From 5d6ab2699cfda84a77134475930652e1fc649d33 Mon Sep 17 00:00:00 2001 From: igarri Date: Wed, 16 Jun 2021 11:48:59 +0100 Subject: [PATCH 001/803] First Performance pass Signed-off-by: igarri --- .../AssetBrowser/AssetBrowserFilterModel.cpp | 3 +- .../AssetBrowser/AssetBrowserModel.cpp | 3 +- .../AssetBrowser/AssetBrowserTableModel.cpp | 56 +++++++++++++++---- .../AssetBrowser/AssetBrowserTableModel.h | 2 + .../Views/AssetBrowserTableView.cpp | 18 +++--- .../Views/AssetBrowserTableView.h | 2 - .../AzAssetBrowser/AzAssetBrowserWindow.cpp | 2 + .../Editor/EditorPreferencesPageFiles.cpp | 21 ++++++- .../Editor/EditorPreferencesPageFiles.h | 7 +++ Code/Sandbox/Editor/Settings.cpp | 2 + Code/Sandbox/Editor/Settings.h | 7 +++ 11 files changed, 96 insertions(+), 27 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp index 9bbdbc8442..3191c9ee8f 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp @@ -185,6 +185,7 @@ namespace AzToolsFramework } } invalidateFilter(); + Q_EMIT filterChanged(); } @@ -204,6 +205,6 @@ namespace AzToolsFramework } } // namespace AssetBrowser -} // namespace AzToolsFramework// namespace AssetBrowser +} // namespace AzToolsFramework #include "AssetBrowser/moc_AssetBrowserFilterModel.cpp" diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserModel.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserModel.cpp index 069ac6de84..5d215f1b97 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserModel.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserModel.cpp @@ -133,7 +133,8 @@ namespace AzToolsFramework { return 0; } - + + //If the column of the parent is one of those we don't want any more rows as children if (parent.isValid()) { if ((parent.column() != aznumeric_cast(AssetBrowserEntry::Column::DisplayName)) && diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp index e03b1116c3..dcd8bb1cf6 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp @@ -14,6 +14,7 @@ namespace AzToolsFramework { AssetBrowserTableModel::AssetBrowserTableModel(QObject* parent /* = nullptr */) : QSortFilterProxyModel(parent) + , m_numberOfItemsDisplayed(200) { setDynamicSortFilter(false); } @@ -88,25 +89,40 @@ namespace AzToolsFramework int AssetBrowserTableModel::BuildTableModelMap( const QAbstractItemModel* model, const QModelIndex& parent /*= QModelIndex()*/, int row /*= 0*/) { + static int cont = 0; int rows = model ? model->rowCount(parent) : 0; + + if (parent == QModelIndex()) + { + cont = 0; + } + for (int i = 0; i < rows; ++i) { - QModelIndex index = model->index(i, 0, parent); - AssetBrowserEntry* entry = GetAssetEntry(m_filterModel->mapToSource(index)); - //We only wanna see the source assets. - if (entry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Source) + if (cont < m_numberOfItemsDisplayed) { - beginInsertRows(parent, row, row); - m_indexMap[row] = index; - endInsertRows(); + QModelIndex index = model->index(i, 0, parent); + AssetBrowserEntry* entry = GetAssetEntry(m_filterModel->mapToSource(index)); + // We only wanna see the source assets. + if (entry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Source) + { + beginInsertRows(parent, row, row); + m_indexMap[row] = index; + endInsertRows(); - Q_EMIT dataChanged(index, index); - ++row; + Q_EMIT dataChanged(index, index); + ++row; + ++cont; + } + + if (model->hasChildren(index) && cont < 10) + { + row = BuildTableModelMap(model, index, row); + } } - - if (model->hasChildren(index)) + else { - row = BuildTableModelMap(model, index, row); + break; } } return row; @@ -134,6 +150,22 @@ namespace AzToolsFramework m_indexMap.clear(); endRemoveRows(); } + + AzToolsFramework::EditorSettingsAPIRequests::SettingOutcome outcome; + AzToolsFramework::EditorSettingsAPIBus::BroadcastResult(outcome, &AzToolsFramework::EditorSettingsAPIBus::Handler::GetValue, + "Settings|MaxDisplayedItemsNumInSearch"); + //AzToolsFramework::EditorSettingsAPIBus::BroadcastResult( + // outcome, &AzToolsFramework::EditorSettingsAPIBus::Handler::GetValue, + // "Settings\ExperimentalFeatures|TotalIlluminationEnabled"); + + AZStd::any* outcomeValue = &outcome.GetValue(); + //bool trr = false; + if (outcomeValue->is() == true) + { + m_numberOfItemsDisplayed = AZStd::any_cast(*outcomeValue); + //trr = AZStd::any_cast(outcomeValue); + } + BuildTableModelMap(sourceModel()); emit layoutChanged(); } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h index 3ce6543f6f..5395512dae 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h @@ -11,6 +11,7 @@ #include #include #endif +#include namespace AzToolsFramework { @@ -49,6 +50,7 @@ namespace AzToolsFramework int BuildTableModelMap(const QAbstractItemModel* model, const QModelIndex& parent = QModelIndex(), int row = 0); private: + int m_numberOfItemsDisplayed; QPointer m_filterModel; QMap m_indexMap; }; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.cpp index 20e3d307ea..924d73433d 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.cpp @@ -5,18 +5,18 @@ * */ -#include +//#include -#include +//#include -#include +//#include #include #include #include -#include -#include -#include +//#include +//#include +//#include #include #include @@ -27,9 +27,9 @@ AZ_PUSH_DISABLE_WARNING( #include #include #include -#include -#include -#include +//#include +//#include +//#include #include AZ_POP_DISABLE_WARNING namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.h b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.h index 7e1c8c9ab4..4df87e6e3f 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.h @@ -8,7 +8,6 @@ #if !defined(Q_MOC_RUN) #include #include -#include #include #include @@ -54,7 +53,6 @@ namespace AzToolsFramework void OnAssetBrowserComponentReady() override; ////////////////////////////////////////////////////////////////////////// - Q_SIGNALS: void selectionChangedSignal(const QItemSelection& selected, const QItemSelection& deselected); void ClearStringFilter(); diff --git a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp index 2a5f853e9b..52721a6162 100644 --- a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp +++ b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp @@ -78,6 +78,8 @@ AzAssetBrowserWindow::AzAssetBrowserWindow(QWidget* parent) m_ui->m_viewSwitcherCheckBox->setVisible(false); m_ui->m_assetBrowserTableViewWidget->setVisible(false); + m_ui->m_searchWidget->SetFilterInputInterval(AZStd::chrono::milliseconds(350)); + if (ed_useNewAssetBrowserTableView) { m_ui->m_viewSwitcherCheckBox->setVisible(true); diff --git a/Code/Sandbox/Editor/EditorPreferencesPageFiles.cpp b/Code/Sandbox/Editor/EditorPreferencesPageFiles.cpp index c09c3441df..cba3888bd1 100644 --- a/Code/Sandbox/Editor/EditorPreferencesPageFiles.cpp +++ b/Code/Sandbox/Editor/EditorPreferencesPageFiles.cpp @@ -42,11 +42,17 @@ void CEditorPreferencesPage_Files::Reflect(AZ::SerializeContext& serialize) ->Field("MaxCount", &AutoBackup::m_maxCount) ->Field("RemindTime", &AutoBackup::m_remindTime); + serialize + .Class() + ->Version(1) + ->Field("Max number of items displayed", &AssetBrowserSearch::m_numOfItemsShown); + serialize.Class() ->Version(1) ->Field("Files", &CEditorPreferencesPage_Files::m_files) ->Field("Editors", &CEditorPreferencesPage_Files::m_editors) - ->Field("AutoBackup", &CEditorPreferencesPage_Files::m_autoBackup); + ->Field("AutoBackup", &CEditorPreferencesPage_Files::m_autoBackup) + ->Field("Asset Browser Search", &CEditorPreferencesPage_Files::m_assetBrowserSearch); AZ::EditContext* editContext = serialize.GetEditContext(); @@ -79,12 +85,19 @@ void CEditorPreferencesPage_Files::Reflect(AZ::SerializeContext& serialize) ->Attribute(AZ::Edit::Attributes::Max, 100) ->DataElement(AZ::Edit::UIHandlers::SpinBox, &AutoBackup::m_remindTime, "Remind Time", "Auto Remind Every (Minutes)"); + editContext->Class("Asset Browser Search View", "Asset Browser Search View") + ->DataElement(AZ::Edit::UIHandlers::SpinBox, &AssetBrowserSearch::m_numOfItemsShown, "Maximum number of displayed items", + "Maximum number of displayed items displayed in the Search View") + ->Attribute(AZ::Edit::Attributes::Min, 200) + ->Attribute(AZ::Edit::Attributes::Max, 1000); + editContext->Class("File Preferences", "Class for handling File Preferences") ->ClassElement(AZ::Edit::ClassElements::EditorData, "") ->Attribute(AZ::Edit::Attributes::Visibility, AZ_CRC("PropertyVisibility_ShowChildrenOnly", 0xef428f20)) ->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_Files::m_files, "Files", "File Preferences") ->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_Files::m_editors, "External Editors", "External Editors") - ->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_Files::m_autoBackup, "Auto Backup", "Auto Backup"); + ->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_Files::m_autoBackup, "Auto Backup", "Auto Backup") + ->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_Files::m_assetBrowserSearch, "Asset Browser Search", "Asset Browser Search"); } } @@ -123,6 +136,8 @@ void CEditorPreferencesPage_Files::OnApply() gSettings.autoBackupTime = m_autoBackup.m_timeInterval; gSettings.autoBackupMaxCount = m_autoBackup.m_maxCount; gSettings.autoRemindTime = m_autoBackup.m_remindTime; + + gSettings.numberOfItemsShownInSearch = m_assetBrowserSearch.m_numOfItemsShown; } void CEditorPreferencesPage_Files::InitializeSettings() @@ -147,4 +162,6 @@ void CEditorPreferencesPage_Files::InitializeSettings() m_autoBackup.m_timeInterval = gSettings.autoBackupTime; m_autoBackup.m_maxCount = gSettings.autoBackupMaxCount; m_autoBackup.m_remindTime = gSettings.autoRemindTime; + + m_assetBrowserSearch.m_numOfItemsShown = gSettings.numberOfItemsShownInSearch; } diff --git a/Code/Sandbox/Editor/EditorPreferencesPageFiles.h b/Code/Sandbox/Editor/EditorPreferencesPageFiles.h index 44bcb3ba8d..2e27cd3c3e 100644 --- a/Code/Sandbox/Editor/EditorPreferencesPageFiles.h +++ b/Code/Sandbox/Editor/EditorPreferencesPageFiles.h @@ -68,10 +68,17 @@ private: int m_remindTime; }; + struct AssetBrowserSearch + { + AZ_TYPE_INFO(AssetBrowserSearch, "{9FBFCD24-9452-49DF-99F4-2711443CEAAE}") + + int m_numOfItemsShown; + }; Files m_files; ExternalEditors m_editors; AutoBackup m_autoBackup; + AssetBrowserSearch m_assetBrowserSearch; QIcon m_icon; }; diff --git a/Code/Sandbox/Editor/Settings.cpp b/Code/Sandbox/Editor/Settings.cpp index bf699c842c..c1929119fb 100644 --- a/Code/Sandbox/Editor/Settings.cpp +++ b/Code/Sandbox/Editor/Settings.cpp @@ -498,6 +498,7 @@ void SEditorSettings::Save() SaveValue("Settings", "AutoBackupTime", autoBackupTime); SaveValue("Settings", "AutoBackupMaxCount", autoBackupMaxCount); SaveValue("Settings", "AutoRemindTime", autoRemindTime); + SaveValue("Settings", "MaxDisplayedItemsNumInSearch", numberOfItemsShownInSearch); SaveValue("Settings", "CameraMoveSpeed", cameraMoveSpeed); SaveValue("Settings", "CameraRotateSpeed", cameraRotateSpeed); SaveValue("Settings", "StylusMode", stylusMode); @@ -710,6 +711,7 @@ void SEditorSettings::Load() LoadValue("Settings", "AutoBackupTime", autoBackupTime); LoadValue("Settings", "AutoBackupMaxCount", autoBackupMaxCount); LoadValue("Settings", "AutoRemindTime", autoRemindTime); + LoadValue("Settings", "MaxDisplayedItemsNumInSearch", numberOfItemsShownInSearch); LoadValue("Settings", "CameraMoveSpeed", cameraMoveSpeed); LoadValue("Settings", "CameraRotateSpeed", cameraRotateSpeed); LoadValue("Settings", "StylusMode", stylusMode); diff --git a/Code/Sandbox/Editor/Settings.h b/Code/Sandbox/Editor/Settings.h index 7618a11485..9591695248 100644 --- a/Code/Sandbox/Editor/Settings.h +++ b/Code/Sandbox/Editor/Settings.h @@ -377,6 +377,13 @@ AZ_POP_DISABLE_DLL_EXPORT_BASECLASS_WARNING int autoRemindTime; ////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////// + // Asset Browser Search View. + ////////////////////////////////////////////////////////////////////////// + //! Current maximum number of items that can be displayed in the AssetBrowser Search View. + int numberOfItemsShownInSearch; + ////////////////////////////////////////////////////////////////////////// + //! If true preview windows is displayed when browsing geometries. bool bPreviewGeometryWindow; From c061802ab0ed017c566b042f675557c959b0151d Mon Sep 17 00:00:00 2001 From: igarri Date: Mon, 21 Jun 2021 13:18:51 +0100 Subject: [PATCH 002/803] Retrieving data from preferences Signed-off-by: igarri --- .../AssetBrowser/AssetBrowserTableModel.cpp | 23 ++++++++++--------- .../Editor/EditorSettingsAPIBus.h | 1 + .../AzAssetBrowser/AzAssetBrowserWindow.cpp | 2 +- .../Editor/EditorPreferencesPageFiles.cpp | 2 +- Code/Sandbox/Editor/Settings.cpp | 5 ++++ Code/Sandbox/Editor/Settings.h | 1 + 6 files changed, 21 insertions(+), 13 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp index dcd8bb1cf6..d76ee9b515 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp @@ -8,6 +8,8 @@ #include #include +#pragma optimize("", off) + namespace AzToolsFramework { namespace AssetBrowser @@ -151,24 +153,23 @@ namespace AzToolsFramework endRemoveRows(); } - AzToolsFramework::EditorSettingsAPIRequests::SettingOutcome outcome; - AzToolsFramework::EditorSettingsAPIBus::BroadcastResult(outcome, &AzToolsFramework::EditorSettingsAPIBus::Handler::GetValue, - "Settings|MaxDisplayedItemsNumInSearch"); - //AzToolsFramework::EditorSettingsAPIBus::BroadcastResult( - // outcome, &AzToolsFramework::EditorSettingsAPIBus::Handler::GetValue, - // "Settings\ExperimentalFeatures|TotalIlluminationEnabled"); + AzToolsFramework::EditorSettingsAPIRequests::SettingOutcome outcome; + AzToolsFramework::EditorSettingsAPIBus::BroadcastResult(outcome, &AzToolsFramework::EditorSettingsAPIBus::Handler::GetValue, + "Settings|MaxDisplayedItemsNumInSearch"); - AZStd::any* outcomeValue = &outcome.GetValue(); - //bool trr = false; - if (outcomeValue->is() == true) + AZStd::any outcomeValue = outcome.GetValue(); + if (outcomeValue.is() == true) { - m_numberOfItemsDisplayed = AZStd::any_cast(*outcomeValue); - //trr = AZStd::any_cast(outcomeValue); + m_numberOfItemsDisplayed = AZStd::any_cast(outcome.GetValue()); } + AzToolsFramework::EditorSettingsAPIBus::BroadcastResult( + m_numberOfItemsDisplayed, &AzToolsFramework::EditorSettingsAPIBus::Handler::GetMaxNumberOfItemsShownInSearchView); + BuildTableModelMap(sourceModel()); emit layoutChanged(); } } // namespace AssetBrowser } // namespace AzToolsFramework #include "AssetBrowser/moc_AssetBrowserTableModel.cpp" +#pragma optimize("", on) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/EditorSettingsAPIBus.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/EditorSettingsAPIBus.h index 4f037b870a..ce45577335 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/EditorSettingsAPIBus.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/EditorSettingsAPIBus.h @@ -37,6 +37,7 @@ namespace AzToolsFramework virtual SettingOutcome GetValue(const AZStd::string_view path) = 0; virtual SettingOutcome SetValue(const AZStd::string_view path, const AZStd::any& value) = 0; virtual ConsoleColorTheme GetConsoleColorTheme() const = 0; + virtual int GetMaxNumberOfItemsShownInSearchView() const = 0; }; using EditorSettingsAPIBus = AZ::EBus; diff --git a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp index 52721a6162..f16f0e362b 100644 --- a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp +++ b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp @@ -78,7 +78,7 @@ AzAssetBrowserWindow::AzAssetBrowserWindow(QWidget* parent) m_ui->m_viewSwitcherCheckBox->setVisible(false); m_ui->m_assetBrowserTableViewWidget->setVisible(false); - m_ui->m_searchWidget->SetFilterInputInterval(AZStd::chrono::milliseconds(350)); + m_ui->m_searchWidget->SetFilterInputInterval(AZStd::chrono::milliseconds(250)); if (ed_useNewAssetBrowserTableView) { diff --git a/Code/Sandbox/Editor/EditorPreferencesPageFiles.cpp b/Code/Sandbox/Editor/EditorPreferencesPageFiles.cpp index cba3888bd1..7833ccdf88 100644 --- a/Code/Sandbox/Editor/EditorPreferencesPageFiles.cpp +++ b/Code/Sandbox/Editor/EditorPreferencesPageFiles.cpp @@ -88,7 +88,7 @@ void CEditorPreferencesPage_Files::Reflect(AZ::SerializeContext& serialize) editContext->Class("Asset Browser Search View", "Asset Browser Search View") ->DataElement(AZ::Edit::UIHandlers::SpinBox, &AssetBrowserSearch::m_numOfItemsShown, "Maximum number of displayed items", "Maximum number of displayed items displayed in the Search View") - ->Attribute(AZ::Edit::Attributes::Min, 200) + ->Attribute(AZ::Edit::Attributes::Min, 10) ->Attribute(AZ::Edit::Attributes::Max, 1000); editContext->Class("File Preferences", "Class for handling File Preferences") diff --git a/Code/Sandbox/Editor/Settings.cpp b/Code/Sandbox/Editor/Settings.cpp index c1929119fb..398ad5f5cb 100644 --- a/Code/Sandbox/Editor/Settings.cpp +++ b/Code/Sandbox/Editor/Settings.cpp @@ -1205,3 +1205,8 @@ AzToolsFramework::ConsoleColorTheme SEditorSettings::GetConsoleColorTheme() cons { return consoleBackgroundColorTheme; } + +int SEditorSettings::GetMaxNumberOfItemsShownInSearchView() const +{ + return SEditorSettings::numberOfItemsShownInSearch; +} diff --git a/Code/Sandbox/Editor/Settings.h b/Code/Sandbox/Editor/Settings.h index 9591695248..ee6aa24ca5 100644 --- a/Code/Sandbox/Editor/Settings.h +++ b/Code/Sandbox/Editor/Settings.h @@ -302,6 +302,7 @@ AZ_POP_DISABLE_DLL_EXPORT_BASECLASS_WARNING SettingOutcome GetValue(const AZStd::string_view path) override; SettingOutcome SetValue(const AZStd::string_view path, const AZStd::any& value) override; AzToolsFramework::ConsoleColorTheme GetConsoleColorTheme() const override; + int GetMaxNumberOfItemsShownInSearchView() const override; void ConvertPath(const AZStd::string_view sourcePath, AZStd::string& category, AZStd::string& attribute); From 514f9ef6c2b373d5c5c821d641cc87f69ba8715f Mon Sep 17 00:00:00 2001 From: igarri Date: Fri, 25 Jun 2021 10:37:39 +0100 Subject: [PATCH 003/803] Adjusted parameters Signed-off-by: igarri --- .../AssetBrowser/AssetBrowserTableModel.cpp | 10 ---------- .../Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp | 2 +- Code/Sandbox/Editor/EditorPreferencesPageFiles.cpp | 2 +- 3 files changed, 2 insertions(+), 12 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp index d76ee9b515..0a2a1954f4 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp @@ -153,16 +153,6 @@ namespace AzToolsFramework endRemoveRows(); } - AzToolsFramework::EditorSettingsAPIRequests::SettingOutcome outcome; - AzToolsFramework::EditorSettingsAPIBus::BroadcastResult(outcome, &AzToolsFramework::EditorSettingsAPIBus::Handler::GetValue, - "Settings|MaxDisplayedItemsNumInSearch"); - - AZStd::any outcomeValue = outcome.GetValue(); - if (outcomeValue.is() == true) - { - m_numberOfItemsDisplayed = AZStd::any_cast(outcome.GetValue()); - } - AzToolsFramework::EditorSettingsAPIBus::BroadcastResult( m_numberOfItemsDisplayed, &AzToolsFramework::EditorSettingsAPIBus::Handler::GetMaxNumberOfItemsShownInSearchView); diff --git a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp index f16f0e362b..c131f62fc6 100644 --- a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp +++ b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp @@ -82,7 +82,7 @@ AzAssetBrowserWindow::AzAssetBrowserWindow(QWidget* parent) if (ed_useNewAssetBrowserTableView) { - m_ui->m_viewSwitcherCheckBox->setVisible(true); + m_ui->m_viewSwitcherCheckBox->setVisible(false); m_tableModel->setFilterRole(Qt::DisplayRole); m_tableModel->setSourceModel(m_filterModel.data()); m_ui->m_assetBrowserTableViewWidget->setModel(m_tableModel.data()); diff --git a/Code/Sandbox/Editor/EditorPreferencesPageFiles.cpp b/Code/Sandbox/Editor/EditorPreferencesPageFiles.cpp index 7833ccdf88..d4e7378d2b 100644 --- a/Code/Sandbox/Editor/EditorPreferencesPageFiles.cpp +++ b/Code/Sandbox/Editor/EditorPreferencesPageFiles.cpp @@ -88,7 +88,7 @@ void CEditorPreferencesPage_Files::Reflect(AZ::SerializeContext& serialize) editContext->Class("Asset Browser Search View", "Asset Browser Search View") ->DataElement(AZ::Edit::UIHandlers::SpinBox, &AssetBrowserSearch::m_numOfItemsShown, "Maximum number of displayed items", "Maximum number of displayed items displayed in the Search View") - ->Attribute(AZ::Edit::Attributes::Min, 10) + ->Attribute(AZ::Edit::Attributes::Min, 100) ->Attribute(AZ::Edit::Attributes::Max, 1000); editContext->Class("File Preferences", "Class for handling File Preferences") From a07445c2da041624c0d54adc09b62497bf63c4ec Mon Sep 17 00:00:00 2001 From: igarri Date: Wed, 30 Jun 2021 13:45:34 +0100 Subject: [PATCH 004/803] Cleanup and removed optimize Signed-off-by: igarri --- .../AssetBrowser/AssetBrowserTableModel.cpp | 3 --- .../AssetBrowser/Views/AssetBrowserTableView.cpp | 12 +----------- 2 files changed, 1 insertion(+), 14 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp index 0a2a1954f4..1c4f141f38 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp @@ -8,8 +8,6 @@ #include #include -#pragma optimize("", off) - namespace AzToolsFramework { namespace AssetBrowser @@ -162,4 +160,3 @@ namespace AzToolsFramework } // namespace AssetBrowser } // namespace AzToolsFramework #include "AssetBrowser/moc_AssetBrowserTableModel.cpp" -#pragma optimize("", on) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.cpp index 924d73433d..2840523683 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.cpp @@ -5,18 +5,10 @@ * */ -//#include - -//#include - -//#include #include #include #include -//#include -//#include -//#include #include #include @@ -27,9 +19,7 @@ AZ_PUSH_DISABLE_WARNING( #include #include #include -//#include -//#include -//#include + #include AZ_POP_DISABLE_WARNING namespace AzToolsFramework From b0ddd938245e406081f341cc635a40481a5a429d Mon Sep 17 00:00:00 2001 From: igarri Date: Wed, 30 Jun 2021 15:16:23 +0100 Subject: [PATCH 005/803] Code cleanup and review changes Signed-off-by: igarri --- .../AssetBrowser/AssetBrowserTableModel.cpp | 13 +++++-------- .../Sandbox/Editor/EditorPreferencesPageFiles.cpp | 15 +++++++-------- Code/Sandbox/Editor/EditorPreferencesPageFiles.h | 2 +- Code/Sandbox/Editor/Settings.cpp | 6 +++--- Code/Sandbox/Editor/Settings.h | 2 +- 5 files changed, 17 insertions(+), 21 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp index 1c4f141f38..2cf5b13c91 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp @@ -89,17 +89,17 @@ namespace AzToolsFramework int AssetBrowserTableModel::BuildTableModelMap( const QAbstractItemModel* model, const QModelIndex& parent /*= QModelIndex()*/, int row /*= 0*/) { - static int cont = 0; + static int displayedItemsCounter = 0; int rows = model ? model->rowCount(parent) : 0; if (parent == QModelIndex()) { - cont = 0; + displayedItemsCounter = 0; } for (int i = 0; i < rows; ++i) { - if (cont < m_numberOfItemsDisplayed) + if (displayedItemsCounter < m_numberOfItemsDisplayed) { QModelIndex index = model->index(i, 0, parent); AssetBrowserEntry* entry = GetAssetEntry(m_filterModel->mapToSource(index)); @@ -112,18 +112,15 @@ namespace AzToolsFramework Q_EMIT dataChanged(index, index); ++row; - ++cont; + ++displayedItemsCounter; } - if (model->hasChildren(index) && cont < 10) + if (model->hasChildren(index)) { row = BuildTableModelMap(model, index, row); } } - else - { break; - } } return row; } diff --git a/Code/Sandbox/Editor/EditorPreferencesPageFiles.cpp b/Code/Sandbox/Editor/EditorPreferencesPageFiles.cpp index d4e7378d2b..f6333b9a76 100644 --- a/Code/Sandbox/Editor/EditorPreferencesPageFiles.cpp +++ b/Code/Sandbox/Editor/EditorPreferencesPageFiles.cpp @@ -42,10 +42,9 @@ void CEditorPreferencesPage_Files::Reflect(AZ::SerializeContext& serialize) ->Field("MaxCount", &AutoBackup::m_maxCount) ->Field("RemindTime", &AutoBackup::m_remindTime); - serialize - .Class() + serialize.Class() ->Version(1) - ->Field("Max number of items displayed", &AssetBrowserSearch::m_numOfItemsShown); + ->Field("Max number of items displayed", &AssetBrowserSearch::m_maxNumberOfItemsShownInSearch); serialize.Class() ->Version(1) @@ -86,10 +85,10 @@ void CEditorPreferencesPage_Files::Reflect(AZ::SerializeContext& serialize) ->DataElement(AZ::Edit::UIHandlers::SpinBox, &AutoBackup::m_remindTime, "Remind Time", "Auto Remind Every (Minutes)"); editContext->Class("Asset Browser Search View", "Asset Browser Search View") - ->DataElement(AZ::Edit::UIHandlers::SpinBox, &AssetBrowserSearch::m_numOfItemsShown, "Maximum number of displayed items", + ->DataElement(AZ::Edit::UIHandlers::SpinBox, &AssetBrowserSearch::m_maxNumberOfItemsShownInSearch, "Maximum number of displayed items", "Maximum number of displayed items displayed in the Search View") - ->Attribute(AZ::Edit::Attributes::Min, 100) - ->Attribute(AZ::Edit::Attributes::Max, 1000); + ->Attribute(AZ::Edit::Attributes::Min, 50) + ->Attribute(AZ::Edit::Attributes::Max, 5000); editContext->Class("File Preferences", "Class for handling File Preferences") ->ClassElement(AZ::Edit::ClassElements::EditorData, "") @@ -137,7 +136,7 @@ void CEditorPreferencesPage_Files::OnApply() gSettings.autoBackupMaxCount = m_autoBackup.m_maxCount; gSettings.autoRemindTime = m_autoBackup.m_remindTime; - gSettings.numberOfItemsShownInSearch = m_assetBrowserSearch.m_numOfItemsShown; + gSettings.maxNumberOfItemsShownInSearch = m_assetBrowserSearch.m_maxNumberOfItemsShownInSearch; } void CEditorPreferencesPage_Files::InitializeSettings() @@ -163,5 +162,5 @@ void CEditorPreferencesPage_Files::InitializeSettings() m_autoBackup.m_maxCount = gSettings.autoBackupMaxCount; m_autoBackup.m_remindTime = gSettings.autoRemindTime; - m_assetBrowserSearch.m_numOfItemsShown = gSettings.numberOfItemsShownInSearch; + m_assetBrowserSearch.m_maxNumberOfItemsShownInSearch = gSettings.maxNumberOfItemsShownInSearch; } diff --git a/Code/Sandbox/Editor/EditorPreferencesPageFiles.h b/Code/Sandbox/Editor/EditorPreferencesPageFiles.h index 2e27cd3c3e..40e9577f7f 100644 --- a/Code/Sandbox/Editor/EditorPreferencesPageFiles.h +++ b/Code/Sandbox/Editor/EditorPreferencesPageFiles.h @@ -72,7 +72,7 @@ private: { AZ_TYPE_INFO(AssetBrowserSearch, "{9FBFCD24-9452-49DF-99F4-2711443CEAAE}") - int m_numOfItemsShown; + int m_maxNumberOfItemsShownInSearch; }; Files m_files; diff --git a/Code/Sandbox/Editor/Settings.cpp b/Code/Sandbox/Editor/Settings.cpp index 398ad5f5cb..d49a1d40d1 100644 --- a/Code/Sandbox/Editor/Settings.cpp +++ b/Code/Sandbox/Editor/Settings.cpp @@ -498,7 +498,7 @@ void SEditorSettings::Save() SaveValue("Settings", "AutoBackupTime", autoBackupTime); SaveValue("Settings", "AutoBackupMaxCount", autoBackupMaxCount); SaveValue("Settings", "AutoRemindTime", autoRemindTime); - SaveValue("Settings", "MaxDisplayedItemsNumInSearch", numberOfItemsShownInSearch); + SaveValue("Settings", "MaxDisplayedItemsNumInSearch", maxNumberOfItemsShownInSearch); SaveValue("Settings", "CameraMoveSpeed", cameraMoveSpeed); SaveValue("Settings", "CameraRotateSpeed", cameraRotateSpeed); SaveValue("Settings", "StylusMode", stylusMode); @@ -711,7 +711,7 @@ void SEditorSettings::Load() LoadValue("Settings", "AutoBackupTime", autoBackupTime); LoadValue("Settings", "AutoBackupMaxCount", autoBackupMaxCount); LoadValue("Settings", "AutoRemindTime", autoRemindTime); - LoadValue("Settings", "MaxDisplayedItemsNumInSearch", numberOfItemsShownInSearch); + LoadValue("Settings", "MaxDisplayedItemsNumInSearch", maxNumberOfItemsShownInSearch); LoadValue("Settings", "CameraMoveSpeed", cameraMoveSpeed); LoadValue("Settings", "CameraRotateSpeed", cameraRotateSpeed); LoadValue("Settings", "StylusMode", stylusMode); @@ -1208,5 +1208,5 @@ AzToolsFramework::ConsoleColorTheme SEditorSettings::GetConsoleColorTheme() cons int SEditorSettings::GetMaxNumberOfItemsShownInSearchView() const { - return SEditorSettings::numberOfItemsShownInSearch; + return SEditorSettings::maxNumberOfItemsShownInSearch; } diff --git a/Code/Sandbox/Editor/Settings.h b/Code/Sandbox/Editor/Settings.h index ee6aa24ca5..802809ac11 100644 --- a/Code/Sandbox/Editor/Settings.h +++ b/Code/Sandbox/Editor/Settings.h @@ -382,7 +382,7 @@ AZ_POP_DISABLE_DLL_EXPORT_BASECLASS_WARNING // Asset Browser Search View. ////////////////////////////////////////////////////////////////////////// //! Current maximum number of items that can be displayed in the AssetBrowser Search View. - int numberOfItemsShownInSearch; + int maxNumberOfItemsShownInSearch; ////////////////////////////////////////////////////////////////////////// From 4251e2600a5defd438edde84ab0e9b087bda8c11 Mon Sep 17 00:00:00 2001 From: igarri Date: Wed, 30 Jun 2021 15:18:29 +0100 Subject: [PATCH 006/803] Fixing Asset Browser Search name Signed-off-by: igarri --- Code/Sandbox/Editor/EditorPreferencesPageFiles.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Sandbox/Editor/EditorPreferencesPageFiles.cpp b/Code/Sandbox/Editor/EditorPreferencesPageFiles.cpp index f6333b9a76..81f5e52828 100644 --- a/Code/Sandbox/Editor/EditorPreferencesPageFiles.cpp +++ b/Code/Sandbox/Editor/EditorPreferencesPageFiles.cpp @@ -51,7 +51,7 @@ void CEditorPreferencesPage_Files::Reflect(AZ::SerializeContext& serialize) ->Field("Files", &CEditorPreferencesPage_Files::m_files) ->Field("Editors", &CEditorPreferencesPage_Files::m_editors) ->Field("AutoBackup", &CEditorPreferencesPage_Files::m_autoBackup) - ->Field("Asset Browser Search", &CEditorPreferencesPage_Files::m_assetBrowserSearch); + ->Field("AssetBrowserSearch", &CEditorPreferencesPage_Files::m_assetBrowserSearch); AZ::EditContext* editContext = serialize.GetEditContext(); From e9f44863a47b8eaaf26a8e745eeecfe10971fe72 Mon Sep 17 00:00:00 2001 From: igarri Date: Wed, 30 Jun 2021 15:21:34 +0100 Subject: [PATCH 007/803] Fixed BuildMap method Signed-off-by: igarri --- .../AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp index 2cf5b13c91..9874c5571f 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp @@ -120,7 +120,10 @@ namespace AzToolsFramework row = BuildTableModelMap(model, index, row); } } + else + { break; + } } return row; } From 8b016f86a63df1b92f86848b0fe5a5284e0ea5c7 Mon Sep 17 00:00:00 2001 From: igarri Date: Fri, 2 Jul 2021 13:38:35 +0100 Subject: [PATCH 008/803] Adressing Code review comments Signed-off-by: igarri --- .../AssetBrowser/AssetBrowserTableModel.cpp | 14 ++++++-------- .../AssetBrowser/AssetBrowserTableModel.h | 3 ++- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp index 9874c5571f..0da7007e01 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp @@ -14,7 +14,6 @@ namespace AzToolsFramework { AssetBrowserTableModel::AssetBrowserTableModel(QObject* parent /* = nullptr */) : QSortFilterProxyModel(parent) - , m_numberOfItemsDisplayed(200) { setDynamicSortFilter(false); } @@ -89,21 +88,20 @@ namespace AzToolsFramework int AssetBrowserTableModel::BuildTableModelMap( const QAbstractItemModel* model, const QModelIndex& parent /*= QModelIndex()*/, int row /*= 0*/) { - static int displayedItemsCounter = 0; int rows = model ? model->rowCount(parent) : 0; if (parent == QModelIndex()) { - displayedItemsCounter = 0; + m_displayedItemsCounter = 0; } - for (int i = 0; i < rows; ++i) + for (int currentRow = 0; currentRow < rows; ++currentRow) { - if (displayedItemsCounter < m_numberOfItemsDisplayed) + if (m_displayedItemsCounter < m_numberOfItemsDisplayed) { - QModelIndex index = model->index(i, 0, parent); + QModelIndex index = model->index(currentRow, 0, parent); AssetBrowserEntry* entry = GetAssetEntry(m_filterModel->mapToSource(index)); - // We only wanna see the source assets. + // We only want to see the source assets. if (entry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Source) { beginInsertRows(parent, row, row); @@ -112,7 +110,7 @@ namespace AzToolsFramework Q_EMIT dataChanged(index, index); ++row; - ++displayedItemsCounter; + ++m_displayedItemsCounter; } if (model->hasChildren(index)) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h index 5395512dae..b2131c2ae3 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h @@ -50,7 +50,8 @@ namespace AzToolsFramework int BuildTableModelMap(const QAbstractItemModel* model, const QModelIndex& parent = QModelIndex(), int row = 0); private: - int m_numberOfItemsDisplayed; + int m_numberOfItemsDisplayed = 0; + int m_displayedItemsCounter = 0; QPointer m_filterModel; QMap m_indexMap; }; From 26d9a3b5b3dd9025499dccbf4620f8974c58e33e Mon Sep 17 00:00:00 2001 From: igarri Date: Wed, 7 Jul 2021 13:54:18 +0100 Subject: [PATCH 009/803] Fixed tabs Signed-off-by: igarri --- Code/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp b/Code/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp index 6bd0c00150..c0e08f86b1 100644 --- a/Code/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp +++ b/Code/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp @@ -81,7 +81,7 @@ AzAssetBrowserWindow::AzAssetBrowserWindow(QWidget* parent) m_ui->m_assetBrowserTableViewWidget->setVisible(false); m_ui->m_toggleDisplayViewBtn->setVisible(false); - m_ui->m_searchWidget->SetFilterInputInterval(AZStd::chrono::milliseconds(250)); + m_ui->m_searchWidget->SetFilterInputInterval(AZStd::chrono::milliseconds(250)); if (ed_useNewAssetBrowserTableView) { m_ui->m_toggleDisplayViewBtn->setVisible(true); From fd6a5134ecb844e2805a03e2a4f9fd71107e0a52 Mon Sep 17 00:00:00 2001 From: evanchia Date: Thu, 8 Jul 2021 14:02:26 -0700 Subject: [PATCH 010/803] Adding C++ retry command Signed-off-by: evanchia --- Code/Tools/AzTestRunner/src/main.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Code/Tools/AzTestRunner/src/main.cpp b/Code/Tools/AzTestRunner/src/main.cpp index c6d887244f..e53e2ae799 100644 --- a/Code/Tools/AzTestRunner/src/main.cpp +++ b/Code/Tools/AzTestRunner/src/main.cpp @@ -126,6 +126,14 @@ namespace AzTestRunner std::cout << "arg[" << i << "] " << argv[i] << std::endl; } + // Construct a full retry command + std::cout << "Full command: " << argv[0] << " " << lib << " " << symbol; + for (int i = 1; i < argc; i++) + { + std::cout << " " << argv[i]; + } + std::cout << std::endl; + std::cout << "LIB: " << lib << std::endl; } From b1a1f78ca685dc4089d1c32c5734eae36680d888 Mon Sep 17 00:00:00 2001 From: evanchia Date: Mon, 12 Jul 2021 16:54:57 -0700 Subject: [PATCH 011/803] Moved retry command to after the test fails Signed-off-by: evanchia --- Code/Tools/AzTestRunner/src/main.cpp | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/Code/Tools/AzTestRunner/src/main.cpp b/Code/Tools/AzTestRunner/src/main.cpp index e53e2ae799..d846cd5cbd 100644 --- a/Code/Tools/AzTestRunner/src/main.cpp +++ b/Code/Tools/AzTestRunner/src/main.cpp @@ -126,17 +126,16 @@ namespace AzTestRunner std::cout << "arg[" << i << "] " << argv[i] << std::endl; } - // Construct a full retry command - std::cout << "Full command: " << argv[0] << " " << lib << " " << symbol; - for (int i = 1; i < argc; i++) - { - std::cout << " " << argv[i]; - } - std::cout << std::endl; - std::cout << "LIB: " << lib << std::endl; } + // Construct a retry command if test fails + std::string retry_command = "Retry command: " + std::string(argv[0]) + " " + lib + " " + symbol; + for (int i = 1; i < argc; i++) + { + retry_command.append(" " + std::string(argv[i])); + } + // Wait for debugger if (waitForDebugger) { @@ -230,6 +229,10 @@ namespace AzTestRunner if (testMainFunction->IsValid()) { result = (*testMainFunction)(argc, argv); + if (result != 0) + { + std::cout << retry_command << std::endl; + } std::cout << "OKAY " << symbol << "() returned " << result << std::endl; testMainFunction.reset(); } From 9bd5b9fbd62273693963bbd28c52c05476d07490 Mon Sep 17 00:00:00 2001 From: evanchia Date: Wed, 14 Jul 2021 16:09:00 -0700 Subject: [PATCH 012/803] Simplified and moved aztestrunner retry command Signed-off-by: evanchia --- Code/Tools/AzTestRunner/src/main.cpp | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/Code/Tools/AzTestRunner/src/main.cpp b/Code/Tools/AzTestRunner/src/main.cpp index d846cd5cbd..96832c3fed 100644 --- a/Code/Tools/AzTestRunner/src/main.cpp +++ b/Code/Tools/AzTestRunner/src/main.cpp @@ -129,13 +129,6 @@ namespace AzTestRunner std::cout << "LIB: " << lib << std::endl; } - // Construct a retry command if test fails - std::string retry_command = "Retry command: " + std::string(argv[0]) + " " + lib + " " + symbol; - for (int i = 1; i < argc; i++) - { - retry_command.append(" " + std::string(argv[i])); - } - // Wait for debugger if (waitForDebugger) { @@ -229,14 +222,16 @@ namespace AzTestRunner if (testMainFunction->IsValid()) { result = (*testMainFunction)(argc, argv); - if (result != 0) - { - std::cout << retry_command << std::endl; - } std::cout << "OKAY " << symbol << "() returned " << result << std::endl; testMainFunction.reset(); } + // Construct a retry command if the test fails + if (result != 0) + { + std::cout << "Retry command: " << std::string(argv[0]) << " " << lib << " " << symbol << std::endl; + } + // unload and reset the module here, because it needs to release resources that were used / activated in // system allocator / etc. module.reset(); From ae60bd0167483bad342bcaae9fa2638ee5df91d9 Mon Sep 17 00:00:00 2001 From: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> Date: Fri, 16 Jul 2021 14:33:39 -0700 Subject: [PATCH 013/803] [installer/2106-font] revert back to default install bootstrapper font Signed-off-by: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> --- .../Windows/Packaging/BootstrapperTheme.xml.in | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cmake/Platform/Windows/Packaging/BootstrapperTheme.xml.in b/cmake/Platform/Windows/Packaging/BootstrapperTheme.xml.in index 8d8416539e..c670ef3d9a 100644 --- a/cmake/Platform/Windows/Packaging/BootstrapperTheme.xml.in +++ b/cmake/Platform/Windows/Packaging/BootstrapperTheme.xml.in @@ -4,15 +4,15 @@ #(loc.WindowTitle) - Open Sans + Segoe UI - Open Sans + Segoe UI - Open Sans + Segoe UI - Open Sans + Segoe UI - Open Sans + Segoe UI From 679ecf480197d234cc86fd123c5535a33c25d474 Mon Sep 17 00:00:00 2001 From: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> Date: Fri, 16 Jul 2021 17:40:27 -0500 Subject: [PATCH 014/803] External Gem and Projects now appear in Editor AssetBrowser (#2227) * External Gem and Projects now appear in Editor AssetBrowser Optimized logic populating the FolderAssetBrowserEntries in the Editor AssetBrowser. Added an "[External]" tag to scan folders which reside outside of the Engine Root Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Fixed conversion of fixed_string to string when normalizing an added AssetBrowser file path. Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * RootAssetBrowserEntry.cpp Linux conditional expression fix Because an AZ::IO::PathView is convertible to an AZ::IO::FixedMaxPath and vice-versa, the conversion of the second part of the ternary expression absolutePathView needs to explicitly convert to an AZ::IO::FixedMaxPath Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> --- .../Entries/AssetBrowserEntry.cpp | 4 +- .../AssetBrowser/Entries/AssetBrowserEntry.h | 5 +- .../Entries/FolderAssetBrowserEntry.cpp | 4 +- .../Entries/RootAssetBrowserEntry.cpp | 201 ++++++++---------- .../Entries/RootAssetBrowserEntry.h | 12 +- .../Entries/SourceAssetBrowserEntry.cpp | 4 +- 6 files changed, 105 insertions(+), 125 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/AssetBrowserEntry.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/AssetBrowserEntry.cpp index 17a20a9d19..7eae7621d2 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/AssetBrowserEntry.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/AssetBrowserEntry.cpp @@ -206,12 +206,12 @@ namespace AzToolsFramework const AZStd::string& AssetBrowserEntry::GetRelativePath() const { - return m_relativePath; + return m_relativePath.Native(); } const AZStd::string& AssetBrowserEntry::GetFullPath() const { - return m_fullPath; + return m_fullPath.Native(); } const AssetBrowserEntry* AssetBrowserEntry::GetChild(int index) const diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/AssetBrowserEntry.h b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/AssetBrowserEntry.h index e4a7b6b4cb..24f037a623 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/AssetBrowserEntry.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/AssetBrowserEntry.h @@ -9,6 +9,7 @@ #if !defined(Q_MOC_RUN) #include #include +#include #include #include @@ -130,8 +131,8 @@ namespace AzToolsFramework protected: AZStd::string m_name; QString m_displayName; - AZStd::string m_relativePath; - AZStd::string m_fullPath; + AZ::IO::Path m_relativePath; + AZ::IO::Path m_fullPath; AZStd::vector m_children; AssetBrowserEntry* m_parentAssetEntry = nullptr; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/FolderAssetBrowserEntry.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/FolderAssetBrowserEntry.cpp index 3c5afab0d0..febd406f23 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/FolderAssetBrowserEntry.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/FolderAssetBrowserEntry.cpp @@ -37,8 +37,8 @@ namespace AzToolsFramework void FolderAssetBrowserEntry::UpdateChildPaths(AssetBrowserEntry* child) const { - child->m_relativePath = m_relativePath + AZ_CORRECT_DATABASE_SEPARATOR + child->m_name; - child->m_fullPath = m_fullPath + AZ_CORRECT_DATABASE_SEPARATOR + child->m_name; + child->m_relativePath = m_relativePath / child->m_name; + child->m_fullPath = m_fullPath / child->m_name; AssetBrowserEntry::UpdateChildPaths(child); } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/RootAssetBrowserEntry.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/RootAssetBrowserEntry.cpp index 090ad0d6ca..0e132d2581 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/RootAssetBrowserEntry.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/RootAssetBrowserEntry.cpp @@ -10,6 +10,7 @@ #include #include +#include #include #include @@ -24,8 +25,6 @@ namespace AzToolsFramework { namespace AssetBrowser { - const char* GEMS_FOLDER_NAME = "Gems"; - RootAssetBrowserEntry::RootAssetBrowserEntry() : AssetBrowserEntry() { @@ -53,13 +52,7 @@ namespace AzToolsFramework EntryCache::GetInstance()->Clear(); m_enginePath = enginePath; - - // there is no "Gems" scan folder registered in db, create one manually - auto gemFolder = aznew FolderAssetBrowserEntry(); - gemFolder->m_name = m_enginePath + AZ_CORRECT_DATABASE_SEPARATOR + GEMS_FOLDER_NAME; - gemFolder->m_displayName = GEMS_FOLDER_NAME; - gemFolder->m_isGemsFolder = true; - AddChild(gemFolder); + m_fullPath = enginePath; } bool RootAssetBrowserEntry::IsInitialUpdate() const @@ -80,8 +73,17 @@ namespace AzToolsFramework if (AZ::IO::FileIOBase::GetInstance()->IsDirectory(scanFolderDatabaseEntry.m_scanFolder.c_str())) { - const auto scanFolder = CreateFolders(scanFolderDatabaseEntry.m_scanFolder.c_str(), this); - scanFolder->m_displayName = QString::fromUtf8(scanFolderDatabaseEntry.m_displayName.c_str()); + const auto scanFolder = CreateFolders(scanFolderDatabaseEntry.m_scanFolder, this); + // Append an "[External]" to the display if the Scan Folder is NOT relative to the Engine Root path + if (!AZ::IO::PathView(scanFolderDatabaseEntry.m_scanFolder).IsRelativeTo(m_enginePath)) + { + scanFolder->m_displayName += " [External]"; + } + else + { + scanFolder->m_displayName = QString::fromUtf8(scanFolderDatabaseEntry.m_displayName.c_str()); + } + EntryCache::GetInstance()->m_scanFolderIdMap[scanFolderDatabaseEntry.m_scanFolderID] = scanFolder; } } @@ -121,38 +123,34 @@ namespace AzToolsFramework return; } - const char* filePath = fileDatabaseEntry.m_fileName.c_str(); + AZ::IO::FixedMaxPath absoluteFilePath = AZ::IO::FixedMaxPath(AZStd::string_view{ scanFolder->GetFullPath() }) + / fileDatabaseEntry.m_fileName.c_str(); AssetBrowserEntry* file; // file can be either folder or actual file if (fileDatabaseEntry.m_isFolder) { - file = CreateFolders(filePath, scanFolder); + file = CreateFolders(absoluteFilePath.Native(), scanFolder); } else { - AZStd::string sourcePath; - AZStd::string sourceName; - AZStd::string sourceExtension; - StringFunc::Path::Split(filePath, nullptr, &sourcePath, &sourceName, &sourceExtension); // if missing create folders leading to file's location and get immediate parent // (we don't need to have fileIds for any folders created yet, they will be added later) - auto parent = CreateFolders(sourcePath.c_str(), scanFolder); + auto parent = CreateFolders(absoluteFilePath.ParentPath().Native(), scanFolder); // for simplicity in AB, files are represented as sources, but they are missing SourceDatabaseEntry-specific information such as SourceUuid auto source = aznew SourceAssetBrowserEntry(); - source->m_name = (sourceName + sourceExtension).c_str(); + source->m_name = absoluteFilePath.Filename().Native(); source->m_fileId = fileDatabaseEntry.m_fileID; source->m_displayName = QString::fromUtf8(source->m_name.c_str()); source->m_scanFolderId = fileDatabaseEntry.m_scanFolderPK; - source->m_extension = sourceExtension.c_str(); + source->m_extension = absoluteFilePath.Extension().Native(); parent->AddChild(source); file = source; } EntryCache::GetInstance()->m_fileIdMap[fileDatabaseEntry.m_fileID] = file; - AZStd::string fullPath = file->m_fullPath; - AzFramework::StringFunc::Path::Normalize(fullPath); - EntryCache::GetInstance()->m_absolutePathToFileId[fullPath] = fileDatabaseEntry.m_fileID; + AZStd::string filePath = AZ::IO::PathView(file->m_fullPath).LexicallyNormal().String(); + EntryCache::GetInstance()->m_absolutePathToFileId[filePath] = fileDatabaseEntry.m_fileID; } bool RootAssetBrowserEntry::RemoveFile(const AZ::s64& fileId) const @@ -305,116 +303,95 @@ namespace AzToolsFramework } } - FolderAssetBrowserEntry* RootAssetBrowserEntry::CreateFolder(const char* folderName, AssetBrowserEntry* parent) + AssetBrowserEntry* RootAssetBrowserEntry::GetNearestAncestor(AZ::IO::PathView absolutePathView, AssetBrowserEntry* parent, + AZStd::unordered_set& visitedSet) + { + auto IsPathRelativeToEntry = [absolutePathView](AssetBrowserEntry* assetBrowserEntry) + { + auto& childPath = assetBrowserEntry->m_fullPath; + return absolutePathView.IsRelativeTo(AZ::IO::PathView(childPath)); + }; + + if (visitedSet.contains(parent)) + { + return {}; + } + + visitedSet.insert(parent); + + AssetBrowserEntry* nearestAncestor{}; + for (AssetBrowserEntry* childBrowserEntry : parent->m_children) + { + if (IsPathRelativeToEntry(childBrowserEntry)) + { + // Walk the AssetBrowserEntry Tree looking for a nearer ancestor to the absolute path + // If one is not found in the recursive call to GetNearestAncestor, then the childBrowserEntry + // is the current best candidate + AssetBrowserEntry* candidateAncestor = GetNearestAncestor(absolutePathView, childBrowserEntry, visitedSet); + candidateAncestor = candidateAncestor != nullptr ? candidateAncestor : childBrowserEntry; + AZ::IO::PathView candidatePathView(candidateAncestor->m_fullPath); + // If the candidate is relative to the current nearest ancestor, then it is even nearer to the path + if (!nearestAncestor || candidatePathView.IsRelativeTo(nearestAncestor->m_fullPath)) + { + nearestAncestor = candidateAncestor; + // If the full path compares equal to the AssetBrowserEntry path, then no need to proceed any further + if (AZ::IO::PathView(nearestAncestor->m_fullPath) == absolutePathView) + { + break; + } + } + } + } + + return nearestAncestor; + } + + FolderAssetBrowserEntry* RootAssetBrowserEntry::CreateFolder(AZStd::string_view folderName, AssetBrowserEntry* parent) { auto it = AZStd::find_if(parent->m_children.begin(), parent->m_children.end(), [folderName](AssetBrowserEntry* entry) - { - if (!azrtti_istypeof(entry)) - { - return false; - } - return AzFramework::StringFunc::Equal(entry->m_name.c_str(), folderName); - }); + { + if (!azrtti_istypeof(entry)) + { + return false; + } + return AZ::IO::PathView(entry->m_name) == AZ::IO::PathView(folderName); + }); if (it != parent->m_children.end()) { return azrtti_cast(*it); } const auto folder = aznew FolderAssetBrowserEntry(); folder->m_name = folderName; - folder->m_displayName = folderName; + folder->m_displayName = QString::fromUtf8(folderName.data(), aznumeric_caster(folderName.size())); parent->AddChild(folder); return folder; } - AssetBrowserEntry* RootAssetBrowserEntry::CreateFolders(const char* relativePath, AssetBrowserEntry* parent) + AssetBrowserEntry* RootAssetBrowserEntry::CreateFolders(AZStd::string_view absolutePath, AssetBrowserEntry* parent) { - auto children(parent->m_children); - int n = 0; + AZ::IO::PathView absolutePathView(absolutePath); + // Find the nearest ancestor path to the absolutePath + AZStd::unordered_set visitedSet; - // check if folder with the same name already exists - // step through every character in relativePath and compare to each child's relative path of suggested parent - // if a character @n in child's rel path mismatches character at n in relativePath, remove that child from further search - while (!children.empty() && relativePath[n]) + if (AssetBrowserEntry* nearestAncestor = GetNearestAncestor(absolutePathView, parent, visitedSet); + nearestAncestor != nullptr) { - AZStd::vector toRemove; - for (auto child : children) - { - auto& childPath = azrtti_istypeof(parent) ? child->m_fullPath : child->m_relativePath; - - // child's path mismatched, remove it from search candidates - if (childPath.length() == n || childPath[n] != relativePath[n]) - { - toRemove.push_back(child); - - // it is possible that child may be a closer parent, substitute it as new potential parent - // e.g. child->m_relativePath = 'Gems', relativePath = 'Gems/Assets', old parent = root, new parent = Gems - if (childPath.length() == n && relativePath[n] == AZ_CORRECT_DATABASE_SEPARATOR) - { - parent = child; - relativePath += n; // advance relative path n characters since the parent has changed - n = 0; // Once the relative path pointer is advanced, reset n - } - } - } - for (auto entry : toRemove) - { - children.erase(AZStd::remove(children.begin(), children.end(), entry), children.end()); - } - n++; + parent = nearestAncestor; } - // filter out the remaining children that don't end with '/' or '\0' - // for example if folderName = "foo", while children may still remain with names like "foo123", - // which is not the same folder - AZStd::vector toRemove; - for (auto child : children) + // If the nearest ancestor is the absolutePath, then it is already crated + if (absolutePathView == AZ::IO::PathView(parent->GetFullPath())) { - auto& childPath = azrtti_istypeof(parent) ? child->m_fullPath : child->m_relativePath; - // check if there are non-null characters remaining @n - if (childPath.length() > n) - { - toRemove.push_back(child); - } - } - for (auto entry : toRemove) - { - children.erase(AZStd::remove(children.begin(), children.end(), entry), children.end()); + return parent; } - // at least one child remains, this means the folder with this name already exists, return it - if (!children.empty()) + // create all missing folders + auto proximateToPath = absolutePathView.IsRelativeTo(parent->m_fullPath) + ? absolutePathView.LexicallyProximate(parent->m_fullPath) + : AZ::IO::FixedMaxPath(absolutePathView); + for (AZ::IO::FixedMaxPath scanFolderSegment : proximateToPath) { - parent = children.front(); - } - // if it's a scanfolder, then do not create folders leading to it - // e.g. instead of 'C:\dev\SampleProject' just create 'SampleProject' - else if (parent->GetEntryType() == AssetEntryType::Root) - { - AZStd::string folderName; - AzFramework::StringFunc::Path::Split(relativePath, nullptr, nullptr, &folderName); - parent = CreateFolder(folderName.c_str(), parent); - parent->m_fullPath = relativePath; - } - // otherwise create all missing folders - else - { - n = 0; - AZStd::string folderName(strlen(relativePath) + 1, '\0'); - // iterate through relativePath until the first '/' - while (relativePath[n] && relativePath[n] != AZ_CORRECT_DATABASE_SEPARATOR) - { - folderName[n] = relativePath[n]; - n++; - } - if (n > 0) - { - parent = CreateFolder(folderName.c_str(), parent); - } - // n+1 also skips the '/' character - if (relativePath[n] && relativePath[n + 1]) - { - parent = CreateFolders(relativePath + n + 1, parent); - } + parent = CreateFolder(scanFolderSegment.c_str(), parent); } return parent; } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/RootAssetBrowserEntry.h b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/RootAssetBrowserEntry.h index 883f9dec01..62fbc7a39d 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/RootAssetBrowserEntry.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/RootAssetBrowserEntry.h @@ -8,6 +8,7 @@ #include #include +#include #include #include @@ -77,12 +78,15 @@ namespace AzToolsFramework private: AZ_DISABLE_COPY_MOVE(RootAssetBrowserEntry); - AZStd::string m_enginePath; + AZ::IO::Path m_enginePath; //! Create folder entry child - FolderAssetBrowserEntry* CreateFolder(const char* folderName, AssetBrowserEntry* parent); - //! Recursively create folder structure leading to relative path from parent - AssetBrowserEntry* CreateFolders(const char* relativePath, AssetBrowserEntry* parent); + FolderAssetBrowserEntry* CreateFolder(AZStd::string_view folderName, AssetBrowserEntry* parent); + //! Recursively create folder structure leading to path from parent + AssetBrowserEntry* CreateFolders(AZStd::string_view absolutePath, AssetBrowserEntry* parent); + // Retrieves the nearest ancestor AssetBrowserEntry from the absolutePath + static AssetBrowserEntry* GetNearestAncestor(AZ::IO::PathView absolutePath, AssetBrowserEntry* parent, + AZStd::unordered_set& visitedSet); bool m_isInitialUpdate = false; }; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/SourceAssetBrowserEntry.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/SourceAssetBrowserEntry.cpp index e45c234c92..1eea909f7c 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/SourceAssetBrowserEntry.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/SourceAssetBrowserEntry.cpp @@ -26,9 +26,7 @@ namespace AzToolsFramework if (EntryCache* cache = EntryCache::GetInstance()) { cache->m_fileIdMap.erase(m_fileId); - AZStd::string fullPath = m_fullPath; - AzFramework::StringFunc::Path::Normalize(fullPath); - cache->m_absolutePathToFileId.erase(fullPath); + cache->m_absolutePathToFileId.erase(m_fullPath.LexicallyNormal().Native()); if (m_sourceId != -1) { From 173126f5a5f1b3a1efc65e5a902c48d63b2a5ad9 Mon Sep 17 00:00:00 2001 From: Brian Herrera Date: Mon, 19 Jul 2021 16:09:47 -0700 Subject: [PATCH 015/803] Add script for license scanner (#2267) * Add script for license scanner This script will scan the source tree for license files and generate a file with the contents of all the licenses. Signed-off-by: brianherrera --- scripts/license_scanner/license_scanner.py | 129 ++++++++++++++++++++ scripts/license_scanner/scanner_config.json | 12 ++ 2 files changed, 141 insertions(+) create mode 100644 scripts/license_scanner/license_scanner.py create mode 100644 scripts/license_scanner/scanner_config.json diff --git a/scripts/license_scanner/license_scanner.py b/scripts/license_scanner/license_scanner.py new file mode 100644 index 0000000000..c0e3c1f1ba --- /dev/null +++ b/scripts/license_scanner/license_scanner.py @@ -0,0 +1,129 @@ +# +# Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. +# +# SPDX-License-Identifier: Apache-2.0 OR MIT +# +# + +import argparse +import fnmatch +import json +import os +import pathlib +import re +import sys + + +class LicenseScanner: + """Class to contain license scanner. + + Scans source tree for license files using provided filename patterns and generates a file + with the contents of all the licenses. + + :param config_file: Config file with license patterns and scanner settings + """ + + DEFAULT_CONFIG_FILE = 'scanner_config.json' + + def __init__(self, config_file=None): + self.config_file = config_file + self.config_data = self._load_config() + self.license_regex = self._load_license_regex() + + def _load_config(self): + """Load config from the provided file. Sets default file if one is not provided.""" + if self.config_file is None: + script_directory = os.path.dirname(os.path.abspath(__file__)) # Default file expected in same dir as script + self.config_file = os.path.join(script_directory, self.DEFAULT_CONFIG_FILE) + + try: + with open(self.config_file) as f: + return json.load(f) + except FileNotFoundError: + print('Config file cannot be found') + raise + + def _load_license_regex(self): + """Returns regex object with case-insensitive matching from the list of filename patterns.""" + regex_patterns = [] + for pattern in self.config_data['license_patterns']: + regex_patterns.append(fnmatch.translate(pattern)) + return re.compile('|'.join(regex_patterns), re.IGNORECASE) + + def scan(self, path=os.curdir): + """Scan directory tree for filenames matching license_regex. + + :param path: Path of the directory to run scanner + :return: Package paths and their corresponding license file contents + :rtype: dict + """ + licenses = 0 + license_files = {} + + for dirpath, dirnames, filenames in os.walk(path): + for file in filenames: + if self.license_regex.match(file): + license_file_content = self._get_license_file_contents(os.path.join(dirpath, file)) + rel_dirpath = os.path.relpath(dirpath, path) # Limit path inside scanned directory + license_files[rel_dirpath] = license_file_content + licenses += 1 + print(f'License file: {os.path.join(dirpath, file)}') + + # Remove directories that should not be scanned + for dir in self.config_data['excluded_directories']: + if dir in dirnames: + dirnames.remove(dir) + print(f'{licenses} license files found.') + return license_files + + def _get_license_file_contents(self, filepath): + try: + with open(filepath, encoding='utf8') as f: + return f.read() + except UnicodeDecodeError: + print(f'Unable to read license file: {filepath}') + pass + + def create_license_file(self, licenses, filepath='NOTICES.txt'): + """Creates file with all the provided license file contents. + + :param licenses: Dict with package paths and their corresponding license file contents + :param filepath: Path to write the file + """ + package_separator = '------------------------------------' + with open(filepath, 'w', encoding='utf8') as f: + for directory, license in licenses.items(): + license_output = '\n\n'.join([ + f'{package_separator}', + f'Package path: {directory}', + 'License:', + f'{license}\n' + ]) + f.write(license_output) + return None + + +def parse_args(): + parser = argparse.ArgumentParser( + description='Script to run LicenseScanner and generate license file') + parser.add_argument('--config-file', '-c', type=pathlib.Path, help='Config file for LicenseScanner') + parser.add_argument('--license-file-path', '-l', type=pathlib.Path, help='Create license file in the provided path') + parser.add_argument('--scan-path', '-s', default=os.curdir, type=pathlib.Path, help='Path to scan') + return parser.parse_args() + + +def main(): + try: + args = parse_args() + ls = LicenseScanner(args.config_file) + licenses = ls.scan(args.scan_path) + + if args.license_file_path: + ls.create_license_file(licenses, args.license_file_path) + except FileNotFoundError as e: + print(f'Type: {type(e).__name__}, Error: {e}') + return 1 + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/scripts/license_scanner/scanner_config.json b/scripts/license_scanner/scanner_config.json new file mode 100644 index 0000000000..b5863a7d31 --- /dev/null +++ b/scripts/license_scanner/scanner_config.json @@ -0,0 +1,12 @@ +{ + "excluded_directories": [ + ".git", + ".venv", + "build", + "license_scanner" + ], + "license_patterns": [ + "LICENSE*", + "COPYING*" + ] +} From afb57c9cf679592a209dbccdd5f38126e03d6b59 Mon Sep 17 00:00:00 2001 From: Scott Romero <24445312+AMZN-ScottR@users.noreply.github.com> Date: Mon, 19 Jul 2021 18:17:55 -0700 Subject: [PATCH 016/803] [stabliziation/2106] update 3rd party license file name to be pulled into the installer package (#2281) License file name was changed in #2267 Signed-off-by: AMZN-ScottR 24445312+AMZN-ScottR@users.noreply.github.com --- cmake/Packaging.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/Packaging.cmake b/cmake/Packaging.cmake index a07e1ec1d3..2240ff472c 100644 --- a/cmake/Packaging.cmake +++ b/cmake/Packaging.cmake @@ -128,7 +128,7 @@ install(FILES ${_cmake_package_dest} # the version string and git tags are intended to be synchronized so it should be safe to use that instead # of directly calling into git which could get messy in certain scenarios if(${CPACK_PACKAGE_VERSION} VERSION_GREATER "0.0.0.0") - set(_3rd_party_license_filename SPDX-Licenses.txt) + set(_3rd_party_license_filename NOTICES.txt) set(_3rd_party_license_url "https://raw.githubusercontent.com/o3de/3p-package-source/${CPACK_PACKAGE_VERSION}/${_3rd_party_license_filename}") set(_3rd_party_license_dest ${CPACK_BINARY_DIR}/${_3rd_party_license_filename}) From abce54b3cd0a574fff1a8612be838779ab597a73 Mon Sep 17 00:00:00 2001 From: Axel Nana Date: Tue, 20 Jul 2021 01:05:09 +0100 Subject: [PATCH 017/803] Add missing `*.hxx` pattern Signed-off-by: Axel Nana --- cmake/Platform/Common/Install_common.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/cmake/Platform/Common/Install_common.cmake b/cmake/Platform/Common/Install_common.cmake index 5b476667e2..0a84d3ceb2 100644 --- a/cmake/Platform/Common/Install_common.cmake +++ b/cmake/Platform/Common/Install_common.cmake @@ -64,6 +64,7 @@ function(ly_setup_target OUTPUT_CONFIGURED_TARGET ALIAS_TARGET_NAME absolute_tar PATTERN *.h PATTERN *.hpp PATTERN *.inl + PATTERN *.hxx ) endif() endforeach() From b58286d9b1022c3e3051c3225b7000935066fd4c Mon Sep 17 00:00:00 2001 From: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> Date: Tue, 20 Jul 2021 20:40:04 -0500 Subject: [PATCH 018/803] Fixed RootAssetBrowserEntry setting of child AssetBrowserEntries The issue is due to RootAssetBrowserEntry::UpdateChildPaths not taking the RootAssetBrowserEntry fullpath into account when appending the child path entry Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> --- .../AssetBrowser/Entries/RootAssetBrowserEntry.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/RootAssetBrowserEntry.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/RootAssetBrowserEntry.cpp index 0e132d2581..eec9970ca3 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/RootAssetBrowserEntry.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Entries/RootAssetBrowserEntry.cpp @@ -399,7 +399,7 @@ namespace AzToolsFramework void RootAssetBrowserEntry::UpdateChildPaths(AssetBrowserEntry* child) const { child->m_relativePath = child->m_name; - child->m_fullPath = child->m_name; + child->m_fullPath = m_fullPath / child->m_name; AssetBrowserEntry::UpdateChildPaths(child); } From 3050a4db479fb2dacf59942f7b0b42d7d82fcdcd Mon Sep 17 00:00:00 2001 From: jckand-amzn Date: Wed, 21 Jul 2021 10:18:18 -0500 Subject: [PATCH 019/803] Removing obsolete Vegetation Debugger test Signed-off-by: jckand-amzn --- .../EditorScripts/Debugger_DebugCVarsWorks.py | 55 ------------------ .../largeworlds/dyn_veg/test_Debugger.py | 56 ------------------- 2 files changed, 111 deletions(-) delete mode 100755 AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/Debugger_DebugCVarsWorks.py delete mode 100755 AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_Debugger.py diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/Debugger_DebugCVarsWorks.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/Debugger_DebugCVarsWorks.py deleted file mode 100755 index 40fd67d957..0000000000 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/Debugger_DebugCVarsWorks.py +++ /dev/null @@ -1,55 +0,0 @@ -""" -Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. - -SPDX-License-Identifier: Apache-2.0 OR MIT -""" - -import os -import sys - -import azlmbr.legacy.general as general -import azlmbr.paths - -sys.path.append(os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Gem", "PythonTests")) -import editor_python_test_tools.hydra_editor_utils as hydra -from editor_python_test_tools.editor_test_helper import EditorTestHelper - - -class TestDebuggerDebugCVarsWorks(EditorTestHelper): - def __init__(self): - EditorTestHelper.__init__(self, log_prefix="Debugger_DebugCVarsWorks", args=["level"]) - - def run_test(self): - """ - Summary: - C2789148 Vegetation Debug CVars are enabled when the Debugger component is present - - Expected Result: - The following commands are available in the Editor only when the Vegetation Debugger Level component is present: - veg_debugDumpReport (Command) - veg_debugRefreshAllAreas (Command) - - :return: None - """ - - # Create empty level - self.test_success = self.create_level( - self.args["level"], - heightmap_resolution=1024, - heightmap_meters_per_pixel=1, - terrain_texture_resolution=4096, - use_terrain=False, - ) - - # Initially run the command in console without Debugger component - general.run_console("veg_debugDumpReport") - - # Add the Vegetation Debugger component to the Level Inspector - hydra.add_level_component("Vegetation Debugger") - - # Run a command again after adding the Vegetation debugger - general.run_console("veg_debugRefreshAllAreas") - - -test = TestDebuggerDebugCVarsWorks() -test.run() diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_Debugger.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_Debugger.py deleted file mode 100755 index ed979136e0..0000000000 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_Debugger.py +++ /dev/null @@ -1,56 +0,0 @@ -""" -Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. - -SPDX-License-Identifier: Apache-2.0 OR MIT -""" - -import os -import pytest -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 editor_python_test_tools.hydra_test_utils as hydra - -logger = logging.getLogger(__name__) -test_directory = os.path.join(os.path.dirname(__file__), "EditorScripts") - - -@pytest.mark.parametrize("project", ["AutomatedTesting"]) -@pytest.mark.parametrize("level", ["tmp_level"]) -@pytest.mark.usefixtures("automatic_process_killer") -@pytest.mark.parametrize("launcher_platform", ['windows_editor']) -class TestDebugger(object): - @pytest.fixture(autouse=True) - def setup_teardown(self, request, workspace, project, level): - # Cleanup our temp level - file_system.delete([os.path.join(workspace.paths.engine_root(), project, "Levels", level)], True, True) - - def teardown(): - # Cleanup our temp level - file_system.delete([os.path.join(workspace.paths.engine_root(), project, "Levels", level)], True, True) - - request.addfinalizer(teardown) - - @pytest.mark.test_case_id("C2789148") - @pytest.mark.SUITE_periodic - @pytest.mark.dynveg_misc - def test_Debugger_DebugCVarsWork(self, request, editor, level, workspace, launcher_platform): - cfg_args = [level] - - expected_lines = [ - "Debugger_DebugCVarsWorks: test started", - "[Warning] Unknown command: veg_debugDumpReport", - "[CONSOLE] Executing console command 'veg_debugRefreshAllAreas'", - "Debugger_DebugCVarsWorks: result=SUCCESS", - ] - - hydra.launch_and_validate_results( - request, - test_directory, - editor, - "Debugger_DebugCVarsWorks.py", - expected_lines=expected_lines, - cfg_args=cfg_args - ) From 7ebdde0be01477ba036bad7f5a1e36ae50e2d879 Mon Sep 17 00:00:00 2001 From: jckand-amzn Date: Wed, 21 Jul 2021 10:25:48 -0500 Subject: [PATCH 020/803] Adding xfail mark to test_LandscapeCanvas_GraphClosed_OnEntityDelete Signed-off-by: jckand-amzn --- .../landscape_canvas/test_GeneralGraphFunctionality.py | 1 + 1 file changed, 1 insertion(+) diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/test_GeneralGraphFunctionality.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/test_GeneralGraphFunctionality.py index bbca71461c..e2aa222c3f 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/test_GeneralGraphFunctionality.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/test_GeneralGraphFunctionality.py @@ -104,6 +104,7 @@ class TestGeneralGraphFunctionality(object): @pytest.mark.test_case_id("C17488412") @pytest.mark.SUITE_periodic + @pytest.mark.xfail(reason="https://github.com/o3de/o3de/issues/2201") def test_LandscapeCanvas_GraphClosed_OnEntityDelete(self, request, editor, level, launcher_platform): cfg_args = [level] From fc1ccb9e8574a1d997bbc791fb46a6a1325ee3a2 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Wed, 21 Jul 2021 17:17:09 -0700 Subject: [PATCH 021/803] Issues/2126 PhysX Gem can't be used as build dependency in engine SDK Part (#2337) * Applying GENEX_EVAL to 2 cases where the genex can produce another genex Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> * Missing case when the folder is an external one to the engine/project (e.g. external gems) Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/LauncherUnified/launcher_generator.cmake | 4 ++-- cmake/LYWrappers.cmake | 15 ++++++++++----- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/Code/LauncherUnified/launcher_generator.cmake b/Code/LauncherUnified/launcher_generator.cmake index 628b5fffac..28fddad1eb 100644 --- a/Code/LauncherUnified/launcher_generator.cmake +++ b/Code/LauncherUnified/launcher_generator.cmake @@ -40,9 +40,9 @@ foreach(project_name project_path IN ZIP_LISTS LY_PROJECTS_TARGET_NAME LY_PROJEC add_custom_target(${project_name}.Assets COMMENT "Processing ${project_name} assets..." COMMAND "${CMAKE_COMMAND}" - -DLY_LOCK_FILE=$/project_assets.lock + -DLY_LOCK_FILE=$>/project_assets.lock -P ${LY_ROOT_FOLDER}/cmake/CommandExecution.cmake - EXEC_COMMAND $ + EXEC_COMMAND $> --zeroAnalysisMode --project-path=${project_real_path} --platforms=${LY_ASSET_DEPLOY_ASSET_TYPE} diff --git a/cmake/LYWrappers.cmake b/cmake/LYWrappers.cmake index 40bf6ef541..cfe6df5c81 100644 --- a/cmake/LYWrappers.cmake +++ b/cmake/LYWrappers.cmake @@ -391,10 +391,10 @@ function(ly_delayed_target_link_libraries) endif() if(item_type STREQUAL MODULE_LIBRARY) - target_include_directories(${target} ${visibility} $) - target_link_libraries(${target} ${visibility} $) - target_compile_definitions(${target} ${visibility} $) - target_compile_options(${target} ${visibility} $) + target_include_directories(${target} ${visibility} $>) + target_link_libraries(${target} ${visibility} $>) + target_compile_definitions(${target} ${visibility} $>) + target_compile_options(${target} ${visibility} $>) else() ly_parse_third_party_dependencies(${item}) target_link_libraries(${target} ${visibility} ${item}) @@ -659,7 +659,12 @@ function(ly_get_vs_folder_directory absolute_target_source_dir output_source_dir if(is_target_prefix_of_engine_root) cmake_path(RELATIVE_PATH absolute_target_source_dir BASE_DIRECTORY ${LY_ROOT_FOLDER} OUTPUT_VARIABLE relative_target_source_dir) else() - cmake_path(GET absolute_target_source_dir RELATIVE_PART relative_target_source_dir) + cmake_path(IS_PREFIX CMAKE_SOURCE_DIR ${absolute_target_source_dir} is_target_prefix_of_source_dir) + if(is_target_prefix_of_source_dir) + cmake_path(RELATIVE_PATH absolute_target_source_dir BASE_DIRECTORY ${CMAKE_SOURCE_DIR} OUTPUT_VARIABLE relative_target_source_dir) + else() + cmake_path(GET absolute_target_source_dir RELATIVE_PART relative_target_source_dir) + endif() endif() set(${output_source_dir} ${relative_target_source_dir} PARENT_SCOPE) From d08cbd2c339a40425c1376ba22f078196ac3b5df Mon Sep 17 00:00:00 2001 From: evanchia Date: Thu, 22 Jul 2021 13:55:55 -0700 Subject: [PATCH 022/803] Moving load level test from sandbox to smoke with fixes Signed-off-by: evanchia --- .../Gem/PythonTests/smoke/CMakeLists.txt | 13 ++- .../test_RemoteConsole_CPULoadLevel_Works.py | 105 ++++++++++++++++++ ... test_RemoteConsole_GPULoadLevel_Works.py} | 3 +- 3 files changed, 113 insertions(+), 8 deletions(-) create mode 100644 AutomatedTesting/Gem/PythonTests/smoke/test_RemoteConsole_CPULoadLevel_Works.py rename AutomatedTesting/Gem/PythonTests/smoke/{test_RemoteConsole_LoadLevel_Works.py => test_RemoteConsole_GPULoadLevel_Works.py} (98%) diff --git a/AutomatedTesting/Gem/PythonTests/smoke/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/smoke/CMakeLists.txt index 600911e9f1..a6584c3de8 100644 --- a/AutomatedTesting/Gem/PythonTests/smoke/CMakeLists.txt +++ b/AutomatedTesting/Gem/PythonTests/smoke/CMakeLists.txt @@ -32,12 +32,12 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) ) ly_add_pytest( - NAME AutomatedTesting::SandboxTest - TEST_SUITE sandbox + NAME AutomatedTesting::LoadLevelGPU + TEST_SUITE smoke TEST_SERIAL - PATH ${CMAKE_CURRENT_LIST_DIR} - PYTEST_MARKS "SUITE_sandbox" - TIMEOUT 1500 + TEST_REQUIRES gpu + PATH ${CMAKE_CURRENT_LIST_DIR}/test_RemoteConsole_GPULoadLevel_Works.py + TIMEOUT 100 RUNTIME_DEPENDENCIES AZ::AssetProcessor AZ::PythonBindingsExample @@ -45,7 +45,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) AutomatedTesting.GameLauncher AutomatedTesting.Assets COMPONENT - Sandbox + Smoke ) ly_add_pytest( @@ -74,4 +74,5 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) AutomatedTesting.GameLauncher AutomatedTesting.Assets ) + endif() diff --git a/AutomatedTesting/Gem/PythonTests/smoke/test_RemoteConsole_CPULoadLevel_Works.py b/AutomatedTesting/Gem/PythonTests/smoke/test_RemoteConsole_CPULoadLevel_Works.py new file mode 100644 index 0000000000..ea27b14aab --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/smoke/test_RemoteConsole_CPULoadLevel_Works.py @@ -0,0 +1,105 @@ +""" +Copyright (c) Contributors to the Open 3D Engine Project. +For complete copyright and license terms please see the LICENSE at the root of this distribution. + +SPDX-License-Identifier: Apache-2.0 OR MIT + + +UI Apps: AutomatedTesting.GameLauncher +Launch AutomatedTesting.GameLauncher with Simple level +Test should run in both gpu and non gpu +""" + +import pytest +import psutil + +# Bail on the test if ly_test_tools doesn't exist. +pytest.importorskip("ly_test_tools") +import ly_test_tools.environment.waiter as waiter +from ly_remote_console.remote_console_commands import RemoteConsole as RemoteConsole +from ly_remote_console.remote_console_commands import ( + send_command_and_expect_response as send_command_and_expect_response, +) + + +@pytest.mark.parametrize("launcher_platform", ["windows"]) +@pytest.mark.parametrize("project", ["AutomatedTesting"]) +@pytest.mark.parametrize("level", ["Simple"]) +@pytest.mark.SUITE_smoke +class TestRemoteConsoleLoadLevelWorks(object): + @pytest.fixture + def remote_console_instance(self, request): + console = RemoteConsole() + + def teardown(): + if console.connected: + console.stop() + + request.addfinalizer(teardown) + + return console + + def test_RemoteConsole_LoadLevel_Works(self, launcher, level, remote_console_instance, launcher_platform): + expected_lines = ['Level system is loading "Simple"'] + + self.launch_and_validate_results_launcher(launcher, level, remote_console_instance, expected_lines) + + def launch_and_validate_results_launcher( + self, + launcher, + level, + remote_console_instance, + expected_lines, + null_renderer=True, + port_listener_timeout=120, + log_monitor_timeout=300, + remote_console_port=4600, + ): + """ + Runs the launcher with the specified level, and monitors Game.log for expected lines. + :param launcher: Configured launcher object to run test against. + :param level: The level to load in the launcher. + :param remote_console_instance: Configured Remote Console object. + :param expected_lines: Expected lines to search log for. + :oaram null_renderer: Specifies the test does not require the renderer. Defaults to True. + :param port_listener_timeout: Timeout for verifying successful connection to Remote Console. + :param log_monitor_timeout: Timeout for monitoring for lines in Game.log + :param remote_console_port: The port used to communicate with the Remote Console. + """ + + def _check_for_listening_port(port): + """ + Checks to see if the connection to the designated port was established. + :param port: Port to listen to. + :return: True if port is listening. + """ + port_listening = False + for conn in psutil.net_connections(): + if "port={}".format(port) in str(conn): + port_listening = True + return port_listening + + if null_renderer: + launcher.args.extend(["-rhi=Null"]) + + # Start the Launcher + with launcher.start(): + + # Ensure Remote Console can be reached + waiter.wait_for( + lambda: _check_for_listening_port(remote_console_port), + port_listener_timeout, + exc=AssertionError("Port {} not listening.".format(remote_console_port)), + ) + remote_console_instance.start(timeout=30) + + # Load the specified level in the launcher + send_command_and_expect_response( + remote_console_instance, f"loadlevel {level}", "LEVEL_LOAD_END", timeout=30 + ) + + # Monitor the console for expected lines + for line in expected_lines: + assert remote_console_instance.expect_log_line( + line, log_monitor_timeout + ), f"Expected line not found: {line}" diff --git a/AutomatedTesting/Gem/PythonTests/smoke/test_RemoteConsole_LoadLevel_Works.py b/AutomatedTesting/Gem/PythonTests/smoke/test_RemoteConsole_GPULoadLevel_Works.py similarity index 98% rename from AutomatedTesting/Gem/PythonTests/smoke/test_RemoteConsole_LoadLevel_Works.py rename to AutomatedTesting/Gem/PythonTests/smoke/test_RemoteConsole_GPULoadLevel_Works.py index b1606e1910..6c4a22bc23 100644 --- a/AutomatedTesting/Gem/PythonTests/smoke/test_RemoteConsole_LoadLevel_Works.py +++ b/AutomatedTesting/Gem/PythonTests/smoke/test_RemoteConsole_GPULoadLevel_Works.py @@ -25,7 +25,6 @@ from ly_remote_console.remote_console_commands import ( @pytest.mark.parametrize("launcher_platform", ["windows"]) @pytest.mark.parametrize("project", ["AutomatedTesting"]) @pytest.mark.parametrize("level", ["Simple"]) -@pytest.mark.SUITE_sandbox class TestRemoteConsoleLoadLevelWorks(object): @pytest.fixture def remote_console_instance(self, request): @@ -80,7 +79,7 @@ class TestRemoteConsoleLoadLevelWorks(object): return port_listening if null_renderer: - launcher.args.extend(["-NullRenderer"]) + launcher.args.extend(["-rhi=Null"]) # Start the Launcher with launcher.start(): From 05728920f7ba4490505b26fbebd691f24c443e26 Mon Sep 17 00:00:00 2001 From: evanchia Date: Thu, 22 Jul 2021 15:05:09 -0700 Subject: [PATCH 023/803] Replaced with imported functions for smoke tests Signed-off-by: evanchia --- .../Gem/PythonTests/smoke/CMakeLists.txt | 1 - .../test_RemoteConsole_CPULoadLevel_Works.py | 63 +------------------ .../test_RemoteConsole_GPULoadLevel_Works.py | 63 +------------------ 3 files changed, 4 insertions(+), 123 deletions(-) diff --git a/AutomatedTesting/Gem/PythonTests/smoke/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/smoke/CMakeLists.txt index a6584c3de8..78ac85de9f 100644 --- a/AutomatedTesting/Gem/PythonTests/smoke/CMakeLists.txt +++ b/AutomatedTesting/Gem/PythonTests/smoke/CMakeLists.txt @@ -41,7 +41,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) RUNTIME_DEPENDENCIES AZ::AssetProcessor AZ::PythonBindingsExample - Legacy::Editor AutomatedTesting.GameLauncher AutomatedTesting.Assets COMPONENT diff --git a/AutomatedTesting/Gem/PythonTests/smoke/test_RemoteConsole_CPULoadLevel_Works.py b/AutomatedTesting/Gem/PythonTests/smoke/test_RemoteConsole_CPULoadLevel_Works.py index ea27b14aab..54d7b3eb6f 100644 --- a/AutomatedTesting/Gem/PythonTests/smoke/test_RemoteConsole_CPULoadLevel_Works.py +++ b/AutomatedTesting/Gem/PythonTests/smoke/test_RemoteConsole_CPULoadLevel_Works.py @@ -16,6 +16,7 @@ import psutil # Bail on the test if ly_test_tools doesn't exist. pytest.importorskip("ly_test_tools") import ly_test_tools.environment.waiter as waiter +import editor_python_test_tools.hydra_test_utils as editor_test_utils from ly_remote_console.remote_console_commands import RemoteConsole as RemoteConsole from ly_remote_console.remote_console_commands import ( send_command_and_expect_response as send_command_and_expect_response, @@ -42,64 +43,4 @@ class TestRemoteConsoleLoadLevelWorks(object): def test_RemoteConsole_LoadLevel_Works(self, launcher, level, remote_console_instance, launcher_platform): expected_lines = ['Level system is loading "Simple"'] - self.launch_and_validate_results_launcher(launcher, level, remote_console_instance, expected_lines) - - def launch_and_validate_results_launcher( - self, - launcher, - level, - remote_console_instance, - expected_lines, - null_renderer=True, - port_listener_timeout=120, - log_monitor_timeout=300, - remote_console_port=4600, - ): - """ - Runs the launcher with the specified level, and monitors Game.log for expected lines. - :param launcher: Configured launcher object to run test against. - :param level: The level to load in the launcher. - :param remote_console_instance: Configured Remote Console object. - :param expected_lines: Expected lines to search log for. - :oaram null_renderer: Specifies the test does not require the renderer. Defaults to True. - :param port_listener_timeout: Timeout for verifying successful connection to Remote Console. - :param log_monitor_timeout: Timeout for monitoring for lines in Game.log - :param remote_console_port: The port used to communicate with the Remote Console. - """ - - def _check_for_listening_port(port): - """ - Checks to see if the connection to the designated port was established. - :param port: Port to listen to. - :return: True if port is listening. - """ - port_listening = False - for conn in psutil.net_connections(): - if "port={}".format(port) in str(conn): - port_listening = True - return port_listening - - if null_renderer: - launcher.args.extend(["-rhi=Null"]) - - # Start the Launcher - with launcher.start(): - - # Ensure Remote Console can be reached - waiter.wait_for( - lambda: _check_for_listening_port(remote_console_port), - port_listener_timeout, - exc=AssertionError("Port {} not listening.".format(remote_console_port)), - ) - remote_console_instance.start(timeout=30) - - # Load the specified level in the launcher - send_command_and_expect_response( - remote_console_instance, f"loadlevel {level}", "LEVEL_LOAD_END", timeout=30 - ) - - # Monitor the console for expected lines - for line in expected_lines: - assert remote_console_instance.expect_log_line( - line, log_monitor_timeout - ), f"Expected line not found: {line}" + editor_test_utils.launch_and_validate_results_launcher(launcher, level, remote_console_instance, expected_lines, null_renderer=True) diff --git a/AutomatedTesting/Gem/PythonTests/smoke/test_RemoteConsole_GPULoadLevel_Works.py b/AutomatedTesting/Gem/PythonTests/smoke/test_RemoteConsole_GPULoadLevel_Works.py index 6c4a22bc23..bfce7895e6 100644 --- a/AutomatedTesting/Gem/PythonTests/smoke/test_RemoteConsole_GPULoadLevel_Works.py +++ b/AutomatedTesting/Gem/PythonTests/smoke/test_RemoteConsole_GPULoadLevel_Works.py @@ -16,6 +16,7 @@ import psutil # Bail on the test if ly_test_tools doesn't exist. pytest.importorskip("ly_test_tools") import ly_test_tools.environment.waiter as waiter +import editor_python_test_tools.hydra_test_utils as editor_test_utils from ly_remote_console.remote_console_commands import RemoteConsole as RemoteConsole from ly_remote_console.remote_console_commands import ( send_command_and_expect_response as send_command_and_expect_response, @@ -41,64 +42,4 @@ class TestRemoteConsoleLoadLevelWorks(object): def test_RemoteConsole_LoadLevel_Works(self, launcher, level, remote_console_instance, launcher_platform): expected_lines = ['Level system is loading "Simple"'] - self.launch_and_validate_results_launcher(launcher, level, remote_console_instance, expected_lines) - - def launch_and_validate_results_launcher( - self, - launcher, - level, - remote_console_instance, - expected_lines, - null_renderer=False, - port_listener_timeout=120, - log_monitor_timeout=300, - remote_console_port=4600, - ): - """ - Runs the launcher with the specified level, and monitors Game.log for expected lines. - :param launcher: Configured launcher object to run test against. - :param level: The level to load in the launcher. - :param remote_console_instance: Configured Remote Console object. - :param expected_lines: Expected lines to search log for. - :oaram null_renderer: Specifies the test does not require the renderer. Defaults to True. - :param port_listener_timeout: Timeout for verifying successful connection to Remote Console. - :param log_monitor_timeout: Timeout for monitoring for lines in Game.log - :param remote_console_port: The port used to communicate with the Remote Console. - """ - - def _check_for_listening_port(port): - """ - Checks to see if the connection to the designated port was established. - :param port: Port to listen to. - :return: True if port is listening. - """ - port_listening = False - for conn in psutil.net_connections(): - if "port={}".format(port) in str(conn): - port_listening = True - return port_listening - - if null_renderer: - launcher.args.extend(["-rhi=Null"]) - - # Start the Launcher - with launcher.start(): - - # Ensure Remote Console can be reached - waiter.wait_for( - lambda: _check_for_listening_port(remote_console_port), - port_listener_timeout, - exc=AssertionError("Port {} not listening.".format(remote_console_port)), - ) - remote_console_instance.start(timeout=30) - - # Load the specified level in the launcher - send_command_and_expect_response( - remote_console_instance, f"loadlevel {level}", "LEVEL_LOAD_END", timeout=30 - ) - - # Monitor the console for expected lines - for line in expected_lines: - assert remote_console_instance.expect_log_line( - line, log_monitor_timeout - ), f"Expected line not found: {line}" + editor_test_utils.launch_and_validate_results_launcher(launcher, level, remote_console_instance, expected_lines, null_renderer=False) From 9358428bebd7d3b0166af8cf447d58d7caf37f72 Mon Sep 17 00:00:00 2001 From: dmcdiar Date: Sun, 25 Jul 2021 22:39:22 -0700 Subject: [PATCH 024/803] Added object release queue notification to the RHI Device and ObjectCollector. Signed-off-by: dmcdiar --- Gems/Atom/RHI/Code/Include/Atom/RHI/Device.h | 4 ++ .../Code/Include/Atom/RHI/ObjectCollector.h | 60 +++++++++++++++++++ Gems/Atom/RHI/Code/Tests/Device.h | 2 + Gems/Atom/RHI/DX12/Code/Source/RHI/Device.cpp | 5 ++ Gems/Atom/RHI/DX12/Code/Source/RHI/Device.h | 1 + .../Atom/RHI/Metal/Code/Source/RHI/Device.cpp | 7 ++- Gems/Atom/RHI/Metal/Code/Source/RHI/Device.h | 3 +- Gems/Atom/RHI/Null/Code/Source/RHI/Device.cpp | 5 ++ Gems/Atom/RHI/Null/Code/Source/RHI/Device.h | 1 + .../RHI/Vulkan/Code/Source/RHI/Device.cpp | 5 ++ Gems/Atom/RHI/Vulkan/Code/Source/RHI/Device.h | 1 + Gems/Atom/RPI/Code/Tests/Common/RHI/Stubs.h | 1 + 12 files changed, 93 insertions(+), 2 deletions(-) diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/Device.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/Device.h index 3f79392403..4232658980 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/Device.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/Device.h @@ -8,6 +8,7 @@ #pragma once +#include #include #include #include @@ -140,6 +141,9 @@ namespace AZ //! Get the memory requirements for allocating a buffer resource. virtual ResourceMemoryRequirements GetResourceMemoryRequirements(const BufferDescriptor& descriptor) = 0; + //! Notifies after all objects currently in the platform release queue are released + virtual void ObjectCollectionNotify(RHI::ObjectCollectorNotifyFunction notifyFunction) = 0; + protected: DeviceFeatures m_features; DeviceLimits m_limits; diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/ObjectCollector.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/ObjectCollector.h index cb66225286..d79a86afea 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/ObjectCollector.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/ObjectCollector.h @@ -34,6 +34,8 @@ namespace AZ using MutexType = NullMutex; }; + using ObjectCollectorNotifyFunction = AZStd::function; + /** * Deferred-releases reference-counted objects at a specific latency. Example: Use to batch-release * objects that exist on the GPU timeline at the end of the frame after syncing the oldest GPU frame. @@ -85,6 +87,9 @@ namespace AZ /// Must not be called at collection time. size_t GetObjectCount() const; + /// Notifies after the current set of pending objects is released. + void Notify(ObjectCollectorNotifyFunction notifyFunction); + private: void QueueForCollectInternal(ObjectPtrType object); @@ -92,6 +97,7 @@ namespace AZ { AZStd::vector m_objects; uint64_t m_collectIteration; + AZStd::vector m_notifies; }; inline bool IsGarbageReady(size_t collectIteration) @@ -106,6 +112,7 @@ namespace AZ mutable typename Traits::MutexType m_mutex; AZStd::vector m_pendingObjects; AZStd::vector m_pendingGarbage; + AZStd::vector m_pendingNotifies; }; template @@ -174,6 +181,45 @@ namespace AZ } m_mutex.unlock(); + if (m_pendingNotifies.size()) + { + if (m_pendingGarbage.size()) + { + // find the newest garbage entry and add any pending notifies + Garbage& latestGarbage = m_pendingGarbage.front(); + size_t latestGarbageAge = m_currentIteration - latestGarbage.m_collectIteration; + size_t i = 1; + while (i < m_pendingGarbage.size()) + { + size_t age = m_currentIteration - m_pendingGarbage[i].m_collectIteration; + if (age < latestGarbageAge) + { + latestGarbage = m_pendingGarbage[i]; + latestGarbageAge = age; + } + } + + latestGarbage.m_notifies.insert(latestGarbage.m_notifies.end(), m_pendingNotifies.begin(), m_pendingNotifies.end()); + + m_mutex.lock(); + m_pendingNotifies.clear(); + m_mutex.unlock(); + + } + else + { + // garbage queue is empty, notify now + m_mutex.lock(); + for (auto& notifyFunction : m_pendingNotifies) + { + notifyFunction(); + } + + m_pendingNotifies.clear(); + m_mutex.unlock(); + } + } + size_t objectCount = 0; size_t i = 0; while (i < m_pendingGarbage.size()) @@ -189,6 +235,12 @@ namespace AZ } } objectCount += garbage.m_objects.size(); + + for (auto& notifyFunction : garbage.m_notifies) + { + notifyFunction(); + } + garbage = AZStd::move(m_pendingGarbage.back()); m_pendingGarbage.pop_back(); } @@ -215,5 +267,13 @@ namespace AZ return objectCount; } + + template + void ObjectCollector::Notify(ObjectCollectorNotifyFunction notifyFunction) + { + m_mutex.lock(); + m_pendingNotifies.push_back(notifyFunction); + m_mutex.unlock(); + } } } diff --git a/Gems/Atom/RHI/Code/Tests/Device.h b/Gems/Atom/RHI/Code/Tests/Device.h index 3a7c513c8b..e11bd75983 100644 --- a/Gems/Atom/RHI/Code/Tests/Device.h +++ b/Gems/Atom/RHI/Code/Tests/Device.h @@ -60,6 +60,8 @@ namespace UnitTest AZ::RHI::ResourceMemoryRequirements GetResourceMemoryRequirements([[maybe_unused]] const AZ::RHI::ImageDescriptor& descriptor) { return AZ::RHI::ResourceMemoryRequirements{}; }; AZ::RHI::ResourceMemoryRequirements GetResourceMemoryRequirements([[maybe_unused]] const AZ::RHI::BufferDescriptor& descriptor) { return AZ::RHI::ResourceMemoryRequirements{}; }; + + void ObjectCollectionNotify(AZ::RHI::ObjectCollectorNotifyFunction notifyFunction) override {} }; AZ::RHI::Ptr MakeTestDevice(); diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/Device.cpp b/Gems/Atom/RHI/DX12/Code/Source/RHI/Device.cpp index 88c9098952..9d23dfa43d 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI/Device.cpp +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/Device.cpp @@ -292,6 +292,11 @@ namespace AZ return memoryRequirements; } + void Device::ObjectCollectionNotify(RHI::ObjectCollectorNotifyFunction notifyFunction) + { + m_releaseQueue.Notify(notifyFunction); + } + //AZStd::vector Device::GetValidSwapChainImageFormats(const RHI::WindowHandle& windowHandle) const //{ // AZStd::vector formatsList; diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/Device.h b/Gems/Atom/RHI/DX12/Code/Source/RHI/Device.h index 149508307a..9119545342 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI/Device.h +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/Device.h @@ -162,6 +162,7 @@ namespace AZ void PreShutdown() override; RHI::ResourceMemoryRequirements GetResourceMemoryRequirements(const RHI::ImageDescriptor & descriptor) override; RHI::ResourceMemoryRequirements GetResourceMemoryRequirements(const RHI::BufferDescriptor & descriptor) override; + void ObjectCollectionNotify(RHI::ObjectCollectorNotifyFunction notifyFunction) override; ////////////////////////////////////////////////////////////////////////// RHI::ResultCode InitSubPlatform(RHI::PhysicalDevice& physicalDevice); diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/Device.cpp b/Gems/Atom/RHI/Metal/Code/Source/RHI/Device.cpp index f0771d7c45..dbd2204e93 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/Device.cpp +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/Device.cpp @@ -315,7 +315,12 @@ namespace AZ memoryRequirements.m_sizeInBytes = bufferSizeAndAlign.size; return memoryRequirements; } - + + void Device::ObjectCollectionNotify(RHI::ObjectCollectorNotifyFunction notifyFunction) + { + m_releaseQueue.Notify(notifyFunction); + } + void Device::InitFeatures() { diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/Device.h b/Gems/Atom/RHI/Metal/Code/Source/RHI/Device.h index d8c3092c59..9cdeee7eae 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/Device.h +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/Device.h @@ -151,7 +151,8 @@ namespace AZ NullDescriptorManager& GetNullDescriptorManager(); RHI::ResourceMemoryRequirements GetResourceMemoryRequirements(const RHI::ImageDescriptor & descriptor) override; RHI::ResourceMemoryRequirements GetResourceMemoryRequirements(const RHI::BufferDescriptor & descriptor) override; - + void ObjectCollectionNotify(RHI::ObjectCollectorNotifyFunction notifyFunction) override; + private: Device() = default; diff --git a/Gems/Atom/RHI/Null/Code/Source/RHI/Device.cpp b/Gems/Atom/RHI/Null/Code/Source/RHI/Device.cpp index 7b94efb69f..08a2c4f411 100644 --- a/Gems/Atom/RHI/Null/Code/Source/RHI/Device.cpp +++ b/Gems/Atom/RHI/Null/Code/Source/RHI/Device.cpp @@ -20,5 +20,10 @@ namespace AZ { formatsCapabilities.fill(static_cast(~0)); } + + void Device::ObjectCollectionNotify(RHI::ObjectCollectorNotifyFunction notifyFunction) + { + notifyFunction(); + } } } diff --git a/Gems/Atom/RHI/Null/Code/Source/RHI/Device.h b/Gems/Atom/RHI/Null/Code/Source/RHI/Device.h index 3aa045212b..cd44135e62 100644 --- a/Gems/Atom/RHI/Null/Code/Source/RHI/Device.h +++ b/Gems/Atom/RHI/Null/Code/Source/RHI/Device.h @@ -42,6 +42,7 @@ namespace AZ void PreShutdown() override {} RHI::ResourceMemoryRequirements GetResourceMemoryRequirements([[maybe_unused]] const RHI::ImageDescriptor& descriptor) override { return RHI::ResourceMemoryRequirements();} RHI::ResourceMemoryRequirements GetResourceMemoryRequirements([[maybe_unused]] const RHI::BufferDescriptor& descriptor) override { return RHI::ResourceMemoryRequirements();} + void ObjectCollectionNotify(RHI::ObjectCollectorNotifyFunction notifyFunction) override; ////////////////////////////////////////////////////////////////////////// }; } diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Device.cpp b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Device.cpp index 6d3080dce8..05ff8bb2a6 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Device.cpp +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Device.cpp @@ -652,6 +652,11 @@ namespace AZ return RHI::ResourceMemoryRequirements{ vkRequirements.alignment, vkRequirements.size }; } + void Device::ObjectCollectionNotify(RHI::ObjectCollectorNotifyFunction notifyFunction) + { + m_releaseQueue.Notify(notifyFunction); + } + void Device::InitFeaturesAndLimits(const PhysicalDevice& physicalDevice) { m_features.m_tessellationShader = (m_enabledDeviceFeatures.tessellationShader == VK_TRUE); diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Device.h b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Device.h index d5f055f4cd..28e56d1fa9 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Device.h +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Device.h @@ -134,6 +134,7 @@ namespace AZ void PreShutdown() override; RHI::ResourceMemoryRequirements GetResourceMemoryRequirements(const RHI::ImageDescriptor& descriptor) override; RHI::ResourceMemoryRequirements GetResourceMemoryRequirements(const RHI::BufferDescriptor& descriptor) override; + void ObjectCollectionNotify(RHI::ObjectCollectorNotifyFunction notifyFunction) override; ////////////////////////////////////////////////////////////////////////// void InitFeaturesAndLimits(const PhysicalDevice& physicalDevice); diff --git a/Gems/Atom/RPI/Code/Tests/Common/RHI/Stubs.h b/Gems/Atom/RPI/Code/Tests/Common/RHI/Stubs.h index 1de06802b1..be362c60d6 100644 --- a/Gems/Atom/RPI/Code/Tests/Common/RHI/Stubs.h +++ b/Gems/Atom/RPI/Code/Tests/Common/RHI/Stubs.h @@ -70,6 +70,7 @@ namespace UnitTest void PreShutdown() override {} AZ::RHI::ResourceMemoryRequirements GetResourceMemoryRequirements([[maybe_unused]] const AZ::RHI::ImageDescriptor& descriptor) { return AZ::RHI::ResourceMemoryRequirements{}; }; AZ::RHI::ResourceMemoryRequirements GetResourceMemoryRequirements([[maybe_unused]] const AZ::RHI::BufferDescriptor& descriptor) { return AZ::RHI::ResourceMemoryRequirements{}; }; + void ObjectCollectionNotify(AZ::RHI::ObjectCollectorNotifyFunction notifyFunction) override {} }; class ImageView From 46777b537e350ce4b115facebcf25533f81a0da4 Mon Sep 17 00:00:00 2001 From: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> Date: Mon, 26 Jul 2021 18:01:14 -0400 Subject: [PATCH 025/803] Brought over LY legacy imgui code Signed-off-by: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> --- .../Debug/MultiplayerDebugByteReporter.cpp | 222 ++++++++++ .../Debug/MultiplayerDebugByteReporter.h | 96 +++++ .../MultiplayerDebugPerEntityReporter.cpp | 385 ++++++++++++++++++ .../Debug/MultiplayerDebugPerEntityReporter.h | 90 ++++ .../Debug/MultiplayerDebugSystemComponent.cpp | 11 + .../Debug/MultiplayerDebugSystemComponent.h | 4 + .../Code/multiplayer_debug_files.cmake | 4 + 7 files changed, 812 insertions(+) create mode 100644 Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.cpp create mode 100644 Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.h create mode 100644 Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.cpp create mode 100644 Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.h diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.cpp b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.cpp new file mode 100644 index 0000000000..382bc70d9b --- /dev/null +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.cpp @@ -0,0 +1,222 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +#include "MultiplayerDebugByteReporter.h" + +#include +#include +#include + +namespace MultiplayerDiagnostics +{ + void MultiplayerDebugByteReporter::ReportBytes(size_t byteSize) + { + m_count++; + m_totalBytes += byteSize; + m_totalBytesThisSecond += byteSize; + m_minBytes = AZStd::min(m_minBytes, byteSize); + m_maxBytes = AZStd::max(m_maxBytes, byteSize); + } + + void MultiplayerDebugByteReporter::AggregateBytes(size_t byteSize) + { + m_aggregateBytes += byteSize; + } + + void MultiplayerDebugByteReporter::ReportAggregateBytes() + { + ReportBytes(m_aggregateBytes); + m_aggregateBytes = 0; + } + + float MultiplayerDebugByteReporter::GetAverageBytes() const + { + if (m_count == 0) + { + AZ_Warning("MultiplayerDebugByteReporter", m_totalBytes == 0, "Attempted to average bytes with a zero count."); + return 0.0f; + } + + return (1.0f * m_totalBytes) / m_count; + } + + size_t MultiplayerDebugByteReporter::GetMaxBytes() const + { + return m_maxBytes; + } + + size_t MultiplayerDebugByteReporter::GetMinBytes() const + { + return m_minBytes; + } + + size_t MultiplayerDebugByteReporter::GetTotalBytes() const + { + return m_totalBytes; + } + + float MultiplayerDebugByteReporter::GetKbitsPerSecond() + { + auto now = AZStd::chrono::monotonic_clock::now(); + + // Check the amount of time elapsed and update totals if necessary. + // Time here is measured in whole seconds from the epoch, providing synchronization in + // reporting intervals across all byte reporters. + AZStd::chrono::seconds nowSeconds = AZStd::chrono::duration_cast(now.time_since_epoch()); + AZStd::chrono::seconds secondsSinceLastUpdate = nowSeconds - + AZStd::chrono::duration_cast(m_lastUpdateTime.time_since_epoch()); + if (secondsSinceLastUpdate.count()) + { + // normalize over elapsed milliseconds + const int k_millisecondsPerSecond = 1000; + auto msSinceLastUpdate = AZStd::chrono::duration_cast(now - m_lastUpdateTime); + m_totalBytesLastSecond = k_millisecondsPerSecond * (1.f * m_totalBytesThisSecond / msSinceLastUpdate.count()); + m_totalBytesThisSecond = 0; + m_lastUpdateTime = now; + } + + const float k_bitsPerByte = 8.0f; + const int k_bitsPerKilobit = 1024; + return k_bitsPerByte * m_totalBytesLastSecond / k_bitsPerKilobit; + } + + void MultiplayerDebugByteReporter::Combine(const MultiplayerDebugByteReporter& other) + { + m_count += other.m_count; + m_totalBytes += other.m_totalBytes; + m_totalBytesThisSecond += other.m_totalBytesThisSecond; + m_minBytes = AZStd::GetMin(m_minBytes, other.m_minBytes); + m_maxBytes = AZStd::GetMax(m_maxBytes, other.m_maxBytes); + } + + void MultiplayerDebugByteReporter::Reset() + { + m_count = 0; + m_totalBytes = 0; + m_totalBytesThisSecond = 0; + m_totalBytesLastSecond = 0; + m_minBytes = std::numeric_limits::max(); + m_maxBytes = 0; + m_aggregateBytes = 0; + } + + void ComponentReporter::ReportField(const char* fieldName, size_t byteSize) + { + MultiplayerDebugByteReporter::AggregateBytes(byteSize); + m_fieldReports[fieldName].ReportBytes(byteSize); + } + + void ComponentReporter::ReportFragmentEnd() + { + MultiplayerDebugByteReporter::ReportAggregateBytes(); + m_componentDirtyBytes.ReportAggregateBytes(); + } + + AZStd::vector ComponentReporter::GetFieldReports() + { + AZStd::vector copy; + for (auto field = m_fieldReports.begin(); field != m_fieldReports.end(); ++field) + { + copy.emplace_back(field->first, &field->second); + } + + auto sortByFrequency = [](const Report& a, const Report& b) + { + return a.second->GetTotalCount() > b.second->GetTotalCount(); + }; + + AZStd::sort(copy.begin(), copy.end(), sortByFrequency); + + return copy; + } + + void ComponentReporter::Combine(const ComponentReporter& other) + { + MultiplayerDebugByteReporter::Combine(other); + + for (const auto& fieldIter : other.m_fieldReports) + { + m_fieldReports[fieldIter.first].Combine(fieldIter.second); + } + + m_componentDirtyBytes.Combine(other.m_componentDirtyBytes); + } + + void EntityReporter::ReportField(AZ::u32 index, const char* componentName, + const char* fieldName, size_t byteSize) + { + if (m_currentComponentReport == nullptr) + { + std::stringstream component; + component << "[" << std::setw(2) << std::setfill('0') << static_cast(index) << "]" << " " << componentName; + m_currentComponentReport = &m_componentReports[component.str().c_str()]; + } + + m_currentComponentReport->ReportField(fieldName, byteSize); + MultiplayerDebugByteReporter::AggregateBytes(byteSize); + } + + void EntityReporter::ReportDirtyBits(AZ::u32 index, const char* componentName, size_t byteSize) + { + const char* const prefix = "MB::"; + if (strncmp(prefix, componentName, 4) == 0) + { + componentName += strlen(prefix); + } + + if (m_currentComponentReport == nullptr) + { + std::stringstream component; + component << "[" << std::setw(2) << std::setfill('0') << static_cast(index) << "]" << " " << componentName; + m_currentComponentReport = &m_componentReports[component.str().c_str()]; + } + + m_currentComponentReport->ReportDirtyBits(byteSize); + m_gdeDirtyBytes.AggregateBytes(byteSize); + } + + void EntityReporter::ReportFragmentEnd() + { + if (m_currentComponentReport) + { + m_currentComponentReport->ReportFragmentEnd(); + m_currentComponentReport = nullptr; + } + + m_gdeDirtyBytes.ReportAggregateBytes(); + MultiplayerDebugByteReporter::ReportAggregateBytes(); + } + + void EntityReporter::Combine(const EntityReporter& other) + { + MultiplayerDebugByteReporter::Combine(other); + + for (const auto& componentIter : other.m_componentReports) + { + m_componentReports[componentIter.first].Combine(componentIter.second); + } + + m_gdeDirtyBytes.Combine(other.m_gdeDirtyBytes); + } + + void EntityReporter::Reset() + { + MultiplayerDebugByteReporter::Reset(); + + m_componentReports.clear(); + m_gdeDirtyBytes.Reset(); + } + + AZStd::map& EntityReporter::GetComponentReports() + { + return m_componentReports; + } +} diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.h b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.h new file mode 100644 index 0000000000..7e6a04569d --- /dev/null +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.h @@ -0,0 +1,96 @@ +/* +* 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 +#include +#include +#include + +namespace MultiplayerDiagnostics +{ + class MultiplayerDebugByteReporter + { + public: + MultiplayerDebugByteReporter() { MultiplayerDebugByteReporter::Reset(); } + virtual ~MultiplayerDebugByteReporter() = default; + + void ReportBytes(size_t byteSize); + void AggregateBytes(size_t byteSize); + void ReportAggregateBytes(); + + float GetAverageBytes() const; + size_t GetMaxBytes() const; + size_t GetMinBytes() const; + size_t GetTotalBytes() const; + float GetKbitsPerSecond(); + + void Combine(const MultiplayerDebugByteReporter& other); + virtual void Reset(); + + size_t GetTotalCount() const { return m_count; } + + private: + size_t m_count; + size_t m_totalBytes; + size_t m_totalBytesThisSecond; + float m_totalBytesLastSecond; + size_t m_minBytes; + size_t m_maxBytes; + size_t m_aggregateBytes; + + AZStd::chrono::monotonic_clock::time_point m_lastUpdateTime; + }; + + class ComponentReporter : public MultiplayerDebugByteReporter + { + public: + ComponentReporter() = default; + + void ReportField(const char* fieldName, size_t byteSize); + void ReportDirtyBits(size_t byteSize) { m_componentDirtyBytes.AggregateBytes(byteSize); } + void ReportFragmentEnd(); + + using Report = AZStd::pair; + AZStd::vector GetFieldReports(); + AZStd::size_t GetTotalDirtyBits() const { return m_componentDirtyBytes.GetTotalBytes(); } + float GetAvgDirtyBits() const { return m_componentDirtyBytes.GetAverageBytes(); } + + void Combine(const ComponentReporter& other); + + private: + AZStd::map m_fieldReports; + MultiplayerDebugByteReporter m_componentDirtyBytes; + }; + + class EntityReporter : public MultiplayerDebugByteReporter + { + public: + EntityReporter() = default; + + void ReportField(AZ::u32 index, const char* componentName, const char* fieldName, size_t byteSize); + void ReportDirtyBits(AZ::u32 index, const char* componentName, size_t byteSize); + void ReportFragmentEnd(); + + void Combine(const EntityReporter& other); + void Reset() override; + + AZStd::map& GetComponentReports(); + AZStd::size_t GetTotalDirtyBits() const { return m_gdeDirtyBytes.GetTotalBytes(); } + float GetAvgDirtyBits() const { return m_gdeDirtyBytes.GetAverageBytes(); } + + private: + ComponentReporter* m_currentComponentReport = nullptr; + AZStd::map m_componentReports; + MultiplayerDebugByteReporter m_gdeDirtyBytes; + }; +} diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.cpp b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.cpp new file mode 100644 index 0000000000..e60b800372 --- /dev/null +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.cpp @@ -0,0 +1,385 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +#include "MultiplayerDebugPerEntityReporter.h" +#include +#include +#include + +#if defined(IMGUI_ENABLED) +#include +#endif + +namespace MultiplayerDiagnostics +{ +#if defined(IMGUI_ENABLED) + static const ImVec4 k_ImGuiTomato = ImVec4(1.0f, 0.4f, 0.3f, 1.0f); + static const ImVec4 k_ImGuiKhaki = ImVec4(0.9f, 0.8f, 0.5f, 1.0f); + static const ImVec4 k_ImGuiCyan = ImVec4(0.5f, 1.0f, 1.0f, 1.0f); + static const ImVec4 k_ImGuiDusk = ImVec4(0.7f, 0.7f, 1.0f, 1.0f); + static const ImVec4 k_ImGuiWhite = ImVec4(1.0f, 1.0f, 1.0f, 1.0f); + + // -------------------------------------------------------------------------------------------- + template + bool ReplicatedStateTreeNode(const AZStd::string& name, Reporter& report, const ImVec4& color, int depth = 0) + { + const int defaultPadAmount = 55; + const int depthReduction = 3; + ImGui::PushStyleColor(ImGuiCol_Text, color); + + const bool expanded = ImGui::TreeNode(name.c_str(), + "%-*s %7.2f kbps %7.2f B Avg. %4zu B Max %10zu B Payload", + defaultPadAmount - depthReduction * depth, + name.c_str(), + report.GetKbitsPerSecond(), + report.GetAverageBytes(), + report.GetMaxBytes(), + report.GetTotalBytes()); + ImGui::PopStyleColor(); + return expanded; + } + + // -------------------------------------------------------------------------------------------- + void DisplayReplicatedStateReport(AZStd::map& componentReports, float kbpsWarn, float maxWarn) + { + for (auto& componentPair : componentReports) + { + ImGui::Separator(); + ComponentReporter& componentReport = componentPair.second; + + if (ReplicatedStateTreeNode(componentPair.first, componentReport, k_ImGuiCyan, 1)) + { + ImGui::Separator(); + ImGui::Columns(6, "replicated_field_columns"); + ImGui::NextColumn(); + ImGui::Text("kbps"); + ImGui::NextColumn(); + ImGui::Text("Avg. Bytes"); + ImGui::NextColumn(); + ImGui::Text("Min Bytes"); + ImGui::NextColumn(); + ImGui::Text("Max Bytes"); + ImGui::NextColumn(); + ImGui::Text("Total Bytes"); + ImGui::NextColumn(); + + auto fieldReports = componentReport.GetFieldReports(); + for (auto& fieldPair : fieldReports) + { + MultiplayerDebugByteReporter& fieldReport = *fieldPair.second; + const float kbitsLastSecond = fieldReport.GetKbitsPerSecond(); + + const ImVec4* textColor = &k_ImGuiWhite; + if (fieldReport.GetMaxBytes() > maxWarn) + { + textColor = &k_ImGuiKhaki; + } + + if (kbitsLastSecond > kbpsWarn) + { + textColor = &k_ImGuiTomato; + } + + ImGui::PushStyleColor(ImGuiCol_Text, *textColor); + + ImGui::Text("%s", fieldPair.first.c_str()); + ImGui::NextColumn(); + ImGui::Text("%.2f", kbitsLastSecond); + ImGui::NextColumn(); + ImGui::Text("%.2f", fieldReport.GetAverageBytes()); + ImGui::NextColumn(); + ImGui::Text("%zu", fieldReport.GetMinBytes()); + ImGui::NextColumn(); + ImGui::Text("%zu", fieldReport.GetMaxBytes()); + ImGui::NextColumn(); + ImGui::Text("%zu", fieldReport.GetTotalBytes()); + ImGui::NextColumn(); + + ImGui::PopStyleColor(); + } + + ImGui::Columns(1); + ImGui::TreePop(); + } + } + } +#endif + + MultiplayerDebugPerEntityReporter::MultiplayerDebugPerEntityReporter () + { + GridMate::Debug::CarrierDrillerBus::Handler::BusConnect(); + } + + // -------------------------------------------------------------------------------------------- + MultiplayerDebugPerEntityReporter::~MultiplayerDebugPerEntityReporter() + { + GridMate::Debug::ReplicaDrillerBus::Handler::BusDisconnect(); + GridMate::Debug::CarrierDrillerBus::Handler::BusDisconnect(); + } + + void MultiplayerDebugPerEntityReporter::OnReceiveReplicaBegin(GridMate::Replica*, const void*, size_t) + { + m_currentReceivingEntityReport.Reset(); + } + + void MultiplayerDebugPerEntityReporter::OnReceiveReplicaEnd(GridMate::Replica* replica) + { + m_receivingEntityReports[replica->GetDebugName()].Combine(m_currentReceivingEntityReport); + } + + void MultiplayerDebugPerEntityReporter::OnReceiveReplicaChunkEnd(GridMate::ReplicaChunkBase* chunk, AZ::u32 chunkIndex) + { + AZ_UNUSED(chunk); + AZ_UNUSED(chunkIndex); + m_currentReceivingEntityReport.ReportFragmentEnd(); + } + + void MultiplayerDebugPerEntityReporter::OnReceiveDataSet(GridMate::ReplicaChunkBase* chunk, AZ::u32 chunkIndex, + GridMate::DataSetBase* dataSet, GridMate::PeerId, GridMate::PeerId, const void*, size_t len) + { + m_currentReceivingEntityReport.ReportField(chunkIndex, chunk->GetDescriptor()->GetChunkName(), chunk->GetDescriptor()->GetDataSetName(chunk, dataSet), len); + } + + void MultiplayerDebugPerEntityReporter::OnReceiveRpc (GridMate::ReplicaChunkBase* chunk, + AZ::u32 chunkIndex, + GridMate::Internal::RpcRequest* rpc, + GridMate::PeerId from, + GridMate::PeerId to, + const void* data, + size_t len) + { + AZ_UNUSED( from ); + AZ_UNUSED( to ); + AZ_UNUSED( data ); + + m_currentReceivingEntityReport.ReportField(chunkIndex, chunk->GetDescriptor()->GetChunkName(), chunk->GetDescriptor()->GetRpcName(chunk, rpc->m_rpc), len); + } + + void MultiplayerDebugPerEntityReporter::OnSendReplicaBegin (GridMate::Replica*) + { + m_currentSendingEntityReport.Reset(); + } + + void MultiplayerDebugPerEntityReporter::OnSendReplicaEnd (GridMate::Replica* replica, const void*, size_t) + { + m_sendingEntityReports[replica->GetDebugName()].Combine(m_currentSendingEntityReport); + } + + void MultiplayerDebugPerEntityReporter::OnSendReplicaChunkEnd (GridMate::ReplicaChunkBase* chunk, + AZ::u32 chunkIndex, + const void*, + size_t) + { + AZ_UNUSED(chunk); + AZ_UNUSED(chunkIndex); + m_currentSendingEntityReport.ReportFragmentEnd(); + } + + void MultiplayerDebugPerEntityReporter::OnSendDataSet (GridMate::ReplicaChunkBase* chunk, + AZ::u32 chunkIndex, + GridMate::DataSetBase* dataSet, + GridMate::PeerId, + GridMate::PeerId, + const void*, + size_t len) + { + m_currentSendingEntityReport.ReportField(chunkIndex, chunk->GetDescriptor()->GetChunkName(), chunk->GetDescriptor()->GetDataSetName(chunk, dataSet), len); + } + + void MultiplayerDebugPerEntityReporter::OnSendRpc (GridMate::ReplicaChunkBase* chunk, + AZ::u32 chunkIndex, + GridMate::Internal::RpcRequest* rpc, + GridMate::PeerId, + GridMate::PeerId, + const void*, + size_t len) + { + m_currentSendingEntityReport.ReportField(chunkIndex, chunk->GetDescriptor()->GetChunkName(), chunk->GetDescriptor()->GetRpcName(chunk, rpc->m_rpc), len); + } + + void MultiplayerDebugPerEntityReporter::OnIncomingConnection (GridMate::Carrier*, GridMate::ConnectionID) + { + } + + void MultiplayerDebugPerEntityReporter::OnFailedToConnect (GridMate::Carrier*, + GridMate::ConnectionID, + GridMate::CarrierDisconnectReason) + { + m_lastSecondStats.clear(); + } + + void MultiplayerDebugPerEntityReporter::OnConnectionEstablished (GridMate::Carrier*, GridMate::ConnectionID) + { + } + + void MultiplayerDebugPerEntityReporter::OnDisconnect (GridMate::Carrier*, + GridMate::ConnectionID, + GridMate::CarrierDisconnectReason) + { + /* + * CarrierDrillerBus doesn't provide enough information to correctly keep track of network traffic for all peers. + * This is a work around until that is fixed to at least not over report the bandwidth amount. + */ + m_lastSecondStats.clear(); + } + + void MultiplayerDebugPerEntityReporter::OnDriverError (GridMate::Carrier*, + GridMate::ConnectionID, + const GridMate::DriverError&) + { + m_lastSecondStats.clear(); + } + + void MultiplayerDebugPerEntityReporter::OnSecurityError (GridMate::Carrier*, + GridMate::ConnectionID, + const GridMate::SecurityError&) + { + m_lastSecondStats.clear(); + } + + void MultiplayerDebugPerEntityReporter::OnUpdateStatistics (const GridMate::string& address, + const GridMate::TrafficControl::Statistics&, + const GridMate::TrafficControl::Statistics&, + const GridMate::TrafficControl::Statistics& effectiveLastSecond, + const GridMate::TrafficControl::Statistics&) + { + m_lastSecondStats[address] = effectiveLastSecond; + } + + void MultiplayerDebugPerEntityReporter::OnConnectionStateChanged (GridMate::Carrier*, + GridMate::ConnectionID, + GridMate::Carrier::ConnectionStates) + { + m_lastSecondStats.clear(); + } + + void MultiplayerDebugPerEntityReporter::UpdateTrafficStatistics() + { +#if defined(IMGUI_ENABLED) + AZ::u32 dataReceived = 0, dataSent = 0; + + for (auto& perConnection : m_lastSecondStats) + { + dataReceived += perConnection.second.m_dataReceived; + dataSent += perConnection.second.m_dataSend; + } + + if (dataReceived !=0 || dataSent != 0) + { + ImGui::Text("Total bandwidth: Sent %u kbps Received %u kbps.", dataSent * 8 / 1000, dataReceived * 8 / 1000); + } + else + { + ImGui::Text("Total bandwidth: Sent -- kbps Received -- kbps."); + } +#endif + } + + // -------------------------------------------------------------------------------------------- + void MultiplayerDebugPerEntityReporter::OnImGuiUpdate() + { +#if defined(IMGUI_ENABLED) + if (ImGui::BeginMainMenuBar()) + { + if (ImGui::BeginMenu("GridMate")) + { + if (m_showServerReportWindow) + { + if (ImGui::MenuItem("Hide Multiplayer Analytics Window")) + { + m_showServerReportWindow = false; + } + } + else if (ImGui::MenuItem("Show Multiplayer Analytics Window")) + { + m_showServerReportWindow = true; + } + + ImGui::End(); + } + + ImGui::EndMainMenuBar(); + } + + if (m_showServerReportWindow) + { + if (ImGui::Begin("Multiplayer Analytics", &m_showServerReportWindow)) + { + // General carrier stats + UpdateTrafficStatistics(); + + if (ImGui::Checkbox("Analyze network traffic", &m_isTrackingMessages)) + { + if (m_isTrackingMessages) + { + GridMate::Debug::ReplicaDrillerBus::Handler::BusConnect(); + } + else + { + GridMate::Debug::ReplicaDrillerBus::Handler::BusDisconnect(); + + m_currentReceivingEntityReport.Reset(); + m_receivingEntityReports.clear(); + + m_currentSendingEntityReport.Reset(); + m_sendingEntityReports.clear(); + } + } + + if (m_isTrackingMessages) + { + ImGui::Separator(); + + static ImGuiTextFilter filter; + filter.Draw(); + + if (ImGui::CollapsingHeader("Received replicas per type")) + { + for (auto& entityPair : m_receivingEntityReports) + { + if (!filter.PassFilter(entityPair.first.c_str())) + { + continue; + } + + ImGui::Separator(); + if (ReplicatedStateTreeNode(entityPair.first, entityPair.second, k_ImGuiDusk)) + { + DisplayReplicatedStateReport(entityPair.second.GetComponentReports(), m_replicatedStateKbpsWarn, m_replicatedStateMaxSizeWarn); + ImGui::TreePop(); + } + } + } + + if (ImGui::CollapsingHeader("Sent replicas per type")) + { + for (auto& entityPair : m_sendingEntityReports) + { + if (!filter.PassFilter(entityPair.first.c_str())) + { + continue; + } + + ImGui::Separator(); + if (ReplicatedStateTreeNode(entityPair.first, entityPair.second, k_ImGuiDusk)) + { + DisplayReplicatedStateReport(entityPair.second.GetComponentReports(), m_replicatedStateKbpsWarn, m_replicatedStateMaxSizeWarn); + ImGui::TreePop(); + } + } + } + } + } + ImGui::End(); + } +#endif + } +} diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.h b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.h new file mode 100644 index 0000000000..96cfadb14d --- /dev/null +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.h @@ -0,0 +1,90 @@ +/* +* 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 +#include "MultiplayerDebugByteReporter.h" +#include + +namespace MultiplayerDiagnostics +{ + /** + * \brief GridMate network live analysis tool via ImGui. + */ + class MultiplayerDebugPerEntityReporter + : public GridMate::Debug::ReplicaDrillerBus::Handler + , public GridMate::Debug::CarrierDrillerBus::Handler + { + public: + MultiplayerDebugPerEntityReporter(); + virtual ~MultiplayerDebugPerEntityReporter(); + + // main update loop + void OnImGuiUpdate(); + + // ReplicaDrillerBus - receive + + void OnReceiveReplicaBegin(GridMate::Replica* replica, const void* data, size_t len) override; + void OnReceiveReplicaEnd(GridMate::Replica* replica) override; + void OnReceiveReplicaChunkEnd(GridMate::ReplicaChunkBase* chunk, AZ::u32 chunkIndex) override; + void OnReceiveDataSet(GridMate::ReplicaChunkBase* chunk, AZ::u32 chunkIndex, GridMate::DataSetBase* dataSet, GridMate::PeerId from, GridMate::PeerId to, const void* data, size_t len) override; + void OnReceiveRpc(GridMate::ReplicaChunkBase* chunk, AZ::u32 chunkIndex, GridMate::Internal::RpcRequest* rpc, GridMate::PeerId from, GridMate::PeerId to, const void* data, size_t len) override; + + // ReplicaDrillerBus - sending + + void OnSendReplicaBegin(GridMate::Replica* replica) override; + void OnSendReplicaEnd(GridMate::Replica* replica, const void* data, size_t len) override; + void OnSendReplicaChunkEnd(GridMate::ReplicaChunkBase* chunk, AZ::u32 chunkIndex, const void* data, size_t len) override; + void OnSendDataSet(GridMate::ReplicaChunkBase* chunk, AZ::u32 chunkIndex, GridMate::DataSetBase* dataSet, GridMate::PeerId from, GridMate::PeerId to, const void* data, size_t len) override; + void OnSendRpc(GridMate::ReplicaChunkBase* chunk, AZ::u32 chunkIndex, GridMate::Internal::RpcRequest* rpc, GridMate::PeerId from, GridMate::PeerId to, const void* data, size_t len) override; + + // CarrierDrillerBus + void OnIncomingConnection (GridMate::Carrier* carrier, GridMate::ConnectionID id) override; + void OnFailedToConnect (GridMate::Carrier* carrier, + GridMate::ConnectionID id, + GridMate::CarrierDisconnectReason reason) override; + void OnConnectionEstablished (GridMate::Carrier* carrier, GridMate::ConnectionID id) override; + void OnDisconnect (GridMate::Carrier* carrier, + GridMate::ConnectionID id, + GridMate::CarrierDisconnectReason reason) override; + void OnDriverError (GridMate::Carrier* carrier, + GridMate::ConnectionID id, + const GridMate::DriverError& error) override; + void OnSecurityError (GridMate::Carrier* carrier, + GridMate::ConnectionID id, + const GridMate::SecurityError& error) override; + void OnUpdateStatistics (const GridMate::string& address, + const GridMate::TrafficControl::Statistics& lastSecond, + const GridMate::TrafficControl::Statistics& lifeTime, + const GridMate::TrafficControl::Statistics& effectiveLastSecond, + const GridMate::TrafficControl::Statistics& effectiveLifeTime) override; + void OnConnectionStateChanged (GridMate::Carrier* carrier, + GridMate::ConnectionID id, + GridMate::Carrier::ConnectionStates newState) override; + + private: + + bool m_showServerReportWindow = false; + bool m_isTrackingMessages = false; + + AZStd::map m_sendingEntityReports{}; + EntityReporter m_currentSendingEntityReport; + + AZStd::map m_receivingEntityReports{}; + EntityReporter m_currentReceivingEntityReport; + + float m_replicatedStateKbpsWarn = 10.f; + float m_replicatedStateMaxSizeWarn = 30.f; + + void UpdateTrafficStatistics(); + AZStd::map m_lastSecondStats; + }; +} diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.cpp b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.cpp index 1611a3213d..b97fa053b2 100644 --- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.cpp @@ -53,6 +53,11 @@ namespace Multiplayer #endif } + void MultiplayerDebugSystemComponent::OnImGuiInitialize() + { + m_reporter = AZStd::make_unique(); + } + #ifdef IMGUI_ENABLED void MultiplayerDebugSystemComponent::OnImGuiMainMenuUpdate() { @@ -318,6 +323,12 @@ namespace Multiplayer ImGui::End(); } } + + + if (m_reporter) + { + m_reporter->OnImGuiUpdate(); + } } #endif } diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.h b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.h index 77daaf9b7d..3dbbd06d6f 100644 --- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.h +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.h @@ -9,6 +9,7 @@ #pragma once #include +#include #ifdef IMGUI_ENABLED # include @@ -42,6 +43,7 @@ namespace Multiplayer #ifdef IMGUI_ENABLED //! ImGui::ImGuiUpdateListenerBus overrides //! @{ + void OnImGuiInitialize() override; void OnImGuiMainMenuUpdate() override; void OnImGuiUpdate() override; //! @} @@ -49,5 +51,7 @@ namespace Multiplayer private: bool m_displayNetworkingStats = false; bool m_displayMultiplayerStats = false; + + AZStd::unique_ptr m_reporter; }; } diff --git a/Gems/Multiplayer/Code/multiplayer_debug_files.cmake b/Gems/Multiplayer/Code/multiplayer_debug_files.cmake index 62bd632e7e..37a1c91640 100644 --- a/Gems/Multiplayer/Code/multiplayer_debug_files.cmake +++ b/Gems/Multiplayer/Code/multiplayer_debug_files.cmake @@ -7,6 +7,10 @@ # set(FILES + Source/Debug/MultiplayerDebugByteReporter.cpp + Source/Debug/MultiplayerDebugByteReporter.h + Source/Debug/MultiplayerDebugPerEntityReporter.cpp + Source/Debug/MultiplayerDebugPerEntityReporter.h Source/Debug/MultiplayerDebugModule.cpp Source/Debug/MultiplayerDebugModule.h Source/Debug/MultiplayerDebugSystemComponent.cpp From f29fd86a395812f07c28998758365e9e97b68d7f Mon Sep 17 00:00:00 2001 From: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> Date: Mon, 26 Jul 2021 19:11:28 -0400 Subject: [PATCH 026/803] More converstion in progress Signed-off-by: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> --- .../Components/MultiplayerComponent.h | 21 +- .../Include/Multiplayer/MultiplayerStats.h | 2 + .../Source/Components/NetBindComponent.cpp | 4 + .../Debug/MultiplayerDebugByteReporter.cpp | 17 +- .../MultiplayerDebugPerEntityInterface.h | 26 ++ .../MultiplayerDebugPerEntityReporter.cpp | 292 ++++++++++-------- .../Debug/MultiplayerDebugPerEntityReporter.h | 93 +++--- .../Code/Source/MultiplayerStats.cpp | 27 ++ .../Code/multiplayer_debug_files.cmake | 1 + 9 files changed, 288 insertions(+), 195 deletions(-) create mode 100644 Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityInterface.h diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/MultiplayerComponent.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/MultiplayerComponent.h index 8526b6c70b..48590e5393 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/Components/MultiplayerComponent.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/MultiplayerComponent.h @@ -105,14 +105,15 @@ namespace Multiplayer template inline void SerializeNetworkPropertyHelper ( - AzNetworking::ISerializer& serializer, - bool modifyRecord, - AzNetworking::FixedSizeBitsetView& bitset, - int32_t bitIndex, - TYPE& value, - const char* name, - NetComponentId componentId, - PropertyIndex propertyIndex, + AzNetworking::ISerializer& serializer, + bool modifyRecord, + AzNetworking::FixedSizeBitsetView& bitset, + int32_t bitIndex, + TYPE& value, + const char* name, + AZ::EntityId entityId, + NetComponentId componentId, + PropertyIndex propertyIndex, MultiplayerStats& stats ) { @@ -133,11 +134,11 @@ namespace Multiplayer { if (modifyRecord) { - stats.RecordPropertyReceived(componentId, propertyIndex, updateSize); + stats.RecordPropertyReceived(entityId, componentId, propertyIndex, updateSize); } else { - stats.RecordPropertySent(componentId, propertyIndex, updateSize); + stats.RecordPropertySent(entityId, componentId, propertyIndex, updateSize); } } } diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/MultiplayerStats.h b/Gems/Multiplayer/Code/Include/Multiplayer/MultiplayerStats.h index d279355d7c..133cbb7aeb 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/MultiplayerStats.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/MultiplayerStats.h @@ -50,6 +50,8 @@ namespace Multiplayer AZStd::vector m_componentStats; void ReserveComponentStats(NetComponentId netComponentId, uint16_t propertyCount, uint16_t rpcCount); + void RecordEntitySerializeStart(AZ::EntityId entityId, const char* entityName); + void RecordEntitySerializeStop(AZ::EntityId entityId, const char* entityName); void RecordPropertySent(NetComponentId netComponentId, PropertyIndex propertyId, uint32_t totalBytes); void RecordPropertyReceived(NetComponentId netComponentId, PropertyIndex propertyId, uint32_t totalBytes); void RecordRpcSent(NetComponentId netComponentId, RpcIndex rpcId, uint32_t totalBytes); diff --git a/Gems/Multiplayer/Code/Source/Components/NetBindComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetBindComponent.cpp index e8da34fc7f..74091908e2 100644 --- a/Gems/Multiplayer/Code/Source/Components/NetBindComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/NetBindComponent.cpp @@ -447,12 +447,16 @@ namespace Multiplayer bool NetBindComponent::SerializeStateDeltaMessage(ReplicationRecord& replicationRecord, AzNetworking::ISerializer& serializer) { + GetMultiplayer()->GetStats().RecordEntitySerializeStart(GetEntityId(), GetEntity()->GetName().c_str()); + bool success = true; for (auto iter = m_multiplayerSerializationComponentVector.begin(); iter != m_multiplayerSerializationComponentVector.end(); ++iter) { success &= (*iter)->SerializeStateDeltaMessage(replicationRecord, serializer); } + GetMultiplayer()->GetStats().RecordEntitySerializeStop(GetEntityId(), GetEntity()->GetName().c_str()); + return success; } diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.cpp b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.cpp index 382bc70d9b..fd31298ad8 100644 --- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.cpp +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.cpp @@ -1,14 +1,11 @@ /* -* 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. -* -*/ + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + #include "MultiplayerDebugByteReporter.h" #include diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityInterface.h b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityInterface.h new file mode 100644 index 0000000000..8cd94944b2 --- /dev/null +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityInterface.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#pragma once + +#include +#include + +namespace MultiplayerDiagnostics +{ + class MultilayerIPerEntityStats + { + public: + virtual ~MultilayerIPerEntityStats(); + + virtual void RecordEntitySerializeStart(AZ::EntityId entityId, const char* entityName) = 0; + virtual void RecordEntitySerializeStop(AZ::EntityId entityId, const char* entityName) = 0; + virtual void RecordPropertySent(Multiplayer::NetComponentId netComponentId, Multiplayer::PropertyIndex propertyId, uint32_t totalBytes); + virtual void RecordPropertyReceived(Multiplayer::NetComponentId netComponentId, Multiplayer::PropertyIndex propertyId, uint32_t totalBytes); + }; +} diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.cpp b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.cpp index e60b800372..32ed7d5a59 100644 --- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.cpp +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.cpp @@ -1,18 +1,16 @@ /* -* 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. -* -*/ + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + #include "MultiplayerDebugPerEntityReporter.h" #include #include #include +#include #if defined(IMGUI_ENABLED) #include @@ -115,151 +113,151 @@ namespace MultiplayerDiagnostics MultiplayerDebugPerEntityReporter::MultiplayerDebugPerEntityReporter () { - GridMate::Debug::CarrierDrillerBus::Handler::BusConnect(); + //GridMate::Debug::CarrierDrillerBus::Handler::BusConnect(); } // -------------------------------------------------------------------------------------------- MultiplayerDebugPerEntityReporter::~MultiplayerDebugPerEntityReporter() { - GridMate::Debug::ReplicaDrillerBus::Handler::BusDisconnect(); - GridMate::Debug::CarrierDrillerBus::Handler::BusDisconnect(); + /*GridMate::Debug::ReplicaDrillerBus::Handler::BusDisconnect(); + GridMate::Debug::CarrierDrillerBus::Handler::BusDisconnect();*/ } - void MultiplayerDebugPerEntityReporter::OnReceiveReplicaBegin(GridMate::Replica*, const void*, size_t) - { - m_currentReceivingEntityReport.Reset(); - } + //void MultiplayerDebugPerEntityReporter::OnReceiveReplicaBegin(GridMate::Replica*, const void*, size_t) + //{ + // m_currentReceivingEntityReport.Reset(); + //} - void MultiplayerDebugPerEntityReporter::OnReceiveReplicaEnd(GridMate::Replica* replica) - { - m_receivingEntityReports[replica->GetDebugName()].Combine(m_currentReceivingEntityReport); - } + //void MultiplayerDebugPerEntityReporter::OnReceiveReplicaEnd(GridMate::Replica* replica) + //{ + // m_receivingEntityReports[replica->GetDebugName()].Combine(m_currentReceivingEntityReport); + //} - void MultiplayerDebugPerEntityReporter::OnReceiveReplicaChunkEnd(GridMate::ReplicaChunkBase* chunk, AZ::u32 chunkIndex) - { - AZ_UNUSED(chunk); - AZ_UNUSED(chunkIndex); - m_currentReceivingEntityReport.ReportFragmentEnd(); - } + //void MultiplayerDebugPerEntityReporter::OnReceiveReplicaChunkEnd(GridMate::ReplicaChunkBase* chunk, AZ::u32 chunkIndex) + //{ + // AZ_UNUSED(chunk); + // AZ_UNUSED(chunkIndex); + // m_currentReceivingEntityReport.ReportFragmentEnd(); + //} - void MultiplayerDebugPerEntityReporter::OnReceiveDataSet(GridMate::ReplicaChunkBase* chunk, AZ::u32 chunkIndex, - GridMate::DataSetBase* dataSet, GridMate::PeerId, GridMate::PeerId, const void*, size_t len) - { - m_currentReceivingEntityReport.ReportField(chunkIndex, chunk->GetDescriptor()->GetChunkName(), chunk->GetDescriptor()->GetDataSetName(chunk, dataSet), len); - } + //void MultiplayerDebugPerEntityReporter::OnReceiveDataSet(GridMate::ReplicaChunkBase* chunk, AZ::u32 chunkIndex, + // GridMate::DataSetBase* dataSet, GridMate::PeerId, GridMate::PeerId, const void*, size_t len) + //{ + // m_currentReceivingEntityReport.ReportField(chunkIndex, chunk->GetDescriptor()->GetChunkName(), chunk->GetDescriptor()->GetDataSetName(chunk, dataSet), len); + //} - void MultiplayerDebugPerEntityReporter::OnReceiveRpc (GridMate::ReplicaChunkBase* chunk, - AZ::u32 chunkIndex, - GridMate::Internal::RpcRequest* rpc, - GridMate::PeerId from, - GridMate::PeerId to, - const void* data, - size_t len) - { - AZ_UNUSED( from ); - AZ_UNUSED( to ); - AZ_UNUSED( data ); + //void MultiplayerDebugPerEntityReporter::OnReceiveRpc (GridMate::ReplicaChunkBase* chunk, + // AZ::u32 chunkIndex, + // GridMate::Internal::RpcRequest* rpc, + // GridMate::PeerId from, + // GridMate::PeerId to, + // const void* data, + // size_t len) + //{ + // AZ_UNUSED( from ); + // AZ_UNUSED( to ); + // AZ_UNUSED( data ); - m_currentReceivingEntityReport.ReportField(chunkIndex, chunk->GetDescriptor()->GetChunkName(), chunk->GetDescriptor()->GetRpcName(chunk, rpc->m_rpc), len); - } + // m_currentReceivingEntityReport.ReportField(chunkIndex, chunk->GetDescriptor()->GetChunkName(), chunk->GetDescriptor()->GetRpcName(chunk, rpc->m_rpc), len); + //} - void MultiplayerDebugPerEntityReporter::OnSendReplicaBegin (GridMate::Replica*) - { - m_currentSendingEntityReport.Reset(); - } + //void MultiplayerDebugPerEntityReporter::OnSendReplicaBegin (GridMate::Replica*) + //{ + // m_currentSendingEntityReport.Reset(); + //} - void MultiplayerDebugPerEntityReporter::OnSendReplicaEnd (GridMate::Replica* replica, const void*, size_t) - { - m_sendingEntityReports[replica->GetDebugName()].Combine(m_currentSendingEntityReport); - } + //void MultiplayerDebugPerEntityReporter::OnSendReplicaEnd (GridMate::Replica* replica, const void*, size_t) + //{ + // m_sendingEntityReports[replica->GetDebugName()].Combine(m_currentSendingEntityReport); + //} - void MultiplayerDebugPerEntityReporter::OnSendReplicaChunkEnd (GridMate::ReplicaChunkBase* chunk, - AZ::u32 chunkIndex, - const void*, - size_t) - { - AZ_UNUSED(chunk); - AZ_UNUSED(chunkIndex); - m_currentSendingEntityReport.ReportFragmentEnd(); - } + //void MultiplayerDebugPerEntityReporter::OnSendReplicaChunkEnd (GridMate::ReplicaChunkBase* chunk, + // AZ::u32 chunkIndex, + // const void*, + // size_t) + //{ + // AZ_UNUSED(chunk); + // AZ_UNUSED(chunkIndex); + // m_currentSendingEntityReport.ReportFragmentEnd(); + //} - void MultiplayerDebugPerEntityReporter::OnSendDataSet (GridMate::ReplicaChunkBase* chunk, - AZ::u32 chunkIndex, - GridMate::DataSetBase* dataSet, - GridMate::PeerId, - GridMate::PeerId, - const void*, - size_t len) - { - m_currentSendingEntityReport.ReportField(chunkIndex, chunk->GetDescriptor()->GetChunkName(), chunk->GetDescriptor()->GetDataSetName(chunk, dataSet), len); - } + //void MultiplayerDebugPerEntityReporter::OnSendDataSet (GridMate::ReplicaChunkBase* chunk, + // AZ::u32 chunkIndex, + // GridMate::DataSetBase* dataSet, + // GridMate::PeerId, + // GridMate::PeerId, + // const void*, + // size_t len) + //{ + // m_currentSendingEntityReport.ReportField(chunkIndex, chunk->GetDescriptor()->GetChunkName(), chunk->GetDescriptor()->GetDataSetName(chunk, dataSet), len); + //} - void MultiplayerDebugPerEntityReporter::OnSendRpc (GridMate::ReplicaChunkBase* chunk, - AZ::u32 chunkIndex, - GridMate::Internal::RpcRequest* rpc, - GridMate::PeerId, - GridMate::PeerId, - const void*, - size_t len) - { - m_currentSendingEntityReport.ReportField(chunkIndex, chunk->GetDescriptor()->GetChunkName(), chunk->GetDescriptor()->GetRpcName(chunk, rpc->m_rpc), len); - } + //void MultiplayerDebugPerEntityReporter::OnSendRpc (GridMate::ReplicaChunkBase* chunk, + // AZ::u32 chunkIndex, + // GridMate::Internal::RpcRequest* rpc, + // GridMate::PeerId, + // GridMate::PeerId, + // const void*, + // size_t len) + //{ + // m_currentSendingEntityReport.ReportField(chunkIndex, chunk->GetDescriptor()->GetChunkName(), chunk->GetDescriptor()->GetRpcName(chunk, rpc->m_rpc), len); + //} - void MultiplayerDebugPerEntityReporter::OnIncomingConnection (GridMate::Carrier*, GridMate::ConnectionID) - { - } + //void MultiplayerDebugPerEntityReporter::OnIncomingConnection (GridMate::Carrier*, GridMate::ConnectionID) + //{ + //} - void MultiplayerDebugPerEntityReporter::OnFailedToConnect (GridMate::Carrier*, - GridMate::ConnectionID, - GridMate::CarrierDisconnectReason) - { - m_lastSecondStats.clear(); - } + //void MultiplayerDebugPerEntityReporter::OnFailedToConnect (GridMate::Carrier*, + // GridMate::ConnectionID, + // GridMate::CarrierDisconnectReason) + //{ + // m_lastSecondStats.clear(); + //} - void MultiplayerDebugPerEntityReporter::OnConnectionEstablished (GridMate::Carrier*, GridMate::ConnectionID) - { - } + //void MultiplayerDebugPerEntityReporter::OnConnectionEstablished (GridMate::Carrier*, GridMate::ConnectionID) + //{ + //} - void MultiplayerDebugPerEntityReporter::OnDisconnect (GridMate::Carrier*, - GridMate::ConnectionID, - GridMate::CarrierDisconnectReason) - { - /* - * CarrierDrillerBus doesn't provide enough information to correctly keep track of network traffic for all peers. - * This is a work around until that is fixed to at least not over report the bandwidth amount. - */ - m_lastSecondStats.clear(); - } + //void MultiplayerDebugPerEntityReporter::OnDisconnect (GridMate::Carrier*, + // GridMate::ConnectionID, + // GridMate::CarrierDisconnectReason) + //{ + // /* + // * CarrierDrillerBus doesn't provide enough information to correctly keep track of network traffic for all peers. + // * This is a work around until that is fixed to at least not over report the bandwidth amount. + // */ + // m_lastSecondStats.clear(); + //} - void MultiplayerDebugPerEntityReporter::OnDriverError (GridMate::Carrier*, - GridMate::ConnectionID, - const GridMate::DriverError&) - { - m_lastSecondStats.clear(); - } + //void MultiplayerDebugPerEntityReporter::OnDriverError (GridMate::Carrier*, + // GridMate::ConnectionID, + // const GridMate::DriverError&) + //{ + // m_lastSecondStats.clear(); + //} - void MultiplayerDebugPerEntityReporter::OnSecurityError (GridMate::Carrier*, - GridMate::ConnectionID, - const GridMate::SecurityError&) - { - m_lastSecondStats.clear(); - } + //void MultiplayerDebugPerEntityReporter::OnSecurityError (GridMate::Carrier*, + // GridMate::ConnectionID, + // const GridMate::SecurityError&) + //{ + // m_lastSecondStats.clear(); + //} - void MultiplayerDebugPerEntityReporter::OnUpdateStatistics (const GridMate::string& address, - const GridMate::TrafficControl::Statistics&, - const GridMate::TrafficControl::Statistics&, - const GridMate::TrafficControl::Statistics& effectiveLastSecond, - const GridMate::TrafficControl::Statistics&) - { - m_lastSecondStats[address] = effectiveLastSecond; - } + //void MultiplayerDebugPerEntityReporter::OnUpdateStatistics (const GridMate::string& address, + // const GridMate::TrafficControl::Statistics&, + // const GridMate::TrafficControl::Statistics&, + // const GridMate::TrafficControl::Statistics& effectiveLastSecond, + // const GridMate::TrafficControl::Statistics&) + //{ + // m_lastSecondStats[address] = effectiveLastSecond; + //} - void MultiplayerDebugPerEntityReporter::OnConnectionStateChanged (GridMate::Carrier*, - GridMate::ConnectionID, - GridMate::Carrier::ConnectionStates) - { - m_lastSecondStats.clear(); - } + //void MultiplayerDebugPerEntityReporter::OnConnectionStateChanged (GridMate::Carrier*, + // GridMate::ConnectionID, + // GridMate::Carrier::ConnectionStates) + //{ + // m_lastSecondStats.clear(); + //} void MultiplayerDebugPerEntityReporter::UpdateTrafficStatistics() { @@ -320,11 +318,11 @@ namespace MultiplayerDiagnostics { if (m_isTrackingMessages) { - GridMate::Debug::ReplicaDrillerBus::Handler::BusConnect(); + //GridMate::Debug::ReplicaDrillerBus::Handler::BusConnect(); } else { - GridMate::Debug::ReplicaDrillerBus::Handler::BusDisconnect(); + //GridMate::Debug::ReplicaDrillerBus::Handler::BusDisconnect(); m_currentReceivingEntityReport.Reset(); m_receivingEntityReports.clear(); @@ -382,4 +380,34 @@ namespace MultiplayerDiagnostics } #endif } + + void MultiplayerDebugPerEntityReporter::RecordEntitySerializeStart(AZ::EntityId entityId, const char* entityName) + { + } + + void MultiplayerDebugPerEntityReporter::RecordEntitySerializeStop(AZ::EntityId entityId, const char* entityName) + { + } + + void MultiplayerDebugPerEntityReporter::RecordPropertySent( + AZ::EntityId entityId, + Multiplayer::NetComponentId netComponentId, + Multiplayer::PropertyIndex propertyId, + uint32_t totalBytes) + { + // TODO + } + + void MultiplayerDebugPerEntityReporter::RecordPropertyReceived( + Multiplayer::NetComponentId netComponentId, + Multiplayer::PropertyIndex propertyId, + uint32_t totalBytes) + { + if (Multiplayer::MultiplayerComponentRegistry* componentRegistry = Multiplayer::GetMultiplayerComponentRegistry()) + { + m_currentReceivingEntityReport.ReportField(static_cast(netComponentId), + componentRegistry->GetComponentName(netComponentId), + componentRegistry->GetComponentPropertyName(netComponentId, propertyId), totalBytes); + } + } } diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.h b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.h index 96cfadb14d..c89c889813 100644 --- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.h +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.h @@ -1,18 +1,20 @@ /* -* 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. -* -*/ + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + #pragma once #include #include "MultiplayerDebugByteReporter.h" + +#include +#include +#include #include +#include namespace MultiplayerDiagnostics { @@ -20,55 +22,60 @@ namespace MultiplayerDiagnostics * \brief GridMate network live analysis tool via ImGui. */ class MultiplayerDebugPerEntityReporter - : public GridMate::Debug::ReplicaDrillerBus::Handler - , public GridMate::Debug::CarrierDrillerBus::Handler + : public AZ::Interface::Registrar { public: MultiplayerDebugPerEntityReporter(); - virtual ~MultiplayerDebugPerEntityReporter(); + ~MultiplayerDebugPerEntityReporter() override; // main update loop void OnImGuiUpdate(); - // ReplicaDrillerBus - receive + //! MultilayerIPerEntityStats + // @{ + void RecordEntitySerializeStart(AZ::EntityId entityId, const char* entityName); + void RecordEntitySerializeStop(AZ::EntityId entityId, const char* entityName); + void RecordPropertySent(Multiplayer::NetComponentId netComponentId, Multiplayer::PropertyIndex propertyId, uint32_t totalBytes) override; + void RecordPropertyReceived(Multiplayer::NetComponentId netComponentId, Multiplayer::PropertyIndex propertyId, uint32_t totalBytes) override; + // }@ - void OnReceiveReplicaBegin(GridMate::Replica* replica, const void* data, size_t len) override; - void OnReceiveReplicaEnd(GridMate::Replica* replica) override; + /*void OnReceiveReplicaBegin(AZ::EntityId entityId, const void* data, size_t len) override; + void OnReceiveReplicaEnd(AZ::EntityId entityId) override; void OnReceiveReplicaChunkEnd(GridMate::ReplicaChunkBase* chunk, AZ::u32 chunkIndex) override; void OnReceiveDataSet(GridMate::ReplicaChunkBase* chunk, AZ::u32 chunkIndex, GridMate::DataSetBase* dataSet, GridMate::PeerId from, GridMate::PeerId to, const void* data, size_t len) override; - void OnReceiveRpc(GridMate::ReplicaChunkBase* chunk, AZ::u32 chunkIndex, GridMate::Internal::RpcRequest* rpc, GridMate::PeerId from, GridMate::PeerId to, const void* data, size_t len) override; + void OnReceiveRpc(GridMate::ReplicaChunkBase* chunk, AZ::u32 chunkIndex, GridMate::Internal::RpcRequest* rpc, GridMate::PeerId from, GridMate::PeerId to, const void* data, size_t len) override;*/ // ReplicaDrillerBus - sending - void OnSendReplicaBegin(GridMate::Replica* replica) override; - void OnSendReplicaEnd(GridMate::Replica* replica, const void* data, size_t len) override; + /*void OnSendReplicaBegin(AZ::EntityId entityId) override; + void OnSendReplicaEnd(AZ::EntityId entityId, const void* data, size_t len) override; void OnSendReplicaChunkEnd(GridMate::ReplicaChunkBase* chunk, AZ::u32 chunkIndex, const void* data, size_t len) override; void OnSendDataSet(GridMate::ReplicaChunkBase* chunk, AZ::u32 chunkIndex, GridMate::DataSetBase* dataSet, GridMate::PeerId from, GridMate::PeerId to, const void* data, size_t len) override; - void OnSendRpc(GridMate::ReplicaChunkBase* chunk, AZ::u32 chunkIndex, GridMate::Internal::RpcRequest* rpc, GridMate::PeerId from, GridMate::PeerId to, const void* data, size_t len) override; + void OnSendRpc(GridMate::ReplicaChunkBase* chunk, AZ::u32 chunkIndex, GridMate::Internal::RpcRequest* rpc, GridMate::PeerId from, GridMate::PeerId to, const void* data, size_t len) override;*/ - // CarrierDrillerBus - void OnIncomingConnection (GridMate::Carrier* carrier, GridMate::ConnectionID id) override; - void OnFailedToConnect (GridMate::Carrier* carrier, - GridMate::ConnectionID id, - GridMate::CarrierDisconnectReason reason) override; - void OnConnectionEstablished (GridMate::Carrier* carrier, GridMate::ConnectionID id) override; - void OnDisconnect (GridMate::Carrier* carrier, - GridMate::ConnectionID id, - GridMate::CarrierDisconnectReason reason) override; - void OnDriverError (GridMate::Carrier* carrier, - GridMate::ConnectionID id, - const GridMate::DriverError& error) override; - void OnSecurityError (GridMate::Carrier* carrier, - GridMate::ConnectionID id, - const GridMate::SecurityError& error) override; - void OnUpdateStatistics (const GridMate::string& address, - const GridMate::TrafficControl::Statistics& lastSecond, - const GridMate::TrafficControl::Statistics& lifeTime, - const GridMate::TrafficControl::Statistics& effectiveLastSecond, - const GridMate::TrafficControl::Statistics& effectiveLifeTime) override; - void OnConnectionStateChanged (GridMate::Carrier* carrier, - GridMate::ConnectionID id, - GridMate::Carrier::ConnectionStates newState) override; + //// CarrierDrillerBus + //void OnIncomingConnection (GridMate::Carrier* carrier, GridMate::ConnectionID id) override; + //void OnFailedToConnect (GridMate::Carrier* carrier, + // GridMate::ConnectionID id, + // GridMate::CarrierDisconnectReason reason) override; + //void OnConnectionEstablished (GridMate::Carrier* carrier, GridMate::ConnectionID id) override; + //void OnDisconnect (GridMate::Carrier* carrier, + // GridMate::ConnectionID id, + // GridMate::CarrierDisconnectReason reason) override; + //void OnDriverError (GridMate::Carrier* carrier, + // GridMate::ConnectionID id, + // const GridMate::DriverError& error) override; + //void OnSecurityError (GridMate::Carrier* carrier, + // GridMate::ConnectionID id, + // const GridMate::SecurityError& error) override; + //void OnUpdateStatistics (const GridMate::string& address, + // const GridMate::TrafficControl::Statistics& lastSecond, + // const GridMate::TrafficControl::Statistics& lifeTime, + // const GridMate::TrafficControl::Statistics& effectiveLastSecond, + // const GridMate::TrafficControl::Statistics& effectiveLifeTime) override; + //void OnConnectionStateChanged (GridMate::Carrier* carrier, + // GridMate::ConnectionID id, + // GridMate::Carrier::ConnectionStates newState) override; private: diff --git a/Gems/Multiplayer/Code/Source/MultiplayerStats.cpp b/Gems/Multiplayer/Code/Source/MultiplayerStats.cpp index 6ee9f09cf7..b3236fbf77 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerStats.cpp +++ b/Gems/Multiplayer/Code/Source/MultiplayerStats.cpp @@ -6,6 +6,7 @@ * */ +#include #include namespace Multiplayer @@ -29,8 +30,29 @@ namespace Multiplayer m_componentStats[netComponentIndex].m_rpcsRecv.resize(rpcCount); } + void MultiplayerStats::RecordEntitySerializeStart(AZ::EntityId entityId, const char* entityName) + { + if (auto* perEntityStats = AZ::Interface::Get()) + { + perEntityStats->RecordEntitySerializeStart(entityId, entityName); + } + } + + void MultiplayerStats::RecordEntitySerializeStop(AZ::EntityId entityId, const char* entityName) + { + if (auto* perEntityStats = AZ::Interface::Get()) + { + perEntityStats->RecordEntitySerializeStop(entityId, entityName); + } + } + void MultiplayerStats::RecordPropertySent(NetComponentId netComponentId, PropertyIndex propertyId, uint32_t totalBytes) { + if (auto* perEntityStats = AZ::Interface::Get()) + { + perEntityStats->RecordPropertySent(netComponentId, propertyId, totalBytes); + } + const uint16_t netComponentIndex = aznumeric_cast(netComponentId); const uint16_t propertyIndex = aznumeric_cast(propertyId); m_componentStats[netComponentIndex].m_propertyUpdatesSent[propertyIndex].m_totalCalls++; @@ -41,6 +63,11 @@ namespace Multiplayer void MultiplayerStats::RecordPropertyReceived(NetComponentId netComponentId, PropertyIndex propertyId, uint32_t totalBytes) { + if (auto* perEntityStats = AZ::Interface::Get()) + { + perEntityStats->RecordPropertyReceived(netComponentId, propertyId, totalBytes); + } + const uint16_t netComponentIndex = aznumeric_cast(netComponentId); const uint16_t propertyIndex = aznumeric_cast(propertyId); m_componentStats[netComponentIndex].m_propertyUpdatesRecv[propertyIndex].m_totalCalls++; diff --git a/Gems/Multiplayer/Code/multiplayer_debug_files.cmake b/Gems/Multiplayer/Code/multiplayer_debug_files.cmake index 37a1c91640..d333269a1d 100644 --- a/Gems/Multiplayer/Code/multiplayer_debug_files.cmake +++ b/Gems/Multiplayer/Code/multiplayer_debug_files.cmake @@ -9,6 +9,7 @@ set(FILES Source/Debug/MultiplayerDebugByteReporter.cpp Source/Debug/MultiplayerDebugByteReporter.h + Source/Debug/MultiplayerDebugPerEntityInterface.h Source/Debug/MultiplayerDebugPerEntityReporter.cpp Source/Debug/MultiplayerDebugPerEntityReporter.h Source/Debug/MultiplayerDebugModule.cpp From a2f3066fa36d0cb1e817f6a7517f067854e11ba9 Mon Sep 17 00:00:00 2001 From: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> Date: Mon, 26 Jul 2021 21:59:19 -0400 Subject: [PATCH 027/803] Imgui per entity works Signed-off-by: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> --- Gems/Multiplayer/Code/CMakeLists.txt | 2 +- .../Components/MultiplayerComponent.h | 5 +- .../Include/Multiplayer/MultiplayerStats.h | 5 +- .../Source/Components/NetBindComponent.cpp | 7 +- .../Debug/MultiplayerDebugByteReporter.cpp | 2 + .../Debug/MultiplayerDebugByteReporter.h | 17 +- .../MultiplayerDebugPerEntityInterface.h | 14 +- .../MultiplayerDebugPerEntityReporter.cpp | 337 ++++-------------- .../Debug/MultiplayerDebugPerEntityReporter.h | 57 +-- .../Debug/MultiplayerDebugSystemComponent.cpp | 14 +- .../Debug/MultiplayerDebugSystemComponent.h | 1 + .../Code/Source/MultiplayerStats.cpp | 29 +- .../EntityReplication/EntityReplicator.cpp | 9 +- 13 files changed, 155 insertions(+), 344 deletions(-) diff --git a/Gems/Multiplayer/Code/CMakeLists.txt b/Gems/Multiplayer/Code/CMakeLists.txt index 96527fbfc4..e8b38c8799 100644 --- a/Gems/Multiplayer/Code/CMakeLists.txt +++ b/Gems/Multiplayer/Code/CMakeLists.txt @@ -79,7 +79,7 @@ ly_add_target( # The "Multiplayer" target is used by clients and servers, Debug is used only on clients. ly_create_alias(NAME Multiplayer.Clients NAMESPACE Gem TARGETS Gem::Multiplayer Gem::Multiplayer.Debug) -ly_create_alias(NAME Multiplayer.Servers NAMESPACE Gem TARGETS Gem::Multiplayer) +ly_create_alias(NAME Multiplayer.Servers NAMESPACE Gem TARGETS Gem::Multiplayer Gem::Multiplayer.Debug) if (PAL_TRAIT_BUILD_HOST_TOOLS) ly_add_target( diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/MultiplayerComponent.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/MultiplayerComponent.h index 48590e5393..64ceb6e16f 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/Components/MultiplayerComponent.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/MultiplayerComponent.h @@ -111,7 +111,6 @@ namespace Multiplayer int32_t bitIndex, TYPE& value, const char* name, - AZ::EntityId entityId, NetComponentId componentId, PropertyIndex propertyIndex, MultiplayerStats& stats @@ -134,11 +133,11 @@ namespace Multiplayer { if (modifyRecord) { - stats.RecordPropertyReceived(entityId, componentId, propertyIndex, updateSize); + stats.RecordPropertyReceived(componentId, propertyIndex, updateSize); } else { - stats.RecordPropertySent(entityId, componentId, propertyIndex, updateSize); + stats.RecordPropertySent(componentId, propertyIndex, updateSize); } } } diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/MultiplayerStats.h b/Gems/Multiplayer/Code/Include/Multiplayer/MultiplayerStats.h index 133cbb7aeb..1299fe174d 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/MultiplayerStats.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/MultiplayerStats.h @@ -50,8 +50,9 @@ namespace Multiplayer AZStd::vector m_componentStats; void ReserveComponentStats(NetComponentId netComponentId, uint16_t propertyCount, uint16_t rpcCount); - void RecordEntitySerializeStart(AZ::EntityId entityId, const char* entityName); - void RecordEntitySerializeStop(AZ::EntityId entityId, const char* entityName); + void RecordEntitySerializeStart(AzNetworking::SerializerMode mode, AZ::EntityId entityId, const char* entityName); + void RecordComponentSerializeEnd(AzNetworking::SerializerMode mode, NetComponentId netComponentId); + void RecordEntitySerializeStop(AzNetworking::SerializerMode mode, AZ::EntityId entityId, const char* entityName); void RecordPropertySent(NetComponentId netComponentId, PropertyIndex propertyId, uint32_t totalBytes); void RecordPropertyReceived(NetComponentId netComponentId, PropertyIndex propertyId, uint32_t totalBytes); void RecordRpcSent(NetComponentId netComponentId, RpcIndex rpcId, uint32_t totalBytes); diff --git a/Gems/Multiplayer/Code/Source/Components/NetBindComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetBindComponent.cpp index 74091908e2..cfaeaedeff 100644 --- a/Gems/Multiplayer/Code/Source/Components/NetBindComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/NetBindComponent.cpp @@ -447,15 +447,18 @@ namespace Multiplayer bool NetBindComponent::SerializeStateDeltaMessage(ReplicationRecord& replicationRecord, AzNetworking::ISerializer& serializer) { - GetMultiplayer()->GetStats().RecordEntitySerializeStart(GetEntityId(), GetEntity()->GetName().c_str()); + auto& stats = GetMultiplayer()->GetStats(); + stats.RecordEntitySerializeStart(serializer.GetSerializerMode(), GetEntityId(), GetEntity()->GetName().c_str()); bool success = true; for (auto iter = m_multiplayerSerializationComponentVector.begin(); iter != m_multiplayerSerializationComponentVector.end(); ++iter) { success &= (*iter)->SerializeStateDeltaMessage(replicationRecord, serializer); + + stats.RecordComponentSerializeEnd(serializer.GetSerializerMode(), (*iter)->GetNetComponentId()); } - GetMultiplayer()->GetStats().RecordEntitySerializeStop(GetEntityId(), GetEntity()->GetName().c_str()); + stats.RecordEntitySerializeStop(serializer.GetSerializerMode(), GetEntityId(), GetEntity()->GetName().c_str()); return success; } diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.cpp b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.cpp index fd31298ad8..2c0a8b5db1 100644 --- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.cpp +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.cpp @@ -12,6 +12,8 @@ #include #include +#pragma optimize("", off) + namespace MultiplayerDiagnostics { void MultiplayerDebugByteReporter::ReportBytes(size_t byteSize) diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.h b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.h index 7e6a04569d..8977c2e6ba 100644 --- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.h +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.h @@ -1,14 +1,11 @@ /* -* 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. -* -*/ + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + #pragma once #include diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityInterface.h b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityInterface.h index 8cd94944b2..94bc11dafa 100644 --- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityInterface.h +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityInterface.h @@ -13,14 +13,16 @@ namespace MultiplayerDiagnostics { - class MultilayerIPerEntityStats + class MultiplayerIPerEntityStats { public: - virtual ~MultilayerIPerEntityStats(); + AZ_RTTI(MultiplayerIPerEntityStats, "{91A1E4F0-8AE6-44B2-89DF-DA34134C408A}"); - virtual void RecordEntitySerializeStart(AZ::EntityId entityId, const char* entityName) = 0; - virtual void RecordEntitySerializeStop(AZ::EntityId entityId, const char* entityName) = 0; - virtual void RecordPropertySent(Multiplayer::NetComponentId netComponentId, Multiplayer::PropertyIndex propertyId, uint32_t totalBytes); - virtual void RecordPropertyReceived(Multiplayer::NetComponentId netComponentId, Multiplayer::PropertyIndex propertyId, uint32_t totalBytes); + virtual void RecordEntitySerializeStart(AzNetworking::SerializerMode mode, AZ::EntityId entityId, const char* entityName) = 0; + virtual void RecordComponentSerializeEnd(AzNetworking::SerializerMode mode, Multiplayer::NetComponentId netComponentId) = 0; + virtual void RecordEntitySerializeStop(AzNetworking::SerializerMode mode, AZ::EntityId entityId, const char* entityName) = 0; + virtual void RecordPropertySent(Multiplayer::NetComponentId netComponentId, Multiplayer::PropertyIndex propertyId, uint32_t totalBytes) = 0; + virtual void RecordPropertyReceived(Multiplayer::NetComponentId netComponentId, Multiplayer::PropertyIndex propertyId, uint32_t totalBytes) = 0; + virtual void RecordRpcSent(Multiplayer::NetComponentId netComponentId, Multiplayer::RpcIndex rpcId, uint32_t totalBytes) = 0; }; } diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.cpp b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.cpp index 32ed7d5a59..c839083f63 100644 --- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.cpp +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.cpp @@ -7,23 +7,22 @@ */ #include "MultiplayerDebugPerEntityReporter.h" -#include -#include -#include #include #if defined(IMGUI_ENABLED) #include #endif +#pragma optimize("", off) + namespace MultiplayerDiagnostics { #if defined(IMGUI_ENABLED) static const ImVec4 k_ImGuiTomato = ImVec4(1.0f, 0.4f, 0.3f, 1.0f); - static const ImVec4 k_ImGuiKhaki = ImVec4(0.9f, 0.8f, 0.5f, 1.0f); - static const ImVec4 k_ImGuiCyan = ImVec4(0.5f, 1.0f, 1.0f, 1.0f); - static const ImVec4 k_ImGuiDusk = ImVec4(0.7f, 0.7f, 1.0f, 1.0f); - static const ImVec4 k_ImGuiWhite = ImVec4(1.0f, 1.0f, 1.0f, 1.0f); + static const ImVec4 k_ImGuiKhaki = ImVec4(0.9f, 0.8f, 0.5f, 1.0f); + static const ImVec4 k_ImGuiCyan = ImVec4(0.5f, 1.0f, 1.0f, 1.0f); + static const ImVec4 k_ImGuiDusk = ImVec4(0.7f, 0.7f, 1.0f, 1.0f); + static const ImVec4 k_ImGuiWhite = ImVec4(1.0f, 1.0f, 1.0f, 1.0f); // -------------------------------------------------------------------------------------------- template @@ -111,291 +110,103 @@ namespace MultiplayerDiagnostics } #endif - MultiplayerDebugPerEntityReporter::MultiplayerDebugPerEntityReporter () - { - //GridMate::Debug::CarrierDrillerBus::Handler::BusConnect(); - } - - // -------------------------------------------------------------------------------------------- - MultiplayerDebugPerEntityReporter::~MultiplayerDebugPerEntityReporter() - { - /*GridMate::Debug::ReplicaDrillerBus::Handler::BusDisconnect(); - GridMate::Debug::CarrierDrillerBus::Handler::BusDisconnect();*/ - } - - //void MultiplayerDebugPerEntityReporter::OnReceiveReplicaBegin(GridMate::Replica*, const void*, size_t) - //{ - // m_currentReceivingEntityReport.Reset(); - //} - - //void MultiplayerDebugPerEntityReporter::OnReceiveReplicaEnd(GridMate::Replica* replica) - //{ - // m_receivingEntityReports[replica->GetDebugName()].Combine(m_currentReceivingEntityReport); - //} - - //void MultiplayerDebugPerEntityReporter::OnReceiveReplicaChunkEnd(GridMate::ReplicaChunkBase* chunk, AZ::u32 chunkIndex) - //{ - // AZ_UNUSED(chunk); - // AZ_UNUSED(chunkIndex); - // m_currentReceivingEntityReport.ReportFragmentEnd(); - //} - - //void MultiplayerDebugPerEntityReporter::OnReceiveDataSet(GridMate::ReplicaChunkBase* chunk, AZ::u32 chunkIndex, - // GridMate::DataSetBase* dataSet, GridMate::PeerId, GridMate::PeerId, const void*, size_t len) - //{ - // m_currentReceivingEntityReport.ReportField(chunkIndex, chunk->GetDescriptor()->GetChunkName(), chunk->GetDescriptor()->GetDataSetName(chunk, dataSet), len); - //} - - //void MultiplayerDebugPerEntityReporter::OnReceiveRpc (GridMate::ReplicaChunkBase* chunk, - // AZ::u32 chunkIndex, - // GridMate::Internal::RpcRequest* rpc, - // GridMate::PeerId from, - // GridMate::PeerId to, - // const void* data, - // size_t len) - //{ - // AZ_UNUSED( from ); - // AZ_UNUSED( to ); - // AZ_UNUSED( data ); - - // m_currentReceivingEntityReport.ReportField(chunkIndex, chunk->GetDescriptor()->GetChunkName(), chunk->GetDescriptor()->GetRpcName(chunk, rpc->m_rpc), len); - //} - - //void MultiplayerDebugPerEntityReporter::OnSendReplicaBegin (GridMate::Replica*) - //{ - // m_currentSendingEntityReport.Reset(); - //} - - //void MultiplayerDebugPerEntityReporter::OnSendReplicaEnd (GridMate::Replica* replica, const void*, size_t) - //{ - // m_sendingEntityReports[replica->GetDebugName()].Combine(m_currentSendingEntityReport); - //} - - //void MultiplayerDebugPerEntityReporter::OnSendReplicaChunkEnd (GridMate::ReplicaChunkBase* chunk, - // AZ::u32 chunkIndex, - // const void*, - // size_t) - //{ - // AZ_UNUSED(chunk); - // AZ_UNUSED(chunkIndex); - // m_currentSendingEntityReport.ReportFragmentEnd(); - //} - - //void MultiplayerDebugPerEntityReporter::OnSendDataSet (GridMate::ReplicaChunkBase* chunk, - // AZ::u32 chunkIndex, - // GridMate::DataSetBase* dataSet, - // GridMate::PeerId, - // GridMate::PeerId, - // const void*, - // size_t len) - //{ - // m_currentSendingEntityReport.ReportField(chunkIndex, chunk->GetDescriptor()->GetChunkName(), chunk->GetDescriptor()->GetDataSetName(chunk, dataSet), len); - //} - - //void MultiplayerDebugPerEntityReporter::OnSendRpc (GridMate::ReplicaChunkBase* chunk, - // AZ::u32 chunkIndex, - // GridMate::Internal::RpcRequest* rpc, - // GridMate::PeerId, - // GridMate::PeerId, - // const void*, - // size_t len) - //{ - // m_currentSendingEntityReport.ReportField(chunkIndex, chunk->GetDescriptor()->GetChunkName(), chunk->GetDescriptor()->GetRpcName(chunk, rpc->m_rpc), len); - //} - - //void MultiplayerDebugPerEntityReporter::OnIncomingConnection (GridMate::Carrier*, GridMate::ConnectionID) - //{ - //} - - //void MultiplayerDebugPerEntityReporter::OnFailedToConnect (GridMate::Carrier*, - // GridMate::ConnectionID, - // GridMate::CarrierDisconnectReason) - //{ - // m_lastSecondStats.clear(); - //} - - //void MultiplayerDebugPerEntityReporter::OnConnectionEstablished (GridMate::Carrier*, GridMate::ConnectionID) - //{ - //} - - //void MultiplayerDebugPerEntityReporter::OnDisconnect (GridMate::Carrier*, - // GridMate::ConnectionID, - // GridMate::CarrierDisconnectReason) - //{ - // /* - // * CarrierDrillerBus doesn't provide enough information to correctly keep track of network traffic for all peers. - // * This is a work around until that is fixed to at least not over report the bandwidth amount. - // */ - // m_lastSecondStats.clear(); - //} - - //void MultiplayerDebugPerEntityReporter::OnDriverError (GridMate::Carrier*, - // GridMate::ConnectionID, - // const GridMate::DriverError&) - //{ - // m_lastSecondStats.clear(); - //} - - //void MultiplayerDebugPerEntityReporter::OnSecurityError (GridMate::Carrier*, - // GridMate::ConnectionID, - // const GridMate::SecurityError&) - //{ - // m_lastSecondStats.clear(); - //} - - //void MultiplayerDebugPerEntityReporter::OnUpdateStatistics (const GridMate::string& address, - // const GridMate::TrafficControl::Statistics&, - // const GridMate::TrafficControl::Statistics&, - // const GridMate::TrafficControl::Statistics& effectiveLastSecond, - // const GridMate::TrafficControl::Statistics&) - //{ - // m_lastSecondStats[address] = effectiveLastSecond; - //} - - //void MultiplayerDebugPerEntityReporter::OnConnectionStateChanged (GridMate::Carrier*, - // GridMate::ConnectionID, - // GridMate::Carrier::ConnectionStates) - //{ - // m_lastSecondStats.clear(); - //} - - void MultiplayerDebugPerEntityReporter::UpdateTrafficStatistics() - { -#if defined(IMGUI_ENABLED) - AZ::u32 dataReceived = 0, dataSent = 0; - - for (auto& perConnection : m_lastSecondStats) - { - dataReceived += perConnection.second.m_dataReceived; - dataSent += perConnection.second.m_dataSend; - } - - if (dataReceived !=0 || dataSent != 0) - { - ImGui::Text("Total bandwidth: Sent %u kbps Received %u kbps.", dataSent * 8 / 1000, dataReceived * 8 / 1000); - } - else - { - ImGui::Text("Total bandwidth: Sent -- kbps Received -- kbps."); - } -#endif - } - // -------------------------------------------------------------------------------------------- void MultiplayerDebugPerEntityReporter::OnImGuiUpdate() { #if defined(IMGUI_ENABLED) - if (ImGui::BeginMainMenuBar()) + static ImGuiTextFilter filter; + filter.Draw(); + + if (ImGui::CollapsingHeader("Receiving Entities")) { - if (ImGui::BeginMenu("GridMate")) + for (auto& entityPair : m_receivingEntityReports) { - if (m_showServerReportWindow) + if (!filter.PassFilter(entityPair.first.c_str())) { - if (ImGui::MenuItem("Hide Multiplayer Analytics Window")) - { - m_showServerReportWindow = false; - } - } - else if (ImGui::MenuItem("Show Multiplayer Analytics Window")) - { - m_showServerReportWindow = true; + continue; } - ImGui::End(); + ImGui::Separator(); + if (ReplicatedStateTreeNode(entityPair.first, entityPair.second, k_ImGuiDusk)) + { + DisplayReplicatedStateReport(entityPair.second.GetComponentReports(), m_replicatedStateKbpsWarn, m_replicatedStateMaxSizeWarn); + ImGui::TreePop(); + } } - - ImGui::EndMainMenuBar(); } - if (m_showServerReportWindow) + if (ImGui::CollapsingHeader("Sending Entities")) { - if (ImGui::Begin("Multiplayer Analytics", &m_showServerReportWindow)) + for (auto& entityPair : m_sendingEntityReports) { - // General carrier stats - UpdateTrafficStatistics(); - - if (ImGui::Checkbox("Analyze network traffic", &m_isTrackingMessages)) + if (!filter.PassFilter(entityPair.first.c_str())) { - if (m_isTrackingMessages) - { - //GridMate::Debug::ReplicaDrillerBus::Handler::BusConnect(); - } - else - { - //GridMate::Debug::ReplicaDrillerBus::Handler::BusDisconnect(); - - m_currentReceivingEntityReport.Reset(); - m_receivingEntityReports.clear(); - - m_currentSendingEntityReport.Reset(); - m_sendingEntityReports.clear(); - } + continue; } - if (m_isTrackingMessages) + ImGui::Separator(); + if (ReplicatedStateTreeNode(entityPair.first, entityPair.second, k_ImGuiDusk)) { - ImGui::Separator(); - - static ImGuiTextFilter filter; - filter.Draw(); - - if (ImGui::CollapsingHeader("Received replicas per type")) - { - for (auto& entityPair : m_receivingEntityReports) - { - if (!filter.PassFilter(entityPair.first.c_str())) - { - continue; - } - - ImGui::Separator(); - if (ReplicatedStateTreeNode(entityPair.first, entityPair.second, k_ImGuiDusk)) - { - DisplayReplicatedStateReport(entityPair.second.GetComponentReports(), m_replicatedStateKbpsWarn, m_replicatedStateMaxSizeWarn); - ImGui::TreePop(); - } - } - } - - if (ImGui::CollapsingHeader("Sent replicas per type")) - { - for (auto& entityPair : m_sendingEntityReports) - { - if (!filter.PassFilter(entityPair.first.c_str())) - { - continue; - } - - ImGui::Separator(); - if (ReplicatedStateTreeNode(entityPair.first, entityPair.second, k_ImGuiDusk)) - { - DisplayReplicatedStateReport(entityPair.second.GetComponentReports(), m_replicatedStateKbpsWarn, m_replicatedStateMaxSizeWarn); - ImGui::TreePop(); - } - } - } + DisplayReplicatedStateReport(entityPair.second.GetComponentReports(), m_replicatedStateKbpsWarn, m_replicatedStateMaxSizeWarn); + ImGui::TreePop(); } } - ImGui::End(); } #endif } - void MultiplayerDebugPerEntityReporter::RecordEntitySerializeStart(AZ::EntityId entityId, const char* entityName) + void MultiplayerDebugPerEntityReporter::RecordEntitySerializeStart(AzNetworking::SerializerMode mode, + [[maybe_unused]] AZ::EntityId entityId, [[maybe_unused]] const char* entityName) { + switch (mode) + { + case AzNetworking::SerializerMode::ReadFromObject: + m_currentSendingEntityReport.Reset(); + break; + case AzNetworking::SerializerMode::WriteToObject: + m_currentReceivingEntityReport.Reset(); + break; + } } - void MultiplayerDebugPerEntityReporter::RecordEntitySerializeStop(AZ::EntityId entityId, const char* entityName) + void MultiplayerDebugPerEntityReporter::RecordComponentSerializeEnd(AzNetworking::SerializerMode mode, [[maybe_unused]] Multiplayer::NetComponentId netComponentId) { + switch (mode) + { + case AzNetworking::SerializerMode::ReadFromObject: + m_currentSendingEntityReport.ReportFragmentEnd(); + break; + case AzNetworking::SerializerMode::WriteToObject: + m_currentReceivingEntityReport.ReportFragmentEnd(); + break; + } + } + + void MultiplayerDebugPerEntityReporter::RecordEntitySerializeStop(AzNetworking::SerializerMode mode, + [[maybe_unused]] AZ::EntityId entityId, const char* entityName) + { + switch (mode) + { + case AzNetworking::SerializerMode::ReadFromObject: + m_sendingEntityReports[entityName].Combine(m_currentSendingEntityReport); + break; + case AzNetworking::SerializerMode::WriteToObject: + m_receivingEntityReports[entityName].Combine(m_currentReceivingEntityReport); + break; + } } void MultiplayerDebugPerEntityReporter::RecordPropertySent( - AZ::EntityId entityId, Multiplayer::NetComponentId netComponentId, Multiplayer::PropertyIndex propertyId, uint32_t totalBytes) { - // TODO + if (const Multiplayer::MultiplayerComponentRegistry* componentRegistry = Multiplayer::GetMultiplayerComponentRegistry()) + { + m_currentSendingEntityReport.ReportField(static_cast(netComponentId), + componentRegistry->GetComponentName(netComponentId), + componentRegistry->GetComponentPropertyName(netComponentId, propertyId), totalBytes); + } } void MultiplayerDebugPerEntityReporter::RecordPropertyReceived( @@ -403,11 +214,21 @@ namespace MultiplayerDiagnostics Multiplayer::PropertyIndex propertyId, uint32_t totalBytes) { - if (Multiplayer::MultiplayerComponentRegistry* componentRegistry = Multiplayer::GetMultiplayerComponentRegistry()) + if (const Multiplayer::MultiplayerComponentRegistry* componentRegistry = Multiplayer::GetMultiplayerComponentRegistry()) { m_currentReceivingEntityReport.ReportField(static_cast(netComponentId), componentRegistry->GetComponentName(netComponentId), componentRegistry->GetComponentPropertyName(netComponentId, propertyId), totalBytes); } } + + void MultiplayerDebugPerEntityReporter::RecordRpcSent(Multiplayer::NetComponentId netComponentId, Multiplayer::RpcIndex rpcId, uint32_t totalBytes) + { + if (const Multiplayer::MultiplayerComponentRegistry* componentRegistry = Multiplayer::GetMultiplayerComponentRegistry()) + { + m_currentSendingEntityReport.ReportField(static_cast(netComponentId), + componentRegistry->GetComponentName(netComponentId), + componentRegistry->GetComponentRpcName(netComponentId, rpcId), totalBytes); + } + } } diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.h b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.h index c89c889813..121c4131ed 100644 --- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.h +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.h @@ -7,7 +7,6 @@ */ #pragma once -#include #include "MultiplayerDebugByteReporter.h" #include @@ -22,66 +21,27 @@ namespace MultiplayerDiagnostics * \brief GridMate network live analysis tool via ImGui. */ class MultiplayerDebugPerEntityReporter - : public AZ::Interface::Registrar + : public AZ::Interface::Registrar { public: - MultiplayerDebugPerEntityReporter(); - ~MultiplayerDebugPerEntityReporter() override; + MultiplayerDebugPerEntityReporter() = default; + ~MultiplayerDebugPerEntityReporter() override = default; // main update loop void OnImGuiUpdate(); //! MultilayerIPerEntityStats // @{ - void RecordEntitySerializeStart(AZ::EntityId entityId, const char* entityName); - void RecordEntitySerializeStop(AZ::EntityId entityId, const char* entityName); + void RecordEntitySerializeStart(AzNetworking::SerializerMode mode, AZ::EntityId entityId, const char* entityName) override; + void RecordComponentSerializeEnd(AzNetworking::SerializerMode mode, Multiplayer::NetComponentId netComponentId) override; + void RecordEntitySerializeStop(AzNetworking::SerializerMode mode, AZ::EntityId entityId, const char* entityName) override; void RecordPropertySent(Multiplayer::NetComponentId netComponentId, Multiplayer::PropertyIndex propertyId, uint32_t totalBytes) override; void RecordPropertyReceived(Multiplayer::NetComponentId netComponentId, Multiplayer::PropertyIndex propertyId, uint32_t totalBytes) override; + void RecordRpcSent(Multiplayer::NetComponentId netComponentId, Multiplayer::RpcIndex rpcId, uint32_t totalBytes) override; // }@ - /*void OnReceiveReplicaBegin(AZ::EntityId entityId, const void* data, size_t len) override; - void OnReceiveReplicaEnd(AZ::EntityId entityId) override; - void OnReceiveReplicaChunkEnd(GridMate::ReplicaChunkBase* chunk, AZ::u32 chunkIndex) override; - void OnReceiveDataSet(GridMate::ReplicaChunkBase* chunk, AZ::u32 chunkIndex, GridMate::DataSetBase* dataSet, GridMate::PeerId from, GridMate::PeerId to, const void* data, size_t len) override; - void OnReceiveRpc(GridMate::ReplicaChunkBase* chunk, AZ::u32 chunkIndex, GridMate::Internal::RpcRequest* rpc, GridMate::PeerId from, GridMate::PeerId to, const void* data, size_t len) override;*/ - - // ReplicaDrillerBus - sending - - /*void OnSendReplicaBegin(AZ::EntityId entityId) override; - void OnSendReplicaEnd(AZ::EntityId entityId, const void* data, size_t len) override; - void OnSendReplicaChunkEnd(GridMate::ReplicaChunkBase* chunk, AZ::u32 chunkIndex, const void* data, size_t len) override; - void OnSendDataSet(GridMate::ReplicaChunkBase* chunk, AZ::u32 chunkIndex, GridMate::DataSetBase* dataSet, GridMate::PeerId from, GridMate::PeerId to, const void* data, size_t len) override; - void OnSendRpc(GridMate::ReplicaChunkBase* chunk, AZ::u32 chunkIndex, GridMate::Internal::RpcRequest* rpc, GridMate::PeerId from, GridMate::PeerId to, const void* data, size_t len) override;*/ - - //// CarrierDrillerBus - //void OnIncomingConnection (GridMate::Carrier* carrier, GridMate::ConnectionID id) override; - //void OnFailedToConnect (GridMate::Carrier* carrier, - // GridMate::ConnectionID id, - // GridMate::CarrierDisconnectReason reason) override; - //void OnConnectionEstablished (GridMate::Carrier* carrier, GridMate::ConnectionID id) override; - //void OnDisconnect (GridMate::Carrier* carrier, - // GridMate::ConnectionID id, - // GridMate::CarrierDisconnectReason reason) override; - //void OnDriverError (GridMate::Carrier* carrier, - // GridMate::ConnectionID id, - // const GridMate::DriverError& error) override; - //void OnSecurityError (GridMate::Carrier* carrier, - // GridMate::ConnectionID id, - // const GridMate::SecurityError& error) override; - //void OnUpdateStatistics (const GridMate::string& address, - // const GridMate::TrafficControl::Statistics& lastSecond, - // const GridMate::TrafficControl::Statistics& lifeTime, - // const GridMate::TrafficControl::Statistics& effectiveLastSecond, - // const GridMate::TrafficControl::Statistics& effectiveLifeTime) override; - //void OnConnectionStateChanged (GridMate::Carrier* carrier, - // GridMate::ConnectionID id, - // GridMate::Carrier::ConnectionStates newState) override; - private: - bool m_showServerReportWindow = false; - bool m_isTrackingMessages = false; - AZStd::map m_sendingEntityReports{}; EntityReporter m_currentSendingEntityReport; @@ -90,8 +50,5 @@ namespace MultiplayerDiagnostics float m_replicatedStateKbpsWarn = 10.f; float m_replicatedStateMaxSizeWarn = 30.f; - - void UpdateTrafficStatistics(); - AZStd::map m_lastSecondStats; }; } diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.cpp b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.cpp index b97fa053b2..73afc45271 100644 --- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.cpp @@ -13,6 +13,8 @@ #include #include +#pragma optimize("", off) + namespace Multiplayer { void MultiplayerDebugSystemComponent::Reflect(AZ::ReflectContext* context) @@ -65,6 +67,7 @@ namespace Multiplayer { ImGui::Checkbox("Networking Stats", &m_displayNetworkingStats); ImGui::Checkbox("Multiplayer Stats", &m_displayMultiplayerStats); + ImGui::Checkbox("Multiplayer Per Entity Stats", &m_displayPerEntityStats); ImGui::EndMenu(); } } @@ -324,10 +327,15 @@ namespace Multiplayer } } - - if (m_reporter) + if (m_displayPerEntityStats) { - m_reporter->OnImGuiUpdate(); + if (ImGui::Begin("Multiplayer Per Entity Analytics", &m_displayPerEntityStats)) + { + if (m_reporter) + { + m_reporter->OnImGuiUpdate(); + } + } } } #endif diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.h b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.h index 3dbbd06d6f..4972ec6bdf 100644 --- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.h +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.h @@ -51,6 +51,7 @@ namespace Multiplayer private: bool m_displayNetworkingStats = false; bool m_displayMultiplayerStats = false; + bool m_displayPerEntityStats = false; AZStd::unique_ptr m_reporter; }; diff --git a/Gems/Multiplayer/Code/Source/MultiplayerStats.cpp b/Gems/Multiplayer/Code/Source/MultiplayerStats.cpp index b3236fbf77..fd1b6a329d 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerStats.cpp +++ b/Gems/Multiplayer/Code/Source/MultiplayerStats.cpp @@ -30,25 +30,33 @@ namespace Multiplayer m_componentStats[netComponentIndex].m_rpcsRecv.resize(rpcCount); } - void MultiplayerStats::RecordEntitySerializeStart(AZ::EntityId entityId, const char* entityName) + void MultiplayerStats::RecordEntitySerializeStart(AzNetworking::SerializerMode mode, AZ::EntityId entityId, const char* entityName) { - if (auto* perEntityStats = AZ::Interface::Get()) + if (auto* perEntityStats = AZ::Interface::Get()) { - perEntityStats->RecordEntitySerializeStart(entityId, entityName); + perEntityStats->RecordEntitySerializeStart(mode, entityId, entityName); } } - void MultiplayerStats::RecordEntitySerializeStop(AZ::EntityId entityId, const char* entityName) + void MultiplayerStats::RecordComponentSerializeEnd(AzNetworking::SerializerMode mode, NetComponentId netComponentId) { - if (auto* perEntityStats = AZ::Interface::Get()) + if (auto* perEntityStats = AZ::Interface::Get()) { - perEntityStats->RecordEntitySerializeStop(entityId, entityName); + perEntityStats->RecordComponentSerializeEnd(mode, netComponentId); + } + } + + void MultiplayerStats::RecordEntitySerializeStop(AzNetworking::SerializerMode mode, AZ::EntityId entityId, const char* entityName) + { + if (auto* perEntityStats = AZ::Interface::Get()) + { + perEntityStats->RecordEntitySerializeStop(mode, entityId, entityName); } } void MultiplayerStats::RecordPropertySent(NetComponentId netComponentId, PropertyIndex propertyId, uint32_t totalBytes) { - if (auto* perEntityStats = AZ::Interface::Get()) + if (auto* perEntityStats = AZ::Interface::Get()) { perEntityStats->RecordPropertySent(netComponentId, propertyId, totalBytes); } @@ -63,7 +71,7 @@ namespace Multiplayer void MultiplayerStats::RecordPropertyReceived(NetComponentId netComponentId, PropertyIndex propertyId, uint32_t totalBytes) { - if (auto* perEntityStats = AZ::Interface::Get()) + if (auto* perEntityStats = AZ::Interface::Get()) { perEntityStats->RecordPropertyReceived(netComponentId, propertyId, totalBytes); } @@ -78,6 +86,11 @@ namespace Multiplayer void MultiplayerStats::RecordRpcSent(NetComponentId netComponentId, RpcIndex rpcId, uint32_t totalBytes) { + if (auto* perEntityStats = AZ::Interface::Get()) + { + perEntityStats->RecordRpcSent(netComponentId, rpcId, totalBytes); + } + const uint16_t netComponentIndex = aznumeric_cast(netComponentId); const uint16_t rpcIndex = aznumeric_cast(rpcId); m_componentStats[netComponentIndex].m_rpcsSent[rpcIndex].m_totalCalls++; diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicator.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicator.cpp index 93fd3ea652..2afadbe4a4 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicator.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicator.cpp @@ -30,6 +30,8 @@ #include +#pragma optimize("", off) + namespace Multiplayer { EntityReplicator::EntityReplicator @@ -441,7 +443,12 @@ namespace Multiplayer { // Received rpc metrics, log rpc sent, number of bytes, and the componentId/rpcId for bandwidth metrics MultiplayerStats& stats = GetMultiplayer()->GetStats(); + stats.RecordEntitySerializeStart(AzNetworking::SerializerMode::ReadFromObject, + GetEntityHandle().GetEntity()->GetId(), GetEntityHandle().GetEntity()->GetName().c_str()); stats.RecordRpcSent(entityRpcMessage.GetComponentId(), entityRpcMessage.GetRpcIndex(), entityRpcMessage.GetEstimatedSerializeSize()); + stats.RecordComponentSerializeEnd(AzNetworking::SerializerMode::ReadFromObject, entityRpcMessage.GetComponentId()); + stats.RecordEntitySerializeStop(AzNetworking::SerializerMode::ReadFromObject, + GetEntityHandle().GetEntity()->GetId(), GetEntityHandle().GetEntity()->GetName().c_str()); m_replicationManager.AddDeferredRpcMessage(entityRpcMessage); } @@ -515,7 +522,7 @@ namespace Multiplayer && (GetRemoteNetworkRole() == NetEntityRole::Server)) { // We are on a server, and we received this message from another server, therefore we should forward this to our autonomous player - // This can occur if we've recently migrated + // This can occur if we've recently migrated result = RpcValidationResult::ForwardToAutonomous; } } From 59f65f265653cc73abeb2db3b94fb8b8bf64a231 Mon Sep 17 00:00:00 2001 From: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> Date: Mon, 26 Jul 2021 23:45:09 -0400 Subject: [PATCH 028/803] Refactored to store entities by entity ids Signed-off-by: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> --- .../Debug/MultiplayerDebugByteReporter.cpp | 20 +----------------- .../Debug/MultiplayerDebugByteReporter.h | 10 +++++++-- .../MultiplayerDebugPerEntityReporter.cpp | 21 +++++++++++-------- .../Debug/MultiplayerDebugPerEntityReporter.h | 4 ++-- 4 files changed, 23 insertions(+), 32 deletions(-) diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.cpp b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.cpp index 2c0a8b5db1..5e912612b7 100644 --- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.cpp +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.cpp @@ -163,25 +163,6 @@ namespace MultiplayerDiagnostics MultiplayerDebugByteReporter::AggregateBytes(byteSize); } - void EntityReporter::ReportDirtyBits(AZ::u32 index, const char* componentName, size_t byteSize) - { - const char* const prefix = "MB::"; - if (strncmp(prefix, componentName, 4) == 0) - { - componentName += strlen(prefix); - } - - if (m_currentComponentReport == nullptr) - { - std::stringstream component; - component << "[" << std::setw(2) << std::setfill('0') << static_cast(index) << "]" << " " << componentName; - m_currentComponentReport = &m_componentReports[component.str().c_str()]; - } - - m_currentComponentReport->ReportDirtyBits(byteSize); - m_gdeDirtyBytes.AggregateBytes(byteSize); - } - void EntityReporter::ReportFragmentEnd() { if (m_currentComponentReport) @@ -203,6 +184,7 @@ namespace MultiplayerDiagnostics m_componentReports[componentIter.first].Combine(componentIter.second); } + SetEntityName(other.GetEntityName()); m_gdeDirtyBytes.Combine(other.m_gdeDirtyBytes); } diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.h b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.h index 8977c2e6ba..3cef9caaac 100644 --- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.h +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.h @@ -54,7 +54,6 @@ namespace MultiplayerDiagnostics ComponentReporter() = default; void ReportField(const char* fieldName, size_t byteSize); - void ReportDirtyBits(size_t byteSize) { m_componentDirtyBytes.AggregateBytes(byteSize); } void ReportFragmentEnd(); using Report = AZStd::pair; @@ -75,12 +74,18 @@ namespace MultiplayerDiagnostics EntityReporter() = default; void ReportField(AZ::u32 index, const char* componentName, const char* fieldName, size_t byteSize); - void ReportDirtyBits(AZ::u32 index, const char* componentName, size_t byteSize); void ReportFragmentEnd(); void Combine(const EntityReporter& other); void Reset() override; + const char* GetEntityName() const { return m_entityName.c_str(); } + void SetEntityName(const char* entityName) + { + // copying because the entity might go away + m_entityName = entityName; + } + AZStd::map& GetComponentReports(); AZStd::size_t GetTotalDirtyBits() const { return m_gdeDirtyBytes.GetTotalBytes(); } float GetAvgDirtyBits() const { return m_gdeDirtyBytes.GetAverageBytes(); } @@ -89,5 +94,6 @@ namespace MultiplayerDiagnostics ComponentReporter* m_currentComponentReport = nullptr; AZStd::map m_componentReports; MultiplayerDebugByteReporter m_gdeDirtyBytes; + AZStd::string m_entityName; }; } diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.cpp b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.cpp index c839083f63..3517dfa86a 100644 --- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.cpp +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.cpp @@ -119,15 +119,15 @@ namespace MultiplayerDiagnostics if (ImGui::CollapsingHeader("Receiving Entities")) { - for (auto& entityPair : m_receivingEntityReports) + for (AZStd::pair& entityPair : m_receivingEntityReports) { - if (!filter.PassFilter(entityPair.first.c_str())) + if (!filter.PassFilter(entityPair.second.GetEntityName())) { continue; } ImGui::Separator(); - if (ReplicatedStateTreeNode(entityPair.first, entityPair.second, k_ImGuiDusk)) + if (ReplicatedStateTreeNode(entityPair.second.GetEntityName(), entityPair.second, k_ImGuiDusk)) { DisplayReplicatedStateReport(entityPair.second.GetComponentReports(), m_replicatedStateKbpsWarn, m_replicatedStateMaxSizeWarn); ImGui::TreePop(); @@ -137,15 +137,16 @@ namespace MultiplayerDiagnostics if (ImGui::CollapsingHeader("Sending Entities")) { - for (auto& entityPair : m_sendingEntityReports) + for (AZStd::pair& entityPair : m_sendingEntityReports) { - if (!filter.PassFilter(entityPair.first.c_str())) + const char* name = entityPair.second.GetEntityName(); + if (!filter.PassFilter(name)) { continue; } ImGui::Separator(); - if (ReplicatedStateTreeNode(entityPair.first, entityPair.second, k_ImGuiDusk)) + if (ReplicatedStateTreeNode(name, entityPair.second, k_ImGuiDusk)) { DisplayReplicatedStateReport(entityPair.second.GetComponentReports(), m_replicatedStateKbpsWarn, m_replicatedStateMaxSizeWarn); ImGui::TreePop(); @@ -162,9 +163,11 @@ namespace MultiplayerDiagnostics { case AzNetworking::SerializerMode::ReadFromObject: m_currentSendingEntityReport.Reset(); + m_currentSendingEntityReport.SetEntityName(entityName); break; case AzNetworking::SerializerMode::WriteToObject: m_currentReceivingEntityReport.Reset(); + m_currentReceivingEntityReport.SetEntityName(entityName); break; } } @@ -183,15 +186,15 @@ namespace MultiplayerDiagnostics } void MultiplayerDebugPerEntityReporter::RecordEntitySerializeStop(AzNetworking::SerializerMode mode, - [[maybe_unused]] AZ::EntityId entityId, const char* entityName) + [[maybe_unused]] AZ::EntityId entityId, [[maybe_unused]] const char* entityName) { switch (mode) { case AzNetworking::SerializerMode::ReadFromObject: - m_sendingEntityReports[entityName].Combine(m_currentSendingEntityReport); + m_sendingEntityReports[entityId].Combine(m_currentSendingEntityReport); break; case AzNetworking::SerializerMode::WriteToObject: - m_receivingEntityReports[entityName].Combine(m_currentReceivingEntityReport); + m_receivingEntityReports[entityId].Combine(m_currentReceivingEntityReport); break; } } diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.h b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.h index 121c4131ed..f34cc2cd35 100644 --- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.h +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.h @@ -42,10 +42,10 @@ namespace MultiplayerDiagnostics private: - AZStd::map m_sendingEntityReports{}; + AZStd::map m_sendingEntityReports{}; EntityReporter m_currentSendingEntityReport; - AZStd::map m_receivingEntityReports{}; + AZStd::map m_receivingEntityReports{}; EntityReporter m_currentReceivingEntityReport; float m_replicatedStateKbpsWarn = 10.f; From 8fa3addda3501ee44308f15e5331b1d27d280565 Mon Sep 17 00:00:00 2001 From: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> Date: Tue, 27 Jul 2021 00:21:40 -0400 Subject: [PATCH 029/803] Added debug overlay for entitie with high network costs Signed-off-by: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> --- .../MultiplayerDebugPerEntityReporter.cpp | 37 +++++++++++++++++++ .../Debug/MultiplayerDebugSystemComponent.cpp | 2 +- 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.cpp b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.cpp index 3517dfa86a..30e6feb2f4 100644 --- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.cpp +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.cpp @@ -7,6 +7,10 @@ */ #include "MultiplayerDebugPerEntityReporter.h" + +#include +#include +#include #include #if defined(IMGUI_ENABLED) @@ -117,6 +121,17 @@ namespace MultiplayerDiagnostics static ImGuiTextFilter filter; filter.Draw(); + char status[100] = {}; + + struct NetworkEntityTraffic + { + const char* m_name = nullptr; + float m_up = 0.f; + float m_down = 0.f; + }; + + AZStd::fixed_unordered_map networkEntitiesTraffic; + if (ImGui::CollapsingHeader("Receiving Entities")) { for (AZStd::pair& entityPair : m_receivingEntityReports) @@ -132,6 +147,9 @@ namespace MultiplayerDiagnostics DisplayReplicatedStateReport(entityPair.second.GetComponentReports(), m_replicatedStateKbpsWarn, m_replicatedStateMaxSizeWarn); ImGui::TreePop(); } + + networkEntitiesTraffic[entityPair.first].m_name = entityPair.second.GetEntityName(); + networkEntitiesTraffic[entityPair.first].m_down = entityPair.second.GetKbitsPerSecond(); } } @@ -151,8 +169,27 @@ namespace MultiplayerDiagnostics DisplayReplicatedStateReport(entityPair.second.GetComponentReports(), m_replicatedStateKbpsWarn, m_replicatedStateMaxSizeWarn); ImGui::TreePop(); } + + networkEntitiesTraffic[entityPair.first].m_name = entityPair.second.GetEntityName(); + networkEntitiesTraffic[entityPair.first].m_up = entityPair.second.GetKbitsPerSecond(); } } + + constexpr float trafficThreshold = 0.1f; + for (AZStd::pair& networkEntity : networkEntitiesTraffic) + { + if (networkEntity.second.m_down < trafficThreshold && networkEntity.second.m_up < trafficThreshold) + { + continue; + } + + azsprintf(status, "%s - %.0f down / %0.f up (kbps)", networkEntity.second.m_name, networkEntity.second.m_down, networkEntity.second.m_up); + AZ::Vector3 entityPosition = AZ::Vector3::CreateZero(); + constexpr bool centerText = true; + AZ::TransformBus::EventResult(entityPosition, networkEntity.first, &AZ::TransformBus::Events::GetWorldTranslation); + AzFramework::DebugDisplayRequestBus::Broadcast(&AzFramework::DebugDisplayRequestBus::Events::DrawTextLabel, + entityPosition, 1.0f, status, centerText, 0, 0); + } #endif } diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.cpp b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.cpp index 73afc45271..44e2f9f6bf 100644 --- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.cpp @@ -329,7 +329,7 @@ namespace Multiplayer if (m_displayPerEntityStats) { - if (ImGui::Begin("Multiplayer Per Entity Analytics", &m_displayPerEntityStats)) + if (ImGui::Begin("Multiplayer Per Entity Analytics", &m_displayPerEntityStats, ImGuiWindowFlags_None)) { if (m_reporter) { From 26c9853ff9916b7216a5e01eef6b9f7be8bb4df1 Mon Sep 17 00:00:00 2001 From: moraaar Date: Tue, 27 Jul 2021 09:11:28 +0100 Subject: [PATCH 030/803] Fixed cloth tangent generation (#2440) - The output vectors were not properly filled with zeros when they already had the expected size. - The tolerance was too large and was causing patches while computing tangents and bitangents. - The handedness was inverted to what is expected in the shader (which always inverts tangent's w). Signed-off-by: moraaar --- .../ClothComponentMesh/ClothComponentMesh.cpp | 2 +- .../Code/Source/System/TangentSpaceHelper.cpp | 20 ++++++++++++------- .../ClothConstraintsTest.cpp | 12 ++++++++--- 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/Gems/NvCloth/Code/Source/Components/ClothComponentMesh/ClothComponentMesh.cpp b/Gems/NvCloth/Code/Source/Components/ClothComponentMesh/ClothComponentMesh.cpp index b791e8a543..7e0ac2f230 100644 --- a/Gems/NvCloth/Code/Source/Components/ClothComponentMesh/ClothComponentMesh.cpp +++ b/Gems/NvCloth/Code/Source/Components/ClothComponentMesh/ClothComponentMesh.cpp @@ -577,7 +577,7 @@ namespace NvCloth const AZ::Vector3& renderTangent = renderTangents[renderVertexIndex]; destTangentsBuffer[index].Set( renderTangent, - 1.0f); + -1.0f); // Shader function ConstructTBN inverts w to change bitangent sign, but the bitangents passed are already corrected, so passing -1.0 to counteract. } if (destBitangentsBuffer) diff --git a/Gems/NvCloth/Code/Source/System/TangentSpaceHelper.cpp b/Gems/NvCloth/Code/Source/System/TangentSpaceHelper.cpp index b43ad1923b..e388643c00 100644 --- a/Gems/NvCloth/Code/Source/System/TangentSpaceHelper.cpp +++ b/Gems/NvCloth/Code/Source/System/TangentSpaceHelper.cpp @@ -11,7 +11,7 @@ namespace NvCloth { namespace { - const float Tolerance = 0.0001f; + const float Tolerance = 1e-7f; } bool TangentSpaceHelper::CalculateNormals( @@ -33,7 +33,8 @@ namespace NvCloth const size_t vertexCount = vertices.size(); // Reset results - outNormals.resize(vertexCount, AZ::Vector3::CreateZero()); + outNormals.resize(vertexCount); + AZStd::fill(outNormals.begin(), outNormals.end(), AZ::Vector3::CreateZero()); // calculate the normals per triangle for (size_t i = 0; i < triangleCount; ++i) @@ -114,8 +115,10 @@ namespace NvCloth const size_t vertexCount = vertices.size(); // Reset results - outTangents.resize(vertexCount, AZ::Vector3::CreateZero()); - outBitangents.resize(vertexCount, AZ::Vector3::CreateZero()); + outTangents.resize(vertexCount); + outBitangents.resize(vertexCount); + AZStd::fill(outTangents.begin(), outTangents.end(), AZ::Vector3::CreateZero()); + AZStd::fill(outBitangents.begin(), outBitangents.end(), AZ::Vector3::CreateZero()); // calculate the base vectors per triangle for (size_t i = 0; i < triangleCount; ++i) @@ -192,9 +195,12 @@ namespace NvCloth const size_t vertexCount = vertices.size(); // Reset results - outTangents.resize(vertexCount, AZ::Vector3::CreateZero()); - outBitangents.resize(vertexCount, AZ::Vector3::CreateZero()); - outNormals.resize(vertexCount, AZ::Vector3::CreateZero()); + outTangents.resize(vertexCount); + outBitangents.resize(vertexCount); + outNormals.resize(vertexCount); + AZStd::fill(outTangents.begin(), outTangents.end(), AZ::Vector3::CreateZero()); + AZStd::fill(outBitangents.begin(), outBitangents.end(), AZ::Vector3::CreateZero()); + AZStd::fill(outNormals.begin(), outNormals.end(), AZ::Vector3::CreateZero()); // calculate the base vectors per triangle for (size_t i = 0; i < triangleCount; ++i) diff --git a/Gems/NvCloth/Code/Tests/Components/ClothComponentMesh/ClothConstraintsTest.cpp b/Gems/NvCloth/Code/Tests/Components/ClothComponentMesh/ClothConstraintsTest.cpp index 5f390ed45d..50ca5c17cd 100644 --- a/Gems/NvCloth/Code/Tests/Components/ClothComponentMesh/ClothConstraintsTest.cpp +++ b/Gems/NvCloth/Code/Tests/Components/ClothComponentMesh/ClothConstraintsTest.cpp @@ -124,6 +124,9 @@ namespace UnitTest const AZStd::vector& motionConstraints = clothConstraints->GetMotionConstraints(); EXPECT_TRUE(motionConstraints.size() == SimulationParticles.size()); + EXPECT_THAT(motionConstraints[0].GetAsVector3(), IsCloseTolerance(SimulationParticles[0].GetAsVector3(), Tolerance)); + EXPECT_THAT(motionConstraints[1].GetAsVector3(), IsCloseTolerance(SimulationParticles[1].GetAsVector3(), Tolerance)); + EXPECT_THAT(motionConstraints[2].GetAsVector3(), IsCloseTolerance(SimulationParticles[2].GetAsVector3(), Tolerance)); EXPECT_NEAR(motionConstraints[0].GetW(), 6.0f, Tolerance); EXPECT_NEAR(motionConstraints[1].GetW(), 0.0f, Tolerance); EXPECT_NEAR(motionConstraints[2].GetW(), 0.0f, Tolerance); @@ -277,6 +280,9 @@ namespace UnitTest const AZStd::vector& separationConstraints = clothConstraints->GetSeparationConstraints(); EXPECT_TRUE(motionConstraints.size() == newParticles.size()); + EXPECT_THAT(motionConstraints[0].GetAsVector3(), IsCloseTolerance(newParticles[0].GetAsVector3(), Tolerance)); + EXPECT_THAT(motionConstraints[1].GetAsVector3(), IsCloseTolerance(newParticles[1].GetAsVector3(), Tolerance)); + EXPECT_THAT(motionConstraints[2].GetAsVector3(), IsCloseTolerance(newParticles[2].GetAsVector3(), Tolerance)); EXPECT_NEAR(motionConstraints[0].GetW(), 3.0f, Tolerance); EXPECT_NEAR(motionConstraints[1].GetW(), 1.5f, Tolerance); EXPECT_NEAR(motionConstraints[2].GetW(), 0.0f, Tolerance); @@ -285,8 +291,8 @@ namespace UnitTest EXPECT_NEAR(separationConstraints[0].GetW(), 3.0f, Tolerance); EXPECT_NEAR(separationConstraints[1].GetW(), 1.5f, Tolerance); EXPECT_NEAR(separationConstraints[2].GetW(), 0.3f, Tolerance); - EXPECT_THAT(separationConstraints[0].GetAsVector3(), IsCloseTolerance(AZ::Vector3(-3.03902f, 2.80752f, 3.80752f), Tolerance)); - EXPECT_THAT(separationConstraints[1].GetAsVector3(), IsCloseTolerance(AZ::Vector3(-1.41659f, 0.651243f, -0.348757f), Tolerance)); - EXPECT_THAT(separationConstraints[2].GetAsVector3(), IsCloseTolerance(AZ::Vector3(6.15313f, -0.876132f, 0.123868f), Tolerance)); + EXPECT_THAT(separationConstraints[0].GetAsVector3(), IsCloseTolerance(AZ::Vector3(0.0f, 3.53553f, 4.53553f), Tolerance)); + EXPECT_THAT(separationConstraints[1].GetAsVector3(), IsCloseTolerance(AZ::Vector3(0.0f, 2.06066f, 1.06066f), Tolerance)); + EXPECT_THAT(separationConstraints[2].GetAsVector3(), IsCloseTolerance(AZ::Vector3(1.0f, -3.74767f, -2.74767f), Tolerance)); } } // namespace UnitTest From 5ebb096d1a3420281a002f20a86351b8b7d1a690 Mon Sep 17 00:00:00 2001 From: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> Date: Tue, 27 Jul 2021 15:49:41 -0400 Subject: [PATCH 031/803] Debug overlay for kpbs per entity works Signed-off-by: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> --- .../MultiplayerDebugPerEntityInterface.h | 1 + .../MultiplayerDebugPerEntityReporter.cpp | 140 +++++++++++++----- .../Debug/MultiplayerDebugPerEntityReporter.h | 25 +++- .../Debug/MultiplayerDebugSystemComponent.cpp | 5 +- .../Code/Source/MultiplayerStats.cpp | 5 + 5 files changed, 138 insertions(+), 38 deletions(-) diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityInterface.h b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityInterface.h index 94bc11dafa..4f177affe3 100644 --- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityInterface.h +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityInterface.h @@ -24,5 +24,6 @@ namespace MultiplayerDiagnostics virtual void RecordPropertySent(Multiplayer::NetComponentId netComponentId, Multiplayer::PropertyIndex propertyId, uint32_t totalBytes) = 0; virtual void RecordPropertyReceived(Multiplayer::NetComponentId netComponentId, Multiplayer::PropertyIndex propertyId, uint32_t totalBytes) = 0; virtual void RecordRpcSent(Multiplayer::NetComponentId netComponentId, Multiplayer::RpcIndex rpcId, uint32_t totalBytes) = 0; + virtual void RecordRpcReceived(Multiplayer::NetComponentId netComponentId, Multiplayer::RpcIndex rpcId, uint32_t totalBytes) = 0; }; } diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.cpp b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.cpp index 30e6feb2f4..3c5495ec6a 100644 --- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.cpp +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.cpp @@ -19,6 +19,21 @@ #pragma optimize("", off) +AZ_CVAR(bool, net_DebugNetworkEntity_Bandwidth, true, nullptr, AZ::ConsoleFunctorFlags::Null, + "If true, prints debug text over entities that use a considerable amount of network traffic"); + +AZ_CVAR(float, net_DebugNetworkEntity_ShowAboveKbps, 1.f, nullptr, AZ::ConsoleFunctorFlags::Null, + "Prints bandwidth on network entities with higher kpbs than this value"); + +AZ_CVAR(float, net_DebugNetworkEntity_WarnAboveKbps, 10.f, nullptr, AZ::ConsoleFunctorFlags::Null, + "Prints bandwidth on network entities with higher kpbs than this value"); + +AZ_CVAR(AZ::Color, net_DebugNetworkEntity_WarningColor, AZ::Colors::Red, nullptr, AZ::ConsoleFunctorFlags::Null, + "If true, prints debug text over entities that use a considerable amount of network traffic"); + +AZ_CVAR(AZ::Color, net_DebugNetworkEntity_BelowWarningColor, AZ::Colors::Grey, nullptr, AZ::ConsoleFunctorFlags::Null, + "If true, prints debug text over entities that use a considerable amount of network traffic"); + namespace MultiplayerDiagnostics { #if defined(IMGUI_ENABLED) @@ -114,6 +129,17 @@ namespace MultiplayerDiagnostics } #endif + MultiplayerDebugPerEntityReporter::MultiplayerDebugPerEntityReporter() + : m_updateDebugOverlay([this]() { UpdateDebugOverlay(); }, AZ::Name("UpdateDebugPerEntityOverlay")) + { + m_updateDebugOverlay.Enqueue(AZ::TimeMs{ 0 }, true); + } + + MultiplayerDebugPerEntityReporter::~MultiplayerDebugPerEntityReporter() + { + m_updateDebugOverlay.RemoveFromQueue(); + } + // -------------------------------------------------------------------------------------------- void MultiplayerDebugPerEntityReporter::OnImGuiUpdate() { @@ -121,17 +147,6 @@ namespace MultiplayerDiagnostics static ImGuiTextFilter filter; filter.Draw(); - char status[100] = {}; - - struct NetworkEntityTraffic - { - const char* m_name = nullptr; - float m_up = 0.f; - float m_down = 0.f; - }; - - AZStd::fixed_unordered_map networkEntitiesTraffic; - if (ImGui::CollapsingHeader("Receiving Entities")) { for (AZStd::pair& entityPair : m_receivingEntityReports) @@ -147,9 +162,6 @@ namespace MultiplayerDiagnostics DisplayReplicatedStateReport(entityPair.second.GetComponentReports(), m_replicatedStateKbpsWarn, m_replicatedStateMaxSizeWarn); ImGui::TreePop(); } - - networkEntitiesTraffic[entityPair.first].m_name = entityPair.second.GetEntityName(); - networkEntitiesTraffic[entityPair.first].m_down = entityPair.second.GetKbitsPerSecond(); } } @@ -169,27 +181,8 @@ namespace MultiplayerDiagnostics DisplayReplicatedStateReport(entityPair.second.GetComponentReports(), m_replicatedStateKbpsWarn, m_replicatedStateMaxSizeWarn); ImGui::TreePop(); } - - networkEntitiesTraffic[entityPair.first].m_name = entityPair.second.GetEntityName(); - networkEntitiesTraffic[entityPair.first].m_up = entityPair.second.GetKbitsPerSecond(); } } - - constexpr float trafficThreshold = 0.1f; - for (AZStd::pair& networkEntity : networkEntitiesTraffic) - { - if (networkEntity.second.m_down < trafficThreshold && networkEntity.second.m_up < trafficThreshold) - { - continue; - } - - azsprintf(status, "%s - %.0f down / %0.f up (kbps)", networkEntity.second.m_name, networkEntity.second.m_down, networkEntity.second.m_up); - AZ::Vector3 entityPosition = AZ::Vector3::CreateZero(); - constexpr bool centerText = true; - AZ::TransformBus::EventResult(entityPosition, networkEntity.first, &AZ::TransformBus::Events::GetWorldTranslation); - AzFramework::DebugDisplayRequestBus::Broadcast(&AzFramework::DebugDisplayRequestBus::Events::DrawTextLabel, - entityPosition, 1.0f, status, centerText, 0, 0); - } #endif } @@ -271,4 +264,85 @@ namespace MultiplayerDiagnostics componentRegistry->GetComponentRpcName(netComponentId, rpcId), totalBytes); } } + + void MultiplayerDebugPerEntityReporter::RecordRpcReceived( + Multiplayer::NetComponentId netComponentId, + Multiplayer::RpcIndex rpcId, + uint32_t totalBytes) + { + if (const Multiplayer::MultiplayerComponentRegistry* componentRegistry = Multiplayer::GetMultiplayerComponentRegistry()) + { + m_currentReceivingEntityReport.ReportField(static_cast(netComponentId), + componentRegistry->GetComponentName(netComponentId), + componentRegistry->GetComponentRpcName(netComponentId, rpcId), totalBytes); + } + } + + void MultiplayerDebugPerEntityReporter::UpdateDebugOverlay() + { + if (net_DebugNetworkEntity_Bandwidth) + { + m_networkEntitiesTraffic.clear(); + + for (AZStd::pair& entityPair : m_receivingEntityReports) + { + m_networkEntitiesTraffic[entityPair.first].m_name = entityPair.second.GetEntityName(); + m_networkEntitiesTraffic[entityPair.first].m_down = entityPair.second.GetKbitsPerSecond(); + } + + for (AZStd::pair& entityPair : m_sendingEntityReports) + { + m_networkEntitiesTraffic[entityPair.first].m_name = entityPair.second.GetEntityName(); + m_networkEntitiesTraffic[entityPair.first].m_up = entityPair.second.GetKbitsPerSecond(); + } + + //get debug display interface for the viewport + if (m_debugDisplay == nullptr) + { + AzFramework::DebugDisplayRequestBus::BusPtr debugDisplayBus; + AzFramework::DebugDisplayRequestBus::Bind(debugDisplayBus, AzFramework::g_defaultSceneEntityDebugDisplayId); + m_debugDisplay = AzFramework::DebugDisplayRequestBus::FindFirstHandler(debugDisplayBus); + } + + const AZ::u32 stateBefore = m_debugDisplay->GetState(); + + for (AZStd::pair& networkEntity : m_networkEntitiesTraffic) + { + if (networkEntity.second.m_down < net_DebugNetworkEntity_ShowAboveKbps && networkEntity.second.m_up < net_DebugNetworkEntity_ShowAboveKbps) + { + continue; + } + + if (networkEntity.second.m_down > net_DebugNetworkEntity_WarnAboveKbps || networkEntity.second.m_up > net_DebugNetworkEntity_WarnAboveKbps) + { + m_debugDisplay->SetColor(net_DebugNetworkEntity_WarningColor); + } + else + { + m_debugDisplay->SetColor(net_DebugNetworkEntity_BelowWarningColor); + } + + if (networkEntity.second.m_down > net_DebugNetworkEntity_ShowAboveKbps && networkEntity.second.m_up > net_DebugNetworkEntity_ShowAboveKbps) + { + azsprintf(m_statusBuffer, "[%s] %.0f down / %0.f up (kbps)", networkEntity.second.m_name, + networkEntity.second.m_down, networkEntity.second.m_up); + } + else if (networkEntity.second.m_down > net_DebugNetworkEntity_ShowAboveKbps) + { + azsprintf(m_statusBuffer, "[%s] %.0f down (kbps)", networkEntity.second.m_name, networkEntity.second.m_down); + } + else + { + azsprintf(m_statusBuffer, "[%s] %.0f up (kbps)", networkEntity.second.m_name, networkEntity.second.m_up); + } + + AZ::Vector3 entityPosition = AZ::Vector3::CreateZero(); + constexpr bool centerText = true; + AZ::TransformBus::EventResult(entityPosition, networkEntity.first, &AZ::TransformBus::Events::GetWorldTranslation); + m_debugDisplay->DrawTextLabel(entityPosition, 1.0f, m_statusBuffer, centerText, 0, 0); + } + + m_debugDisplay->SetState(stateBefore); + } + } } diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.h b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.h index f34cc2cd35..23192062e3 100644 --- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.h +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.h @@ -10,7 +10,10 @@ #include "MultiplayerDebugByteReporter.h" #include +#include +#include #include +#include #include #include #include @@ -24,8 +27,8 @@ namespace MultiplayerDiagnostics : public AZ::Interface::Registrar { public: - MultiplayerDebugPerEntityReporter() = default; - ~MultiplayerDebugPerEntityReporter() override = default; + MultiplayerDebugPerEntityReporter(); + ~MultiplayerDebugPerEntityReporter() override; // main update loop void OnImGuiUpdate(); @@ -38,10 +41,15 @@ namespace MultiplayerDiagnostics void RecordPropertySent(Multiplayer::NetComponentId netComponentId, Multiplayer::PropertyIndex propertyId, uint32_t totalBytes) override; void RecordPropertyReceived(Multiplayer::NetComponentId netComponentId, Multiplayer::PropertyIndex propertyId, uint32_t totalBytes) override; void RecordRpcSent(Multiplayer::NetComponentId netComponentId, Multiplayer::RpcIndex rpcId, uint32_t totalBytes) override; + void RecordRpcReceived(Multiplayer::NetComponentId netComponentId, Multiplayer::RpcIndex rpcId, uint32_t totalBytes) override; // }@ + void UpdateDebugOverlay(); + private: + AZ::ScheduledEvent m_updateDebugOverlay; + AZStd::map m_sendingEntityReports{}; EntityReporter m_currentSendingEntityReport; @@ -50,5 +58,18 @@ namespace MultiplayerDiagnostics float m_replicatedStateKbpsWarn = 10.f; float m_replicatedStateMaxSizeWarn = 30.f; + + char m_statusBuffer[100] = {}; + + struct NetworkEntityTraffic + { + const char* m_name = nullptr; + float m_up = 0.f; + float m_down = 0.f; + }; + + AZStd::fixed_unordered_map m_networkEntitiesTraffic; + + AzFramework::DebugDisplayRequests* m_debugDisplay = nullptr; }; } diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.cpp b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.cpp index 44e2f9f6bf..835aae0d72 100644 --- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.cpp @@ -13,8 +13,6 @@ #include #include -#pragma optimize("", off) - namespace Multiplayer { void MultiplayerDebugSystemComponent::Reflect(AZ::ReflectContext* context) @@ -329,7 +327,8 @@ namespace Multiplayer if (m_displayPerEntityStats) { - if (ImGui::Begin("Multiplayer Per Entity Analytics", &m_displayPerEntityStats, ImGuiWindowFlags_None)) + //ImGui::SetNextWindowSize({500, 400}); + if (ImGui::Begin("Multiplayer Per Entity Stats", &m_displayPerEntityStats, ImGuiWindowFlags_AlwaysAutoResize)) { if (m_reporter) { diff --git a/Gems/Multiplayer/Code/Source/MultiplayerStats.cpp b/Gems/Multiplayer/Code/Source/MultiplayerStats.cpp index fd1b6a329d..05be869872 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerStats.cpp +++ b/Gems/Multiplayer/Code/Source/MultiplayerStats.cpp @@ -101,6 +101,11 @@ namespace Multiplayer void MultiplayerStats::RecordRpcReceived(NetComponentId netComponentId, RpcIndex rpcId, uint32_t totalBytes) { + if (auto* perEntityStats = AZ::Interface::Get()) + { + perEntityStats->RecordRpcReceived(netComponentId, rpcId, totalBytes); + } + const uint16_t netComponentIndex = aznumeric_cast(netComponentId); const uint16_t rpcIndex = aznumeric_cast(rpcId); m_componentStats[netComponentIndex].m_rpcsRecv[rpcIndex].m_totalCalls++; From 416f9aecf71faf3df82bfcabb23ba87f1b13d809 Mon Sep 17 00:00:00 2001 From: Benjamin Jillich Date: Wed, 28 Jul 2021 15:09:38 +0200 Subject: [PATCH 032/803] Removed collision mesh aabb color from render option Signed-off-by: Benjamin Jillich --- .../Source/RenderPlugin/RenderOptions.cpp | 23 ------------------- .../Source/RenderPlugin/RenderOptions.h | 6 ----- 2 files changed, 29 deletions(-) diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderOptions.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderOptions.cpp index ef74cf466f..5e57d64167 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderOptions.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderOptions.cpp @@ -55,7 +55,6 @@ namespace EMStudio const char* RenderOptions::s_nodeAABBColorOptionName = "nodeAABBColor"; const char* RenderOptions::s_staticAABBColorOptionName = "staticAABBColor"; const char* RenderOptions::s_meshAABBColorOptionName = "meshAABBColor"; - const char* RenderOptions::s_collisionMeshAABBColorOptionName = "collisionMeshAABBColor"; const char* RenderOptions::s_OBBsColorOptionName = "OBBsColor"; const char* RenderOptions::s_lineSkeletonColorOptionName = "lineSkeletonColor_v2"; const char* RenderOptions::s_skeletonColorOptionName = "skeletonColor"; @@ -108,7 +107,6 @@ namespace EMStudio , m_nodeAABBColor(1.0f, 0.0f, 0.0f, 1.0f) , m_staticAABBColor(0.0f, 0.7f, 0.7f, 1.0f) , m_meshAABBColor(0.0f, 0.0f, 0.7f, 1.0f) - , m_collisionMeshAABBColor(0.0f, 0.7f, 0.0f, 1.0f) , m_OBBsColor(1.0f, 1.0f, 0.0f, 1.0f) , m_lineSkeletonColor(0.33333f, 1.0f, 0.0f, 1.0f) , m_skeletonColor(0.19f, 0.58f, 0.19f, 1.0f) @@ -169,7 +167,6 @@ namespace EMStudio SetNodeAABBColor(other.GetNodeAABBColor()); SetStaticAABBColor(other.GetStaticAABBColor()); SetMeshAABBColor(other.GetMeshAABBColor()); - SetCollisionMeshAABBColor(other.GetCollisionMeshAABBColor()); SetOBBsColor(other.GetOBBsColor()); SetLineSkeletonColor(other.GetLineSkeletonColor()); SetSkeletonColor(other.GetSkeletonColor()); @@ -206,7 +203,6 @@ namespace EMStudio settings->setValue(s_nodeAABBColorOptionName, ColorToString(m_nodeAABBColor)); settings->setValue(s_staticAABBColorOptionName, ColorToString(m_staticAABBColor)); settings->setValue(s_meshAABBColorOptionName, ColorToString(m_meshAABBColor)); - settings->setValue(s_collisionMeshAABBColorOptionName, ColorToString(m_collisionMeshAABBColor)); settings->setValue(s_collisionMeshColorOptionName, ColorToString(m_collisionMeshColor)); settings->setValue(s_OBBsColorOptionName, ColorToString(m_OBBsColor)); settings->setValue(s_lineSkeletonColorOptionName, ColorToString(m_lineSkeletonColor)); @@ -275,7 +271,6 @@ namespace EMStudio options.m_nodeAABBColor = StringToColor(settings->value(s_nodeAABBColorOptionName, ColorToString(options.m_nodeAABBColor)).toString()); options.m_staticAABBColor = StringToColor(settings->value(s_staticAABBColorOptionName, ColorToString(options.m_staticAABBColor)).toString()); options.m_meshAABBColor = StringToColor(settings->value(s_meshAABBColorOptionName, ColorToString(options.m_meshAABBColor)).toString()); - options.m_collisionMeshAABBColor = StringToColor(settings->value(s_collisionMeshAABBColorOptionName, ColorToString(options.m_collisionMeshAABBColor)).toString()); options.m_collisionMeshColor = StringToColor(settings->value(s_collisionMeshColorOptionName, ColorToString(options.m_collisionMeshColor)).toString()); options.m_OBBsColor = StringToColor(settings->value(s_OBBsColorOptionName, ColorToString(options.m_OBBsColor)).toString()); options.m_lineSkeletonColor = StringToColor(settings->value(s_lineSkeletonColorOptionName, ColorToString(options.m_lineSkeletonColor)).toString()); @@ -393,7 +388,6 @@ namespace EMStudio ->Field(s_nodeAABBColorOptionName, &RenderOptions::m_nodeAABBColor) ->Field(s_staticAABBColorOptionName, &RenderOptions::m_staticAABBColor) ->Field(s_meshAABBColorOptionName, &RenderOptions::m_meshAABBColor) - ->Field(s_collisionMeshAABBColorOptionName, &RenderOptions::m_collisionMeshAABBColor) ->Field(s_OBBsColorOptionName, &RenderOptions::m_OBBsColor) ->Field(s_lineSkeletonColorOptionName, &RenderOptions::m_lineSkeletonColor) ->Field(s_skeletonColorOptionName, &RenderOptions::m_skeletonColor) @@ -552,9 +546,6 @@ namespace EMStudio ->DataElement(AZ::Edit::UIHandlers::Default, &RenderOptions::m_meshAABBColor, "Mesh based AABB color", "Color for the runtime-updated AABB calculated based on the deformed meshes.") ->Attribute(AZ::Edit::Attributes::ChangeNotify, &RenderOptions::OnMeshAABBColorChangedCallback) - ->DataElement(AZ::Edit::UIHandlers::Default, &RenderOptions::m_collisionMeshAABBColor, "CollisionMesh based AABB color", - "Color for the runtime-updated AABB calculated based on the deformed collision meshes.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &RenderOptions::OnCollisionMeshAABBColorChangedCallback) ->DataElement(AZ::Edit::UIHandlers::Default, &RenderOptions::m_OBBsColor, "Joint OBB color", "Color used for the pre-calculated joint oriented bounding boxes.") ->Attribute(AZ::Edit::Attributes::ChangeNotify, &RenderOptions::OnOBBsColorChangedCallback) @@ -903,15 +894,6 @@ namespace EMStudio } } - void RenderOptions::SetCollisionMeshAABBColor(const AZ::Color& collisionMeshAABBColor) - { - if (!collisionMeshAABBColor.IsClose(m_collisionMeshAABBColor)) - { - m_collisionMeshAABBColor = collisionMeshAABBColor; - OnCollisionMeshAABBColorChangedCallback(); - } - } - void RenderOptions::SetOBBsColor(const AZ::Color& OBBsColor) { if (!OBBsColor.IsClose(m_OBBsColor)) @@ -1258,11 +1240,6 @@ namespace EMStudio PluginOptionsNotificationsBus::Event(s_meshAABBColorOptionName, &PluginOptionsNotificationsBus::Events::OnOptionChanged, s_meshAABBColorOptionName); } - void RenderOptions::OnCollisionMeshAABBColorChangedCallback() const - { - PluginOptionsNotificationsBus::Event(s_collisionMeshAABBColorOptionName, &PluginOptionsNotificationsBus::Events::OnOptionChanged, s_collisionMeshAABBColorOptionName); - } - void RenderOptions::OnOBBsColorChangedCallback() const { PluginOptionsNotificationsBus::Event(s_OBBsColorOptionName, &PluginOptionsNotificationsBus::Events::OnOptionChanged, s_OBBsColorOptionName); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderOptions.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderOptions.h index 1df1a023c8..5e12cf935f 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderOptions.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderOptions.h @@ -59,7 +59,6 @@ namespace EMStudio static const char* s_nodeAABBColorOptionName; static const char* s_staticAABBColorOptionName; static const char* s_meshAABBColorOptionName; - static const char* s_collisionMeshAABBColorOptionName; static const char* s_OBBsColorOptionName; static const char* s_lineSkeletonColorOptionName; static const char* s_skeletonColorOptionName; @@ -191,9 +190,6 @@ namespace EMStudio AZ::Color GetMeshAABBColor() const { return m_meshAABBColor; } void SetMeshAABBColor(const AZ::Color& meshAABBColor); - AZ::Color GetCollisionMeshAABBColor() const { return m_collisionMeshAABBColor; } - void SetCollisionMeshAABBColor(const AZ::Color& collisionMeshAABBColor); - AZ::Color GetOBBsColor() const { return m_OBBsColor; } void SetOBBsColor(const AZ::Color& OBBsColor); @@ -303,7 +299,6 @@ namespace EMStudio void OnNodeAABBColorChangedCallback() const; void OnStaticAABBColorChangedCallback() const; void OnMeshAABBColorChangedCallback() const; - void OnCollisionMeshAABBColorChangedCallback() const; void OnOBBsColorChangedCallback() const; void OnLineSkeletonColorChangedCallback() const; void OnSkeletonColorChangedCallback() const; @@ -361,7 +356,6 @@ namespace EMStudio AZ::Color m_nodeAABBColor; AZ::Color m_staticAABBColor; AZ::Color m_meshAABBColor; - AZ::Color m_collisionMeshAABBColor; AZ::Color m_OBBsColor; AZ::Color m_lineSkeletonColor; AZ::Color m_skeletonColor; From e9718d9ce87ceb09c209777174ca46d37ef4a288 Mon Sep 17 00:00:00 2001 From: Benjamin Jillich Date: Wed, 28 Jul 2021 15:30:34 +0200 Subject: [PATCH 033/803] Converted the EMFX Mesh to use AZ::Aabb instead of MCore::AABB Signed-off-by: Benjamin Jillich --- Gems/EMotionFX/Code/EMotionFX/Source/Mesh.cpp | 9 +++------ Gems/EMotionFX/Code/EMotionFX/Source/Mesh.h | 3 ++- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.cpp index 51486c39b5..60ebd9a2dc 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.cpp @@ -1372,20 +1372,17 @@ namespace EMotionFX } - void Mesh::CalcAABB(MCore::AABB* outBoundingBox, const Transform& transform, uint32 vertexFrequency) + void Mesh::CalcAabb(AZ::Aabb* outBoundingBox, const Transform& transform, uint32 vertexFrequency) { MCORE_ASSERT(vertexFrequency >= 1); + *outBoundingBox = AZ::Aabb::CreateNull(); - // init the bounding box - outBoundingBox->Init(); - - // get the position data AZ::Vector3* positions = (AZ::Vector3*)FindVertexData(ATTRIB_POSITIONS); const uint32 numVerts = GetNumVertices(); for (uint32 i = 0; i < numVerts; i += vertexFrequency) { - outBoundingBox->Encapsulate(transform.TransformPoint(positions[i])); + outBoundingBox->AddPoint(transform.TransformPoint(positions[i])); } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.h b/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.h index f9a9f960ce..cb929dc7db 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.h @@ -9,6 +9,7 @@ #pragma once #include "EMotionFXConfig.h" +#include #include #include #include @@ -571,7 +572,7 @@ namespace EMotionFX * @param vertexFrequency This is the for loop increase counter value. A value of 1 means every vertex will be processed * while a value of 2 means every second vertex, etc. The value must be 1 or higher. */ - void CalcAABB(MCore::AABB* outBoundingBox, const Transform& transform, uint32 vertexFrequency = 1); + void CalcAabb(AZ::Aabb* outBoundingBox, const Transform& transform, uint32 vertexFrequency = 1); /** * The mesh type used to indicate if a mesh is either static, like a cube or building, cpu deformed, if it needs to be processed on the CPU, or GPU deformed if it can be processed fully on the GPU. From 462c31b5de49ffe05c1788741278d2865a685ae1 Mon Sep 17 00:00:00 2001 From: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> Date: Wed, 28 Jul 2021 09:53:44 -0400 Subject: [PATCH 034/803] Refactoring to use AZ::Events Signed-off-by: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> --- .../Include/Multiplayer/MultiplayerStats.h | 30 ++++++++- .../Debug/MultiplayerDebugByteReporter.cpp | 38 ++++++------ .../Debug/MultiplayerDebugByteReporter.h | 20 +++--- .../MultiplayerDebugPerEntityInterface.h | 29 --------- .../MultiplayerDebugPerEntityReporter.cpp | 61 ++++++++++++++++--- .../Debug/MultiplayerDebugPerEntityReporter.h | 34 +++++------ .../Debug/MultiplayerDebugSystemComponent.cpp | 4 +- .../Debug/MultiplayerDebugSystemComponent.h | 2 +- .../Code/Source/MultiplayerStats.cpp | 59 ++++++++---------- .../EntityReplication/EntityReplicator.cpp | 11 ++-- .../Code/multiplayer_debug_files.cmake | 1 - 11 files changed, 156 insertions(+), 133 deletions(-) delete mode 100644 Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityInterface.h diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/MultiplayerStats.h b/Gems/Multiplayer/Code/Include/Multiplayer/MultiplayerStats.h index 1299fe174d..98a7b165f8 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/MultiplayerStats.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/MultiplayerStats.h @@ -55,8 +55,8 @@ namespace Multiplayer void RecordEntitySerializeStop(AzNetworking::SerializerMode mode, AZ::EntityId entityId, const char* entityName); void RecordPropertySent(NetComponentId netComponentId, PropertyIndex propertyId, uint32_t totalBytes); void RecordPropertyReceived(NetComponentId netComponentId, PropertyIndex propertyId, uint32_t totalBytes); - void RecordRpcSent(NetComponentId netComponentId, RpcIndex rpcId, uint32_t totalBytes); - void RecordRpcReceived(NetComponentId netComponentId, RpcIndex rpcId, uint32_t totalBytes); + void RecordRpcSent(AZ::EntityId entityId, const char* entityName, NetComponentId netComponentId, RpcIndex rpcId, uint32_t totalBytes); + void RecordRpcReceived(AZ::EntityId entityId, const char* entityName, NetComponentId netComponentId, RpcIndex rpcId, uint32_t totalBytes); void TickStats(AZ::TimeMs metricFrameTimeMs); Metric CalculateComponentPropertyUpdateSentMetrics(NetComponentId netComponentId) const; @@ -67,5 +67,31 @@ namespace Multiplayer Metric CalculateTotalPropertyUpdateRecvMetrics() const; Metric CalculateTotalRpcsSentMetrics() const; Metric CalculateTotalRpcsRecvMetrics() const; + + struct Events + { + AZ::Event m_entitySerializeStart; + AZ::Event m_componentSerializeEnd; + AZ::Event m_entitySerializeStop; + AZ::Event m_propertySent; + AZ::Event m_propertyReceived; + AZ::Event m_rpcSent; + AZ::Event m_rpcReceived; + }; + + Events m_events; + + struct EventHandlers + { + AZ::Event::Handler m_entitySerializeStart; + AZ::Event::Handler m_componentSerializeEnd; + AZ::Event::Handler m_entitySerializeStop; + AZ::Event::Handler m_propertySent; + AZ::Event::Handler m_propertyReceived; + AZ::Event::Handler m_rpcSent; + AZ::Event::Handler m_rpcReceived; + }; + + void ConnectHandlers(EventHandlers& handlers); }; } diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.cpp b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.cpp index 5e912612b7..a29350e43a 100644 --- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.cpp +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.cpp @@ -14,7 +14,7 @@ #pragma optimize("", off) -namespace MultiplayerDiagnostics +namespace Multiplayer { void MultiplayerDebugByteReporter::ReportBytes(size_t byteSize) { @@ -44,7 +44,7 @@ namespace MultiplayerDiagnostics return 0.0f; } - return (1.0f * m_totalBytes) / m_count; + return aznumeric_cast(m_totalBytes) / aznumeric_cast(m_count); } size_t MultiplayerDebugByteReporter::GetMaxBytes() const @@ -64,26 +64,26 @@ namespace MultiplayerDiagnostics float MultiplayerDebugByteReporter::GetKbitsPerSecond() { - auto now = AZStd::chrono::monotonic_clock::now(); + const auto now = AZStd::chrono::monotonic_clock::now(); // Check the amount of time elapsed and update totals if necessary. // Time here is measured in whole seconds from the epoch, providing synchronization in // reporting intervals across all byte reporters. - AZStd::chrono::seconds nowSeconds = AZStd::chrono::duration_cast(now.time_since_epoch()); - AZStd::chrono::seconds secondsSinceLastUpdate = nowSeconds - + const AZStd::chrono::seconds nowSeconds = AZStd::chrono::duration_cast(now.time_since_epoch()); + const AZStd::chrono::seconds secondsSinceLastUpdate = nowSeconds - AZStd::chrono::duration_cast(m_lastUpdateTime.time_since_epoch()); if (secondsSinceLastUpdate.count()) { // normalize over elapsed milliseconds - const int k_millisecondsPerSecond = 1000; - auto msSinceLastUpdate = AZStd::chrono::duration_cast(now - m_lastUpdateTime); - m_totalBytesLastSecond = k_millisecondsPerSecond * (1.f * m_totalBytesThisSecond / msSinceLastUpdate.count()); + constexpr int k_millisecondsPerSecond = 1000; + const auto msSinceLastUpdate = AZStd::chrono::duration_cast(now - m_lastUpdateTime); + m_totalBytesLastSecond = k_millisecondsPerSecond * aznumeric_cast(m_totalBytesThisSecond) / aznumeric_cast(msSinceLastUpdate.count()); m_totalBytesThisSecond = 0; m_lastUpdateTime = now; } - const float k_bitsPerByte = 8.0f; - const int k_bitsPerKilobit = 1024; + constexpr float k_bitsPerByte = 8.0f; + constexpr int k_bitsPerKilobit = 1024; return k_bitsPerByte * m_totalBytesLastSecond / k_bitsPerKilobit; } @@ -107,19 +107,19 @@ namespace MultiplayerDiagnostics m_aggregateBytes = 0; } - void ComponentReporter::ReportField(const char* fieldName, size_t byteSize) + void MultiplayerDebugComponentReporter::ReportField(const char* fieldName, size_t byteSize) { MultiplayerDebugByteReporter::AggregateBytes(byteSize); m_fieldReports[fieldName].ReportBytes(byteSize); } - void ComponentReporter::ReportFragmentEnd() + void MultiplayerDebugComponentReporter::ReportFragmentEnd() { MultiplayerDebugByteReporter::ReportAggregateBytes(); m_componentDirtyBytes.ReportAggregateBytes(); } - AZStd::vector ComponentReporter::GetFieldReports() + AZStd::vector MultiplayerDebugComponentReporter::GetFieldReports() { AZStd::vector copy; for (auto field = m_fieldReports.begin(); field != m_fieldReports.end(); ++field) @@ -137,7 +137,7 @@ namespace MultiplayerDiagnostics return copy; } - void ComponentReporter::Combine(const ComponentReporter& other) + void MultiplayerDebugComponentReporter::Combine(const MultiplayerDebugComponentReporter& other) { MultiplayerDebugByteReporter::Combine(other); @@ -149,7 +149,7 @@ namespace MultiplayerDiagnostics m_componentDirtyBytes.Combine(other.m_componentDirtyBytes); } - void EntityReporter::ReportField(AZ::u32 index, const char* componentName, + void MultiplayerDebugEntityReporter::ReportField(AZ::u32 index, const char* componentName, const char* fieldName, size_t byteSize) { if (m_currentComponentReport == nullptr) @@ -163,7 +163,7 @@ namespace MultiplayerDiagnostics MultiplayerDebugByteReporter::AggregateBytes(byteSize); } - void EntityReporter::ReportFragmentEnd() + void MultiplayerDebugEntityReporter::ReportFragmentEnd() { if (m_currentComponentReport) { @@ -175,7 +175,7 @@ namespace MultiplayerDiagnostics MultiplayerDebugByteReporter::ReportAggregateBytes(); } - void EntityReporter::Combine(const EntityReporter& other) + void MultiplayerDebugEntityReporter::Combine(const MultiplayerDebugEntityReporter& other) { MultiplayerDebugByteReporter::Combine(other); @@ -188,7 +188,7 @@ namespace MultiplayerDiagnostics m_gdeDirtyBytes.Combine(other.m_gdeDirtyBytes); } - void EntityReporter::Reset() + void MultiplayerDebugEntityReporter::Reset() { MultiplayerDebugByteReporter::Reset(); @@ -196,7 +196,7 @@ namespace MultiplayerDiagnostics m_gdeDirtyBytes.Reset(); } - AZStd::map& EntityReporter::GetComponentReports() + AZStd::map& MultiplayerDebugEntityReporter::GetComponentReports() { return m_componentReports; } diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.h b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.h index 3cef9caaac..934c6f3aac 100644 --- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.h +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.h @@ -13,7 +13,7 @@ #include #include -namespace MultiplayerDiagnostics +namespace Multiplayer { class MultiplayerDebugByteReporter { @@ -48,10 +48,10 @@ namespace MultiplayerDiagnostics AZStd::chrono::monotonic_clock::time_point m_lastUpdateTime; }; - class ComponentReporter : public MultiplayerDebugByteReporter + class MultiplayerDebugComponentReporter : public MultiplayerDebugByteReporter { public: - ComponentReporter() = default; + MultiplayerDebugComponentReporter() = default; void ReportField(const char* fieldName, size_t byteSize); void ReportFragmentEnd(); @@ -61,22 +61,22 @@ namespace MultiplayerDiagnostics AZStd::size_t GetTotalDirtyBits() const { return m_componentDirtyBytes.GetTotalBytes(); } float GetAvgDirtyBits() const { return m_componentDirtyBytes.GetAverageBytes(); } - void Combine(const ComponentReporter& other); + void Combine(const MultiplayerDebugComponentReporter& other); private: AZStd::map m_fieldReports; MultiplayerDebugByteReporter m_componentDirtyBytes; }; - class EntityReporter : public MultiplayerDebugByteReporter + class MultiplayerDebugEntityReporter : public MultiplayerDebugByteReporter { public: - EntityReporter() = default; + MultiplayerDebugEntityReporter() = default; void ReportField(AZ::u32 index, const char* componentName, const char* fieldName, size_t byteSize); void ReportFragmentEnd(); - void Combine(const EntityReporter& other); + void Combine(const MultiplayerDebugEntityReporter& other); void Reset() override; const char* GetEntityName() const { return m_entityName.c_str(); } @@ -86,13 +86,13 @@ namespace MultiplayerDiagnostics m_entityName = entityName; } - AZStd::map& GetComponentReports(); + AZStd::map& GetComponentReports(); AZStd::size_t GetTotalDirtyBits() const { return m_gdeDirtyBytes.GetTotalBytes(); } float GetAvgDirtyBits() const { return m_gdeDirtyBytes.GetAverageBytes(); } private: - ComponentReporter* m_currentComponentReport = nullptr; - AZStd::map m_componentReports; + MultiplayerDebugComponentReporter* m_currentComponentReport = nullptr; + AZStd::map m_componentReports; MultiplayerDebugByteReporter m_gdeDirtyBytes; AZStd::string m_entityName; }; diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityInterface.h b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityInterface.h deleted file mode 100644 index 4f177affe3..0000000000 --- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityInterface.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -#pragma once - -#include -#include - -namespace MultiplayerDiagnostics -{ - class MultiplayerIPerEntityStats - { - public: - AZ_RTTI(MultiplayerIPerEntityStats, "{91A1E4F0-8AE6-44B2-89DF-DA34134C408A}"); - - virtual void RecordEntitySerializeStart(AzNetworking::SerializerMode mode, AZ::EntityId entityId, const char* entityName) = 0; - virtual void RecordComponentSerializeEnd(AzNetworking::SerializerMode mode, Multiplayer::NetComponentId netComponentId) = 0; - virtual void RecordEntitySerializeStop(AzNetworking::SerializerMode mode, AZ::EntityId entityId, const char* entityName) = 0; - virtual void RecordPropertySent(Multiplayer::NetComponentId netComponentId, Multiplayer::PropertyIndex propertyId, uint32_t totalBytes) = 0; - virtual void RecordPropertyReceived(Multiplayer::NetComponentId netComponentId, Multiplayer::PropertyIndex propertyId, uint32_t totalBytes) = 0; - virtual void RecordRpcSent(Multiplayer::NetComponentId netComponentId, Multiplayer::RpcIndex rpcId, uint32_t totalBytes) = 0; - virtual void RecordRpcReceived(Multiplayer::NetComponentId netComponentId, Multiplayer::RpcIndex rpcId, uint32_t totalBytes) = 0; - }; -} diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.cpp b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.cpp index 3c5495ec6a..da32bbb666 100644 --- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.cpp +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.cpp @@ -34,7 +34,7 @@ AZ_CVAR(AZ::Color, net_DebugNetworkEntity_WarningColor, AZ::Colors::Red, nullptr AZ_CVAR(AZ::Color, net_DebugNetworkEntity_BelowWarningColor, AZ::Colors::Grey, nullptr, AZ::ConsoleFunctorFlags::Null, "If true, prints debug text over entities that use a considerable amount of network traffic"); -namespace MultiplayerDiagnostics +namespace Multiplayer { #if defined(IMGUI_ENABLED) static const ImVec4 k_ImGuiTomato = ImVec4(1.0f, 0.4f, 0.3f, 1.0f); @@ -64,12 +64,12 @@ namespace MultiplayerDiagnostics } // -------------------------------------------------------------------------------------------- - void DisplayReplicatedStateReport(AZStd::map& componentReports, float kbpsWarn, float maxWarn) + void DisplayReplicatedStateReport(AZStd::map& componentReports, float kbpsWarn, float maxWarn) { for (auto& componentPair : componentReports) { ImGui::Separator(); - ComponentReporter& componentReport = componentPair.second; + MultiplayerDebugComponentReporter& componentReport = componentPair.second; if (ReplicatedStateTreeNode(componentPair.first, componentReport, k_ImGuiCyan, 1)) { @@ -94,7 +94,7 @@ namespace MultiplayerDiagnostics const float kbitsLastSecond = fieldReport.GetKbitsPerSecond(); const ImVec4* textColor = &k_ImGuiWhite; - if (fieldReport.GetMaxBytes() > maxWarn) + if (aznumeric_cast(fieldReport.GetMaxBytes()) > maxWarn) { textColor = &k_ImGuiKhaki; } @@ -133,6 +133,37 @@ namespace MultiplayerDiagnostics : m_updateDebugOverlay([this]() { UpdateDebugOverlay(); }, AZ::Name("UpdateDebugPerEntityOverlay")) { m_updateDebugOverlay.Enqueue(AZ::TimeMs{ 0 }, true); + + m_eventHandlers.m_entitySerializeStart = decltype(m_eventHandlers.m_entitySerializeStart)([this](AzNetworking::SerializerMode mode, AZ::EntityId entityId, const char* entityName) + { + RecordEntitySerializeStart(mode, entityId, entityName); + }); + m_eventHandlers.m_componentSerializeEnd = decltype(m_eventHandlers.m_componentSerializeEnd)([this](AzNetworking::SerializerMode mode, Multiplayer::NetComponentId netComponentId) + { + RecordComponentSerializeEnd(mode, netComponentId); + }); + m_eventHandlers.m_entitySerializeStop = decltype(m_eventHandlers.m_entitySerializeStop)([this](AzNetworking::SerializerMode mode, AZ::EntityId entityId, const char* entityName) + { + RecordEntitySerializeStop(mode, entityId, entityName); + }); + m_eventHandlers.m_propertySent = decltype(m_eventHandlers.m_propertySent)([this](Multiplayer::NetComponentId netComponentId, Multiplayer::PropertyIndex propertyId, uint32_t totalBytes) + { + RecordPropertySent(netComponentId, propertyId, totalBytes); + }); + m_eventHandlers.m_propertyReceived = decltype(m_eventHandlers.m_propertyReceived)([this](Multiplayer::NetComponentId netComponentId, Multiplayer::PropertyIndex propertyId, uint32_t totalBytes) + { + RecordPropertyReceived(netComponentId, propertyId, totalBytes); + }); + m_eventHandlers.m_rpcSent = decltype(m_eventHandlers.m_rpcSent)([this](AZ::EntityId entityId, const char* entityName, Multiplayer::NetComponentId netComponentId, Multiplayer::RpcIndex rpcId, uint32_t totalBytes) + { + RecordRpcSent(entityId, entityName, netComponentId, rpcId, totalBytes); + }); + m_eventHandlers.m_rpcReceived = decltype(m_eventHandlers.m_rpcReceived)([this](AZ::EntityId entityId, const char* entityName, Multiplayer::NetComponentId netComponentId, Multiplayer::RpcIndex rpcId, uint32_t totalBytes) + { + RecordRpcSent(entityId, entityName, netComponentId, rpcId, totalBytes); + }); + + GetMultiplayer()->GetStats().ConnectHandlers(m_eventHandlers); } MultiplayerDebugPerEntityReporter::~MultiplayerDebugPerEntityReporter() @@ -149,7 +180,7 @@ namespace MultiplayerDiagnostics if (ImGui::CollapsingHeader("Receiving Entities")) { - for (AZStd::pair& entityPair : m_receivingEntityReports) + for (AZStd::pair& entityPair : m_receivingEntityReports) { if (!filter.PassFilter(entityPair.second.GetEntityName())) { @@ -167,7 +198,7 @@ namespace MultiplayerDiagnostics if (ImGui::CollapsingHeader("Sending Entities")) { - for (AZStd::pair& entityPair : m_sendingEntityReports) + for (AZStd::pair& entityPair : m_sendingEntityReports) { const char* name = entityPair.second.GetEntityName(); if (!filter.PassFilter(name)) @@ -255,26 +286,38 @@ namespace MultiplayerDiagnostics } } - void MultiplayerDebugPerEntityReporter::RecordRpcSent(Multiplayer::NetComponentId netComponentId, Multiplayer::RpcIndex rpcId, uint32_t totalBytes) + void MultiplayerDebugPerEntityReporter::RecordRpcSent(AZ::EntityId entityId, const char* entityName, Multiplayer::NetComponentId netComponentId, Multiplayer::RpcIndex rpcId, uint32_t totalBytes) { if (const Multiplayer::MultiplayerComponentRegistry* componentRegistry = Multiplayer::GetMultiplayerComponentRegistry()) { + // MultiplayerDebugByteReporter requires a + RecordEntitySerializeStart(AzNetworking::SerializerMode::ReadFromObject, entityId, entityName); + m_currentSendingEntityReport.ReportField(static_cast(netComponentId), componentRegistry->GetComponentName(netComponentId), componentRegistry->GetComponentRpcName(netComponentId, rpcId), totalBytes); + + RecordComponentSerializeEnd(AzNetworking::SerializerMode::ReadFromObject, netComponentId); + RecordEntitySerializeStop(AzNetworking::SerializerMode::ReadFromObject, entityId, entityName); } } void MultiplayerDebugPerEntityReporter::RecordRpcReceived( + AZ::EntityId entityId, const char* entityName, Multiplayer::NetComponentId netComponentId, Multiplayer::RpcIndex rpcId, uint32_t totalBytes) { if (const Multiplayer::MultiplayerComponentRegistry* componentRegistry = Multiplayer::GetMultiplayerComponentRegistry()) { + RecordEntitySerializeStart(AzNetworking::SerializerMode::WriteToObject, entityId, entityName); + m_currentReceivingEntityReport.ReportField(static_cast(netComponentId), componentRegistry->GetComponentName(netComponentId), componentRegistry->GetComponentRpcName(netComponentId, rpcId), totalBytes); + + RecordComponentSerializeEnd(AzNetworking::SerializerMode::WriteToObject, netComponentId); + RecordEntitySerializeStop(AzNetworking::SerializerMode::WriteToObject, entityId, entityName); } } @@ -284,13 +327,13 @@ namespace MultiplayerDiagnostics { m_networkEntitiesTraffic.clear(); - for (AZStd::pair& entityPair : m_receivingEntityReports) + for (AZStd::pair& entityPair : m_receivingEntityReports) { m_networkEntitiesTraffic[entityPair.first].m_name = entityPair.second.GetEntityName(); m_networkEntitiesTraffic[entityPair.first].m_down = entityPair.second.GetKbitsPerSecond(); } - for (AZStd::pair& entityPair : m_sendingEntityReports) + for (AZStd::pair& entityPair : m_sendingEntityReports) { m_networkEntitiesTraffic[entityPair.first].m_name = entityPair.second.GetEntityName(); m_networkEntitiesTraffic[entityPair.first].m_up = entityPair.second.GetKbitsPerSecond(); diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.h b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.h index 23192062e3..d6ceaaf04c 100644 --- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.h +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.h @@ -10,38 +10,35 @@ #include "MultiplayerDebugByteReporter.h" #include -#include #include #include #include -#include -#include +#include #include -namespace MultiplayerDiagnostics +namespace Multiplayer { /** * \brief GridMate network live analysis tool via ImGui. */ class MultiplayerDebugPerEntityReporter - : public AZ::Interface::Registrar { public: MultiplayerDebugPerEntityReporter(); - ~MultiplayerDebugPerEntityReporter() override; + ~MultiplayerDebugPerEntityReporter(); // main update loop void OnImGuiUpdate(); - //! MultilayerIPerEntityStats + //! Event handlers // @{ - void RecordEntitySerializeStart(AzNetworking::SerializerMode mode, AZ::EntityId entityId, const char* entityName) override; - void RecordComponentSerializeEnd(AzNetworking::SerializerMode mode, Multiplayer::NetComponentId netComponentId) override; - void RecordEntitySerializeStop(AzNetworking::SerializerMode mode, AZ::EntityId entityId, const char* entityName) override; - void RecordPropertySent(Multiplayer::NetComponentId netComponentId, Multiplayer::PropertyIndex propertyId, uint32_t totalBytes) override; - void RecordPropertyReceived(Multiplayer::NetComponentId netComponentId, Multiplayer::PropertyIndex propertyId, uint32_t totalBytes) override; - void RecordRpcSent(Multiplayer::NetComponentId netComponentId, Multiplayer::RpcIndex rpcId, uint32_t totalBytes) override; - void RecordRpcReceived(Multiplayer::NetComponentId netComponentId, Multiplayer::RpcIndex rpcId, uint32_t totalBytes) override; + void RecordEntitySerializeStart(AzNetworking::SerializerMode mode, AZ::EntityId entityId, const char* entityName); + void RecordComponentSerializeEnd(AzNetworking::SerializerMode mode, Multiplayer::NetComponentId netComponentId); + void RecordEntitySerializeStop(AzNetworking::SerializerMode mode, AZ::EntityId entityId, const char* entityName); + void RecordPropertySent(Multiplayer::NetComponentId netComponentId, Multiplayer::PropertyIndex propertyId, uint32_t totalBytes); + void RecordPropertyReceived(Multiplayer::NetComponentId netComponentId, Multiplayer::PropertyIndex propertyId, uint32_t totalBytes); + void RecordRpcSent(AZ::EntityId entityId, const char* entityName, Multiplayer::NetComponentId netComponentId, Multiplayer::RpcIndex rpcId, uint32_t totalBytes); + void RecordRpcReceived(AZ::EntityId entityId, const char* entityName, Multiplayer::NetComponentId netComponentId, Multiplayer::RpcIndex rpcId, uint32_t totalBytes); // }@ void UpdateDebugOverlay(); @@ -49,12 +46,13 @@ namespace MultiplayerDiagnostics private: AZ::ScheduledEvent m_updateDebugOverlay; + Multiplayer::MultiplayerStats::EventHandlers m_eventHandlers; - AZStd::map m_sendingEntityReports{}; - EntityReporter m_currentSendingEntityReport; + AZStd::map m_sendingEntityReports{}; + MultiplayerDebugEntityReporter m_currentSendingEntityReport; - AZStd::map m_receivingEntityReports{}; - EntityReporter m_currentReceivingEntityReport; + AZStd::map m_receivingEntityReports{}; + MultiplayerDebugEntityReporter m_currentReceivingEntityReport; float m_replicatedStateKbpsWarn = 10.f; float m_replicatedStateMaxSizeWarn = 30.f; diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.cpp b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.cpp index 835aae0d72..03d79025f7 100644 --- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.cpp @@ -55,7 +55,7 @@ namespace Multiplayer void MultiplayerDebugSystemComponent::OnImGuiInitialize() { - m_reporter = AZStd::make_unique(); + m_reporter = AZStd::make_unique(); } #ifdef IMGUI_ENABLED @@ -65,7 +65,7 @@ namespace Multiplayer { ImGui::Checkbox("Networking Stats", &m_displayNetworkingStats); ImGui::Checkbox("Multiplayer Stats", &m_displayMultiplayerStats); - ImGui::Checkbox("Multiplayer Per Entity Stats", &m_displayPerEntityStats); + ImGui::Checkbox("Multiplayer Entity Stats", &m_displayPerEntityStats); ImGui::EndMenu(); } } diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.h b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.h index 4972ec6bdf..a7f76e075a 100644 --- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.h +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.h @@ -53,6 +53,6 @@ namespace Multiplayer bool m_displayMultiplayerStats = false; bool m_displayPerEntityStats = false; - AZStd::unique_ptr m_reporter; + AZStd::unique_ptr m_reporter; }; } diff --git a/Gems/Multiplayer/Code/Source/MultiplayerStats.cpp b/Gems/Multiplayer/Code/Source/MultiplayerStats.cpp index 05be869872..7e56cd34f3 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerStats.cpp +++ b/Gems/Multiplayer/Code/Source/MultiplayerStats.cpp @@ -6,7 +6,6 @@ * */ -#include #include namespace Multiplayer @@ -32,86 +31,65 @@ namespace Multiplayer void MultiplayerStats::RecordEntitySerializeStart(AzNetworking::SerializerMode mode, AZ::EntityId entityId, const char* entityName) { - if (auto* perEntityStats = AZ::Interface::Get()) - { - perEntityStats->RecordEntitySerializeStart(mode, entityId, entityName); - } + m_events.m_entitySerializeStart.Signal(mode, entityId, entityName); } void MultiplayerStats::RecordComponentSerializeEnd(AzNetworking::SerializerMode mode, NetComponentId netComponentId) { - if (auto* perEntityStats = AZ::Interface::Get()) - { - perEntityStats->RecordComponentSerializeEnd(mode, netComponentId); - } + m_events.m_componentSerializeEnd.Signal(mode, netComponentId); } void MultiplayerStats::RecordEntitySerializeStop(AzNetworking::SerializerMode mode, AZ::EntityId entityId, const char* entityName) { - if (auto* perEntityStats = AZ::Interface::Get()) - { - perEntityStats->RecordEntitySerializeStop(mode, entityId, entityName); - } + m_events.m_entitySerializeStop.Signal(mode, entityId, entityName); } void MultiplayerStats::RecordPropertySent(NetComponentId netComponentId, PropertyIndex propertyId, uint32_t totalBytes) { - if (auto* perEntityStats = AZ::Interface::Get()) - { - perEntityStats->RecordPropertySent(netComponentId, propertyId, totalBytes); - } - const uint16_t netComponentIndex = aznumeric_cast(netComponentId); const uint16_t propertyIndex = aznumeric_cast(propertyId); m_componentStats[netComponentIndex].m_propertyUpdatesSent[propertyIndex].m_totalCalls++; m_componentStats[netComponentIndex].m_propertyUpdatesSent[propertyIndex].m_totalBytes += totalBytes; m_componentStats[netComponentIndex].m_propertyUpdatesSent[propertyIndex].m_callHistory[m_recordMetricIndex]++; m_componentStats[netComponentIndex].m_propertyUpdatesSent[propertyIndex].m_byteHistory[m_recordMetricIndex] += totalBytes; + + m_events.m_propertySent.Signal(netComponentId, propertyId, totalBytes); } void MultiplayerStats::RecordPropertyReceived(NetComponentId netComponentId, PropertyIndex propertyId, uint32_t totalBytes) { - if (auto* perEntityStats = AZ::Interface::Get()) - { - perEntityStats->RecordPropertyReceived(netComponentId, propertyId, totalBytes); - } - const uint16_t netComponentIndex = aznumeric_cast(netComponentId); const uint16_t propertyIndex = aznumeric_cast(propertyId); m_componentStats[netComponentIndex].m_propertyUpdatesRecv[propertyIndex].m_totalCalls++; m_componentStats[netComponentIndex].m_propertyUpdatesRecv[propertyIndex].m_totalBytes += totalBytes; m_componentStats[netComponentIndex].m_propertyUpdatesRecv[propertyIndex].m_callHistory[m_recordMetricIndex]++; m_componentStats[netComponentIndex].m_propertyUpdatesRecv[propertyIndex].m_byteHistory[m_recordMetricIndex] += totalBytes; + + m_events.m_propertyReceived.Signal(netComponentId, propertyId, totalBytes); } - void MultiplayerStats::RecordRpcSent(NetComponentId netComponentId, RpcIndex rpcId, uint32_t totalBytes) + void MultiplayerStats::RecordRpcSent(AZ::EntityId entityId, const char* entityName, NetComponentId netComponentId, RpcIndex rpcId, uint32_t totalBytes) { - if (auto* perEntityStats = AZ::Interface::Get()) - { - perEntityStats->RecordRpcSent(netComponentId, rpcId, totalBytes); - } - const uint16_t netComponentIndex = aznumeric_cast(netComponentId); const uint16_t rpcIndex = aznumeric_cast(rpcId); m_componentStats[netComponentIndex].m_rpcsSent[rpcIndex].m_totalCalls++; m_componentStats[netComponentIndex].m_rpcsSent[rpcIndex].m_totalBytes += totalBytes; m_componentStats[netComponentIndex].m_rpcsSent[rpcIndex].m_callHistory[m_recordMetricIndex]++; m_componentStats[netComponentIndex].m_rpcsSent[rpcIndex].m_byteHistory[m_recordMetricIndex] += totalBytes; + + m_events.m_rpcSent.Signal(entityId, entityName, netComponentId, rpcId, totalBytes); } - void MultiplayerStats::RecordRpcReceived(NetComponentId netComponentId, RpcIndex rpcId, uint32_t totalBytes) + void MultiplayerStats::RecordRpcReceived(AZ::EntityId entityId, const char* entityName, NetComponentId netComponentId, RpcIndex rpcId, uint32_t totalBytes) { - if (auto* perEntityStats = AZ::Interface::Get()) - { - perEntityStats->RecordRpcReceived(netComponentId, rpcId, totalBytes); - } - const uint16_t netComponentIndex = aznumeric_cast(netComponentId); const uint16_t rpcIndex = aznumeric_cast(rpcId); m_componentStats[netComponentIndex].m_rpcsRecv[rpcIndex].m_totalCalls++; m_componentStats[netComponentIndex].m_rpcsRecv[rpcIndex].m_totalBytes += totalBytes; m_componentStats[netComponentIndex].m_rpcsRecv[rpcIndex].m_callHistory[m_recordMetricIndex]++; m_componentStats[netComponentIndex].m_rpcsRecv[rpcIndex].m_byteHistory[m_recordMetricIndex] += totalBytes; + + m_events.m_rpcReceived.Signal(entityId, entityName, netComponentId, rpcId, totalBytes); } void MultiplayerStats::TickStats(AZ::TimeMs metricFrameTimeMs) @@ -231,4 +209,15 @@ namespace Multiplayer } return result; } + + void MultiplayerStats::ConnectHandlers(EventHandlers& handlers) + { + handlers.m_entitySerializeStart.Connect(m_events.m_entitySerializeStart); + handlers.m_componentSerializeEnd.Connect(m_events.m_componentSerializeEnd); + handlers.m_entitySerializeStop.Connect(m_events.m_entitySerializeStop); + handlers.m_propertySent.Connect(m_events.m_propertySent); + handlers.m_propertyReceived.Connect(m_events.m_propertyReceived); + handlers.m_rpcSent.Connect(m_events.m_rpcSent); + handlers.m_rpcReceived.Connect(m_events.m_rpcReceived); + } } diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicator.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicator.cpp index 2afadbe4a4..457ed3eed5 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicator.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicator.cpp @@ -443,12 +443,8 @@ namespace Multiplayer { // Received rpc metrics, log rpc sent, number of bytes, and the componentId/rpcId for bandwidth metrics MultiplayerStats& stats = GetMultiplayer()->GetStats(); - stats.RecordEntitySerializeStart(AzNetworking::SerializerMode::ReadFromObject, - GetEntityHandle().GetEntity()->GetId(), GetEntityHandle().GetEntity()->GetName().c_str()); - stats.RecordRpcSent(entityRpcMessage.GetComponentId(), entityRpcMessage.GetRpcIndex(), entityRpcMessage.GetEstimatedSerializeSize()); - stats.RecordComponentSerializeEnd(AzNetworking::SerializerMode::ReadFromObject, entityRpcMessage.GetComponentId()); - stats.RecordEntitySerializeStop(AzNetworking::SerializerMode::ReadFromObject, - GetEntityHandle().GetEntity()->GetId(), GetEntityHandle().GetEntity()->GetName().c_str()); + stats.RecordRpcSent(GetEntityHandle().GetEntity()->GetId(), GetEntityHandle().GetEntity()->GetName().c_str(), + entityRpcMessage.GetComponentId(), entityRpcMessage.GetRpcIndex(), entityRpcMessage.GetEstimatedSerializeSize()); m_replicationManager.AddDeferredRpcMessage(entityRpcMessage); } @@ -631,7 +627,8 @@ namespace Multiplayer { // Received rpc metrics, log rpc received, time spent, number of bytes, and the componentId/rpcId for bandwidth metrics MultiplayerStats& stats = GetMultiplayer()->GetStats(); - stats.RecordRpcReceived(entityRpcMessage.GetComponentId(), entityRpcMessage.GetRpcIndex(), entityRpcMessage.GetEstimatedSerializeSize()); + stats.RecordRpcReceived(GetEntityHandle().GetEntity()->GetId(), GetEntityHandle().GetEntity()->GetName().c_str(), + entityRpcMessage.GetComponentId(), entityRpcMessage.GetRpcIndex(), entityRpcMessage.GetEstimatedSerializeSize()); if (!m_netBindComponent) { diff --git a/Gems/Multiplayer/Code/multiplayer_debug_files.cmake b/Gems/Multiplayer/Code/multiplayer_debug_files.cmake index d333269a1d..37a1c91640 100644 --- a/Gems/Multiplayer/Code/multiplayer_debug_files.cmake +++ b/Gems/Multiplayer/Code/multiplayer_debug_files.cmake @@ -9,7 +9,6 @@ set(FILES Source/Debug/MultiplayerDebugByteReporter.cpp Source/Debug/MultiplayerDebugByteReporter.h - Source/Debug/MultiplayerDebugPerEntityInterface.h Source/Debug/MultiplayerDebugPerEntityReporter.cpp Source/Debug/MultiplayerDebugPerEntityReporter.h Source/Debug/MultiplayerDebugModule.cpp From e80931185bc0aab051eca321f3b602dca1e5e0d6 Mon Sep 17 00:00:00 2001 From: Benjamin Jillich Date: Wed, 28 Jul 2021 15:59:11 +0200 Subject: [PATCH 035/803] Ported RenderPlugin from MCore::AABB to AZ::AaBB * Containing functionality verified. * Zoom to joints * Normals scale multiplier * View closeup * Calculating the scene aabb * Rendering the actor instance aabbs * Selection aabb Signed-off-by: Benjamin Jillich --- .../Source/RenderPlugin/RenderPlugin.cpp | 80 +++++++++---------- .../Source/RenderPlugin/RenderPlugin.h | 2 +- 2 files changed, 41 insertions(+), 41 deletions(-) diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.cpp index 182314f2a6..ab219b2b92 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.cpp @@ -266,8 +266,7 @@ namespace EMStudio return; } - MCore::AABB aabb; - aabb.Init(); + AZ::Aabb aabb = AZ::Aabb::CreateNull(); const EMotionFX::Actor* actor = actorInstance->GetActor(); const EMotionFX::Skeleton* skeleton = actor->GetSkeleton(); @@ -276,21 +275,20 @@ namespace EMStudio for (const EMotionFX::Node* joint : joints) { const AZ::Vector3 jointPosition = pose->GetWorldSpaceTransform(joint->GetNodeIndex()).mPosition; - - aabb.Encapsulate(jointPosition); + aabb.AddPoint(jointPosition); const AZ::u32 childCount = joint->GetNumChildNodes(); for (AZ::u32 i = 0; i < childCount; ++i) { EMotionFX::Node* childJoint = skeleton->GetNode(joint->GetChildIndex(i)); const AZ::Vector3 childPosition = pose->GetWorldSpaceTransform(childJoint->GetNodeIndex()).mPosition; - aabb.Encapsulate(childPosition); + aabb.AddPoint(childPosition); } } - if (aabb.CheckIfIsValid()) + if (aabb.IsValid()) { - aabb.Widen(aabb.CalcRadius()); + aabb.Expand(AZ::Vector3(aabb.GetExtents().GetLength() * 0.5f)); bool isFollowModeActive = false; for (const RenderViewWidget* viewWidget : m_viewWidgets) @@ -619,35 +617,30 @@ namespace EMStudio EMotionFX::ActorInstance* actorInstance = EMotionFX::ActorInstance::Create(mActor); actorInstance->UpdateMeshDeformers(0.0f, true); - MCore::AABB aabb; - actorInstance->CalcMeshBasedAABB(0, &aabb); + AZ::Aabb aabb; + actorInstance->CalcMeshBasedAabb(0, &aabb); - if (aabb.CheckIfIsValid() == false) + if (!aabb.IsValid()) { - actorInstance->CalcNodeOBBBasedAABB(&aabb); + actorInstance->CalcNodeBasedAabb(&aabb); } - if (aabb.CheckIfIsValid() == false) - { - actorInstance->CalcNodeBasedAABB(&aabb); - } - - mCharacterHeight = aabb.CalcHeight(); + mCharacterHeight = aabb.GetExtents().GetZ(); mOffsetFromTrajectoryNode = aabb.GetMin().GetY() + (mCharacterHeight * 0.5f); actorInstance->Destroy(); // scale the normals down to 1% of the character size, that looks pretty nice on all models - mNormalsScaleMultiplier = aabb.CalcRadius() * 0.01f; + const float radius = AZ::Vector3(aabb.GetMax() - aabb.GetMin()).GetLength() * 0.5f; + mNormalsScaleMultiplier = radius * 0.01f; } // zoom to characters void RenderPlugin::ViewCloseup(bool selectedInstancesOnly, RenderWidget* renderWidget, float flightTime) { - const MCore::AABB sceneAABB = GetSceneAABB(selectedInstancesOnly); - - if (sceneAABB.CheckIfIsValid()) + const AZ::Aabb sceneAabb = GetSceneAabb(selectedInstancesOnly); + if (sceneAabb.IsValid()) { // in case the given view widget parameter is nullptr apply it on all view widgets if (!renderWidget) @@ -655,13 +648,13 @@ namespace EMStudio for (RenderViewWidget* viewWidget : m_viewWidgets) { RenderWidget* current = viewWidget->GetRenderWidget(); - current->ViewCloseup(sceneAABB, flightTime); + current->ViewCloseup(sceneAabb, flightTime); } } // only apply it to the given view widget else { - renderWidget->ViewCloseup(sceneAABB, flightTime); + renderWidget->ViewCloseup(sceneAabb, flightTime); } } } @@ -882,9 +875,9 @@ namespace EMStudio // get the AABB containing all actor instances in the scene - MCore::AABB RenderPlugin::GetSceneAABB(bool selectedInstancesOnly) + AZ::Aabb RenderPlugin::GetSceneAabb(bool selectedInstancesOnly) { - MCore::AABB finalAABB; + AZ::Aabb finalAabb = AZ::Aabb::CreateNull(); CommandSystem::SelectionList& selection = GetCommandManager()->GetCurrentSelection(); if (mUpdateCallback) @@ -922,20 +915,28 @@ namespace EMStudio } // get the mesh based AABB - MCore::AABB aabb; - actorInstance->CalcMeshBasedAABB(0, &aabb); + AZ::Aabb aabb; + actorInstance->CalcMeshBasedAabb(0, &aabb); // get the node based AABB - if (aabb.CheckIfIsValid() == false) + if (!aabb.IsValid()) { - actorInstance->CalcNodeBasedAABB(&aabb); + actorInstance->CalcNodeBasedAabb(&aabb); } // make sure the actor instance is covered in our global bounding box - finalAABB.Encapsulate(aabb); + if (aabb.IsValid()) + { + finalAabb.AddAabb(aabb); + } } - return finalAABB; + if (!finalAabb.IsValid()) + { + finalAabb.Set(AZ::Vector3(-1.0f, -1.0f, 0.0f), AZ::Vector3(1.0f, 1.0f, 0.0f)); + } + + return finalAabb; } @@ -1155,9 +1156,8 @@ namespace EMStudio settings.mNodeBasedColor = renderOptions->GetNodeAABBColor(); settings.mStaticBasedColor = renderOptions->GetStaticAABBColor(); settings.mMeshBasedColor = renderOptions->GetMeshAABBColor(); - settings.mCollisionMeshBasedColor = renderOptions->GetCollisionMeshAABBColor(); - renderUtil->RenderAABBs(actorInstance, settings); + renderUtil->RenderAabbs(actorInstance, settings); } if (widget->GetRenderFlag(RenderViewWidget::RENDER_OBB)) @@ -1169,10 +1169,10 @@ namespace EMStudio const MCommon::Camera* camera = widget->GetRenderWidget()->GetCamera(); const AZ::Vector3& cameraPos = camera->GetPosition(); - MCore::AABB aabb; - actorInstance->CalcNodeBasedAABB(&aabb); - const AZ::Vector3 aabbMid = aabb.CalcMiddle(); - const float aabbRadius = aabb.CalcRadius(); + AZ::Aabb aabb; + actorInstance->CalcNodeBasedAabb(&aabb); + const AZ::Vector3 aabbMid = aabb.GetCenter(); + const float aabbRadius = AZ::Vector3(aabb.GetMax() - aabb.GetMin()).GetLength() * 0.5f; const float camDistance = fabs((cameraPos - aabbMid).GetLength()); // Avoid rendering too big joint spheres when zooming in onto a joint. @@ -1185,7 +1185,7 @@ namespace EMStudio // Scale the joint spheres based on the character's extents, to avoid really large joint spheres // on small characters and too small spheres on large characters. static const float baseRadius = 0.005f; - const float jointSphereRadius = aabb.CalcRadius() * scaleMultiplier * baseRadius; + const float jointSphereRadius = aabbRadius * scaleMultiplier * baseRadius; renderUtil->RenderSimpleSkeleton(actorInstance, &visibleJointIndices, &selectedJointIndices, renderOptions->GetLineSkeletonColor(), renderOptions->GetSelectedObjectColor(), jointSphereRadius); @@ -1268,8 +1268,8 @@ namespace EMStudio // render the selection if (renderOptions->GetRenderSelectionBox() && EMotionFX::GetActorManager().GetNumActorInstances() != 1 && GetCurrentSelection()->CheckIfHasActorInstance(actorInstance)) { - MCore::AABB aabb = actorInstance->GetAABB(); - aabb.Widen(aabb.CalcRadius() * 0.005f); + AZ::Aabb aabb = actorInstance->GetAabb(); + aabb.Expand(AZ::Vector3(0.005f)); renderUtil->RenderSelection(aabb, renderOptions->GetSelectionColor()); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.h index 68cabbefa3..7fa0a880d0 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.h @@ -154,7 +154,7 @@ namespace EMStudio MCORE_INLINE CommandSystem::SelectionList* GetCurrentSelection() const { return mCurrentSelection; } MCORE_INLINE MCommon::RenderUtil* GetRenderUtil() const { return mRenderUtil; } - MCore::AABB GetSceneAABB(bool selectedInstancesOnly); + AZ::Aabb GetSceneAabb(bool selectedInstancesOnly); MCommon::RenderUtil::TrajectoryTracePath* FindTracePath(EMotionFX::ActorInstance* actorInstance); void ResetSelectedTrajectoryPaths(); From 9c72510a4fb6dc10cba848752b1e788a19830d0f Mon Sep 17 00:00:00 2001 From: pappeste Date: Wed, 23 Jun 2021 14:52:30 -0700 Subject: [PATCH 036/803] removing files that got added by rebase MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> (+1 squashed commits) Squashed commits: [a19269426] fixing more strings Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> (+1 squashed commits) Squashed commits: [d2a049324] fixing more strings Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> (+1 squashed commits) Squashed commits: [a1ff4c101] trying to build Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Editor/CryEdit.cpp | 3 - Code/Editor/Export/ExportManager.cpp | 4 +- .../Plugins/FFMPEGPlugin/FFMPEGPlugin.cpp | 2 - Code/Editor/Util/PathUtil.h | 6 +- Code/Editor/Util/StringHelpers.cpp | 120 - Code/Editor/Util/StringHelpers.h | 15 - Code/LauncherUnified/Launcher.h | 3 - Code/Legacy/CryCommon/CryArray.h | 13 +- Code/Legacy/CryCommon/CryCustomTypes.h | 46 +- Code/Legacy/CryCommon/CryFile.h | 11 +- Code/Legacy/CryCommon/CryFixedString.h | 2337 --------------- Code/Legacy/CryCommon/CryListenerSet.h | 2 +- Code/Legacy/CryCommon/CryName.h | 16 +- Code/Legacy/CryCommon/CryPath.h | 139 +- Code/Legacy/CryCommon/CrySizer.h | 6 +- Code/Legacy/CryCommon/CryString.h | 2523 ----------------- Code/Legacy/CryCommon/CryThread_windows.h | 2 +- Code/Legacy/CryCommon/CryTypeInfo.cpp | 81 +- Code/Legacy/CryCommon/CryTypeInfo.h | 9 +- Code/Legacy/CryCommon/IEntityRenderState.h | 2 +- Code/Legacy/CryCommon/IFont.h | 7 +- Code/Legacy/CryCommon/IRenderer.h | 3 +- Code/Legacy/CryCommon/ISerialize.h | 120 +- Code/Legacy/CryCommon/IShader.h | 37 +- Code/Legacy/CryCommon/ISystem.h | 2 +- Code/Legacy/CryCommon/IXml.h | 4 +- Code/Legacy/CryCommon/Linux_Win32Wrapper.h | 3 - Code/Legacy/CryCommon/LyShine/UiBase.h | 1 - .../CryCommon/LyShine/UiSerializeHelpers.h | 148 - Code/Legacy/CryCommon/StlUtils.h | 2 +- Code/Legacy/CryCommon/StringUtils.h | 1358 --------- Code/Legacy/CryCommon/TypeInfo_decl.h | 5 +- Code/Legacy/CryCommon/UnicodeBinding.h | 58 +- Code/Legacy/CryCommon/WinBase.cpp | 2 +- Code/Legacy/CryCommon/crycommon_files.cmake | 3 - Code/Legacy/CryCommon/platform.h | 9 - Code/Legacy/CryCommon/platform_impl.cpp | 6 +- Code/Legacy/CrySystem/CmdLine.cpp | 20 +- Code/Legacy/CrySystem/DebugCallStack.cpp | 22 +- .../CrySystem/LevelSystem/LevelSystem.cpp | 2 +- .../CrySystem/LocalizedStringManager.cpp | 18 +- Code/Legacy/CrySystem/Log.cpp | 6 +- Code/Legacy/CrySystem/Log.h | 2 +- Code/Legacy/CrySystem/System.cpp | 2 +- Code/Legacy/CrySystem/SystemWin32.cpp | 12 +- Code/Legacy/CrySystem/XConsole.cpp | 2 +- Code/Legacy/CrySystem/XConsole.h | 42 +- .../CrySystem/XML/SerializeXMLReader.cpp | 4 +- .../Legacy/CrySystem/XML/SerializeXMLReader.h | 8 +- Code/Legacy/CrySystem/XML/XMLBinaryReader.cpp | 2 +- Code/Legacy/CrySystem/XML/XMLBinaryWriter.cpp | 16 +- Code/Legacy/CrySystem/XML/XMLPatcher.cpp | 6 +- Code/Legacy/CrySystem/XML/XMLPatcher.h | 2 +- Code/Legacy/CrySystem/XML/xml.cpp | 8 +- .../AtomLyIntegration/AtomFont/FFont.h | 1 - .../Platform/Windows/FFontXML_Windows.cpp | 2 +- .../Components/BlastSystemComponent.cpp | 2 - Gems/LmbrCentral/Code/Source/LmbrCentral.cpp | 8 +- .../Code/Editor/Animation/UiAnimViewNodes.cpp | 2 +- .../Code/Editor/PropertyHandlerChar.cpp | 3 +- .../Code/Source/LyShineSystemComponent.h | 4 +- .../Platform/Windows/UiClipboard_Windows.cpp | 5 +- Gems/LyShine/Code/Source/StringUtfUtils.h | 3 +- .../LyShine/Code/Source/UiButtonComponent.cpp | 41 +- Gems/LyShine/Code/Source/UiImageComponent.cpp | 13 +- Gems/LyShine/Code/Source/UiSerialize.cpp | 64 - Gems/LyShine/Code/Source/UiTextComponent.cpp | 22 +- .../Code/Source/UiTextInputComponent.cpp | 51 +- Gems/LyShine/Code/Tests/SerializationTest.cpp | 1 - Gems/LyShine/Code/Tests/SpriteTest.cpp | 1 - .../Code/Source/Cinematics/CaptureTrack.cpp | 2 +- .../Code/Source/Cinematics/CommentTrack.cpp | 2 +- .../Code/Source/Cinematics/EventTrack.cpp | 2 +- .../Code/Source/Cinematics/SceneNode.cpp | 2 +- .../Source/Cinematics/TrackEventTrack.cpp | 2 +- .../Code/Source/MaestroSystemComponent.h | 4 +- Gems/Metastream/Code/Tests/MetastreamTest.cpp | 2 - .../Code/Source/SystemComponent.cpp | 2 - 78 files changed, 330 insertions(+), 7193 deletions(-) delete mode 100644 Code/Legacy/CryCommon/CryFixedString.h delete mode 100644 Code/Legacy/CryCommon/CryString.h delete mode 100644 Code/Legacy/CryCommon/StringUtils.h diff --git a/Code/Editor/CryEdit.cpp b/Code/Editor/CryEdit.cpp index 4bfc6a319d..973a818b92 100644 --- a/Code/Editor/CryEdit.cpp +++ b/Code/Editor/CryEdit.cpp @@ -4150,15 +4150,12 @@ struct CryAllocatorsRAII CryAllocatorsRAII() { AZ_Assert(!AZ::AllocatorInstance::IsReady(), "Expected allocator to not be initialized, hunt down the static that is initializing it"); - AZ_Assert(!AZ::AllocatorInstance::IsReady(), "Expected allocator to not be initialized, hunt down the static that is initializing it"); AZ::AllocatorInstance::Create(); - AZ::AllocatorInstance::Create(); } ~CryAllocatorsRAII() { - AZ::AllocatorInstance::Destroy(); AZ::AllocatorInstance::Destroy(); } }; diff --git a/Code/Editor/Export/ExportManager.cpp b/Code/Editor/Export/ExportManager.cpp index 682dcf3980..03aa0bed8b 100644 --- a/Code/Editor/Export/ExportManager.cpp +++ b/Code/Editor/Export/ExportManager.cpp @@ -88,7 +88,7 @@ Export::CObject::CObject(const char* pName) nParent = -1; - cry_strcpy(name, pName); + azstrcpy(name, pName); materialName[0] = '\0'; @@ -102,7 +102,7 @@ Export::CObject::CObject(const char* pName) void Export::CObject::SetMaterialName(const char* pName) { - cry_strcpy(materialName, pName); + azstrcpy(materialName, pName); } diff --git a/Code/Editor/Plugins/FFMPEGPlugin/FFMPEGPlugin.cpp b/Code/Editor/Plugins/FFMPEGPlugin/FFMPEGPlugin.cpp index dd2a1d602a..630ab3eb8e 100644 --- a/Code/Editor/Plugins/FFMPEGPlugin/FFMPEGPlugin.cpp +++ b/Code/Editor/Plugins/FFMPEGPlugin/FFMPEGPlugin.cpp @@ -8,8 +8,6 @@ #include "FFMPEGPlugin.h" -#include "CryString.h" -typedef CryStringT string; #include "Include/ICommandManager.h" #include "Util/PathUtil.h" diff --git a/Code/Editor/Util/PathUtil.h b/Code/Editor/Util/PathUtil.h index 0f87df0d5c..98f484ec94 100644 --- a/Code/Editor/Util/PathUtil.h +++ b/Code/Editor/Util/PathUtil.h @@ -230,7 +230,7 @@ namespace Path } template - inline bool EndsWithSlash(CryStackStringT* path) + inline bool EndsWithSlash(AZStd::fixed_string* path) { if ((!path) || (path->empty())) { @@ -271,7 +271,7 @@ namespace Path } template - inline void AddBackslash(CryStackStringT* path) + inline void AddBackslash(AZstd::fixed_string* path) { if (path->empty()) { @@ -284,7 +284,7 @@ namespace Path } template - inline void AddSlash(CryStackStringT* path) + inline void AddSlash(AZstd::fixed_string* path) { if (path->empty()) { diff --git a/Code/Editor/Util/StringHelpers.cpp b/Code/Editor/Util/StringHelpers.cpp index 836090e923..a6bf622ad0 100644 --- a/Code/Editor/Util/StringHelpers.cpp +++ b/Code/Editor/Util/StringHelpers.cpp @@ -380,126 +380,6 @@ bool StringHelpers::ContainsIgnoreCase(const wstring& str, const wstring& patter return false; } -bool StringHelpers::MatchesWildcards(const string& str, const string& wildcards) -{ - using namespace CryStringUtils_Internal; - return MatchesWildcards_Tpl(str.c_str(), wildcards.c_str()); -} - -bool StringHelpers::MatchesWildcards(const wstring& str, const wstring& wildcards) -{ - using namespace CryStringUtils_Internal; - return MatchesWildcards_Tpl(str.c_str(), wildcards.c_str()); -} - -bool StringHelpers::MatchesWildcardsIgnoreCase(const string& str, const string& wildcards) -{ - using namespace CryStringUtils_Internal; - return MatchesWildcards_Tpl(str.c_str(), wildcards.c_str()); -} - -bool StringHelpers::MatchesWildcardsIgnoreCase(const wstring& str, const wstring& wildcards) -{ - using namespace CryStringUtils_Internal; - return MatchesWildcards_Tpl(str.c_str(), wildcards.c_str()); -} - - -template -static inline bool MatchesWildcardsIgnoreCaseExt_Tpl(const TS& str, const TS& wildcards, std::vector& wildcardMatches) -{ - const typename TS::value_type* savedStrBegin = 0; - const typename TS::value_type* savedStrEnd = 0; - const typename TS::value_type* savedWild = 0; - size_t savedWildCount = 0; - - const typename TS::value_type* pStr = str.c_str(); - const typename TS::value_type* pWild = wildcards.c_str(); - size_t wildCount = 0; - - while ((*pStr) && (*pWild != '*')) - { - if (*pWild == '?') - { - wildcardMatches.push_back(TS(pStr, pStr + 1)); - ++wildCount; - } - else if (ToLower(*pWild) != ToLower(*pStr)) - { - wildcardMatches.resize(wildcardMatches.size() - wildCount); - return false; - } - ++pWild; - ++pStr; - } - - while (*pStr) - { - if (*pWild == '*') - { - if (!pWild[1]) - { - wildcardMatches.push_back(TS(pStr)); - return true; - } - savedWild = pWild++; - savedStrBegin = pStr; - savedStrEnd = pStr; - savedWildCount = wildCount; - wildcardMatches.push_back(TS(savedStrBegin, savedStrEnd)); - ++wildCount; - } - else if (*pWild == '?') - { - wildcardMatches.push_back(TS(pStr, pStr + 1)); - ++wildCount; - ++pWild; - ++pStr; - } - else if (ToLower(*pWild) == ToLower(*pStr)) - { - ++pWild; - ++pStr; - } - else - { - wildcardMatches.resize(wildcardMatches.size() - (wildCount - savedWildCount)); - wildCount = savedWildCount; - ++savedStrEnd; - pWild = savedWild + 1; - pStr = savedStrEnd; - wildcardMatches.push_back(TS(savedStrBegin, savedStrEnd)); - ++wildCount; - } - } - - while (*pWild == '*') - { - ++pWild; - wildcardMatches.push_back(TS()); - ++wildCount; - } - - if (*pWild) - { - wildcardMatches.resize(wildcardMatches.size() - wildCount); - return false; - } - - return true; -} - -bool StringHelpers::MatchesWildcardsIgnoreCaseExt(const string& str, const string& wildcards, std::vector& wildcardMatches) -{ - return MatchesWildcardsIgnoreCaseExt_Tpl(str, wildcards, wildcardMatches); -} - -bool StringHelpers::MatchesWildcardsIgnoreCaseExt(const wstring& str, const wstring& wildcards, std::vector& wildcardMatches) -{ - return MatchesWildcardsIgnoreCaseExt_Tpl(str, wildcards, wildcardMatches); -} - - string StringHelpers::TrimLeft(const string& s) { const size_t first = s.find_first_not_of(" \r\t"); diff --git a/Code/Editor/Util/StringHelpers.h b/Code/Editor/Util/StringHelpers.h index c05063f207..da4aa9c9cc 100644 --- a/Code/Editor/Util/StringHelpers.h +++ b/Code/Editor/Util/StringHelpers.h @@ -11,8 +11,6 @@ #define CRYINCLUDE_CRYCOMMONTOOLS_STRINGHELPERS_H #pragma once -#include - namespace StringHelpers { // compares two strings to see if they are the same or different, case sensitive @@ -65,19 +63,6 @@ namespace StringHelpers bool ContainsIgnoreCase(const string& str, const string& pattern); bool ContainsIgnoreCase(const wstring& str, const wstring& pattern); - // checks to see if a string contains a wildcard string pattern, case sensitive - // returns true if the string does match the wildcard string pattern or false if it does not - bool MatchesWildcards(const string& str, const string& wildcards); - bool MatchesWildcards(const wstring& str, const wstring& wildcards); - - // checks to see if a string contains a wildcard string pattern, case is ignored - // returns true if the string does match the wildcard string pattern or false if it does not - bool MatchesWildcardsIgnoreCase(const string& str, const string& wildcards); - bool MatchesWildcardsIgnoreCase(const wstring& str, const wstring& wildcards); - - bool MatchesWildcardsIgnoreCaseExt(const string& str, const string& wildcards, std::vector& wildcardMatches); - bool MatchesWildcardsIgnoreCaseExt(const wstring& str, const wstring& wildcards, std::vector& wildcardMatches); - string TrimLeft(const string& s); wstring TrimLeft(const wstring& s); diff --git a/Code/LauncherUnified/Launcher.h b/Code/LauncherUnified/Launcher.h index e0b3abdf95..5ff6009e43 100644 --- a/Code/LauncherUnified/Launcher.h +++ b/Code/LauncherUnified/Launcher.h @@ -21,15 +21,12 @@ namespace O3DELauncher CryAllocatorsRAII() { AZ_Assert(!AZ::AllocatorInstance::IsReady(), "Expected allocator to not be initialized, hunt down the static that is initializing it"); - AZ_Assert(!AZ::AllocatorInstance::IsReady(), "Expected allocator to not be initialized, hunt down the static that is initializing it"); AZ::AllocatorInstance::Create(); - AZ::AllocatorInstance::Create(); } ~CryAllocatorsRAII() { - AZ::AllocatorInstance::Destroy(); AZ::AllocatorInstance::Destroy(); } }; diff --git a/Code/Legacy/CryCommon/CryArray.h b/Code/Legacy/CryCommon/CryArray.h index 167f1cfb57..8b0cea3de6 100644 --- a/Code/Legacy/CryCommon/CryArray.h +++ b/Code/Legacy/CryCommon/CryArray.h @@ -12,6 +12,7 @@ #pragma once #include "CryLegacyAllocator.h" +#include //--------------------------------------------------------------------------- // Convenient iteration macros @@ -58,18 +59,6 @@ struct fake_move_helper } }; -// Override for string to ensure proper construction -template <> -struct fake_move_helper -{ - static void move(string& dest, string& source) - { - ::new((void*)&dest) string(); - dest = source; - source.~string(); - } -}; - // Generic move function: transfer an existing source object to uninitialized dest address. // Addresses must not overlap (requirement on caller). // May be specialized for specific types, to provide a more optimal move. diff --git a/Code/Legacy/CryCommon/CryCustomTypes.h b/Code/Legacy/CryCommon/CryCustomTypes.h index 9594f5a333..74f3cbc9dc 100644 --- a/Code/Legacy/CryCommon/CryCustomTypes.h +++ b/Code/Legacy/CryCommon/CryCustomTypes.h @@ -16,10 +16,10 @@ #pragma once #include "CryTypeInfo.h" -#include "CryFixedString.h" #include #include #include +#include #define STATIC_CONST(T, name, val) \ static inline T name() { static T t = val; return t; } @@ -46,7 +46,7 @@ inline bool HasString(const T& val, FToString flags, const void* def_data = 0) float NumToFromString(float val, int digits, bool floating, char buffer[], int buf_size); template -string NumToString(T val, int min_digits, int max_digits, bool floating) +AZStd::string NumToString(T val, int min_digits, int max_digits, bool floating) { char buffer[64]; float f(val); @@ -68,7 +68,7 @@ struct CStructInfo { CStructInfo(cstr name, size_t size, size_t align, Array vars = Array(), Array templates = Array()); virtual bool IsType(CTypeInfo const& Info) const; - virtual string ToString(const void* data, FToString flags = 0, const void* def_data = 0) const; + virtual AZStd::string ToString(const void* data, FToString flags = 0, const void* def_data = 0) const; virtual bool FromString(void* data, cstr str, FFromString flags = 0) const; virtual bool ToValue(const void* data, void* value, const CTypeInfo& typeVal) const; virtual bool FromValue(void* data, const void* value, const CTypeInfo& typeVal) const; @@ -86,9 +86,9 @@ struct CStructInfo } protected: - Array Vars; - CryStackStringT EndianDesc; // Encodes instructions for endian swapping. - bool HasBitfields; + Array Vars; + AZStd::fixed_string<16> EndianDesc; // Encodes instructions for endian swapping. + bool HasBitfields; Array TemplateTypes; void MakeEndianDesc(); @@ -124,11 +124,11 @@ struct TTypeInfo return false; } - virtual string ToString(const void* data, FToString flags = 0, const void* def_data = 0) const + virtual AZStd::string ToString(const void* data, FToString flags = 0, const void* def_data = 0) const { if (!HasString(*(const T*)data, flags, def_data)) { - return string(); + return AZStd::string(); } return ::ToString(*(const T*)data); } @@ -193,7 +193,7 @@ struct TProxyTypeInfo return false; } - virtual string ToString(const void* data, FToString flags = 0, const void* def_data = 0) const + virtual AZStd::string ToString(const void* data, FToString flags = 0, const void* def_data = 0) const { T val = T(*(const S*)data); T def_val = def_data ? T(*(const S*)def_data) : T(); @@ -234,32 +234,32 @@ protected: // Customisation for string. template<> -inline string TTypeInfo::ToString(const void* data, FToString flags, const void* def_data) const +inline AZStd::string TTypeInfo::ToString(const void* data, FToString flags, const void* def_data) const { - const string& val = *(const string*)data; + const AZStd::string& val = *(const AZStd::string*)data; if (def_data && flags.SkipDefault) { - if (val == *(const string*)def_data) + if (val == *(const AZStd::string*)def_data) { - return string(); + return AZStd::string(); } } return val; } template<> -inline bool TTypeInfo::FromString(void* data, cstr str, FFromString flags) const +inline bool TTypeInfo::FromString(void* data, cstr str, FFromString flags) const { if (!*str && flags.SkipEmpty) { return true; } - *(string*)data = str; + *(AZStd::string*)data = str; return true; } template<> -void TTypeInfo::GetMemoryUsage(ICrySizer* pSizer, void const* data) const; +void TTypeInfo::GetMemoryUsage(ICrySizer* pSizer, void const* data) const; //--------------------------------------------------------------------------- // @@ -632,11 +632,11 @@ protected: } // Override ToString: Limit to significant digits. - virtual string ToString(const void* data, FToString flags = 0, const void* def_data = 0) const + virtual AZStd::string ToString(const void* data, FToString flags = 0, const void* def_data = 0) const { if (!HasString(*(const S*)data, flags, def_data)) { - return string(); + return AZStd::string(); } static int digits = int_ceil(log10f(float(nQUANT))); return NumToString(*(const TFixed*)data, 1, digits + 3, true); @@ -907,12 +907,12 @@ struct TEnumInfo return false; } - virtual string ToString(const void* data, FToString flags, const void* def_data) const + virtual AZStd::string ToString(const void* data, FToString flags, const void* def_data) const { TInt val = *(const TInt*)(data); if (flags.SkipDefault && val == (def_data ? *(const TInt*)def_data : TInt(0))) { - return string(); + return AZStd::string(); } if (cstr sName = TEnumDef::ToName(val)) @@ -1153,13 +1153,13 @@ struct CEnumDefUuid return false; } - string ToString(const void* data, FToString flags, const void* def_data) const override + AZStd::string ToString(const void* data, FToString flags, const void* def_data) const override { const AZ::Uuid& uuidData = *reinterpret_cast(data); const AZ::Uuid& defUuidData = *reinterpret_cast(def_data); if (flags.SkipDefault && uuidData == (def_data ? defUuidData : AZ::Uuid::CreateNull())) { - return string(); + return AZStd::string(); } if (cstr sName = ToName(uuidData)) @@ -1167,7 +1167,7 @@ struct CEnumDefUuid return sName; } - return string(); + return AZStd::string(); } bool FromString(void* data, cstr str, FFromString flags) const override diff --git a/Code/Legacy/CryCommon/CryFile.h b/Code/Legacy/CryCommon/CryFile.h index a043e4fa9b..0888216f9c 100644 --- a/Code/Legacy/CryCommon/CryFile.h +++ b/Code/Legacy/CryCommon/CryFile.h @@ -18,7 +18,6 @@ #include #include #include -#include "StringUtils.h" #include ////////////////////////////////////////////////////////////////////////// @@ -222,7 +221,7 @@ inline CCryFile::~CCryFile() inline bool CCryFile::Open(const char* filename, const char* mode, int nOpenFlagsEx) { char tempfilename[CRYFILE_MAX_PATH] = ""; - cry_strcpy(tempfilename, filename); + azstrcpy(tempfilename, filename); #if !defined (_RELEASE) if (gEnv && gEnv->IsEditor() && gEnv->pConsole) @@ -233,8 +232,8 @@ inline bool CCryFile::Open(const char* filename, const char* mode, int nOpenFlag const int lowercasePaths = pCvar->GetIVal(); if (lowercasePaths) { - const string lowerString = PathUtil::ToLower(tempfilename); - cry_strcpy(tempfilename, lowerString.c_str()); + const AZStd::string lowerString = PathUtil::ToLower(tempfilename); + azstrcpy(tempfilename, lowerString.c_str()); } } } @@ -243,7 +242,7 @@ inline bool CCryFile::Open(const char* filename, const char* mode, int nOpenFlag { Close(); } - cry_strcpy(m_filename, tempfilename); + azstrcpy(m_filename, tempfilename); if (m_pIArchive) { @@ -430,7 +429,7 @@ inline const char* CCryFile::GetAdjustedFilename() const // Returns standard path otherwise. if (gameUrl != &szAdjustedFile[0]) { - cry_strcpy(szAdjustedFile, gameUrl); + azstrcpy(szAdjustedFile, gameUrl); } return szAdjustedFile; } diff --git a/Code/Legacy/CryCommon/CryFixedString.h b/Code/Legacy/CryCommon/CryFixedString.h deleted file mode 100644 index 299a5718a7..0000000000 --- a/Code/Legacy/CryCommon/CryFixedString.h +++ /dev/null @@ -1,2337 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - -// Description : Stack-based fixed-size String class, similar to CryString. -// will switch to heap-based allocation when string does no longer fit -// Can easily be substituted instead of CryString. - - -#ifndef CRYINCLUDE_CRYCOMMON_CRYFIXEDSTRING_H -#define CRYINCLUDE_CRYCOMMON_CRYFIXEDSTRING_H -#pragma once - -#include -#include -#include -#include -#include -#include -#include - -#include "CryString.h" - -#ifndef CRY_STRING_DEBUG -#define CRY_STRING_DEBUG(s) -#endif - -#define UNITTEST_CRYFIXEDSTRING (0) - -template -class CharTraits; - -// traits for char -template <> -class CharTraits -{ -public: - typedef size_t size_type; - typedef char value_type; - typedef const value_type* const_str; - typedef value_type* pointer; - typedef const value_type* const_pointer; - typedef value_type& reference; - typedef const value_type& const_reference; - typedef pointer iterator; - typedef const_pointer const_iterator; - - ILINE int _isspace(value_type c) const - { - return ::isspace((int)c); - } - - ILINE value_type _traits_toupper(value_type c) const - { - return static_cast(toupper(c)); - } - - ILINE value_type _traits_tolower(value_type c) const - { - return static_cast(tolower(c)); - } - - ILINE value_type _ascii_tolower(value_type c) const - { - return (c >= 'A' && c <= 'Z') ? c - 'A' + 'a' : c; - } - - ILINE value_type _ascii_toupper(value_type c) const - { - return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c; - } - - ILINE int _strcmp (const_str a, const_str b) const - { - return ::strcmp(a, b); - } - - ILINE int _strncmp (const_str a, const_str b, size_type n) const - { - return ::strncmp(a, b, n); - } - - ILINE int _stricmp (const_str a, const_str b) const - { - return ::azstricmp(a, b); - } - - ILINE int _strnicmp (const_str a, const_str b, size_type n) const - { - return ::azstrnicmp(a, b, n); - } - - ILINE size_type _strspn(const_str str, const_str strCharSet) const - { - return (str == NULL) ? 0 : (size_type)::strspn(str, strCharSet); - } - - ILINE size_type _strcspn(const_str str, const_str strCharSet) const - { - return (str == NULL) ? 0 : (size_type)::strcspn(str, strCharSet); - } - - static ILINE size_type _strlen(const_str str) - { - return (str == NULL) ? 0 : (size_type)::strlen(str); - } - - ILINE const_str _strchr(const_str str, value_type c) const - { - return (str == NULL) ? 0 : ::strchr(str, c); - } - - ILINE value_type* _strstr(value_type* str, const_str strSearch) const - { - return (str == NULL) ? 0 : (value_type*) ::strstr(str, strSearch); - } - - ILINE void _copy(value_type* dest, const value_type* src, size_type count) - { - memcpy(dest, src, count * sizeof(value_type)); - } - - ILINE void _move(value_type* dest, const value_type* src, size_type count) - { - memmove(dest, src, count * sizeof(value_type)); - } - - ILINE void _set(value_type* dest, value_type ch, size_type count) - { - memset(dest, ch, count * sizeof(value_type)); - } - - ILINE int _vsnprintf(value_type* str, size_type size, const_str format, va_list ap) - { - return ::azvsnprintf(str, size, format, ap); - } -}; - -// traits for wchar_t -template <> -class CharTraits -{ -public: - typedef size_t size_type; - typedef wchar_t value_type; - typedef const value_type* const_str; - typedef value_type* pointer; - typedef const value_type* const_pointer; - typedef value_type& reference; - typedef const value_type& const_reference; - typedef pointer iterator; - typedef const_pointer const_iterator; - - ILINE int _isspace(value_type c) const - { - return iswspace(c); - } - - ILINE value_type _traits_toupper(value_type c) const - { - return towupper(c); - } - - ILINE value_type _traits_tolower(value_type c) const - { - return towlower(c); - } - - ILINE value_type _ascii_tolower(value_type c) const - { - return ((((c) >= 'A') && ((c) <= 'Z')) ? ((c) - 'A' + 'a') : (c)); - } - - ILINE value_type _ascii_toupper(value_type c) const - { - return ((((c) >= 'a') && ((c) <= 'z')) ? ((c) - 'a' + 'A') : (c)); - } - - ILINE int _strcmp (const_str a, const_str b) const - { - return wcscmp (a, b); - } - - ILINE int _strncmp (const_str a, const_str b, size_type n) const - { - return wcsncmp (a, b, n); - } - - ILINE int _stricmp (const_str a, const_str b) const - { - return azwcsicmp(a, b); - } - - ILINE int _strnicmp (const_str a, const_str b, size_type n) const - { - return azwcsnicmp(a, b, n); - } - - ILINE size_type _strspn(const_str str, const_str strCharSet) const - { - return (str == NULL) ? 0 : (size_type)::wcsspn(str, strCharSet); - } - - ILINE size_type _strcspn(const_str str, const_str strCharSet) const - { - return (str == NULL) ? 0 : (size_type)::wcscspn(str, strCharSet); - } - - static ILINE size_type _strlen(const_str str) - { - return (str == NULL) ? 0 : (size_type)::wcslen(str); - } - - ILINE const_str _strchr(const_str str, value_type c) const - { - return (str == NULL) ? 0 : ::wcschr(str, c); - } - - ILINE value_type* _strstr(value_type* str, const_str strSearch) const - { - return (str == NULL) ? 0 : ::wcsstr(str, strSearch); - } - - ILINE void _copy(value_type* dest, const value_type* src, size_type count) - { - memcpy(dest, src, count * sizeof(value_type)); - } - - ILINE void _move(value_type* dest, const value_type* src, size_type count) - { - memmove(dest, src, count * sizeof(value_type)); - } - - ILINE void _set(value_type* dest, value_type ch, size_type count) - { - wmemset(dest, ch, count); - } - - ILINE int _vsnprintf(value_type* str, size_type size, const_str format, va_list ap) - { - return ::_vsnwprintf_s(str, size + 1, size, format, ap); - } -}; - -template -class CryStackStringT - : public CharTraits -{ -public: - ////////////////////////////////////////////////////////////////////////// - // Types compatible with STL string. - ////////////////////////////////////////////////////////////////////////// - typedef CryStackStringT _Self; - typedef size_t size_type; - typedef T value_type; - typedef const value_type* const_str; - typedef value_type* pointer; - typedef const value_type* const_pointer; - typedef value_type& reference; - typedef const value_type& const_reference; - typedef pointer iterator; - typedef const_pointer const_iterator; - static const size_type MAX_SIZE = S; - - enum _npos_type - { - npos = (size_type) ~0 - }; - - ////////////////////////////////////////////////////////////////////////// - // Constructors - ////////////////////////////////////////////////////////////////////////// - CryStackStringT(); - -public: - - CryStackStringT(const _Self& str); - CryStackStringT(const _Self& str, size_type nOff, size_type nCount); - CryStackStringT(size_type nRepeat, value_type ch); - - // The reason of making this constructor unavailable (for a while) is - // explained in comments in front of the declaration of - // CryStringT::CryStringT(size_type nRepeat, value_type ch) - // (see CryString.h). -private: - CryStackStringT(value_type ch, size_type nRepeat); - -public: - - CryStackStringT(const_str str); - CryStackStringT(const CryStringT& str); - CryStackStringT(const_str str, size_type nLength); - CryStackStringT(const_iterator _First, const_iterator _Last); - ~CryStackStringT(); - - ////////////////////////////////////////////////////////////////////////// - // STL string like interface. - ////////////////////////////////////////////////////////////////////////// - //! Operators. - size_type length() const; - size_type size() const; - bool empty() const; - void clear(); // free up the data - - //! Returns the storage currently allocated to hold the string, a value at least as large as length(). - // Also: capacity is always >= (MAX_SIZE-1) - size_type capacity() const; - - // Sets the capacity of the string to a number at least as great as a specified number. - // nCount = 0 is shrinking string to fit number of characters in it. - // Shrink to fit post-cond: capacity() >= (MAX_SIZE-1) - void reserve(size_type nCount = 0); - - _Self& append(const value_type* _Ptr); - _Self& append(const value_type* _Ptr, size_type nCount); - _Self& append(const _Self& _Str, size_type nOff, size_type nCount); - _Self& append(const _Self& _Str); - _Self& append(size_type nCount, value_type _Ch); - _Self& append(const_iterator _First, const_iterator _Last); - - _Self& assign(const_str _Ptr); - _Self& assign(const_str _Ptr, size_type nCount); - _Self& assign(const _Self& _Str, size_type off, size_type nCount); - _Self& assign(const _Self& _Str); - _Self& assign(size_type nCount, value_type _Ch); - _Self& assign(const_iterator _First, const_iterator _Last); - - value_type at(size_type index) const; - //value_type& at( size_type index ); - - const_iterator begin() const { return m_str; }; - const_iterator end() const { return m_str + length(); }; - - iterator begin() { return m_str; }; - iterator end() { return m_str + length(); }; - - //! cast to C string operator. - operator const_str() const { - return m_str; - } - - //! cast to C string. - const value_type* c_str() const { return m_str; } - const value_type* data() const { return m_str; }; - - ////////////////////////////////////////////////////////////////////////// - // string comparison. - ////////////////////////////////////////////////////////////////////////// - int compare(const _Self& _Str) const; - int compare(size_type _Pos1, size_type _Num1, const _Self& _Str) const; - int compare(size_type _Pos1, size_type _Num1, const _Self& _Str, size_type nOff, size_type nCount) const; - int compare(const value_type* _Ptr) const; - int compare(size_type _Pos1, size_type _Num1, const value_type* _Ptr, size_type _Num2 = npos) const; - - // Case insensitive comparison - int compareNoCase(const _Self& _Str) const; - int compareNoCase(size_type _Pos1, size_type _Num1, const _Self& _Str) const; - int compareNoCase(size_type _Pos1, size_type _Num1, const _Self& _Str, size_type nOff, size_type nCount) const; - int compareNoCase(const value_type* _Ptr) const; - int compareNoCase(size_type _Pos1, size_type _Num1, const value_type* _Ptr, size_type _Num2 = npos) const; - - // Copies at most a specified number of characters from an indexed position in a source string to a target character array. - size_type copy(value_type* _Ptr, size_type nCount, size_type nOff = 0) const; - - void push_back(value_type _Ch) { _ConcatenateInPlace(&_Ch, 1); } - void resize(size_type nCount, value_type _Ch = ' '); - - //! simple sub-string extraction - _Self substr(size_type pos, size_type count = npos) const; - - // replace part of string. - _Self& replace(value_type chOld, value_type chNew); - _Self& replace(const_str strOld, const_str strNew); - _Self& replace(size_type pos, size_type count, const_str strNew); - _Self& replace(size_type pos, size_type count, const_str strNew, size_type count2); - _Self& replace(size_type pos, size_type count, size_type nNumChars, value_type chNew); - - // insert new elements to string. - _Self& insert(size_type nIndex, value_type ch); - _Self& insert(size_type nIndex, size_type nCount, value_type ch); - _Self& insert(size_type nIndex, const_str pstr); - _Self& insert(size_type nIndex, const_str pstr, size_type nCount); - - //! delete count characters starting at zero-based index - _Self& erase(size_type nIndex, size_type count = npos); - - //! searching (return starting index, or -1 if not found) - //! look for a single character match - //! like "C" strchr - size_type find(value_type ch, size_type pos = 0) const; - //! look for a specific sub-string - //! like "C" strstr - size_type find(const_str subs, size_type pos = 0) const; - size_type rfind(value_type ch, size_type pos = npos) const; - - size_type find_first_of(value_type _Ch, size_type nOff = 0) const; - size_type find_first_of(const_str charSet, size_type nOff = 0) const; - //size_type find_first_of( const value_type* _Ptr,size_type _Off,size_type _Count ) const; - size_type find_first_of(const _Self& _Str, size_type _Off = 0) const; - - size_type find_first_not_of(value_type _Ch, size_type _Off = 0) const; - size_type find_first_not_of(const value_type* _Ptr, size_type _Off = 0) const; - size_type find_first_not_of(const value_type* _Ptr, size_type _Off, size_type _Count) const; - size_type find_first_not_of(const _Self& _Str, size_type _Off = 0) const; - - void swap(_Self& _Str); - - ////////////////////////////////////////////////////////////////////////// - // overloaded operators. - ////////////////////////////////////////////////////////////////////////// - // overloaded indexing. - value_type operator[](size_type index) const; - // value_type& operator[]( size_type index ); // same as at() - - // overloaded assignment - _Self& operator=(const _Self& str); - _Self& operator=(value_type ch); - _Self& operator=(const_str str); - _Self& operator=(const CryStringT& str); - - void move(_Self& src); - -#if defined(LINUX) || defined(APPLE) - template - _Self& operator=(const CryStackStringT& str) - { - _Assign(str.c_str(), str.size()); - return *this; - } -#endif - - // string concatenation - _Self& operator+=(const _Self& str); - _Self& operator+=(value_type ch); - _Self& operator+=(const_str str); - _Self& operator+=(const CryStringT& str); - - size_t GetAllocatedMemory() const - { - size_t size = sizeof(*this); - if (m_str != m_strBuf) - { - size += (m_nAllocSize + 1) * sizeof(value_type); - } - return size; - } - - ////////////////////////////////////////////////////////////////////////// - // Extended functions. - // This functions are not in the STL string. - // They have an ATL CString interface. - ////////////////////////////////////////////////////////////////////////// - //! Format string, use (sprintf) - _Self& Format(const value_type* format, ...); - - //! Format string fast, directly formats into string's buffer. - // Make sure there is enough space to hold the string - _Self& FormatFast (const value_type* format, ...); - - //! Converts the string to lower-case. - // This function uses the "C" locale for case-conversion (ie, A-Z only). - _Self& MakeLower(); - - //! Converts the string to upper-case. - // This function uses the "C" locale for case-conversion (ie, A-Z only). - _Self& MakeUpper(); - - _Self& Trim(); - _Self& Trim(value_type ch); - _Self& Trim(const value_type* sCharSet); - - _Self& TrimLeft(); - _Self& TrimLeft(value_type ch); - _Self& TrimLeft(const value_type* sCharSet); - - _Self& TrimRight(); - _Self& TrimRight(value_type ch); - _Self& TrimRight(const value_type* sCharSet); - - _Self SpanIncluding(const_str charSet) const; - _Self SpanExcluding(const_str charSet) const; - _Self Tokenize(const_str charSet, int& nStart) const; - _Self Mid(size_type nFirst, size_type nCount = npos) const { return substr(nFirst, nCount); }; - - _Self Left(size_type count) const; - _Self Right(size_type count) const; - ////////////////////////////////////////////////////////////////////////// - - // public utilities. - static bool _IsValidString(const_str str); - -public: - ////////////////////////////////////////////////////////////////////////// - // Only used for debugging statistics. - ////////////////////////////////////////////////////////////////////////// - static size_t _usedMemory(size_t size) - { - static size_t s_used_memory = 0; - s_used_memory += size; - return s_used_memory; - } - - //private: -public: - size_type m_nLength; - size_type m_nAllocSize; - value_type* m_str; // pointer to ref counted string data - value_type m_strBuf[MAX_SIZE]; - - // implementation helpers - void _AllocData(size_type nLen); - void _FreeData(value_type* pData); - void _Free(); - void _Initialize(); - - void _Concatenate(const_str sStr1, size_type nLen1, const_str sStr2, size_type nLen2); - void _ConcatenateInPlace(const_str sStr, size_type nLen); - void _Assign(const_str sStr, size_type nLen); - void _MakeUnique(); -}; - - -///////////////////////////////////////////////////////////////////////////// -// CryStackStringT Implementation -////////////////////////////////////////////////////////////////////////// - -////////////////////////////////////////////////////////////////////////// -template -inline bool CryStackStringT::_IsValidString(const_str) -{ - return true; -} - -////////////////////////////////////////////////////////////////////////// -template -inline void CryStackStringT::_Assign(const_str sStr, size_type nLen) -{ - // Check if this string is shared (reference count greater then 1) or not enough capacity to store new string. - // Then allocate new string buffer. - if (nLen > capacity()) - { - _Free(); - _AllocData(nLen); - } - // Copy characters from new string to this buffer. - CharTraits::_copy(m_str, sStr, nLen); - // Set new length. - m_nLength = nLen; - // Make null terminated string. - m_str[nLen] = 0; - CRY_STRING_DEBUG(m_str) -} - -////////////////////////////////////////////////////////////////////////// -template -inline void CryStackStringT::_Concatenate(const_str sStr1, size_type nLen1, const_str sStr2, size_type nLen2) -{ - size_type nLen = nLen1 + nLen2; - if (nLen1 * 2 > nLen) - { - nLen = nLen1 * 2; - } - if (nLen != 0) - { - if (nLen < 8) - { - nLen = 8; - } - _AllocData(nLen); - CharTraits::_copy(m_str, sStr1, nLen1); - CharTraits::_copy(m_str + nLen1, sStr2, nLen2); - m_nLength = nLen1 + nLen2; - m_str[nLen1 + nLen2] = 0; - } - CRY_STRING_DEBUG(m_str) -} - -////////////////////////////////////////////////////////////////////////// -template -inline void CryStackStringT::_ConcatenateInPlace(const_str sStr, size_type nLen) -{ - if (nLen != 0) - { - // Check if this string is shared (reference count greater then 1) or not enough capacity to store new string. - // Then allocate new string buffer. - if (length() + nLen > capacity()) - { - value_type* pOldData = m_str; - _Concatenate(m_str, length(), sStr, nLen); - _FreeData(pOldData); - } - else - { - CharTraits::_copy(m_str + length(), sStr, nLen); - m_nLength += nLen; - m_str[m_nLength] = 0; // Make null terminated string. - } - } -} - -////////////////////////////////////////////////////////////////////////// -template -inline void CryStackStringT::_MakeUnique() -{ -} - -////////////////////////////////////////////////////////////////////////// -template -inline void CryStackStringT::_Initialize() -{ - m_strBuf[0] = 0; - m_str = m_strBuf; - m_nLength = 0; - m_nAllocSize = MAX_SIZE - 1; // 0 termination not counted! -} - -// always allocate one extra character for '\0' termination -// assumes [optimistically] that data length will equal allocation length -template -inline void CryStackStringT::_AllocData(size_type nLen) -{ - assert(nLen >= 0); - assert(nLen <= INT_MAX - 1); // max size (enough room for 1 extra) - - if (nLen == 0) - { - _Initialize(); - } - else - { - size_type allocLen = (nLen + 1) * sizeof(value_type); - value_type* pData = m_strBuf; - if (allocLen > MAX_SIZE) - { - pData = (value_type*)CryModuleMalloc(allocLen); - _usedMemory(allocLen); // For statistics. - m_nAllocSize = nLen; - } - else - { - m_nAllocSize = MAX_SIZE - 1; - } - m_nLength = nLen; - m_str = pData; - m_str[nLen] = 0; // null terminated string. - } -} - -////////////////////////////////////////////////////////////////////////// -template -inline void CryStackStringT::_Free() -{ - _FreeData(m_str); - _Initialize(); -} - -////////////////////////////////////////////////////////////////////////// -template -inline void CryStackStringT::_FreeData(value_type* pData) -{ - if (pData != m_strBuf) - { - size_t allocLen = (m_nAllocSize + 1) * sizeof(value_type); - _usedMemory(-check_cast(allocLen)); // For statistics. - CryModuleFree(pData); - } -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStackStringT::CryStackStringT() -{ - _Initialize(); -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStackStringT::CryStackStringT(const CryStackStringT& str) -{ - _Initialize(); - _Assign(str.c_str(), str.length()); -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStackStringT::CryStackStringT(const CryStackStringT& str, size_type nOff, size_type nCount) -{ - _Initialize(); - assign(str, nOff, nCount); -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStackStringT::CryStackStringT(const_str str) -{ - _Initialize(); - // Make a copy of C string. - size_type nLen = this->_strlen(str); - if (nLen != 0) - { - _AllocData(nLen); - CharTraits::_copy(m_str, str, nLen); - CRY_STRING_DEBUG(m_str) - } -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStackStringT::CryStackStringT(const CryStringT& str) -{ - _Initialize(); - size_t nLength = str.size(); - if (nLength > 0) - { - _AllocData(nLength); - CharTraits::_copy(m_str, str.c_str(), nLength); - CRY_STRING_DEBUG(m_str) - } -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStackStringT::CryStackStringT(const_str str, size_type nLength) -{ - _Initialize(); - if (nLength > 0) - { - _AllocData(nLength); - CharTraits::_copy(m_str, str, nLength); - CRY_STRING_DEBUG(m_str) - } -} - -////////////////////////////////////////////////////////////////////////// -// The reason of making this constructor unavailable (for a while) is -// explained in comments in front of the declaration of -// CryStringT::CryStringT(size_type nRepeat, value_type ch) -// (see CryString.h). -template -inline CryStackStringT::CryStackStringT(size_type nRepeat, value_type ch) -{ - _Initialize(); - if (nRepeat > 0) - { - _AllocData(nRepeat); - CharTraits::_set(m_str, ch, nRepeat); - CRY_STRING_DEBUG(m_str) - } -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStackStringT::CryStackStringT(const_iterator _First, const_iterator _Last) -{ - _Initialize(); - size_type nLength = (size_type)(_Last - _First); - if (nLength > 0) - { - _AllocData(nLength); - CharTraits::_copy(m_str, _First, nLength); - CRY_STRING_DEBUG(m_str) - } -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStackStringT::~CryStackStringT() -{ - _FreeData(m_str); -} - -////////////////////////////////////////////////////////////////////////// -template -inline typename CryStackStringT::size_type CryStackStringT::length() const -{ - return m_nLength; -} -template -inline typename CryStackStringT::size_type CryStackStringT::size() const -{ - return m_nLength; -} -template -inline typename CryStackStringT::size_type CryStackStringT::capacity() const -{ - return m_nAllocSize; -} - -template -inline bool CryStackStringT::empty() const -{ - return length() == 0; -} - -////////////////////////////////////////////////////////////////////////// -template -inline void CryStackStringT::clear() -{ - if (length() == 0) - { - return; - } - _Free(); - assert(length() == 0); -} - -////////////////////////////////////////////////////////////////////////// -template -inline void CryStackStringT::reserve(size_type nCount) -{ - // Reserve of 0 is shrinking container to fit number of characters in it.. - if (nCount > capacity()) - { - value_type* pOldData = m_str; - size_type nOldLength = m_nLength; - _AllocData(nCount); - CharTraits::_copy(m_str, pOldData, nOldLength); - m_nLength = nOldLength; - m_str[m_nLength] = 0; - _FreeData(pOldData); - } - else if (nCount == 0) - { - if (length() != capacity()) - { - value_type* pOldData = m_str; - if (pOldData != m_strBuf) // in case we fit into our static buffer, we cannot shrink anyway - { - size_type nOldLength = m_nLength; - _AllocData(m_nLength); - // if (pOldData != m_strBuf || m_str != m_strBuf) // actually always true - // { - CharTraits::_copy(m_str, pOldData, nOldLength); // we can safely use CharTraits::_copy, as we never overlap here (in case of static buffer, we don't shrink anyway) - _FreeData(pOldData); - // } - } - } - } - CRY_STRING_DEBUG(m_str) -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStackStringT& CryStackStringT::append(const_str _Ptr) -{ - *this += _Ptr; - return *this; -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStackStringT& CryStackStringT::append(const_str _Ptr, size_type nCount) -{ - _ConcatenateInPlace(_Ptr, nCount); - return *this; -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStackStringT& CryStackStringT::append(const CryStackStringT& _Str, size_type off, size_type nCount) -{ - size_type len = _Str.length(); - if (off > len) - { - return *this; - } - if (off + nCount > len) - { - nCount = len - off; - } - _ConcatenateInPlace(_Str.m_str + off, nCount); - return *this; -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStackStringT& CryStackStringT::append(const CryStackStringT& _Str) -{ - *this += _Str; - return *this; -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStackStringT& CryStackStringT::append(size_type nCount, value_type _Ch) -{ - if (nCount > 0) - { - if (length() + nCount >= capacity()) - { - value_type* pOldData = m_str; - size_type nOldLength = m_nLength; - _AllocData(length() + nCount); - CharTraits::_copy(m_str, pOldData, nOldLength); - CharTraits::_set(m_str + nOldLength, _Ch, nCount); - _FreeData(pOldData); - } - else - { - size_type nOldLength = length(); - CharTraits::_set(m_str + nOldLength, _Ch, nCount); - m_nLength = nOldLength + nCount; - m_str[length()] = 0; // Make null terminated string. - } - } - CRY_STRING_DEBUG(m_str) - return *this; -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStackStringT& CryStackStringT::append(const_iterator _First, const_iterator _Last) -{ - append(_First, (size_type)(_Last - _First)); - return *this; -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStackStringT& CryStackStringT::assign(const_str _Ptr) -{ - *this = _Ptr; - return *this; -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStackStringT& CryStackStringT::assign(const_str _Ptr, size_type nCount) -{ - size_type len = this->_strlen(_Ptr); - _Assign(_Ptr, (nCount < len) ? nCount : len); - return *this; -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStackStringT& CryStackStringT::assign(const CryStackStringT& _Str, size_type off, size_type nCount) -{ - size_type len = _Str.length(); - if (off > len) - { - return *this; - } - if (off + nCount > len) - { - nCount = len - off; - } - _Assign(_Str.m_str + off, nCount); - return *this; -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStackStringT& CryStackStringT::assign(const CryStackStringT& _Str) -{ - *this = _Str; - return *this; -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStackStringT& CryStackStringT::assign(size_type nCount, value_type _Ch) -{ - if (nCount >= 1) - { - _AllocData(nCount); - CharTraits::_set(m_str, _Ch, nCount); - CRY_STRING_DEBUG(m_str) - } - return *this; -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStackStringT& CryStackStringT::assign(const_iterator _First, const_iterator _Last) -{ - assign(_First, (size_type)(_Last - _First)); - return *this; -} - -////////////////////////////////////////////////////////////////////////// -template -inline typename CryStackStringT::value_type CryStackStringT::at(size_type index) const -{ - assert(index >= 0 && index < length()); - return m_str[index]; -} - -/* -inline value_type& CryStackStringT::at( size_type index ) -{ -// same as GetAt -assert( index >= 0 && index < length() ); -return m_str[index]; -} -*/ - -template -inline typename CryStackStringT::value_type CryStackStringT::operator[](size_type index) const -{ - assert(index < length()); - return m_str[index]; -} - - -/* -inline value_type& CryStackStringT::operator[]( size_type index ) -{ -// same as GetAt -assert( index >= 0 && index < length() ); -return m_str[index]; -} -*/ - - -////////////////////////////////////////////////////////////////////////// -template -inline int CryStackStringT::compare(const CryStackStringT& _Str) const -{ - return CharTraits::_strcmp(m_str, _Str.m_str); -} - -template -inline int CryStackStringT::compare(size_type _Pos1, size_type _Num1, const CryStackStringT& _Str) const -{ - return compare(_Pos1, _Num1, _Str.m_str, npos); -} - -template -inline int CryStackStringT::compare(size_type _Pos1, size_type _Num1, const CryStackStringT& _Str, size_type nOff, size_type nCount) const -{ - assert(nOff < _Str.length()); - return compare(_Pos1, _Num1, _Str.m_str + nOff, nCount); -} - -template -inline int CryStackStringT::compare(const value_type* _Ptr) const -{ - return CharTraits::_strcmp(m_str, _Ptr); -} - -template -inline int CryStackStringT::compare(size_type _Pos1, size_type _Num1, const value_type* _Ptr, size_type _Num2) const -{ - assert(_Pos1 < length()); - if (length() - _Pos1 < _Num1) - { - _Num1 = length() - _Pos1; // trim to size - } - int res = _Num1 == 0 ? 0 : CharTraits::_strncmp(m_str + _Pos1, _Ptr, (_Num1 < _Num2) ? _Num1 : _Num2); - return (res != 0 ? res : _Num2 == npos && _Ptr[_Num1] == 0 ? 0 : _Num1 < _Num2 ? -1 : _Num1 == _Num2 ? 0 : +1); -} - -////////////////////////////////////////////////////////////////////////// -template -inline int CryStackStringT::compareNoCase(const CryStackStringT& _Str) const -{ - return CharTraits::_stricmp(m_str, _Str.m_str); -} - -template -inline int CryStackStringT::compareNoCase(size_type _Pos1, size_type _Num1, const CryStackStringT& _Str) const -{ - return compareNoCase(_Pos1, _Num1, _Str.m_str, npos); -} - -template -inline int CryStackStringT::compareNoCase(size_type _Pos1, size_type _Num1, const CryStackStringT& _Str, size_type nOff, size_type nCount) const -{ - assert(nOff < _Str.length()); - return compareNoCase(_Pos1, _Num1, _Str.m_str + nOff, nCount); -} - -template -inline int CryStackStringT::compareNoCase(const value_type* _Ptr) const -{ - return CharTraits::_stricmp(m_str, _Ptr); -} - -template -inline int CryStackStringT::compareNoCase(size_type _Pos1, size_type _Num1, const value_type* _Ptr, size_type _Num2) const -{ - assert(_Pos1 < length()); - if (length() - _Pos1 < _Num1) - { - _Num1 = length() - _Pos1; // trim to size - } - int res = _Num1 == 0 ? 0 : CharTraits::_strnicmp(m_str + _Pos1, _Ptr, (_Num1 < _Num2) ? _Num1 : _Num2); - return (res != 0 ? res : _Num2 == npos && _Ptr[_Num1] == 0 ? 0 : _Num1 < _Num2 ? -1 : _Num1 == _Num2 ? 0 : +1); -} - -////////////////////////////////////////////////////////////////////////// -template -inline typename CryStackStringT::size_type CryStackStringT::copy(value_type* _Ptr, size_type nCount, size_type nOff) const -{ - assert(nOff < length()); - if (nCount < 0) - { - nCount = 0; - } - if (nOff + nCount > length()) // trim to offset. - { - nCount = length() - nOff; - } - - CharTraits::_copy(_Ptr, m_str + nOff, nCount); - return nCount; -} - -////////////////////////////////////////////////////////////////////////// -template -inline void CryStackStringT::resize(size_type nCount, value_type _Ch) -{ - _MakeUnique(); - if (nCount > length()) - { - size_type numToAdd = nCount - length(); - append(numToAdd, _Ch); - } - else if (nCount < length()) - { - m_nLength = nCount; - m_str[length()] = 0; // Make null terminated string. - } -} - -////////////////////////////////////////////////////////////////////////// -//! compare helpers -template -inline bool operator==(const CryStackStringT& s1, const CryStackStringT& s2) -{ return s1.compare(s2) == 0; } -template -inline bool operator==(const CryStackStringT& s1, const typename CryStackStringT::value_type* s2) -{ return s1.compare(s2) == 0; } -template -inline bool operator==(const typename CryStackStringT::value_type* s1, const CryStackStringT& s2) -{ return s2.compare(s1) == 0; } -template -inline bool operator!=(const CryStackStringT& s1, const CryStackStringT& s2) -{ return s1.compare(s2) != 0; } -template -inline bool operator!=(const CryStackStringT& s1, const typename CryStackStringT::value_type* s2) -{ return s1.compare(s2) != 0; } -template -inline bool operator!=(const typename CryStackStringT::value_type* s1, const CryStackStringT& s2) -{ return s2.compare(s1) != 0; } -template -inline bool operator<(const CryStackStringT& s1, const CryStackStringT& s2) -{ return s1.compare(s2) < 0; } -template -inline bool operator<(const CryStackStringT& s1, const typename CryStackStringT::value_type* s2) -{ return s1.compare(s2) < 0; } -template -inline bool operator<(const typename CryStackStringT::value_type* s1, const CryStackStringT& s2) -{ return s2.compare(s1) > 0; } -template -inline bool operator>(const CryStackStringT& s1, const CryStackStringT& s2) -{ return s1.compare(s2) > 0; } -template -inline bool operator>(const CryStackStringT& s1, const typename CryStackStringT::value_type* s2) -{ return s1.compare(s2) > 0; } -template -inline bool operator>(const typename CryStackStringT::value_type* s1, const CryStackStringT& s2) -{ return s2.compare(s1) < 0; } -template -inline bool operator<=(const CryStackStringT& s1, const CryStackStringT& s2) -{ return s1.compare(s2) <= 0; } -template -inline bool operator<=(const CryStackStringT& s1, const typename CryStackStringT::value_type* s2) -{ return s1.compare(s2) <= 0; } -template -inline bool operator<=(const typename CryStackStringT::value_type* s1, const CryStackStringT& s2) -{ return s2.compare(s1) >= 0; } -template -inline bool operator>=(const CryStackStringT& s1, const CryStackStringT& s2) -{ return s1.compare(s2) >= 0; } -template -inline bool operator>=(const CryStackStringT& s1, const typename CryStackStringT::value_type* s2) -{ return s1.compare(s2) >= 0; } -template -inline bool operator>=(const typename CryStackStringT::value_type* s1, const CryStackStringT& s2) -{ return s2.compare(s1) <= 0; } - -////////////////////////////////////////////////////////////////////////// -template -inline CryStackStringT& CryStackStringT::operator=(value_type ch) -{ - _Assign(&ch, 1); - return *this; -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStackStringT operator+(const CryStackStringT& string1, typename CryStackStringT::value_type ch) -{ - CryStackStringT s(string1); - s.append(1, ch); - return s; -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStackStringT operator+(typename CryStackStringT::value_type ch, const CryStackStringT& str) -{ - CryStackStringT s; - s.reserve(str.size() + 1); - s.append(1, ch); - s.append(str); - return s; -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStackStringT operator+(const CryStackStringT& string1, const CryStackStringT& string2) -{ - CryStackStringT s(string1); - s.append(string2); - return s; -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStackStringT operator+(const CryStackStringT& str1, const typename CryStackStringT::value_type* str2) -{ - CryStackStringT s(str1); - s.append(str2); - return s; -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStackStringT operator+(const typename CryStackStringT::value_type* str1, const CryStackStringT& str2) -{ - assert(str1 == NULL || (CryStackStringT::_IsValidString(str1))); - CryStackStringT s; - s.reserve(CharTraits::_strlen(str1) + str2.size()); - s.append(str1); - s.append(str2); - return s; -} - -template -inline CryStackStringT& CryStackStringT::operator=(const CryStackStringT& str) -{ - _Assign (str.c_str(), str.length()); - return *this; -} - -template -inline CryStackStringT& CryStackStringT::operator=(const_str str) -{ - assert(str == NULL || _IsValidString(str)); - _Assign(str, this->_strlen(str)); - return *this; -} - -template -inline CryStackStringT& CryStackStringT::operator=(const CryStringT& str) -{ - _Assign(str.c_str(), str.size()); - return *this; -} - -template -inline CryStackStringT& CryStackStringT::operator+=(const CryStringT& str) -{ - _ConcatenateInPlace(str.c_str(), str.size()); - return *this; -} - -template -inline CryStackStringT& CryStackStringT::operator+=(const_str str) -{ - assert(str == NULL || _IsValidString(str)); - _ConcatenateInPlace(str, this->_strlen(str)); - return *this; -} - -template -inline CryStackStringT& CryStackStringT::operator+=(value_type ch) -{ - _ConcatenateInPlace(&ch, 1); - return *this; -} - -template -inline CryStackStringT& CryStackStringT::operator+=(const CryStackStringT& str) -{ - _ConcatenateInPlace(str.m_str, str.length()); - return *this; -} - -//! find first single character -template -inline typename CryStackStringT::size_type CryStackStringT::find(value_type ch, size_type pos) const -{ - if (!(/*pos >= 0 && */ pos <= length())) - { - return (typename CryStackStringT::size_type)npos; - } - const_str str = CharTraits::_strchr(m_str + pos, ch); - // return npos if not found and index otherwise - return (str == NULL) ? npos : (size_type)(str - m_str); -} - -//! find a sub-string (like strstr) -template -inline typename CryStackStringT::size_type CryStackStringT::find(const_str subs, size_type pos) const -{ - assert(_IsValidString(subs)); - if (!(pos >= 0 && pos <= length())) - { - return npos; - } - - // find first matching substring - const_str str = CharTraits::_strstr(m_str + pos, subs); - - // return npos for not found, distance from beginning otherwise - return (str == NULL) ? npos : (size_type)(str - m_str); -} - -//! find last single character -template -inline typename CryStackStringT::size_type CryStackStringT::rfind(value_type ch, size_type pos) const -{ - const_str str; - if (pos == npos) - { - // find last single character - str = strrchr(m_str, ch); - // return -1 if not found, distance from beginning otherwise - return (str == NULL) ? (size_type) - 1 : (size_type)(str - m_str); - } - else - { - if (pos == npos) - { - pos = length(); - } - if (!(pos >= 0 && pos <= length())) - { - return npos; - } - - value_type tmp = m_str[pos + 1]; - m_str[pos + 1] = 0; - str = strrchr(m_str, ch); - m_str[pos + 1] = tmp; - } - // return -1 if not found, distance from beginning otherwise - return (str == NULL) ? (size_type) - 1 : (size_type)(str - m_str); -} - -////////////////////////////////////////////////////////////////////////// -template -inline typename CryStackStringT::size_type CryStackStringT::find_first_of(const CryStackStringT& _Str, size_type _Off) const -{ - return find_first_of(_Str.m_str, _Off); -} - -////////////////////////////////////////////////////////////////////////// -template -inline typename CryStackStringT::size_type CryStackStringT::find_first_of(value_type _Ch, size_type nOff) const -{ - if (!(nOff >= 0 && nOff <= length())) - { - return npos; - } - value_type charSet[2] = { _Ch, 0 }; - const_str str = strpbrk(m_str + nOff, charSet); - return (str == NULL) ? -1 : (size_type)(str - m_str); -} - -////////////////////////////////////////////////////////////////////////// -template -inline typename CryStackStringT::size_type CryStackStringT::find_first_of(const_str charSet, size_type nOff) const -{ - assert(_IsValidString(charSet)); - if (!(nOff >= 0 && nOff <= length())) - { - return npos; - } - const_str str = strpbrk(m_str + nOff, charSet); - return (str == NULL) ? (size_type) - 1 : (size_type)(str - m_str); -} - -//size_type find_first_not_of(const _Self& __s, size_type __pos = 0) const -//{ return find_first_not_of(__s._M_start, __pos, __s.size()); } - -//size_type find_first_not_of(const _CharT* __s, size_type __pos = 0) const -//{ _STLP_FIX_LITERAL_BUG(__s) return find_first_not_of(__s, __pos, _Traits::length(__s)); } - -//size_type find_first_not_of(const _CharT* __s, size_type __pos, size_type __n) const; - -//size_type find_first_not_of(_CharT __c, size_type __pos = 0) const; - - -////////////////////////////////////////////////////////////////////////// -template -inline typename CryStackStringT::size_type CryStackStringT::find_first_not_of(const value_type* _Ptr, size_type _Off) const -{ return find_first_not_of(_Ptr, _Off, this->_strlen(_Ptr)); } - -////////////////////////////////////////////////////////////////////////// -template -inline typename CryStackStringT::size_type CryStackStringT::find_first_not_of(const CryStackStringT& _Str, size_type _Off) const -{ return find_first_not_of(_Str.m_str, _Off); } - -////////////////////////////////////////////////////////////////////////// -template -inline typename CryStackStringT::size_type CryStackStringT::find_first_not_of(value_type _Ch, size_type _Off) const -{ - if (_Off > length()) - { - return npos; - } - else - { - for (const value_type* str = begin() + _Off; str != end(); ++str) - { - if (*str != _Ch) - { - return size_type(str - begin()); // Character found! - } - } - return npos; - } -} - -////////////////////////////////////////////////////////////////////////// -template -inline typename CryStackStringT::size_type CryStackStringT::find_first_not_of(const value_type* _Ptr, size_type _Off, size_type _Count) const -{ - if (_Off > length()) - { - return npos; - } - else - { - const value_type* charsFirst = _Ptr, * charsLast = _Ptr + _Count; - for (const value_type* str = begin() + _Off; str != end(); ++str) - { - const value_type* c; - for (c = charsFirst; c != charsLast; ++c) - { - if (*c == *str) - { - break; - } - } - if (c == charsLast) - { - return size_type(str - begin());// Current character not in char set. - } - } - return npos; - } -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStackStringT CryStackStringT::substr(size_type pos, size_type count) const -{ - if (pos >= length()) - { - return CryStackStringT(); - } - if (count == npos) - { - count = length() - pos; - } - if (pos + count > length()) - { - count = length() - pos; - } - return CryStackStringT(m_str + pos, count); -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStackStringT& CryStackStringT::erase(size_type nIndex, size_type nCount) -{ - if (nIndex < 0) - { - nIndex = 0; - } - if (nCount < 0 || nCount > length() - nIndex) - { - nCount = length() - nIndex; - } - if (nCount > 0 && nIndex < length()) - { - _MakeUnique(); - size_type nNumToCopy = length() - (nIndex + nCount) + 1; - CharTraits::_move(m_str + nIndex, m_str + nIndex + nCount, nNumToCopy); - m_nLength = length() - nCount; - } - - return *this; -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStackStringT& CryStackStringT::insert(size_type nIndex, value_type ch) -{ - return insert(nIndex, 1, ch); -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStackStringT& CryStackStringT::insert(size_type nIndex, size_type nCount, value_type ch) -{ - _MakeUnique(); - - if (nIndex < 0) - { - nIndex = 0; - } - - size_type nNewLength = length(); - if (nIndex > nNewLength) - { - nIndex = nNewLength; - } - nNewLength += nCount; - - if (capacity() < nNewLength) - { - value_type* pOldData = m_str; - size_type nOldLength = m_nLength; - const_str pstr = m_str; - _AllocData(nNewLength); - CharTraits::_copy(m_str, pstr, nOldLength + 1); - _FreeData(pOldData); - } - - CharTraits::_move(m_str + nIndex + nCount, m_str + nIndex, (nNewLength - nIndex)); - CharTraits::_set(m_str + nIndex, ch, nCount); - m_nLength = nNewLength; - CRY_STRING_DEBUG(m_str) - - return *this; -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStackStringT& CryStackStringT::insert(size_type nIndex, const_str pstr, size_type nCount) -{ - if (nIndex < 0) - { - nIndex = 0; - } - - size_type nInsertLength = nCount; - size_type nNewLength = length(); - if (nInsertLength > 0) - { - _MakeUnique(); - if (nIndex > nNewLength) - { - nIndex = nNewLength; - } - nNewLength += nInsertLength; - - if (capacity() < nNewLength) - { - value_type* pOldData = m_str; - size_type nOldLength = m_nLength; - const_str pOldStr = m_str; - _AllocData(nNewLength); - CharTraits::_copy(m_str, pOldStr, (nOldLength + 1)); - _FreeData(pOldData); - } - - CharTraits::_move(m_str + nIndex + nInsertLength, m_str + nIndex, (nNewLength - nIndex - nInsertLength + 1)); - CharTraits::_copy(m_str + nIndex, pstr, nInsertLength); - m_nLength = nNewLength; - m_str[length()] = 0; - } - CRY_STRING_DEBUG(m_str) - - return *this; -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStackStringT& CryStackStringT::insert(size_type nIndex, const_str pstr) -{ - return insert(nIndex, pstr, this->_strlen(pstr)); -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStackStringT& CryStackStringT::replace(size_type pos, size_type count, const_str strNew) -{ - return replace(pos, count, strNew, this->_strlen(strNew)); -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStackStringT& CryStackStringT::replace(size_type pos, size_type count, const_str strNew, size_type count2) -{ - erase(pos, count); - insert(pos, strNew, count2); - return *this; -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStackStringT& CryStackStringT::replace(size_type pos, size_type count, size_type nNumChars, value_type chNew) -{ - erase(pos, count); - insert(pos, nNumChars, chNew); - return *this; -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStackStringT& CryStackStringT::replace(value_type chOld, value_type chNew) -{ - if (chOld != chNew) - { - _MakeUnique(); - value_type* strend = m_str + length(); - for (value_type* str = m_str; str != strend; ++str) - { - if (*str == chOld) - { - *str = chNew; - } - } - } - return *this; -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStackStringT& CryStackStringT::replace(const_str strOld, const_str strNew) -{ - size_type nSourceLen = this->_strlen(strOld); - if (nSourceLen == 0) - { - return *this; - } - size_type nReplacementLen = this->_strlen(strNew); - - size_type nCount = 0; - value_type* strStart = m_str; - value_type* strEnd = m_str + length(); - value_type* strTarget; - while (strStart < strEnd) - { - while ((strTarget = CharTraits::_strstr(strStart, strOld)) != NULL) - { - nCount++; - strStart = strTarget + nSourceLen; - } - strStart += this->_strlen(strStart) + 1; - } - - if (nCount > 0) - { - _MakeUnique(); - - size_type nOldLength = length(); - size_type nNewLength = nOldLength + (nReplacementLen - nSourceLen) * nCount; - if (capacity() < nNewLength) - { - value_type* pOldData = m_str; - size_type nPrevLength = m_nLength; - const_str pstr = m_str; - _AllocData(nNewLength); - CharTraits::_copy(m_str, pstr, nPrevLength); - _FreeData(pOldData); - } - strStart = m_str; - strEnd = m_str + length(); - - while (strStart < strEnd) - { - while ((strTarget = CharTraits::_strstr(strStart, strOld)) != NULL) - { - size_type nBalance = nOldLength - ((size_type)(strTarget - m_str) + nSourceLen); - CharTraits::_move(strTarget + nReplacementLen, strTarget + nSourceLen, nBalance); - CharTraits::_copy(strTarget, strNew, nReplacementLen); - strStart = strTarget + nReplacementLen; - strStart[nBalance] = 0; - nOldLength += (nReplacementLen - nSourceLen); - } - strStart += this->_strlen(strStart) + 1; - } - m_nLength = nNewLength; - } - CRY_STRING_DEBUG(m_str) - - return *this; -} - -////////////////////////////////////////////////////////////////////////// -template -inline void CryStackStringT::move(CryStackStringT& str) -{ - memcpy(this, &str, sizeof(*this)); - if (str.m_str == str.m_strBuf) - { - m_str = m_strBuf; - } -} - -template -inline void CryStackStringT::swap(CryStackStringT& _Str) -{ - CryStackStringT temp; - temp.move(*this); - move(_Str); - _Str.move(temp); -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStackStringT& CryStackStringT::Format(const_str format, ...) -{ - assert(_IsValidString(format)); - - value_type temp[4096]; // Limited to 4096 characters! - va_list argList; - va_start(argList, format); - this->_vsnprintf(temp, 4095, format, argList); - temp[4095] = '\0'; - va_end(argList); - *this = temp; - return *this; -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStackStringT& CryStackStringT::FormatFast(const_str format, ...) -{ - assert(_IsValidString(format)); - - va_list argList; - va_start(argList, format); - - int newLength = this->_vsnprintf(m_str, capacity(), format, argList); - if (newLength >= 0) - { - m_nLength = (size_type)newLength; - } - else - { - m_nLength = capacity(); - m_str[capacity()] = '\0'; - } - - va_end(argList); - - return *this; -} - - -////////////////////////////////////////////////////////////////////////// -template -inline CryStackStringT& CryStackStringT::MakeLower() -{ - _MakeUnique(); - for (value_type* s = m_str; *s != 0; s++) - { - *s = this->_ascii_tolower(*s); - } - return *this; -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStackStringT& CryStackStringT::MakeUpper() -{ - _MakeUnique(); - for (value_type* s = m_str; *s != 0; s++) - { - *s = this->_ascii_toupper(*s); - } - return *this; -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStackStringT& CryStackStringT::Trim() -{ - return TrimRight().TrimLeft(); -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStackStringT& CryStackStringT::Trim(value_type ch) -{ - _MakeUnique(); - const value_type chset[2] = { ch, 0 }; - return TrimRight(chset).TrimLeft(chset); -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStackStringT& CryStackStringT::Trim(const value_type* sCharSet) -{ - _MakeUnique(); - return TrimRight(sCharSet).TrimLeft(sCharSet); -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStackStringT& CryStackStringT::TrimRight(value_type ch) -{ - const value_type chset[2] = { ch, 0 }; - return TrimRight(chset); -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStackStringT& CryStackStringT::TrimRight(const value_type* sCharSet) -{ - if (!sCharSet || !(*sCharSet) || length() < 1) - { - return *this; - } - - const value_type* last = m_str + length() - 1; - const value_type* str = last; - while ((str != m_str) && (CharTraits::_strchr(sCharSet, *str) != 0)) - { - str--; - } - - if (str != last) - { - // Just shrink length of the string. - size_type nNewLength = (size_type)(str - m_str) + 1; // m_str can change in _MakeUnique - _MakeUnique(); - m_nLength = nNewLength; - m_str[nNewLength] = 0; - } - - return *this; -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStackStringT& CryStackStringT::TrimRight() -{ - if (length() < 1) - { - return *this; - } - - const value_type* last = m_str + length() - 1; - const value_type* str = last; - while ((str != m_str) && (CharTraits::_isspace(*str) != 0)) - { - str--; - } - - if (str != last) // something changed? - { - // Just shrink length of the string. - size_type nNewLength = (size_type)(str - m_str) + 1; // m_str can change in _MakeUnique - _MakeUnique(); - m_nLength = nNewLength; - m_str[nNewLength] = 0; - } - - return *this; -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStackStringT& CryStackStringT::TrimLeft(value_type ch) -{ - const value_type chset[2] = { ch, 0 }; - return TrimLeft(chset); -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStackStringT& CryStackStringT::TrimLeft(const value_type* sCharSet) -{ - if (!sCharSet || !(*sCharSet)) - { - return *this; - } - - const value_type* str = m_str; - while ((*str != 0) && (CharTraits::_strchr(sCharSet, *str) != 0)) - { - str++; - } - - if (str != m_str) - { - size_type nOff = (size_type)(str - m_str); // m_str can change in _MakeUnique - _MakeUnique(); - size_type nNewLength = length() - nOff; - CharTraits::_move(m_str, m_str + nOff, nNewLength + 1); - m_nLength = nNewLength; - m_str[nNewLength] = 0; - } - - return *this; -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStackStringT& CryStackStringT::TrimLeft() -{ - const value_type* str = m_str; - while ((*str != 0) && (CharTraits::_isspace(*str) != 0)) - { - str++; - } - - if (str != m_str) - { - size_type nOff = (size_type)(str - m_str); // m_str can change in _MakeUnique - _MakeUnique(); - size_type nNewLength = length() - nOff; - CharTraits::_move(m_str, m_str + nOff, nNewLength + 1); - m_nLength = nNewLength; - m_str[nNewLength] = 0; - } - - return *this; -} - -template -inline CryStackStringT CryStackStringT::Right(size_type count) const -{ - if (count == npos) - { - return CryStackStringT(); - } - else if (count > length()) - { - return *this; - } - - return CryStackStringT(m_str + length() - count, count); -} - -template -inline CryStackStringT CryStackStringT::Left(size_type count) const -{ - if (count == npos) - { - return CryStackStringT(); - } - else if (count > length()) - { - count = length(); - } - - return CryStackStringT(m_str, count); -} - -// strspn equivalent -template -inline CryStackStringT CryStackStringT::SpanIncluding(const_str charSet) const -{ - assert(_IsValidString(charSet)); - return Left((size_type)this->_strspn(m_str, charSet)); -} - -// strcspn equivalent -template -inline CryStackStringT CryStackStringT::SpanExcluding(const_str charSet) const -{ - assert(_IsValidString(charSet)); - return Left((size_type)this->_strcspn(m_str, charSet)); -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStackStringT CryStackStringT::Tokenize(const_str charSet, int& nStart) const -{ - if (nStart < 0) - { - return CryStackStringT(); - } - - if (!charSet) - { - return *this; - } - - const_str sPlace = m_str + nStart; - const_str sEnd = m_str + length(); - if (sPlace < sEnd) - { - int nIncluding = (int)this->_strspn(sPlace, charSet); - - if ((sPlace + nIncluding) < sEnd) - { - sPlace += nIncluding; - int nExcluding = (int)this->_strcspn(sPlace, charSet); - int nFrom = nStart + nIncluding; - nStart = nFrom + nExcluding + 1; - - return substr(nFrom, nExcluding); - } - } - // Return empty string. - nStart = -1; - return CryStackStringT(); -} - -#if defined(_RELEASE) -#define ASSERT_LEN (void)(0) -#define ASSERT_WLEN (void)(0) -#else -#define ASSERT_LEN CRY_ASSERT_TRACE(this->length() <= S, ("String '%s' is %u character(s) longer than MAX_SIZE=%u", this->c_str(), this->length() - S, S)) -#define ASSERT_WLEN CRY_ASSERT_TRACE(this->length() <= S, ("Wide-char string '%ls' is %u character(s) longer than MAX_SIZE=%u", this->c_str(), this->length() - S, S)) -#endif - -// a template specialization for char -template -class CryFixedStringT - : public CryStackStringT -{ -public: - typedef CryStackStringT _parentType; - typedef CryFixedStringT _Self; - typedef size_t size_type; - typedef char value_type; - typedef const value_type* const_str; - typedef value_type* pointer; - typedef const value_type* const_pointer; - typedef value_type& reference; - typedef const value_type& const_reference; - typedef pointer iterator; - typedef const_pointer const_iterator; - static const size_type MAX_SIZE = S; - CryFixedStringT() - : _parentType() {} - CryFixedStringT(const _parentType& str) - : _parentType(str) {ASSERT_LEN; } - CryFixedStringT(const _parentType& str, size_type nOff, size_type nCount) - : _parentType(str, nOff, nCount) {ASSERT_LEN; } - CryFixedStringT(const _Self& str) - : _parentType(str) {ASSERT_LEN; } - CryFixedStringT(const _Self& str, size_type nOff, size_type nCount) - : _parentType(str, nOff, nCount) {ASSERT_LEN; } - CryFixedStringT(size_type nRepeat, value_type ch) - : _parentType(nRepeat, ch) {ASSERT_LEN; } - CryFixedStringT(const_str str) - : _parentType (str) {ASSERT_LEN; } - CryFixedStringT(const_str str, size_type nLength) - : _parentType(str, nLength) {ASSERT_LEN; } - CryFixedStringT(const_iterator _First, const_iterator _Last) - : _parentType(_First, _Last) {ASSERT_LEN; } - - template - _Self& operator=(const CryFixedStringT& str) - { - _parentType::operator = (str); - ASSERT_LEN; - return *this; - } - template - _Self& operator=(const CryStackStringT& str) - { - _parentType::operator = (str); - ASSERT_LEN; - return *this; - } - _Self& operator=(value_type ch) - { - _parentType::operator = (ch); - ASSERT_LEN; - return *this; - } - - void GetMemoryUsage(class ICrySizer* pSizer) const{} -}; - -// a template specialization for a fixed list of CryFixedString [Jan M.] -template -class CCryFixedStringListT -{ -public: - CCryFixedStringListT() - { Clear(); } - - void Clear() - { - m_currentAmount = -1; - for (int a = 0; a < NUM_MAX_ELEMENTS; ++a) - { - m_data[a] = ""; - } - } - - void Add(const char* name) - { - m_data[++m_currentAmount] = name; - if (m_currentAmount == NUM_MAX_ELEMENTS) - { - m_currentAmount = -1; - } - } - - const char* operator[](int index) - { - if (index <= m_currentAmount) - { - return m_data[index].c_str(); - } - return NULL; - } - - ILINE int Size() { return m_currentAmount + 1; } - - CryFixedStringT<32>* GetData(int& amount) - { - amount = m_currentAmount + 1; - return m_data; - } -private: - const static int NUM_MAX_ELEMENTS = maxElements; - CryFixedStringT m_data[NUM_MAX_ELEMENTS]; - int32 m_currentAmount; -}; - -// a template specialization for wchar_t -template -class CryFixedWStringT - : public CryStackStringT -{ -public: - typedef CryStackStringT _parentType; - typedef CryFixedWStringT _Self; - typedef size_t size_type; - typedef wchar_t value_type; - typedef const value_type* const_str; - typedef value_type* pointer; - typedef const value_type* const_pointer; - typedef value_type& reference; - typedef const value_type& const_reference; - typedef pointer iterator; - typedef const_pointer const_iterator; - static const size_type MAX_SIZE = S; - CryFixedWStringT() - : _parentType() {} - CryFixedWStringT(const _parentType& str) - : _parentType(str) {ASSERT_WLEN; } - CryFixedWStringT(const _parentType& str, size_type nOff, size_type nCount) - : _parentType(str, nOff, nCount) {ASSERT_WLEN; } - CryFixedWStringT(const _Self& str) - : _parentType(str) {ASSERT_WLEN; } - CryFixedWStringT(const _Self& str, size_type nOff, size_type nCount) - : _parentType(str, nOff, nCount) {ASSERT_WLEN; } - CryFixedWStringT(size_type nRepeat, value_type ch) - : _parentType(nRepeat, ch) {ASSERT_WLEN; } - CryFixedWStringT(const_str str) - : _parentType (str) {ASSERT_WLEN; } - CryFixedWStringT(const_str str, size_type nLength) - : _parentType(str, nLength) {ASSERT_WLEN; } - CryFixedWStringT(const_iterator _First, const_iterator _Last) - : _parentType(_First, _Last) {ASSERT_WLEN; } - - template - _Self& operator=(const CryFixedWStringT& str) - { - _parentType::operator = (str); - ASSERT_WLEN; - return *this; - } - template - _Self& operator=(const CryStackStringT& str) - { - _parentType::operator = (str); - ASSERT_WLEN; - return *this; - } -}; -#undef ASSERT_LEN -#undef ASSERT_WLEN -typedef CryStackStringT stack_string; - -// Special string type used for specifying file paths. -typedef CryStackStringT CryPathString; - - -#if UNITTEST_CRYFIXEDSTRING - -struct SUnitTest_FixedString -{ - bool UnitAssert(const char* message, const char* value, const char* refValue) - { - int res = strcmp(value, refValue); - CRY_ASSERT_MESSAGE(res == 0, message); - return res == 0; - } - - bool UnitAssert(const char* message, const wchar_t* value, const wchar_t* refValue) - { - int res = wcscmp(value, refValue); - CRY_ASSERT_MESSAGE(res == 0, message); - return res == 0; - } - - bool UnitAssert(const char* message, bool cond) - { - CRY_ASSERT_MESSAGE(cond, message); - return cond; - } - - bool UnitAssert(const char* message, size_t a, size_t b) - { - CRY_ASSERT_MESSAGE(a == b, message); - return a == b; - } - - int UnitTest() - { - CryStackStringT str1; - CryStackStringT str2; - CryStackStringT str3; - CryStackStringT str4; - CryStackStringT str5; - CryStackStringT wstr1; - CryStackStringT wstr2; - CryFixedStringT<100> fixedString100; - CryFixedStringT<200> fixedString200; - - typedef CryStackStringT T; - T* pStr = new T; - * pStr = "adads"; - delete pStr; - - str1 = "abcd"; - UnitAssert ("Assignment1-EnoughSpace", str1, "abcd"); - - str2 = "efg"; - UnitAssert ("Assignment2-EnoughSpace", str2, "efg"); - - str2 = str1; - UnitAssert ("Assignment3-EnoughSpace", str2, "abcd"); - - str3 = str1; - UnitAssert ("Assignment4-NotEnoughSpace", str3, "abcd"); - - str1 += "XY"; - UnitAssert ("Concatenate-EnoughSpace", str1, "abcdXY"); - - str2 += "efghijk"; - UnitAssert ("Concatenate-NotEnoughSpace", str2, "abcdefghijk"); - - str1.replace("bc", ""); - UnitAssert ("Replace-Shrink-EnoughSpace", str1, "adXY"); - - str1.replace("XY", "1234"); - UnitAssert ("Replace-Grow-EnoughSpace", str1, "ad1234"); - - str1.replace("1234", "1234567890"); - UnitAssert ("Replace-Grow-NotEnoughSpace", str1, "ad1234567890"); - - str1.reserve(200); - UnitAssert ("Reserve200-SameString", str1, "ad1234567890"); - UnitAssert ("Reserve200-Capacity", str1.capacity() == 200); - - str1.reserve(0); - UnitAssert ("Reserve0-SameString", str1, "ad1234567890"); - UnitAssert ("Reserve0-Capacity==Length", str1.capacity() == str1.length()); - - str1.erase(7); // doesn't change capacity - UnitAssert ("Erase-SameString", str1, "ad12345"); - - str4.assign("abc"); - UnitAssert ("Str4 Assignment", str4, "abc"); - str4.reserve(9); - UnitAssert ("Str4", str4.capacity() >= 9); // capacity is always >= MAX_SIZE-1 - str4.reserve(0); - UnitAssert ("Str4-Shrink", str4.capacity() >= 9); // capacity is always >= MAX_SIZE-1 - - size_t idx = str1.find("123"); - UnitAssert ("Str1-Find", idx == 2); - - idx = str1.find("123", 3); - UnitAssert ("Str1-Find", idx == str1.npos); - - wstr1 = L"abc"; - UnitAssert ("WStr1-Assign", wstr1, L"abc"); - UnitAssert ("WStr1-CompareCaseGT", wstr1.compare(L"aBc") > 0); - UnitAssert ("WStr1-CompareCaseLT", wstr1.compare(L"babc") < 0); - UnitAssert ("WStr1-CompareNoCase", wstr1.compareNoCase(L"aBc") == 0); - - str1.Format("This is a %s %S with %d params", "mixed", L"string", 3); - str2.Format("This is a %S %s with %d params", L"mixed", "string", 3); - UnitAssert ("Str1-Format1", str1, "This is a mixed string with 3 params"); - UnitAssert ("Str1-Format2", str1, str2); - - wstr1.Format(L"This is a %s %S with %d params", L"mixed", "string", 3); - wstr2.Format(L"This is a %S %s with %d params", "mixed", L"string", 3); - UnitAssert ("WStr1-Format1", wstr1, L"This is a mixed string with 3 params"); - UnitAssert ("WStr1-Format2", wstr1, wstr2); - - str5.FormatFast("%s", "12345"); - UnitAssert ("Str5-FormatFast", str5, "12345"); - - str5.FormatFast("%s", "012345"); - UnitAssert ("Str5-FormatFast-Truncate", str5, "01234"); - - fixedString100 = str5; - str2 = fixedString200; - fixedString200 = fixedString100; - UnitAssert ("FixedString-Test2", fixedString100, "01234"); - UnitAssert ("FixedString-Test1", fixedString100, fixedString200); - - CryStackStringT testStr; - CryFixedStringT<100> testStr2; - CryFixedWStringT<100> testWStr1; - string normalString; - wstring normalWString; - normalString = string(testStr); - normalString = string(testStr2); - normalString.assign(testStr2.c_str()); - // normalString = testStr; // <- must NOT compile, as we don't allow it! - // normalWString = testWStr1; // <- must NOT compile, as we don't allow it! - normalWString = wstring(testWStr1); - return 0; - } -}; -#endif // #if UNITTEST_CRYFIXEDSTRING - -#endif // CRYINCLUDE_CRYCOMMON_CRYFIXEDSTRING_H diff --git a/Code/Legacy/CryCommon/CryListenerSet.h b/Code/Legacy/CryCommon/CryListenerSet.h index 6addfa384e..6857cf7e5d 100644 --- a/Code/Legacy/CryCommon/CryListenerSet.h +++ b/Code/Legacy/CryCommon/CryListenerSet.h @@ -182,7 +182,7 @@ private: // DO NOT REMOVE - following methods only to be accessed only via CN }; typedef std::vector TListenerVec; - typedef std::vector TAllocatedNameVec; + typedef std::vector TAllocatedNameVec; inline void StartNotificationScope(); inline void EndNotificationScope(); diff --git a/Code/Legacy/CryCommon/CryName.h b/Code/Legacy/CryCommon/CryName.h index 0495ad78f1..8e62a52517 100644 --- a/Code/Legacy/CryCommon/CryName.h +++ b/Code/Legacy/CryCommon/CryName.h @@ -395,13 +395,13 @@ inline bool CCryName::operator>(const CCryName& n) const return m_str > n.m_str; } -inline bool operator==(const string& s, const CCryName& n) +inline bool operator==(const AZStd::string& s, const CCryName& n) { - return n == s; + return s == n; } -inline bool operator!=(const string& s, const CCryName& n) +inline bool operator!=(const AZStd::string& s, const CCryName& n) { - return n != s; + return s != n; } inline bool operator==(const char* s, const CCryName& n) @@ -543,13 +543,13 @@ inline bool CCryNameCRC::operator>(const CCryNameCRC& n) const return m_nID > n.m_nID; } -inline bool operator==(const string& s, const CCryNameCRC& n) +inline bool operator==(const AZStd::string& s, const CCryNameCRC& n) { - return n == s; + return s == n; } -inline bool operator!=(const string& s, const CCryNameCRC& n) +inline bool operator!=(const AZStd::string& s, const CCryNameCRC& n) { - return n != s; + return s != n; } inline bool operator==(const char* s, const CCryNameCRC& n) diff --git a/Code/Legacy/CryCommon/CryPath.h b/Code/Legacy/CryCommon/CryPath.h index 32db308a85..e01e7a2e4b 100644 --- a/Code/Legacy/CryCommon/CryPath.h +++ b/Code/Legacy/CryCommon/CryPath.h @@ -17,6 +17,8 @@ #include #include #include +#include +#include #include "platform.h" @@ -31,26 +33,28 @@ #define CRY_NATIVE_PATH_SEPSTR DOS_PATH_SEP_STR #endif +typedef AZStd::fixed_string<512> stack_string; + namespace PathUtil { const static int maxAliasLength = 32; - inline string GetLocalizationFolder() + inline AZStd::string GetLocalizationFolder() { return gEnv->pCryPak->GetLocalizationFolder(); } - inline string GetLocalizationRoot() + inline AZStd::string GetLocalizationRoot() { return gEnv->pCryPak->GetLocalizationRoot(); } //! Convert a path to the uniform form. - inline string ToUnixPath(const string& strPath) + inline AZStd::string ToUnixPath(const AZStd::string& strPath) { - if (strPath.find(DOS_PATH_SEP_CHR) != string::npos) + if (strPath.find(DOS_PATH_SEP_CHR) != AZStd::string::npos) { - string path = strPath; - path.replace(DOS_PATH_SEP_CHR, UNIX_PATH_SEP_CHR); + AZStd::string path = strPath; + AZ::StringFunc::Replace(path, DOS_PATH_SEP_CHR, UNIX_PATH_SEP_CHR); return path; } return strPath; @@ -73,19 +77,19 @@ namespace PathUtil } //! Convert a path to the DOS form. - inline string ToDosPath(const string& strPath) + inline AZStd::string ToDosPath(const AZStd::string& strPath) { - if (strPath.find(UNIX_PATH_SEP_CHR) != string::npos) + if (strPath.find(UNIX_PATH_SEP_CHR) != AZStd::string::npos) { - string path = strPath; - path.replace(UNIX_PATH_SEP_CHR, DOS_PATH_SEP_CHR); + AZStd::string path = strPath; + AZ::StringFunc::Replace(path, UNIX_PATH_SEP_CHR, DOS_PATH_SEP_CHR); return path; } return strPath; } //! Convert a path to the Native form. - inline string ToNativePath(const string& strPath) + inline AZStd::string ToNativePath(const AZStd::string& strPath) { #if AZ_LEGACY_CRYCOMMON_TRAIT_USE_UNIX_PATHS return ToUnixPath(strPath); @@ -95,10 +99,10 @@ namespace PathUtil } //! Convert a path to lowercase form - inline string ToLower(const string& strPath) + inline AZStd::string ToLower(const AZStd::string& strPath) { - string path = strPath; - path.MakeLower(); + AZStd::string path = strPath; + AZStd::to_lower(path.begin(), path.end()); return path; } @@ -108,9 +112,9 @@ namespace PathUtil //! @param path [OUT] Extracted file path. //! @param filename [OUT] Extracted file (without extension). //! @param ext [OUT] Extracted files extension. - inline void Split(const string& filepath, string& path, string& filename, string& fext) + inline void Split(const AZStd::string& filepath, AZStd::string& path, AZStd::string& filename, AZStd::string& fext) { - path = filename = fext = string(); + path = filename = fext = AZStd::string(); if (filepath.empty()) { return; @@ -142,16 +146,16 @@ namespace PathUtil //! @param filepath [IN] Full file name inclusing path. //! @param path [OUT] Extracted file path. //! @param file [OUT] Extracted file (with extension). - inline void Split(const string& filepath, string& path, string& file) + inline void Split(const AZStd::string& filepath, AZStd::string& path, AZStd::string& file) { - string fext; + AZStd::string fext; Split(filepath, path, file, fext); file += fext; } // Extract extension from full specified file path // Returns - // pointer to the extension (without .) or pointer to an empty 0-terminated string + // pointer to the extension (without .) or pointer to an empty 0-terminated AZStd::string inline const char* GetExt(const char* filepath) { const char* str = filepath; @@ -174,7 +178,7 @@ namespace PathUtil } //! Extract path from full specified file path. - inline string GetPath(const string& filepath) + inline AZStd::string GetPath(const AZStd::string& filepath) { const char* str = filepath.c_str(); for (const char* p = str + filepath.length() - 1; p >= str; --p) @@ -191,9 +195,9 @@ namespace PathUtil } //! Extract path from full specified file path. - inline string GetPath(const char* filepath) + inline AZStd::string GetPath(const char* filepath) { - return GetPath(string(filepath)); + return GetPath(AZStd::string(filepath)); } //! Extract path from full specified file path. @@ -214,7 +218,7 @@ namespace PathUtil } //! Extract file name with extension from full specified file path. - inline string GetFile(const string& filepath) + inline AZStd::string GetFile(const AZStd::string& filepath) { const char* str = filepath.c_str(); for (const char* p = str + filepath.length() - 1; p >= str; --p) @@ -247,7 +251,7 @@ namespace PathUtil } //! Replace extension for given file. - inline void RemoveExtension(string& filepath) + inline void RemoveExtension(AZStd::string& filepath) { const char* str = filepath.c_str(); for (const char* p = str + filepath.length() - 1; p >= str; --p) @@ -291,15 +295,15 @@ namespace PathUtil } //! Extract file name without extension from full specified file path. - inline string GetFileName(const string& filepath) + inline AZStd::string GetFileName(const AZStd::string& filepath) { - string file = filepath; + AZStd::string file = filepath; RemoveExtension(file); return GetFile(file); } //! Removes the trailing slash or backslash from a given path. - inline string RemoveSlash(const string& path) + inline AZStd::string RemoveSlash(const AZStd::string& path) { if (path.empty() || (path[path.length() - 1] != '/' && path[path.length() - 1] != '\\')) { @@ -309,13 +313,13 @@ namespace PathUtil } //! get slash - inline string GetSlash() + inline AZStd::string GetSlash() { return CRY_NATIVE_PATH_SEPSTR; } //! add a backslash if needed - inline string AddSlash(const string& path) + inline AZStd::string AddSlash(const AZStd::string& path) { if (path.empty() || path[path.length() - 1] == '/') { @@ -343,9 +347,9 @@ namespace PathUtil } //! add a backslash if needed - inline string AddSlash(const char* path) + inline AZStd::string AddSlash(const char* path) { - return AddSlash(string(path)); + return AddSlash(AZStd::string(path)); } inline stack_string ReplaceExtension(const stack_string& filepath, const char* ext) @@ -364,9 +368,9 @@ namespace PathUtil } //! Replace extension for given file. - inline string ReplaceExtension(const string& filepath, const char* ext) + inline AZStd::string ReplaceExtension(const AZStd::string& filepath, const char* ext) { - string str = filepath; + AZStd::string str = filepath; if (ext != 0) { RemoveExtension(str); @@ -380,29 +384,30 @@ namespace PathUtil } //! Replace extension for given file. - inline string ReplaceExtension(const char* filepath, const char* ext) + inline AZStd::string ReplaceExtension(const char* filepath, const char* ext) { - return ReplaceExtension(string(filepath), ext); + return ReplaceExtension(AZStd::string(filepath), ext); } //! Makes a fully specified file path from path and file name. - inline string Make(const string& path, const string& file) + inline AZStd::string Make(const AZStd::string& path, const AZStd::string& file) { return AddSlash(path) + file; } //! Makes a fully specified file path from path and file name. - inline string Make(const string& dir, const string& filename, const string& ext) + inline AZStd::string Make(const AZStd::string& dir, const AZStd::string& filename, const AZStd::string& ext) { - string path = ReplaceExtension(filename, ext); + AZStd::string path = filename; + AZ::StringFunc::Path::ReplaceExtension(path, ext.c_str()); path = AddSlash(dir) + path; return path; } //! Makes a fully specified file path from path and file name. - inline string Make(const string& dir, const string& filename, const char* ext) + inline AZStd::string Make(const AZStd::string& dir, const AZStd::string& filename, const char* ext) { - return Make(dir, filename, string(ext)); + return Make(dir, filename, AZStd::string(ext)); } //! Makes a fully specified file path from path and file name. @@ -414,42 +419,43 @@ namespace PathUtil //! Makes a fully specified file path from path and file name. inline stack_string Make(const stack_string& dir, const stack_string& filename, const stack_string& ext) { - stack_string path = ReplaceExtension(filename, ext); - path = AddSlash(dir) + path; - return path; + AZStd::string path = filename; + AZ::StringFunc::Path::ReplaceExtension(path, ext.c_str()); + path = AddSlash(dir.c_str()) + path; + return stack_string(path.c_str()); } //! Makes a fully specified file path from path and file name. - inline string Make(const char* path, const string& file) + inline AZStd::string Make(const char* path, const AZStd::string& file) { - return Make(string(path), file); + return Make(AZStd::string(path), file); } //! Makes a fully specified file path from path and file name. - inline string Make(const string& path, const char* file) + inline AZStd::string Make(const AZStd::string& path, const char* file) { - return Make(path, string(file)); + return Make(path, AZStd::string(file)); } //! Makes a fully specified file path from path and file name. - inline string Make(const char path[], const char file[]) + inline AZStd::string Make(const char path[], const char file[]) { - return Make(string(path), string(file)); + return Make(AZStd::string(path), AZStd::string(file)); } //! Makes a fully specified file path from path and file name. - inline string Make(const char* path, const char* file, const char* ext) + inline AZStd::string Make(const char* path, const char* file, const char* ext) { - return Make(string(path), string(file), string(ext)); + return Make(AZStd::string(path), AZStd::string(file), AZStd::string(ext)); } //! Makes a fully specified file path from path and file name. - inline string MakeFullPath(const string& relativePath) + inline AZStd::string MakeFullPath(const AZStd::string& relativePath) { return relativePath; } - inline string GetParentDirectory (const string& strFilePath, int nGeneration = 1) + inline AZStd::string GetParentDirectory (const AZStd::string& strFilePath, int nGeneration = 1) { for (const char* p = strFilePath.c_str() + strFilePath.length() - 2; // -2 is for the possible trailing slash: there always must be some trailing symbol which is the file/directory name for which we should get the parent p >= strFilePath.c_str(); @@ -458,23 +464,23 @@ namespace PathUtil switch (*p) { case ':': - return string (strFilePath.c_str(), p); + return AZStd::string(strFilePath.c_str(), p); case '/': case '\\': // we've reached a path separator - return everything before it. if (!--nGeneration) { - return string(strFilePath.c_str(), p); + return AZStd::string(strFilePath.c_str(), p); } break; } } // it seems the file name is a pure name, without path or extension - return string(); + return AZStd::string(); } template - inline CryStackStringT GetParentDirectoryStackString(const CryStackStringT& strFilePath, int nGeneration = 1) + inline AZStd::basic_fixed_string GetParentDirectoryStackString(const AZStd::basic_fixed_string& strFilePath, int nGeneration = 1) { for (const char* p = strFilePath.c_str() + strFilePath.length() - 2; // -2 is for the possible trailing slash: there always must be some trailing symbol which is the file/directory name for which we should get the parent p >= strFilePath.c_str(); @@ -483,19 +489,19 @@ namespace PathUtil switch (*p) { case ':': - return CryStackStringT (strFilePath.c_str(), p); + return AZStd::basic_fixed_string (strFilePath.c_str(), p); case '/': case '\\': // we've reached a path separator - return everything before it. if (!--nGeneration) { - return CryStackStringT(strFilePath.c_str(), p); + return AZStd::basic_fixed_string(strFilePath.c_str(), p); } break; } } // it seems the file name is a pure name, without path or extension - return CryStackStringT(); + return AZStd::basic_fixed_string(); } ////////////////////////////////////////////////////////////////////////// @@ -503,7 +509,8 @@ namespace PathUtil // Make a game correct path out of any input path. inline stack_string MakeGamePath(const stack_string& path) { - stack_string relativePath(ToUnixPath(path)); + stack_string relativePath = path; + ToUnixPath(relativePath); if ((!gEnv) || (!gEnv->pFileIO)) { @@ -512,7 +519,7 @@ namespace PathUtil unsigned int index = 0; if (relativePath.length() && relativePath[index] == '@') // already aliased { - if (relativePath.compareNoCase(0, 9, "@assets@/") == 0) + if (AZ::StringFunc::Equal(relativePath.c_str(), "@assets@/", false, 9)) { return relativePath.substr(9); // assets is assumed. } @@ -526,7 +533,7 @@ namespace PathUtil if ( (rootPath.size() > 0) && (rootPath.size() < relativePath.size()) && - (relativePath.compareNoCase(0, rootPath.size(), rootPath) == 0) + (AZ::StringFunc::Equal(relativePath.c_str(), rootPath.c_str(), false, rootPath.size())) ) { stack_string chopped_string = relativePath.substr(rootPath.size()); @@ -543,13 +550,13 @@ namespace PathUtil ////////////////////////////////////////////////////////////////////////// // Description: // Make a game correct path out of any input path. - inline string MakeGamePath(const string& path) + inline AZStd::string MakeGamePath(const AZStd::string& path) { stack_string stackPath(path.c_str()); return MakeGamePath(stackPath).c_str(); } - // returns true if the string matches the wildcard + // returns true if the AZStd::string matches the wildcard inline bool MatchWildcard (const char* szString, const char* szWildcard) { const char* pString = szString, * pWildcard = szWildcard; @@ -595,7 +602,7 @@ namespace PathUtil if (!*pWildcard) { - return true; // the rest of the string doesn't matter: the wildcard ends with * + return true; // the rest of the AZStd::string doesn't matter: the wildcard ends with * } for (; *pString; ++pString) { diff --git a/Code/Legacy/CryCommon/CrySizer.h b/Code/Legacy/CryCommon/CrySizer.h index 9301360bd5..add2cdd397 100644 --- a/Code/Legacy/CryCommon/CrySizer.h +++ b/Code/Legacy/CryCommon/CrySizer.h @@ -208,9 +208,7 @@ public: this->AddObject(rPair.first); this->AddObject(rPair.second); } - void AddObject(const string& rString) {this->AddObject(rString.c_str(), rString.capacity()); } - void AddObject(const CryStringT& rString) {this->AddObject(rString.c_str(), rString.capacity()); } - void AddObject(const CryFixedStringT<32>&){} + void AddObject(const AZStd::string& rString) {this->AddObject(rString.c_str(), rString.capacity()); } void AddObject(const wchar_t&) {} void AddObject(const char&) {} void AddObject(const unsigned char&) {} @@ -427,7 +425,7 @@ public: #endif #ifndef NOT_USE_CRY_STRING - bool Add (const string& strText) + bool Add (const AZStd::string& strText) { AddString(strText); return true; diff --git a/Code/Legacy/CryCommon/CryString.h b/Code/Legacy/CryCommon/CryString.h deleted file mode 100644 index 72469e3dca..0000000000 --- a/Code/Legacy/CryCommon/CryString.h +++ /dev/null @@ -1,2523 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - -// Description : Custom reference counted string class. -// Can easily be substituted instead of string - - -#ifndef CRYINCLUDE_CRYCOMMON_CRYSTRING_H -#define CRYINCLUDE_CRYCOMMON_CRYSTRING_H -#pragma once - -#include -#include - -#if !defined(NOT_USE_CRY_STRING) - -#include -#include -#include -#include -#include -#include "LegacyAllocator.h" - -#define CRY_STRING - -// forward declaration of CryStackString -template -class CryStackStringT; - - -class CConstCharWrapper; //forward declaration for special const char * without memory allocations - -//extern void CryDebugStr( const char *format,... ); -//#define CRY_STRING_DEBUG(s) { if (*s) CryDebugStr( "[%6d] %s",_usedMemory(0),(s) );} -#define CRY_STRING_DEBUG(s) - -class CryStringAllocator - : public AZ::SimpleSchemaAllocator -{ -public: - AZ_TYPE_INFO(CryStringAllocator, "{763DFC83-8A6E-4FD9-B6BC-BBF56E93E4EE}"); - - using Base = AZ::SimpleSchemaAllocator; - using Descriptor = Base::Descriptor; - - CryStringAllocator() - : Base("CryStringAllocator", "Allocator for CryString") - { - Descriptor desc; - desc.m_systemChunkSize = 4 * 1024 * 1024; // grow by 4 MB at a time - desc.m_subAllocator = &AZ::AllocatorInstance::Get(); - Create(desc); - } -}; - -////////////////////////////////////////////////////////////////////////// -// CryStringT class. -////////////////////////////////////////////////////////////////////////// -template -class CryStringT -{ -public: - ////////////////////////////////////////////////////////////////////////// - // Types compatible with STL string. - ////////////////////////////////////////////////////////////////////////// - typedef CryStringT _Self; - typedef size_t size_type; - typedef T value_type; - typedef const value_type* const_str; - typedef value_type* pointer; - typedef const value_type* const_pointer; - typedef value_type& reference; - typedef const value_type& const_reference; - typedef pointer iterator; - typedef const_pointer const_iterator; - - enum _npos_type - { - npos = (size_type) ~0 - }; - - ////////////////////////////////////////////////////////////////////////// - // Constructors - ////////////////////////////////////////////////////////////////////////// - CryStringT(); - -protected: - CryStringT(const CConstCharWrapper& str); //ctor for strings without memory allocations - friend class CConstCharWrapper; -public: - - CryStringT(const _Self& str); - CryStringT(const _Self& str, size_type nOff, size_type nCount); - - // Before September 2012 this constructor looked like this: - // explicit CryStringT( value_type ch, size_type nRepeat = 1 ); - // It was very error-prone, because the matching constructor - // std::string constructor is different: - // std::string( size_type nRepeat, value_type ch ); - // - // To prevent hard-to-catch bugs, we removed all calls of this - // constructor in the existing CryEngine code (in September 2012) - // and started using proper order of parameters (matching std::). - // - // To catch calls using the reversed arguments in other projects, - // we retain the previous function with reversed arguments, - // and declare it private. - CryStringT(size_type nRepeat, value_type ch); -private: - CryStringT(value_type ch, size_type nRepeat); - -public: - - CryStringT(const_str str); - CryStringT(const_str str, size_type nLength); - CryStringT(const_iterator _First, const_iterator _Last); - ~CryStringT(); - - ////////////////////////////////////////////////////////////////////////// - // STL string like interface. - ////////////////////////////////////////////////////////////////////////// - //! Operators. - size_type length() const; - size_type size() const; - bool empty() const; - void clear(); // free up the data - - //! Returns the storage currently allocated to hold the string, a value at least as large as length(). - size_type capacity() const; - - // Sets the capacity of the string to a number at least as great as a specified number. - // nCount = 0 is shrinking string to fit number of characters in it. - void reserve(size_type nCount = 0); - - _Self& append(const value_type* _Ptr); - _Self& append(const value_type* _Ptr, size_type nCount); - _Self& append(const _Self& _Str, size_type nOff, size_type nCount); - _Self& append(const _Self& _Str); - _Self& append(size_type nCount, value_type _Ch); - _Self& append(const_iterator _First, const_iterator _Last); - - _Self& assign(const_str _Ptr); - _Self& assign(const_str _Ptr, size_type nCount); - _Self& assign(const _Self& _Str, size_type off, size_type nCount); - _Self& assign(const _Self& _Str); - _Self& assign(size_type nCount, value_type _Ch); - _Self& assign(const_iterator _First, const_iterator _Last); - - value_type at(size_type index) const; - - const_iterator begin() const { return m_str; }; - const_iterator end() const { return m_str + length(); }; - - iterator begin() { return m_str; }; - iterator end() { return m_str + length(); }; - - // Following functions are commented out because they provide direct write access to - // the string and such access doesn't work properly with our current reference-count - // implementation. - // If you really need write access to your string's elements, please consider - // using CryStackStringT<> instead of CryString<>. Alternatively, you can modify - // your string by multiple calls of erase() and append(). - // Note: If you need *linear memory read* access to your string's elements, use data() - // or c_str(). If you need *linear memory write* access to your string's elements, - // use a non-string class (std::vector<>, DynArray<>, etc.) instead of CryString<>. - //value_type& at( size_type index ); - //iterator begin() { return m_str; }; - //iterator end() { return m_str+length(); }; - - //! cast to C string operator. - operator const_str() const { - return m_str; - } - - //! cast to C string. - const value_type* c_str() const { return m_str; } - const value_type* data() const { return m_str; }; - - ////////////////////////////////////////////////////////////////////////// - // string comparison. - ////////////////////////////////////////////////////////////////////////// - int compare(const _Self& _Str) const; - int compare(size_type _Pos1, size_type _Num1, const _Self& _Str) const; - int compare(size_type _Pos1, size_type _Num1, const _Self& _Str, size_type nOff, size_type nCount) const; - int compare(const char* _Ptr) const; - int compare(const wchar_t* _Ptr) const; - int compare(size_type _Pos1, size_type _Num1, const value_type* _Ptr, size_type _Num2 = npos) const; - - // Case insensitive comparison - int compareNoCase(const _Self& _Str) const; - int compareNoCase(size_type _Pos1, size_type _Num1, const _Self& _Str) const; - int compareNoCase(size_type _Pos1, size_type _Num1, const _Self& _Str, size_type nOff, size_type nCount) const; - int compareNoCase(const value_type* _Ptr) const; - int compareNoCase(size_type _Pos1, size_type _Num1, const value_type* _Ptr, size_type _Num2 = npos) const; - - // Copies at most a specified number of characters from an indexed position in a source string to a target character array. - size_type copy(value_type* _Ptr, size_type nCount, size_type nOff = 0) const; - - void push_back(value_type _Ch) { _ConcatenateInPlace(&_Ch, 1); } - void resize(size_type nCount, value_type _Ch = ' '); - - //! simple sub-string extraction - _Self substr(size_type pos, size_type count = npos) const; - - // replace part of string. - _Self& replace(value_type chOld, value_type chNew); - _Self& replace(const_str strOld, const_str strNew); - _Self& replace(size_type pos, size_type count, const_str strNew); - _Self& replace(size_type pos, size_type count, const_str strNew, size_type count2); - _Self& replace(size_type pos, size_type count, size_type nNumChars, value_type chNew); - - // insert new elements to string. - _Self& insert(size_type nIndex, value_type ch); - _Self& insert(size_type nIndex, size_type nCount, value_type ch); - _Self& insert(size_type nIndex, const_str pstr); - _Self& insert(size_type nIndex, const_str pstr, size_type nCount); - - //! delete count characters starting at zero-based index - _Self& erase(size_type nIndex, size_type count = npos); - - //! searching (return starting index, or -1 if not found) - //! look for a single character match - //! like "C" strchr - size_type find(value_type ch, size_type pos = 0) const; - //! look for a specific sub-string - //! like "C" strstr - size_type find(const_str subs, size_type pos = 0) const; - size_type rfind(value_type ch, size_type pos = npos) const; - size_type rfind(const _Self& subs, size_type pos = 0) const; - - size_type find_first_of(value_type _Ch, size_type nOff = 0) const; - size_type find_first_of(const_str charSet, size_type nOff = 0) const; - //size_type find_first_of( const value_type* _Ptr,size_type _Off,size_type _Count ) const; - size_type find_first_of(const _Self& _Str, size_type _Off = 0) const; - - size_type find_first_not_of(value_type _Ch, size_type _Off = 0) const; - size_type find_first_not_of(const value_type* _Ptr, size_type _Off = 0) const; - size_type find_first_not_of(const value_type* _Ptr, size_type _Off, size_type _Count) const; - size_type find_first_not_of(const _Self& _Str, size_type _Off = 0) const; - - size_type find_last_of(value_type _Ch, size_type _Off = npos) const; - size_type find_last_of(const value_type* _Ptr, size_type _Off = npos) const; - size_type find_last_of(const value_type* _Ptr, size_type _Off, size_type _Count) const; - size_type find_last_of(const _Self& _Str, size_type _Off = npos) const; - - size_type find_last_not_of(value_type _Ch, size_type _Off = npos) const; - size_type find_last_not_of(const value_type* _Ptr, size_type _Off = npos) const; - size_type find_last_not_of(const value_type* _Ptr, size_type _Off, size_type _Count) const; - size_type find_last_not_of(const _Self& _Str, size_type _Off = npos) const; - - - void swap(_Self& _Str); - - ////////////////////////////////////////////////////////////////////////// - // overloaded operators. - ////////////////////////////////////////////////////////////////////////// - // overloaded indexing. - //value_type operator[]( size_type index ) const; // same as at() - // value_type& operator[]( size_type index ); // same as at() - - // overloaded assignment - _Self& operator=(const _Self& str); - _Self& operator=(value_type ch); - _Self& operator=(const_str str); - - template - CryStringT(const CryStackStringT& str); - -protected: - // we prohibit an implicit conversion from CryStackString to make user aware of allocation! - // -> use string(stackedString) instead - // as the private statement seems to be ignored (VS C++), we add a compile time error, see below - template - _Self& operator=(const CryStackStringT& str) - { - // we add a compile-time error as the Visual C++ compiler seems to ignore the private statement? -#if defined(__clang__) - //CLANG_TODO: clang verifies things differently -#else - static_assert(false, "Use explicit string assignment when assigning from_StackString"); -#endif - // not reached, as above will generate a compile time error - _Assign(str.c_str(), str.length()); - return *this; - } - -public: - // string concatenation - _Self& operator+=(const _Self& str); - _Self& operator+=(value_type ch); - _Self& operator+=(const_str str); - - //template friend CryStringT operator+( const CryStringT& str1, const CryStringT& str2 ); - //template friend CryStringT operator+( const CryStringT& str, value_type ch ); - //template friend CryStringT operator+( value_type ch, const CryStringT& str ); - //template friend CryStringT operator+( const CryStringT& str1, const_str str2 ); - //template friend CryStringT operator+( const_str str1, const CryStringT& str2 ); - - size_t GetAllocatedMemory() const - { - StrHeader* header = _header(); - if (header == _emptyHeader()) - { - return 0; - } - return sizeof(StrHeader) + (header->nAllocSize + 1) * sizeof(value_type); - } - - ////////////////////////////////////////////////////////////////////////// - // Extended functions. - // This functions are not in the STL string. - // They have an ATL CString interface. - ////////////////////////////////////////////////////////////////////////// - //! Format string, use (sprintf) - _Self& Format(const value_type* format, ...); - - //! Converts the string to lower-case - // This function uses the "C" locale for case-conversion (ie, A-Z only) - _Self& MakeLower(); - - //! Converts the string to upper-case - // This function uses the "C" locale for case-conversion (ie, A-Z only) - _Self& MakeUpper(); - - _Self& Trim(); - _Self& Trim(value_type ch); - _Self& Trim(const value_type* sCharSet); - - _Self& TrimLeft(); - _Self& TrimLeft(value_type ch); - _Self& TrimLeft(const value_type* sCharSet); - - _Self& TrimRight(); - _Self& TrimRight(value_type ch); - _Self& TrimRight(const value_type* sCharSet); - - _Self SpanIncluding(const_str charSet) const; - _Self SpanExcluding(const_str charSet) const; - _Self Tokenize(const_str charSet, int& nStart) const; - _Self Mid(size_type nFirst, size_type nCount = npos) const { return substr(nFirst, nCount); }; - - _Self Left(size_type count) const; - _Self Right(size_type count) const; - ////////////////////////////////////////////////////////////////////////// - - // public utilities. - static size_type _strlen(const_str str); - static size_type _strnlen(const_str str, size_type maxLen); - static const_str _strchr(const_str str, value_type c); - static const_str _strrchr(const_str str, value_type c); - static value_type* _strstr(value_type* str, const_str strSearch); - static bool _IsValidString(const_str str); - -#if defined(WIN32) || defined(WIN64) - static int _vscpf(const_str format, va_list args); -#endif - static int _vsnpf(value_type* buf, int cnt, const_str format, va_list args); - - -public: - ////////////////////////////////////////////////////////////////////////// - // Only used for debugging statistics. - ////////////////////////////////////////////////////////////////////////// - static size_t _usedMemory(ptrdiff_t size) - { - static size_t s_used_memory = 0; - s_used_memory += size; - return s_used_memory; - } - -protected: - value_type* m_str; // pointer to ref counted string data - - // String header. Immediately after this header in memory starts actual string data. - struct StrHeader - { - int nRefCount; - int nLength; - int nAllocSize; // Size of memory allocated at the end of this class. - - value_type* GetChars() { return (value_type*)(this + 1); } - void AddRef() { nRefCount++; /*InterlockedIncrement(&_header()->nRefCount);*/}; - int Release() { return --nRefCount; }; - }; - static StrHeader* _emptyHeader() - { - // Define 2 static buffers in a row. The 2nd is a dummy object to hold a single empty char string. - static StrHeader sEmptyStringBuffer[2] = { - {-1, 0, 0}, {0, 0, 0} - }; - return &sEmptyStringBuffer[0]; - } - - // implementation helpers - StrHeader* _header() const; - - void _AllocData(size_type nLen); - static void _FreeData(StrHeader* pData); - void _Free(); - void _Initialize(); - - void _Concatenate(const_str sStr1, size_type nLen1, const_str sStr2, size_type nLen2); - void _ConcatenateInPlace(const_str sStr, size_type nLen); - void _Assign(const_str sStr, size_type nLen); - void _MakeUnique(); - - static void _copy(value_type* dest, const value_type* src, size_type count); - static void _move(value_type* dest, const value_type* src, size_type count); - static void _set(value_type* dest, value_type ch, size_type count); -}; - -// Variant of CryStringT which does not share memory with other strings. -template -class CryStringLocalT - : public CryStringT -{ -public: - typedef CryStringT BaseType; - typedef typename BaseType::const_str const_str; - typedef typename BaseType::value_type value_type; - typedef typename BaseType::size_type size_type; - typedef typename BaseType::iterator iterator; - - CryStringLocalT() - {} - CryStringLocalT(const CryStringLocalT& str) - : BaseType(str.c_str()) - {} - CryStringLocalT(const BaseType& str) - : BaseType(str.c_str()) - {} - template - CryStringLocalT(const CryStackStringT& str) - : BaseType(str.c_str()) - {} - CryStringLocalT(const_str str) - : BaseType(str) - {} - CryStringLocalT(const_str str, size_t len) - : BaseType(str, len) - {} - CryStringLocalT(const_str begin, const_str end) - : BaseType(begin, end) - {} - CryStringLocalT(size_type nRepeat, value_type ch) - : BaseType(nRepeat, ch) - {} - - CryStringLocalT(const typename CryStringT::_Self& str, size_type nOff, size_type nCount) - : BaseType(str, nOff, nCount) - {} - - CryStringLocalT& operator=(const BaseType& str) - { - BaseType::operator=(str.c_str()); - return *this; - } - CryStringLocalT& operator=(const CryStringLocalT& str) - { - BaseType::operator=(str.c_str()); - return *this; - } - CryStringLocalT& operator=(const_str str) - { - BaseType::operator=(str); - return *this; - } - iterator begin() { return BaseType::m_str; } - using BaseType::begin; // const version - iterator end() { return BaseType::m_str + BaseType::length(); } - using BaseType::end; // const version -}; - -typedef CryStringLocalT CryStringLocal; - - -// wrapper class for creation of strings without memory allocation -// it creates a string with pointer pointing to const char* location -// destructor sets the string to empty -// NOTE: never copy a string from it, just use it as function parameters instead of const char* itself -class CConstCharWrapper -{ -public: - //passing *this is safe since the char pointer is already set and therefore is the this-ptr constructed complete enough -#pragma warning (push) -#pragma warning (disable : 4355) - CConstCharWrapper(const char* const cpString) - : cpChar(cpString) - , str(*this){AZ_Assert(cpString, "c-string parameter cannot be nullptr"); } //create stack string -#pragma warning (pop) - ~CConstCharWrapper(){str.m_str = CryStringT::_emptyHeader()->GetChars(); }//reset string - operator const CryStringT&() const { - return str; - } //cast operator to const string reference -private: - const char* const cpChar; - CryStringT str; - - char* GetCharPointer() const {return const_cast(cpChar); } //access function for string ctor - - friend class CryStringT; //both are bidirectional friends to avoid any other accesses -}; - - -//macro needed because compiler somehow cannot find the cast operator when not invoked directly -#define CONST_TEMP_STRING(a) ((const string&)CConstCharWrapper(a)) - -///////////////////////////////////////////////////////////////////////////// -// CryStringT Implementation -////////////////////////////////////////////////////////////////////////// - -template -inline typename CryStringT::StrHeader * CryStringT::_header() const -{ - AZ_Assert(m_str != nullptr, "string header is nullptr"); - return ((StrHeader*)m_str) - 1; -} - -template -inline typename CryStringT::size_type CryStringT::_strlen(const_str str) -{ - return (str == NULL) ? 0 : (size_type)::strlen(str); -} - -template <> -inline CryStringT::size_type CryStringT::_strlen(const_str str) -{ - return (str == NULL) ? 0 : (size_type)::wcslen(str); -} - -template -inline typename CryStringT::size_type CryStringT::_strnlen(const_str str, size_type maxLen) -{ - size_type len = 0; - if (str) - { - while (len < maxLen && *str != '\0') - { - len++; - str++; - } - } - return len; -} - -template -inline typename CryStringT::const_str CryStringT::_strchr(const_str str, value_type c) -{ - return (str == NULL) ? 0 : ::strchr(str, c); -} - -template <> -inline CryStringT::const_str CryStringT::_strchr(const_str str, value_type c) -{ - return (str == NULL) ? 0 : ::wcschr(str, c); -} - -template -inline typename CryStringT::const_str CryStringT::_strrchr(const_str str, value_type c) -{ - return (str == NULL) ? 0 : ::strrchr(str, c); -} - -template <> -inline CryStringT::const_str CryStringT::_strrchr(const_str str, value_type c) -{ - return (str == NULL) ? 0 : ::wcsrchr(str, c); -} - -template -inline typename CryStringT::value_type * CryStringT::_strstr(value_type * str, const_str strSearch) -{ - return (str == NULL) ? 0 : (value_type*)::strstr(str, strSearch); -} - -template <> -inline CryStringT::value_type * CryStringT::_strstr(value_type * str, const_str strSearch) -{ - return (str == NULL) ? 0 : ::wcsstr(str, strSearch); -} - -////////////////////////////////////////////////////////////////////////// -template -inline void CryStringT::_copy(value_type* dest, const value_type* src, size_type count) -{ - if (dest != src) - { - memcpy(dest, src, count * sizeof(value_type)); - } -} - -////////////////////////////////////////////////////////////////////////// -template -inline void CryStringT::_move(value_type* dest, const value_type* src, size_type count) -{ - memmove(dest, src, count * sizeof(value_type)); -} - -////////////////////////////////////////////////////////////////////////// -template -inline void CryStringT::_set(value_type* dest, value_type ch, size_type count) -{ - static_assert(sizeof(value_type) == sizeof(T)); - static_assert(sizeof(value_type) == 1); - memset(dest, ch, count); -} - -////////////////////////////////////////////////////////////////////////// -template <> -inline void CryStringT::_set(value_type* dest, value_type ch, size_type count) -{ - static_assert(sizeof(value_type) == sizeof(wchar_t)); - wmemset(dest, ch, count); -} - -#if defined(WIN32) || defined(WIN64) - -template<> -inline int CryStringT::_vscpf(const_str format, va_list args) -{ - return _vscprintf(format, args); -} - -template<> -inline int CryStringT::_vscpf(const_str format, va_list args) -{ - return _vscwprintf(format, args); -} - -template<> -inline int CryStringT::_vsnpf(value_type* buf, int cnt, const_str format, va_list args) -{ - return azvsnprintf(buf, cnt, format, args); -} - -template<> -inline int CryStringT::_vsnpf(value_type* buf, int cnt, const_str format, va_list args) -{ - return azvsnwprintf(buf, cnt, format, args); -} - -#else - -template<> -inline int CryStringT::_vsnpf(value_type* buf, int cnt, const_str format, va_list args) -{ - return vsnprintf(buf, cnt, format, args); -} - -template<> -inline int CryStringT::_vsnpf(value_type* buf, int cnt, const_str format, va_list args) -{ - return vswprintf(buf, cnt, format, args); -} - -#endif - -////////////////////////////////////////////////////////////////////////// -template -inline bool CryStringT::_IsValidString(const_str) -{ - /* - if (str == NULL) - return false; - int nLength = _strlen(str); - return !::IsBadStringPtrA(str, nLength); - */ - return true; -} - -////////////////////////////////////////////////////////////////////////// -template -inline void CryStringT::_Assign(const_str sStr, size_type nLen) -{ - // Check if this string is shared (reference count greater then 1) or not enough capacity to store new string. - // Then allocate new string buffer. - if (_header()->nRefCount > 1 || nLen > capacity()) - { - _Free(); - _AllocData(nLen); - } - // Copy characters from new string to this buffer. - _copy(m_str, sStr, nLen); - // Set new length. - _header()->nLength = aznumeric_cast(nLen); - // Make null terminated string. - m_str[nLen] = 0; - CRY_STRING_DEBUG(m_str) -} - -////////////////////////////////////////////////////////////////////////// -template -inline void CryStringT::_Concatenate(const_str sStr1, size_type nLen1, const_str sStr2, size_type nLen2) -{ - size_type nLen = nLen1 + nLen2; - - if (nLen1 * 2 > nLen) - { - nLen = nLen1 * 2; - } - - if (nLen != 0) - { - if (nLen < 8) - { - nLen = 8; - } - - _AllocData(nLen); - _copy(m_str, sStr1, nLen1); - _copy(m_str + nLen1, sStr2, nLen2); - _header()->nLength = aznumeric_cast(nLen1 + nLen2); - m_str[nLen1 + nLen2] = 0; - } - CRY_STRING_DEBUG(m_str) -} - -////////////////////////////////////////////////////////////////////////// -template -inline void CryStringT::_ConcatenateInPlace(const_str sStr, size_type nLen) -{ - if (nLen != 0) - { - // Check if this string is shared (reference count greater then 1) or not enough capacity to store new string. - // Then allocate new string buffer. - if (_header()->nRefCount > 1 || length() + nLen > capacity()) - { - StrHeader* pOldData = _header(); - _Concatenate(m_str, length(), sStr, nLen); - _FreeData(pOldData); - } - else - { - _copy(m_str + length(), sStr, nLen); - _header()->nLength = aznumeric_cast(_header()->nLength + nLen); - m_str[_header()->nLength] = 0; // Make null terminated string. - } - } -} - -////////////////////////////////////////////////////////////////////////// -template -inline void CryStringT::_MakeUnique() -{ - if (_header()->nRefCount > 1) - { - // If string is shared, make a copy of string buffer. - StrHeader* pOldData = _header(); - // This will not free header because reference count is greater then 1. - _Free(); - // Allocate a new string buffer. - _AllocData(pOldData->nLength); - // Full copy of null terminated string. - _copy(m_str, pOldData->GetChars(), pOldData->nLength + 1); - CRY_STRING_DEBUG(m_str) - } -} - -////////////////////////////////////////////////////////////////////////// -template -inline void CryStringT::_Initialize() -{ - m_str = _emptyHeader()->GetChars(); -} - -// always allocate one extra character for '\0' termination -// assumes [optimistically] that data length will equal allocation length -template -inline void CryStringT::_AllocData(size_type nLen) -{ - AZ_Assert(nLen <= (std::numeric_limits::max)() - 1, "New string allocation size %zu is greater than the max allowed size of %d", - nLen, (std::numeric_limits::max)() - 1); // max size (enough room for 1 extra) - - if (nLen == 0) - { - _Initialize(); - } - else - { - size_type allocLen = sizeof(StrHeader) + (nLen + 1) * sizeof(value_type); - - StrHeader* pData = (StrHeader*)azmalloc(allocLen, 32, CryStringAllocator); - - _usedMemory(allocLen); // For statistics. - pData->nRefCount = 1; - m_str = pData->GetChars(); - pData->nLength = aznumeric_cast(nLen); - pData->nAllocSize = aznumeric_cast(nLen); - m_str[nLen] = 0; // null terminated string. - } -} - -////////////////////////////////////////////////////////////////////////// -template -inline void CryStringT::_Free() -{ - if (_header()->nRefCount >= 0) // Not empty string. - { - _FreeData(_header()); - _Initialize(); - } -} - -////////////////////////////////////////////////////////////////////////// -template -inline void CryStringT::_FreeData(StrHeader* pData) -{ - //Cry uses -1 to represent strings on the stack. - if (pData->nRefCount < 0) - { - return; - } - - if (pData->nRefCount == 0 || pData->Release() <= 0) - { - azfree((void*)pData, CryStringAllocator); - } -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStringT::CryStringT() -{ - _Initialize(); -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStringT::CryStringT(const CryStringT& str) -{ - AZ_Assert(str._header()->nRefCount != 0, "Reference count input cry string should be greater than 0"); - if (str._header()->nRefCount >= 0) - { - m_str = str.m_str; - _header()->AddRef(); - } - else - { - _Initialize(); - } -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStringT::CryStringT(const CryStringT& str, size_type nOff, size_type nCount) -{ - _Initialize(); - assign(str, nOff, nCount); -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStringT::CryStringT(const_str str) -{ - _Initialize(); - // Make a copy of C string. - size_type nLen = _strlen(str); - if (nLen != 0) - { - _AllocData(nLen); - _copy(m_str, str, nLen); - CRY_STRING_DEBUG(m_str) - } -} - -template -inline CryStringT::CryStringT(const CConstCharWrapper& str) -{ - _Initialize(); - m_str = const_cast(str.GetCharPointer()); -} - -template -template -inline CryStringT::CryStringT(const CryStackStringT& str) -{ - _Initialize(); - const size_type nLength = str.length(); - if (nLength > 0) - { - _AllocData(nLength); - _copy(m_str, str, nLength); - CRY_STRING_DEBUG(m_str) - } -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStringT::CryStringT(const_str str, size_type nLength) -{ - _Initialize(); - if (nLength > 0) - { - _AllocData(nLength); - _copy(m_str, str, nLength); - CRY_STRING_DEBUG(m_str) - } -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStringT::CryStringT(size_type nRepeat, value_type ch) -{ - _Initialize(); - if (nRepeat > 0) - { - _AllocData(nRepeat); - _set(m_str, ch, nRepeat); - CRY_STRING_DEBUG(m_str) - } -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStringT::CryStringT(const_iterator _First, const_iterator _Last) -{ - _Initialize(); - size_type nLength = (size_type)(_Last - _First); - if (nLength > 0) - { - _AllocData(nLength); - _copy(m_str, _First, nLength); - CRY_STRING_DEBUG(m_str) - } -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStringT::~CryStringT() -{ - _FreeData(_header()); -} - -////////////////////////////////////////////////////////////////////////// -template -inline typename CryStringT::size_type CryStringT::length() const -{ - return _header()->nLength; -} -template -inline typename CryStringT::size_type CryStringT::size() const -{ - return _header()->nLength; -} -template -inline typename CryStringT::size_type CryStringT::capacity() const -{ - return _header()->nAllocSize; -} - -template -inline bool CryStringT::empty() const -{ - return length() == 0; -} - -////////////////////////////////////////////////////////////////////////// -template -inline void CryStringT::clear() -{ - if (length() == 0) - { - return; - } - if (_header()->nRefCount >= 0) - { - _Free(); - } - else - { - resize(0); - } - AZ_Assert(length() == 0, "Cleared string should have a length of 0"); - AZ_Assert(_header()->nRefCount < 0 || capacity() == 0, - "Cleared string should have a reference count or capacity of 0"); -} - -////////////////////////////////////////////////////////////////////////// -template -inline void CryStringT::reserve(size_type nCount) -{ - // Reserve of 0 is shrinking container to fit number of characters in it.. - if (nCount > capacity()) - { - StrHeader* pOldData = _header(); - _AllocData(nCount); - _copy(m_str, pOldData->GetChars(), pOldData->nLength); - _header()->nLength = pOldData->nLength; - m_str[pOldData->nLength] = 0; - _FreeData(pOldData); - } - else if (nCount == 0) - { - if (length() != capacity()) - { - StrHeader* pOldData = _header(); - _AllocData(length()); - _copy(m_str, pOldData->GetChars(), pOldData->nLength); - _FreeData(pOldData); - } - } - CRY_STRING_DEBUG(m_str) -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStringT& CryStringT::append(const_str _Ptr) -{ - *this += _Ptr; - return *this; -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStringT& CryStringT::append(const_str _Ptr, size_type nCount) -{ - _ConcatenateInPlace(_Ptr, nCount); - return *this; -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStringT& CryStringT::append(const CryStringT& _Str, size_type off, size_type nCount) -{ - size_type len = _Str.length(); - if (off > len) - { - return *this; - } - if (off + nCount > len) - { - nCount = len - off; - } - _ConcatenateInPlace(_Str.m_str + off, nCount); - return *this; -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStringT& CryStringT::append(const CryStringT& _Str) -{ - *this += _Str; - return *this; -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStringT& CryStringT::append(size_type nCount, value_type _Ch) -{ - if (nCount > 0) - { - if (_header()->nRefCount > 1 || length() + nCount > capacity()) - { - StrHeader* pOldData = _header(); - _AllocData(length() + nCount); - _copy(m_str, pOldData->GetChars(), pOldData->nLength); - _set(m_str + pOldData->nLength, _Ch, nCount); - _FreeData(pOldData); - } - else - { - size_type nOldLength = length(); - _set(m_str + nOldLength, _Ch, nCount); - _header()->nLength = aznumeric_cast(nOldLength + nCount); - m_str[length()] = 0; // Make null terminated string. - } - } - CRY_STRING_DEBUG(m_str) - return *this; -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStringT& CryStringT::append(const_iterator _First, const_iterator _Last) -{ - append(_First, (size_type)(_Last - _First)); - return *this; -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStringT& CryStringT::assign(const_str _Ptr) -{ - *this = _Ptr; - return *this; -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStringT& CryStringT::assign(const_str _Ptr, size_type nCount) -{ - size_type len = _strnlen(_Ptr, nCount); - _Assign(_Ptr, len); - return *this; -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStringT& CryStringT::assign(const CryStringT& _Str, size_type off, size_type nCount) -{ - size_type len = _Str.length(); - if (off > len) - { - return *this; - } - if (off + nCount > len) - { - nCount = len - off; - } - _Assign(_Str.m_str + off, nCount); - return *this; -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStringT& CryStringT::assign(const CryStringT& _Str) -{ - *this = _Str; - return *this; -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStringT& CryStringT::assign(size_type nCount, value_type _Ch) -{ - if (nCount >= 1) - { - _AllocData(nCount); - _set(m_str, _Ch, nCount); - CRY_STRING_DEBUG(m_str) - } - return *this; -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStringT& CryStringT::assign(const_iterator _First, const_iterator _Last) -{ - assign(_First, (size_type)(_Last - _First)); - return *this; -} - -////////////////////////////////////////////////////////////////////////// -template -inline typename CryStringT::value_type CryStringT::at(size_type index) const -{ - AZ_Assert(index >= 0 && index < length(), "index into CryString is out of range"); - return m_str[index]; -} - -////////////////////////////////////////////////////////////////////////// -template -inline int CryStringT::compare(const CryStringT& _Str) const -{ - return compare(_Str.m_str); -} - -template -inline int CryStringT::compare(size_type _Pos1, size_type _Num1, const CryStringT& _Str) const -{ - return compare(_Pos1, _Num1, _Str.m_str, npos); -} - -template -inline int CryStringT::compare(size_type _Pos1, size_type _Num1, const CryStringT& _Str, size_type nOff, size_type nCount) const -{ - AZ_Assert(nOff < _Str.length(), "Offset into input string is larger than the index range"); - return compare(_Pos1, _Num1, _Str.m_str + nOff, nCount); -} - -template -inline int CryStringT::compare(const char* _Ptr) const -{ - return strcmp(m_str, _Ptr); -} - -template -inline int CryStringT::compare(const wchar_t* _Ptr) const -{ - return wcscmp(m_str, _Ptr); -} - -template -inline int CryStringT::compare(size_type _Pos1, size_type _Num1, const value_type* _Ptr, size_type _Num2) const -{ - AZ_Assert(_Pos1 < length(), "position index to compare is larger than the length of this string"); - if (length() - _Pos1 < _Num1) - { - _Num1 = length() - _Pos1; // trim to size - } - int res = _Num1 == 0 ? 0 : strncmp(m_str + _Pos1, _Ptr, (_Num1 < _Num2) ? _Num1 : _Num2); - return (res != 0 ? res : _Num2 == npos && _Ptr[_Num1] == 0 ? 0 : _Num1 < _Num2 ? -1 : _Num1 == _Num2 ? 0 : +1); -} - -////////////////////////////////////////////////////////////////////////// -template -inline int CryStringT::compareNoCase(const CryStringT& _Str) const -{ - return _stricmp(m_str, _Str.m_str); -} - -template -inline int CryStringT::compareNoCase(size_type _Pos1, size_type _Num1, const CryStringT& _Str) const -{ - return compareNoCase(_Pos1, _Num1, _Str.m_str, npos); -} - -template -inline int CryStringT::compareNoCase(size_type _Pos1, size_type _Num1, const CryStringT& _Str, size_type nOff, size_type nCount) const -{ - AZ_Assert(nOff < _Str.length(), "offset to start comparison within input string is larger than the string index range"); - return compareNoCase(_Pos1, _Num1, _Str.m_str + nOff, nCount); -} - -template -inline int CryStringT::compareNoCase(const value_type* _Ptr) const -{ - return _stricmp(m_str, _Ptr); -} - -template -inline int CryStringT::compareNoCase(size_type _Pos1, size_type _Num1, const value_type* _Ptr, size_type _Num2) const -{ - AZ_Assert(_Pos1 < length(), "Position to start case-insensitive search is larger the indexable range"); - if (length() - _Pos1 < _Num1) - { - _Num1 = length() - _Pos1; // trim to size - } - int res = _Num1 == 0 ? 0 : _strnicmp(m_str + _Pos1, _Ptr, (_Num1 < _Num2) ? _Num1 : _Num2); - return (res != 0 ? res : _Num2 == npos && _Ptr[_Num1] == 0 ? 0 : _Num1 < _Num2 ? -1 : _Num1 == _Num2 ? 0 : +1); -} - -////////////////////////////////////////////////////////////////////////// -template -inline typename CryStringT::size_type CryStringT::copy(value_type* _Ptr, size_type nCount, size_type nOff) const -{ - AZ_Assert(nOff < length(), "Offset to copy from string to output address is outside the indexable range"); - if (nCount < 0) - { - nCount = 0; - } - if (nOff + nCount > length()) // trim to offset. - { - nCount = length() - nOff; - } - - _copy(_Ptr, m_str + nOff, nCount); - return nCount; -} - -////////////////////////////////////////////////////////////////////////// -template -inline void CryStringT::resize(size_type nCount, value_type _Ch) -{ - _MakeUnique(); - if (nCount > length()) - { - size_type numToAdd = nCount - length(); - append(numToAdd, _Ch); - } - else if (nCount < length()) - { - _header()->nLength = nCount; - m_str[length()] = 0; // Make null terminated string. - } -} - -////////////////////////////////////////////////////////////////////////// -//! compare helpers -template -inline bool operator==(const CryStringT& s1, const CryStringT& s2) -{ return s1.compare(s2) == 0; } -template -inline bool operator==(const CryStringT& s1, const typename CryStringT::value_type* s2) -{ return s1.compare(s2) == 0; } -template -inline bool operator==(const typename CryStringT::value_type* s1, const CryStringT& s2) -{ return s2.compare(s1) == 0; } -template -inline bool operator!=(const CryStringT& s1, const CryStringT& s2) -{ return s1.compare(s2) != 0; } -template -inline bool operator!=(const CryStringT& s1, const typename CryStringT::value_type* s2) -{ return s1.compare(s2) != 0; } -template -inline bool operator!=(const typename CryStringT::value_type* s1, const CryStringT& s2) -{ return s2.compare(s1) != 0; } -template -inline bool operator<(const CryStringT& s1, const CryStringT& s2) -{ return s1.compare(s2) < 0; } -template -inline bool operator<(const CryStringT& s1, const typename CryStringT::value_type* s2) -{ return s1.compare(s2) < 0; } -template -inline bool operator<(const typename CryStringT::value_type* s1, const CryStringT& s2) -{ return s2.compare(s1) > 0; } -template -inline bool operator>(const CryStringT& s1, const CryStringT& s2) -{ return s1.compare(s2) > 0; } -template -inline bool operator>(const CryStringT& s1, const typename CryStringT::value_type* s2) -{ return s1.compare(s2) > 0; } -template -inline bool operator>(const typename CryStringT::value_type* s1, const CryStringT& s2) -{ return s2.compare(s1) < 0; } -template -inline bool operator<=(const CryStringT& s1, const CryStringT& s2) -{ return s1.compare(s2) <= 0; } -template -inline bool operator<=(const CryStringT& s1, const typename CryStringT::value_type* s2) -{ return s1.compare(s2) <= 0; } -template -inline bool operator<=(const typename CryStringT::value_type* s1, const CryStringT& s2) -{ return s2.compare(s1) >= 0; } -template -inline bool operator>=(const CryStringT& s1, const CryStringT& s2) -{ return s1.compare(s2) >= 0; } -template -inline bool operator>=(const CryStringT& s1, const typename CryStringT::value_type* s2) -{ return s1.compare(s2) >= 0; } -template -inline bool operator>=(const typename CryStringT::value_type* s1, const CryStringT& s2) -{ return s2.compare(s1) <= 0; } - -////////////////////////////////////////////////////////////////////////// -template -inline CryStringT& CryStringT::operator=(value_type ch) -{ - _Assign(&ch, 1); - return *this; -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStringT operator+(const CryStringT& string1, typename CryStringT::value_type ch) -{ - CryStringT s(string1); - s.append(1, ch); - return s; -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStringT operator+(typename CryStringT::value_type ch, const CryStringT& str) -{ - CryStringT s; - s.reserve(str.size() + 1); - s.append(1, ch); - s.append(str); - return s; -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStringT operator+(const CryStringT& string1, const CryStringT& string2) -{ - CryStringT s(string1); - s.append(string2); - return s; -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStringT operator+(const CryStringT& str1, const typename CryStringT::value_type* str2) -{ - CryStringT s(str1); - s.append(str2); - return s; -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStringT operator+(const typename CryStringT::value_type* str1, const CryStringT& str2) -{ - AZ_Assert(str1 == nullptr || CryStringT::_IsValidString(str1), "Input string is not valid"); - CryStringT s; - s.reserve(CryStringT::_strlen(str1) + str2.size()); - s.append(str1); - s.append(str2); - return s; -} - -template -inline CryStringT& CryStringT::operator=(const CryStringT& str) -{ - if (m_str != str.m_str) - { - if (_header()->nRefCount < 0) - { - // Empty string. - // _Assign( str.m_str,str.length() ); - if (str._header()->nRefCount < 0) - { - ; // two empty strings... - } - else - { - m_str = str.m_str; - _header()->AddRef(); - } - } - else if (str._header()->nRefCount < 0) - { - // If source string is empty. - _Free(); - m_str = str.m_str; - } - else - { - // Copy string reference. - _Free(); - m_str = str.m_str; - _header()->AddRef(); - } - } - return *this; -} - -template -inline CryStringT& CryStringT::operator=(const_str str) -{ - AZ_Assert(str == nullptr || _IsValidString(str), "Input string is not valid"); - _Assign(str, _strlen(str)); - return *this; -} - -template -inline CryStringT& CryStringT::operator+=(const_str str) -{ - AZ_Assert(str == nullptr || _IsValidString(str), "Input string is not valid"); - _ConcatenateInPlace(str, _strlen(str)); - return *this; -} - -template -inline CryStringT& CryStringT::operator+=(value_type ch) -{ - _ConcatenateInPlace(&ch, 1); - return *this; -} - -template -inline CryStringT& CryStringT::operator+=(const CryStringT& str) -{ - _ConcatenateInPlace(str.m_str, str.length()); - return *this; -} - -//! find first single character -template -inline typename CryStringT::size_type CryStringT::find(value_type ch, size_type pos) const -{ - if (!(pos >= 0 && pos <= length())) - { - return (typename CryStringT::size_type)npos; - } - const_str str = _strchr(m_str + pos, ch); - // return npos if not found and index otherwise - return (str == NULL) ? npos : (size_type)(str - m_str); -} - -//! find a sub-string (like strstr) -template -inline typename CryStringT::size_type CryStringT::find(const_str subs, size_type pos) const -{ - AZ_Assert(_IsValidString(subs), "Input string is not valid"); - if (!(pos >= 0 && pos <= length())) - { - return npos; - } - - // find first matching substring - const_str str = _strstr(m_str + pos, subs); - - // return npos for not found, distance from beginning otherwise - return (str == NULL) ? npos : (size_type)(str - m_str); -} - -//! find last single character -template -inline typename CryStringT::size_type CryStringT::rfind(value_type ch, size_type pos) const -{ - const_str str; - if (pos == npos) - { - // find last single character - str = _strrchr(m_str, ch); - // return -1 if not found, distance from beginning otherwise - return (str == NULL) ? (size_type) - 1 : (size_type)(str - m_str); - } - else - { - if (pos == npos) - { - pos = length(); - } - if (!(pos >= 0 && pos <= length())) - { - return npos; - } - - value_type tmp = m_str[pos + 1]; - m_str[pos + 1] = 0; - str = _strrchr(m_str, ch); - m_str[pos + 1] = tmp; - } - // return -1 if not found, distance from beginning otherwise - return (str == NULL) ? (size_type) - 1 : (size_type)(str - m_str); -} - -template -inline typename CryStringT::size_type CryStringT::rfind(const CryStringT& subs, size_type pos) const -{ - size_type res = npos; - for (int i = (int)size(); i >= (int)pos; --i) - { - size_type findRes = find(subs, i); - if (findRes != npos) - { - res = findRes; - break; - } - } - return res; -} - -////////////////////////////////////////////////////////////////////////// -template -inline typename CryStringT::size_type CryStringT::find_first_of(const CryStringT& _Str, size_type _Off) const -{ - return find_first_of(_Str.m_str, _Off); -} - -////////////////////////////////////////////////////////////////////////// -template -inline typename CryStringT::size_type CryStringT::find_first_of(value_type _Ch, size_type nOff) const -{ - if (!(nOff >= 0 && nOff <= length())) - { - return npos; - } - value_type charSet[2] = { _Ch, 0 }; - const_str str = strpbrk(m_str + nOff, charSet); - return (str == NULL) ? (size_type) - 1 : (size_type)(str - m_str); -} - -////////////////////////////////////////////////////////////////////////// -template -inline typename CryStringT::size_type CryStringT::find_first_of(const_str charSet, size_type nOff) const -{ - AZ_Assert(_IsValidString(charSet), "input c-string must not be nullptr"); - if (!(nOff >= 0 && nOff <= length())) - { - return npos; - } - const_str str = strpbrk(m_str + nOff, charSet); - return (str == NULL) ? (size_type) - 1 : (size_type)(str - m_str); -} - -template <> -inline CryStringT::size_type CryStringT::find_first_of(const_str charSet, size_type nOff) const -{ - AZ_Assert(_IsValidString(charSet), "input c-string must not be nullptr"); - if (!(nOff >= 0 && nOff <= length())) - { - return npos; - } - const_str str = wcspbrk(m_str + nOff, charSet); - return (str == NULL) ? (size_type) - 1 : (size_type)(str - m_str); -} - -//size_type find_first_not_of(const _Self& __s, size_type __pos = 0) const -//{ return find_first_not_of(__s._M_start, __pos, __s.size()); } - -//size_type find_first_not_of(const _CharT* __s, size_type __pos = 0) const -//{ _STLP_FIX_LITERAL_BUG(__s) return find_first_not_of(__s, __pos, _Traits::length(__s)); } - -//size_type find_first_not_of(const _CharT* __s, size_type __pos, size_type __n) const; - -//size_type find_first_not_of(_CharT __c, size_type __pos = 0) const; - - -////////////////////////////////////////////////////////////////////////// -template -inline typename CryStringT::size_type CryStringT::find_first_not_of(const value_type* _Ptr, size_type _Off) const -{ return find_first_not_of(_Ptr, _Off, _strlen(_Ptr)); } - -////////////////////////////////////////////////////////////////////////// -template -inline typename CryStringT::size_type CryStringT::find_first_not_of(const CryStringT& _Str, size_type _Off) const -{ return find_first_not_of(_Str.m_str, _Off); } - -////////////////////////////////////////////////////////////////////////// -template -inline typename CryStringT::size_type CryStringT::find_first_not_of(value_type _Ch, size_type _Off) const -{ - if (_Off > length()) - { - return npos; - } - else - { - for (const value_type* str = begin() + _Off; str != end(); ++str) - { - if (*str != _Ch) - { - return size_type(str - begin()); // Character found! - } - } - return npos; - } -} - -////////////////////////////////////////////////////////////////////////// -template -inline typename CryStringT::size_type CryStringT::find_first_not_of(const value_type* _Ptr, size_type _Off, size_type _Count) const -{ - if (_Off > length()) - { - return npos; - } - else - { - const value_type* charsFirst = _Ptr, * charsLast = _Ptr + _Count; - for (const value_type* str = begin() + _Off; str != end(); ++str) - { - const value_type* c; - for (c = charsFirst; c != charsLast; ++c) - { - if (*c == *str) - { - break; - } - } - if (c == charsLast) - { - return size_type(str - begin());// Current character not in char set. - } - } - return npos; - } -} -////////////////////////////////////////////////////////////////////////// -template -inline typename CryStringT::size_type CryStringT::find_last_of(value_type _Ch, size_type _Off) const -{ - size_type nLenght(length()); - // Empty strings, always return npos (same semantic as std::string). - if (nLenght == 0) - { - return npos; - } - - // If the offset is is bigger than the size of the string - if (_Off >= nLenght) - { - // We set it to the size of the string -1, so we will not do bad pointer operations nor we will - // test the null terminating character. - _Off = nLenght - 1; - } - - // From the character at the offset position, going to to the direction of the first character. - for (const value_type* str = begin() + _Off; true; --str) - { - // We found a character in the string which matches the input character. - if (*str == _Ch) - { - return size_type(str - begin()); // Character found! - } - // If the next element will be begin()-1, then we should stop. - if (str == begin()) - { - break; - } - } - - // We found nothing. - return npos; -} -////////////////////////////////////////////////////////////////////////// -template -inline typename CryStringT::size_type CryStringT::find_last_of(const value_type* _Ptr, size_type _Off) const -{ - // This function is actually a convenience alias... - // BTW: what will happeb if wchar_t is used here? - return find_last_of(_Ptr, _Off, _strlen(_Ptr)); -} -////////////////////////////////////////////////////////////////////////// -template -inline typename CryStringT::size_type CryStringT::find_last_of(const value_type* _Ptr, size_type _Off, size_type _Count) const -{ - size_type nLenght(length()); - // Empty strings, always return npos (same semantic as std::string). - if (nLenght == 0) - { - return npos; - } - - // If the offset is is bigger than the size of the string - if (_Off >= nLenght) - { - // We set it to the size of the string -1, so we will not do bad pointer operations nor we will - // test the null terminating character. - _Off = nLenght - 1; - } - - // From the character at the offset position, going to to the direction of the first character. - const value_type* charsFirst = _Ptr, * charsLast = _Ptr + _Count; - for (const value_type* str = begin() + _Off; true; --str) - { - const value_type* c; - // For every character in the character set. - for (c = charsFirst; c != charsLast; ++c) - { - // If the current character matches any of the charcaters in the input string... - if (*c == *str) - { - // This is the value we must return. - return size_type(str - begin()); - } - } - - // If the next element will be begin()-1, then we should stop. - if (str == begin()) - { - break; - } - } - // We couldn't find any character of the input string in the current string. - return npos; -} -///////////////////////////////////////////////////////////////////////////// -template -inline typename CryStringT::size_type CryStringT::find_last_of(const _Self& strCharSet, size_type _Off) const -{ - size_type nLenght(length()); - // Empty strings, always return npos (same semantic as std::string). - if (nLenght == 0) - { - return npos; - } - - // If the offset is is bigger than the size of the string - if (_Off >= nLenght) - { - // We set it to the size of the string -1, so we will not do bad pointer operations nor we will - // test the null terminating character. - _Off = nLenght - 1; - } - - - // From the character at the offset position, going to to the direction of the first character. - for (const value_type* str = begin() + _Off; true; --str) - { - // We check every character of the input string. - for (const value_type* strInputCharacter = strCharSet.begin(); strInputCharacter != strCharSet.end(); ++strInputCharacter) - { - // If any character matches. - if (*str == *strInputCharacter) - { - // We return the position where we found it. - return size_type(str - begin()); // Character found! - } - } - // If the next element will be begin()-1, then we should stop. - if (str == begin()) - { - break; - } - } - - // As we couldn't find any matching character...we return the appropriate value. - return npos; -} -////////////////////////////////////////////////////////////////////////// -template -inline typename CryStringT::size_type CryStringT::find_last_not_of(value_type _Ch, size_type _Off) const -{ - size_type nLenght(length()); - // Empty strings, always return npos (same semantic as std::string). - if (nLenght == 0) - { - return npos; - } - - // If the offset is is bigger than the size of the string - if (_Off >= nLenght) - { - // We set it to the size of the string -1, so we will not do bad pointer operations nor we will - // test the null terminating character. - _Off = nLenght - 1; - } - - - // From the character at the offset position, going to to the direction of the first character. - for (const value_type* str = begin() + _Off; true; --str) - { - // If the current character being analyzed is different of the input character. - if (*str != _Ch) - { - // We found the last item which is not the input character before the given offset. - return size_type(str - begin()); // Character found! - } - // If the next element will be begin()-1, then we should stop. - if (str == begin()) - { - break; - } - } - - // As we couldn't find any matching character...we return the appropriate value. - return npos; -} -////////////////////////////////////////////////////////////////////////// -template -inline typename CryStringT::size_type CryStringT::find_last_not_of(const value_type* _Ptr, size_type _Off) const -{ - // This function is actually a convenience alias... - // BTW: what will happeb if wchar_t is used here? - return find_last_not_of(_Ptr, _Off, _strlen(_Ptr)); -} -////////////////////////////////////////////////////////////////////////// -template -inline typename CryStringT::size_type CryStringT::find_last_not_of(const value_type* _Ptr, size_type _Off, size_type _Count) const -{ - size_type nLenght(length()); - // Empty strings, always return npos (same semantic as std::string). - if (nLenght == 0) - { - return npos; - } - - // If the offset is is bigger than the size of the string - if (_Off >= nLenght) - { - // We set it to the size of the string -1, so we will not do bad pointer operations nor we will - // test the null terminating character. - _Off = nLenght - 1; - } - - - // From the character at the offset position, going to to the direction of the first character. - const value_type* charsFirst = _Ptr, * charsLast = _Ptr + _Count; - for (const value_type* str = begin() + _Off; true; --str) - { - bool boFoundAny(false); - const value_type* c; - // For every character in the character set. - for (c = charsFirst; c != charsLast; ++c) - { - // If the current character matches any of the charcaters in the input string... - if (*c == *str) - { - // So we signal it was found and stop this search. - boFoundAny = true; - break; - } - } - - // Using a different solution of the other similar methods - // to make it easier to read. - // If the character being analyzed is not in the set... - if (!boFoundAny) - { - //.. we return the position where we found it. - return size_type(str - begin()); - } - - // If the next element will be begin()-1, then we should stop. - if (str == begin()) - { - break; - } - } - // We couldn't find any character of the input string not in the character set. - return npos; -} -////////////////////////////////////////////////////////////////////////// -template -inline typename CryStringT::size_type CryStringT::find_last_not_of(const _Self& _Str, size_type _Off) const -{ - size_type nLenght(length()); - // Empty strings, always return npos (same semantic as std::string). - if (nLenght == 0) - { - return npos; - } - - // If the offset is is bigger than the size of the string - if (_Off >= nLenght) - { - // We set it to the size of the string -1, so we will not do bad pointer operations nor we will - // test the null terminating character. - _Off = nLenght - 1; - } - - - // From the character at the offset position, going to to the direction of the first character. - for (const value_type* str = begin() + _Off; true; --str) - { - bool boFoundAny(false); - for (const value_type* strInputCharacter = _Str.begin(); strInputCharacter != _Str.end(); ++strInputCharacter) - { - // The character matched one of the character set... - if (*strInputCharacter == *str) - { - // So we signal it was found and stop this search. - boFoundAny = true; - break; - } - } - - // Using a different solution of the other similar methods - // to make it easier to read. - // If the character being analyzed is not in the set... - if (!boFoundAny) - { - //.. we return the position where we found it. - return size_type(str - begin()); - } - - // If the next element will be begin()-1, then we should stop. - if (str == begin()) - { - break; - } - } - - // As we couldn't find any matching character...we return the appropriate value. - return npos; -} -////////////////////////////////////////////////////////////////////////// -template -inline CryStringT CryStringT::substr(size_type pos, size_type count) const -{ - if (pos >= length()) - { - return CryStringT(); - } - if (count == npos) - { - count = length() - pos; - } - if (pos + count > length()) - { - count = length() - pos; - } - return CryStringT(m_str + pos, count); -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStringT& CryStringT::erase(size_type nIndex, size_type nCount) -{ - if (nIndex < 0) - { - nIndex = 0; - } - if (nCount < 0 || nCount > length() - nIndex) - { - nCount = length() - nIndex; - } - if (nCount > 0 && nIndex < length()) - { - _MakeUnique(); - size_type nNumToCopy = length() - (nIndex + nCount) + 1; - _move(m_str + nIndex, m_str + nIndex + nCount, nNumToCopy); - _header()->nLength = length() - nCount; - } - - return *this; -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStringT& CryStringT::insert(size_type nIndex, value_type ch) -{ - return insert(nIndex, 1, ch); -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStringT& CryStringT::insert(size_type nIndex, size_type nCount, value_type ch) -{ - _MakeUnique(); - - if (nIndex < 0) - { - nIndex = 0; - } - - size_type nNewLength = length(); - if (nIndex > nNewLength) - { - nIndex = nNewLength; - } - nNewLength += nCount; - - if (capacity() < nNewLength) - { - StrHeader* pOldData = _header(); - const_str pstr = m_str; - _AllocData(nNewLength); - _copy(m_str, pstr, pOldData->nLength + 1); - _FreeData(pOldData); - } - - _move(m_str + nIndex + nCount, m_str + nIndex, (nNewLength - nIndex - nCount) + 1); - _set(m_str + nIndex, ch, nCount); - _header()->nLength = nNewLength; - CRY_STRING_DEBUG(m_str) - - return *this; -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStringT& CryStringT::insert(size_type nIndex, const_str pstr, size_type nCount) -{ - if (nIndex < 0) - { - nIndex = 0; - } - - size_type nInsertLength = nCount; - size_type nNewLength = length(); - if (nInsertLength > 0) - { - _MakeUnique(); - if (nIndex > nNewLength) - { - nIndex = nNewLength; - } - nNewLength += nInsertLength; - - if (capacity() < nNewLength) - { - StrHeader* pOldData = _header(); - const_str pOldStr = m_str; - _AllocData(nNewLength); - _copy(m_str, pOldStr, (pOldData->nLength + 1)); - _FreeData(pOldData); - } - - _move(m_str + nIndex + nInsertLength, m_str + nIndex, (nNewLength - nIndex - nInsertLength + 1)); - _copy(m_str + nIndex, pstr, nInsertLength); - _header()->nLength = nNewLength; - m_str[length()] = 0; - } - CRY_STRING_DEBUG(m_str) - - return *this; -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStringT& CryStringT::insert(size_type nIndex, const_str pstr) -{ - return insert(nIndex, pstr, _strlen(pstr)); -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStringT& CryStringT::replace(size_type pos, size_type count, const_str strNew) -{ - return replace(pos, count, strNew, _strlen(strNew)); -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStringT& CryStringT::replace(size_type pos, size_type count, const_str strNew, size_type count2) -{ - erase(pos, count); - insert(pos, strNew, count2); - return *this; -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStringT& CryStringT::replace(size_type pos, size_type count, size_type nNumChars, value_type chNew) -{ - erase(pos, count); - insert(pos, nNumChars, chNew); - return *this; -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStringT& CryStringT::replace(value_type chOld, value_type chNew) -{ - if (chOld != chNew) - { - _MakeUnique(); - value_type* strend = m_str + length(); - for (value_type* str = m_str; str != strend; ++str) - { - if (*str == chOld) - { - *str = chNew; - } - } - } - return *this; -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStringT& CryStringT::replace(const_str strOld, const_str strNew) -{ - size_type nSourceLen = _strlen(strOld); - if (nSourceLen == 0) - { - return *this; - } - size_type nReplacementLen = _strlen(strNew); - - size_type nCount = 0; - value_type* strStart = m_str; - value_type* strEnd = m_str + length(); - value_type* strTarget; - while (strStart < strEnd) - { - while ((strTarget = _strstr(strStart, strOld)) != NULL) - { - nCount++; - strStart = strTarget + nSourceLen; - } - strStart += _strlen(strStart) + 1; - } - - if (nCount > 0) - { - _MakeUnique(); - - size_type nOldLength = length(); - size_type nNewLength = nOldLength + (nReplacementLen - nSourceLen) * nCount; - if (capacity() < nNewLength || _header()->nRefCount > 1) - { - StrHeader* pOldData = _header(); - const_str pstr = m_str; - _AllocData(nNewLength); - _copy(m_str, pstr, pOldData->nLength); - _FreeData(pOldData); - } - strStart = m_str; - strEnd = m_str + length(); - - while (strStart < strEnd) - { - while ((strTarget = _strstr(strStart, strOld)) != NULL) - { - size_type nBalance = nOldLength - ((size_type)(strTarget - m_str) + nSourceLen); - _move(strTarget + nReplacementLen, strTarget + nSourceLen, nBalance); - _copy(strTarget, strNew, nReplacementLen); - strStart = strTarget + nReplacementLen; - strStart[nBalance] = 0; - nOldLength += (nReplacementLen - nSourceLen); - } - strStart += _strlen(strStart) + 1; - } - _header()->nLength = nNewLength; - } - CRY_STRING_DEBUG(m_str) - - return *this; -} - -////////////////////////////////////////////////////////////////////////// -template -inline void CryStringT::swap(CryStringT& _Str) -{ - value_type* temp = _Str.m_str; - _Str.m_str = m_str; - m_str = temp; -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStringT& CryStringT::Format(const_str format, ...) -{ - AZ_Assert(_IsValidString(format), "format c-string must not be nullptr"); - -#if defined(WIN32) || defined(WIN64) - va_list argList; - va_start(argList, format); - int n = _vscpf(format, argList); - if (n < 0) - { - n = 0; - } - resize(n); //this will actually allocate n+1 elements to accommodate the null terminator - _vsnpf(m_str, n, format, argList); - va_end(argList); - return *this; -#else - value_type temp[4096]; // Limited to 4096 characters! - va_list argList; - va_start(argList, format); - _vsnpf(temp, 4096, format, argList); - temp[4095] = '\0'; - va_end(argList); - *this = temp; - return *this; -#endif -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStringT& CryStringT::MakeLower() -{ - _MakeUnique(); - for (value_type* s = m_str; *s != 0; s++) - { - const value_type c = *s; - *s = (c >= 'A' && c <= 'Z') ? c - 'A' + 'a' : c; // ASCII only, standard "C" locale - } - return *this; -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStringT& CryStringT::MakeUpper() -{ - _MakeUnique(); - for (value_type* s = m_str; *s != 0; s++) - { - const value_type c = *s; - *s = (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c; // ASCII only, standard "C" locale - } - return *this; -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStringT& CryStringT::Trim() -{ - return TrimRight().TrimLeft(); -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStringT& CryStringT::Trim(value_type ch) -{ - _MakeUnique(); - const value_type chset[2] = { ch, 0 }; - return TrimRight(chset).TrimLeft(chset); -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStringT& CryStringT::Trim(const value_type* sCharSet) -{ - _MakeUnique(); - return TrimRight(sCharSet).TrimLeft(sCharSet); -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStringT& CryStringT::TrimRight(value_type ch) -{ - const value_type chset[2] = { ch, 0 }; - return TrimRight(chset); -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStringT& CryStringT::TrimRight(const value_type* sCharSet) -{ - if (!sCharSet || !(*sCharSet) || length() < 1) - { - return *this; - } - - const value_type* last = m_str + length() - 1; - const value_type* str = last; - while ((str != m_str) && (_strchr(sCharSet, *str) != 0)) - { - str--; - } - - if (str != last) - { - // Just shrink length of the string. - size_type nNewLength = (size_type)(str - m_str) + 1; // m_str can change in _MakeUnique - _MakeUnique(); - _header()->nLength = nNewLength; - m_str[nNewLength] = 0; - } - - return *this; -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStringT& CryStringT::TrimRight() -{ - if (length() < 1) - { - return *this; - } - - const value_type* last = m_str + length() - 1; - const value_type* str = last; - while ((str != m_str) && (isspace((unsigned char)*str) != 0)) - { - str--; - } - - if (str != last) // something changed? - { - // Just shrink length of the string. - size_type nNewLength = (size_type)(str - m_str) + 1; // m_str can change in _MakeUnique - _MakeUnique(); - _header()->nLength = nNewLength; - m_str[nNewLength] = 0; - } - - return *this; -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStringT& CryStringT::TrimLeft(value_type ch) -{ - const value_type chset[2] = { ch, 0 }; - return TrimLeft(chset); -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStringT& CryStringT::TrimLeft(const value_type* sCharSet) -{ - if (!sCharSet || !(*sCharSet)) - { - return *this; - } - - const value_type* str = m_str; - while ((*str != 0) && (_strchr(sCharSet, *str) != 0)) - { - str++; - } - - if (str != m_str) - { - size_type nOff = (size_type)(str - m_str); // m_str can change in _MakeUnique - _MakeUnique(); - size_type nNewLength = length() - nOff; - _move(m_str, m_str + nOff, nNewLength + 1); - _header()->nLength = nNewLength; - m_str[nNewLength] = 0; - } - - return *this; -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStringT& CryStringT::TrimLeft() -{ - const value_type* str = m_str; - while ((*str != 0) && (isspace((unsigned char)*str) != 0)) - { - str++; - } - - if (str != m_str) - { - size_type nOff = (size_type)(str - m_str); // m_str can change in _MakeUnique - _MakeUnique(); - size_type nNewLength = length() - nOff; - _move(m_str, m_str + nOff, nNewLength + 1); - _header()->nLength = nNewLength; - m_str[nNewLength] = 0; - } - - return *this; -} - -template -inline CryStringT CryStringT::Right(size_type count) const -{ - if (count == npos) - { - return CryStringT(); - } - else if (count > length()) - { - return *this; - } - - return CryStringT(m_str + length() - count, count); -} - -template -inline CryStringT CryStringT::Left(size_type count) const -{ - if (count == npos) - { - return CryStringT(); - } - else if (count > length()) - { - count = length(); - } - - return CryStringT(m_str, count); -} - -// strspn equivalent -template -inline CryStringT CryStringT::SpanIncluding(const_str charSet) const -{ - AZ_Assert(_IsValidString(charSet), "input c-string must not be nullptr"); - return Left((size_type)strspn(m_str, charSet)); -} - -// strcspn equivalent -template -inline CryStringT CryStringT::SpanExcluding(const_str charSet) const -{ - AZ_Assert(_IsValidString(charSet), "input c-string must not be nullptr"); - return Left((size_type)strcspn(m_str, charSet)); -} - -////////////////////////////////////////////////////////////////////////// -template -inline CryStringT CryStringT::Tokenize(const_str charSet, int& nStart) const -{ - if (nStart < 0) - { - return CryStringT(); - } - - if (!charSet) - { - return *this; - } - - const_str sPlace = m_str + nStart; - const_str sEnd = m_str + length(); - if (sPlace < sEnd) - { - int nIncluding = (int)strspn(sPlace, charSet); - - if ((sPlace + nIncluding) < sEnd) - { - sPlace += nIncluding; - int nExcluding = (int)strcspn(sPlace, charSet); - int nFrom = nStart + nIncluding; - nStart = nFrom + nExcluding + 1; - - return substr(nFrom, nExcluding); - } - } - // Return empty string. - nStart = -1; - return CryStringT(); -} - -////////////////////////////////////////////////////////////////////////// -// This code prevents std::string compiling in Win32 with STLPort -////////////////////////////////////////////////////////////////////////// -#if defined(WIN32) && !defined(WIN64) && defined(_STLP_BEGIN_NAMESPACE) && !defined(DONT_BAN_STD_STRING) -#define CRYINCLUDE_STLP_STRING_FWD_H -#define CRYINCLUDE_STLP_INTERNAL_STRING_H -namespace std -{ - //const char* __get_c_string( const CryStringT &str ) { return str.c_str(); }; - class string - { - // std::string must not be used if CryString included. - // Use string instead. - }; -} -////////////////////////////////////////////////////////////////////////// -#endif // WIN64 - -typedef CryStringT string; -typedef CryStringT wstring; - -#else // !defined(NOT_USE_CRY_STRING) - -#include // STL string -typedef std::string string; -typedef std::wstring wstring; - -#endif // !defined(NOT_USE_CRY_STRING) - -namespace AZStd -{ - template <> - struct hash<::string> - { - typedef ::string argument_type; - typedef size_t result_type; - inline result_type operator()(const argument_type& value) const - { - return hash_string(value.c_str(), value.length()); - } - - static size_t hash_string(const char* str, size_t length) - { - size_t hash = 14695981039346656037ULL; - const size_t fnvPrime = 1099511628211ULL; - const char* cptr = str; - for (; length; --length) - { - hash ^= static_cast(*cptr++); - hash *= fnvPrime; - } - return hash; - } - }; -} - -#endif // CRYINCLUDE_CRYCOMMON_CRYSTRING_H diff --git a/Code/Legacy/CryCommon/CryThread_windows.h b/Code/Legacy/CryCommon/CryThread_windows.h index b80666ce73..f85ddf763c 100644 --- a/Code/Legacy/CryCommon/CryThread_windows.h +++ b/Code/Legacy/CryCommon/CryThread_windows.h @@ -260,7 +260,7 @@ private: volatile bool m_bIsStarted; volatile bool m_bIsRunning; volatile bool m_bCreatedThread; - string m_name; + AZStd::string m_name; protected: virtual void Terminate() diff --git a/Code/Legacy/CryCommon/CryTypeInfo.cpp b/Code/Legacy/CryCommon/CryTypeInfo.cpp index bd2bfb8bb2..ffadc732b0 100644 --- a/Code/Legacy/CryCommon/CryTypeInfo.cpp +++ b/Code/Legacy/CryCommon/CryTypeInfo.cpp @@ -114,7 +114,7 @@ TYPE_INFO_INT(uint64) TYPE_INFO_BASIC(float) TYPE_INFO_BASIC(double) -TYPE_INFO_BASIC(string) +TYPE_INFO_BASIC(AZStd::string) const CTypeInfo&PtrTypeInfo() @@ -129,9 +129,9 @@ const CTypeInfo&PtrTypeInfo() // String conversion functions needed by TypeInfo. // bool -string ToString(bool const& val) +AZStd::string ToString(bool const& val) { - static string sTrue = "true", sFalse = "false"; + static AZStd::string sTrue = "true", sFalse = "false"; return val ? sTrue : sFalse; } @@ -151,14 +151,14 @@ bool FromString(bool& val, cstr s) } // int64 -string ToString(int64 const& val) +AZStd::string ToString(int64 const& val) { char buffer[64]; _i64toa_s(val, buffer, sizeof(buffer), 10); return buffer; } // uint64 -string ToString(uint64 const& val) +AZStd::string ToString(uint64 const& val) { char buffer[64]; sprintf_s(buffer, "%" PRIu64, val); @@ -168,7 +168,7 @@ string ToString(uint64 const& val) // long -string ToString(long const& val) +AZStd::string ToString(long const& val) { char buffer[64]; _ltoa_s(val, buffer, sizeof(buffer), 10); @@ -176,7 +176,7 @@ string ToString(long const& val) } // ulong -string ToString(unsigned long const& val) +AZStd::string ToString(unsigned long const& val) { char buffer[64]; _ultoa_s(val, buffer, sizeof(buffer), 10); @@ -233,33 +233,33 @@ bool FromString(uint64& val, const char* s) { return Clamped bool FromString(long& val, const char* s) { return ClampedIntFromString(val, s); } bool FromString(unsigned long& val, const char* s) { return ClampedIntFromString(val, s); } -string ToString(int const& val) { return ToString(long(val)); } +AZStd::string ToString(int const& val) { return ToString(long(val)); } bool FromString(int& val, const char* s) { return ClampedIntFromString(val, s); } -string ToString(unsigned int const& val) { return ToString((unsigned long)(val)); } +AZStd::string ToString(unsigned int const& val) { return ToString((unsigned long)(val)); } bool FromString(unsigned int& val, const char* s) { return ClampedIntFromString(val, s); } -string ToString(short const& val) { return ToString(long(val)); } +AZStd::string ToString(short const& val) { return ToString(long(val)); } bool FromString(short& val, const char* s) { return ClampedIntFromString(val, s); } -string ToString(unsigned short const& val) { return ToString((unsigned long)(val)); } +AZStd::string ToString(unsigned short const& val) { return ToString((unsigned long)(val)); } bool FromString(unsigned short& val, const char* s) { return ClampedIntFromString(val, s); } -string ToString(char const& val) { return ToString(long(val)); } +AZStd::string ToString(char const& val) { return ToString(long(val)); } bool FromString(char& val, const char* s) { return ClampedIntFromString(val, s); } -string ToString(wchar_t const& val) { return ToString(long(val)); } +AZStd::string ToString(wchar_t const& val) { return ToString(long(val)); } bool FromString(wchar_t& val, const char* s) { return ClampedIntFromString(val, s); } -string ToString(signed char const& val) { return ToString(long(val)); } +AZStd::string ToString(signed char const& val) { return ToString(long(val)); } bool FromString(signed char& val, const char* s) { return ClampedIntFromString(val, s); } -string ToString(unsigned char const& val) { return ToString((unsigned long)(val)); } +AZStd::string ToString(unsigned char const& val) { return ToString((unsigned long)(val)); } bool FromString(unsigned char& val, const char* s) { return ClampedIntFromString(val, s); } -string ToString(const AZ::Uuid& val) +AZStd::string ToString(const AZ::Uuid& val) { - return val.ToString(); + return val.ToString(); } bool FromString(AZ::Uuid& val, const char* s) @@ -295,7 +295,7 @@ float NumToFromString(float val, int digits, bool floating, char buffer[], int b } // double -string ToString(double const& val) +AZStd::string ToString(double const& val) { char buffer[64]; sprintf_s(buffer, "%.16g", val); @@ -307,7 +307,7 @@ bool FromString(double& val, const char* s) } // float -string ToString(float const& val) +AZStd::string ToString(float const& val) { char buffer[64]; for (int digits = 7; digits < 10; digits++) @@ -329,11 +329,11 @@ bool FromString(float& val, const char* s) // string override. template <> -void TTypeInfo::GetMemoryUsage(ICrySizer* pSizer, void const* data) const +void TTypeInfo::GetMemoryUsage(ICrySizer* pSizer, void const* data) const { // CRAIG: just a temp hack to try and get things working #if !defined(LINUX) && !defined(APPLE) - pSizer->AddString(*(string*)data); + pSizer->AddString(*(AZStd::string*)data); #endif } @@ -343,7 +343,7 @@ struct STypeInfoTest { STypeInfoTest() { - TestType(string("well")); + TestType(AZStd::string("well")); TestType(true); @@ -435,7 +435,7 @@ bool CTypeInfo::CVarInfo::GetAttr(cstr name) const return FindAttr(Attrs, name) != 0; } -bool CTypeInfo::CVarInfo::GetAttr(cstr name, string& val) const +bool CTypeInfo::CVarInfo::GetAttr(cstr name, AZStd::string& val) const { cstr valstr = FindAttr(Attrs, name); if (!valstr) @@ -459,7 +459,7 @@ bool CTypeInfo::CVarInfo::GetAttr(cstr name, string& val) const end--; } } - val = string(valstr, end - valstr); + val = AZStd::string(valstr, end - valstr); return true; } @@ -735,7 +735,7 @@ bool CStructInfo::ToValue(const void* data, void* value, const CTypeInfo& typeVa Nameless , 1, ,2 1,2 ; */ -static void StripCommas(string& str) +static void StripCommas(AZStd::string& str) { size_t nLast = str.size(); while (nLast > 0 && str[nLast - 1] == ',') @@ -745,9 +745,9 @@ static void StripCommas(string& str) str.resize(nLast); } -string CStructInfo::ToString(const void* data, FToString flags, const void* def_data) const +AZStd::string CStructInfo::ToString(const void* data, FToString flags, const void* def_data) const { - string str; // Return str. + AZStd::string str; // Return str. for (int i = 0; i < Vars.size(); i++) { @@ -763,7 +763,7 @@ string CStructInfo::ToString(const void* data, FToString flags, const void* def_ str += ","; } - string substr = var.ToString(data, FToString(flags).Sub(0), def_data); + AZStd::string substr = var.ToString(data, FToString(flags).Sub(0), def_data); if (flags.SkipDefault && substr.empty()) { @@ -772,7 +772,7 @@ string CStructInfo::ToString(const void* data, FToString flags, const void* def_ if (flags.NamedFields) { - if (*str) + if (*str.c_str()) { str += ","; } @@ -782,7 +782,7 @@ string CStructInfo::ToString(const void* data, FToString flags, const void* def_ str += "="; } } - if (substr.find(',') != string::npos || substr.find('=') != string::npos) + if (substr.find(',') != AZStd::string::npos || substr.find('=') != AZStd::string::npos) { // Encase nested composite types in parens. str += "("; @@ -811,7 +811,7 @@ string CStructInfo::ToString(const void* data, FToString flags, const void* def_ // Retrieve and return one subelement from src, advancing the pointer. // Copy to tempstr if necessary. -typedef CryStackStringT CTempStr; +typedef AZStd::fixed_string<256> CTempStr; void ParseElement(cstr& src, cstr& varname, cstr& val, CTempStr& tempstr) { @@ -882,21 +882,24 @@ void ParseElement(cstr& src, cstr& varname, cstr& val, CTempStr& tempstr) if (*end) { // Must copy sub string to temp. - val = (cstr)tempstr + (val - varname); - eq = (cstr)tempstr + (eq - varname); - varname = tempstr.assign(varname, end); + val = tempstr.c_str() + (val - varname); + eq = tempstr.c_str() + (eq - varname); + tempstr.assign(varname, end); + varname = tempstr.c_str(); non_const(*eq) = 0; } else { // Copy just varname to temp, return val in place. - varname = tempstr.assign(varname, eq); + tempstr.assign(varname, eq); + varname = tempstr.c_str(); } } else if (*end) { // Must copy sub string to temp. - val = tempstr.assign(val, end); + tempstr.assign(val, end); + val = tempstr.c_str(); } // Else can return val without copying. @@ -963,7 +966,7 @@ void CStructInfo::SwapEndian(void* data, size_t nCount, bool bWriting) const { non_const(*this).MakeEndianDesc(); - if (EndianDesc.length() == 1 && !HasBitfields && EndianDescSize(EndianDesc) == Size) + if (EndianDesc.length() == 1 && !HasBitfields && EndianDescSize(EndianDesc.c_str()) == Size) { // Optimised array swap. size_t nElems = (EndianDesc[0u] & 0x3F) * nCount; @@ -989,7 +992,7 @@ void CStructInfo::SwapEndian(void* data, size_t nCount, bool bWriting) const // First swap bits. // Iterate the endian descriptor. void* step = data; - for (cstr desc = EndianDesc; *desc; desc++) + for (cstr desc = EndianDesc.c_str(); *desc; desc++) { size_t nElems = *desc & 0x3F; switch (*desc & 0xC0) @@ -1064,7 +1067,7 @@ void CStructInfo::MakeEndianDesc() // Struct-computed endian desc. CStructInfo const& infoSub = static_cast(var.Type); non_const(infoSub).MakeEndianDesc(); - subdesc = infoSub.EndianDesc; + subdesc = infoSub.EndianDesc.c_str(); if (!*subdesc) { // No swapping. diff --git a/Code/Legacy/CryCommon/CryTypeInfo.h b/Code/Legacy/CryCommon/CryTypeInfo.h index 43b9d3e5b9..0bd734492a 100644 --- a/Code/Legacy/CryCommon/CryTypeInfo.h +++ b/Code/Legacy/CryCommon/CryTypeInfo.h @@ -17,13 +17,12 @@ #include #include "CryArray.h" #include "Options.h" -#include "CryString.h" #include "TypeInfo_decl.h" class ICrySizer; class CCryName; -string ToString(CCryName const& val); +AZStd::string ToString(CCryName const& val); bool FromString(CCryName& val, const char* s); //--------------------------------------------------------------------------- @@ -85,7 +84,7 @@ struct CTypeInfo // // Convert value to string. - virtual string ToString([[maybe_unused]] const void* data, [[maybe_unused]] FToString flags = 0, [[maybe_unused]] const void* def_data = 0) const + virtual AZStd::string ToString([[maybe_unused]] const void* data, [[maybe_unused]] FToString flags = 0, [[maybe_unused]] const void* def_data = 0) const { return ""; } // Write value from string, return success. @@ -180,7 +179,7 @@ struct CTypeInfo assert(!bBitfield); return Type.FromString((char*)base + Offset, str, flags); } - string ToString(const void* base, FToString flags = 0, const void* def_base = 0) const + AZStd::string ToString(const void* base, FToString flags = 0, const void* def_base = 0) const { assert(!bBitfield); return Type.ToString((const char*)base + Offset, flags, def_base ? (const char*)def_base + Offset : 0); @@ -189,7 +188,7 @@ struct CTypeInfo // Attribute access. Not fast. bool GetAttr(cstr name) const; bool GetAttr(cstr name, float& val) const; - bool GetAttr(cstr name, string& val) const; + bool GetAttr(cstr name, AZStd::string& val) const; // Comment, excluding attributes. cstr GetComment() const; diff --git a/Code/Legacy/CryCommon/IEntityRenderState.h b/Code/Legacy/CryCommon/IEntityRenderState.h index 9ee974b7fc..e9f041ba17 100644 --- a/Code/Legacy/CryCommon/IEntityRenderState.h +++ b/Code/Legacy/CryCommon/IEntityRenderState.h @@ -205,7 +205,7 @@ struct IRenderNode // Debug info about object. virtual const char* GetName() const = 0; virtual const char* GetEntityClassName() const = 0; - virtual string GetDebugString([[maybe_unused]] char type = 0) const { return ""; } + virtual AZStd::string GetDebugString([[maybe_unused]] char type = 0) const { return ""; } virtual float GetImportance() const { return 1.f; } // Description: diff --git a/Code/Legacy/CryCommon/IFont.h b/Code/Legacy/CryCommon/IFont.h index c95182abd7..41e9f5653a 100644 --- a/Code/Legacy/CryCommon/IFont.h +++ b/Code/Legacy/CryCommon/IFont.h @@ -16,7 +16,6 @@ #include #include -#include #include #include @@ -101,7 +100,7 @@ struct ICryFont // All font names separated by , // Example: // "console,default,hud" - virtual string GetLoadedFontNames() const = 0; + virtual AZStd::string GetLoadedFontNames() const = 0; //! \brief Called when the g_language (current language) setting changes. //! @@ -264,7 +263,7 @@ struct IFFont // Description: // Wraps text based on specified maximum line width (UTF-8) - virtual void WrapText(string& result, float maxWidth, const char* pStr, const STextDrawContext& ctx) = 0; + virtual void WrapText(AZStd::string& result, float maxWidth, const char* pStr, const STextDrawContext& ctx) = 0; // Description: // Puts the memory used by this font into the given sizer. @@ -338,7 +337,7 @@ struct FontFamily FontFamily& operator=(const FontFamily&) = delete; FontFamily& operator=(const FontFamily&&) = delete; - string familyName; + AZStd::string familyName; IFFont* normal; IFFont* bold; IFFont* italic; diff --git a/Code/Legacy/CryCommon/IRenderer.h b/Code/Legacy/CryCommon/IRenderer.h index d3557129bf..254f1933de 100644 --- a/Code/Legacy/CryCommon/IRenderer.h +++ b/Code/Legacy/CryCommon/IRenderer.h @@ -17,7 +17,6 @@ #include "Cry_Matrix33.h" #include "Cry_Color.h" #include "smartptr.h" -#include "StringUtils.h" #include // <> required for Interfuscator #include "smartptr.h" #include @@ -1449,7 +1448,7 @@ struct IRenderer virtual const char* EF_GetShaderMissLogPath() = 0; ///////////////////////////////////////////////////////////////////////////////// - virtual string* EF_GetShaderNames(int& nNumShaders) = 0; + virtual AZStd::string* EF_GetShaderNames(int& nNumShaders) = 0; // Summary: // Reloads file virtual bool EF_ReloadFile (const char* szFileName) = 0; diff --git a/Code/Legacy/CryCommon/ISerialize.h b/Code/Legacy/CryCommon/ISerialize.h index 0476237903..84e665850f 100644 --- a/Code/Legacy/CryCommon/ISerialize.h +++ b/Code/Legacy/CryCommon/ISerialize.h @@ -179,28 +179,16 @@ struct SSerializeString void resize(int sz) { m_str.resize(sz); } void reserve(int sz) { m_str.reserve(sz); } - void set_string(const string& s) + void set_string(const AZStd::string& s) { m_str.assign(s.begin(), s.size()); } -#if !defined(RESOURCE_COMPILER) - void set_string(const CryStringLocal& s) - { - m_str.assign(s.begin(), s.size()); - } -#endif - template - void set_string(const CryFixedStringT& s) - { - m_str.assign(s.begin(), s.size()); - } - - operator const string () const { + operator const AZStd::string() const { return m_str; } private: - string m_str; + AZStd::string m_str; }; // the ISerialize is intended to be implemented by objects that need @@ -308,7 +296,7 @@ public: m_pSerialize->Value(szName, value); } - void Value(const char* szName, string& value, int policy) + void Value(const char* szName, AZStd::string& value, int policy) { if (IsWriting()) { @@ -327,11 +315,11 @@ public: value = serializeString.c_str(); } } - ILINE void Value(const char* szName, string& value) + ILINE void Value(const char* szName, AZStd::string& value) { Value(szName, value, 0); } - void Value(const char* szName, const string& value, int policy) + void Value(const char* szName, const AZStd::string& value, int policy) { if (IsWriting()) { @@ -343,76 +331,7 @@ public: assert(0 && "This function can only be used for Writing"); } } - ILINE void Value(const char* szName, const string& value) - { - Value(szName, value, 0); - } - template - void Value(const char* szName, CryStringLocalT& value, int policy) - { - if (IsWriting()) - { - SSerializeString& serializeString = SetSharedSerializeString(value); - m_pSerialize->WriteStringValue(szName, serializeString, policy); - } - else - { - if (GetSerializationTarget() != eST_Script) - { - value = ""; - } - - SSerializeString& serializeString = SetSharedSerializeString(value); - m_pSerialize->ReadStringValue(szName, serializeString, policy); - value = serializeString.c_str(); - } - } - template - ILINE void Value(const char* szName, CryStringLocalT& value) - { - Value(szName, value, 0); - } - template - void Value(const char* szName, const CryStringLocalT& value, int policy) - { - if (IsWriting()) - { - SSerializeString& serializeString = SetSharedSerializeString(value); - m_pSerialize->WriteStringValue(szName, serializeString, policy); - } - else - { - assert(0 && "This function can only be used for Writing"); - } - } - template - ILINE void Value(const char* szName, const CryStringLocalT& value) - { - Value(szName, value, 0); - } - template - void Value(const char* szName, CryFixedStringT& value, int policy) - { - if (IsWriting()) - { - SSerializeString& serializeString = SetSharedSerializeString(value); - m_pSerialize->WriteStringValue(szName, serializeString, policy); - } - else - { - if (GetSerializationTarget() != eST_Script) - { - value = ""; - } - - SSerializeString& serializeString = SetSharedSerializeString(value); - m_pSerialize->ReadStringValue(szName, serializeString, policy); - assert(serializeString.length() <= S); - value = serializeString.c_str(); - } - } - template - ILINE void Value(const char* szName, CryFixedStringT& value) + ILINE void Value(const char* szName, const AZStd::string& value) { Value(szName, value, 0); } @@ -493,7 +412,7 @@ public: m_pSerialize->ValueWithDefault(name, x, defaultValue); } - void ValueWithDefault(const char* szName, string& value, const string& defaultValue) + void ValueWithDefault(const char* szName, AZStd::string& value, const AZStd::string& defaultValue) { static SSerializeString defaultSerializeString; @@ -919,34 +838,13 @@ public: return CSerializeWrapper(m_pSerialize); } - SSerializeString& SetSharedSerializeString(const string& str) + SSerializeString& SetSharedSerializeString(const AZStd::string& str) { static SSerializeString serializeString; serializeString.set_string(str); return serializeString; } -#if !defined(RESOURCE_COMPILER) - SSerializeString& SetSharedSerializeString(const CryStringLocal& str) - { - - - static SSerializeString serializeString; - serializeString.set_string(str); - return serializeString; - } -#endif - - template - SSerializeString& SetSharedSerializeString(const CryFixedStringT& str) - { - - - static SSerializeString serializeString; - serializeString.set_string(str); - return serializeString; - } - private: TISerialize* m_pSerialize; }; diff --git a/Code/Legacy/CryCommon/IShader.h b/Code/Legacy/CryCommon/IShader.h index 3a49e4d1ac..978da1a77f 100644 --- a/Code/Legacy/CryCommon/IShader.h +++ b/Code/Legacy/CryCommon/IShader.h @@ -25,7 +25,6 @@ #include "Cry_Matrix33.h" #include "Cry_Color.h" #include "smartptr.h" -#include "StringUtils.h" #include // <> required for Interfuscator #include "smartptr.h" #include "VertexFormats.h" @@ -1394,12 +1393,12 @@ struct IRenderTarget struct STexSamplerFX { #if SHADER_REFLECT_TEXTURE_SLOTS - string m_szUIName; - string m_szUIDescription; + AZStd::string m_szUIName; + AZStd::string m_szUIDescription; #endif - string m_szName; - string m_szTexture; + AZStd::string m_szName; + AZStd::string m_szTexture; union { @@ -1708,7 +1707,7 @@ struct SEfResTextureExt //------------------------------------------------------------------------------ struct SEfResTexture { - string m_Name; + AZStd::string m_Name; bool m_bUTile; bool m_bVTile; signed char m_Filter; @@ -1890,7 +1889,7 @@ struct SEfResTexture struct SBaseShaderResources { AZStd::vector m_ShaderParams; - string m_TexturePath; + AZStd::string m_TexturePath; const char* m_szMaterialName; float m_AlphaRef; @@ -2146,8 +2145,8 @@ struct SShaderTextureSlot m_TexType = eTT_MaxTexType; } - string m_Name; - string m_Description; + AZStd::string m_Name; + AZStd::string m_Description; byte m_TexType; // 2D, 3D, Cube etc.. void GetMemoryUsage(ICrySizer* pSizer) const @@ -2726,7 +2725,7 @@ protected: virtual ~ILightAnimWrapper() {} protected: - string m_name; + AZStd::string m_name; IAnimNode* m_pNode; }; @@ -3256,12 +3255,12 @@ enum EGrNodeIOSemantic struct SShaderGraphFunction { - string m_Data; - string m_Name; - std::vector inParams; - std::vector outParams; - std::vector szInTypes; - std::vector szOutTypes; + AZStd::string m_Data; + AZStd::string m_Name; + std::vector inParams; + std::vector outParams; + std::vector szInTypes; + std::vector szOutTypes; }; struct SShaderGraphNode @@ -3269,8 +3268,8 @@ struct SShaderGraphNode EGrNodeType m_eType; EGrNodeFormat m_eFormat; EGrNodeIOSemantic m_eSemantic; - string m_CustomSemantics; - string m_Name; + AZStd::string m_CustomSemantics; + AZStd::string m_Name; bool m_bEditable; bool m_bWasAdded; SShaderGraphFunction* m_pFunction; @@ -3296,7 +3295,7 @@ struct SShaderGraphBlock { EGrBlockType m_eType; EGrBlockSamplerType m_eSamplerType; - string m_ClassName; + AZStd::string m_ClassName; FXShaderGraphNodes m_Nodes; ~SShaderGraphBlock(); diff --git a/Code/Legacy/CryCommon/ISystem.h b/Code/Legacy/CryCommon/ISystem.h index d934995b4d..973196ac4c 100644 --- a/Code/Legacy/CryCommon/ISystem.h +++ b/Code/Legacy/CryCommon/ISystem.h @@ -946,7 +946,7 @@ struct ISystem // If m_GraphicsSettingsMap is defined (in Graphics Settings Dialog box), fills in mapping based on sys_spec_Full // Arguments: // sPath - e.g. "Game/Config/CVarGroups" - virtual void AddCVarGroupDirectory(const string& sPath) = 0; + virtual void AddCVarGroupDirectory(const AZStd::string& sPath) = 0; // Summary: // Saves system configuration. diff --git a/Code/Legacy/CryCommon/IXml.h b/Code/Legacy/CryCommon/IXml.h index b722da78e3..e4cb752234 100644 --- a/Code/Legacy/CryCommon/IXml.h +++ b/Code/Legacy/CryCommon/IXml.h @@ -94,12 +94,12 @@ void testXml(bool bReuseStrings) // Summary: // Special string wrapper for xml nodes. class XmlString - : public string + : public AZStd::string { public: XmlString() {}; XmlString(const char* str) - : string(str) {}; + : AZStd::string(str) {}; operator const char*() const { return c_str(); diff --git a/Code/Legacy/CryCommon/Linux_Win32Wrapper.h b/Code/Legacy/CryCommon/Linux_Win32Wrapper.h index 2dea83925d..e47d16d1bc 100644 --- a/Code/Legacy/CryCommon/Linux_Win32Wrapper.h +++ b/Code/Legacy/CryCommon/Linux_Win32Wrapper.h @@ -329,9 +329,6 @@ inline uint32 GetTickCount() #define _wtof(str) wcstod(str, 0) -// Need to include this before using it's used in finddata, but after the strnicmp definition -#include "CryString.h" - typedef struct __finddata64_t { //!< atributes set by find request diff --git a/Code/Legacy/CryCommon/LyShine/UiBase.h b/Code/Legacy/CryCommon/LyShine/UiBase.h index 274618821e..af6314be2c 100644 --- a/Code/Legacy/CryCommon/LyShine/UiBase.h +++ b/Code/Legacy/CryCommon/LyShine/UiBase.h @@ -65,6 +65,5 @@ namespace AZ AZ_TYPE_INFO_SPECIALIZE(ColorF, "{63782551-A309-463B-A301-3A360800DF1E}"); AZ_TYPE_INFO_SPECIALIZE(ColorB, "{6F0CC2C0-0CC6-4DBF-9297-B043F270E6A4}"); AZ_TYPE_INFO_SPECIALIZE(Vec4, "{CAC9510C-8C00-41D4-BC4D-2C6A8136EB30}"); - AZ_TYPE_INFO_SPECIALIZE(CryStringT, "{835199FB-292B-4DB3-BC7C-366E356300FA}"); } // namespace AZ diff --git a/Code/Legacy/CryCommon/LyShine/UiSerializeHelpers.h b/Code/Legacy/CryCommon/LyShine/UiSerializeHelpers.h index 05289c6c50..3ad3de2d3d 100644 --- a/Code/Legacy/CryCommon/LyShine/UiSerializeHelpers.h +++ b/Code/Legacy/CryCommon/LyShine/UiSerializeHelpers.h @@ -22,154 +22,6 @@ namespace LyShine { - //////////////////////////////////////////////////////////////////////////////////////////////// - // Helper function to VersionConverter to convert a CryString field to an AZStd::String - // Inline to avoid DLL linkage issues - inline bool ConvertSubElementFromCryStringToAzString( - AZ::SerializeContext& context, - AZ::SerializeContext::DataElementNode& classElement, - const char* subElementName) - { - int index = classElement.FindElement(AZ_CRC(subElementName)); - if (index != -1) - { - AZ::SerializeContext::DataElementNode& elementNode = classElement.GetSubElement(index); - - CryStringT oldData; - - if (!elementNode.GetData(oldData)) - { - // Error, old subElement was not a string or not valid - AZ_Error("Serialization", false, "Cannot get string data for element %s.", subElementName); - return false; - } - - // Remove old version. - classElement.RemoveElement(index); - - // Add a new element for the new data. - int newElementIndex = classElement.AddElement(context, subElementName); - if (newElementIndex == -1) - { - // Error adding the new sub element - AZ_Error("Serialization", false, "AddElement failed for converted element %s", subElementName); - return false; - } - - AZStd::string newData(oldData.c_str()); - classElement.GetSubElement(newElementIndex).SetData(context, newData); - } - - // if the field did not exist then we do not report an error - return true; - } - - //////////////////////////////////////////////////////////////////////////////////////////////// - // Helper function to VersionConverter to convert a CryString field to a char - // Inline to avoid DLL linkage issues - inline bool ConvertSubElementFromCryStringToChar( - AZ::SerializeContext& context, - AZ::SerializeContext::DataElementNode& classElement, - const char* subElementName, - char defaultValue) - { - int index = classElement.FindElement(AZ_CRC(subElementName)); - if (index != -1) - { - AZ::SerializeContext::DataElementNode& elementNode = classElement.GetSubElement(index); - - CryStringT oldData; - - if (!elementNode.GetData(oldData)) - { - // Error, old subElement was not a CryString - AZ_Error("Serialization", false, "Element %s is not a CryString.", subElementName); - return false; - } - - // Remove old version. - classElement.RemoveElement(index); - - // Add a new element for the new data. - int newElementIndex = classElement.AddElement(context, subElementName); - if (newElementIndex == -1) - { - // Error adding the new sub element - AZ_Error("Serialization", false, "AddElement failed for converted element %s", subElementName); - return false; - } - - char newData = (oldData.empty()) ? defaultValue : oldData[0]; - classElement.GetSubElement(newElementIndex).SetData(context, newData); - } - - // if the field did not exist then we do not report an error - return true; - } - - //////////////////////////////////////////////////////////////////////////////////////////////// - // Helper function to VersionConverter to convert a CryString field to a simple asset reference - // Inline to avoid DLL linkage issues - template - inline bool ConvertSubElementFromCryStringToAssetRef( - AZ::SerializeContext& context, - AZ::SerializeContext::DataElementNode& classElement, - const char* subElementName) - { - int index = classElement.FindElement(AZ_CRC(subElementName)); - if (index != -1) - { - AZ::SerializeContext::DataElementNode& elementNode = classElement.GetSubElement(index); - - CryStringT oldData; - - if (!elementNode.GetData(oldData)) - { - // Error, old subElement was not a CryString - AZ_Error("Serialization", false, "Element %s is not a CryString.", subElementName); - return false; - } - - // Remove old version. - classElement.RemoveElement(index); - - // Add a new element for the new data. - int simpleAssetRefIndex = classElement.AddElement >(context, subElementName); - if (simpleAssetRefIndex == -1) - { - // Error adding the new sub element - AZ_Error("Serialization", false, "AddElement failed for simpleAssetRefIndex %s", subElementName); - return false; - } - - // add a sub element for the SimpleAssetReferenceBase within the SimpleAssetReference - AZ::SerializeContext::DataElementNode& simpleAssetRefNode = classElement.GetSubElement(simpleAssetRefIndex); - int simpleAssetRefBaseIndex = simpleAssetRefNode.AddElement(context, "BaseClass1"); - if (simpleAssetRefBaseIndex == -1) - { - // Error adding the new sub element - AZ_Error("Serialization", false, "AddElement failed for converted element BaseClass1"); - return false; - } - - // add a sub element for the AssetPath within the SimpleAssetReference - AZ::SerializeContext::DataElementNode& simpleAssetRefBaseNode = simpleAssetRefNode.GetSubElement(simpleAssetRefBaseIndex); - int assetPathElementIndex = simpleAssetRefBaseNode.AddElement(context, "AssetPath"); - if (assetPathElementIndex == -1) - { - // Error adding the new sub element - AZ_Error("Serialization", false, "AddElement failed for converted element AssetPath"); - return false; - } - - AZStd::string newData(oldData.c_str()); - simpleAssetRefBaseNode.GetSubElement(assetPathElementIndex).SetData(context, newData); - } - - // if the field did not exist then we do not report an error - return true; - } - //////////////////////////////////////////////////////////////////////////////////////////////// // Helper function to VersionConverter to convert an AZStd::string field to a simple asset reference // Inline to avoid DLL linkage issues diff --git a/Code/Legacy/CryCommon/StlUtils.h b/Code/Legacy/CryCommon/StlUtils.h index 2438ee9f7b..d7e5697593 100644 --- a/Code/Legacy/CryCommon/StlUtils.h +++ b/Code/Legacy/CryCommon/StlUtils.h @@ -494,7 +494,7 @@ namespace stl //! Specialization of string to const char cast. template <> - inline const char* constchar_cast(const string& type) + inline const char* constchar_cast(const AZStd::string& type) { return type.c_str(); } diff --git a/Code/Legacy/CryCommon/StringUtils.h b/Code/Legacy/CryCommon/StringUtils.h deleted file mode 100644 index ffd1001f95..0000000000 --- a/Code/Legacy/CryCommon/StringUtils.h +++ /dev/null @@ -1,1358 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - -#ifndef _CRY_ENGINE_STRING_UTILS_HDR_ -#define _CRY_ENGINE_STRING_UTILS_HDR_ - -#pragma once - -#include "CryString.h" -#include -#include // std::replace, std::min -#include "UnicodeFunctions.h" -#include "UnicodeIterator.h" -#include - -#if !defined(RESOURCE_COMPILER) -# include "CryCrc32.h" -#endif - -#if defined(LINUX) || defined(APPLE) -# include -#endif - -namespace CryStringUtils -{ - // Convert a single ASCII character to lower case, this is compatible with the standard "C" locale (ie, only A-Z). - inline char toLowerAscii(char c) - { - return (c >= 'A' && c <= 'Z') ? (c - 'A' + 'a') : c; - } - - // Convert a single ASCII character to upper case, this is compatible with the standard "C" locale (ie, only A-Z). - inline char toUpperAscii(char c) - { - return (c >= 'a' && c <= 'z') ? (c - 'a' + 'A') : c; - } -} - -// cry_strXXX() and CryStringUtils_Internal::strXXX(): -// -// The functions copy characters from src to dst one by one until any of -// the following conditions is met: -// 1) the end of the destination buffer (minus one character) is reached. -// 2) the end of the source buffer is reached. -// 3) zero character is found in the source buffer. -// -// When any of 1), 2), 3) happens, the functions write the terminating zero -// character to the destination buffer and return. -// -// The functions guarantee writing the terminating zero character to the -// destination buffer (if the buffer can fit at least one character). -// -// The functions return false when a null pointer is passed or when -// clamping happened (i.e. when the end of the destination buffer is -// reached but the source has some characters left). - -namespace CryStringUtils_Internal -{ - template - inline bool strcpy_with_clamp(TChar* const dst, size_t const dst_size_in_bytes, const TChar* const src, size_t const src_size_in_bytes) - { - COMPILE_TIME_ASSERT(sizeof(TChar) == sizeof(char) || sizeof(TChar) == sizeof(wchar_t)); - - if (!dst || dst_size_in_bytes < sizeof(TChar)) - { - return false; - } - - if (!src || src_size_in_bytes < sizeof(TChar)) - { - dst[0] = 0; - return src != 0; // we return true for non-null src without characters - } - - const size_t src_n = src_size_in_bytes / sizeof(TChar); - const size_t n = (std::min)(dst_size_in_bytes / sizeof(TChar) - 1, src_n); - - for (size_t i = 0; i < n; ++i) - { - dst[i] = src[i]; - if (!src[i]) - { - return true; - } - } - - dst[n] = 0; - return n >= src_n || src[n] == 0; - } - - template - inline bool strcat_with_clamp(TChar* const dst, size_t const dst_size_in_bytes, const TChar* const src, size_t const src_size_in_bytes) - { - COMPILE_TIME_ASSERT(sizeof(TChar) == sizeof(char) || sizeof(TChar) == sizeof(wchar_t)); - - if (!dst || dst_size_in_bytes < sizeof(TChar)) - { - return false; - } - - const size_t dst_n = dst_size_in_bytes / sizeof(TChar) - 1; - - size_t dst_len = 0; - while (dst_len < dst_n && dst[dst_len]) - { - ++dst_len; - } - - if (!src || src_size_in_bytes < sizeof(TChar)) - { - dst[dst_len] = 0; - return src != 0; // we return true for non-null src without characters - } - - const size_t src_n = src_size_in_bytes / sizeof(TChar); - const size_t n = (std::min)(dst_n - dst_len, src_n); - TChar* dst_ptr = &dst[dst_len]; - - for (size_t i = 0; i < n; ++i) - { - *dst_ptr++ = src[i]; - if (!src[i]) - { - return true; - } - } - - *dst_ptr = 0; - return n >= src_n || src[n] == 0; - } - - // Compares characters as case-sensitive, locale agnostic. - template - struct SCharComparatorCaseSensitive - { - static bool IsEqual(CharType a, CharType b) - { - return a == b; - } - }; - - // Compares characters as case-insensitive, uses the standard "C" locale. - template - struct SCharComparatorCaseInsensitive - { - static bool IsEqual(CharType a, CharType b) - { - if (a < 0x80 && b < 0x80) - { - a = (CharType)CryStringUtils::toLowerAscii(char(a)); - b = (CharType)CryStringUtils::toLowerAscii(char(b)); - } - return a == b; - } - }; - - // Template for wildcard matching, UCS code-point aware. - // Can be used for ASCII and Unicode (UTF-8/UTF-16/UTF-32), but not for ANSI. - // ? will match exactly one code-point. - // * will match zero or more code-points. - template class CharComparator, class CharType> - inline bool MatchesWildcards_Tpl(const CharType* pStr, const CharType* pWild) - { - const CharType* savedStr = 0; - const CharType* savedWild = 0; - - while ((*pStr) && (*pWild != '*')) - { - if (!CharComparator::IsEqual(*pWild, *pStr) && (*pWild != '?')) - { - return false; - } - - // We need special handling of '?' for Unicode - if (*pWild == '?' && *pStr > 127) - { - Unicode::CIterator utf(pStr, pStr + 4); - if (utf.IsAtValidCodepoint()) - { - pStr = (++utf).GetPosition(); - --pStr; - } - } - - ++pWild; - ++pStr; - } - - while (*pStr) - { - if (*pWild == '*') - { - if (!*++pWild) - { - return true; - } - savedWild = pWild; - savedStr = pStr + 1; - } - else if (CharComparator::IsEqual(*pWild, *pStr) || (*pWild == '?')) - { - // We need special handling of '?' for Unicode - if (*pWild == '?' && *pStr > 127) - { - Unicode::CIterator utf(pStr, pStr + 4); - if (utf.IsAtValidCodepoint()) - { - pStr = (++utf).GetPosition(); - --pStr; - } - } - - ++pWild; - ++pStr; - } - else - { - pWild = savedWild; - pStr = savedStr++; - } - } - - while (*pWild == '*') - { - ++pWild; - } - - return *pWild == 0; - } -} // namespace CryStringUtils_Internal - - -inline bool cry_strcpy(char* const dst, size_t const dst_size_in_bytes, const char* const src) -{ - return CryStringUtils_Internal::strcpy_with_clamp(dst, dst_size_in_bytes, src, (size_t)-1); -} - -inline bool cry_strcpy(char* const dst, size_t const dst_size_in_bytes, const char* const src, size_t const src_size_in_bytes) -{ - return CryStringUtils_Internal::strcpy_with_clamp(dst, dst_size_in_bytes, src, src_size_in_bytes); -} - -template -inline bool cry_strcpy(char(&dst)[SIZE_IN_CHARS], const char* const src) -{ - return CryStringUtils_Internal::strcpy_with_clamp(dst, SIZE_IN_CHARS, src, (size_t)-1); -} - -template -inline bool cry_strcpy(char(&dst)[SIZE_IN_CHARS], const char* const src, size_t const src_size_in_bytes) -{ - return CryStringUtils_Internal::strcpy_with_clamp(dst, SIZE_IN_CHARS, src, src_size_in_bytes); -} - - -inline bool cry_wstrcpy(wchar_t* const dst, size_t const dst_size_in_bytes, const wchar_t* const src) -{ - return CryStringUtils_Internal::strcpy_with_clamp(dst, dst_size_in_bytes, src, (size_t)-1); -} - -inline bool cry_wstrcpy(wchar_t* const dst, size_t const dst_size_in_bytes, const wchar_t* const src, size_t const src_size_in_bytes) -{ - return CryStringUtils_Internal::strcpy_with_clamp(dst, dst_size_in_bytes, src, src_size_in_bytes); -} - -template -inline bool cry_wstrcpy(wchar_t(&dst)[SIZE_IN_WCHARS], const wchar_t* const src) -{ - return CryStringUtils_Internal::strcpy_with_clamp(dst, SIZE_IN_WCHARS * sizeof(wchar_t), src, (size_t)-1); -} - -template -inline bool cry_wstrcpy(wchar_t(&dst)[SIZE_IN_WCHARS], const wchar_t* const src, size_t const src_size_in_bytes) -{ - return CryStringUtils_Internal::strcpy_with_clamp(dst, SIZE_IN_WCHARS * sizeof(wchar_t), src, src_size_in_bytes); -} - - -inline bool cry_strcat(char* const dst, size_t const dst_size_in_bytes, const char* const src) -{ - return CryStringUtils_Internal::strcat_with_clamp(dst, dst_size_in_bytes, src, (size_t)-1); -} - -inline bool cry_strcat(char* const dst, size_t const dst_size_in_bytes, const char* const src, size_t const src_size_in_bytes) -{ - return CryStringUtils_Internal::strcat_with_clamp(dst, dst_size_in_bytes, src, src_size_in_bytes); -} - -template -inline bool cry_strcat(char(&dst)[SIZE_IN_CHARS], const char* const src) -{ - return CryStringUtils_Internal::strcat_with_clamp(dst, SIZE_IN_CHARS, src, (size_t)-1); -} - -template -inline bool cry_strcat(char(&dst)[SIZE_IN_CHARS], const char* const src, size_t const src_size_in_bytes) -{ - return CryStringUtils_Internal::strcat_with_clamp(dst, SIZE_IN_CHARS, src, src_size_in_bytes); -} - - -inline bool cry_wstrcat(wchar_t* const dst, size_t const dst_size_in_bytes, const wchar_t* const src) -{ - return CryStringUtils_Internal::strcat_with_clamp(dst, dst_size_in_bytes, src, (size_t)-1); -} - -inline bool cry_wstrcat(wchar_t* const dst, size_t const dst_size_in_bytes, const wchar_t* const src, size_t const src_size_in_bytes) -{ - return CryStringUtils_Internal::strcat_with_clamp(dst, dst_size_in_bytes, src, src_size_in_bytes); -} - -template -inline bool cry_wstrcat(wchar_t(&dst)[SIZE_IN_WCHARS], const wchar_t* const src) -{ - return CryStringUtils_Internal::strcat_with_clamp(dst, SIZE_IN_WCHARS * sizeof(wchar_t), src, (size_t)-1); -} - -template -inline bool cry_wstrcat(wchar_t(&dst)[SIZE_IN_WCHARS], const wchar_t* const src, size_t const src_size_in_bytes) -{ - return CryStringUtils_Internal::strcat_with_clamp(dst, SIZE_IN_WCHARS * sizeof(wchar_t), src, src_size_in_bytes); -} - - -namespace CryStringUtils -{ - enum - { - CRY_DEFAULT_HASH_SEED = 40503, // This is a large 16 bit prime number (perfect for seeding) - CRY_EMPTY_STR_HASH = 3350499166U, // HashString("") - }; - - // removes the extension from the file path - // \param szFilePath the source path - inline char* StripFileExtension(char* szFilePath) - { - for (char* p = szFilePath + (int)strlen(szFilePath) - 1; p >= szFilePath; --p) - { - switch (*p) - { - case ':': - case '/': - case '\\': - // we've reached a path separator - it means there's no extension in this name - return nullptr; - case '.': - // there's an extension in this file name - *p = '\0'; - return p + 1; - } - } - // it seems the file name is a pure name, without path or extension - return nullptr; - } - - - // returns the parent directory of the given file or directory. - // the returned path is WITHOUT the trailing slash - // if the input path has a trailing slash, it's ignored - // nGeneration - is the number of parents to scan up - // Note: A drive specifier (if any) will always be kept (Windows-specific). - template - StringCls GetParentDirectory(const StringCls& strFilePath, int nGeneration = 1) - { - for (const char* p = strFilePath.c_str() + strFilePath.length() - 2; // -2 is for the possible trailing slash: there always must be some trailing symbol which is the file/directory name for which we should get the parent - p >= strFilePath.c_str(); - --p) - { - switch (*p) - { - case ':': - return StringCls(strFilePath.c_str(), p); - break; - case '/': - case '\\': - // we've reached a path separator - return everything before it. - if (!--nGeneration) - { - return StringCls(strFilePath.c_str(), p); - } - break; - } - } - ; - // the file name is a pure name, without path or extension - return StringCls(); - } - - /*! - // converts all chars to lower case - */ - inline string ToLower(const string& str) - { - string temp = str; - -#ifndef NOT_USE_CRY_STRING - temp.MakeLower(); -#else - std::transform(temp.begin(), temp.end(), temp.begin(), toLowerAscii); // STL MakeLower -#endif - - return temp; - } - - /// Converts the single character to lower case. - /*! - \param c source character to convert to lower case if possible - \return the lower case character equivalent if possible - */ - inline char ToLower(char c) - { - return ((c <= 'Z') && (c >= 'A')) ? c + ('a' - 'A') : c; - } - - /// Converts the specified character into lowercase. - /*! - \param c the character to convert to lowercase - \return the lowercase character - */ - // Converts all ASCII characters to upper case. - // Note: Any non-ASCII characters are left unchanged. - // This function is ASCII-only and locale agnostic. - inline string toUpper (const string& str) - { - string temp = str; - -#ifndef NOT_USE_CRY_STRING - temp.MakeUpper(); -#else - std::transform(temp.begin(), temp.end(), temp.begin(), toUpperAscii); // STL MakeLower -#endif - - return temp; - } - - // searches and returns the pointer to the extension of the given file - /*! - \param szFileName source filename to search - // This function is Unicode agnostic and locale agnostic. - */ - inline const char* FindExtension(const char* szFileName) - { - const char* szEnd = szFileName + (int)strlen(szFileName); - for (const char* p = szEnd - 1; p >= szFileName; --p) - { - if (*p == '.') - { - return p + 1; - } - } - - return szEnd; - } - - // searches and returns the pointer to the file name in the given file path - /*! - \param szFilePath source path to search - */ - inline const char* FindFileNameInPath(const char* szFilePath) - { - for (const char* p = szFilePath + (int)strlen(szFilePath) - 1; p >= szFilePath; --p) - { - if (*p == '\\' || *p == '/') - { - return p + 1; - } - } - return szFilePath; - } - - // works like strstr, but is case-insensitive - /*! - \param szString the source string - \param szSubstring the sub-string to look for - */ - inline const char* stristr(const char* szString, const char* szSubstring) - { - int nSuperstringLength = (int)strlen(szString); - int nSubstringLength = (int)strlen(szSubstring); - - for (int nSubstringPos = 0; nSubstringPos <= nSuperstringLength - nSubstringLength; ++nSubstringPos) - { - if (_strnicmp(szString + nSubstringPos, szSubstring, nSubstringLength) == 0) - { - return szString + nSubstringPos; - } - } - return nullptr; - } - - -#ifndef NOT_USE_CRY_STRING - - /* - \param strPath the path to "unify" - */ - inline void UnifyFilePath(stack_string& strPath) - { - strPath.replace('\\', '/'); - strPath.MakeLower(); - } - - template - inline void UnifyFilePath(CryStackStringT& strPath) - { - strPath.replace('\\', '/'); - strPath.MakeLower(); - } - - /// Replaces backslashes with forward slashes and transforms string to lowercase. - /*! - \param strPath the path to "unify" - */ - inline void UnifyFilePath(string& strPath) - { - strPath.replace('\\', '/'); - strPath.MakeLower(); - } - -#endif - - // converts the number to a string - /* - \param nNumber an unsigned number - \return the unsigned number as a string - */ - inline string ToString(unsigned nNumber) - { - char szNumber[16]; - sprintf_s(szNumber, "%u", nNumber); - return szNumber; - } - - /// Converts the number to a string. - /*! - \param nNumber an signed integer - \return the signed integer as a string - */ - inline string ToString(signed int nNumber) - { - char szNumber[16]; - sprintf_s(szNumber, "%d", nNumber); - return szNumber; - } - - /// Converts the floating point number to a string. - /*! - \param nNumber a floating point number - \return the floating point number as a string - */ - inline string ToString(float nNumber) - { - char szNumber[128]; - sprintf_s(szNumber, "%f", nNumber); - return szNumber; - } - - /// Converts the boolean value to a string ("0" or "1"). - /*! - \param nNumber an unsigned number - \return the bool as a string (either "1" or "0") - */ - inline string ToString(bool nNumber) - { - char szNumber[4]; - sprintf_s(szNumber, "%i", (int)nNumber); - return szNumber; - } - -#ifdef CRYINCLUDE_CRYCOMMON_CRY_MATRIX44_H - /// Converts a Matrix44 to a string. - /*! - \param m A matrix of type Matrix44 - \return the matrix in the format {0,0,0,0}{0,0,0,0}{0,0,0,0}{0,0,0,0} - */ - inline string ToString(const Matrix44& m) - { - char szBuf[0x200]; - sprintf_s(szBuf, "{%g,%g,%g,%g}{%g,%g,%g,%g}{%g,%g,%g,%g}{%g,%g,%g,%g}", - m(0, 0), m(0, 1), m(0, 2), m(0, 3), - m(1, 0), m(1, 1), m(1, 2), m(1, 3), - m(2, 0), m(2, 1), m(2, 2), m(2, 3), - m(3, 0), m(3, 1), m(3, 2), m(3, 3)); - return szBuf; - } -#endif - -#ifdef CRYINCLUDE_CRYCOMMON_CRY_QUAT_H - /// Converts a CryQuat to a string. - /*! - \param m A quaternion of type CryQuat - \return the quaternion in the format {0,{0,0,0,0}} - */ - inline string ToString (const CryQuat& q) - { - char szBuf[0x100]; - sprintf_s(szBuf, "{%g,{%g,%g,%g}}", q.w, q.v.x, q.v.y, q.v.z); - return szBuf; - } -#endif - -#ifdef CRYINCLUDE_CRYCOMMON_CRY_VECTOR3_H - /// Converts a Vec3 to a string. - /*! - \param m A vector of type Vec3 - \return the vector in the format {0,0,0} - */ - inline string ToString (const Vec3& v) - { - char szBuf[0x80]; - sprintf_s(szBuf, "{%g,%g,%g}", v.x, v.y, v.z); - return szBuf; - } -#endif - - /// This function only exists to allow ToString to compile if it is ever used with an unsupported type. - /*! - \param unknownType - \return a string that reads "unknown" - */ - template - inline string ToString(T& unknownType) - { - char szValue[8]; - sprintf_s(szValue, "%s", "unknown"); - return szValue; - } - - // does the same as strstr, but the szString is allowed to be no more than the specified size - /*! - \param szString the source string - \param szSubstring the sub-string to look for - \param nSuperstringLength the maximum size of szString - */ - inline const char* strnstr(const char* szString, const char* szSubstring, int nSuperstringLength) - { - int nSubstringLength = (int)strlen(szSubstring); - if (!nSubstringLength) - { - return szString; - } - - for (int nSubstringPos = 0; szString[nSubstringPos] && nSubstringPos < nSuperstringLength - nSubstringLength; ++nSubstringPos) - { - if (strncmp(szString + nSubstringPos, szSubstring, nSubstringLength) == 0) - { - return szString + nSubstringPos; - } - } - return nullptr; - } - - - // Finds the string in the array of strings. - // Returns its 0-based index or -1 if not found. - // Comparison is case-sensitive. - // The string array end is demarked by the NULL value. - // This function is Unicode agnostic (but no Unicode collation is performed for equality test) and locale agnostic. - inline int findString(const char* szString, const char* arrStringList[]) - { - for (const char** p = arrStringList; *p; ++p) - { - if (0 == strcmp(*p, szString)) - { - return (int)(p - arrStringList); - } - } - return -1; // string was not found - } - - /// Finds the string in the array of strings. - /*! - \param szString the string to look for - \param arrStringList array of strings - \remark comparison is case-sensitive - \remark The string array end is delimited by the nullptr value - \return its 0-based index or -1 if not found - */ - inline int FindString(const char* szString, const char* arrStringList[]) - { - for (const char** p = arrStringList; *p; ++p) - { - if (0 == strcmp(*p, szString)) - { - return (int)(p - arrStringList); - } - } - return -1; // string was not found - } - - /// Used for printing out sets of objects of string type. - /*! - \remark just forms the comma-delimited string where each string in the set is presented as a formatted substring - \param setStrings set of strings to print - \return a formatted string - */ - inline string ToString(const std::set& setStrings) - { - string strResult; - if (!setStrings.empty()) - { - strResult += "{"; - for (std::set::const_iterator it = setStrings.begin(); it != setStrings.end(); ++it) - { - if (it != setStrings.begin()) - { - strResult += ", "; - } - strResult += "\""; - strResult += *it; - strResult += "\""; - } - strResult += "}"; - } - return strResult; - } - - // Cuts the string and adds leading ... if it's longer than specified maximum length. - // This function is ASCII-only and locale agnostic. - inline string cutString(const string& strPath, unsigned nMaxLength) - { - if (strPath.length() > nMaxLength && nMaxLength > 3) - { - return string("...") + string(strPath.c_str() + strPath.length() - (nMaxLength - 3)); - } - else - { - return strPath; - } - } - - /// Cuts the string and adds leading ... if it's longer than specified maximum length. - /*! - \param str the string to cut - \param nMaxLength the allowed length of the string before its cut. - \return a shortened string starting in ellipses or the source string if it's smaller than nMaxLength - */ - inline string CutString(const string& str, unsigned nMaxLength) - { - if (str.length() > nMaxLength && nMaxLength > 3) - { - return string("...") + string(str.c_str() + str.length() - (nMaxLength - 3)); - } - else - { - return str; - } - } - - /// Converts the given set of NUMBERS into the string. - /*! - \param setMtlms A numeric set to convert into a string - \param szFormat - \param szPostfix - */ - template - string ToString(const std::set& setMtls, const char* szFormat, const char* szPostfix = "") - { - string strResult; - char szBuffer[64]; - if (!setMtls.empty()) - { - strResult += strResult.empty() ? "(" : " ("; - for (typename std::set::const_iterator it = setMtls.begin(); it != setMtls.end(); ) - { - if (it != setMtls.begin()) - { - strResult += ", "; - } - sprintf_s(szBuffer, szFormat, *it); - strResult += szBuffer; - T nStart = *it; - - ++it; - - if (it != setMtls.end() && *it == nStart + 1) - { - T nPrev = *it; - // we've got a region - while (++it != setMtls.end() && *it == nPrev + 1) - { - nPrev = *it; - } - if (nPrev == nStart + 1) - { - // special case - range of length 1 - strResult += ","; - } - else - { - strResult += ".."; - } - sprintf_s(szBuffer, szFormat, nPrev); - strResult += szBuffer; - } - } - strResult += ")"; - } - return szPostfix[0] ? strResult + szPostfix : strResult; - } - - - // Attempts to find a matching wildcard in a string. - /*! - \param szString source string - \param szWildcard the wildcard, supports * and ? - // returns true if the string matches the wildcard - // Note: ANSI input is not supported, ASCII is fine since it's a subset of UTF-8. - */ - inline bool MatchWildcard(const char* szString, const char* szWildcard) - { - return CryStringUtils_Internal::MatchesWildcards_Tpl(szString, szWildcard); - } - - // Returns true if the string matches the wildcard. - // Supports wildcard ? (matches one code-point) and * (matches zero or more code-points). - // This function is Unicode aware and uses the "C" locale for case comparison. - // Note: ANSI input is not supported, ASCII is fine since it's a subset of UTF-8. - inline bool MatchWildcardIgnoreCase(const char* szString, const char* szWildcard) - { - return CryStringUtils_Internal::MatchesWildcards_Tpl(szString, szWildcard); - } - -#if !defined(RESOURCE_COMPILER) - - // calculates a hash value for a given string - inline uint32 CalculateHash(const char* str) - { - return CCrc32::Compute(str); - } - - // calculates a hash value for the lower case version of a given string - inline uint32 CalculateHashLowerCase(const char* str) - { - return CCrc32::ComputeLowercase(str); - } - - // This function is Unicode agnostic and locale agnostic. - inline uint32 HashStringSeed(const char* string, const uint32 seed) - { - // A string hash taken from the FRD/Crysis2 (game) code with low probability of clashes - // Recommend you use the CRY_DEFAULT_HASH_SEED (see HashString) - const char* p; - uint32 hash = seed; - for (p = string; *p != '\0'; p++) - { - hash += *p; - hash += (hash << 10); - hash ^= (hash >> 6); - } - hash += (hash << 3); - hash ^= (hash >> 11); - hash += (hash << 15); - return hash; - } - - // This function is ASCII-only and uses the standard "C" locale for case conversion. - inline uint32 HashStringLowerSeed(const char* string, const uint32 seed) - { - // computes the hash of 'string' converted to lower case - // also see the comment in HashStringSeed - const char* p; - uint32 hash = seed; - for (p = string; *p != '\0'; p++) - { - hash += toLowerAscii(*p); - hash += (hash << 10); - hash ^= (hash >> 6); - } - hash += (hash << 3); - hash ^= (hash >> 11); - hash += (hash << 15); - return hash; - } - - // This function is Unicode agnostic and locale agnostic. - inline uint32 HashString(const char* string) - { - return HashStringSeed(string, CRY_DEFAULT_HASH_SEED); - } - - // This function is ASCII-only and uses the standard "C" locale for case conversion. - inline uint32 HashStringLower(const char* string) - { - return HashStringLowerSeed(string, CRY_DEFAULT_HASH_SEED); - } -#endif - - // converts all chars to lower case - avoids memory allocation - /*! - \param str Reference to string to convert into lowercase. - */ - inline void ToLowerInplace(string& str) - { -#ifndef NOT_USE_CRY_STRING - str.MakeLower(); -#else - std::transform(str.begin(), str.end(), str.begin(), toLowerAscii); // STL MakeLower -#endif - } - - /// Converts all chars to lower case - avoids memory allocation - /*! - \param str Reference to string to convert into lowercase. - */ - inline void ToLowerInplace(char* str) - { - if (str == nullptr) - { - return; - } - - for (char* s = str; *s != '\0'; s++) - { - *s = toLowerAscii(*s); - } - } - - -#ifndef NOT_USE_CRY_STRING - - // Converts a wide string (can be UTF-16 or UTF-32 depending on platform) to UTF-8. - // This function is Unicode aware and locale agnostic. - /// Converts a wide string to a UTF8 string. - /*! - \param str The wide string to convert. - \return dstr The wide string converted into the specified UTF8 type. - */ - template - inline void WStrToUTF8(const wchar_t* str, T& dstr) - { - string utf8; - Unicode::Convert(utf8, str); - - // Note: This function expects T to have assign(ptr, len) function - dstr.assign(utf8.c_str(), utf8.length()); - } - - // Converts a wide string (can be UTF-16 or UTF-32 depending on platform) to UTF-8. - // This function is Unicode aware and locale agnostic. - /// Converts a wide string to UTF8. - /*! - \param str The wchar_t string to convert. - \return The UTF8 string. - */ - inline string WStrToUTF8(const wchar_t* str) - { - return Unicode::Convert(str); - } - - /// Converts a UTF8 string to a wide string. - /*! - \param str The UTF8 string to convert. - \return dstr The UTF8 string converted into the specified type. - */ - template - inline void UTF8ToWStr(const char* str, T& dstr) - { - wstring wide; - Unicode::Convert(wide, str); - - // Note: This function expects T to have assign(ptr, len) function - dstr.assign(wide.c_str(), wide.length()); - } - - // Converts an UTF-8 string to wide string (can be UTF-16 or UTF-32 depending on platform). - // This function is Unicode aware and locale agnostic. - /*! - \param str The UTF8 string to convert. - \return str as converted to wstring. - */ - inline wstring UTF8ToWStr(const char* str) - { - return Unicode::Convert(str); - } - - /// Converts a string to a wide character string - /*! - \param str Source string. - \param dstr Destination wstring. - */ - inline void StrToWstr(const char* str, wstring& dstr) - { - CryStackStringT tmp; - tmp.resize(strlen(str)); - tmp.clear(); - - while (const wchar_t c = (wchar_t)(*str++)) - { - tmp.append(1, c); - } - - dstr.assign(tmp.data(), tmp.length()); - } - -#endif // NOT_USE_CRY_STRING - - /// The type used to parse a yes/no string -#if defined(_DISALLOW_ENUM_CLASS) - enum YesNoType -#else - enum class YesNoType -#endif - { - Yes, - No, - Invalid - }; - - // parse the yes/no string - /*! - \param szString any of the following strings: yes, enable, true, 1, no, disable, false, 0 - \return YesNoType::Yes if szString is yes/enable/true/1, YesNoType::No if szString is no, disable, false, 0 and YesNoType::Invalid if the string is not one of the expected values. - */ - inline YesNoType ToYesNoType(const char* szString) - { - if (!_stricmp(szString, "yes") - || !_stricmp(szString, "enable") - || !_stricmp(szString, "true") - || !_stricmp(szString, "1")) -#if defined(_DISALLOW_ENUM_CLASS) - { - return Yes; - } -#else - { - return YesNoType::Yes; - } -#endif - if (!_stricmp(szString, "no") - || !_stricmp(szString, "disable") - || !_stricmp(szString, "false") - || !_stricmp(szString, "0")) -#if defined(_DISALLOW_ENUM_CLASS) - { - return No; - } -#else - { - return YesNoType::No; - } -#endif - -#if defined(_DISALLOW_ENUM_CLASS) - return Invalid; -#else - return YesNoType::Invalid; -#endif - } - - /// Verifies if the filename provided only contains the accepted characters. - /*! - \param fileName the filename to verify - \return true if the filename only contains alphanumeric values and/or dot, dash and underscores. - */ - inline bool IsValidFileName(const char* fileName) - { - size_t i = 0; - for (;; ) - { - const char c = fileName[i++]; - if (c == 0) - { - return true; - } - if (!((c >= '0' && c <= '9') - || (c >= 'A' && c <= 'Z') - || (c >= 'a' && c <= 'z') - || c == '.' || c == '-' || c == '_')) - { - return false; - } - } - } - - - /************************************************************************** - *void _makepath() - build path name from components - * - *Purpose: - * create a path name from its individual components - * - *Entry: - * char *path - pointer to buffer for constructed path - * char *drive - pointer to drive component, may or may not contain trailing ':' - * char *dir - pointer to subdirectory component, may or may not include leading and/or trailing '/' or '\' characters - * char *fname - pointer to file base name component - * char *ext - pointer to extension component, may or may not contain a leading '.'. - * - *Exit: - * path - pointer to constructed path name - * - *******************************************************************************/ - ILINE void portable_makepath(char path[_MAX_PATH], const char* drive, const char* dir, const char* fname, const char* ext) - { - const char* p; - - /* we assume that the arguments are in the following form (although we - * do not diagnose invalid arguments or illegal filenames (such as - * names longer than 8.3 or with illegal characters in them) - * - * drive: - * A ; or - * A: - * dir: - * \top\next\last\ ; or - * /top/next/last/ ; or - * either of the above forms with either/both the leading - * and trailing / or \ removed. Mixed use of '/' and '\' is - * also tolerated - * fname: - * any valid file name - * ext: - * any valid extension (none if empty or null ) - */ - - /* copy drive */ - - if (drive && *drive) - { - *path++ = *drive; - *path++ = (':'); - } - - /* copy dir */ - - if ((p = dir) && *p) - { - do - { - *path++ = *p++; - } while (*p); - if (*(p - 1) != '/' && *(p - 1) != ('\\')) - { - *path++ = ('\\'); - } - } - - /* copy fname */ - - if (p = fname) - { - while (*p) - { - *path++ = *p++; - } - } - - /* copy ext, including 0-terminator - check to see if a '.' needs - * to be inserted. - */ - - if (p = ext) - { - if (*p && *p != ('.')) - { - *path++ = ('.'); - } - while (*path++ = *p++) - { - ; - } - } - else - { - /* better add the 0-terminator */ - *path = ('\0'); - } - } - - /// Create a path name from its individual components. - /*! - \param char *path pointer to buffer for constructed path - \param char *drive pointer to drive component, may or may not contain trailing ':' - \param char *dir pointer to subdirectory component, may or may not include leading and/or trailing '/' or '\' characters - \param char *fname pointer to file base name component - \param char *ext pointer to extension component, may or may not contain a leading '.'. - \return path pointer to constructed path name - */ - inline void MakePath(char path[_MAX_PATH], const char* drive, const char* dir, const char* fname, const char* ext) - { - const char* p; - - // we assume that the arguments are in the following form (although we - // do not diagnose invalid arguments or illegal filenames (such as - // names longer than 8.3 or with illegal characters in them) - // - // drive: - // A ; or - // A: - // dir: - // \top\next\last\ ; or - // /top/next/last/ ; or - // either of the above forms with either/both the leading - // and trailing / or \ removed. Mixed use of '/' and '\' is - // also tolerated - // fname: - // any valid file name - // ext: - // any valid extension (none if empty or null ) - // - - // copy drive - if (drive && *drive) - { - *path++ = *drive; - *path++ = (':'); - } - - // copy dir - if ((p = dir) && *p) - { - do - { - *path++ = *p++; - } while (*p); - if (*(p - 1) != '/' && *(p - 1) != ('\\')) - { - *path++ = ('\\'); - } - } - - // copy fname - if (p = fname) - { - while (*p) - { - *path++ = *p++; - } - } - - // copy ext, including 0-terminator - check to see if a '.' needs - // to be inserted. - if (p = ext) - { - if (*p && *p != ('.')) - { - *path++ = ('.'); - } - while (*path++ = *p++) - { - ; - } - } - else - { - // better add the 0-terminator - *path = ('\0'); - } - } - - // Copies characters from a string. - /*! - \param destination Pointer to the destination array where the content is to be copied. - \param source C string to be copied. - \param num Maximum number of characters to be copied from source. - \remark Parameter order is the same as strncpy; Copies only up to num characters from source to destination. - \return true if entirety of source was copied into destination. - */ - inline bool strncpy(char* destination, const char* source, size_t num) - { - bool reply = false; - -#if CRY_STRING_ASSERTS && !defined(RESOURCE_COMPILER) - CRY_ASSERT(destination); - CRY_ASSERT(source); -#endif - - if (num) - { - size_t i; - for (i = 0; source[i] && (i + 1) < num; ++i) - { - destination[i] = source[i]; - } - destination[i] = '\0'; - reply = (source[i] == '\0'); - } - -#if CRY_STRING_ASSERTS && !defined(RESOURCE_COMPILER) - CRY_ASSERT_MESSAGE(reply, string().Format("String '%s' is too big to fit into a buffer of length %u", source, (unsigned int)num)); -#endif - return reply; - } - - // Copies wide characters from a wide string. - /*! - \param destination Pointer to the destination wchar_t array where the content is to be copied. - \param source C wide string to be copied. - \param num Maximum number of characters to be copied from source. - \remark Parameter order is the same as strncpy; Copies only up to num characters from source to destination. - \return true if entirety of source was copied into destination. - */ - inline bool wstrncpy(wchar_t* destination, const wchar_t* source, size_t bufferLength) - { - bool reply = false; - -#if CRY_STRING_ASSERTS && !defined(RESOURCE_COMPILER) - CRY_ASSERT(destination); - CRY_ASSERT(source); -#endif - - if (bufferLength) - { - size_t i; - for (i = 0; source[i] && (i + 1) < bufferLength; ++i) - { - destination[i] = source[i]; - } - destination[i] = '\0'; - reply = (source[i] == '\0'); - } - -#if CRY_STRING_ASSERTS && !defined(RESOURCE_COMPILER) - CRY_ASSERT_MESSAGE(reply, string().Format("String '%ls' is too big to fit into a buffer of length %u", source, (unsigned int)bufferLength)); -#endif - return reply; - } - - // Copies a C string into a destination buffer up to a specified delimiter or null terminator. - /*! - \param destination Pointer to a buffer where the resulting C-string is stored. - \param source C string to be copied. - \param num Maximum number of characters to be copied from source. - \param delimiter Delimiter character up to which the string will be copied. - \return Number of bytes written into destination (including null terminator) or 0 if delimiter is not found within the first num bytes of source. - */ - inline size_t CopyStringUntilFindChar(char* destination, const char* source, size_t num, char delimiter) - { - size_t reply = 0; - -#if CRY_STRING_ASSERTS && !defined(RESOURCE_COMPILER) - CRY_ASSERT(destination); - CRY_ASSERT(source); -#endif - - if (num) - { - size_t i; - for (i = 0; source[i] && source[i] != delimiter && (i + 1) < num; ++i) - { - destination[i] = source[i]; - } - destination[i] = '\0'; - reply = (source[i] == delimiter) ? (i + 1) : 0; - } - - return reply; - } -} // namespace CryStringUtils - -#endif // CRYINCLUDE_CRYCOMMON_STRINGUTILS_H diff --git a/Code/Legacy/CryCommon/TypeInfo_decl.h b/Code/Legacy/CryCommon/TypeInfo_decl.h index f763ec6ebb..28a0b370a9 100644 --- a/Code/Legacy/CryCommon/TypeInfo_decl.h +++ b/Code/Legacy/CryCommon/TypeInfo_decl.h @@ -15,6 +15,7 @@ #pragma once #include +#include ////////////////////////////////////////////////////////////////////////// // Meta-type support. @@ -55,7 +56,7 @@ inline const CTypeInfo& TypeInfo(const T* t) // Type info declaration, with additional prototypes for string conversions. #define BASIC_TYPE_INFO(Type) \ - string ToString(Type const & val); \ + AZStd::string ToString(Type const & val); \ bool FromString(Type & val, const char* s); \ DECLARE_TYPE_INFO(Type) @@ -105,7 +106,7 @@ BASIC_TYPE_INFO(double) BASIC_TYPE_INFO(AZ::Uuid) -DECLARE_TYPE_INFO(string) +DECLARE_TYPE_INFO(AZStd::string) // All pointers share same TypeInfo. const CTypeInfo&PtrTypeInfo(); diff --git a/Code/Legacy/CryCommon/UnicodeBinding.h b/Code/Legacy/CryCommon/UnicodeBinding.h index 6bfa846035..aaefcf0f55 100644 --- a/Code/Legacy/CryCommon/UnicodeBinding.h +++ b/Code/Legacy/CryCommon/UnicodeBinding.h @@ -12,7 +12,6 @@ // // (At least) the following string types can be bound with these helper functions: // Types Input Output Null-Terminator -// CryStringT, (::string, ::wstring): yes yes implied by type (also Stack and Fixed variants) // std::basic_string, std::string, std::wstring: yes yes implied by type // QString: yes yes implied by type // std::vector, std::list, std::deque: yes yes not present @@ -56,18 +55,14 @@ // Forward declare the supported types. // Before actually instantiating a binding however, you need to have the full definition included. // Also, this allows us to work with QChar/QString as declared names without a dependency on Qt. -template -class CryStackStringT; -template -class CryFixedStringT; -template -class CryFixedWStringT; -template -class CryStringLocalT; -template -class CryStringT; +namespace AZStd +{ + template + class basic_fixed_string; +} class QChar; class QString; + namespace Unicode { namespace Detail @@ -253,36 +248,15 @@ namespace Unicode static const bool isValid = SValidChar::value; static const EBind value = isValid ? eBind_Iterators : eBind_Impossible; }; - template - struct SBindObject, InferEncoding> - { - typedef typename add_const::type CharType; - static const bool isValid = SValidChar::value; - static const EBind value = isValid ? eBind_Data : eBind_Impossible; - }; - template - struct SBindObject, InferEncoding> - { - typedef typename add_const::type CharType; - static const bool isValid = SValidChar::value; - static const EBind value = isValid ? eBind_Data : eBind_Impossible; - }; template - struct SBindObject, InferEncoding> + struct SBindObject, InferEncoding> { typedef typename add_const::type CharType; static const bool isValid = SValidChar::value; static const EBind value = isValid ? eBind_Data : eBind_Impossible; }; template - struct SBindObject, InferEncoding> - { - typedef char CharType; - static const bool isValid = SValidChar::value; - static const EBind value = isValid ? eBind_Data : eBind_Impossible; - }; - template - struct SBindObject, InferEncoding> + struct SBindObject, InferEncoding> { typedef wchar_t CharType; static const bool isValid = SValidChar::value; @@ -348,22 +322,8 @@ namespace Unicode static const bool isValid = SValidChar::value; static const EBind value = isValid ? eBind_Iterators : eBind_Impossible; }; - template - struct SBindOutput, InferEncoding> - { - typedef T CharType; - static const bool isValid = SValidChar::value; - static const EBind value = isValid ? eBind_Data : eBind_Impossible; - }; - template - struct SBindOutput, InferEncoding> - { - typedef T CharType; - static const bool isValid = SValidChar::value; - static const EBind value = isValid ? eBind_Data : eBind_Impossible; - }; template - struct SBindOutput, InferEncoding> + struct SBindOutput, InferEncoding> { typedef T CharType; static const bool isValid = SValidChar::value; diff --git a/Code/Legacy/CryCommon/WinBase.cpp b/Code/Legacy/CryCommon/WinBase.cpp index 3208da9d68..a60dbdf00b 100644 --- a/Code/Legacy/CryCommon/WinBase.cpp +++ b/Code/Legacy/CryCommon/WinBase.cpp @@ -486,7 +486,7 @@ void _splitpath(const char* inpath, char* drv, char* dir, char* fname, char* ext drv[0] = 0; } - typedef CryStackStringT path_stack_string; + typedef AZStd::fixed_string path_stack_string; const path_stack_string inPath(inpath); string::size_type s = inPath.rfind('/', inPath.size());//position of last / diff --git a/Code/Legacy/CryCommon/crycommon_files.cmake b/Code/Legacy/CryCommon/crycommon_files.cmake index 0392f11c89..63c5b49513 100644 --- a/Code/Legacy/CryCommon/crycommon_files.cmake +++ b/Code/Legacy/CryCommon/crycommon_files.cmake @@ -78,7 +78,6 @@ set(FILES CryCrc32.h CryCustomTypes.h CryFile.h - CryFixedString.h CryHeaders.h CryHeaders_info.cpp CryListenerSet.h @@ -87,7 +86,6 @@ set(FILES CryPath.h CryPodArray.h CrySizer.h - CryString.h CrySystemBus.h CryThread.h CryThreadImpl.h @@ -111,7 +109,6 @@ set(FILES SimpleSerialize.h smartptr.h StlUtils.h - StringUtils.h Synchronization.h Tarray.h Timer.h diff --git a/Code/Legacy/CryCommon/platform.h b/Code/Legacy/CryCommon/platform.h index b3846b88dd..60edf10de9 100644 --- a/Code/Legacy/CryCommon/platform.h +++ b/Code/Legacy/CryCommon/platform.h @@ -689,9 +689,6 @@ void SetFlags(T& dest, U flags, bool b) #include AZ_RESTRICTED_FILE(platform_h) #endif -// Platform wrappers must be included before CryString.h -# include "CryString.h" - // Include support for meta-type data. #include "TypeInfo_decl.h" @@ -701,12 +698,6 @@ void SetFlags(T& dest, U flags, bool b) bool CrySetFileAttributes(const char* lpFileName, uint32 dwFileAttributes); threadID CryGetCurrentThreadId(); -#if !defined(NOT_USE_CRY_STRING) -// Fixed-Sized (stack based string) -// put after the platform wrappers because of missing wcsicmp/wcsnicmp functions - #include "CryFixedString.h" -#endif - // need this in a common header file and any other file would be too misleading enum ETriState { diff --git a/Code/Legacy/CryCommon/platform_impl.cpp b/Code/Legacy/CryCommon/platform_impl.cpp index a677ba30b6..6ec8df0365 100644 --- a/Code/Legacy/CryCommon/platform_impl.cpp +++ b/Code/Legacy/CryCommon/platform_impl.cpp @@ -8,7 +8,6 @@ #include -#include #include #include #include @@ -248,10 +247,7 @@ int CryMessageBox([[maybe_unused]] const char* lpText, [[maybe_unused]] const ch return 0; } #endif - wstring wideText, wideCaption; - Unicode::Convert(wideText, lpText); - Unicode::Convert(wideCaption, lpCaption); - return MessageBoxW(NULL, wideText.c_str(), wideCaption.c_str(), uType); + return MessageBox(NULL, lpText, lpCaption, uType); #else return 0; #endif diff --git a/Code/Legacy/CrySystem/CmdLine.cpp b/Code/Legacy/CrySystem/CmdLine.cpp index cb805b6990..50b8b2c092 100644 --- a/Code/Legacy/CrySystem/CmdLine.cpp +++ b/Code/Legacy/CrySystem/CmdLine.cpp @@ -11,7 +11,7 @@ #include "CmdLine.h" -void CCmdLine::PushCommand(const string& sCommand, const string& sParameter) +void CCmdLine::PushCommand(const AZStd::string& sCommand, const AZStd::string& sParameter) { if (sCommand.empty()) { @@ -47,7 +47,7 @@ CCmdLine::CCmdLine(const char* commandLine) char* src = (char*)commandLine; - string command, parameter; + AZStd::string command, parameter; for (;; ) { @@ -56,12 +56,12 @@ CCmdLine::CCmdLine(const char* commandLine) break; } - string arg = Next(src); + AZStd::string arg = Next(src); if (m_args.empty()) { // this is the filename, convert backslash to forward slash - arg.replace('\\', '/'); + AZ::StringFunc::Replace(arg, '\\', '/'); m_args.push_back(CCmdLineArg("filename", arg.c_str(), eCLAT_Executable)); } else @@ -90,7 +90,7 @@ CCmdLine::CCmdLine(const char* commandLine) } else { - parameter += string(" ") + arg; + parameter += AZStd::string(" ") + arg; } } } @@ -151,7 +151,7 @@ const ICmdLineArg* CCmdLine::FindArg(const ECmdLineArgType ArgType, const char* } -string CCmdLine::Next(char*& src) +AZStd::string CCmdLine::Next(char*& src) { char ch = 0; char* org = src; @@ -170,7 +170,7 @@ string CCmdLine::Next(char*& src) ; } - return string(org, src - 1); + return AZStd::string(org, src - 1); case '[': org = src; @@ -178,7 +178,7 @@ string CCmdLine::Next(char*& src) { ; } - return string(org, src - 1); + return AZStd::string(org, src - 1); case ' ': ch = *src++; @@ -190,12 +190,12 @@ string CCmdLine::Next(char*& src) ; } - return string(org, src); + return AZStd::string(org, src); } ch = *src++; } - return string(); + return AZStd::string(); } diff --git a/Code/Legacy/CrySystem/DebugCallStack.cpp b/Code/Legacy/CrySystem/DebugCallStack.cpp index 576c3ee9fb..1914e82515 100644 --- a/Code/Legacy/CrySystem/DebugCallStack.cpp +++ b/Code/Legacy/CrySystem/DebugCallStack.cpp @@ -430,18 +430,18 @@ void DebugCallStack::LogExceptionInfo(EXCEPTION_POINTERS* pex) { const char* const szMessage = m_bIsFatalError ? s_szFatalErrorCode : m_szBugMessage; excName = szMessage; - cry_strcpy(excCode, szMessage); - cry_strcpy(excAddr, ""); - cry_strcpy(desc, ""); - cry_strcpy(m_excModule, ""); - cry_strcpy(excDesc, szMessage); + azstrcpy(excCode, szMessage); + azstrcpy(excAddr, ""); + azstrcpy(desc, ""); + azstrcpy(m_excModule, ""); + azstrcpy(excDesc, szMessage); } else { sprintf_s(excAddr, "0x%04X:0x%p", pex->ContextRecord->SegCs, pex->ExceptionRecord->ExceptionAddress); sprintf_s(excCode, "0x%08X", pex->ExceptionRecord->ExceptionCode); excName = TranslateExceptionCode(pex->ExceptionRecord->ExceptionCode); - cry_strcpy(desc, ""); + azstrcpy(desc, ""); sprintf_s(excDesc, "%s\r\n%s", excName, desc); @@ -471,9 +471,9 @@ void DebugCallStack::LogExceptionInfo(EXCEPTION_POINTERS* pex) WriteLineToLog("Exception Description: %s", desc); - cry_strcpy(m_excDesc, excDesc); - cry_strcpy(m_excAddr, excAddr); - cry_strcpy(m_excCode, excCode); + azstrcpy(m_excDesc, excDesc); + azstrcpy(m_excAddr, excAddr); + azstrcpy(m_excCode, excCode); char errs[32768]; @@ -499,7 +499,7 @@ void DebugCallStack::LogExceptionInfo(EXCEPTION_POINTERS* pex) dumpCallStack(funcs); // Fill call stack. char str[s_iCallStackSize]; - cry_strcpy(str, ""); + azstrcpy(str, ""); for (unsigned int i = 0; i < funcs.size(); i++) { char temp[s_iCallStackSize]; @@ -509,7 +509,7 @@ void DebugCallStack::LogExceptionInfo(EXCEPTION_POINTERS* pex) cry_strcat(errs, temp); cry_strcat(errs, "\n"); } - cry_strcpy(m_excCallstack, str); + azstrcpy(m_excCallstack, str); } cry_strcat(errorString, errs); diff --git a/Code/Legacy/CrySystem/LevelSystem/LevelSystem.cpp b/Code/Legacy/CrySystem/LevelSystem/LevelSystem.cpp index e8cc4d484c..83db5e4a29 100644 --- a/Code/Legacy/CrySystem/LevelSystem/LevelSystem.cpp +++ b/Code/Legacy/CrySystem/LevelSystem/LevelSystem.cpp @@ -567,7 +567,7 @@ ILevel* CLevelSystem::LoadLevelInternal(const char* _levelName) INDENT_LOG_DURING_SCOPE(); char levelName[256]; - cry_strcpy(levelName, _levelName); + azstrcpy(levelName, _levelName); // Not remove a scope!!! { diff --git a/Code/Legacy/CrySystem/LocalizedStringManager.cpp b/Code/Legacy/CrySystem/LocalizedStringManager.cpp index ce39f08480..fe0fd9cb22 100644 --- a/Code/Legacy/CrySystem/LocalizedStringManager.cpp +++ b/Code/Legacy/CrySystem/LocalizedStringManager.cpp @@ -528,7 +528,7 @@ static void CopyLowercase(char* dst, size_t dstSize, const char* src, size_t src } ////////////////////////////////////////////////////////////////////////// -static void ReplaceEndOfLine(CryFixedStringT& s) +static void ReplaceEndOfLine(AZStd::fixed_string& s) { const string oldSubstr("\\n"); const string newSubstr(" \n"); @@ -536,7 +536,7 @@ static void ReplaceEndOfLine(CryFixedStringT::npos) + if (pos == AZStd::fixed_string::npos) { return; } @@ -955,7 +955,7 @@ bool CLocalizedStringsManager::DoLoadExcelXmlSpreadsheet(const char* sFileName, bool bFirstRow = true; - CryFixedStringT sTmp; + AZStd::fixed_string sTmp; // lower case event name char szLowerCaseEvent[128]; @@ -1609,7 +1609,7 @@ bool CLocalizedStringsManager::DoLoadAGSXmlDocument(const char* sFileName, uint8 { continue; } - AzFramework::StringFunc::Replace(textValue, "\\n", " \n"); // carried over from helper func ReplaceEndOfLine(CryFixedStringT<>& s) + AzFramework::StringFunc::Replace(textValue, "\\n", " \n"); if (keyString[0] == '@') { AzFramework::StringFunc::LChop(keyString, 1); @@ -2536,7 +2536,7 @@ void CLocalizedStringsManager::LocalizeNumber(int number, string& outNumberStrin int n = abs(number); string separator; - CryFixedStringT<64> tmp; + AZStd::fixed_string<64> tmp; LocalizeString_ch("@ui_thousand_separator", separator); while (n > 0) { @@ -2565,7 +2565,7 @@ void CLocalizedStringsManager::LocalizeNumber_Decimal(float number, int decimals { if (number == 0.0f) { - CryFixedStringT<64> tmp; + AZStd::fixed_string<64> tmp; tmp.Format("%.*f", decimals, number); outNumberString.assign(tmp.c_str()); return; @@ -2585,7 +2585,7 @@ void CLocalizedStringsManager::LocalizeNumber_Decimal(float number, int decimals int decimalsAsInt = aznumeric_cast(int_round(decimalsOnly * pow(10.0f, decimals))); - CryFixedStringT<64> tmp; + AZStd::fixed_string<64> tmp; tmp.Format("%s%s%0*d", intPart.c_str(), commaSeparator.c_str(), decimals, decimalsAsInt); outNumberString.assign(tmp.c_str()); @@ -2657,7 +2657,7 @@ void CLocalizedStringsManager::LocalizeTime(time_t t, bool bMakeLocalTime, bool if (len > 0) { // len includes terminating null! - CryFixedWStringT<256> tmpString; + AZStd::fixed_wstring<256> tmpString; tmpString.resize(len); ::GetTimeFormatW(lcID, flags, &systemTime, 0, (wchar_t*) tmpString.c_str(), len); Unicode::Convert(outTimeString, tmpString); @@ -2678,7 +2678,7 @@ void CLocalizedStringsManager::LocalizeDate(time_t t, bool bMakeLocalTime, bool UnixTimeToSystemTime(t, &systemTime); // len includes terminating null! - CryFixedWStringT<256> tmpString; + AZStd::fixed_wstring<256> tmpString; if (bIncludeWeekday) { diff --git a/Code/Legacy/CrySystem/Log.cpp b/Code/Legacy/CrySystem/Log.cpp index d2d8495063..2c7c307d50 100644 --- a/Code/Legacy/CrySystem/Log.cpp +++ b/Code/Legacy/CrySystem/Log.cpp @@ -509,7 +509,7 @@ void CLog::LogV(const ELogType type, [[maybe_unused]]int flags, const char* szFo stack_string s = szBuffer; s += "\t "; s += sAssetScope; - cry_strcpy(szBuffer, s.c_str()); + azstrcpy(szBuffer, s.c_str()); } } @@ -863,7 +863,7 @@ bool CLog::LogToMainThread(const char* szString, ELogType logType, bool bAdd, SL { // When logging from other thread then main, push all log strings to queue. SLogMsg msg; - cry_strcpy(msg.msg, szString); + azstrcpy(msg.msg, szString); msg.bAdd = bAdd; msg.destination = destination; msg.logType = logType; @@ -1286,7 +1286,7 @@ void CLog::CreateBackupFile() const string bakdest = PathUtil::Make(LOG_BACKUP_PATH, sFileWithoutExt + sBackupNameAttachment + "." + sExt); fileSystem->CreatePath(LOG_BACKUP_PATH); - cry_strcpy(m_sBackupFilename, bakdest.c_str()); + azstrcpy(m_sBackupFilename, bakdest.c_str()); // Remove any existing backup file with the same name first since the copy will fail otherwise. fileSystem->Remove(m_sBackupFilename); fileSystem->Copy(m_szFilename, bakdest); diff --git a/Code/Legacy/CrySystem/Log.h b/Code/Legacy/CrySystem/Log.h index 5b1956b12f..3c0fa98037 100644 --- a/Code/Legacy/CrySystem/Log.h +++ b/Code/Legacy/CrySystem/Log.h @@ -37,7 +37,7 @@ class CLog { public: typedef std::list Callbacks; - typedef CryStackStringT LogStringType; + typedef AZStd::fixed_string LogStringType; // constructor CLog(ISystem* pSystem); diff --git a/Code/Legacy/CrySystem/System.cpp b/Code/Legacy/CrySystem/System.cpp index 7fa7f7d2b0..bf4de8489d 100644 --- a/Code/Legacy/CrySystem/System.cpp +++ b/Code/Legacy/CrySystem/System.cpp @@ -1190,7 +1190,7 @@ void CSystem::WarningV(EValidatorModule module, EValidatorSeverity severity, int if (file && *file) { - CryFixedStringT fmt = szBuffer; + AZStd::fixed_string fmt = szBuffer; fmt += " [File="; fmt += file; fmt += "]"; diff --git a/Code/Legacy/CrySystem/SystemWin32.cpp b/Code/Legacy/CrySystem/SystemWin32.cpp index 2cc41adc08..943a540ae6 100644 --- a/Code/Legacy/CrySystem/SystemWin32.cpp +++ b/Code/Legacy/CrySystem/SystemWin32.cpp @@ -127,7 +127,7 @@ const char* CSystem::GetUserName() DWORD dwSize = iNameBufferSize; wchar_t nameW[iNameBufferSize]; ::GetUserNameW(nameW, &dwSize); - cry_strcpy(szNameBuffer, CryStringUtils::WStrToUTF8(nameW)); + azstrcpy(szNameBuffer, CryStringUtils::WStrToUTF8(nameW)); return szNameBuffer; #else #if defined(LINUX) @@ -283,7 +283,7 @@ static const char* GetLastSystemErrorMessage() 0, NULL)) { - cry_strcpy(szBuffer, (char*)lpMsgBuf); + azstrcpy(szBuffer, (char*)lpMsgBuf); LocalFree(lpMsgBuf); } else @@ -505,7 +505,9 @@ bool CSystem::GetWinGameFolder(char* szMyDocumentsPath, int maxPathSize) if (bSucceeded) { // Convert from UNICODE to UTF-8 - cry_strcpy(szMyDocumentsPath, maxPathSize, CryStringUtils::WStrToUTF8(wMyDocumentsPath)); + AZStd::string str; + AZStd::to_string(str, AZStd::wstring(wMyDocumentsPath)); + azstrcpy(szMyDocumentsPath, maxPathSize, str.c_str()); CoTaskMemFree(wMyDocumentsPath); } } @@ -519,7 +521,9 @@ bool CSystem::GetWinGameFolder(char* szMyDocumentsPath, int maxPathSize) bSucceeded = SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_PERSONAL | CSIDL_FLAG_CREATE, NULL, 0, wMyDocumentsPath)); if (bSucceeded) { - cry_strcpy(szMyDocumentsPath, maxPathSize, CryStringUtils::WStrToUTF8(wMyDocumentsPath)); + AZStd::string str; + AZStd::to_string(str, AZStd::wstring(wMyDocumentsPath)); + azstrcpy(szMyDocumentsPath, maxPathSize, str.c_str()); } } diff --git a/Code/Legacy/CrySystem/XConsole.cpp b/Code/Legacy/CrySystem/XConsole.cpp index 09b3182c04..a69d86e8b7 100644 --- a/Code/Legacy/CrySystem/XConsole.cpp +++ b/Code/Legacy/CrySystem/XConsole.cpp @@ -1554,7 +1554,7 @@ const char* CXConsole::GetFlagsString(const uint32 dwFlags) // hiding this makes it a bit more difficult for cheaters // if(dwFlags&VF_CHEAT) cry_strcat( sFlags,"CHEAT, "); - cry_strcpy(sFlags, ""); + azstrcpy(sFlags, ""); if (dwFlags & VF_READONLY) { diff --git a/Code/Legacy/CrySystem/XConsole.h b/Code/Legacy/CrySystem/XConsole.h index eca52771dd..f09c8e5ad7 100644 --- a/Code/Legacy/CrySystem/XConsole.h +++ b/Code/Legacy/CrySystem/XConsole.h @@ -42,11 +42,11 @@ enum ScrollDir ////////////////////////////////////////////////////////////////////////// struct CConsoleCommand { - string m_sName; // Console command name - string m_sCommand; // lua code that is executed when this command is invoked - string m_sHelp; // optional help string - can be shown in the console with " ?" - int m_nFlags; // bitmask consist of flag starting with VF_ e.g. VF_CHEAT - ConsoleCommandFunc m_func; // Pointer to console command. + AZStd::string m_sName; // Console command name + AZStd::string m_sCommand; // lua code that is executed when this command is invoked + AZStd::string m_sHelp; // optional help string - can be shown in the console with " ?" + int m_nFlags; // bitmask consist of flag starting with VF_ e.g. VF_CHEAT + ConsoleCommandFunc m_func; // Pointer to console command. ////////////////////////////////////////////////////////////////////////// CConsoleCommand() @@ -67,7 +67,7 @@ struct CConsoleCommand struct CConsoleCommandArgs : public IConsoleCmdArgs { - CConsoleCommandArgs(string& line, std::vector& args) + CConsoleCommandArgs(AZStd::string& line, std::vector& args) : m_line(line) , m_args(args) {}; virtual int GetArgCount() const { return m_args.size(); }; @@ -87,8 +87,8 @@ struct CConsoleCommandArgs } private: - std::vector& m_args; - string& m_line; + std::vector& m_args; + AZStd::string& m_line; }; @@ -132,7 +132,7 @@ class CXConsole , public AzFramework::CommandRegistrationBus::Handler { public: - typedef std::deque ConsoleBuffer; + typedef std::deque ConsoleBuffer; typedef ConsoleBuffer::iterator ConsoleBufferItor; typedef ConsoleBuffer::reverse_iterator ConsoleBufferRItor; @@ -262,7 +262,7 @@ protected: // ------------------------------------------------------------------ void AddInputUTF8(const AZStd::string& textUTF8); void RemoveInputChar(bool bBackSpace); void ExecuteInputBuffer(); - void ExecuteCommand(CConsoleCommand& cmd, string& params, bool bIgnoreDevMode = false); + void ExecuteCommand(CConsoleCommand& cmd, AZStd::string& params, bool bIgnoreDevMode = false); void ScrollConsole(); @@ -294,7 +294,7 @@ protected: // ------------------------------------------------------------------ // Arguments: // bFromConsole - true=from console, false=from outside - void SplitCommands(const char* line, std::list& split); + void SplitCommands(const char* line, std::list& split); void ExecuteStringInternal(const char* command, const bool bFromConsole, const bool bSilentMode = false); void ExecuteDeferredCommands(); @@ -320,27 +320,27 @@ private: // ---------------------------------------------------------- void PostLine(const char* lineOfText, size_t len); - typedef std::map ConsoleCommandsMap; + typedef std::map ConsoleCommandsMap; typedef ConsoleCommandsMap::iterator ConsoleCommandsMapItor; - typedef std::map ConsoleBindsMap; + typedef std::map ConsoleBindsMap; typedef ConsoleBindsMap::iterator ConsoleBindsMapItor; - typedef std::map > ArgumentAutoCompleteMap; + typedef std::map > ArgumentAutoCompleteMap; struct SConfigVar { - string m_value; + AZStd::string m_value; bool m_partOfGroup; }; - typedef std::map ConfigVars; + typedef std::map ConfigVars; struct SDeferredCommand { - string command; + AZStd::string command; bool silentMode; - SDeferredCommand(const string& _command, bool _silentMode) + SDeferredCommand(const AZStd::string& _command, bool _silentMode) : command(_command) , silentMode(_silentMode) {} @@ -359,10 +359,10 @@ private: // ---------------------------------------------------------- int m_nProgress; int m_nProgressRange; - string m_sInputBuffer; - string m_sReturnString; + AZStd::string m_sInputBuffer; + AZStd::string m_sReturnString; - string m_sPrevTab; + AZStd::string m_sPrevTab; int m_nTabCount; ConsoleCommandsMap m_mapCommands; // diff --git a/Code/Legacy/CrySystem/XML/SerializeXMLReader.cpp b/Code/Legacy/CrySystem/XML/SerializeXMLReader.cpp index da4bf66eee..55fab84286 100644 --- a/Code/Legacy/CrySystem/XML/SerializeXMLReader.cpp +++ b/Code/Legacy/CrySystem/XML/SerializeXMLReader.cpp @@ -49,7 +49,7 @@ bool CSerializeXMLReaderImpl::Value(const char* name, int8& value) return bResult; } -bool CSerializeXMLReaderImpl::Value(const char* name, string& value) +bool CSerializeXMLReaderImpl::Value(const char* name, AZStd::string& value) { DefaultValue(value); // Set input value to default. if (m_nErrors) @@ -177,7 +177,7 @@ void CSerializeXMLReaderImpl::EndGroup() ////////////////////////////////////////////////////////////////////////// const char* CSerializeXMLReaderImpl::GetStackInfo() const { - static string str; + static AZStd::string str; str.assign(""); for (int i = 0; i < (int)m_nodeStack.size(); i++) { diff --git a/Code/Legacy/CrySystem/XML/SerializeXMLReader.h b/Code/Legacy/CrySystem/XML/SerializeXMLReader.h index c0e2059886..177db0ffaa 100644 --- a/Code/Legacy/CrySystem/XML/SerializeXMLReader.h +++ b/Code/Legacy/CrySystem/XML/SerializeXMLReader.h @@ -47,7 +47,7 @@ public: g_pXmlStrCmp = pPrevCmpFunc; return bReturn; } - ILINE bool GetAttr([[maybe_unused]] XmlNodeRef& node, [[maybe_unused]] const char* name, [[maybe_unused]] const string& value) + ILINE bool GetAttr([[maybe_unused]] XmlNodeRef& node, [[maybe_unused]] const char* name, [[maybe_unused]] const AZStd::string& value) { return false; } @@ -75,7 +75,7 @@ public: } bool Value(const char* name, int8& value); - bool Value(const char* name, string& value); + bool Value(const char* name, AZStd::string& value); bool Value(const char* name, CTimeValue& value); bool Value(const char* name, XmlNodeRef& value); @@ -172,8 +172,8 @@ private: void DefaultValue(Quat& v) const { v.w = 1.0f; v.v.x = 0; v.v.y = 0; v.v.z = 0; } void DefaultValue(CTimeValue& v) const { v.SetValue(0); } //void DefaultValue( char *str ) const { if (str) str[0] = 0; } - void DefaultValue(string& str) const { str = ""; } - void DefaultValue([[maybe_unused]] const string& str) const {} + void DefaultValue(AZStd::string& str) const { str = ""; } + void DefaultValue([[maybe_unused]] const AZStd::string& str) const {} void DefaultValue([[maybe_unused]] SNetObjectID& id) const {} void DefaultValue([[maybe_unused]] SSerializeString& str) const {} void DefaultValue(XmlNodeRef& ref) const { ref = NULL; } diff --git a/Code/Legacy/CrySystem/XML/XMLBinaryReader.cpp b/Code/Legacy/CrySystem/XML/XMLBinaryReader.cpp index bd31fb3ba4..e59f6b8969 100644 --- a/Code/Legacy/CrySystem/XML/XMLBinaryReader.cpp +++ b/Code/Legacy/CrySystem/XML/XMLBinaryReader.cpp @@ -32,7 +32,7 @@ const char* XMLBinary::XMLBinaryReader::GetErrorDescription() const void XMLBinary::XMLBinaryReader::SetErrorDescription(const char* text) { - cry_strcpy(m_errorDescription, text); + azstrcpy(m_errorDescription, text); } diff --git a/Code/Legacy/CrySystem/XML/XMLBinaryWriter.cpp b/Code/Legacy/CrySystem/XML/XMLBinaryWriter.cpp index 60e0d2e4f1..81994b26e0 100644 --- a/Code/Legacy/CrySystem/XML/XMLBinaryWriter.cpp +++ b/Code/Legacy/CrySystem/XML/XMLBinaryWriter.cpp @@ -84,7 +84,7 @@ static void write(XMLBinary::IDataWriter* const pFile, size_t& nPosition, const } ////////////////////////////////////////////////////////////////////////// -bool XMLBinary::CXMLBinaryWriter::WriteNode(IDataWriter* pFile, XmlNodeRef node, bool bNeedSwapEndian, XMLBinary::IFilter* pFilter, string& error) +bool XMLBinary::CXMLBinaryWriter::WriteNode(IDataWriter* pFile, XmlNodeRef node, bool bNeedSwapEndian, XMLBinary::IFilter* pFilter, AZStd::string& error) { error = ""; @@ -99,7 +99,7 @@ bool XMLBinary::CXMLBinaryWriter::WriteNode(IDataWriter* pFile, XmlNodeRef node, static const uint nMaxNodeCount = (NodeIndex) ~0; if (m_nodes.size() > nMaxNodeCount) { - error.Format("XMLBinary: Too many nodes: %d (max is %i)", m_nodes.size(), nMaxNodeCount); + error = AZStd::string::format("XMLBinary: Too many nodes: %d (max is %i)", m_nodes.size(), nMaxNodeCount); return false; } @@ -192,7 +192,7 @@ bool XMLBinary::CXMLBinaryWriter::WriteNode(IDataWriter* pFile, XmlNodeRef node, return true; } -bool XMLBinary::CXMLBinaryWriter::CompileTables(XmlNodeRef node, XMLBinary::IFilter* pFilter, string& error) +bool XMLBinary::CXMLBinaryWriter::CompileTables(XmlNodeRef node, XMLBinary::IFilter* pFilter, AZStd::string& error) { bool ok = CompileTablesForNode(node, -1, pFilter, error); ok = ok && CompileChildTable(node, pFilter, error); @@ -200,7 +200,7 @@ bool XMLBinary::CXMLBinaryWriter::CompileTables(XmlNodeRef node, XMLBinary::IFil } ////////////////////////////////////////////////////////////////////////// -bool XMLBinary::CXMLBinaryWriter::CompileTablesForNode(XmlNodeRef node, int nParentIndex, XMLBinary::IFilter* pFilter, string& error) +bool XMLBinary::CXMLBinaryWriter::CompileTablesForNode(XmlNodeRef node, int nParentIndex, XMLBinary::IFilter* pFilter, AZStd::string& error) { // Add the tag to the string table. int nTagStringOffset = AddString(node->getTag()); @@ -231,7 +231,7 @@ bool XMLBinary::CXMLBinaryWriter::CompileTablesForNode(XmlNodeRef node, int nPar static const int nMaxAttributeCount = (uint16) ~0; if (nAttributeCount > nMaxAttributeCount) { - error.Format("XMLBinary: Too many attributes in a node: %d (max is %i)", nAttributeCount, nMaxAttributeCount); + error = AZStd::string::format("XMLBinary: Too many attributes in a node: %d (max is %i)", nAttributeCount, nMaxAttributeCount); return false; } @@ -261,7 +261,7 @@ bool XMLBinary::CXMLBinaryWriter::CompileTablesForNode(XmlNodeRef node, int nPar { if (++nChildCount > nMaxChildCount) { - error.Format("XMLBinary: Too many children in node '%s': %d (max is %i)", childNode->getTag(), nChildCount, nMaxChildCount); + error = AZStd::string::format("XMLBinary: Too many children in node '%s': %d (max is %i)", childNode->getTag(), nChildCount, nMaxChildCount); return false; } if (!CompileTablesForNode(childNode, nIndex, pFilter, error)) @@ -277,7 +277,7 @@ bool XMLBinary::CXMLBinaryWriter::CompileTablesForNode(XmlNodeRef node, int nPar } ////////////////////////////////////////////////////////////////////////// -bool XMLBinary::CXMLBinaryWriter::CompileChildTable(XmlNodeRef node, XMLBinary::IFilter* pFilter, string& error) +bool XMLBinary::CXMLBinaryWriter::CompileChildTable(XmlNodeRef node, XMLBinary::IFilter* pFilter, AZStd::string& error) { const int nIndex = m_nodesMap.find(node)->second; // Assume node always exist in map. const int nFirstChildIndex = (int)m_childs.size(); @@ -298,7 +298,7 @@ bool XMLBinary::CXMLBinaryWriter::CompileChildTable(XmlNodeRef node, XMLBinary:: } if (nChildCount != nd.nChildCount) { - error.Format("XMLBinary: Internal error in CompileChildTable()"); + error = AZStd::string::format("XMLBinary: Internal error in CompileChildTable()"); return false; } diff --git a/Code/Legacy/CrySystem/XML/XMLPatcher.cpp b/Code/Legacy/CrySystem/XML/XMLPatcher.cpp index f78fa93a60..ff4cfc91d2 100644 --- a/Code/Legacy/CrySystem/XML/XMLPatcher.cpp +++ b/Code/Legacy/CrySystem/XML/XMLPatcher.cpp @@ -345,7 +345,7 @@ void CXMLPatcher::DumpXMLNodes( AZ::IO::HandleType inFileHandle, int inIndent, const XmlNodeRef& inNode, - CryFixedStringT<512>* ioTempString) + AZStd::fixed_string<512>* ioTempString) { auto pPak = gEnv->pCryPak; @@ -393,7 +393,7 @@ void CXMLPatcher::DumpFiles( DumpXMLFile(string().Format("PATCH_%s", pOrigFileName), inBefore); - CryFixedStringT<128> newFileName(pOrigFileName); + AZStd::fixed_string<128> newFileName(pOrigFileName); newFileName.replace(".xml", "_patched.xml"); DumpXMLFile(string().Format("PATCH_%s", newFileName.c_str()), inAfter); @@ -414,7 +414,7 @@ void CXMLPatcher::DumpXMLFile( if (fileHandle != AZ::IO::InvalidHandle) { - CryFixedStringT<512> tempStr; + AZStd::fixed_string<512> tempStr; DumpXMLNodes(fileHandle, 0, inNode, &tempStr); diff --git a/Code/Legacy/CrySystem/XML/XMLPatcher.h b/Code/Legacy/CrySystem/XML/XMLPatcher.h index 039b369723..ccc5f481eb 100644 --- a/Code/Legacy/CrySystem/XML/XMLPatcher.h +++ b/Code/Legacy/CrySystem/XML/XMLPatcher.h @@ -59,7 +59,7 @@ protected: AZ::IO::HandleType inFileHandle, int inIndent, const XmlNodeRef& inNode, - CryFixedStringT<512>* ioTempString); + AZStd::fixed_string<512>* ioTempString); void DumpFiles( const char* pInXMLFileName, const XmlNodeRef& inBefore, diff --git a/Code/Legacy/CrySystem/XML/xml.cpp b/Code/Legacy/CrySystem/XML/xml.cpp index 5761d8a963..c6e660155f 100644 --- a/Code/Legacy/CrySystem/XML/xml.cpp +++ b/Code/Legacy/CrySystem/XML/xml.cpp @@ -1691,8 +1691,8 @@ XmlNodeRef XmlParserImp::ParseFile(const char* filename, XmlString& errorString, char str[1024]; - CryStackStringT adjustedFilename; - CryStackStringT pakPath; + AZStd::fixed_string<256> adjustedFilename; + AZStd::fixed_string<256> pakPath; if (fileSize <= 0) { CCryFile xmlFile; @@ -1761,7 +1761,7 @@ XmlNodeRef XmlParserImp::ParseFile(const char* filename, XmlString& errorString, // not binary XML - refuse to load if in scripts dir and not in bin xml to help reduce hacking // wish we could compile the text xml parser out, but too much work to get everything moved over static const char SCRIPTS_DIR[] = "Scripts/"; - CryFixedStringT<32> strScripts("S"); + AZStd::fixed_string<32> strScripts("S"); strScripts += "c"; strScripts += "r"; strScripts += "i"; @@ -1770,7 +1770,7 @@ XmlNodeRef XmlParserImp::ParseFile(const char* filename, XmlString& errorString, strScripts += "s"; strScripts += "/"; // exclude files and PAKs from Mods folder - CryFixedStringT<8> modsStr("M"); + AZStd::fixed_string<8> modsStr("M"); modsStr += "o"; modsStr += "d"; modsStr += "s"; diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/FFont.h b/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/FFont.h index 795c823fd6..7974d0f2c1 100644 --- a/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/FFont.h +++ b/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/FFont.h @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include "AtomFont.h" diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Platform/Windows/FFontXML_Windows.cpp b/Gems/AtomLyIntegration/AtomFont/Code/Platform/Windows/FFontXML_Windows.cpp index 9aaaf2ffeb..f72ba6e1ff 100644 --- a/Gems/AtomLyIntegration/AtomFont/Code/Platform/Windows/FFontXML_Windows.cpp +++ b/Gems/AtomLyIntegration/AtomFont/Code/Platform/Windows/FFontXML_Windows.cpp @@ -18,7 +18,7 @@ namespace AtomFontInternal if (SUCCEEDED(SHGetFolderPath(0, CSIDL_FONTS, 0, SHGFP_TYPE_DEFAULT, sysFontPath))) { const char* fontPath = m_strFontPath.c_str(); - const char* fontName = CryStringUtils::FindFileNameInPath(fontPath); + const char* fontName = AZ::IO::PathView(fontPath).Filename(); string newFontPath(sysFontPath); newFontPath += "/"; diff --git a/Gems/Blast/Code/Source/Components/BlastSystemComponent.cpp b/Gems/Blast/Code/Source/Components/BlastSystemComponent.cpp index b7a7443daa..933633b5e3 100644 --- a/Gems/Blast/Code/Source/Components/BlastSystemComponent.cpp +++ b/Gems/Blast/Code/Source/Components/BlastSystemComponent.cpp @@ -437,8 +437,6 @@ namespace Blast static void CmdToggleBlastDebugVisualization(IConsoleCmdArgs* args) { - using namespace CryStringUtils; - const int argumentCount = args->GetArgCount(); if (argumentCount == 2) diff --git a/Gems/LmbrCentral/Code/Source/LmbrCentral.cpp b/Gems/LmbrCentral/Code/Source/LmbrCentral.cpp index 640fc2100e..78742028f9 100644 --- a/Gems/LmbrCentral/Code/Source/LmbrCentral.cpp +++ b/Gems/LmbrCentral/Code/Source/LmbrCentral.cpp @@ -85,7 +85,7 @@ namespace LmbrCentral { static const char* s_assetCatalogFilename = "assetcatalog.xml"; - using LmbrCentralAllocatorScope = AZ::AllocatorScope; + using LmbrCentralAllocatorScope = AZ::AllocatorScope; // This component boots the required allocators for LmbrCentral everywhere but AssetBuilders class LmbrCentralAllocatorComponent @@ -347,12 +347,6 @@ namespace LmbrCentral m_allocatorShutdowns.push_back([]() { AZ::AllocatorInstance::Destroy(); }); } - if (!AZ::AllocatorInstance::IsReady()) - { - AZ::AllocatorInstance::Create(); - m_allocatorShutdowns.push_back([]() { AZ::AllocatorInstance::Destroy(); }); - } - // Register asset handlers. Requires "AssetDatabaseService" AZ_Assert(AZ::Data::AssetManager::IsReady(), "Asset manager isn't ready!"); diff --git a/Gems/LyShine/Code/Editor/Animation/UiAnimViewNodes.cpp b/Gems/LyShine/Code/Editor/Animation/UiAnimViewNodes.cpp index d930b4b581..9cca6cdf8d 100644 --- a/Gems/LyShine/Code/Editor/Animation/UiAnimViewNodes.cpp +++ b/Gems/LyShine/Code/Editor/Animation/UiAnimViewNodes.cpp @@ -1512,7 +1512,7 @@ int CUiAnimViewNodesCtrl::GetMatNameAndSubMtlIndexFromName(QString& matName, con if (const char* pCh = strstr(nodeName, ".[")) { char matPath[MAX_PATH]; - cry_strcpy(matPath, nodeName, (size_t)(pCh - nodeName)); + azstrcpy(matPath, nodeName, (size_t)(pCh - nodeName)); matName = matPath; pCh += 2; if ((*pCh) != 0) diff --git a/Gems/LyShine/Code/Editor/PropertyHandlerChar.cpp b/Gems/LyShine/Code/Editor/PropertyHandlerChar.cpp index ac55cd38e9..98cbd22f71 100644 --- a/Gems/LyShine/Code/Editor/PropertyHandlerChar.cpp +++ b/Gems/LyShine/Code/Editor/PropertyHandlerChar.cpp @@ -47,7 +47,8 @@ bool PropertyHandlerChar::ReadValuesIntoGUI(size_t index, AzToolsFramework::Prop // NOTE: this assumes the uint32_t can be interpreted as a wchar_t, it seems to // work for cases tested but may not in general. wchar_t wcharString[2] = { static_cast(instance), 0 }; - AZStd::string val(CryStringUtils::WStrToUTF8(wcharString)); + AZStd::string val; + AZStd::to_string(val, AZStd::wstring(wcharString)); GUI->setValue(val); } GUI->blockSignals(false); diff --git a/Gems/LyShine/Code/Source/LyShineSystemComponent.h b/Gems/LyShine/Code/Source/LyShineSystemComponent.h index 9b5f32aa57..f922c59afe 100644 --- a/Gems/LyShine/Code/Source/LyShineSystemComponent.h +++ b/Gems/LyShine/Code/Source/LyShineSystemComponent.h @@ -22,9 +22,9 @@ namespace LyShine { - // LyShine depends on the LegacyAllocator and CryStringAllocator. This will be managed + // LyShine depends on the LegacyAllocator. This will be managed // by the LyShineSystemComponent - using LyShineAllocatorScope = AZ::AllocatorScope; + using LyShineAllocatorScope = AZ::AllocatorScope; class LyShineSystemComponent : public AZ::Component diff --git a/Gems/LyShine/Code/Source/Platform/Windows/UiClipboard_Windows.cpp b/Gems/LyShine/Code/Source/Platform/Windows/UiClipboard_Windows.cpp index 318a165914..cbd0b2d6cb 100644 --- a/Gems/LyShine/Code/Source/Platform/Windows/UiClipboard_Windows.cpp +++ b/Gems/LyShine/Code/Source/Platform/Windows/UiClipboard_Windows.cpp @@ -20,7 +20,8 @@ bool UiClipboard::SetText(const AZStd::string& text) { if (text.length() > 0) { - auto wstr = CryStringUtils::UTF8ToWStr(text.c_str()); + AZStd::wstring wstr; + AZStd::to_wstring(wstr, text); const SIZE_T buffSize = (wstr.size() + 1) * sizeof(WCHAR); if (HGLOBAL hBuffer = GlobalAlloc(GMEM_MOVEABLE, buffSize)) { @@ -46,7 +47,7 @@ AZStd::string UiClipboard::GetText() if (HANDLE hText = GetClipboardData(CF_UNICODETEXT)) { const WCHAR* text = static_cast(GlobalLock(hText)); - outText = CryStringUtils::WStrToUTF8(text); + AZStd::to_string(outText, AZStd::wstring(text)); GlobalUnlock(hText); } CloseClipboard(); diff --git a/Gems/LyShine/Code/Source/StringUtfUtils.h b/Gems/LyShine/Code/Source/StringUtfUtils.h index 74a27afe9f..e10e691a6f 100644 --- a/Gems/LyShine/Code/Source/StringUtfUtils.h +++ b/Gems/LyShine/Code/Source/StringUtfUtils.h @@ -36,7 +36,8 @@ namespace LyShine // In the long run it would be better to eliminate // this function and use Unicode::CIterator<>::Position instead. wchar_t wcharString[2] = { static_cast(multiByteChar), 0 }; - AZStd::string utf8String(CryStringUtils::WStrToUTF8(wcharString)); + AZStd::string utf8String; + AZStd::to_string(utf8String, AZStd::wstring(wcharString)); int utf8Length = utf8String.length(); return utf8Length; } diff --git a/Gems/LyShine/Code/Source/UiButtonComponent.cpp b/Gems/LyShine/Code/Source/UiButtonComponent.cpp index bf0a67d08a..c6ba64848e 100644 --- a/Gems/LyShine/Code/Source/UiButtonComponent.cpp +++ b/Gems/LyShine/Code/Source/UiButtonComponent.cpp @@ -220,48 +220,9 @@ bool UiButtonComponent::VersionConverter(AZ::SerializeContext& context, // conversion from version 1 to 2: // - Need to convert CryString elements to AZStd::string // - Need to convert Color to Color and Alpha - if (classElement.GetVersion() < 2) - { - if (!LyShine::ConvertSubElementFromCryStringToAzString(context, classElement, "SelectedSprite")) - { - return false; - } - - if (!LyShine::ConvertSubElementFromCryStringToAzString(context, classElement, "PressedSprite")) - { - return false; - } - - if (!LyShine::ConvertSubElementFromCryStringToAzString(context, classElement, "DisabledSprite")) - { - return false; - } - - if (!LyShine::ConvertSubElementFromColorToColorPlusAlpha(context, classElement, "SelectedColor", "SelectedAlpha")) - { - return false; - } - - if (!LyShine::ConvertSubElementFromColorToColorPlusAlpha(context, classElement, "PressedColor", "PressedAlpha")) - { - return false; - } - - if (!LyShine::ConvertSubElementFromColorToColorPlusAlpha(context, classElement, "DisabledColor", "DisabledAlpha")) - { - return false; - } - } - // conversion from version 2 to 3: // - Need to convert CryString ActionName elements to AZStd::string - if (classElement.GetVersion() < 3) - { - if (!LyShine::ConvertSubElementFromCryStringToAzString(context, classElement, "ActionName")) - { - return false; - } - } + AZ_Assert(classElement.GetVersion() < 3, "Unsupported UiButtonComponent version: %d", classElement.GetVersion()); // conversion from version 3 to 4: // - Need to convert AZStd::string sprites to AzFramework::SimpleAssetReference diff --git a/Gems/LyShine/Code/Source/UiImageComponent.cpp b/Gems/LyShine/Code/Source/UiImageComponent.cpp index 901c13d594..8f4145c07b 100644 --- a/Gems/LyShine/Code/Source/UiImageComponent.cpp +++ b/Gems/LyShine/Code/Source/UiImageComponent.cpp @@ -2663,18 +2663,7 @@ bool UiImageComponent::VersionConverter(AZ::SerializeContext& context, // conversion from version 1: // - Need to convert CryString elements to AZStd::string // - Need to convert Color to Color and Alpha - if (classElement.GetVersion() <= 1) - { - if (!LyShine::ConvertSubElementFromCryStringToAzString(context, classElement, "SpritePath")) - { - return false; - } - - if (!LyShine::ConvertSubElementFromColorToColorPlusAlpha(context, classElement, "Color", "Alpha")) - { - return false; - } - } + AZ_Assert(classElement.GetVersion() <= 1, "Unsupported UiImageComponent version: %d", classElement.GetVersion()); // conversion from version 1 or 2 to current: // - Need to convert AZStd::string sprites to AzFramework::SimpleAssetReference diff --git a/Gems/LyShine/Code/Source/UiSerialize.cpp b/Gems/LyShine/Code/Source/UiSerialize.cpp index f44d011863..e0892596ff 100644 --- a/Gems/LyShine/Code/Source/UiSerialize.cpp +++ b/Gems/LyShine/Code/Source/UiSerialize.cpp @@ -31,67 +31,6 @@ namespace UiSerialize { - //////////////////////////////////////////////////////////////////////////////////////////////////// - class CryStringTCharSerializer - : public AZ::SerializeContext::IDataSerializer - { - /// Return the size of binary buffer necessary to store the value in binary format - size_t GetRequiredBinaryBufferSize(const void* classPtr) const - { - const CryStringT* string = reinterpret_cast*>(classPtr); - return string->length() + 1; - } - - /// Store the class data into a stream. - size_t Save(const void* classPtr, AZ::IO::GenericStream& stream, [[maybe_unused]] bool isDataBigEndian /*= false*/) override - { - const CryStringT* string = reinterpret_cast*>(classPtr); - const char* data = string->c_str(); - - return static_cast(stream.Write(string->length() + 1, reinterpret_cast(data))); - } - - size_t DataToText(AZ::IO::GenericStream& in, AZ::IO::GenericStream& out, [[maybe_unused]] bool isDataBigEndian /*= false*/) override - { - size_t len = in.GetLength(); - char* buffer = static_cast(azmalloc(len)); - in.Read(in.GetLength(), reinterpret_cast(buffer)); - - AZStd::string outText = buffer; - azfree(buffer); - - return static_cast(out.Write(outText.size(), outText.data())); - } - - size_t TextToData(const char* text, unsigned int textVersion, AZ::IO::GenericStream& stream, [[maybe_unused]] bool isDataBigEndian /*= false*/) override - { - (void)textVersion; - - size_t len = strlen(text) + 1; - stream.Seek(0, AZ::IO::GenericStream::ST_SEEK_BEGIN); - return static_cast(stream.Write(len, reinterpret_cast(text))); - } - - bool Load(void* classPtr, AZ::IO::GenericStream& stream, unsigned int /*version*/, [[maybe_unused]] bool isDataBigEndian /*= false*/) override - { - CryStringT* string = reinterpret_cast*>(classPtr); - - size_t len = stream.GetLength(); - char* buffer = static_cast(azmalloc(len)); - - stream.Read(len, reinterpret_cast(buffer)); - - *string = buffer; - azfree(buffer); - return true; - } - - bool CompareValueData(const void* lhs, const void* rhs) override - { - return AZ::SerializeContext::EqualityCompareHelper >::CompareValues(lhs, rhs); - } - }; - ////////////////////////////////////////////////////////////////////////// void UiOffsetsScriptConstructor(UiTransform2dInterface::Offsets* thisPtr, AZ::ScriptDataContext& dc) { @@ -553,9 +492,6 @@ namespace UiSerialize if (serializeContext) { - serializeContext->Class >()-> - Serializer(&AZ::Serialize::StaticInstance::s_instance); - serializeContext->Class() ->Version(1) ->Field("SerializeString", &AnimationData::m_serializeData); diff --git a/Gems/LyShine/Code/Source/UiTextComponent.cpp b/Gems/LyShine/Code/Source/UiTextComponent.cpp index 025c22a895..76a789c5cf 100644 --- a/Gems/LyShine/Code/Source/UiTextComponent.cpp +++ b/Gems/LyShine/Code/Source/UiTextComponent.cpp @@ -4995,28 +4995,8 @@ bool UiTextComponent::VersionConverter(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement) { // conversion from version 1: Need to convert Color to Color and Alpha - if (classElement.GetVersion() == 1) - { - if (!LyShine::ConvertSubElementFromCryStringToAssetRef(context, classElement, "FontFileName")) - { - return false; - } - - if (!LyShine::ConvertSubElementFromColorToColorPlusAlpha(context, classElement, "Color", "Alpha")) - { - return false; - } - } - // conversion from version 1 or 2: Need to convert Text from CryString to AzString - if (classElement.GetVersion() <= 2) - { - // Call internal function to work-around serialization of empty AZ std string - if (!LyShine::ConvertSubElementFromCryStringToAzString(context, classElement, "Text")) - { - return false; - } - } + AZ_Assert(classElement.GetVersion() <= 2, "Unsupported UiTextComponent version: %d", classElement.GetVersion()); // Versions prior to v4: Change default font if (classElement.GetVersion() <= 3) diff --git a/Gems/LyShine/Code/Source/UiTextInputComponent.cpp b/Gems/LyShine/Code/Source/UiTextInputComponent.cpp index e37d8787e1..c746d14095 100644 --- a/Gems/LyShine/Code/Source/UiTextInputComponent.cpp +++ b/Gems/LyShine/Code/Source/UiTextInputComponent.cpp @@ -1185,7 +1185,8 @@ void UiTextInputComponent::UpdateDisplayedTextFunction() // NOTE: this assumes the uint32_t can be interpreted as a wchar_t, it seems to // work for cases tested but may not in general. wchar_t wcharString[2] = { static_cast(this->GetReplacementCharacter()), 0 }; - AZStd::string replacementCharString(CryStringUtils::WStrToUTF8(wcharString)); + AZStd::string replacementCharString; + AZStd::to_string(replacementCharString, AZStd::wstring(wcharString)); int numReplacementChars = LyShine::GetUtf8StringLength(originalText); @@ -1475,54 +1476,10 @@ bool UiTextInputComponent::VersionConverter(AZ::SerializeContext& context, // conversion from version 1: // - Need to convert CryString elements to AZStd::string // - Need to convert Color to Color and Alpha - if (classElement.GetVersion() <= 1) - { - if (!LyShine::ConvertSubElementFromCryStringToAzString(context, classElement, "SelectedSprite")) - { - return false; - } - - if (!LyShine::ConvertSubElementFromCryStringToAzString(context, classElement, "PressedSprite")) - { - return false; - } - - if (!LyShine::ConvertSubElementFromColorToColorPlusAlpha(context, classElement, "SelectedColor", "SelectedAlpha")) - { - return false; - } - - if (!LyShine::ConvertSubElementFromColorToColorPlusAlpha(context, classElement, "PressedColor", "PressedAlpha")) - { - return false; - } - - if (!LyShine::ConvertSubElementFromCryStringToChar(context, classElement, "ReplacementCharacter", defaultReplacementChar)) - { - return false; - } - } - // conversion from version 1 or 2 to current: // - Need to convert CryString ActionName elements to AZStd::string - if (classElement.GetVersion() <= 2) - { - if (!LyShine::ConvertSubElementFromCryStringToAzString(context, classElement, "ChangeAction")) - { - return false; - } - - if (!LyShine::ConvertSubElementFromCryStringToAzString(context, classElement, "EndEditAction")) - { - return false; - } - - if (!LyShine::ConvertSubElementFromCryStringToAzString(context, classElement, "EnterAction")) - { - return false; - } - } - + AZ_Assert(classElement.GetVersion() <= 2, "Unsupported UiTextInputComponent version: %d", classElement.GetVersion()); + // conversion from version 1, 2 or 3 to current: // - Need to convert AZStd::string sprites to AzFramework::SimpleAssetReference if (classElement.GetVersion() <= 3) diff --git a/Gems/LyShine/Code/Tests/SerializationTest.cpp b/Gems/LyShine/Code/Tests/SerializationTest.cpp index e5ed3638d4..70ae590358 100644 --- a/Gems/LyShine/Code/Tests/SerializationTest.cpp +++ b/Gems/LyShine/Code/Tests/SerializationTest.cpp @@ -24,7 +24,6 @@ namespace UnitTest appDesc.m_stackRecordLevels = 20; AZ::ComponentApplication::StartupParameters appStartup; - // Module needs to be created this way to create CryString allocator for test appStartup.m_createStaticModulesCallback = [](AZStd::vector& modules) { diff --git a/Gems/LyShine/Code/Tests/SpriteTest.cpp b/Gems/LyShine/Code/Tests/SpriteTest.cpp index 0ac3465cd7..84b47955b4 100644 --- a/Gems/LyShine/Code/Tests/SpriteTest.cpp +++ b/Gems/LyShine/Code/Tests/SpriteTest.cpp @@ -27,7 +27,6 @@ namespace UnitTest appDesc.m_stackRecordLevels = 20; AZ::ComponentApplication::StartupParameters appStartup; - // Module needs to be created this way to create CryString allocator for test appStartup.m_createStaticModulesCallback = [](AZStd::vector& modules) { diff --git a/Gems/Maestro/Code/Source/Cinematics/CaptureTrack.cpp b/Gems/Maestro/Code/Source/Cinematics/CaptureTrack.cpp index 114e768975..60d578d1f8 100644 --- a/Gems/Maestro/Code/Source/Cinematics/CaptureTrack.cpp +++ b/Gems/Maestro/Code/Source/Cinematics/CaptureTrack.cpp @@ -52,7 +52,7 @@ void CCaptureTrack::GetKeyInfo(int key, const char*& description, float& duratio char prefix[64] = "Frame"; if (!m_keys[key].prefix.empty()) { - cry_strcpy(prefix, m_keys[key].prefix.c_str()); + azstrcpy(prefix, m_keys[key].prefix.c_str()); } description = buffer; if (!m_keys[key].folder.empty()) diff --git a/Gems/Maestro/Code/Source/Cinematics/CommentTrack.cpp b/Gems/Maestro/Code/Source/Cinematics/CommentTrack.cpp index c9a50a0979..1dd72de567 100644 --- a/Gems/Maestro/Code/Source/Cinematics/CommentTrack.cpp +++ b/Gems/Maestro/Code/Source/Cinematics/CommentTrack.cpp @@ -25,7 +25,7 @@ void CCommentTrack::GetKeyInfo(int key, const char*& description, float& duratio description = 0; duration = m_keys[key].m_duration; - cry_strcpy(desc, m_keys[key].m_strComment.c_str()); + azstrcpy(desc, m_keys[key].m_strComment.c_str()); description = desc; } diff --git a/Gems/Maestro/Code/Source/Cinematics/EventTrack.cpp b/Gems/Maestro/Code/Source/Cinematics/EventTrack.cpp index 5e1a63b4bc..278833cfe2 100644 --- a/Gems/Maestro/Code/Source/Cinematics/EventTrack.cpp +++ b/Gems/Maestro/Code/Source/Cinematics/EventTrack.cpp @@ -69,7 +69,7 @@ void CEventTrack::GetKeyInfo(int key, const char*& description, float& duration) CheckValid(); description = 0; duration = 0; - cry_strcpy(desc, m_keys[key].event.c_str()); + azstrcpy(desc, m_keys[key].event.c_str()); if (!m_keys[key].eventValue.empty()) { cry_strcat(desc, ", "); diff --git a/Gems/Maestro/Code/Source/Cinematics/SceneNode.cpp b/Gems/Maestro/Code/Source/Cinematics/SceneNode.cpp index 4ffb7f0413..9e3fe212df 100644 --- a/Gems/Maestro/Code/Source/Cinematics/SceneNode.cpp +++ b/Gems/Maestro/Code/Source/Cinematics/SceneNode.cpp @@ -916,7 +916,7 @@ void CAnimSceneNode::ApplyCameraKey(ISelectKey& key, SAnimContext& ec) void CAnimSceneNode::ApplyEventKey(IEventKey& key, [[maybe_unused]] SAnimContext& ec) { char funcName[1024]; - cry_strcpy(funcName, "Event_"); + azstrcpy(funcName, "Event_"); cry_strcat(funcName, key.event.c_str()); gEnv->pMovieSystem->SendGlobalEvent(funcName); } diff --git a/Gems/Maestro/Code/Source/Cinematics/TrackEventTrack.cpp b/Gems/Maestro/Code/Source/Cinematics/TrackEventTrack.cpp index f6a0920901..3eca733a1d 100644 --- a/Gems/Maestro/Code/Source/Cinematics/TrackEventTrack.cpp +++ b/Gems/Maestro/Code/Source/Cinematics/TrackEventTrack.cpp @@ -143,7 +143,7 @@ void CTrackEventTrack::GetKeyInfo(int key, const char*& description, float& dura CheckValid(); description = 0; duration = 0; - cry_strcpy(desc, m_keys[key].event.c_str()); + azstrcpy(desc, m_keys[key].event.c_str()); if (!m_keys[key].eventValue.empty()) { cry_strcat(desc, ", "); diff --git a/Gems/Maestro/Code/Source/MaestroSystemComponent.h b/Gems/Maestro/Code/Source/MaestroSystemComponent.h index e5776c6628..b27075dbc0 100644 --- a/Gems/Maestro/Code/Source/MaestroSystemComponent.h +++ b/Gems/Maestro/Code/Source/MaestroSystemComponent.h @@ -17,10 +17,10 @@ namespace Maestro { - // Ensure that Maestro always has the LegacyAllocator and CryStringAllocators available + // Ensure that Maestro always has the LegacyAllocator available // NOTE: This component is only activated in the AssetBuilder, as the required allocators are // booted by the launcher or editor. - using MaestroAllocatorScope = AZ::AllocatorScope; + using MaestroAllocatorScope = AZ::AllocatorScope; class MaestroAllocatorComponent : public AZ::Component diff --git a/Gems/Metastream/Code/Tests/MetastreamTest.cpp b/Gems/Metastream/Code/Tests/MetastreamTest.cpp index c304a1c55f..4f1d37391a 100644 --- a/Gems/Metastream/Code/Tests/MetastreamTest.cpp +++ b/Gems/Metastream/Code/Tests/MetastreamTest.cpp @@ -38,12 +38,10 @@ protected: AZ::AllocatorInstance::Create(); AZ::AllocatorInstance::Create(); AZ::AllocatorInstance::Create(); - AZ::AllocatorInstance::Create(); } void TeardownEnvironment() override { - AZ::AllocatorInstance::Destroy(); AZ::AllocatorInstance::Destroy(); AZ::AllocatorInstance::Destroy(); AZ::AllocatorInstance::Destroy(); diff --git a/Gems/PhysXDebug/Code/Source/SystemComponent.cpp b/Gems/PhysXDebug/Code/Source/SystemComponent.cpp index 96da22480d..0ccc77bba4 100644 --- a/Gems/PhysXDebug/Code/Source/SystemComponent.cpp +++ b/Gems/PhysXDebug/Code/Source/SystemComponent.cpp @@ -577,8 +577,6 @@ namespace PhysXDebug static void physx_Debug([[maybe_unused]] const AZ::ConsoleCommandContainer& arguments) { - using namespace CryStringUtils; - const int argumentCount = arguments.size(); if (argumentCount == 1) From 63d2f34ad6641546c81674a79ee39eb20370b90d Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Wed, 28 Jul 2021 11:06:14 -0700 Subject: [PATCH 037/803] more fixes, AtomFont still requires more work Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Legacy/CryCommon/ILocalizationManager.h | 30 +++++++++---------- .../Legacy/CryCommon/LocalizationManagerBus.h | 24 +++++++-------- .../AtomLyIntegration/AtomFont/AtomFont.h | 4 +-- .../AtomLyIntegration/AtomFont/AtomNullFont.h | 4 +-- .../AtomLyIntegration/AtomFont/FFont.h | 12 ++++---- .../AtomLyIntegration/AtomFont/FontRenderer.h | 2 +- .../AtomLyIntegration/AtomFont/FontTexture.h | 4 +-- .../AtomLyIntegration/AtomFont/GlyphCache.h | 2 +- .../AtomFont/Code/Source/FFontXML_Internal.h | 14 ++++----- 9 files changed, 47 insertions(+), 49 deletions(-) diff --git a/Code/Legacy/CryCommon/ILocalizationManager.h b/Code/Legacy/CryCommon/ILocalizationManager.h index de100152b3..2cba093f21 100644 --- a/Code/Legacy/CryCommon/ILocalizationManager.h +++ b/Code/Legacy/CryCommon/ILocalizationManager.h @@ -34,14 +34,14 @@ struct SLocalizedInfoGame } const char* szCharacterName; - string sUtf8TranslatedText; + AZStd::string sUtf8TranslatedText; bool bUseSubtitle; }; struct SLocalizedAdvancesSoundEntry { - string sName; + AZStd::string sName; float fValue; void GetMemoryUsage(ICrySizer* pSizer) const { @@ -178,12 +178,12 @@ struct ILocalizationManager // bEnglish - if true, translates the string into the always present English language. // Returns: // true if localization was successful, false otherwise - virtual bool LocalizeString_ch([[maybe_unused]] const char* sString, [[maybe_unused]] string& outLocalizedString, [[maybe_unused]] bool bEnglish = false) override { return false; } + virtual bool LocalizeString_ch([[maybe_unused]] const char* sString, [[maybe_unused]] AZStd::string& outLocalizedString, [[maybe_unused]] bool bEnglish = false) override { return false; } // Summary: - // Same as LocalizeString( const char* sString, string& outLocalizedString, bool bEnglish=false ) + // Same as LocalizeString( const char* sString, AZStd::string& outLocalizedString, bool bEnglish=false ) // but at the moment this is faster. - virtual bool LocalizeString_s([[maybe_unused]] const string& sString, [[maybe_unused]] string& outLocalizedString, [[maybe_unused]] bool bEnglish = false) override { return false; } + virtual bool LocalizeString_s([[maybe_unused]] const AZStd::string& sString, [[maybe_unused]] AZStd::string& outLocalizedString, [[maybe_unused]] bool bEnglish = false) override { return false; } // Summary: virtual void LocalizeAndSubstituteInternal([[maybe_unused]] AZStd::string& locString, [[maybe_unused]] const AZStd::vector& keys, [[maybe_unused]] const AZStd::vector& values) override {} @@ -196,7 +196,7 @@ struct ILocalizationManager // bEnglish - if true, returns the always present English version of the label. // Returns: // True if localization was successful, false otherwise. - virtual bool LocalizeLabel([[maybe_unused]] const char* sLabel, [[maybe_unused]] string& outLocalizedString, [[maybe_unused]] bool bEnglish = false) override { return false; } + virtual bool LocalizeLabel([[maybe_unused]] const char* sLabel, [[maybe_unused]] AZStd::string& outLocalizedString, [[maybe_unused]] bool bEnglish = false) override { return false; } virtual bool IsLocalizedInfoFound([[maybe_unused]] const char* sKey) { return false; } // Summary: @@ -251,7 +251,7 @@ struct ILocalizationManager // sLocalizedString - Corresponding english language string. // Returns: // True if successful, false otherwise (key not found). - virtual bool GetEnglishString([[maybe_unused]] const char* sKey, [[maybe_unused]] string& sLocalizedString) override { return false; } + virtual bool GetEnglishString([[maybe_unused]] const char* sKey, [[maybe_unused]] AZStd::string& sLocalizedString) override { return false; } // Summary: // Get Subtitle for Key or Label . @@ -261,21 +261,21 @@ struct ILocalizationManager // bForceSubtitle - If true, get subtitle (sLocalized or sEnglish) even if not specified in Data file. // Returns: // True if subtitle found (and outSubtitle filled in), false otherwise. - virtual bool GetSubtitle([[maybe_unused]] const char* sKeyOrLabel, [[maybe_unused]] string& outSubtitle, [[maybe_unused]] bool bForceSubtitle = false) override { return false; } + virtual bool GetSubtitle([[maybe_unused]] const char* sKeyOrLabel, [[maybe_unused]] AZStd::string& outSubtitle, [[maybe_unused]] bool bForceSubtitle = false) override { return false; } // Description: // These methods format outString depending on sString with ordered arguments // FormatStringMessage(outString, "This is %2 and this is %1", "second", "first"); // Arguments: // outString - This is first and this is second. - virtual void FormatStringMessage_List([[maybe_unused]] string& outString, [[maybe_unused]] const string& sString, [[maybe_unused]] const char** sParams, [[maybe_unused]] int nParams) override {} - virtual void FormatStringMessage([[maybe_unused]] string& outString, [[maybe_unused]] const string& sString, [[maybe_unused]] const char* param1, [[maybe_unused]] const char* param2 = 0, [[maybe_unused]] const char* param3 = 0, [[maybe_unused]] const char* param4 = 0) override {} + virtual void FormatStringMessage_List([[maybe_unused]] AZStd::string& outString, [[maybe_unused]] const AZStd::string& sString, [[maybe_unused]] const char** sParams, [[maybe_unused]] int nParams) override {} + virtual void FormatStringMessage([[maybe_unused]] AZStd::string& outString, [[maybe_unused]] const AZStd::string& sString, [[maybe_unused]] const char* param1, [[maybe_unused]] const char* param2 = 0, [[maybe_unused]] const char* param3 = 0, [[maybe_unused]] const char* param4 = 0) override {} - virtual void LocalizeTime([[maybe_unused]] time_t t, [[maybe_unused]] bool bMakeLocalTime, [[maybe_unused]] bool bShowSeconds, [[maybe_unused]] string& outTimeString) override {} - virtual void LocalizeDate([[maybe_unused]] time_t t, [[maybe_unused]] bool bMakeLocalTime, [[maybe_unused]] bool bShort, [[maybe_unused]] bool bIncludeWeekday, [[maybe_unused]] string& outDateString) override {} - virtual void LocalizeDuration([[maybe_unused]] int seconds, [[maybe_unused]] string& outDurationString) override {} - virtual void LocalizeNumber([[maybe_unused]] int number, [[maybe_unused]] string& outNumberString) override {} - virtual void LocalizeNumber_Decimal([[maybe_unused]] float number, [[maybe_unused]] int decimals, [[maybe_unused]] string& outNumberString) override {} + virtual void LocalizeTime([[maybe_unused]] time_t t, [[maybe_unused]] bool bMakeLocalTime, [[maybe_unused]] bool bShowSeconds, [[maybe_unused]] AZStd::string& outTimeString) override {} + virtual void LocalizeDate([[maybe_unused]] time_t t, [[maybe_unused]] bool bMakeLocalTime, [[maybe_unused]] bool bShort, [[maybe_unused]] bool bIncludeWeekday, [[maybe_unused]] AZStd::string& outDateString) override {} + virtual void LocalizeDuration([[maybe_unused]] int seconds, [[maybe_unused]] AZStd::string& outDurationString) override {} + virtual void LocalizeNumber([[maybe_unused]] int number, [[maybe_unused]] AZStd::string& outNumberString) override {} + virtual void LocalizeNumber_Decimal([[maybe_unused]] float number, [[maybe_unused]] int decimals, [[maybe_unused]] AZStd::string& outNumberString) override {} // Summary: // Returns true if the project has localization configured for use, false otherwise. diff --git a/Code/Legacy/CryCommon/LocalizationManagerBus.h b/Code/Legacy/CryCommon/LocalizationManagerBus.h index 8daca5562a..69ab32cebf 100644 --- a/Code/Legacy/CryCommon/LocalizationManagerBus.h +++ b/Code/Legacy/CryCommon/LocalizationManagerBus.h @@ -99,12 +99,12 @@ public: // bEnglish - if true, translates the string into the always present English language. // Returns: // true if localization was successful, false otherwise - virtual bool LocalizeString_ch(const char* sString, string& outLocalizedString, bool bEnglish = false) = 0; + virtual bool LocalizeString_ch(const char* sString, AZStd::string& outLocalizedString, bool bEnglish = false) = 0; // Summary: // Same as LocalizeString( const char* sString, string& outLocalizedString, bool bEnglish=false ) // but at the moment this is faster. - virtual bool LocalizeString_s(const string& sString, string& outLocalizedString, bool bEnglish = false) = 0; + virtual bool LocalizeString_s(const AZStd::string& sString, AZStd::string& outLocalizedString, bool bEnglish = false) = 0; // Set up system for passing in placeholder data for localized strings // Summary: @@ -138,7 +138,7 @@ public: // bEnglish - if true, returns the always present English version of the label. // Returns: // True if localization was successful, false otherwise. - virtual bool LocalizeLabel(const char* sLabel, string& outLocalizedString, bool bEnglish = false) = 0; + virtual bool LocalizeLabel(const char* sLabel, AZStd::string& outLocalizedString, bool bEnglish = false) = 0; // Summary: // Return number of localization entries. @@ -151,7 +151,7 @@ public: // sLocalizedString - Corresponding english language string. // Returns: // True if successful, false otherwise (key not found). - virtual bool GetEnglishString(const char* sKey, string& sLocalizedString) = 0; + virtual bool GetEnglishString(const char* sKey, AZStd::string& sLocalizedString) = 0; // Summary: // Get Subtitle for Key or Label . @@ -161,21 +161,21 @@ public: // bForceSubtitle - If true, get subtitle (sLocalized or sEnglish) even if not specified in Data file. // Returns: // True if subtitle found (and outSubtitle filled in), false otherwise. - virtual bool GetSubtitle(const char* sKeyOrLabel, string& outSubtitle, bool bForceSubtitle = false) = 0; + virtual bool GetSubtitle(const char* sKeyOrLabel, AZStd::string& outSubtitle, bool bForceSubtitle = false) = 0; // Description: // These methods format outString depending on sString with ordered arguments // FormatStringMessage(outString, "This is %2 and this is %1", "second", "first"); // Arguments: // outString - This is first and this is second. - virtual void FormatStringMessage_List(string& outString, const string& sString, const char** sParams, int nParams) = 0; - virtual void FormatStringMessage(string& outString, const string& sString, const char* param1, const char* param2 = 0, const char* param3 = 0, const char* param4 = 0) = 0; + virtual void FormatStringMessage_List(AZStd::string& outString, const AZStd::string& sString, const char** sParams, int nParams) = 0; + virtual void FormatStringMessage(AZStd::string& outString, const AZStd::string& sString, const char* param1, const char* param2 = 0, const char* param3 = 0, const char* param4 = 0) = 0; - virtual void LocalizeTime(time_t t, bool bMakeLocalTime, bool bShowSeconds, string& outTimeString) = 0; - virtual void LocalizeDate(time_t t, bool bMakeLocalTime, bool bShort, bool bIncludeWeekday, string& outDateString) = 0; - virtual void LocalizeDuration(int seconds, string& outDurationString) = 0; - virtual void LocalizeNumber(int number, string& outNumberString) = 0; - virtual void LocalizeNumber_Decimal(float number, int decimals, string& outNumberString) = 0; + virtual void LocalizeTime(time_t t, bool bMakeLocalTime, bool bShowSeconds, AZStd::string& outTimeString) = 0; + virtual void LocalizeDate(time_t t, bool bMakeLocalTime, bool bShort, bool bIncludeWeekday, AZStd::string& outDateString) = 0; + virtual void LocalizeDuration(int seconds, AZStd::string& outDurationString) = 0; + virtual void LocalizeNumber(int number, AZStd::string& outNumberString) = 0; + virtual void LocalizeNumber_Decimal(float number, int decimals, AZStd::string& outNumberString) = 0; // Summary: // Returns true if the project has localization configured for use, false otherwise. diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/AtomFont.h b/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/AtomFont.h index 7dd2629bd0..7636b45060 100644 --- a/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/AtomFont.h +++ b/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/AtomFont.h @@ -82,7 +82,7 @@ namespace AZ FontFamilyPtr GetFontFamily(const char* fontFamilyName) override; void AddCharsToFontTextures(FontFamilyPtr fontFamily, const char* chars, int glyphSizeX = ICryFont::defaultGlyphSizeX, int glyphSizeY = ICryFont::defaultGlyphSizeY) override; void GetMemoryUsage([[maybe_unused]] ICrySizer* sizer) const override {} - string GetLoadedFontNames() const; + AZStd::string GetLoadedFontNames() const; void OnLanguageChanged() override; void ReloadAllFonts() override; ////////////////////////////////////////////////////////////////////////////////// @@ -124,7 +124,7 @@ namespace AZ //! \param fontFamilyName The name of the font family, or path to a font family file. //! \param outputDirectory Path to loaded font family (no filename), may need resolving with PathUtil::MakeGamePath. //! \param outputFullPath Full path to loaded font family, may need resolving with PathUtil::MakeGamePath. - XmlNodeRef LoadFontFamilyXml(const char* fontFamilyName, string& outputDirectory, string& outputFullPath); + XmlNodeRef LoadFontFamilyXml(const char* fontFamilyName, AZStd::string& outputDirectory, AZStd::string& outputFullPath); // Data::AssetBus::Handler overrides... void OnAssetReady(Data::Asset asset) override; diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/AtomNullFont.h b/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/AtomNullFont.h index ebbdaf09d0..4820d1c176 100644 --- a/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/AtomNullFont.h +++ b/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/AtomNullFont.h @@ -42,7 +42,7 @@ namespace AZ size_t GetTextLength([[maybe_unused]] const char* str, [[maybe_unused]] const bool asciiMultiLine) const override { return 0; } - void WrapText(string& result, [[maybe_unused]] float maxWidth, const char* str, [[maybe_unused]] const TextDrawContext& ctx) override { result = str; } + void WrapText(AZStd::string& result, [[maybe_unused]] float maxWidth, const char* str, [[maybe_unused]] const TextDrawContext& ctx) override { result = str; } void GetMemoryUsage([[maybe_unused]] ICrySizer* sizer) const override {} @@ -76,7 +76,7 @@ namespace AZ virtual FontFamilyPtr GetFontFamily([[maybe_unused]] const char* fontFamilyName) override { CRY_ASSERT(false); return nullptr; } virtual void AddCharsToFontTextures([[maybe_unused]] FontFamilyPtr fontFamily, [[maybe_unused]] const char* chars, [[maybe_unused]] int glyphSizeX, [[maybe_unused]] int glyphSizeY) override {}; virtual void GetMemoryUsage([[maybe_unused]] ICrySizer* sizer) const override {} - virtual string GetLoadedFontNames() const override { return ""; } + virtual AZStd::string GetLoadedFontNames() const override { return ""; } virtual void OnLanguageChanged() override { } virtual void ReloadAllFonts() override { } diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/FFont.h b/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/FFont.h index 7974d0f2c1..6f56d912a0 100644 --- a/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/FFont.h +++ b/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/FFont.h @@ -122,7 +122,7 @@ namespace AZ struct FontEffect { - string m_name; + AZStd::string m_name; std::vector m_passes; FontEffect(const char* name) @@ -178,7 +178,7 @@ namespace AZ void DrawString(float x, float y, float z, const char* str, const bool asciiMultiLine, const TextDrawContext& ctx) override; Vec2 GetTextSize(const char* str, const bool asciiMultiLine, const TextDrawContext& ctx) override; size_t GetTextLength(const char* str, const bool asciiMultiLine) const override; - void WrapText(string& result, float maxWidth, const char* str, const TextDrawContext& ctx) override; + void WrapText(AZStd::string& result, float maxWidth, const char* str, const TextDrawContext& ctx) override; void GetMemoryUsage([[maybe_unused]] ICrySizer* sizer) const override {}; void GetGradientTextureCoord(float& minU, float& minV, float& maxU, float& maxV) const override; unsigned int GetEffectId(const char* effectName) const override; @@ -215,7 +215,7 @@ namespace AZ FFont(AtomFont* atomFont, const char* fontName); FontTexture* GetFontTexture() const { return m_fontTexture; } - const string& GetName() const { return m_name; } + const AZStd::string& GetName() const { return m_name; } FontEffect* AddEffect(const char* effectName); FontEffect* GetDefaultEffect(); @@ -291,8 +291,8 @@ namespace AZ static constexpr uint32_t NumBuffers = 2; static constexpr float WindowScaleWidth = 800.0f; static constexpr float WindowScaleHeight = 600.0f; - string m_name; - string m_curPath; + AZStd::string m_name; + AZStd::string m_curPath; AZ::Name m_dynamicDrawContextName = AZ::Name(AZ::AtomFontDynamicDrawContextName); @@ -341,7 +341,7 @@ namespace AZ FFont* font = const_cast(static_cast(ptr)); if (font && font->m_atomFont) { - font->m_atomFont->UnregisterFont(font->m_name); + font->m_atomFont->UnregisterFont(font->m_name.c_str()); font->m_atomFont = nullptr; } diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/FontRenderer.h b/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/FontRenderer.h index 9f95c12180..3cfb900055 100644 --- a/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/FontRenderer.h +++ b/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/FontRenderer.h @@ -60,7 +60,7 @@ namespace AZ FontRenderer(); ~FontRenderer(); - int LoadFromFile(const string& fileName); + int LoadFromFile(const AZStd::string& fileName); int LoadFromMemory(unsigned char* buffer, int bufferSize); int Release(); diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/FontTexture.h b/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/FontTexture.h index 91fecfa3ef..b9bdce6810 100644 --- a/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/FontTexture.h +++ b/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/FontTexture.h @@ -74,7 +74,7 @@ namespace AZ FontTexture(); ~FontTexture(); - int CreateFromFile(const string& fileName, int width, int height, AZ::FontSmoothMethod smoothMethod, AZ::FontSmoothAmount smoothAmount, int widthCharCount = 16, int heightCharCount = 16); + int CreateFromFile(const AZStd::string& fileName, int width, int height, AZ::FontSmoothMethod smoothMethod, AZ::FontSmoothAmount smoothAmount, int widthCharCount = 16, int heightCharCount = 16); //! Default texture slot width/height is 16x8 slots, allowing for 128 glyphs to be stored in the font texture. This was //! previously 16x16, allowing 256 glyphs to be stored. For reference, there are 95 printable ASCII characters, so by @@ -129,7 +129,7 @@ namespace AZ // useful for special feature rendering interleaved with fonts (e.g. box behind the text) void CreateGradientSlot(); - int WriteToFile(const string& fileName); + int WriteToFile(const AZStd::string& fileName); void GetMemoryUsage([[maybe_unused]] ICrySizer* sizer) const {} diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/GlyphCache.h b/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/GlyphCache.h index cd37cb6b79..8c6cf721b3 100644 --- a/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/GlyphCache.h +++ b/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/GlyphCache.h @@ -79,7 +79,7 @@ namespace AZ int Create(int iCacheSize, int glyphBitmapWidth, int glyphBitmapHeight, FontSmoothMethod smoothMethod, FontSmoothAmount smoothAmount, float sizeRatio); int Release(); - int LoadFontFromFile(const string& fileName); + int LoadFontFromFile(const AZStd::string& fileName); int LoadFontFromMemory(unsigned char* fileBuffer, int dataSize); int ReleaseFont(); diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Source/FFontXML_Internal.h b/Gems/AtomLyIntegration/AtomFont/Code/Source/FFontXML_Internal.h index 2cae7b45ee..ac6d140dfc 100644 --- a/Gems/AtomLyIntegration/AtomFont/Code/Source/FFontXML_Internal.h +++ b/Gems/AtomLyIntegration/AtomFont/Code/Source/FFontXML_Internal.h @@ -36,7 +36,7 @@ namespace AtomFontInternal ELEMENT_PASS_BLEND = 14 }; - inline int GetBlendModeFromString(const string& str, bool dst) + inline int GetBlendModeFromString(const AZStd::string& str, bool dst) { int blend = GS_BLSRC_ONE; @@ -100,7 +100,7 @@ namespace AtomFontInternal ); } - inline AZ::FontSmoothMethod TranslateSmoothMethod(const string& value) + inline AZ::FontSmoothMethod TranslateSmoothMethod(const AZStd::string& value) { AZ::FontSmoothMethod smoothMethod = AZ::FontSmoothMethod::None; if (value == "blur") @@ -179,9 +179,8 @@ namespace AtomFontInternal void FoundElementImpl(); // notify methods - void FoundElement(const string& name) + void FoundElement(const AZStd::string& name) { - //MessageBox(NULL, string("[" + name + "]").c_str(), "FoundElement", MB_OK); // process the previous element switch (m_nElement) { @@ -246,9 +245,8 @@ namespace AtomFontInternal } } - void FoundAttribute(const string& name, const string& value) + void FoundAttribute(const AZStd::string& name, const AZStd::string& value) { - //MessageBox(NULL, string(name + "\n" + value).c_str(), "FoundAttribute", MB_OK); switch (m_nElement) { case ELEMENT_FONT: @@ -388,8 +386,8 @@ namespace AtomFontInternal AZ::FFont::FontEffect* m_effect; AZ::FFont::FontRenderingPass* m_pass; - string m_strFontPath; - string m_strFontEffectPath; + AZStd::string m_strFontPath; + AZStd::string m_strFontEffectPath; vector2l m_FontTexSize; AZ::AtomFont::GlyphSize m_slotSizes; float m_SizeRatio = IFFontConstants::defaultSizeRatio; From 72f808876c9bdaa4127edb2aae4b73e746858baa Mon Sep 17 00:00:00 2001 From: antonmic <56370189+antonmic@users.noreply.github.com> Date: Wed, 28 Jul 2021 16:35:51 -0700 Subject: [PATCH 038/803] Improvements to pass statistics and SRG debugability Signed-off-by: antonmic <56370189+antonmic@users.noreply.github.com> --- .../Atom/RHI.Reflect/ConstantsLayout.h | 5 +- .../Atom/RHI.Reflect/NameIdReflectionMap.h | 9 +++ .../RHI/Code/Include/Atom/RHI/ConstantsData.h | 8 +++ .../Atom/RHI/ShaderResourceGroupData.h | 3 + .../Atom/RHI/ShaderResourceGroupDebug.h | 21 ++++++ .../Source/RHI.Reflect/ConstantsLayout.cpp | 35 ++++++---- .../RHI/Code/Source/RHI/ConstantsData.cpp | 66 +++++++++++++++++++ .../Source/RHI/ShaderResourceGroupData.cpp | 5 ++ .../Source/RHI/ShaderResourceGroupDebug.cpp | 59 +++++++++++++++++ .../Atom/RHI/Code/atom_rhi_public_files.cmake | 2 + .../Include/Atom/RPI.Public/Pass/PassSystem.h | 15 ++++- .../RPI.Public/Pass/PassSystemInterface.h | 41 ++++++++---- .../Include/Atom/RPI.Public/Pass/RasterPass.h | 3 + .../Source/RPI.Public/Pass/PassSystem.cpp | 24 +++++++ .../Source/RPI.Public/Pass/RasterPass.cpp | 7 ++ .../Source/RPI.Public/Pass/RenderPass.cpp | 2 + ...AtomViewportDisplayInfoSystemComponent.cpp | 25 +++---- 17 files changed, 289 insertions(+), 41 deletions(-) create mode 100644 Gems/Atom/RHI/Code/Include/Atom/RHI/ShaderResourceGroupDebug.h create mode 100644 Gems/Atom/RHI/Code/Source/RHI/ShaderResourceGroupDebug.cpp diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI.Reflect/ConstantsLayout.h b/Gems/Atom/RHI/Code/Include/Atom/RHI.Reflect/ConstantsLayout.h index 09415f1bc2..003a7dcd23 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI.Reflect/ConstantsLayout.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI.Reflect/ConstantsLayout.h @@ -81,6 +81,10 @@ namespace AZ //! If validation is disabled, true is always returned. bool ValidateAccess(ShaderInputConstantIndex inputIndex) const; + //! Prints to the console the shader input names specified by input list of indices + //! Will ignore any indices outside of the inputs array bounds + void DebugPrintNames(AZStd::array_view constantList) const; + protected: ConstantsLayout() = default; @@ -94,7 +98,6 @@ namespace AZ AZStd::vector m_inputs; IdReflectionMapForConstants m_idReflection; - AZStd::vector m_intervals; uint32_t m_sizeInBytes = 0; HashValue64 m_hash = InvalidHash; }; diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI.Reflect/NameIdReflectionMap.h b/Gems/Atom/RHI/Code/Include/Atom/RHI.Reflect/NameIdReflectionMap.h index 7756e7d290..b6042ab34c 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI.Reflect/NameIdReflectionMap.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI.Reflect/NameIdReflectionMap.h @@ -68,6 +68,9 @@ namespace AZ /// Return the number of entries size_t Size() const; + // Returns true if size is zero + bool IsEmpty() const; + class NameIdReflectionMapSerializationEvents : public SerializeContext::IEventHandler { @@ -168,6 +171,12 @@ namespace AZ return m_reflectionMap.size(); } + template + bool NameIdReflectionMap::IsEmpty() const + { + return Size() == 0; + } + template void NameIdReflectionMap::Sort() { diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/ConstantsData.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/ConstantsData.h index 5fd10212d4..27bd418b8a 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/ConstantsData.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/ConstantsData.h @@ -84,6 +84,14 @@ namespace AZ //! Returns the constants layout. const ConstantsLayout* GetLayout() const; + //! Returns whether other constant data and this have the same value at the specified shader input index + bool ConstantIsEqual(const ConstantsData& other, ShaderInputConstantIndex inputIndex) const; + + //! Performs a diff between this and input constant data and returns a list of all the shader input indices + //! for which the constants are not the same between the two. If one of the two has more constants than the + //! other, these additional constants will be added to the end of the returned list. + AZStd::vector GetIndicesOfDifferingConstants(const ConstantsData& other) const; + private: enum class ValidateConstantAccessExpect : uint32_t { diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/ShaderResourceGroupData.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/ShaderResourceGroupData.h index a145ba7ece..17ed3a64f1 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/ShaderResourceGroupData.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/ShaderResourceGroupData.h @@ -172,6 +172,9 @@ namespace AZ //! Different platforms might follow different packing rules for the internally-managed SRG constant buffer. AZStd::array_view GetConstantData() const; + //! Returns the underlying ConstantsData struct + const ConstantsData& GetConstantsData() const; + //! Returns the shader resource layout for this group. const ShaderResourceGroupLayout* GetLayout() const; diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/ShaderResourceGroupDebug.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/ShaderResourceGroupDebug.h new file mode 100644 index 0000000000..b81f9e0c0b --- /dev/null +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/ShaderResourceGroupDebug.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ +#pragma once + +namespace AZ +{ + namespace RHI + { + class ConstantsData; + struct DrawItem; + class ShaderResourceGroup; + + void PrintConstantDataDiff(const ShaderResourceGroup& shaderResourceGroup, ConstantsData& referenceData, bool updateReferenceData = false); + void PrintConstantDataDiff(const DrawItem& drawItem, ConstantsData& referenceData, u32 srgBindingSlot, bool updateReferenceData = false); + + } +} diff --git a/Gems/Atom/RHI/Code/Source/RHI.Reflect/ConstantsLayout.cpp b/Gems/Atom/RHI/Code/Source/RHI.Reflect/ConstantsLayout.cpp index 3f9d9d9d63..fa85fbd884 100644 --- a/Gems/Atom/RHI/Code/Source/RHI.Reflect/ConstantsLayout.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI.Reflect/ConstantsLayout.cpp @@ -17,10 +17,9 @@ namespace AZ if (SerializeContext* serializeContext = azrtti_cast(context)) { serializeContext->Class() - ->Version(0) + ->Version(1) // Version 1: Adding debug helper functions to Shader Resource Groups ->Field("m_inputs", &ConstantsLayout::m_inputs) ->Field("m_idReflection", &ConstantsLayout::m_idReflection) - ->Field("m_intervals", &ConstantsLayout::m_intervals) ->Field("m_sizeInBytes", &ConstantsLayout::m_sizeInBytes) ->Field("m_hash", &ConstantsLayout::m_hash); } @@ -42,7 +41,6 @@ namespace AZ { m_inputs.clear(); m_idReflection.Clear(); - m_intervals.clear(); m_sizeInBytes = 0; m_hash = InvalidHash; } @@ -66,11 +64,8 @@ namespace AZ return false; } - // The constant data size is the maximum offset + size from the start of the struct. - constantDataSize = AZStd::max(constantDataSize, constantDescriptor.m_constantByteOffset + constantDescriptor.m_constantByteCount); - - // Add the [min, max) interval for the inline constant. - m_intervals.emplace_back(constantDescriptor.m_constantByteOffset, constantDescriptor.m_constantByteOffset + constantDescriptor.m_constantByteCount); + uint32_t end = constantDescriptor.m_constantByteOffset + constantDescriptor.m_constantByteCount; + constantDataSize = AZStd::max(constantDataSize, end); ++constantInputIndex; m_hash = TypeHash64(constantDescriptor.GetHash(), m_hash); @@ -99,7 +94,10 @@ namespace AZ Interval ConstantsLayout::GetInterval(ShaderInputConstantIndex inputIndex) const { - return m_intervals[inputIndex.GetIndex()]; + const ShaderInputConstantDescriptor& desc = GetShaderInput(inputIndex); + uint32_t start = desc.m_constantByteOffset; + uint32_t end = start + desc.m_constantByteCount; + return Interval(start, end); } const ShaderInputConstantDescriptor& ConstantsLayout::GetShaderInput(ShaderInputConstantIndex inputIndex) const @@ -138,8 +136,8 @@ namespace AZ { if (!m_sizeInBytes) { - AZ_Assert(m_intervals.empty(), "Constants size is not valid."); - return m_intervals.empty(); + AZ_Assert(m_idReflection.IsEmpty(), "Constants size is not valid."); + return m_idReflection.IsEmpty(); } } @@ -148,5 +146,20 @@ namespace AZ return true; } + + void ConstantsLayout::DebugPrintNames(AZStd::array_view constantList) const + { + AZStd::string output; + for (const ShaderInputConstantIndex& constandIdx : constantList) + { + if (constandIdx.GetIndex() < m_inputs.size()) + { + output += m_inputs[constandIdx.GetIndex()].m_name.GetCStr(); + output += " - "; + } + } + AZ_Printf("RHI", output.c_str()); + } + } } diff --git a/Gems/Atom/RHI/Code/Source/RHI/ConstantsData.cpp b/Gems/Atom/RHI/Code/Source/RHI/ConstantsData.cpp index e00896d44e..29d451b4d5 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/ConstantsData.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/ConstantsData.cpp @@ -404,5 +404,71 @@ namespace AZ AZ_Assert(m_layout, "Constants layout is null"); return m_layout.get(); } + + bool ConstantsData::ConstantIsEqual(const ConstantsData& other, ShaderInputConstantIndex inputIndex) const + { + AZStd::array_view myConstans = GetConstantRaw(inputIndex); + AZStd::array_view otherConstans = other.GetConstantRaw(inputIndex); + + // If they point to the same data, they are equal + if (myConstans == otherConstans) + { + return true; + } + + // If they point to data of different size, they are not equal + if (myConstans.size() != otherConstans.size()) + { + return false; + } + + // If they point to differing data of same size, compare the data + // Note: due to small size of data this loop will be faster than a mem compare + for(uint32_t i = 0; i < myConstans.size(); ++i) + { + if (myConstans[i] != otherConstans[i]) + { + return false; + } + } + + // Arrays point to different locations in memory but all bytes match, return true + return true; + } + + AZStd::vector ConstantsData::GetIndicesOfDifferingConstants(const ConstantsData& other) const + { + AZStd::vector differingIndices; + + if (m_layout == nullptr || other.m_layout == nullptr) + { + return differingIndices; + } + + AZStd::array_view myShaderInputs = m_layout->GetShaderInputList(); + AZStd::array_view otherShaderInputs = other.m_layout->GetShaderInputList(); + + size_t minSize = AZStd::min(myShaderInputs.size(), otherShaderInputs.size()); + size_t maxSize = AZStd::max(myShaderInputs.size(), otherShaderInputs.size()); + + for (size_t idx = 0; idx < minSize; ++idx) + { + const ShaderInputConstantIndex inputIndex(idx); + if (!ConstantIsEqual(other, inputIndex)) + { + differingIndices.push_back(inputIndex); + } + } + + // If sizes are different, add difference at the end + for (size_t idx = minSize; idx < maxSize; ++idx) + { + const ShaderInputConstantIndex inputIndex(idx); + differingIndices.push_back(inputIndex); + } + + return differingIndices; + } + } } diff --git a/Gems/Atom/RHI/Code/Source/RHI/ShaderResourceGroupData.cpp b/Gems/Atom/RHI/Code/Source/RHI/ShaderResourceGroupData.cpp index f2b57bf1e5..65499fb57d 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/ShaderResourceGroupData.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/ShaderResourceGroupData.cpp @@ -334,5 +334,10 @@ namespace AZ return m_constantsData.GetConstantData(); } + const ConstantsData& ShaderResourceGroupData::GetConstantsData() const + { + return m_constantsData; + } + } // namespace RHI } // namespace AZ diff --git a/Gems/Atom/RHI/Code/Source/RHI/ShaderResourceGroupDebug.cpp b/Gems/Atom/RHI/Code/Source/RHI/ShaderResourceGroupDebug.cpp new file mode 100644 index 0000000000..4bd8d0aab8 --- /dev/null +++ b/Gems/Atom/RHI/Code/Source/RHI/ShaderResourceGroupDebug.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include +#include +#include + +namespace AZ +{ + namespace RHI + { + + void PrintConstantDataDiff(const ShaderResourceGroup& shaderResourceGroup, ConstantsData& referenceData, bool updateReferenceData) + { + const RHI::ConstantsData& currentData = shaderResourceGroup.GetData().GetConstantsData(); + + AZStd::vector differingIndices = currentData.GetIndicesOfDifferingConstants(referenceData); + + if (differingIndices.size() > 0) + { + AZ_Printf("RHI", "Detected different SRG values for the following fields:\n"); + if (currentData.GetLayout()) + { + currentData.GetLayout()->DebugPrintNames(differingIndices); + } + } + + if (updateReferenceData) + { + referenceData = currentData; + } + } + + void PrintConstantDataDiff(const DrawItem& drawItem, ConstantsData& referenceData, u32 srgBindingSlot, bool updateReferenceData) + { + s32 srgIndex = -1; + for (u32 i = 0; i < drawItem.m_shaderResourceGroupCount; ++i) + { + if (drawItem.m_shaderResourceGroups[i]->GetBindingSlot() == srgBindingSlot) + { + srgIndex = i; + break; + } + } + + if (srgIndex != -1) + { + const ShaderResourceGroup& srg = *drawItem.m_shaderResourceGroups[srgIndex]; + PrintConstantDataDiff(srg, referenceData, updateReferenceData); + } + } + + } +} diff --git a/Gems/Atom/RHI/Code/atom_rhi_public_files.cmake b/Gems/Atom/RHI/Code/atom_rhi_public_files.cmake index b489cbbbb4..2bf2acd892 100644 --- a/Gems/Atom/RHI/Code/atom_rhi_public_files.cmake +++ b/Gems/Atom/RHI/Code/atom_rhi_public_files.cmake @@ -156,10 +156,12 @@ set(FILES Source/RHI/ScopeAttachment.cpp Include/Atom/RHI/ShaderResourceGroup.h Include/Atom/RHI/ShaderResourceGroupData.h + Include/Atom/RHI/ShaderResourceGroupDebug.h Include/Atom/RHI/ShaderResourceGroupInvalidateRegistry.h Include/Atom/RHI/ShaderResourceGroupPool.h Source/RHI/ShaderResourceGroup.cpp Source/RHI/ShaderResourceGroupData.cpp + Source/RHI/ShaderResourceGroupDebug.cpp Source/RHI/ShaderResourceGroupInvalidateRegistry.cpp Source/RHI/ShaderResourceGroupPool.cpp Include/Atom/RHI/MemoryStatisticsBuilder.h diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/PassSystem.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/PassSystem.h index de57e2e3f6..5998798ae8 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/PassSystem.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/PassSystem.h @@ -74,6 +74,12 @@ namespace AZ const AZ::Name& GetTargetedPassDebuggingName() const override; void ConnectEvent(OnReadyLoadTemplatesEvent::Handler& handler) override; PassSystemState GetState() const override; + SwapChainPass* FindSwapChainPass(AzFramework::NativeWindowHandle windowHandle) const override; + + // PassSystemInterface statistics related functions + void IncrementFrameDrawItemCount(u32 numDrawItems) override; + void IncrementFrameRenderPassCount() override; + PassSystemFrameStatistics GetFrameStatistics() override; // PassSystemInterface factory related functions... void AddPassCreator(Name className, PassCreator createFunction) override; @@ -92,7 +98,6 @@ namespace AZ void RegisterPass(Pass* pass) override; void UnregisterPass(Pass* pass) override; AZStd::vector FindPasses(const PassFilter& passFilter) const override; - SwapChainPass* FindSwapChainPass(AzFramework::NativeWindowHandle windowHandle) const override; private: // Returns the root of the pass tree hierarchy @@ -115,6 +120,9 @@ namespace AZ void QueueForRemoval(Pass* pass) override; void QueueForInitialization(Pass* pass) override; + // Resets the frame statistic counters + void ResetFrameStatistics(); + // Lists for queuing passes for various function calls // Name of the list reflects the pass function it will call AZStd::vector< Ptr > m_buildPassList; @@ -140,13 +148,16 @@ namespace AZ AZ::Name m_targetedPassDebugName; // Counts the number of passes - int32_t m_passCounter = 0; + u32 m_passCounter = 0; // Events OnReadyLoadTemplatesEvent m_loadTemplatesEvent; // Used to track what phase of execution the pass system is in PassSystemState m_state = PassSystemState::Unitialized; + + // Counters used to gather statistics about the frame + PassSystemFrameStatistics m_frameStatistics; }; } // namespace RPI } // namespace AZ diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/PassSystemInterface.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/PassSystemInterface.h index cc66a7c228..246e43a2f7 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/PassSystemInterface.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/PassSystemInterface.h @@ -66,6 +66,14 @@ namespace AZ FrameEnd, }; + //! Frame counters used for collecting statistics + struct PassSystemFrameStatistics + { + u32 m_numRenderPassesExecuted = 0; + u32 m_totalDrawItemsRendered = 0; + u32 m_maxDrawItemsRenderedInAPass = 0; + }; + class PassSystemInterface { friend class Pass; @@ -115,6 +123,27 @@ namespace AZ virtual void SetTargetedPassDebuggingName(const AZ::Name& targetPassName) = 0; virtual const AZ::Name& GetTargetedPassDebuggingName() const = 0; + //! Find the SwapChainPass associated with window Handle + virtual SwapChainPass* FindSwapChainPass(AzFramework::NativeWindowHandle windowHandle) const = 0; + + using OnReadyLoadTemplatesEvent = AZ::Event<>; + //! Connect a handler to listen to the event that the pass system is ready to load pass templates + //! The event is triggered when pass system is initialized and asset system is ready. + //! The handler can add new pass templates or load pass template mappings from assets + virtual void ConnectEvent(OnReadyLoadTemplatesEvent::Handler& handler) = 0; + + virtual PassSystemState GetState() const = 0; + + // Passes call this function to notify the pass system that they are drawing X draw items this frame + // Used for Pass System statistics + virtual void IncrementFrameDrawItemCount(u32 numDrawItems) = 0; + + // Increments the counter for the number of render passes executed this frame (does not include passes that are disabled) + virtual void IncrementFrameRenderPassCount() = 0; + + // Get frame statistics from the Pass System + virtual PassSystemFrameStatistics GetFrameStatistics() = 0; + // --- Pass Factory related functionality --- //! Directly creates a pass given a PassDescriptor @@ -171,17 +200,6 @@ namespace AZ //! Find matching passes from registered passes with specified filter virtual AZStd::vector FindPasses(const PassFilter& passFilter) const = 0; - //! Find the SwapChainPass associated with window Handle - virtual SwapChainPass* FindSwapChainPass(AzFramework::NativeWindowHandle windowHandle) const = 0; - - using OnReadyLoadTemplatesEvent = AZ::Event<>; - //! Connect a handler to listen to the event that the pass system is ready to load pass templates - //! The event is triggered when pass system is initialized and asset system is ready. - //! The handler can add new pass templates or load pass template mappings from assets - virtual void ConnectEvent(OnReadyLoadTemplatesEvent::Handler& handler) = 0; - - virtual PassSystemState GetState() const = 0; - private: // These functions are only meant to be used by the Pass class @@ -199,7 +217,6 @@ namespace AZ //! Unregisters the pass with the pass library. Called in the Pass destructor. virtual void UnregisterPass(Pass* pass) = 0; - }; namespace PassSystemEvents diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/RasterPass.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/RasterPass.h index 735b3930c8..b0d941083b 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/RasterPass.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/RasterPass.h @@ -42,6 +42,8 @@ namespace AZ //! Expose shader resource group. ShaderResourceGroup* GetShaderResourceGroup(); + u32 GetDrawItemCount(); + protected: explicit RasterPass(const PassDescriptor& descriptor); @@ -68,6 +70,7 @@ namespace AZ RHI::Viewport m_viewportState; bool m_overrideScissorSate = false; bool m_overrideViewportState = false; + u32 m_drawItemCount = 0; }; } // namespace RPI } // namespace AZ diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/PassSystem.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/PassSystem.cpp index 91cc645947..3092b9ecd0 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/PassSystem.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/PassSystem.cpp @@ -308,6 +308,7 @@ namespace AZ AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzRender); AZ_ATOM_PROFILE_FUNCTION("RPI", "PassSystem: FrameUpdate"); + ResetFrameStatistics(); ProcessQueuedChanges(); m_state = PassSystemState::Rendering; @@ -392,6 +393,29 @@ namespace AZ handler.Connect(m_loadTemplatesEvent); } + void PassSystem::ResetFrameStatistics() + { + m_frameStatistics.m_numRenderPassesExecuted = 0; + m_frameStatistics.m_totalDrawItemsRendered = 0; + m_frameStatistics.m_maxDrawItemsRenderedInAPass = 0; + } + + PassSystemFrameStatistics PassSystem::GetFrameStatistics() + { + return m_frameStatistics; + } + + void PassSystem::IncrementFrameDrawItemCount(u32 numDrawItems) + { + m_frameStatistics.m_totalDrawItemsRendered += numDrawItems; + m_frameStatistics.m_maxDrawItemsRenderedInAPass = AZStd::max(m_frameStatistics.m_maxDrawItemsRenderedInAPass, numDrawItems); + } + + void PassSystem::IncrementFrameRenderPassCount() + { + ++m_frameStatistics.m_numRenderPassesExecuted; + } + // --- Pass Factory Functions --- void PassSystem::AddPassCreator(Name className, PassCreator createFunction) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RasterPass.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RasterPass.cpp index ee38c1e5ef..ae74e355f2 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RasterPass.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RasterPass.cpp @@ -112,6 +112,11 @@ namespace AZ return m_shaderResourceGroup.get(); } + u32 RasterPass::GetDrawItemCount() + { + return m_drawItemCount; + } + // --- Pass behaviour overrides --- void RasterPass::Validate(PassValidationResults& validationResults) @@ -145,6 +150,8 @@ namespace AZ // Draw List m_drawListView = view->GetDrawList(m_drawListTag); + m_drawItemCount = m_drawListView.size(); + PassSystemInterface::Get()->IncrementFrameDrawItemCount(m_drawItemCount); } RenderPass::FrameBeginInternal(params); diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RenderPass.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RenderPass.cpp index 96649573b2..92e6d8b2b6 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RenderPass.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RenderPass.cpp @@ -200,6 +200,8 @@ namespace AZ m_attachmentCopy.lock()->FrameBegin(params); } CollectSrgs(); + + PassSystemInterface::Get()->IncrementFrameRenderPassCount(); } diff --git a/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.cpp b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.cpp index af9fd7fdd8..ef341f8dc8 100644 --- a/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.cpp +++ b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.cpp @@ -229,25 +229,20 @@ namespace AZ::Render AZ::RPI::ViewportContextPtr viewportContext = GetViewportContext(); auto rootPass = viewportContext->GetCurrentPipeline()->GetRootPass(); const RPI::PipelineStatisticsResult stats = rootPass->GetLatestPipelineStatisticsResult(); - AZStd::function)> containingPassCount = [&containingPassCount](const AZ::RPI::Ptr pass) - { - int count = 1; - if (auto passAsParent = pass->AsParent()) - { - for (const auto& child : passAsParent->GetChildren()) - { - count += containingPassCount(child); - } - } - return count; - }; - const int numPasses = containingPassCount(rootPass); + + RPI::PassSystemFrameStatistics passSystemFrameStatistics = AZ::RPI::PassSystemInterface::Get()->GetFrameStatistics(); + DrawLine(AZStd::string::format( - "Total Passes: %d Vertex Count: %lld Primitive Count: %lld", - numPasses, + "RenderPasses: %d Vertex Count: %lld Primitive Count: %lld", + passSystemFrameStatistics.m_numRenderPassesExecuted, aznumeric_cast(stats.m_vertexCount), aznumeric_cast(stats.m_primitiveCount) )); + DrawLine(AZStd::string::format( + "Total Draw Item Count: %d Max Draw Items in a Pass: %d", + passSystemFrameStatistics.m_totalDrawItemsRendered, + passSystemFrameStatistics.m_maxDrawItemsRenderedInAPass + )); } void AtomViewportDisplayInfoSystemComponent::UpdateFramerate() From 56eda61828f9fb9beaf328ad2107de00ffd482f6 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Thu, 29 Jul 2021 15:49:44 -0700 Subject: [PATCH 039/803] remove of UNICODE/_UNICODE Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../WinAPI/AzCore/Debug/Trace_WinAPI.cpp | 4 - .../WinAPI/AzCore/IO/SystemFile_WinAPI.cpp | 115 +----------------- .../Module/DynamicModuleHandle_WinAPI.cpp | 5 - .../AzCore/std/parallel/config_WinAPI.h | 12 +- .../Windows/AzCore/PlatformIncl_Windows.h | 1 + Code/Legacy/CryCommon/AppleSpecific.h | 5 - Code/Legacy/CryCommon/LinuxSpecific.h | 5 - Code/Legacy/CryCommon/platform.h | 2 +- 8 files changed, 5 insertions(+), 144 deletions(-) diff --git a/Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/Debug/Trace_WinAPI.cpp b/Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/Debug/Trace_WinAPI.cpp index d4a0f52941..143bd8f9d0 100644 --- a/Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/Debug/Trace_WinAPI.cpp +++ b/Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/Debug/Trace_WinAPI.cpp @@ -61,16 +61,12 @@ namespace AZ void OutputToDebugger(const char* window, const char* message) { AZ_UNUSED(window); -#ifdef _UNICODE wchar_t messageW[g_maxMessageLength]; size_t numCharsConverted; if (mbstowcs_s(&numCharsConverted, messageW, message, g_maxMessageLength - 1) == 0) { OutputDebugStringW(messageW); } -#else // !_UNICODE - OutputDebugString(message); -#endif // !_UNICODE } } } diff --git a/Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/IO/SystemFile_WinAPI.cpp b/Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/IO/SystemFile_WinAPI.cpp index 090e29a535..15d779017d 100644 --- a/Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/IO/SystemFile_WinAPI.cpp +++ b/Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/IO/SystemFile_WinAPI.cpp @@ -28,7 +28,6 @@ namespace //========================================================================= DWORD GetAttributes(const char* fileName) { -#ifdef _UNICODE wchar_t fileNameW[AZ_MAX_PATH_LEN]; size_t numCharsConverted; if (mbstowcs_s(&numCharsConverted, fileNameW, fileName, AZ_ARRAY_SIZE(fileNameW) - 1) == 0) @@ -39,9 +38,6 @@ namespace { return INVALID_FILE_ATTRIBUTES; } -#else //!_UNICODE - return GetFileAttributes(fileName); -#endif // !_UNICODE } //========================================================================= @@ -51,7 +47,6 @@ namespace //========================================================================= BOOL SetAttributes(const char* fileName, DWORD fileAttributes) { -#ifdef _UNICODE wchar_t fileNameW[AZ_MAX_PATH_LEN]; size_t numCharsConverted; if (mbstowcs_s(&numCharsConverted, fileNameW, fileName, AZ_ARRAY_SIZE(fileNameW) - 1) == 0) @@ -62,9 +57,6 @@ namespace { return FALSE; } -#else //!_UNICODE - return SetFileAttributes(fileName, fileAttributes); -#endif // !_UNICODE } //========================================================================= @@ -76,7 +68,6 @@ namespace // * GetLastError() on Windows-like platforms // * errno on Unix platforms //========================================================================= -#if defined(_UNICODE) bool CreateDirRecursive(wchar_t* dirPath) { if (CreateDirectoryW(dirPath, nullptr)) @@ -112,53 +103,6 @@ namespace } return false; } -#else - bool CreateDirRecursive(char* dirPath) - { - if (CreateDirectory(dirPath, nullptr)) - { - return true; // Created without error - } - DWORD error = GetLastError(); - if (error == ERROR_PATH_NOT_FOUND) - { - // try to create our parent hierarchy - for (size_t i = strlen(dirPath); i > 0; --i) - { - if (dirPath[i] == '/' || dirPath[i] == '\\') - { - char delimiter = dirPath[i]; - dirPath[i] = 0; // null-terminate at the previous slash - bool ret = CreateDirRecursive(dirPath); - dirPath[i] = delimiter; // restore slash - if (ret) - { - // now that our parent is created, try to create again - if (CreateDirectory(dirPath, nullptr)) - { - return true; - } - DWORD creationError = GetLastError(); - if (creationError == ERROR_ALREADY_EXISTS) - { - DWORD attributes = GetFileAttributes(dirPath); - return (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0; - } - return false; - } - return false; - } - } - // if we reach here then there was no parent folder to create, so we failed for other reasons - } - else if (error == ERROR_ALREADY_EXISTS) - { - DWORD attributes = GetFileAttributes(dirPath); - return (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0; - } - return false; - } -#endif static const SystemFile::FileHandleType PlatformSpecificInvalidHandle = INVALID_HANDLE_VALUE; } @@ -208,7 +152,6 @@ bool SystemFile::PlatformOpen(int mode, int platformFlags) CreatePath(m_fileName.c_str()); } -# ifdef _UNICODE wchar_t fileNameW[AZ_MAX_PATH_LEN]; size_t numCharsConverted; m_handle = INVALID_HANDLE_VALUE; @@ -216,9 +159,6 @@ bool SystemFile::PlatformOpen(int mode, int platformFlags) { m_handle = CreateFileW(fileNameW, dwDesiredAccess, dwShareMode, 0, dwCreationDisposition, dwFlagsAndAttributes, 0); } -# else //!_UNICODE - m_handle = CreateFile(m_fileName.c_str(), dwDesiredAccess, dwShareMode, 0, dwCreationDisposition, dwFlagsAndAttributes, 0); -# endif // !_UNICODE if (m_handle == INVALID_HANDLE_VALUE) { @@ -417,7 +357,6 @@ namespace Platform HANDLE hFile; int lastError; -#ifdef _UNICODE wchar_t filterW[AZ_MAX_PATH_LEN]; size_t numCharsConverted; hFile = INVALID_HANDLE_VALUE; @@ -425,39 +364,28 @@ namespace Platform { hFile = FindFirstFile(filterW, &fd); } -#else // !_UNICODE - hFile = FindFirstFile(filter, &fd); -#endif // !_UNICODE if (hFile != INVALID_HANDLE_VALUE) { const char* fileName; -#ifdef _UNICODE char fileNameA[AZ_MAX_PATH_LEN]; fileName = NULL; if (wcstombs_s(&numCharsConverted, fileNameA, fd.cFileName, AZ_ARRAY_SIZE(fileNameA) - 1) == 0) { fileName = fileNameA; } -#else // !_UNICODE - fileName = fd.cFileName; -#endif // !_UNICODE cb(fileName, (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0); // List all the other files in the directory. - while (FindNextFile(hFile, &fd) != 0) + while (FindNextFileW(hFile, &fd) != 0) { -#ifdef _UNICODE fileName = NULL; if (wcstombs_s(&numCharsConverted, fileNameA, fd.cFileName, AZ_ARRAY_SIZE(fileNameA) - 1) == 0) { fileName = fileNameA; } -#else // !_UNICODE - fileName = fd.cFileName; -#endif // !_UNICODE cb(fileName, (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0); } @@ -483,16 +411,12 @@ namespace Platform { HANDLE handle = nullptr; -#ifdef _UNICODE wchar_t fileNameW[AZ_MAX_PATH_LEN]; size_t numCharsConverted; if (mbstowcs_s(&numCharsConverted, fileNameW, fileName, AZ_ARRAY_SIZE(fileNameW) - 1) == 0) { handle = CreateFileW(fileNameW, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); } -#else // !_UNICODE - handle = CreateFileA(fileName, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); -#endif // !_UNICODE if (handle == INVALID_HANDLE_VALUE) { @@ -524,16 +448,12 @@ namespace Platform WIN32_FILE_ATTRIBUTE_DATA data = { 0 }; BOOL result = FALSE; -#ifdef _UNICODE wchar_t fileNameW[AZ_MAX_PATH_LEN]; size_t numCharsConverted; if (mbstowcs_s(&numCharsConverted, fileNameW, fileName, AZ_ARRAY_SIZE(fileNameW) - 1) == 0) { result = GetFileAttributesExW(fileNameW, GetFileExInfoStandard, &data); } -#else // !_UNICODE - result = GetFileAttributesExA(fileName, GetFileExInfoStandard, &data); -#endif // !_UNICODE if (result) { @@ -553,7 +473,6 @@ namespace Platform bool Delete(const char* fileName) { -#ifdef _UNICODE wchar_t fileNameW[AZ_MAX_PATH_LEN]; size_t numCharsConverted; if (mbstowcs_s(&numCharsConverted, fileNameW, fileName, AZ_ARRAY_SIZE(fileNameW) - 1) == 0) @@ -568,20 +487,12 @@ namespace Platform { return false; } -#else // !_UNICODE - if (DeleteFile(fileName) == 0) - { - EBUS_EVENT(FileIOEventBus, OnError, nullptr, fileName, (int)GetLastError()); - return false; - } -#endif // !_UNICODE return true; } bool Rename(const char* sourceFileName, const char* targetFileName, bool overwrite) { -#ifdef _UNICODE wchar_t sourceFileNameW[AZ_MAX_PATH_LEN]; wchar_t targetFileNameW[AZ_MAX_PATH_LEN]; size_t numCharsConverted; @@ -598,13 +509,6 @@ namespace Platform { return false; } -#else // !_UNICODE - if (MoveFileEx(sourceFileName, targetFileName, overwrite ? MOVEFILE_REPLACE_EXISTING : 0) == 0) - { - EBUS_EVENT(FileIOEventBus, OnError, nullptr, sourceFileName, (int)GetLastError()); - return false; - } -#endif // !_UNICODE return true; } @@ -639,7 +543,6 @@ namespace Platform { if (dirName) { -#if defined(_UNICODE) wchar_t dirPath[AZ_MAX_PATH_LEN]; size_t numCharsConverted; if (mbstowcs_s(&numCharsConverted, dirPath, dirName, AZ_ARRAY_SIZE(dirPath) - 1) == 0) @@ -651,18 +554,6 @@ namespace Platform } return success; } -#else - char dirPath[AZ_MAX_PATH_LEN]; - if (azstrcpy(dirPath, AZ_ARRAY_SIZE(dirPath), dirName) == 0) - { - bool success = CreateDirRecursive(dirPath); - if (!success) - { - EBUS_EVENT(FileIOEventBus, OnError, nullptr, dirName, (int)GetLastError()); - } - return success; - } -#endif } return false; } @@ -671,16 +562,12 @@ namespace Platform { if (dirName) { -#if defined(_UNICODE) wchar_t dirNameW[AZ_MAX_PATH_LEN]; size_t numCharsConverted; if (mbstowcs_s(&numCharsConverted, dirNameW, dirName, AZ_ARRAY_SIZE(dirNameW) - 1) == 0) { return RemoveDirectory(dirNameW) != 0; } -#else - return RemoveDirectory(dirName) != 0; -#endif } return false; diff --git a/Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/Module/DynamicModuleHandle_WinAPI.cpp b/Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/Module/DynamicModuleHandle_WinAPI.cpp index cc04fb6bd5..659650d2e2 100644 --- a/Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/Module/DynamicModuleHandle_WinAPI.cpp +++ b/Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/Module/DynamicModuleHandle_WinAPI.cpp @@ -98,7 +98,6 @@ namespace AZ bool alreadyLoaded = false; -# ifdef _UNICODE wchar_t fileNameW[MAX_PATH]; size_t numCharsConverted; errno_t wcharResult = mbstowcs_s(&numCharsConverted, fileNameW, m_fileName.c_str(), AZ_ARRAY_SIZE(fileNameW) - 1); @@ -114,10 +113,6 @@ namespace AZ m_handle = NULL; return LoadStatus::LoadFailure; } -# else //!_UNICODE - alreadyLoaded = NULL != GetModuleHandleA(m_fileName.c_str()); - m_handle = LoadLibraryA(m_fileName.c_str()); -# endif // !_UNICODE if (m_handle) { diff --git a/Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/std/parallel/config_WinAPI.h b/Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/std/parallel/config_WinAPI.h index fe7620c173..fb91e4d503 100644 --- a/Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/std/parallel/config_WinAPI.h +++ b/Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/std/parallel/config_WinAPI.h @@ -75,22 +75,14 @@ extern "C" AZ_DLL_IMPORT HANDLE _stdcall CreateSemaphoreW(LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, LONG lInitialCount, LONG lMaximumCount, LPCWSTR lpName); AZ_DLL_IMPORT BOOL _stdcall ReleaseSemaphore(HANDLE hSemaphore, LONG lReleaseCount, LPLONG lpPreviousCount); #ifndef CreateSemaphore - #ifdef UNICODE - #define CreateSemaphore CreateSemaphoreW - #else - #define CreateSemaphore CreateSemaphoreA - #endif + #define CreateSemaphore CreateSemaphoreW #endif // Event AZ_DLL_IMPORT HANDLE _stdcall CreateEventA(LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset, BOOL bInitialState, LPCSTR lpName); AZ_DLL_IMPORT HANDLE _stdcall CreateEventW(LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset, BOOL bInitialState, LPCWSTR lpName); #ifndef CreateEvent - #ifdef UNICODE - #define CreateEvent CreateEventW - #else - #define CreateEvent CreateEventA - #endif + #define CreateEvent CreateEventW #endif AZ_DLL_IMPORT BOOL _stdcall SetEvent(HANDLE); } diff --git a/Code/Framework/AzCore/Platform/Windows/AzCore/PlatformIncl_Windows.h b/Code/Framework/AzCore/Platform/Windows/AzCore/PlatformIncl_Windows.h index 6adef282eb..f58e772155 100644 --- a/Code/Framework/AzCore/Platform/Windows/AzCore/PlatformIncl_Windows.h +++ b/Code/Framework/AzCore/Platform/Windows/AzCore/PlatformIncl_Windows.h @@ -9,6 +9,7 @@ #pragma once #define WIN32_LEAN_AND_MEAN +#define UNICODE //#define NOGDICAPMASKS //- CC_*, LC_*, PC_*, CP_*, TC_*, RC_ //#define NOVIRTUALKEYCODES //- VK_* //#define NOWINMESSAGES //- WM_*, EM_*, LB_*, CB_* diff --git a/Code/Legacy/CryCommon/AppleSpecific.h b/Code/Legacy/CryCommon/AppleSpecific.h index 4d17c18bac..caf85a8f44 100644 --- a/Code/Legacy/CryCommon/AppleSpecific.h +++ b/Code/Legacy/CryCommon/AppleSpecific.h @@ -192,13 +192,8 @@ typedef WCHAR* LPUWSTR, * PUWSTR; typedef const WCHAR* LPCWSTR, * PCWSTR; typedef const WCHAR* LPCUWSTR, * PCUWSTR; -#ifdef UNICODE typedef LPCWSTR LPCTSTR; typedef LPWSTR LPTSTR; -#else -typedef LPCSTR LPCTSTR; -typedef LPSTR LPTSTR; -#endif typedef DWORD COLORREF; #define RGB(r,g,b) ((COLORREF)(((BYTE)(r)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(b))<<16))) diff --git a/Code/Legacy/CryCommon/LinuxSpecific.h b/Code/Legacy/CryCommon/LinuxSpecific.h index 5fc1f7b801..72673cafe3 100644 --- a/Code/Legacy/CryCommon/LinuxSpecific.h +++ b/Code/Legacy/CryCommon/LinuxSpecific.h @@ -156,13 +156,8 @@ typedef WCHAR* LPUWSTR, * PUWSTR; typedef const WCHAR* LPCWSTR, * PCWSTR; typedef const WCHAR* LPCUWSTR, * PCUWSTR; -#ifdef UNICODE typedef LPCWSTR LPCTSTR; typedef LPWSTR LPTSTR; -#else -typedef LPCSTR LPCTSTR; -typedef LPSTR LPTSTR; -#endif typedef char TCHAR; typedef DWORD COLORREF; diff --git a/Code/Legacy/CryCommon/platform.h b/Code/Legacy/CryCommon/platform.h index 60edf10de9..c040139b5a 100644 --- a/Code/Legacy/CryCommon/platform.h +++ b/Code/Legacy/CryCommon/platform.h @@ -176,7 +176,7 @@ // In Win32 Release we use static linkage #ifdef WIN32 - #if !defined(_RELEASE) || defined(RESOURCE_COMPILER) || defined(EDITOR) || defined(_FORCEDLL) + #if !defined(_RELEASE) || defined(EDITOR) || defined(_FORCEDLL) // All windows targets not in Release built as DLLs. #ifndef _USRDLL #define _USRDLL From f21fc79dc45842c67ce7640b8bf061963ccf78de Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Thu, 29 Jul 2021 15:50:24 -0700 Subject: [PATCH 040/803] remove of unicode files from Cry Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Legacy/CryCommon/UnicodeBinding.h | 946 -------------- Code/Legacy/CryCommon/UnicodeEncoding.h | 767 ----------- Code/Legacy/CryCommon/UnicodeFunctions.h | 1265 ------------------- Code/Legacy/CryCommon/UnicodeIterator.h | 615 --------- Code/Legacy/CryCommon/crycommon_files.cmake | 4 - 5 files changed, 3597 deletions(-) delete mode 100644 Code/Legacy/CryCommon/UnicodeBinding.h delete mode 100644 Code/Legacy/CryCommon/UnicodeEncoding.h delete mode 100644 Code/Legacy/CryCommon/UnicodeFunctions.h delete mode 100644 Code/Legacy/CryCommon/UnicodeIterator.h diff --git a/Code/Legacy/CryCommon/UnicodeBinding.h b/Code/Legacy/CryCommon/UnicodeBinding.h deleted file mode 100644 index aaefcf0f55..0000000000 --- a/Code/Legacy/CryCommon/UnicodeBinding.h +++ /dev/null @@ -1,946 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - -// Note: The utilities in this file should typically not be used directly, -// consider including UnicodeFunctions.h or UnicodeIterator.h instead. -// -// (At least) the following string types can be bound with these helper functions: -// Types Input Output Null-Terminator -// std::basic_string, std::string, std::wstring: yes yes implied by type -// QString: yes yes implied by type -// std::vector, std::list, std::deque: yes yes not present -// T[] (fixed-length buffer): yes yes guaranteed to be emitted on output, accepted on input -// T * and size_t (user-specified-size buffer): no yes guaranteed to be emitted on output -// const T * (null-terminated string): yes no expected -// const T[] (literal): yes no implied as the last item in the array -// pair of iterators over T: yes no should not be included in the range -// uint32 (single UCS code-point): yes no not present -// If some other string type is not listed, you can still use it for input easily by passing begin/end iterators. -// Note: For all types, T can be any 8-bit, 16-bit or 32-bit integral or character type. -// Further T types may be processed by explicitly passing InputEncoding and OutputEncoding. -// We never actively tested such scenario's, so no guarantees on floating and user-defined types as code-units. - - -#pragma once - -#ifndef assert -// Some tools use CRT's assert, most engine and game modules use CryAssert.h (via platform.h maybe). -// We don't want to force a choice upon all code that uses Unicode utilities, so we just assume assert is defined. -#error This header uses assert macro, please provide an applicable definition before including UnicodeXXX.h -#endif - -#include "UnicodeEncoding.h" -#include // For str(n)len and memcpy. -#include // For wcs(n)len. -#include // For size_t and ptrdiff_t. -#include // For std::iterator_traits. -#include // For std::basic_string. -#include // For std::vector. -#include // For std::list. -#include // For std::deque. -#include // ... standard type-traits (as of C++11). - -#if defined(AZ_RESTRICTED_PLATFORM) -#undef AZ_RESTRICTED_SECTION -#define UNICODEBINDING_H_SECTION_1 1 -#define UNICODEBINDING_H_SECTION_2 2 -#endif - -// Forward declare the supported types. -// Before actually instantiating a binding however, you need to have the full definition included. -// Also, this allows us to work with QChar/QString as declared names without a dependency on Qt. -namespace AZStd -{ - template - class basic_fixed_string; -} -class QChar; -class QString; - -namespace Unicode -{ - namespace Detail - { - // Import standard type traits. - // This requires C++11 compiler support. - using std::add_const; - using std::conditional; - using std::extent; - using std::integral_constant; - using std::is_arithmetic; - using std::is_array; - using std::is_base_of; - using std::is_const; - using std::is_convertible; - using std::is_integral; - using std::is_pointer; - using std::is_same; - using std::make_unsigned; - using std::remove_cv; - using std::remove_extent; - using std::remove_pointer; - - // SVoid: - // Result type will be void if T is well-formed. - // Note: This is mostly used to test the presence of member types at compile-time. - template - struct SVoid - { - typedef void type; - }; - - // SValidChar: - // Determine if T is a valid character type in the given compile-time context. - // The InferEncoding flag is set if the encoding has to be detected automatically. - // The Input flag is set if the type is used for input (and not set if the type is used for output). - template - struct SValidChar - { - typedef typename remove_cv::type BaseType; - static const bool isArithmeticType = is_arithmetic::value; - static const bool isQChar = is_same::value; - static const bool isUsable = isArithmeticType || isQChar; - static const bool isValidQualified = !is_const::value || Input; - static const bool isKnownSize = sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4; - static const bool isValidInferred = isKnownSize || !InferEncoding; - static const bool value = isUsable && isValidQualified && isValidInferred; - }; - - // SPackedIterators: - // A pair of iterators over some range. - // Note: Packing iterators into a single object allows us to pass them as a single argument like all other types. - template - struct SPackedIterators - { - const T begin, end; - SPackedIterators(const T& _begin, const T& _end) - : begin(_begin) - , end(_end) {} - }; - - // SPackedBuffer: - // A buffer-pointer/length tuple. - // Note: Packing them into a single object allows us to pass them as a single argument like all other types. - template - struct SPackedBuffer - { - T buffer; - size_t size; - SPackedBuffer(T _buffer, size_t _size) - : buffer(_buffer) - , size(_size) {} - }; - - // SDependentType: - // Makes the name of type T dependent on X (which is otherwise meaningless). - // Note: This is used to force two-phase lookup so we don't need the definition of T until instantiation. - // This way we can convince standards-compliant compilers Clang and GCC to not require definition of forward-declared types. - // Specifically, we forward-declare Qt's QString and QChar, for which the definition will never be available outside Editor. - template - struct SDependentType - { - typedef T type; - }; - - // EBind: - // Methods of binding a type for input and/or output. - // Note: These are used for tag-dispatch by binding functions, and are private to the implementation. - enum EBind - { // Input Output Description - eBind_Impossible, // No No Can't bind this type. - eBind_Iterators, // Yes Yes Bind by using begin() and end() member functions. - eBind_Data, // Yes Yes Bind by using data() and size() member functions. - eBind_Literal, // Yes No Bind a fixed size buffer (const element, aka string literal). - eBind_Buffer, // Yes No Bind a fixed size buffer (non-const element) that may be null-terminated. - eBind_PackedBuffer, // No Yes Bind a user-specified size buffer (non-const element). - eBind_NullTerminated, // Yes No Bind a null-terminated buffer of unknown length (C string). - eBind_CodePoint, // Yes No Bind a single code-point value. - }; - - // SBindIterator: - // Find the EBind for input from iterator pair of type T at compile-time. - // If the type is not supported, the resulting value will be eBind_Impossible - template - struct SBindIterator - { - typedef const void CharType; - static const EBind value = eBind_Impossible; - }; - template - struct SBindIterator - { - typedef typename add_const::type CharType; - static const bool isValid = SValidChar::value; - static const EBind value = isValid ? eBind_Iterators : eBind_Impossible; - }; - template - struct SBindIterator::type, - typename SVoid::type - > - { - typedef typename add_const::type CharType; - typedef typename T::iterator_category IteratorCategory; - static const bool isInputIterator = is_base_of::value; - static const bool isValid = SValidChar::value; - static const EBind value = isValid && isInputIterator ? eBind_Iterators : eBind_Impossible; - }; - - // SBindObject: - // Find the EBind for input from object of type T at compile-time. - // If the type is not supported, the resulting value will be eBind_Impossible. - template - struct SBindObject - { - typedef typename add_const< - typename conditional< - is_array::value, - typename remove_extent::type, - typename remove_pointer::type - >::type - >::type CharType; - static const size_t FixedSize = extent::value; - COMPILE_TIME_ASSERT(!is_array::value || FixedSize > 0); - static const bool isConstArray = is_array::value && is_const::type>::value; - static const bool isBufferArray = is_array::value && !isConstArray; - static const bool isPointer = is_pointer::value; - static const bool isCodePoint = is_integral::value; - static const bool isValidChar = SValidChar::value; - static const EBind value = - !isValidChar ? eBind_Impossible : - isConstArray ? eBind_Literal : - isBufferArray ? eBind_Buffer : - isPointer ? eBind_NullTerminated : - isCodePoint ? eBind_CodePoint : - eBind_Impossible; - }; - template - struct SBindObject, InferEncoding> - { - typedef typename add_const::type CharType; - static const bool isValid = SValidChar::value; - static const EBind value = isValid ? eBind_Data : eBind_Impossible; - }; - template - struct SBindObject, InferEncoding> - { - typedef typename add_const::type CharType; - static const bool isValid = SValidChar::value; - static const EBind value = isValid ? eBind_Data : eBind_Impossible; - }; - template - struct SBindObject, InferEncoding> - { - typedef typename add_const::type CharType; - static const bool isValid = SValidChar::value; - static const EBind value = isValid ? eBind_Iterators : eBind_Impossible; - }; - template - struct SBindObject, InferEncoding> - { - typedef typename add_const::type CharType; - static const bool isValid = SValidChar::value; - static const EBind value = isValid ? eBind_Iterators : eBind_Impossible; - }; - template - struct SBindObject, InferEncoding> - { - typedef typename add_const::type CharType; - static const bool isValid = SValidChar::value; - static const EBind value = isValid ? eBind_Data : eBind_Impossible; - }; - template - struct SBindObject, InferEncoding> - { - typedef wchar_t CharType; - static const bool isValid = SValidChar::value; - static const EBind value = isValid ? eBind_Data : eBind_Impossible; - }; - template - struct SBindObject - { - typedef const QChar CharType; - static const EBind value = eBind_Data; - }; - template - struct SBindObject, InferEncoding> - { - typedef typename SBindIterator::CharType CharType; - static const EBind value = eBind_Iterators; - }; - - // SBindOutput: - // Find the EBind for output to object of type T at compile-time. - // If the type is not supported, the resulting value will be eBind_Impossible. - template - struct SBindOutput - { - typedef typename remove_extent::type CharType; - static const size_t FixedSize = extent::value; - static const bool isArray = is_array::value; - static const bool isValid = SValidChar::type, InferEncoding, false>::value; - static const EBind value = isArray && isValid ? eBind_Buffer : eBind_Impossible; - }; - template - struct SBindOutput, InferEncoding> - { - typedef OutputCharType CharType; - static const bool isValid = SValidChar::value; - static const EBind value = isValid ? eBind_PackedBuffer : eBind_Impossible; - }; - template - struct SBindOutput, InferEncoding> - { - typedef CharT CharType; - static const bool isValid = SValidChar::value; - static const EBind value = isValid ? eBind_Data : eBind_Impossible; - }; - template - struct SBindOutput, InferEncoding> - { - typedef T CharType; - static const bool isValid = SValidChar::value; - static const EBind value = isValid ? eBind_Data : eBind_Impossible; - }; - template - struct SBindOutput, InferEncoding> - { - typedef T CharType; - static const bool isValid = SValidChar::value; - static const EBind value = isValid ? eBind_Iterators : eBind_Impossible; - }; - template - struct SBindOutput, InferEncoding> - { - typedef T CharType; - static const bool isValid = SValidChar::value; - static const EBind value = isValid ? eBind_Iterators : eBind_Impossible; - }; - template - struct SBindOutput, InferEncoding> - { - typedef T CharType; - static const bool isValid = SValidChar::value; - static const EBind value = isValid ? eBind_Data : eBind_Impossible; - }; - template - struct SBindOutput - { - typedef QChar CharType; - static const EBind value = eBind_Data; - }; - - // SInferEncoding: - // Infers the encoding of the given character type. - // Note: This will always pick an UTF encoding type based on the size of the element type. - template - struct SInferEncoding - { - typedef SBindObject ObjectType; - typedef SBindIterator IteratorType; - typedef typename conditional< - IteratorType::value != eBind_Impossible, - typename IteratorType::CharType, - typename ObjectType::CharType - >::type CharType; - static const EEncoding value = - sizeof(CharType) == 1 ? eEncoding_UTF8 : - sizeof(CharType) == 2 ? eEncoding_UTF16 : - eEncoding_UTF32; - COMPILE_TIME_ASSERT(value != eEncoding_UTF32 || sizeof(CharType) == 4); - }; - - // SBindCharacter: - // Pick the base character type to use during input or output with this element type. - template::value, bool IsQChar = is_same::type>::value> - struct SBindCharacter - { - typedef typename make_unsigned::type BaseType; // The standard doesn't define if a character type is signed or unsigned. - typedef typename remove_cv::type UnqualifiedType; - typedef typename conditional::type type; - }; - template - struct SBindCharacter - { - COMPILE_TIME_ASSERT(is_arithmetic::value); - typedef typename remove_cv::type UnqualifiedType; - typedef typename conditional::type type; - }; - template - struct SBindCharacter - { - typedef typename conditional::type type; - typedef typename SDependentType::type ActuallyQChar; // Force two-phase name lookup on QChar. - COMPILE_TIME_ASSERT(sizeof(ActuallyQChar) == sizeof(type)); // In case Qt ever changes QChar. - }; - - // SBindPointer: - // Pick the pointer type to use during input or output with buffers (potentially inside string types). - template - struct SBindPointer - { - COMPILE_TIME_ASSERT(is_pointer::value || is_array::value); - typedef typename conditional< - is_pointer::value, - typename remove_pointer::type, - typename remove_extent::type - >::type UnboundCharType; - typedef typename SBindCharacter::type BoundCharType; - typedef BoundCharType* type; - }; - - // SAutomaticallyDeduced: - // Placeholder type that is never defined, used by SRequire for SFINAE overloading. - struct SAutomaticallyDeduced; - - // SRequire: - // Helper for SFINAE overloading. - // Similar to C++11's std::enable_if, which is not in boost (with that exact name anyway). - template - struct SRequire - { - typedef T type; - }; - template - struct SRequire {}; - - // SafeCast: - // Cast a pointer to type T, but only allowing safe casts. - // This guards against bad code in other functions since it prevents unintended casts. - template - inline T SafeCast(SourceChar* ptr, typename SRequire::value>::type* = 0) - { - // Allow casts from pointer-to-integral to unrelated pointer-to-integral, provided they are of the same size. - typedef typename remove_pointer::type TargetChar; - COMPILE_TIME_ASSERT(is_integral::value && is_integral::value); - COMPILE_TIME_ASSERT(sizeof(SourceChar) == sizeof(TargetChar)); - return reinterpret_cast(ptr); - } - template - inline T SafeCast(SourceChar* ptr, typename SRequire::type, QChar>::value>::type* = 0) - { - // Allow casts from pointer-to-QChar to unrelated pointer-to-integral, provided they are of the same size. - typedef typename remove_pointer::type TargetChar; - COMPILE_TIME_ASSERT(is_integral::value); - COMPILE_TIME_ASSERT(sizeof(SourceChar) == sizeof(TargetChar)); - return reinterpret_cast(ptr); - } - template - inline T SafeCast(SourceChar* ptr, typename SRequire::value&& !is_same::type, QChar>::value>::type* = 0) - { - // Any other casts that are allowed by C++. - return static_cast(ptr); - } - - // SCharacterTrait: - // Exposes some basic traits for a given character. - // Note: Map to (hopefully optimized) CRT functions where possible. - template::value> - struct SCharacterTrait - { - static size_t StrLen(const T* nts) // Fall-back strlen. - { - size_t result = 0; - while (*nts != 0) - { - ++nts; - ++result; - } - return result; - } - static size_t StrNLen(const T* ptr, size_t len) // Fall-back strnlen. - { - size_t result = 0; - while (*ptr != 0 && result != len) - { - ++ptr; - ++result; - } - return result; - } - }; - template - struct SCharacterTrait - { - static size_t StrLen(const T* nts) // Narrow CRT strlen. - { - return ::strlen(SafeCast(nts)); - } - static size_t StrNLen(const T* ptr, size_t len) // Narrow CRT strnlen. - { - return ::strnlen(SafeCast(ptr), len); - } - }; - template - struct SCharacterTrait - { - static size_t StrLen(const T* nts) // Wide CRT strlen. - { - return ::wcslen(SafeCast(nts)); - } - static size_t StrNLen(const T* ptr, size_t len) // Wide CRT strnlen. - { -#if defined(AZ_RESTRICTED_PLATFORM) - #define AZ_RESTRICTED_SECTION UNICODEBINDING_H_SECTION_1 - #include AZ_RESTRICTED_FILE(UnicodeBinding_h) -#endif - return ::wcsnlen(SafeCast(ptr), len); -#if defined(AZ_RESTRICTED_PLATFORM) - #define AZ_RESTRICTED_SECTION UNICODEBINDING_H_SECTION_2 - #include AZ_RESTRICTED_FILE(UnicodeBinding_h) -#endif - } - }; - - // void Feed(const SPackedIterators &its, Sink &out, tag): - // Feeds the provided sink from provided packed iterator-range. - template - inline void Feed(const SPackedIterators& its, Sink& out, integral_constant) - { - typedef typename std::iterator_traits::value_type UnboundCharType; - typedef typename SBindCharacter::type BoundCharType; - for (InputIteratorType it = its.begin; it != its.end; ++it) - { - const UnboundCharType unbound = *it; - const BoundCharType bound = static_cast(unbound); - const uint32 item = static_cast(bound); - out(item); - } - } - - // void Feed(const SPackedIterators &its, Sink &out, tag): - // Feeds the provided sink from provided packed pointer-range. - // This is slightly better code-generation than using generic iterators. - template - inline void Feed(const SPackedIterators& its, Sink& out, integral_constant) - { - typedef typename SBindPointer::type PointerType; - assert(reinterpret_cast(its.begin) <= reinterpret_cast(its.end) && "Invalid range specified"); - const size_t length = its.end - its.begin; - PointerType ptr = SafeCast(its.begin); - assert((ptr || !length) && "Passed a non-empty range containing a null-pointer"); - for (size_t i = 0; i < length; ++i, ++ptr) - { - const uint32 item = static_cast(*ptr); - out(item); - } - } - - // void Feed(const InputStringType &in, Sink &out, tag): - // Feeds the provided sink from a container, using it's iterators. - // Note: Dispatches to one of the packed-range overloads. - template - inline void Feed(const InputStringType& in, Sink& out, integral_constant tag) - { - typedef typename InputStringType::const_iterator IteratorType; - Detail::SPackedIterators its(in.begin(), in.end()); - Feed(its, out, tag); - } - - // void Feed(const InputStringType &in, Sink &out, tag): - // Feeds the provided sink from a string-object's buffer. - template - inline void Feed(const InputStringType& in, Sink& out, integral_constant) - { - typedef typename InputStringType::size_type SizeType; - typedef typename InputStringType::value_type ValueType; - typedef typename SBindPointer::type PointerType; - const SizeType length = in.size(); - if (length) - { - PointerType ptr = SafeCast(in.data()); - for (SizeType i = 0; i < length; ++i, ++ptr) - { - const uint32 item = static_cast(*ptr); - out(item); - } - } - } - - // void Feed(const InputStringType &in, Sink &out, tag): - // Feeds the provided sink from a string-literal. - // Note: The literal is assumed to be null-terminated. - // It's possible that a const-element fixed-size-buffer is mistaken as a literal. - // However, we expect no-one uses such buffers that are not null-terminated already. - // If somehow this use-case is desired, either terminate the buffer, or remove const from the buffer, or pass iterators. - template - inline void Feed(const InputStringType& in, Sink& out, integral_constant) - { - COMPILE_TIME_ASSERT(is_array::value && extent::value > 0); - typedef typename SBindPointer::type PointerType; - const size_t length = extent::value - 1; - PointerType ptr = SafeCast(in); - assert(ptr[length] == 0 && "Literal is not null-terminated"); - for (size_t i = 0; i < length; ++i, ++ptr) - { - const uint32 item = static_cast(*ptr); - out(item); - } - } - - // void Feed(const InputStringType &in, Sink &out, tag): - // Feeds the provided sink from a non-const-element fixed-size buffer. - // Note: The buffer is allowed to be null-terminated, but it's not required. - template - inline void Feed(const InputStringType& in, Sink& out, integral_constant) - { - COMPILE_TIME_ASSERT(is_array::value && extent::value > 0); - typedef typename SBindPointer::type PointerType; - typedef typename SBindPointer::BoundCharType CharType; - const size_t length = extent::value; - PointerType ptr = SafeCast(in); - for (size_t i = 0; i < length; ++i, ++ptr) - { - const CharType unbound = *ptr; - if (unbound == 0) - { - break; - } - const uint32 item = static_cast(unbound); - out(item); - } - } - - // void Feed(const InputStringType &in, Sink &out, tag): - // Feeds the provided sink from a null-terminated C-style string. - template - inline void Feed(const InputStringType& in, Sink& out, integral_constant) - { - COMPILE_TIME_ASSERT(is_pointer::value); - typedef typename SBindPointer::type PointerType; - typedef typename SBindPointer::BoundCharType CharType; - PointerType ptr = SafeCast(in); - if (ptr) - { - while (true) - { - const CharType unbound = *ptr; - ++ptr; - if (unbound == 0) - { - break; - } - const uint32 item = static_cast(unbound); - out(item); - } - } - } - - // void Feed(const InputCharType &in, Sink &out, tag): - // Feeds the provided sink from a single value (interpreted as an UCS code-point). - template - inline void Feed(const InputCharType& in, Sink& out, integral_constant) - { - COMPILE_TIME_ASSERT(is_arithmetic::value); - const uint32 item = static_cast(in); - out(item); - } - - // size_t EncodedLength(const SPackedIterators &its, tag): - // Determines the length of the input sequence in a range of iterators. - template - inline size_t EncodedLength(const SPackedIterators& its, integral_constant) - { - return std::distance(its.begin, its.end); // std::distance will pick optimal implementation depending on iterator category. - } - - // size_t EncodedLength(const InputStringType &in, tag): - // Determines the length of an input container, which would otherwise be enumerated with iterators. - template - inline size_t EncodedLength(const InputStringType& in, integral_constant) - { - return in.size(); // Can there be a container without size()? At the very least, not in the supported types. - } - - // size_t EncodedLength(const InputStringType &in, tag): - // Determines the length of the input container. The container uses contiguous element layout. - template - inline size_t EncodedLength(const InputStringType& in, integral_constant) - { - return in.size(); - } - - // size_t EncodedLength(const InputStringType &in, tag): - // Determines the length of the input string-literal. This is a compile-time constant. - template - inline size_t EncodedLength(const InputStringType& in, integral_constant) - { - COMPILE_TIME_ASSERT(is_array::value && extent::value > 0); - return extent::value - 1; - } - - // size_t EncodedLength(const InputStringType &in, tag): - // Determines the length of the input fixed-size-buffer. We look for an (optional) null-terminator in the buffer. - template - inline size_t EncodedLength(const InputStringType& in, integral_constant) - { - COMPILE_TIME_ASSERT(is_array::value && extent::value > 0); - typedef typename remove_extent::type CharType; - return SCharacterTrait::StrNLen(in, extent::value); - } - - // size_t EncodedLength(const InputStringType &in, tag): - // Determines the length of the input used-specified buffer. We look for an (optional) null-terminator in the buffer. - template - inline size_t EncodedLength(const SPackedBuffer& in, integral_constant) - { - return in.buffer ? SCharacterTrait::StrNLen(in.buffer, in.size) : 0; - } - - // size_t EncodedLength(const InputStringType &in, tag): - // Determines the length of the input null-terminated c-style string. We just use strlen() if available. - template - inline size_t EncodedLength(const InputStringType& in, integral_constant) - { - COMPILE_TIME_ASSERT(is_pointer::value); - typedef typename remove_pointer::type CharType; - return in ? SCharacterTrait::StrLen(in) : 0; - } - - // size_t EncodedLength(const InputCharType &in, tag): - // Determines the length of a single UCS code-point. This is always 1. - template - inline size_t EncodedLength([[maybe_unused]] const InputCharType& in, integral_constant) - { - COMPILE_TIME_ASSERT(is_arithmetic::value); - return 1; - } - - // const void *EncodedPointer(const SPackedIterators &its, tag): - // Get a pointer to contiguous storage for an iterator range. - // Note: This can only work if the iterators are pointers, or the storage won't be guaranteed contiguous. - template - inline const void* EncodedPointer(const SPackedIterators& its, integral_constant) - { - return its.begin; - } - - // const void *EncodedPointer(const InputStringType &in, tag): - // Get a pointer to contiguous storage for string/vector object. - // Note: This can only work for containers that actually use contiguous storage, which is determined by the SBindXXX helpers. - template - inline const void* EncodedPointer(const InputStringType& in, integral_constant) - { - return in.data(); - } - - // const void *EncodedPointer(const InputStringType &in, tag): - // Get a pointer to contiguous storage for a string-literal. - template - inline const void* EncodedPointer(const InputStringType& in, integral_constant) - { - COMPILE_TIME_ASSERT(is_array::value && extent::value > 0); - return in; // We can just let the array type decay to a pointer. - } - - // const void *EncodedPointer(const InputStringType &in, tag): - // Get a pointer to contiguous storage for a fixed-size-buffer. - template - inline const void* EncodedPointer(const InputStringType& in, integral_constant) - { - COMPILE_TIME_ASSERT(is_array::value && extent::value > 0); - return in; // We can just let the array type decay to a pointer. - } - - // const void *EncodedPointer(const InputStringType &in, tag): - // Get a pointer to contiguous storage for a null-terminated c-style-string. - template - inline const void* EncodedPointer(const InputStringType& in, integral_constant) - { - COMPILE_TIME_ASSERT(is_pointer::value); - return in; // Implied - } - - // const void *EncodedPointer(const InputCharType &in, tag): - // Get a pointer to contiguous storage for a single UCS code-point. - template - inline const void* EncodedPointer(const InputCharType& in, integral_constant) - { - COMPILE_TIME_ASSERT(is_arithmetic::value); - return ∈ // Take the address of the parameter (which is kept on the stack of the caller). - } - - // SWriteSink: - // A helper that performs writing to the type T and can be passed as Sink type to a trans-coder helper. - template - struct SWriteSink; - template - struct SWriteSink - { - typedef typename T::value_type OutputCharType; - T& out; - SWriteSink(T& _out, size_t) - : out(_out) - { - if (!Append) - { - // If not appending, clear the object beforehand. - out.clear(); - } - } - void operator()(uint32 item) - { - const OutputCharType bound = static_cast(item); - out.push_back(bound); // We assume this can't fail and STL container takes care of memory. - } - void operator()(const void*, size_t); // Not implemented. - void HintSequence(uint32 length) {} // Don't care about sequences. - bool CanWrite() const { return true; } // Always writable - }; - template - struct SWriteSink - { - typedef SBindPointer BindHelper; - typedef typename BindHelper::UnboundCharType CharType; - CharType* ptr; - SWriteSink(T& out, size_t length) - { - const size_t offset = Append ? out.size() : 0; - length += offset; - out.resize(length); // resize() can't fail without exceptions, so assert instead. - assert((out.size() == length) && "Buffer resize failed (out-of-memory?)"); - const CharType* base = length ? out.data() : 0; - ptr = const_cast(base + offset); - } - void operator()(uint32 item) - { - *SafeCast(ptr) = static_cast(item); - ++ptr; - } - void operator()(const void* src, size_t length) - { - ::memcpy(ptr, src, length * sizeof(CharType)); - ptr += length; - } - void HintSequence([[maybe_unused]] uint32 length) {} // Don't care about sequences. - bool CanWrite() const { return true; } // Always writable - }; - template - struct SWriteSink, Append, eBind_PackedBuffer> - { - typedef typename remove_pointer

::type ElementType; - typedef SBindPointer BindHelper; - typedef typename BindHelper::UnboundCharType CharType; - CharType* ptr; - CharType* const terminator; - SWriteSink(CharType* _terminator) - : terminator(_terminator) {} - SWriteSink(SPackedBuffer

& out, size_t) - : terminator(out.size && out.buffer ? out.buffer + out.size - 1 : 0) - { - const size_t offset = Append - ? EncodedLength(out, integral_constant()) - : 0; - const size_t fixedOffset = Append && offset >= out.size - ? out.size - 1 // In case the buffer is already full and not terminated. - : offset; - CharType* base = static_cast(out.buffer); - ptr = terminator ? base + fixedOffset : 0; - } - ~SWriteSink() - { - if (ptr) - { - *ptr = 0; // Guarantees that the output is null-terminated. - } - } - void operator()(uint32 item) - { - if (ptr != terminator) // Guarantees we don't overflow the buffer. - { - *SafeCast(ptr) = static_cast(item); - ++ptr; - } - } - void operator()(const void* src, size_t length) - { - const size_t maxLength = terminator - ptr; - if (length > maxLength) - { - length = maxLength; - } - ::memcpy(ptr, src, length * sizeof(CharType)); - ptr += length; - } - void HintSequence(uint32 length) - { - if (terminator && (ptr + length >= terminator)) - { - // This sequence will overflow the buffer. - // In this case, we prefer to not generate any part of the sequence. - // Terminate at the current position and flag as full. - *ptr = 0; - ptr = terminator; - } - } - bool CanWrite() const - { - return terminator != ptr; - } - }; - template - struct SWriteSink // Uses above implementation with specialized constructor - : SWriteSink::type*>, Append, eBind_PackedBuffer> - { - typedef typename remove_extent::type ElementType; - typedef SWriteSink, Append, eBind_PackedBuffer> Super; - typedef SBindPointer BindHelper; - typedef typename BindHelper::UnboundCharType CharType; - SWriteSink(T& out, size_t) - : Super(out + extent::value - 1) - { - const size_t offset = Append - ? EncodedLength(out, integral_constant()) - : 0; - const size_t fixedOffset = Append && offset >= extent::value - ? extent::value - 1 // In case the buffer is already full and not terminated. - : offset; - Super::ptr = out + fixedOffset; // Qualification for Super required for two-phase lookup. - } - }; - - // SIsBlockCopyable: - // Check if block-copy optimization is possible for these types. - // InputType should be an instantiation of SBindObject or SBindIterator. - // OutputType should be an instantiation of SBindOutput. - // Note: This doesn't take into account safe/unsafe conversions, just if the underlying storage types are compatible. - template - struct SIsBlockCopyable - { - template - struct SIsContiguous - { - static const bool value = - M == eBind_Data || - M == eBind_Literal || - M == eBind_Buffer || - M == eBind_PackedBuffer || - M == eBind_NullTerminated || - M == eBind_CodePoint; - }; - template - struct SIsPointers - { - static const bool value = false; - }; - template - struct SIsPointers > - { - static const bool value = true; - }; - typedef typename SBindCharacter::type InputCharType; - typedef typename SBindCharacter::type OutputCharType; - static const bool isIntegral = is_integral::value && is_integral::value; - static const bool isSameSize = sizeof(InputCharType) == sizeof(OutputCharType); - static const bool isInputContiguous = (SIsContiguous::value || SIsPointers::value); - static const bool isOutputContiguous = (SIsContiguous::value || SIsPointers::value); - static const bool value = isIntegral && isSameSize && isInputContiguous && isOutputContiguous; - }; - } -} diff --git a/Code/Legacy/CryCommon/UnicodeEncoding.h b/Code/Legacy/CryCommon/UnicodeEncoding.h deleted file mode 100644 index a3e20b639c..0000000000 --- a/Code/Legacy/CryCommon/UnicodeEncoding.h +++ /dev/null @@ -1,767 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - -// Description : Generic Unicode encoding helpers. -// -// Defines encoding and decoding functions used by the higher-level functions. -// These are used by the various conversion functions in UnicodeFunctions.h and UnicodeIterator.h. -// Note: You can use these functions manually for low-level functionality, but we don't recommend that. -// In that case, you probably want to check inside the nested Detail namespace for the elementary bits. - - -#pragma once -#include "BaseTypes.h" // For uint8, uint16, uint32 -#include "CompileTimeAssert.h" // For COMPILE_TIME_ASSERT macro -namespace Unicode -{ - // Supported encoding/conversion types. - enum EEncoding - { - // UTF-8 encoding, see http://www.unicode.org/resources/utf8.html. - // Input and output are supported. - // Note: This format maps the entire UCS, where each code-point can take [1, 4] 8-bit code-units. - // Note: This is a strict super-set of Latin1/ISO-885901 as well as ASCII. - eEncoding_UTF8, - - // UTF-16 encoding, see http://tools.ietf.org/html/rfc2781. - // Input and output are supported. - // Note: This format maps the entire UCS, where each code-point can take [1, 2] 16-bit code-units. - eEncoding_UTF16, - - // UTF-32 encoding, see http://www.unicode.org/reports/tr17/. - // Input and output are supported. - // Note: This format maps the entire UCS, each code-point is stored in a single 32-bit code-unit. - eEncoding_UTF32, - - // ASCII encoding, see http://en.wikipedia.org/wiki/ASCII. - // Input and output are supported (any output UCS values out of supported range are mapped to question mark). - // Note: Only values [U+0000, U+007F] can be mapped. - eEncoding_ASCII, - - // Latin1, aka ISO-8859-1 encoding, see http://en.wikipedia.org/wiki/ISO/IEC_8859-1. - // Only input is supported. - // Note: This is a strict super-set of ASCII, it additionally maps [U+00A0, U+00FF]. - eEncoding_Latin1, - - // Windows ANSI codepage 1252, see http://en.wikipedia.org/wiki/Windows-1252. - // Only input is supported. - // Note: This is a strict super-set of ASCII and Latin1/ISO-8859-1, it maps some code-units from [0x80, 0x9F]. - eEncoding_Win1252, - }; - - // Methods of recovery from invalid encoded sequences. - enum EErrorRecovery - { - // No attempt to detect invalid encoding is performed, the input is assumed to be valid. - // If the input is not valid, the output is undefined (in debug, this condition will cause an assert to trigger). - eErrorRecovery_None, - - // When an invalidly encoded sequence is detected, the sequence is discarded (will not be part of the output). - // Typically used for logic/hashing purposes when the input is almost certainly valid. - eErrorRecovery_Discard, - - // When an invalidly encoded sequence is detected, the sequence is replaced with the replacement-character (U+FFFD). - // Typically used when the output sequence is used for UI display purposes. - eErrorRecovery_Replace, - - // When an invalidly encoded sequence is detected, the sequence is replaced with the eEncoding_Latin1 equivalent. - // If the sequence is also not valid Latin1 encoded, the sequence is discarded. - // Typically used when reading generic text files with 1-byte code-units. - // Note: This recovery method can only be used when decoding UTF-8. - eErrorRecovery_FallbackLatin1ThenDiscard, - - // When an invalidly encoded sequence is detected, the sequence is replaced with the eEncoding_Win1252 equivalent. - // If the sequence is also not valid codepage 1252 encoded, the sequence is discarded. - // Typically used when reading text files generated on Windows with 1-byte code-units. - // Note: This recovery method can only be used when decoding UTF-8. - eErrorRecovery_FallbackWin1252ThenDiscard, - - // When an invalidly encoded sequence is detected, the sequence is replaced with the eEncoding_Latin1 equivalent. - // If the sequence is also not valid Latin1 encoded, it is replaced with the replacement-character (U+FFFD). - // Typically used when reading generic text files with 1-byte code-units. - // Note: This recovery method can only be used when decoding UTF-8. - eErrorRecovery_FallbackLatin1ThenReplace, - - // When an invalidly encoded sequence is detected, the sequence is replaced with the eEncoding_Win1252 equivalent. - // If the sequence is also not valid codepage 1252 encoded, it is replaced with the replacement-character (U+FFFD). - // Typically used when reading text files generated on Windows with 1-byte code-units. - // Note: This recovery method can only be used when decoding UTF-8. - eErrorRecovery_FallbackWin1252ThenReplace, - }; - - namespace Detail - { - // Decode(state, unit): Decodes a single code-unit of an encoding into an UCS code-point. - // When Safe flag is set, encoding errors are detected so a fall-back encoding or other recovery method can be used. - // Interpret return value as follows: - // < 0x001FFFFF: Decoded codepoint (== return value), call again with next code-unit and clear state. - // < 0x80000000: Intermediate state returned, call again with next code-unit and the returned state. - // >= 0x80000000: Bad encoding detected, up to 16 bits (UTF-16) or 24 bits (UTF-8, last in lower bits) - // contain previous consumed values (does not happen if Safe == false). - template - inline uint32 Decode(uint32 state, uint32 unit); - - // Some constant values used when encoding/decoding. - enum - { - cDecodeShiftRemaining = 26, // Where to store the remaining count in the state. - cDecodeOneRemaining = 1 << cDecodeShiftRemaining, // Remaining value of one. - cDecodeMaskRemaining = 3 << cDecodeShiftRemaining, // All possible remaining bits that can be used. - cDecodeLeadBit = 1 << 22, // All bits up to and including this one are reserved. - cDecodeErrorBit = 1 << 31, // Set if an error occurs during decoding. - cDecodeOverlongBit = 1 << 30, // Set if overlong sequence was used. - cDecodeSurrogateBit = 1 << 29, // Set if surrogate code-point decoded in UTF-8. - cDecodeInvalidBit = 1 << 28, // Set if invalid code-point decoded (U+FFFE/FFFF). - cDecodeSuccess = 0, // Placeholder to indicate no error occurred. - cCodepointMax = 0x10FFFF, // The maximum value of an UCS code-point. - cLeadSurrogateFirst = 0xD800, // The first valid UTF-16 lead-surrogate value. - cLeadSurrogateLast = 0xDBFF, // The last valid UTF-16 lead-surrogate value. - cTrailSurrogateFirst = 0xDC00, // The first valid UTF-16 trail-surrogate value. - cTrailSurrogateLast = 0xDFFF, // The last valid UTF-16 trail-surrogate value. - cReplacementCharacter = 0xFFFD, // The default replacement character. - }; - - // Validate the UTF-8 state of a multi-byte sequence. - // The safe decoder of UTF-8 will call this function when a full potential code-point has been decoded. - // This function is (at most) called for 50% of the decoded UTF-8 code-units, but likely at much lower frequency. - inline uint32 DecodeValidate8(uint32 state) - { - uint32 errorbits = (state >> 8) | cDecodeErrorBit; - state ^= (state & 0x400000) >> 1; // For 3-byte sequences, bit 5 of the lead byte needs to be cleared. - const uint32 cp = - (state & 0x3F) | - ((state & 0x3F00) >> 2) | - ((state & 0x3F0000) >> 4) | - ((state & 0x07000000) >> 6); - if (cp <= cCodepointMax) - { - if (cp >= cLeadSurrogateFirst && cp <= cTrailSurrogateLast) - { - errorbits += cDecodeSurrogateBit; // CESU-8 encoding might have been used. - } - else - { - uint32 minval = 0x80; - minval += (0x00400000 & state) ? 0x800 - 0x80 : 0; - minval += (0x40000000 & state) ? 0x10000 - 0x80 : 0; - if (cp >= minval) - { - if ((cp & 0xFFFFFFFEU) != 0xFFFEU) - { - return cp; // Valid code-point. - } - errorbits += cDecodeInvalidBit; // Invalid character used. - } - errorbits += cDecodeOverlongBit; // Overlong encoding used. - } - } - return errorbits; - } - - // Decode UTF-8, unsafe. - template<> - inline uint32 Decode(uint32 state, uint32 unit) - { - if (state == 0) // First byte. - { - unit = unit & 0xFF; - if (unit < 0xC0) - { - return unit; // Single-unit (ASCII). - } - uint32 remaining = (unit >> 4) - 0xC; - remaining += (remaining == 0); - return (unit & 0x1F) + (remaining << cDecodeShiftRemaining); // Lead byte of multi-byte. - } - state = (state << 6) + (unit & 0x3F) + (state & cDecodeMaskRemaining) - cDecodeOneRemaining; // Apply c-byte. - return state & ~cDecodeLeadBit; // Mask off the lead bits of a 4-byte sequence. - } - - // Decode UTF-8, safe - template<> - inline uint32 Decode(uint32 state, uint32 unit) - { - if (unit <= 0xF4) // Discard out-of-range values immediately. - { - if (state == 0) // First byte. - { - if (unit < 0x80) - { - return unit; // Single-byte. - } - if (unit < 0xC2) - { - return cDecodeErrorBit; // Invalid continuation byte (or illegal 0xC0/0xC1). - } - uint32 remaining = (unit >> 4) - 0xC; - remaining += (remaining == 0); - return unit + (remaining << cDecodeShiftRemaining); // Multi-byte. - } - if ((unit & 0xC0) == 0x80) - { - const uint32 remaining = (state & cDecodeMaskRemaining) - cDecodeOneRemaining; - state = (state << 8) + unit; - if (remaining != 0) - { - return state | remaining; // Intermediate byte of a multi-byte sequence. - } - return DecodeValidate8(state); // Final byte of a multi-byte sequence. - } - } - return cDecodeErrorBit | state; - } - - // Decode UTF-16, unsafe. - template<> - inline uint32 Decode(uint32 state, uint32 unit) - { - const bool bLead = (unit >= cLeadSurrogateFirst) && (unit <= cLeadSurrogateLast); - const uint32 initial = unit + (bLead << cDecodeShiftRemaining); - const uint32 pair = 0x10000 + ((state & 0x3FF) << 10) + (unit & 0x3FF); - return state == 0 ? initial : pair; - } - - // Decode UTF-16, safe. - template<> - inline uint32 Decode(uint32 state, uint32 unit) - { - const bool bTrail = (unit >= cTrailSurrogateFirst) && (unit <= cTrailSurrogateLast); - if (state != 0 && !bTrail) - { - return cDecodeErrorBit + (state & 0xFFFF); // Lead surrogate without trail surrogate - } - uint32 result = Decode(state, unit); - bool bValid = (result & 0xFFFFFFFEU) != 0xFFFEU; - return bValid ? result : result + cDecodeErrorBit + cDecodeInvalidBit; - } - - // Decode UTF-32, unsafe. - template<> - inline uint32 Decode([[maybe_unused]] uint32 state, uint32 unit) - { - return unit; - } - - // Decode UTF-32, safe. - template<> - inline uint32 Decode([[maybe_unused]] uint32 state, uint32 unit) - { - if (unit > cCodepointMax) - { - return cDecodeErrorBit; - } - if (unit >= cLeadSurrogateFirst && unit <= cTrailSurrogateLast) - { - return cDecodeErrorBit | cDecodeSurrogateBit; - } - if ((unit & 0xFFFEU) == 0xFFFEU) - { - return cDecodeErrorBit | cDecodeInvalidBit; - } - return unit; - } - - // Decode ASCII, unsafe. - template<> - inline uint32 Decode([[maybe_unused]] uint32 state, uint32 unit) - { - return unit; - } - - // Decode ASCII, safe. - template<> - inline uint32 Decode([[maybe_unused]] uint32 state, uint32 unit) - { - if (unit > 0x7F) - { - return cDecodeErrorBit; - } - return unit; - } - - // Decode Latin1, unsafe. - template<> - inline uint32 Decode([[maybe_unused]] uint32 state, uint32 unit) - { - return unit; - } - - // Decode Latin1, safe. - template<> - inline uint32 Decode([[maybe_unused]] uint32 state, uint32 unit) - { - if ((unit >= 0x80 && unit <= 0x9F) || (unit > 0xFF)) - { - return cDecodeErrorBit; - } - return unit; - } - - // Decode Windows CP-1252, unsafe. - template<> - inline uint32 Decode([[maybe_unused]] uint32 state, uint32 unit) - { - static const uint16 cp1252[] = - { - 0x20AC, 0x0081, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, - 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x008D, 0x017D, 0x008F, - 0x0090, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, - 0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x009D, 0x017E, 0x0178, - }; - return (unit < 0x80 || unit > 0x9F) ? unit : cp1252[unit - 0x80]; - } - - // Decode Windows CP-1252, safe. - template<> - inline uint32 Decode(uint32 state, uint32 unit) - { - if (unit > 0xFF) - { - return cDecodeErrorBit; - } - uint32 result = Decode(state, unit); - if (!(unit < 0x80 || unit > 0x9F) && (result == unit)) - { - return cDecodeErrorBit; // Not defined in codepage 1252. - } - return result; - } - - // SBase: - // Utility to apply empty-base-optimization on type T. - // Will fall back to a member if T is a reference type. - template - struct SBase - : T - { - SBase(T base) - : T(base) {} - T& GetBase() { return *this; } - const T& GetBase() const { return *this; } - }; - template - struct SBase - { - T& base; - SBase(T& b) - : base(b) {} - T& GetBase() { return base; } - const T& GetBase() const { return base; } - }; - - // SDecoder: - // Functor to decode UCS code-points from an input range. - // Recovery functor will be invoked as a fall-back if decoding fails. - // This allows ensuring all the output is valid (even if the input isn't). - // Note: The destructor will automatically flush any remaining (erroneous) state, you can also call Finalize(). - template - struct SDecoder - : SBase - , SBase - { - uint32 state; - SDecoder(Sink sink, Recovery recovery = Recovery()) - : SBase(sink) - , SBase(recovery) - , state(0) {} - SDecoder() { Finalize(); } - Recovery& recovery() { return SBase::GetBase(); } - Sink& sink() { return SBase::GetBase(); } - void operator()(uint32 unit) - { - state = Detail::Decode(state, unit); - if (state <= 0x1FFFFF) - { - sink()(state); - state = 0; - } - else if (state & Detail::cDecodeErrorBit) - { - recovery()(sink(), state, unit); - state = 0; - } - } - void Finalize() - { - if (state) - { - recovery()(sink(), state, 0); - state = 0; - } - } - }; - - // SDecoder: - // Functor to decode to UCS code-points from an input range. - // No attempt to discover or recover from encoding errors is made, can only safely be used with known-valid input. - template - struct SDecoder - : SBase - { - uint32 state; - SDecoder(Sink sink) - : SBase(sink) - , state(0) {} - Sink& sink() { return SBase::GetBase(); } - void operator()(uint32 unit) - { - state = Detail::Decode(state, unit); - if (state <= 0x1FFFFF) - { - sink()(state); - state = 0; - } - } - void Finalize() {} - }; - - // SEncoder: - // Generic Unicode encoder functor. - // Encoding must be one an encoding type for which output is supported. - // The Sink type must have HintSequence member for UTF-8 and UTF-16 (although it may be a no-op). - // In general, you feed operator() with UCS code-points and it will emit code-units. - template - struct SEncoder - { - static const bool value = false; - }; - - // SEncoder: - // Specialization of ASCII encoder functor. - // Note: Any out-of-range character is mapped to question mark. - template - struct SEncoder - : SBase - { - static const bool value = true; - typedef uint8 value_type; - SEncoder(Sink sink) - : SBase(sink) {} - void operator()(uint32 cp) - { - cp = cp < 0x80 ? cp : (uint32)'?'; - SBase::GetBase()(value_type(cp)); - } - }; - - // SEncoder: - // Specialization of UTF-8 encoder functor. - template - struct SEncoder - : SBase - { - static const bool value = true; - typedef uint8 value_type; - SEncoder(Sink sink) - : SBase(sink) {} - Sink& sink() { return SBase::GetBase(); } - void operator()(uint32 cp) - { - if (cp < 0x80) - { - // Single byte sequence. - sink()(value_type(cp)); - } - else - { - // Expand 21-bit value to 32-bit. - uint32 bits = - (cp & 0x00003F) + - ((cp & 0x000FC0) << 2) + - ((cp & 0x03F000) << 4) + - ((cp & 0x1C0000) << 6); - - // Type of sequence. - const bool bSeq4 = (cp >= 0x10000); - const bool bSeq3 = (cp >= 0x800); - - // Mask lead-bytes and continuation-bytes. - uint32 mask = 0xEFE0C080; - mask ^= (bSeq3 << 14); - mask += (bSeq4 ? 0xA00000 : 0); - bits |= mask; - - // Length of the sequence. - const uint32 length = (uint32)bSeq4 + (uint32)bSeq3 + 1; - sink().HintSequence(length); - - // Sink the multi-byte sequence. - if (bSeq4) - { - sink()(value_type(bits >> 24)); - } - if (bSeq3) - { - sink()(value_type(bits >> 16)); - } - sink()(value_type(bits >> 8)); - sink()(value_type(bits)); - } - } - }; - - // SEncoder: - // Specialization of UTF-16 encoder functor. - template - struct SEncoder - : SBase - { - static const bool value = true; - typedef uint16 value_type; - SEncoder(Sink sink) - : SBase(sink) {} - Sink& sink() { return SBase::GetBase(); } - void operator()(uint32 cp) - { - if (cp < 0x10000) - { - // Single unit - sink()(value_type(cp)); - } - else - { - // We will generate two-element sequence - sink().HintSequence(2); - - // Surrogate pair - cp -= 0x10000; - uint32 lead = ((cp >> 10) & 0x3FF) + Detail::cLeadSurrogateFirst; - uint32 trail = (cp & 0x3FF) + Detail::cTrailSurrogateFirst; - sink()(value_type(lead)); - sink()(value_type(trail)); - } - } - }; - - // SEncoder: - // Specialization of UTF-32 encoder functor. - // Note: This is a no-op, but we want to be able to express UTF-32 just like the other encodings. - template - struct SEncoder - : SBase - { - static const bool value = true; - typedef uint32 value_type; - SEncoder(Sink sink) - : SBase(sink) {} - void operator()(uint32 cp) - { - SBase::GetBase()(value_type(cp)); - } - }; - - // SDecoder, void>: - // Specialization for unsafe no-op trans-coding. - // Since the conversion is a no-op, no need to keep any state or do any computation. - // Note: For a decoding with a fallback, this is not possible since we can't guarantee the input is valid. - template - struct SDecoder, void> - { - Sink sink; - SDecoder(Sink s) - : sink(s) {} - void operator()(uint32 unit) - { - sink(unit); - } - void Finalize() {} - }; - - // SRecoveryDiscard: - // Recovery handler that, on encoding error, discards the offending sequence. - template - struct SRecoveryDiscard - { - SRecoveryDiscard() {} - void operator()([[maybe_unused]] Sink& sink, [[maybe_unused]] uint32 error, [[maybe_unused]] uint32 unit) {} - }; - - // SRecoveryReplace: - // Recovery handler that, on encoding error, replaces the sequence with replacement-character (U+FFFD). - // Note: This implementation matches a whole invalid sequence, it could be changed to emit for every code-unit. - template - struct SRecoveryReplace - { - SRecoveryReplace() {} - void operator()(Sink& sink, uint32 error, uint32 unit) { sink(cReplacementCharacter); } - }; - - // SRecoveryFallback: - // Recovery handler that, on encoding error, falls back to another encoding. - // The fallback encoding must be stateless (ie: ASCII, Latin1 or Win1252). - // This type assumes an 8-bit primary encoding since the only viable fallback encodings are 8-bit. - template - struct SRecoveryFallback - : NextFallback - { - SRecoveryFallback() - : NextFallback() {} - void operator()(Sink& sink, uint32 error, uint32 unit) - { - SDecoder fallback(sink, *static_cast(this)); - uint8 byte1(error >> 16); - uint8 byte2(error >> 8); - uint8 byte3(error); - uint8 byte4(unit); - if (byte1) - { - fallback(byte1); - } - if (byte1 | byte2) - { - fallback(byte2); - } - if (byte1 | byte2 | byte3) - { - fallback(byte3); - } - fallback(byte4); - } - }; - - // SRecoveryFallbackHelper: - // Helper to pick a SRecoveryFallback instantiation based on RecoveryMethod. - template - struct SRecoveryFallbackHelper - { - // A compilation error here means RecoveryMethod value was unexpected here - COMPILE_TIME_ASSERT( - RecoveryMethod == eErrorRecovery_FallbackLatin1ThenDiscard || - RecoveryMethod == eErrorRecovery_FallbackLatin1ThenReplace || - RecoveryMethod == eErrorRecovery_FallbackWin1252ThenDiscard || - RecoveryMethod == eErrorRecovery_FallbackWin1252ThenReplace); - typedef SEncoder SinkType; - static const EEncoding FallbackEncoding = - RecoveryMethod == eErrorRecovery_FallbackLatin1ThenDiscard || - RecoveryMethod == eErrorRecovery_FallbackLatin1ThenReplace - ? eEncoding_Latin1 : eEncoding_Win1252; - template - struct Pick - { - typedef SRecoveryDiscard type; - }; - template - struct Pick - { - typedef SRecoveryReplace type; - }; - typedef typename Pick::type NextFallback; - typedef SRecoveryFallback RecoveryType; - typedef SDecoder FullType; - }; - - // STranscoderSelect: - // Derives a chained decoder/encoder pair that performs code-unit -> code-unit transform. - // The RecoveryMethod template parameter determines the behavior during encoding. - // This is the basic way to perform trans-coding, and is the type instantiated by the higher-level functions. - template - struct STranscoderSelect; - template - struct STranscoderSelect - : SDecoder, void> - { - typedef SDecoder, void> TranscoderType; - STranscoderSelect(Sink sink) - : TranscoderType(sink) {} - }; - template - struct STranscoderSelect - : SDecoder, SRecoveryDiscard > > - { - typedef SRecoveryDiscard > RecoveryType; - typedef SDecoder, RecoveryType> TranscoderType; - STranscoderSelect(Sink sink) - : TranscoderType(sink) {} - }; - template - struct STranscoderSelect - : SDecoder, SRecoveryReplace > > - { - typedef SRecoveryReplace > RecoveryType; - typedef SDecoder, RecoveryType> TranscoderType; - STranscoderSelect(Sink sink) - : TranscoderType(sink) {} - }; - template - struct STranscoderSelect - : SRecoveryFallbackHelper::FullType - { - static const EErrorRecovery RecoveryMethod = eErrorRecovery_FallbackLatin1ThenDiscard; - typedef typename SRecoveryFallbackHelper::RecoveryType RecoveryType; - typedef typename SRecoveryFallbackHelper::FullType TranscoderType; - STranscoderSelect(Sink sink) - : TranscoderType(sink) {} - }; - template - struct STranscoderSelect - : SRecoveryFallbackHelper::FullType - { - static const EErrorRecovery RecoveryMethod = eErrorRecovery_FallbackLatin1ThenReplace; - typedef typename SRecoveryFallbackHelper::RecoveryType RecoveryType; - typedef typename SRecoveryFallbackHelper::FullType TranscoderType; - STranscoderSelect(Sink sink) - : TranscoderType(sink) {} - }; - template - struct STranscoderSelect - : SRecoveryFallbackHelper::FullType - { - static const EErrorRecovery RecoveryMethod = eErrorRecovery_FallbackWin1252ThenDiscard; - typedef typename SRecoveryFallbackHelper::RecoveryType RecoveryType; - typedef typename SRecoveryFallbackHelper::FullType TranscoderType; - STranscoderSelect(Sink sink) - : TranscoderType(sink) {} - }; - template - struct STranscoderSelect - : SRecoveryFallbackHelper::FullType - { - static const EErrorRecovery RecoveryMethod = eErrorRecovery_FallbackWin1252ThenReplace; - typedef typename SRecoveryFallbackHelper::RecoveryType RecoveryType; - typedef typename SRecoveryFallbackHelper::FullType TranscoderType; - STranscoderSelect(Sink sink) - : TranscoderType(sink) {} - }; - - // SIsSafeEncoding: - // Check if the given recovery mode is safe. - // This is used for SFINAE checks in higher-level functions. - template - struct SIsSafeEncoding - { - static const bool value = - R == eErrorRecovery_Discard || - R == eErrorRecovery_Replace || - R == eErrorRecovery_FallbackLatin1ThenDiscard || - R == eErrorRecovery_FallbackLatin1ThenReplace || - R == eErrorRecovery_FallbackWin1252ThenDiscard || - R == eErrorRecovery_FallbackWin1252ThenReplace; - }; - - // SIsCopyableEncoding: - // Check if data in one encoding can be copied directly to another encoding. - // This is the basis for block-copy and string-assign optimizations in un-safe conversion functions. - // Note: There are more valid combinations, they are left out since those can't occur with the output encodings supported. - // Note: Only used for un-safe functions since it doesn't account for potential invalid sequences (they would be copied over). - template - struct SIsCopyableEncoding - { - static const bool value = - InputEncoding == eEncoding_ASCII || // ASCII and Latin1 values don't change in any encoding. - (InputEncoding == eEncoding_Latin1 && OutputEncoding != eEncoding_ASCII); // Except Latin1 -> ASCII is lossy. - }; - template - struct SIsCopyableEncoding - { - static const bool value = true; // If the input and output encodings are the same, then it's copyable. - }; - } -} diff --git a/Code/Legacy/CryCommon/UnicodeFunctions.h b/Code/Legacy/CryCommon/UnicodeFunctions.h deleted file mode 100644 index 48debe9706..0000000000 --- a/Code/Legacy/CryCommon/UnicodeFunctions.h +++ /dev/null @@ -1,1265 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - -// Generic Unicode string functions. -// -// Implements the following functions: -// Analyze: Reports all information on the input string, (length for all encodings, validity- and non-ASCII flags). -// Validate: Checks if the input string is valid encoded. -// Length: Reports the encoded length of some known-valid input, as-if it was encoded in the given output encoding. -// LengthSafe: Reports the encoded length of some input, as-if it was encoded in the given output encoding/recovery. -// Convert: Converts input from a known-valid string type/encoding to another string type/encoding. -// ConvertSafe: Converts and recovers encoding errors from one string type/encoding to another string type/encoding. -// Append: Appends input from a known-valid string type/encoding to another string type/encoding. -// AppendSafe: Appends and recovers encoding errors from one string type/encoding to another string type/encoding. -// -// Note: Ideally the safe functions should be used only once when accepting input from the user or from a file. -// Afterwards, the content is known-safe and the unsafe functions can be used for optimal performance. -// Using ConvertSafe once with a reasonable fall-back (depending on the where the input is from) should be the goal. -// -// Each function has several overloads: -// - One variant to handle a string object / buffer / pointer (1 arg), and one to handle iterators (2 args). -// - One variant with automatic encoding (picks UTF encoding depending on character size), and one for specific encoding. -// - One variant that returns a new string, and one that takes an existing string to overwrite (Convert(Safe) only). -// Each function takes one default argument that employs SFINAE to pick the correct overload depending on the arguments. - - -#pragma once -#include "UnicodeBinding.h" -namespace Unicode -{ - // Results of analysis of an input range of code-units (in any encoding). - // This is returned by calling Analyze() function. - struct SAnalysisResult - { - // The type to use for counting units. - // Can be changed to uint64_t for dealing with 4GB+ of string data. - typedef uint32 size_type; - - size_type inputUnits; // The number of input units analyzed. - size_type outputUnits8; // The number of output units when encoded with UTF-8. - size_type outputUnits16; // The number of output units when encoded with UTF-16. - size_type outputUnits32; // The number of output units when encoded with UTF-32 (aka number of UCS code-points). - size_type cpNonAscii; // The number of non-ASCII UCS code-points encountered. - size_type cpInvalid; // The number of invalid UCS code-point encountered (or 0xFFFFFFFF if not available). - - // Default constructor, initialize everything to zero. - SAnalysisResult() - : inputUnits(0) - , outputUnits8(0) - , outputUnits16(0) - , outputUnits32(0) - , cpInvalid(0) - , cpNonAscii(0) {} - - // Check if the input range was empty. - bool IsEmpty() const { return inputUnits == 0; } - - // Check if the input range only contained ASCII characters. - bool IsAscii() const { return cpNonAscii == 0; } - - // Check if the input range was valid (has no encoding errors). - // Note: This returns false if an unsafe decoder was used for analysis. - bool IsValid() const { return cpInvalid == 0; } - - // Get the length of the input range, in source code-units. - size_type LengthInSourceUnits() const { return inputUnits; } - - // Get the length of the input range, in UCS code-points. - size_type LengthInUCS() const { return outputUnits32; } - - // Get the length of the input range when encoded with the given encoding, in code-units. - // Note: If the encoding is not supported for output, the function returns 0. - size_type LengthInEncodingUnits(EEncoding encoding) const - { - switch (encoding) - { - case eEncoding_ASCII: - case eEncoding_UTF32: - return outputUnits32; - case eEncoding_UTF16: - return outputUnits16; - case eEncoding_UTF8: - return outputUnits8; - default: - return 0; - } - } - - // Get the length of the input range when encoded with the given encoding, in bytes. - // Note: If the encoding is not supported for output, the function returns 0. - size_type LengthInEncodingBytes(EEncoding encoding) const - { - size_type units = LengthInEncodingUnits(encoding); - switch (encoding) - { - case eEncoding_UTF32: - return units << 2; - case eEncoding_UTF16: - return units << 1; - default: - return units; - } - } - }; - - namespace Detail - { - // SDummySink: - // A sink implementation that does nothing. - struct SDummySink - { - void operator()([[maybe_unused]] uint32 unit) {} - void HintSequence([[maybe_unused]] uint32 length) {} - }; - - // SCountingSink: - // A sink that counts the number of units of output. - struct SCountingSink - { - size_t result; - - SCountingSink() - : result(0) {} - void operator()([[maybe_unused]] uint32 unit) { ++result; } - void HintSequence([[maybe_unused]] uint32 length) {} - }; - - // SAnalysisSink: - // A sink that updates analysis statistics. - struct SAnalysisSink - { - SAnalysisResult& result; - - SAnalysisSink(SAnalysisResult& _result) - : result(_result) {} - void operator()(uint32 cp) - { - const bool isCat2 = cp >= 0x80; - const bool isCat3 = cp >= 0x800; - const bool isCat4 = cp >= 0x10000; - result.outputUnits32 += 1; - result.outputUnits16 += (1 + isCat4); - result.outputUnits8 += (1 + isCat4 + isCat3 + isCat2); - result.cpNonAscii += isCat2; - } - void HintSequence([[maybe_unused]] uint32 length) {} - }; - - // SAnalysisRecovery: - // A recovery helper for analysis that counts invalid sequences. - struct SAnalysisRecovery - { - SAnalysisRecovery() {} - void operator()(SAnalysisSink& sink, [[maybe_unused]] uint32 error, [[maybe_unused]] uint32 unit) - { - sink.result.cpInvalid += 1; - } - }; - - // SValidationRecovery: - // A recovery helper for validation, it tracks if there is any invalid sequence. - struct SValidationRecovery - { - bool isValid; - - SValidationRecovery() - : isValid(true) {} - void operator()([[maybe_unused]] SDummySink& sink, [[maybe_unused]] uint32 error, [[maybe_unused]] uint32 unit) - { - isValid = false; - } - }; - - // SAnalyzer: - // Helper to perform analysis, counts the input for a given encoding. - template - struct SAnalyzer - { - SDecoder decoder; - - SAnalyzer(SAnalysisResult& result) - : decoder(result) {} - void operator()(uint32 item) - { - decoder.sink().result.inputUnits += 1; - decoder(item); - } - }; - - // Analyze(target, source): - // Analyze string and store analysis result. - // This is the generic function called by other Analyze overloads. - template - inline void Analyze(SAnalysisResult& target, const InputStringType& source) - { - // Bind methods. - const EBind bindMethod = SBindObject::value; - integral_constant tag; - - // Analyze using helper. - SAnalyzer analyzer(target); - Feed(source, analyzer, tag); - } - - // Validate(source): - // Tests that the string is valid encoding. - // This is the generic function called by other Validate overloads. - template - inline bool Validate(const InputStringType& source) - { - // Bind methods. - const EBind bindMethod = SBindObject::value; - integral_constant tag; - - // Validate using helper. - SDummySink sink; - SDecoder validator(sink); - Feed(source, validator, tag); - return validator.recovery().isValid; - } - - // Length(str): - // Find length of a string (in code-units) after trans-coding from InputEncoding to OutputEncoding. - // This is the generic function called by the other Length overloads. - template - inline size_t Length(const InputStringType& source) - { - // If this assert hits, consider using LengthSafe. - assert((Detail::Validate(source)) && "Length was used with non-safe input"); - - // Bind methods. - const EBind bindMethod = SBindObject::value; - integral_constant tag; - - // All copyable encodings have the property that the number of input encoding units equals the output units. - // In addition, this also holds for UTF-32 (always 1) -> ASCII (always 1), even though it's lossy. - const bool isCopyable = SIsCopyableEncoding::value; - const bool isCountable = isCopyable || (InputEncoding == eEncoding_UTF32 && OutputEncoding == eEncoding_ASCII); - - if (isCountable) - { - // Optimization: The number of input units is equal to the number of output units. - return EncodedLength(source, tag); - } - else - { - // We need to perform the conversion. - SCountingSink sink; - STranscoderSelect transcoder(sink); - Feed(source, transcoder, tag); - return sink.result; - } - } - - // LengthSafe(str): - // Find length of a string (in code-units) after trans-coding from InputEncoding to OutputEncoding. - // Note: The Recovery type used during conversion may influence the result, so this needs to match if you use the length information. - // This is the generic function called by the other LengthSafe overloads. - template - inline size_t LengthSafe(const InputStringType& source) - { - // SRequire a safe recovery method. - COMPILE_TIME_ASSERT(SIsSafeEncoding::value); - - // Bind methods. - const EBind bindMethod = SBindObject::value; - integral_constant tag; - - // We can't optimize here, since we cannot assume the input is validly encoded - SCountingSink sink; - STranscoderSelect transcoder(sink); - Feed(source, transcoder, tag); - return sink.result; - } - - // SBlockCopy: - // Helper for block-copying entire string at once (as an optimization) - // This optimization will effectively try to memcpy or assign the whole string at once. - // Note: We need to do some partial specialization here to find out if the optimization is valid, so we can't use a function in C++98. - template - struct SBlockCopy - { - static const EBind bindMethod = SBindObject::value; - typedef integral_constant TagType; - size_t operator()(OutputStringType& target, const InputStringType& source) - { - // Optimization: Use block copying for these types. - TagType tag; - const size_t length = EncodedLength(source, tag); - SinkType sink(target, length); - if (sink.CanWrite()) - { - const void* const dataPtr = EncodedPointer(source, tag); - sink(dataPtr, length); - } - return length; - } - }; - - // SBlockCopy: - // Specialization that will use direct string assignment. - // Note: This optimization is not selected when appending, this could be a future optimization if this is common. - // Reason for this is that the += operator is not present on all supported types (ie, std::vector) - template - struct SBlockCopy - { - size_t operator()(SameStringType& target, const SameStringType& source) - { - // Optimization: Use copy assignment. - target = source; - return source.size(); - } - }; - - // SBlockCopy: - // Fall-back specialization for Enable == false. - // Note: This specialization has to exist for the linker, but should never be called (and optimized away). - template - struct SBlockCopy - { - size_t operator()([[maybe_unused]] OutputStringType& target, [[maybe_unused]] const InputStringType& source) - { - assert(false && "Should never be called"); - return 0; - } - }; - - // Convert(target, source): - // Trans-code a string from InputEncoding to OutputEncoding. - // This is the generic function that is called by Convert and Append overloads. - // Returns the number of code-units required for full output (excluding any terminators) - template - inline size_t Convert(OutputStringType& target, const InputStringType& source) - { - // If this assert hits, consider using ConvertSafe. - assert((Detail::Validate(source)) && "Convert was used with non-safe input"); - - // Bind methods. - const EBind inputBindMethod = SBindObject::value; - const EBind outputBindMethod = SBindOutput::value; - integral_constant tag; - typedef SWriteSink SinkType; - - // Check if we can optimize this. - const bool isCopyable = SIsCopyableEncoding::value; - const bool isBlocks = SIsBlockCopyable, SBindOutput >::value; - const bool useBlockCopy = isCopyable && isBlocks; - size_t length; - if (useBlockCopy) - { - // Use optimized path. - SBlockCopy blockCopy; - length = blockCopy(target, source); - } - else - { - // We need to perform the conversion code-unit by code-unit. - length = Detail::Length(source); - SinkType sink(target, length); - if (sink.CanWrite()) - { - STranscoderSelect transcoder(sink); - Feed(source, transcoder, tag); - } - } - return length; - } - - // ConvertSafe(target, source): - // Safely trans-code a string from InputEncoding to OutputEncoding using the specified Recovery to handle encoding errors. - // This is the generic function called by ConvertSafe and AppendSafe overloads. - template - inline size_t ConvertSafe(OutputStringType& target, const InputStringType& source) - { - // SRequire a safe recovery method. - COMPILE_TIME_ASSERT(SIsSafeEncoding::value); - - // Bind methods. - const EBind inputBindMethod = SBindObject::value; - const EBind outputBindMethod = SBindOutput::value; - integral_constant tag; - typedef SWriteSink SinkType; - - // We can't optimize with block-copy here, since we cannot assume the input is validly encoded. - const size_t length = Detail::LengthSafe(source); - SinkType sink(target, length); - if (sink.CanWrite()) - { - STranscoderSelect transcoder(sink); - Feed(source, transcoder, tag); - } - return length; - } - - // SReqAutoObj: - // Require that T is usable as input object, with automatic encoding. - // This is used as a SFINAE argument for overload resolution of the main functions. - template - struct SReqAutoObj - : SRequire< - SBindObject::value != eBind_Impossible&& - SEncoder::value&& - SIsSafeEncoding::value - > {}; - - // SReqAutoIts: - // Require that T is usable as input iterator, with automatic encoding. - // This is used as a SFINAE argument for overload resolution of the main functions. - template - struct SReqAutoIts - : SRequire< - SBindIterator::value != eBind_Impossible&& - SEncoder::value&& - SIsSafeEncoding::value - > {}; - - // SReqAnyObj: - // Require that T is usable as input object, with user-specified encoding. - // This is used as a SFINAE argument for overload resolution of the main functions. - template - struct SReqAnyObj - : SRequire< - SBindObject::value != eBind_Impossible&& - SEncoder::value&& - SIsSafeEncoding::value - > {}; - - // SReqAnyIts: - // Require that T is usable as input iterator, with user-specified encoding. - // This is used as a SFINAE argument for overload resolution of the main functions. - template - struct SReqAnyIts - : SRequire< - SBindIterator::value != eBind_Impossible&& - SEncoder::value&& - SIsSafeEncoding::value - > {}; - - // SReqAutoObjOut: - // Require that I is usable as input object, and O as output object, with automatic encoding. - // This is used as a SFINAE argument for overload resolution of the main functions. - template - struct SReqAutoObjOut - : SRequire< - SBindObject::value != eBind_Impossible&& - SBindOutput, O>::type, true>::value != eBind_Impossible&& - SEncoder::value&& - SIsSafeEncoding::value - > {}; - - // SReqAutoItsOut: - // Require that I is usable as input iterator, and O as output object, with automatic encoding. - // This is used as a SFINAE argument for overload resolution of the main functions. - template - struct SReqAutoItsOut - : SRequire< - SBindIterator::value != eBind_Impossible&& - SBindOutput, O>::type, true>::value != eBind_Impossible&& - SEncoder::value&& - SIsSafeEncoding::value - > {}; - - // SReqAnyObjOut: - // Require that I is usable as input object, and O as output object, with user-specified encoding. - // This is used as a SFINAE argument for overload resolution of the main functions. - template - struct SReqAnyObjOut - : SRequire< - SBindObject::value != eBind_Impossible&& - SBindOutput, O>::type, false>::value != eBind_Impossible&& - SEncoder::value&& - SIsSafeEncoding::value - > {}; - - // SReqAnyItsOut: - // Require that I is usable as input object, and O as output object, with user-specified encoding. - // This is used as a SFINAE argument for overload resolution of the main functions. - template - struct SReqAnyItsOut - : SRequire< - SBindIterator::value != eBind_Impossible&& - SBindOutput, O>::type, false>::value != eBind_Impossible&& - SEncoder::value&& - SIsSafeEncoding::value - > {}; - } - - // SAnalysisResult Analyze(str): - // Analyze the given string with the given encoding, providing information on validity and encoding length. - template - inline SAnalysisResult Analyze(const InputStringType& str, - typename Detail::SReqAnyObj::type* = 0) - { - SAnalysisResult result; - Detail::Analyze(result, str); - return result; - } - - // SAnalysisResult Analyze(str): - // Analyze the (assumed) Unicode string input, providing information on validity and encoding length. - // The Unicode encoding is picked automatically depending on the input type. - template - inline SAnalysisResult Analyze(const InputStringType& str, - typename Detail::SReqAutoObj::type* = 0) - { - const EEncoding InputEncoding = Detail::SInferEncoding::value; - SAnalysisResult result; - Detail::Analyze(result, str); - return result; - } - - // SAnalysisResult Analyze(begin, end): - // Analyze the given range with the given encoding, providing information on validity and encoding length. - template - inline SAnalysisResult Analyze(InputIteratorType begin, InputIteratorType end, - typename Detail::SReqAnyIts::type* = 0) - { - typedef Detail::SPackedIterators InputStringType; - const InputStringType its(begin, end); - SAnalysisResult result; - Detail::Analyze(result, its); - return result; - } - - // SAnalysisResult Analyze(begin, end): - // Analyze the given (assumed) Unicode range, providing information on validity and encoding length. - // The Unicode encoding is picked automatically depending on the input type. - template - inline SAnalysisResult Analyze(InputIteratorType begin, InputIteratorType end, - typename Detail::SReqAutoIts::type* = 0) - { - const EEncoding InputEncoding = Detail::SInferEncoding::value; - typedef Detail::SPackedIterators InputStringType; - const InputStringType its(begin, end); - SAnalysisResult result; - Detail::Analyze(result, its); - return result; - } - - // bool Validate(str): - // Checks if the given string is valid in the given encoding. - template - inline bool Validate(const InputStringType& str, - typename Detail::SReqAnyObj::type* = 0) - { - return Detail::Validate(str); - } - - // bool Validate(str): - // Checks if the given string is a valid Unicode string. - // The Unicode encoding is picked automatically depending on the input type. - template - inline bool Validate(const InputStringType& str, - typename Detail::SReqAutoObj::type* = 0) - { - const EEncoding InputEncoding = Detail::SInferEncoding::value; - return Detail::Validate(str); - } - - // bool Validate(begin, end): - // Checks if the given range is valid in the given encoding. - template - inline bool Validate(InputIteratorType begin, InputIteratorType end, - typename Detail::SReqAnyIts::type* = 0) - { - typedef Detail::SPackedIterators InputStringType; - const InputStringType its(begin, end); - return Detail::Validate(its); - } - - // bool Validate(begin, end): - // Checks if the given range is valid Unicode. - // The Unicode encoding is picked automatically depending on the input type. - template - inline bool Validate(InputIteratorType begin, InputIteratorType end, - typename Detail::SReqAutoIts::type* = 0) - { - const EEncoding InputEncoding = Detail::SInferEncoding::value; - typedef Detail::SPackedIterators InputStringType; - const InputStringType its(begin, end); - return Detail::Validate(its); - } - - // size_t Length(str): - // Get the length (in OutputEncoding) of the given known-valid string with the given InputEncoding. - // Note: Length assumes the input is valid encoded, if this is not guaranteed (ie, user-input), use LengthSafe. - template - inline size_t Length(const InputStringType& str, - typename Detail::SReqAnyObj::type* = 0) - { - return Detail::Length(str); - } - - // size_t Length(str): - // Get the length (in OutputEncoding) of the given known-valid Unicode string. - // The Unicode encoding is picked automatically depending on the input type. - // Note: Length assumes the input is valid encoded, if this is not guaranteed (ie, user-input), use LengthSafe. - template - inline size_t Length(const InputStringType& str, - typename Detail::SReqAutoObj::type* = 0) - { - const EEncoding InputEncoding = Detail::SInferEncoding::value; - return Detail::Length(str); - } - - // size_t Length(begin, end): - // Get the length (in OutputEncoding) of the known-valid range with the given InputEncoding. - // Note: Length assumes the input is valid encoded, if this is not guaranteed (ie, user-input), use LengthSafe. - template - inline size_t Length(InputIteratorType begin, InputIteratorType end, - typename Detail::SReqAnyIts::type* = 0) - { - typedef Detail::SPackedIterators InputStringType; - const InputStringType its(begin, end); - return Detail::Length(its); - } - - // size_t Length(begin, end): - // Get the length (in OutputEncoding) of the known-valid Unicode range. - // The Unicode encoding is picked automatically depending on the input type. - // Note: Length assumes the input is valid encoded, if this is not guaranteed (ie, user-input), use LengthSafe. - template - inline size_t Length(InputIteratorType begin, InputIteratorType end, - typename Detail::SReqAutoIts::type* = 0) - { - const EEncoding InputEncoding = Detail::SInferEncoding::value; - typedef Detail::SPackedIterators InputStringType; - const InputStringType its(begin, end); - return Detail::Length(its); - } - - // size_t LengthSafe(str): - // Get the length (in OutputEncoding) of the given string with the given InputEncoding. - // Note: LengthSafe uses the specified Recovery parameter to fix encoding errors, if the input is known-valid, use Length. - template - inline size_t LengthSafe(const InputStringType& str, - typename Detail::SReqAnyObj::type* = 0) - { - return Detail::LengthSafe(str); - } - - // size_t LengthSafe(str): - // Get the length (in OutputEncoding) of the given Unicode string. - // The Unicode encoding is picked automatically depending on the input type. - // Note: LengthSafe uses the specified Recovery parameter to fix encoding errors, if the input is known-valid, use Length. - template - inline size_t LengthSafe(const InputStringType& str, - typename Detail::SReqAutoObj::type* = 0) - { - const EEncoding InputEncoding = Detail::SInferEncoding::value; - return Detail::LengthSafe(str); - } - - // size_t LengthSafe(begin, end): - // Get the length (in OutputEncoding) of the range with the given InputEncoding. - // Note: LengthSafe uses the specified Recovery parameter to fix encoding errors, if the input is known-valid, use Length. - template - inline size_t LengthSafe(InputIteratorType begin, InputIteratorType end, - typename Detail::SReqAnyIts::type* = 0) - { - typedef Detail::SPackedIterators InputStringType; - const InputStringType its(begin, end); - return Detail::LengthSafe(its); - } - - // size_t LengthSafe(begin, end): - // Get the length (in OutputEncoding) of the Unicode range. - // The Unicode encoding is picked automatically depending on the input type. - // Note: LengthSafe uses the specified Recovery parameter to fix encoding errors, if the input is known-valid, use Length. - template - inline size_t LengthSafe(InputIteratorType begin, InputIteratorType end, - typename Detail::SReqAutoIts::type* = 0) - { - const EEncoding InputEncoding = Detail::SInferEncoding::value; - typedef Detail::SPackedIterators InputStringType; - const InputStringType its(begin, end); - return Detail::LengthSafe(its); - } - - // OutputStringType &Convert(result, str): - // Converts the given string in the given input encoding and stores into the result string with the given output encoding. - // Note: Convert assumes the input is valid encoded, if this is not guaranteed (ie, user-input), use ConvertSafe. - template - inline OutputStringType& Convert(OutputStringType& result, const InputStringType& str, - typename Detail::SReqAnyObjOut::type* = 0) - { - Detail::Convert(result, str); - return result; - } - - // OutputStringType &Convert(result, str): - // Converts the (assumed) Unicode string input and stores into the result Unicode string. - // The Unicode encodings are picked automatically depending on the input type and output type. - // Note: Convert assumes the input is valid encoded, if this is not guaranteed (ie, user-input), use ConvertSafe. - template - inline OutputStringType& Convert(OutputStringType& result, const InputStringType& str, - typename Detail::SReqAutoObjOut::type* = 0) - { - const EEncoding InputEncoding = Detail::SInferEncoding::value; - const EEncoding OutputEncoding = Detail::SInferEncoding::value; - Detail::Convert(result, str); - return result; - } - - // OutputStringType &Convert(result, begin, end): - // Converts the given range in the given input encoding and stores into the result string with the given output encoding. - // Note: Convert assumes the input is valid encoded, if this is not guaranteed (ie, user-input), use ConvertSafe. - template - inline OutputStringType& Convert(OutputStringType& result, InputIteratorType begin, InputIteratorType end, - typename Detail::SReqAnyItsOut::type* = 0) - { - typedef Detail::SPackedIterators InputStringType; - const InputStringType its(begin, end); - Detail::Convert(result, its); - return result; - } - - // OutputStringType &Convert(result, begin, end): - // Converts the (assumed) Unicode range and stores into the result Unicode string. - // The Unicode encodings are picked automatically depending on the range type and output type. - // Note: Convert assumes the input is valid encoded, if this is not guaranteed (ie, user-input), use ConvertSafe. - template - inline OutputStringType& Convert(OutputStringType& result, InputIteratorType begin, InputIteratorType end, - typename Detail::SReqAutoItsOut::type* = 0) - { - const EEncoding InputEncoding = Detail::SInferEncoding::value; - const EEncoding OutputEncoding = Detail::SInferEncoding::value; - typedef Detail::SPackedIterators InputStringType; - const InputStringType its(begin, end); - Detail::Convert(result, its); - return result; - } - - // size_t Convert(buffer, length, str): - // Converts the given string in the given input encoding and stores into the result buffer with the given output encoding. - // Returns the required length of the output buffer, in code-units, including the null-terminator. - // Note: Convert assumes the input is valid encoded, if this is not guaranteed (ie, user-input), use ConvertSafe. - template - inline size_t Convert(OutputCharType* buffer, size_t length, const InputStringType& str, - typename Detail::SReqAnyObjOut::type* = 0) - { - typedef Detail::SPackedBuffer OutputStringType; - OutputStringType result(buffer, length); - return Detail::Convert(result, str) + 1; - } - - // size_t Convert(buffer, length, str): - // Converts the (assumed) Unicode string input and stores into the result Unicode buffer. - // The Unicode encodings are picked automatically depending on the buffer type and output type. - // Returns the required length of the output buffer, in code-units, including the null-terminator. - // Note: Convert assumes the input is valid encoded, if this is not guaranteed (ie, user-input), use ConvertSafe. - template - inline size_t Convert(OutputCharType* buffer, size_t length, const InputStringType& str, - typename Detail::SReqAutoObjOut::type* = 0) - { - const EEncoding InputEncoding = Detail::SInferEncoding::value; - const EEncoding OutputEncoding = Detail::SInferEncoding::value; - typedef Detail::SPackedBuffer OutputStringType; - OutputStringType result(buffer, length); - return Detail::Convert(result, str) + 1; - } - - // size_t Convert(buffer, length, begin, end): - // Converts the given range in the given input encoding and stores into the result buffer with the given output encoding. - // Returns the required length of the output buffer, in code-units, including the null-terminator. - // Note: Convert assumes the input is valid encoded, if this is not guaranteed (ie, user-input), use ConvertSafe. - template - inline size_t Convert(OutputCharType* buffer, size_t length, InputIteratorType begin, InputIteratorType end, - typename Detail::SReqAnyItsOut::type* = 0) - { - typedef Detail::SPackedIterators InputStringType; - typedef Detail::SPackedBuffer OutputStringType; - const InputStringType its(begin, end); - OutputStringType result(buffer, length); - return Detail::Convert(result, its) + 1; - } - - // size_t Convert(buffer, length, begin, end): - // Converts the (assumed) Unicode range and stores into the result Unicode buffer. - // The Unicode encodings are picked automatically depending on the range type and output type. - // Returns the required length of the output buffer, in code-units, including the null-terminator. - // Note: Convert assumes the input is valid encoded, if this is not guaranteed (ie, user-input), use ConvertSafe. - template - inline size_t Convert(OutputCharType* buffer, size_t length, InputIteratorType begin, InputIteratorType end, - typename Detail::SReqAutoItsOut::type* = 0) - { - const EEncoding InputEncoding = Detail::SInferEncoding::value; - const EEncoding OutputEncoding = Detail::SInferEncoding::value; - typedef Detail::SPackedIterators InputStringType; - typedef Detail::SPackedBuffer OutputStringType; - const InputStringType its(begin, end); - OutputStringType result(buffer, length); - return Detail::Convert(result, its) + 1; - } - - // OutputStringType Convert(str): - // Converts the given string in the given input encoding to a new string of the given type and output encoding. - // Note: Convert assumes the input is valid encoded, if this is not guaranteed (ie, user-input), use ConvertSafe. - template - inline OutputStringType Convert(const InputStringType& str, - typename Detail::SReqAnyObjOut::type* = 0) - { - OutputStringType result; - Detail::Convert(result, str); - return result; - } - - // OutputStringType Convert(str): - // Converts the (assumed) Unicode string input to a new Unicode string of the given type. - // The Unicode encodings are picked automatically depending on the input type and output type. - // Note: Convert assumes the input is valid encoded, if this is not guaranteed (ie, user-input), use ConvertSafe. - template - inline OutputStringType Convert(const InputStringType& str, - typename Detail::SReqAutoObjOut::type* = 0) - { - const EEncoding InputEncoding = Detail::SInferEncoding::value; - const EEncoding OutputEncoding = Detail::SInferEncoding::value; - OutputStringType result; - Detail::Convert(result, str); - return result; - } - - // OutputStringType Convert(begin, end): - // Converts the given range in the given input encoding to a new string of the given type and output encoding. - // Note: Convert assumes the input is valid encoded, if this is not guaranteed (ie, user-input), use ConvertSafe. - template - inline OutputStringType Convert(InputIteratorType begin, InputIteratorType end, - typename Detail::SReqAnyItsOut::type* = 0) - { - typedef Detail::SPackedIterators InputStringType; - const InputStringType its(begin, end); - OutputStringType result; - Detail::Convert(result, its); - return result; - } - - // OutputStringType Convert(begin, end): - // Converts the (assumed) Unicode range to a new Unicode string of the given type. - // The Unicode encodings are picked automatically depending on the range type and output type. - // Note: Convert assumes the input is valid encoded, if this is not guaranteed (ie, user-input), use ConvertSafe. - template - inline OutputStringType Convert(InputIteratorType begin, InputIteratorType end, - typename Detail::SReqAutoItsOut::type* = 0) - { - const EEncoding InputEncoding = Detail::SInferEncoding::value; - const EEncoding OutputEncoding = Detail::SInferEncoding::value; - typedef Detail::SPackedIterators InputStringType; - const InputStringType its(begin, end); - OutputStringType result; - Detail::Convert(result, its); - return result; - } - - // OutputStringType &ConvertSafe(result, str): - // Converts the given string in the given input encoding and stores into the result string with the given output encoding. - // Note: ConvertSafe uses the specified Recovery parameter to fix encoding errors, if the input is known-valid, use Convert. - template - inline OutputStringType& ConvertSafe(OutputStringType& result, const InputStringType& str, - typename Detail::SReqAnyObjOut::type* = 0) - { - Detail::ConvertSafe(result, str); - return result; - } - - // OutputStringType &ConvertSafe(result, str): - // Converts the (assumed) Unicode string input and stores into the result Unicode string. - // The Unicode encodings are picked automatically depending on the input type and output type. - // Note: ConvertSafe uses the specified Recovery parameter to fix encoding errors, if the input is known-valid, use Convert. - template - inline OutputStringType& ConvertSafe(OutputStringType& result, const InputStringType& str, - typename Detail::SReqAutoObjOut::type* = 0) - { - const EEncoding InputEncoding = Detail::SInferEncoding::value; - const EEncoding OutputEncoding = Detail::SInferEncoding::value; - Detail::ConvertSafe(result, str); - return result; - } - - // OutputStringType &ConvertSafe(result, begin, end): - // Converts the given range in the given input encoding and stores into the result string with the given output encoding. - // Note: ConvertSafe uses the specified Recovery parameter to fix encoding errors, if the input is known-valid, use Convert. - template - inline OutputStringType& ConvertSafe(OutputStringType& result, InputIteratorType begin, InputIteratorType end, - typename Detail::SReqAnyItsOut::type* = 0) - { - typedef Detail::SPackedIterators InputStringType; - const InputStringType its(begin, end); - Detail::ConvertSafe(result, its); - return result; - } - - // OutputStringType &ConvertSafe(result, begin, end): - // Converts the (assumed) Unicode range and stores into the result Unicode string. - // The Unicode encodings are picked automatically depending on the range type and output type. - // Note: ConvertSafe uses the specified Recovery parameter to fix encoding errors, if the input is known-valid, use Convert. - template - inline OutputStringType& ConvertSafe(OutputStringType& result, InputIteratorType begin, InputIteratorType end, - typename Detail::SReqAutoItsOut::type* = 0) - { - const EEncoding InputEncoding = Detail::SInferEncoding::value; - const EEncoding OutputEncoding = Detail::SInferEncoding::value; - typedef Detail::SPackedIterators InputStringType; - const InputStringType its(begin, end); - Detail::ConvertSafe(result, its); - return result; - } - - // size_t ConvertSafe(buffer, length, str): - // Converts the given string in the given input encoding and stores into the result buffer with the given output encoding. - // Returns the required length of the output buffer, in code-units, including the null-terminator. - // Note: ConvertSafe uses the specified Recovery parameter to fix encoding errors, if the input is known-valid, use Convert. - template - inline size_t ConvertSafe(OutputCharType* buffer, size_t length, const InputStringType& str, - typename Detail::SReqAnyObjOut::type* = 0) - { - typedef Detail::SPackedBuffer OutputStringType; - OutputStringType result(buffer, length); - return Detail::ConvertSafe(result, str) + 1; - } - - // size_t ConvertSafe(buffer, length, str): - // Converts the (assumed) Unicode string input and stores into the result Unicode buffer. - // The Unicode encodings are picked automatically depending on the buffer type and output type. - // Returns the required length of the output buffer, in code-units, including the null-terminator. - // Note: ConvertSafe uses the specified Recovery parameter to fix encoding errors, if the input is known-valid, use Convert. - template - inline size_t ConvertSafe(OutputCharType* buffer, size_t length, const InputStringType& str, - typename Detail::SReqAutoObjOut::type* = 0) - { - const EEncoding InputEncoding = Detail::SInferEncoding::value; - const EEncoding OutputEncoding = Detail::SInferEncoding::value; - typedef Detail::SPackedBuffer OutputStringType; - OutputStringType result(buffer, length); - return Detail::ConvertSafe(result, str) + 1; - } - - // size_t ConvertSafe(buffer, length, begin, end): - // Converts the given range in the given input encoding and stores into the result buffer with the given output encoding. - // Returns the required length of the output buffer, in code-units, including the null-terminator. - // Note: ConvertSafe uses the specified Recovery parameter to fix encoding errors, if the input is known-valid, use Convert. - template - inline size_t ConvertSafe(OutputCharType* buffer, size_t length, InputIteratorType begin, InputIteratorType end, - typename Detail::SReqAnyItsOut::type* = 0) - { - typedef Detail::SPackedIterators InputStringType; - typedef Detail::SPackedBuffer OutputStringType; - const InputStringType its(begin, end); - OutputStringType result(buffer, length); - return Detail::ConvertSafe(result, its) + 1; - } - - // size_t ConvertSafe(buffer, length, begin, end): - // Converts the (assumed) Unicode range and stores into the result Unicode buffer. - // The Unicode encodings are picked automatically depending on the range type and output type. - // Returns the required length of the output buffer, in code-units, including the null-terminator. - // Note: ConvertSafe uses the specified Recovery parameter to fix encoding errors, if the input is known-valid, use Convert. - template - inline size_t ConvertSafe(OutputCharType* buffer, size_t length, InputIteratorType begin, InputIteratorType end, - typename Detail::SReqAutoItsOut::type* = 0) - { - const EEncoding InputEncoding = Detail::SInferEncoding::value; - const EEncoding OutputEncoding = Detail::SInferEncoding::value; - typedef Detail::SPackedIterators InputStringType; - typedef Detail::SPackedBuffer OutputStringType; - const InputStringType its(begin, end); - OutputStringType result(buffer, length); - return Detail::Convert(result, its) + 1; - } - - // OutputStringType ConvertSafe(str): - // Converts the given string in the given input encoding to a new string of the given type and output encoding. - // Note: ConvertSafe uses the specified Recovery parameter to fix encoding errors, if the input is known-valid, use Convert. - template - inline OutputStringType ConvertSafe(const InputStringType& str, - typename Detail::SReqAnyObjOut::type* = 0) - { - OutputStringType result; - Detail::ConvertSafe(result, str); - return result; - } - - // OutputStringType ConvertSafe(str): - // Converts the (assumed) Unicode string input to a new Unicode string of the given type. - // The Unicode encodings are picked automatically depending on the input type and output type. - // Note: ConvertSafe uses the specified Recovery parameter to fix encoding errors, if the input is known-valid, use Convert. - template - inline OutputStringType ConvertSafe(const InputStringType& str, - typename Detail::SReqAutoObjOut::type* = 0) - { - const EEncoding InputEncoding = Detail::SInferEncoding::value; - const EEncoding OutputEncoding = Detail::SInferEncoding::value; - OutputStringType result; - Detail::ConvertSafe(result, str); - return result; - } - - // OutputStringType ConvertSafe(begin, end): - // Converts the given range in the given input encoding to a new string of the given type and output encoding. - // Note: ConvertSafe uses the specified Recovery parameter to fix encoding errors, if the input is known-valid, use Convert. - template - inline OutputStringType ConvertSafe(InputIteratorType begin, InputIteratorType end, - typename Detail::SReqAnyItsOut::type* = 0) - { - typedef Detail::SPackedIterators InputStringType; - const InputStringType its(begin, end); - OutputStringType result; - Detail::ConvertSafe(result, its); - return result; - } - - // OutputStringType ConvertSafe(begin, end): - // Converts the (assumed) Unicode range to a new Unicode string of the given type. - // The Unicode encodings are picked automatically depending on the range type and output type. - // Note: ConvertSafe uses the specified Recovery parameter to fix encoding errors, if the input is known-valid, use Convert. - template - inline OutputStringType ConvertSafe(InputIteratorType begin, InputIteratorType end, - typename Detail::SReqAutoItsOut::type* = 0) - { - const EEncoding InputEncoding = Detail::SInferEncoding::value; - const EEncoding OutputEncoding = Detail::SInferEncoding::value; - typedef Detail::SPackedIterators InputStringType; - const InputStringType its(begin, end); - OutputStringType result; - Detail::ConvertSafe(result, its); - return result; - } - - // OutputStringType &Append(result, str): - // Appends the given string in the given input encoding and stores at the end of the result string with the given output encoding. - // Note: Append assumes the input is valid encoded, if this is not guaranteed (ie, user-input), use AppendSafe. - template - inline OutputStringType& Append(OutputStringType& result, const InputStringType& str, - typename Detail::SReqAnyObjOut::type* = 0) - { - Detail::Convert(result, str); - return result; - } - - // OutputStringType &Append(result, str): - // Appends the (assumed) Unicode string input and stores at the end of the result Unicode string. - // The Unicode encodings are picked automatically depending on the input type and output type. - // Note: Append assumes the input is valid encoded, if this is not guaranteed (ie, user-input), use AppendSafe. - template - inline OutputStringType& Append(OutputStringType& result, const InputStringType& str, - typename Detail::SReqAutoObjOut::type* = 0) - { - const EEncoding InputEncoding = Detail::SInferEncoding::value; - const EEncoding OutputEncoding = Detail::SInferEncoding::value; - Detail::Convert(result, str); - return result; - } - - // OutputStringType &Append(result, begin, end): - // Appends the given range in the given input encoding and stores at the end of the result string with the given output encoding. - // Note: Append assumes the input is valid encoded, if this is not guaranteed (ie, user-input), use AppendSafe. - template - inline OutputStringType& Append(OutputStringType& result, InputIteratorType begin, InputIteratorType end, - typename Detail::SReqAnyItsOut::type* = 0) - { - typedef Detail::SPackedIterators InputStringType; - const InputStringType its(begin, end); - Detail::Convert(result, its); - return result; - } - - // OutputStringType &Append(result, begin, end): - // Appends the (assumed) Unicode range and stores at the end of the result Unicode string. - // The Unicode encodings are picked automatically depending on the range type and output type. - // Note: Append assumes the input is valid encoded, if this is not guaranteed (ie, user-input), use AppendSafe. - template - inline OutputStringType& Append(OutputStringType& result, InputIteratorType begin, InputIteratorType end, - typename Detail::SReqAutoItsOut::type* = 0) - { - const EEncoding InputEncoding = Detail::SInferEncoding::value; - const EEncoding OutputEncoding = Detail::SInferEncoding::value; - typedef Detail::SPackedIterators InputStringType; - const InputStringType its(begin, end); - Detail::Convert(result, its); - return result; - } - - // size_t Append(buffer, length, str): - // Appends the given string in the given input encoding to the result buffer with the given output encoding. - // Returns the required length of the output buffer, in code-units, including the null-terminator. - // Note: Append assumes the input is valid encoded, if this is not guaranteed (ie, user-input), use AppendSafe. - template - inline size_t Append(OutputCharType* buffer, size_t length, const InputStringType& str, - typename Detail::SReqAnyObjOut::type* = 0) - { - typedef Detail::SPackedBuffer OutputStringType; - OutputStringType result(buffer, length); - return Detail::Convert(result, str) + 1; - } - - // size_t Append(buffer, length, str): - // Appends the (assumed) Unicode string input to the result Unicode buffer. - // The Unicode encodings are picked automatically depending on the buffer type and output type. - // Returns the required length of the output buffer, in code-units, including the null-terminator. - // Note: Append assumes the input is valid encoded, if this is not guaranteed (ie, user-input), use AppendSafe. - template - inline size_t Append(OutputCharType* buffer, size_t length, const InputStringType& str, - typename Detail::SReqAutoObjOut::type* = 0) - { - const EEncoding InputEncoding = Detail::SInferEncoding::value; - const EEncoding OutputEncoding = Detail::SInferEncoding::value; - typedef Detail::SPackedBuffer OutputStringType; - OutputStringType result(buffer, length); - return Detail::Convert(result, str) + 1; - } - - // size_t Append(buffer, length, begin, end): - // Appends the given range in the given input encoding to the result buffer with the given output encoding. - // Returns the required length of the output buffer, in code-units, including the null-terminator. - // Note: Append assumes the input is valid encoded, if this is not guaranteed (ie, user-input), use AppendSafe. - template - inline size_t Append(OutputCharType* buffer, size_t length, InputIteratorType begin, InputIteratorType end, - typename Detail::SReqAnyItsOut::type* = 0) - { - typedef Detail::SPackedIterators InputStringType; - typedef Detail::SPackedBuffer OutputStringType; - const InputStringType its(begin, end); - OutputStringType result(buffer, length); - return Detail::Convert(result, its) + 1; - } - - // size_t Append(buffer, length, begin, end): - // Appends the (assumed) Unicode range to the result Unicode buffer. - // The Unicode encodings are picked automatically depending on the range type and output type. - // Returns the required length of the output buffer, in code-units, including the null-terminator. - // Note: Append assumes the input is valid encoded, if this is not guaranteed (ie, user-input), use AppendSafe. - template - inline size_t Append(OutputCharType* buffer, size_t length, InputIteratorType begin, InputIteratorType end, - typename Detail::SReqAutoItsOut::type* = 0) - { - const EEncoding InputEncoding = Detail::SInferEncoding::value; - const EEncoding OutputEncoding = Detail::SInferEncoding::value; - typedef Detail::SPackedIterators InputStringType; - typedef Detail::SPackedBuffer OutputStringType; - const InputStringType its(begin, end); - OutputStringType result(buffer, length); - return Detail::Convert(result, its) + 1; - } - - // OutputStringType &AppendSafe(result, str): - // Appends the given string in the given input encoding and stores at the end of the result string with the given output encoding. - // Note: AppendSafe uses the specified Recovery parameter to fix encoding errors, if the input is known-valid, use Append. - template - inline OutputStringType& AppendSafe(OutputStringType& result, const InputStringType& str, - typename Detail::SReqAnyObjOut::type* = 0) - { - Detail::ConvertSafe(result, str); - return result; - } - - // OutputStringType &AppendSafe(result, str): - // Appends the (assumed) Unicode string input and stores at the end of the result Unicode string. - // The Unicode encodings are picked automatically depending on the input type and output type. - // Note: AppendSafe uses the specified Recovery parameter to fix encoding errors, if the input is known-valid, use Append. - template - inline OutputStringType& AppendSafe(OutputStringType& result, const InputStringType& str, - typename Detail::SReqAutoObjOut::type* = 0) - { - const EEncoding InputEncoding = Detail::SInferEncoding::value; - const EEncoding OutputEncoding = Detail::SInferEncoding::value; - Detail::ConvertSafe(result, str); - return result; - } - - // OutputStringType &AppendSafe(result, begin, end): - // Appends the given range in the given input encoding and stores at the end of the result string with the given output encoding. - // Note: AppendSafe uses the specified Recovery parameter to fix encoding errors, if the input is known-valid, use Append. - template - inline OutputStringType& AppendSafe(OutputStringType& result, InputIteratorType begin, InputIteratorType end, - typename Detail::SReqAnyItsOut::type* = 0) - { - typedef Detail::SPackedIterators InputStringType; - const InputStringType its(begin, end); - Detail::ConvertSafe(result, its); - return result; - } - - // OutputStringType &AppendSafe(result, begin, end): - // Appends the (assumed) Unicode range and stores at the end of the result Unicode string. - // The Unicode encodings are picked automatically depending on the range type and output type. - // Note: AppendSafe uses the specified Recovery parameter to fix encoding errors, if the input is known-valid, use Append. - template - inline OutputStringType& AppendSafe(OutputStringType& result, InputIteratorType begin, InputIteratorType end, - typename Detail::SReqAutoItsOut::type* = 0) - { - const EEncoding InputEncoding = Detail::SInferEncoding::value; - const EEncoding OutputEncoding = Detail::SInferEncoding::value; - typedef Detail::SPackedIterators InputStringType; - const InputStringType its(begin, end); - Detail::ConvertSafe(result, its); - return result; - } - - // size_t AppendSafe(buffer, length, str): - // Appends the given string in the given input encoding to the result buffer with the given output encoding. - // Returns the required length of the output buffer, in code-units, including the null-terminator. - // Note: AppendSafe uses the specified Recovery parameter to fix encoding errors, if the input is known-valid, use Append. - template - inline size_t AppendSafe(OutputCharType* buffer, size_t length, const InputStringType& str, - typename Detail::SReqAnyObjOut::type* = 0) - { - typedef Detail::SPackedBuffer OutputStringType; - OutputStringType result(buffer, length); - return Detail::ConvertSafe(result, str) + 1; - } - - // size_t AppendSafe(buffer, length, str): - // Appends the (assumed) Unicode string input to the result Unicode buffer. - // The Unicode encodings are picked automatically depending on the buffer type and output type. - // Returns the required length of the output buffer, in code-units, including the null-terminator. - // Note: AppendSafe uses the specified Recovery parameter to fix encoding errors, if the input is known-valid, use Append. - template - inline size_t AppendSafe(OutputCharType* buffer, size_t length, const InputStringType& str, - typename Detail::SReqAutoObjOut::type* = 0) - { - const EEncoding InputEncoding = Detail::SInferEncoding::value; - const EEncoding OutputEncoding = Detail::SInferEncoding::value; - typedef Detail::SPackedBuffer OutputStringType; - OutputStringType result(buffer, length); - return Detail::ConvertSafe(result, str) + 1; - } - - // size_t AppendSafe(buffer, length, begin, end): - // Appends the given range in the given input encoding to the result buffer with the given output encoding. - // Returns the required length of the output buffer, in code-units, including the null-terminator. - // Note: AppendSafe uses the specified Recovery parameter to fix encoding errors, if the input is known-valid, use Append. - template - inline size_t AppendSafe(OutputCharType* buffer, size_t length, InputIteratorType begin, InputIteratorType end, - typename Detail::SReqAnyItsOut::type* = 0) - { - typedef Detail::SPackedIterators InputStringType; - typedef Detail::SPackedBuffer OutputStringType; - const InputStringType its(begin, end); - OutputStringType result(buffer, length); - return Detail::ConvertSafe(result, its) + 1; - } - - // size_t AppendSafe(buffer, length, begin, end): - // Appends the (assumed) Unicode range to the result Unicode buffer. - // The Unicode encodings are picked automatically depending on the range type and output type. - // Returns the required length of the output buffer, in code-units, including the null-terminator. - // Note: AppendSafe uses the specified Recovery parameter to fix encoding errors, if the input is known-valid, use Append. - template - inline size_t AppendSafe(OutputCharType* buffer, size_t length, InputIteratorType begin, InputIteratorType end, - typename Detail::SReqAutoItsOut::type* = 0) - { - const EEncoding InputEncoding = Detail::SInferEncoding::value; - const EEncoding OutputEncoding = Detail::SInferEncoding::value; - typedef Detail::SPackedIterators InputStringType; - typedef Detail::SPackedBuffer OutputStringType; - const InputStringType its(begin, end); - OutputStringType result(buffer, length); - return Detail::Convert(result, its) + 1; - } -} diff --git a/Code/Legacy/CryCommon/UnicodeIterator.h b/Code/Legacy/CryCommon/UnicodeIterator.h deleted file mode 100644 index d939eaa721..0000000000 --- a/Code/Legacy/CryCommon/UnicodeIterator.h +++ /dev/null @@ -1,615 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - -// Description : Encoded Unicode sequence iteration. -// -// For lower level accessing of encoded text, an STL compatible iterator wrapper is provided. -// This iterator will decode the underlying sequence, abstracting it to a sequence of UCS code-points. -// Using the iterator wrapper, you can find where in an encoded string code-points (or encoding errors) are located. -// Note: The iterator is an input-only iterator, you cannot write to the underlying sequence. - - -#pragma once -#include "UnicodeBinding.h" -namespace Unicode -{ - namespace Detail - { - // MoveNext(it, checker, tag): - // Moves the iterator to the next UCS code-point in the encoded sequence. - // Non-specialized version (for 1:1 code-unit to code-point). - template - inline void MoveNext(BaseIterator& it, const BoundsChecker& checker, const integral_constant) - { - COMPILE_TIME_ASSERT( - Encoding == eEncoding_ASCII || - Encoding == eEncoding_UTF32 || - Encoding == eEncoding_Latin1 || - Encoding == eEncoding_Win1252); - assert(!checker.IsEnd(it) && "Attempt to iterate past the end of the sequence"); - - // All of these encodings use a single code-unit for each code-point. - ++it; - } - - // MoveNext(it, checker, tag): - // Moves the iterator to the next UCS code-point in the encoded sequence. - // Specialized for UTF-8. - template - inline void MoveNext(BaseIterator& it, const BoundsChecker& checker, integral_constant) - { - assert(!checker.IsEnd(it) && "Attempt to iterate past the end of the sequence"); - - // UTF-8: just need to skip up to 3 continuation bytes. - for (int i = 0; i < 4; ++i) - { - ++it; - if (checker.IsEnd(it)) // :WARN: always returns false if "safe" bool is false! - { - break; - } - uint32 val = static_cast(*it); - if ((val & 0xC0) != 0x80) - { - break; - } - } - } - - // MoveNext(it, checker, tag): - // Moves the iterator to the next UCS code-point in the encoded sequence. - // Specialized for UTF-16. - template - inline void MoveNext(BaseIterator& it, const BoundsChecker& checker, integral_constant) - { - assert(!checker.IsEnd(it) && "Attempt to iterate past the end of the sequence"); - - // UTF-16: just need to skip one lead surrogate. - ++it; - uint32 val = static_cast(*it); - if (val >= cLeadSurrogateFirst && val <= cLeadSurrogateLast) - { - if (!checker.IsEnd(it)) - { - ++it; - } - } - } - - // MovePrev(it, checker, tag): - // Moves the iterator to the previous UCS code-point in the encoded sequence. - // Non-specialized version (for 1:1 code-unit to code-point). - template - inline void MovePrev(BaseIterator& it, const BoundsChecker& checker, const integral_constant) - { - COMPILE_TIME_ASSERT( - Encoding == eEncoding_ASCII || - Encoding == eEncoding_UTF32 || - Encoding == eEncoding_Latin1 || - Encoding == eEncoding_Win1252); - assert(!checker.IsBegin(it) && "Attempt to iterate past the beginning of the sequence"); - - // All of these encodings use a single code-unit for each code-point. - --it; - } - - // MovePrev(it, checker, tag): - // Moves the iterator to the previous UCS code-point in the encoded sequence. - // Specialized for UTF-8. - template - inline void MovePrev(BaseIterator& it, const BoundsChecker& checker, integral_constant) - { - assert(!checker.IsBegin(it) && "Attempt to iterate past the beginning of the sequence"); - - // UTF-8: just need to skip up to 3 continuation bytes. - for (int i = 0; i < 4; ++i) - { - --it; - if (checker.IsBegin(it)) - { - break; - } - uint32 val = static_cast(*it); - if ((val & 0xC0) != 0x80) - { - break; - } - } - } - - // MovePrev(it, checker, tag): - // Moves the iterator to the previous UCS code-point in the encoded sequence. - // Specialized for UTF-16. - template - inline void MovePrev(BaseIterator& it, const BoundsChecker& checker, integral_constant) - { - assert(!checker.IsBegin(it) && "Attempt to iterate past the beginning of the sequence"); - - // UTF-16: just need to skip one lead surrogate. - --it; - uint32 val = static_cast(*it); - if (val >= cLeadSurrogateFirst && val <= cLeadSurrogateLast) - { - if (!checker.IsBegin(it)) - { - --it; - } - } - } - - // SBaseIterators: - // Utility to access base iterators properties from CIterator. - // This is the bounds-checked specialization, the range information is kept to defend against malformed sequences. - template - struct SBaseIterators - { - typedef BaseIterator type; - type begin, end; - type it; - - SBaseIterators(const BaseIterator& _begin, const BaseIterator& _end) - : begin(_begin) - , end(_end) - , it(_begin) {} - - SBaseIterators(const SBaseIterators& other) - : begin(other.begin) - , end(other.end) - , it(other.it) {} - - SBaseIterators& operator =(const SBaseIterators& other) - { - begin = other.begin; - end = other.end; - it = other.it; - return *this; - } - - bool IsBegin(const BaseIterator& _it) const - { - return begin == _it; - } - - bool IsEnd(const BaseIterator& _it) const - { - return end == _it; - } - - bool IsEqual(const SBaseIterators& other) const - { - return it == other.it - && begin == other.begin - && end == other.end; - } - - // Note: Only called inside assert. - // O(N) version; works with any forward-iterator (or better) - bool IsInRange(const BaseIterator& _it, std::forward_iterator_tag) const - { - for (BaseIterator i = begin; i != end; ++i) - { - if (_it == i) - { - return true; - } - } - return false; - } - - // Note: Only called inside assert. - // O(1) version; requires random-access-iterator. - bool IsInRange(const BaseIterator& _it, std::random_access_iterator_tag) const - { - return (begin <= _it && _it < end); - } - - // Note: Only called inside assert. - // Dispatches to the O(1) version if a random-access iterator is used (common case). - bool IsInRange(const BaseIterator& _it) const - { - return IsInRange(_it, typename std::iterator_traits::iterator_category()); - } - }; - - // SBaseIterators: - // Utility to access base iterators properties from CIterator. - // This is the un-checked specialization for known-safe sequences. - template - struct SBaseIterators - { - typedef BaseIterator type; - type it; - - explicit SBaseIterators(const BaseIterator& begin) - : it(begin) {} - - SBaseIterators(const BaseIterator& begin, const BaseIterator& end) - : it(begin) {} - - SBaseIterators(const SBaseIterators& other) - : it(other.it) {} - - SBaseIterators& operator =(const SBaseIterators& other) - { - it = other.it; - return *this; - } - - bool IsBegin(const BaseIterator&) const - { - return false; - } - - bool IsEnd(const BaseIterator&) const - { - return false; - } - - bool IsEqual(const SBaseIterators& other) const - { - return it == other.it; - } - - bool IsInRange(const BaseIterator&) const - { - return true; - } - }; - - // SIteratorSink: - // Helper to store the last code-point and error bit that was decoded. - // This is the safe specialization for potentially malformed sequences. - template - struct SIteratorSink - { - static const uint32 cEmpty = 0xFFFFFFFFU; - uint32 value; - bool error; - - void Clear() - { - value = cEmpty; - error = false; - } - - bool IsEmpty() const - { - return value == cEmpty; - } - - bool IsError() const - { - return error; - } - - const uint32& GetValue() const - { - return value; - } - - void MarkDecodingError() - { - value = cReplacementCharacter; - error = true; - } - - template - void Decode(const SBaseIterators& its, integral_constant) - { - typedef SDecoder DecoderType; - DecoderType decoder(*this, *this); - Clear(); - for (BaseIterator it = its.it; IsEmpty(); ++it) - { - uint32 val = static_cast(*it); - decoder(val); - if (its.IsEnd(it)) - { - break; - } - } - if (IsEmpty()) - { - // If we still have neither a new value or an error flag, just treat as error. - // This can happen if we reached the end of the sequence, but it ends in an incomplete code-sequence. - MarkDecodingError(); - } - } - - template - void DecodeIfEmpty(const SBaseIterators& its, integral_constant tag) - { - if (IsEmpty()) - { - Decode(its, tag); - } - } - - void operator()(uint32 unit) - { - value = unit; - } - - void operator()(SIteratorSink&, uint32, uint32) - { - MarkDecodingError(); - } - }; - - // SIteratorSink: - // Helper to store the last code-point that was decoded. - // This is the un-safe specialization for known-valid sequences. - // Note: No error-state is tracked since we won't handle that regardless for un-safe CIterator. - template<> - struct SIteratorSink - { - static const uint32 cEmpty = 0xFFFFFFFFU; - uint32 value; - - void Clear() - { - value = cEmpty; - } - - bool IsEmpty() const - { - return value == cEmpty; - } - - bool IsError() const - { - return false; - } - - const uint32& GetValue() const - { - return value; - } - - template - void Decode(const SBaseIterators& its, integral_constant) - { - typedef SDecoder DecoderType; - DecoderType decoder(*this); - for (BaseIterator it = its.it; IsEmpty(); ++it) - { - uint32 val = static_cast(*it); - decoder(val); - } - } - - template - void DecodeIfEmpty(const SBaseIterators& its, integral_constant tag) - { - if (IsEmpty()) - { - Decode(its, tag); - } - } - - void operator()(uint32 unit) - { - value = unit; - } - }; - } - - // CIterator: - // Helper class that can iterate over an encoded text sequence and read the underlying UCS code-points. - // If the Safe flag is set, bounds checking is performed inside multi-unit sequences to guard against decoding errors. - // This requires the user to know where the sequence ends (use the constructor taking two parameters). - // Note: The BaseIterator must be forward-iterator or better when Safe flag is set. - // If the Safe flag is not set, you must guarantee the sequence is validly encoded, and allows the use of the single argument constructor. - // In the case of unsafe iterator used for C-style string pointer, look for a U+0000 dereferenced value to end the iteration. - // Regardless of the Safe flag, the user must ensure that the iterator is never moved past the beginning or end of the range (just like any other STL iterator). - // Example of typical usage: - // string utf8 = "foo"; // UTF-8 - // for (Unicode::CIterator it(utf8.begin(), utf8.end()); it != utf8.end(); ++it) - // { - // uint32 codepoint = *it; // 32-bit UCS code-point - // } - // Example unsafe usage: (for known-valid encoded C-style strings): - // const char *pValid = "foo"; // UTF-8 - // for (Unicode::CIterator it = pValid; *it != 0; ++it) - // { - // uint32 codepoint = *it; // 32-bit UCS code-point - // } - template::value> - class CIterator - { - // The iterator value in the encoded sequence. - // Optionally provides bounds-checking. - Detail::SBaseIterators its; - - // The cached UCS code-point at the current position. - // Mutable because dereferencing is conceptually const, but does cache some state in this case. - mutable Detail::SIteratorSink sink; - - public: - // Types for compatibility with STL bidirectional iterator requirements. - typedef const uint32 value_type; - typedef const uint32& reference; - typedef const uint32* pointer; - typedef const ptrdiff_t difference_type; - typedef std::bidirectional_iterator_tag iterator_category; - - // Construct an iterator for the given range. - // The initial position of the iterator as at the beginning of the range. - CIterator(const BaseIterator& begin, const BaseIterator& end) - : its(begin, end) - { - sink.Clear(); - } - - // Construct an iterator from a single iterator (typically C-style string pointer). - // This can only be used for unsafe iterators. - template - CIterator(const IteratorType& it, typename Detail::SRequire::value, IteratorType>::type* = 0) - : its(static_cast(it)) - { - sink.Clear(); - } - - // Copy-construct an iterator. - CIterator(const CIterator& other) - : its(other.its) - , sink(other.sink) {} - - // Copy-assign an iterator. - CIterator& operator =(const CIterator& other) - { - its = other.its; - sink = other.sink; - return *this; - } - - // Test if the iterator points at an encoding error in the underlying encoded sequence. - // If so, the function returns false. - // When using an un-safe iterator, this function always returns true, if a sequence can contain encoding errors, you must use the safe variant. - // Note: This requires the underlying iterator to be dereferenced, so you cannot use it only while the iterator is inside the valid range. - bool IsAtValidCodepoint() const - { - assert(!its.IsEnd(its.it) && "Attempt to dereference the past-the-end iterator"); - Detail::integral_constant tag; - sink.DecodeIfEmpty(its, tag); - return !sink.IsError(); - } - - // Gets the current position in the underlying encoded sequence. - // If the iterator points to an invalidly encoded sequence (ie, IsError() returns true), the direction of iteration is significant. - // In that case the returned position is approximated; to work around this: move all iterators of which the position is compared in the same direction. - const BaseIterator& GetPosition() const - { - return its.it; - } - - // Sets the current position in the underlying encoded sequence. - // You may not set the position outside the range for which this iterator was constructed. - void SetPosition(const BaseIterator& it) - { - assert(its.IsInRange(it) && "Attempt to set the underlying iterator outside of the supported range"); - its.it = it; - } - - // Test if this iterator is equal to another iterator instance. - // Note: In the presence of an invalidly encoded sequence (ie, IsError() returns true), the direction of iteration is significant. - // To work around this, you can either: - // 1) Move all iterators that will be compared in the same direction; or - // 2) Compare the dereferenced iterator value(s) instead (if applicable). - bool operator ==(const CIterator& other) const - { - return its.IsEqual(other.its); - } - - // Test if this iterator is equal to another base iterator. - // Note: If the provided iterator does not point to the the first code-unit of an UCS code-point, the behavior is undefined. - bool operator ==(const BaseIterator& other) const - { - return its.it == other; - } - - // Test if this iterator is equal to another iterator instance. - // Note: In the presence of an invalidly encoded sequence (ie, IsError() returns true), the direction of iteration is significant. - // To work around this, you can either: - // 1) Move all iterators that will be compared in the same direction; or - // 2) Compare the dereferenced iterator value(s) instead (if applicable). - bool operator !=(const CIterator& other) const - { - return !its.IsEqual(other.its); - } - - // Test if this iterator is equal to another base iterator. - // Note: If the provided iterator does not point to the the first code-unit of an UCS code-point, the behavior is undefined. - bool operator !=(const BaseIterator& other) const - { - return its.it != other; - } - - // Get the decoded UCS code-point at the current position in the sequence. - // If the iterator points to an invalidly encoded sequence (ie, IsError() returns true) the function returns U+FFFD (replacement character). - reference operator *() const - { - assert(!its.IsEnd(its.it) && "Attempt to dereference the past-the-end iterator"); - Detail::integral_constant tag; - sink.DecodeIfEmpty(its, tag); - return sink.GetValue(); - } - - // Advance the iterator to the next UCS code-point. - // Note: You must make sure the iterator is not at the end of the sequence, even in Safe mode. - // However, in Safe mode, the iterator will never move past the end of the sequence in the presence of encoding errors. - CIterator& operator ++() - { - Detail::integral_constant tag; - Detail::MoveNext(its.it, its, tag); - sink.Clear(); - return *this; - } - - // Go back to the previous UCS code-point. - // Note: You must make sure the iterator is not at the beginning of the sequence, even in Safe mode. - // However, in Safe mode, the iterators will never move past the beginning of the sequence in the presence of encoding errors. - CIterator& operator --() - { - Detail::integral_constant tag; - Detail::MovePrev(its.it, its, tag); - sink.Clear(); - return *this; - } - - // Advance the iterator to the next UCS code-point, return a copy of the iterator position before advancing. - // Note: You must make sure the iterator is not at the end of the sequence, even in Safe mode. - // However, in Safe mode, the iterator will never move past the end of the sequence in the presence of encoding errors. - CIterator operator ++(int) - { - CIterator result = *this; - ++*this; - return result; - } - - // Go back to the previous UCS code-point, return a copy of the iterator position before going back. - // Note: You must make sure the iterator is not at the beginning of the sequence, even in Safe mode. - // However, in Safe mode, the iterators will never move past the beginning of the sequence in the presence of encoding errors. - CIterator operator --(int) - { - CIterator result = *this; - --*this; - return result; - } - }; - - namespace Detail - { - // SIteratorSpecializer: - // Specializes the CIterator template to use for a given string type. - // Note: The reason we use this is because MSVC doesn't want to deduce this on the MakeIterator declaration. - template - struct SIteratorSpecializer - { - typedef CIterator type; - }; - } - - // MakeIterator(const StringType &str): - // Helper function to make an UCS code-point iterator given an Unicode string. - // Example usage: - // string utf8 = "foo"; // UTF-8 - // auto it = Unicode::MakeIterator(utf8); - // while (it != utf8.end()) - // { - // uint32 codepoint = *it; // 32-bit UCS code-point - // } - // Or, in a for-loop: - // for (auto it = Unicode::MakeIterator(utf8); it != utf8.end(); ++it) {} - template - inline typename Detail::SIteratorSpecializer::type MakeIterator(const StringType& str) - { - return typename Detail::SIteratorSpecializer::type(str.begin(), str.end()); - } -} diff --git a/Code/Legacy/CryCommon/crycommon_files.cmake b/Code/Legacy/CryCommon/crycommon_files.cmake index 63c5b49513..c78a6a4df0 100644 --- a/Code/Legacy/CryCommon/crycommon_files.cmake +++ b/Code/Legacy/CryCommon/crycommon_files.cmake @@ -116,10 +116,6 @@ set(FILES TimeValue_info.h TypeInfo_decl.h TypeInfo_impl.h - UnicodeBinding.h - UnicodeEncoding.h - UnicodeFunctions.h - UnicodeIterator.h VectorMap.h VectorSet.h VertexFormats.h From b86349c3bf909d8181af535cd6efff77c8a8b446 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Thu, 29 Jul 2021 15:50:39 -0700 Subject: [PATCH 041/803] Some fixes for AzCore Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../AzCore/Debug/StackTracer_Windows.cpp | 18 +++++++-------- .../IO/Streamer/StorageDrive_Windows.cpp | 15 +++++++++---- .../AzCore/IPC/SharedMemory_Windows.cpp | 13 +++++++---- .../NativeUISystemComponent_Windows.cpp | 13 ++++++++--- .../Windows/AzCore/Platform_Windows.cpp | 8 +++---- .../Windows/AzCore/Utils/Utils_Windows.cpp | 7 +++++- .../std/parallel/internal/thread_Windows.cpp | 22 +++++++++++-------- 7 files changed, 62 insertions(+), 34 deletions(-) diff --git a/Code/Framework/AzCore/Platform/Windows/AzCore/Debug/StackTracer_Windows.cpp b/Code/Framework/AzCore/Platform/Windows/AzCore/Debug/StackTracer_Windows.cpp index d2cdac84c7..8a99616de3 100644 --- a/Code/Framework/AzCore/Platform/Windows/AzCore/Debug/StackTracer_Windows.cpp +++ b/Code/Framework/AzCore/Platform/Windows/AzCore/Debug/StackTracer_Windows.cpp @@ -90,7 +90,7 @@ namespace AZ { { case CBA_EVENT: evt = (PIMAGEHLP_CBA_EVENT)CallbackData; - _tprintf(_T("%s"), (PTSTR)evt->desc); + _tprintf(_T("%s"), evt->desc); break; default: @@ -300,7 +300,7 @@ namespace AZ { return; } - const HMODULE hNtDll = GetModuleHandle(_T("ntdll.dll")); + const HMODULE hNtDll = GetModuleHandleW(L"ntdll.dll"); m_LdrRegisterDllNotification = reinterpret_cast(GetProcAddress(hNtDll, "LdrRegisterDllNotification")); if (m_LdrRegisterDllNotification) @@ -324,7 +324,7 @@ namespace AZ { return; } - const HMODULE hNtDll = GetModuleHandle(_T("ntdll.dll")); + const HMODULE hNtDll = GetModuleHandleW(L"ntdll.dll"); m_LdrUnregisterDllNotification = reinterpret_cast(GetProcAddress(hNtDll, "LdrUnregisterDllNotification")); if (m_LdrUnregisterDllNotification) @@ -609,8 +609,8 @@ namespace AZ { if (GetFileVersionInfoA(szImg, dwHandle, dwSize, vData) != 0) { UINT len; - TCHAR szSubBlock[] = _T("\\"); - if (VerQueryValue(vData, szSubBlock, (LPVOID*) &fInfo, &len) == 0) + TCHAR szSubBlock[] = L"\\"; + if (VerQueryValueW(vData, szSubBlock, (LPVOID*) &fInfo, &len) == 0) { fInfo = NULL; } @@ -711,7 +711,7 @@ namespace AZ { typedef BOOL (__stdcall * tM32N)(HANDLE hSnapshot, LPMODULEENTRY32 lpme); // try both dlls... - const TCHAR* dllname[] = { _T("kernel32.dll"), _T("tlhelp32.dll") }; + const TCHAR* dllname[] = { L"kernel32.dll", L"tlhelp32.dll" }; HINSTANCE hToolhelp = NULL; tCT32S pCT32S = NULL; tM32F pM32F = NULL; @@ -822,7 +822,7 @@ namespace AZ { const SIZE_T TTBUFLEN = 8096; int cnt = 0; - hPsapi = LoadLibrary(_T("psapi.dll")); + hPsapi = LoadLibraryW(L"psapi.dll"); if (hPsapi == NULL) { return FALSE; @@ -956,10 +956,10 @@ cleanup: // In that scenario, we may try to load and older dbghelp.dll which could cause issues // To overcome this, we try to load dbghelp.dll from the Win 10 SDK folder, if that doesn't // work, load the default. - g_dbgHelpDll = LoadLibrary(_T(R"(C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\dbghelp.dll)")); + g_dbgHelpDll = LoadLibraryW(LR"(C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\dbghelp.dll)"); if (g_dbgHelpDll == NULL) { - g_dbgHelpDll = LoadLibrary(_T("dbghelp.dll")); + g_dbgHelpDll = LoadLibrary(L"dbghelp.dll"); } } if (g_dbgHelpDll == NULL) diff --git a/Code/Framework/AzCore/Platform/Windows/AzCore/IO/Streamer/StorageDrive_Windows.cpp b/Code/Framework/AzCore/Platform/Windows/AzCore/IO/Streamer/StorageDrive_Windows.cpp index 671cc99aac..2489749b51 100644 --- a/Code/Framework/AzCore/Platform/Windows/AzCore/IO/Streamer/StorageDrive_Windows.cpp +++ b/Code/Framework/AzCore/Platform/Windows/AzCore/IO/Streamer/StorageDrive_Windows.cpp @@ -16,6 +16,7 @@ #include #include #include +#include namespace AZ::IO { @@ -467,8 +468,10 @@ namespace AZ::IO DWORD createFlags = m_constructionOptions.m_enableUnbufferedReads ? (FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING) : FILE_FLAG_OVERLAPPED; DWORD shareMode = (m_constructionOptions.m_enableSharing || data.m_sharedRead) ? FILE_SHARE_READ: 0; - file = ::CreateFile( - data.m_path.GetAbsolutePath(), // file name + AZStd::wstring filenameW; + AZStd::to_wstring(filenameW, data.m_path.GetAbsolutePath()); + file = ::CreateFileW( + filenameW.c_str(), // file name FILE_GENERIC_READ, // desired access shareMode, // share mode nullptr, // security attributes @@ -806,7 +809,9 @@ namespace AZ::IO } WIN32_FILE_ATTRIBUTE_DATA attributes; - if (::GetFileAttributesEx(fileExists.m_path.GetAbsolutePath(), GetFileExInfoStandard, &attributes)) + AZStd::wstring filenameW; + AZStd::to_wstring(filenameW, fileExists.m_path.GetAbsolutePath()); + if (::GetFileAttributesExW(filenameW.c_str(), GetFileExInfoStandard, &attributes)) { if ((attributes.dwFileAttributes != INVALID_FILE_ATTRIBUTES) && ((attributes.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)) @@ -863,7 +868,9 @@ namespace AZ::IO else { WIN32_FILE_ATTRIBUTE_DATA attributes; - if (::GetFileAttributesEx(command.m_path.GetAbsolutePath(), GetFileExInfoStandard, &attributes) && + AZStd::wstring filenameW; + AZStd::to_wstring(filenameW, command.m_path.GetAbsolutePath()); + if (::GetFileAttributesExW(filenameW.c_str(), GetFileExInfoStandard, &attributes) && (attributes.dwFileAttributes != INVALID_FILE_ATTRIBUTES) && ((attributes.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)) { fileSize.LowPart = attributes.nFileSizeLow; diff --git a/Code/Framework/AzCore/Platform/Windows/AzCore/IPC/SharedMemory_Windows.cpp b/Code/Framework/AzCore/Platform/Windows/AzCore/IPC/SharedMemory_Windows.cpp index 0797541652..21b2a76ba0 100644 --- a/Code/Framework/AzCore/Platform/Windows/AzCore/IPC/SharedMemory_Windows.cpp +++ b/Code/Framework/AzCore/Platform/Windows/AzCore/IPC/SharedMemory_Windows.cpp @@ -10,6 +10,7 @@ #include #include +#include namespace AZ { @@ -41,7 +42,9 @@ namespace AZ SetSecurityDescriptorDacl(secAttr.lpSecurityDescriptor, TRUE, 0, FALSE); // Obtain global mutex - m_globalMutex = CreateMutex(&secAttr, FALSE, fullName); + AZStd::wstring fullNameW; + AZStd::to_wstring(fullNameW, fullName); + m_globalMutex = CreateMutexW(&secAttr, FALSE, fullNameW.c_str()); DWORD error = GetLastError(); if (m_globalMutex == NULL || (error == ERROR_ALREADY_EXISTS && openIfCreated == false)) { @@ -51,7 +54,7 @@ namespace AZ // Create the file mapping. azsnprintf(fullName, AZ_ARRAY_SIZE(fullName), "%s_Data", name); - m_mapHandle = CreateFileMapping(INVALID_HANDLE_VALUE, &secAttr, PAGE_READWRITE, 0, size, fullName); + m_mapHandle = CreateFileMappingW(INVALID_HANDLE_VALUE, &secAttr, PAGE_READWRITE, 0, size, fullNameW.c_str()); error = GetLastError(); if (m_mapHandle == NULL || (error == ERROR_ALREADY_EXISTS && openIfCreated == false)) { @@ -66,8 +69,10 @@ namespace AZ { char fullName[256]; ComposeMutexName(fullName, AZ_ARRAY_SIZE(fullName), name); + AZStd::wstring fullNameW; + AZStd::to_wstring(fullNameW, fullName); - m_globalMutex = OpenMutex(SYNCHRONIZE, TRUE, fullName); + m_globalMutex = OpenMutex(SYNCHRONIZE, TRUE, fullNameW.c_str()); AZ_Warning("AZSystem", m_globalMutex != NULL, "Failed to open OS mutex [%s]\n", m_name); if (m_globalMutex == NULL) { @@ -76,7 +81,7 @@ namespace AZ } azsnprintf(fullName, AZ_ARRAY_SIZE(fullName), "%s_Data", name); - m_mapHandle = OpenFileMapping(FILE_MAP_WRITE, false, fullName); + m_mapHandle = OpenFileMapping(FILE_MAP_WRITE, false, fullNameW.c_str()); if (m_mapHandle == NULL) { AZ_TracePrintf("AZSystem", "OpenFileMapping %s failed with error %d\n", m_name, GetLastError()); diff --git a/Code/Framework/AzCore/Platform/Windows/AzCore/NativeUI/NativeUISystemComponent_Windows.cpp b/Code/Framework/AzCore/Platform/Windows/AzCore/NativeUI/NativeUISystemComponent_Windows.cpp index 568f727905..af2a629092 100644 --- a/Code/Framework/AzCore/Platform/Windows/AzCore/NativeUI/NativeUISystemComponent_Windows.cpp +++ b/Code/Framework/AzCore/Platform/Windows/AzCore/NativeUI/NativeUISystemComponent_Windows.cpp @@ -10,6 +10,7 @@ #include #include +#include namespace { @@ -105,11 +106,17 @@ namespace { // Set the text for window title, message, buttons. info = (DlgInfo*)lParam; - SetWindowText(hDlg, info->m_title.c_str()); - SetWindowText(GetDlgItem(hDlg, 0), info->m_message.c_str()); + AZStd::wstring titleW; + AZStd::to_wstring(titleW, info->m_title.c_str()); + SetWindowTextW(hDlg, titleW.c_str()); + AZStd::wstring messageW; + AZStd::to_wstring(messageW, info->m_message.c_str()); + SetWindowTextW(GetDlgItem(hDlg, 0), messageW.c_str()); for (int i = 0; i < info->m_options.size(); i++) { - SetWindowText(GetDlgItem(hDlg, i + 1), info->m_options[i].c_str()); + AZStd::wstring optionW; + AZStd::to_wstring(optionW, info->m_options[i].c_str()); + SetWindowTextW(GetDlgItem(hDlg, i + 1), optionW.c_str()); } } break; diff --git a/Code/Framework/AzCore/Platform/Windows/AzCore/Platform_Windows.cpp b/Code/Framework/AzCore/Platform/Windows/AzCore/Platform_Windows.cpp index 27e0bd11e1..dc675cd931 100644 --- a/Code/Framework/AzCore/Platform/Windows/AzCore/Platform_Windows.cpp +++ b/Code/Framework/AzCore/Platform/Windows/AzCore/Platform_Windows.cpp @@ -37,7 +37,7 @@ namespace AZ { DWORD dataType = REG_SZ; DWORD dataSize = sizeof(machineInfo); - ret = RegQueryValueEx(key, "MachineGuid", 0, &dataType, (LPBYTE)machineInfo, &dataSize); + ret = RegQueryValueExW(key, L"MachineGuid", 0, &dataType, (LPBYTE)machineInfo, &dataSize); RegCloseKey(key); } else @@ -45,7 +45,7 @@ namespace AZ AZ_Error("System", false, "Failed to open HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Cryptography\\MachineGuid!") } - TCHAR* hostname = machineInfo + _tcslen(machineInfo); + TCHAR* hostname = machineInfo + wcslen(machineInfo); // salt the guid time with ComputerName/UserName DWORD bufCharCount = DWORD(sizeof(machineInfo) - (hostname - machineInfo)); if (!::GetComputerName(hostname, &bufCharCount)) @@ -53,7 +53,7 @@ namespace AZ AZ_Error("System", false, "GetComputerName filed with code %d", GetLastError()); } - TCHAR* username = hostname + _tcslen(hostname); + TCHAR* username = hostname + wcslen(hostname); bufCharCount = DWORD(sizeof(machineInfo) - (username - machineInfo)); if( !GetUserName( username, &bufCharCount ) ) { @@ -62,7 +62,7 @@ namespace AZ Sha1 hash; AZ::u32 digest[5] = { 0 }; - hash.ProcessBytes(machineInfo, _tcslen(machineInfo) * sizeof(TCHAR)); + hash.ProcessBytes(machineInfo, wcslen(machineInfo) * sizeof(TCHAR)); hash.GetDigest(digest); s_machineId = digest[0]; if (s_machineId == 0) diff --git a/Code/Framework/AzCore/Platform/Windows/AzCore/Utils/Utils_Windows.cpp b/Code/Framework/AzCore/Platform/Windows/AzCore/Utils/Utils_Windows.cpp index 749cf1ba82..fd8353b45f 100644 --- a/Code/Framework/AzCore/Platform/Windows/AzCore/Utils/Utils_Windows.cpp +++ b/Code/Framework/AzCore/Platform/Windows/AzCore/Utils/Utils_Windows.cpp @@ -8,6 +8,7 @@ #include #include +#include #include @@ -15,7 +16,11 @@ namespace AZ::Utils { void NativeErrorMessageBox(const char* title, const char* message) { - ::MessageBox(0, message, title, MB_OK | MB_ICONERROR); + AZStd::wstring wtitle; + AZStd::to_wstring(wtitle, title); + AZStd::wstring wmessage; + AZStd::to_wstring(wmessage, message); + ::MessageBoxW(0, wmessage.c_str(), wtitle.c_str(), MB_OK | MB_ICONERROR); } AZ::IO::FixedMaxPathString GetHomeDirectory() diff --git a/Code/Framework/AzCore/Platform/Windows/AzCore/std/parallel/internal/thread_Windows.cpp b/Code/Framework/AzCore/Platform/Windows/AzCore/std/parallel/internal/thread_Windows.cpp index ea92a16838..246181334a 100644 --- a/Code/Framework/AzCore/Platform/Windows/AzCore/std/parallel/internal/thread_Windows.cpp +++ b/Code/Framework/AzCore/Platform/Windows/AzCore/std/parallel/internal/thread_Windows.cpp @@ -8,6 +8,7 @@ #include #include +#include #include @@ -37,17 +38,20 @@ namespace AZStd // SetThreadDescription was added in 1607 (aka RS1). Since we can't guarantee the user is running 1607 or later, we need to ask for the function from the kernel. using SetThreadDescriptionFunc = HRESULT(WINAPI*)(_In_ HANDLE hThread, _In_ PCWSTR lpThreadDescription); - auto setThreadDescription = reinterpret_cast(::GetProcAddress(::GetModuleHandle("Kernel32.dll"), "SetThreadDescription")); - if (setThreadDescription) + HMODULE kernel32Handle = ::GetModuleHandleW(L"Kernel32.dll"); + if (kernel32Handle) { - // Convert the thread name to Unicode - wchar_t threadNameW[MAX_PATH]; - size_t numCharsConverted; - errno_t wcharResult = mbstowcs_s(&numCharsConverted, threadNameW, threadName, AZ_ARRAY_SIZE(threadNameW) - 1); - if (wcharResult == 0) + SetThreadDescriptionFunc setThreadDescription = reinterpret_cast(::GetProcAddress(kernel32Handle, "SetThreadDescription")); + if (setThreadDescription) { - setThreadDescription(hThread, threadNameW); - return true; + // Convert the thread name to Unicode + AZStd::wstring threadNameW; + AZStd::to_wstring(threadNameW, threadName); + if (!threadNameW.empty()) + { + setThreadDescription(hThread, threadNameW.c_str()); + return true; + } } } From 95c6fd83ead69bad55b067fe3eb3a9549064738a Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Thu, 29 Jul 2021 15:53:16 -0700 Subject: [PATCH 042/803] remove !defined(RESOURCE_COMPILER) since is not defined anywhere (resource compiler was removed) Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Legacy/CryCommon/ILog.h | 2 -- Code/Legacy/CryCommon/IXml.h | 10 ---------- Code/Legacy/CryCommon/ProjectDefines.h | 7 ++----- Code/Legacy/CryCommon/platform_impl.cpp | 2 -- 4 files changed, 2 insertions(+), 19 deletions(-) diff --git a/Code/Legacy/CryCommon/ILog.h b/Code/Legacy/CryCommon/ILog.h index de60c1e9e0..e71e1f036d 100644 --- a/Code/Legacy/CryCommon/ILog.h +++ b/Code/Legacy/CryCommon/ILog.h @@ -145,9 +145,7 @@ struct ILog virtual void Unindent(class CLogIndenter* indenter) = 0; #endif -#if !defined(RESOURCE_COMPILER) virtual void FlushAndClose() = 0; -#endif }; #if !defined(SUPPORT_LOG_IDENTER) diff --git a/Code/Legacy/CryCommon/IXml.h b/Code/Legacy/CryCommon/IXml.h index e4cb752234..a380ce167b 100644 --- a/Code/Legacy/CryCommon/IXml.h +++ b/Code/Legacy/CryCommon/IXml.h @@ -147,13 +147,11 @@ public: XmlNodeRef& operator=(IXmlNode* newp); XmlNodeRef& operator=(const XmlNodeRef& newp); -#if !defined(RESOURCE_COMPILER) template void GetMemoryUsage(Sizer* pSizer) const { pSizer->AddObject(p); } -#endif //Support for range based for, and stl algorithms. class XmlNodeRefIterator begin(); @@ -399,7 +397,6 @@ public: // -#if !defined(RESOURCE_COMPILER) // // Summary: // Collect all allocated memory @@ -423,7 +420,6 @@ public: // Save in small memory chunks. virtual bool saveToFile(const char* fileName, size_t chunkSizeBytes, AZ::IO::HandleType fileHandle = AZ::IO::InvalidHandle) = 0; // -#endif //##@} @@ -792,12 +788,9 @@ struct IXmlSerializer virtual ISerialize* GetWriter(XmlNodeRef& node) = 0; virtual ISerialize* GetReader(XmlNodeRef& node) = 0; // -#if !defined(RESOURCE_COMPILER) virtual void GetMemoryUsage(ICrySizer* pSizer) const = 0; -#endif }; -#if !defined(RESOURCE_COMPILER) ////////////////////////////////////////////////////////////////////////// // Summary: // XML Parser interface. @@ -867,7 +860,6 @@ struct IXmlTableReader virtual float GetCurrentRowHeight() = 0; // }; -#endif ////////////////////////////////////////////////////////////////////////// // Summary: @@ -900,7 +892,6 @@ struct IXmlUtils virtual IXmlSerializer* CreateXmlSerializer() = 0; // -#if !defined(RESOURCE_COMPILER) // // Summary: // Creates XML Parser. @@ -945,7 +936,6 @@ struct IXmlUtils // Set to NULL to clear an existing transform and disable further patching virtual void SetXMLPatcher(XmlNodeRef* pPatcher) = 0; // -#endif }; #endif // CRYINCLUDE_CRYCOMMON_IXML_H diff --git a/Code/Legacy/CryCommon/ProjectDefines.h b/Code/Legacy/CryCommon/ProjectDefines.h index 3d635c491c..e359fe669b 100644 --- a/Code/Legacy/CryCommon/ProjectDefines.h +++ b/Code/Legacy/CryCommon/ProjectDefines.h @@ -42,10 +42,7 @@ // Type used for vertex indices // WARNING: If you change this typedef, you need to update AssetProcessorPlatformConfig.ini to convert cgf and abc files to the proper index format. -#if defined(RESOURCE_COMPILER) -typedef uint32 vtx_idx; -#define AZ_RESTRICTED_SECTION_IMPLEMENTED -#elif defined(MOBILE) +#if defined(MOBILE) typedef uint16 vtx_idx; #define AZ_RESTRICTED_SECTION_IMPLEMENTED #elif defined(AZ_RESTRICTED_PLATFORM) @@ -138,7 +135,7 @@ typedef uint32 vtx_idx; # define PHYSICS_STACK_SIZE (128U << 10) #endif -#if (!defined(_RELEASE) || defined(PERFORMANCE_BUILD)) && !defined(RESOURCE_COMPILER) +#if (!defined(_RELEASE) || defined(PERFORMANCE_BUILD)) #ifndef ENABLE_PROFILING_CODE #define ENABLE_PROFILING_CODE #endif diff --git a/Code/Legacy/CryCommon/platform_impl.cpp b/Code/Legacy/CryCommon/platform_impl.cpp index 6ec8df0365..54bf38aaa0 100644 --- a/Code/Legacy/CryCommon/platform_impl.cpp +++ b/Code/Legacy/CryCommon/platform_impl.cpp @@ -240,13 +240,11 @@ void CryLowLatencySleep(unsigned int dwMilliseconds) int CryMessageBox([[maybe_unused]] const char* lpText, [[maybe_unused]] const char* lpCaption, [[maybe_unused]] unsigned int uType) { #ifdef WIN32 -#if !defined(RESOURCE_COMPILER) ICVar* const pCVar = gEnv && gEnv->pConsole ? gEnv->pConsole->GetCVar("sys_no_crash_dialog") : NULL; if ((pCVar && pCVar->GetIVal() != 0) || (gEnv && gEnv->bNoAssertDialog)) { return 0; } -#endif return MessageBox(NULL, lpText, lpCaption, uType); #else return 0; From 99bf5e54c4a7db18bf20b3029259771375d3ddc8 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Thu, 29 Jul 2021 15:53:32 -0700 Subject: [PATCH 043/803] More string fixes Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Legacy/CryCommon/IMovieSystem.h | 11 +- Code/Legacy/CryCommon/LyShine/ILyShine.h | 10 +- Code/Legacy/CrySystem/CmdLine.h | 8 +- Code/Legacy/CrySystem/CmdLineArg.h | 4 +- Code/Legacy/CrySystem/ConsoleBatchFile.cpp | 26 +-- Code/Legacy/CrySystem/ConsoleHelpGen.cpp | 68 +++--- Code/Legacy/CrySystem/ConsoleHelpGen.h | 10 +- Code/Legacy/CrySystem/DebugCallStack.cpp | 38 ++-- Code/Legacy/CrySystem/DebugCallStack.h | 10 +- Code/Legacy/CrySystem/IDebugCallStack.cpp | 2 +- Code/Legacy/CrySystem/IDebugCallStack.h | 10 +- .../CrySystem/LevelSystem/LevelSystem.cpp | 2 +- .../CrySystem/LocalizedStringManager.cpp | 209 ++++++++++-------- .../Legacy/CrySystem/LocalizedStringManager.h | 66 +++--- Code/Legacy/CrySystem/Log.cpp | 28 +-- Code/Legacy/CrySystem/System.cpp | 30 +-- Code/Legacy/CrySystem/System.h | 14 +- Code/Legacy/CrySystem/SystemCFG.cpp | 62 +++--- Code/Legacy/CrySystem/SystemCFG.h | 16 +- Code/Legacy/CrySystem/SystemInit.cpp | 1 - Code/Legacy/CrySystem/SystemWin32.cpp | 8 +- Code/Legacy/CrySystem/XML/ReadWriteXMLSink.h | 2 +- Code/Legacy/CrySystem/XML/ReadXMLSink.cpp | 9 +- .../CrySystem/XML/SerializeXMLWriter.cpp | 4 +- .../Legacy/CrySystem/XML/SerializeXMLWriter.h | 2 +- Code/Legacy/CrySystem/XML/WriteXMLSource.cpp | 4 +- Code/Legacy/CrySystem/XML/XMLBinaryWriter.h | 12 +- Code/Legacy/CrySystem/XML/XMLPatcher.cpp | 17 +- Code/Legacy/CrySystem/XML/XmlUtils.cpp | 2 +- Code/Legacy/CrySystem/XML/xml.cpp | 18 +- Code/Tools/GridHub/GridHub/gridhub.cpp | 4 - Code/Tools/Standalone/CMakeLists.txt | 2 - .../Platform/Windows/FFontXML_Windows.cpp | 12 +- .../Platform/Windows/FontTexture_Windows.cpp | 2 +- .../AtomFont/Code/Source/AtomFont.cpp | 121 +++++----- .../AtomFont/Code/Source/FFont.cpp | 4 +- .../Code/Editor/PropertyHandlerChar.cpp | 3 +- .../Platform/Windows/UiClipboard_Windows.cpp | 6 +- Gems/LyShine/Code/Source/StringUtfUtils.h | 3 +- .../LyShine/Code/Source/UiButtonComponent.cpp | 2 +- Gems/LyShine/Code/Source/UiImageComponent.cpp | 2 +- Gems/LyShine/Code/Source/UiTextComponent.cpp | 2 +- .../Code/Source/UiTextInputComponent.cpp | 5 +- 43 files changed, 439 insertions(+), 432 deletions(-) diff --git a/Code/Legacy/CryCommon/IMovieSystem.h b/Code/Legacy/CryCommon/IMovieSystem.h index 074c7ab01d..915dc925bf 100644 --- a/Code/Legacy/CryCommon/IMovieSystem.h +++ b/Code/Legacy/CryCommon/IMovieSystem.h @@ -112,7 +112,7 @@ public: CAnimParamType() : m_type(kAnimParamTypeInvalid) {} - CAnimParamType(const string& name) + CAnimParamType(const AZStd::string& name) { *this = name; } @@ -128,17 +128,12 @@ public: m_type = type; } - void operator =(const string& name) - { - m_type = kAnimParamTypeByString; - m_name = name; - } - void operator =(const AZStd::string& name) { m_type = kAnimParamTypeByString; m_name = name; } + // Convert to enum. This needs to be explicit, // otherwise operator== will be ambiguous AnimParamType GetType() const { return m_type; } @@ -1437,7 +1432,7 @@ inline void SAnimContext::Serialize(XmlNodeRef& xmlNode, bool bLoading) { if (sequence) { - string fullname = sequence->GetName(); + AZStd::string fullname = sequence->GetName(); xmlNode->setAttr("sequence", fullname.c_str()); } xmlNode->setAttr("dt", dt); diff --git a/Code/Legacy/CryCommon/LyShine/ILyShine.h b/Code/Legacy/CryCommon/LyShine/ILyShine.h index 07bffda0fe..7832497d8c 100644 --- a/Code/Legacy/CryCommon/LyShine/ILyShine.h +++ b/Code/Legacy/CryCommon/LyShine/ILyShine.h @@ -46,7 +46,7 @@ public: virtual AZ::EntityId CreateCanvas() = 0; //! Load a UI Canvas from in-game - virtual AZ::EntityId LoadCanvas(const string& assetIdPathname) = 0; + virtual AZ::EntityId LoadCanvas(const AZStd::string& assetIdPathname) = 0; //! Create an empty UI Canvas (for the UI editor) // @@ -54,7 +54,7 @@ public: virtual AZ::EntityId CreateCanvasInEditor(UiEntityContext* entityContext) = 0; //! Load a UI Canvas from the UI editor - virtual AZ::EntityId LoadCanvasInEditor(const string& assetIdPathname, const string& sourceAssetPathname, UiEntityContext* entityContext) = 0; + virtual AZ::EntityId LoadCanvasInEditor(const AZStd::string& assetIdPathname, const AZStd::string& sourceAssetPathname, UiEntityContext* entityContext) = 0; //! Reload a UI Canvas from xml. For use in the editor for the undo system only virtual AZ::EntityId ReloadCanvasFromXml(const AZStd::string& xmlString, UiEntityContext* entityContext) = 0; @@ -65,7 +65,7 @@ public: //! Get a loaded canvas by path name //! NOTE: this only searches canvases loaded in the game (not the editor) - virtual AZ::EntityId FindLoadedCanvasByPathName(const string& assetIdPathname) = 0; + virtual AZ::EntityId FindLoadedCanvasByPathName(const AZStd::string& assetIdPathname) = 0; //! Release a canvas from use either in-game or in editor, destroy UI Canvas if no longer used in either virtual void ReleaseCanvas(AZ::EntityId canvas, bool forEditor = false) = 0; @@ -74,10 +74,10 @@ public: virtual void ReleaseCanvasDeferred(AZ::EntityId canvas) = 0; //! Load a sprite object. - virtual ISprite* LoadSprite(const string& pathname) = 0; + virtual ISprite* LoadSprite(const AZStd::string& pathname) = 0; //! Create a sprite that references the specified render target - virtual ISprite* CreateSprite(const string& renderTargetName) = 0; + virtual ISprite* CreateSprite(const AZStd::string& renderTargetName) = 0; //! Check if a sprite's texture asset exists. The .sprite sidecar file is optional and is not checked virtual bool DoesSpriteTextureAssetExist(const AZStd::string& pathname) = 0; diff --git a/Code/Legacy/CrySystem/CmdLine.h b/Code/Legacy/CrySystem/CmdLine.h index 9ad7effebd..5e5c6466f1 100644 --- a/Code/Legacy/CrySystem/CmdLine.h +++ b/Code/Legacy/CrySystem/CmdLine.h @@ -29,13 +29,13 @@ public: virtual const ICmdLineArg* GetArg(int n) const; virtual int GetArgCount() const; virtual const ICmdLineArg* FindArg(const ECmdLineArgType ArgType, const char* name, bool caseSensitive = false) const; - virtual const char* GetCommandLine() const { return m_sCmdLine; }; + virtual const char* GetCommandLine() const { return m_sCmdLine.c_str(); }; private: - void PushCommand(const string& sCommand, const string& sParameter); - string Next(char*& str); + void PushCommand(const AZStd::string& sCommand, const AZStd::string& sParameter); + AZStd::string Next(char*& str); - string m_sCmdLine; + AZStd::string m_sCmdLine; std::vector m_args; }; diff --git a/Code/Legacy/CrySystem/CmdLineArg.h b/Code/Legacy/CrySystem/CmdLineArg.h index cc79981a72..5e3a629e7c 100644 --- a/Code/Legacy/CrySystem/CmdLineArg.h +++ b/Code/Legacy/CrySystem/CmdLineArg.h @@ -34,8 +34,8 @@ public: private: ECmdLineArgType m_type; - string m_name; - string m_value; + AZStd::string m_name; + AZStd::string m_value; }; #endif // CRYINCLUDE_CRYSYSTEM_CMDLINEARG_H diff --git a/Code/Legacy/CrySystem/ConsoleBatchFile.cpp b/Code/Legacy/CrySystem/ConsoleBatchFile.cpp index 6e36780ac0..8b25773c45 100644 --- a/Code/Legacy/CrySystem/ConsoleBatchFile.cpp +++ b/Code/Legacy/CrySystem/ConsoleBatchFile.cpp @@ -57,7 +57,7 @@ bool CConsoleBatchFile::ExecuteConfigFile(const char* sFilename) Init(); } - string filename; + AZStd::string filename; if (sFilename[0] != '@') // console config files are actually by default in @root@ instead of @assets@ { @@ -78,7 +78,7 @@ bool CConsoleBatchFile::ExecuteConfigFile(const char* sFilename) filename = sFilename; } - if (strlen(PathUtil::GetExt(filename)) == 0) + if (strlen(PathUtil::GetExt(filename.c_str())) == 0) { filename = PathUtil::ReplaceExtension(filename, "cfg"); } @@ -88,20 +88,20 @@ bool CConsoleBatchFile::ExecuteConfigFile(const char* sFilename) { const char* szLog = "Executing console batch file (try game,config,root):"; - string filenameLog; - string sfn = PathUtil::GetFile(filename); + AZStd::string filenameLog; + AZStd::string sfn = PathUtil::GetFile(filename); - if (file.Open(filename, "rb", AZ::IO::IArchive::FOPEN_HINT_QUIET | AZ::IO::IArchive::FOPEN_ONDISK)) + if (file.Open(filename.c_str(), "rb", AZ::IO::IArchive::FOPEN_HINT_QUIET | AZ::IO::IArchive::FOPEN_ONDISK)) { - filenameLog = string("game/") + sfn; + filenameLog = AZStd::string("game/") + sfn; } - else if (file.Open(string("config/") + sfn, "rb", AZ::IO::IArchive::FOPEN_HINT_QUIET | AZ::IO::IArchive::FOPEN_ONDISK)) + else if (file.Open((AZStd::string("config/") + sfn).c_str(), "rb", AZ::IO::IArchive::FOPEN_HINT_QUIET | AZ::IO::IArchive::FOPEN_ONDISK)) { - filenameLog = string("game/config/") + sfn; + filenameLog = AZStd::string("game/config/") + sfn; } - else if (file.Open(string("./") + sfn, "rb", AZ::IO::IArchive::FOPEN_HINT_QUIET | AZ::IO::IArchive::FOPEN_ONDISK)) + else if (file.Open((AZStd::string("./") + sfn).c_str(), "rb", AZ::IO::IArchive::FOPEN_HINT_QUIET | AZ::IO::IArchive::FOPEN_ONDISK)) { - filenameLog = string("./") + sfn; + filenameLog = AZStd::string("./") + sfn; } else { @@ -142,11 +142,11 @@ bool CConsoleBatchFile::ExecuteConfigFile(const char* sFilename) str++; } - string strLine = s; + AZStd::string strLine = s; //trim all whitespace characters at the beginning and the end of the current line and store its size - strLine.Trim(); + AZ::StringFunc::TrimWhiteSpace(strLine, true, true); size_t strLineSize = strLine.size(); //skip comments, comments start with ";" or "--" but may have preceding whitespace characters @@ -168,7 +168,7 @@ bool CConsoleBatchFile::ExecuteConfigFile(const char* sFilename) } { - m_pConsole->ExecuteString(strLine); + m_pConsole->ExecuteString(strLine.c_str()); } } // See above diff --git a/Code/Legacy/CrySystem/ConsoleHelpGen.cpp b/Code/Legacy/CrySystem/ConsoleHelpGen.cpp index 0740e3a0f7..ff86577258 100644 --- a/Code/Legacy/CrySystem/ConsoleHelpGen.cpp +++ b/Code/Legacy/CrySystem/ConsoleHelpGen.cpp @@ -17,9 +17,9 @@ // remove bad characters, toupper, not very fast -string CConsoleHelpGen::FixAnchorName(const char* szName) +AZStd::string CConsoleHelpGen::FixAnchorName(const char* szName) { - string ret; + AZStd::string ret; const char* p = szName; @@ -45,9 +45,9 @@ string CConsoleHelpGen::FixAnchorName(const char* szName) return ret; } -string CConsoleHelpGen::GetCleanPrefix(const char* p) +AZStd::string CConsoleHelpGen::GetCleanPrefix(const char* p) { - string sRet; + AZStd::string sRet; while (*p != '_' && *p != 0) { @@ -58,9 +58,9 @@ string CConsoleHelpGen::GetCleanPrefix(const char* p) } -string CConsoleHelpGen::SplitPrefixString_Part1(const char* p) +AZStd::string CConsoleHelpGen::SplitPrefixString_Part1(const char* p) { - string sRet; + AZStd::string sRet; while (*p != 10 && *p != 13 && *p != 0) { @@ -140,7 +140,7 @@ void CConsoleHelpGen::LogVersion(FILE* f) const char fext[_MAX_PATH]; _splitpath_s(s, fdrive, fdir, file, fext); - KeyValue(f, "Executable", (string(file) + fext).c_str()); + KeyValue(f, "Executable", (AZStd::string(file) + fext).c_str()); } { @@ -273,11 +273,11 @@ void CConsoleHelpGen::SingleLinePrefix(FILE* f, const char* szPrefix, const char } else if (m_eWorkMode == eWM_Confluence) { - string sPrefix; + AZStd::string sPrefix; if (*szPrefix) { - sPrefix = string(szPrefix) + "_"; + sPrefix = AZStd::string(szPrefix) + "_"; } // fprintf(f,"| %s | [%s|%s] |\n",sPrefix.c_str(),szPrefixDesc,szLink); // e.g. "" "CL_" "CC_" "I_" "T_" @@ -406,7 +406,7 @@ void CConsoleHelpGen::InsertConsoleCommands(std::setsecond; - if (_strnicmp(cmd.m_sName, szLocalPrefix, strlen(szLocalPrefix)) == 0) + if (_strnicmp(cmd.m_sName.c_str(), szLocalPrefix, strlen(szLocalPrefix)) == 0) { setCmdAndVars.insert(cmd.m_sName.c_str()); } @@ -415,7 +415,7 @@ void CConsoleHelpGen::InsertConsoleCommands(std::set& setCmdAndVars, std::map mapPrefix) const +void CConsoleHelpGen::InsertConsoleVars(std::set& setCmdAndVars, std::map mapPrefix) const { CXConsole::ConsoleVariablesMap::const_iterator itrVar, itrVarEnd = m_rParent.m_mapVariables.end(); @@ -425,11 +425,11 @@ void CConsoleHelpGen::InsertConsoleVars(std::set& bool bInsert = true; { - std::map::const_iterator it2, end = mapPrefix.end(); + std::map::const_iterator it2, end = mapPrefix.end(); for (it2 = mapPrefix.begin(); it2 != end; ++it2) { - if (it2->first != "___" && _strnicmp(var->GetName(), it2->first, it2->first.size()) == 0) + if (it2->first != "___" && _strnicmp(var->GetName(), it2->first.c_str(), it2->first.size()) == 0) { bInsert = false; break; @@ -446,7 +446,7 @@ void CConsoleHelpGen::InsertConsoleVars(std::set& -void CConsoleHelpGen::InsertConsoleCommands(std::set& setCmdAndVars, std::map mapPrefix) const +void CConsoleHelpGen::InsertConsoleCommands(std::set& setCmdAndVars, std::map mapPrefix) const { CXConsole::ConsoleCommandsMap::const_iterator itrCmd, itrCmdEnd = m_rParent.m_mapCommands.end(); @@ -456,11 +456,11 @@ void CConsoleHelpGen::InsertConsoleCommands(std::set::const_iterator it2, end = mapPrefix.end(); + std::map::const_iterator it2, end = mapPrefix.end(); for (it2 = mapPrefix.begin(); it2 != end; ++it2) { - if (it2->first != "___" && _strnicmp(cmd.m_sName, it2->first, it2->first.size()) == 0) + if (it2->first != "___" && _strnicmp(cmd.m_sName.c_str(), it2->first.c_str(), it2->first.size()) == 0) { bInsert = false; break; @@ -480,7 +480,7 @@ void CConsoleHelpGen::CreateSingleEntryFile(const char* szName) const assert(m_eWorkMode == eWM_Confluence); // only needed for confluence FILE* f3 = nullptr; - azfopen(&f3, (string(GetFolderName()) + GetFileExtension() + "/" + FixAnchorName(szName)).c_str(), "w"); + azfopen(&f3, (AZStd::string(GetFolderName()) + GetFileExtension() + "/" + FixAnchorName(szName)).c_str(), "w"); if (!f3) { @@ -582,7 +582,7 @@ void CConsoleHelpGen::IncludeSingleEntry(FILE* f, const char* szName) const { fprintf(f, "

\n");
 
-            string sHelp = szHelp;
+            AZStd::string sHelp = szHelp;
 
             // currently not required as the {noformat} is used
             //          sHelp.replace("[","\\[");       sHelp.replace("]","\\]");
@@ -604,7 +604,7 @@ void CConsoleHelpGen::IncludeSingleEntry(FILE* f, const char* szName) const
 
 void CConsoleHelpGen::Work()
 {
-    //  string sEngineFolder = string("@user@/")+GetFolderName();
+    //  AZStd::string sEngineFolder = AZStd::string("@user@/")+GetFolderName();
     //  gEnv->pCryPak->RemoveDir(sEngineFolder.c_str());            // todo: check if that works
     //  gEnv->pFileIO->CreatePath(sEngineFolder.c_str());
 
@@ -653,7 +653,7 @@ void CConsoleHelpGen::CreateMainPages()
 {
     gEnv->pFileIO->CreatePath(GetFolderName());
 
-    std::map mapPrefix;
+    std::map mapPrefix;
 
     // order here doesn't matter, after the name some help can be added (after the first return)
     mapPrefix[     "AI_"] = "Artificial Intelligence";
@@ -701,7 +701,7 @@ void CConsoleHelpGen::CreateMainPages()
     mapPrefix[     "___"] = "Remaining";            // key defined to get it sorted in the end
 
     FILE* f1 = nullptr;
-    azfopen(&f1, (string(GetFolderName()) + "/index" + GetFileExtension()).c_str(), "w");
+    azfopen(&f1, (AZStd::string(GetFolderName()) + "/index" + GetFileExtension()).c_str(), "w");
     if (!f1)
     {
         return;
@@ -729,17 +729,17 @@ void CConsoleHelpGen::CreateMainPages()
 
     // show all registered Prefix with one line
     {
-        std::map::const_iterator it, end = mapPrefix.end();
+        std::map::const_iterator it, end = mapPrefix.end();
 
         StartH3(f1, "Registered Prefixes");
 
         for (it = mapPrefix.begin(); it != end; ++it)
         {
             const char* szLocalPrefix = it->first.c_str();      // can be 0 for remaining ones
-            string sCleanPrefix = GetCleanPrefix(szLocalPrefix);
-            string sPrefixName = SplitPrefixString_Part1(it->second);
+            AZStd::string sCleanPrefix = GetCleanPrefix(szLocalPrefix);
+            AZStd::string sPrefixName = SplitPrefixString_Part1(it->second);
 
-            SingleLinePrefix(f1, sCleanPrefix.c_str(), sPrefixName.c_str(), (string("CONSOLEPREFIX") + FixAnchorName(sCleanPrefix.c_str()) + GetFileExtension()).c_str());
+            SingleLinePrefix(f1, sCleanPrefix.c_str(), sPrefixName.c_str(), (AZStd::string("CONSOLEPREFIX") + FixAnchorName(sCleanPrefix.c_str()) + GetFileExtension()).c_str());
             //          fprintf(f1,"   * [[CONSOLEPREFIX%s][%s_ %s]]\n",FixAnchorName(sCleanPrefix.c_str()).c_str(),sCleanPrefix.c_str(),sPrefixName.c_str());
         }
 
@@ -750,15 +750,15 @@ void CConsoleHelpGen::CreateMainPages()
 
 
     {
-        std::map::const_iterator it, it2, end = mapPrefix.end();
+        std::map::const_iterator it, it2, end = mapPrefix.end();
 
         StartH3(f1, "Console Commands and Variables Sorted by Prefix");
 
         for (it = mapPrefix.begin(); it != end; ++it)
         {
             const char* szLocalPrefix = it->first.c_str();      // can be 0 for remaining ones
-            string sCleanPrefix = GetCleanPrefix(szLocalPrefix);
-            string sPrefixName = SplitPrefixString_Part1(it->second);
+            AZStd::string sCleanPrefix = GetCleanPrefix(szLocalPrefix);
+            AZStd::string sPrefixName = SplitPrefixString_Part1(it->second);
 
             std::set setCmdAndVars;      // to get console variables and commands sorted together
 
@@ -777,11 +777,11 @@ void CConsoleHelpGen::CreateMainPages()
 
             // -------------------------------
 
-            string sSubName = string("CONSOLEPREFIX") + sCleanPrefix;
+            AZStd::string sSubName = AZStd::string("CONSOLEPREFIX") + sCleanPrefix;
 
             StartPrefix(f1, sCleanPrefix.c_str(), sPrefixName.c_str(), (sSubName + GetFileExtension()).c_str());
 
-            string sFileOut = string(GetFolderName()) + "/" + sSubName + GetFileExtension();
+            AZStd::string sFileOut = AZStd::string(GetFolderName()) + "/" + sSubName + GetFileExtension();
             FILE* f2 = nullptr;
             azfopen(&f2, sFileOut.c_str(), "w");
             if (!f2)
@@ -792,7 +792,7 @@ void CConsoleHelpGen::CreateMainPages()
 
             // headline
             {
-                string sHeadline;
+                AZStd::string sHeadline;
 
                 if (sCleanPrefix.empty())
                 {
@@ -800,7 +800,7 @@ void CConsoleHelpGen::CreateMainPages()
                 }
                 else
                 {
-                    sHeadline = string("Console Commands and Variables with Prefix ") + sCleanPrefix + "_";
+                    sHeadline = AZStd::string("Console Commands and Variables with Prefix ") + sCleanPrefix + "_";
                 }
 
                 StartH1(f2, sHeadline.c_str());
@@ -821,7 +821,7 @@ void CConsoleHelpGen::CreateMainPages()
                 for (itI = setCmdAndVars.begin(); itI != endI; ++itI)
                 {
                     SingleLineEntry_InGlobal(f1, *itI, (sSubName + GetFileExtension() + "#Anchor" + FixAnchorName(*itI)).c_str());
-                    SingleLineEntry_InGroup(f2, *itI, (string("#Anchor") + FixAnchorName(*itI)).c_str());
+                    SingleLineEntry_InGroup(f2, *itI, (AZStd::string("#Anchor") + FixAnchorName(*itI)).c_str());
                 }
 
                 EndH3(f2);
@@ -842,7 +842,7 @@ void CConsoleHelpGen::CreateMainPages()
                         }
                         bFirst = false;
 
-                        Anchor(f2, (string("Anchor") + FixAnchorName(*itI)).c_str());      // anchor
+                        Anchor(f2, (AZStd::string("Anchor") + FixAnchorName(*itI)).c_str());      // anchor
 
                         IncludeSingleEntry(f2, *itI);
                     }
diff --git a/Code/Legacy/CrySystem/ConsoleHelpGen.h b/Code/Legacy/CrySystem/ConsoleHelpGen.h
index 9ff797ca07..576232fe7a 100644
--- a/Code/Legacy/CrySystem/ConsoleHelpGen.h
+++ b/Code/Legacy/CrySystem/ConsoleHelpGen.h
@@ -59,19 +59,19 @@ private: // --------------------------------------------------------
     // insert if the name starts with the with prefix
     void InsertConsoleCommands(std::set& setCmdAndVars, const char* szPrefix) const;
     // insert if the name does not start with any of the prefix in the map
-    void InsertConsoleVars(std::set& setCmdAndVars, std::map mapPrefix) const;
+    void InsertConsoleVars(std::set& setCmdAndVars, std::map mapPrefix) const;
     // insert if the name does not start with any of the prefix in the map
-    void InsertConsoleCommands(std::set& setCmdAndVars, std::map mapPrefix) const;
+    void InsertConsoleCommands(std::set& setCmdAndVars, std::map mapPrefix) const;
 
     // a single file for the entry is generate
     void CreateSingleEntryFile(const char* szName) const;
 
     void IncludeSingleEntry(FILE* f, const char* szName) const;
 
-    static string FixAnchorName(const char* szName);
-    static string GetCleanPrefix(const char* p);
+    static AZStd::string FixAnchorName(const char* szName);
+    static AZStd::string GetCleanPrefix(const char* p);
     // split before "|" (to get the prefix itself)
-    static string SplitPrefixString_Part1(const char* p);
+    static AZStd::string SplitPrefixString_Part1(const char* p);
     // split string after "|" (to get the optional help)
     static const char* SplitPrefixString_Part2(const char* p);
 
diff --git a/Code/Legacy/CrySystem/DebugCallStack.cpp b/Code/Legacy/CrySystem/DebugCallStack.cpp
index 1914e82515..c5d932429c 100644
--- a/Code/Legacy/CrySystem/DebugCallStack.cpp
+++ b/Code/Legacy/CrySystem/DebugCallStack.cpp
@@ -348,7 +348,7 @@ void DebugCallStack::ReportBug(const char* szErrorMessage)
     m_szBugMessage = NULL;
 }
 
-void DebugCallStack::dumpCallStack(std::vector& funcs)
+void DebugCallStack::dumpCallStack(std::vector& funcs)
 {
     WriteLineToLog("=============================================================================");
     int len = (int)funcs.size();
@@ -364,7 +364,7 @@ void DebugCallStack::dumpCallStack(std::vector& funcs)
 //////////////////////////////////////////////////////////////////////////
 void DebugCallStack::LogExceptionInfo(EXCEPTION_POINTERS* pex)
 {
-    string path("");
+    AZStd::string path("");
     if ((gEnv) && (gEnv->pFileIO))
     {
         const char* logAlias = gEnv->pFileIO->GetAlias("@log@");
@@ -379,12 +379,12 @@ void DebugCallStack::LogExceptionInfo(EXCEPTION_POINTERS* pex)
         }
     }
 
-    string fileName = path;
+    AZStd::string fileName = path;
     fileName += "error.log";
 
     struct stat fileInfo;
-    string timeStamp;
-    string backupPath;
+    AZStd::string timeStamp;
+    AZStd::string backupPath;
     if (gEnv->IsDedicated())
     {
         backupPath = PathUtil::ToUnixPath(PathUtil::AddSlash(path + "DumpBackups"));
@@ -399,7 +399,7 @@ void DebugCallStack::LogExceptionInfo(EXCEPTION_POINTERS* pex)
             strftime(tempBuffer, sizeof(tempBuffer), "%d %b %Y (%H %M %S)", &creationTime);
             timeStamp = tempBuffer;
 
-            string backupFileName = backupPath + timeStamp + " error.log";
+            AZStd::string backupFileName = backupPath + timeStamp + " error.log";
             CopyFile(fileName.c_str(), backupFileName.c_str(), true);
         }
     }
@@ -414,8 +414,8 @@ void DebugCallStack::LogExceptionInfo(EXCEPTION_POINTERS* pex)
     char versionbuf[1024];
     azstrcpy(versionbuf, AZ_ARRAY_SIZE(versionbuf), "");
     PutVersion(versionbuf, AZ_ARRAY_SIZE(versionbuf));
-    cry_strcat(errorString, versionbuf);
-    cry_strcat(errorString, "\n");
+    azstrcat(errorString, versionbuf);
+    azstrcat(errorString, "\n");
 
     char excCode[MAX_WARNING_LENGTH];
     char excAddr[80];
@@ -481,9 +481,9 @@ void DebugCallStack::LogExceptionInfo(EXCEPTION_POINTERS* pex)
         excCode, excAddr, m_excModule, excName, desc);
 
 
-    cry_strcat(errs, "\nCall Stack Trace:\n");
+    azstrcat(errs, "\nCall Stack Trace:\n");
 
-    std::vector funcs;
+    std::vector funcs;
     {
         AZ::Debug::StackFrame frames[25];
         AZ::Debug::SymbolStorage::StackLine lines[AZ_ARRAY_SIZE(frames)];
@@ -504,15 +504,15 @@ void DebugCallStack::LogExceptionInfo(EXCEPTION_POINTERS* pex)
         {
             char temp[s_iCallStackSize];
             sprintf_s(temp, "%2zd) %s", funcs.size() - i, (const char*)funcs[i].c_str());
-            cry_strcat(str, temp);
-            cry_strcat(str, "\r\n");
-            cry_strcat(errs, temp);
-            cry_strcat(errs, "\n");
+            azstrcat(str, temp);
+            azstrcat(str, "\r\n");
+            azstrcat(errs, temp);
+            azstrcat(errs, "\n");
         }
         azstrcpy(m_excCallstack, str);
     }
 
-    cry_strcat(errorString, errs);
+    azstrcat(errorString, errs);
 
     if (f)
     {
@@ -593,7 +593,7 @@ void DebugCallStack::LogExceptionInfo(EXCEPTION_POINTERS* pex)
                     timeStamp = tempBuffer;
                 }
 
-                string backupFileName = backupPath + timeStamp + " error.dmp";
+                AZStd::string backupFileName = backupPath + timeStamp + " error.dmp";
                 CopyFile(fileName.c_str(), backupFileName.c_str(), true);
             }
 
@@ -818,7 +818,7 @@ void DebugCallStack::ResetFPU(EXCEPTION_POINTERS* pex)
     }
 }
 
-string DebugCallStack::GetModuleNameForAddr(void* addr)
+AZStd::string DebugCallStack::GetModuleNameForAddr(void* addr)
 {
     if (m_modules.empty())
     {
@@ -844,7 +844,7 @@ string DebugCallStack::GetModuleNameForAddr(void* addr)
     return m_modules.rbegin()->second;
 }
 
-void DebugCallStack::GetProcNameForAddr(void* addr, string& procName, void*& baseAddr, string& filename, int& line)
+void DebugCallStack::GetProcNameForAddr(void* addr, AZStd::string& procName, void*& baseAddr, AZStd::string& filename, int& line)
 {
     AZ::Debug::SymbolStorage::StackLine func, file, module;
     AZ::Debug::SymbolStorage::FindFunctionFromIP(addr, &func, &file, &module, line, baseAddr);
@@ -852,7 +852,7 @@ void DebugCallStack::GetProcNameForAddr(void* addr, string& procName, void*& bas
     filename = file;
 }
 
-string DebugCallStack::GetCurrentFilename()
+AZStd::string DebugCallStack::GetCurrentFilename()
 {
     char fullpath[MAX_PATH_LENGTH + 1];
     GetModuleFileName(NULL, fullpath, MAX_PATH_LENGTH);
diff --git a/Code/Legacy/CrySystem/DebugCallStack.h b/Code/Legacy/CrySystem/DebugCallStack.h
index f0c708a2b5..28f587011e 100644
--- a/Code/Legacy/CrySystem/DebugCallStack.h
+++ b/Code/Legacy/CrySystem/DebugCallStack.h
@@ -35,20 +35,20 @@ public:
 
     ISystem* GetSystem() { return m_pSystem; };
 
-    virtual string GetModuleNameForAddr(void* addr);
-    virtual void GetProcNameForAddr(void* addr, string& procName, void*& baseAddr, string& filename, int& line);
-    virtual string GetCurrentFilename();
+    virtual AZStd::string GetModuleNameForAddr(void* addr);
+    virtual void GetProcNameForAddr(void* addr, AZStd::string& procName, void*& baseAddr, AZStd::string& filename, int& line);
+    virtual AZStd::string GetCurrentFilename();
 
     void installErrorHandler(ISystem* pSystem);
     virtual int handleException(EXCEPTION_POINTERS* exception_pointer);
 
     virtual void ReportBug(const char*);
 
-    void dumpCallStack(std::vector& functions);
+    void dumpCallStack(std::vector& functions);
 
     void SetUserDialogEnable(const bool bUserDialogEnable);
 
-    typedef std::map TModules;
+    typedef std::map TModules;
 protected:
     static void RemoveOldFiles();
     static void RemoveFile(const char* szFileName);
diff --git a/Code/Legacy/CrySystem/IDebugCallStack.cpp b/Code/Legacy/CrySystem/IDebugCallStack.cpp
index 4ca481be88..ff43f6e56f 100644
--- a/Code/Legacy/CrySystem/IDebugCallStack.cpp
+++ b/Code/Legacy/CrySystem/IDebugCallStack.cpp
@@ -237,7 +237,7 @@ void IDebugCallStack::WriteLineToLog(const char* format, ...)
     char        szBuffer[MAX_WARNING_LENGTH];
     va_start(ArgList, format);
     vsnprintf_s(szBuffer, sizeof(szBuffer), sizeof(szBuffer) - 1, format, ArgList);
-    cry_strcat(szBuffer, "\n");
+    azstrcat(szBuffer, "\n");
     szBuffer[sizeof(szBuffer) - 1] = '\0';
     va_end(ArgList);
 
diff --git a/Code/Legacy/CrySystem/IDebugCallStack.h b/Code/Legacy/CrySystem/IDebugCallStack.h
index c05d0827b0..a2c1d3f5e2 100644
--- a/Code/Legacy/CrySystem/IDebugCallStack.h
+++ b/Code/Legacy/CrySystem/IDebugCallStack.h
@@ -33,23 +33,23 @@ public:
     virtual int handleException([[maybe_unused]] EXCEPTION_POINTERS* exception_pointer){return 0; }
 
     // returns the module name of a given address
-    virtual string GetModuleNameForAddr([[maybe_unused]] void* addr) { return "[unknown]"; }
+    virtual AZStd::string GetModuleNameForAddr([[maybe_unused]] void* addr) { return "[unknown]"; }
 
     // returns the function name of a given address together with source file and line number (if available) of a given address
-    virtual void GetProcNameForAddr(void* addr, string& procName, void*& baseAddr, string& filename, int& line)
+    virtual void GetProcNameForAddr(void* addr, AZStd::string& procName, void*& baseAddr, AZStd::string& filename, int& line)
     {
         filename = "[unknown]";
         line = 0;
         baseAddr = addr;
 #if defined(PLATFORM_64BIT)
-        procName.Format("[%016llX]", addr);
+        procName = AZStd::string::format("[%016llX]", addr);
 #else
-        procName.Format("[%08X]", addr);
+        procName = AZStd::string::format("[%08X]", addr);
 #endif
     }
 
     // returns current filename
-    virtual string GetCurrentFilename()  { return "[unknown]"; }
+    virtual AZStd::string GetCurrentFilename()  { return "[unknown]"; }
 
     //! Dumps Current Call Stack to log.
     virtual void LogCallstack();
diff --git a/Code/Legacy/CrySystem/LevelSystem/LevelSystem.cpp b/Code/Legacy/CrySystem/LevelSystem/LevelSystem.cpp
index 83db5e4a29..3e6432a721 100644
--- a/Code/Legacy/CrySystem/LevelSystem/LevelSystem.cpp
+++ b/Code/Legacy/CrySystem/LevelSystem/LevelSystem.cpp
@@ -480,7 +480,7 @@ CLevelInfo* CLevelSystem::GetLevelInfoInternal(const AZStd::string& levelName)
     for (AZStd::vector::iterator it = m_levelInfos.begin(); it != m_levelInfos.end(); ++it)
     {
         {
-            if (!azstricmp(PathUtil::GetFileName(it->GetName()), levelName.c_str()))
+            if (!azstricmp(PathUtil::GetFileName(it->GetName()).c_str(), levelName.c_str()))
             {
                 return &(*it);
             }
diff --git a/Code/Legacy/CrySystem/LocalizedStringManager.cpp b/Code/Legacy/CrySystem/LocalizedStringManager.cpp
index fe0fd9cb22..e3ccb22f88 100644
--- a/Code/Legacy/CrySystem/LocalizedStringManager.cpp
+++ b/Code/Legacy/CrySystem/LocalizedStringManager.cpp
@@ -20,7 +20,6 @@
 #include "System.h" // to access InitLocalization()
 #include 
 #include 
-#include 
 #include 
 #include 
 
@@ -146,9 +145,9 @@ static void ReloadDialogData([[maybe_unused]] IConsoleCmdArgs* pArgs)
 #if !defined(_RELEASE)
 static void TestFormatMessage ([[maybe_unused]] IConsoleCmdArgs* pArgs)
 {
-    string fmt1 ("abc %1 def % gh%2i %");
-    string fmt2 ("abc %[action:abc] %2 def % gh%1i %1");
-    string out1, out2;
+    AZStd::string fmt1 ("abc %1 def % gh%2i %");
+    AZStd::string fmt2 ("abc %[action:abc] %2 def % gh%1i %1");
+    AZStd::string out1, out2;
     LocalizationManagerRequestBus::Broadcast(&LocalizationManagerRequestBus::Events::FormatStringMessage, out1, fmt1, "first", "second", "third", nullptr);
     CryLogAlways("%s", out1.c_str());
     LocalizationManagerRequestBus::Broadcast(&LocalizationManagerRequestBus::Events::FormatStringMessage, out2, fmt2, "second", nullptr, nullptr, nullptr);
@@ -206,18 +205,18 @@ CLocalizedStringsManager::CLocalizedStringsManager(ISystem* pSystem)
 
     // Populate available languages by scanning the localization directory for paks
     // Default to US English if language is not supported
-    string sPath;
-    const string sLocalizationFolder(PathUtil::GetLocalizationFolder());
+    AZStd::string sPath;
+    const AZStd::string sLocalizationFolder(PathUtil::GetLocalizationFolder());
     ILocalizationManager::TLocalizationBitfield availableLanguages = 0;
     
     AZ::IO::FileIOBase* fileIO = AZ::IO::FileIOBase::GetInstance();
     // test language name against supported languages
     for (int i = 0; i < ILocalizationManager::ePILID_MAX_OR_INVALID; i++)
     {
-        string sCurrentLanguage = LangNameFromPILID((ILocalizationManager::EPlatformIndependentLanguageID)i);  
+        AZStd::string sCurrentLanguage = LangNameFromPILID((ILocalizationManager::EPlatformIndependentLanguageID)i);
         sPath = sLocalizationFolder.c_str() + sCurrentLanguage;
-        sPath.MakeLower();
-        if (fileIO && fileIO->IsDirectory(sPath))
+        AZStd::to_lower(sPath.begin(), sPath.end());
+        if (fileIO && fileIO->IsDirectory(sPath.c_str()))
         {
             availableLanguages |= ILocalizationManager::LocalizationBitfieldFromPILID((ILocalizationManager::EPlatformIndependentLanguageID)i);
             if (m_cvarLocalizationDebug >= 2)
@@ -366,7 +365,7 @@ bool CLocalizedStringsManager::SetLanguage(const char* sLanguage)
     // Check if already language loaded.
     for (uint32 i = 0; i < m_languages.size(); i++)
     {
-        if (_stricmp(sLanguage, m_languages[i]->sLanguage) == 0)
+        if (_stricmp(sLanguage, m_languages[i]->sLanguage.c_str()) == 0)
         {
             InternalSetCurrentLanguage(m_languages[i]);
             return true;
@@ -441,9 +440,9 @@ void CLocalizedStringsManager::AddControl([[maybe_unused]] int nKey)
 }
 
 //////////////////////////////////////////////////////////////////////////
-void CLocalizedStringsManager::ParseFirstLine(IXmlTableReader* pXmlTableReader, char* nCellIndexToType, std::map& SoundMoodIndex, std::map& EventParameterIndex)
+void CLocalizedStringsManager::ParseFirstLine(IXmlTableReader* pXmlTableReader, char* nCellIndexToType, std::map& SoundMoodIndex, std::map& EventParameterIndex)
 {
-    string sCellContent;
+    AZStd::string sCellContent;
 
     for (;; )
     {
@@ -466,7 +465,7 @@ void CLocalizedStringsManager::ParseFirstLine(IXmlTableReader* pXmlTableReader,
         }
 
         sCellContent.assign(pContent, contentSize);
-        sCellContent.MakeLower();
+        AZStd::to_lower(sCellContent.begin(), sCellContent.end());
 
         for (int i = 0; i < sizeof(sLocalizedColumnNames) / sizeof(sLocalizedColumnNames[0]); ++i)
         {
@@ -530,8 +529,8 @@ static void CopyLowercase(char* dst, size_t dstSize, const char* src, size_t src
 //////////////////////////////////////////////////////////////////////////
 static void ReplaceEndOfLine(AZStd::fixed_string& s)
 {
-    const string oldSubstr("\\n");
-    const string newSubstr(" \n");
+    const AZStd::string oldSubstr("\\n");
+    const AZStd::string newSubstr(" \n");
     size_t pos = 0;
     for (;; )
     {
@@ -565,7 +564,7 @@ void CLocalizedStringsManager::OnSystemEvent(
 
             for (TStringVec::iterator it = m_tagLoadRequests.begin(); it != m_tagLoadRequests.end(); ++it)
             {
-                LoadLocalizationDataByTag(*it);
+                LoadLocalizationDataByTag(it->c_str());
             }
         }
 
@@ -577,7 +576,7 @@ void CLocalizedStringsManager::OnSystemEvent(
         // Load all tags after the Editor has finished initialization.
         for (TTagFileNames::iterator it = m_tagFileNames.begin(); it != m_tagFileNames.end(); ++it)
         {
-            LoadLocalizationDataByTag(it->first);
+            LoadLocalizationDataByTag(it->first.c_str());
         }
 
         break;
@@ -600,7 +599,7 @@ bool CLocalizedStringsManager::InitLocalizationData(
     for (int i = 0; i < root->getChildCount(); i++)
     {
         XmlNodeRef typeNode = root->getChild(i);
-        string sType = typeNode->getTag();
+        AZStd::string sType = typeNode->getTag();
 
         // tags should be unique
         if (m_tagFileNames.find(sType) != m_tagFileNames.end())
@@ -678,9 +677,9 @@ bool CLocalizedStringsManager::LoadLocalizationDataByTag(
     for (TStringVec::iterator it2 = vEntries.begin(); it2 != vEntries.end(); ++it2)
     {
         //Only load files of the correct type for the configured format
-        if ((m_cvarLocalizationFormat == 0 && strstr(*it2, ".xml")) || (m_cvarLocalizationFormat == 1 && strstr(*it2, ".agsxml")))
+        if ((m_cvarLocalizationFormat == 0 && strstr(it2->c_str(), ".xml")) || (m_cvarLocalizationFormat == 1 && strstr(it2->c_str(), ".agsxml")))
         {
-            bResult &= (this->*loadFunction)(*it2, it->second.id, bReload);
+            bResult &= (this->*loadFunction)(it2->c_str(), it->second.id, bReload);
         }
     }
 
@@ -824,7 +823,7 @@ bool CLocalizedStringsManager::LoadAllLocalizationData(bool bReload)
 {
     for (TTagFileNames::iterator it = m_tagFileNames.begin(); it != m_tagFileNames.end(); ++it)
     {
-        if(!LoadLocalizationDataByTag(it->first, bReload))
+        if(!LoadLocalizationDataByTag(it->first.c_str(), bReload))
             return false;
     }
     return true;
@@ -837,6 +836,37 @@ bool CLocalizedStringsManager::LoadExcelXmlSpreadsheet(const char* sFileName, bo
     return (this->*loadFunction)(sFileName, 0, bReload);
 }
 
+enum class YesNoType
+{
+    Yes,
+    No,
+    Invalid
+};
+
+// parse the yes/no string
+/*!
+\param szString any of the following strings: yes, enable, true, 1, no, disable, false, 0
+\return YesNoType::Yes if szString is yes/enable/true/1, YesNoType::No if szString is no, disable, false, 0 and YesNoType::Invalid if the string is not one of the expected values.
+*/
+inline YesNoType ToYesNoType(const char* szString)
+{
+    if (!_stricmp(szString, "yes")
+        || !_stricmp(szString, "enable")
+        || !_stricmp(szString, "true")
+        || !_stricmp(szString, "1"))
+    {
+        return YesNoType::Yes;
+    }
+    if (!_stricmp(szString, "no")
+        || !_stricmp(szString, "disable")
+        || !_stricmp(szString, "false")
+        || !_stricmp(szString, "0"))
+    {
+        return YesNoType::No;
+    }
+    return YesNoType::Invalid;
+}
+
 //////////////////////////////////////////////////////////////////////
 // Loads a string-table from a Excel XML Spreadsheet file.
 bool CLocalizedStringsManager::DoLoadExcelXmlSpreadsheet(const char* sFileName, uint8 nTagID, bool bReload)
@@ -850,7 +880,7 @@ bool CLocalizedStringsManager::DoLoadExcelXmlSpreadsheet(const char* sFileName,
     //check if this table has already been loaded
     if (!bReload)
     {
-        if (m_loadedTables.find(CONST_TEMP_STRING(sFileName)) != m_loadedTables.end())
+        if (m_loadedTables.find(AZStd::string(sFileName)) != m_loadedTables.end())
         {
             return (true);
         }
@@ -866,12 +896,12 @@ bool CLocalizedStringsManager::DoLoadExcelXmlSpreadsheet(const char* sFileName,
     }
 
     XmlNodeRef root;
-    string sPath;
+    AZStd::string sPath;
     {
-        const string sLocalizationFolder(PathUtil::GetLocalizationRoot());
-        const string& languageFolder = m_pLanguage->sLanguage;
+        const AZStd::string sLocalizationFolder(PathUtil::GetLocalizationRoot());
+        const AZStd::string& languageFolder = m_pLanguage->sLanguage;
         sPath = sLocalizationFolder.c_str() + languageFolder + PathUtil::GetSlash() + sFileName;
-        root = m_pSystem->LoadXmlFromFile(sPath);
+        root = m_pSystem->LoadXmlFromFile(sPath.c_str());
         if (!root)
         {
             CryLog("Loading Localization File %s failed!", sPath.c_str());
@@ -948,10 +978,10 @@ bool CLocalizedStringsManager::DoLoadExcelXmlSpreadsheet(const char* sFileName,
     memset(nCellIndexToType, 0, sizeof(nCellIndexToType));
 
     // SoundMood Index
-    std::map SoundMoodIndex;
+    std::map SoundMoodIndex;
 
     // EventParameter Index
-    std::map EventParameterIndex;
+    std::map EventParameterIndex;
 
     bool bFirstRow = true;
 
@@ -1083,7 +1113,7 @@ bool CLocalizedStringsManager::DoLoadExcelXmlSpreadsheet(const char* sFileName,
                 break;
             case ELOCALIZED_COLUMN_USE_SUBTITLE:
                 sTmp.assign(cell.ptr, cell.count);
-                bUseSubtitle = CryStringUtils::ToYesNoType(sTmp.c_str()) == CryStringUtils::YesNoType::No ? false : true; // favor yes (yes and invalid -> yes)
+                bUseSubtitle = ToYesNoType(sTmp.c_str()) == YesNoType::No ? false : true; // favor yes (yes and invalid -> yes)
                 break;
             case ELOCALIZED_COLUMN_VOLUME:
                 sTmp.assign(cell.ptr, cell.count);
@@ -1121,7 +1151,7 @@ bool CLocalizedStringsManager::DoLoadExcelXmlSpreadsheet(const char* sFileName,
                 {
                     bIsIntercepted = true;
                 }
-                bIsDirectRadio = bIsIntercepted || (CryStringUtils::ToYesNoType(sTmp.c_str()) == CryStringUtils::YesNoType::Yes ? true : false); // favor no (no and invalid -> no)
+                bIsDirectRadio = bIsIntercepted || (ToYesNoType(sTmp.c_str()) == YesNoType::Yes ? true : false); // favor no (no and invalid -> no)
                 ++nItems;
                 break;
             // legacy names
@@ -1358,7 +1388,7 @@ bool CLocalizedStringsManager::DoLoadExcelXmlSpreadsheet(const char* sFileName,
             }
             else
             {
-                pEntry->TranslatedText.psUtf8Uncompressed = new string(sTmp.c_str(), sTmp.c_str() + sTmp.length());
+                pEntry->TranslatedText.psUtf8Uncompressed = new AZStd::string(sTmp.c_str(), sTmp.c_str() + sTmp.length());
             }
         }
 
@@ -1367,7 +1397,7 @@ bool CLocalizedStringsManager::DoLoadExcelXmlSpreadsheet(const char* sFileName,
         // the CryString makes sure, that only the ref-count is increment on assignment
         if (*szLowerCaseEvent)
         {
-            PrototypeSoundEvents::iterator it = m_prototypeEvents.find(CONST_TEMP_STRING(szLowerCaseEvent));
+            PrototypeSoundEvents::iterator it = m_prototypeEvents.find(AZStd::string(szLowerCaseEvent));
             if (it != m_prototypeEvents.end())
             {
                 pEntry->sPrototypeSoundEvent = *it;
@@ -1384,8 +1414,8 @@ bool CLocalizedStringsManager::DoLoadExcelXmlSpreadsheet(const char* sFileName,
         {
             sTmp.assign(sWho.ptr, sWho.count);
             ReplaceEndOfLine(sTmp);
-            sTmp.replace(" ", "_");
-            string tmp;
+            AZStd::replace(sTmp.begin(), sTmp.end(), ' ', '_');
+            AZStd::string tmp;
             {
                 tmp = sTmp.c_str();
             }
@@ -1531,19 +1561,19 @@ bool CLocalizedStringsManager::DoLoadAGSXmlDocument(const char* sFileName, uint8
     }
     if (!bReload)
     {
-        if (m_loadedTables.find(CONST_TEMP_STRING(sFileName)) != m_loadedTables.end())
+        if (m_loadedTables.find(AZStd::string(sFileName)) != m_loadedTables.end())
         {
             return true;
         }
     }
     ListAndClearProblemLabels();
     XmlNodeRef root;
-    string sPath;
+    AZStd::string sPath;
     {
-        const string sLocalizationFolder(PathUtil::GetLocalizationRoot());
-        const string& languageFolder = m_pLanguage->sLanguage;
+        const AZStd::string sLocalizationFolder(PathUtil::GetLocalizationRoot());
+        const AZStd::string& languageFolder = m_pLanguage->sLanguage;
         sPath = sLocalizationFolder.c_str() + languageFolder + PathUtil::GetSlash() + sFileName;
-        root = m_pSystem->LoadXmlFromFile(sPath);
+        root = m_pSystem->LoadXmlFromFile(sPath.c_str());
         if (!root)
         {
             AZ_TracePrintf(LOC_WINDOW, "Loading Localization File %s failed!", sPath.c_str());
@@ -1654,7 +1684,7 @@ bool CLocalizedStringsManager::DoLoadAGSXmlDocument(const char* sFileName, uint8
             }
             else
             {
-                pEntry->TranslatedText.psUtf8Uncompressed = new string(textString, textString + textLength);
+                pEntry->TranslatedText.psUtf8Uncompressed = new AZStd::string(textString, textString + textLength);
             }
         }
         {
@@ -1714,7 +1744,7 @@ void CLocalizedStringsManager::ReloadData()
     FreeLocalizationData();
     for (tmapFilenames::iterator it = temp.begin(); it != temp.end(); it++)
     {
-        (this->*loadFunction)((*it).first, (*it).second.nTagID, true);
+        (this->*loadFunction)((*it).first.c_str(), (*it).second.nTagID, true);
     }
 }
 
@@ -1732,19 +1762,19 @@ void CLocalizedStringsManager::AddLocalizedString(SLanguage* pLanguage, SLocaliz
 }
 
 //////////////////////////////////////////////////////////////////////////
-bool CLocalizedStringsManager::LocalizeString_ch(const char* sString, string& outLocalizedString, bool bEnglish)
+bool CLocalizedStringsManager::LocalizeString_ch(const char* sString, AZStd::string& outLocalizedString, bool bEnglish)
 {
     return LocalizeStringInternal(sString, strlen(sString), outLocalizedString, bEnglish);
 }
 
 //////////////////////////////////////////////////////////////////////////
-bool CLocalizedStringsManager::LocalizeString_s(const string& sString, string& outLocalizedString, bool bEnglish)
+bool CLocalizedStringsManager::LocalizeString_s(const AZStd::string& sString, AZStd::string& outLocalizedString, bool bEnglish)
 {
     return LocalizeStringInternal(sString.c_str(), sString.length(), outLocalizedString, bEnglish);
 }
 
 //////////////////////////////////////////////////////////////////////////
-bool CLocalizedStringsManager::LocalizeStringInternal(const char* pStr, size_t len, string& outLocalizedString, bool bEnglish)
+bool CLocalizedStringsManager::LocalizeStringInternal(const char* pStr, size_t len, AZStd::string& outLocalizedString, bool bEnglish)
 {
     assert (m_pLanguage);
     if (m_pLanguage == 0)
@@ -1755,7 +1785,7 @@ bool CLocalizedStringsManager::LocalizeStringInternal(const char* pStr, size_t l
     }
 
     // note: we don't write directly to outLocalizedString, in case it aliases pStr
-    string out;
+    AZStd::string out;
 
     // scan the string
     const char* pPos = pStr;
@@ -1783,8 +1813,8 @@ bool CLocalizedStringsManager::LocalizeStringInternal(const char* pStr, size_t l
         }
 
         // localize token
-        string token(pLabel, pLabelEnd);
-        string sLocalizedToken;
+        AZStd::string token(pLabel, pLabelEnd);
+        AZStd::string sLocalizedToken;
         if (bEnglish)
         {
             GetEnglishString(token.c_str(), sLocalizedToken);
@@ -1803,7 +1833,7 @@ bool CLocalizedStringsManager::LocalizeStringInternal(const char* pStr, size_t l
 
 void CLocalizedStringsManager::LocalizeAndSubstituteInternal(AZStd::string& locString, const AZStd::vector& keys, const AZStd::vector& values)
 {
-    string outString;
+    AZStd::string outString;
     LocalizeString_ch(locString.c_str(), outString);
     locString = outString .c_str();
     if (values.size() != keys.size())
@@ -1866,7 +1896,7 @@ static void LogDecompTimer(__int64 nTotalTicks, __int64 nDecompTicks, __int64 nA
 }
 #endif
 
-string CLocalizedStringsManager::SLocalizedStringEntry::GetTranslatedText(const SLanguage* pLanguage) const
+AZStd::string CLocalizedStringsManager::SLocalizedStringEntry::GetTranslatedText(const SLanguage* pLanguage) const
 {
     FUNCTION_PROFILER_FAST(GetISystem(), PROFILE_SYSTEM, g_bProfilerEnabled);
     if ((flags & IS_COMPRESSED) != 0)
@@ -1876,7 +1906,7 @@ string CLocalizedStringsManager::SLocalizedStringEntry::GetTranslatedText(const
         nTotalTicks = CryGetTicks();
 #endif  //LOG_DECOMP_TIMES
 
-        string outputString;
+        AZStd::string outputString;
         if (TranslatedText.szCompressed != NULL)
         {
             uint8 decompressionBuffer[COMPRESSION_FIXED_BUFFER_LENGTH];
@@ -1923,7 +1953,7 @@ string CLocalizedStringsManager::SLocalizedStringEntry::GetTranslatedText(const
         }
         else
         {
-            string emptyOutputString;
+            AZStd::string emptyOutputString;
             return emptyOutputString;
         }
     }
@@ -1949,7 +1979,7 @@ void CLocalizedStringsManager::ListAndClearProblemLabels()
         CryLog ("These labels caused localization problems:");
         INDENT_LOG_DURING_SCOPE();
 
-        for (std::map::iterator iter = m_warnedAboutLabels.begin(); iter != m_warnedAboutLabels.end(); iter++)
+        for (std::map::iterator iter = m_warnedAboutLabels.begin(); iter != m_warnedAboutLabels.end(); iter++)
         {
             CryLog ("%s", iter->first.c_str());
         }
@@ -1961,7 +1991,7 @@ void CLocalizedStringsManager::ListAndClearProblemLabels()
 #endif
 
 //////////////////////////////////////////////////////////////////////////
-bool CLocalizedStringsManager::LocalizeLabel(const char* sLabel, string& outLocalString, bool bEnglish)
+bool CLocalizedStringsManager::LocalizeLabel(const char* sLabel, AZStd::string& outLocalString, bool bEnglish)
 {
     assert(sLabel);
     if (!m_pLanguage || !sLabel)
@@ -1979,8 +2009,7 @@ bool CLocalizedStringsManager::LocalizeLabel(const char* sLabel, string& outLoca
 
             if (entry != NULL)
             {
-                
-                string translatedText = entry->GetTranslatedText(m_pLanguage);
+                AZStd::string translatedText = entry->GetTranslatedText(m_pLanguage);
                 if ((bEnglish || translatedText.empty()) && entry->pEditorExtension != NULL)
                 {
                     //assert(!"No Localization Text available!");
@@ -2011,7 +2040,7 @@ bool CLocalizedStringsManager::LocalizeLabel(const char* sLabel, string& outLoca
 
 
 //////////////////////////////////////////////////////////////////////////
-bool CLocalizedStringsManager::GetEnglishString(const char* sKey, string& sLocalizedString)
+bool CLocalizedStringsManager::GetEnglishString(const char* sKey, AZStd::string& sLocalizedString)
 {
     assert(sKey);
     if (!m_pLanguage || !sKey)
@@ -2086,7 +2115,7 @@ bool CLocalizedStringsManager::GetLocalizedInfoByKey(const char* sKey, SLocalize
         const SLocalizedStringEntry* entry = stl::find_in_map(m_pLanguage->m_keysMap, keyCRC32, NULL);
         if (entry != NULL)
         {
-            outGameInfo.szCharacterName = entry->sCharacterName;
+            outGameInfo.szCharacterName = entry->sCharacterName.c_str();
             outGameInfo.sUtf8TranslatedText = entry->GetTranslatedText(m_pLanguage);
 
             outGameInfo.bUseSubtitle = (entry->flags & SLocalizedStringEntry::USE_SUBTITLE);
@@ -2119,7 +2148,7 @@ bool CLocalizedStringsManager::GetLocalizedInfoByKey(const char* sKey, SLocalize
         {
             bResult = true;
 
-            pOutSoundInfo->szCharacterName = pEntry->sCharacterName;
+            pOutSoundInfo->szCharacterName = pEntry->sCharacterName.c_str();
             pOutSoundInfo->sUtf8TranslatedText = pEntry->GetTranslatedText(m_pLanguage);
 
             //pOutSoundInfo->sOriginalActorLine = pEntry->sOriginalActorLine.c_str();
@@ -2213,7 +2242,7 @@ bool CLocalizedStringsManager::GetLocalizedInfoByIndex(int nIndex, SLocalizedInf
     }
     const SLocalizedStringEntry* pEntry = entryVec[nIndex];
 
-    outGameInfo.szCharacterName = pEntry->sCharacterName;
+    outGameInfo.szCharacterName = pEntry->sCharacterName.c_str();
     outGameInfo.sUtf8TranslatedText = pEntry->GetTranslatedText(m_pLanguage);
 
     outGameInfo.bUseSubtitle = (pEntry->flags & SLocalizedStringEntry::USE_SUBTITLE);
@@ -2233,18 +2262,18 @@ bool CLocalizedStringsManager::GetLocalizedInfoByIndex(int nIndex, SLocalizedInf
         return false;
     }
     const SLocalizedStringEntry* pEntry = entryVec[nIndex];
-    outEditorInfo.szCharacterName = pEntry->sCharacterName;
+    outEditorInfo.szCharacterName = pEntry->sCharacterName.c_str();
     outEditorInfo.sUtf8TranslatedText = pEntry->GetTranslatedText(m_pLanguage);
 
     assert(pEntry->pEditorExtension != NULL);
 
-    outEditorInfo.sKey = pEntry->pEditorExtension->sKey;
+    outEditorInfo.sKey = pEntry->pEditorExtension->sKey.c_str();
 
-    outEditorInfo.sOriginalActorLine = pEntry->pEditorExtension->sOriginalActorLine;
-    outEditorInfo.sUtf8TranslatedActorLine = pEntry->pEditorExtension->sUtf8TranslatedActorLine;
+    outEditorInfo.sOriginalActorLine = pEntry->pEditorExtension->sOriginalActorLine.c_str();
+    outEditorInfo.sUtf8TranslatedActorLine = pEntry->pEditorExtension->sUtf8TranslatedActorLine.c_str();
 
     //outEditorInfo.sOriginalText = pEntry->sOriginalText;
-    outEditorInfo.sOriginalCharacterName = pEntry->pEditorExtension->sOriginalCharacterName;
+    outEditorInfo.sOriginalCharacterName = pEntry->pEditorExtension->sOriginalCharacterName.c_str();
 
     outEditorInfo.nRow = pEntry->pEditorExtension->nRow;
     outEditorInfo.bUseSubtitle = (pEntry->flags & SLocalizedStringEntry::USE_SUBTITLE);
@@ -2252,7 +2281,7 @@ bool CLocalizedStringsManager::GetLocalizedInfoByIndex(int nIndex, SLocalizedInf
 }
 
 //////////////////////////////////////////////////////////////////////////
-bool CLocalizedStringsManager::GetSubtitle(const char* sKeyOrLabel, string& outSubtitle, bool bForceSubtitle)
+bool CLocalizedStringsManager::GetSubtitle(const char* sKeyOrLabel, AZStd::string& outSubtitle, bool bForceSubtitle)
 {
     assert(sKeyOrLabel);
     if (!m_pLanguage || !sKeyOrLabel || !*sKeyOrLabel)
@@ -2376,13 +2405,13 @@ void InternalFormatStringMessage(StringClass& outString, const StringClass& sStr
 }
 
 //////////////////////////////////////////////////////////////////////////
-void CLocalizedStringsManager::FormatStringMessage_List(string& outString, const string& sString, const char** sParams, int nParams)
+void CLocalizedStringsManager::FormatStringMessage_List(AZStd::string& outString, const AZStd::string& sString, const char** sParams, int nParams)
 {
     InternalFormatStringMessage(outString, sString, sParams, nParams);
 }
 
 //////////////////////////////////////////////////////////////////////////
-void CLocalizedStringsManager::FormatStringMessage(string& outString, const string& sString, const char* param1, const char* param2, const char* param3, const char* param4)
+void CLocalizedStringsManager::FormatStringMessage(AZStd::string& outString, const AZStd::string& sString, const char* param1, const char* param2, const char* param3, const char* param4)
 {
     InternalFormatStringMessage(outString, sString, param1, param2, param3, param4);
 }
@@ -2462,7 +2491,7 @@ void CLocalizedStringsManager::InternalSetCurrentLanguage(CLocalizedStringsManag
 #if defined (WIN32) || defined(WIN64)
     if (m_pLanguage != 0)
     {
-        g_currentLanguageID = GetLanguageID(m_pLanguage->sLanguage);
+        g_currentLanguageID = GetLanguageID(m_pLanguage->sLanguage.c_str());
     }
     else
     {
@@ -2494,7 +2523,7 @@ void CLocalizedStringsManager::InternalSetCurrentLanguage(CLocalizedStringsManag
     }
 }
 
-void CLocalizedStringsManager::LocalizeDuration(int seconds, string& outDurationString)
+void CLocalizedStringsManager::LocalizeDuration(int seconds, AZStd::string& outDurationString)
 {
     int s = seconds;
     int d, h, m;
@@ -2504,27 +2533,27 @@ void CLocalizedStringsManager::LocalizeDuration(int seconds, string& outDuration
     s -= h * 3600;
     m = s / 60;
     s = s - m * 60;
-    string str;
+    AZStd::string str;
     if (d > 1)
     {
-        str.Format("%d @ui_days %02d:%02d:%02d", d, h, m, s);
+        str = AZStd::string::format("%d @ui_days %02d:%02d:%02d", d, h, m, s);
     }
     else if (d > 0)
     {
-        str.Format("%d @ui_day %02d:%02d:%02d", d, h, m, s);
+        str = AZStd::string::format("%d @ui_day %02d:%02d:%02d", d, h, m, s);
     }
     else if (h > 0)
     {
-        str.Format("%02d:%02d:%02d", h, m, s);
+        str = AZStd::string::format("%02d:%02d:%02d", h, m, s);
     }
     else
     {
-        str.Format("%02d:%02d", m, s);
+        str = AZStd::string::format("%02d:%02d", m, s);
     }
     LocalizeString_s(str, outDurationString);
 }
 
-void CLocalizedStringsManager::LocalizeNumber(int number, string& outNumberString)
+void CLocalizedStringsManager::LocalizeNumber(int number, AZStd::string& outNumberString)
 {
     if (number == 0)
     {
@@ -2535,7 +2564,7 @@ void CLocalizedStringsManager::LocalizeNumber(int number, string& outNumberStrin
     outNumberString.assign("");
 
     int n = abs(number);
-    string separator;
+    AZStd::string separator;
     AZStd::fixed_string<64> tmp;
     LocalizeString_ch("@ui_thousand_separator", separator);
     while (n > 0)
@@ -2544,41 +2573,41 @@ void CLocalizedStringsManager::LocalizeNumber(int number, string& outNumberStrin
         int b = n - (a * 1000);
         if (a > 0)
         {
-            tmp.Format("%s%03d%s", separator.c_str(), b, tmp.c_str());
+            tmp = AZStd::string::format("%s%03d%s", separator.c_str(), b, tmp.c_str());
         }
         else
         {
-            tmp.Format("%d%s", b, tmp.c_str());
+            tmp = AZStd::string::format("%d%s", b, tmp.c_str());
         }
         n = a;
     }
 
     if (number < 0)
     {
-        tmp.Format("-%s", tmp.c_str());
+        tmp = AZStd::string::format("-%s", tmp.c_str());
     }
 
     outNumberString.assign(tmp.c_str());
 }
 
-void CLocalizedStringsManager::LocalizeNumber_Decimal(float number, int decimals, string& outNumberString)
+void CLocalizedStringsManager::LocalizeNumber_Decimal(float number, int decimals, AZStd::string& outNumberString)
 {
     if (number == 0.0f)
     {
         AZStd::fixed_string<64> tmp;
-        tmp.Format("%.*f", decimals, number);
+        tmp = AZStd::fixed_string<64>::format("%.*f", decimals, number);
         outNumberString.assign(tmp.c_str());
         return;
     }
 
     outNumberString.assign("");
 
-    string commaSeparator;
+    AZStd::string commaSeparator;
     LocalizeString_ch("@ui_decimal_separator", commaSeparator);
     float f = number > 0.0f ? number : -number;
     int d = (int)f;
 
-    string intPart;
+    AZStd::string intPart;
     LocalizeNumber(d, intPart);
 
     float decimalsOnly = f - (float)d;
@@ -2586,7 +2615,7 @@ void CLocalizedStringsManager::LocalizeNumber_Decimal(float number, int decimals
     int decimalsAsInt = aznumeric_cast(int_round(decimalsOnly * pow(10.0f, decimals)));
 
     AZStd::fixed_string<64> tmp;
-    tmp.Format("%s%s%0*d", intPart.c_str(), commaSeparator.c_str(), decimals, decimalsAsInt);
+    tmp = AZStd::fixed_string<64>::format("%s%s%0*d", intPart.c_str(), commaSeparator.c_str(), decimals, decimalsAsInt);
 
     outNumberString.assign(tmp.c_str());
 }
@@ -2640,7 +2669,7 @@ namespace
     }
 };
 
-void CLocalizedStringsManager::LocalizeTime(time_t t, bool bMakeLocalTime, bool bShowSeconds, string& outTimeString)
+void CLocalizedStringsManager::LocalizeTime(time_t t, bool bMakeLocalTime, bool bShowSeconds, AZStd::string& outTimeString)
 {
     if (bMakeLocalTime)
     {
@@ -2664,7 +2693,7 @@ void CLocalizedStringsManager::LocalizeTime(time_t t, bool bMakeLocalTime, bool
     }
 }
 
-void CLocalizedStringsManager::LocalizeDate(time_t t, bool bMakeLocalTime, bool bShort, bool bIncludeWeekday, string& outDateString)
+void CLocalizedStringsManager::LocalizeDate(time_t t, bool bMakeLocalTime, bool bShort, bool bIncludeWeekday, AZStd::string& outDateString)
 {
     if (bMakeLocalTime)
     {
@@ -2689,7 +2718,7 @@ void CLocalizedStringsManager::LocalizeDate(time_t t, bool bMakeLocalTime, bool
             // len includes terminating null!
             tmpString.resize(len);
             ::GetDateFormatW(lcID, 0, &systemTime, L"ddd", (wchar_t*) tmpString.c_str(), len);
-            string utf8;
+            AZStd::string utf8;
             Unicode::Convert(utf8, tmpString);
             outDateString.append(utf8);
             outDateString.append(" ");
@@ -2702,7 +2731,7 @@ void CLocalizedStringsManager::LocalizeDate(time_t t, bool bMakeLocalTime, bool
         // len includes terminating null!
         tmpString.resize(len);
         ::GetDateFormatW(lcID, flags, &systemTime, 0, (wchar_t*) tmpString.c_str(), len);
-        string utf8;
+        AZStd::string utf8;
         Unicode::Convert(utf8, tmpString);
         outDateString.append(utf8);
     }
@@ -2710,7 +2739,7 @@ void CLocalizedStringsManager::LocalizeDate(time_t t, bool bMakeLocalTime, bool
 
 #else // #if defined (WIN32) || defined(WIN64)
 
-void CLocalizedStringsManager::LocalizeTime(time_t t, bool bMakeLocalTime, bool bShowSeconds, string& outTimeString)
+void CLocalizedStringsManager::LocalizeTime(time_t t, bool bMakeLocalTime, bool bShowSeconds, AZStd::string& outTimeString)
 {
     struct tm theTime;
     if (bMakeLocalTime)
@@ -2737,7 +2766,7 @@ void CLocalizedStringsManager::LocalizeTime(time_t t, bool bMakeLocalTime, bool
     Unicode::Convert(outTimeString, buf);
 }
 
-void CLocalizedStringsManager::LocalizeDate(time_t t, bool bMakeLocalTime, bool bShort, bool bIncludeWeekday, string& outDateString)
+void CLocalizedStringsManager::LocalizeDate(time_t t, bool bMakeLocalTime, bool bShort, bool bIncludeWeekday, AZStd::string& outDateString)
 {
     struct tm theTime;
     if (bMakeLocalTime)
diff --git a/Code/Legacy/CrySystem/LocalizedStringManager.h b/Code/Legacy/CrySystem/LocalizedStringManager.h
index 581a657c81..72a7916d1f 100644
--- a/Code/Legacy/CrySystem/LocalizedStringManager.h
+++ b/Code/Legacy/CrySystem/LocalizedStringManager.h
@@ -25,7 +25,7 @@ class CLocalizedStringsManager
     , public ISystemEventListener
 {
 public:
-    typedef std::vector TLocalizationTagVec;
+    typedef std::vector TLocalizationTagVec;
 
     constexpr const static size_t LOADING_FIXED_STRING_LENGTH = 2048;
     constexpr const static size_t COMPRESSION_FIXED_BUFFER_LENGTH = 6144;
@@ -56,11 +56,11 @@ public:
     void ReloadData() override;
     void FreeData();
 
-    bool LocalizeString_s(const string& sString, string& outLocalizedString, bool bEnglish = false) override;
-    bool LocalizeString_ch(const char* sString, string& outLocalizedString, bool bEnglish = false) override;
+    bool LocalizeString_s(const AZStd::string& sString, AZStd::string& outLocalizedString, bool bEnglish = false) override;
+    bool LocalizeString_ch(const char* sString, AZStd::string& outLocalizedString, bool bEnglish = false) override;
 
     void LocalizeAndSubstituteInternal(AZStd::string& locString, const AZStd::vector& keys, const AZStd::vector& values) override;
-    bool LocalizeLabel(const char* sLabel, string& outLocalizedString, bool bEnglish = false) override;
+    bool LocalizeLabel(const char* sLabel, AZStd::string& outLocalizedString, bool bEnglish = false) override;
     bool IsLocalizedInfoFound(const char* sKey);
     bool GetLocalizedInfoByKey(const char* sKey, SLocalizedInfoGame& outGameInfo);
     bool GetLocalizedInfoByKey(const char* sKey, SLocalizedSoundInfoGame* pOutSoundInfoGame);
@@ -68,17 +68,17 @@ public:
     bool GetLocalizedInfoByIndex(int nIndex, SLocalizedInfoGame& outGameInfo);
     bool GetLocalizedInfoByIndex(int nIndex, SLocalizedInfoEditor& outEditorInfo);
 
-    bool GetEnglishString(const char* sKey, string& sLocalizedString) override;
-    bool GetSubtitle(const char* sKeyOrLabel, string& outSubtitle, bool bForceSubtitle = false) override;
+    bool GetEnglishString(const char* sKey, AZStd::string& sLocalizedString) override;
+    bool GetSubtitle(const char* sKeyOrLabel, AZStd::string& outSubtitle, bool bForceSubtitle = false) override;
 
-    void FormatStringMessage_List(string& outString, const string& sString, const char** sParams, int nParams) override;
-    void FormatStringMessage(string& outString, const string& sString, const char* param1, const char* param2 = 0, const char* param3 = 0, const char* param4 = 0) override;
+    void FormatStringMessage_List(AZStd::string& outString, const AZStd::string& sString, const char** sParams, int nParams) override;
+    void FormatStringMessage(AZStd::string& outString, const AZStd::string& sString, const char* param1, const char* param2 = 0, const char* param3 = 0, const char* param4 = 0) override;
 
-    void LocalizeTime(time_t t, bool bMakeLocalTime, bool bShowSeconds, string& outTimeString) override;
-    void LocalizeDate(time_t t, bool bMakeLocalTime, bool bShort, bool bIncludeWeekday, string& outDateString) override;
-    void LocalizeDuration(int seconds, string& outDurationString) override;
-    void LocalizeNumber(int number, string& outNumberString) override;
-    void LocalizeNumber_Decimal(float number, int decimals, string& outNumberString) override;
+    void LocalizeTime(time_t t, bool bMakeLocalTime, bool bShowSeconds, AZStd::string& outTimeString) override;
+    void LocalizeDate(time_t t, bool bMakeLocalTime, bool bShort, bool bIncludeWeekday, AZStd::string& outDateString) override;
+    void LocalizeDuration(int seconds, AZStd::string& outDurationString) override;
+    void LocalizeNumber(int number, AZStd::string& outNumberString) override;
+    void LocalizeNumber_Decimal(float number, int decimals, AZStd::string& outNumberString) override;
 
     bool ProjectUsesLocalization() const override;
     // ~ILocalizationManager
@@ -95,7 +95,7 @@ public:
 private:
     void SetAvailableLocalizationsBitfield(const ILocalizationManager::TLocalizationBitfield availableLocalizations);
 
-    bool LocalizeStringInternal(const char* pStr, size_t len, string& outLocalizedString, bool bEnglish);
+    bool LocalizeStringInternal(const char* pStr, size_t len, AZStd::string& outLocalizedString, bool bEnglish);
 
     bool DoLoadExcelXmlSpreadsheet(const char* sFileName, uint8 tagID, bool bReload);
     typedef bool(CLocalizedStringsManager::*LoadFunc)(const char*, uint8, bool);
@@ -104,11 +104,11 @@ private:
 
     struct SLocalizedStringEntryEditorExtension
     {
-        string  sKey;                                           // Map key text equivalent (without @)
-        string  sOriginalActorLine;             // english text
-        string  sUtf8TranslatedActorLine;       // localized text
-        string  sOriginalText;                      // subtitle. if empty, uses English text
-        string  sOriginalCharacterName;     // english character name speaking via XML asset
+        AZStd::string  sKey;                                           // Map key text equivalent (without @)
+        AZStd::string  sOriginalActorLine;             // english text
+        AZStd::string  sUtf8TranslatedActorLine;       // localized text
+        AZStd::string  sOriginalText;                      // subtitle. if empty, uses English text
+        AZStd::string  sOriginalCharacterName;     // english character name speaking via XML asset
 
         unsigned int nRow;                              // Number of row in XML file
 
@@ -141,15 +141,15 @@ private:
 
         union trans_text
         {
-            string*     psUtf8Uncompressed;
+            AZStd::string*     psUtf8Uncompressed;
             uint8*      szCompressed;       // Note that no size information is stored. This is for struct size optimization and unfortunately renders the size info inaccurate.
         };
 
-        string sCharacterName;  // character name speaking via XML asset
+        AZStd::string sCharacterName;  // character name speaking via XML asset
         trans_text TranslatedText;  // Subtitle of this line
 
         // audio specific part
-        string      sPrototypeSoundEvent;           // associated sound event prototype (radio, ...)
+        AZStd::string      sPrototypeSoundEvent;           // associated sound event prototype (radio, ...)
         CryHalf     fVolume;
         CryHalf     fRadioRatio;
         // SoundMoods
@@ -191,7 +191,7 @@ private:
             }
         };
 
-        string GetTranslatedText(const SLanguage* pLanguage) const;
+        AZStd::string GetTranslatedText(const SLanguage* pLanguage) const;
 
         void GetMemoryUsage(ICrySizer* pSizer) const
         {
@@ -224,7 +224,7 @@ private:
         typedef std::vector TLocalizedStringEntries;
         typedef std::vector THuffmanCoders;
 
-        string sLanguage;
+        AZStd::string sLanguage;
         StringsKeyMap m_keysMap;
         TLocalizedStringEntries m_vLocalizedStrings;
         THuffmanCoders m_vEncoders;
@@ -246,7 +246,7 @@ private:
     };
 
 #ifndef _RELEASE
-    std::map m_warnedAboutLabels;
+    std::map m_warnedAboutLabels;
     bool m_haveWarnedAboutAtLeastOneLabel;
 
     void LocalizedStringsManagerWarning(const char* label, const char* message);
@@ -259,45 +259,45 @@ private:
     void AddLocalizedString(SLanguage* pLanguage, SLocalizedStringEntry* pEntry, const uint32 keyCRC32);
     void AddControl(int nKey);
     //////////////////////////////////////////////////////////////////////////
-    void ParseFirstLine(IXmlTableReader* pXmlTableReader, char* nCellIndexToType, std::map& SoundMoodIndex, std::map& EventParameterIndex);
+    void ParseFirstLine(IXmlTableReader* pXmlTableReader, char* nCellIndexToType, std::map& SoundMoodIndex, std::map& EventParameterIndex);
     void InternalSetCurrentLanguage(SLanguage* pLanguage);
     ISystem* m_pSystem;
     // Pointer to the current language.
     SLanguage* m_pLanguage;
 
     // all loaded Localization Files
-    typedef std::pair pairFileName;
-    typedef std::map tmapFilenames;
+    typedef std::pair pairFileName;
+    typedef std::map tmapFilenames;
     tmapFilenames m_loadedTables;
 
 
     // filenames per tag
-    typedef std::vector TStringVec;
+    typedef std::vector TStringVec;
     struct STag
     {
         TStringVec  filenames;
         uint8               id;
         bool                loaded;
     };
-    typedef std::map TTagFileNames;
+    typedef std::map TTagFileNames;
     TTagFileNames m_tagFileNames;
     TStringVec m_tagLoadRequests;
 
     // Array of loaded languages.
     std::vector m_languages;
 
-    typedef std::set PrototypeSoundEvents;
+    typedef std::set PrototypeSoundEvents;
     PrototypeSoundEvents m_prototypeEvents;  // this set is purely used for clever string/string assigning to save memory
 
     struct less_strcmp
     {
-        bool operator()(const string& left, const string& right) const
+        bool operator()(const AZStd::string& left, const AZStd::string& right) const
         {
             return strcmp(left.c_str(), right.c_str()) < 0;
         }
     };
 
-    typedef std::set CharacterNameSet;
+    typedef std::set CharacterNameSet;
     CharacterNameSet m_characterNameSet; // this set is purely used for clever string/string assigning to save memory
 
     // CVARs
diff --git a/Code/Legacy/CrySystem/Log.cpp b/Code/Legacy/CrySystem/Log.cpp
index 2c7c307d50..c23ed6e264 100644
--- a/Code/Legacy/CrySystem/Log.cpp
+++ b/Code/Legacy/CrySystem/Log.cpp
@@ -466,7 +466,7 @@ void CLog::LogV(const ELogType type, [[maybe_unused]]int flags, const char* szFo
     {
     case eWarning:
     case eWarningAlways:
-        cry_strcpy(szString, MAX_WARNING_LENGTH, "$6[Warning] ");
+        azstrcpy(szString, MAX_WARNING_LENGTH, "$6[Warning] ");
         szString += 12;     // strlen("$6[Warning] ");
         szAfterColour += 2;
         prefixSize = 12;
@@ -474,7 +474,7 @@ void CLog::LogV(const ELogType type, [[maybe_unused]]int flags, const char* szFo
 
     case eError:
     case eErrorAlways:
-        cry_strcpy(szString, MAX_WARNING_LENGTH, "$4[Error] ");
+        azstrcpy(szString, MAX_WARNING_LENGTH, "$4[Error] ");
         szString += 10;     // strlen("$4[Error] ");
         szAfterColour += 2;
         prefixSize = 10;
@@ -532,7 +532,7 @@ void CLog::LogV(const ELogType type, [[maybe_unused]]int flags, const char* szFo
             }
         }
         i = m_iLastHistoryItem = m_iLastHistoryItem + 1 & sz - 1;
-        cry_strcpy(m_history[i].str, m_history[i].ptr = szSpamCheck);
+        azstrcpy(m_history[i].str, m_history[i].ptr = szSpamCheck);
         m_history[i].type = type;
         m_history[i].time = time;
     }
@@ -956,7 +956,7 @@ void CLog::LogStringToFile(const char* szString, ELogType logType, bool bAdd, [[
             {
                 timeStr.clear();
                 uint32 dwMs = (uint32)((currenttime - lasttime).GetMilliSeconds());
-                timeStr.Format("<%3d.%.3d>: ", dwMs / 1000, dwMs % 1000);
+                timeStr = AZStd::string::format("<%3d.%.3d>: ", dwMs / 1000, dwMs % 1000);
                 tempString = timeStr + tempString;
             }
             lasttime = currenttime;
@@ -983,7 +983,7 @@ void CLog::LogStringToFile(const char* szString, ELogType logType, bool bAdd, [[
             {
                 timeStr.clear();
                 uint32 dwMs = (uint32)((currenttime - lasttime).GetMilliSeconds());
-                timeStr.Format("<%3d.%.3d>: ", dwMs / 1000, dwMs % 1000);
+                timeStr = AZStd::string::format("<%3d.%.3d>: ", dwMs / 1000, dwMs % 1000);
                 tempString = timeStr + tempString;
             }
             lasttime = currenttime;
@@ -1000,7 +1000,7 @@ void CLog::LogStringToFile(const char* szString, ELogType logType, bool bAdd, [[
                 {
                     timeStr.clear();
                     uint32 dwMs = (uint32)((currenttime - lasttime).GetMilliSeconds());
-                    timeStr.Format("<%3d.%.3d>: ", dwMs / 1000, dwMs % 1000);
+                    timeStr = AZStd::string::format("<%3d.%.3d>: ", dwMs / 1000, dwMs % 1000);
                     tempString = timeStr + tempString;
                 }
                 if (bFirst)
@@ -1218,10 +1218,10 @@ void CLog::CreateBackupFile() const
 
     // boswej: only create a backup if logging to the engine root, otherwise the
     // log output has been overridden and the user is responsible
-    string logDir = PathUtil::RemoveSlash(PathUtil::ToUnixPath(PathUtil::GetParentDirectory(m_szFilename)));
+    AZStd::string logDir = PathUtil::RemoveSlash(PathUtil::ToUnixPath(PathUtil::GetParentDirectory(m_szFilename)));
 
-    string sExt = PathUtil::GetExt(m_szFilename);
-    string sFileWithoutExt = PathUtil::GetFileName(m_szFilename);
+    AZStd::string sExt = PathUtil::GetExt(m_szFilename);
+    AZStd::string sFileWithoutExt = PathUtil::GetFileName(m_szFilename);
 
     {
         assert(::strstr(sFileWithoutExt, ":") == 0);
@@ -1234,14 +1234,14 @@ void CLog::CreateBackupFile() const
     AZ::IO::HandleType inFileHandle = AZ::IO::InvalidHandle;
     fileSystem->Open(m_szFilename, AZ::IO::OpenMode::ModeRead | AZ::IO::OpenMode::ModeBinary, inFileHandle);
 
-    string sBackupNameAttachment;
+    AZStd::string sBackupNameAttachment;
 
     // parse backup name attachment
     // e.g. BackupNameAttachment="attachment name"
     if (inFileHandle != AZ::IO::InvalidHandle)
     {
         bool bKeyFound = false;
-        string sName;
+        AZStd::string sName;
 
         while (!fileSystem->Eof(inFileHandle))
         {
@@ -1253,7 +1253,7 @@ void CLog::CreateBackupFile() const
                 {
                     bKeyFound = true;
 
-                    if (sName.find("BackupNameAttachment=") == string::npos)
+                    if (sName.find("BackupNameAttachment=") == AZStd::string::npos)
                     {
 #ifdef WIN32
                         OutputDebugString("Log::CreateBackupFile ERROR '");
@@ -1284,12 +1284,12 @@ void CLog::CreateBackupFile() const
         fileSystem->Close(inFileHandle);
     }
 
-    string bakdest = PathUtil::Make(LOG_BACKUP_PATH, sFileWithoutExt + sBackupNameAttachment + "." + sExt);
+    AZStd::string bakdest = PathUtil::Make(LOG_BACKUP_PATH, sFileWithoutExt + sBackupNameAttachment + "." + sExt);
     fileSystem->CreatePath(LOG_BACKUP_PATH);
     azstrcpy(m_sBackupFilename, bakdest.c_str());
     // Remove any existing backup file with the same name first since the copy will fail otherwise.
     fileSystem->Remove(m_sBackupFilename);
-    fileSystem->Copy(m_szFilename, bakdest);
+    fileSystem->Copy(m_szFilename, bakdest.c_str());
 #endif // AZ_LEGACY_CRYSYSTEM_TRAIT_ALLOW_CREATE_BACKUP_LOG_FILE
 }
 
diff --git a/Code/Legacy/CrySystem/System.cpp b/Code/Legacy/CrySystem/System.cpp
index bf4de8489d..9c2e1b1129 100644
--- a/Code/Legacy/CrySystem/System.cpp
+++ b/Code/Legacy/CrySystem/System.cpp
@@ -88,14 +88,7 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
     }
 
     // Handle with the default procedure
-#if defined(UNICODE) || defined(_UNICODE)
     assert(IsWindowUnicode(hWnd) && "Window should be Unicode when compiling with UNICODE");
-#else
-    if (!IsWindowUnicode(hWnd))
-    {
-        return DefWindowProcA(hWnd, uMsg, wParam, lParam);
-    }
-#endif
     return DefWindowProcW(hWnd, uMsg, wParam, lParam);
 }
 #endif
@@ -138,7 +131,6 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
 #include "RemoteConsole/RemoteConsole.h"
 
 #include 
-#include 
 
 #include 
 #include 
@@ -1209,10 +1201,11 @@ void CSystem::WarningV(EValidatorModule module, EValidatorSeverity severity, int
 }
 
 //////////////////////////////////////////////////////////////////////////
-void CSystem::GetLocalizedPath(const char* sLanguage, string& sLocalizedPath)
+void CSystem::GetLocalizedPath(const char* sLanguage, AZStd::string& sLocalizedPath)
 {
     // Omit the trailing slash!
-    string sLocalizationFolder(string().assign(PathUtil::GetLocalizationFolder(), 0, PathUtil::GetLocalizationFolder().size() - 1));
+    AZStd::string sLocalizationFolder(PathUtil::GetLocalizationFolder());
+    sLocalizationFolder.pop_back();
 
     int locFormat = 0;
     LocalizationManagerRequestBus::BroadcastResult(locFormat, &LocalizationManagerRequestBus::Events::GetLocalizationFormat);
@@ -1228,16 +1221,17 @@ void CSystem::GetLocalizedPath(const char* sLanguage, string& sLocalizedPath)
     }
     else
     {
-        sLocalizedPath = string("Localized/") + sLanguage + "_xml.pak";
+        sLocalizedPath = AZStd::string("Localized/") + sLanguage + "_xml.pak";
         }
     }
 }
 
 //////////////////////////////////////////////////////////////////////////
-void CSystem::GetLocalizedAudioPath(const char* sLanguage, string& sLocalizedPath)
+void CSystem::GetLocalizedAudioPath(const char* sLanguage, AZStd::string& sLocalizedPath)
 {
     // Omit the trailing slash!
-    string sLocalizationFolder(string().assign(PathUtil::GetLocalizationFolder(), 0, PathUtil::GetLocalizationFolder().size() - 1));
+    AZStd::string sLocalizationFolder(PathUtil::GetLocalizationFolder());
+    sLocalizationFolder.pop_back();
 
     if (sLocalizationFolder.compareNoCase("Languages") != 0)
     {
@@ -1245,14 +1239,14 @@ void CSystem::GetLocalizedAudioPath(const char* sLanguage, string& sLocalizedPat
     }
     else
     {
-        sLocalizedPath = string("Localized/") + sLanguage + ".pak";
+        sLocalizedPath = AZStd::string("Localized/") + sLanguage + ".pak";
     }
 }
 
 //////////////////////////////////////////////////////////////////////////
 void CSystem::CloseLanguagePak(const char* sLanguage)
 {
-    string sLocalizedPath;
+    AZStd::string sLocalizedPath;
     GetLocalizedPath(sLanguage, sLocalizedPath);
     m_env.pCryPak->ClosePacks({ sLocalizedPath.c_str(), sLocalizedPath.size() });
 }
@@ -1260,7 +1254,7 @@ void CSystem::CloseLanguagePak(const char* sLanguage)
 //////////////////////////////////////////////////////////////////////////
 void CSystem::CloseLanguageAudioPak(const char* sLanguage)
 {
-    string sLocalizedPath;
+    AZStd::string sLocalizedPath;
     GetLocalizedAudioPath(sLanguage, sLocalizedPath);
     m_env.pCryPak->ClosePacks({ sLocalizedPath.c_str(), sLocalizedPath.size() });
 }
@@ -1334,11 +1328,11 @@ void CSystem::ExecuteCommandLine(bool deferred)
 
         if (pCmd->GetType() == eCLAT_Post)
         {
-            string sLine = pCmd->GetName();
+            AZStd::string sLine = pCmd->GetName();
             {
                 if (pCmd->GetValue())
                 {
-                    sLine += string(" ") + pCmd->GetValue();
+                    sLine += AZStd::string(" ") + pCmd->GetValue();
                 }
 
                 GetILog()->Log("Executing command from command line: \n%s\n", sLine.c_str()); // - the actual command might be executed much later (e.g. level load pause)
diff --git a/Code/Legacy/CrySystem/System.h b/Code/Legacy/CrySystem/System.h
index c66b2aab60..b6c4e0a96a 100644
--- a/Code/Legacy/CrySystem/System.h
+++ b/Code/Legacy/CrySystem/System.h
@@ -453,7 +453,7 @@ private:
     bool ReLaunchMediaCenter();
     void UpdateAudioSystems();
 
-    void AddCVarGroupDirectory(const string& sPath);
+    void AddCVarGroupDirectory(const AZStd::string& sPath);
 
     AZStd::unique_ptr LoadDynamiclibrary(const char* dllName) const;
 
@@ -623,7 +623,7 @@ private: // ------------------------------------------------------
     //  ICVar *m_sys_filecache;
     ICVar* m_gpu_particle_physics;
 
-    string  m_sSavedRDriver;                                //!< to restore the driver when quitting the dedicated server
+    AZStd::string  m_sSavedRDriver;                                //!< to restore the driver when quitting the dedicated server
 
     //////////////////////////////////////////////////////////////////////////
     //! User define callback for system events.
@@ -672,8 +672,8 @@ public:
     void OpenBasicPaks();
     void OpenLanguagePak(const char* sLanguage);
     void OpenLanguageAudioPak(const char* sLanguage);
-    void GetLocalizedPath(const char* sLanguage, string& sLocalizedPath);
-    void GetLocalizedAudioPath(const char* sLanguage, string& sLocalizedPath);
+    void GetLocalizedPath(const char* sLanguage, AZStd::string& sLocalizedPath);
+    void GetLocalizedAudioPath(const char* sLanguage, AZStd::string& sLocalizedPath);
     void CloseLanguagePak(const char* sLanguage);
     void CloseLanguageAudioPak(const char* sLanguage);
     void UpdateMovieSystem(const int updateFlags, const float fFrameTime, const bool bPreUpdate);
@@ -718,14 +718,14 @@ protected: // -------------------------------------------------------------
 
     CCmdLine*                                      m_pCmdLine;
 
-    string  m_currentLanguageAudio;
-    string  m_systemConfigName; // computed from system_(hardwareplatform)_(assetsPlatform) - eg, system_android_android.cfg or system_windows_pc.cfg
+    AZStd::string  m_currentLanguageAudio;
+    AZStd::string  m_systemConfigName; // computed from system_(hardwareplatform)_(assetsPlatform) - eg, system_android_android.cfg or system_windows_pc.cfg
 
     std::vector< std::pair > m_updateTimes;
 
     struct SErrorMessage
     {
-        string m_Message;
+        AZStd::string m_Message;
         float m_fTimeToShow;
         float m_Color[4];
         bool m_HardFailure;
diff --git a/Code/Legacy/CrySystem/SystemCFG.cpp b/Code/Legacy/CrySystem/SystemCFG.cpp
index 719928384b..062713c015 100644
--- a/Code/Legacy/CrySystem/SystemCFG.cpp
+++ b/Code/Legacy/CrySystem/SystemCFG.cpp
@@ -279,7 +279,7 @@ public:
         int nFlags = pCVar->GetFlags();
         if (((nFlags & VF_DUMPTODISK) && (nFlags & VF_MODIFIED)) || (nFlags & VF_WASINCONFIG))
         {
-            string szValue = pCVar->GetString();
+            AZStd::string szValue = pCVar->GetString();
             int pos;
 
             pos = 1;
@@ -287,7 +287,7 @@ public:
             {
                 pos = szValue.find_first_of("\\", pos);
 
-                if (pos == string::npos)
+                if (pos == AZStd::string::npos)
                 {
                     break;
                 }
@@ -302,7 +302,7 @@ public:
             {
                 pos = szValue.find_first_of("\"", pos);
 
-                if (pos == string::npos)
+                if (pos == AZStd::string::npos)
                 {
                     break;
                 }
@@ -311,7 +311,7 @@ public:
                 pos += 2;
             }
 
-            string szLine = pCVar->GetName();
+            AZStd::string szLine = pCVar->GetName();
 
             if (pCVar->GetType() == CVAR_STRING)
             {
@@ -344,7 +344,7 @@ void CSystem::SaveConfiguration()
 //////////////////////////////////////////////////////////////////////////
 // system cfg
 //////////////////////////////////////////////////////////////////////////
-CSystemConfiguration::CSystemConfiguration(const string& strSysConfigFilePath, CSystem* pSystem, ILoadConfigurationEntrySink* pSink, bool warnIfMissing)
+CSystemConfiguration::CSystemConfiguration(const AZStd::string& strSysConfigFilePath, CSystem* pSystem, ILoadConfigurationEntrySink* pSink, bool warnIfMissing)
     : m_strSysConfigFilePath(strSysConfigFilePath)
     , m_bError(false)
     , m_pSink(pSink)
@@ -364,14 +364,14 @@ CSystemConfiguration::~CSystemConfiguration()
 //////////////////////////////////////////////////////////////////////////
 bool CSystemConfiguration::ParseSystemConfig()
 {
-    string filename = m_strSysConfigFilePath;
-    if (strlen(PathUtil::GetExt(filename)) == 0)
+    AZStd::string filename = m_strSysConfigFilePath;
+    if (strlen(PathUtil::GetExt(filename.c_str())) == 0)
     {
         filename = PathUtil::ReplaceExtension(filename, "cfg");
     }
 
     CCryFile file;
-    string filenameLog;
+    AZStd::string filenameLog;
     {
         int flags = AZ::IO::IArchive::FOPEN_HINT_QUIET | AZ::IO::IArchive::FOPEN_ONDISK;
 
@@ -380,7 +380,7 @@ bool CSystemConfiguration::ParseSystemConfig()
             // this is used when theres a very specific file to read, like @user@/game.cfg which is read
             // IN ADDITION to the one in the game folder, and afterwards to override values in it.
             // if the file is missing and its already prefixed with an alias, there is no need to look any further.
-            if (!(file.Open(filename, "rb", flags)))
+            if (!(file.Open(filename.c_str(), "rb", flags)))
             {
                 if (m_warnIfMissing)
                 {
@@ -394,11 +394,11 @@ bool CSystemConfiguration::ParseSystemConfig()
             // otherwise, if the file isn't prefixed with an alias, then its likely one of the convenience mappings
             // to either root or assets/config.  this is done so that code can just request a simple file name and get its data
             if (
-                !(file.Open(filename, "rb", flags)) &&
-                !(file.Open(string("@root@/") + filename, "rb", flags)) &&
-                !(file.Open(string("@assets@/") + filename, "rb", flags)) &&
-                !(file.Open(string("@assets@/config/") + filename, "rb", flags)) &&
-                !(file.Open(string("@assets@/config/spec/") + filename, "rb", flags))
+                !(file.Open(filename.c_str(), "rb", flags)) &&
+                !(file.Open((AZStd::string("@root@/") + filename).c_str(), "rb", flags)) &&
+                !(file.Open((AZStd::string("@assets@/") + filename).c_str(), "rb", flags)) &&
+                !(file.Open((AZStd::string("@assets@/config/") + filename).c_str(), "rb", flags)) &&
+                !(file.Open((AZStd::string("@assets@/config/spec/") + filename).c_str(), "rb", flags))
                 )
             {
                 if (m_warnIfMissing)
@@ -429,7 +429,7 @@ bool CSystemConfiguration::ParseSystemConfig()
     sAllText[nLen] = '\0';
     sAllText[nLen + 1] = '\0';
 
-    string strGroup;            // current group e.g. "[General]"
+    AZStd::string strGroup;            // current group e.g. "[General]"
 
     char* strLast = sAllText + nLen;
     char* str = sAllText;
@@ -447,11 +447,11 @@ bool CSystemConfiguration::ParseSystemConfig()
             str++;
         }
 
-        string strLine = s;
+        AZStd::string strLine = s;
 
         // detect groups e.g. "[General]"   should set strGroup="General"
         {
-            string strTrimmedLine(RemoveWhiteSpaces(strLine));
+            AZStd::string strTrimmedLine(RemoveWhiteSpaces(strLine));
             size_t size = strTrimmedLine.size();
 
             if (size >= 3)
@@ -466,7 +466,7 @@ bool CSystemConfiguration::ParseSystemConfig()
         }
 
         //trim all whitespace characters at the beginning and the end of the current line and store its size
-        strLine.Trim();
+        AZ::StringFunc::TrimWhiteSpace(strLine, true, true);
         size_t strLineSize = strLine.size();
 
         //skip comments, comments start with ";" or "--" but may have preceding whitespace characters
@@ -488,35 +488,35 @@ bool CSystemConfiguration::ParseSystemConfig()
         }
 
         //if line contains a '=' try to read and assign console variable
-        string::size_type posEq(strLine.find("=", 0));
-        if (string::npos != posEq)
+        AZStd::string::size_type posEq(strLine.find("=", 0));
+        if (AZStd::string::npos != posEq)
         {
-            string stemp(strLine, 0, posEq);
-            string strKey(RemoveWhiteSpaces(stemp));
+            AZStd::string stemp(strLine, 0, posEq);
+            AZStd::string strKey(RemoveWhiteSpaces(stemp));
 
             {
                 // extract value
-                string::size_type posValueStart(strLine.find("\"", posEq + 1) + 1);
-                string::size_type posValueEnd(strLine.rfind('\"'));
+                AZStd::string::size_type posValueStart(strLine.find("\"", posEq + 1) + 1);
+                AZStd::string::size_type posValueEnd(strLine.rfind('\"'));
 
-                string strValue;
+                AZStd::string strValue;
 
-                if (string::npos != posValueStart && string::npos != posValueEnd)
+                if (AZStd::string::npos != posValueStart && AZStd::string::npos != posValueEnd)
                 {
-                    strValue = string(strLine, posValueStart, posValueEnd - posValueStart);
+                    strValue = AZStd::string(strLine, posValueStart, posValueEnd - posValueStart);
                 }
                 else
                 {
-                    string strTmp(strLine, posEq + 1, strLine.size() - (posEq + 1));
+                    AZStd::string strTmp(strLine, posEq + 1, strLine.size() - (posEq + 1));
                     strValue = RemoveWhiteSpaces(strTmp);
                 }
 
                 {
                     // replace '\\\\' with '\\' and '\\\"' with '\"'
-                    strValue.replace("\\\\", "\\");
-                    strValue.replace("\\\"", "\"");
+                    AZ::StringFunc::Replace(strValue, "\\\\", "\\");
+                    AZ::StringFunc::Replace(strValue, "\\\"", "\"");
                     
-                    m_pSink->OnLoadConfigurationEntry(strKey, strValue, strGroup);
+                    m_pSink->OnLoadConfigurationEntry(strKey.c_str(), strValue.c_str(), strGroup.c_str());
                 }
             }
         }
diff --git a/Code/Legacy/CrySystem/SystemCFG.h b/Code/Legacy/CrySystem/SystemCFG.h
index ac4f04d146..cfaefd2e45 100644
--- a/Code/Legacy/CrySystem/SystemCFG.h
+++ b/Code/Legacy/CrySystem/SystemCFG.h
@@ -15,17 +15,17 @@
 #include 
 #include 
 
-typedef string SysConfigKey;
-typedef string SysConfigValue;
+typedef AZStd::string SysConfigKey;
+typedef AZStd::string SysConfigValue;
 
 //////////////////////////////////////////////////////////////////////////
 class CSystemConfiguration
 {
 public:
-    CSystemConfiguration(const string& strSysConfigFilePath, CSystem* pSystem, ILoadConfigurationEntrySink* pSink, bool warnIfMissing = true);
+    CSystemConfiguration(const AZStd::string& strSysConfigFilePath, CSystem* pSystem, ILoadConfigurationEntrySink* pSink, bool warnIfMissing = true);
     ~CSystemConfiguration();
 
-    string RemoveWhiteSpaces(string& s)
+    AZStd::string RemoveWhiteSpaces(AZStd::string& s)
     {
         s.Trim();
         return s;
@@ -39,10 +39,10 @@ private: // ----------------------------------------
     //   success
     bool ParseSystemConfig();
 
-    CSystem*                                               m_pSystem;
-    string                                                  m_strSysConfigFilePath;
-    bool                                                        m_bError;
-    ILoadConfigurationEntrySink*       m_pSink;                                         // never 0
+    CSystem*                           m_pSystem;
+    AZStd::string                      m_strSysConfigFilePath;
+    bool                               m_bError;
+    ILoadConfigurationEntrySink*       m_pSink;  // never 0
     bool m_warnIfMissing;
 };
 
diff --git a/Code/Legacy/CrySystem/SystemInit.cpp b/Code/Legacy/CrySystem/SystemInit.cpp
index cce3cf4aec..ae177a9974 100644
--- a/Code/Legacy/CrySystem/SystemInit.cpp
+++ b/Code/Legacy/CrySystem/SystemInit.cpp
@@ -33,7 +33,6 @@
 
 #include "CryLibrary.h"
 #include "CryPath.h"
-#include 
 
 #include 
 #include 
diff --git a/Code/Legacy/CrySystem/SystemWin32.cpp b/Code/Legacy/CrySystem/SystemWin32.cpp
index 943a540ae6..a4be0e5054 100644
--- a/Code/Legacy/CrySystem/SystemWin32.cpp
+++ b/Code/Legacy/CrySystem/SystemWin32.cpp
@@ -505,9 +505,7 @@ bool CSystem::GetWinGameFolder(char* szMyDocumentsPath, int maxPathSize)
             if (bSucceeded)
             {
                 // Convert from UNICODE to UTF-8
-                AZStd::string str;
-                AZStd::to_string(str, AZStd::wstring(wMyDocumentsPath));
-                azstrcpy(szMyDocumentsPath, maxPathSize, str.c_str());
+                azstrcpy(szMyDocumentsPath, maxPathSize, CryStringUtils::WStrToUTF8(wMyDocumentsPath));
                 CoTaskMemFree(wMyDocumentsPath);
             }
         }
@@ -521,9 +519,7 @@ bool CSystem::GetWinGameFolder(char* szMyDocumentsPath, int maxPathSize)
         bSucceeded = SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_PERSONAL | CSIDL_FLAG_CREATE, NULL, 0, wMyDocumentsPath));
         if (bSucceeded)
         {
-            AZStd::string str;
-            AZStd::to_string(str, AZStd::wstring(wMyDocumentsPath));
-            azstrcpy(szMyDocumentsPath, maxPathSize, str.c_str());
+            azstrcpy(szMyDocumentsPath, maxPathSize, CryStringUtils::WStrToUTF8(wMyDocumentsPath));
         }
     }
 
diff --git a/Code/Legacy/CrySystem/XML/ReadWriteXMLSink.h b/Code/Legacy/CrySystem/XML/ReadWriteXMLSink.h
index 2634195f64..b4dd28e813 100644
--- a/Code/Legacy/CrySystem/XML/ReadWriteXMLSink.h
+++ b/Code/Legacy/CrySystem/XML/ReadWriteXMLSink.h
@@ -36,7 +36,7 @@ public:
     ELSE_LOAD_PROPERTY(Vec3);                       \
     ELSE_LOAD_PROPERTY(int);                        \
     ELSE_LOAD_PROPERTY(float);                      \
-    ELSE_LOAD_PROPERTY(string);                     \
+    ELSE_LOAD_PROPERTY(AZStd::string);              \
     ELSE_LOAD_PROPERTY(bool);
 
 
diff --git a/Code/Legacy/CrySystem/XML/ReadXMLSink.cpp b/Code/Legacy/CrySystem/XML/ReadXMLSink.cpp
index bddc538bba..e75fed22ed 100644
--- a/Code/Legacy/CrySystem/XML/ReadXMLSink.cpp
+++ b/Code/Legacy/CrySystem/XML/ReadXMLSink.cpp
@@ -13,7 +13,7 @@
 #include 
 #include 
 
-typedef std::map IdTable;
+typedef std::map IdTable;
 struct SParseParams
 {
     IdTable idTable;
@@ -98,7 +98,7 @@ struct ReadPropertyTyped
 };
 
 template <>
-struct ReadPropertyTyped
+struct ReadPropertyTyped
 {
     static bool Load(const SParseParams& parseParams, const char* name, XmlNodeRef& definition, XmlNodeRef& data, IReadXMLSink* pSink)
     {
@@ -235,8 +235,9 @@ bool LoadProperty(const SParseParams& parseParams, XmlNodeRef& definition, XmlNo
 
             dataToRead = GetISystem()->CreateXmlNode(data->getTag());
 
-            string content = childRef->getContent();
-            dataToRead->setAttr(name, content.Trim().c_str());
+            AZStd::string content = childRef->getContent();
+            AZ::StringFunc::TrimWhiteSpace(content, true, true);
+            dataToRead->setAttr(name, content.c_str());
         }
 
         if (!dataToRead->haveAttr(name))
diff --git a/Code/Legacy/CrySystem/XML/SerializeXMLWriter.cpp b/Code/Legacy/CrySystem/XML/SerializeXMLWriter.cpp
index e98071ace0..26007eb229 100644
--- a/Code/Legacy/CrySystem/XML/SerializeXMLWriter.cpp
+++ b/Code/Legacy/CrySystem/XML/SerializeXMLWriter.cpp
@@ -114,7 +114,7 @@ void CSerializeXMLWriterImpl::GetMemoryUsage(ICrySizer* pSizer) const
 //////////////////////////////////////////////////////////////////////////
 const char* CSerializeXMLWriterImpl::GetStackInfo() const
 {
-    static string str;
+    static AZStd::string str;
     str.assign("");
     for (int i = 0; i < (int)m_nodeStack.size(); i++)
     {
@@ -138,7 +138,7 @@ const char* CSerializeXMLWriterImpl::GetStackInfo() const
 //////////////////////////////////////////////////////////////////////////
 const char* CSerializeXMLWriterImpl::GetLuaStackInfo() const
 {
-    static string str;
+    static AZStd::string str;
     str.assign("");
     for (int i = 0; i < (int)m_luaSaveStack.size(); i++)
     {
diff --git a/Code/Legacy/CrySystem/XML/SerializeXMLWriter.h b/Code/Legacy/CrySystem/XML/SerializeXMLWriter.h
index 12a2f6f151..41dbe3dd7b 100644
--- a/Code/Legacy/CrySystem/XML/SerializeXMLWriter.h
+++ b/Code/Legacy/CrySystem/XML/SerializeXMLWriter.h
@@ -138,7 +138,7 @@ private:
     bool IsDefaultValue(const Quat& v) const { return v.w == 1.0f && v.v.x == 0 && v.v.y == 0 && v.v.z == 0; };
     bool IsDefaultValue(const CTimeValue& v) const { return v.GetValue() == 0; };
     bool IsDefaultValue(const char* str) const { return !str || !*str; };
-    bool IsDefaultValue(const string& str) const { return str.empty(); };
+    bool IsDefaultValue(const AZStd::string& str) const { return str.empty(); };
     bool IsDefaultValue(const SSerializeString& str) const { return str.empty(); };
     //////////////////////////////////////////////////////////////////////////
 
diff --git a/Code/Legacy/CrySystem/XML/WriteXMLSource.cpp b/Code/Legacy/CrySystem/XML/WriteXMLSource.cpp
index 2a532befd3..b0d7a6f1af 100644
--- a/Code/Legacy/CrySystem/XML/WriteXMLSource.cpp
+++ b/Code/Legacy/CrySystem/XML/WriteXMLSource.cpp
@@ -12,7 +12,7 @@
 
 #include 
 
-typedef std::map IdTable;
+typedef std::map IdTable;
 
 static bool IsOptionalWriteXML(XmlNodeRef& definition);
 
@@ -66,7 +66,7 @@ struct WritePropertyTyped
 };
 
 template <>
-struct WritePropertyTyped
+struct WritePropertyTyped
     : public WritePropertyTyped
 {
 };
diff --git a/Code/Legacy/CrySystem/XML/XMLBinaryWriter.h b/Code/Legacy/CrySystem/XML/XMLBinaryWriter.h
index 7dcbe075cd..810a2268c9 100644
--- a/Code/Legacy/CrySystem/XML/XMLBinaryWriter.h
+++ b/Code/Legacy/CrySystem/XML/XMLBinaryWriter.h
@@ -25,25 +25,25 @@ namespace XMLBinary
     {
     public:
         CXMLBinaryWriter();
-        bool WriteNode(IDataWriter* pFile, XmlNodeRef node, bool bNeedSwapEndian, XMLBinary::IFilter* pFilter, string& error);
+        bool WriteNode(IDataWriter* pFile, XmlNodeRef node, bool bNeedSwapEndian, XMLBinary::IFilter* pFilter, AZStd::string & error);
 
     private:
-        bool CompileTables(XmlNodeRef node, XMLBinary::IFilter* pFilter, string& error);
+        bool CompileTables(XmlNodeRef node, XMLBinary::IFilter* pFilter, AZStd::string& error);
 
-        bool CompileTablesForNode(XmlNodeRef node, int nParentIndex, XMLBinary::IFilter* pFilter, string& error);
-        bool CompileChildTable(XmlNodeRef node, XMLBinary::IFilter* pFilter, string& error);
+        bool CompileTablesForNode(XmlNodeRef node, int nParentIndex, XMLBinary::IFilter* pFilter, AZStd::string& error);
+        bool CompileChildTable(XmlNodeRef node, XMLBinary::IFilter* pFilter, AZStd::string& error);
         int AddString(const XmlString& sString);
 
     private:
         // tables.
         typedef std::map NodesMap;
-        typedef std::map StringMap;
+        typedef std::map StringMap;
 
         std::vector m_nodes;
         NodesMap m_nodesMap;
         std::vector m_attributes;
         std::vector m_childs;
-        std::vector m_strings;
+        std::vector m_strings;
         StringMap m_stringMap;
 
         uint m_nStringDataSize;
diff --git a/Code/Legacy/CrySystem/XML/XMLPatcher.cpp b/Code/Legacy/CrySystem/XML/XMLPatcher.cpp
index ff4cfc91d2..03c5af92d3 100644
--- a/Code/Legacy/CrySystem/XML/XMLPatcher.cpp
+++ b/Code/Legacy/CrySystem/XML/XMLPatcher.cpp
@@ -9,7 +9,6 @@
 
 #include "CrySystem_precompiled.h"
 #include "XMLPatcher.h"
-#include "StringUtils.h"
 
 CXMLPatcher::CXMLPatcher(XmlNodeRef& patchXML)
 {
@@ -84,7 +83,7 @@ XmlNodeRef CXMLPatcher::FindPatchForFile(
             {
                 const char* pForFile = child->getAttr("forfile");
 
-                if (pForFile && CryStringUtils::stristr(pForFile, pInFileToPatch) != 0)
+                if (pForFile && AZ::StringFunc::Find(pForFile, pInFileToPatch) != AZStd::string::npos)
                 {
                     result = child;
                     break;
@@ -353,7 +352,7 @@ void CXMLPatcher::DumpXMLNodes(
 
     INDENT();
 
-    ioTempString->Format("<%s ", inNode->getTag());
+    *ioTempString = AZStd::fixed_string<512>::format("<%s ", inNode->getTag());
 
     pPak->FWrite(ioTempString->c_str(), ioTempString->length(), inFileHandle);
 
@@ -361,7 +360,7 @@ void CXMLPatcher::DumpXMLNodes(
     {
         const char* pKey, * pVal;
         inNode->getAttributeByIndex(i, &pKey, &pVal);
-        ioTempString->Format("%s=\"%s\" ", pKey, pVal);
+        *ioTempString = AZStd::fixed_string<512>::format("%s=\"%s\" ", pKey, pVal);
         pPak->FWrite(ioTempString->c_str(), ioTempString->length(), inFileHandle);
     }
     pPak->FWrite(">\n", 2, inFileHandle);
@@ -372,7 +371,7 @@ void CXMLPatcher::DumpXMLNodes(
     }
 
     INDENT();
-    ioTempString->Format("\n", inNode->getTag());
+    *ioTempString = AZStd::fixed_string<512>::format("\n", inNode->getTag());
     pPak->FWrite(ioTempString->c_str(), ioTempString->length(), inFileHandle);
 }
 
@@ -391,12 +390,12 @@ void CXMLPatcher::DumpFiles(
         {
             pOrigFileName++;
 
-            DumpXMLFile(string().Format("PATCH_%s", pOrigFileName), inBefore);
+            DumpXMLFile(AZStd::string::format("PATCH_%s", pOrigFileName).c_str(), inBefore);
 
-            AZStd::fixed_string<128>        newFileName(pOrigFileName);
-            newFileName.replace(".xml", "_patched.xml");
+            AZStd::string newFileName(pOrigFileName);
+            AZ::StringFunc::Replace(newFileName, ".xml", "_patched.xml");
 
-            DumpXMLFile(string().Format("PATCH_%s", newFileName.c_str()), inAfter);
+            DumpXMLFile(AZStd::string::format("PATCH_%s", newFileName.c_str()).c_str(), inAfter);
         }
         else
         {
diff --git a/Code/Legacy/CrySystem/XML/XmlUtils.cpp b/Code/Legacy/CrySystem/XML/XmlUtils.cpp
index 1b341ee99e..5e31fff8d7 100644
--- a/Code/Legacy/CrySystem/XML/XmlUtils.cpp
+++ b/Code/Legacy/CrySystem/XML/XmlUtils.cpp
@@ -313,7 +313,7 @@ bool CXmlUtils::SaveBinaryXmlFile(const char* filename, XmlNodeRef root)
         return false;
     }
     XMLBinary::CXMLBinaryWriter writer;
-    string error;
+    AZStd::string error;
     return writer.WriteNode(&fileSink, root, false, 0, error);
 }
 
diff --git a/Code/Legacy/CrySystem/XML/xml.cpp b/Code/Legacy/CrySystem/XML/xml.cpp
index c6e660155f..728d9441f2 100644
--- a/Code/Legacy/CrySystem/XML/xml.cpp
+++ b/Code/Legacy/CrySystem/XML/xml.cpp
@@ -984,13 +984,13 @@ XmlString CXmlNode::MakeValidXmlString(const XmlString& instr) const
     XmlString str = instr;
 
     // check if str contains any invalid characters
-    str.replace("&", "&");
-    str.replace("\"", """);
-    str.replace("\'", "'");
-    str.replace("<", "<");
-    str.replace(">", ">");
-    str.replace("...", ">");
-    str.replace("\n", "
");
+    AZ::StringFunc::Replace(str, "&", "&");
+    AZ::StringFunc::Replace(str, "\"", """);
+    AZ::StringFunc::Replace(str, "\'", "'");
+    AZ::StringFunc::Replace(str, "<", "<");
+    AZ::StringFunc::Replace(str, ">", ">");
+    AZ::StringFunc::Replace(str, "...", ">");
+    AZ::StringFunc::Replace(str, "\n", "
");
 
     return str;
 }
@@ -1732,9 +1732,9 @@ XmlNodeRef XmlParserImp::ParseFile(const char* filename, XmlString& errorString,
             return 0;
         }
         adjustedFilename = xmlFile.GetAdjustedFilename();
-        adjustedFilename.replace('\\', '/');
+        AZStd::replace(adjustedFilename.begin(), adjustedFilename.end(), '\\', '/');
         pakPath = xmlFile.GetPakPath();
-        pakPath.replace('\\', '/');
+        AZStd::replace(pakPath.begin(), pakPath.end(), '\\', '/');
     }
 
     if (g_bEnableBinaryXmlLoading)
diff --git a/Code/Tools/GridHub/GridHub/gridhub.cpp b/Code/Tools/GridHub/GridHub/gridhub.cpp
index f6f0988022..3dbecf681f 100644
--- a/Code/Tools/GridHub/GridHub/gridhub.cpp
+++ b/Code/Tools/GridHub/GridHub/gridhub.cpp
@@ -362,13 +362,9 @@ GridHubComponent::GridHubComponent()
     DWORD dwCompNameLen = AZ_ARRAY_SIZE(name);
     if ( GetComputerName(name, &dwCompNameLen) != 0 ) 
     {
-#ifdef _UNICODE
         char c[MAX_COMPUTERNAME_LENGTH + 1];
         wcstombs(c, name, AZ_ARRAY_SIZE(c));
         m_hubName = c;
-#else
-        m_hubName = name;
-#endif
     }
     else
 #endif
diff --git a/Code/Tools/Standalone/CMakeLists.txt b/Code/Tools/Standalone/CMakeLists.txt
index 479b8be11f..a8242022a8 100644
--- a/Code/Tools/Standalone/CMakeLists.txt
+++ b/Code/Tools/Standalone/CMakeLists.txt
@@ -36,7 +36,6 @@ ly_add_target(
             ${additional_dependencies}
     COMPILE_DEFINITIONS 
         PRIVATE
-            UNICODE
             STANDALONETOOLS_ENABLE_LUA_IDE
 )
 
@@ -68,6 +67,5 @@ ly_add_target(
             ${additional_dependencies}
     COMPILE_DEFINITIONS 
         PRIVATE
-            UNICODE
             STANDALONETOOLS_ENABLE_PROFILER
 )
diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Platform/Windows/FFontXML_Windows.cpp b/Gems/AtomLyIntegration/AtomFont/Code/Platform/Windows/FFontXML_Windows.cpp
index f72ba6e1ff..4c923c43c4 100644
--- a/Gems/AtomLyIntegration/AtomFont/Code/Platform/Windows/FFontXML_Windows.cpp
+++ b/Gems/AtomLyIntegration/AtomFont/Code/Platform/Windows/FFontXML_Windows.cpp
@@ -8,6 +8,8 @@
 
 #include 
 
+#include 
+
 #include 
 
 namespace AtomFontInternal
@@ -17,13 +19,11 @@ namespace AtomFontInternal
         TCHAR sysFontPath[MAX_PATH];
         if (SUCCEEDED(SHGetFolderPath(0, CSIDL_FONTS, 0, SHGFP_TYPE_DEFAULT, sysFontPath)))
         {
-            const char* fontPath = m_strFontPath.c_str();
-            const char* fontName = AZ::IO::PathView(fontPath).Filename();
+            const AZ::IO::PathView fontName = AZ::IO::PathView(m_strFontPath.c_str()).Filename();
 
-            string newFontPath(sysFontPath);
-            newFontPath += "/";
-            newFontPath += fontName;
-            m_font->Load(newFontPath, m_FontTexSize.x, m_FontTexSize.y, m_slotSizes.x, m_slotSizes.y, CreateTTFFontFlag(m_FontSmoothMethod, m_FontSmoothAmount), m_SizeRatio);
+            AZ::IO::Path newFontPath(sysFontPath);
+            newFontPath /= fontName;
+            m_font->Load(newFontPath.c_str(), m_FontTexSize.x, m_FontTexSize.y, m_slotSizes.x, m_slotSizes.y, CreateTTFFontFlag(m_FontSmoothMethod, m_FontSmoothAmount), m_SizeRatio);
         }
     }
 }
diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Platform/Windows/FontTexture_Windows.cpp b/Gems/AtomLyIntegration/AtomFont/Code/Platform/Windows/FontTexture_Windows.cpp
index 5aae754a7d..33950689f5 100644
--- a/Gems/AtomLyIntegration/AtomFont/Code/Platform/Windows/FontTexture_Windows.cpp
+++ b/Gems/AtomLyIntegration/AtomFont/Code/Platform/Windows/FontTexture_Windows.cpp
@@ -11,7 +11,7 @@
 #include 
 
 //-------------------------------------------------------------------------------------------------
-int AZ::FontTexture::WriteToFile(const string& fileName)
+int AZ::FontTexture::WriteToFile(const AZStd::string& fileName)
 {
     AZ::IO::FileIOStream outputFile(fileName.c_str(), AZ::IO::OpenMode::ModeWrite | AZ::IO::OpenMode::ModeBinary);
 
diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Source/AtomFont.cpp b/Gems/AtomLyIntegration/AtomFont/Code/Source/AtomFont.cpp
index 35c2b26b48..ecf0789220 100644
--- a/Gems/AtomLyIntegration/AtomFont/Code/Source/AtomFont.cpp
+++ b/Gems/AtomLyIntegration/AtomFont/Code/Source/AtomFont.cpp
@@ -46,7 +46,7 @@ static void DumfontTexture(IConsoleCmdArgs* cmdArgs)
 
     if (fontName && *fontName && *fontName != '0')
     {
-        string fontFilePath("@devroot@/");
+        AZStd::string fontFilePath("@devroot@/");
         fontFilePath += fontName;
         fontFilePath += ".bmp";
 
@@ -61,7 +61,7 @@ static void DumfontTexture(IConsoleCmdArgs* cmdArgs)
 
 static void DumfontNames([[maybe_unused]] IConsoleCmdArgs* cmdArgs)
 {
-    string names = gEnv->pCryFont->GetLoadedFontNames();
+    AZStd::string names = gEnv->pCryFont->GetLoadedFontNames();
     gEnv->pLog->LogWithType(IMiniLog::eInputResponse, "Currently loaded fonts: %s", names.c_str());
 }
 
@@ -97,15 +97,15 @@ namespace
                 && !m_boldItalicFontFilename.empty();
         }
 
-        string m_lang;                      //!< Stores a comma-separated list of languages this collection of fonts applies to.
+        AZStd::string m_lang;               //!< Stores a comma-separated list of languages this collection of fonts applies to.
                                             //!< If this is an empty string, it implies that these set of fonts will be applied
                                             //!< by default (when a language is being used but no fonts in the font family are
                                             //!< mapped to that language).
 
-        string m_fontFilename;              //!< Font used when no styling is applied.
-        string m_boldFontFilename;          //!< Bold-styled font
-        string m_italicFontFilename;        //!< Italic-styled font
-        string m_boldItalicFontFilename;    //!< Bold-italic-styled font
+        AZStd::string m_fontFilename;              //!< Font used when no styling is applied.
+        AZStd::string m_boldFontFilename;          //!< Bold-styled font
+        AZStd::string m_italicFontFilename;        //!< Italic-styled font
+        AZStd::string m_boldItalicFontFilename;    //!< Bold-italic-styled font
     };
 
     //! Stores parsed font family XML data.
@@ -152,7 +152,7 @@ namespace
             return !m_fontFamilyName.empty();
         }
 
-        string m_fontFamilyName;                  //!< Value of the "name" font-family tag attribute
+        AZStd::string m_fontFamilyName;                  //!< Value of the "name" font-family tag attribute
         AZStd::list m_fontTagsXml;    //!< List of child  tag data.
     };
 
@@ -179,7 +179,7 @@ namespace
                 return false;
             }
 
-            string name;
+            AZStd::string name;
 
             for (int i = 0, count = node->getNumAttributes(); i < count; ++i)
             {
@@ -187,7 +187,7 @@ namespace
                 const char* value = "";
                 if (node->getAttributeByIndex(i, &key, &value))
                 {
-                    if (string(key) == "name")
+                    if (AZStd::string(key) == "name")
                     {
                         name = value;
                     }
@@ -199,7 +199,7 @@ namespace
                 }
             }
 
-            name.Trim();
+            AZ::StringFunc::TrimWhiteSpace(name, true, true);
             if (!name.empty())
             {
                 xmlData.m_fontFamilyName = name;
@@ -216,14 +216,14 @@ namespace
         {
             xmlData.m_fontTagsXml.push_back(FontTagXml());
 
-            string lang;
+            AZStd::string lang;
             for (int i = 0, count = node->getNumAttributes(); i < count; ++i)
             {
                 const char* key = "";
                 const char* value = "";
                 if (node->getAttributeByIndex(i, &key, &value))
                 {
-                    if (string(key) == "lang")
+                    if (AZStd::string(key) == "lang")
                     {
                         lang = value;
                     }
@@ -235,7 +235,7 @@ namespace
                 }
             }
 
-            lang.Trim();
+            AZ::StringFunc::TrimWhiteSpace(lang, true, true);
             if (!lang.empty())
             {
                 xmlData.m_fontTagsXml.back().m_lang = lang;
@@ -253,8 +253,8 @@ namespace
                 return false;
             }
 
-            string path;
-            string tags;
+            AZStd::string path;
+            AZStd::string tags;
 
             for (int i = 0, count = node->getNumAttributes(); i < count; ++i)
             {
@@ -262,11 +262,11 @@ namespace
                 const char* value = "";
                 if (node->getAttributeByIndex(i, &key, &value))
                 {
-                    if (string(key) == "path")
+                    if (AZStd::string(key) == "path")
                     {
                         path = value;
                     }
-                    else if (string(key) == "tags")
+                    else if (AZStd::string(key) == "tags")
                     {
                         tags = value;
                     }
@@ -278,7 +278,7 @@ namespace
                 }
             }
 
-            tags.Trim();
+            AZ::StringFunc::TrimWhiteSpace(tags, true, true);
             if (tags.empty())
             {
                 xmlData.m_fontTagsXml.back().m_fontFilename = path;
@@ -315,7 +315,7 @@ namespace
     //! when referencing font family names from font family XML files), and
     //! attempting to load the XML files directly via ISystem() methods can
     //! produce a lot of warning noise.
-    XmlNodeRef SafeLoadXmlFromFile(const string& xmlPath)
+    XmlNodeRef SafeLoadXmlFromFile(const AZStd::string& xmlPath)
     {
         if (gEnv->pCryPak->IsFileExist(xmlPath.c_str()))
         {
@@ -383,8 +383,8 @@ void AZ::AtomFont::Release()
 
 IFFont* AZ::AtomFont::NewFont(const char* fontName)
 {
-    string name = fontName;
-    name.MakeLower();
+    AZStd::string name = fontName;
+    AZStd::to_lower(name.begin(), name.end());
     AzFramework::FontId fontId = GetFontId(name.c_str());
 
     FontMapItor it = m_fonts.find(fontId);
@@ -404,7 +404,9 @@ IFFont* AZ::AtomFont::NewFont(const char* fontName)
 
 IFFont* AZ::AtomFont::GetFont(const char* fontName) const
 {
-    AzFramework::FontId fontId = GetFontId(string(fontName).MakeLower().c_str());
+    AZStd::string name = fontName;
+    AZStd::to_lower(name.begin(), name.end());
+    AzFramework::FontId fontId = GetFontId(name.c_str());
     FontMapConstItor it = m_fonts.find(fontId);
     return it != m_fonts.end() ? it->second : 0;
 }
@@ -423,8 +425,8 @@ AzFramework::FontDrawInterface* AZ::AtomFont::GetDefaultFontDrawInterface() cons
 FontFamilyPtr AZ::AtomFont::LoadFontFamily(const char* fontFamilyName)
 {
     FontFamilyPtr fontFamily(nullptr);
-    string fontFamilyPath;
-    string fontFamilyFullPath;
+    AZStd::string fontFamilyPath;
+    AZStd::string fontFamilyFullPath;
     
     XmlNodeRef root = LoadFontFamilyXml(fontFamilyName, fontFamilyPath, fontFamilyFullPath);
 
@@ -450,13 +452,13 @@ FontFamilyPtr AZ::AtomFont::LoadFontFamily(const char* fontFamilyName)
                 }
                 else
                 {
-                    int searchPos = 0;
-                    string langToken;
-
                     // "lang" font-tag attribute could be comma-separated
-                    while (!(langToken = fontTagXml.m_lang.Tokenize(",", searchPos)).empty())
+                    AZStd::vector tokens;
+                    AZ::StringFunc::Tokenize(fontTagXml.m_lang, tokens, ',');
+                    for(AZStd::string& langToken : tokens)
                     {
-                        if (langToken.Trim() == currentLanguage)
+                        AZ::StringFunc::TrimWhiteSpace(langToken, true, true);
+                        if (langToken == currentLanguage)
                         {
                             langSpecificFont = &fontTagXml;
                             break;
@@ -494,7 +496,7 @@ FontFamilyPtr AZ::AtomFont::LoadFontFamily(const char* fontFamilyName)
                     // Map the font family name both by path and by name defined
                     // within the Font Family XML itself. This allows font 
                     // families to also be referenced simply by name.
-                    if (!AddFontFamilyToMaps(fontFamilyFullPath, xmlData.m_fontFamilyName, fontFamily))
+                    if (!AddFontFamilyToMaps(fontFamilyFullPath.c_str(), xmlData.m_fontFamilyName.c_str(), fontFamily))
                     {
                         SAFE_RELEASE(normal);
                         SAFE_RELEASE(bold);
@@ -540,7 +542,7 @@ FontFamilyPtr AZ::AtomFont::LoadFontFamily(const char* fontFamilyName)
             // Use filepath as familyName so font loading/unloading doesn't break with duplicate file names
             fontFamily->familyName = fontFamilyName;
 
-            if (!AddFontFamilyToMaps(fontFamilyName, fontFamily->familyName, fontFamily))
+            if (!AddFontFamilyToMaps(fontFamilyName, fontFamily->familyName.c_str(), fontFamily))
             {
                 SAFE_RELEASE(font);
 
@@ -581,7 +583,9 @@ FontFamilyPtr AZ::AtomFont::GetFontFamily(const char* fontFamilyName)
     // or just the filename of a font itself. Fonts are mapped by font family
     // name or by filepath, so attempt lookup using the map first since it's
     // the fastest.
-    string loweredName = string(fontFamilyName).Trim().MakeLower();
+    AZStd::string loweredName = AZStd::string(fontFamilyName);
+    AZ::StringFunc::TrimWhiteSpace(loweredName, true, true);
+    AZStd::to_lower(loweredName.begin(), loweredName.end());
     auto it = m_fontFamilies.find(PathUtil::MakeGamePath(loweredName).c_str());
     if (it != m_fontFamilies.end())
     {
@@ -596,9 +600,9 @@ FontFamilyPtr AZ::AtomFont::GetFontFamily(const char* fontFamilyName)
         for (const auto& fontFamilyIter : m_fontFamilies)
         {
             const AZStd::string& mappedFontFamilyName = fontFamilyIter.first;
-            string mappedFilenameNoExtension = PathUtil::GetFileName(mappedFontFamilyName.c_str());
+            AZStd::string mappedFilenameNoExtension = PathUtil::GetFileName(mappedFontFamilyName.c_str());
 
-            string searchStringFilenameNoExtension = PathUtil::GetFileName(loweredName);
+            AZStd::string searchStringFilenameNoExtension = PathUtil::GetFileName(loweredName);
 
             if (mappedFilenameNoExtension == searchStringFilenameNoExtension)
             {
@@ -619,9 +623,9 @@ void AZ::AtomFont::AddCharsToFontTextures(FontFamilyPtr fontFamily, const char*
     fontFamily->boldItalic->AddCharsToFontTexture(chars, glyphSizeX, glyphSizeY);
 }
 
-string AZ::AtomFont::GetLoadedFontNames() const
+AZStd::string AZ::AtomFont::GetLoadedFontNames() const
 {
-    string ret;
+    AZStd::string ret;
     for (FontMapConstItor it = m_fonts.begin(), itEnd = m_fonts.end(); it != itEnd; ++it)
     {
         FFont* font = it->second;
@@ -678,7 +682,9 @@ void AZ::AtomFont::ReloadAllFonts()
 
 void AZ::AtomFont::UnregisterFont(const char* fontName)
 {
-    AzFramework::FontId fontId = GetFontId(string(fontName).MakeLower().c_str());
+    AZStd::string name(fontName);
+    AZStd::to_lower(name.begin(), name.end());
+    AzFramework::FontId fontId = GetFontId(name.c_str());
     FontMapItor it = m_fonts.find(fontId);
 
 #if defined(AZ_ENABLE_TRACING)
@@ -715,10 +721,10 @@ void AZ::AtomFont::UnregisterFont(const char* fontName)
 
 IFFont* AZ::AtomFont::LoadFont(const char* fontName)
 {
-    string fontNameLower = fontName;
-    fontNameLower.MakeLower();
+    AZStd::string fontNameLower = fontName;
+    AZStd::to_lower(fontNameLower.begin(), fontNameLower.end());
 
-    IFFont* font = GetFont(fontNameLower);
+    IFFont* font = GetFont(fontNameLower.c_str());
     if (font)
     {
         font->AddRef(); // use existing loaded font
@@ -726,10 +732,10 @@ IFFont* AZ::AtomFont::LoadFont(const char* fontName)
     else
     {
         // attempt to create and load a new font, use the font pathname as the font name
-        font = NewFont(fontNameLower);
+        font = NewFont(fontNameLower.c_str());
         if (!font)
         {
-            string errorMsg = "Error creating a new font named ";
+            AZStd::string errorMsg = "Error creating a new font named ";
             errorMsg += fontNameLower;
             errorMsg += ".";
             CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_ERROR, errorMsg.c_str());
@@ -737,12 +743,12 @@ IFFont* AZ::AtomFont::LoadFont(const char* fontName)
         else
         {
             // creating font adds one to its refcount so no need for AddRef here
-            if (!font->Load(fontNameLower))
+            if (!font->Load(fontNameLower.c_str()))
             {
-                string errorMsg = "Error loading a font from ";
+                AZStd::string errorMsg = "Error loading a font from ";
                 errorMsg += fontNameLower;
                 errorMsg += ".";
-                CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_ERROR, errorMsg);
+                CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_ERROR, errorMsg.c_str());
                 font->Release();
                 font = nullptr;
             }
@@ -764,8 +770,9 @@ void AZ::AtomFont::ReleaseFontFamily(FontFamily* fontFamily)
     // Note that the FontFamily is mapped both by filename and by "family name"
     auto it = m_fontFamilyReverseLookup[fontFamily];
     m_fontFamilies.erase(it);
-    string familyName(fontFamily->familyName);
-    m_fontFamilies.erase(familyName.MakeLower().c_str());
+    AZStd::string familyName(fontFamily->familyName);
+    AZStd::to_lower(familyName.begin(), familyName.end());
+    m_fontFamilies.erase(familyName.c_str());
 
     // Reverse lookup is used to avoid needing to store filename path with
     // the font family, so we need to remove that entry also.
@@ -785,12 +792,11 @@ bool AZ::AtomFont::AddFontFamilyToMaps(const char* fontFamilyFilename, const cha
     }
 
     // We don't support "updating" mapped values. 
-    AZStd::string loweredFilename(PathUtil::MakeGamePath(string(fontFamilyFilename)).c_str());
+    AZStd::string loweredFilename(PathUtil::MakeGamePath(AZStd::string(fontFamilyFilename)).c_str());
     AZStd::to_lower(loweredFilename.begin(), loweredFilename.end());
     if (m_fontFamilies.find(loweredFilename) != m_fontFamilies.end())
     {
-        string warnMsg;
-        warnMsg.Format("Couldn't load Font Family '%s': already loaded", fontFamilyFilename);
+        AZStd::string warnMsg = AZStd::string::format("Couldn't load Font Family '%s': already loaded", fontFamilyFilename);
         CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, warnMsg.c_str());
         return false;
     }
@@ -801,8 +807,7 @@ bool AZ::AtomFont::AddFontFamilyToMaps(const char* fontFamilyFilename, const cha
     AZStd::to_lower(loweredFontFamilyName.begin(), loweredFontFamilyName.end());
     if (m_fontFamilies.find(loweredFontFamilyName) != m_fontFamilies.end())
     {
-        string warnMsg;
-        warnMsg.Format("Couldn't load Font Family '%s': already loaded", fontFamilyName);
+        AZStd::string warnMsg = AZStd::string::format("Couldn't load Font Family '%s': already loaded", fontFamilyName);
         CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, warnMsg.c_str());
         return false;
     }
@@ -819,7 +824,7 @@ bool AZ::AtomFont::AddFontFamilyToMaps(const char* fontFamilyFilename, const cha
     return true;
 }
 
-XmlNodeRef AZ::AtomFont::LoadFontFamilyXml(const char* fontFamilyName, string& outputDirectory, string& outputFullPath)
+XmlNodeRef AZ::AtomFont::LoadFontFamilyXml(const char* fontFamilyName, AZStd::string& outputDirectory, AZStd::string& outputFullPath)
 {
     outputFullPath = fontFamilyName;
     outputDirectory = PathUtil::GetPath(fontFamilyName);
@@ -829,8 +834,8 @@ XmlNodeRef AZ::AtomFont::LoadFontFamilyXml(const char* fontFamilyName, string& o
     // not a path, so we try to build a "best guess" path from the name.
     if (!root)
     {
-        string fileNoExtension(PathUtil::GetFileName(fontFamilyName));
-        string fileExtension(PathUtil::GetExt(fontFamilyName));
+        AZStd::string fileNoExtension(PathUtil::GetFileName(fontFamilyName));
+        AZStd::string fileExtension(PathUtil::GetExt(fontFamilyName));
 
         if (fileExtension.empty())
         {
@@ -838,14 +843,14 @@ XmlNodeRef AZ::AtomFont::LoadFontFamilyXml(const char* fontFamilyName, string& o
         }
 
         // Try: "fonts/fontName.fontfamily"
-        outputDirectory = string("fonts/");
+        outputDirectory = AZStd::string("fonts/");
         outputFullPath = outputDirectory + fileNoExtension + fileExtension;
         root = SafeLoadXmlFromFile(outputFullPath);
 
         // Finally, try: "fonts/fontName/fontName.fontfamily"
         if (!root)
         {
-            outputDirectory = string("fonts/") + fileNoExtension + "/";
+            outputDirectory = AZStd::string("fonts/") + fileNoExtension + "/";
             outputFullPath = outputDirectory + fileNoExtension + fileExtension;
             root = SafeLoadXmlFromFile(outputFullPath);
         }
diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp b/Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp
index c07717945a..ddb2fa6292 100644
--- a/Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp
+++ b/Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp
@@ -126,7 +126,7 @@ bool AZ::FFont::Load(const char* fontFilePath, unsigned int width, unsigned int
 
     auto pPak = gEnv->pCryPak;
 
-    string fullFile;
+    AZStd::string fullFile;
     if (pPak->IsAbsPath(fontFilePath))
     {
         fullFile = fontFilePath;
@@ -1166,7 +1166,7 @@ size_t AZ::FFont::GetTextLength(const char* str, const bool asciiMultiLine) cons
     return len;
 }
 
-void AZ::FFont::WrapText(string& result, float maxWidth, const char* str, const TextDrawContext& ctx)
+void AZ::FFont::WrapText(AZStd::string& result, float maxWidth, const char* str, const TextDrawContext& ctx)
 {
     result = str;
 
diff --git a/Gems/LyShine/Code/Editor/PropertyHandlerChar.cpp b/Gems/LyShine/Code/Editor/PropertyHandlerChar.cpp
index 98cbd22f71..ac55cd38e9 100644
--- a/Gems/LyShine/Code/Editor/PropertyHandlerChar.cpp
+++ b/Gems/LyShine/Code/Editor/PropertyHandlerChar.cpp
@@ -47,8 +47,7 @@ bool PropertyHandlerChar::ReadValuesIntoGUI(size_t index, AzToolsFramework::Prop
         // NOTE: this assumes the uint32_t can be interpreted as a wchar_t, it seems to
         // work for cases tested but may not in general.
         wchar_t wcharString[2] = { static_cast(instance), 0 };
-        AZStd::string val;
-        AZStd::to_string(val, AZStd::wstring(wcharString));
+        AZStd::string val(CryStringUtils::WStrToUTF8(wcharString));
         GUI->setValue(val);
     }
     GUI->blockSignals(false);
diff --git a/Gems/LyShine/Code/Source/Platform/Windows/UiClipboard_Windows.cpp b/Gems/LyShine/Code/Source/Platform/Windows/UiClipboard_Windows.cpp
index cbd0b2d6cb..7bcdc26712 100644
--- a/Gems/LyShine/Code/Source/Platform/Windows/UiClipboard_Windows.cpp
+++ b/Gems/LyShine/Code/Source/Platform/Windows/UiClipboard_Windows.cpp
@@ -9,7 +9,6 @@
 
 #include "UiClipboard.h"
 #include 
-#include 
 
 bool UiClipboard::SetText(const AZStd::string& text)
 {
@@ -20,8 +19,7 @@ bool UiClipboard::SetText(const AZStd::string& text)
         {
             if (text.length() > 0)
             {
-                AZStd::wstring wstr;
-                AZStd::to_wstring(wstr, text);
+                auto wstr = CryStringUtils::UTF8ToWStr(text.c_str());
                 const SIZE_T buffSize = (wstr.size() + 1) * sizeof(WCHAR);
                 if (HGLOBAL hBuffer = GlobalAlloc(GMEM_MOVEABLE, buffSize))
                 {
@@ -47,7 +45,7 @@ AZStd::string UiClipboard::GetText()
         if (HANDLE hText = GetClipboardData(CF_UNICODETEXT))
         {
             const WCHAR* text = static_cast(GlobalLock(hText));
-            AZStd::to_string(outText, AZStd::wstring(text));
+            outText = CryStringUtils::WStrToUTF8(text);
             GlobalUnlock(hText);
         }
         CloseClipboard();
diff --git a/Gems/LyShine/Code/Source/StringUtfUtils.h b/Gems/LyShine/Code/Source/StringUtfUtils.h
index e10e691a6f..74a27afe9f 100644
--- a/Gems/LyShine/Code/Source/StringUtfUtils.h
+++ b/Gems/LyShine/Code/Source/StringUtfUtils.h
@@ -36,8 +36,7 @@ namespace LyShine
         // In the long run it would be better to eliminate
         // this function and use Unicode::CIterator<>::Position instead.
         wchar_t wcharString[2] = { static_cast(multiByteChar), 0 };
-        AZStd::string utf8String;
-        AZStd::to_string(utf8String, AZStd::wstring(wcharString));
+        AZStd::string utf8String(CryStringUtils::WStrToUTF8(wcharString));
         int utf8Length = utf8String.length();
         return utf8Length;
     }
diff --git a/Gems/LyShine/Code/Source/UiButtonComponent.cpp b/Gems/LyShine/Code/Source/UiButtonComponent.cpp
index c6ba64848e..11bb088400 100644
--- a/Gems/LyShine/Code/Source/UiButtonComponent.cpp
+++ b/Gems/LyShine/Code/Source/UiButtonComponent.cpp
@@ -222,7 +222,7 @@ bool UiButtonComponent::VersionConverter(AZ::SerializeContext& context,
     // - Need to convert Color to Color and Alpha
     // conversion from version 2 to 3:
     // - Need to convert CryString ActionName elements to AZStd::string
-    AZ_Assert(classElement.GetVersion() < 3, "Unsupported UiButtonComponent version: %d", classElement.GetVersion());
+    AZ_Assert(classElement.GetVersion() >= 3, "Unsupported UiButtonComponent version: %d", classElement.GetVersion());
 
     // conversion from version 3 to 4:
     // - Need to convert AZStd::string sprites to AzFramework::SimpleAssetReference
diff --git a/Gems/LyShine/Code/Source/UiImageComponent.cpp b/Gems/LyShine/Code/Source/UiImageComponent.cpp
index 8f4145c07b..06996fbb48 100644
--- a/Gems/LyShine/Code/Source/UiImageComponent.cpp
+++ b/Gems/LyShine/Code/Source/UiImageComponent.cpp
@@ -2663,7 +2663,7 @@ bool UiImageComponent::VersionConverter(AZ::SerializeContext& context,
     // conversion from version 1:
     // - Need to convert CryString elements to AZStd::string
     // - Need to convert Color to Color and Alpha
-    AZ_Assert(classElement.GetVersion() <= 1, "Unsupported UiImageComponent version: %d", classElement.GetVersion());
+    AZ_Assert(classElement.GetVersion() > 1, "Unsupported UiImageComponent version: %d", classElement.GetVersion());
 
     // conversion from version 1 or 2 to current:
     // - Need to convert AZStd::string sprites to AzFramework::SimpleAssetReference
diff --git a/Gems/LyShine/Code/Source/UiTextComponent.cpp b/Gems/LyShine/Code/Source/UiTextComponent.cpp
index 76a789c5cf..fadf09571f 100644
--- a/Gems/LyShine/Code/Source/UiTextComponent.cpp
+++ b/Gems/LyShine/Code/Source/UiTextComponent.cpp
@@ -4996,7 +4996,7 @@ bool UiTextComponent::VersionConverter(AZ::SerializeContext& context,
 {
     // conversion from version 1: Need to convert Color to Color and Alpha
     // conversion from version 1 or 2: Need to convert Text from CryString to AzString
-    AZ_Assert(classElement.GetVersion() <= 2, "Unsupported UiTextComponent version: %d", classElement.GetVersion());
+    AZ_Assert(classElement.GetVersion() > 2, "Unsupported UiTextComponent version: %d", classElement.GetVersion());
 
     // Versions prior to v4: Change default font
     if (classElement.GetVersion() <= 3)
diff --git a/Gems/LyShine/Code/Source/UiTextInputComponent.cpp b/Gems/LyShine/Code/Source/UiTextInputComponent.cpp
index c746d14095..c149c5a4d4 100644
--- a/Gems/LyShine/Code/Source/UiTextInputComponent.cpp
+++ b/Gems/LyShine/Code/Source/UiTextInputComponent.cpp
@@ -1185,8 +1185,7 @@ void UiTextInputComponent::UpdateDisplayedTextFunction()
                 // NOTE: this assumes the uint32_t can be interpreted as a wchar_t, it seems to
                 // work for cases tested but may not in general.
                 wchar_t wcharString[2] = { static_cast(this->GetReplacementCharacter()), 0 };
-                AZStd::string replacementCharString;
-                AZStd::to_string(replacementCharString, AZStd::wstring(wcharString));
+                AZStd::string replacementCharString(CryStringUtils::WStrToUTF8(wcharString));
 
                 int numReplacementChars = LyShine::GetUtf8StringLength(originalText);
 
@@ -1478,7 +1477,7 @@ bool UiTextInputComponent::VersionConverter(AZ::SerializeContext& context,
     // - Need to convert Color to Color and Alpha
     // conversion from version 1 or 2 to current:
     // - Need to convert CryString ActionName elements to AZStd::string
-    AZ_Assert(classElement.GetVersion() <= 2, "Unsupported UiTextInputComponent version: %d", classElement.GetVersion());
+    AZ_Assert(classElement.GetVersion() > 2, "Unsupported UiTextInputComponent version: %d", classElement.GetVersion());
     
     // conversion from version 1, 2 or 3 to current:
     // - Need to convert AZStd::string sprites to AzFramework::SimpleAssetReference

From 902bdeb6d6092d0b88066fbb873eaa043c3b788a Mon Sep 17 00:00:00 2001
From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>
Date: Thu, 29 Jul 2021 16:50:50 -0700
Subject: [PATCH 044/803] Create RUN target as helpers for the project-centric
 workflow (#2520) (#2635)

* Create RUN target as helpers for the project-centric workflow

Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>

* typo fix

Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>

* rename target as ".Imported" and create "" as the metatarget that is used for debugging and building in o3de

Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>
---
 Code/Editor/CMakeLists.txt                 |  2 +
 cmake/Platform/Common/Install_common.cmake | 43 ++++++++++++++++++----
 cmake/SettingsRegistry.cmake               |  7 +---
 cmake/install/InstalledTarget.in           |  2 +
 4 files changed, 42 insertions(+), 12 deletions(-)

diff --git a/Code/Editor/CMakeLists.txt b/Code/Editor/CMakeLists.txt
index 5a846a267a..db6b8e958e 100644
--- a/Code/Editor/CMakeLists.txt
+++ b/Code/Editor/CMakeLists.txt
@@ -163,6 +163,8 @@ ly_add_target(
         editor_files.cmake
     PLATFORM_INCLUDE_FILES
         Platform/${PAL_PLATFORM_NAME}/editor_${PAL_PLATFORM_NAME_LOWERCASE}.cmake
+    TARGET_PROPERTIES
+        LY_INSTALL_GENERATE_RUN_TARGET TRUE
     BUILD_DEPENDENCIES
         PRIVATE
             3rdParty::Qt::Core
diff --git a/cmake/Platform/Common/Install_common.cmake b/cmake/Platform/Common/Install_common.cmake
index 1ac59ee83f..8058fb5908 100644
--- a/cmake/Platform/Common/Install_common.cmake
+++ b/cmake/Platform/Common/Install_common.cmake
@@ -9,6 +9,15 @@ include(cmake/FileUtil.cmake)
 
 set(CMAKE_INSTALL_MESSAGE NEVER) # Simplify messages to reduce output noise
 
+define_property(TARGET PROPERTY LY_INSTALL_GENERATE_RUN_TARGET
+    BRIEF_DOCS "Defines if a \"RUN\" targets should be created when installing this target Gem"
+    FULL_DOCS [[
+        Property which is set on targets that should generate a "RUN"
+        target when installed. This \"RUN\" target helps to run the 
+        binary from the installed location directly from the IDE.
+    ]]
+)
+
 ly_set(CMAKE_INSTALL_DEFAULT_COMPONENT_NAME Core)
 
 cmake_path(RELATIVE_PATH CMAKE_RUNTIME_OUTPUT_DIRECTORY BASE_DIRECTORY ${CMAKE_BINARY_DIR} OUTPUT_VARIABLE runtime_output_directory)
@@ -105,15 +114,19 @@ function(ly_setup_target OUTPUT_CONFIGURED_TARGET ALIAS_TARGET_NAME absolute_tar
         set(NAMESPACE_PLACEHOLDER "")
         set(NAME_PLACEHOLDER ${TARGET_NAME})
     endif()
+    get_target_property(should_create_helper ${TARGET_NAME} LY_INSTALL_GENERATE_RUN_TARGET)
+    if(should_create_helper)
+        set(NAME_PLACEHOLDER ${NAME_PLACEHOLDER}.Imported)
+    endif()
 
     set(TARGET_TYPE_PLACEHOLDER "")
-    get_target_property(target_type ${NAME_PLACEHOLDER} TYPE)
+    get_target_property(target_type ${TARGET_NAME} TYPE)
     # Remove the _LIBRARY since we dont need to pass that to ly_add_targets
     string(REPLACE "_LIBRARY" "" TARGET_TYPE_PLACEHOLDER ${target_type})
     # For HEADER_ONLY libs we end up generating "INTERFACE" libraries, need to specify HEADERONLY instead
     string(REPLACE "INTERFACE" "HEADERONLY" TARGET_TYPE_PLACEHOLDER ${TARGET_TYPE_PLACEHOLDER})
     if(TARGET_TYPE_PLACEHOLDER STREQUAL "MODULE")
-        get_target_property(gem_module ${NAME_PLACEHOLDER} GEM_MODULE)
+        get_target_property(gem_module ${TARGET_NAME} GEM_MODULE)
         if(gem_module)
             set(TARGET_TYPE_PLACEHOLDER "GEM_MODULE")
         endif()
@@ -146,7 +159,6 @@ function(ly_setup_target OUTPUT_CONFIGURED_TARGET ALIAS_TARGET_NAME absolute_tar
         unset(RUNTIME_DEPENDENCIES_PLACEHOLDER)
     endif()
 
-
     get_target_property(inteface_build_dependencies_props ${TARGET_NAME} INTERFACE_LINK_LIBRARIES)
     unset(INTERFACE_BUILD_DEPENDENCIES_PLACEHOLDER)
     if(inteface_build_dependencies_props)
@@ -170,6 +182,23 @@ function(ly_setup_target OUTPUT_CONFIGURED_TARGET ALIAS_TARGET_NAME absolute_tar
     list(REMOVE_DUPLICATES INTERFACE_BUILD_DEPENDENCIES_PLACEHOLDER)
     string(REPLACE ";" "\n" INTERFACE_BUILD_DEPENDENCIES_PLACEHOLDER "${INTERFACE_BUILD_DEPENDENCIES_PLACEHOLDER}")
 
+    # If the target is an executable/application, add a custom target so we can debug the target in project-centric workflow
+    if(should_create_helper)
+        string(REPLACE ".Imported" "" RUN_TARGET_NAME ${NAME_PLACEHOLDER})
+        set(target_types_with_debugging_helper EXECUTABLE APPLICATION)
+        if(NOT target_type IN_LIST target_types_with_debugging_helper)
+            message(FATAL_ERROR "Cannot generate a RUN target for ${TARGET_NAME}, type is ${target_type}")
+        endif()
+        set(TARGET_RUN_HELPER
+"add_custom_target(${RUN_TARGET_NAME})
+set_target_properties(${RUN_TARGET_NAME} PROPERTIES 
+    FOLDER \"CMakePredefinedTargets/SDK\"
+    VS_DEBUGGER_COMMAND \$>
+    VS_DEBUGGER_COMMAND_ARGUMENTS \"--project-path=\${LY_DEFAULT_PROJECT_PATH}\"
+)"
+)
+    endif()
+
     # Config file
     set(target_file_contents "# Generated by O3DE install\n\n")
     if(NOT target_type STREQUAL INTERFACE_LIBRARY)
@@ -182,13 +211,13 @@ function(ly_setup_target OUTPUT_CONFIGURED_TARGET ALIAS_TARGET_NAME absolute_tar
             set(target_location "\${LY_ROOT_FOLDER}/${library_output_directory}/${PAL_PLATFORM_NAME}/$/${target_library_output_subdirectory}/$")
         elseif(target_type STREQUAL SHARED_LIBRARY)
             string(APPEND target_file_contents 
-"set_property(TARGET ${TARGET_NAME} 
+"set_property(TARGET ${NAME_PLACEHOLDER} 
     APPEND_STRING PROPERTY IMPORTED_IMPLIB
         $<$$:\"\${LY_ROOT_FOLDER}/${archive_output_directory}/${PAL_PLATFORM_NAME}/$/$\"$
 )
 ")
             string(APPEND target_file_contents 
-"set_property(TARGET ${TARGET_NAME} 
+"set_property(TARGET ${NAME_PLACEHOLDER} 
     PROPERTY IMPORTED_IMPLIB_$> 
         \"\${LY_ROOT_FOLDER}/${archive_output_directory}/${PAL_PLATFORM_NAME}/$/$\"
 )
@@ -200,11 +229,11 @@ function(ly_setup_target OUTPUT_CONFIGURED_TARGET ALIAS_TARGET_NAME absolute_tar
 
         if(target_location)
             string(APPEND target_file_contents
-"set_property(TARGET ${TARGET_NAME}
+"set_property(TARGET ${NAME_PLACEHOLDER}
     APPEND_STRING PROPERTY IMPORTED_LOCATION
         $<$$:${target_location}$
 )
-set_property(TARGET ${TARGET_NAME}
+set_property(TARGET ${NAME_PLACEHOLDER}
     PROPERTY IMPORTED_LOCATION_$>
         ${target_location}
 )
diff --git a/cmake/SettingsRegistry.cmake b/cmake/SettingsRegistry.cmake
index 934bae4e30..a1e6de73f8 100644
--- a/cmake/SettingsRegistry.cmake
+++ b/cmake/SettingsRegistry.cmake
@@ -158,10 +158,6 @@ function(ly_delayed_generate_settings_registry)
                 message(FATAL_ERROR "Dependency ${gem_target} from ${target} does not exist")
             endif()
 
-            get_property(has_manually_added_dependencies TARGET ${gem_target} PROPERTY MANUALLY_ADDED_DEPENDENCIES SET)
-            get_target_property(target_type ${gem_target} TYPE)
-
-
             ly_get_gem_module_root(gem_module_root ${gem_target})
             file(RELATIVE_PATH gem_module_root_relative_to_engine_root ${LY_ROOT_FOLDER} ${gem_module_root})
 
@@ -179,7 +175,8 @@ function(ly_delayed_generate_settings_registry)
         list(JOIN target_gem_dependencies_names ",\n" target_gem_dependencies_names)
         string(CONFIGURE ${gems_json_template} gem_json @ONLY)
         get_target_property(is_imported ${target} IMPORTED)
-        if(is_imported)
+        get_target_property(target_type ${target} TYPE)
+        if(is_imported OR target_type STREQUAL UTILITY)
             unset(target_dir)
             foreach(conf IN LISTS CMAKE_CONFIGURATION_TYPES)
                 string(TOUPPER ${conf} UCONF)
diff --git a/cmake/install/InstalledTarget.in b/cmake/install/InstalledTarget.in
index 0503fd5f2b..a4f4fa4763 100644
--- a/cmake/install/InstalledTarget.in
+++ b/cmake/install/InstalledTarget.in
@@ -17,6 +17,8 @@ ly_add_target(
 @RUNTIME_DEPENDENCIES_PLACEHOLDER@
 )
 
+@TARGET_RUN_HELPER@
+
 set(configs @CMAKE_CONFIGURATION_TYPES@)
 foreach(config ${configs})
     include("@NAME_PLACEHOLDER@_${config}.cmake" OPTIONAL)

From 9041c8c9171cf67ef667656b407db9976da38864 Mon Sep 17 00:00:00 2001
From: nvsickle 
Date: Thu, 29 Jul 2021 16:58:11 -0700
Subject: [PATCH 045/803] Ensure network autonomy gets set before entity
 activation on non-dedicated servers

-Exposes an AutoActivate flag to INetworkEntityManager and ensured it got respected for all paths
-Tweak SpawnDefaultPlayerPrefab to not immediately activate its spawned entity to allow SetAllowAutonomy to be picked up from the net bind component during component activation

Signed-off-by: nvsickle 
---
 .../NetworkEntity/INetworkEntityManager.h          |  3 ++-
 .../Code/Source/MultiplayerSystemComponent.cpp     |  4 +++-
 .../Source/NetworkEntity/NetworkEntityManager.cpp  | 14 ++++++++++----
 .../Source/NetworkEntity/NetworkEntityManager.h    |  5 +++--
 4 files changed, 18 insertions(+), 8 deletions(-)

diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/NetworkEntity/INetworkEntityManager.h b/Gems/Multiplayer/Code/Include/Multiplayer/NetworkEntity/INetworkEntityManager.h
index 1c8894d6c2..c9bb799588 100644
--- a/Gems/Multiplayer/Code/Include/Multiplayer/NetworkEntity/INetworkEntityManager.h
+++ b/Gems/Multiplayer/Code/Include/Multiplayer/NetworkEntity/INetworkEntityManager.h
@@ -59,7 +59,8 @@ namespace Multiplayer
         (
             const PrefabEntityId& prefabEntryId,
             NetEntityRole netEntityRole,
-            const AZ::Transform& transform
+            const AZ::Transform& transform,
+            AutoActivate autoActivate = AutoActivate::Activate
         ) = 0;
 
         //! Creates new entities of the given archetype
diff --git a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp
index 21c7ce80d6..22abd3991b 100644
--- a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp
+++ b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp
@@ -643,6 +643,7 @@ namespace Multiplayer
             {
                 controlledEntity.GetNetBindComponent()->SetOwningConnectionId(connection->GetConnectionId());
             }
+            controlledEntity.Activate();
             
             if (connection->GetUserData() == nullptr) // Only add user data if the connect event handler has not already done so
             {
@@ -763,6 +764,7 @@ namespace Multiplayer
             {
                 controlledEntityNetBindComponent->SetAllowAutonomy(true);
             }
+            controlledEntity.Activate();
         }
         
         AZLOG_INFO("Multiplayer operating in %s mode", GetEnumString(m_agentType));
@@ -964,7 +966,7 @@ namespace Multiplayer
     NetworkEntityHandle MultiplayerSystemComponent::SpawnDefaultPlayerPrefab()
     {
         PrefabEntityId playerPrefabEntityId(AZ::Name(static_cast(sv_defaultPlayerSpawnAsset).c_str()));
-        INetworkEntityManager::EntityList entityList = m_networkEntityManager.CreateEntitiesImmediate(playerPrefabEntityId, NetEntityRole::Authority, AZ::Transform::CreateIdentity());
+        INetworkEntityManager::EntityList entityList = m_networkEntityManager.CreateEntitiesImmediate(playerPrefabEntityId, NetEntityRole::Authority, AZ::Transform::CreateIdentity(), Multiplayer::AutoActivate::DoNotActivate);
 
         NetworkEntityHandle controlledEntity;
         if (entityList.size() > 0)
diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp
index 1460d015fa..6446451369 100644
--- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp
+++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp
@@ -304,7 +304,7 @@ namespace Multiplayer
     }
     
     INetworkEntityManager::EntityList NetworkEntityManager::CreateEntitiesImmediate(
-        const AzFramework::Spawnable& spawnable, NetEntityRole netEntityRole)
+        const AzFramework::Spawnable& spawnable, NetEntityRole netEntityRole, AutoActivate autoActivate)
     {
         INetworkEntityManager::EntityList returnList;
 
@@ -354,6 +354,11 @@ namespace Multiplayer
                 const NetEntityId netEntityId = NextId();
                 netBindComponent->PreInit(clone, prefabEntityId, netEntityId, netEntityRole);
 
+                if (autoActivate == AutoActivate::DoNotActivate)
+                {
+                    clone->SetRuntimeActiveByDefault(false);
+                }
+
                 AzFramework::GameEntityContextRequestBus::Broadcast(
                     &AzFramework::GameEntityContextRequestBus::Events::AddGameEntity, clone);
 
@@ -373,10 +378,11 @@ namespace Multiplayer
     (
         const PrefabEntityId& prefabEntryId,
         NetEntityRole netEntityRole,
-        const AZ::Transform& transform
+        const AZ::Transform& transform,
+        AutoActivate autoActivate
     )
     {
-        return CreateEntitiesImmediate(prefabEntryId, NextId(), netEntityRole, AutoActivate::Activate, transform);
+        return CreateEntitiesImmediate(prefabEntryId, NextId(), netEntityRole, autoActivate, transform);
     }
 
     INetworkEntityManager::EntityList NetworkEntityManager::CreateEntitiesImmediate
@@ -409,7 +415,7 @@ namespace Multiplayer
 
         if (entityIndex == PrefabEntityId::AllIndices)
         {
-            return CreateEntitiesImmediate(*netSpawnable, netEntityRole);
+            return CreateEntitiesImmediate(*netSpawnable, netEntityRole, autoActivate);
         }
 
         const AzFramework::Spawnable::EntityList& entities = netSpawnable->GetEntities();
diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.h b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.h
index fdd0201b7a..adbf7df8da 100644
--- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.h
+++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.h
@@ -42,12 +42,13 @@ namespace Multiplayer
         HostId GetHostId() const override;
         ConstNetworkEntityHandle GetEntity(NetEntityId netEntityId) const override;
 
-        EntityList CreateEntitiesImmediate(const AzFramework::Spawnable& spawnable, NetEntityRole netEntityRole);
+        EntityList CreateEntitiesImmediate(const AzFramework::Spawnable& spawnable, NetEntityRole netEntityRole, AutoActivate autoActivate);
         EntityList CreateEntitiesImmediate
         (
             const PrefabEntityId& prefabEntryId,
             NetEntityRole netEntityRole,
-            const AZ::Transform& transform
+            const AZ::Transform& transform,
+            AutoActivate autoActivate = AutoActivate::Activate
         ) override;
         EntityList CreateEntitiesImmediate
         (

From 015424eb35cdb7b25abd07cdb4ee8ef77b47306e Mon Sep 17 00:00:00 2001
From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>
Date: Fri, 30 Jul 2021 11:51:21 -0700
Subject: [PATCH 046/803] Conversion to unicode, everything except
 StreamerConfiguration

Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>
---
 Code/Framework/AzCore/AzCore/Debug/Trace.cpp  |  1 -
 Code/Framework/AzCore/AzCore/Debug/Trace.h    |  5 ++
 .../AzCore/AzCore/std/string/conversions.h    | 82 +++++++++++++++++++
 .../Common/Apple/AzCore/Debug/Trace_Apple.cpp |  1 +
 .../WinAPI/AzCore/Debug/Trace_WinAPI.cpp      | 19 +++--
 .../Linux/AzCore/Debug/Trace_Linux.cpp        |  4 +-
 .../Mac/AzCore/IPC/SharedMemory_Mac.cpp       |  2 +-
 .../Mac/AzCore/IPC/SharedMemory_Mac.h         |  1 -
 .../StreamerConfiguration_Windows.cpp         |  4 +-
 .../AzCore/IPC/SharedMemory_Windows.cpp       | 32 ++++----
 .../Windows/AzCore/IPC/SharedMemory_Windows.h |  3 -
 11 files changed, 121 insertions(+), 33 deletions(-)

diff --git a/Code/Framework/AzCore/AzCore/Debug/Trace.cpp b/Code/Framework/AzCore/AzCore/Debug/Trace.cpp
index 6d491c97b8..bd3b12a3b8 100644
--- a/Code/Framework/AzCore/AzCore/Debug/Trace.cpp
+++ b/Code/Framework/AzCore/AzCore/Debug/Trace.cpp
@@ -38,7 +38,6 @@ namespace AZ
             void DebugBreak();
 #endif
             void Terminate(int exitCode);
-            void OutputToDebugger(const char* window, const char* message);
         }
     }
 
diff --git a/Code/Framework/AzCore/AzCore/Debug/Trace.h b/Code/Framework/AzCore/AzCore/Debug/Trace.h
index a680cbdfed..bae074281c 100644
--- a/Code/Framework/AzCore/AzCore/Debug/Trace.h
+++ b/Code/Framework/AzCore/AzCore/Debug/Trace.h
@@ -15,6 +15,11 @@ namespace AZ
 {
     namespace Debug
     {
+        namespace Platform
+        {
+            void OutputToDebugger(const char* window, const char* message);
+        }
+    
         /// Global instance to the tracer.
         extern class Trace      g_tracer;
 
diff --git a/Code/Framework/AzCore/AzCore/std/string/conversions.h b/Code/Framework/AzCore/AzCore/std/string/conversions.h
index 3e5a393cf8..4dc5bbd547 100644
--- a/Code/Framework/AzCore/AzCore/std/string/conversions.h
+++ b/Code/Framework/AzCore/AzCore/std/string/conversions.h
@@ -49,6 +49,25 @@ namespace AZStd
                 }
             }
 
+            template
+            static inline void to_string(AZStd::basic_fixed_string& dest, const wchar_t* first, const wchar_t* last)
+            {
+                if constexpr (Size == 2)
+                {
+                    Utf8::Unchecked::utf16to8(first, last, AZStd::back_inserter(dest));
+                }
+                else if constexpr (Size == 4)
+                {
+                    Utf8::Unchecked::utf32to8(first, last, AZStd::back_inserter(dest));
+                }
+                else
+                {
+                    // Workaround to defer static_assert evaluation until this function is invoked by using the template parameter
+                    using StringType = AZStd::basic_string;
+                    static_assert(!AZStd::is_same_v, "only wchar_t types of size 2 or 4 can be converted to utf8");
+                }
+            }
+
             template
             static inline void to_wstring(AZStd::basic_string& dest, const char* first, const char* last)
             {
@@ -67,6 +86,25 @@ namespace AZStd
                     static_assert(!AZStd::is_same_v, "Cannot convert a utf8 string to a wchar_t that isn't size 2 or 4");
                 }
             }
+
+            template
+            static inline void to_wstring(AZStd::basic_fixed_string& dest, const char* first, const char* last)
+            {
+                if constexpr (Size == 2)
+                {
+                    Utf8::Unchecked::utf8to16(first, last, AZStd::back_inserter(dest));
+                }
+                else if constexpr (Size == 4)
+                {
+                    Utf8::Unchecked::utf8to32(first, last, AZStd::back_inserter(dest));
+                }
+                else
+                {
+                    // Workaround to defer static_assert evaluation until this function is invoked by using the template parameter
+                    using StringType = AZStd::basic_string;
+                    static_assert(!AZStd::is_same_v, "Cannot convert a utf8 string to a wchar_t that isn't size 2 or 4");
+                }
+            }
         };
     }
     // 21.5: numeric conversions
@@ -266,6 +304,28 @@ namespace AZStd
         return to_string(dest, src.c_str(), src.length());
     }
 
+    template
+    void to_string(AZStd::basic_fixed_string& dest, const wchar_t* str, size_t srcLen = 0)
+    {
+        dest.clear();
+
+        if (srcLen == 0)
+        {
+            srcLen = wcslen(str);
+        }
+
+        if (srcLen > 0)
+        {
+            Internal::WCharTPlatformConverter<>::to_string(dest, str, str + srcLen);
+        }
+    }
+
+    template
+    void to_string(AZStd::basic_fixed_string& dest, const AZStd::basic_fixed_string& src)
+    {
+        return to_string(dest, src.c_str(), src.length());
+    }
+
     template
     int stoi(const AZStd::basic_string& str, AZStd::size_t* idx = 0, int base = 10)
     {
@@ -384,6 +444,28 @@ namespace AZStd
         return to_wstring(dest, src.c_str(), src.length());
     }
 
+    template
+    void to_wstring(AZStd::basic_fixed_string& dest, const char* str, size_t strLen = 0)
+    {
+        dest.clear();
+
+        if (strLen == 0)
+        {
+            strLen = strlen(str);
+        }
+
+        if (strLen > 0)
+        {
+            Internal::WCharTPlatformConverter<>::to_wstring(dest, str, str + strLen);
+        }
+    }
+
+    template
+    void to_wstring(AZStd::basic_fixed_string& dest, const AZStd::basic_fixed_string& src)
+    {
+        return to_wstring(dest, src.c_str(), src.length());
+    }
+
     // Convert a range of chars to lower case
 #if defined(AZSTD_USE_OLD_RW_STL)
     template
diff --git a/Code/Framework/AzCore/Platform/Common/Apple/AzCore/Debug/Trace_Apple.cpp b/Code/Framework/AzCore/Platform/Common/Apple/AzCore/Debug/Trace_Apple.cpp
index 62fe849c36..4ae25bfaf9 100644
--- a/Code/Framework/AzCore/Platform/Common/Apple/AzCore/Debug/Trace_Apple.cpp
+++ b/Code/Framework/AzCore/Platform/Common/Apple/AzCore/Debug/Trace_Apple.cpp
@@ -72,6 +72,7 @@ namespace AZ
 
             void OutputToDebugger(const char*, const char*)
             {
+                // std::cout << title << ": " << message;
             }
         }
     }
diff --git a/Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/Debug/Trace_WinAPI.cpp b/Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/Debug/Trace_WinAPI.cpp
index 143bd8f9d0..99ea10e4bc 100644
--- a/Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/Debug/Trace_WinAPI.cpp
+++ b/Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/Debug/Trace_WinAPI.cpp
@@ -12,6 +12,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 
 #include 
 
@@ -22,7 +24,7 @@ namespace AZ
     LPTOP_LEVEL_EXCEPTION_FILTER g_previousExceptionHandler = nullptr;
 #endif
 
-    const int g_maxMessageLength = 4096;
+    constexpr int g_maxMessageLength = 4096;
 
     namespace Debug
     {
@@ -58,15 +60,18 @@ namespace AZ
                 TerminateProcess(GetCurrentProcess(), exitCode);
             }
 
-            void OutputToDebugger(const char* window, const char* message)
+            void OutputToDebugger([[maybe_unused]] const char* window, const char* message)
             {
-                AZ_UNUSED(window);
-                wchar_t messageW[g_maxMessageLength];
-                size_t numCharsConverted;
-                if (mbstowcs_s(&numCharsConverted, messageW, message, g_maxMessageLength - 1) == 0)
+                AZStd::fixed_wstring tmpW;
+                if(window)
                 {
-                    OutputDebugStringW(messageW);
+                    AZStd::to_wstring(tmpW, window);
+                    tmpW += L": ";
+                    OutputDebugStringW(tmpW.c_str());
+                    tmpW.clear();
                 }
+                AZStd::to_wstring(tmpW, message);
+                OutputDebugStringW(tmpW.c_str());
             }
         }
     }
diff --git a/Code/Framework/AzCore/Platform/Linux/AzCore/Debug/Trace_Linux.cpp b/Code/Framework/AzCore/Platform/Linux/AzCore/Debug/Trace_Linux.cpp
index 3f9e475153..86c7e14ae6 100644
--- a/Code/Framework/AzCore/Platform/Linux/AzCore/Debug/Trace_Linux.cpp
+++ b/Code/Framework/AzCore/Platform/Linux/AzCore/Debug/Trace_Linux.cpp
@@ -7,6 +7,7 @@
  */
 
 #include 
+#include 
 
 namespace AZ
 {
@@ -14,8 +15,9 @@ namespace AZ
     {
         namespace Platform
         {
-            void OutputToDebugger(const char*, const char*)
+            void OutputToDebugger(const char* title, const char* message)
             {
+                // std::cout << title << ": " << message;
             }
         }
     }
diff --git a/Code/Framework/AzCore/Platform/Mac/AzCore/IPC/SharedMemory_Mac.cpp b/Code/Framework/AzCore/Platform/Mac/AzCore/IPC/SharedMemory_Mac.cpp
index 7f13ec442a..5555704040 100644
--- a/Code/Framework/AzCore/Platform/Mac/AzCore/IPC/SharedMemory_Mac.cpp
+++ b/Code/Framework/AzCore/Platform/Mac/AzCore/IPC/SharedMemory_Mac.cpp
@@ -29,7 +29,7 @@ namespace AZ
         return errno;
     }
 
-    void SharedMemory_Mac::ComposeMutexName(char* dest, size_t length, const char* name)
+    void ComposeMutexName(char* dest, size_t length, const char* name)
     {
         azstrncpy(m_name, AZ_ARRAY_SIZE(m_name), name, strlen(name));
 
diff --git a/Code/Framework/AzCore/Platform/Mac/AzCore/IPC/SharedMemory_Mac.h b/Code/Framework/AzCore/Platform/Mac/AzCore/IPC/SharedMemory_Mac.h
index 8e172d920f..c0d5d7c2e9 100644
--- a/Code/Framework/AzCore/Platform/Mac/AzCore/IPC/SharedMemory_Mac.h
+++ b/Code/Framework/AzCore/Platform/Mac/AzCore/IPC/SharedMemory_Mac.h
@@ -29,7 +29,6 @@ namespace AZ
 
         static int GetLastError();
 
-        void ComposeMutexName(char* dest, size_t length, const char* name);
         CreateResult Create(const char* name, unsigned int size, bool openIfCreated);
         bool Open(const char* name);
         void Close();
diff --git a/Code/Framework/AzCore/Platform/Windows/AzCore/IO/Streamer/StreamerConfiguration_Windows.cpp b/Code/Framework/AzCore/Platform/Windows/AzCore/IO/Streamer/StreamerConfiguration_Windows.cpp
index 35835c374c..0813d2d057 100644
--- a/Code/Framework/AzCore/Platform/Windows/AzCore/IO/Streamer/StreamerConfiguration_Windows.cpp
+++ b/Code/Framework/AzCore/Platform/Windows/AzCore/IO/Streamer/StreamerConfiguration_Windows.cpp
@@ -290,7 +290,7 @@ namespace AZ::IO
     static bool CollectHardwareInfo(HardwareInformation& hardwareInfo, bool addAllDrives, bool reportHardware)
     {
         char drives[512];
-        if (::GetLogicalDriveStrings(sizeof(drives) - 1, drives))
+        if (::GetLogicalDriveStringsA(sizeof(drives) - 1, drives))
         {
             AZStd::unordered_map driveMappings;
             char* driveIt = drives;
@@ -318,7 +318,7 @@ namespace AZ::IO
                     deviceName += driveIt;
                     deviceName.erase(deviceName.length() - 1); // Erase the slash.
 
-                    HANDLE deviceHandle = ::CreateFile(
+                    HANDLE deviceHandle = ::CreateFileA(
                         deviceName.c_str(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr);
                     if (deviceHandle != INVALID_HANDLE_VALUE)
                     {
diff --git a/Code/Framework/AzCore/Platform/Windows/AzCore/IPC/SharedMemory_Windows.cpp b/Code/Framework/AzCore/Platform/Windows/AzCore/IPC/SharedMemory_Windows.cpp
index 21b2a76ba0..20c126f7a8 100644
--- a/Code/Framework/AzCore/Platform/Windows/AzCore/IPC/SharedMemory_Windows.cpp
+++ b/Code/Framework/AzCore/Platform/Windows/AzCore/IPC/SharedMemory_Windows.cpp
@@ -11,6 +11,7 @@
 #include 
 #include 
 #include 
+#include 
 
 namespace AZ
 {
@@ -21,16 +22,17 @@ namespace AZ
     {
     }
 
-    void SharedMemory_Windows::ComposeMutexName(char* dest, size_t length, const char* name)
+    void ComposeName(AZStd::fixed_wstring<256>& dest, const char* name, const wchar_t* suffix)
     {
-        azstrncpy(m_name, AZ_ARRAY_SIZE(m_name), name, strlen(name));
-        azsnprintf(dest, length, "%s_Mutex", name);
+        AZStd::to_wstring(dest, name);
+        dest += L"_";
+        dest += suffix;
     }
 
     SharedMemory_Common::CreateResult SharedMemory_Windows::Create(const char* name, unsigned int size, bool openIfCreated)
     {
-        char fullName[256];
-        ComposeMutexName(fullName, AZ_ARRAY_SIZE(fullName), name);
+        AZStd::fixed_wstring<256> fullName;
+        ComposeName(fullName, name, L"Mutex");
 
         // Security attributes
         SECURITY_ATTRIBUTES secAttr;
@@ -42,9 +44,7 @@ namespace AZ
         SetSecurityDescriptorDacl(secAttr.lpSecurityDescriptor, TRUE, 0, FALSE);
 
         // Obtain global mutex
-        AZStd::wstring fullNameW;
-        AZStd::to_wstring(fullNameW, fullName);
-        m_globalMutex = CreateMutexW(&secAttr, FALSE, fullNameW.c_str());
+        m_globalMutex = CreateMutexW(&secAttr, FALSE, fullName.c_str());
         DWORD error = GetLastError();
         if (m_globalMutex == NULL || (error == ERROR_ALREADY_EXISTS && openIfCreated == false))
         {
@@ -53,8 +53,8 @@ namespace AZ
         }
 
         // Create the file mapping.
-        azsnprintf(fullName, AZ_ARRAY_SIZE(fullName), "%s_Data", name);
-        m_mapHandle = CreateFileMappingW(INVALID_HANDLE_VALUE, &secAttr, PAGE_READWRITE, 0, size, fullNameW.c_str());
+        ComposeName(fullName, name, L"Data");
+        m_mapHandle = CreateFileMappingW(INVALID_HANDLE_VALUE, &secAttr, PAGE_READWRITE, 0, size, fullName.c_str());
         error = GetLastError();
         if (m_mapHandle == NULL || (error == ERROR_ALREADY_EXISTS && openIfCreated == false))
         {
@@ -67,12 +67,10 @@ namespace AZ
 
     bool SharedMemory_Windows::Open(const char* name)
     {
-        char fullName[256];
-        ComposeMutexName(fullName, AZ_ARRAY_SIZE(fullName), name);
-        AZStd::wstring fullNameW;
-        AZStd::to_wstring(fullNameW, fullName);
+        AZStd::fixed_wstring<256> fullName;
+        ComposeName(fullName, name, L"Mutex");
 
-        m_globalMutex = OpenMutex(SYNCHRONIZE, TRUE, fullNameW.c_str());
+        m_globalMutex = OpenMutex(SYNCHRONIZE, TRUE, fullName.c_str());
         AZ_Warning("AZSystem", m_globalMutex != NULL, "Failed to open OS mutex [%s]\n", m_name);
         if (m_globalMutex == NULL)
         {
@@ -80,8 +78,8 @@ namespace AZ
             return false;
         }
 
-        azsnprintf(fullName, AZ_ARRAY_SIZE(fullName), "%s_Data", name);
-        m_mapHandle = OpenFileMapping(FILE_MAP_WRITE, false, fullNameW.c_str());
+        ComposeName(fullName, name, L"Data");
+        m_mapHandle = OpenFileMapping(FILE_MAP_WRITE, false, fullName.c_str());
         if (m_mapHandle == NULL)
         {
             AZ_TracePrintf("AZSystem", "OpenFileMapping %s failed with error %d\n", m_name, GetLastError());
diff --git a/Code/Framework/AzCore/Platform/Windows/AzCore/IPC/SharedMemory_Windows.h b/Code/Framework/AzCore/Platform/Windows/AzCore/IPC/SharedMemory_Windows.h
index 7f206f5413..7b10b9163e 100644
--- a/Code/Framework/AzCore/Platform/Windows/AzCore/IPC/SharedMemory_Windows.h
+++ b/Code/Framework/AzCore/Platform/Windows/AzCore/IPC/SharedMemory_Windows.h
@@ -41,9 +41,6 @@ namespace AZ
         HANDLE m_mapHandle;
         HANDLE m_globalMutex;
         int m_lastLockResult;
-
-    private:
-        void ComposeMutexName(char* dest, size_t length, const char* name);
     };
 
     using SharedMemory_Platform = SharedMemory_Windows;

From 0ea11294abfcd69123143e7c48eef1fd23ba1ebe Mon Sep 17 00:00:00 2001
From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>
Date: Fri, 30 Jul 2021 12:29:06 -0700
Subject: [PATCH 047/803] fixes for crcfix

Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>
---
 Code/Framework/Crcfix/crcfix.cpp | 87 +++++++++++++++++---------------
 1 file changed, 45 insertions(+), 42 deletions(-)

diff --git a/Code/Framework/Crcfix/crcfix.cpp b/Code/Framework/Crcfix/crcfix.cpp
index ce599e9a63..778b9e2185 100644
--- a/Code/Framework/Crcfix/crcfix.cpp
+++ b/Code/Framework/Crcfix/crcfix.cpp
@@ -12,6 +12,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -23,11 +24,11 @@ int g_longestFixTimeMs = 0;
 
 class Filename
 {
-    char    fullpath[MAX_PATH];
-    char    drive[_MAX_DRIVE];
-    char    dir[_MAX_DIR];
-    char    fname[_MAX_FNAME];
-    char    ext[_MAX_EXT];
+    wchar_t    fullpath[MAX_PATH];
+    wchar_t    drive[_MAX_DRIVE];
+    wchar_t    dir[_MAX_DIR];
+    wchar_t    fname[_MAX_FNAME];
+    wchar_t    ext[_MAX_EXT];
 
 public:
     Filename()
@@ -35,21 +36,21 @@ public:
         fullpath[0] = drive[0] = dir[0] = fname[0] = ext[0] = 0;
     }
 
-    Filename(const AZStd::string& filename)
+    Filename(const AZStd::wstring& filename)
     {
-        _splitpath(filename.c_str(), drive, dir, fname, ext);
-        strcpy(fullpath, filename.c_str());
+        _wsplitpath(filename.c_str(), drive, dir, fname, ext);
+        wcscpy(fullpath, filename.c_str());
     }
 
-    void        SetExt(const char* pExt)        { strcpy(ext, pExt); _makepath(fullpath, drive, dir, fname, pExt); }
-    const char* GetFullPath() const             { return fullpath; }
-    bool        Exists() const                  { return _access(fullpath, 0) == 0; }
-    bool        IsReadOnly() const              { return _access(fullpath, 6) == -1; }
-    bool        SetReadOnly() const             { return _chmod(fullpath, _S_IREAD) == 0; }
-    bool        SetWritable() const             { return _chmod(fullpath, _S_IREAD | _S_IWRITE) == 0; }
-    bool        Delete() const                  { return remove(fullpath) == 0; }
-    bool        Rename(const char* fn2) const   { return MoveFileEx(fullpath, fn2, MOVEFILE_COPY_ALLOWED|MOVEFILE_REPLACE_EXISTING) == 0; }
-    bool        Copy(const char* dest) const    { return ::CopyFileA(fullpath, dest, FALSE) == TRUE; }
+    void        SetExt(const wchar_t* pExt)     { wcscpy(ext, pExt); _wmakepath(fullpath, drive, dir, fname, pExt); }
+    const wchar_t* GetFullPath() const          { return fullpath; }
+    bool        Exists() const                  { return _waccess(fullpath, 0) == 0; }
+    bool        IsReadOnly() const              { return _waccess(fullpath, 6) == -1; }
+    bool        SetReadOnly() const             { return _wchmod(fullpath, _S_IREAD) == 0; }
+    bool        SetWritable() const             { return _wchmod(fullpath, _S_IREAD | _S_IWRITE) == 0; }
+    bool        Delete() const                  { return _wremove(fullpath) == 0; }
+    bool        Rename(const wchar_t* fn2) const{ return MoveFileEx(fullpath, fn2, MOVEFILE_COPY_ALLOWED|MOVEFILE_REPLACE_EXISTING) == 0; }
+    bool        Copy(const wchar_t* dest) const { return ::CopyFile(fullpath, dest, FALSE) == TRUE; }
 };
 
 class CRCfix
@@ -64,7 +65,7 @@ public:
     int     Fix(Filename srce);
 };
 
-void FixFiles(const AZStd::string& dir, const AZStd::string& files, FILETIME* pLastRun, bool verbose, int& nFound, int& nProcessed, int& nFixed, int& nFailed)
+void FixFiles(const AZStd::wstring& dir, const AZStd::wstring& files, FILETIME* pLastRun, bool verbose, int& nFound, int& nProcessed, int& nFixed, int& nFailed)
 {
     CRCfix fixer;
     WIN32_FIND_DATA wfd;
@@ -78,14 +79,14 @@ void FixFiles(const AZStd::string& dir, const AZStd::string& files, FILETIME* pL
             {
                 if (verbose)
                 {
-                    AZ_TracePrintf("CrcFix", "\tProcessing %s ...", wfd.cFileName);
+                    AZ_TracePrintf("CrcFix", "\tProcessing %ls ...", wfd.cFileName);
                 }
                 nFound++;
 
                 int n = 0;
                 if ((wfd.dwFileAttributes & FILE_ATTRIBUTE_READONLY) == 0 && (!pLastRun || CompareFileTime(pLastRun, &wfd.ftLastWriteTime) <= 0))
                 {
-                    n = fixer.Fix(Filename(dir + "\\" + wfd.cFileName));
+                    n = fixer.Fix(Filename(dir + L"\\" + wfd.cFileName));
                     nProcessed++;
                 }
                 if (n < 0)
@@ -110,11 +111,11 @@ void FixFiles(const AZStd::string& dir, const AZStd::string& files, FILETIME* pL
     FindClose(hFind);
 }
 
-void FixDirectories(const AZStd::string& dirs, const AZStd::string& files, FILETIME* pLastRun, bool verbose, int& nFound, int& nProcessed, int& nFixed, int& nFailed)
+void FixDirectories(const AZStd::wstring& dirs, const AZStd::wstring& files, FILETIME* pLastRun, bool verbose, int& nFound, int& nProcessed, int& nFixed, int& nFailed)
 {
     if (verbose)
     {
-        AZ_TracePrintf("CrcFix", "Processing %s ...\n", dirs.c_str());
+        AZ_TracePrintf("CrcFix", "Processing %ls ...\n", dirs.c_str());
     }
 
     // do files
@@ -123,7 +124,7 @@ void FixDirectories(const AZStd::string& dirs, const AZStd::string& files, FILET
     // do folders
     WIN32_FIND_DATA wfd;
     HANDLE hFind;
-    hFind = FindFirstFile((dirs + "\\*").c_str(), &wfd);
+    hFind = FindFirstFile((dirs + L"\\*").c_str(), &wfd);
     if (hFind != INVALID_HANDLE_VALUE)
     {
         do
@@ -134,7 +135,7 @@ void FixDirectories(const AZStd::string& dirs, const AZStd::string& files, FILET
                 {
                     continue;
                 }
-                FixDirectories(AZStd::string(dirs + "\\" + wfd.cFileName), files, pLastRun, verbose, nFound, nProcessed, nFixed, nFailed);
+                FixDirectories(AZStd::wstring(dirs + L"\\" + wfd.cFileName), files, pLastRun, verbose, nFound, nProcessed, nFixed, nFailed);
             }
         } while (FindNextFile(hFind, &wfd));
     }
@@ -161,9 +162,9 @@ int main(int argc, char* argv[])
         char root[MAX_PATH];
         AZ::Utils::GetExecutableDirectory(root, MAX_PATH);
 
-        AZStd::vector entries;
+        AZStd::vector entries;
 
-        const char* logfilename = NULL;
+        AZStd::wstring logfilename;
         FILETIME    lastRun;
         FILETIME* pLastRun = NULL;
 
@@ -176,10 +177,12 @@ int main(int argc, char* argv[])
             {
                 continue;
             }
+            AZStd::wstring pArgW;
+            AZStd::to_wstring(pArgW, pArg);
             if (_strnicmp(pArg, "-log:", 5) == 0)
             {
-                logfilename = pArg + 5;
-                HANDLE hFile = CreateFile(logfilename, 0, 0, NULL, OPEN_EXISTING, 0, NULL);
+                logfilename.assign(pArgW.begin() + 5, pArgW.end());
+                HANDLE hFile = CreateFile(logfilename.data(), 0, 0, NULL, OPEN_EXISTING, 0, NULL);
                 if (hFile != INVALID_HANDLE_VALUE)
                 {
                     pLastRun = &lastRun;
@@ -193,7 +196,7 @@ int main(int argc, char* argv[])
             }
             else
             {
-                entries.push_back(AZStd::string(pArg));
+                entries.emplace_back(AZStd::move(pArgW));
             }
         }
 
@@ -202,10 +205,10 @@ int main(int argc, char* argv[])
         int nProcessed = 0;
         int nFixed = 0;
         int nFailed = 0;
-        for (AZStd::vector::const_iterator iEntry = entries.begin(); iEntry != entries.end(); ++iEntry)
+        for (AZStd::vector::const_iterator iEntry = entries.begin(); iEntry != entries.end(); ++iEntry)
         {
-            AZStd::string entry = (iEntry->at(0) == '\\' || iEntry->find(":") != iEntry->npos) ? *iEntry : AZStd::string(root) + "\\" + *iEntry;
-            AZStd::string::size_type split = entry.find("*\\");
+            AZStd::wstring entry = (iEntry->at(0) == L'\\' || iEntry->find(L":") != iEntry->npos) ? *iEntry : AZStd::wstring(root) + L"\\" + *iEntry;
+            AZStd::wstring::size_type split = entry.find(L"*\\");
             bool doSubdirs = split != entry.npos;
             if (doSubdirs)
             {
@@ -213,7 +216,7 @@ int main(int argc, char* argv[])
             }
             else
             {
-                split = entry.rfind("\\");
+                split = entry.rfind(L"\\");
                 if (split == entry.npos)
                 {
                     split = 0;
@@ -223,9 +226,9 @@ int main(int argc, char* argv[])
         }
 
         // update timestamp
-        if (logfilename)
+        if (!logfilename.empty())
         {
-            HANDLE      hFile = CreateFile(logfilename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
+            HANDLE      hFile = CreateFile(logfilename.data(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
             GetSystemTimeAsFileTime(&lastRun);
             SetFileTime(hFile, NULL, NULL, &lastRun);
             char log[1024];
@@ -383,12 +386,12 @@ int CRCfix::Fix(Filename srce)
 
     bool        changed = false;
     Filename    dest(srce);
-    dest.SetExt("xxx");
+    dest.SetExt(L"xxx");
 
     linenum = 0;
 
-    FILE* infile = fopen(srce.GetFullPath(), "r");
-    FILE* outfile = fopen(dest.GetFullPath(), "w");
+    FILE* infile = _wfopen(srce.GetFullPath(), L"r");
+    FILE* outfile = _wfopen(dest.GetFullPath(), L"w");
 
     if (!infile || !outfile)
     {
@@ -475,7 +478,7 @@ int CRCfix::Fix(Filename srce)
     if (changed)
     {
         Filename    backup(srce);
-        backup.SetExt("crcfix_old");
+        backup.SetExt(L"crcfix_old");
 
         if (backup.Exists())
         {
@@ -486,7 +489,7 @@ int CRCfix::Fix(Filename srce)
 
         if (!srce.Copy(backup.GetFullPath()))
         {
-            AZ_TracePrintf("CrcFix", "Failed to copy %s to %s\n", srce, backup);
+            AZ_TracePrintf("CrcFix", "Failed to copy %ls to %ls\n", srce, backup);
 
             int dt = static_cast(AZStd::chrono::milliseconds(AZStd::chrono::system_clock::now() - startTime).count());
             g_totalFixTimeMs += dt;
@@ -500,7 +503,7 @@ int CRCfix::Fix(Filename srce)
 
         if (!dest.Rename(srce.GetFullPath()))
         {
-            AZ_TracePrintf("CrcFix", "Failed to rename %s to %s\n", dest, srce);
+            AZ_TracePrintf("CrcFix", "Failed to rename %ls to %ls\n", dest, srce);
 
             int dt = static_cast(AZStd::chrono::milliseconds(AZStd::chrono::system_clock::now() - startTime).count());
             g_totalFixTimeMs += dt;
@@ -514,7 +517,7 @@ int CRCfix::Fix(Filename srce)
 
         if (!backup.Delete())
         {
-            AZ_TracePrintf("CrcFix", "Failed to delete %s\n", backup);
+            AZ_TracePrintf("CrcFix", "Failed to delete %ls\n", backup);
         }
     }
     else

From 203532b91d508861738455636450812cb4299f14 Mon Sep 17 00:00:00 2001
From: chcurran <82187351+carlitosan@users.noreply.github.com>
Date: Fri, 30 Jul 2021 13:25:33 -0700
Subject: [PATCH 048/803] prove that SC tests are running

Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com>
---
 .../Code/Tests/ScriptCanvas_RuntimeInterpreted.cpp           | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/Gems/ScriptCanvasTesting/Code/Tests/ScriptCanvas_RuntimeInterpreted.cpp b/Gems/ScriptCanvasTesting/Code/Tests/ScriptCanvas_RuntimeInterpreted.cpp
index c2fa59b037..df29a56fd5 100644
--- a/Gems/ScriptCanvasTesting/Code/Tests/ScriptCanvas_RuntimeInterpreted.cpp
+++ b/Gems/ScriptCanvasTesting/Code/Tests/ScriptCanvas_RuntimeInterpreted.cpp
@@ -84,6 +84,11 @@ public:
     }
 };
 
+TEST_F(ScriptCanvasTestFixture, ProveError)
+{
+    EXPECT_TRUE(false);
+}
+
 TEST_F(ScriptCanvasTestFixture, EntityIdInputForOnGraphStart)
 {
     RunUnitTestGraph("LY_SC_UnitTest_EntityIdInputForOnGraphStart");

From 188f2f5afec1d7449ab18fb93d056c3e48f6888b Mon Sep 17 00:00:00 2001
From: chcurran <82187351+carlitosan@users.noreply.github.com>
Date: Fri, 30 Jul 2021 14:36:57 -0700
Subject: [PATCH 049/803] remove failing tests, since the farm proved the SC
 suite is running

Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com>
---
 .../Code/Tests/ScriptCanvas_RuntimeInterpreted.cpp           | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/Gems/ScriptCanvasTesting/Code/Tests/ScriptCanvas_RuntimeInterpreted.cpp b/Gems/ScriptCanvasTesting/Code/Tests/ScriptCanvas_RuntimeInterpreted.cpp
index df29a56fd5..c2fa59b037 100644
--- a/Gems/ScriptCanvasTesting/Code/Tests/ScriptCanvas_RuntimeInterpreted.cpp
+++ b/Gems/ScriptCanvasTesting/Code/Tests/ScriptCanvas_RuntimeInterpreted.cpp
@@ -84,11 +84,6 @@ public:
     }
 };
 
-TEST_F(ScriptCanvasTestFixture, ProveError)
-{
-    EXPECT_TRUE(false);
-}
-
 TEST_F(ScriptCanvasTestFixture, EntityIdInputForOnGraphStart)
 {
     RunUnitTestGraph("LY_SC_UnitTest_EntityIdInputForOnGraphStart");

From c5dcef180c38317bcb39ef1859ca33d299d62107 Mon Sep 17 00:00:00 2001
From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>
Date: Fri, 30 Jul 2021 17:30:11 -0700
Subject: [PATCH 050/803] fixes/improvements to AzCore

Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>
---
 .../AzCore/AzCore/std/string/conversions.h    | 47 +++++++++--
 .../AzCore/AzCore/std/string/utf8/unchecked.h | 79 +++++++++++++------
 .../WinAPI/AzCore/Utils/Utils_WinAPI.cpp      |  9 ++-
 Code/Framework/AzCore/Tests/AZStd/String.cpp  |  9 ---
 4 files changed, 104 insertions(+), 40 deletions(-)

diff --git a/Code/Framework/AzCore/AzCore/std/string/conversions.h b/Code/Framework/AzCore/AzCore/std/string/conversions.h
index 4dc5bbd547..cb90881933 100644
--- a/Code/Framework/AzCore/AzCore/std/string/conversions.h
+++ b/Code/Framework/AzCore/AzCore/std/string/conversions.h
@@ -35,11 +35,11 @@ namespace AZStd
             {
                 if constexpr (Size == 2)
                 {
-                    Utf8::Unchecked::utf16to8(first, last, AZStd::back_inserter(dest));
+                    Utf8::Unchecked::utf16to8(first, last, AZStd::back_inserter(dest), dest.max_size());
                 }
                 else if constexpr (Size == 4)
                 {
-                    Utf8::Unchecked::utf32to8(first, last, AZStd::back_inserter(dest));
+                    Utf8::Unchecked::utf32to8(first, last, AZStd::back_inserter(dest), dest.max_size());
                 }
                 else
                 {
@@ -54,11 +54,29 @@ namespace AZStd
             {
                 if constexpr (Size == 2)
                 {
-                    Utf8::Unchecked::utf16to8(first, last, AZStd::back_inserter(dest));
+                    Utf8::Unchecked::utf16to8(first, last, AZStd::back_inserter(dest), dest.max_size());
                 }
                 else if constexpr (Size == 4)
                 {
-                    Utf8::Unchecked::utf32to8(first, last, AZStd::back_inserter(dest));
+                    Utf8::Unchecked::utf32to8(first, last, AZStd::back_inserter(dest), dest.max_size());
+                }
+                else
+                {
+                    // Workaround to defer static_assert evaluation until this function is invoked by using the template parameter
+                    using StringType = AZStd::basic_string;
+                    static_assert(!AZStd::is_same_v, "only wchar_t types of size 2 or 4 can be converted to utf8");
+                }
+            }
+
+            static inline void to_string(char* dest, size_t destSize, const wchar_t* first, const wchar_t* last)
+            {
+                if constexpr (Size == 2)
+                {
+                    Utf8::Unchecked::utf16to8(first, last, dest, destSize);
+                }
+                else if constexpr (Size == 4)
+                {
+                    Utf8::Unchecked::utf32to8(first, last, dest, destSize);
                 }
                 else
                 {
@@ -73,11 +91,11 @@ namespace AZStd
             {
                 if constexpr (Size == 2)
                 {
-                    Utf8::Unchecked::utf8to16(first, last, AZStd::back_inserter(dest));
+                    Utf8::Unchecked::utf8to16(first, last, AZStd::back_inserter(dest), dest.max_size());
                 }
                 else if constexpr (Size == 4)
                 {
-                    Utf8::Unchecked::utf8to32(first, last, AZStd::back_inserter(dest));
+                    Utf8::Unchecked::utf8to32(first, last, AZStd::back_inserter(dest), dest.max_size());
                 }
                 else
                 {
@@ -92,11 +110,11 @@ namespace AZStd
             {
                 if constexpr (Size == 2)
                 {
-                    Utf8::Unchecked::utf8to16(first, last, AZStd::back_inserter(dest));
+                    Utf8::Unchecked::utf8to16(first, last, AZStd::back_inserter(dest), dest.max_size());
                 }
                 else if constexpr (Size == 4)
                 {
-                    Utf8::Unchecked::utf8to32(first, last, AZStd::back_inserter(dest));
+                    Utf8::Unchecked::utf8to32(first, last, AZStd::back_inserter(dest), dest.max_size());
                 }
                 else
                 {
@@ -326,6 +344,19 @@ namespace AZStd
         return to_string(dest, src.c_str(), src.length());
     }
 
+    inline void to_string(char* dest, size_t destSize, const wchar_t* str, size_t srcLen = 0)
+    {
+        if (srcLen == 0)
+        {
+            srcLen = wcslen(str) + 1;
+        }
+
+        if (srcLen > 0)
+        {
+            Internal::WCharTPlatformConverter<>::to_string(dest, destSize, str, str + srcLen + 1); // copy null terminator
+        }
+    }
+
     template
     int stoi(const AZStd::basic_string& str, AZStd::size_t* idx = 0, int base = 10)
     {
diff --git a/Code/Framework/AzCore/AzCore/std/string/utf8/unchecked.h b/Code/Framework/AzCore/AzCore/std/string/utf8/unchecked.h
index 9608ff897b..cfc917ddc4 100644
--- a/Code/Framework/AzCore/AzCore/std/string/utf8/unchecked.h
+++ b/Code/Framework/AzCore/AzCore/std/string/utf8/unchecked.h
@@ -92,33 +92,58 @@ namespace Utf8::Unchecked
             return temp;
         }
 
-        static Iterator to_utf8_sequence(AZ::u32 cp, Iterator result)
+        static Iterator to_utf8_sequence(AZ::u32 cp, Iterator& result, size_t& resultMaxSize)
         {
             if (cp < 0x80)
             {
                 // one octet
+                resultMaxSize -= 1; // no need to check the calling function will exit the loop
                 *(result++) = static_cast(cp);
             }
             else if (cp < 0x800)
             {
                 // two octets
-                *(result++) = static_cast((cp >> 6) | 0xc0);
-                *(result++) = static_cast((cp & 0x3f) | 0x80);
+                if (resultMaxSize >= 2)
+                {
+                    *(result++) = static_cast((cp >> 6) | 0xc0);
+                    *(result++) = static_cast((cp & 0x3f) | 0x80);
+                    resultMaxSize -= 2;
+                }
+                else
+                {
+                    resultMaxSize = 0;
+                }
             }
             else if (cp < 0x10000)
             {
                 // three octets
-                *(result++) = static_cast((cp >> 12) | 0xe0);
-                *(result++) = static_cast(((cp >> 6) & 0x3f) | 0x80);
-                *(result++) = static_cast((cp & 0x3f) | 0x80);
+                if (resultMaxSize >= 3)
+                {
+                    *(result++) = static_cast((cp >> 12) | 0xe0);
+                    *(result++) = static_cast(((cp >> 6) & 0x3f) | 0x80);
+                    *(result++) = static_cast((cp & 0x3f) | 0x80);
+                    resultMaxSize -= 3;
+                }
+                else
+                {
+                    resultMaxSize = 0;
+                }
             }
             else
             {
                 // four octets
-                *(result++) = static_cast((cp >> 18) | 0xf0);
-                *(result++) = static_cast(((cp >> 12) & 0x3f) | 0x80);
-                *(result++) = static_cast(((cp >> 6) & 0x3f) | 0x80);
-                *(result++) = static_cast((cp & 0x3f) | 0x80);
+                if (resultMaxSize >= 4)
+                {
+                    *(result++) = static_cast((cp >> 18) | 0xf0);
+                    *(result++) = static_cast(((cp >> 12) & 0x3f) | 0x80);
+                    *(result++) = static_cast(((cp >> 6) & 0x3f) | 0x80);
+                    *(result++) = static_cast((cp & 0x3f) | 0x80);
+                    resultMaxSize -= 4;
+                }
+                else
+                {
+                    resultMaxSize = 0;
+                }
             }
             return result;
         }
@@ -155,9 +180,9 @@ namespace Utf8::Unchecked
     };
 
     template 
-    Utf8Iterator utf16to8(u16bit_iterator start, u16bit_iterator end, Utf8Iterator result)
+    Utf8Iterator utf16to8(u16bit_iterator start, u16bit_iterator end, Utf8Iterator result, size_t resultMaxSize)
     {
-        while (start != end)
+        while (start != end && resultMaxSize > 0)
         {
             AZ::u32 cp = Utf8::Internal::mask16(*start++);
             // Take care of surrogate pairs first
@@ -166,52 +191,62 @@ namespace Utf8::Unchecked
                 AZ::u32 trail_surrogate = Utf8::Internal::mask16(*start++);
                 cp = (cp << 10) + trail_surrogate + Internal::SURROGATE_OFFSET;
             }
-            octet_iterator::to_utf8_sequence(cp, result);
+            octet_iterator::to_utf8_sequence(cp, result, resultMaxSize);
         }
         return result;
     }
 
     template 
-    u16bit_iterator utf8to16(Utf8Iterator start, Utf8Iterator end, u16bit_iterator result)
+    u16bit_iterator utf8to16(Utf8Iterator start, Utf8Iterator end, u16bit_iterator result, size_t resultMaxSize)
     {
         octet_iterator utf8Start(start);
         octet_iterator utf8Last(end);
-        while (utf8Start != utf8Last)
+        while (utf8Start != utf8Last && resultMaxSize > 0)
         {
             AZ::u32 cp = *utf8Start++;
             if (cp > 0xffff)
             {
                 //make a surrogate pair
-                *result++ = static_cast((cp >> 10) + Internal::LEAD_OFFSET);
-                *result++ = static_cast((cp & 0x3ff) + Internal::TRAIL_SURROGATE_MIN);
+                if (resultMaxSize >= 2)
+                {
+                    *result++ = static_cast((cp >> 10) + Internal::LEAD_OFFSET);
+                    *result++ = static_cast((cp & 0x3ff) + Internal::TRAIL_SURROGATE_MIN);
+                    resultMaxSize -= 2;
+                }
+                else
+                {
+                    resultMaxSize = 0;
+                }
             }
             else
             {
                 *result++ = static_cast(cp);
+                resultMaxSize -= 1;
             }
         }
         return result;
     }
 
     template 
-    Utf8Iterator utf32to8(u32bit_iterator start, u32bit_iterator end, Utf8Iterator result)
+    Utf8Iterator utf32to8(u32bit_iterator start, u32bit_iterator end, Utf8Iterator result, size_t resultMaxSize)
     {
-        while (start != end)
+        while (start != end && resultMaxSize > 0)
         {
-            octet_iterator::to_utf8_sequence(*start++, result);
+            octet_iterator::to_utf8_sequence(*start++, result, resultMaxSize);
         }
 
         return result;
     }
 
     template 
-    u32bit_iterator utf8to32(Utf8Iterator start, Utf8Iterator end, u32bit_iterator result)
+    u32bit_iterator utf8to32(Utf8Iterator start, Utf8Iterator end, u32bit_iterator result, size_t resultMaxSize)
     {
         octet_iterator utf8Start(start);
         octet_iterator utf8Last(end);
-        while (utf8Start != utf8Last)
+        while (utf8Start != utf8Last && resultMaxSize > 0)
         {
             *result++ = *utf8Start++;
+            --resultMaxSize;
         }
 
         return result;
diff --git a/Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/Utils/Utils_WinAPI.cpp b/Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/Utils/Utils_WinAPI.cpp
index 66257735b4..c57f2b31f6 100644
--- a/Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/Utils/Utils_WinAPI.cpp
+++ b/Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/Utils/Utils_WinAPI.cpp
@@ -11,6 +11,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 
@@ -29,7 +30,9 @@ namespace AZ
             result.m_pathIncludesFilename = true;
             // Platform specific get exe path: http://stackoverflow.com/a/1024937
             // https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getmodulefilenamea
-            const DWORD pathLen = GetModuleFileNameA(nullptr, exeStorageBuffer, static_cast(exeStorageSize));
+            AZStd::wstring pathBuffer;
+            pathBuffer.resize(exeStorageSize);
+            const DWORD pathLen = GetModuleFileName(nullptr, pathBuffer.data(), static_cast(exeStorageSize));
             const DWORD errorCode = GetLastError();
             if (pathLen == exeStorageSize && errorCode == ERROR_INSUFFICIENT_BUFFER)
             {
@@ -39,6 +42,10 @@ namespace AZ
             {
                 result.m_pathStored = ExecutablePathResult::GeneralError;
             }
+            else
+            {
+                AZStd::to_string(exeStorageBuffer, exeStorageSize, pathBuffer.c_str());
+            }
 
             return result;
         }
diff --git a/Code/Framework/AzCore/Tests/AZStd/String.cpp b/Code/Framework/AzCore/Tests/AZStd/String.cpp
index 0e6ea4727c..2d2602e456 100644
--- a/Code/Framework/AzCore/Tests/AZStd/String.cpp
+++ b/Code/Framework/AzCore/Tests/AZStd/String.cpp
@@ -628,10 +628,6 @@ namespace UnitTest
         }
     }
 
-#if defined(AZ_COMPILER_MSVC)
-#   pragma warning(push)
-#   pragma warning( disable: 4428 )   // universal-character-name encountered in source
-#endif // AZ_COMPILER_MSVC
     TEST_F(String, Algorithms)
     {
         string str = string::format("%s %d", "BlaBla", 5);
@@ -1114,11 +1110,6 @@ namespace UnitTest
         EXPECT_FALSE(other2.Valid());
     }
 
-    // StringAlgorithmTest-End
-#if defined(AZ_COMPILER_MSVC)
-#   pragma warning(pop)
-#endif // AZ_COMPILER_MSVC
-
     TEST_F(String, ConstString)
     {
         string_view cstr1;

From 63445e107a0da2584475b16539d2499f54153909 Mon Sep 17 00:00:00 2001
From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>
Date: Fri, 30 Jul 2021 17:33:50 -0700
Subject: [PATCH 051/803] fxies for AzFramework

Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>
---
 .../Network/AssetProcessorConnection.cpp      |  2 +-
 .../Android/platform_android_files.cmake      |  1 -
 .../AssetProcessorConnection_Default.cpp      | 24 ------------------
 .../AzFramework/IO/LocalFileIO_WinAPI.cpp     | 17 ++++++++-----
 .../AssetProcessorConnection_WinAPI.cpp       | 25 -------------------
 .../Platform/Linux/platform_linux_files.cmake |  1 -
 .../Platform/Mac/platform_mac_files.cmake     |  1 -
 .../AssetSystemComponentHelper_Windows.cpp    | 12 ++++++---
 .../TargetManagementComponent_Windows.cpp     |  9 ++++---
 .../Windowing/NativeWindow_Windows.cpp        | 17 ++++++++-----
 .../Windows/platform_windows_files.cmake      |  1 -
 .../Platform/iOS/platform_ios_files.cmake     |  1 -
 12 files changed, 36 insertions(+), 75 deletions(-)
 delete mode 100644 Code/Framework/AzFramework/Platform/Common/Default/AzFramework/Network/AssetProcessorConnection_Default.cpp
 delete mode 100644 Code/Framework/AzFramework/Platform/Common/WinAPI/AzFramework/Network/AssetProcessorConnection_WinAPI.cpp

diff --git a/Code/Framework/AzFramework/AzFramework/Network/AssetProcessorConnection.cpp b/Code/Framework/AzFramework/AzFramework/Network/AssetProcessorConnection.cpp
index a65a3079a0..ebea29c2d9 100644
--- a/Code/Framework/AzFramework/AzFramework/Network/AssetProcessorConnection.cpp
+++ b/Code/Framework/AzFramework/AzFramework/Network/AssetProcessorConnection.cpp
@@ -136,7 +136,7 @@ namespace AzFramework
             AZStd::array buffer;
             azsnprintf(buffer.data(), buffer.size(), "(%p/%#" PRIxPTR "): %s\n", this, numericThreadId, msg.data());
 
-            Platform::DebugOutput(buffer.data());
+            AZ::Debug::Platform::OutputToDebugger("AssetProcessorConnection", buffer.data());
 #else // ASSETPROCESORCONNECTION_VERBOSE_LOGGING is not defined
             (void)format;
 #endif
diff --git a/Code/Framework/AzFramework/Platform/Android/platform_android_files.cmake b/Code/Framework/AzFramework/Platform/Android/platform_android_files.cmake
index 35b5a10151..c220bc1154 100644
--- a/Code/Framework/AzFramework/Platform/Android/platform_android_files.cmake
+++ b/Code/Framework/AzFramework/Platform/Android/platform_android_files.cmake
@@ -14,7 +14,6 @@ set(FILES
     AzFramework/Application/Application_Android.cpp
     ../Common/Unimplemented/AzFramework/Asset/AssetSystemComponentHelper_Unimplemented.cpp
     AzFramework/IO/LocalFileIO_Android.cpp
-    ../Common/Default/AzFramework/Network/AssetProcessorConnection_Default.cpp
     ../Common/Unimplemented/AzFramework/StreamingInstall/StreamingInstall_Unimplemented.cpp
     ../Common/Default/AzFramework/TargetManagement/TargetManagementComponent_Default.cpp
     AzFramework/Windowing/NativeWindow_Android.cpp
diff --git a/Code/Framework/AzFramework/Platform/Common/Default/AzFramework/Network/AssetProcessorConnection_Default.cpp b/Code/Framework/AzFramework/Platform/Common/Default/AzFramework/Network/AssetProcessorConnection_Default.cpp
deleted file mode 100644
index 5bc020a1d6..0000000000
--- a/Code/Framework/AzFramework/Platform/Common/Default/AzFramework/Network/AssetProcessorConnection_Default.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
-
-#include 
-
-namespace AzFramework
-{
-    namespace AssetSystem
-    {
-        namespace Platform
-        {
-            void DebugOutput(const char* message)
-            {
-                fputs("AssetProcessorConnection:", stdout);
-                fputs(message, stdout);
-            }
-        }
-    }
-}
diff --git a/Code/Framework/AzFramework/Platform/Common/WinAPI/AzFramework/IO/LocalFileIO_WinAPI.cpp b/Code/Framework/AzFramework/Platform/Common/WinAPI/AzFramework/IO/LocalFileIO_WinAPI.cpp
index 4c7d84b511..58afebfb90 100644
--- a/Code/Framework/AzFramework/Platform/Common/WinAPI/AzFramework/IO/LocalFileIO_WinAPI.cpp
+++ b/Code/Framework/AzFramework/Platform/Common/WinAPI/AzFramework/IO/LocalFileIO_WinAPI.cpp
@@ -9,6 +9,7 @@
 #include 
 #include 
 #include 
+#include 
 
 namespace AZ
 {
@@ -33,7 +34,7 @@ namespace AZ
             char resolvedPath[AZ_MAX_PATH_LEN];
             ResolvePath(filePath, resolvedPath, AZ_MAX_PATH_LEN);
 
-            AZ::OSString searchPattern;
+            AZStd::string searchPattern;
             if ((resolvedPath[0] == 0) || (resolvedPath[1] == 0))
             {
                 return ResultCode::Error; // not a valid path.
@@ -54,7 +55,9 @@ namespace AZ
             searchPattern += "\\*.*"; // use our own filtering function!
 
             WIN32_FIND_DATA findData;
-            HANDLE hFind = FindFirstFile(searchPattern.c_str(), &findData);
+            AZStd::wstring searchPatternW;
+            AZStd::to_wstring(searchPatternW, searchPattern.c_str());
+            HANDLE hFind = FindFirstFileW(searchPatternW.c_str(), &findData);
 
             if (hFind != INVALID_HANDLE_VALUE)
             {
@@ -63,15 +66,17 @@ namespace AZ
                 char tempBuffer[AZ_MAX_PATH_LEN];
                 do
                 {
-                    AZStd::string_view filenameView = findData.cFileName;
+                    AZStd::string fileName;
+                    AZStd::to_string(fileName, findData.cFileName);
+                    AZStd::string_view filenameView = fileName;
                     // Skip over the current directory and parent directory paths to prevent infinite recursion
-                    if (filenameView == "." || filenameView == ".." || !NameMatchesFilter(findData.cFileName, filter))
+                    if (filenameView == "." || filenameView == ".." || !NameMatchesFilter(fileName.c_str(), filter))
                     {
                         continue;
                     }
 
-                    AZ::OSString foundFilePath = CheckForTrailingSlash(resolvedPath);
-                    foundFilePath += findData.cFileName;
+                    AZStd::string foundFilePath = CheckForTrailingSlash(resolvedPath);
+                    foundFilePath += fileName;
                     AZStd::replace(foundFilePath.begin(), foundFilePath.end(), '\\', '/');
 
                     // if aliased, de-alias!
diff --git a/Code/Framework/AzFramework/Platform/Common/WinAPI/AzFramework/Network/AssetProcessorConnection_WinAPI.cpp b/Code/Framework/AzFramework/Platform/Common/WinAPI/AzFramework/Network/AssetProcessorConnection_WinAPI.cpp
deleted file mode 100644
index a02e697df6..0000000000
--- a/Code/Framework/AzFramework/Platform/Common/WinAPI/AzFramework/Network/AssetProcessorConnection_WinAPI.cpp
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
-
-#include 
-#include 
-
-namespace AzFramework
-{
-    namespace AssetSystem
-    {
-        namespace Platform
-        {
-            void DebugOutput(const char* message)
-            {
-                OutputDebugString("AssetProcessorConnection:");
-                OutputDebugString(message);
-            }
-        }
-    }
-}
diff --git a/Code/Framework/AzFramework/Platform/Linux/platform_linux_files.cmake b/Code/Framework/AzFramework/Platform/Linux/platform_linux_files.cmake
index 60b16938a1..21201d954d 100644
--- a/Code/Framework/AzFramework/Platform/Linux/platform_linux_files.cmake
+++ b/Code/Framework/AzFramework/Platform/Linux/platform_linux_files.cmake
@@ -17,7 +17,6 @@ set(FILES
     AzFramework/Process/ProcessCommon.h
     AzFramework/Process/ProcessCommunicator_Linux.cpp
     ../Common/UnixLike/AzFramework/IO/LocalFileIO_UnixLike.cpp
-    ../Common/Default/AzFramework/Network/AssetProcessorConnection_Default.cpp
     ../Common/Unimplemented/AzFramework/StreamingInstall/StreamingInstall_Unimplemented.cpp
     ../Common/Default/AzFramework/TargetManagement/TargetManagementComponent_Default.cpp
     AzFramework/Windowing/NativeWindow_Linux.cpp
diff --git a/Code/Framework/AzFramework/Platform/Mac/platform_mac_files.cmake b/Code/Framework/AzFramework/Platform/Mac/platform_mac_files.cmake
index c428160892..78f11a65da 100644
--- a/Code/Framework/AzFramework/Platform/Mac/platform_mac_files.cmake
+++ b/Code/Framework/AzFramework/Platform/Mac/platform_mac_files.cmake
@@ -17,7 +17,6 @@ set(FILES
     AzFramework/Process/ProcessCommon.h
     AzFramework/Process/ProcessCommunicator_Mac.cpp
     ../Common/UnixLike/AzFramework/IO/LocalFileIO_UnixLike.cpp
-    ../Common/Default/AzFramework/Network/AssetProcessorConnection_Default.cpp
     ../Common/Unimplemented/AzFramework/StreamingInstall/StreamingInstall_Unimplemented.cpp
     AzFramework/TargetManagement/TargetManagementComponent_Mac.cpp
     AzFramework/Windowing/NativeWindow_Mac.mm
diff --git a/Code/Framework/AzFramework/Platform/Windows/AzFramework/Asset/AssetSystemComponentHelper_Windows.cpp b/Code/Framework/AzFramework/Platform/Windows/AzFramework/Asset/AssetSystemComponentHelper_Windows.cpp
index 4b685b25a3..a3782ae081 100644
--- a/Code/Framework/AzFramework/Platform/Windows/AzFramework/Asset/AssetSystemComponentHelper_Windows.cpp
+++ b/Code/Framework/AzFramework/Platform/Windows/AzFramework/Asset/AssetSystemComponentHelper_Windows.cpp
@@ -48,10 +48,10 @@ namespace AzFramework::AssetSystem::Platform
                     // Get the first module, because that will be the executable
                     if (EnumProcessModules(processHandle, &moduleHandle, sizeof(moduleHandle), &bytesNeededForAllProcessModules))
                     {
-                        char processName[4096] = TEXT("");
-                        if (GetModuleBaseNameA(processHandle, moduleHandle, processName, AZ_ARRAY_SIZE(processName)) > 0)
+                        wchar_t processName[4096] = L"";
+                        if (GetModuleBaseName(processHandle, moduleHandle, processName, AZ_ARRAY_SIZE(processName)) > 0)
                         {
-                            if (azstricmp(processName, "AssetProcessor") == 0)
+                            if (azwcsicmp(processName, L"AssetProcessor") == 0)
                             {
                                 AllowSetForegroundWindow(processId);
                             }
@@ -126,7 +126,11 @@ namespace AzFramework::AssetSystem::Platform
         si.wShowWindow = SW_MINIMIZE;
         PROCESS_INFORMATION pi;
 
-        bool createResult = ::CreateProcessA(nullptr, fullLaunchCommand.data(), nullptr, nullptr, FALSE, 0, nullptr, AZ::IO::FixedMaxPathString{ executableDirectory }.c_str(), &si, &pi) != 0;
+        AZStd::wstring fullLaunchCommandW;
+        AZStd::to_wstring(fullLaunchCommandW, fullLaunchCommand.c_str());
+        AZStd::wstring execututableDirectoryW;
+        AZStd::to_wstring(execututableDirectoryW, executableDirectory.data());
+        bool createResult = ::CreateProcessW(nullptr, fullLaunchCommandW.data(), nullptr, nullptr, FALSE, 0, nullptr, execututableDirectoryW.c_str(), &si, &pi) != 0;
 
         if (ap_tether_lifetime && apJob && createResult)
         {
diff --git a/Code/Framework/AzFramework/Platform/Windows/AzFramework/TargetManagement/TargetManagementComponent_Windows.cpp b/Code/Framework/AzFramework/Platform/Windows/AzFramework/TargetManagement/TargetManagementComponent_Windows.cpp
index fbfb3778cb..e168968278 100644
--- a/Code/Framework/AzFramework/Platform/Windows/AzFramework/TargetManagement/TargetManagementComponent_Windows.cpp
+++ b/Code/Framework/AzFramework/Platform/Windows/AzFramework/TargetManagement/TargetManagementComponent_Windows.cpp
@@ -10,6 +10,7 @@
 #include 
 #include 
 #include 
+#include 
 
 namespace AzFramework
 {
@@ -35,12 +36,12 @@ namespace AzFramework
         AZStd::string GetNeighborhoodName()
         {
             AZStd::string neighborhoodName;
-            
-            char localhost[MAX_COMPUTERNAME_LENGTH + 1];
+
+            wchar_t localhost[MAX_COMPUTERNAME_LENGTH + 1];
             DWORD len = AZ_ARRAY_SIZE(localhost);
-            if (GetComputerName(localhost, &len))
+            if (GetComputerNameW(localhost, &len))
             {
-                neighborhoodName = localhost;
+                AZStd::to_string(neighborhoodName, localhost);
             }
 
             return neighborhoodName;
diff --git a/Code/Framework/AzFramework/Platform/Windows/AzFramework/Windowing/NativeWindow_Windows.cpp b/Code/Framework/AzFramework/Platform/Windows/AzFramework/Windowing/NativeWindow_Windows.cpp
index 0047929120..22a293891c 100644
--- a/Code/Framework/AzFramework/Platform/Windows/AzFramework/Windowing/NativeWindow_Windows.cpp
+++ b/Code/Framework/AzFramework/Platform/Windows/AzFramework/Windowing/NativeWindow_Windows.cpp
@@ -11,6 +11,7 @@
 
 #include 
 #include 
+#include 
 
 namespace AzFramework
 {
@@ -41,7 +42,7 @@ namespace AzFramework
         static DWORD ConvertToWin32WindowStyleMask(const WindowStyleMasks& styleMasks);
         static LRESULT CALLBACK WindowCallback(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
 
-        static const char* s_defaultClassName;
+        static const wchar_t* s_defaultClassName;
 
         void WindowSizeChanged(const uint32_t width, const uint32_t height);
 
@@ -57,7 +58,7 @@ namespace AzFramework
         GetDpiForWindowType* m_getDpiFunction = nullptr;
     };
 
-    const char* NativeWindowImpl_Win32::s_defaultClassName = "O3DEWin32Class";
+    const wchar_t* NativeWindowImpl_Win32::s_defaultClassName = L"O3DEWin32Class";
 
     NativeWindow::Implementation* NativeWindow::Implementation::Create()
     {
@@ -88,7 +89,7 @@ namespace AzFramework
 
         // register window class if it does not exist
         WNDCLASSEX windowClass;
-        if (GetClassInfoEx(hInstance, s_defaultClassName, &windowClass) == false)
+        if (GetClassInfoExW(hInstance, s_defaultClassName, &windowClass) == false)
         {
             windowClass.cbSize = sizeof(WNDCLASSEX);
             windowClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
@@ -127,8 +128,10 @@ namespace AzFramework
         m_height = geometry.m_height;
 
         // create main window
-        m_win32Handle = CreateWindow(
-            s_defaultClassName, title.c_str(),
+        AZStd::wstring titleW;
+        AZStd::to_wstring(titleW, title);
+        m_win32Handle = CreateWindowW(
+            s_defaultClassName, titleW.c_str(),
             windowStyle,
             geometry.m_posX, geometry.m_posY, windowRect.right - windowRect.left, windowRect.bottom - windowRect.top,
             NULL, NULL, hInstance, NULL);
@@ -175,7 +178,9 @@ namespace AzFramework
 
     void NativeWindowImpl_Win32::SetWindowTitle(const AZStd::string& title)
     {
-        SetWindowText(m_win32Handle, title.c_str());
+        AZStd::wstring titleW;
+        AZStd::to_wstring(titleW, title);
+        SetWindowTextW(m_win32Handle, titleW.c_str());
     }
 
     DWORD NativeWindowImpl_Win32::ConvertToWin32WindowStyleMask(const WindowStyleMasks& styleMasks)
diff --git a/Code/Framework/AzFramework/Platform/Windows/platform_windows_files.cmake b/Code/Framework/AzFramework/Platform/Windows/platform_windows_files.cmake
index af43234bd0..b8f5b5f841 100644
--- a/Code/Framework/AzFramework/Platform/Windows/platform_windows_files.cmake
+++ b/Code/Framework/AzFramework/Platform/Windows/platform_windows_files.cmake
@@ -18,7 +18,6 @@ set(FILES
     AzFramework/Process/ProcessCommunicator_Win.cpp
     ../Common/WinAPI/AzFramework/IO/LocalFileIO_WinAPI.cpp
     AzFramework/IO/LocalFileIO_Windows.cpp
-    ../Common/WinAPI/AzFramework/Network/AssetProcessorConnection_WinAPI.cpp
     ../Common/Unimplemented/AzFramework/StreamingInstall/StreamingInstall_Unimplemented.cpp
     AzFramework/TargetManagement/TargetManagementComponent_Windows.cpp
     AzFramework/Windowing/NativeWindow_Windows.cpp
diff --git a/Code/Framework/AzFramework/Platform/iOS/platform_ios_files.cmake b/Code/Framework/AzFramework/Platform/iOS/platform_ios_files.cmake
index f47eb136be..7745f43ec9 100644
--- a/Code/Framework/AzFramework/Platform/iOS/platform_ios_files.cmake
+++ b/Code/Framework/AzFramework/Platform/iOS/platform_ios_files.cmake
@@ -14,7 +14,6 @@ set(FILES
     AzFramework/Application/Application_iOS.mm
     ../Common/Unimplemented/AzFramework/Asset/AssetSystemComponentHelper_Unimplemented.cpp
     ../Common/UnixLike/AzFramework/IO/LocalFileIO_UnixLike.cpp
-    ../Common/Default/AzFramework/Network/AssetProcessorConnection_Default.cpp
     ../Common/Unimplemented/AzFramework/StreamingInstall/StreamingInstall_Unimplemented.cpp
     ../Common/Default/AzFramework/TargetManagement/TargetManagementComponent_Default.cpp
     AzFramework/Windowing/NativeWindow_ios.mm

From 3f6335dc324d0b80ec730af155026fbf97d2f8a4 Mon Sep 17 00:00:00 2001
From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>
Date: Fri, 30 Jul 2021 17:34:14 -0700
Subject: [PATCH 052/803] Fixes for AzQtComponents

Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>
---
 .../AzQtComponents/AzQtComponents/Gallery/main.cpp       | 9 ++-------
 1 file changed, 2 insertions(+), 7 deletions(-)

diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/main.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/main.cpp
index 51ca2b349f..2a4a29ffe6 100644
--- a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/main.cpp
+++ b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/main.cpp
@@ -40,13 +40,8 @@ const QString g_ui_1_0_SettingKey = QStringLiteral("useUI_1_0");
 
 static void LogToDebug([[maybe_unused]] QtMsgType Type, [[maybe_unused]] const QMessageLogContext& Context, const QString& message)
 {
-#ifdef Q_OS_WIN
-    OutputDebugStringW(L"Qt: ");
-    OutputDebugStringW(reinterpret_cast(message.utf16()));
-    OutputDebugStringW(L"\n");
-#else
-    std::wcerr << L"Qt: " << message.toStdWString() << std::endl;
-#endif
+    AZ::Debug::Platform::OutputToDebugger("Qt", message.toStdString().c_str());
+    AZ::Debug::Platform::OutputToDebugger(nullptr, "\n");
 }
 
 /*

From 1b4c06d03dbe44243cbf1dc03005aad85b0e36f0 Mon Sep 17 00:00:00 2001
From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>
Date: Fri, 30 Jul 2021 17:38:46 -0700
Subject: [PATCH 053/803] other Framework fixes

Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>
---
 .../AzTest/AzTest/Platform/Windows/Platform_Windows.cpp        | 3 ++-
 .../Platform/Windows/GridMate/Session/LANSession_Windows.cpp   | 2 +-
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/Code/Framework/AzTest/AzTest/Platform/Windows/Platform_Windows.cpp b/Code/Framework/AzTest/AzTest/Platform/Windows/Platform_Windows.cpp
index 08e86fdc16..777ba66c6d 100644
--- a/Code/Framework/AzTest/AzTest/Platform/Windows/Platform_Windows.cpp
+++ b/Code/Framework/AzTest/AzTest/Platform/Windows/Platform_Windows.cpp
@@ -9,6 +9,7 @@
 #include 
 #include 
 #include 
+#include 
 
 //-------------------------------------------------------------------------------------------------
 class ModuleHandle
@@ -151,7 +152,7 @@ namespace AZ
             va_start(mark, format);
             azvsnprintf(message, MAX_PRINT_MSG, format, mark);
             va_end(mark);
-            OutputDebugString(message);
+            AZ::Debug::Platform::OutputToDebugger(nullptr, message);
         }
 
         AZ::EnvironmentInstance Platform::GetTestRunnerEnvironment()
diff --git a/Code/Framework/GridMate/Platform/Windows/GridMate/Session/LANSession_Windows.cpp b/Code/Framework/GridMate/Platform/Windows/GridMate/Session/LANSession_Windows.cpp
index 4bf038a2cf..59a1c65781 100644
--- a/Code/Framework/GridMate/Platform/Windows/GridMate/Session/LANSession_Windows.cpp
+++ b/Code/Framework/GridMate/Platform/Windows/GridMate/Session/LANSession_Windows.cpp
@@ -21,7 +21,7 @@ namespace GridMate
 
             char procPath[256];
             char procName[256];
-            DWORD ret = GetModuleFileName(NULL, procPath, 256);
+            DWORD ret = GetModuleFileNameA(NULL, procPath, 256);
             if (ret > 0)
             {
                 ::_splitpath_s(procPath, 0, 0, 0, 0, procName, 256, 0, 0);

From 41ad6d7b7a9326f23c29abf6cef8fb3e442f1d05 Mon Sep 17 00:00:00 2001
From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>
Date: Fri, 30 Jul 2021 17:39:02 -0700
Subject: [PATCH 054/803] Code/Legacy cleanup

Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>
---
 Code/Legacy/CryCommon/platform_impl.cpp       |  38 ++--
 Code/Legacy/CrySystem/ConsoleHelpGen.cpp      |   6 +-
 Code/Legacy/CrySystem/DebugCallStack.cpp      |  19 +-
 Code/Legacy/CrySystem/IDebugCallStack.cpp     |   2 +-
 .../CrySystem/LocalizedStringManager.cpp      |  31 ++-
 Code/Legacy/CrySystem/Log.cpp                 |  21 +--
 Code/Legacy/CrySystem/System.cpp              |  18 +-
 Code/Legacy/CrySystem/SystemCFG.cpp           |  42 +++--
 Code/Legacy/CrySystem/SystemCFG.h             |   6 -
 Code/Legacy/CrySystem/SystemInit.cpp          |  57 +++---
 Code/Legacy/CrySystem/SystemWin32.cpp         |  40 ++--
 .../CrySystem/WindowsErrorReporting.cpp       |   4 +-
 Code/Legacy/CrySystem/XConsole.cpp            | 177 ++++++++----------
 Code/Legacy/CrySystem/XConsole.h              |  18 +-
 Code/Legacy/CrySystem/XConsoleVariable.cpp    |  32 ++--
 Code/Legacy/CrySystem/XConsoleVariable.h      |  52 +++--
 16 files changed, 267 insertions(+), 296 deletions(-)

diff --git a/Code/Legacy/CryCommon/platform_impl.cpp b/Code/Legacy/CryCommon/platform_impl.cpp
index 54bf38aaa0..6badd2fe1e 100644
--- a/Code/Legacy/CryCommon/platform_impl.cpp
+++ b/Code/Legacy/CryCommon/platform_impl.cpp
@@ -10,13 +10,14 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 
 #include 
 #include 
 #include 
 #include 
+#include 
+#include 
 
 // Section dictionary
 #if defined(AZ_RESTRICTED_PLATFORM)
@@ -245,18 +246,23 @@ int CryMessageBox([[maybe_unused]] const char* lpText, [[maybe_unused]] const ch
     {
         return 0;
     }
-    return MessageBox(NULL, lpText, lpCaption, uType);
+    AZStd::wstring lpTextW;
+    AZStd::to_wstring(lpTextW, lpText);
+    AZStd::wstring lpCaptionW;
+    AZStd::to_wstring(lpCaptionW, lpCaption);
+    return MessageBoxW(NULL, lpTextW.c_str(), lpCaptionW.c_str(), uType);
 #else
     return 0;
 #endif
 }
 
 // Initializes root folder of the game, optionally returns exe and path name.
-void InitRootDir(char szExeFileName[], uint nExeSize, char szExeRootName[], [[maybe_unused]] uint nRootSize)
+void InitRootDir(char szExeFileName[], uint nExeSize, char szExeRootName[], uint nRootSize)
 {
-    WCHAR szPath[_MAX_PATH];
-    size_t nLen = GetModuleFileNameW(GetModuleHandle(NULL), szPath, _MAX_PATH);
-    assert(nLen < _MAX_PATH && "The path to the current executable exceeds the expected length");
+    char szPath[_MAX_PATH];
+    AZ::Utils::GetExecutablePathReturnType ret = AZ::Utils::GetExecutablePath(szPath, _MAX_PATH);
+    AZ_Assert(ret.m_pathStored == AZ::Utils::ExecutablePathResult::Success, "The path to the current executable exceeds the expected length");
+    const size_t nLen = strnlen(szPath, _MAX_PATH);
 
     // Find path above exe name and deepest folder.
     bool firstIteration = true;
@@ -271,25 +277,27 @@ void InitRootDir(char szExeFileName[], uint nExeSize, char szExeRootName[], [[ma
                 // Return exe path
                 if (szExeRootName)
                 {
-                    Unicode::Convert(szExeRootName, n+1, szPath);
+                    azstrncpy(szExeRootName, nRootSize, szPath + n + 1, nLen - n - 1);
                 }
 
                 // Return exe name
                 if (szExeFileName)
                 {
-                    Unicode::Convert(szExeFileName, nExeSize, szPath + n);
+                    azstrncpy(szExeFileName, nExeSize, szPath + n, nLen - n);
                 }
                 firstIteration = false;
             }
             // Check if the engineroot exists
-            wcscat_s(szPath, L"\\engine.json");
+            azstrcat(szPath, "\\engine.json");
             WIN32_FILE_ATTRIBUTE_DATA data;
-            BOOL res = GetFileAttributesExW(szPath, GetFileExInfoStandard, &data);
+            AZStd::wstring szPathW;
+            AZStd::to_wstring(szPathW, szPath);
+            BOOL res = GetFileAttributesExW(szPathW.c_str(), GetFileExInfoStandard, &data);
             if (res != 0 && data.dwFileAttributes != INVALID_FILE_ATTRIBUTES)
             {
                 // Found file
                 szPath[n] = 0;
-                SetCurrentDirectoryW(szPath);
+                SetCurrentDirectoryW(szPathW.c_str());
                 break;
             }
         }
@@ -423,7 +431,9 @@ uint32 CryGetFileAttributes(const char* lpFileName)
 #if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED)
 #undef AZ_RESTRICTED_SECTION_IMPLEMENTED
 #else
-    res = GetFileAttributesEx(lpFileName, GetFileExInfoStandard, &data);
+    AZStd::wstring lpFileNameW;
+    AZStd::to_wstring(lpFileNameW, lpFileName);
+    res = GetFileAttributesExW(lpFileNameW.c_str(), GetFileExInfoStandard, &data);
 #endif
     return res ? data.dwFileAttributes : -1;
 }
@@ -438,7 +448,9 @@ bool CrySetFileAttributes(const char* lpFileName, uint32 dwFileAttributes)
 #if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED)
 #undef AZ_RESTRICTED_SECTION_IMPLEMENTED
 #else
-    return SetFileAttributes(lpFileName, dwFileAttributes) != 0;
+    AZStd::wstring lpFileNameW;
+    AZStd::to_wstring(lpFileNameW, lpFileName);
+    return SetFileAttributes(lpFileNameW.c_str(), dwFileAttributes) != 0;
 #endif
 }
 
diff --git a/Code/Legacy/CrySystem/ConsoleHelpGen.cpp b/Code/Legacy/CrySystem/ConsoleHelpGen.cpp
index ff86577258..661487a299 100644
--- a/Code/Legacy/CrySystem/ConsoleHelpGen.cpp
+++ b/Code/Legacy/CrySystem/ConsoleHelpGen.cpp
@@ -6,13 +6,13 @@
  *
  */
 
+#if defined(WIN32) || defined(WIN64)
 
 #include "CrySystem_precompiled.h"
 
-#if defined(WIN32) || defined(WIN64)
-
 #include "ConsoleHelpGen.h"
 #include "System.h"
+#include 
 
 
 
@@ -132,7 +132,7 @@ void CConsoleHelpGen::LogVersion(FILE* f) const
     char s[1024];
 
     {
-        GetModuleFileName(NULL, s, sizeof(s));
+        AZ::Utils::GetExecutablePath(s, 1024);
 
         char fdir[_MAX_PATH];
         char fdrive[_MAX_PATH];
diff --git a/Code/Legacy/CrySystem/DebugCallStack.cpp b/Code/Legacy/CrySystem/DebugCallStack.cpp
index c5d932429c..289d4070ff 100644
--- a/Code/Legacy/CrySystem/DebugCallStack.cpp
+++ b/Code/Legacy/CrySystem/DebugCallStack.cpp
@@ -18,6 +18,7 @@
 
 #include 
 #include 
+#include 
 
 #define VS_VERSION_INFO                 1
 #define IDD_CRITICAL_ERROR              101
@@ -400,7 +401,11 @@ void DebugCallStack::LogExceptionInfo(EXCEPTION_POINTERS* pex)
             timeStamp = tempBuffer;
 
             AZStd::string backupFileName = backupPath + timeStamp + " error.log";
-            CopyFile(fileName.c_str(), backupFileName.c_str(), true);
+            AZStd::wstring fileNameW;
+            AZStd::to_wstring(fileNameW, fileName.c_str());
+            AZStd::wstring backupFileNameW;
+            AZStd::to_wstring(backupFileNameW, backupFileName.c_str());
+            CopyFileW(fileNameW.c_str(), backupFileNameW.c_str(), true);
         }
     }
 
@@ -594,7 +599,11 @@ void DebugCallStack::LogExceptionInfo(EXCEPTION_POINTERS* pex)
                 }
 
                 AZStd::string backupFileName = backupPath + timeStamp + " error.dmp";
-                CopyFile(fileName.c_str(), backupFileName.c_str(), true);
+                AZStd::wstring fileNameW;
+                AZStd::to_wstring(fileNameW, fileName.c_str());
+                AZStd::wstring backupFileNameW;
+                AZStd::to_wstring(backupFileNameW, backupFileName.c_str());
+                CopyFileW(fileNameW.c_str(), backupFileNameW.c_str(), true);
             }
 
             CryEngineExceptionFilterMiniDump(pex, fileName.c_str(), mdumpValue);
@@ -635,11 +644,11 @@ void DebugCallStack::LogExceptionInfo(EXCEPTION_POINTERS* pex)
         {
             if (SaveCurrentLevel())
             {
-                MessageBox(NULL, "Level has been successfully saved!\r\nPress Ok to terminate Editor.", "Save", MB_OK);
+                MessageBoxW(NULL, L"Level has been successfully saved!\r\nPress Ok to terminate Editor.", L"Save", MB_OK);
             }
             else
             {
-                MessageBox(NULL, "Error saving level.\r\nPress Ok to terminate Editor.", "Save", MB_OK | MB_ICONWARNING);
+                MessageBoxW(NULL, L"Error saving level.\r\nPress Ok to terminate Editor.", L"Save", MB_OK | MB_ICONWARNING);
             }
         }
     }
@@ -855,7 +864,7 @@ void DebugCallStack::GetProcNameForAddr(void* addr, AZStd::string& procName, voi
 AZStd::string DebugCallStack::GetCurrentFilename()
 {
     char fullpath[MAX_PATH_LENGTH + 1];
-    GetModuleFileName(NULL, fullpath, MAX_PATH_LENGTH);
+    AZ::Utils::GetExecutablePath(fullpath, MAX_PATH_LENGTH);
     return fullpath;
 }
 
diff --git a/Code/Legacy/CrySystem/IDebugCallStack.cpp b/Code/Legacy/CrySystem/IDebugCallStack.cpp
index ff43f6e56f..bee43b237b 100644
--- a/Code/Legacy/CrySystem/IDebugCallStack.cpp
+++ b/Code/Legacy/CrySystem/IDebugCallStack.cpp
@@ -187,7 +187,7 @@ AZ_PUSH_DISABLE_WARNING(4996, "-Wunknown-warning-option")
     azstrcat(str, length, "\n");
 
 #if AZ_LEGACY_CRYSYSTEM_TRAIT_DEBUGCALLSTACK_APPEND_MODULENAME
-    GetModuleFileNameA(NULL, s, sizeof(s));
+    AZ::Utils::GetExecutablePath(s, sizeof(s));
     
     // Log EXE filename only if possible (not full EXE path which could contain sensitive info)
     AZStd::string exeName;
diff --git a/Code/Legacy/CrySystem/LocalizedStringManager.cpp b/Code/Legacy/CrySystem/LocalizedStringManager.cpp
index e3ccb22f88..42bdb3afef 100644
--- a/Code/Legacy/CrySystem/LocalizedStringManager.cpp
+++ b/Code/Legacy/CrySystem/LocalizedStringManager.cpp
@@ -25,6 +25,7 @@
 
 #include 
 #include 
+#include 
 
 #define MAX_CELL_COUNT 32
 
@@ -2329,12 +2330,11 @@ bool CLocalizedStringsManager::GetSubtitle(const char* sKeyOrLabel, AZStd::strin
     }
 }
 
-template
-void InternalFormatStringMessage(StringClass& outString, const StringClass& sString, const CharType** sParams, int nParams)
+void InternalFormatStringMessage(AZStd::string& outString, const AZStd::string& sString, const char** sParams, int nParams)
 {
-    static const CharType token = (CharType) '%';
-    static const CharType tokens1[2] = { token, (CharType) '\0' };
-    static const CharType tokens2[3] = { token, token, (CharType) '\0' };
+    static const char token = '%';
+    static const char tokens1[2] = { token, '\0' };
+    static const char tokens2[3] = { token, token, '\0' };
 
     int maxArgUsed = 0;
     int lastPos = 0;
@@ -2342,8 +2342,8 @@ void InternalFormatStringMessage(StringClass& outString, const StringClass& sStr
     const int sourceLen = sString.length();
     while (true)
     {
-        int foundPos = sString.find(token, curPos);
-        if (foundPos != string::npos)
+        auto foundPos = sString.find(token, curPos);
+        if (foundPos != AZStd::string::npos)
         {
             if (foundPos + 1 < sourceLen)
             {
@@ -2360,8 +2360,8 @@ void InternalFormatStringMessage(StringClass& outString, const StringClass& sStr
                     }
                     else
                     {
-                        StringClass tmp (sString);
-                        tmp.replace(tokens1, tokens2);
+                        AZStd::string tmp(sString);
+                        AZ::StringFunc::Replace(tmp, tokens1, tokens2);
                         if constexpr (sizeof(*tmp.c_str()) == sizeof(char))
                         {
                             CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "Parameter for argument %d is missing. [%s]", nArg + 1, (const char*)tmp.c_str());
@@ -2391,11 +2391,10 @@ void InternalFormatStringMessage(StringClass& outString, const StringClass& sStr
     }
 }
 
-template
-void InternalFormatStringMessage(StringClass& outString, const StringClass& sString, const CharType* param1, const CharType* param2 = 0, const CharType* param3 = 0, const CharType* param4 = 0)
+void InternalFormatStringMessage(AZStd::string& outString, const AZStd::string& sString, const char* param1, const char* param2 = 0, const char* param3 = 0, const char* param4 = 0)
 {
     static const int MAX_PARAMS = 4;
-    const CharType* params[MAX_PARAMS] = { param1, param2, param3, param4 };
+    const char* params[MAX_PARAMS] = { param1, param2, param3, param4 };
     int nParams = 0;
     while (nParams < MAX_PARAMS && params[nParams])
     {
@@ -2677,7 +2676,7 @@ void CLocalizedStringsManager::LocalizeTime(time_t t, bool bMakeLocalTime, bool
         localtime_s(&thetime, &t);
         t = gEnv->pTimer->DateToSecondsUTC(thetime);
     }
-    outTimeString.resize(0);
+    outTimeString.clear();
     LCID lcID = g_currentLanguageID.lcID ? g_currentLanguageID.lcID : LOCALE_USER_DEFAULT;
     DWORD flags = bShowSeconds == false ? TIME_NOSECONDS : 0;
     SYSTEMTIME systemTime;
@@ -2689,7 +2688,7 @@ void CLocalizedStringsManager::LocalizeTime(time_t t, bool bMakeLocalTime, bool
         AZStd::fixed_wstring<256> tmpString;
         tmpString.resize(len);
         ::GetTimeFormatW(lcID, flags, &systemTime, 0, (wchar_t*) tmpString.c_str(), len);
-        Unicode::Convert(outTimeString, tmpString);
+        AZStd::to_string(outTimeString, tmpString.data());
     }
 }
 
@@ -2719,7 +2718,7 @@ void CLocalizedStringsManager::LocalizeDate(time_t t, bool bMakeLocalTime, bool
             tmpString.resize(len);
             ::GetDateFormatW(lcID, 0, &systemTime, L"ddd", (wchar_t*) tmpString.c_str(), len);
             AZStd::string utf8;
-            Unicode::Convert(utf8, tmpString);
+            AZStd::to_string(utf8, tmpString.data());
             outDateString.append(utf8);
             outDateString.append(" ");
         }
@@ -2732,7 +2731,7 @@ void CLocalizedStringsManager::LocalizeDate(time_t t, bool bMakeLocalTime, bool
         tmpString.resize(len);
         ::GetDateFormatW(lcID, flags, &systemTime, 0, (wchar_t*) tmpString.c_str(), len);
         AZStd::string utf8;
-        Unicode::Convert(utf8, tmpString);
+        AZStd::to_string(utf8, tmpString.data());
         outDateString.append(utf8);
     }
 }
diff --git a/Code/Legacy/CrySystem/Log.cpp b/Code/Legacy/CrySystem/Log.cpp
index c23ed6e264..6ee6af6c22 100644
--- a/Code/Legacy/CrySystem/Log.cpp
+++ b/Code/Legacy/CrySystem/Log.cpp
@@ -18,7 +18,6 @@
 #include 
 #include "System.h"
 #include "CryPath.h"                    // PathUtil::ReplaceExtension()
-#include "UnicodeFunctions.h"
 
 #include 
 #include 
@@ -1052,13 +1051,7 @@ void CLog::LogStringToFile(const char* szString, ELogType logType, bool bAdd, [[
 #if !defined(_RELEASE)
     if (queueState == MessageQueueState::NotQueued)
     {
-        // Note: OutputDebugString(A) only accepts current ANSI code-page, and the W variant will call the A variant internally.
-        // Here we replace non-ASCII characters with '?', which is the same as OutputDebugStringW will do for non-ANSI.
-        // Thus, we discard slightly more characters (ie, those inside the current ANSI code-page, but outside ASCII).
-        // In exchange, we save double-converting that would have happened otherwise (UTF-8 -> UTF-16 -> ANSI).
-        LogStringType asciiString;
-        Unicode::ConvertSafe(asciiString, tempString);
-        OutputDebugString(asciiString.c_str());
+        AZ::Debug::Platform::OutputToDebugger(nullptr, tempString.c_str());
     }
 
     if (!bIsMainThread)
@@ -1224,8 +1217,8 @@ void CLog::CreateBackupFile() const
     AZStd::string sFileWithoutExt = PathUtil::GetFileName(m_szFilename);
 
     {
-        assert(::strstr(sFileWithoutExt, ":") == 0);
-        assert(::strstr(sFileWithoutExt, "\\") == 0);
+        assert(::strstr(sFileWithoutExt.c_str(), ":") == 0);
+        assert(::strstr(sFileWithoutExt.c_str(), "\\") == 0);
     }
 
     PathUtil::RemoveExtension(sFileWithoutExt);
@@ -1255,11 +1248,9 @@ void CLog::CreateBackupFile() const
 
                     if (sName.find("BackupNameAttachment=") == AZStd::string::npos)
                     {
-#ifdef WIN32
-                        OutputDebugString("Log::CreateBackupFile ERROR '");
-                        OutputDebugString(sName.c_str());
-                        OutputDebugString("' not recognized \n");
-#endif
+                        AZ::Debug::Platform::OutputToDebugger("CrySystem Log", "Log::CreateBackupFile ERROR '");
+                        AZ::Debug::Platform::OutputToDebugger(nullptr, sName.c_str());
+                        AZ::Debug::Platform::OutputToDebugger(nullptr, "' not recognized \n");
                         assert(0);      // broken log file? - first line should include this name - written by LogVersion()
                         return;
                     }
diff --git a/Code/Legacy/CrySystem/System.cpp b/Code/Legacy/CrySystem/System.cpp
index 9c2e1b1129..8c42c4a027 100644
--- a/Code/Legacy/CrySystem/System.cpp
+++ b/Code/Legacy/CrySystem/System.cpp
@@ -1148,7 +1148,7 @@ void CSystem::WarningV(EValidatorModule module, EValidatorSeverity severity, int
     if (sModuleFilter && *sModuleFilter != 0)
     {
         const char* sModule = ValidatorModuleToString(module);
-        if (strlen(sModule) > 1 || CryStringUtils::stristr(sModule, sModuleFilter) == 0)
+        if (strlen(sModule) > 1 || AZ::StringFunc::Find(sModule, sModuleFilter) == AZStd::string::npos)
         {
             // Filter out warnings from other modules.
             return;
@@ -1215,13 +1215,13 @@ void CSystem::GetLocalizedPath(const char* sLanguage, AZStd::string& sLocalizedP
     }
     else
     {
-    if (sLocalizationFolder.compareNoCase("Languages") != 0)
-    {
-        sLocalizedPath = sLocalizationFolder + "/" + sLanguage + "_xml.pak";
-    }
-    else
-    {
-        sLocalizedPath = AZStd::string("Localized/") + sLanguage + "_xml.pak";
+        if (AZ::StringFunc::Equal(sLocalizationFolder, "Languages", false))
+        {
+            sLocalizedPath = sLocalizationFolder + "/" + sLanguage + "_xml.pak";
+        }
+        else
+        {
+            sLocalizedPath = AZStd::string("Localized/") + sLanguage + "_xml.pak";
         }
     }
 }
@@ -1233,7 +1233,7 @@ void CSystem::GetLocalizedAudioPath(const char* sLanguage, AZStd::string& sLocal
     AZStd::string sLocalizationFolder(PathUtil::GetLocalizationFolder());
     sLocalizationFolder.pop_back();
 
-    if (sLocalizationFolder.compareNoCase("Languages") != 0)
+    if (AZ::StringFunc::Equal(sLocalizationFolder, "Languages", false))
     {
         sLocalizedPath = sLocalizationFolder + "/" + sLanguage + ".pak";
     }
diff --git a/Code/Legacy/CrySystem/SystemCFG.cpp b/Code/Legacy/CrySystem/SystemCFG.cpp
index 062713c015..4d193c72a5 100644
--- a/Code/Legacy/CrySystem/SystemCFG.cpp
+++ b/Code/Legacy/CrySystem/SystemCFG.cpp
@@ -114,20 +114,22 @@ void CSystem::QueryVersionInfo()
 
     char ver[1024 * 8];
 
-    GetModuleFileName(NULL, moduleName, _MAX_PATH);  //retrieves the PATH for the current module
+    AZ::Utils::GetExecutablePath(moduleName, _MAX_PATH);  //retrieves the PATH for the current module
 
 #ifdef AZ_MONOLITHIC_BUILD
-    GetModuleFileName(NULL, moduleName, _MAX_PATH);  //retrieves the PATH for the current module
+    AZ::Utils::GetExecutablePath(moduleName, _MAX_PATH);  //retrieves the PATH for the current module
 #else // AZ_MONOLITHIC_BUILD
     azstrcpy(moduleName, AZ_ARRAY_SIZE(moduleName), "CrySystem.dll"); // we want to version from the system dll
 #endif // AZ_MONOLITHIC_BUILD
 
-    int verSize = GetFileVersionInfoSize(moduleName, &dwHandle);
+    AZStd::wstring moduleNameW;
+    AZStd::to_wstring(moduleNameW, moduleName);
+    int verSize = GetFileVersionInfoSizeW(moduleNameW.c_str(), &dwHandle);
     if (verSize > 0)
     {
-        GetFileVersionInfo(moduleName, dwHandle, 1024 * 8, ver);
+        GetFileVersionInfoW(moduleNameW.c_str(), dwHandle, 1024 * 8, ver);
         VS_FIXEDFILEINFO* vinfo;
-        VerQueryValue(ver, "\\", (void**)&vinfo, &len);
+        VerQueryValueW(ver, L"\\", (void**)&vinfo, &len);
 
         const uint32 verIndices[4] = {0, 1, 2, 3};
         m_fileVersion.v[verIndices[0]] = m_productVersion.v[verIndices[0]] = vinfo->dwFileVersionLS & 0xFFFF;
@@ -143,14 +145,14 @@ void CSystem::QueryVersionInfo()
         }* lpTranslate;
 
         UINT count = 0;
-        char path[256];
+        wchar_t path[256];
         char* version = NULL;
 
-        VerQueryValue(ver, "\\VarFileInfo\\Translation", (LPVOID*)&lpTranslate, &count);
+        VerQueryValueW(ver, L"\\VarFileInfo\\Translation", (LPVOID*)&lpTranslate, &count);
         if (lpTranslate != NULL)
         {
-            azsnprintf(path, sizeof(path), "\\StringFileInfo\\%04x%04x\\InternalName", lpTranslate[0].wLanguage, lpTranslate[0].wCodePage);
-            VerQueryValue(ver, path, (LPVOID*)&version, &count);
+            azsnwprintf(path, sizeof(path), L"\\StringFileInfo\\%04x%04x\\InternalName", lpTranslate[0].wLanguage, lpTranslate[0].wCodePage);
+            VerQueryValueW(ver, path, (LPVOID*)&version, &count);
             if (version)
             {
                 m_buildVersion.Set(version);
@@ -211,7 +213,7 @@ void CSystem::LogVersion()
     CryLogAlways("Running 64 bit Mac version");
 #endif
 #if AZ_LEGACY_CRYSYSTEM_TRAIT_SYSTEMCFG_MODULENAME
-    GetModuleFileName(NULL, s, sizeof(s));
+    AZ::Utils::GetExecutablePath(s, sizeof(s));
 
     // Log EXE filename only if possible (not full EXE path which could contain sensitive info)
     AZStd::string exeName;
@@ -448,25 +450,24 @@ bool CSystemConfiguration::ParseSystemConfig()
         }
 
         AZStd::string strLine = s;
+        AZ::StringFunc::TrimWhiteSpace(strLine, true, true);
 
         // detect groups e.g. "[General]"   should set strGroup="General"
         {
-            AZStd::string strTrimmedLine(RemoveWhiteSpaces(strLine));
-            size_t size = strTrimmedLine.size();
+            size_t size = strLine.size();
 
             if (size >= 3)
             {
-                if (strTrimmedLine[0] == '[' && strTrimmedLine[size - 1] == ']')       // currently no comments are allowed to be behind groups
+                if (strLine[0] == '[' && strLine[size - 1] == ']')  // currently no comments are allowed to be behind groups
                 {
-                    strGroup = &strTrimmedLine[1];
-                    strGroup.resize(size - 2);                                  // remove [ and ]
+                    strGroup = &strLine[1];
+                    strGroup.resize(size - 2);                      // remove [ and ]
                     continue;                                       // next line
                 }
             }
         }
 
         //trim all whitespace characters at the beginning and the end of the current line and store its size
-        AZ::StringFunc::TrimWhiteSpace(strLine, true, true);
         size_t strLineSize = strLine.size();
 
         //skip comments, comments start with ";" or "--" but may have preceding whitespace characters
@@ -491,8 +492,9 @@ bool CSystemConfiguration::ParseSystemConfig()
         AZStd::string::size_type posEq(strLine.find("=", 0));
         if (AZStd::string::npos != posEq)
         {
-            AZStd::string stemp(strLine, 0, posEq);
-            AZStd::string strKey(RemoveWhiteSpaces(stemp));
+            AZStd::string stemp;
+            AZStd::string strKey(strLine, 0, posEq);
+            AZ::StringFunc::TrimWhiteSpace(strKey, true, true);
 
             {
                 // extract value
@@ -507,8 +509,8 @@ bool CSystemConfiguration::ParseSystemConfig()
                 }
                 else
                 {
-                    AZStd::string strTmp(strLine, posEq + 1, strLine.size() - (posEq + 1));
-                    strValue = RemoveWhiteSpaces(strTmp);
+                    strValue = AZStd::string(strLine, posEq + 1, strLine.size() - (posEq + 1));
+                    AZ::StringFunc::TrimWhiteSpace(strValue, true, true);
                 }
 
                 {
diff --git a/Code/Legacy/CrySystem/SystemCFG.h b/Code/Legacy/CrySystem/SystemCFG.h
index cfaefd2e45..7ec6f1231b 100644
--- a/Code/Legacy/CrySystem/SystemCFG.h
+++ b/Code/Legacy/CrySystem/SystemCFG.h
@@ -25,12 +25,6 @@ public:
     CSystemConfiguration(const AZStd::string& strSysConfigFilePath, CSystem* pSystem, ILoadConfigurationEntrySink* pSink, bool warnIfMissing = true);
     ~CSystemConfiguration();
 
-    AZStd::string RemoveWhiteSpaces(AZStd::string& s)
-    {
-        s.Trim();
-        return s;
-    }
-
     bool IsError() const { return m_bError; }
 
 private: // ----------------------------------------
diff --git a/Code/Legacy/CrySystem/SystemInit.cpp b/Code/Legacy/CrySystem/SystemInit.cpp
index ae177a9974..0c1411e649 100644
--- a/Code/Legacy/CrySystem/SystemInit.cpp
+++ b/Code/Legacy/CrySystem/SystemInit.cpp
@@ -451,7 +451,7 @@ AZStd::unique_ptr CSystem::LoadDLL(const char* dllName)
     //////////////////////////////////////////////////////////////////////////
     // After loading DLL initialize it by calling ModuleInitISystem
     //////////////////////////////////////////////////////////////////////////
-    string moduleName = PathUtil::GetFileName(dllName);
+    AZStd::string moduleName = PathUtil::GetFileName(dllName);
 
     typedef void*(*PtrFunc_ModuleInitISystem)(ISystem* pSystem, const char* moduleName);
     PtrFunc_ModuleInitISystem pfnModuleInitISystem = handle->GetFunction(DLL_MODULE_INIT_ISYSTEM);
@@ -523,7 +523,7 @@ void CSystem::ShutdownModuleLibraries()
 /////////////////////////////////////////////////////////////////////////////////
 
 #if defined(WIN32) || defined(WIN64)
-wstring GetErrorStringUnsupportedGPU(const char* gpuName, unsigned int gpuVendorId, unsigned int gpuDeviceId)
+AZStd::wstring GetErrorStringUnsupportedGPU(const char* gpuName, unsigned int gpuVendorId, unsigned int gpuDeviceId)
 {
     const size_t fullLangID = (size_t) GetKeyboardLayout(0);
     const size_t primLangID = fullLangID & 0x3FF;
@@ -877,19 +877,19 @@ void CSystem::InitLocalization()
         languageID = ILocalizationManager::EPlatformIndependentLanguageID::ePILID_English_US;
     }
 
-    string language = m_pLocalizationManager->LangNameFromPILID(languageID);
+    AZStd::string language = m_pLocalizationManager->LangNameFromPILID(languageID);
     m_pLocalizationManager->SetLanguage(language.c_str());
     if (m_pLocalizationManager->GetLocalizationFormat() == 1)
     {
-        string translationsListXML = LOCALIZATION_TRANSLATIONS_LIST_FILE_NAME;
-        m_pLocalizationManager->InitLocalizationData(translationsListXML);
+        AZStd::string translationsListXML = LOCALIZATION_TRANSLATIONS_LIST_FILE_NAME;
+        m_pLocalizationManager->InitLocalizationData(translationsListXML.c_str());
 
         m_pLocalizationManager->LoadAllLocalizationData();
     }
     else
     {
         // if the language value cannot be found, let's default to the english pak
-        OpenLanguagePak(language);
+        OpenLanguagePak(language.c_str());
     }
 
     if (auto console = AZ::Interface::Get(); console != nullptr)
@@ -907,7 +907,7 @@ void CSystem::InitLocalization()
             }
         }
     }
-    OpenLanguageAudioPak(language);
+    OpenLanguageAudioPak(language.c_str());
 }
 
 void CSystem::OpenBasicPaks()
@@ -971,10 +971,10 @@ void CSystem::OpenLanguagePak(const char* sLanguage)
     // Initialize languages.
 
     // Omit the trailing slash!
-    string sLocalizationFolder = PathUtil::GetLocalizationFolder();
+    AZStd::string sLocalizationFolder = PathUtil::GetLocalizationFolder();
 
     // load xml pak with full filenames to perform wildcard searches.
-    string sLocalizedPath;
+    AZStd::string sLocalizedPath;
     GetLocalizedPath(sLanguage, sLocalizedPath);
     if (!m_env.pCryPak->OpenPacks({ sLocalizationFolder.c_str(), sLocalizationFolder.size() }, { sLocalizedPath.c_str(), sLocalizedPath.size() }, 0))
     {
@@ -1001,15 +1001,15 @@ void CSystem::OpenLanguageAudioPak([[maybe_unused]] const char* sLanguage)
     int nPakFlags = 0;
 
     // Omit the trailing slash!
-    string sLocalizationFolder(string().assign(PathUtil::GetLocalizationFolder(), 0, PathUtil::GetLocalizationFolder().size() - 1));
+    AZStd::string sLocalizationFolder(AZStd::string().assign(PathUtil::GetLocalizationFolder(), 0, PathUtil::GetLocalizationFolder().size() - 1));
 
-    if (sLocalizationFolder.compareNoCase("Languages") == 0)
+    if (!AZ::StringFunc::Equal(sLocalizationFolder, "Languages", false))
     {
         sLocalizationFolder = "@assets@";
     }
 
     // load localized pak with crc32 filenames on consoles to save memory.
-    string sLocalizedPath = "loc.pak";
+    AZStd::string sLocalizedPath = "loc.pak";
 
     if (!m_env.pCryPak->OpenPacks(sLocalizationFolder.c_str(), sLocalizedPath.c_str(), nPakFlags))
     {
@@ -1019,10 +1019,10 @@ void CSystem::OpenLanguageAudioPak([[maybe_unused]] const char* sLanguage)
 }
 
 
-string GetUniqueLogFileName(string logFileName)
+AZStd::string GetUniqueLogFileName(AZStd::string logFileName)
 {
-    string logFileNamePrefix = logFileName;
-    if ((logFileNamePrefix[0] != '@') && (AzFramework::StringFunc::Path::IsRelative(logFileNamePrefix)))
+    AZStd::string logFileNamePrefix = logFileName;
+    if ((logFileNamePrefix[0] != '@') && (AzFramework::StringFunc::Path::IsRelative(logFileNamePrefix.c_str())))
     {
         logFileNamePrefix = "@log@/";
         logFileNamePrefix += logFileName;
@@ -1038,9 +1038,9 @@ string GetUniqueLogFileName(string logFileName)
         return logFileNamePrefix;
     }
 
-    string logFileExtension;
+    AZStd::string logFileExtension;
     size_t extensionIndex = logFileName.find_last_of('.');
-    if (extensionIndex != string::npos)
+    if (extensionIndex != AZStd::string::npos)
     {
         logFileExtension = logFileName.substr(extensionIndex, logFileName.length() - extensionIndex);
         logFileNamePrefix = logFileName.substr(0, extensionIndex);
@@ -1214,7 +1214,7 @@ bool CSystem::Init(const SSystemInitParams& startupParams)
 
         osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
 AZ_PUSH_DISABLE_WARNING(4996, "-Wunknown-warning-option")
-        GetVersionExA(&osvi);
+        GetVersionExW(&osvi);
 AZ_POP_DISABLE_WARNING
 
         bool bIsWindowsXPorLater = osvi.dwMajorVersion > 5 || (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion >= 1);
@@ -1309,7 +1309,7 @@ AZ_POP_DISABLE_WARNING
             }
             else if (startupParams.sLogFileName)    //otherwise see if the startup params has a log file name, if so use it
             {
-                const string sUniqueLogFileName = GetUniqueLogFileName(startupParams.sLogFileName);
+                const AZStd::string sUniqueLogFileName = GetUniqueLogFileName(startupParams.sLogFileName);
                 m_env.pLog->SetFileName(sUniqueLogFileName.c_str(), startupParams.autoBackupLogs);
             }
             else//use the default log name
@@ -1657,20 +1657,20 @@ static void LoadConfigurationCmd(IConsoleCmdArgs* pParams)
         return;
     }
 
-    GetISystem()->LoadConfiguration(string("Config/") + pParams->GetArg(1));
+    GetISystem()->LoadConfiguration((AZStd::string("Config/") + pParams->GetArg(1)).c_str());
 }
 
 
 // --------------------------------------------------------------------------------------------------------------------------
 
-static string ConcatPath(const char* szPart1, const char* szPart2)
+static AZStd::string ConcatPath(const char* szPart1, const char* szPart2)
 {
     if (szPart1[0] == 0)
     {
         return szPart2;
     }
 
-    string ret;
+    AZStd::string ret;
 
     ret.reserve(strlen(szPart1) + 1 + strlen(szPart2));
 
@@ -2134,12 +2134,12 @@ void CSystem::CreateAudioVars()
 }
 
 /////////////////////////////////////////////////////////////////////
-void CSystem::AddCVarGroupDirectory(const string& sPath)
+void CSystem::AddCVarGroupDirectory(const AZStd::string& sPath)
 {
     CryLog("creating CVarGroups from directory '%s' ...", sPath.c_str());
     INDENT_LOG_DURING_SCOPE();
 
-    AZ::IO::ArchiveFileIterator handle = gEnv->pCryPak->FindFirst(ConcatPath(sPath, "*.cfg").c_str());
+    AZ::IO::ArchiveFileIterator handle = gEnv->pCryPak->FindFirst(ConcatPath(sPath.c_str(), "*.cfg").c_str());
 
     if (!handle)
     {
@@ -2152,16 +2152,9 @@ void CSystem::AddCVarGroupDirectory(const string& sPath)
         {
             if (handle.m_filename != "." && handle.m_filename != "..")
             {
-                AddCVarGroupDirectory(ConcatPath(sPath, handle.m_filename.data()));
+                AddCVarGroupDirectory(ConcatPath(sPath.c_str(), handle.m_filename.data()));
             }
         }
-        else
-        {
-            string sFilePath = ConcatPath(sPath, handle.m_filename.data());
-
-            string sCVarName = sFilePath;
-            PathUtil::RemoveExtension(sCVarName);
-        }
     } while (handle = gEnv->pCryPak->FindNext(handle));
 
     gEnv->pCryPak->FindClose(handle);
diff --git a/Code/Legacy/CrySystem/SystemWin32.cpp b/Code/Legacy/CrySystem/SystemWin32.cpp
index a4be0e5054..9fd01f1905 100644
--- a/Code/Legacy/CrySystem/SystemWin32.cpp
+++ b/Code/Legacy/CrySystem/SystemWin32.cpp
@@ -15,7 +15,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include  // for AZ_MAX_PATH_LEN
 #include 
@@ -127,7 +126,7 @@ const char* CSystem::GetUserName()
     DWORD dwSize = iNameBufferSize;
     wchar_t nameW[iNameBufferSize];
     ::GetUserNameW(nameW, &dwSize);
-    azstrcpy(szNameBuffer, CryStringUtils::WStrToUTF8(nameW));
+    AZStd::to_string(szNameBuffer, iNameBufferSize, nameW, dwSize);
     return szNameBuffer;
 #else
 #if defined(LINUX)
@@ -171,12 +170,12 @@ int CSystem::GetApplicationInstance()
     // this code below essentially "locks" an instance of the USER folder to a specific running application
     if (m_iApplicationInstance == -1)
     {
-        string suffix;
+        AZStd::wstring suffix;
         for (int instance = 0;; ++instance)
         {
-            suffix.Format("(%d)", instance);
+            suffix = AZStd::wstring::format(L"LumberyardApplication(%d)", instance);
 
-            CreateMutex(NULL, TRUE, "LumberyardApplication" + suffix);
+            CreateMutexW(NULL, TRUE, suffix.c_str());
             // search for duplicates
             if (GetLastError() != ERROR_ALREADY_EXISTS)
             {
@@ -195,13 +194,13 @@ int CSystem::GetApplicationInstance()
 int CSystem::GetApplicationLogInstance([[maybe_unused]] const char* logFilePath)
 {
 #if AZ_TRAIT_OS_USE_WINDOWS_MUTEX
-    string suffix;
+    AZStd::wstring suffix;
     int instance = 0;
     for (;; ++instance)
     {
-        suffix.Format("(%d)", instance);
+        suffix = AZStd::wstring::format(L"%s(%d)", logFilePath, instance);
 
-        CreateMutex(NULL, TRUE, logFilePath + suffix);
+        CreateMutexW(NULL, TRUE, suffix.c_str());
         if (GetLastError() != ERROR_ALREADY_EXISTS)
         {
             break;
@@ -218,7 +217,7 @@ struct CryDbgModule
 {
     HANDLE heap;
     WIN_HMODULE handle;
-    string name;
+    AZStd::string name;
     DWORD dwSize;
 };
 
@@ -343,12 +342,15 @@ void CSystem::FatalError(const char* format, ...)
     assert(szBuffer[0] >= ' ');
     //  strcpy(szBuffer,szBuffer+1);    // remove verbosity tag since it is not supported by ::MessageBox
 
-    OutputDebugString(szBuffer);
+    AZ::Debug::Platform::OutputToDebugger("CrySystem", szBuffer);
+
 #ifdef WIN32
     OnFatalError(szBuffer);
     if (!g_cvars.sys_no_crash_dialog)
     {
-        ::MessageBox(NULL, szBuffer, "Open 3D Engine Error", MB_OK | MB_ICONERROR | MB_SYSTEMMODAL);
+        AZStd::wstring szBufferW;
+        AZStd::to_wstring(szBufferW, szBuffer);
+        ::MessageBoxW(NULL, szBufferW.c_str(), L"Open 3D Engine Error", MB_OK | MB_ICONERROR | MB_SYSTEMMODAL);
     }
 
     // Dump callstack.
@@ -461,20 +463,20 @@ bool CSystem::ReLaunchMediaCenter()
     }
 
     // Get the path to Media Center
-    char szExpandedPath[AZ_MAX_PATH_LEN];
-    if (!ExpandEnvironmentStrings("%SystemRoot%\\ehome\\ehshell.exe", szExpandedPath, AZ_MAX_PATH_LEN))
+    wchar_t szExpandedPath[AZ_MAX_PATH_LEN];
+    if (!ExpandEnvironmentStringsW(L"%SystemRoot%\\ehome\\ehshell.exe", szExpandedPath, AZ_MAX_PATH_LEN))
     {
         return false;
     }
 
     // Skip if ehshell.exe doesn't exist
-    if (GetFileAttributes(szExpandedPath) == 0xFFFFFFFF)
+    if (GetFileAttributesW(szExpandedPath) == 0xFFFFFFFF)
     {
         return false;
     }
 
     // Launch ehshell.exe
-    INT_PTR result = (INT_PTR)ShellExecute(NULL, TEXT("open"), szExpandedPath, NULL, NULL, SW_SHOWNORMAL);
+    INT_PTR result = (INT_PTR)ShellExecuteW(NULL, TEXT("open"), szExpandedPath, NULL, NULL, SW_SHOWNORMAL);
     return (result > 32);
 }
 #else
@@ -491,7 +493,7 @@ bool CSystem::GetWinGameFolder(char* szMyDocumentsPath, int maxPathSize)
     bool bSucceeded  = false;
     // check Vista and later OS first
 
-    HMODULE shell32 = LoadLibraryA("Shell32.dll");
+    HMODULE shell32 = LoadLibraryW(L"Shell32.dll");
     if (shell32)
     {
         typedef long (__stdcall * T_SHGetKnownFolderPath)(REFKNOWNFOLDERID rfid, unsigned long dwFlags, void* hToken, wchar_t** ppszPath);
@@ -505,7 +507,7 @@ bool CSystem::GetWinGameFolder(char* szMyDocumentsPath, int maxPathSize)
             if (bSucceeded)
             {
                 // Convert from UNICODE to UTF-8
-                azstrcpy(szMyDocumentsPath, maxPathSize, CryStringUtils::WStrToUTF8(wMyDocumentsPath));
+                AZStd::to_string(szMyDocumentsPath, maxPathSize, wMyDocumentsPath);
                 CoTaskMemFree(wMyDocumentsPath);
             }
         }
@@ -519,7 +521,7 @@ bool CSystem::GetWinGameFolder(char* szMyDocumentsPath, int maxPathSize)
         bSucceeded = SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_PERSONAL | CSIDL_FLAG_CREATE, NULL, 0, wMyDocumentsPath));
         if (bSucceeded)
         {
-            azstrcpy(szMyDocumentsPath, maxPathSize, CryStringUtils::WStrToUTF8(wMyDocumentsPath));
+            AZStd::to_string(szMyDocumentsPath, maxPathSize, wMyDocumentsPath);
         }
     }
 
@@ -547,7 +549,7 @@ void CSystem::DetectGameFolderAccessRights()
     BOOL bAccessStatus = FALSE;
 
     // Get a pointer to the existing DACL.
-    dwRes = GetNamedSecurityInfo(".", SE_FILE_OBJECT,
+    dwRes = GetNamedSecurityInfoW(L".", SE_FILE_OBJECT,
             DACL_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION,
             NULL, NULL, &pDACL, NULL, &pSD);
 
diff --git a/Code/Legacy/CrySystem/WindowsErrorReporting.cpp b/Code/Legacy/CrySystem/WindowsErrorReporting.cpp
index a02f55b69e..d467923c74 100644
--- a/Code/Legacy/CrySystem/WindowsErrorReporting.cpp
+++ b/Code/Legacy/CrySystem/WindowsErrorReporting.cpp
@@ -66,7 +66,9 @@ LONG WINAPI CryEngineExceptionFilterMiniDump(struct _EXCEPTION_POINTERS* pExcept
         return EXCEPTION_CONTINUE_SEARCH;
     }
 
-    HANDLE hFile = ::CreateFile(szDumpPath, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+    AZStd::wstring szDumpPathW;
+    AZStd::to_wstring(szDumpPathW, szDumpPath);
+    HANDLE hFile = ::CreateFileW(szDumpPathW.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
     if (hFile == INVALID_HANDLE_VALUE)
     {
         CryLogAlways("Failed to record DMP file: could not open file '%s' for writing - error code: %d", szDumpPath, GetLastError());
diff --git a/Code/Legacy/CrySystem/XConsole.cpp b/Code/Legacy/CrySystem/XConsole.cpp
index a69d86e8b7..f5e946be43 100644
--- a/Code/Legacy/CrySystem/XConsole.cpp
+++ b/Code/Legacy/CrySystem/XConsole.cpp
@@ -15,9 +15,6 @@
 #include "XConsoleVariable.h"
 #include "System.h"
 #include "ConsoleBatchFile.h"
-#include "StringUtils.h"
-#include "UnicodeFunctions.h"
-#include "UnicodeIterator.h"
 
 #include 
 #include 
@@ -88,11 +85,13 @@ inline int GetCharPrio(char x)
     }
 }
 // case sensitive
-inline bool less_CVar(const char* left, const char* right)
+inline bool less_CVar(const AZStd::string& left, const AZStd::string& right)
 {
+    AZStd::string_view leftView(left);
+    AZStd::string_view rightView(right);
     for (;; )
     {
-        uint32 l = GetCharPrio(*left), r = GetCharPrio(*right);
+        uint32 l = GetCharPrio(leftView.front()), r = GetCharPrio(rightView.front());
 
         if (l < r)
         {
@@ -103,13 +102,13 @@ inline bool less_CVar(const char* left, const char* right)
             return false;
         }
 
-        if (*left == 0 || *right == 0)
+        if (leftView.front() == 0 || rightView.front() == 0)
         {
             break;
         }
 
-        ++left;
-        ++right;
+        leftView.remove_prefix(1);
+        rightView.remove_prefix(1);
     }
 
     return false;
@@ -149,7 +148,7 @@ void Bind(IConsoleCmdArgs* cmdArgs)
 {
     if (cmdArgs->GetArgCount() >= 3)
     {
-        string arg;
+        AZStd::string arg;
         for (int i = 2; i < cmdArgs->GetArgCount(); ++i)
         {
             arg += cmdArgs->GetArg(i);
@@ -414,9 +413,7 @@ void CXConsole::Init(ISystem* pSystem)
 void CXConsole::LogChangeMessage(const char* name, const bool isConst, const bool isCheat, const bool isReadOnly, const bool isDeprecated,
     const char* oldValue, const char* newValue, [[maybe_unused]] const bool isProcessingGroup, const bool allowChange)
 {
-    string logMessage;
-
-    logMessage.Format
+    AZStd::string logMessage = AZStd::string::format
         ("[CVARS]: [%s] variable [%s] from [%s] to [%s]%s; Marked as%s%s%s%s",
         (allowChange) ? "CHANGED" : "IGNORED CHANGE",
         name,
@@ -452,7 +449,7 @@ void CXConsole::RegisterVar(ICVar* pCVar, ConsoleVarFunc pChangeFunc)
     bool isReadOnly = ((pCVar->GetFlags() & VF_READONLY) != 0);
     bool isDeprecated = ((pCVar->GetFlags() & VF_DEPRECATED) != 0);
 
-    ConfigVars::iterator it = m_configVars.find(CONST_TEMP_STRING(pCVar->GetName()));
+    ConfigVars::iterator it = m_configVars.find(pCVar->GetName());
     if (it != m_configVars.end())
     {
         SConfigVar& var = it->second;
@@ -906,7 +903,7 @@ void CXConsole::DumpKeyBinds(IKeyBindDumpSink* pCallback)
 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 const char* CXConsole::FindKeyBind(const char* sCmd) const
 {
-    ConsoleBindsMap::const_iterator it = m_mapBinds.find(CONST_TEMP_STRING(sCmd));
+    ConsoleBindsMap::const_iterator it = m_mapBinds.find(sCmd);
 
     if (it != m_mapBinds.end())
     {
@@ -1263,9 +1260,7 @@ bool CXConsole::ProcessInput(const AzFramework::InputChannel& inputChannel)
         if (m_nCursorPos)
         {
             const char* pCursor = m_sInputBuffer.c_str() + m_nCursorPos;
-            Unicode::CIterator pUnicode(pCursor);
-            --pUnicode; // Note: This moves back one UCS code-point, but doesn't necessarily match one displayed character (ie, combining diacritics)
-            pCursor = pUnicode.GetPosition();
+            pCursor -= Utf8::Internal::sequence_length(pCursor); // Note: This moves back one UCS code-point, but doesn't necessarily match one displayed character (ie, combining diacritics)
             m_nCursorPos = pCursor - m_sInputBuffer.c_str();
         }
         return true;
@@ -1275,9 +1270,7 @@ bool CXConsole::ProcessInput(const AzFramework::InputChannel& inputChannel)
         if (m_nCursorPos < (int)(m_sInputBuffer.length()))
         {
             const char* pCursor = m_sInputBuffer.c_str() + m_nCursorPos;
-            Unicode::CIterator pUnicode(pCursor);
-            ++pUnicode; // Note: This moves forward one UCS code-point, but doesn't necessarily match one displayed character (ie, combining diacritics)
-            pCursor = pUnicode.GetPosition();
+            pCursor += Utf8::Internal::sequence_length(pCursor); // Note: This moves forward one UCS code-point, but doesn't necessarily match one displayed character (ie, combining diacritics)
             m_nCursorPos = pCursor - m_sInputBuffer.c_str();
         }
         return true;
@@ -1446,7 +1439,7 @@ bool CXConsole::GetLineNo(const int indwLineNo, char* outszBuffer, const int ind
     {
         buf++;                          // to jump over verbosity level character
     }
-    cry_strcpy(outszBuffer, indwBufferSize, buf);
+    azstrcpy(outszBuffer, indwBufferSize, buf);
 
     return true;
 }
@@ -1558,27 +1551,27 @@ const char* CXConsole::GetFlagsString(const uint32 dwFlags)
 
     if (dwFlags & VF_READONLY)
     {
-        cry_strcat(sFlags, "READONLY, ");
+        azstrcat(sFlags, "READONLY, ");
     }
     if (dwFlags & VF_DEPRECATED)
     {
-        cry_strcat(sFlags, "DEPRECATED, ");
+        azstrcat(sFlags, "DEPRECATED, ");
     }
     if (dwFlags & VF_DUMPTODISK)
     {
-        cry_strcat(sFlags, "DUMPTODISK, ");
+        azstrcat(sFlags, "DUMPTODISK, ");
     }
     if (dwFlags & VF_REQUIRE_LEVEL_RELOAD)
     {
-        cry_strcat(sFlags, "REQUIRE_LEVEL_RELOAD, ");
+        azstrcat(sFlags, "REQUIRE_LEVEL_RELOAD, ");
     }
     if (dwFlags & VF_REQUIRE_APP_RESTART)
     {
-        cry_strcat(sFlags, "REQUIRE_APP_RESTART, ");
+        azstrcat(sFlags, "REQUIRE_APP_RESTART, ");
     }
     if (dwFlags & VF_RESTRICTEDMODE)
     {
-        cry_strcat(sFlags, "RESTRICTEDMODE, ");
+        azstrcat(sFlags, "RESTRICTEDMODE, ");
     }
 
     if (sFlags[0] != 0)
@@ -1794,7 +1787,7 @@ void CXConsole::DisplayHelp(const char* help, const char* name)
         char* start, * pos;
         for (pos = strstr((char*)help, "\n"), start = (char*)help; pos; start = ++pos)
         {
-            string s = start;
+            AZStd::string s = start;
             s.resize(pos - start);
             ConsoleLogInputResponse("    $3%s", s.c_str());
             pos = strstr(pos, "\n");
@@ -1816,11 +1809,12 @@ void CXConsole::ExecuteString(const char* command, const bool bSilentMode, const
 
     // Store the string commands into a list and defer the execution for later.
     // The commands will be processed in CXConsole::Update()
-    string str(command);
-    str.TrimLeft();
+    AZStd::string str(command);
+    AZ::StringFunc::TrimWhiteSpace(str, true, false);
 
     // Unroll the exec command
-    bool unroll = (0 == str.Left(strlen("exec")).compareNoCase("exec"));
+    
+    bool unroll = (0 == AZ::StringFunc::Find(str, "exec", 0, false, false));
 
     if (unroll)
     {
@@ -1858,10 +1852,10 @@ void CXConsole::ResetCVarsToDefaults()
 
 }
 
-void CXConsole::SplitCommands(const char* line, std::list& split)
+void CXConsole::SplitCommands(const char* line, std::list& split)
 {
     const char* start = line;
-    string working;
+    AZStd::string working;
 
     while (true)
     {
@@ -1881,7 +1875,7 @@ void CXConsole::SplitCommands(const char* line, std::list& split)
         case '\0':
         {
             working.assign(start, line - 1);
-            working.Trim();
+            AZ::StringFunc::TrimWhiteSpace(working, true, true);
 
             if (!working.empty())
             {
@@ -1931,15 +1925,15 @@ void CXConsole::ExecuteStringInternal(const char* command, const bool bFromConso
     ConsoleCommandsMapItor itrCmd;
     ConsoleVariablesMapItor itrVar;
 
-    std::list lineCommands;
+    std::list lineCommands;
     SplitCommands(command, lineCommands);
 
-    string sTemp;
-    string sCommand, sLineCommand;
+    AZStd::string sTemp;
+    AZStd::string sCommand, sLineCommand;
 
     while (!lineCommands.empty())
     {
-        string::size_type nPos;
+        AZStd::string::size_type nPos;
 
         {
             sTemp = lineCommands.front();
@@ -1951,17 +1945,17 @@ void CXConsole::ExecuteStringInternal(const char* command, const bool bFromConso
             {
                 if (GetStatus())
                 {
-                    AddLine(sTemp);
+                    AddLine(sTemp.c_str());
                 }
             }
 
             nPos = sTemp.find_first_of('=');
 
-            if (nPos != string::npos)
+            if (nPos != AZStd::string::npos)
             {
                 sCommand = sTemp.substr(0, nPos);
             }
-            else if ((nPos = sTemp.find_first_of(' ')) != string::npos)
+            else if ((nPos = sTemp.find_first_of(' ')) != AZStd::string::npos)
             {
                 sCommand = sTemp.substr(0, nPos);
             }
@@ -1970,7 +1964,7 @@ void CXConsole::ExecuteStringInternal(const char* command, const bool bFromConso
                 sCommand = sTemp;
             }
 
-            sCommand.Trim();
+            AZ::StringFunc::TrimWhiteSpace(sCommand, true, true);
 
             //////////////////////////////////////////
             // Search for CVars
@@ -2005,7 +1999,7 @@ void CXConsole::ExecuteStringInternal(const char* command, const bool bFromConso
 
         //////////////////////////////////////////
         //Check  if is a variable
-        itrVar = m_mapVariables.find(sCommand);
+        itrVar = m_mapVariables.find(sCommand.c_str());
         if (itrVar != m_mapVariables.end())
         {
             ICVar* pCVar = itrVar->second;
@@ -2017,10 +2011,10 @@ void CXConsole::ExecuteStringInternal(const char* command, const bool bFromConso
                     m_blockCounter++;
                 }
 
-                if (nPos != string::npos)
+                if (nPos != AZStd::string::npos)
                 {
                     sTemp = sTemp.substr(nPos + 1);     // remove the command from sTemp
-                    sTemp.Trim(" \t\r\n\"\'");
+                    AZ::StringFunc::StripEnds(sTemp, " \t\r\n\"\'");
 
                     if (sTemp == "?")
                     {
@@ -2094,12 +2088,12 @@ void CXConsole::ExecuteDeferredCommands()
 }
 
 //////////////////////////////////////////////////////////////////////////
-void CXConsole::ExecuteCommand(CConsoleCommand& cmd, string& str, bool bIgnoreDevMode)
+void CXConsole::ExecuteCommand(CConsoleCommand& cmd, AZStd::string& str, bool bIgnoreDevMode)
 {
     CryLog ("[CONSOLE] Executing console command '%s'", str.c_str());
     INDENT_LOG_DURING_SCOPE();
 
-    std::vector args;
+    std::vector args;
     size_t t;
 
     {
@@ -2118,7 +2112,7 @@ void CXConsole::ExecuteCommand(CConsoleCommand& cmd, string& str, bool bIgnoreDe
                 {
                     ;
                 }
-                args.push_back(string(start + 1, commandLine - 1));
+                args.push_back(AZStd::string(start + 1, commandLine - 1));
                 start = commandLine;
                 break;
             }
@@ -2129,7 +2123,7 @@ void CXConsole::ExecuteCommand(CConsoleCommand& cmd, string& str, bool bIgnoreDe
             {
                 if ((*commandLine == ' ') || !*commandLine)
                 {
-                    args.push_back(string(start, commandLine));
+                    args.push_back(AZStd::string(start, commandLine));
                     start = commandLine + 1;
                 }
             }
@@ -2139,7 +2133,7 @@ void CXConsole::ExecuteCommand(CConsoleCommand& cmd, string& str, bool bIgnoreDe
 
         if (args.size() >= 2 && args[1] == "?")
         {
-            DisplayHelp(cmd.m_sHelp, cmd.m_sName.c_str());
+            DisplayHelp(cmd.m_sHelp.c_str(), cmd.m_sName.c_str());
             return;
         }
 
@@ -2166,13 +2160,13 @@ void CXConsole::ExecuteCommand(CConsoleCommand& cmd, string& str, bool bIgnoreDe
         return;
     }
 
-    string buf;
+    AZStd::string buf;
     {
         // only do this for commands with script implementation
         for (;; )
         {
             t = str.find_first_of("\\", t);
-            if (t == string::npos)
+            if (t == AZStd::string::npos)
             {
                 break;
             }
@@ -2183,7 +2177,7 @@ void CXConsole::ExecuteCommand(CConsoleCommand& cmd, string& str, bool bIgnoreDe
         for (t = 1;; )
         {
             t = str.find_first_of("\"", t);
-            if (t == string::npos)
+            if (t == AZStd::string::npos)
             {
                 break;
             }
@@ -2194,9 +2188,9 @@ void CXConsole::ExecuteCommand(CConsoleCommand& cmd, string& str, bool bIgnoreDe
         buf = cmd.m_sCommand;
 
         size_t pp = buf.find("%%");
-        if (pp != string::npos)
+        if (pp != AZStd::string::npos)
         {
-            string list = "";
+            AZStd::string list = "";
             for (unsigned int i = 1; i < args.size(); i++)
             {
                 list += "\"" + args[i] + "\"";
@@ -2207,9 +2201,9 @@ void CXConsole::ExecuteCommand(CConsoleCommand& cmd, string& str, bool bIgnoreDe
             }
             buf.replace(pp, 2, list);
         }
-        else if ((pp = buf.find("%line")) != string::npos)
+        else if ((pp = buf.find("%line")) != AZStd::string::npos)
         {
-            string tmp = "\"" + str.substr(str.find(" ") + 1) + "\"";
+            AZStd::string tmp = "\"" + str.substr(str.find(" ") + 1) + "\"";
             if (args.size() > 1)
             {
                 buf.replace(pp, 5, tmp);
@@ -2226,7 +2220,7 @@ void CXConsole::ExecuteCommand(CConsoleCommand& cmd, string& str, bool bIgnoreDe
                 char pat[10];
                 azsprintf(pat, "%%%d", i);
                 size_t pos = buf.find(pat);
-                if (pos == string::npos)
+                if (pos == AZStd::string::npos)
                 {
                     if (i != args.size())
                     {
@@ -2241,7 +2235,7 @@ void CXConsole::ExecuteCommand(CConsoleCommand& cmd, string& str, bool bIgnoreDe
                         ConsoleWarning("Not enough arguments for: %s", cmd.m_sName.c_str());
                         return;
                     }
-                    string arg = "\"" + args[i] + "\"";
+                    AZStd::string arg = "\"" + args[i] + "\"";
                     buf.replace(pos, strlen(pat), arg);
                 }
             }
@@ -2340,15 +2334,15 @@ const char* CXConsole::ProcessCompletion(const char* szInputBuffer)
     }
     //try to search in command list
     bool bArgumentAutoComplete = false;
-    std::vector matches;
+    std::vector matches;
 
-    if (m_sPrevTab.find(' ') != string::npos)
+    if (m_sPrevTab.find(' ') != AZStd::string::npos)
     {
         bool bProcessAutoCompl = true;
 
         // Find command.
-        string sVar = m_sPrevTab.substr(0, m_sPrevTab.find(' '));
-        ICVar* pCVar = GetCVar(sVar);
+        AZStd::string sVar = m_sPrevTab.substr(0, m_sPrevTab.find(' '));
+        ICVar* pCVar = GetCVar(sVar.c_str());
         if (pCVar)
         {
             if (!(pCVar->GetFlags() & VF_RESTRICTEDMODE) && con_restricted)            // in restricted mode we allow only VF_RESTRICTEDMODE CVars&CCmd
@@ -2376,7 +2370,7 @@ const char* CXConsole::ProcessCompletion(const char* szInputBuffer)
                 int nMatches = pArgumentAutoComplete->GetCount();
                 for (int i = 0; i < nMatches; i++)
                 {
-                    string cmd = string(sVar) + " " + pArgumentAutoComplete->GetValue(i);
+                    AZStd::string cmd = AZStd::string(sVar) + " " + pArgumentAutoComplete->GetValue(i);
                     if (_strnicmp(m_sPrevTab.c_str(), cmd.c_str(), m_sPrevTab.length()) == 0)
                     {
                         {
@@ -2436,10 +2430,10 @@ const char* CXConsole::ProcessCompletion(const char* szInputBuffer)
     {
         ConsoleLogInput(" ");       // empty line before auto completion
 
-        for (std::vector::iterator i = matches.begin(); i != matches.end(); ++i)
+        for (std::vector::iterator i = matches.begin(); i != matches.end(); ++i)
         {
             // List matching variables
-            const char* sVar = *i;
+            const char* sVar = i->c_str();
             ICVar* pVar = GetCVar(sVar);
 
             if (pVar)
@@ -2453,7 +2447,7 @@ const char* CXConsole::ProcessCompletion(const char* szInputBuffer)
         }
     }
 
-    for (std::vector::iterator i = matches.begin(); i != matches.end(); ++i)
+    for (std::vector::iterator i = matches.begin(); i != matches.end(); ++i)
     {
         if (m_nTabCount <= nMatch)
         {
@@ -2485,8 +2479,8 @@ void CXConsole::DisplayVarValue(ICVar* pVar)
 
     const char* sFlagsString = GetFlagsString(pVar->GetFlags());
 
-    string sValue = (pVar->GetFlags() & VF_INVISIBLE) ? "" : pVar->GetString();
-    string sVar = pVar->GetName();
+    AZStd::string sValue = (pVar->GetFlags() & VF_INVISIBLE) ? "" : pVar->GetString();
+    AZStd::string sVar = pVar->GetName();
 
     char szRealState[40] = "";
 
@@ -2623,12 +2617,8 @@ void CXConsole::AddLine(const char* inputStr)
 
 void CXConsole::PostLine(const char* lineOfText, size_t len)
 {
-    string line;
-
-    {
-        line = string(lineOfText, len);
-        m_dqConsoleBuffer.push_back(line);
-    }
+    AZStd::string line = AZStd::string(lineOfText, len);
+    m_dqConsoleBuffer.push_back(line);
 
     int nBufferSize = con_line_buffer_size;
 
@@ -2701,7 +2691,7 @@ void CXConsole::RemoveOutputPrintSink(IOutputPrintSink* inpSink)
 //////////////////////////////////////////////////////////////////////////
 void CXConsole::AddLinePlus(const char* inputStr)
 {
-    string str, tmpStr;
+    AZStd::string str, tmpStr;
 
     {
         if (!m_dqConsoleBuffer.size())
@@ -2717,13 +2707,13 @@ void CXConsole::AddLinePlus(const char* inputStr)
             str.resize(str.size() - 1);
         }
 
-        string::size_type nPos;
-        while ((nPos = str.find('\n')) != string::npos)
+        AZStd::string::size_type nPos;
+        while ((nPos = str.find('\n')) != AZStd::string::npos)
         {
             str.replace(nPos, 1, 1, ' ');
         }
 
-        while ((nPos = str.find('\r')) != string::npos)
+        while ((nPos = str.find('\r')) != AZStd::string::npos)
         {
             str.replace(nPos, 1, 1, ' ');
         }
@@ -2783,7 +2773,7 @@ void CXConsole::AddInputUTF8(const AZStd::string& textUTF8)
 //////////////////////////////////////////////////////////////////////////
 void CXConsole::ExecuteInputBuffer()
 {
-    string sTemp = m_sInputBuffer;
+    AZStd::string sTemp = m_sInputBuffer;
     if (m_sInputBuffer.empty())
     {
         return;
@@ -2814,9 +2804,7 @@ void CXConsole::RemoveInputChar(bool bBackSpace)
             const char* const pBase = m_sInputBuffer.c_str();
             const char* pCursor = pBase + m_nCursorPos;
             const char* const pEnd = pCursor;
-            Unicode::CIterator pUnicode(pCursor);
-            pUnicode--; // Remove one UCS code-point, doesn't account for combining diacritics
-            pCursor = pUnicode.GetPosition();
+            pCursor -= Utf8::Internal::sequence_length(pCursor); // Remove one UCS code-point, doesn't account for combining diacritics
             size_t length = pEnd - pCursor;
             m_sInputBuffer.erase(pCursor - pBase, length);
             m_nCursorPos -= length;
@@ -2829,9 +2817,7 @@ void CXConsole::RemoveInputChar(bool bBackSpace)
             const char* const pBase = m_sInputBuffer.c_str();
             const char* pCursor = pBase + m_nCursorPos;
             const char* const pBegin = pCursor;
-            Unicode::CIterator pUnicode(pCursor);
-            pUnicode--; // Remove one UCS code-point, doesn't account for combining diacritics
-            pCursor = pUnicode.GetPosition();
+            pCursor -= Utf8::Internal::sequence_length(pCursor); // Remove one UCS code-point, doesn't account for combining diacritics
             size_t length = pCursor - pBegin;
             m_sInputBuffer.erase(pBegin - pBase, length);
         }
@@ -2905,28 +2891,29 @@ void CXConsole::Paste()
 #if defined(AZ_PLATFORM_WINDOWS)
     if (OpenClipboard(NULL) != 0)
     {
-        wstring data;
+        AZStd::string data;
         const HANDLE wideData = GetClipboardData(CF_UNICODETEXT);
         if (wideData)
         {
             const LPCWSTR pWideData = (LPCWSTR)GlobalLock(wideData);
             if (pWideData)
             {
-                // Note: This conversion is just to make sure we discard malicious or malformed data
-                Unicode::ConvertSafe(data, pWideData);
+                AZStd::to_string(data, pWideData);
                 GlobalUnlock(wideData);
             }
         }
         CloseClipboard();
 
-        for (Unicode::CIterator it(data.begin(), data.end()); it != data.end(); ++it)
+        Utf8::Unchecked::octet_iterator end(data.end());
+        for (Utf8::Unchecked::octet_iterator it(data.begin()); it != end; ++it)
         {
             const uint32 cp = *it;
             if (cp != '\r')
             {
                 // Convert UCS code-point into UTF-8 string
-                char utf8_buf[5];
-                Unicode::Convert(utf8_buf, cp);
+                char utf8_buf[5] = {0};
+                size_t size = 5;
+                it.to_utf8_sequence(cp, utf8_buf, size);
                 AddInputUTF8(utf8_buf);
             }
         }
@@ -3030,7 +3017,7 @@ void CXConsole::AddCVarsToHash(ConsoleVariablesVector::const_iterator begin, Con
     {
         // add name & variable to string. We add both since adding only the value could cause
         // many collisions with variables all having value 0 or all 1.
-        string hashStr = it->first;
+        AZStd::string hashStr = it->first;
 
         runningNameCrc32.Add(hashStr.c_str(), hashStr.length());
         hashStr += it->second->GetDataProbeString();
@@ -3281,7 +3268,7 @@ void CXConsole::FindVar(const char* substr)
 
     for (size_t i = 0; i < cmdCount; i++)
     {
-        if (CryStringUtils::stristr(cmds[i], substr))
+        if (AZ::StringFunc::Find(cmds[i], substr) != AZStd::string::npos)
         {
             ICVar* pCvar = gEnv->pConsole->GetCVar(cmds[i]);
             if (pCvar)
@@ -3399,7 +3386,7 @@ const char* CXConsole::AutoCompletePrev(const char* substr)
 }
 
 //////////////////////////////////////////////////////////////////////////
-inline size_t sizeOf (const string& str)
+inline size_t sizeOf (const AZStd::string& str)
 {
     return str.capacity() + 1;
 }
diff --git a/Code/Legacy/CrySystem/XConsole.h b/Code/Legacy/CrySystem/XConsole.h
index f09c8e5ad7..b141a88e52 100644
--- a/Code/Legacy/CrySystem/XConsole.h
+++ b/Code/Legacy/CrySystem/XConsole.h
@@ -95,26 +95,12 @@ private:
 
 struct string_nocase_lt
 {
-    bool operator()(const char* s1, const char* s2) const
+    bool operator()(const AZStd::string& s1, const AZStd::string& s2) const
     {
-        return azstricmp(s1, s2) < 0;
+        return azstricmp(s1.c_str(), s2.c_str()) < 0;
     }
 };
 
-/* - very dangerous to use with STL containers
-struct string_nocase_lt
-{
-    bool operator()( const char *s1,const char *s2 ) const
-    {
-        return _stricmp(s1,s2) < 0;
-    }
-    bool operator()( const string &s1,const string &s2 ) const
-    {
-        return _stricmp(s1.c_str(),s2.c_str()) < 0;
-    }
-};
-*/
-
 //forward declarations
 class ITexture;
 struct IRenderer;
diff --git a/Code/Legacy/CrySystem/XConsoleVariable.cpp b/Code/Legacy/CrySystem/XConsoleVariable.cpp
index 370931088f..ab6ed0b078 100644
--- a/Code/Legacy/CrySystem/XConsoleVariable.cpp
+++ b/Code/Legacy/CrySystem/XConsoleVariable.cpp
@@ -286,7 +286,7 @@ void CXConsoleVariableCVarGroup::OnLoadConfigurationEntry_End()
 {
     if (!m_sDefaultValue.empty())
     {
-        gEnv->pConsole->LoadConfigVar(GetName(), m_sDefaultValue);
+        gEnv->pConsole->LoadConfigVar(GetName(), m_sDefaultValue.c_str());
         m_sDefaultValue.clear();
     }
 }
@@ -299,9 +299,9 @@ CXConsoleVariableCVarGroup::CXConsoleVariableCVarGroup(CXConsole* pConsole, cons
 }
 
 
-string CXConsoleVariableCVarGroup::GetDetailedInfo() const
+AZStd::string CXConsoleVariableCVarGroup::GetDetailedInfo() const
 {
-    string sRet = GetName();
+    AZStd::string sRet = GetName();
 
     sRet += " [";
 
@@ -326,11 +326,11 @@ string CXConsoleVariableCVarGroup::GetDetailedInfo() const
     sRet += "/default] [current]:\n";
 
 
-    std::map::const_iterator it, end = m_CVarGroupDefault.m_KeyValuePair.end();
+    std::map::const_iterator it, end = m_CVarGroupDefault.m_KeyValuePair.end();
 
     for (it = m_CVarGroupDefault.m_KeyValuePair.begin(); it != end; ++it)
     {
-        const string& rKey = it->first;
+        const AZStd::string& rKey = it->first;
 
         sRet += " ... ";
         sRet += rKey;
@@ -344,7 +344,7 @@ string CXConsoleVariableCVarGroup::GetDetailedInfo() const
             sRet += "/";
         }
         sRet += GetValueSpec(rKey);
-        ICVar* pCVar = gEnv->pConsole->GetCVar(rKey);
+        ICVar* pCVar = gEnv->pConsole->GetCVar(rKey.c_str());
         if (pCVar)
         {
             sRet += " [";
@@ -369,7 +369,7 @@ const char* CXConsoleVariableCVarGroup::GetHelp()
     }
 
     // create help on demand
-    string sRet = "Console variable group to apply settings to multiple variables\n\n";
+    AZStd::string sRet = "Console variable group to apply settings to multiple variables\n\n";
 
     sRet += GetDetailedInfo();
 
@@ -545,12 +545,12 @@ bool CXConsoleVariableCVarGroup::TestCVars(const SCVarGroup* pGroup, const ICVar
 bool CXConsoleVariableCVarGroup::TestCVars(const SCVarGroup& rGroup, const ICVar::EConsoleLogMode mode, const SCVarGroup* pExclude) const
 {
     bool bRet = true;
-    std::map::const_iterator it, end = rGroup.m_KeyValuePair.end();
+    std::map::const_iterator it, end = rGroup.m_KeyValuePair.end();
 
     for (it = rGroup.m_KeyValuePair.begin(); it != end; ++it)
     {
-        const string& rKey = it->first;
-        const string& rValue = it->second;
+        const AZStd::string& rKey = it->first;
+        const AZStd::string& rValue = it->second;
 
         if (pExclude)
         {
@@ -674,7 +674,7 @@ bool CXConsoleVariableCVarGroup::TestCVars(const SCVarGroup& rGroup, const ICVar
 
 
 
-string CXConsoleVariableCVarGroup::GetValueSpec(const string& sKey, const int* pSpec) const
+AZStd::string CXConsoleVariableCVarGroup::GetValueSpec(const AZStd::string& sKey, const int* pSpec) const
 {
     if (pSpec)
     {
@@ -685,7 +685,7 @@ string CXConsoleVariableCVarGroup::GetValueSpec(const string& sKey, const int* p
             const SCVarGroup* pGrp = itGrp->second;
 
             // check in spec
-            std::map::const_iterator it = pGrp->m_KeyValuePair.find(sKey);
+            std::map::const_iterator it = pGrp->m_KeyValuePair.find(sKey);
 
             if (it != pGrp->m_KeyValuePair.end())
             {
@@ -695,7 +695,7 @@ string CXConsoleVariableCVarGroup::GetValueSpec(const string& sKey, const int* p
     }
 
     // check in default
-    std::map::const_iterator it = m_CVarGroupDefault.m_KeyValuePair.find(sKey);
+    std::map::const_iterator it = m_CVarGroupDefault.m_KeyValuePair.find(sKey);
 
     if (it != m_CVarGroupDefault.m_KeyValuePair.end())
     {
@@ -708,14 +708,14 @@ string CXConsoleVariableCVarGroup::GetValueSpec(const string& sKey, const int* p
 
 void CXConsoleVariableCVarGroup::ApplyCVars(const SCVarGroup& rGroup, const SCVarGroup* pExclude)
 {
-    std::map::const_iterator it, end = rGroup.m_KeyValuePair.end();
+    std::map::const_iterator it, end = rGroup.m_KeyValuePair.end();
 
     bool wasProcessingGroup = m_pConsole->GetIsProcessingGroup();
     m_pConsole->SetProcessingGroup(true);
 
     for (it = rGroup.m_KeyValuePair.begin(); it != end; ++it)
     {
-        const string& rKey = it->first;
+        const AZStd::string& rKey = it->first;
 
         if (pExclude)
         {
@@ -728,7 +728,7 @@ void CXConsoleVariableCVarGroup::ApplyCVars(const SCVarGroup& rGroup, const SCVa
         // Useful for debugging cvar groups
         //CryLogAlways("[CVARS]: [APPLY] ([%s]) [%s] = [%s]", GetName(), rKey.c_str(), it->second.c_str());
 
-        m_pConsole->LoadConfigVar(rKey, it->second);
+        m_pConsole->LoadConfigVar(rKey.c_str(), it->second.c_str());
     }
 
     m_pConsole->SetProcessingGroup(wasProcessingGroup);
diff --git a/Code/Legacy/CrySystem/XConsoleVariable.h b/Code/Legacy/CrySystem/XConsoleVariable.h
index 0dd05cdb07..e4f9c14355 100644
--- a/Code/Legacy/CrySystem/XConsoleVariable.h
+++ b/Code/Legacy/CrySystem/XConsoleVariable.h
@@ -16,6 +16,7 @@
 #include "SFunctor.h"
 
 class CXConsole;
+typedef AZStd::fixed_string<512> stack_string;
 
 inline int64 TextToInt64(const char* s, int64 nCurrent, bool bBitfield)
 {
@@ -184,13 +185,13 @@ public:
 
     // interface ICVar --------------------------------------------------------------------------------------
 
-    virtual int GetIVal() const { return atoi(m_sValue); }
-    virtual int64 GetI64Val() const { return _atoi64(m_sValue); }
-    virtual float GetFVal() const { return (float)atof(m_sValue); }
-    virtual const char* GetString() const { return m_sValue; }
+    virtual int GetIVal() const { return atoi(m_sValue.c_str()); }
+    virtual int64 GetI64Val() const { return _atoi64(m_sValue.c_str()); }
+    virtual float GetFVal() const { return (float)atof(m_sValue.c_str()); }
+    virtual const char* GetString() const { return m_sValue.c_str(); }
     virtual void ResetImpl()
     {
-        Set(m_sDefault);
+        Set(m_sDefault.c_str());
     }
     virtual void Set(const char* s)
     {
@@ -219,8 +220,7 @@ public:
 
     virtual void Set(float f)
     {
-        stack_string s;
-        s.Format("%g", f);
+        stack_string s = stack_string::format("%g", f);
 
         if ((m_sValue == s.c_str()) && (m_nFlags & VF_ALWAYSONCHANGE) == 0)
         {
@@ -233,8 +233,7 @@ public:
 
     virtual void Set(int i)
     {
-        stack_string s;
-        s.Format("%d", i);
+        stack_string s = stack_string::format("%d", i);
 
         if ((m_sValue == s.c_str()) && (m_nFlags & VF_ALWAYSONCHANGE) == 0)
         {
@@ -248,8 +247,8 @@ public:
 
     virtual void GetMemoryUsage(class ICrySizer* pSizer) const { pSizer->AddObject(this, sizeof(*this)); }
 private: // --------------------------------------------------------------------------------------------
-    string m_sValue;                                            
-    string m_sDefault;                                                                              //!<
+    AZStd::string m_sValue;                                            
+    AZStd::string m_sDefault;                                                                              //!<
 };
 
 
@@ -296,8 +295,7 @@ public:
             return;
         }
 
-        stack_string s;
-        s.Format("%d", i);
+        stack_string s = stack_string::format("%d", i);
 
         if (m_pConsole->OnBeforeVarChange(this, s.c_str()))
         {
@@ -364,8 +362,7 @@ public:
             return;
         }
 
-        stack_string s;
-        s.Format("%lld", i);
+        stack_string s = stack_string::format("%lld", i);
 
         if (m_pConsole->OnBeforeVarChange(this, s.c_str()))
         {
@@ -442,8 +439,7 @@ public:
             return;
         }
 
-        stack_string s;
-        s.Format("%g", f);
+        stack_string s = stack_string::format("%g", f);
 
         if (m_pConsole->OnBeforeVarChange(this, s.c_str()))
         {
@@ -718,7 +714,7 @@ public:
     {
         return m_sValue.c_str();
     }
-    virtual void ResetImpl() { Set(m_sDefault); }
+    virtual void ResetImpl() { Set(m_sDefault.c_str()); }
     virtual void Set(const char* s)
     {
         if ((m_sValue == s) && (m_nFlags & VF_ALWAYSONCHANGE) == 0)
@@ -740,14 +736,12 @@ public:
     }
     virtual void Set(float f)
     {
-        stack_string s;
-        s.Format("%g", f);
+        stack_string s = stack_string::format("%g", f);
         Set(s.c_str());
     }
     virtual void Set(int i)
     {
-        stack_string s;
-        s.Format("%d", i);
+        stack_string s = stack_string::format("%d", i);
         Set(s.c_str());
     }
     virtual int GetType() { return CVAR_STRING; }
@@ -755,8 +749,8 @@ public:
     virtual void GetMemoryUsage(class ICrySizer* pSizer) const { pSizer->AddObject(this, sizeof(*this)); }
 private: // --------------------------------------------------------------------------------------------
 
-    string m_sValue;
-    string m_sDefault;
+    AZStd::string m_sValue;
+    AZStd::string m_sDefault;
     const char*& m_userPtr;                                         //!<
 };
 
@@ -778,7 +772,7 @@ public:
 
     // Returns:
     //   part of the help string - useful to log out detailed description without additional help text
-    string GetDetailedInfo() const;
+    AZStd::string GetDetailedInfo() const;
 
     // interface ICVar -----------------------------------------------------------------------------------
 
@@ -809,7 +803,7 @@ private: // --------------------------------------------------------------------
 
     struct SCVarGroup
     {
-        std::map                         m_KeyValuePair;                 // e.g. m_KeyValuePair["r_fullscreen"]="0"
+        std::map                      m_KeyValuePair;                 // e.g. m_KeyValuePair["r_fullscreen"]="0"
         void GetMemoryUsage(class ICrySizer* pSizer) const
         {
             pSizer->AddObject(m_KeyValuePair);
@@ -818,15 +812,15 @@ private: // --------------------------------------------------------------------
 
     SCVarGroup                                                      m_CVarGroupDefault;
     typedef std::map      TCVarGroupStateMap;
-    TCVarGroupStateMap                                      m_CVarGroupStates;
-    string                                                              m_sDefaultValue;                // used by OnLoadConfigurationEntry_End()
+    TCVarGroupStateMap                                              m_CVarGroupStates;
+    AZStd::string                                                   m_sDefaultValue;                // used by OnLoadConfigurationEntry_End()
 
     void ApplyCVars(const SCVarGroup& rGroup, const SCVarGroup* pExclude = 0);
 
     // Arguments:
     //   sKey - must exist, at least in default
     //   pSpec - can be 0
-    string GetValueSpec(const string& sKey, const int* pSpec = 0) const;
+    AZStd::string GetValueSpec(const AZStd::string& sKey, const int* pSpec = 0) const;
 
     // should only be used by TestCVars()
     // Returns:

From f665f572f3790324e9d498902c00887f09a53438 Mon Sep 17 00:00:00 2001
From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>
Date: Fri, 30 Jul 2021 18:53:50 -0700
Subject: [PATCH 055/803] Gems/Atom builds

Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>
---
 Code/Editor/BaseLibrary.cpp                   |   3 +-
 Code/Editor/Core/QtEditorApplication.cpp      |   7 +-
 Code/Editor/IEditorImpl.cpp                   |   2 +-
 Code/Editor/Include/IFileUtil.h               |   1 -
 Code/Editor/QtUtil.h                          |  24 ----
 Code/Editor/Util/FileUtil.h                   |   1 -
 Code/Editor/Util/PathUtil.cpp                 |  37 +++---
 Code/Editor/Util/PathUtil.h                   |  16 +--
 .../AzCore/AzCore/std/string/conversions.h    |  35 +++++-
 Code/Legacy/CryCommon/IStatObj.h              |  12 +-
 Code/Legacy/CryCommon/IXml.h                  |   8 +-
 .../Support/platform/win/CrashSupport_win.cpp |   5 +-
 Code/Tools/GridHub/GridHub/gridhub.cpp        |   8 +-
 Code/Tools/GridHub/GridHub/main.cpp           | 106 +++++++++---------
 .../Code/Source/LuxCore/LuxCoreRenderer.cpp   |   2 +-
 .../Windows/LaunchLuxCoreUI_Windows.cpp       |  12 +-
 .../Windows/RHI/PhysicalDevice_Windows.cpp    |   2 +-
 .../Windows/RHI/WindowsVersionQuery.cpp       |   4 +-
 Gems/Atom/RHI/DX12/Code/Source/RHI/Fence.cpp  |   8 +-
 Gems/CrashReporting/Code/CMakeLists.txt       |   1 +
 .../Code/Tests/AnimGraphCopyPasteTests.cpp    |   2 +-
 Gems/Maestro/Code/Source/Cinematics/Movie.cpp |   4 +-
 Gems/Maestro/Code/Source/Cinematics/Movie.h   |   2 +-
 .../SaveData_SystemComponent_Windows.cpp      |   3 +-
 24 files changed, 159 insertions(+), 146 deletions(-)

diff --git a/Code/Editor/BaseLibrary.cpp b/Code/Editor/BaseLibrary.cpp
index ee1c85756d..3c3ccfe13d 100644
--- a/Code/Editor/BaseLibrary.cpp
+++ b/Code/Editor/BaseLibrary.cpp
@@ -258,9 +258,8 @@ bool CBaseLibrary::SaveLibrary(const char* name, bool saveEmptyLibrary)
     }
     if (!bRes)
     {
-        string strMessage;
         QByteArray filenameUtf8 = fileName.toUtf8();
-        strMessage.Format("The file %s is read-only and the save of the library couldn't be performed. Try to remove the \"read-only\" flag or check-out the file and then try again.", filenameUtf8.data());
+        AZStd::string strMessage = AZStd::string::format("The file %s is read-only and the save of the library couldn't be performed. Try to remove the \"read-only\" flag or check-out the file and then try again.", filenameUtf8.data());
         CryMessageBox(strMessage.c_str(), "Saving Error", MB_OK | MB_ICONWARNING);
     }
     return bRes;
diff --git a/Code/Editor/Core/QtEditorApplication.cpp b/Code/Editor/Core/QtEditorApplication.cpp
index 46e789cd7c..9ec3b57e29 100644
--- a/Code/Editor/Core/QtEditorApplication.cpp
+++ b/Code/Editor/Core/QtEditorApplication.cpp
@@ -206,11 +206,8 @@ namespace
 
     static void LogToDebug([[maybe_unused]] QtMsgType Type, [[maybe_unused]] const QMessageLogContext& Context, const QString& message)
     {
-#if defined(WIN32) || defined(WIN64)
-        OutputDebugStringW(L"Qt: ");
-        OutputDebugStringW(reinterpret_cast(message.utf16()));
-        OutputDebugStringW(L"\n");
-#endif
+        AZ::Debug::Platform::OutputToDebugger("Qt", message.utf8());
+        AZ::Debug::Platform::OutputToDebugger(nullptr, "\n");
     }
 }
 
diff --git a/Code/Editor/IEditorImpl.cpp b/Code/Editor/IEditorImpl.cpp
index c09c0a8e62..2e755bd36a 100644
--- a/Code/Editor/IEditorImpl.cpp
+++ b/Code/Editor/IEditorImpl.cpp
@@ -1109,7 +1109,7 @@ void CEditorImpl::DetectVersion()
 
     char ver[1024 * 8];
 
-    GetModuleFileName(NULL, exe, _MAX_PATH);
+    AZ::Utils::GetExecutablePath(exe, _MAX_PATH);
 
     int verSize = GetFileVersionInfoSize(exe, &dwHandle);
     if (verSize > 0)
diff --git a/Code/Editor/Include/IFileUtil.h b/Code/Editor/Include/IFileUtil.h
index f402786e67..8cb86b812e 100644
--- a/Code/Editor/Include/IFileUtil.h
+++ b/Code/Editor/Include/IFileUtil.h
@@ -8,7 +8,6 @@
 
 #pragma once
 
-#include "StringUtils.h"
 #include "../Include/SandboxAPI.h"
 
 class QWidget;
diff --git a/Code/Editor/QtUtil.h b/Code/Editor/QtUtil.h
index bb1f8ba427..a9aaadc491 100644
--- a/Code/Editor/QtUtil.h
+++ b/Code/Editor/QtUtil.h
@@ -10,8 +10,6 @@
 #pragma once
 
 #include 
-#include 
-#include "UnicodeFunctions.h"
 
 #include 
 #include 
@@ -36,28 +34,6 @@ public:
 
 namespace QtUtil
 {
-    // From QString to CryString
-    inline CryStringT ToString(const QString& str)
-    {
-        return Unicode::Convert >(str);
-    }
-
-    // From CryString to QString
-    inline QString ToQString(const CryStringT& str)
-    {
-        return Unicode::Convert(str);
-    }
-
-    // From const char * to QString
-    inline QString ToQString(const char* str, size_t len = -1)
-    {
-        if (len == -1)
-        {
-            len = strlen(str);
-        }
-        return Unicode::Convert(str, str + len);
-    }
-
     // Replacement for CString::trimRight()
     inline QString trimRight(const QString& str)
     {
diff --git a/Code/Editor/Util/FileUtil.h b/Code/Editor/Util/FileUtil.h
index 000215e98d..06cceaaafc 100644
--- a/Code/Editor/Util/FileUtil.h
+++ b/Code/Editor/Util/FileUtil.h
@@ -10,7 +10,6 @@
 #pragma once
 
 #include "CryThread.h"
-#include "StringUtils.h"
 #include "../Include/SandboxAPI.h"
 #include 
 #include 
diff --git a/Code/Editor/Util/PathUtil.cpp b/Code/Editor/Util/PathUtil.cpp
index 4bb5c20ece..e91d85e4d2 100644
--- a/Code/Editor/Util/PathUtil.cpp
+++ b/Code/Editor/Util/PathUtil.cpp
@@ -15,24 +15,20 @@
 #include  // for ebus events
 #include 
 #include 
+#include 
 
 #include 
 
-namespace
-{
-    string g_currentModName; // folder name only!
-}
-
 namespace Path
 {
     //////////////////////////////////////////////////////////////////////////
     void SplitPath(const QString& rstrFullPathFilename, QString& rstrDriveLetter, QString& rstrDirectory, QString& rstrFilename, QString& rstrExtension)
     {
-        string          strFullPathString(rstrFullPathFilename.toUtf8().data());
-        string          strDriveLetter;
-        string          strDirectory;
-        string          strFilename;
-        string          strExtension;
+        AZStd::string   strFullPathString(rstrFullPathFilename.toUtf8().data());
+        AZStd::string   strDriveLetter;
+        AZStd::string   strDirectory;
+        AZStd::string   strFilename;
+        AZStd::string   strExtension;
 
         char*           szPath((char*)strFullPathString.c_str());
         char*           pchLastPosition(szPath);
@@ -81,16 +77,16 @@ namespace Path
             strFilename.assign(pchLastPosition, pchCurrentPosition);
         }
 
-        rstrDriveLetter = strDriveLetter;
-        rstrDirectory = strDirectory;
-        rstrFilename = strFilename;
-        rstrExtension = strExtension;
+        rstrDriveLetter = strDriveLetter.c_str();
+        rstrDirectory = strDirectory.c_str();
+        rstrFilename = strFilename.c_str();
+        rstrExtension = strExtension.c_str();
     }
     //////////////////////////////////////////////////////////////////////////
     void GetDirectoryQueue(const QString& rstrSourceDirectory, QStringList& rcstrDirectoryTree)
     {
-        string                      strCurrentDirectoryName;
-        string                      strSourceDirectory(rstrSourceDirectory.toUtf8().data());
+        AZStd::string           strCurrentDirectoryName;
+        AZStd::string           strSourceDirectory(rstrSourceDirectory.toUtf8().data());
         const char*             szSourceDirectory(strSourceDirectory.c_str());
         const char*             pchCurrentPosition(szSourceDirectory);
         const char*             pchLastPosition(szSourceDirectory);
@@ -207,7 +203,9 @@ namespace Path
 
     bool IsFolder(const char* pPath)
     {
-        DWORD attrs = GetFileAttributes(pPath);
+        AZStd::wstring pPathW;
+        AZStd::to_wstring(pPathW, pPath);
+        DWORD attrs = GetFileAttributes(pPathW.c_str());
 
         if (attrs == FILE_ATTRIBUTE_DIRECTORY)
         {
@@ -255,16 +253,17 @@ namespace Path
     /// Get the data folder
     AZStd::string GetEditingGameDataFolder()
     {
+        static AZStd::string s_currentModName;
         // query the editor root.  The bus exists in case we want tools to be able to override this.
 
 
-        if (g_currentModName.empty())
+        if (s_currentModName.empty())
         {
             return GetGameAssetsFolder();
         }
         AZStd::string str(GetGameAssetsFolder());
         str += "Mods\\";
-        str += g_currentModName;
+        str += s_currentModName;
         return str;
     }
 
diff --git a/Code/Editor/Util/PathUtil.h b/Code/Editor/Util/PathUtil.h
index 98f484ec94..30887e698b 100644
--- a/Code/Editor/Util/PathUtil.h
+++ b/Code/Editor/Util/PathUtil.h
@@ -93,7 +93,7 @@ namespace Path
 #endif
         file = path_buffer;
     }
-    inline void Split(const string& filepath, string& path, string& file)
+    inline void Split(const AZStd::string& filepath, AZStd::string& path, AZStd::string& file)
     {
         char path_buffer[_MAX_PATH];
         char drive[_MAX_DRIVE];
@@ -101,7 +101,7 @@ namespace Path
         char fname[_MAX_FNAME];
         char ext[_MAX_EXT];
 #ifdef AZ_COMPILER_MSVC
-        _splitpath_s(filepath, drive, AZ_ARRAY_SIZE(drive), dir, AZ_ARRAY_SIZE(dir), 0, 0, 0, 0);
+        _splitpath_s(filepath.c_str(), drive, AZ_ARRAY_SIZE(drive), dir, AZ_ARRAY_SIZE(dir), 0, 0, 0, 0);
         _makepath_s(path_buffer, AZ_ARRAY_SIZE(path_buffer), drive, dir, 0, 0);
         path = path_buffer;
         _makepath_s(path_buffer, AZ_ARRAY_SIZE(path_buffer), 0, 0, fname, ext);
@@ -137,7 +137,7 @@ namespace Path
         filename = fname;
         fext = ext;
     }
-    inline void Split(const string& filepath, string& path, string& filename, string& fext)
+    inline void Split(const AZStd::string& filepath, AZStd::string& path, AZStd::string& filename, AZStd::string& fext)
     {
         char path_buffer[_MAX_PATH];
         char drive[_MAX_DRIVE];
@@ -145,7 +145,7 @@ namespace Path
         char fname[_MAX_FNAME];
         char ext[_MAX_EXT];
 #ifdef AZ_COMPILER_MSVC
-        _splitpath_s(filepath, drive, AZ_ARRAY_SIZE(drive), dir, AZ_ARRAY_SIZE(dir), fname, AZ_ARRAY_SIZE(fname), ext, AZ_ARRAY_SIZE(ext));
+        _splitpath_s(filepath.c_str(), drive, AZ_ARRAY_SIZE(drive), dir, AZ_ARRAY_SIZE(dir), fname, AZ_ARRAY_SIZE(fname), ext, AZ_ARRAY_SIZE(ext));
         _makepath_s(path_buffer, AZ_ARRAY_SIZE(path_buffer), drive, dir, 0, 0);
 #else
         _splitpath(filepath, drive, dir, fname, ext);
@@ -271,7 +271,7 @@ namespace Path
     }
 
     template
-    inline void AddBackslash(AZstd::fixed_string* path)
+    inline void AddBackslash(AZStd::fixed_string* path)
     {
         if (path->empty())
         {
@@ -284,7 +284,7 @@ namespace Path
     }
 
     template
-    inline void AddSlash(AZstd::fixed_string* path)
+    inline void AddSlash(AZStd::fixed_string* path)
     {
         if (path->empty())
         {
@@ -357,7 +357,7 @@ namespace Path
     {
         return CaselessPaths(GetRelativePath(path, true));
     }
-    inline string FullPathToGamePath(const char* path)
+    inline AZStd::string FullPathToGamePath(const char* path)
     {
         return CaselessPaths(GetRelativePath(path, true)).toUtf8().data();
     }
@@ -394,7 +394,7 @@ namespace Path
     inline QString GetAudioLocalizationFolder(bool returnAbsolutePath)
     {
         // Omit the trailing slash!
-        QString sLocalizationFolder(QString(PathUtil::GetLocalizationFolder()).left(static_cast(PathUtil::GetLocalizationFolder().size()) - 1));
+        QString sLocalizationFolder(QString(PathUtil::GetLocalizationFolder().c_str()).left(static_cast(PathUtil::GetLocalizationFolder().size()) - 1));
 
         if (!sLocalizationFolder.isEmpty())
         {
diff --git a/Code/Framework/AzCore/AzCore/std/string/conversions.h b/Code/Framework/AzCore/AzCore/std/string/conversions.h
index cb90881933..fcfe82ba5f 100644
--- a/Code/Framework/AzCore/AzCore/std/string/conversions.h
+++ b/Code/Framework/AzCore/AzCore/std/string/conversions.h
@@ -80,9 +80,7 @@ namespace AZStd
                 }
                 else
                 {
-                    // Workaround to defer static_assert evaluation until this function is invoked by using the template parameter
-                    using StringType = AZStd::basic_string;
-                    static_assert(!AZStd::is_same_v, "only wchar_t types of size 2 or 4 can be converted to utf8");
+                    static_assert(false, "only wchar_t types of size 2 or 4 can be converted to utf8");
                 }
             }
 
@@ -123,6 +121,22 @@ namespace AZStd
                     static_assert(!AZStd::is_same_v, "Cannot convert a utf8 string to a wchar_t that isn't size 2 or 4");
                 }
             }
+
+            static inline void to_wstring(wchar_t* dest, size_t destSize, const char* first, const char* last)
+            {
+                if constexpr (Size == 2)
+                {
+                    Utf8::Unchecked::utf8to16(first, last, dest, destSize);
+                }
+                else if constexpr (Size == 4)
+                {
+                    Utf8::Unchecked::utf8to32(first, last, dest, destSize);
+                }
+                else
+                {
+                    static_assert(false, "Cannot convert a utf8 string to a wchar_t that isn't size 2 or 4");
+                }
+            }
         };
     }
     // 21.5: numeric conversions
@@ -348,7 +362,7 @@ namespace AZStd
     {
         if (srcLen == 0)
         {
-            srcLen = wcslen(str) + 1;
+            srcLen = wcslen(str);
         }
 
         if (srcLen > 0)
@@ -497,6 +511,19 @@ namespace AZStd
         return to_wstring(dest, src.c_str(), src.length());
     }
 
+    inline void to_wstring(wchar_t* dest, size_t destSize, const char* str, size_t srcLen = 0)
+    {
+        if (srcLen == 0)
+        {
+            srcLen = strlen(str) + 1;
+        }
+
+        if (srcLen > 0)
+        {
+            Internal::WCharTPlatformConverter<>::to_wstring(dest, destSize, str, str + srcLen + 1); // copy null terminator
+        }
+    }
+
     // Convert a range of chars to lower case
 #if defined(AZSTD_USE_OLD_RW_STL)
     template
diff --git a/Code/Legacy/CryCommon/IStatObj.h b/Code/Legacy/CryCommon/IStatObj.h
index ff3bbc41e3..4921ab3a25 100644
--- a/Code/Legacy/CryCommon/IStatObj.h
+++ b/Code/Legacy/CryCommon/IStatObj.h
@@ -201,7 +201,7 @@ struct IStreamable
     virtual void StartStreaming(bool bFinishNow, IReadStream_AutoPtr* ppStream) = 0;
     virtual int GetStreamableContentMemoryUsage(bool bJustForDebug = false) = 0;
     virtual void ReleaseStreamableContent() = 0;
-    virtual void GetStreamableName(string& sName) = 0;
+    virtual void GetStreamableName(AZStd::string& sName) = 0;
     virtual uint32 GetLastDrawMainFrameId() = 0;
     virtual bool IsUnloadable() const = 0;
 
@@ -239,8 +239,8 @@ struct IStatObj
         SSubObject() { bShadowProxy = 0; }
 
         EStaticSubObjectType nType;
-        string name;
-        string properties;
+        AZStd::string name;
+        AZStd::string properties;
         int nParent;          // Index of the parent sub object, if there`s hierarchy between them.
         Matrix34 tm;          // Transformation matrix.
         Matrix34 localTM;     // Local transformation matrix, relative to parent.
@@ -510,10 +510,10 @@ struct IStatObj
     virtual bool IsUnloadable() const = 0;
     virtual void SetCanUnload(bool value) = 0;
 
-    virtual string& GetFileName() = 0;
-    virtual const string& GetFileName() const = 0;
+    virtual AZStd::string& GetFileName() = 0;
+    virtual const AZStd::string& GetFileName() const = 0;
 
-    virtual const string& GetCGFNodeName() const = 0;
+    virtual const AZStd::string& GetCGFNodeName() const = 0;
 
     // Summary:
     //     Returns the filename of the object
diff --git a/Code/Legacy/CryCommon/IXml.h b/Code/Legacy/CryCommon/IXml.h
index a380ce167b..80c2415f9c 100644
--- a/Code/Legacy/CryCommon/IXml.h
+++ b/Code/Legacy/CryCommon/IXml.h
@@ -101,7 +101,13 @@ public:
     XmlString(const char* str)
         : AZStd::string(str) {};
 
-    operator const char*() const {
+    size_t GetAllocatedMemory() const
+    {
+        return sizeof(XmlString) + capacity() * sizeof(AZStd::string::value_type);
+    }
+
+    operator const char*() const
+    {
         return c_str();
     }
 };
diff --git a/Code/Tools/CrashHandler/Support/platform/win/CrashSupport_win.cpp b/Code/Tools/CrashHandler/Support/platform/win/CrashSupport_win.cpp
index 3933b5ea91..6010ac8e17 100644
--- a/Code/Tools/CrashHandler/Support/platform/win/CrashSupport_win.cpp
+++ b/Code/Tools/CrashHandler/Support/platform/win/CrashSupport_win.cpp
@@ -10,13 +10,14 @@
 #include 
 
 #include 
+#include 
 #include 
 
 namespace CrashHandler
 {
-    void GetExecutablePathA(char* pathBuffer, int& bufferSize)
+    void GetExecutablePath(char* pathBuffer, int& bufferSize)
     {
-        GetModuleFileNameA(nullptr, pathBuffer, bufferSize);
+        AZ::Utils::GetExecutablePath(pathBuffer, bufferSize);
     }
 
     void GetExecutablePathW(wchar_t* pathBuffer, int& bufferSize)
diff --git a/Code/Tools/GridHub/GridHub/gridhub.cpp b/Code/Tools/GridHub/GridHub/gridhub.cpp
index 3dbecf681f..978589ab74 100644
--- a/Code/Tools/GridHub/GridHub/gridhub.cpp
+++ b/Code/Tools/GridHub/GridHub/gridhub.cpp
@@ -358,13 +358,11 @@ GridHubComponent::GridHubComponent()
     m_isLogToFile = false;
     
 #ifdef AZ_PLATFORM_WINDOWS
-    TCHAR name[MAX_COMPUTERNAME_LENGTH + 1];
+    wchar_t name[MAX_COMPUTERNAME_LENGTH + 1];
     DWORD dwCompNameLen = AZ_ARRAY_SIZE(name);
-    if ( GetComputerName(name, &dwCompNameLen) != 0 ) 
+    if (GetComputerName(name, &dwCompNameLen) != 0) 
     {
-        char c[MAX_COMPUTERNAME_LENGTH + 1];
-        wcstombs(c, name, AZ_ARRAY_SIZE(c));
-        m_hubName = c;
+        AZStd::to_string(m_hubName, name);
     }
     else
 #endif
diff --git a/Code/Tools/GridHub/GridHub/main.cpp b/Code/Tools/GridHub/GridHub/main.cpp
index f02906e0d4..670367bf06 100644
--- a/Code/Tools/GridHub/GridHub/main.cpp
+++ b/Code/Tools/GridHub/GridHub/main.cpp
@@ -16,7 +16,6 @@
 #include 
 #include 
 #include 
-#include 
 #endif
 
 #include "gridhub.hxx"
@@ -39,6 +38,7 @@ AZ_POP_DISABLE_WARNING
 #include 
 #include 
 #include 
+#include 
 
 #ifdef AZ_PLATFORM_WINDOWS
 #include 
@@ -53,9 +53,9 @@ AZ_POP_DISABLE_WARNING
 #endif
 
 #ifdef AZ_PLATFORM_WINDOWS
-#define GRIDHUB_TSR_SUFFIX _T("_copyapp_")
-#define GRIDHUB_TSR_NAME _T("GridHub_copyapp_.exe")
-#define GRIDHUB_IMAGE_NAME _T("GridHub.exe")
+#define GRIDHUB_TSR_SUFFIX L"_copyapp_"
+#define GRIDHUB_TSR_NAME L"GridHub_copyapp_.exe"
+#define GRIDHUB_IMAGE_NAME L"GridHub.exe"
 #else
 #define GRIDHUB_TSR_SUFFIX "_copyapp_"
 #define GRIDHUB_TSR_NAME "GridHub_copyapp_"
@@ -191,7 +191,7 @@ protected:
          specializations.Append("gridhub");
      }
 
-    QString         m_originalExeFileName;
+     QString        m_originalExeFileName;
      QDateTime      m_originalExeLastModified;
      bool           m_monitorForExeChanges;
      bool           m_needToRelaunch;
@@ -305,22 +305,22 @@ public:
     {
 #ifdef AZ_PLATFORM_WINDOWS
         HRESULT hres;
-        TCHAR startupFolder[MAX_PATH] = {0};
-        TCHAR fullLinkName[MAX_PATH] = {0};
+        wchar_t startupFolder[MAX_PATH] = {0};
+        wchar_t fullLinkName[MAX_PATH] = {0};
 
         LPITEMIDLIST pidlFolder = NULL;
         hres = SHGetFolderLocation(0,/*CSIDL_COMMON_STARTUP all users required admin access*/CSIDL_STARTUP,NULL,0,&pidlFolder);
         if (SUCCEEDED(hres))
         {
-            if( SHGetPathFromIDList(pidlFolder,startupFolder) )
+            if (SHGetPathFromIDList(pidlFolder, startupFolder))
             {
-                _tcscat_s(fullLinkName,startupFolder);
-                _tcscat_s(fullLinkName,"\\Amazon Grid Hub.lnk");
+                wcscat_s(fullLinkName, startupFolder);
+                wcscat_s(fullLinkName, L"\\Amazon Grid Hub.lnk");
             }
             CoTaskMemFree(pidlFolder);
         }
 
-        if( moduleFilename.isEmpty() || _tcslen(fullLinkName) == 0 )
+        if( moduleFilename.isEmpty() || wcslen(fullLinkName) == 0 )
             return;
 
         // for development, never autoadd to startup
@@ -342,8 +342,8 @@ public:
                 IPersistFile* ppf;
 
                 // Set the path to the shortcut target and add the description.
-                psl->SetPath(moduleFilename.toUtf8().data());
-                psl->SetDescription("Amazon Grid Hub");
+                psl->SetPath(moduleFilename.toStdWString().c_str());
+                psl->SetDescription(L"Amazon Grid Hub");
 
                 // Query IShellLink for the IPersistFile interface, used for saving the
                 // shortcut in persistent storage.
@@ -351,16 +351,8 @@ public:
 
                 if (SUCCEEDED(hres))
                 {
-                    WCHAR wsz[MAX_PATH];
-
-                    // Ensure that the string is Unicode.
-                    MultiByteToWideChar(CP_ACP, 0, fullLinkName, -1, wsz, MAX_PATH);
-
-                    // Add code here to check return value from MultiByteWideChar
-                    // for success.
-
                     // Save the link by calling IPersistFile::Save.
-                    hres = ppf->Save(wsz, TRUE);
+                    hres = ppf->Save(fullLinkName, TRUE);
                     ppf->Release();
                 }
                 psl->Release();
@@ -412,13 +404,17 @@ GridHubApplication::Create(const Descriptor& descriptor, const StartupParameters
     {
         bool isError = false;
 #ifdef AZ_PLATFORM_WINDOWS
-        TCHAR originalExeFileName[MAX_PATH];
-        if (GetModuleFileName(NULL, originalExeFileName, AZ_ARRAY_SIZE(originalExeFileName)))
+        char originalExeFileName[MAX_PATH];
+        if (AZ::Utils::GetExecutablePath(originalExeFileName, AZ_ARRAY_SIZE(originalExeFileName)).m_pathStored == AZ::Utils::ExecutablePathResult::Success)
         {
-            PathRemoveFileSpec(originalExeFileName);
-            PathAppend(originalExeFileName, GRIDHUB_IMAGE_NAME);
+            wchar_t originalExeFileNameW[MAX_PATH];
+            AZStd::to_wstring(originalExeFileNameW, MAX_PATH, originalExeFileName, MAX_PATH);
+            PathRemoveFileSpec(originalExeFileNameW);
+            PathAppend(originalExeFileNameW, GRIDHUB_IMAGE_NAME);
 
-            m_originalExeFileName = originalExeFileName;
+            AZStd::string finalExeFileName;
+            AZStd::to_string(finalExeFileName, originalExeFileNameW);
+            m_originalExeFileName = finalExeFileName.c_str();
 
             m_originalExeLastModified = QFileInfo(m_originalExeFileName).lastModified();
         }
@@ -489,18 +485,20 @@ void GridHubApplication::RegisterCoreComponents()
 void CopyAndRun(bool failSilently)
 {
 #ifdef AZ_PLATFORM_WINDOWS
-    TCHAR myFileName[MAX_PATH] = { _T(0) };
-    if (GetModuleFileName(NULL, myFileName, MAX_PATH ))
+    char myFileName[MAX_PATH] = { 0 };
+    if (AZ::Utils::GetExecutablePath(myFileName, MAX_PATH).m_pathStored == AZ::Utils::ExecutablePathResult::Success)
     {
-        TCHAR sourceProcPath[MAX_PATH] = { _T(0) };
-        TCHAR targetProcPath[MAX_PATH] = { _T(0) };
-        TCHAR procDrive[MAX_PATH] = { _T(0) };
-        TCHAR procDir[MAX_PATH] = { _T(0) };
-        TCHAR procFname[MAX_PATH] = { _T(0) };
-        TCHAR procExt[MAX_PATH] = { _T(0) };
-        _tsplitpath_s(myFileName, procDrive, procDir, procFname, procExt);
-        _tmakepath_s(sourceProcPath, procDrive, procDir, GRIDHUB_IMAGE_NAME, NULL);
-        _tmakepath_s(targetProcPath, procDrive, procDir, GRIDHUB_TSR_NAME, NULL);
+        wchar_t myFileNameW[MAX_PATH] = { 0 };
+        AZStd::to_wstring(myFileNameW, MAX_PATH, myFileName, MAX_PATH);
+        wchar_t sourceProcPath[MAX_PATH] = { 0 };
+        wchar_t targetProcPath[MAX_PATH] = { 0 };
+        wchar_t procDrive[MAX_PATH] = { 0 };
+        wchar_t procDir[MAX_PATH] = { 0 };
+        wchar_t procFname[MAX_PATH] = { 0 };
+        wchar_t procExt[MAX_PATH] = { 0 };
+        _wsplitpath_s(myFileNameW, procDrive, procDir, procFname, procExt);
+        _wmakepath_s(sourceProcPath, procDrive, procDir, GRIDHUB_IMAGE_NAME, NULL);
+        _wmakepath_s(targetProcPath, procDrive, procDir, GRIDHUB_TSR_NAME, NULL);
         if (CopyFileEx(sourceProcPath, targetProcPath, NULL, NULL, NULL, 0))
         {
             STARTUPINFO si;
@@ -527,9 +525,9 @@ void CopyAndRun(bool failSilently)
         {
             if (!failSilently)
             {
-                TCHAR errorMsg[1024] = { _T(0) };
-                _stprintf_s(errorMsg, _T("Failed to copy GridHub. Make sure that %s%s is writable!"), procFname, procExt);
-                MessageBox(NULL, errorMsg, NULL, MB_ICONSTOP|MB_OK);
+                wchar_t errorMsg[1024] = { 0 };
+                swprintf_s(errorMsg, L"Failed to copy GridHub. Make sure that %s%s is writable!", procFname, procExt);
+                MessageBoxW(NULL, errorMsg, NULL, MB_ICONSTOP|MB_OK);
             }
         }
     }
@@ -565,16 +563,18 @@ void CopyAndRun(bool failSilently)
 void RelaunchImage()
 {
 #ifdef AZ_PLATFORM_WINDOWS
-    TCHAR myFileName[MAX_PATH] = { _T(0) };
-    if (GetModuleFileName(NULL, myFileName, MAX_PATH))
+    char myFileName[MAX_PATH] = { 0 };
+    if (AZ::Utils::GetExecutablePath(myFileName, MAX_PATH).m_pathStored == AZ::Utils::ExecutablePathResult::Success)
     {
-        TCHAR targetProcPath[MAX_PATH] = { _T(0) };
-        TCHAR procDrive[MAX_PATH] = { _T(0) };
-        TCHAR procDir[MAX_PATH] = { _T(0) };
-        TCHAR procFname[MAX_PATH] = { _T(0) };
-        TCHAR procExt[MAX_PATH] = { _T(0) };
-        _tsplitpath_s(myFileName, procDrive, procDir, procFname, procExt);
-        _tmakepath_s(targetProcPath, procDrive, procDir, GRIDHUB_IMAGE_NAME, NULL);
+        wchar_t myFileNameW[MAX_PATH] = { 0 };
+        AZStd::to_wstring(myFileNameW, MAX_PATH, myFileName, MAX_PATH);
+        wchar_t targetProcPath[MAX_PATH] = { 0 };
+        wchar_t procDrive[MAX_PATH] = { 0 };
+        wchar_t procDir[MAX_PATH] = { 0 };
+        wchar_t procFname[MAX_PATH] = { 0 };
+        wchar_t procExt[MAX_PATH] = { 0 };
+        _wsplitpath_s(myFileNameW, procDrive, procDir, procFname, procExt);
+        _wmakepath_s(targetProcPath, procDrive, procDir, GRIDHUB_IMAGE_NAME, NULL);
 
         STARTUPINFO si;
         PROCESS_INFORMATION pi;
@@ -635,8 +635,8 @@ int main(int argc, char *argv[])
     {
 
 #ifdef AZ_PLATFORM_WINDOWS
-        TCHAR exeFileName[MAX_PATH];
-        if( GetModuleFileName(NULL,exeFileName,AZ_ARRAY_SIZE(exeFileName)) )
+        char exeFileName[MAX_PATH];
+        if (AZ::Utils::GetExecutablePath(exeFileName, AZ_ARRAY_SIZE(exeFileName)).m_pathStored == AZ::Utils::ExecutablePathResult::Success)
 #elif defined AZ_PLATFORM_LINUX
         //KDAB_TODO
         char exeFileName[MAXPATHLEN];
@@ -661,7 +661,7 @@ int main(int argc, char *argv[])
         {
 #ifdef AZ_PLATFORM_WINDOWS
             // Create a OS named mutex while the OS is running
-            HANDLE hInstanceMutex = CreateMutex(NULL,TRUE,"Global\\GridHub-Instance");
+            HANDLE hInstanceMutex = CreateMutex(NULL, TRUE, L"Global\\GridHub-Instance");
             AZ_Assert(hInstanceMutex!=NULL,"Failed to create OS mutex [GridHub-Instance]\n");
             if( hInstanceMutex != NULL && GetLastError() == ERROR_ALREADY_EXISTS)
             {
diff --git a/Gems/Atom/Feature/Common/Code/Source/LuxCore/LuxCoreRenderer.cpp b/Gems/Atom/Feature/Common/Code/Source/LuxCore/LuxCoreRenderer.cpp
index 40fcbc7f31..c753079d5b 100644
--- a/Gems/Atom/Feature/Common/Code/Source/LuxCore/LuxCoreRenderer.cpp
+++ b/Gems/Atom/Feature/Common/Code/Source/LuxCore/LuxCoreRenderer.cpp
@@ -19,7 +19,7 @@
 
 namespace LuxCoreUI
 {
-    void LaunchLuxCoreUI(const AZStd::string& luxCoreExeFullPath, AZStd::string& commandLine);
+    void LaunchLuxCoreUI(const AZStd::string& luxCoreExeFullPath, const AZStd::string& commandLine);
 }
 
 namespace AZ
diff --git a/Gems/Atom/Feature/Common/Code/Source/Platform/Windows/LaunchLuxCoreUI_Windows.cpp b/Gems/Atom/Feature/Common/Code/Source/Platform/Windows/LaunchLuxCoreUI_Windows.cpp
index 3c8f304cb6..7f15949201 100644
--- a/Gems/Atom/Feature/Common/Code/Source/Platform/Windows/LaunchLuxCoreUI_Windows.cpp
+++ b/Gems/Atom/Feature/Common/Code/Source/Platform/Windows/LaunchLuxCoreUI_Windows.cpp
@@ -7,11 +7,12 @@
  */
 
 #include 
+#include 
 #include 
 
 namespace LuxCoreUI
 {
-    void LaunchLuxCoreUI(const AZStd::string& luxCoreExeFullPath, AZStd::string& commandLine)
+    void LaunchLuxCoreUI(const AZStd::string& luxCoreExeFullPath, const AZStd::string& commandLine)
     {
         STARTUPINFO si;
         PROCESS_INFORMATION pi;
@@ -20,9 +21,14 @@ namespace LuxCoreUI
         si.cb = sizeof(si);
         ZeroMemory(&pi, sizeof(pi));
 
+        AZStd::wstring luxCoreExeFullPathW;
+        AZStd::to_wstring(luxCoreExeFullPathW, luxCoreExeFullPath.c_str());
+        AZStd::wstring commandLineW;
+        AZStd::to_wstring(commandLineW, commandLine.c_str());
+
         // start the program up
-        CreateProcess(luxCoreExeFullPath.data(),   // the path
-            commandLine.data(),        // Command line
+        CreateProcessW(luxCoreExeFullPathW.c_str(),   // the path
+            commandLineW.data(),        // Command line
             NULL,           // Process handle not inheritable
             NULL,           // Thread handle not inheritable
             FALSE,          // Set handle inheritance to FALSE
diff --git a/Gems/Atom/RHI/DX12/Code/Source/Platform/Windows/RHI/PhysicalDevice_Windows.cpp b/Gems/Atom/RHI/DX12/Code/Source/Platform/Windows/RHI/PhysicalDevice_Windows.cpp
index 6e5206fc00..2c56a860e8 100644
--- a/Gems/Atom/RHI/DX12/Code/Source/Platform/Windows/RHI/PhysicalDevice_Windows.cpp
+++ b/Gems/Atom/RHI/DX12/Code/Source/Platform/Windows/RHI/PhysicalDevice_Windows.cpp
@@ -78,7 +78,7 @@ namespace AZ
             }
 
             constexpr uint32_t SubKeyLength = 256;
-            char subKeyName[SubKeyLength];
+            wchar_t subKeyName[SubKeyLength];
 
             uint32_t driverVersion = 0;
 
diff --git a/Gems/Atom/RHI/DX12/Code/Source/Platform/Windows/RHI/WindowsVersionQuery.cpp b/Gems/Atom/RHI/DX12/Code/Source/Platform/Windows/RHI/WindowsVersionQuery.cpp
index 0301d48454..91f0a712dd 100644
--- a/Gems/Atom/RHI/DX12/Code/Source/Platform/Windows/RHI/WindowsVersionQuery.cpp
+++ b/Gems/Atom/RHI/DX12/Code/Source/Platform/Windows/RHI/WindowsVersionQuery.cpp
@@ -18,7 +18,7 @@ namespace AZ
             bool GetWindowsVersionFromSystemDLL(WindowsVersion* windowsVersion)
             {
                 // We get the file version of one of the system DLLs to get the OS version.
-                constexpr const char* dllName = "Kernel32.dll";
+                constexpr const wchar_t* dllName = L"Kernel32.dll";
                 VS_FIXEDFILEINFO* fileInfo = nullptr;
                 DWORD handle;
                 DWORD infoSize = GetFileVersionInfoSize(dllName, &handle);
@@ -28,7 +28,7 @@ namespace AZ
                     if (GetFileVersionInfo(dllName, handle, infoSize, versionData.data()) != 0)
                     {
                         UINT len;
-                        const char* subBlock = "\\";
+                        const wchar_t* subBlock = L"\\";
                         if (VerQueryValue(versionData.data(), subBlock, reinterpret_cast(&fileInfo), &len) != 0)
                         {
                             windowsVersion->m_majorVersion = HIWORD(fileInfo->dwProductVersionMS);
diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/Fence.cpp b/Gems/Atom/RHI/DX12/Code/Source/RHI/Fence.cpp
index db15930c01..f61aa3f67f 100644
--- a/Gems/Atom/RHI/DX12/Code/Source/RHI/Fence.cpp
+++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/Fence.cpp
@@ -13,9 +13,13 @@ namespace AZ
     namespace DX12
     {
         FenceEvent::FenceEvent(const char* name)
-            : m_EventHandle(CreateEvent(nullptr, false, false, name))
+            : m_EventHandle(nullptr)
             , m_name(name)
-        {}
+        {
+            AZStd::wstring nameW;
+            AZStd::to_wstring(nameW, name);
+            m_EventHandle = CreateEvent(nullptr, false, false, nameW.c_str());
+        }
 
         FenceEvent::~FenceEvent()
         {
diff --git a/Gems/CrashReporting/Code/CMakeLists.txt b/Gems/CrashReporting/Code/CMakeLists.txt
index 37224ea1aa..b12b5d8944 100644
--- a/Gems/CrashReporting/Code/CMakeLists.txt
+++ b/Gems/CrashReporting/Code/CMakeLists.txt
@@ -28,6 +28,7 @@ ly_add_target(
     BUILD_DEPENDENCIES
         PRIVATE
             AZ::CrashHandler
+            AZ::AzCore
 )
 
 # Load the "Gem::CrashReporting" module in Clients and Servers
diff --git a/Gems/EMotionFX/Code/Tests/AnimGraphCopyPasteTests.cpp b/Gems/EMotionFX/Code/Tests/AnimGraphCopyPasteTests.cpp
index eb16a1a57c..4feb8cd86a 100644
--- a/Gems/EMotionFX/Code/Tests/AnimGraphCopyPasteTests.cpp
+++ b/Gems/EMotionFX/Code/Tests/AnimGraphCopyPasteTests.cpp
@@ -159,7 +159,7 @@ namespace EMotionFX
                     (azrtti_typeid<>(conditionPrototype) != azrtti_typeid()))
                 {
                     AZ::TypeId type = azrtti_typeid<>(conditionPrototype);
-                    OutputDebugString(AZStd::string::format("Condition: Name=%s, Type=%s\n", conditionPrototype->GetPaletteName(), type.ToString().c_str()).c_str());
+                    AZ::Debug::Platform::OutputToDebugger(nullptr, AZStd::string::format("Condition: Name=%s, Type=%s\n", conditionPrototype->GetPaletteName(), type.ToString().c_str()).c_str());
                     result.emplace_back(azrtti_typeid<>(conditionPrototype));
                 }
             }
diff --git a/Gems/Maestro/Code/Source/Cinematics/Movie.cpp b/Gems/Maestro/Code/Source/Cinematics/Movie.cpp
index 2d5aa7b410..a6d9e47eb1 100644
--- a/Gems/Maestro/Code/Source/Cinematics/Movie.cpp
+++ b/Gems/Maestro/Code/Source/Cinematics/Movie.cpp
@@ -1963,7 +1963,7 @@ void CLightAnimWrapper::InvalidateAllNodes()
 
 CLightAnimWrapper* CLightAnimWrapper::FindLightAnim(const char* name)
 {
-    LightAnimWrapperCache::const_iterator it = ms_lightAnimWrapperCache.find(CONST_TEMP_STRING(name));
+    LightAnimWrapperCache::const_iterator it = ms_lightAnimWrapperCache.find(name);
     return it != ms_lightAnimWrapperCache.end() ? (*it).second : 0;
 }
 
@@ -1976,7 +1976,7 @@ void CLightAnimWrapper::CacheLightAnim(const char* name, CLightAnimWrapper* p)
 //////////////////////////////////////////////////////////////////////////
 void CLightAnimWrapper::RemoveCachedLightAnim(const char* name)
 {
-    ms_lightAnimWrapperCache.erase(CONST_TEMP_STRING(name));
+    ms_lightAnimWrapperCache.erase(name);
 }
 
 #ifdef MOVIESYSTEM_SUPPORT_EDITING
diff --git a/Gems/Maestro/Code/Source/Cinematics/Movie.h b/Gems/Maestro/Code/Source/Cinematics/Movie.h
index cb97cfc40b..6ac857d652 100644
--- a/Gems/Maestro/Code/Source/Cinematics/Movie.h
+++ b/Gems/Maestro/Code/Source/Cinematics/Movie.h
@@ -48,7 +48,7 @@ public:
     static void InvalidateAllNodes();
 
 private:
-    typedef std::map LightAnimWrapperCache;
+    typedef std::map LightAnimWrapperCache;
     static StaticInstance ms_lightAnimWrapperCache;
     static AZStd::intrusive_ptr ms_pLightAnimSet;
 
diff --git a/Gems/SaveData/Code/Source/Platform/Windows/SaveData_SystemComponent_Windows.cpp b/Gems/SaveData/Code/Source/Platform/Windows/SaveData_SystemComponent_Windows.cpp
index 236b2f525c..2e473cfea7 100644
--- a/Gems/SaveData/Code/Source/Platform/Windows/SaveData_SystemComponent_Windows.cpp
+++ b/Gems/SaveData/Code/Source/Platform/Windows/SaveData_SystemComponent_Windows.cpp
@@ -10,6 +10,7 @@
 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -99,7 +100,7 @@ namespace SaveData
     AZStd::string GetExecutableName()
     {
         char moduleFileName[AZ_MAX_PATH_LEN];
-        GetModuleFileNameA(nullptr, moduleFileName, AZ_MAX_PATH_LEN);
+        AZ::Utils::GetExecutablePath(moduleFileName, AZ_MAX_PATH_LEN);
 
         const AZStd::string moduleFileNameString(moduleFileName);
         const size_t executableNameStart = moduleFileNameString.find_last_of('\\') + 1;

From 8eb92057115ea2fd87354fc230f885ffc3d28927 Mon Sep 17 00:00:00 2001
From: Dayo Lawal 
Date: Mon, 2 Aug 2021 00:34:43 -0500
Subject: [PATCH 056/803] AtomToolsMainWindow

Signed-off-by: Dayo Lawal 
---
 .../Window/AtomToolsMainWindow.h              |  48 +++++++
 .../Source/Window/AtomToolsMainWindow.cpp     | 135 ++++++++++++++++++
 .../Code/atomtoolsframework_files.cmake       |   2 +
 .../Source/Window/MaterialEditorWindow.cpp    |  97 +------------
 .../Code/Source/Window/MaterialEditorWindow.h |  24 ++--
 .../Window/ShaderManagementConsoleWindow.cpp  | 103 ++-----------
 .../Window/ShaderManagementConsoleWindow.h    |  26 ++--
 7 files changed, 217 insertions(+), 218 deletions(-)
 create mode 100644 Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindow.h
 create mode 100644 Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp

diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindow.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindow.h
new file mode 100644
index 0000000000..21afe114f5
--- /dev/null
+++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindow.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#pragma once
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+namespace AtomToolsFramework
+{
+    class AtomToolsMainWindow
+        : public AzQtComponents::DockMainWindow
+    {
+    public:
+        AtomToolsMainWindow(QWidget* parent = 0);
+    protected:
+        AzQtComponents::FancyDocking* m_advancedDockManager = nullptr;
+        QWidget* m_centralWidget = nullptr;
+        QMenuBar* m_menuBar = nullptr;
+        AzQtComponents::TabWidget* m_tabWidget = nullptr;
+
+        virtual void SetupMenu();
+
+        virtual void SetupTabs();
+        virtual void AddTabForDocumentId(const AZ::Uuid& documentId);
+        virtual void RemoveTabForDocumentId(const AZ::Uuid& documentId);
+        virtual void UpdateTabForDocumentId(const AZ::Uuid& documentId);
+        virtual AZ::Uuid GetDocumentIdFromTab(const int tabIndex) const;
+        
+        virtual void OpenTabContextMenu();
+        virtual void SelectPreviousTab();
+        virtual void SelectNextTab();
+
+        QMenu* m_menuFile = {};
+    };
+}
diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp
new file mode 100644
index 0000000000..15edd8c5b6
--- /dev/null
+++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#include 
+
+
+namespace AtomToolsFramework
+{
+    AtomToolsMainWindow::AtomToolsMainWindow(QWidget* parent)
+        : AzQtComponents::DockMainWindow(parent)
+    {
+        m_advancedDockManager = new AzQtComponents::FancyDocking(this);
+
+        setDockNestingEnabled(true);
+        setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea);
+        setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea);
+        setCorner(Qt::TopRightCorner, Qt::RightDockWidgetArea);
+        setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea);
+
+        m_menuBar = new QMenuBar(this);
+        m_menuBar->setObjectName("MenuBar");
+        setMenuBar(m_menuBar);
+
+        m_centralWidget = new QWidget(this);
+        m_tabWidget = new AzQtComponents::TabWidget(m_centralWidget);
+        m_tabWidget->setObjectName("TabWidget");
+        m_tabWidget->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Preferred);
+        m_tabWidget->setContentsMargins(0, 0, 0, 0);
+    }
+
+    void AtomToolsMainWindow::SetupMenu()
+    {
+        // Generating the main menu manually because it's easier and we will have some dynamic or data driven entries
+        m_menuFile = m_menuBar->addMenu("&File");
+    }
+
+    void AtomToolsMainWindow::SetupTabs()
+    {
+        // The tab bar should only be visible if it has active documents
+        m_tabWidget->setVisible(false);
+        m_tabWidget->setTabBarAutoHide(false);
+        m_tabWidget->setMovable(true);
+        m_tabWidget->setTabsClosable(true);
+        m_tabWidget->setUsesScrollButtons(true);
+
+        // Add context menu for right-clicking on tabs
+        m_tabWidget->setContextMenuPolicy(Qt::ContextMenuPolicy::CustomContextMenu);
+        connect(m_tabWidget, &QWidget::customContextMenuRequested, this, [this]() {
+            OpenTabContextMenu();
+        });
+    }
+
+    void AtomToolsMainWindow::AddTabForDocumentId(const AZ::Uuid& documentId)
+    {
+        // Blocking signals from the tab bar so the currentChanged signal is not sent while a document is already being opened.
+        // This prevents the OnDocumentOpened notification from being sent recursively.
+        const QSignalBlocker blocker(m_tabWidget);
+
+        // If a tab for this document already exists then select it instead of creating a new one
+        for (int tabIndex = 0; tabIndex < m_tabWidget->count(); ++tabIndex)
+        {
+            if (documentId == GetDocumentIdFromTab(tabIndex))
+            {
+                m_tabWidget->setCurrentIndex(tabIndex);
+                m_tabWidget->repaint();
+                return;
+            }
+        }
+    }
+
+    void AtomToolsMainWindow::RemoveTabForDocumentId(const AZ::Uuid& documentId)
+    {
+        // We are not blocking signals here because we want closing tabs to close the associated document
+        // and automatically select the next document.
+        for (int tabIndex = 0; tabIndex < m_tabWidget->count(); ++tabIndex)
+        {
+            if (documentId == GetDocumentIdFromTab(tabIndex))
+            {
+                m_tabWidget->removeTab(tabIndex);
+                m_tabWidget->setVisible(m_tabWidget->count() > 0);
+                m_tabWidget->repaint();
+                break;
+            }
+        }
+    }
+
+    void AtomToolsMainWindow::UpdateTabForDocumentId(const AZ::Uuid& documentId)
+    {
+        // Whenever a document is opened, saved, or modified we need to update the tab label
+        if (!documentId.IsNull())
+        {
+            return;
+        }
+    }
+
+    AZ::Uuid AtomToolsMainWindow::GetDocumentIdFromTab(const int tabIndex) const
+    {
+        const QVariant tabData = m_tabWidget->tabBar()->tabData(tabIndex);
+        if (!tabData.isNull())
+        {
+            // We need to be able to convert between a UUID and a string to store and retrieve a document ID from the tab bar
+            const QString documentIdString = tabData.toString();
+            const QByteArray documentIdBytes = documentIdString.toUtf8();
+            const AZ::Uuid documentId(documentIdBytes.data(), documentIdBytes.size());
+            return documentId;
+        }
+        return AZ::Uuid::CreateNull();
+    }
+
+    void AtomToolsMainWindow::OpenTabContextMenu()
+    {
+    }
+    
+    void AtomToolsMainWindow::SelectPreviousTab()
+    {
+        if (m_tabWidget->count() > 1)
+        {
+            // Adding count to wrap around when index <= 0
+            m_tabWidget->setCurrentIndex((m_tabWidget->currentIndex() + m_tabWidget->count() - 1) % m_tabWidget->count());
+        }
+    }
+
+    void AtomToolsMainWindow::SelectNextTab()
+    {
+        if (m_tabWidget->count() > 1)
+        {
+            m_tabWidget->setCurrentIndex((m_tabWidget->currentIndex() + 1) % m_tabWidget->count());
+        }
+    }
+}
diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake b/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake
index 86fc3f5f5e..5ef4426537 100644
--- a/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake
+++ b/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake
@@ -24,6 +24,7 @@ set(FILES
     Include/AtomToolsFramework/Viewport/RenderViewportWidget.h
     Include/AtomToolsFramework/Viewport/ModularViewportCameraController.h
     Include/AtomToolsFramework/Viewport/ModularViewportCameraControllerRequestBus.h
+	Include/AtomToolsFramework/Window/AtomToolsMainWindow.h
     Source/Application/AtomToolsApplication.cpp
     Source/Communication/LocalServer.cpp
     Source/Communication/LocalSocket.cpp
@@ -40,4 +41,5 @@ set(FILES
     Source/Util/Util.cpp
     Source/Viewport/RenderViewportWidget.cpp
     Source/Viewport/ModularViewportCameraController.cpp
+	Source/Window/AtomToolsMainWindow.cpp
 )
diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp
index abb0102de6..78670ac710 100644
--- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp
+++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp
@@ -56,7 +56,7 @@ AZ_POP_DISABLE_WARNING
 namespace MaterialEditor
 {
     MaterialEditorWindow::MaterialEditorWindow(QWidget* parent /* = 0 */)
-        : AzQtComponents::DockMainWindow(parent)
+        : AtomToolsFramework::AtomToolsMainWindow(parent)
     {
         resize(1280, 1024);
 
@@ -83,29 +83,12 @@ namespace MaterialEditor
             setWindowTitle(QApplication::applicationName());
         }
 
-        m_advancedDockManager = new AzQtComponents::FancyDocking(this);
-
         setObjectName("MaterialEditorWindow");
-        setDockNestingEnabled(true);
-        setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea);
-        setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea);
-        setCorner(Qt::TopRightCorner, Qt::RightDockWidgetArea);
-        setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea);
-
-        m_menuBar = new QMenuBar(this);
-        m_menuBar->setObjectName("MenuBar");
-        setMenuBar(m_menuBar);
 
         m_toolBar = new MaterialEditorToolBar(this);
         m_toolBar->setObjectName("ToolBar");
         addToolBar(m_toolBar);
 
-        m_centralWidget = new QWidget(this);
-        m_tabWidget = new AzQtComponents::TabWidget(m_centralWidget);
-        m_tabWidget->setObjectName("TabWidget");
-        m_tabWidget->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Preferred);
-        m_tabWidget->setContentsMargins(0, 0, 0, 0);
-
         m_materialViewport = new MaterialViewportWidget(m_centralWidget);
         m_materialViewport->setObjectName("Viewport");
         m_materialViewport->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
@@ -370,8 +353,7 @@ namespace MaterialEditor
 
     void MaterialEditorWindow::SetupMenu()
     {
-        // Generating the main menu manually because it's easier and we will have some dynamic or data driven entries
-        m_menuFile = m_menuBar->addMenu("&File");
+        AtomToolsFramework::AtomToolsMainWindow::SetupMenu();
 
         m_actionNew = m_menuFile->addAction("&New...", [this]() {
             CreateMaterialDialog createDialog(this);
@@ -563,18 +545,7 @@ namespace MaterialEditor
 
     void MaterialEditorWindow::SetupTabs()
     {
-        // The tab bar should only be visible if it has active documents
-        m_tabWidget->setVisible(false);
-        m_tabWidget->setTabBarAutoHide(false);
-        m_tabWidget->setMovable(true);
-        m_tabWidget->setTabsClosable(true);
-        m_tabWidget->setUsesScrollButtons(true);
-
-        // Add context menu for right-clicking on tabs
-        m_tabWidget->setContextMenuPolicy(Qt::ContextMenuPolicy::CustomContextMenu);
-        connect(m_tabWidget, &QWidget::customContextMenuRequested, this, [this]() {
-            OpenTabContextMenu();
-        });
+        AtomToolsFramework::AtomToolsMainWindow::SetupTabs();
 
         // This signal will be triggered whenever a tab is added, removed, selected, clicked, dragged
         // When the last tab is removed tabIndex will be -1 and the document ID will be null
@@ -600,20 +571,7 @@ namespace MaterialEditor
             return;
         }
 
-        // Blocking signals from the tab bar so the currentChanged signal is not sent while a document is already being opened.
-        // This prevents the OnDocumentOpened notification from being sent recursively.
-        const QSignalBlocker blocker(m_tabWidget);
-
-        // If a tab for this document already exists then select it instead of creating a new one
-        for (int tabIndex = 0; tabIndex < m_tabWidget->count(); ++tabIndex)
-        {
-            if (documentId == GetDocumentIdFromTab(tabIndex))
-            {
-                m_tabWidget->setCurrentIndex(tabIndex);
-                m_tabWidget->repaint();
-                return;
-            }
-        }
+        AtomToolsMainWindow::AddTabForDocumentId(documentId);
 
         // Create a new tab for the document ID and assign it's label to the file name of the document.
         AZStd::string absolutePath;
@@ -639,22 +597,6 @@ namespace MaterialEditor
         m_tabWidget->repaint();
     }
 
-    void MaterialEditorWindow::RemoveTabForDocumentId(const AZ::Uuid& documentId)
-    {
-        // We are not blocking signals here because we want closing tabs to close the associated document
-        // and automatically select the next document. 
-        for (int tabIndex = 0; tabIndex < m_tabWidget->count(); ++tabIndex)
-        {
-            if (documentId == GetDocumentIdFromTab(tabIndex))
-            {
-                m_tabWidget->removeTab(tabIndex);
-                m_tabWidget->setVisible(m_tabWidget->count() > 0);
-                m_tabWidget->repaint();
-                break;
-            }
-        }
-    }
-
     void MaterialEditorWindow::UpdateTabForDocumentId(const AZ::Uuid& documentId)
     {
         // Whenever a document is opened, saved, or modified we need to update the tab label
@@ -698,20 +640,6 @@ namespace MaterialEditor
         return absolutePath.c_str();
     }
 
-    AZ::Uuid MaterialEditorWindow::GetDocumentIdFromTab(const int tabIndex) const
-    {
-        const QVariant tabData = m_tabWidget->tabBar()->tabData(tabIndex);
-        if (!tabData.isNull())
-        {
-            // We need to be able to convert between a UUID and a string to store and retrieve a document ID from the tab bar
-            const QString documentIdString = tabData.toString();
-            const QByteArray documentIdBytes = documentIdString.toUtf8();
-            const AZ::Uuid documentId(documentIdBytes.data(), documentIdBytes.size());
-            return documentId;
-        }
-        return AZ::Uuid::CreateNull();
-    }
-
     void MaterialEditorWindow::OpenTabContextMenu()
     {
         const QTabBar* tabBar = m_tabWidget->tabBar();
@@ -738,23 +666,6 @@ namespace MaterialEditor
             tabMenu.exec(QCursor::pos());
         }
     }
-
-    void MaterialEditorWindow::SelectPreviousTab()
-    {
-        if (m_tabWidget->count() > 1)
-        {
-            // Adding count to wrap around when index <= 0
-            m_tabWidget->setCurrentIndex((m_tabWidget->currentIndex() + m_tabWidget->count() - 1) % m_tabWidget->count());
-        }
-    }
-
-    void MaterialEditorWindow::SelectNextTab()
-    {
-        if (m_tabWidget->count() > 1)
-        {
-            m_tabWidget->setCurrentIndex((m_tabWidget->currentIndex() + 1) % m_tabWidget->count());
-        }
-    }
 } // namespace MaterialEditor
 
 #include 
diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.h
index dac420ab21..96f03e6eed 100644
--- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.h
+++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.h
@@ -11,6 +11,7 @@
 #if !defined(Q_MOC_RUN)
 #include 
 #include 
+#include 
 
 AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT
 #include 
@@ -44,7 +45,7 @@ namespace MaterialEditor
      * 3) MaterialPropertyInspector  - The user edits the properties of the selected Material.
      */
     class MaterialEditorWindow
-        : public AzQtComponents::DockMainWindow
+        : public AtomToolsFramework::AtomToolsMainWindow
         , private MaterialEditorWindowRequestBus::Handler
         , private MaterialDocumentNotificationBus::Handler
     {
@@ -52,6 +53,8 @@ namespace MaterialEditor
     public:
         AZ_CLASS_ALLOCATOR(MaterialEditorWindow, AZ::SystemAllocator, 0);
 
+        using Base = AtomToolsFramework::AtomToolsMainWindow;
+
         MaterialEditorWindow(QWidget* parent = 0);
         ~MaterialEditorWindow();
 
@@ -75,31 +78,22 @@ namespace MaterialEditor
         void OnDocumentUndoStateChanged(const AZ::Uuid& documentId) override;
         void OnDocumentSaved(const AZ::Uuid& documentId) override;
 
-        void SetupMenu();
+        void SetupMenu() override;
 
-        void SetupTabs();
-        void AddTabForDocumentId(const AZ::Uuid& documentId);
-        void RemoveTabForDocumentId(const AZ::Uuid& documentId);
-        void UpdateTabForDocumentId(const AZ::Uuid& documentId);
+        void SetupTabs() override;
+        void AddTabForDocumentId(const AZ::Uuid& documentId) override;
+        void UpdateTabForDocumentId(const AZ::Uuid& documentId) override;
         QString GetDocumentPath(const AZ::Uuid& documentId) const;
-        AZ::Uuid GetDocumentIdFromTab(const int tabIndex) const;
 
-        void OpenTabContextMenu();
-        void SelectPreviousTab();
-        void SelectNextTab();
+        void OpenTabContextMenu() override;
 
         void closeEvent(QCloseEvent* closeEvent) override;
 
-        AzQtComponents::FancyDocking* m_advancedDockManager = nullptr;
-        QWidget* m_centralWidget = nullptr;
-        QMenuBar* m_menuBar = nullptr;
-        AzQtComponents::TabWidget* m_tabWidget = nullptr;
         MaterialViewportWidget* m_materialViewport = nullptr;
         MaterialEditorToolBar* m_toolBar = nullptr;
 
         AZStd::unordered_map  m_dockWidgets;
 
-        QMenu* m_menuFile = {};
         QAction* m_actionNew = {};
         QAction* m_actionOpen = {};
         QAction* m_actionOpenRecent = {};
diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp
index 3900720bf6..90a2e238a9 100644
--- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp
+++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp
@@ -38,29 +38,16 @@ AZ_POP_DISABLE_WARNING
 namespace ShaderManagementConsole
 {
     ShaderManagementConsoleWindow::ShaderManagementConsoleWindow(QWidget* parent /* = 0 */)
-        : AzQtComponents::DockMainWindow(parent)
+        : AtomToolsFramework::AtomToolsMainWindow(parent)
     {
         setWindowTitle("Shader Management Console");
 
-        m_advancedDockManager = new AzQtComponents::FancyDocking(this);
-
-        setDockNestingEnabled(true);
-        setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea);
-        setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea);
-        setCorner(Qt::TopRightCorner, Qt::RightDockWidgetArea);
-        setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea);
-
-        m_menuBar = new QMenuBar(this);
-        setMenuBar(m_menuBar);
+        setObjectName("ShaderManagementConsoleWindow");
 
         m_toolBar = new ShaderManagementConsoleToolBar(this);
+        m_toolBar->setObjectName("ToolBar");
         addToolBar(m_toolBar);
 
-        m_centralWidget = new QWidget(this);
-        m_tabWidget = new AzQtComponents::TabWidget(m_centralWidget);
-        m_tabWidget->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Preferred);
-        m_tabWidget->setContentsMargins(0, 0, 0, 0);
-
         QVBoxLayout* vl = new QVBoxLayout(m_centralWidget);
         vl->setMargin(0);
         vl->setContentsMargins(0, 0, 0, 0);
@@ -144,7 +131,7 @@ namespace ShaderManagementConsole
 
         m_actionUndo->setEnabled(canUndo);
         m_actionRedo->setEnabled(canRedo);
-        m_actionPreferences->setEnabled(false);
+        m_actionSettings->setEnabled(false);
 
         m_actionAssetBrowser->setEnabled(true);
         m_actionPythonTerminal->setEnabled(true);
@@ -188,8 +175,7 @@ namespace ShaderManagementConsole
 
     void ShaderManagementConsoleWindow::SetupMenu()
     {
-        // Generating the main menu manually because it's easier and we will have some dynamic or data driven entries
-        m_menuFile = m_menuBar->addMenu("&File");
+        AtomToolsFramework::AtomToolsMainWindow::SetupMenu();
 
         m_actionOpen = m_menuFile->addAction("&Open...", [this]() {
             const AZStd::vector assetTypes = {
@@ -264,9 +250,9 @@ namespace ShaderManagementConsole
 
         m_menuEdit->addSeparator();
 
-        m_actionPreferences = m_menuEdit->addAction("&Preferences...", [this]() {
+        m_actionSettings = m_menuEdit->addAction("&Preferences...", [this]() {
         }, QKeySequence::Preferences);
-        m_actionPreferences->setEnabled(false);
+        m_actionSettings->setEnabled(false);
 
         m_menuView = m_menuBar->addMenu("&View");
 
@@ -304,18 +290,7 @@ namespace ShaderManagementConsole
 
     void ShaderManagementConsoleWindow::SetupTabs()
     {
-        // The tab bar should only be visible if it has active documents
-        m_tabWidget->setVisible(false);
-        m_tabWidget->setTabBarAutoHide(false);
-        m_tabWidget->setMovable(true);
-        m_tabWidget->setTabsClosable(true);
-        m_tabWidget->setUsesScrollButtons(true);
-
-        // Add context menu for right-clicking on tabs
-        m_tabWidget->setContextMenuPolicy(Qt::ContextMenuPolicy::CustomContextMenu);
-        connect(m_tabWidget, &QWidget::customContextMenuRequested, this, [this]() {
-            OpenTabContextMenu();
-        });
+        AtomToolsFramework::AtomToolsMainWindow::SetupTabs();
 
         // This signal will be triggered whenever a tab is added, removed, selected, clicked, dragged
         // When the last tab is removed tabIndex will be -1 and the document ID will be null
@@ -339,20 +314,7 @@ namespace ShaderManagementConsole
             return;
         }
 
-        // Blocking signals from the tab bar so the currentChanged signal is not sent while a document is already being opened.
-        // This prevents the OnDocumentOpened notification from being sent recursively.
-        const QSignalBlocker blocker(m_tabWidget);
-
-        // If a tab for this document already exists then select it instead of creating a new one
-        for (int tabIndex = 0; tabIndex < m_tabWidget->count(); ++tabIndex)
-        {
-            if (documentId == GetDocumentIdFromTab(tabIndex))
-            {
-                m_tabWidget->setCurrentIndex(tabIndex);
-                m_tabWidget->repaint();
-                return;
-            }
-        }
+        AtomToolsMainWindow::AddTabForDocumentId(documentId);
 
         // Create a new tab for the document ID and assign it's label to the file name of the document.
         AZStd::string absolutePath;
@@ -382,22 +344,6 @@ namespace ShaderManagementConsole
         CreateDocumentContent(documentId, model);
     }
 
-    void ShaderManagementConsoleWindow::RemoveTabForDocumentId(const AZ::Uuid& documentId)
-    {
-        // We are not blocking signals here because we want closing tabs to close the associated document
-        // and automatically select the next document. 
-        for (int tabIndex = 0; tabIndex < m_tabWidget->count(); ++tabIndex)
-        {
-            if (documentId == GetDocumentIdFromTab(tabIndex))
-            {
-                m_tabWidget->removeTab(tabIndex);
-                m_tabWidget->setVisible(m_tabWidget->count() > 0);
-                m_tabWidget->repaint();
-                break;
-            }
-        }
-    }
-
     void ShaderManagementConsoleWindow::UpdateTabForDocumentId(const AZ::Uuid& documentId)
     {
         // Whenever a document is opened, saved, or modified we need to update the tab label
@@ -434,20 +380,6 @@ namespace ShaderManagementConsole
         }
     }
 
-    AZ::Uuid ShaderManagementConsoleWindow::GetDocumentIdFromTab(const int tabIndex) const
-    {
-        const QVariant tabData = m_tabWidget->tabBar()->tabData(tabIndex);
-        if (!tabData.isNull())
-        {
-            // We need to be able to convert between a UUID and a string to store and retrieve a document ID from the tab bar
-            const QString documentIdString = tabData.toString();
-            const QByteArray documentIdBytes = documentIdString.toUtf8();
-            const AZ::Uuid documentId(documentIdBytes.data(), documentIdBytes.size());
-            return documentId;
-        }
-        return AZ::Uuid::CreateNull();
-    }
-
     void ShaderManagementConsoleWindow::OpenTabContextMenu()
     {
         const QTabBar* tabBar = m_tabWidget->tabBar();
@@ -472,23 +404,6 @@ namespace ShaderManagementConsole
         }
     }
 
-    void ShaderManagementConsoleWindow::SelectPreviousTab()
-    {
-        if (m_tabWidget->count() > 1)
-        {
-            // Adding count to wrap around when index <= 0
-            m_tabWidget->setCurrentIndex((m_tabWidget->currentIndex() + m_tabWidget->count() - 1) % m_tabWidget->count());
-        }
-    }
-
-    void ShaderManagementConsoleWindow::SelectNextTab()
-    {
-        if (m_tabWidget->count() > 1)
-        {
-            m_tabWidget->setCurrentIndex((m_tabWidget->currentIndex() + 1) % m_tabWidget->count());
-        }
-    }
-
     void ShaderManagementConsoleWindow::SelectDocumentForTab(const int tabIndex)
     {
         const AZ::Uuid documentId = GetDocumentIdFromTab(tabIndex);
diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.h b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.h
index 5ab94aa34e..cb371bc4d6 100644
--- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.h
+++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.h
@@ -14,6 +14,7 @@
 
 #include 
 #include 
+#include 
 
 AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT
 #include 
@@ -42,13 +43,15 @@ namespace ShaderManagementConsole
      * its panels, managing selection of assets, and performing high-level actions like saving. It contains...
      */
     class ShaderManagementConsoleWindow
-        : public AzQtComponents::DockMainWindow
+        : public AtomToolsFramework::AtomToolsMainWindow
         , private ShaderManagementConsoleDocumentNotificationBus::Handler
     {
         Q_OBJECT
     public:
         AZ_CLASS_ALLOCATOR(ShaderManagementConsoleWindow, AZ::SystemAllocator, 0);
 
+        using Base = AtomToolsFramework::AtomToolsMainWindow;
+
         ShaderManagementConsoleWindow(QWidget* parent = 0);
         ~ShaderManagementConsoleWindow();
 
@@ -60,17 +63,13 @@ namespace ShaderManagementConsole
         void OnDocumentUndoStateChanged(const AZ::Uuid& documentId) override;
         void OnDocumentSaved(const AZ::Uuid& documentId) override;
 
-        void SetupMenu();
+        void SetupMenu() override; 
 
-        void SetupTabs();
-        void AddTabForDocumentId(const AZ::Uuid& documentId);
-        void RemoveTabForDocumentId(const AZ::Uuid& documentId);
-        void UpdateTabForDocumentId(const AZ::Uuid& documentId);
-        AZ::Uuid GetDocumentIdFromTab(const int tabIndex) const;
+        void SetupTabs() override;
+        void AddTabForDocumentId(const AZ::Uuid& documentId) override;
+        void UpdateTabForDocumentId(const AZ::Uuid& documentId) override;
 
-        void OpenTabContextMenu();
-        void SelectPreviousTab();
-        void SelectNextTab();
+        void OpenTabContextMenu() override;
 
         void SelectDocumentForTab(const int tabIndex);
         void CloseDocumentForTab(const int tabIndex);
@@ -80,10 +79,6 @@ namespace ShaderManagementConsole
 
         void CreateDocumentContent(const AZ::Uuid& documentId, QStandardItemModel* model);
 
-        AzQtComponents::FancyDocking* m_advancedDockManager = nullptr;
-        QMenuBar* m_menuBar = nullptr;
-        QWidget* m_centralWidget = nullptr;
-        AzQtComponents::TabWidget* m_tabWidget = nullptr;
         ShaderManagementConsoleBrowserWidget* m_assetBrowser = nullptr;
         ShaderManagementConsoleToolBar* m_toolBar = nullptr;
         AzToolsFramework::CScriptTermDialog* m_pythonTerminal = nullptr;
@@ -91,7 +86,6 @@ namespace ShaderManagementConsole
         AzQtComponents::StyledDockWidget* m_assetBrowserDockWidget = nullptr;
         AzQtComponents::StyledDockWidget* m_pythonTerminalDockWidget = nullptr;
 
-        QMenu* m_menuFile = {};
         QMenu* m_menuNew = {};
         QAction* m_actionOpen = {};
         QAction* m_actionOpenRecent = {};
@@ -106,7 +100,7 @@ namespace ShaderManagementConsole
         QMenu* m_menuEdit = {};
         QAction* m_actionUndo = {};
         QAction* m_actionRedo = {};
-        QAction* m_actionPreferences = {};
+        QAction* m_actionSettings = {};
 
         QMenu* m_menuView = {};
         QAction* m_actionAssetBrowser = {};

From a241eb8e1cb21c141d1996fc929e6ca0242e8018 Mon Sep 17 00:00:00 2001
From: igarri 
Date: Mon, 2 Aug 2021 11:18:24 +0100
Subject: [PATCH 057/803] Added Sensible default

Signed-off-by: igarri 
---
 .../AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h      | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h
index abc3bf315b..d80e2bd093 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h
@@ -51,7 +51,7 @@ namespace AzToolsFramework
             int BuildTableModelMap(const QAbstractItemModel* model, const QModelIndex& parent = QModelIndex(), int row = 0);
 
         private:
-            int m_numberOfItemsDisplayed = 0;
+            int m_numberOfItemsDisplayed = 50;
             int m_displayedItemsCounter = 0;
             QPointer m_filterModel;
             QMap m_indexMap;

From e651f255772b11d01f1210178e6f567981dba36c Mon Sep 17 00:00:00 2001
From: Benjamin Jillich 
Date: Mon, 2 Aug 2021 13:17:34 +0200
Subject: [PATCH 058/803] Ported the render plugin, render update callback and
 render widget

Signed-off-by: Benjamin Jillich 
---
 .../Rendering/Common/RotateManipulator.h       |  2 +-
 .../Rendering/Common/TranslateManipulator.h    |  2 +-
 .../Source/BlendTreeRotationMath2Node.cpp      |  1 -
 .../Source/RenderPlugin/RenderPlugin.cpp       |  2 +-
 .../RenderPlugin/RenderUpdateCallback.cpp      |  7 +++----
 .../Source/RenderPlugin/RenderWidget.cpp       | 18 ++++++++----------
 .../Source/RenderPlugin/RenderWidget.h         | 12 ++++--------
 7 files changed, 18 insertions(+), 26 deletions(-)

diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RotateManipulator.h b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RotateManipulator.h
index c6d719ae7c..5443bad219 100644
--- a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RotateManipulator.h
+++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RotateManipulator.h
@@ -8,7 +8,7 @@
 
 #pragma once
 
-// include the Core system
+#include 
 #include 
 #include 
 #include 
diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/TranslateManipulator.h b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/TranslateManipulator.h
index 362f6c19be..7bc0bacfe0 100644
--- a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/TranslateManipulator.h
+++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/TranslateManipulator.h
@@ -9,7 +9,7 @@
 #ifndef __MCOMMON_TRANSLATEMANIPULATOR_H
 #define __MCOMMON_TRANSLATEMANIPULATOR_H
 
-// include the Core system
+#include 
 #include 
 #include 
 #include "MCommonConfig.h"
diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeRotationMath2Node.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeRotationMath2Node.cpp
index d01a6e5f0d..1f15333561 100644
--- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeRotationMath2Node.cpp
+++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeRotationMath2Node.cpp
@@ -105,7 +105,6 @@ namespace EMotionFX
         }
 
         // If both x and y inputs have connections
-        //MCore::Quaternion x = MCore::AzQuatToEmfxQuat(m_defaultValue);
         AZ::Quaternion x = m_defaultValue;
         AZ::Quaternion y = x;
         if (mConnections.size() == 2)
diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.cpp
index ab219b2b92..e4663750ce 100644
--- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.cpp
+++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.cpp
@@ -915,7 +915,7 @@ namespace EMStudio
             }
 
             // get the mesh based AABB
-            AZ::Aabb aabb;
+            AZ::Aabb aabb = AZ::Aabb::CreateNull();
             actorInstance->CalcMeshBasedAabb(0, &aabb);
 
             // get the node based AABB
diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderUpdateCallback.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderUpdateCallback.cpp
index 4c032cb2ea..fed309d2e5 100644
--- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderUpdateCallback.cpp
+++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderUpdateCallback.cpp
@@ -170,9 +170,8 @@ namespace EMStudio
             settings.mNodeBasedColor          = renderOptions->GetNodeAABBColor();
             settings.mStaticBasedColor        = renderOptions->GetStaticAABBColor();
             settings.mMeshBasedColor          = renderOptions->GetMeshAABBColor();
-            settings.mCollisionMeshBasedColor = renderOptions->GetCollisionMeshAABBColor();
 
-            renderUtil->RenderAABBs(actorInstance, settings);
+            renderUtil->RenderAabbs(actorInstance, settings);
         }
 
         if (widget->GetRenderFlag(RenderViewWidget::RENDER_OBB))
@@ -260,8 +259,8 @@ namespace EMStudio
         // render the selection
         if (renderOptions->GetRenderSelectionBox() && EMotionFX::GetActorManager().GetNumActorInstances() != 1 && mPlugin->GetCurrentSelection()->CheckIfHasActorInstance(actorInstance))
         {
-            MCore::AABB aabb = actorInstance->GetAABB();
-            aabb.Widen(aabb.CalcRadius() * 0.005f);
+            AZ::Aabb aabb = actorInstance->GetAabb();
+            aabb.Expand(aabb.GetExtents() * 0.005f);
             renderUtil->RenderSelection(aabb, renderOptions->GetSelectionColor());
         }
 
diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderWidget.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderWidget.cpp
index c74f693765..fb0ce4fdbf 100644
--- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderWidget.cpp
+++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderWidget.cpp
@@ -72,9 +72,8 @@ namespace EMStudio
     }
 
     // start view closeup flight
-    void RenderWidget::ViewCloseup(const MCore::AABB& aabb, float flightTime, uint32 viewCloseupWaiting)
+    void RenderWidget::ViewCloseup(const AZ::Aabb& aabb, float flightTime, uint32 viewCloseupWaiting)
     {
-        //LogError("ViewCloseup: AABB: Pos=(%.3f, %.3f, %.3f), Width=%.3f, Height=%.3f, Depth=%.3f", aabb.CalcMiddle().x, aabb.CalcMiddle().y, aabb.CalcMiddle().z, aabb.CalcWidth(), aabb.CalcHeight(), aabb.CalcDepth());
         mViewCloseupWaiting     = viewCloseupWaiting;
         mViewCloseupAABB        = aabb;
         mViewCloseupFlightTime  = flightTime;
@@ -82,9 +81,8 @@ namespace EMStudio
 
     void RenderWidget::ViewCloseup(bool selectedInstancesOnly, float flightTime, uint32 viewCloseupWaiting)
     {
-        //LogError("ViewCloseup: AABB: Pos=(%.3f, %.3f, %.3f), Width=%.3f, Height=%.3f, Depth=%.3f", aabb.CalcMiddle().x, aabb.CalcMiddle().y, aabb.CalcMiddle().z, aabb.CalcWidth(), aabb.CalcHeight(), aabb.CalcDepth());
         mViewCloseupWaiting     = viewCloseupWaiting;
-        mViewCloseupAABB        = mPlugin->GetSceneAABB(selectedInstancesOnly);
+        mViewCloseupAABB        = mPlugin->GetSceneAabb(selectedInstancesOnly);
         mViewCloseupFlightTime  = flightTime;
     }
 
@@ -603,14 +601,15 @@ namespace EMStudio
                             if (actor->CheckIfHasMeshes(actorInstance->GetLODLevel()) == false)
                             {
                                 // calculate the node based AABB
-                                MCore::AABB box;
-                                actorInstance->CalcNodeBasedAABB(&box);
+                                AZ::Aabb box;
+                                actorInstance->CalcNodeBasedAabb(&box);
 
                                 // render the aabb
-                                if (box.CheckIfIsValid())
+                                if (box.IsValid())
                                 {
+                                    const MCore::AABB mcoreAabb(box.GetMin(), box.GetMax());
                                     AZ::Vector3 ii, n;
-                                    if (ray.Intersects(box, &ii, &n))
+                                    if (ray.Intersects(mcoreAabb, &ii, &n))
                                     {
                                         selectedActorInstance = actorInstance;
                                         oldIntersectionPoint = ii;
@@ -1169,8 +1168,7 @@ namespace EMStudio
             mViewCloseupWaiting--;
             if (mViewCloseupWaiting == 0)
             {
-                mCamera->ViewCloseup(mViewCloseupAABB, mViewCloseupFlightTime);
-                //mViewCloseupWaiting = 0;
+                mCamera->ViewCloseup(MCore::AABB(mViewCloseupAABB.GetMin(), mViewCloseupAABB.GetMax()), mViewCloseupFlightTime);
             }
         }
 
diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderWidget.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderWidget.h
index b6776d43a4..10722f744a 100644
--- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderWidget.h
+++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderWidget.h
@@ -6,11 +6,10 @@
  *
  */
 
-#ifndef __EMSTUDIO_RENDERWIDGET_H
-#define __EMSTUDIO_RENDERWIDGET_H
+#pragma once
 
-//
 #if !defined(Q_MOC_RUN)
+#include 
 #include 
 #include "../EMStudioConfig.h"
 #include 
@@ -117,7 +116,7 @@ namespace EMStudio
         MCORE_INLINE MCommon::Camera* GetCamera() const                                                     { return mCamera; }
         MCORE_INLINE CameraMode GetCameraMode() const                                                       { return mCameraMode; }
         MCORE_INLINE void SetSkipFollowCalcs(bool skipFollowCalcs)                                          { mSkipFollowCalcs = skipFollowCalcs; }
-        void ViewCloseup(const MCore::AABB& aabb, float flightTime, uint32 viewCloseupWaiting = 5);
+        void ViewCloseup(const AZ::Aabb& aabb, float flightTime, uint32 viewCloseupWaiting = 5);
         void ViewCloseup(bool selectedInstancesOnly, float flightTime, uint32 viewCloseupWaiting = 5);
         void SwitchCamera(CameraMode mode);
 
@@ -161,7 +160,7 @@ namespace EMStudio
 
         // used for closeup camera flights
         uint32                                  mViewCloseupWaiting;
-        MCore::AABB                             mViewCloseupAABB;
+        AZ::Aabb                                mViewCloseupAABB;
         float                                   mViewCloseupFlightTime;
 
         // manipulator helper data
@@ -175,6 +174,3 @@ namespace EMStudio
         int32                                   mPixelsMovedSinceRightClick;
     };
 } // namespace EMStudio
-
-
-#endif

From b840b24de2c018f0a50f4e580bad54dde07d88c2 Mon Sep 17 00:00:00 2001
From: Benjamin Jillich 
Date: Mon, 2 Aug 2021 14:38:20 +0200
Subject: [PATCH 059/803] Ported the actor and a few other places

* Fixed a bug with updating the static aabb for actors. It called that before the mesh was loaded resulting in an invalid aabb.
* Ported a few more places to AZ::Aabb from MCore::AABB

Signed-off-by: Benjamin Jillich 
---
 .../Code/Source/AtomActorInstance.cpp         |  9 ++---
 .../CommandSystem/Source/ActorCommands.cpp    |  9 ++---
 .../ExporterLib/Exporter/NodeExport.cpp       | 12 +++---
 .../EMotionFX/Code/EMotionFX/Source/Actor.cpp | 38 +++++++++----------
 Gems/EMotionFX/Code/EMotionFX/Source/Actor.h  | 10 ++---
 5 files changed, 37 insertions(+), 41 deletions(-)

diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp
index 706ed27a4d..f9c0242b77 100644
--- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp
+++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp
@@ -83,10 +83,10 @@ namespace AZ
             // Update RenderActorInstance world bounding box
             // The bounding box is moving with the actor instance.
             // The entity and actor transforms are kept in sync already.
-            m_worldAABB = AZ::Aabb::CreateFromMinMax(m_actorInstance->GetAABB().GetMin(), m_actorInstance->GetAABB().GetMax());
+            m_worldAABB = m_actorInstance->GetAabb();
 
             // Update RenderActorInstance local bounding box
-            // NB: computing the local bbox from the world bbox makes the local bbox artifically larger than it should be
+            // NB: computing the local bbox from the world bbox makes the local bbox artificially larger than it should be
             // instead EMFX should support getting the local bbox from the actor instance directly
             m_localAABB = m_worldAABB.GetTransformedAabb(m_transformInterface->GetWorldTM().GetInverse());
 
@@ -107,9 +107,8 @@ namespace AZ
                 {
                     if (debugOptions.m_drawAABB)
                     {
-                        const MCore::AABB emfxAabb = m_actorInstance->GetAABB();
-                        const AZ::Aabb azAabb = AZ::Aabb::CreateFromMinMax(emfxAabb.GetMin(), emfxAabb.GetMax());
-                        auxGeom->DrawAabb(azAabb, AZ::Color(0.0f, 1.0f, 1.0f, 1.0f), RPI::AuxGeomDraw::DrawStyle::Line);
+                        const AZ::Aabb& aabb = m_actorInstance->GetAabb();
+                        auxGeom->DrawAabb(aabb, AZ::Color(0.0f, 1.0f, 1.0f, 1.0f), RPI::AuxGeomDraw::DrawStyle::Line);
                     }
 
                     if (debugOptions.m_drawSkeleton)
diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ActorCommands.cpp b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ActorCommands.cpp
index a21b618b91..52a4ec6a0b 100644
--- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ActorCommands.cpp
+++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ActorCommands.cpp
@@ -1063,11 +1063,10 @@ namespace CommandSystem
                 continue;
             }
 
-            MCore::AABB newAABB;
-            actorInstance->SetStaticBasedAABB(actor->GetStaticAABB());  // this is needed as the CalcStaticBasedAABB uses the current AABB as starting point
-            actorInstance->CalcStaticBasedAABB(&newAABB);
-            actorInstance->SetStaticBasedAABB(newAABB);
-            //actorInstance->UpdateVisualizeScale();
+            actorInstance->SetStaticBasedAabb(actor->GetStaticAabb());  // this is needed as the CalcStaticBasedAabb uses the current AABB as starting point
+            AZ::Aabb newAabb;
+            actorInstance->CalcStaticBasedAabb(&newAabb);
+            actorInstance->SetStaticBasedAabb(newAabb);
 
             const float factor = (float)MCore::Distance::GetConversionFactor(beforeUnitType, targetUnitType);
             actorInstance->SetVisualizeScale(actorInstance->GetVisualizeScale() * factor);
diff --git a/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/NodeExport.cpp b/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/NodeExport.cpp
index a9010fb524..c66c3ca8ef 100644
--- a/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/NodeExport.cpp
+++ b/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/NodeExport.cpp
@@ -184,12 +184,12 @@ namespace ExporterLib
         EMotionFX::FileFormat::Actor_Nodes nodesChunk;
         nodesChunk.mNumNodes        = numNodes;
         nodesChunk.mNumRootNodes    = actor->GetSkeleton()->GetNumRootNodes();
-        nodesChunk.mStaticBoxMin.mX = actor->GetStaticAABB().GetMin().GetX();
-        nodesChunk.mStaticBoxMin.mY = actor->GetStaticAABB().GetMin().GetY();
-        nodesChunk.mStaticBoxMin.mZ = actor->GetStaticAABB().GetMin().GetZ();
-        nodesChunk.mStaticBoxMax.mX = actor->GetStaticAABB().GetMax().GetX();
-        nodesChunk.mStaticBoxMax.mY = actor->GetStaticAABB().GetMax().GetY();
-        nodesChunk.mStaticBoxMax.mZ = actor->GetStaticAABB().GetMax().GetZ();
+        nodesChunk.mStaticBoxMin.mX = actor->GetStaticAabb().GetMin().GetX();
+        nodesChunk.mStaticBoxMin.mY = actor->GetStaticAabb().GetMin().GetY();
+        nodesChunk.mStaticBoxMin.mZ = actor->GetStaticAabb().GetMin().GetZ();
+        nodesChunk.mStaticBoxMax.mX = actor->GetStaticAabb().GetMax().GetX();
+        nodesChunk.mStaticBoxMax.mY = actor->GetStaticAabb().GetMax().GetY();
+        nodesChunk.mStaticBoxMax.mZ = actor->GetStaticAabb().GetMax().GetZ();
 
         // endian conversion and write it
         ConvertUnsignedInt(&nodesChunk.mNumNodes, targetEndianType);
diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp
index 973d8eb460..c55509e817 100644
--- a/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp
+++ b/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp
@@ -97,6 +97,7 @@ namespace EMotionFX
         mID                         = MCore::GetIDGenerator().GenerateID();
         mUnitType                   = GetEMotionFX().GetUnitType();
         mFileUnitType               = mUnitType;
+        m_staticAabb                = AZ::Aabb::CreateNull();
 
         mUsedForVisualization       = false;
         mDirtyFlag                  = false;
@@ -148,7 +149,7 @@ namespace EMotionFX
         result->mMotionExtractionNode   = mMotionExtractionNode;
         result->mUnitType               = mUnitType;
         result->mFileUnitType           = mFileUnitType;
-        result->mStaticAABB             = mStaticAABB;
+        result->m_staticAabb            = m_staticAabb;
         result->mRetargetRootNode       = mRetargetRootNode;
         result->mInvBindPoseTransforms  = mInvBindPoseTransforms;
         result->m_optimizeSkeleton      = m_optimizeSkeleton;
@@ -1405,10 +1406,6 @@ namespace EMotionFX
 
         m_simulatedObjectSetup->InitAfterLoad(this);
 
-        // build the static axis aligned bounding box by creating an actor instance (needed to perform cpu skinning mesh deforms and mesh scaling etc)
-        // then copy it over to the actor
-        UpdateStaticAABB();
-
         // rescale all content if needed
         if (convertUnitType)
         {
@@ -1526,6 +1523,10 @@ namespace EMotionFX
                     mMorphSetups[i] = nullptr;
                 }
             }
+
+            // build the static axis aligned bounding box by creating an actor instance (needed to perform cpu skinning mesh deforms and mesh scaling etc)
+            // then copy it over to the actor
+            UpdateStaticAabb();
         }
 
         m_isReady = true;
@@ -1534,16 +1535,13 @@ namespace EMotionFX
     }
 
     // update the static AABB (very heavy as it has to create an actor instance, update mesh deformers, calculate the mesh based bounds etc)
-    void Actor::UpdateStaticAABB()
+    void Actor::UpdateStaticAabb()
     {
-        if (!mStaticAABB.CheckIfIsValid())
-        {
-            ActorInstance* actorInstance = ActorInstance::Create(this, nullptr, mThreadIndex);
-            //actorInstance->UpdateMeshDeformers(0.0f);
-            //actorInstance->UpdateStaticBasedAABBDimensions();
-            actorInstance->GetStaticBasedAABB(&mStaticAABB);
-            actorInstance->Destroy();
-        }
+        ActorInstance* actorInstance = ActorInstance::Create(this, nullptr, mThreadIndex);
+        actorInstance->UpdateMeshDeformers(0.0f);
+        actorInstance->UpdateStaticBasedAabbDimensions();
+        actorInstance->GetStaticBasedAabb(&m_staticAabb);
+        actorInstance->Destroy();
     }
 
 
@@ -2206,14 +2204,14 @@ namespace EMotionFX
 #endif
     }
 
-    const MCore::AABB& Actor::GetStaticAABB() const
+    const AZ::Aabb& Actor::GetStaticAabb() const
     {
-        return mStaticAABB;
+        return m_staticAabb;
     }
 
-    void Actor::SetStaticAABB(const MCore::AABB& box)
+    void Actor::SetStaticAabb(const AZ::Aabb& aabb)
     {
-        mStaticAABB = box;
+        m_staticAabb = aabb;
     }
 
     //---------------------------------
@@ -2422,8 +2420,8 @@ namespace EMotionFX
         }
 
         // update static aabb
-        mStaticAABB.SetMin(mStaticAABB.GetMin() * scaleFactor);
-        mStaticAABB.SetMax(mStaticAABB.GetMax() * scaleFactor);
+        m_staticAabb.SetMin(m_staticAabb.GetMin() * scaleFactor);
+        m_staticAabb.SetMax(m_staticAabb.GetMax() * scaleFactor);
 
         // update mesh data for all LOD levels
         const uint32 numLODs = GetNumLODLevels();
diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Actor.h b/Gems/EMotionFX/Code/EMotionFX/Source/Actor.h
index 6c3ab6bf29..53cbe7e05a 100644
--- a/Gems/EMotionFX/Code/EMotionFX/Source/Actor.h
+++ b/Gems/EMotionFX/Code/EMotionFX/Source/Actor.h
@@ -16,11 +16,11 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
 // include MCore related files
-#include 
 #include 
 #include 
 #include 
@@ -781,9 +781,9 @@ namespace EMotionFX
         void ResizeTransformData();
         void CopyTransformsFrom(const Actor* other);
 
-        const MCore::AABB& GetStaticAABB() const;
-        void SetStaticAABB(const MCore::AABB& box);
-        void UpdateStaticAABB();    // VERY heavy operation, you shouldn't call this ever (internally creates an actor instance, updates mesh deformers, calcs a mesh based aabb, destroys the actor instance again)
+        const AZ::Aabb& GetStaticAabb() const;
+        void SetStaticAabb(const AZ::Aabb& aabb);
+        void UpdateStaticAabb();    // VERY heavy operation, you shouldn't call this ever (internally creates an actor instance, updates mesh deformers, calcs a mesh based aabb, destroys the actor instance again)
 
         void SetThreadIndex(uint32 index)                   { mThreadIndex = index; }
         uint32 GetThreadIndex() const                       { return mThreadIndex; }
@@ -985,7 +985,7 @@ namespace EMotionFX
         uint32                                          mRetargetRootNode;          /**< The retarget root node, which controls the height displacement of the character. This is most likely the hip or pelvis node. */
         uint32                                          mID;                        /**< The unique identification number for the actor. */
         uint32                                          mThreadIndex;               /**< The thread number we are running on, which is a value starting at 0, up to the number of threads in the job system. */
-        MCore::AABB                                     mStaticAABB;                /**< The static AABB. */
+        AZ::Aabb                                        m_staticAabb;               /**< The static AABB. */
         bool                                            mDirtyFlag;                 /**< The dirty flag which indicates whether the user has made changes to the actor since the last file save operation. */
         bool                                            mUsedForVisualization;      /**< Indicates if the actor is used for visualization specific things and is not used as a normal in-game actor. */
         bool                                            m_optimizeSkeleton;         /**< Indicates if we should perform/ */

From b9cfce8165fd368018a6ea73f25f42828f523899 Mon Sep 17 00:00:00 2001
From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>
Date: Mon, 2 Aug 2021 09:26:06 -0700
Subject: [PATCH 060/803] Gems/AtomLyIntegration

Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>
---
 .../Platform/Windows/FFontXML_Windows.cpp     |  7 +++-
 .../AtomFont/Code/Source/FFont.cpp            | 42 ++++++++++++-------
 .../AtomFont/Code/Source/FontRenderer.cpp     |  7 ++--
 .../AtomFont/Code/Source/FontTexture.cpp      | 10 ++---
 .../AtomFont/Code/Source/GlyphCache.cpp       |  2 +-
 .../Source/AnimGraph/GameController.cpp       | 21 +++++-----
 6 files changed, 53 insertions(+), 36 deletions(-)

diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Platform/Windows/FFontXML_Windows.cpp b/Gems/AtomLyIntegration/AtomFont/Code/Platform/Windows/FFontXML_Windows.cpp
index 4c923c43c4..dc7c6ccbb2 100644
--- a/Gems/AtomLyIntegration/AtomFont/Code/Platform/Windows/FFontXML_Windows.cpp
+++ b/Gems/AtomLyIntegration/AtomFont/Code/Platform/Windows/FFontXML_Windows.cpp
@@ -9,6 +9,7 @@
 #include 
 
 #include 
+#include 
 
 #include 
 
@@ -16,11 +17,13 @@ namespace AtomFontInternal
 {
     void XmlFontShader::FoundElementImpl()
     {
-        TCHAR sysFontPath[MAX_PATH];
-        if (SUCCEEDED(SHGetFolderPath(0, CSIDL_FONTS, 0, SHGFP_TYPE_DEFAULT, sysFontPath)))
+        wchar_t sysFontPathW[MAX_PATH];
+        if (SUCCEEDED(SHGetFolderPath(0, CSIDL_FONTS, 0, SHGFP_TYPE_DEFAULT, sysFontPathW)))
         {
             const AZ::IO::PathView fontName = AZ::IO::PathView(m_strFontPath.c_str()).Filename();
 
+            AZStd::string sysFontPath;
+            AZStd::to_string(sysFontPath, sysFontPathW);
             AZ::IO::Path newFontPath(sysFontPath);
             newFontPath /= fontName;
             m_font->Load(newFontPath.c_str(), m_FontTexSize.x, m_FontTexSize.y, m_slotSizes.x, m_slotSizes.y, CreateTTFFontFlag(m_FontSmoothMethod, m_FontSmoothAmount), m_SizeRatio);
diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp b/Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp
index ddb2fa6292..fe6f733abc 100644
--- a/Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp
+++ b/Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp
@@ -13,6 +13,8 @@
 
 #if !defined(USE_NULLFONT_ALWAYS)
 
+#include 
+
 #include 
 #include 
 #include 
@@ -26,7 +28,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 
 #include 
@@ -409,6 +410,9 @@ Vec2 AZ::FFont::GetTextSizeUInternal(
     const size_t fxIdx = ctx.m_fxIdx < fxSize ? ctx.m_fxIdx : 0;
     const FontEffect& fx = m_effects[fxIdx];
 
+    AZStd::wstring strW;
+    AZStd::to_wstring(strW, str);
+
     for (size_t i = 0, numPasses = fx.m_passes.size(); i < numPasses; ++i)
     {
         const FontRenderingPass* pass = &fx.m_passes[numPasses - i - 1];
@@ -426,7 +430,7 @@ Vec2 AZ::FFont::GetTextSizeUInternal(
 
         // parse the string, ignoring control characters
         uint32_t nextCh = 0;
-        Unicode::CIterator pChar(str);
+        const wchar_t* pChar = strW.c_str();
         while (uint32_t ch = *pChar)
         {
             ++pChar;
@@ -556,6 +560,9 @@ uint32_t AZ::FFont::GetNumQuadsForText(const char* str, const bool asciiMultiLin
     const size_t fxIdx = ctx.m_fxIdx < fxSize ? ctx.m_fxIdx : 0;
     const FontEffect& fx = m_effects[fxIdx];
 
+    AZStd::wstring strW;
+    AZStd::to_wstring(strW, str);
+
     for (size_t j = 0, numPasses = fx.m_passes.size(); j < numPasses; ++j)
     {
         size_t i = numPasses - j - 1;
@@ -567,7 +574,7 @@ uint32_t AZ::FFont::GetNumQuadsForText(const char* str, const bool asciiMultiLin
         }
 
         uint32_t nextCh = 0;
-        Unicode::CIterator pChar(str);
+        const wchar_t* pChar = strW.c_str();
         while (uint32_t ch = *pChar)
         {
             ++pChar;
@@ -862,9 +869,12 @@ int AZ::FFont::CreateQuadsForText(const RHI::Viewport& viewport, float x, float
             }
         }
 
+        AZStd::wstring strW;
+        AZStd::to_wstring(strW, str);
+
         // parse the string, ignoring control characters
         uint32_t nextCh = 0;
-        Unicode::CIterator pChar(str);
+        const wchar_t* pChar = strW.c_str();
         while (uint32_t ch = *pChar)
         {
             ++pChar;
@@ -1188,7 +1198,7 @@ void AZ::FFont::WrapText(AZStd::string& result, float maxWidth, const char* str,
     const bool multiLine = strSize.y > GetRestoredFontSize(ctx).y;
 
     int lastSpace = -1;
-    const char* pLastSpace = NULL;
+    const wchar_t* pLastSpace = NULL;
     float lastSpaceWidth = 0.0f;
 
     float curCharWidth = 0.0f;
@@ -1197,7 +1207,9 @@ void AZ::FFont::WrapText(AZStd::string& result, float maxWidth, const char* str,
     float widthSum = 0.0f;
 
     int curChar = 0;
-    Unicode::CIterator pChar(result.c_str());
+    AZStd::wstring resultW;
+    AZStd::to_wstring(resultW, result.c_str());
+    const wchar_t* pChar = resultW.c_str();
     while (uint32_t ch = *pChar)
     {
         // Dollar sign escape codes.  The following scenarios can happen with dollar signs embedded in a string.
@@ -1224,7 +1236,7 @@ void AZ::FFont::WrapText(AZStd::string& result, float maxWidth, const char* str,
         // get char width and sum it to the line width
         // Note: This is not unicode compatible, since char-width depends on surrounding context (ie, combining diacritics etc)
         char codepoint[5];
-        Unicode::Convert(codepoint, ch);
+        AZStd::to_string(codepoint, 5, (wchar_t*)&ch, 1);
         curCharWidth = GetTextSize(codepoint, true, ctx).x;
 
         // keep track of spaces
@@ -1233,15 +1245,15 @@ void AZ::FFont::WrapText(AZStd::string& result, float maxWidth, const char* str,
         {
             lastSpace = curChar;
             lastSpaceWidth = curLineWidth + curCharWidth;
-            pLastSpace = pChar.GetPosition();
+            pLastSpace = pChar;
             assert(*pLastSpace == ' ');
         }
 
         bool prevCharWasNewline = false;
-        const bool notFirstChar = pChar.GetPosition() != result.c_str();
+        const bool notFirstChar = pChar != resultW.c_str();
         if (*pChar && notFirstChar)
         {
-            const char* pPrevCharStr = pChar.GetPosition() - 1;
+            const wchar_t* pPrevCharStr = pChar - 1;
             prevCharWasNewline = pPrevCharStr[0] == '\n';
         }
 
@@ -1268,12 +1280,12 @@ void AZ::FFont::WrapText(AZStd::string& result, float maxWidth, const char* str,
             }
             else
             {
-                const char* buf = pChar.GetPosition();
-                size_t bytesProcessed = buf - result.c_str();
-                result.insert(bytesProcessed, '\n'); // Insert the newline, this invalidates the iterator
-                buf = result.c_str() + bytesProcessed; // In case reallocation occurs, we ensure we are inside the new buffer
+                const wchar_t* buf = pChar;
+                size_t bytesProcessed = buf - resultW.c_str();
+                resultW.insert(resultW.begin() + bytesProcessed, L'\n'); // Insert the newline, this invalidates the iterator
+                buf = resultW.c_str() + bytesProcessed; // In case reallocation occurs, we ensure we are inside the new buffer
                 assert(*buf == '\n');
-                pChar.SetPosition(buf); // pChar once again points inside the target string, at the current character
+                pChar = buf; // pChar once again points inside the target string, at the current character
                 assert(*pChar == ch);
                 ++pChar;
                 ++curChar;
diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Source/FontRenderer.cpp b/Gems/AtomLyIntegration/AtomFont/Code/Source/FontRenderer.cpp
index 101a506ddc..17ac896cf7 100644
--- a/Gems/AtomLyIntegration/AtomFont/Code/Source/FontRenderer.cpp
+++ b/Gems/AtomLyIntegration/AtomFont/Code/Source/FontRenderer.cpp
@@ -22,6 +22,8 @@
 
 #include 
 
+#include 
+
 // Sizes are defined in in 26.6 fixed float format (TT_F26Dot6), where
 // 1 unit is 1/64 of a pixel.
 constexpr int FractionalPixelUnits = 64;
@@ -94,7 +96,7 @@ AZ::FontRenderer::~FontRenderer()
 }
 
 //-------------------------------------------------------------------------------------------------
-int AZ::FontRenderer::LoadFromFile(const string& fileName)
+int AZ::FontRenderer::LoadFromFile(const AZStd::string& fileName)
 {
     int iError = FT_Init_FreeType(&m_library);
 
@@ -309,8 +311,7 @@ Vec2 AZ::FontRenderer::GetKerning(uint32_t leftGlyph, uint32_t rightGlyph)
 #if !defined(_RELEASE)
         if (0 != ftError)
         {
-            string warnMsg;
-            warnMsg.Format("FT_Get_Kerning returned %d", ftError);
+            AZStd::string warnMsg = AZStd::string::format("FT_Get_Kerning returned %d", ftError);
             CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, warnMsg.c_str());
         }
 #endif
diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Source/FontTexture.cpp b/Gems/AtomLyIntegration/AtomFont/Code/Source/FontTexture.cpp
index 6008881ec3..1ee7f80eda 100644
--- a/Gems/AtomLyIntegration/AtomFont/Code/Source/FontTexture.cpp
+++ b/Gems/AtomLyIntegration/AtomFont/Code/Source/FontTexture.cpp
@@ -14,8 +14,8 @@
 #if !defined(USE_NULLFONT_ALWAYS)
 
 #include 
-#include 
 #include 
+#include 
 
 //-------------------------------------------------------------------------------------------------
 AZ::FontTexture::FontTexture()
@@ -44,7 +44,7 @@ AZ::FontTexture::~FontTexture()
 }
 
 //-------------------------------------------------------------------------------------------------
-int AZ::FontTexture::CreateFromFile(const string& fileName, int width, int height, AZ::FontSmoothMethod smoothMethod, AZ::FontSmoothAmount smoothAmount, int widthCellCount, int heightCellCount)
+int AZ::FontTexture::CreateFromFile(const AZStd::string& fileName, int width, int height, AZ::FontSmoothMethod smoothMethod, AZ::FontSmoothAmount smoothAmount, int widthCellCount, int heightCellCount)
 {
     if (!m_glyphCache.LoadFontFromFile(fileName))
     {
@@ -255,10 +255,10 @@ int AZ::FontTexture::PreCacheString(const char* string, int* updated, float size
     uint16_t slotUsage = m_slotUsage++;
     int updateCount = 0;
 
-    uint32_t character;
-    for (Unicode::CIterator it(string); *it; ++it)
+    AZStd::wstring stringW;
+    AZStd::to_wstring(stringW, string);
+    for (wchar_t character : stringW)
     {
-        character = *it;
         TextureSlot* slot = GetCharSlot(character, clampedGlyphSize);
 
         if (!slot)
diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Source/GlyphCache.cpp b/Gems/AtomLyIntegration/AtomFont/Code/Source/GlyphCache.cpp
index 12ebd99183..ee52d36af5 100644
--- a/Gems/AtomLyIntegration/AtomFont/Code/Source/GlyphCache.cpp
+++ b/Gems/AtomLyIntegration/AtomFont/Code/Source/GlyphCache.cpp
@@ -124,7 +124,7 @@ int AZ::GlyphCache::Release()
 }
 
 //-------------------------------------------------------------------------------------------------
-int AZ::GlyphCache::LoadFontFromFile(const string& fileName)
+int AZ::GlyphCache::LoadFontFromFile(const AZStd::string & fileName)
 {
     return m_fontRenderer.LoadFromFile(fileName);
 }
diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GameController.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GameController.cpp
index 7038441e4c..c3b929ae7a 100644
--- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GameController.cpp
+++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GameController.cpp
@@ -12,6 +12,7 @@
 #if AZ_TRAIT_EMOTIONFX_HAS_GAME_CONTROLLER
 
 #include 
+#include 
 
 
 // joystick enum callback
@@ -20,7 +21,7 @@ BOOL CALLBACK GameController::EnumJoysticksCallback(const DIDEVICEINSTANCE* pdid
     GameController* manager = static_cast(pContext);
 
     // store the name
-    manager->mDeviceInfo.mName = pdidInstance->tszProductName;
+    AZStd::to_string(manager->mDeviceInfo.mName, pdidInstance->tszProductName);
 
     // Skip anything other than the perferred Joystick device as defined by the control panel.
     // Instead you could store all the enumerated Joysticks and let the user pick.
@@ -71,7 +72,7 @@ BOOL CALLBACK GameController::EnumObjectsCallback(const DIDEVICEOBJECTINSTANCE*
 
     if (pdidoi->guidType == GUID_XAxis)
     {
-        manager->mDeviceElements[ ELEM_POS_X ].mName                = pdidoi->tszName;
+        AZStd::to_string(manager->mDeviceElements[ ELEM_POS_X ].mName, pdidoi->tszName);
         manager->mDeviceElements[ ELEM_POS_X ].mPresent             = true;
         manager->mDeviceElements[ ELEM_POS_X ].mValue               = 0.0f;
         //manager->mDeviceElements[ ELEM_POS_X ].mCalibrationValue  = 0.0f;
@@ -81,7 +82,7 @@ BOOL CALLBACK GameController::EnumObjectsCallback(const DIDEVICEOBJECTINSTANCE*
 
     if (pdidoi->guidType == GUID_YAxis)
     {
-        manager->mDeviceElements[ ELEM_POS_Y ].mName                = pdidoi->tszName;
+        AZStd::to_string(manager->mDeviceElements[ ELEM_POS_Y ].mName, pdidoi->tszName);
         manager->mDeviceElements[ ELEM_POS_Y ].mPresent             = true;
         manager->mDeviceElements[ ELEM_POS_Y ].mValue               = 0.0f;
         //manager->mDeviceElements[ ELEM_POS_Y ].mCalibrationValue  = 0.0f;
@@ -91,7 +92,7 @@ BOOL CALLBACK GameController::EnumObjectsCallback(const DIDEVICEOBJECTINSTANCE*
 
     if (pdidoi->guidType == GUID_ZAxis)
     {
-        manager->mDeviceElements[ ELEM_POS_Z ].mName                = pdidoi->tszName;
+        AZStd::to_string(manager->mDeviceElements[ ELEM_POS_Z ].mName, pdidoi->tszName);
         manager->mDeviceElements[ ELEM_POS_Z ].mPresent             = true;
         manager->mDeviceElements[ ELEM_POS_Z ].mValue               = 0.0f;
         //manager->mDeviceElements[ ELEM_POS_Z ].mCalibrationValue  = 0.0f;
@@ -101,7 +102,7 @@ BOOL CALLBACK GameController::EnumObjectsCallback(const DIDEVICEOBJECTINSTANCE*
 
     if (pdidoi->guidType == GUID_RxAxis)
     {
-        manager->mDeviceElements[ ELEM_ROT_X ].mName                = pdidoi->tszName;
+        AZStd::to_string(manager->mDeviceElements[ ELEM_ROT_X ].mName, pdidoi->tszName);
         manager->mDeviceElements[ ELEM_ROT_X ].mPresent             = true;
         manager->mDeviceElements[ ELEM_ROT_X ].mValue               = 0.0f;
         //manager->mDeviceElements[ ELEM_ROT_X ].mCalibrationValue  = 0.0f;
@@ -111,7 +112,7 @@ BOOL CALLBACK GameController::EnumObjectsCallback(const DIDEVICEOBJECTINSTANCE*
 
     if (pdidoi->guidType == GUID_RyAxis)
     {
-        manager->mDeviceElements[ ELEM_ROT_Y ].mName                = pdidoi->tszName;
+        AZStd::to_string(manager->mDeviceElements[ ELEM_ROT_Y ].mName, pdidoi->tszName);
         manager->mDeviceElements[ ELEM_ROT_Y ].mPresent             = true;
         manager->mDeviceElements[ ELEM_ROT_Y ].mValue               = 0.0f;
         //manager->mDeviceElements[ ELEM_ROT_Y ].mCalibrationValue  = 0.0f;
@@ -121,7 +122,7 @@ BOOL CALLBACK GameController::EnumObjectsCallback(const DIDEVICEOBJECTINSTANCE*
 
     if (pdidoi->guidType == GUID_RzAxis)
     {
-        manager->mDeviceElements[ ELEM_ROT_Z ].mName                = pdidoi->tszName;
+        AZStd::to_string(manager->mDeviceElements[ ELEM_ROT_Z ].mName, pdidoi->tszName);
         manager->mDeviceElements[ ELEM_ROT_Z ].mPresent             = true;
         manager->mDeviceElements[ ELEM_ROT_Z ].mValue               = 0.0f;
         //manager->mDeviceElements[ ELEM_ROT_Z ].mCalibrationValue  = 0.0f;
@@ -134,7 +135,7 @@ BOOL CALLBACK GameController::EnumObjectsCallback(const DIDEVICEOBJECTINSTANCE*
     {
         if (manager->mDeviceInfo.mNumSliders == 0)
         {
-            manager->mDeviceElements[ ELEM_SLIDER_1 ].mName                 = pdidoi->tszName;
+            AZStd::to_string(manager->mDeviceElements[ ELEM_SLIDER_1 ].mName, pdidoi->tszName);
             manager->mDeviceElements[ ELEM_SLIDER_1 ].mPresent              = true;
             manager->mDeviceElements[ ELEM_SLIDER_1 ].mValue                = 0.0f;
             //manager->mDeviceElements[ ELEM_SLIDER_1 ].mCalibrationValue   = 0.0f;
@@ -142,7 +143,7 @@ BOOL CALLBACK GameController::EnumObjectsCallback(const DIDEVICEOBJECTINSTANCE*
         }
         else
         {
-            manager->mDeviceElements[ ELEM_SLIDER_2 ].mName                 = pdidoi->tszName;
+            AZStd::to_string(manager->mDeviceElements[ ELEM_SLIDER_2 ].mName, pdidoi->tszName);
             manager->mDeviceElements[ ELEM_SLIDER_2 ].mPresent              = true;
             manager->mDeviceElements[ ELEM_SLIDER_2 ].mValue                = 0.0f;
             //manager->mDeviceElements[ ELEM_SLIDER_2 ].mCalibrationValue   = 0.0f;
@@ -156,7 +157,7 @@ BOOL CALLBACK GameController::EnumObjectsCallback(const DIDEVICEOBJECTINSTANCE*
     if (pdidoi->guidType == GUID_POV)
     {
         const uint32 povIndex = manager->mDeviceInfo.mNumPOVs;
-        manager->mDeviceElements[ ELEM_POV_1 + povIndex ].mName                 = pdidoi->tszName;
+        AZStd::to_string(manager->mDeviceElements[ ELEM_POV_1 + povIndex ].mName, pdidoi->tszName);
         manager->mDeviceElements[ ELEM_POV_1 + povIndex ].mPresent              = true;
         manager->mDeviceElements[ ELEM_POV_1 + povIndex ].mValue                = 0.0f;
         //manager->mDeviceElements[ ELEM_POV_1 + povIndex ].mCalibrationValue   = 0.0f;

From db7536acda4583ff46d2e4f84618e086f2577565 Mon Sep 17 00:00:00 2001
From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>
Date: Mon, 2 Aug 2021 11:44:34 -0700
Subject: [PATCH 061/803] Gems/Maestro

Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>
---
 Code/Editor/Export/ExportManager.cpp          |  2 +-
 Code/Editor/TrackView/CommentNodeAnimator.cpp |  2 +-
 .../TrackView/TrackViewDopeSheetBase.cpp      |  6 ++---
 Code/Editor/TrackView/TrackViewNodes.cpp      |  2 +-
 Code/Legacy/CryCommon/ISurfaceType.h          | 14 +++++------
 Code/Legacy/CryCommon/Mocks/IRendererMock.h   |  2 +-
 Code/Legacy/CryCommon/Mocks/ISystemMock.h     |  2 +-
 Code/Legacy/CryCommon/WinBase.cpp             | 10 ++++----
 Code/Legacy/CryCommon/platform_impl.cpp       |  2 +-
 Code/Legacy/CrySystem/XConsole.cpp            |  2 +-
 .../Support/include/CrashSupport.h            | 24 ++++++++-----------
 .../Components/BlastSystemComponent.cpp       |  1 +
 .../Animation/UiAnimViewDopeSheetBase.cpp     |  6 ++---
 .../Source/Cinematics/AnimComponentNode.h     |  6 ++---
 .../Code/Source/Cinematics/AnimPostFXNode.cpp |  2 +-
 .../Code/Source/Cinematics/AnimSequence.cpp   | 17 ++-----------
 .../Code/Source/Cinematics/AnimSequence.h     |  2 +-
 .../Source/Cinematics/CompoundSplineTrack.cpp | 10 ++++----
 .../Source/Cinematics/CompoundSplineTrack.h   |  2 +-
 .../Code/Source/Cinematics/EventTrack.cpp     |  4 ++--
 .../Code/Source/Cinematics/MaterialNode.h     |  2 +-
 Gems/Maestro/Code/Source/Cinematics/Movie.cpp | 23 +++++++++---------
 .../Code/Source/Cinematics/SceneNode.cpp      |  4 ++--
 .../Source/Cinematics/ScreenFaderTrack.cpp    |  2 +-
 .../Source/Cinematics/TrackEventTrack.cpp     |  4 ++--
 25 files changed, 68 insertions(+), 85 deletions(-)

diff --git a/Code/Editor/Export/ExportManager.cpp b/Code/Editor/Export/ExportManager.cpp
index 03aa0bed8b..5ba250c960 100644
--- a/Code/Editor/Export/ExportManager.cpp
+++ b/Code/Editor/Export/ExportManager.cpp
@@ -46,7 +46,7 @@ namespace
         SEfResTexture* pTex = pRes->GetTextureResource(nSlot);
         if (pTex)
         {
-            cry_strcat(outName, Path::GamePathToFullPath(pTex->m_Name.c_str()).toUtf8().data());
+            azstrcat(outName, Path::GamePathToFullPath(pTex->m_Name.c_str()).toUtf8().data());
         }
     }
 
diff --git a/Code/Editor/TrackView/CommentNodeAnimator.cpp b/Code/Editor/TrackView/CommentNodeAnimator.cpp
index 47f4c5d9ae..579bba00ef 100644
--- a/Code/Editor/TrackView/CommentNodeAnimator.cpp
+++ b/Code/Editor/TrackView/CommentNodeAnimator.cpp
@@ -92,7 +92,7 @@ void CCommentNodeAnimator::AnimateCommentTextTrack(CTrackViewTrack* pTrack, cons
         if (commentKey.m_duration > 0 && ac.time < keyHandle.GetTime() + commentKey.m_duration)
         {
             m_commentContext.m_strComment = commentKey.m_strComment;
-            cry_strcpy(m_commentContext.m_strFont,  commentKey.m_strFont.c_str());
+            azstrcpy(m_commentContext.m_strFont,  commentKey.m_strFont.c_str());
             m_commentContext.m_color = commentKey.m_color;
             m_commentContext.m_align = commentKey.m_align;
             m_commentContext.m_size = commentKey.m_size;
diff --git a/Code/Editor/TrackView/TrackViewDopeSheetBase.cpp b/Code/Editor/TrackView/TrackViewDopeSheetBase.cpp
index 34ca2f062f..f66bb19bf3 100644
--- a/Code/Editor/TrackView/TrackViewDopeSheetBase.cpp
+++ b/Code/Editor/TrackView/TrackViewDopeSheetBase.cpp
@@ -2808,10 +2808,10 @@ void CTrackViewDopeSheetBase::DrawKeys(CTrackViewTrack* pTrack, QPainter* painte
                 }
                 else
                 {
-                    cry_strcpy(keydesc, "{");
+                    azstrcpy(keydesc, "{");
                 }
-                cry_strcat(keydesc, pDescription);
-                cry_strcat(keydesc, "}");
+                azstrcat(keydesc, pDescription);
+                azstrcat(keydesc, "}");
                 // Draw key description text.
                 // Find next key.
                 const QRect textRect(QPoint(x + 10, rect.top()), QPoint(x1, rect.bottom()));
diff --git a/Code/Editor/TrackView/TrackViewNodes.cpp b/Code/Editor/TrackView/TrackViewNodes.cpp
index d69c256049..90e5598876 100644
--- a/Code/Editor/TrackView/TrackViewNodes.cpp
+++ b/Code/Editor/TrackView/TrackViewNodes.cpp
@@ -2516,7 +2516,7 @@ int CTrackViewNodesCtrl::GetMatNameAndSubMtlIndexFromName(QString& matName, cons
     if (const char* pCh = strstr(nodeName, ".["))
     {
         char matPath[MAX_PATH];
-        cry_strcpy(matPath, nodeName, (size_t)(pCh - nodeName));
+        azstrcpy(matPath, nodeName, (size_t)(pCh - nodeName));
         matName = matPath;
         pCh += 2;
         if ((*pCh) != 0)
diff --git a/Code/Legacy/CryCommon/ISurfaceType.h b/Code/Legacy/CryCommon/ISurfaceType.h
index db5ec4eed4..10bddbbe6c 100644
--- a/Code/Legacy/CryCommon/ISurfaceType.h
+++ b/Code/Legacy/CryCommon/ISurfaceType.h
@@ -85,7 +85,7 @@ struct ISurfaceType
     };
     struct SBreakable2DParams
     {
-        string particle_effect;
+        AZStd::string particle_effect;
         float blast_radius;
         float blast_radius_first;
         float vert_size_spread;
@@ -97,12 +97,12 @@ struct ISurfaceType
         float shard_density;
         int use_edge_alpha;
         float crack_decal_scale;
-        string crack_decal_mtl;
+        AZStd::string crack_decal_mtl;
         float max_fracture;
-        string full_fracture_fx;
-        string fracture_fx;
+        AZStd::string full_fracture_fx;
+        AZStd::string fracture_fx;
         int no_procedural_full_fracture;
-        string broken_mtl;
+        AZStd::string broken_mtl;
         float destroy_timeout;
         float destroy_timeout_spread;
 
@@ -125,8 +125,8 @@ struct ISurfaceType
     };
     struct SBreakageParticles
     {
-        string type;
-        string particle_effect;
+        AZStd::string type;
+        AZStd::string particle_effect;
         int count_per_unit;
         float count_scale;
         float scale;
diff --git a/Code/Legacy/CryCommon/Mocks/IRendererMock.h b/Code/Legacy/CryCommon/Mocks/IRendererMock.h
index ff3550a738..be9c1eec8b 100644
--- a/Code/Legacy/CryCommon/Mocks/IRendererMock.h
+++ b/Code/Legacy/CryCommon/Mocks/IRendererMock.h
@@ -283,7 +283,7 @@ public:
     MOCK_METHOD0(EF_GetShaderMissLogPath,
         const char*());
     MOCK_METHOD1(EF_GetShaderNames,
-        string * (int& nNumShaders));
+        AZStd::string * (int& nNumShaders));
     MOCK_METHOD1(EF_ReloadFile,
         bool(const char* szFileName));
     MOCK_METHOD1(EF_ReloadFile_Request,
diff --git a/Code/Legacy/CryCommon/Mocks/ISystemMock.h b/Code/Legacy/CryCommon/Mocks/ISystemMock.h
index d891365696..9e4b7c99ec 100644
--- a/Code/Legacy/CryCommon/Mocks/ISystemMock.h
+++ b/Code/Legacy/CryCommon/Mocks/ISystemMock.h
@@ -122,7 +122,7 @@ public:
         const SFileVersion&());
 
     MOCK_METHOD1(AddCVarGroupDirectory,
-        void(const string&));
+        void(const AZStd::string&));
     MOCK_METHOD0(SaveConfiguration,
         void());
     MOCK_METHOD3(LoadConfiguration,
diff --git a/Code/Legacy/CryCommon/WinBase.cpp b/Code/Legacy/CryCommon/WinBase.cpp
index a60dbdf00b..fe9c539569 100644
--- a/Code/Legacy/CryCommon/WinBase.cpp
+++ b/Code/Legacy/CryCommon/WinBase.cpp
@@ -349,23 +349,23 @@ void _makepath(char* path, const char* drive, const char* dir, const char* filen
     }
     if (dir && dir[0])
     {
-        cry_strcat(tmp, dir);
+        azstrcat(tmp, dir);
         ch = tmp[strlen(tmp) - 1];
         if (ch != '/' && ch != '\\')
         {
-            cry_strcat(tmp, "\\");
+            azstrcat(tmp, "\\");
         }
     }
     if (filename && filename[0])
     {
-        cry_strcat(tmp, filename);
+        azstrcat(tmp, filename);
         if (ext && ext[0])
         {
             if (ext[0] != '.')
             {
-                cry_strcat(tmp, ".");
+                azstrcat(tmp, ".");
             }
-            cry_strcat(tmp, ext);
+            azstrcat(tmp, ext);
         }
     }
     azstrcpy(path, strlen(tmp) + 1, tmp);
diff --git a/Code/Legacy/CryCommon/platform_impl.cpp b/Code/Legacy/CryCommon/platform_impl.cpp
index 6badd2fe1e..1523622538 100644
--- a/Code/Legacy/CryCommon/platform_impl.cpp
+++ b/Code/Legacy/CryCommon/platform_impl.cpp
@@ -499,7 +499,7 @@ inline void CryDebugStr([[maybe_unused]] const char* format, ...)
      va_start(ArgList, format);
      azvsnprintf(szBuffer,sizeof(szBuffer)-1, format, ArgList);
      va_end(ArgList);
-     cry_strcat(szBuffer,"\n");
+     azstrcat(szBuffer,"\n");
      OutputDebugString(szBuffer);
      #endif
      */
diff --git a/Code/Legacy/CrySystem/XConsole.cpp b/Code/Legacy/CrySystem/XConsole.cpp
index f5e946be43..2348e78a0e 100644
--- a/Code/Legacy/CrySystem/XConsole.cpp
+++ b/Code/Legacy/CrySystem/XConsole.cpp
@@ -1545,7 +1545,7 @@ const char* CXConsole::GetFlagsString(const uint32 dwFlags)
     static char sFlags[256];
 
     // hiding this makes it a bit more difficult for cheaters
-    //  if(dwFlags&VF_CHEAT)                  cry_strcat( sFlags,"CHEAT, ");
+    //  if(dwFlags&VF_CHEAT)                  azstrcat( sFlags,"CHEAT, ");
 
     azstrcpy(sFlags, "");
 
diff --git a/Code/Tools/CrashHandler/Support/include/CrashSupport.h b/Code/Tools/CrashHandler/Support/include/CrashSupport.h
index 9932d950d4..1393930913 100644
--- a/Code/Tools/CrashHandler/Support/include/CrashSupport.h
+++ b/Code/Tools/CrashHandler/Support/include/CrashSupport.h
@@ -11,6 +11,8 @@
 #pragma once
 
 #include 
+#include 
+#include 
 
 #include 
 #include 
@@ -23,30 +25,24 @@
 namespace CrashHandler
 {
     std::string GetTimeString();
-    void GetExecutablePathA(char* pathBuffer, int& bufferSize);
-    void GetExecutablePathW(wchar_t* pathBuffer, int& bufferSize);
     void GetTimeInfo(tm& curTime);
 
-    template 
-    inline void GetExecutablePath(T& returnPath)
+    inline void GetExecutablePath(std::string& returnPath)
     {
         char currentFileName[CRASH_HANDLER_MAX_PATH_LEN] = { 0 };
-        int bufferLen{ CRASH_HANDLER_MAX_PATH_LEN };
-        GetExecutablePathA(currentFileName, bufferLen);
+        AZ::Utils::GetExecutablePath(currentFileName, CRASH_HANDLER_MAX_PATH_LEN);
 
         returnPath = currentFileName;
         std::replace(returnPath.begin(), returnPath.end(), '\\', '/');
     }
 
-    template <>
-    inline void GetExecutablePath(std::wstring& returnPath)
+    inline void GetExecutablePath(std::wstring& returnPathW)
     {
-        wchar_t currentFileName[CRASH_HANDLER_MAX_PATH_LEN] = { 0 };
-        int bufferLen{ CRASH_HANDLER_MAX_PATH_LEN };
-        GetExecutablePathW(currentFileName, bufferLen);
-
-        returnPath = currentFileName;
-        std::replace(returnPath.begin(), returnPath.end(), '\\', '/');
+        std::string returnPath;
+        GetExecutablePath(returnPath);
+        wchar_t currentFileNameW[CRASH_HANDLER_MAX_PATH_LEN] = { 0 };
+        AZStd::to_wstring(currentFileNameW, CRASH_HANDLER_MAX_PATH_LEN, returnPath.c_str(), returnPath.size());
+        returnPathW = currentFileNameW;
     }
 
     template
diff --git a/Gems/Blast/Code/Source/Components/BlastSystemComponent.cpp b/Gems/Blast/Code/Source/Components/BlastSystemComponent.cpp
index 933633b5e3..bee94ed116 100644
--- a/Gems/Blast/Code/Source/Components/BlastSystemComponent.cpp
+++ b/Gems/Blast/Code/Source/Components/BlastSystemComponent.cpp
@@ -32,6 +32,7 @@
 #include 
 #include 
 #endif
+#include 
 
 namespace Blast
 {
diff --git a/Gems/LyShine/Code/Editor/Animation/UiAnimViewDopeSheetBase.cpp b/Gems/LyShine/Code/Editor/Animation/UiAnimViewDopeSheetBase.cpp
index f9ce0e522f..ae0880e98e 100644
--- a/Gems/LyShine/Code/Editor/Animation/UiAnimViewDopeSheetBase.cpp
+++ b/Gems/LyShine/Code/Editor/Animation/UiAnimViewDopeSheetBase.cpp
@@ -2362,10 +2362,10 @@ void CUiAnimViewDopeSheetBase::DrawKeys(CUiAnimViewTrack* pTrack, QPainter* pain
                 }
                 else
                 {
-                    cry_strcpy(keydesc, "{");
+                    azstrcpy(keydesc, "{");
                 }
-                cry_strcat(keydesc, pDescription);
-                cry_strcat(keydesc, "}");
+                azstrcat(keydesc, pDescription);
+                azstrcat(keydesc, "}");
                 // Draw key description text.
                 // Find next key.
                 const QRect textRect(QPoint(x + 10, rect.top()), QPoint(x1, rect.bottom()));
diff --git a/Gems/Maestro/Code/Source/Cinematics/AnimComponentNode.h b/Gems/Maestro/Code/Source/Cinematics/AnimComponentNode.h
index 4df6021aa9..5ad3ab6f94 100644
--- a/Gems/Maestro/Code/Source/Cinematics/AnimComponentNode.h
+++ b/Gems/Maestro/Code/Source/Cinematics/AnimComponentNode.h
@@ -144,7 +144,7 @@ private:
     {
     public:
         BehaviorPropertyInfo() {}
-        BehaviorPropertyInfo(const string& name)
+        BehaviorPropertyInfo(const AZStd::string& name)
         {
             *this = name;
         }
@@ -154,7 +154,7 @@ private:
             m_animNodeParamInfo.paramType = other.m_displayName;
             m_animNodeParamInfo.name = &m_displayName[0];
         }
-        BehaviorPropertyInfo& operator=(const string& str)
+        BehaviorPropertyInfo& operator=(const AZStd::string& str)
         {
             // TODO: clean this up - this weird memory sharing was copied from legacy Cry - could be better.
             m_displayName = str;
@@ -163,7 +163,7 @@ private:
             return *this;
         }
 
-        string     m_displayName;
+        AZStd::string m_displayName;
         SParamInfo m_animNodeParamInfo;
     };
     
diff --git a/Gems/Maestro/Code/Source/Cinematics/AnimPostFXNode.cpp b/Gems/Maestro/Code/Source/Cinematics/AnimPostFXNode.cpp
index 78d878c0eb..fd7f99c9b3 100644
--- a/Gems/Maestro/Code/Source/Cinematics/AnimPostFXNode.cpp
+++ b/Gems/Maestro/Code/Source/Cinematics/AnimPostFXNode.cpp
@@ -39,7 +39,7 @@ public:
         virtual void GetDefault(bool& val) const = 0;
         virtual void GetDefault(Vec4& val) const = 0;
 
-        string m_name;
+        AZStd::string m_name;
 
     protected:
         virtual ~CControlParamBase(){}
diff --git a/Gems/Maestro/Code/Source/Cinematics/AnimSequence.cpp b/Gems/Maestro/Code/Source/Cinematics/AnimSequence.cpp
index e9f77f7947..23017e5779 100644
--- a/Gems/Maestro/Code/Source/Cinematics/AnimSequence.cpp
+++ b/Gems/Maestro/Code/Source/Cinematics/AnimSequence.cpp
@@ -98,10 +98,10 @@ void CAnimSequence::SetName(const char* name)
         return;   // should never happen, null pointer guard
     }
 
-    string originalName = GetName();
+    AZStd::string originalName = GetName();
 
     m_name = name;
-    m_pMovieSystem->OnSequenceRenamed(originalName, m_name.c_str());
+    m_pMovieSystem->OnSequenceRenamed(originalName.c_str(), m_name.c_str());
 
     // the sequence named LIGHT_ANIMATION_SET_NAME is a singleton sequence to hold all light animations.
     if (m_name == LIGHT_ANIMATION_SET_NAME)
@@ -744,9 +744,6 @@ void CAnimSequence::Deactivate()
         static_cast(animNode)->OnReset();
     }
 
-    // Remove a possibly cached game hint associated with this anim sequence.
-    stack_string sTemp("anim_sequence_");
-    sTemp += m_name.c_str();
     // Audio: Release precached sound
 
     m_bActive = false;
@@ -776,16 +773,6 @@ void CAnimSequence::PrecacheStatic(const float startTime)
         return;
     }
 
-    // Try to cache this sequence's game hint if one exists.
-    stack_string sTemp("anim_sequence_");
-    sTemp += m_name.c_str();
-
-    //if (gEnv->pAudioSystem)
-    {
-        // Make sure to use the non-serializable game hint type as trackview sequences get properly reactivated after load
-        // Audio: Precache sound
-    }
-
     gEnv->pLog->Log("=== Precaching render data for cutscene: %s ===", GetName());
 
     m_precached = true;
diff --git a/Gems/Maestro/Code/Source/Cinematics/AnimSequence.h b/Gems/Maestro/Code/Source/Cinematics/AnimSequence.h
index 2c12f6e5ea..f69017c3a6 100644
--- a/Gems/Maestro/Code/Source/Cinematics/AnimSequence.h
+++ b/Gems/Maestro/Code/Source/Cinematics/AnimSequence.h
@@ -174,7 +174,7 @@ private:
 
     uint32 m_id;
     AZStd::string m_name;
-    mutable string m_fullNameHolder;
+    mutable AZStd::string m_fullNameHolder;
     Range m_timeRange;
     TrackEvents m_events;
 
diff --git a/Gems/Maestro/Code/Source/Cinematics/CompoundSplineTrack.cpp b/Gems/Maestro/Code/Source/Cinematics/CompoundSplineTrack.cpp
index 4dd52a734a..62de2dfdf5 100644
--- a/Gems/Maestro/Code/Source/Cinematics/CompoundSplineTrack.cpp
+++ b/Gems/Maestro/Code/Source/Cinematics/CompoundSplineTrack.cpp
@@ -457,31 +457,31 @@ void CCompoundSplineTrack::GetKeyInfo(int key, const char*& description, float&
         {
             float dummy;
             m_subTracks[0]->GetKeyInfo(m, subDesc, dummy);
-            cry_strcat(str, subDesc);
+            azstrcat(str, subDesc);
             break;
         }
     }
     if (m == m_subTracks[0]->GetNumKeys())
     {
-        cry_strcat(str, m_subTrackNames[0].c_str());
+        azstrcat(str, m_subTrackNames[0].c_str());
     }
     // Tail cases
     for (int i = 1; i < GetSubTrackCount(); ++i)
     {
-        cry_strcat(str, ",");
+        azstrcat(str, ",");
         for (m = 0; m < m_subTracks[i]->GetNumKeys(); ++m)
         {
             if (m_subTracks[i]->GetKeyTime(m) == time)
             {
                 float dummy;
                 m_subTracks[i]->GetKeyInfo(m, subDesc, dummy);
-                cry_strcat(str, subDesc);
+                azstrcat(str, subDesc);
                 break;
             }
         }
         if (m == m_subTracks[i]->GetNumKeys())
         {
-            cry_strcat(str, m_subTrackNames[i].c_str());
+            azstrcat(str, m_subTrackNames[i].c_str());
         }
     }
 }
diff --git a/Gems/Maestro/Code/Source/Cinematics/CompoundSplineTrack.h b/Gems/Maestro/Code/Source/Cinematics/CompoundSplineTrack.h
index f22b0fb144..b0a2733316 100644
--- a/Gems/Maestro/Code/Source/Cinematics/CompoundSplineTrack.h
+++ b/Gems/Maestro/Code/Source/Cinematics/CompoundSplineTrack.h
@@ -108,7 +108,7 @@ public:
 
     virtual int NextKeyByTime(int key) const;
 
-    void SetSubTrackName(const int i, const string& name) { assert (i < MAX_SUBTRACKS); m_subTrackNames[i] = name; }
+    void SetSubTrackName(const int i, const AZStd::string& name) { assert (i < MAX_SUBTRACKS); m_subTrackNames[i] = name; }
 
 #ifdef MOVIESYSTEM_SUPPORT_EDITING
     virtual ColorB GetCustomColor() const
diff --git a/Gems/Maestro/Code/Source/Cinematics/EventTrack.cpp b/Gems/Maestro/Code/Source/Cinematics/EventTrack.cpp
index 278833cfe2..36d468e36d 100644
--- a/Gems/Maestro/Code/Source/Cinematics/EventTrack.cpp
+++ b/Gems/Maestro/Code/Source/Cinematics/EventTrack.cpp
@@ -72,8 +72,8 @@ void CEventTrack::GetKeyInfo(int key, const char*& description, float& duration)
     azstrcpy(desc, m_keys[key].event.c_str());
     if (!m_keys[key].eventValue.empty())
     {
-        cry_strcat(desc, ", ");
-        cry_strcat(desc, m_keys[key].eventValue.c_str());
+        azstrcat(desc, ", ");
+        azstrcat(desc, m_keys[key].eventValue.c_str());
     }
 
     description = desc;
diff --git a/Gems/Maestro/Code/Source/Cinematics/MaterialNode.h b/Gems/Maestro/Code/Source/Cinematics/MaterialNode.h
index 51d1b8be15..003312c426 100644
--- a/Gems/Maestro/Code/Source/Cinematics/MaterialNode.h
+++ b/Gems/Maestro/Code/Source/Cinematics/MaterialNode.h
@@ -58,7 +58,7 @@ private:
     float m_fMaxKeyValue;
 
     std::vector< CAnimNode::SParamInfo > m_dynamicShaderParamInfos;
-    typedef AZStd::unordered_map< string, size_t, stl::hash_string_caseless, stl::equality_string_caseless > TDynamicShaderParamsMap;
+    typedef AZStd::unordered_map, stl::equality_string_caseless > TDynamicShaderParamsMap;
     TDynamicShaderParamsMap m_nameToDynamicShaderParam;
 };
 
diff --git a/Gems/Maestro/Code/Source/Cinematics/Movie.cpp b/Gems/Maestro/Code/Source/Cinematics/Movie.cpp
index a6d9e47eb1..b7fb82e0e7 100644
--- a/Gems/Maestro/Code/Source/Cinematics/Movie.cpp
+++ b/Gems/Maestro/Code/Source/Cinematics/Movie.cpp
@@ -75,19 +75,19 @@ static SMovieSequenceAutoComplete s_movieSequenceAutoComplete;
 // Serialization for anim nodes & param types
 #define REGISTER_NODE_TYPE(name) assert(g_animNodeEnumToStringMap.find(AnimNodeType::name) == g_animNodeEnumToStringMap.end()); \
     g_animNodeEnumToStringMap[AnimNodeType::name] = STRINGIFY(name);                                                            \
-    g_animNodeStringToEnumMap[string(STRINGIFY(name))] = AnimNodeType::name;
+    g_animNodeStringToEnumMap[AZStd::string(STRINGIFY(name))] = AnimNodeType::name;
 
 #define REGISTER_PARAM_TYPE(name) assert(g_animParamEnumToStringMap.find(AnimParamType::name) == g_animParamEnumToStringMap.end()); \
     g_animParamEnumToStringMap[AnimParamType::name] = STRINGIFY(name);                                                              \
-    g_animParamStringToEnumMap[string(STRINGIFY(name))] = AnimParamType::name;
+    g_animParamStringToEnumMap[AZStd::string(STRINGIFY(name))] = AnimParamType::name;
 
 namespace
 {
-    AZStd::unordered_map g_animNodeEnumToStringMap;
-    StaticInstance >> g_animNodeStringToEnumMap;
+    AZStd::unordered_map g_animNodeEnumToStringMap;
+    StaticInstance >> g_animNodeStringToEnumMap;
 
-    AZStd::unordered_map g_animParamEnumToStringMap;
-    StaticInstance >> g_animParamStringToEnumMap;
+    AZStd::unordered_map g_animParamEnumToStringMap;
+    StaticInstance >> g_animParamStringToEnumMap;
 
     // If you get an assert in this function, it means two node types have the same enum value.
     void RegisterNodeTypes()
@@ -1479,8 +1479,7 @@ void CMovieSystem::GoToFrame(const char* seqName, float targetFrame)
 
     if (gEnv->IsEditor() && gEnv->IsEditorGameMode() == false)
     {
-        string editorCmd;
-        editorCmd.Format("mov_goToFrameEditor %s %f", seqName, targetFrame);
+        AZStd::string editorCmd = AZStd::string::format("mov_goToFrameEditor %s %f", seqName, targetFrame);
         gEnv->pConsole->ExecuteString(editorCmd.c_str());
         return;
     }
@@ -1679,7 +1678,7 @@ void CMovieSystem::SerializeNodeType(AnimNodeType& animNodeType, XmlNodeRef& xml
     {
         const char* pTypeString = "Invalid";
         assert(g_animNodeEnumToStringMap.find(animNodeType) != g_animNodeEnumToStringMap.end());
-        pTypeString = g_animNodeEnumToStringMap[animNodeType];
+        pTypeString = g_animNodeEnumToStringMap[animNodeType].c_str();
         xmlNode->setAttr(kType, pTypeString);
     }
 }
@@ -1780,7 +1779,7 @@ void CMovieSystem::SaveParamTypeToXml(const CAnimParamType& animParamType, XmlNo
         }
 
         assert(g_animParamEnumToStringMap.find(animParamType.m_type) != g_animParamEnumToStringMap.end());
-        pTypeString = g_animParamEnumToStringMap[animParamType.m_type];
+        pTypeString = g_animParamEnumToStringMap[animParamType.m_type].c_str();
     }
 
     xmlNode->setAttr(kParamType, pTypeString);
@@ -1815,7 +1814,7 @@ const char* CMovieSystem::GetParamTypeName(const CAnimParamType& animParamType)
     {
         if (g_animParamEnumToStringMap.find(animParamType.m_type) != g_animParamEnumToStringMap.end())
         {
-            return g_animParamEnumToStringMap[animParamType.m_type];
+            return g_animParamEnumToStringMap[animParamType.m_type].c_str();
         }
     }
 
@@ -1970,7 +1969,7 @@ CLightAnimWrapper* CLightAnimWrapper::FindLightAnim(const char* name)
 //////////////////////////////////////////////////////////////////////////
 void CLightAnimWrapper::CacheLightAnim(const char* name, CLightAnimWrapper* p)
 {
-    ms_lightAnimWrapperCache.insert(LightAnimWrapperCache::value_type(string(name), p));
+    ms_lightAnimWrapperCache.insert(LightAnimWrapperCache::value_type(AZStd::string(name), p));
 }
 
 //////////////////////////////////////////////////////////////////////////
diff --git a/Gems/Maestro/Code/Source/Cinematics/SceneNode.cpp b/Gems/Maestro/Code/Source/Cinematics/SceneNode.cpp
index 9e3fe212df..799747eb12 100644
--- a/Gems/Maestro/Code/Source/Cinematics/SceneNode.cpp
+++ b/Gems/Maestro/Code/Source/Cinematics/SceneNode.cpp
@@ -917,7 +917,7 @@ void CAnimSceneNode::ApplyEventKey(IEventKey& key, [[maybe_unused]] SAnimContext
 {
     char funcName[1024];
     azstrcpy(funcName, "Event_");
-    cry_strcat(funcName, key.event.c_str());
+    azstrcat(funcName, key.event.c_str());
     gEnv->pMovieSystem->SendGlobalEvent(funcName);
 }
 
@@ -1003,7 +1003,7 @@ void CAnimSceneNode::ApplyGotoKey(CGotoTrack*   poGotoTrack, SAnimContext& ec)
         {
             if (stDiscreteFloadKey.m_fValue >= 0)
             {
-                string fullname = m_pSequence->GetName();
+                AZStd::string fullname = m_pSequence->GetName();
                 GetMovieSystem()->GoToFrame(fullname.c_str(), stDiscreteFloadKey.m_fValue);
             }
         }
diff --git a/Gems/Maestro/Code/Source/Cinematics/ScreenFaderTrack.cpp b/Gems/Maestro/Code/Source/Cinematics/ScreenFaderTrack.cpp
index af5b931dec..3541fe718e 100644
--- a/Gems/Maestro/Code/Source/Cinematics/ScreenFaderTrack.cpp
+++ b/Gems/Maestro/Code/Source/Cinematics/ScreenFaderTrack.cpp
@@ -32,7 +32,7 @@ void CScreenFaderTrack::GetKeyInfo(int key, const char*& description, float& dur
     CheckValid();
     description = 0;
     duration = m_keys[key].m_fadeTime;
-    cry_strcpy(desc, m_keys[key].m_fadeType == IScreenFaderKey::eFT_FadeIn ? "In" : "Out");
+    azstrcpy(desc, m_keys[key].m_fadeType == IScreenFaderKey::eFT_FadeIn ? "In" : "Out");
 
     description = desc;
 }
diff --git a/Gems/Maestro/Code/Source/Cinematics/TrackEventTrack.cpp b/Gems/Maestro/Code/Source/Cinematics/TrackEventTrack.cpp
index 3eca733a1d..25d709bcdc 100644
--- a/Gems/Maestro/Code/Source/Cinematics/TrackEventTrack.cpp
+++ b/Gems/Maestro/Code/Source/Cinematics/TrackEventTrack.cpp
@@ -146,8 +146,8 @@ void CTrackEventTrack::GetKeyInfo(int key, const char*& description, float& dura
     azstrcpy(desc, m_keys[key].event.c_str());
     if (!m_keys[key].eventValue.empty())
     {
-        cry_strcat(desc, ", ");
-        cry_strcat(desc, m_keys[key].eventValue.c_str());
+        azstrcat(desc, ", ");
+        azstrcat(desc, m_keys[key].eventValue.c_str());
     }
 
     description = desc;

From 93a3d3efa07abe909474ee81f981b9df98524c01 Mon Sep 17 00:00:00 2001
From: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com>
Date: Mon, 2 Aug 2021 15:57:29 -0400
Subject: [PATCH 062/803] Bandwith overlay works without imgui

Signed-off-by: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com>
---
 .../Include/Multiplayer/IMultiplayerDebug.h   |  28 ++++
 .../Debug/MultiplayerDebugByteReporter.cpp    |   4 +-
 .../MultiplayerDebugPerEntityReporter.cpp     | 130 ++++++++----------
 .../Debug/MultiplayerDebugPerEntityReporter.h |   3 +-
 .../Debug/MultiplayerDebugSystemComponent.cpp |  35 ++++-
 .../Debug/MultiplayerDebugSystemComponent.h   |  11 +-
 Gems/Multiplayer/Code/multiplayer_files.cmake |   1 +
 7 files changed, 135 insertions(+), 77 deletions(-)
 create mode 100644 Gems/Multiplayer/Code/Include/Multiplayer/IMultiplayerDebug.h

diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/IMultiplayerDebug.h b/Gems/Multiplayer/Code/Include/Multiplayer/IMultiplayerDebug.h
new file mode 100644
index 0000000000..384db66317
--- /dev/null
+++ b/Gems/Multiplayer/Code/Include/Multiplayer/IMultiplayerDebug.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#pragma once
+
+namespace Multiplayer
+{
+    //! @class IMultiplayerDebug
+    //! @brief IMultiplayerDebug provides access to multiplayer debug overlays
+    class IMultiplayerDebug
+    {
+    public:
+        AZ_RTTI(IMultiplayerDebug, "{C5EB7F3A-E19F-4921-A604-C9BDC910123C}");
+
+        virtual ~IMultiplayerDebug() = default;
+
+        //!
+        virtual void ShowEntityBandwidthDebugOverlay() = 0;
+
+        //!
+        virtual void HideEntityBandwidthDebugOverlay() = 0;
+    };
+}
diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.cpp b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.cpp
index a29350e43a..38a1a27dcd 100644
--- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.cpp
+++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.cpp
@@ -8,12 +8,10 @@
 
 #include "MultiplayerDebugByteReporter.h"
 
-#include 
+#include  // for std::setfill
 #include 
 #include 
 
-#pragma optimize("", off)
-
 namespace Multiplayer
 {
     void MultiplayerDebugByteReporter::ReportBytes(size_t byteSize)
diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.cpp b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.cpp
index da32bbb666..b0bfe097e1 100644
--- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.cpp
+++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.cpp
@@ -17,11 +17,6 @@
 #include 
 #endif
 
-#pragma optimize("", off)
-
-AZ_CVAR(bool, net_DebugNetworkEntity_Bandwidth, true, nullptr, AZ::ConsoleFunctorFlags::Null,
-    "If true, prints debug text over entities that use a considerable amount of network traffic");
-
 AZ_CVAR(float, net_DebugNetworkEntity_ShowAboveKbps, 1.f, nullptr, AZ::ConsoleFunctorFlags::Null,
     "Prints bandwidth on network entities with higher kpbs than this value");
 
@@ -304,8 +299,8 @@ namespace Multiplayer
 
     void MultiplayerDebugPerEntityReporter::RecordRpcReceived(
         AZ::EntityId entityId, const char* entityName,
-        Multiplayer::NetComponentId netComponentId,
-        Multiplayer::RpcIndex rpcId,
+        NetComponentId netComponentId,
+        RpcIndex rpcId,
         uint32_t totalBytes)
     {
         if (const Multiplayer::MultiplayerComponentRegistry* componentRegistry = Multiplayer::GetMultiplayerComponentRegistry())
@@ -323,69 +318,66 @@ namespace Multiplayer
 
     void MultiplayerDebugPerEntityReporter::UpdateDebugOverlay()
     {
-        if (net_DebugNetworkEntity_Bandwidth)
+        m_networkEntitiesTraffic.clear();
+
+        for (AZStd::pair& entityPair : m_receivingEntityReports)
         {
-            m_networkEntitiesTraffic.clear();
-
-            for (AZStd::pair& entityPair : m_receivingEntityReports)
-            {
-                m_networkEntitiesTraffic[entityPair.first].m_name = entityPair.second.GetEntityName();
-                m_networkEntitiesTraffic[entityPair.first].m_down = entityPair.second.GetKbitsPerSecond();
-            }
-
-            for (AZStd::pair& entityPair : m_sendingEntityReports)
-            {
-                m_networkEntitiesTraffic[entityPair.first].m_name = entityPair.second.GetEntityName();
-                m_networkEntitiesTraffic[entityPair.first].m_up = entityPair.second.GetKbitsPerSecond();
-            }
-
-            //get debug display interface for the viewport
-            if (m_debugDisplay == nullptr)
-            {
-                AzFramework::DebugDisplayRequestBus::BusPtr debugDisplayBus;
-                AzFramework::DebugDisplayRequestBus::Bind(debugDisplayBus, AzFramework::g_defaultSceneEntityDebugDisplayId);
-                m_debugDisplay = AzFramework::DebugDisplayRequestBus::FindFirstHandler(debugDisplayBus);
-            }
-
-            const AZ::u32 stateBefore = m_debugDisplay->GetState();
-
-            for (AZStd::pair& networkEntity : m_networkEntitiesTraffic)
-            {
-                if (networkEntity.second.m_down < net_DebugNetworkEntity_ShowAboveKbps && networkEntity.second.m_up < net_DebugNetworkEntity_ShowAboveKbps)
-                {
-                    continue;
-                }
-
-                if (networkEntity.second.m_down > net_DebugNetworkEntity_WarnAboveKbps || networkEntity.second.m_up > net_DebugNetworkEntity_WarnAboveKbps)
-                {
-                    m_debugDisplay->SetColor(net_DebugNetworkEntity_WarningColor);
-                }
-                else
-                {
-                    m_debugDisplay->SetColor(net_DebugNetworkEntity_BelowWarningColor);
-                }
-
-                if (networkEntity.second.m_down > net_DebugNetworkEntity_ShowAboveKbps && networkEntity.second.m_up > net_DebugNetworkEntity_ShowAboveKbps)
-                {
-                    azsprintf(m_statusBuffer, "[%s] %.0f down / %0.f up (kbps)", networkEntity.second.m_name,
-                        networkEntity.second.m_down, networkEntity.second.m_up);
-                }
-                else if (networkEntity.second.m_down > net_DebugNetworkEntity_ShowAboveKbps)
-                {
-                    azsprintf(m_statusBuffer, "[%s] %.0f down (kbps)", networkEntity.second.m_name, networkEntity.second.m_down);
-                }
-                else
-                {
-                    azsprintf(m_statusBuffer, "[%s] %.0f up (kbps)", networkEntity.second.m_name, networkEntity.second.m_up);
-                }
-
-                AZ::Vector3 entityPosition = AZ::Vector3::CreateZero();
-                constexpr bool centerText = true;
-                AZ::TransformBus::EventResult(entityPosition, networkEntity.first, &AZ::TransformBus::Events::GetWorldTranslation);
-                m_debugDisplay->DrawTextLabel(entityPosition, 1.0f, m_statusBuffer, centerText, 0, 0);
-            }
-
-            m_debugDisplay->SetState(stateBefore);
+            m_networkEntitiesTraffic[entityPair.first].m_name = entityPair.second.GetEntityName();
+            m_networkEntitiesTraffic[entityPair.first].m_down = entityPair.second.GetKbitsPerSecond();
         }
+
+        for (AZStd::pair& entityPair : m_sendingEntityReports)
+        {
+            m_networkEntitiesTraffic[entityPair.first].m_name = entityPair.second.GetEntityName();
+            m_networkEntitiesTraffic[entityPair.first].m_up = entityPair.second.GetKbitsPerSecond();
+        }
+
+        //get debug display interface for the viewport
+        if (m_debugDisplay == nullptr)
+        {
+            AzFramework::DebugDisplayRequestBus::BusPtr debugDisplayBus;
+            AzFramework::DebugDisplayRequestBus::Bind(debugDisplayBus, AzFramework::g_defaultSceneEntityDebugDisplayId);
+            m_debugDisplay = AzFramework::DebugDisplayRequestBus::FindFirstHandler(debugDisplayBus);
+        }
+
+        const AZ::u32 stateBefore = m_debugDisplay->GetState();
+
+        for (AZStd::pair& networkEntity : m_networkEntitiesTraffic)
+        {
+            if (networkEntity.second.m_down < net_DebugNetworkEntity_ShowAboveKbps && networkEntity.second.m_up < net_DebugNetworkEntity_ShowAboveKbps)
+            {
+                continue;
+            }
+
+            if (networkEntity.second.m_down > net_DebugNetworkEntity_WarnAboveKbps || networkEntity.second.m_up > net_DebugNetworkEntity_WarnAboveKbps)
+            {
+                m_debugDisplay->SetColor(net_DebugNetworkEntity_WarningColor);
+            }
+            else
+            {
+                m_debugDisplay->SetColor(net_DebugNetworkEntity_BelowWarningColor);
+            }
+
+            if (networkEntity.second.m_down > net_DebugNetworkEntity_ShowAboveKbps && networkEntity.second.m_up > net_DebugNetworkEntity_ShowAboveKbps)
+            {
+                azsprintf(m_statusBuffer, "[%s] %.0f down / %0.f up (kbps)", networkEntity.second.m_name,
+                    networkEntity.second.m_down, networkEntity.second.m_up);
+            }
+            else if (networkEntity.second.m_down > net_DebugNetworkEntity_ShowAboveKbps)
+            {
+                azsprintf(m_statusBuffer, "[%s] %.0f down (kbps)", networkEntity.second.m_name, networkEntity.second.m_down);
+            }
+            else
+            {
+                azsprintf(m_statusBuffer, "[%s] %.0f up (kbps)", networkEntity.second.m_name, networkEntity.second.m_up);
+            }
+
+            AZ::Vector3 entityPosition = AZ::Vector3::CreateZero();
+            constexpr bool centerText = true;
+            AZ::TransformBus::EventResult(entityPosition, networkEntity.first, &AZ::TransformBus::Events::GetWorldTranslation);
+            m_debugDisplay->DrawTextLabel(entityPosition, 1.0f, m_statusBuffer, centerText, 0, 0);
+        }
+
+        m_debugDisplay->SetState(stateBefore);
     }
 }
diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.h b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.h
index d6ceaaf04c..8a33bc78ee 100644
--- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.h
+++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.h
@@ -11,7 +11,6 @@
 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -66,7 +65,7 @@ namespace Multiplayer
             float m_down = 0.f;
         };
 
-        AZStd::fixed_unordered_map m_networkEntitiesTraffic;
+        AZStd::unordered_map m_networkEntitiesTraffic;
 
         AzFramework::DebugDisplayRequests* m_debugDisplay = nullptr;
     };
diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.cpp b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.cpp
index 03d79025f7..f892ee9724 100644
--- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.cpp
+++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.cpp
@@ -13,6 +13,11 @@
 #include 
 #include 
 
+void OnDebugNetworkEntity_ShowBandwidth_Changed(const bool& showBandwidth);
+
+AZ_CVAR(bool, net_DebugNetworkEntity_ShowBandwidth, false, &OnDebugNetworkEntity_ShowBandwidth_Changed, AZ::ConsoleFunctorFlags::Null,
+    "If true, prints bandwidth values over entities that use a considerable amount of network traffic");
+
 namespace Multiplayer
 {
     void MultiplayerDebugSystemComponent::Reflect(AZ::ReflectContext* context)
@@ -53,11 +58,20 @@ namespace Multiplayer
 #endif
     }
 
-    void MultiplayerDebugSystemComponent::OnImGuiInitialize()
+    void MultiplayerDebugSystemComponent::ShowEntityBandwidthDebugOverlay()
     {
         m_reporter = AZStd::make_unique();
     }
 
+    void MultiplayerDebugSystemComponent::HideEntityBandwidthDebugOverlay()
+    {
+        m_reporter.reset();
+    }
+
+    void MultiplayerDebugSystemComponent::OnImGuiInitialize()
+    {
+    }
+
 #ifdef IMGUI_ENABLED
     void MultiplayerDebugSystemComponent::OnImGuiMainMenuUpdate()
     {
@@ -327,15 +341,32 @@ namespace Multiplayer
 
         if (m_displayPerEntityStats)
         {
-            //ImGui::SetNextWindowSize({500, 400});
+            // This overrides @net_DebugNetworkEntity_ShowBandwidth value
             if (ImGui::Begin("Multiplayer Per Entity Stats", &m_displayPerEntityStats, ImGuiWindowFlags_AlwaysAutoResize))
             {
                 if (m_reporter)
                 {
                     m_reporter->OnImGuiUpdate();
                 }
+                else
+                {
+                    ShowEntityBandwidthDebugOverlay();
+                }
             }
         }
     }
 #endif
 }
+
+void OnDebugNetworkEntity_ShowBandwidth_Changed(const bool& showBandwidth)
+{
+    if (showBandwidth)
+    {
+        AZ::Interface::Get()->ShowEntityBandwidthDebugOverlay();
+    }
+    else
+    {
+        AZ::Interface::Get()->HideEntityBandwidthDebugOverlay();
+    }
+}
+
diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.h b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.h
index a7f76e075a..87b238c79b 100644
--- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.h
+++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.h
@@ -9,7 +9,9 @@
 #pragma once
 
 #include 
+#include 
 #include 
+#include 
 
 #ifdef IMGUI_ENABLED
 #   include 
@@ -20,6 +22,7 @@ namespace Multiplayer
 {
     class MultiplayerDebugSystemComponent final
         : public AZ::Component
+        , public AZ::Interface::Registrar
 #ifdef IMGUI_ENABLED
         , public ImGui::ImGuiUpdateListenerBus::Handler
 #endif
@@ -30,7 +33,7 @@ namespace Multiplayer
         static void Reflect(AZ::ReflectContext* context);
         static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided);
         static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required);
-        static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatbile);
+        static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible);
 
         ~MultiplayerDebugSystemComponent() override = default;
 
@@ -40,6 +43,12 @@ namespace Multiplayer
         void Deactivate() override;
         //! @}
 
+        //! IMultiplayerDebugSystem overrides
+        //! @{
+        void ShowEntityBandwidthDebugOverlay() override;
+        void HideEntityBandwidthDebugOverlay() override;
+        //! @}
+
 #ifdef IMGUI_ENABLED
         //! ImGui::ImGuiUpdateListenerBus overrides
         //! @{
diff --git a/Gems/Multiplayer/Code/multiplayer_files.cmake b/Gems/Multiplayer/Code/multiplayer_files.cmake
index 7392ea6856..0b2adb1530 100644
--- a/Gems/Multiplayer/Code/multiplayer_files.cmake
+++ b/Gems/Multiplayer/Code/multiplayer_files.cmake
@@ -8,6 +8,7 @@
 
 set(FILES
     Include/Multiplayer/IMultiplayer.h
+    Include/Multiplayer/IMultiplayerDebug.h
     Include/Multiplayer/IMultiplayerTools.h
     Include/Multiplayer/MultiplayerConstants.h
     Include/Multiplayer/MultiplayerStats.h

From 58ff2d8cab609637c16d2988451e0e494971444a Mon Sep 17 00:00:00 2001
From: Dayo Lawal 
Date: Mon, 2 Aug 2021 14:59:45 -0500
Subject: [PATCH 063/803] AtomToolsMainWindowRequestBus

Signed-off-by: Dayo Lawal 
---
 .../Window/AtomToolsMainWindow.h              | 22 +++++-
 .../AtomToolsMainWindowFactoryRequestBus.h    | 30 ++++++++
 .../Window/AtomToolsMainWindowRequestBus.h    | 63 +++++++++++++++
 .../Source/Window/AtomToolsMainWindow.cpp     | 77 ++++++++++++++++++-
 .../Code/atomtoolsframework_files.cmake       |  6 +-
 .../Source/Window/MaterialEditorWindow.cpp    | 70 +----------------
 .../Code/Source/Window/MaterialEditorWindow.h | 11 ---
 .../Window/ShaderManagementConsoleWindow.cpp  | 43 ++++-------
 .../Window/ShaderManagementConsoleWindow.h    |  5 --
 9 files changed, 206 insertions(+), 121 deletions(-)
 create mode 100644 Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindowFactoryRequestBus.h
 create mode 100644 Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindowRequestBus.h

diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindow.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindow.h
index 21afe114f5..2cc6621cec 100644
--- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindow.h
+++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindow.h
@@ -8,6 +8,7 @@
 
 #pragma once
 #include 
+#include 
 
 #include 
 #include 
@@ -22,14 +23,19 @@ namespace AtomToolsFramework
 {
     class AtomToolsMainWindow
         : public AzQtComponents::DockMainWindow
+        , protected AtomToolsFramework::AtomToolsMainWindowRequestBus::Handler
     {
     public:
         AtomToolsMainWindow(QWidget* parent = 0);
+        ~AtomToolsMainWindow();
+
     protected:
-        AzQtComponents::FancyDocking* m_advancedDockManager = nullptr;
-        QWidget* m_centralWidget = nullptr;
-        QMenuBar* m_menuBar = nullptr;
-        AzQtComponents::TabWidget* m_tabWidget = nullptr;
+        void ActivateWindow() override;
+        bool AddDockWidget(const AZStd::string& name, QWidget* widget, uint32_t area, uint32_t orientation) override;
+        void RemoveDockWidget(const AZStd::string& name) override;
+        void SetDockWidgetVisible(const AZStd::string& name, bool visible) override;
+        bool IsDockWidgetVisible(const AZStd::string& name) const override;
+        AZStd::vector GetDockWidgetNames() const override;
 
         virtual void SetupMenu();
 
@@ -43,6 +49,14 @@ namespace AtomToolsFramework
         virtual void SelectPreviousTab();
         virtual void SelectNextTab();
 
+        AzQtComponents::FancyDocking* m_advancedDockManager = nullptr;
+        QWidget* m_centralWidget = nullptr;
+        QMenuBar* m_menuBar = nullptr;
+        AzQtComponents::TabWidget* m_tabWidget = nullptr;
+
+        AZStd::unordered_map m_dockWidgets;
+
         QMenu* m_menuFile = {};
+        //StatusBarWidget* m_statusBar = {};
     };
 }
diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindowFactoryRequestBus.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindowFactoryRequestBus.h
new file mode 100644
index 0000000000..aed0d877db
--- /dev/null
+++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindowFactoryRequestBus.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#pragma once
+
+#include 
+
+namespace AtomToolsFramework
+{
+    //! AtomToolsMainWindowFactoryRequestBus provides
+    class AtomToolsMainWindowFactoryRequests : public AZ::EBusTraits
+    {
+    public:
+        static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
+        static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
+
+        /// Creates and shows the AtomToolsMainWindow
+        virtual void CreateAtomToolsMainWindow() = 0;
+
+        //! Destroys material editor window and releases all cached assets
+        virtual void DestroyAtomToolsMainWindow() = 0;
+    };
+    using AtomToolsMainWindowFactoryRequestBus = AZ::EBus;
+
+} // namespace AtomToolsFramework
diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindowRequestBus.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindowRequestBus.h
new file mode 100644
index 0000000000..fd98b3b68b
--- /dev/null
+++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindowRequestBus.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#pragma once
+#pragma warning(disable : 4100)
+#include 
+#include 
+#include 
+
+class QWidget;
+
+namespace AtomToolsFramework
+{
+    //! AtomToolsMainWindowRequestBus provides
+    class AtomToolsMainWindowRequests : public AZ::EBusTraits
+    {
+    public:
+        static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
+        static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
+
+        //! Bring main window to foreground
+        virtual void ActivateWindow() = 0;
+
+        //! Add dockable widget in main window
+        //! @param name title of the dockable window
+        //! @param widget docked window content
+        //! @param area location of docked window corresponding to Qt::DockWidgetArea
+        //! @param orientation orientation of docked window corresponding to Qt::Orientation
+        virtual bool AddDockWidget(const AZStd::string& name, QWidget* widget, uint32_t area, uint32_t orientation) = 0;
+
+        //! Destroy dockable widget in main window
+        //! @param name title of the dockable window
+        virtual void RemoveDockWidget(const AZStd::string& name) = 0;
+
+        //! Show or hide dockable widget in main window
+        //! @param name title of the dockable window
+        virtual void SetDockWidgetVisible(const AZStd::string& name, bool visible) = 0;
+
+        //! Determine visibility of dockable widget in main window
+        //! @param name title of the dockable window
+        virtual bool IsDockWidgetVisible(const AZStd::string& name) const = 0;
+
+        //! Get a list of registered docked widget names
+        virtual AZStd::vector GetDockWidgetNames() const = 0;
+
+        //! Resizes the Material Editor window to achieve a requested size for the viewport render target.
+        //! (This indicates the size of the render target, not the desktop-scaled QT widget size).
+        virtual void ResizeViewportRenderTarget(uint32_t width, uint32_t height) {};
+
+        //! Forces the viewport's render target to use the given resolution, ignoring the size of the viewport widget.
+        virtual void LockViewportRenderTargetSize(uint32_t width, uint32_t height) {};
+
+        //! Releases the viewport's render target resolution lock, allowing it to match the viewport widget again.
+        virtual void UnlockViewportRenderTargetSize() {};
+    };
+    using AtomToolsMainWindowRequestBus = AZ::EBus;
+
+} // namespace AtomToolsFramework
diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp
index 15edd8c5b6..849169e2e3 100644
--- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp
+++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp
@@ -8,7 +8,6 @@
 
 #include 
 
-
 namespace AtomToolsFramework
 {
     AtomToolsMainWindow::AtomToolsMainWindow(QWidget* parent)
@@ -31,6 +30,80 @@ namespace AtomToolsFramework
         m_tabWidget->setObjectName("TabWidget");
         m_tabWidget->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Preferred);
         m_tabWidget->setContentsMargins(0, 0, 0, 0);
+
+        AtomToolsMainWindowRequestBus::Handler::BusConnect();
+    }
+
+    AtomToolsMainWindow::~AtomToolsMainWindow()
+    {
+        AtomToolsMainWindowRequestBus::Handler::BusDisconnect();
+    }
+
+    void AtomToolsMainWindow::ActivateWindow()
+    {
+        activateWindow();
+        raise();
+    }
+
+    bool AtomToolsMainWindow::AddDockWidget(const AZStd::string& name, QWidget* widget, uint32_t area, uint32_t orientation)
+    {
+        auto dockWidgetItr = m_dockWidgets.find(name);
+        if (dockWidgetItr != m_dockWidgets.end() || !widget)
+        {
+            return false;
+        }
+
+        auto dockWidget = new AzQtComponents::StyledDockWidget(name.c_str());
+        dockWidget->setObjectName(QString("%1_DockWidget").arg(name.c_str()));
+        dockWidget->setFeatures(QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable);
+        widget->setObjectName(name.c_str());
+        widget->setParent(dockWidget);
+        widget->setMinimumSize(QSize(300, 300));
+        dockWidget->setWidget(widget);
+        addDockWidget(aznumeric_cast(area), dockWidget);
+        resizeDocks({ dockWidget }, { 400 }, aznumeric_cast(orientation));
+        m_dockWidgets[name] = dockWidget;
+        return true;
+    }
+
+    void AtomToolsMainWindow::RemoveDockWidget(const AZStd::string& name)
+    {
+        auto dockWidgetItr = m_dockWidgets.find(name);
+        if (dockWidgetItr != m_dockWidgets.end())
+        {
+            delete dockWidgetItr->second;
+            m_dockWidgets.erase(dockWidgetItr);
+        }
+    }
+
+    void AtomToolsMainWindow::SetDockWidgetVisible(const AZStd::string& name, bool visible)
+    {
+        auto dockWidgetItr = m_dockWidgets.find(name);
+        if (dockWidgetItr != m_dockWidgets.end())
+        {
+            dockWidgetItr->second->setVisible(visible);
+        }
+    }
+
+    bool AtomToolsMainWindow::IsDockWidgetVisible(const AZStd::string& name) const
+    {
+        auto dockWidgetItr = m_dockWidgets.find(name);
+        if (dockWidgetItr != m_dockWidgets.end())
+        {
+            return dockWidgetItr->second->isVisible();
+        }
+        return false;
+    }
+
+    AZStd::vector AtomToolsMainWindow::GetDockWidgetNames() const
+    {
+        AZStd::vector names;
+        names.reserve(m_dockWidgets.size());
+        for (const auto& dockWidgetPair : m_dockWidgets)
+        {
+            names.push_back(dockWidgetPair.first);
+        }
+        return names;
     }
 
     void AtomToolsMainWindow::SetupMenu()
@@ -132,4 +205,4 @@ namespace AtomToolsFramework
             m_tabWidget->setCurrentIndex((m_tabWidget->currentIndex() + 1) % m_tabWidget->count());
         }
     }
-}
+} // namespace AtomToolsFramework
diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake b/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake
index 5ef4426537..0769aac86c 100644
--- a/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake
+++ b/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake
@@ -24,7 +24,9 @@ set(FILES
     Include/AtomToolsFramework/Viewport/RenderViewportWidget.h
     Include/AtomToolsFramework/Viewport/ModularViewportCameraController.h
     Include/AtomToolsFramework/Viewport/ModularViewportCameraControllerRequestBus.h
-	Include/AtomToolsFramework/Window/AtomToolsMainWindow.h
+    Include/AtomToolsFramework/Window/AtomToolsMainWindow.h
+    Include/AtomToolsFramework/Window/AtomToolsMainWindowRequestBus.h
+    Include/AtomToolsFramework/Window/AtomToolsMainWindowFactoryRequestBus.h
     Source/Application/AtomToolsApplication.cpp
     Source/Communication/LocalServer.cpp
     Source/Communication/LocalSocket.cpp
@@ -41,5 +43,5 @@ set(FILES
     Source/Util/Util.cpp
     Source/Viewport/RenderViewportWidget.cpp
     Source/Viewport/ModularViewportCameraController.cpp
-	Source/Window/AtomToolsMainWindow.cpp
+    Source/Window/AtomToolsMainWindow.cpp
 )
diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp
index 78670ac710..96a94ebfcc 100644
--- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp
+++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp
@@ -131,7 +131,6 @@ namespace MaterialEditor
             m_advancedDockManager->restoreState(windowState);
         }
 
-        MaterialEditorWindowRequestBus::Handler::BusConnect();
         MaterialDocumentNotificationBus::Handler::BusConnect();
         OnDocumentOpened(AZ::Uuid::CreateNull());
     }
@@ -139,76 +138,9 @@ namespace MaterialEditor
     MaterialEditorWindow::~MaterialEditorWindow()
     {
         MaterialDocumentNotificationBus::Handler::BusDisconnect();
-        MaterialEditorWindowRequestBus::Handler::BusDisconnect();
-    }
-
-    void MaterialEditorWindow::ActivateWindow()
-    {
-        activateWindow();
-        raise();
-    }
-
-    bool MaterialEditorWindow::AddDockWidget(const AZStd::string& name, QWidget* widget, uint32_t area, uint32_t orientation)
-    {
-        auto dockWidgetItr = m_dockWidgets.find(name);
-        if (dockWidgetItr != m_dockWidgets.end() || !widget)
-        {
-            return false;
-        }
-
-        auto dockWidget = new AzQtComponents::StyledDockWidget(name.c_str());
-        dockWidget->setObjectName(QString("%1_DockWidget").arg(name.c_str()));
-        dockWidget->setFeatures(QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable);
-        widget->setObjectName(name.c_str());
-        widget->setParent(dockWidget);
-        widget->setMinimumSize(QSize(300, 300));
-        dockWidget->setWidget(widget);
-        addDockWidget(aznumeric_cast(area), dockWidget);
-        resizeDocks({ dockWidget }, { 400 }, aznumeric_cast(orientation));
-        m_dockWidgets[name] = dockWidget;
-        return true;
-    }
-
-    void MaterialEditorWindow::RemoveDockWidget(const AZStd::string& name)
-    {
-        auto dockWidgetItr = m_dockWidgets.find(name);
-        if (dockWidgetItr != m_dockWidgets.end())
-        {
-            delete dockWidgetItr->second;
-            m_dockWidgets.erase(dockWidgetItr);
-        }
-    }
-
-    void MaterialEditorWindow::SetDockWidgetVisible(const AZStd::string& name, bool visible)
-    {
-        auto dockWidgetItr = m_dockWidgets.find(name);
-        if (dockWidgetItr != m_dockWidgets.end())
-        {
-            dockWidgetItr->second->setVisible(visible);
-        }
-    }
-
-    bool MaterialEditorWindow::IsDockWidgetVisible(const AZStd::string& name) const
-    {
-        auto dockWidgetItr = m_dockWidgets.find(name);
-        if (dockWidgetItr != m_dockWidgets.end())
-        {
-            return dockWidgetItr->second->isVisible();
-        }
-        return false;
-    }
-
-    AZStd::vector MaterialEditorWindow::GetDockWidgetNames() const
-    {
-        AZStd::vector names;
-        names.reserve(m_dockWidgets.size());
-        for (const auto& dockWidgetPair : m_dockWidgets)
-        {
-            names.push_back(dockWidgetPair.first);
-        }
-        return names;
     }
 
+    
     void MaterialEditorWindow::ResizeViewportRenderTarget(uint32_t width, uint32_t height)
     {
         QSize requestedViewportSize = QSize(width, height) / devicePixelRatioF();
diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.h
index 96f03e6eed..a443f04ebe 100644
--- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.h
+++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.h
@@ -46,7 +46,6 @@ namespace MaterialEditor
      */
     class MaterialEditorWindow
         : public AtomToolsFramework::AtomToolsMainWindow
-        , private MaterialEditorWindowRequestBus::Handler
         , private MaterialDocumentNotificationBus::Handler
     {
         Q_OBJECT
@@ -59,14 +58,6 @@ namespace MaterialEditor
         ~MaterialEditorWindow();
 
     private:
-        // MaterialEditorWindowRequestBus::Handler overrides...
-        void ActivateWindow() override;
-        bool AddDockWidget(const AZStd::string& name, QWidget* widget, uint32_t area, uint32_t orientation) override;
-        void RemoveDockWidget(const AZStd::string& name) override;
-        void SetDockWidgetVisible(const AZStd::string& name, bool visible) override;
-        bool IsDockWidgetVisible(const AZStd::string& name) const override;
-        AZStd::vector GetDockWidgetNames() const override;
-
         void ResizeViewportRenderTarget(uint32_t width, uint32_t height) override;
         void LockViewportRenderTargetSize(uint32_t width, uint32_t height) override;
         void UnlockViewportRenderTargetSize() override;
@@ -92,8 +83,6 @@ namespace MaterialEditor
         MaterialViewportWidget* m_materialViewport = nullptr;
         MaterialEditorToolBar* m_toolBar = nullptr;
 
-        AZStd::unordered_map  m_dockWidgets;
-
         QAction* m_actionNew = {};
         QAction* m_actionOpen = {};
         QAction* m_actionOpenRecent = {};
diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp
index 90a2e238a9..05f88655ca 100644
--- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp
+++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp
@@ -58,24 +58,8 @@ namespace ShaderManagementConsole
         SetupMenu();
         SetupTabs();
 
-        m_assetBrowserDockWidget = new AzQtComponents::StyledDockWidget("Asset Browser");
-        m_assetBrowserDockWidget->setObjectName(m_assetBrowserDockWidget->windowTitle());
-        m_assetBrowserDockWidget->setFeatures(QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable);
-        m_assetBrowser = new ShaderManagementConsoleBrowserWidget(m_assetBrowserDockWidget);
-        m_assetBrowser->setMinimumSize(QSize(300, 300));
-        m_assetBrowserDockWidget->setWidget(m_assetBrowser);
-        addDockWidget(Qt::BottomDockWidgetArea, m_assetBrowserDockWidget);
-        resizeDocks({ m_assetBrowserDockWidget }, { 400 }, Qt::Vertical);
-
-        m_pythonTerminalDockWidget = new AzQtComponents::StyledDockWidget("Python Terminal");
-        m_pythonTerminalDockWidget->setObjectName(m_pythonTerminalDockWidget->windowTitle());
-        m_pythonTerminalDockWidget->setFeatures(QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable);
-        m_pythonTerminal = new AzToolsFramework::CScriptTermDialog(m_pythonTerminalDockWidget);
-        m_pythonTerminal->setMinimumSize(QSize(300, 300));
-        m_pythonTerminalDockWidget->setWidget(m_pythonTerminal);
-        addDockWidget(Qt::BottomDockWidgetArea, m_pythonTerminalDockWidget);
-        resizeDocks({ m_pythonTerminalDockWidget }, { 400 }, Qt::Vertical);
-        m_pythonTerminalDockWidget->setVisible(false);
+        AddDockWidget("Asset Browser", new ShaderManagementConsoleBrowserWidget, Qt::BottomDockWidgetArea, Qt::Vertical);
+        AddDockWidget("Python Terminal", new AzToolsFramework::CScriptTermDialog, Qt::BottomDockWidgetArea, Qt::Horizontal);
 
         ShaderManagementConsoleDocumentNotificationBus::Handler::BusConnect();
         OnDocumentOpened(AZ::Uuid::CreateNull());
@@ -256,17 +240,20 @@ namespace ShaderManagementConsole
 
         m_menuView = m_menuBar->addMenu("&View");
 
-        m_actionAssetBrowser = m_menuView->addAction("&Asset Browser", [this]() {
-            m_assetBrowserDockWidget->setVisible(!m_assetBrowserDockWidget->isVisible());
-        });
-
-        m_actionPythonTerminal = m_menuView->addAction("Python &Terminal", [this]() {
-            m_pythonTerminalDockWidget->setVisible(!m_pythonTerminalDockWidget->isVisible());
-            if (m_pythonTerminalDockWidget->isVisible())
+        m_actionAssetBrowser = m_menuView->addAction(
+            "&Asset Browser",
+            [this]()
             {
-                // reposition console window on the bottom, otherwise it gets docked in some weird spot...
-                addDockWidget(Qt::BottomDockWidgetArea, m_pythonTerminalDockWidget);
-            }
+                const AZStd::string label = "Asset Browser";
+                SetDockWidgetVisible(label, !IsDockWidgetVisible(label));
+            });
+
+        m_actionPythonTerminal = m_menuView->addAction(
+            "Python &Terminal",
+            [this]()
+            {
+                const AZStd::string label = "Python Terminal";
+                SetDockWidgetVisible(label, !IsDockWidgetVisible(label));
             });
 
         m_menuView->addSeparator();
diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.h b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.h
index cb371bc4d6..8513366ec2 100644
--- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.h
+++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.h
@@ -79,12 +79,7 @@ namespace ShaderManagementConsole
 
         void CreateDocumentContent(const AZ::Uuid& documentId, QStandardItemModel* model);
 
-        ShaderManagementConsoleBrowserWidget* m_assetBrowser = nullptr;
         ShaderManagementConsoleToolBar* m_toolBar = nullptr;
-        AzToolsFramework::CScriptTermDialog* m_pythonTerminal = nullptr;
-
-        AzQtComponents::StyledDockWidget* m_assetBrowserDockWidget = nullptr;
-        AzQtComponents::StyledDockWidget* m_pythonTerminalDockWidget = nullptr;
 
         QMenu* m_menuNew = {};
         QAction* m_actionOpen = {};

From 5b88d96eec29a5b6359243f5413693f3acf619f0 Mon Sep 17 00:00:00 2001
From: Kyle B 
Date: Mon, 2 Aug 2021 13:36:10 -0700
Subject: [PATCH 064/803] Exposed fields to the mesh component giving greater
 Lod control from the editor

Signed-off-by: Kyle B 
---
 .../Atom/Feature/Mesh/MeshFeatureProcessor.h  | 12 ++-
 .../Mesh/MeshFeatureProcessorInterface.h      |  7 ++
 .../Code/Source/Mesh/MeshFeatureProcessor.cpp | 74 +++++++++++++++++--
 .../Code/Include/Atom/RPI.Public/Culling.h    |  5 ++
 .../CommonFeatures/Mesh/MeshComponentBus.h    |  6 ++
 .../Code/Source/Mesh/EditorMeshComponent.cpp  |  7 ++
 .../Source/Mesh/MeshComponentController.cpp   | 32 ++++++++
 .../Source/Mesh/MeshComponentController.h     |  7 ++
 .../Code/Source/AtomActorInstance.cpp         | 20 +++++
 .../Code/Source/AtomActorInstance.h           |  4 +
 10 files changed, 167 insertions(+), 7 deletions(-)

diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h
index a2d9517ec4..3cdff52ba7 100644
--- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h
+++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h
@@ -63,8 +63,12 @@ namespace AZ
             void SetRayTracingData();
             void SetSortKey(RHI::DrawItemSortKey sortKey);
             RHI::DrawItemSortKey GetSortKey();
-            void SetLodOverride(RPI::Cullable::LodOverride lodOverride);
+            void SetLodOverride( RPI::Cullable::LodOverride lodOverride);
             RPI::Cullable::LodOverride GetLodOverride();
+            void SetMinimumScreenCoverage(float minimumScreenCoverage);
+            float GetMinimumScreenCoverage();
+            void SetQualityDecayRate(float qualityDecayRate);
+            float GetQualityDecayRate();
             void UpdateDrawPackets(bool forceUpdate = false);
             void BuildCullable();
             void UpdateCullBounds(const TransformServiceFeatureProcessor* transformService);
@@ -158,6 +162,12 @@ namespace AZ
             void SetLodOverride(const MeshHandle& meshHandle, RPI::Cullable::LodOverride lodOverride) override;
             RPI::Cullable::LodOverride GetLodOverride(const MeshHandle& meshHandle) override;
 
+            void SetMinimumScreenCoverage(const MeshHandle& meshHandle, float minimumScreenCoverage) override;
+            float GetMinimumScreenCoverage(const MeshHandle& meshHandle) override;
+
+            void SetQualityDecayRate(const MeshHandle& meshHandle, float qualityDecayRate) override;
+            float GetQualityDecayRate(const MeshHandle& meshHandle) override;
+
             void SetExcludeFromReflectionCubeMaps(const MeshHandle& meshHandle, bool excludeFromReflectionCubeMaps) override;
             void SetRayTracingEnabled(const MeshHandle& meshHandle, bool rayTracingEnabled) override;
             void SetVisible(const MeshHandle& meshHandle, bool visible) override;
diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessorInterface.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessorInterface.h
index 4e74302276..b71b420625 100644
--- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessorInterface.h
+++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessorInterface.h
@@ -98,6 +98,13 @@ namespace AZ
             virtual void SetLodOverride(const MeshHandle& meshHandle, RPI::Cullable::LodOverride lodOverride) = 0;
             //! Gets the LOD override for a given mesh handle.
             virtual RPI::Cullable::LodOverride GetLodOverride(const MeshHandle& meshHandle) = 0;
+
+            virtual void SetMinimumScreenCoverage(const MeshHandle& meshHandle, float minimumScreenCoverage) = 0;
+            virtual float GetMinimumScreenCoverage(const MeshHandle& meshHandle) = 0;
+
+            virtual void SetQualityDecayRate(const MeshHandle& meshHandle, float qualityDecayRate) = 0;
+            virtual float GetQualityDecayRate(const MeshHandle& meshHandle) = 0;
+
             //! Sets the option to exclude this mesh from baked reflection probe cubemaps
             virtual void SetExcludeFromReflectionCubeMaps(const MeshHandle& meshHandle, bool excludeFromReflectionCubeMaps) = 0;
             //! Sets the option to exclude this mesh from raytracing
diff --git a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp
index c6362f3a5d..ce8ead9318 100644
--- a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp
+++ b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp
@@ -380,6 +380,48 @@ namespace AZ
             }
         }
 
+        void MeshFeatureProcessor::SetMinimumScreenCoverage( const MeshHandle& meshHandle, float minimumScreenCoverage)
+        {
+            if (meshHandle.IsValid())
+            {
+                meshHandle->SetMinimumScreenCoverage(minimumScreenCoverage);
+            }
+        }
+
+        float MeshFeatureProcessor::GetMinimumScreenCoverage(const MeshHandle& meshHandle)
+        {
+            if (meshHandle.IsValid())
+            {
+                return meshHandle->GetMinimumScreenCoverage();
+            }
+            else
+            {
+                AZ_Assert(false, "Invalid mesh handle");
+                return 0;
+            }
+        }
+
+        void MeshFeatureProcessor::SetQualityDecayRate(const MeshHandle& meshHandle, float qualityDecayRate)
+        {
+            if (meshHandle.IsValid())
+            {
+                meshHandle->SetQualityDecayRate(qualityDecayRate);
+            }
+        }
+
+        float MeshFeatureProcessor::GetQualityDecayRate(const MeshHandle& meshHandle)
+        {
+            if (meshHandle.IsValid())
+            {
+                return meshHandle->GetQualityDecayRate();
+            }
+            else
+            {
+                AZ_Assert(false, "Invalid mesh handle");
+                return 0;
+            }
+        }
+
         void MeshFeatureProcessor::SetExcludeFromReflectionCubeMaps(const MeshHandle& meshHandle, bool excludeFromReflectionCubeMaps)
         {
             if (meshHandle.IsValid())
@@ -1001,6 +1043,26 @@ namespace AZ
             return m_cullable.m_lodData.m_lodOverride;
         }
 
+        void MeshDataInstance::SetMinimumScreenCoverage(float minimumScreenCoverage)
+        {
+            m_cullable.m_lodData.m_minimumScreenCoverage = minimumScreenCoverage;
+        }
+
+        float MeshDataInstance::GetMinimumScreenCoverage()
+        {
+            return m_cullable.m_lodData.m_minimumScreenCoverage;
+        }
+
+        void MeshDataInstance::SetQualityDecayRate(float qualityDecayRate)
+        {
+            m_cullable.m_lodData.m_qualityDecayRate = qualityDecayRate;
+        }
+
+        float MeshDataInstance::GetQualityDecayRate()
+        {
+            return m_cullable.m_lodData.m_qualityDecayRate;
+        }
+
         void MeshDataInstance::UpdateDrawPackets(bool forceUpdate /*= false*/)
         {
             AZ_PROFILE_FUNCTION(Debug::ProfileCategory::AzRender);
@@ -1036,13 +1098,11 @@ namespace AZ
             cullData.m_drawListMask.reset();
 
             const size_t lodCount = lodAssets.size();
+
             for (size_t lodIndex = 0; lodIndex < lodCount; ++lodIndex)
             {
                 //initialize the lod
                 RPI::Cullable::LodData::Lod& lod = lodData.m_lods[lodIndex];
-                //[GFX TODO][ATOM-5562] - Level of detail: override lod distances and add global lod multiplier(s)
-                static const float MinimumScreenCoverage = 1.0f/1080.0f;        //mesh should cover at least a screen pixel at 1080p to be drawn
-                static const float ReductionFactor = 0.5f;
                 if (lodIndex == 0)
                 {
                     //first lod
@@ -1051,17 +1111,19 @@ namespace AZ
                 else
                 {
                     //every other lod: use the previous lod's min
-                    lod.m_screenCoverageMax = AZStd::GetMax(lodData.m_lods[lodIndex-1].m_screenCoverageMin, MinimumScreenCoverage);
+                    lod.m_screenCoverageMax = AZStd::GetMax(lodData.m_lods[lodIndex - 1].m_screenCoverageMin, lodData.m_minimumScreenCoverage);
                 }
+
                 if (lodIndex < lodAssets.size() - 1)
                 {
                     //first and middle lods: compute a stepdown value for the min
-                    lod.m_screenCoverageMin = AZStd::GetMax(ReductionFactor * lod.m_screenCoverageMax, MinimumScreenCoverage);
+                    lod.m_screenCoverageMin =
+                        AZStd::GetMax(lodData.m_qualityDecayRate * lod.m_screenCoverageMax, lodData.m_minimumScreenCoverage);
                 }
                 else
                 {
                     //last lod: use MinimumScreenCoverage for the min
-                    lod.m_screenCoverageMin = MinimumScreenCoverage;
+                    lod.m_screenCoverageMin = lodData.m_minimumScreenCoverage;
                 }
 
                 lod.m_drawPackets.clear();
diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Culling.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Culling.h
index bcc4dfb89f..30cf091735 100644
--- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Culling.h
+++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Culling.h
@@ -88,6 +88,11 @@ namespace AZ
                 //! Suggest setting to: 0.5f*localAabb.GetExtents().GetMaxElement()
                 float m_lodSelectionRadius = 1.0f;
 
+                // the minimum possibe area a sphere enclosing a mesh projected onto the screen should have before it is culled.
+                float m_minimumScreenCoverage = 1.0f / 1080.0f;
+                // The screen area decay between 0 and 1, i.e. closer to 1 -> lose quality immediately, closer to 0 -> never lose quality 
+                float m_qualityDecayRate = 0.5f;
+
                 LodOverride m_lodOverride = NoLodOverride;
             };
             LodData m_lodData;
diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Mesh/MeshComponentBus.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Mesh/MeshComponentBus.h
index ff75f7f45a..baef507b7a 100644
--- a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Mesh/MeshComponentBus.h
+++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Mesh/MeshComponentBus.h
@@ -39,6 +39,12 @@ namespace AZ
             virtual void SetLodOverride(RPI::Cullable::LodOverride lodOverride) = 0;
             virtual RPI::Cullable::LodOverride GetLodOverride() const = 0;
 
+            virtual void SetMinimumScreenCoverage(float minimumScreenCoverage) = 0;
+            virtual float GetMinimumScreenCoverage() const = 0;
+
+            virtual void SetQualityDecayRate(float qualityDecayRate) = 0;
+            virtual float GetQualityDecayRate() const = 0;
+
             virtual void SetVisibility(bool visible) = 0;
             virtual bool GetVisibility() const = 0;
 
diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp
index fc62690cc4..bdbf445b7f 100644
--- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp
+++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp
@@ -76,6 +76,13 @@ namespace AZ
                         ->DataElement(AZ::Edit::UIHandlers::ComboBox, &MeshComponentConfig::m_lodOverride, "Lod Override", "Allows the rendered LOD to be overridden instead of being calculated automatically.")
                             ->Attribute(AZ::Edit::Attributes::EnumValues, &MeshComponentConfig::GetLodOverrideValues)
                             ->Attribute(AZ::Edit::Attributes::Visibility, &MeshComponentConfig::IsAssetSet)
+                        ->DataElement(AZ::Edit::UIHandlers::Default, &MeshComponentConfig::m_minimumScreenCoverage, "Minimum Screen Coverage", "Minimum proportion of screen area an entitiy takes up, after that the entitiy is culled.")
+                            ->Attribute(AZ::Edit::Attributes::Min, 0.f)
+                            ->Attribute(AZ::Edit::Attributes::Max, 1.f)
+                        ->DataElement(AZ::Edit::UIHandlers::Default, &MeshComponentConfig::m_qualityDecayRate, "Quality Decay Rate",
+                            "Rate at which mesh quality decays (0 -> always stay highest quality, 1 -> quality falls off to lowest quality immediately).")
+                            ->Attribute(AZ::Edit::Attributes::Min, 0.f)
+                            ->Attribute(AZ::Edit::Attributes::Max, 1.f)
                         ->DataElement(AZ::Edit::UIHandlers::CheckBox, &MeshComponentConfig::m_excludeFromReflectionCubeMaps, "Exclude from reflection cubemaps", "Mesh will not be visible in baked reflection probe cubemaps")
                             ->Attribute(AZ::Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly)
                         ->DataElement(AZ::Edit::UIHandlers::CheckBox, &MeshComponentConfig::m_useForwardPassIblSpecular, "Use Forward Pass IBL Specular",
diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp
index 29bd9a839b..5fde185e4c 100644
--- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp
+++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp
@@ -40,6 +40,8 @@ namespace AZ
                     ->Field("ModelAsset", &MeshComponentConfig::m_modelAsset)
                     ->Field("SortKey", &MeshComponentConfig::m_sortKey)
                     ->Field("LodOverride", &MeshComponentConfig::m_lodOverride)
+                    ->Field("MinimumScreenCoverage", &MeshComponentConfig::m_minimumScreenCoverage)
+                    ->Field("QualityDecayRate", &MeshComponentConfig::m_qualityDecayRate)
                     ->Field("ExcludeFromReflectionCubeMaps", &MeshComponentConfig::m_excludeFromReflectionCubeMaps)
                     ->Field("UseForwardPassIBLSpecular", &MeshComponentConfig::m_useForwardPassIblSpecular);
             }
@@ -116,10 +118,16 @@ namespace AZ
                     ->Event("GetSortKey", &MeshComponentRequestBus::Events::GetSortKey)
                     ->Event("SetLodOverride", &MeshComponentRequestBus::Events::SetLodOverride)
                     ->Event("GetLodOverride", &MeshComponentRequestBus::Events::GetLodOverride)
+                    ->Event("SetMinimumScreenCoverage", &MeshComponentRequestBus::Events::SetMinimumScreenCoverage)
+                    ->Event("GetMinimumScreenCoverage", &MeshComponentRequestBus::Events::GetMinimumScreenCoverage)
+                    ->Event("SetQualityDecayRate", &MeshComponentRequestBus::Events::SetQualityDecayRate)
+                    ->Event("GetQualityDecayRate", &MeshComponentRequestBus::Events::GetQualityDecayRate)
                     ->VirtualProperty("ModelAssetId", "GetModelAssetId", "SetModelAssetId")
                     ->VirtualProperty("ModelAssetPath", "GetModelAssetPath", "SetModelAssetPath")
                     ->VirtualProperty("SortKey", "GetSortKey", "SetSortKey")
                     ->VirtualProperty("LodOverride", "GetLodOverride", "SetLodOverride")
+                    ->VirtualProperty("MinimumScreenCoverage", "GetMinimumScreenCoverage", "SetMinimumScreenCoverage")
+                    ->VirtualProperty("QualityDecayRate", "GetQualityDecayRate", "SetQualityDecayRate")
                     ;
             }
         }
@@ -325,6 +333,8 @@ namespace AZ
                 m_meshFeatureProcessor->SetTransform(m_meshHandle, transform, m_cachedNonUniformScale);
                 m_meshFeatureProcessor->SetSortKey(m_meshHandle, m_configuration.m_sortKey);
                 m_meshFeatureProcessor->SetLodOverride(m_meshHandle, m_configuration.m_lodOverride);
+                m_meshFeatureProcessor->SetMinimumScreenCoverage(m_meshHandle, m_configuration.m_minimumScreenCoverage);
+                m_meshFeatureProcessor->SetQualityDecayRate(m_meshHandle, m_configuration.m_qualityDecayRate);
                 m_meshFeatureProcessor->SetExcludeFromReflectionCubeMaps(m_meshHandle, m_configuration.m_excludeFromReflectionCubeMaps);
                 m_meshFeatureProcessor->SetVisible(m_meshHandle, m_isVisible);
 
@@ -426,6 +436,28 @@ namespace AZ
             return m_meshFeatureProcessor->GetSortKey(m_meshHandle);
         }
 
+        void MeshComponentController::SetMinimumScreenCoverage(float minimumScreenCoverage)
+        {
+            m_configuration.m_minimumScreenCoverage = minimumScreenCoverage;
+            m_meshFeatureProcessor->SetMinimumScreenCoverage(m_meshHandle, minimumScreenCoverage);
+        }
+
+        float MeshComponentController::GetMinimumScreenCoverage() const
+        {
+            return m_meshFeatureProcessor->GetMinimumScreenCoverage(m_meshHandle);
+        }
+
+        void MeshComponentController::SetQualityDecayRate(float qualityDecayRate)
+        {
+            m_configuration.m_qualityDecayRate = qualityDecayRate;
+            m_meshFeatureProcessor->SetQualityDecayRate(m_meshHandle, qualityDecayRate);
+        }
+
+        float MeshComponentController::GetQualityDecayRate() const
+        {
+            return m_meshFeatureProcessor->GetQualityDecayRate(m_meshHandle);
+        }
+
         void MeshComponentController::SetVisibility(bool visible)
         {
             if (m_isVisible != visible)
diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h
index 80b483452f..f94771b3e5 100644
--- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h
+++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h
@@ -46,6 +46,8 @@ namespace AZ
             Data::Asset m_modelAsset = { AZ::Data::AssetLoadBehavior::QueueLoad };
             RHI::DrawItemSortKey m_sortKey = 0;
             RPI::Cullable::LodOverride m_lodOverride = RPI::Cullable::NoLodOverride;
+            float m_minimumScreenCoverage = 1.0f / 1080.0f;
+            float m_qualityDecayRate = 0.5f;
             bool m_excludeFromReflectionCubeMaps = false;
             bool m_useForwardPassIblSpecular = false;
         };
@@ -97,6 +99,11 @@ namespace AZ
             void SetLodOverride(RPI::Cullable::LodOverride lodOverride) override;
             RPI::Cullable::LodOverride GetLodOverride() const override;
 
+            void SetMinimumScreenCoverage(float minimumScreenCoverage) override;
+            float GetMinimumScreenCoverage() const override;
+            void SetQualityDecayRate(float qualityDecayRate) override;
+            float GetQualityDecayRate() const override;
+
             void SetVisibility(bool visible) override;
             bool GetVisibility() const override;
 
diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp
index 4c6045d7ce..63912aa8a6 100644
--- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp
+++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp
@@ -415,6 +415,26 @@ namespace AZ
             return m_meshFeatureProcessor->GetLodOverride(*m_meshHandle);
         }
 
+        void AtomActorInstance::SetMinimumScreenCoverage(float minimumScreenCoverage)
+        {
+            m_meshFeatureProcessor->SetMinimumScreenCoverage(*m_meshHandle, minimumScreenCoverage);
+        }
+
+        float AtomActorInstance::GetMinimumScreenCoverage() const
+        {
+            return m_meshFeatureProcessor->GetMinimumScreenCoverage(*m_meshHandle);
+        }
+
+        void AtomActorInstance::SetQualityDecayRate(float qualityDecayRate)
+        {
+            m_meshFeatureProcessor->SetQualityDecayRate(*m_meshHandle, qualityDecayRate);
+        }
+
+        float AtomActorInstance::GetQualityDecayRate() const
+        {
+            return m_meshFeatureProcessor->GetQualityDecayRate(*m_meshHandle);
+        }
+
         void AtomActorInstance::SetVisibility(bool visible)
         {
             SetIsVisible(visible);
diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.h b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.h
index c854fed3c1..bd9afc668e 100644
--- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.h
+++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.h
@@ -140,6 +140,10 @@ namespace AZ
             RHI::DrawItemSortKey GetSortKey() const override;
             void SetLodOverride(RPI::Cullable::LodOverride lodOverride) override;
             RPI::Cullable::LodOverride GetLodOverride() const override;
+            void SetMinimumScreenCoverage(float minimumScreenCoverage) override;
+            float GetMinimumScreenCoverage() const override;
+            void SetQualityDecayRate(float qualityDecayRate) override;
+            float GetQualityDecayRate() const override;
             void SetVisibility(bool visible) override;
             bool GetVisibility() const override;
             // GetWorldBounds/GetLocalBounds already overridden by BoundsRequestBus::Handler

From 1a48118ece6816993409a08a90a0f2161b2229de Mon Sep 17 00:00:00 2001
From: Kyle B 
Date: Mon, 2 Aug 2021 14:01:38 -0700
Subject: [PATCH 065/803] Added comments and formatted as close to the original

Signed-off-by: Kyle B 
---
 .../Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h  | 2 +-
 .../Atom/Feature/Mesh/MeshFeatureProcessorInterface.h      | 7 ++++---
 .../Common/Code/Source/Mesh/MeshFeatureProcessor.cpp       | 4 +---
 .../Code/Source/Mesh/EditorMeshComponent.cpp               | 1 +
 .../Code/Source/Mesh/MeshComponentController.h             | 1 +
 5 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h
index 3cdff52ba7..e7e794c76e 100644
--- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h
+++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h
@@ -63,7 +63,7 @@ namespace AZ
             void SetRayTracingData();
             void SetSortKey(RHI::DrawItemSortKey sortKey);
             RHI::DrawItemSortKey GetSortKey();
-            void SetLodOverride( RPI::Cullable::LodOverride lodOverride);
+            void SetLodOverride(RPI::Cullable::LodOverride lodOverride);
             RPI::Cullable::LodOverride GetLodOverride();
             void SetMinimumScreenCoverage(float minimumScreenCoverage);
             float GetMinimumScreenCoverage();
diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessorInterface.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessorInterface.h
index b71b420625..dd64472161 100644
--- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessorInterface.h
+++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessorInterface.h
@@ -98,13 +98,14 @@ namespace AZ
             virtual void SetLodOverride(const MeshHandle& meshHandle, RPI::Cullable::LodOverride lodOverride) = 0;
             //! Gets the LOD override for a given mesh handle.
             virtual RPI::Cullable::LodOverride GetLodOverride(const MeshHandle& meshHandle) = 0;
-
+            //! Sets the minimum screen percentage for a given mesh handle. This property is the minimum screen percentage the object can take up before culled.
             virtual void SetMinimumScreenCoverage(const MeshHandle& meshHandle, float minimumScreenCoverage) = 0;
+            //! Gets the minimum screen percentage for a given mesh handle.
             virtual float GetMinimumScreenCoverage(const MeshHandle& meshHandle) = 0;
-
+            //! Sets the quality decay rate. This property is the speed at which the quality of the mesh with degrade if you are linearly moving away.
             virtual void SetQualityDecayRate(const MeshHandle& meshHandle, float qualityDecayRate) = 0;
+            //! Gets the quality decay rate.
             virtual float GetQualityDecayRate(const MeshHandle& meshHandle) = 0;
-
             //! Sets the option to exclude this mesh from baked reflection probe cubemaps
             virtual void SetExcludeFromReflectionCubeMaps(const MeshHandle& meshHandle, bool excludeFromReflectionCubeMaps) = 0;
             //! Sets the option to exclude this mesh from raytracing
diff --git a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp
index ce8ead9318..7d1d7ed851 100644
--- a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp
+++ b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp
@@ -1098,7 +1098,6 @@ namespace AZ
             cullData.m_drawListMask.reset();
 
             const size_t lodCount = lodAssets.size();
-
             for (size_t lodIndex = 0; lodIndex < lodCount; ++lodIndex)
             {
                 //initialize the lod
@@ -1117,8 +1116,7 @@ namespace AZ
                 if (lodIndex < lodAssets.size() - 1)
                 {
                     //first and middle lods: compute a stepdown value for the min
-                    lod.m_screenCoverageMin =
-                        AZStd::GetMax(lodData.m_qualityDecayRate * lod.m_screenCoverageMax, lodData.m_minimumScreenCoverage);
+                    lod.m_screenCoverageMin = AZStd::GetMax(lodData.m_qualityDecayRate * lod.m_screenCoverageMax, lodData.m_minimumScreenCoverage);
                 }
                 else
                 {
diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp
index bdbf445b7f..d46017af16 100644
--- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp
+++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp
@@ -79,6 +79,7 @@ namespace AZ
                         ->DataElement(AZ::Edit::UIHandlers::Default, &MeshComponentConfig::m_minimumScreenCoverage, "Minimum Screen Coverage", "Minimum proportion of screen area an entitiy takes up, after that the entitiy is culled.")
                             ->Attribute(AZ::Edit::Attributes::Min, 0.f)
                             ->Attribute(AZ::Edit::Attributes::Max, 1.f)
+                            ->Attribute(AZ::Edit::Attributes::Suffix, " percent")
                         ->DataElement(AZ::Edit::UIHandlers::Default, &MeshComponentConfig::m_qualityDecayRate, "Quality Decay Rate",
                             "Rate at which mesh quality decays (0 -> always stay highest quality, 1 -> quality falls off to lowest quality immediately).")
                             ->Attribute(AZ::Edit::Attributes::Min, 0.f)
diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h
index f94771b3e5..888d4bb154 100644
--- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h
+++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h
@@ -101,6 +101,7 @@ namespace AZ
 
             void SetMinimumScreenCoverage(float minimumScreenCoverage) override;
             float GetMinimumScreenCoverage() const override;
+
             void SetQualityDecayRate(float qualityDecayRate) override;
             float GetQualityDecayRate() const override;
 

From 29a2ad79a44d850e0046609c1c4ffd2a5012c0cc Mon Sep 17 00:00:00 2001
From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>
Date: Mon, 2 Aug 2021 14:04:18 -0700
Subject: [PATCH 066/803] Gems/Gestures

Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>
---
 Code/Legacy/CryCommon/LyShine/Bus/UiCanvasBus.h               | 2 +-
 Code/Legacy/CrySystem/XConsole.cpp                            | 4 ++--
 .../Code/Include/Gestures/GestureRecognizerClickOrTap.inl     | 1 +
 Gems/Gestures/Code/Include/Gestures/GestureRecognizerDrag.inl | 1 +
 Gems/Gestures/Code/Include/Gestures/GestureRecognizerHold.h   | 1 +
 Gems/Gestures/Code/Include/Gestures/GestureRecognizerHold.inl | 1 +
 .../Gestures/Code/Include/Gestures/GestureRecognizerPinch.inl | 1 +
 .../Code/Include/Gestures/GestureRecognizerRotate.inl         | 1 +
 .../Gestures/Code/Include/Gestures/GestureRecognizerSwipe.inl | 1 +
 9 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/Code/Legacy/CryCommon/LyShine/Bus/UiCanvasBus.h b/Code/Legacy/CryCommon/LyShine/Bus/UiCanvasBus.h
index 44962ddb61..4702435b83 100644
--- a/Code/Legacy/CryCommon/LyShine/Bus/UiCanvasBus.h
+++ b/Code/Legacy/CryCommon/LyShine/Bus/UiCanvasBus.h
@@ -101,7 +101,7 @@ public: // member functions
 
     //! Save this canvas to the given path in XML
     //! \return true if no error
-    virtual bool SaveToXml(const string& assetIdPathname, const string& sourceAssetPathname) = 0;
+    virtual bool SaveToXml(const AZStd::string& assetIdPathname, const AZStd::string& sourceAssetPathname) = 0;
 
     //! Initialize a set of entities that have been added to the canvas
     //! Used when instantiating a slice or for undo/redo, copy/paste
diff --git a/Code/Legacy/CrySystem/XConsole.cpp b/Code/Legacy/CrySystem/XConsole.cpp
index 2348e78a0e..0f67e4ffd9 100644
--- a/Code/Legacy/CrySystem/XConsole.cpp
+++ b/Code/Legacy/CrySystem/XConsole.cpp
@@ -2911,9 +2911,9 @@ void CXConsole::Paste()
             if (cp != '\r')
             {
                 // Convert UCS code-point into UTF-8 string
-                char utf8_buf[5] = {0};
+                AZStd::fixed_string<5> utf8_buf = {0};
                 size_t size = 5;
-                it.to_utf8_sequence(cp, utf8_buf, size);
+                it.to_utf8_sequence(cp, utf8_buf.data(), size);
                 AddInputUTF8(utf8_buf);
             }
         }
diff --git a/Gems/Gestures/Code/Include/Gestures/GestureRecognizerClickOrTap.inl b/Gems/Gestures/Code/Include/Gestures/GestureRecognizerClickOrTap.inl
index 84837972e8..57716c7d9f 100644
--- a/Gems/Gestures/Code/Include/Gestures/GestureRecognizerClickOrTap.inl
+++ b/Gems/Gestures/Code/Include/Gestures/GestureRecognizerClickOrTap.inl
@@ -8,6 +8,7 @@
 
 #include 
 #include 
+#include 
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
 inline void Gestures::RecognizerClickOrTap::Config::Reflect(AZ::ReflectContext* context)
diff --git a/Gems/Gestures/Code/Include/Gestures/GestureRecognizerDrag.inl b/Gems/Gestures/Code/Include/Gestures/GestureRecognizerDrag.inl
index 368f236338..2c1af6fbc9 100644
--- a/Gems/Gestures/Code/Include/Gestures/GestureRecognizerDrag.inl
+++ b/Gems/Gestures/Code/Include/Gestures/GestureRecognizerDrag.inl
@@ -8,6 +8,7 @@
 
 #include 
 #include 
+#include 
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
 inline void Gestures::RecognizerDrag::Config::Reflect(AZ::ReflectContext* context)
diff --git a/Gems/Gestures/Code/Include/Gestures/GestureRecognizerHold.h b/Gems/Gestures/Code/Include/Gestures/GestureRecognizerHold.h
index b8d538b426..87c53d815a 100644
--- a/Gems/Gestures/Code/Include/Gestures/GestureRecognizerHold.h
+++ b/Gems/Gestures/Code/Include/Gestures/GestureRecognizerHold.h
@@ -9,6 +9,7 @@
 
 #include "IGestureRecognizer.h"
 
+#include 
 #include 
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/Gems/Gestures/Code/Include/Gestures/GestureRecognizerHold.inl b/Gems/Gestures/Code/Include/Gestures/GestureRecognizerHold.inl
index 48f23cce1f..b399639f6d 100644
--- a/Gems/Gestures/Code/Include/Gestures/GestureRecognizerHold.inl
+++ b/Gems/Gestures/Code/Include/Gestures/GestureRecognizerHold.inl
@@ -8,6 +8,7 @@
 
 #include 
 #include 
+#include 
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
 inline void Gestures::RecognizerHold::Config::Reflect(AZ::ReflectContext* context)
diff --git a/Gems/Gestures/Code/Include/Gestures/GestureRecognizerPinch.inl b/Gems/Gestures/Code/Include/Gestures/GestureRecognizerPinch.inl
index e577be0e48..f6c0427b2c 100644
--- a/Gems/Gestures/Code/Include/Gestures/GestureRecognizerPinch.inl
+++ b/Gems/Gestures/Code/Include/Gestures/GestureRecognizerPinch.inl
@@ -8,6 +8,7 @@
 
 #include 
 #include 
+#include 
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
 inline void Gestures::RecognizerPinch::Config::Reflect(AZ::ReflectContext* context)
diff --git a/Gems/Gestures/Code/Include/Gestures/GestureRecognizerRotate.inl b/Gems/Gestures/Code/Include/Gestures/GestureRecognizerRotate.inl
index eb3b20287e..9dff9a115a 100644
--- a/Gems/Gestures/Code/Include/Gestures/GestureRecognizerRotate.inl
+++ b/Gems/Gestures/Code/Include/Gestures/GestureRecognizerRotate.inl
@@ -8,6 +8,7 @@
 
 #include 
 #include 
+#include 
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
 inline void Gestures::RecognizerRotate::Config::Reflect(AZ::ReflectContext* context)
diff --git a/Gems/Gestures/Code/Include/Gestures/GestureRecognizerSwipe.inl b/Gems/Gestures/Code/Include/Gestures/GestureRecognizerSwipe.inl
index 9fdab7b1a2..8d59525e93 100644
--- a/Gems/Gestures/Code/Include/Gestures/GestureRecognizerSwipe.inl
+++ b/Gems/Gestures/Code/Include/Gestures/GestureRecognizerSwipe.inl
@@ -8,6 +8,7 @@
 
 #include 
 #include 
+#include 
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
 inline void Gestures::RecognizerSwipe::Config::Reflect(AZ::ReflectContext* context)

From 63ed78d2679e9eaec353a2d3af0a40f0fb22a0c6 Mon Sep 17 00:00:00 2001
From: Dayo Lawal 
Date: Mon, 2 Aug 2021 17:27:26 -0500
Subject: [PATCH 067/803] status_bar

Signed-off-by: Dayo Lawal 
---
 .../Window/AtomToolsMainWindow.h              |  1 +
 .../Source/Window/AtomToolsMainWindow.cpp     |  4 +++
 .../Source/Window/MaterialEditorWindow.cpp    | 35 ++++++++++++-------
 .../Code/Source/Window/MaterialEditorWindow.h |  2 --
 .../Code/materialeditorwindow_files.cmake     |  6 ++--
 .../Window/ShaderManagementConsoleWindow.cpp  |  4 +++
 6 files changed, 34 insertions(+), 18 deletions(-)

diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindow.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindow.h
index 2cc6621cec..edb8ff4322 100644
--- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindow.h
+++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindow.h
@@ -53,6 +53,7 @@ namespace AtomToolsFramework
         QWidget* m_centralWidget = nullptr;
         QMenuBar* m_menuBar = nullptr;
         AzQtComponents::TabWidget* m_tabWidget = nullptr;
+        QStatusBar* m_statusBar = nullptr;
 
         AZStd::unordered_map m_dockWidgets;
 
diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp
index 849169e2e3..ffc618c574 100644
--- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp
+++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp
@@ -31,6 +31,10 @@ namespace AtomToolsFramework
         m_tabWidget->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Preferred);
         m_tabWidget->setContentsMargins(0, 0, 0, 0);
 
+        m_statusBar = new QStatusBar(this);
+        m_statusBar->setObjectName("StatusBar");
+        statusBar()->addPermanentWidget(m_statusBar, 1);
+
         AtomToolsMainWindowRequestBus::Handler::BusConnect();
     }
 
diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp
index 96a94ebfcc..733a01539e 100644
--- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp
+++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp
@@ -101,10 +101,6 @@ namespace MaterialEditor
         m_centralWidget->setLayout(vl);
         setCentralWidget(m_centralWidget);
 
-        m_statusBar = new StatusBarWidget(this);
-        m_statusBar->setObjectName("StatusBar");
-        statusBar()->addPermanentWidget(m_statusBar, 1);
-
         SetupMenu();
         SetupTabs();
 
@@ -245,7 +241,8 @@ namespace MaterialEditor
         const QString documentPath = GetDocumentPath(documentId);
         if (!documentPath.isEmpty())
         {
-            m_statusBar->UpdateStatusInfo(QString("Material opened: %1").arg(documentPath));
+            const QString status = QString("Material closed: %1").arg(documentPath);
+            m_statusBar->setWindowIconText(QString("%1").arg(status));
         }
     }
 
@@ -254,7 +251,8 @@ namespace MaterialEditor
         RemoveTabForDocumentId(documentId);
 
         const QString documentPath = GetDocumentPath(documentId);
-        m_statusBar->UpdateStatusInfo(QString("Material closed: %1").arg(documentPath));
+        const QString status = QString("Material closed: %1").arg(documentPath);
+        m_statusBar->setWindowIconText(QString("%1").arg(status));
     }
 
     void MaterialEditorWindow::OnDocumentModified(const AZ::Uuid& documentId)
@@ -280,7 +278,8 @@ namespace MaterialEditor
         UpdateTabForDocumentId(documentId);
 
         const QString documentPath = GetDocumentPath(documentId);
-        m_statusBar->UpdateStatusInfo(QString("Material saved: %1").arg(documentPath));
+        const QString status = QString("Material closed: %1").arg(documentPath);
+        m_statusBar->setWindowIconText(QString("%1").arg(status));
     }
 
     void MaterialEditorWindow::SetupMenu()
@@ -321,7 +320,8 @@ namespace MaterialEditor
             if (!result)
             {
                 const QString documentPath = GetDocumentPath(documentId);
-                m_statusBar->UpdateStatusError(QString("Failed to save material: %1").arg(documentPath));
+                const QString status = QString("Failed to save material: %1").arg(documentPath);
+                m_statusBar->setWindowIconText(QString("%1").arg(status));
             }
         }, QKeySequence::Save);
 
@@ -334,7 +334,8 @@ namespace MaterialEditor
                 documentId, AtomToolsFramework::GetSaveFileInfo(documentPath).absoluteFilePath().toUtf8().constData());
             if (!result)
             {
-                m_statusBar->UpdateStatusError(QString("Failed to save material: %1").arg(documentPath));
+                const QString status = QString("Failed to save material: %1").arg(documentPath);
+                m_statusBar->setWindowIconText(QString("%1").arg(status));
             }
         }, QKeySequence::SaveAs);
 
@@ -347,7 +348,8 @@ namespace MaterialEditor
                 documentId, AtomToolsFramework::GetSaveFileInfo(documentPath).absoluteFilePath().toUtf8().constData());
             if (!result)
             {
-                m_statusBar->UpdateStatusError(QString("Failed to save material: %1").arg(documentPath));
+                const QString status = QString("Failed to save material: %1").arg(documentPath);
+                m_statusBar->setWindowIconText(QString("%1").arg(status));
             }
         });
 
@@ -356,7 +358,8 @@ namespace MaterialEditor
             MaterialDocumentSystemRequestBus::BroadcastResult(result, &MaterialDocumentSystemRequestBus::Events::SaveAllDocuments);
             if (!result)
             {
-                m_statusBar->UpdateStatusError(QString("Failed to save materials."));
+                const QString status = QString("Failed to save materials.");
+                m_statusBar->setWindowIconText(QString("%1").arg(status));
             }
         });
 
@@ -401,7 +404,8 @@ namespace MaterialEditor
             if (!result)
             {
                 const QString documentPath = GetDocumentPath(documentId);
-                m_statusBar->UpdateStatusError(QString("Failed to perform Undo in material: %1").arg(documentPath));
+                const QString status = QString("Failed to perform Undo in material: %1").arg(documentPath);
+                m_statusBar->setWindowIconText(QString("%1").arg(status));
             }
         }, QKeySequence::Undo);
 
@@ -412,7 +416,8 @@ namespace MaterialEditor
             if (!result)
             {
                 const QString documentPath = GetDocumentPath(documentId);
-                m_statusBar->UpdateStatusError(QString("Failed to perform Undo in material: %1").arg(documentPath));
+                const QString status = QString("Failed to perform Undo in material: %1").arg(documentPath);
+                m_statusBar->setWindowIconText(QString("%1").arg(status));
             }
         }, QKeySequence::Redo);
 
@@ -505,6 +510,10 @@ namespace MaterialEditor
 
         AtomToolsMainWindow::AddTabForDocumentId(documentId);
 
+        // Blocking signals from the tab bar so the currentChanged signal is not sent while a document is already being opened.
+        // This prevents the OnDocumentOpened notification from being sent recursively.
+        const QSignalBlocker blocker(m_tabWidget);
+
         // Create a new tab for the document ID and assign it's label to the file name of the document.
         AZStd::string absolutePath;
         MaterialDocumentRequestBus::EventResult(absolutePath, documentId, &MaterialDocumentRequestBus::Events::GetAbsolutePath);
diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.h
index a443f04ebe..65c13a094d 100644
--- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.h
+++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.h
@@ -113,7 +113,5 @@ namespace MaterialEditor
         QMenu* m_menuHelp = {};
         QAction* m_actionHelp = {};
         QAction* m_actionAbout = {};
-
-        StatusBarWidget* m_statusBar = {};
     };
 } // namespace MaterialEditor
diff --git a/Gems/Atom/Tools/MaterialEditor/Code/materialeditorwindow_files.cmake b/Gems/Atom/Tools/MaterialEditor/Code/materialeditorwindow_files.cmake
index f5891a5c2b..caef9916f6 100644
--- a/Gems/Atom/Tools/MaterialEditor/Code/materialeditorwindow_files.cmake
+++ b/Gems/Atom/Tools/MaterialEditor/Code/materialeditorwindow_files.cmake
@@ -42,15 +42,15 @@ set(FILES
     Source/Window/PerformanceMonitor/PerformanceMonitorWidget.cpp
     Source/Window/PerformanceMonitor/PerformanceMonitorWidget.h
     Source/Window/PerformanceMonitor/PerformanceMonitorWidget.ui
+    Source/Window/StatusBar/StatusBarWidget.cpp
+    Source/Window/StatusBar/StatusBarWidget.h
+    Source/Window/StatusBar/StatusBarWidget.ui
     Source/Window/ToolBar/MaterialEditorToolBar.h
     Source/Window/ToolBar/MaterialEditorToolBar.cpp
     Source/Window/ToolBar/ModelPresetComboBox.h
     Source/Window/ToolBar/ModelPresetComboBox.cpp
     Source/Window/ToolBar/LightingPresetComboBox.h
     Source/Window/ToolBar/LightingPresetComboBox.cpp
-    Source/Window/StatusBar/StatusBarWidget.cpp
-    Source/Window/StatusBar/StatusBarWidget.h
-    Source/Window/StatusBar/StatusBarWidget.ui
     Source/Window/MaterialInspector/MaterialInspector.h
     Source/Window/MaterialInspector/MaterialInspector.cpp
     Source/Window/ViewportSettingsInspector/ViewportSettingsInspector.h
diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp
index 05f88655ca..e02ab83597 100644
--- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp
+++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp
@@ -303,6 +303,10 @@ namespace ShaderManagementConsole
 
         AtomToolsMainWindow::AddTabForDocumentId(documentId);
 
+        // Blocking signals from the tab bar so the currentChanged signal is not sent while a document is already being opened.
+        // This prevents the OnDocumentOpened notification from being sent recursively.
+        const QSignalBlocker blocker(m_tabWidget);
+
         // Create a new tab for the document ID and assign it's label to the file name of the document.
         AZStd::string absolutePath;
         ShaderManagementConsoleDocumentRequestBus::EventResult(absolutePath, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::GetAbsolutePath);

From d5c491a694b3990ab6a5ab15a72f237cb4bc10a0 Mon Sep 17 00:00:00 2001
From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>
Date: Mon, 2 Aug 2021 16:04:46 -0700
Subject: [PATCH 068/803] Gems\MetaStream

Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>
---
 Gems/Metastream/Code/Source/MetastreamGem.cpp | 2 +-
 Gems/Metastream/Code/Tests/MetastreamTest.cpp | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/Gems/Metastream/Code/Source/MetastreamGem.cpp b/Gems/Metastream/Code/Source/MetastreamGem.cpp
index d1792c439f..2bb213662c 100644
--- a/Gems/Metastream/Code/Source/MetastreamGem.cpp
+++ b/Gems/Metastream/Code/Source/MetastreamGem.cpp
@@ -323,7 +323,7 @@ namespace Metastream
         {
             // Initialise and start the HTTP server
             m_server = std::unique_ptr(new CivetHttpServer(m_cache.get()));
-            string serverOptions = m_serverOptionsCVar->GetString();
+            AZStd::string serverOptions = m_serverOptionsCVar->GetString();
             CryLogAlways("Initializing Metastream: Options=\"%s\"", serverOptions.c_str());
 
             bool result = m_server->Start(serverOptions.c_str());
diff --git a/Gems/Metastream/Code/Tests/MetastreamTest.cpp b/Gems/Metastream/Code/Tests/MetastreamTest.cpp
index 4f1d37391a..1b25fb5327 100644
--- a/Gems/Metastream/Code/Tests/MetastreamTest.cpp
+++ b/Gems/Metastream/Code/Tests/MetastreamTest.cpp
@@ -60,7 +60,7 @@ public:
 
     }
 
-    const string m_serverOptionsString = "document_root=Gems/Metastream/Files;listening_ports=8082";
+    const char* m_serverOptionsString = "document_root=Gems/Metastream/Files;listening_ports=8082";
 
 protected:
     void SetUp() override

From 0620f6dff3267d2a5efda4ee89babd064083c562 Mon Sep 17 00:00:00 2001
From: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com>
Date: Mon, 2 Aug 2021 19:06:02 -0400
Subject: [PATCH 069/803] Minor refactoring

Signed-off-by: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com>
---
 .../Source/Debug/MultiplayerDebugByteReporter.cpp  |  3 ---
 .../Source/Debug/MultiplayerDebugByteReporter.h    |  5 -----
 .../Debug/MultiplayerDebugSystemComponent.cpp      | 14 +++++++++-----
 .../Source/Debug/MultiplayerDebugSystemComponent.h |  2 ++
 4 files changed, 11 insertions(+), 13 deletions(-)

diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.cpp b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.cpp
index 38a1a27dcd..361f9d943d 100644
--- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.cpp
+++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.cpp
@@ -169,7 +169,6 @@ namespace Multiplayer
             m_currentComponentReport = nullptr;
         }
 
-        m_gdeDirtyBytes.ReportAggregateBytes();
         MultiplayerDebugByteReporter::ReportAggregateBytes();
     }
 
@@ -183,7 +182,6 @@ namespace Multiplayer
         }
 
         SetEntityName(other.GetEntityName());
-        m_gdeDirtyBytes.Combine(other.m_gdeDirtyBytes);
     }
 
     void MultiplayerDebugEntityReporter::Reset()
@@ -191,7 +189,6 @@ namespace Multiplayer
         MultiplayerDebugByteReporter::Reset();
 
         m_componentReports.clear();
-        m_gdeDirtyBytes.Reset();
     }
 
     AZStd::map& MultiplayerDebugEntityReporter::GetComponentReports()
diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.h b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.h
index 934c6f3aac..279f7fb360 100644
--- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.h
+++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.h
@@ -58,8 +58,6 @@ namespace Multiplayer
 
         using Report = AZStd::pair;
         AZStd::vector GetFieldReports();
-        AZStd::size_t GetTotalDirtyBits() const { return m_componentDirtyBytes.GetTotalBytes(); }
-        float GetAvgDirtyBits() const { return m_componentDirtyBytes.GetAverageBytes(); }
 
         void Combine(const MultiplayerDebugComponentReporter& other);
 
@@ -87,13 +85,10 @@ namespace Multiplayer
         }
 
         AZStd::map& GetComponentReports();
-        AZStd::size_t GetTotalDirtyBits() const { return m_gdeDirtyBytes.GetTotalBytes(); }
-        float GetAvgDirtyBits() const { return m_gdeDirtyBytes.GetAverageBytes(); }
 
     private:
         MultiplayerDebugComponentReporter* m_currentComponentReport = nullptr;
         AZStd::map m_componentReports;
-        MultiplayerDebugByteReporter m_gdeDirtyBytes;
         AZStd::string m_entityName;
     };
 }
diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.cpp b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.cpp
index f892ee9724..0e015fc86d 100644
--- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.cpp
+++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.cpp
@@ -341,17 +341,21 @@ namespace Multiplayer
 
         if (m_displayPerEntityStats)
         {
-            // This overrides @net_DebugNetworkEntity_ShowBandwidth value
             if (ImGui::Begin("Multiplayer Per Entity Stats", &m_displayPerEntityStats, ImGuiWindowFlags_AlwaysAutoResize))
             {
+                if (ImGui::Checkbox("Show Bandwidth over Entities", &m_displayPerEntityBandwidth))
+                {
+                    // This overrides @net_DebugNetworkEntity_ShowBandwidth value
+                    if (m_reporter == nullptr)
+                    {
+                        ShowEntityBandwidthDebugOverlay();
+                    }
+                }
+
                 if (m_reporter)
                 {
                     m_reporter->OnImGuiUpdate();
                 }
-                else
-                {
-                    ShowEntityBandwidthDebugOverlay();
-                }
             }
         }
     }
diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.h b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.h
index 87b238c79b..9be53cca02 100644
--- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.h
+++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.h
@@ -60,7 +60,9 @@ namespace Multiplayer
     private:
         bool m_displayNetworkingStats = false;
         bool m_displayMultiplayerStats = false;
+
         bool m_displayPerEntityStats = false;
+        bool m_displayPerEntityBandwidth = false;
 
         AZStd::unique_ptr m_reporter;
     };

From 061cb98f74971b54744e8f241eeab3b3a26393b2 Mon Sep 17 00:00:00 2001
From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>
Date: Mon, 2 Aug 2021 16:07:23 -0700
Subject: [PATCH 070/803] auto-search/replace

Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>
---
 Code/Editor/BaseLibraryManager.cpp            |   2 +-
 Code/Editor/Commands/CommandManager.cpp       |   2 +-
 Code/Editor/Commands/CommandManager.h         |  22 ++--
 Code/Editor/ConfigGroup.h                     |   6 +-
 Code/Editor/Controls/SplineCtrlEx.h           |   2 +-
 Code/Editor/Include/Command.h                 | 110 +++++++++---------
 .../EditorAssetImporter/AssetImporterPlugin.h |   2 +-
 Code/Editor/Util/EditorUtils.h                |   1 +
 Code/Editor/Util/FileUtil.cpp                 |   2 +-
 Code/Editor/Util/IXmlHistoryManager.h         |   2 +-
 Code/Editor/Util/StringHelpers.cpp            |  42 +++----
 Code/Editor/Util/StringHelpers.h              |  42 +++----
 Code/Editor/Util/XmlHistoryManager.cpp        |   2 +-
 Code/Editor/Util/XmlHistoryManager.h          |   2 +-
 .../GridMate/GridMate/Carrier/Carrier.cpp     |   8 +-
 .../GridMate/GridMate/Carrier/Carrier.h       |   2 +-
 .../GridMate/Carrier/DefaultHandshake.cpp     |   2 +-
 .../GridMate/Carrier/DefaultHandshake.h       |   2 +-
 .../GridMate/GridMate/Carrier/Driver.h        |   4 +-
 .../GridMate/GridMate/Carrier/Handshake.h     |   2 +-
 .../GridMate/Carrier/SocketDriver.cpp         |  14 +--
 .../GridMate/GridMate/Carrier/SocketDriver.h  |  14 +--
 .../GridMate/Drillers/SessionDriller.cpp      |   2 +-
 .../GridMate/Drillers/SessionDriller.h        |   2 +-
 .../GridMate/GridMate/Session/LANSession.cpp  |  12 +-
 .../GridMate/Session/LANSessionServiceTypes.h |   6 +-
 .../GridMate/GridMate/Session/Session.cpp     |   8 +-
 .../GridMate/GridMate/Session/Session.h       |  12 +-
 Code/Framework/GridMate/Tests/Session.cpp     |  12 +-
 .../Framework/GridMate/Tests/TestProfiler.cpp |   2 +-
 .../Legacy/CryCommon/LocalizationManagerBus.h |   2 +-
 .../LyShine/Animation/IUiAnimation.h          |  11 +-
 Code/Legacy/CryCommon/LyShine/ISprite.h       |   7 +-
 33 files changed, 179 insertions(+), 184 deletions(-)

diff --git a/Code/Editor/BaseLibraryManager.cpp b/Code/Editor/BaseLibraryManager.cpp
index 8e555cae8c..2189156454 100644
--- a/Code/Editor/BaseLibraryManager.cpp
+++ b/Code/Editor/BaseLibraryManager.cpp
@@ -560,7 +560,7 @@ QString CBaseLibraryManager::MakeUniqueItemName(const QString& srcName, const QS
         return srcName;
     }
 
-    std::sort(possibleDuplicates.begin(), possibleDuplicates.end(), [](const string& strOne, const string& strTwo)
+    std::sort(possibleDuplicates.begin(), possibleDuplicates.end(), [](const AZStd::string& strOne, const AZStd::string& strTwo)
         {
             // I can assume size sorting since if the length is different, either one of the two strings doesn't
             // closely match the string we are trying to duplicate, or it's a bigger number (X1 vs X10)
diff --git a/Code/Editor/Commands/CommandManager.cpp b/Code/Editor/Commands/CommandManager.cpp
index 90059ea195..708fccd16b 100644
--- a/Code/Editor/Commands/CommandManager.cpp
+++ b/Code/Editor/Commands/CommandManager.cpp
@@ -79,7 +79,7 @@ CEditorCommandManager::~CEditorCommandManager()
     m_uiCommands.clear();
 }
 
-string CEditorCommandManager::GetFullCommandName(const string& module, const string& name)
+string CEditorCommandManager::GetFullCommandName(const AZStd::string& module, const string& name)
 {
     string fullName = module;
     fullName += ".";
diff --git a/Code/Editor/Commands/CommandManager.h b/Code/Editor/Commands/CommandManager.h
index 2ec4a137bc..a76df830d0 100644
--- a/Code/Editor/Commands/CommandManager.h
+++ b/Code/Editor/Commands/CommandManager.h
@@ -48,20 +48,20 @@ public:
         const AZStd::function& functor,
         const CCommand0::SUIInfo& uiInfo);
     bool AttachUIInfo(const char* fullCmdName, const CCommand0::SUIInfo& uiInfo);
-    bool GetUIInfo(const string& module, const string& name, CCommand0::SUIInfo& uiInfo) const;
-    bool GetUIInfo(const string& fullCmdName, CCommand0::SUIInfo& uiInfo) const;
-    QString Execute(const string& cmdLine);
-    QString Execute(const string& module, const string& name, const CCommand::CArgs& args);
+    bool GetUIInfo(const AZStd::string& module, const AZStd::string& name, CCommand0::SUIInfo& uiInfo) const;
+    bool GetUIInfo(const AZStd::string& fullCmdName, CCommand0::SUIInfo& uiInfo) const;
+    QString Execute(const AZStd::string& cmdLine);
+    QString Execute(const AZStd::string& module, const AZStd::string& name, const CCommand::CArgs& args);
     void Execute(int commandId);
     void GetCommandList(std::vector& cmds) const;
     //! Used in the console dialog
-    string AutoComplete(const string& substr) const;
+    string AutoComplete(const AZStd::string& substr) const;
     bool IsRegistered(const char* module, const char* name) const;
     bool IsRegistered(const char* cmdLine) const;
     bool IsRegistered(int commandId) const;
-    void SetCommandAvailableInScripting(const string& module, const string& name);
-    bool IsCommandAvailableInScripting(const string& module, const string& name) const;
-    bool IsCommandAvailableInScripting(const string& fullCmdName) const;
+    void SetCommandAvailableInScripting(const AZStd::string& module, const AZStd::string& name);
+    bool IsCommandAvailableInScripting(const AZStd::string& module, const AZStd::string& name) const;
+    bool IsCommandAvailableInScripting(const AZStd::string& fullCmdName) const;
     //! Turning off the warning is needed for reloading the ribbon bar.
     void TurnDuplicateWarningOn() { m_bWarnDuplicate = true; }
     void TurnDuplicateWarningOff() { m_bWarnDuplicate = false; }
@@ -86,9 +86,9 @@ protected:
     bool m_bWarnDuplicate;
 
     static int GenNewCommandId();
-    static string GetFullCommandName(const string& module, const string& name);
-    static void GetArgsFromString(const string& argsTxt, CCommand::CArgs& argList);
-    void LogCommand(const string& fullCmdName, const CCommand::CArgs& args) const;
+    static string GetFullCommandName(const AZStd::string& module, const AZStd::string& name);
+    static void GetArgsFromString(const AZStd::string& argsTxt, CCommand::CArgs& argList);
+    void LogCommand(const AZStd::string& fullCmdName, const CCommand::CArgs& args) const;
     QString ExecuteAndLogReturn(CCommand* pCommand, const CCommand::CArgs& args);
 };
 
diff --git a/Code/Editor/ConfigGroup.h b/Code/Editor/ConfigGroup.h
index 35c0b8e47f..5d9b22b2b9 100644
--- a/Code/Editor/ConfigGroup.h
+++ b/Code/Editor/ConfigGroup.h
@@ -47,12 +47,12 @@ namespace Config
             return m_type;
         }
 
-        ILINE const string& GetName() const
+        ILINE const AZStd::string& GetName() const
         {
             return m_name;
         }
 
-        ILINE const string& GetDescription() const
+        ILINE const AZStd::string& GetDescription() const
         {
             return m_description;
         }
@@ -71,7 +71,7 @@ namespace Config
         static EType TranslateType(const bool&) { return eType_BOOL; }
         static EType TranslateType(const int&) { return eType_INT; }
         static EType TranslateType(const float&) { return eType_FLOAT; }
-        static EType TranslateType(const string&) { return eType_STRING; }
+        static EType TranslateType(const AZStd::string&) { return eType_STRING; }
 
     protected:
         EType m_type;
diff --git a/Code/Editor/Controls/SplineCtrlEx.h b/Code/Editor/Controls/SplineCtrlEx.h
index 8592febf88..de07c4214b 100644
--- a/Code/Editor/Controls/SplineCtrlEx.h
+++ b/Code/Editor/Controls/SplineCtrlEx.h
@@ -53,7 +53,7 @@ class QRubberBand;
 class ISplineSet
 {
 public:
-    virtual ISplineInterpolator* GetSplineFromID(const string& id) = 0;
+    virtual ISplineInterpolator* GetSplineFromID(const AZStd::string& id) = 0;
     virtual string GetIDFromSpline(ISplineInterpolator* pSpline) = 0;
     virtual int GetSplineCount() const = 0;
     virtual int GetKeyCountAtTime(float time, float threshold) const = 0;
diff --git a/Code/Editor/Include/Command.h b/Code/Editor/Include/Command.h
index 69853ddb4f..92a7736446 100644
--- a/Code/Editor/Include/Command.h
+++ b/Code/Editor/Include/Command.h
@@ -27,10 +27,10 @@ class CCommand
 {
 public:
     CCommand(
-        const string& module,
-        const string& name,
-        const string& description,
-        const string& example)
+        const AZStd::string& module,
+        const AZStd::string& name,
+        const AZStd::string& description,
+        const AZStd::string& example)
         : m_module(module)
         , m_name(name)
         , m_description(description)
@@ -79,7 +79,7 @@ public:
         }
         int GetArgCount() const
         { return m_args.size(); }
-        const string& GetArg(int i) const
+        const AZStd::string& GetArg(int i) const
         {
             assert(0 <= i && i < GetArgCount());
             return m_args[i];
@@ -89,10 +89,10 @@ public:
         unsigned char m_stringFlags;    // This is needed to quote string parameters when logging a command.
     };
 
-    const string& GetName() const { return m_name; }
-    const string& GetModule() const { return m_module; }
-    const string& GetDescription() const { return m_description; }
-    const string& GetExample() const { return m_example; }
+    const AZStd::string& GetName() const { return m_name; }
+    const AZStd::string& GetModule() const { return m_module; }
+    const AZStd::string& GetDescription() const { return m_description; }
+    const AZStd::string& GetExample() const { return m_example; }
 
     void SetAvailableInScripting() { m_bAlsoAvailableInScripting = true; };
     bool IsAvailableInScripting() const { return m_bAlsoAvailableInScripting; }
@@ -137,8 +137,8 @@ class CCommand0
     : public CCommand
 {
 public:
-    CCommand0(const string& module, const string& name,
-        const string& description, const string& example,
+    CCommand0(const AZStd::string& module, const AZStd::string& name,
+        const AZStd::string& description, const AZStd::string& example,
         const AZStd::function& functor)
         : CCommand(module, name, description, example)
         , m_functor(functor) {}
@@ -179,8 +179,8 @@ class CCommand0wRet
     : public CCommand
 {
 public:
-    CCommand0wRet(const string& module, const string& name,
-        const string& description, const string& example,
+    CCommand0wRet(const AZStd::string& module, const AZStd::string& name,
+        const AZStd::string& description, const AZStd::string& example,
         const AZStd::function& functor);
 
     QString Execute(const CArgs& args);
@@ -195,8 +195,8 @@ class CCommand1
     : public CCommand
 {
 public:
-    CCommand1(const string& module, const string& name,
-        const string& description, const string& example,
+    CCommand1(const AZStd::string& module, const AZStd::string& name,
+        const AZStd::string& description, const AZStd::string& example,
         const AZStd::function& functor);
 
     QString Execute(const CArgs& args);
@@ -211,8 +211,8 @@ class CCommand1wRet
     : public CCommand
 {
 public:
-    CCommand1wRet(const string& module, const string& name,
-        const string& description, const string& example,
+    CCommand1wRet(const AZStd::string& module, const AZStd::string& name,
+        const AZStd::string& description, const AZStd::string& example,
         const AZStd::function& functor);
 
     QString Execute(const CArgs& args);
@@ -227,8 +227,8 @@ class CCommand2
     : public CCommand
 {
 public:
-    CCommand2(const string& module, const string& name,
-        const string& description, const string& example,
+    CCommand2(const AZStd::string& module, const AZStd::string& name,
+        const AZStd::string& description, const AZStd::string& example,
         const AZStd::function& functor);
 
     QString Execute(const CArgs& args);
@@ -243,8 +243,8 @@ class CCommand2wRet
     : public CCommand
 {
 public:
-    CCommand2wRet(const string& module, const string& name,
-        const string& description, const string& example,
+    CCommand2wRet(const AZStd::string& module, const AZStd::string& name,
+        const AZStd::string& description, const AZStd::string& example,
         const AZStd::function& functor);
 
     QString Execute(const CArgs& args);
@@ -259,8 +259,8 @@ class CCommand3
     : public CCommand
 {
 public:
-    CCommand3(const string& module, const string& name,
-        const string& description, const string& example,
+    CCommand3(const AZStd::string& module, const AZStd::string& name,
+        const AZStd::string& description, const AZStd::string& example,
         const AZStd::function& functor);
 
     QString Execute(const CArgs& args);
@@ -275,8 +275,8 @@ class CCommand3wRet
     : public CCommand
 {
 public:
-    CCommand3wRet(const string& module, const string& name,
-        const string& description, const string& example,
+    CCommand3wRet(const AZStd::string& module, const AZStd::string& name,
+        const AZStd::string& description, const AZStd::string& example,
         const AZStd::function& functor);
 
     QString Execute(const CArgs& args);
@@ -291,8 +291,8 @@ class CCommand4
     : public CCommand
 {
 public:
-    CCommand4(const string& module, const string& name,
-        const string& description, const string& example,
+    CCommand4(const AZStd::string& module, const AZStd::string& name,
+        const AZStd::string& description, const AZStd::string& example,
         const AZStd::function& functor);
 
     QString Execute(const CArgs& args);
@@ -307,8 +307,8 @@ class CCommand4wRet
     : public CCommand
 {
 public:
-    CCommand4wRet(const string& module, const string& name,
-        const string& description, const string& example,
+    CCommand4wRet(const AZStd::string& module, const AZStd::string& name,
+        const AZStd::string& description, const AZStd::string& example,
         const AZStd::function& functor);
 
     QString Execute(const CArgs& args);
@@ -323,8 +323,8 @@ class CCommand5
     : public CCommand
 {
 public:
-    CCommand5(const string& module, const string& name,
-        const string& description, const string& example,
+    CCommand5(const AZStd::string& module, const AZStd::string& name,
+        const AZStd::string& description, const AZStd::string& example,
         const AZStd::function& functor);
 
     QString Execute(const CArgs& args);
@@ -339,8 +339,8 @@ class CCommand6
     : public CCommand
 {
 public:
-    CCommand6(const string& module, const string& name,
-        const string& description, const string& example,
+    CCommand6(const AZStd::string& module, const AZStd::string& name,
+        const AZStd::string& description, const AZStd::string& example,
         const AZStd::function& functor);
 
     QString Execute(const CArgs& args);
@@ -353,8 +353,8 @@ protected:
 //////////////////////////////////////////////////////////////////////////
 
 template 
-CCommand0wRet::CCommand0wRet(const string& module, const string& name,
-    const string& description, const string& example,
+CCommand0wRet::CCommand0wRet(const AZStd::string& module, const AZStd::string& name,
+    const AZStd::string& description, const AZStd::string& example,
     const AZStd::function& functor)
     : CCommand(module, name, description, example)
     , m_functor(functor)
@@ -373,8 +373,8 @@ QString CCommand0wRet::Execute(const CCommand::CArgs& args)
 //////////////////////////////////////////////////////////////////////////
 
 template 
-CCommand1::CCommand1(const string& module, const string& name,
-    const string& description, const string& example,
+CCommand1::CCommand1(const AZStd::string& module, const AZStd::string& name,
+    const AZStd::string& description, const AZStd::string& example,
     const AZStd::function& functor)
     : CCommand(module, name, description, example)
     , m_functor(functor)
@@ -410,8 +410,8 @@ QString CCommand1::Execute(const CCommand::CArgs& args)
 //////////////////////////////////////////////////////////////////////////
 
 template 
-CCommand1wRet::CCommand1wRet(const string& module, const string& name,
-    const string& description, const string& example,
+CCommand1wRet::CCommand1wRet(const AZStd::string& module, const AZStd::string& name,
+    const AZStd::string& description, const AZStd::string& example,
     const AZStd::function& functor)
     : CCommand(module, name, description, example)
     , m_functor(functor)
@@ -448,8 +448,8 @@ QString CCommand1wRet::Execute(const CCommand::CArgs& args)
 //////////////////////////////////////////////////////////////////////////
 
 template 
-CCommand2::CCommand2(const string& module, const string& name,
-    const string& description, const string& example,
+CCommand2::CCommand2(const AZStd::string& module, const AZStd::string& name,
+    const AZStd::string& description, const AZStd::string& example,
     const AZStd::function& functor)
     : CCommand(module, name, description, example)
     , m_functor(functor)
@@ -487,8 +487,8 @@ QString CCommand2::Execute(const CCommand::CArgs& args)
 //////////////////////////////////////////////////////////////////////////
 
 template 
-CCommand2wRet::CCommand2wRet(const string& module, const string& name,
-    const string& description, const string& example,
+CCommand2wRet::CCommand2wRet(const AZStd::string& module, const AZStd::string& name,
+    const AZStd::string& description, const AZStd::string& example,
     const AZStd::function& functor)
     : CCommand(module, name, description, example)
     , m_functor(functor)
@@ -527,8 +527,8 @@ QString CCommand2wRet::Execute(const CCommand::CArgs& args)
 //////////////////////////////////////////////////////////////////////////
 
 template 
-CCommand3::CCommand3(const string& module, const string& name,
-    const string& description, const string& example,
+CCommand3::CCommand3(const AZStd::string& module, const AZStd::string& name,
+    const AZStd::string& description, const AZStd::string& example,
     const AZStd::function& functor)
     : CCommand(module, name, description, example)
     , m_functor(functor)
@@ -568,8 +568,8 @@ QString CCommand3::Execute(const CCommand::CArgs& args)
 //////////////////////////////////////////////////////////////////////////
 
 template 
-CCommand3wRet::CCommand3wRet(const string& module, const string& name,
-    const string& description, const string& example,
+CCommand3wRet::CCommand3wRet(const AZStd::string& module, const AZStd::string& name,
+    const AZStd::string& description, const AZStd::string& example,
     const AZStd::function& functor)
     : CCommand(module, name, description, example)
     , m_functor(functor)
@@ -610,8 +610,8 @@ QString CCommand3wRet::Execute(const CCommand::CArgs& args)
 //////////////////////////////////////////////////////////////////////////
 
 template 
-CCommand4::CCommand4(const string& module, const string& name,
-    const string& description, const string& example,
+CCommand4::CCommand4(const AZStd::string& module, const AZStd::string& name,
+    const AZStd::string& description, const AZStd::string& example,
     const AZStd::function& functor)
     : CCommand(module, name, description, example)
     , m_functor(functor)
@@ -654,8 +654,8 @@ QString CCommand4::Execute(const CCommand::CArgs& args)
 //////////////////////////////////////////////////////////////////////////
 
 template 
-CCommand4wRet::CCommand4wRet(const string& module, const string& name,
-    const string& description, const string& example,
+CCommand4wRet::CCommand4wRet(const AZStd::string& module, const AZStd::string& name,
+    const AZStd::string& description, const AZStd::string& example,
     const AZStd::function& functor)
     : CCommand(module, name, description, example)
     , m_functor(functor)
@@ -699,8 +699,8 @@ QString CCommand4wRet::Execute(const CCommand::CArgs& args)
 //////////////////////////////////////////////////////////////////////////
 
 template 
-CCommand5::CCommand5(const string& module, const string& name,
-    const string& description, const string& example,
+CCommand5::CCommand5(const AZStd::string& module, const AZStd::string& name,
+    const AZStd::string& description, const AZStd::string& example,
     const AZStd::function& functor)
     : CCommand(module, name, description, example)
     , m_functor(functor)
@@ -745,8 +745,8 @@ QString CCommand5::Execute(const CCommand::CArgs& args)
 //////////////////////////////////////////////////////////////////////////
 
 template 
-CCommand6::CCommand6(const string& module, const string& name,
-    const string& description, const string& example,
+CCommand6::CCommand6(const AZStd::string& module, const AZStd::string& name,
+    const AZStd::string& description, const AZStd::string& example,
     const AZStd::function& functor)
     : CCommand(module, name, description, example)
     , m_functor(functor)
diff --git a/Code/Editor/Plugins/EditorAssetImporter/AssetImporterPlugin.h b/Code/Editor/Plugins/EditorAssetImporter/AssetImporterPlugin.h
index c5b6694af4..8bdfb48774 100644
--- a/Code/Editor/Plugins/EditorAssetImporter/AssetImporterPlugin.h
+++ b/Code/Editor/Plugins/EditorAssetImporter/AssetImporterPlugin.h
@@ -41,7 +41,7 @@ public:
         return m_editor;
     }
 
-    const string& GetToolName() const
+    const AZStd::string& GetToolName() const
     {
         return m_toolName;
     }
diff --git a/Code/Editor/Util/EditorUtils.h b/Code/Editor/Util/EditorUtils.h
index fb767c98b3..1eb73532ef 100644
--- a/Code/Editor/Util/EditorUtils.h
+++ b/Code/Editor/Util/EditorUtils.h
@@ -18,6 +18,7 @@
 #include 
 #include "Util/FileUtil.h"
 #include 
+#include 
 
 //! Typedef for quaternion.
 //typedef CryQuat Quat;
diff --git a/Code/Editor/Util/FileUtil.cpp b/Code/Editor/Util/FileUtil.cpp
index 9e4f688f69..d57d690154 100644
--- a/Code/Editor/Util/FileUtil.cpp
+++ b/Code/Editor/Util/FileUtil.cpp
@@ -1330,7 +1330,7 @@ IFileUtil::ECopyTreeResult CFileUtil::CopyTree(const QString& strSourceDirectory
         const QString fileName = QFileInfo(filePath).fileName();
 
         bool ignored = false;
-        for (const string& ignoredFile : ignoredPatterns)
+        for (const AZStd::string& ignoredFile : ignoredPatterns)
         {
             if (StringHelpers::CompareIgnoreCase(fileName.toStdString().c_str(), ignoredFile.c_str()) == 0)
             {
diff --git a/Code/Editor/Util/IXmlHistoryManager.h b/Code/Editor/Util/IXmlHistoryManager.h
index 78d849df7d..e133d073bc 100644
--- a/Code/Editor/Util/IXmlHistoryManager.h
+++ b/Code/Editor/Util/IXmlHistoryManager.h
@@ -62,7 +62,7 @@ struct IXmlHistoryManager
     // History
     virtual void ClearHistory(bool flagAsSaved = false) = 0;
     virtual int GetVersionCount() const = 0;
-    virtual const string& GetVersionDesc(int number) const = 0;
+    virtual const AZStd::string& GetVersionDesc(int number) const = 0;
     virtual int GetCurrentVersionNumber() const = 0;
 
     // Views
diff --git a/Code/Editor/Util/StringHelpers.cpp b/Code/Editor/Util/StringHelpers.cpp
index a6bf622ad0..bf607e475e 100644
--- a/Code/Editor/Util/StringHelpers.cpp
+++ b/Code/Editor/Util/StringHelpers.cpp
@@ -84,7 +84,7 @@ static inline int Vsnprintf_s(wchar_t* str, size_t sizeInBytes, [[maybe_unused]]
 }
 
 
-int StringHelpers::Compare(const string& str0, const string& str1)
+int StringHelpers::Compare(const AZStd::string& str0, const AZStd::string& str1)
 {
     const size_t minLength = Util::getMin(str0.length(), str1.length());
     const int result = std::memcmp(str0.c_str(), str1.c_str(), minLength);
@@ -119,7 +119,7 @@ int StringHelpers::Compare(const wstring& str0, const wstring& str1)
 }
 
 
-int StringHelpers::CompareIgnoreCase(const string& str0, const string& str1)
+int StringHelpers::CompareIgnoreCase(const AZStd::string& str0, const AZStd::string& str1)
 {
     const size_t minLength = Util::getMin(str0.length(), str1.length());
     const int result = azmemicmp(str0.c_str(), str1.c_str(), minLength);
@@ -154,7 +154,7 @@ int StringHelpers::CompareIgnoreCase(const wstring& str0, const wstring& str1)
 }
 
 
-bool StringHelpers::Equals(const string& str0, const string& str1)
+bool StringHelpers::Equals(const AZStd::string& str0, const AZStd::string& str1)
 {
     if (str0.length() != str1.length())
     {
@@ -173,7 +173,7 @@ bool StringHelpers::Equals(const wstring& str0, const wstring& str1)
 }
 
 
-bool StringHelpers::EqualsIgnoreCase(const string& str0, const string& str1)
+bool StringHelpers::EqualsIgnoreCase(const AZStd::string& str0, const AZStd::string& str1)
 {
     if (str0.length() != str1.length())
     {
@@ -200,7 +200,7 @@ bool StringHelpers::EqualsIgnoreCase(const wstring& str0, const wstring& str1)
 }
 
 
-bool StringHelpers::StartsWith(const string& str, const string& pattern)
+bool StringHelpers::StartsWith(const AZStd::string& str, const AZStd::string& pattern)
 {
     if (str.length() < pattern.length())
     {
@@ -219,7 +219,7 @@ bool StringHelpers::StartsWith(const wstring& str, const wstring& pattern)
 }
 
 
-bool StringHelpers::StartsWithIgnoreCase(const string& str, const string& pattern)
+bool StringHelpers::StartsWithIgnoreCase(const AZStd::string& str, const AZStd::string& pattern)
 {
     if (str.length() < pattern.length())
     {
@@ -246,7 +246,7 @@ bool StringHelpers::StartsWithIgnoreCase(const wstring& str, const wstring& patt
 }
 
 
-bool StringHelpers::EndsWith(const string& str, const string& pattern)
+bool StringHelpers::EndsWith(const AZStd::string& str, const AZStd::string& pattern)
 {
     if (str.length() < pattern.length())
     {
@@ -265,7 +265,7 @@ bool StringHelpers::EndsWith(const wstring& str, const wstring& pattern)
 }
 
 
-bool StringHelpers::EndsWithIgnoreCase(const string& str, const string& pattern)
+bool StringHelpers::EndsWithIgnoreCase(const AZStd::string& str, const AZStd::string& pattern)
 {
     if (str.length() < pattern.length())
     {
@@ -292,7 +292,7 @@ bool StringHelpers::EndsWithIgnoreCase(const wstring& str, const wstring& patter
 }
 
 
-bool StringHelpers::Contains(const string& str, const string& pattern)
+bool StringHelpers::Contains(const AZStd::string& str, const AZStd::string& pattern)
 {
     const size_t patternLength = pattern.length();
     if (str.length() < patternLength)
@@ -329,7 +329,7 @@ bool StringHelpers::Contains(const wstring& str, const wstring& pattern)
 }
 
 
-bool StringHelpers::ContainsIgnoreCase(const string& str, const string& pattern)
+bool StringHelpers::ContainsIgnoreCase(const AZStd::string& str, const AZStd::string& pattern)
 {
     const size_t patternLength = pattern.length();
     if (str.length() < patternLength)
@@ -380,7 +380,7 @@ bool StringHelpers::ContainsIgnoreCase(const wstring& str, const wstring& patter
     return false;
 }
 
-string StringHelpers::TrimLeft(const string& s)
+string StringHelpers::TrimLeft(const AZStd::string& s)
 {
     const size_t first = s.find_first_not_of(" \r\t");
     return (first == s.npos) ? string() : s.substr(first);
@@ -393,7 +393,7 @@ wstring StringHelpers::TrimLeft(const wstring& s)
 }
 
 
-string StringHelpers::TrimRight(const string& s)
+string StringHelpers::TrimRight(const AZStd::string& s)
 {
     const size_t last = s.find_last_not_of(" \r\t");
     return (last == s.npos) ? s : s.substr(0, last + 1);
@@ -406,7 +406,7 @@ wstring StringHelpers::TrimRight(const wstring& s)
 }
 
 
-string StringHelpers::Trim(const string& s)
+string StringHelpers::Trim(const AZStd::string& s)
 {
     return TrimLeft(TrimRight(s));
 }
@@ -447,7 +447,7 @@ static inline TS RemoveDuplicateSpaces_Tpl(const TS& s)
     return res;
 }
 
-string StringHelpers::RemoveDuplicateSpaces(const string& s)
+string StringHelpers::RemoveDuplicateSpaces(const AZStd::string& s)
 {
     return RemoveDuplicateSpaces_Tpl(s);
 }
@@ -470,7 +470,7 @@ static inline TS MakeLowerCase_Tpl(const TS& s)
     return copy;
 }
 
-string StringHelpers::MakeLowerCase(const string& s)
+string StringHelpers::MakeLowerCase(const AZStd::string& s)
 {
     return MakeLowerCase_Tpl(s);
 }
@@ -493,7 +493,7 @@ static inline TS MakeUpperCase_Tpl(const TS& s)
     return copy;
 }
 
-string StringHelpers::MakeUpperCase(const string& s)
+string StringHelpers::MakeUpperCase(const AZStd::string& s)
 {
     return MakeUpperCase_Tpl(s);
 }
@@ -517,7 +517,7 @@ static inline TS Replace_Tpl(const TS& s, const typename TS::value_type oldChar,
     return copy;
 }
 
-string StringHelpers::Replace(const string& s, char oldChar, char newChar)
+string StringHelpers::Replace(const AZStd::string& s, char oldChar, char newChar)
 {
     return Replace_Tpl(s, oldChar, newChar);
 }
@@ -528,12 +528,12 @@ wstring StringHelpers::Replace(const wstring& s, wchar_t oldChar, wchar_t newCha
 }
 
 
-void StringHelpers::ConvertStringByRef(string& out, const string& in)
+void StringHelpers::ConvertStringByRef(string& out, const AZStd::string& in)
 {
     out = in;
 }
 
-void StringHelpers::ConvertStringByRef(wstring& out, const string& in)
+void StringHelpers::ConvertStringByRef(wstring& out, const AZStd::string& in)
 {
     Unicode::Convert(out, in);
 }
@@ -630,7 +630,7 @@ static inline void SplitByAnyOf_Tpl(const TS& str, const TS& separators, bool bR
 
 
 
-void StringHelpers::Split(const string& str, const string& separator, bool bReturnEmptyPartsToo, std::vector& outParts)
+void StringHelpers::Split(const AZStd::string& str, const AZStd::string& separator, bool bReturnEmptyPartsToo, std::vector& outParts)
 {
     Split_Tpl(str, separator, bReturnEmptyPartsToo, outParts);
 }
@@ -641,7 +641,7 @@ void StringHelpers::Split(const wstring& str, const wstring& separator, bool bRe
 }
 
 
-void StringHelpers::SplitByAnyOf(const string& str, const string& separators, bool bReturnEmptyPartsToo, std::vector& outParts)
+void StringHelpers::SplitByAnyOf(const AZStd::string& str, const AZStd::string& separators, bool bReturnEmptyPartsToo, std::vector& outParts)
 {
     SplitByAnyOf_Tpl(str, separators, bReturnEmptyPartsToo, outParts);
 }
diff --git a/Code/Editor/Util/StringHelpers.h b/Code/Editor/Util/StringHelpers.h
index da4aa9c9cc..ec5515fbc9 100644
--- a/Code/Editor/Util/StringHelpers.h
+++ b/Code/Editor/Util/StringHelpers.h
@@ -15,83 +15,83 @@ namespace StringHelpers
 {
     // compares two strings to see if they are the same or different, case sensitive
     // returns 0 if the strings are the same, a -1 if the first string is bigger, or a 1 if the second string is bigger
-    int Compare(const string& str0, const string& str1);
+    int Compare(const AZStd::string& str0, const AZStd::string& str1);
     int Compare(const wstring& str0, const wstring& str1);
 
     // compares two strings to see if they are the same or different, case is ignored
     // returns 0 if the strings are the same, a -1 if the first string is bigger, or a 1 if the second string is bigger
-    int CompareIgnoreCase(const string& str0, const string& str1);
+    int CompareIgnoreCase(const AZStd::string& str0, const AZStd::string& str1);
     int CompareIgnoreCase(const wstring& str0, const wstring& str1);
 
     // compares two strings to see if they are the same, case senstive
     // returns true if they are the same or false if they are different
-    bool Equals(const string& str0, const string& str1);
+    bool Equals(const AZStd::string& str0, const AZStd::string& str1);
     bool Equals(const wstring& str0, const wstring& str1);
 
     // compares two strings to see if they are the same, case is ignored
     // returns true if they are the same or false if they are different
-    bool EqualsIgnoreCase(const string& str0, const string& str1);
+    bool EqualsIgnoreCase(const AZStd::string& str0, const AZStd::string& str1);
     bool EqualsIgnoreCase(const wstring& str0, const wstring& str1);
 
     // checks to see if a string starts with a specified string, case sensitive
     // returns true if the string does start with a specified string or false if it does not
-    bool StartsWith(const string& str, const string& pattern);
+    bool StartsWith(const AZStd::string& str, const AZStd::string& pattern);
     bool StartsWith(const wstring& str, const wstring& pattern);
 
     // checks to see if a string starts with a specified string, case is ignored
     // returns true if the string does start with a specified string or false if it does not
-    bool StartsWithIgnoreCase(const string& str, const string& pattern);
+    bool StartsWithIgnoreCase(const AZStd::string& str, const AZStd::string& pattern);
     bool StartsWithIgnoreCase(const wstring& str, const wstring& pattern);
 
     // checks to see if a string ends with a specified string, case sensitive
     // returns true if the string does end with a specified string or false if it does not
-    bool EndsWith(const string& str, const string& pattern);
+    bool EndsWith(const AZStd::string& str, const AZStd::string& pattern);
     bool EndsWith(const wstring& str, const wstring& pattern);
 
     // checks to see if a string ends with a specified string, case is ignored
     // returns true if the string does end with a specified string or false if it does not
-    bool EndsWithIgnoreCase(const string& str, const string& pattern);
+    bool EndsWithIgnoreCase(const AZStd::string& str, const AZStd::string& pattern);
     bool EndsWithIgnoreCase(const wstring& str, const wstring& pattern);
 
     // checks to see if a string contains a specified string, case sensitive
     // returns true if the string does contain the specified string or false if it does not
-    bool Contains(const string& str, const string& pattern);
+    bool Contains(const AZStd::string& str, const AZStd::string& pattern);
     bool Contains(const wstring& str, const wstring& pattern);
 
     // checks to see if a string contains a specified string, case is ignored
     // returns true if the string does contain the specified string or false if it does not
-    bool ContainsIgnoreCase(const string& str, const string& pattern);
+    bool ContainsIgnoreCase(const AZStd::string& str, const AZStd::string& pattern);
     bool ContainsIgnoreCase(const wstring& str, const wstring& pattern);
 
-    string TrimLeft(const string& s);
+    string TrimLeft(const AZStd::string& s);
     wstring TrimLeft(const wstring& s);
 
-    string TrimRight(const string& s);
+    string TrimRight(const AZStd::string& s);
     wstring TrimRight(const wstring& s);
 
-    string Trim(const string& s);
+    string Trim(const AZStd::string& s);
     wstring Trim(const wstring& s);
 
-    string RemoveDuplicateSpaces(const string& s);
+    string RemoveDuplicateSpaces(const AZStd::string& s);
     wstring RemoveDuplicateSpaces(const wstring& s);
 
     // converts a string with upper case characters to be all lower case
     // returns the string in all lower case
-    string MakeLowerCase(const string& s);
+    string MakeLowerCase(const AZStd::string& s);
     wstring MakeLowerCase(const wstring& s);
 
     // converts a string with lower case characters to be all upper case
     // returns the string in all upper case
-    string MakeUpperCase(const string& s);
+    string MakeUpperCase(const AZStd::string& s);
     wstring MakeUpperCase(const wstring& s);
 
     // replace a specified character in a string with a specified replacement character
     // returns string with specified character replaced
-    string Replace(const string& s, char oldChar, char newChar);
+    string Replace(const AZStd::string& s, char oldChar, char newChar);
     wstring Replace(const wstring& s, wchar_t oldChar, wchar_t newChar);
 
-    void ConvertStringByRef(string& out, const string& in);
-    void ConvertStringByRef(wstring& out, const string& in);
+    void ConvertStringByRef(string& out, const AZStd::string& in);
+    void ConvertStringByRef(wstring& out, const AZStd::string& in);
     void ConvertStringByRef(string& out, const wstring& in);
     void ConvertStringByRef(wstring& out, const wstring& in);
 
@@ -103,10 +103,10 @@ namespace StringHelpers
         return out;
     }
     
-    void Split(const string& str, const string& separator, bool bReturnEmptyPartsToo, std::vector& outParts);
+    void Split(const AZStd::string& str, const AZStd::string& separator, bool bReturnEmptyPartsToo, std::vector& outParts);
     void Split(const wstring& str, const wstring& separator, bool bReturnEmptyPartsToo, std::vector& outParts);
 
-    void SplitByAnyOf(const string& str, const string& separators, bool bReturnEmptyPartsToo, std::vector& outParts);
+    void SplitByAnyOf(const AZStd::string& str, const AZStd::string& separators, bool bReturnEmptyPartsToo, std::vector& outParts);
     void SplitByAnyOf(const wstring& str, const wstring& separators, bool bReturnEmptyPartsToo, std::vector& outParts);
 
     string FormatVA(const char* const format, va_list parg);
diff --git a/Code/Editor/Util/XmlHistoryManager.cpp b/Code/Editor/Util/XmlHistoryManager.cpp
index 3aea041d29..5a1bc237bb 100644
--- a/Code/Editor/Util/XmlHistoryManager.cpp
+++ b/Code/Editor/Util/XmlHistoryManager.cpp
@@ -419,7 +419,7 @@ void CXmlHistoryManager::ClearHistory(bool flagAsSaved)
 }
 
 /////////////////////////////////////////////////////////////////////////////
-const string& CXmlHistoryManager::GetVersionDesc(int number) const
+const AZStd::string& CXmlHistoryManager::GetVersionDesc(int number) const
 {
     THistoryInfoMap::const_iterator it = m_HistoryInfoMap.find(number);
     if (it != m_HistoryInfoMap.end())
diff --git a/Code/Editor/Util/XmlHistoryManager.h b/Code/Editor/Util/XmlHistoryManager.h
index d894bc7f00..12699536e5 100644
--- a/Code/Editor/Util/XmlHistoryManager.h
+++ b/Code/Editor/Util/XmlHistoryManager.h
@@ -103,7 +103,7 @@ public:
     // History
     void ClearHistory(bool flagAsSaved = false);
     int GetVersionCount() const { return m_LatestVersion; }
-    const string& GetVersionDesc(int number) const;
+    const AZStd::string& GetVersionDesc(int number) const;
     int GetCurrentVersionNumber() const { return m_CurrentVersion; }
 
     // Views
diff --git a/Code/Framework/GridMate/GridMate/Carrier/Carrier.cpp b/Code/Framework/GridMate/GridMate/Carrier/Carrier.cpp
index 3c3c1183e4..23e967c3fa 100644
--- a/Code/Framework/GridMate/GridMate/Carrier/Carrier.cpp
+++ b/Code/Framework/GridMate/GridMate/Carrier/Carrier.cpp
@@ -417,7 +417,7 @@ namespace GridMate
     {
         GM_CLASS_ALLOCATOR(Connection); // make a pool and use it...
 
-        Connection(CarrierThread* threadOwner, const string& address);
+        Connection(CarrierThread* threadOwner, const AZStd::string& address);
         ~Connection();
 
         CarrierThread*              m_threadOwner;                                  ///< Pointer to the carrier thread that operates with this connection.
@@ -999,7 +999,7 @@ namespace GridMate
         /// Connect with host and port. This is ASync operation, the connection is active after OnConnectionEstablished is called.
         ConnectionID    Connect(const char* hostAddress, unsigned int port) override;
         /// Connect with internal address format. This is ASync operation, the connection is active after OnConnectionEstablished is called.
-        ConnectionID    Connect(const string& address) override;
+        ConnectionID    Connect(const AZStd::string& address) override;
         /// Request a disconnect procedure. This is ASync operation, the connection is closed after OnDisconnect is called.
         void            Disconnect(ConnectionID id) override;
 
@@ -1118,7 +1118,7 @@ using namespace GridMate;
 // Connection
 //////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////
-Connection::Connection(CarrierThread* threadOwner, const string& address)
+Connection::Connection(CarrierThread* threadOwner, const AZStd::string& address)
     : m_threadOwner(threadOwner)
     , m_threadConn(NULL)
     , m_fullAddress(address)
@@ -3740,7 +3740,7 @@ CarrierImpl::Connect(const char* hostAddress, unsigned int port)
 // [1/12/2011]
 //=========================================================================
 ConnectionID
-CarrierImpl::Connect(const string& address)
+CarrierImpl::Connect(const AZStd::string& address)
 {
     // check if we don't have it in the list.
     for(auto& i : m_connections)
diff --git a/Code/Framework/GridMate/GridMate/Carrier/Carrier.h b/Code/Framework/GridMate/GridMate/Carrier/Carrier.h
index 5bfa621af1..2968582c0d 100644
--- a/Code/Framework/GridMate/GridMate/Carrier/Carrier.h
+++ b/Code/Framework/GridMate/GridMate/Carrier/Carrier.h
@@ -88,7 +88,7 @@ namespace GridMate
         /// Connect with host and port. This is ASync operation, the connection is active after OnConnectionEstablished is called.
         virtual ConnectionID    Connect(const char* hostAddress, unsigned int port) = 0;
         /// Connect with internal address format. This is ASync operation, the connection is active after OnConnectionEstablished is called.
-        virtual ConnectionID    Connect(const string& address) = 0;
+        virtual ConnectionID    Connect(const AZStd::string& address) = 0;
         /// Request a disconnect procedure. This is ASync operation, the connection is closed after OnDisconnect is called.
         virtual void            Disconnect(ConnectionID id) = 0;
 
diff --git a/Code/Framework/GridMate/GridMate/Carrier/DefaultHandshake.cpp b/Code/Framework/GridMate/GridMate/Carrier/DefaultHandshake.cpp
index bc657becbc..58436bb757 100644
--- a/Code/Framework/GridMate/GridMate/Carrier/DefaultHandshake.cpp
+++ b/Code/Framework/GridMate/GridMate/Carrier/DefaultHandshake.cpp
@@ -98,7 +98,7 @@ DefaultHandshake::OnConfirmAck(ConnectionID id, ReadBuffer& rb)
 // [11/5/2010]
 //=========================================================================
 bool
-DefaultHandshake::OnNewConnection(const string& address)
+DefaultHandshake::OnNewConnection(const AZStd::string& address)
 {
     (void)address;
     return true; /// We don't have a ban list yet
diff --git a/Code/Framework/GridMate/GridMate/Carrier/DefaultHandshake.h b/Code/Framework/GridMate/GridMate/Carrier/DefaultHandshake.h
index 0b9240dfa3..8f456e4649 100644
--- a/Code/Framework/GridMate/GridMate/Carrier/DefaultHandshake.h
+++ b/Code/Framework/GridMate/GridMate/Carrier/DefaultHandshake.h
@@ -47,7 +47,7 @@ namespace GridMate
         */
         virtual bool                OnConfirmAck(ConnectionID id, ReadBuffer& rb);
         /// Return true if you want to reject early reject a connection.
-        virtual bool                OnNewConnection(const string& address);
+        virtual bool                OnNewConnection(const AZStd::string& address);
         /// Called when we close a connection.
         virtual void                OnDisconnect(ConnectionID id);
         /// Return timeout in milliseconds of the handshake procedure.
diff --git a/Code/Framework/GridMate/GridMate/Carrier/Driver.h b/Code/Framework/GridMate/GridMate/Carrier/Driver.h
index 84e43b5acf..2c806be5e0 100644
--- a/Code/Framework/GridMate/GridMate/Carrier/Driver.h
+++ b/Code/Framework/GridMate/GridMate/Carrier/Driver.h
@@ -140,7 +140,7 @@ namespace GridMate
         /// @{ Address conversion functionality. They MUST implemented thread safe. Generally this is not a problem since they just part local data.
         ///  Create address from ip and port. If ip == NULL we will assign a broadcast address.
         virtual string          IPPortToAddress(const char* ip, unsigned int port) const = 0;
-        virtual bool            AddressToIPPort(const string& address, string& ip, unsigned int& port) const = 0;
+        virtual bool            AddressToIPPort(const AZStd::string& address, AZStd::string& ip, unsigned int& port) const = 0;
         /// @}
 
         /**
@@ -150,7 +150,7 @@ namespace GridMate
          * \note Driver address allocates internal resources, use it only when you intend to communicate. Otherwise operate with
          * the string address.
          */
-        virtual AZStd::intrusive_ptr CreateDriverAddress(const string& address) = 0;
+        virtual AZStd::intrusive_ptr CreateDriverAddress(const AZStd::string& address) = 0;
 
         /**
          * Returns true if the driver can accept new data (ex, has buffer space).
diff --git a/Code/Framework/GridMate/GridMate/Carrier/Handshake.h b/Code/Framework/GridMate/GridMate/Carrier/Handshake.h
index 5d06f2f1b8..ffd332b65c 100644
--- a/Code/Framework/GridMate/GridMate/Carrier/Handshake.h
+++ b/Code/Framework/GridMate/GridMate/Carrier/Handshake.h
@@ -53,7 +53,7 @@ namespace GridMate
          */
         virtual bool                OnConfirmAck(ConnectionID id, ReadBuffer& rb) = 0;
         /// Return true if you want to reject early reject a connection.
-        virtual bool                OnNewConnection(const string& address) = 0;
+        virtual bool                OnNewConnection(const AZStd::string& address) = 0;
         /// Called when we close a connection.
         virtual void                OnDisconnect(ConnectionID id) = 0;
         /// Return timeout in milliseconds of the handshake procedure.
diff --git a/Code/Framework/GridMate/GridMate/Carrier/SocketDriver.cpp b/Code/Framework/GridMate/GridMate/Carrier/SocketDriver.cpp
index b75de6f383..fc3062062c 100644
--- a/Code/Framework/GridMate/GridMate/Carrier/SocketDriver.cpp
+++ b/Code/Framework/GridMate/GridMate/Carrier/SocketDriver.cpp
@@ -498,7 +498,7 @@ namespace GridMate
         }
     }
 
-    SocketDriverAddress::SocketDriverAddress(Driver* driver, const string& ip, unsigned int port)
+    SocketDriverAddress::SocketDriverAddress(Driver* driver, const AZStd::string& ip, unsigned int port)
         : DriverAddress(driver)
     {
         AZ_Assert(!ip.empty(), "Invalid address string!");
@@ -1156,7 +1156,7 @@ namespace GridMate
     // [3/4/2013]
     //=========================================================================
     bool
-    SocketDriverCommon::AddressStringToIPPort(const string& address, string& ip, unsigned int& port)
+    SocketDriverCommon::AddressStringToIPPort(const AZStd::string& address, AZStd::string& ip, unsigned int& port)
     {
         AZStd::size_t pos = address.find('|');
         AZ_Assert(pos != string::npos, "Invalid driver address!");
@@ -1176,7 +1176,7 @@ namespace GridMate
     // [7/11/2013]
     //=========================================================================
     Driver::BSDSocketFamilyType
-    SocketDriverCommon::AddressFamilyType(const string& ip)
+    SocketDriverCommon::AddressFamilyType(const AZStd::string& ip)
     {
         // TODO: We can/should use inet_ntop() to detect the family type
         AZStd::size_t pos = ip.find(".");
@@ -1198,13 +1198,13 @@ namespace GridMate
     //////////////////////////////////////////////////////////////////////////
     //////////////////////////////////////////////////////////////////////////
     //=========================================================================
-    // CreateDriverAddress(const string&)
+    // CreateDriverAddress(const AZStd::string&)
     // [1/12/2011]
     //=========================================================================
     AZStd::intrusive_ptr
-    SocketDriver::CreateDriverAddress(const string& address)
+    SocketDriver::CreateDriverAddress(const AZStd::string& address)
     {
-        string ip;
+        AZStd::string ip;
         unsigned int port;
         if (!AddressToIPPort(address, ip, port))
         {
@@ -1243,7 +1243,7 @@ namespace GridMate
     namespace Utils
     {
         // \note function moved here to use addinfo when IPV6 is not in use, consider moving those definitions to a header file
-        bool GetIpByHostName(int familyType, const char* hostName, string& ip)
+        bool GetIpByHostName(int familyType, const char* hostName, AZStd::string& ip)
         {
             static const size_t kMaxLen = 64; // max length of ipv6 ip is 45 chars, so all ips should be able to fit in this buf
             char ipBuf[kMaxLen];
diff --git a/Code/Framework/GridMate/GridMate/Carrier/SocketDriver.h b/Code/Framework/GridMate/GridMate/Carrier/SocketDriver.h
index bda135f532..7555c92639 100644
--- a/Code/Framework/GridMate/GridMate/Carrier/SocketDriver.h
+++ b/Code/Framework/GridMate/GridMate/Carrier/SocketDriver.h
@@ -83,7 +83,7 @@ namespace GridMate
 
         SocketDriverAddress(Driver* driver);
         SocketDriverAddress(Driver* driver, const sockaddr* addr);
-        SocketDriverAddress(Driver* driver, const string& ip, unsigned int port);
+        SocketDriverAddress(Driver* driver, const AZStd::string& ip, unsigned int port);
 
         bool operator==(const SocketDriverAddress& rhs) const;
         bool operator!=(const SocketDriverAddress& rhs) const;
@@ -164,17 +164,17 @@ namespace GridMate
         /// @{ Address conversion functionality. They MUST implemented thread safe. Generally this is not a problem since they just part local data.
         ///  Create address from ip and port. If ip == NULL we will assign a broadcast address.
         virtual string  IPPortToAddress(const char* ip, unsigned int port) const                        { return IPPortToAddressString(ip, port); }
-        virtual bool    AddressToIPPort(const string& address, string& ip, unsigned int& port) const    { return AddressStringToIPPort(address, ip, port); }
+        virtual bool    AddressToIPPort(const AZStd::string& address, AZStd::string& ip, unsigned int& port) const    { return AddressStringToIPPort(address, ip, port); }
         /// Create address for the socket driver from IP and port
         static string   IPPortToAddressString(const char* ip, unsigned int port);
         /// Decompose an address to IP and port
-        static bool     AddressStringToIPPort(const string& address, string& ip, unsigned int& port);
+        static bool     AddressStringToIPPort(const AZStd::string& address, AZStd::string& ip, unsigned int& port);
         /// Return the family type of the address (AF_INET,AF_INET6 AF_UNSPEC)
-        static BSDSocketFamilyType  AddressFamilyType(const string& ip);
+        static BSDSocketFamilyType  AddressFamilyType(const AZStd::string& ip);
         static BSDSocketFamilyType  AddressFamilyType(const char* ip)           { return AddressFamilyType(string(ip)); }
         /// @}
 
-        virtual AZStd::intrusive_ptr CreateDriverAddress(const string& address) = 0;
+        virtual AZStd::intrusive_ptr CreateDriverAddress(const AZStd::string& address) = 0;
         /// Additional CreateDriverAddress function should be implemented.
         virtual AZStd::intrusive_ptr CreateDriverAddress(const sockaddr* sockAddr) = 0;
 
@@ -352,7 +352,7 @@ namespace GridMate
         * \note Driver address allocates internal resources, use it only when you intend to communicate. Otherwise operate with
         * the string address.
         */
-        virtual AZStd::intrusive_ptr CreateDriverAddress(const string& address);
+        virtual AZStd::intrusive_ptr CreateDriverAddress(const AZStd::string& address);
         virtual AZStd::intrusive_ptr CreateDriverAddress(const sockaddr* addr);
         /// Called only from the DriverAddress when the use count becomes 0
         virtual void    DestroyDriverAddress(DriverAddress* address);
@@ -364,7 +364,7 @@ namespace GridMate
     namespace Utils
     {
         ///< Retrieves ip address corresponding to a host name. Blocks thread until dns resolving is happened.
-        bool GetIpByHostName(int familyType, const char* hostName, string& ip);
+        bool GetIpByHostName(int familyType, const char* hostName, AZStd::string& ip);
     }
 
     /**
diff --git a/Code/Framework/GridMate/GridMate/Drillers/SessionDriller.cpp b/Code/Framework/GridMate/GridMate/Drillers/SessionDriller.cpp
index 5a34b70e74..a7130218f8 100644
--- a/Code/Framework/GridMate/GridMate/Drillers/SessionDriller.cpp
+++ b/Code/Framework/GridMate/GridMate/Drillers/SessionDriller.cpp
@@ -224,7 +224,7 @@ namespace GridMate
         // [4/15/2011]
         //=========================================================================
         void
-        SessionDriller::OnSessionError(GridSession* session, const string& errorMsg)
+        SessionDriller::OnSessionError(GridSession* session, const AZStd::string& errorMsg)
         {
             m_output->BeginTag(m_drillerTag);
             m_output->BeginTag(AZ_CRC("SessionError", 0xc689cc40));
diff --git a/Code/Framework/GridMate/GridMate/Drillers/SessionDriller.h b/Code/Framework/GridMate/GridMate/Drillers/SessionDriller.h
index b89fae3d73..59f178976f 100644
--- a/Code/Framework/GridMate/GridMate/Drillers/SessionDriller.h
+++ b/Code/Framework/GridMate/GridMate/Drillers/SessionDriller.h
@@ -62,7 +62,7 @@ namespace GridMate
             /// Callback that notifies the title when a session will be left. session pointer is NOT valid after the callback returns.
             virtual void OnSessionDelete(GridSession* session);
             /// Called when a session error occurs.
-            virtual void OnSessionError(GridSession* session, const string& errorMsg);
+            virtual void OnSessionError(GridSession* session, const AZStd::string& errorMsg);
             /// Called when the actual game(match) starts
             virtual void OnSessionStart(GridSession* session);
             /// Called when the actual game(match) ends
diff --git a/Code/Framework/GridMate/GridMate/Session/LANSession.cpp b/Code/Framework/GridMate/GridMate/Session/LANSession.cpp
index fca43c2709..0127d8fa23 100644
--- a/Code/Framework/GridMate/GridMate/Session/LANSession.cpp
+++ b/Code/Framework/GridMate/GridMate/Session/LANSession.cpp
@@ -37,7 +37,7 @@ namespace GridMate
     {
         friend class LANMemberIDMarshaler;
 
-        static LANMemberID Create(MemberIDCompact id, const string& address)
+        static LANMemberID Create(MemberIDCompact id, const AZStd::string& address)
         {
             LANMemberID mid;
             mid.m_id = id;
@@ -45,7 +45,7 @@ namespace GridMate
             return mid;
         }
 
-        void SetAddress(const string& address)
+        void SetAddress(const AZStd::string& address)
         {
             m_address = address;
         }
@@ -120,14 +120,14 @@ namespace GridMate
         /// Creates the local player.
         GridMember* CreateLocalMember(bool isHost, bool isInvited, RemotePeerMode peerMode);
         /// Creates remote player, when he wants to join.
-        GridMember* CreateRemoteMember(const string& address, ReadBuffer& data, RemotePeerMode peerMode, ConnectionID connId = InvalidConnectionID) override;
+        GridMember* CreateRemoteMember(const AZStd::string& address, ReadBuffer& data, RemotePeerMode peerMode, ConnectionID connId = InvalidConnectionID) override;
 
         /// Called when we receive the session replica. We create one and return the pointer.
         LANSessionReplica*  OnSessionReplicaArrived();
 
         /// Called when session parameters have changed.
         void OnSessionParamChanged(const GridSessionParam& param) override { (void)param; }
-        void OnSessionParamRemoved(const string& paramId) override { (void)paramId; }
+        void OnSessionParamRemoved(const AZStd::string& paramId) override { (void)paramId; }
 
     private:
         explicit LANSession(LANSessionService* service);
@@ -762,7 +762,7 @@ LANSession::CreateLocalMember(bool isHost, bool isInvited, RemotePeerMode peerMo
 // [2/2/2011]
 //==========================================================================
 GridMember*
-LANSession::CreateRemoteMember(const string& address, ReadBuffer& data, RemotePeerMode peerMode, ConnectionID connId)
+LANSession::CreateRemoteMember(const AZStd::string& address, ReadBuffer& data, RemotePeerMode peerMode, ConnectionID connId)
 {
     MemberIDCompact id;
     data.Read(id);
@@ -803,7 +803,7 @@ LANSession::OnStateCreate(AZ::HSM& sm, const AZ::HSM::Event& e)
     {
         // patch the ID if we use implicit port
         AZ_Assert(m_carrier, "Carrier must be created!");
-        string ip;
+        AZStd::string ip;
         unsigned int port;
         SocketDriverCommon::AddressStringToIPPort(m_myMember->GetId().ToAddress(), ip, port);
         AZ_Assert(port == 0 || port == m_carrier->GetPort(), "Carrier port missmatch! It should either be 0 (and patched here) in the implicit bind or the port number for explicit bind!");
diff --git a/Code/Framework/GridMate/GridMate/Session/LANSessionServiceTypes.h b/Code/Framework/GridMate/GridMate/Session/LANSessionServiceTypes.h
index ee4c0a8659..20ade42a6e 100644
--- a/Code/Framework/GridMate/GridMate/Session/LANSessionServiceTypes.h
+++ b/Code/Framework/GridMate/GridMate/Session/LANSessionServiceTypes.h
@@ -39,9 +39,9 @@ namespace GridMate
         {}
 
         int     m_familyType;                   ///< Socket driver specific, by default 0.
-        string  m_serverAddress;                ///< Address of the server, we empty we create a broadcast address.
+        AZStd::string  m_serverAddress;         ///< Address of the server, we empty we create a broadcast address.
         int     m_serverPort;                   ///< Server port (must be provided).
-        string  m_listenAddress;                ///< Address to bind for listening. By default is empty, which means we are listening to any address.
+        AZStd::string  m_listenAddress;         ///< Address to bind for listening. By default is empty, which means we are listening to any address.
         int     m_listenPort;                   ///< Search listen port, if not set we will use ephimeral port.
         unsigned int m_broadcastFrequencyMs;    ///< Time in MS between search broadcasts.
     };
@@ -52,7 +52,7 @@ namespace GridMate
     struct LANSearchInfo
         : public SearchInfo
     {
-        string m_serverIP; ///< server ID as we see it
+        AZStd::string m_serverIP; ///< server ID as we see it
         AZ::u16 m_serverPort; ///< server port for the session
     };
 }
diff --git a/Code/Framework/GridMate/GridMate/Session/Session.cpp b/Code/Framework/GridMate/GridMate/Session/Session.cpp
index 5746a91c19..8a9bdea273 100644
--- a/Code/Framework/GridMate/GridMate/Session/Session.cpp
+++ b/Code/Framework/GridMate/GridMate/Session/Session.cpp
@@ -92,7 +92,7 @@ namespace GridMate
             */
             virtual bool            OnConfirmAck(ConnectionID id, ReadBuffer& rb)   { (void)id; (void)rb; return true; } // we don't do any further filtering
             /// Return true if you want to reject early reject a connection.
-            virtual bool            OnNewConnection(const string& address);
+            virtual bool            OnNewConnection(const AZStd::string& address);
             /// Called when we close a connection.
             virtual void            OnDisconnect(ConnectionID id);
             /// Return timeout in milliseconds of the handshake procedure.
@@ -684,7 +684,7 @@ GridSession::SetParam(const GridSessionParam& param)
 // RemoveParam
 //=========================================================================
 bool
-GridSession::RemoveParam(const string& paramId)
+GridSession::RemoveParam(const AZStd::string& paramId)
 {
     AZ_Assert(m_state, "Invalid session state replica. Session is not initialized.");
 
@@ -970,7 +970,7 @@ GridSession::AddMember(GridMember* member)
 // IsAddressInMemberList
 //=========================================================================
 bool
-GridSession::IsAddressInMemberList(const string& address)
+GridSession::IsAddressInMemberList(const AZStd::string& address)
 {
     for (AZStd::size_t i = 0; i < m_members.size(); ++i)
     {
@@ -2783,7 +2783,7 @@ bool GridSessionHandshake::OnConfirmRequest(ConnectionID id, ReadBuffer& rb)
 //=========================================================================
 // OnNewConnection
 //=========================================================================
-bool GridSessionHandshake::OnNewConnection(const string& address)
+bool GridSessionHandshake::OnNewConnection(const AZStd::string& address)
 {
     AZStd::lock_guard l(m_dataLock);
 
diff --git a/Code/Framework/GridMate/GridMate/Session/Session.h b/Code/Framework/GridMate/GridMate/Session/Session.h
index 63aa504a49..03556756ba 100644
--- a/Code/Framework/GridMate/GridMate/Session/Session.h
+++ b/Code/Framework/GridMate/GridMate/Session/Session.h
@@ -249,7 +249,7 @@ namespace GridMate
         /// Callback that notifies the title when a session will be left. session pointer is NOT valid after the callback returns.
         virtual void OnSessionDelete(GridSession* session) { (void)session; }
         /// Called when a session error occurs.
-        virtual void OnSessionError(GridSession* session, const string& errorMsg) { (void)session; (void)errorMsg; }
+        virtual void OnSessionError(GridSession* session, const AZStd::string& errorMsg) { (void)session; (void)errorMsg; }
         /// Called when the actual game(match) starts
         virtual void OnSessionStart(GridSession* session) { (void)session; }
         /// Called when the actual game(match) ends
@@ -484,7 +484,7 @@ namespace GridMate
         // Adds/updates a parameter. Returns false if parameter can not be added.
         bool SetParam(const GridSessionParam& param);
         // Removes a parameter by id. Returns false if parameter can not be removed.
-        bool RemoveParam(const string& paramId);
+        bool RemoveParam(const AZStd::string& paramId);
         // Removes a parameter by index. Returns false if parameter can not be removed.
         bool RemoveParam(unsigned int index);
 
@@ -543,9 +543,9 @@ namespace GridMate
         /// Frees a slot based on a slot type.
         void FreeSlot(int slotType);
         /// Creates remote player, when he wants to join.
-        virtual GridMember* CreateRemoteMember(const string& address, ReadBuffer& data, RemotePeerMode peerMode, ConnectionID connId = InvalidConnectionID) = 0;
+        virtual GridMember* CreateRemoteMember(const AZStd::string& address, ReadBuffer& data, RemotePeerMode peerMode, ConnectionID connId = InvalidConnectionID) = 0;
         /// Returns true if this address belongs to a member in the list, otherwise false.
-        virtual bool IsAddressInMemberList(const string& address);
+        virtual bool IsAddressInMemberList(const AZStd::string& address);
         virtual bool IsConnectionIdInMemberList(const ConnectionID& connId);
         /// Adds a created member to the session. Return false if no free slow was found!
         virtual bool AddMember(GridMember* member);
@@ -558,7 +558,7 @@ namespace GridMate
         /// Called when a session parameter is added/changed.
         virtual void OnSessionParamChanged(const GridSessionParam& param) = 0;
         /// Called when a session parameter is deleted.
-        virtual void OnSessionParamRemoved(const string& paramId) = 0;
+        virtual void OnSessionParamRemoved(const AZStd::string& paramId) = 0;
         //////////////////////////////////////////////////////////////////////////
 
         SessionID m_sessionId; ///< Session id. Content of the string will vary based on session types and platforms.
@@ -975,7 +975,7 @@ namespace GridMate
             /// Callback that notifies the title when a session will be left. session pointer is NOT valid after the callback returns.
             virtual void OnSessionDelete(GridSession* session) { (void)session; }
             /// Called when a session error occurs.
-            virtual void OnSessionError(GridSession* session, const string& errorMsg) { (void)session; (void)errorMsg; }
+            virtual void OnSessionError(GridSession* session, const AZStd::string& errorMsg) { (void)session; (void)errorMsg; }
             /// Called when the actual game(match) starts
             virtual void OnSessionStart(GridSession* session) { (void)session; }
             /// Called when the actual game(match) ends
diff --git a/Code/Framework/GridMate/Tests/Session.cpp b/Code/Framework/GridMate/Tests/Session.cpp
index 9e10e84e98..0c5baef483 100644
--- a/Code/Framework/GridMate/Tests/Session.cpp
+++ b/Code/Framework/GridMate/Tests/Session.cpp
@@ -241,7 +241,7 @@ namespace UnitTest
                 (void)reason;
             }
 
-            void OnSessionError(GridSession* session, const string& /*errorMsg*/) override
+            void OnSessionError(GridSession* session, const AZStd::string& /*errorMsg*/) override
             {
                 (void)session;
 #ifndef AZ_LAN_TEST_MAIN_THREAD_BLOCKED  // we will receive an error is we block for a long time
@@ -599,7 +599,7 @@ namespace UnitTest
             (void)member;
             (void)reason;
         }
-        void OnSessionError(GridSession* session, const string& /*errorMsg*/) override
+        void OnSessionError(GridSession* session, const AZStd::string& /*errorMsg*/) override
         {
             (void)session;
             AZ_TEST_ASSERT(false);
@@ -834,7 +834,7 @@ namespace UnitTest
             (void)member;
             (void)reason;
         }
-        void OnSessionError(GridSession* session, const string& /*errorMsg*/) override
+        void OnSessionError(GridSession* session, const AZStd::string& /*errorMsg*/) override
         {
             (void)session;
 #ifndef AZ_LAN_TEST_MAIN_THREAD_BLOCKED  // we will receive an error is we block for a long time
@@ -1207,7 +1207,7 @@ namespace UnitTest
             (void)member;
             (void)reason;
         }
-        void OnSessionError(GridSession* session, const string& /*errorMsg*/) override
+        void OnSessionError(GridSession* session, const AZStd::string& /*errorMsg*/) override
         {
             (void)session;
             AZ_TEST_ASSERT(false);
@@ -1521,7 +1521,7 @@ namespace UnitTest
             (void)member;
             (void)reason;
         }
-        void OnSessionError(GridSession* session, const string& /*errorMsg*/) override
+        void OnSessionError(GridSession* session, const AZStd::string& /*errorMsg*/) override
         {
             (void)session;
             // On this test we will get a open port error because we have multiple hosts. This is ok, since we test migration here!
@@ -1861,7 +1861,7 @@ namespace UnitTest
             (void)member;
             (void)reason;
         }
-        void OnSessionError(GridSession* session, const string& /*errorMsg*/) override
+        void OnSessionError(GridSession* session, const AZStd::string& /*errorMsg*/) override
         {
             (void)session;
             // On this test we will get a open port error because we have multiple hosts. This is ok, since we test migration here!
diff --git a/Code/Framework/GridMate/Tests/TestProfiler.cpp b/Code/Framework/GridMate/Tests/TestProfiler.cpp
index 428c1249ee..9f79d5a9fe 100644
--- a/Code/Framework/GridMate/Tests/TestProfiler.cpp
+++ b/Code/Framework/GridMate/Tests/TestProfiler.cpp
@@ -34,7 +34,7 @@ static bool CollectPerformanceCounters(const AZ::Debug::ProfilerRegister& reg, c
     return true;
 }
 
-static string FormatString(const string& pre, const string& name, const string& post, AZ::u64 time, AZ::u64 calls)
+static string FormatString(const AZStd::string& pre, const AZStd::string& name, const AZStd::string& post, AZ::u64 time, AZ::u64 calls)
 {
     string units = "us";
     if (AZ::u64 divtime = time / 1000)
diff --git a/Code/Legacy/CryCommon/LocalizationManagerBus.h b/Code/Legacy/CryCommon/LocalizationManagerBus.h
index 69ab32cebf..1d818de111 100644
--- a/Code/Legacy/CryCommon/LocalizationManagerBus.h
+++ b/Code/Legacy/CryCommon/LocalizationManagerBus.h
@@ -102,7 +102,7 @@ public:
     virtual bool LocalizeString_ch(const char* sString, AZStd::string& outLocalizedString, bool bEnglish = false) = 0;
 
     // Summary:
-    //   Same as LocalizeString( const char* sString, string& outLocalizedString, bool bEnglish=false )
+    //   Same as LocalizeString( const char* sString, AZStd::string& outLocalizedString, bool bEnglish=false )
     //   but at the moment this is faster.
     virtual bool LocalizeString_s(const AZStd::string& sString, AZStd::string& outLocalizedString, bool bEnglish = false) = 0;
 
diff --git a/Code/Legacy/CryCommon/LyShine/Animation/IUiAnimation.h b/Code/Legacy/CryCommon/LyShine/Animation/IUiAnimation.h
index 3515dab68e..e04fb6ada7 100644
--- a/Code/Legacy/CryCommon/LyShine/Animation/IUiAnimation.h
+++ b/Code/Legacy/CryCommon/LyShine/Animation/IUiAnimation.h
@@ -120,7 +120,7 @@ public:
     CUiAnimParamType()
         : m_type(eUiAnimParamType_Invalid) {}
 
-    CUiAnimParamType(const string& name)
+    CUiAnimParamType(const AZStd::string& name)
     {
         *this = name;
     }
@@ -136,17 +136,12 @@ public:
         m_type = (EUiAnimParamType)type;
     }
 
-    void operator =(const string& name)
-    {
-        m_type = eUiAnimParamType_ByString;
-        m_name = name;
-    }
-
     void operator =(const AZStd::string& name)
     {
         m_type = eUiAnimParamType_ByString;
         m_name = name.c_str();
     }
+
     // Convert to enum. This needs to be explicit,
     // otherwise operator== will be ambiguous
     EUiAnimParamType GetType() const { return m_type; }
@@ -1301,7 +1296,7 @@ inline void SUiAnimContext::Serialize(IUiAnimationSystem* animationSystem, XmlNo
     {
         if (pSequence)
         {
-            string fullname = pSequence->GetName();
+            AZStd::string fullname = pSequence->GetName();
             xmlNode->setAttr("sequence", fullname.c_str());
         }
         xmlNode->setAttr("dt", dt);
diff --git a/Code/Legacy/CryCommon/LyShine/ISprite.h b/Code/Legacy/CryCommon/LyShine/ISprite.h
index cd2b70ef25..373024d2db 100644
--- a/Code/Legacy/CryCommon/LyShine/ISprite.h
+++ b/Code/Legacy/CryCommon/LyShine/ISprite.h
@@ -59,10 +59,10 @@ public: // member functions
     virtual ~ISprite() {}
 
     //! Get the pathname of this sprite
-    virtual const string& GetPathname() const = 0;
+    virtual const AZStd::string& GetPathname() const = 0;
 
     //! Get the pathname of the texture of this sprite
-    virtual const string& GetTexturePathname() const = 0;
+    virtual const AZStd::string& GetTexturePathname() const = 0;
 
     //! Get the borders of this sprite
     virtual Borders GetBorders() const = 0;
@@ -77,7 +77,7 @@ public: // member functions
     virtual void Serialize(TSerialize ser) = 0;
 
     //! Save this sprite data to disk
-    virtual bool SaveToXml(const string& pathname) = 0;
+    virtual bool SaveToXml(const AZStd::string& pathname) = 0;
 
     //! Test if this sprite has any borders
     virtual bool AreBordersZeroWidth() const = 0;
@@ -136,4 +136,3 @@ public: // member functions
     //! Returns true if this sprite is configured as a sprite-sheet, false otherwise
     virtual bool IsSpriteSheet() const = 0;
 };
-

From 36abde95a9a312ed56625d422138a86150752ff6 Mon Sep 17 00:00:00 2001
From: Chris Santora 
Date: Fri, 23 Jul 2021 16:09:24 -0700
Subject: [PATCH 071/803] Added a new registry setting that disables automatic
 conversion of materials from model files like FBX.

By default, processing of model files (like FBX) automatically convert the included materials to Atom materials, using StandardPBR. This adds a job dependency on StandardPBR.materialtype, which propagates to any related azsl files as well. Thus any change to azsl code will cause all model files in the project to rebuild.

Some game teams have no interest in using the auto-converted materials; they always use a Material Component to apply material overrides for every mesh. This new setting allows teams to disable material auto-conversion for the entire project, thus removing the job dependency on StandardPBR.materialtype. Instead, every mesh will be assigned the same default material. Any change to azsl code will cause that one default material to rebuild, but this will not trigger any models to rebuild.

Details:
- Added /O3DE/SceneAPI/MaterialConverter registry settings for configuring the scene material converter. It includes an enable flag, and a default material to use when conversion is disabled.
- Added SceneBuilderDependencyRequests::AddFingerprintInfo which allows ScenePI components to modify the scene builder analysis fingerprint. We use this to reprocess scene files when the material converter settings change.
- Updated SceneAPI's material asset builder to skip the StandardPBR dependency when material conversion is disabled.
- Added some code to MaterialComponentController to handle an edge case that may when disabling material conversion on an existing project, and assigned materials disappear.

Testing:
- Changing the registery setting does trigger a rebuild of the fbx files.
- When material conversion is disabled, changing an azsl file does not cause fbx files to rebuild, but the shader still reloads as expected.
- Made a test level using multiple models with multiple meshes, made various adjustments to the material slots for each mesh, and tried switcihng the material conversion registry setting from true to false. (Details below)
- TODO: Will merge this change to a customer's fork and test on their existing content.

Details about my test level:
- Made a new test level AtomTest project
- Added two entities, both using multi-mat_mesh-groups_1m_cubes.fbx
- Added a material component to both entities
  - Entity 1 material assignments
    - Blue_Zaxis: left as-is
    - Green_Yaxis: exported the material
    - Red_Xaxis: exported the material, and changed the material instance color to pink
    - StingrayPBS1: exported the material, scaled the UVs in the exported material source, and changed the material instance color to green.
    - With_Texture: selected an existing brick material, changed the material instance color to red.
  - Entity 2 material assignments
    - Default Material: set to an existing brick material
    - Blue_Zaxis: manually assigned built-in material that was converted from fbx
    - Green_Yaxis: manually assigned built-in material that was converted from fbx, and changed the material instance color to orange

Signed-off-by: santorac <55155825+santorac@users.noreply.github.com>
---
 .../SceneCore/SceneBuilderDependencyBus.h     |   7 +-
 .../MaterialConverterSystemComponent.cpp      |  56 +++++++-
 .../MaterialConverterSystemComponent.h        |  17 +++
 .../RPI.Edit/Material/MaterialConverterBus.h  |  13 +-
 .../RPI.Reflect/Model/ModelMaterialSlot.h     |   2 +
 .../Model/MaterialAssetBuilderComponent.cpp   | 129 ++++++++++++++++--
 .../Model/MaterialAssetBuilderComponent.h     |   8 ++
 .../Model/ModelExporterComponent.cpp          |  10 +-
 .../Material/MaterialComponentController.cpp  |  93 ++++++++++++-
 .../Material/MaterialComponentController.h    |   9 +-
 .../SceneBuilder/SceneBuilderComponent.cpp    |   7 +
 .../SceneBuilder/SceneBuilderComponent.h      |   1 +
 .../SceneBuilder/SceneBuilderWorker.cpp       |   2 +
 Registry/sceneassetimporter.setreg            |   5 +
 14 files changed, 335 insertions(+), 24 deletions(-)

diff --git a/Code/Tools/SceneAPI/SceneCore/SceneBuilderDependencyBus.h b/Code/Tools/SceneAPI/SceneCore/SceneBuilderDependencyBus.h
index 6500b5ca28..752d4a431f 100644
--- a/Code/Tools/SceneAPI/SceneCore/SceneBuilderDependencyBus.h
+++ b/Code/Tools/SceneAPI/SceneCore/SceneBuilderDependencyBus.h
@@ -24,7 +24,12 @@ namespace AZ
             : public AZ::EBusTraits
         {
         public:
-            virtual void ReportJobDependencies(JobDependencyList& jobDependencyList, const char* platformIdentifier) = 0;
+            //! Builders can implement this function to add job dependencies on other assets that may be used in the scene file conversion process.
+            virtual void ReportJobDependencies(JobDependencyList& jobDependencyList, const char* platformIdentifier) { AZ_UNUSED(jobDependencyList); AZ_UNUSED(platformIdentifier); }
+            
+            //! Builders can implement this function to append to the job analysis fingerprint. This can be used to trigger rebuilds when global configuration changes.
+            //! See also AssetBuilderDesc::m_analysisFingerprint.
+            virtual void AddFingerprintInfo(AZStd::set& fingerprintInfo) { AZ_UNUSED(fingerprintInfo); }
         };
         using SceneBuilderDependencyBus = EBus;
     } // namespace SceneAPI
diff --git a/Gems/Atom/Feature/Common/Code/Source/Material/MaterialConverterSystemComponent.cpp b/Gems/Atom/Feature/Common/Code/Source/Material/MaterialConverterSystemComponent.cpp
index d173018ef7..d5fdcd9e41 100644
--- a/Gems/Atom/Feature/Common/Code/Source/Material/MaterialConverterSystemComponent.cpp
+++ b/Gems/Atom/Feature/Common/Code/Source/Material/MaterialConverterSystemComponent.cpp
@@ -12,12 +12,26 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
+#include 
+
 namespace AZ
 {
     namespace Render
     {
+        void MaterialConverterSettings::Reflect(AZ::ReflectContext* context)
+        {
+            if (auto serializeContext = azrtti_cast(context); serializeContext)
+            {
+                serializeContext->Class()
+                                ->Version(1)
+                                ->Field("Enable", &MaterialConverterSettings::m_enable)
+                                ->Field("DefaultMaterial", &MaterialConverterSettings::m_defaultMaterial);
+            }
+        }
+
         void MaterialConverterSystemComponent::Reflect(AZ::ReflectContext* context)
         {
             if (auto* serialize = azrtti_cast(context))
@@ -26,10 +40,22 @@ namespace AZ
                     ->Version(3)
                     ->Attribute(Edit::Attributes::SystemComponentTags, AZStd::vector({ AssetBuilderSDK::ComponentTags::AssetBuilder }));
             }
+
+            MaterialConverterSettings::Reflect(context);
+        }
+        
+        void MaterialConverterSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& services)
+        {
+            services.emplace_back(AZ_CRC_CE("FingerprintModification"));
         }
 
         void MaterialConverterSystemComponent::Activate()
         {
+            if (auto* settingsRegistry = AZ::SettingsRegistry::Get())
+            {
+                settingsRegistry->GetObject(m_settings, "/O3DE/SceneAPI/MaterialConverter");
+            }
+
             RPI::MaterialConverterBus::Handler::BusConnect();
         }
 
@@ -37,11 +63,21 @@ namespace AZ
         {
             RPI::MaterialConverterBus::Handler::BusDisconnect();
         }
+        
+        bool MaterialConverterSystemComponent::IsEnabled() const
+        {
+            return m_settings.m_enable;
+        }
 
         bool MaterialConverterSystemComponent::ConvertMaterial(
             const AZ::SceneAPI::DataTypes::IMaterialData& materialData, RPI::MaterialSourceData& sourceData)
         {
             using namespace AZ::RPI;
+            
+            if (!m_settings.m_enable)
+            {
+                return false;
+            }
 
             // The source data for generating material asset
             sourceData.m_materialType = GetMaterialTypePath();
@@ -142,7 +178,25 @@ namespace AZ
 
         const char* MaterialConverterSystemComponent::GetMaterialTypePath() const
         {
-            return "Materials/Types/StandardPBR.materialtype";
+            if (m_settings.m_enable)
+            {
+                return "Materials/Types/StandardPBR.materialtype";
+            }
+            else
+            {
+                return nullptr;
+            }
+        }
+
+        AZStd::string MaterialConverterSystemComponent::GetDefaultMaterialPath() const
+        {
+            if (m_settings.m_defaultMaterial.empty())
+            {
+                AZ_Error("MaterialConverterSystemComponent", m_settings.m_enable,
+                    "Material conversion is disabled but a default material not specified in registry /O3DE/SceneAPI/MaterialConverter/DefaultMaterial");
+            }
+
+            return m_settings.m_defaultMaterial;
         }
     }
 }
diff --git a/Gems/Atom/Feature/Common/Code/Source/Material/MaterialConverterSystemComponent.h b/Gems/Atom/Feature/Common/Code/Source/Material/MaterialConverterSystemComponent.h
index 38d4faedc8..e7e5c63732 100644
--- a/Gems/Atom/Feature/Common/Code/Source/Material/MaterialConverterSystemComponent.h
+++ b/Gems/Atom/Feature/Common/Code/Source/Material/MaterialConverterSystemComponent.h
@@ -18,6 +18,16 @@ namespace AZ
 {
     namespace Render
     {
+        struct MaterialConverterSettings
+        {
+            AZ_TYPE_INFO(MaterialConverterSettings, "{8D91601D-570A-4557-99C8-631DB4928040}");
+            
+            static void Reflect(AZ::ReflectContext* context);
+
+            bool m_enable = true;
+            AZStd::string m_defaultMaterial;
+        };
+
         //! Atom's implementation of converting SceneAPI data into Atom's default material: StandardPBR
         class MaterialConverterSystemComponent final
             : public AZ::Component
@@ -27,13 +37,20 @@ namespace AZ
             AZ_COMPONENT(MaterialConverterSystemComponent, "{C2338D45-6456-4521-B469-B000A13F2493}");
 
             static void Reflect(AZ::ReflectContext* context);
+            
+            static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& services);
 
             void Activate() override;
             void Deactivate() override;
 
             // MaterialConverterBus overrides ...
+            bool IsEnabled() const override;
             bool ConvertMaterial(const AZ::SceneAPI::DataTypes::IMaterialData& materialData, RPI::MaterialSourceData& out) override;
             const char* GetMaterialTypePath() const override;
+            AZStd::string GetDefaultMaterialPath() const override;
+
+        private:
+            MaterialConverterSettings m_settings;
         };
     }
 }
diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialConverterBus.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialConverterBus.h
index 120c1ee28b..e5aa32c175 100644
--- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialConverterBus.h
+++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialConverterBus.h
@@ -29,10 +29,19 @@ namespace AZ
             : public AZ::EBusTraits
         {
         public:
-            //! Returns true if the converion was successful
+
+            virtual bool IsEnabled() const = 0;
+
+            //! Converts data from a IMaterialData object to an Atom MaterialSourceData.
+            //! Only works when IsEnabled() is true.
+            //! @return true if the MaterialSourceData output was populated with converted material data.
             virtual bool ConvertMaterial(const AZ::SceneAPI::DataTypes::IMaterialData& materialData, MaterialSourceData& out) = 0;
-            //! Returns the path to the .materialtype file that the materials are based on, such as StandardPBR.materialtype, etc.
+
+            //! Returns the path to the .materialtype file that the converted materials are based on, such as StandardPBR.materialtype, etc. Or nullptr when conversion is disabled.
             virtual const char* GetMaterialTypePath() const = 0;
+
+            //! Returns the path to a .material file to use as the default material when conversion is disabled.
+            virtual AZStd::string GetDefaultMaterialPath() const = 0;
         };
 
         using MaterialConverterBus = AZ::EBus;
diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Model/ModelMaterialSlot.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Model/ModelMaterialSlot.h
index dd46aca6cd..30088d2d52 100644
--- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Model/ModelMaterialSlot.h
+++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Model/ModelMaterialSlot.h
@@ -25,6 +25,8 @@ namespace AZ
                 
             static void Reflect(AZ::ReflectContext* context);
 
+            // Note that StableId is uint32_t for legacy reasons: we used to use AssetId::m_subId as the material slot ID. But actually the original MaterialUid
+            // is 64 bit so we might want to switch this to be uint64_t at some point.
             using StableId = uint32_t;
             static const StableId InvalidStableId;
 
diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MaterialAssetBuilderComponent.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MaterialAssetBuilderComponent.cpp
index 7187cb391a..3eb60956ad 100644
--- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MaterialAssetBuilderComponent.cpp
+++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MaterialAssetBuilderComponent.cpp
@@ -28,6 +28,7 @@
 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -70,28 +71,74 @@ namespace AZ
 
         void MaterialAssetDependenciesComponent::ReportJobDependencies(SceneAPI::JobDependencyList& jobDependencyList, const char* platformIdentifier)
         {
-            AssetBuilderSDK::SourceFileDependency materialTypeSource;
+            bool conversionEnabled = false;
+            RPI::MaterialConverterBus::BroadcastResult(conversionEnabled, &RPI::MaterialConverterBus::Events::IsEnabled);
+            
             // Right now, scene file importing only supports a single material type, once that changes, this will have to be re-designed, see ATOM-3554
-            RPI::MaterialConverterBus::BroadcastResult(materialTypeSource.m_sourceFileDependencyPath, &RPI::MaterialConverterBus::Events::GetMaterialTypePath);
+            const char* materialTypePath = nullptr;
+            RPI::MaterialConverterBus::BroadcastResult(materialTypePath, &RPI::MaterialConverterBus::Events::GetMaterialTypePath);
 
-            AssetBuilderSDK::JobDependency jobDependency;
-            jobDependency.m_jobKey = "Atom Material Builder";
-            jobDependency.m_sourceFile = materialTypeSource;
-            jobDependency.m_platformIdentifier = platformIdentifier;
-            jobDependency.m_type = AssetBuilderSDK::JobDependencyType::Order;
-
-            if (!materialTypeSource.m_sourceFileDependencyPath.empty())
+            if (conversionEnabled && materialTypePath)
             {
+                AssetBuilderSDK::SourceFileDependency materialTypeSource;
+                materialTypeSource.m_sourceFileDependencyPath = materialTypePath;
+
+                AssetBuilderSDK::JobDependency jobDependency;
+                jobDependency.m_jobKey = "Atom Material Builder";
+                jobDependency.m_sourceFile = materialTypeSource;
+                jobDependency.m_platformIdentifier = platformIdentifier;
+                jobDependency.m_type = AssetBuilderSDK::JobDependencyType::Order;
+
                 jobDependencyList.push_back(jobDependency);
             }
         }
+        
+        void MaterialAssetDependenciesComponent::AddFingerprintInfo(AZStd::set& fingerprintInfo)
+        {
+            // This will cause scene files to be reprocessed whenever the global MaterialConverter settings change.
+
+            bool conversionEnabled = false;
+            RPI::MaterialConverterBus::BroadcastResult(conversionEnabled, &RPI::MaterialConverterBus::Events::IsEnabled);
+            fingerprintInfo.insert(AZStd::string::format("[MaterialConverter enabled=%d]", conversionEnabled));
+
+            if (!conversionEnabled)
+            {
+                AZStd::string defaultMaterialPath;
+                RPI::MaterialConverterBus::BroadcastResult(defaultMaterialPath, &RPI::MaterialConverterBus::Events::GetDefaultMaterialPath);
+                fingerprintInfo.insert(AZStd::string::format("[MaterialConverter defaultMaterial=%s]", defaultMaterialPath.c_str()));
+            }
+        }
 
         void MaterialAssetBuilderComponent::Reflect(ReflectContext* context)
         {
             if (auto* serialize = azrtti_cast(context))
             {
                 serialize->Class()
-                    ->Version(16);  // Optional material conversion
+                    ->Version(16);  // Optional material conversion 
+            }
+        }
+        
+        Data::Asset MaterialAssetBuilderComponent::GetDefaultMaterialAsset() const
+        {
+            AZStd::string defaultMaterialPath;
+            RPI::MaterialConverterBus::BroadcastResult(defaultMaterialPath, &RPI::MaterialConverterBus::Events::GetDefaultMaterialPath);
+
+            if (defaultMaterialPath.empty())
+            {
+                return {};
+            }
+            else
+            {
+                auto defaultMaterialAssetId = RPI::AssetUtils::MakeAssetId(defaultMaterialPath, 0);
+                if (!defaultMaterialAssetId.IsSuccess())
+                {
+                    AZ_Error("MaterialAssetBuilderComponent", false, "Could not find asset '%s'", defaultMaterialPath.c_str());
+                    return {};
+                }
+                else
+                {
+                    return Data::AssetManager::Instance().CreateAsset(defaultMaterialAssetId.GetValue(), Data::AssetLoadBehaviorNamespace::PreLoad);
+                }
             }
         }
 
@@ -119,8 +166,8 @@ namespace AZ
 
             BindToCall(&MaterialAssetBuilderComponent::BuildMaterials);
         }
-
-        SceneAPI::Events::ProcessingResult MaterialAssetBuilderComponent::BuildMaterials(MaterialAssetBuilderContext& context) const
+        
+        SceneAPI::Events::ProcessingResult MaterialAssetBuilderComponent::ConvertMaterials(MaterialAssetBuilderContext& context) const
         {
             const auto& scene = context.m_scene;
             const Uuid sourceSceneUuid = scene.GetSourceGuid();
@@ -193,6 +240,64 @@ namespace AZ
 
             return SceneAPI::Events::ProcessingResult::Success;
         }
+
+        SceneAPI::Events::ProcessingResult MaterialAssetBuilderComponent::AssignDefaultMaterials(MaterialAssetBuilderContext& context) const
+        {
+            Data::Asset defaultMaterialAsset = GetDefaultMaterialAsset();
+
+            if (!defaultMaterialAsset.GetId().IsValid())
+            {
+                AZ_Warning("MaterialAssetBuilderComponent", false, "Material conversion is disabled but no default material was provided. The model will likely be invisible by default.");
+                // Return success because it's just a warning.
+                return SceneAPI::Events::ProcessingResult::Success;
+            }
+
+            const auto& scene = context.m_scene;
+            const Uuid sourceSceneUuid = scene.GetSourceGuid();
+            const auto& sceneGraph = scene.GetGraph();
+
+            auto names = sceneGraph.GetNameStorage();
+            auto content = sceneGraph.GetContentStorage();
+            auto pairView = SceneAPI::Containers::Views::MakePairView(names, content);
+
+            auto view = SceneAPI::Containers::Views::MakeSceneGraphDownwardsView<
+                SceneAPI::Containers::Views::BreadthFirst>(
+                    sceneGraph, sceneGraph.GetRoot(), pairView.cbegin(), true);
+
+            for (const auto& viewIt : view)
+            {
+                if (viewIt.second == nullptr)
+                {
+                    continue;
+                }
+
+                if (azrtti_istypeof(viewIt.second.get()))
+                {
+                    auto materialData = AZStd::static_pointer_cast(viewIt.second);
+                    uint64_t materialUid = materialData->GetUniqueId();
+
+                    context.m_outputMaterialsByUid[materialUid] = { defaultMaterialAsset, materialData->GetMaterialName() };
+                }
+            }
+
+            return SceneAPI::Events::ProcessingResult::Success;
+        }
+
+        SceneAPI::Events::ProcessingResult MaterialAssetBuilderComponent::BuildMaterials(MaterialAssetBuilderContext& context) const
+        {
+            bool conversionEnabled = false;
+            RPI::MaterialConverterBus::BroadcastResult(conversionEnabled, &RPI::MaterialConverterBus::Events::IsEnabled);
+
+            if (conversionEnabled)
+            {
+                return ConvertMaterials(context);
+            }
+            else
+            {
+                return AssignDefaultMaterials(context);
+            }
+
+        }
     } // namespace RPI
 } // namespace AZ
 
diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MaterialAssetBuilderComponent.h b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MaterialAssetBuilderComponent.h
index f02034c35d..f89ae1cde9 100644
--- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MaterialAssetBuilderComponent.h
+++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MaterialAssetBuilderComponent.h
@@ -39,6 +39,13 @@ namespace AZ
 
             // Required for ExportingComponent
             static void Reflect(AZ::ReflectContext* context);
+
+        private:
+
+            SceneAPI::Events::ProcessingResult ConvertMaterials(MaterialAssetBuilderContext& context) const;
+            SceneAPI::Events::ProcessingResult AssignDefaultMaterials(MaterialAssetBuilderContext& context) const;
+            
+            Data::Asset GetDefaultMaterialAsset() const;
         };
 
         /**
@@ -65,6 +72,7 @@ namespace AZ
 
             // SceneAPI::SceneBuilderDependencyBus::Handler overrides...
             void ReportJobDependencies(SceneAPI::JobDependencyList& jobDependencyList, const char* platformIdentifier) override;
+            void AddFingerprintInfo(AZStd::set& fingerprintInfo) override;
         };
     } // namespace RPI
 } // namespace AZ
diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/ModelExporterComponent.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/ModelExporterComponent.cpp
index ea39ea9031..f7e672ab32 100644
--- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/ModelExporterComponent.cpp
+++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/ModelExporterComponent.cpp
@@ -78,9 +78,17 @@ namespace AZ
             //Export MaterialAssets
             for (auto& materialPair : materialsByUid)
             {
+                const Data::Asset& asset = materialPair.second.m_asset;
+                
+                // MaterialAssetBuilderContext could attach an independent material asset rather than
+                // generate one using the scene data, so we must skip the export step in that case.
+                if (asset.GetId().m_guid != exportEventContext.GetScene().GetSourceGuid())
+                {
+                    continue;
+                }
+
                 uint64_t materialUid = materialPair.first;
                 const AZStd::string& sceneName = exportEventContext.GetScene().GetName();
-                const Data::Asset& asset = materialPair.second.m_asset;
 
                 // escape the material name acceptable for a filename
                 AZStd::string materialName = materialPair.second.m_name;
diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.cpp
index e39f5cfad5..5d4e7883b0 100644
--- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.cpp
+++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.cpp
@@ -8,8 +8,10 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
+#include 
 
 namespace AZ
 {
@@ -85,6 +87,7 @@ namespace AZ
         void MaterialComponentController::Deactivate()
         {
             MaterialComponentRequestBus::Handler::BusDisconnect();
+            MeshComponentNotificationBus::Handler::BusDisconnect();
             TickBus::Handler::BusDisconnect();
             ReleaseMaterials();
 
@@ -111,6 +114,55 @@ namespace AZ
         {
             InitializeMaterialInstance(asset);
         }
+        
+        void MaterialComponentController::OnModelReady(const Data::Asset&, const Data::Instance&)
+        {
+            MeshComponentNotificationBus::Handler::BusDisconnect();
+
+            // If there is a circumstance where the saved material assignments are empty, fill them in with the default material.
+            // (This could happen as a result of LoadMaterials() clearing the asset reference to deal with an edge case)
+
+            // Now that a model asset is ready, see if there are any empty assignments that need to be filled...
+            RPI::ModelMaterialSlotMap modelMaterialSlots;
+            MaterialReceiverRequestBus::EventResult(modelMaterialSlots, m_entityId, &MaterialReceiverRequestBus::Events::GetModelMaterialSlots);
+
+            AZStd::vector> newMaterialAssets;
+            newMaterialAssets.reserve(m_configuration.m_materials.size());
+
+            // First we fill the empty slots but don't connect to AssetBus yet. If the same material asset appears multiple times,
+            // AssetBus will call OnAssetReady only the *first* time we connect for that asset. The full list of m_configuration.m_materials
+            // needs to be updated before that happens.
+            for (auto& materialPair : m_configuration.m_materials)
+            {
+                auto& materialAsset = materialPair.second.m_materialAsset;
+
+                if (!materialAsset.GetId().IsValid())
+                {
+                    auto slotIter = modelMaterialSlots.find(materialPair.first.m_materialSlotStableId);
+                    if (slotIter != modelMaterialSlots.end())
+                    {
+                        materialAsset = slotIter->second.m_defaultMaterialAsset;
+                        newMaterialAssets.push_back(materialAsset);
+                    }
+                    else
+                    {
+                        AZ_Error("MaterialComponentController", false, "Could not find material slot %d", materialPair.first.m_materialSlotStableId);
+                    }
+                }
+            }
+
+            // Now that the configuration is updated with all the default material assets, we can load and connect them.
+            // If there are duplicates in this list, the redundant calls will be ignored.
+            for (auto& materialAsset : newMaterialAssets)
+            {
+                if (!materialAsset.IsReady())
+                {
+                    materialAsset.QueueLoad();
+                }
+
+                Data::AssetBus::MultiHandler::BusConnect(materialAsset.GetId());
+            }
+        }
 
         void MaterialComponentController::OnTick([[maybe_unused]] float deltaTime, [[maybe_unused]] AZ::ScriptTimePoint time)
         {
@@ -186,11 +238,42 @@ namespace AZ
             for (auto& materialPair : m_configuration.m_materials)
             {
                 auto& materialAsset = materialPair.second.m_materialAsset;
-                if (materialAsset.GetId().IsValid() && !Data::AssetBus::MultiHandler::BusIsConnectedId(materialAsset.GetId()))
+
+                // This is a special case where a material was auto-generated from the model file, connected to a Material Component by the user,
+                // and then later a setting was changed to NOT auto-generate the model materials anymore. We need to switch to the new default
+                // material rather than trying to use the old default material which no longer exists. If that's the case, we reset the asset
+                // and OnModelReady will fill in the appropriate default material asset later.
                 {
-                    anyQueued = true;
-                    materialAsset.QueueLoad();
-                    Data::AssetBus::MultiHandler::BusConnect(materialAsset.GetId());
+                    Data::AssetId modelAssetId;
+                    MeshComponentRequestBus::EventResult(modelAssetId, m_entityId, &MeshComponentRequestBus::Events::GetModelAssetId);
+                    bool materialWasGeneratedFromModel = (modelAssetId.m_guid == materialAsset.GetId().m_guid);
+
+                    Data::AssetInfo assetInfo;
+                    Data::AssetCatalogRequestBus::BroadcastResult(assetInfo, &Data::AssetCatalogRequestBus::Events::GetAssetInfoById, materialAsset.GetId());
+                    bool materialAssetExists = assetInfo.m_assetId.IsValid();
+
+                    if (materialWasGeneratedFromModel && !materialAssetExists)
+                    {
+                        AZ_Warning("MaterialComponentController", false, "The default material assignment for this slot has changed and will be replaced (was '%s').",
+                            materialAsset.ToString().c_str());
+                        materialAsset.Reset();
+                    }
+                }
+
+                if (materialAsset.GetId().IsValid())
+                {
+                    if (!Data::AssetBus::MultiHandler::BusIsConnectedId(materialAsset.GetId()))
+                    {
+                        anyQueued = true;
+                        materialAsset.QueueLoad();
+                        Data::AssetBus::MultiHandler::BusConnect(materialAsset.GetId());
+                    }
+                }
+                else
+                {
+                    // Since a material asset wasn't found, we'll need to supply a default material. But the default materials
+                    // won't be known until after the mesh component has loaded the model data.
+                    MeshComponentNotificationBus::Handler::BusConnect(m_entityId);
                 }
             }
 
@@ -199,7 +282,7 @@ namespace AZ
                 ReleaseMaterials();
             }
         }
-
+        
         void MaterialComponentController::InitializeMaterialInstance(const Data::Asset& asset)
         {
             bool allReady = true;
diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.h
index de7f991d60..b2177d1191 100644
--- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.h
+++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.h
@@ -13,6 +13,7 @@
 #include 
 #include 
 #include 
+#include 
 
 namespace AZ
 {
@@ -22,6 +23,7 @@ namespace AZ
         //! to provide material overrides on a per-entity basis.
         class MaterialComponentController final
             : MaterialComponentRequestBus::Handler
+            , MeshComponentNotificationBus::Handler
             , Data::AssetBus::MultiHandler
             , TickBus::Handler
         {
@@ -68,13 +70,16 @@ namespace AZ
 
             AZ_DISABLE_COPY(MaterialComponentController);
 
-            //! Data::AssetBus interface
+            //! Data::AssetBus overrides...
             void OnAssetReady(Data::Asset asset) override;
             void OnAssetReloaded(Data::Asset asset) override;
 
-            //! AZ::TickBus interface implementation
+            // AZ::TickBus overrides...
             void OnTick(float deltaTime, AZ::ScriptTimePoint time) override;
 
+            // MeshComponentNotificationBus overrides...
+            void OnModelReady(const Data::Asset& modelAsset, const Data::Instance& model) override;
+
             void LoadMaterials();
             void InitializeMaterialInstance(const Data::Asset& asset);
             void ReleaseMaterials();
diff --git a/Gems/SceneProcessing/Code/Source/SceneBuilder/SceneBuilderComponent.cpp b/Gems/SceneProcessing/Code/Source/SceneBuilder/SceneBuilderComponent.cpp
index 524b79b012..430733f3a1 100644
--- a/Gems/SceneProcessing/Code/Source/SceneBuilder/SceneBuilderComponent.cpp
+++ b/Gems/SceneProcessing/Code/Source/SceneBuilder/SceneBuilderComponent.cpp
@@ -73,6 +73,13 @@ namespace SceneBuilder
         required.emplace_back(AZ_CRC_CE("AssetImportRequestHandler"));
     }
 
+    void BuilderPluginComponent::GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& services)
+    {
+        // Any components that can modify the analysis fingerprint via SceneBuilderDependencyRequests::AddFingerprintInfo must be activated first,
+        // so they contribute to the fingerprint calculated in BuilderPluginComponent::Activate().
+        services.emplace_back(AZ_CRC_CE("FingerprintModification"));
+    }
+
     void BuilderPluginComponent::Reflect(AZ::ReflectContext* context)
     {
         AZ::SerializeContext* serializeContext = azrtti_cast(context);
diff --git a/Gems/SceneProcessing/Code/Source/SceneBuilder/SceneBuilderComponent.h b/Gems/SceneProcessing/Code/Source/SceneBuilder/SceneBuilderComponent.h
index b4eee64bc6..0bfe118a4c 100644
--- a/Gems/SceneProcessing/Code/Source/SceneBuilder/SceneBuilderComponent.h
+++ b/Gems/SceneProcessing/Code/Source/SceneBuilder/SceneBuilderComponent.h
@@ -29,6 +29,7 @@ namespace SceneBuilder
         void Deactivate() override;
         
         static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required);
+        static void GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& services);
         
     private:
         SceneBuilderWorker m_sceneBuilder;
diff --git a/Gems/SceneProcessing/Code/Source/SceneBuilder/SceneBuilderWorker.cpp b/Gems/SceneProcessing/Code/Source/SceneBuilder/SceneBuilderWorker.cpp
index 18ee0285b8..2af4613e9e 100644
--- a/Gems/SceneProcessing/Code/Source/SceneBuilder/SceneBuilderWorker.cpp
+++ b/Gems/SceneProcessing/Code/Source/SceneBuilder/SceneBuilderWorker.cpp
@@ -69,6 +69,8 @@ namespace SceneBuilder
                 context->EnumerateDerived(callback, azrtti_typeid(), azrtti_typeid());
                 context->EnumerateDerived(callback, azrtti_typeid(), azrtti_typeid());
             }
+            
+            AZ::SceneAPI::SceneBuilderDependencyBus::Broadcast(&AZ::SceneAPI::SceneBuilderDependencyRequests::AddFingerprintInfo, fragments);
 
             for (const AZStd::string& element : fragments)
             {
diff --git a/Registry/sceneassetimporter.setreg b/Registry/sceneassetimporter.setreg
index bd7c4d0705..6fef3a40dc 100644
--- a/Registry/sceneassetimporter.setreg
+++ b/Registry/sceneassetimporter.setreg
@@ -10,6 +10,11 @@
 					".fbx",
 					".stl"
 				]
+			},
+			"MaterialConverter": 
+			{
+				"Enable": true,
+				"DefaultMaterial": "Materials/Presets/PBR/default_grid.material"
 			}
 		}
 	}

From 58f1cb9b6c02f4a315c3b21ba6212e382a92166c Mon Sep 17 00:00:00 2001
From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>
Date: Mon, 2 Aug 2021 17:55:08 -0700
Subject: [PATCH 072/803] Gems/LytShine

Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>
---
 .../Animation/Controls/UiSplineCtrlEx.cpp     |  2 +-
 .../Animation/Controls/UiSplineCtrlEx.h       |  4 +-
 .../Editor/Animation/UiAnimViewAnimNode.cpp   |  4 +-
 .../Editor/Animation/UiAnimViewDialog.cpp     |  6 +--
 .../Editor/Animation/UiAnimViewFindDlg.cpp    |  3 +-
 .../Animation/UiAnimViewNewSequenceDialog.cpp |  2 +-
 .../Code/Editor/Animation/UiAnimViewNodes.cpp | 14 +++---
 .../Editor/Animation/UiAnimViewSequence.cpp   | 12 ++---
 .../Code/Editor/Animation/UiAnimViewUndo.cpp  |  6 +--
 .../Code/Editor/Animation/UiAnimViewUndo.h    |  6 +--
 Gems/LyShine/Code/Editor/AssetTreeEntry.cpp   |  2 +-
 Gems/LyShine/Code/Editor/EditorMenu.cpp       |  2 +-
 .../Code/Editor/PropertiesContainer.cpp       |  2 +-
 .../Code/Editor/PropertyHandlerChar.cpp       | 13 +++---
 .../Code/Editor/PropertyHandlerDirectory.cpp  |  8 ++--
 .../Code/Editor/SpriteBorderEditor.cpp        |  2 +-
 .../Code/Source/Animation/AnimSequence.cpp    |  4 +-
 .../Code/Source/Animation/AnimSequence.h      |  2 +-
 .../Code/Source/Animation/AzEntityNode.cpp    |  4 +-
 .../Code/Source/Animation/AzEntityNode.h      |  6 +--
 .../Source/Animation/CompoundSplineTrack.h    |  2 +-
 .../Source/Animation/UiAnimationSystem.cpp    | 18 ++++----
 Gems/LyShine/Code/Source/LyShine.cpp          | 10 ++---
 Gems/LyShine/Code/Source/LyShine.h            | 10 ++---
 Gems/LyShine/Code/Source/LyShineDebug.cpp     |  4 +-
 .../LyShine/Code/Source/LyShineLoadScreen.cpp |  6 +--
 .../Platform/Windows/UiClipboard_Windows.cpp  |  6 ++-
 Gems/LyShine/Code/Source/Sprite.cpp           | 18 ++++----
 Gems/LyShine/Code/Source/Sprite.h             | 16 +++----
 Gems/LyShine/Code/Source/StringUtfUtils.h     | 25 +++++------
 .../Tests/internal/test_UiTextComponent.cpp   |  2 +-
 Gems/LyShine/Code/Source/TextMarkup.cpp       |  3 +-
 .../LyShine/Code/Source/UiCanvasComponent.cpp | 12 ++---
 Gems/LyShine/Code/Source/UiCanvasComponent.h  |  6 +--
 Gems/LyShine/Code/Source/UiCanvasManager.cpp  | 16 +++----
 Gems/LyShine/Code/Source/UiCanvasManager.h    |  2 +-
 .../Code/Source/UiDropdownComponent.cpp       |  3 +-
 .../Code/Source/UiInteractableState.cpp       |  2 +-
 Gems/LyShine/Code/Source/UiTextComponent.cpp  | 44 +++++++++++--------
 .../Source/UiTextComponentOffsetsSelector.cpp |  2 +-
 .../Code/Source/UiTextInputComponent.cpp      |  5 ++-
 41 files changed, 161 insertions(+), 155 deletions(-)

diff --git a/Gems/LyShine/Code/Editor/Animation/Controls/UiSplineCtrlEx.cpp b/Gems/LyShine/Code/Editor/Animation/Controls/UiSplineCtrlEx.cpp
index 39e5bd0f5f..746ea04559 100644
--- a/Gems/LyShine/Code/Editor/Animation/Controls/UiSplineCtrlEx.cpp
+++ b/Gems/LyShine/Code/Editor/Animation/Controls/UiSplineCtrlEx.cpp
@@ -135,7 +135,7 @@ private:
         std::vector keySelectionFlags;
         _smart_ptr undo;
         _smart_ptr redo;
-        string id;
+        AZStd::string id;
         ISplineInterpolator* pSpline;
     };
 
diff --git a/Gems/LyShine/Code/Editor/Animation/Controls/UiSplineCtrlEx.h b/Gems/LyShine/Code/Editor/Animation/Controls/UiSplineCtrlEx.h
index 18ee7e173c..2a7b0c3d1f 100644
--- a/Gems/LyShine/Code/Editor/Animation/Controls/UiSplineCtrlEx.h
+++ b/Gems/LyShine/Code/Editor/Animation/Controls/UiSplineCtrlEx.h
@@ -45,8 +45,8 @@ class QRubberBand;
 class ISplineSet
 {
 public:
-    virtual ISplineInterpolator* GetSplineFromID(const string& id) = 0;
-    virtual string GetIDFromSpline(ISplineInterpolator* pSpline) = 0;
+    virtual ISplineInterpolator* GetSplineFromID(const AZStd::string& id) = 0;
+    virtual AZStd::string GetIDFromSpline(ISplineInterpolator* pSpline) = 0;
     virtual int GetSplineCount() const = 0;
     virtual int GetKeyCountAtTime(float time, float threshold) const = 0;
 };
diff --git a/Gems/LyShine/Code/Editor/Animation/UiAnimViewAnimNode.cpp b/Gems/LyShine/Code/Editor/Animation/UiAnimViewAnimNode.cpp
index f860725276..8880795466 100644
--- a/Gems/LyShine/Code/Editor/Animation/UiAnimViewAnimNode.cpp
+++ b/Gems/LyShine/Code/Editor/Animation/UiAnimViewAnimNode.cpp
@@ -1100,7 +1100,7 @@ bool CUiAnimViewAnimNode::SetName(const char* pName)
         }
     }
 
-    string oldName = GetName();
+    AZStd::string oldName = GetName();
     m_pAnimNode->SetName(pName);
 
     if (UiAnimUndo::IsRecording())
@@ -1108,7 +1108,7 @@ bool CUiAnimViewAnimNode::SetName(const char* pName)
         UiAnimUndo::Record(new CUndoAnimNodeRename(this, oldName));
     }
 
-    GetSequence()->OnNodeRenamed(this, oldName);
+    GetSequence()->OnNodeRenamed(this, oldName.c_str());
 
     return true;
 }
diff --git a/Gems/LyShine/Code/Editor/Animation/UiAnimViewDialog.cpp b/Gems/LyShine/Code/Editor/Animation/UiAnimViewDialog.cpp
index 61d6b66b29..ac210ba2f2 100644
--- a/Gems/LyShine/Code/Editor/Animation/UiAnimViewDialog.cpp
+++ b/Gems/LyShine/Code/Editor/Animation/UiAnimViewDialog.cpp
@@ -992,7 +992,7 @@ void CUiAnimViewDialog::ReloadSequencesComboBox()
         for (int k = 0; k < numSequences; ++k)
         {
             CUiAnimViewSequence* pSequence = pSequenceManager->GetSequenceByIndex(k);
-            QString fullname = QtUtil::ToQString(pSequence->GetName());
+            QString fullname = pSequence->GetName();
             m_sequencesComboBox->addItem(fullname);
         }
     }
@@ -1132,7 +1132,7 @@ void CUiAnimViewDialog::OnSequenceChanged(CUiAnimViewSequence* pSequence)
 
     if (pSequence)
     {
-        m_currentSequenceName = QtUtil::ToQString(pSequence->GetName());
+        m_currentSequenceName = pSequence->GetName();
 
         pSequence->Reset(true);
         SaveZoomScrollSettings();
@@ -1733,7 +1733,7 @@ void CUiAnimViewDialog::OnNodeRenamed(CUiAnimViewNode* pNode, const char* pOldNa
     {
         if (m_currentSequenceName == QString(pOldName))
         {
-            m_currentSequenceName = QtUtil::ToQString(pNode->GetName());
+            m_currentSequenceName = pNode->GetName();
         }
 
         ReloadSequencesComboBox();
diff --git a/Gems/LyShine/Code/Editor/Animation/UiAnimViewFindDlg.cpp b/Gems/LyShine/Code/Editor/Animation/UiAnimViewFindDlg.cpp
index 86f1f786d0..511866db43 100644
--- a/Gems/LyShine/Code/Editor/Animation/UiAnimViewFindDlg.cpp
+++ b/Gems/LyShine/Code/Editor/Animation/UiAnimViewFindDlg.cpp
@@ -13,7 +13,6 @@
 #include "UiAnimViewSequenceManager.h"
 
 #include 
-#include 
 #include 
 
 #include 
@@ -64,7 +63,7 @@ void CUiAnimViewFindDlg::FillData()
             ObjName obj;
             obj.m_objName = pNode->GetName();
             obj.m_directorName = pNode->HasDirectorAsParent() ? pNode->HasDirectorAsParent()->GetName() : "";
-            string fullname = seq->GetName();
+            AZStd::string fullname = seq->GetName();
             obj.m_seqName = fullname.c_str();
             m_objs.push_back(obj);
         }
diff --git a/Gems/LyShine/Code/Editor/Animation/UiAnimViewNewSequenceDialog.cpp b/Gems/LyShine/Code/Editor/Animation/UiAnimViewNewSequenceDialog.cpp
index 7c4882e7f0..ac824bfc4d 100644
--- a/Gems/LyShine/Code/Editor/Animation/UiAnimViewNewSequenceDialog.cpp
+++ b/Gems/LyShine/Code/Editor/Animation/UiAnimViewNewSequenceDialog.cpp
@@ -46,7 +46,7 @@ void CUiAVNewSequenceDialog::OnOK()
     for (int k = 0; k < CUiAnimViewSequenceManager::GetSequenceManager()->GetCount(); ++k)
     {
         CUiAnimViewSequence* pSequence = CUiAnimViewSequenceManager::GetSequenceManager()->GetSequenceByIndex(k);
-        QString fullname = QtUtil::ToQString(pSequence->GetName());
+        QString fullname = pSequence->GetName();
 
         if (fullname.compare(m_sequenceName, Qt::CaseInsensitive) == 0)
         {
diff --git a/Gems/LyShine/Code/Editor/Animation/UiAnimViewNodes.cpp b/Gems/LyShine/Code/Editor/Animation/UiAnimViewNodes.cpp
index 9cca6cdf8d..67fd542c3f 100644
--- a/Gems/LyShine/Code/Editor/Animation/UiAnimViewNodes.cpp
+++ b/Gems/LyShine/Code/Editor/Animation/UiAnimViewNodes.cpp
@@ -486,7 +486,7 @@ CUiAnimViewNodesCtrl::CRecord* CUiAnimViewNodesCtrl::AddAnimNodeRecord(CRecord*
 {
     CRecord* pNewRecord = new CRecord(pAnimNode);
 
-    pNewRecord->setText(0, QtUtil::ToQString(pAnimNode->GetName()));
+    pNewRecord->setText(0, pAnimNode->GetName());
     UpdateUiAnimNodeRecord(pNewRecord, pAnimNode);
     pParentRecord->insertChild(GetInsertPosition(pParentRecord, pAnimNode), pNewRecord);
     FillNodesRec(pNewRecord, pAnimNode);
@@ -499,7 +499,7 @@ CUiAnimViewNodesCtrl::CRecord* CUiAnimViewNodesCtrl::AddTrackRecord(CRecord* pPa
 {
     CRecord* pNewTrackRecord = new CRecord(pTrack);
     pNewTrackRecord->setSizeHint(0, QSize(30, 18));
-    pNewTrackRecord->setText(0, QtUtil::ToQString(pTrack->GetName()));
+    pNewTrackRecord->setText(0, pTrack->GetName());
     UpdateTrackRecord(pNewTrackRecord, pTrack);
     pParentRecord->insertChild(GetInsertPosition(pParentRecord, pTrack), pNewTrackRecord);
     FillNodesRec(pNewTrackRecord, pTrack);
@@ -708,7 +708,7 @@ void CUiAnimViewNodesCtrl::OnFillItems()
         m_nodeToRecordMap.clear();
 
         CRecord* pRootGroupRec = new CRecord(pSequence);
-        pRootGroupRec->setText(0, QtUtil::ToQString(pSequence->GetName()));
+        pRootGroupRec->setText(0, pSequence->GetName());
         QFont f = font();
         f.setBold(true);
         pRootGroupRec->setData(0, Qt::FontRole, f);
@@ -1323,7 +1323,7 @@ int CUiAnimViewNodesCtrl::ShowPopupMenuSingleSelection(UiAnimContextMenu& contex
                     continue;
                 }
 
-                QAction* a = contextMenu.main.addAction(QString("  %1").arg(QtUtil::ToQString(pTrack2->GetName())));
+                QAction* a = contextMenu.main.addAction(QString("  %1").arg(pTrack2->GetName()));
                 a->setData(eMI_ShowHideBase + childIndex);
                 a->setCheckable(true);
                 a->setChecked(!pTrack2->IsHidden());
@@ -1459,7 +1459,7 @@ void CUiAnimViewNodesCtrl::FillAutoCompletionListForFilter()
 
         for (unsigned int i = 0; i < animNodeCount; ++i)
         {
-            strings << QtUtil::ToQString(animNodes.GetNode(i)->GetName());
+            strings << QString(animNodes.GetNode(i)->GetName());
         }
     }
     else
@@ -1512,7 +1512,7 @@ int CUiAnimViewNodesCtrl::GetMatNameAndSubMtlIndexFromName(QString& matName, con
     if (const char* pCh = strstr(nodeName, ".["))
     {
         char matPath[MAX_PATH];
-        azstrcpy(matPath, nodeName, (size_t)(pCh - nodeName));
+        azstrncpy(matPath, nodeName, (size_t)(pCh - nodeName));
         matName = matPath;
         pCh += 2;
         if ((*pCh) != 0)
@@ -1763,7 +1763,7 @@ void CUiAnimViewNodesCtrl::OnNodeRenamed(CUiAnimViewNode* pNode, [[maybe_unused]
     if (!m_bIgnoreNotifications)
     {
         CRecord* pNodeRecord = GetNodeRecord(pNode);
-        pNodeRecord->setText(0, QtUtil::ToQString(pNode->GetName()));
+        pNodeRecord->setText(0, pNode->GetName());
 
         update();
     }
diff --git a/Gems/LyShine/Code/Editor/Animation/UiAnimViewSequence.cpp b/Gems/LyShine/Code/Editor/Animation/UiAnimViewSequence.cpp
index 7f7f8f7aaf..cdafd8a4ce 100644
--- a/Gems/LyShine/Code/Editor/Animation/UiAnimViewSequence.cpp
+++ b/Gems/LyShine/Code/Editor/Animation/UiAnimViewSequence.cpp
@@ -683,7 +683,7 @@ bool CUiAnimViewSequence::SetName(const char* pName)
         return false;
     }
 
-    string oldName = GetName();
+    AZStd::string oldName = GetName();
     m_pAnimSequence->SetName(pName);
 
     if (UiAnimUndo::IsRecording())
@@ -691,7 +691,7 @@ bool CUiAnimViewSequence::SetName(const char* pName)
         UiAnimUndo::Record(new CUndoAnimNodeRename(this, oldName));
     }
 
-    GetSequence()->OnNodeRenamed(this, oldName);
+    GetSequence()->OnNodeRenamed(this, oldName.c_str());
 
     return true;
 }
@@ -893,7 +893,7 @@ std::deque CUiAnimViewSequence::GetMatchingTracks(CUiAnimView
 {
     std::deque matchingTracks;
 
-    const string trackName = trackNode->getAttr("name");
+    const AZStd::string trackName = trackNode->getAttr("name");
 
     IUiAnimationSystem* animationSystem = nullptr;
     EBUS_EVENT_RESULT(animationSystem, UiEditorAnimationBus, GetAnimationSystem);
@@ -956,11 +956,11 @@ void CUiAnimViewSequence::GetMatchedPasteLocationsRec(std::vectorgetChild(nodeIndex);
-        const string tagName = xmlChildNode->getTag();
+        const AZStd::string tagName = xmlChildNode->getTag();
 
         if (tagName == "Node")
         {
-            const string nodeName = xmlChildNode->getAttr("name");
+            const AZStd::string nodeName = xmlChildNode->getAttr("name");
 
             int nodeType = eUiAnimNodeType_Invalid;
             xmlChildNode->getAttr("type", nodeType);
@@ -982,7 +982,7 @@ void CUiAnimViewSequence::GetMatchedPasteLocationsRec(std::vectorgetAttr("name");
+            const AZStd::string trackName = xmlChildNode->getAttr("name");
 
             IUiAnimationSystem* animationSystem = nullptr;
             EBUS_EVENT_RESULT(animationSystem, UiEditorAnimationBus, GetAnimationSystem);
diff --git a/Gems/LyShine/Code/Editor/Animation/UiAnimViewUndo.cpp b/Gems/LyShine/Code/Editor/Animation/UiAnimViewUndo.cpp
index 8ab6f2e58c..cd4bf5b1ac 100644
--- a/Gems/LyShine/Code/Editor/Animation/UiAnimViewUndo.cpp
+++ b/Gems/LyShine/Code/Editor/Animation/UiAnimViewUndo.cpp
@@ -546,7 +546,7 @@ void CUndoAnimNodeReparent::AddParentsInChildren(CUiAnimViewAnimNode* pCurrentNo
 }
 
 //////////////////////////////////////////////////////////////////////////
-CUndoAnimNodeRename::CUndoAnimNodeRename(CUiAnimViewAnimNode* pNode, const string& oldName)
+CUndoAnimNodeRename::CUndoAnimNodeRename(CUiAnimViewAnimNode* pNode, const AZStd::string& oldName)
     : m_pNode(pNode)
     , m_newName(pNode->GetName())
     , m_oldName(oldName)
@@ -556,13 +556,13 @@ CUndoAnimNodeRename::CUndoAnimNodeRename(CUiAnimViewAnimNode* pNode, const strin
 //////////////////////////////////////////////////////////////////////////
 void CUndoAnimNodeRename::Undo([[maybe_unused]] bool bUndo)
 {
-    m_pNode->SetName(m_oldName);
+    m_pNode->SetName(m_oldName.c_str());
 }
 
 //////////////////////////////////////////////////////////////////////////
 void CUndoAnimNodeRename::Redo()
 {
-    m_pNode->SetName(m_newName);
+    m_pNode->SetName(m_newName.c_str());
 }
 
 //////////////////////////////////////////////////////////////////////////
diff --git a/Gems/LyShine/Code/Editor/Animation/UiAnimViewUndo.h b/Gems/LyShine/Code/Editor/Animation/UiAnimViewUndo.h
index d79336cedd..923420c653 100644
--- a/Gems/LyShine/Code/Editor/Animation/UiAnimViewUndo.h
+++ b/Gems/LyShine/Code/Editor/Animation/UiAnimViewUndo.h
@@ -304,7 +304,7 @@ class CUndoAnimNodeRename
     : public UiAnimUndoObject
 {
 public:
-    CUndoAnimNodeRename(CUiAnimViewAnimNode* pNode, const string& oldName);
+    CUndoAnimNodeRename(CUiAnimViewAnimNode* pNode, const AZStd::string& oldName);
 
 protected:
     virtual int GetSize() override { return sizeof(*this); };
@@ -315,8 +315,8 @@ protected:
 
 private:
     CUiAnimViewAnimNode* m_pNode;
-    string m_newName;
-    string m_oldName;
+    AZStd::string m_newName;
+    AZStd::string m_oldName;
 };
 
 /** Base class for track event transactions
diff --git a/Gems/LyShine/Code/Editor/AssetTreeEntry.cpp b/Gems/LyShine/Code/Editor/AssetTreeEntry.cpp
index caff5d2da0..206da8cb3a 100644
--- a/Gems/LyShine/Code/Editor/AssetTreeEntry.cpp
+++ b/Gems/LyShine/Code/Editor/AssetTreeEntry.cpp
@@ -75,7 +75,7 @@ void AssetTreeEntry::Insert(const AZStd::string& path, const AZStd::string& menu
         AZStd::string folderName;
         AZStd::string remainderPath;
         size_t separator = path.find('/');
-        if (separator == string::npos)
+        if (separator == AZStd::string::npos)
         {
             folderName = path;
         }
diff --git a/Gems/LyShine/Code/Editor/EditorMenu.cpp b/Gems/LyShine/Code/Editor/EditorMenu.cpp
index 97db065a4d..840bd206ab 100644
--- a/Gems/LyShine/Code/Editor/EditorMenu.cpp
+++ b/Gems/LyShine/Code/Editor/EditorMenu.cpp
@@ -724,7 +724,7 @@ void EditorWindow::AddMenu_View_LanguageSetting(QMenu* viewMenu)
     // Iterate through the subdirectories of the localization folder. Each
     // directory corresponds to a different language containing localization
     // translations for that language.
-    string fullLocPath(string(gEnv->pFileIO->GetAlias("@assets@")) + "/" + string(m_startupLocFolderName.toUtf8().constData()));
+    AZStd::string fullLocPath(AZStd::string(gEnv->pFileIO->GetAlias("@assets@")) + "/" + AZStd::string(m_startupLocFolderName.toUtf8().constData()));
     QDir locDir(fullLocPath.c_str());
     locDir.setFilter(QDir::Dirs | QDir::NoDotAndDotDot);
     locDir.setSorting(QDir::Name);
diff --git a/Gems/LyShine/Code/Editor/PropertiesContainer.cpp b/Gems/LyShine/Code/Editor/PropertiesContainer.cpp
index 36a78fe684..21b3b99b02 100644
--- a/Gems/LyShine/Code/Editor/PropertiesContainer.cpp
+++ b/Gems/LyShine/Code/Editor/PropertiesContainer.cpp
@@ -788,7 +788,7 @@ void PropertiesContainer::Update()
     }
     else // more than one entity selected
     {
-        displayName = ToString(selectedEntitiesAmount) + " elements selected";
+        displayName = (ToString(selectedEntitiesAmount) + " elements selected").c_str();
     }
 
     // Update the selected element display name
diff --git a/Gems/LyShine/Code/Editor/PropertyHandlerChar.cpp b/Gems/LyShine/Code/Editor/PropertyHandlerChar.cpp
index ac55cd38e9..b3cacec065 100644
--- a/Gems/LyShine/Code/Editor/PropertyHandlerChar.cpp
+++ b/Gems/LyShine/Code/Editor/PropertyHandlerChar.cpp
@@ -9,6 +9,8 @@
 
 #include "PropertyHandlerChar.h"
 
+#include 
+
 QWidget* PropertyHandlerChar::CreateGUI(QWidget* pParent)
 {
     AzToolsFramework::PropertyStringLineEditCtrl* ctrl = aznew AzToolsFramework::PropertyStringLineEditCtrl(pParent);
@@ -29,12 +31,8 @@ void PropertyHandlerChar::WriteGUIValuesIntoProperty(size_t index, AzToolsFramew
 {
     (int)index;
     AZStd::string str = GUI->value();
-    uint32_t character = '\0';
-    if (!str.empty())
-    {
-        Unicode::CIterator pChar(str.c_str());
-        character = *pChar;
-    }
+    wchar_t character = '\0';
+    AZStd::to_wstring(&character, 1, str.c_str());
     instance = character;
 }
 
@@ -47,7 +45,8 @@ bool PropertyHandlerChar::ReadValuesIntoGUI(size_t index, AzToolsFramework::Prop
         // NOTE: this assumes the uint32_t can be interpreted as a wchar_t, it seems to
         // work for cases tested but may not in general.
         wchar_t wcharString[2] = { static_cast(instance), 0 };
-        AZStd::string val(CryStringUtils::WStrToUTF8(wcharString));
+        AZStd::string val;
+        AZStd::to_string(val, wcharString);
         GUI->setValue(val);
     }
     GUI->blockSignals(false);
diff --git a/Gems/LyShine/Code/Editor/PropertyHandlerDirectory.cpp b/Gems/LyShine/Code/Editor/PropertyHandlerDirectory.cpp
index ab51c3a29d..1f3e28b077 100644
--- a/Gems/LyShine/Code/Editor/PropertyHandlerDirectory.cpp
+++ b/Gems/LyShine/Code/Editor/PropertyHandlerDirectory.cpp
@@ -93,7 +93,7 @@ AzToolsFramework::AssetBrowser::AssetSelectionModel PropertyAssetDirectorySelect
 
 void PropertyAssetDirectorySelectionCtrl::SetFolderSelection(const AZStd::string& folderPath)
 {
-    string strFolderPath = folderPath.c_str();
+    AZStd::string strFolderPath = folderPath.c_str();
     if (strFolderPath.empty())
     {
         m_folderPath.clear();
@@ -106,12 +106,14 @@ void PropertyAssetDirectorySelectionCtrl::SetFolderSelection(const AZStd::string
         // the project folder, which we need to omit since file IO routines
         // seem to assume this anyways.
         strFolderPath = strFolderPath.substr(strFolderPath.find('/') + 1);
-        m_folderPath = PathUtil::MakeGamePath(strFolderPath).MakeLower();
+        m_folderPath = PathUtil::MakeGamePath(strFolderPath);
+        AZStd::to_lower(m_folderPath.begin(), m_folderPath.end());
     }
     // For paths in gems, absolute paths are returned
     else
     {
-        m_folderPath = Path::FullPathToGamePath(strFolderPath.c_str()).MakeLower();
+        m_folderPath = Path::FullPathToGamePath(strFolderPath.c_str());
+        AZStd::to_lower(m_folderPath.begin(), m_folderPath.end());
     }
 }
 
diff --git a/Gems/LyShine/Code/Editor/SpriteBorderEditor.cpp b/Gems/LyShine/Code/Editor/SpriteBorderEditor.cpp
index 2bb1686a93..d833c93af8 100644
--- a/Gems/LyShine/Code/Editor/SpriteBorderEditor.cpp
+++ b/Gems/LyShine/Code/Editor/SpriteBorderEditor.cpp
@@ -921,7 +921,7 @@ void SpriteBorderEditor::AddButtonsSection(QGridLayout* gridLayout, int& rowNum)
                 // The texture is guaranteed to exist so use that to get the full path.
                 QString fullTexturePath = Path::GamePathToFullPath(m_sprite->GetTexturePathname().c_str());
                 const char* const spriteExtension = "sprite";
-                string fullSpritePath = PathUtil::ReplaceExtension(fullTexturePath.toUtf8().data(), spriteExtension);
+                AZStd::string fullSpritePath = PathUtil::ReplaceExtension(fullTexturePath.toUtf8().data(), spriteExtension);
 
                 FileHelpers::SourceControlAddOrEdit(fullSpritePath.c_str(), QApplication::activeWindow());
 
diff --git a/Gems/LyShine/Code/Source/Animation/AnimSequence.cpp b/Gems/LyShine/Code/Source/Animation/AnimSequence.cpp
index f1ecb4af9e..43a80d5002 100644
--- a/Gems/LyShine/Code/Source/Animation/AnimSequence.cpp
+++ b/Gems/LyShine/Code/Source/Animation/AnimSequence.cpp
@@ -80,10 +80,10 @@ void CUiAnimSequence::SetName(const char* name)
         return;   // should never happen, null pointer guard
     }
 
-    string originalName = GetName();
+    AZStd::string originalName = GetName();
 
     m_name = name;
-    m_pUiAnimationSystem->OnSequenceRenamed(originalName, m_name.c_str());
+    m_pUiAnimationSystem->OnSequenceRenamed(originalName.c_str(), m_name.c_str());
 
     if (GetOwner())
     {
diff --git a/Gems/LyShine/Code/Source/Animation/AnimSequence.h b/Gems/LyShine/Code/Source/Animation/AnimSequence.h
index efbe886ce2..e4026ce250 100644
--- a/Gems/LyShine/Code/Source/Animation/AnimSequence.h
+++ b/Gems/LyShine/Code/Source/Animation/AnimSequence.h
@@ -146,7 +146,7 @@ private:
 
     uint32 m_id;
     AZStd::string m_name;
-    mutable string m_fullNameHolder;
+    mutable AZStd::string m_fullNameHolder;
     Range m_timeRange;
     UiTrackEvents m_events;
 
diff --git a/Gems/LyShine/Code/Source/Animation/AzEntityNode.cpp b/Gems/LyShine/Code/Source/Animation/AzEntityNode.cpp
index ca435dadf9..32dfb97a58 100644
--- a/Gems/LyShine/Code/Source/Animation/AzEntityNode.cpp
+++ b/Gems/LyShine/Code/Source/Animation/AzEntityNode.cpp
@@ -278,8 +278,8 @@ const AZ::SerializeContext::ClassElement* CUiAnimAzEntityNode::ComputeOffsetFrom
 
         if (mismatch)
         {
-            string warnMsg = "Data mismatch reading animation data for type ";
-            warnMsg += classData->m_typeId.ToString();
+            AZStd::string warnMsg = "Data mismatch reading animation data for type ";
+            warnMsg += classData->m_typeId.ToString();
             warnMsg += ". The field \"";
             warnMsg += paramData.GetName();
             if (!element)
diff --git a/Gems/LyShine/Code/Source/Animation/AzEntityNode.h b/Gems/LyShine/Code/Source/Animation/AzEntityNode.h
index 6ca26ef84a..56680f1094 100644
--- a/Gems/LyShine/Code/Source/Animation/AzEntityNode.h
+++ b/Gems/LyShine/Code/Source/Animation/AzEntityNode.h
@@ -170,14 +170,14 @@ private:
 
     struct SScriptPropertyParamInfo
     {
-        string variableName;
-        string displayName;
+        AZStd::string variableName;
+        AZStd::string displayName;
         bool isVectorTable;
         SParamInfo animNodeParamInfo;
     };
 
     std::vector< SScriptPropertyParamInfo > m_entityScriptPropertiesParamInfos;
-    typedef AZStd::unordered_map< string, size_t, stl::hash_string_caseless, stl::equality_string_caseless > TScriptPropertyParamInfoMap;
+    typedef AZStd::unordered_map, stl::equality_string_caseless > TScriptPropertyParamInfoMap;
     TScriptPropertyParamInfoMap m_nameToScriptPropertyParamInfo;
     #ifdef CHECK_FOR_TOO_MANY_ONPROPERTY_SCRIPT_CALLS
     uint32 m_OnPropertyCalls;
diff --git a/Gems/LyShine/Code/Source/Animation/CompoundSplineTrack.h b/Gems/LyShine/Code/Source/Animation/CompoundSplineTrack.h
index b707d0bc77..3ae230d4e4 100644
--- a/Gems/LyShine/Code/Source/Animation/CompoundSplineTrack.h
+++ b/Gems/LyShine/Code/Source/Animation/CompoundSplineTrack.h
@@ -112,7 +112,7 @@ public:
 
     virtual int NextKeyByTime(int key) const;
 
-    void SetSubTrackName(const int i, const string& name) { assert (i < MAX_SUBTRACKS); m_subTrackNames[i] = name; }
+    void SetSubTrackName(const int i, const AZStd::string& name) { assert (i < MAX_SUBTRACKS); m_subTrackNames[i] = name; }
 
 #ifdef UI_ANIMATION_SYSTEM_SUPPORT_EDITING
     virtual ColorB GetCustomColor() const
diff --git a/Gems/LyShine/Code/Source/Animation/UiAnimationSystem.cpp b/Gems/LyShine/Code/Source/Animation/UiAnimationSystem.cpp
index 5c897620c7..1ea35006e2 100644
--- a/Gems/LyShine/Code/Source/Animation/UiAnimationSystem.cpp
+++ b/Gems/LyShine/Code/Source/Animation/UiAnimationSystem.cpp
@@ -27,19 +27,19 @@
 // Serialization for anim nodes & param types
 #define REGISTER_NODE_TYPE(name) assert(g_animNodeEnumToStringMap.find(eUiAnimNodeType_ ## name) == g_animNodeEnumToStringMap.end()); \
     g_animNodeEnumToStringMap[eUiAnimNodeType_ ## name] = STRINGIFY(name);                                                            \
-    g_animNodeStringToEnumMap[string(STRINGIFY(name))] = eUiAnimNodeType_ ## name;
+    g_animNodeStringToEnumMap[AZStd::string(STRINGIFY(name))] = eUiAnimNodeType_ ## name;
 
 #define REGISTER_PARAM_TYPE(name) assert(g_animParamEnumToStringMap.find(eUiAnimParamType_ ## name) == g_animParamEnumToStringMap.end()); \
     g_animParamEnumToStringMap[eUiAnimParamType_ ## name] = STRINGIFY(name);                                                              \
-    g_animParamStringToEnumMap[string(STRINGIFY(name))] = eUiAnimParamType_ ## name;
+    g_animParamStringToEnumMap[AZStd::string(STRINGIFY(name))] = eUiAnimParamType_ ## name;
 
 namespace
 {
-    AZStd::unordered_map g_animNodeEnumToStringMap;
-    StaticInstance >> g_animNodeStringToEnumMap;
+    AZStd::unordered_map g_animNodeEnumToStringMap;
+    StaticInstance >> g_animNodeStringToEnumMap;
 
-    AZStd::unordered_map g_animParamEnumToStringMap;
-    StaticInstance >> g_animParamStringToEnumMap;
+    AZStd::unordered_map g_animParamEnumToStringMap;
+    StaticInstance >> g_animParamStringToEnumMap;
 
     // If you get an assert in this function, it means two node types have the same enum value.
     void RegisterNodeTypes()
@@ -1189,7 +1189,7 @@ void UiAnimationSystem::SerializeNodeType(EUiAnimNodeType& animNodeType, XmlNode
     {
         const char* pTypeString = "Invalid";
         assert(g_animNodeEnumToStringMap.find(animNodeType) != g_animNodeEnumToStringMap.end());
-        pTypeString = g_animNodeEnumToStringMap[animNodeType];
+        pTypeString = g_animNodeEnumToStringMap[animNodeType].c_str();
         xmlNode->setAttr(kType, pTypeString);
     }
 }
@@ -1273,7 +1273,7 @@ void UiAnimationSystem::SerializeParamType(CUiAnimParamType& animParamType, XmlN
         else
         {
             assert(g_animParamEnumToStringMap.find(animParamType.m_type) != g_animParamEnumToStringMap.end());
-            pTypeString = g_animParamEnumToStringMap[animParamType.m_type];
+            pTypeString = g_animParamEnumToStringMap[animParamType.m_type].c_str();
         }
 
         xmlNode->setAttr(kParamType, pTypeString);
@@ -1341,7 +1341,7 @@ const char* UiAnimationSystem::GetParamTypeName(const CUiAnimParamType& animPara
     {
         if (g_animParamEnumToStringMap.find(animParamType.m_type) != g_animParamEnumToStringMap.end())
         {
-            return g_animParamEnumToStringMap[animParamType.m_type];
+            return g_animParamEnumToStringMap[animParamType.m_type].c_str();
         }
     }
 
diff --git a/Gems/LyShine/Code/Source/LyShine.cpp b/Gems/LyShine/Code/Source/LyShine.cpp
index f5edc4d7f1..4e265bd973 100644
--- a/Gems/LyShine/Code/Source/LyShine.cpp
+++ b/Gems/LyShine/Code/Source/LyShine.cpp
@@ -287,7 +287,7 @@ AZ::EntityId CLyShine::CreateCanvas()
 }
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
-AZ::EntityId CLyShine::LoadCanvas(const string& assetIdPathname)
+AZ::EntityId CLyShine::LoadCanvas(const AZStd::string& assetIdPathname)
 {
     return m_uiCanvasManager->LoadCanvas(assetIdPathname.c_str());
 }
@@ -299,7 +299,7 @@ AZ::EntityId CLyShine::CreateCanvasInEditor(UiEntityContext* entityContext)
 }
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
-AZ::EntityId CLyShine::LoadCanvasInEditor(const string& assetIdPathname, const string& sourceAssetPathname, UiEntityContext* entityContext)
+AZ::EntityId CLyShine::LoadCanvasInEditor(const AZStd::string& assetIdPathname, const AZStd::string& sourceAssetPathname, UiEntityContext* entityContext)
 {
     return m_uiCanvasManager->LoadCanvasInEditor(assetIdPathname, sourceAssetPathname, entityContext);
 }
@@ -317,7 +317,7 @@ AZ::EntityId CLyShine::FindCanvasById(LyShine::CanvasId id)
 }
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
-AZ::EntityId CLyShine::FindLoadedCanvasByPathName(const string& assetIdPathname)
+AZ::EntityId CLyShine::FindLoadedCanvasByPathName(const AZStd::string& assetIdPathname)
 {
     return m_uiCanvasManager->FindLoadedCanvasByPathName(assetIdPathname.c_str());
 }
@@ -335,13 +335,13 @@ void CLyShine::ReleaseCanvasDeferred(AZ::EntityId canvas)
 }
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
-ISprite* CLyShine::LoadSprite(const string& pathname)
+ISprite* CLyShine::LoadSprite(const AZStd::string& pathname)
 {
     return CSprite::LoadSprite(pathname);
 }
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
-ISprite* CLyShine::CreateSprite(const string& renderTargetName)
+ISprite* CLyShine::CreateSprite(const AZStd::string& renderTargetName)
 {
     return CSprite::CreateSprite(renderTargetName);
 }
diff --git a/Gems/LyShine/Code/Source/LyShine.h b/Gems/LyShine/Code/Source/LyShine.h
index a7a8cab700..cb5b77a861 100644
--- a/Gems/LyShine/Code/Source/LyShine.h
+++ b/Gems/LyShine/Code/Source/LyShine.h
@@ -56,18 +56,18 @@ public:
     IDraw2d* GetDraw2d() override;
 
     AZ::EntityId CreateCanvas() override;
-    AZ::EntityId LoadCanvas(const string& assetIdPathname) override;
+    AZ::EntityId LoadCanvas(const AZStd::string& assetIdPathname) override;
     AZ::EntityId CreateCanvasInEditor(UiEntityContext* entityContext) override;
-    AZ::EntityId LoadCanvasInEditor(const string& assetIdPathname, const string& sourceAssetPathname, UiEntityContext* entityContext) override;
+    AZ::EntityId LoadCanvasInEditor(const AZStd::string& assetIdPathname, const AZStd::string& sourceAssetPathname, UiEntityContext* entityContext) override;
     AZ::EntityId ReloadCanvasFromXml(const AZStd::string& xmlString, UiEntityContext* entityContext) override;
     AZ::EntityId FindCanvasById(LyShine::CanvasId id) override;
-    AZ::EntityId FindLoadedCanvasByPathName(const string& assetIdPathname) override;
+    AZ::EntityId FindLoadedCanvasByPathName(const AZStd::string& assetIdPathname) override;
 
     void ReleaseCanvas(AZ::EntityId canvas, bool forEditor) override;
     void ReleaseCanvasDeferred(AZ::EntityId canvas) override;
 
-    ISprite* LoadSprite(const string& pathname) override;
-    ISprite* CreateSprite(const string& renderTargetName) override;
+    ISprite* LoadSprite(const AZStd::string& pathname) override;
+    ISprite* CreateSprite(const AZStd::string& renderTargetName) override;
     bool DoesSpriteTextureAssetExist(const AZStd::string& pathname) override;
 
     void PostInit() override;
diff --git a/Gems/LyShine/Code/Source/LyShineDebug.cpp b/Gems/LyShine/Code/Source/LyShineDebug.cpp
index c7ffea1aec..c7dccc162f 100644
--- a/Gems/LyShine/Code/Source/LyShineDebug.cpp
+++ b/Gems/LyShine/Code/Source/LyShineDebug.cpp
@@ -995,7 +995,7 @@ static AZ::Entity* CreateButton(const char* name, bool atRoot, AZ::EntityId pare
         EBUS_EVENT_ID(buttonId, UiInteractableStatesBus, SetStateColor, UiInteractableStatesInterface::StatePressed, buttonId, pressedColor);
         EBUS_EVENT_ID(buttonId, UiInteractableStatesBus, SetStateAlpha, UiInteractableStatesInterface::StatePressed, buttonId, pressedColor.GetA());
 
-        string pathname = "Textures/Basic/Button_Sliced_Normal.sprite";
+        AZStd::string pathname = "Textures/Basic/Button_Sliced_Normal.sprite";
         ISprite* sprite = gEnv->pLyShine->LoadSprite(pathname);
 
         EBUS_EVENT_ID(buttonId, UiImageBus, SetSprite, sprite);
@@ -1094,7 +1094,7 @@ static AZ::Entity* CreateTextInput(const char* name, bool atRoot, AZ::EntityId p
         EBUS_EVENT_ID(textInputId, UiInteractableStatesBus, SetStateColor, UiInteractableStatesInterface::StatePressed, textInputId, pressedColor);
         EBUS_EVENT_ID(textInputId, UiInteractableStatesBus, SetStateAlpha, UiInteractableStatesInterface::StatePressed, textInputId, pressedColor.GetA());
 
-        string pathname = "Textures/Basic/Button_Sliced_Normal.sprite";
+        AZStd::string pathname = "Textures/Basic/Button_Sliced_Normal.sprite";
         ISprite* sprite = gEnv->pLyShine->LoadSprite(pathname);
 
         EBUS_EVENT_ID(textInputId, UiImageBus, SetSprite, sprite);
diff --git a/Gems/LyShine/Code/Source/LyShineLoadScreen.cpp b/Gems/LyShine/Code/Source/LyShineLoadScreen.cpp
index 9d4f0bcc3c..64a577efa2 100644
--- a/Gems/LyShine/Code/Source/LyShineLoadScreen.cpp
+++ b/Gems/LyShine/Code/Source/LyShineLoadScreen.cpp
@@ -215,7 +215,7 @@ namespace LyShine
     AZ::EntityId LyShineLoadScreenComponent::loadFromCfg(const char* pathVarName, const char* autoPlayVarName)
     {
         ICVar* pathVar = gEnv->pConsole->GetCVar(pathVarName);
-        string path = pathVar ? pathVar->GetString() : "";
+        AZStd::string path = pathVar ? pathVar->GetString() : "";
         if (path.empty())
         {
             // No canvas specified.
@@ -238,7 +238,7 @@ namespace LyShine
         EBUS_EVENT_ID(canvasId, UiCanvasBus, SetDrawOrder, std::numeric_limits::max());
 
         ICVar* autoPlayVar = gEnv->pConsole->GetCVar(autoPlayVarName);
-        string sequence = autoPlayVar ? autoPlayVar->GetString() : "";
+        AZStd::string sequence = autoPlayVar ? autoPlayVar->GetString() : "";
         if (sequence.empty())
         {
             // Nothing to auto-play.
@@ -253,7 +253,7 @@ namespace LyShine
             return canvasId;
         }
 
-        animSystem->PlaySequence(sequence, nullptr, false, false);
+        animSystem->PlaySequence(sequence.c_str(), nullptr, false, false);
 
         return canvasId;
     }
diff --git a/Gems/LyShine/Code/Source/Platform/Windows/UiClipboard_Windows.cpp b/Gems/LyShine/Code/Source/Platform/Windows/UiClipboard_Windows.cpp
index 7bcdc26712..ae118aee00 100644
--- a/Gems/LyShine/Code/Source/Platform/Windows/UiClipboard_Windows.cpp
+++ b/Gems/LyShine/Code/Source/Platform/Windows/UiClipboard_Windows.cpp
@@ -9,6 +9,7 @@
 
 #include "UiClipboard.h"
 #include 
+#include 
 
 bool UiClipboard::SetText(const AZStd::string& text)
 {
@@ -19,7 +20,8 @@ bool UiClipboard::SetText(const AZStd::string& text)
         {
             if (text.length() > 0)
             {
-                auto wstr = CryStringUtils::UTF8ToWStr(text.c_str());
+                AZStd::wstring wstr;
+                AZStd::to_wstring(wstr, text.c_str());
                 const SIZE_T buffSize = (wstr.size() + 1) * sizeof(WCHAR);
                 if (HGLOBAL hBuffer = GlobalAlloc(GMEM_MOVEABLE, buffSize))
                 {
@@ -45,7 +47,7 @@ AZStd::string UiClipboard::GetText()
         if (HANDLE hText = GetClipboardData(CF_UNICODETEXT))
         {
             const WCHAR* text = static_cast(GlobalLock(hText));
-            outText = CryStringUtils::WStrToUTF8(text);
+            AZStd::to_string(outText, text);
             GlobalUnlock(hText);
         }
         CloseClipboard();
diff --git a/Gems/LyShine/Code/Source/Sprite.cpp b/Gems/LyShine/Code/Source/Sprite.cpp
index 134768f814..0e0edb8e34 100644
--- a/Gems/LyShine/Code/Source/Sprite.cpp
+++ b/Gems/LyShine/Code/Source/Sprite.cpp
@@ -146,9 +146,9 @@ namespace
     {
         if (ser.IsReading())
         {
-            string stringVal;
+            AZStd::string stringVal;
             ser.Value(attributeName, stringVal);
-            stringVal.replace(',', ' ');
+            AZ::StringFunc::Replace(stringVal, ',', ' ');
             char* pEnd = nullptr;
             float uVal = strtof(stringVal.c_str(), &pEnd);
             float vVal = strtof(pEnd, nullptr);
@@ -202,13 +202,13 @@ CSprite::~CSprite()
 }
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
-const string& CSprite::GetPathname() const
+const AZStd::string& CSprite::GetPathname() const
 {
     return m_pathname;
 }
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
-const string& CSprite::GetTexturePathname() const
+const AZStd::string& CSprite::GetTexturePathname() const
 {
     return m_texturePathname;
 }
@@ -283,7 +283,7 @@ void CSprite::Serialize(TSerialize ser)
                 m_spriteSheetCells.push_back(SpriteSheetCell());
             }
 
-            string aliasTemp;
+            AZStd::string aliasTemp;
             if (ser.IsReading())
             {
                 ser.Value("alias", aliasTemp);
@@ -318,7 +318,7 @@ void CSprite::Serialize(TSerialize ser)
 }
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
-bool CSprite::SaveToXml(const string& pathname)
+bool CSprite::SaveToXml(const AZStd::string& pathname)
 {
     // NOTE: The input pathname has to be a path that can used to save - so not an Asset ID
     // because of this we do not store the pathname
@@ -331,7 +331,7 @@ bool CSprite::SaveToXml(const string& pathname)
     ser.Value(spriteVersionNumberTag, spriteFileVersionNumber);
     Serialize(ser);
 
-    return root->saveToFile(pathname);
+    return root->saveToFile(pathname.c_str());
 }
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -629,7 +629,7 @@ void CSprite::Shutdown()
 }
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
-CSprite* CSprite::LoadSprite(const string& pathname)
+CSprite* CSprite::LoadSprite(const AZStd::string& pathname)
 {
     AZStd::string spritePath;
     AZStd::string texturePath;
@@ -691,7 +691,7 @@ CSprite* CSprite::LoadSprite(const string& pathname)
 }
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
-CSprite* CSprite::CreateSprite(const string& renderTargetName)
+CSprite* CSprite::CreateSprite(const AZStd::string& renderTargetName)
 {
     // test if the sprite is already loaded, if so return loaded sprite
     auto result = s_loadedSprites->find(renderTargetName);
diff --git a/Gems/LyShine/Code/Source/Sprite.h b/Gems/LyShine/Code/Source/Sprite.h
index e7e353a77b..8a645b78b1 100644
--- a/Gems/LyShine/Code/Source/Sprite.h
+++ b/Gems/LyShine/Code/Source/Sprite.h
@@ -32,13 +32,13 @@ public: // member functions
 
     ~CSprite() override;
 
-    const string& GetPathname() const override;
-    const string& GetTexturePathname() const override;
+    const AZStd::string& GetPathname() const override;
+    const AZStd::string& GetTexturePathname() const override;
     Borders GetBorders() const override;
     void SetBorders(Borders borders) override;
     void SetCellBorders(int cellIndex, Borders borders) override;
     void Serialize(TSerialize ser) override;
-    bool SaveToXml(const string& pathname) override;
+    bool SaveToXml(const AZStd::string& pathname) override;
     bool AreBordersZeroWidth() const override;
     bool AreCellBordersZeroWidth(int index) const override;
     AZ::Vector2 GetSize() override;
@@ -72,8 +72,8 @@ public: // static member functions
 
     static void Initialize();
     static void Shutdown();
-    static CSprite* LoadSprite(const string& pathname);
-    static CSprite* CreateSprite(const string& renderTargetName);
+    static CSprite* LoadSprite(const AZStd::string& pathname);
+    static CSprite* CreateSprite(const AZStd::string& renderTargetName);
     static bool DoesSpriteTextureAssetExist(const AZStd::string& pathname);
 
     //! Replaces baseSprite with newSprite with proper ref-count handling and null-checks.
@@ -96,7 +96,7 @@ protected: // member functions
     bool CellIndexWithinRange(int cellIndex) const;
 
 private: // types
-    typedef AZStd::unordered_map, stl::equality_string_caseless > CSpriteHashMap;
+    typedef AZStd::unordered_map, stl::equality_string_caseless > CSpriteHashMap;
 
 private: // member functions
     bool LoadFromXmlFile();
@@ -109,8 +109,8 @@ private: // data
 
     SpriteSheetCellContainer m_spriteSheetCells;  //!< Stores information for each cell defined within the sprite-sheet.
 
-    string m_pathname;
-    string m_texturePathname;
+    AZStd::string m_pathname;
+    AZStd::string m_texturePathname;
     Borders m_borders;
     AZ::Data::Instance m_image;
     int m_numSpriteSheetCellTags;                       //!< Number of Cell child-tags in sprite XML; unfortunately needed to help with serialization.
diff --git a/Gems/LyShine/Code/Source/StringUtfUtils.h b/Gems/LyShine/Code/Source/StringUtfUtils.h
index 74a27afe9f..40dd22dd33 100644
--- a/Gems/LyShine/Code/Source/StringUtfUtils.h
+++ b/Gems/LyShine/Code/Source/StringUtfUtils.h
@@ -7,6 +7,8 @@
  */
 #pragma once
 
+#include 
+
 namespace LyShine
 {
     //! \brief Returns the number of UTF8 characters in a string.
@@ -16,15 +18,9 @@ namespace LyShine
     //! character in the string.
     inline int GetUtf8StringLength(const AZStd::string& utf8String)
     {
-        int utf8StrLen = 0;
-        Unicode::CIterator pChar(utf8String.c_str());
-        while (uint32_t ch = *pChar)
-        {
-            ++pChar;
-            ++utf8StrLen;
-        }
-
-        return utf8StrLen;
+        AZStd::wstring utf8StringW;
+        AZStd::to_wstring(utf8StringW, utf8String.c_str());
+        return static_cast(utf8StringW.size());
     }
 
     //! \brief Returns the number of bytes of the size of the given multi-byte char.
@@ -34,17 +30,16 @@ namespace LyShine
         // NOTE: this assumes the uint32_t can be interpreted as a wchar_t, it seems to
         // work for cases tested but may not in general.
         // In the long run it would be better to eliminate
-        // this function and use Unicode::CIterator<>::Position instead.
-        wchar_t wcharString[2] = { static_cast(multiByteChar), 0 };
-        AZStd::string utf8String(CryStringUtils::WStrToUTF8(wcharString));
-        int utf8Length = utf8String.length();
-        return utf8Length;
+        // this function and use some sequence_lenght function that is not internal.
+        return Utf8::Internal::sequence_length(&multiByteChar);
     }
 
     inline int GetByteLengthOfUtf8Chars(const char* utf8String, int numUtf8Chars)
     {
+        AZStd::wstring utf8StringW;
+        AZStd::to_wstring(utf8StringW, utf8String);
+        AZStd::wstring::const_iterator pChar = utf8StringW.begin();
         int byteStrlen = 0;
-        Unicode::CIterator pChar(utf8String);
         for (int i = 0; i < numUtf8Chars; i++)
         {
             uint32_t ch = *pChar;
diff --git a/Gems/LyShine/Code/Source/Tests/internal/test_UiTextComponent.cpp b/Gems/LyShine/Code/Source/Tests/internal/test_UiTextComponent.cpp
index 3cd137b25f..8cf2cd2edb 100644
--- a/Gems/LyShine/Code/Source/Tests/internal/test_UiTextComponent.cpp
+++ b/Gems/LyShine/Code/Source/Tests/internal/test_UiTextComponent.cpp
@@ -3508,7 +3508,7 @@ void UiTextComponent::UnitTestLocalization(CLyShine* lyshine, IConsoleCmdArgs* /
 {
     ILocalizationManager* pLocMan = GetISystem()->GetLocalizationManager();
 
-    string localizationXml("libs/localization/localization.xml");
+    AZStd::string localizationXml("libs/localization/localization.xml");
 
     bool initLocSuccess = false;
 
diff --git a/Gems/LyShine/Code/Source/TextMarkup.cpp b/Gems/LyShine/Code/Source/TextMarkup.cpp
index 864d7a2cfc..8c1a6e0b62 100644
--- a/Gems/LyShine/Code/Source/TextMarkup.cpp
+++ b/Gems/LyShine/Code/Source/TextMarkup.cpp
@@ -162,7 +162,8 @@ namespace
                     }
                     else if (AZStd::string(key) == "color")
                     {
-                        AZStd::string colorValue(string(value).Trim());
+                        AZStd::string colorValue(value);
+                        AZ::StringFunc::TrimWhiteSpace(colorValue, true, true);
                         AZStd::string::size_type ExpectedNumChars = 7;
                         if (ExpectedNumChars == colorValue.size() && '#' == colorValue.at(0))
                         {
diff --git a/Gems/LyShine/Code/Source/UiCanvasComponent.cpp b/Gems/LyShine/Code/Source/UiCanvasComponent.cpp
index 72d9f92d1f..b665f039b0 100644
--- a/Gems/LyShine/Code/Source/UiCanvasComponent.cpp
+++ b/Gems/LyShine/Code/Source/UiCanvasComponent.cpp
@@ -177,11 +177,11 @@ namespace
 
     ////////////////////////////////////////////////////////////////////////////////////////////////
     // test if the given text file starts with the given text string
-    bool TestFileStartString(const string& pathname, const char* expectedStart)
+    bool TestFileStartString(const AZStd::string& pathname, const char* expectedStart)
     {
         // Open the file using CCryFile, this supports it being in the pak file or a standalone file
         CCryFile file;
-        if (!file.Open(pathname, "r"))
+        if (!file.Open(pathname.c_str(), "r"))
         {
             return false;
         }
@@ -208,7 +208,7 @@ namespace
 
     ////////////////////////////////////////////////////////////////////////////////////////////////
     // Check if the given file was saved using AZ serialization
-    bool IsValidAzSerializedFile(const string& pathname)
+    bool IsValidAzSerializedFile(const AZStd::string& pathname)
     {
         return TestFileStartString(pathname, " dstData;
@@ -3884,7 +3884,7 @@ UiCanvasComponent* UiCanvasComponent::CreateCanvasInternal(UiEntityContext* enti
 }
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
-UiCanvasComponent*  UiCanvasComponent::LoadCanvasInternal(const string& pathnameToOpen, bool forEditor, const string& assetIdPathname, UiEntityContext* entityContext,
+UiCanvasComponent*  UiCanvasComponent::LoadCanvasInternal(const AZStd::string& pathnameToOpen, bool forEditor, const AZStd::string& assetIdPathname, UiEntityContext* entityContext,
     const AZ::SliceComponent::EntityIdToEntityIdMap* previousRemapTable, AZ::EntityId previousCanvasId)
 {
     UiCanvasComponent* canvasComponent = nullptr;
diff --git a/Gems/LyShine/Code/Source/UiCanvasComponent.h b/Gems/LyShine/Code/Source/UiCanvasComponent.h
index 852bb482d0..097f23cbda 100644
--- a/Gems/LyShine/Code/Source/UiCanvasComponent.h
+++ b/Gems/LyShine/Code/Source/UiCanvasComponent.h
@@ -99,7 +99,7 @@ public: // member functions
     LyShine::EntityArray PickElements(const AZ::Vector2& bound0, const AZ::Vector2& bound1) override;
     AZ::EntityId FindInteractableToHandleEvent(AZ::Vector2 point) override;
 
-    bool SaveToXml(const string& assetIdPathname, const string& sourceAssetPathname) override;
+    bool SaveToXml(const AZStd::string& assetIdPathname, const AZStd::string& sourceAssetPathname) override;
     void FixupCreatedEntities(LyShine::EntityArray topLevelEntities, bool makeUniqueNamesAndIds, AZ::Entity* optionalInsertionPoint) override;
     void AddElement(AZ::Entity* element, AZ::Entity* parent, AZ::Entity* insertBefore) override;
     void ReinitializeElements() override;
@@ -307,7 +307,7 @@ public: // static member functions
     static void Shutdown();
 
     static UiCanvasComponent* CreateCanvasInternal(UiEntityContext* entityContext, bool forEditor);
-    static UiCanvasComponent* LoadCanvasInternal(const string& pathToOpen, bool forEditor, const string& assetIdPathname, UiEntityContext* entityContext,
+    static UiCanvasComponent* LoadCanvasInternal(const AZStd::string& pathToOpen, bool forEditor, const AZStd::string& assetIdPathname, UiEntityContext* entityContext,
         const AZ::SliceComponent::EntityIdToEntityIdMap* previousRemapTable = nullptr, AZ::EntityId previousCanvasId = AZ::EntityId());
     static UiCanvasComponent* FixupReloadedCanvasForEditorInternal(AZ::Entity* newCanvasEntity,
         AZ::Entity* rootSliceEntity, UiEntityContext* entityContext,
@@ -403,7 +403,7 @@ private: // member functions
     void DestroyRenderTarget();
     void RenderCanvasToTexture();
 
-    bool SaveCanvasToFile(const string& pathname, AZ::DataStream::StreamType streamType);
+    bool SaveCanvasToFile(const AZStd::string& pathname, AZ::DataStream::StreamType streamType);
     bool SaveCanvasToStream(AZ::IO::GenericStream& stream, AZ::DataStream::StreamType streamType);
 
     //! Notify elements that their canvas space rect has changed since the last update, and recompute invalid layouts
diff --git a/Gems/LyShine/Code/Source/UiCanvasManager.cpp b/Gems/LyShine/Code/Source/UiCanvasManager.cpp
index cb27f09672..bed3bcf433 100644
--- a/Gems/LyShine/Code/Source/UiCanvasManager.cpp
+++ b/Gems/LyShine/Code/Source/UiCanvasManager.cpp
@@ -342,7 +342,7 @@ void UiCanvasManager::OnCatalogAssetChanged(const AZ::Data::AssetId& assetId)
 
             // reload canvas with the same entity IDs (except for new entities, deleted entities etc)
             UiGameEntityContext* entityContext = new UiGameEntityContext();
-            string pathname(assetPath.c_str());
+            AZStd::string pathname(assetPath.c_str());
             UiCanvasComponent* newCanvasComponent = UiCanvasComponent::LoadCanvasInternal(pathname, false, "", entityContext, &existingRemapTable, existingCanvasEntityId);
 
             if (!newCanvasComponent)
@@ -393,7 +393,7 @@ AZ::EntityId UiCanvasManager::CreateCanvasInEditor(UiEntityContext* entityContex
 }
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
-AZ::EntityId UiCanvasManager::LoadCanvasInEditor(const string& assetIdPathname, const string& sourceAssetPathname, UiEntityContext* entityContext)
+AZ::EntityId UiCanvasManager::LoadCanvasInEditor(const AZStd::string& assetIdPathname, const AZStd::string& sourceAssetPathname, UiEntityContext* entityContext)
 {
     return LoadCanvasInternal(assetIdPathname.c_str(), true, sourceAssetPathname.c_str(), entityContext);
 }
@@ -1064,10 +1064,10 @@ void UiCanvasManager::DebugDisplayCanvasData(int setting) const
     for (auto canvas : m_loadedCanvases)
     {
         // Name
-        const string pathname = canvas->GetPathname().c_str();
+        const AZStd::string pathname = canvas->GetPathname().c_str();
         size_t lastDot = pathname.find_last_of(".");
         size_t lastSlash = pathname.find_last_of("/");
-        string leafName = pathname;
+        AZStd::string leafName = pathname;
         if (lastDot > lastSlash)
         {
             leafName = pathname.substr(lastSlash+1, lastDot-lastSlash-1);
@@ -1209,10 +1209,10 @@ void UiCanvasManager::DebugDisplayDrawCallData() const
     for (auto canvas : m_loadedCanvases)
     {
         // Name
-        const string pathname = canvas->GetPathname().c_str();
+        const AZStd::string pathname = canvas->GetPathname().c_str();
         size_t lastDot = pathname.find_last_of(".");
         size_t lastSlash = pathname.find_last_of("/");
-        string leafName = pathname;
+        AZStd::string leafName = pathname;
         if (lastDot > lastSlash)
         {
             leafName = pathname.substr(lastSlash+1, lastDot-lastSlash-1);
@@ -1373,7 +1373,7 @@ void UiCanvasManager::DebugReportDrawCalls(const AZStd::string& name) const
         }
 
         // Name of canvas
-        const string pathname = canvas->GetPathname().c_str();
+        const AZStd::string pathname = canvas->GetPathname().c_str();
         logLine = "\r\n=====================================================================================\r\n";
         AZ::IO::LocalFileIO::GetInstance()->Write(logHandle, logLine.c_str(), logLine.size());
         logLine = AZStd::string::format("Canvas: %s\r\n", pathname.c_str());
@@ -1461,7 +1461,7 @@ void UiCanvasManager::DebugReportDrawCalls(const AZStd::string& name) const
                 {
                     if (!loggedCanvasHeader)
                     {
-                        const string pathname = canvas->GetPathname().c_str();
+                        const AZStd::string pathname = canvas->GetPathname().c_str();
                         logLine = AZStd::string::format("\r\nCanvas: %s\r\n\r\n", pathname.c_str());
                         AZ::IO::LocalFileIO::GetInstance()->Write(logHandle, logLine.c_str(), logLine.size());
                         loggedCanvasHeader = true;
diff --git a/Gems/LyShine/Code/Source/UiCanvasManager.h b/Gems/LyShine/Code/Source/UiCanvasManager.h
index 85783fab84..ebcee200e4 100644
--- a/Gems/LyShine/Code/Source/UiCanvasManager.h
+++ b/Gems/LyShine/Code/Source/UiCanvasManager.h
@@ -68,7 +68,7 @@ public: // member functions
     // ~AssetCatalogEventBus::Handler
 
     AZ::EntityId CreateCanvasInEditor(UiEntityContext* entityContext);
-    AZ::EntityId LoadCanvasInEditor(const string& assetIdPathname, const string& sourceAssetPathname, UiEntityContext* entityContext);
+    AZ::EntityId LoadCanvasInEditor(const AZStd::string& assetIdPathname, const AZStd::string& sourceAssetPathname, UiEntityContext* entityContext);
     AZ::EntityId ReloadCanvasFromXml(const AZStd::string& xmlString, UiEntityContext* entityContext);
 
     void ReleaseCanvas(AZ::EntityId canvas, bool forEditor);
diff --git a/Gems/LyShine/Code/Source/UiDropdownComponent.cpp b/Gems/LyShine/Code/Source/UiDropdownComponent.cpp
index 1940d57cbb..448c208c5e 100644
--- a/Gems/LyShine/Code/Source/UiDropdownComponent.cpp
+++ b/Gems/LyShine/Code/Source/UiDropdownComponent.cpp
@@ -826,7 +826,8 @@ AZ::Outcome UiDropdownComponent::ValidatePotentialExpandedP
 }
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
-AZ::FailureValue FailureMessage(string message) {
+AZ::FailureValue FailureMessage(AZStd::string message)
+{
     return AZ::Failure(AZStd::string(message));
 }
 
diff --git a/Gems/LyShine/Code/Source/UiInteractableState.cpp b/Gems/LyShine/Code/Source/UiInteractableState.cpp
index d3440a9354..98abae4484 100644
--- a/Gems/LyShine/Code/Source/UiInteractableState.cpp
+++ b/Gems/LyShine/Code/Source/UiInteractableState.cpp
@@ -575,7 +575,7 @@ void UiInteractableStateFont::SetFontPathname(const AZStd::string& pathname)
             fontFamily = gEnv->pCryFont->LoadFontFamily(fileName.c_str());
             if (!fontFamily)
             {
-                string errorMsg = "Error loading a font from ";
+                AZStd::string errorMsg = "Error loading a font from ";
                 errorMsg += fileName.c_str();
                 errorMsg += ".";
                 CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_ERROR, errorMsg.c_str());
diff --git a/Gems/LyShine/Code/Source/UiTextComponent.cpp b/Gems/LyShine/Code/Source/UiTextComponent.cpp
index fadf09571f..be26a5a618 100644
--- a/Gems/LyShine/Code/Source/UiTextComponent.cpp
+++ b/Gems/LyShine/Code/Source/UiTextComponent.cpp
@@ -623,12 +623,14 @@ namespace
 
             int batchCurChar = 0;
 
-            Unicode::CIterator pChar(drawBatch.text.c_str());
+            Utf8::Unchecked::octet_iterator pChar(drawBatch.text.data());
             uint32_t prevCh = 0;
             while (uint32_t ch = *pChar)
             {
-                char codepoint[5];
-                Unicode::Convert(codepoint, ch);
+                size_t maxSize = 5;
+                char codepoint[5] = { 0 };
+                char* codepointPtr = codepoint;
+                Utf8::Unchecked::octet_iterator::to_utf8_sequence(ch, codepointPtr, maxSize);
 
                 float curCharWidth = drawBatch.font->GetTextSize(codepoint, true, ctx).x;
 
@@ -652,15 +654,15 @@ namespace
                     lastSpaceIndexInBatch = batchCurChar;
                     lastSpaceBatch = &drawBatch;
                     lastSpaceWidth = curLineWidth + curCharWidth;
-                    pLastSpace = pChar.GetPosition();
+                    pLastSpace = pChar.base();
                     assert(*pLastSpace == ' ');
                 }
 
                 bool prevCharWasNewline = false;
-                const bool isFirstChar = pChar.GetPosition() == drawBatch.text.c_str();
+                const bool isFirstChar = pChar.base() == drawBatch.text.c_str();
                 if (ch && !isFirstChar)
                 {
-                    const char* pPrevCharStr = pChar.GetPosition() - 1;
+                    const char* pPrevCharStr = pChar.base() - 1;
                     prevCharWasNewline = pPrevCharStr[0] == '\n';
                 }
                 else if (isFirstChar)
@@ -705,12 +707,12 @@ namespace
                     }
                     else
                     {
-                        const char* pBuf = pChar.GetPosition();
+                        char* pBuf = pChar.base();
                         AZStd::string::size_type bytesProcessed = pBuf - drawBatch.text.c_str();
                         drawBatch.text.insert(bytesProcessed, "\n"); // Insert the newline, this invalidates the iterator
-                        pBuf = drawBatch.text.c_str() + bytesProcessed; // In case reallocation occurs, we ensure we are inside the new buffer
+                        pBuf = drawBatch.text.data() + bytesProcessed; // In case reallocation occurs, we ensure we are inside the new buffer
                         assert(*pBuf == '\n');
-                        pChar.SetPosition(pBuf); // pChar once again points inside the target string, at the current character
+                        pChar = Utf8::Unchecked::octet_iterator(pBuf); // pChar once again points inside the target string, at the current character
                         assert(*pChar == ch);
                         ++pChar;
                         ++curChar;
@@ -1189,7 +1191,7 @@ void UiTextComponent::DrawBatch::CalculateSize(const STextDrawContext& ctx, bool
             if (displayString.length() > 0)
             {
                 AZStd::string::size_type endpos = displayString.find_last_not_of(" \t\n\v\f\r");
-                if ((endpos != string::npos) && (endpos != displayString.length() - 1))
+                if ((endpos != AZStd::string::npos) && (endpos != displayString.length() - 1))
                 {
                     displayString.erase(endpos + 1);
                 }
@@ -1295,12 +1297,14 @@ bool UiTextComponent::DrawBatch::GetOverflowInfo(const STextDrawContext& ctx,
 
         float maxEffectOffsetX = font->GetMaxEffectOffset(ctx.m_fxIdx).x;
 
-        Unicode::CIterator pChar(text.c_str());
+        Utf8::Unchecked::octet_iterator pChar(text.data());
         uint32_t prevCh = 0;
         while (uint32_t ch = *pChar)
         {
-            char codepoint[5];
-            Unicode::Convert(codepoint, ch);
+            size_t maxSize = 5;
+            char codepoint[5] = { 0 };
+            char* codepointPtr = codepoint;
+            Utf8::Unchecked::octet_iterator::to_utf8_sequence(ch, codepointPtr, maxSize);
 
             float curCharWidth = font->GetTextSize(codepoint, true, ctx).x;
             if (prevCh)
@@ -2274,7 +2278,7 @@ int UiTextComponent::GetCharIndexFromCanvasSpacePoint(AZ::Vector2 point, bool mu
         // Iterate across the line
         for (const DrawBatch& drawBatch : batchLine.drawBatchList)
         {
-            Unicode::CIterator pChar(drawBatch.text.c_str());
+            Utf8::Unchecked::octet_iterator pChar(drawBatch.text.data());
             while (uint32_t ch = *pChar)
             {
                 ++pChar;
@@ -4827,14 +4831,16 @@ int UiTextComponent::GetStartEllipseIndexInDrawBatch(const DrawBatch* drawBatchT
 {
     float overflowStringSize = 0.0f;
     int ellipsisCharPos = 0;
-    Unicode::CIterator pChar(drawBatchToEllipse->text.c_str());
+    Utf8::Unchecked::octet_iterator pChar(drawBatchToEllipse->text.data());
     uint32_t stringBufferIndex = 0;
     uint32_t prevCh = 0;
     while (uint32_t ch = *pChar)
     {
         ++pChar;
-        char codepoint[5];
-        Unicode::Convert(codepoint, ch);
+        size_t maxSize = 5;
+        char codepoint[5] = { 0 };
+        char* codepointPtr = codepoint;
+        Utf8::Unchecked::octet_iterator::to_utf8_sequence(ch, codepointPtr, maxSize);
         
         overflowStringSize += drawBatchToEllipse->font->GetTextSize(codepoint, true, ctx).x;
 
@@ -4925,7 +4931,7 @@ AZ::Vector2 UiTextComponent::GetTextSizeFromDrawBatchLines(const UiTextComponent
 ////////////////////////////////////////////////////////////////////////////////////////////////////
 AZStd::string UiTextComponent::GetLocalizedText([[maybe_unused]] const AZStd::string& text)
 {
-    string locText;
+    AZStd::string locText;
     LocalizationManagerRequestBus::Broadcast(&LocalizationManagerRequestBus::Events::LocalizeString_ch, m_text.c_str(), locText, false);
     return locText.c_str();
 }
@@ -5110,7 +5116,7 @@ int UiTextComponent::GetLineNumberFromCharIndex(const DrawBatchLines& drawBatchL
 
         for (const DrawBatch& drawBatch : batchLine.drawBatchList)
         {
-            Unicode::CIterator pChar(drawBatch.text.c_str());
+            Utf8::Unchecked::octet_iterator pChar(drawBatch.text.data());
             while (uint32_t ch = *pChar)
             {
                 ++pChar;
diff --git a/Gems/LyShine/Code/Source/UiTextComponentOffsetsSelector.cpp b/Gems/LyShine/Code/Source/UiTextComponentOffsetsSelector.cpp
index b4e8a8d63e..b472f79bd6 100644
--- a/Gems/LyShine/Code/Source/UiTextComponentOffsetsSelector.cpp
+++ b/Gems/LyShine/Code/Source/UiTextComponentOffsetsSelector.cpp
@@ -30,7 +30,7 @@ void UiTextComponentOffsetsSelector::ParseBatchLine(const UiTextComponent::DrawB
     {
         // Iterate character by character over DrawBatch string contents,
         // looking for m_firstIndex and m_lastIndex.
-        Unicode::CIterator pChar(drawBatch.text.c_str());
+        Utf8::Unchecked::octet_iterator pChar(drawBatch.text.data());
         while (uint32_t ch = *pChar)
         {
             ++pChar;
diff --git a/Gems/LyShine/Code/Source/UiTextInputComponent.cpp b/Gems/LyShine/Code/Source/UiTextInputComponent.cpp
index c149c5a4d4..8cc0efcaaf 100644
--- a/Gems/LyShine/Code/Source/UiTextInputComponent.cpp
+++ b/Gems/LyShine/Code/Source/UiTextInputComponent.cpp
@@ -70,7 +70,7 @@ namespace
         if (stringLength > 0 && stringLength >= utf8Index)
         {
             // Iterate over the string until the given index is found.
-            Unicode::CIterator pChar(utf8String.c_str());
+            Utf8::Unchecked::octet_iterator pChar(utf8String.data());
             while (uint32_t ch = *pChar)
             {
                 if (utf8Index == utfIndexIter)
@@ -1185,7 +1185,8 @@ void UiTextInputComponent::UpdateDisplayedTextFunction()
                 // NOTE: this assumes the uint32_t can be interpreted as a wchar_t, it seems to
                 // work for cases tested but may not in general.
                 wchar_t wcharString[2] = { static_cast(this->GetReplacementCharacter()), 0 };
-                AZStd::string replacementCharString(CryStringUtils::WStrToUTF8(wcharString));
+                AZStd::string replacementCharString;
+                AZStd::to_string(replacementCharString, wcharString, 1);
 
                 int numReplacementChars = LyShine::GetUtf8StringLength(originalText);
 

From ad14d9cdd7a65ef44decde1ada4bb76741ba4a29 Mon Sep 17 00:00:00 2001
From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>
Date: Mon, 2 Aug 2021 17:55:27 -0700
Subject: [PATCH 073/803] AtomFont

Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>
---
 .../AtomFont/Code/Include/AtomLyIntegration/AtomFont/FBitmap.h  | 2 +-
 .../AtomFont/Code/Platform/Common/FontTexture_Common.cpp        | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/FBitmap.h b/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/FBitmap.h
index 0e97440538..6443633245 100644
--- a/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/FBitmap.h
+++ b/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/FBitmap.h
@@ -26,7 +26,7 @@ namespace AZ
         int Create(int width, int height);
         int Release();
 
-        int SaveBitmap(const string& fileName);
+        int SaveBitmap(const AZStd::string& fileName);
         int Get32Bpp(unsigned int** buffer)
         {
             (*buffer) = new unsigned int[m_width * m_height];
diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Platform/Common/FontTexture_Common.cpp b/Gems/AtomLyIntegration/AtomFont/Code/Platform/Common/FontTexture_Common.cpp
index 02cbb5a7a4..e3be52965c 100644
--- a/Gems/AtomLyIntegration/AtomFont/Code/Platform/Common/FontTexture_Common.cpp
+++ b/Gems/AtomLyIntegration/AtomFont/Code/Platform/Common/FontTexture_Common.cpp
@@ -11,7 +11,7 @@
 #include 
 
 //-------------------------------------------------------------------------------------------------
-int AZ::FontTexture::WriteToFile([[maybe_unused]] const string& fileName)
+int AZ::FontTexture::WriteToFile([[maybe_unused]] const AZStd::string& fileName)
 {
     return 1;
 }

From b1e9d81d96b2d30cd5e3a82dcb6503f7617ac73c Mon Sep 17 00:00:00 2001
From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>
Date: Mon, 2 Aug 2021 17:55:55 -0700
Subject: [PATCH 074/803] Gems/GameStateSamples

Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>
---
 .../GameStateSamples/GameStatePrimaryControllerDisconnected.inl | 2 +-
 .../Include/GameStateSamples/GameStatePrimaryUserSignedOut.inl  | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/Gems/GameStateSamples/Code/Include/GameStateSamples/GameStatePrimaryControllerDisconnected.inl b/Gems/GameStateSamples/Code/Include/GameStateSamples/GameStatePrimaryControllerDisconnected.inl
index 4e9fb33c7e..ded069a638 100644
--- a/Gems/GameStateSamples/Code/Include/GameStateSamples/GameStatePrimaryControllerDisconnected.inl
+++ b/Gems/GameStateSamples/Code/Include/GameStateSamples/GameStatePrimaryControllerDisconnected.inl
@@ -83,7 +83,7 @@ namespace GameStateSamples
             return;
         }
 
-        string localizedMessage;
+        AZStd::string localizedMessage;
         const char* localizationKey = AZ_TRAIT_GAMESTATESAMPLES_PRIMARY_CONTROLLER_DISCONNECTED_LOC_KEY;
         bool wasLocalized = false;
         LocalizationManagerRequestBus::BroadcastResult(wasLocalized,
diff --git a/Gems/GameStateSamples/Code/Include/GameStateSamples/GameStatePrimaryUserSignedOut.inl b/Gems/GameStateSamples/Code/Include/GameStateSamples/GameStatePrimaryUserSignedOut.inl
index d7e45fcbdd..62fa9710dc 100644
--- a/Gems/GameStateSamples/Code/Include/GameStateSamples/GameStatePrimaryUserSignedOut.inl
+++ b/Gems/GameStateSamples/Code/Include/GameStateSamples/GameStatePrimaryUserSignedOut.inl
@@ -99,7 +99,7 @@ namespace GameStateSamples
             return;
         }
 
-        string localizedMessage;
+        AZStd::string localizedMessage;
         const char* localizationKey = "@PRIMARY_CONTROLLER_DISCONNECTED_LOC_KEY";
         bool wasLocalized = false;
         LocalizationManagerRequestBus::BroadcastResult(wasLocalized,

From 3b28267569005e7eed1f88b0ce082a129898b454 Mon Sep 17 00:00:00 2001
From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>
Date: Mon, 2 Aug 2021 17:56:28 -0700
Subject: [PATCH 075/803] Gems/PhysXDebug

Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>
---
 Gems/PhysXDebug/Code/Source/SystemComponent.cpp | 1 -
 Gems/PhysXDebug/Code/Source/SystemComponent.h   | 1 +
 2 files changed, 1 insertion(+), 1 deletion(-)

diff --git a/Gems/PhysXDebug/Code/Source/SystemComponent.cpp b/Gems/PhysXDebug/Code/Source/SystemComponent.cpp
index 0ccc77bba4..4944626d77 100644
--- a/Gems/PhysXDebug/Code/Source/SystemComponent.cpp
+++ b/Gems/PhysXDebug/Code/Source/SystemComponent.cpp
@@ -30,7 +30,6 @@
 #include 
 
 #include 
-#include 
 
 #include 
 
diff --git a/Gems/PhysXDebug/Code/Source/SystemComponent.h b/Gems/PhysXDebug/Code/Source/SystemComponent.h
index 40434ad3e1..83756f20f9 100644
--- a/Gems/PhysXDebug/Code/Source/SystemComponent.h
+++ b/Gems/PhysXDebug/Code/Source/SystemComponent.h
@@ -18,6 +18,7 @@
 
 #include 
 #include 
+#include 
 
 #include 
 

From a14b4e478ee4b893fca85f00f56e4f4378f1d6e3 Mon Sep 17 00:00:00 2001
From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>
Date: Mon, 2 Aug 2021 17:56:56 -0700
Subject: [PATCH 076/803] Code/Editor

Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>
---
 Code/Editor/BaseLibraryManager.cpp            |   4 +-
 Code/Editor/Commands/CommandManager.cpp       |  71 +-
 Code/Editor/Commands/CommandManager.h         |   8 +-
 Code/Editor/ConfigGroup.cpp                   |   6 +-
 Code/Editor/ConfigGroup.h                     |   4 +-
 Code/Editor/Controls/ConsoleSCB.cpp           |   4 +-
 Code/Editor/Controls/FolderTreeCtrl.cpp       |   2 +-
 .../PropertyGenericCtrl.cpp                   |   4 +-
 Code/Editor/Controls/SplineCtrlEx.cpp         |   2 +-
 Code/Editor/Controls/SplineCtrlEx.h           |   2 +-
 Code/Editor/Core/QtEditorApplication.cpp      |   2 +-
 Code/Editor/Core/Tests/test_Main.cpp          |   2 +-
 Code/Editor/CryEdit.cpp                       |  38 +-
 Code/Editor/CryEdit.h                         |  24 +-
 Code/Editor/CryEditDoc.cpp                    |   8 +-
 Code/Editor/CryEditDoc.h                      |   2 +-
 Code/Editor/CryEditPy.cpp                     |   4 +-
 Code/Editor/EditorFileMonitor.cpp             |  12 +-
 Code/Editor/GameExporter.cpp                  |  10 +-
 Code/Editor/IEditorImpl.cpp                   |  33 +-
 Code/Editor/Include/Command.h                 |  24 +-
 Code/Editor/LevelFileDialog.cpp               |   6 +-
 Code/Editor/LogFile.cpp                       |  26 +-
 Code/Editor/MainWindow.cpp                    |   2 +-
 .../Platform/Windows/Util/Mailer_Windows.cpp  |   4 +-
 Code/Editor/PluginManager.cpp                 |   4 +-
 .../EditorAssetImporter/AssetImporterPlugin.h |   2 +-
 Code/Editor/ResourceSelectorHost.cpp          |   4 +-
 Code/Editor/SelectSequenceDialog.cpp          |   2 +-
 Code/Editor/ToolBox.cpp                       |  10 +-
 .../Editor/TrackView/CommentKeyUIControls.cpp |   2 +-
 .../TrackView/SequenceKeyUIControls.cpp       |   2 +-
 Code/Editor/TrackView/TrackViewAnimNode.cpp   |   4 +-
 Code/Editor/TrackView/TrackViewFindDlg.cpp    |   2 +-
 Code/Editor/TrackView/TrackViewNodes.cpp      |   2 +-
 Code/Editor/TrackView/TrackViewSequence.cpp   |   8 +-
 Code/Editor/TrackViewNewSequenceDialog.cpp    |   2 +-
 .../Util/AutoDirectoryRestoreFileDialog.cpp   |   2 +-
 Code/Editor/Util/FileUtil.cpp                 |  15 +-
 Code/Editor/Util/ImageASC.cpp                 |   3 +-
 Code/Editor/Util/ImageTIF.cpp                 |   6 +-
 Code/Editor/Util/ImageUtil.cpp                |   3 +-
 Code/Editor/Util/StringHelpers.cpp            | 847 +-----------------
 Code/Editor/Util/StringHelpers.h              | 188 +---
 Code/Editor/Util/XmlHistoryManager.cpp        |   6 +-
 Code/Editor/Util/XmlHistoryManager.h          |   2 +-
 Code/Legacy/CrySystem/XConsole.cpp            |   7 +-
 47 files changed, 208 insertions(+), 1219 deletions(-)

diff --git a/Code/Editor/BaseLibraryManager.cpp b/Code/Editor/BaseLibraryManager.cpp
index 2189156454..da41525d8b 100644
--- a/Code/Editor/BaseLibraryManager.cpp
+++ b/Code/Editor/BaseLibraryManager.cpp
@@ -526,7 +526,7 @@ void CBaseLibraryManager::Serialize(XmlNodeRef& node, bool bLoading)
 QString CBaseLibraryManager::MakeUniqueItemName(const QString& srcName, const QString& libName)
 {
     // unlikely we'll ever encounter more than 16
-    std::vector possibleDuplicates;
+    std::vector possibleDuplicates;
     possibleDuplicates.reserve(16);
 
     // search for strings in the database that might have a similar name (ignore case)
@@ -550,7 +550,7 @@ QString CBaseLibraryManager::MakeUniqueItemName(const QString& srcName, const QS
         const QString& name = pItem->GetName();
         if (name.startsWith(srcName, Qt::CaseInsensitive))
         {
-            possibleDuplicates.push_back(string(name.toUtf8().data()));
+            possibleDuplicates.push_back(AZStd::string(name.toUtf8().data()));
         }
     }
     pEnum->Release();
diff --git a/Code/Editor/Commands/CommandManager.cpp b/Code/Editor/Commands/CommandManager.cpp
index 708fccd16b..35f55babe2 100644
--- a/Code/Editor/Commands/CommandManager.cpp
+++ b/Code/Editor/Commands/CommandManager.cpp
@@ -79,9 +79,9 @@ CEditorCommandManager::~CEditorCommandManager()
     m_uiCommands.clear();
 }
 
-string CEditorCommandManager::GetFullCommandName(const AZStd::string& module, const string& name)
+AZStd::string CEditorCommandManager::GetFullCommandName(const AZStd::string& module, const AZStd::string& name)
 {
-    string fullName = module;
+    AZStd::string fullName = module;
     fullName += ".";
     fullName += name;
     return fullName;
@@ -91,10 +91,10 @@ bool CEditorCommandManager::AddCommand(CCommand* pCommand, TPfnDeleter deleter)
 {
     assert(pCommand);
 
-    string module = pCommand->GetModule();
-    string name = pCommand->GetName();
+    AZStd::string module = pCommand->GetModule();
+    AZStd::string name = pCommand->GetName();
 
-    if (IsRegistered(module, name) && m_bWarnDuplicate)
+    if (IsRegistered(module.c_str(), name.c_str()) && m_bWarnDuplicate)
     {
         QString errMsg;
 
@@ -118,7 +118,7 @@ bool CEditorCommandManager::AddCommand(CCommand* pCommand, TPfnDeleter deleter)
 
 bool CEditorCommandManager::UnregisterCommand(const char* module, const char* name)
 {
-    string fullName = GetFullCommandName(module, name);
+    AZStd::string fullName = GetFullCommandName(module, name);
     CommandTable::iterator itr = m_commands.find(fullName);
 
     if (itr != m_commands.end())
@@ -154,7 +154,7 @@ bool CEditorCommandManager::RegisterUICommand(
         return false;
     }
 
-    return AttachUIInfo(GetFullCommandName(module, name), uiInfo);
+    return AttachUIInfo(GetFullCommandName(module, name).c_str(), uiInfo);
 }
 
 bool CEditorCommandManager::AttachUIInfo(const char* fullCmdName, const CCommand0::SUIInfo& uiInfo)
@@ -190,14 +190,14 @@ bool CEditorCommandManager::AttachUIInfo(const char* fullCmdName, const CCommand
     return true;
 }
 
-bool CEditorCommandManager::GetUIInfo(const string& module, const string& name, CCommand0::SUIInfo& uiInfo) const
+bool CEditorCommandManager::GetUIInfo(const AZStd::string& module, const AZStd::string& name, CCommand0::SUIInfo& uiInfo) const
 {
-    string fullName = GetFullCommandName(module, name);
+    AZStd::string fullName = GetFullCommandName(module, name);
 
     return GetUIInfo(fullName, uiInfo);
 }
 
-bool CEditorCommandManager::GetUIInfo(const string& fullCmdName, CCommand0::SUIInfo& uiInfo) const
+bool CEditorCommandManager::GetUIInfo(const AZStd::string& fullCmdName, CCommand0::SUIInfo& uiInfo) const
 {
     CommandTable::const_iterator iter = m_commands.find(fullCmdName);
 
@@ -223,9 +223,9 @@ int CEditorCommandManager::GenNewCommandId()
     return uniqueId++;
 }
 
-QString CEditorCommandManager::Execute(const string& module, const string& name, const CCommand::CArgs& args)
+QString CEditorCommandManager::Execute(const AZStd::string& module, const AZStd::string& name, const CCommand::CArgs& args)
 {
-    string fullName = GetFullCommandName(module, name);
+    AZStd::string fullName = GetFullCommandName(module, name);
     CommandTable::iterator iter = m_commands.find(fullName);
 
     if (iter != m_commands.end())
@@ -245,18 +245,18 @@ QString CEditorCommandManager::Execute(const string& module, const string& name,
     return "";
 }
 
-QString CEditorCommandManager::Execute(const string& cmdLine)
+QString CEditorCommandManager::Execute(const AZStd::string& cmdLine)
 {
-    string cmdTxt, argsTxt;
+    AZStd::string cmdTxt, argsTxt;
     size_t argStart = cmdLine.find_first_of(' ');
 
     cmdTxt = cmdLine.substr(0, argStart);
     argsTxt = "";
 
-    if (argStart != string::npos)
+    if (argStart != AZStd::string::npos)
     {
         argsTxt = cmdLine.substr(argStart + 1);
-        argsTxt.Trim();
+        AZ::StringFunc::TrimWhiteSpace(argsTxt, true, true);
     }
 
     CommandTable::iterator itr = m_commands.find(cmdTxt);
@@ -301,7 +301,7 @@ void CEditorCommandManager::Execute(int commandId)
     }
 }
 
-void CEditorCommandManager::GetCommandList(std::vector& cmds) const
+void CEditorCommandManager::GetCommandList(std::vector& cmds) const
 {
     cmds.clear();
     cmds.reserve(m_commands.size());
@@ -315,9 +315,9 @@ void CEditorCommandManager::GetCommandList(std::vector& cmds) const
     std::sort(cmds.begin(), cmds.end());
 }
 
-string CEditorCommandManager::AutoComplete(const string& substr) const
+AZStd::string CEditorCommandManager::AutoComplete(const AZStd::string& substr) const
 {
-    std::vector cmds;
+    std::vector cmds;
     GetCommandList(cmds);
 
     // If substring is empty return first command.
@@ -358,7 +358,7 @@ string CEditorCommandManager::AutoComplete(const string& substr) const
 
 bool CEditorCommandManager::IsRegistered(const char* module, const char* name) const
 {
-    string fullName = GetFullCommandName(module, name);
+    AZStd::string fullName = GetFullCommandName(module, name);
     CommandTable::const_iterator iter = m_commands.find(fullName);
 
     if (iter != m_commands.end())
@@ -373,7 +373,7 @@ bool CEditorCommandManager::IsRegistered(const char* module, const char* name) c
 
 bool CEditorCommandManager::IsRegistered(const char* cmdLine_) const
 {
-    string cmdTxt, argsTxt, cmdLine(cmdLine_);
+    AZStd::string cmdTxt, argsTxt, cmdLine(cmdLine_);
     size_t argStart = cmdLine.find_first_of(' ');
     cmdTxt = cmdLine.substr(0, argStart);
     CommandTable::const_iterator iter = m_commands.find(cmdTxt);
@@ -402,9 +402,9 @@ bool CEditorCommandManager::IsRegistered(int commandId) const
     return false;
 }
 
-void CEditorCommandManager::SetCommandAvailableInScripting(const string& module, const string& name)
+void CEditorCommandManager::SetCommandAvailableInScripting(const AZStd::string& module, const AZStd::string& name)
 {
-    string fullName = GetFullCommandName(module, name);
+    AZStd::string fullName = GetFullCommandName(module, name);
     CommandTable::iterator iter = m_commands.find(fullName);
 
     if (iter != m_commands.end())
@@ -413,7 +413,7 @@ void CEditorCommandManager::SetCommandAvailableInScripting(const string& module,
     }
 }
 
-bool CEditorCommandManager::IsCommandAvailableInScripting(const string& fullCmdName) const
+bool CEditorCommandManager::IsCommandAvailableInScripting(const AZStd::string& fullCmdName) const
 {
     CommandTable::const_iterator iter = m_commands.find(fullCmdName);
 
@@ -425,16 +425,16 @@ bool CEditorCommandManager::IsCommandAvailableInScripting(const string& fullCmdN
     return false;
 }
 
-bool CEditorCommandManager::IsCommandAvailableInScripting(const string& module, const string& name) const
+bool CEditorCommandManager::IsCommandAvailableInScripting(const AZStd::string& module, const AZStd::string& name) const
 {
-    string fullName = GetFullCommandName(module, name);
+    AZStd::string fullName = GetFullCommandName(module, name);
 
     return IsCommandAvailableInScripting(fullName);
 }
 
-void CEditorCommandManager::LogCommand(const string& fullCmdName, const CCommand::CArgs& args) const
+void CEditorCommandManager::LogCommand(const AZStd::string& fullCmdName, const CCommand::CArgs& args) const
 {
-    string cmdLine = fullCmdName;
+    AZStd::string cmdLine = fullCmdName;
 
     for (int i = 0; i < args.GetArgCount(); ++i)
     {
@@ -509,7 +509,7 @@ void CEditorCommandManager::LogCommand(const string& fullCmdName, const CCommand
 
     if (pScriptTermDialog)
     {
-        string text = "> ";
+        AZStd::string text = "> ";
         text += cmdLine;
         text += "\r\n";
         pScriptTermDialog->AppendText(text.c_str());
@@ -526,14 +526,14 @@ QString CEditorCommandManager::ExecuteAndLogReturn(CCommand* pCommand, const CCo
     return result;
 }
 
-void CEditorCommandManager::GetArgsFromString(const string& argsTxt, CCommand::CArgs& argList)
+void CEditorCommandManager::GetArgsFromString(const AZStd::string& argsTxt, CCommand::CArgs& argList)
 {
     const char quoteSymbol = '\'';
     int curPos = 0;
     int prevPos = 0;
-    string arg = argsTxt.Tokenize(" ", curPos);
-
-    while (!arg.empty())
+    AZStd::vector tokens;
+    AZ::StringFunc::Tokenize(argsTxt, tokens, ' ');
+    for(AZStd::string& arg : tokens)
     {
         if (arg[0] == quoteSymbol)   // A special consideration for a quoted string
         {
@@ -542,11 +542,11 @@ void CEditorCommandManager::GetArgsFromString(const string& argsTxt, CCommand::C
                 size_t openingQuotePos = argsTxt.find(quoteSymbol, prevPos);
                 size_t closingQuotePos = argsTxt.find(quoteSymbol, curPos);
 
-                if (closingQuotePos != string::npos)
+                if (closingQuotePos != AZStd::string::npos)
                 {
                     arg = argsTxt.substr(openingQuotePos + 1, closingQuotePos - openingQuotePos - 1);
                     size_t nextArgPos = argsTxt.find(' ', closingQuotePos + 1);
-                    curPos = nextArgPos != string::npos ? nextArgPos + 1 : argsTxt.length();
+                    curPos = nextArgPos != AZStd::string::npos ? nextArgPos + 1 : argsTxt.length();
 
                     for (; curPos < argsTxt.length(); ++curPos)    // Skip spaces.
                     {
@@ -565,6 +565,5 @@ void CEditorCommandManager::GetArgsFromString(const string& argsTxt, CCommand::C
 
         argList.Add(arg.c_str());
         prevPos = curPos;
-        arg = argsTxt.Tokenize(" ", curPos);
     }
 }
diff --git a/Code/Editor/Commands/CommandManager.h b/Code/Editor/Commands/CommandManager.h
index a76df830d0..0af744ac72 100644
--- a/Code/Editor/Commands/CommandManager.h
+++ b/Code/Editor/Commands/CommandManager.h
@@ -53,9 +53,9 @@ public:
     QString Execute(const AZStd::string& cmdLine);
     QString Execute(const AZStd::string& module, const AZStd::string& name, const CCommand::CArgs& args);
     void Execute(int commandId);
-    void GetCommandList(std::vector& cmds) const;
+    void GetCommandList(std::vector& cmds) const;
     //! Used in the console dialog
-    string AutoComplete(const AZStd::string& substr) const;
+    AZStd::string AutoComplete(const AZStd::string& substr) const;
     bool IsRegistered(const char* module, const char* name) const;
     bool IsRegistered(const char* cmdLine) const;
     bool IsRegistered(int commandId) const;
@@ -74,7 +74,7 @@ protected:
     };
 
     //! A full command name to an actual command mapping
-    typedef std::map CommandTable;
+    typedef std::map CommandTable;
     AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
     CommandTable m_commands;
 
@@ -86,7 +86,7 @@ protected:
     bool m_bWarnDuplicate;
 
     static int GenNewCommandId();
-    static string GetFullCommandName(const AZStd::string& module, const AZStd::string& name);
+    static AZStd::string GetFullCommandName(const AZStd::string& module, const AZStd::string& name);
     static void GetArgsFromString(const AZStd::string& argsTxt, CCommand::CArgs& argList);
     void LogCommand(const AZStd::string& fullCmdName, const CCommand::CArgs& args) const;
     QString ExecuteAndLogReturn(CCommand* pCommand, const CCommand::CArgs& args);
diff --git a/Code/Editor/ConfigGroup.cpp b/Code/Editor/ConfigGroup.cpp
index 4e61c38f4b..04c92ff155 100644
--- a/Code/Editor/ConfigGroup.cpp
+++ b/Code/Editor/ConfigGroup.cpp
@@ -127,9 +127,9 @@ namespace Config
 
                     case IConfigVar::eType_STRING:
                     {
-                        string currentValue = 0;
+                        AZStd::string currentValue = 0;
                         var->Get(¤tValue);
-                        node->setAttr(szName, currentValue);
+                        node->setAttr(szName, currentValue.c_str());
                         break;
                     }
                     }
@@ -186,7 +186,7 @@ namespace Config
 
                 case IConfigVar::eType_STRING:
                 {
-                    string currentValue = 0;
+                    AZStd::string currentValue = 0;
                     var->GetDefault(¤tValue);
                     QString readValue(currentValue.c_str());
                     if (node->getAttr(szName, readValue))
diff --git a/Code/Editor/ConfigGroup.h b/Code/Editor/ConfigGroup.h
index 5d9b22b2b9..aa379d4445 100644
--- a/Code/Editor/ConfigGroup.h
+++ b/Code/Editor/ConfigGroup.h
@@ -76,8 +76,8 @@ namespace Config
     protected:
         EType m_type;
         uint8 m_flags;
-        string m_name;
-        string m_description;
+        AZStd::string m_name;
+        AZStd::string m_description;
         void* m_ptr;
         ICVar* m_pCVar;
     };
diff --git a/Code/Editor/Controls/ConsoleSCB.cpp b/Code/Editor/Controls/ConsoleSCB.cpp
index 9f1921395c..0c664bbc59 100644
--- a/Code/Editor/Controls/ConsoleSCB.cpp
+++ b/Code/Editor/Controls/ConsoleSCB.cpp
@@ -180,7 +180,7 @@ bool ConsoleLineEdit::event(QEvent* ev)
 
         if (newStr.isEmpty())
         {
-            newStr = GetIEditor()->GetCommandManager()->AutoComplete(cstring.toUtf8().data());
+            newStr = GetIEditor()->GetCommandManager()->AutoComplete(cstring.toUtf8().data()).c_str();
         }
     }
 
@@ -211,7 +211,7 @@ void ConsoleLineEdit::keyPressEvent(QKeyEvent* ev)
         {
             if (commandManager->IsRegistered(str.toUtf8().data()))
             {
-                commandManager->Execute(QtUtil::ToString(str));
+                commandManager->Execute(str.toUtf8().data());
             }
             else
             {
diff --git a/Code/Editor/Controls/FolderTreeCtrl.cpp b/Code/Editor/Controls/FolderTreeCtrl.cpp
index 17b6dccac7..b1cbb9414e 100644
--- a/Code/Editor/Controls/FolderTreeCtrl.cpp
+++ b/Code/Editor/Controls/FolderTreeCtrl.cpp
@@ -400,7 +400,7 @@ void CFolderTreeCtrl::RemoveEmptyFolderItems(const QString& folder)
 
 void CFolderTreeCtrl::Edit(const QString& path)
 {
-    CFileUtil::EditTextFile(QtUtil::ToString(path), 0, IFileUtil::FILE_TYPE_SCRIPT);
+    CFileUtil::EditTextFile(path.toUtf8().data(), 0, IFileUtil::FILE_TYPE_SCRIPT);
 }
 
 void CFolderTreeCtrl::ShowInExplorer(const QString& path)
diff --git a/Code/Editor/Controls/ReflectedPropertyControl/PropertyGenericCtrl.cpp b/Code/Editor/Controls/ReflectedPropertyControl/PropertyGenericCtrl.cpp
index 1916ce5e16..a2c66b8b10 100644
--- a/Code/Editor/Controls/ReflectedPropertyControl/PropertyGenericCtrl.cpp
+++ b/Code/Editor/Controls/ReflectedPropertyControl/PropertyGenericCtrl.cpp
@@ -132,7 +132,9 @@ void LocalStringPropertyEditor::onEditClicked()
         if (pMgr->GetLocalizedInfoByIndex(i, sInfo))
         {
             item.desc = tr("English Text:\r\n");
-            item.desc += QString::fromWCharArray(Unicode::Convert(sInfo.sUtf8TranslatedText).c_str());
+            AZStd::wstring utf8TranslatedTextW;
+            AZStd::to_wstring(utf8TranslatedTextW, sInfo.sUtf8TranslatedText);
+            item.desc += QString::fromWCharArray(utf8TranslatedTextW.c_str());
             item.name = sInfo.sKey;
             items.push_back(item);
         }
diff --git a/Code/Editor/Controls/SplineCtrlEx.cpp b/Code/Editor/Controls/SplineCtrlEx.cpp
index 2afc3f16aa..73ede63951 100644
--- a/Code/Editor/Controls/SplineCtrlEx.cpp
+++ b/Code/Editor/Controls/SplineCtrlEx.cpp
@@ -127,7 +127,7 @@ private:
         std::vector keySelectionFlags;
         _smart_ptr undo;
         _smart_ptr redo;
-        string id;
+        AZStd::string id;
         ISplineInterpolator* pSpline;
     };
 
diff --git a/Code/Editor/Controls/SplineCtrlEx.h b/Code/Editor/Controls/SplineCtrlEx.h
index de07c4214b..add4bcb0a9 100644
--- a/Code/Editor/Controls/SplineCtrlEx.h
+++ b/Code/Editor/Controls/SplineCtrlEx.h
@@ -54,7 +54,7 @@ class ISplineSet
 {
 public:
     virtual ISplineInterpolator* GetSplineFromID(const AZStd::string& id) = 0;
-    virtual string GetIDFromSpline(ISplineInterpolator* pSpline) = 0;
+    virtual AZStd::string GetIDFromSpline(ISplineInterpolator* pSpline) = 0;
     virtual int GetSplineCount() const = 0;
     virtual int GetKeyCountAtTime(float time, float threshold) const = 0;
 };
diff --git a/Code/Editor/Core/QtEditorApplication.cpp b/Code/Editor/Core/QtEditorApplication.cpp
index 9ec3b57e29..11f65bfaa5 100644
--- a/Code/Editor/Core/QtEditorApplication.cpp
+++ b/Code/Editor/Core/QtEditorApplication.cpp
@@ -206,7 +206,7 @@ namespace
 
     static void LogToDebug([[maybe_unused]] QtMsgType Type, [[maybe_unused]] const QMessageLogContext& Context, const QString& message)
     {
-        AZ::Debug::Platform::OutputToDebugger("Qt", message.utf8());
+        AZ::Debug::Platform::OutputToDebugger("Qt", message.toUtf8().data());
         AZ::Debug::Platform::OutputToDebugger(nullptr, "\n");
     }
 }
diff --git a/Code/Editor/Core/Tests/test_Main.cpp b/Code/Editor/Core/Tests/test_Main.cpp
index c0772753c6..c0e34311ec 100644
--- a/Code/Editor/Core/Tests/test_Main.cpp
+++ b/Code/Editor/Core/Tests/test_Main.cpp
@@ -52,7 +52,7 @@ protected:
     }
 
 private:
-    AZ::AllocatorScope m_allocatorScope;
+    AZ::AllocatorScope m_allocatorScope;
     SSystemGlobalEnvironment m_stubEnv;
     AZ::IO::LocalFileIO m_fileIO;
     NiceMock* m_cryPak;
diff --git a/Code/Editor/CryEdit.cpp b/Code/Editor/CryEdit.cpp
index 973a818b92..b69bfa78f3 100644
--- a/Code/Editor/CryEdit.cpp
+++ b/Code/Editor/CryEdit.cpp
@@ -272,8 +272,8 @@ void CCryDocManager::OnFileNew()
     m_pDefTemplate->OpenDocumentFile(NULL);
     // if returns NULL, the user has already been alerted
 }
-BOOL CCryDocManager::DoPromptFileName(QString& fileName, [[maybe_unused]] UINT nIDSTitle,
-    [[maybe_unused]] DWORD lFlags, BOOL bOpenFileDialog, [[maybe_unused]] CDocTemplate* pTemplate)
+bool CCryDocManager::DoPromptFileName(QString& fileName, [[maybe_unused]] UINT nIDSTitle,
+    [[maybe_unused]] DWORD lFlags, bool bOpenFileDialog, [[maybe_unused]] CDocTemplate* pTemplate)
 {
     CLevelFileDialog levelFileDialog(bOpenFileDialog);
     levelFileDialog.show();
@@ -287,7 +287,7 @@ BOOL CCryDocManager::DoPromptFileName(QString& fileName, [[maybe_unused]] UINT n
 
     return false;
 }
-CCryEditDoc* CCryDocManager::OpenDocumentFile(LPCTSTR lpszFileName, BOOL bAddToMRU)
+CCryEditDoc* CCryDocManager::OpenDocumentFile(const char* lpszFileName, bool bAddToMRU)
 {
     assert(lpszFileName != NULL);
 
@@ -657,7 +657,7 @@ struct SharedData
 //
 //      This function uses a technique similar to that described in KB
 //      article Q141752 to locate the previous instance of the application. .
-BOOL CCryEditApp::FirstInstance(bool bForceNewInstance)
+bool CCryEditApp::FirstInstance(bool bForceNewInstance)
 {
     QSystemSemaphore sem(QString(O3DEApplicationName) + "_sem", 1);
     sem.acquire();
@@ -805,12 +805,12 @@ void CCryEditApp::InitDirectory()
 // Needed to work with custom memory manager.
 //////////////////////////////////////////////////////////////////////////
 
-CCryEditDoc* CCrySingleDocTemplate::OpenDocumentFile(LPCTSTR lpszPathName, BOOL bMakeVisible /*= true*/)
+CCryEditDoc* CCrySingleDocTemplate::OpenDocumentFile(const char* lpszPathName, bool bMakeVisible /*= true*/)
 {
     return OpenDocumentFile(lpszPathName, true, bMakeVisible);
 }
 
-CCryEditDoc* CCrySingleDocTemplate::OpenDocumentFile(LPCTSTR lpszPathName, BOOL bAddToMRU, [[maybe_unused]] BOOL bMakeVisible)
+CCryEditDoc* CCrySingleDocTemplate::OpenDocumentFile(const char* lpszPathName, bool bAddToMRU, [[maybe_unused]] bool bMakeVisible)
 {
     CCryEditDoc* pCurDoc = GetIEditor()->GetDocument();
 
@@ -849,7 +849,7 @@ CCryEditDoc* CCrySingleDocTemplate::OpenDocumentFile(LPCTSTR lpszPathName, BOOL
     return pCurDoc;
 }
 
-CCrySingleDocTemplate::Confidence CCrySingleDocTemplate::MatchDocType(LPCTSTR lpszPathName, CCryEditDoc*& rpDocMatch)
+CCrySingleDocTemplate::Confidence CCrySingleDocTemplate::MatchDocType(const char* lpszPathName, CCryEditDoc*& rpDocMatch)
 {
     assert(lpszPathName != NULL);
     rpDocMatch = NULL;
@@ -1059,7 +1059,7 @@ AZ::Outcome CCryEditApp::InitGameSystem(HWND hwndForInputSy
 }
 
 /////////////////////////////////////////////////////////////////////////////
-BOOL CCryEditApp::CheckIfAlreadyRunning()
+bool CCryEditApp::CheckIfAlreadyRunning()
 {
     bool bForceNewInstance = false;
 
@@ -1303,7 +1303,7 @@ void CCryEditApp::InitLevel(const CEditCommandLineInfo& cmdInfo)
 }
 
 /////////////////////////////////////////////////////////////////////////////
-BOOL CCryEditApp::InitConsole()
+bool CCryEditApp::InitConsole()
 {
     // Execute command from cmdline -exec_line if applicable
     if (!m_execLineCmd.isEmpty())
@@ -1593,7 +1593,7 @@ void CCryEditApp::RunInitPythonScript(CEditCommandLineInfo& cmdInfo)
 
 /////////////////////////////////////////////////////////////////////////////
 // CCryEditApp initialization
-BOOL CCryEditApp::InitInstance()
+bool CCryEditApp::InitInstance()
 {
     QElapsedTimer startupTimer;
     startupTimer.start();
@@ -2281,7 +2281,7 @@ void CCryEditApp::EnableIdleProcessing()
     AZ_Assert(m_disableIdleProcessingCounter >= 0, "m_disableIdleProcessingCounter must be nonnegative");
 }
 
-BOOL CCryEditApp::OnIdle([[maybe_unused]] LONG lCount)
+bool CCryEditApp::OnIdle([[maybe_unused]] LONG lCount)
 {
     if (0 == m_disableIdleProcessingCounter)
     {
@@ -3226,7 +3226,7 @@ void CCryEditApp::OnCreateLevel()
 //////////////////////////////////////////////////////////////////////////
 bool CCryEditApp::CreateLevel(bool& wasCreateLevelOperationCancelled)
 {
-    BOOL bIsDocModified = GetIEditor()->GetDocument()->IsModified();
+    bool bIsDocModified = GetIEditor()->GetDocument()->IsModified();
     if (GetIEditor()->GetDocument()->IsDocumentReady() && bIsDocModified)
     {
         QString str = QObject::tr("Level %1 has been changed. Save Level?").arg(GetIEditor()->GetGameEngine()->GetLevelName());
@@ -3280,7 +3280,7 @@ bool CCryEditApp::CreateLevel(bool& wasCreateLevelOperationCancelled)
         GetIEditor()->GetDocument()->DeleteTemporaryLevel();
     }
 
-    if (levelName.length() == 0 || !CryStringUtils::IsValidFileName(levelName.toUtf8().data()))
+    if (levelName.length() == 0 || !AZ::StringFunc::Path::IsValid(levelName.toUtf8().data()))
     {
         QMessageBox::critical(AzToolsFramework::GetActiveWindow(), QString(), QObject::tr("Level name is invalid, please choose another name."));
         return false;
@@ -3313,13 +3313,15 @@ bool CCryEditApp::CreateLevel(bool& wasCreateLevelOperationCancelled)
         DWORD dw = GetLastError();
 
 #ifdef WIN32
-        FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+        wchar_t windowsErrorMessageW[ERROR_LEN] = { 0 };
+        FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
             NULL,
             dw,
             MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
-            windowsErrorMessage.data(),
-            windowsErrorMessage.length(), NULL);
+            windowsErrorMessageW,
+            ERROR_LEN - 1, NULL);
         _getcwd(cwd.data(), cwd.length());
+        AZStd::to_string(windowsErrorMessage.data(), ERROR_LEN, windowsErrorMessageW);
 #else
         windowsErrorMessage = strerror(dw);
         cwd = QDir::currentPath().toUtf8();
@@ -3393,7 +3395,7 @@ void CCryEditApp::OnOpenSlice()
 }
 
 //////////////////////////////////////////////////////////////////////////
-CCryEditDoc* CCryEditApp::OpenDocumentFile(LPCTSTR lpszFileName)
+CCryEditDoc* CCryEditApp::OpenDocumentFile(const char* lpszFileName)
 {
     if (m_openingLevel)
     {
@@ -4250,7 +4252,7 @@ extern "C" int AZ_DLL_EXPORT CryEditMain(int argc, char* argv[])
 
         int exitCode = 0;
 
-        BOOL didCryEditStart = CCryEditApp::instance()->InitInstance();
+        bool didCryEditStart = CCryEditApp::instance()->InitInstance();
         AZ_Error("Editor", didCryEditStart, "O3DE Editor did not initialize correctly, and will close."
             "\nThis could be because of incorrectly configured components, or missing required gems."
             "\nSee other errors for more details.");
diff --git a/Code/Editor/CryEdit.h b/Code/Editor/CryEdit.h
index af0fbb0971..431a9cb817 100644
--- a/Code/Editor/CryEdit.h
+++ b/Code/Editor/CryEdit.h
@@ -135,16 +135,16 @@ public:
     virtual void AddToRecentFileList(const QString& lpszPathName);
     ECreateLevelResult CreateLevel(const QString& levelName, QString& fullyQualifiedLevelName);
     static void InitDirectory();
-    BOOL FirstInstance(bool bForceNewInstance = false);
+    bool FirstInstance(bool bForceNewInstance = false);
     void InitFromCommandLine(CEditCommandLineInfo& cmdInfo);
-    BOOL CheckIfAlreadyRunning();
+    bool CheckIfAlreadyRunning();
     //! @return successful outcome if initialization succeeded. or failed outcome with error message.
     AZ::Outcome InitGameSystem(HWND hwndForInputSystem);
     void CreateSplashScreen();
     void InitPlugins();
     bool InitGame();
 
-    BOOL InitConsole();
+    bool InitConsole();
     int IdleProcessing(bool bBackground);
     bool IsWindowInForeground();
     void RunInitPythonScript(CEditCommandLineInfo& cmdInfo);
@@ -171,10 +171,10 @@ public:
     // Overrides
     // ClassWizard generated virtual function overrides
 public:
-    virtual BOOL InitInstance();
+    virtual bool InitInstance();
     virtual int ExitInstance(int exitCode = 0);
-    virtual BOOL OnIdle(LONG lCount);
-    virtual CCryEditDoc* OpenDocumentFile(LPCTSTR lpszFileName);
+    virtual bool OnIdle(LONG lCount);
+    virtual CCryEditDoc* OpenDocumentFile(const char* lpszFileName);
 
     CCryDocManager* GetDocManager() { return m_pDocManager; }
 
@@ -454,9 +454,9 @@ public:
     ~CCrySingleDocTemplate() {};
     // avoid creating another CMainFrame
     // close other type docs before opening any things
-    virtual CCryEditDoc* OpenDocumentFile(LPCTSTR lpszPathName, BOOL bAddToMRU, BOOL bMakeVisible);
-    virtual CCryEditDoc* OpenDocumentFile(LPCTSTR lpszPathName, BOOL bMakeVisible = TRUE);
-    virtual Confidence MatchDocType(LPCTSTR lpszPathName, CCryEditDoc*& rpDocMatch);
+    virtual CCryEditDoc* OpenDocumentFile(const char* lpszPathName, bool bAddToMRU, bool bMakeVisible);
+    virtual CCryEditDoc* OpenDocumentFile(const char* lpszPathName, bool bMakeVisible = TRUE);
+    virtual Confidence MatchDocType(const char* lpszPathName, CCryEditDoc*& rpDocMatch);
 
 private:
     const QMetaObject* m_documentClass = nullptr;
@@ -471,9 +471,9 @@ public:
     CCrySingleDocTemplate* SetDefaultTemplate(CCrySingleDocTemplate* pNew);
     // Copied from MFC to get rid of the silly ugly unoverridable doc-type pick dialog
     virtual void OnFileNew();
-    virtual BOOL DoPromptFileName(QString& fileName, UINT nIDSTitle,
-        DWORD lFlags, BOOL bOpenFileDialog, CDocTemplate* pTemplate);
-    virtual CCryEditDoc* OpenDocumentFile(LPCTSTR lpszFileName, BOOL bAddToMRU);
+    virtual bool DoPromptFileName(QString& fileName, UINT nIDSTitle,
+        DWORD lFlags, bool bOpenFileDialog, CDocTemplate* pTemplate);
+    virtual CCryEditDoc* OpenDocumentFile(const char* lpszFileName, bool bAddToMRU);
 
     QVector m_templateList;
 };
diff --git a/Code/Editor/CryEditDoc.cpp b/Code/Editor/CryEditDoc.cpp
index 43f599b191..5438f44f37 100644
--- a/Code/Editor/CryEditDoc.cpp
+++ b/Code/Editor/CryEditDoc.cpp
@@ -426,8 +426,8 @@ void CCryEditDoc::Load(TDocMultiArchive& arrXmlAr, const QString& szFilename)
         Audio::AudioSystemRequestBus::BroadcastResult(controlsPath, &Audio::AudioSystemRequestBus::Events::GetControlsPath);
         QString sAudioLevelPath(controlsPath);
         sAudioLevelPath += "levels/";
-        string const sLevelNameOnly = PathUtil::GetFileName(fileName.toUtf8().data());
-        sAudioLevelPath += sLevelNameOnly;
+        AZStd::string const sLevelNameOnly = PathUtil::GetFileName(fileName.toUtf8().data());
+        sAudioLevelPath += sLevelNameOnly.c_str();
         QByteArray path = sAudioLevelPath.toUtf8();
         Audio::SAudioManagerRequestData oAMData(path, Audio::eADS_LEVEL_SPECIFIC);
         Audio::SAudioRequest oAudioRequestData;
@@ -1919,7 +1919,7 @@ void CCryEditDoc::LogLoadTime(int time)
 
     CLogFile::FormatLine("[LevelLoadTime] Level %s loaded in %d seconds", level.toUtf8().data(), time / 1000);
 #if defined(AZ_PLATFORM_WINDOWS)
-    SetFileAttributes(filename.toUtf8().data(), FILE_ATTRIBUTE_ARCHIVE);
+    SetFileAttributesW(filename.toStdWString().c_str(), FILE_ATTRIBUTE_ARCHIVE);
 #endif
 
     FILE* file = nullptr;
@@ -2152,7 +2152,7 @@ void CCryEditDoc::OnEnvironmentPropertyChanged(IVariable* pVar)
     }
 }
 
-QString CCryEditDoc::GetCryIndexPath(const LPCTSTR levelFilePath)
+QString CCryEditDoc::GetCryIndexPath(const char* levelFilePath)
 {
     QString levelPath = Path::GetPath(levelFilePath);
     QString levelName = Path::GetFileName(levelFilePath);
diff --git a/Code/Editor/CryEditDoc.h b/Code/Editor/CryEditDoc.h
index 574f8eb7da..9d86f62489 100644
--- a/Code/Editor/CryEditDoc.h
+++ b/Code/Editor/CryEditDoc.h
@@ -180,7 +180,7 @@ protected:
     void OnStartLevelResourceList();
     static void OnValidateSurfaceTypesChanged(ICVar*);
 
-    QString GetCryIndexPath(const LPCTSTR levelFilePath);
+    QString GetCryIndexPath(const char* levelFilePath);
 
     //////////////////////////////////////////////////////////////////////////
     // SliceEditorEntityOwnershipServiceNotificationBus::Handler
diff --git a/Code/Editor/CryEditPy.cpp b/Code/Editor/CryEditPy.cpp
index e65af3a19b..6abaf933fe 100644
--- a/Code/Editor/CryEditPy.cpp
+++ b/Code/Editor/CryEditPy.cpp
@@ -210,7 +210,7 @@ namespace
     const char* PyGetCurrentLevelName()
     {
         // Using static member to capture temporary data
-        static string tempLevelName;
+        static AZStd::string tempLevelName;
         tempLevelName = GetIEditor()->GetGameEngine()->GetLevelName().toUtf8().data();
         return tempLevelName.c_str();
     }
@@ -218,7 +218,7 @@ namespace
     const char* PyGetCurrentLevelPath()
     {
         // Using static member to capture temporary data
-        static string tempLevelPath;
+        static AZStd::string tempLevelPath;
         tempLevelPath = GetIEditor()->GetGameEngine()->GetLevelPath().toUtf8().data();
         return tempLevelPath.c_str();
     }
diff --git a/Code/Editor/EditorFileMonitor.cpp b/Code/Editor/EditorFileMonitor.cpp
index 96dc883ab0..ae5d900f2d 100644
--- a/Code/Editor/EditorFileMonitor.cpp
+++ b/Code/Editor/EditorFileMonitor.cpp
@@ -55,10 +55,10 @@ bool CEditorFileMonitor::RegisterListener(IFileChangeListener* pListener, const
 
 
 //////////////////////////////////////////////////////////////////////////
-static string CanonicalizePath(const char* path)
+static AZStd::string CanonicalizePath(const char* path)
 {
     auto canon = QFileInfo(path).canonicalFilePath();
-    return canon.isEmpty() ? string(path) : string(canon.toUtf8());
+    return canon.isEmpty() ? AZStd::string(path) : AZStd::string(canon.toUtf8());
 }
 
 //////////////////////////////////////////////////////////////////////////
@@ -66,8 +66,8 @@ bool CEditorFileMonitor::RegisterListener(IFileChangeListener* pListener, const
 {
     bool success = true;
 
-    string gameFolder = Path::GetEditingGameDataFolder().c_str();
-    string naivePath;
+    AZStd::string gameFolder = Path::GetEditingGameDataFolder().c_str();
+    AZStd::string naivePath;
     CFileChangeMonitor* fileChangeMonitor = CFileChangeMonitor::Instance();
     AZ_Assert(fileChangeMonitor, "CFileChangeMonitor singleton missing.");
 
@@ -75,12 +75,12 @@ bool CEditorFileMonitor::RegisterListener(IFileChangeListener* pListener, const
     // Append slash in preparation for appending the second part.
     naivePath = PathUtil::AddSlash(naivePath);
     naivePath += sFolderRelativeToGame;
-    naivePath.replace('/', '\\');
+    AZ::StringFunc::Replace(naivePath, '/', '\\');
 
     // Remove the final slash if the given item is a folder so the file change monitor correctly picks up on it.
     naivePath = PathUtil::RemoveSlash(naivePath);
 
-    string canonicalizedPath = CanonicalizePath(naivePath.c_str());
+    AZStd::string canonicalizedPath = CanonicalizePath(naivePath.c_str());
 
     if (fileChangeMonitor->IsDirectory(canonicalizedPath.c_str()) || fileChangeMonitor->IsFile(canonicalizedPath.c_str()))
     {
diff --git a/Code/Editor/GameExporter.cpp b/Code/Editor/GameExporter.cpp
index 006eb9189c..4c9031f08d 100644
--- a/Code/Editor/GameExporter.cpp
+++ b/Code/Editor/GameExporter.cpp
@@ -378,11 +378,11 @@ void CGameExporter::ExportFileList(const QString& path, const QString& levelName
 {
     // process the folder of the specified map name, producing a filelist.xml file
     //  that can later be used for map downloads
-    string newpath;
+    AZStd::string newpath;
 
     QString filename = levelName;
-    string mapname = (filename + ".dds").toUtf8().data();
-    string metaname = (filename + ".xml").toUtf8().data();
+    AZStd::string mapname = (filename + ".dds").toUtf8().data();
+    AZStd::string metaname = (filename + ".xml").toUtf8().data();
 
     XmlNodeRef rootNode = gEnv->pSystem->CreateXmlNode("download");
     rootNode->setAttr("name", filename.toUtf8().data());
@@ -434,9 +434,9 @@ void CGameExporter::ExportFileList(const QString& path, const QString& levelName
                     newFileNode->setAttr("size", handle.m_fileDesc.nSize);
 
                     unsigned char md5[16];
-                    string filenameToHash = GetIEditor()->GetGameEngine()->GetLevelPath().toUtf8().data();
+                    AZStd::string filenameToHash = GetIEditor()->GetGameEngine()->GetLevelPath().toUtf8().data();
                     filenameToHash += "/";
-                    filenameToHash += string{ handle.m_filename.data(), handle.m_filename.size() };
+                    filenameToHash += AZStd::string{ handle.m_filename.data(), handle.m_filename.size() };
                     if (gEnv->pCryPak->ComputeMD5(filenameToHash.data(), md5))
                     {
                         char md5string[33];
diff --git a/Code/Editor/IEditorImpl.cpp b/Code/Editor/IEditorImpl.cpp
index 2e755bd36a..65d5792aa5 100644
--- a/Code/Editor/IEditorImpl.cpp
+++ b/Code/Editor/IEditorImpl.cpp
@@ -26,6 +26,7 @@ AZ_POP_DISABLE_WARNING
 #include 
 #include 
 #include 
+#include 
 
 // AzFramework
 #include 
@@ -1107,16 +1108,18 @@ void CEditorImpl::DetectVersion()
     DWORD dwHandle;
     UINT len;
 
-    char ver[1024 * 8];
+    wchar_t ver[1024 * 8];
 
     AZ::Utils::GetExecutablePath(exe, _MAX_PATH);
+    AZStd::wstring exeW;
+    AZStd::to_wstring(exeW, exe);
 
-    int verSize = GetFileVersionInfoSize(exe, &dwHandle);
+    int verSize = GetFileVersionInfoSizeW(exeW.c_str(), &dwHandle);
     if (verSize > 0)
     {
-        GetFileVersionInfo(exe, dwHandle, 1024 * 8, ver);
+        GetFileVersionInfoW(exeW.c_str(), dwHandle, 1024 * 8, ver);
         VS_FIXEDFILEINFO* vinfo;
-        VerQueryValue(ver, "\\", (void**)&vinfo, &len);
+        VerQueryValueW(ver, L"\\", (void**)&vinfo, &len);
 
         m_fileVersion.v[0] = vinfo->dwFileVersionLS & 0xFFFF;
         m_fileVersion.v[1] = vinfo->dwFileVersionLS >> 16;
@@ -1557,31 +1560,31 @@ IExportManager* CEditorImpl::GetExportManager()
 void CEditorImpl::AddUIEnums()
 {
     // Spec settings for shadow casting lights
-    string SpecString[4];
+    AZStd::string SpecString[4];
     QStringList types;
     types.push_back("Never=0");
-    SpecString[0].Format("VeryHigh Spec=%d", CONFIG_VERYHIGH_SPEC);
+    SpecString[0] = AZStd::string::format("VeryHigh Spec=%d", CONFIG_VERYHIGH_SPEC);
     types.push_back(SpecString[0].c_str());
-    SpecString[1].Format("High Spec=%d", CONFIG_HIGH_SPEC);
+    SpecString[1] = AZStd::string::format("High Spec=%d", CONFIG_HIGH_SPEC);
     types.push_back(SpecString[1].c_str());
-    SpecString[2].Format("Medium Spec=%d", CONFIG_MEDIUM_SPEC);
+    SpecString[2] = AZStd::string::format("Medium Spec=%d", CONFIG_MEDIUM_SPEC);
     types.push_back(SpecString[2].c_str());
-    SpecString[3].Format("Low Spec=%d", CONFIG_LOW_SPEC);
+    SpecString[3] = AZStd::string::format("Low Spec=%d", CONFIG_LOW_SPEC);
     types.push_back(SpecString[3].c_str());
     m_pUIEnumsDatabase->SetEnumStrings("CastShadows", types);
 
     // Power-of-two percentages
-    string percentStringPOT[5];
+    AZStd::string percentStringPOT[5];
     types.clear();
-    percentStringPOT[0].Format("Default=%d", 0);
+    percentStringPOT[0] = AZStd::string::format("Default=%d", 0);
     types.push_back(percentStringPOT[0].c_str());
-    percentStringPOT[1].Format("12.5=%d", 1);
+    percentStringPOT[1] = AZStd::string::format("12.5=%d", 1);
     types.push_back(percentStringPOT[1].c_str());
-    percentStringPOT[2].Format("25=%d", 2);
+    percentStringPOT[2] = AZStd::string::format("25=%d", 2);
     types.push_back(percentStringPOT[2].c_str());
-    percentStringPOT[3].Format("50=%d", 3);
+    percentStringPOT[3] = AZStd::string::format("50=%d", 3);
     types.push_back(percentStringPOT[3].c_str());
-    percentStringPOT[4].Format("100=%d", 4);
+    percentStringPOT[4] = AZStd::string::format("100=%d", 4);
     types.push_back(percentStringPOT[4].c_str());
     m_pUIEnumsDatabase->SetEnumStrings("ShadowMinResPercent", types);
 }
diff --git a/Code/Editor/Include/Command.h b/Code/Editor/Include/Command.h
index 92a7736446..e4fea5a3e7 100644
--- a/Code/Editor/Include/Command.h
+++ b/Code/Editor/Include/Command.h
@@ -18,7 +18,7 @@
 
 #include "Util/EditorUtils.h"
 
-inline string ToString(const QString& s)
+inline AZStd::string ToString(const QString& s)
 {
     return s.toUtf8().data();
 }
@@ -85,7 +85,7 @@ public:
             return m_args[i];
         }
     private:
-        DynArray m_args;
+        DynArray m_args;
         unsigned char m_stringFlags;    // This is needed to quote string parameters when logging a command.
     };
 
@@ -104,15 +104,15 @@ public:
 
 protected:
     friend class CEditorCommandManager;
-    string m_module;
-    string m_name;
-    string m_description;
-    string m_example;
+    AZStd::string m_module;
+    AZStd::string m_name;
+    AZStd::string m_description;
+    AZStd::string m_example;
     bool m_bAlsoAvailableInScripting;
 
     template 
-    static string ToString_(T t) { return ::ToString(t); }
-    static inline string ToString_(const char* val)
+    static AZStd::string ToString_(T t) { return ::ToString(t); }
+    static inline AZStd::string ToString_(const char* val)
     { return val; }
     template 
     static bool FromString_(T& t, const char* s) { return ::FromString(t, s); }
@@ -146,10 +146,10 @@ public:
     // UI metadata for this command, if any
     struct SUIInfo
     {
-        string caption;
-        string tooltip;
-        string description;
-        string iconFilename;
+        AZStd::string caption;
+        AZStd::string tooltip;
+        AZStd::string description;
+        AZStd::string iconFilename;
         int iconIndex;
         int commandId; // Windows command id
 
diff --git a/Code/Editor/LevelFileDialog.cpp b/Code/Editor/LevelFileDialog.cpp
index 41bb4d6faa..cefa1330eb 100644
--- a/Code/Editor/LevelFileDialog.cpp
+++ b/Code/Editor/LevelFileDialog.cpp
@@ -98,7 +98,7 @@ CLevelFileDialog::CLevelFileDialog(bool openDialog, QWidget* parent)
         connect(ui->nameLineEdit, &QLineEdit::textChanged, this, &CLevelFileDialog::OnNameChanged);
     }
 
-    // reject invalid file names (see CryStringUtils::IsValidFileName)
+    // reject invalid file names
     ui->nameLineEdit->setValidator(new QRegExpValidator(QRegExp("^[a-zA-Z0-9_\\-./]*$"), ui->nameLineEdit));
 
     ReloadTree();
@@ -315,7 +315,7 @@ void CLevelFileDialog::OnNewFolder()
             const QString newFolderName = inputDlg.textValue();
             const QString newFolderPath = parentFullPath + "/" + newFolderName;
 
-            if (!CryStringUtils::IsValidFileName(newFolderName.toUtf8().data()))
+            if (!AZ::StringFunc::Path::IsValid(newFolderName.toUtf8().data()))
             {
                 QMessageBox box(this);
                 box.setText(tr("Please enter a single, valid folder name(standard English alphanumeric characters only)"));
@@ -416,7 +416,7 @@ bool CLevelFileDialog::ValidateSaveLevelPath(QString& errorMessage) const
     const QString enteredPath = GetEnteredPath();
     const QString levelPath = GetLevelPath();
 
-    if (!CryStringUtils::IsValidFileName(Path::GetFileName(levelPath).toUtf8().data()))
+    if (!AZ::StringFunc::Path::IsValid(Path::GetFileName(levelPath).toUtf8().data()))
     {
         errorMessage = tr("Please enter a valid level name (standard English alphanumeric characters only)");
         return false;
diff --git a/Code/Editor/LogFile.cpp b/Code/Editor/LogFile.cpp
index 8c04eab58c..76c6f34181 100644
--- a/Code/Editor/LogFile.cpp
+++ b/Code/Editor/LogFile.cpp
@@ -180,14 +180,14 @@ void CLogFile::FormatLineV(const char * format, va_list argList)
 void CLogFile::AboutSystem()
 {
     char szBuffer[MAX_LOGBUFFER_SIZE];
+    wchar_t szBufferW[MAX_LOGBUFFER_SIZE];
 #if defined(AZ_PLATFORM_WINDOWS) || defined(AZ_PLATFORM_LINUX)
     //////////////////////////////////////////////////////////////////////
     // Write the system informations to the log
     //////////////////////////////////////////////////////////////////////
 
-    char szProfileBuffer[128];
-    char szLanguageBuffer[64];
-    //char szCPUModel[64];
+    wchar_t szLanguageBufferW[64];
+    //wchar_t szCPUModel[64];
     MEMORYSTATUS MemoryStatus;
 #endif // defined(AZ_PLATFORM_WINDOWS) || defined(AZ_PLATFORM_LINUX)
 
@@ -201,11 +201,13 @@ void CLogFile::AboutSystem()
     //////////////////////////////////////////////////////////////////////
 
     // Get system language
-    GetLocaleInfo(LOCALE_SYSTEM_DEFAULT, LOCALE_SENGLANGUAGE,
-        szLanguageBuffer, sizeof(szLanguageBuffer));
+    GetLocaleInfoW(LOCALE_SYSTEM_DEFAULT, LOCALE_SENGLANGUAGE,
+        szLanguageBufferW, sizeof(szLanguageBufferW));
+    AZStd::string szLanguageBuffer;
+    AZStd::to_string(szLanguageBuffer, szLanguageBufferW);
 
     // Format and send OS information line
-    azsnprintf(szBuffer, MAX_LOGBUFFER_SIZE, "Current Language: %s ", szLanguageBuffer);
+    azsnprintf(szBuffer, MAX_LOGBUFFER_SIZE, "Current Language: %s ", szLanguageBuffer.c_str());
     CryLog("%s", szBuffer);
 #else
     QLocale locale;
@@ -294,7 +296,8 @@ AZ_POP_DISABLE_WARNING
     //////////////////////////////////////////////////////////////////////
 
     str += " (";
-    GetWindowsDirectory(szBuffer, sizeof(szBuffer));
+    GetWindowsDirectoryW(szBufferW, sizeof(szBufferW));
+    AZStd::to_string(szBuffer, MAX_LOGBUFFER_SIZE, szBufferW);
     str += szBuffer;
     str += ")";
     CryLog("%s", str.toUtf8().data());
@@ -381,12 +384,13 @@ AZ_POP_DISABLE_WARNING
 
 #if defined(AZ_PLATFORM_WINDOWS)
     EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &DisplayConfig);
-    GetPrivateProfileString("boot.description", "display.drv",
-        "(Unknown graphics card)", szProfileBuffer, sizeof(szProfileBuffer),
-        "system.ini");
+    GetPrivateProfileStringW(L"boot.description", L"display.drv",
+        L"(Unknown graphics card)", szLanguageBufferW, sizeof(szLanguageBufferW),
+        L"system.ini");
+    AZStd::to_string(szLanguageBuffer, szLanguageBufferW);
     azsnprintf(szBuffer, MAX_LOGBUFFER_SIZE, "Current display mode is %dx%dx%d, %s",
         DisplayConfig.dmPelsWidth, DisplayConfig.dmPelsHeight,
-        DisplayConfig.dmBitsPerPel, szProfileBuffer);
+        DisplayConfig.dmBitsPerPel, szLanguageBuffer.c_str());
     CryLog("%s", szBuffer);
 #else
     auto screen = QGuiApplication::primaryScreen();
diff --git a/Code/Editor/MainWindow.cpp b/Code/Editor/MainWindow.cpp
index ff322b79ac..c5352cbc4c 100644
--- a/Code/Editor/MainWindow.cpp
+++ b/Code/Editor/MainWindow.cpp
@@ -1634,7 +1634,7 @@ void MainWindow::OnUpdateConnectionStatus()
 
         status = tr("Pending Jobs : %1  Failed Jobs : %2").arg(m_connectionListener->GetJobsCount()).arg(failureCount);
 
-        statusBar->SetItem(QtUtil::ToQString("connection"), status, tooltip, icon);
+        statusBar->SetItem("connection", status, tooltip, icon);
 
         if (m_showAPDisconnectDialog && m_connectionListener->GetState() != EConnectionState::Connected)
         {
diff --git a/Code/Editor/Platform/Windows/Util/Mailer_Windows.cpp b/Code/Editor/Platform/Windows/Util/Mailer_Windows.cpp
index e7cc8658f0..0b33caed88 100644
--- a/Code/Editor/Platform/Windows/Util/Mailer_Windows.cpp
+++ b/Code/Editor/Platform/Windows/Util/Mailer_Windows.cpp
@@ -60,11 +60,11 @@ bool CMailer::SendMail(const char* subject,
     // Handle Recipients
     MapiRecipDesc* recipients = new MapiRecipDesc[numRecipients];
 
-    std::vector addresses;
+    std::vector addresses;
     addresses.resize(numRecipients);
     for (i = 0; i < numRecipients; i++)
     {
-        addresses[i] = string("SMTP:") + _recipients[i];
+        addresses[i] = AZStd::string("SMTP:") + _recipients[i];
     }
 
     for (i = 0; i < numRecipients; i++)
diff --git a/Code/Editor/PluginManager.cpp b/Code/Editor/PluginManager.cpp
index f03cb54fce..3432ca33ba 100644
--- a/Code/Editor/PluginManager.cpp
+++ b/Code/Editor/PluginManager.cpp
@@ -126,8 +126,8 @@ namespace
 
 bool CPluginManager::LoadPlugins(const char* pPathWithMask)
 {
-    QString strPath = QtUtil::ToQString(PathUtil::GetPath(pPathWithMask));
-    QString strMask = QString::fromUtf8(PathUtil::GetFile(pPathWithMask));
+    QString strPath = PathUtil::GetPath(pPathWithMask).c_str();
+    QString strMask = PathUtil::GetFile(pPathWithMask);
 
     CLogFile::WriteLine("[Plugin Manager] Loading plugins...");
 
diff --git a/Code/Editor/Plugins/EditorAssetImporter/AssetImporterPlugin.h b/Code/Editor/Plugins/EditorAssetImporter/AssetImporterPlugin.h
index 8bdfb48774..d78e6cab4e 100644
--- a/Code/Editor/Plugins/EditorAssetImporter/AssetImporterPlugin.h
+++ b/Code/Editor/Plugins/EditorAssetImporter/AssetImporterPlugin.h
@@ -88,7 +88,7 @@ private:
     IEditor* const m_editor;
 
     // Tool name
-    string m_toolName;
+    AZStd::string m_toolName;
 
     // Context provider for the Asset Browser
     AZ::AssetBrowserContextProvider m_assetBrowserContextProvider;
diff --git a/Code/Editor/ResourceSelectorHost.cpp b/Code/Editor/ResourceSelectorHost.cpp
index d265b3ffbe..edab4be57c 100644
--- a/Code/Editor/ResourceSelectorHost.cpp
+++ b/Code/Editor/ResourceSelectorHost.cpp
@@ -101,10 +101,10 @@ public:
     }
 
 private:
-    typedef std::map > TTypeMap;
+    typedef std::map > TTypeMap;
     TTypeMap m_typeMap;
 
-    std::map m_globallySelectedResources;
+    std::map m_globallySelectedResources;
 };
 
 // ---------------------------------------------------------------------------
diff --git a/Code/Editor/SelectSequenceDialog.cpp b/Code/Editor/SelectSequenceDialog.cpp
index 2566a8be82..11e30b91d7 100644
--- a/Code/Editor/SelectSequenceDialog.cpp
+++ b/Code/Editor/SelectSequenceDialog.cpp
@@ -37,7 +37,7 @@ CSelectSequenceDialog::GetItems(std::vector& outItems)
     {
         IAnimSequence* pSeq = pMovieSys->GetSequence(i);
         SItem item;
-        string fullname = pSeq->GetName();
+        AZStd::string fullname = pSeq->GetName();
         item.name = fullname.c_str();
         outItems.push_back(item);
     }
diff --git a/Code/Editor/ToolBox.cpp b/Code/Editor/ToolBox.cpp
index 77cb479873..0a1752a509 100644
--- a/Code/Editor/ToolBox.cpp
+++ b/Code/Editor/ToolBox.cpp
@@ -350,7 +350,7 @@ void CToolBoxManager::LoadShelves(QString scriptPath, QString shelvesPath, Actio
             continue;
         }
 
-        QString shelfName(PathUtil::GetFileName(files[idx].filename.toUtf8().data()));
+        QString shelfName(PathUtil::GetFileName(files[idx].filename.toUtf8().data()).c_str());
 
         AmazonToolbar toolbar(shelfName, shelfName);
         Load(shelvesPath + QString("/") + files[idx].filename, &toolbar, false, actionManager);
@@ -408,7 +408,7 @@ void CToolBoxManager::Load(QString xmlpath, AmazonToolbar* pToolbar, bool bToolb
     AZ::IO::FixedMaxPathString engineRoot = AZ::Utils::GetEnginePath();
     QDir engineDir = !engineRoot.empty() ? QDir(QString(engineRoot.c_str())) : QDir::current();
 
-    string enginePath = PathUtil::AddSlash(engineDir.absolutePath().toUtf8().data());
+    AZStd::string enginePath = PathUtil::AddSlash(engineDir.absolutePath().toUtf8().data());
 
     for (int i = 0; i < toolBoxNode->getChildCount(); ++i)
     {
@@ -434,11 +434,11 @@ void CToolBoxManager::Load(QString xmlpath, AmazonToolbar* pToolbar, bool bToolb
             continue;
         }
 
-        string shelfPath = PathUtil::GetParentDirectory(xmlpath.toUtf8().data());
-        string fullIconPath = enginePath + PathUtil::AddSlash(shelfPath.c_str());
+        AZStd::string shelfPath = PathUtil::GetParentDirectory(xmlpath.toUtf8().data());
+        AZStd::string fullIconPath = enginePath + PathUtil::AddSlash(shelfPath.c_str());
         fullIconPath.append(iconPath.toUtf8().data());
 
-        pMacro->SetIconPath(fullIconPath);
+        pMacro->SetIconPath(fullIconPath.c_str());
 
         QString toolTip(macroNode->getAttr("tooltip"));
         pMacro->action()->setToolTip(toolTip);
diff --git a/Code/Editor/TrackView/CommentKeyUIControls.cpp b/Code/Editor/TrackView/CommentKeyUIControls.cpp
index 4c5dc10bfa..91fa969e20 100644
--- a/Code/Editor/TrackView/CommentKeyUIControls.cpp
+++ b/Code/Editor/TrackView/CommentKeyUIControls.cpp
@@ -52,7 +52,7 @@ public:
         CFileUtil::ScanDirectory((Path::GetEditingGameDataFolder() + "/Fonts/").c_str(), "*.xml", fa, true);
         for (size_t i = 0; i < fa.size(); ++i)
         {
-            string name = fa[i].filename.toUtf8().data();
+            AZStd::string name = fa[i].filename.toUtf8().data();
             PathUtil::RemoveExtension(name);
             mv_font->AddEnumItem(name.c_str(), name.c_str());
         }
diff --git a/Code/Editor/TrackView/SequenceKeyUIControls.cpp b/Code/Editor/TrackView/SequenceKeyUIControls.cpp
index 5ef5a9c4ab..e280f06dc7 100644
--- a/Code/Editor/TrackView/SequenceKeyUIControls.cpp
+++ b/Code/Editor/TrackView/SequenceKeyUIControls.cpp
@@ -91,7 +91,7 @@ bool CSequenceKeyUIControls::OnKeySelectionChange(CTrackViewKeyBundle& selectedK
                 bool bNotParent = !bNotMe || pCurrentSequence->IsAncestorOf(pSequence) == false;
                 if (bNotMe && bNotParent)
                 {
-                    string seqName = pCurrentSequence->GetName();
+                    AZStd::string seqName = pCurrentSequence->GetName();
 
                     QString ownerIdString = CTrackViewDialog::GetEntityIdAsString(pCurrentSequence->GetSequenceComponentEntityId());
                     mv_sequence->AddEnumItem(seqName.c_str(), ownerIdString);
diff --git a/Code/Editor/TrackView/TrackViewAnimNode.cpp b/Code/Editor/TrackView/TrackViewAnimNode.cpp
index c66ea5635c..abff423ab7 100644
--- a/Code/Editor/TrackView/TrackViewAnimNode.cpp
+++ b/Code/Editor/TrackView/TrackViewAnimNode.cpp
@@ -1010,13 +1010,13 @@ bool CTrackViewAnimNode::SetName(const char* pName)
         }
     }
 
-    string oldName = GetName();
+    AZStd::string oldName = GetName();
     m_animNode->SetName(pName);
 
     CTrackViewSequence* sequence = GetSequence();
     AZ_Assert(sequence, "Nodes should never have a null sequence.");
 
-    sequence->OnNodeRenamed(this, oldName);
+    sequence->OnNodeRenamed(this, oldName.c_str());
 
     return true;
 }
diff --git a/Code/Editor/TrackView/TrackViewFindDlg.cpp b/Code/Editor/TrackView/TrackViewFindDlg.cpp
index 3d6e93fb05..18d574bf0b 100644
--- a/Code/Editor/TrackView/TrackViewFindDlg.cpp
+++ b/Code/Editor/TrackView/TrackViewFindDlg.cpp
@@ -61,7 +61,7 @@ void CTrackViewFindDlg::FillData()
             ObjName obj;
             obj.m_objName = pNode->GetName();
             obj.m_directorName = pNode->HasDirectorAsParent() ? pNode->HasDirectorAsParent()->GetName() : "";
-            string fullname = seq->GetName();
+            AZStd::string fullname = seq->GetName();
             obj.m_seqName = fullname.c_str();
             m_objs.push_back(obj);
         }
diff --git a/Code/Editor/TrackView/TrackViewNodes.cpp b/Code/Editor/TrackView/TrackViewNodes.cpp
index 90e5598876..000bdf21d0 100644
--- a/Code/Editor/TrackView/TrackViewNodes.cpp
+++ b/Code/Editor/TrackView/TrackViewNodes.cpp
@@ -2516,7 +2516,7 @@ int CTrackViewNodesCtrl::GetMatNameAndSubMtlIndexFromName(QString& matName, cons
     if (const char* pCh = strstr(nodeName, ".["))
     {
         char matPath[MAX_PATH];
-        azstrcpy(matPath, nodeName, (size_t)(pCh - nodeName));
+        azstrncpy(matPath, nodeName, (size_t)(pCh - nodeName));
         matName = matPath;
         pCh += 2;
         if ((*pCh) != 0)
diff --git a/Code/Editor/TrackView/TrackViewSequence.cpp b/Code/Editor/TrackView/TrackViewSequence.cpp
index 7ccecd7292..3647c554dc 100644
--- a/Code/Editor/TrackView/TrackViewSequence.cpp
+++ b/Code/Editor/TrackView/TrackViewSequence.cpp
@@ -1073,7 +1073,7 @@ std::deque CTrackViewSequence::GetMatchingTracks(CTrackViewAni
 {
     std::deque matchingTracks;
 
-    const string trackName = trackNode->getAttr("name");
+    const AZStd::string trackName = trackNode->getAttr("name");
 
     CAnimParamType animParamType;
     animParamType.LoadFromXml(trackNode);
@@ -1133,11 +1133,11 @@ void CTrackViewSequence::GetMatchedPasteLocationsRec(std::vectorgetChild(nodeIndex);
-        const string tagName = xmlChildNode->getTag();
+        const AZStd::string tagName = xmlChildNode->getTag();
 
         if (tagName == "Node")
         {
-            const string nodeName = xmlChildNode->getAttr("name");
+            const AZStd::string nodeName = xmlChildNode->getAttr("name");
 
             int nodeType = static_cast(AnimNodeType::Invalid);
             xmlChildNode->getAttr("type", nodeType);
@@ -1159,7 +1159,7 @@ void CTrackViewSequence::GetMatchedPasteLocationsRec(std::vectorgetAttr("name");
+            const AZStd::string trackName = xmlChildNode->getAttr("name");
 
             CAnimParamType trackParamType;
             trackParamType.Serialize(xmlChildNode, true);
diff --git a/Code/Editor/TrackViewNewSequenceDialog.cpp b/Code/Editor/TrackViewNewSequenceDialog.cpp
index 30691b0215..0efc7a932e 100644
--- a/Code/Editor/TrackViewNewSequenceDialog.cpp
+++ b/Code/Editor/TrackViewNewSequenceDialog.cpp
@@ -81,7 +81,7 @@ void CTVNewSequenceDialog::OnOK()
     for (int k = 0; k < GetIEditor()->GetSequenceManager()->GetCount(); ++k)
     {
         CTrackViewSequence* pSequence = GetIEditor()->GetSequenceManager()->GetSequenceByIndex(k);
-        QString fullname = QtUtil::ToQString(pSequence->GetName());
+        QString fullname = pSequence->GetName();
 
         if (fullname.compare(m_sequenceName, Qt::CaseInsensitive) == 0)
         {
diff --git a/Code/Editor/Util/AutoDirectoryRestoreFileDialog.cpp b/Code/Editor/Util/AutoDirectoryRestoreFileDialog.cpp
index f5ba0c507d..a14303cd69 100644
--- a/Code/Editor/Util/AutoDirectoryRestoreFileDialog.cpp
+++ b/Code/Editor/Util/AutoDirectoryRestoreFileDialog.cpp
@@ -45,7 +45,7 @@ int CAutoDirectoryRestoreFileDialog::exec()
         foreach(const QString&fileName, selectedFiles())
         {
             QFileInfo info(fileName);
-            if (!CryStringUtils::IsValidFileName(info.fileName().toStdString().c_str()))
+            if (!AZ::StringFunc::Path::IsValid(info.fileName().toStdString().c_str()))
             {
                 QMessageBox::warning(this, tr("Error"), tr("Please select a valid file name (standard English alphanumeric characters only)"));
                 problem = true;
diff --git a/Code/Editor/Util/FileUtil.cpp b/Code/Editor/Util/FileUtil.cpp
index d57d690154..f5535f5590 100644
--- a/Code/Editor/Util/FileUtil.cpp
+++ b/Code/Editor/Util/FileUtil.cpp
@@ -264,7 +264,7 @@ void CFileUtil::EditTextureFile(const char* textureFile, [[maybe_unused]] bool b
     }
 
     bool failedToLaunch = true;
-    QByteArray textureEditorPath = gSettings.textureEditor.toUtf8();
+    const QString& textureEditorPath = gSettings.textureEditor;
 
     // Give the user a warning if they don't have a texture editor configured
     if (textureEditorPath.isEmpty())
@@ -278,8 +278,7 @@ void CFileUtil::EditTextureFile(const char* textureFile, [[maybe_unused]] bool b
     // Use the Win32 API calls to open the right editor; the OS knows how to do this even better than
     // Qt does.
     QString fullTexturePathFixedForWindows = QString(fullTexturePath.data()).replace('/', '\\');
-    QByteArray fullTexturePathFixedForWindowsUtf8 = fullTexturePathFixedForWindows.toUtf8();
-    HINSTANCE hInst = ShellExecute(NULL, "open", textureEditorPath.data(), fullTexturePathFixedForWindowsUtf8.data(), NULL, SW_SHOWNORMAL);
+    HINSTANCE hInst = ShellExecuteW(NULL, L"open", textureEditorPath.toStdWString().c_str(), fullTexturePathFixedForWindows.toStdWString().c_str(), NULL, SW_SHOWNORMAL);
     failedToLaunch = ((DWORD_PTR)hInst <= 32);
 #elif defined(AZ_PLATFORM_MAC)
     failedToLaunch = QProcess::execute(QString("/usr/bin/open"), {"-a", gSettings.textureEditor, QString(fullTexturePath.data()) }) != 0;
@@ -298,7 +297,7 @@ void CFileUtil::EditTextureFile(const char* textureFile, [[maybe_unused]] bool b
 //////////////////////////////////////////////////////////////////////////
 bool CFileUtil::EditMayaFile(const char* filepath, const bool bExtractFromPak, const bool bUseGameFolder)
 {
-    QString dosFilepath = QtUtil::ToQString(PathUtil::ToDosPath(filepath));
+    QString dosFilepath = PathUtil::ToDosPath(filepath).c_str();
     if (bExtractFromPak)
     {
         ExtractFile(dosFilepath);
@@ -313,7 +312,7 @@ bool CFileUtil::EditMayaFile(const char* filepath, const bool bExtractFromPak, c
             dosFilepath = sGameFolder + '\\' + filepath;
         }
 
-        dosFilepath = PathUtil::ToDosPath(dosFilepath.toUtf8().data());
+        dosFilepath = PathUtil::ToDosPath(dosFilepath.toUtf8().data()).c_str();
     }
 
     const char* engineRoot;
@@ -1304,7 +1303,7 @@ IFileUtil::ECopyTreeResult CFileUtil::CopyTree(const QString& strSourceDirectory
     // all with the same names and all with the same files names inside. If you would make a depth-first search
     // you could end up with the files from the deepest folder in ALL your folders.
 
-    std::vector ignoredPatterns;
+    std::vector ignoredPatterns;
     StringHelpers::Split(ignoreFilesAndFolders, "|", false, ignoredPatterns);
 
     QDirIterator::IteratorFlags flags = QDirIterator::NoIteratorFlags;
@@ -2218,7 +2217,9 @@ uint32 CFileUtil::GetAttributes(const char* filename, bool bUseSourceControl /*=
         return SCC_FILE_ATTRIBUTE_READONLY | SCC_FILE_ATTRIBUTE_INPAK;
     }
 
-    DWORD dwAttrib = ::GetFileAttributes(file.GetAdjustedFilename());
+    AZStd::wstring fileW;
+    AZStd::to_wstring(fileW, file.GetAdjustedFilename());
+    DWORD dwAttrib = ::GetFileAttributesW(fileW.c_str());
     if (dwAttrib == INVALID_FILE_ATTRIBUTES)
     {
         return SCC_FILE_ATTRIBUTE_INVALID;
diff --git a/Code/Editor/Util/ImageASC.cpp b/Code/Editor/Util/ImageASC.cpp
index 69a6892c65..e6e947f342 100644
--- a/Code/Editor/Util/ImageASC.cpp
+++ b/Code/Editor/Util/ImageASC.cpp
@@ -24,8 +24,7 @@ bool CImageASC::Save(const QString& fileName, const CFloatImage& image)
     uint32 height = image.GetHeight();
     float* pixels = image.GetData();
 
-    string fileHeader;
-    fileHeader.Format(
+    AZStd::string fileHeader = AZStd::string::format(
         // Number of columns and rows in the data
         "ncols %d\n"
         "nrows %d\n"
diff --git a/Code/Editor/Util/ImageTIF.cpp b/Code/Editor/Util/ImageTIF.cpp
index 9040306a44..7029609825 100644
--- a/Code/Editor/Util/ImageTIF.cpp
+++ b/Code/Editor/Util/ImageTIF.cpp
@@ -399,8 +399,8 @@ bool CImageTIF::SaveRAW(const QString& fileName, const void* pData, int width, i
 
         if (preset && preset[0])
         {
-            string tiffphotoshopdata, valueheader;
-            string presetkeyvalue = string("/preset=") + string(preset);
+            AZStd::string tiffphotoshopdata, valueheader;
+            AZStd::string presetkeyvalue = AZStd::string("/preset=") + AZStd::string(preset);
 
             valueheader.push_back('\x1C');
             valueheader.push_back('\x02');
@@ -472,7 +472,7 @@ const char* CImageTIF::GetPreset(const QString& fileName)
             libtiffDummyWriteProc, libtiffDummySeekProc,
             libtiffDummyCloseProc, libtiffDummySizeProc, libtiffDummyMapFileProc, libtiffDummyUnmapFileProc);
 
-    string strReturn;
+    AZStd::string strReturn;
     char* preset = NULL;
     int size;
     if (tif)
diff --git a/Code/Editor/Util/ImageUtil.cpp b/Code/Editor/Util/ImageUtil.cpp
index 1b985c82f9..3ac15495cc 100644
--- a/Code/Editor/Util/ImageUtil.cpp
+++ b/Code/Editor/Util/ImageUtil.cpp
@@ -86,8 +86,7 @@ bool CImageUtil::SavePGM(const QString& fileName, const CImageEx& image)
     uint32* pixels = image.GetData();
 
     // Create the file header.
-    string fileHeader;
-    fileHeader.Format(
+    AZStd::string fileHeader = AZStd::string::format(
         // P2 = PGM header for ASCII output.  (P5 is PGM header for binary output)
         "P2\n"
         // width and height of the image
diff --git a/Code/Editor/Util/StringHelpers.cpp b/Code/Editor/Util/StringHelpers.cpp
index bf607e475e..a1e2b4ae08 100644
--- a/Code/Editor/Util/StringHelpers.cpp
+++ b/Code/Editor/Util/StringHelpers.cpp
@@ -7,117 +7,10 @@
  */
 
 
-#include 
 #include "StringHelpers.h"
 #include "Util.h"
-#include "StringUtils.h" // From CryCommon
-#include "UnicodeFunctions.h"
-#include 
-#include 
-
-#include  // WideCharToMultibyte(), CP_UTF8, etc.
-#include 
-
-static inline char ToLower(const char c)
-{
-    return tolower(c);
-}
-
-static inline wchar_t ToLower(const wchar_t c)
-{
-    return towlower(c);
-}
-
-
-static inline char ToUpper(const char c)
-{
-    return toupper(c);
-}
-
-static inline wchar_t ToUpper(const wchar_t c)
-{
-    return towupper(c);
-}
-
-
-static inline int Vscprintf(const char* format, va_list argList)
-{
-#if defined(AZ_PLATFORM_WINDOWS)
-    return _vscprintf(format, argList);
-#elif AZ_TRAIT_OS_PLATFORM_APPLE || defined(AZ_PLATFORM_LINUX)
-    int retval;
-    va_list argcopy;
-    va_copy(argcopy, argList);
-    retval = azvsnprintf(NULL, 0, format, argcopy);
-    va_end(argcopy);
-    return retval;
-#else
-    #error Not supported!
-#endif
-}
-
-static inline int Vscprintf(const wchar_t* format, va_list argList)
-{
-#if defined(AZ_PLATFORM_WINDOWS)
-    return _vscwprintf(format, argList);
-#elif AZ_TRAIT_OS_PLATFORM_APPLE || defined(AZ_PLATFORM_LINUX)
-    int retval;
-    va_list argcopy;
-    va_copy(argcopy, argList);
-    retval = azvsnwprintf(NULL, 0, format, argcopy);
-    va_end(argcopy);
-    return retval;
-#else
-    #error Not supported!
-#endif
-}
-
-
-static inline int Vsnprintf_s(char* str, size_t sizeInBytes, [[maybe_unused]] size_t count, const char* format, va_list argList)
-{
-    return azvsnprintf(str, sizeInBytes, format, argList);
-}
-
-static inline int Vsnprintf_s(wchar_t* str, size_t sizeInBytes, [[maybe_unused]] size_t count, const wchar_t* format, va_list argList)
-{
-    return azvsnwprintf(str, sizeInBytes, format, argList);
-}
-
-
-int StringHelpers::Compare(const AZStd::string& str0, const AZStd::string& str1)
-{
-    const size_t minLength = Util::getMin(str0.length(), str1.length());
-    const int result = std::memcmp(str0.c_str(), str1.c_str(), minLength);
-    if (result)
-    {
-        return result;
-    }
-    else
-    {
-        return (str0.length() == str1.length())
-               ? 0
-               : ((str0.length() < str1.length()) ? -1 : +1);
-    }
-}
-
-int StringHelpers::Compare(const wstring& str0, const wstring& str1)
-{
-    const size_t minLength = Util::getMin(str0.length(), str1.length());
-    for (size_t i = 0; i < minLength; ++i)
-    {
-        const wchar_t c0 = str0[i];
-        const wchar_t c1 = str1[i];
-        if (c0 != c1)
-        {
-            return (c0 < c1) ? -1 : 1;
-        }
-    }
-
-    return (str0.length() == str1.length())
-           ? 0
-           : ((str0.length() < str1.length()) ? -1 : +1);
-}
 
+#include 
 
 int StringHelpers::CompareIgnoreCase(const AZStd::string& str0, const AZStd::string& str1)
 {
@@ -135,7 +28,7 @@ int StringHelpers::CompareIgnoreCase(const AZStd::string& str0, const AZStd::str
     }
 }
 
-int StringHelpers::CompareIgnoreCase(const wstring& str0, const wstring& str1)
+int StringHelpers::CompareIgnoreCase(const AZStd::wstring& str0, const AZStd::wstring& str1)
 {
     const size_t minLength = Util::getMin(str0.length(), str1.length());
     for (size_t i = 0; i < minLength; ++i)
@@ -153,402 +46,6 @@ int StringHelpers::CompareIgnoreCase(const wstring& str0, const wstring& str1)
            : ((str0.length() < str1.length()) ? -1 : +1);
 }
 
-
-bool StringHelpers::Equals(const AZStd::string& str0, const AZStd::string& str1)
-{
-    if (str0.length() != str1.length())
-    {
-        return false;
-    }
-    return std::memcmp(str0.c_str(), str1.c_str(), str1.length()) == 0;
-}
-
-bool StringHelpers::Equals(const wstring& str0, const wstring& str1)
-{
-    if (str0.length() != str1.length())
-    {
-        return false;
-    }
-    return std::memcmp(str0.c_str(), str1.c_str(), str1.length() * sizeof(wstring::value_type)) == 0;
-}
-
-
-bool StringHelpers::EqualsIgnoreCase(const AZStd::string& str0, const AZStd::string& str1)
-{
-    if (str0.length() != str1.length())
-    {
-        return false;
-    }
-    return azmemicmp(str0.c_str(), str1.c_str(), str1.length()) == 0;
-}
-
-bool StringHelpers::EqualsIgnoreCase(const wstring& str0, const wstring& str1)
-{
-    const size_t str1Length = str1.length();
-    if (str0.length() != str1Length)
-    {
-        return false;
-    }
-    for (size_t i = 0; i < str1Length; ++i)
-    {
-        if (towlower(str0[i]) != towlower(str1[i]))
-        {
-            return false;
-        }
-    }
-    return true;
-}
-
-
-bool StringHelpers::StartsWith(const AZStd::string& str, const AZStd::string& pattern)
-{
-    if (str.length() < pattern.length())
-    {
-        return false;
-    }
-    return std::memcmp(str.c_str(), pattern.c_str(), pattern.length()) == 0;
-}
-
-bool StringHelpers::StartsWith(const wstring& str, const wstring& pattern)
-{
-    if (str.length() < pattern.length())
-    {
-        return false;
-    }
-    return std::memcmp(str.c_str(), pattern.c_str(), pattern.length() * sizeof(wstring::value_type)) == 0;
-}
-
-
-bool StringHelpers::StartsWithIgnoreCase(const AZStd::string& str, const AZStd::string& pattern)
-{
-    if (str.length() < pattern.length())
-    {
-        return false;
-    }
-    return azmemicmp(str.c_str(), pattern.c_str(), pattern.length()) == 0;
-}
-
-bool StringHelpers::StartsWithIgnoreCase(const wstring& str, const wstring& pattern)
-{
-    const size_t patternLength = pattern.length();
-    if (str.length() < patternLength)
-    {
-        return false;
-    }
-    for (size_t i = 0; i < patternLength; ++i)
-    {
-        if (towlower(str[i]) != towlower(pattern[i]))
-        {
-            return false;
-        }
-    }
-    return true;
-}
-
-
-bool StringHelpers::EndsWith(const AZStd::string& str, const AZStd::string& pattern)
-{
-    if (str.length() < pattern.length())
-    {
-        return false;
-    }
-    return std::memcmp(str.c_str() + str.length() - pattern.length(), pattern.c_str(), pattern.length()) == 0;
-}
-
-bool StringHelpers::EndsWith(const wstring& str, const wstring& pattern)
-{
-    if (str.length() < pattern.length())
-    {
-        return false;
-    }
-    return std::memcmp(str.c_str() + str.length() - pattern.length(), pattern.c_str(), pattern.length() * sizeof(wstring::value_type)) == 0;
-}
-
-
-bool StringHelpers::EndsWithIgnoreCase(const AZStd::string& str, const AZStd::string& pattern)
-{
-    if (str.length() < pattern.length())
-    {
-        return false;
-    }
-    return azmemicmp(str.c_str() + str.length() - pattern.length(), pattern.c_str(), pattern.length()) == 0;
-}
-
-bool StringHelpers::EndsWithIgnoreCase(const wstring& str, const wstring& pattern)
-{
-    const size_t patternLength = pattern.length();
-    if (str.length() < patternLength)
-    {
-        return false;
-    }
-    for (size_t i = str.length() - patternLength, j = 0; i < patternLength; ++i, ++j)
-    {
-        if (towlower(str[i]) != towlower(pattern[j]))
-        {
-            return false;
-        }
-    }
-    return true;
-}
-
-
-bool StringHelpers::Contains(const AZStd::string& str, const AZStd::string& pattern)
-{
-    const size_t patternLength = pattern.length();
-    if (str.length() < patternLength)
-    {
-        return false;
-    }
-    const size_t n = str.length() - patternLength + 1;
-    for (size_t i = 0; i < n; ++i)
-    {
-        if (std::memcmp(str.c_str() + i, pattern.c_str(), patternLength) == 0)
-        {
-            return true;
-        }
-    }
-    return false;
-}
-
-bool StringHelpers::Contains(const wstring& str, const wstring& pattern)
-{
-    const size_t patternLength = pattern.length();
-    if (str.length() < patternLength)
-    {
-        return false;
-    }
-    const size_t n = str.length() - patternLength + 1;
-    for (size_t i = 0; i < n; ++i)
-    {
-        if (std::memcmp(str.c_str() + i, pattern.c_str(), patternLength * sizeof(wstring::value_type)) == 0)
-        {
-            return true;
-        }
-    }
-    return false;
-}
-
-
-bool StringHelpers::ContainsIgnoreCase(const AZStd::string& str, const AZStd::string& pattern)
-{
-    const size_t patternLength = pattern.length();
-    if (str.length() < patternLength)
-    {
-        return false;
-    }
-    const size_t n = str.length() - patternLength + 1;
-    for (size_t i = 0; i < n; ++i)
-    {
-        if (azmemicmp(str.c_str() + i, pattern.c_str(), patternLength) == 0)
-        {
-            return true;
-        }
-    }
-    return false;
-}
-
-bool StringHelpers::ContainsIgnoreCase(const wstring& str, const wstring& pattern)
-{
-    const size_t patternLength = pattern.length();
-    if (patternLength == 0)
-    {
-        return true;
-    }
-    if (str.length() < patternLength)
-    {
-        return false;
-    }
-
-    const wstring::value_type firstPatternLetter = towlower(pattern[0]);
-    const size_t n = str.length() - patternLength + 1;
-    for (size_t i = 0; i < n; ++i)
-    {
-        bool match = true;
-        for (size_t j = 0; j < patternLength; ++j)
-        {
-            if (towlower(str[i + j]) != towlower(pattern[j]))
-            {
-                match = false;
-                break;
-            }
-        }
-        if (match)
-        {
-            return true;
-        }
-    }
-    return false;
-}
-
-string StringHelpers::TrimLeft(const AZStd::string& s)
-{
-    const size_t first = s.find_first_not_of(" \r\t");
-    return (first == s.npos) ? string() : s.substr(first);
-}
-
-wstring StringHelpers::TrimLeft(const wstring& s)
-{
-    const size_t first = s.find_first_not_of(L" \r\t");
-    return (first == s.npos) ? wstring() : s.substr(first);
-}
-
-
-string StringHelpers::TrimRight(const AZStd::string& s)
-{
-    const size_t last = s.find_last_not_of(" \r\t");
-    return (last == s.npos) ? s : s.substr(0, last + 1);
-}
-
-wstring StringHelpers::TrimRight(const wstring& s)
-{
-    const size_t last = s.find_last_not_of(L" \r\t");
-    return (last == s.npos) ? s : s.substr(0, last + 1);
-}
-
-
-string StringHelpers::Trim(const AZStd::string& s)
-{
-    return TrimLeft(TrimRight(s));
-}
-
-wstring StringHelpers::Trim(const wstring& s)
-{
-    return TrimLeft(TrimRight(s));
-}
-
-
-template 
-static inline TS RemoveDuplicateSpaces_Tpl(const TS& s)
-{
-    TS res;
-    bool spaceFound = false;
-
-    for (size_t i = 0, n = s.length(); i < n; ++i)
-    {
-        if ((s[i] == ' ') || (s[i] == '\r') || (s[i] == '\t'))
-        {
-            spaceFound = true;
-        }
-        else
-        {
-            if (spaceFound)
-            {
-                res += ' ';
-                spaceFound = false;
-            }
-            res += s[i];
-        }
-    }
-
-    if (spaceFound)
-    {
-        res += ' ';
-    }
-    return res;
-}
-
-string StringHelpers::RemoveDuplicateSpaces(const AZStd::string& s)
-{
-    return RemoveDuplicateSpaces_Tpl(s);
-}
-
-wstring StringHelpers::RemoveDuplicateSpaces(const wstring& s)
-{
-    return RemoveDuplicateSpaces_Tpl(s);
-}
-
-
-template 
-static inline TS MakeLowerCase_Tpl(const TS& s)
-{
-    TS copy;
-    copy.reserve(s.length());
-    for (typename TS::const_iterator it = s.begin(), end = s.end(); it != end; ++it)
-    {
-        copy.append(1, ToLower(*it));
-    }
-    return copy;
-}
-
-string StringHelpers::MakeLowerCase(const AZStd::string& s)
-{
-    return MakeLowerCase_Tpl(s);
-}
-
-wstring StringHelpers::MakeLowerCase(const wstring& s)
-{
-    return MakeLowerCase_Tpl(s);
-}
-
-
-template 
-static inline TS MakeUpperCase_Tpl(const TS& s)
-{
-    TS copy;
-    copy.reserve(s.length());
-    for (typename TS::const_iterator it = s.begin(), end = s.end(); it != end; ++it)
-    {
-        copy.append(1, ToUpper(*it));
-    }
-    return copy;
-}
-
-string StringHelpers::MakeUpperCase(const AZStd::string& s)
-{
-    return MakeUpperCase_Tpl(s);
-}
-
-wstring StringHelpers::MakeUpperCase(const wstring& s)
-{
-    return MakeUpperCase_Tpl(s);
-}
-
-
-template 
-static inline TS Replace_Tpl(const TS& s, const typename TS::value_type oldChar, const typename TS::value_type newChar)
-{
-    TS copy;
-    copy.reserve(s.length());
-    for (typename TS::const_iterator it = s.begin(), end = s.end(); it != end; ++it)
-    {
-        const typename TS::value_type c = (*it);
-        copy.append(1, ((c == oldChar) ? newChar : c));
-    }
-    return copy;
-}
-
-string StringHelpers::Replace(const AZStd::string& s, char oldChar, char newChar)
-{
-    return Replace_Tpl(s, oldChar, newChar);
-}
-
-wstring StringHelpers::Replace(const wstring& s, wchar_t oldChar, wchar_t newChar)
-{
-    return Replace_Tpl(s, oldChar, newChar);
-}
-
-
-void StringHelpers::ConvertStringByRef(string& out, const AZStd::string& in)
-{
-    out = in;
-}
-
-void StringHelpers::ConvertStringByRef(wstring& out, const AZStd::string& in)
-{
-    Unicode::Convert(out, in);
-}
-
-void StringHelpers::ConvertStringByRef(string& out, const wstring& in)
-{
-    Unicode::Convert(out, in);
-}
-
-void StringHelpers::ConvertStringByRef(wstring& out, const wstring& in)
-{
-    out = in;
-}
-
-
 template 
 static inline void Split_Tpl(const TS& str, const TS& separator, bool bReturnEmptyPartsToo, std::vector& outParts)
 {
@@ -588,348 +85,12 @@ static inline void Split_Tpl(const TS& str, const TS& separator, bool bReturnEmp
     }
 }
 
-
-template 
-static inline void SplitByAnyOf_Tpl(const TS& str, const TS& separators, bool bReturnEmptyPartsToo, std::vector& outParts)
-{
-    if (str.empty())
-    {
-        return;
-    }
-
-    if (separators.empty())
-    {
-        for (size_t i = 0; i < str.length(); ++i)
-        {
-            outParts.push_back(str.substr(i, 1));
-        }
-        return;
-    }
-
-    size_t partStart = 0;
-
-    for (;; )
-    {
-        const size_t pos = str.find_first_of(separators, partStart);
-        if (pos == TS::npos)
-        {
-            break;
-        }
-        if (bReturnEmptyPartsToo || (pos > partStart))
-        {
-            outParts.push_back(str.substr(partStart, pos - partStart));
-        }
-        partStart = pos + 1;
-    }
-
-    if (bReturnEmptyPartsToo || (partStart < str.length()))
-    {
-        outParts.push_back(str.substr(partStart, str.length() - partStart));
-    }
-}
-
-
-
-void StringHelpers::Split(const AZStd::string& str, const AZStd::string& separator, bool bReturnEmptyPartsToo, std::vector& outParts)
+void StringHelpers::Split(const AZStd::string& str, const AZStd::string& separator, bool bReturnEmptyPartsToo, std::vector& outParts)
 {
     Split_Tpl(str, separator, bReturnEmptyPartsToo, outParts);
 }
 
-void StringHelpers::Split(const wstring& str, const wstring& separator, bool bReturnEmptyPartsToo, std::vector& outParts)
+void StringHelpers::Split(const AZStd::wstring& str, const AZStd::wstring& separator, bool bReturnEmptyPartsToo, std::vector& outParts)
 {
     Split_Tpl(str, separator, bReturnEmptyPartsToo, outParts);
 }
-
-
-void StringHelpers::SplitByAnyOf(const AZStd::string& str, const AZStd::string& separators, bool bReturnEmptyPartsToo, std::vector& outParts)
-{
-    SplitByAnyOf_Tpl(str, separators, bReturnEmptyPartsToo, outParts);
-}
-
-void StringHelpers::SplitByAnyOf(const wstring& str, const wstring& separators, bool bReturnEmptyPartsToo, std::vector& outParts)
-{
-    SplitByAnyOf_Tpl(str, separators, bReturnEmptyPartsToo, outParts);
-}
-
-
-template 
-static inline TS FormatVA_Tpl(const typename TS::value_type* const format, va_list parg)
-{
-    if ((format == 0) || (format[0] == 0))
-    {
-        return TS();
-    }
-
-    std::vector bf;
-    size_t capacity = 0;
-
-    size_t wantedCapacity = Vscprintf(format, parg);
-    wantedCapacity += 2;  // '+ 2' to prevent uncertainty when Vsnprintf_s() returns 'size - 1'
-
-    for (;; )
-    {
-        if (wantedCapacity > capacity)
-        {
-            capacity = wantedCapacity;
-            bf.resize(capacity + 1);
-        }
-
-        const int countWritten = Vsnprintf_s(&bf[0], capacity + 1, _TRUNCATE, format, parg);
-
-        if ((countWritten >= 0) && (capacity > (size_t)countWritten + 1))
-        {
-            bf[countWritten] = 0;
-            return TS(&bf[0]);
-        }
-
-        wantedCapacity = capacity * 2;
-    }
-}
-
-string StringHelpers::FormatVA(const char* const format, va_list parg)
-{
-    return FormatVA_Tpl(format, parg);
-}
-
-wstring StringHelpers::FormatVA(const wchar_t* const format, va_list parg)
-{
-    return FormatVA_Tpl(format, parg);
-}
-
-//////////////////////////////////////////////////////////////////////////
-
-template 
-static inline void SafeCopy_Tpl(TC* const pDstBuffer, const size_t dstBufferSizeInBytes, const TC* const pSrc)
-{
-    if (dstBufferSizeInBytes >= sizeof(TC))
-    {
-        const size_t n = dstBufferSizeInBytes / sizeof(TC) - 1;
-        size_t i;
-        for (i = 0; i < n && pSrc[i]; ++i)
-        {
-            pDstBuffer[i] = pSrc[i];
-        }
-        pDstBuffer[i] = 0;
-    }
-}
-
-template 
-static inline void SafeCopyPadZeros_Tpl(TC* const pDstBuffer, const size_t dstBufferSizeInBytes, const TC* const pSrc)
-{
-    if (dstBufferSizeInBytes > 0)
-    {
-        const size_t n = (dstBufferSizeInBytes < sizeof(TC)) ? 0 : dstBufferSizeInBytes / sizeof(TC) - 1;
-        size_t i;
-        for (i = 0; i < n && pSrc[i]; ++i)
-        {
-            pDstBuffer[i] = pSrc[i];
-        }
-        memset(&pDstBuffer[i], 0, dstBufferSizeInBytes - i * sizeof(TC));
-    }
-}
-
-
-void StringHelpers::SafeCopy(char* const pDstBuffer, const size_t dstBufferSizeInBytes, const char* const pSrc)
-{
-    SafeCopy_Tpl(pDstBuffer, dstBufferSizeInBytes, pSrc);
-}
-
-void StringHelpers::SafeCopy(wchar_t* const pDstBuffer, const size_t dstBufferSizeInBytes, const wchar_t* const pSrc)
-{
-    SafeCopy_Tpl(pDstBuffer, dstBufferSizeInBytes, pSrc);
-}
-
-
-void StringHelpers::SafeCopyPadZeros(char* const pDstBuffer, const size_t dstBufferSizeInBytes, const char* const pSrc)
-{
-    SafeCopyPadZeros_Tpl(pDstBuffer, dstBufferSizeInBytes, pSrc);
-}
-
-void StringHelpers::SafeCopyPadZeros(wchar_t* const pDstBuffer, const size_t dstBufferSizeInBytes, const wchar_t* const pSrc)
-{
-    SafeCopyPadZeros_Tpl(pDstBuffer, dstBufferSizeInBytes, pSrc);
-}
-
-//////////////////////////////////////////////////////////////////////////
-
-bool StringHelpers::Utf16ContainsAsciiOnly(const wchar_t* wstr)
-{
-    while (*wstr)
-    {
-        if (*wstr > 127 || *wstr < 0)
-        {
-            return false;
-        }
-        ++wstr;
-    }
-    return true;
-}
-
-
-string StringHelpers::ConvertAsciiUtf16ToAscii(const wchar_t* wstr)
-{
-    const size_t len = wcslen(wstr);
-
-    string result;
-    result.reserve(len);
-
-    for (size_t i = 0; i < len; ++i)
-    {
-        result.push_back(wstr[i] & 0x7F);
-    }
-
-    return result;
-}
-
-
-wstring StringHelpers::ConvertAsciiToUtf16(const char* str)
-{
-    const size_t len = strlen(str);
-
-    wstring result;
-    result.reserve(len);
-
-    for (size_t i = 0; i < len; ++i)
-    {
-        result.push_back(str[i] & 0x7F);
-    }
-
-    return result;
-}
-
-#if defined(AZ_PLATFORM_WINDOWS)
-static string ConvertUtf16ToMultibyte(const wchar_t* wstr, uint codePage, char badChar)
-{
-    if (wstr[0] == 0)
-    {
-        return string();
-    }
-
-    const int len = aznumeric_caster(wcslen(wstr));
-
-    // Request needed buffer size, in bytes
-    int neededByteCount = WideCharToMultiByte(
-            codePage,
-            0,
-            wstr,
-            len,
-            0,
-            0,
-            ((badChar && codePage != CP_UTF8) ? &badChar : NULL),
-            NULL);
-    if (neededByteCount <= 0)
-    {
-        return string();
-    }
-    ++neededByteCount; // extra space for terminating zero
-
-    std::vector buffer(neededByteCount);
-
-    const int byteCount = WideCharToMultiByte(
-            codePage,
-            0,
-            wstr,
-            len,
-            &buffer[0], // output buffer
-            neededByteCount - 1, // size of the output buffer in bytes
-            ((badChar && codePage != CP_UTF8) ? &badChar : NULL),
-            NULL);
-    if (byteCount != neededByteCount - 1)
-    {
-        return string();
-    }
-
-    buffer[byteCount] = 0;
-
-    return string(&buffer[0]);
-}
-
-
-static wstring ConvertMultibyteToUtf16(const char* str, uint codePage)
-{
-    if (str[0] == 0)
-    {
-        return wstring();
-    }
-
-    const int len = aznumeric_caster(strlen(str));
-
-    // Request needed buffer size, in characters
-    int neededCharCount = MultiByteToWideChar(
-            codePage,
-            0,
-            str,
-            len,
-            0,
-            0);
-    if (neededCharCount <= 0)
-    {
-        return wstring();
-    }
-    ++neededCharCount; // extra space for terminating zero
-
-    std::vector wbuffer(neededCharCount);
-
-    const int charCount = MultiByteToWideChar(
-            codePage,
-            0,
-            str,
-            len,
-            &wbuffer[0], // output buffer
-            neededCharCount - 1); // size of the output buffer in characters
-    if (charCount != neededCharCount - 1)
-    {
-        return wstring();
-    }
-
-    wbuffer[charCount] = 0;
-
-    return wstring(&wbuffer[0]);
-}
-
-
-wstring StringHelpers::ConvertUtf8ToUtf16(const char* str)
-{
-    return ConvertMultibyteToUtf16(str, CP_UTF8);
-}
-
-
-string StringHelpers::ConvertUtf16ToUtf8(const wchar_t* wstr)
-{
-    return ConvertUtf16ToMultibyte(wstr, CP_UTF8, 0);
-}
-
-
-wstring StringHelpers::ConvertAnsiToUtf16(const char* str)
-{
-    return ConvertMultibyteToUtf16(str, CP_ACP);
-}
-
-
-string StringHelpers::ConvertUtf16ToAnsi(const wchar_t* wstr, char badChar)
-{
-    return ConvertUtf16ToMultibyte(wstr, CP_ACP, badChar);
-}
-#endif  //AZ_PLATFORM_WINDOWS
-
-string StringHelpers::ConvertAnsiToAscii(const char* str, char badChar)
-{
-    const size_t len = strlen(str);
-
-    string result;
-    result.reserve(len);
-
-    for (size_t i = 0; i < len; ++i)
-    {
-        char c = str[i];
-        if (c < 0 || c > 127)
-        {
-            c = badChar;
-        }
-        result.push_back(c);
-    }
-
-    return result;
-}
-
-// eof
diff --git a/Code/Editor/Util/StringHelpers.h b/Code/Editor/Util/StringHelpers.h
index ec5515fbc9..0e393e92dd 100644
--- a/Code/Editor/Util/StringHelpers.h
+++ b/Code/Editor/Util/StringHelpers.h
@@ -13,193 +13,13 @@
 
 namespace StringHelpers
 {
-    // compares two strings to see if they are the same or different, case sensitive
-    // returns 0 if the strings are the same, a -1 if the first string is bigger, or a 1 if the second string is bigger
-    int Compare(const AZStd::string& str0, const AZStd::string& str1);
-    int Compare(const wstring& str0, const wstring& str1);
-
     // compares two strings to see if they are the same or different, case is ignored
     // returns 0 if the strings are the same, a -1 if the first string is bigger, or a 1 if the second string is bigger
     int CompareIgnoreCase(const AZStd::string& str0, const AZStd::string& str1);
-    int CompareIgnoreCase(const wstring& str0, const wstring& str1);
+    int CompareIgnoreCase(const AZStd::wstring& str0, const AZStd::wstring& str1);
+  
+    void Split(const AZStd::string& str, const AZStd::string& separator, bool bReturnEmptyPartsToo, std::vector& outParts);
+    void Split(const AZStd::wstring& str, const AZStd::wstring& separator, bool bReturnEmptyPartsToo, std::vector& outParts);
 
-    // compares two strings to see if they are the same, case senstive
-    // returns true if they are the same or false if they are different
-    bool Equals(const AZStd::string& str0, const AZStd::string& str1);
-    bool Equals(const wstring& str0, const wstring& str1);
-
-    // compares two strings to see if they are the same, case is ignored
-    // returns true if they are the same or false if they are different
-    bool EqualsIgnoreCase(const AZStd::string& str0, const AZStd::string& str1);
-    bool EqualsIgnoreCase(const wstring& str0, const wstring& str1);
-
-    // checks to see if a string starts with a specified string, case sensitive
-    // returns true if the string does start with a specified string or false if it does not
-    bool StartsWith(const AZStd::string& str, const AZStd::string& pattern);
-    bool StartsWith(const wstring& str, const wstring& pattern);
-
-    // checks to see if a string starts with a specified string, case is ignored
-    // returns true if the string does start with a specified string or false if it does not
-    bool StartsWithIgnoreCase(const AZStd::string& str, const AZStd::string& pattern);
-    bool StartsWithIgnoreCase(const wstring& str, const wstring& pattern);
-
-    // checks to see if a string ends with a specified string, case sensitive
-    // returns true if the string does end with a specified string or false if it does not
-    bool EndsWith(const AZStd::string& str, const AZStd::string& pattern);
-    bool EndsWith(const wstring& str, const wstring& pattern);
-
-    // checks to see if a string ends with a specified string, case is ignored
-    // returns true if the string does end with a specified string or false if it does not
-    bool EndsWithIgnoreCase(const AZStd::string& str, const AZStd::string& pattern);
-    bool EndsWithIgnoreCase(const wstring& str, const wstring& pattern);
-
-    // checks to see if a string contains a specified string, case sensitive
-    // returns true if the string does contain the specified string or false if it does not
-    bool Contains(const AZStd::string& str, const AZStd::string& pattern);
-    bool Contains(const wstring& str, const wstring& pattern);
-
-    // checks to see if a string contains a specified string, case is ignored
-    // returns true if the string does contain the specified string or false if it does not
-    bool ContainsIgnoreCase(const AZStd::string& str, const AZStd::string& pattern);
-    bool ContainsIgnoreCase(const wstring& str, const wstring& pattern);
-
-    string TrimLeft(const AZStd::string& s);
-    wstring TrimLeft(const wstring& s);
-
-    string TrimRight(const AZStd::string& s);
-    wstring TrimRight(const wstring& s);
-
-    string Trim(const AZStd::string& s);
-    wstring Trim(const wstring& s);
-
-    string RemoveDuplicateSpaces(const AZStd::string& s);
-    wstring RemoveDuplicateSpaces(const wstring& s);
-
-    // converts a string with upper case characters to be all lower case
-    // returns the string in all lower case
-    string MakeLowerCase(const AZStd::string& s);
-    wstring MakeLowerCase(const wstring& s);
-
-    // converts a string with lower case characters to be all upper case
-    // returns the string in all upper case
-    string MakeUpperCase(const AZStd::string& s);
-    wstring MakeUpperCase(const wstring& s);
-
-    // replace a specified character in a string with a specified replacement character
-    // returns string with specified character replaced
-    string Replace(const AZStd::string& s, char oldChar, char newChar);
-    wstring Replace(const wstring& s, wchar_t oldChar, wchar_t newChar);
-
-    void ConvertStringByRef(string& out, const AZStd::string& in);
-    void ConvertStringByRef(wstring& out, const AZStd::string& in);
-    void ConvertStringByRef(string& out, const wstring& in);
-    void ConvertStringByRef(wstring& out, const wstring& in);
-
-    template 
-    O ConvertString(const I& in)
-    {
-        O out;
-        ConvertStringByRef(out, in);
-        return out;
-    }
-    
-    void Split(const AZStd::string& str, const AZStd::string& separator, bool bReturnEmptyPartsToo, std::vector& outParts);
-    void Split(const wstring& str, const wstring& separator, bool bReturnEmptyPartsToo, std::vector& outParts);
-
-    void SplitByAnyOf(const AZStd::string& str, const AZStd::string& separators, bool bReturnEmptyPartsToo, std::vector& outParts);
-    void SplitByAnyOf(const wstring& str, const wstring& separators, bool bReturnEmptyPartsToo, std::vector& outParts);
-
-    string FormatVA(const char* const format, va_list parg);
-    wstring FormatVA(const wchar_t* const format, va_list parg);
-
-    inline string Format(const char* const format, ...)
-    {
-        if ((format == 0) || (format[0] == 0))
-        {
-            return string();
-        }
-        va_list parg;
-        va_start(parg, format);
-        const string result = FormatVA(format, parg);
-        va_end(parg);
-        return result;
-    }
-
-    inline wstring Format(const wchar_t* const format, ...)
-    {
-        if ((format == 0) || (format[0] == 0))
-        {
-            return wstring();
-        }
-        va_list parg;
-        va_start(parg, format);
-        const wstring result = FormatVA(format, parg);
-        va_end(parg);
-        return result;
-    }
-
-    //////////////////////////////////////////////////////////////////////////
-
-    void SafeCopy(char* const pDstBuffer, const size_t dstBufferSizeInBytes, const char* const pSrc);
-    void SafeCopy(wchar_t* const pDstBuffer, const size_t dstBufferSizeInBytes, const wchar_t* const pSrc);
-
-    void SafeCopyPadZeros(char* const pDstBuffer, const size_t dstBufferSizeInBytes, const char* const pSrc);
-    void SafeCopyPadZeros(wchar_t* const pDstBuffer, const size_t dstBufferSizeInBytes, const wchar_t* const pSrc);
-
-    //////////////////////////////////////////////////////////////////////////
-
-    // ASCII
-    // ANSI (system default Windows ANSI code page)
-    // UTF-8
-    // UTF-16
-
-    // ASCII -> UTF-16
-
-    bool Utf16ContainsAsciiOnly(const wchar_t* wstr);
-    string ConvertAsciiUtf16ToAscii(const wchar_t* wstr);
-    wstring ConvertAsciiToUtf16(const char* str);
-
-    // UTF-8 <-> UTF-16
-#if defined(AZ_PLATFORM_WINDOWS)
-    wstring ConvertUtf8ToUtf16(const char* str);
-    string ConvertUtf16ToUtf8(const wchar_t* wstr);
-
-    inline string ConvertUtfToUtf8(const char* str)
-    {
-        return string(str);
-    }
-
-    inline string ConvertUtfToUtf8(const wchar_t* wstr)
-    {
-        return ConvertUtf16ToUtf8(wstr);
-    }
-
-    inline wstring ConvertUtfToUtf16(const char* str)
-    {
-        return ConvertUtf8ToUtf16(str);
-    }
-
-    inline wstring ConvertUtfToUtf16(const wchar_t* wstr)
-    {
-        return wstring(wstr);
-    }
-
-    // ANSI <-> UTF-8, UTF-16
-
-    wstring ConvertAnsiToUtf16(const char* str);
-    string ConvertUtf16ToAnsi(const wchar_t* wstr, char badChar);
-
-    inline string ConvertAnsiToUtf8(const char* str)
-    {
-        return ConvertUtf16ToUtf8(ConvertAnsiToUtf16(str).c_str());
-    }
-    inline string ConvertUtf8ToAnsi(const char* str, char badChar)
-    {
-        return ConvertUtf16ToAnsi(ConvertUtf8ToUtf16(str).c_str(), badChar);
-    }
-#endif
-
-    // ANSI -> ASCII
-    string ConvertAnsiToAscii(const char* str, char badChar);
 }
 #endif // CRYINCLUDE_CRYCOMMONTOOLS_STRINGHELPERS_H
diff --git a/Code/Editor/Util/XmlHistoryManager.cpp b/Code/Editor/Util/XmlHistoryManager.cpp
index 5a1bc237bb..b642929af1 100644
--- a/Code/Editor/Util/XmlHistoryManager.cpp
+++ b/Code/Editor/Util/XmlHistoryManager.cpp
@@ -427,7 +427,7 @@ const AZStd::string& CXmlHistoryManager::GetVersionDesc(int number) const
         return it->second.HistoryDescription;
     }
 
-    static string undef("UNDEFINED");
+    static AZStd::string undef("UNDEFINED");
     return undef;
 }
 
@@ -493,7 +493,7 @@ void CXmlHistoryManager::SetActiveGroupInt(const SXmlHistoryGroup* pGroup, const
     UnloadInt();
 
     TEventHandlerList eventHandler;
-    string undoDesc;
+    AZStd::string undoDesc;
 
     if (pGroup)
     {
@@ -534,7 +534,7 @@ void CXmlHistoryManager::SetActiveGroupInt(const SXmlHistoryGroup* pGroup, const
                 }
             }
         }
-        undoDesc.Format("Changed View to \"%s\"", displayName ? displayName : "UNDEFINED");
+        undoDesc = AZStd::string::format("Changed View to \"%s\"", displayName ? displayName : "UNDEFINED");
     }
     else
     {
diff --git a/Code/Editor/Util/XmlHistoryManager.h b/Code/Editor/Util/XmlHistoryManager.h
index 12699536e5..176f0a8d83 100644
--- a/Code/Editor/Util/XmlHistoryManager.h
+++ b/Code/Editor/Util/XmlHistoryManager.h
@@ -161,7 +161,7 @@ private:
 
         const SXmlHistoryGroup* CurrGroup;
         TGroupIndexMap CurrUserIndex;
-        string HistoryDescription;
+        AZStd::string HistoryDescription;
         bool IsNullUndo;
         bool HistoryInvalidated;
         TXmlHistotyGroupPtrList ActiveGroups;
diff --git a/Code/Legacy/CrySystem/XConsole.cpp b/Code/Legacy/CrySystem/XConsole.cpp
index 0f67e4ffd9..252ab8137d 100644
--- a/Code/Legacy/CrySystem/XConsole.cpp
+++ b/Code/Legacy/CrySystem/XConsole.cpp
@@ -2907,14 +2907,13 @@ void CXConsole::Paste()
         Utf8::Unchecked::octet_iterator end(data.end());
         for (Utf8::Unchecked::octet_iterator it(data.begin()); it != end; ++it)
         {
-            const uint32 cp = *it;
+            const wchar_t cp = *it;
             if (cp != '\r')
             {
                 // Convert UCS code-point into UTF-8 string
                 AZStd::fixed_string<5> utf8_buf = {0};
-                size_t size = 5;
-                it.to_utf8_sequence(cp, utf8_buf.data(), size);
-                AddInputUTF8(utf8_buf);
+                AZStd::to_string(utf8_buf.data(), 5, &cp, 1);
+                AddInputUTF8(utf8_buf.c_str());
             }
         }
     }

From 2ed07c2a6ad3937cd53f97cce159111cfd87a961 Mon Sep 17 00:00:00 2001
From: Dayo Lawal 
Date: Mon, 2 Aug 2021 23:09:28 -0500
Subject: [PATCH 077/803] delete MEWindowsRequestBus

Signed-off-by: Dayo Lawal 
---
 .../Window/AtomToolsMainWindow.h              |  2 +-
 .../Window/AtomToolsMainWindowRequestBus.h    |  2 +-
 .../Window/MaterialEditorWindowRequestBus.h   | 64 -------------------
 3 files changed, 2 insertions(+), 66 deletions(-)
 delete mode 100644 Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Window/MaterialEditorWindowRequestBus.h

diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindow.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindow.h
index edb8ff4322..6b02bd1c06 100644
--- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindow.h
+++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindow.h
@@ -23,7 +23,7 @@ namespace AtomToolsFramework
 {
     class AtomToolsMainWindow
         : public AzQtComponents::DockMainWindow
-        , protected AtomToolsFramework::AtomToolsMainWindowRequestBus::Handler
+        , protected AtomToolsMainWindowRequestBus::Handler
     {
     public:
         AtomToolsMainWindow(QWidget* parent = 0);
diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindowRequestBus.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindowRequestBus.h
index fd98b3b68b..ee21554844 100644
--- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindowRequestBus.h
+++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindowRequestBus.h
@@ -48,7 +48,7 @@ namespace AtomToolsFramework
         //! Get a list of registered docked widget names
         virtual AZStd::vector GetDockWidgetNames() const = 0;
 
-        //! Resizes the Material Editor window to achieve a requested size for the viewport render target.
+        //! Resizes the main window to achieve a requested size for the viewport render target.
         //! (This indicates the size of the render target, not the desktop-scaled QT widget size).
         virtual void ResizeViewportRenderTarget(uint32_t width, uint32_t height) {};
 
diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Window/MaterialEditorWindowRequestBus.h b/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Window/MaterialEditorWindowRequestBus.h
deleted file mode 100644
index 6b62549684..0000000000
--- a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Window/MaterialEditorWindowRequestBus.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
-
-#pragma once
-
-#include 
-#include 
-#include 
-
-class QWidget;
-
-namespace MaterialEditor
-{
-    //! MaterialEditorWindowRequestBus provides 
-    class MaterialEditorWindowRequests
-        : public AZ::EBusTraits
-    {
-    public:
-        static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
-        static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
-
-        //! Bring main window to foreground
-        virtual void ActivateWindow() = 0;
-
-        //! Add dockable widget in main window
-        //! @param name title of the dockable window
-        //! @param widget docked window content
-        //! @param area location of docked window corresponding to Qt::DockWidgetArea
-        //! @param orientation orientation of docked window corresponding to Qt::Orientation
-        virtual bool AddDockWidget(const AZStd::string& name, QWidget* widget, uint32_t area, uint32_t orientation) = 0;
-
-        //! Destroy dockable widget in main window
-        //! @param name title of the dockable window
-        virtual void RemoveDockWidget(const AZStd::string& name) = 0;
-
-        //! Show or hide dockable widget in main window
-        //! @param name title of the dockable window
-        virtual void SetDockWidgetVisible(const AZStd::string& name, bool visible) = 0;
-
-        //! Determine visibility of dockable widget in main window
-        //! @param name title of the dockable window
-        virtual bool IsDockWidgetVisible(const AZStd::string& name) const = 0;
-
-        //! Get a list of registered docked widget names
-        virtual AZStd::vector GetDockWidgetNames() const = 0;
-
-        //! Resizes the Material Editor window to achieve a requested size for the viewport render target.
-        //! (This indicates the size of the render target, not the desktop-scaled QT widget size).
-        virtual void ResizeViewportRenderTarget(uint32_t width, uint32_t height) = 0;
-
-        //! Forces the viewport's render target to use the given resolution, ignoring the size of the viewport widget.
-        virtual void LockViewportRenderTargetSize(uint32_t width, uint32_t height) = 0;
-
-        //! Releases the viewport's render target resolution lock, allowing it to match the viewport widget again.
-        virtual void UnlockViewportRenderTargetSize() = 0;
-    };
-    using MaterialEditorWindowRequestBus = AZ::EBus;
-
-} // namespace MaterialEditor

From f9d5a4a93b661f77363e17b1b4b0b3625a317776 Mon Sep 17 00:00:00 2001
From: Benjamin Jillich 
Date: Tue, 3 Aug 2021 16:06:51 +0200
Subject: [PATCH 078/803] Ported MCommon::RenderUtil

* Removed collision mesh based AABB rendering.
* Ported to AZ::Aabb
* Reduced the number of triangles used for rendering default spheres for joints to improve rendering times.

Signed-off-by: Benjamin Jillich 
---
 .../EMotionFX/Rendering/Common/RenderUtil.cpp | 73 +++++++------------
 .../EMotionFX/Rendering/Common/RenderUtil.h   | 24 +++---
 2 files changed, 37 insertions(+), 60 deletions(-)

diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RenderUtil.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RenderUtil.cpp
index 6301b0d7e3..36bce97f88 100644
--- a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RenderUtil.cpp
+++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RenderUtil.cpp
@@ -198,7 +198,7 @@ namespace MCommon
 
 
     // render the current bounding box of the given actor instance
-    void RenderUtil::RenderAABB(const MCore::AABB& box, const MCore::RGBAColor& color, bool directlyRender)
+    void RenderUtil::RenderAabb(const AZ::Aabb& box, const MCore::RGBAColor& color, bool directlyRender)
     {
         AZ::Vector3 min = box.GetMin();
         AZ::Vector3 max = box.GetMax();
@@ -238,12 +238,12 @@ namespace MCommon
 
 
     // render selection gizmo around the given AABB
-    void RenderUtil::RenderSelection(const MCore::AABB& box, const MCore::RGBAColor& color, bool directlyRender)
+    void RenderUtil::RenderSelection(const AZ::Aabb& box, const MCore::RGBAColor& color, bool directlyRender)
     {
-        //const Vector3 center  = box.CalcMiddle();
-        const AZ::Vector3       min     = box.GetMin();// + (box.GetMin()-center).Normalized()*0.005f;
-        const AZ::Vector3       max     = box.GetMax();// + (box.GetMax()-center).Normalized()*0.005f;
-        const float             scale   = box.CalcRadius() * 0.1f;
+        const AZ::Vector3       min     = box.GetMin();
+        const AZ::Vector3       max     = box.GetMax();
+        const float             radius  = AZ::Vector3(box.GetMax() - box.GetMin()).GetLength() * 0.5f;
+        const float             scale   = radius * 0.1f;
         const AZ::Vector3       up      = AZ::Vector3(0.0f, 1.0f, 0.0f) * scale;
         const AZ::Vector3       right   = AZ::Vector3(1.0f, 0.0f, 0.0f) * scale;
         const AZ::Vector3       front   = AZ::Vector3(0.0f, 0.0f, 1.0f) * scale;
@@ -304,46 +304,29 @@ namespace MCommon
     {
         mNodeBasedAABB              = true;
         mMeshBasedAABB              = true;
-        mCollisionMeshBasedAABB     = true;
         mStaticBasedAABB            = true;
         mStaticBasedColor           = MCore::RGBAColor(0.0f, 0.7f, 0.7f);
         mNodeBasedColor             = MCore::RGBAColor(1.0f, 0.0f, 0.0f);
-        mCollisionMeshBasedColor    = MCore::RGBAColor(0.0f, 0.7f, 0.0f);
         mMeshBasedColor             = MCore::RGBAColor(0.0f, 0.0f, 0.7f);
     }
 
 
     // render the given types of AABBs of a actor instance
-    void RenderUtil::RenderAABBs(EMotionFX::ActorInstance* actorInstance, const AABBRenderSettings& renderSettings, bool directlyRender)
+    void RenderUtil::RenderAabbs(EMotionFX::ActorInstance* actorInstance, const AABBRenderSettings& renderSettings, bool directlyRender)
     {
-        // get the current LOD level
         const uint32 lodLevel = actorInstance->GetLODLevel();
 
-        // handle the collision mesh based AABB
-        if (renderSettings.mCollisionMeshBasedAABB)
-        {
-            // calculate the collision mesh based AABB
-            MCore::AABB box;
-            actorInstance->CalcCollisionMeshBasedAABB(lodLevel, &box);
-
-            // render the aabb
-            if (box.CheckIfIsValid())
-            {
-                RenderAABB(box, renderSettings.mCollisionMeshBasedColor);
-            }
-        }
-
         // handle the node based AABB
         if (renderSettings.mNodeBasedAABB)
         {
             // calculate the node based AABB
-            MCore::AABB box;
-            actorInstance->CalcNodeBasedAABB(&box);
+            AZ::Aabb box;
+            actorInstance->CalcNodeBasedAabb(&box);
 
             // render the aabb
-            if (box.CheckIfIsValid())
+            if (box.IsValid())
             {
-                RenderAABB(box, renderSettings.mNodeBasedColor);
+                RenderAabb(box, renderSettings.mNodeBasedColor);
             }
         }
 
@@ -351,26 +334,26 @@ namespace MCommon
         if (renderSettings.mMeshBasedAABB)
         {
             // calculate the mesh based AABB
-            MCore::AABB box;
-            actorInstance->CalcMeshBasedAABB(lodLevel, &box);
+            AZ::Aabb box;
+            actorInstance->CalcMeshBasedAabb(lodLevel, &box);
 
             // render the aabb
-            if (box.CheckIfIsValid())
+            if (box.IsValid())
             {
-                RenderAABB(box, renderSettings.mMeshBasedColor);
+                RenderAabb(box, renderSettings.mMeshBasedColor);
             }
         }
 
         if (renderSettings.mStaticBasedAABB)
         {
             // calculate the static based AABB
-            MCore::AABB box;
-            actorInstance->CalcStaticBasedAABB(&box);
+            AZ::Aabb box;
+            actorInstance->CalcStaticBasedAabb(&box);
 
             // render the aabb
-            if (box.CheckIfIsValid())
+            if (box.IsValid())
             {
-                RenderAABB(box, renderSettings.mStaticBasedColor);
+                RenderAabb(box, renderSettings.mStaticBasedColor);
             }
         }
 
@@ -1639,7 +1622,7 @@ namespace MCommon
 
             // calculate the intersection points with the ground plane and create an AABB around those
             // if there is no intersection point then use the ray target as point, which is the projection onto the far plane basically
-            MCore::AABB aabb;
+            AZ::Aabb aabb = AZ::Aabb::CreateNull();
             AZ::Vector3 intersectionPoint;
             const AZ::Plane groundPlane = AZ::Plane::CreateFromNormalAndPoint(AZ::Vector3(0.0f, 0.0f, 1.0f), AZ::Vector3::CreateZero());
             for (AZ::u32 i = 0; i < 4; ++i)
@@ -1649,7 +1632,7 @@ namespace MCommon
                     corners[i] = intersectionPoint;
                 }
 
-                aabb.Encapsulate(corners[i]);
+                aabb.AddPoint(corners[i]);
             }
 
             // set the grid start and end values
@@ -1665,9 +1648,9 @@ namespace MCommon
 
 
     // get aabb which includes all actor instances
-    MCore::AABB RenderUtil::CalcSceneAABB()
+    AZ::Aabb RenderUtil::CalcSceneAabb()
     {
-        MCore::AABB finalAABB;
+        AZ::Aabb finalAABB = AZ::Aabb::CreateNull();
 
         // get the number of actor instances and iterate through them
         const uint32 numActorInstances = EMotionFX::GetActorManager().GetNumActorInstances();
@@ -1685,17 +1668,17 @@ namespace MCommon
             actorInstance->UpdateMeshDeformers(0.0f);
 
             // get the mesh based bounding box
-            MCore::AABB boundingBox;
-            actorInstance->CalcMeshBasedAABB(actorInstance->GetLODLevel(), &boundingBox);
+            AZ::Aabb boundingBox;
+            actorInstance->CalcMeshBasedAabb(actorInstance->GetLODLevel(), &boundingBox);
 
             // in case there aren't any meshes, use the node based bounding box
-            if (boundingBox.CheckIfIsValid() == false)
+            if (!boundingBox.IsValid())
             {
-                actorInstance->CalcNodeBasedAABB(&boundingBox);
+                actorInstance->CalcNodeBasedAabb(&boundingBox);
             }
 
             // make sure the actor instance is covered in our world bounding box
-            finalAABB.Encapsulate(boundingBox);
+            finalAABB.AddAabb(boundingBox);
         }
 
         return finalAABB;
diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RenderUtil.h b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RenderUtil.h
index 8b1cd30b6c..5c5d7bbef8 100644
--- a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RenderUtil.h
+++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RenderUtil.h
@@ -6,10 +6,9 @@
  *
  */
 
-#ifndef __MCOMMON_RENDERUTIL_H
-#define __MCOMMON_RENDERUTIL_H
+#pragma once
 
-// include required headers
+#include 
 #include 
 #include 
 #include 
@@ -111,7 +110,7 @@ namespace MCommon
          * Render tangents and bitangents of the mesh.
          * @param mesh A pointer to the mesh which will be rendered.
          * @param worldTM The world space transformation matrix of the node to which the given mesh belongs to.
-         * @param scale This parameter controls the length of the tangents and bitangentss. The default size of the tangents and bitangents is one unit.
+         * @param scale This parameter controls the length of the tangents and bitangents. The default size of the tangents and bitangents is one unit.
          * @param colorTangents The color of the tangents.
          * @param mirroredBitangentColor The color of the mirrored bitangents, so the ones that have a w value of -1.
          * @param colorBitangent The color of the face bitangents.
@@ -127,7 +126,7 @@ namespace MCommon
          * @param directlyRender Will call the RenderLines() function internally in case it is set to true. If false
          *                       you have to make sure to call RenderLines() manually at the end of your custom render frame function.
          */
-        void RenderAABB(const MCore::AABB& box, const MCore::RGBAColor& color, bool directlyRender = false);
+        void RenderAabb(const AZ::Aabb& box, const MCore::RGBAColor& color, bool directlyRender = false);
 
         /**
          * Render a selection gizmo around the given axis aligned bounding box.
@@ -136,7 +135,7 @@ namespace MCommon
          * @param directlyRender Will call the RenderLines() function internally in case it is set to true. If false
          *                       you have to make sure to call RenderLines() manually at the end of your custom render frame function.
          */
-        void RenderSelection(const MCore::AABB& box, const MCore::RGBAColor& color, bool directlyRender = false);
+        void RenderSelection(const AZ::Aabb& box, const MCore::RGBAColor& color, bool directlyRender = false);
 
         /**
          * The render settings used to enable the different AABB types of an actor instance.
@@ -152,11 +151,9 @@ namespace MCommon
 
             bool                mNodeBasedAABB;             /**< Enable in case you want to render the node based AABB (default=true). */
             bool                mMeshBasedAABB;             /**< Enable in case you want to render the mesh based AABB (default=true). */
-            bool                mCollisionMeshBasedAABB;    /**< Enable in case you want to render the collision mesh based AABB (default=true). */
             bool                mStaticBasedAABB;           /**< Enable in case you want to render the static based AABB (default=true). */
             MCore::RGBAColor    mNodeBasedColor;            /**< The color of the node based AABB. */
             MCore::RGBAColor    mMeshBasedColor;            /**< The color of the mesh based AABB. */
-            MCore::RGBAColor    mCollisionMeshBasedColor;   /**< The color of the collision mesh based AABB. */
             MCore::RGBAColor    mStaticBasedColor;          /**< The color of the static based AABB. */
         };
 
@@ -168,7 +165,7 @@ namespace MCommon
          * @param directlyRender Will call the RenderLines() function internally in case it is set to true. If false
          *                       you have to make sure to call RenderLines() manually at the end of your custom render frame function.
          */
-        void RenderAABBs(EMotionFX::ActorInstance* actorInstance, const AABBRenderSettings& renderSettings = AABBRenderSettings(), bool directlyRender = false);
+        void RenderAabbs(EMotionFX::ActorInstance* actorInstance, const AABBRenderSettings& renderSettings = AABBRenderSettings(), bool directlyRender = false);
 
         /**
          * Render OBB for all enabled nodes inside the actor instance.
@@ -615,7 +612,7 @@ namespace MCommon
          * Calculate the aabb which includes all actor instances.
          * @return The aabb which includes all actor instances.
          */
-        MCore::AABB CalcSceneAABB();
+        AZ::Aabb CalcSceneAabb();
 
         struct TrajectoryPathParticle
         {
@@ -722,7 +719,7 @@ namespace MCommon
 
         /**
          * Change the shape of a given arrow head util mesh. This method can be used to adjust an already allocated arrow head util mesh.
-         * For example this can be usedful if you need to change the radius or the height of an arrow head.
+         * For example this can be useful if you need to change the radius or the height of an arrow head.
          * @param mesh A pointer to the arrow head util mesh. Note that this mesh has to be created using CreateArrowHead().
          * @param height The height of the arrow head from the base to the head.
          * @param radius The radius of the base of the arrow head.
@@ -735,7 +732,7 @@ namespace MCommon
          * @param radius The radius of the sphere.
          * @return A pointer to the newly created util sphere mesh.
          */
-        static UtilMesh* CreateSphere(float radius, uint32 numSegments = 8);
+        static UtilMesh* CreateSphere(float radius, uint32 numSegments = 5);
 
         /**
          * Create an util mesh we can use to render cubes.
@@ -831,6 +828,3 @@ namespace MCommon
         static uint32                   mNumMaxTriangleVertices;    /**< The maximum capacity of the triangle vertex buffer */
     };
 } // namespace MCommon
-
-
-#endif

From aab8ab97065b53d874ad9ebbc9251da5ae1f3b2a Mon Sep 17 00:00:00 2001
From: Benjamin Jillich 
Date: Tue, 3 Aug 2021 17:04:26 +0200
Subject: [PATCH 079/803] Removed OBBs from Actor including the node infos

Signed-off-by: Benjamin Jillich 
---
 .../Pipeline/RCExt/Actor/ActorBuilder.cpp     |   2 +-
 .../EMotionFX/Code/EMotionFX/Source/Actor.cpp | 115 +-----------------
 Gems/EMotionFX/Code/EMotionFX/Source/Actor.h  |  74 +----------
 .../EMotionFX/Code/Tests/AnimGraphFixture.cpp |   2 +-
 .../Code/Tests/MorphTargetRuntimeTests.cpp    |   2 +-
 .../Code/Tests/UI/CanMorphManyShapes.cpp      |   2 +-
 6 files changed, 6 insertions(+), 191 deletions(-)

diff --git a/Gems/EMotionFX/Code/EMotionFX/Pipeline/RCExt/Actor/ActorBuilder.cpp b/Gems/EMotionFX/Code/EMotionFX/Pipeline/RCExt/Actor/ActorBuilder.cpp
index 35d38dd359..0c5916f684 100644
--- a/Gems/EMotionFX/Code/EMotionFX/Pipeline/RCExt/Actor/ActorBuilder.cpp
+++ b/Gems/EMotionFX/Code/EMotionFX/Pipeline/RCExt/Actor/ActorBuilder.cpp
@@ -272,7 +272,7 @@ namespace EMotionFX
             // Post create actor
             actor->SetUnitType(MCore::Distance::UNITTYPE_METERS);
             actor->SetFileUnitType(MCore::Distance::UNITTYPE_METERS);
-            actor->PostCreateInit(/*makeGeomLodsCompatibleWithSkeletalLODs=*/false, /*generateOBBs=*/false, /*convertUnitType=*/false);
+            actor->PostCreateInit(/*makeGeomLodsCompatibleWithSkeletalLODs=*/false, /*convertUnitType=*/false);
 
             // Only enable joints that are used for skinning (and their parents).
             // On top of that, enable all joints marked as critical joints.
diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp
index c55509e817..62bd8b32cb 100644
--- a/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp
+++ b/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp
@@ -42,7 +42,6 @@
 #include 
 #include 
 #include 
-#include 
 
 #include 
 
@@ -50,11 +49,6 @@ namespace EMotionFX
 {
     AZ_CLASS_ALLOCATOR_IMPL(Actor, ActorAllocator, 0)
 
-    Actor::NodeInfo::NodeInfo()
-    {
-        mOBB.Init();
-    }
-
     Actor::LODLevel::LODLevel()
     {
     }
@@ -188,7 +182,6 @@ namespace EMotionFX
         result->mSkeleton = mSkeleton->Clone();
 
         // clone lod data
-        result->mNodeInfos = mNodeInfos;
         const uint32 numNodes = mSkeleton->GetNumNodes();
 
         const size_t numLodLevels = m_meshLodData.m_lodLevels.size();
@@ -998,18 +991,6 @@ namespace EMotionFX
         }
     }
 
-    // update the bounding volumes
-    void Actor::UpdateNodeBindPoseOBBs(uint32 lodLevel)
-    {
-        // for all nodes
-        const uint32 numNodes = mSkeleton->GetNumNodes();
-        for (uint32 i = 0; i < numNodes; ++i)
-        {
-            CalcOBBFromBindPose(lodLevel, i);
-        }
-    }
-
-
     // remove all node groups
     void Actor::RemoveAllNodeGroups()
     {
@@ -1353,9 +1334,8 @@ namespace EMotionFX
         }
     }
 
-
     // post init
-    void Actor::PostCreateInit(bool makeGeomLodsCompatibleWithSkeletalLODs, bool generateOBBs, bool convertUnitType)
+    void Actor::PostCreateInit(bool makeGeomLodsCompatibleWithSkeletalLODs, bool convertUnitType)
     {
         if (mThreadIndex == MCORE_INVALIDINDEX32)
         {
@@ -1388,11 +1368,6 @@ namespace EMotionFX
         mSkeleton->GetBindPose()->ForceUpdateFullModelSpacePose();
         mSkeleton->GetBindPose()->ZeroMorphWeights();
 
-        if (generateOBBs)
-        {
-            UpdateNodeBindPoseOBBs(0);
-        }
-
         if (!GetHasMirrorInfo())
         {
             AllocateNodeMirrorInfos();
@@ -1883,7 +1858,6 @@ namespace EMotionFX
     void Actor::SetNumNodes(uint32 numNodes)
     {
         mSkeleton->SetNumNodes(numNodes);
-        mNodeInfos.resize(numNodes);
 
         AZStd::vector& lodLevels = m_meshLodData.m_lodLevels;
         for (LODLevel& lodLevel : lodLevels)
@@ -1901,7 +1875,6 @@ namespace EMotionFX
         mSkeleton->GetBindPose()->LinkToActor(this, Pose::FLAG_LOCALTRANSFORMREADY, false);
 
         // initialize the LOD data
-        mNodeInfos.emplace_back();
         AZStd::vector& lodLevels = m_meshLodData.m_lodLevels;
         for (LODLevel& lodLevel : lodLevels)
         {
@@ -1932,7 +1905,6 @@ namespace EMotionFX
     void Actor::RemoveNode(uint32 nr, bool delMem)
     {
         mSkeleton->RemoveNode(nr, delMem);
-        mNodeInfos.erase(mNodeInfos.begin() + nr);
 
         AZStd::vector& lodLevels = m_meshLodData.m_lodLevels;
         for (LODLevel& lodLevel : lodLevels)
@@ -1944,7 +1916,6 @@ namespace EMotionFX
     void Actor::DeleteAllNodes()
     {
         mSkeleton->RemoveAllNodes();
-        mNodeInfos.clear();
 
         AZStd::vector& lodLevels = m_meshLodData.m_lodLevels;
         for (LODLevel& lodLevel : lodLevels)
@@ -2263,82 +2234,6 @@ namespace EMotionFX
         return (stack->CheckIfHasDeformerOfType(SoftSkinDeformer::TYPE_ID) || stack->CheckIfHasDeformerOfType(DualQuatSkinDeformer::TYPE_ID));
     }
 
-
-    // calculate the OBB for a given node
-    void Actor::CalcOBBFromBindPose(uint32 lodLevel, uint32 nodeIndex)
-    {
-        AZStd::vector points;
-
-        // if there is a mesh
-        Mesh* mesh = GetMesh(lodLevel, nodeIndex);
-        if (mesh)
-        {
-            // if the mesh is not skinned
-            if (mesh->FindSharedVertexAttributeLayer(SkinningInfoVertexAttributeLayer::TYPE_ID) == nullptr)
-            {
-                mesh->ExtractOriginalVertexPositions(points);
-            }
-        }
-        else // there is no mesh, so maybe this is a bone
-        {
-            const Transform& invBindPoseTransform = GetInverseBindPoseTransform(nodeIndex);
-
-            // for all nodes inside the actor where this node belongs to
-            const uint32 numNodes = mSkeleton->GetNumNodes();
-            for (uint32 n = 0; n < numNodes; ++n)
-            {
-                Mesh* loopMesh = GetMesh(lodLevel, n);
-                if (loopMesh == nullptr)
-                {
-                    continue;
-                }
-
-                // get the vertex positions in bind pose
-                const uint32 numVerts = loopMesh->GetNumVertices();
-                points.reserve(numVerts * 2);
-                AZ::Vector3* positions = (AZ::Vector3*)loopMesh->FindOriginalVertexData(Mesh::ATTRIB_POSITIONS);
-
-                SkinningInfoVertexAttributeLayer* skinLayer = (SkinningInfoVertexAttributeLayer*)loopMesh->FindSharedVertexAttributeLayer(SkinningInfoVertexAttributeLayer::TYPE_ID);
-                if (skinLayer)
-                {
-                    // iterate over all skinning influences and see if this node number is used
-                    // if so, add it to the list of points
-                    const uint32* orgVertices = (uint32*)loopMesh->FindVertexData(Mesh::ATTRIB_ORGVTXNUMBERS);
-                    for (uint32 v = 0; v < numVerts; ++v)
-                    {
-                        // get the original vertex number
-                        const uint32 orgVtx = orgVertices[v];
-
-                        // for all skinning influences for this vertex
-                        const size_t numInfluences = skinLayer->GetNumInfluences(orgVtx);
-                        for (size_t i = 0; i < numInfluences; ++i)
-                        {
-                            // get the node used by this influence
-                            const uint32 nodeNr = skinLayer->GetInfluence(orgVtx, i)->GetNodeNr();
-
-                            // if this is the same node as we are updating the bounds for, add the vertex position to the list
-                            if (nodeNr == nodeIndex)
-                            {
-                                const AZ::Vector3 tempPos(positions[v]);
-                                points.emplace_back(invBindPoseTransform.TransformPoint(tempPos));
-                            }
-                        } // for all influences
-                    } // for all vertices
-                } // if there is skinning info
-            } // for all nodes
-        }
-
-        // init from the set of points
-        if (!points.empty())
-        {
-            GetNodeOBB(nodeIndex).InitFromPoints(&points[0], static_cast(points.size()));
-        }
-        else
-        {
-            GetNodeOBB(nodeIndex).Init();
-        }
-    }
-
     // remove the mesh for a given node in a given LOD
     void Actor::RemoveNodeMeshForLOD(uint32 lodLevel, uint32 nodeIndex, bool destroyMesh)
     {
@@ -2411,14 +2306,6 @@ namespace EMotionFX
             mInvBindPoseTransforms[i] = bindPose->GetModelSpaceTransform(i).Inversed();
         }
 
-        // update node obbs
-        for (uint32 i = 0; i < numNodes; ++i)
-        {
-            MCore::OBB& box = GetNodeOBB(i);
-            box.SetExtents(box.GetExtents() * scaleFactor);
-            box.SetCenter(box.GetCenter() * scaleFactor);
-        }
-
         // update static aabb
         m_staticAabb.SetMin(m_staticAabb.GetMin() * scaleFactor);
         m_staticAabb.SetMax(m_staticAabb.GetMax() * scaleFactor);
diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Actor.h b/Gems/EMotionFX/Code/EMotionFX/Source/Actor.h
index 53cbe7e05a..1c1173a9a2 100644
--- a/Gems/EMotionFX/Code/EMotionFX/Source/Actor.h
+++ b/Gems/EMotionFX/Code/EMotionFX/Source/Actor.h
@@ -24,7 +24,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 
 // include required headers
@@ -564,17 +563,6 @@ namespace EMotionFX
          */
         void SetMorphSetup(uint32 lodLevel, MorphSetup* setup);
 
-        /**
-         * Update the oriented bounding volumes (OBB) of all the nodes inside this actor.
-         * This is a very heavy calculation and must NOT be performed on a per-frame basis but only as pre-process step.
-         * The OBBs of the nodes are already being calculated at export time, so you shouldn't really need to use this method.
-         * Only when the bind pose geometry has changed you can update the node OBBs by calling this method.
-         * For more information about how the bounds are calculated please see the Node::GetOBB() and Node::CalcOBBFromBindPose() methods.
-         * The calculations performed by this method are automatically spread over multiple threads to improve the performance.
-         * @param lodLevel The geometry LOD level to use while calculating the object oriented bounds per node.
-         */
-        void UpdateNodeBindPoseOBBs(uint32 lodLevel);
-
         /**
          * Get the number of node groups inside this actor object.
          * @result The number of node groups.
@@ -758,7 +746,7 @@ namespace EMotionFX
         void MakeGeomLODsCompatibleWithSkeletalLODs();
 
         void ReinitializeMeshDeformers();
-        void PostCreateInit(bool makeGeomLodsCompatibleWithSkeletalLODs = true, bool generateOBBs = true, bool convertUnitType = true);
+        void PostCreateInit(bool makeGeomLodsCompatibleWithSkeletalLODs = true, bool convertUnitType = true);
 
         void AutoDetectMirrorAxes();
         const MCore::Array& GetNodeMirrorInfos() const;
@@ -808,57 +796,6 @@ namespace EMotionFX
         bool CheckIfHasMorphDeformer(uint32 lodLevel, uint32 nodeIndex) const;
         bool CheckIfHasSkinningDeformer(uint32 lodLevel, uint32 nodeIndex) const;
 
-        /**
-         * Calculate the object oriented box for a given LOD level.
-         * This will try to fit the tightest bounding box around the mesh of a node.
-         * If the node has no mesh and acts as bone inside skinning deformations the resulting box will contain
-         * all the vertices that are influenced by this given node/bone.
-         * Calculating this box is already done at export time. But you can use this to recalculate it if the mesh data changed.
-         * This method is relatively slow and not meant for per-frame calculations but only for preprocessing.
-         * You can use the GetOBB() method to retrieve the calculated box at any time.
-         * Nodes that do not have a mesh and not act as bone will have invalid OBB bounds, as they have no volume. You can check whether
-         * this is the case or not by using the MCore::OBB::IsValid() method.
-         * The box is stored in local space of the node.
-         * @param lodLevel The geometry LOD level to generate the OBBs from.
-         * @param nodeIndex The node to calculate the OBB for.
-         */
-        void CalcOBBFromBindPose(uint32 lodLevel, uint32 nodeIndex);
-
-        /**
-         * Get the object oriented bounding box for this node.
-         * The box is in local space. In order to convert it into world space you have to multiply the corner points of the box
-         * with the world space matrix of this node.
-         * Nodes that do not have a mesh and do not act as bone will have invalid bounds. You can use the MCore::OBB::CheckIfIsValid() method to check if
-         * the bounds are valid bounds or not. If it is not, then it means there was nothing to calculate the box from.
-         * Object Oriented Boxes for the nodes are calculated at export time by using the Actor::UpdateNodeBindPoseOBBs() and Node::CalcOBBFromBindPose() methods.
-         * @param nodeIndex The index of the node to get the OBB for.
-         * @result The object oriented bounding box that has been calculated before already.
-         */
-        MCore::OBB& GetNodeOBB(uint32 nodeIndex)                            { return mNodeInfos[nodeIndex].mOBB; }
-
-        /**
-         * Get the object oriented bounding box for this node.
-         * The box is in local space. In order to convert it into world space you have to multiply the corner points of the box
-         * with the world space matrix of this node.
-         * Nodes that do not have a mesh and do not act as bone will have invalid bounds. You can use the MCore::OBB::CheckIfIsValid() method to check if
-         * the bounds are valid bounds or not. If it is not, then it means there was nothing to calculate the box from.
-         * Object Oriented Boxes for the nodes are calculated at export time by using the Actor::UpdateNodeBindPoseOBBs() and Node::CalcOBBFromBindPose() methods.
-         * @param nodeIndex The index of the node to get the OBB for.
-         * @result The object oriented bounding box that has been calculated before already.
-         */
-        const MCore::OBB& GetNodeOBB(uint32 nodeIndex) const                { return mNodeInfos[nodeIndex].mOBB; }
-
-        /**
-         * Set the object oriented bounding box for this node.
-         * The box is in local space. In order to convert it into world space you have to multiply the corner points of the box
-         * with the world space matrix of this node.
-         * Nodes that do not have a mesh and do not act as bone will have invalid bounds. You can use the MCore::OBB::CheckIfIsValid() method to check if
-         * the bounds are valid bounds or not. If it is not, then it means there was nothing to calculate the box from.
-         * @param nodeIndex The index of the node to set the OBB for.
-         * @param obb The object oriented bounding box that has been calculated before already.
-         */
-        void SetNodeOBB(uint32 nodeIndex, const MCore::OBB& obb)            { mNodeInfos[nodeIndex].mOBB = obb; }
-
         void RemoveNodeMeshForLOD(uint32 lodLevel, uint32 nodeIndex, bool destroyMesh = true);
 
         void SetNumNodes(uint32 numNodes);
@@ -917,14 +854,6 @@ namespace EMotionFX
 
         Node* FindJointByMeshName(const AZStd::string_view meshName) const;
 
-        // per node info (shared between lods)
-        struct EMFX_API NodeInfo
-        {
-            MCore::OBB  mOBB;
-
-            NodeInfo();
-        };
-
         // data per node, per lod
         struct EMFX_API NodeLODInfo
         {
@@ -968,7 +897,6 @@ namespace EMotionFX
 
         Skeleton*                                       mSkeleton;                  /**< The skeleton, containing the nodes and bind pose. */
         MCore::Array                        mDependencies;              /**< The dependencies on other actors (shared meshes and transforms). */
-        AZStd::vector                         mNodeInfos;                 /**< The per node info, shared between lods. */
         AZStd::string                                   mName;                      /**< The name of the actor. */
         AZStd::string                                   mFileName;                  /**< The filename of the actor. */
         MCore::Array                    mNodeMirrorInfos;           /**< The array of node mirror info. */
diff --git a/Gems/EMotionFX/Code/Tests/AnimGraphFixture.cpp b/Gems/EMotionFX/Code/Tests/AnimGraphFixture.cpp
index 31c5455571..ab9d91046b 100644
--- a/Gems/EMotionFX/Code/Tests/AnimGraphFixture.cpp
+++ b/Gems/EMotionFX/Code/Tests/AnimGraphFixture.cpp
@@ -45,7 +45,7 @@ namespace EMotionFX
             ConstructActor();
             ASSERT_TRUE(m_actor) << "Construct actor did not build a valid actor.";
             m_actor->ResizeTransformData();
-            m_actor->PostCreateInit(/*makeGeomLodsCompatibleWithSkeletalLODs=*/ false, /*generateOBBs=*/ false, /*convertUnitType=*/ false);
+            m_actor->PostCreateInit(/*makeGeomLodsCompatibleWithSkeletalLODs=*/ false, /*convertUnitType=*/ false);
         }
         {
             m_motionSet = aznew MotionSet("testMotionSet");
diff --git a/Gems/EMotionFX/Code/Tests/MorphTargetRuntimeTests.cpp b/Gems/EMotionFX/Code/Tests/MorphTargetRuntimeTests.cpp
index 0f022b72ef..24afc7af47 100644
--- a/Gems/EMotionFX/Code/Tests/MorphTargetRuntimeTests.cpp
+++ b/Gems/EMotionFX/Code/Tests/MorphTargetRuntimeTests.cpp
@@ -84,7 +84,7 @@ namespace EMotionFX
             // Without this call, the bind pose does not know about newly added
             // morph target (mMorphWeights.GetLength() == 0)
             m_actor->ResizeTransformData();
-            m_actor->PostCreateInit(/*makeGeomLodsCompatibleWithSkeletalLODs=*/false, /*generateOBBs=*/false, /*convertUnitType=*/false);
+            m_actor->PostCreateInit(/*makeGeomLodsCompatibleWithSkeletalLODs=*/false, /*convertUnitType=*/false);
 
             m_animGraph = AZStd::make_unique();
 
diff --git a/Gems/EMotionFX/Code/Tests/UI/CanMorphManyShapes.cpp b/Gems/EMotionFX/Code/Tests/UI/CanMorphManyShapes.cpp
index 978532505b..ba24c501ab 100644
--- a/Gems/EMotionFX/Code/Tests/UI/CanMorphManyShapes.cpp
+++ b/Gems/EMotionFX/Code/Tests/UI/CanMorphManyShapes.cpp
@@ -68,7 +68,7 @@ namespace EMotionFX
 
             // Without this call, the bind pose does not know about newly added morph target (mMorphWeights.GetLength() == 0)
             m_actor->ResizeTransformData();
-            m_actor->PostCreateInit(/*makeGeomLodsCompatibleWithSkeletalLODs=*/false, /*generateOBBs=*/false, /*convertUnitType=*/false);
+            m_actor->PostCreateInit(/*makeGeomLodsCompatibleWithSkeletalLODs=*/false, /*convertUnitType=*/false);
 
             m_animGraph = AZStd::make_unique();
 

From b335285e19aae79fb0535211ab2e4713f739f30a Mon Sep 17 00:00:00 2001
From: Benjamin Jillich 
Date: Tue, 3 Aug 2021 17:13:19 +0200
Subject: [PATCH 080/803] Removed OBB rendering helpers and color options (was
 already hidden from the UI)

Signed-off-by: Benjamin Jillich 
---
 .../EMotionFX/Rendering/Common/RenderUtil.cpp | 71 -------------------
 .../EMotionFX/Rendering/Common/RenderUtil.h   | 12 ----
 Gems/EMotionFX/Code/EMotionFX/Source/Node.cpp |  1 -
 .../Source/RenderPlugin/RenderOptions.cpp     | 23 ------
 .../Source/RenderPlugin/RenderOptions.h       |  6 --
 .../Source/RenderPlugin/RenderPlugin.cpp      |  4 --
 .../RenderPlugin/RenderUpdateCallback.cpp     |  4 --
 .../Source/RenderPlugin/RenderViewWidget.cpp  |  3 -
 .../Source/RenderPlugin/RenderViewWidget.h    |  1 -
 9 files changed, 125 deletions(-)

diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RenderUtil.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RenderUtil.cpp
index 36bce97f88..8464cb2b2a 100644
--- a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RenderUtil.cpp
+++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RenderUtil.cpp
@@ -403,77 +403,6 @@ namespace MCommon
         }
     }
 
-
-    // render object orientated bounding  boxes for all enabled nodes inside the actor instance
-    void RenderUtil::RenderOBBs(EMotionFX::ActorInstance* actorInstance, const AZStd::unordered_set* visibleJointIndices, const AZStd::unordered_set* selectedJointIndices, const MCore::RGBAColor& color, const MCore::RGBAColor& selectedColor, bool directlyRender)
-    {
-        AZ::Vector3 p[8];
-
-        // get the actor it is an instance from
-        const EMotionFX::Actor* actor = actorInstance->GetActor();
-        const EMotionFX::Skeleton* skeleton = actor->GetSkeleton();
-        const EMotionFX::Pose* pose = actorInstance->GetTransformData()->GetCurrentPose();
-
-        // iterate through all enabled nodes
-        MCore::RGBAColor tempColor;
-        const uint32 numEnabled = actorInstance->GetNumEnabledNodes();
-        for (uint32 i = 0; i < numEnabled; ++i)
-        {
-            const EMotionFX::Node* joint = skeleton->GetNode(actorInstance->GetEnabledNode(i));
-            const AZ::u32 jointIndex = joint->GetNodeIndex();
-
-            if (!visibleJointIndices || visibleJointIndices->empty() ||
-                (visibleJointIndices->find(jointIndex) != visibleJointIndices->end()))
-            {
-                const MCore::OBB& obb = actor->GetNodeOBB(jointIndex);
-                EMotionFX::Transform worldTransform = pose->GetWorldSpaceTransform(jointIndex);
-
-                // skip the OBB if it isn't valid
-                if (obb.CheckIfIsValid() == false)
-                {
-                    continue;
-                }
-
-                // check if the current bone is selected and set the color according to it
-                if (selectedJointIndices && selectedJointIndices->find(jointIndex) != selectedJointIndices->end())
-                {
-                    tempColor = selectedColor;
-                }
-                else
-                {
-                    tempColor = color;
-                }
-
-                obb.CalcCornerPoints(p);
-                for (uint32 a = 0; a < 8; a++)
-                {
-                    p[a] = worldTransform.TransformPoint(p[a]);
-                }
-
-                // render
-                RenderLine(p[0], p[1], tempColor);
-                RenderLine(p[1], p[2], tempColor);
-                RenderLine(p[2], p[3], tempColor);
-                RenderLine(p[0], p[3], tempColor);
-
-                RenderLine(p[1], p[5], tempColor);
-                RenderLine(p[3], p[7], tempColor);
-                RenderLine(p[2], p[6], tempColor);
-                RenderLine(p[0], p[4], tempColor);
-
-                RenderLine(p[4], p[5], tempColor);
-                RenderLine(p[4], p[7], tempColor);
-                RenderLine(p[6], p[7], tempColor);
-                RenderLine(p[6], p[5], tempColor);
-            }
-        }
-
-        if (directlyRender)
-        {
-            RenderLines();
-        }
-    }
-
     // render wireframe mesh
     void RenderUtil::RenderWireframe(EMotionFX::Mesh* mesh, const AZ::Transform& worldTM, const MCore::RGBAColor& color, bool directlyRender, float offsetScale)
     {
diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RenderUtil.h b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RenderUtil.h
index 5c5d7bbef8..f63d41e812 100644
--- a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RenderUtil.h
+++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RenderUtil.h
@@ -167,18 +167,6 @@ namespace MCommon
          */
         void RenderAabbs(EMotionFX::ActorInstance* actorInstance, const AABBRenderSettings& renderSettings = AABBRenderSettings(), bool directlyRender = false);
 
-        /**
-         * Render OBB for all enabled nodes inside the actor instance.
-         * @param actorInstance A pointer to the actor instance which will be rendered.
-         * @param[in] visibleJointIndices List of visible joint indices. nullptr in case all joints should be rendered.
-         * @param[in] selectedJointIndices List of selected joint indices. nullptr in case selection should not be considered.
-         * @param[in] color The color of the OBBs.
-         * @param[in] selectedColor The color of the selected OBBs.
-         * @param[in] directlyRender Will call the RenderLines() function internally in case it is set to true. If false
-         *                           you have to make sure to call RenderLines() manually at the end of your custom render frame function.
-         */
-        void RenderOBBs(EMotionFX::ActorInstance* actorInstance, const AZStd::unordered_set* visibleJointIndices = nullptr, const AZStd::unordered_set* selectedJointIndices = nullptr, const MCore::RGBAColor& color = MCore::RGBAColor(1.0f, 1.0f, 0.0f, 1.0f), const MCore::RGBAColor& selectedColor = MCore::RGBAColor(1.0f, 0.647f, 0.0f), bool directlyRender = false);
-
         /**
          * Render a simple line based skeleton for all enabled nodes of the actor instance.
          * @param[in] actorInstance A pointer to the actor instance which will be rendered.
diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Node.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Node.cpp
index 2aa6b796ab..8ab7fa540d 100644
--- a/Gems/EMotionFX/Code/EMotionFX/Source/Node.cpp
+++ b/Gems/EMotionFX/Code/EMotionFX/Source/Node.cpp
@@ -98,7 +98,6 @@ namespace EMotionFX
         result->mChildIndices       = mChildIndices;
         //result->mImportanceFactor = mImportanceFactor;
         result->mNodeFlags          = mNodeFlags;
-        result->mOBB                = mOBB;
         result->mSemanticNameID     = mSemanticNameID;
 
         // copy the node attributes
diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderOptions.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderOptions.cpp
index 5e57d64167..274edd36ce 100644
--- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderOptions.cpp
+++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderOptions.cpp
@@ -55,7 +55,6 @@ namespace EMStudio
     const char* RenderOptions::s_nodeAABBColorOptionName = "nodeAABBColor";
     const char* RenderOptions::s_staticAABBColorOptionName = "staticAABBColor";
     const char* RenderOptions::s_meshAABBColorOptionName = "meshAABBColor";
-    const char* RenderOptions::s_OBBsColorOptionName = "OBBsColor";
     const char* RenderOptions::s_lineSkeletonColorOptionName = "lineSkeletonColor_v2";
     const char* RenderOptions::s_skeletonColorOptionName = "skeletonColor";
     const char* RenderOptions::s_selectionColorOptionName = "selectionColor";
@@ -107,7 +106,6 @@ namespace EMStudio
         , m_nodeAABBColor(1.0f, 0.0f, 0.0f, 1.0f)
         , m_staticAABBColor(0.0f, 0.7f, 0.7f, 1.0f)
         , m_meshAABBColor(0.0f, 0.0f, 0.7f, 1.0f)
-        , m_OBBsColor(1.0f, 1.0f, 0.0f, 1.0f)
         , m_lineSkeletonColor(0.33333f, 1.0f, 0.0f, 1.0f)
         , m_skeletonColor(0.19f, 0.58f, 0.19f, 1.0f)
         , m_selectionColor(1.0f, 1.0f, 1.0f, 1.0f)
@@ -167,7 +165,6 @@ namespace EMStudio
         SetNodeAABBColor(other.GetNodeAABBColor());
         SetStaticAABBColor(other.GetStaticAABBColor());
         SetMeshAABBColor(other.GetMeshAABBColor());
-        SetOBBsColor(other.GetOBBsColor());
         SetLineSkeletonColor(other.GetLineSkeletonColor());
         SetSkeletonColor(other.GetSkeletonColor());
         SetSelectionColor(other.GetSelectionColor());
@@ -204,7 +201,6 @@ namespace EMStudio
         settings->setValue(s_staticAABBColorOptionName, ColorToString(m_staticAABBColor));
         settings->setValue(s_meshAABBColorOptionName, ColorToString(m_meshAABBColor));
         settings->setValue(s_collisionMeshColorOptionName, ColorToString(m_collisionMeshColor));
-        settings->setValue(s_OBBsColorOptionName, ColorToString(m_OBBsColor));
         settings->setValue(s_lineSkeletonColorOptionName, ColorToString(m_lineSkeletonColor));
         settings->setValue(s_skeletonColorOptionName, ColorToString(m_skeletonColor));
         settings->setValue(s_selectionColorOptionName, ColorToString(m_selectionColor));
@@ -272,7 +268,6 @@ namespace EMStudio
         options.m_staticAABBColor = StringToColor(settings->value(s_staticAABBColorOptionName, ColorToString(options.m_staticAABBColor)).toString());
         options.m_meshAABBColor = StringToColor(settings->value(s_meshAABBColorOptionName, ColorToString(options.m_meshAABBColor)).toString());
         options.m_collisionMeshColor = StringToColor(settings->value(s_collisionMeshColorOptionName, ColorToString(options.m_collisionMeshColor)).toString());
-        options.m_OBBsColor = StringToColor(settings->value(s_OBBsColorOptionName, ColorToString(options.m_OBBsColor)).toString());
         options.m_lineSkeletonColor = StringToColor(settings->value(s_lineSkeletonColorOptionName, ColorToString(options.m_lineSkeletonColor)).toString());
         options.m_skeletonColor = StringToColor(settings->value(s_skeletonColorOptionName, ColorToString(options.m_skeletonColor)).toString());
         options.m_selectionColor = StringToColor(settings->value(s_selectionColorOptionName, ColorToString(options.m_selectionColor)).toString());
@@ -388,7 +383,6 @@ namespace EMStudio
             ->Field(s_nodeAABBColorOptionName, &RenderOptions::m_nodeAABBColor)
             ->Field(s_staticAABBColorOptionName, &RenderOptions::m_staticAABBColor)
             ->Field(s_meshAABBColorOptionName, &RenderOptions::m_meshAABBColor)
-            ->Field(s_OBBsColorOptionName, &RenderOptions::m_OBBsColor)
             ->Field(s_lineSkeletonColorOptionName, &RenderOptions::m_lineSkeletonColor)
             ->Field(s_skeletonColorOptionName, &RenderOptions::m_skeletonColor)
             ->Field(s_selectionColorOptionName, &RenderOptions::m_selectionColor)
@@ -546,9 +540,6 @@ namespace EMStudio
             ->DataElement(AZ::Edit::UIHandlers::Default, &RenderOptions::m_meshAABBColor, "Mesh based AABB color",
                 "Color for the runtime-updated AABB calculated based on the deformed meshes.")
             ->Attribute(AZ::Edit::Attributes::ChangeNotify, &RenderOptions::OnMeshAABBColorChangedCallback)
-            ->DataElement(AZ::Edit::UIHandlers::Default, &RenderOptions::m_OBBsColor, "Joint OBB color",
-                "Color used for the pre-calculated joint oriented bounding boxes.")
-            ->Attribute(AZ::Edit::Attributes::ChangeNotify, &RenderOptions::OnOBBsColorChangedCallback)
             ->DataElement(AZ::Edit::UIHandlers::Default, &RenderOptions::m_lineSkeletonColor, "Line based skeleton color",
                 "Line-based skeleton color.")
             ->Attribute(AZ::Edit::Attributes::ChangeNotify, &RenderOptions::OnLineSkeletonColorChangedCallback)
@@ -894,15 +885,6 @@ namespace EMStudio
         }
     }
 
-    void RenderOptions::SetOBBsColor(const AZ::Color& OBBsColor)
-    {
-        if (!OBBsColor.IsClose(m_OBBsColor))
-        {
-            m_OBBsColor = OBBsColor;
-            OnOBBsColorChangedCallback();
-        }
-    }
-
     void RenderOptions::SetLineSkeletonColor(const AZ::Color& lineSkeletonColor)
     {
         if (!lineSkeletonColor.IsClose(m_lineSkeletonColor))
@@ -1240,11 +1222,6 @@ namespace EMStudio
         PluginOptionsNotificationsBus::Event(s_meshAABBColorOptionName, &PluginOptionsNotificationsBus::Events::OnOptionChanged, s_meshAABBColorOptionName);
     }
 
-    void RenderOptions::OnOBBsColorChangedCallback() const
-    {
-        PluginOptionsNotificationsBus::Event(s_OBBsColorOptionName, &PluginOptionsNotificationsBus::Events::OnOptionChanged, s_OBBsColorOptionName);
-    }
-
     void RenderOptions::OnLineSkeletonColorChangedCallback() const
     {
         PluginOptionsNotificationsBus::Event(s_lineSkeletonColorOptionName, &PluginOptionsNotificationsBus::Events::OnOptionChanged, s_lineSkeletonColorOptionName);
diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderOptions.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderOptions.h
index 5e12cf935f..60f7aa1291 100644
--- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderOptions.h
+++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderOptions.h
@@ -59,7 +59,6 @@ namespace EMStudio
         static const char* s_nodeAABBColorOptionName;
         static const char* s_staticAABBColorOptionName;
         static const char* s_meshAABBColorOptionName;
-        static const char* s_OBBsColorOptionName;
         static const char* s_lineSkeletonColorOptionName;
         static const char* s_skeletonColorOptionName;
         static const char* s_selectionColorOptionName;
@@ -190,9 +189,6 @@ namespace EMStudio
         AZ::Color GetMeshAABBColor() const { return m_meshAABBColor; }
         void SetMeshAABBColor(const AZ::Color& meshAABBColor);
 
-        AZ::Color GetOBBsColor() const { return m_OBBsColor; }
-        void SetOBBsColor(const AZ::Color& OBBsColor);
-
         AZ::Color GetLineSkeletonColor() const { return m_lineSkeletonColor; }
         void SetLineSkeletonColor(const AZ::Color& lineSkeletonColor);
 
@@ -299,7 +295,6 @@ namespace EMStudio
         void OnNodeAABBColorChangedCallback() const;
         void OnStaticAABBColorChangedCallback() const;
         void OnMeshAABBColorChangedCallback() const;
-        void OnOBBsColorChangedCallback() const;
         void OnLineSkeletonColorChangedCallback() const;
         void OnSkeletonColorChangedCallback() const;
         void OnSelectionColorChangedCallback() const;
@@ -356,7 +351,6 @@ namespace EMStudio
         AZ::Color        m_nodeAABBColor;
         AZ::Color        m_staticAABBColor;
         AZ::Color        m_meshAABBColor;
-        AZ::Color        m_OBBsColor;
         AZ::Color        m_lineSkeletonColor;
         AZ::Color        m_skeletonColor;
         AZ::Color        m_selectionColor;
diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.cpp
index e4663750ce..ef281b8301 100644
--- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.cpp
+++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.cpp
@@ -1160,10 +1160,6 @@ namespace EMStudio
             renderUtil->RenderAabbs(actorInstance, settings);
         }
 
-        if (widget->GetRenderFlag(RenderViewWidget::RENDER_OBB))
-        {
-            renderUtil->RenderOBBs(actorInstance, &visibleJointIndices, &selectedJointIndices, renderOptions->GetOBBsColor(), renderOptions->GetSelectedObjectColor());
-        }
         if (widget->GetRenderFlag(RenderViewWidget::RENDER_LINESKELETON))
         {
             const MCommon::Camera* camera = widget->GetRenderWidget()->GetCamera();
diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderUpdateCallback.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderUpdateCallback.cpp
index fed309d2e5..6de228fa52 100644
--- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderUpdateCallback.cpp
+++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderUpdateCallback.cpp
@@ -174,10 +174,6 @@ namespace EMStudio
             renderUtil->RenderAabbs(actorInstance, settings);
         }
 
-        if (widget->GetRenderFlag(RenderViewWidget::RENDER_OBB))
-        {
-            renderUtil->RenderOBBs(actorInstance, &visibleJointIndices, &selectedJointIndices, renderOptions->GetOBBsColor(), renderOptions->GetSelectedObjectColor());
-        }
         if (widget->GetRenderFlag(RenderViewWidget::RENDER_LINESKELETON))
         {
             renderUtil->RenderSimpleSkeleton(actorInstance, &visibleJointIndices, &selectedJointIndices, renderOptions->GetLineSkeletonColor(), renderOptions->GetSelectedObjectColor());
diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderViewWidget.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderViewWidget.cpp
index 76e1a1e7f3..55699c165f 100644
--- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderViewWidget.cpp
+++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderViewWidget.cpp
@@ -108,7 +108,6 @@ namespace EMStudio
             CreateViewOptionEntry(contextMenu, "Face Normals", RENDER_FACENORMALS);
             CreateViewOptionEntry(contextMenu, "Tangents", RENDER_TANGENTS);
             CreateViewOptionEntry(contextMenu, "Actor Bounding Boxes", RENDER_AABB);
-            CreateViewOptionEntry(contextMenu, "Joint OBBs", RENDER_OBB, false);
             CreateViewOptionEntry(contextMenu, "Collision Meshes", RENDER_COLLISIONMESHES, false);
             contextMenu->addSeparator();
             CreateViewOptionEntry(contextMenu, "Line Skeleton", RENDER_LINESKELETON);
@@ -233,7 +232,6 @@ namespace EMStudio
         SetRenderFlag(RENDER_TANGENTS, false);
 
         SetRenderFlag(RENDER_AABB, false);
-        SetRenderFlag(RENDER_OBB, false);
         SetRenderFlag(RENDER_COLLISIONMESHES, false);
         SetRenderFlag(RENDER_RAGDOLL_COLLIDERS, true);
         SetRenderFlag(RENDER_RAGDOLL_JOINTLIMITS, true);
@@ -410,7 +408,6 @@ namespace EMStudio
         }
 
         // Override some settings as we removed those from the menu.
-        SetRenderFlag(RENDER_OBB, false);
         SetRenderFlag(RENDER_COLLISIONMESHES, false);
         SetRenderFlag(RENDER_TEXTURING, false);
 
diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderViewWidget.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderViewWidget.h
index 74e5e0ce72..defdb0d2a7 100644
--- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderViewWidget.h
+++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderViewWidget.h
@@ -52,7 +52,6 @@ namespace EMStudio
             RENDER_VERTEXNORMALS            = 6,
             RENDER_TANGENTS                 = 7,
             RENDER_AABB                     = 8,
-            RENDER_OBB                      = 9,
             RENDER_COLLISIONMESHES          = 10,
             RENDER_SKELETON                 = 11,
             RENDER_LINESKELETON             = 12,

From 8190d61e185ff31ff2d986f4447f5f2bd28d1cc4 Mon Sep 17 00:00:00 2001
From: Benjamin Jillich 
Date: Tue, 3 Aug 2021 17:14:04 +0200
Subject: [PATCH 081/803] Removed MCore::OBB

Signed-off-by: Benjamin Jillich 
---
 Gems/EMotionFX/Code/MCore/Source/OBB.cpp    | 638 --------------------
 Gems/EMotionFX/Code/MCore/Source/OBB.h      | 235 -------
 Gems/EMotionFX/Code/MCore/Source/OBB.inl    |  36 --
 Gems/EMotionFX/Code/MCore/mcore_files.cmake |   3 -
 4 files changed, 912 deletions(-)
 delete mode 100644 Gems/EMotionFX/Code/MCore/Source/OBB.cpp
 delete mode 100644 Gems/EMotionFX/Code/MCore/Source/OBB.h
 delete mode 100644 Gems/EMotionFX/Code/MCore/Source/OBB.inl

diff --git a/Gems/EMotionFX/Code/MCore/Source/OBB.cpp b/Gems/EMotionFX/Code/MCore/Source/OBB.cpp
deleted file mode 100644
index 66c47e9475..0000000000
--- a/Gems/EMotionFX/Code/MCore/Source/OBB.cpp
+++ /dev/null
@@ -1,638 +0,0 @@
-/*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
-
-// include required headers
-#include "OBB.h"
-#include "AABB.h"
-
-#include 
-#include 
-#include 
-#include 
-
-namespace MCore
-{
-    // check if the box contains a given point
-    bool OBB::Contains(const AZ::Vector3& p) const
-    {
-        // translate to box space
-        AZ::Vector3 relPoint = p - mCenter;
-
-        // convert the box into box space and test each axis
-        float f = mRotation.GetBasisX().Dot(relPoint);
-        if (f >= mExtents.GetX() || f <= -mExtents.GetX())
-        {
-            return false;
-        }
-
-        f = mRotation.GetBasisY().Dot(relPoint);
-        if (f >= mExtents.GetY() || f <= -mExtents.GetY())
-        {
-            return false;
-        }
-
-        f = mRotation.GetBasisZ().Dot(relPoint);
-        if (f >= mExtents.GetZ() || f <= -mExtents.GetZ())
-        {
-            return false;
-        }
-
-        return true;
-    }
-
-
-    void OBB::Create(const AABB& aabb, const AZ::Transform& mat)
-    {
-        // calculate the center and extents
-        mCenter  = aabb.CalcMiddle();
-        mExtents = aabb.CalcExtents();
-
-        // transform the center
-        mCenter = mat.TransformPoint(mCenter);
-
-        // set the rotation
-        mRotation = mat;
-    }
-
-
-    void OBB::Transform(const AZ::Transform& transMatrix)
-    {
-        mCenter   = transMatrix.TransformPoint(mCenter);
-        mRotation = transMatrix * mRotation;
-    }
-
-
-    void OBB::Transformed(const AZ::Transform& transMatrix, OBB* outOBB) const
-    {
-        outOBB->mExtents  = mExtents;
-        outOBB->mCenter   = transMatrix.TransformPoint(mCenter);
-        outOBB->mRotation = transMatrix * mRotation;
-    }
-
-
-    bool OBB::CheckIfIsInside(const OBB& box) const
-    {
-        // make a 4x4 from the box & inverse it
-        AZ::Transform M0 = box.mRotation;
-        M0.SetTranslation(box.mCenter);
-        AZ::Transform M0Inv = M0.GetInverse();
-
-        // with our inversed 4x4, create box1 in space of box0
-        OBB _1in0;
-        Transformed(M0Inv, &_1in0);
-
-        // this should cancel out box0's rotation, i.e. it's now an AABB
-
-        // the two boxes are in the same space so now we can compare them
-        // create the AABB of (box1 in space of box0)
-        const AZ::Transform& mtx = _1in0.mRotation;
-
-        AZ::Vector3 transformedAxisX = mtx.GetUniformScale() * (mtx.GetRotation().GetConjugate().TransformVector(AZ::Vector3::CreateAxisX()));
-        AZ::Vector3 transformedAxisY = mtx.GetUniformScale() * (mtx.GetRotation().GetConjugate().TransformVector(AZ::Vector3::CreateAxisY()));
-        AZ::Vector3 transformedAxisZ = mtx.GetUniformScale() * (mtx.GetRotation().GetConjugate().TransformVector(AZ::Vector3::CreateAxisZ()));
-
-        float f = transformedAxisX.GetAbs().Dot(mExtents) - box.mExtents.GetX();
-        if (f > _1in0.mCenter.GetX())
-        {
-            return false;
-        }
-        if (-f < _1in0.mCenter.GetX())
-        {
-            return false;
-        }
-
-        f = transformedAxisY.GetAbs().Dot(mExtents) - box.mExtents.GetY();
-        if (f > _1in0.mCenter.GetY())
-        {
-            return false;
-        }
-        if (-f < _1in0.mCenter.GetY())
-        {
-            return false;
-        }
-
-        f = transformedAxisZ.GetAbs().Dot(mExtents) - box.mExtents.GetZ();
-        if (f > _1in0.mCenter.GetZ())
-        {
-            return false;
-        }
-        if (-f < _1in0.mCenter.GetZ())
-        {
-            return false;
-        }
-
-        return true;
-    }
-
-
-    // calculate the corner points for the OBB
-    void OBB::CalcCornerPoints(AZ::Vector3* outPoints) const
-    {
-        MCORE_ASSERT(outPoints);
-        MCORE_ASSERT(CheckIfIsValid());
-
-        AZ::Vector3 right   = MCore::GetRight(mRotation);
-        AZ::Vector3 up      = MCore::GetUp(mRotation);
-        AZ::Vector3 forward = MCore::GetForward(mRotation);
-
-        right   *= mExtents.GetX();
-        up      *= mExtents.GetZ();
-        forward *= mExtents.GetY();
-
-        //     7+------+6
-        //     /|     /|
-        //    / |    / |
-        //   / 4+---/--+5
-        // 3+------+2 /
-        //  | /    | /
-        //  |/     |/
-        // 0+------+1
-
-        outPoints[0] = mCenter - right - up - forward;
-        outPoints[1] = mCenter + right - up - forward;
-        outPoints[2] = mCenter + right + up - forward;
-        outPoints[3] = mCenter - right + up - forward;
-        outPoints[4] = mCenter - right - up + forward;
-        outPoints[5] = mCenter + right - up + forward;
-        outPoints[6] = mCenter + right + up + forward;
-        outPoints[7] = mCenter - right + up + forward;
-    }
-
-
-    //----------------------------------------------------------------------------------------------------------
-
-    // calculate the 3 eigen vectors
-    void OBB::GetRealSymmetricEigenvectors(const float A[6], AZ::Vector3& v1, AZ::Vector3& v2, AZ::Vector3& v3)
-    {
-        // compute coefficients for cubic equation
-        const float c2 = A[0] + A[3] + A[5];
-        const float a12sq = A[1] * A[1];
-        const float a13sq = A[2] * A[2];
-        const float a23sq = A[4] * A[4];
-        const float a11a22 = A[0] * A[3];
-        const float c1 = a11a22 - a12sq + A[0] * A[5] - a13sq + A[3] * A[5] - a23sq;
-        const float c0 = a11a22 * A[5] + 2.0f * A[1] * A[2] * A[4] - A[0] * a23sq - A[3] * a13sq - A[5] * a12sq;
-
-        // compute intermediate values for root solving
-        const float c2sq = c2 * c2;
-        const float a = (3.0f * c1 - c2sq) / 3.0f;
-        const float b = (9.0f * c1 * c2 - 2.0f * c2sq * c2 - 27.f * c0) / 27.0f;
-        const float halfb = b * 0.5f;
-        const float halfb2 = halfb * halfb;
-        const float Q = halfb2 + a * a * a / 27.0f;
-
-        // determine type of eigenspaces
-        if (Q > 1.0e-6f)
-        {
-            // one eigenvalue, use standard basis
-            v1.Set(1.0f, 0.0f, 0.0f);
-            v2.Set(0.0f, 1.0f, 0.0f);
-            v3.Set(0.0f, 0.0f, 1.0f);
-            return;
-        }
-        else
-        if (Q < -1.0e-6f)
-        {
-            // three distinct eigenvalues
-
-            // intermediate terms
-            const float theta_3 = Math::ATan2(Math::Sqrt(-Q), -halfb) / 3.0f;
-            float rho = Math::Sqrt(halfb2 - Q);
-            const float c2_3 = c2 / 3.0f;
-            float rho_13 = powf(Math::Abs(rho), 1.0f / 3.0f);
-            if (rho < 0.0f)
-            {
-                rho_13 = -rho_13;
-            }
-            float ct_3, st_3;
-            const float sqrt3 = Math::Sqrt(3.0f);
-            ct_3 = Math::Cos(theta_3);
-            st_3 = Math::Sin(theta_3);
-
-            // compute each eigenvalue and eigenvector
-            // sort from largest to smallest
-            float lambda1 = c2_3 + 2.0f * rho_13 * ct_3;
-            CalcSymmetricEigenVector(A, lambda1, v1);
-
-            float lambda2 = c2_3 - rho_13 * (ct_3 + sqrt3 * st_3);
-            if (lambda2 > lambda1)
-            {
-                v2 = v1;
-                float temp = lambda2;
-                lambda2 = lambda1;
-                lambda1 = temp;
-                CalcSymmetricEigenVector(A, lambda2, v1);
-            }
-            else
-            {
-                CalcSymmetricEigenVector(A, lambda2, v2);
-            }
-
-            float lambda3 = c2_3 - rho_13 * (ct_3 - sqrt3 * st_3);
-            if (lambda3 > lambda1)
-            {
-                v3 = v2;
-                v2 = v1;
-                CalcSymmetricEigenVector(A, lambda3, v1);
-            }
-            else
-            if (lambda3 > lambda2)
-            {
-                v3 = v2;
-                CalcSymmetricEigenVector(A, lambda3, v2);
-            }
-            else
-            {
-                CalcSymmetricEigenVector(A, lambda3, v3);
-            }
-        }
-        else
-        {
-            // two distinct eigenvalues
-
-            // intermediate terms
-            float c2_3 = c2 / 3.0f;
-            float halfb_13 = Math::Pow(Math::Abs(halfb), 1.0f / 3.0f);
-            if (halfb < 0.0f)
-            {
-                halfb_13 = -halfb_13;
-            }
-
-            // compute each eigenvalue and eigenvector
-            // sort from largest to smallest
-            float lambda1 = c2_3 + halfb_13;
-            CalcSymmetricEigenPair(A, lambda1, v1, v2);
-
-            float lambda2 = c2_3 - 2.0f * halfb_13;
-            if (lambda2 > lambda1)
-            {
-                v3 = v2;
-                v2 = v1;
-                CalcSymmetricEigenVector(A, lambda2, v1);
-            }
-            else
-            {
-                CalcSymmetricEigenVector(A, lambda2, v3);
-            }
-        }
-
-        v1.Normalize();
-        v2.Normalize();
-        v3.Normalize();
-
-        if ((v1.Cross(v2)).Dot(v3) < 0.0f)
-        {
-            v3 = -v3;
-        }
-    }
-
-
-    // calculate the eigen vector from a symmetric matrix in combination with a given eigen value
-    void OBB::CalcSymmetricEigenVector(const float A[6], float eigenValue, AZ::Vector3& v1)
-    {
-        const float m11 = A[0] - eigenValue;
-        const float m12 = A[1];
-        const float m13 = A[2];
-        const float m22 = A[3] - eigenValue;
-        const float m23 = A[4];
-        const float m33 = A[5] - eigenValue;
-
-        // compute cross product matrix, and find column with maximal entry
-        const float u11 = m22 * m33 - m23 * m23;
-        float max = Math::Abs(u11);
-        int c = 1;
-        const float u12 = m13 * m23 - m12 * m33;
-        if (Math::Abs(u12) > max)
-        {
-            max = Math::Abs(u12);
-            c = 2;
-        }
-
-        const float u13 = m12 * m23 - m13 * m22;
-        if (Math::Abs(u13) > max)
-        {
-            max = Math::Abs(u13);
-            c = 3;
-        }
-
-        const float u22 = m11 * m33 - m13 * m13;
-        if (Math::Abs(u22) > max)
-        {
-            max = Math::Abs(u22);
-            c = 2;
-        }
-
-        const float u23 = m12 * m13 - m23 * m11;
-        if (Math::Abs(u23) > max)
-        {
-            max = Math::Abs(u23);
-            c = 3;
-        }
-
-        const float u33 = m11 * m22 - m12 * m12;
-        if (Math::Abs(u33) > max)
-        {
-            max = Math::Abs(u33);
-            c = 3;
-        }
-
-        // return column with maximal entry
-        if (c == 1)
-        {
-            v1.Set(u11, u12, u13);
-        }
-        else
-        if (c == 2)
-        {
-            v1.Set(u12, u22, u23);
-        }
-        else
-        {
-            v1.Set(u13, u23, u33);
-        }
-    }
-
-
-    //-------------------------------------------------------------------------------
-    // Given symmetric matrix A and eigenvalue l, returns eigenvector pair
-    // Assumes that order of eigenvalue is 2
-    //-------------------------------------------------------------------------------
-    void OBB::CalcSymmetricEigenPair(const float A[6], float eigenValue, AZ::Vector3& v1, AZ::Vector3& v2)
-    {
-        // find maximal entry in M
-        const float m11 = A[0] - eigenValue;
-        float max = Math::Abs(m11);
-        int r = 1, c = 1;
-        if (Math::Abs(A[1]) > max)
-        {
-            max = Math::Abs(A[1]);
-            r = 1;
-            c = 2;
-        }
-
-        if (Math::Abs(A[2]) > max)
-        {
-            max = Math::Abs(A[2]);
-            r = 1;
-            c = 3;
-        }
-
-        const float m22 = A[3] - eigenValue;
-        if (Math::Abs(m22) > max)
-        {
-            max = Math::Abs(m22);
-            r = 2;
-            c = 2;
-        }
-
-        if (Math::Abs(A[4]) > max)
-        {
-            max = Math::Abs(A[4]);
-            r = 2;
-            c = 3;
-        }
-
-        const float m33 = A[5] - eigenValue;
-        if (Math::Abs(m33) > max)
-        {
-            r = 3;
-            c = 3;
-        }
-
-        // compute eigenvectors for each case
-        if (r == 1)
-        {
-            if (c == 3)
-            {
-                v1.Set(A[2], 0.0f, -m11);
-                v2.Set(-A[1] * m11, m11 * m11 + A[2] * A[2], -A[1] * A[2]);
-            }
-            else
-            {
-                v1.Set(-A[1], m11, 0.0f);
-                v2.Set(-A[2] * m11, -A[2] * A[1], m11 * m11 + A[1] * A[1]);
-            }
-        }
-        else
-        if (r == 2)
-        {
-            v1.Set(0.0f, -A[4], m22);
-            v2.Set(m22 * m22 + A[4] * A[4], -A[1] * m22, -A[1] * A[4]);
-        }
-        else
-        if (r == 3)
-        {
-            v1.Set(0.0f, -m33, A[4]);
-            v2.Set(A[4] * A[4] + m33 * m33, -A[2] * A[4], -A[2] * m33);
-        }
-    }
-
-    //-----------------------
-
-    //-------------------------------------------------------------------------------
-    // Compute covariance matrix for set of points
-    // Returns centroid and unique values of matrix
-    //-------------------------------------------------------------------------------
-    void OBB::CovarianceMatrix(const AZ::Vector3* points, uint32 numPoints, AZ::Vector3& mean, float C[6])
-    {
-        uint32 i;
-
-        // compute mean
-        mean = points[0];
-        for (i = 1; i < numPoints; ++i)
-        {
-            mean += points[i];
-        }
-
-        mean *= 1.0f / numPoints;
-
-        // compute each element of matrix
-        memset(C, 0, sizeof(float) * 6);
-        for (i = 0; i < numPoints; ++i)
-        {
-            const AZ::Vector3 diff = points[i] - mean;
-            C[0] += diff.GetX() * diff.GetX();
-            C[1] += diff.GetX() * diff.GetY();
-            C[2] += diff.GetX() * diff.GetZ();
-            C[3] += diff.GetY() * diff.GetY();
-            C[4] += diff.GetY() * diff.GetZ();
-            C[5] += diff.GetZ() * diff.GetZ();
-        }
-
-        // normalize the matrix values
-        float maxC = 0.0f;
-        for (i = 0; i < 6; ++i)
-        {
-            if (Math::Abs(C[i]) > maxC)
-            {
-                maxC = Math::Abs(C[i]);
-            }
-        }
-        for (i = 0; i < 6; ++i)
-        {
-            C[i] /= maxC;
-        }
-    }
-
-
-    // calc the best fit for a given x rotation slice
-    void OBB::InitFromPointsRange(const AZ::Vector3* points, uint32 numPoints, float xDegrees, float* outMinArea, AABB* outMinBox, AZ::Transform* outMinMatrix)
-    {
-        // calculate the x rotation matrix
-        AZ::Transform rotMatrix = AZ::Transform::CreateRotationX(Math::DegreesToRadians(xDegrees));
-
-        // try the same over the z axis
-        for (float z = -180.0f; z < 180.0f; z += 5.0f)
-        {
-            // calculate the final rotation matrix
-            rotMatrix = AZ::Transform::CreateRotationZ(Math::DegreesToRadians(z)) * rotMatrix;
-
-            // calculate the inverse so we can transform the point set into space of this current rotation
-            AZ::Transform invMatrix = rotMatrix.GetInverse();
-
-            // rotate the points into the space of the current rotation
-            AABB box;
-            box.Init();
-            for (uint32 i = 0; i < numPoints; ++i)
-            {
-                box.Encapsulate(invMatrix.TransformPoint(points[i]));
-            }
-
-            // check if the surface area of this box is smaller than the smallest one we have
-            const float area = box.CalcSurfaceArea();
-            if (area < *outMinArea)
-            {
-                *outMinArea     = area;
-                *outMinBox      = box;
-                *outMinMatrix   = rotMatrix;
-            }
-        }
-    }
-
-
-    // Compute bounding box for set of points
-    void OBB::InitFromPoints(const AZ::Vector3* points, uint32 numPoints)
-    {
-        // if we have no points, just init
-        if (numPoints == 0)
-        {
-            Init();
-            return;
-        }
-
-        // some values we need
-        const uint32 MAX_NUM = (360 / 5) + 1;
-        AABB    minBoxes[MAX_NUM];
-        AZ::Transform  minRotMatrices[MAX_NUM];
-        float   minAreas[MAX_NUM];
-        for (uint32 i = 0; i < MAX_NUM; ++i)
-        {
-            minAreas[i] = FLT_MAX;
-        }
-
-
-        // try all rotation on the x axis (multithreaded)
-        AZ::JobCompletion jobCompletion;           
-        uint32 index = 0;
-        for (float x = -180.0f; x < 180.0f; x += 5.0f)
-        {
-            MCORE_ASSERT(index < MAX_NUM);
-
-            // create the job and add it
-            AZ::JobContext* jobContext = nullptr;
-            AZ::Job* job = AZ::CreateJobFunction([this, &minAreas, &minBoxes, &minRotMatrices, &numPoints, &points, x, index]()
-            {   
-                InitFromPointsRange(points, numPoints, x, &minAreas[index], &minBoxes[index], &minRotMatrices[index]);
-            }, true, jobContext);
-
-            job->SetDependent(&jobCompletion);
-            job->Start();
-
-            index++;
-        }
-
-        jobCompletion.StartAndWaitForCompletion();
-
-        // find the real minimum value (single threaded lookup)
-        float minimumArea = FLT_MAX;
-        uint32 minimumIndex = 0;
-        for (uint32 i = 0; i < MAX_NUM; ++i)
-        {
-            if (minAreas[i] < minimumArea)
-            {
-                minimumArea     = minAreas[i];
-                minimumIndex    = i;
-            }
-        }
-
-        // update
-        mRotation   = minRotMatrices[minimumIndex];
-        mCenter     = mRotation.TransformPoint(minBoxes[minimumIndex].CalcMiddle());
-        mExtents    = minBoxes[minimumIndex].CalcExtents();
-
-        /*
-            // compute covariance matrix
-            float C[6];
-            CovarianceMatrix( points, numPoints, mCenter, C );
-
-            // get principle axes
-            Vector3 basis[3];
-            GetRealSymmetricEigenvectors( C, basis[0], basis[1], basis[2] );
-
-            // init the min and max vectors
-            Vector3 minVec;
-            Vector3 maxVec;
-            minVec.Set(FLT_MAX, FLT_MAX, FLT_MAX);
-            maxVec.Set(-FLT_MAX, -FLT_MAX, -FLT_MAX);
-
-            // find the min and max
-            for (uint32 i=0; i maxVec[j])
-                        maxVec[j] = length;
-                    else
-                    if (length < minVec[j])
-                        minVec[j] = length;
-                }
-            }
-
-            // build the matrix from the calculated basis vectors
-            mRotation.Identity();
-            mRotation.SetRow(0, basis[0]);
-            mRotation.SetRow(1, basis[1]);
-            mRotation.SetRow(2, basis[2]);
-
-            // calculate the extents
-            mExtents = (maxVec - minVec) * 0.5f;
-        */
-    }
-
-
-    // calculate the minimum and maximum point
-    void OBB::CalcMinMaxPoints(AZ::Vector3* outMin, AZ::Vector3* outMax) const
-    {
-        AZ::Transform rotation = mRotation;
-        rotation.SetTranslation(AZ::Vector3::CreateZero());
-        AZ::Vector3 rotatedExtents = rotation.TransformPoint(mExtents);
-        *outMax = mCenter + rotatedExtents;
-        *outMin = mCenter - rotatedExtents;
-
-        //       +------+MAX
-        //      /|     /|
-        //     / |    / |
-        //    /  +---/--+
-        //   +------+  /
-        //   | /    | /
-        //   |/     |/
-        //MIN+------+
-    }
-}   // namespace MCore
diff --git a/Gems/EMotionFX/Code/MCore/Source/OBB.h b/Gems/EMotionFX/Code/MCore/Source/OBB.h
deleted file mode 100644
index 64cf61fb20..0000000000
--- a/Gems/EMotionFX/Code/MCore/Source/OBB.h
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
-
-#pragma once
-
-#include 
-#include 
-#include "StandardHeaders.h"
-
-
-namespace MCore
-{
-    // forward declarations
-    class AABB;
-
-
-    /**
-     * 3D Oriented Bounding Box (OBB) template.
-     * This is basically a AABB with an arbitrary rotation.
-     */
-    class MCORE_API OBB
-    {
-    public:
-        /**
-         * The constructor.
-         * This automatically initializes the box. After initialization the box is invalid since it basically has no size yet.
-         * The IsValid() method will return false.
-         */
-        MCORE_INLINE OBB()                                                                      { Init(); }
-
-        /**
-         * Construct the OBB from a given axis aligned bounding box and a transformation.
-         * @param aabb The axis aligned bounding box.
-         * @param transformation The transformation of the box.
-         */
-        MCORE_INLINE OBB(const AABB& aabb, const AZ::Transform& transformation)                 { Create(aabb, transformation); }
-
-        /**
-         * Construct the OBB from a center, extends and a rotation.
-         * @param center The center of the box.
-         * @param extents The extents of the box, which start at the center of the box.
-         * @param rot The matrix, representing the transformation of the box.
-         */
-        MCORE_INLINE OBB(const AZ::Vector3& center, const AZ::Vector3& extents, const AZ::Transform& rot)
-            : mRotation(rot)
-            , mExtents(extents)
-            , mCenter(center)    {}
-
-        /**
-         * Reset the OBB with as center 0,0,0, infinite negative extents and no rotation.
-         * This makes the box an invalid box as well, because the extents have not been set.
-         */
-        MCORE_INLINE void Init();
-
-        /**
-         * Initialize the box from a set of points.
-         * This uses the covariant matrix and eigen vectors to fit the box to the set of points.
-         * @param points The set of points to fit the box to.
-         * @param numPoints The number of points inside array specified as first parameter.
-         */
-        void InitFromPoints(const AZ::Vector3* points, uint32 numPoints);
-
-        /**
-         * Check if this box OBB contains a given point or not.
-         * @param p The point to check.
-         * @result Returns true when the point is inside this box, otherwise false is returned.
-         */
-        bool Contains(const AZ::Vector3& p) const;
-
-        /**
-         * Check if this OBB is inside another specified box.
-         * @param box The OBB to check.
-         * @result Returns true when this OBB is inside the box specified as parameter.
-         */
-        bool CheckIfIsInside(const OBB& box) const;
-
-        /**
-         * Create the OBB from a given AABB and a matrix.
-         * @param aabb The axis aligned bounding box.
-         * @param mat The matrix, which represents the orientation of the box.
-         */
-        void Create(const AABB& aabb, const AZ::Transform& mat);
-
-        /**
-         * Transform this OBB with a given matrix.
-         * This means the transformation specified as parameter will be applied to the current transformation of the OBB.
-         * So the transformation specified is NOT an absolute rotation, but a relative transformation.
-         * @param transMatrix The relative transformation matrix, to be applied to the current transformation.
-         */
-        void Transform(const AZ::Transform& transMatrix);
-
-        /**
-         * Calculate the transformed version of this OBB.
-         * @param rotMatrix The transformation matrix to be applied to the rotation of this OBB, so not an absolute rotation!
-         * @param outOBB A pointer to the OBB to fill with the rotated version of this OBB.
-         */
-        void Transformed(const AZ::Transform& rotMatrix, OBB* outOBB) const;
-
-        /**
-         * Check if this is a valid OBB or not.
-         * The box is only valid if the extents are non-negative.
-         * @result Returns true when the OBB is valid, otherwise false is returned.
-         */
-        MCORE_INLINE bool CheckIfIsValid() const;
-
-        /**
-         * Set the center of the box.
-         * @param center The new center of the box.
-         */
-        MCORE_INLINE void SetCenter(const AZ::Vector3& center)                                      { mCenter = center; }
-
-        /**
-         * Set the extents of the box.
-         * @param extents The new extents of the box.
-         */
-        MCORE_INLINE void SetExtents(const AZ::Vector3& extents)                                    { mExtents = extents; }
-
-        /**
-         * Set the transformation of the box.
-         * @param transform The new transformation of the box.
-         */
-        MCORE_INLINE void SetTransformation(const AZ::Transform& transform)                         { mRotation = transform; }
-
-        /**
-         * Get the center of the box.
-         * @result The center point of the box.
-         */
-        MCORE_INLINE const AZ::Vector3& GetCenter() const                                           { return mCenter; }
-
-        /**
-         * Get the extents of the box.
-         * @result The extents of the box, which start at the center.
-         */
-        MCORE_INLINE const AZ::Vector3& GetExtents() const                                          { return mExtents; }
-
-        /**
-         * Get the transformation of the box.
-         * @result The transformation of the box.
-         */
-        MCORE_INLINE const AZ::Transform& GetTransformation() const                                 { return mRotation; }
-
-        /**
-         * Calculate the 8 corner points of the box.
-         * The layout is as follows:
-         * 
-         *
-         *     7+------+6
-         *     /|     /|
-         *    / |    / |
-         *   / 4+---/--+5
-         * 3+------+2 /
-         *  | /    | /
-         *  |/     |/
-         * 0+------+1
-         *
-         * 
- * @param outPoints the array of at least 8 vectors to write the points in. - */ - void CalcCornerPoints(AZ::Vector3* outPoints) const; - - /** - * Calculate the rotated minimum and maximum points of the box. - * After rotation it is possible that the min point is not really the min anymore though. The same goes for max. - * But the main use for this method however is to quickly approximate an AABB from this OBB, without having to - * calculate all 8 corner points. - *
-         *
-         *        +------+MAX
-         *       /|     /|
-         *      / |    / |
-         *     /  +---/--+
-         *    +------+  /
-         *    | /    | /
-         *    |/     |/
-         * MIN+------+
-         *
-         * 
- * @param outMin The vector that we will write the minimum point to. - * @param outMax The vector that we will write the maximum point to. - */ - void CalcMinMaxPoints(AZ::Vector3* outMin, AZ::Vector3* outMax) const; - - private: - AZ::Transform mRotation; /**< The rotation of the box. */ // TODO: store the center inside the translation component and extents inside last column? - AZ::Vector3 mExtents; /**< The extents of the box. */ - AZ::Vector3 mCenter; /**< The center of the box. */ - - /** - * Calculate the three eigen vectors for a symmetric matrix. - * @param A The symmetric matrix values. - * @param v1 The first output eigen vector. - * @param v2 The second output eigen vector. - * @param v3 The third output eigen vector. - */ - void GetRealSymmetricEigenvectors(const float A[6], AZ::Vector3& v1, AZ::Vector3& v2, AZ::Vector3& v3); - - /** - * Calculate the eigen vector from a symmetric matrix. - * This assumes that the specified eigenvalue is of order 1. - * @param A The symmetric matrix values. - * @param eigenValue The eigen value. - * @param v1 The output eigen vector. - */ - void CalcSymmetricEigenVector(const float A[6], float eigenValue, AZ::Vector3& v1); - - /** - * Calculate the pair of eigen vectors from a symmetric matrix. - * This assumes that the specified eigen value is of order 2. - * @param A The symmetric matrix values. - * @param eigenValue The eigen value. - * @param v1 The first output eigen vector. - * @param v2 The second output eigen vector. - */ - void CalcSymmetricEigenPair(const float A[6], float eigenValue, AZ::Vector3& v1, AZ::Vector3& v2); - - /** - * Calculate the covariance matrix from a set of points. - * @param points The set of points to calculate the covariance matrix from. - * @param numPoints The number of points inside the specified set of points. - * @param mean The statistical mean will be output in this vector. - * @param C The covariance matrix values that will be written to. Since the matrix is symmetric we only output one triangle of the 3x3 matrix. - */ - void CovarianceMatrix(const AZ::Vector3 * points, uint32 numPoints, AZ::Vector3 & mean, float C[6]); - - void InitFromPointsRange(const AZ::Vector3* points, uint32 numPoints, float xDegrees, float* outMinArea, AABB* outMinBox, AZ::Transform* outMinMatrix); - }; - - // include the inline code -#include "OBB.inl" -} // namespace MCore diff --git a/Gems/EMotionFX/Code/MCore/Source/OBB.inl b/Gems/EMotionFX/Code/MCore/Source/OBB.inl deleted file mode 100644 index e8d82dd247..0000000000 --- a/Gems/EMotionFX/Code/MCore/Source/OBB.inl +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -// initialize the box -// this creates an invalid box (with negative extents) so the IsValid method will return false -MCORE_INLINE void OBB::Init() -{ - mCenter = AZ::Vector3::CreateZero(); - mExtents.Set(-FLT_MAX, -FLT_MAX, -FLT_MAX); - mRotation = AZ::Transform::CreateIdentity(); -} - - -// check if the OBB is valid -MCORE_INLINE bool OBB::CheckIfIsValid() const -{ - if (mExtents.GetX() < 0.0f) - { - return false; - } - if (mExtents.GetY() < 0.0f) - { - return false; - } - if (mExtents.GetZ() < 0.0f) - { - return false; - } - return true; -} - diff --git a/Gems/EMotionFX/Code/MCore/mcore_files.cmake b/Gems/EMotionFX/Code/MCore/mcore_files.cmake index b0d8a67ccd..43a41b4a11 100644 --- a/Gems/EMotionFX/Code/MCore/mcore_files.cmake +++ b/Gems/EMotionFX/Code/MCore/mcore_files.cmake @@ -101,9 +101,6 @@ set(FILES Source/MemoryTracker.cpp Source/MemoryTracker.h Source/MultiThreadManager.h - Source/OBB.cpp - Source/OBB.h - Source/OBB.inl Source/PlaneEq.cpp Source/PlaneEq.h Source/PlaneEq.inl From 854e5409505c0a80dc015b67d7455125e1e6d156 Mon Sep 17 00:00:00 2001 From: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> Date: Tue, 3 Aug 2021 12:42:48 -0400 Subject: [PATCH 082/803] Cleanup Signed-off-by: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> --- .../Debug/MultiplayerDebugByteReporter.cpp | 19 +++-- .../Debug/MultiplayerDebugByteReporter.h | 8 +- .../MultiplayerDebugPerEntityReporter.cpp | 76 ++++++++++--------- .../Debug/MultiplayerDebugPerEntityReporter.h | 18 ++--- .../Debug/MultiplayerDebugSystemComponent.cpp | 15 ++-- .../Debug/MultiplayerDebugSystemComponent.h | 4 +- 6 files changed, 74 insertions(+), 66 deletions(-) diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.cpp b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.cpp index 361f9d943d..f69291013a 100644 --- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.cpp +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.cpp @@ -14,6 +14,11 @@ namespace Multiplayer { + MultiplayerDebugByteReporter::MultiplayerDebugByteReporter() + { + MultiplayerDebugByteReporter::Reset(); + } + void MultiplayerDebugByteReporter::ReportBytes(size_t byteSize) { m_count++; @@ -80,9 +85,9 @@ namespace Multiplayer m_lastUpdateTime = now; } - constexpr float k_bitsPerByte = 8.0f; - constexpr int k_bitsPerKilobit = 1024; - return k_bitsPerByte * m_totalBytesLastSecond / k_bitsPerKilobit; + constexpr float bitsPerByte = 8.0f; + constexpr int bitsPerKilobit = 1024; + return bitsPerByte * m_totalBytesLastSecond / bitsPerKilobit; } void MultiplayerDebugByteReporter::Combine(const MultiplayerDebugByteReporter& other) @@ -139,9 +144,9 @@ namespace Multiplayer { MultiplayerDebugByteReporter::Combine(other); - for (const auto& fieldIter : other.m_fieldReports) + for (const auto& fieldIterator : other.m_fieldReports) { - m_fieldReports[fieldIter.first].Combine(fieldIter.second); + m_fieldReports[fieldIterator.first].Combine(fieldIterator.second); } m_componentDirtyBytes.Combine(other.m_componentDirtyBytes); @@ -176,9 +181,9 @@ namespace Multiplayer { MultiplayerDebugByteReporter::Combine(other); - for (const auto& componentIter : other.m_componentReports) + for (const auto& componentIterator : other.m_componentReports) { - m_componentReports[componentIter.first].Combine(componentIter.second); + m_componentReports[componentIterator.first].Combine(componentIterator.second); } SetEntityName(other.GetEntityName()); diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.h b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.h index 279f7fb360..8f7513d5d4 100644 --- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.h +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.h @@ -18,7 +18,7 @@ namespace Multiplayer class MultiplayerDebugByteReporter { public: - MultiplayerDebugByteReporter() { MultiplayerDebugByteReporter::Reset(); } + MultiplayerDebugByteReporter(); virtual ~MultiplayerDebugByteReporter() = default; void ReportBytes(size_t byteSize); @@ -48,7 +48,8 @@ namespace Multiplayer AZStd::chrono::monotonic_clock::time_point m_lastUpdateTime; }; - class MultiplayerDebugComponentReporter : public MultiplayerDebugByteReporter + class MultiplayerDebugComponentReporter final + : public MultiplayerDebugByteReporter { public: MultiplayerDebugComponentReporter() = default; @@ -66,7 +67,8 @@ namespace Multiplayer MultiplayerDebugByteReporter m_componentDirtyBytes; }; - class MultiplayerDebugEntityReporter : public MultiplayerDebugByteReporter + class MultiplayerDebugEntityReporter final + : public MultiplayerDebugByteReporter { public: MultiplayerDebugEntityReporter() = default; diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.cpp b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.cpp index b0bfe097e1..adfef397b6 100644 --- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.cpp +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.cpp @@ -17,16 +17,16 @@ #include #endif -AZ_CVAR(float, net_DebugNetworkEntity_ShowAboveKbps, 1.f, nullptr, AZ::ConsoleFunctorFlags::Null, +AZ_CVAR(float, net_DebugEntities_ShowAboveKbps, 1.f, nullptr, AZ::ConsoleFunctorFlags::Null, "Prints bandwidth on network entities with higher kpbs than this value"); -AZ_CVAR(float, net_DebugNetworkEntity_WarnAboveKbps, 10.f, nullptr, AZ::ConsoleFunctorFlags::Null, +AZ_CVAR(float, net_DebugEntities_WarnAboveKbps, 10.f, nullptr, AZ::ConsoleFunctorFlags::Null, "Prints bandwidth on network entities with higher kpbs than this value"); -AZ_CVAR(AZ::Color, net_DebugNetworkEntity_WarningColor, AZ::Colors::Red, nullptr, AZ::ConsoleFunctorFlags::Null, +AZ_CVAR(AZ::Color, net_DebugEntities_WarningColor, AZ::Colors::Red, nullptr, AZ::ConsoleFunctorFlags::Null, "If true, prints debug text over entities that use a considerable amount of network traffic"); -AZ_CVAR(AZ::Color, net_DebugNetworkEntity_BelowWarningColor, AZ::Colors::Grey, nullptr, AZ::ConsoleFunctorFlags::Null, +AZ_CVAR(AZ::Color, net_DebugEntities_BelowWarningColor, AZ::Colors::Grey, nullptr, AZ::ConsoleFunctorFlags::Null, "If true, prints debug text over entities that use a considerable amount of network traffic"); namespace Multiplayer @@ -133,7 +133,8 @@ namespace Multiplayer { RecordEntitySerializeStart(mode, entityId, entityName); }); - m_eventHandlers.m_componentSerializeEnd = decltype(m_eventHandlers.m_componentSerializeEnd)([this](AzNetworking::SerializerMode mode, Multiplayer::NetComponentId netComponentId) + m_eventHandlers.m_componentSerializeEnd = decltype(m_eventHandlers.m_componentSerializeEnd)([this](AzNetworking::SerializerMode mode, + NetComponentId netComponentId) { RecordComponentSerializeEnd(mode, netComponentId); }); @@ -141,19 +142,25 @@ namespace Multiplayer { RecordEntitySerializeStop(mode, entityId, entityName); }); - m_eventHandlers.m_propertySent = decltype(m_eventHandlers.m_propertySent)([this](Multiplayer::NetComponentId netComponentId, Multiplayer::PropertyIndex propertyId, uint32_t totalBytes) + m_eventHandlers.m_propertySent = decltype(m_eventHandlers.m_propertySent)([this](NetComponentId netComponentId, + PropertyIndex propertyId, uint32_t totalBytes) { RecordPropertySent(netComponentId, propertyId, totalBytes); }); - m_eventHandlers.m_propertyReceived = decltype(m_eventHandlers.m_propertyReceived)([this](Multiplayer::NetComponentId netComponentId, Multiplayer::PropertyIndex propertyId, uint32_t totalBytes) + m_eventHandlers.m_propertyReceived = decltype(m_eventHandlers.m_propertyReceived)([this](NetComponentId netComponentId, + PropertyIndex propertyId, uint32_t totalBytes) { RecordPropertyReceived(netComponentId, propertyId, totalBytes); }); - m_eventHandlers.m_rpcSent = decltype(m_eventHandlers.m_rpcSent)([this](AZ::EntityId entityId, const char* entityName, Multiplayer::NetComponentId netComponentId, Multiplayer::RpcIndex rpcId, uint32_t totalBytes) + m_eventHandlers.m_rpcSent = decltype(m_eventHandlers.m_rpcSent)([this](AZ::EntityId entityId, const char* entityName, + NetComponentId netComponentId, + RpcIndex rpcId, uint32_t totalBytes) { RecordRpcSent(entityId, entityName, netComponentId, rpcId, totalBytes); }); - m_eventHandlers.m_rpcReceived = decltype(m_eventHandlers.m_rpcReceived)([this](AZ::EntityId entityId, const char* entityName, Multiplayer::NetComponentId netComponentId, Multiplayer::RpcIndex rpcId, uint32_t totalBytes) + m_eventHandlers.m_rpcReceived = decltype(m_eventHandlers.m_rpcReceived)([this](AZ::EntityId entityId, const char* entityName, + NetComponentId netComponentId, + RpcIndex rpcId, uint32_t totalBytes) { RecordRpcSent(entityId, entityName, netComponentId, rpcId, totalBytes); }); @@ -161,11 +168,6 @@ namespace Multiplayer GetMultiplayer()->GetStats().ConnectHandlers(m_eventHandlers); } - MultiplayerDebugPerEntityReporter::~MultiplayerDebugPerEntityReporter() - { - m_updateDebugOverlay.RemoveFromQueue(); - } - // -------------------------------------------------------------------------------------------- void MultiplayerDebugPerEntityReporter::OnImGuiUpdate() { @@ -228,7 +230,8 @@ namespace Multiplayer } } - void MultiplayerDebugPerEntityReporter::RecordComponentSerializeEnd(AzNetworking::SerializerMode mode, [[maybe_unused]] Multiplayer::NetComponentId netComponentId) + void MultiplayerDebugPerEntityReporter::RecordComponentSerializeEnd(AzNetworking::SerializerMode mode, [[maybe_unused]] NetComponentId + netComponentId) { switch (mode) { @@ -256,11 +259,11 @@ namespace Multiplayer } void MultiplayerDebugPerEntityReporter::RecordPropertySent( - Multiplayer::NetComponentId netComponentId, - Multiplayer::PropertyIndex propertyId, + NetComponentId netComponentId, + PropertyIndex propertyId, uint32_t totalBytes) { - if (const Multiplayer::MultiplayerComponentRegistry* componentRegistry = Multiplayer::GetMultiplayerComponentRegistry()) + if (const MultiplayerComponentRegistry* componentRegistry = GetMultiplayerComponentRegistry()) { m_currentSendingEntityReport.ReportField(static_cast(netComponentId), componentRegistry->GetComponentName(netComponentId), @@ -269,11 +272,11 @@ namespace Multiplayer } void MultiplayerDebugPerEntityReporter::RecordPropertyReceived( - Multiplayer::NetComponentId netComponentId, - Multiplayer::PropertyIndex propertyId, + NetComponentId netComponentId, + PropertyIndex propertyId, uint32_t totalBytes) { - if (const Multiplayer::MultiplayerComponentRegistry* componentRegistry = Multiplayer::GetMultiplayerComponentRegistry()) + if (const MultiplayerComponentRegistry* componentRegistry = GetMultiplayerComponentRegistry()) { m_currentReceivingEntityReport.ReportField(static_cast(netComponentId), componentRegistry->GetComponentName(netComponentId), @@ -281,9 +284,10 @@ namespace Multiplayer } } - void MultiplayerDebugPerEntityReporter::RecordRpcSent(AZ::EntityId entityId, const char* entityName, Multiplayer::NetComponentId netComponentId, Multiplayer::RpcIndex rpcId, uint32_t totalBytes) + void MultiplayerDebugPerEntityReporter::RecordRpcSent(AZ::EntityId entityId, const char* entityName, NetComponentId netComponentId, + RpcIndex rpcId, uint32_t totalBytes) { - if (const Multiplayer::MultiplayerComponentRegistry* componentRegistry = Multiplayer::GetMultiplayerComponentRegistry()) + if (const MultiplayerComponentRegistry* componentRegistry = GetMultiplayerComponentRegistry()) { // MultiplayerDebugByteReporter requires a RecordEntitySerializeStart(AzNetworking::SerializerMode::ReadFromObject, entityId, entityName); @@ -303,7 +307,7 @@ namespace Multiplayer RpcIndex rpcId, uint32_t totalBytes) { - if (const Multiplayer::MultiplayerComponentRegistry* componentRegistry = Multiplayer::GetMultiplayerComponentRegistry()) + if (const MultiplayerComponentRegistry* componentRegistry = GetMultiplayerComponentRegistry()) { RecordEntitySerializeStart(AzNetworking::SerializerMode::WriteToObject, entityId, entityName); @@ -320,19 +324,18 @@ namespace Multiplayer { m_networkEntitiesTraffic.clear(); + // Merging up and down traffic to provide a unified debug text per entity for (AZStd::pair& entityPair : m_receivingEntityReports) { m_networkEntitiesTraffic[entityPair.first].m_name = entityPair.second.GetEntityName(); m_networkEntitiesTraffic[entityPair.first].m_down = entityPair.second.GetKbitsPerSecond(); } - for (AZStd::pair& entityPair : m_sendingEntityReports) { m_networkEntitiesTraffic[entityPair.first].m_name = entityPair.second.GetEntityName(); m_networkEntitiesTraffic[entityPair.first].m_up = entityPair.second.GetKbitsPerSecond(); } - //get debug display interface for the viewport if (m_debugDisplay == nullptr) { AzFramework::DebugDisplayRequestBus::BusPtr debugDisplayBus; @@ -342,28 +345,28 @@ namespace Multiplayer const AZ::u32 stateBefore = m_debugDisplay->GetState(); - for (AZStd::pair& networkEntity : m_networkEntitiesTraffic) + for (const AZStd::pair& networkEntity : m_networkEntitiesTraffic) { - if (networkEntity.second.m_down < net_DebugNetworkEntity_ShowAboveKbps && networkEntity.second.m_up < net_DebugNetworkEntity_ShowAboveKbps) + if (networkEntity.second.m_down < net_DebugEntities_ShowAboveKbps && networkEntity.second.m_up < net_DebugEntities_ShowAboveKbps) { continue; } - if (networkEntity.second.m_down > net_DebugNetworkEntity_WarnAboveKbps || networkEntity.second.m_up > net_DebugNetworkEntity_WarnAboveKbps) + if (networkEntity.second.m_down > net_DebugEntities_WarnAboveKbps || networkEntity.second.m_up > net_DebugEntities_WarnAboveKbps) { - m_debugDisplay->SetColor(net_DebugNetworkEntity_WarningColor); + m_debugDisplay->SetColor(net_DebugEntities_WarningColor); } else { - m_debugDisplay->SetColor(net_DebugNetworkEntity_BelowWarningColor); + m_debugDisplay->SetColor(net_DebugEntities_BelowWarningColor); } - if (networkEntity.second.m_down > net_DebugNetworkEntity_ShowAboveKbps && networkEntity.second.m_up > net_DebugNetworkEntity_ShowAboveKbps) + if (networkEntity.second.m_down > net_DebugEntities_ShowAboveKbps && networkEntity.second.m_up > net_DebugEntities_ShowAboveKbps) { azsprintf(m_statusBuffer, "[%s] %.0f down / %0.f up (kbps)", networkEntity.second.m_name, networkEntity.second.m_down, networkEntity.second.m_up); } - else if (networkEntity.second.m_down > net_DebugNetworkEntity_ShowAboveKbps) + else if (networkEntity.second.m_down > net_DebugEntities_ShowAboveKbps) { azsprintf(m_statusBuffer, "[%s] %.0f down (kbps)", networkEntity.second.m_name, networkEntity.second.m_down); } @@ -373,9 +376,12 @@ namespace Multiplayer } AZ::Vector3 entityPosition = AZ::Vector3::CreateZero(); - constexpr bool centerText = true; AZ::TransformBus::EventResult(entityPosition, networkEntity.first, &AZ::TransformBus::Events::GetWorldTranslation); - m_debugDisplay->DrawTextLabel(entityPosition, 1.0f, m_statusBuffer, centerText, 0, 0); + if (entityPosition.IsZero() == false) + { + constexpr bool centerText = true; + m_debugDisplay->DrawTextLabel(entityPosition, 1.0f, m_statusBuffer, centerText, 0, 0); + } } m_debugDisplay->SetState(stateBefore); diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.h b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.h index 8a33bc78ee..8a68110b93 100644 --- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.h +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.h @@ -18,34 +18,34 @@ namespace Multiplayer { /** - * \brief GridMate network live analysis tool via ImGui. + * \brief Multiplayer traffic live analysis tool via ImGui. */ class MultiplayerDebugPerEntityReporter { public: MultiplayerDebugPerEntityReporter(); - ~MultiplayerDebugPerEntityReporter(); - // main update loop + //! main update loop void OnImGuiUpdate(); //! Event handlers // @{ void RecordEntitySerializeStart(AzNetworking::SerializerMode mode, AZ::EntityId entityId, const char* entityName); - void RecordComponentSerializeEnd(AzNetworking::SerializerMode mode, Multiplayer::NetComponentId netComponentId); + void RecordComponentSerializeEnd(AzNetworking::SerializerMode mode, NetComponentId netComponentId); void RecordEntitySerializeStop(AzNetworking::SerializerMode mode, AZ::EntityId entityId, const char* entityName); - void RecordPropertySent(Multiplayer::NetComponentId netComponentId, Multiplayer::PropertyIndex propertyId, uint32_t totalBytes); - void RecordPropertyReceived(Multiplayer::NetComponentId netComponentId, Multiplayer::PropertyIndex propertyId, uint32_t totalBytes); - void RecordRpcSent(AZ::EntityId entityId, const char* entityName, Multiplayer::NetComponentId netComponentId, Multiplayer::RpcIndex rpcId, uint32_t totalBytes); - void RecordRpcReceived(AZ::EntityId entityId, const char* entityName, Multiplayer::NetComponentId netComponentId, Multiplayer::RpcIndex rpcId, uint32_t totalBytes); + void RecordPropertySent(NetComponentId netComponentId, PropertyIndex propertyId, uint32_t totalBytes); + void RecordPropertyReceived(NetComponentId netComponentId, PropertyIndex propertyId, uint32_t totalBytes); + void RecordRpcSent(AZ::EntityId entityId, const char* entityName, NetComponentId netComponentId, RpcIndex rpcId, uint32_t totalBytes); + void RecordRpcReceived(AZ::EntityId entityId, const char* entityName, NetComponentId netComponentId, RpcIndex rpcId, uint32_t totalBytes); // }@ + //! Draws bandwidth text over entities void UpdateDebugOverlay(); private: AZ::ScheduledEvent m_updateDebugOverlay; - Multiplayer::MultiplayerStats::EventHandlers m_eventHandlers; + MultiplayerStats::EventHandlers m_eventHandlers; AZStd::map m_sendingEntityReports{}; MultiplayerDebugEntityReporter m_currentSendingEntityReport; diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.cpp b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.cpp index 407b6f5f2d..b6dc9573fa 100644 --- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.cpp @@ -13,9 +13,9 @@ #include #include -void OnDebugNetworkEntity_ShowBandwidth_Changed(const bool& showBandwidth); +void OnDebugEntities_ShowBandwidth_Changed(const bool& showBandwidth); -AZ_CVAR(bool, net_DebugNetworkEntity_ShowBandwidth, false, &OnDebugNetworkEntity_ShowBandwidth_Changed, AZ::ConsoleFunctorFlags::Null, +AZ_CVAR(bool, net_DebugEntities_ShowBandwidth, false, &OnDebugEntities_ShowBandwidth_Changed, AZ::ConsoleFunctorFlags::Null, "If true, prints bandwidth values over entities that use a considerable amount of network traffic"); namespace Multiplayer @@ -458,13 +458,10 @@ namespace Multiplayer { if (ImGui::Begin("Multiplayer Per Entity Stats", &m_displayPerEntityStats, ImGuiWindowFlags_AlwaysAutoResize)) { - if (ImGui::Checkbox("Show Bandwidth over Entities", &m_displayPerEntityBandwidth)) + // This overrides @net_DebugNetworkEntity_ShowBandwidth value + if (m_reporter == nullptr) { - // This overrides @net_DebugNetworkEntity_ShowBandwidth value - if (m_reporter == nullptr) - { - ShowEntityBandwidthDebugOverlay(); - } + ShowEntityBandwidthDebugOverlay(); } if (m_reporter) @@ -477,7 +474,7 @@ namespace Multiplayer #endif } -void OnDebugNetworkEntity_ShowBandwidth_Changed(const bool& showBandwidth) +void OnDebugEntities_ShowBandwidth_Changed(const bool& showBandwidth) { if (showBandwidth) { diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.h b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.h index 9be53cca02..7555073f10 100644 --- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.h +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.h @@ -43,7 +43,7 @@ namespace Multiplayer void Deactivate() override; //! @} - //! IMultiplayerDebugSystem overrides + //! IMultiplayerDebug overrides //! @{ void ShowEntityBandwidthDebugOverlay() override; void HideEntityBandwidthDebugOverlay() override; @@ -62,8 +62,6 @@ namespace Multiplayer bool m_displayMultiplayerStats = false; bool m_displayPerEntityStats = false; - bool m_displayPerEntityBandwidth = false; - AZStd::unique_ptr m_reporter; }; } From 2118ef7a21ad2d5d80979e80d9516e9a6177a443 Mon Sep 17 00:00:00 2001 From: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> Date: Tue, 3 Aug 2021 12:48:36 -0400 Subject: [PATCH 083/803] Preparing for PR Signed-off-by: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> --- Gems/Multiplayer/Code/Include/Multiplayer/IMultiplayerDebug.h | 4 ++-- .../Code/Source/Debug/MultiplayerDebugSystemComponent.cpp | 4 ---- .../Code/Source/Debug/MultiplayerDebugSystemComponent.h | 1 - 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/IMultiplayerDebug.h b/Gems/Multiplayer/Code/Include/Multiplayer/IMultiplayerDebug.h index 384db66317..e528a44ed9 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/IMultiplayerDebug.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/IMultiplayerDebug.h @@ -19,10 +19,10 @@ namespace Multiplayer virtual ~IMultiplayerDebug() = default; - //! + //! Enables printing of debug text over entities that have significant amount of traffic. virtual void ShowEntityBandwidthDebugOverlay() = 0; - //! + //! Disables printing of debug text over entities that have significant amount of traffic. virtual void HideEntityBandwidthDebugOverlay() = 0; }; } diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.cpp b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.cpp index b6dc9573fa..27a4dff485 100644 --- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.cpp @@ -63,10 +63,6 @@ namespace Multiplayer m_reporter.reset(); } - void MultiplayerDebugSystemComponent::OnImGuiInitialize() - { - } - #ifdef IMGUI_ENABLED void MultiplayerDebugSystemComponent::OnImGuiMainMenuUpdate() { diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.h b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.h index 7555073f10..7b3c852f58 100644 --- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.h +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.h @@ -52,7 +52,6 @@ namespace Multiplayer #ifdef IMGUI_ENABLED //! ImGui::ImGuiUpdateListenerBus overrides //! @{ - void OnImGuiInitialize() override; void OnImGuiMainMenuUpdate() override; void OnImGuiUpdate() override; //! @} From 72aed355cedf9fe28e24e396c64db93a4b1946a2 Mon Sep 17 00:00:00 2001 From: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> Date: Tue, 3 Aug 2021 12:54:32 -0400 Subject: [PATCH 084/803] Cleanup Signed-off-by: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> --- .../Source/NetworkEntity/EntityReplication/EntityReplicator.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicator.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicator.cpp index 457ed3eed5..4155f8813b 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicator.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicator.cpp @@ -30,8 +30,6 @@ #include -#pragma optimize("", off) - namespace Multiplayer { EntityReplicator::EntityReplicator From 65704110ad283e031f3ee9bae1d74b340f5e3f80 Mon Sep 17 00:00:00 2001 From: evanchia Date: Tue, 3 Aug 2021 10:28:45 -0700 Subject: [PATCH 085/803] removing pytest skips on smoke tests Signed-off-by: evanchia --- .../PythonTests/smoke/test_RemoteConsole_CPULoadLevel_Works.py | 2 -- .../PythonTests/smoke/test_RemoteConsole_GPULoadLevel_Works.py | 2 -- 2 files changed, 4 deletions(-) diff --git a/AutomatedTesting/Gem/PythonTests/smoke/test_RemoteConsole_CPULoadLevel_Works.py b/AutomatedTesting/Gem/PythonTests/smoke/test_RemoteConsole_CPULoadLevel_Works.py index 54d7b3eb6f..6522514f2f 100644 --- a/AutomatedTesting/Gem/PythonTests/smoke/test_RemoteConsole_CPULoadLevel_Works.py +++ b/AutomatedTesting/Gem/PythonTests/smoke/test_RemoteConsole_CPULoadLevel_Works.py @@ -13,8 +13,6 @@ Test should run in both gpu and non gpu import pytest import psutil -# Bail on the test if ly_test_tools doesn't exist. -pytest.importorskip("ly_test_tools") import ly_test_tools.environment.waiter as waiter import editor_python_test_tools.hydra_test_utils as editor_test_utils from ly_remote_console.remote_console_commands import RemoteConsole as RemoteConsole diff --git a/AutomatedTesting/Gem/PythonTests/smoke/test_RemoteConsole_GPULoadLevel_Works.py b/AutomatedTesting/Gem/PythonTests/smoke/test_RemoteConsole_GPULoadLevel_Works.py index bfce7895e6..7debcab938 100644 --- a/AutomatedTesting/Gem/PythonTests/smoke/test_RemoteConsole_GPULoadLevel_Works.py +++ b/AutomatedTesting/Gem/PythonTests/smoke/test_RemoteConsole_GPULoadLevel_Works.py @@ -13,8 +13,6 @@ Test should run in both gpu and non gpu import pytest import psutil -# Bail on the test if ly_test_tools doesn't exist. -pytest.importorskip("ly_test_tools") import ly_test_tools.environment.waiter as waiter import editor_python_test_tools.hydra_test_utils as editor_test_utils from ly_remote_console.remote_console_commands import RemoteConsole as RemoteConsole From 963cbcaf6184092aade9924475b530ed70523087 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Tue, 3 Aug 2021 10:31:43 -0700 Subject: [PATCH 086/803] Remove A version of some fw declarations and macro defines since those are error prone to define, if someone were to include windows.h after that header, it would cause issues Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../AzCore/AzCore/std/parallel/binary_semaphore.h | 4 ++-- .../Common/WinAPI/AzCore/std/parallel/config_WinAPI.h | 8 -------- .../AzCore/std/parallel/internal/semaphore_WinAPI.h | 4 ++-- 3 files changed, 4 insertions(+), 12 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/std/parallel/binary_semaphore.h b/Code/Framework/AzCore/AzCore/std/parallel/binary_semaphore.h index 797de5fceb..f9d0cdbe4d 100644 --- a/Code/Framework/AzCore/AzCore/std/parallel/binary_semaphore.h +++ b/Code/Framework/AzCore/AzCore/std/parallel/binary_semaphore.h @@ -38,13 +38,13 @@ namespace AZStd binary_semaphore(bool initialState = false) { - m_event = CreateEvent(nullptr, false, initialState, nullptr); + m_event = CreateEventW(nullptr, false, initialState, nullptr); AZ_Assert(m_event != NULL, "CreateEvent error: %d\n", GetLastError()); } binary_semaphore(const char* name, bool initialState = false) { (void)name; // name is used only for debug, if we pass it to the semaphore it will become named semaphore - m_event = CreateEvent(nullptr, false, initialState, nullptr); + m_event = CreateEventW(nullptr, false, initialState, nullptr); AZ_Assert(m_event != NULL, "CreateEvent error: %d\n", GetLastError()); } diff --git a/Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/std/parallel/config_WinAPI.h b/Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/std/parallel/config_WinAPI.h index fb91e4d503..86117c0539 100644 --- a/Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/std/parallel/config_WinAPI.h +++ b/Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/std/parallel/config_WinAPI.h @@ -71,19 +71,11 @@ extern "C" using LPSECURITY_ATTRIBUTES = SECURITY_ATTRIBUTES*; // Semaphore - AZ_DLL_IMPORT HANDLE _stdcall CreateSemaphoreA(LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, LONG lInitialCount, LONG lMaximumCount, LPCSTR lpName); AZ_DLL_IMPORT HANDLE _stdcall CreateSemaphoreW(LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, LONG lInitialCount, LONG lMaximumCount, LPCWSTR lpName); AZ_DLL_IMPORT BOOL _stdcall ReleaseSemaphore(HANDLE hSemaphore, LONG lReleaseCount, LPLONG lpPreviousCount); - #ifndef CreateSemaphore - #define CreateSemaphore CreateSemaphoreW - #endif // Event - AZ_DLL_IMPORT HANDLE _stdcall CreateEventA(LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset, BOOL bInitialState, LPCSTR lpName); AZ_DLL_IMPORT HANDLE _stdcall CreateEventW(LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset, BOOL bInitialState, LPCWSTR lpName); - #ifndef CreateEvent - #define CreateEvent CreateEventW - #endif AZ_DLL_IMPORT BOOL _stdcall SetEvent(HANDLE); } diff --git a/Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/std/parallel/internal/semaphore_WinAPI.h b/Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/std/parallel/internal/semaphore_WinAPI.h index cca90787e6..cd6b216057 100644 --- a/Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/std/parallel/internal/semaphore_WinAPI.h +++ b/Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/std/parallel/internal/semaphore_WinAPI.h @@ -15,14 +15,14 @@ namespace AZStd { inline semaphore::semaphore(unsigned int initialCount, unsigned int maximumCount) { - m_semaphore = CreateSemaphore(NULL, initialCount, maximumCount, 0); + m_semaphore = CreateSemaphoreW(NULL, initialCount, maximumCount, 0); AZ_Assert(m_semaphore != NULL, "CreateSemaphore error: %d\n", GetLastError()); } inline semaphore::semaphore(const char* name, unsigned int initialCount, unsigned int maximumCount) { (void)name; // name is used only for debug, if we pass it to the semaphore it will become named semaphore - m_semaphore = CreateSemaphore(NULL, initialCount, maximumCount, 0); + m_semaphore = CreateSemaphoreW(NULL, initialCount, maximumCount, 0); AZ_Assert(m_semaphore != NULL, "CreateSemaphore error: %d\n", GetLastError()); } From 928c8ff16c74121c5d80e9de7988fae806f6b483 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Tue, 3 Aug 2021 10:50:58 -0700 Subject: [PATCH 087/803] add unit tests Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Framework/AzCore/Tests/AZStd/String.cpp | 21 ++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/Code/Framework/AzCore/Tests/AZStd/String.cpp b/Code/Framework/AzCore/Tests/AZStd/String.cpp index 2d2602e456..c0d378bd39 100644 --- a/Code/Framework/AzCore/Tests/AZStd/String.cpp +++ b/Code/Framework/AzCore/Tests/AZStd/String.cpp @@ -686,6 +686,27 @@ namespace UnitTest wstr1 = wstring::format(L"%hs", str.c_str()); AZ_TEST_ASSERT(wstr1 == L"BLABLA 5"); + // wstring to char buffer + char strBuffer[9]; + to_string(strBuffer, 9, wstr1.c_str()); + AZ_TEST_ASSERT(0 == azstricmp(strBuffer, "BLABLA 5")); + + // wchar_t buffer to char buffer + wchar_t wstrBuffer[9] = L"BLABLA 5"; + memset(strBuffer, 0, AZ_ARRAY_SIZE(strBuffer)); + to_string(strBuffer, 9, wstrBuffer); + AZ_TEST_ASSERT(0 == azstricmp(strBuffer, "BLABLA 5")); + + // string to wchar_t buffer + memset(wstrBuffer, 0, AZ_ARRAY_SIZE(wstrBuffer)); + to_wstring(wstrBuffer, 9, str1.c_str()); + AZ_TEST_ASSERT(0 == azwcsicmp(wstrBuffer, L"BlaBla 5")); + + // char buffer to wchar_t buffer + memset(wstrBuffer, 0, AZ_ARRAY_SIZE(wstrBuffer)); + to_wstring(wstrBuffer, 9, strBuffer); + AZ_TEST_ASSERT(0 == azwcsicmp(wstrBuffer, L"BLABLA 5")); + // wchar UTF16/UTF32 to/from Utf8 wstr1 = L"this is a \u20AC \u00A3 test"; // that's a euro and a pound sterling AZStd::to_string(str, wstr1); From e0d0bbfdaed37487b74cb02cd0156bd43b203347 Mon Sep 17 00:00:00 2001 From: kberg-amzn Date: Tue, 3 Aug 2021 13:12:37 -0700 Subject: [PATCH 088/803] Changes to desync debug output to make it less stressful on bandwidth and the server, as well as some fixes to corrections on the local client Signed-off-by: kberg-amzn --- .../Serialization/StringifySerializer.cpp | 18 +- .../Serialization/StringifySerializer.h | 12 +- Gems/Multiplayer/Code/CMakeLists.txt | 2 +- .../LocalPredictionPlayerInputComponent.h | 13 +- .../Multiplayer/Components/NetBindComponent.h | 19 +- .../Multiplayer/NetworkTime/INetworkTime.h | 5 + .../NetworkTime/RewindableObject.inl | 2 +- ...tionPlayerInputComponent.AutoComponent.xml | 1 - .../LocalPredictionPlayerInputComponent.cpp | 176 ++++++++---------- .../Source/Components/NetBindComponent.cpp | 15 ++ .../Source/MultiplayerSystemComponent.cpp | 4 +- .../EntityReplicationManager.cpp | 14 +- .../EntityReplicationManager.h | 1 + .../Code/Source/NetworkTime/NetworkTime.cpp | 9 + .../Code/Source/NetworkTime/NetworkTime.h | 1 + 15 files changed, 154 insertions(+), 138 deletions(-) diff --git a/Code/Framework/AzNetworking/AzNetworking/Serialization/StringifySerializer.cpp b/Code/Framework/AzNetworking/AzNetworking/Serialization/StringifySerializer.cpp index b35b01d45c..df018cb6ce 100644 --- a/Code/Framework/AzNetworking/AzNetworking/Serialization/StringifySerializer.cpp +++ b/Code/Framework/AzNetworking/AzNetworking/Serialization/StringifySerializer.cpp @@ -23,9 +23,9 @@ namespace AzNetworking return m_string; } - const StringifySerializer::StringMap& StringifySerializer::GetValueMap() const + const StringifySerializer::ValueMap& StringifySerializer::GetValueMap() const { - return m_map; + return m_valueMap; } SerializerMode StringifySerializer::GetSerializerMode() const @@ -137,22 +137,22 @@ namespace AzNetworking template bool StringifySerializer::ProcessData(const char* name, const T& value) { - // Only add delimeters after we have processed at least one element + const AZStd::string keyString = m_prefix + name; + if (!m_string.empty()) { + // Only add delimeters after we have processed at least one element m_string += m_delimeter; } if (m_outputFieldNames) { - m_string += m_prefix; - m_string += name; - m_string += m_separator; + m_string += keyString; } - AZ::CVarFixedString string = AZ::ConsoleTypeHelpers::ValueToString(value); - m_string += string.c_str(); - m_map[m_prefix + name] = string.c_str(); + AZ::CVarFixedString valueString = AZ::ConsoleTypeHelpers::ValueToString(value); + m_valueMap[keyString] = valueString.c_str(); + return true; } } diff --git a/Code/Framework/AzNetworking/AzNetworking/Serialization/StringifySerializer.h b/Code/Framework/AzNetworking/AzNetworking/Serialization/StringifySerializer.h index d93f08822b..379b5198c7 100644 --- a/Code/Framework/AzNetworking/AzNetworking/Serialization/StringifySerializer.h +++ b/Code/Framework/AzNetworking/AzNetworking/Serialization/StringifySerializer.h @@ -20,17 +20,15 @@ namespace AzNetworking { public: - using StringMap = AZStd::map; + using ValueMap = AZStd::map; StringifySerializer(char delimeter = ' ', bool outputFieldNames = true, const AZStd::string& seperator = "="); - // GetString - // After serializing objects, get the serialized values as a single string + //! After serializing objects, get the serialized values as a single string. const AZStd::string& GetString() const; - // GetValueMap - // After serializing objects, get the serialized values as key value pairs - const StringMap& GetValueMap() const; + //! After serializing objects, get the serialized values as a map of key/value pairs. + const ValueMap& GetValueMap() const; // ISerializer interfaces SerializerMode GetSerializerMode() const override; @@ -67,7 +65,7 @@ namespace AzNetworking char m_delimeter; bool m_outputFieldNames = true; - StringMap m_map; + ValueMap m_valueMap; AZStd::string m_string; AZStd::string m_prefix; AZStd::string m_separator; diff --git a/Gems/Multiplayer/Code/CMakeLists.txt b/Gems/Multiplayer/Code/CMakeLists.txt index 96527fbfc4..e8b38c8799 100644 --- a/Gems/Multiplayer/Code/CMakeLists.txt +++ b/Gems/Multiplayer/Code/CMakeLists.txt @@ -79,7 +79,7 @@ ly_add_target( # The "Multiplayer" target is used by clients and servers, Debug is used only on clients. ly_create_alias(NAME Multiplayer.Clients NAMESPACE Gem TARGETS Gem::Multiplayer Gem::Multiplayer.Debug) -ly_create_alias(NAME Multiplayer.Servers NAMESPACE Gem TARGETS Gem::Multiplayer) +ly_create_alias(NAME Multiplayer.Servers NAMESPACE Gem TARGETS Gem::Multiplayer Gem::Multiplayer.Debug) if (PAL_TRAIT_BUILD_HOST_TOOLS) ly_add_target( diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/LocalPredictionPlayerInputComponent.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/LocalPredictionPlayerInputComponent.h index fbb7131f76..4e5d7f2d49 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/Components/LocalPredictionPlayerInputComponent.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/LocalPredictionPlayerInputComponent.h @@ -10,6 +10,7 @@ #include #include +#include namespace Multiplayer { @@ -41,8 +42,7 @@ namespace Multiplayer ( AzNetworking::IConnection* invokingConnection, const Multiplayer::NetworkInputArray& inputArray, - const AZ::HashValue32& stateHash, - const AzNetworking::PacketEncodingBuffer& clientState + const AZ::HashValue32& stateHash ) override; void HandleSendMigrateClientInput @@ -58,11 +58,6 @@ namespace Multiplayer const AzNetworking::PacketEncodingBuffer& correction ) override; - //! Return true if we're currently replaying inputs after a correction. - //! If this value returns true, effects, audio, and other cosmetic triggers should be suppressed - //! @return true if we're within correction scope and replaying inputs - bool IsReplayingInput() const; - //! Return true if we're currently migrating from one host to another. //! @return boolean true if we're currently migrating from one host to another bool IsMigrating() const; @@ -79,6 +74,9 @@ namespace Multiplayer void UpdateAutonomous(AZ::TimeMs deltaTimeMs); void UpdateBankedTime(AZ::TimeMs deltaTimeMs); + using StateHistoryItem = AZStd::unique_ptr; + AZStd::map m_predictiveStateHistory; + // Implicitly sorted player input history, back() is the input that corresponds to the latest client input Id NetworkInputHistory m_inputHistory; @@ -104,7 +102,6 @@ namespace Multiplayer ClientInputId m_lastMigratedInputId = ClientInputId{ 0 }; // Used to resend inputs that were queued during a migration event HostFrameId m_serverMigrateFrameId = InvalidHostFrameId; - bool m_replayingInput = false; // True if we're replaying inputs under a correction event (use this to suppress effects or audio) bool m_allowMigrateClientInput = false; // True if this component was migrated, we will allow the client to send us migrated inputs (one time only) }; } diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetBindComponent.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetBindComponent.h index e0574e23a3..c050495f1f 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetBindComponent.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetBindComponent.h @@ -87,9 +87,19 @@ namespace Multiplayer AzNetworking::ConnectionId GetOwningConnectionId() const; void SetAllowAutonomy(bool value); MultiplayerComponentInputVector AllocateComponentInputs(); + + //! Return true if we're currently processing inputs. + //! @return true if we're within ProcessInput scope and writing to predictive state bool IsProcessingInput() const; + + //! Return true if we're currently replaying inputs after a correction. + //! If this value returns true, effects, audio, and other cosmetic triggers should be suppressed + //! @return true if we're within correction scope and replaying inputs + bool IsReprocessingInput() const; + void CreateInput(NetworkInput& networkInput, float deltaTime); void ProcessInput(NetworkInput& networkInput, float deltaTime); + void ReprocessInput(NetworkInput& networkInput, float deltaTime); bool HandleRpcMessage(AzNetworking::IConnection* invokingConnection, NetEntityRole remoteRole, NetworkEntityRpcMessage& message); bool HandlePropertyChangeMessage(AzNetworking::ISerializer& serializer, bool notifyChanges = true); @@ -177,10 +187,11 @@ namespace Multiplayer AzNetworking::ConnectionId m_owningConnectionId = AzNetworking::InvalidConnectionId; - bool m_isProcessingInput = false; - bool m_isMigrationDataValid = false; - bool m_needsToBeStopped = false; - bool m_allowAutonomy = false; // Set to true for the hosts controlled entity + bool m_isProcessingInput = false; // Set to true when we are processing input + bool m_isReprocessingInput = false; // Set to true when we are reprocessing input (during a correction) + bool m_isMigrationDataValid = false; + bool m_needsToBeStopped = false; + bool m_allowAutonomy = false; // Set to true for the hosts controlled entity friend class NetworkEntityManager; friend class EntityReplicationManager; diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/NetworkTime/INetworkTime.h b/Gems/Multiplayer/Code/Include/Multiplayer/NetworkTime/INetworkTime.h index 35ea317f62..441ad9876a 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/NetworkTime/INetworkTime.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/NetworkTime/INetworkTime.h @@ -54,6 +54,11 @@ namespace Multiplayer //! @return the HostFrameId taking into account the provided rewinding connectionId virtual HostFrameId GetHostFrameIdForRewindingConnection(AzNetworking::ConnectionId rewindConnectionId) const = 0; + //! Forcibly sets the current network time to the provided frameId and game time in milliseconds. + //! @param frameId the new HostFrameId to use + //! @param timeMs the new HostTimeMs to use + virtual void ForceSetTime(HostFrameId frameId, AZ::TimeMs timeMs) = 0; + //! Alters the current HostFrameId and binds that alteration to the provided ConnectionId. //! @param frameId the new HostFrameId to use //! @param timeMs the new HostTimeMs to use diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/NetworkTime/RewindableObject.inl b/Gems/Multiplayer/Code/Include/Multiplayer/NetworkTime/RewindableObject.inl index b3a14e698b..496e87a7a2 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/NetworkTime/RewindableObject.inl +++ b/Gems/Multiplayer/Code/Include/Multiplayer/NetworkTime/RewindableObject.inl @@ -72,7 +72,7 @@ namespace Multiplayer const HostFrameId frameTime = GetCurrentTimeForProperty(); if (frameTime < m_headTime) { - AZ_Assert(false, "Trying to mutate a rewindable in the past"); + AZ_Assert(false, "Trying to mutate a rewindable value in the past"); } else if (m_headTime < frameTime) { diff --git a/Gems/Multiplayer/Code/Source/AutoGen/LocalPredictionPlayerInputComponent.AutoComponent.xml b/Gems/Multiplayer/Code/Source/AutoGen/LocalPredictionPlayerInputComponent.AutoComponent.xml index 0c799a7b3f..1a7496a77d 100644 --- a/Gems/Multiplayer/Code/Source/AutoGen/LocalPredictionPlayerInputComponent.AutoComponent.xml +++ b/Gems/Multiplayer/Code/Source/AutoGen/LocalPredictionPlayerInputComponent.AutoComponent.xml @@ -22,7 +22,6 @@ - diff --git a/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp b/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp index df0d84c427..58e8890672 100644 --- a/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp @@ -21,9 +21,11 @@ namespace Multiplayer AZ_CVAR(AZ::TimeMs, cl_MaxRewindHistoryMs, AZ::TimeMs{ 2000 }, nullptr, AZ::ConsoleFunctorFlags::Null, "Maximum number of milliseconds to keep for server correction rewind and replay"); #ifndef AZ_RELEASE_BUILD AZ_CVAR(float, cl_DebugHackTimeMultiplier, 1.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "Scalar value used to simulate clock hacking cheats for validating bank time system and anticheat"); - AZ_CVAR(bool, cl_EnableDesyncDebugging, false, nullptr, AZ::ConsoleFunctorFlags::Null, "If enabled, debug logs will contain verbose information on detected state desyncs"); + AZ_CVAR(bool, cl_EnableDesyncDebugging, true, nullptr, AZ::ConsoleFunctorFlags::Null, "If enabled, debug logs will contain verbose information on detected state desyncs"); + AZ_CVAR(uint32_t, cl_PredictiveStateHistorySize, 120, nullptr, AZ::ConsoleFunctorFlags::Null, "Controls how many inputs of predictive state should be retained for debugging desyncs"); #endif + AZ_CVAR(bool, sv_ForceCorrections, false, nullptr, AZ::ConsoleFunctorFlags::Null, "If enabled, the server will force a correction for every input received for debugging"); AZ_CVAR(bool, sv_EnableCorrections, true, nullptr, AZ::ConsoleFunctorFlags::Null, "Enables server corrections on autonomous proxy desyncs"); AZ_CVAR(double, sv_MaxBankTimeWindowSec, 0.2, nullptr, AZ::ConsoleFunctorFlags::Null, "Maximum bank time we allow before we start rejecting autonomous proxy move inputs due to anticheat kicking in"); AZ_CVAR(double, sv_BankTimeDecay, 0.025, nullptr, AZ::ConsoleFunctorFlags::Null, "Amount to decay bank time by, in case of more permanent shifts in client latency"); @@ -45,6 +47,40 @@ namespace Multiplayer return serializer.GetString(); } + void PrintCorrectionDifferences(const AzNetworking::StringifySerializer& client, const AzNetworking::StringifySerializer& server) + { + const auto& clientMap = client.GetValueMap(); + const auto& serverMap = server.GetValueMap(); + + AzNetworking::StringifySerializer::ValueMap differences = clientMap; + for (auto iter = server.GetValueMap().begin(); iter != server.GetValueMap().end(); ++iter) + { + auto serverValueIter = clientMap.find(iter->first); + if (iter->second == differences[iter->first]) + { + differences.erase(iter->first); + } + } + + if (differences.empty()) + { + AZLOG_ERROR("The hash mismatched, but no differences were found.") + } + + for (auto iter = differences.begin(); iter != differences.end(); ++iter) + { + auto clientValueIter = clientMap.find(iter->first); + auto serverValueIter = serverMap.find(iter->first); + if (clientValueIter == clientMap.end() || serverValueIter == serverMap.end()) + { + AZLOG_ERROR(" %s (Not found in server and/or client value map!)", iter->first.c_str()); + continue; + } + + AZLOG_ERROR(" %s Server=%s Client=%s", iter->first.c_str(), serverValueIter->second.c_str(), clientValueIter->second.c_str()); + } + } + void LocalPredictionPlayerInputComponent::LocalPredictionPlayerInputComponent::Reflect(AZ::ReflectContext* context) { AZ::SerializeContext* serializeContext = azrtti_cast(context); @@ -106,8 +142,7 @@ namespace Multiplayer ( AzNetworking::IConnection* invokingConnection, const Multiplayer::NetworkInputArray& inputArray, - const AZ::HashValue32& stateHash, - [[maybe_unused]] const AzNetworking::PacketEncodingBuffer& clientState + const AZ::HashValue32& stateHash ) { if (invokingConnection == nullptr) @@ -176,7 +211,7 @@ namespace Multiplayer } } - if (sv_EnableCorrections && (currentTimeMs - m_lastCorrectionSentTimeMs > sv_MinCorrectionTimeMs)) + if (sv_ForceCorrections || (sv_EnableCorrections && (currentTimeMs - m_lastCorrectionSentTimeMs > sv_MinCorrectionTimeMs))) { m_lastCorrectionSentTimeMs = currentTimeMs; @@ -210,69 +245,6 @@ namespace Multiplayer // Send correction SendClientInputCorrection(GetLastInputId(), correction); - -#ifndef AZ_RELEASE_BUILD - AZStd::string clientStateString; - AZStd::string serverStateString; - if (cl_EnableDesyncDebugging) - { - // In debug, show which states caused the correction - // Write in client state - AzNetworking::NetworkOutputSerializer clientStateSerializer(clientState.GetBuffer(), clientState.GetSize()); - GetNetBindComponent()->SerializeEntityCorrection(clientStateSerializer); - - // Read out state values - AzNetworking::StringifySerializer clientValues; - GetNetBindComponent()->SerializeEntityCorrection(clientValues); - - // Restore server state - AzNetworking::NetworkOutputSerializer serverStateSerializer(correction.GetBuffer(), correction.GetSize()); - GetNetBindComponent()->SerializeEntityCorrection(serverStateSerializer); - - // Read out state values - AzNetworking::StringifySerializer serverValues; - GetNetBindComponent()->SerializeEntityCorrection(serverValues); - - AZStd::map> mapComparison; - - // put the server value in the first part of the pair - for (const auto& pair : serverValues.GetValueMap()) - { - mapComparison[pair.first].first = pair.second; - } - - // put the client value in the second part of the pair - for (const auto& pair : clientValues.GetValueMap()) - { - mapComparison[pair.first].second = pair.second; - } - - bool firstIt = true; - for (const auto& mapPair : mapComparison) - { - if (mapPair.second.first != mapPair.second.second) - { - if (!firstIt) - { - clientStateString += ","; - serverStateString += ","; - } - firstIt = false; - - AZStd::string clientValue = mapPair.second.second.empty() ? "" : mapPair.second.second; - AZStd::string serverValue = mapPair.second.first.empty() ? "" : mapPair.second.first; - clientStateString += mapPair.first + "=" + clientValue; - serverStateString += mapPair.first + "=" + serverValue; - } - } - } - else - { - clientStateString = "available in debug only"; - serverStateString = "available in debug only"; - } - AZLOG_ERROR("** Autonomous proxy desync detected! ** clientState=[%s], serverState=[%s]", clientStateString.c_str(), serverStateString.c_str()); -#endif } } } @@ -331,7 +303,7 @@ namespace Multiplayer void LocalPredictionPlayerInputComponentController::HandleSendClientInputCorrection ( - AzNetworking::IConnection* invokingConnection, + [[maybe_unused]] AzNetworking::IConnection* invokingConnection, const Multiplayer::ClientInputId& inputId, const AzNetworking::PacketEncodingBuffer& correction ) @@ -356,6 +328,25 @@ namespace Multiplayer GetNetBindComponent()->SerializeEntityCorrection(serializer); m_correctionEvent.Signal(); +#ifndef AZ_RELEASE_BUILD + if (cl_EnableDesyncDebugging) + { + AZLOG_INFO("** Autonomous Desync - Corrected clientInputId=%d ", aznumeric_cast(inputId)); + auto iter = m_predictiveStateHistory.find(inputId); + if (iter != m_predictiveStateHistory.end()) + { + // Read out state values + AzNetworking::StringifySerializer serverValues; + GetNetBindComponent()->SerializeEntityCorrection(serverValues); + PrintCorrectionDifferences(*iter->second, serverValues); + } + else + { + AZLOG_INFO("Received correction that is too old to diff, increase cl_PredictiveStateHistorySize"); + } + } +#endif + AZLOG ( NET_Prediction, @@ -370,29 +361,13 @@ namespace Multiplayer // If this correction is for a move outside our input history window, just start replaying from the oldest move we have available const uint32_t startReplayIndex = (inputHistorySize > historicalDelta) ? (inputHistorySize - historicalDelta) : 0; - // Flag that we are replaying inputs - struct ScopedReplayingInput - { - ScopedReplayingInput(LocalPredictionPlayerInputComponentController* instance) - : m_instance(instance) - { - m_instance->m_replayingInput = true; - } - ~ScopedReplayingInput() - { - m_instance->m_replayingInput = false; - } - LocalPredictionPlayerInputComponentController* m_instance; - }; - ScopedReplayingInput markReplayingInput(this); - const float clientInputRateSec = static_cast(static_cast(cl_InputRateMs)) / 1000.0; for (uint32_t replayIndex = startReplayIndex; replayIndex < inputHistorySize; ++replayIndex) { // Reprocess the input for this frame NetworkInput& input = m_inputHistory[replayIndex]; ScopedAlterTime scopedTime(input.GetHostFrameId(), input.GetHostTimeMs(), invokingConnection->GetConnectionId()); - GetNetBindComponent()->ProcessInput(input, clientInputRateSec); + GetNetBindComponent()->ReprocessInput(input, clientInputRateSec); AZLOG ( @@ -405,11 +380,6 @@ namespace Multiplayer } } - bool LocalPredictionPlayerInputComponentController::IsReplayingInput() const - { - return m_replayingInput; - } - bool LocalPredictionPlayerInputComponentController::IsMigrating() const { return m_lastMigratedInputId != ClientInputId{ 0 }; @@ -519,17 +489,6 @@ namespace Multiplayer AzNetworking::HashSerializer hashSerializer; GetNetBindComponent()->SerializeEntityCorrection(hashSerializer); - // In debug, send the entire client output state to the server to make it easier to debug desync issues - AzNetworking::PacketEncodingBuffer processInputResult; -#ifndef AZ_RELEASE_BUILD - if (cl_EnableDesyncDebugging) - { - AzNetworking::NetworkInputSerializer processInputResultSerializer(processInputResult.GetBuffer(), processInputResult.GetCapacity()); - GetNetBindComponent()->SerializeEntityCorrection(processInputResultSerializer); - processInputResult.Resize(processInputResultSerializer.GetSize()); - } -#endif - // Save this input and discard move history outside our client rewind window m_inputHistory.PushBack(input); while (m_inputHistory.Size() > maxClientInputs) @@ -548,10 +507,23 @@ namespace Multiplayer inputArray[i] = m_inputHistory[historyIndex]; } +#ifndef AZ_RELEASE_BUILD + if (cl_EnableDesyncDebugging) + { + StateHistoryItem inputHistory = AZStd::make_unique(); + while (m_predictiveStateHistory.size() > cl_PredictiveStateHistorySize) + { + m_predictiveStateHistory.erase(m_predictiveStateHistory.begin()); + } + GetNetBindComponent()->SerializeEntityCorrection(*inputHistory); + m_predictiveStateHistory.emplace(m_clientInputId, AZStd::move(inputHistory)); + } +#endif + // Send the input to server (only when we are not migrating) if (!IsMigrating()) { - SendClientInput(inputArray, hashSerializer.GetHash(), processInputResult); + SendClientInput(inputArray, hashSerializer.GetHash()); } } } diff --git a/Gems/Multiplayer/Code/Source/Components/NetBindComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetBindComponent.cpp index e8da34fc7f..cbbbadeffa 100644 --- a/Gems/Multiplayer/Code/Source/Components/NetBindComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/NetBindComponent.cpp @@ -267,6 +267,11 @@ namespace Multiplayer return m_isProcessingInput; } + bool NetBindComponent::IsReprocessingInput() const + { + return m_isReprocessingInput; + } + void NetBindComponent::CreateInput(NetworkInput& networkInput, float deltaTime) { // Only autonomous or authority runs this logic @@ -279,12 +284,21 @@ namespace Multiplayer void NetBindComponent::ProcessInput(NetworkInput& networkInput, float deltaTime) { + m_isProcessingInput = true; // Only autonomous and authority runs this logic AZ_Assert((NetworkRoleHasController(m_netEntityRole)), "Incorrect network role for input processing"); for (MultiplayerComponent* multiplayerComponent : m_multiplayerInputComponentVector) { multiplayerComponent->GetController()->ProcessInput(networkInput, deltaTime); } + m_isProcessingInput = false; + } + + void NetBindComponent::ReprocessInput(NetworkInput& networkInput, float deltaTime) + { + m_isReprocessingInput = true; + ProcessInput(networkInput, deltaTime); + m_isReprocessingInput = false; } bool NetBindComponent::HandleRpcMessage(AzNetworking::IConnection* invokingConnection, NetEntityRole remoteRole, NetworkEntityRpcMessage& message) @@ -649,6 +663,7 @@ namespace Multiplayer MultiplayerComponent* multiplayerComponent = azrtti_cast(component); if (multiplayerComponent != nullptr) { + multiplayerComponent->SetOwningConnectionId(m_owningConnectionId); m_multiplayerInputComponentVector.push_back(multiplayerComponent); } } diff --git a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp index 21c7ce80d6..16df4a629a 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp +++ b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp @@ -554,7 +554,7 @@ namespace Multiplayer m_tickFactor = 0.0f; m_lastReplicatedHostTimeMs = packet.GetHostTimeMs(); m_lastReplicatedHostFrameId = packet.GetHostFrameId(); - m_networkTime.AlterTime(m_lastReplicatedHostFrameId, m_lastReplicatedHostTimeMs, AzNetworking::InvalidConnectionId); + m_networkTime.ForceSetTime(m_lastReplicatedHostFrameId, m_lastReplicatedHostTimeMs); } for (AZStd::size_t i = 0; i < packet.GetEntityMessages().size(); ++i) @@ -856,7 +856,7 @@ namespace Multiplayer { m_tickFactor += deltaTime / serverRateSeconds; // Linear close to the origin, but asymptote at y = 1 - const float renderBlendFactor = AZStd::clamp(1.0f - (std::pow(cl_renderTickBlendBase, m_tickFactor)), 0.0f, 1.0f); + const float renderBlendFactor = AZStd::clamp(1.0f - (std::pow(cl_renderTickBlendBase, m_tickFactor)), 0.0f, m_tickFactor); AZLOG ( NET_Blending, diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.cpp index b9e9a9a87e..78e90cc7fb 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.cpp @@ -524,6 +524,7 @@ namespace Multiplayer bool EntityReplicationManager::HandlePropertyChangeMessage ( + AzNetworking::IConnection* invokingConnection, EntityReplicator* entityReplicator, AzNetworking::PacketId packetId, NetEntityId netEntityId, @@ -558,6 +559,12 @@ namespace Multiplayer NetBindComponent* netBindComponent = replicatorEntity.GetNetBindComponent(); AZ_Assert(netBindComponent != nullptr, "No NetBindComponent"); + if (createEntity) + { + // Always set our invoking connectionId for any newly created entities, since this connection now 'owns' them from a rewind perspective + netBindComponent->SetOwningConnectionId(invokingConnection->GetConnectionId()); + } + const bool changeNetworkRole = (netBindComponent->GetNetEntityRole() != localNetworkRole); if (changeNetworkRole) { @@ -744,7 +751,7 @@ namespace Multiplayer bool EntityReplicationManager::HandleEntityUpdateMessage ( - [[maybe_unused]] AzNetworking::IConnection* invokingConnection, + AzNetworking::IConnection* invokingConnection, const AzNetworking::IPacketHeader& packetHeader, const NetworkEntityUpdateMessage& updateMessage ) @@ -794,7 +801,7 @@ namespace Multiplayer } // This may implicitly create a replicator for us - bool handled = HandlePropertyChangeMessage(entityReplicator, packetHeader.GetPacketId(), updateMessage.GetEntityId(), updateMessage.GetNetworkRole(), outputSerializer, prefabEntityId); + bool handled = HandlePropertyChangeMessage(invokingConnection, entityReplicator, packetHeader.GetPacketId(), updateMessage.GetEntityId(), updateMessage.GetNetworkRole(), outputSerializer, prefabEntityId); AZ_Assert(handled, "Failed to handle NetworkEntityUpdateMessage message"); return handled; @@ -1121,7 +1128,7 @@ namespace Multiplayer } } - bool EntityReplicationManager::HandleEntityMigration([[maybe_unused]] AzNetworking::IConnection* invokingConnection, EntityMigrationMessage& message) + bool EntityReplicationManager::HandleEntityMigration(AzNetworking::IConnection* invokingConnection, EntityMigrationMessage& message) { EntityReplicator* replicator = GetEntityReplicator(message.m_entityId); { @@ -1130,6 +1137,7 @@ namespace Multiplayer AzNetworking::TrackChangedSerializer outputSerializer(message.m_propertyUpdateData.GetBuffer(), message.m_propertyUpdateData.GetSize()); if (!HandlePropertyChangeMessage ( + invokingConnection, replicator, AzNetworking::InvalidPacketId, message.m_entityId, diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.h b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.h index 9f5e743bbc..731a1a7556 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.h +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.h @@ -136,6 +136,7 @@ namespace Multiplayer bool HandlePropertyChangeMessage ( + AzNetworking::IConnection* invokingConnection, EntityReplicator* entityReplicator, AzNetworking::PacketId packetId, NetEntityId netEntityId, diff --git a/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.cpp b/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.cpp index 645ce1fc00..5ae698e622 100644 --- a/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.cpp @@ -65,6 +65,15 @@ namespace Multiplayer return (IsTimeRewound() && (rewindConnectionId == m_rewindingConnectionId)) ? m_unalteredFrameId : m_hostFrameId; } + void NetworkTime::ForceSetTime(HostFrameId frameId, AZ::TimeMs timeMs) + { + AZ_Assert(!IsTimeRewound(), "Forcibly setting network time is unsupported under a rewound time scope"); + m_unalteredFrameId = frameId; + m_hostFrameId = frameId; + m_hostTimeMs = timeMs; + m_rewindingConnectionId = AzNetworking::InvalidConnectionId; + } + void NetworkTime::AlterTime(HostFrameId frameId, AZ::TimeMs timeMs, AzNetworking::ConnectionId rewindConnectionId) { m_hostFrameId = frameId; diff --git a/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.h b/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.h index 4d568f40d9..4b94d3b6f2 100644 --- a/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.h +++ b/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.h @@ -32,6 +32,7 @@ namespace Multiplayer AZ::TimeMs GetHostTimeMs() const override; AzNetworking::ConnectionId GetRewindingConnectionId() const override; HostFrameId GetHostFrameIdForRewindingConnection(AzNetworking::ConnectionId rewindConnectionId) const override; + void ForceSetTime(HostFrameId frameId, AZ::TimeMs timeMs) override; void AlterTime(HostFrameId frameId, AZ::TimeMs timeMs, AzNetworking::ConnectionId rewindConnectionId) override; void SyncEntitiesToRewindState(const AZ::Aabb& rewindVolume) override; void ClearRewoundEntities() override; From 699e8edb360da3916a8fa925735bb342627a564b Mon Sep 17 00:00:00 2001 From: kberg-amzn Date: Wed, 28 Jul 2021 12:31:19 -0700 Subject: [PATCH 089/803] Corrects math computing blend factors to interpolate state between received network updates Signed-off-by: kberg-amzn --- .../Source/MultiplayerSystemComponent.cpp | 37 +++++++++++++------ .../Code/Source/MultiplayerSystemComponent.h | 2 +- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp index 9a46bb10de..21c7ce80d6 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp +++ b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp @@ -69,19 +69,24 @@ namespace Multiplayer { using namespace AzNetworking; - AZ_CVAR(uint16_t, cl_clientport, 0, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "The port to bind to for game traffic when connecting to a remote host, a value of 0 will select any available port"); - AZ_CVAR(AZ::CVarFixedString, cl_serveraddr, AZ::CVarFixedString(LocalHost), nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "The address of the remote server or host to connect to"); - AZ_CVAR(AZ::CVarFixedString, cl_serverpassword, "", nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "Optional server password"); + AZ_CVAR(uint16_t, cl_clientport, 0, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, + "The port to bind to for game traffic when connecting to a remote host, a value of 0 will select any available port"); + AZ_CVAR(AZ::CVarFixedString, cl_serveraddr, AZ::CVarFixedString(LocalHost), nullptr, AZ::ConsoleFunctorFlags::DontReplicate, + "The address of the remote server or host to connect to"); AZ_CVAR(uint16_t, cl_serverport, DefaultServerPort, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "The port of the remote host to connect to for game traffic"); AZ_CVAR(uint16_t, sv_port, DefaultServerPort, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "The port that this multiplayer gem will bind to for game traffic"); AZ_CVAR(AZ::CVarFixedString, sv_map, "nolevel", nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "The map the server should load"); - AZ_CVAR(AZ::CVarFixedString, sv_gamerules, "norules", nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "GameRules server works with"); AZ_CVAR(ProtocolType, sv_protocol, ProtocolType::Udp, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "This flag controls whether we use TCP or UDP for game networking"); AZ_CVAR(bool, sv_isDedicated, true, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "Whether the host command creates an independent or client hosted server"); AZ_CVAR(bool, sv_isTransient, true, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "Whether a dedicated server shuts down if all existing connections disconnect."); - AZ_CVAR(AZ::TimeMs, cl_defaultNetworkEntityActivationTimeSliceMs, AZ::TimeMs{ 0 }, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "Max Ms to use to activate entities coming from the network, 0 means instantiate everything"); + AZ_CVAR(AZ::TimeMs, cl_defaultNetworkEntityActivationTimeSliceMs, AZ::TimeMs{ 0 }, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, + "Max Ms to use to activate entities coming from the network, 0 means instantiate everything"); AZ_CVAR(AZ::TimeMs, sv_serverSendRateMs, AZ::TimeMs{ 50 }, nullptr, AZ::ConsoleFunctorFlags::Null, "Minimum number of milliseconds between each network update"); - AZ_CVAR(AZ::CVarFixedString, sv_defaultPlayerSpawnAsset, "prefabs/player.network.spawnable", nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "The default spawnable to use when a new player connects"); + AZ_CVAR(AZ::CVarFixedString, sv_defaultPlayerSpawnAsset, "prefabs/player.network.spawnable", nullptr, AZ::ConsoleFunctorFlags::DontReplicate, + "The default spawnable to use when a new player connects"); + AZ_CVAR(float, cl_renderTickBlendBase, 0.15f, nullptr, AZ::ConsoleFunctorFlags::Null, + "The base used for blending between network updates, 0.1 will be quite linear, 0.2 or 0.3 will " + "slow down quicker and may be better suited to connections with highly variable latency"); void MultiplayerSystemComponent::Reflect(AZ::ReflectContext* context) { @@ -546,7 +551,7 @@ namespace Multiplayer if ((GetAgentType() == MultiplayerAgentType::Client) && (packet.GetHostFrameId() > m_lastReplicatedHostFrameId)) { // Update client to latest server time - m_renderBlendFactor = 0.0f; + m_tickFactor = 0.0f; m_lastReplicatedHostTimeMs = packet.GetHostTimeMs(); m_lastReplicatedHostFrameId = packet.GetHostFrameId(); m_networkTime.AlterTime(m_lastReplicatedHostFrameId, m_lastReplicatedHostTimeMs, AzNetworking::InvalidConnectionId); @@ -849,10 +854,18 @@ namespace Multiplayer void MultiplayerSystemComponent::TickVisibleNetworkEntities(float deltaTime, float serverRateSeconds) { + m_tickFactor += deltaTime / serverRateSeconds; // Linear close to the origin, but asymptote at y = 1 - const float targetAdjustBlend = AZStd::clamp(deltaTime / serverRateSeconds, 0.0f, 1.0f); - m_renderBlendFactor = 1.0f - (std::pow(0.2f, m_renderBlendFactor + targetAdjustBlend)); - AZLOG(NET_Blending, "Computed blend factor of %0.2f using a frametime of %0.2f and a serverTickRate of %0.2f", m_renderBlendFactor, deltaTime, serverRateSeconds); + const float renderBlendFactor = AZStd::clamp(1.0f - (std::pow(cl_renderTickBlendBase, m_tickFactor)), 0.0f, 1.0f); + AZLOG + ( + NET_Blending, + "Computed blend factor of %0.3f using a tick factor of %0.3f, a frametime of %0.3f and a serverTickRate of %0.3f", + renderBlendFactor, + m_tickFactor, + deltaTime, + serverRateSeconds + ); if (Camera::ActiveCameraRequestBus::HasHandlers()) { @@ -895,7 +908,7 @@ namespace Multiplayer for (NetBindComponent* netBindComponent : gatheredEntities) { - netBindComponent->NotifyPreRender(deltaTime, m_renderBlendFactor); + netBindComponent->NotifyPreRender(deltaTime, renderBlendFactor); } } else @@ -907,7 +920,7 @@ namespace Multiplayer NetBindComponent* netBindComponent = entity->FindComponent(); if (netBindComponent != nullptr) { - netBindComponent->NotifyPreRender(deltaTime, m_renderBlendFactor); + netBindComponent->NotifyPreRender(deltaTime, renderBlendFactor); } } } diff --git a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h index 37e8138a71..ab37958962 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h +++ b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h @@ -155,7 +155,7 @@ namespace Multiplayer HostFrameId m_lastReplicatedHostFrameId = HostFrameId(0); double m_serverSendAccumulator = 0.0; - float m_renderBlendFactor = 0.0f; + float m_tickFactor = 0.0f; #if !defined(AZ_RELEASE_BUILD) MultiplayerEditorConnection m_editorConnectionListener; From 4eacd076da89f7552eae93b47b8534d5538f4026 Mon Sep 17 00:00:00 2001 From: Dayo Lawal Date: Tue, 3 Aug 2021 15:53:20 -0500 Subject: [PATCH 090/803] Fixing ME and ATWindowNotificationBus Signed-off-by: Dayo Lawal --- .../Window/AtomToolsMainWindow.h | 7 +++-- .../AtomToolsMainWindowNotificationBus.h} | 11 ++++---- .../Window/AtomToolsMainWindowRequestBus.h | 3 +++ .../Code/atomtoolsframework_files.cmake | 3 ++- .../Source/Window/MaterialEditorWindow.cpp | 9 ++++--- .../Code/Source/Window/MaterialEditorWindow.h | 7 +++-- .../Window/MaterialEditorWindowComponent.cpp | 26 +++++++++++-------- .../Code/materialeditorwindow_files.cmake | 2 -- ...erManagementConsoleWindowNotificationBus.h | 26 ------------------- .../Window/ShaderManagementConsoleWindow.cpp | 18 +++++++------ .../Window/ShaderManagementConsoleWindow.h | 8 +++--- .../shadermanagementconsolewindow_files.cmake | 1 - 12 files changed, 50 insertions(+), 71 deletions(-) rename Gems/Atom/Tools/{MaterialEditor/Code/Include/Atom/Window/MaterialEditorWindowNotificationBus.h => AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindowNotificationBus.h} (62%) delete mode 100644 Gems/Atom/Tools/ShaderManagementConsole/Code/Include/Atom/Window/ShaderManagementConsoleWindowNotificationBus.h diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindow.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindow.h index 6b02bd1c06..8d500c1320 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindow.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindow.h @@ -7,8 +7,8 @@ */ #pragma once -#include #include +#include #include #include @@ -44,7 +44,7 @@ namespace AtomToolsFramework virtual void RemoveTabForDocumentId(const AZ::Uuid& documentId); virtual void UpdateTabForDocumentId(const AZ::Uuid& documentId); virtual AZ::Uuid GetDocumentIdFromTab(const int tabIndex) const; - + virtual void OpenTabContextMenu(); virtual void SelectPreviousTab(); virtual void SelectNextTab(); @@ -58,6 +58,5 @@ namespace AtomToolsFramework AZStd::unordered_map m_dockWidgets; QMenu* m_menuFile = {}; - //StatusBarWidget* m_statusBar = {}; }; -} +} // namespace AtomToolsFramework diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Window/MaterialEditorWindowNotificationBus.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindowNotificationBus.h similarity index 62% rename from Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Window/MaterialEditorWindowNotificationBus.h rename to Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindowNotificationBus.h index 38f77e8bf5..cf5c02085d 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Window/MaterialEditorWindowNotificationBus.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindowNotificationBus.h @@ -10,17 +10,16 @@ #include -namespace MaterialEditor +namespace AtomToolsFramework { - class MaterialEditorWindowNotifications - : public AZ::EBusTraits + class AtomToolsMainWindowNotifications : public AZ::EBusTraits { public: static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple; static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; - virtual void OnMaterialEditorWindowClosing() {}; + virtual void OnAtomToolsMainWindowWindowClosing(){}; }; - using MaterialEditorWindowNotificationBus = AZ::EBus; + using AtomToolsMainWindowNotificationBus = AZ::EBus; -} // namespace MaterialEditor +} // namespace AtomToolsFramework diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindowRequestBus.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindowRequestBus.h index ee21554844..6edb44bc5c 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindowRequestBus.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindowRequestBus.h @@ -7,7 +7,10 @@ */ #pragma once + +//! Disables "unreferenced formal parameter" warning #pragma warning(disable : 4100) + #include #include #include diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake b/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake index 0769aac86c..49e641eb9c 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake @@ -27,6 +27,7 @@ set(FILES Include/AtomToolsFramework/Window/AtomToolsMainWindow.h Include/AtomToolsFramework/Window/AtomToolsMainWindowRequestBus.h Include/AtomToolsFramework/Window/AtomToolsMainWindowFactoryRequestBus.h + Include/AtomToolsFramework/Window/AtomToolsMainWindowNotificationBus.h Source/Application/AtomToolsApplication.cpp Source/Communication/LocalServer.cpp Source/Communication/LocalSocket.cpp @@ -44,4 +45,4 @@ set(FILES Source/Viewport/RenderViewportWidget.cpp Source/Viewport/ModularViewportCameraController.cpp Source/Window/AtomToolsMainWindow.cpp -) +) \ No newline at end of file diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp index 733a01539e..43d91e9721 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp @@ -15,10 +15,10 @@ #include #include -#include #include #include +#include #include #include @@ -185,7 +185,8 @@ namespace MaterialEditor QByteArray windowState = m_advancedDockManager->saveState(); windowSettings->m_mainWindowState.assign(windowState.begin(), windowState.end()); - MaterialEditorWindowNotificationBus::Broadcast(&MaterialEditorWindowNotifications::OnMaterialEditorWindowClosing); + AtomToolsFramework::AtomToolsMainWindowNotificationBus::Broadcast( + &AtomToolsFramework::AtomToolsMainWindowNotifications::OnAtomToolsMainWindowWindowClosing); } void MaterialEditorWindow::OnDocumentOpened(const AZ::Uuid& documentId) @@ -284,7 +285,7 @@ namespace MaterialEditor void MaterialEditorWindow::SetupMenu() { - AtomToolsFramework::AtomToolsMainWindow::SetupMenu(); + Base::SetupMenu(); m_actionNew = m_menuFile->addAction("&New...", [this]() { CreateMaterialDialog createDialog(this); @@ -482,7 +483,7 @@ namespace MaterialEditor void MaterialEditorWindow::SetupTabs() { - AtomToolsFramework::AtomToolsMainWindow::SetupTabs(); + Base::SetupTabs(); // This signal will be triggered whenever a tab is added, removed, selected, clicked, dragged // When the last tab is removed tabIndex will be -1 and the document ID will be null diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.h index 65c13a094d..d865f1170d 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.h @@ -9,9 +9,9 @@ #pragma once #if !defined(Q_MOC_RUN) -#include #include #include +#include AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT #include @@ -19,14 +19,13 @@ AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnin #include #include -#include #include -#include #include +#include #include -#include #include +#include AZ_POP_DISABLE_WARNING #endif diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowComponent.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowComponent.cpp index 05641e8e55..88c7c0576f 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowComponent.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowComponent.cpp @@ -18,6 +18,8 @@ #include #include #include +#include + namespace MaterialEditor { @@ -33,25 +35,27 @@ namespace MaterialEditor if (AZ::BehaviorContext* behaviorContext = azrtti_cast(context)) { - behaviorContext->EBus("MaterialEditorWindowFactoryRequestBus") + using FactoryRequestBus = MaterialEditorWindowFactoryRequestBus; + behaviorContext->EBus("MaterialEditorWindowFactoryRequestBus") ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) ->Attribute(AZ::Script::Attributes::Category, "Editor") ->Attribute(AZ::Script::Attributes::Module, "materialeditor") - ->Event("CreateMaterialEditorWindow", &MaterialEditorWindowFactoryRequestBus::Events::CreateMaterialEditorWindow) - ->Event("DestroyMaterialEditorWindow", &MaterialEditorWindowFactoryRequestBus::Events::DestroyMaterialEditorWindow) + ->Event("CreateMaterialEditorWindow", &FactoryRequestBus::Events::CreateMaterialEditorWindow) + ->Event("DestroyMaterialEditorWindow", &FactoryRequestBus::Events::DestroyMaterialEditorWindow) ; - behaviorContext->EBus("MaterialEditorWindowRequestBus") + using RequestBus = AtomToolsFramework::AtomToolsMainWindowRequestBus; + behaviorContext->EBus("MaterialEditorWindowRequestBus") ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) ->Attribute(AZ::Script::Attributes::Category, "Editor") ->Attribute(AZ::Script::Attributes::Module, "materialeditor") - ->Event("ActivateWindow", &MaterialEditorWindowRequestBus::Events::ActivateWindow) - ->Event("SetDockWidgetVisible", &MaterialEditorWindowRequestBus::Events::SetDockWidgetVisible) - ->Event("IsDockWidgetVisible", &MaterialEditorWindowRequestBus::Events::IsDockWidgetVisible) - ->Event("GetDockWidgetNames", &MaterialEditorWindowRequestBus::Events::GetDockWidgetNames) - ->Event("ResizeViewportRenderTarget", &MaterialEditorWindowRequestBus::Events::ResizeViewportRenderTarget) - ->Event("LockViewportRenderTargetSize", &MaterialEditorWindowRequestBus::Events::LockViewportRenderTargetSize) - ->Event("UnlockViewportRenderTargetSize", &MaterialEditorWindowRequestBus::Events::UnlockViewportRenderTargetSize) + ->Event("ActivateWindow", &RequestBus::Events::ActivateWindow) + ->Event("SetDockWidgetVisible", &RequestBus::Events::SetDockWidgetVisible) + ->Event("IsDockWidgetVisible", &RequestBus::Events::IsDockWidgetVisible) + ->Event("GetDockWidgetNames", &RequestBus::Events::GetDockWidgetNames) + ->Event("ResizeViewportRenderTarget", &RequestBus::Events::ResizeViewportRenderTarget) + ->Event("LockViewportRenderTargetSize", &RequestBus::Events::LockViewportRenderTargetSize) + ->Event("UnlockViewportRenderTargetSize", &RequestBus::Events::UnlockViewportRenderTargetSize) ; } } diff --git a/Gems/Atom/Tools/MaterialEditor/Code/materialeditorwindow_files.cmake b/Gems/Atom/Tools/MaterialEditor/Code/materialeditorwindow_files.cmake index caef9916f6..34d4bc9a28 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/materialeditorwindow_files.cmake +++ b/Gems/Atom/Tools/MaterialEditor/Code/materialeditorwindow_files.cmake @@ -9,8 +9,6 @@ set(FILES Include/Atom/Window/MaterialEditorWindowModule.h Include/Atom/Window/MaterialEditorWindowSettings.h - Include/Atom/Window/MaterialEditorWindowNotificationBus.h - Include/Atom/Window/MaterialEditorWindowRequestBus.h Include/Atom/Window/MaterialEditorWindowFactoryRequestBus.h Source/Window/MaterialEditorBrowserInteractions.h Source/Window/MaterialEditorBrowserInteractions.cpp diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Include/Atom/Window/ShaderManagementConsoleWindowNotificationBus.h b/Gems/Atom/Tools/ShaderManagementConsole/Code/Include/Atom/Window/ShaderManagementConsoleWindowNotificationBus.h deleted file mode 100644 index e74e81cf4b..0000000000 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Include/Atom/Window/ShaderManagementConsoleWindowNotificationBus.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -#pragma once - -#include - -namespace ShaderManagementConsole -{ - class ShaderManagementConsoleWindowNotifications - : public AZ::EBusTraits - { - public: - static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple; - static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; - - virtual void OnShaderManagementConsoleWindowClosing() {}; - }; - using ShaderManagementConsoleWindowNotificationBus = AZ::EBus; - -} // namespace ShaderManagementConsole diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp index e02ab83597..825b17fb5e 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp @@ -5,6 +5,12 @@ * SPDX-License-Identifier: Apache-2.0 OR MIT * */ + +#include +#include + +#include +#include #include @@ -15,11 +21,6 @@ #include #include #include -#include - -#include -#include -#include #include @@ -80,7 +81,8 @@ namespace ShaderManagementConsole return; } - ShaderManagementConsoleWindowNotificationBus::Broadcast(&ShaderManagementConsoleWindowNotifications::OnShaderManagementConsoleWindowClosing); + AtomToolsFramework::AtomToolsMainWindowNotificationBus::Broadcast( + &AtomToolsFramework::AtomToolsMainWindowNotifications::OnAtomToolsMainWindowWindowClosing); } void ShaderManagementConsoleWindow::OnDocumentOpened(const AZ::Uuid& documentId) @@ -159,7 +161,7 @@ namespace ShaderManagementConsole void ShaderManagementConsoleWindow::SetupMenu() { - AtomToolsFramework::AtomToolsMainWindow::SetupMenu(); + Base::SetupMenu(); m_actionOpen = m_menuFile->addAction("&Open...", [this]() { const AZStd::vector assetTypes = { @@ -277,7 +279,7 @@ namespace ShaderManagementConsole void ShaderManagementConsoleWindow::SetupTabs() { - AtomToolsFramework::AtomToolsMainWindow::SetupTabs(); + Base::SetupTabs(); // This signal will be triggered whenever a tab is added, removed, selected, clicked, dragged // When the last tab is removed tabIndex will be -1 and the document ID will be null diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.h b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.h index 8513366ec2..127a777ddd 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.h +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.h @@ -9,11 +9,11 @@ #pragma once #if !defined(Q_MOC_RUN) -#include #include +#include -#include #include +#include #include AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT @@ -26,8 +26,8 @@ AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnin #include #include -#include #include +#include AZ_POP_DISABLE_WARNING #endif @@ -63,7 +63,7 @@ namespace ShaderManagementConsole void OnDocumentUndoStateChanged(const AZ::Uuid& documentId) override; void OnDocumentSaved(const AZ::Uuid& documentId) override; - void SetupMenu() override; + void SetupMenu() override; void SetupTabs() override; void AddTabForDocumentId(const AZ::Uuid& documentId) override; diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/shadermanagementconsolewindow_files.cmake b/Gems/Atom/Tools/ShaderManagementConsole/Code/shadermanagementconsolewindow_files.cmake index dad4f759d7..056b74e411 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/shadermanagementconsolewindow_files.cmake +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/shadermanagementconsolewindow_files.cmake @@ -8,7 +8,6 @@ set(FILES Include/Atom/Window/ShaderManagementConsoleWindowModule.h - Include/Atom/Window/ShaderManagementConsoleWindowNotificationBus.h Include/Atom/Window/ShaderManagementConsoleWindowRequestBus.h Include/Atom/Core/ShaderManagementConsoleRequestBus.h Source/Window/ShaderManagementConsoleBrowserInteractions.h From a92ed42829dc74d092fe8a189ed7c008ed70d879 Mon Sep 17 00:00:00 2001 From: evanchia Date: Tue, 3 Aug 2021 16:51:19 -0700 Subject: [PATCH 091/803] minor fixes for c++ retry command Signed-off-by: evanchia --- Code/Tools/AzTestRunner/src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Tools/AzTestRunner/src/main.cpp b/Code/Tools/AzTestRunner/src/main.cpp index 96832c3fed..225975b654 100644 --- a/Code/Tools/AzTestRunner/src/main.cpp +++ b/Code/Tools/AzTestRunner/src/main.cpp @@ -229,7 +229,7 @@ namespace AzTestRunner // Construct a retry command if the test fails if (result != 0) { - std::cout << "Retry command: " << std::string(argv[0]) << " " << lib << " " << symbol << std::endl; + std::cout << "Retry command:\n " << argv[0] << " " << lib << " " << symbol << std::endl; } // unload and reset the module here, because it needs to release resources that were used / activated in From 259bc3f85e59e0f306d2aa7c3db584eab27384ef Mon Sep 17 00:00:00 2001 From: Dayo Lawal Date: Tue, 3 Aug 2021 19:24:46 -0500 Subject: [PATCH 092/803] ATWindowNotificationBus and ATFactoryRequestBus Signed-off-by: Dayo Lawal --- .../Application/AtomToolsApplication.h | 12 +++++ .../Window/AtomToolsMainWindow.h | 1 + .../AtomToolsMainWindowFactoryRequestBus.h | 8 ++-- .../AtomToolsMainWindowNotificationBus.h | 2 +- .../Application/AtomToolsApplication.cpp | 23 +++++++++- .../MaterialEditorWindowFactoryRequestBus.h | 31 ------------- .../Code/Source/MaterialEditorApplication.cpp | 46 ++----------------- .../Code/Source/MaterialEditorApplication.h | 14 ------ .../Source/Window/MaterialEditorWindow.cpp | 2 +- .../Code/materialeditorwindow_files.cmake | 1 - .../ShaderManagementConsoleWindowRequestBus.h | 33 ------------- .../ShaderManagementConsoleApplication.cpp | 33 +++---------- .../ShaderManagementConsoleApplication.h | 15 +----- .../Window/ShaderManagementConsoleWindow.cpp | 2 +- ...ShaderManagementConsoleWindowComponent.cpp | 10 ++-- .../ShaderManagementConsoleWindowComponent.h | 4 +- .../shadermanagementconsolewindow_files.cmake | 1 - 17 files changed, 61 insertions(+), 177 deletions(-) delete mode 100644 Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Window/MaterialEditorWindowFactoryRequestBus.h delete mode 100644 Gems/Atom/Tools/ShaderManagementConsole/Code/Include/Atom/Window/ShaderManagementConsoleWindowRequestBus.h diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h index bceea24aad..ee7c37f7f1 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h @@ -9,12 +9,17 @@ #include #include +#include + #include #include #include + #include #include + #include + #include #include #include @@ -31,6 +36,7 @@ namespace AtomToolsFramework , protected AzFramework::AssetSystemStatusBus::Handler , protected AzToolsFramework::EditorPythonConsoleNotificationBus::Handler , protected AZ::UserSettingsOwnerRequestBus::Handler + , protected AtomToolsMainWindowNotificationBus::Handler { public: AZ_TYPE_INFO(AtomTools::AtomToolsApplication, "{A0DF25BA-6F74-4F11-9F85-0F99278D5986}"); @@ -38,6 +44,7 @@ namespace AtomToolsFramework using Base = AzFramework::Application; AtomToolsApplication(int* argc, char*** argv); + ~AtomToolsApplication(); ////////////////////////////////////////////////////////////////////////// // AzFramework::Application @@ -52,6 +59,11 @@ namespace AtomToolsFramework void Stop() override; protected: + ////////////////////////////////////////////////////////////////////////// + // AtomsToolMainWindowNotificationBus::Handler overrides... + void OnMainWindowClosing() override; + ////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////// // AssetDatabaseRequestsBus::Handler overrides... bool GetAssetDatabaseLocation(AZStd::string& result) override; diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindow.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindow.h index 8d500c1320..f3271123b0 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindow.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindow.h @@ -8,6 +8,7 @@ #pragma once #include + #include #include diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindowFactoryRequestBus.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindowFactoryRequestBus.h index aed0d877db..c93b4ba4b9 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindowFactoryRequestBus.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindowFactoryRequestBus.h @@ -19,11 +19,11 @@ namespace AtomToolsFramework static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single; static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; - /// Creates and shows the AtomToolsMainWindow - virtual void CreateAtomToolsMainWindow() = 0; + /// Creates and shows main window + virtual void CreateMainWindow() = 0; - //! Destroys material editor window and releases all cached assets - virtual void DestroyAtomToolsMainWindow() = 0; + //! Destroys main window and releases all cached assets + virtual void DestroyMainWindow() = 0; }; using AtomToolsMainWindowFactoryRequestBus = AZ::EBus; diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindowNotificationBus.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindowNotificationBus.h index cf5c02085d..cadd3440d9 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindowNotificationBus.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindowNotificationBus.h @@ -18,7 +18,7 @@ namespace AtomToolsFramework static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple; static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; - virtual void OnAtomToolsMainWindowWindowClosing(){}; + virtual void OnMainWindowClosing(){}; }; using AtomToolsMainWindowNotificationBus = AZ::EBus; diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp index 3a542db1a4..4094e7a3a0 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp @@ -10,6 +10,7 @@ #include #include +#include #include #include @@ -66,6 +67,11 @@ namespace AtomToolsFramework }); } + AtomToolsApplication ::~AtomToolsApplication() + { + AtomToolsMainWindowNotificationBus::Handler::BusDisconnect(); + } + void AtomToolsApplication::CreateReflectionManager() { Base::CreateReflectionManager(); @@ -147,12 +153,21 @@ namespace AtomToolsFramework m_timer.start(); } + void AtomToolsApplication::OnMainWindowClosing() + { + ExitMainLoop(); + } + void AtomToolsApplication::Destroy() { + // before modules are unloaded, destroy UI to free up any assets it cached + AtomToolsMainWindowFactoryRequestBus::Broadcast(&AtomToolsMainWindowFactoryRequestBus::Handler::DestroyMainWindow); + AzToolsFramework::EditorPythonConsoleNotificationBus::Handler::BusDisconnect(); AzToolsFramework::AssetDatabase::AssetDatabaseRequestsBus::Handler::BusDisconnect(); - + AtomToolsMainWindowNotificationBus::Handler::BusDisconnect(); AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::StartDisconnectingAssetProcessor); + Base::Destroy(); } @@ -391,6 +406,10 @@ namespace AtomToolsFramework LoadSettings(); + AtomToolsMainWindowNotificationBus::Handler::BusConnect(); + + AtomToolsMainWindowFactoryRequestBus::Broadcast(&AtomToolsMainWindowFactoryRequestBus::Handler::CreateMainWindow); + auto editorPythonEventsInterface = AZ::Interface::Get(); if (editorPythonEventsInterface) { @@ -438,6 +457,8 @@ namespace AtomToolsFramework void AtomToolsApplication::Stop() { + AtomToolsMainWindowFactoryRequestBus::Broadcast(&AtomToolsMainWindowFactoryRequestBus::Handler::DestroyMainWindow); + UnloadSettings(); Base::Stop(); } diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Window/MaterialEditorWindowFactoryRequestBus.h b/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Window/MaterialEditorWindowFactoryRequestBus.h deleted file mode 100644 index 58eb662bd8..0000000000 --- a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Window/MaterialEditorWindowFactoryRequestBus.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -#pragma once - -#include - -namespace MaterialEditor -{ - //! MaterialEditorWindowFactoryRequestBus provides - class MaterialEditorWindowFactoryRequests - : public AZ::EBusTraits - { - public: - static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single; - static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; - - /// Creates and shows the MaterialEditorWindow - virtual void CreateMaterialEditorWindow() = 0; - - //! Destroys material editor window and releases all cached assets - virtual void DestroyMaterialEditorWindow() = 0; - }; - using MaterialEditorWindowFactoryRequestBus = AZ::EBus; - -} // namespace MaterialEditor diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp index 7b9372e72b..53409d717f 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp @@ -6,8 +6,6 @@ * */ -#include - #include #include @@ -17,8 +15,9 @@ #include #include -#include -#include + +#include +#include #include #include @@ -84,7 +83,6 @@ namespace MaterialEditor MaterialEditorApplication::~MaterialEditorApplication() { AzToolsFramework::AssetDatabase::AssetDatabaseRequestsBus::Handler::BusDisconnect(); - MaterialEditorWindowNotificationBus::Handler::BusDisconnect(); AzToolsFramework::EditorPythonConsoleNotificationBus::Handler::BusDisconnect(); } @@ -96,22 +94,6 @@ namespace MaterialEditor outModules.push_back(aznew MaterialEditorWindowModule); } - void MaterialEditorApplication::OnMaterialEditorWindowClosing() - { - ExitMainLoop(); - } - - void MaterialEditorApplication::Destroy() - { - // before modules are unloaded, destroy UI to free up any assets it cached - MaterialEditor::MaterialEditorWindowFactoryRequestBus::Broadcast( - &MaterialEditor::MaterialEditorWindowFactoryRequestBus::Handler::DestroyMaterialEditorWindow); - - MaterialEditorWindowNotificationBus::Handler::BusDisconnect(); - - Base::Destroy(); - } - AZStd::vector MaterialEditorApplication::GetCriticalAssetFilters() const { return AZStd::vector({ "passes/", "config/", "MaterialEditor" }); @@ -122,8 +104,8 @@ namespace MaterialEditor const AZStd::string activateWindowSwitchName = "activatewindow"; if (commandLine.HasSwitch(activateWindowSwitchName)) { - MaterialEditor::MaterialEditorWindowRequestBus::Broadcast( - &MaterialEditor::MaterialEditorWindowRequestBus::Handler::ActivateWindow); + AtomToolsFramework::AtomToolsMainWindowRequestBus::Broadcast( + &AtomToolsFramework::AtomToolsMainWindowRequestBus::Handler::ActivateWindow); } // Process command line options for opening one or more material documents on startup @@ -138,22 +120,4 @@ namespace MaterialEditor Base::ProcessCommandLine(commandLine); } - - void MaterialEditorApplication::StartInternal() - { - Base::StartInternal(); - - MaterialEditorWindowNotificationBus::Handler::BusConnect(); - - MaterialEditor::MaterialEditorWindowFactoryRequestBus::Broadcast( - &MaterialEditor::MaterialEditorWindowFactoryRequestBus::Handler::CreateMaterialEditorWindow); - } - - void MaterialEditorApplication::Stop() - { - MaterialEditor::MaterialEditorWindowFactoryRequestBus::Broadcast( - &MaterialEditor::MaterialEditorWindowFactoryRequestBus::Handler::DestroyMaterialEditorWindow); - - Base::Stop(); - } } // namespace MaterialEditor diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h index b1c742d4dd..2fbab79e41 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h @@ -9,7 +9,6 @@ #pragma once #include -#include #include #include @@ -20,7 +19,6 @@ namespace MaterialEditor class MaterialEditorApplication : public AtomToolsFramework::AtomToolsApplication - , private MaterialEditorWindowNotificationBus::Handler { public: AZ_TYPE_INFO(MaterialEditor::MaterialEditorApplication, "{30F90CA5-1253-49B5-8143-19CEE37E22BB}"); @@ -34,21 +32,9 @@ namespace MaterialEditor // AzFramework::Application void CreateStaticModules(AZStd::vector& outModules) override; const char* GetCurrentConfigurationName() const override; - void Stop() override; private: - ////////////////////////////////////////////////////////////////////////// - // MaterialEditorWindowNotificationBus::Handler overrides... - void OnMaterialEditorWindowClosing() override; - ////////////////////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////////////////////////////// - // AzFramework::Application overrides... - void Destroy() override; - ////////////////////////////////////////////////////////////////////////// - void ProcessCommandLine(const AZ::CommandLine& commandLine) override; - void StartInternal() override; AZStd::string GetBuildTargetName() const override; //! List of common asset filters for things that need to be compiled to run the material editor diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp index 43d91e9721..8367f30680 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp @@ -186,7 +186,7 @@ namespace MaterialEditor windowSettings->m_mainWindowState.assign(windowState.begin(), windowState.end()); AtomToolsFramework::AtomToolsMainWindowNotificationBus::Broadcast( - &AtomToolsFramework::AtomToolsMainWindowNotifications::OnAtomToolsMainWindowWindowClosing); + &AtomToolsFramework::AtomToolsMainWindowNotifications::OnMainWindowClosing); } void MaterialEditorWindow::OnDocumentOpened(const AZ::Uuid& documentId) diff --git a/Gems/Atom/Tools/MaterialEditor/Code/materialeditorwindow_files.cmake b/Gems/Atom/Tools/MaterialEditor/Code/materialeditorwindow_files.cmake index 34d4bc9a28..6294adad88 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/materialeditorwindow_files.cmake +++ b/Gems/Atom/Tools/MaterialEditor/Code/materialeditorwindow_files.cmake @@ -9,7 +9,6 @@ set(FILES Include/Atom/Window/MaterialEditorWindowModule.h Include/Atom/Window/MaterialEditorWindowSettings.h - Include/Atom/Window/MaterialEditorWindowFactoryRequestBus.h Source/Window/MaterialEditorBrowserInteractions.h Source/Window/MaterialEditorBrowserInteractions.cpp Source/Window/MaterialEditorWindow.h diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Include/Atom/Window/ShaderManagementConsoleWindowRequestBus.h b/Gems/Atom/Tools/ShaderManagementConsole/Code/Include/Atom/Window/ShaderManagementConsoleWindowRequestBus.h deleted file mode 100644 index a60b2c0e4c..0000000000 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Include/Atom/Window/ShaderManagementConsoleWindowRequestBus.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -#pragma once - -#include -#include -#include - -namespace ShaderManagementConsole -{ - //! ShaderManagementConsoleWindowRequestBus provides - class ShaderManagementConsoleWindowRequests - : public AZ::EBusTraits - { - public: - static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single; - static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; - - /// Creates and shows main window - virtual void CreateShaderManagementConsoleWindow() = 0; - - //! Destroys main window - virtual void DestroyShaderManagementConsoleWindow() = 0; - }; - using ShaderManagementConsoleWindowRequestBus = AZ::EBus; - -} // namespace ShaderManagementConsole diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp index 7d2aa02e19..e3b3c6e5aa 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp @@ -35,7 +35,6 @@ #include #include -#include #include #include #include @@ -77,6 +76,12 @@ namespace ShaderManagementConsole *AZ::SettingsRegistry::Get(), GetBuildTargetName()); } + ShaderManagementConsoleApplication::~ShaderManagementConsoleApplication() + { + AzToolsFramework::AssetDatabase::AssetDatabaseRequestsBus::Handler::BusDisconnect(); + AzToolsFramework::EditorPythonConsoleNotificationBus::Handler::BusDisconnect(); + } + void ShaderManagementConsoleApplication::CreateStaticModules(AZStd::vector& outModules) { Base::CreateStaticModules(outModules); @@ -84,23 +89,6 @@ namespace ShaderManagementConsole outModules.push_back(aznew ShaderManagementConsoleWindowModule); } - void ShaderManagementConsoleApplication::OnShaderManagementConsoleWindowClosing() - { - ExitMainLoop(); - ShaderManagementConsoleWindowNotificationBus::Handler::BusDisconnect(); - AzToolsFramework::EditorPythonConsoleNotificationBus::Handler::BusDisconnect(); - } - - void ShaderManagementConsoleApplication::Destroy() - { - // before modules are unloaded, destroy UI to free up any assets it cached - ShaderManagementConsole::ShaderManagementConsoleWindowRequestBus::Broadcast(&ShaderManagementConsole::ShaderManagementConsoleWindowRequestBus::Handler::DestroyShaderManagementConsoleWindow); - - ShaderManagementConsoleWindowNotificationBus::Handler::BusDisconnect(); - - Base::Destroy(); - } - AZStd::vector ShaderManagementConsoleApplication::GetCriticalAssetFilters() const { return AZStd::vector({ "passes/", "config/" }); @@ -129,13 +117,4 @@ namespace ShaderManagementConsole ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::OpenDocument, openDocumentPath); } } - - void ShaderManagementConsoleApplication::StartInternal() - { - Base::StartInternal(); - - ShaderManagementConsoleWindowNotificationBus::Handler::BusConnect(); - - ShaderManagementConsole::ShaderManagementConsoleWindowRequestBus::Broadcast(&ShaderManagementConsole::ShaderManagementConsoleWindowRequestBus::Handler::CreateShaderManagementConsoleWindow); - } } // namespace ShaderManagementConsole diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h index 5d3696fee3..4fad40400c 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h @@ -9,7 +9,6 @@ #pragma once #include -#include #include #include @@ -18,7 +17,6 @@ namespace ShaderManagementConsole { class ShaderManagementConsoleApplication : public AtomToolsFramework::AtomToolsApplication - , private ShaderManagementConsoleWindowNotificationBus::Handler { public: AZ_TYPE_INFO(ShaderManagementConsole::ShaderManagementConsoleApplication, "{A31B1AEB-4DA3-49CD-884A-CC998FF7546F}"); @@ -26,7 +24,7 @@ namespace ShaderManagementConsole using Base = AtomToolsFramework::AtomToolsApplication; ShaderManagementConsoleApplication(int* argc, char*** argv); - virtual ~ShaderManagementConsoleApplication() = default; + virtual ~ShaderManagementConsoleApplication(); ////////////////////////////////////////////////////////////////////////// // AzFramework::Application @@ -34,18 +32,7 @@ namespace ShaderManagementConsole const char* GetCurrentConfigurationName() const override; private: - ////////////////////////////////////////////////////////////////////////// - // ShaderManagementConsoleWindowNotificationBus::Handler overrides... - void OnShaderManagementConsoleWindowClosing() override; - ////////////////////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////////////////////////////// - // AzFramework::Application overrides... - void Destroy() override; - ////////////////////////////////////////////////////////////////////////// - void ProcessCommandLine(); - void StartInternal() override; AZStd::string GetBuildTargetName() const override; AZStd::vector GetCriticalAssetFilters() const override; }; diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp index 825b17fb5e..24acf1eb89 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp @@ -82,7 +82,7 @@ namespace ShaderManagementConsole } AtomToolsFramework::AtomToolsMainWindowNotificationBus::Broadcast( - &AtomToolsFramework::AtomToolsMainWindowNotifications::OnAtomToolsMainWindowWindowClosing); + &AtomToolsFramework::AtomToolsMainWindowNotifications::OnMainWindowClosing); } void ShaderManagementConsoleWindow::OnDocumentOpened(const AZ::Uuid& documentId) diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindowComponent.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindowComponent.cpp index 06c219f1cc..b93f164323 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindowComponent.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindowComponent.cpp @@ -44,12 +44,12 @@ namespace ShaderManagementConsole if (AZ::BehaviorContext* behaviorContext = azrtti_cast(context)) { - behaviorContext->EBus("ShaderManagementConsoleWindowRequestBus") + behaviorContext->EBus("ShaderManagementConsoleWindowRequestBus") ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation) ->Attribute(AZ::Script::Attributes::Category, "Editor") ->Attribute(AZ::Script::Attributes::Module, "shadermanagementconsole") - ->Event("CreateShaderManagementConsoleWindow", &ShaderManagementConsoleWindowRequestBus::Events::CreateShaderManagementConsoleWindow) - ->Event("DestroyShaderManagementConsoleWindow", &ShaderManagementConsoleWindowRequestBus::Events::DestroyShaderManagementConsoleWindow) + ->Event("CreateShaderManagementConsoleWindow", &ShaderManagementConsoleWindowFactoryRequestBus::Events::CreateShaderManagementConsoleWindow) + ->Event("DestroyShaderManagementConsoleWindow", &ShaderManagementConsoleWindowFactoryRequestBus::Events::DestroyShaderManagementConsoleWindow) ; behaviorContext->EBus("ShaderManagementConsoleRequestBus") @@ -87,7 +87,7 @@ namespace ShaderManagementConsole void ShaderManagementConsoleWindowComponent::Activate() { AzToolsFramework::EditorWindowRequestBus::Handler::BusConnect(); - ShaderManagementConsoleWindowRequestBus::Handler::BusConnect(); + ShaderManagementConsoleWindowFactoryRequestBus::Handler::BusConnect(); ShaderManagementConsoleRequestBus::Handler::BusConnect(); AzToolsFramework::SourceControlConnectionRequestBus::Broadcast(&AzToolsFramework::SourceControlConnectionRequests::EnableSourceControl, true); } @@ -95,7 +95,7 @@ namespace ShaderManagementConsole void ShaderManagementConsoleWindowComponent::Deactivate() { ShaderManagementConsoleRequestBus::Handler::BusDisconnect(); - ShaderManagementConsoleWindowRequestBus::Handler::BusDisconnect(); + ShaderManagementConsoleWindowFactoryRequestBus::Handler::BusDisconnect(); AzToolsFramework::EditorWindowRequestBus::Handler::BusDisconnect(); m_window.reset(); diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindowComponent.h b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindowComponent.h index 472fc14efb..3d573ec416 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindowComponent.h +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindowComponent.h @@ -13,7 +13,7 @@ #include -#include +#include #include #include #include @@ -24,7 +24,7 @@ namespace ShaderManagementConsole //! used for initialization and registration of other classes, including ShaderManagementConsoleWindow. class ShaderManagementConsoleWindowComponent : public AZ::Component - , private ShaderManagementConsoleWindowRequestBus::Handler + , private ShaderManagementConsoleWindowFactoryRequestBus::Handler , private ShaderManagementConsoleRequestBus::Handler , private AzToolsFramework::EditorWindowRequestBus::Handler { diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/shadermanagementconsolewindow_files.cmake b/Gems/Atom/Tools/ShaderManagementConsole/Code/shadermanagementconsolewindow_files.cmake index 056b74e411..0d33d990a4 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/shadermanagementconsolewindow_files.cmake +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/shadermanagementconsolewindow_files.cmake @@ -8,7 +8,6 @@ set(FILES Include/Atom/Window/ShaderManagementConsoleWindowModule.h - Include/Atom/Window/ShaderManagementConsoleWindowRequestBus.h Include/Atom/Core/ShaderManagementConsoleRequestBus.h Source/Window/ShaderManagementConsoleBrowserInteractions.h Source/Window/ShaderManagementConsoleBrowserInteractions.cpp From f8c8181b0cc6a7c600b7d3d7464d1a00cde4b0b1 Mon Sep 17 00:00:00 2001 From: Dayo Lawal Date: Tue, 3 Aug 2021 19:47:50 -0500 Subject: [PATCH 093/803] Bug fix (updating WindowComponent) Signed-off-by: Dayo Lawal --- .../Window/MaterialEditorWindowComponent.cpp | 18 +++++++++--------- .../Window/MaterialEditorWindowComponent.h | 10 +++++----- .../ShaderManagementConsoleWindowComponent.cpp | 16 +++++++++------- .../ShaderManagementConsoleWindowComponent.h | 10 +++++----- 4 files changed, 28 insertions(+), 26 deletions(-) diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowComponent.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowComponent.cpp index 88c7c0576f..33987df5b6 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowComponent.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowComponent.cpp @@ -6,7 +6,6 @@ * */ -#include #include #include #include @@ -23,6 +22,9 @@ namespace MaterialEditor { + using FactoryRequestBus = AtomToolsFramework::AtomToolsMainWindowFactoryRequestBus; + using RequestBus = AtomToolsFramework::AtomToolsMainWindowRequestBus; + void MaterialEditorWindowComponent::Reflect(AZ::ReflectContext* context) { MaterialEditorWindowSettings::Reflect(context); @@ -35,16 +37,14 @@ namespace MaterialEditor if (AZ::BehaviorContext* behaviorContext = azrtti_cast(context)) { - using FactoryRequestBus = MaterialEditorWindowFactoryRequestBus; behaviorContext->EBus("MaterialEditorWindowFactoryRequestBus") ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) ->Attribute(AZ::Script::Attributes::Category, "Editor") ->Attribute(AZ::Script::Attributes::Module, "materialeditor") - ->Event("CreateMaterialEditorWindow", &FactoryRequestBus::Events::CreateMaterialEditorWindow) - ->Event("DestroyMaterialEditorWindow", &FactoryRequestBus::Events::DestroyMaterialEditorWindow) + ->Event("CreateMaterialEditorWindow", &FactoryRequestBus::Events::CreateMainWindow) + ->Event("DestroyMaterialEditorWindow", &FactoryRequestBus::Events::DestroyMainWindow) ; - using RequestBus = AtomToolsFramework::AtomToolsMainWindowRequestBus; behaviorContext->EBus("MaterialEditorWindowRequestBus") ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) ->Attribute(AZ::Script::Attributes::Category, "Editor") @@ -84,26 +84,26 @@ namespace MaterialEditor void MaterialEditorWindowComponent::Activate() { AzToolsFramework::EditorWindowRequestBus::Handler::BusConnect(); - MaterialEditorWindowFactoryRequestBus::Handler::BusConnect(); + FactoryRequestBus::Handler::BusConnect(); AzToolsFramework::SourceControlConnectionRequestBus::Broadcast(&AzToolsFramework::SourceControlConnectionRequests::EnableSourceControl, true); } void MaterialEditorWindowComponent::Deactivate() { - MaterialEditorWindowFactoryRequestBus::Handler::BusDisconnect(); + FactoryRequestBus::Handler::BusDisconnect(); AzToolsFramework::EditorWindowRequestBus::Handler::BusDisconnect(); m_window.reset(); } - void MaterialEditorWindowComponent::CreateMaterialEditorWindow() + void MaterialEditorWindowComponent::CreateMainWindow() { m_materialEditorBrowserInteractions.reset(aznew MaterialEditorBrowserInteractions); m_window.reset(aznew MaterialEditorWindow); } - void MaterialEditorWindowComponent::DestroyMaterialEditorWindow() + void MaterialEditorWindowComponent::DestroyMainWindow() { m_window.reset(); } diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowComponent.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowComponent.h index c62e399236..87f6160089 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowComponent.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowComponent.h @@ -11,7 +11,7 @@ #include #include -#include +#include #include #include @@ -22,7 +22,7 @@ namespace MaterialEditor class MaterialEditorWindowComponent : public AZ::Component , private AzToolsFramework::EditorWindowRequestBus::Handler - , private MaterialEditorWindowFactoryRequestBus::Handler + , private AtomToolsFramework::AtomToolsMainWindowFactoryRequestBus::Handler { public: AZ_COMPONENT(MaterialEditorWindowComponent, "{03976F19-3C74-49FE-A15F-7D3CADBA616C}"); @@ -35,9 +35,9 @@ namespace MaterialEditor private: //////////////////////////////////////////////////////////////////////// - // MaterialEditorWindowFactoryRequestBus::Handler overrides... - void CreateMaterialEditorWindow() override; - void DestroyMaterialEditorWindow() override; + // AtomToolsMainWindowFactoryRequestBus::Handler overrides... + void CreateMainWindow() override; + void DestroyMainWindow() override; //////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindowComponent.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindowComponent.cpp index b93f164323..e9dda40a50 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindowComponent.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindowComponent.cpp @@ -34,6 +34,8 @@ AZ_POP_DISABLE_WARNING namespace ShaderManagementConsole { + using FactoryRequestBus = AtomToolsFramework::AtomToolsMainWindowFactoryRequestBus; + void ShaderManagementConsoleWindowComponent::Reflect(AZ::ReflectContext* context) { if (AZ::SerializeContext* serialize = azrtti_cast(context)) @@ -44,12 +46,12 @@ namespace ShaderManagementConsole if (AZ::BehaviorContext* behaviorContext = azrtti_cast(context)) { - behaviorContext->EBus("ShaderManagementConsoleWindowRequestBus") + behaviorContext->EBus("ShaderManagementConsoleWindowRequestBus") ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation) ->Attribute(AZ::Script::Attributes::Category, "Editor") ->Attribute(AZ::Script::Attributes::Module, "shadermanagementconsole") - ->Event("CreateShaderManagementConsoleWindow", &ShaderManagementConsoleWindowFactoryRequestBus::Events::CreateShaderManagementConsoleWindow) - ->Event("DestroyShaderManagementConsoleWindow", &ShaderManagementConsoleWindowFactoryRequestBus::Events::DestroyShaderManagementConsoleWindow) + ->Event("CreateShaderManagementConsoleWindow", &FactoryRequestBus::Events::CreateMainWindow) + ->Event("DestroyShaderManagementConsoleWindow", &FactoryRequestBus::Events::DestroyMainWindow) ; behaviorContext->EBus("ShaderManagementConsoleRequestBus") @@ -87,7 +89,7 @@ namespace ShaderManagementConsole void ShaderManagementConsoleWindowComponent::Activate() { AzToolsFramework::EditorWindowRequestBus::Handler::BusConnect(); - ShaderManagementConsoleWindowFactoryRequestBus::Handler::BusConnect(); + FactoryRequestBus::Handler::BusConnect(); ShaderManagementConsoleRequestBus::Handler::BusConnect(); AzToolsFramework::SourceControlConnectionRequestBus::Broadcast(&AzToolsFramework::SourceControlConnectionRequests::EnableSourceControl, true); } @@ -95,7 +97,7 @@ namespace ShaderManagementConsole void ShaderManagementConsoleWindowComponent::Deactivate() { ShaderManagementConsoleRequestBus::Handler::BusDisconnect(); - ShaderManagementConsoleWindowFactoryRequestBus::Handler::BusDisconnect(); + FactoryRequestBus::Handler::BusDisconnect(); AzToolsFramework::EditorWindowRequestBus::Handler::BusDisconnect(); m_window.reset(); @@ -106,7 +108,7 @@ namespace ShaderManagementConsole return m_window.get(); } - void ShaderManagementConsoleWindowComponent::CreateShaderManagementConsoleWindow() + void ShaderManagementConsoleWindowComponent::CreateMainWindow() { m_assetBrowserInteractions.reset(aznew ShaderManagementConsoleBrowserInteractions); @@ -114,7 +116,7 @@ namespace ShaderManagementConsole m_window->show(); } - void ShaderManagementConsoleWindowComponent::DestroyShaderManagementConsoleWindow() + void ShaderManagementConsoleWindowComponent::DestroyMainWindow() { m_window.reset(); } diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindowComponent.h b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindowComponent.h index 3d573ec416..9b43babd9a 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindowComponent.h +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindowComponent.h @@ -13,7 +13,7 @@ #include -#include +#include #include #include #include @@ -24,7 +24,7 @@ namespace ShaderManagementConsole //! used for initialization and registration of other classes, including ShaderManagementConsoleWindow. class ShaderManagementConsoleWindowComponent : public AZ::Component - , private ShaderManagementConsoleWindowFactoryRequestBus::Handler + , private AtomToolsFramework::AtomToolsMainWindowFactoryRequestBus::Handler , private ShaderManagementConsoleRequestBus::Handler , private AzToolsFramework::EditorWindowRequestBus::Handler { @@ -51,9 +51,9 @@ namespace ShaderManagementConsole ////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// - // ShaderManagementConsoleWindowRequestBus::Handler overrides... - void CreateShaderManagementConsoleWindow() override; - void DestroyShaderManagementConsoleWindow() override; + // AtomToolsMainWindowFactoryRequestBus::Handler overrides... + void CreateMainWindow() override; + void DestroyMainWindow() override; //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// From cbfdf99a9efab15a79cdc7ed790291921afcf706 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Tue, 3 Aug 2021 17:59:09 -0700 Subject: [PATCH 094/803] More github cleanup Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../GridMate/GridMate/Carrier/Carrier.cpp | 14 ++++---- .../GridMate/GridMate/Carrier/Carrier.h | 7 ++-- .../GridMate/Carrier/DefaultTrafficControl.h | 2 +- .../GridMate/GridMate/Carrier/Driver.h | 11 +++--- .../GridMate/GridMate/Carrier/Handshake.h | 1 - .../GridMate/Carrier/SecureSocketDriver.cpp | 6 ++-- .../GridMate/Carrier/SecureSocketDriver.h | 6 ++-- .../GridMate/Carrier/SocketDriver.cpp | 27 +++++++------- .../GridMate/GridMate/Carrier/SocketDriver.h | 12 +++---- .../GridMate/Carrier/TrafficControl.h | 1 - .../GridMate/GridMate/Carrier/Utils.h | 4 +-- .../GridMate/Drillers/CarrierDriller.cpp | 2 +- .../GridMate/Drillers/CarrierDriller.h | 2 +- .../GridMate/Drillers/ReplicaDriller.cpp | 1 - .../GridMate/Online/UserServiceTypes.h | 1 - .../GridMate/GridMate/Replica/ReplicaStatus.h | 3 +- .../GridMate/GridMate/Session/LANSession.cpp | 28 +++++++-------- .../GridMate/Session/LANSessionServiceTypes.h | 2 +- .../GridMate/GridMate/Session/Session.cpp | 36 +++++++++---------- .../GridMate/GridMate/Session/Session.h | 20 +++++------ .../GridMate/GridMate/String/StringUtils.h | 10 ------ .../GridMate/GridMate/String/string.h | 26 -------------- .../GridMate/VoiceChat/VoiceChatServiceBus.h | 1 - .../GridMate/GridMate/gridmate_files.cmake | 1 - .../GridMate/Session/LANSession_Android.cpp | 5 ++- .../GridMate/Carrier/Utils_UnixLike.cpp | 4 +-- .../WinAPI/GridMate/Carrier/Utils_WinAPI.cpp | 4 +-- .../GridMate/Session/LANSession_Linux.cpp | 5 ++- .../GridMate/String/StringUtils_Platform.h | 8 ----- .../Mac/GridMate/Session/LANSession_Mac.cpp | 5 ++- .../GridMate/Session/LANSession_Windows.cpp | 6 ++-- .../iOS/GridMate/Session/LANSession_iOS.cpp | 5 ++- Code/Framework/GridMate/Tests/Carrier.cpp | 8 ++--- .../Tests/CarrierStreamSocketDriverTests.cpp | 6 ++-- Code/Framework/GridMate/Tests/Replica.cpp | 4 +-- Code/Framework/GridMate/Tests/Serialize.cpp | 4 +-- .../Framework/GridMate/Tests/TestProfiler.cpp | 20 +++++------ 37 files changed, 125 insertions(+), 183 deletions(-) delete mode 100644 Code/Framework/GridMate/GridMate/String/StringUtils.h delete mode 100644 Code/Framework/GridMate/GridMate/String/string.h delete mode 100644 Code/Framework/GridMate/Platform/Linux/GridMate/String/StringUtils_Platform.h diff --git a/Code/Framework/GridMate/GridMate/Carrier/Carrier.cpp b/Code/Framework/GridMate/GridMate/Carrier/Carrier.cpp index 23e967c3fa..0285a7fc02 100644 --- a/Code/Framework/GridMate/GridMate/Carrier/Carrier.cpp +++ b/Code/Framework/GridMate/GridMate/Carrier/Carrier.cpp @@ -422,7 +422,7 @@ namespace GridMate CarrierThread* m_threadOwner; ///< Pointer to the carrier thread that operates with this connection. AZStd::atomic m_threadConn; ///< Pointer to a thread connection. You can use it in the main thread only for a reference. - string m_fullAddress; ///< Connection full address. + AZStd::string m_fullAddress; ///< Connection full address. Carrier::ConnectionStates m_state; @@ -604,7 +604,7 @@ namespace GridMate Connection* m_connection; ThreadConnection* m_threadConnection; - string m_newConnectionAddress; + AZStd::string m_newConnectionAddress; CarrierErrorCode m_errorCode; AZ::u32 m_newRateBytesPerSec; ///< new send rate AZStd::vector > m_ackCallbacks; @@ -1007,7 +1007,7 @@ namespace GridMate unsigned int GetMessageMTU() override { return m_maxMsgDataSizeBytes; } - string ConnectionToAddress(ConnectionID id) override; + AZStd::string ConnectionToAddress(ConnectionID id) override; void SendWithCallback(const char* data, unsigned int dataSize, AZStd::unique_ptr ackCallback, ConnectionID target = AllConnections, DataReliability reliability = SEND_RELIABLE, DataPriority priority = PRIORITY_NORMAL, unsigned char channel = 0) override; void Send(const char* data, unsigned int dataSize, ConnectionID target = AllConnections, DataReliability reliability = SEND_RELIABLE, DataPriority priority = PRIORITY_NORMAL, unsigned char channel = 0) override @@ -3902,10 +3902,10 @@ CarrierImpl::DeleteConnection(Connection* conn, CarrierDisconnectReason reason) // Carrier // [9/14/2010] //========================================================================= -string +AZStd::string CarrierImpl::ConnectionToAddress(ConnectionID id) { - string str; + AZStd::string str; AZ_Assert(id != InvalidConnectionID, "Invalid connection id!"); if (id != InvalidConnectionID) { @@ -4911,7 +4911,7 @@ DefaultCarrier::Create(const CarrierDesc& desc, IGridMate* gridMate) // ReasonToString // [4/11/2011] //========================================================================= -string +AZStd::string CarrierEventsBase::ReasonToString(CarrierDisconnectReason reason) { const char* reasonStr = 0; @@ -4951,5 +4951,5 @@ CarrierEventsBase::ReasonToString(CarrierDisconnectReason reason) reasonStr = "Unknown reason"; } - return string(reasonStr); + return AZStd::string(reasonStr); } diff --git a/Code/Framework/GridMate/GridMate/Carrier/Carrier.h b/Code/Framework/GridMate/GridMate/Carrier/Carrier.h index 2968582c0d..94c31ed6d2 100644 --- a/Code/Framework/GridMate/GridMate/Carrier/Carrier.h +++ b/Code/Framework/GridMate/GridMate/Carrier/Carrier.h @@ -9,7 +9,6 @@ #define GM_CARRIER_H #include -#include #include #include #include @@ -100,7 +99,7 @@ namespace GridMate /// Returns maximum message size (with splitting or without). Splitting will make your message reliable, which might not be optimal for Unreliable messages. It's better to send two unreliable. //virtual unsigned int GetMaxMessageSize(bool withSplitting = true) = 0; - virtual string ConnectionToAddress(ConnectionID id) = 0; + virtual AZStd::string ConnectionToAddress(ConnectionID id) = 0; /** * Sends buffer with an ACK callback. When the transport layer recieves an ACK it will run the callback. @@ -401,7 +400,7 @@ namespace GridMate public: virtual ~CarrierEventsBase() {} - string ReasonToString(CarrierDisconnectReason reason); + AZStd::string ReasonToString(CarrierDisconnectReason reason); }; class CarrierEvents @@ -517,7 +516,7 @@ namespace GridMate // Traffic control /// Called every second when you update last second statistics - virtual void OnUpdateStatistics(const GridMate::string& address, const TrafficControl::Statistics& lastSecond, const TrafficControl::Statistics& lifeTime, const TrafficControl::Statistics& effectiveLastSecond, const TrafficControl::Statistics& effectiveLifeTime) = 0; + virtual void OnUpdateStatistics(const AZStd::string& address, const TrafficControl::Statistics& lastSecond, const TrafficControl::Statistics& lifeTime, const TrafficControl::Statistics& effectiveLastSecond, const TrafficControl::Statistics& effectiveLifeTime) = 0; // Simulator /// Enable/Disable diff --git a/Code/Framework/GridMate/GridMate/Carrier/DefaultTrafficControl.h b/Code/Framework/GridMate/GridMate/Carrier/DefaultTrafficControl.h index 525009b015..1d8a1f6b46 100644 --- a/Code/Framework/GridMate/GridMate/Carrier/DefaultTrafficControl.h +++ b/Code/Framework/GridMate/GridMate/Carrier/DefaultTrafficControl.h @@ -145,7 +145,7 @@ namespace GridMate StatisticData m_sdEffectiveLastSecond; ///< Last second statistics for effective data. StatisticData m_sdEffectiveCurrentSecond; ///< Elapsing second statistics for effective data. - string m_address; ///< Full address for this connection. (we need for debug only) + AZStd::string m_address; ///< Full address for this connection. (we need for debug only) unsigned int m_recvPacketAllowance; ///< Current allowance for number of incoming packets bool m_canReceiveData; ///< Able to receive data on this connection diff --git a/Code/Framework/GridMate/GridMate/Carrier/Driver.h b/Code/Framework/GridMate/GridMate/Carrier/Driver.h index 2c806be5e0..d6d47fc491 100644 --- a/Code/Framework/GridMate/GridMate/Carrier/Driver.h +++ b/Code/Framework/GridMate/GridMate/Carrier/Driver.h @@ -10,10 +10,9 @@ #include -#include - #include #include +#include namespace GridMate { @@ -139,7 +138,7 @@ namespace GridMate /// @{ Address conversion functionality. They MUST implemented thread safe. Generally this is not a problem since they just part local data. /// Create address from ip and port. If ip == NULL we will assign a broadcast address. - virtual string IPPortToAddress(const char* ip, unsigned int port) const = 0; + virtual AZStd::string IPPortToAddress(const char* ip, unsigned int port) const = 0; virtual bool AddressToIPPort(const AZStd::string& address, AZStd::string& ip, unsigned int& port) const = 0; /// @} @@ -188,11 +187,11 @@ namespace GridMate virtual ~DriverAddress() {} - virtual string ToString() const = 0; + virtual AZStd::string ToString() const = 0; - virtual string ToAddress() const = 0; + virtual AZStd::string ToAddress() const = 0; - virtual string GetIP() const = 0; + virtual AZStd::string GetIP() const = 0; virtual unsigned int GetPort() const = 0; diff --git a/Code/Framework/GridMate/GridMate/Carrier/Handshake.h b/Code/Framework/GridMate/GridMate/Carrier/Handshake.h index ffd332b65c..0f825da49b 100644 --- a/Code/Framework/GridMate/GridMate/Carrier/Handshake.h +++ b/Code/Framework/GridMate/GridMate/Carrier/Handshake.h @@ -10,7 +10,6 @@ #include #include -#include namespace GridMate { diff --git a/Code/Framework/GridMate/GridMate/Carrier/SecureSocketDriver.cpp b/Code/Framework/GridMate/GridMate/Carrier/SecureSocketDriver.cpp index 7d0d5644b3..031e8561ec 100644 --- a/Code/Framework/GridMate/GridMate/Carrier/SecureSocketDriver.cpp +++ b/Code/Framework/GridMate/GridMate/Carrier/SecureSocketDriver.cpp @@ -1712,7 +1712,7 @@ namespace GridMate } // Calculate HMAC of buffer using the secret and peer address - GridMate::string addrStr = endpoint->ToAddress(); + AZStd::string addrStr = endpoint->ToAddress(); unsigned char result[EVP_MAX_MD_SIZE]; unsigned int resultLen = 0; HMAC(EVP_sha1(), m_cookieSecret.m_currentSecret, sizeof(m_cookieSecret.m_currentSecret), @@ -1745,7 +1745,7 @@ namespace GridMate } // Calculate HMAC of buffer using the secret and peer address - GridMate::string addrStr = endpoint->ToAddress(); + AZStd::string addrStr = endpoint->ToAddress(); unsigned char result[EVP_MAX_MD_SIZE]; unsigned int resultLen = 0; HMAC(EVP_sha1(), m_cookieSecret.m_currentSecret, COOKIE_SECRET_LENGTH, @@ -1809,7 +1809,7 @@ namespace GridMate #ifdef AZ_DebugUseSocketDebugLog if (handshake) { - GridMate::string line = GridMate::string::format("%lld | [%08x] RawRecv %s size %d connection exists\n", AZStd::chrono::system_clock::now().time_since_epoch().count(), this, type, bytesReceived); + AZStd::string line = AZStd::string::format("%lld | [%08x] RawRecv %s size %d connection exists\n", AZStd::chrono::system_clock::now().time_since_epoch().count(), this, type, bytesReceived); connection->m_dbgLog += line; } #endif diff --git a/Code/Framework/GridMate/GridMate/Carrier/SecureSocketDriver.h b/Code/Framework/GridMate/GridMate/Carrier/SecureSocketDriver.h index 529ccea408..76b7958085 100644 --- a/Code/Framework/GridMate/GridMate/Carrier/SecureSocketDriver.h +++ b/Code/Framework/GridMate/GridMate/Carrier/SecureSocketDriver.h @@ -23,7 +23,7 @@ //#define AZ_DebugSecureSocket AZ_TracePrintf //#define AZ_DebugSecureSocketConnection(window, fmt, ...) \ //{\ -// GridMate::string line = GridMate::string::format(fmt, __VA_ARGS__);\ +// AZStd::string line = AZStd::string::format(fmt, __VA_ARGS__);\ // this->m_dbgLog += line;\ //} @@ -226,7 +226,7 @@ namespace GridMate int m_dbgDgramsReceived; int m_dbgPort; #ifdef AZ_DebugUseSocketDebugLog - GridMate::string m_dbgLog; + AZStd::string m_dbgLog; #endif }; @@ -262,7 +262,7 @@ namespace GridMate AZ::u32 m_maxTempBufferSize; AZStd::queue m_globalInQueue; AZStd::unordered_map m_connections; - AZStd::unordered_map m_ipToNumConnections; + AZStd::unordered_map m_ipToNumConnections; SecureSocketDesc m_desc; AZStd::chrono::system_clock::time_point m_lastTimerCheck; ///Time last timers were checked }; diff --git a/Code/Framework/GridMate/GridMate/Carrier/SocketDriver.cpp b/Code/Framework/GridMate/GridMate/Carrier/SocketDriver.cpp index fc3062062c..6acf778798 100644 --- a/Code/Framework/GridMate/GridMate/Carrier/SocketDriver.cpp +++ b/Code/Framework/GridMate/GridMate/Carrier/SocketDriver.cpp @@ -18,7 +18,6 @@ //#define AZ_LOG_UNBOUND_SEND_RECEIVE #include -#include #include #include @@ -575,7 +574,7 @@ namespace GridMate return !(*this == rhs); } - string SocketDriverAddress::ToString() const + AZStd::string SocketDriverAddress::ToString() const { char ip[64]; unsigned short port; @@ -590,15 +589,15 @@ namespace GridMate port = ntohs(m_sockAddr.sin_port); } - return string::format("%s|%d", ip, port); + return AZStd::string::format("%s|%d", ip, port); } - string SocketDriverAddress::ToAddress() const + AZStd::string SocketDriverAddress::ToAddress() const { return ToString(); } - string SocketDriverAddress::GetIP() const + AZStd::string SocketDriverAddress::GetIP() const { char ip[64]; if (m_sockAddr.sin_family == AF_INET6) @@ -609,7 +608,7 @@ namespace GridMate { inet_ntop(AF_INET, const_cast(reinterpret_cast(&m_sockAddr.sin_addr)), ip, AZ_ARRAY_SIZE(ip)); } - return string(ip); + return AZStd::string(ip); } unsigned int SocketDriverAddress::GetPort() const @@ -1144,11 +1143,11 @@ namespace GridMate // CreateSocketDriver // [3/4/2013] //========================================================================= - string + AZStd::string SocketDriverCommon::IPPortToAddressString(const char* ip, unsigned int port) { AZ_Assert(ip != nullptr, "Invalid address!"); - return string::format("%s|%d", ip, port); + return AZStd::string::format("%s|%d", ip, port); } //========================================================================= @@ -1159,14 +1158,14 @@ namespace GridMate SocketDriverCommon::AddressStringToIPPort(const AZStd::string& address, AZStd::string& ip, unsigned int& port) { AZStd::size_t pos = address.find('|'); - AZ_Assert(pos != string::npos, "Invalid driver address!"); - if (pos == string::npos) + AZ_Assert(pos != AZStd::string::npos, "Invalid driver address!"); + if (pos == AZStd::string::npos) { return false; } - ip = string(address.begin(), address.begin() + pos); - port = AZStd::stoi(string(address.begin() + pos + 1, address.end())); + ip = AZStd::string(address.begin(), address.begin() + pos); + port = AZStd::stoi(AZStd::string(address.begin() + pos + 1, address.end())); return true; } @@ -1180,12 +1179,12 @@ namespace GridMate { // TODO: We can/should use inet_ntop() to detect the family type AZStd::size_t pos = ip.find("."); - if (pos != string::npos) + if (pos != AZStd::string::npos) { return BSD_AF_INET; } pos = ip.find("::"); - if (pos != string::npos) + if (pos != AZStd::string::npos) { return BSD_AF_INET6; } diff --git a/Code/Framework/GridMate/GridMate/Carrier/SocketDriver.h b/Code/Framework/GridMate/GridMate/Carrier/SocketDriver.h index 7555c92639..835414b374 100644 --- a/Code/Framework/GridMate/GridMate/Carrier/SocketDriver.h +++ b/Code/Framework/GridMate/GridMate/Carrier/SocketDriver.h @@ -88,9 +88,9 @@ namespace GridMate bool operator==(const SocketDriverAddress& rhs) const; bool operator!=(const SocketDriverAddress& rhs) const; - virtual string ToString() const; - virtual string ToAddress() const; - virtual string GetIP() const; + virtual AZStd::string ToString() const; + virtual AZStd::string ToAddress() const; + virtual AZStd::string GetIP() const; virtual unsigned int GetPort() const; virtual const void* GetTargetAddress(unsigned int& addressSize) const; @@ -163,15 +163,15 @@ namespace GridMate /// @{ Address conversion functionality. They MUST implemented thread safe. Generally this is not a problem since they just part local data. /// Create address from ip and port. If ip == NULL we will assign a broadcast address. - virtual string IPPortToAddress(const char* ip, unsigned int port) const { return IPPortToAddressString(ip, port); } + virtual AZStd::string IPPortToAddress(const char* ip, unsigned int port) const { return IPPortToAddressString(ip, port); } virtual bool AddressToIPPort(const AZStd::string& address, AZStd::string& ip, unsigned int& port) const { return AddressStringToIPPort(address, ip, port); } /// Create address for the socket driver from IP and port - static string IPPortToAddressString(const char* ip, unsigned int port); + static AZStd::string IPPortToAddressString(const char* ip, unsigned int port); /// Decompose an address to IP and port static bool AddressStringToIPPort(const AZStd::string& address, AZStd::string& ip, unsigned int& port); /// Return the family type of the address (AF_INET,AF_INET6 AF_UNSPEC) static BSDSocketFamilyType AddressFamilyType(const AZStd::string& ip); - static BSDSocketFamilyType AddressFamilyType(const char* ip) { return AddressFamilyType(string(ip)); } + static BSDSocketFamilyType AddressFamilyType(const char* ip) { return AddressFamilyType(AZStd::string(ip)); } /// @} virtual AZStd::intrusive_ptr CreateDriverAddress(const AZStd::string& address) = 0; diff --git a/Code/Framework/GridMate/GridMate/Carrier/TrafficControl.h b/Code/Framework/GridMate/GridMate/Carrier/TrafficControl.h index 2b49f320b5..7b79124a73 100644 --- a/Code/Framework/GridMate/GridMate/Carrier/TrafficControl.h +++ b/Code/Framework/GridMate/GridMate/Carrier/TrafficControl.h @@ -9,7 +9,6 @@ #define GM_TRAFFIC_CONTROL_H #include -#include #include diff --git a/Code/Framework/GridMate/GridMate/Carrier/Utils.h b/Code/Framework/GridMate/GridMate/Carrier/Utils.h index 2b15696ac2..db58ec979e 100644 --- a/Code/Framework/GridMate/GridMate/Carrier/Utils.h +++ b/Code/Framework/GridMate/GridMate/Carrier/Utils.h @@ -8,14 +8,14 @@ #ifndef GM_CARRIER_UTILS_H #define GM_CARRIER_UTILS_H -#include +#include namespace GridMate { namespace Utils { ///< Returns the machines address(ip) in a string. familyType is platform dependent. - string GetMachineAddress(int familyType = 0); + AZStd::string GetMachineAddress(int familyType = 0); ///< Returns a broadcast address based on a family type. On ipv6 we emulate broadbast using the multicast on the all nodes address (FF02::1). familyType is platform dependent. const char* GetBroadcastAddress(int familyType = 0); } diff --git a/Code/Framework/GridMate/GridMate/Drillers/CarrierDriller.cpp b/Code/Framework/GridMate/GridMate/Drillers/CarrierDriller.cpp index 528afa6cce..38f029f0f5 100644 --- a/Code/Framework/GridMate/GridMate/Drillers/CarrierDriller.cpp +++ b/Code/Framework/GridMate/GridMate/Drillers/CarrierDriller.cpp @@ -64,7 +64,7 @@ namespace GridMate // OnUpdateStatistics // [4/14/2011] //========================================================================= - void CarrierDriller::OnUpdateStatistics(const GridMate::string& address, const TrafficControl::Statistics& lastSecond, const TrafficControl::Statistics& lifeTime, const TrafficControl::Statistics& effectiveLastSecond, const TrafficControl::Statistics& effectiveLifeTime) + void CarrierDriller::OnUpdateStatistics(const AZStd::string& address, const TrafficControl::Statistics& lastSecond, const TrafficControl::Statistics& lifeTime, const TrafficControl::Statistics& effectiveLastSecond, const TrafficControl::Statistics& effectiveLifeTime) { m_output->BeginTag(m_drillerTag); m_output->BeginTag(AZ_CRC("Statistics", 0xe2d38b22)); diff --git a/Code/Framework/GridMate/GridMate/Drillers/CarrierDriller.h b/Code/Framework/GridMate/GridMate/Drillers/CarrierDriller.h index bb3cb1e3b2..b12441e6fa 100644 --- a/Code/Framework/GridMate/GridMate/Drillers/CarrierDriller.h +++ b/Code/Framework/GridMate/GridMate/Drillers/CarrierDriller.h @@ -42,7 +42,7 @@ namespace GridMate ////////////////////////////////////////////////////////////////////////// // Carrier Driller Bus - void OnUpdateStatistics(const GridMate::string& address, const TrafficControl::Statistics& lastSecond, const TrafficControl::Statistics& lifeTime, const TrafficControl::Statistics& effectiveLastSecond, const TrafficControl::Statistics& effectiveLifeTime) override; + void OnUpdateStatistics(const AZStd::string& address, const TrafficControl::Statistics& lastSecond, const TrafficControl::Statistics& lifeTime, const TrafficControl::Statistics& effectiveLastSecond, const TrafficControl::Statistics& effectiveLifeTime) override; void OnConnectionStateChanged(Carrier* carrier, ConnectionID id, Carrier::ConnectionStates newState) override; ////////////////////////////////////////////////////////////////////////// diff --git a/Code/Framework/GridMate/GridMate/Drillers/ReplicaDriller.cpp b/Code/Framework/GridMate/GridMate/Drillers/ReplicaDriller.cpp index e70aceabc9..cb48578255 100644 --- a/Code/Framework/GridMate/GridMate/Drillers/ReplicaDriller.cpp +++ b/Code/Framework/GridMate/GridMate/Drillers/ReplicaDriller.cpp @@ -9,7 +9,6 @@ #include #include #include -#include using namespace AZ::Debug; diff --git a/Code/Framework/GridMate/GridMate/Online/UserServiceTypes.h b/Code/Framework/GridMate/GridMate/Online/UserServiceTypes.h index 2617d98d73..c1753b3bb2 100644 --- a/Code/Framework/GridMate/GridMate/Online/UserServiceTypes.h +++ b/Code/Framework/GridMate/GridMate/Online/UserServiceTypes.h @@ -9,7 +9,6 @@ #define GM_USER_SERVICE_TYPES_H #include -#include namespace GridMate { diff --git a/Code/Framework/GridMate/GridMate/Replica/ReplicaStatus.h b/Code/Framework/GridMate/GridMate/Replica/ReplicaStatus.h index 019a595f6f..aeb5c1b2bb 100644 --- a/Code/Framework/GridMate/GridMate/Replica/ReplicaStatus.h +++ b/Code/Framework/GridMate/GridMate/Replica/ReplicaStatus.h @@ -12,7 +12,6 @@ #include #include #include -#include #include namespace GridMate @@ -102,7 +101,7 @@ namespace GridMate }; AZ::u8 m_flags; - string m_replicaName; + AZStd::string m_replicaName; }; DataSet m_options; // Flags and debug info diff --git a/Code/Framework/GridMate/GridMate/Session/LANSession.cpp b/Code/Framework/GridMate/GridMate/Session/LANSession.cpp index 0127d8fa23..e4e1c9e9b6 100644 --- a/Code/Framework/GridMate/GridMate/Session/LANSession.cpp +++ b/Code/Framework/GridMate/GridMate/Session/LANSession.cpp @@ -52,17 +52,17 @@ namespace GridMate MemberIDCompact GetID() const { return m_id; } - virtual string ToString() const + virtual AZStd::string ToString() const { - return string::format("%x", m_id); + return AZStd::string::format("%x", m_id); } - virtual string ToAddress() const { return m_address; } + virtual AZStd::string ToAddress() const { return m_address; } virtual MemberIDCompact Compact() const { return m_id; } virtual bool IsValid() const { return m_id != 0; } private: MemberIDCompact m_id; - string m_address; + AZStd::string m_address; }; class LANMemberIDMarshaler @@ -141,7 +141,7 @@ namespace GridMate bool MatchMake(const LANSearchParams& sp); - string MakeSessionId(); + AZStd::string MakeSessionId(); Driver* m_driver; ///< Driver for network searches @@ -199,7 +199,7 @@ namespace GridMate : public CtorContextBase { CtorDataSet m_memberId; - CtorDataSet m_memberAddress; ///< As the server/host sees it! + CtorDataSet m_memberAddress; ///< As the server/host sees it! CtorDataSet m_peerMode; CtorDataSet m_isHost; }; @@ -232,7 +232,7 @@ namespace GridMate AZ_Assert(session, "We need to have a valid session!"); LANMember* member; MemberIDCompact memberId = ctorContext.m_memberId.Get(); - string memberAddress = ctorContext.m_memberAddress.Get(); + AZStd::string memberAddress = ctorContext.m_memberAddress.Get(); RemotePeerMode remotePeerMode = ctorContext.m_peerMode.Get(); bool isMemberHost = ctorContext.m_isHost.Get(); @@ -349,7 +349,7 @@ namespace GridMate { namespace Platform { - void AssignExtendedName(GridMate::string& extendedName); + void AssignExtendedName(AZStd::string& extendedName); } } @@ -364,7 +364,7 @@ LANMember::LANMember(const LANMemberID& id, LANSession* session) : GridMember(id.Compact()) , m_memberId(id) { - string extendedName; + AZStd::string extendedName; Platform::AssignExtendedName(extendedName); m_session = session; @@ -741,8 +741,8 @@ LANSession::CreateLocalMember(bool isHost, bool isInvited, RemotePeerMode peerMo { AZ_Assert(m_myMember == nullptr, "We already have added a local member!"); - string ip = Utils::GetMachineAddress(m_carrierDesc.m_familyType); - string address = SocketDriverCommon::IPPortToAddressString(ip.c_str(), m_carrierDesc.m_port); + AZStd::string ip = Utils::GetMachineAddress(m_carrierDesc.m_familyType); + AZStd::string address = SocketDriverCommon::IPPortToAddressString(ip.c_str(), m_carrierDesc.m_port); ///////////////////////////////////////////////////////////////////////////// // TODO: Use the UUID as an ID, we will need to add marshalers and so on AZ::Uuid uuid = AZ::Uuid::CreateRandom(); @@ -881,7 +881,7 @@ LANSession::OnStateHostMigrateSession(AZ::HSM& sm, const AZ::HSM::Event& e) if (m_driver->Initialize(Driver::BSD_AF_INET, nullptr, hostPort, true) != Driver::EC_OK) { // check the output for more info - string errorMsg = string::format("Failed to initialize socket at port %d!", hostPort); + AZStd::string errorMsg = AZStd::string::format("Failed to initialize socket at port %d!", hostPort); EBUS_DBG_EVENT(Debug::SessionDrillerBus, OnSessionError, this, errorMsg); EBUS_EVENT_ID(m_gridMate, SessionEventBus, OnSessionError, this, errorMsg); // We can't be a real host if we failed to provide matching services. @@ -899,7 +899,7 @@ LANSession::OnStateHostMigrateSession(AZ::HSM& sm, const AZ::HSM::Event& e) // MakeSessionId // [3/7/2013] //========================================================================= -string +AZStd::string LANSession::MakeSessionId() { char temp[64]; @@ -990,7 +990,7 @@ LANSearch::Update() wb.Write(m_searchParams.m_params[i].m_type); } - string serverAddress = m_searchParams.m_serverAddress; + AZStd::string serverAddress = m_searchParams.m_serverAddress; if (serverAddress.empty()) { serverAddress = Utils::GetBroadcastAddress(m_searchParams.m_familyType); diff --git a/Code/Framework/GridMate/GridMate/Session/LANSessionServiceTypes.h b/Code/Framework/GridMate/GridMate/Session/LANSessionServiceTypes.h index 20ade42a6e..42524e034a 100644 --- a/Code/Framework/GridMate/GridMate/Session/LANSessionServiceTypes.h +++ b/Code/Framework/GridMate/GridMate/Session/LANSessionServiceTypes.h @@ -20,7 +20,7 @@ namespace GridMate : m_port (0) // by default session can't be found (searched for) {} - string m_address; /// empty to accept any address otherwise you can provide a specific bind address. + AZStd::string m_address; /// empty to accept any address otherwise you can provide a specific bind address. /** * Use 0 if you don't want you session to be searchable (default) * Port on which we will register the LAN session (it will be used for session communication and should be different than the game/carrier one). diff --git a/Code/Framework/GridMate/GridMate/Session/Session.cpp b/Code/Framework/GridMate/GridMate/Session/Session.cpp index 8a9bdea273..471e21127c 100644 --- a/Code/Framework/GridMate/GridMate/Session/Session.cpp +++ b/Code/Framework/GridMate/GridMate/Session/Session.cpp @@ -60,7 +60,7 @@ namespace GridMate typedef vector NewConnectionsType; typedef vector UserDataBufferType; - typedef unordered_set AddressSetType; + typedef unordered_set AddressSetType; GridSessionHandshake(unsigned int handshakeTimeoutMS, const VersionType& version); virtual ~GridSessionHandshake() {} @@ -99,12 +99,12 @@ namespace GridMate virtual unsigned int GetHandshakeTimeOutMS() const { return m_handshakeTimeOutMS; } ////////////////////////////////////////////////////////////////////////// - void BanAddress(string address); + void BanAddress(AZStd::string address); void SetHost(bool isHost); void SetInvited(bool isInvited); void SetHostMigration(bool isMigrating); void SetUserData(const void* data, size_t dataSize); - void SetSessionId(string sessionId); + void SetSessionId(AZStd::string sessionId); bool IsNewConnections() { return !m_newConnections.empty(); } NewConnectionsType& AcquireNewConnections(); void ReleaseNewConnections(); @@ -117,7 +117,7 @@ namespace GridMate NewConnectionsType m_newConnections; AddressSetType m_banList; UserDataBufferType m_userData; - string m_sessionId; + AZStd::string m_sessionId; RemotePeerMode m_peerMode; VersionType m_version; @@ -165,7 +165,7 @@ void GridSessionParam::SetValue(AZ::s32* values, size_t numElements) if (numElements > 0) { AZ_Assert(values != nullptr, "Invalid values pointer!"); - string temp; + AZStd::string temp; for (size_t i = 0; i < numElements; ++i) { AZStd::to_string(temp, values[i]); @@ -183,7 +183,7 @@ void GridSessionParam::SetValue(AZ::s64* values, size_t numElements) if (numElements > 0) { AZ_Assert(values != nullptr, "Invalid values pointer!"); - string temp; + AZStd::string temp; for (size_t i = 0; i < numElements; ++i) { AZStd::to_string(temp, values[i]); @@ -201,7 +201,7 @@ void GridSessionParam::SetValue(float* values, size_t numElements) if (numElements > 0) { AZ_Assert(values != nullptr, "Invalid values pointer!"); - string temp; + AZStd::string temp; for (size_t i = 0; i < numElements; ++i) { AZStd::to_string(temp, values[i]); @@ -219,7 +219,7 @@ void GridSessionParam::SetValue(double* values, size_t numElements) if (numElements > 0) { AZ_Assert(values != nullptr, "Invalid values pointer!"); - string temp; + AZStd::string temp; for (size_t i = 0; i < numElements; ++i) { AZStd::to_string(temp, values[i]); @@ -726,7 +726,7 @@ GridSession::RemoveParam(unsigned int index) { const GridSessionReplica::ParamContainer& curParams = m_state->m_params.Get(); const GridSessionParam& foundParam = curParams.at(index); - string paramId = foundParam.m_id; + AZStd::string paramId = foundParam.m_id; m_state->m_params.Modify([=](Internal::GridSessionReplica::ParamContainer& params) { params.erase(¶ms.at(index)); @@ -1220,7 +1220,7 @@ GridSession::OnDriverError(Carrier* carrier, ConnectionID id, const DriverError& return; // not for us } uintptr_t idInt = reinterpret_cast(static_cast(id)); - string errorMsg = string::format("Carrier driver error ConnectionID: %" PRIuPTR "ErrorCode: 0x%08x", idInt, error.m_errorCode); + AZStd::string errorMsg = AZStd::string::format("Carrier driver error ConnectionID: %" PRIuPTR "ErrorCode: 0x%08x", idInt, error.m_errorCode); EBUS_DBG_EVENT(Debug::SessionDrillerBus, OnSessionError, this, errorMsg); EBUS_EVENT_ID(m_gridMate, SessionEventBus, OnSessionError, this, errorMsg); @@ -1248,7 +1248,7 @@ GridSession::OnSecurityError(Carrier* carrier, ConnectionID id, const SecurityEr return; // not for us } uintptr_t idInt = reinterpret_cast(static_cast(id)); - string errorMsg = string::format("Carrier security error ConnectionID: %" PRIuPTR " ErrorCode: 0x%08x", idInt, error.m_errorCode); + AZStd::string errorMsg = AZStd::string::format("Carrier security error ConnectionID: %" PRIuPTR " ErrorCode: 0x%08x", idInt, error.m_errorCode); EBUS_DBG_EVENT(Debug::SessionDrillerBus, OnSessionError, this, errorMsg); } @@ -1976,7 +1976,7 @@ GridMember::GetNatType() const //========================================================================= // GetName //========================================================================= -string +AZStd::string GridMember::GetName() const { return m_clientState ? m_clientState->m_name.Get().c_str() : "Unknown"; @@ -2244,7 +2244,7 @@ GridMember::GetProcessId() const //========================================================================= // GetMachineName //========================================================================= -string +AZStd::string GridMember::GetMachineName() const { if (m_clientState) @@ -2253,7 +2253,7 @@ GridMember::GetMachineName() const } else { - return string(); + return AZStd::string(); } } @@ -2688,7 +2688,7 @@ HandshakeErrorCode GridSessionHandshake::OnReceiveRequest(ConnectionID id, ReadB { (void)id; AZStd::lock_guard l(m_dataLock); - string sessionId; + AZStd::string sessionId; bool isInvited = false; RemotePeerMode peerMode; VersionType version; @@ -2761,7 +2761,7 @@ bool GridSessionHandshake::OnConfirmRequest(ConnectionID id, ReadBuffer& rb) (void)id; AZStd::lock_guard l(m_dataLock); - string sessionId; + AZStd::string sessionId; if (!rb.Read(sessionId)) { return false; @@ -2818,7 +2818,7 @@ void GridSessionHandshake::OnDisconnect(ConnectionID id) //========================================================================= // BanAddress //========================================================================= -void GridSessionHandshake::BanAddress(string address) +void GridSessionHandshake::BanAddress(AZStd::string address) { AZStd::lock_guard l(m_dataLock); m_banList.insert(address); @@ -2864,7 +2864,7 @@ void GridSessionHandshake::SetUserData(const void* data, size_t dataSize) //========================================================================= // SetSessionId //========================================================================= -void GridSessionHandshake::SetSessionId(string sessionId) +void GridSessionHandshake::SetSessionId(AZStd::string sessionId) { AZStd::lock_guard l(m_dataLock); m_sessionId = sessionId; diff --git a/Code/Framework/GridMate/GridMate/Session/Session.h b/Code/Framework/GridMate/GridMate/Session/Session.h index 03556756ba..5080570373 100644 --- a/Code/Framework/GridMate/GridMate/Session/Session.h +++ b/Code/Framework/GridMate/GridMate/Session/Session.h @@ -39,8 +39,8 @@ namespace GridMate struct MemberID { virtual ~MemberID() {} - virtual string ToString() const = 0; - virtual string ToAddress() const = 0; + virtual AZStd::string ToString() const = 0; + virtual AZStd::string ToAddress() const = 0; virtual MemberIDCompact Compact() const = 0; virtual bool IsValid() const = 0; @@ -50,7 +50,7 @@ namespace GridMate AZ_FORCE_INLINE bool operator!=(const MemberIDCompact& rhs) const { return Compact() != rhs; } }; - typedef string SessionID; + typedef AZStd::string SessionID; struct SearchInfo; @@ -87,8 +87,8 @@ namespace GridMate void SetValue(float* values, size_t numElements); void SetValue(double* values, size_t numElements); - string m_id; - string m_value; + AZStd::string m_id; + AZStd::string m_value; AZ::u8 m_type; AZ_FORCE_INLINE bool operator==(const GridSessionParam& rhs) const { return m_type == rhs.m_type && m_id == rhs.m_id && m_value == rhs.m_value; } @@ -303,7 +303,7 @@ namespace GridMate virtual const PlayerId* GetPlayerId() const = 0; NatType GetNatType() const; - string GetName() const; + AZStd::string GetName() const; GridSession* GetSession() const { return m_session; } @@ -353,7 +353,7 @@ namespace GridMate //@{ Platform information AZ::PlatformID GetPlatformId() const; AZ::u32 GetProcessId() const; - string GetMachineName() const; + AZStd::string GetMachineName() const; //@} protected: @@ -568,7 +568,7 @@ namespace GridMate Internal::GridSessionHandshake* m_handshake; typedef unordered_set ConnectionIDSet; ConnectionIDSet m_connections; - string m_hostAddress; + AZStd::string m_hostAddress; bool m_isShutdown; GridMember* m_myMember; ///< Created with the session and bound when the server replica arrives. @@ -923,14 +923,14 @@ namespace GridMate DataSet m_numConnections; DataSet m_natType; - DataSet m_name; + DataSet m_name; DataSet m_memberId; DataSet m_newHostVote; ///< Used when in host migration, to cast machine's vote. MuteDataSetType m_muteList; ///< List of all players we have muted. // Platform and application informational data DataSet > m_platformId; - DataSet m_machineName; + DataSet m_machineName; DataSet m_processId; DataSet m_isInvited; }; diff --git a/Code/Framework/GridMate/GridMate/String/StringUtils.h b/Code/Framework/GridMate/GridMate/String/StringUtils.h deleted file mode 100644 index 6f1ca89b0b..0000000000 --- a/Code/Framework/GridMate/GridMate/String/StringUtils.h +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ -#pragma once - -#include diff --git a/Code/Framework/GridMate/GridMate/String/string.h b/Code/Framework/GridMate/GridMate/String/string.h deleted file mode 100644 index 779f5034c5..0000000000 --- a/Code/Framework/GridMate/GridMate/String/string.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ -#ifndef GM_CONTAINERS_STRING_H -#define GM_CONTAINERS_STRING_H - -#include -#include -#include // for getting from string->wstring and backwards - -namespace GridMate -{ - /** - * All libs should use specialized allocators - */ - typedef AZStd::basic_string, SysContAlloc > string; - typedef AZStd::basic_string, SysContAlloc > wstring; - - typedef AZStd::basic_string, GridMateStdAlloc > gridmate_string; - typedef AZStd::basic_string, GridMateStdAlloc > gridmate_wstring; -} -#endif // GM_CONTAINERS_STRING_H diff --git a/Code/Framework/GridMate/GridMate/VoiceChat/VoiceChatServiceBus.h b/Code/Framework/GridMate/GridMate/VoiceChat/VoiceChatServiceBus.h index 98fcd48b85..b5c09a411a 100644 --- a/Code/Framework/GridMate/GridMate/VoiceChat/VoiceChatServiceBus.h +++ b/Code/Framework/GridMate/GridMate/VoiceChat/VoiceChatServiceBus.h @@ -10,7 +10,6 @@ #include #include -#include namespace GridMate { diff --git a/Code/Framework/GridMate/GridMate/gridmate_files.cmake b/Code/Framework/GridMate/GridMate/gridmate_files.cmake index 8c94fe80ad..e318a8adcd 100644 --- a/Code/Framework/GridMate/GridMate/gridmate_files.cmake +++ b/Code/Framework/GridMate/GridMate/gridmate_files.cmake @@ -120,6 +120,5 @@ set(FILES Session/Session.cpp Session/Session.h Session/SessionServiceBus.h - String/string.h VoiceChat/VoiceChatServiceBus.h ) diff --git a/Code/Framework/GridMate/Platform/Android/GridMate/Session/LANSession_Android.cpp b/Code/Framework/GridMate/Platform/Android/GridMate/Session/LANSession_Android.cpp index e70e839d42..05fb56dfc1 100644 --- a/Code/Framework/GridMate/Platform/Android/GridMate/Session/LANSession_Android.cpp +++ b/Code/Framework/GridMate/Platform/Android/GridMate/Session/LANSession_Android.cpp @@ -6,19 +6,18 @@ * */ -#include #include namespace GridMate { namespace Platform { - void AssignExtendedName(GridMate::string& extendedName) + void AssignExtendedName(AZStd::string& extendedName) { char hostName[64]; gethostname(hostName, AZ_ARRAY_SIZE(hostName)); - extendedName = GridMate::string::format("%s", hostName); + extendedName = AZStd::string::format("%s", hostName); } } } diff --git a/Code/Framework/GridMate/Platform/Common/UnixLike/GridMate/Carrier/Utils_UnixLike.cpp b/Code/Framework/GridMate/Platform/Common/UnixLike/GridMate/Carrier/Utils_UnixLike.cpp index ea824e7564..7d04ff640b 100644 --- a/Code/Framework/GridMate/Platform/Common/UnixLike/GridMate/Carrier/Utils_UnixLike.cpp +++ b/Code/Framework/GridMate/Platform/Common/UnixLike/GridMate/Carrier/Utils_UnixLike.cpp @@ -18,9 +18,9 @@ namespace GridMate { - string Utils::GetMachineAddress(int familyType) + AZStd::string Utils::GetMachineAddress(int familyType) { - string machineName; + AZStd::string machineName; struct ifaddrs* ifAddrStruct = nullptr; struct ifaddrs* ifa = nullptr; diff --git a/Code/Framework/GridMate/Platform/Common/WinAPI/GridMate/Carrier/Utils_WinAPI.cpp b/Code/Framework/GridMate/Platform/Common/WinAPI/GridMate/Carrier/Utils_WinAPI.cpp index dd9b737180..095f8ba6c7 100644 --- a/Code/Framework/GridMate/Platform/Common/WinAPI/GridMate/Carrier/Utils_WinAPI.cpp +++ b/Code/Framework/GridMate/Platform/Common/WinAPI/GridMate/Carrier/Utils_WinAPI.cpp @@ -16,9 +16,9 @@ namespace GridMate { - string Utils::GetMachineAddress(int familyType) + AZStd::string Utils::GetMachineAddress(int familyType) { - string machineName; + AZStd::string machineName; char name[MAX_PATH]; int result = gethostname(name, sizeof(name)); AZ_Error("GridMate", result == 0, "Failed in gethostname with result=%d, WSAGetLastError=%d!", result, WSAGetLastError()); diff --git a/Code/Framework/GridMate/Platform/Linux/GridMate/Session/LANSession_Linux.cpp b/Code/Framework/GridMate/Platform/Linux/GridMate/Session/LANSession_Linux.cpp index e70e839d42..05fb56dfc1 100644 --- a/Code/Framework/GridMate/Platform/Linux/GridMate/Session/LANSession_Linux.cpp +++ b/Code/Framework/GridMate/Platform/Linux/GridMate/Session/LANSession_Linux.cpp @@ -6,19 +6,18 @@ * */ -#include #include namespace GridMate { namespace Platform { - void AssignExtendedName(GridMate::string& extendedName) + void AssignExtendedName(AZStd::string& extendedName) { char hostName[64]; gethostname(hostName, AZ_ARRAY_SIZE(hostName)); - extendedName = GridMate::string::format("%s", hostName); + extendedName = AZStd::string::format("%s", hostName); } } } diff --git a/Code/Framework/GridMate/Platform/Linux/GridMate/String/StringUtils_Platform.h b/Code/Framework/GridMate/Platform/Linux/GridMate/String/StringUtils_Platform.h deleted file mode 100644 index 03320d1dd8..0000000000 --- a/Code/Framework/GridMate/Platform/Linux/GridMate/String/StringUtils_Platform.h +++ /dev/null @@ -1,8 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ -#pragma once diff --git a/Code/Framework/GridMate/Platform/Mac/GridMate/Session/LANSession_Mac.cpp b/Code/Framework/GridMate/Platform/Mac/GridMate/Session/LANSession_Mac.cpp index e70e839d42..05fb56dfc1 100644 --- a/Code/Framework/GridMate/Platform/Mac/GridMate/Session/LANSession_Mac.cpp +++ b/Code/Framework/GridMate/Platform/Mac/GridMate/Session/LANSession_Mac.cpp @@ -6,19 +6,18 @@ * */ -#include #include namespace GridMate { namespace Platform { - void AssignExtendedName(GridMate::string& extendedName) + void AssignExtendedName(AZStd::string& extendedName) { char hostName[64]; gethostname(hostName, AZ_ARRAY_SIZE(hostName)); - extendedName = GridMate::string::format("%s", hostName); + extendedName = AZStd::string::format("%s", hostName); } } } diff --git a/Code/Framework/GridMate/Platform/Windows/GridMate/Session/LANSession_Windows.cpp b/Code/Framework/GridMate/Platform/Windows/GridMate/Session/LANSession_Windows.cpp index 59a1c65781..8925746a79 100644 --- a/Code/Framework/GridMate/Platform/Windows/GridMate/Session/LANSession_Windows.cpp +++ b/Code/Framework/GridMate/Platform/Windows/GridMate/Session/LANSession_Windows.cpp @@ -6,15 +6,15 @@ * */ -#include #include #include +#include namespace GridMate { namespace Platform { - void AssignExtendedName(GridMate::string& extendedName) + void AssignExtendedName(AZStd::string& extendedName) { char hostName[64]; gethostname(hostName, AZ_ARRAY_SIZE(hostName)); @@ -31,7 +31,7 @@ namespace GridMate azsnprintf(procName, AZ_ARRAY_SIZE(procName), "Unknown"); } - extendedName = GridMate::string::format("%s::%s", hostName, procName); + extendedName = AZStd::string::format("%s::%s", hostName, procName); } } } diff --git a/Code/Framework/GridMate/Platform/iOS/GridMate/Session/LANSession_iOS.cpp b/Code/Framework/GridMate/Platform/iOS/GridMate/Session/LANSession_iOS.cpp index e70e839d42..05fb56dfc1 100644 --- a/Code/Framework/GridMate/Platform/iOS/GridMate/Session/LANSession_iOS.cpp +++ b/Code/Framework/GridMate/Platform/iOS/GridMate/Session/LANSession_iOS.cpp @@ -6,19 +6,18 @@ * */ -#include #include namespace GridMate { namespace Platform { - void AssignExtendedName(GridMate::string& extendedName) + void AssignExtendedName(AZStd::string& extendedName) { char hostName[64]; gethostname(hostName, AZ_ARRAY_SIZE(hostName)); - extendedName = GridMate::string::format("%s", hostName); + extendedName = AZStd::string::format("%s", hostName); } } } diff --git a/Code/Framework/GridMate/Tests/Carrier.cpp b/Code/Framework/GridMate/Tests/Carrier.cpp index 45cb16dbb2..8d3ec4eef6 100644 --- a/Code/Framework/GridMate/Tests/Carrier.cpp +++ b/Code/Framework/GridMate/Tests/Carrier.cpp @@ -193,7 +193,7 @@ namespace UnitTest CarrierCallbacksHandler clientCB, serverCB; TestCarrierDesc serverCarrierDesc, clientCarrierDesc; - string str("Hello this is a carrier test!"); + AZStd::string str("Hello this is a carrier test!"); const char* targetAddress = "127.0.0.1"; @@ -377,7 +377,7 @@ namespace UnitTest CarrierCallbacksHandler clientCB, serverCB; TestCarrierDesc serverCarrierDesc, clientCarrierDesc; - string str("Hello this is a carrier test!"); + AZStd::string str("Hello this is a carrier test!"); clientCarrierDesc.m_driver = SocketProvider::CreateDriverForJoin(); serverCarrierDesc.m_driver = SocketProvider::CreateDriverForHost(); @@ -469,7 +469,7 @@ namespace UnitTest CarrierCallbacksHandler clientCB, serverCB; TestCarrierDesc serverCarrierDesc, clientCarrierDesc; - string str("Hello this is a carrier stress test!"); + AZStd::string str("Hello this is a carrier stress test!"); clientCarrierDesc.m_enableDisconnectDetection = false; serverCarrierDesc.m_enableDisconnectDetection = false; @@ -1401,7 +1401,7 @@ namespace UnitTest CarrierCallbacksHandler clientCB, serverCB; CarrierDesc serverCarrierDesc, clientCarrierDesc; - string str("Hello this is a carrier test!"); + AZStd::string str("Hello this is a carrier test!"); const char* targetAddress = "127.0.0.1"; diff --git a/Code/Framework/GridMate/Tests/CarrierStreamSocketDriverTests.cpp b/Code/Framework/GridMate/Tests/CarrierStreamSocketDriverTests.cpp index aac15562df..6af6a6ab87 100644 --- a/Code/Framework/GridMate/Tests/CarrierStreamSocketDriverTests.cpp +++ b/Code/Framework/GridMate/Tests/CarrierStreamSocketDriverTests.cpp @@ -188,7 +188,7 @@ namespace UnitTest CarrierStreamCallbacksHandler clientCB, serverCB; TestCarrierDesc serverCarrierDesc, clientCarrierDesc; - string str("Hello this is a carrier test!"); + AZStd::string str("Hello this is a carrier test!"); const char* targetAddress = "127.0.0.1"; @@ -374,7 +374,7 @@ namespace UnitTest CarrierStreamCallbacksHandler clientCB, serverCB; TestCarrierDesc serverCarrierDesc, clientCarrierDesc; - string str("Hello this is a carrier test!"); + AZStd::string str("Hello this is a carrier test!"); clientCarrierDesc.m_driver = CreateDriverForJoin(clientCarrierDesc); serverCarrierDesc.m_driver = CreateDriverForHost(serverCarrierDesc); @@ -475,7 +475,7 @@ namespace UnitTest CarrierStreamCallbacksHandler clientCB, serverCB; UnitTest::TestCarrierDesc serverCarrierDesc, clientCarrierDesc; - string str("Hello this is a carrier stress test!"); + AZStd::string str("Hello this is a carrier stress test!"); clientCarrierDesc.m_enableDisconnectDetection = /*false*/ true; serverCarrierDesc.m_enableDisconnectDetection = /*false*/ true; diff --git a/Code/Framework/GridMate/Tests/Replica.cpp b/Code/Framework/GridMate/Tests/Replica.cpp index 0b8fab10ce..83a3a1f5a1 100644 --- a/Code/Framework/GridMate/Tests/Replica.cpp +++ b/Code/Framework/GridMate/Tests/Replica.cpp @@ -3687,7 +3687,7 @@ public: void Touch() { - string randomStr; + AZStd::string randomStr; for (unsigned i = 0; i < k_strSize; ++i) { randomStr += 'a' + (rand() % 26); @@ -3698,7 +3698,7 @@ public: bool IsReplicaMigratable() override { return false; } static const unsigned k_strSize = 64; - DataSet m_value; + DataSet m_value; }; void run() diff --git a/Code/Framework/GridMate/Tests/Serialize.cpp b/Code/Framework/GridMate/Tests/Serialize.cpp index 4c74e9526a..9a681dc018 100644 --- a/Code/Framework/GridMate/Tests/Serialize.cpp +++ b/Code/Framework/GridMate/Tests/Serialize.cpp @@ -471,12 +471,12 @@ namespace UnitTest // ------------------------------------ // String { - string s = "hello"; + AZStd::string s = "hello"; wb.Write(s); AZ_TEST_ASSERT(wb.Size() == s.length() + sizeof(AZ::u16)); - string rs; + AZStd::string rs; rb = ReadBuffer(wb.GetEndianType(), wb.Get(), wb.Size()); rb.Read(rs); AZ_TEST_ASSERT(rs == s); diff --git a/Code/Framework/GridMate/Tests/TestProfiler.cpp b/Code/Framework/GridMate/Tests/TestProfiler.cpp index 9f79d5a9fe..26e9312ecf 100644 --- a/Code/Framework/GridMate/Tests/TestProfiler.cpp +++ b/Code/Framework/GridMate/Tests/TestProfiler.cpp @@ -34,15 +34,15 @@ static bool CollectPerformanceCounters(const AZ::Debug::ProfilerRegister& reg, c return true; } -static string FormatString(const AZStd::string& pre, const AZStd::string& name, const AZStd::string& post, AZ::u64 time, AZ::u64 calls) +static AZStd::string FormatString(const AZStd::string& pre, const AZStd::string& name, const AZStd::string& post, AZ::u64 time, AZ::u64 calls) { - string units = "us"; + AZStd::string units = "us"; if (AZ::u64 divtime = time / 1000) { time = divtime; units = "ms"; } - return string::format("%s%s %s %10llu%s (%llu calls)\n", pre.c_str(), name.c_str(), post.c_str(), time, units.c_str(), calls); + return AZStd::string::format("%s%s %s %10llu%s (%llu calls)\n", pre.c_str(), name.c_str(), post.c_str(), time, units.c_str(), calls); } struct TotalSortContainer @@ -56,28 +56,28 @@ struct TotalSortContainer { if (m_self && level >= 0) { - string levelIndent; + AZStd::string levelIndent; for (AZ::s32 i = 0; i < level; i++) { levelIndent += (i == level - 1) ? "+---" : "| "; } - string name = m_self->m_name ? m_self->m_name : m_self->m_function; - string outputTotal = FormatString(levelIndent, name, " Total:", m_self->m_timeData.m_time, m_self->m_timeData.m_calls); + AZStd::string name = m_self->m_name ? m_self->m_name : m_self->m_function; + AZStd::string outputTotal = FormatString(levelIndent, name, " Total:", m_self->m_timeData.m_time, m_self->m_timeData.m_calls); AZ_Printf(systemId, outputTotal.c_str()); if (m_self->m_timeData.m_childrenTime || m_self->m_timeData.m_childrenCalls) { - string childIndent = levelIndent; + AZStd::string childIndent = levelIndent; for (auto i = name.begin(); i != name.end(); ++i) { childIndent += " "; } childIndent[level * 4] = '|'; - string outputChild = FormatString(childIndent, "", "Child:", m_self->m_timeData.m_childrenTime, m_self->m_timeData.m_childrenCalls); + AZStd::string outputChild = FormatString(childIndent, "", "Child:", m_self->m_timeData.m_childrenTime, m_self->m_timeData.m_childrenCalls); AZ_Printf(systemId, outputChild.c_str()); - string outputSelf = FormatString(childIndent, "", "Self :", m_self->m_timeData.m_time - m_self->m_timeData.m_childrenTime, m_self->m_timeData.m_calls); + AZStd::string outputSelf = FormatString(childIndent, "", "Self :", m_self->m_timeData.m_time - m_self->m_timeData.m_childrenTime, m_self->m_timeData.m_calls); AZ_Printf(systemId, outputSelf.c_str()); } } @@ -237,7 +237,7 @@ void TestProfiler::PrintProfilingSelf(const char* systemId) AZ_Printf(systemId, "Profiling timers by exclusive execution time:\n"); for (auto profiler : selfSorted) { - string str = FormatString("", profiler->m_name ? profiler->m_name : profiler->m_function, "Self Time:", + AZStd::string str = FormatString("", profiler->m_name ? profiler->m_name : profiler->m_function, "Self Time:", profiler->m_timeData.m_time - profiler->m_timeData.m_childrenTime, profiler->m_timeData.m_calls); AZ_Printf(systemId, str.c_str()); } From e28602dbbb4a09a389f0519ed680fc051a5d59cb Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Tue, 3 Aug 2021 17:59:35 -0700 Subject: [PATCH 095/803] linux fixes Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Editor/Export/ExportManager.cpp | 6 +- Code/Editor/TrackView/CommentNodeAnimator.cpp | 2 +- .../TrackView/TrackViewDopeSheetBase.cpp | 6 +- Code/Editor/TrackView/TrackViewNodes.cpp | 2 +- Code/Editor/Util/FileUtil.cpp | 9 +- Code/Editor/Util/PathUtil.cpp | 13 +-- Code/Editor/Util/PathUtil.h | 4 +- Code/Editor/Util/StringHelpers.cpp | 2 +- Code/Editor/Util/StringHelpers.h | 3 + Code/Framework/AzCore/AzCore/base.h | 108 +++++++++--------- .../AzCore/AzCore/std/string/conversions.h | 34 +----- .../WinAPI/AzCore/Utils/Utils_WinAPI.cpp | 7 +- .../AzFramework/IO/LocalFileIO_WinAPI.cpp | 6 +- Code/Legacy/CryCommon/CryFile.h | 8 +- Code/Legacy/CryCommon/CryListenerSet.h | 2 +- Code/Legacy/CryCommon/CryName.h | 8 +- Code/Legacy/CryCommon/CryPath.h | 2 +- Code/Legacy/CryCommon/ISerialize.h | 4 +- Code/Legacy/CryCommon/Linux_Win32Wrapper.h | 4 +- Code/Legacy/CryCommon/WinBase.cpp | 57 ++++----- Code/Legacy/CrySystem/DebugCallStack.cpp | 22 ++-- Code/Legacy/CrySystem/IDebugCallStack.cpp | 2 +- Code/Legacy/CrySystem/IDebugCallStack.h | 6 +- .../CrySystem/LevelSystem/LevelSystem.cpp | 2 +- .../CrySystem/LocalizedStringManager.cpp | 4 +- Code/Legacy/CrySystem/Log.cpp | 8 +- Code/Legacy/CrySystem/SystemWin32.cpp | 2 +- Code/Legacy/CrySystem/XConsole.cpp | 16 +-- Code/Legacy/CrySystem/XML/XMLBinaryReader.cpp | 2 +- Code/Legacy/CrySystem/XML/XMLBinaryWriter.cpp | 2 +- Code/Tools/GridHub/GridHub/gridhub.cpp | 4 +- Code/Tools/GridHub/GridHub/gridhub.hxx | 2 +- .../Process/TestImpactWin32_Process.cpp | 7 +- .../Animation/UiAnimViewDopeSheetBase.cpp | 6 +- .../UiClipboard_Unimplemented.cpp | 7 +- .../Code/Source/Cinematics/CaptureTrack.cpp | 2 +- .../Code/Source/Cinematics/CommentTrack.cpp | 2 +- .../Source/Cinematics/CompoundSplineTrack.cpp | 10 +- .../Code/Source/Cinematics/EventTrack.cpp | 6 +- .../Code/Source/Cinematics/SceneNode.cpp | 4 +- .../Source/Cinematics/ScreenFaderTrack.cpp | 2 +- .../Source/Cinematics/TrackEventTrack.cpp | 6 +- 42 files changed, 186 insertions(+), 225 deletions(-) diff --git a/Code/Editor/Export/ExportManager.cpp b/Code/Editor/Export/ExportManager.cpp index 5ba250c960..981e38c029 100644 --- a/Code/Editor/Export/ExportManager.cpp +++ b/Code/Editor/Export/ExportManager.cpp @@ -46,7 +46,7 @@ namespace SEfResTexture* pTex = pRes->GetTextureResource(nSlot); if (pTex) { - azstrcat(outName, Path::GamePathToFullPath(pTex->m_Name.c_str()).toUtf8().data()); + azstrcat(outName, AZ_ARRAY_SIZE(outName), Path::GamePathToFullPath(pTex->m_Name.c_str()).toUtf8().data()); } } @@ -88,7 +88,7 @@ Export::CObject::CObject(const char* pName) nParent = -1; - azstrcpy(name, pName); + azstrcpy(name, AZ_ARRAY_SIZE(name), pName); materialName[0] = '\0'; @@ -102,7 +102,7 @@ Export::CObject::CObject(const char* pName) void Export::CObject::SetMaterialName(const char* pName) { - azstrcpy(materialName, pName); + azstrcpy(materialName, AZ_ARRAY_SIZE(materialName), pName); } diff --git a/Code/Editor/TrackView/CommentNodeAnimator.cpp b/Code/Editor/TrackView/CommentNodeAnimator.cpp index 579bba00ef..cc3e7da972 100644 --- a/Code/Editor/TrackView/CommentNodeAnimator.cpp +++ b/Code/Editor/TrackView/CommentNodeAnimator.cpp @@ -92,7 +92,7 @@ void CCommentNodeAnimator::AnimateCommentTextTrack(CTrackViewTrack* pTrack, cons if (commentKey.m_duration > 0 && ac.time < keyHandle.GetTime() + commentKey.m_duration) { m_commentContext.m_strComment = commentKey.m_strComment; - azstrcpy(m_commentContext.m_strFont, commentKey.m_strFont.c_str()); + azstrcpy(m_commentContext.m_strFont, AZ_ARRAY_SIZE(m_commentContext.m_strFont), commentKey.m_strFont.c_str()); m_commentContext.m_color = commentKey.m_color; m_commentContext.m_align = commentKey.m_align; m_commentContext.m_size = commentKey.m_size; diff --git a/Code/Editor/TrackView/TrackViewDopeSheetBase.cpp b/Code/Editor/TrackView/TrackViewDopeSheetBase.cpp index f66bb19bf3..bf2e39e64d 100644 --- a/Code/Editor/TrackView/TrackViewDopeSheetBase.cpp +++ b/Code/Editor/TrackView/TrackViewDopeSheetBase.cpp @@ -2808,10 +2808,10 @@ void CTrackViewDopeSheetBase::DrawKeys(CTrackViewTrack* pTrack, QPainter* painte } else { - azstrcpy(keydesc, "{"); + azstrcpy(keydesc, AZ_ARRAY_SIZE(keydesc), "{"); } - azstrcat(keydesc, pDescription); - azstrcat(keydesc, "}"); + azstrcat(keydesc, AZ_ARRAY_SIZE(keydesc), pDescription); + azstrcat(keydesc, AZ_ARRAY_SIZE(keydesc), "}"); // Draw key description text. // Find next key. const QRect textRect(QPoint(x + 10, rect.top()), QPoint(x1, rect.bottom())); diff --git a/Code/Editor/TrackView/TrackViewNodes.cpp b/Code/Editor/TrackView/TrackViewNodes.cpp index 000bdf21d0..9652de51ef 100644 --- a/Code/Editor/TrackView/TrackViewNodes.cpp +++ b/Code/Editor/TrackView/TrackViewNodes.cpp @@ -2516,7 +2516,7 @@ int CTrackViewNodesCtrl::GetMatNameAndSubMtlIndexFromName(QString& matName, cons if (const char* pCh = strstr(nodeName, ".[")) { char matPath[MAX_PATH]; - azstrncpy(matPath, nodeName, (size_t)(pCh - nodeName)); + azstrncpy(matPath, AZ_ARRAY_SIZE(matPath), nodeName, (size_t)(pCh - nodeName)); matName = matPath; pCh += 2; if ((*pCh) != 0) diff --git a/Code/Editor/Util/FileUtil.cpp b/Code/Editor/Util/FileUtil.cpp index f5535f5590..3157a04bd8 100644 --- a/Code/Editor/Util/FileUtil.cpp +++ b/Code/Editor/Util/FileUtil.cpp @@ -2217,15 +2217,14 @@ uint32 CFileUtil::GetAttributes(const char* filename, bool bUseSourceControl /*= return SCC_FILE_ATTRIBUTE_READONLY | SCC_FILE_ATTRIBUTE_INPAK; } - AZStd::wstring fileW; - AZStd::to_wstring(fileW, file.GetAdjustedFilename()); - DWORD dwAttrib = ::GetFileAttributesW(fileW.c_str()); - if (dwAttrib == INVALID_FILE_ATTRIBUTES) + + const char* adjustedFile = file.GetAdjustedFilename(); + if (!AZ::IO::SystemFile::Exists(adjustedFile)) { return SCC_FILE_ATTRIBUTE_INVALID; } - if (dwAttrib & FILE_ATTRIBUTE_READONLY) + if (!AZ::IO::SystemFile::IsWritable(adjustedFile)) { return SCC_FILE_ATTRIBUTE_NORMAL | SCC_FILE_ATTRIBUTE_READONLY; } diff --git a/Code/Editor/Util/PathUtil.cpp b/Code/Editor/Util/PathUtil.cpp index e91d85e4d2..2f99f42188 100644 --- a/Code/Editor/Util/PathUtil.cpp +++ b/Code/Editor/Util/PathUtil.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include @@ -203,16 +204,7 @@ namespace Path bool IsFolder(const char* pPath) { - AZStd::wstring pPathW; - AZStd::to_wstring(pPathW, pPath); - DWORD attrs = GetFileAttributes(pPathW.c_str()); - - if (attrs == FILE_ATTRIBUTE_DIRECTORY) - { - return true; - } - - return false; + return AZ::IO::FileIOBase::GetInstance()->IsDirectory(pPath); } ////////////////////////////////////////////////////////////////////////// @@ -256,7 +248,6 @@ namespace Path static AZStd::string s_currentModName; // query the editor root. The bus exists in case we want tools to be able to override this. - if (s_currentModName.empty()) { return GetGameAssetsFolder(); diff --git a/Code/Editor/Util/PathUtil.h b/Code/Editor/Util/PathUtil.h index 30887e698b..4ea30d1f74 100644 --- a/Code/Editor/Util/PathUtil.h +++ b/Code/Editor/Util/PathUtil.h @@ -106,7 +106,7 @@ namespace Path path = path_buffer; _makepath_s(path_buffer, AZ_ARRAY_SIZE(path_buffer), 0, 0, fname, ext); #else - _splitpath(filepath, drive, dir, fname, ext); + _splitpath(filepath.c_str(), drive, dir, fname, ext); _makepath(path_buffer, drive, dir, 0, 0); path = path_buffer; _makepath(path_buffer, 0, 0, fname, ext); @@ -148,7 +148,7 @@ namespace Path _splitpath_s(filepath.c_str(), drive, AZ_ARRAY_SIZE(drive), dir, AZ_ARRAY_SIZE(dir), fname, AZ_ARRAY_SIZE(fname), ext, AZ_ARRAY_SIZE(ext)); _makepath_s(path_buffer, AZ_ARRAY_SIZE(path_buffer), drive, dir, 0, 0); #else - _splitpath(filepath, drive, dir, fname, ext); + _splitpath(filepath.c_str(), drive, dir, fname, ext); _makepath(path_buffer, drive, dir, 0, 0); #endif path = path_buffer; diff --git a/Code/Editor/Util/StringHelpers.cpp b/Code/Editor/Util/StringHelpers.cpp index a1e2b4ae08..6c819270bd 100644 --- a/Code/Editor/Util/StringHelpers.cpp +++ b/Code/Editor/Util/StringHelpers.cpp @@ -15,7 +15,7 @@ int StringHelpers::CompareIgnoreCase(const AZStd::string& str0, const AZStd::string& str1) { const size_t minLength = Util::getMin(str0.length(), str1.length()); - const int result = azmemicmp(str0.c_str(), str1.c_str(), minLength); + const int result = azstrnicmp(str0.c_str(), str1.c_str(), minLength); if (result) { return result; diff --git a/Code/Editor/Util/StringHelpers.h b/Code/Editor/Util/StringHelpers.h index 0e393e92dd..b5c84d7fe3 100644 --- a/Code/Editor/Util/StringHelpers.h +++ b/Code/Editor/Util/StringHelpers.h @@ -11,6 +11,9 @@ #define CRYINCLUDE_CRYCOMMONTOOLS_STRINGHELPERS_H #pragma once +#include +#include + namespace StringHelpers { // compares two strings to see if they are the same or different, case is ignored diff --git a/Code/Framework/AzCore/AzCore/base.h b/Code/Framework/AzCore/AzCore/base.h index 252133e781..00fdbf515e 100644 --- a/Code/Framework/AzCore/AzCore/base.h +++ b/Code/Framework/AzCore/AzCore/base.h @@ -51,74 +51,72 @@ # define azvscprintf(_format, _va_list) _vscprintf(_format, _va_list) # define azscwprintf _scwprintf # define azvscwprintf _vscwprintf -# define azstrtok(_buffer, _size, _delim, _context) strtok_s(_buffer, _delim, _context) -# define azstrcat strcat_s -# define azstrncat strncat_s -# define strtoll _strtoi64 -# define strtoull _strtoui64 -# define azsscanf sscanf_s -# define azstrcpy strcpy_s -# define azstrncpy strncpy_s -# define azstricmp _stricmp -# define azstrnicmp _strnicmp -# define azisfinite _finite -# define azltoa _ltoa_s -# define azitoa _itoa_s -# define azui64toa _ui64toa_s -# define azswscanf swscanf_s -# define azwcsicmp _wcsicmp -# define azwcsnicmp _wcsnicmp -# define azmemicmp _memicmp +# define azstrtok(_buffer, _size, _delim, _context) strtok_s(_buffer, _delim, _context) +# define azstrcat(_dest, _destSize, _src) strcat_s(_dest, _destSize, _src) +# define azstrncat(_dest, _destSize, _src, _count) strncat_s(_dest, _destSize, _src, _count) +# define strtoll _strtoi64 +# define strtoull _strtoui64 +# define azsscanf sscanf_s +# define azstrcpy(_dest, _destSize, _src) strcpy_s(_dest, _destSize, _src) +# define azstrncpy(_dest, _destSize, _src, _count) strncpy_s(_dest, _destSize, _src, _count) +# define azstricmp _stricmp +# define azstrnicmp _strnicmp +# define azisfinite _finite +# define azltoa _ltoa_s +# define azitoa _itoa_s +# define azui64toa _ui64toa_s +# define azswscanf swscanf_s +# define azwcsicmp _wcsicmp +# define azwcsnicmp _wcsnicmp // note: for cross-platform compatibility, do not use the return value of azfopen. On Windows, it's an errno_t and 0 indicates success. On other platforms, the return value is a FILE*, and a 0 value indicates failure. -# define azfopen fopen_s +# define azfopen(_fp, _filename, _attrib) fopen_s(_fp, _filename, _attrib) # define azfscanf fscanf_s -# define azsprintf(_buffer, ...) sprintf_s(_buffer, AZ_ARRAY_SIZE(_buffer), __VA_ARGS__) -# define azstrlwr _strlwr_s -# define azvsprintf vsprintf_s -# define azwcscpy wcscpy_s -# define azstrtime _strtime_s -# define azstrdate _strdate_s -# define azlocaltime(time, result) localtime_s(result, time) +# define azsprintf(_buffer, ...) sprintf_s(_buffer, AZ_ARRAY_SIZE(_buffer), __VA_ARGS__) +# define azstrlwr _strlwr_s +# define azvsprintf vsprintf_s +# define azwcscpy wcscpy_s +# define azstrtime _strtime_s +# define azstrdate _strdate_s +# define azlocaltime(time, result) localtime_s(result, time) #else -# define azsnprintf snprintf -# define azvsnprintf vsnprintf +# define azsnprintf snprintf +# define azvsnprintf vsnprintf # if AZ_TRAIT_COMPILER_DEFINE_AZSWNPRINTF_AS_SWPRINTF -# define azsnwprintf swprintf -# define azvsnwprintf vswprintf +# define azsnwprintf swprintf +# define azvsnwprintf vswprintf # else -# define azsnwprintf snwprintf -# define azvsnwprintf vsnwprintf +# define azsnwprintf snwprintf +# define azvsnwprintf vsnwprintf # endif -# define azscprintf(...) azsnprintf(nullptr, static_cast(0), __VA_ARGS__); -# define azvscprintf(_format, _va_list) azvsnprintf(nullptr, static_cast(0), _format, _va_list); -# define azscwprintf(...) azsnwprintf(nullptr, static_cast(0), __VA_ARGS__); -# define azvscwprintf(_format, _va_list) azvsnwprintf(nullptr, static_cast(0), _format, _va_list); -# define azstrtok(_buffer, _size, _delim, _context) strtok(_buffer, _delim) -# define azstrcat(_dest, _destSize, _src) strcat(_dest, _src) -# define azstrncat(_dest, _destSize, _src, _count) strncat(_dest, _src, _count) -# define azsscanf sscanf -# define azstrcpy(_dest, _destSize, _src) strcpy(_dest, _src) -# define azstrncpy(_dest, _destSize, _src, _count) strncpy(_dest, _src, _count) -# define azstricmp strcasecmp -# define azstrnicmp strncasecmp +# define azscprintf(...) azsnprintf(nullptr, static_cast(0), __VA_ARGS__); +# define azvscprintf(_format, _va_list) azvsnprintf(nullptr, static_cast(0), _format, _va_list); +# define azscwprintf(...) azsnwprintf(nullptr, static_cast(0), __VA_ARGS__); +# define azvscwprintf(_format, _va_list) azvsnwprintf(nullptr, static_cast(0), _format, _va_list); +# define azstrtok(_buffer, _size, _delim, _context) strtok(_buffer, _delim) +# define azstrcat(_dest, _destSize, _src) strcat(_dest, _src) +# define azstrncat(_dest, _destSize, _src, _count) strncat(_dest, _src, _count) +# define azsscanf sscanf +# define azstrcpy(_dest, _destSize, _src) strcpy(_dest, _src) +# define azstrncpy(_dest, _destSize, _src, _count) strncpy(_dest, _src, _count) +# define azstricmp strcasecmp +# define azstrnicmp strncasecmp # if defined(NDK_REV_MAJOR) && NDK_REV_MAJOR < 16 -# define azisfinite __isfinitef +# define azisfinite __isfinitef # else -# define azisfinite isfinite +# define azisfinite isfinite # endif -# define azltoa(_value, _buffer, _size, _radix) ltoa(_value, _buffer, _radix) -# define azitoa(_value, _buffer, _size, _radix) itoa(_value, _buffer, _radix) -# define azui64toa(_value, _buffer, _size, _radix) _ui64toa(_value, _buffer, _radix) -# define azswscanf swscanf -# define azwcsicmp wcsicmp -# define azwcsnicmp wcsnicmp -# define azmemicmp memicmp +# define azltoa(_value, _buffer, _size, _radix) ltoa(_value, _buffer, _radix) +# define azitoa(_value, _buffer, _size, _radix) itoa(_value, _buffer, _radix) +# define azui64toa(_value, _buffer, _size, _radix) _ui64toa(_value, _buffer, _radix) +# define azswscanf swscanf +# define azwcsicmp wcscasecmp +# define azwcsnicmp wcsnicmp // note: for cross-platform compatibility, do not use the return value of azfopen. On Windows, it's an errno_t and 0 indicates success. On other platforms, the return value is a FILE*, and a 0 value indicates failure. -# define azfopen(_fp, _filename, _attrib) *(_fp) = fopen(_filename, _attrib) -# define azfscanf fscanf +# define azfopen(_fp, _filename, _attrib) *(_fp) = fopen(_filename, _attrib) +# define azfscanf fscanf # define azsprintf sprintf # define azstrlwr(_buffer, _size) strlwr(_buffer) diff --git a/Code/Framework/AzCore/AzCore/std/string/conversions.h b/Code/Framework/AzCore/AzCore/std/string/conversions.h index fcfe82ba5f..91af1029b4 100644 --- a/Code/Framework/AzCore/AzCore/std/string/conversions.h +++ b/Code/Framework/AzCore/AzCore/std/string/conversions.h @@ -30,6 +30,8 @@ namespace AZStd template struct WCharTPlatformConverter { + static_assert(Size == size_t{ 2 } || Size == size_t{ 4 }, "only wchar_t types of size 2 or 4 can be converted to utf8"); + template static inline void to_string(AZStd::basic_string& dest, const wchar_t* first, const wchar_t* last) { @@ -41,12 +43,6 @@ namespace AZStd { Utf8::Unchecked::utf32to8(first, last, AZStd::back_inserter(dest), dest.max_size()); } - else - { - // Workaround to defer static_assert evaluation until this function is invoked by using the template parameter - using StringType = AZStd::basic_string; - static_assert(!AZStd::is_same_v, "only wchar_t types of size 2 or 4 can be converted to utf8"); - } } template @@ -60,12 +56,6 @@ namespace AZStd { Utf8::Unchecked::utf32to8(first, last, AZStd::back_inserter(dest), dest.max_size()); } - else - { - // Workaround to defer static_assert evaluation until this function is invoked by using the template parameter - using StringType = AZStd::basic_string; - static_assert(!AZStd::is_same_v, "only wchar_t types of size 2 or 4 can be converted to utf8"); - } } static inline void to_string(char* dest, size_t destSize, const wchar_t* first, const wchar_t* last) @@ -78,10 +68,6 @@ namespace AZStd { Utf8::Unchecked::utf32to8(first, last, dest, destSize); } - else - { - static_assert(false, "only wchar_t types of size 2 or 4 can be converted to utf8"); - } } template @@ -95,12 +81,6 @@ namespace AZStd { Utf8::Unchecked::utf8to32(first, last, AZStd::back_inserter(dest), dest.max_size()); } - else - { - // Workaround to defer static_assert evaluation until this function is invoked by using the template parameter - using StringType = AZStd::basic_string; - static_assert(!AZStd::is_same_v, "Cannot convert a utf8 string to a wchar_t that isn't size 2 or 4"); - } } template @@ -114,12 +94,6 @@ namespace AZStd { Utf8::Unchecked::utf8to32(first, last, AZStd::back_inserter(dest), dest.max_size()); } - else - { - // Workaround to defer static_assert evaluation until this function is invoked by using the template parameter - using StringType = AZStd::basic_string; - static_assert(!AZStd::is_same_v, "Cannot convert a utf8 string to a wchar_t that isn't size 2 or 4"); - } } static inline void to_wstring(wchar_t* dest, size_t destSize, const char* first, const char* last) @@ -132,10 +106,6 @@ namespace AZStd { Utf8::Unchecked::utf8to32(first, last, dest, destSize); } - else - { - static_assert(false, "Cannot convert a utf8 string to a wchar_t that isn't size 2 or 4"); - } } }; } diff --git a/Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/Utils/Utils_WinAPI.cpp b/Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/Utils/Utils_WinAPI.cpp index c57f2b31f6..a4af19a2a4 100644 --- a/Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/Utils/Utils_WinAPI.cpp +++ b/Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/Utils/Utils_WinAPI.cpp @@ -30,9 +30,8 @@ namespace AZ result.m_pathIncludesFilename = true; // Platform specific get exe path: http://stackoverflow.com/a/1024937 // https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getmodulefilenamea - AZStd::wstring pathBuffer; - pathBuffer.resize(exeStorageSize); - const DWORD pathLen = GetModuleFileName(nullptr, pathBuffer.data(), static_cast(exeStorageSize)); + wchar_t pathBufferW[AZ_MAX_PATH_LEN] = { 0 }; + const DWORD pathLen = GetModuleFileNameW(nullptr, pathBufferW, static_cast(exeStorageSize)); const DWORD errorCode = GetLastError(); if (pathLen == exeStorageSize && errorCode == ERROR_INSUFFICIENT_BUFFER) { @@ -44,7 +43,7 @@ namespace AZ } else { - AZStd::to_string(exeStorageBuffer, exeStorageSize, pathBuffer.c_str()); + AZStd::to_string(exeStorageBuffer, exeStorageSize, pathBufferW); } return result; diff --git a/Code/Framework/AzFramework/Platform/Common/WinAPI/AzFramework/IO/LocalFileIO_WinAPI.cpp b/Code/Framework/AzFramework/Platform/Common/WinAPI/AzFramework/IO/LocalFileIO_WinAPI.cpp index 58afebfb90..61957fced0 100644 --- a/Code/Framework/AzFramework/Platform/Common/WinAPI/AzFramework/IO/LocalFileIO_WinAPI.cpp +++ b/Code/Framework/AzFramework/Platform/Common/WinAPI/AzFramework/IO/LocalFileIO_WinAPI.cpp @@ -20,7 +20,9 @@ namespace AZ char resolvedPath[AZ_MAX_PATH_LEN]; ResolvePath(filePath, resolvedPath, AZ_MAX_PATH_LEN); - DWORD fileAttributes = GetFileAttributesA(resolvedPath); + wchar_t resolvedPathW[AZ_MAX_PATH_LEN]; + AZStd::to_wstring(resolvedPathW, AZ_MAX_PATH_LEN, resolvedPath); + DWORD fileAttributes = GetFileAttributesW(resolvedPathW); if (fileAttributes == INVALID_FILE_ATTRIBUTES) { return false; @@ -174,7 +176,7 @@ namespace AZ bool LocalFileIO::IsAbsolutePath(const char* path) const { - char drive[16]; + char drive[16] = { 0 }; _splitpath_s(path, drive, 16, nullptr, 0, nullptr, 0, nullptr, 0); return strlen(drive) > 0; } diff --git a/Code/Legacy/CryCommon/CryFile.h b/Code/Legacy/CryCommon/CryFile.h index 0888216f9c..0d2dac7c16 100644 --- a/Code/Legacy/CryCommon/CryFile.h +++ b/Code/Legacy/CryCommon/CryFile.h @@ -221,7 +221,7 @@ inline CCryFile::~CCryFile() inline bool CCryFile::Open(const char* filename, const char* mode, int nOpenFlagsEx) { char tempfilename[CRYFILE_MAX_PATH] = ""; - azstrcpy(tempfilename, filename); + azstrcpy(tempfilename, CRYFILE_MAX_PATH, filename); #if !defined (_RELEASE) if (gEnv && gEnv->IsEditor() && gEnv->pConsole) @@ -233,7 +233,7 @@ inline bool CCryFile::Open(const char* filename, const char* mode, int nOpenFlag if (lowercasePaths) { const AZStd::string lowerString = PathUtil::ToLower(tempfilename); - azstrcpy(tempfilename, lowerString.c_str()); + azstrcpy(tempfilename, CRYFILE_MAX_PATH, lowerString.c_str()); } } } @@ -242,7 +242,7 @@ inline bool CCryFile::Open(const char* filename, const char* mode, int nOpenFlag { Close(); } - azstrcpy(m_filename, tempfilename); + azstrcpy(m_filename, CRYFILE_MAX_PATH, tempfilename); if (m_pIArchive) { @@ -429,7 +429,7 @@ inline const char* CCryFile::GetAdjustedFilename() const // Returns standard path otherwise. if (gameUrl != &szAdjustedFile[0]) { - azstrcpy(szAdjustedFile, gameUrl); + azstrcpy(szAdjustedFile, AZ::IO::IArchive::MaxPath, gameUrl); } return szAdjustedFile; } diff --git a/Code/Legacy/CryCommon/CryListenerSet.h b/Code/Legacy/CryCommon/CryListenerSet.h index 6857cf7e5d..e5be89aa9f 100644 --- a/Code/Legacy/CryCommon/CryListenerSet.h +++ b/Code/Legacy/CryCommon/CryListenerSet.h @@ -418,7 +418,7 @@ inline size_t CListenerSet::MemSize() const size += sizeof(typename TAllocatedNameVec::value_type); for (typename TAllocatedNameVec::const_iterator iter(m_allocatedNames.begin()); iter != m_allocatedNames.end(); ++iter) { - size += iter->GetAllocatedMemory(); + size += iter->capacity() * sizeof(char) + sizeof(AZStd::string); } #endif diff --git a/Code/Legacy/CryCommon/CryName.h b/Code/Legacy/CryCommon/CryName.h index 8e62a52517..552391419a 100644 --- a/Code/Legacy/CryCommon/CryName.h +++ b/Code/Legacy/CryCommon/CryName.h @@ -397,11 +397,11 @@ inline bool CCryName::operator>(const CCryName& n) const inline bool operator==(const AZStd::string& s, const CCryName& n) { - return s == n; + return s == n.c_str(); } inline bool operator!=(const AZStd::string& s, const CCryName& n) { - return s != n; + return s != n.c_str(); } inline bool operator==(const char* s, const CCryName& n) @@ -545,11 +545,11 @@ inline bool CCryNameCRC::operator>(const CCryNameCRC& n) const inline bool operator==(const AZStd::string& s, const CCryNameCRC& n) { - return s == n; + return n == s.c_str(); } inline bool operator!=(const AZStd::string& s, const CCryNameCRC& n) { - return s != n; + return n != s.c_str(); } inline bool operator==(const char* s, const CCryNameCRC& n) diff --git a/Code/Legacy/CryCommon/CryPath.h b/Code/Legacy/CryCommon/CryPath.h index e01e7a2e4b..046006f738 100644 --- a/Code/Legacy/CryCommon/CryPath.h +++ b/Code/Legacy/CryCommon/CryPath.h @@ -419,7 +419,7 @@ namespace PathUtil //! Makes a fully specified file path from path and file name. inline stack_string Make(const stack_string& dir, const stack_string& filename, const stack_string& ext) { - AZStd::string path = filename; + AZStd::string path = filename.c_str(); AZ::StringFunc::Path::ReplaceExtension(path, ext.c_str()); path = AddSlash(dir.c_str()) + path; return stack_string(path.c_str()); diff --git a/Code/Legacy/CryCommon/ISerialize.h b/Code/Legacy/CryCommon/ISerialize.h index 84e665850f..d427e222bb 100644 --- a/Code/Legacy/CryCommon/ISerialize.h +++ b/Code/Legacy/CryCommon/ISerialize.h @@ -387,7 +387,7 @@ public: bool ValueChar(const char* name, char* buffer, int len) { - string temp; + AZStd::string temp; if (IsReading()) { Value(name, temp); @@ -400,7 +400,7 @@ public: } else { - temp = string(buffer, buffer + len); + temp = AZStd::string(buffer, buffer + len); Value(name, temp); } return true; diff --git a/Code/Legacy/CryCommon/Linux_Win32Wrapper.h b/Code/Legacy/CryCommon/Linux_Win32Wrapper.h index e47d16d1bc..6507d7c8ee 100644 --- a/Code/Legacy/CryCommon/Linux_Win32Wrapper.h +++ b/Code/Legacy/CryCommon/Linux_Win32Wrapper.h @@ -14,6 +14,8 @@ #include #include #include +#include + /* Memory block identification */ #define _FREE_BLOCK 0 #define _NORMAL_BLOCK 1 @@ -344,7 +346,7 @@ private: char m_DirectoryName[260]; //!< directory name, needed when getting file attributes on the fly char m_ToMatch[260]; //!< pattern to match with DIR* m_Dir; //!< directory handle - std::vector m_Entries; //!< all file entries in the current directories + std::vector m_Entries; //!< all file entries in the current directories public: inline __finddata64_t() diff --git a/Code/Legacy/CryCommon/WinBase.cpp b/Code/Legacy/CryCommon/WinBase.cpp index fe9c539569..74d383b88d 100644 --- a/Code/Legacy/CryCommon/WinBase.cpp +++ b/Code/Legacy/CryCommon/WinBase.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #ifdef APPLE #include @@ -77,8 +78,6 @@ unsigned int g_EnableMultipleAssert = 0;//set to something else than 0 if to ena #include #endif -#include "StringUtils.h" - #if AZ_TRAIT_COMPILER_DEFINE_FS_ERRNO_TYPE typedef int FS_ERRNO_TYPE; #if AZ_TRAIT_COMPILER_DEFINE_FS_STAT_TYPE @@ -349,23 +348,23 @@ void _makepath(char* path, const char* drive, const char* dir, const char* filen } if (dir && dir[0]) { - azstrcat(tmp, dir); + azstrcat(tmp, MAX_PATH, dir); ch = tmp[strlen(tmp) - 1]; if (ch != '/' && ch != '\\') { - azstrcat(tmp, "\\"); + azstrcat(tmp, MAX_PATH, "\\"); } } if (filename && filename[0]) { - azstrcat(tmp, filename); + azstrcat(tmp, MAX_PATH, filename); if (ext && ext[0]) { if (ext[0] != '.') { - azstrcat(tmp, "."); + azstrcat(tmp, MAX_PATH, "."); } - azstrcat(tmp, ext); + azstrcat(tmp, MAX_PATH, ext); } } azstrcpy(path, strlen(tmp) + 1, tmp); @@ -489,9 +488,9 @@ void _splitpath(const char* inpath, char* drv, char* dir, char* fname, char* ext typedef AZStd::fixed_string path_stack_string; const path_stack_string inPath(inpath); - string::size_type s = inPath.rfind('/', inPath.size());//position of last / + AZStd::string::size_type s = inPath.rfind('/', inPath.size());//position of last / path_stack_string fName; - if (s == string::npos) + if (s == AZStd::string::npos) { if (dir) { @@ -503,9 +502,9 @@ void _splitpath(const char* inpath, char* drv, char* dir, char* fname, char* ext { if (dir) { - azstrcpy(dir, AZ_MAX_PATH_LEN, (inPath.substr((string::size_type)0, (string::size_type)(s + 1))).c_str()); //assign directory + azstrcpy(dir, AZ_MAX_PATH_LEN, (inPath.substr((AZStd::string::size_type)0, (AZStd::string::size_type)(s + 1))).c_str()); //assign directory } - fName = inPath.substr((string::size_type)(s + 1)); //assign remaining string as rest + fName = inPath.substr((AZStd::string::size_type)(s + 1)); //assign remaining string as rest } if (fName.size() == 0) { @@ -521,8 +520,8 @@ void _splitpath(const char* inpath, char* drv, char* dir, char* fname, char* ext else { //dir and drive are now set - s = fName.find(".", (string::size_type)0);//position of first . - if (s == string::npos) + s = fName.find(".", (AZStd::string::size_type)0);//position of first . + if (s == AZStd::string::npos) { if (ext) { @@ -547,7 +546,7 @@ void _splitpath(const char* inpath, char* drv, char* dir, char* fname, char* ext } else { - azstrcpy(fname, AZ_MAX_PATH_LEN, (fName.substr((string::size_type)0, s)).c_str()); //assign filename + azstrcpy(fname, AZ_MAX_PATH_LEN, (fName.substr((AZStd::string::size_type)0, s)).c_str()); //assign filename } } } @@ -779,17 +778,17 @@ BOOL SystemTimeToFileTime(const SYSTEMTIME* syst, LPFILETIME ft) return TRUE; } -void adaptFilenameToLinux(string& rAdjustedFilename) +void adaptFilenameToLinux(AZStd::string& rAdjustedFilename) { //first replace all \\ by / - string::size_type loc = 0; - while ((loc = rAdjustedFilename.find("\\", loc)) != string::npos) + AZStd::string::size_type loc = 0; + while ((loc = rAdjustedFilename.find("\\", loc)) != AZStd::string::npos) { rAdjustedFilename.replace(loc, 1, "/"); } loc = 0; //remove /./ - while ((loc = rAdjustedFilename.find("/./", loc)) != string::npos) + while ((loc = rAdjustedFilename.find("/./", loc)) != AZStd::string::npos) { rAdjustedFilename.replace(loc, 3, "/"); } @@ -798,16 +797,16 @@ void adaptFilenameToLinux(string& rAdjustedFilename) void replaceDoublePathFilename(char* szFileName) { //replace "\.\" by "\" - string s(szFileName); - string::size_type loc = 0; + AZStd::string s(szFileName); + AZStd::string::size_type loc = 0; //remove /./ - while ((loc = s.find("/./", loc)) != string::npos) + while ((loc = s.find("/./", loc)) != AZStd::string::npos) { s.replace(loc, 3, "/"); } loc = 0; //remove "\.\" - while ((loc = s.find("\\.\\", loc)) != string::npos) + while ((loc = s.find("\\.\\", loc)) != AZStd::string::npos) { s.replace(loc, 3, "\\"); } @@ -817,8 +816,8 @@ void replaceDoublePathFilename(char* szFileName) const int comparePathNames(const char* cpFirst, const char* cpSecond, unsigned int len) { //create two strings and replace the \\ by / and /./ by / - string first(cpFirst); - string second(cpSecond); + AZStd::string first(cpFirst); + AZStd::string second(cpSecond); adaptFilenameToLinux(first); adaptFilenameToLinux(second); if (strlen(cpFirst) < len || strlen(cpSecond) < len) @@ -1618,14 +1617,16 @@ const bool GetFilenameNoCase return true; } -DWORD GetFileAttributes(LPCSTR lpFileName) +DWORD GetFileAttributes(LPCWSTR lpFileNameW) { + AZStd::string lpFileName; + AZStd::to_string(lpFileName, lpFileNameW); struct stat fileStats; - const int success = stat(lpFileName, &fileStats); + const int success = stat(lpFileName.c_str(), &fileStats); if (success == -1) { char adjustedFilename[MAX_PATH]; - GetFilenameNoCase(lpFileName, adjustedFilename); + GetFilenameNoCase(lpFileName.c_str(), adjustedFilename); if (stat(adjustedFilename, &fileStats) == -1) { return (DWORD)INVALID_FILE_ATTRIBUTES; @@ -1648,7 +1649,7 @@ DWORD GetFileAttributes(LPCSTR lpFileName) uint32 CryGetFileAttributes(const char* lpFileName) { - string fn = lpFileName; + AZStd::string fn = lpFileName; adaptFilenameToLinux(fn); const char* buffer = fn.c_str(); return GetFileAttributes(buffer); diff --git a/Code/Legacy/CrySystem/DebugCallStack.cpp b/Code/Legacy/CrySystem/DebugCallStack.cpp index 289d4070ff..c0923341ad 100644 --- a/Code/Legacy/CrySystem/DebugCallStack.cpp +++ b/Code/Legacy/CrySystem/DebugCallStack.cpp @@ -435,18 +435,18 @@ void DebugCallStack::LogExceptionInfo(EXCEPTION_POINTERS* pex) { const char* const szMessage = m_bIsFatalError ? s_szFatalErrorCode : m_szBugMessage; excName = szMessage; - azstrcpy(excCode, szMessage); - azstrcpy(excAddr, ""); - azstrcpy(desc, ""); - azstrcpy(m_excModule, ""); - azstrcpy(excDesc, szMessage); + azstrcpy(excCode, AZ_ARRAY_SIZE(excCode), szMessage); + azstrcpy(excAddr, AZ_ARRAY_SIZE(excAddr), ""); + azstrcpy(desc, AZ_ARRAY_SIZE(desc), ""); + azstrcpy(m_excModule, AZ_ARRAY_SIZE(m_excModule), ""); + azstrcpy(excDesc, AZ_ARRAY_SIZE(excDesc), szMessage); } else { sprintf_s(excAddr, "0x%04X:0x%p", pex->ContextRecord->SegCs, pex->ExceptionRecord->ExceptionAddress); sprintf_s(excCode, "0x%08X", pex->ExceptionRecord->ExceptionCode); excName = TranslateExceptionCode(pex->ExceptionRecord->ExceptionCode); - azstrcpy(desc, ""); + azstrcpy(desc, AZ_ARRAY_SIZE(desc), ""); sprintf_s(excDesc, "%s\r\n%s", excName, desc); @@ -476,9 +476,9 @@ void DebugCallStack::LogExceptionInfo(EXCEPTION_POINTERS* pex) WriteLineToLog("Exception Description: %s", desc); - azstrcpy(m_excDesc, excDesc); - azstrcpy(m_excAddr, excAddr); - azstrcpy(m_excCode, excCode); + azstrcpy(m_excDesc, AZ_ARRAY_SIZE(m_excDesc), excDesc); + azstrcpy(m_excAddr, AZ_ARRAY_SIZE(m_excAddr), excAddr); + azstrcpy(m_excCode, AZ_ARRAY_SIZE(m_excCode), excCode); char errs[32768]; @@ -504,7 +504,7 @@ void DebugCallStack::LogExceptionInfo(EXCEPTION_POINTERS* pex) dumpCallStack(funcs); // Fill call stack. char str[s_iCallStackSize]; - azstrcpy(str, ""); + azstrcpy(str, AZ_ARRAY_SIZE(str), ""); for (unsigned int i = 0; i < funcs.size(); i++) { char temp[s_iCallStackSize]; @@ -514,7 +514,7 @@ void DebugCallStack::LogExceptionInfo(EXCEPTION_POINTERS* pex) azstrcat(errs, temp); azstrcat(errs, "\n"); } - azstrcpy(m_excCallstack, str); + azstrcpy(m_excCallstack, AZ_ARRAY_SIZE(m_excCallstack), str); } azstrcat(errorString, errs); diff --git a/Code/Legacy/CrySystem/IDebugCallStack.cpp b/Code/Legacy/CrySystem/IDebugCallStack.cpp index bee43b237b..1176c15f0e 100644 --- a/Code/Legacy/CrySystem/IDebugCallStack.cpp +++ b/Code/Legacy/CrySystem/IDebugCallStack.cpp @@ -237,7 +237,7 @@ void IDebugCallStack::WriteLineToLog(const char* format, ...) char szBuffer[MAX_WARNING_LENGTH]; va_start(ArgList, format); vsnprintf_s(szBuffer, sizeof(szBuffer), sizeof(szBuffer) - 1, format, ArgList); - azstrcat(szBuffer, "\n"); + azstrcat(szBuffer, MAX_WARNING_LENGTH, "\n"); szBuffer[sizeof(szBuffer) - 1] = '\0'; va_end(ArgList); diff --git a/Code/Legacy/CrySystem/IDebugCallStack.h b/Code/Legacy/CrySystem/IDebugCallStack.h index a2c1d3f5e2..1a65fbbdb7 100644 --- a/Code/Legacy/CrySystem/IDebugCallStack.h +++ b/Code/Legacy/CrySystem/IDebugCallStack.h @@ -41,11 +41,7 @@ public: filename = "[unknown]"; line = 0; baseAddr = addr; -#if defined(PLATFORM_64BIT) - procName = AZStd::string::format("[%016llX]", addr); -#else - procName = AZStd::string::format("[%08X]", addr); -#endif + procName = AZStd::string::format("[%p]", addr); } // returns current filename diff --git a/Code/Legacy/CrySystem/LevelSystem/LevelSystem.cpp b/Code/Legacy/CrySystem/LevelSystem/LevelSystem.cpp index 3e6432a721..d21fff3dd3 100644 --- a/Code/Legacy/CrySystem/LevelSystem/LevelSystem.cpp +++ b/Code/Legacy/CrySystem/LevelSystem/LevelSystem.cpp @@ -567,7 +567,7 @@ ILevel* CLevelSystem::LoadLevelInternal(const char* _levelName) INDENT_LOG_DURING_SCOPE(); char levelName[256]; - azstrcpy(levelName, _levelName); + azstrcpy(levelName, AZ_ARRAY_SIZE(levelName), _levelName); // Not remove a scope!!! { diff --git a/Code/Legacy/CrySystem/LocalizedStringManager.cpp b/Code/Legacy/CrySystem/LocalizedStringManager.cpp index 42bdb3afef..cffe1c38c6 100644 --- a/Code/Legacy/CrySystem/LocalizedStringManager.cpp +++ b/Code/Legacy/CrySystem/LocalizedStringManager.cpp @@ -2762,7 +2762,7 @@ void CLocalizedStringsManager::LocalizeTime(time_t t, bool bMakeLocalTime, bool const size_t bufSize = sizeof(buf) / sizeof(buf[0]); wcsftime(buf, bufSize, bShowSeconds ? L"%#X" : L"%X", &theTime); buf[bufSize - 1] = 0; - Unicode::Convert(outTimeString, buf); + AZStd::to_string(outTimeString, buf); } void CLocalizedStringsManager::LocalizeDate(time_t t, bool bMakeLocalTime, bool bShort, bool bIncludeWeekday, AZStd::string& outDateString) @@ -2790,7 +2790,7 @@ void CLocalizedStringsManager::LocalizeDate(time_t t, bool bMakeLocalTime, bool const wchar_t* format = bShort ? (bIncludeWeekday ? L"%a %x" : L"%x") : L"%#x"; // long format always contains Weekday name wcsftime(buf, bufSize, format, &theTime); buf[bufSize - 1] = 0; - Unicode::Convert(outDateString, buf); + AZStd::to_string(outDateString, buf); } diff --git a/Code/Legacy/CrySystem/Log.cpp b/Code/Legacy/CrySystem/Log.cpp index 6ee6af6c22..0385ff8eb3 100644 --- a/Code/Legacy/CrySystem/Log.cpp +++ b/Code/Legacy/CrySystem/Log.cpp @@ -508,7 +508,7 @@ void CLog::LogV(const ELogType type, [[maybe_unused]]int flags, const char* szFo stack_string s = szBuffer; s += "\t "; s += sAssetScope; - azstrcpy(szBuffer, s.c_str()); + azstrcpy(szBuffer, AZ_ARRAY_SIZE(szBuffer), s.c_str()); } } @@ -531,7 +531,7 @@ void CLog::LogV(const ELogType type, [[maybe_unused]]int flags, const char* szFo } } i = m_iLastHistoryItem = m_iLastHistoryItem + 1 & sz - 1; - azstrcpy(m_history[i].str, m_history[i].ptr = szSpamCheck); + azstrcpy(m_history[i].str, AZ_ARRAY_SIZE(m_history[i].str), m_history[i].ptr = szSpamCheck); m_history[i].type = type; m_history[i].time = time; } @@ -862,7 +862,7 @@ bool CLog::LogToMainThread(const char* szString, ELogType logType, bool bAdd, SL { // When logging from other thread then main, push all log strings to queue. SLogMsg msg; - azstrcpy(msg.msg, szString); + azstrcpy(msg.msg, AZ_ARRAY_SIZE(msg.msg), szString); msg.bAdd = bAdd; msg.destination = destination; msg.logType = logType; @@ -1277,7 +1277,7 @@ void CLog::CreateBackupFile() const AZStd::string bakdest = PathUtil::Make(LOG_BACKUP_PATH, sFileWithoutExt + sBackupNameAttachment + "." + sExt); fileSystem->CreatePath(LOG_BACKUP_PATH); - azstrcpy(m_sBackupFilename, bakdest.c_str()); + azstrcpy(m_sBackupFilename, AZ_ARRAY_SIZE(m_sBackupFilename), bakdest.c_str()); // Remove any existing backup file with the same name first since the copy will fail otherwise. fileSystem->Remove(m_sBackupFilename); fileSystem->Copy(m_szFilename, bakdest.c_str()); diff --git a/Code/Legacy/CrySystem/SystemWin32.cpp b/Code/Legacy/CrySystem/SystemWin32.cpp index 9fd01f1905..66be2a2ca5 100644 --- a/Code/Legacy/CrySystem/SystemWin32.cpp +++ b/Code/Legacy/CrySystem/SystemWin32.cpp @@ -282,7 +282,7 @@ static const char* GetLastSystemErrorMessage() 0, NULL)) { - azstrcpy(szBuffer, (char*)lpMsgBuf); + azstrcpy(szBuffer, AZ_ARRAY_SIZE(szBuffer), (char*)lpMsgBuf); LocalFree(lpMsgBuf); } else diff --git a/Code/Legacy/CrySystem/XConsole.cpp b/Code/Legacy/CrySystem/XConsole.cpp index 252ab8137d..6da42420f8 100644 --- a/Code/Legacy/CrySystem/XConsole.cpp +++ b/Code/Legacy/CrySystem/XConsole.cpp @@ -1547,31 +1547,31 @@ const char* CXConsole::GetFlagsString(const uint32 dwFlags) // hiding this makes it a bit more difficult for cheaters // if(dwFlags&VF_CHEAT) azstrcat( sFlags,"CHEAT, "); - azstrcpy(sFlags, ""); + azstrcpy(sFlags, AZ_ARRAY_SIZE(sFlags), ""); if (dwFlags & VF_READONLY) { - azstrcat(sFlags, "READONLY, "); + azstrcat(sFlags, AZ_ARRAY_SIZE(sFlags), "READONLY, "); } if (dwFlags & VF_DEPRECATED) { - azstrcat(sFlags, "DEPRECATED, "); + azstrcat(sFlags, AZ_ARRAY_SIZE(sFlags), "DEPRECATED, "); } if (dwFlags & VF_DUMPTODISK) { - azstrcat(sFlags, "DUMPTODISK, "); + azstrcat(sFlags, AZ_ARRAY_SIZE(sFlags), "DUMPTODISK, "); } if (dwFlags & VF_REQUIRE_LEVEL_RELOAD) { - azstrcat(sFlags, "REQUIRE_LEVEL_RELOAD, "); + azstrcat(sFlags, AZ_ARRAY_SIZE(sFlags), "REQUIRE_LEVEL_RELOAD, "); } if (dwFlags & VF_REQUIRE_APP_RESTART) { - azstrcat(sFlags, "REQUIRE_APP_RESTART, "); + azstrcat(sFlags, AZ_ARRAY_SIZE(sFlags), "REQUIRE_APP_RESTART, "); } if (dwFlags & VF_RESTRICTEDMODE) { - azstrcat(sFlags, "RESTRICTEDMODE, "); + azstrcat(sFlags, AZ_ARRAY_SIZE(sFlags), "RESTRICTEDMODE, "); } if (sFlags[0] != 0) @@ -3325,7 +3325,7 @@ const char* CXConsole::AutoComplete(const char* substr) const char* szCmd = cmds[i]; size_t cmdlen = strlen(szCmd); - if (cmdlen >= substrLen && azmemicmp(szCmd, substr, substrLen) == 0) + if (cmdlen >= substrLen && azstrnicmp(szCmd, substr, substrLen) == 0) { if (substrLen == cmdlen) { diff --git a/Code/Legacy/CrySystem/XML/XMLBinaryReader.cpp b/Code/Legacy/CrySystem/XML/XMLBinaryReader.cpp index e59f6b8969..c86c0691a9 100644 --- a/Code/Legacy/CrySystem/XML/XMLBinaryReader.cpp +++ b/Code/Legacy/CrySystem/XML/XMLBinaryReader.cpp @@ -32,7 +32,7 @@ const char* XMLBinary::XMLBinaryReader::GetErrorDescription() const void XMLBinary::XMLBinaryReader::SetErrorDescription(const char* text) { - azstrcpy(m_errorDescription, text); + azstrcpy(m_errorDescription, AZ_ARRAY_SIZE(m_errorDescription), text); } diff --git a/Code/Legacy/CrySystem/XML/XMLBinaryWriter.cpp b/Code/Legacy/CrySystem/XML/XMLBinaryWriter.cpp index 81994b26e0..7fd9df30c9 100644 --- a/Code/Legacy/CrySystem/XML/XMLBinaryWriter.cpp +++ b/Code/Legacy/CrySystem/XML/XMLBinaryWriter.cpp @@ -99,7 +99,7 @@ bool XMLBinary::CXMLBinaryWriter::WriteNode(IDataWriter* pFile, XmlNodeRef node, static const uint nMaxNodeCount = (NodeIndex) ~0; if (m_nodes.size() > nMaxNodeCount) { - error = AZStd::string::format("XMLBinary: Too many nodes: %d (max is %i)", m_nodes.size(), nMaxNodeCount); + error = AZStd::string::format("XMLBinary: Too many nodes: %zu (max is %i)", m_nodes.size(), nMaxNodeCount); return false; } diff --git a/Code/Tools/GridHub/GridHub/gridhub.cpp b/Code/Tools/GridHub/GridHub/gridhub.cpp index 978589ab74..24dd440411 100644 --- a/Code/Tools/GridHub/GridHub/gridhub.cpp +++ b/Code/Tools/GridHub/GridHub/gridhub.cpp @@ -543,7 +543,7 @@ GridHubComponent::OnMemberJoined([[maybe_unused]] GridMate::GridSession* session case AZ::PlatformID::PLATFORM_WINDOWS_64: case AZ::PlatformID::PLATFORM_APPLE_MAC: { - GridMate::string localMachineName = GridMate::Utils::GetMachineAddress(); + AZStd::string localMachineName = GridMate::Utils::GetMachineAddress(); if( member->GetMachineName() == localMachineName ) { ExternalProcessMonitor mi; @@ -629,7 +629,7 @@ bool GridHubComponent::StartSession(bool isRestarting) AZ_Assert(GridMate::HasGridMateService(m_gridMate), "Failed to start multiplayer service for LAN!"); // if we get an address 169.X.X.X (AZCP is NOT ready) or 127.0.0.1 when network is not ready - GridMate::string machineIP = GridMate::Utils::GetMachineAddress(); + AZStd::string machineIP = GridMate::Utils::GetMachineAddress(); if( machineIP == "127.0.0.1" || machineIP.compare(0,4,"169.") == 0 ) { AZ_Warning("GridHub", false, "\nCurrent IP %s might be invalid.\n",machineIP.c_str()); diff --git a/Code/Tools/GridHub/GridHub/gridhub.hxx b/Code/Tools/GridHub/GridHub/gridhub.hxx index 468cf525a0..849dbb92e1 100644 --- a/Code/Tools/GridHub/GridHub/gridhub.hxx +++ b/Code/Tools/GridHub/GridHub/gridhub.hxx @@ -141,7 +141,7 @@ public: /// Callback that notifies the title when a session will be left. session pointer is NOT valid after the callback returns. void OnSessionDelete(GridMate::GridSession* session) override; /// Called when a session error occurs. - void OnSessionError(GridMate::GridSession* session, const GridMate::string& errorMsg ) { (void)session; (void)errorMsg; } + void OnSessionError(GridMate::GridSession* session, const AZStd::string& errorMsg ) { (void)session; (void)errorMsg; } /// Called when the actual game(match) starts void OnSessionStart(GridMate::GridSession* session) { (void)session; } /// Called when the actual game(match) ends diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Source/Platform/Windows/Process/TestImpactWin32_Process.cpp b/Code/Tools/TestImpactFramework/Runtime/Code/Source/Platform/Windows/Process/TestImpactWin32_Process.cpp index 2630a63bee..dd65722560 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Source/Platform/Windows/Process/TestImpactWin32_Process.cpp +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Source/Platform/Windows/Process/TestImpactWin32_Process.cpp @@ -11,6 +11,7 @@ #include #include +#include namespace TestImpact { @@ -55,9 +56,11 @@ namespace TestImpact CreatePipes(sa, si); - if (!CreateProcess( + AZStd::wstring argsW; + AZStd::to_wstring(argsW, args.c_str()); + if (!CreateProcessW( NULL, - &args[0], + argsW.c_str(), NULL, NULL, IsPiping(), diff --git a/Gems/LyShine/Code/Editor/Animation/UiAnimViewDopeSheetBase.cpp b/Gems/LyShine/Code/Editor/Animation/UiAnimViewDopeSheetBase.cpp index ae0880e98e..a38736ff67 100644 --- a/Gems/LyShine/Code/Editor/Animation/UiAnimViewDopeSheetBase.cpp +++ b/Gems/LyShine/Code/Editor/Animation/UiAnimViewDopeSheetBase.cpp @@ -2362,10 +2362,10 @@ void CUiAnimViewDopeSheetBase::DrawKeys(CUiAnimViewTrack* pTrack, QPainter* pain } else { - azstrcpy(keydesc, "{"); + azstrcpy(keydesc, AZ_ARRAY_SIZE(keydesc), "{"); } - azstrcat(keydesc, pDescription); - azstrcat(keydesc, "}"); + azstrcat(keydesc, AZ_ARRAY_SIZE(keydesc), pDescription); + azstrcat(keydesc, AZ_ARRAY_SIZE(keydesc), "}"); // Draw key description text. // Find next key. const QRect textRect(QPoint(x + 10, rect.top()), QPoint(x1, rect.bottom())); diff --git a/Gems/LyShine/Code/Source/Platform/Common/Unimplemented/UiClipboard_Unimplemented.cpp b/Gems/LyShine/Code/Source/Platform/Common/Unimplemented/UiClipboard_Unimplemented.cpp index 744cb65ac8..9175c7b2be 100644 --- a/Gems/LyShine/Code/Source/Platform/Common/Unimplemented/UiClipboard_Unimplemented.cpp +++ b/Gems/LyShine/Code/Source/Platform/Common/Unimplemented/UiClipboard_Unimplemented.cpp @@ -8,16 +8,13 @@ // UiClipboard is responsible setting and getting clipboard data for the UI elements in a platform-independent way. #include "UiClipboard.h" -#include -bool UiClipboard::SetText(const AZStd::string& text) +bool UiClipboard::SetText([[maybe_unused]] const AZStd::string& text) { - AZ_UNUSED(text); return false; } AZStd::string UiClipboard::GetText() { - AZStd::string outText; - return outText; + return {}; } diff --git a/Gems/Maestro/Code/Source/Cinematics/CaptureTrack.cpp b/Gems/Maestro/Code/Source/Cinematics/CaptureTrack.cpp index 60d578d1f8..f4faf4dbeb 100644 --- a/Gems/Maestro/Code/Source/Cinematics/CaptureTrack.cpp +++ b/Gems/Maestro/Code/Source/Cinematics/CaptureTrack.cpp @@ -52,7 +52,7 @@ void CCaptureTrack::GetKeyInfo(int key, const char*& description, float& duratio char prefix[64] = "Frame"; if (!m_keys[key].prefix.empty()) { - azstrcpy(prefix, m_keys[key].prefix.c_str()); + azstrcpy(prefix, AZ_ARRAY_SIZE(prefix), m_keys[key].prefix.c_str()); } description = buffer; if (!m_keys[key].folder.empty()) diff --git a/Gems/Maestro/Code/Source/Cinematics/CommentTrack.cpp b/Gems/Maestro/Code/Source/Cinematics/CommentTrack.cpp index 1dd72de567..8c1baf4684 100644 --- a/Gems/Maestro/Code/Source/Cinematics/CommentTrack.cpp +++ b/Gems/Maestro/Code/Source/Cinematics/CommentTrack.cpp @@ -25,7 +25,7 @@ void CCommentTrack::GetKeyInfo(int key, const char*& description, float& duratio description = 0; duration = m_keys[key].m_duration; - azstrcpy(desc, m_keys[key].m_strComment.c_str()); + azstrcpy(desc, AZ_ARRAY_SIZE(desc), m_keys[key].m_strComment.c_str()); description = desc; } diff --git a/Gems/Maestro/Code/Source/Cinematics/CompoundSplineTrack.cpp b/Gems/Maestro/Code/Source/Cinematics/CompoundSplineTrack.cpp index 62de2dfdf5..884a90b200 100644 --- a/Gems/Maestro/Code/Source/Cinematics/CompoundSplineTrack.cpp +++ b/Gems/Maestro/Code/Source/Cinematics/CompoundSplineTrack.cpp @@ -457,31 +457,31 @@ void CCompoundSplineTrack::GetKeyInfo(int key, const char*& description, float& { float dummy; m_subTracks[0]->GetKeyInfo(m, subDesc, dummy); - azstrcat(str, subDesc); + azstrcat(str, AZ_ARRAY_SIZE(str), subDesc); break; } } if (m == m_subTracks[0]->GetNumKeys()) { - azstrcat(str, m_subTrackNames[0].c_str()); + azstrcat(str, AZ_ARRAY_SIZE(str), m_subTrackNames[0].c_str()); } // Tail cases for (int i = 1; i < GetSubTrackCount(); ++i) { - azstrcat(str, ","); + azstrcat(str, AZ_ARRAY_SIZE(str), ","); for (m = 0; m < m_subTracks[i]->GetNumKeys(); ++m) { if (m_subTracks[i]->GetKeyTime(m) == time) { float dummy; m_subTracks[i]->GetKeyInfo(m, subDesc, dummy); - azstrcat(str, subDesc); + azstrcat(str, AZ_ARRAY_SIZE(str), subDesc); break; } } if (m == m_subTracks[i]->GetNumKeys()) { - azstrcat(str, m_subTrackNames[i].c_str()); + azstrcat(str, AZ_ARRAY_SIZE(str), m_subTrackNames[i].c_str()); } } } diff --git a/Gems/Maestro/Code/Source/Cinematics/EventTrack.cpp b/Gems/Maestro/Code/Source/Cinematics/EventTrack.cpp index 36d468e36d..4d32a4a4a1 100644 --- a/Gems/Maestro/Code/Source/Cinematics/EventTrack.cpp +++ b/Gems/Maestro/Code/Source/Cinematics/EventTrack.cpp @@ -69,11 +69,11 @@ void CEventTrack::GetKeyInfo(int key, const char*& description, float& duration) CheckValid(); description = 0; duration = 0; - azstrcpy(desc, m_keys[key].event.c_str()); + azstrcpy(desc, AZ_ARRAY_SIZE(desc), m_keys[key].event.c_str()); if (!m_keys[key].eventValue.empty()) { - azstrcat(desc, ", "); - azstrcat(desc, m_keys[key].eventValue.c_str()); + azstrcat(desc, AZ_ARRAY_SIZE(desc), ", "); + azstrcat(desc, AZ_ARRAY_SIZE(desc), m_keys[key].eventValue.c_str()); } description = desc; diff --git a/Gems/Maestro/Code/Source/Cinematics/SceneNode.cpp b/Gems/Maestro/Code/Source/Cinematics/SceneNode.cpp index 799747eb12..be6d18eeb2 100644 --- a/Gems/Maestro/Code/Source/Cinematics/SceneNode.cpp +++ b/Gems/Maestro/Code/Source/Cinematics/SceneNode.cpp @@ -916,8 +916,8 @@ void CAnimSceneNode::ApplyCameraKey(ISelectKey& key, SAnimContext& ec) void CAnimSceneNode::ApplyEventKey(IEventKey& key, [[maybe_unused]] SAnimContext& ec) { char funcName[1024]; - azstrcpy(funcName, "Event_"); - azstrcat(funcName, key.event.c_str()); + azstrcpy(funcName, AZ_ARRAY_SIZE(funcName), "Event_"); + azstrcat(funcName, AZ_ARRAY_SIZE(funcName), key.event.c_str()); gEnv->pMovieSystem->SendGlobalEvent(funcName); } diff --git a/Gems/Maestro/Code/Source/Cinematics/ScreenFaderTrack.cpp b/Gems/Maestro/Code/Source/Cinematics/ScreenFaderTrack.cpp index 3541fe718e..9ac19f91ea 100644 --- a/Gems/Maestro/Code/Source/Cinematics/ScreenFaderTrack.cpp +++ b/Gems/Maestro/Code/Source/Cinematics/ScreenFaderTrack.cpp @@ -32,7 +32,7 @@ void CScreenFaderTrack::GetKeyInfo(int key, const char*& description, float& dur CheckValid(); description = 0; duration = m_keys[key].m_fadeTime; - azstrcpy(desc, m_keys[key].m_fadeType == IScreenFaderKey::eFT_FadeIn ? "In" : "Out"); + azstrcpy(desc, AZ_ARRAY_SIZE(desc), m_keys[key].m_fadeType == IScreenFaderKey::eFT_FadeIn ? "In" : "Out"); description = desc; } diff --git a/Gems/Maestro/Code/Source/Cinematics/TrackEventTrack.cpp b/Gems/Maestro/Code/Source/Cinematics/TrackEventTrack.cpp index 25d709bcdc..83b141cfb2 100644 --- a/Gems/Maestro/Code/Source/Cinematics/TrackEventTrack.cpp +++ b/Gems/Maestro/Code/Source/Cinematics/TrackEventTrack.cpp @@ -143,11 +143,11 @@ void CTrackEventTrack::GetKeyInfo(int key, const char*& description, float& dura CheckValid(); description = 0; duration = 0; - azstrcpy(desc, m_keys[key].event.c_str()); + azstrcpy(desc, AZ_ARRAY_SIZE(desc), m_keys[key].event.c_str()); if (!m_keys[key].eventValue.empty()) { - azstrcat(desc, ", "); - azstrcat(desc, m_keys[key].eventValue.c_str()); + azstrcat(desc, AZ_ARRAY_SIZE(desc), ", "); + azstrcat(desc, AZ_ARRAY_SIZE(desc), m_keys[key].eventValue.c_str()); } description = desc; From 3db93a564d1a7b5e8c7b87eccb56ce6009a4dd47 Mon Sep 17 00:00:00 2001 From: Kyle B Date: Tue, 3 Aug 2021 18:28:55 -0700 Subject: [PATCH 096/803] Made formatting changes per pull comments, incuding adding comments, changing spacing, and changing the ui type of component fields Signed-off-by: Kyle B --- .../Include/Atom/Feature/Mesh/MeshFeatureProcessor.h | 8 ++++---- .../Common/Code/Source/Mesh/MeshFeatureProcessor.cpp | 12 ++++++------ Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Culling.h | 2 +- .../Code/Source/Mesh/EditorMeshComponent.cpp | 4 ++-- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h index e7e794c76e..08f2dde474 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h @@ -62,13 +62,13 @@ namespace AZ void BuildDrawPacketList(size_t modelLodIndex); void SetRayTracingData(); void SetSortKey(RHI::DrawItemSortKey sortKey); - RHI::DrawItemSortKey GetSortKey(); + RHI::DrawItemSortKey GetSortKey() const; void SetLodOverride(RPI::Cullable::LodOverride lodOverride); - RPI::Cullable::LodOverride GetLodOverride(); + RPI::Cullable::LodOverride GetLodOverride() const; void SetMinimumScreenCoverage(float minimumScreenCoverage); - float GetMinimumScreenCoverage(); + float GetMinimumScreenCoverage() const; void SetQualityDecayRate(float qualityDecayRate); - float GetQualityDecayRate(); + float GetQualityDecayRate() const; void UpdateDrawPackets(bool forceUpdate = false); void BuildCullable(); void UpdateCullBounds(const TransformServiceFeatureProcessor* transformService); diff --git a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp index 7d1d7ed851..286724b06a 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp @@ -380,7 +380,7 @@ namespace AZ } } - void MeshFeatureProcessor::SetMinimumScreenCoverage( const MeshHandle& meshHandle, float minimumScreenCoverage) + void MeshFeatureProcessor::SetMinimumScreenCoverage(const MeshHandle& meshHandle, float minimumScreenCoverage) { if (meshHandle.IsValid()) { @@ -388,7 +388,7 @@ namespace AZ } } - float MeshFeatureProcessor::GetMinimumScreenCoverage(const MeshHandle& meshHandle) + float MeshFeatureProcessor::GetMinimumScreenCoverage(const MeshHandle& meshHandle) const { if (meshHandle.IsValid()) { @@ -1028,7 +1028,7 @@ namespace AZ } } - RHI::DrawItemSortKey MeshDataInstance::GetSortKey() + RHI::DrawItemSortKey MeshDataInstance::GetSortKey() const { return m_sortKey; } @@ -1038,7 +1038,7 @@ namespace AZ m_cullable.m_lodData.m_lodOverride = lodOverride; } - RPI::Cullable::LodOverride MeshDataInstance::GetLodOverride() + RPI::Cullable::LodOverride MeshDataInstance::GetLodOverride() const { return m_cullable.m_lodData.m_lodOverride; } @@ -1048,7 +1048,7 @@ namespace AZ m_cullable.m_lodData.m_minimumScreenCoverage = minimumScreenCoverage; } - float MeshDataInstance::GetMinimumScreenCoverage() + float MeshDataInstance::GetMinimumScreenCoverage() const { return m_cullable.m_lodData.m_minimumScreenCoverage; } @@ -1058,7 +1058,7 @@ namespace AZ m_cullable.m_lodData.m_qualityDecayRate = qualityDecayRate; } - float MeshDataInstance::GetQualityDecayRate() + float MeshDataInstance::GetQualityDecayRate() const { return m_cullable.m_lodData.m_qualityDecayRate; } diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Culling.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Culling.h index 30cf091735..4a39a21e0b 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Culling.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Culling.h @@ -89,7 +89,7 @@ namespace AZ float m_lodSelectionRadius = 1.0f; // the minimum possibe area a sphere enclosing a mesh projected onto the screen should have before it is culled. - float m_minimumScreenCoverage = 1.0f / 1080.0f; + float m_minimumScreenCoverage = 1.0f / 1080.0f; //For default, mesh should cover at least a screen pixel at 1080p to be drawn // The screen area decay between 0 and 1, i.e. closer to 1 -> lose quality immediately, closer to 0 -> never lose quality float m_qualityDecayRate = 0.5f; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp index d46017af16..3308767de9 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp @@ -76,11 +76,11 @@ namespace AZ ->DataElement(AZ::Edit::UIHandlers::ComboBox, &MeshComponentConfig::m_lodOverride, "Lod Override", "Allows the rendered LOD to be overridden instead of being calculated automatically.") ->Attribute(AZ::Edit::Attributes::EnumValues, &MeshComponentConfig::GetLodOverrideValues) ->Attribute(AZ::Edit::Attributes::Visibility, &MeshComponentConfig::IsAssetSet) - ->DataElement(AZ::Edit::UIHandlers::Default, &MeshComponentConfig::m_minimumScreenCoverage, "Minimum Screen Coverage", "Minimum proportion of screen area an entitiy takes up, after that the entitiy is culled.") + ->DataElement(AZ::Edit::UIHandlers::Slider, &MeshComponentConfig::m_minimumScreenCoverage, "Minimum Screen Coverage", "Minimum proportion of screen area an entitiy takes up, after that the entitiy is culled.") ->Attribute(AZ::Edit::Attributes::Min, 0.f) ->Attribute(AZ::Edit::Attributes::Max, 1.f) ->Attribute(AZ::Edit::Attributes::Suffix, " percent") - ->DataElement(AZ::Edit::UIHandlers::Default, &MeshComponentConfig::m_qualityDecayRate, "Quality Decay Rate", + ->DataElement(AZ::Edit::UIHandlers::Slider, &MeshComponentConfig::m_qualityDecayRate, "Quality Decay Rate", "Rate at which mesh quality decays (0 -> always stay highest quality, 1 -> quality falls off to lowest quality immediately).") ->Attribute(AZ::Edit::Attributes::Min, 0.f) ->Attribute(AZ::Edit::Attributes::Max, 1.f) From 82c5f80fbd163317d823f4d700befc971562a1ea Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Tue, 3 Aug 2021 18:56:46 -0700 Subject: [PATCH 097/803] More windows/linux fixes Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Framework/AzCore/AzCore/base.h | 20 +++++++++---------- Code/Framework/AzCore/Tests/Debug.cpp | 4 ++-- Code/Legacy/CryCommon/platform_impl.cpp | 2 +- Code/Legacy/CrySystem/DebugCallStack.cpp | 16 +++++++-------- .../Code/Editor/Animation/UiAnimViewNodes.cpp | 2 +- 5 files changed, 22 insertions(+), 22 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/base.h b/Code/Framework/AzCore/AzCore/base.h index 00fdbf515e..20f5c17b27 100644 --- a/Code/Framework/AzCore/AzCore/base.h +++ b/Code/Framework/AzCore/AzCore/base.h @@ -71,7 +71,7 @@ // note: for cross-platform compatibility, do not use the return value of azfopen. On Windows, it's an errno_t and 0 indicates success. On other platforms, the return value is a FILE*, and a 0 value indicates failure. # define azfopen(_fp, _filename, _attrib) fopen_s(_fp, _filename, _attrib) -# define azfscanf fscanf_s +# define azfscanf fscanf_s # define azsprintf(_buffer, ...) sprintf_s(_buffer, AZ_ARRAY_SIZE(_buffer), __VA_ARGS__) # define azstrlwr _strlwr_s @@ -118,19 +118,19 @@ # define azfopen(_fp, _filename, _attrib) *(_fp) = fopen(_filename, _attrib) # define azfscanf fscanf -# define azsprintf sprintf -# define azstrlwr(_buffer, _size) strlwr(_buffer) -# define azvsprintf vsprintf -# define azwcscpy(_dest, _size, _buffer) wcscpy(_dest, _buffer) -# define azstrtime _strtime -# define azstrdate _strdate -# define azlocaltime localtime_r +# define azsprintf sprintf +# define azstrlwr(_buffer, _size) strlwr(_buffer) +# define azvsprintf vsprintf +# define azwcscpy(_dest, _size, _buffer) wcscpy(_dest, _buffer) +# define azstrtime _strtime +# define azstrdate _strdate +# define azlocaltime localtime_r #endif #if AZ_TRAIT_USE_POSIX_STRERROR_R -# define azstrerror_s(_dst, _num, _err) strerror_r(_err, _dst, _num) +# define azstrerror_s(_dst, _num, _err) strerror_r(_err, _dst, _num) #else -# define azstrerror_s strerror_s +# define azstrerror_s strerror_s #endif #define AZ_INVALID_POINTER reinterpret_cast(0x0badf00dul) diff --git a/Code/Framework/AzCore/Tests/Debug.cpp b/Code/Framework/AzCore/Tests/Debug.cpp index 3d214ffc68..6181823737 100644 --- a/Code/Framework/AzCore/Tests/Debug.cpp +++ b/Code/Framework/AzCore/Tests/Debug.cpp @@ -56,7 +56,7 @@ namespace UnitTest int isFoundModule = 0; char expectedNameBuffer[AZ_ARRAY_SIZE(SymbolStorage::ModuleInfo::m_modName)]; #if defined(AZCORETEST_DLL_NAME) - azstrncpy(expectedNameBuffer, AZCORETEST_DLL_NAME, AZ_ARRAY_SIZE(expectedNameBuffer)); + azstrncpy(expectedNameBuffer, AZ_ARRAY_SIZE(expectedNameBuffer), AZCORETEST_DLL_NAME, AZ_ARRAY_SIZE(expectedNameBuffer)); #else azstrncpy(expectedNameBuffer, "azcoretests.dll", AZ_ARRAY_SIZE(expectedNameBuffer)); #endif @@ -65,7 +65,7 @@ namespace UnitTest for (u32 i = 0; i < SymbolStorage::GetNumLoadedModules(); ++i) { char nameBuffer[AZ_ARRAY_SIZE(SymbolStorage::ModuleInfo::m_modName)]; - azstrncpy(nameBuffer, SymbolStorage::GetModuleInfo(i)->m_fileName, AZ_ARRAY_SIZE(nameBuffer)); + azstrncpy(nameBuffer, AZ_ARRAY_SIZE(nameBuffer), SymbolStorage::GetModuleInfo(i)->m_fileName, AZ_ARRAY_SIZE(nameBuffer)); AZStd::to_lower(nameBuffer, nameBuffer + AZ_ARRAY_SIZE(nameBuffer)); if (strstr(nameBuffer, expectedNameBuffer)) diff --git a/Code/Legacy/CryCommon/platform_impl.cpp b/Code/Legacy/CryCommon/platform_impl.cpp index 1523622538..3d7b2180fc 100644 --- a/Code/Legacy/CryCommon/platform_impl.cpp +++ b/Code/Legacy/CryCommon/platform_impl.cpp @@ -288,7 +288,7 @@ void InitRootDir(char szExeFileName[], uint nExeSize, char szExeRootName[], uint firstIteration = false; } // Check if the engineroot exists - azstrcat(szPath, "\\engine.json"); + azstrcat(szPath, AZ_ARRAY_SIZE(szPath), "\\engine.json"); WIN32_FILE_ATTRIBUTE_DATA data; AZStd::wstring szPathW; AZStd::to_wstring(szPathW, szPath); diff --git a/Code/Legacy/CrySystem/DebugCallStack.cpp b/Code/Legacy/CrySystem/DebugCallStack.cpp index c0923341ad..ef27ef2c59 100644 --- a/Code/Legacy/CrySystem/DebugCallStack.cpp +++ b/Code/Legacy/CrySystem/DebugCallStack.cpp @@ -419,8 +419,8 @@ void DebugCallStack::LogExceptionInfo(EXCEPTION_POINTERS* pex) char versionbuf[1024]; azstrcpy(versionbuf, AZ_ARRAY_SIZE(versionbuf), ""); PutVersion(versionbuf, AZ_ARRAY_SIZE(versionbuf)); - azstrcat(errorString, versionbuf); - azstrcat(errorString, "\n"); + azstrcat(errorString, AZ_ARRAY_SIZE(errorString), versionbuf); + azstrcat(errorString, AZ_ARRAY_SIZE(errorString), "\n"); char excCode[MAX_WARNING_LENGTH]; char excAddr[80]; @@ -486,7 +486,7 @@ void DebugCallStack::LogExceptionInfo(EXCEPTION_POINTERS* pex) excCode, excAddr, m_excModule, excName, desc); - azstrcat(errs, "\nCall Stack Trace:\n"); + azstrcat(errs, AZ_ARRAY_SIZE(errs), "\nCall Stack Trace:\n"); std::vector funcs; { @@ -509,15 +509,15 @@ void DebugCallStack::LogExceptionInfo(EXCEPTION_POINTERS* pex) { char temp[s_iCallStackSize]; sprintf_s(temp, "%2zd) %s", funcs.size() - i, (const char*)funcs[i].c_str()); - azstrcat(str, temp); - azstrcat(str, "\r\n"); - azstrcat(errs, temp); - azstrcat(errs, "\n"); + azstrcat(str, AZ_ARRAY_SIZE(str), temp); + azstrcat(str, AZ_ARRAY_SIZE(str), "\r\n"); + azstrcat(errs, AZ_ARRAY_SIZE(errs), temp); + azstrcat(errs, AZ_ARRAY_SIZE(errs), "\n"); } azstrcpy(m_excCallstack, AZ_ARRAY_SIZE(m_excCallstack), str); } - azstrcat(errorString, errs); + azstrcat(errorString, AZ_ARRAY_SIZE(errorString), errs); if (f) { diff --git a/Gems/LyShine/Code/Editor/Animation/UiAnimViewNodes.cpp b/Gems/LyShine/Code/Editor/Animation/UiAnimViewNodes.cpp index 67fd542c3f..679477e3d3 100644 --- a/Gems/LyShine/Code/Editor/Animation/UiAnimViewNodes.cpp +++ b/Gems/LyShine/Code/Editor/Animation/UiAnimViewNodes.cpp @@ -1512,7 +1512,7 @@ int CUiAnimViewNodesCtrl::GetMatNameAndSubMtlIndexFromName(QString& matName, con if (const char* pCh = strstr(nodeName, ".[")) { char matPath[MAX_PATH]; - azstrncpy(matPath, nodeName, (size_t)(pCh - nodeName)); + azstrncpy(matPath, AZ_ARRAY_SIZE(matPath), nodeName, (size_t)(pCh - nodeName)); matName = matPath; pCh += 2; if ((*pCh) != 0) From 9c5c2e7de651c2d4c643ec2859ee763af5cc063b Mon Sep 17 00:00:00 2001 From: Kyle B Date: Tue, 3 Aug 2021 19:34:17 -0700 Subject: [PATCH 098/803] un-did const on function that did not need it Signed-off-by: Kyle B --- .../Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp index 286724b06a..166c5610b1 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp @@ -388,7 +388,7 @@ namespace AZ } } - float MeshFeatureProcessor::GetMinimumScreenCoverage(const MeshHandle& meshHandle) const + float MeshFeatureProcessor::GetMinimumScreenCoverage(const MeshHandle& meshHandle) { if (meshHandle.IsValid()) { From eeed7df429f0d25917e42e5217b460bfcc41c2eb Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Tue, 3 Aug 2021 20:24:36 -0700 Subject: [PATCH 099/803] fixing no unity builds Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../ProjectSettingsContainer.cpp | 1 + .../GridMate/Carrier/DefaultHandshake.h | 1 + .../Carrier/DefaultTrafficControl.cpp | 1 + .../GridMate/Carrier/DefaultTrafficControl.h | 2 ++ .../GridMate/GridMate/Carrier/Handshake.h | 1 + Code/Legacy/CryCommon/Linux_Win32Wrapper.h | 2 +- Code/Legacy/CryCommon/WinBase.cpp | 25 +++++++++++++++++-- .../Code/Source/Animation/AnimSequence.cpp | 2 ++ .../Code/Source/SystemComponent.cpp | 1 + 9 files changed, 33 insertions(+), 3 deletions(-) diff --git a/Code/Editor/Plugins/ProjectSettingsTool/ProjectSettingsContainer.cpp b/Code/Editor/Plugins/ProjectSettingsTool/ProjectSettingsContainer.cpp index a7a238d241..772469808b 100644 --- a/Code/Editor/Plugins/ProjectSettingsTool/ProjectSettingsContainer.cpp +++ b/Code/Editor/Plugins/ProjectSettingsTool/ProjectSettingsContainer.cpp @@ -8,6 +8,7 @@ #include "ProjectSettingsContainer.h" +#include #include #include #include diff --git a/Code/Framework/GridMate/GridMate/Carrier/DefaultHandshake.h b/Code/Framework/GridMate/GridMate/Carrier/DefaultHandshake.h index 8f456e4649..9225cca8d7 100644 --- a/Code/Framework/GridMate/GridMate/Carrier/DefaultHandshake.h +++ b/Code/Framework/GridMate/GridMate/Carrier/DefaultHandshake.h @@ -9,6 +9,7 @@ #define GM_DEFAULT_HANDSHAKE_H #include +#include namespace GridMate { diff --git a/Code/Framework/GridMate/GridMate/Carrier/DefaultTrafficControl.cpp b/Code/Framework/GridMate/GridMate/Carrier/DefaultTrafficControl.cpp index 5da3c784ff..f9280d9918 100644 --- a/Code/Framework/GridMate/GridMate/Carrier/DefaultTrafficControl.cpp +++ b/Code/Framework/GridMate/GridMate/Carrier/DefaultTrafficControl.cpp @@ -12,6 +12,7 @@ #include #include +#include using namespace GridMate; diff --git a/Code/Framework/GridMate/GridMate/Carrier/DefaultTrafficControl.h b/Code/Framework/GridMate/GridMate/Carrier/DefaultTrafficControl.h index 1d8a1f6b46..259c619f53 100644 --- a/Code/Framework/GridMate/GridMate/Carrier/DefaultTrafficControl.h +++ b/Code/Framework/GridMate/GridMate/Carrier/DefaultTrafficControl.h @@ -12,6 +12,8 @@ #include +#include + namespace GridMate { /** diff --git a/Code/Framework/GridMate/GridMate/Carrier/Handshake.h b/Code/Framework/GridMate/GridMate/Carrier/Handshake.h index 0f825da49b..5f67b6637c 100644 --- a/Code/Framework/GridMate/GridMate/Carrier/Handshake.h +++ b/Code/Framework/GridMate/GridMate/Carrier/Handshake.h @@ -10,6 +10,7 @@ #include #include +#include namespace GridMate { diff --git a/Code/Legacy/CryCommon/Linux_Win32Wrapper.h b/Code/Legacy/CryCommon/Linux_Win32Wrapper.h index 6507d7c8ee..912546cb7b 100644 --- a/Code/Legacy/CryCommon/Linux_Win32Wrapper.h +++ b/Code/Legacy/CryCommon/Linux_Win32Wrapper.h @@ -378,7 +378,7 @@ typedef struct _finddata_t extern int _findnext64(intptr_t last, __finddata64_t* pFindData); extern intptr_t _findfirst64(const char* pFileName, __finddata64_t* pFindData); -extern DWORD GetFileAttributes(LPCSTR lpFileName); +extern DWORD GetFileAttributesW(LPCWSTR lpFileName); extern const bool GetFilenameNoCase(const char* file, char*, const bool cCreateNew = false); diff --git a/Code/Legacy/CryCommon/WinBase.cpp b/Code/Legacy/CryCommon/WinBase.cpp index 74d383b88d..64e9d9b066 100644 --- a/Code/Legacy/CryCommon/WinBase.cpp +++ b/Code/Legacy/CryCommon/WinBase.cpp @@ -1648,12 +1648,33 @@ DWORD GetFileAttributes(LPCWSTR lpFileNameW) uint32 CryGetFileAttributes(const char* lpFileName) { - AZStd::string fn = lpFileName; adaptFilenameToLinux(fn); const char* buffer = fn.c_str(); - return GetFileAttributes(buffer); + struct stat fileStats; + const int success = stat(buffer, &fileStats); + if (success == -1) + { + char adjustedFilename[MAX_PATH]; + GetFilenameNoCase(buffer, adjustedFilename); + if (stat(adjustedFilename, &fileStats) == -1) + { + return (DWORD)INVALID_FILE_ATTRIBUTES; + } + } + DWORD ret = 0; + + const int acc = (fileStats.st_mode & S_IWRITE); + + if (acc != 0) + { + if (S_ISDIR(fileStats.st_mode) != 0) + { + ret |= FILE_ATTRIBUTE_DIRECTORY; + } + } + return (ret == 0) ? FILE_ATTRIBUTE_NORMAL : ret;//return file attribute normal as the default value, must only be set if no other attributes have been found } __finddata64_t::~__finddata64_t() diff --git a/Gems/LyShine/Code/Source/Animation/AnimSequence.cpp b/Gems/LyShine/Code/Source/Animation/AnimSequence.cpp index 43a80d5002..0b19c4a06a 100644 --- a/Gems/LyShine/Code/Source/Animation/AnimSequence.cpp +++ b/Gems/LyShine/Code/Source/Animation/AnimSequence.cpp @@ -594,6 +594,8 @@ void CUiAnimSequence::Activate() } } +typedef AZStd::fixed_string<512> stack_string; + ////////////////////////////////////////////////////////////////////////// void CUiAnimSequence::Deactivate() { diff --git a/Gems/PhysXDebug/Code/Source/SystemComponent.cpp b/Gems/PhysXDebug/Code/Source/SystemComponent.cpp index 4944626d77..f46c8e229a 100644 --- a/Gems/PhysXDebug/Code/Source/SystemComponent.cpp +++ b/Gems/PhysXDebug/Code/Source/SystemComponent.cpp @@ -30,6 +30,7 @@ #include #include +#include #include From 9bab6761096d1490f487f296ed32efb728707686 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Tue, 3 Aug 2021 20:25:21 -0700 Subject: [PATCH 100/803] enabling test impact framework tool build and fixed it Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Tools/TestImpactFramework/CMakeLists.txt | 6 ++---- .../Platform/Windows/Process/TestImpactWin32_Process.cpp | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/Code/Tools/TestImpactFramework/CMakeLists.txt b/Code/Tools/TestImpactFramework/CMakeLists.txt index 04cbee98dc..1cdf02d101 100644 --- a/Code/Tools/TestImpactFramework/CMakeLists.txt +++ b/Code/Tools/TestImpactFramework/CMakeLists.txt @@ -11,8 +11,6 @@ ly_get_list_relative_pal_filename(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Platf include(${pal_source_dir}/PAL_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) if(PAL_TRAIT_TEST_IMPACT_FRAMEWORK_SUPPORTED) - if(LY_TEST_IMPACT_INSTRUMENTATION_BIN) - add_subdirectory(Runtime) - add_subdirectory(Frontend) - endif() + add_subdirectory(Runtime) + add_subdirectory(Frontend) endif() diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Source/Platform/Windows/Process/TestImpactWin32_Process.cpp b/Code/Tools/TestImpactFramework/Runtime/Code/Source/Platform/Windows/Process/TestImpactWin32_Process.cpp index dd65722560..7ba061f932 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Source/Platform/Windows/Process/TestImpactWin32_Process.cpp +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Source/Platform/Windows/Process/TestImpactWin32_Process.cpp @@ -60,7 +60,7 @@ namespace TestImpact AZStd::to_wstring(argsW, args.c_str()); if (!CreateProcessW( NULL, - argsW.c_str(), + argsW.data(), NULL, NULL, IsPiping(), From 1b002dcc82ca4fbb8e466c2d569d5e1c0fc9566a Mon Sep 17 00:00:00 2001 From: Benjamin Jillich Date: Wed, 4 Aug 2021 11:48:16 +0200 Subject: [PATCH 101/803] Saving node chunk v2 and adapting the chunk processor and importer to it Signed-off-by: Benjamin Jillich --- .../ExporterLib/Exporter/NodeExport.cpp | 50 +++--------------- .../Source/Importer/ActorFileFormat.h | 8 +-- .../Source/Importer/ChunkProcessors.cpp | 52 ++----------------- .../Source/Importer/ChunkProcessors.h | 3 +- .../EMotionFX/Source/Importer/Importer.cpp | 4 +- 5 files changed, 18 insertions(+), 99 deletions(-) diff --git a/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/NodeExport.cpp b/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/NodeExport.cpp index c66c3ca8ef..79861be4b8 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/NodeExport.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/NodeExport.cpp @@ -18,21 +18,6 @@ namespace ExporterLib { - void WriteObbToNodeChunk(EMotionFX::FileFormat::Actor_Node& nodeChunk, const MCore::OBB& obb) - { - AZ::Transform obbMatrix = obb.GetTransformation(); - obbMatrix.GetBasisX().StoreToFloat3(nodeChunk.mOBB); - nodeChunk.mOBB[3] = 0.0f; - obbMatrix.GetBasisY().StoreToFloat3(nodeChunk.mOBB + 4); - nodeChunk.mOBB[7] = 0.0f; - obbMatrix.GetBasisZ().StoreToFloat3(nodeChunk.mOBB + 8); - nodeChunk.mOBB[11] = 0.0f; - nodeChunk.mOBB[12] = 0.0f; - nodeChunk.mOBB[13] = 0.0f; - nodeChunk.mOBB[14] = 0.0f; - nodeChunk.mOBB[15] = 1.0f; - } - void SaveNode(MCore::Stream* file, EMotionFX::Actor* actor, EMotionFX::Node* node, MCore::Endian::EEndianType targetEndianType) { MCORE_ASSERT(file); @@ -47,7 +32,7 @@ namespace ExporterLib const uint32 numChilds = node->GetNumChildNodes(); const EMotionFX::Transform& transform = actor->GetBindPose()->GetLocalSpaceTransform(nodeIndex); AZ::PackedVector3f position = AZ::PackedVector3f(transform.mPosition); - AZ::Quaternion rotation = transform.mRotation.GetNormalized();; + AZ::Quaternion rotation = transform.mRotation.GetNormalized(); #ifndef EMFX_SCALE_DISABLED AZ::PackedVector3f scale = AZ::PackedVector3f(transform.mScale); @@ -56,14 +41,13 @@ namespace ExporterLib #endif // create the node chunk and copy over the information - EMotionFX::FileFormat::Actor_Node nodeChunk; - memset(&nodeChunk, 0, sizeof(EMotionFX::FileFormat::Actor_Node)); + EMotionFX::FileFormat::Actor_Node2 nodeChunk; + memset(&nodeChunk, 0, sizeof(EMotionFX::FileFormat::Actor_Node2)); CopyVector(nodeChunk.mLocalPos, position); CopyQuaternion(nodeChunk.mLocalQuat, rotation); CopyVector(nodeChunk.mLocalScale, scale); - //nodeChunk.mImportanceFactor = FLT_MAX;//importance; nodeChunk.mNumChilds = numChilds; nodeChunk.mParentIndex = parentIndex; @@ -98,10 +82,6 @@ namespace ExporterLib nodeChunk.mNodeFlags &= ~EMotionFX::Node::ENodeFlags::FLAG_CRITICAL; } - // OBB - WriteObbToNodeChunk(nodeChunk, actor->GetNodeOBB(node->GetNodeIndex())); - - // log the node chunk information MCore::LogDetailedInfo("- Node: name='%s' index=%i", actor->GetSkeleton()->GetNode(nodeIndex)->GetName(), nodeIndex); if (parentIndex == MCORE_INVALIDINDEX32) @@ -140,19 +120,13 @@ namespace ExporterLib ConvertUnsignedInt(&nodeChunk.mNumChilds, targetEndianType); ConvertUnsignedInt(&nodeChunk.mSkeletalLODs, targetEndianType); - for (uint32 j = 0; j < 16; ++j) - { - ConvertFloat(&nodeChunk.mOBB[j], targetEndianType); - } - // write it - file->Write(&nodeChunk, sizeof(EMotionFX::FileFormat::Actor_Node)); + file->Write(&nodeChunk, sizeof(EMotionFX::FileFormat::Actor_Node2)); // write the name of the node and parent SaveString(node->GetName(), file, targetEndianType); } - void SaveNodes(MCore::Stream* file, EMotionFX::Actor* actor, MCore::Endian::EEndianType targetEndianType) { uint32 i; @@ -167,10 +141,10 @@ namespace ExporterLib // chunk information EMotionFX::FileFormat::FileChunk chunkHeader; chunkHeader.mChunkID = EMotionFX::FileFormat::ACTOR_CHUNK_NODES; - chunkHeader.mVersion = 1; + chunkHeader.mVersion = 2; // get the nodes chunk size - chunkHeader.mSizeInBytes = sizeof(EMotionFX::FileFormat::Actor_Nodes) + numNodes * sizeof(EMotionFX::FileFormat::Actor_Node); + chunkHeader.mSizeInBytes = sizeof(EMotionFX::FileFormat::Actor_Nodes2) + numNodes * sizeof(EMotionFX::FileFormat::Actor_Node2); for (i = 0; i < numNodes; i++) { chunkHeader.mSizeInBytes += GetStringChunkSize(actor->GetSkeleton()->GetNode(i)->GetName()); @@ -181,23 +155,15 @@ namespace ExporterLib file->Write(&chunkHeader, sizeof(EMotionFX::FileFormat::FileChunk)); // nodes chunk - EMotionFX::FileFormat::Actor_Nodes nodesChunk; + EMotionFX::FileFormat::Actor_Nodes2 nodesChunk; nodesChunk.mNumNodes = numNodes; nodesChunk.mNumRootNodes = actor->GetSkeleton()->GetNumRootNodes(); - nodesChunk.mStaticBoxMin.mX = actor->GetStaticAabb().GetMin().GetX(); - nodesChunk.mStaticBoxMin.mY = actor->GetStaticAabb().GetMin().GetY(); - nodesChunk.mStaticBoxMin.mZ = actor->GetStaticAabb().GetMin().GetZ(); - nodesChunk.mStaticBoxMax.mX = actor->GetStaticAabb().GetMax().GetX(); - nodesChunk.mStaticBoxMax.mY = actor->GetStaticAabb().GetMax().GetY(); - nodesChunk.mStaticBoxMax.mZ = actor->GetStaticAabb().GetMax().GetZ(); // endian conversion and write it ConvertUnsignedInt(&nodesChunk.mNumNodes, targetEndianType); ConvertUnsignedInt(&nodesChunk.mNumRootNodes, targetEndianType); - ConvertFileVector3(&nodesChunk.mStaticBoxMin, targetEndianType); - ConvertFileVector3(&nodesChunk.mStaticBoxMax, targetEndianType); - file->Write(&nodesChunk, sizeof(EMotionFX::FileFormat::Actor_Nodes)); + file->Write(&nodesChunk, sizeof(EMotionFX::FileFormat::Actor_Nodes2)); // write the nodes for (uint32 n = 0; n < numNodes; n++) diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ActorFileFormat.h b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ActorFileFormat.h index b8a5cc9616..402c70c8a1 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ActorFileFormat.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ActorFileFormat.h @@ -108,7 +108,7 @@ namespace EMotionFX // a node header // (not aligned) - struct Actor_Node + struct Actor_Node2 { FileQuaternion mLocalQuat; // the local rotation (before hierarchy) FileVector3 mLocalPos; // the local translation (before hierarchy) @@ -117,7 +117,6 @@ namespace EMotionFX uint32 mParentIndex;// parent node number, or 0xFFFFFFFF in case of a root node uint32 mNumChilds; // the number of child nodes uint8 mNodeFlags; // #1 bit boolean specifies whether we have to include this node in the bounds calculation or not - float mOBB[16]; // followed by: // string : node name (the unique name of the node) @@ -200,14 +199,11 @@ namespace EMotionFX // uint16 [mNumNodes] }; - // (aligned) - struct Actor_Nodes + struct Actor_Nodes2 { uint32 mNumNodes; uint32 mNumRootNodes; - FileVector3 mStaticBoxMin; - FileVector3 mStaticBoxMax; // followed by Actor_Node4[mNumNodes] or Actor_NODE5[mNumNodes] (for v2) }; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ChunkProcessors.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ChunkProcessors.cpp index 7e7a9ae1c2..ddb240841b 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ChunkProcessors.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ChunkProcessors.cpp @@ -355,12 +355,9 @@ namespace EMotionFX return mLoggingActive; } - //================================================================================================= - - // a chunk that contains all nodes in one chunk - bool ChunkProcessorActorNodes::Process(MCore::File* file, Importer::ImportParameters& importParams) + bool ChunkProcessorActorNodes2::Process(MCore::File* file, Importer::ImportParameters& importParams) { const MCore::Endian::EEndianType endianType = importParams.mEndianType; Actor* actor = importParams.mActor; @@ -369,28 +366,12 @@ namespace EMotionFX MCORE_ASSERT(actor); Skeleton* skeleton = actor->GetSkeleton(); - FileFormat::Actor_Nodes nodesHeader; - file->Read(&nodesHeader, sizeof(FileFormat::Actor_Nodes)); + FileFormat::Actor_Nodes2 nodesHeader; + file->Read(&nodesHeader, sizeof(FileFormat::Actor_Nodes2)); // convert endian MCore::Endian::ConvertUnsignedInt32(&nodesHeader.mNumNodes, endianType); MCore::Endian::ConvertUnsignedInt32(&nodesHeader.mNumRootNodes, endianType); - MCore::Endian::ConvertFloat(&nodesHeader.mStaticBoxMin.mX, endianType); - MCore::Endian::ConvertFloat(&nodesHeader.mStaticBoxMin.mY, endianType); - MCore::Endian::ConvertFloat(&nodesHeader.mStaticBoxMin.mZ, endianType); - MCore::Endian::ConvertFloat(&nodesHeader.mStaticBoxMax.mX, endianType); - MCore::Endian::ConvertFloat(&nodesHeader.mStaticBoxMax.mY, endianType); - MCore::Endian::ConvertFloat(&nodesHeader.mStaticBoxMax.mZ, endianType); - - // convert endian and coord system of the static box - AZ::Vector3 boxMin(nodesHeader.mStaticBoxMin.mX, nodesHeader.mStaticBoxMin.mY, nodesHeader.mStaticBoxMin.mZ); - AZ::Vector3 boxMax(nodesHeader.mStaticBoxMax.mX, nodesHeader.mStaticBoxMax.mY, nodesHeader.mStaticBoxMax.mZ); - - // build the box and set it - MCore::AABB staticBox; - staticBox.SetMin(boxMin); - staticBox.SetMax(boxMax); - actor->SetStaticAABB(staticBox); // pre-allocate space for the nodes actor->SetNumNodes(nodesHeader.mNumNodes); @@ -410,8 +391,8 @@ namespace EMotionFX for (uint32 n = 0; n < nodesHeader.mNumNodes; ++n) { // read the node header - FileFormat::Actor_Node nodeChunk; - file->Read(&nodeChunk, sizeof(FileFormat::Actor_Node)); + FileFormat::Actor_Node2 nodeChunk; + file->Read(&nodeChunk, sizeof(FileFormat::Actor_Node2)); // read the node name const char* nodeName = SharedHelperData::ReadString(file, importParams.mSharedData, endianType); @@ -420,7 +401,6 @@ namespace EMotionFX MCore::Endian::ConvertUnsignedInt32(&nodeChunk.mParentIndex, endianType); MCore::Endian::ConvertUnsignedInt32(&nodeChunk.mSkeletalLODs, endianType); MCore::Endian::ConvertUnsignedInt32(&nodeChunk.mNumChilds, endianType); - MCore::Endian::ConvertFloat(&nodeChunk.mOBB[0], endianType, 16); // show the name of the node, the parent and the number of children if (GetLogging()) @@ -453,11 +433,6 @@ namespace EMotionFX ConvertScale(&scale, endianType); ConvertQuaternion(&rot, endianType); - // make sure the input data is normalized - // TODO: this isn't really needed as we already normalized? - //rot.FastNormalize(); - //scaleRot.FastNormalize(); - // set the local transform Transform bindTransform; bindTransform.mPosition = pos; @@ -503,23 +478,6 @@ namespace EMotionFX skeleton->AddRootNode(nodeIndex); } - // OBB - AZ::Matrix4x4 obbMatrix4x4 = AZ::Matrix4x4::CreateFromRowMajorFloat16(nodeChunk.mOBB); - - const AZ::Vector3 obbCenter = obbMatrix4x4.GetTranslation(); - const AZ::Vector3 obbExtents = obbMatrix4x4.GetRowAsVector3(3); - - // initialize the OBB - MCore::OBB obb; - obb.SetCenter(obbCenter); - obb.SetExtents(obbExtents); - - // need to transpose to go from row major to column major - const AZ::Matrix3x3 obbMatrix3x3 = AZ::Matrix3x3::CreateFromMatrix4x4(obbMatrix4x4).GetTranspose(); - const AZ::Transform obbTransform = AZ::Transform::CreateFromMatrix3x3AndTranslation(obbMatrix3x3, obbExtents); - obb.SetTransformation(obbTransform); - actor->SetNodeOBB(nodeIndex, obb); - if (GetLogging()) { MCore::LogDetailedInfo(" - Position: x=%f, y=%f, z=%f", diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ChunkProcessors.h b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ChunkProcessors.h index 306e4af0c8..56822c6940 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ChunkProcessors.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ChunkProcessors.h @@ -256,7 +256,6 @@ namespace EMotionFX virtual ~ChunkProcessor(); }; - //------------------------------------------------------------------------------------------------- /** @@ -287,7 +286,7 @@ namespace EMotionFX EMFX_CHUNKPROCESSOR(ChunkProcessorActorInfo3, FileFormat::ACTOR_CHUNK_INFO, 3) EMFX_CHUNKPROCESSOR(ChunkProcessorActorProgMorphTarget, FileFormat::ACTOR_CHUNK_STDPROGMORPHTARGET, 1) EMFX_CHUNKPROCESSOR(ChunkProcessorActorNodeGroups, FileFormat::ACTOR_CHUNK_NODEGROUPS, 1) - EMFX_CHUNKPROCESSOR(ChunkProcessorActorNodes, FileFormat::ACTOR_CHUNK_NODES, 1) + EMFX_CHUNKPROCESSOR(ChunkProcessorActorNodes2, FileFormat::ACTOR_CHUNK_NODES, 2) EMFX_CHUNKPROCESSOR(ChunkProcessorActorProgMorphTargets, FileFormat::ACTOR_CHUNK_STDPMORPHTARGETS, 1) EMFX_CHUNKPROCESSOR(ChunkProcessorActorProgMorphTargets2, FileFormat::ACTOR_CHUNK_STDPMORPHTARGETS, 2) EMFX_CHUNKPROCESSOR(ChunkProcessorActorNodeMotionSources, FileFormat::ACTOR_CHUNK_NODEMOTIONSOURCES, 1) diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/Importer.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/Importer.cpp index 67cbb91c06..82da9ccd86 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/Importer.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/Importer.cpp @@ -352,7 +352,7 @@ namespace EMotionFX } // post create init - actor->PostCreateInit(actorSettings.mMakeGeomLODsCompatibleWithSkeletalLODs, false, actorSettings.mUnitTypeConvert); + actor->PostCreateInit(actorSettings.mMakeGeomLODsCompatibleWithSkeletalLODs, actorSettings.mUnitTypeConvert); } // close the file and return a pointer to the actor we loaded @@ -846,7 +846,7 @@ namespace EMotionFX RegisterChunkProcessor(aznew ChunkProcessorActorInfo3()); RegisterChunkProcessor(aznew ChunkProcessorActorProgMorphTarget()); RegisterChunkProcessor(aznew ChunkProcessorActorNodeGroups()); - RegisterChunkProcessor(aznew ChunkProcessorActorNodes()); + RegisterChunkProcessor(aznew ChunkProcessorActorNodes2()); RegisterChunkProcessor(aznew ChunkProcessorActorProgMorphTargets()); RegisterChunkProcessor(aznew ChunkProcessorActorProgMorphTargets2()); RegisterChunkProcessor(aznew ChunkProcessorActorNodeMotionSources()); From e9ef0a02ec30689e692da05575fa86dbdf4e79d2 Mon Sep 17 00:00:00 2001 From: evanchia Date: Wed, 4 Aug 2021 11:17:38 -0700 Subject: [PATCH 102/803] minor fixes for c++ retry command Signed-off-by: evanchia --- Code/Tools/AzTestRunner/src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Tools/AzTestRunner/src/main.cpp b/Code/Tools/AzTestRunner/src/main.cpp index 225975b654..d9ee727447 100644 --- a/Code/Tools/AzTestRunner/src/main.cpp +++ b/Code/Tools/AzTestRunner/src/main.cpp @@ -229,7 +229,7 @@ namespace AzTestRunner // Construct a retry command if the test fails if (result != 0) { - std::cout << "Retry command:\n " << argv[0] << " " << lib << " " << symbol << std::endl; + std::cout << "Retry command: " << std::endl << argv[0] << " " << lib << " " << symbol << std::endl; } // unload and reset the module here, because it needs to release resources that were used / activated in From a550827e978d97abb83c1bb4a03aaca4aa5ffdfd Mon Sep 17 00:00:00 2001 From: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> Date: Wed, 4 Aug 2021 14:32:15 -0400 Subject: [PATCH 103/803] Addressing PR Signed-off-by: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> --- .../Code/Source/Debug/MultiplayerDebugByteReporter.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.cpp b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.cpp index f69291013a..45305e3b39 100644 --- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.cpp +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.cpp @@ -43,7 +43,6 @@ namespace Multiplayer { if (m_count == 0) { - AZ_Warning("MultiplayerDebugByteReporter", m_totalBytes == 0, "Attempted to average bytes with a zero count."); return 0.0f; } @@ -158,7 +157,7 @@ namespace Multiplayer if (m_currentComponentReport == nullptr) { std::stringstream component; - component << "[" << std::setw(2) << std::setfill('0') << static_cast(index) << "]" << " " << componentName; + component << "[" << std::setw(2) << std::setfill('0') << aznumeric_cast(index) << "]" << " " << componentName; m_currentComponentReport = &m_componentReports[component.str().c_str()]; } From 4b817a6483560691a5f95a34355c87c8972b05ab Mon Sep 17 00:00:00 2001 From: Shirang Jia Date: Wed, 4 Aug 2021 17:57:47 -0700 Subject: [PATCH 104/803] Include build failure root cause in email notification (#2491) Signed-off-by: shiranj --- scripts/build/Jenkins/Jenkinsfile | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/scripts/build/Jenkins/Jenkinsfile b/scripts/build/Jenkins/Jenkinsfile index 70618fea78..e693168af0 100644 --- a/scripts/build/Jenkins/Jenkinsfile +++ b/scripts/build/Jenkins/Jenkinsfile @@ -577,13 +577,19 @@ finally { ) } node('controller') { - step([ - $class: 'Mailer', - notifyEveryUnstableBuild: true, - recipients: emailextrecipients([ + if("${currentBuild.currentResult}" == "SUCCESS") { + emailBody = "${BUILD_URL}\nSuccess!" + } else { + buildFailure = tm('${BUILD_FAILURE_ANALYZER}') + emailBody = "${BUILD_URL}\n${buildFailure}!" + } + emailext ( + body: "${emailBody}", + subject: "${currentBuild.currentResult}: ${JOB_NAME} - Build # ${BUILD_NUMBER}", + recipientProviders: [ [$class: 'RequesterRecipientProvider'] - ]) - ]) + ] + ) } } catch(Exception e) { } From c979ab03385f19970e1a422b23a6d2d9e09d888f Mon Sep 17 00:00:00 2001 From: dmcdiar Date: Wed, 4 Aug 2021 18:26:43 -0700 Subject: [PATCH 105/803] Keep the mutex locked while processing pending notifies. Signed-off-by: dmcdiar --- .../RHI/Code/Include/Atom/RHI/ObjectCollector.h | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/ObjectCollector.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/ObjectCollector.h index d79a86afea..3f9fed056f 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/ObjectCollector.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/ObjectCollector.h @@ -179,7 +179,6 @@ namespace AZ { m_pendingGarbage.push_back({ AZStd::move(m_pendingObjects), m_currentIteration }); } - m_mutex.unlock(); if (m_pendingNotifies.size()) { @@ -200,25 +199,19 @@ namespace AZ } latestGarbage.m_notifies.insert(latestGarbage.m_notifies.end(), m_pendingNotifies.begin(), m_pendingNotifies.end()); - - m_mutex.lock(); - m_pendingNotifies.clear(); - m_mutex.unlock(); - } else { // garbage queue is empty, notify now - m_mutex.lock(); for (auto& notifyFunction : m_pendingNotifies) { notifyFunction(); } - - m_pendingNotifies.clear(); - m_mutex.unlock(); } + + m_pendingNotifies.clear(); } + m_mutex.unlock(); size_t objectCount = 0; size_t i = 0; From baab204c0bf79a7932ad5ddbb57931e68c47802c Mon Sep 17 00:00:00 2001 From: Kyle B Date: Thu, 5 Aug 2021 00:07:54 -0700 Subject: [PATCH 106/803] updated Mock with new interface values Signed-off-by: Kyle B --- .../Feature/Common/Code/Mocks/MockMeshFeatureProcessor.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Gems/Atom/Feature/Common/Code/Mocks/MockMeshFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Mocks/MockMeshFeatureProcessor.h index 72e547fc1b..0eea0df514 100644 --- a/Gems/Atom/Feature/Common/Code/Mocks/MockMeshFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Mocks/MockMeshFeatureProcessor.h @@ -32,9 +32,13 @@ namespace UnitTest MOCK_METHOD2(SetLocalAabb, void(const MeshHandle&, const AZ::Aabb&)); MOCK_CONST_METHOD1(GetLocalAabb, AZ::Aabb(const MeshHandle&)); MOCK_METHOD2(SetSortKey, void (const MeshHandle&, AZ::RHI::DrawItemSortKey)); - MOCK_METHOD1(GetSortKey, AZ::RHI::DrawItemSortKey(const MeshHandle&)); + MOCK_CONST_METHOD1(GetSortKey, AZ::RHI::DrawItemSortKey(const MeshHandle&)); MOCK_METHOD2(SetLodOverride, void(const MeshHandle&, AZ::RPI::Cullable::LodOverride)); - MOCK_METHOD1(GetLodOverride, AZ::RPI::Cullable::LodOverride(const MeshHandle&)); + MOCK_CONST_METHOD1(GetLodOverride, AZ::RPI::Cullable::LodOverride(const MeshHandle&)); + MOCK_METHOD2(SetMinimumScreenCoverage, void(const MeshHandle&, float)); + MOCK_CONST_METHOD1(GetMinimumScreenCoverage, float(const MeshHandle&)); + MOCK_METHOD2(SetQualityDecayRate, void(const MeshHandle&, float)); + MOCK_CONST_METHOD1(GetQualityDecayRate, float(const MeshHandle&)); MOCK_METHOD2(AcquireMesh, MeshHandle (const AZ::Render::MeshHandleDescriptor&, const AZ::Render::MaterialAssignmentMap&)); MOCK_METHOD2(AcquireMesh, MeshHandle (const AZ::Render::MeshHandleDescriptor&, const AZ::Data::Instance&)); MOCK_METHOD2(SetRayTracingEnabled, void (const MeshHandle&, bool)); From d134deee1dccdfe4f4af64fcafe289377fe02316 Mon Sep 17 00:00:00 2001 From: Benjamin Jillich Date: Thu, 5 Aug 2021 15:07:14 +0200 Subject: [PATCH 107/803] Add bounding volume expansion to the actor instance Signed-off-by: Benjamin Jillich --- .../Code/EMotionFX/Source/ActorInstance.cpp | 343 ++++-------------- .../Code/EMotionFX/Source/ActorInstance.h | 84 ++--- 2 files changed, 95 insertions(+), 332 deletions(-) diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.cpp index b2091f967f..162d826ca4 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.cpp @@ -67,7 +67,7 @@ namespace EMotionFX mMotionSamplingTimer = 0.0f; mTrajectoryDelta.IdentityWithZeroScale(); - mStaticAABB.Init(); + m_staticAabb = AZ::Aabb::CreateNull(); mAnimGraphInstance = nullptr; @@ -137,15 +137,15 @@ namespace EMotionFX UpdateDependencies(); // update the static based AABB dimensions - mStaticAABB = mActor->GetStaticAABB(); - if (mStaticAABB.CheckIfIsValid() == false) + m_staticAabb = mActor->GetStaticAabb(); + if (!m_staticAabb.IsValid()) { UpdateMeshDeformers(0.0f, true); // TODO: not really thread safe because of shared meshes, although it probably will output correctly - UpdateStaticBasedAABBDimensions(); + UpdateStaticBasedAabbDimensions(); } // update the bounds - UpdateBounds(0, mBoundsUpdateType, 1); + UpdateBounds(/*lodLevel=*/0, mBoundsUpdateType); // register it GetActorManager().RegisterActorInstance(this); @@ -254,12 +254,12 @@ namespace EMotionFX UpdateAttachments(); // update the attachment parent matrices // update the bounds when needed - if (GetBoundsUpdateEnabled() && mBoundsUpdateType != BOUNDS_MESH_BASED) + if (GetBoundsUpdateEnabled()) { mBoundsUpdatePassedTime += timePassedInSeconds; if (mBoundsUpdatePassedTime >= mBoundsUpdateFrequency) { - UpdateBounds(mLODLevel, BOUNDS_NODE_BASED, mBoundsUpdateItemFreq); + UpdateBounds(mLODLevel, mBoundsUpdateType, mBoundsUpdateItemFreq); mBoundsUpdatePassedTime = 0.0f; } } @@ -354,7 +354,7 @@ namespace EMotionFX } // update the bounds when needed - if (GetBoundsUpdateEnabled() && mBoundsUpdateType != BOUNDS_MESH_BASED) + if (GetBoundsUpdateEnabled()) { mBoundsUpdatePassedTime += timePassedInSeconds; if (mBoundsUpdatePassedTime >= mBoundsUpdateFrequency) @@ -407,18 +407,6 @@ namespace EMotionFX stack->Update(this, node, timePassedInSeconds, processDisabledDeformers); } } - - // Update the bounds when we are set to use mesh based bounds. - if (GetBoundsUpdateEnabled() && - GetBoundsUpdateType() == BOUNDS_MESH_BASED) - { - mBoundsUpdatePassedTime += timePassedInSeconds; - if (mBoundsUpdatePassedTime >= mBoundsUpdateFrequency) - { - UpdateBounds(mLODLevel, mBoundsUpdateType, mBoundsUpdateItemFreq); - mBoundsUpdatePassedTime = 0.0f; - } - } } // Update the mesh morph deformers, which updates the vertex positions on the CPU, so performing CPU morphing. @@ -439,18 +427,6 @@ namespace EMotionFX stack->UpdateByModifierType(this, node, timePassedInSeconds, MorphMeshDeformer::TYPE_ID, true, processDisabledDeformers); } } - - // Update the bounds when we are set to use mesh based bounds. - if (GetBoundsUpdateEnabled() && - GetBoundsUpdateType() == BOUNDS_MESH_BASED) - { - mBoundsUpdatePassedTime += timePassedInSeconds; - if (mBoundsUpdatePassedTime >= mBoundsUpdateFrequency) - { - UpdateBounds(mLODLevel, mBoundsUpdateType, mBoundsUpdateItemFreq); - mBoundsUpdatePassedTime = 0.0f; - } - } } void ActorInstance::PostPhysicsUpdate(float timePassedInSeconds) @@ -639,118 +615,40 @@ namespace EMotionFX { // calculate the static based AABB case BOUNDS_STATIC_BASED: - CalcStaticBasedAABB(&mAABB); + CalcStaticBasedAabb(&m_aabb); break; // based on the world space positions of the nodes (least accurate, but fastest) case BOUNDS_NODE_BASED: - CalcNodeBasedAABB(&mAABB, itemFrequency); - break; - - // based on the world space positions of the vertices of the collision meshes (faster and more accurate than mesh based) - case BOUNDS_COLLISIONMESH_BASED: - CalcCollisionMeshBasedAABB(geomLODLevel, &mAABB, itemFrequency); + CalcNodeBasedAabb(&m_aabb, itemFrequency); break; // based on the world space positions of the vertices of the meshes (most accurate) case BOUNDS_MESH_BASED: - CalcMeshBasedAABB(geomLODLevel, &mAABB, itemFrequency); - break; - - // based on the world space positions of the vertices of the meshes (most accurate) - case BOUNDS_NODEOBB_BASED: - CalcNodeOBBBasedAABB(&mAABB, itemFrequency); - break; - - case BOUNDS_NODEOBBFAST_BASED: - CalcNodeOBBBasedAABBFast(&mAABB, itemFrequency); + UpdateMeshDeformers(0.0f); + CalcMeshBasedAabb(geomLODLevel, &m_aabb, itemFrequency); break; // when we're dealing with an unspecified bounding volume update method default: MCore::LogInfo("*** EMotionFX::ActorInstance::UpdateBounds() - Unknown boundsType specified! (%d) ***", (uint32)boundsType); } - } - // calculate the axis aligned bounding box that contains the object oriented boxes of all nodes - void ActorInstance::CalcNodeOBBBasedAABBFast(MCore::AABB* outResult, uint32 nodeFrequency) - { - // init the axis aligned bounding box - outResult->Init(); - - const Pose* pose = mTransformData->GetCurrentPose(); - const Skeleton* skeleton = mActor->GetSkeleton(); - - // for all nodes, encapsulate the world space positions - uint16 nodeNr; - const uint32 numNodes = GetNumEnabledNodes(); - for (uint32 i = 0; i < numNodes; i += nodeFrequency) + // Expand the bounding volume by a tolerance area in case set. + if (m_boundsExpandBy > 0.0f) { - nodeNr = GetEnabledNode(i); - Node* node = skeleton->GetNode(nodeNr); - if (node->GetIncludeInBoundsCalc()) - { - const MCore::OBB& obb = mActor->GetNodeOBB(nodeNr); - if (obb.CheckIfIsValid() == false) - { - continue; - } - - // calculate the corner points of the node in local space - AZ::Vector3 minPoint, maxPoint; - obb.CalcMinMaxPoints(&minPoint, &maxPoint); - - // encapsulate the results in the AABB box - const Transform worldTransform = pose->GetWorldSpaceTransform(nodeNr); - outResult->Encapsulate(worldTransform.TransformPoint(minPoint)); - outResult->Encapsulate(worldTransform.TransformPoint(maxPoint)); - } - } - } - - // more accurate node obb based method that uses the 8 corner points of the obb - void ActorInstance::CalcNodeOBBBasedAABB(MCore::AABB* outResult, uint32 nodeFrequency) - { - // init the axis aligned bounding box - outResult->Init(); - - const Pose* pose = mTransformData->GetCurrentPose(); - const Skeleton* skeleton = mActor->GetSkeleton(); - - // for all nodes, encapsulate the world space positions - AZ::Vector3 cornerPoints[8]; - uint16 nodeNr; - const uint32 numNodes = GetNumEnabledNodes(); - for (uint32 i = 0; i < numNodes; i += nodeFrequency) - { - nodeNr = GetEnabledNode(i); - Node* node = skeleton->GetNode(nodeNr); - if (node->GetIncludeInBoundsCalc()) - { - const MCore::OBB& obb = mActor->GetNodeOBB(nodeNr); - if (obb.CheckIfIsValid() == false) - { - continue; - } - - // calculate the 8 corner points - obb.CalcCornerPoints(cornerPoints); - - const Transform worldTransform = pose->GetWorldSpaceTransform(nodeNr); - - // encapsulate all OBB world space corner points inside the AABB - for (uint32 p = 0; p < 8; ++p) - { - outResult->Encapsulate(worldTransform.TransformPoint(cornerPoints[p])); - } - } + const AZ::Vector3 center = m_aabb.GetCenter(); + const AZ::Vector3 halfExtents = m_aabb.GetExtents() * 0.5f; + const AZ::Vector3 scaledHalfExtents = halfExtents * (1.0f + m_boundsExpandBy); + m_aabb.SetMin(center - scaledHalfExtents); + m_aabb.SetMax(center + scaledHalfExtents); } } // calculate the axis aligned bounding box based on the world space positions of the nodes - void ActorInstance::CalcNodeBasedAABB(MCore::AABB* outResult, uint32 nodeFrequency) + void ActorInstance::CalcNodeBasedAabb(AZ::Aabb* outResult, uint32 nodeFrequency) { - outResult->Init(); + *outResult = AZ::Aabb::CreateNull(); const Pose* pose = mTransformData->GetCurrentPose(); const Skeleton* skeleton = mActor->GetSkeleton(); @@ -763,16 +661,15 @@ namespace EMotionFX nodeNr = GetEnabledNode(i); if (skeleton->GetNode(nodeNr)->GetIncludeInBoundsCalc()) { - outResult->Encapsulate(pose->GetWorldSpaceTransform(nodeNr).mPosition); + outResult->AddPoint(pose->GetWorldSpaceTransform(nodeNr).mPosition); } } } // calculate the AABB that contains all world space vertices of all meshes - void ActorInstance::CalcMeshBasedAABB(uint32 geomLODLevel, MCore::AABB* outResult, uint32 vertexFrequency) + void ActorInstance::CalcMeshBasedAabb(uint32 geomLODLevel, AZ::Aabb* outResult, uint32 vertexFrequency) { - // init the axis aligned bounding box - outResult->Init(); + *outResult = AZ::Aabb::CreateNull(); const Pose* pose = mTransformData->GetCurrentPose(); const Skeleton* skeleton = mActor->GetSkeleton(); @@ -800,52 +697,9 @@ namespace EMotionFX const Transform worldTransform = pose->GetMeshNodeWorldSpaceTransform(geomLODLevel, nodeNr); // calculate and encapsulate the mesh bounds inside the total mesh box - MCore::AABB meshBox; - mesh->CalcAABB(&meshBox, worldTransform, vertexFrequency); - outResult->Encapsulate(meshBox); - } - } - - void ActorInstance::CalcCollisionMeshBasedAABB(uint32 geomLODLevel, MCore::AABB* outResult, uint32 vertexFrequency) - { - // init the axis aligned bounding box - outResult->Init(); - - const Pose* pose = mTransformData->GetCurrentPose(); - const Skeleton* skeleton = mActor->GetSkeleton(); - - // for all nodes, encapsulate the world space positions - uint16 nodeNr; - const uint32 numNodes = GetNumEnabledNodes(); - for (uint32 i = 0; i < numNodes; ++i) - { - nodeNr = GetEnabledNode(i); - Node* node = skeleton->GetNode(nodeNr); - - // skip nodes without collision meshes - Mesh* mesh = mActor->GetMesh(geomLODLevel, nodeNr); - if (mesh == nullptr) - { - continue; - } - - if (mesh->GetIsCollisionMesh() == false) - { - continue; - } - - // if this node should be excluded - if (node->GetIncludeInBoundsCalc() == false) - { - continue; - } - - const Transform worldTransform = pose->GetMeshNodeWorldSpaceTransform(geomLODLevel, nodeNr); - - // calculate and encapsulate the mesh bounds inside the total mesh box - MCore::AABB meshBox; - mesh->CalcAABB(&meshBox, worldTransform, vertexFrequency); - outResult->Encapsulate(meshBox); + AZ::Aabb meshBox; + mesh->CalcAabb(&meshBox, worldTransform, vertexFrequency); + outResult->AddAabb(meshBox); } } @@ -1567,111 +1421,45 @@ namespace EMotionFX } // update the static based aabb dimensions - void ActorInstance::UpdateStaticBasedAABBDimensions() + void ActorInstance::UpdateStaticBasedAabbDimensions() { - // backup the transform Transform orgTransform = GetLocalSpaceTransform(); - //------------------------------------- - - // reset position and scale SetLocalSpacePosition(AZ::Vector3::CreateZero()); + EMFX_SCALECODE(SetLocalSpaceScale(AZ::Vector3(1.0f, 1.0f, 1.0f));) - EMFX_SCALECODE( - SetLocalSpaceScale(AZ::Vector3(1.0f, 1.0f, 1.0f));) + UpdateTransformations(0.0f, true); + UpdateMeshDeformers(0.0f); - // rotate over x, y and z axis - AZ::Vector3 boxMin(FLT_MAX, FLT_MAX, FLT_MAX); - AZ::Vector3 boxMax(-FLT_MAX, -FLT_MAX, -FLT_MAX); - for (uint32 axis = 0; axis < 3; axis++) + // calculate the aabb of this + if (mActor->CheckIfHasMeshes(0)) { - for (uint32 i = 0; i < 360; i += 45) // steps of 45 degrees - { - // rotate a given amount of degrees over the axis we are currently testing - AZ::Vector3 axisVector(0.0f, 0.0f, 0.0f); - axisVector.SetElement(axis, 1.0f); - const float angle = static_cast(i); - SetLocalSpaceRotation(MCore::CreateFromAxisAndAngle(axisVector, MCore::Math::DegreesToRadians(angle))); - - UpdateTransformations(0.0f, true); - UpdateMeshDeformers(0.0f); - - // calculate the aabb of this - if (mActor->CheckIfHasMeshes(0)) - { - CalcMeshBasedAABB(0, &mStaticAABB); - } - else - { - CalcNodeBasedAABB(&mStaticAABB); - } - - // find the minimum and maximum - const AZ::Vector3& curMin = mStaticAABB.GetMin(); - const AZ::Vector3& curMax = mStaticAABB.GetMax(); - if (curMin.GetX() < boxMin.GetX()) - { - boxMin.SetX(curMin.GetX()); - } - if (curMin.GetY() < boxMin.GetY()) - { - boxMin.SetY(curMin.GetY()); - } - if (curMin.GetZ() < boxMin.GetZ()) - { - boxMin.SetZ(curMin.GetZ()); - } - if (curMax.GetX() > boxMax.GetX()) - { - boxMax.SetX(curMax.GetX()); - } - if (curMax.GetY() > boxMax.GetY()) - { - boxMax.SetY(curMax.GetY()); - } - if (curMax.GetZ() > boxMax.GetZ()) - { - boxMax.SetZ(curMax.GetZ()); - } - } + CalcMeshBasedAabb(0, &m_staticAabb); + } + else + { + CalcNodeBasedAabb(&m_staticAabb); } - mStaticAABB.SetMin(boxMin); - mStaticAABB.SetMax(boxMax); - - /* - // calculate the center point of the box - const AZ::Vector3 center = mStaticAABB.CalcMiddle(); - - // find the maximum of the width, height and depth - const float maxDim = MCore::Max3( mStaticAABB.CalcWidth(), mStaticAABB.CalcHeight(), mStaticAABB.CalcDepth() ) * 0.5f; - - // make width, height and depth the same as its maximum - mStaticAABB.SetMin( center + AZ::Vector3(-maxDim, -maxDim, -maxDim) ); - mStaticAABB.SetMax( center + AZ::Vector3( maxDim, maxDim, maxDim) ); - */ - //------------------------------------- - - // restore the transform mLocalTransform = orgTransform; } // calculate the moved static based aabb - void ActorInstance::CalcStaticBasedAABB(MCore::AABB* outResult) + void ActorInstance::CalcStaticBasedAabb(AZ::Aabb* outResult) { if (GetIsSkinAttachment()) { - mSelfAttachment->GetAttachToActorInstance()->CalcStaticBasedAABB(outResult); + mSelfAttachment->GetAttachToActorInstance()->CalcStaticBasedAabb(outResult); return; } - *outResult = mStaticAABB; + *outResult = m_staticAabb; EMFX_SCALECODE( - outResult->SetMin(mStaticAABB.GetMin() * mWorldTransform.mScale); - outResult->SetMax(mStaticAABB.GetMax() * mWorldTransform.mScale);) + outResult->SetMin(m_staticAabb.GetMin() * mWorldTransform.mScale); + outResult->SetMax(m_staticAabb.GetMax() * mWorldTransform.mScale);) outResult->Translate(mWorldTransform.mPosition); } - // adjust the animgraph instance + // adjust the anim graph instance void ActorInstance::SetAnimGraphInstance(AnimGraphInstance* instance) { mAnimGraphInstance = instance; @@ -1774,29 +1562,29 @@ namespace EMotionFX SetFlag(BOOL_BOUNDSUPDATEENABLED, enable); } - void ActorInstance::SetStaticBasedAABB(const MCore::AABB& aabb) + void ActorInstance::SetStaticBasedAabb(const AZ::Aabb& aabb) { - mStaticAABB = aabb; + m_staticAabb = aabb; } - void ActorInstance::GetStaticBasedAABB(MCore::AABB* outAABB) + void ActorInstance::GetStaticBasedAabb(AZ::Aabb* outAabb) { - *outAABB = mStaticAABB; + *outAabb = m_staticAabb; } - const MCore::AABB& ActorInstance::GetStaticBasedAABB() const + const AZ::Aabb& ActorInstance::GetStaticBasedAabb() const { - return mStaticAABB; + return m_staticAabb; } - const MCore::AABB& ActorInstance::GetAABB() const + const AZ::Aabb& ActorInstance::GetAabb() const { - return mAABB; + return m_aabb; } - void ActorInstance::SetAABB(const MCore::AABB& aabb) + void ActorInstance::SetAabb(const AZ::Aabb& aabb) { - mAABB = aabb; + m_aabb = aabb; } uint32 ActorInstance::GetNumAttachments() const @@ -2018,23 +1806,20 @@ namespace EMotionFX mVisualizeScale = 0.0f; UpdateMeshDeformers(0.0f); - MCore::AABB box; - CalcCollisionMeshBasedAABB(0, &box); - if (box.CheckIfIsValid()) + AZ::Aabb box = AZ::Aabb::CreateNull(); + + CalcNodeBasedAabb(&box); + if (box.IsValid()) { - mVisualizeScale = MCore::Max(mVisualizeScale, box.CalcRadius()); + const float boxRadius = AZ::Vector3(box.GetMax() - box.GetMin()).GetLength() * 0.5f; + mVisualizeScale = MCore::Max(mVisualizeScale, boxRadius); } - CalcNodeBasedAABB(&box); - if (box.CheckIfIsValid()) + CalcMeshBasedAabb(0, &box); + if (box.IsValid()) { - mVisualizeScale = MCore::Max(mVisualizeScale, box.CalcRadius()); - } - - CalcMeshBasedAABB(0, &box); - if (box.CheckIfIsValid()) - { - mVisualizeScale = MCore::Max(mVisualizeScale, box.CalcRadius()); + const float boxRadius = AZ::Vector3(box.GetMax() - box.GetMin()).GetLength() * 0.5f; + mVisualizeScale = MCore::Max(mVisualizeScale, boxRadius); } mVisualizeScale *= 0.01f; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.h b/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.h index 3567175d6d..4488a1386f 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.h @@ -60,9 +60,6 @@ namespace EMotionFX { BOUNDS_NODE_BASED = 0, /**< Calculate the bounding volumes based on the world space node positions. */ BOUNDS_MESH_BASED = 1, /**< Calculate the bounding volumes based on the world space vertex positions. */ - BOUNDS_COLLISIONMESH_BASED = 2, /**< Calculate the bounding volumes based on the world space collision mesh vertex positions. */ - BOUNDS_NODEOBB_BASED = 3, /**< Calculate the bounding volumes based on the oriented bounding boxes of the nodes. Uses all 8 corner points of the individual node OBB boxes. */ - BOUNDS_NODEOBBFAST_BASED = 4, /**< Calculate the bounding volumes based on the oriented bounding boxes of the nodes. Uses the min and max point of the individual node OBB boxes. This is less accurate but faster. */ BOUNDS_STATIC_BASED = 5 /**< Calculate the bounding volumes based on an approximate box, based on the mesh bounds, and move this box along with the actor instance position. */ }; @@ -348,6 +345,14 @@ namespace EMotionFX */ EBoundsType GetBoundsUpdateType() const; + /** + * Get the normalized percentage that the calculated bounding box is expanded with. + * This can be used to add a tolerance area to the calculated bounding box to avoid clipping the character too early. + * A static bounding box together with the expansion is the recommended way for maximum performance. + * @result A value of 1.0 means that the calculated bounding box won't be expanded at all, while 2.0 means it is twice the size. + */ + float GetExpandBoundsBy() const { return m_boundsExpandBy; } + /** * Get the bounding volume auto-update item frequency. * A value of 1 would mean every node or vertex will be taken into account in the bounds calculation. @@ -376,11 +381,19 @@ namespace EMotionFX /** * Set the bounding volume auto-update type. * This can be either based on the node's world space positions, the mesh vertex world space positions, or the - * collision mesh vertex world space postitions. + * collision mesh vertex world space positions. * @param bType The bounding volume update type. */ void SetBoundsUpdateType(EBoundsType bType); + /** + * Set the normalized percentage that the calculated bounding box should be expanded with. + * This can be used to add a tolerance area to the calculated bounding box to avoid clipping the character too early. + * A static bounding box together with the expansion is the recommended way for maximum performance. + * @param[in] expandBy A value of 1.0 means that the calculated bounding box won't be expanded at all, while 2.0 means it will be twice the size. + */ + void SetExpandBoundsBy(float expandBy) { m_boundsExpandBy = expandBy; } + /** * Set the bounding volume auto-update item frequency. * A value of 1 would mean every node or vertex will be taken into account in the bounds calculation. @@ -420,11 +433,11 @@ namespace EMotionFX * This function is generally only executed once, when creating the actor instance. * The CalcStaticBasedAABB function then simply translates this box along with the actor instance's position. */ - void UpdateStaticBasedAABBDimensions(); + void UpdateStaticBasedAabbDimensions(); - void SetStaticBasedAABB(const MCore::AABB& aabb); - void GetStaticBasedAABB(MCore::AABB* outAABB); - const MCore::AABB& GetStaticBasedAABB() const; + void SetStaticBasedAabb(const AZ::Aabb& aabb); + void GetStaticBasedAabb(AZ::Aabb* outAabb); + const AZ::Aabb& GetStaticBasedAabb() const; /** * Calculate an axis aligned bounding box that can be used as static AABB. It is static in the way that the volume does not change. It can however be translated as it will move @@ -434,7 +447,7 @@ namespace EMotionFX * If there are no meshes present, a widened node based box will be used instead as basis. * @param outResult The resulting bounding box, moved along with the actor instance's position. */ - void CalcStaticBasedAABB(MCore::AABB* outResult); + void CalcStaticBasedAabb(AZ::Aabb* outResult); /** * Calculate the axis aligned bounding box based on the world space positions of the nodes. @@ -442,7 +455,7 @@ namespace EMotionFX * @param nodeFrequency This will include every "nodeFrequency"-th node. So a value of 1 will include all nodes. A value of 2 would * process every second node, meaning that half of the nodes will be skipped. A value of 4 would process every 4th node, etc. */ - void CalcNodeBasedAABB(MCore::AABB* outResult, uint32 nodeFrequency = 1); + void CalcNodeBasedAabb(AZ::Aabb* outResult, uint32 nodeFrequency = 1); /** * Calculate the axis aligned bounding box based on the world space vertex coordinates of the meshes. @@ -452,43 +465,7 @@ namespace EMotionFX * @param vertexFrequency This includes every "vertexFrequency"-th vertex. So for example a value of 2 would skip every second vertex and * so will process half of the vertices. A value of 4 would process only each 4th vertex, etc. */ - void CalcMeshBasedAABB(uint32 geomLODLevel, MCore::AABB* outResult, uint32 vertexFrequency = 1); - - /** - * Calculate the axis aligned bounding box based on the world space vertex coordinates of the collision meshes. - * If the actor has no collision meshes, the created box will be invalid. - * @param geomLODLevel The geometry LOD level to calculate the box for. - * @param outResult The AABB where this method should store the resulting box in. - * @param vertexFrequency This includes every "vertexFrequency"-th vertex. So for example a value of 2 would skip every second vertex and - * so will process half of the vertices. A value of 4 would process only each 4th vertex, etc. - */ - void CalcCollisionMeshBasedAABB(uint32 geomLODLevel, MCore::AABB* outResult, uint32 vertexFrequency = 1); - - /** - * Calculate the axis aligned bounding box that contains the object oriented boxes of all nodes. - * The OBB (oriented bounding box) of each node is calculated by fitting an OBB to its mesh. - * The OBB of nodes that act as bones and have no meshes themselves are fit to the set of vertices that are influenced by the given bone. - * This method will give more accurate results than the CalcNodeBasedAABB method in trade for a bit lower performance. - * Also one big advantage of this method is that you can use these bounds for hit detection, without having artists setup collision meshes. - * @param outResult The AABB where this method should store the resulting box in. - * @param nodeFrequency This will include every "nodeFrequency"-th node. So a value of 1 will include all nodes. A value of 2 would - * process every second node, meaning that half of the nodes will be skipped. A value of 4 would process every 4th node, etc. - */ - void CalcNodeOBBBasedAABB(MCore::AABB* outResult, uint32 nodeFrequency = 1); - - /** - * Calculate the axis aligned bounding box that contains the object oriented boxes of all nodes. - * The OBB (oriented bounding box) of each node is calculated by fitting an OBB to its mesh. - * The OBB of nodes that act as bones and have no meshes themselves are fit to the set of vertices that are influenced by the given bone. - * This method will give more accurate results than the CalcNodeBasedAABB method in trade for a bit lower performance. - * Also one big advantage of this method is that you can use these bounds for hit detection, without having artists setup collision meshes. - * NOTE: this is a faster variant from the CalcNodeOBBBasedAABB method. The difference is that this method only transforms the min and max point of the box in local space. - * Therefore it is less accurate, but it might still be enough. The original CalcNodeOBBBasedAABB method calculates the 8 corner points of the node obb boxes. - * @param outResult The AABB where this method should store the resulting box in. - * @param nodeFrequency This will include every "nodeFrequency"-th node. So a value of 1 will include all nodes. A value of 2 would - * process every second node, meaning that half of the nodes will be skipped. A value of 4 would process every 4th node, etc. - */ - void CalcNodeOBBBasedAABBFast(MCore::AABB* outResult, uint32 nodeFrequency = 1); + void CalcMeshBasedAabb(uint32 geomLODLevel, AZ::Aabb* outResult, uint32 vertexFrequency = 1); /** * Get the axis aligned bounding box. @@ -496,14 +473,14 @@ namespace EMotionFX * That method is also called automatically when the bounds auto-update feature is enabled. * @result The axis aligned bounding box. */ - const MCore::AABB& GetAABB() const; + const AZ::Aabb& GetAabb() const; /** * Set the axis aligned bounding box. * Please beware that this box will get automatically overwritten when automatic bounds update is enabled. * @param aabb The axis aligned bounding box to store. */ - void SetAABB(const MCore::AABB& aabb); + void SetAabb(const AZ::Aabb& aabb); //------------------------------------------------------------------------------------------- @@ -887,8 +864,8 @@ namespace EMotionFX private: TransformData* mTransformData; /**< The transformation data for this instance. */ - MCore::AABB mAABB; /**< The axis aligned bounding box. */ - MCore::AABB mStaticAABB; /**< A static pre-calculated bounding box, which we can move along with the position of the actor instance, and use for visibility checks. */ + AZ::Aabb m_aabb; /**< The axis aligned bounding box. */ + AZ::Aabb m_staticAabb; /**< A static pre-calculated bounding box, which we can move along with the position of the actor instance, and use for visibility checks. */ Transform mLocalTransform = Transform::CreateIdentity(); Transform mWorldTransform = Transform::CreateIdentity(); @@ -907,7 +884,7 @@ namespace EMotionFX MotionSystem* mMotionSystem; /**< The motion system, that handles all motion playback and blending etc. */ AnimGraphInstance* mAnimGraphInstance; /**< A pointer to the anim graph instance, which can be nullptr when there is no anim graph instance. */ AZStd::unique_ptr m_ragdollInstance; - MCore::Mutex mLock; /**< The multithread lock. */ + MCore::Mutex mLock; /**< The multi-thread lock. */ void* mCustomData; /**< A pointer to custom data for this actor. This could be a pointer to your engine or game object for example. */ AZ::Entity* m_entity; /**< The entity to which the actor instance belongs to. */ float mBoundsUpdateFrequency; /**< The bounds update frequency. Which is a time value in seconds. */ @@ -920,7 +897,8 @@ namespace EMotionFX uint32 mBoundsUpdateItemFreq; /**< The bounds update item counter step size. A value of 1 means every vertex/node, a value of 2 means every second vertex/node, etc. */ uint32 mID; /**< The unique identification number for the actor instance. */ uint32 mThreadIndex; /**< The thread index. This specifies the thread number this actor instance is being processed in. */ - EBoundsType mBoundsUpdateType; /**< The bounds update type (node based, mesh based or colliison mesh based). */ + EBoundsType mBoundsUpdateType; /**< The bounds update type (node based, mesh based or collision mesh based). */ + float m_boundsExpandBy = 0.25f; /**< Expand bounding box by normalized percentage. (Default: 25% greater than the calculated bounding box) */ uint8 mNumAttachmentRefs; /**< Specifies how many actor instances use this actor instance as attachment. */ uint8 mBoolFlags; /**< Boolean flags. */ From 60fa18ec279ba9d39487692ff6a1d943eb920179 Mon Sep 17 00:00:00 2001 From: Benjamin Jillich Date: Thu, 5 Aug 2021 15:09:00 +0200 Subject: [PATCH 108/803] Added box expansion percentage to the (editor)actor components Signed-off-by: Benjamin Jillich --- .../Integration/Components/ActorComponent.cpp | 39 ++++++++++--- .../Integration/Components/ActorComponent.h | 21 ++++--- .../Components/EditorActorComponent.cpp | 55 ++++++++++--------- 3 files changed, 71 insertions(+), 44 deletions(-) diff --git a/Gems/EMotionFX/Code/Source/Integration/Components/ActorComponent.cpp b/Gems/EMotionFX/Code/Source/Integration/Components/ActorComponent.cpp index 74133997e4..b033e46a87 100644 --- a/Gems/EMotionFX/Code/Source/Integration/Components/ActorComponent.cpp +++ b/Gems/EMotionFX/Code/Source/Integration/Components/ActorComponent.cpp @@ -58,27 +58,32 @@ namespace EMotionFX }; ////////////////////////////////////////////////////////////////////////// - void ActorComponent::BoundingBoxConfiguration::Set(ActorInstance* actor) const + void ActorComponent::BoundingBoxConfiguration::Set(ActorInstance* actorInstance) const { + actorInstance->SetExpandBoundsBy(m_expandBy * 0.01f); // Normalize percentage for internal use. (1% == 0.01f) + if (m_autoUpdateBounds) { - actor->SetupAutoBoundsUpdate(m_updateTimeFrequency, m_boundsType, m_updateItemFrequency); + actorInstance->SetupAutoBoundsUpdate(m_updateTimeFrequency, m_boundsType, m_updateItemFrequency); } else { - actor->SetBoundsUpdateType(m_boundsType); - actor->SetBoundsUpdateEnabled(false); + actorInstance->SetBoundsUpdateType(m_boundsType); + actorInstance->SetBoundsUpdateEnabled(false); } } - void ActorComponent::BoundingBoxConfiguration::SetAndUpdate(ActorInstance* actor) const + void ActorComponent::BoundingBoxConfiguration::SetAndUpdate(ActorInstance* actorInstance) const { - Set(actor); - const AZ::u32 freq = actor->GetBoundsUpdateEnabled() ? actor->GetBoundsUpdateItemFrequency() : 1; - actor->UpdateBounds(0, actor->GetBoundsUpdateType(), freq); + Set(actorInstance); + + const AZ::u32 updateFrequency = actorInstance->GetBoundsUpdateEnabled() ? actorInstance->GetBoundsUpdateItemFrequency() : 1; + const ActorInstance::EBoundsType boundUpdateType = actorInstance->GetBoundsUpdateType(); + + actorInstance->UpdateBounds(actorInstance->GetLODLevel(), boundUpdateType, updateFrequency); } - void ActorComponent::BoundingBoxConfiguration::Reflect(AZ::ReflectContext * context) + void ActorComponent::BoundingBoxConfiguration::Reflect(AZ::ReflectContext* context) { if (auto* serializeContext = azrtti_cast(context)) { @@ -105,10 +110,26 @@ namespace EMotionFX ->Field("m_autoUpdateBounds", &BoundingBoxConfiguration::m_autoUpdateBounds) ->Field("m_updateTimeFrequency", &BoundingBoxConfiguration::m_updateTimeFrequency) ->Field("m_updateItemFrequency", &BoundingBoxConfiguration::m_updateItemFrequency) + ->Field("expandBy", &BoundingBoxConfiguration::m_expandBy) ; } } + AZ::Crc32 ActorComponent::BoundingBoxConfiguration::GetVisibilityAutoUpdate() const + { + return m_boundsType != EMotionFX::ActorInstance::BOUNDS_STATIC_BASED ? AZ::Edit::PropertyVisibility::Show : AZ::Edit::PropertyVisibility::Hide; + } + + AZ::Crc32 ActorComponent::BoundingBoxConfiguration::GetVisibilityAutoUpdateSettings() const + { + if (m_boundsType == EMotionFX::ActorInstance::BOUNDS_STATIC_BASED || m_autoUpdateBounds == false) + { + return AZ::Edit::PropertyVisibility::Hide; + } + + return AZ::Edit::PropertyVisibility::Show; + } + ////////////////////////////////////////////////////////////////////////// void ActorComponent::Configuration::Reflect(AZ::ReflectContext* context) { diff --git a/Gems/EMotionFX/Code/Source/Integration/Components/ActorComponent.h b/Gems/EMotionFX/Code/Source/Integration/Components/ActorComponent.h index 0f36846a50..2bf85692be 100644 --- a/Gems/EMotionFX/Code/Source/Integration/Components/ActorComponent.h +++ b/Gems/EMotionFX/Code/Source/Integration/Components/ActorComponent.h @@ -45,24 +45,29 @@ namespace EMotionFX AZ_COMPONENT(ActorComponent, "{BDC97E7F-A054-448B-A26F-EA2B5D78E377}"); friend class EditorActorComponent; - struct BoundingBoxConfiguration + class BoundingBoxConfiguration { + public: AZ_TYPE_INFO(BoundingBoxConfiguration, "{EBCFF975-00A5-4578-85C7-59909F52067C}"); BoundingBoxConfiguration() = default; - EMotionFX::ActorInstance::EBoundsType m_boundsType = EMotionFX::ActorInstance::BOUNDS_STATIC_BASED; - bool m_autoUpdateBounds = true; - float m_updateTimeFrequency = 0.f; - AZ::u32 m_updateItemFrequency = 1; + EMotionFX::ActorInstance::EBoundsType m_boundsType = EMotionFX::ActorInstance::BOUNDS_STATIC_BASED; + float m_expandBy = 25.0f; ///< Expand the bounding volume by the given percentage. + bool m_autoUpdateBounds = true; + float m_updateTimeFrequency = 0.0f; + AZ::u32 m_updateItemFrequency = 1; - // Set the bounding box configuration of the given actor instance to the parameters given by `this'. The actor instance must not be null (this is not checked). - void Set(ActorInstance* inst) const; + // Set the bounding box configuration of the given actor instance to the parameters given by 'this'. The actor instance must not be null (this is not checked). + void Set(ActorInstance* actorInstance) const; // Set the bounding box configuration, then update the bounds of the actor instance - void SetAndUpdate(ActorInstance* inst) const; + void SetAndUpdate(ActorInstance* actorInstance) const; static void Reflect(AZ::ReflectContext* context); + + AZ::Crc32 GetVisibilityAutoUpdate() const; + AZ::Crc32 GetVisibilityAutoUpdateSettings() const; }; /** diff --git a/Gems/EMotionFX/Code/Source/Integration/Editor/Components/EditorActorComponent.cpp b/Gems/EMotionFX/Code/Source/Integration/Editor/Components/EditorActorComponent.cpp index efc5cbd9a2..ed5333da9c 100644 --- a/Gems/EMotionFX/Code/Source/Integration/Editor/Components/EditorActorComponent.cpp +++ b/Gems/EMotionFX/Code/Source/Integration/Editor/Components/EditorActorComponent.cpp @@ -62,39 +62,40 @@ namespace EMotionFX { editContext->Class("Actor Bounding Box Config", "") ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->DataElement(AZ::Edit::UIHandlers::ComboBox, &ActorComponent::BoundingBoxConfiguration::m_boundsType, "Bounds type", - "The method used to compute the Actor bounding box. NOTE: ordered by least expensive to compute to most expensive to compute." - ) - ->EnumAttribute(ActorInstance::BOUNDS_STATIC_BASED, "Static bounds (source-asset bounds)") - ->EnumAttribute(ActorInstance::BOUNDS_NODE_BASED, "Bone position-based") - ->EnumAttribute(ActorInstance::BOUNDS_NODEOBB_BASED, "Bone local bounding box-based") - ->EnumAttribute(ActorInstance::BOUNDS_MESH_BASED, "Render mesh vertex position-based (VERY EXPENSIVE)") - - ->DataElement(0, &ActorComponent::BoundingBoxConfiguration::m_autoUpdateBounds, + "The method used to compute the Actor bounding box. NOTE: ordered by least expensive to compute to most expensive to compute.") + ->EnumAttribute(ActorInstance::BOUNDS_STATIC_BASED, "Static (Recommended)") + ->EnumAttribute(ActorInstance::BOUNDS_NODE_BASED, "Bone position-based") + ->EnumAttribute(ActorInstance::BOUNDS_MESH_BASED, "Mesh vertex-based (Expensive)") + ->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ::Edit::PropertyRefreshLevels::EntireTree) + ->DataElement(AZ::Edit::UIHandlers::Default, &ActorComponent::BoundingBoxConfiguration::m_expandBy, + "Expand by", + "Percentage that the calculated bounding box should be automatically expanded with. " + "This can be used to add a tolerance area to the calculated bounding box to avoid clipping the character too early. " + "A static bounding box together with the expansion is the recommended way for maximum performance. (Default = 25%)") + ->Attribute(AZ::Edit::Attributes::Suffix, " %") + ->Attribute(AZ::Edit::Attributes::Min, 0.0f) + ->DataElement(AZ::Edit::UIHandlers::Default, &ActorComponent::BoundingBoxConfiguration::m_autoUpdateBounds, "Automatically update bounds?", - "If true, bounds are automatically updated based on some frequency. Otherwise bounds are computed only at creation or when triggered manually" - ) - ->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ::Edit::PropertyRefreshLevels::AttributesAndValues) - - ->DataElement(0, &ActorComponent::BoundingBoxConfiguration::m_updateTimeFrequency, + "If true, bounds are automatically updated based on some frequency. Otherwise bounds are computed only at creation or when triggered manually") + ->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ::Edit::PropertyRefreshLevels::EntireTree) + ->Attribute(AZ::Edit::Attributes::Visibility, &ActorComponent::BoundingBoxConfiguration::GetVisibilityAutoUpdate) + ->DataElement(AZ::Edit::UIHandlers::Default, &ActorComponent::BoundingBoxConfiguration::m_updateTimeFrequency, "Update frequency", - "How often to update bounds automatically" - ) - ->Attribute(AZ::Edit::Attributes::Suffix, " Hz") - ->Attribute(AZ::Edit::Attributes::Min, 0.f) - ->Attribute(AZ::Edit::Attributes::Step, 0.001f) - ->Attribute(AZ::Edit::Attributes::Visibility, &ActorComponent::BoundingBoxConfiguration::m_autoUpdateBounds) - - ->DataElement(0, &ActorComponent::BoundingBoxConfiguration::m_updateItemFrequency, + "How often to update bounds automatically") + ->Attribute(AZ::Edit::Attributes::Suffix, " Hz") + ->Attribute(AZ::Edit::Attributes::Min, 0.0f) + ->Attribute(AZ::Edit::Attributes::Max, FLT_MAX) + ->Attribute(AZ::Edit::Attributes::Step, 0.1f) + ->Attribute(AZ::Edit::Attributes::Visibility, &ActorComponent::BoundingBoxConfiguration::GetVisibilityAutoUpdateSettings) + ->DataElement(AZ::Edit::UIHandlers::Default, &ActorComponent::BoundingBoxConfiguration::m_updateItemFrequency, "Update item skip factor", "How many items (bones or vertices) to skip when automatically updating bounds." - "
i.e. =1 uses every single item, =2 uses every 2nd item, =3 uses every 3rd item... " - ) - ->Attribute(AZ::Edit::Attributes::Suffix, " items") - ->Attribute(AZ::Edit::Attributes::Min, (AZ::u32)1) - ->Attribute(AZ::Edit::Attributes::Visibility, &ActorComponent::BoundingBoxConfiguration::m_autoUpdateBounds) + "
i.e. =1 uses every single item, =2 uses every 2nd item, =3 uses every 3rd item...") + ->Attribute(AZ::Edit::Attributes::Suffix, " items") + ->Attribute(AZ::Edit::Attributes::Min, (AZ::u32)1) + ->Attribute(AZ::Edit::Attributes::Visibility, &ActorComponent::BoundingBoxConfiguration::GetVisibilityAutoUpdateSettings) ; editContext->Class("Actor", "The Actor component manages an instance of an Actor") From f65bf1a06bc67ca0f425eb15a277876ca56e114e Mon Sep 17 00:00:00 2001 From: Benjamin Jillich Date: Thu, 5 Aug 2021 15:10:16 +0200 Subject: [PATCH 109/803] Increased version in the actor group exporter to automatically reprocess all actors to use the new node chunks Signed-off-by: Benjamin Jillich --- .../EMotionFX/Pipeline/RCExt/Actor/ActorGroupExporter.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Gems/EMotionFX/Code/EMotionFX/Pipeline/RCExt/Actor/ActorGroupExporter.cpp b/Gems/EMotionFX/Code/EMotionFX/Pipeline/RCExt/Actor/ActorGroupExporter.cpp index bf79fbf05c..ba8168476c 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Pipeline/RCExt/Actor/ActorGroupExporter.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Pipeline/RCExt/Actor/ActorGroupExporter.cpp @@ -48,7 +48,10 @@ namespace EMotionFX AZ::SerializeContext* serializeContext = azrtti_cast(context); if (serializeContext) { - serializeContext->Class()->Version(2); + // Increasing the version number of the actor group exporter will make sure all actor products will be force re-generated. + // Version history: + // v3: Introduced Actor_Nodes2 (replaced Actor_Nodes) and Actor_Node2 (replaced Actor_Node) + serializeContext->Class()->Version(3); } } From 73fee0c57e4206f5b2194b768fcc5d51a5628c72 Mon Sep 17 00:00:00 2001 From: Yuriy Toporovskyy Date: Wed, 4 Aug 2021 10:39:57 -0400 Subject: [PATCH 110/803] Camera Component, Editor Viewport Widget refactoring. - Handle changing of active camera entirely inside CameraComponentController - Remove a LOT of legacy Cry things related to cameras - Add a CameraSystemComponent to handle ActiveCameraRequestBus and CameraSystemRequestBus Signed-off-by: Yuriy Toporovskyy --- Code/Editor/2DViewport.cpp | 2 +- Code/Editor/AnimationContext.cpp | 9 - Code/Editor/CryEdit.cpp | 115 +- Code/Editor/CryEditDoc.cpp | 2 + Code/Editor/EditorViewportWidget.cpp | 917 ++-- Code/Editor/EditorViewportWidget.h | 605 +-- Code/Editor/Export/ExportManager.cpp | 10 +- Code/Editor/GameEngine.cpp | 9 - Code/Editor/Objects/ObjectManager.cpp | 14 +- Code/Editor/RenderViewport.cpp | 4142 ----------------- Code/Editor/RenderViewport.h | 595 --- Code/Editor/Settings.cpp | 1 + Code/Editor/TrackView/CommentNodeAnimator.cpp | 19 +- .../TrackView/SequenceBatchRenderDialog.cpp | 12 +- Code/Editor/TrackView/TrackViewAnimNode.cpp | 1 + Code/Editor/UndoViewRotation.cpp | 18 +- Code/Editor/UndoViewRotation.h | 2 + Code/Editor/ViewManager.cpp | 11 +- Code/Editor/ViewPane.cpp | 18 - Code/Editor/Viewport.cpp | 1 - Code/Editor/Viewport.h | 14 +- Code/Editor/ViewportTitleDlg.cpp | 32 +- .../AzCore/AzCore/Math/MatrixUtils.cpp | 16 + .../AzCore/AzCore/Math/MatrixUtils.h | 4 + .../AzFramework/Components/CameraBus.h | 3 + Code/Legacy/CryCommon/ISystem.h | 3 - .../CrySystem/LevelSystem/LevelSystem.cpp | 10 +- .../LevelSystem/SpawnableLevelSystem.cpp | 6 +- Code/Legacy/CrySystem/System.h | 4 - .../CrySystem/ViewSystem/DebugCamera.cpp | 16 +- Code/Legacy/CrySystem/ViewSystem/View.cpp | 114 +- .../CrySystem/ViewSystem/ViewSystem.cpp | 35 +- .../Component/DebugCamera/CameraComponent.h | 1 + .../Code/Source/CameraComponent.cpp | 5 + .../Editor/AudioControlsEditorPlugin.cpp | 11 +- Gems/Camera/Code/Source/CameraComponent.cpp | 1 + .../Code/Source/CameraComponentController.cpp | 29 +- .../Code/Source/CameraComponentController.h | 7 +- Gems/Camera/Code/Source/CameraGem.cpp | 3 + .../Code/Source/CameraSystemComponent.cpp | 128 + .../Code/Source/CameraSystemComponent.h | 60 + .../Code/Source/EditorCameraComponent.cpp | 39 +- .../Code/Source/EditorCameraComponent.h | 5 - .../Source/ViewportCameraSelectorWindow.cpp | 91 +- .../ViewportCameraSelectorWindow_Internals.h | 7 +- Gems/Camera/Code/camera_files.cmake | 7 +- .../Code/Source/SystemComponent.cpp | 18 +- 47 files changed, 1126 insertions(+), 6046 deletions(-) create mode 100644 Gems/Camera/Code/Source/CameraSystemComponent.cpp create mode 100644 Gems/Camera/Code/Source/CameraSystemComponent.h diff --git a/Code/Editor/2DViewport.cpp b/Code/Editor/2DViewport.cpp index 56f2e7bdf5..e231792329 100644 --- a/Code/Editor/2DViewport.cpp +++ b/Code/Editor/2DViewport.cpp @@ -952,7 +952,7 @@ void Q2DViewport::DrawViewerMarker(DisplayContext& dc) dc.SetColor(QColor(0, 0, 255)); // blue dc.DrawWireBox(-dim * noScale, dim * noScale); - float fov = GetIEditor()->GetSystem()->GetViewCamera().GetFov(); + float fov = 60; // GetIEditor()->GetSystem()->GetViewCamera().GetFov(); Vec3 q[4]; float dist = 30; diff --git a/Code/Editor/AnimationContext.cpp b/Code/Editor/AnimationContext.cpp index debe5e3b01..b67e9e602e 100644 --- a/Code/Editor/AnimationContext.cpp +++ b/Code/Editor/AnimationContext.cpp @@ -61,15 +61,6 @@ protected: { camObjId = pEditorEntity->GetId(); } - - CViewport* pViewport = GetIEditor()->GetViewManager()->GetSelectedViewport(); - if (CRenderViewport* rvp = viewport_cast(pViewport)) - { - if (!rvp->IsSequenceCamera()) - { - return; - } - } } // Switch camera in active rendering view. diff --git a/Code/Editor/CryEdit.cpp b/Code/Editor/CryEdit.cpp index 4bfc6a319d..ec2df83ba7 100644 --- a/Code/Editor/CryEdit.cpp +++ b/Code/Editor/CryEdit.cpp @@ -3728,24 +3728,24 @@ void CCryEditApp::OnToolsPreferences() ////////////////////////////////////////////////////////////////////////// void CCryEditApp::OnSwitchToDefaultCamera() { - CViewport* vp = GetIEditor()->GetViewManager()->GetSelectedViewport(); - if (CRenderViewport* rvp = viewport_cast(vp)) - { - rvp->SetDefaultCamera(); - } + //CViewport* vp = GetIEditor()->GetViewManager()->GetSelectedViewport(); + //if (CRenderViewport* rvp = viewport_cast(vp)) + //{ + // rvp->SetDefaultCamera(); + //} } ////////////////////////////////////////////////////////////////////////// -void CCryEditApp::OnUpdateSwitchToDefaultCamera(QAction* action) +void CCryEditApp::OnUpdateSwitchToDefaultCamera([[maybe_unused]] QAction* action) { Q_ASSERT(action->isCheckable()); - CViewport* pViewport = GetIEditor()->GetViewManager()->GetSelectedViewport(); - if (CRenderViewport* rvp = viewport_cast(pViewport)) - { - action->setEnabled(true); - action->setChecked(rvp->IsDefaultCamera()); - } - else + //CViewport* pViewport = GetIEditor()->GetViewManager()->GetSelectedViewport(); + //if (false) // (CRenderViewport* rvp = viewport_cast(pViewport)) + //{ + // action->setEnabled(true); + // action->setChecked(rvp->IsDefaultCamera()); + //} + //else { action->setEnabled(false); } @@ -3754,11 +3754,11 @@ void CCryEditApp::OnUpdateSwitchToDefaultCamera(QAction* action) ////////////////////////////////////////////////////////////////////////// void CCryEditApp::OnSwitchToSequenceCamera() { - CViewport* vp = GetIEditor()->GetViewManager()->GetSelectedViewport(); - if (CRenderViewport* rvp = viewport_cast(vp)) - { - rvp->SetSequenceCamera(); - } + //CViewport* vp = GetIEditor()->GetViewManager()->GetSelectedViewport(); + //if (CRenderViewport* rvp = viewport_cast(vp)) + //{ + // rvp->SetSequenceCamera(); + //} } ////////////////////////////////////////////////////////////////////////// @@ -3766,27 +3766,27 @@ void CCryEditApp::OnUpdateSwitchToSequenceCamera(QAction* action) { Q_ASSERT(action->isCheckable()); - CViewport* pViewport = GetIEditor()->GetViewManager()->GetSelectedViewport(); + //CViewport* pViewport = GetIEditor()->GetViewManager()->GetSelectedViewport(); - if (CRenderViewport* rvp = viewport_cast(pViewport)) - { - bool enableAction = false; + //if (CRenderViewport* rvp = viewport_cast(pViewport)) + //{ + // bool enableAction = false; - // only enable if we're editing a sequence in Track View and have cameras in the level - if (GetIEditor()->GetAnimation()->GetSequence()) - { + // // only enable if we're editing a sequence in Track View and have cameras in the level + // if (GetIEditor()->GetAnimation()->GetSequence()) + // { - AZ::EBusAggregateResults componentCameras; - Camera::CameraBus::BroadcastResult(componentCameras, &Camera::CameraRequests::GetCameras); + // AZ::EBusAggregateResults componentCameras; + // Camera::CameraBus::BroadcastResult(componentCameras, &Camera::CameraRequests::GetCameras); - const int numCameras = componentCameras.values.size(); - enableAction = (numCameras > 0); - } + // const int numCameras = componentCameras.values.size(); + // enableAction = (numCameras > 0); + // } - action->setEnabled(enableAction); - action->setChecked(rvp->IsSequenceCamera()); - } - else + // action->setEnabled(enableAction); + // action->setChecked(rvp->IsSequenceCamera()); + //} + //else { action->setEnabled(false); } @@ -3795,31 +3795,32 @@ void CCryEditApp::OnUpdateSwitchToSequenceCamera(QAction* action) ////////////////////////////////////////////////////////////////////////// void CCryEditApp::OnSwitchToSelectedcamera() { - CViewport* vp = GetIEditor()->GetViewManager()->GetSelectedViewport(); - if (CRenderViewport* rvp = viewport_cast(vp)) - { - rvp->SetSelectedCamera(); - } + //CViewport* vp = GetIEditor()->GetViewManager()->GetSelectedViewport(); + //if (CRenderViewport* rvp = viewport_cast(vp)) + //{ + // rvp->SetSelectedCamera(); + //} } ////////////////////////////////////////////////////////////////////////// void CCryEditApp::OnUpdateSwitchToSelectedCamera(QAction* action) { Q_ASSERT(action->isCheckable()); - AzToolsFramework::EntityIdList selectedEntityList; - AzToolsFramework::ToolsApplicationRequests::Bus::BroadcastResult(selectedEntityList, &AzToolsFramework::ToolsApplicationRequests::GetSelectedEntities); - AZ::EBusAggregateResults cameras; - Camera::CameraBus::BroadcastResult(cameras, &Camera::CameraRequests::GetCameras); - bool isCameraComponentSelected = selectedEntityList.size() > 0 ? AZStd::find(cameras.values.begin(), cameras.values.end(), *selectedEntityList.begin()) != cameras.values.end() : false; + (void)action; + //AzToolsFramework::EntityIdList selectedEntityList; + //AzToolsFramework::ToolsApplicationRequests::Bus::BroadcastResult(selectedEntityList, &AzToolsFramework::ToolsApplicationRequests::GetSelectedEntities); + //AZ::EBusAggregateResults cameras; + //Camera::CameraBus::BroadcastResult(cameras, &Camera::CameraRequests::GetCameras); + //bool isCameraComponentSelected = selectedEntityList.size() > 0 ? AZStd::find(cameras.values.begin(), cameras.values.end(), *selectedEntityList.begin()) != cameras.values.end() : false; - CViewport* pViewport = GetIEditor()->GetViewManager()->GetSelectedViewport(); - CRenderViewport* rvp = viewport_cast(pViewport); - if (isCameraComponentSelected && rvp) - { - action->setEnabled(true); - action->setChecked(rvp->IsSelectedCamera()); - } - else + //CViewport* pViewport = GetIEditor()->GetViewManager()->GetSelectedViewport(); + //CRenderViewport* rvp = viewport_cast(pViewport); + //if (isCameraComponentSelected && rvp) + //{ + // action->setEnabled(true); + // action->setChecked(rvp->IsSelectedCamera()); + //} + //else { action->setEnabled(false); } @@ -3828,11 +3829,11 @@ void CCryEditApp::OnUpdateSwitchToSelectedCamera(QAction* action) ////////////////////////////////////////////////////////////////////////// void CCryEditApp::OnSwitchcameraNext() { - CViewport* vp = GetIEditor()->GetActiveView(); - if (CRenderViewport* rvp = viewport_cast(vp)) - { - rvp->CycleCamera(); - } + //CViewport* vp = GetIEditor()->GetActiveView(); + //if (CRenderViewport* rvp = viewport_cast(vp)) + //{ + // rvp->CycleCamera(); + //} } ////////////////////////////////////////////////////////////////////////// diff --git a/Code/Editor/CryEditDoc.cpp b/Code/Editor/CryEditDoc.cpp index 43f599b191..feafeec4f5 100644 --- a/Code/Editor/CryEditDoc.cpp +++ b/Code/Editor/CryEditDoc.cpp @@ -19,6 +19,7 @@ #include #include #include +#include // AzFramework #include @@ -53,6 +54,7 @@ #include "MainWindow.h" #include "LevelFileDialog.h" #include "StatObjBus.h" +#include "Undo/Undo.h" #include #include diff --git a/Code/Editor/EditorViewportWidget.cpp b/Code/Editor/EditorViewportWidget.cpp index 4ea36728ad..c77ef2ef3f 100644 --- a/Code/Editor/EditorViewportWidget.cpp +++ b/Code/Editor/EditorViewportWidget.cpp @@ -46,7 +46,7 @@ #include #include #include -#include +#include // AtomToolsFramework #include @@ -73,6 +73,7 @@ #include "EditorPreferencesPageGeneral.h" #include "ViewportManipulatorController.h" #include "LegacyViewportCameraController.h" +#include "EditorViewportSettings.h" #include "ViewPane.h" #include "CustomResolutionDlg.h" @@ -91,6 +92,8 @@ // Atom #include #include +#include + #include #include @@ -163,6 +166,10 @@ namespace AZ::ViewportHelpers { m_renderViewport.OnStopPlayInEditor(); } + void OnStartPlayInEditorBegin() override + { + m_renderViewport.OnStartPlayInEditorBegin(); + } private: EditorViewportWidget& m_renderViewport; @@ -175,16 +182,12 @@ namespace AZ::ViewportHelpers EditorViewportWidget::EditorViewportWidget(const QString& name, QWidget* parent) : QtViewport(parent) - , m_Camera(GetIEditor()->GetSystem()->GetViewCamera()) - , m_camFOV(gSettings.viewports.fDefaultFov) , m_defaultViewName(name) , m_renderViewport(nullptr) //m_renderViewport is initialized later, in SetViewportId { // need this to be set in order to allow for language switching on Windows setAttribute(Qt::WA_InputMethodEnabled); - LockCameraMovement(true); - EditorViewportWidget::SetViewTM(m_Camera.GetMatrix()); m_defaultViewTM.SetIdentity(); if (GetIEditor()->GetViewManager()->GetSelectedViewport() == nullptr) @@ -197,8 +200,6 @@ EditorViewportWidget::EditorViewportWidget(const QString& name, QWidget* parent) m_displayContext.pIconManager = GetIEditor()->GetIconManager(); GetIEditor()->GetUndoManager()->AddListener(this); - m_PhysicalLocation.SetIdentity(); - // The renderer requires something, so don't allow us to shrink to absolutely nothing // This won't in fact stop the viewport from being shrunk, when it's the centralWidget for // the MainWindow, but it will stop the viewport from getting resize events @@ -206,22 +207,14 @@ EditorViewportWidget::EditorViewportWidget(const QString& name, QWidget* parent) // to be the same thing. setMinimumSize(50, 50); - OnCreate(); - setMouseTracking(true); Camera::EditorCameraRequestBus::Handler::BusConnect(); + Camera::CameraNotificationBus::Handler::BusConnect(); + m_editorEntityNotifications = AZStd::make_unique(*this); AzFramework::AssetCatalogEventBus::Handler::BusConnect(); - auto handleCameraChange = [this](const AZ::Matrix4x4&) - { - UpdateCameraFromViewportContext(); - }; - - m_cameraViewMatrixChangeHandler = AZ::RPI::ViewportContext::MatrixChangedEvent::Handler(handleCameraChange); - m_cameraProjectionMatrixChangeHandler = AZ::RPI::ViewportContext::MatrixChangedEvent::Handler(handleCameraChange); - m_manipulatorManager = GetIEditor()->GetViewManager()->GetManipulatorManager(); if (!m_pPrimaryViewport) { @@ -240,28 +233,20 @@ EditorViewportWidget::~EditorViewportWidget() DisconnectViewportInteractionRequestBus(); m_editorEntityNotifications.reset(); Camera::EditorCameraRequestBus::Handler::BusDisconnect(); - OnDestroy(); + Camera::CameraNotificationBus::Handler::BusDisconnect(); GetIEditor()->GetUndoManager()->RemoveListener(this); GetIEditor()->UnregisterNotifyListener(this); } -////////////////////////////////////////////////////////////////////////// -// EditorViewportWidget message handlers -////////////////////////////////////////////////////////////////////////// -int EditorViewportWidget::OnCreate() -{ - CreateRenderContext(); - - return 0; -} - ////////////////////////////////////////////////////////////////////////// void EditorViewportWidget::resizeEvent(QResizeEvent* event) { + // Call base class resize event while not rendering PushDisableRendering(); QtViewport::resizeEvent(event); PopDisableRendering(); + // Emit Legacy system events about the viewport size change const QRect rcWindow = rect().translated(mapToGlobal(QPoint())); gEnv->pSystem->GetISystemEventDispatcher()->OnSystemEvent(ESYSTEM_EVENT_MOVE, rcWindow.left(), rcWindow.top()); @@ -271,10 +256,12 @@ void EditorViewportWidget::resizeEvent(QResizeEvent* event) gEnv->pSystem->GetISystemEventDispatcher()->OnSystemEvent(ESYSTEM_EVENT_RESIZE, width(), height()); - // We queue the window resize event because the render overlay may be hidden. - // If the render overlay is not visible, the native window that is backing it will - // also be hidden, and it will not resize until it becomes visible. - m_windowResizedEvent = true; + // In the case of the default viewport camera, we must re-set the FOV, which also updates the aspect ratio + // Component cameras hand this themselves + if (m_viewSourceType == ViewSourceType::None) + { + SetFOV(GetFOV()); + } } ////////////////////////////////////////////////////////////////////////// @@ -383,15 +370,6 @@ AzToolsFramework::ViewportInteraction::MouseInteraction EditorViewportWidget::Bu BuildMousePick(WidgetToViewport(point))); } -void EditorViewportWidget::InjectFakeMouseMove(int deltaX, int deltaY, Qt::MouseButtons buttons) -{ - // this is required, otherwise the user will see the context menu - OnMouseMove(Qt::NoModifier, buttons, QCursor::pos() + QPoint(deltaX, deltaY)); - // we simply move the prev mouse position, so the change will be picked up - // by the next ProcessMouse call - m_prevMousePos -= QPoint(deltaX, deltaY); -} - ////////////////////////////////////////////////////////////////////////// bool EditorViewportWidget::event(QEvent* event) { @@ -403,19 +381,6 @@ bool EditorViewportWidget::event(QEvent* event) m_keyDown.clear(); break; - case QEvent::ShortcutOverride: - { - // Ensure we exit game mode on escape, even if something else would eat our escape key event. - if (static_cast(event)->key() == Qt::Key_Escape && GetIEditor()->IsInGameMode()) - { - GetIEditor()->SetInGameMode(false); - event->accept(); - return true; - } - break; - } - - case QEvent::Shortcut: // a shortcut should immediately clear us, otherwise the release event never gets sent m_keyDown.clear(); @@ -425,12 +390,6 @@ bool EditorViewportWidget::event(QEvent* event) return QtViewport::event(event); } -////////////////////////////////////////////////////////////////////////// -void EditorViewportWidget::ResetContent() -{ - QtViewport::ResetContent(); -} - ////////////////////////////////////////////////////////////////////////// void EditorViewportWidget::UpdateContent(int flags) { @@ -461,26 +420,6 @@ void EditorViewportWidget::Update() return; } - if (m_updateCameraPositionNextTick) - { - auto cameraState = GetCameraState(); - AZ::Matrix3x4 matrix; - matrix.SetBasisAndTranslation(cameraState.m_side, cameraState.m_forward, cameraState.m_up, cameraState.m_position); - auto m = AZMatrix3x4ToLYMatrix3x4(matrix); - - SetViewTM(m); - m_Camera.SetZRange(cameraState.m_nearClip, cameraState.m_farClip); - } - - // Ensure the FOV matches our internally stored setting if we're using the Editor camera - if (!m_viewEntityId.IsValid() && !GetIEditor()->IsInGameMode()) - { - SetFOV(GetFOV()); - } - - // Reset the camera update flag now that we're finished updating our viewport context - m_updateCameraPositionNextTick = false; - // Don't wait for changes to update the focused viewport. if (CheckRespondToInput()) { @@ -558,25 +497,13 @@ void EditorViewportWidget::Update() PushDisableRendering(); - m_viewTM = m_Camera.GetMatrix(); // synchronize. - // Render { // TODO: Move out this logic to a controller and refactor to work with Atom - - OnRender(); - ProcessRenderLisneters(m_displayContext); m_displayContext.Flush2D(); - // m_renderer->SwitchToNativeResolutionBackbuffer(); - - // 3D engine stats - - CCamera CurCamera = gEnv->pSystem->GetViewCamera(); - gEnv->pSystem->SetViewCamera(m_Camera); - // Post Render Callback { PostRenderers::iterator itr = m_postRenderers.begin(); @@ -586,8 +513,6 @@ void EditorViewportWidget::Update() (*itr)->OnPostRender(); } } - - gEnv->pSystem->SetViewCamera(CurCamera); } { @@ -609,35 +534,7 @@ void EditorViewportWidget::Update() m_bUpdateViewport = false; } -////////////////////////////////////////////////////////////////////////// -void EditorViewportWidget::SetViewEntity(const AZ::EntityId& viewEntityId, bool lockCameraMovement) -{ - // if they've picked the same camera, then that means they want to toggle - if (viewEntityId.IsValid() && viewEntityId != m_viewEntityId) - { - LockCameraMovement(lockCameraMovement); - m_viewEntityId = viewEntityId; - AZStd::string entityName; - AZ::ComponentApplicationBus::BroadcastResult(entityName, &AZ::ComponentApplicationRequests::GetEntityName, viewEntityId); - SetName(QString("Camera entity: %1").arg(entityName.c_str())); - } - else - { - SetDefaultCamera(); - } - PostCameraSet(); -} - -////////////////////////////////////////////////////////////////////////// -void EditorViewportWidget::ResetToViewSourceType(const ViewSourceType& viewSourceType) -{ - LockCameraMovement(true); - m_viewEntityId.SetInvalid(); - m_cameraObjectId = GUID_NULL; - m_viewSourceType = viewSourceType; - SetViewTM(GetViewTM()); -} ////////////////////////////////////////////////////////////////////////// void EditorViewportWidget::PostCameraSet() @@ -647,10 +544,28 @@ void EditorViewportWidget::PostCameraSet() m_viewPane->OnFOVChanged(GetFOV()); } + // CryLegacy notify GetIEditor()->Notify(eNotify_CameraChanged); - QScopedValueRollback rb(m_ignoreSetViewFromEntityPerspective, true); + + // Special case in the editor; if the camera is the default editor camera, + // notify that the active view changed. In game mode, it is a hard error to not have + // any cameras on the view stack! + if (m_viewSourceType == ViewSourceType::None) + { + m_sendingOnActiveChanged = true; + Camera::CameraNotificationBus::Broadcast( + &Camera::CameraNotificationBus::Events::OnActiveViewChanged, AZ::EntityId()); + m_sendingOnActiveChanged = false; + } + + // Notify about editor camera change Camera::EditorCameraNotificationBus::Broadcast( &Camera::EditorCameraNotificationBus::Events::OnViewportViewEntityChanged, m_viewEntityId); + + // The editor view entity ID has changed, and the editor camera component "Be This Camera" text needs to be updated + AzToolsFramework::PropertyEditorGUIMessages::Bus::Broadcast( + &AzToolsFramework::PropertyEditorGUIMessages::RequestRefresh, + AzToolsFramework::PropertyModificationRefreshLevel::Refresh_AttributesAndValues); } ////////////////////////////////////////////////////////////////////////// @@ -658,16 +573,7 @@ CBaseObject* EditorViewportWidget::GetCameraObject() const { CBaseObject* pCameraObject = nullptr; - if (m_viewSourceType == ViewSourceType::SequenceCamera) - { - m_cameraObjectId = GetViewManager()->GetCameraObjectId(); - } - if (m_cameraObjectId != GUID_NULL) - { - // Find camera object from id. - pCameraObject = GetIEditor()->GetObjectManager()->FindObject(m_cameraObjectId); - } - else if (m_viewSourceType == ViewSourceType::CameraComponent || m_viewSourceType == ViewSourceType::AZ_Entity) + if (m_viewSourceType == ViewSourceType::CameraComponent) { AzToolsFramework::ComponentEntityEditorRequestBus::EventResult( pCameraObject, m_viewEntityId, &AzToolsFramework::ComponentEntityEditorRequests::GetSandboxObject); @@ -714,7 +620,7 @@ void EditorViewportWidget::OnEditorNotifyEvent(EEditorNotifyEvent event) if (m_renderViewport) { - m_renderViewport->SetInputProcessingEnabled(false); + m_renderViewport->GetControllerList()->SetEnabled(false); } } break; @@ -723,10 +629,6 @@ void EditorViewportWidget::OnEditorNotifyEvent(EEditorNotifyEvent event) if (GetIEditor()->GetViewManager()->GetGameViewport() == this) { SetCurrentCursor(STD_CURSOR_DEFAULT); - m_bInRotateMode = false; - m_bInMoveMode = false; - m_bInOrbitMode = false; - m_bInZoomMode = false; if (m_inFullscreenPreview) { @@ -738,7 +640,7 @@ void EditorViewportWidget::OnEditorNotifyEvent(EEditorNotifyEvent event) if (m_renderViewport) { - m_renderViewport->SetInputProcessingEnabled(true); + m_renderViewport->GetControllerList()->SetEnabled(true); } break; @@ -818,21 +720,6 @@ void EditorViewportWidget::OnEditorNotifyEvent(EEditorNotifyEvent event) } } -////////////////////////////////////////////////////////////////////////// -void EditorViewportWidget::OnRender() -{ - if (m_rcClient.isEmpty()) - { - // Even in null rendering, update the view camera. - // This is necessary so that automated editor tests using the null renderer to test systems like dynamic vegetation - // are still able to manipulate the current logical camera position, even if nothing is rendered. - GetIEditor()->GetSystem()->SetViewCamera(m_Camera); - return; - } - - FUNCTION_PROFILER(GetIEditor()->GetSystem(), PROFILE_EDITOR); -} - void EditorViewportWidget::OnBeginPrepareRender() { if (!m_debugDisplay) @@ -853,82 +740,6 @@ void EditorViewportWidget::OnBeginPrepareRender() Update(); m_isOnPaint = false; - float fNearZ = GetIEditor()->GetConsoleVar("cl_DefaultNearPlane"); - float fFarZ = m_Camera.GetFarPlane(); - - CBaseObject* cameraObject = GetCameraObject(); - if (cameraObject) - { - AZ::Matrix3x3 lookThroughEntityCorrection = AZ::Matrix3x3::CreateIdentity(); - if (m_viewEntityId.IsValid()) - { - Camera::CameraRequestBus::EventResult(fNearZ, m_viewEntityId, &Camera::CameraComponentRequests::GetNearClipDistance); - Camera::CameraRequestBus::EventResult(fFarZ, m_viewEntityId, &Camera::CameraComponentRequests::GetFarClipDistance); - LmbrCentral::EditorCameraCorrectionRequestBus::EventResult( - lookThroughEntityCorrection, m_viewEntityId, &LmbrCentral::EditorCameraCorrectionRequests::GetTransformCorrection); - } - - m_viewTM = cameraObject->GetWorldTM() * AZMatrix3x3ToLYMatrix3x3(lookThroughEntityCorrection); - m_viewTM.OrthonormalizeFast(); - - m_Camera.SetMatrix(m_viewTM); - - int w = m_rcClient.width(); - int h = m_rcClient.height(); - - m_Camera.SetFrustum(w, h, GetFOV(), fNearZ, fFarZ); - } - else if (m_viewEntityId.IsValid()) - { - Camera::CameraRequestBus::EventResult(fNearZ, m_viewEntityId, &Camera::CameraComponentRequests::GetNearClipDistance); - Camera::CameraRequestBus::EventResult(fFarZ, m_viewEntityId, &Camera::CameraComponentRequests::GetFarClipDistance); - int w = m_rcClient.width(); - int h = m_rcClient.height(); - - m_Camera.SetFrustum(w, h, GetFOV(), fNearZ, fFarZ); - } - else - { - // Normal camera. - m_cameraObjectId = GUID_NULL; - int w = m_rcClient.width(); - int h = m_rcClient.height(); - - // Don't bother doing an FOV calculation if we don't have a valid viewport - // This prevents frustum calculation bugs with a null viewport - if (w <= 1 || h <= 1) - { - return; - } - - float fov = gSettings.viewports.fDefaultFov; - - // match viewport fov to default / selected title menu fov - if (GetFOV() != fov) - { - if (m_viewPane) - { - m_viewPane->OnFOVChanged(fov); - SetFOV(fov); - } - } - - // Just for editor: Aspect ratio fix when changing the viewport - if (!GetIEditor()->IsInGameMode()) - { - float viewportAspectRatio = float( w ) / h; - float targetAspectRatio = GetAspectRatio(); - if (targetAspectRatio > viewportAspectRatio) - { - // Correct for vertical FOV change. - float maxTargetHeight = float( w ) / targetAspectRatio; - fov = 2 * atanf((h * tan(fov / 2)) / maxTargetHeight); - } - } - m_Camera.SetFrustum(w, h, fov, fNearZ); - } - - GetIEditor()->GetSystem()->SetViewCamera(m_Camera); if (GetIEditor()->IsInGameMode()) { @@ -1144,17 +955,6 @@ void EditorViewportWidget::OnMenuSelectCurrentCamera() AzFramework::CameraState EditorViewportWidget::GetCameraState() { - if (m_viewEntityId.IsValid()) - { - bool cameraStateAcquired = false; - AzFramework::CameraState cameraState; - Camera::EditorCameraViewRequestBus::BroadcastResult(cameraStateAcquired, - &Camera::EditorCameraViewRequestBus::Events::GetCameraState, cameraState); - if (cameraStateAcquired) - { - return cameraState; - } - } return m_renderViewport->GetCameraState(); } @@ -1460,13 +1260,11 @@ void EditorViewportWidget::SetViewportId(int id) } auto viewportContext = m_renderViewport->GetViewportContext(); m_defaultViewportContextName = viewportContext->GetName(); + m_defaultView = viewportContext->GetDefaultView(); QBoxLayout* layout = new QBoxLayout(QBoxLayout::Direction::TopToBottom, this); layout->setContentsMargins(QMargins()); layout->addWidget(m_renderViewport); - viewportContext->ConnectViewMatrixChangedHandler(m_cameraViewMatrixChangeHandler); - viewportContext->ConnectProjectionMatrixChangedHandler(m_cameraProjectionMatrixChangeHandler); - m_renderViewport->GetControllerList()->Add(AZStd::make_shared()); if (ed_useNewCameraSystem) @@ -1675,7 +1473,6 @@ bool EditorViewportWidget::AddCameraMenuItems(QMenu* menu) menu->addSeparator(); } - AZ::ViewportHelpers::AddCheckbox(menu, "Lock Camera Movement", &m_bLockCameraMovement); menu->addSeparator(); // Camera Sub menu @@ -1692,13 +1489,7 @@ bool EditorViewportWidget::AddCameraMenuItems(QMenu* menu) const int numCameras = getCameraResults.values.size(); // only enable if we're editing a sequence in Track View and have cameras in the level - bool enableSequenceCameraMenu = (GetIEditor()->GetAnimation()->GetSequence() && numCameras); - - action = customCameraMenu->addAction(tr("Sequence Camera")); - action->setCheckable(true); - action->setChecked(m_viewSourceType == ViewSourceType::SequenceCamera); - action->setEnabled(enableSequenceCameraMenu); - connect(action, &QAction::triggered, this, &EditorViewportWidget::SetSequenceCamera); + //bool enableSequenceCameraMenu = (GetIEditor()->GetAnimation()->GetSequence() && numCameras); QVector additionalCameras; additionalCameras.reserve(getCameraResults.values.size()); @@ -1733,28 +1524,33 @@ bool EditorViewportWidget::AddCameraMenuItems(QMenu* menu) customCameraMenu->addAction(cameraAction); } - action = customCameraMenu->addAction(tr("Look through entity")); - bool areAnyEntitiesSelected = false; - AzToolsFramework::ToolsApplicationRequestBus::BroadcastResult(areAnyEntitiesSelected, &AzToolsFramework::ToolsApplicationRequests::AreAnyEntitiesSelected); - action->setCheckable(areAnyEntitiesSelected || m_viewSourceType == ViewSourceType::AZ_Entity); - action->setEnabled(areAnyEntitiesSelected || m_viewSourceType == ViewSourceType::AZ_Entity); - action->setChecked(m_viewSourceType == ViewSourceType::AZ_Entity); - connect(action, &QAction::triggered, this, [this](bool isChecked) - { - if (isChecked) - { - AzToolsFramework::EntityIdList selectedEntityList; - AzToolsFramework::ToolsApplicationRequests::Bus::BroadcastResult(selectedEntityList, &AzToolsFramework::ToolsApplicationRequests::GetSelectedEntities); - if (selectedEntityList.size()) - { - SetEntityAsCamera(*selectedEntityList.begin()); - } - } - else - { - SetDefaultCamera(); - } - }); + // should this functionality be supported? You can already look through a camera entity + // in multiple different ways, and this additional method of doing so seems unneccessary and confusing + // (since it would select some arbitrary camera entity if there are multiple selected) + + //action = customCameraMenu->addAction(tr("Look through entity")); + //bool areAnyEntitiesSelected = false; + //AzToolsFramework::ToolsApplicationRequestBus::BroadcastResult(areAnyEntitiesSelected, &AzToolsFramework::ToolsApplicationRequests::AreAnyEntitiesSelected); + //action->setCheckable(areAnyEntitiesSelected || m_viewSourceType == ViewSourceType::AZ_Entity); + //action->setEnabled(areAnyEntitiesSelected || m_viewSourceType == ViewSourceType::AZ_Entity); + //action->setChecked(m_viewSourceType == ViewSourceType::AZ_Entity); + //connect(action, &QAction::triggered, this, [this](bool isChecked) + // { + // if (isChecked) + // { + // AzToolsFramework::EntityIdList selectedEntityList; + // AzToolsFramework::ToolsApplicationRequests::Bus::BroadcastResult(selectedEntityList, &AzToolsFramework::ToolsApplicationRequests::GetSelectedEntities); + // if (selectedEntityList.size()) + // { + // SetEntityAsCamera(*selectedEntityList.begin()); + // } + // } + // else + // { + // SetDefaultCamera(); + // } + // }); + return true; } @@ -1783,28 +1579,6 @@ void EditorViewportWidget::ResizeView(int width, int height) } } -////////////////////////////////////////////////////////////////////////// -void EditorViewportWidget::ToggleCameraObject() -{ - if (m_viewSourceType == ViewSourceType::SequenceCamera) - { - ResetToViewSourceType(ViewSourceType::LegacyCamera); - } - else - { - ResetToViewSourceType(ViewSourceType::SequenceCamera); - } - PostCameraSet(); - GetIEditor()->GetAnimation()->ForceAnimation(); -} - -////////////////////////////////////////////////////////////////////////// -void EditorViewportWidget::SetCamera(const CCamera& camera) -{ - m_Camera = camera; - SetViewTM(m_Camera.GetMatrix()); -} - ////////////////////////////////////////////////////////////////////////// EditorViewportWidget* EditorViewportWidget::GetPrimaryViewport() { @@ -1858,64 +1632,64 @@ void EditorViewportWidget::keyPressEvent(QKeyEvent* event) #endif // defined(AZ_PLATFORM_WINDOWS) } -void EditorViewportWidget::SetViewTM(const Matrix34& viewTM, bool bMoveOnly) +void EditorViewportWidget::SetViewTM(const Matrix34& tm) { - Matrix34 camMatrix = viewTM; - - // If no collision flag set do not check for terrain elevation. - if (GetType() == ET_ViewportCamera) + if (m_viewSourceType == ViewSourceType::None) { - if ((GetIEditor()->GetDisplaySettings()->GetSettings() & SETTINGS_NOCOLLISION) == 0) - { - Vec3 p = camMatrix.GetTranslation(); - bool adjustCameraElevation = true; - auto terrain = AzFramework::Terrain::TerrainDataRequestBus::FindFirstHandler(); - if (terrain) - { - AZ::Aabb terrainAabb(terrain->GetTerrainAabb()); - - // Adjust the AABB to include all Z values. Since the goal here is to snap the camera to the terrain height if - // it's below the terrain, we only want to verify the camera is within the XY bounds of the terrain to adjust the elevation. - terrainAabb.SetMin(AZ::Vector3(terrainAabb.GetMin().GetX(), terrainAabb.GetMin().GetY(), -AZ::Constants::FloatMax)); - terrainAabb.SetMax(AZ::Vector3(terrainAabb.GetMax().GetX(), terrainAabb.GetMax().GetY(), AZ::Constants::FloatMax)); - - if (!terrainAabb.Contains(LYVec3ToAZVec3(p))) - { - adjustCameraElevation = false; - } - else if (terrain->GetIsHoleFromFloats(p.x, p.y)) - { - adjustCameraElevation = false; - } - } - - if (adjustCameraElevation) - { - float z = GetIEditor()->GetTerrainElevation(p.x, p.y); - if (p.z < z + 0.25) - { - p.z = z + 0.25; - camMatrix.SetTranslation(p); - } - } - } - - // Also force this position on game. - if (GetIEditor()->GetGameEngine()) - { - GetIEditor()->GetGameEngine()->SetPlayerViewMatrix(viewTM); - } + m_defaultViewTM = tm; } + SetViewTM(tm, false); +} +void EditorViewportWidget::SetViewTM(const Matrix34& camMatrix, bool bMoveOnly) +{ + AZ_Warning("EditorViewportWidget", !bMoveOnly, "'Move Only' mode is deprecated"); CBaseObject* cameraObject = GetCameraObject(); - if (cameraObject) + + // Check if the active view entity is the same as the entity having the current view + // Sometimes this isn't the case because the active view is in the process of changing + // If it isn't, then we're doing the wrong thing below: we end up copying data from one (seemingly random) + // camera to another (seemingly random) camera + enum class ShouldUpdateObject { - // Ignore camera movement if locked. - if (IsCameraMovementLocked() || (!GetIEditor()->GetAnimation()->IsRecordMode() && !IsCameraObjectMove())) + Yes, No, YesButViewsOutOfSync + }; + + const ShouldUpdateObject shouldUpdateObject = [&]() { + if (!cameraObject) { - return; + return ShouldUpdateObject::No; } + if (m_viewSourceType == ViewSourceType::CameraComponent) + { + if (!m_viewEntityId.IsValid()) + { + // Should be impossible anyways + AZ_Assert(false, "Internal logic error - view entity Id and view source type out of sync. Please report this as a bug"); + return ShouldUpdateObject::No; + } + + // Check that the current view is the same view as the view entity view + AZ::RPI::ViewPtr viewEntityView; + AZ::RPI::ViewProviderBus::EventResult( + viewEntityView, m_viewEntityId, + &AZ::RPI::ViewProviderBus::Events::GetView + ); + + return viewEntityView == GetCurrentAtomView() ? ShouldUpdateObject::Yes : ShouldUpdateObject::YesButViewsOutOfSync; + } + else + { + AZ_Assert(false, "Internal logic error - view source type is the default camera, but there is somehow a camera object. Please report this as a bug."); + + // For non-component cameras, can't do any complicated view-based checks + return ShouldUpdateObject::No; + } + }(); + + if (shouldUpdateObject == ShouldUpdateObject::Yes) + { AZ::Matrix3x3 lookThroughEntityCorrection = AZ::Matrix3x3::CreateIdentity(); if (m_viewEntityId.IsValid()) { @@ -1924,89 +1698,77 @@ void EditorViewportWidget::SetViewTM(const Matrix34& viewTM, bool bMoveOnly) &LmbrCentral::EditorCameraCorrectionRequests::GetInverseTransformCorrection); } - if (m_pressedKeyState != KeyPressedState::PressedInPreviousFrame) + int flags = 0; { - AzToolsFramework::ScopedUndoBatch undo("Move Camera"); + // It isn't clear what this logic is supposed to do (it's legacy code)... + // For now, instead of removing it, just assert if the m_pressedKeyState isn't as expected + // Do not touch unless you really know what you're doing! + AZ_Assert(m_pressedKeyState == KeyPressedState::AllUp, "Internal logic error - key pressed state got changed. Please report this as a bug"); + + AZStd::optional undo; + if (m_pressedKeyState != KeyPressedState::PressedInPreviousFrame) + { + flags = eObjectUpdateFlags_UserInput; + undo.emplace("Move Camera"); + } + if (bMoveOnly) { - // specify eObjectUpdateFlags_UserInput so that an undo command gets logged - cameraObject->SetWorldPos(camMatrix.GetTranslation(), eObjectUpdateFlags_UserInput); + cameraObject->SetWorldPos(camMatrix.GetTranslation(), flags); } else { - // specify eObjectUpdateFlags_UserInput so that an undo command gets logged - cameraObject->SetWorldTM(camMatrix * AZMatrix3x3ToLYMatrix3x3(lookThroughEntityCorrection), eObjectUpdateFlags_UserInput); - } - } - else - { - if (bMoveOnly) - { - // Do not specify eObjectUpdateFlags_UserInput, so that an undo command does not get logged; we covered it already when m_pressedKeyState was PressedThisFrame - cameraObject->SetWorldPos(camMatrix.GetTranslation()); - } - else - { - // Do not specify eObjectUpdateFlags_UserInput, so that an undo command does not get logged; we covered it already when m_pressedKeyState was PressedThisFrame - cameraObject->SetWorldTM(camMatrix * AZMatrix3x3ToLYMatrix3x3(lookThroughEntityCorrection)); + cameraObject->SetWorldTM(camMatrix * AZMatrix3x3ToLYMatrix3x3(lookThroughEntityCorrection), flags); } } } - else if (m_viewEntityId.IsValid()) + else if (shouldUpdateObject == ShouldUpdateObject::YesButViewsOutOfSync) { - // Ignore camera movement if locked. - if (IsCameraMovementLocked() || (!GetIEditor()->GetAnimation()->IsRecordMode() && !IsCameraObjectMove())) - { - return; - } - - if (m_pressedKeyState != KeyPressedState::PressedInPreviousFrame) - { - AzToolsFramework::ScopedUndoBatch undo("Move Camera"); - if (bMoveOnly) - { - AZ::TransformBus::Event( - m_viewEntityId, &AZ::TransformInterface::SetWorldTranslation, - LYVec3ToAZVec3(camMatrix.GetTranslation())); - } - else - { - AZ::TransformBus::Event( - m_viewEntityId, &AZ::TransformInterface::SetWorldTM, - LYTransformToAZTransform(camMatrix)); - } - - AzToolsFramework::ToolsApplicationRequestBus::Broadcast(&AzToolsFramework::ToolsApplicationRequests::AddDirtyEntity, m_viewEntityId); - } - else - { - if (bMoveOnly) - { - AZ::TransformBus::Event( - m_viewEntityId, &AZ::TransformInterface::SetWorldTranslation, - LYVec3ToAZVec3(camMatrix.GetTranslation())); - } - else - { - AZ::TransformBus::Event( - m_viewEntityId, &AZ::TransformInterface::SetWorldTM, - LYTransformToAZTransform(camMatrix)); - } - } - - AzToolsFramework::PropertyEditorGUIMessages::Bus::Broadcast( - &AzToolsFramework::PropertyEditorGUIMessages::RequestRefresh, - AzToolsFramework::PropertyModificationRefreshLevel::Refresh_AttributesAndValues); + // Technically this should not cause anything to go wrong, but may indicate some underlying bug by a caller + // of SetViewTm, for example, trying to set the view TM in the middle of a camera change. + // If this is an important case, it can potentially be supported by caching the requested view TM + // until the entity and view ptr become synchronized. + AZ_Error("EditorViewportWidget", + m_playInEditorState == PlayInEditorState::Editor, + "Viewport camera entity ID and view out of sync; request view transform will be ignored. " + "Please report this as a bug." + ); } if (m_pressedKeyState == KeyPressedState::PressedThisFrame) { m_pressedKeyState = KeyPressedState::PressedInPreviousFrame; } +} - QtViewport::SetViewTM(camMatrix); +const Matrix34& EditorViewportWidget::GetViewTM() const +{ + // `m_viewTmStorage' is only required because we must return a reference + m_viewTmStorage = AZTransformToLYTransform(GetCurrentAtomView()->GetCameraTransform()); + return m_viewTmStorage; +}; - m_Camera.SetMatrix(camMatrix); +AZ::EntityId EditorViewportWidget::GetCurrentViewEntityId() +{ + // Sanity check that this camera entity ID is actually the camera entity which owns the current active render view + if (m_viewSourceType == ViewSourceType::CameraComponent) + { + // Check that the current view is the same view as the view entity view + AZ::RPI::ViewPtr viewEntityView; + AZ::RPI::ViewProviderBus::EventResult( + viewEntityView, m_viewEntityId, + &AZ::RPI::ViewProviderBus::Events::GetView + ); + + const bool isViewEntityCorrect = viewEntityView == GetCurrentAtomView(); + AZ_Error("EditorViewportWidget", isViewEntityCorrect, + "GetCurrentViewEntityId called while the current view is being changed. " + "You may get inconsistent results if you make use of the returned entity ID. " + "This is an internal error, please report it as a bug." + ); + } + + return m_viewEntityId; } ////////////////////////////////////////////////////////////////////////// @@ -2412,14 +2174,10 @@ void EditorViewportWidget::ViewToWorldRay(const QPoint& vp, Vec3& raySrc, Vec3& } ////////////////////////////////////////////////////////////////////////// -float EditorViewportWidget::GetScreenScaleFactor(const Vec3& worldPoint) const +float EditorViewportWidget::GetScreenScaleFactor([[maybe_unused]] const Vec3& worldPoint) const { - float dist = m_Camera.GetPosition().GetDistance(worldPoint); - if (dist < m_Camera.GetNearPlane()) - { - dist = m_Camera.GetNearPlane(); - } - return dist; + AZ_Error("CryLegacy", false, "EditorViewportWidget::GetScreenScaleFactor not implemented"); + return 1.f; } ////////////////////////////////////////////////////////////////////////// float EditorViewportWidget::GetScreenScaleFactor(const CCamera& camera, const Vec3& object_position) @@ -2429,12 +2187,6 @@ float EditorViewportWidget::GetScreenScaleFactor(const CCamera& camera, const Ve return dist; } -////////////////////////////////////////////////////////////////////////// -void EditorViewportWidget::OnDestroy() -{ - DestroyRenderContext(); -} - ////////////////////////////////////////////////////////////////////////// bool EditorViewportWidget::CheckRespondToInput() const { @@ -2454,7 +2206,7 @@ bool EditorViewportWidget::CheckRespondToInput() const ////////////////////////////////////////////////////////////////////////// bool EditorViewportWidget::HitTest(const QPoint& point, HitContext& hitInfo) { - hitInfo.camera = &m_Camera; + hitInfo.camera = nullptr; hitInfo.pExcludedObject = GetCameraObject(); return QtViewport::HitTest(point, hitInfo); } @@ -2462,8 +2214,12 @@ bool EditorViewportWidget::HitTest(const QPoint& point, HitContext& hitInfo) ////////////////////////////////////////////////////////////////////////// bool EditorViewportWidget::IsBoundsVisible(const AABB& box) const { + AZ_Assert(false, "Not supported"); + (void)box; + return false; + // If at least part of bbox is visible then its visible. - return m_Camera.IsAABBVisible_F(AABB(box.min, box.max)); + //return m_Camera.IsAABBVisible_F(AABB(box.min, box.max)); } ////////////////////////////////////////////////////////////////////////// @@ -2508,11 +2264,11 @@ void EditorViewportWidget::CenterOnAABB(const AABB& aabb) Matrix34 newTM = Matrix34(rotationMatrix, newPosition); // Set new orbit distance - m_orbitDistance = distanceToTarget; - m_orbitDistance = fabs(m_orbitDistance); + float orbitDistance = distanceToTarget; + orbitDistance = fabs(orbitDistance); SetViewTM(newTM); - SandboxEditor::OrbitCameraControlsBus::Event(GetViewportId(), &SandboxEditor::OrbitCameraControlsBus::Events::SetOrbitDistance, m_orbitDistance); + SandboxEditor::OrbitCameraControlsBus::Event(GetViewportId(), &SandboxEditor::OrbitCameraControlsBus::Events::SetOrbitDistance, orbitDistance); } void EditorViewportWidget::CenterOnSliceInstance() @@ -2562,130 +2318,123 @@ void EditorViewportWidget::SetFOV(float fov) { if (m_viewEntityId.IsValid()) { - Camera::CameraRequestBus::Event(m_viewEntityId, &Camera::CameraComponentRequests::SetFov, AZ::RadToDeg(fov)); + Camera::CameraRequestBus::Event(m_viewEntityId, &Camera::CameraComponentRequests::SetFovRadians, fov); } else { - m_camFOV = fov; - // Set the active camera's FOV - { - AZ::Matrix4x4 clipMatrix; - AZ::MakePerspectiveFovMatrixRH( - clipMatrix, - GetFOV(), - aznumeric_cast(width()) / aznumeric_cast(height()), - m_Camera.GetNearPlane(), - m_Camera.GetFarPlane(), - true - ); - m_renderViewport->GetViewportContext()->SetCameraProjectionMatrix(clipMatrix); - } - } - - if (m_viewPane) - { - m_viewPane->OnFOVChanged(fov); + auto m = m_defaultView->GetViewToClipMatrix(); + AZ::SetPerspectiveMatrixFOV(m, fov, aznumeric_cast(width()) / aznumeric_cast(height())); + m_defaultView->SetViewToClipMatrix(m); } } ////////////////////////////////////////////////////////////////////////// float EditorViewportWidget::GetFOV() const { - if (m_viewSourceType == ViewSourceType::SequenceCamera) - { - CBaseObject* cameraObject = GetCameraObject(); - - AZ::EntityId cameraEntityId; - AzToolsFramework::ComponentEntityObjectRequestBus::EventResult(cameraEntityId, cameraObject, &AzToolsFramework::ComponentEntityObjectRequestBus::Events::GetAssociatedEntityId); - if (cameraEntityId.IsValid()) - { - // component Camera - float fov = DEFAULT_FOV; - Camera::CameraRequestBus::EventResult(fov, cameraEntityId, &Camera::CameraComponentRequests::GetFov); - return AZ::DegToRad(fov); - } - } - if (m_viewEntityId.IsValid()) { - float fov = AZ::RadToDeg(m_camFOV); - Camera::CameraRequestBus::EventResult(fov, m_viewEntityId, &Camera::CameraComponentRequests::GetFov); - return AZ::DegToRad(fov); + float fov = 0.f; // AZ::RadToDeg(m_camFOV); + Camera::CameraRequestBus::EventResult(fov, m_viewEntityId, &Camera::CameraComponentRequests::GetFovRadians); + return fov; + } + else + { + return AZ::GetPerspectiveMatrixFOV(m_defaultView->GetViewToClipMatrix()); + } +} + +void EditorViewportWidget::OnActiveViewChanged(const AZ::EntityId& viewEntityId) +{ + // Avoid re-entry + if (m_sendingOnActiveChanged) + { + return; } - return m_camFOV; -} + // Ignore any changes in simulation mode + if (m_playInEditorState != PlayInEditorState::Editor) + { + return; + } -////////////////////////////////////////////////////////////////////////// -bool EditorViewportWidget::CreateRenderContext() -{ - return true; -} + // if they've picked the same camera, then that means they want to toggle + if (viewEntityId.IsValid()) + { + // Any such events for game entities should be filtered out by the check above + AZ_Error( + "EditorViewportWidget", + Camera::EditorCameraViewRequestBus::FindFirstHandler(viewEntityId) != nullptr, + "Internal logic error - active view changed to an entity which is not an editor camera. " + "Please report this as a bug." + ); -////////////////////////////////////////////////////////////////////////// -void EditorViewportWidget::DestroyRenderContext() -{ + m_viewEntityId = viewEntityId; + m_viewSourceType = ViewSourceType::CameraComponent; + AZStd::string entityName; + AZ::ComponentApplicationBus::BroadcastResult(entityName, &AZ::ComponentApplicationRequests::GetEntityName, viewEntityId); + SetName(QString("Camera entity: %1").arg(entityName.c_str())); + + PostCameraSet(); + } + else + { + SetDefaultCamera(); + } } ////////////////////////////////////////////////////////////////////////// void EditorViewportWidget::SetDefaultCamera() { - if (IsDefaultCamera()) - { - return; - } - ResetToViewSourceType(ViewSourceType::None); - GetViewManager()->SetCameraObjectId(m_cameraObjectId); + m_viewEntityId.SetInvalid(); + m_viewSourceType = ViewSourceType::None; + GetViewManager()->SetCameraObjectId(GUID_NULL); SetName(m_defaultViewName); SetViewTM(m_defaultViewTM); + + // Synchronize the configured editor viewport FOV to the default camera + if (m_viewPane) + { + const float fov = gSettings.viewports.fDefaultFov; + m_viewPane->OnFOVChanged(fov); + SetFOV(fov); + } + + // Push the default view as the active view + auto atomViewportRequests = AZ::Interface::Get(); + if (atomViewportRequests) + { + const AZ::Name contextName = atomViewportRequests->GetDefaultViewportContextName(); + atomViewportRequests->PushView(contextName, m_defaultView); + } + PostCameraSet(); } ////////////////////////////////////////////////////////////////////////// -bool EditorViewportWidget::IsDefaultCamera() const +AZ::RPI::ViewPtr EditorViewportWidget::GetCurrentAtomView() const { - return m_viewSourceType == ViewSourceType::None; -} - -////////////////////////////////////////////////////////////////////////// -void EditorViewportWidget::SetSequenceCamera() -{ - if (m_viewSourceType == ViewSourceType::SequenceCamera) + auto atomViewportRequests = AZ::Interface::Get(); + if (atomViewportRequests) { - // Reset if we were checked before - SetDefaultCamera(); + const AZ::Name contextName = atomViewportRequests->GetDefaultViewportContextName(); + return atomViewportRequests->GetCurrentView(contextName); } else { - ResetToViewSourceType(ViewSourceType::SequenceCamera); - - SetName(tr("Sequence Camera")); - SetViewTM(GetViewTM()); - - GetViewManager()->SetCameraObjectId(m_cameraObjectId); - PostCameraSet(); - - // ForceAnimation() so Track View will set the Camera params - // if a camera is animated in the sequences. - if (GetIEditor() && GetIEditor()->GetAnimation()) - { - GetIEditor()->GetAnimation()->ForceAnimation(); - } + return nullptr; } } ////////////////////////////////////////////////////////////////////////// void EditorViewportWidget::SetComponentCamera(const AZ::EntityId& entityId) { - ResetToViewSourceType(ViewSourceType::CameraComponent); - SetViewEntity(entityId); + SetViewFromEntityPerspective(entityId); } ////////////////////////////////////////////////////////////////////////// void EditorViewportWidget::SetEntityAsCamera(const AZ::EntityId& entityId, bool lockCameraMovement) { - ResetToViewSourceType(ViewSourceType::AZ_Entity); - SetViewEntity(entityId, lockCameraMovement); + SetViewAndMovementLockFromEntityPerspective(entityId, lockCameraMovement); } void EditorViewportWidget::SetFirstComponentCamera() @@ -2733,7 +2482,7 @@ bool EditorViewportWidget::IsSelectedCamera() const AzToolsFramework::ToolsApplicationRequests::Bus::BroadcastResult( selectedEntityList, &AzToolsFramework::ToolsApplicationRequests::GetSelectedEntities); - if ((m_viewSourceType == ViewSourceType::CameraComponent || m_viewSourceType == ViewSourceType::AZ_Entity) + if ((m_viewSourceType == ViewSourceType::CameraComponent) && !selectedEntityList.empty() && AZStd::find(selectedEntityList.begin(), selectedEntityList.end(), m_viewEntityId) != selectedEntityList.end()) { @@ -2755,17 +2504,17 @@ void EditorViewportWidget::CycleCamera() SetFirstComponentCamera(); break; } - case EditorViewportWidget::ViewSourceType::SequenceCamera: - { - AZ_Error("EditorViewportWidget", false, "Legacy cameras no longer exist, unable to set sequence camera."); - break; - } - case EditorViewportWidget::ViewSourceType::LegacyCamera: - { - AZ_Warning("EditorViewportWidget", false, "Legacy cameras no longer exist, using first found component camera instead."); - SetFirstComponentCamera(); - break; - } + //case EditorViewportWidget::ViewSourceType::SequenceCamera: + //{ + // AZ_Error("EditorViewportWidget", false, "Legacy cameras no longer exist, unable to set sequence camera."); + // break; + //} + //case EditorViewportWidget::ViewSourceType::LegacyCamera: + //{ + // AZ_Warning("EditorViewportWidget", false, "Legacy cameras no longer exist, using first found component camera instead."); + // SetFirstComponentCamera(); + // break; + //} case EditorViewportWidget::ViewSourceType::CameraComponent: { AZ::EBusAggregateResults results; @@ -2784,12 +2533,12 @@ void EditorViewportWidget::CycleCamera() SetDefaultCamera(); break; } - case EditorViewportWidget::ViewSourceType::AZ_Entity: - { - // we may decide to have this iterate over just selected entities - SetDefaultCamera(); - break; - } + //case EditorViewportWidget::ViewSourceType::AZ_Entity: + //{ + // // we may decide to have this iterate over just selected entities + // SetDefaultCamera(); + // break; + //} default: { SetDefaultCamera(); @@ -2803,11 +2552,28 @@ void EditorViewportWidget::SetViewFromEntityPerspective(const AZ::EntityId& enti SetViewAndMovementLockFromEntityPerspective(entityId, false); } -void EditorViewportWidget::SetViewAndMovementLockFromEntityPerspective(const AZ::EntityId& entityId, bool lockCameraMovement) +void EditorViewportWidget::SetViewAndMovementLockFromEntityPerspective(const AZ::EntityId& entityId, [[maybe_unused]] bool lockCameraMovement) { - if (!m_ignoreSetViewFromEntityPerspective) + // This is an editor event, so is only serviced during edit mode, not play game mode + // + if (m_playInEditorState != PlayInEditorState::Editor) { - SetEntityAsCamera(entityId, lockCameraMovement); + AZ_Warning("EditorViewportWidget", false, + "Tried to change the editor camera during play game in editor; this is currently unsupported" + ); + return; + } + + AZ_Assert(lockCameraMovement == false, "SetViewAndMovementLockFromEntityPerspective with lockCameraMovement == true not supported"); + + if (entityId.IsValid()) + { + EBUS_EVENT_ID(entityId, Camera::CameraRequestBus, MakeActiveView); + } + else + { + // The default camera + SetDefaultCamera(); } } @@ -2822,7 +2588,7 @@ bool EditorViewportWidget::GetActiveCameraPosition(AZ::Vector3& cameraPos) else { // Use viewTM, which is synced with the camera and guaranteed to be up-to-date - cameraPos = LYVec3ToAZVec3(m_viewTM.GetTranslation()); + cameraPos = LYVec3ToAZVec3(GetViewTM().GetTranslation()); } return true; @@ -2836,17 +2602,26 @@ bool EditorViewportWidget::GetActiveCameraState(AzFramework::CameraState& camera if (m_pPrimaryViewport == this) { cameraState = GetCameraState(); - return true; } return false; } +void EditorViewportWidget::OnStartPlayInEditorBegin() +{ + m_playInEditorState = PlayInEditorState::Starting; +} + void EditorViewportWidget::OnStartPlayInEditor() { + m_playInEditorState = PlayInEditorState::Started; + if (m_viewEntityId.IsValid()) { + // Note that this is assuming that the Atom camera components will share the same view ptr + // in editor as in game mode + m_viewEntityIdCachedForEditMode = m_viewEntityId; AZ::EntityId runtimeEntityId; AzToolsFramework::EditorEntityContextRequestBus::Broadcast( @@ -2859,20 +2634,14 @@ void EditorViewportWidget::OnStartPlayInEditor() void EditorViewportWidget::OnStopPlayInEditor() { - if (m_viewEntityIdCachedForEditMode.IsValid()) - { - m_viewEntityId = m_viewEntityIdCachedForEditMode; - m_viewEntityIdCachedForEditMode.SetInvalid(); - } -} + m_playInEditorState = PlayInEditorState::Editor; -////////////////////////////////////////////////////////////////////////// -void EditorViewportWidget::OnCameraFOVVariableChanged([[maybe_unused]] IVariable* var) -{ - if (m_viewPane) - { - m_viewPane->OnFOVChanged(GetFOV()); - } + // Note that: + // - this is assuming that the Atom camera components will share the same view ptr in editor as in game mode. + // - if `m_viewEntityIdCachedForEditMode' is invalid, the camera before game mode was the default editor camera + // - we MUST set the camera again when exiting game mode, because when rendering with trackview, the editor camera gets set somehow + SetViewFromEntityPerspective(m_viewEntityIdCachedForEditMode); + m_viewEntityIdCachedForEditMode.SetInvalid(); } ////////////////////////////////////////////////////////////////////////// @@ -2905,11 +2674,6 @@ void EditorViewportWidget::ShowCursor() m_bCursorHidden = false; } -bool EditorViewportWidget::IsKeyDown(Qt::Key key) const -{ - return m_keyDown.contains(key); -} - ////////////////////////////////////////////////////////////////////////// void EditorViewportWidget::PushDisableRendering() { @@ -2947,6 +2711,17 @@ QSize EditorViewportWidget::WidgetToViewport(const QSize& size) const return size * WidgetToViewportFactor(); } +////////////////////////////////////////////////////////////////////////// +double EditorViewportWidget::WidgetToViewportFactor() const +{ +#if defined(AZ_PLATFORM_WINDOWS) + // Needed for high DPI mode on windows + return devicePixelRatioF(); +#else + return 1.0; +#endif +} + ////////////////////////////////////////////////////////////////////////// void EditorViewportWidget::BeginUndoTransaction() { @@ -2960,12 +2735,6 @@ void EditorViewportWidget::EndUndoTransaction() Update(); } -void EditorViewportWidget::UpdateCurrentMousePos(const QPoint& newPosition) -{ - m_prevMousePos = m_mousePos; - m_mousePos = newPosition; -} - void* EditorViewportWidget::GetSystemCursorConstraintWindow() const { AzFramework::SystemCursorState systemCursorState = AzFramework::SystemCursorState::Unknown; @@ -3041,7 +2810,8 @@ void EditorViewportWidget::RestoreViewportAfterGameMode() } else { - SetViewTM(m_gameTM); + AZ_Error("CryLegacy", false, "Not restoring the editor viewport camera is currently unsupported"); + SetViewTM(preGameModeViewTM); } } @@ -3060,12 +2830,6 @@ void EditorViewportWidget::UpdateScene() } } -void EditorViewportWidget::UpdateCameraFromViewportContext() -{ - // Queue a sync for the next tick, to ensure the latest version of the viewport context transform is used - m_updateCameraPositionNextTick = true; -} - void EditorViewportWidget::SetAsActiveViewport() { auto viewportContextManager = AZ::Interface::Get(); @@ -3125,7 +2889,7 @@ float EditorViewportSettings::AngleStep() const AZ_CVAR_EXTERNED(bool, ed_previewGameInFullscreen_once); -bool EditorViewportWidget::ShouldPreviewFullscreen() const +bool EditorViewportWidget::ShouldPreviewFullscreen() { CLayoutWnd* layout = GetIEditor()->GetViewManager()->GetLayout(); if (!layout) @@ -3134,25 +2898,16 @@ bool EditorViewportWidget::ShouldPreviewFullscreen() const return false; } - // Doesn't work with split layout - if (layout->GetLayout() != EViewLayout::ET_Layout0) - { - return false; - } + // Doesn't work with split layout (TODO: figure out why and make it work) + if (layout->GetLayout() != EViewLayout::ET_Layout0) { return false; } // Not supported in VR - if (gSettings.bEnableGameModeVR) - { - return false; - } + if (gSettings.bEnableGameModeVR) { return false; } // If level not loaded, don't preview in fullscreen (preview shouldn't work at all without a level, but it does) if (auto ge = GetIEditor()->GetGameEngine()) { - if (!ge->IsLevelLoaded()) - { - return false; - } + if (!ge->IsLevelLoaded()) { return false; } } // Check 'ed_previewGameInFullscreen_once' @@ -3169,12 +2924,12 @@ bool EditorViewportWidget::ShouldPreviewFullscreen() const void EditorViewportWidget::StartFullscreenPreview() { - AZ_Assert(!m_inFullscreenPreview, "EditorViewportWidget::StartFullscreenPreview called when already in full screen preview"); + AZ_Assert(!m_inFullscreenPreview, AZ_FUNCTION_SIGNATURE " - called when already in full screen preview"); m_inFullscreenPreview = true; // Pick the screen on which the main window lies to use as the screen for the full screen preview - const QScreen* screen = MainWindow::instance()->screen(); - const QRect screenGeometry = screen->geometry(); + QScreen* screen = MainWindow::instance()->screen(); + QRect screenGeometry = screen->geometry(); // Unparent this and show it, which turns it into a free floating window // Also set style to frameless and disable resizing by user diff --git a/Code/Editor/EditorViewportWidget.h b/Code/Editor/EditorViewportWidget.h index 1829995d02..d17a8acb52 100644 --- a/Code/Editor/EditorViewportWidget.h +++ b/Code/Editor/EditorViewportWidget.h @@ -34,6 +34,7 @@ #include #include #include +#include #endif #include @@ -65,130 +66,120 @@ namespace AzToolsFramework // EditorViewportWidget window AZ_PUSH_DISABLE_DLL_EXPORT_BASECLASS_WARNING AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING -class SANDBOX_API EditorViewportWidget +class SANDBOX_API EditorViewportWidget final : public QtViewport - , public IEditorNotifyListener - , public IUndoManagerListener - , public Camera::EditorCameraRequestBus::Handler - , public AzFramework::InputSystemCursorConstraintRequestBus::Handler - , public AzToolsFramework::ViewportInteraction::ViewportFreezeRequestBus::Handler - , public AzToolsFramework::ViewportInteraction::MainEditorViewportInteractionRequestBus::Handler - , public AzFramework::AssetCatalogEventBus::Handler - , public AZ::RPI::SceneNotificationBus::Handler + , private IEditorNotifyListener + , private IUndoManagerListener + , private Camera::EditorCameraRequestBus::Handler + , private Camera::CameraNotificationBus::Handler + , private AzFramework::InputSystemCursorConstraintRequestBus::Handler + , private AzToolsFramework::ViewportInteraction::ViewportFreezeRequestBus::Handler + , private AzToolsFramework::ViewportInteraction::MainEditorViewportInteractionRequestBus::Handler + , private AzFramework::AssetCatalogEventBus::Handler + , private AZ::RPI::SceneNotificationBus::Handler { AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING AZ_POP_DISABLE_DLL_EXPORT_BASECLASS_WARNING Q_OBJECT -public: - struct SResolution - { - SResolution() - : width(0) - , height(0) - { - } - - SResolution(int w, int h) - : width(w) - , height(h) - { - } - - int width; - int height; - }; public: EditorViewportWidget(const QString& name, QWidget* parent = nullptr); + ~EditorViewportWidget() override; static const GUID& GetClassID() { return QtViewport::GetClassID(); } - /** Get type of this viewport. - */ - virtual EViewportType GetType() const { return ET_ViewportCamera; } - virtual void SetType([[maybe_unused]] EViewportType type) { assert(type == ET_ViewportCamera); }; + static EditorViewportWidget* GetPrimaryViewport(); - virtual ~EditorViewportWidget(); + // Used by ViewPan in some circumstances + void ConnectViewportInteractionRequestBus(); + void DisconnectViewportInteractionRequestBus(); - Q_INVOKABLE void InjectFakeMouseMove(int deltaX, int deltaY, Qt::MouseButtons buttons); + // QtViewport/IDisplayViewport/CViewport + // These methods are made public in the derived class because they are called with an object whose static type is known to be this class type. + void SetFOV(float fov) override; + float GetFOV() const override; - // Replacement for still used CRenderer methods - void UnProjectFromScreen(float sx, float sy, float sz, float* px, float* py, float* pz) const; - void ProjectToScreen(float ptx, float pty, float ptz, float* sx, float* sy, float* sz) const; +private: + //////////////////////////////////////////////////////////////////////// + // Private types ... -public: - virtual void Update(); - - virtual void ResetContent(); - virtual void UpdateContent(int flags); - - void OnTitleMenu(QMenu* menu) override; - - void SetCamera(const CCamera& camera); - const CCamera& GetCamera() const { return m_Camera; }; - virtual void SetViewTM(const Matrix34& tm) + enum class ViewSourceType { - if (m_viewSourceType == ViewSourceType::None) - { - m_defaultViewTM = tm; - } - SetViewTM(tm, false); - } + None, + CameraComponent, + ViewSourceTypesCount, + }; + enum class PlayInEditorState + { + Editor, Starting, Started + }; + enum class KeyPressedState + { + AllUp, + PressedThisFrame, + PressedInPreviousFrame, + }; - //! Map world space position to viewport position. - virtual QPoint WorldToView(const Vec3& wp) const; - virtual QPoint WorldToViewParticleEditor(const Vec3& wp, int width, int height) const; - virtual Vec3 WorldToView3D(const Vec3& wp, int nFlags = 0) const; - - //! Map viewport position to world space position. - virtual Vec3 ViewToWorld(const QPoint& vp, bool* collideWithTerrain = nullptr, bool onlyTerrain = false, bool bSkipVegetation = false, bool bTestRenderMesh = false, bool* collideWithObject = nullptr) const override; - virtual void ViewToWorldRay(const QPoint& vp, Vec3& raySrc, Vec3& rayDir) const override; - virtual Vec3 ViewToWorldNormal(const QPoint& vp, bool onlyTerrain, bool bTestRenderMesh = false) override; - virtual float GetScreenScaleFactor(const Vec3& worldPoint) const; - virtual float GetScreenScaleFactor(const CCamera& camera, const Vec3& object_position); - virtual float GetAspectRatio() const; - virtual bool HitTest(const QPoint& point, HitContext& hitInfo); - virtual bool IsBoundsVisible(const AABB& box) const; - virtual void CenterOnSelection(); - virtual void CenterOnAABB(const AABB& aabb); - void CenterOnSliceInstance() override; + //////////////////////////////////////////////////////////////////////// + // Method overrides ... + // QWidget void focusOutEvent(QFocusEvent* event) override; void keyPressEvent(QKeyEvent* event) override; + bool event(QEvent* event) override; + void resizeEvent(QResizeEvent* event) override; + void paintEvent(QPaintEvent* event) override; + void mousePressEvent(QMouseEvent* event) override; - void SetFOV(float fov); - float GetFOV() const; + // QtViewport/IDisplayViewport/CViewport + EViewportType GetType() const override { return ET_ViewportCamera; } + void SetType([[maybe_unused]] EViewportType type) override { assert(type == ET_ViewportCamera); }; + AzToolsFramework::ViewportInteraction::MouseInteraction BuildMouseInteraction( + Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, const QPoint& point) override; + void SetViewportId(int id) override; + QPoint WorldToView(const Vec3& wp) const override; + QPoint WorldToViewParticleEditor(const Vec3& wp, int width, int height) const override; + Vec3 WorldToView3D(const Vec3& wp, int nFlags = 0) const override; + Vec3 ViewToWorld(const QPoint& vp, bool* collideWithTerrain = nullptr, bool onlyTerrain = false, bool bSkipVegetation = false, bool bTestRenderMesh = false, bool* collideWithObject = nullptr) const override; + void ViewToWorldRay(const QPoint& vp, Vec3& raySrc, Vec3& rayDir) const override; + Vec3 ViewToWorldNormal(const QPoint& vp, bool onlyTerrain, bool bTestRenderMesh = false) override; + float GetScreenScaleFactor(const Vec3& worldPoint) const override; + float GetScreenScaleFactor(const CCamera& camera, const Vec3& object_position) override; + float GetAspectRatio() const override; + bool HitTest(const QPoint& point, HitContext& hitInfo) override; + bool IsBoundsVisible(const AABB& box) const override; + void CenterOnSelection() override; + void CenterOnAABB(const AABB& aabb) override; + void CenterOnSliceInstance() override; + void OnTitleMenu(QMenu* menu) override; + void SetViewTM(const Matrix34& tm) override; + const Matrix34& GetViewTM() const override; + void Update() override; + void UpdateContent(int flags) override; - void SetDefaultCamera(); - bool IsDefaultCamera() const; - void SetSequenceCamera(); - bool IsSequenceCamera() const { return m_viewSourceType == ViewSourceType::SequenceCamera; } - void SetSelectedCamera(); - bool IsSelectedCamera() const; - void SetComponentCamera(const AZ::EntityId& entityId); - void SetEntityAsCamera(const AZ::EntityId& entityId, bool lockCameraMovement = false); - void SetFirstComponentCamera(); - void SetViewEntity(const AZ::EntityId& cameraEntityId, bool lockCameraMovement = false); - void PostCameraSet(); - // This switches the active camera to the next one in the list of (default, all custom cams). - void CycleCamera(); + // SceneNotificationBus + void OnBeginPrepareRender() override; - // Camera::EditorCameraRequestBus - void SetViewFromEntityPerspective(const AZ::EntityId& entityId) override; - void SetViewAndMovementLockFromEntityPerspective(const AZ::EntityId& entityId, bool lockCameraMovement) override; - AZ::EntityId GetCurrentViewEntityId() override { return m_viewEntityId; } - bool GetActiveCameraPosition(AZ::Vector3& cameraPos) override; - bool GetActiveCameraState(AzFramework::CameraState& cameraState) override; + // Camera::CameraNotificationBus + void OnActiveViewChanged(const AZ::EntityId&) override; + + // IEditorEventListener + void OnEditorNotifyEvent(EEditorNotifyEvent event) override; // AzToolsFramework::EditorEntityContextNotificationBus (handler moved to cpp to resolve link issues in unity builds) - virtual void OnStartPlayInEditor(); - virtual void OnStopPlayInEditor(); + void OnStartPlayInEditor(); + void OnStopPlayInEditor(); + void OnStartPlayInEditorBegin(); - AzFramework::CameraState GetCameraState(); - AzFramework::ScreenPoint ViewportWorldToScreen(const AZ::Vector3& worldPosition); + // IUndoManagerListener + void BeginUndoTransaction() override; + void EndUndoTransaction() override; + + // AzFramework::InputSystemCursorConstraintRequestBus + void* GetSystemCursorConstraintWindow() const override; // AzToolsFramework::ViewportFreezeRequestBus bool IsViewportInputFrozen() override; @@ -204,142 +195,19 @@ public: void BeginWidgetContext() override; void EndWidgetContext() override; - // CViewport... - void SetViewportId(int id) override; - - void ConnectViewportInteractionRequestBus(); - void DisconnectViewportInteractionRequestBus(); - - void LockCameraMovement(bool bLock) { m_bLockCameraMovement = bLock; } - bool IsCameraMovementLocked() const { return m_bLockCameraMovement; } - - void EnableCameraObjectMove(bool bMove) { m_bMoveCameraObject = bMove; } - bool IsCameraObjectMove() const { return m_bMoveCameraObject; } - - void SetPlayerControl(uint32 i) { m_PlayerControl = i; }; - uint32 GetPlayerControl() { return m_PlayerControl; }; - - const DisplayContext& GetDisplayContext() const { return m_displayContext; } - CBaseObject* GetCameraObject() const; - - QPoint WidgetToViewport(const QPoint& point) const; - QPoint ViewportToWidget(const QPoint& point) const; - QSize WidgetToViewport(const QSize& size) const; - - AzToolsFramework::ViewportInteraction::MouseInteraction BuildMouseInteraction( - Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, const QPoint& point) override; - - void SetPlayerPos() - { - Matrix34 m = GetViewTM(); - m.SetTranslation(m.GetTranslation() - m_PhysicalLocation.t); - SetViewTM(m); - - m_AverageFrameTime = 0.14f; - - m_PhysicalLocation.SetIdentity(); - - m_LocalEntityMat.SetIdentity(); - m_PrevLocalEntityMat.SetIdentity(); - - m_absCameraHigh = 2.0f; - m_absCameraPos = Vec3(0, 3, 2); - m_absCameraPosVP = Vec3(0, -3, 1.5); - - m_absCurrentSlope = 0.0f; - - m_absLookDirectionXY = Vec2(0, 1); - - m_LookAt = Vec3(ZERO); - m_LookAtRate = Vec3(ZERO); - m_vCamPos = Vec3(ZERO); - m_vCamPosRate = Vec3(ZERO); - - m_relCameraRotX = 0; - m_relCameraRotZ = 0; - - uint32 numSample6 = m_arrAnimatedCharacterPath.size(); - for (uint32 i = 0; i < numSample6; i++) - { - m_arrAnimatedCharacterPath[i] = Vec3(ZERO); - } - - numSample6 = m_arrSmoothEntityPath.size(); - for (uint32 i = 0; i < numSample6; i++) - { - m_arrSmoothEntityPath[i] = Vec3(ZERO); - } - - uint32 numSample7 = m_arrRunStrafeSmoothing.size(); - for (uint32 i = 0; i < numSample7; i++) - { - m_arrRunStrafeSmoothing[i] = 0; - } - - m_vWorldDesiredBodyDirection = Vec2(0, 1); - m_vWorldDesiredBodyDirectionSmooth = Vec2(0, 1); - m_vWorldDesiredBodyDirectionSmoothRate = Vec2(0, 1); - - m_vWorldDesiredBodyDirection2 = Vec2(0, 1); - - m_vWorldDesiredMoveDirection = Vec2(0, 1); - m_vWorldDesiredMoveDirectionSmooth = Vec2(0, 1); - m_vWorldDesiredMoveDirectionSmoothRate = Vec2(0, 1); - m_vLocalDesiredMoveDirection = Vec2(0, 1); - m_vLocalDesiredMoveDirectionSmooth = Vec2(0, 1); - m_vLocalDesiredMoveDirectionSmoothRate = Vec2(0, 1); - - m_vWorldAimBodyDirection = Vec2(0, 1); - - m_MoveSpeedMSec = 5.0f; - m_key_W = 0; - m_keyrcr_W = 0; - m_key_S = 0; - m_keyrcr_S = 0; - m_key_A = 0; - m_keyrcr_A = 0; - m_key_D = 0; - m_keyrcr_D = 0; - m_key_SPACE = 0; - m_keyrcr_SPACE = 0; - m_ControllMode = 0; - - m_State = -1; - m_Stance = 1; //combat - - m_udGround = 0.0f; - m_lrGround = 0.0f; - AABB aabb = AABB(Vec3(-40.0f, -40.0f, -0.25f), Vec3(+40.0f, +40.0f, +0.0f)); - m_GroundOBB = OBB::CreateOBBfromAABB(Matrix33(IDENTITY), aabb); - m_GroundOBBPos = Vec3(0, 0, -0.01f); - }; - - static EditorViewportWidget* GetPrimaryViewport(); - - AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING - CCamera m_Camera; - AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING - -protected: - struct SScopedCurrentContext; + // Camera::EditorCameraRequestBus + void SetViewFromEntityPerspective(const AZ::EntityId& entityId) override; + void SetViewAndMovementLockFromEntityPerspective(const AZ::EntityId& entityId, bool lockCameraMovement) override; + AZ::EntityId GetCurrentViewEntityId() override; + bool GetActiveCameraPosition(AZ::Vector3& cameraPos) override; + bool GetActiveCameraState(AzFramework::CameraState& cameraState) override; + //////////////////////////////////////////////////////////////////////// + // Private helpers... void SetViewTM(const Matrix34& tm, bool bMoveOnly); - - // Called to render stuff. - virtual void OnRender(); - - virtual void OnEditorNotifyEvent(EEditorNotifyEvent event); - - //! Get currently active camera object. - void ToggleCameraObject(); - - void RenderConstructionPlane(); void RenderSnapMarker(); - void RenderAll(); - void OnBeginPrepareRender() override; - // Update the safe frame, safe action, safe title, and borders rectangles based on // viewport size and target aspect ratio. void UpdateSafeFrame(); @@ -353,193 +221,41 @@ protected: // Draw a selected region if it has been selected void RenderSelectedRegion(); - virtual bool CreateRenderContext(); - virtual void DestroyRenderContext(); - - void OnMenuCommandChangeAspectRatio(unsigned int commandId); - bool AdjustObjectPosition(const ray_hit& hit, Vec3& outNormal, Vec3& outPos) const; bool RayRenderMeshIntersection(IRenderMesh* pRenderMesh, const Vec3& vInPos, const Vec3& vInDir, Vec3& vOutPos, Vec3& vOutNormal) const; bool AddCameraMenuItems(QMenu* menu); void ResizeView(int width, int height); - void OnCameraFOVVariableChanged(IVariable* var); - void HideCursor(); void ShowCursor(); - bool IsKeyDown(Qt::Key key) const; + double WidgetToViewportFactor() const; - enum class ViewSourceType - { - None, - SequenceCamera, - LegacyCamera, - CameraComponent, - AZ_Entity, - ViewSourceTypesCount, - }; - void ResetToViewSourceType(const ViewSourceType& viewSourType); - - bool ShouldPreviewFullscreen() const; + bool ShouldPreviewFullscreen(); void StartFullscreenPreview(); void StopFullscreenPreview(); - bool m_inFullscreenPreview = false; - bool m_bRenderContextCreated = false; - bool m_bInRotateMode = false; - bool m_bInMoveMode = false; - bool m_bInOrbitMode = false; - bool m_bInZoomMode = false; - - QPoint m_mousePos = QPoint(0, 0); - QPoint m_prevMousePos = QPoint(0, 0); // for tablets, you can't use SetCursorPos and need to remember the prior point and delta with that. - - - float m_moveSpeed = 1; - - float m_orbitDistance = 10.0f; - AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING - Vec3 m_orbitTarget; - - //------------------------------------------- - //--- player-control in CharEdit --- - //------------------------------------------- - f32 m_MoveSpeedMSec; - - uint32 m_key_W, m_keyrcr_W; - uint32 m_key_S, m_keyrcr_S; - uint32 m_key_A, m_keyrcr_A; - uint32 m_key_D, m_keyrcr_D; - - uint32 m_key_SPACE, m_keyrcr_SPACE; - uint32 m_ControllMode; - - int32 m_Stance; - int32 m_State; - f32 m_AverageFrameTime; - - uint32 m_PlayerControl = 0; - - f32 m_absCameraHigh; - Vec3 m_absCameraPos; - Vec3 m_absCameraPosVP; - - f32 m_absCurrentSlope; //in radiants - - Vec2 m_absLookDirectionXY; - - Vec3 m_LookAt; - Vec3 m_LookAtRate; - Vec3 m_vCamPos; - Vec3 m_vCamPosRate; - float m_camFOV; - - f32 m_relCameraRotX; - f32 m_relCameraRotZ; - - QuatTS m_PhysicalLocation; - - Matrix34 m_AnimatedCharacterMat; - - Matrix34 m_LocalEntityMat; //this is used for data-driven animations where the character is running on the spot - Matrix34 m_PrevLocalEntityMat; - - std::vector m_arrVerticesHF; - std::vector m_arrIndicesHF; - - std::vector m_arrAnimatedCharacterPath; - std::vector m_arrSmoothEntityPath; - std::vector m_arrRunStrafeSmoothing; - - Vec2 m_vWorldDesiredBodyDirection; - Vec2 m_vWorldDesiredBodyDirectionSmooth; - Vec2 m_vWorldDesiredBodyDirectionSmoothRate; - - Vec2 m_vWorldDesiredBodyDirection2; - - - Vec2 m_vWorldDesiredMoveDirection; - Vec2 m_vWorldDesiredMoveDirectionSmooth; - Vec2 m_vWorldDesiredMoveDirectionSmoothRate; - Vec2 m_vLocalDesiredMoveDirection; - Vec2 m_vLocalDesiredMoveDirectionSmooth; - Vec2 m_vLocalDesiredMoveDirectionSmoothRate; - Vec2 m_vWorldAimBodyDirection; - - f32 m_udGround; - f32 m_lrGround; - OBB m_GroundOBB; - Vec3 m_GroundOBBPos; - - // Index of camera objects. - mutable GUID m_cameraObjectId; - mutable AZ::EntityId m_viewEntityId; - mutable ViewSourceType m_viewSourceType = ViewSourceType::None; - AZ::EntityId m_viewEntityIdCachedForEditMode; - Matrix34 m_preGameModeViewTM; - uint m_disableRenderingCount = 0; - bool m_bLockCameraMovement; - bool m_bUpdateViewport = false; - bool m_bMoveCameraObject = true; - - enum class KeyPressedState - { - AllUp, - PressedThisFrame, - PressedInPreviousFrame, - }; - KeyPressedState m_pressedKeyState = KeyPressedState::AllUp; - - Matrix34 m_defaultViewTM; - const QString m_defaultViewName; - - DisplayContext m_displayContext; - - - bool m_isOnPaint = false; - static EditorViewportWidget* m_pPrimaryViewport; - - QRect m_safeFrame; - QRect m_safeAction; - QRect m_safeTitle; - - CPredefinedAspectRatios m_predefinedAspectRatios; - - bool m_bCursorHidden = false; - void OnMenuResolutionCustom(); void OnMenuCreateCameraEntityFromCurrentView(); void OnMenuSelectCurrentCamera(); - int OnCreate(); - void resizeEvent(QResizeEvent* event) override; - void paintEvent(QPaintEvent* event) override; - void mousePressEvent(QMouseEvent* event) override; - // From a series of input primitives, compose a complete mouse interaction. AzToolsFramework::ViewportInteraction::MouseInteraction BuildMouseInteractionInternal( AzToolsFramework::ViewportInteraction::MouseButtons buttons, AzToolsFramework::ViewportInteraction::KeyboardModifiers modifiers, const AzToolsFramework::ViewportInteraction::MousePick& mousePick) const; + // Given a point in the viewport, return the pick ray into the scene. // note: The argument passed to parameter **point**, originating // from a Qt event, must first be passed to WidgetToViewport before being // passed to BuildMousePick. AzToolsFramework::ViewportInteraction::MousePick BuildMousePick(const QPoint& point); - bool event(QEvent* event) override; - void OnDestroy(); - bool CheckRespondToInput() const; - // AzFramework::InputSystemCursorConstraintRequestBus - void* GetSystemCursorConstraintWindow() const override; - void BuildDragDropContext(AzQtComponents::ViewportDragContext& context, const QPoint& pt) override; -private: void SetAsActiveViewport(); void PushDisableRendering(); void PopDisableRendering(); @@ -547,48 +263,131 @@ private: AzToolsFramework::ViewportInteraction::MousePick BuildMousePickInternal(const QPoint& point) const; void RestoreViewportAfterGameMode(); - void UpdateCameraFromViewportContext(); - double WidgetToViewportFactor() const - { -#if defined(AZ_PLATFORM_WINDOWS) - // Needed for high DPI mode on windows - return devicePixelRatioF(); -#else - return 1.0f; -#endif - } - - void BeginUndoTransaction() override; - void EndUndoTransaction() override; - - void UpdateCurrentMousePos(const QPoint& newPosition); void UpdateScene(); + void SetDefaultCamera(); + void SetSelectedCamera(); + bool IsSelectedCamera() const; + void SetComponentCamera(const AZ::EntityId& entityId); + void SetEntityAsCamera(const AZ::EntityId& entityId, bool lockCameraMovement = false); + void SetFirstComponentCamera(); + void PostCameraSet(); + // This switches the active camera to the next one in the list of (default, all custom cams). + void CycleCamera(); + + AzFramework::CameraState GetCameraState(); + AzFramework::ScreenPoint ViewportWorldToScreen(const AZ::Vector3& worldPosition); + + QPoint WidgetToViewport(const QPoint& point) const; + QPoint ViewportToWidget(const QPoint& point) const; + QSize WidgetToViewport(const QSize& size) const; + + const DisplayContext& GetDisplayContext() const { return m_displayContext; } + CBaseObject* GetCameraObject() const; + + void UnProjectFromScreen(float sx, float sy, float sz, float* px, float* py, float* pz) const; + void ProjectToScreen(float ptx, float pty, float ptz, float* sx, float* sy, float* sz) const; + + AZ::RPI::ViewPtr GetCurrentAtomView() const; + + //////////////////////////////////////////////////////////////////////// + // Members ... + friend class AZ::ViewportHelpers::EditorEntityNotifications; + + AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING + + // Singleton for the primary viewport + static EditorViewportWidget* m_pPrimaryViewport; + + // The simulation (play-game in editor) state + PlayInEditorState m_playInEditorState = PlayInEditorState::Editor; + + // Whether we are doing a full screen game preview (play-game in editor) or a regular one + bool m_inFullscreenPreview = false; + + // The entity ID of the current camera for this viewport, or invalid if the default editor camera + AZ::EntityId m_viewEntityId; + + // Determines also if the current camera for this viewport is default editor camera + ViewSourceType m_viewSourceType = ViewSourceType::None; + + // During play game in editor, holds the editor entity ID of the last + AZ::EntityId m_viewEntityIdCachedForEditMode; + + // The editor camera TM before switching to game mode + Matrix34 m_preGameModeViewTM; + + // Disables rendering during some periods of time, e.g. undo/redo, resize events + uint m_disableRenderingCount = 0; + + // Determines if the viewport needs updating (false when out of focus for example) + bool m_bUpdateViewport = false; + + // Avoid re-entering PostCameraSet->OnActiveViewChanged->PostCameraSet + bool m_sendingOnActiveChanged = false; + + // Legacy... + KeyPressedState m_pressedKeyState = KeyPressedState::AllUp; + + // The last camera matrix of the default editor camera, used when switching back to editor camera to restore the right TM + Matrix34 m_defaultViewTM; + + // The name to use for the default editor camera + const QString m_defaultViewName; + + // Note that any attempts to draw anything with this object will crash. Exists here for legacy "reasons" + DisplayContext m_displayContext; + + // Re-entrency guard for on paint events + bool m_isOnPaint = false; + + // Shapes of various safe frame helpers which can be displayed in the editor + QRect m_safeFrame; + QRect m_safeAction; + QRect m_safeTitle; + + // Aspect ratios available in the title bar + CPredefinedAspectRatios m_predefinedAspectRatios; + + // Is the cursor hidden or displayed? + bool m_bCursorHidden = false; + + // Shim for QtViewport, which used to be responsible for visibility queries in the editor, + // these are now forwarded to EntityVisibilityQuery AzFramework::EntityVisibilityQuery m_entityVisibilityQuery; + // Handlers for grid snapping/editor event callbacks SandboxEditor::GridSnappingChangedEvent::Handler m_gridSnappingHandler; AZStd::unique_ptr m_editorViewportSettingsCallbacks; + // Used for some legacy logic which lets the widget release a grabbed keyboard at the right times + // Unclear if it's still necessary. QSet m_keyDown; + // State for ViewportFreezeRequestBus, currently does nothing bool m_freezeViewportInput = false; + // This widget holds a reference to the manipulator manage because its responsible for drawing manipulators AZStd::shared_ptr m_manipulatorManager; - // Used to prevent circular set camera events - bool m_ignoreSetViewFromEntityPerspective = false; - bool m_windowResizedEvent = false; - + // Helper for getting EditorEntityNotificationBus events AZStd::unique_ptr m_editorEntityNotifications; + + // The widget to which Atom will actually render AtomToolsFramework::RenderViewportWidget* m_renderViewport = nullptr; - bool m_updateCameraPositionNextTick = false; - AZ::RPI::ViewportContext::MatrixChangedEvent::Handler m_cameraViewMatrixChangeHandler; - AZ::RPI::ViewportContext::MatrixChangedEvent::Handler m_cameraProjectionMatrixChangeHandler; + // Atom debug display AzFramework::DebugDisplayRequests* m_debugDisplay = nullptr; + // The default view created for the viewport context, which is used as the "Editor Camera" + AZ::RPI::ViewPtr m_defaultView; + + // The name to set on the viewport context when this viewport widget is set as the active one AZ::Name m_defaultViewportContextName; + // DO NOT USE THIS! It exists only to satisfy the signature of the base class method GetViewTm + mutable Matrix34 m_viewTmStorage; + AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING }; diff --git a/Code/Editor/Export/ExportManager.cpp b/Code/Editor/Export/ExportManager.cpp index 682dcf3980..f1ef96c8f8 100644 --- a/Code/Editor/Export/ExportManager.cpp +++ b/Code/Editor/Export/ExportManager.cpp @@ -662,11 +662,11 @@ bool CExportManager::ProcessObjectsForExport() GetIEditor()->GetAnimation()->SetRecording(false); GetIEditor()->GetAnimation()->SetPlaying(false); - CViewport* vp = GetIEditor()->GetViewManager()->GetSelectedViewport(); - if (CRenderViewport* rvp = viewport_cast(vp)) - { - rvp->SetSequenceCamera(); - } + //CViewport* vp = GetIEditor()->GetViewManager()->GetSelectedViewport(); + //if (CRenderViewport* rvp = viewport_cast(vp)) + //{ + // rvp->SetSequenceCamera(); + //} int startFrame = 0; timeValue = startFrame * fpsTimeInterval; diff --git a/Code/Editor/GameEngine.cpp b/Code/Editor/GameEngine.cpp index dff6476ff9..bb0b1d4547 100644 --- a/Code/Editor/GameEngine.cpp +++ b/Code/Editor/GameEngine.cpp @@ -572,8 +572,6 @@ void CGameEngine::SwitchToInGame() m_pISystem->GetIMovieSystem()->EnablePhysicsEvents(true); m_bInGameMode = true; - gEnv->pSystem->GetViewCamera().SetMatrix(m_playerViewTM); - // Disable accelerators. GetIEditor()->EnableAcceleratos(false); //! Send event to switch into game. @@ -627,13 +625,6 @@ void CGameEngine::SwitchToInEditor() m_bInGameMode = false; - // save the current gameView matrix for editor - if (pGameViewport) - { - Matrix34 gameView = gEnv->pSystem->GetViewCamera().GetMatrix(); - pGameViewport->SetGameTM(gameView); - } - // Out of game in Editor mode. if (pGameViewport) { diff --git a/Code/Editor/Objects/ObjectManager.cpp b/Code/Editor/Objects/ObjectManager.cpp index 58cd016e22..928a864cfb 100644 --- a/Code/Editor/Objects/ObjectManager.cpp +++ b/Code/Editor/Objects/ObjectManager.cpp @@ -32,7 +32,11 @@ #include AZ_CVAR_EXTERNED(bool, ed_visibility_logTiming); -AZ_CVAR_EXTERNED(bool, ed_visibility_use); + +AZ_CVAR( + bool, ed_visibility_use, true, nullptr, AZ::ConsoleFunctorFlags::Null, + "Enable/disable using the new IVisibilitySystem for Entity visibility determination"); + /*! * Class Description used for object templates. @@ -1327,7 +1331,7 @@ void CObjectManager::FindDisplayableObjects(DisplayContext& dc, [[maybe_unused]] pDispayedViewObjects->SetSerialNumber(m_visibilitySerialNumber); // update viewport to be latest serial number - const CCamera& camera = GetIEditor()->GetSystem()->GetViewCamera(); + //const CCamera& camera = GetIEditor()->GetSystem()->GetViewCamera(); AABB bbox; bbox.min.zero(); bbox.max.zero(); @@ -1376,11 +1380,11 @@ void CObjectManager::FindDisplayableObjects(DisplayContext& dc, [[maybe_unused]] { CBaseObject* obj = m_visibleObjects[i]; - if (obj && obj->IsInCameraView(camera)) + if (obj /* && obj->IsInCameraView(camera)*/) { // Check if object is too far. - float visRatio = obj->GetCameraVisRatio(camera); - if (visRatio > m_maxObjectViewDistRatio || (dc.flags & DISPLAY_SELECTION_HELPERS) || obj->IsSelected()) + // float visRatio = obj->GetCameraVisRatio(camera); + if (/*visRatio > m_maxObjectViewDistRatio || */ (dc.flags & DISPLAY_SELECTION_HELPERS) || obj->IsSelected()) { pDispayedViewObjects->AddObject(obj); } diff --git a/Code/Editor/RenderViewport.cpp b/Code/Editor/RenderViewport.cpp index d268a57684..e69de29bb2 100644 --- a/Code/Editor/RenderViewport.cpp +++ b/Code/Editor/RenderViewport.cpp @@ -1,4142 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - -// Description : implementation filefov - - -#include "EditorDefs.h" - -#include "RenderViewport.h" - -// Qt -#include -#include -#include -#include -#include - -// AzCore -#include -#include -#include -#include -#include -#include -#include - -// AzFramework -#include -#include -#include -#if defined(AZ_PLATFORM_WINDOWS) -# include -#endif // defined(AZ_PLATFORM_WINDOWS) -#include // for AzFramework::InputDeviceMouse - -// AzQtComponents -#include - -// AzToolsFramework -#include -#include -#include -#include -#include -#include - - -// CryCommon -#include - -// AzFramework -#include - -// Editor -#include "Util/fastlib.h" -#include "CryEditDoc.h" -#include "GameEngine.h" -#include "ViewManager.h" -#include "Objects/DisplayContext.h" -#include "DisplaySettings.h" -#include "Include/IObjectManager.h" -#include "Include/IDisplayViewport.h" -#include "Objects/ObjectManager.h" -#include "ProcessInfo.h" -#include "IPostEffectGroup.h" -#include "EditorPreferencesPageGeneral.h" - -#include "ViewPane.h" -#include "CustomResolutionDlg.h" -#include "AnimationContext.h" -#include "Objects/SelectionGroup.h" -#include "Core/QtEditorApplication.h" - -// ComponentEntityEditorPlugin -#include - -// LmbrCentral -#include - -#include - -#include -#include -#include - -AZ_CVAR( - bool, ed_visibility_use, true, nullptr, AZ::ConsoleFunctorFlags::Null, - "Enable/disable using the new IVisibilitySystem for Entity visibility determination"); - -CRenderViewport* CRenderViewport::m_pPrimaryViewport = nullptr; - -#if AZ_TRAIT_OS_PLATFORM_APPLE -void StopFixedCursorMode(); -void StartFixedCursorMode(QObject *viewport); -#endif - -#define MAX_ORBIT_DISTANCE (2000.0f) -#define RENDER_MESH_TEST_DISTANCE (0.2f) -#define CURSOR_FONT_HEIGHT 8.0f -#define FORWARD_DIRECTION Vec3(0, 1, 0) - -static const char TextCantCreateCameraNoLevel[] = "Cannot create camera when no level is loaded."; - -class EditorEntityNotifications - : public AzToolsFramework::EditorEntityContextNotificationBus::Handler - , public AzToolsFramework::EditorContextMenuBus::Handler -{ -public: - EditorEntityNotifications(CRenderViewport& renderViewport) - : m_renderViewport(renderViewport) - { - AzToolsFramework::EditorEntityContextNotificationBus::Handler::BusConnect(); - AzToolsFramework::EditorContextMenuBus::Handler::BusConnect(); - } - - ~EditorEntityNotifications() override - { - AzToolsFramework::EditorEntityContextNotificationBus::Handler::BusDisconnect(); - AzToolsFramework::EditorContextMenuBus::Handler::BusDisconnect(); - } - - // AzToolsFramework::EditorEntityContextNotificationBus - void OnStartPlayInEditor() override - { - m_renderViewport.OnStartPlayInEditor(); - } - void OnStopPlayInEditor() override - { - m_renderViewport.OnStopPlayInEditor(); - } - - // AzToolsFramework::EditorContextMenu::Bus - void PopulateEditorGlobalContextMenu(QMenu* menu, const AZ::Vector2& point, int flags) override - { - m_renderViewport.PopulateEditorGlobalContextMenu(menu, point, flags); - } -private: - CRenderViewport& m_renderViewport; -}; - -struct CRenderViewport::SScopedCurrentContext -{ - const CRenderViewport* m_viewport; - CRenderViewport::SPreviousContext m_previousContext; - - explicit SScopedCurrentContext(const CRenderViewport* viewport) - : m_viewport(viewport) - { - m_previousContext = viewport->SetCurrentContext(); - - // During normal updates of RenderViewport the value of m_cameraSetForWidgetRenderingCount is expected to be 0. - // This is to guarantee no loss in performance by tracking unnecessary calls to SetCurrentContext/RestorePreviousContext. - // If some code makes additional calls to Pre/PostWidgetRendering then the assert will be triggered because - // m_cameraSetForWidgetRenderingCount will be greater than 0. - // There is a legitimate case where the counter can be greater than 0. This is when QtViewport is processing mouse callbacks. - // QtViewport::MouseCallback() is surrounded by Pre/PostWidgetRendering and the m_processingMouseCallbacksCounter - // tracks this specific case. If an update of a RenderViewport happens while processing the mouse callback, - // for example when showing a QMessageBox, then both counters must match. - AZ_Assert(viewport->m_cameraSetForWidgetRenderingCount == viewport->m_processingMouseCallbacksCounter, - "SScopedCurrentContext constructor was called while viewport widget context is active " - "- this is unnecessary"); - } - - ~SScopedCurrentContext() - { - m_viewport->RestorePreviousContext(m_previousContext); - } -}; - -////////////////////////////////////////////////////////////////////////// -// CRenderViewport -////////////////////////////////////////////////////////////////////////// - -CRenderViewport::CRenderViewport(const QString& name, QWidget* parent) - : QtViewport(parent) - , m_Camera(GetIEditor()->GetSystem()->GetViewCamera()) - , m_camFOV(gSettings.viewports.fDefaultFov) - , m_defaultViewName(name) -{ - // need this to be set in order to allow for language switching on Windows - setAttribute(Qt::WA_InputMethodEnabled); - LockCameraMovement(true); - - CRenderViewport::SetViewTM(m_Camera.GetMatrix()); - m_defaultViewTM.SetIdentity(); - - if (GetIEditor()->GetViewManager()->GetSelectedViewport() == nullptr) - { - GetIEditor()->GetViewManager()->SelectViewport(this); - } - - GetIEditor()->RegisterNotifyListener(this); - - m_displayContext.pIconManager = GetIEditor()->GetIconManager(); - GetIEditor()->GetUndoManager()->AddListener(this); - - m_PhysicalLocation.SetIdentity(); - - // The renderer requires something, so don't allow us to shrink to absolutely nothing - // This won't in fact stop the viewport from being shrunk, when it's the centralWidget for - // the MainWindow, but it will stop the viewport from getting resize events - // once it's smaller than that, which from the renderer's perspective works out - // to be the same thing. - setMinimumSize(50, 50); - - OnCreate(); - - setFocusPolicy(Qt::StrongFocus); - - Camera::EditorCameraRequestBus::Handler::BusConnect(); - m_editorEntityNotifications = AZStd::make_unique(*this); - - m_manipulatorManager = GetIEditor()->GetViewManager()->GetManipulatorManager(); - if (!m_pPrimaryViewport) - { - m_pPrimaryViewport = this; - } - - m_hwnd = renderOverlayHWND(); -} - -////////////////////////////////////////////////////////////////////////// -CRenderViewport::~CRenderViewport() -{ - AzFramework::WindowNotificationBus::Event(m_hwnd, &AzFramework::WindowNotificationBus::Handler::OnWindowClosed); - - if (m_pPrimaryViewport == this) - { - m_pPrimaryViewport = nullptr; - } - - AzFramework::WindowRequestBus::Handler::BusDisconnect(); - DisconnectViewportInteractionRequestBus(); - m_editorEntityNotifications.reset(); - Camera::EditorCameraRequestBus::Handler::BusDisconnect(); - OnDestroy(); - GetIEditor()->GetUndoManager()->RemoveListener(this); - GetIEditor()->UnregisterNotifyListener(this); -} - -////////////////////////////////////////////////////////////////////////// -// CRenderViewport message handlers -////////////////////////////////////////////////////////////////////////// -int CRenderViewport::OnCreate() -{ - CreateRenderContext(); - - return 0; -} - -////////////////////////////////////////////////////////////////////////// -void CRenderViewport::resizeEvent(QResizeEvent* event) -{ - PushDisableRendering(); - QtViewport::resizeEvent(event); - PopDisableRendering(); - - const QRect rcWindow = rect().translated(mapToGlobal(QPoint())); - - gEnv->pSystem->GetISystemEventDispatcher()->OnSystemEvent(ESYSTEM_EVENT_MOVE, rcWindow.left(), rcWindow.top()); - - m_rcClient = rect(); - m_rcClient.setBottomRight(WidgetToViewport(m_rcClient.bottomRight())); - - gEnv->pSystem->GetISystemEventDispatcher()->OnSystemEvent(ESYSTEM_EVENT_RESIZE, width(), height()); - - // We queue the window resize event because the render overlay may be hidden. - // If the render overlay is not visible, the native window that is backing it will - // also be hidden, and it will not resize until it becomes visible. - m_windowResizedEvent = true; -} - -////////////////////////////////////////////////////////////////////////// -void CRenderViewport::paintEvent([[maybe_unused]] QPaintEvent* event) -{ - // Do not call CViewport::OnPaint() for painting messages - // FIXME: paintEvent() isn't the best place for such logic. Should listen to proper eNotify events and to the stuff there instead. (Repeats for other view port classes too). - CGameEngine* ge = GetIEditor()->GetGameEngine(); - if ((ge && ge->IsLevelLoaded()) || (GetType() != ET_ViewportCamera)) - { - setRenderOverlayVisible(true); - m_isOnPaint = true; - Update(); - m_isOnPaint = false; - } - else - { - setRenderOverlayVisible(false); - QPainter painter(this); // device context for painting - - // draw gradient background - const QRect rc = rect(); - QLinearGradient gradient(rc.topLeft(), rc.bottomLeft()); - gradient.setColorAt(0, QColor(80, 80, 80)); - gradient.setColorAt(1, QColor(200, 200, 200)); - painter.fillRect(rc, gradient); - - // if we have some level loaded/loading/new - // we draw a text - if (!GetIEditor()->GetLevelFolder().isEmpty()) - { - const int kFontSize = 200; - const char* kFontName = "Arial"; - const QColor kTextColor(255, 255, 255); - const QColor kTextShadowColor(0, 0, 0); - const QFont font(kFontName, kFontSize / 10.0); - painter.setFont(font); - - QString friendlyName = QFileInfo(GetIEditor()->GetLevelName()).fileName(); - const QString strMsg = tr("Preparing level %1...").arg(friendlyName); - - // draw text shadow - painter.setPen(kTextShadowColor); - painter.drawText(rc, Qt::AlignCenter, strMsg); - painter.setPen(kTextColor); - // offset rect for normal text - painter.drawText(rc.translated(-1, -1), Qt::AlignCenter, strMsg); - } - } -} - -////////////////////////////////////////////////////////////////////////// -void CRenderViewport::mousePressEvent(QMouseEvent* event) -{ - // There's a bug caused by having a mix of MFC and Qt where if the render viewport - // had focus and then an MFC widget gets focus, Qt internally still thinks - // that the widget that had focus before (the render viewport) has it now. - // Because of this, Qt won't set the window that the viewport is in as the - // focused widget, and the render viewport won't get keyboard input. - // Forcing the window to activate should allow the window to take focus - // and then the call to setFocus() will give it focus. - // All so that the ::keyPressEvent() gets called. - ActivateWindowAndSetFocus(); - - GetIEditor()->GetViewManager()->SelectViewport(this); - - QtViewport::mousePressEvent(event); -} - -AzToolsFramework::ViewportInteraction::MousePick CRenderViewport::BuildMousePickInternal(const QPoint& point) const -{ - using namespace AzToolsFramework::ViewportInteraction; - - MousePick mousePick; - Vec3 from, dir; - ViewToWorldRay(point, from, dir); - mousePick.m_rayOrigin = LYVec3ToAZVec3(from); - mousePick.m_rayDirection = LYVec3ToAZVec3(dir); - mousePick.m_screenCoordinates = AzFramework::ScreenPoint(point.x(), point.y()); - return mousePick; -} - -AzToolsFramework::ViewportInteraction::MousePick CRenderViewport::BuildMousePick(const QPoint& point) -{ - using namespace AzToolsFramework::ViewportInteraction; - - PreWidgetRendering(); - const MousePick mousePick = BuildMousePickInternal(point); - PostWidgetRendering(); - return mousePick; -} - -AzToolsFramework::ViewportInteraction::MouseInteraction CRenderViewport::BuildMouseInteractionInternal( - const AzToolsFramework::ViewportInteraction::MouseButtons buttons, - const AzToolsFramework::ViewportInteraction::KeyboardModifiers modifiers, - const AzToolsFramework::ViewportInteraction::MousePick& mousePick) const -{ - using namespace AzToolsFramework::ViewportInteraction; - - MouseInteraction mouse; - mouse.m_interactionId.m_cameraId = m_viewEntityId; - mouse.m_interactionId.m_viewportId = GetViewportId(); - mouse.m_mouseButtons = buttons; - mouse.m_mousePick = mousePick; - mouse.m_keyboardModifiers = modifiers; - return mouse; -} - -AzToolsFramework::ViewportInteraction::MouseInteraction CRenderViewport::BuildMouseInteraction( - const Qt::MouseButtons buttons, const Qt::KeyboardModifiers modifiers, const QPoint& point) -{ - using namespace AzToolsFramework::ViewportInteraction; - - return BuildMouseInteractionInternal( - BuildMouseButtons(buttons), - BuildKeyboardModifiers(modifiers), - BuildMousePick(WidgetToViewport(point))); -} - -namespace RenderViewportUtil -{ - static bool JustAltHeld(const Qt::KeyboardModifiers modifiers) - { - return (modifiers & Qt::ShiftModifier) == 0 - && (modifiers & Qt::ControlModifier) == 0 - && (modifiers & Qt::AltModifier) != 0; - } - - static bool NoModifiersHeld(const Qt::KeyboardModifiers modifiers) - { - return (modifiers & Qt::ShiftModifier) == 0 - && (modifiers & Qt::ControlModifier) == 0 - && (modifiers & Qt::AltModifier) == 0; - } - - static bool AllowDolly(const Qt::KeyboardModifiers modifiers) - { - return JustAltHeld(modifiers); - } - - static bool AllowOrbit(const Qt::KeyboardModifiers modifiers) - { - return JustAltHeld(modifiers); - } - - static bool AllowPan(const Qt::KeyboardModifiers modifiers) - { - // begin pan with alt (inverted movement) or no modifiers - return JustAltHeld(modifiers) || NoModifiersHeld(modifiers); - } - - static bool InvertPan(const Qt::KeyboardModifiers modifiers) - { - return JustAltHeld(modifiers); - } -} // namespace RenderViewportUtil - - -////////////////////////////////////////////////////////////////////////// -void CRenderViewport::OnLButtonDown(Qt::KeyboardModifiers modifiers, const QPoint& point) -{ - using namespace AzToolsFramework::ViewportInteraction; - using AzToolsFramework::EditorInteractionSystemViewportSelectionRequestBus; - - if (GetIEditor()->IsInGameMode() || m_freezeViewportInput) - { - return; - } - - if (!m_renderer) - { - return; - } - - // Force the visible object cache to be updated - this is to ensure that - // selection will work properly even if helpers are not being displayed, - // in which case the cache is not updated every frame. - if (m_displayContext.settings && !m_displayContext.settings->IsDisplayHelpers()) - { - GetIEditor()->GetObjectManager()->ForceUpdateVisibleObjectCache(m_displayContext); - } - - const auto scaledPoint = WidgetToViewport(point); - const auto mouseInteraction = BuildMouseInteractionInternal( - MouseButtonsFromButton(MouseButton::Left), - BuildKeyboardModifiers(modifiers), - BuildMousePick(scaledPoint)); - - bool manipulatorInteraction = false; - EditorInteractionSystemViewportSelectionRequestBus::EventResult( - manipulatorInteraction, AzToolsFramework::GetEntityContextId(), - &EditorInteractionSystemViewportSelectionRequestBus::Events::InternalHandleMouseManipulatorInteraction, - MouseInteractionEvent(mouseInteraction, MouseEvent::Down)); - - if (!manipulatorInteraction) - { - if (RenderViewportUtil::AllowOrbit(modifiers)) - { - m_bInOrbitMode = true; - m_orbitTarget = - GetViewTM().GetTranslation() + GetViewTM().TransformVector(FORWARD_DIRECTION) * m_orbitDistance; - - // mouse buttons are treated as keys as well - if (m_pressedKeyState == KeyPressedState::AllUp) - { - m_pressedKeyState = KeyPressedState::PressedThisFrame; - } - - m_mousePos = scaledPoint; - m_prevMousePos = scaledPoint; - - HideCursor(); - CaptureMouse(); - - // no further handling of left mouse button down - return; - } - - EditorInteractionSystemViewportSelectionRequestBus::Event( - AzToolsFramework::GetEntityContextId(), - &EditorInteractionSystemViewportSelectionRequestBus::Events::InternalHandleMouseViewportInteraction, - MouseInteractionEvent(mouseInteraction, MouseEvent::Down)); - } -} - -////////////////////////////////////////////////////////////////////////// -void CRenderViewport::OnLButtonUp(Qt::KeyboardModifiers modifiers, const QPoint& point) -{ - using namespace AzToolsFramework::ViewportInteraction; - using AzToolsFramework::EditorInteractionSystemViewportSelectionRequestBus; - - if (GetIEditor()->IsInGameMode() || m_freezeViewportInput) - { - return; - } - - // Convert point to position on terrain. - if (!m_renderer) - { - return; - } - - // Update viewports after done with actions. - GetIEditor()->UpdateViews(eUpdateObjects); - - const auto scaledPoint = WidgetToViewport(point); - - const auto mouseInteraction = BuildMouseInteractionInternal( - MouseButtonsFromButton(MouseButton::Left), - BuildKeyboardModifiers(modifiers), - BuildMousePick(scaledPoint)); - - if (m_bInOrbitMode) - { - m_bInOrbitMode = false; - - ReleaseMouse(); - ShowCursor(); - } - - AzToolsFramework::EditorInteractionSystemViewportSelectionRequestBus::Event( - AzToolsFramework::GetEntityContextId(), - &EditorInteractionSystemViewportSelectionRequestBus::Events::InternalHandleAllMouseInteractions, - MouseInteractionEvent(mouseInteraction, MouseEvent::Up)); -} - -////////////////////////////////////////////////////////////////////////// -void CRenderViewport::OnLButtonDblClk(Qt::KeyboardModifiers modifiers, const QPoint& point) -{ - using namespace AzToolsFramework::ViewportInteraction; - using AzToolsFramework::EditorInteractionSystemViewportSelectionRequestBus; - - if (GetIEditor()->IsInGameMode() || m_freezeViewportInput) - { - return; - } - - const auto scaledPoint = WidgetToViewport(point); - const auto mouseInteraction = BuildMouseInteractionInternal( - MouseButtonsFromButton(MouseButton::Left), - BuildKeyboardModifiers(modifiers), - BuildMousePick(scaledPoint)); - - AzToolsFramework::EditorInteractionSystemViewportSelectionRequestBus::Event( - AzToolsFramework::GetEntityContextId(), - &EditorInteractionSystemViewportSelectionRequestBus::Events::InternalHandleAllMouseInteractions, - MouseInteractionEvent(mouseInteraction, MouseEvent::DoubleClick)); -} - -////////////////////////////////////////////////////////////////////////// -void CRenderViewport::OnRButtonDown(Qt::KeyboardModifiers modifiers, const QPoint& point) -{ - using namespace AzToolsFramework::ViewportInteraction; - using AzToolsFramework::EditorInteractionSystemViewportSelectionRequestBus; - - if (GetIEditor()->IsInGameMode() || m_freezeViewportInput) - { - return; - } - - SetFocus(); - - const auto scaledPoint = WidgetToViewport(point); - const auto mouseInteraction = BuildMouseInteractionInternal( - MouseButtonsFromButton(MouseButton::Right), - BuildKeyboardModifiers(modifiers), - BuildMousePick(scaledPoint)); - - AzToolsFramework::EditorInteractionSystemViewportSelectionRequestBus::Event( - AzToolsFramework::GetEntityContextId(), - &EditorInteractionSystemViewportSelectionRequestBus::Events::InternalHandleAllMouseInteractions, - MouseInteractionEvent(mouseInteraction, MouseEvent::Down)); - - if (RenderViewportUtil::AllowDolly(modifiers)) - { - m_bInZoomMode = true; - } - else - { - m_bInRotateMode = true; - } - - // mouse buttons are treated as keys as well - if (m_pressedKeyState == KeyPressedState::AllUp) - { - m_pressedKeyState = KeyPressedState::PressedThisFrame; - } - - m_mousePos = scaledPoint; - m_prevMousePos = m_mousePos; - - HideCursor(); - - // we can't capture the mouse here, or it will stop the popup menu - // when the mouse is released. -} - -////////////////////////////////////////////////////////////////////////// -void CRenderViewport::OnRButtonUp(Qt::KeyboardModifiers modifiers, const QPoint& point) -{ - using namespace AzToolsFramework::ViewportInteraction; - using AzToolsFramework::EditorInteractionSystemViewportSelectionRequestBus; - - if (GetIEditor()->IsInGameMode() || m_freezeViewportInput) - { - return; - } - - const auto scaledPoint = WidgetToViewport(point); - const auto mouseInteraction = BuildMouseInteractionInternal( - MouseButtonsFromButton(MouseButton::Right), - BuildKeyboardModifiers(modifiers), - BuildMousePick(scaledPoint)); - - AzToolsFramework::EditorInteractionSystemViewportSelectionRequestBus::Event( - AzToolsFramework::GetEntityContextId(), - &EditorInteractionSystemViewportSelectionRequestBus::Events::InternalHandleAllMouseInteractions, - MouseInteractionEvent(mouseInteraction, MouseEvent::Up)); - - m_bInRotateMode = false; - m_bInZoomMode = false; - - ReleaseMouse(); - - if (!m_bInMoveMode) - { - ShowCursor(); - } -} - -////////////////////////////////////////////////////////////////////////// -void CRenderViewport::OnMButtonDown(Qt::KeyboardModifiers modifiers, const QPoint& point) -{ - using namespace AzToolsFramework::ViewportInteraction; - using AzToolsFramework::EditorInteractionSystemViewportSelectionRequestBus; - - if (GetIEditor()->IsInGameMode() || m_freezeViewportInput) - { - return; - } - - const auto scaledPoint = WidgetToViewport(point); - const auto mouseInteraction = BuildMouseInteractionInternal( - MouseButtonsFromButton(MouseButton::Middle), - BuildKeyboardModifiers(modifiers), - BuildMousePick(scaledPoint)); - - if (RenderViewportUtil::AllowPan(modifiers)) - { - m_bInMoveMode = true; - - // mouse buttons are treated as keys as well - if (m_pressedKeyState == KeyPressedState::AllUp) - { - m_pressedKeyState = KeyPressedState::PressedThisFrame; - } - - m_mousePos = scaledPoint; - m_prevMousePos = scaledPoint; - - HideCursor(); - CaptureMouse(); - } - - AzToolsFramework::EditorInteractionSystemViewportSelectionRequestBus::Event( - AzToolsFramework::GetEntityContextId(), - &EditorInteractionSystemViewportSelectionRequestBus::Events::InternalHandleAllMouseInteractions, - MouseInteractionEvent(mouseInteraction, MouseEvent::Down)); -} - -////////////////////////////////////////////////////////////////////////// -void CRenderViewport::OnMButtonUp(Qt::KeyboardModifiers modifiers, const QPoint& point) -{ - using namespace AzToolsFramework::ViewportInteraction; - using AzToolsFramework::EditorInteractionSystemViewportSelectionRequestBus; - - if (GetIEditor()->IsInGameMode() || m_freezeViewportInput) - { - return; - } - - const auto scaledPoint = WidgetToViewport(point); - UpdateCurrentMousePos(scaledPoint); - - const auto tryRestoreMouse = [this] - { - // if we are currently looking (rotateMode) or dollying (zoomMode) - // do not show the cursor on mouse up as rmb is still held - if (!m_bInZoomMode && !m_bInRotateMode) - { - ReleaseMouse(); - ShowCursor(); - } - }; - - if (m_bInMoveMode) - { - m_bInMoveMode = false; - tryRestoreMouse(); - } - - const auto mouseInteraction = BuildMouseInteractionInternal( - MouseButtonsFromButton(MouseButton::Middle), - BuildKeyboardModifiers(modifiers), - BuildMousePick(scaledPoint)); - - AzToolsFramework::EditorInteractionSystemViewportSelectionRequestBus::Event( - AzToolsFramework::GetEntityContextId(), - &EditorInteractionSystemViewportSelectionRequestBus::Events::InternalHandleAllMouseInteractions, - MouseInteractionEvent(mouseInteraction, MouseEvent::Up)); -} - -void CRenderViewport::OnMouseMove(Qt::KeyboardModifiers modifiers, Qt::MouseButtons buttons, const QPoint& point) -{ - using namespace AzToolsFramework::ViewportInteraction; - using AzToolsFramework::EditorInteractionSystemViewportSelectionRequestBus; - - if (GetIEditor()->IsInGameMode() || m_freezeViewportInput) - { - return; - } - - const auto scaledPoint = WidgetToViewport(point); - - const auto mouseInteraction = BuildMouseInteractionInternal( - BuildMouseButtons(buttons), - BuildKeyboardModifiers(modifiers), - BuildMousePick(scaledPoint)); - - AzToolsFramework::EditorInteractionSystemViewportSelectionRequestBus::Event( - AzToolsFramework::GetEntityContextId(), - &EditorInteractionSystemViewportSelectionRequestBus::Events::InternalHandleAllMouseInteractions, - MouseInteractionEvent(mouseInteraction, MouseEvent::Move)); -} - -void CRenderViewport::InjectFakeMouseMove(int deltaX, int deltaY, Qt::MouseButtons buttons) -{ - // this is required, otherwise the user will see the context menu - OnMouseMove(Qt::NoModifier, buttons, QCursor::pos() + QPoint(deltaX, deltaY)); - // we simply move the prev mouse position, so the change will be picked up - // by the next ProcessMouse call - m_prevMousePos -= QPoint(deltaX, deltaY); -} - -////////////////////////////////////////////////////////////////////////// -void CRenderViewport::ProcessMouse() -{ - if (GetIEditor()->IsInGameMode() || m_freezeViewportInput) - { - return; - } - - const auto point = WidgetToViewport(mapFromGlobal(QCursor::pos())); - - if (point == m_prevMousePos) - { - return; - } - - // specifically for the right mouse button click, which triggers rotate or zoom, - // we can't capture the mouse until the user has moved the mouse, otherwise the - // right click context menu won't popup - if (!m_mouseCaptured && (m_bInZoomMode || m_bInRotateMode)) - { - if ((point - m_mousePos).manhattanLength() > QApplication::startDragDistance()) - { - CaptureMouse(); - } - } - - float speedScale = GetCameraMoveSpeed(); - - if (CheckVirtualKey(Qt::Key_Control)) - { - speedScale *= gSettings.cameraFastMoveSpeed; - } - - if (m_PlayerControl) - { - if (m_bInRotateMode) - { - f32 MousedeltaX = (m_mousePos.x() - point.x()); - f32 MousedeltaY = (m_mousePos.y() - point.y()); - m_relCameraRotZ += MousedeltaX; - - if (GetCameraInvertYRotation()) - { - MousedeltaY = -MousedeltaY; - } - m_relCameraRotZ += MousedeltaX; - m_relCameraRotX += MousedeltaY; - - ResetCursor(); - } - } - else if ((m_bInRotateMode && m_bInMoveMode) || m_bInZoomMode) - { - // Zoom. - Matrix34 m = GetViewTM(); - - Vec3 ydir = m.GetColumn1().GetNormalized(); - Vec3 pos = m.GetTranslation(); - - const float posDelta = 0.2f * (m_prevMousePos.y() - point.y()) * speedScale; - pos = pos - ydir * posDelta; - m_orbitDistance = m_orbitDistance + posDelta; - m_orbitDistance = fabs(m_orbitDistance); - - m.SetTranslation(pos); - SetViewTM(m); - - ResetCursor(); - } - else if (m_bInRotateMode) - { - Ang3 angles(-point.y() + m_prevMousePos.y(), 0, -point.x() + m_prevMousePos.x()); - angles = angles * 0.002f * GetCameraRotateSpeed(); - if (GetCameraInvertYRotation()) - { - angles.x = -angles.x; - } - Matrix34 camtm = GetViewTM(); - Ang3 ypr = CCamera::CreateAnglesYPR(Matrix33(camtm)); - ypr.x += angles.z; - ypr.y += angles.x; - - ypr.y = CLAMP(ypr.y, -1.5f, 1.5f); // to keep rotation in reasonable range - // In the recording mode of a custom camera, the z rotation is allowed. - if (GetCameraObject() == nullptr || (!GetIEditor()->GetAnimation()->IsRecordMode() && !IsCameraObjectMove())) - { - ypr.z = 0; // to have camera always upward - } - - camtm = Matrix34(CCamera::CreateOrientationYPR(ypr), camtm.GetTranslation()); - SetViewTM(camtm); - - ResetCursor(); - } - else if (m_bInMoveMode) - { - // Slide. - Matrix34 m = GetViewTM(); - Vec3 xdir = m.GetColumn0().GetNormalized(); - Vec3 zdir = m.GetColumn2().GetNormalized(); - - const auto modifiers = QGuiApplication::queryKeyboardModifiers(); - if (RenderViewportUtil::InvertPan(modifiers)) - { - xdir = -xdir; - zdir = -zdir; - } - - Vec3 pos = m.GetTranslation(); - pos += 0.1f * xdir * (point.x() - m_prevMousePos.x()) * speedScale + 0.1f * zdir * (m_prevMousePos.y() - point.y()) * speedScale; - m.SetTranslation(pos); - SetViewTM(m, true); - - ResetCursor(); - } - else if (m_bInOrbitMode) - { - Ang3 angles(-point.y() + m_prevMousePos.y(), 0, -point.x() + m_prevMousePos.x()); - angles = angles * 0.002f * GetCameraRotateSpeed(); - - if (GetCameraInvertPan()) - { - angles.z = -angles.z; - } - - Ang3 ypr = CCamera::CreateAnglesYPR(Matrix33(GetViewTM())); - ypr.x += angles.z; - ypr.y = CLAMP(ypr.y, -1.5f, 1.5f); // to keep rotation in reasonable range - ypr.y += angles.x; - - Matrix33 rotateTM = CCamera::CreateOrientationYPR(ypr); - - Vec3 src = GetViewTM().GetTranslation(); - Vec3 trg = m_orbitTarget; - float fCameraRadius = (trg - src).GetLength(); - - // Calc new source. - src = trg - rotateTM * Vec3(0, 1, 0) * fCameraRadius; - Matrix34 camTM = rotateTM; - camTM.SetTranslation(src); - - SetViewTM(camTM); - - ResetCursor(); - } -} - -void CRenderViewport::ResetCursor() -{ -#ifdef AZ_PLATFORM_WINDOWS - if (!gSettings.stylusMode) - { - const QPoint point = mapToGlobal(ViewportToWidget(m_prevMousePos)); - AzQtComponents::SetCursorPos(point); - } -#endif - - // Recalculate the prev mouse pos even if we just reset to it to avoid compounding floating point math issues with DPI scaling - m_prevMousePos = WidgetToViewport(mapFromGlobal(QCursor::pos())); -} - -////////////////////////////////////////////////////////////////////////// -bool CRenderViewport::event(QEvent* event) -{ - switch (event->type()) - { - case QEvent::WindowActivate: - GetIEditor()->GetViewManager()->SelectViewport(this); - // also kill the keys; if we alt-tab back to the viewport, or come back from the debugger, it's done (and there's no guarantee we'll get the keyrelease event anyways) - m_keyDown.clear(); - break; - - case QEvent::Shortcut: - // a shortcut should immediately clear us, otherwise the release event never gets sent - m_keyDown.clear(); - break; - - case QEvent::ShortcutOverride: - { - // since we respond to the following things, let Qt know so that shortcuts don't override us - bool respondsToEvent = false; - - auto keyEvent = static_cast(event); - bool manipulatorInteracting = false; - AzToolsFramework::ManipulatorManagerRequestBus::EventResult( - manipulatorInteracting, - AzToolsFramework::g_mainManipulatorManagerId, - &AzToolsFramework::ManipulatorManagerRequestBus::Events::Interacting); - - // If a manipulator is active, stop all shortcuts from working, except for the escape key, which cancels in some cases - if ((keyEvent->key() != Qt::Key_Escape) && manipulatorInteracting) - { - respondsToEvent = true; - } - else - { - // In game mode we never want to be overridden by shortcuts - if (GetIEditor()->IsInGameMode() && GetType() == ET_ViewportCamera) - { - respondsToEvent = true; - } - else - { - if (!(keyEvent->modifiers() & Qt::ControlModifier)) - { - switch (keyEvent->key()) - { - case Qt::Key_Up: - case Qt::Key_W: - case Qt::Key_Down: - case Qt::Key_S: - case Qt::Key_Left: - case Qt::Key_A: - case Qt::Key_Right: - case Qt::Key_D: - respondsToEvent = true; - break; - - default: - break; - } - } - } - } - - if (respondsToEvent) - { - event->accept(); - return true; - } - - // because we're doing keyboard grabs, we need to detect - // when a shortcut matched so that we can track the buttons involved - // in the shortcut, since the key released event won't be generated in that case - ProcessKeyRelease(keyEvent); - } - break; - default: - // do nothing - break; - } - - return QtViewport::event(event); -} - -////////////////////////////////////////////////////////////////////////// -void CRenderViewport::ResetContent() -{ - QtViewport::ResetContent(); -} - -////////////////////////////////////////////////////////////////////////// -void CRenderViewport::UpdateContent(int flags) -{ - QtViewport::UpdateContent(flags); - if (flags & eUpdateObjects) - { - m_bUpdateViewport = true; - } -} - -////////////////////////////////////////////////////////////////////////// -void CRenderViewport::Update() -{ - FUNCTION_PROFILER(GetIEditor()->GetSystem(), PROFILE_EDITOR); - - if (Editor::EditorQtApplication::instance()->isMovingOrResizing()) - { - return; - } - - if (!m_renderer || m_rcClient.isEmpty() || GetIEditor()->IsInMatEditMode()) - { - return; - } - - if (!isVisible()) - { - return; - } - - // Only send the resize event if the render overlay is visible. This is to make sure - // the native window has resized. - if (m_windowResizedEvent && isRenderOverlayVisible()) - { - AzFramework::WindowNotificationBus::Event(renderOverlayHWND(), &AzFramework::WindowNotificationBus::Handler::OnWindowResized, m_rcClient.width(), m_rcClient.height()); - m_windowResizedEvent = false; - } - - // Don't wait for changes to update the focused viewport. - if (CheckRespondToInput()) - { - m_bUpdateViewport = true; - } - - // While Renderer doesn't support fast rendering of the scene to more then 1 viewport - // render only focused viewport if more then 1 are opened and always update is off. - if (!m_isOnPaint && m_viewManager->GetNumberOfGameViewports() > 1 && GetType() == ET_ViewportCamera) - { - if (m_pPrimaryViewport != this) - { - if (CheckRespondToInput()) // If this is the focused window, set primary viewport. - { - m_pPrimaryViewport = this; - } - else if (!m_bUpdateViewport) // Skip this viewport. - { - return; - } - } - } - - if (CheckRespondToInput()) - { - ProcessMouse(); - ProcessKeys(); - } - - const bool isGameMode = GetIEditor()->IsInGameMode(); - const bool isSimulationMode = GetIEditor()->GetGameEngine()->GetSimulationMode(); - - // Allow debug visualization in both 'game' (Ctrl-G) and 'simulation' (Ctrl-P) modes - if (isGameMode || isSimulationMode) - { - if (!IsRenderingDisabled()) - { - // Disable rendering to avoid recursion into Update() - PushDisableRendering(); - - // draw debug visualizations - { - const AzFramework::DisplayContextRequestGuard displayContextGuard(m_displayContext); - - const AZ::u32 prevState = m_displayContext.GetState(); - m_displayContext.SetState( - e_Mode3D | e_AlphaBlended | e_FillModeSolid | e_CullModeBack | e_DepthWriteOn | e_DepthTestOn); - - AzFramework::DebugDisplayRequestBus::BusPtr debugDisplayBus; - AzFramework::DebugDisplayRequestBus::Bind( - debugDisplayBus, AzFramework::g_defaultSceneEntityDebugDisplayId); - AZ_Assert(debugDisplayBus, "Invalid DebugDisplayRequestBus."); - - AzFramework::DebugDisplayRequests* debugDisplay = - AzFramework::DebugDisplayRequestBus::FindFirstHandler(debugDisplayBus); - - AzFramework::EntityDebugDisplayEventBus::Broadcast( - &AzFramework::EntityDebugDisplayEvents::DisplayEntityViewport, - AzFramework::ViewportInfo{ GetViewportId() }, *debugDisplay); - - m_displayContext.SetState(prevState); - } - - QtViewport::Update(); - PopDisableRendering(); - } - - // Game mode rendering is handled by CryAction - if (isGameMode) - { - return; - } - } - - // Prevents rendering recursion due to recursive Paint messages. - if (IsRenderingDisabled()) - { - return; - } - - PushDisableRendering(); - - m_viewTM = m_Camera.GetMatrix(); // synchronize. - - // Render - if (!m_bRenderContextCreated) - { - if (!CreateRenderContext()) - { - return; - } - } - - if (ed_visibility_use) - { - auto start = std::chrono::steady_clock::now(); - - m_entityVisibilityQuery.UpdateVisibility(GetCameraState()); - } - - { - SScopedCurrentContext context(this); - - m_renderer->SetClearColor(Vec3(0.4f, 0.4f, 0.4f)); - - InitDisplayContext(); - - OnRender(); - - ProcessRenderLisneters(m_displayContext); - - m_displayContext.Flush2D(); - - m_renderer->SwitchToNativeResolutionBackbuffer(); - - // 3D engine stats - - CCamera CurCamera = gEnv->pSystem->GetViewCamera(); - gEnv->pSystem->SetViewCamera(m_Camera); - - // Post Render Callback - { - PostRenderers::iterator itr = m_postRenderers.begin(); - PostRenderers::iterator end = m_postRenderers.end(); - for (; itr != end; ++itr) - { - (*itr)->OnPostRender(); - } - } - - gEnv->pSystem->SetViewCamera(CurCamera); - } - - QtViewport::Update(); - - PopDisableRendering(); - m_bUpdateViewport = false; -} - -////////////////////////////////////////////////////////////////////////// -void CRenderViewport::SetViewEntity(const AZ::EntityId& viewEntityId, bool lockCameraMovement) -{ - // if they've picked the same camera, then that means they want to toggle - if (viewEntityId.IsValid() && viewEntityId != m_viewEntityId) - { - LockCameraMovement(lockCameraMovement); - m_viewEntityId = viewEntityId; - AZStd::string entityName; - AZ::ComponentApplicationBus::BroadcastResult(entityName, &AZ::ComponentApplicationRequests::GetEntityName, viewEntityId); - SetName(QString("Camera entity: %1").arg(entityName.c_str())); - } - else - { - SetDefaultCamera(); - } - - PostCameraSet(); -} - -////////////////////////////////////////////////////////////////////////// -void CRenderViewport::ResetToViewSourceType(const ViewSourceType& viewSourceType) -{ - LockCameraMovement(true); - m_pCameraFOVVariable = nullptr; - m_viewEntityId.SetInvalid(); - m_cameraObjectId = GUID_NULL; - m_viewSourceType = viewSourceType; - SetViewTM(GetViewTM()); -} - -////////////////////////////////////////////////////////////////////////// -void CRenderViewport::PostCameraSet() -{ - if (m_viewPane) - { - m_viewPane->OnFOVChanged(GetFOV()); - } - - GetIEditor()->Notify(eNotify_CameraChanged); - QScopedValueRollback rb(m_ignoreSetViewFromEntityPerspective, true); - Camera::EditorCameraNotificationBus::Broadcast( - &Camera::EditorCameraNotificationBus::Events::OnViewportViewEntityChanged, m_viewEntityId); -} - -////////////////////////////////////////////////////////////////////////// -CBaseObject* CRenderViewport::GetCameraObject() const -{ - CBaseObject* pCameraObject = nullptr; - - if (m_viewSourceType == ViewSourceType::SequenceCamera) - { - m_cameraObjectId = GetViewManager()->GetCameraObjectId(); - } - if (m_cameraObjectId != GUID_NULL) - { - // Find camera object from id. - pCameraObject = GetIEditor()->GetObjectManager()->FindObject(m_cameraObjectId); - } - else if (m_viewSourceType == ViewSourceType::CameraComponent || m_viewSourceType == ViewSourceType::AZ_Entity) - { - AzToolsFramework::ComponentEntityEditorRequestBus::EventResult( - pCameraObject, m_viewEntityId, &AzToolsFramework::ComponentEntityEditorRequests::GetSandboxObject); - } - return pCameraObject; -} - -////////////////////////////////////////////////////////////////////////// -void CRenderViewport::OnEditorNotifyEvent(EEditorNotifyEvent event) -{ - switch (event) - { - case eNotify_OnBeginGameMode: - { - if (GetIEditor()->GetViewManager()->GetGameViewport() == this) - { - m_preGameModeViewTM = GetViewTM(); - // this should only occur for the main viewport and no others. - ShowCursor(); - - // If the user has selected game mode, enable outputting to any attached HMD and properly size the context - // to the resolution specified by the VR device. - if (gSettings.bEnableGameModeVR) - { - const AZ::VR::HMDDeviceInfo* deviceInfo = nullptr; - EBUS_EVENT_RESULT(deviceInfo, AZ::VR::HMDDeviceRequestBus, GetDeviceInfo); - AZ_Warning("Render Viewport", deviceInfo, "No VR device detected"); - - if (deviceInfo) - { - m_previousContext = SetCurrentContext(deviceInfo->renderWidth, deviceInfo->renderHeight); - if (m_renderer->GetIStereoRenderer()) - { - m_renderer->GetIStereoRenderer()->OnResolutionChanged(); - } - SetActiveWindow(); - SetFocus(); - SetSelected(true); - } - } - else - { - m_previousContext = SetCurrentContext(); - } - SetCurrentCursor(STD_CURSOR_GAME); - } - } - break; - - case eNotify_OnEndGameMode: - if (GetIEditor()->GetViewManager()->GetGameViewport() == this) - { - SetCurrentCursor(STD_CURSOR_DEFAULT); - if (m_renderer->GetCurrentContextHWND() != renderOverlayHWND()) - { - // if this warning triggers it means that someone else (ie, some other part of the code) - // called SetCurrentContext(...) on the renderer, probably did some rendering, but then either - // failed to set the context back when done, or set it back to the wrong one. - CryWarning(VALIDATOR_MODULE_3DENGINE, VALIDATOR_WARNING, "RenderViewport render context was not correctly restored by someone else."); - } - RestorePreviousContext(m_previousContext); - m_bInRotateMode = false; - m_bInMoveMode = false; - m_bInOrbitMode = false; - m_bInZoomMode = false; - - RestoreViewportAfterGameMode(); - } - break; - - case eNotify_OnCloseScene: - SetDefaultCamera(); - break; - - case eNotify_OnBeginNewScene: - PushDisableRendering(); - break; - - case eNotify_OnEndNewScene: - PopDisableRendering(); - - { - // Default this to the size of default terrain in case there is no listener on the buss - AZ::Aabb terrainAabb = AZ::Aabb::CreateFromMinMaxValues(0, 0, 32, 1024, 1024, 32); - AzFramework::Terrain::TerrainDataRequestBus::BroadcastResult(terrainAabb, &AzFramework::Terrain::TerrainDataRequests::GetTerrainAabb); - float sx = terrainAabb.GetXExtent(); - float sy = terrainAabb.GetYExtent(); - - Matrix34 viewTM; - viewTM.SetIdentity(); - // Initial camera will be at middle of the map at the height of 2 - // meters above the terrain (default terrain height is 32) - viewTM.SetTranslation(Vec3(sx * 0.5f, sy * 0.5f, 34.0f)); - SetViewTM(viewTM); - } - break; - - case eNotify_OnBeginTerrainCreate: - PushDisableRendering(); - break; - - case eNotify_OnEndTerrainCreate: - PopDisableRendering(); - - { - // Default this to the size of default terrain in case there is no listener on the buss - AZ::Aabb terrainAabb = AZ::Aabb::CreateFromMinMaxValues(0, 0, 32, 1024, 1024, 32); - AzFramework::Terrain::TerrainDataRequestBus::BroadcastResult(terrainAabb, &AzFramework::Terrain::TerrainDataRequests::GetTerrainAabb); - float sx = terrainAabb.GetXExtent(); - float sy = terrainAabb.GetYExtent(); - - Matrix34 viewTM; - viewTM.SetIdentity(); - // Initial camera will be at middle of the map at the height of 2 - // meters above the terrain (default terrain height is 32) - viewTM.SetTranslation(Vec3(sx * 0.5f, sy * 0.5f, 34.0f)); - SetViewTM(viewTM); - } - break; - - case eNotify_OnBeginLayerExport: - case eNotify_OnBeginSceneSave: - PushDisableRendering(); - break; - case eNotify_OnEndLayerExport: - case eNotify_OnEndSceneSave: - PopDisableRendering(); - break; - - case eNotify_OnBeginLoad: // disables viewport input when starting to load an existing level - case eNotify_OnBeginCreate: // disables viewport input when starting to create a new level - m_freezeViewportInput = true; - break; - - case eNotify_OnEndLoad: // enables viewport input when finished loading an existing level - case eNotify_OnEndCreate: // enables viewport input when finished creating a new level - m_freezeViewportInput = false; - break; - } -} - -////////////////////////////////////////////////////////////////////////// -namespace { - inline Vec3 NegY(const Vec3& v, float y) - { - return Vec3(v.x, y - v.y, v.z); - } -} - -////////////////////////////////////////////////////////////////////////// -void CRenderViewport::OnRender() -{ - if (m_rcClient.isEmpty() || m_renderer->GetRenderType() == eRT_Null) // Null is crashing in CryEngine on macOS - { - // Even in null rendering, update the view camera. - // This is necessary so that automated editor tests using the null renderer to test systems like dynamic vegetation - // are still able to manipulate the current logical camera position, even if nothing is rendered. - GetIEditor()->GetSystem()->SetViewCamera(m_Camera); - return; - } - - FUNCTION_PROFILER(GetIEditor()->GetSystem(), PROFILE_EDITOR); - - float fNearZ = GetIEditor()->GetConsoleVar("cl_DefaultNearPlane"); - float fFarZ = m_Camera.GetFarPlane(); - - CBaseObject* cameraObject = GetCameraObject(); - if (cameraObject) - { - AZ::Matrix3x3 lookThroughEntityCorrection = AZ::Matrix3x3::CreateIdentity(); - if (m_viewEntityId.IsValid()) - { - Camera::CameraRequestBus::EventResult(fNearZ, m_viewEntityId, &Camera::CameraComponentRequests::GetNearClipDistance); - Camera::CameraRequestBus::EventResult(fFarZ, m_viewEntityId, &Camera::CameraComponentRequests::GetFarClipDistance); - LmbrCentral::EditorCameraCorrectionRequestBus::EventResult( - lookThroughEntityCorrection, m_viewEntityId, - &LmbrCentral::EditorCameraCorrectionRequests::GetTransformCorrection); - } - - m_viewTM = cameraObject->GetWorldTM() * AZMatrix3x3ToLYMatrix3x3(lookThroughEntityCorrection); - m_viewTM.OrthonormalizeFast(); - - m_Camera.SetMatrix(m_viewTM); - - int w = m_rcClient.width(); - int h = m_rcClient.height(); - - m_Camera.SetFrustum(w, h, GetFOV(), fNearZ, fFarZ); - } - else if (m_viewEntityId.IsValid()) - { - Camera::CameraRequestBus::EventResult(fNearZ, m_viewEntityId, &Camera::CameraComponentRequests::GetNearClipDistance); - Camera::CameraRequestBus::EventResult(fFarZ, m_viewEntityId, &Camera::CameraComponentRequests::GetFarClipDistance); - int w = m_rcClient.width(); - int h = m_rcClient.height(); - - m_Camera.SetFrustum(w, h, GetFOV(), fNearZ, fFarZ); - } - else - { - // Normal camera. - m_cameraObjectId = GUID_NULL; - int w = m_rcClient.width(); - int h = m_rcClient.height(); - - float fov = gSettings.viewports.fDefaultFov; - - // match viewport fov to default / selected title menu fov - if (GetFOV() != fov) - { - if (m_viewPane) - { - m_viewPane->OnFOVChanged(fov); - SetFOV(fov); - } - } - - // Just for editor: Aspect ratio fix when changing the viewport - if (!GetIEditor()->IsInGameMode()) - { - float viewportAspectRatio = float( w ) / h; - float targetAspectRatio = GetAspectRatio(); - if (targetAspectRatio > viewportAspectRatio) - { - // Correct for vertical FOV change. - float maxTargetHeight = float( w ) / targetAspectRatio; - fov = 2 * atanf((h * tan(fov / 2)) / maxTargetHeight); - } - } - - m_Camera.SetFrustum(w, h, fov, fNearZ); - } - - GetIEditor()->GetSystem()->SetViewCamera(m_Camera); - - CGameEngine* ge = GetIEditor()->GetGameEngine(); - - bool levelIsDisplayable = (ge && ge->IsLevelLoaded() && GetIEditor()->GetDocument() && GetIEditor()->GetDocument()->IsDocumentReady()); - - //Handle scene render tasks such as gizmos and handles but only when not in VR - if (!m_renderer->IsStereoEnabled()) - { - DisplayContext& displayContext = m_displayContext; - - PreWidgetRendering(); - - RenderAll(); - - // Draw 2D helpers. - TransformationMatrices backupSceneMatrices; - m_renderer->Set2DMode(m_rcClient.right(), m_rcClient.bottom(), backupSceneMatrices); - displayContext.SetState(e_Mode3D | e_AlphaBlended | e_FillModeSolid | e_CullModeBack | e_DepthWriteOn | e_DepthTestOn); - - // Display cursor string. - RenderCursorString(); - - if (gSettings.viewports.bShowSafeFrame) - { - UpdateSafeFrame(); - RenderSafeFrame(); - } - - const AzFramework::DisplayContextRequestGuard displayContextGuard(displayContext); - - AzFramework::DebugDisplayRequestBus::BusPtr debugDisplayBus; - AzFramework::DebugDisplayRequestBus::Bind( - debugDisplayBus, AzFramework::g_defaultSceneEntityDebugDisplayId); - AZ_Assert(debugDisplayBus, "Invalid DebugDisplayRequestBus."); - - AzFramework::DebugDisplayRequests* debugDisplay = - AzFramework::DebugDisplayRequestBus::FindFirstHandler(debugDisplayBus); - - AzFramework::ViewportDebugDisplayEventBus::Event( - AzToolsFramework::GetEntityContextId(), &AzFramework::ViewportDebugDisplayEvents::DisplayViewport2d, - AzFramework::ViewportInfo{ GetViewportId() }, *debugDisplay); - - m_renderer->Unset2DMode(backupSceneMatrices); - - PostWidgetRendering(); - } - - if (levelIsDisplayable) - { - m_renderer->SetViewport(0, 0, m_renderer->GetWidth(), m_renderer->GetHeight(), m_nCurViewportID); - } - else - { - ColorF viewportBackgroundColor(pow(71.0f / 255.0f, 2.2f), pow(71.0f / 255.0f, 2.2f), pow(71.0f / 255.0f, 2.2f)); - m_renderer->ClearTargetsLater(FRT_CLEAR_COLOR, viewportBackgroundColor); - DrawBackground(); - } -} - -////////////////////////////////////////////////////////////////////////// -void CRenderViewport::RenderSelectionRectangle() -{ - if (m_selectedRect.isEmpty()) - { - return; - } - - Vec3 topLeft(m_selectedRect.left(), m_selectedRect.top(), 1); - Vec3 bottomRight(m_selectedRect.right() +1, m_selectedRect.bottom() + 1, 1); - - m_displayContext.DepthTestOff(); - m_displayContext.SetColor(1, 1, 1, 0.4f); - m_displayContext.DrawWireBox(topLeft, bottomRight); - m_displayContext.DepthTestOn(); -} - -////////////////////////////////////////////////////////////////////////// -void CRenderViewport::InitDisplayContext() -{ - FUNCTION_PROFILER(GetIEditor()->GetSystem(), PROFILE_EDITOR); - - // Draw all objects. - DisplayContext& displayContext = m_displayContext; - displayContext.settings = GetIEditor()->GetDisplaySettings(); - displayContext.view = this; - displayContext.renderer = m_renderer; - displayContext.box.min = Vec3(-100000.0f, -100000.0f, -100000.0f); - displayContext.box.max = Vec3(100000.0f, 100000.0f, 100000.0f); - displayContext.camera = &m_Camera; - displayContext.flags = 0; - - if (!displayContext.settings->IsDisplayLabels() || !displayContext.settings->IsDisplayHelpers()) - { - displayContext.flags |= DISPLAY_HIDENAMES; - } - - if (displayContext.settings->IsDisplayLinks() && displayContext.settings->IsDisplayHelpers()) - { - displayContext.flags |= DISPLAY_LINKS; - } - - if (m_bDegradateQuality) - { - displayContext.flags |= DISPLAY_DEGRADATED; - } - - if (displayContext.settings->GetRenderFlags() & RENDER_FLAG_BBOX) - { - displayContext.flags |= DISPLAY_BBOX; - } - - if (displayContext.settings->IsDisplayTracks() && displayContext.settings->IsDisplayHelpers()) - { - displayContext.flags |= DISPLAY_TRACKS; - displayContext.flags |= DISPLAY_TRACKTICKS; - } - - if (GetIEditor()->GetReferenceCoordSys() == COORDS_WORLD) - { - displayContext.flags |= DISPLAY_WORLDSPACEAXIS; - } -} - -////////////////////////////////////////////////////////////////////////// -void CRenderViewport::PopulateEditorGlobalContextMenu(QMenu* /*menu*/, const AZ::Vector2& /*point*/, int /*flags*/) -{ - m_bInMoveMode = false; -} - -////////////////////////////////////////////////////////////////////////// -void CRenderViewport::RenderAll() -{ - // Draw all objects. - DisplayContext& displayContext = m_displayContext; - - m_renderer->ResetToDefault(); - - displayContext.SetState(e_Mode3D | e_AlphaBlended | e_FillModeSolid | e_CullModeBack | e_DepthWriteOn | e_DepthTestOn); - GetIEditor()->GetObjectManager()->Display(displayContext); - - RenderSelectedRegion(); - - RenderSnapMarker(); - - if (gSettings.viewports.bShowGridGuide - && GetIEditor()->GetDisplaySettings()->IsDisplayHelpers()) - { - RenderSnappingGrid(); - } - - if (displayContext.settings->GetDebugFlags() & DBG_MEMINFO) - { - ProcessMemInfo mi; - CProcessInfo::QueryMemInfo(mi); - int MB = 1024 * 1024; - QString str = QStringLiteral("WorkingSet=%1Mb, PageFile=%2Mb, PageFaults=%3").arg(mi.WorkingSet / MB).arg(mi.PagefileUsage / MB).arg(mi.PageFaultCount); - m_renderer->TextToScreenColor(1, 1, 1, 0, 0, 1, str.toUtf8().data()); - } - - { - const AzFramework::DisplayContextRequestGuard displayContextGuard(displayContext); - - AzFramework::DebugDisplayRequestBus::BusPtr debugDisplayBus; - AzFramework::DebugDisplayRequestBus::Bind( - debugDisplayBus, AzFramework::g_defaultSceneEntityDebugDisplayId); - AZ_Assert(debugDisplayBus, "Invalid DebugDisplayRequestBus."); - - AzFramework::DebugDisplayRequests* debugDisplay = - AzFramework::DebugDisplayRequestBus::FindFirstHandler(debugDisplayBus); - - // allow the override of in-editor visualization - AzFramework::ViewportDebugDisplayEventBus::Event( - AzToolsFramework::GetEntityContextId(), &AzFramework::ViewportDebugDisplayEvents::DisplayViewport, - AzFramework::ViewportInfo{ GetViewportId() }, *debugDisplay); - - m_entityVisibilityQuery.DisplayVisibility(*debugDisplay); - - if (m_manipulatorManager != nullptr) - { - using namespace AzToolsFramework::ViewportInteraction; - - debugDisplay->DepthTestOff(); - m_manipulatorManager->DrawManipulators( - *debugDisplay, GetCameraState(), - BuildMouseInteractionInternal( - MouseButtons(TranslateMouseButtons(QGuiApplication::mouseButtons())), - BuildKeyboardModifiers(QGuiApplication::queryKeyboardModifiers()), - BuildMousePickInternal(WidgetToViewport(mapFromGlobal(QCursor::pos()))))); - debugDisplay->DepthTestOn(); - } - } -} - -////////////////////////////////////////////////////////////////////////// -void CRenderViewport::DrawAxis() -{ - AZ_Assert(m_cameraSetForWidgetRenderingCount > 0, - "DrawAxis was called but viewport widget rendering was not set. PreWidgetRendering must be called before."); - - DisplayContext& dc = m_displayContext; - - // show axis only if draw helpers is activated - if (!dc.settings->IsDisplayHelpers()) - { - return; - } - - Vec3 colX(1, 0, 0), colY(0, 1, 0), colZ(0, 0, 1), colW(1, 1, 1); - Vec3 pos(50, 50, 0.1f); // Bottom-left corner - - float wx, wy, wz; - m_renderer->UnProjectFromScreen(pos.x, pos.y, pos.z, &wx, &wy, &wz); - Vec3 posInWorld(wx, wy, wz); - float screenScale = GetScreenScaleFactor(posInWorld); - float length = 0.03f * screenScale; - float arrowSize = 0.02f * screenScale; - float textSize = 1.1f; - - Vec3 x(length, 0, 0); - Vec3 y(0, length, 0); - Vec3 z(0, 0, length); - - int prevRState = dc.GetState(); - dc.DepthWriteOff(); - dc.DepthTestOff(); - dc.CullOff(); - dc.SetLineWidth(1); - - dc.SetColor(colX); - dc.DrawLine(posInWorld, posInWorld + x); - dc.DrawArrow(posInWorld + x * 0.9f, posInWorld + x, arrowSize); - dc.SetColor(colY); - dc.DrawLine(posInWorld, posInWorld + y); - dc.DrawArrow(posInWorld + y * 0.9f, posInWorld + y, arrowSize); - dc.SetColor(colZ); - dc.DrawLine(posInWorld, posInWorld + z); - dc.DrawArrow(posInWorld + z * 0.9f, posInWorld + z, arrowSize); - - dc.SetColor(colW); - dc.DrawTextLabel(posInWorld + x, textSize, "x"); - dc.DrawTextLabel(posInWorld + y, textSize, "y"); - dc.DrawTextLabel(posInWorld + z, textSize, "z"); - - dc.DepthWriteOn(); - dc.DepthTestOn(); - dc.CullOn(); - dc.SetState(prevRState); -} - -////////////////////////////////////////////////////////////////////////// -void CRenderViewport::DrawBackground() -{ - DisplayContext& dc = m_displayContext; - - if (!dc.settings->IsDisplayHelpers()) // show gradient bg only if draw helpers are activated - { - return; - } - - int heightVP = m_renderer->GetHeight() - 1; - int widthVP = m_renderer->GetWidth() - 1; - Vec3 pos(0, 0, 0); - - Vec3 x(widthVP, 0, 0); - Vec3 y(0, heightVP, 0); - - float height = m_rcClient.height(); - - Vec3 src = NegY(pos, height); - Vec3 trgx = NegY(pos + x, height); - Vec3 trgy = NegY(pos + y, height); - - QColor topColor = palette().color(QPalette::Window); - QColor bottomColor = palette().color(QPalette::Disabled, QPalette::WindowText); - - ColorB firstC(topColor.red(), topColor.green(), topColor.blue(), 255.0f); - ColorB secondC(bottomColor.red(), bottomColor.green(), bottomColor.blue(), 255.0f); - - TransformationMatrices backupSceneMatrices; - - m_renderer->Set2DMode(m_rcClient.right(), m_rcClient.bottom(), backupSceneMatrices); - m_displayContext.SetState(e_Mode3D | e_AlphaBlended | e_FillModeSolid | e_CullModeBack | e_DepthWriteOn | e_DepthTestOn); - dc.DrawQuadGradient(src, trgx, pos + x, pos, secondC, firstC); - m_renderer->Unset2DMode(backupSceneMatrices); -} - -////////////////////////////////////////////////////////////////////////// -void CRenderViewport::RenderCursorString() -{ - if (m_cursorStr.isEmpty()) - { - return; - } - - const auto point = WidgetToViewport(mapFromGlobal(QCursor::pos())); - - // Display hit object name. - float col[4] = { 1, 1, 1, 1 }; - m_renderer->Draw2dLabel(point.x() + 12, point.y() + 4, 1.2f, col, false, "%s", m_cursorStr.toUtf8().data()); - - if (!m_cursorSupplementaryStr.isEmpty()) - { - float col2[4] = { 1, 1, 0, 1 }; - m_renderer->Draw2dLabel(point.x() + 12, point.y() + 4 + CURSOR_FONT_HEIGHT * 1.2f, 1.2f, col2, false, "%s", m_cursorSupplementaryStr.toUtf8().data()); - } -} - -////////////////////////////////////////////////////////////////////////// -void CRenderViewport::UpdateSafeFrame() -{ - m_safeFrame = m_rcClient; - - if (m_safeFrame.height() == 0) - { - return; - } - - const bool allowSafeFrameBiggerThanViewport = false; - - float safeFrameAspectRatio = float( m_safeFrame.width()) / m_safeFrame.height(); - float targetAspectRatio = GetAspectRatio(); - bool viewportIsWiderThanSafeFrame = (targetAspectRatio <= safeFrameAspectRatio); - if (viewportIsWiderThanSafeFrame || allowSafeFrameBiggerThanViewport) - { - float maxSafeFrameWidth = m_safeFrame.height() * targetAspectRatio; - float widthDifference = m_safeFrame.width() - maxSafeFrameWidth; - - m_safeFrame.setLeft(m_safeFrame.left() + widthDifference * 0.5); - m_safeFrame.setRight(m_safeFrame.right() - widthDifference * 0.5); - } - else - { - float maxSafeFrameHeight = m_safeFrame.width() / targetAspectRatio; - float heightDifference = m_safeFrame.height() - maxSafeFrameHeight; - - m_safeFrame.setTop(m_safeFrame.top() + heightDifference * 0.5); - m_safeFrame.setBottom(m_safeFrame.bottom() - heightDifference * 0.5); - } - - m_safeFrame.adjust(0, 0, -1, -1); // <-- aesthetic improvement. - - const float SAFE_ACTION_SCALE_FACTOR = 0.05f; - m_safeAction = m_safeFrame; - m_safeAction.adjust(m_safeFrame.width() * SAFE_ACTION_SCALE_FACTOR, m_safeFrame.height() * SAFE_ACTION_SCALE_FACTOR, - -m_safeFrame.width() * SAFE_ACTION_SCALE_FACTOR, -m_safeFrame.height() * SAFE_ACTION_SCALE_FACTOR); - - const float SAFE_TITLE_SCALE_FACTOR = 0.1f; - m_safeTitle = m_safeFrame; - m_safeTitle.adjust(m_safeFrame.width() * SAFE_TITLE_SCALE_FACTOR, m_safeFrame.height() * SAFE_TITLE_SCALE_FACTOR, - -m_safeFrame.width() * SAFE_TITLE_SCALE_FACTOR, -m_safeFrame.height() * SAFE_TITLE_SCALE_FACTOR); -} - -////////////////////////////////////////////////////////////////////////// -void CRenderViewport::RenderSafeFrame() -{ - RenderSafeFrame(m_safeFrame, 0.75f, 0.75f, 0, 0.8f); - RenderSafeFrame(m_safeAction, 0, 0.85f, 0.80f, 0.8f); - RenderSafeFrame(m_safeTitle, 0.80f, 0.60f, 0, 0.8f); -} - -////////////////////////////////////////////////////////////////////////// -void CRenderViewport::RenderSafeFrame(const QRect& frame, float r, float g, float b, float a) -{ - m_displayContext.SetColor(r, g, b, a); - - const int LINE_WIDTH = 2; - for (int i = 0; i < LINE_WIDTH; i++) - { - Vec3 topLeft(frame.left() + i, frame.top() + i, 0); - Vec3 bottomRight(frame.right() - i, frame.bottom() - i, 0); - m_displayContext.DrawWireBox(topLeft, bottomRight); - } -} - -////////////////////////////////////////////////////////////////////////// -float CRenderViewport::GetAspectRatio() const -{ - return gSettings.viewports.fDefaultAspectRatio; -} - -////////////////////////////////////////////////////////////////////////// -void CRenderViewport::RenderSnapMarker() -{ - if (!gSettings.snap.markerDisplay) - { - return; - } - - QPoint point = QCursor::pos(); - ScreenToClient(point); - Vec3 p = MapViewToCP(point); - - DisplayContext& dc = m_displayContext; - - float fScreenScaleFactor = GetScreenScaleFactor(p); - - Vec3 x(1, 0, 0); - Vec3 y(0, 1, 0); - Vec3 z(0, 0, 1); - x = x * gSettings.snap.markerSize * fScreenScaleFactor * 0.1f; - y = y * gSettings.snap.markerSize * fScreenScaleFactor * 0.1f; - z = z * gSettings.snap.markerSize * fScreenScaleFactor * 0.1f; - - dc.SetColor(gSettings.snap.markerColor); - dc.DrawLine(p - x, p + x); - dc.DrawLine(p - y, p + y); - dc.DrawLine(p - z, p + z); - - point = WorldToView(p); - - int s = 8; - dc.DrawLine2d(point + QPoint(-s, -s), point + QPoint(s, -s), 0); - dc.DrawLine2d(point + QPoint(-s, s), point + QPoint(s, s), 0); - dc.DrawLine2d(point + QPoint(-s, -s), point + QPoint(-s, s), 0); - dc.DrawLine2d(point + QPoint(s, -s), point + QPoint(s, s), 0); -} - -////////////////////////////////////////////////////////////////////////// -static void OnMenuDisplayWireframe() -{ - ICVar* piVar(gEnv->pConsole->GetCVar("r_wireframe")); - int nRenderMode = piVar->GetIVal(); - if (nRenderMode != R_WIREFRAME_MODE) - { - piVar->Set(R_WIREFRAME_MODE); - } - else - { - piVar->Set(R_SOLID_MODE); - } -} - -////////////////////////////////////////////////////////////////////////// -static void OnMenuTargetAspectRatio(float aspect) -{ - gSettings.viewports.fDefaultAspectRatio = aspect; -} - -////////////////////////////////////////////////////////////////////////// -void CRenderViewport::OnMenuResolutionCustom() -{ - CCustomResolutionDlg resDlg(width(), height(), parentWidget()); - if (resDlg.exec() == QDialog::Accepted) - { - ResizeView(resDlg.GetWidth(), resDlg.GetHeight()); - - const QString text = QString::fromLatin1("%1 x %2").arg(resDlg.GetWidth()).arg(resDlg.GetHeight()); - - QStringList customResPresets; - CViewportTitleDlg::LoadCustomPresets("ResPresets", "ResPresetFor2ndView", customResPresets); - CViewportTitleDlg::UpdateCustomPresets(text, customResPresets); - CViewportTitleDlg::SaveCustomPresets("ResPresets", "ResPresetFor2ndView", customResPresets); - } -} - -////////////////////////////////////////////////////////////////////////// -void CRenderViewport::OnMenuCreateCameraEntityFromCurrentView() -{ - Camera::EditorCameraSystemRequestBus::Broadcast(&Camera::EditorCameraSystemRequests::CreateCameraEntityFromViewport); -} - -////////////////////////////////////////////////////////////////////////// -void CRenderViewport::OnMenuSelectCurrentCamera() -{ - CBaseObject* pCameraObject = GetCameraObject(); - - if (pCameraObject && !pCameraObject->IsSelected()) - { - GetIEditor()->BeginUndo(); - IObjectManager* pObjectManager = GetIEditor()->GetObjectManager(); - pObjectManager->ClearSelection(); - pObjectManager->SelectObject(pCameraObject); - GetIEditor()->AcceptUndo("Select Current Camera"); - } -} - -static AzFramework::CameraState CameraStateFromCCamera( - const CCamera& camera, const float fov, const float width, const float height) -{ - FUNCTION_PROFILER(GetIEditor()->GetSystem(), PROFILE_EDITOR); - - AzFramework::CameraState state; - state.m_forward = LYVec3ToAZVec3(camera.GetViewdir()); - state.m_up = LYVec3ToAZVec3(camera.GetUp()); - state.m_side = state.m_forward.Cross(state.m_up); - state.m_position = LYVec3ToAZVec3(camera.GetPosition()); - state.m_fovOrZoom = fov; - state.m_nearClip = camera.GetNearPlane(); - state.m_farClip = camera.GetFarPlane(); - state.m_orthographic = false; - state.m_viewportSize = AZ::Vector2(width, height); - - return state; -} - -AzFramework::CameraState CRenderViewport::GetCameraState() -{ - return CameraStateFromCCamera(GetCamera(), GetFOV(), m_rcClient.width(), m_rcClient.height()); -} - -bool CRenderViewport::GridSnappingEnabled() -{ - return false; -} - -float CRenderViewport::GridSize() -{ - return 0.0f; -} - -bool CRenderViewport::ShowGrid() -{ - return false; -} - -bool CRenderViewport::AngleSnappingEnabled() -{ - return false; -} - -float CRenderViewport::AngleStep() -{ - return 0.0f; -} - -AZ::Vector3 CRenderViewport::PickTerrain(const AzFramework::ScreenPoint& point) -{ - FUNCTION_PROFILER(GetIEditor()->GetSystem(), PROFILE_EDITOR); - - return LYVec3ToAZVec3(ViewToWorld(AzToolsFramework::ViewportInteraction::QPointFromScreenPoint(point), nullptr, true)); -} - -AZ::EntityId CRenderViewport::PickEntity(const AzFramework::ScreenPoint& point) -{ - FUNCTION_PROFILER(GetIEditor()->GetSystem(), PROFILE_EDITOR); - - PreWidgetRendering(); - - AZ::EntityId entityId; - HitContext hitInfo; - hitInfo.view = this; - if (HitTest(AzToolsFramework::ViewportInteraction::QPointFromScreenPoint(point), hitInfo)) - { - if (hitInfo.object && (hitInfo.object->GetType() == OBJTYPE_AZENTITY)) - { - auto entityObject = static_cast(hitInfo.object); - entityId = entityObject->GetAssociatedEntityId(); - } - } - - PostWidgetRendering(); - - return entityId; -} - -float CRenderViewport::TerrainHeight(const AZ::Vector2& position) -{ - return GetIEditor()->GetTerrainElevation(position.GetX(), position.GetY()); -} - -void CRenderViewport::FindVisibleEntities(AZStd::vector& visibleEntitiesOut) -{ - FUNCTION_PROFILER(GetIEditor()->GetSystem(), PROFILE_EDITOR); - - if (ed_visibility_use) - { - visibleEntitiesOut.assign(m_entityVisibilityQuery.Begin(), m_entityVisibilityQuery.End()); - } - else - { - if (m_displayContext.GetView() == nullptr) - { - return; - } - - const AZStd::vector& entityIdCache = - m_displayContext.GetView()->GetVisibleObjectsCache()->GetEntityIdCache(); - - visibleEntitiesOut.assign(entityIdCache.begin(), entityIdCache.end()); - } -} - -AzFramework::ScreenPoint CRenderViewport::ViewportWorldToScreen(const AZ::Vector3& worldPosition) -{ - FUNCTION_PROFILER(GetIEditor()->GetSystem(), PROFILE_EDITOR); - - PreWidgetRendering(); - const AzFramework::ScreenPoint screenPosition = - AzToolsFramework::ViewportInteraction::ScreenPointFromQPoint(WorldToView(AZVec3ToLYVec3(worldPosition))); - PostWidgetRendering(); - - return screenPosition; -} - -bool CRenderViewport::IsViewportInputFrozen() -{ - return m_freezeViewportInput; -} - -void CRenderViewport::FreezeViewportInput(bool freeze) -{ - m_freezeViewportInput = freeze; -} - -QWidget* CRenderViewport::GetWidgetForViewportContextMenu() -{ - return this; -} - -void CRenderViewport::BeginWidgetContext() -{ - PreWidgetRendering(); -} - -void CRenderViewport::EndWidgetContext() -{ - PostWidgetRendering(); -} - -bool CRenderViewport::ShowingWorldSpace() -{ - using namespace AzToolsFramework::ViewportInteraction; - return BuildKeyboardModifiers(QGuiApplication::queryKeyboardModifiers()).Shift(); -} - -void CRenderViewport::SetWindowTitle(const AZStd::string& title) -{ - // Do not support the WindowRequestBus changing the editor window title - AZ_UNUSED(title); -} - -AzFramework::WindowSize CRenderViewport::GetClientAreaSize() const -{ - return AzFramework::WindowSize(m_rcClient.width(), m_rcClient.height()); -} - - -void CRenderViewport::ResizeClientArea(AzFramework::WindowSize clientAreaSize) -{ - QWidget* window = this->window(); - window->resize(aznumeric_cast(clientAreaSize.m_width), aznumeric_cast(clientAreaSize.m_height)); -} - -bool CRenderViewport::GetFullScreenState() const -{ - // CRenderViewport does not currently support full screen. - return false; -} - -void CRenderViewport::SetFullScreenState([[maybe_unused]]bool fullScreenState) -{ - // CRenderViewport does not currently support full screen. -} - -bool CRenderViewport::CanToggleFullScreenState() const -{ - // CRenderViewport does not currently support full screen. - return false; -} - -void CRenderViewport::ToggleFullScreenState() -{ - // CRenderViewport does not currently support full screen. -} - -void CRenderViewport::ConnectViewportInteractionRequestBus() -{ - AzToolsFramework::ViewportInteraction::ViewportFreezeRequestBus::Handler::BusConnect(GetViewportId()); - AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::Handler::BusConnect(GetViewportId()); - AzToolsFramework::ViewportInteraction::MainEditorViewportInteractionRequestBus::Handler::BusConnect(GetViewportId()); - m_viewportUi.ConnectViewportUiBus(GetViewportId()); - - AzFramework::InputSystemCursorConstraintRequestBus::Handler::BusConnect(); -} - -void CRenderViewport::DisconnectViewportInteractionRequestBus() -{ - AzFramework::InputSystemCursorConstraintRequestBus::Handler::BusDisconnect(); - - m_viewportUi.DisconnectViewportUiBus(); - AzToolsFramework::ViewportInteraction::MainEditorViewportInteractionRequestBus::Handler::BusDisconnect(); - AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::Handler::BusDisconnect(); - AzToolsFramework::ViewportInteraction::ViewportFreezeRequestBus::Handler::BusDisconnect(); -} - -////////////////////////////////////////////////////////////////////////// -static void ToggleBool(bool* variable, bool* disableVariableIfOn) -{ - *variable = !*variable; - if (*variable && disableVariableIfOn) - { - *disableVariableIfOn = false; - } -} - -////////////////////////////////////////////////////////////////////////// -static void ToggleInt(int* variable) -{ - *variable = !*variable; -} - -////////////////////////////////////////////////////////////////////////// -static void AddCheckbox(QMenu* menu, const QString& text, bool* variable, bool* disableVariableIfOn = nullptr) -{ - QAction* action = menu->addAction(text); - QObject::connect(action, &QAction::triggered, action, [variable, disableVariableIfOn] { ToggleBool(variable, disableVariableIfOn); - }); - action->setCheckable(true); - action->setChecked(*variable); -} - -////////////////////////////////////////////////////////////////////////// -static void AddCheckbox(QMenu* menu, const QString& text, int* variable) -{ - QAction* action = menu->addAction(text); - QObject::connect(action, &QAction::triggered, action, [variable] { ToggleInt(variable); - }); - action->setCheckable(true); - action->setChecked(*variable); -} - -////////////////////////////////////////////////////////////////////////// -void CRenderViewport::OnTitleMenu(QMenu* menu) -{ - const int nWireframe = gEnv->pConsole->GetCVar("r_wireframe")->GetIVal(); - QAction* action = menu->addAction(tr("Wireframe")); - connect(action, &QAction::triggered, action, OnMenuDisplayWireframe); - action->setCheckable(true); - action->setChecked(nWireframe == R_WIREFRAME_MODE); - - const bool bDisplayLabels = GetIEditor()->GetDisplaySettings()->IsDisplayLabels(); - action = menu->addAction(tr("Labels")); - connect(action, &QAction::triggered, this, [bDisplayLabels] {GetIEditor()->GetDisplaySettings()->DisplayLabels(!bDisplayLabels); - }); - action->setCheckable(true); - action->setChecked(bDisplayLabels); - - AddCheckbox(menu, tr("Show Safe Frame"), &gSettings.viewports.bShowSafeFrame); - AddCheckbox(menu, tr("Show Construction Plane"), &gSettings.snap.constructPlaneDisplay); - AddCheckbox(menu, tr("Show Trigger Bounds"), &gSettings.viewports.bShowTriggerBounds); - AddCheckbox(menu, tr("Show Icons"), &gSettings.viewports.bShowIcons, &gSettings.viewports.bShowSizeBasedIcons); - AddCheckbox(menu, tr("Show Size-based Icons"), &gSettings.viewports.bShowSizeBasedIcons, &gSettings.viewports.bShowIcons); - AddCheckbox(menu, tr("Show Helpers of Frozen Objects"), &gSettings.viewports.nShowFrozenHelpers); - - if (!m_predefinedAspectRatios.IsEmpty()) - { - QMenu* aspectRatiosMenu = menu->addMenu(tr("Target Aspect Ratio")); - - for (size_t i = 0; i < m_predefinedAspectRatios.GetCount(); ++i) - { - const QString& aspectRatioString = m_predefinedAspectRatios.GetName(i); - QAction* aspectRatioAction = aspectRatiosMenu->addAction(aspectRatioString); - connect(aspectRatioAction, &QAction::triggered, this, [i, this] { OnMenuTargetAspectRatio(m_predefinedAspectRatios.GetValue(i)); - }); - aspectRatioAction->setCheckable(true); - aspectRatioAction->setChecked(m_predefinedAspectRatios.IsCurrent(i)); - } - } - - // Set ourself as the active viewport so the following actions create a camera from this view - GetIEditor()->GetViewManager()->SelectViewport(this); - - CGameEngine* gameEngine = GetIEditor()->GetGameEngine(); - - if (Camera::EditorCameraSystemRequestBus::HasHandlers()) - { - action = menu->addAction(tr("Create camera entity from current view")); - connect(action, &QAction::triggered, this, &CRenderViewport::OnMenuCreateCameraEntityFromCurrentView); - - if (!gameEngine || !gameEngine->IsLevelLoaded()) - { - action->setEnabled(false); - action->setToolTip(tr(TextCantCreateCameraNoLevel)); - menu->setToolTipsVisible(true); - } - } - - if (!gameEngine || !gameEngine->IsLevelLoaded()) - { - action->setEnabled(false); - action->setToolTip(tr(TextCantCreateCameraNoLevel)); - menu->setToolTipsVisible(true); - } - - if (GetCameraObject()) - { - action = menu->addAction(tr("Select Current Camera")); - connect(action, &QAction::triggered, this, &CRenderViewport::OnMenuSelectCurrentCamera); - } - - // Add Cameras. - bool bHasCameras = AddCameraMenuItems(menu); - CRenderViewport* pFloatingViewport = nullptr; - - if (GetIEditor()->GetViewManager()->GetViewCount() > 1) - { - for (int i = 0; i < GetIEditor()->GetViewManager()->GetViewCount(); ++i) - { - CViewport* vp = GetIEditor()->GetViewManager()->GetView(i); - if (!vp) - { - continue; - } - - if (viewport_cast(vp) == nullptr) - { - continue; - } - - if (vp->GetViewportId() == MAX_NUM_VIEWPORTS - 1) - { - menu->addSeparator(); - - QMenu* floatViewMenu = menu->addMenu(tr("Floating View")); - - pFloatingViewport = (CRenderViewport*)vp; - pFloatingViewport->AddCameraMenuItems(floatViewMenu); - - if (bHasCameras) - { - floatViewMenu->addSeparator(); - } - - QMenu* resolutionMenu = floatViewMenu->addMenu(tr("Resolution")); - - QStringList customResPresets; - CViewportTitleDlg::LoadCustomPresets("ResPresets", "ResPresetFor2ndView", customResPresets); - CViewportTitleDlg::AddResolutionMenus(resolutionMenu, [this](int width, int height) { ResizeView(width, height); }, customResPresets); - if (!resolutionMenu->actions().isEmpty()) - { - resolutionMenu->addSeparator(); - } - QAction* customResolutionAction = resolutionMenu->addAction(tr("Custom...")); - connect(customResolutionAction, &QAction::triggered, this, &CRenderViewport::OnMenuResolutionCustom); - break; - } - } - } -} - -////////////////////////////////////////////////////////////////////////// -bool CRenderViewport::AddCameraMenuItems(QMenu* menu) -{ - if (!menu->isEmpty()) - { - menu->addSeparator(); - } - - AddCheckbox(menu, "Lock Camera Movement", &m_bLockCameraMovement); - menu->addSeparator(); - - // Camera Sub menu - QMenu* customCameraMenu = menu->addMenu(tr("Camera")); - - QAction* action = customCameraMenu->addAction("Editor Camera"); - action->setCheckable(true); - action->setChecked(m_viewSourceType == ViewSourceType::None); - connect(action, &QAction::triggered, this, &CRenderViewport::SetDefaultCamera); - - AZ::EBusAggregateResults getCameraResults; - Camera::CameraBus::BroadcastResult(getCameraResults, &Camera::CameraRequests::GetCameras); - - const int numCameras = getCameraResults.values.size(); - - // only enable if we're editing a sequence in Track View and have cameras in the level - bool enableSequenceCameraMenu = (GetIEditor()->GetAnimation()->GetSequence() && numCameras); - - action = customCameraMenu->addAction(tr("Sequence Camera")); - action->setCheckable(true); - action->setChecked(m_viewSourceType == ViewSourceType::SequenceCamera); - action->setEnabled(enableSequenceCameraMenu); - connect(action, &QAction::triggered, this, &CRenderViewport::SetSequenceCamera); - - QVector additionalCameras; - additionalCameras.reserve(getCameraResults.values.size()); - - for (const AZ::EntityId& entityId : getCameraResults.values) - { - AZStd::string entityName; - AZ::ComponentApplicationBus::BroadcastResult(entityName, &AZ::ComponentApplicationRequests::GetEntityName, entityId); - action = new QAction(QString(entityName.c_str()), nullptr); - additionalCameras.append(action); - action->setCheckable(true); - action->setChecked(m_viewEntityId == entityId && m_viewSourceType == ViewSourceType::CameraComponent); - connect(action, &QAction::triggered, this, [this, entityId](bool isChecked) - { - if (isChecked) - { - SetComponentCamera(entityId); - } - else - { - SetDefaultCamera(); - } - }); - } - - std::sort(additionalCameras.begin(), additionalCameras.end(), [] (QAction* a1, QAction* a2) { - return QString::compare(a1->text(), a2->text(), Qt::CaseInsensitive) < 0; - }); - - for (QAction* cameraAction : additionalCameras) - { - customCameraMenu->addAction(cameraAction); - } - - action = customCameraMenu->addAction(tr("Look through entity")); - AzToolsFramework::EntityIdList selectedEntityList; - AzToolsFramework::ToolsApplicationRequests::Bus::BroadcastResult(selectedEntityList, &AzToolsFramework::ToolsApplicationRequests::GetSelectedEntities); - action->setCheckable(selectedEntityList.size() > 0 || m_viewSourceType == ViewSourceType::AZ_Entity); - action->setEnabled(selectedEntityList.size() > 0 || m_viewSourceType == ViewSourceType::AZ_Entity); - action->setChecked(m_viewSourceType == ViewSourceType::AZ_Entity); - connect(action, &QAction::triggered, this, [this](bool isChecked) - { - if (isChecked) - { - AzToolsFramework::EntityIdList selectedEntityList; - AzToolsFramework::ToolsApplicationRequests::Bus::BroadcastResult(selectedEntityList, &AzToolsFramework::ToolsApplicationRequests::GetSelectedEntities); - if (selectedEntityList.size()) - { - SetEntityAsCamera(*selectedEntityList.begin()); - } - } - else - { - SetDefaultCamera(); - } - }); - return true; -} - -////////////////////////////////////////////////////////////////////////// -void CRenderViewport::ResizeView(int width, int height) -{ - const QRect rView = rect().translated(mapToGlobal(QPoint())); - int deltaWidth = width - rView.width(); - int deltaHeight = height - rView.height(); - - if (window()->isFullScreen()) - { - setGeometry(rView.left(), rView.top(), rView.width() + deltaWidth, rView.height() + deltaHeight); - } - else - { - QWidget* window = this->window(); - if (window->isMaximized()) - { - window->showNormal(); - } - - const QSize deltaSize = QSize(width, height) - size(); - window->move(0, 0); - window->resize(window->size() + deltaSize); - } -} - -////////////////////////////////////////////////////////////////////////// -void CRenderViewport::ToggleCameraObject() -{ - if (m_viewSourceType == ViewSourceType::SequenceCamera) - { - ResetToViewSourceType(ViewSourceType::LegacyCamera); - } - else - { - ResetToViewSourceType(ViewSourceType::SequenceCamera); - } - PostCameraSet(); - GetIEditor()->GetAnimation()->ForceAnimation(); -} - -void CRenderViewport::OnMouseWheel(Qt::KeyboardModifiers modifiers, short zDelta, const QPoint& point) -{ - using namespace AzToolsFramework::ViewportInteraction; - using AzToolsFramework::EditorInteractionSystemViewportSelectionRequestBus; - - if (GetIEditor()->IsInGameMode() || m_freezeViewportInput) - { - return; - } - - const auto scaledPoint = WidgetToViewport(point); - const auto mouseInteraction = BuildMouseInteractionInternal( - MouseButtonsFromButton(MouseButton::None), - BuildKeyboardModifiers(modifiers), - BuildMousePick(scaledPoint)); - - bool handled = false; - MouseInteractionResult result = MouseInteractionResult::None; - AzToolsFramework::EditorInteractionSystemViewportSelectionRequestBus::EventResult( - result, AzToolsFramework::GetEntityContextId(), - &EditorInteractionSystemViewportSelectionRequestBus::Events::InternalHandleAllMouseInteractions, - MouseInteractionEvent(mouseInteraction, zDelta)); - - handled = result != MouseInteractionResult::None; - - if (!handled) - { - Matrix34 m = GetViewTM(); - const Vec3 ydir = m.GetColumn1().GetNormalized(); - - Vec3 pos = m.GetTranslation(); - - const float posDelta = 0.01f * zDelta * gSettings.wheelZoomSpeed; - pos += ydir * posDelta; - m_orbitDistance = m_orbitDistance - posDelta; - m_orbitDistance = fabs(m_orbitDistance); - - m.SetTranslation(pos); - SetViewTM(m, true); - - QtViewport::OnMouseWheel(modifiers, zDelta, scaledPoint); - } -} - -////////////////////////////////////////////////////////////////////////// -void CRenderViewport::SetCamera(const CCamera& camera) -{ - m_Camera = camera; - SetViewTM(m_Camera.GetMatrix()); -} - -////////////////////////////////////////////////////////////////////////// -float CRenderViewport::GetCameraMoveSpeed() const -{ - return gSettings.cameraMoveSpeed; -} - -////////////////////////////////////////////////////////////////////////// -float CRenderViewport::GetCameraRotateSpeed() const -{ - return gSettings.cameraRotateSpeed; -} - -////////////////////////////////////////////////////////////////////////// -bool CRenderViewport::GetCameraInvertYRotation() const -{ - return gSettings.invertYRotation; -} - -////////////////////////////////////////////////////////////////////////// -float CRenderViewport::GetCameraInvertPan() const -{ - return gSettings.invertPan; -} - -////////////////////////////////////////////////////////////////////////// -CRenderViewport* CRenderViewport::GetPrimaryViewport() -{ - return m_pPrimaryViewport; -} - -////////////////////////////////////////////////////////////////////////// -void CRenderViewport::focusOutEvent([[maybe_unused]] QFocusEvent* event) -{ - // if we lose focus, the keyboard map needs to be cleared immediately - if (!m_keyDown.isEmpty()) - { - m_keyDown.clear(); - - releaseKeyboard(); - } -} - -void CRenderViewport::keyPressEvent(QKeyEvent* event) -{ - // Special case Escape key and bubble way up to the top level parent so that it can cancel us out of any active tool - // or clear the current selection - if (event->key() == Qt::Key_Escape) - { - QCoreApplication::sendEvent(GetIEditor()->GetEditorMainWindow(), event); - } - - // NOTE: we keep track of keypresses and releases explicitly because the OS/Qt will insert a slight delay between sending - // keyevents when the key is held down. This is standard, but makes responding to key events for game style input silly - // because we want the movement to be butter smooth. - if (!event->isAutoRepeat()) - { - if (m_keyDown.isEmpty()) - { - grabKeyboard(); - } - - m_keyDown.insert(event->key()); - } - - QtViewport::keyPressEvent(event); - -#if defined(AZ_PLATFORM_WINDOWS) - // In game mode on windows we need to forward raw text events to the input system. - if (GetIEditor()->IsInGameMode() && GetType() == ET_ViewportCamera) - { - // Get the QString as a '\0'-terminated array of unsigned shorts. - // The result remains valid until the string is modified. - const ushort* codeUnitsUTF16 = event->text().utf16(); - while (ushort codeUnitUTF16 = *codeUnitsUTF16) - { - AzFramework::RawInputNotificationBusWindows::Broadcast(&AzFramework::RawInputNotificationsWindows::OnRawInputCodeUnitUTF16Event, codeUnitUTF16); - ++codeUnitsUTF16; - } - } -#endif // defined(AZ_PLATFORM_WINDOWS) -} - -void CRenderViewport::ProcessKeyRelease(QKeyEvent* event) -{ - if (!event->isAutoRepeat()) - { - if (m_keyDown.contains(event->key())) - { - m_keyDown.remove(event->key()); - - if (m_keyDown.isEmpty()) - { - releaseKeyboard(); - } - } - } -} - -void CRenderViewport::keyReleaseEvent(QKeyEvent* event) -{ - ProcessKeyRelease(event); - - QtViewport::keyReleaseEvent(event); -} - -void CRenderViewport::SetViewTM(const Matrix34& viewTM, bool bMoveOnly) -{ - Matrix34 camMatrix = viewTM; - - // If no collision flag set do not check for terrain elevation. - if (GetType() == ET_ViewportCamera) - { - if ((GetIEditor()->GetDisplaySettings()->GetSettings() & SETTINGS_NOCOLLISION) == 0) - { - Vec3 p = camMatrix.GetTranslation(); - bool adjustCameraElevation = true; - auto terrain = AzFramework::Terrain::TerrainDataRequestBus::FindFirstHandler(); - if (terrain) - { - AZ::Aabb terrainAabb(terrain->GetTerrainAabb()); - - // Adjust the AABB to include all Z values. Since the goal here is to snap the camera to the terrain height if - // it's below the terrain, we only want to verify the camera is within the XY bounds of the terrain to adjust the elevation. - terrainAabb.SetMin(AZ::Vector3(terrainAabb.GetMin().GetX(), terrainAabb.GetMin().GetY(), -AZ::Constants::FloatMax)); - terrainAabb.SetMax(AZ::Vector3(terrainAabb.GetMax().GetX(), terrainAabb.GetMax().GetY(), AZ::Constants::FloatMax)); - - if (!terrainAabb.Contains(LYVec3ToAZVec3(p))) - { - adjustCameraElevation = false; - } - else if (terrain->GetIsHoleFromFloats(p.x, p.y)) - { - adjustCameraElevation = false; - } - } - - if (adjustCameraElevation) - { - float z = GetIEditor()->GetTerrainElevation(p.x, p.y); - if (p.z < z + 0.25) - { - p.z = z + 0.25; - camMatrix.SetTranslation(p); - } - } - } - - // Also force this position on game. - if (GetIEditor()->GetGameEngine()) - { - GetIEditor()->GetGameEngine()->SetPlayerViewMatrix(viewTM); - } - } - - CBaseObject* cameraObject = GetCameraObject(); - if (cameraObject) - { - // Ignore camera movement if locked. - if (IsCameraMovementLocked() || (!GetIEditor()->GetAnimation()->IsRecordMode() && !IsCameraObjectMove())) - { - return; - } - - AZ::Matrix3x3 lookThroughEntityCorrection = AZ::Matrix3x3::CreateIdentity(); - if (m_viewEntityId.IsValid()) - { - LmbrCentral::EditorCameraCorrectionRequestBus::EventResult( - lookThroughEntityCorrection, m_viewEntityId, - &LmbrCentral::EditorCameraCorrectionRequests::GetInverseTransformCorrection); - } - - if (m_pressedKeyState != KeyPressedState::PressedInPreviousFrame) - { - CUndo undo("Move Camera"); - if (bMoveOnly) - { - // specify eObjectUpdateFlags_UserInput so that an undo command gets logged - cameraObject->SetWorldPos(camMatrix.GetTranslation(), eObjectUpdateFlags_UserInput); - } - else - { - // specify eObjectUpdateFlags_UserInput so that an undo command gets logged - cameraObject->SetWorldTM(camMatrix * AZMatrix3x3ToLYMatrix3x3(lookThroughEntityCorrection), eObjectUpdateFlags_UserInput); - } - } - else - { - if (bMoveOnly) - { - // Do not specify eObjectUpdateFlags_UserInput, so that an undo command does not get logged; we covered it already when m_pressedKeyState was PressedThisFrame - cameraObject->SetWorldPos(camMatrix.GetTranslation()); - } - else - { - // Do not specify eObjectUpdateFlags_UserInput, so that an undo command does not get logged; we covered it already when m_pressedKeyState was PressedThisFrame - cameraObject->SetWorldTM(camMatrix * AZMatrix3x3ToLYMatrix3x3(lookThroughEntityCorrection)); - } - } - - using namespace AzToolsFramework; - ComponentEntityObjectRequestBus::Event(cameraObject, &ComponentEntityObjectRequestBus::Events::UpdatePreemptiveUndoCache); - } - else if (m_viewEntityId.IsValid()) - { - // Ignore camera movement if locked. - if (IsCameraMovementLocked() || (!GetIEditor()->GetAnimation()->IsRecordMode() && !IsCameraObjectMove())) - { - return; - } - - if (m_pressedKeyState != KeyPressedState::PressedInPreviousFrame) - { - CUndo undo("Move Camera"); - if (bMoveOnly) - { - AZ::TransformBus::Event( - m_viewEntityId, &AZ::TransformInterface::SetWorldTranslation, - LYVec3ToAZVec3(camMatrix.GetTranslation())); - } - else - { - AZ::TransformBus::Event( - m_viewEntityId, &AZ::TransformInterface::SetWorldTM, - LYTransformToAZTransform(camMatrix)); - } - } - else - { - if (bMoveOnly) - { - AZ::TransformBus::Event( - m_viewEntityId, &AZ::TransformInterface::SetWorldTranslation, - LYVec3ToAZVec3(camMatrix.GetTranslation())); - } - else - { - AZ::TransformBus::Event( - m_viewEntityId, &AZ::TransformInterface::SetWorldTM, - LYTransformToAZTransform(camMatrix)); - } - } - - AzToolsFramework::PropertyEditorGUIMessages::Bus::Broadcast( - &AzToolsFramework::PropertyEditorGUIMessages::RequestRefresh, - AzToolsFramework::PropertyModificationRefreshLevel::Refresh_AttributesAndValues); - } - - if (m_pressedKeyState == KeyPressedState::PressedThisFrame) - { - m_pressedKeyState = KeyPressedState::PressedInPreviousFrame; - } - - QtViewport::SetViewTM(camMatrix); - - m_Camera.SetMatrix(camMatrix); -} - -////////////////////////////////////////////////////////////////////////// -void CRenderViewport::RenderSelectedRegion() -{ - AABB box; - GetIEditor()->GetSelectedRegion(box); - if (box.IsEmpty()) - { - return; - } - - float x1 = box.min.x; - float y1 = box.min.y; - float x2 = box.max.x; - float y2 = box.max.y; - - DisplayContext& dc = m_displayContext; - - float fMaxSide = MAX(y2 - y1, x2 - x1); - if (fMaxSide < 0.1f) - { - return; - } - float fStep = fMaxSide / 100.0f; - - float fMinZ = 0; - float fMaxZ = 0; - - // Draw yellow border lines. - dc.SetColor(1, 1, 0, 1); - float offset = 0.01f; - Vec3 p1, p2; - - const float defaultTerrainHeight = AzFramework::Terrain::TerrainDataRequests::GetDefaultTerrainHeight(); - auto terrain = AzFramework::Terrain::TerrainDataRequestBus::FindFirstHandler(); - - for (float y = y1; y < y2; y += fStep) - { - p1.x = x1; - p1.y = y; - p1.z = terrain ? terrain->GetHeightFromFloats(p1.x, p1.y) + offset : defaultTerrainHeight + offset; - - p2.x = x1; - p2.y = y + fStep; - p2.z = terrain ? terrain->GetHeightFromFloats(p2.x, p2.y) + offset : defaultTerrainHeight + offset; - dc.DrawLine(p1, p2); - - p1.x = x2; - p1.y = y; - p1.z = terrain ? terrain->GetHeightFromFloats(p1.x, p1.y) + offset : defaultTerrainHeight + offset; - - p2.x = x2; - p2.y = y + fStep; - p2.z = terrain ? terrain->GetHeightFromFloats(p2.x, p2.y) + offset : defaultTerrainHeight + offset; - dc.DrawLine(p1, p2); - - fMinZ = min(fMinZ, min(p1.z, p2.z)); - fMaxZ = max(fMaxZ, max(p1.z, p2.z)); - } - for (float x = x1; x < x2; x += fStep) - { - p1.x = x; - p1.y = y1; - p1.z = terrain ? terrain->GetHeightFromFloats(p1.x, p1.y) + offset : defaultTerrainHeight + offset; - - p2.x = x + fStep; - p2.y = y1; - p2.z = terrain ? terrain->GetHeightFromFloats(p2.x, p2.y) + offset : defaultTerrainHeight + offset; - dc.DrawLine(p1, p2); - - p1.x = x; - p1.y = y2; - p1.z = terrain ? terrain->GetHeightFromFloats(p1.x, p1.y) + offset : defaultTerrainHeight + offset; - - p2.x = x + fStep; - p2.y = y2; - p2.z = terrain ? terrain->GetHeightFromFloats(p2.x, p2.y) + offset : defaultTerrainHeight + offset; - dc.DrawLine(p1, p2); - - fMinZ = min(fMinZ, min(p1.z, p2.z)); - fMaxZ = max(fMaxZ, max(p1.z, p2.z)); - } - - { - // Draw a box area - float fBoxOver = fMaxSide / 5.0f; - float fBoxHeight = fBoxOver + fMaxZ - fMinZ; - - ColorB boxColor(64, 64, 255, 128); // light blue - ColorB transparent(boxColor.r, boxColor.g, boxColor.b, 0); - - Vec3 base[] = { - Vec3(x1, y1, fMinZ), - Vec3(x2, y1, fMinZ), - Vec3(x2, y2, fMinZ), - Vec3(x1, y2, fMinZ) - }; - - - // Generate vertices - static AABB boxPrev(AABB::RESET); - static std::vector verts; - static std::vector colors; - - if (!IsEquivalent(boxPrev, box)) - { - verts.resize(0); - colors.resize(0); - for (int i = 0; i < 4; ++i) - { - Vec3& p = base[i]; - - verts.push_back(p); - verts.push_back(Vec3(p.x, p.y, p.z + fBoxHeight)); - verts.push_back(Vec3(p.x, p.y, p.z + fBoxHeight + fBoxOver)); - - colors.push_back(boxColor); - colors.push_back(boxColor); - colors.push_back(transparent); - } - boxPrev = box; - } - - // Generate indices - const int numInds = 4 * 12; - static vtx_idx inds[numInds]; - static bool bNeedIndsInit = true; - if (bNeedIndsInit) - { - vtx_idx* pInds = &inds[0]; - - for (int i = 0; i < 4; ++i) - { - int over = 0; - if (i == 3) - { - over = -12; - } - - int ind = i * 3; - *pInds++ = ind; - *pInds++ = ind + 3 + over; - *pInds++ = ind + 1; - - *pInds++ = ind + 1; - *pInds++ = ind + 3 + over; - *pInds++ = ind + 4 + over; - - ind = i * 3 + 1; - *pInds++ = ind; - *pInds++ = ind + 3 + over; - *pInds++ = ind + 1; - - *pInds++ = ind + 1; - *pInds++ = ind + 3 + over; - *pInds++ = ind + 4 + over; - } - bNeedIndsInit = false; - } - - // Draw lines - for (int i = 0; i < 4; ++i) - { - Vec3& p = base[i]; - - dc.DrawLine(p, Vec3(p.x, p.y, p.z + fBoxHeight), ColorF(1, 1, 0, 1), ColorF(1, 1, 0, 1)); - dc.DrawLine(Vec3(p.x, p.y, p.z + fBoxHeight), Vec3(p.x, p.y, p.z + fBoxHeight + fBoxOver), ColorF(1, 1, 0, 1), ColorF(1, 1, 0, 0)); - } - - // Draw volume - dc.DepthWriteOff(); - dc.CullOff(); - dc.pRenderAuxGeom->DrawTriangles(&verts[0], verts.size(), &inds[0], numInds, &colors[0]); - dc.CullOn(); - dc.DepthWriteOn(); - } -} - -////////////////////////////////////////////////////////////////////////// -void CRenderViewport::ProcessKeys() -{ - FUNCTION_PROFILER(GetIEditor()->GetSystem(), PROFILE_EDITOR); - - if (m_PlayerControl || GetIEditor()->IsInGameMode() || !CheckRespondToInput() || m_freezeViewportInput) - { - return; - } - - //m_Camera.UpdateFrustum(); - Matrix34 m = GetViewTM(); - Vec3 ydir = m.GetColumn1().GetNormalized(); - Vec3 xdir = m.GetColumn0().GetNormalized(); - Vec3 zdir = m.GetColumn2().GetNormalized(); - - Vec3 pos = GetViewTM().GetTranslation(); - - float speedScale = AZStd::GetMin( - 60.0f * GetIEditor()->GetSystem()->GetITimer()->GetFrameTime(), 20.0f); - - speedScale *= GetCameraMoveSpeed(); - - // Use the global modifier keys instead of our keymap. It's more reliable. - const bool shiftPressed = QGuiApplication::queryKeyboardModifiers() & Qt::ShiftModifier; - const bool controlPressed = QGuiApplication::queryKeyboardModifiers() & Qt::ControlModifier; - - if (shiftPressed) - { - speedScale *= gSettings.cameraFastMoveSpeed; - } - - if (controlPressed) - { - return; - } - - bool bIsPressedSome = false; - - if (IsKeyDown(Qt::Key_Up) || IsKeyDown(Qt::Key_W)) - { - // move forward - bIsPressedSome = true; - pos = pos + (speedScale * m_moveSpeed * ydir); - } - - if (IsKeyDown(Qt::Key_Down) || IsKeyDown(Qt::Key_S)) - { - // move backward - bIsPressedSome = true; - pos = pos - (speedScale * m_moveSpeed * ydir); - } - - if (IsKeyDown(Qt::Key_Left) || IsKeyDown(Qt::Key_A)) - { - // move left - bIsPressedSome = true; - pos = pos - (speedScale * m_moveSpeed * xdir); - } - - if (IsKeyDown(Qt::Key_Right) || IsKeyDown(Qt::Key_D)) - { - // move right - bIsPressedSome = true; - pos = pos + (speedScale * m_moveSpeed * xdir); - } - - if (IsKeyDown(Qt::Key_E)) - { - // move Up - bIsPressedSome = true; - pos = pos + (speedScale * m_moveSpeed * zdir); - } - - if (IsKeyDown(Qt::Key_Q)) - { - // move down - bIsPressedSome = true; - pos = pos - (speedScale * m_moveSpeed * zdir); - } - - if (bIsPressedSome) - { - // Only change the keystate to pressed if it wasn't already marked in - // a previous frame. Otherwise, the undo/redo stack will be all off - // from what SetViewTM() does. - if (m_pressedKeyState == KeyPressedState::AllUp) - { - m_pressedKeyState = KeyPressedState::PressedThisFrame; - } - - m.SetTranslation(pos); - SetViewTM(m, true); - } - - bool mouseModifierKeysDown = ((QGuiApplication::mouseButtons() & (Qt::RightButton | Qt::MiddleButton)) != 0); - - if (!bIsPressedSome && !mouseModifierKeysDown) - { - m_pressedKeyState = KeyPressedState::AllUp; - } -} - -Vec3 CRenderViewport::WorldToView3D(const Vec3& wp, [[maybe_unused]] int nFlags) const -{ - AZ_Assert(m_cameraSetForWidgetRenderingCount > 0, - "WorldToView3D was called but viewport widget rendering was not set. PreWidgetRendering must be called before."); - - Vec3 out(0, 0, 0); - float x, y, z; - - m_renderer->ProjectToScreen(wp.x, wp.y, wp.z, &x, &y, &z); - if (_finite(x) && _finite(y) && _finite(z)) - { - out.x = (x / 100) * m_rcClient.width(); - out.y = (y / 100) * m_rcClient.height(); - out.x /= QHighDpiScaling::factor(windowHandle()->screen()); - out.y /= QHighDpiScaling::factor(windowHandle()->screen()); - out.z = z; - } - return out; -} - -////////////////////////////////////////////////////////////////////////// -QPoint CRenderViewport::WorldToView(const Vec3& wp) const -{ - AZ_Assert(m_cameraSetForWidgetRenderingCount > 0, - "WorldToView was called but viewport widget rendering was not set. PreWidgetRendering must be called before."); - - QPoint p; - float x, y, z; - - m_renderer->ProjectToScreen(wp.x, wp.y, wp.z, &x, &y, &z); - if (_finite(x) || _finite(y)) - { - p.rx() = (x / 100) * m_rcClient.width(); - p.ry() = (y / 100) * m_rcClient.height(); - } - else - { - QPoint(0, 0); - } - - return p; -} -////////////////////////////////////////////////////////////////////////// -QPoint CRenderViewport::WorldToViewParticleEditor(const Vec3& wp, int width, int height) const -{ - QPoint p; - float x, y, z; - - m_renderer->ProjectToScreen(wp.x, wp.y, wp.z, &x, &y, &z); - if (_finite(x) || _finite(y)) - { - p.rx() = (x / 100) * width; - p.ry() = (y / 100) * height; - } - else - { - QPoint(0, 0); - } - return p; -} - -////////////////////////////////////////////////////////////////////////// -Vec3 CRenderViewport::ViewToWorld(const QPoint& vp, bool* collideWithTerrain, bool onlyTerrain, bool bSkipVegetation, bool bTestRenderMesh, bool* collideWithObject) const -{ - AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::Editor); - - // Make sure we initialize the value if a pointer has been passed in - if (collideWithTerrain != nullptr) - { - *collideWithTerrain = false; - } - - // Make sure we initialize the value if a pointer has been passed in - if (collideWithObject != nullptr) -{ - *collideWithObject = false; - } - - if (!m_renderer) - { - return Vec3(0, 0, 0); - } - - QRect rc = m_rcClient; - - Vec3 pos0; - if (!m_Camera.Unproject(Vec3(vp.x(), rc.bottom() - vp.y(), 0), pos0)) - { - return Vec3(0, 0, 0); - } - if (!IsVectorInValidRange(pos0)) - { - pos0.Set(0, 0, 0); - } - - Vec3 pos1; - if (!m_Camera.Unproject(Vec3(vp.x(), rc.bottom() - vp.y(), 1), pos1)) - { - return Vec3(0, 0, 0); - } - if (!IsVectorInValidRange(pos1)) - { - pos1.Set(1, 0, 0); - } - - const float maxDistance = 10000.f; - - Vec3 v = (pos1 - pos0); - v = v.GetNormalized(); - v = v * maxDistance; - - if (!_finite(v.x) || !_finite(v.y) || !_finite(v.z)) - { - return Vec3(0, 0, 0); - } - - Vec3 colp = pos0 + 0.002f * v; - - AZ_UNUSED(vp) - AZ_UNUSED(bTestRenderMesh) - AZ_UNUSED(bSkipVegetation) - AZ_UNUSED(bSkipVegetation) - AZStd::optional> hitDistancePosition; - - if (!onlyTerrain && !GetIEditor()->IsTerrainAxisIgnoreObjects()) - { - AzFramework::EntityContextId editorContextId; - AzToolsFramework::EditorEntityContextRequestBus::BroadcastResult( - editorContextId, &AzToolsFramework::EditorEntityContextRequests::GetEditorEntityContextId); - - AzFramework::RenderGeometry::RayRequest ray; - ray.m_startWorldPosition = LYVec3ToAZVec3(pos0); - ray.m_endWorldPosition = LYVec3ToAZVec3(pos0 + v); - ray.m_onlyVisible = true; - - AzFramework::RenderGeometry::RayResult result; - AzFramework::RenderGeometry::IntersectorBus::EventResult(result, editorContextId, - &AzFramework::RenderGeometry::IntersectorInterface::RayIntersect, ray); - - if (result) - { - if (!hitDistancePosition || result.m_distance < hitDistancePosition->first) - { - hitDistancePosition = {result.m_distance, result.m_worldPosition}; - if (collideWithObject) - { - *collideWithObject = true; - } - } - } - } - - if (hitDistancePosition) - { - colp = AZVec3ToLYVec3(hitDistancePosition->second); - } - - - return colp; -} - -////////////////////////////////////////////////////////////////////////// -Vec3 CRenderViewport::ViewToWorldNormal(const QPoint& vp, bool onlyTerrain, bool bTestRenderMesh) -{ - AZ_UNUSED(vp) - AZ_UNUSED(bTestRenderMesh) - - AZ_Assert(m_cameraSetForWidgetRenderingCount > 0, - "ViewToWorldNormal was called but viewport widget rendering was not set. PreWidgetRendering must be called before."); - - AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::Editor); - - if (!m_renderer) - { - return Vec3(0, 0, 1); - } - - QRect rc = m_rcClient; - - Vec3 pos0, pos1; - float wx, wy, wz; - m_renderer->UnProjectFromScreen(vp.x(), rc.bottom() - vp.y(), 0, &wx, &wy, &wz); - if (!_finite(wx) || !_finite(wy) || !_finite(wz)) - { - return Vec3(0, 0, 1); - } - pos0(wx, wy, wz); - if (!IsVectorInValidRange(pos0)) - { - pos0.Set(0, 0, 0); - } - - m_renderer->UnProjectFromScreen(vp.x(), rc.bottom() - vp.y(), 1, &wx, &wy, &wz); - if (!_finite(wx) || !_finite(wy) || !_finite(wz)) - { - return Vec3(0, 0, 1); - } - pos1(wx, wy, wz); - - Vec3 v = (pos1 - pos0); - if (!IsVectorInValidRange(pos1)) - { - pos1.Set(1, 0, 0); - } - - const float maxDistance = 2000.f; - v = v.GetNormalized(); - v = v * maxDistance; - - if (!_finite(v.x) || !_finite(v.y) || !_finite(v.z)) - { - return Vec3(0, 0, 1); - } - - Vec3 colp(0, 0, 0); - - - AZStd::optional> hitDistanceNormal; - - if (!onlyTerrain && !GetIEditor()->IsTerrainAxisIgnoreObjects()) - { - AzFramework::EntityContextId editorContextId; - AzToolsFramework::EditorEntityContextRequestBus::BroadcastResult( - editorContextId, &AzToolsFramework::EditorEntityContextRequests::GetEditorEntityContextId); - - AzFramework::RenderGeometry::RayRequest ray; - ray.m_startWorldPosition = LYVec3ToAZVec3(pos0); - ray.m_endWorldPosition = LYVec3ToAZVec3(pos0 + v); - ray.m_onlyVisible = true; - - AzFramework::RenderGeometry::RayResult result; - AzFramework::RenderGeometry::IntersectorBus::EventResult(result, editorContextId, - &AzFramework::RenderGeometry::IntersectorInterface::RayIntersect, ray); - - if (result) - { - if (!hitDistanceNormal || result.m_distance < hitDistanceNormal->first) - { - hitDistanceNormal = { result.m_distance, result.m_worldNormal }; - } - } - } - - return hitDistanceNormal ? AZVec3ToLYVec3(hitDistanceNormal->second) : Vec3(0, 0, 1); -} - -////////////////////////////////////////////////////////////////////////// -bool CRenderViewport::AdjustObjectPosition(const ray_hit& hit, Vec3& outNormal, Vec3& outPos) const -{ - Matrix34A objMat, objMatInv; - Matrix33 objRot, objRotInv; - - if (hit.pCollider->GetiForeignData() != PHYS_FOREIGN_ID_STATIC) - { - return false; - } - - IRenderNode* pNode = (IRenderNode*) hit.pCollider->GetForeignData(PHYS_FOREIGN_ID_STATIC); - if (!pNode || !pNode->GetEntityStatObj()) - { - return false; - } - - IStatObj* pEntObject = pNode->GetEntityStatObj(hit.partid, 0, &objMat, false); - if (!pEntObject || !pEntObject->GetRenderMesh()) - { - return false; - } - - objRot = Matrix33(objMat); - objRot.NoScale(); // No scale. - objRotInv = objRot; - objRotInv.Invert(); - - float fWorldScale = objMat.GetColumn(0).GetLength(); // GetScale - float fWorldScaleInv = 1.0f / fWorldScale; - - // transform decal into object space - objMatInv = objMat; - objMatInv.Invert(); - - // put into normal object space hit direction of projection - Vec3 invhitn = -(hit.n); - Vec3 vOS_HitDir = objRotInv.TransformVector(invhitn).GetNormalized(); - - // put into position object space hit position - Vec3 vOS_HitPos = objMatInv.TransformPoint(hit.pt); - vOS_HitPos -= vOS_HitDir * RENDER_MESH_TEST_DISTANCE * fWorldScaleInv; - - IRenderMesh* pRM = pEntObject->GetRenderMesh(); - - AABB aabbRNode; - pRM->GetBBox(aabbRNode.min, aabbRNode.max); - Vec3 vOut(0, 0, 0); - if (!Intersect::Ray_AABB(Ray(vOS_HitPos, vOS_HitDir), aabbRNode, vOut)) - { - return false; - } - - if (!pRM || !pRM->GetVerticesCount()) - { - return false; - } - - if (RayRenderMeshIntersection(pRM, vOS_HitPos, vOS_HitDir, outPos, outNormal)) - { - outNormal = objRot.TransformVector(outNormal).GetNormalized(); - outPos = objMat.TransformPoint(outPos); - return true; - } - return false; -} - -////////////////////////////////////////////////////////////////////////// -bool CRenderViewport::RayRenderMeshIntersection(IRenderMesh*, const Vec3&, const Vec3&, Vec3&, Vec3&) const -{ - return false; -} - -////////////////////////////////////////////////////////////////////////// -void CRenderViewport::ViewToWorldRay(const QPoint& vp, Vec3& raySrc, Vec3& rayDir) const -{ - AZ_Assert(m_cameraSetForWidgetRenderingCount > 0, - "ViewToWorldRay was called but SScopedCurrentContext was not set at a higher scope! This means the camera for this call is incorrect."); - - if (!m_renderer) - { - return; - } - - QRect rc = m_rcClient; - - Vec3 pos0, pos1; - float wx, wy, wz; - m_renderer->UnProjectFromScreen(vp.x(), rc.bottom() - vp.y(), 0, &wx, &wy, &wz); - if (!_finite(wx) || !_finite(wy) || !_finite(wz)) - { - return; - } - if (fabs(wx) > 1000000 || fabs(wy) > 1000000 || fabs(wz) > 1000000) - { - return; - } - pos0(wx, wy, wz); - m_renderer->UnProjectFromScreen(vp.x(), rc.bottom() - vp.y(), 1, &wx, &wy, &wz); - if (!_finite(wx) || !_finite(wy) || !_finite(wz)) - { - return; - } - if (fabs(wx) > 1000000 || fabs(wy) > 1000000 || fabs(wz) > 1000000) - { - return; - } - pos1(wx, wy, wz); - - Vec3 v = (pos1 - pos0); - v = v.GetNormalized(); - - raySrc = pos0; - rayDir = v; -} - -////////////////////////////////////////////////////////////////////////// -float CRenderViewport::GetScreenScaleFactor(const Vec3& worldPoint) const -{ - float dist = m_Camera.GetPosition().GetDistance(worldPoint); - if (dist < m_Camera.GetNearPlane()) - { - dist = m_Camera.GetNearPlane(); - } - return dist; -} -////////////////////////////////////////////////////////////////////////// -float CRenderViewport::GetScreenScaleFactor(const CCamera& camera, const Vec3& object_position) -{ - Vec3 camPos = camera.GetPosition(); - float dist = camPos.GetDistance(object_position); - return dist; -} - -////////////////////////////////////////////////////////////////////////// -void CRenderViewport::OnDestroy() -{ - DestroyRenderContext(); -} - -////////////////////////////////////////////////////////////////////////// -bool CRenderViewport::CheckRespondToInput() const -{ - if (!Editor::EditorQtApplication::IsActive()) - { - return false; - } - - if (!hasFocus()) - { - return false; - } - - return true; -} - -////////////////////////////////////////////////////////////////////////// -bool CRenderViewport::HitTest(const QPoint& point, HitContext& hitInfo) -{ - hitInfo.camera = &m_Camera; - hitInfo.pExcludedObject = GetCameraObject(); - return QtViewport::HitTest(point, hitInfo); -} - -////////////////////////////////////////////////////////////////////////// -bool CRenderViewport::IsBoundsVisible(const AABB& box) const -{ - // If at least part of bbox is visible then its visible. - return m_Camera.IsAABBVisible_F(AABB(box.min, box.max)); -} - -////////////////////////////////////////////////////////////////////////// -void CRenderViewport::CenterOnSelection() -{ - if (!GetIEditor()->GetSelection()->IsEmpty()) - { - // Get selection bounds & center - CSelectionGroup* sel = GetIEditor()->GetSelection(); - AABB selectionBounds = sel->GetBounds(); - CenterOnAABB(selectionBounds); - } -} - -void CRenderViewport::CenterOnAABB(const AABB& aabb) -{ - Vec3 selectionCenter = aabb.GetCenter(); - - // Minimum center size is 40cm - const float minSelectionRadius = 0.4f; - const float selectionSize = std::max(minSelectionRadius, aabb.GetRadius()); - - // Move camera 25% further back than required - const float centerScale = 1.25f; - - // Decompose original transform matrix - const Matrix34& originalTM = GetViewTM(); - AffineParts affineParts; - affineParts.SpectralDecompose(originalTM); - - // Forward vector is y component of rotation matrix - Matrix33 rotationMatrix(affineParts.rot); - const Vec3 viewDirection = rotationMatrix.GetColumn1().GetNormalized(); - - // Compute adjustment required by FOV != 90 degrees - const float fov = GetFOV(); - const float fovScale = (1.0f / tan(fov * 0.5f)); - - // Compute new transform matrix - const float distanceToTarget = selectionSize * fovScale * centerScale; - const Vec3 newPosition = selectionCenter - (viewDirection * distanceToTarget); - Matrix34 newTM = Matrix34(rotationMatrix, newPosition); - - // Set new orbit distance - m_orbitDistance = distanceToTarget; - m_orbitDistance = fabs(m_orbitDistance); - - SetViewTM(newTM); -} - -void CRenderViewport::CenterOnSliceInstance() -{ - AzToolsFramework::EntityIdList selectedEntityList; - AzToolsFramework::ToolsApplicationRequestBus::BroadcastResult(selectedEntityList, &AzToolsFramework::ToolsApplicationRequests::GetSelectedEntities); - - AZ::SliceComponent::SliceInstanceAddress sliceAddress; - AzToolsFramework::ToolsApplicationRequestBus::BroadcastResult(sliceAddress, - &AzToolsFramework::ToolsApplicationRequestBus::Events::FindCommonSliceInstanceAddress, selectedEntityList); - - if (!sliceAddress.IsValid()) - { - return; - } - - AZ::EntityId sliceRootEntityId; - AzToolsFramework::ToolsApplicationRequestBus::BroadcastResult(sliceRootEntityId, - &AzToolsFramework::ToolsApplicationRequestBus::Events::GetRootEntityIdOfSliceInstance, sliceAddress); - - if (!sliceRootEntityId.IsValid()) - { - return; - } - - AzToolsFramework::ToolsApplicationRequestBus::Broadcast( - &AzToolsFramework::ToolsApplicationRequestBus::Events::SetSelectedEntities, AzToolsFramework::EntityIdList{sliceRootEntityId}); - - const AZ::SliceComponent::InstantiatedContainer* instantiatedContainer = sliceAddress.GetInstance()->GetInstantiated(); - - AABB aabb(Vec3(std::numeric_limits::max()), Vec3(-std::numeric_limits::max())); - for (AZ::Entity* entity : instantiatedContainer->m_entities) - { - CEntityObject* entityObject = nullptr; - AzToolsFramework::ComponentEntityEditorRequestBus::EventResult(entityObject, entity->GetId(), - &AzToolsFramework::ComponentEntityEditorRequestBus::Events::GetSandboxObject); - AABB box; - entityObject->GetBoundBox(box); - aabb.Add(box.min); - aabb.Add(box.max); - } - CenterOnAABB(aabb); -} - -////////////////////////////////////////////////////////////////////////// -void CRenderViewport::SetFOV(float fov) -{ - if (m_pCameraFOVVariable) - { - m_pCameraFOVVariable->Set(fov); - } - else - { - m_camFOV = fov; - } - - if (m_viewPane) - { - m_viewPane->OnFOVChanged(fov); - } -} - -////////////////////////////////////////////////////////////////////////// -float CRenderViewport::GetFOV() const -{ - if (m_viewSourceType == ViewSourceType::SequenceCamera) - { - CBaseObject* cameraObject = GetCameraObject(); - - AZ::EntityId cameraEntityId; - AzToolsFramework::ComponentEntityObjectRequestBus::EventResult(cameraEntityId, cameraObject, &AzToolsFramework::ComponentEntityObjectRequestBus::Events::GetAssociatedEntityId); - if (cameraEntityId.IsValid()) - { - // component Camera - float fov = DEFAULT_FOV; - Camera::CameraRequestBus::EventResult(fov, cameraEntityId, &Camera::CameraComponentRequests::GetFov); - return AZ::DegToRad(fov); - } - } - - if (m_pCameraFOVVariable) - { - float fov; - m_pCameraFOVVariable->Get(fov); - return fov; - } - else if (m_viewEntityId.IsValid()) - { - float fov = AZ::RadToDeg(m_camFOV); - Camera::CameraRequestBus::EventResult(fov, m_viewEntityId, &Camera::CameraComponentRequests::GetFov); - return AZ::DegToRad(fov); - } - - return m_camFOV; -} - -////////////////////////////////////////////////////////////////////////// -bool CRenderViewport::CreateRenderContext() -{ - // Create context. - if (m_renderer && !m_bRenderContextCreated) - { - m_bRenderContextCreated = true; - - AzFramework::WindowRequestBus::Handler::BusConnect(renderOverlayHWND()); - AzFramework::WindowSystemNotificationBus::Broadcast(&AzFramework::WindowSystemNotificationBus::Handler::OnWindowCreated, renderOverlayHWND()); - - WIN_HWND oldContext = m_renderer->GetCurrentContextHWND(); - m_renderer->CreateContext(renderOverlayHWND()); - m_renderer->SetCurrentContext(oldContext); // restore prior context - return true; - } - return false; -} - -////////////////////////////////////////////////////////////////////////// -void CRenderViewport::DestroyRenderContext() -{ - // Destroy render context. - if (m_renderer && m_bRenderContextCreated) - { - // Do not delete primary context. - if (m_hwnd != m_renderer->GetHWND()) - { - m_renderer->DeleteContext(m_hwnd); - } - m_bRenderContextCreated = false; - } -} - -////////////////////////////////////////////////////////////////////////// -void CRenderViewport::SetDefaultCamera() -{ - if (IsDefaultCamera()) - { - return; - } - ResetToViewSourceType(ViewSourceType::None); - GetViewManager()->SetCameraObjectId(m_cameraObjectId); - SetName(m_defaultViewName); - SetViewTM(m_defaultViewTM); - PostCameraSet(); -} - -////////////////////////////////////////////////////////////////////////// -bool CRenderViewport::IsDefaultCamera() const -{ - return m_viewSourceType == ViewSourceType::None; -} - -////////////////////////////////////////////////////////////////////////// -void CRenderViewport::SetSequenceCamera() -{ - if (m_viewSourceType == ViewSourceType::SequenceCamera) - { - // Reset if we were checked before - SetDefaultCamera(); - } - else - { - ResetToViewSourceType(ViewSourceType::SequenceCamera); - - SetName(tr("Sequence Camera")); - SetViewTM(GetViewTM()); - - GetViewManager()->SetCameraObjectId(m_cameraObjectId); - PostCameraSet(); - - // ForceAnimation() so Track View will set the Camera params - // if a camera is animated in the sequences. - if (GetIEditor() && GetIEditor()->GetAnimation()) - { - GetIEditor()->GetAnimation()->ForceAnimation(); - } -} -} - -////////////////////////////////////////////////////////////////////////// -void CRenderViewport::SetComponentCamera(const AZ::EntityId& entityId) -{ - ResetToViewSourceType(ViewSourceType::CameraComponent); - SetViewEntity(entityId); -} - -////////////////////////////////////////////////////////////////////////// -void CRenderViewport::SetEntityAsCamera(const AZ::EntityId& entityId, bool lockCameraMovement) -{ - ResetToViewSourceType(ViewSourceType::AZ_Entity); - SetViewEntity(entityId, lockCameraMovement); -} - -void CRenderViewport::SetFirstComponentCamera() -{ - AZ::EBusAggregateResults results; - Camera::CameraBus::BroadcastResult(results, &Camera::CameraRequests::GetCameras); - AZStd::sort_heap(results.values.begin(), results.values.end()); - AZ::EntityId entityId; - if (results.values.size() > 0) - { - entityId = results.values[0]; - } - SetComponentCamera(entityId); -} - -////////////////////////////////////////////////////////////////////////// -void CRenderViewport::SetSelectedCamera() -{ - AZ::EBusAggregateResults cameraList; - Camera::CameraBus::BroadcastResult(cameraList, &Camera::CameraRequests::GetCameras); - if (cameraList.values.size() > 0) - { - AzToolsFramework::EntityIdList selectedEntityList; - AzToolsFramework::ToolsApplicationRequests::Bus::BroadcastResult(selectedEntityList, &AzToolsFramework::ToolsApplicationRequests::GetSelectedEntities); - for (const AZ::EntityId& entityId : selectedEntityList) - { - if (AZStd::find(cameraList.values.begin(), cameraList.values.end(), entityId) != cameraList.values.end()) - { - SetComponentCamera(entityId); - } - } - } -} - -////////////////////////////////////////////////////////////////////////// -bool CRenderViewport::IsSelectedCamera() const -{ - CBaseObject* pCameraObject = GetCameraObject(); - if (pCameraObject && pCameraObject == GetIEditor()->GetSelectedObject()) - { - return true; - } - - AzToolsFramework::EntityIdList selectedEntityList; - AzToolsFramework::ToolsApplicationRequests::Bus::BroadcastResult( - selectedEntityList, &AzToolsFramework::ToolsApplicationRequests::GetSelectedEntities); - - if ((m_viewSourceType == ViewSourceType::CameraComponent || m_viewSourceType == ViewSourceType::AZ_Entity) - && !selectedEntityList.empty() - && AZStd::find(selectedEntityList.begin(), selectedEntityList.end(), m_viewEntityId) != selectedEntityList.end()) - { - return true; - } - - return false; -} - -////////////////////////////////////////////////////////////////////////// -void CRenderViewport::CycleCamera() -{ - // None -> Sequence -> LegacyCamera -> ... LegacyCamera -> CameraComponent -> ... CameraComponent -> None - // AZ_Entity has been intentionally left out of the cycle for now. - switch (m_viewSourceType) - { - case CRenderViewport::ViewSourceType::None: - { - SetFirstComponentCamera(); - break; - } - case CRenderViewport::ViewSourceType::SequenceCamera: - { - AZ_Error("CRenderViewport", false, "Legacy cameras no longer exist, unable to set sequence camera."); - break; - } - case CRenderViewport::ViewSourceType::LegacyCamera: - { - AZ_Warning("CRenderViewport", false, "Legacy cameras no longer exist, using first found component camera instead."); - SetFirstComponentCamera(); - break; - } - case CRenderViewport::ViewSourceType::CameraComponent: - { - AZ::EBusAggregateResults results; - Camera::CameraBus::BroadcastResult(results, &Camera::CameraRequests::GetCameras); - AZStd::sort_heap(results.values.begin(), results.values.end()); - auto&& currentCameraIterator = AZStd::find(results.values.begin(), results.values.end(), m_viewEntityId); - if (currentCameraIterator != results.values.end()) - { - ++currentCameraIterator; - if (currentCameraIterator != results.values.end()) - { - SetComponentCamera(*currentCameraIterator); - break; - } - } - SetDefaultCamera(); - break; - } - case CRenderViewport::ViewSourceType::AZ_Entity: - { - // we may decide to have this iterate over just selected entities - SetDefaultCamera(); - break; - } - default: - { - SetDefaultCamera(); - break; - } - } -} - -void CRenderViewport::SetViewFromEntityPerspective(const AZ::EntityId& entityId) -{ - SetViewAndMovementLockFromEntityPerspective(entityId, false); -} - -void CRenderViewport::SetViewAndMovementLockFromEntityPerspective(const AZ::EntityId& entityId, bool lockCameraMovement) -{ - if (!m_ignoreSetViewFromEntityPerspective) - { - SetEntityAsCamera(entityId, lockCameraMovement); - } -} - -bool CRenderViewport::GetActiveCameraPosition(AZ::Vector3& cameraPos) -{ - cameraPos = LYVec3ToAZVec3(m_viewTM.GetTranslation()); - return true; -} - -bool CRenderViewport::GetActiveCameraState(AzFramework::CameraState& cameraState) -{ - if (m_pPrimaryViewport == this) - { - if (GetIEditor()->IsInGameMode()) - { - return false; - } - else - { - const auto& camera = GetCamera(); - cameraState = CameraStateFromCCamera(camera, GetFOV(), m_rcClient.width(), m_rcClient.height()); - } - - return true; - } - - return false; -} - -void CRenderViewport::OnStartPlayInEditor() -{ - if (m_viewEntityId.IsValid()) - { - m_viewEntityIdCachedForEditMode = m_viewEntityId; - AZ::EntityId runtimeEntityId; - AzToolsFramework::EditorEntityContextRequestBus::Broadcast( - &AzToolsFramework::EditorEntityContextRequestBus::Events::MapEditorIdToRuntimeId, - m_viewEntityId, runtimeEntityId); - - m_viewEntityId = runtimeEntityId; - } - // Force focus the render viewport, otherwise we don't receive keyPressEvents until the user first clicks a - // mouse button. See also CRenderViewport::mousePressEvent for a deatiled description of the underlying bug. - // We need to queue this up because we don't actually lose focus until sometime after this function returns. - QTimer::singleShot(0, this, &CRenderViewport::ActivateWindowAndSetFocus); -} - -void CRenderViewport::OnStopPlayInEditor() -{ - if (m_viewEntityIdCachedForEditMode.IsValid()) - { - m_viewEntityId = m_viewEntityIdCachedForEditMode; - m_viewEntityIdCachedForEditMode.SetInvalid(); - } -} - -void CRenderViewport::ActivateWindowAndSetFocus() -{ - window()->activateWindow(); - setFocus(); -} - -////////////////////////////////////////////////////////////////////////// -void CRenderViewport::RenderConstructionPlane() -{ - // noop -} - -////////////////////////////////////////////////////////////////////////// -void CRenderViewport::RenderSnappingGrid() -{ - // noop -} - -////////////////////////////////////////////////////////////////////////// -CRenderViewport::SPreviousContext CRenderViewport::SetCurrentContext(int newWidth, int newHeight) const -{ - SPreviousContext x; - x.window = reinterpret_cast(m_renderer->GetCurrentContextHWND()); - x.mainViewport = m_renderer->IsCurrentContextMainVP(); - x.width = m_renderer->GetCurrentContextViewportWidth(); - x.height = m_renderer->GetCurrentContextViewportHeight(); - x.rendererCamera = m_renderer->GetCamera(); - - const float scale = CLAMP(gEnv->pConsole->GetCVar("r_ResolutionScale")->GetFVal(), MIN_RESOLUTION_SCALE, MAX_RESOLUTION_SCALE); - const QSize newSize = WidgetToViewport(QSize(newWidth, newHeight)) * scale; - - // No way to query the requested Qt scale here, so do it this way for now - float widthScale = aznumeric_cast(newSize.width()) / aznumeric_cast(newWidth); - float heightScale = aznumeric_cast(newSize.height()) / aznumeric_cast(newHeight); - - m_renderer->SetCurrentContext(renderOverlayHWND()); - m_renderer->ChangeViewport(0, 0, newWidth, newHeight, true, widthScale, heightScale); - m_renderer->SetCamera(m_Camera); - - return x; -} - -////////////////////////////////////////////////////////////////////////// -CRenderViewport::SPreviousContext CRenderViewport::SetCurrentContext() const -{ - const auto r = rect(); - return SetCurrentContext(r.width(), r.height()); -} - -////////////////////////////////////////////////////////////////////////// -void CRenderViewport::RestorePreviousContext(const SPreviousContext& x) const -{ - if (x.window && x.window != m_renderer->GetCurrentContextHWND()) - { - m_renderer->SetCurrentContext(x.window); - m_renderer->ChangeViewport(0, 0, x.width, x.height, x.mainViewport); - m_renderer->SetCamera(x.rendererCamera); - } -} - -void CRenderViewport::PreWidgetRendering() -{ - // if we have not already set the render context for the viewport, do it now - // based on the current state of the renderer/viewport, record the previous - // context to restore afterwards - if (m_cameraSetForWidgetRenderingCount == 0) - { - m_preWidgetContext = SetCurrentContext(); - } - - // keep track of how many times we've attempted to update the context - m_cameraSetForWidgetRenderingCount++; -} - -void CRenderViewport::PostWidgetRendering() -{ - if (m_cameraSetForWidgetRenderingCount > 0) - { - m_cameraSetForWidgetRenderingCount--; - - // unwinding - when the viewport context is no longer required, - // restore the previous context when widget rendering first began - if (m_cameraSetForWidgetRenderingCount == 0) - { - RestorePreviousContext(m_preWidgetContext); - } - } -} - -////////////////////////////////////////////////////////////////////////// -void CRenderViewport::OnCameraFOVVariableChanged([[maybe_unused]] IVariable* var) -{ - if (m_viewPane) - { - m_viewPane->OnFOVChanged(GetFOV()); - } -} - -////////////////////////////////////////////////////////////////////////// -void CRenderViewport::HideCursor() -{ - if (m_bCursorHidden || !gSettings.viewports.bHideMouseCursorWhenCaptured) - { - return; - } - - qApp->setOverrideCursor(Qt::BlankCursor); -#if AZ_TRAIT_OS_PLATFORM_APPLE - StartFixedCursorMode(this); -#endif - m_bCursorHidden = true; -} - -////////////////////////////////////////////////////////////////////////// -void CRenderViewport::ShowCursor() -{ - if (!m_bCursorHidden || !gSettings.viewports.bHideMouseCursorWhenCaptured) - { - return; - } - -#if AZ_TRAIT_OS_PLATFORM_APPLE - StopFixedCursorMode(); -#endif - qApp->restoreOverrideCursor(); - m_bCursorHidden = false; -} - -bool CRenderViewport::IsKeyDown(Qt::Key key) const -{ - return m_keyDown.contains(key); -} - -////////////////////////////////////////////////////////////////////////// -void CRenderViewport::PushDisableRendering() -{ - assert(m_disableRenderingCount >= 0); - ++m_disableRenderingCount; -} - -////////////////////////////////////////////////////////////////////////// -void CRenderViewport::PopDisableRendering() -{ - assert(m_disableRenderingCount >= 1); - --m_disableRenderingCount; -} - -////////////////////////////////////////////////////////////////////////// -bool CRenderViewport::IsRenderingDisabled() const -{ - return m_disableRenderingCount > 0; -} - -////////////////////////////////////////////////////////////////////////// -QPoint CRenderViewport::WidgetToViewport(const QPoint &point) const -{ - return point * WidgetToViewportFactor(); -} - -QPoint CRenderViewport::ViewportToWidget(const QPoint &point) const -{ - return point / WidgetToViewportFactor(); -} - -////////////////////////////////////////////////////////////////////////// -QSize CRenderViewport::WidgetToViewport(const QSize &size) const -{ - return size * WidgetToViewportFactor(); -} - -////////////////////////////////////////////////////////////////////////// -void CRenderViewport::BeginUndoTransaction() -{ - PushDisableRendering(); -} - -////////////////////////////////////////////////////////////////////////// -void CRenderViewport::EndUndoTransaction() -{ - PopDisableRendering(); - Update(); -} - -void CRenderViewport::UpdateCurrentMousePos(const QPoint& newPosition) -{ - m_prevMousePos = m_mousePos; - m_mousePos = newPosition; -} - -void CRenderViewport::BuildDragDropContext(AzQtComponents::ViewportDragContext& context, const QPoint& pt) -{ - const auto scaledPoint = WidgetToViewport(pt); - QtViewport::BuildDragDropContext(context, scaledPoint); -} - -void* CRenderViewport::GetSystemCursorConstraintWindow() const -{ - AzFramework::SystemCursorState systemCursorState = AzFramework::SystemCursorState::Unknown; - - AzFramework::InputSystemCursorRequestBus::EventResult( - systemCursorState, - AzFramework::InputDeviceMouse::Id, - &AzFramework::InputSystemCursorRequests::GetSystemCursorState); - - const bool systemCursorConstrained = - (systemCursorState == AzFramework::SystemCursorState::ConstrainedAndHidden || - systemCursorState == AzFramework::SystemCursorState::ConstrainedAndVisible); - - return systemCursorConstrained ? renderOverlayHWND() : nullptr; -} - -void CRenderViewport::RestoreViewportAfterGameMode() -{ - Matrix34 preGameModeViewTM = m_preGameModeViewTM; - - QString text = - QString( - tr("When leaving \" Game Mode \" the engine will automatically restore your camera position to the default position before you " - "had entered Game mode.

If you dislike this setting you can always change this anytime in the global " - "preferences.

")) - .arg(EditorPreferencesGeneralRestoreViewportCameraSettingName); - QString restoreOnExitGameModePopupDisabledRegKey("Editor/AutoHide/ViewportCameraRestoreOnExitGameMode"); - - // Read the popup disabled registry value - QSettings settings; - QVariant restoreOnExitGameModePopupDisabledRegValue = settings.value(restoreOnExitGameModePopupDisabledRegKey); - - // Has the user previously disabled being asked about restoring the camera on exiting game mode? - if (restoreOnExitGameModePopupDisabledRegValue.isNull()) - { - // No, ask them now - QMessageBox messageBox(QMessageBox::Question, "O3DE", text, QMessageBox::StandardButtons(QMessageBox::No | QMessageBox::Yes), this); - messageBox.setDefaultButton(QMessageBox::Yes); - - QCheckBox* checkBox = new QCheckBox(QStringLiteral("Do not show this message again")); - checkBox->setChecked(true); - messageBox.setCheckBox(checkBox); - - // Unconstrain the system cursor and make it visible before we show the dialog box, otherwise the user can't see the cursor. - AzFramework::InputSystemCursorRequestBus::Event(AzFramework::InputDeviceMouse::Id, - &AzFramework::InputSystemCursorRequests::SetSystemCursorState, - AzFramework::SystemCursorState::UnconstrainedAndVisible); - - int response = messageBox.exec(); - - if (checkBox->isChecked()) - { - settings.setValue(restoreOnExitGameModePopupDisabledRegKey, response); - } - - // Update the value only if the popup hasn't previously been disabled and the value has changed - bool newSetting = (response == QMessageBox::Yes); - if (newSetting != GetIEditor()->GetEditorSettings()->restoreViewportCamera) - { - GetIEditor()->GetEditorSettings()->restoreViewportCamera = newSetting; - GetIEditor()->GetEditorSettings()->Save(); - } - } - - bool restoreViewportCamera = GetIEditor()->GetEditorSettings()->restoreViewportCamera; - if (restoreViewportCamera) - { - SetViewTM(preGameModeViewTM); - } - else - { - SetViewTM(m_gameTM); - } -} - -#include diff --git a/Code/Editor/RenderViewport.h b/Code/Editor/RenderViewport.h index c66d56176e..8f5e19f93d 100644 --- a/Code/Editor/RenderViewport.h +++ b/Code/Editor/RenderViewport.h @@ -51,599 +51,4 @@ namespace AzToolsFramework class ManipulatorManager; } -// CRenderViewport window -AZ_PUSH_DISABLE_DLL_EXPORT_BASECLASS_WARNING -AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING -class SANDBOX_API CRenderViewport - : public QtViewport - , public IEditorNotifyListener - , public IUndoManagerListener - , public Camera::EditorCameraRequestBus::Handler - , public AzFramework::InputSystemCursorConstraintRequestBus::Handler - , public AzToolsFramework::ViewportInteraction::ViewportFreezeRequestBus::Handler - , public AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::Handler - , public AzToolsFramework::ViewportInteraction::MainEditorViewportInteractionRequestBus::Handler - , public AzFramework::WindowRequestBus::Handler -{ -AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING -AZ_POP_DISABLE_DLL_EXPORT_BASECLASS_WARNING - Q_OBJECT -public: - struct SResolution - { - SResolution() - : width(0) - , height(0) - { - } - - SResolution(int w, int h) - : width(w) - , height(h) - { - } - - int width; - int height; - }; - -public: - CRenderViewport(const QString& name, QWidget* parent = nullptr); - - static const GUID& GetClassID() - { - return QtViewport::GetClassID(); - } - - /** Get type of this viewport. - */ - virtual EViewportType GetType() const { return ET_ViewportCamera; } - virtual void SetType([[maybe_unused]] EViewportType type) { assert(type == ET_ViewportCamera); }; - - // Implementation -public: - virtual ~CRenderViewport(); - - Q_INVOKABLE void InjectFakeMouseMove(int deltaX, int deltaY, Qt::MouseButtons buttons); - -public: - virtual void Update(); - - virtual void ResetContent(); - virtual void UpdateContent(int flags); - - void OnTitleMenu(QMenu* menu) override; - - void SetCamera(const CCamera& camera); - const CCamera& GetCamera() const { return m_Camera; }; - virtual void SetViewTM(const Matrix34& tm) - { - if (m_viewSourceType == ViewSourceType::None) - { - m_defaultViewTM = tm; - } - SetViewTM(tm, false); - } - - //! Map world space position to viewport position. - virtual QPoint WorldToView(const Vec3& wp) const; - virtual QPoint WorldToViewParticleEditor(const Vec3& wp, int width, int height) const; - virtual Vec3 WorldToView3D(const Vec3& wp, int nFlags = 0) const; - - //! Map viewport position to world space position. - virtual Vec3 ViewToWorld(const QPoint& vp, bool* collideWithTerrain = nullptr, bool onlyTerrain = false, bool bSkipVegetation = false, bool bTestRenderMesh = false, bool* collideWithObject = nullptr) const override; - virtual void ViewToWorldRay(const QPoint& vp, Vec3& raySrc, Vec3& rayDir) const override; - virtual Vec3 ViewToWorldNormal(const QPoint& vp, bool onlyTerrain, bool bTestRenderMesh = false) override; - virtual float GetScreenScaleFactor(const Vec3& worldPoint) const; - virtual float GetScreenScaleFactor(const CCamera& camera, const Vec3& object_position); - virtual float GetAspectRatio() const; - virtual bool HitTest(const QPoint& point, HitContext& hitInfo); - virtual bool IsBoundsVisible(const AABB& box) const; - virtual void CenterOnSelection(); - virtual void CenterOnAABB(const AABB& aabb); - void CenterOnSliceInstance() override; - - void focusOutEvent(QFocusEvent* event) override; - void keyPressEvent(QKeyEvent* event) override; - void keyReleaseEvent(QKeyEvent* event) override; - - void SetFOV(float fov); - float GetFOV() const; - - void SetDefaultCamera(); - bool IsDefaultCamera() const; - void SetSequenceCamera(); - bool IsSequenceCamera() const { return m_viewSourceType == ViewSourceType::SequenceCamera; } - void SetSelectedCamera(); - bool IsSelectedCamera() const; - void SetComponentCamera(const AZ::EntityId& entityId); - void SetEntityAsCamera(const AZ::EntityId& entityId, bool lockCameraMovement = false); - void SetFirstComponentCamera(); - void SetViewEntity(const AZ::EntityId& cameraEntityId, bool lockCameraMovement = false); - void PostCameraSet(); - // This switches the active camera to the next one in the list of (default, all custom cams). - void CycleCamera(); - - // Camera::EditorCameraRequestBus - void SetViewFromEntityPerspective(const AZ::EntityId& entityId) override; - void SetViewAndMovementLockFromEntityPerspective(const AZ::EntityId& entityId, bool lockCameraMovement) override; - AZ::EntityId GetCurrentViewEntityId() override { return m_viewEntityId; } - bool GetActiveCameraPosition(AZ::Vector3& cameraPos) override; - bool GetActiveCameraState(AzFramework::CameraState& cameraState) override; - - // AzToolsFramework::EditorEntityContextNotificationBus (handler moved to cpp to resolve link issues in unity builds) - virtual void OnStartPlayInEditor(); - virtual void OnStopPlayInEditor(); - - // AzToolsFramework::EditorContextMenu::Bus (handler moved to cpp to resolve link issues in unity builds) - // We use this to determine when the viewport context menu is being displayed so we can exit move mode - void PopulateEditorGlobalContextMenu(QMenu* /*menu*/, const AZ::Vector2& /*point*/, int /*flags*/); - - // AzToolsFramework::ViewportInteractionRequestBus - AzFramework::CameraState GetCameraState() override; - bool GridSnappingEnabled() override; - float GridSize() override; - bool ShowGrid() override; - bool AngleSnappingEnabled() override; - float AngleStep() override; - AzFramework::ScreenPoint ViewportWorldToScreen(const AZ::Vector3& worldPosition) override; - AZStd::optional ViewportScreenToWorld(const AzFramework::ScreenPoint&, float) override - { - return {}; - } - AZStd::optional ViewportScreenToWorldRay( - const AzFramework::ScreenPoint&) override - { - return {}; - } - float DeviceScalingFactor() override { return 1.0f; } - - // AzToolsFramework::ViewportFreezeRequestBus - bool IsViewportInputFrozen() override; - void FreezeViewportInput(bool freeze) override; - - // AzToolsFramework::MainEditorViewportInteractionRequestBus - AZ::EntityId PickEntity(const AzFramework::ScreenPoint& point) override; - AZ::Vector3 PickTerrain(const AzFramework::ScreenPoint& point) override; - float TerrainHeight(const AZ::Vector2& position) override; - void FindVisibleEntities(AZStd::vector& visibleEntitiesOut) override; - bool ShowingWorldSpace() override; - QWidget* GetWidgetForViewportContextMenu() override; - void BeginWidgetContext() override; - void EndWidgetContext() override; - - // WindowRequestBus::Handler... - void SetWindowTitle(const AZStd::string& title) override; - AzFramework::WindowSize GetClientAreaSize() const override; - void ResizeClientArea(AzFramework::WindowSize) override; - bool GetFullScreenState() const override; - void SetFullScreenState(bool fullScreenState) override; - bool CanToggleFullScreenState() const override; - void ToggleFullScreenState() override; - float GetDpiScaleFactor() const override { return 1.0f; }; - - void ConnectViewportInteractionRequestBus(); - void DisconnectViewportInteractionRequestBus(); - - void ActivateWindowAndSetFocus(); - - void LockCameraMovement(bool bLock) { m_bLockCameraMovement = bLock; } - bool IsCameraMovementLocked() const { return m_bLockCameraMovement; } - - void EnableCameraObjectMove(bool bMove) { m_bMoveCameraObject = bMove; } - bool IsCameraObjectMove() const { return m_bMoveCameraObject; } - - void SetPlayerControl(uint32 i) { m_PlayerControl = i; }; - uint32 GetPlayerControl() { return m_PlayerControl; }; - - const DisplayContext& GetDisplayContext() const { return m_displayContext; } - CBaseObject* GetCameraObject() const; - - QPoint WidgetToViewport(const QPoint& point) const; - QPoint ViewportToWidget(const QPoint& point) const; - QSize WidgetToViewport(const QSize& size) const; - - AzToolsFramework::ViewportInteraction::MouseInteraction BuildMouseInteraction( - Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, const QPoint& point) override; - - void SetPlayerPos() - { - Matrix34 m = GetViewTM(); - m.SetTranslation(m.GetTranslation() - m_PhysicalLocation.t); - SetViewTM(m); - - m_AverageFrameTime = 0.14f; - - m_PhysicalLocation.SetIdentity(); - - m_LocalEntityMat.SetIdentity(); - m_PrevLocalEntityMat.SetIdentity(); - - m_absCameraHigh = 2.0f; - m_absCameraPos = Vec3(0, 3, 2); - m_absCameraPosVP = Vec3(0, -3, 1.5); - - m_absCurrentSlope = 0.0f; - - m_absLookDirectionXY = Vec2(0, 1); - - m_LookAt = Vec3(ZERO); - m_LookAtRate = Vec3(ZERO); - m_vCamPos = Vec3(ZERO); - m_vCamPosRate = Vec3(ZERO); - - m_relCameraRotX = 0; - m_relCameraRotZ = 0; - - uint32 numSample6 = m_arrAnimatedCharacterPath.size(); - for (uint32 i = 0; i < numSample6; i++) - { - m_arrAnimatedCharacterPath[i] = Vec3(ZERO); - } - - numSample6 = m_arrSmoothEntityPath.size(); - for (uint32 i = 0; i < numSample6; i++) - { - m_arrSmoothEntityPath[i] = Vec3(ZERO); - } - - uint32 numSample7 = m_arrRunStrafeSmoothing.size(); - for (uint32 i = 0; i < numSample7; i++) - { - m_arrRunStrafeSmoothing[i] = 0; - } - - m_vWorldDesiredBodyDirection = Vec2(0, 1); - m_vWorldDesiredBodyDirectionSmooth = Vec2(0, 1); - m_vWorldDesiredBodyDirectionSmoothRate = Vec2(0, 1); - - m_vWorldDesiredBodyDirection2 = Vec2(0, 1); - - m_vWorldDesiredMoveDirection = Vec2(0, 1); - m_vWorldDesiredMoveDirectionSmooth = Vec2(0, 1); - m_vWorldDesiredMoveDirectionSmoothRate = Vec2(0, 1); - m_vLocalDesiredMoveDirection = Vec2(0, 1); - m_vLocalDesiredMoveDirectionSmooth = Vec2(0, 1); - m_vLocalDesiredMoveDirectionSmoothRate = Vec2(0, 1); - - m_vWorldAimBodyDirection = Vec2(0, 1); - - m_MoveSpeedMSec = 5.0f; - m_key_W = 0; - m_keyrcr_W = 0; - m_key_S = 0; - m_keyrcr_S = 0; - m_key_A = 0; - m_keyrcr_A = 0; - m_key_D = 0; - m_keyrcr_D = 0; - m_key_SPACE = 0; - m_keyrcr_SPACE = 0; - m_ControllMode = 0; - - m_State = -1; - m_Stance = 1; //combat - - m_udGround = 0.0f; - m_lrGround = 0.0f; - AABB aabb = AABB(Vec3(-40.0f, -40.0f, -0.25f), Vec3(+40.0f, +40.0f, +0.0f)); - m_GroundOBB = OBB::CreateOBBfromAABB(Matrix33(IDENTITY), aabb); - m_GroundOBBPos = Vec3(0, 0, -0.01f); - }; - - static CRenderViewport* GetPrimaryViewport(); - - AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING - CCamera m_Camera; - AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING - -protected: - struct SScopedCurrentContext; - - void SetViewTM(const Matrix34& tm, bool bMoveOnly); - - virtual float GetCameraMoveSpeed() const; - virtual float GetCameraRotateSpeed() const; - virtual bool GetCameraInvertYRotation() const; - virtual float GetCameraInvertPan() const; - - // Called to render stuff. - virtual void OnRender(); - - virtual void OnEditorNotifyEvent(EEditorNotifyEvent event); - - //! Get currently active camera object. - void ToggleCameraObject(); - - void RenderConstructionPlane(); - void RenderSnapMarker(); - void RenderCursorString(); - void RenderSnappingGrid(); - void ProcessMouse(); - void ProcessKeys(); - - void RenderAll(); - void DrawAxis(); - void DrawBackground(); - void InitDisplayContext(); - void ResetCursor(); - - struct SPreviousContext - { - CCamera rendererCamera; - HWND window; - int width; - int height; - bool mainViewport; - }; - - SPreviousContext m_preWidgetContext; - - // Create an auto-sized render context that is sized based on the Editor's current - // viewport. - SPreviousContext SetCurrentContext() const; - - SPreviousContext SetCurrentContext(int newWidth, int newHeight) const; - void RestorePreviousContext(const SPreviousContext& x) const; - - void PreWidgetRendering() override; - void PostWidgetRendering() override; - - // Update the safe frame, safe action, safe title, and borders rectangles based on - // viewport size and target aspect ratio. - void UpdateSafeFrame(); - - // Draw safe frame, safe action, safe title rectangles and borders. - void RenderSafeFrame(); - - // Draw one of the safe frame rectangles with the desired color. - void RenderSafeFrame(const QRect& frame, float r, float g, float b, float a); - - // Draw the selection rectangle. - void RenderSelectionRectangle(); - - // Draw a selected region if it has been selected - void RenderSelectedRegion(); - - virtual bool CreateRenderContext(); - virtual void DestroyRenderContext(); - - void OnMenuCommandChangeAspectRatio(unsigned int commandId); - - bool AdjustObjectPosition(const ray_hit& hit, Vec3& outNormal, Vec3& outPos) const; - bool RayRenderMeshIntersection(IRenderMesh* pRenderMesh, const Vec3& vInPos, const Vec3& vInDir, Vec3& vOutPos, Vec3& vOutNormal) const; - - bool AddCameraMenuItems(QMenu* menu); - void ResizeView(int width, int height); - - void OnCameraFOVVariableChanged(IVariable* var); - - void HideCursor(); - void ShowCursor(); - - bool IsKeyDown(Qt::Key key) const; - - enum class ViewSourceType - { - None, - SequenceCamera, - LegacyCamera, - CameraComponent, - AZ_Entity, - ViewSourceTypesCount, - }; - void ResetToViewSourceType(const ViewSourceType& viewSourType); - - //! Assigned renderer. - IRenderer* m_renderer = nullptr; - bool m_bRenderContextCreated = false; - bool m_bInRotateMode = false; - bool m_bInMoveMode = false; - bool m_bInOrbitMode = false; - bool m_bInZoomMode = false; - - QPoint m_mousePos = QPoint(0, 0); - QPoint m_prevMousePos = QPoint(0, 0); // for tablets, you can't use SetCursorPos and need to remember the prior point and delta with that. - - - float m_moveSpeed = 1; - - float m_orbitDistance = 10.0f; - AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING - Vec3 m_orbitTarget; - - //------------------------------------------- - //--- player-control in CharEdit --- - //------------------------------------------- - f32 m_MoveSpeedMSec; - - uint32 m_key_W, m_keyrcr_W; - uint32 m_key_S, m_keyrcr_S; - uint32 m_key_A, m_keyrcr_A; - uint32 m_key_D, m_keyrcr_D; - - uint32 m_key_SPACE, m_keyrcr_SPACE; - uint32 m_ControllMode; - - int32 m_Stance; - int32 m_State; - f32 m_AverageFrameTime; - - uint32 m_PlayerControl = 0; - - f32 m_absCameraHigh; - Vec3 m_absCameraPos; - Vec3 m_absCameraPosVP; - - f32 m_absCurrentSlope; //in radiants - - Vec2 m_absLookDirectionXY; - - Vec3 m_LookAt; - Vec3 m_LookAtRate; - Vec3 m_vCamPos; - Vec3 m_vCamPosRate; - float m_camFOV; - - f32 m_relCameraRotX; - f32 m_relCameraRotZ; - - QuatTS m_PhysicalLocation; - - Matrix34 m_AnimatedCharacterMat; - - Matrix34 m_LocalEntityMat; //this is used for data-driven animations where the character is running on the spot - Matrix34 m_PrevLocalEntityMat; - - std::vector m_arrVerticesHF; - std::vector m_arrIndicesHF; - - std::vector m_arrAnimatedCharacterPath; - std::vector m_arrSmoothEntityPath; - std::vector m_arrRunStrafeSmoothing; - - Vec2 m_vWorldDesiredBodyDirection; - Vec2 m_vWorldDesiredBodyDirectionSmooth; - Vec2 m_vWorldDesiredBodyDirectionSmoothRate; - - Vec2 m_vWorldDesiredBodyDirection2; - - - Vec2 m_vWorldDesiredMoveDirection; - Vec2 m_vWorldDesiredMoveDirectionSmooth; - Vec2 m_vWorldDesiredMoveDirectionSmoothRate; - Vec2 m_vLocalDesiredMoveDirection; - Vec2 m_vLocalDesiredMoveDirectionSmooth; - Vec2 m_vLocalDesiredMoveDirectionSmoothRate; - Vec2 m_vWorldAimBodyDirection; - - f32 m_udGround; - f32 m_lrGround; - OBB m_GroundOBB; - Vec3 m_GroundOBBPos; - - // Index of camera objects. - mutable GUID m_cameraObjectId = GUID_NULL; - mutable AZ::EntityId m_viewEntityId; - mutable ViewSourceType m_viewSourceType = ViewSourceType::None; - AZ::EntityId m_viewEntityIdCachedForEditMode; - Matrix34 m_preGameModeViewTM; - uint m_disableRenderingCount = 0; - bool m_bLockCameraMovement; - bool m_bUpdateViewport = false; - bool m_bMoveCameraObject = true; - - enum class KeyPressedState - { - AllUp, - PressedThisFrame, - PressedInPreviousFrame, - }; - KeyPressedState m_pressedKeyState = KeyPressedState::AllUp; - - Matrix34 m_defaultViewTM; - const QString m_defaultViewName; - - DisplayContext m_displayContext; - - - bool m_isOnPaint = false; - static CRenderViewport* m_pPrimaryViewport; - - QRect m_safeFrame; - QRect m_safeAction; - QRect m_safeTitle; - - CPredefinedAspectRatios m_predefinedAspectRatios; - - IVariable* m_pCameraFOVVariable = nullptr; - bool m_bCursorHidden = false; - - void OnMenuResolutionCustom(); - void OnMenuCreateCameraEntityFromCurrentView(); - void OnMenuSelectCurrentCamera(); - - int OnCreate(); - void resizeEvent(QResizeEvent* event) override; - void paintEvent(QPaintEvent* event) override; - void mousePressEvent(QMouseEvent* event) override; - void OnLButtonDown(Qt::KeyboardModifiers modifiers, const QPoint& point) override; - void OnLButtonUp(Qt::KeyboardModifiers modifiers, const QPoint& point) override; - void OnLButtonDblClk(Qt::KeyboardModifiers modifiers, const QPoint& point) override; - void OnMButtonDown(Qt::KeyboardModifiers modifiers, const QPoint& point) override; - void OnMButtonUp(Qt::KeyboardModifiers modifiers, const QPoint& point) override; - void OnRButtonDown(Qt::KeyboardModifiers modifiers, const QPoint& point) override; - void OnRButtonUp(Qt::KeyboardModifiers modifiers, const QPoint& point) override; - void OnMouseMove(Qt::KeyboardModifiers modifiers, Qt::MouseButtons buttons, const QPoint& point) override; - void OnMouseWheel(Qt::KeyboardModifiers modifiers, short zDelta, const QPoint& pt) override; - - // From a series of input primitives, compose a complete mouse interaction. - AzToolsFramework::ViewportInteraction::MouseInteraction BuildMouseInteractionInternal( - AzToolsFramework::ViewportInteraction::MouseButtons buttons, - AzToolsFramework::ViewportInteraction::KeyboardModifiers modifiers, - const AzToolsFramework::ViewportInteraction::MousePick& mousePick) const; - // Given a point in the viewport, return the pick ray into the scene. - // note: The argument passed to parameter **point**, originating - // from a Qt event, must first be passed to WidgetToViewport before being - // passed to BuildMousePick. - AzToolsFramework::ViewportInteraction::MousePick BuildMousePick(const QPoint& point); - - bool event(QEvent* event) override; - void OnDestroy(); - - bool CheckRespondToInput() const; - - // AzFramework::InputSystemCursorConstraintRequestBus - void* GetSystemCursorConstraintWindow() const override; - - void BuildDragDropContext(AzQtComponents::ViewportDragContext& context, const QPoint& pt) override; - -private: - void ProcessKeyRelease(QKeyEvent* event); - void PushDisableRendering(); - void PopDisableRendering(); - bool IsRenderingDisabled() const; - AzToolsFramework::ViewportInteraction::MousePick BuildMousePickInternal( - const QPoint& point) const; - - void RestoreViewportAfterGameMode(); - - double WidgetToViewportFactor() const - { -#if defined(AZ_PLATFORM_WINDOWS) - // Needed for high DPI mode on windows - return devicePixelRatioF(); -#else - return 1.0f; #endif - } - - void BeginUndoTransaction() override; - void EndUndoTransaction() override; - - void UpdateCurrentMousePos(const QPoint& newPosition); - - AzFramework::EntityVisibilityQuery m_entityVisibilityQuery; - - SPreviousContext m_previousContext; - QSet m_keyDown; - - bool m_freezeViewportInput = false; - - size_t m_cameraSetForWidgetRenderingCount = 0; ///< How many calls to PreWidgetRendering happened before - ///< subsequent calls to PostWidetRendering. - AZStd::shared_ptr m_manipulatorManager; - - // Used to prevent circular set camera events - bool m_ignoreSetViewFromEntityPerspective = false; - bool m_windowResizedEvent = false; - - // Cache hwnd value for teardown to avoid infinite loops in retrieving it from destroyed widgets. - HWND m_hwnd; - - AZStd::unique_ptr m_editorEntityNotifications; - - AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING -}; - -#endif // CRYINCLUDE_EDITOR_RENDERVIEWPORT_H diff --git a/Code/Editor/Settings.cpp b/Code/Editor/Settings.cpp index 8f86c74b25..8226081bd6 100644 --- a/Code/Editor/Settings.cpp +++ b/Code/Editor/Settings.cpp @@ -26,6 +26,7 @@ // AzFramework #include +#include // AzToolsFramework #include diff --git a/Code/Editor/TrackView/CommentNodeAnimator.cpp b/Code/Editor/TrackView/CommentNodeAnimator.cpp index 47f4c5d9ae..f01cbc84b4 100644 --- a/Code/Editor/TrackView/CommentNodeAnimator.cpp +++ b/Code/Editor/TrackView/CommentNodeAnimator.cpp @@ -161,16 +161,19 @@ void CCommentNodeAnimator::Render(CTrackViewAnimNode* pNode, [[maybe_unused]] co Vec2 CCommentNodeAnimator::GetScreenPosFromNormalizedPos(const Vec2& unitPos) { - const CCamera& cam = gEnv->pSystem->GetViewCamera(); - float width = (float)cam.GetViewSurfaceX(); - int height = cam.GetViewSurfaceZ(); - float fAspectRatio = gSettings.viewports.fDefaultAspectRatio; - float camWidth = height * fAspectRatio; + (void)unitPos; + AZ_Error("CryLegacy", false, "CCommentNodeAnimator::GetScreenPosFromNormalizedPos not supported"); + return Vec2(0, 0); + //const CCamera& cam = gEnv->pSystem->GetViewCamera(); + //float width = (float)cam.GetViewSurfaceX(); + //int height = cam.GetViewSurfaceZ(); + //float fAspectRatio = gSettings.viewports.fDefaultAspectRatio; + //float camWidth = height * fAspectRatio; - float x = 0.5f * width + 0.5f * camWidth * unitPos.x; - float y = 0.5f * height * (1.f - unitPos.y); + //float x = 0.5f * width + 0.5f * camWidth * unitPos.x; + //float y = 0.5f * height * (1.f - unitPos.y); - return Vec2(x, y); + //return Vec2(x, y); } void CCommentNodeAnimator::DrawText(const char* szFontName, float fSize, const Vec2& unitPos, const ColorF col, const char* szText, int align) diff --git a/Code/Editor/TrackView/SequenceBatchRenderDialog.cpp b/Code/Editor/TrackView/SequenceBatchRenderDialog.cpp index 7b08b3e614..4f06e3cc84 100644 --- a/Code/Editor/TrackView/SequenceBatchRenderDialog.cpp +++ b/Code/Editor/TrackView/SequenceBatchRenderDialog.cpp @@ -44,7 +44,12 @@ namespace { const int g_useActiveViewportResolution = -1; // reserved value to indicate the use of the active viewport resolution int resolutions[][2] = { - { 1280, 720 }, { 1920, 1080 }, { 1998, 1080 }, { 2048, 858 }, { 2560, 1440 }, + {1280, 720}, + {1920, 1080}, + {1998, 1080}, + {2048, 858}, + {2560, 1440}, + {3840, 2160}, { g_useActiveViewportResolution, g_useActiveViewportResolution } // active viewport res must be the last element of the resolution array }; @@ -1067,6 +1072,10 @@ void CSequenceBatchRenderDialog::OnUpdateEnd(IAnimSequence* sequence) { GetIEditor()->GetMovieSystem()->DisableFixedStepForCapture(); + // Important: End batch render mode BEFORE leaving Game Mode. + // Otherwise track view will set the active camera based on the directors in the current sequence while leaving game mode + GetIEditor()->GetMovieSystem()->EnableBatchRenderMode(false); + GetIEditor()->GetMovieSystem()->RemoveMovieListener(sequence, this); GetIEditor()->SetInGameMode(false); GetIEditor()->GetGameEngine()->Update(); // Update is needed because SetInGameMode() queues game mode, Update() executes it. @@ -1186,7 +1195,6 @@ void CSequenceBatchRenderDialog::OnUpdateFinalize() m_ui->m_pGoBtn->setText(tr("Start")); m_ui->m_pGoBtn->setIcon(QPixmap(":/Trackview/clapperboard_ready.png")); - GetIEditor()->GetMovieSystem()->EnableBatchRenderMode(false); m_renderContext.currentItemIndex = -1; m_ui->BATCH_RENDER_PRESS_ESC_TO_CANCEL->setText(m_ffmpegPluginStatusMsg); diff --git a/Code/Editor/TrackView/TrackViewAnimNode.cpp b/Code/Editor/TrackView/TrackViewAnimNode.cpp index c66ea5635c..8696faf516 100644 --- a/Code/Editor/TrackView/TrackViewAnimNode.cpp +++ b/Code/Editor/TrackView/TrackViewAnimNode.cpp @@ -27,6 +27,7 @@ #include #include #include +#include // Editor #include "AnimationContext.h" diff --git a/Code/Editor/UndoViewRotation.cpp b/Code/Editor/UndoViewRotation.cpp index d226a516d1..c3c6f4253a 100644 --- a/Code/Editor/UndoViewRotation.cpp +++ b/Code/Editor/UndoViewRotation.cpp @@ -17,10 +17,24 @@ // Editor #include "ViewManager.h" +#include +#include +#include +#include + +Ang3 CUndoViewRotation::GetActiveCameraRotation() +{ + AZ::Transform activeCameraTm = AZ::Transform::CreateIdentity(); + EBUS_EVENT_RESULT(activeCameraTm, Camera::ActiveCameraRequestBus, GetActiveCameraTransform); + const AZ::Matrix3x4 cameraMatrix = AZ::Matrix3x4::CreateFromTransform(activeCameraTm); + const Matrix33 cameraMatrixCry = AZMatrix3x3ToLYMatrix3x3(AZ::Matrix3x3::CreateFromMatrix3x4(cameraMatrix)); + return RAD2DEG(Ang3::GetAnglesXYZ(cameraMatrixCry)); +} + CUndoViewRotation::CUndoViewRotation(const QString& pUndoDescription) { m_undoDescription = pUndoDescription; - m_undo = RAD2DEG(Ang3::GetAnglesXYZ(Matrix33(GetIEditor()->GetSystem()->GetViewCamera().GetMatrix()))); + m_undo = GetActiveCameraRotation(); } int CUndoViewRotation::GetSize() @@ -40,7 +54,7 @@ void CUndoViewRotation::Undo(bool bUndo) { if (bUndo) { - m_redo = RAD2DEG(Ang3::GetAnglesXYZ(Matrix33(GetIEditor()->GetSystem()->GetViewCamera().GetMatrix()))); + m_redo = GetActiveCameraRotation(); } Matrix34 tm = pRenderViewport->GetViewTM(); diff --git a/Code/Editor/UndoViewRotation.h b/Code/Editor/UndoViewRotation.h index 49e9b333eb..2e086a3f05 100644 --- a/Code/Editor/UndoViewRotation.h +++ b/Code/Editor/UndoViewRotation.h @@ -29,6 +29,8 @@ protected: void Redo(); private: + static Ang3 GetActiveCameraRotation(); + Ang3 m_undo; Ang3 m_redo; QString m_undoDescription; diff --git a/Code/Editor/ViewManager.cpp b/Code/Editor/ViewManager.cpp index 5a3e92a525..88c4823249 100644 --- a/Code/Editor/ViewManager.cpp +++ b/Code/Editor/ViewManager.cpp @@ -80,7 +80,8 @@ CViewManager::CViewManager() } else { - RegisterQtViewPaneWithName(GetIEditor(), "Perspective", LyViewPane::CategoryViewport, viewportOptions); + AZ_Assert(false, "Non-Atom viewport no longer supported"); + //RegisterQtViewPaneWithName(GetIEditor(), "Perspective", LyViewPane::CategoryViewport, viewportOptions); } viewportOptions.viewportType = ET_ViewportMap; @@ -251,10 +252,10 @@ void CViewManager::SelectViewport(CViewport* pViewport) ////////////////////////////////////////////////////////////////////////// CViewport* CViewManager::GetGameViewport() const { - if (CRenderViewport::GetPrimaryViewport()) - { - return CRenderViewport::GetPrimaryViewport(); - } + //if (CRenderViewport::GetPrimaryViewport()) + //{ + // return CRenderViewport::GetPrimaryViewport(); + //} return GetViewport(ET_ViewportCamera);; } diff --git a/Code/Editor/ViewPane.cpp b/Code/Editor/ViewPane.cpp index 19b653b865..b4af87775c 100644 --- a/Code/Editor/ViewPane.cpp +++ b/Code/Editor/ViewPane.cpp @@ -305,10 +305,6 @@ void CLayoutViewPane::AttachViewport(QWidget* pViewport) { vp->SetViewportId(GetId()); vp->SetViewPane(this); - if (CRenderViewport* renderViewport = viewport_cast(vp)) - { - renderViewport->ConnectViewportInteractionRequestBus(); - } if (EditorViewportWidget* renderViewport = viewport_cast(vp)) { renderViewport->ConnectViewportInteractionRequestBus(); @@ -356,10 +352,6 @@ void CLayoutViewPane::DisconnectRenderViewportInteractionRequestBus() { if (QtViewport* vp = qobject_cast(m_viewport)) { - if (CRenderViewport* renderViewport = viewport_cast(vp)) - { - renderViewport->DisconnectViewportInteractionRequestBus(); - } if (EditorViewportWidget* renderViewport = viewport_cast(vp)) { renderViewport->DisconnectViewportInteractionRequestBus(); @@ -469,16 +461,6 @@ void CLayoutViewPane::SetAspectRatio(unsigned int x, unsigned int y) ////////////////////////////////////////////////////////////////////////// void CLayoutViewPane::SetViewportFOV(float fov) { - if (CRenderViewport* pRenderViewport = qobject_cast(m_viewport)) - { - pRenderViewport->SetFOV(DEG2RAD(fov)); - - // if viewport camera is active, make selected fov new default - if (pRenderViewport->GetViewManager()->GetCameraObjectId() == GUID_NULL) - { - gSettings.viewports.fDefaultFov = DEG2RAD(fov); - } - } if (EditorViewportWidget* pRenderViewport = qobject_cast(m_viewport)) { pRenderViewport->SetFOV(DEG2RAD(fov)); diff --git a/Code/Editor/Viewport.cpp b/Code/Editor/Viewport.cpp index 906a60ac47..ba310cb52d 100644 --- a/Code/Editor/Viewport.cpp +++ b/Code/Editor/Viewport.cpp @@ -189,7 +189,6 @@ QtViewport::QtViewport(QWidget* parent) { m_constructionMatrix[i].SetIdentity(); } - m_viewTM.SetIdentity(); m_screenTM.SetIdentity(); m_pMouseOverObject = 0; diff --git a/Code/Editor/Viewport.h b/Code/Editor/Viewport.h index c94a77b06e..5b4f23fd2b 100644 --- a/Code/Editor/Viewport.h +++ b/Code/Editor/Viewport.h @@ -165,11 +165,19 @@ public: ////////////////////////////////////////////////////////////////////////// //! Set current view matrix, //! This is a matrix that transforms from world to view space. - virtual void SetViewTM(const Matrix34& tm) { m_viewTM = tm; }; + virtual void SetViewTM([[maybe_unused]] const Matrix34& tm) + { + AZ_Error("CryLegacy", false, "QtViewport::SetViewTM not implemented"); + } //! Get current view matrix. //! This is a matrix that transforms from world space to view space. - virtual const Matrix34& GetViewTM() const { return m_viewTM; }; + virtual const Matrix34& GetViewTM() const + { + AZ_Error("CryLegacy", false, "QtViewport::GetViewTM not implemented"); + static const Matrix34 m; + return m; + }; ////////////////////////////////////////////////////////////////////////// //! Get current screen matrix. @@ -277,8 +285,6 @@ protected: CLayoutViewPane* m_viewPane = nullptr; CViewManager* m_viewManager; AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING - // Viewport matrix. - Matrix34 m_viewTM; // Screen Matrix Matrix34 m_screenTM; int m_nCurViewportID; diff --git a/Code/Editor/ViewportTitleDlg.cpp b/Code/Editor/ViewportTitleDlg.cpp index 4d27506929..6d2d91f546 100644 --- a/Code/Editor/ViewportTitleDlg.cpp +++ b/Code/Editor/ViewportTitleDlg.cpp @@ -644,13 +644,31 @@ void CViewportTitleDlg::CreateViewportInformationMenu() void CViewportTitleDlg::AddResolutionMenus(QMenu* menu, std::function callback, const QStringList& customPresets) { - static const CRenderViewport::SResolution resolutions[] = { - CRenderViewport::SResolution(1280, 720), - CRenderViewport::SResolution(1920, 1080), - CRenderViewport::SResolution(2560, 1440), - CRenderViewport::SResolution(2048, 858), - CRenderViewport::SResolution(1998, 1080), - CRenderViewport::SResolution(3840, 2160) + struct SResolution + { + SResolution() + : width(0) + , height(0) + { + } + + SResolution(int w, int h) + : width(w) + , height(h) + { + } + + int width; + int height; + }; + + static const SResolution resolutions[] = { + SResolution(1280, 720), + SResolution(1920, 1080), + SResolution(2560, 1440), + SResolution(2048, 858), + SResolution(1998, 1080), + SResolution(3840, 2160) }; static const size_t resolutionCount = sizeof(resolutions) / sizeof(resolutions[0]); diff --git a/Code/Framework/AzCore/AzCore/Math/MatrixUtils.cpp b/Code/Framework/AzCore/AzCore/Math/MatrixUtils.cpp index a578640d0d..c5b76cbab7 100644 --- a/Code/Framework/AzCore/AzCore/Math/MatrixUtils.cpp +++ b/Code/Framework/AzCore/AzCore/Math/MatrixUtils.cpp @@ -44,6 +44,22 @@ namespace AZ return &out; } + void SetPerspectiveMatrixFOV(Matrix4x4& out, float fovY, float aspectRatio) + { + float sinFov, cosFov; + SinCos(0.5f * fovY, sinFov, cosFov); + float yScale = cosFov / sinFov; //cot(fovY/2) + float xScale = yScale / aspectRatio; + + out.SetElement(0, 0, xScale); + out.SetElement(1, 1, yScale); + } + + float GetPerspectiveMatrixFOV(const Matrix4x4& m) + { + return 2.0 * atan(1.0f / m.GetElement(1, 1)); + } + Matrix4x4* MakeFrustumMatrixRH(Matrix4x4& out, float left, float right, float bottom, float top, float nearDist, float farDist, bool reverseDepth) { AZ_Assert(right > left, "right should be greater than left"); diff --git a/Code/Framework/AzCore/AzCore/Math/MatrixUtils.h b/Code/Framework/AzCore/AzCore/Math/MatrixUtils.h index 72a7b29887..2679791fae 100644 --- a/Code/Framework/AzCore/AzCore/Math/MatrixUtils.h +++ b/Code/Framework/AzCore/AzCore/Math/MatrixUtils.h @@ -64,4 +64,8 @@ namespace AZ //! Transforms a position by a matrix. This function can be used with any generic cases which include projection matrices. Vector3 MatrixTransformPosition(const Matrix4x4& matrix, const Vector3& inPosition); + + void SetPerspectiveMatrixFOV(Matrix4x4& out, float fovY, float aspectRatio); + float GetPerspectiveMatrixFOV(const Matrix4x4& m); + } // namespace AZ diff --git a/Code/Framework/AzFramework/AzFramework/Components/CameraBus.h b/Code/Framework/AzFramework/AzFramework/Components/CameraBus.h index 0b2a0cbb78..e20578e939 100644 --- a/Code/Framework/AzFramework/AzFramework/Components/CameraBus.h +++ b/Code/Framework/AzFramework/AzFramework/Components/CameraBus.h @@ -114,6 +114,9 @@ namespace Camera //! Makes the camera the active view virtual void MakeActiveView() = 0; + //! Check if this camera is the active render camera + virtual bool IsActiveView() = 0; + //! Get the camera frustum's aggregate configuration virtual Configuration GetCameraConfiguration() { diff --git a/Code/Legacy/CryCommon/ISystem.h b/Code/Legacy/CryCommon/ISystem.h index d934995b4d..1e1aae99be 100644 --- a/Code/Legacy/CryCommon/ISystem.h +++ b/Code/Legacy/CryCommon/ISystem.h @@ -900,9 +900,6 @@ struct ISystem // Retrieves access to XML utilities interface. virtual IXmlUtils* GetXmlUtils() = 0; - virtual void SetViewCamera(CCamera& Camera) = 0; - virtual CCamera& GetViewCamera() = 0; - // Description: // When ignore update sets to true, system will ignore and updates and render calls. virtual void IgnoreUpdates(bool bIgnore) = 0; diff --git a/Code/Legacy/CrySystem/LevelSystem/LevelSystem.cpp b/Code/Legacy/CrySystem/LevelSystem/LevelSystem.cpp index e8cc4d484c..27dead077c 100644 --- a/Code/Legacy/CrySystem/LevelSystem/LevelSystem.cpp +++ b/Code/Legacy/CrySystem/LevelSystem/LevelSystem.cpp @@ -620,9 +620,9 @@ ILevel* CLevelSystem::LoadLevelInternal(const char* _levelName) // Reset the camera to (1,1,1) (not (0,0,0) which is the invalid/uninitialised state, // to avoid the hack in the renderer to not show anything if the camera is at the origin). - CCamera defaultCam; - defaultCam.SetPosition(Vec3(1.0f)); - m_pSystem->SetViewCamera(defaultCam); + //CCamera defaultCam; + //defaultCam.SetPosition(Vec3(1.0f)); + //m_pSystem->SetViewCamera(defaultCam); m_pLoadingLevelInfo = pLevelInfo; OnLoadingStart(levelName); @@ -953,8 +953,8 @@ void CLevelSystem::UnloadLevel() Audio::AudioSystemRequestBus::Broadcast(&Audio::AudioSystemRequestBus::Events::PushRequestBlocking, oAudioRequestData); // Reset the camera to (0,0,0) which is the invalid/uninitialised state - CCamera defaultCam; - m_pSystem->SetViewCamera(defaultCam); + //CCamera defaultCam; + //m_pSystem->SetViewCamera(defaultCam); OnUnloadComplete(m_lastLevelName.c_str()); diff --git a/Code/Legacy/CrySystem/LevelSystem/SpawnableLevelSystem.cpp b/Code/Legacy/CrySystem/LevelSystem/SpawnableLevelSystem.cpp index 103d5999f7..962469532d 100644 --- a/Code/Legacy/CrySystem/LevelSystem/SpawnableLevelSystem.cpp +++ b/Code/Legacy/CrySystem/LevelSystem/SpawnableLevelSystem.cpp @@ -272,7 +272,7 @@ namespace LegacyLevelSystem // to avoid the hack in the renderer to not show anything if the camera is at the origin). CCamera defaultCam; defaultCam.SetPosition(Vec3(1.0f)); - m_pSystem->SetViewCamera(defaultCam); + //m_pSystem->SetViewCamera(defaultCam); OnLoadingStart(levelName); @@ -588,8 +588,8 @@ namespace LegacyLevelSystem Audio::AudioSystemRequestBus::Broadcast(&Audio::AudioSystemRequestBus::Events::PushRequestBlocking, oAudioRequestData); // Reset the camera to (0,0,0) which is the invalid/uninitialised state - CCamera defaultCam; - m_pSystem->SetViewCamera(defaultCam); + //CCamera defaultCam; + //m_pSystem->SetViewCamera(defaultCam); OnUnloadComplete(m_lastLevelName.c_str()); diff --git a/Code/Legacy/CrySystem/System.h b/Code/Legacy/CrySystem/System.h index c66b2aab60..db20dd8f1b 100644 --- a/Code/Legacy/CrySystem/System.h +++ b/Code/Legacy/CrySystem/System.h @@ -353,9 +353,6 @@ public: virtual IXmlUtils* GetXmlUtils(); ////////////////////////////////////////////////////////////////////////// - void SetViewCamera(CCamera& Camera){ m_ViewCamera = Camera; } - CCamera& GetViewCamera() { return m_ViewCamera; } - void IgnoreUpdates(bool bIgnore) { m_bIgnoreUpdates = bIgnore; }; void SetIProcess(IProcess* process); @@ -494,7 +491,6 @@ private: // ------------------------------------------------------ SSystemGlobalEnvironment m_env; CTimer m_Time; //!< - CCamera m_ViewCamera; //!< bool m_bInitializedSuccessfully; //!< true if the system completed all initialization steps bool m_bRelaunch; //!< relaunching the app or not (true beforerelaunch) int m_iLoadingMode; //!< Game is loading w/o changing context (0 not, 1 quickloading, 2 full loading) diff --git a/Code/Legacy/CrySystem/ViewSystem/DebugCamera.cpp b/Code/Legacy/CrySystem/ViewSystem/DebugCamera.cpp index e8d21c961f..8bf5c4eee3 100644 --- a/Code/Legacy/CrySystem/ViewSystem/DebugCamera.cpp +++ b/Code/Legacy/CrySystem/ViewSystem/DebugCamera.cpp @@ -58,10 +58,10 @@ DebugCamera::~DebugCamera() /////////////////////////////////////////////////////////////////////////////// void DebugCamera::OnEnable() { - m_position = gEnv->pSystem->GetViewCamera().GetPosition(); + m_position = Vec3_Zero; // gEnv->pSystem->GetViewCamera().GetPosition(); m_moveInput = Vec3_Zero; - Ang3 cameraAngles = Ang3(gEnv->pSystem->GetViewCamera().GetMatrix()); + Ang3 cameraAngles = Ang3(ZERO); // Ang3(gEnv->pSystem->GetViewCamera().GetMatrix()); m_cameraYaw = RAD2DEG(cameraAngles.z); m_cameraPitch = RAD2DEG(cameraAngles.x); m_view = Matrix33(Ang3(DEG2RAD(m_cameraPitch), 0.0f, DEG2RAD(m_cameraYaw))); @@ -126,13 +126,13 @@ void DebugCamera::Update() /////////////////////////////////////////////////////////////////////////////// void DebugCamera::PostUpdate() { - if (m_cameraMode == DebugCamera::ModeOff) - { - return; - } + //if (m_cameraMode == DebugCamera::ModeOff) + //{ + // return; + //} - CCamera& camera = gEnv->pSystem->GetViewCamera(); - camera.SetMatrix(Matrix34(m_view, m_position)); + //CCamera& camera = gEnv->pSystem->GetViewCamera(); + //camera.SetMatrix(Matrix34(m_view, m_position)); } /////////////////////////////////////////////////////////////////////////////// diff --git a/Code/Legacy/CrySystem/ViewSystem/View.cpp b/Code/Legacy/CrySystem/ViewSystem/View.cpp index ef9f2591c4..26f75ced76 100644 --- a/Code/Legacy/CrySystem/ViewSystem/View.cpp +++ b/Code/Legacy/CrySystem/ViewSystem/View.cpp @@ -57,77 +57,79 @@ void CView::Release() //------------------------------------------------------------------------ void CView::Update(float frameTime, bool isActive) { - //FIXME:some cameras may need to be updated always - if (!isActive) - { - return; - } + (void)(frameTime, isActive); + AZ_ErrorOnce("CryLegacy", false, "CryLegacy view system no longer available (CView::Update)"); + ////FIXME:some cameras may need to be updated always + //if (!isActive) + //{ + // return; + //} - if (m_azEntity) - { - m_viewParams.SaveLast(); + //if (m_azEntity) + //{ + // m_viewParams.SaveLast(); - CCamera* pSysCam = &m_pSystem->GetViewCamera(); + // CCamera* pSysCam = &m_pSystem->GetViewCamera(); - //process screen shaking - ProcessShaking(frameTime); + // //process screen shaking + // ProcessShaking(frameTime); - //FIXME:to let the updateView implementation use the correct shakeVector - m_viewParams.currentShakeShift = m_viewParams.rotation * m_viewParams.currentShakeShift; + // //FIXME:to let the updateView implementation use the correct shakeVector + // m_viewParams.currentShakeShift = m_viewParams.rotation * m_viewParams.currentShakeShift; - m_viewParams.frameTime = frameTime; - //update view position/rotation - if (m_azEntity != nullptr) - { - auto entityTransform = m_azEntity->GetTransform(); - if (entityTransform != nullptr) - { - AZ::Transform transform = entityTransform->GetWorldTM(); - m_viewParams.position = AZVec3ToLYVec3(transform.GetTranslation()); - m_viewParams.rotation = AZQuaternionToLYQuaternion(transform.GetRotation()); - } - } + // m_viewParams.frameTime = frameTime; + // //update view position/rotation + // if (m_azEntity != nullptr) + // { + // auto entityTransform = m_azEntity->GetTransform(); + // if (entityTransform != nullptr) + // { + // AZ::Transform transform = entityTransform->GetWorldTM(); + // m_viewParams.position = AZVec3ToLYVec3(transform.GetTranslation()); + // m_viewParams.rotation = AZQuaternionToLYQuaternion(transform.GetRotation()); + // } + // } - ApplyFrameAdditiveAngles(m_viewParams.rotation); + // ApplyFrameAdditiveAngles(m_viewParams.rotation); - const float fNearZ = gEnv->pSystem->GetIViewSystem()->GetDefaultZNear(); + // const float fNearZ = gEnv->pSystem->GetIViewSystem()->GetDefaultZNear(); - //see if the view have to use a custom near clipping plane - const float nearPlane = (m_viewParams.nearplane >= CAMERA_MIN_NEAR) ? (m_viewParams.nearplane) : fNearZ; - const float farPlane = (m_viewParams.farplane > 0.f) ? m_viewParams.farplane : DEFAULT_FAR; - float fov = (m_viewParams.fov < 0.001f) ? DEFAULT_FOV : m_viewParams.fov; + // //see if the view have to use a custom near clipping plane + // const float nearPlane = (m_viewParams.nearplane >= CAMERA_MIN_NEAR) ? (m_viewParams.nearplane) : fNearZ; + // const float farPlane = (m_viewParams.farplane > 0.f) ? m_viewParams.farplane : DEFAULT_FAR; + // float fov = (m_viewParams.fov < 0.001f) ? DEFAULT_FOV : m_viewParams.fov; - m_camera.SetFrustum(pSysCam->GetViewSurfaceX(), pSysCam->GetViewSurfaceZ(), fov, nearPlane, farPlane, pSysCam->GetPixelAspectRatio()); + // m_camera.SetFrustum(pSysCam->GetViewSurfaceX(), pSysCam->GetViewSurfaceZ(), fov, nearPlane, farPlane, pSysCam->GetPixelAspectRatio()); - //apply shake & set the view matrix - m_viewParams.rotation *= m_viewParams.currentShakeQuat; - m_viewParams.rotation.NormalizeSafe(); - m_viewParams.position += m_viewParams.currentShakeShift; + // //apply shake & set the view matrix + // m_viewParams.rotation *= m_viewParams.currentShakeQuat; + // m_viewParams.rotation.NormalizeSafe(); + // m_viewParams.position += m_viewParams.currentShakeShift; - // Blending between cameras needs to happen after Camera space rendering calculations have been applied - // so that the m_viewParams.position is in World Space again - m_viewParams.UpdateBlending(frameTime); + // // Blending between cameras needs to happen after Camera space rendering calculations have been applied + // // so that the m_viewParams.position is in World Space again + // m_viewParams.UpdateBlending(frameTime); - // [VR] specific - // Add HMD's pose tracking on top of current camera pose - // Each game-title can decide whether to keep this functionality here or (most likely) - // move it somewhere else. + // // [VR] specific + // // Add HMD's pose tracking on top of current camera pose + // // Each game-title can decide whether to keep this functionality here or (most likely) + // // move it somewhere else. - Quat q = m_viewParams.rotation; - Vec3 pos = m_viewParams.position; - Vec3 p = Vec3(ZERO); + // Quat q = m_viewParams.rotation; + // Vec3 pos = m_viewParams.position; + // Vec3 p = Vec3(ZERO); - Matrix34 viewMtx(q); - viewMtx.SetTranslation(pos + p); - m_camera.SetMatrix(viewMtx); + // Matrix34 viewMtx(q); + // viewMtx.SetTranslation(pos + p); + // m_camera.SetMatrix(viewMtx); - m_camera.SetEntityRotation(m_viewParams.rotation); - m_camera.SetEntityPos(pos); - } - else - { - m_linkedTo = AZ::EntityId(0); - } + // m_camera.SetEntityRotation(m_viewParams.rotation); + // m_camera.SetEntityPos(pos); + //} + //else + //{ + // m_linkedTo = AZ::EntityId(0); + //} } //----------------------------------------------------------------------- diff --git a/Code/Legacy/CrySystem/ViewSystem/ViewSystem.cpp b/Code/Legacy/CrySystem/ViewSystem/ViewSystem.cpp index a82e78c08c..575c373dcd 100644 --- a/Code/Legacy/CrySystem/ViewSystem/ViewSystem.cpp +++ b/Code/Legacy/CrySystem/ViewSystem/ViewSystem.cpp @@ -253,7 +253,8 @@ void CViewSystem::Update(float frameTime) } } - m_pSystem->SetViewCamera(rCamera); + AZ_ErrorOnce("CryLegacy", false, "CryLegacy view system no longer available (CViewSystem::Update)"); + //m_pSystem->SetViewCamera(rCamera); } } @@ -557,23 +558,25 @@ void CViewSystem::SetOverrideCameraRotation(bool bOverride, Quat rotation) ////////////////////////////////////////////////////////////////////////// void CViewSystem::UpdateSoundListeners() { - assert(gEnv->IsEditor() && !gEnv->IsEditorGameMode()); + AZ_ErrorOnce("CryLegacy", false, "CryLegacy view system no longer available (CViewSystem::UpdateSoundListeners)"); - // In Editor we may want to control global listeners outside of the game view. - if (m_bControlsAudioListeners) - { - IView* const pActiveView = static_cast(GetActiveView()); - TViewMap::const_iterator Iter(m_views.begin()); - TViewMap::const_iterator const IterEnd(m_views.end()); + //assert(gEnv->IsEditor() && !gEnv->IsEditorGameMode()); - for (; Iter != IterEnd; ++Iter) - { - IView* const pView = Iter->second; - bool const bIsActive = (pView == pActiveView); - CCamera const& rCamera = bIsActive ? gEnv->pSystem->GetViewCamera() : pView->GetCamera(); - pView->UpdateAudioListener(rCamera.GetMatrix()); - } - } + //// In Editor we may want to control global listeners outside of the game view. + //if (m_bControlsAudioListeners) + //{ + // IView* const pActiveView = static_cast(GetActiveView()); + // TViewMap::const_iterator Iter(m_views.begin()); + // TViewMap::const_iterator const IterEnd(m_views.end()); + + // for (; Iter != IterEnd; ++Iter) + // { + // IView* const pView = Iter->second; + // bool const bIsActive = (pView == pActiveView); + // CCamera const& rCamera = bIsActive ? gEnv->pSystem->GetViewCamera() : pView->GetCamera(); + // pView->UpdateAudioListener(rCamera.GetMatrix()); + // } + //} } ////////////////////////////////////////////////////////////////// diff --git a/Gems/Atom/Component/DebugCamera/Code/Include/Atom/Component/DebugCamera/CameraComponent.h b/Gems/Atom/Component/DebugCamera/Code/Include/Atom/Component/DebugCamera/CameraComponent.h index d5c84c7441..fb9c543bca 100644 --- a/Gems/Atom/Component/DebugCamera/Code/Include/Atom/Component/DebugCamera/CameraComponent.h +++ b/Gems/Atom/Component/DebugCamera/Code/Include/Atom/Component/DebugCamera/CameraComponent.h @@ -103,6 +103,7 @@ namespace AZ void SetOrthographic(bool orthographic) override; void SetOrthographicHalfWidth(float halfWidth) override; void MakeActiveView() override; + bool IsActiveView() override; // RPI::WindowContextNotificationBus overrides... void OnViewportResized(uint32_t width, uint32_t height) override; diff --git a/Gems/Atom/Component/DebugCamera/Code/Source/CameraComponent.cpp b/Gems/Atom/Component/DebugCamera/Code/Source/CameraComponent.cpp index 330b6571f3..217cf0f061 100644 --- a/Gems/Atom/Component/DebugCamera/Code/Source/CameraComponent.cpp +++ b/Gems/Atom/Component/DebugCamera/Code/Source/CameraComponent.cpp @@ -250,6 +250,11 @@ namespace AZ // do nothing } + bool CameraComponent::IsActiveView() + { + return false; + } + void CameraComponent::OnViewportResized(uint32_t width, uint32_t height) { AZ_UNUSED(width) diff --git a/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorPlugin.cpp b/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorPlugin.cpp index b318cea128..2a97bdfb92 100644 --- a/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorPlugin.cpp +++ b/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorPlugin.cpp @@ -23,6 +23,8 @@ #include #include +#include + using namespace AudioControls; @@ -148,18 +150,21 @@ void CAudioControlsEditorPlugin::ExecuteTrigger(const AZStd::string_view sTrigge Audio::AudioSystemRequestBus::BroadcastResult(ms_nAudioTriggerID, &Audio::AudioSystemRequestBus::Events::GetAudioTriggerID, sTriggerName.data()); if (ms_nAudioTriggerID != INVALID_AUDIO_CONTROL_ID) { + AZ::Transform activeCameraTm = AZ::Transform::CreateIdentity(); + EBUS_EVENT_RESULT(activeCameraTm, Camera::ActiveCameraRequestBus, GetActiveCameraTransform); + const AZ::Matrix3x4 cameraMatrix = AZ::Matrix3x4::CreateFromTransform(activeCameraTm); + Audio::SAudioRequest request; request.nFlags = Audio::eARF_PRIORITY_NORMAL; - const AZ::Matrix3x4 listenerTxfm = AZ::Matrix3x4::CreateIdentity(); - Audio::SAudioListenerRequestData requestData(listenerTxfm); + Audio::SAudioListenerRequestData requestData(cameraMatrix); requestData.oNewPosition.NormalizeForwardVec(); requestData.oNewPosition.NormalizeUpVec(); request.pData = &requestData; Audio::AudioSystemRequestBus::Broadcast(&Audio::AudioSystemRequestBus::Events::PushRequest, request); - ms_pIAudioProxy->SetPosition(listenerTxfm); + ms_pIAudioProxy->SetPosition(cameraMatrix); ms_pIAudioProxy->ExecuteTrigger(ms_nAudioTriggerID); } } diff --git a/Gems/Camera/Code/Source/CameraComponent.cpp b/Gems/Camera/Code/Source/CameraComponent.cpp index 04c245bc95..0b892b0367 100644 --- a/Gems/Camera/Code/Source/CameraComponent.cpp +++ b/Gems/Camera/Code/Source/CameraComponent.cpp @@ -103,6 +103,7 @@ namespace Camera ->Event("SetNearClipDistance", &CameraRequestBus::Events::SetNearClipDistance) ->Event("SetFarClipDistance", &CameraRequestBus::Events::SetFarClipDistance) ->Event("MakeActiveView", &CameraRequestBus::Events::MakeActiveView) + ->Event("IsActiveView", &CameraRequestBus::Events::IsActiveView) ->Event("IsOrthographic", &CameraRequestBus::Events::IsOrthographic) ->Event("SetOrthographic", &CameraRequestBus::Events::SetOrthographic) ->Event("GetOrthographicHalfWidth", &CameraRequestBus::Events::GetOrthographicHalfWidth) diff --git a/Gems/Camera/Code/Source/CameraComponentController.cpp b/Gems/Camera/Code/Source/CameraComponentController.cpp index bbe8235449..a81ef1c9ae 100644 --- a/Gems/Camera/Code/Source/CameraComponentController.cpp +++ b/Gems/Camera/Code/Source/CameraComponentController.cpp @@ -24,7 +24,7 @@ namespace Camera if (auto serializeContext = azrtti_cast(context)) { serializeContext->Class() - ->Version(3) + ->Version(4) ->Field("Orthographic", &CameraComponentConfig::m_orthographic) ->Field("Orthographic Half Width", &CameraComponentConfig::m_orthographicHalfWidth) ->Field("Field of View", &CameraComponentConfig::m_fov) @@ -51,6 +51,7 @@ namespace Camera ->Attribute(AZ::Edit::Attributes::Visibility, &CameraComponentConfig::GetOrthographicParameterVisibility) ->Attribute(AZ::Edit::Attributes::Min, 0.001f) ->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ::Edit::PropertyRefreshLevels::ValuesOnly) + ->DataElement(AZ::Edit::UIHandlers::Default, &CameraComponentConfig::m_fov, "Field of view", "Vertical field of view in degrees") ->Attribute(AZ::Edit::Attributes::Min, MIN_FOV) ->Attribute(AZ::Edit::Attributes::Suffix, " degrees") @@ -130,6 +131,11 @@ namespace Camera void CameraComponentController::DeactivateAtomView() { + if (!IsActiveView()) + { + return; + } + auto atomViewportRequests = AZ::Interface::Get(); if (atomViewportRequests) { @@ -413,6 +419,11 @@ namespace Camera void CameraComponentController::MakeActiveView() { + if (IsActiveView()) + { + return; + } + // Set Legacy Cry view, if it exists if (m_viewSystem) { @@ -433,6 +444,11 @@ namespace Camera CameraNotificationBus::Broadcast(&CameraNotificationBus::Events::OnActiveViewChanged, m_entityId); } + bool CameraComponentController::IsActiveView() + { + return AZ::RPI::ViewportContextNotificationBus::Handler::BusIsConnected(); + } + void CameraComponentController::OnTransformChanged([[maybe_unused]] const AZ::Transform& local, const AZ::Transform& world) { if (m_updatingTransformFromEntity) @@ -459,6 +475,17 @@ namespace Camera UpdateCamera(); } + void CameraComponentController::OnViewportDefaultViewChanged(AZ::RPI::ViewPtr view) + { + if (m_atomCamera != view) + { + // Note that when disconnected from this bus, this signals that we are not the active view + // There is nothing else to do here: leave our view on the viewport context stack, don't need + // to update properties. The viewport context system should handle it all! + AZ::RPI::ViewportContextNotificationBus::Handler::BusDisconnect(); + } + } + AZ::RPI::ViewPtr CameraComponentController::GetView() const { return m_atomCamera; diff --git a/Gems/Camera/Code/Source/CameraComponentController.h b/Gems/Camera/Code/Source/CameraComponentController.h index c004dbe6ec..3d7844e6ac 100644 --- a/Gems/Camera/Code/Source/CameraComponentController.h +++ b/Gems/Camera/Code/Source/CameraComponentController.h @@ -69,9 +69,6 @@ namespace Camera CameraComponentController() = default; explicit CameraComponentController(const CameraComponentConfig& config); - void ActivateAtomView(); - void DeactivateAtomView(); - // Controller interface static void Reflect(AZ::ReflectContext* context); static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required); @@ -107,12 +104,14 @@ namespace Camera void SetOrthographicHalfWidth(float halfWidth) override; void MakeActiveView() override; + bool IsActiveView() override; // AZ::TransformNotificationBus::Handler interface void OnTransformChanged(const AZ::Transform& local, const AZ::Transform& world) override; // AZ::RPI::ViewportContextNotificationBus::Handler interface void OnViewportSizeChanged(AzFramework::WindowSize size) override; + void OnViewportDefaultViewChanged(AZ::RPI::ViewPtr view) override; // AZ::RPI::ViewProviderBus::Handler interface AZ::RPI::ViewPtr GetView() const override; @@ -120,6 +119,8 @@ namespace Camera private: AZ_DISABLE_COPY(CameraComponentController); + void ActivateAtomView(); + void DeactivateAtomView(); void UpdateCamera(); void SetupAtomAuxGeom(AZ::RPI::ViewportContextPtr viewportContext); diff --git a/Gems/Camera/Code/Source/CameraGem.cpp b/Gems/Camera/Code/Source/CameraGem.cpp index 11da0310bd..7efb09a59c 100644 --- a/Gems/Camera/Code/Source/CameraGem.cpp +++ b/Gems/Camera/Code/Source/CameraGem.cpp @@ -10,6 +10,7 @@ #include #include "CameraComponent.h" +#include "CameraSystemComponent.h" #if defined(CAMERA_EDITOR) #include "CameraEditorSystemComponent.h" @@ -31,6 +32,7 @@ namespace Camera { m_descriptors.insert(m_descriptors.end(), { Camera::CameraComponent::CreateDescriptor(), + Camera::CameraSystemComponent::CreateDescriptor(), #if defined(CAMERA_EDITOR) CameraEditorSystemComponent::CreateDescriptor(), @@ -55,6 +57,7 @@ namespace Camera AZ::ComponentTypeList GetRequiredSystemComponents() const override { return AZ::ComponentTypeList { + azrtti_typeid(), #if defined(CAMERA_EDITOR) azrtti_typeid(), #endif // CAMERA_EDITOR diff --git a/Gems/Camera/Code/Source/CameraSystemComponent.cpp b/Gems/Camera/Code/Source/CameraSystemComponent.cpp new file mode 100644 index 0000000000..1202e29e20 --- /dev/null +++ b/Gems/Camera/Code/Source/CameraSystemComponent.cpp @@ -0,0 +1,128 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include "CameraSystemComponent.h" + +#include +#include + +#include +#include + +namespace Camera +{ + void CameraSystemComponent::Reflect(AZ::ReflectContext* context) + { + if (AZ::SerializeContext* serializeContext = azrtti_cast(context)) + { + serializeContext->Class() + ->Version(1) + ; + } + } + + void CameraSystemComponent::Activate() + { + CameraSystemRequestBus::Handler::BusConnect(); + ActiveCameraRequestBus::Handler::BusConnect(); + CameraNotificationBus::Handler::BusConnect(); + } + + void CameraSystemComponent::Deactivate() + { + CameraSystemRequestBus::Handler::BusDisconnect(); + ActiveCameraRequestBus::Handler::BusDisconnect(); + CameraNotificationBus::Handler::BusDisconnect(); + } + + AZ::EntityId CameraSystemComponent::GetActiveCamera() + { + return m_activeView; + } + + const AZ::Transform& CameraSystemComponent::GetActiveCameraTransform() + { + if (m_activeView.IsValid()) + { + AZ::TransformBus::EventResult(m_activeViewProperties.transform, m_activeView, &AZ::TransformBus::Events::GetWorldTM); + } + else + { + // In editor, invalid entity ID for the active view denotes the "default editor camera" + // In game, this is an impossible state and if we reached here, we'll likely fail somehow... + m_activeViewProperties.transform = AZ::Transform::CreateIdentity(); + + using namespace AZ::RPI; + if (auto viewSystem = ViewportContextRequests::Get()) + { + if (auto view = viewSystem->GetCurrentView(viewSystem->GetDefaultViewportContextName())) + { + m_activeViewProperties.transform = view->GetCameraTransform(); + } + } + } + + return m_activeViewProperties.transform; + } + + const Configuration& CameraSystemComponent::GetActiveCameraConfiguration() + { + if (m_activeView.IsValid()) + { + CameraRequestBus::EventResult(m_activeViewProperties.configuration, m_activeView, &CameraRequestBus::Events::GetCameraConfiguration); + } + else + { + auto& cfg = m_activeViewProperties.configuration; + cfg = Configuration(); + + // In editor, invalid entity ID for the active view denotes the "default editor camera" + // In game, this is an impossible state and if we reached here, we'll likely fail somehow... + using namespace AZ::RPI; + if (auto viewSystem = ViewportContextRequests::Get()) + { + if (auto view = viewSystem->GetCurrentView(viewSystem->GetDefaultViewportContextName())) + { + const auto& viewToClip = view->GetViewToClipMatrix(); + cfg.m_fovRadians = AZ::GetPerspectiveMatrixFOV(viewToClip); + + // A = f / (n - f) + // B = n * f / (n - f) + // Then... + // B / A + // = (n * f / (n - f)) / (f / (n - f)) + // = (n * f) / (f) + // = n + // and... + // n * f / (n - f) = B + // n * ((n - f) / f)^-1 = B + // n * (n/f - 1)^-1 = B + // (n/f - 1)^-1 = B/n + // n/f - 1 = n/B + // f = n/(n/B + 1) + const float A = viewToClip.GetElement(2, 2); + const float B = viewToClip.GetElement(2, 3); + cfg.m_nearClipDistance = B / A; + cfg.m_farClipDistance = cfg.m_nearClipDistance / (cfg.m_nearClipDistance / B + 1.f); + + // NB: assumes reversed depth! + AZStd::swap(cfg.m_farClipDistance, cfg.m_nearClipDistance); + + // No idea what to do here. Seems to be unused? + cfg.m_frustumWidth = cfg.m_frustumHeight = 1.0f; + } + } + } + + return m_activeViewProperties.configuration; + } + + void CameraSystemComponent::OnActiveViewChanged(const AZ::EntityId& activeView) + { + m_activeView = activeView; + } +} // namespace Camera diff --git a/Gems/Camera/Code/Source/CameraSystemComponent.h b/Gems/Camera/Code/Source/CameraSystemComponent.h new file mode 100644 index 0000000000..726975ff9d --- /dev/null +++ b/Gems/Camera/Code/Source/CameraSystemComponent.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ +#pragma once + +#include + +#include + +namespace Camera +{ + class CameraSystemComponent + : public AZ::Component + , private CameraSystemRequestBus::Handler + , private ActiveCameraRequestBus::Handler + , private CameraNotificationBus::Handler + { + public: + AZ_COMPONENT(CameraSystemComponent, "{5DF8DB49-6430-4718-9417-85321596EDA5}"); + static void Reflect(AZ::ReflectContext* context); + + CameraSystemComponent() = default; + ~CameraSystemComponent() override = default; + + ////////////////////////////////////////////////////////////////////////// + // AZ::Component + void Activate() override; + void Deactivate() override; + ////////////////////////////////////////////////////////////////////////// + + private: + ////////////////////////////////////////////////////////////////////////// + // CameraSystemRequestBus + AZ::EntityId GetActiveCamera() override; + ////////////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////////////////// + // ActiveCameraRequestBus + const AZ::Transform& GetActiveCameraTransform() override; + const Configuration& GetActiveCameraConfiguration() override; + ////////////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////////////////// + // CameraNotificationBus + void OnActiveViewChanged(const AZ::EntityId&) override; + ////////////////////////////////////////////////////////////////////////// + + struct CameraProperties + { + AZ::Transform transform; + Configuration configuration; + }; + + AZ::EntityId m_activeView; + CameraProperties m_activeViewProperties; + }; +} diff --git a/Gems/Camera/Code/Source/EditorCameraComponent.cpp b/Gems/Camera/Code/Source/EditorCameraComponent.cpp index 14e8e46e72..4ebec334ec 100644 --- a/Gems/Camera/Code/Source/EditorCameraComponent.cpp +++ b/Gems/Camera/Code/Source/EditorCameraComponent.cpp @@ -38,40 +38,24 @@ namespace Camera EditorCameraComponentBase::Activate(); AzFramework::EntityDebugDisplayEventBus::Handler::BusConnect(GetEntityId()); - EditorCameraNotificationBus::Handler::BusConnect(); EditorCameraViewRequestBus::Handler::BusConnect(GetEntityId()); - - AZ::EntityId currentViewEntity; - EditorCameraRequests::Bus::BroadcastResult(currentViewEntity, &EditorCameraRequests::GetCurrentViewEntityId); - if (currentViewEntity == GetEntityId()) - { - m_controller.ActivateAtomView(); - m_isActiveEditorCamera = true; - } } void EditorCameraComponent::Deactivate() { - if (m_isActiveEditorCamera) - { - m_controller.DeactivateAtomView(); - m_isActiveEditorCamera = false; - } - EditorCameraViewRequestBus::Handler::BusDisconnect(GetEntityId()); - EditorCameraNotificationBus::Handler::BusDisconnect(); AzFramework::EntityDebugDisplayEventBus::Handler::BusDisconnect(); EditorCameraComponentBase::Deactivate(); } AZ::u32 EditorCameraComponent::OnConfigurationChanged() { - bool isActiveEditorCamera = m_isActiveEditorCamera; + bool isActiveEditorCamera = m_controller.IsActiveView(); AZ::u32 configurationHash = EditorCameraComponentBase::OnConfigurationChanged(); // If we were the active editor camera before, ensure we get reactivated after our controller gets disabled then re-enabled if (isActiveEditorCamera) { - EditorCameraRequests::Bus::Broadcast(&EditorCameraRequests::SetViewFromEntityPerspective, GetEntityId()); + m_controller.MakeActiveView(); } return configurationHash; } @@ -139,25 +123,6 @@ namespace Camera } } - void EditorCameraComponent::OnViewportViewEntityChanged([[maybe_unused]] const AZ::EntityId& newViewId) - { - if (newViewId == GetEntityId()) - { - if (!m_isActiveEditorCamera) - { - m_controller.ActivateAtomView(); - m_isActiveEditorCamera = true; - AzToolsFramework::PropertyEditorGUIMessages::Bus::Broadcast(&AzToolsFramework::PropertyEditorGUIMessages::RequestRefresh, AzToolsFramework::PropertyModificationRefreshLevel::Refresh_AttributesAndValues); - } - } - else if (m_isActiveEditorCamera) - { - m_controller.DeactivateAtomView(); - m_isActiveEditorCamera = false; - AzToolsFramework::PropertyEditorGUIMessages::Bus::Broadcast(&AzToolsFramework::PropertyEditorGUIMessages::RequestRefresh, AzToolsFramework::PropertyModificationRefreshLevel::Refresh_AttributesAndValues); - } - } - bool EditorCameraComponent::GetCameraState(AzFramework::CameraState& cameraState) { const CameraComponentConfig& config = m_controller.GetConfiguration(); diff --git a/Gems/Camera/Code/Source/EditorCameraComponent.h b/Gems/Camera/Code/Source/EditorCameraComponent.h index 095427a4a7..02b9d591d0 100644 --- a/Gems/Camera/Code/Source/EditorCameraComponent.h +++ b/Gems/Camera/Code/Source/EditorCameraComponent.h @@ -37,7 +37,6 @@ namespace Camera : public EditorCameraComponentBase , public EditorCameraViewRequestBus::Handler , private AzFramework::EntityDebugDisplayEventBus::Handler - , private EditorCameraNotificationBus::Handler { public: AZ_EDITOR_COMPONENT(EditorCameraComponent, EditorCameraComponentTypeId, AzToolsFramework::Components::EditorComponentBase); @@ -55,9 +54,6 @@ namespace Camera const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay) override; - /// EditorCameraNotificationBus::Handler interface - void OnViewportViewEntityChanged(const AZ::EntityId& newViewId) override; - /// EditorCameraViewRequestBus::Handler interface void ToggleCameraAsActiveView() override { OnPossessCameraButtonClicked(); } bool GetCameraState(AzFramework::CameraState& cameraState) override; @@ -67,7 +63,6 @@ namespace Camera AZ::Crc32 OnPossessCameraButtonClicked(); AZStd::string GetCameraViewButtonText() const; - bool m_isActiveEditorCamera = false; float m_frustumViewPercentLength = 1.f; AZ::Color m_frustumDrawColor = AzFramework::ViewportColors::HoverColor; }; diff --git a/Gems/Camera/Code/Source/ViewportCameraSelectorWindow.cpp b/Gems/Camera/Code/Source/ViewportCameraSelectorWindow.cpp index 9644aa76f9..0a12ec60e0 100644 --- a/Gems/Camera/Code/Source/ViewportCameraSelectorWindow.cpp +++ b/Gems/Camera/Code/Source/ViewportCameraSelectorWindow.cpp @@ -17,6 +17,7 @@ #include #include #include +#include namespace Qt { @@ -83,8 +84,8 @@ namespace Camera return m_cameraId < rhs.m_cameraId; } - CameraListModel::CameraListModel(QObject* myParent) - : QAbstractListModel(myParent) + CameraListModel::CameraListModel(ViewportCameraSelectorWindow* myParent) + : QAbstractListModel(myParent), m_parent(myParent) { m_cameraItems.push_back(AZ::EntityId()); CameraNotificationBus::Handler::BusConnect(); @@ -120,6 +121,18 @@ namespace Camera void CameraListModel::OnCameraAdded(const AZ::EntityId& cameraId) { + // If the camera entity is not an editor camera entity, don't add it to the list. + // This occurs when we're in simulation mode. + bool isEditorEntity = false; + AzToolsFramework::EditorEntityContextRequestBus::BroadcastResult( + isEditorEntity, + &AzToolsFramework::EditorEntityContextRequests::IsEditorEntity, + cameraId); + if (!isEditorEntity) + { + return; + } + beginInsertRows(QModelIndex(), rowCount(), rowCount()); m_cameraItems.push_back(cameraId); endInsertRows(); @@ -143,38 +156,38 @@ namespace Camera ////////////////////////////////////////////////////////////////////////// /// Maestro::EditorSequenceNotificationBus::Handler - void CameraListModel::OnSequenceSelected(const AZ::EntityId& sequenceEntityId) + void CameraListModel::OnSequenceSelected(const AZ::EntityId& ) { // Add or Remove the Sequence Camera option if a valid // sequence is selected in Track View. // Check to see if the Sequence Camera option is already present - bool found = false; - int index = 0; - for (const CameraListItem& cameraItem : m_cameraItems) - { - if (cameraItem.m_cameraName == m_sequenceCameraName) - { - found = true; - break; - } - ++index; - } + //bool found = false; + //int index = 0; + //for (const CameraListItem& cameraItem : m_cameraItems) + //{ + // if (cameraItem.m_cameraName == m_sequenceCameraName) + // { + // found = true; + // break; + // } + // ++index; + //} - // If it is present, but no sequence is selected, removed it. - if (found && !sequenceEntityId.IsValid()) - { - beginRemoveRows(QModelIndex(), index, index); - m_cameraItems.erase(m_cameraItems.begin() + index); - endRemoveRows(); - } - // If it is not present, and there is a sequence selected show it. - else if (!found && sequenceEntityId.IsValid()) - { - beginInsertRows(QModelIndex(), rowCount(), rowCount()); - m_cameraItems.push_back(CameraListItem(m_sequenceCameraName, sequenceEntityId)); - endInsertRows(); - } + //// If it is present, but no sequence is selected, removed it. + //if (found && !sequenceEntityId.IsValid()) + //{ + // beginRemoveRows(QModelIndex(), index, index); + // m_cameraItems.erase(m_cameraItems.begin() + index); + // endRemoveRows(); + //} + //// If it is not present, and there is a sequence selected show it. + //else if (!found && sequenceEntityId.IsValid()) + //{ + // beginInsertRows(QModelIndex(), rowCount(), rowCount()); + // m_cameraItems.push_back(CameraListItem(m_sequenceCameraName, sequenceEntityId)); + // endInsertRows(); + //} } QModelIndex CameraListModel::GetIndexForEntityId(const AZ::EntityId entityId) @@ -191,7 +204,7 @@ namespace Camera return index(row, 0); } - const char* CameraListModel::m_sequenceCameraName = "Sequence camera"; + //const char* CameraListModel::m_sequenceCameraName = "Sequence camera"; ViewportCameraSelectorWindow::ViewportCameraSelectorWindow(QWidget* parent) : m_ignoreViewportViewEntityChanged(false) @@ -242,8 +255,9 @@ namespace Camera if (current.row() != previous.row()) { // Lock camera editing when in sequence camera mode. - const AZStd::string& selectedCameraName = selectionModel()->currentIndex().data(Qt::DisplayRole).toString().toUtf8().data(); - bool lockCameraMovement = (selectedCameraName == CameraListModel::m_sequenceCameraName); + //const AZStd::string& selectedCameraName = selectionModel()->currentIndex().data(Qt::DisplayRole).toString().toUtf8().data(); + //bool lockCameraMovement = (selectedCameraName == CameraListModel::m_sequenceCameraName); + bool lockCameraMovement = false; QScopedValueRollback rb(m_ignoreViewportViewEntityChanged, true); AZ::EntityId entityId = selectionModel()->currentIndex().data(Qt::CameraIdRole).value(); @@ -298,14 +312,15 @@ namespace Camera void ViewportCameraSelectorWindow::OnCameraChanged(const AZ::EntityId& oldCameraEntityId, const AZ::EntityId& newCameraEntityId) { AZ_UNUSED(oldCameraEntityId); + AZ_UNUSED(newCameraEntityId); - // If the Sequence camera option is selected, respond to camera changes by selecting the camera used by the sequence. - const AZStd::string& selectedCameraName = selectionModel()->currentIndex().data(Qt::DisplayRole).toString().toUtf8().data(); - if (selectedCameraName == CameraListModel::m_sequenceCameraName) - { - QScopedValueRollback rb(m_ignoreViewportViewEntityChanged, true); - EditorCameraRequests::Bus::Broadcast(&EditorCameraRequests::SetViewAndMovementLockFromEntityPerspective, newCameraEntityId, true); - } + //// If the Sequence camera option is selected, respond to camera changes by selecting the camera used by the sequence. + //const AZStd::string& selectedCameraName = selectionModel()->currentIndex().data(Qt::DisplayRole).toString().toUtf8().data(); + //if (selectedCameraName == CameraListModel::m_sequenceCameraName) + //{ + // QScopedValueRollback rb(m_ignoreViewportViewEntityChanged, true); + // EditorCameraRequests::Bus::Broadcast(&EditorCameraRequests::SetViewAndMovementLockFromEntityPerspective, newCameraEntityId, true); + //} } // swallow mouse move events so we can disable sloppy selection diff --git a/Gems/Camera/Code/Source/ViewportCameraSelectorWindow_Internals.h b/Gems/Camera/Code/Source/ViewportCameraSelectorWindow_Internals.h index a681d049c3..74a7b292f3 100644 --- a/Gems/Camera/Code/Source/ViewportCameraSelectorWindow_Internals.h +++ b/Gems/Camera/Code/Source/ViewportCameraSelectorWindow_Internals.h @@ -46,6 +46,8 @@ namespace Camera AZ::EntityId m_sequenceId; }; + struct ViewportCameraSelectorWindow; + // holds a list of camera items struct CameraListModel : public QAbstractListModel @@ -54,9 +56,9 @@ namespace Camera { public: - static const char* m_sequenceCameraName; + //static const char* m_sequenceCameraName; - CameraListModel(QObject* myParent); + CameraListModel(ViewportCameraSelectorWindow* myParent); ~CameraListModel(); // QAbstractItemModel interface @@ -76,6 +78,7 @@ namespace Camera AZStd::vector m_cameraItems; AZ::EntityId m_sequenceCameraEntityId; bool m_sequenceCameraSelected; + ViewportCameraSelectorWindow* m_parent; }; struct ViewportCameraSelectorWindow diff --git a/Gems/Camera/Code/camera_files.cmake b/Gems/Camera/Code/camera_files.cmake index 295589e453..4848653121 100644 --- a/Gems/Camera/Code/camera_files.cmake +++ b/Gems/Camera/Code/camera_files.cmake @@ -1,7 +1,6 @@ # -# Copyright (c) Contributors to the Open 3D Engine Project. -# For complete copyright and license terms please see the LICENSE at the root of this distribution. -# +# Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. +# # SPDX-License-Identifier: Apache-2.0 OR MIT # # @@ -9,6 +8,8 @@ set(FILES camera_files.cmake Source/CameraComponent.cpp Source/CameraComponent.h + Source/CameraSystemComponent.cpp + Source/CameraSystemComponent.h Source/CameraComponentConverter.cpp Source/CameraComponentController.cpp Source/CameraComponentController.h diff --git a/Gems/PhysXDebug/Code/Source/SystemComponent.cpp b/Gems/PhysXDebug/Code/Source/SystemComponent.cpp index 96da22480d..97cb4f33d3 100644 --- a/Gems/PhysXDebug/Code/Source/SystemComponent.cpp +++ b/Gems/PhysXDebug/Code/Source/SystemComponent.cpp @@ -18,13 +18,13 @@ #include #include #include -#include #include #include #include #include #include +#include #include #include @@ -468,16 +468,25 @@ namespace PhysXDebug RenderBuffers(); } + AZ::Vector3 GetViewCameraPosition() + { + using namespace Camera; + + AZ::Transform tm = AZ::Transform::CreateIdentity(); + ActiveCameraRequestBus::BroadcastResult(tm, &ActiveCameraRequestBus::Events::GetActiveCameraTransform); + return tm.GetTranslation(); + } + void SystemComponent::UpdateColliderVisualizationByProximity() { if (auto* debug = AZ::Interface::Get(); UseEditorPhysicsScene() && m_settings.m_visualizeCollidersByProximity && debug != nullptr) { - const CCamera& camera = gEnv->pSystem->GetViewCamera(); + const AZ::Vector3& viewPos = GetViewCameraPosition(); const PhysX::Debug::ColliderProximityVisualization data( m_settings.m_visualizeCollidersByProximity, - LYVec3ToAZVec3(camera.GetPosition()), + viewPos, m_culling.m_boxSize * 0.5f); debug->UpdateColliderProximityVisualization(data); } @@ -663,8 +672,7 @@ namespace PhysXDebug AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::Physics); // Currently using the Cry view camera to support Editor, Game and Launcher modes. This will be updated in due course. - const CCamera& camera = gEnv->pSystem->GetViewCamera(); - AZ::Vector3 cameraTranslation = LYVec3ToAZVec3(camera.GetPosition()); + const AZ::Vector3 cameraTranslation = GetViewCameraPosition(); if (!cameraTranslation.IsClose(AZ::Vector3::CreateZero())) { From 2079b274c32eb7414327146bd27a5a5521564d8c Mon Sep 17 00:00:00 2001 From: Yuriy Toporovskyy Date: Wed, 4 Aug 2021 16:16:17 -0400 Subject: [PATCH 111/803] Fixup merge errors Signed-off-by: Yuriy Toporovskyy --- Code/Editor/EditorViewportWidget.cpp | 23 ++++++++++++++++------- Code/Editor/EditorViewportWidget.h | 2 +- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/Code/Editor/EditorViewportWidget.cpp b/Code/Editor/EditorViewportWidget.cpp index c77ef2ef3f..b4e844adb4 100644 --- a/Code/Editor/EditorViewportWidget.cpp +++ b/Code/Editor/EditorViewportWidget.cpp @@ -2898,16 +2898,25 @@ bool EditorViewportWidget::ShouldPreviewFullscreen() return false; } - // Doesn't work with split layout (TODO: figure out why and make it work) - if (layout->GetLayout() != EViewLayout::ET_Layout0) { return false; } + // Doesn't work with split layout + if (layout->GetLayout() != EViewLayout::ET_Layout0) + { + return false; + } // Not supported in VR - if (gSettings.bEnableGameModeVR) { return false; } + if (gSettings.bEnableGameModeVR) + { + return false; + } // If level not loaded, don't preview in fullscreen (preview shouldn't work at all without a level, but it does) if (auto ge = GetIEditor()->GetGameEngine()) { - if (!ge->IsLevelLoaded()) { return false; } + if (!ge->IsLevelLoaded()) + { + return false; + } } // Check 'ed_previewGameInFullscreen_once' @@ -2924,12 +2933,12 @@ bool EditorViewportWidget::ShouldPreviewFullscreen() void EditorViewportWidget::StartFullscreenPreview() { - AZ_Assert(!m_inFullscreenPreview, AZ_FUNCTION_SIGNATURE " - called when already in full screen preview"); + AZ_Assert(!m_inFullscreenPreview, "EditorViewportWidget::StartFullscreenPreview called when already in full screen preview"); m_inFullscreenPreview = true; // Pick the screen on which the main window lies to use as the screen for the full screen preview - QScreen* screen = MainWindow::instance()->screen(); - QRect screenGeometry = screen->geometry(); + const QScreen* screen = MainWindow::instance()->screen(); + const QRect screenGeometry = screen->geometry(); // Unparent this and show it, which turns it into a free floating window // Also set style to frameless and disable resizing by user diff --git a/Code/Editor/EditorViewportWidget.h b/Code/Editor/EditorViewportWidget.h index d17a8acb52..dabbbe95f6 100644 --- a/Code/Editor/EditorViewportWidget.h +++ b/Code/Editor/EditorViewportWidget.h @@ -232,7 +232,7 @@ private: double WidgetToViewportFactor() const; - bool ShouldPreviewFullscreen(); + bool ShouldPreviewFullscreen() const; void StartFullscreenPreview(); void StopFullscreenPreview(); From 9d9ce7cc3356e41eac4f3699158b497011f918f5 Mon Sep 17 00:00:00 2001 From: Yuriy Toporovskyy Date: Wed, 4 Aug 2021 16:20:03 -0400 Subject: [PATCH 112/803] Fixup merge errors Signed-off-by: Yuriy Toporovskyy --- Code/Editor/EditorViewportWidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Editor/EditorViewportWidget.cpp b/Code/Editor/EditorViewportWidget.cpp index b4e844adb4..2d5171a0e9 100644 --- a/Code/Editor/EditorViewportWidget.cpp +++ b/Code/Editor/EditorViewportWidget.cpp @@ -620,7 +620,7 @@ void EditorViewportWidget::OnEditorNotifyEvent(EEditorNotifyEvent event) if (m_renderViewport) { - m_renderViewport->GetControllerList()->SetEnabled(false); + m_renderViewport->SetInputProcessingEnabled(false); } } break; From 590de17343cb52e4f4cfcf93ce872d6c0cabf328 Mon Sep 17 00:00:00 2001 From: Yuriy Toporovskyy Date: Wed, 4 Aug 2021 16:35:10 -0400 Subject: [PATCH 113/803] Delete code which was only commented out Signed-off-by: Yuriy Toporovskyy --- Code/Editor/2DViewport.cpp | 3 +- Code/Editor/CryEdit.cpp | 67 +---------------- Code/Editor/EditorViewportWidget.cpp | 54 +------------- Code/Editor/Export/ExportManager.cpp | 6 -- Code/Editor/Objects/ObjectManager.cpp | 7 +- Code/Editor/ViewManager.cpp | 6 -- .../CrySystem/LevelSystem/LevelSystem.cpp | 10 --- .../LevelSystem/SpawnableLevelSystem.cpp | 10 --- .../CrySystem/ViewSystem/DebugCamera.cpp | 11 +-- Code/Legacy/CrySystem/ViewSystem/View.cpp | 71 ------------------- .../CrySystem/ViewSystem/ViewSystem.cpp | 19 ----- .../Source/ViewportCameraSelectorWindow.cpp | 43 ----------- .../ViewportCameraSelectorWindow_Internals.h | 3 - 13 files changed, 11 insertions(+), 299 deletions(-) diff --git a/Code/Editor/2DViewport.cpp b/Code/Editor/2DViewport.cpp index e231792329..838d30e0b3 100644 --- a/Code/Editor/2DViewport.cpp +++ b/Code/Editor/2DViewport.cpp @@ -952,7 +952,8 @@ void Q2DViewport::DrawViewerMarker(DisplayContext& dc) dc.SetColor(QColor(0, 0, 255)); // blue dc.DrawWireBox(-dim * noScale, dim * noScale); - float fov = 60; // GetIEditor()->GetSystem()->GetViewCamera().GetFov(); + constexpr float DefaultFov = 60.f; + float fov = DefaultFov; Vec3 q[4]; float dist = 30; diff --git a/Code/Editor/CryEdit.cpp b/Code/Editor/CryEdit.cpp index ec2df83ba7..96836c9f1e 100644 --- a/Code/Editor/CryEdit.cpp +++ b/Code/Editor/CryEdit.cpp @@ -3728,24 +3728,12 @@ void CCryEditApp::OnToolsPreferences() ////////////////////////////////////////////////////////////////////////// void CCryEditApp::OnSwitchToDefaultCamera() { - //CViewport* vp = GetIEditor()->GetViewManager()->GetSelectedViewport(); - //if (CRenderViewport* rvp = viewport_cast(vp)) - //{ - // rvp->SetDefaultCamera(); - //} } ////////////////////////////////////////////////////////////////////////// -void CCryEditApp::OnUpdateSwitchToDefaultCamera([[maybe_unused]] QAction* action) +void CCryEditApp::OnUpdateSwitchToDefaultCamera(QAction* action) { Q_ASSERT(action->isCheckable()); - //CViewport* pViewport = GetIEditor()->GetViewManager()->GetSelectedViewport(); - //if (false) // (CRenderViewport* rvp = viewport_cast(pViewport)) - //{ - // action->setEnabled(true); - // action->setChecked(rvp->IsDefaultCamera()); - //} - //else { action->setEnabled(false); } @@ -3754,39 +3742,12 @@ void CCryEditApp::OnUpdateSwitchToDefaultCamera([[maybe_unused]] QAction* action ////////////////////////////////////////////////////////////////////////// void CCryEditApp::OnSwitchToSequenceCamera() { - //CViewport* vp = GetIEditor()->GetViewManager()->GetSelectedViewport(); - //if (CRenderViewport* rvp = viewport_cast(vp)) - //{ - // rvp->SetSequenceCamera(); - //} } ////////////////////////////////////////////////////////////////////////// void CCryEditApp::OnUpdateSwitchToSequenceCamera(QAction* action) { Q_ASSERT(action->isCheckable()); - - //CViewport* pViewport = GetIEditor()->GetViewManager()->GetSelectedViewport(); - - //if (CRenderViewport* rvp = viewport_cast(pViewport)) - //{ - // bool enableAction = false; - - // // only enable if we're editing a sequence in Track View and have cameras in the level - // if (GetIEditor()->GetAnimation()->GetSequence()) - // { - - // AZ::EBusAggregateResults componentCameras; - // Camera::CameraBus::BroadcastResult(componentCameras, &Camera::CameraRequests::GetCameras); - - // const int numCameras = componentCameras.values.size(); - // enableAction = (numCameras > 0); - // } - - // action->setEnabled(enableAction); - // action->setChecked(rvp->IsSequenceCamera()); - //} - //else { action->setEnabled(false); } @@ -3795,32 +3756,12 @@ void CCryEditApp::OnUpdateSwitchToSequenceCamera(QAction* action) ////////////////////////////////////////////////////////////////////////// void CCryEditApp::OnSwitchToSelectedcamera() { - //CViewport* vp = GetIEditor()->GetViewManager()->GetSelectedViewport(); - //if (CRenderViewport* rvp = viewport_cast(vp)) - //{ - // rvp->SetSelectedCamera(); - //} } ////////////////////////////////////////////////////////////////////////// void CCryEditApp::OnUpdateSwitchToSelectedCamera(QAction* action) { Q_ASSERT(action->isCheckable()); - (void)action; - //AzToolsFramework::EntityIdList selectedEntityList; - //AzToolsFramework::ToolsApplicationRequests::Bus::BroadcastResult(selectedEntityList, &AzToolsFramework::ToolsApplicationRequests::GetSelectedEntities); - //AZ::EBusAggregateResults cameras; - //Camera::CameraBus::BroadcastResult(cameras, &Camera::CameraRequests::GetCameras); - //bool isCameraComponentSelected = selectedEntityList.size() > 0 ? AZStd::find(cameras.values.begin(), cameras.values.end(), *selectedEntityList.begin()) != cameras.values.end() : false; - - //CViewport* pViewport = GetIEditor()->GetViewManager()->GetSelectedViewport(); - //CRenderViewport* rvp = viewport_cast(pViewport); - //if (isCameraComponentSelected && rvp) - //{ - // action->setEnabled(true); - // action->setChecked(rvp->IsSelectedCamera()); - //} - //else { action->setEnabled(false); } @@ -3829,11 +3770,7 @@ void CCryEditApp::OnUpdateSwitchToSelectedCamera(QAction* action) ////////////////////////////////////////////////////////////////////////// void CCryEditApp::OnSwitchcameraNext() { - //CViewport* vp = GetIEditor()->GetActiveView(); - //if (CRenderViewport* rvp = viewport_cast(vp)) - //{ - // rvp->CycleCamera(); - //} + } ////////////////////////////////////////////////////////////////////////// diff --git a/Code/Editor/EditorViewportWidget.cpp b/Code/Editor/EditorViewportWidget.cpp index 2d5171a0e9..73b0483592 100644 --- a/Code/Editor/EditorViewportWidget.cpp +++ b/Code/Editor/EditorViewportWidget.cpp @@ -1524,33 +1524,6 @@ bool EditorViewportWidget::AddCameraMenuItems(QMenu* menu) customCameraMenu->addAction(cameraAction); } - // should this functionality be supported? You can already look through a camera entity - // in multiple different ways, and this additional method of doing so seems unneccessary and confusing - // (since it would select some arbitrary camera entity if there are multiple selected) - - //action = customCameraMenu->addAction(tr("Look through entity")); - //bool areAnyEntitiesSelected = false; - //AzToolsFramework::ToolsApplicationRequestBus::BroadcastResult(areAnyEntitiesSelected, &AzToolsFramework::ToolsApplicationRequests::AreAnyEntitiesSelected); - //action->setCheckable(areAnyEntitiesSelected || m_viewSourceType == ViewSourceType::AZ_Entity); - //action->setEnabled(areAnyEntitiesSelected || m_viewSourceType == ViewSourceType::AZ_Entity); - //action->setChecked(m_viewSourceType == ViewSourceType::AZ_Entity); - //connect(action, &QAction::triggered, this, [this](bool isChecked) - // { - // if (isChecked) - // { - // AzToolsFramework::EntityIdList selectedEntityList; - // AzToolsFramework::ToolsApplicationRequests::Bus::BroadcastResult(selectedEntityList, &AzToolsFramework::ToolsApplicationRequests::GetSelectedEntities); - // if (selectedEntityList.size()) - // { - // SetEntityAsCamera(*selectedEntityList.begin()); - // } - // } - // else - // { - // SetDefaultCamera(); - // } - // }); - return true; } @@ -2212,14 +2185,10 @@ bool EditorViewportWidget::HitTest(const QPoint& point, HitContext& hitInfo) } ////////////////////////////////////////////////////////////////////////// -bool EditorViewportWidget::IsBoundsVisible(const AABB& box) const +bool EditorViewportWidget::IsBoundsVisible(const AABB&) const { AZ_Assert(false, "Not supported"); - (void)box; return false; - - // If at least part of bbox is visible then its visible. - //return m_Camera.IsAABBVisible_F(AABB(box.min, box.max)); } ////////////////////////////////////////////////////////////////////////// @@ -2333,7 +2302,7 @@ float EditorViewportWidget::GetFOV() const { if (m_viewEntityId.IsValid()) { - float fov = 0.f; // AZ::RadToDeg(m_camFOV); + float fov = 0.f; Camera::CameraRequestBus::EventResult(fov, m_viewEntityId, &Camera::CameraComponentRequests::GetFovRadians); return fov; } @@ -2504,17 +2473,6 @@ void EditorViewportWidget::CycleCamera() SetFirstComponentCamera(); break; } - //case EditorViewportWidget::ViewSourceType::SequenceCamera: - //{ - // AZ_Error("EditorViewportWidget", false, "Legacy cameras no longer exist, unable to set sequence camera."); - // break; - //} - //case EditorViewportWidget::ViewSourceType::LegacyCamera: - //{ - // AZ_Warning("EditorViewportWidget", false, "Legacy cameras no longer exist, using first found component camera instead."); - // SetFirstComponentCamera(); - // break; - //} case EditorViewportWidget::ViewSourceType::CameraComponent: { AZ::EBusAggregateResults results; @@ -2533,12 +2491,6 @@ void EditorViewportWidget::CycleCamera() SetDefaultCamera(); break; } - //case EditorViewportWidget::ViewSourceType::AZ_Entity: - //{ - // // we may decide to have this iterate over just selected entities - // SetDefaultCamera(); - // break; - //} default: { SetDefaultCamera(); @@ -2889,7 +2841,7 @@ float EditorViewportSettings::AngleStep() const AZ_CVAR_EXTERNED(bool, ed_previewGameInFullscreen_once); -bool EditorViewportWidget::ShouldPreviewFullscreen() +bool EditorViewportWidget::ShouldPreviewFullscreen() const { CLayoutWnd* layout = GetIEditor()->GetViewManager()->GetLayout(); if (!layout) diff --git a/Code/Editor/Export/ExportManager.cpp b/Code/Editor/Export/ExportManager.cpp index f1ef96c8f8..0d114d5da8 100644 --- a/Code/Editor/Export/ExportManager.cpp +++ b/Code/Editor/Export/ExportManager.cpp @@ -662,12 +662,6 @@ bool CExportManager::ProcessObjectsForExport() GetIEditor()->GetAnimation()->SetRecording(false); GetIEditor()->GetAnimation()->SetPlaying(false); - //CViewport* vp = GetIEditor()->GetViewManager()->GetSelectedViewport(); - //if (CRenderViewport* rvp = viewport_cast(vp)) - //{ - // rvp->SetSequenceCamera(); - //} - int startFrame = 0; timeValue = startFrame * fpsTimeInterval; diff --git a/Code/Editor/Objects/ObjectManager.cpp b/Code/Editor/Objects/ObjectManager.cpp index 928a864cfb..33926c2174 100644 --- a/Code/Editor/Objects/ObjectManager.cpp +++ b/Code/Editor/Objects/ObjectManager.cpp @@ -1331,7 +1331,6 @@ void CObjectManager::FindDisplayableObjects(DisplayContext& dc, [[maybe_unused]] pDispayedViewObjects->SetSerialNumber(m_visibilitySerialNumber); // update viewport to be latest serial number - //const CCamera& camera = GetIEditor()->GetSystem()->GetViewCamera(); AABB bbox; bbox.min.zero(); bbox.max.zero(); @@ -1380,11 +1379,9 @@ void CObjectManager::FindDisplayableObjects(DisplayContext& dc, [[maybe_unused]] { CBaseObject* obj = m_visibleObjects[i]; - if (obj /* && obj->IsInCameraView(camera)*/) + if (obj) { - // Check if object is too far. - // float visRatio = obj->GetCameraVisRatio(camera); - if (/*visRatio > m_maxObjectViewDistRatio || */ (dc.flags & DISPLAY_SELECTION_HELPERS) || obj->IsSelected()) + if ((dc.flags & DISPLAY_SELECTION_HELPERS) || obj->IsSelected()) { pDispayedViewObjects->AddObject(obj); } diff --git a/Code/Editor/ViewManager.cpp b/Code/Editor/ViewManager.cpp index 88c4823249..4f39f862e4 100644 --- a/Code/Editor/ViewManager.cpp +++ b/Code/Editor/ViewManager.cpp @@ -81,7 +81,6 @@ CViewManager::CViewManager() else { AZ_Assert(false, "Non-Atom viewport no longer supported"); - //RegisterQtViewPaneWithName(GetIEditor(), "Perspective", LyViewPane::CategoryViewport, viewportOptions); } viewportOptions.viewportType = ET_ViewportMap; @@ -252,11 +251,6 @@ void CViewManager::SelectViewport(CViewport* pViewport) ////////////////////////////////////////////////////////////////////////// CViewport* CViewManager::GetGameViewport() const { - //if (CRenderViewport::GetPrimaryViewport()) - //{ - // return CRenderViewport::GetPrimaryViewport(); - //} - return GetViewport(ET_ViewportCamera);; } diff --git a/Code/Legacy/CrySystem/LevelSystem/LevelSystem.cpp b/Code/Legacy/CrySystem/LevelSystem/LevelSystem.cpp index 27dead077c..dc2526f213 100644 --- a/Code/Legacy/CrySystem/LevelSystem/LevelSystem.cpp +++ b/Code/Legacy/CrySystem/LevelSystem/LevelSystem.cpp @@ -618,12 +618,6 @@ ILevel* CLevelSystem::LoadLevelInternal(const char* _levelName) } } - // Reset the camera to (1,1,1) (not (0,0,0) which is the invalid/uninitialised state, - // to avoid the hack in the renderer to not show anything if the camera is at the origin). - //CCamera defaultCam; - //defaultCam.SetPosition(Vec3(1.0f)); - //m_pSystem->SetViewCamera(defaultCam); - m_pLoadingLevelInfo = pLevelInfo; OnLoadingStart(levelName); @@ -952,10 +946,6 @@ void CLevelSystem::UnloadLevel() oAudioRequestData.pData = &oAMData3; Audio::AudioSystemRequestBus::Broadcast(&Audio::AudioSystemRequestBus::Events::PushRequestBlocking, oAudioRequestData); - // Reset the camera to (0,0,0) which is the invalid/uninitialised state - //CCamera defaultCam; - //m_pSystem->SetViewCamera(defaultCam); - OnUnloadComplete(m_lastLevelName.c_str()); // -- kenzo: this will close all pack files for this level diff --git a/Code/Legacy/CrySystem/LevelSystem/SpawnableLevelSystem.cpp b/Code/Legacy/CrySystem/LevelSystem/SpawnableLevelSystem.cpp index 962469532d..f541ad1cec 100644 --- a/Code/Legacy/CrySystem/LevelSystem/SpawnableLevelSystem.cpp +++ b/Code/Legacy/CrySystem/LevelSystem/SpawnableLevelSystem.cpp @@ -268,12 +268,6 @@ namespace LegacyLevelSystem // This is a workaround until the replacement for GameEntityContext is done AzFramework::GameEntityContextEventBus::Broadcast(&AzFramework::GameEntityContextEventBus::Events::OnPreGameEntitiesStarted); - // Reset the camera to (1,1,1) (not (0,0,0) which is the invalid/uninitialised state, - // to avoid the hack in the renderer to not show anything if the camera is at the origin). - CCamera defaultCam; - defaultCam.SetPosition(Vec3(1.0f)); - //m_pSystem->SetViewCamera(defaultCam); - OnLoadingStart(levelName); auto pPak = gEnv->pCryPak; @@ -587,10 +581,6 @@ namespace LegacyLevelSystem oAudioRequestData.pData = &oAMData3; Audio::AudioSystemRequestBus::Broadcast(&Audio::AudioSystemRequestBus::Events::PushRequestBlocking, oAudioRequestData); - // Reset the camera to (0,0,0) which is the invalid/uninitialised state - //CCamera defaultCam; - //m_pSystem->SetViewCamera(defaultCam); - OnUnloadComplete(m_lastLevelName.c_str()); AzFramework::RootSpawnableInterface::Get()->ReleaseRootSpawnable(); diff --git a/Code/Legacy/CrySystem/ViewSystem/DebugCamera.cpp b/Code/Legacy/CrySystem/ViewSystem/DebugCamera.cpp index 8bf5c4eee3..1616816844 100644 --- a/Code/Legacy/CrySystem/ViewSystem/DebugCamera.cpp +++ b/Code/Legacy/CrySystem/ViewSystem/DebugCamera.cpp @@ -58,10 +58,10 @@ DebugCamera::~DebugCamera() /////////////////////////////////////////////////////////////////////////////// void DebugCamera::OnEnable() { - m_position = Vec3_Zero; // gEnv->pSystem->GetViewCamera().GetPosition(); + m_position = Vec3_Zero; m_moveInput = Vec3_Zero; - Ang3 cameraAngles = Ang3(ZERO); // Ang3(gEnv->pSystem->GetViewCamera().GetMatrix()); + Ang3 cameraAngles = Ang3(ZERO); m_cameraYaw = RAD2DEG(cameraAngles.z); m_cameraPitch = RAD2DEG(cameraAngles.x); m_view = Matrix33(Ang3(DEG2RAD(m_cameraPitch), 0.0f, DEG2RAD(m_cameraYaw))); @@ -126,13 +126,6 @@ void DebugCamera::Update() /////////////////////////////////////////////////////////////////////////////// void DebugCamera::PostUpdate() { - //if (m_cameraMode == DebugCamera::ModeOff) - //{ - // return; - //} - - //CCamera& camera = gEnv->pSystem->GetViewCamera(); - //camera.SetMatrix(Matrix34(m_view, m_position)); } /////////////////////////////////////////////////////////////////////////////// diff --git a/Code/Legacy/CrySystem/ViewSystem/View.cpp b/Code/Legacy/CrySystem/ViewSystem/View.cpp index 26f75ced76..610d6b4a14 100644 --- a/Code/Legacy/CrySystem/ViewSystem/View.cpp +++ b/Code/Legacy/CrySystem/ViewSystem/View.cpp @@ -59,77 +59,6 @@ void CView::Update(float frameTime, bool isActive) { (void)(frameTime, isActive); AZ_ErrorOnce("CryLegacy", false, "CryLegacy view system no longer available (CView::Update)"); - ////FIXME:some cameras may need to be updated always - //if (!isActive) - //{ - // return; - //} - - //if (m_azEntity) - //{ - // m_viewParams.SaveLast(); - - // CCamera* pSysCam = &m_pSystem->GetViewCamera(); - - // //process screen shaking - // ProcessShaking(frameTime); - - // //FIXME:to let the updateView implementation use the correct shakeVector - // m_viewParams.currentShakeShift = m_viewParams.rotation * m_viewParams.currentShakeShift; - - // m_viewParams.frameTime = frameTime; - // //update view position/rotation - // if (m_azEntity != nullptr) - // { - // auto entityTransform = m_azEntity->GetTransform(); - // if (entityTransform != nullptr) - // { - // AZ::Transform transform = entityTransform->GetWorldTM(); - // m_viewParams.position = AZVec3ToLYVec3(transform.GetTranslation()); - // m_viewParams.rotation = AZQuaternionToLYQuaternion(transform.GetRotation()); - // } - // } - - // ApplyFrameAdditiveAngles(m_viewParams.rotation); - - // const float fNearZ = gEnv->pSystem->GetIViewSystem()->GetDefaultZNear(); - - // //see if the view have to use a custom near clipping plane - // const float nearPlane = (m_viewParams.nearplane >= CAMERA_MIN_NEAR) ? (m_viewParams.nearplane) : fNearZ; - // const float farPlane = (m_viewParams.farplane > 0.f) ? m_viewParams.farplane : DEFAULT_FAR; - // float fov = (m_viewParams.fov < 0.001f) ? DEFAULT_FOV : m_viewParams.fov; - - // m_camera.SetFrustum(pSysCam->GetViewSurfaceX(), pSysCam->GetViewSurfaceZ(), fov, nearPlane, farPlane, pSysCam->GetPixelAspectRatio()); - - // //apply shake & set the view matrix - // m_viewParams.rotation *= m_viewParams.currentShakeQuat; - // m_viewParams.rotation.NormalizeSafe(); - // m_viewParams.position += m_viewParams.currentShakeShift; - - // // Blending between cameras needs to happen after Camera space rendering calculations have been applied - // // so that the m_viewParams.position is in World Space again - // m_viewParams.UpdateBlending(frameTime); - - // // [VR] specific - // // Add HMD's pose tracking on top of current camera pose - // // Each game-title can decide whether to keep this functionality here or (most likely) - // // move it somewhere else. - - // Quat q = m_viewParams.rotation; - // Vec3 pos = m_viewParams.position; - // Vec3 p = Vec3(ZERO); - - // Matrix34 viewMtx(q); - // viewMtx.SetTranslation(pos + p); - // m_camera.SetMatrix(viewMtx); - - // m_camera.SetEntityRotation(m_viewParams.rotation); - // m_camera.SetEntityPos(pos); - //} - //else - //{ - // m_linkedTo = AZ::EntityId(0); - //} } //----------------------------------------------------------------------- diff --git a/Code/Legacy/CrySystem/ViewSystem/ViewSystem.cpp b/Code/Legacy/CrySystem/ViewSystem/ViewSystem.cpp index 575c373dcd..28cf0eb07a 100644 --- a/Code/Legacy/CrySystem/ViewSystem/ViewSystem.cpp +++ b/Code/Legacy/CrySystem/ViewSystem/ViewSystem.cpp @@ -254,7 +254,6 @@ void CViewSystem::Update(float frameTime) } AZ_ErrorOnce("CryLegacy", false, "CryLegacy view system no longer available (CViewSystem::Update)"); - //m_pSystem->SetViewCamera(rCamera); } } @@ -559,24 +558,6 @@ void CViewSystem::SetOverrideCameraRotation(bool bOverride, Quat rotation) void CViewSystem::UpdateSoundListeners() { AZ_ErrorOnce("CryLegacy", false, "CryLegacy view system no longer available (CViewSystem::UpdateSoundListeners)"); - - //assert(gEnv->IsEditor() && !gEnv->IsEditorGameMode()); - - //// In Editor we may want to control global listeners outside of the game view. - //if (m_bControlsAudioListeners) - //{ - // IView* const pActiveView = static_cast(GetActiveView()); - // TViewMap::const_iterator Iter(m_views.begin()); - // TViewMap::const_iterator const IterEnd(m_views.end()); - - // for (; Iter != IterEnd; ++Iter) - // { - // IView* const pView = Iter->second; - // bool const bIsActive = (pView == pActiveView); - // CCamera const& rCamera = bIsActive ? gEnv->pSystem->GetViewCamera() : pView->GetCamera(); - // pView->UpdateAudioListener(rCamera.GetMatrix()); - // } - //} } ////////////////////////////////////////////////////////////////// diff --git a/Gems/Camera/Code/Source/ViewportCameraSelectorWindow.cpp b/Gems/Camera/Code/Source/ViewportCameraSelectorWindow.cpp index 0a12ec60e0..edd39772e0 100644 --- a/Gems/Camera/Code/Source/ViewportCameraSelectorWindow.cpp +++ b/Gems/Camera/Code/Source/ViewportCameraSelectorWindow.cpp @@ -158,36 +158,6 @@ namespace Camera /// Maestro::EditorSequenceNotificationBus::Handler void CameraListModel::OnSequenceSelected(const AZ::EntityId& ) { - // Add or Remove the Sequence Camera option if a valid - // sequence is selected in Track View. - - // Check to see if the Sequence Camera option is already present - //bool found = false; - //int index = 0; - //for (const CameraListItem& cameraItem : m_cameraItems) - //{ - // if (cameraItem.m_cameraName == m_sequenceCameraName) - // { - // found = true; - // break; - // } - // ++index; - //} - - //// If it is present, but no sequence is selected, removed it. - //if (found && !sequenceEntityId.IsValid()) - //{ - // beginRemoveRows(QModelIndex(), index, index); - // m_cameraItems.erase(m_cameraItems.begin() + index); - // endRemoveRows(); - //} - //// If it is not present, and there is a sequence selected show it. - //else if (!found && sequenceEntityId.IsValid()) - //{ - // beginInsertRows(QModelIndex(), rowCount(), rowCount()); - // m_cameraItems.push_back(CameraListItem(m_sequenceCameraName, sequenceEntityId)); - // endInsertRows(); - //} } QModelIndex CameraListModel::GetIndexForEntityId(const AZ::EntityId entityId) @@ -204,8 +174,6 @@ namespace Camera return index(row, 0); } - //const char* CameraListModel::m_sequenceCameraName = "Sequence camera"; - ViewportCameraSelectorWindow::ViewportCameraSelectorWindow(QWidget* parent) : m_ignoreViewportViewEntityChanged(false) { @@ -254,9 +222,6 @@ namespace Camera { if (current.row() != previous.row()) { - // Lock camera editing when in sequence camera mode. - //const AZStd::string& selectedCameraName = selectionModel()->currentIndex().data(Qt::DisplayRole).toString().toUtf8().data(); - //bool lockCameraMovement = (selectedCameraName == CameraListModel::m_sequenceCameraName); bool lockCameraMovement = false; QScopedValueRollback rb(m_ignoreViewportViewEntityChanged, true); @@ -313,14 +278,6 @@ namespace Camera { AZ_UNUSED(oldCameraEntityId); AZ_UNUSED(newCameraEntityId); - - //// If the Sequence camera option is selected, respond to camera changes by selecting the camera used by the sequence. - //const AZStd::string& selectedCameraName = selectionModel()->currentIndex().data(Qt::DisplayRole).toString().toUtf8().data(); - //if (selectedCameraName == CameraListModel::m_sequenceCameraName) - //{ - // QScopedValueRollback rb(m_ignoreViewportViewEntityChanged, true); - // EditorCameraRequests::Bus::Broadcast(&EditorCameraRequests::SetViewAndMovementLockFromEntityPerspective, newCameraEntityId, true); - //} } // swallow mouse move events so we can disable sloppy selection diff --git a/Gems/Camera/Code/Source/ViewportCameraSelectorWindow_Internals.h b/Gems/Camera/Code/Source/ViewportCameraSelectorWindow_Internals.h index 74a7b292f3..a4d662ef8b 100644 --- a/Gems/Camera/Code/Source/ViewportCameraSelectorWindow_Internals.h +++ b/Gems/Camera/Code/Source/ViewportCameraSelectorWindow_Internals.h @@ -55,9 +55,6 @@ namespace Camera , public Maestro::EditorSequenceNotificationBus::Handler { public: - - //static const char* m_sequenceCameraName; - CameraListModel(ViewportCameraSelectorWindow* myParent); ~CameraListModel(); From 62214567c1b0a7f3b8723b232fc499f0ccee2177 Mon Sep 17 00:00:00 2001 From: yuriy0 Date: Wed, 4 Aug 2021 16:38:57 -0400 Subject: [PATCH 114/803] Handle non-default viewport context Co-authored-by: Nicholas Van Sickle Signed-off-by: Yuriy Toporovskyy --- Code/Editor/EditorViewportWidget.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Code/Editor/EditorViewportWidget.cpp b/Code/Editor/EditorViewportWidget.cpp index 73b0483592..32b308ae9b 100644 --- a/Code/Editor/EditorViewportWidget.cpp +++ b/Code/Editor/EditorViewportWidget.cpp @@ -2382,7 +2382,10 @@ void EditorViewportWidget::SetDefaultCamera() ////////////////////////////////////////////////////////////////////////// AZ::RPI::ViewPtr EditorViewportWidget::GetCurrentAtomView() const { - auto atomViewportRequests = AZ::Interface::Get(); +if (m_renderViewport && m_renderViewport->GetViewportContext()) +{ + return m_viewportContext->GetDefaultView(); +} if (atomViewportRequests) { const AZ::Name contextName = atomViewportRequests->GetDefaultViewportContextName(); From 83099a7f5b44bda1827e02cdc1c45519491307de Mon Sep 17 00:00:00 2001 From: Yuriy Toporovskyy Date: Wed, 4 Aug 2021 16:42:59 -0400 Subject: [PATCH 115/803] Update mocks for ISystem changes Signed-off-by: Yuriy Toporovskyy --- Code/Legacy/CryCommon/Mocks/ISystemMock.h | 4 ---- .../Code/Tests/UI/LODSkinnedMeshTests.cpp | 14 -------------- 2 files changed, 18 deletions(-) diff --git a/Code/Legacy/CryCommon/Mocks/ISystemMock.h b/Code/Legacy/CryCommon/Mocks/ISystemMock.h index d891365696..e357af6d87 100644 --- a/Code/Legacy/CryCommon/Mocks/ISystemMock.h +++ b/Code/Legacy/CryCommon/Mocks/ISystemMock.h @@ -100,10 +100,6 @@ public: XmlNodeRef(const char*, bool)); MOCK_METHOD0(GetXmlUtils, IXmlUtils * ()); - MOCK_METHOD1(SetViewCamera, - void(CCamera & Camera)); - MOCK_METHOD0(GetViewCamera, - CCamera & ()); MOCK_METHOD1(IgnoreUpdates, void(bool bIgnore)); MOCK_METHOD1(SetIProcess, diff --git a/Gems/EMotionFX/Code/Tests/UI/LODSkinnedMeshTests.cpp b/Gems/EMotionFX/Code/Tests/UI/LODSkinnedMeshTests.cpp index 4b48936c88..9a11d1bd4b 100644 --- a/Gems/EMotionFX/Code/Tests/UI/LODSkinnedMeshTests.cpp +++ b/Gems/EMotionFX/Code/Tests/UI/LODSkinnedMeshTests.cpp @@ -46,18 +46,6 @@ namespace EMotionFX class LODSystemMock : public SystemMock { - public: - CCamera& GetViewCamera() override - { - return m_camera; - } - void SetViewCameraPosition(Vec3& vec) - { - m_camera.SetPosition(vec); - } - - protected: - CCamera m_camera; }; class LODSkinnedMeshColorFixture @@ -207,7 +195,6 @@ namespace EMotionFX EXPECT_EQ(actorInstance->GetLODLevel(), 0); Vec3 newVec{ 0,30,0 }; - m_data.m_system.SetViewCameraPosition(newVec); // Tick! AZ::TickBus::Broadcast(&AZ::TickBus::Events::OnTick, 0.0f, AZ::ScriptTimePoint{}); @@ -217,7 +204,6 @@ namespace EMotionFX EXPECT_EQ(actorInstance->GetLODLevel(), 3); newVec.y = 50; - m_data.m_system.SetViewCameraPosition(newVec); // Tick! AZ::TickBus::Broadcast(&AZ::TickBus::Events::OnTick, 0.0f, AZ::ScriptTimePoint{}); From ca96f0055d6b93e1939539de3640dfcc4b29fa5f Mon Sep 17 00:00:00 2001 From: Yuriy Toporovskyy Date: Wed, 4 Aug 2021 16:48:41 -0400 Subject: [PATCH 116/803] Remove TrackView-related camera logic TrackView uses 'normal' camera entities now Signed-off-by: Yuriy Toporovskyy --- .../Source/ViewportCameraSelectorWindow.cpp | 62 +------------------ .../ViewportCameraSelectorWindow_Internals.h | 29 +-------- 2 files changed, 3 insertions(+), 88 deletions(-) diff --git a/Gems/Camera/Code/Source/ViewportCameraSelectorWindow.cpp b/Gems/Camera/Code/Source/ViewportCameraSelectorWindow.cpp index edd39772e0..61f921d019 100644 --- a/Gems/Camera/Code/Source/ViewportCameraSelectorWindow.cpp +++ b/Gems/Camera/Code/Source/ViewportCameraSelectorWindow.cpp @@ -39,7 +39,6 @@ namespace Camera { CameraListItem::CameraListItem(const AZ::EntityId& cameraId) : m_cameraId(cameraId) - , m_sequenceId(AZ::EntityId()) { if (cameraId.IsValid()) { @@ -52,44 +51,24 @@ namespace Camera } } - // Used for a virtual camera that is really whatever camera is being - // used for a Track View Sequence. - CameraListItem::CameraListItem(const char* cameraName, const AZ::EntityId& sequenceId) - : m_cameraName(cameraName) - , m_sequenceId(sequenceId) - { - Maestro::SequenceComponentNotificationBus::Handler::BusConnect(sequenceId); - } - CameraListItem::~CameraListItem() { - Maestro::SequenceComponentNotificationBus::Handler::BusDisconnect(); - if (m_cameraId.IsValid()) { AZ::EntityBus::Handler::BusDisconnect(m_cameraId); } } - ////////////////////////////////////////////////////////////////////////// - /// Maestro::SequenceComponentNotificationBus::Handler - void CameraListItem::OnCameraChanged(const AZ::EntityId& oldCameraEntityId, const AZ::EntityId& newCameraEntityId) - { - AZ_UNUSED(oldCameraEntityId); - m_cameraId = newCameraEntityId; - } - bool CameraListItem::operator<(const CameraListItem& rhs) { return m_cameraId < rhs.m_cameraId; } - CameraListModel::CameraListModel(ViewportCameraSelectorWindow* myParent) - : QAbstractListModel(myParent), m_parent(myParent) + CameraListModel::CameraListModel(QWidget* myParent) + : QAbstractListModel(myParent) { m_cameraItems.push_back(AZ::EntityId()); CameraNotificationBus::Handler::BusConnect(); - Maestro::EditorSequenceNotificationBus::Handler::BusConnect(); } CameraListModel::~CameraListModel() @@ -97,7 +76,6 @@ namespace Camera // set the view entity id back to Invalid, thus enabling the editor camera EditorCameraRequests::Bus::Broadcast(&EditorCameraRequests::SetViewFromEntityPerspective, AZ::EntityId()); - Maestro::EditorSequenceNotificationBus::Handler::BusDisconnect(); CameraNotificationBus::Handler::BusDisconnect(); } @@ -154,12 +132,6 @@ namespace Camera } } - ////////////////////////////////////////////////////////////////////////// - /// Maestro::EditorSequenceNotificationBus::Handler - void CameraListModel::OnSequenceSelected(const AZ::EntityId& ) - { - } - QModelIndex CameraListModel::GetIndexForEntityId(const AZ::EntityId entityId) { int row = 0; @@ -203,17 +175,10 @@ namespace Camera // bus connections EditorCameraNotificationBus::Handler::BusConnect(); AzToolsFramework::EditorEntityContextNotificationBus::Handler::BusConnect(); - Maestro::EditorSequenceNotificationBus::Handler::BusConnect(); } ViewportCameraSelectorWindow::~ViewportCameraSelectorWindow() { - if (Maestro::SequenceComponentNotificationBus::Handler::BusIsConnected()) - { - Maestro::SequenceComponentNotificationBus::Handler::BusDisconnect(); - } - - Maestro::EditorSequenceNotificationBus::Handler::BusDisconnect(); AzToolsFramework::EditorEntityContextNotificationBus::Handler::BusDisconnect(); EditorCameraNotificationBus::Handler::BusDisconnect(); } @@ -257,29 +222,6 @@ namespace Camera setDisabled(false); } - ////////////////////////////////////////////////////////////////////////// - /// Maestro::EditorSequenceNotificationBus::Handler - void ViewportCameraSelectorWindow::OnSequenceSelected(const AZ::EntityId& sequenceEntityId) - { - // Connect to the Sequence Component Bus when a sequence is selected for OnCameraChanged. - if (Maestro::SequenceComponentNotificationBus::Handler::BusIsConnected()) - { - Maestro::SequenceComponentNotificationBus::Handler::BusDisconnect(); - } - if (sequenceEntityId.IsValid()) - { - Maestro::SequenceComponentNotificationBus::Handler::BusConnect(sequenceEntityId); - } - } - - ////////////////////////////////////////////////////////////////////////// - /// Maestro::SequenceComponentNotificationBus::Handler - void ViewportCameraSelectorWindow::OnCameraChanged(const AZ::EntityId& oldCameraEntityId, const AZ::EntityId& newCameraEntityId) - { - AZ_UNUSED(oldCameraEntityId); - AZ_UNUSED(newCameraEntityId); - } - // swallow mouse move events so we can disable sloppy selection void ViewportCameraSelectorWindow::mouseMoveEvent(QMouseEvent*) {} diff --git a/Gems/Camera/Code/Source/ViewportCameraSelectorWindow_Internals.h b/Gems/Camera/Code/Source/ViewportCameraSelectorWindow_Internals.h index a4d662ef8b..e75a820eec 100644 --- a/Gems/Camera/Code/Source/ViewportCameraSelectorWindow_Internals.h +++ b/Gems/Camera/Code/Source/ViewportCameraSelectorWindow_Internals.h @@ -9,8 +9,6 @@ #include #include -#include -#include #include #include #include @@ -25,37 +23,26 @@ namespace Camera // Each item in the list holds the camera's entityId and name struct CameraListItem : public AZ::EntityBus::Handler - , public Maestro::SequenceComponentNotificationBus::Handler { public: CameraListItem(const AZ::EntityId& cameraId); - // Used for a virtual camera that is really whatever camera is being - // used for a Track View Sequence. - CameraListItem(const char* cameraName, const AZ::EntityId& sequenceId); ~CameraListItem(); void OnEntityNameChanged(const AZStd::string& name) override { m_cameraName = name; } - ////////////////////////////////////////////////////////////////////////// - /// Maestro::SequenceComponentNotificationBus::Handler - void OnCameraChanged(const AZ::EntityId& oldCameraEntityId, const AZ::EntityId& newCameraEntityId) override; bool operator<(const CameraListItem& rhs); AZ::EntityId m_cameraId; AZStd::string m_cameraName; - AZ::EntityId m_sequenceId; }; - struct ViewportCameraSelectorWindow; - // holds a list of camera items struct CameraListModel : public QAbstractListModel , public CameraNotificationBus::Handler - , public Maestro::EditorSequenceNotificationBus::Handler { public: - CameraListModel(ViewportCameraSelectorWindow* myParent); + CameraListModel(QWidget* myParent); ~CameraListModel(); // QAbstractItemModel interface @@ -66,24 +53,18 @@ namespace Camera void OnCameraAdded(const AZ::EntityId& cameraId) override; void OnCameraRemoved(const AZ::EntityId& cameraId) override; - ////////////////////////////////////////////////////////////////////////// - /// Maestro::EditorSequenceNotificationBus::Handler - void OnSequenceSelected(const AZ::EntityId& sequenceEntityId) override; QModelIndex GetIndexForEntityId(const AZ::EntityId entityId); private: AZStd::vector m_cameraItems; AZ::EntityId m_sequenceCameraEntityId; bool m_sequenceCameraSelected; - ViewportCameraSelectorWindow* m_parent; }; struct ViewportCameraSelectorWindow : public QListView , public EditorCameraNotificationBus::Handler , public AzToolsFramework::EditorEntityContextNotificationBus::Handler - , public Maestro::EditorSequenceNotificationBus::Handler - , public Maestro::SequenceComponentNotificationBus::Handler { public: ViewportCameraSelectorWindow(QWidget* parent = nullptr); @@ -101,14 +82,6 @@ namespace Camera void OnStartPlayInEditor() override; void OnStopPlayInEditor() override; - ////////////////////////////////////////////////////////////////////////// - /// Maestro::EditorSequenceNotificationBus::Handler - void OnSequenceSelected(const AZ::EntityId& sequenceEntityId) override; - - ////////////////////////////////////////////////////////////////////////// - /// Maestro::SequenceComponentNotificationBus::Handler - void OnCameraChanged(const AZ::EntityId& oldCameraEntityId, const AZ::EntityId& newCameraEntityId) override; - void mouseMoveEvent(QMouseEvent*) override; void mouseDoubleClickEvent(QMouseEvent* event) override; QModelIndex moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers) override; From 70adac4f9678d762694b0c8fe0885ec3f984283e Mon Sep 17 00:00:00 2001 From: Yuriy Toporovskyy Date: Wed, 4 Aug 2021 16:59:50 -0400 Subject: [PATCH 117/803] Remove ed_useAtomNativeViewport - Legacy Cry viewport no longer supported Signed-off-by: Yuriy Toporovskyy --- Code/Editor/ViewManager.cpp | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/Code/Editor/ViewManager.cpp b/Code/Editor/ViewManager.cpp index 4f39f862e4..2ccbac09ed 100644 --- a/Code/Editor/ViewManager.cpp +++ b/Code/Editor/ViewManager.cpp @@ -32,12 +32,10 @@ #include -AZ_CVAR(bool, ed_useAtomNativeViewport, true, nullptr, AZ::ConsoleFunctorFlags::Null, "Use the new Atom-native Editor viewport (experimental, not yet stable"); - bool CViewManager::IsMultiViewportEnabled() { // Enable multi-viewport for legacy renderer, or if we're using the new fully Atom-native viewport - return ed_useAtomNativeViewport; + return true; } ////////////////////////////////////////////////////////////////////// @@ -74,14 +72,7 @@ CViewManager::CViewManager() RegisterQtViewPane(GetIEditor(), "Left", LyViewPane::CategoryViewport, viewportOptions); viewportOptions.viewportType = ET_ViewportCamera; - if (ed_useAtomNativeViewport) - { - RegisterQtViewPaneWithName(GetIEditor(), "Perspective", LyViewPane::CategoryViewport, viewportOptions); - } - else - { - AZ_Assert(false, "Non-Atom viewport no longer supported"); - } + RegisterQtViewPaneWithName(GetIEditor(), "Perspective", LyViewPane::CategoryViewport, viewportOptions); viewportOptions.viewportType = ET_ViewportMap; RegisterQtViewPane(GetIEditor(), "Map", LyViewPane::CategoryViewport, viewportOptions); From e82342dce0957b6068b994978ed0a36075f3b1bd Mon Sep 17 00:00:00 2001 From: Yuriy Toporovskyy Date: Wed, 4 Aug 2021 17:19:46 -0400 Subject: [PATCH 118/803] Delete code which was only commented out Signed-off-by: Yuriy Toporovskyy --- Code/Editor/TrackView/CommentNodeAnimator.cpp | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/Code/Editor/TrackView/CommentNodeAnimator.cpp b/Code/Editor/TrackView/CommentNodeAnimator.cpp index f01cbc84b4..ee01656938 100644 --- a/Code/Editor/TrackView/CommentNodeAnimator.cpp +++ b/Code/Editor/TrackView/CommentNodeAnimator.cpp @@ -159,21 +159,10 @@ void CCommentNodeAnimator::Render(CTrackViewAnimNode* pNode, [[maybe_unused]] co } } -Vec2 CCommentNodeAnimator::GetScreenPosFromNormalizedPos(const Vec2& unitPos) +Vec2 CCommentNodeAnimator::GetScreenPosFromNormalizedPos(const Vec2&) { - (void)unitPos; AZ_Error("CryLegacy", false, "CCommentNodeAnimator::GetScreenPosFromNormalizedPos not supported"); return Vec2(0, 0); - //const CCamera& cam = gEnv->pSystem->GetViewCamera(); - //float width = (float)cam.GetViewSurfaceX(); - //int height = cam.GetViewSurfaceZ(); - //float fAspectRatio = gSettings.viewports.fDefaultAspectRatio; - //float camWidth = height * fAspectRatio; - - //float x = 0.5f * width + 0.5f * camWidth * unitPos.x; - //float y = 0.5f * height * (1.f - unitPos.y); - - //return Vec2(x, y); } void CCommentNodeAnimator::DrawText(const char* szFontName, float fSize, const Vec2& unitPos, const ColorF col, const char* szText, int align) From bb36a4d40c42eb9dcb3c570119dbb65596159a41 Mon Sep 17 00:00:00 2001 From: Yuriy Toporovskyy Date: Wed, 4 Aug 2021 17:20:21 -0400 Subject: [PATCH 119/803] Style Signed-off-by: Yuriy Toporovskyy --- Code/Legacy/CrySystem/ViewSystem/View.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Code/Legacy/CrySystem/ViewSystem/View.cpp b/Code/Legacy/CrySystem/ViewSystem/View.cpp index 610d6b4a14..e1191f0a17 100644 --- a/Code/Legacy/CrySystem/ViewSystem/View.cpp +++ b/Code/Legacy/CrySystem/ViewSystem/View.cpp @@ -55,9 +55,8 @@ void CView::Release() } //------------------------------------------------------------------------ -void CView::Update(float frameTime, bool isActive) +void CView::Update([[maybe_unused]] float frameTime, [[maybe_unused]] bool isActive) { - (void)(frameTime, isActive); AZ_ErrorOnce("CryLegacy", false, "CryLegacy view system no longer available (CView::Update)"); } From bf361c2c13c9b8ec77dd855375ee79e76a04ff22 Mon Sep 17 00:00:00 2001 From: Yuriy Toporovskyy Date: Wed, 4 Aug 2021 17:20:45 -0400 Subject: [PATCH 120/803] Handle the case where a camera deactivates and the previous camera on the stack should become the active view Signed-off-by: Yuriy Toporovskyy --- .../Code/Source/CameraComponentController.cpp | 24 ++++++++++--------- .../Code/Source/CameraComponentController.h | 1 + 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/Gems/Camera/Code/Source/CameraComponentController.cpp b/Gems/Camera/Code/Source/CameraComponentController.cpp index a81ef1c9ae..a8b5b8992e 100644 --- a/Gems/Camera/Code/Source/CameraComponentController.cpp +++ b/Gems/Camera/Code/Source/CameraComponentController.cpp @@ -115,6 +115,13 @@ namespace Camera AZ_Assert(m_atomCamera, "Attempted to activate Atom camera before component activation"); const AZ::Name contextName = atomViewportRequests->GetDefaultViewportContextName(); + + // Connect to the bus the first time we activate the view + if (!AZ::RPI::ViewportContextNotificationBus::Handler::BusIsConnectedId(contextName)) + { + AZ::RPI::ViewportContextNotificationBus::Handler::BusConnect(contextName); + } + // Ensure the Atom camera is updated with our current transform state AZ::Transform localTransform; AZ::TransformBus::EventResult(localTransform, m_entityId, &AZ::TransformBus::Events::GetLocalTM); @@ -125,7 +132,6 @@ namespace Camera // Push the Atom camera after we make sure we're up-to-date with our component's transform to ensure the viewport reads the correct state UpdateCamera(); atomViewportRequests->PushView(contextName, m_atomCamera); - AZ::RPI::ViewportContextNotificationBus::Handler::BusConnect(contextName); } } @@ -140,7 +146,6 @@ namespace Camera if (atomViewportRequests) { const AZ::Name contextName = atomViewportRequests->GetDefaultViewportContextName(); - AZ::RPI::ViewportContextNotificationBus::Handler::BusDisconnect(contextName); atomViewportRequests->PopView(contextName, m_atomCamera); } } @@ -446,7 +451,7 @@ namespace Camera bool CameraComponentController::IsActiveView() { - return AZ::RPI::ViewportContextNotificationBus::Handler::BusIsConnected(); + return m_isActiveView; } void CameraComponentController::OnTransformChanged([[maybe_unused]] const AZ::Transform& local, const AZ::Transform& world) @@ -472,18 +477,15 @@ namespace Camera void CameraComponentController::OnViewportSizeChanged([[maybe_unused]] AzFramework::WindowSize size) { - UpdateCamera(); + if (IsActiveView()) + { + UpdateCamera(); + } } void CameraComponentController::OnViewportDefaultViewChanged(AZ::RPI::ViewPtr view) { - if (m_atomCamera != view) - { - // Note that when disconnected from this bus, this signals that we are not the active view - // There is nothing else to do here: leave our view on the viewport context stack, don't need - // to update properties. The viewport context system should handle it all! - AZ::RPI::ViewportContextNotificationBus::Handler::BusDisconnect(); - } + m_isActiveView = m_atomCamera == view; } AZ::RPI::ViewPtr CameraComponentController::GetView() const diff --git a/Gems/Camera/Code/Source/CameraComponentController.h b/Gems/Camera/Code/Source/CameraComponentController.h index 3d7844e6ac..923da65618 100644 --- a/Gems/Camera/Code/Source/CameraComponentController.h +++ b/Gems/Camera/Code/Source/CameraComponentController.h @@ -132,6 +132,7 @@ namespace Camera AZ::RPI::AuxGeomDrawPtr m_atomAuxGeom; AZ::Event::Handler m_onViewMatrixChanged; bool m_updatingTransformFromEntity = false; + bool m_isActiveView = false; // Cry view integration IView* m_view = nullptr; From 83e43dd517a06e82a1b2f8acb840316c6b68e750 Mon Sep 17 00:00:00 2001 From: Yuriy Toporovskyy Date: Wed, 4 Aug 2021 17:38:19 -0400 Subject: [PATCH 121/803] Re-use existing code Signed-off-by: Yuriy Toporovskyy --- .../Code/Source/CameraSystemComponent.cpp | 30 +++++-------------- 1 file changed, 7 insertions(+), 23 deletions(-) diff --git a/Gems/Camera/Code/Source/CameraSystemComponent.cpp b/Gems/Camera/Code/Source/CameraSystemComponent.cpp index 1202e29e20..7c7dac429d 100644 --- a/Gems/Camera/Code/Source/CameraSystemComponent.cpp +++ b/Gems/Camera/Code/Source/CameraSystemComponent.cpp @@ -10,6 +10,8 @@ #include #include +#include + #include #include @@ -87,30 +89,12 @@ namespace Camera { if (auto view = viewSystem->GetCurrentView(viewSystem->GetDefaultViewportContextName())) { - const auto& viewToClip = view->GetViewToClipMatrix(); - cfg.m_fovRadians = AZ::GetPerspectiveMatrixFOV(viewToClip); + AzFramework::CameraState cam; + AzFramework::SetCameraClippingVolumeFromPerspectiveFovMatrixRH(cam, view->GetViewToClipMatrix()); - // A = f / (n - f) - // B = n * f / (n - f) - // Then... - // B / A - // = (n * f / (n - f)) / (f / (n - f)) - // = (n * f) / (f) - // = n - // and... - // n * f / (n - f) = B - // n * ((n - f) / f)^-1 = B - // n * (n/f - 1)^-1 = B - // (n/f - 1)^-1 = B/n - // n/f - 1 = n/B - // f = n/(n/B + 1) - const float A = viewToClip.GetElement(2, 2); - const float B = viewToClip.GetElement(2, 3); - cfg.m_nearClipDistance = B / A; - cfg.m_farClipDistance = cfg.m_nearClipDistance / (cfg.m_nearClipDistance / B + 1.f); - - // NB: assumes reversed depth! - AZStd::swap(cfg.m_farClipDistance, cfg.m_nearClipDistance); + cfg.m_fovRadians = cam.m_fovOrZoom; + cfg.m_nearClipDistance = cam.m_nearClip; + cfg.m_farClipDistance = cam.m_farClip; // No idea what to do here. Seems to be unused? cfg.m_frustumWidth = cfg.m_frustumHeight = 1.0f; From b221ec3024c2486d1cccba3bbf80ce8de22fca05 Mon Sep 17 00:00:00 2001 From: Yuriy Toporovskyy Date: Thu, 5 Aug 2021 10:12:24 -0400 Subject: [PATCH 122/803] Merge fixup Signed-off-by: Yuriy Toporovskyy --- Gems/Camera/Code/camera_files.cmake | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Gems/Camera/Code/camera_files.cmake b/Gems/Camera/Code/camera_files.cmake index 4848653121..26769b071c 100644 --- a/Gems/Camera/Code/camera_files.cmake +++ b/Gems/Camera/Code/camera_files.cmake @@ -1,6 +1,7 @@ # -# Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. -# +# Copyright (c) Contributors to the Open 3D Engine Project. +# For complete copyright and license terms please see the LICENSE at the root of this distribution. +# # SPDX-License-Identifier: Apache-2.0 OR MIT # # From a85b97d9ac28cb666d2f6bff23496243609ab63a Mon Sep 17 00:00:00 2001 From: Yuriy Toporovskyy Date: Thu, 5 Aug 2021 10:19:16 -0400 Subject: [PATCH 123/803] Remove unused code Signed-off-by: Yuriy Toporovskyy --- Code/Editor/EditorViewportWidget.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Code/Editor/EditorViewportWidget.cpp b/Code/Editor/EditorViewportWidget.cpp index 32b308ae9b..22e6fb9803 100644 --- a/Code/Editor/EditorViewportWidget.cpp +++ b/Code/Editor/EditorViewportWidget.cpp @@ -1486,11 +1486,6 @@ bool EditorViewportWidget::AddCameraMenuItems(QMenu* menu) AZ::EBusAggregateResults getCameraResults; Camera::CameraBus::BroadcastResult(getCameraResults, &Camera::CameraRequests::GetCameras); - const int numCameras = getCameraResults.values.size(); - - // only enable if we're editing a sequence in Track View and have cameras in the level - //bool enableSequenceCameraMenu = (GetIEditor()->GetAnimation()->GetSequence() && numCameras); - QVector additionalCameras; additionalCameras.reserve(getCameraResults.values.size()); From ba33dd44334b417f82adccc85b1db2b97dc3b072 Mon Sep 17 00:00:00 2001 From: Yuriy Toporovskyy Date: Thu, 5 Aug 2021 10:27:24 -0400 Subject: [PATCH 124/803] Fix strange commit which was automatically created by Githubs 'Suggested Change' feature. Signed-off-by: Yuriy Toporovskyy --- Code/Editor/EditorViewportWidget.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/Code/Editor/EditorViewportWidget.cpp b/Code/Editor/EditorViewportWidget.cpp index 22e6fb9803..b205ca5b78 100644 --- a/Code/Editor/EditorViewportWidget.cpp +++ b/Code/Editor/EditorViewportWidget.cpp @@ -2377,14 +2377,9 @@ void EditorViewportWidget::SetDefaultCamera() ////////////////////////////////////////////////////////////////////////// AZ::RPI::ViewPtr EditorViewportWidget::GetCurrentAtomView() const { -if (m_renderViewport && m_renderViewport->GetViewportContext()) -{ - return m_viewportContext->GetDefaultView(); -} - if (atomViewportRequests) + if (m_renderViewport && m_renderViewport->GetViewportContext()) { - const AZ::Name contextName = atomViewportRequests->GetDefaultViewportContextName(); - return atomViewportRequests->GetCurrentView(contextName); + return m_renderViewport->GetViewportContext()->GetDefaultView(); } else { From 0d0d94f575dfed5f1cf8c83b0841017501cc42a6 Mon Sep 17 00:00:00 2001 From: Nemerle Date: Thu, 5 Aug 2021 16:46:38 +0200 Subject: [PATCH 125/803] Editor code: tidy up BOOLs,NULLs and overrides pt2. A few 'typedefs' replaced by 'using's This shouldn't have any functional changes at all, just c++17 modernization It's a part 2 of a split #2847 Signed-off-by: Nemerle --- Code/Editor/Lib/Tests/test_EditorUtils.cpp | 4 +- Code/Editor/Lib/Tests/test_Main.cpp | 2 +- Code/Editor/Objects/BaseObject.cpp | 60 ++++++------- Code/Editor/Objects/BaseObject.h | 16 ++-- Code/Editor/Objects/EntityObject.cpp | 50 +++++------ Code/Editor/Objects/EntityObject.h | 2 +- Code/Editor/Objects/Gizmo.h | 2 +- Code/Editor/Objects/GizmoManager.cpp | 2 +- Code/Editor/Objects/LineGizmo.cpp | 6 +- Code/Editor/Objects/ObjectLoader.cpp | 14 +-- Code/Editor/Objects/ObjectLoader.h | 2 +- Code/Editor/Objects/ObjectManager.cpp | 90 +++++++++---------- Code/Editor/Objects/SelectionGroup.cpp | 2 +- Code/Editor/Objects/TrackGizmo.cpp | 2 +- .../Platform/Windows/Util/Mailer_Windows.cpp | 8 +- .../SandboxIntegration.cpp | 2 +- .../ComponentPaletteWindow.cpp | 2 +- .../EditorCommon/DockTitleBarWidget.cpp | 16 ++-- Code/Editor/Plugins/FFMPEGPlugin/main.cpp | 2 +- .../PlatformSettings_Android.cpp | 4 +- .../ProjectSettingsTool/Validators.cpp | 2 +- 21 files changed, 145 insertions(+), 145 deletions(-) diff --git a/Code/Editor/Lib/Tests/test_EditorUtils.cpp b/Code/Editor/Lib/Tests/test_EditorUtils.cpp index 59deb178a9..3556757ae3 100644 --- a/Code/Editor/Lib/Tests/test_EditorUtils.cpp +++ b/Code/Editor/Lib/Tests/test_EditorUtils.cpp @@ -23,12 +23,12 @@ namespace EditorUtilsTest BusConnect(); } - ~WarningDetector() + ~WarningDetector() override { BusDisconnect(); } - virtual bool OnWarning(const char* /*window*/, const char* /*message*/) override + bool OnWarning(const char* /*window*/, const char* /*message*/) override { m_gotWarning = true; return true; diff --git a/Code/Editor/Lib/Tests/test_Main.cpp b/Code/Editor/Lib/Tests/test_Main.cpp index a30afb0b7c..4faf68181e 100644 --- a/Code/Editor/Lib/Tests/test_Main.cpp +++ b/Code/Editor/Lib/Tests/test_Main.cpp @@ -17,7 +17,7 @@ class EditorLibTestEnvironment : public AZ::Test::ITestEnvironment { public: - virtual ~EditorLibTestEnvironment() {} + ~EditorLibTestEnvironment() override {} protected: void SetupEnvironment() override diff --git a/Code/Editor/Objects/BaseObject.cpp b/Code/Editor/Objects/BaseObject.cpp index c13c5932b0..482055d7ed 100644 --- a/Code/Editor/Objects/BaseObject.cpp +++ b/Code/Editor/Objects/BaseObject.cpp @@ -57,12 +57,12 @@ public: CUndoBaseObject(CBaseObject* pObj, const char* undoDescription); protected: - virtual int GetSize() { return sizeof(*this); } - virtual QString GetDescription() { return m_undoDescription; }; - virtual QString GetObjectName(); + int GetSize() override { return sizeof(*this); } + QString GetDescription() override { return m_undoDescription; }; + QString GetObjectName() override; - virtual void Undo(bool bUndo); - virtual void Redo(); + void Undo(bool bUndo) override; + void Redo() override; protected: QString m_undoDescription; @@ -81,12 +81,12 @@ public: CUndoBaseObjectMinimal(CBaseObject* obj, const char* undoDescription, int flags); protected: - virtual int GetSize() { return sizeof(*this); } - virtual QString GetDescription() { return m_undoDescription; }; - virtual QString GetObjectName(); + int GetSize() override { return sizeof(*this); } + QString GetDescription() override { return m_undoDescription; }; + QString GetObjectName() override; - virtual void Undo(bool bUndo); - virtual void Redo(); + void Undo(bool bUndo) override; + void Redo() override; private: struct StateStruct @@ -119,7 +119,7 @@ public: , m_bKeepPos(bKeepPos) , m_bAttach(bAttach) {} - virtual void Undo([[maybe_unused]] bool bUndo) override + void Undo([[maybe_unused]] bool bUndo) override { if (m_bAttach) { @@ -131,7 +131,7 @@ public: } } - virtual void Redo() override + void Redo() override { if (m_bAttach) { @@ -167,8 +167,8 @@ private: } } - virtual int GetSize() { return sizeof(CUndoAttachBaseObject); } - virtual QString GetDescription() { return "Attachment Changed"; } + int GetSize() override { return sizeof(CUndoAttachBaseObject); } + QString GetDescription() override { return "Attachment Changed"; } GUID m_attachedObjectGUID; GUID m_parentObjectGUID; @@ -184,7 +184,7 @@ CUndoBaseObject::CUndoBaseObject(CBaseObject* obj, const char* undoDescription) m_undoDescription = undoDescription; m_guid = obj->GetId(); - m_redo = 0; + m_redo = nullptr; m_undo = XmlHelpers::CreateXmlNode("Undo"); CObjectArchive ar(GetIEditor()->GetObjectManager(), m_undo, false); ar.bUndo = true; @@ -355,7 +355,7 @@ void CObjectCloneContext::AddClone(CBaseObject* pFromObject, CBaseObject* pToObj ////////////////////////////////////////////////////////////////////////// CBaseObject* CObjectCloneContext::FindClone(CBaseObject* pFromObject) { - CBaseObject* pTarget = stl::find_in_map(m_objectsMap, pFromObject, (CBaseObject*) NULL); + CBaseObject* pTarget = stl::find_in_map(m_objectsMap, pFromObject, (CBaseObject*) nullptr); return pTarget; } @@ -426,7 +426,7 @@ bool CBaseObject::Init([[maybe_unused]] IEditor* ie, CBaseObject* prev, [[maybe_ { SetFlags(m_flags & (~OBJFLAG_DELETED)); - if (prev != 0) + if (prev != nullptr) { SetUniqueName(prev->GetName()); SetLocalTM(prev->GetPos(), prev->GetRotation(), prev->GetScale()); @@ -457,7 +457,7 @@ CBaseObject::~CBaseObject() for (Childs::iterator c = m_childs.begin(); c != m_childs.end(); c++) { CBaseObject* child = *c; - child->m_parent = 0; + child->m_parent = nullptr; } m_childs.clear(); } @@ -470,10 +470,10 @@ void CBaseObject::Done() // From children DetachAll(); - SetLookAt(0); + SetLookAt(nullptr); if (m_lookatSource) { - m_lookatSource->SetLookAt(0); + m_lookatSource->SetLookAt(nullptr); } SetFlags(m_flags | OBJFLAG_DELETED); @@ -1730,7 +1730,7 @@ bool CBaseObject::IntersectRayBounds(const Ray& ray) ////////////////////////////////////////////////////////////////////////// namespace { - typedef std::pair Edge2D; + using Edge2D = std::pair; } bool IsIncludePointsInConvexHull(Edge2D* pEdgeArray0, int nEdgeArray0Size, Edge2D* pEdgeArray1, int nEdgeArray1Size) { @@ -2065,7 +2065,7 @@ void CBaseObject::GetAllChildren(TBaseObjects& outAllChildren, CBaseObject* pObj for (int i = 0, iChildCount(pBaseObj->GetChildCount()); i < iChildCount; ++i) { CBaseObject* pChild = pBaseObj->GetChild(i); - if (pChild == NULL) + if (pChild == nullptr) { continue; } @@ -2081,7 +2081,7 @@ void CBaseObject::GetAllChildren(DynArray< _smart_ptr >& outAllChil for (int i = 0, iChildCount(pBaseObj->GetChildCount()); i < iChildCount; ++i) { CBaseObject* pChild = pBaseObj->GetChild(i); - if (pChild == NULL) + if (pChild == nullptr) { continue; } @@ -2097,7 +2097,7 @@ void CBaseObject::GetAllChildren(CSelectionGroup& outAllChildren, CBaseObject* p for (int i = 0, iChildCount(pBaseObj->GetChildCount()); i < iChildCount; ++i) { CBaseObject* pChild = pBaseObj->GetChild(i); - if (pChild == NULL) + if (pChild == nullptr) { continue; } @@ -2109,7 +2109,7 @@ void CBaseObject::GetAllChildren(CSelectionGroup& outAllChildren, CBaseObject* p ////////////////////////////////////////////////////////////////////////// void CBaseObject::CloneChildren(CBaseObject* pFromObject) { - if (pFromObject == NULL) + if (pFromObject == nullptr) { return; } @@ -2119,7 +2119,7 @@ void CBaseObject::CloneChildren(CBaseObject* pFromObject) CBaseObject* pFromChildObject = pFromObject->GetChild(i); CBaseObject* pChildClone = GetObjectManager()->CloneObject(pFromChildObject); - if (pChildClone == NULL) + if (pChildClone == nullptr) { continue; } @@ -2248,7 +2248,7 @@ void CBaseObject::DetachThis(bool bKeepPos) // Copy parent to temp var, erasing child from parent may delete this node if child referenced only from parent. CBaseObject* parent = m_parent; - m_parent = 0; + m_parent = nullptr; parent->RemoveChild(this); if (bKeepPos) @@ -2389,7 +2389,7 @@ void CBaseObject::InvalidateTM([[maybe_unused]] int flags) // Invalidate matrices off all child objects. for (int i = 0; i < m_childs.size(); i++) { - if (m_childs[i] != 0 && m_childs[i]->m_bMatrixValid) + if (m_childs[i] != nullptr && m_childs[i]->m_bMatrixValid) { m_childs[i]->InvalidateTM(eObjectUpdateFlags_ParentChanged); } @@ -2538,7 +2538,7 @@ void CBaseObject::SetLookAt(CBaseObject* target) ////////////////////////////////////////////////////////////////////////// bool CBaseObject::IsLookAtTarget() const { - return m_lookatSource != 0; + return m_lookatSource != nullptr; } ////////////////////////////////////////////////////////////////////////// @@ -2806,7 +2806,7 @@ bool CBaseObject::IntersectRayMesh(const Vec3& raySrc, const Vec3& rayDir, SRayH outHitInfo.bInFirstHit = false; outHitInfo.bUseCache = false; - return pStatObj->RayIntersection(outHitInfo, 0); + return pStatObj->RayIntersection(outHitInfo, nullptr); } ////////////////////////////////////////////////////////////////////////// diff --git a/Code/Editor/Objects/BaseObject.h b/Code/Editor/Objects/BaseObject.h index a05bbb61af..47dba99ab7 100644 --- a/Code/Editor/Objects/BaseObject.h +++ b/Code/Editor/Objects/BaseObject.h @@ -321,7 +321,7 @@ public: //! Set object selected status. virtual void SetSelected(bool bSelect); //! Return associated 3DEngine render node - virtual IRenderNode* GetEngineNode() const { return NULL; }; + virtual IRenderNode* GetEngineNode() const { return nullptr; }; //! Set object highlighted (Note: not selected) virtual void SetHighlight(bool bHighlight); //! Check if object is highlighted. @@ -410,9 +410,9 @@ public: //! Scans hierarchy up to determine if we child of specified node. virtual bool IsChildOf(CBaseObject* node); //! Get all child objects - void GetAllChildren(TBaseObjects& outAllChildren, CBaseObject* pObj = NULL) const; - void GetAllChildren(DynArray< _smart_ptr >& outAllChildren, CBaseObject* pObj = NULL) const; - void GetAllChildren(CSelectionGroup& outAllChildren, CBaseObject* pObj = NULL) const; + void GetAllChildren(TBaseObjects& outAllChildren, CBaseObject* pObj = nullptr) const; + void GetAllChildren(DynArray< _smart_ptr >& outAllChildren, CBaseObject* pObj = nullptr) const; + void GetAllChildren(CSelectionGroup& outAllChildren, CBaseObject* pObj = nullptr) const; //! Clone Children void CloneChildren(CBaseObject* pFromObject); //! Attach new child node. @@ -468,8 +468,8 @@ public: //! Called when object is being created (use GetMouseCreateCallback for more advanced mouse creation callback). virtual int MouseCreateCallback(CViewport* view, EMouseEvent event, QPoint& point, int flags); // Return pointer to the callback object used when creating object by the mouse. - // If this function return NULL MouseCreateCallback method will be used instead. - virtual IMouseCreateCallback* GetMouseCreateCallback() { return 0; }; + // If this function return nullptr MouseCreateCallback method will be used instead. + virtual IMouseCreateCallback* GetMouseCreateCallback() { return nullptr; }; //! Draw object to specified viewport. virtual void Display([[maybe_unused]] DisplayContext& disp) {} @@ -598,7 +598,7 @@ public: bool CanBeHightlighted() const; bool IsSkipSelectionHelper() const; - virtual IStatObj* GetIStatObj() { return NULL; } + virtual IStatObj* GetIStatObj() { return nullptr; } // Invalidates cached transformation matrix. // nWhyFlags - Flags that indicate the reason for matrix invalidation. @@ -672,7 +672,7 @@ protected: //! Draw warning icons virtual void DrawWarningIcons(DisplayContext& dc, const Vec3& pos); //! Check if dimension's figures can be displayed before draw them. - virtual void DrawDimensions(DisplayContext& dc, AABB* pMergedBoundBox = NULL); + virtual void DrawDimensions(DisplayContext& dc, AABB* pMergedBoundBox = nullptr); //! Draw highlight. virtual void DrawHighlight(DisplayContext& dc); diff --git a/Code/Editor/Objects/EntityObject.cpp b/Code/Editor/Objects/EntityObject.cpp index 3b23894aac..0f4a17f3ba 100644 --- a/Code/Editor/Objects/EntityObject.cpp +++ b/Code/Editor/Objects/EntityObject.cpp @@ -56,18 +56,18 @@ public: } protected: - virtual void Release() { delete this; }; - virtual int GetSize() { return sizeof(*this); }; // Return size of xml state. - virtual QString GetDescription() { return "Entity Link"; }; - virtual QString GetObjectName(){ return ""; }; + void Release() override { delete this; }; + int GetSize() override { return sizeof(*this); }; // Return size of xml state. + QString GetDescription() override { return "Entity Link"; }; + QString GetObjectName() override{ return ""; }; - virtual void Undo([[maybe_unused]] bool bUndo) + void Undo([[maybe_unused]] bool bUndo) override { for (int i = 0, iLinkSize(m_Links.size()); i < iLinkSize; ++i) { SLink& link = m_Links[i]; CBaseObject* pObj = GetIEditor()->GetObjectManager()->FindObject(link.entityID); - if (pObj == NULL) + if (pObj == nullptr) { continue; } @@ -83,7 +83,7 @@ protected: pEntity->LoadLink(link.linkXmlNode->getChild(0)); } } - virtual void Redo(){} + void Redo() override{} private: @@ -109,7 +109,7 @@ public: , m_bAttach(bAttach) {} - virtual void Undo([[maybe_unused]] bool bUndo) override + void Undo([[maybe_unused]] bool bUndo) override { if (!m_bAttach) { @@ -117,7 +117,7 @@ public: } } - virtual void Redo() override + void Redo() override { if (m_bAttach) { @@ -138,8 +138,8 @@ private: } } - virtual int GetSize() { return sizeof(CUndoAttachEntity); } - virtual QString GetDescription() { return "Attachment Changed"; } + int GetSize() override { return sizeof(CUndoAttachEntity); } + QString GetDescription() override { return "Attachment Changed"; } GUID m_attachedEntityGUID; CEntityObject::EAttachmentType m_attachmentType; @@ -167,7 +167,7 @@ CEntityObject::CEntityObject() { m_bLoadFailed = false; - m_visualObject = 0; + m_visualObject = nullptr; m_box.min.Set(0, 0, 0); m_box.max.Set(0, 0, 0); @@ -225,7 +225,7 @@ CEntityObject::CEntityObject() mv_ratioLOD.SetLimits(0, 255); mv_viewDistanceMultiplier.SetLimits(0.0f, IRenderNode::VIEW_DISTANCE_MULTIPLIER_MAX); - m_physicsState = 0; + m_physicsState = nullptr; m_attachmentType = eAT_Pivot; @@ -540,7 +540,7 @@ IVariable* CEntityObject::FindVariableInSubBlock(CVarBlockPtr& properties, IVari ////////////////////////////////////////////////////////////////////////// void CEntityObject::AdjustLightProperties(CVarBlockPtr& properties, const char* pSubBlock) { - IVariable* pSubBlockVar = pSubBlock ? properties->FindVariable(pSubBlock) : NULL; + IVariable* pSubBlockVar = pSubBlock ? properties->FindVariable(pSubBlock) : nullptr; if (IVariable* pRadius = FindVariableInSubBlock(properties, pSubBlockVar, "Radius")) { @@ -933,7 +933,7 @@ void CEntityObject::Serialize(CObjectArchive& ar) { XmlNodeRef eventTarget = eventTargets->getChild(i); CEntityEventTarget et; - et.target = 0; + et.target = nullptr; GUID targetId = GUID_NULL; eventTarget->getAttr("TargetId", targetId); eventTarget->getAttr("Event", et.event); @@ -1029,7 +1029,7 @@ void CEntityObject::Serialize(CObjectArchive& ar) { CEntityEventTarget& et = m_eventTargets[i]; GUID targetId = GUID_NULL; - if (et.target != 0) + if (et.target != nullptr) { targetId = et.target->GetId(); } @@ -1060,7 +1060,7 @@ XmlNodeRef CEntityObject::Export([[maybe_unused]] const QString& levelPath, XmlN { if (m_bLoadFailed) { - return 0; + return nullptr; } // Do not export entity with bad id. @@ -1268,7 +1268,7 @@ void CEntityObject::OnEvent(ObjectEvent event) IObjectManager* objMan = GetIEditor()->GetObjectManager(); if (objMan && objMan->IsLightClass(this)) { - OnPropertyChange(NULL); + OnPropertyChange(nullptr); } break; } @@ -1314,7 +1314,7 @@ IVariable* CEntityObject::GetLightVariable(const char* name0) const { IVariable* pChild = pLightProperties->GetVariable(i); - if (pChild == NULL) + if (pChild == nullptr) { continue; } @@ -1341,7 +1341,7 @@ QString CEntityObject::GetLightAnimation() const { IVariable* pChild = pStyleGroup->GetVariable(i); - if (pChild == NULL) + if (pChild == nullptr) { continue; } @@ -1617,7 +1617,7 @@ void CEntityObject::RemoveEventTarget(int index, [[maybe_unused]] bool bUpdateSc ////////////////////////////////////////////////////////////////////////// int CEntityObject::AddEntityLink(const QString& name, GUID targetEntityId) { - CEntityObject* target = 0; + CEntityObject* target = nullptr; if (targetEntityId != GUID_NULL) { CBaseObject* pObject = FindObject(targetEntityId); @@ -1635,7 +1635,7 @@ int CEntityObject::AddEntityLink(const QString& name, GUID targetEntityId) StoreUndo("Add EntityLink"); - CLineGizmo* pLineGizmo = 0; + CLineGizmo* pLineGizmo = nullptr; // Assign event target. if (target) @@ -1968,7 +1968,7 @@ void CEntityObject::ResetCallbacks() //@FIXME Hack to display radii of properties. // wires properties from param block, to this entity internal variables. - IVariable* var = 0; + IVariable* var = nullptr; var = pProperties->FindVariable("Radius", false); if (var && (var->GetType() == IVariable::FLOAT || var->GetType() == IVariable::INT)) { @@ -2194,7 +2194,7 @@ template T CEntityObject::GetEntityProperty(const char* pName, T defaultvalue) const { CVarBlock* pProperties = GetProperties2(); - IVariable* pVariable = NULL; + IVariable* pVariable = nullptr; if (pProperties) { pVariable = pProperties->FindVariable(pName); @@ -2228,7 +2228,7 @@ template void CEntityObject::SetEntityProperty(const char* pName, T value) { CVarBlock* pProperties = GetProperties2(); - IVariable* pVariable = NULL; + IVariable* pVariable = nullptr; if (pProperties) { pVariable = pProperties->FindVariable(pName); diff --git a/Code/Editor/Objects/EntityObject.h b/Code/Editor/Objects/EntityObject.h index 76bd71a1f1..2dc89fdf80 100644 --- a/Code/Editor/Objects/EntityObject.h +++ b/Code/Editor/Objects/EntityObject.h @@ -185,7 +185,7 @@ public: void RemoveAllEntityLinks(); virtual void EntityLinked([[maybe_unused]] const QString& name, [[maybe_unused]] GUID targetEntityId){} virtual void EntityUnlinked([[maybe_unused]] const QString& name, [[maybe_unused]] GUID targetEntityId) {} - void LoadLink(XmlNodeRef xmlNode, CObjectArchive* pArchive = NULL); + void LoadLink(XmlNodeRef xmlNode, CObjectArchive* pArchive = nullptr); void SaveLink(XmlNodeRef xmlNode); ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// diff --git a/Code/Editor/Objects/Gizmo.h b/Code/Editor/Objects/Gizmo.h index 1e5b07abff..0dba75ae9c 100644 --- a/Code/Editor/Objects/Gizmo.h +++ b/Code/Editor/Objects/Gizmo.h @@ -67,7 +67,7 @@ public: //! Set this gizmo to be deleted. void DeleteThis(); - virtual CBaseObjectPtr GetBaseObject() const { return NULL; } + virtual CBaseObjectPtr GetBaseObject() const { return nullptr; } protected: diff --git a/Code/Editor/Objects/GizmoManager.cpp b/Code/Editor/Objects/GizmoManager.cpp index 697ca3e93c..e0fdd69c8e 100644 --- a/Code/Editor/Objects/GizmoManager.cpp +++ b/Code/Editor/Objects/GizmoManager.cpp @@ -79,7 +79,7 @@ CGizmo* CGizmoManager::GetGizmoByIndex(int nIndex) const return *ii; } } - return NULL; + return nullptr; } ////////////////////////////////////////////////////////////////////////// diff --git a/Code/Editor/Objects/LineGizmo.cpp b/Code/Editor/Objects/LineGizmo.cpp index 46026be614..31ea341f5b 100644 --- a/Code/Editor/Objects/LineGizmo.cpp +++ b/Code/Editor/Objects/LineGizmo.cpp @@ -37,8 +37,8 @@ CLineGizmo::~CLineGizmo() { m_object[1]->RemoveEventListener(this); } - m_object[0] = 0; - m_object[1] = 0; + m_object[0] = nullptr; + m_object[1] = nullptr; } ////////////////////////////////////////////////////////////////////////// @@ -164,7 +164,7 @@ void CLineGizmo::SetName(const char* sName) ////////////////////////////////////////////////////////////////////////// bool CLineGizmo::HitTest([[maybe_unused]] HitContext& hc) { - return 0; + return false; /* if (hc.distanceTollerance != 0) return 0; diff --git a/Code/Editor/Objects/ObjectLoader.cpp b/Code/Editor/Objects/ObjectLoader.cpp index 98f771dc76..2583eb6230 100644 --- a/Code/Editor/Objects/ObjectLoader.cpp +++ b/Code/Editor/Objects/ObjectLoader.cpp @@ -28,8 +28,8 @@ CObjectArchive::CObjectArchive(IObjectManager* objMan, XmlNodeRef xmlRoot, bool m_nFlags = 0; node = xmlRoot; m_pCurrentErrorReport = GetIEditor()->GetErrorReport(); - m_pGeometryPak = NULL; - m_pCurrentObject = NULL; + m_pGeometryPak = nullptr; + m_pCurrentObject = nullptr; m_bNeedResolveObjects = false; m_bProgressBarEnabled = true; } @@ -145,7 +145,7 @@ void CObjectArchive::ResolveObjects() // Objects can be added to the list here (from Groups). numObj = m_loadedObjects.size(); } - m_pCurrentErrorReport->SetCurrentValidatorObject(NULL); + m_pCurrentErrorReport->SetCurrentValidatorObject(nullptr); ////////////////////////////////////////////////////////////////////////// GetIEditor()->ResumeUndo(); } @@ -238,7 +238,7 @@ void CObjectArchive::ResolveObjects() // might generate unrelated errors m_pCurrentErrorReport->SetCurrentValidatorObject(nullptr); } - m_pCurrentErrorReport->SetCurrentValidatorObject(NULL); + m_pCurrentErrorReport->SetCurrentValidatorObject(nullptr); ////////////////////////////////////////////////////////////////////////// } @@ -257,7 +257,7 @@ void CObjectArchive::ResolveObjects() } m_bNeedResolveObjects = false; - m_pCurrentErrorReport->SetCurrentValidatorObject(NULL); + m_pCurrentErrorReport->SetCurrentValidatorObject(nullptr); m_sequenceIdRemap.clear(); m_pendingIds.clear(); } @@ -314,7 +314,7 @@ void CObjectArchive::LoadObjects(XmlNodeRef& rootObjectsNode) for (int i = 0; i < numObjects; i++) { XmlNodeRef objNode = rootObjectsNode->getChild(i); - LoadObject(objNode, NULL); + LoadObject(objNode, nullptr); } } @@ -401,7 +401,7 @@ void CObjectArchive::AddSequenceIdMapping(uint32 oldId, uint32 newId) { assert(oldId != newId); assert(GetIEditor()->GetMovieSystem()->FindSequenceById(oldId) || stl::find(m_pendingIds, oldId)); - assert(GetIEditor()->GetMovieSystem()->FindSequenceById(newId) == NULL); + assert(GetIEditor()->GetMovieSystem()->FindSequenceById(newId) == nullptr); assert(stl::find(m_pendingIds, newId) == false); m_sequenceIdRemap[oldId] = newId; m_pendingIds.push_back(newId); diff --git a/Code/Editor/Objects/ObjectLoader.h b/Code/Editor/Objects/ObjectLoader.h index 350ffa10a9..afe76875ec 100644 --- a/Code/Editor/Objects/ObjectLoader.h +++ b/Code/Editor/Objects/ObjectLoader.h @@ -67,7 +67,7 @@ AZ_POP_DISABLE_DLL_EXPORT_BASECLASS_WARNING void LoadObjects(XmlNodeRef& rootObjectsNode); //! Load one object from archive. - CBaseObject* LoadObject(const XmlNodeRef& objNode, CBaseObject* pPrevObject = NULL); + CBaseObject* LoadObject(const XmlNodeRef& objNode, CBaseObject* pPrevObject = nullptr); ////////////////////////////////////////////////////////////////////////// int GetLoadedObjectsCount() { return m_loadedObjects.size(); } diff --git a/Code/Editor/Objects/ObjectManager.cpp b/Code/Editor/Objects/ObjectManager.cpp index 58cd016e22..69e30c46ed 100644 --- a/Code/Editor/Objects/ObjectManager.cpp +++ b/Code/Editor/Objects/ObjectManager.cpp @@ -49,16 +49,16 @@ public: GUID guid; public: - REFGUID ClassID() + REFGUID ClassID() override { return guid; } - ObjectType GetObjectType() { return superType->GetObjectType(); }; - QString ClassName() { return type; }; - QString Category() { return category; }; + ObjectType GetObjectType() override { return superType->GetObjectType(); }; + QString ClassName() override { return type; }; + QString Category() override { return category; }; QObject* CreateQObject() const override { return superType->CreateQObject(); } - QString GetTextureIcon() { return superType->GetTextureIcon(); }; - QString GetFileSpec() + QString GetTextureIcon() override { return superType->GetTextureIcon(); }; + QString GetFileSpec() override { if (!fileSpec.isEmpty()) { @@ -69,7 +69,7 @@ public: return superType->GetFileSpec(); } }; - virtual int GameCreationOrder() { return superType->GameCreationOrder(); }; + int GameCreationOrder() override { return superType->GameCreationOrder(); }; }; void CBaseObjectsCache::AddObject(CBaseObject* object) @@ -86,7 +86,7 @@ void CBaseObjectsCache::AddObject(CBaseObject* object) ////////////////////////////////////////////////////////////////////////// // CObjectManager implementation. ////////////////////////////////////////////////////////////////////////// -CObjectManager* g_pObjectManager = 0; +CObjectManager* g_pObjectManager = nullptr; ////////////////////////////////////////////////////////////////////////// CObjectManager::CObjectManager() @@ -182,19 +182,19 @@ CBaseObject* CObjectManager::NewObject(CObjectClassDesc* cls, CBaseObject* prev, if (!AddObject(obj)) { - obj = 0; + obj = nullptr; } } else { - obj = 0; + obj = nullptr; } - GetIEditor()->GetErrorReport()->SetCurrentValidatorObject(NULL); + GetIEditor()->GetErrorReport()->SetCurrentValidatorObject(nullptr); } GetIEditor()->ResumeUndo(); - if (obj != 0 && GetIEditor()->IsUndoRecording()) + if (obj != nullptr && GetIEditor()->IsUndoRecording()) { // AZ entity creations are handled through the AZ undo system. if (obj->GetType() != OBJTYPE_AZENTITY) @@ -228,7 +228,7 @@ CBaseObject* CObjectManager::NewObject(CObjectArchive& ar, CBaseObject* pUndoObj if (!objNode->getAttr("Type", typeName)) { - return 0; + return nullptr; } if (!objNode->getAttr("Id", id)) @@ -268,7 +268,7 @@ CBaseObject* CObjectManager::NewObject(CObjectArchive& ar, CBaseObject* pUndoObj if (!cls) { CryWarning(VALIDATOR_MODULE_EDITOR, VALIDATOR_ERROR, "RuntimeClass %s not registered", typeName.toUtf8().data()); - return 0; + return nullptr; } pObject = qobject_cast(cls->CreateQObject()); @@ -301,29 +301,29 @@ CBaseObject* CObjectManager::NewObject(CObjectArchive& ar, CBaseObject* pUndoObj GetIEditor()->GetErrorReport()->ReportError(errorRecord); } - return 0; + return nullptr; //CoCreateGuid( &pObject->m_guid ); // generate uniq GUID for this object. } } GetIEditor()->GetErrorReport()->SetCurrentValidatorObject(pObject); - if (!pObject->Init(GetIEditor(), 0, "")) + if (!pObject->Init(GetIEditor(), nullptr, "")) { - GetIEditor()->GetErrorReport()->SetCurrentValidatorObject(NULL); - return 0; + GetIEditor()->GetErrorReport()->SetCurrentValidatorObject(nullptr); + return nullptr; } if (!AddObject(pObject)) { - GetIEditor()->GetErrorReport()->SetCurrentValidatorObject(NULL); - return 0; + GetIEditor()->GetErrorReport()->SetCurrentValidatorObject(nullptr); + return nullptr; } //pObject->Serialize( ar ); - GetIEditor()->GetErrorReport()->SetCurrentValidatorObject(NULL); + GetIEditor()->GetErrorReport()->SetCurrentValidatorObject(nullptr); - if (pObject != 0 && pUndoObject == 0) + if (pObject != nullptr && pUndoObject == nullptr) { // If new object with no undo, record it. if (CUndo::IsRecording()) @@ -355,7 +355,7 @@ CBaseObject* CObjectManager::NewObject(const QString& typeName, CBaseObject* pre if (!cls) { GetIEditor()->GetSystem()->GetILog()->Log("Warning: RuntimeClass %s (as well as %s) not registered", typeName.toUtf8().data(), fullName.toUtf8().data()); - return 0; + return nullptr; } CBaseObject* pObject = NewObject(cls, prev, file, newObjectName); return pObject; @@ -411,7 +411,7 @@ void CObjectManager::DeleteObject(CBaseObject* obj) void CObjectManager::DeleteSelection(CSelectionGroup* pSelection) { AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::Editor); - if (pSelection == NULL) + if (pSelection == nullptr) { return; } @@ -527,7 +527,7 @@ CBaseObject* CObjectManager::CloneObject(CBaseObject* obj) ////////////////////////////////////////////////////////////////////////// CBaseObject* CObjectManager::FindObject(REFGUID guid) const { - CBaseObject* result = stl::find_in_map(m_objects, guid, (CBaseObject*)0); + CBaseObject* result = stl::find_in_map(m_objects, guid, (CBaseObject*)nullptr); return result; } @@ -603,7 +603,7 @@ void CObjectManager::FindObjectsInAABB(const AABB& aabb, std::vectorGetId(), 0); + CBaseObjectPtr p = stl::find_in_map(m_objects, obj->GetId(), nullptr); if (p) { CErrorRecord err; @@ -908,7 +908,7 @@ void CObjectManager::UnfreezeAll() bool CObjectManager::SelectObject(CBaseObject* obj, bool bUseMask) { assert(obj); - if (obj == NULL) + if (obj == nullptr) { return false; } @@ -974,7 +974,7 @@ void CObjectManager::UnselectObject(CBaseObject* obj) CSelectionGroup* CObjectManager::GetSelection(const QString& name) const { - CSelectionGroup* selection = stl::find_in_map(m_selections, name, (CSelectionGroup*)0); + CSelectionGroup* selection = stl::find_in_map(m_selections, name, (CSelectionGroup*)nullptr); return selection; } @@ -993,7 +993,7 @@ void CObjectManager::NameSelection(const QString& name) return; } - CSelectionGroup* selection = stl::find_in_map(m_selections, name, (CSelectionGroup*)0); + CSelectionGroup* selection = stl::find_in_map(m_selections, name, (CSelectionGroup*)nullptr); if (selection) { assert(selection != 0); @@ -1020,7 +1020,7 @@ void CObjectManager::SerializeNameSelection(XmlNodeRef& rootNode, bool bLoading) return; } - _smart_ptr tmpGroup(0); + _smart_ptr tmpGroup(nullptr); QString selRootStr("NameSelection"); QString selNodeStr("NameSelectionNode"); @@ -1075,7 +1075,7 @@ void CObjectManager::SerializeNameSelection(XmlNodeRef& rootNode, bool bLoading) else { startNode = rootNode->newChild(selRootStr.toUtf8().data()); - CSelectionGroup* objSelection = 0; + CSelectionGroup* objSelection = nullptr; for (TNameSelectionMap::iterator it = m_selections.begin(); it != m_selections.end(); ++it) { @@ -1186,7 +1186,7 @@ int CObjectManager::InvertSelection() void CObjectManager::SetSelection(const QString& name) { AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::Editor); - CSelectionGroup* selection = stl::find_in_map(m_selections, name, (CSelectionGroup*)0); + CSelectionGroup* selection = stl::find_in_map(m_selections, name, (CSelectionGroup*)nullptr); if (selection) { UnselectCurrent(); @@ -1201,7 +1201,7 @@ void CObjectManager::RemoveSelection(const QString& name) AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::Editor); QString selName = name; - CSelectionGroup* selection = stl::find_in_map(m_selections, name, (CSelectionGroup*)0); + CSelectionGroup* selection = stl::find_in_map(m_selections, name, (CSelectionGroup*)nullptr); if (selection) { if (selection == m_currSelection) @@ -1359,7 +1359,7 @@ void CObjectManager::FindDisplayableObjects(DisplayContext& dc, [[maybe_unused]] for (int i = 0, iCount(pSelection->GetCount()); i < iCount; ++i) { CBaseObject* pObj(pSelection->GetObject(i)); - if (pObj == NULL) + if (pObj == nullptr) { continue; } @@ -1443,7 +1443,7 @@ void CObjectManager::BeginEditParams(CBaseObject* obj, int flags) void CObjectManager::EndEditParams([[maybe_unused]] int flags) { m_bSingleSelection = false; - m_currEditObject = 0; + m_currEditObject = nullptr; //m_bSelectionChanged = false; // don't need to clear for ungroup } @@ -1657,7 +1657,7 @@ bool CObjectManager::HitTest(HitContext& hitInfo) HitContext hcOrg = hitInfo; if (hcOrg.view) { - hcOrg.view->GetPerpendicularAxis(0, &hcOrg.b2DViewport); + hcOrg.view->GetPerpendicularAxis(nullptr, &hcOrg.b2DViewport); } hcOrg.rayDir = hcOrg.rayDir.GetNormalized(); @@ -1692,7 +1692,7 @@ bool CObjectManager::HitTest(HitContext& hitInfo) const bool iconsPrioritized = true; // Force icons to always be prioritized over other things you hit. Can change to be a configurable option in the future. - CBaseObject* selected = 0; + CBaseObject* selected = nullptr; const char* name = nullptr; bool iconHit = false; int numVis = pDispayedViewObjects->GetObjectCount(); @@ -1993,11 +1993,11 @@ bool CObjectManager::EnableUniqObjectNames(bool bEnable) CObjectClassDesc* CObjectManager::FindClass(const QString& className) { IClassDesc* cls = CClassFactory::Instance()->FindClass(className.toUtf8().data()); - if (cls != NULL && cls->SystemClassID() == ESYSTEM_CLASS_OBJECT) + if (cls != nullptr && cls->SystemClassID() == ESYSTEM_CLASS_OBJECT) { return (CObjectClassDesc*)cls; } - return 0; + return nullptr; } ////////////////////////////////////////////////////////////////////////// @@ -2101,7 +2101,7 @@ void CObjectManager::LoadClassTemplates(const QString& path) { // Construct the full filepath of the current file XmlNodeRef node = XmlHelpers::LoadXmlFromFile((dir + files[k].filename).toUtf8().data()); - if (node != 0 && node->isTag("ObjectTemplates")) + if (node != nullptr && node->isTag("ObjectTemplates")) { QString name; for (int i = 0; i < node->getChildCount(); i++) @@ -2449,7 +2449,7 @@ void CObjectManager::EndObjectsLoading() { delete m_pLoadProgress; } - m_pLoadProgress = 0; + m_pLoadProgress = nullptr; } ////////////////////////////////////////////////////////////////////////// @@ -2481,20 +2481,20 @@ bool CObjectManager::IsLightClass(CBaseObject* pObject) { if (pEntity->GetEntityClass().compare(CLASS_LIGHT) == 0) { - return TRUE; + return true; } if (pEntity->GetEntityClass().compare(CLASS_RIGIDBODY_LIGHT) == 0) { - return TRUE; + return true; } if (pEntity->GetEntityClass().compare(CLASS_DESTROYABLE_LIGHT) == 0) { - return TRUE; + return true; } } } - return FALSE; + return false; } void CObjectManager::FindAndRenameProperty2(const char* property2Name, const QString& oldValue, const QString& newValue) diff --git a/Code/Editor/Objects/SelectionGroup.cpp b/Code/Editor/Objects/SelectionGroup.cpp index 5912cf050e..027c88172e 100644 --- a/Code/Editor/Objects/SelectionGroup.cpp +++ b/Code/Editor/Objects/SelectionGroup.cpp @@ -636,7 +636,7 @@ void CSelectionGroup::FinishChanges() for (int i = 0; i < iObjectSize; ++i) { CBaseObject* pObject = selectedObjects[i]; - if (pObject == NULL) + if (pObject == nullptr) { continue; } diff --git a/Code/Editor/Objects/TrackGizmo.cpp b/Code/Editor/Objects/TrackGizmo.cpp index ed1132bd2b..8cbd7df2e5 100644 --- a/Code/Editor/Objects/TrackGizmo.cpp +++ b/Code/Editor/Objects/TrackGizmo.cpp @@ -34,7 +34,7 @@ namespace { ////////////////////////////////////////////////////////////////////////// CTrackGizmo::CTrackGizmo() { - m_pAnimNode = 0; + m_pAnimNode = nullptr; m_worldBbox.min = Vec3(-10000, -10000, -10000); m_worldBbox.max = Vec3(10000, 10000, 10000); diff --git a/Code/Editor/Platform/Windows/Util/Mailer_Windows.cpp b/Code/Editor/Platform/Windows/Util/Mailer_Windows.cpp index e7cc8658f0..7ac1181cdd 100644 --- a/Code/Editor/Platform/Windows/Util/Mailer_Windows.cpp +++ b/Code/Editor/Platform/Windows/Util/Mailer_Windows.cpp @@ -51,8 +51,8 @@ bool CMailer::SendMail(const char* subject, attachments[i].flFlags = 0; attachments[i].nPosition = (ULONG)-1; attachments[i].lpszPathName = (char*)(const char*)_attachments[k]; - attachments[i].lpszFileName = NULL; - attachments[i].lpFileType = NULL; + attachments[i].lpszFileName = nullptr; + attachments[i].lpFileType = nullptr; i++; } int numAttachments = i; @@ -74,14 +74,14 @@ bool CMailer::SendMail(const char* subject, recipients[i].lpszName = (char*)(const char*)_recipients[i]; recipients[i].lpszAddress = (char*)addresses[i].c_str(); recipients[i].ulEIDSize = 0; - recipients[i].lpEntryID = NULL; + recipients[i].lpEntryID = nullptr; } MapiMessage message; memset(&message, 0, sizeof(message)); message.lpszSubject = (char*)(const char*)subject; message.lpszNoteText = (char*)(const char*)messageBody; - message.lpszMessageType = NULL; + message.lpszMessageType = nullptr; message.nRecipCount = numRecipients; message.lpRecips = recipients; diff --git a/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp b/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp index 874868b5bc..c78537c77d 100644 --- a/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp +++ b/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp @@ -1815,7 +1815,7 @@ void SandboxIntegrationManager::ContextMenu_PushEntitiesToSlice(AzToolsFramework (void)targetAncestorId; (void)affectEntireHierarchy; - AZ::SerializeContext* serializeContext = NULL; + AZ::SerializeContext* serializeContext = nullptr; EBUS_EVENT_RESULT(serializeContext, AZ::ComponentApplicationBus, GetSerializeContext); AZ_Assert(serializeContext, "No serialize context"); diff --git a/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/ComponentPalette/ComponentPaletteWindow.cpp b/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/ComponentPalette/ComponentPaletteWindow.cpp index 78d3e51e4d..1791301654 100644 --- a/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/ComponentPalette/ComponentPaletteWindow.cpp +++ b/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/ComponentPalette/ComponentPaletteWindow.cpp @@ -42,7 +42,7 @@ void ComponentPaletteWindow::Init() layout->setContentsMargins(0, 0, 0, 0); layout->setSpacing(0); - QHBoxLayout* gridLayout = new QHBoxLayout(NULL); + QHBoxLayout* gridLayout = new QHBoxLayout(nullptr); gridLayout->setSizeConstraint(QLayout::SetMaximumSize); gridLayout->setContentsMargins(0, 0, 0, 0); gridLayout->setSpacing(0); diff --git a/Code/Editor/Plugins/EditorCommon/DockTitleBarWidget.cpp b/Code/Editor/Plugins/EditorCommon/DockTitleBarWidget.cpp index adb8ef0bc5..0569adf069 100644 --- a/Code/Editor/Plugins/EditorCommon/DockTitleBarWidget.cpp +++ b/Code/Editor/Plugins/EditorCommon/DockTitleBarWidget.cpp @@ -30,13 +30,13 @@ class CDockWidgetTitleButton public: CDockWidgetTitleButton(QWidget* parent); - QSize sizeHint() const; - QSize minimumSizeHint() const { return sizeHint(); } + QSize sizeHint() const override; + QSize minimumSizeHint() const override { return sizeHint(); } protected: - void enterEvent(QEvent* ev); - void leaveEvent(QEvent* ev); - void paintEvent(QPaintEvent* ev); + void enterEvent(QEvent* ev) override; + void leaveEvent(QEvent* ev) override; + void paintEvent(QPaintEvent* ev) override; }; class CTitleBarText @@ -85,10 +85,10 @@ QSize CDockWidgetTitleButton::sizeHint() const { ensurePolished(); - int size = 2 * style()->pixelMetric(QStyle::PM_DockWidgetTitleBarButtonMargin, 0, this); + int size = 2 * style()->pixelMetric(QStyle::PM_DockWidgetTitleBarButtonMargin, nullptr, this); if (!icon().isNull()) { - int iconSize = style()->pixelMetric(QStyle::PM_SmallIconSize, 0, this); + int iconSize = style()->pixelMetric(QStyle::PM_SmallIconSize, nullptr, this); QSize sz = icon().actualSize(QSize(iconSize, iconSize)); size += qMax(sz.width(), sz.height()); } @@ -145,7 +145,7 @@ void CDockWidgetTitleButton::paintEvent([[maybe_unused]] QPaintEvent* ev) opt.activeSubControls = QStyle::SubControls(); opt.features = QStyleOptionToolButton::None; opt.arrowType = Qt::NoArrow; - int size = style()->pixelMetric(QStyle::PM_SmallIconSize, 0, this); + int size = style()->pixelMetric(QStyle::PM_SmallIconSize, nullptr, this); opt.iconSize = QSize(size, size); style()->drawComplexControl(QStyle::CC_ToolButton, &opt, &painter, this); } diff --git a/Code/Editor/Plugins/FFMPEGPlugin/main.cpp b/Code/Editor/Plugins/FFMPEGPlugin/main.cpp index 3432a9975e..ce0e91942b 100644 --- a/Code/Editor/Plugins/FFMPEGPlugin/main.cpp +++ b/Code/Editor/Plugins/FFMPEGPlugin/main.cpp @@ -15,7 +15,7 @@ PLUGIN_API IPlugin* CreatePluginInstance(PLUGIN_INIT_PARAM* pInitParam) if (pInitParam->pluginVersion != SANDBOX_PLUGIN_SYSTEM_VERSION) { pInitParam->outErrorCode = IPlugin::eError_VersionMismatch; - return 0; + return nullptr; } ModuleInitISystem(GetIEditor()->GetSystem(), "FFMPEGPlugin"); diff --git a/Code/Editor/Plugins/ProjectSettingsTool/PlatformSettings_Android.cpp b/Code/Editor/Plugins/ProjectSettingsTool/PlatformSettings_Android.cpp index d11cc04ba0..fe73253805 100644 --- a/Code/Editor/Plugins/ProjectSettingsTool/PlatformSettings_Android.cpp +++ b/Code/Editor/Plugins/ProjectSettingsTool/PlatformSettings_Android.cpp @@ -165,8 +165,8 @@ namespace ProjectSettingsTool if (editContext) { editContext->Class("Splashscreens", "All splashscreen overrides for Android.") - ->DataElement(0, &AndroidSplashscreens::m_landscapeSplashscreens) - ->DataElement(0, &AndroidSplashscreens::m_portraitSplashscreens) + ->DataElement(nullptr, &AndroidSplashscreens::m_landscapeSplashscreens) + ->DataElement(nullptr, &AndroidSplashscreens::m_portraitSplashscreens) ; } } diff --git a/Code/Editor/Plugins/ProjectSettingsTool/Validators.cpp b/Code/Editor/Plugins/ProjectSettingsTool/Validators.cpp index e8bb900be9..4dfc4ee25a 100644 --- a/Code/Editor/Plugins/ProjectSettingsTool/Validators.cpp +++ b/Code/Editor/Plugins/ProjectSettingsTool/Validators.cpp @@ -16,7 +16,7 @@ namespace { - typedef ProjectSettingsTool::FunctorValidator::ReturnType RetType; + using RetType = ProjectSettingsTool::FunctorValidator::ReturnType; static const int noMaxLength = -1; static const int maxIosVersionLength = 18; From 3ad3dfd6623e23ac3a5fef4559ba79052ee6656f Mon Sep 17 00:00:00 2001 From: Yuriy Toporovskyy Date: Thu, 5 Aug 2021 10:50:29 -0400 Subject: [PATCH 126/803] Address PR feedback Signed-off-by: Yuriy Toporovskyy --- Code/Editor/EditorViewportWidget.cpp | 2 +- Code/Editor/UndoViewRotation.cpp | 5 ++++- Code/Framework/AzCore/AzCore/Math/MatrixUtils.cpp | 2 +- .../Code/Source/Editor/AudioControlsEditorPlugin.cpp | 5 ++++- Gems/Camera/Code/Source/CameraSystemComponent.cpp | 9 +++++---- Gems/Camera/Code/Source/CameraSystemComponent.h | 3 ++- 6 files changed, 17 insertions(+), 9 deletions(-) diff --git a/Code/Editor/EditorViewportWidget.cpp b/Code/Editor/EditorViewportWidget.cpp index b205ca5b78..26c96f54b1 100644 --- a/Code/Editor/EditorViewportWidget.cpp +++ b/Code/Editor/EditorViewportWidget.cpp @@ -2513,7 +2513,7 @@ void EditorViewportWidget::SetViewAndMovementLockFromEntityPerspective(const AZ: if (entityId.IsValid()) { - EBUS_EVENT_ID(entityId, Camera::CameraRequestBus, MakeActiveView); + Camera::CameraRequestBus::Event(entityId, &Camera::CameraRequestBus::Events::MakeActiveView); } else { diff --git a/Code/Editor/UndoViewRotation.cpp b/Code/Editor/UndoViewRotation.cpp index c3c6f4253a..a305641d3b 100644 --- a/Code/Editor/UndoViewRotation.cpp +++ b/Code/Editor/UndoViewRotation.cpp @@ -25,7 +25,10 @@ Ang3 CUndoViewRotation::GetActiveCameraRotation() { AZ::Transform activeCameraTm = AZ::Transform::CreateIdentity(); - EBUS_EVENT_RESULT(activeCameraTm, Camera::ActiveCameraRequestBus, GetActiveCameraTransform); + Camera::ActiveCameraRequestBus::BroadcastResult( + activeCameraTm, + &Camera::ActiveCameraRequestBus::Events::GetActiveCameraTransform + ); const AZ::Matrix3x4 cameraMatrix = AZ::Matrix3x4::CreateFromTransform(activeCameraTm); const Matrix33 cameraMatrixCry = AZMatrix3x3ToLYMatrix3x3(AZ::Matrix3x3::CreateFromMatrix3x4(cameraMatrix)); return RAD2DEG(Ang3::GetAnglesXYZ(cameraMatrixCry)); diff --git a/Code/Framework/AzCore/AzCore/Math/MatrixUtils.cpp b/Code/Framework/AzCore/AzCore/Math/MatrixUtils.cpp index c5b76cbab7..eabfcd8cf0 100644 --- a/Code/Framework/AzCore/AzCore/Math/MatrixUtils.cpp +++ b/Code/Framework/AzCore/AzCore/Math/MatrixUtils.cpp @@ -57,7 +57,7 @@ namespace AZ float GetPerspectiveMatrixFOV(const Matrix4x4& m) { - return 2.0 * atan(1.0f / m.GetElement(1, 1)); + return 2.0 * AZStd::atan(1.0f / m.GetElement(1, 1)); } Matrix4x4* MakeFrustumMatrixRH(Matrix4x4& out, float left, float right, float bottom, float top, float nearDist, float farDist, bool reverseDepth) diff --git a/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorPlugin.cpp b/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorPlugin.cpp index 2a97bdfb92..2b7023df61 100644 --- a/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorPlugin.cpp +++ b/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorPlugin.cpp @@ -151,7 +151,10 @@ void CAudioControlsEditorPlugin::ExecuteTrigger(const AZStd::string_view sTrigge if (ms_nAudioTriggerID != INVALID_AUDIO_CONTROL_ID) { AZ::Transform activeCameraTm = AZ::Transform::CreateIdentity(); - EBUS_EVENT_RESULT(activeCameraTm, Camera::ActiveCameraRequestBus, GetActiveCameraTransform); + Camera::ActiveCameraRequestBus::BroadcastResult( + activeCameraTm, + &Camera::ActiveCameraRequestBus::Events::GetActiveCameraTransform + ); const AZ::Matrix3x4 cameraMatrix = AZ::Matrix3x4::CreateFromTransform(activeCameraTm); Audio::SAudioRequest request; diff --git a/Gems/Camera/Code/Source/CameraSystemComponent.cpp b/Gems/Camera/Code/Source/CameraSystemComponent.cpp index 7c7dac429d..e9b0132cf8 100644 --- a/Gems/Camera/Code/Source/CameraSystemComponent.cpp +++ b/Gems/Camera/Code/Source/CameraSystemComponent.cpp @@ -1,5 +1,6 @@ /* - * Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. * * SPDX-License-Identifier: Apache-2.0 OR MIT * @@ -19,7 +20,7 @@ namespace Camera { void CameraSystemComponent::Reflect(AZ::ReflectContext* context) { - if (AZ::SerializeContext* serializeContext = azrtti_cast(context)) + if (auto serializeContext = azrtti_cast(context)) { serializeContext->Class() ->Version(1) @@ -36,9 +37,9 @@ namespace Camera void CameraSystemComponent::Deactivate() { - CameraSystemRequestBus::Handler::BusDisconnect(); - ActiveCameraRequestBus::Handler::BusDisconnect(); CameraNotificationBus::Handler::BusDisconnect(); + ActiveCameraRequestBus::Handler::BusDisconnect(); + CameraSystemRequestBus::Handler::BusDisconnect(); } AZ::EntityId CameraSystemComponent::GetActiveCamera() diff --git a/Gems/Camera/Code/Source/CameraSystemComponent.h b/Gems/Camera/Code/Source/CameraSystemComponent.h index 726975ff9d..1b8f31b91e 100644 --- a/Gems/Camera/Code/Source/CameraSystemComponent.h +++ b/Gems/Camera/Code/Source/CameraSystemComponent.h @@ -1,5 +1,6 @@ /* - * Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. * * SPDX-License-Identifier: Apache-2.0 OR MIT * From 56dee47c6bf6c4544ed66a6f51a46234cfc64d4a Mon Sep 17 00:00:00 2001 From: Yuriy Toporovskyy Date: Thu, 5 Aug 2021 11:56:09 -0400 Subject: [PATCH 127/803] Address more PR feedback Signed-off-by: Yuriy Toporovskyy --- Code/Editor/AnimationContext.cpp | 1 - Code/Editor/EditorViewportWidget.h | 2 - Code/Editor/Export/ExportManager.cpp | 1 - .../SandboxIntegration.cpp | 1 + Code/Editor/RenderViewport.cpp | 0 Code/Editor/RenderViewport.h | 54 ------------------- Code/Editor/TrackView/TrackViewAnimNode.cpp | 1 - Code/Editor/ViewManager.cpp | 1 - Code/Editor/ViewportTitleDlg.h | 1 - Code/Editor/editor_lib_files.cmake | 2 - .../Code/Source/CameraSystemComponent.h | 2 +- .../ViewportCameraSelectorWindow_Internals.h | 2 +- .../Code/Source/SystemComponent.cpp | 2 +- 13 files changed, 4 insertions(+), 66 deletions(-) delete mode 100644 Code/Editor/RenderViewport.cpp delete mode 100644 Code/Editor/RenderViewport.h diff --git a/Code/Editor/AnimationContext.cpp b/Code/Editor/AnimationContext.cpp index b67e9e602e..d557a8635c 100644 --- a/Code/Editor/AnimationContext.cpp +++ b/Code/Editor/AnimationContext.cpp @@ -16,7 +16,6 @@ // Editor #include "TrackView/TrackViewDialog.h" -#include "RenderViewport.h" #include "ViewManager.h" #include "Objects/SelectionGroup.h" #include "Include/IObjectManager.h" diff --git a/Code/Editor/EditorViewportWidget.h b/Code/Editor/EditorViewportWidget.h index dabbbe95f6..33ed001735 100644 --- a/Code/Editor/EditorViewportWidget.h +++ b/Code/Editor/EditorViewportWidget.h @@ -8,8 +8,6 @@ #pragma once -// RenderViewport.h : header file -// #if !defined(Q_MOC_RUN) #include diff --git a/Code/Editor/Export/ExportManager.cpp b/Code/Editor/Export/ExportManager.cpp index 0d114d5da8..54f3c2f723 100644 --- a/Code/Editor/Export/ExportManager.cpp +++ b/Code/Editor/Export/ExportManager.cpp @@ -22,7 +22,6 @@ #include "OBJExporter.h" #include "OCMExporter.h" #include "FBXExporterDialog.h" -#include "RenderViewport.h" #include "TrackViewExportKeyTimeDlg.h" #include "AnimationContext.h" #include "TrackView/DirectorNodeAnimator.h" diff --git a/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp b/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp index 874868b5bc..29db338a85 100644 --- a/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp +++ b/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp @@ -84,6 +84,7 @@ #include #include #include "CryEdit.h" +#include "Undo/Undo.h" #include #include diff --git a/Code/Editor/RenderViewport.cpp b/Code/Editor/RenderViewport.cpp deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/Code/Editor/RenderViewport.h b/Code/Editor/RenderViewport.h deleted file mode 100644 index 8f5e19f93d..0000000000 --- a/Code/Editor/RenderViewport.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - -#ifndef CRYINCLUDE_EDITOR_RENDERVIEWPORT_H -#define CRYINCLUDE_EDITOR_RENDERVIEWPORT_H - -#pragma once -// RenderViewport.h : header file -// - -#if !defined(Q_MOC_RUN) -#include - -#include - -#include "Viewport.h" -#include "Objects/DisplayContext.h" -#include "Undo/Undo.h" -#include "Util/PredefinedAspectRatios.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#endif - -#include -#include - -// forward declarations. -class CBaseObject; -class QMenu; -class QKeyEvent; -class EditorEntityNotifications; -struct ray_hit; -struct IRenderMesh; -struct IVariable; - -namespace AzToolsFramework -{ - class ManipulatorManager; -} - -#endif diff --git a/Code/Editor/TrackView/TrackViewAnimNode.cpp b/Code/Editor/TrackView/TrackViewAnimNode.cpp index 8696faf516..9d0892888f 100644 --- a/Code/Editor/TrackView/TrackViewAnimNode.cpp +++ b/Code/Editor/TrackView/TrackViewAnimNode.cpp @@ -34,7 +34,6 @@ #include "Clipboard.h" #include "CommentNodeAnimator.h" #include "DirectorNodeAnimator.h" -#include "RenderViewport.h" #include "ViewManager.h" #include "Include/IObjectManager.h" #include "Objects/GizmoManager.h" diff --git a/Code/Editor/ViewManager.cpp b/Code/Editor/ViewManager.cpp index 2ccbac09ed..7277a0f4f3 100644 --- a/Code/Editor/ViewManager.cpp +++ b/Code/Editor/ViewManager.cpp @@ -26,7 +26,6 @@ #include "LayoutWnd.h" #include "2DViewport.h" #include "TopRendererWnd.h" -#include "RenderViewport.h" #include "EditorViewportWidget.h" #include "CryEditDoc.h" diff --git a/Code/Editor/ViewportTitleDlg.h b/Code/Editor/ViewportTitleDlg.h index a5b4da8075..8a1766a764 100644 --- a/Code/Editor/ViewportTitleDlg.h +++ b/Code/Editor/ViewportTitleDlg.h @@ -12,7 +12,6 @@ #pragma once #if !defined(Q_MOC_RUN) -#include "RenderViewport.h" #include #include diff --git a/Code/Editor/editor_lib_files.cmake b/Code/Editor/editor_lib_files.cmake index 386b495faa..a007a95e7b 100644 --- a/Code/Editor/editor_lib_files.cmake +++ b/Code/Editor/editor_lib_files.cmake @@ -807,8 +807,6 @@ set(FILES ViewportManipulatorController.h LegacyViewportCameraController.cpp LegacyViewportCameraController.h - RenderViewport.cpp - RenderViewport.h TopRendererWnd.cpp TopRendererWnd.h ViewManager.cpp diff --git a/Gems/Camera/Code/Source/CameraSystemComponent.h b/Gems/Camera/Code/Source/CameraSystemComponent.h index 1b8f31b91e..7fc8d15d6b 100644 --- a/Gems/Camera/Code/Source/CameraSystemComponent.h +++ b/Gems/Camera/Code/Source/CameraSystemComponent.h @@ -58,4 +58,4 @@ namespace Camera AZ::EntityId m_activeView; CameraProperties m_activeViewProperties; }; -} +} // namespace Camera diff --git a/Gems/Camera/Code/Source/ViewportCameraSelectorWindow_Internals.h b/Gems/Camera/Code/Source/ViewportCameraSelectorWindow_Internals.h index e75a820eec..2c3d114908 100644 --- a/Gems/Camera/Code/Source/ViewportCameraSelectorWindow_Internals.h +++ b/Gems/Camera/Code/Source/ViewportCameraSelectorWindow_Internals.h @@ -42,7 +42,7 @@ namespace Camera , public CameraNotificationBus::Handler { public: - CameraListModel(QWidget* myParent); + explicit CameraListModel(QWidget* myParent); ~CameraListModel(); // QAbstractItemModel interface diff --git a/Gems/PhysXDebug/Code/Source/SystemComponent.cpp b/Gems/PhysXDebug/Code/Source/SystemComponent.cpp index 97cb4f33d3..16cbdaaf64 100644 --- a/Gems/PhysXDebug/Code/Source/SystemComponent.cpp +++ b/Gems/PhysXDebug/Code/Source/SystemComponent.cpp @@ -470,7 +470,7 @@ namespace PhysXDebug AZ::Vector3 GetViewCameraPosition() { - using namespace Camera; + using Camera::ActiveCameraRequestBus; AZ::Transform tm = AZ::Transform::CreateIdentity(); ActiveCameraRequestBus::BroadcastResult(tm, &ActiveCameraRequestBus::Events::GetActiveCameraTransform); From 39907f4ca1439785c29638bdbc7a027fa5f18d07 Mon Sep 17 00:00:00 2001 From: nggieber Date: Thu, 5 Aug 2021 09:12:52 -0700 Subject: [PATCH 128/803] Removes focus from tabs in o3de.exe Signed-off-by: nggieber --- Code/Tools/ProjectManager/Source/ScreensCtrl.cpp | 1 + Code/Tools/ProjectManager/Source/UpdateProjectCtrl.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/Code/Tools/ProjectManager/Source/ScreensCtrl.cpp b/Code/Tools/ProjectManager/Source/ScreensCtrl.cpp index 30b8ef1d34..8b8b8ac78b 100644 --- a/Code/Tools/ProjectManager/Source/ScreensCtrl.cpp +++ b/Code/Tools/ProjectManager/Source/ScreensCtrl.cpp @@ -30,6 +30,7 @@ namespace O3DE::ProjectManager // add a tab widget at the bottom of the stack m_tabWidget = new QTabWidget(); + m_tabWidget->tabBar()->setFocusPolicy(Qt::NoFocus); m_screenStack->addWidget(m_tabWidget); connect(m_tabWidget, &QTabWidget::currentChanged, this, &ScreensCtrl::TabChanged); } diff --git a/Code/Tools/ProjectManager/Source/UpdateProjectCtrl.cpp b/Code/Tools/ProjectManager/Source/UpdateProjectCtrl.cpp index 6aba261cd2..28c9d342e6 100644 --- a/Code/Tools/ProjectManager/Source/UpdateProjectCtrl.cpp +++ b/Code/Tools/ProjectManager/Source/UpdateProjectCtrl.cpp @@ -54,6 +54,7 @@ namespace O3DE::ProjectManager QTabWidget* tabWidget = new QTabWidget(); tabWidget->setObjectName("projectSettingsTab"); tabWidget->tabBar()->setObjectName("projectSettingsTabBar"); + tabWidget->tabBar()->setFocusPolicy(Qt::NoFocus); tabWidget->addTab(m_updateSettingsScreen, tr("General")); QPushButton* gemsButton = new QPushButton(tr("Configure Gems"), this); From 1768dc5980bf66c0f8c517d250369885abd87978 Mon Sep 17 00:00:00 2001 From: nggieber Date: Thu, 5 Aug 2021 09:29:48 -0700 Subject: [PATCH 129/803] Reenabled focusing of tab but removed focus rect Signed-off-by: nggieber --- Code/Tools/ProjectManager/Resources/ProjectManager.qss | 5 +++++ Code/Tools/ProjectManager/Source/ScreensCtrl.cpp | 1 - Code/Tools/ProjectManager/Source/UpdateProjectCtrl.cpp | 1 - 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Code/Tools/ProjectManager/Resources/ProjectManager.qss b/Code/Tools/ProjectManager/Resources/ProjectManager.qss index 74acc1c7ef..e18bf34931 100644 --- a/Code/Tools/ProjectManager/Resources/ProjectManager.qss +++ b/Code/Tools/ProjectManager/Resources/ProjectManager.qss @@ -53,6 +53,11 @@ QTabBar::tab:pressed { color: #0e60eb; } +QTabBar::focus { + outline: 0px; + outline: none; + outline-style: none; + } /************** General (Forms) **************/ diff --git a/Code/Tools/ProjectManager/Source/ScreensCtrl.cpp b/Code/Tools/ProjectManager/Source/ScreensCtrl.cpp index 8b8b8ac78b..30b8ef1d34 100644 --- a/Code/Tools/ProjectManager/Source/ScreensCtrl.cpp +++ b/Code/Tools/ProjectManager/Source/ScreensCtrl.cpp @@ -30,7 +30,6 @@ namespace O3DE::ProjectManager // add a tab widget at the bottom of the stack m_tabWidget = new QTabWidget(); - m_tabWidget->tabBar()->setFocusPolicy(Qt::NoFocus); m_screenStack->addWidget(m_tabWidget); connect(m_tabWidget, &QTabWidget::currentChanged, this, &ScreensCtrl::TabChanged); } diff --git a/Code/Tools/ProjectManager/Source/UpdateProjectCtrl.cpp b/Code/Tools/ProjectManager/Source/UpdateProjectCtrl.cpp index 28c9d342e6..6aba261cd2 100644 --- a/Code/Tools/ProjectManager/Source/UpdateProjectCtrl.cpp +++ b/Code/Tools/ProjectManager/Source/UpdateProjectCtrl.cpp @@ -54,7 +54,6 @@ namespace O3DE::ProjectManager QTabWidget* tabWidget = new QTabWidget(); tabWidget->setObjectName("projectSettingsTab"); tabWidget->tabBar()->setObjectName("projectSettingsTabBar"); - tabWidget->tabBar()->setFocusPolicy(Qt::NoFocus); tabWidget->addTab(m_updateSettingsScreen, tr("General")); QPushButton* gemsButton = new QPushButton(tr("Configure Gems"), this); From 574bef0cd8daabdae79d933b1011153a6853f83b Mon Sep 17 00:00:00 2001 From: evanchia Date: Thu, 5 Aug 2021 10:19:15 -0700 Subject: [PATCH 130/803] Escape character in Jenkins for test metrics Signed-off-by: evanchia --- scripts/build/Jenkins/Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/build/Jenkins/Jenkinsfile b/scripts/build/Jenkins/Jenkinsfile index 9aa09e136e..517fa1136d 100644 --- a/scripts/build/Jenkins/Jenkinsfile +++ b/scripts/build/Jenkins/Jenkinsfile @@ -370,7 +370,7 @@ def TestMetrics(Map pipelineConfig, String workspace, String branchName, String def command = "${pipelineConfig.PYTHON_DIR}/python.cmd -u mars/scripts/python/ctest_test_metric_scraper.py " + '-e jenkins.creds.user %username% -e jenkins.creds.pass %apitoken% ' + "-e jenkins.base_url ${env.JENKINS_URL} " + - "${cmakeBuildDir} ${branchName} %BUILD_NUMBER% AR ${configuration} ${repoName} --url ${env.BUILD_URL}" + "${cmakeBuildDir} ${branchName} %BUILD_NUMBER% AR ${configuration} ${repoName} --url ${env.BUILD_URL}.replace('%','%%')" bat label: "Publishing ${buildJobName} Test Metrics", script: command } From bf7512ebf4b9045b8892779bcc89d6773be5774b Mon Sep 17 00:00:00 2001 From: Dayo Lawal Date: Thu, 5 Aug 2021 14:07:48 -0500 Subject: [PATCH 131/803] Merge fix Signed-off-by: Dayo Lawal --- .../Application/AtomToolsApplication.cpp | 16 ++++-- .../Code/Source/MaterialEditorApplication.cpp | 15 +---- .../Code/Source/MaterialEditorApplication.h | 1 - .../Scripts/GenerateAllMaterialScreenshots.py | 4 +- .../ShaderManagementConsoleApplication.cpp | 57 +++++++------------ .../ShaderManagementConsoleApplication.h | 3 +- 6 files changed, 37 insertions(+), 59 deletions(-) diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp index 4094e7a3a0..25ef43cfa4 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -70,6 +71,8 @@ namespace AtomToolsFramework AtomToolsApplication ::~AtomToolsApplication() { AtomToolsMainWindowNotificationBus::Handler::BusDisconnect(); + AzToolsFramework::AssetDatabase::AssetDatabaseRequestsBus::Handler::BusDisconnect(); + AzToolsFramework::EditorPythonConsoleNotificationBus::Handler::BusDisconnect(); } void AtomToolsApplication::CreateReflectionManager() @@ -93,14 +96,12 @@ namespace AtomToolsFramework if (auto behaviorContext = azrtti_cast(context)) { - auto targetName = GetBuildTargetName(); - // this will put these methods into the 'azlmbr.AtomTools.general' module - auto addGeneral = [targetName](AZ::BehaviorContext::GlobalMethodBuilder methodBuilder) + auto addGeneral = [](AZ::BehaviorContext::GlobalMethodBuilder methodBuilder) { methodBuilder->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation) ->Attribute(AZ::Script::Attributes::Category, "Editor") - ->Attribute(AZ::Script::Attributes::Module, targetName); + ->Attribute(AZ::Script::Attributes::Module, "atomtools.general"); }; // The reflection here is based on patterns in CryEditPythonHandler::Reflect addGeneral(behaviorContext->Method( @@ -288,6 +289,13 @@ namespace AtomToolsFramework void AtomToolsApplication::ProcessCommandLine(const AZ::CommandLine& commandLine) { + const AZStd::string activateWindowSwitchName = "activatewindow"; + if (commandLine.HasSwitch(activateWindowSwitchName)) + { + AtomToolsFramework::AtomToolsMainWindowRequestBus::Broadcast( + &AtomToolsFramework::AtomToolsMainWindowRequestBus::Handler::ActivateWindow); + } + const AZStd::string timeoputSwitchName = "timeout"; if (commandLine.HasSwitch(timeoputSwitchName)) { diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp index 53409d717f..0dd8da5415 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp @@ -17,7 +17,6 @@ #include #include -#include #include #include @@ -76,16 +75,11 @@ namespace MaterialEditor { QApplication::setApplicationName("O3DE Material Editor"); + // The settings registry has been created at this point, so add the CMake target AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddBuildSystemTargetSpecialization( *AZ::SettingsRegistry::Get(), GetBuildTargetName()); } - MaterialEditorApplication::~MaterialEditorApplication() - { - AzToolsFramework::AssetDatabase::AssetDatabaseRequestsBus::Handler::BusDisconnect(); - AzToolsFramework::EditorPythonConsoleNotificationBus::Handler::BusDisconnect(); - } - void MaterialEditorApplication::CreateStaticModules(AZStd::vector& outModules) { Base::CreateStaticModules(outModules); @@ -101,13 +95,6 @@ namespace MaterialEditor void MaterialEditorApplication::ProcessCommandLine(const AZ::CommandLine& commandLine) { - const AZStd::string activateWindowSwitchName = "activatewindow"; - if (commandLine.HasSwitch(activateWindowSwitchName)) - { - AtomToolsFramework::AtomToolsMainWindowRequestBus::Broadcast( - &AtomToolsFramework::AtomToolsMainWindowRequestBus::Handler::ActivateWindow); - } - // Process command line options for opening one or more material documents on startup size_t openDocumentCount = commandLine.GetNumMiscValues(); for (size_t openDocumentIndex = 0; openDocumentIndex < openDocumentCount; ++openDocumentIndex) diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h index 2fbab79e41..6209a01116 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h @@ -26,7 +26,6 @@ namespace MaterialEditor using Base = AtomToolsFramework::AtomToolsApplication; MaterialEditorApplication(int* argc, char*** argv); - virtual ~MaterialEditorApplication(); ////////////////////////////////////////////////////////////////////////// // AzFramework::Application diff --git a/Gems/Atom/Tools/MaterialEditor/Scripts/GenerateAllMaterialScreenshots.py b/Gems/Atom/Tools/MaterialEditor/Scripts/GenerateAllMaterialScreenshots.py index d2c9bf209e..d7f52d7a24 100755 --- a/Gems/Atom/Tools/MaterialEditor/Scripts/GenerateAllMaterialScreenshots.py +++ b/Gems/Atom/Tools/MaterialEditor/Scripts/GenerateAllMaterialScreenshots.py @@ -114,11 +114,11 @@ def SetCameraPitch(pitch): azlmbr.render.ArcBallControllerRequestBus(azlmbr.bus.Broadcast, 'SetPitch', pitch) def IdleFrames(numFrames): - azlmbr.materialeditor.general.idle_wait_frames(numFrames) + azlmbr.atomtools.general.idle_wait_frames(numFrames) def CaptureScreenshot(screenshotOutputPath): print("Capturing screenshot to " + screenshotOutputPath + " ...") - return ScreenshotHelper(azlmbr.materialeditor.general.idle_wait_frames).capture_screenshot_blocking(screenshotOutputPath) + return ScreenshotHelper(azlmbr.atomtools.general.idle_wait_frames).capture_screenshot_blocking(screenshotOutputPath) def ResizeViewport(width, height): # This locks the size of the render target to the desired resolution diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp index e3b3c6e5aa..38319e7ce4 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp @@ -6,6 +6,18 @@ * */ +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + #include #include #include @@ -23,30 +35,17 @@ #include #include -#include - -#include -#include - #include #include -#include -#include - -#include -#include -#include -#include - AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT -#include #include #include AZ_POP_DISABLE_WARNING namespace ShaderManagementConsole { + //! This function returns the build system target name of "ShaderManagementConsole" AZStd::string ShaderManagementConsoleApplication::GetBuildTargetName() const { #if !defined (LY_CMAKE_TARGET) @@ -76,12 +75,6 @@ namespace ShaderManagementConsole *AZ::SettingsRegistry::Get(), GetBuildTargetName()); } - ShaderManagementConsoleApplication::~ShaderManagementConsoleApplication() - { - AzToolsFramework::AssetDatabase::AssetDatabaseRequestsBus::Handler::BusDisconnect(); - AzToolsFramework::EditorPythonConsoleNotificationBus::Handler::BusDisconnect(); - } - void ShaderManagementConsoleApplication::CreateStaticModules(AZStd::vector& outModules) { Base::CreateStaticModules(outModules); @@ -94,27 +87,19 @@ namespace ShaderManagementConsole return AZStd::vector({ "passes/", "config/" }); } - void ShaderManagementConsoleApplication::ProcessCommandLine() + void ShaderManagementConsoleApplication::ProcessCommandLine(const AZ::CommandLine& commandLine) { - // Process command line options for running one or more python scripts on startup - const AZStd::string runPythonScriptSwitchName = "runpython"; - size_t runPythonScriptCount = m_commandLine.GetNumSwitchValues(runPythonScriptSwitchName); - for (size_t runPythonScriptIndex = 0; runPythonScriptIndex < runPythonScriptCount; ++runPythonScriptIndex) - { - const AZStd::string runPythonScriptPath = m_commandLine.GetSwitchValue(runPythonScriptSwitchName, runPythonScriptIndex); - AZStd::vector runPythonArgs; - AzToolsFramework::EditorPythonRunnerRequestBus::Broadcast( - &AzToolsFramework::EditorPythonRunnerRequestBus::Events::ExecuteByFilenameWithArgs, - runPythonScriptPath, - runPythonArgs); - } - // Process command line options for opening one or more documents on startup size_t openDocumentCount = m_commandLine.GetNumMiscValues(); for (size_t openDocumentIndex = 0; openDocumentIndex < openDocumentCount; ++openDocumentIndex) { - const AZStd::string openDocumentPath = m_commandLine.GetMiscValue(openDocumentIndex); - ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::OpenDocument, openDocumentPath); + const AZStd::string openDocumentPath = commandLine.GetMiscValue(openDocumentIndex); + + AZ_Printf(GetBuildTargetName().c_str(), "Opening document: %s", openDocumentPath.c_str()); + ShaderManagementConsoleDocumentSystemRequestBus::Broadcast( + &ShaderManagementConsoleDocumentSystemRequestBus::Events::OpenDocument, openDocumentPath); } + + Base::ProcessCommandLine(commandLine); } } // namespace ShaderManagementConsole diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h index 4fad40400c..4e3f92c0e5 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h @@ -24,7 +24,6 @@ namespace ShaderManagementConsole using Base = AtomToolsFramework::AtomToolsApplication; ShaderManagementConsoleApplication(int* argc, char*** argv); - virtual ~ShaderManagementConsoleApplication(); ////////////////////////////////////////////////////////////////////////// // AzFramework::Application @@ -32,7 +31,7 @@ namespace ShaderManagementConsole const char* GetCurrentConfigurationName() const override; private: - void ProcessCommandLine(); + void ProcessCommandLine(const AZ::CommandLine& commandLine); AZStd::string GetBuildTargetName() const override; AZStd::vector GetCriticalAssetFilters() const override; }; From 9a82005cb8e3d516b43064651b056df6e57128e2 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Thu, 5 Aug 2021 12:42:33 -0700 Subject: [PATCH 132/803] PR comments/fixes Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../AzCore/AzCore/std/string/conversions.h | 26 ++++++++++++------- .../WinAPI/AzCore/Utils/Utils_WinAPI.cpp | 2 +- .../Linux/AzCore/Debug/Trace_Linux.cpp | 2 +- Code/Framework/AzCore/Tests/AZStd/String.cpp | 2 +- 4 files changed, 20 insertions(+), 12 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/std/string/conversions.h b/Code/Framework/AzCore/AzCore/std/string/conversions.h index 91af1029b4..235eb188d1 100644 --- a/Code/Framework/AzCore/AzCore/std/string/conversions.h +++ b/Code/Framework/AzCore/AzCore/std/string/conversions.h @@ -58,15 +58,15 @@ namespace AZStd } } - static inline void to_string(char* dest, size_t destSize, const wchar_t* first, const wchar_t* last) + static inline char* to_string(char* dest, size_t destSize, const wchar_t* first, const wchar_t* last) { if constexpr (Size == 2) { - Utf8::Unchecked::utf16to8(first, last, dest, destSize); + return Utf8::Unchecked::utf16to8(first, last, dest, destSize); } else if constexpr (Size == 4) { - Utf8::Unchecked::utf32to8(first, last, dest, destSize); + return Utf8::Unchecked::utf32to8(first, last, dest, destSize); } } @@ -96,15 +96,15 @@ namespace AZStd } } - static inline void to_wstring(wchar_t* dest, size_t destSize, const char* first, const char* last) + static inline wchar_t* to_wstring(wchar_t* dest, size_t destSize, const char* first, const char* last) { if constexpr (Size == 2) { - Utf8::Unchecked::utf8to16(first, last, dest, destSize); + return Utf8::Unchecked::utf8to16(first, last, dest, destSize); } else if constexpr (Size == 4) { - Utf8::Unchecked::utf8to32(first, last, dest, destSize); + return Utf8::Unchecked::utf8to32(first, last, dest, destSize); } } }; @@ -337,7 +337,11 @@ namespace AZStd if (srcLen > 0) { - Internal::WCharTPlatformConverter<>::to_string(dest, destSize, str, str + srcLen + 1); // copy null terminator + char* endStr = Internal::WCharTPlatformConverter<>::to_string(dest, destSize, str, str + srcLen); + if (*(endStr - 1) != '\0') + { + *endStr = '\0'; // copy null terminator + } } } @@ -485,12 +489,16 @@ namespace AZStd { if (srcLen == 0) { - srcLen = strlen(str) + 1; + srcLen = strlen(str); } if (srcLen > 0) { - Internal::WCharTPlatformConverter<>::to_wstring(dest, destSize, str, str + srcLen + 1); // copy null terminator + wchar_t* endWStr = Internal::WCharTPlatformConverter<>::to_wstring(dest, destSize, str, str + srcLen); + if (*(endWStr - 1) != '\0') + { + *endWStr = '\0'; // copy null terminator + } } } diff --git a/Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/Utils/Utils_WinAPI.cpp b/Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/Utils/Utils_WinAPI.cpp index a4af19a2a4..dc104668be 100644 --- a/Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/Utils/Utils_WinAPI.cpp +++ b/Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/Utils/Utils_WinAPI.cpp @@ -30,7 +30,7 @@ namespace AZ result.m_pathIncludesFilename = true; // Platform specific get exe path: http://stackoverflow.com/a/1024937 // https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getmodulefilenamea - wchar_t pathBufferW[AZ_MAX_PATH_LEN] = { 0 }; + wchar_t pathBufferW[AZ::IO::MaxPathLength] = { 0 }; const DWORD pathLen = GetModuleFileNameW(nullptr, pathBufferW, static_cast(exeStorageSize)); const DWORD errorCode = GetLastError(); if (pathLen == exeStorageSize && errorCode == ERROR_INSUFFICIENT_BUFFER) diff --git a/Code/Framework/AzCore/Platform/Linux/AzCore/Debug/Trace_Linux.cpp b/Code/Framework/AzCore/Platform/Linux/AzCore/Debug/Trace_Linux.cpp index 86c7e14ae6..1ca06fcf7f 100644 --- a/Code/Framework/AzCore/Platform/Linux/AzCore/Debug/Trace_Linux.cpp +++ b/Code/Framework/AzCore/Platform/Linux/AzCore/Debug/Trace_Linux.cpp @@ -15,7 +15,7 @@ namespace AZ { namespace Platform { - void OutputToDebugger(const char* title, const char* message) + void OutputToDebugger([[maybe_unused]] const char* title, [[maybe_unused]] const char* message) { // std::cout << title << ": " << message; } diff --git a/Code/Framework/AzCore/Tests/AZStd/String.cpp b/Code/Framework/AzCore/Tests/AZStd/String.cpp index c0d378bd39..309f561a75 100644 --- a/Code/Framework/AzCore/Tests/AZStd/String.cpp +++ b/Code/Framework/AzCore/Tests/AZStd/String.cpp @@ -703,7 +703,7 @@ namespace UnitTest AZ_TEST_ASSERT(0 == azwcsicmp(wstrBuffer, L"BlaBla 5")); // char buffer to wchar_t buffer - memset(wstrBuffer, 0, AZ_ARRAY_SIZE(wstrBuffer)); + memset(wstrBuffer, L' ', AZ_ARRAY_SIZE(wstrBuffer)); // to check that the null terminator is properly placed to_wstring(wstrBuffer, 9, strBuffer); AZ_TEST_ASSERT(0 == azwcsicmp(wstrBuffer, L"BLABLA 5")); From d955189a31a5f8eb6ddc4529c3d28421aba6a558 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Thu, 5 Aug 2021 12:43:46 -0700 Subject: [PATCH 133/803] Removal of unused files from Code/Editor XmlHistoryManager.cpp was being compiled but unused Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Editor/Animation/SkeletonHierarchy.cpp | 149 --- Code/Editor/Animation/SkeletonHierarchy.h | 57 -- Code/Editor/Animation/SkeletonMapper.cpp | 368 -------- Code/Editor/Animation/SkeletonMapper.h | 76 -- .../Animation/SkeletonMapperOperator.cpp | 284 ------ .../Editor/Animation/SkeletonMapperOperator.h | 164 ---- Code/Editor/ControlMRU.cpp | 135 --- Code/Editor/ControlMRU.h | 24 - Code/Editor/Controls/ConsoleSCBMFC.cpp | 543 ----------- Code/Editor/Util/IXmlHistoryManager.h | 73 -- Code/Editor/Util/StringNoCasePredicate.h | 62 -- Code/Editor/Util/XmlHistoryManager.cpp | 875 ------------------ Code/Editor/Util/XmlHistoryManager.h | 218 ----- Code/Editor/editor_lib_files.cmake | 4 - 14 files changed, 3032 deletions(-) delete mode 100644 Code/Editor/Animation/SkeletonHierarchy.cpp delete mode 100644 Code/Editor/Animation/SkeletonHierarchy.h delete mode 100644 Code/Editor/Animation/SkeletonMapper.cpp delete mode 100644 Code/Editor/Animation/SkeletonMapper.h delete mode 100644 Code/Editor/Animation/SkeletonMapperOperator.cpp delete mode 100644 Code/Editor/Animation/SkeletonMapperOperator.h delete mode 100644 Code/Editor/ControlMRU.cpp delete mode 100644 Code/Editor/ControlMRU.h delete mode 100644 Code/Editor/Controls/ConsoleSCBMFC.cpp delete mode 100644 Code/Editor/Util/IXmlHistoryManager.h delete mode 100644 Code/Editor/Util/StringNoCasePredicate.h delete mode 100644 Code/Editor/Util/XmlHistoryManager.cpp delete mode 100644 Code/Editor/Util/XmlHistoryManager.h diff --git a/Code/Editor/Animation/SkeletonHierarchy.cpp b/Code/Editor/Animation/SkeletonHierarchy.cpp deleted file mode 100644 index 3015ff5e27..0000000000 --- a/Code/Editor/Animation/SkeletonHierarchy.cpp +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - -#include "EditorDefs.h" -#include "SkeletonHierarchy.h" - -using namespace Skeleton; - -/* - - CHierarchy - -*/ - -CHierarchy::CHierarchy() -{ -} - -CHierarchy::~CHierarchy() -{ -} - -// - -uint32 CHierarchy::AddNode(const char* name, const QuatT& pose, int32 parent) -{ - int32 index = FindNodeIndexByName(name); - - if (index < 0) - { - m_nodes.push_back(SNode()); - index = int32(m_nodes.size() - 1); - } - - m_nodes[index].name = name; - m_nodes[index].pose = pose; - m_nodes[index].parent = parent; - return uint32(index); -} - -int32 CHierarchy::FindNodeIndexByName(const char* name) const -{ - uint32 count = uint32(m_nodes.size()); - for (uint32 i = 0; i < count; ++i) - { - if (::_stricmp(m_nodes[i].name, name)) - { - continue; - } - - return i; - } - - return -1; -} - -const CHierarchy::SNode* CHierarchy::FindNode(const char* name) const -{ - int32 index = FindNodeIndexByName(name); - return index < 0 ? NULL : &m_nodes[index]; -} - -void CHierarchy::CreateFrom(IDefaultSkeleton* pIDefaultSkeleton) -{ - const uint32 jointCount = pIDefaultSkeleton->GetJointCount(); - - m_nodes.clear(); - m_nodes.reserve(jointCount); - for (uint32 i = 0; i < jointCount; ++i) - { - m_nodes.push_back(SNode()); - - m_nodes.back().name = pIDefaultSkeleton->GetJointNameByID(int32(i)); - m_nodes.back().pose = pIDefaultSkeleton->GetDefaultAbsJointByID(int32(i)); - - m_nodes.back().parent = pIDefaultSkeleton->GetJointParentIDByID(int32(i)); - } - - ValidateReferences(); -} - -void CHierarchy::ValidateReferences() -{ - uint32 nodeCount = m_nodes.size(); - if (!nodeCount) - { - return; - } - - for (uint32 i = 0; i < nodeCount; ++i) - { - if (m_nodes[i].parent < nodeCount) - { - continue; - } - - m_nodes[i].parent = -1; - } -} - -void CHierarchy::AbsoluteToRelative(const QuatT* pSource, QuatT* pDestination) -{ - uint32 count = uint32(m_nodes.size()); - std::vector absolutes(count); - for (uint32 i = 0; i < count; ++i) - { - absolutes[i] = pSource[i]; - } - - for (uint32 i = 0; i < count; ++i) - { - int32 parent = m_nodes[i].parent; - if (parent < 0) - { - pDestination[i] = absolutes[i]; - continue; - } - - pDestination[i].t = (absolutes[i].t - absolutes[parent].t) * absolutes[parent].q; - pDestination[i].q = absolutes[parent].q.GetInverted() * absolutes[i].q; - } -} - -bool CHierarchy::SerializeTo(XmlNodeRef& node) -{ - XmlNodeRef hierarchy = node->newChild("Hierarchy"); - - uint32 nodeCount = uint32(m_nodes.size()); - std::vector nodes(nodeCount); - for (uint32 i = 0; i < nodeCount; ++i) - { - XmlNodeRef parent = hierarchy; - if (m_nodes[i].parent > -1) - { - parent = nodes[m_nodes[i].parent]; - } - - nodes[i] = parent->newChild("Node"); - nodes[i]->setAttr("name", m_nodes[i].name); - } - - return true; -} diff --git a/Code/Editor/Animation/SkeletonHierarchy.h b/Code/Editor/Animation/SkeletonHierarchy.h deleted file mode 100644 index ad0d8fc7fc..0000000000 --- a/Code/Editor/Animation/SkeletonHierarchy.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - -#ifndef CRYINCLUDE_EDITOR_ANIMATION_SKELETONHIERARCHY_H -#define CRYINCLUDE_EDITOR_ANIMATION_SKELETONHIERARCHY_H -#pragma once - -namespace Skeleton { - class CHierarchy - : public _reference_target_t - { - public: - struct SNode - { - string name; - QuatT pose; - - int32 parent; - - /* TODO: Implement - uint32 childrenIndex; - uint32 childrenCount; - */ - }; - - public: - CHierarchy(); - ~CHierarchy(); - - public: - uint32 AddNode(const char* name, const QuatT& pose, int32 parent = -1); - uint32 GetNodeCount() const { return uint32(m_nodes.size()); } - SNode* GetNode(uint32 index) { return &m_nodes[index]; } - const SNode* GetNode(uint32 index) const { return &m_nodes[index]; } - int32 FindNodeIndexByName(const char* name) const; - const SNode* FindNode(const char* name) const; - void ClearNodes() { m_nodes.clear(); } - - void CreateFrom(IDefaultSkeleton* rIDefaultSkeleton); - void ValidateReferences(); - - void AbsoluteToRelative(const QuatT* pSource, QuatT* pDestination); - - bool SerializeTo(XmlNodeRef& node); - - private: - std::vector m_nodes; - }; -} // namespace Skeleton - -#endif // CRYINCLUDE_EDITOR_ANIMATION_SKELETONHIERARCHY_H diff --git a/Code/Editor/Animation/SkeletonMapper.cpp b/Code/Editor/Animation/SkeletonMapper.cpp deleted file mode 100644 index 3913801fc8..0000000000 --- a/Code/Editor/Animation/SkeletonMapper.cpp +++ /dev/null @@ -1,368 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - -#include "EditorDefs.h" - -#include "SkeletonMapper.h" - -using namespace Skeleton; - -/* - - CMapper - -*/ - -CMapper::CMapper() -{ -} - -CMapper::~CMapper() -{ -} - -// - -void CMapper::CreateFromHierarchy() -{ - m_nodes.clear(); - - uint32 nodeCount = m_hierarchy.GetNodeCount(); - m_nodes.resize(nodeCount); -} - -// - -uint32 CMapper::CreateLocation(const char* name) -{ - int32 index = FindLocation(name); - if (index < 1) - { - CMapperLocation* pLocation = new CMapperLocation(); - pLocation->SetName(name); - m_locations.push_back(pLocation); - } - return uint32(m_locations.size() - 1); -} - -void CMapper::ClearLocations() -{ - uint32 count = uint32(m_nodes.size()); - for (uint32 i = 0; i < count; ++i) - { - m_nodes[i].position = NULL; - m_nodes[i].orientation = NULL; - } - - m_locations.clear(); -} - -int32 CMapper::FindLocation(const char* name) const -{ - uint32 count = uint32(m_locations.size()); - for (uint32 i = 0; i < count; ++i) - { - if (::_stricmp(m_locations[i]->GetName(), name)) - { - continue; - } - - return int32(i); - } - - return -1; -} - -void CMapper::SetLocation(CMapperLocation& location) -{ - int32 index = FindLocation(location.GetName()); - if (index < 0) - { - m_locations.push_back(&location); - return; - } - - m_locations[index] = &location; -} - -// - -bool CMapper::CreateLocationsHierarchy(uint32 index, CHierarchy& hierarchy, int32 hierarchyParent) -{ - if (NodeHasLocation(index)) - { - const CHierarchy::SNode* pNode = m_hierarchy.GetNode(index); - uint32 nodeIndex = hierarchy.AddNode(pNode->name, pNode->pose, hierarchyParent); - hierarchyParent = uint32(nodeIndex); - } - - std::vector children; - GetChildrenIndices(index, children); - uint32 childCount = uint32(children.size()); - for (uint32 i = 0; i < childCount; ++i) - { - CreateLocationsHierarchy(children[i], hierarchy, hierarchyParent); - } - - return hierarchy.GetNodeCount() != 0; -} - -bool CMapper::CreateLocationsHierarchy(CHierarchy& hierarchy) -{ - hierarchy.ClearNodes(); - if (!CreateLocationsHierarchy(0, hierarchy, -1)) - { - return false; - } - - hierarchy.ValidateReferences(); - return true; -} - -void CMapper::Map(QuatT* pResult) -{ - uint32 outputCount = m_hierarchy.GetNodeCount(); - std::vector absolutes(outputCount); - for (uint32 i = 0; i < outputCount; ++i) - { - pResult[i].SetIdentity(); - absolutes[i].SetIdentity(); - - CHierarchy::SNode* pNode = m_hierarchy.GetNode(i); - if (!pNode) - { - continue; - } - - CHierarchy::SNode* pParent = pNode->parent < 0 ? - NULL : m_hierarchy.GetNode(pNode->parent); - if (pParent) - { - pResult[i].t = - (pNode->pose.t - pParent->pose.t) * pParent->pose.q; - } - - if (m_nodes[i].position) - { - pResult[i].t = m_nodes[i].position->Compute().t; - } - - if (m_nodes[i].orientation) - { - absolutes[i] = m_nodes[i].orientation->Compute().q; - } - else if (pParent) - { - Quat relative = pParent->pose.q.GetInverted() * pNode->pose.q; - absolutes[i] = absolutes[pNode->parent] * relative; - } - } - - for (uint32 i = 0; i < outputCount; ++i) - { - CHierarchy::SNode* pNode = m_hierarchy.GetNode(i); - if (!pNode) - { - continue; - } - - CHierarchy::SNode* pParent = pNode->parent < 0 ? - NULL : m_hierarchy.GetNode(pNode->parent); - if (!pParent) - { - pResult[i].q = absolutes[i]; - continue; - } - - pResult[i].q = absolutes[i]; - if (!m_nodes[i].position) - { - pResult[i].t = pResult[pNode->parent].t + - pResult[i].t * absolutes[pNode->parent].GetInverted(); - } - } -} - -// - -bool CMapper::NodeHasLocation(uint32 index) -{ - if (CMapperOperator* pOperator = m_nodes[index].position) - { - if (pOperator->IsOfClass("Location")) - { - return true; - } - if (pOperator->HasLinksOfClass("Location")) - { - return true; - } - } - - if (CMapperOperator* pOperator = m_nodes[index].orientation) - { - if (pOperator->IsOfClass("Location")) - { - return true; - } - if (pOperator->HasLinksOfClass("Location")) - { - return true; - } - } - - return false; -} - -void CMapper::GetChildrenIndices(uint32 parent, std::vector& children) -{ - uint32 nodeCount = m_hierarchy.GetNodeCount(); - for (uint32 i = 0; i < nodeCount; ++i) - { - if (m_hierarchy.GetNode(i)->parent != parent) - { - continue; - } - - children.push_back(i); - } -} - -bool CMapper::ChildrenHaveLocation(uint32 index) -{ - std::vector children; - GetChildrenIndices(index, children); - - uint32 childrenCount = uint32(children.size()); - for (uint32 i = 0; i < childrenCount; ++i) - { - if (ChildrenHaveLocation(children[i])) - { - return true; - } - } - - return false; -} - -bool CMapper::NodeOrChildrenHaveLocation(uint32 index) -{ - if (NodeHasLocation(index)) - { - return true; - } - - std::vector children; - GetChildrenIndices(index, children); - - uint32 childrenCount = uint32(children.size()); - for (uint32 i = 0; i < childrenCount; ++i) - { - if (NodeOrChildrenHaveLocation(children[i])) - { - return true; - } - } - - return false; -} - -bool CMapper::SerializeTo(XmlNodeRef& node) -{ - XmlNodeRef hierarchy = node->newChild("Hierarchy"); - - uint32 nodeCount = GetNodeCount(); - std::vector nodes(nodeCount); - for (uint32 i = 0; i < nodeCount; ++i) - { - if (!NodeOrChildrenHaveLocation(i)) - { - continue; - } - - CHierarchy::SNode* pNode = m_hierarchy.GetNode(i); - if (!pNode) - { - return false; - } - - XmlNodeRef xmlParent = hierarchy; - int32 parent = pNode->parent; - if (parent > -1) - { - xmlParent = nodes[parent]; - } - - nodes[i] = xmlParent->newChild("Node"); - nodes[i]->setAttr("name", pNode->name); - - if (CMapperOperator* pOperator = m_nodes[i].position) - { - XmlNodeRef position = nodes[i]->newChild("Position"); - XmlNodeRef child = position->newChild("Operator"); - if (!pOperator->SerializeWithLinksTo(child)) - { - return false; - } - } - - if (CMapperOperator* pOperator = m_nodes[i].orientation) - { - XmlNodeRef orientation = nodes[i]->newChild("Orientation"); - XmlNodeRef child = orientation->newChild("Operator"); - if (!pOperator->SerializeWithLinksTo(child)) - { - return false; - } - } - } - - return true; -} - -bool CMapper::SerializeFrom(XmlNodeRef& node, int32 parent) -{ - int childCount = uint32(node->getChildCount()); - for (int i = 0; i < childCount; ++i) - { - XmlNodeRef child = node->getChild(i); - if (::_stricmp(child->getTag(), "Node")) - { - continue; - } - - uint32 index = m_hierarchy.AddNode(child->getAttr("name"), QuatT(IDENTITY), parent); - if (!SerializeFrom(child, int32(index))) - { - return false; - } - } - - return true; -} - -bool CMapper::SerializeFrom(XmlNodeRef& node) -{ - XmlNodeRef hierarchy = node->findChild("Hierarchy"); - if (!hierarchy) - { - return false; - } - - m_hierarchy.ClearNodes(); - - if (!SerializeFrom(hierarchy, -1)) - { - return false; - } - - m_nodes.resize(m_hierarchy.GetNodeCount()); - - return true; -} diff --git a/Code/Editor/Animation/SkeletonMapper.h b/Code/Editor/Animation/SkeletonMapper.h deleted file mode 100644 index 159b019396..0000000000 --- a/Code/Editor/Animation/SkeletonMapper.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - -#ifndef CRYINCLUDE_EDITOR_ANIMATION_SKELETONMAPPER_H -#define CRYINCLUDE_EDITOR_ANIMATION_SKELETONMAPPER_H -#pragma once - - -#include "SkeletonHierarchy.h" -#include "SkeletonMapperOperator.h" - -namespace Skeleton { - class CMapper - { - public: - struct SNode - { - _smart_ptr position; - _smart_ptr orientation; - }; - - public: - CMapper(); - ~CMapper(); - - public: - CHierarchy& GetHierarchy() { return m_hierarchy; } - void CreateFromHierarchy(); - - uint32 GetNodeCount() const { return uint32(m_nodes.size()); } - SNode* GetNode(uint32 index) { return &m_nodes[index]; } - const SNode* GetNode(uint32 index) const { return &m_nodes[index]; } - - uint32 CreateLocation(const char* name); - void ClearLocations(); - int32 FindLocation(const char* name) const; - - uint32 GetLocationCount() const { return uint32(m_locations.size()); } - void SetLocation(CMapperLocation& location); - CMapperLocation* GetLocation(uint32 index) { return m_locations[index]; } - const CMapperLocation* GetLocation(uint32 index) const { return m_locations[index]; } - - bool CreateLocationsHierarchy(CHierarchy& hierarchy); - - void Map(QuatT* pResult); - - bool SerializeTo(XmlNodeRef& node); - bool SerializeFrom(XmlNodeRef& node); - - private: - bool NodeHasLocation(uint32 index); - bool ChildrenHaveLocation(uint32 index); - bool NodeOrChildrenHaveLocation(uint32 index); - - bool SerializeFrom(XmlNodeRef& node, int32 parent); - - bool CreateLocationsHierarchy(uint32 index, CHierarchy& hierarchy, int32 hierarchyParent = -1); - - // TEMP - void GetChildrenIndices(uint32 parent, std::vector& children); - - private: - CHierarchy m_hierarchy; - std::vector<_smart_ptr > m_locations; - - std::vector m_nodes; - }; -} // namespace Skeleton - -#endif // CRYINCLUDE_EDITOR_ANIMATION_SKELETONMAPPER_H diff --git a/Code/Editor/Animation/SkeletonMapperOperator.cpp b/Code/Editor/Animation/SkeletonMapperOperator.cpp deleted file mode 100644 index 7a69173bed..0000000000 --- a/Code/Editor/Animation/SkeletonMapperOperator.cpp +++ /dev/null @@ -1,284 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - -#include "EditorDefs.h" - -#include "SkeletonMapperOperator.h" - -using namespace Skeleton; - -/* - - CMapperOperatorDesc - -*/ - -std::vector CMapperOperatorDesc::s_descs; - -// - -CMapperOperatorDesc::CMapperOperatorDesc(const char* name) -{ - s_descs.push_back(this); -} - -/* - - CMapperOperator - -*/ - -CMapperOperator::CMapperOperator(const char* className, uint32 positionCount, uint32 orientationCount) -{ - m_className = className; - m_position.resize(positionCount, NULL); - m_orientation.resize(orientationCount, NULL); -} - -CMapperOperator::~CMapperOperator() -{ -} - -// - -bool CMapperOperator::IsOfClass(const char* className) -{ - if (::_stricmp(m_className, className)) - { - return false; - } - - return true; -} - -uint32 CMapperOperator::HasLinksOfClass(const char* className) -{ - uint32 count = 0; - - uint32 positionCount = m_position.size(); - for (uint32 i = 0; i < positionCount; ++i) - { - CMapperOperator* pOperator = m_position[i]; - if (!pOperator) - { - continue; - } - - if (pOperator->IsOfClass(className)) - { - ++count; - } - } - - uint32 orientationCount = m_orientation.size(); - for (uint32 i = 0; i < orientationCount; ++i) - { - CMapperOperator* pOperator = m_orientation[i]; - if (!pOperator) - { - continue; - } - - if (pOperator->IsOfClass(className)) - { - ++count; - } - } - - return count; -} - -// - -bool CMapperOperator::SerializeTo(XmlNodeRef& node) -{ - node->setAttr("class", m_className); - - uint32 parameterCount = uint32(m_parameters.size()); - for (uint32 i = 0; i < parameterCount; ++i) - { - m_parameters[i]->Serialize(node, false); - } - - return true; -} - -bool CMapperOperator::SerializeFrom(XmlNodeRef& node) -{ - uint32 parameterCount = uint32(m_parameters.size()); - for (uint32 i = 0; i < parameterCount; ++i) - { - m_parameters[i]->Serialize(node, true); - } - - return true; -} - -bool CMapperOperator::SerializeWithLinksTo(XmlNodeRef& node) -{ - if (!SerializeTo(node)) - { - return false; - } - - uint32 positionCount = uint32(m_position.size()); - for (uint32 i = 0; i < positionCount; ++i) - { - CMapperOperator* pOperator = m_position[i]; - if (!pOperator) - { - continue; - } - - XmlNodeRef position = node->newChild("Position"); - position->setAttr("index", i); - - XmlNodeRef child = position->newChild("Operator"); - if (!pOperator->SerializeWithLinksTo(child)) - { - return false; - } - } - - uint32 orientationCount = uint32(m_orientation.size()); - for (uint32 i = 0; i < orientationCount; ++i) - { - CMapperOperator* pOperator = m_orientation[i]; - if (!pOperator) - { - continue; - } - - XmlNodeRef orientation = node->newChild("Orientation"); - orientation->setAttr("index", i); - - XmlNodeRef child = orientation->newChild("Operator"); - if (!pOperator->SerializeWithLinksTo(child)) - { - return false; - } - } - - return true; -} - -bool CMapperOperator::SerializeWithLinksFrom(XmlNodeRef& node) -{ - if (!SerializeFrom(node)) - { - return false; - } - - return true; -} -/* - - CMapperOperator_Transform - -*/ - -class CMapperOperator_Transform - : public CMapperOperator -{ -public: - CMapperOperator_Transform() - : CMapperOperator("Transform", 1, 1) - { - m_pAngles = new CVariable(); - m_pAngles->SetName("rotation"); - m_pAngles->Set(Vec3(0.0f, 0.0f, 0.0f)); - m_pAngles->SetLimits(-180.0f, 180.0f); - AddParameter(*m_pAngles); - - m_pVector = new CVariable(); - m_pVector->SetName("vector"); - m_pVector->Set(Vec3(0.0f, 0.0f, 0.0f)); - AddParameter(*m_pVector); - - m_pScale = new CVariable(); - m_pScale->SetName("scale"); - m_pScale->Set(Vec3(1.0f, 1.0f, 1.0f)); - AddParameter(*m_pScale); - } - - // CMapperOperator -public: - virtual QuatT CMapperOperator_Transform::Compute() - { - QuatT result(IDENTITY); - m_pVector->Get(result.t); - - Vec3 scale; - m_pScale->Get(scale); - - Vec3 angles; - m_pAngles->Get(angles); - - result.q = Quat::CreateRotationXYZ( - Ang3(DEG2RAD(angles.x), DEG2RAD(angles.y), DEG2RAD(angles.z))); - - if (CMapperOperator* pOperator = GetPosition(0)) - { - result.t = pOperator->Compute().t.CompMul(scale) + result.t; - } - if (CMapperOperator* pOperator = GetOrientation(0)) - { - result.q = pOperator->Compute().q * result.q; - } - return result; - } - -private: - CVariable* m_pVector; - CVariable* m_pAngles; - CVariable* m_pScale; -}; - -SkeletonMapperOperatorRegister(Transform, CMapperOperator_Transform) - -class CMapperOperator_PositionsToOrientation - : public CMapperOperator -{ -public: - CMapperOperator_PositionsToOrientation() - : CMapperOperator("PositionsToOrientation", 3, 0) - { - } - - // CMapperOperator -public: - virtual QuatT Compute() - { - CMapperOperator* pOperator0 = GetPosition(0); - CMapperOperator* pOperator1 = GetPosition(1); - CMapperOperator* pOperator2 = GetPosition(2); - if (!pOperator0 || !pOperator1 || !pOperator2) - { - return QuatT(IDENTITY); - } - - Vec3 p0 = pOperator0->Compute().t; - Vec3 p1 = pOperator1->Compute().t; - Vec3 p2 = pOperator2->Compute().t; - - Vec3 m = (p1 + p2) * 0.5f; - Vec3 y = (m - p0).GetNormalized(); - Vec3 z = (p1 - p2).GetNormalized(); - Vec3 x = y % z; - z = x % y; - - Matrix33 m33; - m33.SetFromVectors(x, y, z); - QuatT result(IDENTITY); - result.q = Quat(m33); - return result; - } -}; - -SkeletonMapperOperatorRegister(PositionsToOrientation, CMapperOperator_PositionsToOrientation) diff --git a/Code/Editor/Animation/SkeletonMapperOperator.h b/Code/Editor/Animation/SkeletonMapperOperator.h deleted file mode 100644 index 68bbb84ac7..0000000000 --- a/Code/Editor/Animation/SkeletonMapperOperator.h +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - -#ifndef CRYINCLUDE_EDITOR_ANIMATION_SKELETONMAPPEROPERATOR_H -#define CRYINCLUDE_EDITOR_ANIMATION_SKELETONMAPPEROPERATOR_H -#pragma once - - -#include "../Util/Variable.h" - -#undef GetClassName - -#define SkeletonMapperOperatorRegister(name, className) \ - class CMapperOperatorDesc_##name \ - : public CMapperOperatorDesc \ - { \ - public: \ - CMapperOperatorDesc_##name() \ - : CMapperOperatorDesc(#name) { } \ - protected: \ - virtual const char* GetName() { return #name; } \ - virtual CMapperOperator* Create() { return new className(); } \ - } mapperOperatorDesc__##name; - -namespace Skeleton { - class CMapperOperator; - - class CMapperOperatorDesc - { - public: - static uint32 GetCount() { return uint32(s_descs.size()); } - static const char* GetName(uint32 index) { return s_descs[index]->GetName(); } - static CMapperOperator* Create(uint32 index) { return s_descs[index]->Create(); } - - private: - static std::vector s_descs; - - public: - CMapperOperatorDesc(const char* name); - - protected: - virtual const char* GetName() = 0; - virtual CMapperOperator* Create() = 0; - }; - - class CMapperOperator - : public _reference_target_t - { - protected: - CMapperOperator(const char* className, uint32 positionCount, uint32 orientationCount); - ~CMapperOperator(); - - public: - const char* GetClassName() { return m_className; } - - uint32 GetPositionCount() const { return uint32(m_position.size()); } - void SetPosition(uint32 index, CMapperOperator* pOperator) { m_position[index] = pOperator; } - CMapperOperator* GetPosition(uint32 index) { return m_position[index]; } - - uint32 GetOrientationCount() const { return uint32(m_orientation.size()); } - void SetOrientation(uint32 index, CMapperOperator* pOperator) { m_orientation[index] = pOperator; } - CMapperOperator* GetOrientation(uint32 index) { return m_orientation[index]; } - - uint32 GetParameterCount() { return uint32(m_parameters.size()); } - IVariable* GetParameter(uint32 index) { return m_parameters[index]; } - - bool IsOfClass(const char* className); - uint32 HasLinksOfClass(const char* className); - - bool SerializeTo(XmlNodeRef& node); - bool SerializeFrom(XmlNodeRef& node); - - bool SerializeWithLinksTo(XmlNodeRef& node); - bool SerializeWithLinksFrom(XmlNodeRef& node); - - protected: - void AddParameter(IVariable& variable) { m_parameters.push_back(&variable); } - - public: - virtual QuatT Compute() = 0; - - private: - const char* m_className; - std::vector<_smart_ptr > m_position; - std::vector<_smart_ptr > m_orientation; - - std::vector m_parameters; - }; - - class CMapperLocation - : public CMapperOperator - { - public: - CMapperLocation() - : CMapperOperator("Location", 0, 0) - { - m_pName = new CVariable(); - m_pName->SetName("name"); - m_pName->SetFlags(m_pName->GetFlags() | IVariable::UI_INVISIBLE); - AddParameter(*m_pName); - - m_pAxis = new CVariable(); - m_pAxis->SetName("axis"); - m_pAxis->SetLimits(-3.0f, +3.0f); - m_pAxis->Set(Vec3(1.0f, 2.0f, 3.0f)); - AddParameter(*m_pAxis); - - m_location = QuatT(IDENTITY); - } - - public: - void SetName(const char* name) { m_pName->Set(name); } - CString GetName() const { CString s; m_pName->Get(s); return s; } - - void SetLocation(const QuatT& location) { m_location = location; } - const QuatT& GetLocation() const { return m_location; } - - // CMapperOperator - public: - virtual QuatT Compute() - { - Vec3 axis; - m_pAxis->Get(axis); - - uint32 x = fabs_tpl(axis.x); - uint32 y = fabs_tpl(axis.y); - uint32 z = fabs_tpl(axis.z); - if (x < 1 || y < 1 || z < 1 || - x > 3 || y > 3 || y > 3 || - x == y || x == z || y == z) - { - return QuatT(IDENTITY); - } - - Matrix33 matrix; - matrix.SetFromVectors( - m_location.q.GetColumn(x - 1) * f32(::sgn(axis.x)), - m_location.q.GetColumn(y - 1) * f32(::sgn(axis.y)), - m_location.q.GetColumn(z - 1) * f32(::sgn(axis.z))); - if (!matrix.IsOrthonormalRH(0.01f)) - { - return QuatT(IDENTITY); - } - - QuatT result = m_location; - result.q = Quat(matrix); - return result; - } - - private: - CVariable* m_pName; - CVariable* m_pAxis; - - QuatT m_location; - }; -} // namespace Skeleton - -#endif // CRYINCLUDE_EDITOR_ANIMATION_SKELETONMAPPEROPERATOR_H diff --git a/Code/Editor/ControlMRU.cpp b/Code/Editor/ControlMRU.cpp deleted file mode 100644 index 47de13950f..0000000000 --- a/Code/Editor/ControlMRU.cpp +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - -#include "EditorDefs.h" -#include "ControlMRU.h" - -IMPLEMENT_XTP_CONTROL(CControlMRU, CXTPControlRecentFileList) - -bool CControlMRU::DoesFileExist(CString& sFileName) -{ - return (_access(sFileName.GetBuffer(), 0) == 0); -} - -void CControlMRU::OnCalcDynamicSize(DWORD dwMode) -{ - CRecentFileList* pRecentFileList = GetRecentFileList(); - - if (!pRecentFileList) - { - return; - } - - CString* pArrNames = pRecentFileList->m_arrNames; - - assert(pArrNames != NULL); - if (!pArrNames) - { - return; - } - - while (m_nIndex + 1 < m_pControls->GetCount()) - { - CXTPControl* pControl = m_pControls->GetAt(m_nIndex + 1); - assert(pControl); - if (pControl->GetID() >= GetFirstMruID() - && pControl->GetID() <= GetFirstMruID() + pRecentFileList->m_nSize) - { - m_pControls->Remove(pControl); - } - else - { - break; - } - } - - if (m_pParent->IsCustomizeMode()) - { - m_dwHideFlags = 0; - SetEnabled(TRUE); - return; - } - - if (pArrNames[0].IsEmpty()) - { - SetCaption(CString(MAKEINTRESOURCE(IDS_NORECENTFILE_CAPTION))); - SetDescription("No recently opened files"); - m_dwHideFlags = 0; - SetEnabled(FALSE); - - return; - } - else - { - SetCaption(CString(MAKEINTRESOURCE(IDS_RECENTFILE_CAPTION))); - SetDescription("Open this document"); - } - - m_dwHideFlags |= xtpHideGeneric; - - CString sCurDir = (Path::GetEditingGameDataFolder() + "\\").c_str(); - int nCurDir = sCurDir.GetLength(); - - CString strName; - CString strTemp; - int iLastValidMRU = 0; - - for (int iMRU = 0; iMRU < pRecentFileList->m_nSize; iMRU++) - { - if (!pRecentFileList->GetDisplayName(strName, iMRU, sCurDir.GetBuffer(), nCurDir)) - { - break; - } - - if (DoesFileExist(pArrNames[iMRU])) - { - CString sCurEntryDir = pArrNames[iMRU].Left(nCurDir); - - if (sCurEntryDir.CompareNoCase(sCurDir) != 0) - { - //unavailable entry (wrong directory) - continue; - } - } - else - { - //invalid entry (not existing) - continue; - } - - int nId = iMRU + GetFirstMruID(); - - CXTPControl* pControl = m_pControls->Add(xtpControlButton, nId, _T(""), m_nIndex + iLastValidMRU + 1, TRUE); - assert(pControl); - - pControl->SetCaption(CXTPControlWindowList::ConstructCaption(strName, iLastValidMRU + 1)); - pControl->SetFlags(xtpFlagManualUpdate); - pControl->SetBeginGroup(iLastValidMRU == 0 && m_nIndex != 0); - pControl->SetParameter(pArrNames[iMRU]); - - CString sDescription = "Open file: " + pArrNames[iMRU]; - pControl->SetDescription(sDescription); - - if ((GetFlags() & xtpFlagWrapRow) && iMRU == 0) - { - pControl->SetFlags(pControl->GetFlags() | xtpFlagWrapRow); - } - - ++iLastValidMRU; - } - - //if no entry was valid, treat as none would exist - if (iLastValidMRU == 0) - { - SetCaption(CString(MAKEINTRESOURCE(IDS_NORECENTFILE_CAPTION))); - SetDescription("No recently opened files"); - m_dwHideFlags = 0; - SetEnabled(FALSE); - } -} diff --git a/Code/Editor/ControlMRU.h b/Code/Editor/ControlMRU.h deleted file mode 100644 index 4ca6562589..0000000000 --- a/Code/Editor/ControlMRU.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - -#pragma once -#ifndef CRYINCLUDE_EDITOR_CONTROLMRU_H -#define CRYINCLUDE_EDITOR_CONTROLMRU_H - -class CControlMRU - : public CXTPControlRecentFileList -{ -protected: - virtual void OnCalcDynamicSize(DWORD dwMode); - -private: - DECLARE_XTP_CONTROL(CControlMRU) - bool DoesFileExist(CString& sFileName); -}; -#endif // CRYINCLUDE_EDITOR_CONTROLMRU_H diff --git a/Code/Editor/Controls/ConsoleSCBMFC.cpp b/Code/Editor/Controls/ConsoleSCBMFC.cpp deleted file mode 100644 index 3337997811..0000000000 --- a/Code/Editor/Controls/ConsoleSCBMFC.cpp +++ /dev/null @@ -1,543 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - -#include "EditorDefs.h" -#include "ConsoleSCBMFC.h" -#include "PropertiesDialog.h" -#include "QtViewPaneManager.h" -#include "Core/QtEditorApplication.h" - -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -namespace MFC -{ - -static CPropertiesDialog* gPropertiesDlg = nullptr; -static CString mfc_popup_helper(HWND hwnd, int x, int y); -static CConsoleSCB* s_consoleSCB = nullptr; - -static QString RemoveColorCode(const QString& text, int& iColorCode) -{ - QString cleanString; - cleanString.reserve(text.size()); - - const int textSize = text.size(); - for (int i = 0; i < textSize; ++i) - { - QChar c = text.at(i); - bool isLast = i == textSize - 1; - if (c == '$' && !isLast && text.at(i + 1).isDigit()) - { - if (iColorCode == 0) - { - iColorCode = text.at(i + 1).digitValue(); - } - ++i; - continue; - } - - if (c == '\r' || c == '\n') - { - ++i; - continue; - } - - cleanString.append(c); - } - - return cleanString; -} - -ConsoleLineEdit::ConsoleLineEdit(QWidget* parent) - : QLineEdit(parent) - , m_historyIndex(0) - , m_bReusedHistory(false) -{ -} - -void ConsoleLineEdit::mousePressEvent(QMouseEvent* ev) -{ - if (ev->type() == QEvent::MouseButtonPress && ev->button() & Qt::RightButton) - { - Q_EMIT variableEditorRequested(); - } - - QLineEdit::mousePressEvent(ev); -} - -void ConsoleLineEdit::mouseDoubleClickEvent(QMouseEvent* ev) -{ - Q_EMIT variableEditorRequested(); -} - -bool ConsoleLineEdit::event(QEvent* ev) -{ - // Tab key doesn't go to keyPressEvent(), must be processed here - - if (ev->type() != QEvent::KeyPress) - { - return QLineEdit::event(ev); - } - - QKeyEvent* ke = static_cast(ev); - if (ke->key() != Qt::Key_Tab) - { - return QLineEdit::event(ev); - } - - QString inputStr = text(); - QString newStr; - - QStringList tokens = inputStr.split(" "); - inputStr = tokens.isEmpty() ? QString() : tokens.first(); - IConsole* console = GetIEditor()->GetSystem()->GetIConsole(); - - const bool ctrlPressed = ke->modifiers() & Qt::ControlModifier; - CString cstring = QtUtil::ToCString(inputStr); // TODO: Use QString once the backend stops using QString - if (ctrlPressed) - { - newStr = QtUtil::ToString(console->AutoCompletePrev(cstring)); - } - else - { - newStr = QtUtil::ToString(console->ProcessCompletion(cstring)); - newStr = QtUtil::ToString(console->AutoComplete(cstring)); - - if (newStr.isEmpty()) - { - newStr = QtUtil::ToQString(GetIEditor()->GetCommandManager()->AutoComplete(QtUtil::ToString(newStr))); - } - } - - if (!newStr.isEmpty()) - { - newStr += " "; - setText(newStr); - } - - deselect(); - return true; -} - -void ConsoleLineEdit::keyPressEvent(QKeyEvent* ev) -{ - IConsole* console = GetIEditor()->GetSystem()->GetIConsole(); - auto commandManager = GetIEditor()->GetCommandManager(); - - console->ResetAutoCompletion(); - - switch (ev->key()) - { - case Qt::Key_Enter: - case Qt::Key_Return: - { - QString str = text().trimmed(); - if (!str.isEmpty()) - { - if (commandManager->IsRegistered(QtUtil::ToCString(str))) - { - commandManager->Execute(QtUtil::ToString(str)); - } - else - { - CLogFile::WriteLine(QtUtil::ToCString(str)); - GetIEditor()->GetSystem()->GetIConsole()->ExecuteString(QtUtil::ToCString(str)); - } - - // If a history command was reused directly via up arrow enter, do not reset history index - if (m_history.size() > 0 && m_historyIndex < m_history.size() && m_history[m_historyIndex] == str) - { - m_bReusedHistory = true; - } - else - { - m_historyIndex = m_history.size(); - } - - // Do not add the same string if it is the top of the stack, but allow duplicate entries otherwise - if (m_history.isEmpty() || m_history.back() != str) - { - m_history.push_back(str); - if (!m_bReusedHistory) - { - m_historyIndex = m_history.size(); - } - } - } - else - { - m_historyIndex = m_history.size(); - } - - setText(QString()); - break; - } - case Qt::Key_AsciiTilde: // ~ - case Qt::Key_Agrave: // ` - // disable log. - GetIEditor()->ShowConsole(false); - setText(QString()); - m_historyIndex = m_history.size(); - break; - case Qt::Key_Escape: - setText(QString()); - m_historyIndex = m_history.size(); - break; - case Qt::Key_Up: - DisplayHistory(false /*bForward*/); - break; - case Qt::Key_Down: - DisplayHistory(true /*bForward*/); - break; - default: - QLineEdit::keyPressEvent(ev); - } -} - -void ConsoleLineEdit::DisplayHistory(bool bForward) -{ - if (m_history.isEmpty()) - { - return; - } - - // Immediately after reusing a history entry, ensure up arrow re-displays command just used - if (!m_bReusedHistory || bForward) - { - m_historyIndex = static_cast(clamp_tpl(static_cast(m_historyIndex) + (bForward ? 1 : -1), 0, m_history.size() - 1)); - } - m_bReusedHistory = false; - - setText(m_history[m_historyIndex]); -} - -ConsoleTextEdit::ConsoleTextEdit(QWidget* parent) - : QTextEdit(parent) -{ -} - - -Lines CConsoleSCB::s_pendingLines; - -CConsoleSCB::CConsoleSCB(QWidget* parent) - : QWidget(parent) - , ui(new Ui::ConsoleMFC()) - , m_richEditTextLength(0) - , m_backgroundTheme(gSettings.consoleBackgroundColorTheme) -{ - m_lines = s_pendingLines; - s_pendingLines.clear(); - s_consoleSCB = this; - ui->setupUi(this); - setMinimumHeight(120); - - // Setup the color table for the default (light) theme - m_colorTable << QColor(0, 0, 0) - << QColor(0, 0, 0) - << QColor(0, 0, 200) // blue - << QColor(0, 200, 0) // green - << QColor(200, 0, 0) // red - << QColor(0, 200, 200) // cyan - << QColor(128, 112, 0) // yellow - << QColor(200, 0, 200) // red+blue - << QColor(0x000080ff) - << QColor(0x008f8f8f); - OnStyleSettingsChanged(); - - connect(ui->button, &QPushButton::clicked, this, &CConsoleSCB::showVariableEditor); - connect(ui->lineEdit, &MFC::ConsoleLineEdit::variableEditorRequested, this, &MFC::CConsoleSCB::showVariableEditor); - connect(Editor::EditorQtApplication::instance(), &Editor::EditorQtApplication::skinChanged, this, &MFC::CConsoleSCB::OnStyleSettingsChanged); - - if (GetIEditor()->IsInConsolewMode()) - { - // Attach / register edit box - //CLogFile::AttachEditBox(m_edit.GetSafeHwnd()); // FIXME - } -} - -CConsoleSCB::~CConsoleSCB() -{ - s_consoleSCB = nullptr; - delete gPropertiesDlg; - gPropertiesDlg = nullptr; - CLogFile::AttachEditBox(nullptr); -} - -void CConsoleSCB::RegisterViewClass() -{ - QtViewOptions opts; - opts.preferedDockingArea = Qt::BottomDockWidgetArea; - opts.isDeletable = false; - opts.isStandard = true; - opts.showInMenu = true; - opts.builtInActionId = ID_VIEW_CONSOLEWINDOW; - opts.sendViewPaneNameBackToAmazonAnalyticsServers = true; - RegisterQtViewPane(GetIEditor(), LyViewPane::Console, LyViewPane::CategoryTools, opts); -} - -void CConsoleSCB::OnStyleSettingsChanged() -{ - ui->button->setIcon(QIcon(QString(":/controls/img/cvar_dark.bmp"))); - - // Set the debug/warning text colors appropriately for the background theme - // (e.g. not have black text on black background) - QColor textColor = Qt::black; - m_backgroundTheme = gSettings.consoleBackgroundColorTheme; - if (m_backgroundTheme == SEditorSettings::ConsoleColorTheme::Dark) - { - textColor = Qt::white; - } - m_colorTable[0] = textColor; - m_colorTable[1] = textColor; - - QColor bgColor; - if (!GetIEditor()->IsInConsolewMode() && CConsoleSCB::GetCreatedInstance() && m_backgroundTheme == SEditorSettings::ConsoleColorTheme::Dark) - { - bgColor = Qt::black; - } - else - { - bgColor = Qt::white; - } - - ui->textEdit->setStyleSheet(QString("QTextEdit{ background: %1 }").arg(bgColor.name(QColor::HexRgb))); - - // Clear out the console text when we change our background color since - // some of the previous text colors may not be appropriate for the - // new background color - ui->textEdit->clear(); -} - -void CConsoleSCB::showVariableEditor() -{ - const QPoint cursorPos = QCursor::pos(); - CString str = mfc_popup_helper(0, cursorPos.x(), cursorPos.y()); - if (!str.IsEmpty()) - { - ui->lineEdit->setText(QtUtil::ToQString(str)); - } -} - -void CConsoleSCB::SetInputFocus() -{ - ui->lineEdit->setFocus(); - ui->lineEdit->setText(QString()); -} - -void CConsoleSCB::AddToConsole(const QString& text, bool bNewLine) -{ - m_lines.push_back({ text, bNewLine }); - FlushText(); -} - -void CConsoleSCB::FlushText() -{ - if (m_lines.empty()) - { - return; - } - - // Store our current cursor in case we need to restore it, and check if - // the user has scrolled the text edit away from the bottom - const QTextCursor oldCursor = ui->textEdit->textCursor(); - QScrollBar* scrollBar = ui->textEdit->verticalScrollBar(); - const int oldScrollValue = scrollBar->value(); - bool scrolledOffBottom = oldScrollValue != scrollBar->maximum(); - - ui->textEdit->moveCursor(QTextCursor::End); - QTextCursor textCursor = ui->textEdit->textCursor(); - - while (!m_lines.empty()) - { - ConsoleLine line = m_lines.front(); - m_lines.pop_front(); - - int iColor = 0; - QString text = MFC::RemoveColorCode(line.text, iColor); - if (iColor < 0 || iColor >= m_colorTable.size()) - { - iColor = 0; - } - - if (line.newLine) - { - text = QtUtil::trimRight(text); - text = "\r\n" + text; - } - - QTextCharFormat format; - const QColor color(m_colorTable[iColor]); - format.setForeground(color); - - if (iColor != 0) - { - format.setFontWeight(QFont::Bold); - } - - textCursor.setCharFormat(format); - textCursor.insertText(text); - } - - // If the user has selected some text in the text edit area or has scrolled - // away from the bottom, then restore the previous cursor and keep the scroll - // bar in the same location - if (oldCursor.hasSelection() || scrolledOffBottom) - { - ui->textEdit->setTextCursor(oldCursor); - scrollBar->setValue(oldScrollValue); - } - // Otherwise scroll to the bottom so the latest text can be seen - else - { - scrollBar->setValue(scrollBar->maximum()); - } -} - -QSize CConsoleSCB::minimumSizeHint() const -{ - return QSize(-1, -1); -} - -QSize CConsoleSCB::sizeHint() const -{ - return QSize(100, 100); -} - -/** static */ -void CConsoleSCB::AddToPendingLines(const QString& text, bool bNewLine) -{ - s_pendingLines.push_back({ text, bNewLine }); -} - -static CVarBlock* VarBlockFromConsoleVars() -{ - IConsole* console = GetIEditor()->GetSystem()->GetIConsole(); - std::vector cmds; - cmds.resize(console->GetNumVars()); - size_t cmdCount = console->GetSortedVars(&cmds[0], cmds.size()); - - CVarBlock* vb = new CVarBlock; - IVariable* pVariable = 0; - for (int i = 0; i < cmdCount; i++) - { - ICVar* pCVar = console->GetCVar(cmds[i]); - if (!pCVar) - { - continue; - } - int varType = pCVar->GetType(); - - switch (varType) - { - case CVAR_INT: - pVariable = new CVariable(); - pVariable->Set(pCVar->GetIVal()); - break; - case CVAR_FLOAT: - pVariable = new CVariable(); - pVariable->Set(pCVar->GetFVal()); - break; - case CVAR_STRING: - pVariable = new CVariable(); - pVariable->Set(pCVar->GetString()); - break; - default: - assert(0); - } - - pVariable->SetDescription(pCVar->GetHelp()); - pVariable->SetName(cmds[i]); - - if (pVariable) - { - vb->AddVariable(pVariable); - } - } - return vb; -} - -static void OnConsoleVariableUpdated(IVariable* pVar) -{ - if (!pVar) - { - return; - } - CString varName = pVar->GetName(); - ICVar* pCVar = GetIEditor()->GetSystem()->GetIConsole()->GetCVar(varName); - if (!pCVar) - { - return; - } - if (pVar->GetType() == IVariable::INT) - { - int val; - pVar->Get(val); - pCVar->Set(val); - } - else if (pVar->GetType() == IVariable::FLOAT) - { - float val; - pVar->Get(val); - pCVar->Set(val); - } - else if (pVar->GetType() == IVariable::STRING) - { - CString val; - pVar->Get(val); - pCVar->Set(val); - } -} - -static CString mfc_popup_helper(HWND hwnd, int x, int y) -{ - IConsole* console = GetIEditor()->GetSystem()->GetIConsole(); - - TSmartPtr vb = VarBlockFromConsoleVars(); - XmlNodeRef node; - if (!gPropertiesDlg) - { - gPropertiesDlg = new CPropertiesDialog("Console Variables", node, AfxGetMainWnd(), true); - } - if (!gPropertiesDlg->m_hWnd) - { - gPropertiesDlg->Create(CPropertiesDialog::IDD, AfxGetMainWnd()); - gPropertiesDlg->SetUpdateCallback(AZStd::bind(OnConsoleVariableUpdated, AZStd::placeholders::_1)); - } - gPropertiesDlg->ShowWindow(SW_SHOW); - gPropertiesDlg->BringWindowToTop(); - gPropertiesDlg->GetPropertyCtrl()->AddVarBlock(vb); - - return ""; -} - -CConsoleSCB* CConsoleSCB::GetCreatedInstance() -{ - return s_consoleSCB; -} - -} // namespace MFC - -#include diff --git a/Code/Editor/Util/IXmlHistoryManager.h b/Code/Editor/Util/IXmlHistoryManager.h deleted file mode 100644 index e133d073bc..0000000000 --- a/Code/Editor/Util/IXmlHistoryManager.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - -#ifndef CRYINCLUDE_EDITOR_UTIL_IXMLHISTORYMANAGER_H -#define CRYINCLUDE_EDITOR_UTIL_IXMLHISTORYMANAGER_H -#pragma once - - -// Helper class to handle Redo/Undo on set of Xml nodes -struct IXmlUndoEventHandler -{ - virtual bool SaveToXml(XmlNodeRef& xmlNode) = 0; - virtual bool LoadFromXml(const XmlNodeRef& xmlNode) = 0; - virtual bool ReloadFromXml(const XmlNodeRef& xmlNode) = 0; -}; - -struct IXmlHistoryEventListener -{ - enum EHistoryEventType - { - eHET_HistoryDeleted, - eHET_HistoryCleared, - eHET_HistorySaved, - - eHET_VersionChanged, - eHET_VersionAdded, - - eHET_HistoryInvalidate, - - eHET_HistoryGroupChanged, - eHET_HistoryGroupAdded, - eHET_HistoryGroupRemoved, - }; - virtual void OnEvent(EHistoryEventType event, void* pData = NULL) = 0; -}; - -struct IXmlHistoryView -{ - virtual bool LoadXml(int typeId, const XmlNodeRef& xmlNode, IXmlUndoEventHandler*& pUndoEventHandler, uint32 userindex) = 0; - virtual void UnloadXml(int typeId) = 0; -}; - -struct IXmlHistoryManager -{ - // Undo/Redo - virtual bool Undo() = 0; - virtual bool Redo() = 0; - virtual bool Goto(int historyNum) = 0; - virtual void RecordUndo(IXmlUndoEventHandler* pEventHandler, const char* desc) = 0; - virtual void UndoEventHandlerDestroyed(IXmlUndoEventHandler* pEventHandler, uint32 typeId = 0, bool destoryForever = false) = 0; - virtual void RestoreUndoEventHandler(IXmlUndoEventHandler* pEventHandler, uint32 typeId) = 0; - - virtual void RegisterEventListener(IXmlHistoryEventListener* pEventListener) = 0; - virtual void UnregisterEventListener(IXmlHistoryEventListener* pEventListener) = 0; - - // History - virtual void ClearHistory(bool flagAsSaved = false) = 0; - virtual int GetVersionCount() const = 0; - virtual const AZStd::string& GetVersionDesc(int number) const = 0; - virtual int GetCurrentVersionNumber() const = 0; - - // Views - virtual void RegisterView(IXmlHistoryView* pView) = 0; - virtual void UnregisterView(IXmlHistoryView* pView) = 0; -}; - -#endif // CRYINCLUDE_EDITOR_UTIL_IXMLHISTORYMANAGER_H diff --git a/Code/Editor/Util/StringNoCasePredicate.h b/Code/Editor/Util/StringNoCasePredicate.h deleted file mode 100644 index 4fb81cf7d6..0000000000 --- a/Code/Editor/Util/StringNoCasePredicate.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - -// Description : Utility class to help in STL algorithms on containers with -// CStrings when intending to use case insensitive searches or sorting for -// example. - - -#ifndef CRYINCLUDE_EDITOR_UTIL_STRINGNOCASEPREDICATE_H -#define CRYINCLUDE_EDITOR_UTIL_STRINGNOCASEPREDICATE_H -#pragma once - -/* -Utility class to help in STL algorithms on containers with CStrings -when intending to use case insensitive searches or sorting for example. - -e.g. -std::vector< CString > v; -... -std::sort( v.begin(), v.end(), CStringNoCasePredicate::LessThan() ); -std::find_if( v.begin(), v.end(), CStringNoCasePredicate::Equal( stringImLookingFor ) ); -*/ -class CStringNoCasePredicate -{ -public: - ////////////////////////////////////////////////////////////////////////// - struct Equal - { - Equal(const QString& referenceString) - : m_referenceString(referenceString) - { - } - - bool operator() (const QString& arg) const - { - return (m_referenceString.compare(arg, Qt::CaseInsensitive) == 0); - } - - private: - const QString& m_referenceString; - }; - ////////////////////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////////////////////////////// - struct LessThan - { - bool operator() (const QString& arg1, const QString& arg2) const - { - return (arg1.CompareNoCase(arg2) < 0); - } - }; - ////////////////////////////////////////////////////////////////////////// -}; - - -#endif // CRYINCLUDE_EDITOR_UTIL_STRINGNOCASEPREDICATE_H diff --git a/Code/Editor/Util/XmlHistoryManager.cpp b/Code/Editor/Util/XmlHistoryManager.cpp deleted file mode 100644 index b642929af1..0000000000 --- a/Code/Editor/Util/XmlHistoryManager.cpp +++ /dev/null @@ -1,875 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - -#include "EditorDefs.h" - -#include "XmlHistoryManager.h" - -//////////////////////////////////////////////////////////////////////////// -SXmlHistory::SXmlHistory(CXmlHistoryManager* pManager, const XmlNodeRef& xmlBaseVersion, uint32 typeId) - : m_pManager(pManager) - , m_typeId(typeId) - , m_DeletedVersion(-1) - , m_SavedVersion(-1) -{ - int newVersionNumber = m_pManager->GetCurrentVersionNumber() + (m_pManager->IsPreparedForNextVersion() ? 1 : 0); - m_xmlVersionList[ newVersionNumber ] = xmlBaseVersion; -} - -//////////////////////////////////////////////////////////////////////////// -void SXmlHistory::AddToHistory(const XmlNodeRef& newXmlVersion) -{ - int newVersionNumber = m_pManager->IncrementVersion(this); - m_xmlVersionList[ newVersionNumber ] = newXmlVersion; -} - -//////////////////////////////////////////////////////////////////////////// -const XmlNodeRef& SXmlHistory::Undo(bool* bVersionExist) -{ - m_pManager->Undo(); - return GetCurrentVersion(bVersionExist); -} - -//////////////////////////////////////////////////////////////////////////// -const XmlNodeRef& SXmlHistory::Redo() -{ - m_pManager->Redo(); - return GetCurrentVersion(); -} - -//////////////////////////////////////////////////////////////////////////// -const XmlNodeRef& SXmlHistory::GetCurrentVersion(bool* bVersionExist, int* iVersionNumber) const -{ - int currentVersion = m_pManager->GetCurrentVersionNumber(); - - TXmlVersionMap::const_iterator it = m_xmlVersionList.begin(); - TXmlVersionMap::const_iterator previt = m_xmlVersionList.begin(); - while (it != m_xmlVersionList.end()) - { - if (it->first > currentVersion) - { - break; - } - previt = it; - ++it; - } - - if (bVersionExist) - { - *bVersionExist = currentVersion >= m_xmlVersionList.begin()->first; - } - if (iVersionNumber) - { - *iVersionNumber = previt->first; - } - - return previt->second; -} - -//////////////////////////////////////////////////////////////////////////// -bool SXmlHistory::IsModified() const -{ - int currVersion; - GetCurrentVersion(NULL, &currVersion); - return m_SavedVersion != currVersion; -} - -//////////////////////////////////////////////////////////////////////////// -void SXmlHistory::FlagAsDeleted() -{ - assert(m_pManager->IsPreparedForNextVersion()); - m_DeletedVersion = m_pManager->GetCurrentVersionNumber() + 1; - m_SavedVersion = -1; -} - -//////////////////////////////////////////////////////////////////////////// -void SXmlHistory::FlagAsSaved() -{ - if (Exist()) - { - int currVersion; - GetCurrentVersion(NULL, &currVersion); - m_SavedVersion = currVersion; - } -} - -//////////////////////////////////////////////////////////////////////////// -bool SXmlHistory::Exist() const -{ - // int currentVersion = m_pManager->GetCurrentVersionNumber(); - // bool deleted = m_DeletedVersion != -1 && currentVersion >= m_DeletedVersion; - // bool exist = currentVersion >= m_xmlVersionList.begin()->first; - // return !deleted && exist; - int currentVersion = m_pManager->GetCurrentVersionNumber(); - return currentVersion >= m_xmlVersionList.begin()->first && (m_DeletedVersion == -1 || currentVersion < m_DeletedVersion); -} - -//////////////////////////////////////////////////////////////////////////// -void SXmlHistory::ClearRedo() -{ - int currentVersion = m_pManager->GetCurrentVersionNumber(); - if (m_DeletedVersion > currentVersion + (m_pManager->IsPreparedForNextVersion() ? 1 : 0)) - { - m_DeletedVersion = -1; - } - TXmlVersionMap::iterator it = m_xmlVersionList.begin(); - for (; it != m_xmlVersionList.end(); ++it) - { - if (it->first > currentVersion) - { - break; - } - } - if (it != m_xmlVersionList.end()) - { - ++it; - while (it != m_xmlVersionList.end()) - { - m_xmlVersionList.erase(it++); - } - } -} - -//////////////////////////////////////////////////////////////////////////// -void SXmlHistory::ClearHistory(bool flagAsSaved) -{ - bool wasModified = !flagAsSaved && IsModified(); - m_DeletedVersion = Exist() ? -1 : 0; - ClearRedo(); - XmlNodeRef latest = m_xmlVersionList.rbegin()->second; - m_xmlVersionList.clear(); - m_xmlVersionList[ 0 ] = latest; - m_SavedVersion = wasModified ? -1 : 0; -} - -//////////////////////////////////////////////////////////////////////////// -SXmlHistoryGroup::SXmlHistoryGroup(CXmlHistoryManager* pManager, uint32 typeId) - : m_pManager(pManager) - , m_typeId(typeId) -{ -} - -//////////////////////////////////////////////////////////////////////////// -SXmlHistory* SXmlHistoryGroup::GetHistory(int index) const -{ - THistoryList::const_iterator it = m_List.begin(); - while (index > 0 && it != m_List.end()) - { - ++it; - if ((*it)->Exist()) - { - --index; - } - } - return it != m_List.end() ? *it : NULL; -} - -//////////////////////////////////////////////////////////////////////////// -int SXmlHistoryGroup::GetHistoryCount() const -{ - int count = 0; - for (THistoryList::const_iterator it = m_List.begin(); it != m_List.end(); ++it) - { - if ((*it)->Exist()) - { - count++; - } - } - return count; -} - -//////////////////////////////////////////////////////////////////////////// -SXmlHistory* SXmlHistoryGroup::GetHistoryByTypeId(uint32 typeId, int index /*= 0*/) const -{ - for (int i = 0; i < GetHistoryCount(); ++i) - { - SXmlHistory* pHistory = GetHistory(i); - if (pHistory->GetTypeId() == typeId) - { - index--; - } - if (index == -1) - { - return pHistory; - } - } - return NULL; -} - -//////////////////////////////////////////////////////////////////////////// -int SXmlHistoryGroup::GetHistoryCountByTypeId(uint32 typeId) const -{ - int res = 0; - for (int i = 0; i < GetHistoryCount(); ++i) - { - if (GetHistory(i)->GetTypeId() == typeId) - { - res++; - } - } - return res; -} - -//////////////////////////////////////////////////////////////////////////// -int SXmlHistoryGroup::CreateXmlHistory(uint32 typeId, const XmlNodeRef& xmlBaseVersion) -{ - if (m_pManager) - { - m_List.push_back(m_pManager->CreateXmlHistory(typeId, xmlBaseVersion)); - return m_List.size() - 1; - } - return -1; -} - -//////////////////////////////////////////////////////////////////////////// -int SXmlHistoryGroup::GetHistoryIndex(const SXmlHistory* pHistory) const -{ - int index = 0; - for (THistoryList::const_iterator it = m_List.begin(); it != m_List.end(); ++it) - { - if (*it == pHistory) - { - return index; - } - index++; - } - return -1; -} - -//////////////////////////////////////////////////////////////////////////// -CXmlHistoryManager::CXmlHistoryManager() - : m_CurrentVersion(0) - , m_LatestVersion(0) - , m_pExclusiveListener(NULL) - , m_RecordNextVersion(false) - , m_pExActiveGroup(NULL) - , m_bIsActiveGroupEx(false) -{ - m_pNullGroup = new SXmlHistoryGroup(this, (uint32) - 1); -} - -CXmlHistoryManager::~CXmlHistoryManager() -{ - delete m_pNullGroup; -} - -///////////////////////////////////////////////////////////////////////////// -bool CXmlHistoryManager::Undo() -{ - if (m_CurrentVersion > 0) - { - int prevVersion = m_CurrentVersion; - const SXmlHistoryGroup* pPrevCurrGroup = GetActiveGroup(); - m_CurrentVersion--; - ReloadCurrentVersion(pPrevCurrGroup, prevVersion); - return true; - } - return false; -} - -///////////////////////////////////////////////////////////////////////////// -bool CXmlHistoryManager::Redo() -{ - if (m_CurrentVersion < m_LatestVersion) - { - int prevVersion = m_CurrentVersion; - const SXmlHistoryGroup* pPrevCurrGroup = GetActiveGroup(); - m_CurrentVersion++; - ReloadCurrentVersion(pPrevCurrGroup, prevVersion); - return true; - } - return false; -} - -///////////////////////////////////////////////////////////////////////////// -bool CXmlHistoryManager::Goto(int historyNum) -{ - if (historyNum >= 0 && historyNum <= m_LatestVersion) - { - int prevVersion = m_CurrentVersion; - const SXmlHistoryGroup* pPrevCurrGroup = GetActiveGroup(); - m_CurrentVersion = historyNum; - ReloadCurrentVersion(pPrevCurrGroup, prevVersion); - return true; - } - return false; -} - -///////////////////////////////////////////////////////////////////////////// -void CXmlHistoryManager::RecordUndo(IXmlUndoEventHandler* pEventHandler, const char* desc) -{ - ClearRedo(); - SXmlHistory* pChangedXml = m_UndoEventHandlerMap[ pEventHandler ].CurrentData; - assert(pChangedXml); - - XmlNodeRef newData = gEnv->pSystem->CreateXmlNode(); -#if !defined(NDEBUG) - bool bRes = -#endif - pEventHandler->SaveToXml(newData); - assert(bRes); - - TXmlHistotyGroupPtrList activeGroups = m_HistoryInfoMap[ m_CurrentVersion ].ActiveGroups; - - pChangedXml->AddToHistory(newData); - m_UndoEventHandlerMap[ pEventHandler ].HistoryData[ m_CurrentVersion ] = pChangedXml; - m_HistoryInfoMap[ m_CurrentVersion ].HistoryDescription = desc; - m_HistoryInfoMap[ m_CurrentVersion ].IsNullUndo = false; - m_HistoryInfoMap[ m_CurrentVersion ].ActiveGroups = activeGroups; - m_HistoryInfoMap[ m_CurrentVersion ].HistoryInvalidated = false; - NotifyUndoEventListener(IXmlHistoryEventListener::eHET_VersionAdded); -} - -///////////////////////////////////////////////////////////////////////////// -void CXmlHistoryManager::UndoEventHandlerDestroyed(IXmlUndoEventHandler* pEventHandler, uint32 typeId /*= 0*/, bool destoryForever /*= false*/) -{ - if (destoryForever) - { - UnregisterUndoEventHandler(pEventHandler); - } - else - { - m_InvalidHandlerMap[typeId] = pEventHandler; - } -} - -///////////////////////////////////////////////////////////////////////////// -void CXmlHistoryManager::RestoreUndoEventHandler(IXmlUndoEventHandler* pEventHandler, uint32 typeId) -{ - TInvalidUndoEventListener::iterator it = m_InvalidHandlerMap.find(typeId); - if (it != m_InvalidHandlerMap.end()) - { - IXmlUndoEventHandler* pLastHandler = it->second; - TUndoEventHandlerMap::iterator lastit = m_UndoEventHandlerMap.find(pLastHandler); - if (lastit != m_UndoEventHandlerMap.end()) - { - m_UndoEventHandlerMap[pEventHandler] = lastit->second; - m_UndoEventHandlerMap.erase(lastit); - } - m_InvalidHandlerMap.erase(it); - } -} - -///////////////////////////////////////////////////////////////////////////// -void CXmlHistoryManager::RegisterEventListener(IXmlHistoryEventListener* pEventListener) -{ - stl::push_back_unique(m_EventListener, pEventListener); -} - -///////////////////////////////////////////////////////////////////////////// -void CXmlHistoryManager::UnregisterEventListener(IXmlHistoryEventListener* pEventListener) -{ - m_EventListener.remove(pEventListener); -} - -///////////////////////////////////////////////////////////////////////////// -void CXmlHistoryManager::PrepareForNextVersion() -{ - assert(!m_RecordNextVersion); - m_RecordNextVersion = true; -} - -///////////////////////////////////////////////////////////////////////////// -void CXmlHistoryManager::RecordNextVersion(SXmlHistory* pHistory, XmlNodeRef newData, const char* undoDesc /*= NULL*/) -{ - assert(m_RecordNextVersion); - RegisterUndoEventHandler(this, pHistory); - m_newHistoryData = newData; - RecordUndo(this, undoDesc ? undoDesc : ""); - m_RecordNextVersion = false; - m_HistoryInfoMap[ m_CurrentVersion ].HistoryInvalidated = true; - UnregisterUndoEventHandler(this); - SetActiveGroupInt(GetActiveGroup()); - NotifyUndoEventListener(IXmlHistoryEventListener::eHET_HistoryInvalidate); -} - -///////////////////////////////////////////////////////////////////////////// -bool CXmlHistoryManager::SaveToXml(XmlNodeRef& xmlNode) -{ - assert(m_newHistoryData); - xmlNode = m_newHistoryData; - return true; -} -///////////////////////////////////////////////////////////////////////////// -void CXmlHistoryManager::ClearHistory(bool flagAsSaved) -{ - TXmlHistotyGroupPtrList activeGropus = m_HistoryInfoMap[ m_CurrentVersion ].ActiveGroups; - for (TXmlHistoryList::iterator it = m_XmlHistoryList.begin(); it != m_XmlHistoryList.end(); ++it) - { - it->ClearHistory(flagAsSaved); - } - - SetActiveGroup(NULL); - - m_CurrentVersion = 0; - m_LatestVersion = 0; - - m_UndoEventHandlerMap.clear(); - m_HistoryInfoMap.clear(); - - m_HistoryInfoMap[ 0 ].HistoryDescription = "New History"; - m_HistoryInfoMap[ 0 ].ActiveGroups = activeGropus; - NotifyUndoEventListener(IXmlHistoryEventListener::eHET_HistoryCleared); -} - -///////////////////////////////////////////////////////////////////////////// -const AZStd::string& CXmlHistoryManager::GetVersionDesc(int number) const -{ - THistoryInfoMap::const_iterator it = m_HistoryInfoMap.find(number); - if (it != m_HistoryInfoMap.end()) - { - return it->second.HistoryDescription; - } - - static AZStd::string undef("UNDEFINED"); - return undef; -} - -///////////////////////////////////////////////////////////////////////////// -void CXmlHistoryManager::RegisterView(IXmlHistoryView* pView) -{ - stl::push_back_unique(m_Views, pView); -} - -///////////////////////////////////////////////////////////////////////////// -void CXmlHistoryManager::UnregisterView(IXmlHistoryView* pView) -{ - m_Views.remove(pView); -} - -///////////////////////////////////////////////////////////////////////////// -SXmlHistoryGroup* CXmlHistoryManager::CreateXmlGroup(uint32 typeId) -{ - m_Groups.push_back(SXmlHistoryGroup(this, typeId)); - return &(*m_Groups.rbegin()); -} - -///////////////////////////////////////////////////////////////////////////// -void CXmlHistoryManager::AddXmlGroup(const SXmlHistoryGroup* pGroup, const char* undoDesc /*= NULL*/) -{ - RecordUndoInternal(undoDesc ? undoDesc : "New XML Group added"); - m_HistoryInfoMap[ m_CurrentVersion ].ActiveGroups.push_back(pGroup); - NotifyUndoEventListener(IXmlHistoryEventListener::eHET_HistoryGroupAdded, (void*)pGroup); -} -///////////////////////////////////////////////////////////////////////////// -void CXmlHistoryManager::RemoveXmlGroup(const SXmlHistoryGroup* pGroup, const char* undoDesc /*= NULL*/) -{ - bool unload = m_HistoryInfoMap[ m_CurrentVersion ].CurrGroup == pGroup; - RecordUndoInternal(undoDesc ? undoDesc : "XML Group deleted"); - TXmlHistotyGroupPtrList& list = m_HistoryInfoMap[ m_CurrentVersion ].ActiveGroups; - stl::find_and_erase(list, pGroup); - if (unload) - { - SetActiveGroupInt(NULL); - } - m_HistoryInfoMap[ m_CurrentVersion ].CurrGroup = m_pNullGroup; - NotifyUndoEventListener(IXmlHistoryEventListener::eHET_HistoryGroupRemoved, (void*)pGroup); -} - -///////////////////////////////////////////////////////////////////////////// -void CXmlHistoryManager::SetActiveGroup(const SXmlHistoryGroup* pGroup, const char* displayName /*= NULL*/, const TGroupIndexMap& groupIndex /*= TGroupIndexMap()*/, bool setExternal /*= false*/) -{ - TGroupIndexMap userIndex; - const SXmlHistoryGroup* pActiveGroup = GetActiveGroup(userIndex); - if (pGroup != pActiveGroup || userIndex != groupIndex || setExternal) - { - const bool isEx = m_CurrentVersion != m_LatestVersion || setExternal; - m_pExActiveGroup = const_cast(pGroup); - m_ExCurrentIndex = groupIndex; - m_bIsActiveGroupEx = true; - SetActiveGroupInt(pGroup, displayName, !isEx, groupIndex); - m_bIsActiveGroupEx = isEx; - } -} - -void CXmlHistoryManager::SetActiveGroupInt(const SXmlHistoryGroup* pGroup, const char* displayName /*= NULL*/, bool bRecordNullUndo /*= false*/, const TGroupIndexMap& groupIndex /*= TGroupIndexMap()*/) -{ - UnloadInt(); - - TEventHandlerList eventHandler; - AZStd::string undoDesc; - - if (pGroup) - { - for (TViews::iterator it = m_Views.begin(); it != m_Views.end(); ++it) - { - IXmlHistoryView* pView = *it; - - std::map userIndexCount; - - for (SXmlHistoryGroup::THistoryList::const_iterator history = pGroup->m_List.begin(); history != pGroup->m_List.end(); ++history) - { - std::map::iterator it2 = userIndexCount.find((*history)->GetTypeId()); - if (it2 == userIndexCount.end()) - { - userIndexCount[ (*history)->GetTypeId() ] = 0; - } - uint32 userindex = userIndexCount[ (*history)->GetTypeId() ]; - IXmlUndoEventHandler* pEventHandler = NULL; - TGroupIndexMap::const_iterator indexIter = groupIndex.find((*history)->GetTypeId()); - if (indexIter == groupIndex.end() || indexIter->second == userindex) - { - if ((*history)->Exist()) - { - if (pView->LoadXml((*history)->GetTypeId(), (*history)->GetCurrentVersion(), pEventHandler, userindex)) - { - if (pEventHandler) - { - m_UndoHandlerViewMap[ pEventHandler ] = pView; - RegisterUndoEventHandler(pEventHandler, *history); - eventHandler.push_back(pEventHandler); - } - } - } - } - if ((*history)->Exist()) - { - userIndexCount[ (*history)->GetTypeId() ]++; - } - } - } - undoDesc = AZStd::string::format("Changed View to \"%s\"", displayName ? displayName : "UNDEFINED"); - } - else - { - undoDesc = "Unloaded Views"; - for (TUndoEventHandlerMap::iterator it = m_UndoEventHandlerMap.begin(); it != m_UndoEventHandlerMap.end(); ++it) - { - eventHandler.push_back(it->first); - } - pGroup = m_pNullGroup; - } - - if (bRecordNullUndo) - { - RecordNullUndo(eventHandler, undoDesc.c_str()); - m_HistoryInfoMap[ m_CurrentVersion ].CurrGroup = pGroup; - m_HistoryInfoMap[ m_CurrentVersion ].CurrUserIndex = groupIndex; - } - NotifyUndoEventListener(IXmlHistoryEventListener::eHET_HistoryGroupChanged); -} - -///////////////////////////////////////////////////////////////////////////// -const SXmlHistoryGroup* CXmlHistoryManager::GetActiveGroup() const -{ - TGroupIndexMap userIndex; - return GetActiveGroup(userIndex); -} - -///////////////////////////////////////////////////////////////////////////// -const SXmlHistoryGroup* CXmlHistoryManager::GetActiveGroup(TGroupIndexMap& currUserIndex /*out*/) const -{ - if (m_bIsActiveGroupEx) - { - currUserIndex = m_ExCurrentIndex; - return m_pExActiveGroup; - } - - int currVersion = m_CurrentVersion; - do - { - THistoryInfoMap::const_iterator it = m_HistoryInfoMap.find(currVersion); - if (it != m_HistoryInfoMap.end()) - { - const SXmlHistoryGroup* pGroup = it->second.CurrGroup; - if (it != m_HistoryInfoMap.end() && pGroup) - { - currUserIndex = it->second.CurrUserIndex; - return pGroup == m_pNullGroup ? NULL : pGroup; - } - } - currVersion--; - } while (currVersion >= 0); - return NULL; -} - -///////////////////////////////////////////////////////////////////////////// -SXmlHistory* CXmlHistoryManager::CreateXmlHistory(uint32 typeId, const XmlNodeRef& xmlBaseVersion) -{ - m_XmlHistoryList.push_back(SXmlHistory(this, xmlBaseVersion, typeId)); - return &(*m_XmlHistoryList.rbegin()); -} - -///////////////////////////////////////////////////////////////////////////// -void CXmlHistoryManager::DeleteXmlHistory(const SXmlHistory* pXmlHistry) -{ - for (TXmlHistoryList::iterator it = m_XmlHistoryList.begin(); it != m_XmlHistoryList.end(); ++it) - { - if (&(*it) == pXmlHistry) - { - m_XmlHistoryList.erase(it); - return; - } - } -} - -///////////////////////////////////////////////////////////////////////////// -void CXmlHistoryManager::UnloadInt() -{ - for (TViews::iterator it = m_Views.begin(); it != m_Views.end(); ++it) - { - IXmlHistoryView* pView = *it; - pView->UnloadXml(-1); - } -} - -///////////////////////////////////////////////////////////////////////////// -namespace -{ - template< class T > - void ClearAfterVersion(T& container, int version) - { - auto foundit = container.end(); - do - { - auto it = container.find(version); - if (it != container.end()) - { - foundit = it; - break; - } - version--; - } while (version >= 0); - if (foundit != container.end()) - { - for (auto it = ++foundit; it != container.end(); ) - { - container.erase(it++); - } - } - } -} - -void CXmlHistoryManager::ClearRedo() -{ - ClearAfterVersion(m_HistoryInfoMap, m_CurrentVersion); - for (TUndoEventHandlerMap::iterator it = m_UndoEventHandlerMap.begin(); it != m_UndoEventHandlerMap.end(); ++it) - { - ClearAfterVersion(it->second.HistoryData, m_CurrentVersion); - } -} - -///////////////////////////////////////////////////////////////////////////// -void CXmlHistoryManager::DeleteAll() -{ - ClearHistory(); - m_Groups.clear(); - m_UndoEventHandlerMap.clear(); - NotifyUndoEventListener(IXmlHistoryEventListener::eHET_HistoryDeleted); -} - -///////////////////////////////////////////////////////////////////////////// -void CXmlHistoryManager::FlagHistoryAsSaved() -{ - for (TXmlHistoryList::iterator it = m_XmlHistoryList.begin(); it != m_XmlHistoryList.end(); ++it) - { - it->FlagAsSaved(); - } - NotifyUndoEventListener(IXmlHistoryEventListener::eHET_HistorySaved); -} - -///////////////////////////////////////////////////////////////////////////// -void CXmlHistoryManager::RecordNullUndo(const TEventHandlerList& eventHandler, const char* desc, bool isNull /*= true*/) -{ - TXmlHistotyGroupPtrList activeGroups = m_HistoryInfoMap[ m_CurrentVersion ].ActiveGroups; - - // if current version is already null undo, overwrite it instead of create a new version - if (m_HistoryInfoMap[ m_CurrentVersion ].IsNullUndo && isNull) - { - assert(m_CurrentVersion); - m_CurrentVersion--; - } - - ClearRedo(); - IncrementVersion(); - - for (TEventHandlerList::const_iterator it = eventHandler.begin(); it != eventHandler.end(); ++it) - { - SXmlHistory* pChangedXml = m_UndoEventHandlerMap[ *it ].CurrentData; - m_UndoEventHandlerMap[ *it ].HistoryData[ m_CurrentVersion ] = pChangedXml; - } - m_HistoryInfoMap[ m_CurrentVersion ].HistoryDescription = desc; - m_HistoryInfoMap[ m_CurrentVersion ].IsNullUndo = isNull; - m_HistoryInfoMap[ m_CurrentVersion ].ActiveGroups = activeGroups; - m_HistoryInfoMap[ m_CurrentVersion ].HistoryInvalidated = false; - NotifyUndoEventListener(IXmlHistoryEventListener::eHET_VersionAdded); -} - -///////////////////////////////////////////////////////////////////////////// -void CXmlHistoryManager::ReloadCurrentVersion(const SXmlHistoryGroup* pPrevGroup, int prevVersion) -{ - m_bIsActiveGroupEx = false; - const SXmlHistoryGroup* pActiveGroup = GetActiveGroup(); - - bool bInvalidated = false; - int start = min(prevVersion, m_CurrentVersion); - int end = max(prevVersion, m_CurrentVersion); - for (int i = start; i <= end; ++i) - { - if (m_HistoryInfoMap[i].HistoryInvalidated) - { - bInvalidated = true; - break; - } - } - - if (!bInvalidated && pPrevGroup == pActiveGroup) - { - for (TUndoEventHandlerMap::iterator it = m_UndoEventHandlerMap.begin(); it != m_UndoEventHandlerMap.end(); ++it) - { - IXmlUndoEventHandler* pEventHandler = it->first; - if (!IsEventHandlerValid(pEventHandler)) - { - assert(false); - continue; - } - SXmlHistory* pXmlHistory = GetLatestHistory(m_UndoEventHandlerMap[ pEventHandler ]); /*m_UndoEventHandlerMap[ pEventHandler ].HistoryData[ m_CurrentVersion ];*/ - if (pXmlHistory) - { - if (pXmlHistory->Exist()) - { - pEventHandler->ReloadFromXml(pXmlHistory->GetCurrentVersion()); - } - } - } - NotifyUndoEventListener(IXmlHistoryEventListener::eHET_VersionChanged); - } - else - { - SetActiveGroupInt(pActiveGroup); - } - - if (bInvalidated) - { - NotifyUndoEventListener(IXmlHistoryEventListener::eHET_HistoryInvalidate); - } - - TXmlHistotyGroupPtrList oldActiveGroups = m_HistoryInfoMap[ prevVersion ].ActiveGroups; - TXmlHistotyGroupPtrList newActiveGroups = m_HistoryInfoMap[ m_CurrentVersion ].ActiveGroups; - - RemoveListFromList(newActiveGroups, oldActiveGroups); - RemoveListFromList(oldActiveGroups, m_HistoryInfoMap[ m_CurrentVersion ].ActiveGroups); - - for (TXmlHistotyGroupPtrList::iterator it = newActiveGroups.begin(); it != newActiveGroups.end(); ++it) - { - NotifyUndoEventListener(IXmlHistoryEventListener::eHET_HistoryGroupAdded, (void*) *it); - } - - for (TXmlHistotyGroupPtrList::iterator it = oldActiveGroups.begin(); it != oldActiveGroups.end(); ++it) - { - NotifyUndoEventListener(IXmlHistoryEventListener::eHET_HistoryGroupRemoved, (void*) *it); - } -} - -///////////////////////////////////////////////////////////////////////////// -void CXmlHistoryManager::RemoveListFromList(TXmlHistotyGroupPtrList& list, const TXmlHistotyGroupPtrList& removeList) -{ - for (TXmlHistotyGroupPtrList::const_iterator rit = removeList.begin(); rit != removeList.end(); ++rit) - { - for (TXmlHistotyGroupPtrList::iterator it = list.begin(); it != list.end(); ++it) - { - if (*it == *rit) - { - list.erase(it); - break; - } - } - } -} - -///////////////////////////////////////////////////////////////////////////// -SXmlHistory* CXmlHistoryManager::GetLatestHistory(SUndoEventHandlerData& eventHandlerData) -{ - int currVersion = m_CurrentVersion; - do - { - THistoryVersionMap::iterator it = eventHandlerData.HistoryData.find(currVersion); - if (it != eventHandlerData.HistoryData.end()) - { - return it->second; - } - currVersion--; - } while (currVersion >= 0); - return NULL; -} - - -///////////////////////////////////////////////////////////////////////////// -void CXmlHistoryManager::NotifyUndoEventListener(IXmlHistoryEventListener::EHistoryEventType event, void* pData) -{ - if (m_pExclusiveListener) - { - m_pExclusiveListener->OnEvent(event, pData); - } - else - { - for (TEventListener::iterator it = m_EventListener.begin(); it != m_EventListener.end(); ++it) - { - (*it)->OnEvent(event, pData); - } - } -} - -///////////////////////////////////////////////////////////////////////////// -int CXmlHistoryManager::IncrementVersion([[maybe_unused]] SXmlHistory* pXmlHistry) -{ - for (TXmlHistoryList::iterator it = m_XmlHistoryList.begin(); it != m_XmlHistoryList.end(); ++it) - { - it->ClearRedo(); - } - return IncrementVersion(); -} - -///////////////////////////////////////////////////////////////////////////// -int CXmlHistoryManager::IncrementVersion() -{ - m_CurrentVersion++; - m_LatestVersion = m_CurrentVersion; - return m_CurrentVersion; -} - -//////////////////////////////////////////////////////////////////////////// -void CXmlHistoryManager::RegisterUndoEventHandler(IXmlUndoEventHandler* pEventHandler, SXmlHistory* pXmlData) -{ - m_UndoEventHandlerMap[ pEventHandler ].CurrentData = pXmlData; -} - -///////////////////////////////////////////////////////////////////////////// -void CXmlHistoryManager::UnregisterUndoEventHandler(IXmlUndoEventHandler* pEventHandler) -{ - TUndoEventHandlerMap::iterator it = m_UndoEventHandlerMap.find(pEventHandler); - if (it != m_UndoEventHandlerMap.end()) - { - m_UndoEventHandlerMap.erase(it); - } -} - -///////////////////////////////////////////////////////////////////////////// -void CXmlHistoryManager::RecordUndoInternal(const char* desc) -{ - TEventHandlerList eventHandler; - for (TUndoEventHandlerMap::iterator it = m_UndoEventHandlerMap.begin(); it != m_UndoEventHandlerMap.end(); ++it) - { - eventHandler.push_back(it->first); - } - RecordNullUndo(eventHandler, desc, false); -} - -///////////////////////////////////////////////////////////////////////////// -bool CXmlHistoryManager::IsEventHandlerValid(IXmlUndoEventHandler* pEventHandler) -{ - for (TInvalidUndoEventListener::iterator it = m_InvalidHandlerMap.begin(); it != m_InvalidHandlerMap.end(); ++it) - { - if (it->second == pEventHandler) - { - return false; - } - } - return true; -} diff --git a/Code/Editor/Util/XmlHistoryManager.h b/Code/Editor/Util/XmlHistoryManager.h deleted file mode 100644 index 176f0a8d83..0000000000 --- a/Code/Editor/Util/XmlHistoryManager.h +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - -#ifndef CRYINCLUDE_EDITOR_UTIL_XMLHISTORYMANAGER_H -#define CRYINCLUDE_EDITOR_UTIL_XMLHISTORYMANAGER_H -#pragma once - - -#include "IXmlHistoryManager.h" - -class CXmlHistoryManager; - -struct SXmlHistory -{ -public: - SXmlHistory(CXmlHistoryManager* pManager, const XmlNodeRef& xmlBaseVersion, uint32 typeId); - - void AddToHistory(const XmlNodeRef& newXmlVersion); - - const XmlNodeRef& Undo(bool* bVersionExist = NULL); - const XmlNodeRef& Redo(); - const XmlNodeRef& GetCurrentVersion(bool* bVersionExist = NULL, int* iVersionNumber = NULL) const; - bool IsModified() const; - uint32 GetTypeId() const {return m_typeId; } - void FlagAsDeleted(); - void FlagAsSaved(); - bool Exist() const; - -private: - friend class CXmlHistoryManager; - - void ClearRedo(); - void ClearHistory(bool flagAsSaved); - -private: - CXmlHistoryManager* m_pManager; - uint32 m_typeId; - int m_DeletedVersion; - int m_SavedVersion; - - typedef std::map< int, XmlNodeRef > TXmlVersionMap; - TXmlVersionMap m_xmlVersionList; -}; - - -struct SXmlHistoryGroup -{ - SXmlHistoryGroup(CXmlHistoryManager* pManager, uint32 typeId); - - SXmlHistory* GetHistory(int index) const; - int GetHistoryCount() const; - - SXmlHistory* GetHistoryByTypeId(uint32 typeId, int index = 0) const; - int GetHistoryCountByTypeId(uint32 typeId) const; - - int CreateXmlHistory(uint32 typeId, const XmlNodeRef& xmlBaseVersion); - uint32 GetTypeId() const {return m_typeId; } - - int GetHistoryIndex(const SXmlHistory* pHistory) const; - -private: - friend class CXmlHistoryManager; - CXmlHistoryManager* m_pManager; - uint32 m_typeId; - - typedef std::list< SXmlHistory* > THistoryList; - THistoryList m_List; -}; - -typedef std::map TGroupIndexMap; - - -class CXmlHistoryManager - : public IXmlHistoryManager - , public IXmlUndoEventHandler -{ -public: - CXmlHistoryManager(); - ~CXmlHistoryManager(); - - // Undo/Redo - bool Undo(); - bool Redo(); - bool Goto(int historyNum); - void RecordUndo(IXmlUndoEventHandler* pEventHandler, const char* desc); - void UndoEventHandlerDestroyed(IXmlUndoEventHandler* pEventHandler, uint32 typeId = 0, bool destoryForever = false); - void RestoreUndoEventHandler(IXmlUndoEventHandler* pEventHandler, uint32 typeId); - - void PrepareForNextVersion(); - void RecordNextVersion(SXmlHistory* pHistory, XmlNodeRef newData, const char* undoDesc = NULL); - bool IsPreparedForNextVersion() const {return m_RecordNextVersion; } - - void RegisterEventListener(IXmlHistoryEventListener* pEventListener); - void UnregisterEventListener(IXmlHistoryEventListener* pEventListener); - void SetExclusiveListener(IXmlHistoryEventListener* pEventListener) { m_pExclusiveListener = pEventListener; } - - // History - void ClearHistory(bool flagAsSaved = false); - int GetVersionCount() const { return m_LatestVersion; } - const AZStd::string& GetVersionDesc(int number) const; - int GetCurrentVersionNumber() const { return m_CurrentVersion; } - - // Views - void RegisterView(IXmlHistoryView* pView); - void UnregisterView(IXmlHistoryView* pView); - - // Xml History Groups - SXmlHistoryGroup* CreateXmlGroup(uint32 typeId); - void SetActiveGroup(const SXmlHistoryGroup* pGroup, const char* displayName = NULL, const TGroupIndexMap& groupIndex = TGroupIndexMap(), bool setExternal = false); - const SXmlHistoryGroup* GetActiveGroup() const; - const SXmlHistoryGroup* GetActiveGroup(TGroupIndexMap& currUserIndex /*out*/) const; - void AddXmlGroup(const SXmlHistoryGroup* pGroup, const char* undoDesc = NULL); - void RemoveXmlGroup(const SXmlHistoryGroup* pGroup, const char* undoDesc = NULL); - - void DeleteAll(); - - void FlagHistoryAsSaved(); - - virtual bool SaveToXml(XmlNodeRef& xmlNode); - virtual bool LoadFromXml([[maybe_unused]] const XmlNodeRef& xmlNode) { return false; }; - virtual bool ReloadFromXml([[maybe_unused]] const XmlNodeRef& xmlNode) { return false; }; - -private: - typedef std::list< SXmlHistory > TXmlHistoryList; - TXmlHistoryList m_XmlHistoryList; - int m_CurrentVersion; - int m_LatestVersion; - SXmlHistoryGroup* m_pNullGroup; // hack for unload view ... - XmlNodeRef m_newHistoryData; - bool m_RecordNextVersion; - bool m_bIsActiveGroupEx; - SXmlHistoryGroup* m_pExActiveGroup; - TGroupIndexMap m_ExCurrentIndex; - - typedef std::list< SXmlHistoryGroup > TXmlHistotyGroupList; - TXmlHistotyGroupList m_Groups; - - // event listener - typedef std::list< IXmlHistoryEventListener* > TEventListener; - TEventListener m_EventListener; - IXmlHistoryEventListener* m_pExclusiveListener; - - // views - typedef std::list< IXmlHistoryView* > TViews; - TViews m_Views; - - typedef std::list< const SXmlHistoryGroup* > TXmlHistotyGroupPtrList; - // history - struct SHistoryInfo - { - SHistoryInfo() - : IsNullUndo(false) - , CurrGroup(NULL) - , HistoryInvalidated(false) {} - - const SXmlHistoryGroup* CurrGroup; - TGroupIndexMap CurrUserIndex; - AZStd::string HistoryDescription; - bool IsNullUndo; - bool HistoryInvalidated; - TXmlHistotyGroupPtrList ActiveGroups; - }; - typedef std::map< int, SHistoryInfo > THistoryInfoMap; - THistoryInfoMap m_HistoryInfoMap; - - // undo event handler - typedef std::map< int, SXmlHistory* > THistoryVersionMap; - struct SUndoEventHandlerData - { - SUndoEventHandlerData() - : CurrentData(NULL) {} - - SXmlHistory* CurrentData; - THistoryVersionMap HistoryData; - }; - typedef std::map< IXmlUndoEventHandler*, SUndoEventHandlerData > TUndoEventHandlerMap; - TUndoEventHandlerMap m_UndoEventHandlerMap; - - typedef std::map< IXmlUndoEventHandler*, IXmlHistoryView* > TUndoHandlerViewMap; - TUndoHandlerViewMap m_UndoHandlerViewMap; - - typedef std::map< uint32, IXmlUndoEventHandler* > TInvalidUndoEventListener; - TInvalidUndoEventListener m_InvalidHandlerMap; - -private: - friend struct SXmlHistory; - friend struct SXmlHistoryGroup; - - int IncrementVersion(SXmlHistory* pXmlHistry); - int IncrementVersion(); - SXmlHistory* CreateXmlHistory(uint32 typeId, const XmlNodeRef& xmlBaseVersion); - void DeleteXmlHistory(const SXmlHistory* pXmlHistry); - - void RegisterUndoEventHandler(IXmlUndoEventHandler* pEventHandler, SXmlHistory* pXmlData); - void UnregisterUndoEventHandler(IXmlUndoEventHandler* pEventHandler); - typedef std::list< IXmlUndoEventHandler* > TEventHandlerList; - void RecordNullUndo(const TEventHandlerList& eventHandler, const char* desc, bool isNull = true); - void ReloadCurrentVersion(const SXmlHistoryGroup* pPrevGroup, int prevVersion); - SXmlHistory* GetLatestHistory(SUndoEventHandlerData& eventHandlerData); - void NotifyUndoEventListener(IXmlHistoryEventListener::EHistoryEventType event, void* pData = NULL); - - void SetActiveGroupInt(const SXmlHistoryGroup* pGroup, const char* displayName = NULL, bool bRecordNullUndo = false, const TGroupIndexMap& groupIndex = TGroupIndexMap()); - void UnloadInt(); - void ClearRedo(); - - void RecordUndoInternal(const char* desc); - void RemoveListFromList(TXmlHistotyGroupPtrList& list, const TXmlHistotyGroupPtrList& removeList); - - bool IsEventHandlerValid(IXmlUndoEventHandler* pEventHandler); -}; - -#endif // CRYINCLUDE_EDITOR_UTIL_XMLHISTORYMANAGER_H diff --git a/Code/Editor/editor_lib_files.cmake b/Code/Editor/editor_lib_files.cmake index 386b495faa..7f59eed7ae 100644 --- a/Code/Editor/editor_lib_files.cmake +++ b/Code/Editor/editor_lib_files.cmake @@ -498,9 +498,7 @@ set(FILES UndoViewPosition.h UndoViewRotation.h Util/GeometryUtil.h - Util/IXmlHistoryManager.h Util/KDTree.h - Util/XmlHistoryManager.h WipFeaturesDlg.h WipFeaturesDlg.ui WipFeaturesDlg.qrc @@ -737,14 +735,12 @@ set(FILES Util/PredefinedAspectRatios.h Util/StringHelpers.cpp Util/StringHelpers.h - Util/StringNoCasePredicate.h Util/TRefCountBase.h Util/Triangulate.cpp Util/Triangulate.h Util/Util.h Util/XmlArchive.cpp Util/XmlArchive.h - Util/XmlHistoryManager.cpp Util/XmlTemplate.cpp Util/XmlTemplate.h Util/bitarray.h From 0545ce4f59c67fdfb094d5610b66165eacdfe78f Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Thu, 5 Aug 2021 12:46:50 -0700 Subject: [PATCH 134/803] More PR comments/fixes Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Editor/ConfigGroup.cpp | 4 ++-- Code/Editor/GameExporter.cpp | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Code/Editor/ConfigGroup.cpp b/Code/Editor/ConfigGroup.cpp index 04c92ff155..d65cbf2c3b 100644 --- a/Code/Editor/ConfigGroup.cpp +++ b/Code/Editor/ConfigGroup.cpp @@ -127,7 +127,7 @@ namespace Config case IConfigVar::eType_STRING: { - AZStd::string currentValue = 0; + AZStd::string currentValue; var->Get(¤tValue); node->setAttr(szName, currentValue.c_str()); break; @@ -186,7 +186,7 @@ namespace Config case IConfigVar::eType_STRING: { - AZStd::string currentValue = 0; + AZStd::string currentValue; var->GetDefault(¤tValue); QString readValue(currentValue.c_str()); if (node->getAttr(szName, readValue)) diff --git a/Code/Editor/GameExporter.cpp b/Code/Editor/GameExporter.cpp index 4c9031f08d..784951cc4d 100644 --- a/Code/Editor/GameExporter.cpp +++ b/Code/Editor/GameExporter.cpp @@ -380,12 +380,12 @@ void CGameExporter::ExportFileList(const QString& path, const QString& levelName // that can later be used for map downloads AZStd::string newpath; - QString filename = levelName; - AZStd::string mapname = (filename + ".dds").toUtf8().data(); - AZStd::string metaname = (filename + ".xml").toUtf8().data(); + AZStd::string filename = levelName.toUtf8().data(); + AZStd::string mapname = (filename + ".dds"); + AZStd::string metaname = (filename + ".xml"); XmlNodeRef rootNode = gEnv->pSystem->CreateXmlNode("download"); - rootNode->setAttr("name", filename.toUtf8().data()); + rootNode->setAttr("name", filename.c_str()); rootNode->setAttr("type", "Map"); XmlNodeRef indexNode = rootNode->newChild("index"); if (indexNode) From aa124347284cfc3b36902719a74d9808cc8948bc Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Thu, 5 Aug 2021 12:47:36 -0700 Subject: [PATCH 135/803] removing some dead code, commented code referring old types, static AZStd::strings Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Editor/CryEdit.cpp | 5 ---- Code/Editor/CryEditPy.cpp | 4 ++-- Code/Editor/GenericSelectItemDialog.cpp | 14 ----------- Code/Editor/LogFile.cpp | 3 --- Code/Editor/QtUtil.h | 1 - Code/Editor/Settings.cpp | 16 ------------- Code/Editor/Util/EditorUtils.cpp | 24 ------------------- Code/Editor/Util/PathUtil.cpp | 4 ++-- Code/Legacy/CryCommon/CryTypeInfo.cpp | 3 ++- Code/Legacy/CrySystem/SystemWin32.cpp | 21 +--------------- .../CrySystem/XML/SerializeXMLReader.cpp | 9 ++++--- .../Legacy/CrySystem/XML/SerializeXMLReader.h | 2 +- .../CrySystem/XML/SerializeXMLWriter.cpp | 18 +++++++------- .../Legacy/CrySystem/XML/SerializeXMLWriter.h | 8 +++---- Code/Legacy/CrySystem/XML/XMLBinaryNode.h | 2 -- .../DataTypes/Rules/IMeshAdvancedRule.h | 3 ++- .../SceneData/GraphData/MaterialData.cpp | 8 +++---- .../SceneData/GraphData/MaterialData.h | 8 +++---- .../Code/Source/Editor/EditorCommon.cpp | 8 +++---- .../Source/OpenGLRender/GLWidget.cpp | 3 +-- 20 files changed, 39 insertions(+), 125 deletions(-) diff --git a/Code/Editor/CryEdit.cpp b/Code/Editor/CryEdit.cpp index b69bfa78f3..3673367c12 100644 --- a/Code/Editor/CryEdit.cpp +++ b/Code/Editor/CryEdit.cpp @@ -1883,11 +1883,6 @@ void CCryEditApp::UnregisterEventLoopHook(IEventLoopHook* pHookToRemove) ////////////////////////////////////////////////////////////////////////// void CCryEditApp::LoadFile(QString fileName) { - //CEditCommandLineInfo cmdLine; - //ProcessCommandLine(cmdinfo); - - //bool bBuilding = false; - //CString file = cmdLine.SpanExcluding() if (GetIEditor()->GetViewManager()->GetViewCount() == 0) { return; diff --git a/Code/Editor/CryEditPy.cpp b/Code/Editor/CryEditPy.cpp index 6abaf933fe..7e07d5553d 100644 --- a/Code/Editor/CryEditPy.cpp +++ b/Code/Editor/CryEditPy.cpp @@ -210,7 +210,7 @@ namespace const char* PyGetCurrentLevelName() { // Using static member to capture temporary data - static AZStd::string tempLevelName; + static AZStd::fixed_string tempLevelName; tempLevelName = GetIEditor()->GetGameEngine()->GetLevelName().toUtf8().data(); return tempLevelName.c_str(); } @@ -218,7 +218,7 @@ namespace const char* PyGetCurrentLevelPath() { // Using static member to capture temporary data - static AZStd::string tempLevelPath; + static AZStd::fixed_string tempLevelPath; tempLevelPath = GetIEditor()->GetGameEngine()->GetLevelPath().toUtf8().data(); return tempLevelPath.c_str(); } diff --git a/Code/Editor/GenericSelectItemDialog.cpp b/Code/Editor/GenericSelectItemDialog.cpp index ef109336ef..59c7986a68 100644 --- a/Code/Editor/GenericSelectItemDialog.cpp +++ b/Code/Editor/GenericSelectItemDialog.cpp @@ -91,20 +91,6 @@ void CGenericSelectItemDialog::ReloadTree() QTreeWidgetItem* hSelected = nullptr; - /* - std::vector::const_iterator iter = m_items.begin(); - while (iter != m_items.end()) - { - const CString& itemName = *iter; - HTREEITEM hItem = m_tree.InsertItem(itemName, 0, 0, TVI_ROOT, TVI_SORT); - if (!m_preselect.IsEmpty() && m_preselect.CompareNoCase(itemName) == 0) - { - hSelected = hItem; - } - ++iter; - } - */ - std::map items; QRegularExpression sep(QStringLiteral("[\\/.") + m_treeSeparator + QStringLiteral("]+")); diff --git a/Code/Editor/LogFile.cpp b/Code/Editor/LogFile.cpp index 76c6f34181..56e91a6806 100644 --- a/Code/Editor/LogFile.cpp +++ b/Code/Editor/LogFile.cpp @@ -572,9 +572,6 @@ void CLogFile::OnWriteToConsole(const char* sText, bool bNewLine) } if (bNewLine) { - //str = CString("\r\n") + str.TrimLeft(); - //str = CString("\r\n") + str; - //str = CString("\r") + str; str = QString("\r\n") + str; str = str.trimmed(); } diff --git a/Code/Editor/QtUtil.h b/Code/Editor/QtUtil.h index a9aaadc491..380f4dfa4a 100644 --- a/Code/Editor/QtUtil.h +++ b/Code/Editor/QtUtil.h @@ -34,7 +34,6 @@ public: namespace QtUtil { - // Replacement for CString::trimRight() inline QString trimRight(const QString& str) { // We prepend a char, so that the left doesn't get trimmed, then we remove it after trimming diff --git a/Code/Editor/Settings.cpp b/Code/Editor/Settings.cpp index 8f86c74b25..ae4fa75d41 100644 --- a/Code/Editor/Settings.cpp +++ b/Code/Editor/Settings.cpp @@ -656,22 +656,6 @@ void SEditorSettings::Save() ////////////////////////////////////////////////////////////////////////// SaveValue("Settings\\Slices", "DynamicByDefault", sliceSettings.dynamicByDefault); - /* - ////////////////////////////////////////////////////////////////////////// - // Save paths. - ////////////////////////////////////////////////////////////////////////// - for (int id = 0; id < EDITOR_PATH_LAST; id++) - { - for (int i = 0; i < searchPaths[id].size(); i++) - { - CString path = searchPaths[id][i]; - CString key; - key.Format( "Paths","Path_%.2d_%.2d",id,i ); - SaveValue( "Paths",key,path ); - } - } - */ - s_editorSettings()->sync(); // --- Settings Registry values diff --git a/Code/Editor/Util/EditorUtils.cpp b/Code/Editor/Util/EditorUtils.cpp index 8f56e4d956..9f42a5da83 100644 --- a/Code/Editor/Util/EditorUtils.cpp +++ b/Code/Editor/Util/EditorUtils.cpp @@ -30,30 +30,6 @@ void HeapCheck::Check([[maybe_unused]] const char* file, [[maybe_unused]] int li _ASSERTE(_CrtCheckMemory()); #endif - /* - int heapstatus = _heapchk(); - switch( heapstatus ) - { - case _HEAPOK: - break; - case _HEAPEMPTY: - break; - case _HEAPBADBEGIN: - { - CString str; - str.Format( "Bad Start of Heap, at file %s line:%d",file,line ); - MessageBox( NULL,str,"Heap Check",MB_OK ); - } - break; - case _HEAPBADNODE: - { - CString str; - str.Format( "Bad Node in Heap, at file %s line:%d",file,line ); - MessageBox( NULL,str,"Heap Check",MB_OK ); - } - break; - } - */ #endif } diff --git a/Code/Editor/Util/PathUtil.cpp b/Code/Editor/Util/PathUtil.cpp index 2f99f42188..22c638e289 100644 --- a/Code/Editor/Util/PathUtil.cpp +++ b/Code/Editor/Util/PathUtil.cpp @@ -245,8 +245,8 @@ namespace Path /// Get the data folder AZStd::string GetEditingGameDataFolder() { - static AZStd::string s_currentModName; - // query the editor root. The bus exists in case we want tools to be able to override this. + // Define here the mod name + static AZStd::fixed_string s_currentModName; if (s_currentModName.empty()) { diff --git a/Code/Legacy/CryCommon/CryTypeInfo.cpp b/Code/Legacy/CryCommon/CryTypeInfo.cpp index ffadc732b0..5f0cb47b63 100644 --- a/Code/Legacy/CryCommon/CryTypeInfo.cpp +++ b/Code/Legacy/CryCommon/CryTypeInfo.cpp @@ -131,7 +131,8 @@ const CTypeInfo&PtrTypeInfo() // bool AZStd::string ToString(bool const& val) { - static AZStd::string sTrue = "true", sFalse = "false"; + static AZStd::fixed_string sTrue = "true"; + static AZStd::fixed_string sFalse = "false"; return val ? sTrue : sFalse; } diff --git a/Code/Legacy/CrySystem/SystemWin32.cpp b/Code/Legacy/CrySystem/SystemWin32.cpp index 66be2a2ca5..b114c9bf12 100644 --- a/Code/Legacy/CrySystem/SystemWin32.cpp +++ b/Code/Legacy/CrySystem/SystemWin32.cpp @@ -173,7 +173,7 @@ int CSystem::GetApplicationInstance() AZStd::wstring suffix; for (int instance = 0;; ++instance) { - suffix = AZStd::wstring::format(L"LumberyardApplication(%d)", instance); + suffix = AZStd::wstring::format(L"O3DEApplication(%d)", instance); CreateMutexW(NULL, TRUE, suffix.c_str()); // search for duplicates @@ -222,25 +222,6 @@ struct CryDbgModule }; #ifdef WIN32 -////////////////////////////////////////////////////////////////////////// -class CStringOrder -{ -public: - bool operator () (const char* szLeft, const char* szRight) const {return azstricmp(szLeft, szRight) < 0; } -}; -typedef std::map StringToSizeMap; -void AddSize (StringToSizeMap& mapSS, const char* szString, unsigned nSize) -{ - StringToSizeMap::iterator it = mapSS.find (szString); - if (it == mapSS.end()) - { - mapSS.insert (StringToSizeMap::value_type(szString, nSize)); - } - else - { - it->second += nSize; - } -} ////////////////////////////////////////////////////////////////////////// const char* GetModuleGroup (const char* szString) diff --git a/Code/Legacy/CrySystem/XML/SerializeXMLReader.cpp b/Code/Legacy/CrySystem/XML/SerializeXMLReader.cpp index 55fab84286..e74b457191 100644 --- a/Code/Legacy/CrySystem/XML/SerializeXMLReader.cpp +++ b/Code/Legacy/CrySystem/XML/SerializeXMLReader.cpp @@ -15,7 +15,7 @@ #define TAG_SCRIPT_TYPE "t" #define TAG_SCRIPT_NAME "n" -//#define LOG_SERIALIZE_STACK(tag,szName) CryLogAlways( "<%s> %s/%s",tag,GetStackInfo(),szName ); +//#define LOG_SERIALIZE_STACK(tag,szName) CryLogAlways( "<%s> %s/%s",tag,GetStackInfo().c_str(), szName); #define LOG_SERIALIZE_STACK(tag, szName) CSerializeXMLReaderImpl::CSerializeXMLReaderImpl(const XmlNodeRef& nodeRef) @@ -175,10 +175,9 @@ void CSerializeXMLReaderImpl::EndGroup() } ////////////////////////////////////////////////////////////////////////// -const char* CSerializeXMLReaderImpl::GetStackInfo() const +AZStd::string CSerializeXMLReaderImpl::GetStackInfo() const { - static AZStd::string str; - str.assign(""); + AZStd::string str; for (int i = 0; i < (int)m_nodeStack.size(); i++) { const char* name = m_nodeStack[i].m_node->getAttr(TAG_SCRIPT_NAME); @@ -195,7 +194,7 @@ const char* CSerializeXMLReaderImpl::GetStackInfo() const str += "/"; } } - return str.c_str(); + return str; } void CSerializeXMLReaderImpl::GetMemoryUsage(ICrySizer* pSizer) const diff --git a/Code/Legacy/CrySystem/XML/SerializeXMLReader.h b/Code/Legacy/CrySystem/XML/SerializeXMLReader.h index 177db0ffaa..f87350d3fe 100644 --- a/Code/Legacy/CrySystem/XML/SerializeXMLReader.h +++ b/Code/Legacy/CrySystem/XML/SerializeXMLReader.h @@ -88,7 +88,7 @@ public: void BeginGroup(const char* szName); bool BeginOptionalGroup(const char* szName, bool condition); void EndGroup(); - const char* GetStackInfo() const; + AZStd::string GetStackInfo() const; void GetMemoryUsage(ICrySizer* pSizer) const; diff --git a/Code/Legacy/CrySystem/XML/SerializeXMLWriter.cpp b/Code/Legacy/CrySystem/XML/SerializeXMLWriter.cpp index 26007eb229..ce3fbcc2b1 100644 --- a/Code/Legacy/CrySystem/XML/SerializeXMLWriter.cpp +++ b/Code/Legacy/CrySystem/XML/SerializeXMLWriter.cpp @@ -64,14 +64,14 @@ void CSerializeXMLWriterImpl::BeginGroup(const char* szName) if (strchr(szName, ' ') != 0) { assert(0 && "Spaces in group name not supported"); - CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "!Spaces in group name not supported: %s/%s", GetStackInfo(), szName); + CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "!Spaces in group name not supported: %s/%s", GetStackInfo().c_str(), szName); } XmlNodeRef node = CreateNodeNamed(szName); CurNode()->addChild(node); m_nodeStack.push_back(node); if (m_nodeStack.size() > MAX_NODE_STACK_DEPTH) { - CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "!Too Deep Node Stack:\r\n%s", GetStackInfo()); + CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "!Too Deep Node Stack:\r\n%s", GetStackInfo().c_str()); } } @@ -112,10 +112,9 @@ void CSerializeXMLWriterImpl::GetMemoryUsage(ICrySizer* pSizer) const } ////////////////////////////////////////////////////////////////////////// -const char* CSerializeXMLWriterImpl::GetStackInfo() const +AZStd::string CSerializeXMLWriterImpl::GetStackInfo() const { - static AZStd::string str; - str.assign(""); + AZStd::string str; for (int i = 0; i < (int)m_nodeStack.size(); i++) { const char* name = m_nodeStack[i]->getAttr(TAG_SCRIPT_NAME); @@ -132,14 +131,13 @@ const char* CSerializeXMLWriterImpl::GetStackInfo() const str += "/"; } } - return str.c_str(); + return str; } ////////////////////////////////////////////////////////////////////////// -const char* CSerializeXMLWriterImpl::GetLuaStackInfo() const +AZStd::string CSerializeXMLWriterImpl::GetLuaStackInfo() const { - static AZStd::string str; - str.assign(""); + AZStd::string str; for (int i = 0; i < (int)m_luaSaveStack.size(); i++) { const char* name = m_luaSaveStack[i]; @@ -149,5 +147,5 @@ const char* CSerializeXMLWriterImpl::GetLuaStackInfo() const str += "."; } } - return str.c_str(); + return str; } diff --git a/Code/Legacy/CrySystem/XML/SerializeXMLWriter.h b/Code/Legacy/CrySystem/XML/SerializeXMLWriter.h index 41dbe3dd7b..5f3e9f2c53 100644 --- a/Code/Legacy/CrySystem/XML/SerializeXMLWriter.h +++ b/Code/Legacy/CrySystem/XML/SerializeXMLWriter.h @@ -77,7 +77,7 @@ private: if (strchr(name, ' ') != 0) { assert(0 && "Spaces in Value name not supported"); - CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "!Spaces in Value name not supported: %s in Group %s", name, GetStackInfo()); + CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "!Spaces in Value name not supported: %s in Group %s", name, GetStackInfo().c_str()); return; } if (GetISystem()->IsDevMode() && CurNode()) @@ -86,7 +86,7 @@ private: if (CurNode()->haveAttr(name)) { assert(0); - CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "!Duplicate tag Value( \"%s\" ) in Group %s", name, GetStackInfo()); + CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "!Duplicate tag Value( \"%s\" ) in Group %s", name, GetStackInfo().c_str()); } } @@ -115,8 +115,8 @@ private: } // Used for printing currebnt stack info for warnings. - const char* GetStackInfo() const; - const char* GetLuaStackInfo() const; + AZStd::string GetStackInfo() const; + AZStd::string GetLuaStackInfo() const; ////////////////////////////////////////////////////////////////////////// // Check For Defaults. diff --git a/Code/Legacy/CrySystem/XML/XMLBinaryNode.h b/Code/Legacy/CrySystem/XML/XMLBinaryNode.h index cd9ce04e6c..34e0ca22ce 100644 --- a/Code/Legacy/CrySystem/XML/XMLBinaryNode.h +++ b/Code/Legacy/CrySystem/XML/XMLBinaryNode.h @@ -189,8 +189,6 @@ public: bool getAttr(const char* key, Vec3d& value) const; bool getAttr(const char* key, Quat& value) const; bool getAttr(const char* key, ColorB& value) const; - // bool getAttr( const char *key,CString &value ) const { XmlString v; if (getAttr(key,v)) { value = (const char*)v; return true; } else return false; } - private: ////////////////////////////////////////////////////////////////////////// diff --git a/Code/Tools/SceneAPI/SceneCore/DataTypes/Rules/IMeshAdvancedRule.h b/Code/Tools/SceneAPI/SceneCore/DataTypes/Rules/IMeshAdvancedRule.h index d3b31913dd..b759fea158 100644 --- a/Code/Tools/SceneAPI/SceneCore/DataTypes/Rules/IMeshAdvancedRule.h +++ b/Code/Tools/SceneAPI/SceneCore/DataTypes/Rules/IMeshAdvancedRule.h @@ -18,7 +18,8 @@ namespace AZ { namespace DataTypes { - const static AZStd::string s_advancedDisabledString = "Disabled"; + const static AZStd::fixed_string s_advancedDisabledString = "Disabled"; + class IMeshAdvancedRule : public IRule { diff --git a/Code/Tools/SceneAPI/SceneData/GraphData/MaterialData.cpp b/Code/Tools/SceneAPI/SceneData/GraphData/MaterialData.cpp index cf0f0a6f56..e41e39dd0a 100644 --- a/Code/Tools/SceneAPI/SceneData/GraphData/MaterialData.cpp +++ b/Code/Tools/SceneAPI/SceneData/GraphData/MaterialData.cpp @@ -18,10 +18,10 @@ namespace AZ { namespace DataTypes = AZ::SceneAPI::DataTypes; - const AZStd::string MaterialData::s_DiffuseMapName = "Diffuse"; - const AZStd::string MaterialData::s_SpecularMapName = "Specular"; - const AZStd::string MaterialData::s_BumpMapName = "Bump"; - const AZStd::string MaterialData::s_emptyString = ""; + const AZStd::fixed_string<8> MaterialData::s_DiffuseMapName = "Diffuse"; + const AZStd::fixed_string<9> MaterialData::s_SpecularMapName = "Specular"; + const AZStd::fixed_string<5> MaterialData::s_BumpMapName = "Bump"; + const AZStd::fixed_string<1> MaterialData::s_emptyString = ""; MaterialData::MaterialData() : m_isNoDraw(false) diff --git a/Code/Tools/SceneAPI/SceneData/GraphData/MaterialData.h b/Code/Tools/SceneAPI/SceneData/GraphData/MaterialData.h index 8cc9de8352..8c8f8bd66e 100644 --- a/Code/Tools/SceneAPI/SceneData/GraphData/MaterialData.h +++ b/Code/Tools/SceneAPI/SceneData/GraphData/MaterialData.h @@ -96,10 +96,10 @@ namespace AZ bool m_isNoDraw; - const static AZStd::string s_DiffuseMapName; - const static AZStd::string s_SpecularMapName; - const static AZStd::string s_BumpMapName; - const static AZStd::string s_emptyString; + const static AZStd::fixed_string<8> s_DiffuseMapName; + const static AZStd::fixed_string<9> s_SpecularMapName; + const static AZStd::fixed_string<5> s_BumpMapName; + const static AZStd::fixed_string<1> s_emptyString; // A unique id which is used to identify a material in a fbx. // This is the same as the ID in the fbx file's FbxNode diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Editor/EditorCommon.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Editor/EditorCommon.cpp index 9938d55502..8ce8b2d487 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Editor/EditorCommon.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Editor/EditorCommon.cpp @@ -57,10 +57,10 @@ namespace ImageProcessingAtomEditor static double mb = kb * 1024.0; static double gb = mb * 1024.0; - static AZStd::string byteStr = "B"; - static AZStd::string kbStr = "KB"; - static AZStd::string mbStr = "MB"; - static AZStd::string gbStr = "GB"; + static AZStd::fixed_string<2> byteStr = "B"; + static AZStd::fixed_string<3> kbStr = "KB"; + static AZStd::fixed_string<3> mbStr = "MB"; + static AZStd::fixed_string<3> gbStr = "GB"; #if AZ_TRAIT_IMAGEPROCESSING_USE_BASE10_BYTE_PREFIX kb = 1000.0; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/OpenGLRender/GLWidget.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/OpenGLRender/GLWidget.cpp index 2d3a8b9eda..cfdcd704c5 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/OpenGLRender/GLWidget.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/OpenGLRender/GLWidget.cpp @@ -284,8 +284,7 @@ namespace EMStudio fpsNumFrames = 0; } - static AZStd::string perfTempString; - perfTempString = AZStd::string::format("%d FPS (%.1f ms)", lastFPS, renderTime); + const AZStd::string perfTempString = AZStd::string::format("%d FPS (%.1f ms)", lastFPS, renderTime); // initialize the painter and get the font metrics //painter.setBrush( Qt::NoBrush ); From b521113fe1f51416a35ee28226e9cc2b521c1743 Mon Sep 17 00:00:00 2001 From: Dayo Lawal Date: Thu, 5 Aug 2021 15:10:13 -0500 Subject: [PATCH 136/803] SMC fix Signed-off-by: Dayo Lawal --- .../Code/Source/ShaderManagementConsoleApplication.h | 1 - 1 file changed, 1 deletion(-) diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h index 206b5cc94f..7a3a422dc9 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h @@ -29,7 +29,6 @@ namespace ShaderManagementConsole // AzFramework::Application void CreateStaticModules(AZStd::vector& outModules) override; const char* GetCurrentConfigurationName() const override; - void Stop() override; private: void ProcessCommandLine(const AZ::CommandLine& commandLine); From e8d685211b684fa5bd332515fe72ce5604d3b826 Mon Sep 17 00:00:00 2001 From: Dayo Lawal Date: Thu, 5 Aug 2021 16:24:49 -0500 Subject: [PATCH 137/803] CreateMenu/CreateTabBar Signed-off-by: Dayo Lawal --- .../Window/AtomToolsMainWindow.h | 6 ++-- .../Source/Window/AtomToolsMainWindow.cpp | 36 ++++++------------- .../Source/Window/MaterialEditorWindow.cpp | 30 ++++++++++++---- .../Code/Source/Window/MaterialEditorWindow.h | 5 +-- .../Window/ShaderManagementConsoleWindow.cpp | 30 ++++++++++++---- .../Window/ShaderManagementConsoleWindow.h | 5 +-- 6 files changed, 64 insertions(+), 48 deletions(-) diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindow.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindow.h index f3271123b0..141fa1cad2 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindow.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindow.h @@ -38,9 +38,9 @@ namespace AtomToolsFramework bool IsDockWidgetVisible(const AZStd::string& name) const override; AZStd::vector GetDockWidgetNames() const override; - virtual void SetupMenu(); + virtual void CreateMenu(); - virtual void SetupTabs(); + virtual void CreateTabBar(); virtual void AddTabForDocumentId(const AZ::Uuid& documentId); virtual void RemoveTabForDocumentId(const AZ::Uuid& documentId); virtual void UpdateTabForDocumentId(const AZ::Uuid& documentId); @@ -57,7 +57,5 @@ namespace AtomToolsFramework QStatusBar* m_statusBar = nullptr; AZStd::unordered_map m_dockWidgets; - - QMenu* m_menuFile = {}; }; } // namespace AtomToolsFramework diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp index ffc618c574..cafaff339e 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp @@ -21,16 +21,6 @@ namespace AtomToolsFramework setCorner(Qt::TopRightCorner, Qt::RightDockWidgetArea); setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea); - m_menuBar = new QMenuBar(this); - m_menuBar->setObjectName("MenuBar"); - setMenuBar(m_menuBar); - - m_centralWidget = new QWidget(this); - m_tabWidget = new AzQtComponents::TabWidget(m_centralWidget); - m_tabWidget->setObjectName("TabWidget"); - m_tabWidget->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Preferred); - m_tabWidget->setContentsMargins(0, 0, 0, 0); - m_statusBar = new QStatusBar(this); m_statusBar->setObjectName("StatusBar"); statusBar()->addPermanentWidget(m_statusBar, 1); @@ -110,26 +100,20 @@ namespace AtomToolsFramework return names; } - void AtomToolsMainWindow::SetupMenu() + void AtomToolsMainWindow::CreateMenu() { - // Generating the main menu manually because it's easier and we will have some dynamic or data driven entries - m_menuFile = m_menuBar->addMenu("&File"); + m_menuBar = new QMenuBar(this); + m_menuBar->setObjectName("MenuBar"); + setMenuBar(m_menuBar); } - void AtomToolsMainWindow::SetupTabs() + void AtomToolsMainWindow::CreateTabBar() { - // The tab bar should only be visible if it has active documents - m_tabWidget->setVisible(false); - m_tabWidget->setTabBarAutoHide(false); - m_tabWidget->setMovable(true); - m_tabWidget->setTabsClosable(true); - m_tabWidget->setUsesScrollButtons(true); - - // Add context menu for right-clicking on tabs - m_tabWidget->setContextMenuPolicy(Qt::ContextMenuPolicy::CustomContextMenu); - connect(m_tabWidget, &QWidget::customContextMenuRequested, this, [this]() { - OpenTabContextMenu(); - }); + m_centralWidget = new QWidget(this); + m_tabWidget = new AzQtComponents::TabWidget(m_centralWidget); + m_tabWidget->setObjectName("TabWidget"); + m_tabWidget->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Preferred); + m_tabWidget->setContentsMargins(0, 0, 0, 0); } void AtomToolsMainWindow::AddTabForDocumentId(const AZ::Uuid& documentId) diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp index 8367f30680..788680a227 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp @@ -93,6 +93,9 @@ namespace MaterialEditor m_materialViewport->setObjectName("Viewport"); m_materialViewport->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); + CreateMenu(); + CreateTabBar(); + QVBoxLayout* vl = new QVBoxLayout(m_centralWidget); vl->setMargin(0); vl->setContentsMargins(0, 0, 0, 0); @@ -101,9 +104,6 @@ namespace MaterialEditor m_centralWidget->setLayout(vl); setCentralWidget(m_centralWidget); - SetupMenu(); - SetupTabs(); - AddDockWidget("Asset Browser", new MaterialBrowserWidget, Qt::BottomDockWidgetArea, Qt::Vertical); AddDockWidget("Inspector", new MaterialInspector, Qt::RightDockWidgetArea, Qt::Horizontal); AddDockWidget("Viewport Settings", new ViewportSettingsInspector, Qt::LeftDockWidgetArea, Qt::Horizontal); @@ -283,9 +283,12 @@ namespace MaterialEditor m_statusBar->setWindowIconText(QString("%1").arg(status)); } - void MaterialEditorWindow::SetupMenu() + void MaterialEditorWindow::CreateMenu() { - Base::SetupMenu(); + Base::CreateMenu(); + + // Generating the main menu manually because it's easier and we will have some dynamic or data driven entries + m_menuFile = m_menuBar->addMenu("&File"); m_actionNew = m_menuFile->addAction("&New...", [this]() { CreateMaterialDialog createDialog(this); @@ -481,9 +484,22 @@ namespace MaterialEditor }); } - void MaterialEditorWindow::SetupTabs() + void MaterialEditorWindow::CreateTabBar() { - Base::SetupTabs(); + Base::CreateTabBar(); + + // The tab bar should only be visible if it has active documents + m_tabWidget->setVisible(false); + m_tabWidget->setTabBarAutoHide(false); + m_tabWidget->setMovable(true); + m_tabWidget->setTabsClosable(true); + m_tabWidget->setUsesScrollButtons(true); + + // Add context menu for right-clicking on tabs + m_tabWidget->setContextMenuPolicy(Qt::ContextMenuPolicy::CustomContextMenu); + connect(m_tabWidget, &QWidget::customContextMenuRequested, this, [this]() { + OpenTabContextMenu(); + }); // This signal will be triggered whenever a tab is added, removed, selected, clicked, dragged // When the last tab is removed tabIndex will be -1 and the document ID will be null diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.h index d865f1170d..e066d0f78a 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.h @@ -68,9 +68,9 @@ namespace MaterialEditor void OnDocumentUndoStateChanged(const AZ::Uuid& documentId) override; void OnDocumentSaved(const AZ::Uuid& documentId) override; - void SetupMenu() override; + void CreateMenu() override; - void SetupTabs() override; + void CreateTabBar() override; void AddTabForDocumentId(const AZ::Uuid& documentId) override; void UpdateTabForDocumentId(const AZ::Uuid& documentId) override; QString GetDocumentPath(const AZ::Uuid& documentId) const; @@ -82,6 +82,7 @@ namespace MaterialEditor MaterialViewportWidget* m_materialViewport = nullptr; MaterialEditorToolBar* m_toolBar = nullptr; + QMenu* m_menuFile = {}; QAction* m_actionNew = {}; QAction* m_actionOpen = {}; QAction* m_actionOpenRecent = {}; diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp index 24acf1eb89..7874fcb2dc 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp @@ -49,6 +49,9 @@ namespace ShaderManagementConsole m_toolBar->setObjectName("ToolBar"); addToolBar(m_toolBar); + CreateMenu(); + CreateTabBar(); + QVBoxLayout* vl = new QVBoxLayout(m_centralWidget); vl->setMargin(0); vl->setContentsMargins(0, 0, 0, 0); @@ -56,9 +59,6 @@ namespace ShaderManagementConsole m_centralWidget->setLayout(vl); setCentralWidget(m_centralWidget); - SetupMenu(); - SetupTabs(); - AddDockWidget("Asset Browser", new ShaderManagementConsoleBrowserWidget, Qt::BottomDockWidgetArea, Qt::Vertical); AddDockWidget("Python Terminal", new AzToolsFramework::CScriptTermDialog, Qt::BottomDockWidgetArea, Qt::Horizontal); @@ -159,9 +159,12 @@ namespace ShaderManagementConsole UpdateTabForDocumentId(documentId); } - void ShaderManagementConsoleWindow::SetupMenu() + void ShaderManagementConsoleWindow::CreateMenu() { - Base::SetupMenu(); + Base::CreateMenu(); + + // Generating the main menu manually because it's easier and we will have some dynamic or data driven entries + m_menuFile = m_menuBar->addMenu("&File"); m_actionOpen = m_menuFile->addAction("&Open...", [this]() { const AZStd::vector assetTypes = { @@ -277,9 +280,22 @@ namespace ShaderManagementConsole }); } - void ShaderManagementConsoleWindow::SetupTabs() + void ShaderManagementConsoleWindow::CreateTabBar() { - Base::SetupTabs(); + Base::CreateTabBar(); + + // The tab bar should only be visible if it has active documents + m_tabWidget->setVisible(false); + m_tabWidget->setTabBarAutoHide(false); + m_tabWidget->setMovable(true); + m_tabWidget->setTabsClosable(true); + m_tabWidget->setUsesScrollButtons(true); + + // Add context menu for right-clicking on tabs + m_tabWidget->setContextMenuPolicy(Qt::ContextMenuPolicy::CustomContextMenu); + connect(m_tabWidget, &QWidget::customContextMenuRequested, this, [this]() { + OpenTabContextMenu(); + }); // This signal will be triggered whenever a tab is added, removed, selected, clicked, dragged // When the last tab is removed tabIndex will be -1 and the document ID will be null diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.h b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.h index 127a777ddd..3b529a52b3 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.h +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.h @@ -63,9 +63,9 @@ namespace ShaderManagementConsole void OnDocumentUndoStateChanged(const AZ::Uuid& documentId) override; void OnDocumentSaved(const AZ::Uuid& documentId) override; - void SetupMenu() override; + void CreateMenu() override; - void SetupTabs() override; + void CreateTabBar() override; void AddTabForDocumentId(const AZ::Uuid& documentId) override; void UpdateTabForDocumentId(const AZ::Uuid& documentId) override; @@ -81,6 +81,7 @@ namespace ShaderManagementConsole ShaderManagementConsoleToolBar* m_toolBar = nullptr; + QMenu* m_menuFile = {}; QMenu* m_menuNew = {}; QAction* m_actionOpen = {}; QAction* m_actionOpenRecent = {}; From 0dc829891a29addd0a74f0ee0d46085ebc57f769 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Thu, 5 Aug 2021 14:30:04 -0700 Subject: [PATCH 138/803] fixing build Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Editor/Util/PathUtil.cpp | 2 +- Code/Legacy/CryCommon/CryTypeInfo.cpp | 7 ++++--- .../SceneAPI/SceneCore/DataTypes/Rules/IMeshAdvancedRule.h | 3 ++- Code/Tools/SceneAPI/SceneData/GraphData/MaterialData.cpp | 7 +------ Code/Tools/SceneAPI/SceneData/GraphData/MaterialData.h | 6 ++---- 5 files changed, 10 insertions(+), 15 deletions(-) diff --git a/Code/Editor/Util/PathUtil.cpp b/Code/Editor/Util/PathUtil.cpp index 22c638e289..3ca4b6222c 100644 --- a/Code/Editor/Util/PathUtil.cpp +++ b/Code/Editor/Util/PathUtil.cpp @@ -254,7 +254,7 @@ namespace Path } AZStd::string str(GetGameAssetsFolder()); str += "Mods\\"; - str += s_currentModName; + str += s_currentModName.c_str(); return str; } diff --git a/Code/Legacy/CryCommon/CryTypeInfo.cpp b/Code/Legacy/CryCommon/CryTypeInfo.cpp index 5f0cb47b63..b1f7f20601 100644 --- a/Code/Legacy/CryCommon/CryTypeInfo.cpp +++ b/Code/Legacy/CryCommon/CryTypeInfo.cpp @@ -16,6 +16,7 @@ #include "CrySizer.h" #include "CryEndian.h" #include "TypeInfo_impl.h" +#include // Traits #if defined(AZ_RESTRICTED_PLATFORM) @@ -131,9 +132,9 @@ const CTypeInfo&PtrTypeInfo() // bool AZStd::string ToString(bool const& val) { - static AZStd::fixed_string sTrue = "true"; - static AZStd::fixed_string sFalse = "false"; - return val ? sTrue : sFalse; + static AZStd::fixed_string<5> sTrue = "true"; + static AZStd::fixed_string<6> sFalse = "false"; + return val ? sTrue.c_str() : sFalse.c_str(); } bool FromString(bool& val, cstr s) diff --git a/Code/Tools/SceneAPI/SceneCore/DataTypes/Rules/IMeshAdvancedRule.h b/Code/Tools/SceneAPI/SceneCore/DataTypes/Rules/IMeshAdvancedRule.h index b759fea158..48310091b3 100644 --- a/Code/Tools/SceneAPI/SceneCore/DataTypes/Rules/IMeshAdvancedRule.h +++ b/Code/Tools/SceneAPI/SceneCore/DataTypes/Rules/IMeshAdvancedRule.h @@ -11,6 +11,7 @@ #include #include #include +#include namespace AZ { @@ -18,7 +19,7 @@ namespace AZ { namespace DataTypes { - const static AZStd::fixed_string s_advancedDisabledString = "Disabled"; + static AZStd::string s_advancedDisabledString = "Disabled"; class IMeshAdvancedRule : public IRule diff --git a/Code/Tools/SceneAPI/SceneData/GraphData/MaterialData.cpp b/Code/Tools/SceneAPI/SceneData/GraphData/MaterialData.cpp index e41e39dd0a..d58a89a110 100644 --- a/Code/Tools/SceneAPI/SceneData/GraphData/MaterialData.cpp +++ b/Code/Tools/SceneAPI/SceneData/GraphData/MaterialData.cpp @@ -18,11 +18,6 @@ namespace AZ { namespace DataTypes = AZ::SceneAPI::DataTypes; - const AZStd::fixed_string<8> MaterialData::s_DiffuseMapName = "Diffuse"; - const AZStd::fixed_string<9> MaterialData::s_SpecularMapName = "Specular"; - const AZStd::fixed_string<5> MaterialData::s_BumpMapName = "Bump"; - const AZStd::fixed_string<1> MaterialData::s_emptyString = ""; - MaterialData::MaterialData() : m_isNoDraw(false) , m_diffuseColor(AZ::Vector3::CreateOne()) @@ -72,7 +67,7 @@ namespace AZ return result->second; } - return s_emptyString; + return m_emptyString; } void MaterialData::SetNoDraw(bool isNoDraw) diff --git a/Code/Tools/SceneAPI/SceneData/GraphData/MaterialData.h b/Code/Tools/SceneAPI/SceneData/GraphData/MaterialData.h index 8c8f8bd66e..2a83a53c53 100644 --- a/Code/Tools/SceneAPI/SceneData/GraphData/MaterialData.h +++ b/Code/Tools/SceneAPI/SceneData/GraphData/MaterialData.h @@ -11,6 +11,7 @@ #include #include #include +#include namespace AZ { @@ -96,10 +97,7 @@ namespace AZ bool m_isNoDraw; - const static AZStd::fixed_string<8> s_DiffuseMapName; - const static AZStd::fixed_string<9> s_SpecularMapName; - const static AZStd::fixed_string<5> s_BumpMapName; - const static AZStd::fixed_string<1> s_emptyString; + const AZStd::string m_emptyString; // A unique id which is used to identify a material in a fbx. // This is the same as the ID in the fbx file's FbxNode From e50723625729df1ebc4608d22129feb105c4ecdc Mon Sep 17 00:00:00 2001 From: Dayo Lawal Date: Thu, 5 Aug 2021 17:59:00 -0500 Subject: [PATCH 139/803] Addressing requests Signed-off-by: Dayo Lawal --- .../Application/AtomToolsApplication.cpp | 2 +- .../Source/Window/AtomToolsMainWindow.cpp | 19 ++++++++++- .../Code/Source/MaterialEditorApplication.cpp | 2 +- .../Source/Window/MaterialEditorWindow.cpp | 13 ------- .../Code/Source/Window/MaterialEditorWindow.h | 11 +----- .../Window/MaterialEditorWindowComponent.cpp | 34 ++++++++----------- .../Code/materialeditorwindow_files.cmake | 3 -- .../ShaderManagementConsoleApplication.cpp | 2 +- .../Window/ShaderManagementConsoleWindow.cpp | 13 ------- .../Window/ShaderManagementConsoleWindow.h | 7 ---- ...ShaderManagementConsoleWindowComponent.cpp | 12 +++---- 11 files changed, 42 insertions(+), 76 deletions(-) diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp index 25ef43cfa4..aedad7706b 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp @@ -476,7 +476,7 @@ namespace AtomToolsFramework appType.m_maskValue = AZ::ApplicationTypeQuery::Masks::Game; } - void AtomToolsApplication::OnTraceMessage([[maybe_unused]] AZStd::string_view message) + void AtomToolsApplication::OnTraceMessage([[maybe_unused]] AZStd::string_view message) { #if defined(AZ_ENABLE_TRACING) AZStd::vector lines; diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp index cafaff339e..af4c3571e7 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp @@ -25,6 +25,8 @@ namespace AtomToolsFramework m_statusBar->setObjectName("StatusBar"); statusBar()->addPermanentWidget(m_statusBar, 1); + m_centralWidget = new QWidget(this); + AtomToolsMainWindowRequestBus::Handler::BusConnect(); } @@ -109,11 +111,26 @@ namespace AtomToolsFramework void AtomToolsMainWindow::CreateTabBar() { - m_centralWidget = new QWidget(this); m_tabWidget = new AzQtComponents::TabWidget(m_centralWidget); m_tabWidget->setObjectName("TabWidget"); m_tabWidget->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Preferred); m_tabWidget->setContentsMargins(0, 0, 0, 0); + + // The tab bar should only be visible if it has active documents + m_tabWidget->setVisible(false); + m_tabWidget->setTabBarAutoHide(false); + m_tabWidget->setMovable(true); + m_tabWidget->setTabsClosable(true); + m_tabWidget->setUsesScrollButtons(true); + + // Add context menu for right-clicking on tabs + m_tabWidget->setContextMenuPolicy(Qt::ContextMenuPolicy::CustomContextMenu); + connect( + m_tabWidget, &QWidget::customContextMenuRequested, this, + [this]() + { + OpenTabContextMenu(); + }); } void AtomToolsMainWindow::AddTabForDocumentId(const AZ::Uuid& documentId) diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp index 0c1cff334c..7b90be2dd1 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp @@ -38,8 +38,8 @@ #include #include -#include #include +#include AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT #include diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp index 788680a227..8d89e7442e 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp @@ -488,19 +488,6 @@ namespace MaterialEditor { Base::CreateTabBar(); - // The tab bar should only be visible if it has active documents - m_tabWidget->setVisible(false); - m_tabWidget->setTabBarAutoHide(false); - m_tabWidget->setMovable(true); - m_tabWidget->setTabsClosable(true); - m_tabWidget->setUsesScrollButtons(true); - - // Add context menu for right-clicking on tabs - m_tabWidget->setContextMenuPolicy(Qt::ContextMenuPolicy::CustomContextMenu); - connect(m_tabWidget, &QWidget::customContextMenuRequested, this, [this]() { - OpenTabContextMenu(); - }); - // This signal will be triggered whenever a tab is added, removed, selected, clicked, dragged // When the last tab is removed tabIndex will be -1 and the document ID will be null // This should automatically clear the active document diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.h index e066d0f78a..d789e1d839 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.h @@ -14,18 +14,9 @@ #include AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT -#include -#include -#include -#include - #include #include -#include - -#include -#include -#include +#include r> AZ_POP_DISABLE_WARNING #endif diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowComponent.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowComponent.cpp index 33987df5b6..4135ec66b4 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowComponent.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowComponent.cpp @@ -6,7 +6,8 @@ * */ -#include +#include +#include #include #include #include @@ -17,14 +18,9 @@ #include #include #include -#include - namespace MaterialEditor { - using FactoryRequestBus = AtomToolsFramework::AtomToolsMainWindowFactoryRequestBus; - using RequestBus = AtomToolsFramework::AtomToolsMainWindowRequestBus; - void MaterialEditorWindowComponent::Reflect(AZ::ReflectContext* context) { MaterialEditorWindowSettings::Reflect(context); @@ -37,25 +33,25 @@ namespace MaterialEditor if (AZ::BehaviorContext* behaviorContext = azrtti_cast(context)) { - behaviorContext->EBus("MaterialEditorWindowFactoryRequestBus") + behaviorContext->EBus("MaterialEditorWindowAtomToolsFramework::AtomToolsMainWindowFactoryRequestBus") ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) ->Attribute(AZ::Script::Attributes::Category, "Editor") ->Attribute(AZ::Script::Attributes::Module, "materialeditor") - ->Event("CreateMaterialEditorWindow", &FactoryRequestBus::Events::CreateMainWindow) - ->Event("DestroyMaterialEditorWindow", &FactoryRequestBus::Events::DestroyMainWindow) + ->Event("CreateMaterialEditorWindow", &AtomToolsFramework::AtomToolsMainWindowFactoryRequestBus::Events::CreateMainWindow) + ->Event("DestroyMaterialEditorWindow", &AtomToolsFramework::AtomToolsMainWindowFactoryRequestBus::Events::DestroyMainWindow) ; - behaviorContext->EBus("MaterialEditorWindowRequestBus") + behaviorContext->EBus("MaterialEditorWindowRequestBus") ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) ->Attribute(AZ::Script::Attributes::Category, "Editor") ->Attribute(AZ::Script::Attributes::Module, "materialeditor") - ->Event("ActivateWindow", &RequestBus::Events::ActivateWindow) - ->Event("SetDockWidgetVisible", &RequestBus::Events::SetDockWidgetVisible) - ->Event("IsDockWidgetVisible", &RequestBus::Events::IsDockWidgetVisible) - ->Event("GetDockWidgetNames", &RequestBus::Events::GetDockWidgetNames) - ->Event("ResizeViewportRenderTarget", &RequestBus::Events::ResizeViewportRenderTarget) - ->Event("LockViewportRenderTargetSize", &RequestBus::Events::LockViewportRenderTargetSize) - ->Event("UnlockViewportRenderTargetSize", &RequestBus::Events::UnlockViewportRenderTargetSize) + ->Event("ActivateWindow", &AtomToolsFramework::AtomToolsMainWindowRequestBus::Events::ActivateWindow) + ->Event("SetDockWidgetVisible", &AtomToolsFramework::AtomToolsMainWindowRequestBus::Events::SetDockWidgetVisible) + ->Event("IsDockWidgetVisible", &AtomToolsFramework::AtomToolsMainWindowRequestBus::Events::IsDockWidgetVisible) + ->Event("GetDockWidgetNames", &AtomToolsFramework::AtomToolsMainWindowRequestBus::Events::GetDockWidgetNames) + ->Event("ResizeViewportRenderTarget", &AtomToolsFramework::AtomToolsMainWindowRequestBus::Events::ResizeViewportRenderTarget) + ->Event("LockViewportRenderTargetSize", &AtomToolsFramework::AtomToolsMainWindowRequestBus::Events::LockViewportRenderTargetSize) + ->Event("UnlockViewportRenderTargetSize", &AtomToolsFramework::AtomToolsMainWindowRequestBus::Events::UnlockViewportRenderTargetSize) ; } } @@ -84,13 +80,13 @@ namespace MaterialEditor void MaterialEditorWindowComponent::Activate() { AzToolsFramework::EditorWindowRequestBus::Handler::BusConnect(); - FactoryRequestBus::Handler::BusConnect(); + AtomToolsFramework::AtomToolsMainWindowFactoryRequestBus::Handler::BusConnect(); AzToolsFramework::SourceControlConnectionRequestBus::Broadcast(&AzToolsFramework::SourceControlConnectionRequests::EnableSourceControl, true); } void MaterialEditorWindowComponent::Deactivate() { - FactoryRequestBus::Handler::BusDisconnect(); + AtomToolsFramework::AtomToolsMainWindowFactoryRequestBus::Handler::BusDisconnect(); AzToolsFramework::EditorWindowRequestBus::Handler::BusDisconnect(); m_window.reset(); diff --git a/Gems/Atom/Tools/MaterialEditor/Code/materialeditorwindow_files.cmake b/Gems/Atom/Tools/MaterialEditor/Code/materialeditorwindow_files.cmake index 6294adad88..b814ad3f47 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/materialeditorwindow_files.cmake +++ b/Gems/Atom/Tools/MaterialEditor/Code/materialeditorwindow_files.cmake @@ -39,9 +39,6 @@ set(FILES Source/Window/PerformanceMonitor/PerformanceMonitorWidget.cpp Source/Window/PerformanceMonitor/PerformanceMonitorWidget.h Source/Window/PerformanceMonitor/PerformanceMonitorWidget.ui - Source/Window/StatusBar/StatusBarWidget.cpp - Source/Window/StatusBar/StatusBarWidget.h - Source/Window/StatusBar/StatusBarWidget.ui Source/Window/ToolBar/MaterialEditorToolBar.h Source/Window/ToolBar/MaterialEditorToolBar.cpp Source/Window/ToolBar/ModelPresetComboBox.h diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp index 37e617fda2..876f58e8d5 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp @@ -36,7 +36,7 @@ #include #include -#include +#include AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT #include diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp index 7874fcb2dc..0a7ce6dd59 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp @@ -284,19 +284,6 @@ namespace ShaderManagementConsole { Base::CreateTabBar(); - // The tab bar should only be visible if it has active documents - m_tabWidget->setVisible(false); - m_tabWidget->setTabBarAutoHide(false); - m_tabWidget->setMovable(true); - m_tabWidget->setTabsClosable(true); - m_tabWidget->setUsesScrollButtons(true); - - // Add context menu for right-clicking on tabs - m_tabWidget->setContextMenuPolicy(Qt::ContextMenuPolicy::CustomContextMenu); - connect(m_tabWidget, &QWidget::customContextMenuRequested, this, [this]() { - OpenTabContextMenu(); - }); - // This signal will be triggered whenever a tab is added, removed, selected, clicked, dragged // When the last tab is removed tabIndex will be -1 and the document ID will be null // This should automatically clear the active document diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.h b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.h index 3b529a52b3..f1c74a1f48 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.h +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.h @@ -17,17 +17,10 @@ #include AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT -#include -#include -#include -#include - #include #include -#include #include -#include AZ_POP_DISABLE_WARNING #endif diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindowComponent.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindowComponent.cpp index e9dda40a50..44715ef64f 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindowComponent.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindowComponent.cpp @@ -34,8 +34,6 @@ AZ_POP_DISABLE_WARNING namespace ShaderManagementConsole { - using FactoryRequestBus = AtomToolsFramework::AtomToolsMainWindowFactoryRequestBus; - void ShaderManagementConsoleWindowComponent::Reflect(AZ::ReflectContext* context) { if (AZ::SerializeContext* serialize = azrtti_cast(context)) @@ -46,12 +44,12 @@ namespace ShaderManagementConsole if (AZ::BehaviorContext* behaviorContext = azrtti_cast(context)) { - behaviorContext->EBus("ShaderManagementConsoleWindowRequestBus") + behaviorContext->EBus("ShaderManagementConsoleWindowRequestBus") ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation) ->Attribute(AZ::Script::Attributes::Category, "Editor") ->Attribute(AZ::Script::Attributes::Module, "shadermanagementconsole") - ->Event("CreateShaderManagementConsoleWindow", &FactoryRequestBus::Events::CreateMainWindow) - ->Event("DestroyShaderManagementConsoleWindow", &FactoryRequestBus::Events::DestroyMainWindow) + ->Event("CreateShaderManagementConsoleWindow", &AtomToolsFramework::AtomToolsMainWindowFactoryRequestBus::Events::CreateMainWindow) + ->Event("DestroyShaderManagementConsoleWindow", &AtomToolsFramework::AtomToolsMainWindowFactoryRequestBus::Events::DestroyMainWindow) ; behaviorContext->EBus("ShaderManagementConsoleRequestBus") @@ -89,7 +87,7 @@ namespace ShaderManagementConsole void ShaderManagementConsoleWindowComponent::Activate() { AzToolsFramework::EditorWindowRequestBus::Handler::BusConnect(); - FactoryRequestBus::Handler::BusConnect(); + AtomToolsFramework::AtomToolsMainWindowFactoryRequestBus::Handler::BusConnect(); ShaderManagementConsoleRequestBus::Handler::BusConnect(); AzToolsFramework::SourceControlConnectionRequestBus::Broadcast(&AzToolsFramework::SourceControlConnectionRequests::EnableSourceControl, true); } @@ -97,7 +95,7 @@ namespace ShaderManagementConsole void ShaderManagementConsoleWindowComponent::Deactivate() { ShaderManagementConsoleRequestBus::Handler::BusDisconnect(); - FactoryRequestBus::Handler::BusDisconnect(); + AtomToolsFramework::AtomToolsMainWindowFactoryRequestBus::Handler::BusDisconnect(); AzToolsFramework::EditorWindowRequestBus::Handler::BusDisconnect(); m_window.reset(); From 32ba658e5eb4b2ea8b1bfcd635bcf8351dfe8794 Mon Sep 17 00:00:00 2001 From: Dayo Lawal Date: Thu, 5 Aug 2021 18:35:54 -0500 Subject: [PATCH 140/803] Typo fix Signed-off-by: Dayo Lawal --- .../Code/Source/MaterialEditorApplication.cpp | 7 +------ .../MaterialEditor/Code/Source/MaterialEditorApplication.h | 2 -- .../Code/Source/Window/MaterialEditorWindowComponent.cpp | 2 +- .../Code/Source/ShaderManagementConsoleApplication.cpp | 5 ----- .../Code/Source/ShaderManagementConsoleApplication.h | 2 -- 5 files changed, 2 insertions(+), 16 deletions(-) diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp index 7b90be2dd1..e12bc2409a 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp @@ -41,14 +41,9 @@ #include #include -AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT -#include -#include -AZ_POP_DISABLE_WARNING - namespace MaterialEditor { - //! This function returns the build system target name of "MaterialEditor + //! This function returns the build system target name of "MaterialEditor" AZStd::string MaterialEditorApplication::GetBuildTargetName() const { #if !defined(LY_CMAKE_TARGET) diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h index f65f719caa..164fb9d920 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h @@ -11,8 +11,6 @@ #include #include -#include - namespace MaterialEditor { class MaterialThumbnailRenderer; diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowComponent.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowComponent.cpp index 4135ec66b4..8406ae891f 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowComponent.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowComponent.cpp @@ -33,7 +33,7 @@ namespace MaterialEditor if (AZ::BehaviorContext* behaviorContext = azrtti_cast(context)) { - behaviorContext->EBus("MaterialEditorWindowAtomToolsFramework::AtomToolsMainWindowFactoryRequestBus") + behaviorContext->EBus("MaterialEditorWindowAtomRequestBus") ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) ->Attribute(AZ::Script::Attributes::Category, "Editor") ->Attribute(AZ::Script::Attributes::Module, "materialeditor") diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp index 876f58e8d5..2a5cd1430a 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp @@ -38,11 +38,6 @@ #include #include -AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT -#include -#include -AZ_POP_DISABLE_WARNING - namespace ShaderManagementConsole { //! This function returns the build system target name of "ShaderManagementConsole" diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h index 7a3a422dc9..0714ec17bc 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h @@ -11,8 +11,6 @@ #include #include -#include - namespace ShaderManagementConsole { class ShaderManagementConsoleApplication From cb5e2c71ffc59725ade56af09a5f27fd5d81ad34 Mon Sep 17 00:00:00 2001 From: Dayo Lawal Date: Thu, 5 Aug 2021 19:08:45 -0500 Subject: [PATCH 141/803] Typo fix2 Signed-off-by: Dayo Lawal --- .../MaterialEditor/Code/Source/Window/MaterialEditorWindow.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.h index d789e1d839..9eb8edbff3 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.h @@ -16,7 +16,7 @@ AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT #include #include -#include r> +#include AZ_POP_DISABLE_WARNING #endif From 3a76f2e6ce08ae736498852cc5d0d61654ddc781 Mon Sep 17 00:00:00 2001 From: evanchia Date: Thu, 5 Aug 2021 17:41:06 -0700 Subject: [PATCH 142/803] Fixing incorrect string replacement in Jenkinsfile Signed-off-by: evanchia --- scripts/build/Jenkins/Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/build/Jenkins/Jenkinsfile b/scripts/build/Jenkins/Jenkinsfile index 517fa1136d..d71d9964d9 100644 --- a/scripts/build/Jenkins/Jenkinsfile +++ b/scripts/build/Jenkins/Jenkinsfile @@ -370,7 +370,7 @@ def TestMetrics(Map pipelineConfig, String workspace, String branchName, String def command = "${pipelineConfig.PYTHON_DIR}/python.cmd -u mars/scripts/python/ctest_test_metric_scraper.py " + '-e jenkins.creds.user %username% -e jenkins.creds.pass %apitoken% ' + "-e jenkins.base_url ${env.JENKINS_URL} " + - "${cmakeBuildDir} ${branchName} %BUILD_NUMBER% AR ${configuration} ${repoName} --url ${env.BUILD_URL}.replace('%','%%')" + "${cmakeBuildDir} ${branchName} %BUILD_NUMBER% AR ${configuration} ${repoName} --url ${env.BUILD_URL.replace('%','%%')}" bat label: "Publishing ${buildJobName} Test Metrics", script: command } From 44a007547c1bf4a097cbeae55d7785b65a248106 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Thu, 5 Aug 2021 19:55:56 -0500 Subject: [PATCH 143/803] minor reformatting and removed unused headers from ME/SMCApplication.* Signed-off-by: Guthrie Adams --- .../Code/Source/MaterialEditorApplication.cpp | 29 +------------------ .../Code/Source/MaterialEditorApplication.h | 2 +- .../ShaderManagementConsoleApplication.cpp | 27 +---------------- .../ShaderManagementConsoleApplication.h | 2 +- 4 files changed, 4 insertions(+), 56 deletions(-) diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp index e12bc2409a..6f9d5aca41 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp @@ -6,40 +6,13 @@ * */ -#include -#include - #include #include #include - #include - -#include - -#include -#include #include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include #include +#include namespace MaterialEditor { diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h index 164fb9d920..da691feff7 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h @@ -34,5 +34,5 @@ namespace MaterialEditor void ProcessCommandLine(const AZ::CommandLine& commandLine) override; AZStd::string GetBuildTargetName() const override; AZStd::vector GetCriticalAssetFilters() const override; - }; + }; } // namespace MaterialEditor diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp index 2a5cd1430a..313522a256 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp @@ -8,35 +8,10 @@ #include #include -#include -#include #include - -#include - -#include #include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include #include +#include namespace ShaderManagementConsole { diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h index 0714ec17bc..24b2020dad 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h @@ -32,5 +32,5 @@ namespace ShaderManagementConsole void ProcessCommandLine(const AZ::CommandLine& commandLine); AZStd::string GetBuildTargetName() const override; AZStd::vector GetCriticalAssetFilters() const override; - }; + }; } // namespace ShaderManagementConsole From 782e8465a48b37221a171881062430cab1884d44 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Thu, 5 Aug 2021 20:05:01 -0500 Subject: [PATCH 144/803] removed StatusBarWidget class references Signed-off-by: Guthrie Adams --- .../Code/Source/Window/MaterialEditorWindow.h | 1 - .../Window/StatusBar/StatusBarWidget.cpp | 37 --------- .../Source/Window/StatusBar/StatusBarWidget.h | 42 ---------- .../Window/StatusBar/StatusBarWidget.ui | 82 ------------------- 4 files changed, 162 deletions(-) delete mode 100644 Gems/Atom/Tools/MaterialEditor/Code/Source/Window/StatusBar/StatusBarWidget.cpp delete mode 100644 Gems/Atom/Tools/MaterialEditor/Code/Source/Window/StatusBar/StatusBarWidget.h delete mode 100644 Gems/Atom/Tools/MaterialEditor/Code/Source/Window/StatusBar/StatusBarWidget.ui diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.h index 9eb8edbff3..5ecff06bc7 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.h @@ -15,7 +15,6 @@ AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT #include -#include #include AZ_POP_DISABLE_WARNING #endif diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/StatusBar/StatusBarWidget.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/StatusBar/StatusBarWidget.cpp deleted file mode 100644 index 4f037ccc58..0000000000 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/StatusBar/StatusBarWidget.cpp +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -#include -#include - -namespace MaterialEditor -{ - StatusBarWidget::StatusBarWidget(QWidget* parent) - : QWidget(parent) - , m_ui(new Ui::StatusBarWidget) - { - m_ui->setupUi(this); - } - - StatusBarWidget::~StatusBarWidget() = default; - - void StatusBarWidget::UpdateStatusInfo(const QString& status) - { - m_ui->m_statusLabel->setText(QString("%1").arg(status)); - } - void StatusBarWidget::UpdateStatusWarning(const QString& status) - { - m_ui->m_statusLabel->setText(QString("%1").arg(status)); - } - void StatusBarWidget::UpdateStatusError(const QString& status) - { - m_ui->m_statusLabel->setText(QString("%1").arg(status)); - } -} // namespace MaterialEditor - -#include diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/StatusBar/StatusBarWidget.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/StatusBar/StatusBarWidget.h deleted file mode 100644 index b637f41add..0000000000 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/StatusBar/StatusBarWidget.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -#pragma once - -#if !defined(Q_MOC_RUN) -#include - -AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT -#include -AZ_POP_DISABLE_WARNING -#endif - -namespace Ui -{ - class StatusBarWidget; -} - -namespace MaterialEditor -{ - //! Status bar for MaterialEditor. - class StatusBarWidget - : public QWidget - { - Q_OBJECT - public: - StatusBarWidget(QWidget* parent = nullptr); - ~StatusBarWidget(); - - void UpdateStatusInfo(const QString& status); - void UpdateStatusWarning(const QString& status); - void UpdateStatusError(const QString& status); - - private: - QScopedPointer m_ui; - }; -} // namespace MaterialEditor diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/StatusBar/StatusBarWidget.ui b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/StatusBar/StatusBarWidget.ui deleted file mode 100644 index e4f1d7a4b7..0000000000 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/StatusBar/StatusBarWidget.ui +++ /dev/null @@ -1,82 +0,0 @@ - - - StatusBarWidget - - - - 0 - 0 - 691 - 165 - - - - - 0 - 0 - - - - - 0 - 0 - - - - Status Bar - - - - 2 - - - 5 - - - 0 - - - 5 - - - 0 - - - - - - 0 - 0 - - - - - - - - - - - - - - Qt::Horizontal - - - QSizePolicy::MinimumExpanding - - - - 40 - 20 - - - - - - - - - - - From d6f08151cc721bc4ba3ab9997719bd0b6ca735e5 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Thu, 5 Aug 2021 20:56:46 -0500 Subject: [PATCH 145/803] removed unused headers and forwards Signed-off-by: Guthrie Adams --- .../Code/Source/MaterialEditorApplication.cpp | 2 +- .../Source/Window/MaterialEditorWindow.cpp | 30 ++++++------------- .../Code/Source/Window/MaterialEditorWindow.h | 7 +---- .../Window/ShaderManagementConsoleWindow.cpp | 29 ++++++++---------- .../Window/ShaderManagementConsoleWindow.h | 10 ++----- 5 files changed, 25 insertions(+), 53 deletions(-) diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp index 6f9d5aca41..bdd9e6fbaf 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp @@ -56,7 +56,7 @@ namespace MaterialEditor AZStd::vector MaterialEditorApplication::GetCriticalAssetFilters() const { - return AZStd::vector({ "passes/", "config/", "MaterialEditor" }); + return AZStd::vector({ "passes/", "config/", "MaterialEditor/" }); } void MaterialEditorApplication::ProcessCommandLine(const AZ::CommandLine& commandLine) diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp index 8d89e7442e..f93edfd275 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp @@ -7,39 +7,27 @@ */ #include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include #include -#include -#include - -#include -#include - -#include -#include -#include - -#include -#include -#include -#include - #include #include #include -#include #include #include #include #include +#include #include AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.h index 5ecff06bc7..9a713426ea 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.h @@ -19,11 +19,6 @@ AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnin AZ_POP_DISABLE_WARNING #endif -namespace AzToolsFramework -{ - class CScriptTermDialog; -} - namespace MaterialEditor { /** @@ -59,8 +54,8 @@ namespace MaterialEditor void OnDocumentSaved(const AZ::Uuid& documentId) override; void CreateMenu() override; - void CreateTabBar() override; + void AddTabForDocumentId(const AZ::Uuid& documentId) override; void UpdateTabForDocumentId(const AZ::Uuid& documentId) override; QString GetDocumentPath(const AZ::Uuid& documentId) const; diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp index 0a7ce6dd59..2cc4e67ba0 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp @@ -6,34 +6,29 @@ * */ -#include -#include - -#include -#include - #include - #include -#include - -#include #include #include #include -#include +#include +#include + +#include +#include +#include AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT #include -#include #include -#include -#include -#include -#include #include +#include #include +#include +#include +#include +#include AZ_POP_DISABLE_WARNING namespace ShaderManagementConsole @@ -482,4 +477,4 @@ namespace ShaderManagementConsole } } // namespace ShaderManagementConsole -#include +#include diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.h b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.h index f1c74a1f48..57bd11cb0a 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.h +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.h @@ -10,11 +10,10 @@ #if !defined(Q_MOC_RUN) #include -#include - #include #include #include +#include AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT #include @@ -24,11 +23,6 @@ AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnin AZ_POP_DISABLE_WARNING #endif -namespace AzToolsFramework -{ - class CScriptTermDialog; -} - namespace ShaderManagementConsole { /** @@ -57,8 +51,8 @@ namespace ShaderManagementConsole void OnDocumentSaved(const AZ::Uuid& documentId) override; void CreateMenu() override; - void CreateTabBar() override; + void AddTabForDocumentId(const AZ::Uuid& documentId) override; void UpdateTabForDocumentId(const AZ::Uuid& documentId) override; From 84623dfb6693ed38596c25a7c2902aaa0c4b997f Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Thu, 5 Aug 2021 19:25:26 -0700 Subject: [PATCH 146/803] FixedMaxPathString replacement Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Editor/CryEditPy.cpp | 4 ++-- Code/Editor/Util/PathUtil.cpp | 2 +- .../Framework/AzCore/Tests/IO/Path/PathTests.cpp | 4 ++-- .../AzFramework/AzFramework/Archive/Archive.cpp | 8 ++++---- .../AzFramework/AzFramework/Archive/IArchive.h | 2 +- .../AzFramework/Archive/NestedArchive.cpp | 16 ++++++++-------- .../AzFramework/Archive/ZipDirStructures.cpp | 2 +- .../native/ui/ProductAssetTreeModel.cpp | 4 ++-- .../native/ui/SourceAssetTreeModel.cpp | 4 ++-- 9 files changed, 23 insertions(+), 23 deletions(-) diff --git a/Code/Editor/CryEditPy.cpp b/Code/Editor/CryEditPy.cpp index 7e07d5553d..e4c300d744 100644 --- a/Code/Editor/CryEditPy.cpp +++ b/Code/Editor/CryEditPy.cpp @@ -210,7 +210,7 @@ namespace const char* PyGetCurrentLevelName() { // Using static member to capture temporary data - static AZStd::fixed_string tempLevelName; + static AZ::IO::FixedMaxPathString tempLevelName; tempLevelName = GetIEditor()->GetGameEngine()->GetLevelName().toUtf8().data(); return tempLevelName.c_str(); } @@ -218,7 +218,7 @@ namespace const char* PyGetCurrentLevelPath() { // Using static member to capture temporary data - static AZStd::fixed_string tempLevelPath; + static AZ::IO::FixedMaxPathString tempLevelPath; tempLevelPath = GetIEditor()->GetGameEngine()->GetLevelPath().toUtf8().data(); return tempLevelPath.c_str(); } diff --git a/Code/Editor/Util/PathUtil.cpp b/Code/Editor/Util/PathUtil.cpp index 3ca4b6222c..e8a5f0f74a 100644 --- a/Code/Editor/Util/PathUtil.cpp +++ b/Code/Editor/Util/PathUtil.cpp @@ -246,7 +246,7 @@ namespace Path AZStd::string GetEditingGameDataFolder() { // Define here the mod name - static AZStd::fixed_string s_currentModName; + static AZ::IO::FixedMaxPathString s_currentModName; if (s_currentModName.empty()) { diff --git a/Code/Framework/AzCore/Tests/IO/Path/PathTests.cpp b/Code/Framework/AzCore/Tests/IO/Path/PathTests.cpp index 79d9f8c302..41e0ac3f09 100644 --- a/Code/Framework/AzCore/Tests/IO/Path/PathTests.cpp +++ b/Code/Framework/AzCore/Tests/IO/Path/PathTests.cpp @@ -418,7 +418,7 @@ namespace UnitTest // Check each operator/= and append overload for success { - AZStd::fixed_string pathString{ "foo" }; + AZ::IO::FixedMaxPathString pathString{ "foo" }; AZ::IO::FixedMaxPath testPath('/'); testPath /= AZ::IO::PathView(pathString); testPath /= pathString; @@ -428,7 +428,7 @@ namespace UnitTest EXPECT_STREQ("foo/foo/foo/foo/f", testPath.c_str()); } { - AZStd::fixed_string pathString{ "foo" }; + AZ::IO::FixedMaxPathString pathString{ "foo" }; AZ::IO::FixedMaxPath testPath('/'); testPath.Append(AZ::IO::PathView(pathString)); testPath.Append(pathString); diff --git a/Code/Framework/AzFramework/AzFramework/Archive/Archive.cpp b/Code/Framework/AzFramework/AzFramework/Archive/Archive.cpp index 8c24250396..a3d2103650 100644 --- a/Code/Framework/AzFramework/AzFramework/Archive/Archive.cpp +++ b/Code/Framework/AzFramework/AzFramework/Archive/Archive.cpp @@ -94,7 +94,7 @@ namespace AZ::IO::ArchiveInternal } return convertedPath; } - return AZStd::make_optional>(sourcePath); + return AZStd::make_optional(sourcePath); } struct CCachedFileRawData @@ -614,7 +614,7 @@ namespace AZ::IO const char* Archive::AdjustFileName(AZStd::string_view src, char* dst, size_t dstSize, uint32_t, bool) { - AZStd::fixed_string srcPath{ src }; + AZ::IO::FixedMaxPathString srcPath{ src }; return AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(srcPath.c_str(), dst, dstSize) ? dst : nullptr; } @@ -2407,14 +2407,14 @@ namespace AZ::IO ////////////////////////////////////////////////////////////////////////// bool Archive::RemoveFile(AZStd::string_view pName) { - AZStd::fixed_string szFullPath{ pName }; + AZ::IO::FixedMaxPathString szFullPath{ pName }; return AZ::IO::FileIOBase::GetDirectInstance()->Remove(szFullPath.c_str()) == AZ::IO::ResultCode::Success; } ////////////////////////////////////////////////////////////////////////// bool Archive::RemoveDir(AZStd::string_view pName) { - AZStd::fixed_string szFullPath{ pName }; + AZ::IO::FixedMaxPathString szFullPath{ pName }; if (AZ::IO::FileIOBase::GetDirectInstance()->IsDirectory(szFullPath.c_str())) { diff --git a/Code/Framework/AzFramework/AzFramework/Archive/IArchive.h b/Code/Framework/AzFramework/AzFramework/Archive/IArchive.h index 3de63169b2..a23a213f05 100644 --- a/Code/Framework/AzFramework/AzFramework/Archive/IArchive.h +++ b/Code/Framework/AzFramework/AzFramework/Archive/IArchive.h @@ -30,7 +30,7 @@ namespace AZ::IO struct INestedArchive; struct IArchive; - using PathString = AZStd::fixed_string; + using PathString = AZ::IO::FixedMaxPathString; using StackString = AZStd::fixed_string<512>; struct MemoryBlock; diff --git a/Code/Framework/AzFramework/AzFramework/Archive/NestedArchive.cpp b/Code/Framework/AzFramework/AzFramework/Archive/NestedArchive.cpp index 16548c6a39..dc1d4aa864 100644 --- a/Code/Framework/AzFramework/AzFramework/Archive/NestedArchive.cpp +++ b/Code/Framework/AzFramework/AzFramework/Archive/NestedArchive.cpp @@ -41,7 +41,7 @@ namespace AZ::IO return ZipDir::ZD_ERROR_INVALID_CALL; } - AZStd::fixed_string fullPath = AdjustPath(szRelativePath); + AZ::IO::FixedMaxPathString fullPath = AdjustPath(szRelativePath); if (fullPath.empty()) { return ZipDir::ZD_ERROR_INVALID_PATH; @@ -63,7 +63,7 @@ namespace AZ::IO return ZipDir::ZD_ERROR_INVALID_CALL; } - AZStd::fixed_string fullPath = AdjustPath(szRelativePath); + AZ::IO::FixedMaxPathString fullPath = AdjustPath(szRelativePath); if (fullPath.empty()) { return ZipDir::ZD_ERROR_INVALID_PATH; @@ -81,7 +81,7 @@ namespace AZ::IO return ZipDir::ZD_ERROR_INVALID_CALL; } - AZStd::fixed_string fullPath = AdjustPath(szRelativePath); + AZ::IO::FixedMaxPathString fullPath = AdjustPath(szRelativePath); if (fullPath.empty()) { return ZipDir::ZD_ERROR_INVALID_PATH; @@ -105,7 +105,7 @@ namespace AZ::IO return ZipDir::ZD_ERROR_INVALID_CALL; } - AZStd::fixed_string fullPath = AdjustPath(szRelativePath); + AZ::IO::FixedMaxPathString fullPath = AdjustPath(szRelativePath); if (fullPath.empty()) { return ZipDir::ZD_ERROR_INVALID_PATH; @@ -122,7 +122,7 @@ namespace AZ::IO return ZipDir::ZD_ERROR_INVALID_CALL; } - AZStd::fixed_string fullPath = AdjustPath(szRelativePath); + AZ::IO::FixedMaxPathString fullPath = AdjustPath(szRelativePath); if (fullPath.empty()) { return ZipDir::ZD_ERROR_INVALID_PATH; @@ -141,7 +141,7 @@ namespace AZ::IO return ZipDir::ZD_ERROR_INVALID_CALL; } - AZStd::fixed_string fullPath = AdjustPath(szRelativePath); + AZ::IO::FixedMaxPathString fullPath = AdjustPath(szRelativePath); if (fullPath.empty()) { return ZipDir::ZD_ERROR_INVALID_PATH; @@ -152,7 +152,7 @@ namespace AZ::IO // finds the file; you don't have to close the returned handle auto NestedArchive::FindFile(AZStd::string_view szRelativePath) -> Handle { - AZStd::fixed_string fullPath = AdjustPath(szRelativePath); + AZ::IO::FixedMaxPathString fullPath = AdjustPath(szRelativePath); if (fullPath.empty()) { return nullptr; @@ -249,7 +249,7 @@ namespace AZ::IO if (m_nFlags & FLAGS_RELATIVE_PATHS_ONLY) { - return AZStd::fixed_string{ szRelativePath }; + return AZ::IO::FixedMaxPathString{ szRelativePath }; } if ((szRelativePath.size() > 1 && szRelativePath[1] == ':') || (m_nFlags & FLAGS_ABSOLUTE_PATHS)) diff --git a/Code/Framework/AzFramework/AzFramework/Archive/ZipDirStructures.cpp b/Code/Framework/AzFramework/AzFramework/Archive/ZipDirStructures.cpp index 034d2f4029..445bba63f4 100644 --- a/Code/Framework/AzFramework/AzFramework/Archive/ZipDirStructures.cpp +++ b/Code/Framework/AzFramework/AzFramework/Archive/ZipDirStructures.cpp @@ -440,7 +440,7 @@ namespace AZ::IO::ZipDir azstrcpy(volume, AZ_ARRAY_SIZE(volume), filename); } - AZStd::fixed_string drive{ AZ::IO::PathView(volume).RootName().Native() }; + AZ::IO::FixedMaxPathString drive{ AZ::IO::PathView(volume).RootName().Native() }; if (drive.empty()) { return false; diff --git a/Code/Tools/AssetProcessor/native/ui/ProductAssetTreeModel.cpp b/Code/Tools/AssetProcessor/native/ui/ProductAssetTreeModel.cpp index 6b5fa191e8..0574f00961 100644 --- a/Code/Tools/AssetProcessor/native/ui/ProductAssetTreeModel.cpp +++ b/Code/Tools/AssetProcessor/native/ui/ProductAssetTreeModel.cpp @@ -195,7 +195,7 @@ namespace AssetProcessor AZ::IO::Path currentFullFolderPath; const AZ::IO::PathView filename = productNamePath.Filename(); const AZ::IO::PathView fullPathWithoutFilename = productNamePath.RemoveFilename(); - AZStd::fixed_string currentPath; + AZ::IO::FixedMaxPathString currentPath; for (auto pathIt = fullPathWithoutFilename.begin(); pathIt != fullPathWithoutFilename.end(); ++pathIt) { currentPath = pathIt->FixedMaxPathString(); @@ -236,7 +236,7 @@ namespace AssetProcessor } AZStd::shared_ptr productItemData = - ProductAssetTreeItemData::MakeShared(&product, product.m_productName, AZStd::fixed_string(filename.Native()).c_str(), false, sourceId); + ProductAssetTreeItemData::MakeShared(&product, product.m_productName, AZ::IO::FixedMaxPathString(filename.Native()).c_str(), false, sourceId); m_productToTreeItem[product.m_productName] = parentItem->CreateChild(productItemData); m_productIdToTreeItem[product.m_productID] = m_productToTreeItem[product.m_productName]; diff --git a/Code/Tools/AssetProcessor/native/ui/SourceAssetTreeModel.cpp b/Code/Tools/AssetProcessor/native/ui/SourceAssetTreeModel.cpp index 6a5e53eb75..1fcdd62cf7 100644 --- a/Code/Tools/AssetProcessor/native/ui/SourceAssetTreeModel.cpp +++ b/Code/Tools/AssetProcessor/native/ui/SourceAssetTreeModel.cpp @@ -94,7 +94,7 @@ namespace AssetProcessor AZ::IO::Path currentFullFolderPath(AZ::IO::PosixPathSeparator); const AZ::IO::FixedMaxPath filename = fullPath.Filename(); fullPath.RemoveFilename(); - AZStd::fixed_string currentPath; + AZ::IO::FixedMaxPathString currentPath; for (auto pathIt = fullPath.begin(); pathIt != fullPath.end(); ++pathIt) { currentPath = pathIt->FixedMaxPathString(); @@ -125,7 +125,7 @@ namespace AssetProcessor } m_sourceToTreeItem[source.m_sourceName] = - parentItem->CreateChild(SourceAssetTreeItemData::MakeShared(&source, &scanFolder, source.m_sourceName, AZStd::fixed_string(filename.Native()).c_str(), false)); + parentItem->CreateChild(SourceAssetTreeItemData::MakeShared(&source, &scanFolder, source.m_sourceName, AZ::IO::FixedMaxPathString(filename.Native()).c_str(), false)); m_sourceIdToTreeItem[source.m_sourceID] = m_sourceToTreeItem[source.m_sourceName]; if (!modelIsResetting) { From 895dc09176351b44de34a7f810b40dc6c854f6dc Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Thu, 5 Aug 2021 19:30:09 -0700 Subject: [PATCH 147/803] addressing PR comments/suggestions Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../AzCore/AzCore/std/string/conversions.h | 4 +- .../AzCore/AzCore/std/string/utf8/unchecked.h | 48 +++++++++++++++++++ .../WinAPI/AzCore/Utils/Utils_WinAPI.cpp | 12 ++++- .../AzCore/Debug/StackTracer_Windows.cpp | 2 +- Code/Legacy/CryCommon/CryTypeInfo.cpp | 4 +- .../DataTypes/Rules/IMeshAdvancedRule.h | 2 +- 6 files changed, 63 insertions(+), 9 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/std/string/conversions.h b/Code/Framework/AzCore/AzCore/std/string/conversions.h index 235eb188d1..473c327143 100644 --- a/Code/Framework/AzCore/AzCore/std/string/conversions.h +++ b/Code/Framework/AzCore/AzCore/std/string/conversions.h @@ -338,7 +338,7 @@ namespace AZStd if (srcLen > 0) { char* endStr = Internal::WCharTPlatformConverter<>::to_string(dest, destSize, str, str + srcLen); - if (*(endStr - 1) != '\0') + if (endStr < (dest + destSize) && *(endStr - 1) != '\0') { *endStr = '\0'; // copy null terminator } @@ -495,7 +495,7 @@ namespace AZStd if (srcLen > 0) { wchar_t* endWStr = Internal::WCharTPlatformConverter<>::to_wstring(dest, destSize, str, str + srcLen); - if (*(endWStr - 1) != '\0') + if (endWStr < (dest + destSize) && *(endWStr - 1) != '\0') { *endWStr = '\0'; // copy null terminator } diff --git a/Code/Framework/AzCore/AzCore/std/string/utf8/unchecked.h b/Code/Framework/AzCore/AzCore/std/string/utf8/unchecked.h index cfc917ddc4..7199c58d3e 100644 --- a/Code/Framework/AzCore/AzCore/std/string/utf8/unchecked.h +++ b/Code/Framework/AzCore/AzCore/std/string/utf8/unchecked.h @@ -251,6 +251,54 @@ namespace Utf8::Unchecked return result; } + + static constexpr size_t utf8_codepoint_length(AZ::u32 cp) + { + if (cp < 0x80) + { + return 1; + } + else if (cp < 0x800) + { + return 2; + } + else if (cp < 0x10000) + { + return 3; + } + return 4; + } + + template + size_t utf16ToUtf8BytesRequired(u16bit_iterator start, u16bit_iterator end) + { + size_t bytesRequired = 0; + while (start != end) + { + AZ::u32 cp = Utf8::Internal::mask16(*start++); + // Take care of surrogate pairs first + if (Utf8::Internal::is_lead_surrogate(cp)) + { + AZ::u32 trail_surrogate = Utf8::Internal::mask16(*start++); + cp = (cp << 10) + trail_surrogate + Internal::SURROGATE_OFFSET; + } + bytesRequired += utf8_codepoint_length(cp); + } + return bytesRequired; + } + + template + size_t utf32ToUtf8BytesRequired(u32bit_iterator start, u32bit_iterator end) + { + size_t bytesRequired = 0; + while (start != end) + { + bytesRequired += utf8_codepoint_length(*start++); + } + return bytesRequired; + } + + } // namespace Utf8::Unchecked diff --git a/Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/Utils/Utils_WinAPI.cpp b/Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/Utils/Utils_WinAPI.cpp index dc104668be..4d8c9c8cfc 100644 --- a/Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/Utils/Utils_WinAPI.cpp +++ b/Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/Utils/Utils_WinAPI.cpp @@ -31,7 +31,7 @@ namespace AZ // Platform specific get exe path: http://stackoverflow.com/a/1024937 // https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getmodulefilenamea wchar_t pathBufferW[AZ::IO::MaxPathLength] = { 0 }; - const DWORD pathLen = GetModuleFileNameW(nullptr, pathBufferW, static_cast(exeStorageSize)); + const DWORD pathLen = GetModuleFileNameW(nullptr, pathBufferW, static_cast(AZStd::size(pathBufferW))); const DWORD errorCode = GetLastError(); if (pathLen == exeStorageSize && errorCode == ERROR_INSUFFICIENT_BUFFER) { @@ -43,7 +43,15 @@ namespace AZ } else { - AZStd::to_string(exeStorageBuffer, exeStorageSize, pathBufferW); + size_t utf8PathSize = Utf8::Unchecked::utf16ToUtf8BytesRequired(pathBufferW, pathBufferW + pathLen); + if (utf8PathSize >= exeStorageSize) + { + result.m_pathStored = ExecutablePathResult::BufferSizeNotLargeEnough; + } + else + { + AZStd::to_string(exeStorageBuffer, exeStorageSize, pathBufferW); + } } return result; diff --git a/Code/Framework/AzCore/Platform/Windows/AzCore/Debug/StackTracer_Windows.cpp b/Code/Framework/AzCore/Platform/Windows/AzCore/Debug/StackTracer_Windows.cpp index 8a99616de3..6cfaf1703b 100644 --- a/Code/Framework/AzCore/Platform/Windows/AzCore/Debug/StackTracer_Windows.cpp +++ b/Code/Framework/AzCore/Platform/Windows/AzCore/Debug/StackTracer_Windows.cpp @@ -90,7 +90,7 @@ namespace AZ { { case CBA_EVENT: evt = (PIMAGEHLP_CBA_EVENT)CallbackData; - _tprintf(_T("%s"), evt->desc); + printf("%s", evt->desc); break; default: diff --git a/Code/Legacy/CryCommon/CryTypeInfo.cpp b/Code/Legacy/CryCommon/CryTypeInfo.cpp index b1f7f20601..82743f7eef 100644 --- a/Code/Legacy/CryCommon/CryTypeInfo.cpp +++ b/Code/Legacy/CryCommon/CryTypeInfo.cpp @@ -132,9 +132,7 @@ const CTypeInfo&PtrTypeInfo() // bool AZStd::string ToString(bool const& val) { - static AZStd::fixed_string<5> sTrue = "true"; - static AZStd::fixed_string<6> sFalse = "false"; - return val ? sTrue.c_str() : sFalse.c_str(); + return val ? "true" : "false"; } bool FromString(bool& val, cstr s) diff --git a/Code/Tools/SceneAPI/SceneCore/DataTypes/Rules/IMeshAdvancedRule.h b/Code/Tools/SceneAPI/SceneCore/DataTypes/Rules/IMeshAdvancedRule.h index 48310091b3..04ed3f0949 100644 --- a/Code/Tools/SceneAPI/SceneCore/DataTypes/Rules/IMeshAdvancedRule.h +++ b/Code/Tools/SceneAPI/SceneCore/DataTypes/Rules/IMeshAdvancedRule.h @@ -19,7 +19,7 @@ namespace AZ { namespace DataTypes { - static AZStd::string s_advancedDisabledString = "Disabled"; + static const char* s_advancedDisabledString = "Disabled"; class IMeshAdvancedRule : public IRule From 6d79f1beee1987bcaac4d5e0c0c84bfdf430c625 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Thu, 5 Aug 2021 19:30:52 -0700 Subject: [PATCH 148/803] more replacements of A functions Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Editor/Platform/Windows/Util/Mailer_Windows.cpp | 2 +- Code/Editor/ProcessInfo.cpp | 2 +- .../Platform/Windows/AzCore/Platform_Windows.cpp | 12 ++++++------ 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Code/Editor/Platform/Windows/Util/Mailer_Windows.cpp b/Code/Editor/Platform/Windows/Util/Mailer_Windows.cpp index 0b33caed88..a3be4cfd45 100644 --- a/Code/Editor/Platform/Windows/Util/Mailer_Windows.cpp +++ b/Code/Editor/Platform/Windows/Util/Mailer_Windows.cpp @@ -28,7 +28,7 @@ bool CMailer::SendMail(const char* subject, GetCurrentDirectoryW(sizeof(dir), dir); // Load MAPI dll - HMODULE hMAPILib = LoadLibraryA("MAPI32.DLL"); + HMODULE hMAPILib = LoadLibraryW(L"MAPI32.DLL"); LPMAPISENDMAIL lpfnMAPISendMail = (LPMAPISENDMAIL) GetProcAddress(hMAPILib, "MAPISendMail"); int numRecipients = (int)_recipients.size(); diff --git a/Code/Editor/ProcessInfo.cpp b/Code/Editor/ProcessInfo.cpp index 87f4f23846..692e5d65ef 100644 --- a/Code/Editor/ProcessInfo.cpp +++ b/Code/Editor/ProcessInfo.cpp @@ -41,7 +41,7 @@ void LoadPSApi() { if (!g_hPSAPI) { - g_hPSAPI = LoadLibraryA("psapi.dll"); + g_hPSAPI = LoadLibraryW(L"psapi.dll"); if (g_hPSAPI) { diff --git a/Code/Framework/AzCore/Platform/Windows/AzCore/Platform_Windows.cpp b/Code/Framework/AzCore/Platform/Windows/AzCore/Platform_Windows.cpp index dc675cd931..cc45b36c41 100644 --- a/Code/Framework/AzCore/Platform/Windows/AzCore/Platform_Windows.cpp +++ b/Code/Framework/AzCore/Platform/Windows/AzCore/Platform_Windows.cpp @@ -31,8 +31,8 @@ namespace AZ // Query the machine guid generated at install time by windows, which is generated from // hardware signatures. This guid is not enough, because images (AWS) may duplicate this, // so include the hostname/username as well - TCHAR machineInfo[MAX_COMPUTERNAME_LENGTH + 1024] = { 0 }; - ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Cryptography", 0, KEY_QUERY_VALUE, &key); + wchar_t machineInfo[MAX_COMPUTERNAME_LENGTH + 1024] = { 0 }; + ret = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Cryptography", 0, KEY_QUERY_VALUE, &key); if (ret == ERROR_SUCCESS) { DWORD dataType = REG_SZ; @@ -45,17 +45,17 @@ namespace AZ AZ_Error("System", false, "Failed to open HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Cryptography\\MachineGuid!") } - TCHAR* hostname = machineInfo + wcslen(machineInfo); + wchar_t* hostname = machineInfo + wcslen(machineInfo); // salt the guid time with ComputerName/UserName DWORD bufCharCount = DWORD(sizeof(machineInfo) - (hostname - machineInfo)); - if (!::GetComputerName(hostname, &bufCharCount)) + if (!::GetComputerNameW(hostname, &bufCharCount)) { AZ_Error("System", false, "GetComputerName filed with code %d", GetLastError()); } - TCHAR* username = hostname + wcslen(hostname); + wchar_t* username = hostname + wcslen(hostname); bufCharCount = DWORD(sizeof(machineInfo) - (username - machineInfo)); - if( !GetUserName( username, &bufCharCount ) ) + if(!GetUserNameW(username, &bufCharCount)) { AZ_Error("System",false,"GetUserName filed with code %d",GetLastError()); } From 4358b6eb27fbb65baebb0afc2444015f8983af83 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Thu, 5 Aug 2021 19:31:12 -0700 Subject: [PATCH 149/803] runtime fixes (Editor running) Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Editor/Controls/ConsoleSCB.cpp | 8 +- Code/Editor/QuickAccessBar.cpp | 6 +- Code/Editor/SettingsManager.cpp | 10 +- Code/Editor/ToolsConfigPage.cpp | 6 +- Code/Legacy/CryCommon/IConsole.h | 2 +- Code/Legacy/CryCommon/Mocks/IConsoleMock.h | 2 +- Code/Legacy/CrySystem/XConsole.cpp | 115 +++++------------- Code/Legacy/CrySystem/XConsole.h | 2 +- Code/Legacy/CrySystem/XConsoleVariable.h | 7 +- .../RemoteConsole/Core/RemoteConsoleCore.cpp | 6 +- 10 files changed, 55 insertions(+), 109 deletions(-) diff --git a/Code/Editor/Controls/ConsoleSCB.cpp b/Code/Editor/Controls/ConsoleSCB.cpp index 0c664bbc59..9c13aa7328 100644 --- a/Code/Editor/Controls/ConsoleSCB.cpp +++ b/Code/Editor/Controls/ConsoleSCB.cpp @@ -562,15 +562,15 @@ static void OnVariableUpdated([[maybe_unused]] int row, ICVar* pCVar) static CVarBlock* VarBlockFromConsoleVars() { IConsole* console = GetIEditor()->GetSystem()->GetIConsole(); - std::vector cmds; + AZStd::vector cmds; cmds.resize(console->GetNumVars()); - size_t cmdCount = console->GetSortedVars(&cmds[0], cmds.size()); + size_t cmdCount = console->GetSortedVars(cmds); CVarBlock* vb = new CVarBlock; IVariable* pVariable = 0; for (int i = 0; i < cmdCount; i++) { - ICVar* pCVar = console->GetCVar(cmds[i]); + ICVar* pCVar = console->GetCVar(cmds[i].data()); if (!pCVar) { continue; @@ -602,7 +602,7 @@ static CVarBlock* VarBlockFromConsoleVars() pCVar->AddOnChangeFunctor(onChange); pVariable->SetDescription(pCVar->GetHelp()); - pVariable->SetName(cmds[i]); + pVariable->SetName(cmds[i].data()); // Transfer the custom limits have they have been set for this variable if (pCVar->HasCustomLimits()) diff --git a/Code/Editor/QuickAccessBar.cpp b/Code/Editor/QuickAccessBar.cpp index 0379be027d..59b4418c4c 100644 --- a/Code/Editor/QuickAccessBar.cpp +++ b/Code/Editor/QuickAccessBar.cpp @@ -68,12 +68,12 @@ void CQuickAccessBar::OnInitDialog() // Add console variables & commands. IConsole* console = GetIEditor()->GetSystem()->GetIConsole(); - std::vector cmds; + AZStd::vector cmds; cmds.resize(console->GetNumVars()); - size_t cmdCount = console->GetSortedVars(&cmds[0], cmds.size()); + size_t cmdCount = console->GetSortedVars(cmds); for (int i = 0; i < cmdCount; ++i) { - m_model->setStringList(m_model->stringList() += cmds[i]); + m_model->setStringList(m_model->stringList() += cmds[i].data()); } } diff --git a/Code/Editor/SettingsManager.cpp b/Code/Editor/SettingsManager.cpp index 82e3eaf1e6..3f170e83c8 100644 --- a/Code/Editor/SettingsManager.cpp +++ b/Code/Editor/SettingsManager.cpp @@ -607,7 +607,7 @@ void CSettingsManager::SerializeCVars(XmlNodeRef& node, bool bLoad) int nCurrentVariable(0); IConsole* piConsole(NULL); ICVar* piVariable(NULL); - std::vector cszVariableNames; + AZStd::vector cszVariableNames; char* szKey(NULL); char* szValue(NULL); @@ -662,7 +662,7 @@ void CSettingsManager::SerializeCVars(XmlNodeRef& node, bool bLoad) nNumberOfVariables = piConsole->GetNumVisibleVars(); cszVariableNames.resize(nNumberOfVariables, NULL); - if (piConsole->GetSortedVars((const char**)&cszVariableNames.front(), nNumberOfVariables, NULL) != nNumberOfVariables) + if (piConsole->GetSortedVars(cszVariableNames, NULL) != nNumberOfVariables) { assert(false); return; @@ -670,12 +670,12 @@ void CSettingsManager::SerializeCVars(XmlNodeRef& node, bool bLoad) for (nCurrentVariable = 0; nCurrentVariable < cszVariableNames.size(); ++nCurrentVariable) { - if (_stricmp(cszVariableNames[nCurrentVariable], "_TestFormatMessage") == 0) + if (_stricmp(cszVariableNames[nCurrentVariable].data(), "_TestFormatMessage") == 0) { continue; } - piVariable = piConsole->GetCVar(cszVariableNames[nCurrentVariable]); + piVariable = piConsole->GetCVar(cszVariableNames[nCurrentVariable].data()); if (!piVariable) { assert(false); @@ -683,7 +683,7 @@ void CSettingsManager::SerializeCVars(XmlNodeRef& node, bool bLoad) } newCVarNode = XmlHelpers::CreateXmlNode(CVAR_NODE); - newCVarNode->setAttr(cszVariableNames[nCurrentVariable], piVariable->GetString()); + newCVarNode->setAttr(cszVariableNames[nCurrentVariable].data(), piVariable->GetString()); cvarsNode->addChild(newCVarNode); } diff --git a/Code/Editor/ToolsConfigPage.cpp b/Code/Editor/ToolsConfigPage.cpp index a2328550e0..7e481506b3 100644 --- a/Code/Editor/ToolsConfigPage.cpp +++ b/Code/Editor/ToolsConfigPage.cpp @@ -818,12 +818,12 @@ void CToolsConfigPage::FillConsoleCmds() { QStringList commands; IConsole* console = GetIEditor()->GetSystem()->GetIConsole(); - std::vector cmds; + AZStd::vector cmds; cmds.resize(console->GetNumVars()); - size_t cmdCount = console->GetSortedVars(&cmds[0], cmds.size()); + size_t cmdCount = console->GetSortedVars(cmds); for (int i = 0; i < cmdCount; ++i) { - commands.push_back(cmds[i]); + commands.push_back(cmds[i].data()); } m_completionModel->setStringList(commands); } diff --git a/Code/Legacy/CryCommon/IConsole.h b/Code/Legacy/CryCommon/IConsole.h index 79bfc5b532..e03de35aa1 100644 --- a/Code/Legacy/CryCommon/IConsole.h +++ b/Code/Legacy/CryCommon/IConsole.h @@ -426,7 +426,7 @@ struct IConsole // szPrefix - 0 or prefix e.g. "sys_spec_" // Return // used size - virtual size_t GetSortedVars(const char** pszArray, size_t numItems, const char* szPrefix = 0) = 0; + virtual size_t GetSortedVars(AZStd::vector& pszArray, const char* szPrefix = 0) = 0; virtual const char* AutoComplete(const char* substr) = 0; virtual const char* AutoCompletePrev(const char* substr) = 0; virtual const char* ProcessCompletion(const char* szInputBuffer) = 0; diff --git a/Code/Legacy/CryCommon/Mocks/IConsoleMock.h b/Code/Legacy/CryCommon/Mocks/IConsoleMock.h index 1475e8e01e..b416aa5f11 100644 --- a/Code/Legacy/CryCommon/Mocks/IConsoleMock.h +++ b/Code/Legacy/CryCommon/Mocks/IConsoleMock.h @@ -56,7 +56,7 @@ public: MOCK_METHOD0(IsOpened, bool ()); MOCK_METHOD0(GetNumVars, int()); MOCK_METHOD0(GetNumVisibleVars, int()); - MOCK_METHOD3(GetSortedVars, size_t (const char** pszArray, size_t numItems, const char* szPrefix)); + MOCK_METHOD2(GetSortedVars, size_t (AZStd::vector& pszArray, const char* szPrefix)); MOCK_METHOD1(AutoComplete, const char*(const char* substr)); MOCK_METHOD1(AutoCompletePrev, const char*(const char* substr)); MOCK_METHOD1(ProcessCompletion, const char*(const char* szInputBuffer)); diff --git a/Code/Legacy/CrySystem/XConsole.cpp b/Code/Legacy/CrySystem/XConsole.cpp index 6da42420f8..0f98dd12d6 100644 --- a/Code/Legacy/CrySystem/XConsole.cpp +++ b/Code/Legacy/CrySystem/XConsole.cpp @@ -84,35 +84,6 @@ inline int GetCharPrio(char x) return x; } } -// case sensitive -inline bool less_CVar(const AZStd::string& left, const AZStd::string& right) -{ - AZStd::string_view leftView(left); - AZStd::string_view rightView(right); - for (;; ) - { - uint32 l = GetCharPrio(leftView.front()), r = GetCharPrio(rightView.front()); - - if (l < r) - { - return true; - } - if (l > r) - { - return false; - } - - if (leftView.front() == 0 || rightView.front() == 0) - { - break; - } - - leftView.remove_prefix(1); - rightView.remove_prefix(1); - } - - return false; -} void Command_SetWaitSeconds(IConsoleCmdArgs* pCmd) { @@ -347,28 +318,6 @@ void CXConsole::Init(ISystem* pSystem) con_restricted = 0; } - // test cases ----------------------------------------------- - assert(GetCVar("con_debug") != 0); // should be registered a few lines above - assert(GetCVar("Con_Debug") == GetCVar("con_debug")); // different case - - // editor - assert(strcmp(AutoComplete("con_"), "con_debug") == 0); - assert(strcmp(AutoComplete("CON_"), "con_debug") == 0); - assert(strcmp(AutoComplete("con_debug"), "con_display_last_messages") == 0); // actually we should reconsider this behavior - assert(strcmp(AutoComplete("Con_Debug"), "con_display_last_messages") == 0); // actually we should reconsider this behavior - - // game - assert(strcmp(ProcessCompletion("con_"), "con_debug ") == 0); - ResetAutoCompletion(); - assert(strcmp(ProcessCompletion("CON_"), "con_debug ") == 0); - ResetAutoCompletion(); - assert(strcmp(ProcessCompletion("con_debug"), "con_debug ") == 0); - ResetAutoCompletion(); - assert(strcmp(ProcessCompletion("Con_Debug"), "con_debug ") == 0); - ResetAutoCompletion(); - - // ---------------------------------------------------------- - m_nLoadingBackTexID = -1; if (gEnv->IsDedicated()) @@ -2424,7 +2373,7 @@ const char* CXConsole::ProcessCompletion(const char* szInputBuffer) if (!matches.empty()) { - std::sort(matches.begin(), matches.end(), less_CVar); // to sort commands with variables + std::sort(matches.begin(), matches.end()); // to sort commands with variables } if (showlist && !matches.empty()) { @@ -3181,7 +3130,7 @@ char* CXConsole::GetCheatVarAt(uint32 nOffset) ////////////////////////////////////////////////////////////////////////// -size_t CXConsole::GetSortedVars(const char** pszArray, size_t numItems, const char* szPrefix) +size_t CXConsole::GetSortedVars(AZStd::vector& pszArray, const char* szPrefix) { size_t i = 0; size_t iPrefixLen = szPrefix ? strlen(szPrefix) : 0; @@ -3191,7 +3140,7 @@ size_t CXConsole::GetSortedVars(const char** pszArray, size_t numItems, const ch ConsoleVariablesMap::const_iterator it, end = m_mapVariables.end(); for (it = m_mapVariables.begin(); it != end; ++it) { - if (pszArray && i >= numItems) + if (i >= pszArray.size()) { break; } @@ -3209,10 +3158,7 @@ size_t CXConsole::GetSortedVars(const char** pszArray, size_t numItems, const ch continue; } - if (pszArray) - { - pszArray[i] = it->first; - } + pszArray[i] = it->first; i++; } @@ -3223,7 +3169,7 @@ size_t CXConsole::GetSortedVars(const char** pszArray, size_t numItems, const ch ConsoleCommandsMap::iterator it, end = m_mapCommands.end(); for (it = m_mapCommands.begin(); it != end; ++it) { - if (pszArray && i >= numItems) + if (i >= pszArray.size()) { break; } @@ -3241,18 +3187,15 @@ size_t CXConsole::GetSortedVars(const char** pszArray, size_t numItems, const ch continue; } - if (pszArray) - { - pszArray[i] = it->first.c_str(); - } + pszArray[i] = it->first.c_str(); i++; } } - if (i != 0 && pszArray) + if (i != 0) { - std::sort(pszArray, pszArray + i, less_CVar); + std::sort(pszArray.begin(), pszArray.end()); } return i; @@ -3261,22 +3204,22 @@ size_t CXConsole::GetSortedVars(const char** pszArray, size_t numItems, const ch ////////////////////////////////////////////////////////////////////////// void CXConsole::FindVar(const char* substr) { - std::vector cmds; + AZStd::vector cmds; cmds.resize(GetNumVars() + m_mapCommands.size()); - size_t cmdCount = GetSortedVars(&cmds[0], cmds.size()); + size_t cmdCount = GetSortedVars(cmds); for (size_t i = 0; i < cmdCount; i++) { if (AZ::StringFunc::Find(cmds[i], substr) != AZStd::string::npos) { - ICVar* pCvar = gEnv->pConsole->GetCVar(cmds[i]); + ICVar* pCvar = gEnv->pConsole->GetCVar(cmds[i].data()); if (pCvar) { DisplayVarValue(pCvar); } else { - ConsoleLogInputResponse(" $3%s $6(Command)", cmds[i]); + ConsoleLogInputResponse(" $3%.*s $6(Command)", aznumeric_cast(cmds[i].size()), cmds[i].data()); } } } @@ -3287,22 +3230,22 @@ const char* CXConsole::AutoComplete(const char* substr) { // following code can be optimized - std::vector cmds; + AZStd::vector cmds; cmds.resize(GetNumVars() + m_mapCommands.size()); - size_t cmdCount = GetSortedVars(&cmds[0], cmds.size()); + size_t cmdCount = GetSortedVars(cmds); size_t substrLen = strlen(substr); // If substring is empty return first command. if (substrLen == 0 && cmdCount > 0) { - return cmds[0]; + return cmds[0].data(); } // find next for (size_t i = 0; i < cmdCount; i++) { - const char* szCmd = cmds[i]; + const char* szCmd = cmds[i].data(); size_t cmdlen = strlen(szCmd); if (cmdlen >= substrLen && memcmp(szCmd, substr, substrLen) == 0) { @@ -3311,18 +3254,18 @@ const char* CXConsole::AutoComplete(const char* substr) i++; if (i < cmdCount) { - return cmds[i]; + return cmds[i].data(); } - return cmds[i - 1]; + return cmds[i - 1].data(); } - return cmds[i]; + return cmds[i].data(); } } // then first matching case insensitive for (size_t i = 0; i < cmdCount; i++) { - const char* szCmd = cmds[i]; + const char* szCmd = cmds[i].data(); size_t cmdlen = strlen(szCmd); if (cmdlen >= substrLen && azstrnicmp(szCmd, substr, substrLen) == 0) @@ -3332,11 +3275,11 @@ const char* CXConsole::AutoComplete(const char* substr) i++; if (i < cmdCount) { - return cmds[i]; + return cmds[i].data(); } - return cmds[i - 1]; + return cmds[i - 1].data(); } - return cmds[i]; + return cmds[i].data(); } } @@ -3357,27 +3300,27 @@ void CXConsole::SetInputLine(const char* szLine) ////////////////////////////////////////////////////////////////////////// const char* CXConsole::AutoCompletePrev(const char* substr) { - std::vector cmds; + AZStd::vector cmds; cmds.resize(GetNumVars() + m_mapCommands.size()); - size_t cmdCount = GetSortedVars(&cmds[0], cmds.size()); + size_t cmdCount = GetSortedVars(cmds); // If substring is empty return last command. if (strlen(substr) == 0 && cmds.size() > 0) { - return cmds[cmdCount - 1]; + return cmds[cmdCount - 1].data(); } for (unsigned int i = 0; i < cmdCount; i++) { - if (azstricmp(substr, cmds[i]) == 0) + if (azstricmp(substr, cmds[i].data()) == 0) { if (i > 0) { - return cmds[i - 1]; + return cmds[i - 1].data(); } else { - return cmds[0]; + return cmds[0].data(); } } } diff --git a/Code/Legacy/CrySystem/XConsole.h b/Code/Legacy/CrySystem/XConsole.h index b141a88e52..16d1870be6 100644 --- a/Code/Legacy/CrySystem/XConsole.h +++ b/Code/Legacy/CrySystem/XConsole.h @@ -181,7 +181,7 @@ public: virtual bool IsOpened(); virtual int GetNumVars(); virtual int GetNumVisibleVars(); - virtual size_t GetSortedVars(const char** pszArray, size_t numItems, const char* szPrefix = 0); + virtual size_t GetSortedVars(AZStd::vector& pszArray, const char* szPrefix = 0); virtual int GetNumCheatVars(); virtual void SetCheatVarHashRange(size_t firstVar, size_t lastVar); virtual void CalcCheatVarHash(); diff --git a/Code/Legacy/CrySystem/XConsoleVariable.h b/Code/Legacy/CrySystem/XConsoleVariable.h index e4f9c14355..122389407f 100644 --- a/Code/Legacy/CrySystem/XConsoleVariable.h +++ b/Code/Legacy/CrySystem/XConsoleVariable.h @@ -179,8 +179,11 @@ public: CXConsoleVariableString(CXConsole* pConsole, const char* sName, const char* szDefault, int nFlags, const char* help) : CXConsoleVariableBase(pConsole, sName, nFlags, help) { - m_sValue = szDefault; - m_sDefault = szDefault; + if (szDefault) + { + m_sValue = szDefault; + m_sDefault = szDefault; + } } // interface ICVar -------------------------------------------------------------------------------------- diff --git a/Code/Tools/RemoteConsole/Core/RemoteConsoleCore.cpp b/Code/Tools/RemoteConsole/Core/RemoteConsoleCore.cpp index 24faf2ccaa..aa439116a0 100644 --- a/Code/Tools/RemoteConsole/Core/RemoteConsoleCore.cpp +++ b/Code/Tools/RemoteConsole/Core/RemoteConsoleCore.cpp @@ -446,10 +446,10 @@ bool SRemoteClient::SendPackage(const char* buffer, int size) ///////////////////////////////////////////////////////////////////////////////////////////// void SRemoteClient::FillAutoCompleteList(AZStd::vector& list) { - AZStd::vector cmds; - size_t count = gEnv->pConsole->GetSortedVars(nullptr, 0); + AZStd::vector cmds; + size_t count = gEnv->pConsole->GetSortedVars(cmds); cmds.resize(count); - count = gEnv->pConsole->GetSortedVars(&cmds[0], count); + count = gEnv->pConsole->GetSortedVars(cmds); for (size_t i = 0; i < count; ++i) { list.push_back(cmds[i]); From b4bf775647c3d2bc03a94988226e1751644ed9ae Mon Sep 17 00:00:00 2001 From: pappeste Date: Wed, 16 Jun 2021 17:14:27 -0700 Subject: [PATCH 150/803] enable the warning Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- cmake/Platform/Common/MSVC/Configurations_msvc.cmake | 1 - 1 file changed, 1 deletion(-) diff --git a/cmake/Platform/Common/MSVC/Configurations_msvc.cmake b/cmake/Platform/Common/MSVC/Configurations_msvc.cmake index 4024e45bad..118a515e30 100644 --- a/cmake/Platform/Common/MSVC/Configurations_msvc.cmake +++ b/cmake/Platform/Common/MSVC/Configurations_msvc.cmake @@ -38,7 +38,6 @@ ly_append_configurations_options( /wd4201 # nonstandard extension used: nameless struct/union. This actually became part of the C++11 std, MS has an open issue: https://developercommunity.visualstudio.com/t/warning-level-4-generates-a-bogus-warning-c4201-no/103064 # Disabling these warnings while they get fixed - /wd4018 # signed/unsigned mismatch /wd4244 # conversion, possible loss of data /wd4245 # conversion, signed/unsigned mismatch /wd4389 # comparison, signed/unsigned mismatch From 97354ce90a9ddd6600271df1e663e21790fc8dc1 Mon Sep 17 00:00:00 2001 From: pappeste Date: Fri, 18 Jun 2021 16:36:30 -0700 Subject: [PATCH 151/803] Sandbox Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Editor/ViewportTitleDlg.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Code/Editor/ViewportTitleDlg.cpp b/Code/Editor/ViewportTitleDlg.cpp index c1e1afb908..cbf2958eea 100644 --- a/Code/Editor/ViewportTitleDlg.cpp +++ b/Code/Editor/ViewportTitleDlg.cpp @@ -451,19 +451,19 @@ void CViewportTitleDlg::AddFOVMenus(QMenu* menu, std::function call { for (size_t i = 0; i < customPresets.size(); ++i) { - if (customPresets[i].isEmpty()) + if (customPresets[static_cast(i)].isEmpty()) { break; } float fov = gSettings.viewports.fDefaultFov; bool ok; - float f = customPresets[i].toDouble(&ok); + float f = customPresets[static_cast(i)].toDouble(&ok); if (ok) { fov = std::max(1.0f, f); fov = std::min(120.0f, f); - QAction* action = menu->addAction(customPresets[i]); + QAction* action = menu->addAction(customPresets[static_cast(i)]); connect(action, &QAction::triggered, action, [fov, callback](){ callback(fov); }); } } @@ -537,13 +537,13 @@ void CViewportTitleDlg::AddAspectRatioMenus(QMenu* menu, std::function(i)].isEmpty()) { break; } static QRegularExpression regex(QStringLiteral("^(\\d+):(\\d+)$")); - QRegularExpressionMatch matches = regex.match(customPresets[i]); + QRegularExpressionMatch matches = regex.match(customPresets[static_cast(i)]); if (matches.hasMatch()) { bool ok; @@ -551,7 +551,7 @@ void CViewportTitleDlg::AddAspectRatioMenus(QMenu* menu, std::functionaddAction(customPresets[i]); + QAction* action = menu->addAction(customPresets[static_cast(i)]); connect(action, &QAction::triggered, action, [width, height, callback]() {callback(width, height); }); } } @@ -668,13 +668,13 @@ void CViewportTitleDlg::AddResolutionMenus(QMenu* menu, std::function(i)].isEmpty()) { break; } static QRegularExpression regex(QStringLiteral("^(\\d+) x (\\d+)$")); - QRegularExpressionMatch matches = regex.match(customPresets[i]); + QRegularExpressionMatch matches = regex.match(customPresets[static_cast(i)]); if (matches.hasMatch()) { bool ok; @@ -682,7 +682,7 @@ void CViewportTitleDlg::AddResolutionMenus(QMenu* menu, std::functionaddAction(customPresets[i]); + QAction* action = menu->addAction(customPresets[static_cast(i)]); connect(action, &QAction::triggered, action, [width, height, callback](){ callback(width, height); }); } } From 10f950b726ca9e6d8fe7f3c776b6094d9027dcce Mon Sep 17 00:00:00 2001 From: pappeste Date: Fri, 18 Jun 2021 17:45:51 -0700 Subject: [PATCH 152/803] fix w4018 Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../Prefab/Benchmark/PrefabBenchmarkFixture.cpp | 4 ++-- .../Prefab/Benchmark/PrefabCreateBenchmarks.cpp | 6 +++--- .../Benchmark/PrefabInstantiateBenchmarks.cpp | 2 +- .../Prefab/Benchmark/PrefabLoadBenchmarks.cpp | 2 +- Code/Legacy/CrySystem/SystemWin32.cpp | 2 +- .../SDKWrapper/AssImpMaterialWrapper.cpp | 2 +- .../Importers/AssImpAnimationImporter.cpp | 4 ++-- .../Importers/AssImpBitangentStreamImporter.cpp | 4 ++-- .../Importers/AssImpBlendShapeImporter.cpp | 8 ++++---- .../Importers/AssImpColorStreamImporter.cpp | 9 ++++----- .../Importers/AssImpMaterialImporter.cpp | 2 +- .../Importers/AssImpTangentStreamImporter.cpp | 4 ++-- .../Importers/AssImpUvMapImporter.cpp | 6 +++--- .../Utilities/AssImpMeshImporterUtilities.cpp | 8 ++++---- .../Code/Source/AWSCoreSystemComponent.cpp | 2 +- .../Attribution/AWSCoreAttributionManager.cpp | 2 +- Gems/AWSMetrics/Code/Source/MetricsManager.cpp | 4 ++-- Gems/AWSMetrics/Code/Source/MetricsQueue.cpp | 2 +- .../AtomFont/Code/Source/FontRenderer.cpp | 4 ++-- .../Code/Source/Family/BlastFamilyImpl.cpp | 2 +- Gems/Blast/Code/Tests/Mocks/BlastMocks.h | 2 +- Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp | 2 +- .../Code/Tests/GradientSignalImageTests.cpp | 8 ++++---- Gems/ImGui/Code/Source/ImGuiManager.cpp | 2 +- .../Code/Source/Shape/ShapeGeometryUtil.cpp | 17 ++++++++--------- .../Editor/Animation/UiAnimViewSequence.cpp | 4 ++-- Gems/LyShine/Code/Editor/SpriteBorderEditor.cpp | 4 ++-- .../LyShine/Code/Source/EditorPropertyTypes.cpp | 3 ++- Gems/LyShine/Code/Source/UiImageComponent.cpp | 12 ++++++------ .../LyShine/Code/Source/UiInteractableState.cpp | 2 +- .../Code/Source/UiParticleEmitterComponent.cpp | 4 ++-- Gems/LyShine/Code/Source/UiTextComponent.cpp | 2 +- Gems/PhysXDebug/Code/Source/SystemComponent.cpp | 4 ++-- 33 files changed, 72 insertions(+), 73 deletions(-) diff --git a/Code/Framework/AzToolsFramework/Tests/Prefab/Benchmark/PrefabBenchmarkFixture.cpp b/Code/Framework/AzToolsFramework/Tests/Prefab/Benchmark/PrefabBenchmarkFixture.cpp index 7e47fa9569..9925d5bff3 100644 --- a/Code/Framework/AzToolsFramework/Tests/Prefab/Benchmark/PrefabBenchmarkFixture.cpp +++ b/Code/Framework/AzToolsFramework/Tests/Prefab/Benchmark/PrefabBenchmarkFixture.cpp @@ -85,7 +85,7 @@ namespace Benchmark void BM_Prefab::CreateEntities(const unsigned int entityCount, AZStd::vector& entities) { - for (int entityIndex = 0; entityIndex < entityCount; ++entityIndex) + for (unsigned int entityIndex = 0; entityIndex < entityCount; ++entityIndex) { AZStd::string entityName = "TestEntity"; entityName = entityName + AZStd::to_string(entityIndex); @@ -101,7 +101,7 @@ namespace Benchmark void BM_Prefab::CreateFakePaths(const unsigned int pathCount) { //setup fake paths - for (int number = 0; number < pathCount; ++number) + for (unsigned int number = 0; number < pathCount; ++number) { AZStd::string path = m_pathString; m_paths.push_back(path + AZStd::to_string(number) + "_" + AZStd::to_string(pathCount)); diff --git a/Code/Framework/AzToolsFramework/Tests/Prefab/Benchmark/PrefabCreateBenchmarks.cpp b/Code/Framework/AzToolsFramework/Tests/Prefab/Benchmark/PrefabCreateBenchmarks.cpp index b809a20944..12efea1cc8 100644 --- a/Code/Framework/AzToolsFramework/Tests/Prefab/Benchmark/PrefabCreateBenchmarks.cpp +++ b/Code/Framework/AzToolsFramework/Tests/Prefab/Benchmark/PrefabCreateBenchmarks.cpp @@ -32,7 +32,7 @@ namespace Benchmark state.ResumeTiming(); - for (int instanceCounter = 0; instanceCounter < numInstances; ++instanceCounter) + for (unsigned int instanceCounter = 0; instanceCounter < numInstances; ++instanceCounter) { newInstances.push_back(m_prefabSystemComponent->CreatePrefab( { entities[instanceCounter] }, @@ -110,7 +110,7 @@ namespace Benchmark AZStd::vector> testInstances; testInstances.resize(numInstancesToAdd); - for (int instanceCounter = 0; instanceCounter < numInstancesToAdd; ++instanceCounter) + for (unsigned int instanceCounter = 0; instanceCounter < numInstancesToAdd; ++instanceCounter) { testInstances[instanceCounter] = (m_prefabSystemComponent->CreatePrefab( { entities[instanceCounter] } @@ -161,7 +161,7 @@ namespace Benchmark state.ResumeTiming(); - for (int instanceCounter = 0; instanceCounter < numInstances; ++instanceCounter) + for (unsigned int instanceCounter = 0; instanceCounter < numInstances; ++instanceCounter) { nestedInstanceRoot = m_prefabSystemComponent->CreatePrefab( {}, diff --git a/Code/Framework/AzToolsFramework/Tests/Prefab/Benchmark/PrefabInstantiateBenchmarks.cpp b/Code/Framework/AzToolsFramework/Tests/Prefab/Benchmark/PrefabInstantiateBenchmarks.cpp index 3e9f0ab08e..90ff30a30e 100644 --- a/Code/Framework/AzToolsFramework/Tests/Prefab/Benchmark/PrefabInstantiateBenchmarks.cpp +++ b/Code/Framework/AzToolsFramework/Tests/Prefab/Benchmark/PrefabInstantiateBenchmarks.cpp @@ -33,7 +33,7 @@ namespace Benchmark state.ResumeTiming(); - for (int instanceCounter = 0; instanceCounter < numInstances; ++instanceCounter) + for (unsigned int instanceCounter = 0; instanceCounter < numInstances; ++instanceCounter) { newInstances[instanceCounter] = m_prefabSystemComponent->InstantiatePrefab(templateToInstantiateId); } diff --git a/Code/Framework/AzToolsFramework/Tests/Prefab/Benchmark/PrefabLoadBenchmarks.cpp b/Code/Framework/AzToolsFramework/Tests/Prefab/Benchmark/PrefabLoadBenchmarks.cpp index 7e64fa886c..a6c1e27caf 100644 --- a/Code/Framework/AzToolsFramework/Tests/Prefab/Benchmark/PrefabLoadBenchmarks.cpp +++ b/Code/Framework/AzToolsFramework/Tests/Prefab/Benchmark/PrefabLoadBenchmarks.cpp @@ -29,7 +29,7 @@ namespace Benchmark state.ResumeTiming(); - for (int templateCounter = 0; templateCounter < numTemplates; ++templateCounter) + for (unsigned int templateCounter = 0; templateCounter < numTemplates; ++templateCounter) { m_prefabLoaderInterface->LoadTemplateFromFile(m_paths[templateCounter]); } diff --git a/Code/Legacy/CrySystem/SystemWin32.cpp b/Code/Legacy/CrySystem/SystemWin32.cpp index 2cc41adc08..3e499f9853 100644 --- a/Code/Legacy/CrySystem/SystemWin32.cpp +++ b/Code/Legacy/CrySystem/SystemWin32.cpp @@ -410,7 +410,7 @@ void CSystem::debug_GetCallStack(const char** pFunctions, int& nCount) unsigned int numFrames = StackRecorder::Record(frames, nMaxCount, 1); SymbolStorage::StackLine* textLines = (SymbolStorage::StackLine*)AZ_ALLOCA(sizeof(SymbolStorage::StackLine)*nMaxCount); SymbolStorage::DecodeFrames(frames, numFrames, textLines); - for (int i = 0; i < numFrames; i++) + for (unsigned int i = 0; i < numFrames; i++) { pFunctions[i] = textLines[i]; } diff --git a/Code/Tools/SceneAPI/SDKWrapper/AssImpMaterialWrapper.cpp b/Code/Tools/SceneAPI/SDKWrapper/AssImpMaterialWrapper.cpp index c24577a6de..8ea25a2ff0 100644 --- a/Code/Tools/SceneAPI/SDKWrapper/AssImpMaterialWrapper.cpp +++ b/Code/Tools/SceneAPI/SDKWrapper/AssImpMaterialWrapper.cpp @@ -194,7 +194,7 @@ namespace AZ AZStd::string AssImpMaterialWrapper::GetTextureFileName(MaterialMapType textureType) const { /// Engine currently doesn't support multiple textures. Right now we only use first texture. - int textureIndex = 0; + unsigned int textureIndex = 0; aiString absTexturePath; switch (textureType) { diff --git a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpAnimationImporter.cpp b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpAnimationImporter.cpp index aadb834aa9..da1db22d5e 100644 --- a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpAnimationImporter.cpp +++ b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpAnimationImporter.cpp @@ -612,10 +612,10 @@ namespace AZ ValueToKeyDataMap valueToKeyDataMap; // Key time can be less than zero, normalize to have zero be the lowest time. double keyOffset = 0; - for (int keyIdx = 0; keyIdx < meshMorphAnim->mNumKeys; keyIdx++) + for (unsigned int keyIdx = 0; keyIdx < meshMorphAnim->mNumKeys; keyIdx++) { aiMeshMorphKey& key = meshMorphAnim->mKeys[keyIdx]; - for (int valIdx = 0; valIdx < key.mNumValuesAndWeights; ++valIdx) + for (unsigned int valIdx = 0; valIdx < key.mNumValuesAndWeights; ++valIdx) { int currentValue = key.mValues[valIdx]; KeyData thisKey(key.mWeights[valIdx], key.mTime); diff --git a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpBitangentStreamImporter.cpp b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpBitangentStreamImporter.cpp index 51e0147599..b9b9af1e65 100644 --- a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpBitangentStreamImporter.cpp +++ b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpBitangentStreamImporter.cpp @@ -89,11 +89,11 @@ namespace AZ bitangentStream->SetGenerationMethod(AZ::SceneAPI::DataTypes::TangentGenerationMethod::FromSourceScene); bitangentStream->ReserveContainerSpace(vertexCount); - for (int sdkMeshIndex = 0; sdkMeshIndex < currentNode->mNumMeshes; ++sdkMeshIndex) + for (unsigned int sdkMeshIndex = 0; sdkMeshIndex < currentNode->mNumMeshes; ++sdkMeshIndex) { const aiMesh* mesh = scene->mMeshes[currentNode->mMeshes[sdkMeshIndex]]; - for (int v = 0; v < mesh->mNumVertices; ++v) + for (unsigned int v = 0; v < mesh->mNumVertices; ++v) { if (!mesh->HasTangentsAndBitangents()) { diff --git a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpBlendShapeImporter.cpp b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpBlendShapeImporter.cpp index d139a1c86c..e8eb5ecf68 100644 --- a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpBlendShapeImporter.cpp +++ b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpBlendShapeImporter.cpp @@ -85,7 +85,7 @@ namespace AZ { int sceneMeshIdx = context.m_sourceNode.GetAssImpNode()->mMeshes[nodeMeshIdx]; const aiMesh* aiMesh = context.m_sourceScene.GetAssImpScene()->mMeshes[sceneMeshIdx]; - for (int animIdx = 0; animIdx < aiMesh->mNumAnimMeshes; animIdx++) + for (unsigned int animIdx = 0; animIdx < aiMesh->mNumAnimMeshes; animIdx++) { aiAnimMesh* aiAnimMesh = aiMesh->mAnimMeshes[animIdx]; animToMeshToAnimMeshIndices[aiAnimMesh->mName.C_Str()].emplace_back(nodeMeshIdx, animIdx); @@ -130,7 +130,7 @@ namespace AZ blendShapeData->ReserveData( aiAnimMesh->mNumVertices, aiAnimMesh->HasTangentsAndBitangents(), uvSetUsedFlags, colorSetUsedFlags); - for (int vertIdx = 0; vertIdx < aiAnimMesh->mNumVertices; ++vertIdx) + for (unsigned int vertIdx = 0; vertIdx < aiAnimMesh->mNumVertices; ++vertIdx) { AZ::Vector3 vertex(AssImpSDKWrapper::AssImpTypeConverter::ToVector3(aiAnimMesh->mVertices[vertIdx])); @@ -184,7 +184,7 @@ namespace AZ } // aiAnimMesh just has a list of positions for vertices. The face indices are on the original mesh. - for (int faceIdx = 0; faceIdx < aiMesh->mNumFaces; ++faceIdx) + for (unsigned int faceIdx = 0; faceIdx < aiMesh->mNumFaces; ++faceIdx) { aiFace face = aiMesh->mFaces[faceIdx]; DataTypes::IBlendShapeData::Face blendFace; @@ -199,7 +199,7 @@ namespace AZ face.mNumIndices); continue; } - for (int idx = 0; idx < face.mNumIndices; ++idx) + for (unsigned int idx = 0; idx < face.mNumIndices; ++idx) { blendFace.vertexIndex[idx] = face.mIndices[idx] + vertexOffset; } diff --git a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpColorStreamImporter.cpp b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpColorStreamImporter.cpp index 438e56e8ad..4043f529df 100644 --- a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpColorStreamImporter.cpp +++ b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpColorStreamImporter.cpp @@ -56,7 +56,7 @@ namespace AZ const aiScene* scene = context.m_sourceScene.GetAssImpScene(); // This node has at least one mesh, verify that the color channel counts are the same for all meshes. - const int expectedColorChannels = scene->mMeshes[currentNode->mMeshes[0]]->GetNumColorChannels(); + const unsigned int expectedColorChannels = scene->mMeshes[currentNode->mMeshes[0]]->GetNumColorChannels(); const bool allMeshesHaveSameNumberOfColorChannels = AZStd::all_of(currentNode->mMeshes + 1, currentNode->mMeshes + currentNode->mNumMeshes, [scene, expectedColorChannels](const unsigned int meshIndex) { @@ -80,17 +80,16 @@ namespace AZ const uint64_t vertexCount = GetVertexCountForAllMeshesOnNode(*currentNode, *scene); Events::ProcessingResultCombiner combinedVertexColorResults; - for (int colorSetIndex = 0; colorSetIndex < expectedColorChannels; ++colorSetIndex) + for (unsigned int colorSetIndex = 0; colorSetIndex < expectedColorChannels; ++colorSetIndex) { - AZStd::shared_ptr vertexColors = AZStd::make_shared(); vertexColors->ReserveContainerSpace(vertexCount); - for (int sdkMeshIndex = 0; sdkMeshIndex < currentNode->mNumMeshes; ++sdkMeshIndex) + for (unsigned int sdkMeshIndex = 0; sdkMeshIndex < currentNode->mNumMeshes; ++sdkMeshIndex) { const aiMesh* mesh = scene->mMeshes[currentNode->mMeshes[sdkMeshIndex]]; - for (int v = 0; v < mesh->mNumVertices; ++v) + for (unsigned int v = 0; v < mesh->mNumVertices; ++v) { if (colorSetIndex < mesh->GetNumColorChannels()) { diff --git a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpMaterialImporter.cpp b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpMaterialImporter.cpp index 4880c8d736..8983c76bac 100644 --- a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpMaterialImporter.cpp +++ b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpMaterialImporter.cpp @@ -56,7 +56,7 @@ namespace AZ Events::ProcessingResultCombiner combinedMaterialImportResults; AZStd::unordered_map> materialMap; - for (int idx = 0; idx < context.m_sourceNode.m_assImpNode->mNumMeshes; ++idx) + for (unsigned int idx = 0; idx < context.m_sourceNode.m_assImpNode->mNumMeshes; ++idx) { int meshIndex = context.m_sourceNode.m_assImpNode->mMeshes[idx]; const aiMesh* assImpMesh = context.m_sourceScene.GetAssImpScene()->mMeshes[meshIndex]; diff --git a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpTangentStreamImporter.cpp b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpTangentStreamImporter.cpp index 6f1c364399..fbafd3d24f 100644 --- a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpTangentStreamImporter.cpp +++ b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpTangentStreamImporter.cpp @@ -91,11 +91,11 @@ namespace AZ tangentStream->SetGenerationMethod(AZ::SceneAPI::DataTypes::TangentGenerationMethod::FromSourceScene); tangentStream->ReserveContainerSpace(vertexCount); - for (int sdkMeshIndex = 0; sdkMeshIndex < currentNode->mNumMeshes; ++sdkMeshIndex) + for (unsigned int sdkMeshIndex = 0; sdkMeshIndex < currentNode->mNumMeshes; ++sdkMeshIndex) { const aiMesh* mesh = scene->mMeshes[currentNode->mMeshes[sdkMeshIndex]]; - for (int v = 0; v < mesh->mNumVertices; ++v) + for (unsigned int v = 0; v < mesh->mNumVertices; ++v) { if (!mesh->HasTangentsAndBitangents()) { diff --git a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpUvMapImporter.cpp b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpUvMapImporter.cpp index 12e13422cf..fc0ac15244 100644 --- a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpUvMapImporter.cpp +++ b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpUvMapImporter.cpp @@ -62,7 +62,7 @@ namespace AZ // so they can be separated by engine code instead. bool foundTextureCoordinates = false; AZStd::array meshesPerTextureCoordinateIndex = {}; - for (int localMeshIndex = 0; localMeshIndex < currentNode->mNumMeshes; ++localMeshIndex) + for (unsigned int localMeshIndex = 0; localMeshIndex < currentNode->mNumMeshes; ++localMeshIndex) { aiMesh* mesh = scene->mMeshes[currentNode->mMeshes[localMeshIndex]]; for (int texCoordIndex = 0; texCoordIndex < meshesPerTextureCoordinateIndex.size(); ++texCoordIndex) @@ -110,7 +110,7 @@ namespace AZ uvMap->ReserveContainerSpace(vertexCount); bool customNameFound = false; AZStd::string name(AZStd::string::format("%s%d", m_defaultNodeName, texCoordIndex)); - for (int sdkMeshIndex = 0; sdkMeshIndex < currentNode->mNumMeshes; ++sdkMeshIndex) + for (unsigned int sdkMeshIndex = 0; sdkMeshIndex < currentNode->mNumMeshes; ++sdkMeshIndex) { const aiMesh* mesh = scene->mMeshes[currentNode->mMeshes[sdkMeshIndex]]; if(mesh->mTextureCoords[texCoordIndex]) @@ -136,7 +136,7 @@ namespace AZ } } - for (int v = 0; v < mesh->mNumVertices; ++v) + for (unsigned int v = 0; v < mesh->mNumVertices; ++v) { if (mesh->mTextureCoords[texCoordIndex]) { diff --git a/Code/Tools/SceneAPI/SceneBuilder/Importers/Utilities/AssImpMeshImporterUtilities.cpp b/Code/Tools/SceneAPI/SceneBuilder/Importers/Utilities/AssImpMeshImporterUtilities.cpp index a9ab292d25..de94018c9b 100644 --- a/Code/Tools/SceneAPI/SceneBuilder/Importers/Utilities/AssImpMeshImporterUtilities.cpp +++ b/Code/Tools/SceneAPI/SceneBuilder/Importers/Utilities/AssImpMeshImporterUtilities.cpp @@ -40,7 +40,7 @@ namespace AZ::SceneAPI::SceneBuilder // This code re-combines them to match previous FBX SDK behavior, // so they can be separated by engine code instead. int vertOffset = 0; - for (int m = 0; m < currentNode->mNumMeshes; ++m) + for (unsigned int m = 0; m < currentNode->mNumMeshes; ++m) { const aiMesh* mesh = scene->mMeshes[currentNode->mMeshes[m]]; @@ -50,7 +50,7 @@ namespace AZ::SceneAPI::SceneBuilder assImpMatIndexToLYIndex.insert(AZStd::pair(mesh->mMaterialIndex, lyMeshIndex++)); } - for (int vertIdx = 0; vertIdx < mesh->mNumVertices; ++vertIdx) + for (unsigned int vertIdx = 0; vertIdx < mesh->mNumVertices; ++vertIdx) { AZ::Vector3 vertex(mesh->mVertices[vertIdx].x, mesh->mVertices[vertIdx].y, mesh->mVertices[vertIdx].z); @@ -68,7 +68,7 @@ namespace AZ::SceneAPI::SceneBuilder } } - for (int faceIdx = 0; faceIdx < mesh->mNumFaces; ++faceIdx) + for (unsigned int faceIdx = 0; faceIdx < mesh->mNumFaces; ++faceIdx) { aiFace face = mesh->mFaces[faceIdx]; AZ::SceneAPI::DataTypes::IMeshData::Face meshFace; @@ -82,7 +82,7 @@ namespace AZ::SceneAPI::SceneBuilder face.mNumIndices); continue; } - for (int idx = 0; idx < face.mNumIndices; ++idx) + for (unsigned int idx = 0; idx < face.mNumIndices; ++idx) { meshFace.vertexIndex[idx] = face.mIndices[idx] + vertOffset; } diff --git a/Gems/AWSCore/Code/Source/AWSCoreSystemComponent.cpp b/Gems/AWSCore/Code/Source/AWSCoreSystemComponent.cpp index c24518a4d7..92a5aa493f 100644 --- a/Gems/AWSCore/Code/Source/AWSCoreSystemComponent.cpp +++ b/Gems/AWSCore/Code/Source/AWSCoreSystemComponent.cpp @@ -160,7 +160,7 @@ namespace AWSCore // assigned to a specific CPU starting with the specified CPU. AZ::JobManagerDesc jobManagerDesc{}; AZ::JobManagerThreadDesc threadDesc(m_firstThreadCPU, m_threadPriority, m_threadStackSize); - for (unsigned int i = 0; i < m_threadCount; ++i) + for (int i = 0; i < m_threadCount; ++i) { jobManagerDesc.m_workerThreads.push_back(threadDesc); if (threadDesc.m_cpuId > -1) diff --git a/Gems/AWSCore/Code/Source/Editor/Attribution/AWSCoreAttributionManager.cpp b/Gems/AWSCore/Code/Source/Editor/Attribution/AWSCoreAttributionManager.cpp index e0b4db9165..85dd1469cb 100644 --- a/Gems/AWSCore/Code/Source/Editor/Attribution/AWSCoreAttributionManager.cpp +++ b/Gems/AWSCore/Code/Source/Editor/Attribution/AWSCoreAttributionManager.cpp @@ -139,7 +139,7 @@ namespace AWSCore AZStd::chrono::seconds lastSendTimeStamp = AZStd::chrono::seconds(lastSendTimeStampSeconds); AZStd::chrono::seconds secondsSinceLastSend = AZStd::chrono::duration_cast(AZStd::chrono::system_clock::now().time_since_epoch()) - lastSendTimeStamp; - if (secondsSinceLastSend.count() >= delayInSeconds) + if (static_cast(secondsSinceLastSend.count()) >= delayInSeconds) { return true; } diff --git a/Gems/AWSMetrics/Code/Source/MetricsManager.cpp b/Gems/AWSMetrics/Code/Source/MetricsManager.cpp index 5c4d910658..03e31770ee 100644 --- a/Gems/AWSMetrics/Code/Source/MetricsManager.cpp +++ b/Gems/AWSMetrics/Code/Source/MetricsManager.cpp @@ -106,7 +106,7 @@ namespace AWSMetrics AZStd::lock_guard lock(m_metricsMutex); m_metricsQueue.AddMetrics(metricsEvent); - if (m_metricsQueue.GetSizeInBytes() >= m_clientConfiguration->GetMaxQueueSizeInBytes()) + if (m_metricsQueue.GetSizeInBytes() >= static_cast(m_clientConfiguration->GetMaxQueueSizeInBytes())) { // Flush the metrics queue when the accumulated metrics size hits the limit m_waitEvent.release(); @@ -431,7 +431,7 @@ namespace AWSMetrics AZStd::lock_guard lock(m_metricsMutex); m_metricsQueue.AddMetrics(offlineRecords[index]); - if (m_metricsQueue.GetSizeInBytes() >= m_clientConfiguration->GetMaxQueueSizeInBytes()) + if (m_metricsQueue.GetSizeInBytes() >= static_cast(m_clientConfiguration->GetMaxQueueSizeInBytes())) { // Flush the metrics queue when the accumulated metrics size hits the limit m_waitEvent.release(); diff --git a/Gems/AWSMetrics/Code/Source/MetricsQueue.cpp b/Gems/AWSMetrics/Code/Source/MetricsQueue.cpp index ab54fb9e3e..4cc037189a 100644 --- a/Gems/AWSMetrics/Code/Source/MetricsQueue.cpp +++ b/Gems/AWSMetrics/Code/Source/MetricsQueue.cpp @@ -216,7 +216,7 @@ namespace AWSMetrics return false; } - for (int metricsIndex = 0; metricsIndex < doc.Size(); metricsIndex++) + for (rapidjson::SizeType metricsIndex = 0; metricsIndex < doc.Size(); metricsIndex++) { MetricsEvent metrics; if (!metrics.ReadFromJson(doc[metricsIndex])) diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Source/FontRenderer.cpp b/Gems/AtomLyIntegration/AtomFont/Code/Source/FontRenderer.cpp index 101a506ddc..225b6d5ff6 100644 --- a/Gems/AtomLyIntegration/AtomFont/Code/Source/FontRenderer.cpp +++ b/Gems/AtomLyIntegration/AtomFont/Code/Source/FontRenderer.cpp @@ -252,8 +252,8 @@ int AZ::FontRenderer::GetGlyph(GlyphBitmap* glyphBitmap, int* horizontalAdvance, const int textureSlotBufferHeight = glyphBitmap->GetHeight(); // might happen if font characters are too big or cache dimenstions in font.xml is too small "" - const bool charWidthFits = iX + m_glyph->bitmap.width <= textureSlotBufferWidth; - const bool charHeightFits = iY + m_glyph->bitmap.rows <= textureSlotBufferHeight; + const bool charWidthFits = static_cast(iX + m_glyph->bitmap.width) <= textureSlotBufferWidth; + const bool charHeightFits = static_cast(iY + m_glyph->bitmap.rows) <= textureSlotBufferHeight; const bool charFitsInSlot = charWidthFits && charHeightFits; AZ_Error("Font", charFitsInSlot, "Character code %d doesn't fit in font texture; check 'sizeRatio' attribute in font XML or adjust this character's sizing in the font.", characterCode); diff --git a/Gems/Blast/Code/Source/Family/BlastFamilyImpl.cpp b/Gems/Blast/Code/Source/Family/BlastFamilyImpl.cpp index ec4925fe51..2690a12f24 100644 --- a/Gems/Blast/Code/Source/Family/BlastFamilyImpl.cpp +++ b/Gems/Blast/Code/Source/Family/BlastFamilyImpl.cpp @@ -450,7 +450,7 @@ namespace Blast const auto buffer = m_asset.GetAccelerator()->fillDebugRender(-1, mode == DebugRenderAabbTreeSegments); if (buffer.lineCount) { - for (int i = 0; i < buffer.lineCount; ++i) + for (uint32_t i = 0; i < buffer.lineCount; ++i) { auto& line = buffer.lines[i]; AZ::Color color; diff --git a/Gems/Blast/Code/Tests/Mocks/BlastMocks.h b/Gems/Blast/Code/Tests/Mocks/BlastMocks.h index 0733862e25..dddd1e275a 100644 --- a/Gems/Blast/Code/Tests/Mocks/BlastMocks.h +++ b/Gems/Blast/Code/Tests/Mocks/BlastMocks.h @@ -562,7 +562,7 @@ namespace Blast public: FakeEntityProvider(uint32_t entityCount) { - for (int i = 0; i < entityCount; ++i) + for (uint32 i = 0; i < entityCount; ++i) { m_entities.push_back(AZStd::make_shared()); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp index 833f8a14f3..a6368ac088 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp @@ -1555,7 +1555,7 @@ namespace EMotionFX const uint32 geomLODLevel = 0; const uint32 numNodes = mSkeleton->GetNumNodes(); - for (int nodeIndex = 0; nodeIndex < numNodes; nodeIndex++) + for (uint32 nodeIndex = 0; nodeIndex < numNodes; nodeIndex++) { // check if this node has a mesh, if not we can skip it Mesh* mesh = GetMesh(geomLODLevel, nodeIndex); diff --git a/Gems/GradientSignal/Code/Tests/GradientSignalImageTests.cpp b/Gems/GradientSignal/Code/Tests/GradientSignalImageTests.cpp index b1aa74c397..ea9a1d380f 100644 --- a/Gems/GradientSignal/Code/Tests/GradientSignalImageTests.cpp +++ b/Gems/GradientSignal/Code/Tests/GradientSignalImageTests.cpp @@ -116,9 +116,9 @@ namespace UnitTest size_t value = 0; AZStd::hash_combine(value, seed); - for (int x = 0; x < width; ++x) + for (AZ::u32 x = 0; x < width; ++x) { - for (int y = 0; y < height; ++y) + for (AZ::u32 y = 0; y < height; ++y) { AZStd::hash_combine(value, x); AZStd::hash_combine(value, y); @@ -141,9 +141,9 @@ namespace UnitTest const AZ::u8 pixelValue = 255; // Image data should be stored inverted on the y axis relative to our engine, so loop backwards through y. - for (int y = height - 1; y >= 0; --y) + for (int y = static_cast(height) - 1; y >= 0; --y) { - for (int x = 0; x < width; ++x) + for (AZ::u32 x = 0; x < width; ++x) { if ((x == pixelX) && (y == pixelY)) { diff --git a/Gems/ImGui/Code/Source/ImGuiManager.cpp b/Gems/ImGui/Code/Source/ImGuiManager.cpp index ac3247b6a4..427af6d7dc 100644 --- a/Gems/ImGui/Code/Source/ImGuiManager.cpp +++ b/Gems/ImGui/Code/Source/ImGuiManager.cpp @@ -409,7 +409,7 @@ void ImGuiManager::Render() break; case ImGuiResolutionMode::MatchToMaxRenderResolution: - if (backBufferWidth <= static_cast(m_renderResolution.x)) + if (backBufferWidth <= static_cast(m_renderResolution.x)) { renderRes[0] = backBufferWidth; renderRes[1] = backBufferHeight; diff --git a/Gems/LmbrCentral/Code/Source/Shape/ShapeGeometryUtil.cpp b/Gems/LmbrCentral/Code/Source/Shape/ShapeGeometryUtil.cpp index cdb97d2702..3b54447fdd 100644 --- a/Gems/LmbrCentral/Code/Source/Shape/ShapeGeometryUtil.cpp +++ b/Gems/LmbrCentral/Code/Source/Shape/ShapeGeometryUtil.cpp @@ -353,10 +353,10 @@ namespace LmbrCentral const AZ::u32 sides, const AZ::u32 segments, const AZ::u32 capSegments, AZ::u32* indices) { - const auto capSegmentTipVerts = capSegments > 0 ? 1 : 0; - const auto totalSegments = segments + capSegments * 2; - const auto numVerts = sides * (totalSegments + 1) + 2 * capSegmentTipVerts; - const auto hasEnds = capSegments > 0; + const AZ::u32 capSegmentTipVerts = capSegments > 0 ? 1 : 0; + const AZ::u32 totalSegments = segments + capSegments * 2; + const AZ::u32 numVerts = sides * (totalSegments + 1) + 2 * capSegmentTipVerts; + const AZ::u32 hasEnds = capSegments > 0; // Start Faces (start point of tube) // Each starting face shares the same vertex at the beginning of the vertex buffer @@ -365,8 +365,7 @@ namespace LmbrCentral // 1 face per side if (hasEnds) { - - for (auto i = 0; i < sides; ++i) + for (AZ::u32 i = 0; i < sides; ++i) { AZ::u32 a = i + 1; AZ::u32 b = a + 1; @@ -383,9 +382,9 @@ namespace LmbrCentral // Middle Faces // 2 triangles per face. // 1 face per side. - for (auto i = 0; i < totalSegments; ++i) + for (AZ::u32 i = 0; i < totalSegments; ++i) { - for (auto j = 0; j < sides; ++j) + for (AZ::u32 j = 0; j < sides; ++j) { // 4 corners for each face // a ------ d @@ -416,7 +415,7 @@ namespace LmbrCentral // 1 face per side if (hasEnds) { - for (auto i = 0; i < sides; ++i) + for (AZ::u32 i = 0; i < sides; ++i) { AZ::u32 a = totalSegments * sides + i + 1; AZ::u32 b = a + 1; diff --git a/Gems/LyShine/Code/Editor/Animation/UiAnimViewSequence.cpp b/Gems/LyShine/Code/Editor/Animation/UiAnimViewSequence.cpp index 86554c2004..b4c98c39bf 100644 --- a/Gems/LyShine/Code/Editor/Animation/UiAnimViewSequence.cpp +++ b/Gems/LyShine/Code/Editor/Animation/UiAnimViewSequence.cpp @@ -1093,7 +1093,7 @@ void CUiAnimViewSequence::DeselectAllKeys() CUiAnimViewSequenceNotificationContext context(this); CUiAnimViewKeyBundle selectedKeys = GetSelectedKeys(); - for (int i = 0; i < selectedKeys.GetKeyCount(); ++i) + for (unsigned int i = 0; i < selectedKeys.GetKeyCount(); ++i) { CUiAnimViewKeyHandle keyHandle = selectedKeys.GetKey(i); keyHandle.Select(false); @@ -1237,7 +1237,7 @@ float CUiAnimViewSequence::ClipTimeOffsetForSliding(const float timeOffset) for (pTrackIter = tracks.begin(); pTrackIter != tracks.end(); ++pTrackIter) { CUiAnimViewTrack* pTrack = *pTrackIter; - for (int i = 0; i < pTrack->GetKeyCount(); ++i) + for (unsigned int i = 0; i < pTrack->GetKeyCount(); ++i) { CUiAnimViewKeyHandle keyHandle = pTrack->GetKey(i); diff --git a/Gems/LyShine/Code/Editor/SpriteBorderEditor.cpp b/Gems/LyShine/Code/Editor/SpriteBorderEditor.cpp index 1d8de3598e..e46073284b 100644 --- a/Gems/LyShine/Code/Editor/SpriteBorderEditor.cpp +++ b/Gems/LyShine/Code/Editor/SpriteBorderEditor.cpp @@ -191,9 +191,9 @@ void SpriteBorderEditor::UpdateSpriteSheetCellInfo(int newNumRows, int newNumCol // Calculate uniformly sized sprite-sheet cell UVs based on the given // row and column cell configuration. - for (int row = 0; row < m_numRows; ++row) + for (unsigned int row = 0; row < m_numRows; ++row) { - for (int col = 0; col < m_numCols; ++col) + for (unsigned int col = 0; col < m_numCols; ++col) { AZ::Vector2 min(col / floatNumCols, row / floatNumRows); AZ::Vector2 max((col + 1) / floatNumCols, (row + 1) / floatNumRows); diff --git a/Gems/LyShine/Code/Source/EditorPropertyTypes.cpp b/Gems/LyShine/Code/Source/EditorPropertyTypes.cpp index 77a9f59732..695412819d 100644 --- a/Gems/LyShine/Code/Source/EditorPropertyTypes.cpp +++ b/Gems/LyShine/Code/Source/EditorPropertyTypes.cpp @@ -17,8 +17,9 @@ LyShine::AZu32ComboBoxVec LyShine::GetEnumSpriteIndexList(AZ::EntityId entityId, int indexCount = 0; EBUS_EVENT_ID_RESULT(indexCount, entityId, UiIndexableImageBus, GetImageIndexCount); + const AZ::u32 indexCountu32 = static_cast(indexCount); - if (indexCount > 0 && (indexMax <= indexCount - 1) && indexMin <= indexMax) + if (indexCount > 0 && (indexMax <= indexCountu32 - 1) && indexMin <= indexMax) { for (AZ::u32 i = indexMin; i <= indexMax; ++i) { diff --git a/Gems/LyShine/Code/Source/UiImageComponent.cpp b/Gems/LyShine/Code/Source/UiImageComponent.cpp index 1e48bdff51..e56d9957b0 100644 --- a/Gems/LyShine/Code/Source/UiImageComponent.cpp +++ b/Gems/LyShine/Code/Source/UiImageComponent.cpp @@ -224,9 +224,9 @@ namespace IDraw2d::Rounding pixelRounding = isPixelAligned ? IDraw2d::Rounding::Nearest : IDraw2d::Rounding::None; float z = 1.0f; int i = 0; - for (int y = 0; y < numY; ++y) + for (uint32 y = 0; y < numY; ++y) { - for (int x = 0; x < numX; x += 1) + for (uint32 x = 0; x < numX; x += 1) { AZ::Vector3 point3(xValues[x], yValues[y], z); point3 = transform * point3; @@ -2030,7 +2030,7 @@ void UiImageComponent::ClipValuesForSlicedLinearFill(uint32 numValues, float* xV float previousPercentage = 0; int previousIndex = startClip; int clampIndex = -1; // to clamp all values greater than m_fillAmount in specified direction. - for (int arrayPos = 1; arrayPos < numValues; ++arrayPos) + for (uint32 arrayPos = 1; arrayPos < numValues; ++arrayPos) { int currentIndex = startClip + arrayPos * clipInc; float thisPercentage = (clipPosition[currentIndex] - clipPosition[startClip]) / totalLength; @@ -2102,7 +2102,7 @@ void UiImageComponent::ClipAndRenderForSlicedRadialFill(uint32 numVertsPerSide, if (m_fillAmount < 0.5f) { // Clips against first half line and then rotating line and adds results to render list. - for (int currentIndex = 0; currentIndex < totalIndices; currentIndex += 3) + for (uint32 currentIndex = 0; currentIndex < totalIndices; currentIndex += 3) { SVF_P2F_C4B_T2F_F4B intermediateVerts[maxTemporaryVerts]; uint16 intermediateIndices[maxTemporaryIndices]; @@ -2118,7 +2118,7 @@ void UiImageComponent::ClipAndRenderForSlicedRadialFill(uint32 numVertsPerSide, else { // Clips against first half line and adds results to render list then clips against the second half line and rotating line and also adds those results to render list. - for (int currentIndex = 0; currentIndex < totalIndices; currentIndex += 3) + for (uint32 currentIndex = 0; currentIndex < totalIndices; currentIndex += 3) { SVF_P2F_C4B_T2F_F4B intermediateVerts[maxTemporaryVerts]; uint16 intermediateIndices[maxTemporaryIndices]; @@ -2201,7 +2201,7 @@ void UiImageComponent::ClipAndRenderForSlicedRadialCornerOrEdgeFill(uint32 numVe int numIndicesToRender = 0; int vertexOffset = 0; - for (int ix = 0; ix < totalIndices; ix += 3) + for (uint32 ix = 0; ix < totalIndices; ix += 3) { int indicesUsed = ClipToLine(verts, &indices[ix], renderVerts, renderIndices, vertexOffset, numIndicesToRender, lineOrigin, lineEnd); numIndicesToRender += indicesUsed; diff --git a/Gems/LyShine/Code/Source/UiInteractableState.cpp b/Gems/LyShine/Code/Source/UiInteractableState.cpp index d3440a9354..7e87782d00 100644 --- a/Gems/LyShine/Code/Source/UiInteractableState.cpp +++ b/Gems/LyShine/Code/Source/UiInteractableState.cpp @@ -616,7 +616,7 @@ UiInteractableStateFont::FontEffectComboBoxVec UiInteractableStateFont::Populate // NOTE: Curently, in order for this to work, when the font is changed we need to do // "RefreshEntireTree" to get the combo box list refreshed. unsigned int numEffects = m_fontFamily ? m_fontFamily->normal->GetNumEffects() : 0; - for (int i = 0; i < numEffects; ++i) + for (unsigned int i = 0; i < numEffects; ++i) { const char* name = m_fontFamily->normal->GetEffectName(i); result.push_back(AZStd::make_pair(i, name)); diff --git a/Gems/LyShine/Code/Source/UiParticleEmitterComponent.cpp b/Gems/LyShine/Code/Source/UiParticleEmitterComponent.cpp index 9668ebf463..a8b678947b 100644 --- a/Gems/LyShine/Code/Source/UiParticleEmitterComponent.cpp +++ b/Gems/LyShine/Code/Source/UiParticleEmitterComponent.cpp @@ -830,7 +830,7 @@ void UiParticleEmitterComponent::Render(LyShine::IRenderGraph* renderGraph) AZ::u32 totalVerticesInserted = 0; // particlesToRender is the max particles we will render, we could render less if some have zero alpha - for (int i = 0; i < particlesToRender; ++i) + for (AZ::u32 i = 0; i < particlesToRender; ++i) { SVF_P2F_C4B_T2F_F4B* firstVertexOfParticle = &m_cachedPrimitive.m_vertices[totalVerticesInserted]; @@ -1827,7 +1827,7 @@ void UiParticleEmitterComponent::ResetParticleBuffers() const int verticesPerParticle = 4; int baseIndex = 0; - for (int i = 0; i < numIndices; i += indicesPerParticle) + for (AZ::u32 i = 0; i < numIndices; i += indicesPerParticle) { m_cachedPrimitive.m_indices[i + 0] = 0 + baseIndex; m_cachedPrimitive.m_indices[i + 1] = 1 + baseIndex; diff --git a/Gems/LyShine/Code/Source/UiTextComponent.cpp b/Gems/LyShine/Code/Source/UiTextComponent.cpp index d95b15622b..87eb4524a2 100644 --- a/Gems/LyShine/Code/Source/UiTextComponent.cpp +++ b/Gems/LyShine/Code/Source/UiTextComponent.cpp @@ -3527,7 +3527,7 @@ UiTextComponent::FontEffectComboBoxVec UiTextComponent::PopulateFontEffectList() if (m_font) { unsigned int numEffects = m_font->GetNumEffects(); - for (int i = 0; i < numEffects; ++i) + for (unsigned int i = 0; i < numEffects; ++i) { const char* name = m_font->GetEffectName(i); result.push_back(AZStd::make_pair(i, name)); diff --git a/Gems/PhysXDebug/Code/Source/SystemComponent.cpp b/Gems/PhysXDebug/Code/Source/SystemComponent.cpp index 7e1c3630cb..992a2a3697 100644 --- a/Gems/PhysXDebug/Code/Source/SystemComponent.cpp +++ b/Gems/PhysXDebug/Code/Source/SystemComponent.cpp @@ -697,7 +697,7 @@ namespace PhysXDebug if (GetCurrentPxScene()) { // Reserve vector capacity - const int numTriangles = rb.getNbTriangles(); + const physx::PxU32 numTriangles = static_cast(rb.getNbTriangles()); m_trianglePoints.reserve(numTriangles * 3); m_triangleColors.reserve(numTriangles * 3); @@ -731,7 +731,7 @@ namespace PhysXDebug if (GetCurrentPxScene()) { - const int numLines = rb.getNbLines(); + const physx::PxU32 numLines = static_cast(rb.getNbLines()); // Reserve vector capacity m_linePoints.reserve(numLines * 2); From eb3e0b0998463b52e877ab4d2dd63d3c72dfe1b6 Mon Sep 17 00:00:00 2001 From: pappeste Date: Thu, 24 Jun 2021 18:40:11 -0700 Subject: [PATCH 153/803] updates after merging development Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../Tests/Prefab/Benchmark/SpawnableCreateBenchmarks.cpp | 2 +- .../SceneBuilder/Importers/AssImpAnimationImporter.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Code/Framework/AzToolsFramework/Tests/Prefab/Benchmark/SpawnableCreateBenchmarks.cpp b/Code/Framework/AzToolsFramework/Tests/Prefab/Benchmark/SpawnableCreateBenchmarks.cpp index 9d35081895..54e53a6ebc 100644 --- a/Code/Framework/AzToolsFramework/Tests/Prefab/Benchmark/SpawnableCreateBenchmarks.cpp +++ b/Code/Framework/AzToolsFramework/Tests/Prefab/Benchmark/SpawnableCreateBenchmarks.cpp @@ -33,7 +33,7 @@ namespace Benchmark AZStd::vector> spawnables; spawnables.reserve(numSpawnables); - for (int spwanableCounter = 0; spwanableCounter < numSpawnables; ++spwanableCounter) + for (unsigned int spwanableCounter = 0; spwanableCounter < numSpawnables; ++spwanableCounter) { AZStd::unique_ptr spawnable = AZStd::make_unique(); AzToolsFramework::Prefab::SpawnableUtils::CreateSpawnable(*spawnable, prefabDom); diff --git a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpAnimationImporter.cpp b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpAnimationImporter.cpp index da1db22d5e..150a50138e 100644 --- a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpAnimationImporter.cpp +++ b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpAnimationImporter.cpp @@ -445,11 +445,11 @@ namespace AZ AZStd::unordered_set boneList; - for (int meshIndex = 0; meshIndex < scene->mNumMeshes; ++meshIndex) + for (unsigned int meshIndex = 0; meshIndex < scene->mNumMeshes; ++meshIndex) { aiMesh* mesh = scene->mMeshes[meshIndex]; - for (int boneIndex = 0; boneIndex < mesh->mNumBones; ++boneIndex) + for (unsigned int boneIndex = 0; boneIndex < mesh->mNumBones; ++boneIndex) { aiBone* bone = mesh->mBones[boneIndex]; From 9f18b6f1be67a6cfadce79047d8a8d77e8adaa74 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Thu, 5 Aug 2021 19:58:46 -0700 Subject: [PATCH 154/803] fixes for new code Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../SceneBuilder/Importers/AssImpImporterUtilities.cpp | 4 ++-- Gems/LyShine/Code/Editor/Animation/UiAVEventsDialog.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpImporterUtilities.cpp b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpImporterUtilities.cpp index 81feff7d69..861d6dd85c 100644 --- a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpImporterUtilities.cpp +++ b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpImporterUtilities.cpp @@ -105,7 +105,7 @@ namespace AZ nodesWithNoMesh.emplace(currentNode->mName.C_Str()); } - for (int childIndex = 0; childIndex < currentNode->mNumChildren; ++childIndex) + for (unsigned int childIndex = 0; childIndex < currentNode->mNumChildren; ++childIndex) { queue.push(currentNode->mChildren[childIndex]); } @@ -176,7 +176,7 @@ namespace AZ return true; } - for (int childIndex = 0; childIndex < node->mNumChildren; ++childIndex) + for (unsigned int childIndex = 0; childIndex < node->mNumChildren; ++childIndex) { const aiNode* childNode = node->mChildren[childIndex]; if (RecursiveHasChildBone(childNode, boneByNameMap)) diff --git a/Gems/LyShine/Code/Editor/Animation/UiAVEventsDialog.cpp b/Gems/LyShine/Code/Editor/Animation/UiAVEventsDialog.cpp index e9f5d04314..b45cee6948 100644 --- a/Gems/LyShine/Code/Editor/Animation/UiAVEventsDialog.cpp +++ b/Gems/LyShine/Code/Editor/Animation/UiAVEventsDialog.cpp @@ -352,7 +352,7 @@ int UiAVEventsModel::GetNumberOfUsageAndFirstTimeUsed(const char* eventName, flo { CUiAnimViewTrack* pTrack = tracks.GetTrack(currentTrack); - for (int currentKey = 0; currentKey < pTrack->GetKeyCount(); ++currentKey) + for (unsigned int currentKey = 0; currentKey < pTrack->GetKeyCount(); ++currentKey) { CUiAnimViewKeyHandle keyHandle = pTrack->GetKey(currentKey); From 1c181af94e0c3dc637efca8822cb9dbb5f22b11d Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Thu, 5 Aug 2021 22:36:43 -0500 Subject: [PATCH 155/803] fixing problems with document tab management Signed-off-by: Guthrie Adams --- .../Window/AtomToolsMainWindow.h | 8 +- .../Source/Window/AtomToolsMainWindow.cpp | 32 ++++- .../Source/Window/MaterialEditorWindow.cpp | 113 +++++----------- .../Code/Source/Window/MaterialEditorWindow.h | 2 - .../Window/ShaderManagementConsoleWindow.cpp | 123 ++++++------------ .../Window/ShaderManagementConsoleWindow.h | 6 +- 6 files changed, 106 insertions(+), 178 deletions(-) diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindow.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindow.h index 141fa1cad2..82444246fd 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindow.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindow.h @@ -39,11 +39,13 @@ namespace AtomToolsFramework AZStd::vector GetDockWidgetNames() const override; virtual void CreateMenu(); - virtual void CreateTabBar(); - virtual void AddTabForDocumentId(const AZ::Uuid& documentId); + + virtual void AddTabForDocumentId( + const AZ::Uuid& documentId, const AZStd::string& label, const AZStd::string& toolTip, AZStd::function widgetCreator); virtual void RemoveTabForDocumentId(const AZ::Uuid& documentId); - virtual void UpdateTabForDocumentId(const AZ::Uuid& documentId); + virtual void UpdateTabForDocumentId( + const AZ::Uuid& documentId, const AZStd::string& label, const AZStd::string& toolTip, bool isModified); virtual AZ::Uuid GetDocumentIdFromTab(const int tabIndex) const; virtual void OpenTabContextMenu(); diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp index af4c3571e7..f6e56b1ff6 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp @@ -133,7 +133,8 @@ namespace AtomToolsFramework }); } - void AtomToolsMainWindow::AddTabForDocumentId(const AZ::Uuid& documentId) + void AtomToolsMainWindow::AddTabForDocumentId( + const AZ::Uuid& documentId, const AZStd::string& label, const AZStd::string& toolTip, AZStd::function widgetCreator) { // Blocking signals from the tab bar so the currentChanged signal is not sent while a document is already being opened. // This prevents the OnDocumentOpened notification from being sent recursively. @@ -149,6 +150,16 @@ namespace AtomToolsFramework return; } } + + const int tabIndex = m_tabWidget->addTab(widgetCreator(), label.c_str()); + + // The user can manually reorder tabs which will invalidate any association by index. + // We need to store the document ID with the tab using the tab instead of a separate mapping. + m_tabWidget->tabBar()->setTabData(tabIndex, QVariant(documentId.ToString())); + m_tabWidget->setTabToolTip(tabIndex, toolTip.c_str()); + m_tabWidget->setCurrentIndex(tabIndex); + m_tabWidget->setVisible(true); + m_tabWidget->repaint(); } void AtomToolsMainWindow::RemoveTabForDocumentId(const AZ::Uuid& documentId) @@ -167,12 +178,27 @@ namespace AtomToolsFramework } } - void AtomToolsMainWindow::UpdateTabForDocumentId(const AZ::Uuid& documentId) + void AtomToolsMainWindow::UpdateTabForDocumentId( + const AZ::Uuid& documentId, const AZStd::string& label, const AZStd::string& toolTip, bool isModified) { // Whenever a document is opened, saved, or modified we need to update the tab label if (!documentId.IsNull()) { - return; + // Because tab order and indexes can change from user interactions, we cannot store a map + // between a tab index and document ID. + // We must iterate over all of the tabs to find the one associated with this document. + for (int tabIndex = 0; tabIndex < m_tabWidget->count(); ++tabIndex) + { + if (documentId == GetDocumentIdFromTab(tabIndex)) + { + // We use an asterisk appended to the file name to denote modified document + const AZStd::string modifiedLabel = isModified ? label + " *" : label; + m_tabWidget->setTabText(tabIndex, modifiedLabel.c_str()); + m_tabWidget->setTabToolTip(tabIndex, toolTip.c_str()); + m_tabWidget->repaint(); + break; + } + } } } diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp index f93edfd275..9ead0d4a50 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp @@ -183,14 +183,31 @@ namespace MaterialEditor MaterialDocumentRequestBus::EventResult(isOpen, documentId, &MaterialDocumentRequestBus::Events::IsOpen); bool isSavable = false; MaterialDocumentRequestBus::EventResult(isSavable, documentId, &MaterialDocumentRequestBus::Events::IsSavable); + bool isModified = false; + MaterialDocumentRequestBus::EventResult(isModified, documentId, &MaterialDocumentRequestBus::Events::IsModified); bool canUndo = false; MaterialDocumentRequestBus::EventResult(canUndo, documentId, &MaterialDocumentRequestBus::Events::CanUndo); bool canRedo = false; MaterialDocumentRequestBus::EventResult(canRedo, documentId, &MaterialDocumentRequestBus::Events::CanRedo); + AZStd::string absolutePath; + MaterialDocumentRequestBus::EventResult(absolutePath, documentId, &MaterialDocumentRequestBus::Events::GetAbsolutePath); + AZStd::string filename; + AzFramework::StringFunc::Path::GetFullFileName(absolutePath.c_str(), filename); // Update UI to display the new document - AddTabForDocumentId(documentId); - UpdateTabForDocumentId(documentId); + if (!documentId.IsNull() && isOpen) + { + // Create a new tab for the document ID and assign it's label to the file name of the document. + AddTabForDocumentId(documentId, filename, absolutePath, [this]{ + // The tab widget requires a dummy page per tab + auto contentWidget = new QWidget(m_centralWidget); + contentWidget->setContentsMargins(0, 0, 0, 0); + contentWidget->setFixedSize(0, 0); + return contentWidget; + }); + } + + UpdateTabForDocumentId(documentId, filename, absolutePath, isModified); const bool hasTabs = m_tabWidget->count() > 0; @@ -246,7 +263,13 @@ namespace MaterialEditor void MaterialEditorWindow::OnDocumentModified(const AZ::Uuid& documentId) { - UpdateTabForDocumentId(documentId); + bool isModified = false; + MaterialDocumentRequestBus::EventResult(isModified, documentId, &MaterialDocumentRequestBus::Events::IsModified); + AZStd::string absolutePath; + MaterialDocumentRequestBus::EventResult(absolutePath, documentId, &MaterialDocumentRequestBus::Events::GetAbsolutePath); + AZStd::string filename; + AzFramework::StringFunc::Path::GetFullFileName(absolutePath.c_str(), filename); + UpdateTabForDocumentId(documentId, filename, absolutePath, isModified); } void MaterialEditorWindow::OnDocumentUndoStateChanged(const AZ::Uuid& documentId) @@ -264,7 +287,13 @@ namespace MaterialEditor void MaterialEditorWindow::OnDocumentSaved(const AZ::Uuid& documentId) { - UpdateTabForDocumentId(documentId); + bool isModified = false; + MaterialDocumentRequestBus::EventResult(isModified, documentId, &MaterialDocumentRequestBus::Events::IsModified); + AZStd::string absolutePath; + MaterialDocumentRequestBus::EventResult(absolutePath, documentId, &MaterialDocumentRequestBus::Events::GetAbsolutePath); + AZStd::string filename; + AzFramework::StringFunc::Path::GetFullFileName(absolutePath.c_str(), filename); + UpdateTabForDocumentId(documentId, filename, absolutePath, isModified); const QString documentPath = GetDocumentPath(documentId); const QString status = QString("Material closed: %1").arg(documentPath); @@ -490,82 +519,6 @@ namespace MaterialEditor }); } - void MaterialEditorWindow::AddTabForDocumentId(const AZ::Uuid& documentId) - { - bool isOpen = false; - MaterialDocumentRequestBus::EventResult(isOpen, documentId, &MaterialDocumentRequestBus::Events::IsOpen); - - if (documentId.IsNull() || !isOpen) - { - return; - } - - AtomToolsMainWindow::AddTabForDocumentId(documentId); - - // Blocking signals from the tab bar so the currentChanged signal is not sent while a document is already being opened. - // This prevents the OnDocumentOpened notification from being sent recursively. - const QSignalBlocker blocker(m_tabWidget); - - // Create a new tab for the document ID and assign it's label to the file name of the document. - AZStd::string absolutePath; - MaterialDocumentRequestBus::EventResult(absolutePath, documentId, &MaterialDocumentRequestBus::Events::GetAbsolutePath); - - AZStd::string filename; - AzFramework::StringFunc::Path::GetFullFileName(absolutePath.c_str(), filename); - - // The tab widget requires a dummy page per tab - QWidget* placeHolderWidget = new QWidget(m_centralWidget); - placeHolderWidget->setContentsMargins(0, 0, 0, 0); - placeHolderWidget->resize(0, 0); - placeHolderWidget->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - - const int tabIndex = m_tabWidget->addTab(placeHolderWidget, filename.c_str()); - - // The user can manually reorder tabs which will invalidate any association by index. - // We need to store the document ID with the tab using the tab instead of a separate mapping. - m_tabWidget->tabBar()->setTabData(tabIndex, QVariant(documentId.ToString())); - m_tabWidget->setTabToolTip(tabIndex, absolutePath.c_str()); - m_tabWidget->setCurrentIndex(tabIndex); - m_tabWidget->setVisible(true); - m_tabWidget->repaint(); - } - - void MaterialEditorWindow::UpdateTabForDocumentId(const AZ::Uuid& documentId) - { - // Whenever a document is opened, saved, or modified we need to update the tab label - if (!documentId.IsNull()) - { - // Because tab order and indexes can change from user interactions, we cannot store a map - // between a tab index and document ID. - // We must iterate over all of the tabs to find the one associated with this document. - for (int tabIndex = 0; tabIndex < m_tabWidget->count(); ++tabIndex) - { - if (documentId == GetDocumentIdFromTab(tabIndex)) - { - AZStd::string absolutePath; - MaterialDocumentRequestBus::EventResult(absolutePath, documentId, &MaterialDocumentRequestBus::Events::GetAbsolutePath); - - AZStd::string filename; - AzFramework::StringFunc::Path::GetFullFileName(absolutePath.c_str(), filename); - - bool isModified = false; - MaterialDocumentRequestBus::EventResult(isModified, documentId, &MaterialDocumentRequestBus::Events::IsModified); - - // We use an asterisk appended to the file name to denote modified document - if (isModified) - { - filename += " *"; - } - - m_tabWidget->setTabText(tabIndex, filename.c_str()); - m_tabWidget->setTabToolTip(tabIndex, absolutePath.c_str()); - m_tabWidget->repaint(); - break; - } - } - } - } - QString MaterialEditorWindow::GetDocumentPath(const AZ::Uuid& documentId) const { AZStd::string absolutePath; diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.h index 9a713426ea..43151b9c03 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.h @@ -56,8 +56,6 @@ namespace MaterialEditor void CreateMenu() override; void CreateTabBar() override; - void AddTabForDocumentId(const AZ::Uuid& documentId) override; - void UpdateTabForDocumentId(const AZ::Uuid& documentId) override; QString GetDocumentPath(const AZ::Uuid& documentId) const; void OpenTabContextMenu() override; diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp index 2cc4e67ba0..0a082f3c33 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp @@ -86,14 +86,32 @@ namespace ShaderManagementConsole ShaderManagementConsoleDocumentRequestBus::EventResult(isOpen, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::IsOpen); bool isSavable = false; ShaderManagementConsoleDocumentRequestBus::EventResult(isSavable, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::IsSavable); + bool isModified = false; + ShaderManagementConsoleDocumentRequestBus::EventResult(isModified, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::IsModified); bool canUndo = false; ShaderManagementConsoleDocumentRequestBus::EventResult(canUndo, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::CanUndo); bool canRedo = false; ShaderManagementConsoleDocumentRequestBus::EventResult(canRedo, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::CanRedo); + AZStd::string absolutePath; + ShaderManagementConsoleDocumentRequestBus::EventResult(absolutePath, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::GetAbsolutePath); + AZStd::string filename; + AzFramework::StringFunc::Path::GetFullFileName(absolutePath.c_str(), filename); // Update UI to display the new document - AddTabForDocumentId(documentId); - UpdateTabForDocumentId(documentId); + if (!documentId.IsNull() && isOpen) + { + // Create a new tab for the document ID and assign it's label to the file name of the document. + AddTabForDocumentId(documentId, filename, absolutePath, [this, documentId]{ + // The document tab contains a table view. + auto contentWidget = new QTableView(m_centralWidget); + contentWidget->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + contentWidget->setSelectionBehavior(QAbstractItemView::SelectRows); + contentWidget->setModel(CreateDocumentContent(documentId)); + return contentWidget; + }); + } + + UpdateTabForDocumentId(documentId, filename, absolutePath, isModified); const bool hasTabs = m_tabWidget->count() > 0; @@ -133,7 +151,13 @@ namespace ShaderManagementConsole void ShaderManagementConsoleWindow::OnDocumentModified(const AZ::Uuid& documentId) { - UpdateTabForDocumentId(documentId); + bool isModified = false; + ShaderManagementConsoleDocumentRequestBus::EventResult(isModified, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::IsModified); + AZStd::string absolutePath; + ShaderManagementConsoleDocumentRequestBus::EventResult(absolutePath, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::GetAbsolutePath); + AZStd::string filename; + AzFramework::StringFunc::Path::GetFullFileName(absolutePath.c_str(), filename); + UpdateTabForDocumentId(documentId, filename, absolutePath, isModified); } void ShaderManagementConsoleWindow::OnDocumentUndoStateChanged(const AZ::Uuid& documentId) @@ -151,7 +175,13 @@ namespace ShaderManagementConsole void ShaderManagementConsoleWindow::OnDocumentSaved(const AZ::Uuid& documentId) { - UpdateTabForDocumentId(documentId); + bool isModified = false; + ShaderManagementConsoleDocumentRequestBus::EventResult(isModified, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::IsModified); + AZStd::string absolutePath; + ShaderManagementConsoleDocumentRequestBus::EventResult(absolutePath, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::GetAbsolutePath); + AZStd::string filename; + AzFramework::StringFunc::Path::GetFullFileName(absolutePath.c_str(), filename); + UpdateTabForDocumentId(documentId, filename, absolutePath, isModified); } void ShaderManagementConsoleWindow::CreateMenu() @@ -291,86 +321,6 @@ namespace ShaderManagementConsole }); } - void ShaderManagementConsoleWindow::AddTabForDocumentId(const AZ::Uuid& documentId) - { - bool isOpen = false; - ShaderManagementConsoleDocumentRequestBus::EventResult(isOpen, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::IsOpen); - - if (documentId.IsNull() || !isOpen) - { - return; - } - - AtomToolsMainWindow::AddTabForDocumentId(documentId); - - // Blocking signals from the tab bar so the currentChanged signal is not sent while a document is already being opened. - // This prevents the OnDocumentOpened notification from being sent recursively. - const QSignalBlocker blocker(m_tabWidget); - - // Create a new tab for the document ID and assign it's label to the file name of the document. - AZStd::string absolutePath; - ShaderManagementConsoleDocumentRequestBus::EventResult(absolutePath, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::GetAbsolutePath); - - AZStd::string filename; - AzFramework::StringFunc::Path::GetFullFileName(absolutePath.c_str(), filename); - - // The document tab contains a table view. - auto tableView = new QTableView(m_centralWidget); - tableView->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - tableView->setSelectionBehavior(QAbstractItemView::SelectRows); - - auto model = new QStandardItemModel(); - tableView->setModel(model); - - const int tabIndex = m_tabWidget->addTab(tableView, filename.c_str()); - - // The user can manually reorder tabs which will invalidate any association by index. - // We need to store the document ID with the tab using the tab instead of a separate mapping. - m_tabWidget->tabBar()->setTabData(tabIndex, QVariant(documentId.ToString())); - m_tabWidget->setTabToolTip(tabIndex, absolutePath.c_str()); - m_tabWidget->setCurrentIndex(tabIndex); - m_tabWidget->setVisible(true); - m_tabWidget->repaint(); - - CreateDocumentContent(documentId, model); - } - - void ShaderManagementConsoleWindow::UpdateTabForDocumentId(const AZ::Uuid& documentId) - { - // Whenever a document is opened, saved, or modified we need to update the tab label - if (!documentId.IsNull()) - { - // Because tab order and indexes can change from user interactions, we cannot store a map - // between a tab index and document ID. - // We must iterate over all of the tabs to find the one associated with this document. - for (int tabIndex = 0; tabIndex < m_tabWidget->count(); ++tabIndex) - { - if (documentId == GetDocumentIdFromTab(tabIndex)) - { - AZStd::string absolutePath; - ShaderManagementConsoleDocumentRequestBus::EventResult(absolutePath, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::GetAbsolutePath); - - AZStd::string filename; - AzFramework::StringFunc::Path::GetFullFileName(absolutePath.c_str(), filename); - - bool isModified = false; - ShaderManagementConsoleDocumentRequestBus::EventResult(isModified, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::IsModified); - - // We use an asterisk appended to the file name to denote modified document - if (isModified) - { - filename += " *"; - } - - m_tabWidget->setTabText(tabIndex, filename.c_str()); - m_tabWidget->setTabToolTip(tabIndex, absolutePath.c_str()); - m_tabWidget->repaint(); - break; - } - } - } - } - void ShaderManagementConsoleWindow::OpenTabContextMenu() { const QTabBar* tabBar = m_tabWidget->tabBar(); @@ -427,7 +377,7 @@ namespace ShaderManagementConsole } } - void ShaderManagementConsoleWindow::CreateDocumentContent(const AZ::Uuid& documentId, QStandardItemModel* model) + QStandardItemModel* ShaderManagementConsoleWindow::CreateDocumentContent(const AZ::Uuid& documentId) { AZStd::unordered_set optionNames; @@ -446,6 +396,7 @@ namespace ShaderManagementConsole size_t shaderVariantCount = 0; ShaderManagementConsoleDocumentRequestBus::EventResult(shaderVariantCount, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::GetShaderVariantCount); + auto model = new QStandardItemModel(); model->setRowCount(static_cast(shaderVariantCount)); model->setColumnCount(static_cast(optionNames.size())); @@ -474,6 +425,8 @@ namespace ShaderManagementConsole model->setItem(variantIndex, optionIndex, item); } } + + return model; } } // namespace ShaderManagementConsole diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.h b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.h index 57bd11cb0a..aae31d1000 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.h +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.h @@ -52,10 +52,6 @@ namespace ShaderManagementConsole void CreateMenu() override; void CreateTabBar() override; - - void AddTabForDocumentId(const AZ::Uuid& documentId) override; - void UpdateTabForDocumentId(const AZ::Uuid& documentId) override; - void OpenTabContextMenu() override; void SelectDocumentForTab(const int tabIndex); @@ -64,7 +60,7 @@ namespace ShaderManagementConsole void closeEvent(QCloseEvent* closeEvent) override; - void CreateDocumentContent(const AZ::Uuid& documentId, QStandardItemModel* model); + QStandardItemModel* CreateDocumentContent(const AZ::Uuid& documentId); ShaderManagementConsoleToolBar* m_toolBar = nullptr; From c85e5a688668da4e2c1a4aff6564a0ca8d5fded1 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Thu, 5 Aug 2021 21:49:00 -0700 Subject: [PATCH 156/803] Some more build fixes Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../Platform/Android/GridMate/Carrier/Utils_Android.cpp | 4 ++-- .../Platform/Linux/GridMate/Session/LANSession_Linux.cpp | 2 ++ .../GridMate/Platform/Mac/GridMate/Session/LANSession_Mac.cpp | 2 ++ Code/Legacy/CrySystem/LocalizedStringManager.cpp | 4 ++-- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Code/Framework/GridMate/Platform/Android/GridMate/Carrier/Utils_Android.cpp b/Code/Framework/GridMate/Platform/Android/GridMate/Carrier/Utils_Android.cpp index 87bb0c3cda..f48e2c2da8 100644 --- a/Code/Framework/GridMate/Platform/Android/GridMate/Carrier/Utils_Android.cpp +++ b/Code/Framework/GridMate/Platform/Android/GridMate/Carrier/Utils_Android.cpp @@ -18,9 +18,9 @@ namespace GridMate { - string Utils::GetMachineAddress(int familyType) + AZStd::string Utils::GetMachineAddress(int familyType) { - string machineName; + AZStd::string machineName; struct RTMRequest { nlmsghdr m_msghdr; diff --git a/Code/Framework/GridMate/Platform/Linux/GridMate/Session/LANSession_Linux.cpp b/Code/Framework/GridMate/Platform/Linux/GridMate/Session/LANSession_Linux.cpp index 05fb56dfc1..ac887bb624 100644 --- a/Code/Framework/GridMate/Platform/Linux/GridMate/Session/LANSession_Linux.cpp +++ b/Code/Framework/GridMate/Platform/Linux/GridMate/Session/LANSession_Linux.cpp @@ -8,6 +8,8 @@ #include +#include + namespace GridMate { namespace Platform diff --git a/Code/Framework/GridMate/Platform/Mac/GridMate/Session/LANSession_Mac.cpp b/Code/Framework/GridMate/Platform/Mac/GridMate/Session/LANSession_Mac.cpp index 05fb56dfc1..ac887bb624 100644 --- a/Code/Framework/GridMate/Platform/Mac/GridMate/Session/LANSession_Mac.cpp +++ b/Code/Framework/GridMate/Platform/Mac/GridMate/Session/LANSession_Mac.cpp @@ -8,6 +8,8 @@ #include +#include + namespace GridMate { namespace Platform diff --git a/Code/Legacy/CrySystem/LocalizedStringManager.cpp b/Code/Legacy/CrySystem/LocalizedStringManager.cpp index 6013b44f92..68a8a6659b 100644 --- a/Code/Legacy/CrySystem/LocalizedStringManager.cpp +++ b/Code/Legacy/CrySystem/LocalizedStringManager.cpp @@ -2337,8 +2337,8 @@ void InternalFormatStringMessage(AZStd::string& outString, const AZStd::string& static const char tokens2[3] = { token, token, '\0' }; int maxArgUsed = 0; - int lastPos = 0; - int curPos = 0; + size_t lastPos = 0; + size_t curPos = 0; const int sourceLen = static_cast(sString.length()); while (true) { From f2c482b03dc672c20d59f3b77524e1c107263d92 Mon Sep 17 00:00:00 2001 From: Nemerle Date: Fri, 6 Aug 2021 13:02:23 +0200 Subject: [PATCH 157/803] Fixes for incorrect nullptr placement. Incorrect DataElement overload getting called in AndroidSplashscreens::Reflect Signed-off-by: Nemerle --- Code/Editor/Lib/Tests/test_Main.cpp | 2 +- .../Plugins/ProjectSettingsTool/PlatformSettings_Android.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Code/Editor/Lib/Tests/test_Main.cpp b/Code/Editor/Lib/Tests/test_Main.cpp index 4faf68181e..6250c540db 100644 --- a/Code/Editor/Lib/Tests/test_Main.cpp +++ b/Code/Editor/Lib/Tests/test_Main.cpp @@ -17,7 +17,7 @@ class EditorLibTestEnvironment : public AZ::Test::ITestEnvironment { public: - ~EditorLibTestEnvironment() override {} + ~EditorLibTestEnvironment() override = default; protected: void SetupEnvironment() override diff --git a/Code/Editor/Plugins/ProjectSettingsTool/PlatformSettings_Android.cpp b/Code/Editor/Plugins/ProjectSettingsTool/PlatformSettings_Android.cpp index fe73253805..ea65cf3e59 100644 --- a/Code/Editor/Plugins/ProjectSettingsTool/PlatformSettings_Android.cpp +++ b/Code/Editor/Plugins/ProjectSettingsTool/PlatformSettings_Android.cpp @@ -165,8 +165,8 @@ namespace ProjectSettingsTool if (editContext) { editContext->Class("Splashscreens", "All splashscreen overrides for Android.") - ->DataElement(nullptr, &AndroidSplashscreens::m_landscapeSplashscreens) - ->DataElement(nullptr, &AndroidSplashscreens::m_portraitSplashscreens) + ->DataElement(AZ::Edit::UIHandlers::Default, &AndroidSplashscreens::m_landscapeSplashscreens) + ->DataElement(AZ::Edit::UIHandlers::Default, &AndroidSplashscreens::m_portraitSplashscreens) ; } } From 6e59b1f519ca27c59e61e09dd66152470610c5e0 Mon Sep 17 00:00:00 2001 From: Yuriy Toporovskyy Date: Fri, 6 Aug 2021 10:30:57 -0400 Subject: [PATCH 158/803] Remove include of deleted file Signed-off-by: Yuriy Toporovskyy --- Gems/LyShine/Code/Editor/Animation/AnimationContext.cpp | 1 - Gems/LyShine/Code/Editor/Animation/UiAnimViewAnimNode.cpp | 1 - Gems/LyShine/Code/Editor/Animation/UiAnimViewNodes.cpp | 1 - 3 files changed, 3 deletions(-) diff --git a/Gems/LyShine/Code/Editor/Animation/AnimationContext.cpp b/Gems/LyShine/Code/Editor/Animation/AnimationContext.cpp index ef01ba4d9f..c2c05277a8 100644 --- a/Gems/LyShine/Code/Editor/Animation/AnimationContext.cpp +++ b/Gems/LyShine/Code/Editor/Animation/AnimationContext.cpp @@ -23,7 +23,6 @@ #include "Animation/UiAnimViewDialog.h" #include "Animation/UiAnimViewUndo.h" -#include "RenderViewport.h" #include "Viewport.h" #include "ViewManager.h" diff --git a/Gems/LyShine/Code/Editor/Animation/UiAnimViewAnimNode.cpp b/Gems/LyShine/Code/Editor/Animation/UiAnimViewAnimNode.cpp index f860725276..2b13132606 100644 --- a/Gems/LyShine/Code/Editor/Animation/UiAnimViewAnimNode.cpp +++ b/Gems/LyShine/Code/Editor/Animation/UiAnimViewAnimNode.cpp @@ -18,7 +18,6 @@ #include "UiAnimViewSequenceManager.h" #include "Objects/EntityObject.h" #include "ViewManager.h" -#include "RenderViewport.h" #include "Clipboard.h" #include diff --git a/Gems/LyShine/Code/Editor/Animation/UiAnimViewNodes.cpp b/Gems/LyShine/Code/Editor/Animation/UiAnimViewNodes.cpp index d930b4b581..136d405465 100644 --- a/Gems/LyShine/Code/Editor/Animation/UiAnimViewNodes.cpp +++ b/Gems/LyShine/Code/Editor/Animation/UiAnimViewNodes.cpp @@ -23,7 +23,6 @@ #include "Objects/EntityObject.h" #include "ViewManager.h" -#include "RenderViewport.h" #include "Export/ExportManager.h" #include From ae9d15c977f1394f5783dd76dadaa407031bbd28 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 6 Aug 2021 09:59:35 -0700 Subject: [PATCH 159/803] Mac/iOS fixes Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../Platform/Mac/AzCore/IPC/SharedMemory_Mac.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Code/Framework/AzCore/Platform/Mac/AzCore/IPC/SharedMemory_Mac.cpp b/Code/Framework/AzCore/Platform/Mac/AzCore/IPC/SharedMemory_Mac.cpp index 5555704040..5b2d2af34f 100644 --- a/Code/Framework/AzCore/Platform/Mac/AzCore/IPC/SharedMemory_Mac.cpp +++ b/Code/Framework/AzCore/Platform/Mac/AzCore/IPC/SharedMemory_Mac.cpp @@ -29,20 +29,19 @@ namespace AZ return errno; } - void ComposeMutexName(char* dest, size_t length, const char* name) + void ComposeName(char* dest, size_t length, const char* name, const char* suffix) { - azstrncpy(m_name, AZ_ARRAY_SIZE(m_name), name, strlen(name)); - // sem_open doesn't support paths bigger than 31, so call it s_Mtx. // While this is enough for Profiler, maybe the code should be smarter // and trim the name instead - azsnprintf(dest, length, "/tmp/%s_Mtx", name); + azsnprintf(dest, length, "/tmp/%s_%s", name, suffix); } SharedMemory_Common::CreateResult SharedMemory_Mac::Create(const char* name, unsigned int size, bool openIfCreated) { char fullName[256]; - ComposeMutexName(fullName, AZ_ARRAY_SIZE(fullName), name); + azstrncpy(m_name, AZ_ARRAY_SIZE(m_name), name, strlen(name)); + ComposeName(fullName, AZ_ARRAY_SIZE(fullName), name, "Mtx"); m_globalMutex = sem_open(fullName, O_CREAT | O_EXCL, 0600, 1); int error = errno; @@ -59,7 +58,7 @@ namespace AZ } // Create the file mapping. - azsnprintf(fullName, AZ_ARRAY_SIZE(fullName), "%s_Data", name); + ComposeName(fullName, AZ_ARRAY_SIZE(fullName), name, "Data"); m_mapHandle = shm_open(fullName, O_RDWR | O_CREAT | O_EXCL, 0600); error = errno; if (error == EEXIST) @@ -80,7 +79,8 @@ namespace AZ bool SharedMemory_Mac::Open(const char* name) { char fullName[256]; - ComposeMutexName(fullName, AZ_ARRAY_SIZE(fullName), name); + azstrncpy(m_name, AZ_ARRAY_SIZE(m_name), name, strlen(name)); + ComposeName(fullName, AZ_ARRAY_SIZE(fullName), name, "Mtx"); m_globalMutex = sem_open(fullName, 0); AZ_Warning("AZSystem", m_globalMutex != nullptr, "Failed to open OS mutex [%s]\n", m_name); @@ -90,7 +90,7 @@ namespace AZ return false; } - azsnprintf(fullName, AZ_ARRAY_SIZE(fullName), "%s_Data", name); + ComposeName(fullName, AZ_ARRAY_SIZE(fullName), name, "Data"); m_mapHandle = shm_open(fullName, O_RDWR, 0600); if (m_mapHandle == -1) { From 8adf8fd7a11309bc4388ab5d63538a1b6d8bfbd9 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 6 Aug 2021 10:00:58 -0700 Subject: [PATCH 160/803] PR comments Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Framework/AzCore/AzCore/std/string/conversions.h | 8 ++++---- .../Platform/Windows/AzCore/IPC/SharedMemory_Windows.cpp | 2 ++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/std/string/conversions.h b/Code/Framework/AzCore/AzCore/std/string/conversions.h index 473c327143..c5c9b29cdb 100644 --- a/Code/Framework/AzCore/AzCore/std/string/conversions.h +++ b/Code/Framework/AzCore/AzCore/std/string/conversions.h @@ -338,9 +338,9 @@ namespace AZStd if (srcLen > 0) { char* endStr = Internal::WCharTPlatformConverter<>::to_string(dest, destSize, str, str + srcLen); - if (endStr < (dest + destSize) && *(endStr - 1) != '\0') + if (endStr < (dest + destSize)) { - *endStr = '\0'; // copy null terminator + *endStr = '\0'; // null terminator } } } @@ -495,9 +495,9 @@ namespace AZStd if (srcLen > 0) { wchar_t* endWStr = Internal::WCharTPlatformConverter<>::to_wstring(dest, destSize, str, str + srcLen); - if (endWStr < (dest + destSize) && *(endWStr - 1) != '\0') + if (endWStr < (dest + destSize)) { - *endWStr = '\0'; // copy null terminator + *endWStr = '\0'; // null terminator } } } diff --git a/Code/Framework/AzCore/Platform/Windows/AzCore/IPC/SharedMemory_Windows.cpp b/Code/Framework/AzCore/Platform/Windows/AzCore/IPC/SharedMemory_Windows.cpp index 20c126f7a8..d9149bdb44 100644 --- a/Code/Framework/AzCore/Platform/Windows/AzCore/IPC/SharedMemory_Windows.cpp +++ b/Code/Framework/AzCore/Platform/Windows/AzCore/IPC/SharedMemory_Windows.cpp @@ -31,6 +31,7 @@ namespace AZ SharedMemory_Common::CreateResult SharedMemory_Windows::Create(const char* name, unsigned int size, bool openIfCreated) { + azstrncpy(m_name, AZ_ARRAY_SIZE(m_name), name, strlen(name)); AZStd::fixed_wstring<256> fullName; ComposeName(fullName, name, L"Mutex"); @@ -67,6 +68,7 @@ namespace AZ bool SharedMemory_Windows::Open(const char* name) { + azstrncpy(m_name, AZ_ARRAY_SIZE(m_name), name, strlen(name)); AZStd::fixed_wstring<256> fullName; ComposeName(fullName, name, L"Mutex"); From 03cf71b12d7322ac15e6dbcf9a00cdaef4e8ecea Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 6 Aug 2021 10:01:20 -0700 Subject: [PATCH 161/803] android fixes Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../Platform/Android/GridMate/Carrier/Utils_Android.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Framework/GridMate/Platform/Android/GridMate/Carrier/Utils_Android.cpp b/Code/Framework/GridMate/Platform/Android/GridMate/Carrier/Utils_Android.cpp index f48e2c2da8..75259fbe64 100644 --- a/Code/Framework/GridMate/Platform/Android/GridMate/Carrier/Utils_Android.cpp +++ b/Code/Framework/GridMate/Platform/Android/GridMate/Carrier/Utils_Android.cpp @@ -67,7 +67,7 @@ namespace GridMate char address[INET6_ADDRSTRLEN] = { 0 }; bool isLoopback = false; - string devname; + AZStd::string devname; for (int rtattrlen = IFA_PAYLOAD(nlmp); RTA_OK(rtatp, rtattrlen); rtatp = RTA_NEXT(rtatp, rtattrlen)) { if (rtatp->rta_type == IFA_ADDRESS) From db942e2cf5b70bcf63992ba5631a8a086d534307 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 6 Aug 2021 10:36:53 -0700 Subject: [PATCH 162/803] addresses PR comments Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Editor/ViewportTitleDlg.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/Code/Editor/ViewportTitleDlg.cpp b/Code/Editor/ViewportTitleDlg.cpp index cbf2958eea..b9c86bf72b 100644 --- a/Code/Editor/ViewportTitleDlg.cpp +++ b/Code/Editor/ViewportTitleDlg.cpp @@ -449,21 +449,21 @@ void CViewportTitleDlg::AddFOVMenus(QMenu* menu, std::function call if (!customPresets.empty()) { - for (size_t i = 0; i < customPresets.size(); ++i) + for (const QString& customPreset : customPresets) { - if (customPresets[static_cast(i)].isEmpty()) + if (customPreset.isEmpty()) { break; } float fov = gSettings.viewports.fDefaultFov; bool ok; - float f = customPresets[static_cast(i)].toDouble(&ok); + float f = customPreset.toDouble(&ok); if (ok) { fov = std::max(1.0f, f); fov = std::min(120.0f, f); - QAction* action = menu->addAction(customPresets[static_cast(i)]); + QAction* action = menu->addAction(customPreset); connect(action, &QAction::triggered, action, [fov, callback](){ callback(fov); }); } } @@ -535,15 +535,15 @@ void CViewportTitleDlg::AddAspectRatioMenus(QMenu* menu, std::functionaddSeparator(); - for (size_t i = 0; i < customPresets.size(); ++i) + for (const QString& customPreset : customPresets) { - if (customPresets[static_cast(i)].isEmpty()) + if (customPreset.isEmpty()) { break; } static QRegularExpression regex(QStringLiteral("^(\\d+):(\\d+)$")); - QRegularExpressionMatch matches = regex.match(customPresets[static_cast(i)]); + QRegularExpressionMatch matches = regex.match(customPreset); if (matches.hasMatch()) { bool ok; @@ -551,7 +551,7 @@ void CViewportTitleDlg::AddAspectRatioMenus(QMenu* menu, std::functionaddAction(customPresets[static_cast(i)]); + QAction* action = menu->addAction(customPreset); connect(action, &QAction::triggered, action, [width, height, callback]() {callback(width, height); }); } } @@ -666,15 +666,15 @@ void CViewportTitleDlg::AddResolutionMenus(QMenu* menu, std::functionaddSeparator(); - for (size_t i = 0; i < customPresets.size(); ++i) + for (const QString& customPreset : customPresets) { - if (customPresets[static_cast(i)].isEmpty()) + if (customPreset.isEmpty()) { break; } static QRegularExpression regex(QStringLiteral("^(\\d+) x (\\d+)$")); - QRegularExpressionMatch matches = regex.match(customPresets[static_cast(i)]); + QRegularExpressionMatch matches = regex.match(customPreset); if (matches.hasMatch()) { bool ok; @@ -682,7 +682,7 @@ void CViewportTitleDlg::AddResolutionMenus(QMenu* menu, std::functionaddAction(customPresets[static_cast(i)]); + QAction* action = menu->addAction(customPreset); connect(action, &QAction::triggered, action, [width, height, callback](){ callback(width, height); }); } } From d7c1185dc23d42e7a535c5977aa1ee568d5f28ab Mon Sep 17 00:00:00 2001 From: John Date: Fri, 6 Aug 2021 20:09:53 +0100 Subject: [PATCH 163/803] Add previously approved changes. Signed-off-by: John --- .../Code/Source/TestImpactConsoleMain.cpp | 89 ++-- ...tImpactConsoleTestSequenceEventHandler.cpp | 145 +++---- ...estImpactConsoleTestSequenceEventHandler.h | 61 +-- .../TestImpactClientFailureReport.h | 125 ------ .../TestImpactClientSequenceReport.h | 240 ++++++++++ .../TestImpactClientTestRun.h | 105 ++++- .../TestImpactClientTestSelection.h | 1 + .../TestImpactFramework/TestImpactRuntime.h | 74 ++-- .../TestEngine/TestImpactTestEngine.cpp | 6 +- .../Source/TestEngine/TestImpactTestEngine.h | 6 +- .../Source/TestImpactClientFailureReport.cpp | 120 ----- .../Source/TestImpactClientSequenceReport.cpp | 312 +++++++++++++ .../Code/Source/TestImpactClientTestRun.cpp | 100 ++++- .../Runtime/Code/Source/TestImpactRuntime.cpp | 409 +++++++++++++----- .../Code/Source/TestImpactRuntimeUtils.cpp | 12 +- .../Code/Source/TestImpactRuntimeUtils.h | 76 ++-- .../testimpactframework_runtime_files.cmake | 5 +- 17 files changed, 1287 insertions(+), 599 deletions(-) delete mode 100644 Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactClientFailureReport.h create mode 100644 Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactClientSequenceReport.h delete mode 100644 Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactClientFailureReport.cpp create mode 100644 Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactClientSequenceReport.cpp diff --git a/Code/Tools/TestImpactFramework/Frontend/Console/Code/Source/TestImpactConsoleMain.cpp b/Code/Tools/TestImpactFramework/Frontend/Console/Code/Source/TestImpactConsoleMain.cpp index 5788da5b2b..8027649a44 100644 --- a/Code/Tools/TestImpactFramework/Frontend/Console/Code/Source/TestImpactConsoleMain.cpp +++ b/Code/Tools/TestImpactFramework/Frontend/Console/Code/Source/TestImpactConsoleMain.cpp @@ -77,7 +77,6 @@ namespace TestImpact //! Wrapper around impact analysis sequences to handle the case where the safe mode option is active. ReturnCode WrappedImpactAnalysisTestSequence( - TestSequenceEventHandler& sequenceEventHandler, const CommandLineOptions& options, Runtime& runtime, const AZStd::optional& changeList) @@ -94,44 +93,30 @@ namespace TestImpact { if (options.GetTestSequenceType() == TestSequenceType::ImpactAnalysis) { - auto [selectedResult, discardedResult] = runtime.SafeImpactAnalysisTestSequence( + auto safeImpactAnalysisSequenceReport = runtime.SafeImpactAnalysisTestSequence( changeList.value(), options.GetTestPrioritizationPolicy(), options.GetTestTargetTimeout(), options.GetGlobalTimeout(), - AZStd::ref(sequenceEventHandler), - AZStd::ref(sequenceEventHandler), - AZStd::ref(sequenceEventHandler)); - - // Handling the possible timeout and failure permutations of the selected and discarded test results is splitting hairs - // so apply the following, admittedly arbitrary, rules to determine what the composite test sequence result should be - if (selectedResult == TestSequenceResult::Success && discardedResult == TestSequenceResult::Success) - { - // Trivial case: both sequences succeeded - result = TestSequenceResult::Success; - } - else if (selectedResult == TestSequenceResult::Failure || discardedResult == TestSequenceResult::Failure) - { - // One sequence failed whilst the other sequence either succeeded or timed out - result = TestSequenceResult::Failure; - } - else - { - // One or both sequences timed out or failed - result = TestSequenceResult::Timeout; - } + SafeImpactAnalysisTestSequenceStartCallback, + SafeImpactAnalysisTestSequenceCompleteCallback, + TestRunCompleteCallback); + + result = safeImpactAnalysisSequenceReport.GetResult(); } else if (options.GetTestSequenceType() == TestSequenceType::ImpactAnalysisNoWrite) { // A no-write impact analysis sequence with safe mode enabled is functionally identical to a regular sequence type // due to a) the selected tests being run without instrumentation and b) the discarded tests also being run without // instrumentation - result = runtime.RegularTestSequence( + auto sequenceReport = runtime.RegularTestSequence( options.GetTestTargetTimeout(), options.GetGlobalTimeout(), - AZStd::ref(sequenceEventHandler), - AZStd::ref(sequenceEventHandler), - AZStd::ref(sequenceEventHandler)); + TestSequenceStartCallback, + TestSequenceCompleteCallback, + TestRunCompleteCallback); + + result = sequenceReport.GetResult(); } else { @@ -153,18 +138,20 @@ namespace TestImpact { throw(Exception("Unexpected sequence type")); } - - result = runtime.ImpactAnalysisTestSequence( + + auto impactAnalysisSequenceReport = runtime.ImpactAnalysisTestSequence( changeList.value(), options.GetTestPrioritizationPolicy(), dynamicDependencyMapPolicy, options.GetTestTargetTimeout(), options.GetGlobalTimeout(), - AZStd::ref(sequenceEventHandler), - AZStd::ref(sequenceEventHandler), - AZStd::ref(sequenceEventHandler)); - } + ImpactAnalysisTestSequenceStartCallback, + ImpactAnalysisTestSequenceCompleteCallback, + TestRunCompleteCallback); + result = impactAnalysisSequenceReport.GetResult(); + } + return GetReturnCodeForTestSequenceResult(result); }; @@ -217,53 +204,51 @@ namespace TestImpact std::cout << "Test impact analysis data for this repository was not found, seed or regular sequence fallbacks will be used.\n"; } - TestSequenceEventHandler sequenceEventHandler(options.GetSuiteFilter()); - switch (const auto type = options.GetTestSequenceType()) { case TestSequenceType::Regular: { - const auto result = runtime.RegularTestSequence( + const auto sequenceReport = runtime.RegularTestSequence( options.GetTestTargetTimeout(), options.GetGlobalTimeout(), - AZStd::ref(sequenceEventHandler), - AZStd::ref(sequenceEventHandler), - AZStd::ref(sequenceEventHandler)); + TestSequenceStartCallback, + TestSequenceCompleteCallback, + TestRunCompleteCallback); - return GetReturnCodeForTestSequenceResult(result); + return GetReturnCodeForTestSequenceResult(sequenceReport.GetResult()); } case TestSequenceType::Seed: { - const auto result = runtime.SeededTestSequence( + const auto sequenceReport = runtime.SeededTestSequence( options.GetTestTargetTimeout(), options.GetGlobalTimeout(), - AZStd::ref(sequenceEventHandler), - AZStd::ref(sequenceEventHandler), - AZStd::ref(sequenceEventHandler)); + TestSequenceStartCallback, + TestSequenceCompleteCallback, + TestRunCompleteCallback); - return GetReturnCodeForTestSequenceResult(result); + return GetReturnCodeForTestSequenceResult(sequenceReport.GetResult()); } case TestSequenceType::ImpactAnalysisNoWrite: case TestSequenceType::ImpactAnalysis: { - return WrappedImpactAnalysisTestSequence(sequenceEventHandler, options, runtime, changeList); + return WrappedImpactAnalysisTestSequence(options, runtime, changeList); } case TestSequenceType::ImpactAnalysisOrSeed: { if (runtime.HasImpactAnalysisData()) { - return WrappedImpactAnalysisTestSequence(sequenceEventHandler, options, runtime, changeList); + return WrappedImpactAnalysisTestSequence(options, runtime, changeList); } else { - const auto result = runtime.SeededTestSequence( + const auto sequenceReport = runtime.SeededTestSequence( options.GetTestTargetTimeout(), options.GetGlobalTimeout(), - AZStd::ref(sequenceEventHandler), - AZStd::ref(sequenceEventHandler), - AZStd::ref(sequenceEventHandler)); + TestSequenceStartCallback, + TestSequenceCompleteCallback, + TestRunCompleteCallback); - return GetReturnCodeForTestSequenceResult(result); + return GetReturnCodeForTestSequenceResult(sequenceReport.GetResult()); } } default: diff --git a/Code/Tools/TestImpactFramework/Frontend/Console/Code/Source/TestImpactConsoleTestSequenceEventHandler.cpp b/Code/Tools/TestImpactFramework/Frontend/Console/Code/Source/TestImpactConsoleTestSequenceEventHandler.cpp index dc29b2580c..da7052933c 100644 --- a/Code/Tools/TestImpactFramework/Frontend/Console/Code/Source/TestImpactConsoleTestSequenceEventHandler.cpp +++ b/Code/Tools/TestImpactFramework/Frontend/Console/Code/Source/TestImpactConsoleTestSequenceEventHandler.cpp @@ -32,72 +32,73 @@ namespace TestImpact std::cout << "Of which " << numExcludedTests << " tests have been excluded and " << numDraftedTests << " tests have been drafted.\n"; } - void FailureReport(const Client::SequenceFailure& failureReport, AZStd::chrono::milliseconds duration) + void FailureReport(const Client::TestRunReport& testRunReport) { - std::cout << "Sequence completed in " << (duration.count() / 1000.f) << "s with"; + std::cout << "Sequence completed in " << (testRunReport.GetDuration().count() / 1000.f) << "s with"; - if (!failureReport.GetExecutionFailures().empty() || - !failureReport.GetTestRunFailures().empty() || - !failureReport.GetTimedOutTests().empty() || - !failureReport.GetUnexecutedTests().empty()) + if (!testRunReport.GetExecutionFailureTests().empty() || + !testRunReport.GetFailingTests().empty() || + !testRunReport.GetTimedOutTests().empty() || + !testRunReport.GetUnexecutedTests().empty()) { std::cout << ":\n"; std::cout << SetColor(Foreground::White, Background::Red).c_str() - << failureReport.GetTestRunFailures().size() + << testRunReport.GetFailingTests().size() << ResetColor().c_str() << " test failures\n"; std::cout << SetColor(Foreground::White, Background::Red).c_str() - << failureReport.GetExecutionFailures().size() + << testRunReport.GetExecutionFailureTests().size() << ResetColor().c_str() << " execution failures\n"; std::cout << SetColor(Foreground::White, Background::Red).c_str() - << failureReport.GetTimedOutTests().size() + << testRunReport.GetTimedOutTests().size() << ResetColor().c_str() << " test timeouts\n"; std::cout << SetColor(Foreground::White, Background::Red).c_str() - << failureReport.GetUnexecutedTests().size() + << testRunReport.GetUnexecutedTests().size() << ResetColor().c_str() << " unexecuted tests\n"; - if (!failureReport.GetTestRunFailures().empty()) + if (!testRunReport.GetFailingTests().empty()) { std::cout << "\nTest failures:\n"; - for (const auto& testRunFailure : failureReport.GetTestRunFailures()) + for (const auto& testRunFailure : testRunReport.GetFailingTests()) { - std::cout << " " << testRunFailure.GetTargetName().c_str(); for (const auto& testCaseFailure : testRunFailure.GetTestCaseFailures()) { - std::cout << "." << testCaseFailure.GetName().c_str(); for (const auto& testFailure : testCaseFailure.GetTestFailures()) { - std::cout << "." << testFailure.GetName().c_str() << "\n"; + std::cout << " " + << testRunFailure.GetTargetName().c_str() + << "." << testCaseFailure.GetName().c_str() + << "." << testFailure.GetName().c_str() << "\n"; } } } } - if (!failureReport.GetExecutionFailures().empty()) + if (!testRunReport.GetExecutionFailureTests().empty()) { std::cout << "\nExecution failures:\n"; - for (const auto& executionFailure : failureReport.GetExecutionFailures()) + for (const auto& executionFailure : testRunReport.GetExecutionFailureTests()) { std::cout << " " << executionFailure.GetTargetName().c_str() << "\n"; std::cout << executionFailure.GetCommandString().c_str() << "\n"; } } - if (!failureReport.GetTimedOutTests().empty()) + if (!testRunReport.GetTimedOutTests().empty()) { std::cout << "\nTimed out tests:\n"; - for (const auto& testTimeout : failureReport.GetTimedOutTests()) + for (const auto& testTimeout : testRunReport.GetTimedOutTests()) { std::cout << " " << testTimeout.GetTargetName().c_str() << "\n"; } } - if (!failureReport.GetUnexecutedTests().empty()) + if (!testRunReport.GetUnexecutedTests().empty()) { std::cout << "\nUnexecuted tests:\n"; - for (const auto& unexecutedTest : failureReport.GetUnexecutedTests()) + for (const auto& unexecutedTest : testRunReport.GetUnexecutedTests()) { std::cout << " " << unexecutedTest.GetTargetName().c_str() << "\n"; } @@ -105,50 +106,42 @@ namespace TestImpact } else { - std::cout << SetColor(Foreground::White, Background::Green).c_str() << " \100% passes!\n" << ResetColor().c_str(); + std::cout << SetColor(Foreground::White, Background::Green).c_str() << " \100% passes!\n" << ResetColor().c_str() << "\n"; } } } - TestSequenceEventHandler::TestSequenceEventHandler(SuiteType suiteFilter) - : m_suiteFilter(suiteFilter) + void TestSequenceStartCallback(SuiteType suiteType, const Client::TestRunSelection& selectedTests) { + Output::TestSuiteFilter(suiteType); + std::cout << selectedTests.GetNumIncludedTestRuns() << " tests selected, " << selectedTests.GetNumExcludedTestRuns() + << " excluded.\n"; } - // TestSequenceStartCallback - void TestSequenceEventHandler::operator()(Client::TestRunSelection&& selectedTests) + void TestSequenceCompleteCallback(SuiteType suiteType, const Client::TestRunSelection& selectedTests) { - ClearState(); - m_numTests = selectedTests.GetNumIncludedTestRuns(); - - Output::TestSuiteFilter(m_suiteFilter); + Output::TestSuiteFilter(suiteType); std::cout << selectedTests.GetNumIncludedTestRuns() << " tests selected, " << selectedTests.GetNumExcludedTestRuns() << " excluded.\n"; } - // ImpactAnalysisTestSequenceStartCallback - void TestSequenceEventHandler::operator()( - Client::TestRunSelection&& selectedTests, - AZStd::vector&& discardedTests, - AZStd::vector&& draftedTests) + void ImpactAnalysisTestSequenceStartCallback( + SuiteType suiteType, + const Client::TestRunSelection& selectedTests, + const AZStd::vector& discardedTests, + const AZStd::vector& draftedTests) { - ClearState(); - m_numTests = selectedTests.GetNumIncludedTestRuns() + draftedTests.size(); - - Output::TestSuiteFilter(m_suiteFilter); + Output::TestSuiteFilter(suiteType); Output::ImpactAnalysisTestSelection( selectedTests.GetTotalNumTests(), discardedTests.size(), selectedTests.GetNumExcludedTestRuns(), draftedTests.size()); } - // SafeImpactAnalysisTestSequenceStartCallback - void TestSequenceEventHandler::operator()( - Client::TestRunSelection&& selectedTests, - Client::TestRunSelection&& discardedTests, - AZStd::vector&& draftedTests) + void SafeImpactAnalysisTestSequenceStartCallback( + SuiteType suiteType, + const Client::TestRunSelection& selectedTests, + const Client::TestRunSelection& discardedTests, + const AZStd::vector& draftedTests) { - ClearState(); - m_numTests = selectedTests.GetNumIncludedTestRuns() + draftedTests.size(); - - Output::TestSuiteFilter(m_suiteFilter); + Output::TestSuiteFilter(suiteType); Output::ImpactAnalysisTestSelection( selectedTests.GetTotalNumTests(), discardedTests.GetTotalNumTests(), @@ -156,40 +149,45 @@ namespace TestImpact draftedTests.size()); } - // TestSequenceCompleteCallback - void TestSequenceEventHandler::operator()( - Client::SequenceFailure&& failureReport, - AZStd::chrono::milliseconds duration) + void TestSequenceCompleteCallback(const Client::SequenceReport& sequenceReport) { - Output::FailureReport(failureReport, duration); + Output::FailureReport(sequenceReport.GetSelectedTestRunReport()); std::cout << "Updating and serializing the test impact analysis data, this may take a moment...\n"; } - // SafeTestSequenceCompleteCallback - void TestSequenceEventHandler::operator()( - Client::SequenceFailure&& selectedFailureReport, - Client::SequenceFailure&& discardedFailureReport, - AZStd::chrono::milliseconds selectedDuration, - AZStd::chrono::milliseconds discaredDuration) + void ImpactAnalysisTestSequenceCompleteCallback(const Client::ImpactAnalysisSequenceReport& sequenceReport) { std::cout << "Selected test run:\n"; - Output::FailureReport(selectedFailureReport, selectedDuration); + Output::FailureReport(sequenceReport.GetSelectedTestRunReport()); - std::cout << "Discarded test run:\n"; - Output::FailureReport(discardedFailureReport, discaredDuration); + std::cout << "Drafted test run:\n"; + Output::FailureReport(sequenceReport.GetDraftedTestRunReport()); std::cout << "Updating and serializing the test impact analysis data, this may take a moment...\n"; } - // TestRunCompleteCallback - void TestSequenceEventHandler::operator()([[maybe_unused]] Client::TestRun&& test) + void SafeImpactAnalysisTestSequenceCompleteCallback(const Client::SafeImpactAnalysisSequenceReport& sequenceReport) { - m_numTestsComplete++; - const auto progress = AZStd::string::format("(%03u/%03u)", m_numTestsComplete, m_numTests, test.GetTargetName().c_str()); + std::cout << "Selected test run:\n"; + Output::FailureReport(sequenceReport.GetSelectedTestRunReport()); + + std::cout << "Discarded test run:\n"; + Output::FailureReport(sequenceReport.GetDiscardedTestRunReport()); + + std::cout << "Drafted test run:\n"; + Output::FailureReport(sequenceReport.GetDraftedTestRunReport()); + + std::cout << "Updating and serializing the test impact analysis data, this may take a moment...\n"; + } + + void TestRunCompleteCallback(const Client::TestRun& testRun, size_t numTestRunsCompleted, size_t totalNumTestRuns) + { + const auto progress = + AZStd::string::format("(%03u/%03u)", numTestRunsCompleted, totalNumTestRuns, testRun.GetTargetName().c_str()); AZStd::string result; - switch (test.GetResult()) + switch (testRun.GetResult()) { case Client::TestRunResult::AllTestsPass: { @@ -216,15 +214,14 @@ namespace TestImpact result = SetColorForString(Foreground::White, Background::Magenta, "TIME"); break; } + default: + { + AZ_Error("TestRunCompleteCallback", false, "Unexpected test result to handle: %u", aznumeric_cast(testRun.GetResult())); + } } - std::cout << progress.c_str() << " " << result.c_str() << " " << test.GetTargetName().c_str() << " (" << (test.GetDuration().count() / 1000.f) << "s)\n"; - } - - void TestSequenceEventHandler::ClearState() - { - m_numTests = 0; - m_numTestsComplete = 0; + std::cout << progress.c_str() << " " << result.c_str() << " " << testRun.GetTargetName().c_str() << " (" + << (testRun.GetDuration().count() / 1000.f) << "s)\n"; } } // namespace Console } // namespace TestImpact diff --git a/Code/Tools/TestImpactFramework/Frontend/Console/Code/Source/TestImpactConsoleTestSequenceEventHandler.h b/Code/Tools/TestImpactFramework/Frontend/Console/Code/Source/TestImpactConsoleTestSequenceEventHandler.h index ea570f6fc8..ff757b2d5a 100644 --- a/Code/Tools/TestImpactFramework/Frontend/Console/Code/Source/TestImpactConsoleTestSequenceEventHandler.h +++ b/Code/Tools/TestImpactFramework/Frontend/Console/Code/Source/TestImpactConsoleTestSequenceEventHandler.h @@ -8,7 +8,7 @@ #include #include -#include +#include #include #include @@ -21,48 +21,33 @@ namespace TestImpact { namespace Console { - //! Event handler for all test sequence types. - class TestSequenceEventHandler - { - public: - explicit TestSequenceEventHandler(SuiteType suiteFilter); + //! Handler for TestSequenceStartCallback event. + void TestSequenceStartCallback(SuiteType suiteType, const Client::TestRunSelection& selectedTests); - //! TestSequenceStartCallback. - void operator()(Client::TestRunSelection&& selectedTests); + //! Handler for TestSequenceStartCallback event. + void ImpactAnalysisTestSequenceStartCallback( + SuiteType suiteType, + const Client::TestRunSelection& selectedTests, + const AZStd::vector& discardedTests, + const AZStd::vector& draftedTests); - //! ImpactAnalysisTestSequenceStartCallback. - void operator()( - Client::TestRunSelection&& selectedTests, - AZStd::vector&& discardedTests, - AZStd::vector&& draftedTests); + //! Handler for SafeImpactAnalysisTestSequenceStartCallback event. + void SafeImpactAnalysisTestSequenceStartCallback( + SuiteType suiteType, + const Client::TestRunSelection& selectedTests, + const Client::TestRunSelection& discardedTests, + const AZStd::vector& draftedTests); - //! SafeImpactAnalysisTestSequenceStartCallback. - void operator()( - Client::TestRunSelection&& selectedTests, - Client::TestRunSelection&& discardedTests, - AZStd::vector&& draftedTests); + //! Handler for TestSequenceCompleteCallback event. + void TestSequenceCompleteCallback(const Client::SequenceReport& sequenceReport); - //! TestSequenceCompleteCallback. - void operator()( - Client::SequenceFailure&& failureReport, - AZStd::chrono::milliseconds duration); + //! Handler for ImpactAnalysisTestSequenceCompleteCallback event. + void ImpactAnalysisTestSequenceCompleteCallback(const Client::ImpactAnalysisSequenceReport& sequenceReport); - //! SafeTestSequenceCompleteCallback. - void operator()( - Client::SequenceFailure&& selectedFailureReport, - Client::SequenceFailure&& discardedFailureReport, - AZStd::chrono::milliseconds selectedDuration, - AZStd::chrono::milliseconds discaredDuration); + //! Handler for SafeImpactAnalysisTestSequenceCompleteCallback event. + void SafeImpactAnalysisTestSequenceCompleteCallback(const Client::SafeImpactAnalysisSequenceReport& sequenceReport); - //! TestRunCompleteCallback. - void operator()(Client::TestRun&& test); - - private: - void ClearState(); - - SuiteType m_suiteFilter; - size_t m_numTests = 0; - size_t m_numTestsComplete = 0; - }; + //! Handler for TestRunCompleteCallback event. + void TestRunCompleteCallback(const Client::TestRun& testRun, size_t numTestRunsCompleted, size_t totalNumTestRuns); } // namespace Console } // namespace TestImpact diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactClientFailureReport.h b/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactClientFailureReport.h deleted file mode 100644 index 063a3fa642..0000000000 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactClientFailureReport.h +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -#pragma once - -#include -#include - -namespace TestImpact -{ - namespace Client - { - //! Represents a test target that failed, either due to failing to execute, completing in an abnormal state or completing with failing tests. - class TargetFailure - { - public: - TargetFailure(const AZStd::string& targetName); - - //! Returns the name of the test target this failure pertains to. - const AZStd::string& GetTargetName() const; - private: - AZStd::string m_targetName; - }; - - //! Represents a test target that failed to execute. - class ExecutionFailure - : public TargetFailure - { - public: - ExecutionFailure(const AZStd::string& targetName, const AZStd::string& command); - - //! Returns the command string used to execute this test target. - const AZStd::string& GetCommandString() const; - private: - AZStd::string m_commandString; - }; - - //! Represents an individual test of a test target that failed. - class TestFailure - { - public: - TestFailure(const AZStd::string& testName, const AZStd::string& errorMessage); - - //! Returns the name of the test that failed. - const AZStd::string& GetName() const; - - //! Returns the error message of the test that failed. - const AZStd::string& GetErrorMessage() const; - - private: - AZStd::string m_name; - AZStd::string m_errorMessage; - }; - - //! Represents a collection of tests that failed. - //! @note Only the failing tests are included in the collection. - class TestCaseFailure - { - public: - TestCaseFailure(const AZStd::string& testCaseName, AZStd::vector&& testFailures); - - //! Returns the name of the test case containing the failing tests. - const AZStd::string& GetName() const; - - //! Returns the collection of tests in this test case that failed. - const AZStd::vector& GetTestFailures() const; - - private: - AZStd::string m_name; - AZStd::vector m_testFailures; - }; - - //! Represents a test target that launched successfully but contains failing tests. - class TestRunFailure - : public TargetFailure - { - public: - TestRunFailure(const AZStd::string& targetName, AZStd::vector&& testFailures); - - //! Returns the total number of failing tests in this run. - size_t GetNumTestFailures() const; - - //! Returns the test cases in this run containing failing tests. - const AZStd::vector& GetTestCaseFailures() const; - - private: - AZStd::vector m_testCaseFailures; - size_t m_numTestFailures = 0; - }; - - //! Base class for reporting failing test sequences. - class SequenceFailure - { - public: - SequenceFailure( - AZStd::vector&& executionFailures, - AZStd::vector&& testRunFailures, - AZStd::vector&& timedOutTests, - AZStd::vector&& unexecutedTests); - - //! Returns the test targets in this sequence that failed to execute. - const AZStd::vector& GetExecutionFailures() const; - - //! Returns the test targets that contain failing tests. - const AZStd::vector& GetTestRunFailures() const; - - //! Returns the test targets in this sequence that were terminated for exceeding their allotted runtime. - const AZStd::vector& GetTimedOutTests() const; - - //! Returns the test targets in this sequence that were not executed due to the sequence terminating prematurely. - const AZStd::vector& GetUnexecutedTests() const; - - private: - AZStd::vector m_executionFailures; - AZStd::vector m_testRunFailures; - AZStd::vector m_timedOutTests; - AZStd::vector m_unexecutedTests; - }; - } // namespace Client -} // namespace TestImpact diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactClientSequenceReport.h b/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactClientSequenceReport.h new file mode 100644 index 0000000000..73f3827fae --- /dev/null +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactClientSequenceReport.h @@ -0,0 +1,240 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#pragma once + +#include +#include +#include + +namespace TestImpact +{ + namespace Client + { + //! Report detailing the result and duration of a given set of test runs along with the details of each individual test run. + class TestRunReport + { + public: + //! Constructs the report for the given set of test runs that were run together in the same set. + //! @param result The result of this set of test runs. + //! @param startTime The time point his set of test runs started. + //! @param duration The duration this set of test runs took to complete. + //! @param passingTests The set of test runs that executed successfully with no failing tests. + //! @param failing tests The set of test runs that executed successfully but had one or more failing tests. + //! @param executionFailureTests The set of test runs that failed to execute. + //! @param timedOutTests The set of test runs that executed successfully but were terminated prematurely due to timing out. + //! @param unexecutedTests The set of test runs that were queued up for execution but did not get the opportunity to execute. + TestRunReport( + TestSequenceResult result, + AZStd::chrono::high_resolution_clock::time_point startTime, + AZStd::chrono::milliseconds duration, + AZStd::vector&& passingTests, + AZStd::vector&& failingTests, + AZStd::vector&& executionFailureTests, + AZStd::vector&& timedOutTests, + AZStd::vector&& unexecutedTests); + + //! Returns the result of this sequence of test runs. + TestSequenceResult GetResult() const; + + //! Returns the time this sequence of test runs started relative to T0. + AZStd::chrono::high_resolution_clock::time_point GetStartTime() const; + + //! Returns the time this sequence of test runs ended relative to T0. + AZStd::chrono::high_resolution_clock::time_point GetEndTime() const; + + //! Returns the duration this sequence of test runs took to complete. + AZStd::chrono::milliseconds GetDuration() const; + + //! Returns the number of passing test runs. + size_t GetNumPassingTests() const; + + //! Returns the number of failing test runs. + size_t GetNumFailingTests() const; + + //! Returns the number of timed out test runs. + size_t GetNumTimedOutTests() const; + + //! Returns the number of unexecuted test runs. + size_t GetNumUnexecutedTests() const; + + //! Returns the set of test runs that executed successfully with no failing tests. + const AZStd::vector& GetPassingTests() const; + + //! Returns the set of test runs that executed successfully but had one or more failing tests. + const AZStd::vector& GetFailingTests() const; + + //! Returns the set of test runs that failed to execute. + const AZStd::vector& GetExecutionFailureTests() const; + + //! Returns the set of test runs that executed successfully but were terminated prematurely due to timing out. + const AZStd::vector& GetTimedOutTests() const; + + //! Returns the set of test runs that were queued up for execution but did not get the opportunity to execute. + const AZStd::vector& GetUnexecutedTests() const; + private: + TestSequenceResult m_result; + AZStd::chrono::high_resolution_clock::time_point m_startTime; + AZStd::chrono::milliseconds m_duration; + AZStd::vector m_passingTests; + AZStd::vector m_failingTests; + AZStd::vector m_executionFailureTests; + AZStd::vector m_timedOutTests; + AZStd::vector m_unexecutedTests; + }; + + //! Report detailing a test run sequence of selected tests. + class SequenceReport + { + public: + //! Constructs the report for a sequence of selected tests. + //! @param suiteType The suite from which the tests have been selected from. + //! @param selectedTests The target names of the selected tests. + //! @param selectedTestRunReport The report for the set of selected test runs. + SequenceReport(SuiteType suiteType, const TestRunSelection& selectedTests, TestRunReport&& selectedTestRunReport); + + //! Returns the tests selected for running in the sequence. + TestRunSelection GetSelectedTests() const; + + //! Returns the report for the selected test runs. + TestRunReport GetSelectedTestRunReport() const; + + //! Returns the start time of the sequence. + AZStd::chrono::high_resolution_clock::time_point GetStartTime() const; + + //! Returns the end time of the sequence. + AZStd::chrono::high_resolution_clock::time_point GetEndTime() const; + + //! Returns the result of the sequence. + virtual TestSequenceResult GetResult() const; + + //! Returns the entire duration the sequence took from start to finish. + virtual AZStd::chrono::milliseconds GetDuration() const; + + //! Get the total number of tests in the sequence that passed. + virtual size_t GetTotalNumPassingTests() const; + + //! Get the total number of tests in the sequence that contain one or more test failures. + virtual size_t GetTotalNumFailingTests() const; + + //! Get the total number of tests in the sequence that timed out whilst in flight. + virtual size_t GetTotalNumTimedOutTests() const; + + //! Get the total number of tests in the sequence that were queued for execution but did not get the oppurtunity to execute. + virtual size_t GetTotalNumUnexecutedTests() const; + + private: + SuiteType m_suite; + TestRunSelection m_selectedTests; + TestRunReport m_selectedTestRunReport; + }; + + //! Report detailing a test run sequence of selected and drafted tests. + class DraftingSequenceReport + : public SequenceReport + { + public: + //! Constructs the report for a sequence of selected and drafted tests. + //! @param suiteType The suite from which the tests have been selected from. + //! @param selectedTests The target names of the selected tests. + //! @param draftedTests The target names of the drafted tests. + //! @param selectedTestRunReport The report for the set of selected test runs. + //! @param draftedTestRunReport The report for the set of drafted test runs. + DraftingSequenceReport( + SuiteType suiteType, + const TestRunSelection& selectedTests, + const AZStd::vector& draftedTests, + TestRunReport&& selectedTestRunReport, + TestRunReport&& draftedTestRunReport); + + // SequenceReport overrides ... + TestSequenceResult GetResult() const override; + AZStd::chrono::milliseconds GetDuration() const override; + size_t GetTotalNumPassingTests() const override; + size_t GetTotalNumFailingTests() const override; + size_t GetTotalNumTimedOutTests() const override; + size_t GetTotalNumUnexecutedTests() const override; + + //! Returns the tests drafted for running in the sequence. + const AZStd::vector& GetDraftedTests() const; + + //! Returns the report for the drafted test runs. + TestRunReport GetDraftedTestRunReport() const; + + private: + AZStd::vector m_draftedTests; + TestRunReport m_draftedTestRunReport; + }; + + //! Report detailing an impact analysis sequence of selected, discarded and drafted tests. + class ImpactAnalysisSequenceReport + : public DraftingSequenceReport + { + public: + //! Constructs the report for a sequence of selected and drafted tests. + //! @param suiteType The suite from which the tests have been selected from. + //! @param selectedTests The target names of the selected tests. + //! @param discardedTests The target names of the discarded tests. + //! @param draftedTests The target names of the drafted tests. + //! @param selectedTestRunReport The report for the set of selected test runs. + //! @param draftedTestRunReport The report for the set of drafted test runs. + ImpactAnalysisSequenceReport( + SuiteType suiteType, + const TestRunSelection& selectedTests, + const AZStd::vector& discardedTests, + const AZStd::vector& draftedTests, + TestRunReport&& selectedTestRunReport, + TestRunReport&& draftedTestRunReport); + + //! Returns the tests discarded from running in the sequence. + const AZStd::vector& GetDiscardedTests() const; + private: + AZStd::vector m_discardedTests; + }; + + //! Report detailing an impact analysis sequence of selected, discarded and drafted tests. + class SafeImpactAnalysisSequenceReport + : public DraftingSequenceReport + { + public: + //! Constructs the report for a sequence of selected and drafted tests. + //! @param suiteType The suite from which the tests have been selected from. + //! @param selectedTests The target names of the selected tests. + //! @param discardedTests The target names of the discarded tests. + //! @param draftedTests The target names of the drafted tests. + //! @param selectedTestRunReport The report for the set of selected test runs. + //! @param discardedTestRunReport The report for the set of discarded test runs. + //! @param draftedTestRunReport The report for the set of drafted test runs. + SafeImpactAnalysisSequenceReport( + SuiteType suiteType, + const TestRunSelection& selectedTests, + const TestRunSelection& discardedTests, + const AZStd::vector& draftedTests, + TestRunReport&& selectedTestRunReport, + TestRunReport&& discardedTestRunReport, + TestRunReport&& draftedTestRunReport); + + // DraftingSequenceReport overrides ... + TestSequenceResult GetResult() const override; + AZStd::chrono::milliseconds GetDuration() const override; + size_t GetTotalNumPassingTests() const override; + size_t GetTotalNumFailingTests() const override; + size_t GetTotalNumTimedOutTests() const override; + size_t GetTotalNumUnexecutedTests() const override; + + //! Returns the report for the discarded test runs. + const TestRunSelection GetDiscardedTests() const; + + //! Returns the report for the discarded test runs. + TestRunReport GetDiscardedTestRunReport() const; + + private: + TestRunSelection m_discardedTests; + TestRunReport m_discardedTestRunReport; + }; + } // namespace Client +} // namespace TestImpact diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactClientTestRun.h b/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactClientTestRun.h index f8a2707b96..4b7715bf1d 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactClientTestRun.h +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactClientTestRun.h @@ -6,8 +6,9 @@ * */ -#include #include +#include +#include #pragma once @@ -25,18 +26,118 @@ namespace TestImpact AllTestsPass //!< The test run completed its run and all tests passed. }; + //! Representation of a completed test run. class TestRun { public: - TestRun(const AZStd::string& name, TestRunResult result, AZStd::chrono::milliseconds duration); + //! Constructs the client facing representation of a given test target's run. + //! @param name The name of the test target. + //! @param commandString The command string used to execute this test target. + //! @param startTime The start time, relative to the sequence start, that this run started. + //! @param duration The duration that this test run took to complete. + //! @param result The result of the run. + TestRun( + const AZStd::string& name, + const AZStd::string& commandString, + AZStd::chrono::high_resolution_clock::time_point startTime, + AZStd::chrono::milliseconds duration, + TestRunResult result); + + //! Returns the test target name. const AZStd::string& GetTargetName() const; + + //! Returns the test run result. TestRunResult GetResult() const; + + //! Returns the test run start time. + AZStd::chrono::high_resolution_clock::time_point GetStartTime() const; + + //! Returns the end time, relative to the sequence start, that this run ended. + AZStd::chrono::high_resolution_clock::time_point GetEndTime() const; + + //! Returns the duration that this test run took to complete. AZStd::chrono::milliseconds GetDuration() const; + //! Returns the command string used to execute this test target. + const AZStd::string& GetCommandString() const; + private: AZStd::string m_targetName; + AZStd::string m_commandString; TestRunResult m_result; + AZStd::chrono::high_resolution_clock::time_point m_startTime; AZStd::chrono::milliseconds m_duration; }; + + //! Represents an individual test of a test target that failed. + class TestFailure + { + public: + TestFailure(const AZStd::string& testName, const AZStd::string& errorMessage); + + //! Returns the name of the test that failed. + const AZStd::string& GetName() const; + + //! Returns the error message of the test that failed. + const AZStd::string& GetErrorMessage() const; + + private: + AZStd::string m_name; + AZStd::string m_errorMessage; + }; + + //! Represents a collection of tests that failed. + //! @note Only the failing tests are included in the collection. + class TestCaseFailure + { + public: + TestCaseFailure(const AZStd::string& testCaseName, AZStd::vector&& testFailures); + + //! Returns the name of the test case containing the failing tests. + const AZStd::string& GetName() const; + + //! Returns the collection of tests in this test case that failed. + const AZStd::vector& GetTestFailures() const; + + private: + AZStd::string m_name; + AZStd::vector m_testFailures; + }; + + //! Representation of a test run's failing tests. + class TestRunWithTestFailures + : public TestRun + { + public: + //! Constructs the client facing representation of a given test target's run. + //! @param name The name of the test target. + //! @param commandString The command string used to execute this test target. + //! @param startTime The start time, relative to the sequence start, that this run started. + //! @param duration The duration that this test run took to complete. + //! @param result The result of the run. + //! @param testFailures The failing tests for this test run. + TestRunWithTestFailures( + const AZStd::string& name, + const AZStd::string& commandString, + AZStd::chrono::high_resolution_clock::time_point startTime, + AZStd::chrono::milliseconds duration, + TestRunResult result, + AZStd::vector&& testFailures); + + //! Constructs the client facing representation of a given test target's run. + //! @param testRun The test run this run is to be derived from. + //! @param testFailures The failing tests for this run. + TestRunWithTestFailures(TestRun&& testRun, AZStd::vector&& testFailures); + + //! Returns the total number of failing tests in this run. + size_t GetNumTestFailures() const; + + //! Returns the test cases in this run containing failing tests. + const AZStd::vector& GetTestCaseFailures() const; + + private: + AZStd::vector m_testCaseFailures; + size_t m_numTestFailures = 0; + }; } // namespace Client } // namespace TestImpact diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactClientTestSelection.h b/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactClientTestSelection.h index af084ee57b..7d2169e680 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactClientTestSelection.h +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactClientTestSelection.h @@ -21,6 +21,7 @@ namespace TestImpact class TestRunSelection { public: + TestRunSelection() = default; TestRunSelection(const AZStd::vector& includedTests, const AZStd::vector& excludedTests); TestRunSelection(AZStd::vector&& includedTests, AZStd::vector&& excludedTests); diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactRuntime.h b/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactRuntime.h index 506aeef53e..69feb48749 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactRuntime.h +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactRuntime.h @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include @@ -34,10 +34,12 @@ namespace TestImpact class TestEngineInstrumentedRun; //! Callback for a test sequence that isn't using test impact analysis to determine selected tests. + //! @parm suiteType The test suite to select tests from. //! @param tests The tests that will be run for this sequence. - using TestSequenceStartCallback = AZStd::function; + using TestSequenceStartCallback = AZStd::function; //! Callback for a test sequence using test impact analysis. + //! @parm suiteType The test suite to select tests from. //! @param selectedTests The tests that have been selected for this run by test impact analysis. //! @param discardedTests The tests that have been rejected for this run by test impact analysis. //! @param draftedTests The tests that have been drafted in for this run due to requirements outside of test impact analysis @@ -46,11 +48,13 @@ namespace TestImpact //! These tests will be run with coverage instrumentation. //! @note discardedTests and draftedTests may contain overlapping tests. using ImpactAnalysisTestSequenceStartCallback = AZStd::function&& discardedTests, - AZStd::vector&& draftedTests)>; + SuiteType suiteType, + const Client::TestRunSelection& selectedTests, + const AZStd::vector& discardedTests, + const AZStd::vector& draftedTests)>; //! Callback for a test sequence using test impact analysis. + //! @parm suiteType The test suite to select tests from. //! @param selectedTests The tests that have been selected for this run by test impact analysis. //! @param discardedTests The tests that have been rejected for this run by test impact analysis. //! These tests will not be run without coverage instrumentation unless there is an entry in the draftedTests list. @@ -59,30 +63,22 @@ namespace TestImpact //! to execute previously). //! @note discardedTests and draftedTests may contain overlapping tests. using SafeImpactAnalysisTestSequenceStartCallback = AZStd::function&& draftedTests)>; + SuiteType suiteType, + const Client::TestRunSelection& selectedTests, + const Client::TestRunSelection& discardedTests, + const AZStd::vector& draftedTests)>; //! Callback for end of a test sequence. - //! @param failureReport The test runs that failed for any reason during this sequence. - //! @param duration The total duration of this test sequence. - using TestSequenceCompleteCallback = AZStd::function; - - //! Callback for end of a test impact analysis test sequence. - //! @param selectedFailureReport The selected test runs that failed for any reason during this sequence. - //! @param discardedFailureReport The discarded test runs that failed for any reason during this sequence. - //! @param duration The total duration of this test sequence. - using SafeTestSequenceCompleteCallback = AZStd::function; + //! @tparam SequenceReportType The report type to be used for the sequence. + //! @param sequenceReport The completed sequence report. + template + using TestSequenceCompleteCallback = AZStd::function; //! Callback for test runs that have completed for any reason. - //! @param selectedTests The test that has completed. - using TestRunCompleteCallback = AZStd::function; + //! @param testRunMeta The test that has completed. + //! @param numTestRunsCompleted The number of test runs that have completed. + //! @param totalNumTestRuns The total number of test runs in the sequence. + using TestRunCompleteCallback = AZStd::function; //! The API exposed to the client responsible for all test runs and persistent data management. class Runtime @@ -108,19 +104,19 @@ namespace TestImpact AZStd::optional maxConcurrency = AZStd::nullopt); ~Runtime(); - + //! Runs a test sequence where all tests with a matching suite in the suite filter and also not on the excluded list are selected. //! @param testTargetTimeout The maximum duration individual test targets may be in flight for (infinite if empty). //! @param globalTimeout The maximum duration the entire test sequence may run for (infinite if empty). //! @param testSequenceStartCallback The client function to be called after the test targets have been selected but prior to running the tests. //! @param testSequenceCompleteCallback The client function to be called after the test sequence has completed. //! @param testRunCompleteCallback The client function to be called after an individual test run has completed. - //! @returns - TestSequenceResult RegularTestSequence( + //! @returns The test run and sequence report for the selected test sequence. + Client::SequenceReport RegularTestSequence( AZStd::optional testTargetTimeout, AZStd::optional globalTimeout, AZStd::optional testSequenceStartCallback, - AZStd::optional testSequenceCompleteCallback, + AZStd::optional> testSequenceCompleteCallback, AZStd::optional testRunCompleteCallback); //! Runs a test sequence where tests are selected according to test impact analysis so long as they are not on the excluded list. @@ -132,15 +128,15 @@ namespace TestImpact //! @param testSequenceStartCallback The client function to be called after the test targets have been selected but prior to running the tests. //! @param testSequenceCompleteCallback The client function to be called after the test sequence has completed. //! @param testRunCompleteCallback The client function to be called after an individual test run has completed. - //! @returns - TestSequenceResult ImpactAnalysisTestSequence( + //! @returns The test run and sequence report for the selected and drafted test sequences. + Client::ImpactAnalysisSequenceReport ImpactAnalysisTestSequence( const ChangeList& changeList, Policy::TestPrioritization testPrioritizationPolicy, Policy::DynamicDependencyMap dynamicDependencyMapPolicy, AZStd::optional testTargetTimeout, AZStd::optional globalTimeout, AZStd::optional testSequenceStartCallback, - AZStd::optional testSequenceCompleteCallback, + AZStd::optional> testSequenceCompleteCallback, AZStd::optional testRunCompleteCallback); //! Runs a test sequence as per the ImpactAnalysisTestSequence where the tests not selected are also run (albeit without instrumentation). @@ -151,14 +147,14 @@ namespace TestImpact //! @param testSequenceStartCallback The client function to be called after the test targets have been selected but prior to running the tests. //! @param testSequenceCompleteCallback The client function to be called after the test sequence has completed. //! @param testRunCompleteCallback The client function to be called after an individual test run has completed. - //! @returns - AZStd::pair SafeImpactAnalysisTestSequence( + //! @returns The test run and sequence report for the selected, discarded and drafted test sequences. + Client::SafeImpactAnalysisSequenceReport SafeImpactAnalysisTestSequence( const ChangeList& changeList, Policy::TestPrioritization testPrioritizationPolicy, AZStd::optional testTargetTimeout, AZStd::optional globalTimeout, AZStd::optional testSequenceStartCallback, - AZStd::optional testSequenceCompleteCallback, + AZStd::optional> testSequenceCompleteCallback, AZStd::optional testRunCompleteCallback); //! Runs all tests not on the excluded list and uses their coverage data to seed the test impact analysis data (ant existing data will be overwritten). @@ -167,12 +163,12 @@ namespace TestImpact //! @param testSequenceStartCallback The client function to be called after the test targets have been selected but prior to running the tests. //! @param testSequenceCompleteCallback The client function to be called after the test sequence has completed. //! @param testRunCompleteCallback The client function to be called after an individual test run has completed. - //! - TestSequenceResult SeededTestSequence( + //! @returns The test run and sequence report for the selected test sequence. + Client::SequenceReport SeededTestSequence( AZStd::optional testTargetTimeout, AZStd::optional globalTimeout, AZStd::optional testSequenceStartCallback, - AZStd::optional testSequenceCompleteCallback, + AZStd::optional> testSequenceCompleteCallback, AZStd::optional testRunCompleteCallback); //! Returns true if the runtime has test impact analysis data (either preexisting or generated). @@ -209,8 +205,8 @@ namespace TestImpact void UpdateAndSerializeDynamicDependencyMap(const AZStd::vector& jobs); RuntimeConfig m_config; - SuiteType m_suiteFilter; RepoPath m_sparTIAFile; + SuiteType m_suiteFilter; Policy::ExecutionFailure m_executionFailurePolicy; Policy::FailedTestCoverage m_failedTestCoveragePolicy; Policy::TestFailure m_testFailurePolicy; diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/TestImpactTestEngine.cpp b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/TestImpactTestEngine.cpp index 61634a8bd3..226301d444 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/TestImpactTestEngine.cpp +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/TestImpactTestEngine.cpp @@ -262,7 +262,7 @@ namespace TestImpact Policy::TestFailure testFailurePolicy, AZStd::optional testTargetTimeout, AZStd::optional globalTimeout, - AZStd::optional callback) + AZStd::optional callback) const { TestEngineJobMap engineJobs; const auto jobInfos = m_testJobInfoGenerator->GenerateTestEnumerationJobInfos(testTargets, TestEnumerator::JobInfo::CachePolicy::Write); @@ -285,7 +285,7 @@ namespace TestImpact [[maybe_unused]]Policy::TargetOutputCapture targetOutputCapture, AZStd::optional testTargetTimeout, AZStd::optional globalTimeout, - AZStd::optional callback) + AZStd::optional callback) const { DeleteArtifactXmls(); @@ -312,7 +312,7 @@ namespace TestImpact [[maybe_unused]]Policy::TargetOutputCapture targetOutputCapture, AZStd::optional testTargetTimeout, AZStd::optional globalTimeout, - AZStd::optional callback) + AZStd::optional callback) const { DeleteArtifactXmls(); diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/TestImpactTestEngine.h b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/TestImpactTestEngine.h index f1bb77f06f..6b097f241f 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/TestImpactTestEngine.h +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/TestImpactTestEngine.h @@ -69,7 +69,7 @@ namespace TestImpact Policy::TestFailure testFailurePolicy, AZStd::optional testTargetTimeout, AZStd::optional globalTimeout, - AZStd::optional callback); + AZStd::optional callback) const; //! Performs a test run without any instrumentation and, for each test target, returns the test run results and metrics about the run. //! @param testTargets The test targets to run. @@ -89,7 +89,7 @@ namespace TestImpact Policy::TargetOutputCapture targetOutputCapture, AZStd::optional testTargetTimeout, AZStd::optional globalTimeout, - AZStd::optional callback); + AZStd::optional callback) const; //! Performs a test run with instrumentation and, for each test target, returns the test run results, coverage data and metrics about the run. //! @param testTargets The test targets to run. @@ -111,7 +111,7 @@ namespace TestImpact Policy::TargetOutputCapture targetOutputCapture, AZStd::optional testTargetTimeout, AZStd::optional globalTimeout, - AZStd::optional callback); + AZStd::optional callback) const; private: //! Cleans up the artifacts directory of any artifacts from previous runs. diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactClientFailureReport.cpp b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactClientFailureReport.cpp deleted file mode 100644 index 000ded2aa8..0000000000 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactClientFailureReport.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -#include - -namespace TestImpact -{ - namespace Client - { - TargetFailure::TargetFailure(const AZStd::string& targetName) - : m_targetName(targetName) - { - } - - const AZStd::string& TargetFailure::GetTargetName() const - { - return m_targetName; - } - - ExecutionFailure::ExecutionFailure(const AZStd::string& targetName, const AZStd::string& command) - : TargetFailure(targetName) - , m_commandString(command) - { - } - - const AZStd::string& ExecutionFailure::GetCommandString() const - { - return m_commandString; - } - - TestFailure::TestFailure(const AZStd::string& testName, const AZStd::string& errorMessage) - : m_name(testName) - , m_errorMessage(errorMessage) - { - } - - const AZStd::string& TestFailure::GetName() const - { - return m_name; - } - - const AZStd::string& TestFailure::GetErrorMessage() const - { - return m_errorMessage; - } - - TestCaseFailure::TestCaseFailure(const AZStd::string& testCaseName, AZStd::vector&& testFailures) - : m_name(testCaseName) - , m_testFailures(AZStd::move(testFailures)) - { - } - - const AZStd::string& TestCaseFailure::GetName() const - { - return m_name; - } - - const AZStd::vector& TestCaseFailure::GetTestFailures() const - { - return m_testFailures; - } - - TestRunFailure::TestRunFailure(const AZStd::string& targetName, AZStd::vector&& testFailures) - : TargetFailure(targetName) - , m_testCaseFailures(AZStd::move(testFailures)) - { - for (const auto& testCase : m_testCaseFailures) - { - m_numTestFailures += testCase.GetTestFailures().size(); - } - } - - size_t TestRunFailure::GetNumTestFailures() const - { - return m_numTestFailures; - } - - const AZStd::vector& TestRunFailure::GetTestCaseFailures() const - { - return m_testCaseFailures; - } - - SequenceFailure::SequenceFailure( - AZStd::vector&& executionFailures, - AZStd::vector&& testRunFailures, - AZStd::vector&& timedOutTests, - AZStd::vector&& unexecutionTests) - : m_executionFailures(AZStd::move(executionFailures)) - , m_testRunFailures(testRunFailures) - , m_timedOutTests(AZStd::move(timedOutTests)) - , m_unexecutedTests(AZStd::move(unexecutionTests)) - { - } - - const AZStd::vector& SequenceFailure::GetExecutionFailures() const - { - return m_executionFailures; - } - - const AZStd::vector& SequenceFailure::GetTestRunFailures() const - { - return m_testRunFailures; - } - - const AZStd::vector& SequenceFailure::GetTimedOutTests() const - { - return m_timedOutTests; - } - - const AZStd::vector& SequenceFailure::GetUnexecutedTests() const - { - return m_unexecutedTests; - } - } // namespace Client -} // namespace TestImpact diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactClientSequenceReport.cpp b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactClientSequenceReport.cpp new file mode 100644 index 0000000000..ba3a479fdf --- /dev/null +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactClientSequenceReport.cpp @@ -0,0 +1,312 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include + +namespace TestImpact +{ + namespace Client + { + //! Calculates the final sequence result for a composite of multiple sequences. + TestSequenceResult CalculateMultiTestSequenceResult(const AZStd::vector& results) + { + // Order of precedence: + // 1. TestSequenceResult::Failure + // 2. TestSequenceResult::Timeout + // 3. TestSequenceResult::Success + + if (const auto it = AZStd::find(results.begin(), results.end(), TestSequenceResult::Failure); + it != results.end()) + { + return TestSequenceResult::Failure; + } + + if (const auto it = AZStd::find(results.begin(), results.end(), TestSequenceResult::Timeout); + it != results.end()) + { + return TestSequenceResult::Timeout; + } + + return TestSequenceResult::Success; + } + + TestRunReport::TestRunReport( + TestSequenceResult result, + AZStd::chrono::high_resolution_clock::time_point startTime, + AZStd::chrono::milliseconds duration, + AZStd::vector&& passingTests, + AZStd::vector&& failingTests, + AZStd::vector&& executionFailureTests, + AZStd::vector&& timedOutTests, + AZStd::vector&& unexecutedTests) + : m_startTime(startTime) + , m_result(result) + , m_duration(duration) + , m_passingTests(AZStd::move(passingTests)) + , m_failingTests(AZStd::move(failingTests)) + , m_executionFailureTests(AZStd::move(executionFailureTests)) + , m_timedOutTests(AZStd::move(timedOutTests)) + , m_unexecutedTests(AZStd::move(unexecutedTests)) + { + } + + TestSequenceResult TestRunReport::GetResult() const + { + return m_result; + } + + AZStd::chrono::high_resolution_clock::time_point TestRunReport::GetStartTime() const + { + return m_startTime; + } + + AZStd::chrono::high_resolution_clock::time_point TestRunReport::GetEndTime() const + { + return m_startTime + m_duration; + } + + AZStd::chrono::milliseconds TestRunReport::GetDuration() const + { + return m_duration; + } + + size_t TestRunReport::GetNumPassingTests() const + { + return m_passingTests.size(); + } + + size_t TestRunReport::GetNumFailingTests() const + { + return m_failingTests.size(); + } + + size_t TestRunReport::GetNumTimedOutTests() const + { + return m_timedOutTests.size(); + } + + size_t TestRunReport::GetNumUnexecutedTests() const + { + return m_unexecutedTests.size(); + } + + const AZStd::vector& TestRunReport::GetPassingTests() const + { + return m_passingTests; + } + + const AZStd::vector& TestRunReport::GetFailingTests() const + { + return m_failingTests; + } + + const AZStd::vector& TestRunReport::GetExecutionFailureTests() const + { + return m_executionFailureTests; + } + + const AZStd::vector& TestRunReport::GetTimedOutTests() const + { + return m_timedOutTests; + } + + const AZStd::vector& TestRunReport::GetUnexecutedTests() const + { + return m_unexecutedTests; + } + + SequenceReport::SequenceReport(SuiteType suiteType, const TestRunSelection& selectedTests, TestRunReport&& selectedTestRunReport) + : m_suite(suiteType) + , m_selectedTests(selectedTests) + , m_selectedTestRunReport(AZStd::move(selectedTestRunReport)) + { + } + + TestSequenceResult SequenceReport::GetResult() const + { + return m_selectedTestRunReport.GetResult(); + } + + AZStd::chrono::high_resolution_clock::time_point SequenceReport::GetStartTime() const + { + return m_selectedTestRunReport.GetStartTime(); + } + + AZStd::chrono::high_resolution_clock::time_point SequenceReport::GetEndTime() const + { + return GetStartTime() + GetDuration(); + } + + AZStd::chrono::milliseconds SequenceReport::GetDuration() const + { + return m_selectedTestRunReport.GetDuration(); + } + + TestRunSelection SequenceReport::GetSelectedTests() const + { + return m_selectedTests; + } + + TestRunReport SequenceReport::GetSelectedTestRunReport() const + { + return m_selectedTestRunReport; + } + + size_t SequenceReport::GetTotalNumPassingTests() const + { + return m_selectedTestRunReport.GetNumPassingTests(); + } + + size_t SequenceReport::GetTotalNumFailingTests() const + { + return m_selectedTestRunReport.GetNumFailingTests(); + } + + size_t SequenceReport::GetTotalNumTimedOutTests() const + { + return m_selectedTestRunReport.GetNumTimedOutTests(); + } + + size_t SequenceReport::GetTotalNumUnexecutedTests() const + { + return m_selectedTestRunReport.GetNumUnexecutedTests(); + } + + DraftingSequenceReport::DraftingSequenceReport( + SuiteType suiteType, + const TestRunSelection& selectedTests, + const AZStd::vector& draftedTests, + TestRunReport&& selectedTestRunReport, + TestRunReport&& draftedTestRunReport) + : SequenceReport(suiteType, selectedTests, AZStd::move(selectedTestRunReport)) + , m_draftedTests(draftedTests) + , m_draftedTestRunReport(AZStd::move(draftedTestRunReport)) + { + } + + TestSequenceResult DraftingSequenceReport::GetResult() const + { + return CalculateMultiTestSequenceResult({SequenceReport::GetResult(), m_draftedTestRunReport.GetResult()}); + } + + AZStd::chrono::milliseconds DraftingSequenceReport::GetDuration() const + { + return SequenceReport::GetDuration() + m_draftedTestRunReport.GetDuration(); + } + + size_t DraftingSequenceReport::GetTotalNumPassingTests() const + { + return SequenceReport::GetTotalNumPassingTests() + m_draftedTestRunReport.GetNumPassingTests(); + } + + size_t DraftingSequenceReport::GetTotalNumFailingTests() const + { + return SequenceReport::GetTotalNumFailingTests() + m_draftedTestRunReport.GetNumFailingTests(); + } + + size_t DraftingSequenceReport::GetTotalNumTimedOutTests() const + { + return SequenceReport::GetTotalNumTimedOutTests() + m_draftedTestRunReport.GetNumTimedOutTests(); + } + + size_t DraftingSequenceReport::GetTotalNumUnexecutedTests() const + { + return SequenceReport::GetTotalNumUnexecutedTests() + m_draftedTestRunReport.GetNumUnexecutedTests(); + } + + const AZStd::vector& DraftingSequenceReport::GetDraftedTests() const + { + return m_draftedTests; + } + + TestRunReport DraftingSequenceReport::GetDraftedTestRunReport() const + { + return m_draftedTestRunReport; + } + + ImpactAnalysisSequenceReport::ImpactAnalysisSequenceReport( + SuiteType suiteType, + const TestRunSelection& selectedTests, + const AZStd::vector& discardedTests, + const AZStd::vector& draftedTests, + TestRunReport&& selectedTestRunReport, + TestRunReport&& draftedTestRunReport) + : DraftingSequenceReport( + suiteType, + selectedTests, + draftedTests, + AZStd::move(selectedTestRunReport), + AZStd::move(draftedTestRunReport)) + , m_discardedTests(discardedTests) + { + } + + const AZStd::vector& ImpactAnalysisSequenceReport::GetDiscardedTests() const + { + return m_discardedTests; + } + + SafeImpactAnalysisSequenceReport::SafeImpactAnalysisSequenceReport( + SuiteType suiteType, + const TestRunSelection& selectedTests, + const TestRunSelection& discardedTests, + const AZStd::vector& draftedTests, + TestRunReport&& selectedTestRunReport, + TestRunReport&& discardedTestRunReport, + TestRunReport&& draftedTestRunReport) + : DraftingSequenceReport( + suiteType, + selectedTests, + draftedTests, + AZStd::move(selectedTestRunReport), + AZStd::move(draftedTestRunReport)) + , m_discardedTests(discardedTests) + , m_discardedTestRunReport(AZStd::move(discardedTestRunReport)) + { + } + + TestSequenceResult SafeImpactAnalysisSequenceReport::GetResult() const + { + return CalculateMultiTestSequenceResult({ DraftingSequenceReport::GetResult(), m_discardedTestRunReport.GetResult() }); + } + + AZStd::chrono::milliseconds SafeImpactAnalysisSequenceReport::GetDuration() const + { + return DraftingSequenceReport::GetDuration() + m_discardedTestRunReport.GetDuration(); + } + + size_t SafeImpactAnalysisSequenceReport::GetTotalNumPassingTests() const + { + return DraftingSequenceReport::GetTotalNumPassingTests() + m_discardedTestRunReport.GetNumPassingTests(); + } + + size_t SafeImpactAnalysisSequenceReport::GetTotalNumFailingTests() const + { + return DraftingSequenceReport::GetTotalNumFailingTests() + m_discardedTestRunReport.GetNumFailingTests(); + } + + size_t SafeImpactAnalysisSequenceReport::GetTotalNumTimedOutTests() const + { + return DraftingSequenceReport::GetTotalNumTimedOutTests() + m_discardedTestRunReport.GetNumTimedOutTests(); + } + + size_t SafeImpactAnalysisSequenceReport::GetTotalNumUnexecutedTests() const + { + return DraftingSequenceReport::GetTotalNumUnexecutedTests() + m_discardedTestRunReport.GetNumUnexecutedTests(); + } + + const TestRunSelection SafeImpactAnalysisSequenceReport::GetDiscardedTests() const + { + return m_discardedTests; + } + + TestRunReport SafeImpactAnalysisSequenceReport::GetDiscardedTestRunReport() const + { + return m_discardedTestRunReport; + } + } // namespace Client +} // namespace TestImpact diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactClientTestRun.cpp b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactClientTestRun.cpp index 582927baa5..0a258c5dac 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactClientTestRun.cpp +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactClientTestRun.cpp @@ -7,14 +7,22 @@ */ #include + namespace TestImpact { namespace Client { - TestRun::TestRun(const AZStd::string& name, TestRunResult result, AZStd::chrono::milliseconds duration) + TestRun::TestRun( + const AZStd::string& name, + const AZStd::string& commandString, + AZStd::chrono::high_resolution_clock::time_point startTime, + AZStd::chrono::milliseconds duration, + TestRunResult result) : m_targetName(name) - , m_result(result) + , m_commandString(commandString) + , m_startTime(startTime) , m_duration(duration) + , m_result(result) { } @@ -23,6 +31,21 @@ namespace TestImpact return m_targetName; } + const AZStd::string& TestRun::GetCommandString() const + { + return m_commandString; + } + + AZStd::chrono::high_resolution_clock::time_point TestRun::GetStartTime() const + { + return m_startTime; + } + + AZStd::chrono::high_resolution_clock::time_point TestRun::GetEndTime() const + { + return m_startTime + m_duration; + } + AZStd::chrono::milliseconds TestRun::GetDuration() const { return m_duration; @@ -32,5 +55,78 @@ namespace TestImpact { return m_result; } + + TestFailure::TestFailure(const AZStd::string& testName, const AZStd::string& errorMessage) + : m_name(testName) + , m_errorMessage(errorMessage) + { + } + + const AZStd::string& TestFailure::GetName() const + { + return m_name; + } + + const AZStd::string& TestFailure::GetErrorMessage() const + { + return m_errorMessage; + } + + TestCaseFailure::TestCaseFailure(const AZStd::string& testCaseName, AZStd::vector&& testFailures) + : m_name(testCaseName) + , m_testFailures(AZStd::move(testFailures)) + { + } + + const AZStd::string& TestCaseFailure::GetName() const + { + return m_name; + } + + const AZStd::vector& TestCaseFailure::GetTestFailures() const + { + return m_testFailures; + } + + static size_t CalculateNumTestRunFailures(const AZStd::vector& testFailures) + { + size_t numTestFailures = 0; + for (const auto& testCase : testFailures) + { + numTestFailures += testCase.GetTestFailures().size(); + } + + return numTestFailures; + } + + TestRunWithTestFailures::TestRunWithTestFailures( + const AZStd::string& name, + const AZStd::string& commandString, + AZStd::chrono::high_resolution_clock::time_point startTime, + AZStd::chrono::milliseconds duration, + TestRunResult result, + AZStd::vector&& testFailures) + : TestRun(name, commandString, startTime, duration, result) + , m_testCaseFailures(AZStd::move(testFailures)) + { + m_numTestFailures = CalculateNumTestRunFailures(m_testCaseFailures); + } + + TestRunWithTestFailures::TestRunWithTestFailures(TestRun&& testRun, AZStd::vector&& testFailures) + : TestRun(AZStd::move(testRun)) + , m_testCaseFailures(AZStd::move(testFailures)) + { + m_numTestFailures = CalculateNumTestRunFailures(m_testCaseFailures); + } + + size_t TestRunWithTestFailures::GetNumTestFailures() const + { + return m_numTestFailures; + } + + const AZStd::vector& TestRunWithTestFailures::GetTestCaseFailures() const + { + return m_testCaseFailures; + } } // namespace Client } // namespace TestImpact diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactRuntime.cpp b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactRuntime.cpp index 57b6db1e8e..478b63e8b2 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactRuntime.cpp +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactRuntime.cpp @@ -34,13 +34,33 @@ namespace TestImpact { } - //! Returns the time elapsed (in milliseconds) since the timer was instantiated - AZStd::chrono::milliseconds Elapsed() + //! Returns the time point that the timer was instantiated. + AZStd::chrono::high_resolution_clock::time_point GetStartTimePoint() const + { + return m_startTime; + } + + //! Returns the time point that the timer was instantiated relative to the specified starting time point. + AZStd::chrono::high_resolution_clock::time_point GetStartTimePointRelative(const Timer& start) const + { + return AZStd::chrono::high_resolution_clock::time_point() + + AZStd::chrono::duration_cast(m_startTime - start.GetStartTimePoint()); + } + + //! Returns the time elapsed (in milliseconds) since the timer was instantiated. + AZStd::chrono::milliseconds GetElapsedMs() const { const auto endTime = AZStd::chrono::high_resolution_clock::now(); return AZStd::chrono::duration_cast(endTime - m_startTime); } + //! Returns the current time point relative to the time point the timer was instantiated. + AZStd::chrono::high_resolution_clock::time_point GetElapsedTimepoint() const + { + const auto endTime = AZStd::chrono::high_resolution_clock::now(); + return m_startTime + AZStd::chrono::duration_cast(endTime - m_startTime); + } + private: AZStd::chrono::high_resolution_clock::time_point m_startTime; }; @@ -49,8 +69,11 @@ namespace TestImpact class TestRunCompleteCallbackHandler { public: - TestRunCompleteCallbackHandler(AZStd::optional testCompleteCallback) - : m_testCompleteCallback(testCompleteCallback) + TestRunCompleteCallbackHandler( + size_t totalTests, + AZStd::optional testCompleteCallback) + : m_totalTests(totalTests) + , m_testCompleteCallback(testCompleteCallback) { } @@ -58,19 +81,27 @@ namespace TestImpact { if (m_testCompleteCallback.has_value()) { - (*m_testCompleteCallback) - (Client::TestRun(testJob.GetTestTarget()->GetName(), testJob.GetTestResult(), testJob.GetDuration())); + Client::TestRun testRun( + testJob.GetTestTarget()->GetName(), + testJob.GetCommandString(), + testJob.GetStartTime(), + testJob.GetDuration(), + testJob.GetTestResult()); + + (*m_testCompleteCallback)(testRun, ++m_numTestsCompleted, m_totalTests); } } private: + const size_t m_totalTests; //!< The total number of tests to run for the entire sequence. + size_t m_numTestsCompleted = 0; //!< The running total of tests that have completed. AZStd::optional m_testCompleteCallback; }; } //! Utility for concatenating two vectors. template - AZStd::vector ConcatenateVectors(const AZStd::vector& v1, const AZStd::vector& v2) + static AZStd::vector ConcatenateVectors(const AZStd::vector& v1, const AZStd::vector& v2) { AZStd::vector result; result.reserve(v1.size() + v2.size()); @@ -298,6 +329,7 @@ namespace TestImpact continue; } + // Add the sources covered by this test target to the coverage map for (const auto& source : job.GetTestCoverge().value().GetSourcesCovered()) { coverage[source.String()].insert(job.GetTestTarget()->GetName()); @@ -309,6 +341,7 @@ namespace TestImpact sourceCoveringTests.reserve(coverage.size()); for (auto&& [source, testTargets] : coverage) { + // Check to see whether this source is inside the repo or not (not a perfect check but weeds out the obvious non-repo sources) if (const auto sourcePath = RepoPath(source); sourcePath.IsRelativeTo(m_config.m_repo.m_root)) { @@ -353,17 +386,17 @@ namespace TestImpact } } - TestSequenceResult Runtime::RegularTestSequence( + Client::SequenceReport Runtime::RegularTestSequence( AZStd::optional testTargetTimeout, AZStd::optional globalTimeout, AZStd::optional testSequenceStartCallback, - AZStd::optional testSequenceEndCallback, + AZStd::optional> testSequenceEndCallback, AZStd::optional testCompleteCallback) { - Timer timer; + const Timer sequenceTimer; AZStd::vector includedTestTargets; AZStd::vector excludedTestTargets; - + // Separate the test targets into those that are excluded by either the test filter or exclusion list and those that are not for (const auto& testTarget : m_dynamicDependencyMap->GetTestTargetList().GetTargets()) { @@ -378,12 +411,17 @@ namespace TestImpact } } - // Sequence start callback + // Extract the client facing representation of selected test targets + const Client::TestRunSelection selectedTests(ExtractTestTargetNames(includedTestTargets), ExtractTestTargetNames(excludedTestTargets)); + + // Inform the client that the sequence is about to start if (testSequenceStartCallback.has_value()) { - (*testSequenceStartCallback)(Client::TestRunSelection(ExtractTestTargetNames(includedTestTargets), ExtractTestTargetNames(excludedTestTargets))); + (*testSequenceStartCallback)(m_suiteFilter, selectedTests); } + // Run the test targets and collect the test run results + const Timer testRunTimer; const auto [result, testJobs] = m_testEngine->RegularRun( includedTestTargets, m_testShardingPolicy, @@ -392,27 +430,124 @@ namespace TestImpact m_targetOutputCapture, testTargetTimeout, globalTimeout, - TestRunCompleteCallbackHandler(testCompleteCallback)); + TestRunCompleteCallbackHandler(includedTestTargets.size(), testCompleteCallback)); + const auto testRunDuration = testRunTimer.GetElapsedMs(); + // Generate the sequence report for the client + const auto sequenceReport = Client::SequenceReport( + m_suiteFilter, + selectedTests, + GenerateTestRunReport(result, testRunTimer.GetStartTimePointRelative(sequenceTimer), testRunDuration, testJobs)); + + // Inform the client that the sequence has ended if (testSequenceEndCallback.has_value()) { - (*testSequenceEndCallback)(GenerateSequenceFailureReport(testJobs), timer.Elapsed()); + (*testSequenceEndCallback)(sequenceReport); } - return result; + return sequenceReport; } - TestSequenceResult Runtime::ImpactAnalysisTestSequence( + //! Wrapper for the impact analysis test sequence to handle both the updating and non-updating policies through a common pathway. + //! @tparam TestRunnerFunctor The functor for running the specified tests. + //! @tparam TestJob The test engine job type returned by the functor. + //! @param suiteType The suite type used for this sequence. + //! @param timer The timer to use for the test run timings. + //! @param testRunner The test runner functor to use for each of the test runs. + //! @param includedSelectedTestTargets The subset of test targets that were selected to run and not also fully excluded from running. + //! @param excludedSelectedTestTargets The subset of test targets that were selected to run but were fully excluded running. + //! @param discardedTestTargets The subset of test targets that were discarded from the test selection and will not be run. + //! @param globalTimeout The maximum duration the entire test sequence may run for (infinite if empty). + //! @param testSequenceStartCallback The client function to be called after the test targets have been selected but prior to running the tests. + //! @param testSequenceCompleteCallback The client function to be called after the test sequence has completed. + //! @param testRunCompleteCallback The client function to be called after an individual test run has completed. + //! @param updateCoverage The function to call to update the dynamic dependency map with test coverage (if any). + template + Client::ImpactAnalysisSequenceReport ImpactAnalysisTestSequenceWrapper( + SuiteType suiteType, + const Timer& sequenceTimer, + const TestRunnerFunctor& testRunner, + const AZStd::vector& includedSelectedTestTargets, + const AZStd::vector& excludedSelectedTestTargets, + const AZStd::vector& discardedTestTargets, + const AZStd::vector& draftedTestTargets, + const AZStd::optional globalTimeout, + AZStd::optional testSequenceStartCallback, + AZStd::optional> testSequenceEndCallback, + AZStd::optional testCompleteCallback, + AZStd::optional& jobs)>> updateCoverage) + { + AZStd::optional sequenceTimeout = globalTimeout; + + // Extract the client facing representation of selected, discarded and drafted test targets + const Client::TestRunSelection selectedTests( + ExtractTestTargetNames(includedSelectedTestTargets), ExtractTestTargetNames(excludedSelectedTestTargets)); + const auto discardedTests = ExtractTestTargetNames(discardedTestTargets); + const auto draftedTests = ExtractTestTargetNames(draftedTestTargets); + + // Inform the client that the sequence is about to start + if (testSequenceStartCallback.has_value()) + { + (*testSequenceStartCallback)(suiteType, selectedTests, discardedTests, draftedTests); + } + + // We share the test run complete handler between the selected and drafted test runs as to present them together as one + // continuous test sequence to the client rather than two discrete test runs + const size_t totalNumTestRuns = includedSelectedTestTargets.size() + draftedTestTargets.size(); + TestRunCompleteCallbackHandler testRunCompleteHandler(totalNumTestRuns, testCompleteCallback); + + // Run the selected test targets and collect the test run results + const Timer selectedTestRunTimer; + const auto [selectedResult, selectedTestJobs] = testRunner(includedSelectedTestTargets, testRunCompleteHandler, globalTimeout); + const auto selectedTestRunDuration = selectedTestRunTimer.GetElapsedMs(); + + // Carry the remaining global sequence time over to the drafted test run + if (globalTimeout.has_value()) + { + const auto elapsed = selectedTestRunDuration; + sequenceTimeout = elapsed < globalTimeout.value() ? globalTimeout.value() - elapsed : AZStd::chrono::milliseconds(0); + } + + // Run the drafted test targets and collect the test run results + Timer draftedTestRunTimer; + const auto [draftedResult, draftedTestJobs] = testRunner(draftedTestTargets, testRunCompleteHandler, globalTimeout); + const auto draftedTestRunDuration = draftedTestRunTimer.GetElapsedMs(); + + // Generate the sequence report for the client + const auto sequenceReport = Client::ImpactAnalysisSequenceReport( + suiteType, + selectedTests, + discardedTests, + draftedTests, + GenerateTestRunReport(selectedResult, selectedTestRunTimer.GetStartTimePointRelative(sequenceTimer), selectedTestRunDuration, selectedTestJobs), + GenerateTestRunReport(draftedResult, draftedTestRunTimer.GetStartTimePointRelative(sequenceTimer), draftedTestRunDuration, draftedTestJobs)); + + // Inform the client that the sequence has ended + if (testSequenceEndCallback.has_value()) + { + (*testSequenceEndCallback)(sequenceReport); + } + + // Update the dynamic dependency map with the latest coverage data (if any) + if (updateCoverage.has_value()) + { + (*updateCoverage)(ConcatenateVectors(selectedTestJobs, draftedTestJobs)); + } + + return sequenceReport; + } + + Client::ImpactAnalysisSequenceReport Runtime::ImpactAnalysisTestSequence( const ChangeList& changeList, Policy::TestPrioritization testPrioritizationPolicy, Policy::DynamicDependencyMap dynamicDependencyMapPolicy, AZStd::optional testTargetTimeout, AZStd::optional globalTimeout, AZStd::optional testSequenceStartCallback, - AZStd::optional testSequenceEndCallback, + AZStd::optional> testSequenceEndCallback, AZStd::optional testCompleteCallback) { - Timer timer; + const Timer sequenceTimer; // Draft in the test targets that have no coverage entries in the dynamic dependency map AZStd::vector draftedTestTargets = m_dynamicDependencyMap->GetNotCoveringTests(); @@ -423,71 +558,94 @@ namespace TestImpact // The subset of selected test targets that are not on the configuration's exclude list and those that are auto [includedSelectedTestTargets, excludedSelectedTestTargets] = SelectTestTargetsByExcludeList(selectedTestTargets); - // We present to the client the included selected test targets and the drafted test targets as distinct sets but internally - // we consider the concatenated set of the two the actual set of tests to run - AZStd::vector testTargetsToRun = ConcatenateVectors(includedSelectedTestTargets, draftedTestTargets); - - if (testSequenceStartCallback.has_value()) + // Functor for running instrumented test targets + const auto instrumentedTestRun = + [this, &testTargetTimeout]( + const AZStd::vector& testsTargets, + TestRunCompleteCallbackHandler& testRunCompleteHandler, + AZStd::optional globalTimeout) { - (*testSequenceStartCallback)( - Client::TestRunSelection(ExtractTestTargetNames(includedSelectedTestTargets), ExtractTestTargetNames(excludedSelectedTestTargets)), - ExtractTestTargetNames(discardedTestTargets), - ExtractTestTargetNames(draftedTestTargets)); - } + return m_testEngine->InstrumentedRun( + testsTargets, + m_testShardingPolicy, + m_executionFailurePolicy, + m_integrationFailurePolicy, + m_testFailurePolicy, + m_targetOutputCapture, + testTargetTimeout, + globalTimeout, + AZStd::ref(testRunCompleteHandler)); + }; + + // Functor for running uninstrumented test targets + const auto regularTestRun = + [this, &testTargetTimeout]( + const AZStd::vector& testsTargets, + TestRunCompleteCallbackHandler& testRunCompleteHandler, + AZStd::optional globalTimeout) + { + return m_testEngine->RegularRun( + testsTargets, + m_testShardingPolicy, + m_executionFailurePolicy, + m_testFailurePolicy, + m_targetOutputCapture, + testTargetTimeout, + globalTimeout, + AZStd::ref(testRunCompleteHandler)); + }; if (dynamicDependencyMapPolicy == Policy::DynamicDependencyMap::Update) { - const auto [result, testJobs] = m_testEngine->InstrumentedRun( - testTargetsToRun, - m_testShardingPolicy, - m_executionFailurePolicy, - Policy::IntegrityFailure::Continue, - m_testFailurePolicy, - m_targetOutputCapture, - testTargetTimeout, - globalTimeout, - TestRunCompleteCallbackHandler(testCompleteCallback)); - - UpdateAndSerializeDynamicDependencyMap(testJobs); - - if (testSequenceEndCallback.has_value()) + AZStd::optional& jobs)>> updateCoverage = + [this](const AZStd::vector& jobs) { - (*testSequenceEndCallback)(GenerateSequenceFailureReport(testJobs), timer.Elapsed()); - } + UpdateAndSerializeDynamicDependencyMap(jobs); + }; - return result; + return ImpactAnalysisTestSequenceWrapper( + m_suiteFilter, + sequenceTimer, + instrumentedTestRun, + includedSelectedTestTargets, + excludedSelectedTestTargets, + discardedTestTargets, + draftedTestTargets, + globalTimeout, + testSequenceStartCallback, + testSequenceEndCallback, + testCompleteCallback, + updateCoverage); } else { - const auto [result, testJobs] = m_testEngine->RegularRun( - testTargetsToRun, - m_testShardingPolicy, - m_executionFailurePolicy, - m_testFailurePolicy, - m_targetOutputCapture, - testTargetTimeout, + return ImpactAnalysisTestSequenceWrapper( + m_suiteFilter, + sequenceTimer, + regularTestRun, + includedSelectedTestTargets, + excludedSelectedTestTargets, + discardedTestTargets, + draftedTestTargets, globalTimeout, - TestRunCompleteCallbackHandler(testCompleteCallback)); - - if (testSequenceEndCallback.has_value()) - { - (*testSequenceEndCallback)(GenerateSequenceFailureReport(testJobs), timer.Elapsed()); - } - - return result; + testSequenceStartCallback, + testSequenceEndCallback, + testCompleteCallback, + AZStd::optional& jobs)>>{ AZStd::nullopt }); } } - AZStd::pair Runtime::SafeImpactAnalysisTestSequence( + Client::SafeImpactAnalysisSequenceReport Runtime::SafeImpactAnalysisTestSequence( const ChangeList& changeList, Policy::TestPrioritization testPrioritizationPolicy, AZStd::optional testTargetTimeout, AZStd::optional globalTimeout, AZStd::optional testSequenceStartCallback, - AZStd::optional testSequenceEndCallback, + AZStd::optional> testSequenceEndCallback, AZStd::optional testCompleteCallback) { - Timer timer; + const Timer sequenceTimer; + auto sequenceTimeout = globalTimeout; // Draft in the test targets that have no coverage entries in the dynamic dependency map AZStd::vector draftedTestTargets = m_dynamicDependencyMap->GetNotCoveringTests(); @@ -501,40 +659,46 @@ namespace TestImpact // The subset of discarded test targets that are not on the configuration's exclude list and those that are auto [includedDiscardedTestTargets, excludedDiscardedTestTargets] = SelectTestTargetsByExcludeList(discardedTestTargets); - // We present to the client the included selected test targets and the drafted test targets as distinct sets but internally - // we consider the concatenated set of the two the actual set of tests to run - AZStd::vector testTargetsToRun = ConcatenateVectors(includedSelectedTestTargets, draftedTestTargets); + // Extract the client facing representation of selected, discarded and drafted test targets + const Client::TestRunSelection selectedTests( + ExtractTestTargetNames(includedSelectedTestTargets), ExtractTestTargetNames(excludedSelectedTestTargets)); + const Client::TestRunSelection discardedTests(ExtractTestTargetNames(includedDiscardedTestTargets), ExtractTestTargetNames(excludedDiscardedTestTargets)); + const auto draftedTests = ExtractTestTargetNames(draftedTestTargets); + // Inform the client that the sequence is about to start if (testSequenceStartCallback.has_value()) { - (*testSequenceStartCallback)( - Client::TestRunSelection(ExtractTestTargetNames(includedSelectedTestTargets), ExtractTestTargetNames(excludedSelectedTestTargets)), - Client::TestRunSelection(ExtractTestTargetNames(includedDiscardedTestTargets), ExtractTestTargetNames(excludedDiscardedTestTargets)), - ExtractTestTargetNames(draftedTestTargets)); + (*testSequenceStartCallback)(m_suiteFilter, selectedTests, discardedTests, draftedTests); } - // Impact analysis run of the selected test targets + // We share the test run complete handler between the selected, discarded and drafted test runs as to present them together as one + // continuous test sequence to the client rather than three discrete test runs + const size_t totalNumTestRuns = includedSelectedTestTargets.size() + draftedTestTargets.size() + includedDiscardedTestTargets.size(); + TestRunCompleteCallbackHandler testRunCompleteHandler(totalNumTestRuns, testCompleteCallback); + + // Run the selected test targets and collect the test run results + const Timer selectedTestRunTimer; const auto [selectedResult, selectedTestJobs] = m_testEngine->InstrumentedRun( - testTargetsToRun, + includedSelectedTestTargets, m_testShardingPolicy, m_executionFailurePolicy, - Policy::IntegrityFailure::Continue, + m_integrationFailurePolicy, m_testFailurePolicy, m_targetOutputCapture, testTargetTimeout, - globalTimeout, - TestRunCompleteCallbackHandler(testCompleteCallback)); - - const auto selectedDuraton = timer.Elapsed(); + sequenceTimeout, + AZStd::ref(testRunCompleteHandler)); + const auto selectedTestRunDuration = selectedTestRunTimer.GetElapsedMs(); // Carry the remaining global sequence time over to the discarded test run if (globalTimeout.has_value()) { - const auto elapsed = timer.Elapsed(); - globalTimeout = elapsed < globalTimeout.value() ? globalTimeout.value() - elapsed : AZStd::chrono::milliseconds(0); + const auto elapsed = selectedTestRunDuration; + sequenceTimeout = elapsed < globalTimeout.value() ? globalTimeout.value() - elapsed : AZStd::chrono::milliseconds(0); } - // Regular run of the discarded test targets + // Run the discarded test targets and collect the test run results + const Timer discardedTestRunTimer; const auto [discardedResult, discardedTestJobs] = m_testEngine->RegularRun( includedDiscardedTestTargets, m_testShardingPolicy, @@ -542,35 +706,63 @@ namespace TestImpact m_testFailurePolicy, m_targetOutputCapture, testTargetTimeout, - globalTimeout, - TestRunCompleteCallbackHandler(testCompleteCallback)); + sequenceTimeout, + AZStd::ref(testRunCompleteHandler)); + const auto discardedTestRunDuration = discardedTestRunTimer.GetElapsedMs(); - const auto discardedDuraton = timer.Elapsed(); - - if (testSequenceEndCallback.has_value()) + // Carry the remaining global sequence time over to the drafted test run + if (globalTimeout.has_value()) { - (*testSequenceEndCallback)( - GenerateSequenceFailureReport(selectedTestJobs), - GenerateSequenceFailureReport(discardedTestJobs), - selectedDuraton, - discardedDuraton); + const auto elapsed = selectedTestRunDuration + discardedTestRunDuration; + sequenceTimeout = elapsed < globalTimeout.value() ? globalTimeout.value() - elapsed : AZStd::chrono::milliseconds(0); } - UpdateAndSerializeDynamicDependencyMap(selectedTestJobs); - return { selectedResult, discardedResult }; + // Run the drafted test targets and collect the test run results + const Timer draftedTestRunTimer; + const auto [draftedResult, draftedTestJobs] = m_testEngine->InstrumentedRun( + draftedTestTargets, + m_testShardingPolicy, + m_executionFailurePolicy, + m_integrationFailurePolicy, + m_testFailurePolicy, + m_targetOutputCapture, + testTargetTimeout, + sequenceTimeout, + AZStd::ref(testRunCompleteHandler)); + const auto draftedTestRunDuration = draftedTestRunTimer.GetElapsedMs(); + + // Generate the sequence report for the client + const auto sequenceReport = Client::SafeImpactAnalysisSequenceReport( + m_suiteFilter, + selectedTests, + discardedTests, + draftedTests, + GenerateTestRunReport(selectedResult, selectedTestRunTimer.GetStartTimePointRelative(sequenceTimer), selectedTestRunDuration, selectedTestJobs), + GenerateTestRunReport(discardedResult, discardedTestRunTimer.GetStartTimePointRelative(sequenceTimer), discardedTestRunDuration, discardedTestJobs), + GenerateTestRunReport(draftedResult, draftedTestRunTimer.GetStartTimePointRelative(sequenceTimer), draftedTestRunDuration, draftedTestJobs)); + + // Inform the client that the sequence has ended + if (testSequenceEndCallback.has_value()) + { + (*testSequenceEndCallback)(sequenceReport); + } + + UpdateAndSerializeDynamicDependencyMap(ConcatenateVectors(selectedTestJobs, draftedTestJobs)); + return sequenceReport; } - TestSequenceResult Runtime::SeededTestSequence( + Client::SequenceReport Runtime::SeededTestSequence( AZStd::optional testTargetTimeout, AZStd::optional globalTimeout, AZStd::optional testSequenceStartCallback, - AZStd::optional testSequenceEndCallback, + AZStd::optional> testSequenceEndCallback, AZStd::optional testCompleteCallback) { - Timer timer; + const Timer sequenceTimer; AZStd::vector includedTestTargets; AZStd::vector excludedTestTargets; + // Separate the test targets into those that are excluded by either the test filter or exclusion list and those that are not for (const auto& testTarget : m_dynamicDependencyMap->GetTestTargetList().GetTargets()) { if (!m_testTargetExcludeList.contains(&testTarget)) @@ -583,31 +775,44 @@ namespace TestImpact } } + // Extract the client facing representation of selected test targets + Client::TestRunSelection selectedTests(ExtractTestTargetNames(includedTestTargets), ExtractTestTargetNames(excludedTestTargets)); + + // Inform the client that the sequence is about to start if (testSequenceStartCallback.has_value()) { - (*testSequenceStartCallback)(Client::TestRunSelection(ExtractTestTargetNames(includedTestTargets), ExtractTestTargetNames(excludedTestTargets))); + (*testSequenceStartCallback)(m_suiteFilter, selectedTests); } + // Run the test targets and collect the test run results + const Timer testRunTimer; const auto [result, testJobs] = m_testEngine->InstrumentedRun( includedTestTargets, m_testShardingPolicy, m_executionFailurePolicy, - Policy::IntegrityFailure::Continue, + m_integrationFailurePolicy, m_testFailurePolicy, m_targetOutputCapture, testTargetTimeout, globalTimeout, - TestRunCompleteCallbackHandler(testCompleteCallback)); + TestRunCompleteCallbackHandler(includedTestTargets.size(), testCompleteCallback)); + const auto testRunDuration = testRunTimer.GetElapsedMs(); + // Generate the sequence report for the client + const auto sequenceReport = Client::SequenceReport( + m_suiteFilter, + selectedTests, + GenerateTestRunReport(result, testRunTimer.GetStartTimePointRelative(sequenceTimer), testRunDuration, testJobs)); + + // Inform the client that the sequence has ended if (testSequenceEndCallback.has_value()) { - (*testSequenceEndCallback)(GenerateSequenceFailureReport(testJobs), timer.Elapsed()); + (*testSequenceEndCallback)(sequenceReport); } ClearDynamicDependencyMapAndRemoveExistingFile(); UpdateAndSerializeDynamicDependencyMap(testJobs); - - return result; + return sequenceReport; } bool Runtime::HasImpactAnalysisData() const diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactRuntimeUtils.cpp b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactRuntimeUtils.cpp index 10a77a2e58..0c61c5f426 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactRuntimeUtils.cpp +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactRuntimeUtils.cpp @@ -24,13 +24,13 @@ namespace TestImpact return TestTargetMetaMapFactory(masterTestListData, suiteFilter); } - AZStd::vector ReadBuildTargetDescriptorFiles(const BuildTargetDescriptorConfig& buildTargetDescriptorConfig) + AZStd::vector ReadBuildTargetDescriptorFiles(const BuildTargetDescriptorConfig& buildTargetDescriptorConfig) { - AZStd::vector buildTargetDescriptors; + AZStd::vector buildTargetDescriptors; for (const auto& buildTargetDescriptorFile : std::filesystem::directory_iterator(buildTargetDescriptorConfig.m_mappingDirectory.c_str())) { const auto buildTargetDescriptorContents = ReadFileContents(buildTargetDescriptorFile.path().string().c_str()); - auto buildTargetDescriptor = TestImpact::BuildTargetDescriptorFactory( + auto buildTargetDescriptor = BuildTargetDescriptorFactory( buildTargetDescriptorContents, buildTargetDescriptorConfig.m_staticInclusionFilters, buildTargetDescriptorConfig.m_inputInclusionFilters, @@ -41,7 +41,7 @@ namespace TestImpact return buildTargetDescriptors; } - AZStd::unique_ptr ConstructDynamicDependencyMap( + AZStd::unique_ptr ConstructDynamicDependencyMap( SuiteType suiteFilter, const BuildTargetDescriptorConfig& buildTargetDescriptorConfig, const TestTargetMetaConfig& testTargetMetaConfig) @@ -50,7 +50,7 @@ namespace TestImpact auto buildTargetDescriptors = ReadBuildTargetDescriptorFiles(buildTargetDescriptorConfig); auto buildTargets = CompileTargetDescriptors(AZStd::move(buildTargetDescriptors), AZStd::move(testTargetmetaMap)); auto&& [productionTargets, testTargets] = buildTargets; - return AZStd::make_unique(AZStd::move(productionTargets), AZStd::move(testTargets)); + return AZStd::make_unique(AZStd::move(productionTargets), AZStd::move(testTargets)); } AZStd::unordered_set ConstructTestTargetExcludeList( @@ -68,7 +68,7 @@ namespace TestImpact return testTargetExcludeList; } - AZStd::vector ExtractTestTargetNames(const AZStd::vector testTargets) + AZStd::vector ExtractTestTargetNames(const AZStd::vector& testTargets) { AZStd::vector testNames; AZStd::transform(testTargets.begin(), testTargets.end(), AZStd::back_inserter(testNames), [](const TestTarget* testTarget) diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactRuntimeUtils.h b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactRuntimeUtils.h index 608888726e..33e15bfd20 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactRuntimeUtils.h +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactRuntimeUtils.h @@ -10,7 +10,7 @@ #include #include -#include +#include #include #include @@ -25,7 +25,7 @@ namespace TestImpact { //! Construct a dynamic dependency map from the build target descriptors and test target metas. - AZStd::unique_ptr ConstructDynamicDependencyMap( + AZStd::unique_ptr ConstructDynamicDependencyMap( SuiteType suiteFilter, const BuildTargetDescriptorConfig& buildTargetDescriptorConfig, const TestTargetMetaConfig& testTargetMetaConfig); @@ -36,16 +36,17 @@ namespace TestImpact const AZStd::vector& excludedTestTargets); //! Extracts the name information from the specified test targets. - AZStd::vector ExtractTestTargetNames(const AZStd::vector testTargets); + AZStd::vector ExtractTestTargetNames(const AZStd::vector& testTargets); //! Generates a test run failure report from the specified test engine job information. //! @tparam TestJob The test engine job type. template - Client::TestRunFailure GenerateTestRunFailure(const TestJob& testJob) + AZStd::vector GenerateTestCaseFailures(const TestJob& testJob) { + AZStd::vector testCaseFailures; + if (testJob.GetTestRun().has_value()) { - AZStd::vector testCaseFailures; for (const auto& testSuite : testJob.GetTestRun()->GetTestSuites()) { AZStd::vector testFailures; @@ -56,57 +57,66 @@ namespace TestImpact testFailures.push_back(Client::TestFailure(testCase.m_name, "No error message retrieved")); } } - + if (!testFailures.empty()) { testCaseFailures.push_back(Client::TestCaseFailure(testSuite.m_name, AZStd::move(testFailures))); } } + } - return Client::TestRunFailure(Client::TestRunFailure(testJob.GetTestTarget()->GetName(), AZStd::move(testCaseFailures))); - } - else - { - return Client::TestRunFailure(testJob.GetTestTarget()->GetName(), { }); - } + return testCaseFailures; } - //! Generates a sequence failure report from the specified list of test engine jobs. - //! @tparam TestJob The test engine job type. template - Client::SequenceFailure GenerateSequenceFailureReport(const AZStd::vector& testJobs) + Client::TestRunReport GenerateTestRunReport( + TestSequenceResult result, + AZStd::chrono::high_resolution_clock::time_point startTime, + AZStd::chrono::milliseconds duration, + const AZStd::vector& testJobs) { - AZStd::vector executionFailures; - AZStd::vector testRunFailures; - AZStd::vector timedOutTestRuns; - AZStd::vector unexecutedTestRuns; - + AZStd::vector passingTests; + AZStd::vector failingTests; + AZStd::vector executionFailureTests; + AZStd::vector timedOutTests; + AZStd::vector unexecutedTests; + for (const auto& testJob : testJobs) { + // Test job start time relative to start time + const auto relativeStartTime = + AZStd::chrono::high_resolution_clock::time_point() + + AZStd::chrono::duration_cast(testJob.GetStartTime() - startTime); + + Client::TestRun clientTestRun( + testJob.GetTestTarget()->GetName(), testJob.GetCommandString(), relativeStartTime, testJob.GetDuration(), + testJob.GetTestResult()); + switch (testJob.GetTestResult()) { case Client::TestRunResult::FailedToExecute: { - executionFailures.push_back(Client::ExecutionFailure(testJob.GetTestTarget()->GetName(), testJob.GetCommandString())); + executionFailureTests.push_back(clientTestRun); break; } case Client::TestRunResult::NotRun: { - unexecutedTestRuns.push_back(testJob.GetTestTarget()->GetName()); + unexecutedTests.push_back(clientTestRun); break; } case Client::TestRunResult::Timeout: { - timedOutTestRuns.push_back(testJob.GetTestTarget()->GetName()); + timedOutTests.push_back(clientTestRun); break; } case Client::TestRunResult::AllTestsPass: { + passingTests.push_back(clientTestRun); break; } case Client::TestRunResult::TestFailures: { - testRunFailures.push_back(GenerateTestRunFailure(testJob)); + failingTests.emplace_back(AZStd::move(clientTestRun), GenerateTestCaseFailures(testJob)); break; } default: @@ -116,11 +126,15 @@ namespace TestImpact } } } - - return Client::SequenceFailure( - AZStd::move(executionFailures), - AZStd::move(testRunFailures), - AZStd::move(timedOutTestRuns), - AZStd::move(unexecutedTestRuns)); + + return Client::TestRunReport( + result, + startTime, + duration, + AZStd::move(passingTests), + AZStd::move(failingTests), + AZStd::move(executionFailureTests), + AZStd::move(timedOutTests), + AZStd::move(unexecutedTests)); } -} +} // namespace TestImpact diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/testimpactframework_runtime_files.cmake b/Code/Tools/TestImpactFramework/Runtime/Code/testimpactframework_runtime_files.cmake index 090bb68fcc..e28bb5ba7b 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/testimpactframework_runtime_files.cmake +++ b/Code/Tools/TestImpactFramework/Runtime/Code/testimpactframework_runtime_files.cmake @@ -19,7 +19,7 @@ set(FILES Include/TestImpactFramework/TestImpactTestSequence.h Include/TestImpactFramework/TestImpactClientTestSelection.h Include/TestImpactFramework/TestImpactClientTestRun.h - Include/TestImpactFramework/TestImpactClientFailureReport.h + Include/TestImpactFramework/TestImpactClientSequenceReport.h Include/TestImpactFramework/TestImpactFileUtils.h Source/Artifact/TestImpactArtifactException.h Source/Artifact/Factory/TestImpactBuildTargetDescriptorFactory.cpp @@ -123,7 +123,8 @@ set(FILES Source/TestImpactRuntimeUtils.h Source/TestImpactClientTestSelection.cpp Source/TestImpactClientTestRun.cpp - Source/TestImpactClientFailureReport.cpp + Source/TestImpactClientSequenceReport.cpp Source/TestImpactChangeListSerializer.cpp + Source/TestImpactChangeListSerializerInternal.h Source/TestImpactRepoPath.cpp ) From 522e284b3d684a5bb22287ce1f9f942b03a5ee23 Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Fri, 6 Aug 2021 12:27:27 -0700 Subject: [PATCH 164/803] fix for failing periodic test Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- ...nvasComponent_OnEntityActivatedDeactivated_PrintMessage.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/AutomatedTesting/Gem/PythonTests/scripting/ScriptCanvasComponent_OnEntityActivatedDeactivated_PrintMessage.py b/AutomatedTesting/Gem/PythonTests/scripting/ScriptCanvasComponent_OnEntityActivatedDeactivated_PrintMessage.py index b07a34dacd..097d3fb42d 100644 --- a/AutomatedTesting/Gem/PythonTests/scripting/ScriptCanvasComponent_OnEntityActivatedDeactivated_PrintMessage.py +++ b/AutomatedTesting/Gem/PythonTests/scripting/ScriptCanvasComponent_OnEntityActivatedDeactivated_PrintMessage.py @@ -93,11 +93,11 @@ def ScriptCanvasComponent_OnEntityActivatedDeactivated_PrintMessage(): if entity_dict["name"] == "Controller": sc_component.get_property_tree() sc_component.set_component_property_value( - "Properties|Variable Fields|Variables|[0]|Name,Value|Datum|Datum|EntityToActivate", + "Properties|Variables|EntityToActivate|Datum|Datum|value|EntityToActivate", entity_to_activate.id, ) sc_component.set_component_property_value( - "Properties|Variable Fields|Variables|[1]|Name,Value|Datum|Datum|EntityToDeactivate", + "Properties|Variables|EntityToDeactivate|Datum|Datum|value|EntityToDeactivate", entity_to_deactivate.id, ) return entity From 7b0118268c294f0c8f7d9337a6e8c8896e7824fb Mon Sep 17 00:00:00 2001 From: John Date: Fri, 6 Aug 2021 20:40:37 +0100 Subject: [PATCH 165/803] Remove missing header from cmake. Signed-off-by: John --- .../Runtime/Code/testimpactframework_runtime_files.cmake | 1 - 1 file changed, 1 deletion(-) diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/testimpactframework_runtime_files.cmake b/Code/Tools/TestImpactFramework/Runtime/Code/testimpactframework_runtime_files.cmake index e28bb5ba7b..76673d9f40 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/testimpactframework_runtime_files.cmake +++ b/Code/Tools/TestImpactFramework/Runtime/Code/testimpactframework_runtime_files.cmake @@ -125,6 +125,5 @@ set(FILES Source/TestImpactClientTestRun.cpp Source/TestImpactClientSequenceReport.cpp Source/TestImpactChangeListSerializer.cpp - Source/TestImpactChangeListSerializerInternal.h Source/TestImpactRepoPath.cpp ) From 6b2c9cbede6ade42081ca222aff56968b3a1b724 Mon Sep 17 00:00:00 2001 From: amzn-phist <52085794+amzn-phist@users.noreply.github.com> Date: Fri, 6 Aug 2021 16:23:01 -0500 Subject: [PATCH 166/803] Fix a crash when reloading AudioControlEditor controls (#2729) * Fix a crash when reloading ACE controls data The crash was due to destruction of xml_node that was held in a unique_ptr. Rapidxml has a very rudimentary memory allocation design, so in most cases dynamic allocations aren't even made. The memory_pool does all the cleanup in its destructor, so having a unique_ptr run its default_delete was causing the crash. Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com> * Fix numerical conversion warnings Wwise source files needed a few fixes for the numerical conversion warning changes that went in recently. Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com> --- .../Source/Engine/FileIOHandler_wwise.cpp | 8 +-- .../Code/Source/Editor/AudioControl.cpp | 2 +- .../Code/Source/Editor/AudioControl.h | 50 ++++++++++--------- .../Source/Editor/AudioControlsLoader.cpp | 8 +-- .../Source/Editor/AudioControlsWriter.cpp | 6 +-- 5 files changed, 38 insertions(+), 36 deletions(-) diff --git a/Gems/AudioEngineWwise/Code/Source/Engine/FileIOHandler_wwise.cpp b/Gems/AudioEngineWwise/Code/Source/Engine/FileIOHandler_wwise.cpp index 9571dd86a9..30084565d6 100644 --- a/Gems/AudioEngineWwise/Code/Source/Engine/FileIOHandler_wwise.cpp +++ b/Gems/AudioEngineWwise/Code/Source/Engine/FileIOHandler_wwise.cpp @@ -69,7 +69,7 @@ namespace Audio AkDeviceSettings deviceSettings; AK::StreamMgr::GetDefaultDeviceSettings(deviceSettings); - deviceSettings.uIOMemorySize = poolSize; + deviceSettings.uIOMemorySize = aznumeric_cast(poolSize); deviceSettings.uSchedulerTypeFlags = AK_SCHEDULER_BLOCKING; Platform::SetThreadProperties(deviceSettings.threadProperties); @@ -198,7 +198,7 @@ namespace Audio deviceDesc.bCanWrite = true; deviceDesc.deviceID = m_deviceID; AK_CHAR_TO_UTF16(deviceDesc.szDeviceName, "IO::IArchive", AZ_ARRAY_SIZE(deviceDesc.szDeviceName)); - deviceDesc.uStringSize = AKPLATFORM::AkUtf16StrLen(deviceDesc.szDeviceName); + deviceDesc.uStringSize = aznumeric_cast(AKPLATFORM::AkUtf16StrLen(deviceDesc.szDeviceName)); } AkUInt32 CBlockingDevice_wwise::GetDeviceData() @@ -219,7 +219,7 @@ namespace Audio AkDeviceSettings deviceSettings; AK::StreamMgr::GetDefaultDeviceSettings(deviceSettings); - deviceSettings.uIOMemorySize = poolSize; + deviceSettings.uIOMemorySize = aznumeric_cast(poolSize); deviceSettings.uSchedulerTypeFlags = AK_SCHEDULER_DEFERRED_LINED_UP; Platform::SetThreadProperties(deviceSettings.threadProperties); @@ -336,7 +336,7 @@ namespace Audio deviceDesc.bCanWrite = false; deviceDesc.deviceID = m_deviceID; AK_CHAR_TO_UTF16(deviceDesc.szDeviceName, "IO::IStreamer", AZ_ARRAY_SIZE(deviceDesc.szDeviceName)); - deviceDesc.uStringSize = AKPLATFORM::AkUtf16StrLen(deviceDesc.szDeviceName); + deviceDesc.uStringSize = aznumeric_cast(AKPLATFORM::AkUtf16StrLen(deviceDesc.szDeviceName)); } AkUInt32 CStreamingDevice_wwise::GetDeviceData() diff --git a/Gems/AudioSystem/Code/Source/Editor/AudioControl.cpp b/Gems/AudioSystem/Code/Source/Editor/AudioControl.cpp index ce268022a8..c0a8fb8dde 100644 --- a/Gems/AudioSystem/Code/Source/Editor/AudioControl.cpp +++ b/Gems/AudioSystem/Code/Source/Editor/AudioControl.cpp @@ -345,7 +345,7 @@ namespace AudioControls { for (auto& connectionNode : m_connectionNodes) { - if (TConnectionPtr connection = audioSystemImpl->CreateConnectionFromXMLNode(connectionNode.m_xmlNode.get(), m_type)) + if (TConnectionPtr connection = audioSystemImpl->CreateConnectionFromXMLNode(connectionNode.m_xmlNode, m_type)) { AddConnection(connection); connectionNode.m_isValid = true; diff --git a/Gems/AudioSystem/Code/Source/Editor/AudioControl.h b/Gems/AudioSystem/Code/Source/Editor/AudioControl.h index 37e67c815c..024e8eb6df 100644 --- a/Gems/AudioSystem/Code/Source/Editor/AudioControl.h +++ b/Gems/AudioSystem/Code/Source/Editor/AudioControl.h @@ -25,46 +25,48 @@ namespace AudioControls { SRawConnectionData(AZ::rapidxml::xml_node* node, bool isValid) { - m_xmlNode = AZStd::move(DeepCopyNode(node)); + m_xmlNode = DeepCopyNode(node); m_isValid = isValid; } - AZStd::unique_ptr> m_xmlNode{}; + AZ::rapidxml::xml_node* m_xmlNode = nullptr; // indicates if the connection is valid for the currently loaded middleware bool m_isValid{ false }; + private: // Rapid XML provides a 'clone_node' utility that will copy an entire node tree, // but it only copies pointers of any strings in the node names and values. - // This causes problems with storing raw xml nodes as this class does because strings - // will be pointing into the memory pool of an xml document that has gone out of scope. + // This causes problems with storage of xml trees, as this class does, because strings + // will be pointing into an xml document's file buffer that has gone out of scope. // This function is a rewritten version of 'clone_node' that does the deep copy of strings // into the new destination tree. - [[nodiscard]] static AZStd::unique_ptr> DeepCopyNode(AZ::rapidxml::xml_node* srcNode) + [[nodiscard]] AZ::rapidxml::xml_node* DeepCopyNode(AZ::rapidxml::xml_node* srcNode) { - AZStd::unique_ptr> destNode; - if (srcNode) + if (!srcNode) { - XmlAllocator& xmlAlloc(AudioControls::s_xmlAllocator); - destNode.reset(xmlAlloc.allocate_node(srcNode->type())); + return nullptr; + } - destNode->name(xmlAlloc.allocate_string(srcNode->name(), srcNode->name_size()), srcNode->name_size()); - destNode->value(xmlAlloc.allocate_string(srcNode->value(), srcNode->value_size()), srcNode->value_size()); + XmlAllocator& xmlAlloc(AudioControls::s_xmlAllocator); + AZ::rapidxml::xml_node* destNode = xmlAlloc.allocate_node(srcNode->type()); - for (AZ::rapidxml::xml_node* child = srcNode->first_node(); child != nullptr; child = child->next_sibling()) - { - destNode->append_node(DeepCopyNode(child).release()); - } + destNode->name(xmlAlloc.allocate_string(srcNode->name(), srcNode->name_size()), srcNode->name_size()); + destNode->value(xmlAlloc.allocate_string(srcNode->value(), srcNode->value_size()), srcNode->value_size()); - for (AZ::rapidxml::xml_attribute* attr = srcNode->first_attribute(); attr != nullptr; attr = attr->next_attribute()) - { - destNode->append_attribute(xmlAlloc.allocate_attribute( - xmlAlloc.allocate_string(attr->name(), attr->name_size()), - xmlAlloc.allocate_string(attr->value(), attr->value_size()), - attr->name_size(), - attr->value_size() - )); - } + for (AZ::rapidxml::xml_node* child = srcNode->first_node(); child != nullptr; child = child->next_sibling()) + { + destNode->append_node(DeepCopyNode(child)); + } + + for (AZ::rapidxml::xml_attribute* attr = srcNode->first_attribute(); attr != nullptr; attr = attr->next_attribute()) + { + destNode->append_attribute(xmlAlloc.allocate_attribute( + xmlAlloc.allocate_string(attr->name(), attr->name_size()), + xmlAlloc.allocate_string(attr->value(), attr->value_size()), + attr->name_size(), + attr->value_size() + )); } return destNode; diff --git a/Gems/AudioSystem/Code/Source/Editor/AudioControlsLoader.cpp b/Gems/AudioSystem/Code/Source/Editor/AudioControlsLoader.cpp index 220cd32b5c..30889e33f0 100644 --- a/Gems/AudioSystem/Code/Source/Editor/AudioControlsLoader.cpp +++ b/Gems/AudioSystem/Code/Source/Editor/AudioControlsLoader.cpp @@ -475,7 +475,7 @@ namespace AudioControls control->AddConnection(connection); } - control->m_connectionNodes.push_back(SRawConnectionData(childNode, connection != nullptr)); + control->m_connectionNodes.emplace_back(childNode, connection != nullptr); childNode = childNode->next_sibling(); } @@ -517,7 +517,7 @@ namespace AudioControls { control->AddConnection(connection); } - control->m_connectionNodes.push_back(SRawConnectionData(connectionNode, connection != nullptr)); + control->m_connectionNodes.emplace_back(connectionNode, connection != nullptr); connectionNode = connectionNode->next_sibling(); } configGroupNode = configGroupNode->next_sibling(); @@ -534,7 +534,7 @@ namespace AudioControls { control->AddConnection(connection); } - control->m_connectionNodes.push_back(SRawConnectionData(connectionNode, connection != nullptr)); + control->m_connectionNodes.emplace_back(connectionNode, connection != nullptr); connectionNode = connectionNode->next_sibling(); } } @@ -576,7 +576,7 @@ namespace AudioControls requestNode->append_node(valueNode); - childControl->m_connectionNodes.push_back(SRawConnectionData(requestNode, false)); + childControl->m_connectionNodes.emplace_back(requestNode, false); return childControl; } diff --git a/Gems/AudioSystem/Code/Source/Editor/AudioControlsWriter.cpp b/Gems/AudioSystem/Code/Source/Editor/AudioControlsWriter.cpp index 91f9aa5138..eb022b706f 100644 --- a/Gems/AudioSystem/Code/Source/Editor/AudioControlsWriter.cpp +++ b/Gems/AudioSystem/Code/Source/Editor/AudioControlsWriter.cpp @@ -356,8 +356,8 @@ namespace AudioControls { if (!connectionNode.m_isValid) { - auto nodeCopy = SRawConnectionData::DeepCopyNode(connectionNode.m_xmlNode.get()); - node->append_node(nodeCopy.release()); + XmlAllocator& xmlAlloc(AudioControls::s_xmlAllocator); + node->append_node(xmlAlloc.clone_node(connectionNode.m_xmlNode)); } } @@ -371,7 +371,7 @@ namespace AudioControls childNode != nullptr) { node->append_node(childNode); - control->m_connectionNodes.push_back(SRawConnectionData(childNode, true)); + control->m_connectionNodes.emplace_back(childNode, true); } } } From d6744690ee281aeda4dfc0759412d2711db13a98 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 6 Aug 2021 15:10:21 -0700 Subject: [PATCH 167/803] platform.h cleanup Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Editor/Include/IObjectManager.h | 1 + Code/Editor/Objects/ObjectLoader.h | 2 + .../PerforcePlugin/PerforceSourceControl.cpp | 1 + Code/Legacy/CryCommon/AndroidSpecific.h | 1 - Code/Legacy/CryCommon/AppleSpecific.h | 7 - Code/Legacy/CryCommon/BitFiddling.h | 11 - Code/Legacy/CryCommon/CryArray.h | 18 +- Code/Legacy/CryCommon/CryAssert.h | 3 +- Code/Legacy/CryCommon/CrySizer.h | 4 +- .../Legacy/CryCommon/CryThreadImpl_pthreads.h | 8 +- Code/Legacy/CryCommon/CryThreadImpl_windows.h | 2 +- Code/Legacy/CryCommon/CryThread_pthreads.h | 2 +- Code/Legacy/CryCommon/CryThread_windows.h | 2 +- Code/Legacy/CryCommon/IFunctorBase.h | 1 + Code/Legacy/CryCommon/IMaterial.h | 1 + Code/Legacy/CryCommon/ISystem.h | 2 +- Code/Legacy/CryCommon/Linux32Specific.h | 1 - Code/Legacy/CryCommon/Linux64Specific.h | 1 - Code/Legacy/CryCommon/LinuxSpecific.h | 17 - Code/Legacy/CryCommon/MTPseudoRandom.cpp | 2 +- Code/Legacy/CryCommon/ProjectDefines.h | 186 ++----- Code/Legacy/CryCommon/Win32specific.h | 1 - Code/Legacy/CryCommon/Win64specific.h | 1 - Code/Legacy/CryCommon/WinBase.cpp | 41 -- Code/Legacy/CryCommon/platform.h | 477 ++---------------- Code/Legacy/CryCommon/platform_impl.cpp | 53 -- Code/Legacy/CryCommon/smartptr.h | 13 +- Code/Legacy/CrySystem/IDebugCallStack.cpp | 2 +- Code/Legacy/CrySystem/SystemInit.cpp | 2 +- Code/Legacy/CrySystem/SystemWin32.cpp | 39 +- .../CrySystem/ViewSystem/ViewSystem.cpp | 2 +- Code/Legacy/CrySystem/XML/xml.cpp | 2 +- .../Source/Animation/UiAnimationSystem.cpp | 8 +- Gems/Maestro/Code/Source/Cinematics/Movie.cpp | 8 +- 34 files changed, 145 insertions(+), 777 deletions(-) diff --git a/Code/Editor/Include/IObjectManager.h b/Code/Editor/Include/IObjectManager.h index ce9d69681b..efc1955a56 100644 --- a/Code/Editor/Include/IObjectManager.h +++ b/Code/Editor/Include/IObjectManager.h @@ -14,6 +14,7 @@ #include #include #include +#include // forward declarations. class CEntityObject; diff --git a/Code/Editor/Objects/ObjectLoader.h b/Code/Editor/Objects/ObjectLoader.h index ccfaeb78f0..fc526970dd 100644 --- a/Code/Editor/Objects/ObjectLoader.h +++ b/Code/Editor/Objects/ObjectLoader.h @@ -15,6 +15,8 @@ #include "Util/GuidUtil.h" #include "ErrorReport.h" +#include + class CPakFile; class CErrorRecord; struct IObjectManager; diff --git a/Code/Editor/Plugins/PerforcePlugin/PerforceSourceControl.cpp b/Code/Editor/Plugins/PerforcePlugin/PerforceSourceControl.cpp index 581f9a576d..1ea70e8c22 100644 --- a/Code/Editor/Plugins/PerforcePlugin/PerforceSourceControl.cpp +++ b/Code/Editor/Plugins/PerforcePlugin/PerforceSourceControl.cpp @@ -9,6 +9,7 @@ #include "CryFile.h" #include "PerforceSourceControl.h" #include "PasswordDlg.h" +#include #include #include diff --git a/Code/Legacy/CryCommon/AndroidSpecific.h b/Code/Legacy/CryCommon/AndroidSpecific.h index 0cb4a6786c..a0f57553ca 100644 --- a/Code/Legacy/CryCommon/AndroidSpecific.h +++ b/Code/Legacy/CryCommon/AndroidSpecific.h @@ -35,7 +35,6 @@ // to what some structs/classes need. #define CRY_FORCE_MALLOC_NEW_ALIGN -#define DEBUG_BREAK raise(SIGTRAP) #define RC_EXECUTABLE "rc" #define USE_CRT 1 #define SIZEOF_PTR 4 diff --git a/Code/Legacy/CryCommon/AppleSpecific.h b/Code/Legacy/CryCommon/AppleSpecific.h index 4d17c18bac..ed76de8986 100644 --- a/Code/Legacy/CryCommon/AppleSpecific.h +++ b/Code/Legacy/CryCommon/AppleSpecific.h @@ -18,7 +18,6 @@ #endif -#define DEBUG_BREAK __builtin_trap() #define RC_EXECUTABLE "rc" ////////////////////////////////////////////////////////////////////////// @@ -52,12 +51,6 @@ #define __COUNTER__ __LINE__ #endif -#ifdef __FUNC__ -#undef __FUNC__ -#endif - -#define __FUNC__ __func__ - typedef void* LPVOID; #define VOID void #define PVOID void* diff --git a/Code/Legacy/CryCommon/BitFiddling.h b/Code/Legacy/CryCommon/BitFiddling.h index 901dd0a49a..342aad9a82 100644 --- a/Code/Legacy/CryCommon/BitFiddling.h +++ b/Code/Legacy/CryCommon/BitFiddling.h @@ -36,7 +36,6 @@ ILINE uint32 countLeadingZeros32(uint32 x) { DWORD result = 32 ^ 31; // assumes result is unmodified if _BitScanReverse returns 0 _BitScanReverse(&result, x); - PREFAST_SUPPRESS_WARNING(6102); result ^= 31; // needed because the index is from LSB (whereas all other implementations are from MSB) return result; } @@ -73,16 +72,6 @@ inline bool IsPowerOfTwo(TInteger x) return (x & (x - 1)) == 0; } -// compile time version of IsPowerOfTwo, useful for STATIC_CHECK -template -struct IsPowerOfTwoCompileTime -{ - enum - { - IsPowerOfTwo = ((nValue & (nValue - 1)) == 0) - }; -}; - inline uint32 NextPower2(uint32 n) { n--; diff --git a/Code/Legacy/CryCommon/CryArray.h b/Code/Legacy/CryCommon/CryArray.h index b304df28af..5b4684fdd2 100644 --- a/Code/Legacy/CryCommon/CryArray.h +++ b/Code/Legacy/CryCommon/CryArray.h @@ -15,24 +15,10 @@ //--------------------------------------------------------------------------- // Convenient iteration macros -#define for_iter(IT, it, b, e) for (IT it = (b), _e = (e); it != _e; ++it) -#define for_container(CT, it, cont) for_iter (CT::iterator, it, (cont).begin(), (cont).end()) #define for_ptr(T, it, b, e) for (T* it = (b), * _e = (e); it != _e; ++it) -#define for_array_ptr(T, it, arr) for_ptr (T, it, (arr).begin(), (arr).end()) - -#define for_array(i, arr) for (int i = 0, _e = (arr).size(); i < _e; i++) -#define for_all(cont) for_array (_i, cont) cont[_i] - -//--------------------------------------------------------------------------- -// Stack array helper -#define ALIGNED_STACK_ARRAY(T, name, size, alignment) \ - PREFAST_SUPPRESS_WARNING(6255) \ - T * name = (T*) alloca((size) * sizeof(T) + alignment - 1); \ - name = Align(name, alignment); - -#define STACK_ARRAY(T, name, size) \ - ALIGNED_STACK_ARRAY(T, name, size, alignof(T)) \ +#define for_array_ptr(T, it, arr) for_ptr (T, it, (arr).begin(), (arr).end()) +#define for_array(i, arr) for (int i = 0, _e = (arr).size(); i < _e; i++) //--------------------------------------------------------------------------- // Specify semantics for moving objects. diff --git a/Code/Legacy/CryCommon/CryAssert.h b/Code/Legacy/CryCommon/CryAssert.h index 1cb5d37c43..1494654d87 100644 --- a/Code/Legacy/CryCommon/CryAssert.h +++ b/Code/Legacy/CryCommon/CryAssert.h @@ -71,7 +71,6 @@ #if defined(USE_CRY_ASSERT) && CRYASSERT_H_TRAIT_USE_CRY_ASSERT_MESSAGE void CryAssertTrace(const char*, ...); bool CryAssert(const char*, const char*, unsigned int, bool*); -void CryDebugBreak(); #define CRY_ASSERT(condition) CRY_ASSERT_MESSAGE(condition, NULL) @@ -86,7 +85,7 @@ void CryDebugBreak(); CryAssertTrace parenthese_message; \ if (CryAssert(#condition, __FILE__, __LINE__, &s_bIgnoreAssert)) \ { \ - DEBUG_BREAK; \ + AZ::Debug::Trace::Break(); \ } \ } \ } while (0) diff --git a/Code/Legacy/CryCommon/CrySizer.h b/Code/Legacy/CryCommon/CrySizer.h index 9301360bd5..583de5bee8 100644 --- a/Code/Legacy/CryCommon/CrySizer.h +++ b/Code/Legacy/CryCommon/CrySizer.h @@ -581,7 +581,7 @@ protected: // use this to push (and automatically pop) the sizer component name at the beginning of the // getSize() function -#define SIZER_COMPONENT_NAME(pSizerPointer, szComponentName) PREFAST_SUPPRESS_WARNING(6246) CrySizerComponentNameHelper AZ_JOIN(sizerHelper, __LINE__)(pSizerPointer, szComponentName, false) -#define SIZER_SUBCOMPONENT_NAME(pSizerPointer, szComponentName) PREFAST_SUPPRESS_WARNING(6246) CrySizerComponentNameHelper AZ_JOIN(sizerHelper, __LINE__)(pSizerPointer, szComponentName, true) +#define SIZER_COMPONENT_NAME(pSizerPointer, szComponentName) CrySizerComponentNameHelper AZ_JOIN(sizerHelper, __LINE__)(pSizerPointer, szComponentName, false) +#define SIZER_SUBCOMPONENT_NAME(pSizerPointer, szComponentName) CrySizerComponentNameHelper AZ_JOIN(sizerHelper, __LINE__)(pSizerPointer, szComponentName, true) #endif // CRYINCLUDE_CRYCOMMON_CRYSIZER_H diff --git a/Code/Legacy/CryCommon/CryThreadImpl_pthreads.h b/Code/Legacy/CryCommon/CryThreadImpl_pthreads.h index c94d4fca90..c3dee7339f 100644 --- a/Code/Legacy/CryCommon/CryThreadImpl_pthreads.h +++ b/Code/Legacy/CryCommon/CryThreadImpl_pthreads.h @@ -14,13 +14,7 @@ #include "CryThread_pthreads.h" -#if PLATFORM_SUPPORTS_THREADLOCAL -THREADLOCAL CrySimpleThreadSelf -* CrySimpleThreadSelf::m_Self = NULL; -#else -TLS_DEFINE(CrySimpleThreadSelf*, g_CrySimpleThreadSelf) -#endif - +AZ_THREAD_LOCAL CrySimpleThreadSelf* CrySimpleThreadSelf::m_Self = NULL; ////////////////////////////////////////////////////////////////////////// // CryEvent(Timed) implementation diff --git a/Code/Legacy/CryCommon/CryThreadImpl_windows.h b/Code/Legacy/CryCommon/CryThreadImpl_windows.h index 5cf970414d..4ddbaedac5 100644 --- a/Code/Legacy/CryCommon/CryThreadImpl_windows.h +++ b/Code/Legacy/CryCommon/CryThreadImpl_windows.h @@ -20,7 +20,7 @@ struct SThreadNameDesc DWORD dwFlags; }; -THREADLOCAL CrySimpleThreadSelf* CrySimpleThreadSelf::m_Self = NULL; +AZ_THREAD_LOCAL CrySimpleThreadSelf* CrySimpleThreadSelf::m_Self = NULL; ////////////////////////////////////////////////////////////////////////// CryEvent::CryEvent() diff --git a/Code/Legacy/CryCommon/CryThread_pthreads.h b/Code/Legacy/CryCommon/CryThread_pthreads.h index 72b29344ec..2c6b389dbb 100644 --- a/Code/Legacy/CryCommon/CryThread_pthreads.h +++ b/Code/Legacy/CryCommon/CryThread_pthreads.h @@ -672,7 +672,7 @@ protected: m_Self = pSelf; } private: - static THREADLOCAL CrySimpleThreadSelf* m_Self; + static AZ_THREAD_LOCAL CrySimpleThreadSelf* m_Self; #else diff --git a/Code/Legacy/CryCommon/CryThread_windows.h b/Code/Legacy/CryCommon/CryThread_windows.h index cc09cc530b..98517133c1 100644 --- a/Code/Legacy/CryCommon/CryThread_windows.h +++ b/Code/Legacy/CryCommon/CryThread_windows.h @@ -189,7 +189,7 @@ public: virtual ~CrySimpleThreadSelf(); protected: void StartThread(unsigned (__stdcall * func)(void*), void* argList); - static THREADLOCAL CrySimpleThreadSelf* m_Self; + static AZ_THREAD_LOCAL CrySimpleThreadSelf* m_Self; private: CrySimpleThreadSelf(const CrySimpleThreadSelf&); CrySimpleThreadSelf& operator = (const CrySimpleThreadSelf&); diff --git a/Code/Legacy/CryCommon/IFunctorBase.h b/Code/Legacy/CryCommon/IFunctorBase.h index 2a8af50d33..1ac37a0e47 100644 --- a/Code/Legacy/CryCommon/IFunctorBase.h +++ b/Code/Legacy/CryCommon/IFunctorBase.h @@ -14,6 +14,7 @@ #define CRYINCLUDE_CRYCOMMON_IFUNCTORBASE_H #pragma once +#include // Base class for functor storage. // Not intended for direct usage. diff --git a/Code/Legacy/CryCommon/IMaterial.h b/Code/Legacy/CryCommon/IMaterial.h index 1faee0eef9..f1967324d8 100644 --- a/Code/Legacy/CryCommon/IMaterial.h +++ b/Code/Legacy/CryCommon/IMaterial.h @@ -37,6 +37,7 @@ struct IRenderMesh; #include #include #include +#include #ifdef MAX_SUB_MATERIALS // This checks that the values are in sync in the different files. diff --git a/Code/Legacy/CryCommon/ISystem.h b/Code/Legacy/CryCommon/ISystem.h index d934995b4d..7cea690687 100644 --- a/Code/Legacy/CryCommon/ISystem.h +++ b/Code/Legacy/CryCommon/ISystem.h @@ -1419,7 +1419,7 @@ namespace Detail } DummyStaticInstance; \ if (!(gEnv->pConsole != 0 ? gEnv->pConsole->Register(&DummyStaticInstance) : 0)) \ { \ - DEBUG_BREAK; \ + AZ::Debug::Trace::Break(); \ CryFatalError("Can not register dummy CVar"); \ } \ } while (0) diff --git a/Code/Legacy/CryCommon/Linux32Specific.h b/Code/Legacy/CryCommon/Linux32Specific.h index b3f06a80b7..e66838f431 100644 --- a/Code/Legacy/CryCommon/Linux32Specific.h +++ b/Code/Legacy/CryCommon/Linux32Specific.h @@ -18,7 +18,6 @@ #define _CPU_X86 //#define _CPU_SSE -#define DEBUG_BREAK raise(SIGTRAP) #define RC_EXECUTABLE "rc" #define USE_CRT 1 #define SIZEOF_PTR 4 diff --git a/Code/Legacy/CryCommon/Linux64Specific.h b/Code/Legacy/CryCommon/Linux64Specific.h index 11b526ee4b..0aa9321025 100644 --- a/Code/Legacy/CryCommon/Linux64Specific.h +++ b/Code/Legacy/CryCommon/Linux64Specific.h @@ -20,7 +20,6 @@ #define _CPU_AMD64 #define _CPU_SSE -#define DEBUG_BREAK ::raise(SIGTRAP) #define RC_EXECUTABLE "rc" #define USE_CRT 1 #define SIZEOF_PTR 8 diff --git a/Code/Legacy/CryCommon/LinuxSpecific.h b/Code/Legacy/CryCommon/LinuxSpecific.h index 5fc1f7b801..cbffae5957 100644 --- a/Code/Legacy/CryCommon/LinuxSpecific.h +++ b/Code/Legacy/CryCommon/LinuxSpecific.h @@ -42,23 +42,6 @@ #include #include -#ifdef __FUNC__ -#undef __FUNC__ -#endif -#if defined(__GNUC__) || defined(__clang__) -#define __FUNC__ __func__ -#else -#define __FUNC__ \ - ({ \ - static char __f[sizeof(__PRETTY_FUNCTION__) + 1]; \ - strcpy(__f, __PRETTY_FUNCTION__); \ - char* __p = (char*)strchr(__f, '('); \ - *__p = 0; \ - while (*(__p) != ' ' && __p != (__f - 1)) {--__p; } \ - (__p + 1); \ - }) -#endif - typedef void* LPVOID; #define VOID void #define PVOID void* diff --git a/Code/Legacy/CryCommon/MTPseudoRandom.cpp b/Code/Legacy/CryCommon/MTPseudoRandom.cpp index 6f163e682f..f8a3950ff0 100644 --- a/Code/Legacy/CryCommon/MTPseudoRandom.cpp +++ b/Code/Legacy/CryCommon/MTPseudoRandom.cpp @@ -63,7 +63,7 @@ void CMTRand_int32::seed(const uint32* array, int size) // init by array } for (int k = n - 1; k; --k) { - PREFAST_SUPPRESS_WARNING(6385) PREFAST_SUPPRESS_WARNING(6386) m_nState[i] = (m_nState[i] ^ ((m_nState[i - 1] ^ (m_nState[i - 1] >> 30)) * 1566083941UL)) - i; + m_nState[i] = (m_nState[i] ^ ((m_nState[i - 1] ^ (m_nState[i - 1] >> 30)) * 1566083941UL)) - i; if ((++i) == n) { m_nState[0] = m_nState[n - 1]; diff --git a/Code/Legacy/CryCommon/ProjectDefines.h b/Code/Legacy/CryCommon/ProjectDefines.h index 3d635c491c..eda5bb8b5f 100644 --- a/Code/Legacy/CryCommon/ProjectDefines.h +++ b/Code/Legacy/CryCommon/ProjectDefines.h @@ -16,10 +16,6 @@ #include "BaseTypes.h" #include -#if defined(_RELEASE) && !defined(RELEASE) - #define RELEASE -#endif - // Section dictionary #if defined(AZ_RESTRICTED_PLATFORM) #define PROJECTDEFINES_H_SECTION_STATS_AGENT 1 @@ -31,57 +27,51 @@ #define AZ_RESTRICTED_SECTION PROJECTDEFINES_H_SECTION_STATS_AGENT #include AZ_RESTRICTED_FILE(ProjectDefines_h) #elif defined(WIN32) || defined(WIN64) -#if !defined(_RELEASE) || defined(PERFORMANCE_BUILD) -#define ENABLE_STATS_AGENT -#endif + #if !defined(_RELEASE) || defined(PERFORMANCE_BUILD) + #define ENABLE_STATS_AGENT + #endif #endif -// The following definitions are used by Sandbox and RC to determine which platform support is needed -#define TOOLS_SUPPORT_POWERVR -#define TOOLS_SUPPORT_ETC2COMP // Type used for vertex indices // WARNING: If you change this typedef, you need to update AssetProcessorPlatformConfig.ini to convert cgf and abc files to the proper index format. #if defined(RESOURCE_COMPILER) -typedef uint32 vtx_idx; -#define AZ_RESTRICTED_SECTION_IMPLEMENTED + typedef uint32 vtx_idx; + #define AZ_RESTRICTED_SECTION_IMPLEMENTED #elif defined(MOBILE) -typedef uint16 vtx_idx; -#define AZ_RESTRICTED_SECTION_IMPLEMENTED + typedef uint16 vtx_idx; + #define AZ_RESTRICTED_SECTION_IMPLEMENTED #elif defined(AZ_RESTRICTED_PLATFORM) #define AZ_RESTRICTED_SECTION PROJECTDEFINES_H_SECTION_VTX_IDX #include AZ_RESTRICTED_FILE(ProjectDefines_h) #endif #if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED) -#undef AZ_RESTRICTED_SECTION_IMPLEMENTED + #undef AZ_RESTRICTED_SECTION_IMPLEMENTED #else -// Uncomment one of the two following typedefs: -typedef uint32 vtx_idx; -//typedef uint16 vtx_idx; + // Uncomment one of the two following typedefs: + typedef uint32 vtx_idx; + //typedef uint16 vtx_idx; #endif -// 0=off, 1=on -#define TERRAIN_USE_CIE_COLORSPACE 0 - // When non-zero, const cvar accesses (by name) are logged in release-mode on consoles. // This can be used to find non-optimal usage scenario's, where the constant should be used directly instead. // Since read accesses tend to be used in flow-control logic, constants allow for better optimization by the compiler. #define LOG_CONST_CVAR_ACCESS 0 #if defined(WIN32) || defined(WIN64) || LOG_CONST_CVAR_ACCESS -#define RELEASE_LOGGING + #define RELEASE_LOGGING #endif #if defined(_RELEASE) && !defined(RELEASE_LOGGING) -#define EXCLUDE_NORMAL_LOG + #define EXCLUDE_NORMAL_LOG #endif // Add the "REMOTE_ASSET_PROCESSOR" define except in release // this makes it so that asset processor functions. Without this, all assets must be present and on local media // with this, the asset processor can be used to remotely process assets. #if !defined(_RELEASE) -# define REMOTE_ASSET_PROCESSOR + #define REMOTE_ASSET_PROCESSOR #endif #if (!defined(_RELEASE) || defined(PERFORMANCE_BUILD)) @@ -93,132 +83,68 @@ typedef uint32 vtx_idx; #define AZ_RESTRICTED_SECTION PROJECTDEFINES_H_SECTION_TRAITS #include AZ_RESTRICTED_FILE(ProjectDefines_h) #else -#define PROJECTDEFINES_H_TRAIT_DISABLE_MONOLITHIC_PROFILING_MARKERS 1 -#if !defined(LINUX) && !defined(APPLE) -#define PROJECTDEFINES_H_TRAIT_ENABLE_SOFTCODE_SYSTEM 1 -#endif -#if defined(WIN32) || defined(WIN64) || defined(LINUX) || defined(APPLE) -#define PROJECTDEFINES_H_TRAIT_USE_GPU_PARTICLES 1 -#endif -#define PROJECTDEFINES_H_TRAIT_USE_MESH_TESSELLATION 1 -#if defined(WIN32) -#define PROJECTDEFINES_H_TRAIT_USE_SVO_GI 1 -#endif -#if defined(APPLE) || defined(LINUX) -#define AZ_LEGACY_CRYCOMMON_TRAIT_USE_PTHREADS 1 -#define AZ_LEGACY_CRYCOMMON_TRAIT_USE_UNIX_PATHS 1 -#endif -#endif - -#define USE_GLOBAL_BUCKET_ALLOCATOR - -#ifdef IS_PROSDK -# define USING_TAGES_SECURITY // Wrapper for TGVM security -# if defined(LINUX) || defined(APPLE) -# error LINUX and Mac does not support evaluation version -# endif -#endif - -#ifdef USING_TAGES_SECURITY -# define TAGES_EXPORT __declspec(dllexport) -#else -# define TAGES_EXPORT -#endif // USING_TAGES_SECURITY -// test ------------------------------------- - -#define _DATAPROBE - - - -//This feature allows automatic crash submission to JIRA, but does not work outside of O3DE -//Note: This #define will be commented out during code export -#define ENABLE_CRASH_HANDLER - -#if !defined(PHYSICS_STACK_SIZE) -# define PHYSICS_STACK_SIZE (128U << 10) + #define PROJECTDEFINES_H_TRAIT_DISABLE_MONOLITHIC_PROFILING_MARKERS 1 + #if !defined(LINUX) && !defined(APPLE) + #define PROJECTDEFINES_H_TRAIT_ENABLE_SOFTCODE_SYSTEM 1 + #endif + #if defined(WIN32) || defined(WIN64) || defined(LINUX) || defined(APPLE) + #define PROJECTDEFINES_H_TRAIT_USE_GPU_PARTICLES 1 + #endif + #define PROJECTDEFINES_H_TRAIT_USE_MESH_TESSELLATION 1 + #if defined(WIN32) + #define PROJECTDEFINES_H_TRAIT_USE_SVO_GI 1 + #endif + #if defined(APPLE) || defined(LINUX) + #define AZ_LEGACY_CRYCOMMON_TRAIT_USE_PTHREADS 1 + #define AZ_LEGACY_CRYCOMMON_TRAIT_USE_UNIX_PATHS 1 + #endif #endif #if (!defined(_RELEASE) || defined(PERFORMANCE_BUILD)) && !defined(RESOURCE_COMPILER) -#ifndef ENABLE_PROFILING_CODE - #define ENABLE_PROFILING_CODE -#endif -#if !(defined(SANDBOX_EXPORTS) || defined(PLUGIN_EXPORTS) || (defined(AZ_MONOLITHIC_BUILD) && PROJECTDEFINES_H_TRAIT_DISABLE_MONOLITHIC_PROFILING_MARKERS)) - #define ENABLE_PROFILING_MARKERS -#endif + #ifndef ENABLE_PROFILING_CODE + #define ENABLE_PROFILING_CODE + #endif -//lightweight profilers, disable for submissions, disables displayinfo inside 3dengine as well -#ifndef ENABLE_LW_PROFILERS - #define ENABLE_LW_PROFILERS -#endif -#endif - -#if defined(ENABLE_PROFILING_CODE) -#define ENABLE_ART_RT_TIME_ESTIMATE -#endif - -#if defined(ENABLE_PROFILING_CODE) && !defined(_RELEASE) - #define FMOD_STREAMING_DEBUGGING 1 -#endif - -#if defined(WIN32) || defined(WIN64) || defined(APPLE) || defined(AZ_PLATFORM_LINUX) -#define FLARES_SUPPORT_EDITING + //lightweight profilers, disable for submissions, disables displayinfo inside 3dengine as well + #ifndef ENABLE_LW_PROFILERS + #define ENABLE_LW_PROFILERS + #endif #endif // Reflect texture slot information - only used in the editor #if defined(WIN32) || defined(WIN64) || defined(AZ_PLATFORM_MAC) -#define SHADER_REFLECT_TEXTURE_SLOTS 1 + #define SHADER_REFLECT_TEXTURE_SLOTS 1 #else -#define SHADER_REFLECT_TEXTURE_SLOTS 0 + #define SHADER_REFLECT_TEXTURE_SLOTS 0 #endif -// these enable and disable certain net features to give compatibility between PCs and consoles / profile and performance builds -#define PC_CONSOLE_NET_COMPATIBLE 0 -#define PROFILE_PERFORMANCE_NET_COMPATIBLE 0 - -#if (!defined(_RELEASE) || defined(PERFORMANCE_BUILD)) && !PROFILE_PERFORMANCE_NET_COMPATIBLE -#define USE_LAGOMETER (1) -#else -#define USE_LAGOMETER (0) -#endif - -// enable this in order to support old style material names in old data ("engine/material.mtl" or "mygame/material.mtl" as opposed to just "material.mtl") -// previously, material names could have the game folder in it, but this is not necessary anymore and would not work with things like gems -// note that if you use any older projects such as GameSDK this should remain enabled -#define SUPPORT_LEGACY_MATERIAL_NAMES - -// Enable additional structures and code for sprite motion blur. Currently non-functional and disabled -// #define PARTICLE_MOTION_BLUR - -// a special ticker thread to run during load and unload of levels -#define USE_NETWORK_STALL_TICKER_THREAD - #if !defined(MOBILE) -//--------------------------------------------------------------------- -// Enable Tessellation Features -// (displacement mapping, subdivision, water tessellation) -//--------------------------------------------------------------------- -// Modules : 3DEngine, Renderer -// Depends on: DX11 + //--------------------------------------------------------------------- + // Enable Tessellation Features + // (displacement mapping, subdivision, water tessellation) + //--------------------------------------------------------------------- + // Modules : 3DEngine, Renderer + // Depends on: DX11 -// Global tessellation feature flag + // Global tessellation feature flag #define TESSELLATION #ifdef TESSELLATION -// Specific features flags + // Specific features flags #define WATER_TESSELLATION #define PARTICLES_TESSELLATION #if PROJECTDEFINES_H_TRAIT_USE_MESH_TESSELLATION -// Mesh tessellation (displacement, smoothing, subd) + // Mesh tessellation (displacement, smoothing, subd) #define MESH_TESSELLATION -// Mesh tessellation also in motion blur passes + // Mesh tessellation also in motion blur passes #define MOTIONBLUR_TESSELLATION #endif -// Dependencies + // Dependencies #ifdef MESH_TESSELLATION #define MESH_TESSELLATION_ENGINE #endif - #ifndef NULL_RENDERER + #ifndef NULL_RENDERER #ifdef WATER_TESSELLATION #define WATER_TESSELLATION_RENDERER #endif @@ -230,7 +156,7 @@ typedef uint32 vtx_idx; #endif #if defined(WATER_TESSELLATION_RENDERER) || defined(PARTICLES_TESSELLATION_RENDERER) || defined(MESH_TESSELLATION_RENDERER) -// Common tessellation flag enabling tessellation stages in renderer + // Common tessellation flag enabling tessellation stages in renderer #define TESSELLATION_RENDERER #endif #endif // !NULL_RENDERER @@ -249,14 +175,8 @@ typedef uint32 vtx_idx; #endif #if defined(ENABLE_PROFILING_CODE) -# define USE_DISK_PROFILER -# define ENABLE_LOADING_PROFILER // requires AZ_PROFILE_TELEMETRY to also be defined -#endif - -#if PROJECTDEFINES_H_TRAIT_USE_GPU_PARTICLES && !defined(NULL_RENDERER) - #define GPU_PARTICLES 1 -#else - #define GPU_PARTICLES 0 + #define USE_DISK_PROFILER + #define ENABLE_LOADING_PROFILER // requires AZ_PROFILE_TELEMETRY to also be defined #endif // The maximum number of joints in an animation diff --git a/Code/Legacy/CryCommon/Win32specific.h b/Code/Legacy/CryCommon/Win32specific.h index 650a4946a0..0519bb1022 100644 --- a/Code/Legacy/CryCommon/Win32specific.h +++ b/Code/Legacy/CryCommon/Win32specific.h @@ -23,7 +23,6 @@ #define ILINE __forceinline #endif -#define DEBUG_BREAK _asm { int 3 } #define RC_EXECUTABLE "rc.exe" #define DEPRECATED __declspec(deprecated) #define TYPENAME(x) typeid(x).name() diff --git a/Code/Legacy/CryCommon/Win64specific.h b/Code/Legacy/CryCommon/Win64specific.h index a3cb11ce32..b1e86f9250 100644 --- a/Code/Legacy/CryCommon/Win64specific.h +++ b/Code/Legacy/CryCommon/Win64specific.h @@ -19,7 +19,6 @@ #define _CPU_SSE #define ILINE __forceinline -#define DEBUG_BREAK CryDebugBreak() #define RC_EXECUTABLE "rc.exe" #define DEPRECATED __declspec(deprecated) #define TYPENAME(x) typeid(x).name() diff --git a/Code/Legacy/CryCommon/WinBase.cpp b/Code/Legacy/CryCommon/WinBase.cpp index 15146fbac1..2861b4470e 100644 --- a/Code/Legacy/CryCommon/WinBase.cpp +++ b/Code/Legacy/CryCommon/WinBase.cpp @@ -1127,20 +1127,6 @@ void CrySleep(unsigned int dwMilliseconds) Sleep(dwMilliseconds); } -////////////////////////////////////////////////////////////////////////// -void CryLowLatencySleep(unsigned int dwMilliseconds) -{ -#if defined(AZ_RESTRICTED_PLATFORM) - #define AZ_RESTRICTED_SECTION WINBASE_CPP_SECTION_6 - #include AZ_RESTRICTED_FILE(WinBase_cpp) -#endif -#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED) -#undef AZ_RESTRICTED_SECTION_IMPLEMENTED -#else - CrySleep(dwMilliseconds); -#endif -} - ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// int CryMessageBox(const char* lpText, const char* lpCaption, unsigned int uType) @@ -1284,14 +1270,6 @@ int CryMessageBox(const char* lpText, const char* lpCaption, unsigned int uType) #endif } -////////////////////////////////////////////////////////////////////////// -short CryGetAsyncKeyState(int vKey) -{ - //TODO: implement - CRY_ASSERT_MESSAGE(0, "CryGetAsyncKeyState not implemented yet"); - return 0; -} - #if defined(LINUX) || defined(APPLE) || defined(DEFINE_CRY_INTERLOCKED_INCREMENT) //[K01]: http://www.memoryhole.net/kyle/2007/05/atomic_incrementing.html //http://forums.devx.com/archive/index.php/t-160558.html @@ -1382,10 +1360,6 @@ threadID CryGetCurrentThreadId() return GetCurrentThreadId(); } -void CryDebugBreak() -{ - __builtin_trap(); -} #endif//LINUX APPLE #if defined(APPLE) || defined(LINUX) @@ -1398,11 +1372,6 @@ DLL_EXPORT void OutputDebugString(const char* outputString) #endif } -DLL_EXPORT void DebugBreak() -{ - CryDebugBreak(); -} - #endif // This code does not have a long life span and will be replaced soon @@ -1626,16 +1595,6 @@ DWORD GetFileAttributes(LPCSTR lpFileName) return (ret == 0) ? FILE_ATTRIBUTE_NORMAL : ret;//return file attribute normal as the default value, must only be set if no other attributes have been found } -uint32 CryGetFileAttributes(const char* lpFileName) -{ - - string fn = lpFileName; - adaptFilenameToLinux(fn); - const char* buffer = fn.c_str(); - return GetFileAttributes(buffer); - -} - __finddata64_t::~__finddata64_t() { if (m_Dir != FS_DIR_NULL) diff --git a/Code/Legacy/CryCommon/platform.h b/Code/Legacy/CryCommon/platform.h index 6aad8dd043..fb96056beb 100644 --- a/Code/Legacy/CryCommon/platform.h +++ b/Code/Legacy/CryCommon/platform.h @@ -7,136 +7,31 @@ */ -// Description : Platform dependend stuff. +// Description : Platform dependent stuff. // Include this file instead of windows h #pragma once #if defined(AZ_RESTRICTED_PLATFORM) #undef AZ_RESTRICTED_SECTION -#define PLATFORM_H_SECTION_1 1 -#define PLATFORM_H_SECTION_2 2 #define PLATFORM_H_SECTION_3 3 -#define PLATFORM_H_SECTION_4 4 #define PLATFORM_H_SECTION_5 5 #define PLATFORM_H_SECTION_6 6 #define PLATFORM_H_SECTION_7 7 #define PLATFORM_H_SECTION_8 8 -#define PLATFORM_H_SECTION_9 9 #define PLATFORM_H_SECTION_10 10 #define PLATFORM_H_SECTION_11 11 #define PLATFORM_H_SECTION_12 12 #define PLATFORM_H_SECTION_13 13 #define PLATFORM_H_SECTION_14 14 -#define PLATFORM_H_SECTION_15 15 #endif -// certain C++ features are not available in some compiler versions -// turn them off here: -// #define _ALLOW_KEYWORD_MACROS -// #define _DISALLOW_INITIALIZER_LISTS -// #define _DISALLOW_ENUM_CLASS - -#if defined(_MSC_VER) - #define _ALLOW_KEYWORD_MACROS - - #define alignof _alignof - #if !defined(_HAS_EXCEPTIONS) - #define _HAS_EXCEPTIONS 0 - #endif -#elif defined(__GNUC__) - #define alignof __alignof__ -#endif - -// Alignment|InitializerList support. -#define _ALLOW_INITIALIZER_LISTS - #if (defined(LINUX) && !defined(ANDROID)) || defined(APPLE) -#define _FILE_OFFSET_BITS 64 // define large file support > 2GB + #define _FILE_OFFSET_BITS 64 // define large file support > 2GB #endif #include -#include - -#if defined(_MSC_VER) // We want the class name to be included, but __FUNCTION__ doesn't contain that on GCC/clang - #define __FUNC__ __FUNCTION__ -#else - #define __FUNC__ __PRETTY_FUNCTION__ -#endif - -#if defined(AZ_RESTRICTED_PLATFORM) - #define AZ_RESTRICTED_SECTION PLATFORM_H_SECTION_1 - #include AZ_RESTRICTED_FILE(platform_h) -#endif -#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED) -#undef AZ_RESTRICTED_SECTION_IMPLEMENTED -#elif defined(_DEBUG) && !defined(LINUX) && !defined(APPLE) - #include -#endif - -#define RESTRICT_POINTER __restrict - -// we have to use it because of VS doesn't support restrict reference variables -#if defined(APPLE) || defined(LINUX) - #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) - #define GCC411_OR_LATER - #endif - #define RESTRICT_REFERENCE __restrict -#else - #define RESTRICT_REFERENCE -#endif - - -#ifndef CHECK_REFERENCE_COUNTS //define that in your StdAfx.h to override per-project -# define CHECK_REFERENCE_COUNTS 0 //default value -#endif - -#if CHECK_REFERENCE_COUNTS -# define CHECK_REFCOUNT_CRASH(x) { if (!(x)) {*((int*)0) = 0; } \ -} -#else -# define CHECK_REFCOUNT_CRASH(x) -#endif - -#ifndef GARBAGE_MEMORY_ON_FREE //define that in your StdAfx.h to override per-project -# define GARBAGE_MEMORY_ON_FREE 0 //default value -#endif - -#if GARBAGE_MEMORY_ON_FREE -# ifndef GARBAGE_MEMORY_RANDOM //define that in your StdAfx.h to override per-project -# define GARBAGE_MEMORY_RANDOM 1 //0 to change it to progressive pattern -# endif -#endif - -////////////////////////////////////////////////////////////////////////// -// Available predefined compiler macros for Visual C++. -// _MSC_VER // Indicates MS Visual C compiler version -#if defined(AZ_RESTRICTED_PLATFORM) - #define AZ_RESTRICTED_SECTION PLATFORM_H_SECTION_2 - #include AZ_RESTRICTED_FILE(platform_h) -#endif -#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED) -#undef AZ_RESTRICTED_SECTION_IMPLEMENTED -#else -// _WIN32, _WIN64 // Indicates target OS -#endif -// _M_IX86, _M_PPC // Indicates target processor -// _DEBUG // Building in Debug mode -// _DLL // Linking with DLL runtime libs -// _MT // Linking with multi-threaded runtime libs -////////////////////////////////////////////////////////////////////////// - -// -// Translate some predefined macros. -// - -// NDEBUG disables std asserts, etc. -// Define it automatically if not compiling with Debug libs, or with ADEBUG flag. -#if !defined(_DEBUG) && !defined(ADEBUG) && !defined(NDEBUG) - #define NDEBUG -#endif - #if defined(AZ_RESTRICTED_PLATFORM) #define AZ_RESTRICTED_SECTION PLATFORM_H_SECTION_3 #include AZ_RESTRICTED_FILE(platform_h) @@ -147,44 +42,6 @@ #define CONSOLE #endif -//render thread settings, as this is accessed inside 3dengine and renderer and needs to be compile time defined, we need to do it here -//enable this macro to strip out the overhead for render thread -// #define STRIP_RENDER_THREAD -#ifdef STRIP_RENDER_THREAD - #define RT_COMMAND_BUF_COUNT 1 -#else -//can be enhanced to triple buffering, FlushFrame needs to be adjusted and RenderObj would become 132 bytes - #define RT_COMMAND_BUF_COUNT 2 -#endif - - -// We use WIN macros without _. -#if defined(AZ_RESTRICTED_PLATFORM) - #define AZ_RESTRICTED_SECTION PLATFORM_H_SECTION_4 - #include AZ_RESTRICTED_FILE(platform_h) -#endif -#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED) -#undef AZ_RESTRICTED_SECTION_IMPLEMENTED -#else -#if defined(_WIN32) && !defined(LINUX32) && !defined(LINUX64) && !defined(APPLE) && !defined(WIN32) - #define WIN32 -#endif -#if defined(_WIN64) && !defined(WIN64) - #define WIN64 -#endif -#endif - -// In Win32 Release we use static linkage -#ifdef WIN32 - #if !defined(_RELEASE) || defined(RESOURCE_COMPILER) || defined(EDITOR) || defined(_FORCEDLL) -// All windows targets not in Release built as DLLs. - #ifndef _USRDLL - #define _USRDLL - #endif - #endif - -#endif //WIN32 - #if defined(AZ_RESTRICTED_PLATFORM) #define AZ_RESTRICTED_SECTION PLATFORM_H_SECTION_5 #include AZ_RESTRICTED_FILE(platform_h) @@ -205,19 +62,17 @@ #define PRId64 "lld" #define PRIu64 "llu" #endif - #define PLATFORM_I64(x) x##ll #else #include - #define PLATFORM_I64(x) x##i64 #endif #if !defined(PRISIZE_T) -#if defined(AZ_RESTRICTED_PLATFORM) - #define AZ_RESTRICTED_SECTION PLATFORM_H_SECTION_6 - #include AZ_RESTRICTED_FILE(platform_h) -#endif -#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED) -#undef AZ_RESTRICTED_SECTION_IMPLEMENTED + #if defined(AZ_RESTRICTED_PLATFORM) + #define AZ_RESTRICTED_SECTION PLATFORM_H_SECTION_6 + #include AZ_RESTRICTED_FILE(platform_h) + #endif + #if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED) + #undef AZ_RESTRICTED_SECTION_IMPLEMENTED #elif defined(WIN64) #define PRISIZE_T "I64u" //size_t defined as unsigned __int64 #elif defined(WIN32) || defined(LINUX32) @@ -228,13 +83,14 @@ #error "Please defined PRISIZE_T for this platform" #endif #endif + #if !defined(PRI_THREADID) -#if defined(AZ_RESTRICTED_PLATFORM) - #define AZ_RESTRICTED_SECTION PLATFORM_H_SECTION_7 - #include AZ_RESTRICTED_FILE(platform_h) -#endif -#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED) -#undef AZ_RESTRICTED_SECTION_IMPLEMENTED + #if defined(AZ_RESTRICTED_PLATFORM) + #define AZ_RESTRICTED_SECTION PLATFORM_H_SECTION_7 + #include AZ_RESTRICTED_FILE(platform_h) + #endif + #if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED) + #undef AZ_RESTRICTED_SECTION_IMPLEMENTED #elif defined(MAC) || defined(IOS) && defined(__LP64__) && defined(__LP64__) #define PRI_THREADID "lld" #elif defined(LINUX64) || defined(ANDROID) @@ -243,6 +99,7 @@ #define PRI_THREADID "d" #endif #endif + #include "ProjectDefines.h" // to get some defines available in every CryEngine project // Function attribute for printf/scanf-style parameters. @@ -277,47 +134,6 @@ #define PRINTF_EMPTY_FORMAT "" #endif -#if defined(IOS) -#define USE_PTHREAD_TLS -#endif - -// Storage class modifier for thread local storage. -// THEADLOCAL should NOT be defined to empty because that creates some -// really hard to find issues. -#if !defined(USE_PTHREAD_TLS) -# define THREADLOCAL AZ_TRAIT_COMPILER_THREAD_LOCAL -#endif //!defined(USE_PTHREAD_TLS) - - - -////////////////////////////////////////////////////////////////////////// -// define Read Write Barrier macro needed for lockless programming -////////////////////////////////////////////////////////////////////////// -#if defined(__arm__) -/** - * (ARMv7) Full memory barriar. - * - * None of GCC 4.6/4.8 or clang 3.3/3.4 have a builtin intrinsic for ARM's ldrex/strex or dmb - * instructions. This is a placeholder until supplied by the toolchain. - */ -inline void __dmb() -{ - // The linux kernel uses "dmb ish" to only sync with local monitor (arch/arm/include/asm/barrier.h): - //#define dmb(option) __asm__ __volatile__ ("dmb " #option : : : "memory") - //#define smp_mb() dmb(ish) - __asm__ __volatile__ ("dmb ish" : : : "memory"); -} - -#define READ_WRITE_BARRIER {__dmb(); } -#else - #define READ_WRITE_BARRIER -#endif -////////////////////////////////////////////////////////////////////////// - -////////////////////////////////////////////////////////////////////////// -// define macro to prevent memory reoderings of reads/and writes -//TODO implement for all GCC platforms, else there are potential crashes with strict aliasing - #define MEMORY_RW_REORDERING_BARRIER do { /*not implemented*/} while (0) //default stack size for threads, currently only used on pthread platforms #if defined(AZ_RESTRICTED_PLATFORM) @@ -325,7 +141,7 @@ inline void __dmb() #include AZ_RESTRICTED_FILE(platform_h) #endif #if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED) -#undef AZ_RESTRICTED_SECTION_IMPLEMENTED + #undef AZ_RESTRICTED_SECTION_IMPLEMENTED #elif defined(LINUX) || defined(APPLE) #if !defined(_DEBUG) #define SIMPLE_THREAD_STACK_SIZE_KB (256) @@ -362,22 +178,6 @@ inline void __dmb() #else #define _HELP(x) "" #endif -////////////////////////////////////////////////////////////////////////// - -////////////////////////////////////////////////////////////////////////// -// Globally Used Defines. -////////////////////////////////////////////////////////////////////////// -// CPU Types: _CPU_X86,_CPU_AMD64,_CPU_G5 -// Platform: WIN23,WIN64,LINUX32,LINUX64,MAC -// CPU supported functionality: _CPU_SSE -////////////////////////////////////////////////////////////////////////// - - - #if defined(_MSC_VER) - #define PREFAST_SUPPRESS_WARNING(W) __pragma(warning(suppress: W)) - #else - #define PREFAST_SUPPRESS_WARNING(W) - #endif #ifdef _PREFAST_ # define PREFAST_ASSUME(cond) __analysis_assume(cond) @@ -385,47 +185,21 @@ inline void __dmb() # define PREFAST_ASSUME(cond) #endif - -#if defined(AZ_RESTRICTED_PLATFORM) - #define AZ_RESTRICTED_SECTION PLATFORM_H_SECTION_9 - #include AZ_RESTRICTED_FILE(platform_h) -#endif -#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED) -#undef AZ_RESTRICTED_SECTION_IMPLEMENTED -#else - #if defined(WIN32) && !defined(WIN64) - #include "Win32specific.h" - #endif - - #if defined(WIN64) - #include "Win64specific.h" - #endif -#endif - -#if defined(LINUX64) && !defined(ANDROID) -#include "Linux64Specific.h" -#endif - -#if defined(LINUX32) && !defined(ANDROID) -#include "Linux32Specific.h" -#endif - -#if defined(ANDROID) -#include "AndroidSpecific.h" -#endif - - #if defined(AZ_RESTRICTED_PLATFORM) #define AZ_RESTRICTED_SECTION PLATFORM_H_SECTION_10 #include AZ_RESTRICTED_FILE(platform_h) -#endif - -#if defined(MAC) -#include "MacSpecific.h" -#endif - -#if defined(IOS) -#include "iOSSpecific.h" +#else + #if defined(WIN64) + #include "Win64specific.h" + #elif defined(LINUX64) + #include "Linux64Specific.h" + #elif defined(MAC) + #include "MacSpecific.h" + #elif defined(ANDROID) + #include "AndroidSpecific.h" + #elif defined(IOS) + #include "iOSSpecific.h" + #endif #endif @@ -480,12 +254,6 @@ ILINE DestinationType alias_cast(SourceType pPtr) #define DEPRECATED #endif -////////////////////////////////////////////////////////////////////////// -// compile time error stuff -////////////////////////////////////////////////////////////////////////// -#undef STATIC_CHECK -#define STATIC_CHECK(expr, msg) static_assert(expr, #msg) - // Assert dialog box macros #include "CryAssert.h" @@ -500,30 +268,8 @@ ILINE DestinationType alias_cast(SourceType pPtr) // Platform dependent functions that emulate Win32 API. // Mostly used only for debugging! ////////////////////////////////////////////////////////////////////////// -void CryDebugBreak(); void CrySleep(unsigned int dwMilliseconds); -void CryLowLatencySleep(unsigned int dwMilliseconds); int CryMessageBox(const char* lpText, const char* lpCaption, unsigned int uType); -short CryGetAsyncKeyState(int vKey); -unsigned int CryGetFileAttributes(const char* lpFileName); - -inline void CryHeapCheck() -{ -#if defined(AZ_RESTRICTED_PLATFORM) - #define AZ_RESTRICTED_SECTION PLATFORM_H_SECTION_11 - #include AZ_RESTRICTED_FILE(platform_h) -#elif !defined(LINUX) && !defined(APPLE) // todo: this might be readded with later xdks? -#if !defined(NDEBUG) - int Result = -#endif - _heapchk(); - assert(Result != _HEAPBADBEGIN); - assert(Result != _HEAPBADNODE); - assert(Result != _HEAPBADPTR); - assert(Result != _HEAPEMPTY); - assert(Result == _HEAPOK); -#endif -} //--------------------------------------------------------------------------- // Useful function to clean the structure. @@ -554,77 +300,6 @@ inline D check_cast(S const& s) return d; } -// Convert one type to another, asserting there is no conversion loss. -// Usage: DestType dest; check_convert(dest, src); -template -inline D& check_convert(D& d, S const& s) -{ - d = D(s); - assert(S(d) == s); - return d; -} - -// Convert one type to another, asserting there is no conversion loss. -// Usage: DestType dest; check_convert(dest) = src; -template -struct CheckConvert -{ - CheckConvert(D& d) - : dest(&d) {} - - template - D& operator=(S const& s) - { - return check_convert(*dest, s); - } - -protected: - D* dest; -}; - -template -inline CheckConvert check_convert(D& d) -{ - return d; -} - -//--------------------------------------------------------------------------- -// Use NoCopy as a base class to easily prevent copy init & assign for any class. -struct NoCopy -{ - NoCopy() {} -private: - NoCopy(const NoCopy&); - NoCopy& operator =(const NoCopy&); -}; - -//--------------------------------------------------------------------------- -// ZeroInit: base class to zero the memory of the derived class before initialization, so local objects initialize the same as static. -// Usage: -// class MyClass: ZeroInit {...} -// class MyChild: public MyClass, ZeroInit {...} // ZeroInit must be the last base class - -template -struct ZeroInit -{ -#if defined(__clang__) || defined(__GNUC__) - bool __dummy; // Dummy var to create non-zero size, ensuring proper placement in TDerived -#endif - - ZeroInit(bool bZero = true) - { - // Optional bool arg to selectively disable zeroing. - if (bZero) - { - // Infer offset of this base class by static casting to derived class. - // Zero only the additional memory of the derived class. - TDerived* struct_end = static_cast(this) + 1; - size_t memory_size = (char*)struct_end - (char*)this; - memset(this, 0, memory_size); - } - } -}; - //--------------------------------------------------------------------------- // Quick const-manipulation macros @@ -705,29 +380,19 @@ threadID CryGetCurrentThreadId(); #include "CryFixedString.h" #endif -// need this in a common header file and any other file would be too misleading -enum ETriState -{ - eTS_false, - eTS_true, - eTS_maybe -}; - - #ifdef __GNUC__ - #define NO_INLINE __attribute__ ((noinline)) -# define NO_INLINE_WEAK __attribute__ ((noinline)) __attribute__((weak)) // marks a function as no_inline, but also as weak to prevent multiple-defined errors - -# define __PACKED __attribute__ ((packed)) - #else - #define NO_INLINE _declspec(noinline) -# define NO_INLINE_WEAK _declspec(noinline) inline - -# define __PACKED - #endif +#ifdef __GNUC__ + #define NO_INLINE __attribute__ ((noinline)) + #define NO_INLINE_WEAK __attribute__ ((noinline)) __attribute__((weak)) // marks a function as no_inline, but also as weak to prevent multiple-defined errors + #define __PACKED __attribute__ ((packed)) +#else + #define NO_INLINE _declspec(noinline) + #define NO_INLINE_WEAK _declspec(noinline) inline + #define __PACKED +#endif // Fallback for Alignment macro of GCC/CLANG (must be after the class definition) #if !defined(_ALIGN) - #define _ALIGN(num) AZ_POP_DISABLE_WARNING + #define _ALIGN(num) AZ_POP_DISABLE_WARNING #endif // Fallback for Alignment macro of MSVC (must be before the class definition) @@ -735,60 +400,13 @@ enum ETriState #define _MS_ALIGN(num) AZ_PUSH_DISABLE_WARNING(4324, "-Wunknown-warning-option") #endif -#if defined(WIN32) || defined(WIN64) -extern "C" { -__declspec(dllimport) unsigned long __stdcall TlsAlloc(); -__declspec(dllimport) void* __stdcall TlsGetValue(unsigned long dwTlsIndex); -__declspec(dllimport) int __stdcall TlsSetValue(unsigned long dwTlsIndex, void* lpTlsValue); -} - - #define TLS_DECLARE(type, var) extern int var##idx; - #define TLS_DEFINE(type, var) \ - int var##idx; \ - struct Init##var { \ - Init##var() { var##idx = TlsAlloc(); } \ - }; \ - Init##var g_init##var; - #define TLS_DEFINE_DEFAULT_VALUE(type, var, value) \ - int var##idx; \ - struct Init##var { \ - Init##var() { var##idx = TlsAlloc(); TlsSetValue(var##idx, reinterpret_cast(value)); } \ - }; \ - Init##var g_init##var; - #define TLS_GET(type, var) (type)TlsGetValue(var##idx) - #define TLS_SET(var, val) TlsSetValue(var##idx, reinterpret_cast(val)) -#elif defined(USE_PTHREAD_TLS) - #define TLS_DECLARE(_TYPE, _VAR) extern SCryPthreadTLS<_TYPE> _VAR##TLSKey; - #define TLS_DEFINE(_TYPE, _VAR) SCryPthreadTLS<_TYPE> _VAR##TLSKey; - #define TLS_DEFINE_DEFAULT_VALUE(_TYPE, _VAR, _DEFAULT) SCryPthreadTLS<_TYPE> _VAR##TLSKey = _DEFAULT; - #define TLS_GET(_TYPE, _VAR) _VAR##TLSKey.Get() - #define TLS_SET(_VAR, _VALUE) _VAR##TLSKey.Set(_VALUE) -#elif defined(THREADLOCAL) - #define TLS_DECLARE(type, var) extern THREADLOCAL type var; -#if defined(LINUX) || defined(MAC) - #define TLS_DEFINE(type, var) THREADLOCAL type var = 0; -#else - #define TLS_DEFINE(type, var) THREADLOCAL type var; -#endif // defined(LINUX) || defined(MAC) - #define TLS_DEFINE_DEFAULT_VALUE(type, var, value) THREADLOCAL type var = value; - #define TLS_GET(type, var) (var) - #define TLS_SET(var, val) (var = (val)) -#else // defined(THREADLOCAL) - #error "There's no support for thread local storage" -#endif - #if defined(AZ_RESTRICTED_PLATFORM) #define AZ_RESTRICTED_SECTION PLATFORM_H_SECTION_13 #include AZ_RESTRICTED_FILE(platform_h) #elif !defined(LINUX) && !defined(APPLE) -typedef int socklen_t; + typedef int socklen_t; #endif - -// Include MultiThreading support. -#include "CryThread.h" -#include "MultiThread.h" - // In RELEASE disable printf and fprintf #if defined(_RELEASE) && !defined(RELEASE_LOGGING) #if defined(AZ_RESTRICTED_PLATFORM) @@ -797,19 +415,4 @@ typedef int socklen_t; #endif #endif -#define _STRINGIFY(x) #x -#define STRINGIFY(x) _STRINGIFY(x) - -#if defined(AZ_RESTRICTED_PLATFORM) - #define AZ_RESTRICTED_SECTION PLATFORM_H_SECTION_15 - #include AZ_RESTRICTED_FILE(platform_h) -#endif -#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED) -#undef AZ_RESTRICTED_SECTION_IMPLEMENTED -#elif defined(WIN32) || defined(WIN64) - #define MESSAGE(msg) message(__FILE__ "(" STRINGIFY(__LINE__) "): " msg) -#else - #define MESSAGE(msg) -#endif - void InitRootDir(char szExeFileName[] = nullptr, uint nExeSize = 0, char szExeRootName[] = nullptr, uint nRootSize = 0); diff --git a/Code/Legacy/CryCommon/platform_impl.cpp b/Code/Legacy/CryCommon/platform_impl.cpp index a677ba30b6..a919b9a002 100644 --- a/Code/Legacy/CryCommon/platform_impl.cpp +++ b/Code/Legacy/CryCommon/platform_impl.cpp @@ -204,17 +204,6 @@ void __stl_debug_message(const char* format_str, ...) #include "CryAssert_impl.h" -////////////////////////////////////////////////////////////////////////// -void CryDebugBreak() -{ -#if defined(WIN32) && !defined(RELEASE) - if (IsDebuggerPresent()) -#endif - { - DebugBreak(); - } -} - ////////////////////////////////////////////////////////////////////////// void CrySleep(unsigned int dwMilliseconds) { @@ -222,21 +211,6 @@ void CrySleep(unsigned int dwMilliseconds) Sleep(dwMilliseconds); } -////////////////////////////////////////////////////////////////////////// -void CryLowLatencySleep(unsigned int dwMilliseconds) -{ - AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::System); -#if defined(AZ_RESTRICTED_PLATFORM) - #define AZ_RESTRICTED_SECTION PLATFORM_IMPL_H_SECTION_CRYLOWLATENCYSLEEP - #include AZ_RESTRICTED_FILE(platform_impl_h) -#endif -#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED) -#undef AZ_RESTRICTED_SECTION_IMPLEMENTED -#else - CrySleep(dwMilliseconds); -#endif -} - ////////////////////////////////////////////////////////////////////////// int CryMessageBox([[maybe_unused]] const char* lpText, [[maybe_unused]] const char* lpCaption, [[maybe_unused]] unsigned int uType) { @@ -302,16 +276,6 @@ void InitRootDir(char szExeFileName[], uint nExeSize, char szExeRootName[], [[ma } } -////////////////////////////////////////////////////////////////////////// -short CryGetAsyncKeyState([[maybe_unused]] int vKey) -{ -#ifdef WIN32 - return GetAsyncKeyState(vKey); -#else - return 0; -#endif -} - ////////////////////////////////////////////////////////////////////////// LONG CryInterlockedIncrement(int volatile* lpAddend) { @@ -417,23 +381,6 @@ void CryLeaveCriticalSection(void* cs) LeaveCriticalSection((CRITICAL_SECTION*)cs); } -////////////////////////////////////////////////////////////////////////// -uint32 CryGetFileAttributes(const char* lpFileName) -{ - WIN32_FILE_ATTRIBUTE_DATA data; - BOOL res; -#if defined(AZ_RESTRICTED_PLATFORM) - #define AZ_RESTRICTED_SECTION PLATFORM_IMPL_H_SECTION_CRYGETFILEATTRIBUTES - #include AZ_RESTRICTED_FILE(platform_impl_h) -#endif -#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED) -#undef AZ_RESTRICTED_SECTION_IMPLEMENTED -#else - res = GetFileAttributesEx(lpFileName, GetFileExInfoStandard, &data); -#endif - return res ? data.dwFileAttributes : -1; -} - ////////////////////////////////////////////////////////////////////////// bool CrySetFileAttributes(const char* lpFileName, uint32 dwFileAttributes) { diff --git a/Code/Legacy/CryCommon/smartptr.h b/Code/Legacy/CryCommon/smartptr.h index 246e18d541..6953348d47 100644 --- a/Code/Legacy/CryCommon/smartptr.h +++ b/Code/Legacy/CryCommon/smartptr.h @@ -13,6 +13,7 @@ #include #include +#include void CryFatalError(const char*, ...) PRINTF_PARAMS(1, 2); #if defined(APPLE) @@ -171,13 +172,13 @@ public: void AddRef() { - CHECK_REFCOUNT_CRASH(m_nRefCounter >= 0); + AZ_Assert(m_nRefCounter >= 0, "Invalid ref count"); ++m_nRefCounter; } void Release() { - CHECK_REFCOUNT_CRASH(m_nRefCounter > 0); + AZ_Assert(m_nRefCounter > 0, "Invalid ref count"); if (--m_nRefCounter == 0) { delete static_cast(this); @@ -215,13 +216,13 @@ public: void AddRef() { - CHECK_REFCOUNT_CRASH(m_nRefCounter >= 0); + AZ_Assert(m_nRefCounter >= 0, "Invalid ref count"); ++m_nRefCounter; } void Release() { - CHECK_REFCOUNT_CRASH(m_nRefCounter > 0); + AZ_Assert(m_nRefCounter > 0, "Invalid ref count"); if (--m_nRefCounter == 0) { delete this; @@ -272,13 +273,13 @@ public: void AddRef() { - CHECK_REFCOUNT_CRASH(m_nRefCounter >= 0); + AZ_Assert(m_nRefCounter >= 0, "Invalid ref count"); ++m_nRefCounter; } void Release() { - CHECK_REFCOUNT_CRASH(m_nRefCounter > 0); + AZ_Assert(m_nRefCounter > 0, "Invalid ref count"); if (--m_nRefCounter == 0) { assert(m_pDeleteFnc); diff --git a/Code/Legacy/CrySystem/IDebugCallStack.cpp b/Code/Legacy/CrySystem/IDebugCallStack.cpp index 4ca481be88..85b9ff4b79 100644 --- a/Code/Legacy/CrySystem/IDebugCallStack.cpp +++ b/Code/Legacy/CrySystem/IDebugCallStack.cpp @@ -227,7 +227,7 @@ void IDebugCallStack::FatalError(const char* description) #if defined(WIN32) || !defined(_RELEASE) int* p = 0x0; - PREFAST_SUPPRESS_WARNING(6011) * p = 1; // we're intentionally crashing here + *p = 1; // we're intentionally crashing here #endif } diff --git a/Code/Legacy/CrySystem/SystemInit.cpp b/Code/Legacy/CrySystem/SystemInit.cpp index cce3cf4aec..8ea653fb81 100644 --- a/Code/Legacy/CrySystem/SystemInit.cpp +++ b/Code/Legacy/CrySystem/SystemInit.cpp @@ -252,7 +252,7 @@ static void CmdCrashTest(IConsoleCmdArgs* pArgs) case 1: { int* p = 0; - PREFAST_SUPPRESS_WARNING(6011) * p = 0xABCD; + *p = 0xABCD; } break; case 2: diff --git a/Code/Legacy/CrySystem/SystemWin32.cpp b/Code/Legacy/CrySystem/SystemWin32.cpp index 2cc41adc08..1f5dc7d0b0 100644 --- a/Code/Legacy/CrySystem/SystemWin32.cpp +++ b/Code/Legacy/CrySystem/SystemWin32.cpp @@ -355,32 +355,25 @@ void CSystem::FatalError(const char* format, ...) IDebugCallStack::instance()->FatalError(szBuffer); #endif - CryDebugBreak(); - // app can not continue + AZ::Debug::Trace::Break(); + #ifdef _DEBUG + #if defined(WIN32) || defined(WIN64) + _flushall(); + // on windows, _exit does all sorts of things which can cause cleanup to fail during a crash, we need to terminate instead. + TerminateProcess(GetCurrentProcess(), 1); + #endif -#if defined(WIN32) && !defined(WIN64) - DEBUG_BREAK; -#endif - -#else - -#if defined(WIN32) || defined(WIN64) - _flushall(); - // on windows, _exit does all sorts of things which can cause cleanup to fail during a crash, we need to terminate instead. - TerminateProcess(GetCurrentProcess(), 1); -#endif - -#if defined(AZ_RESTRICTED_PLATFORM) -#define AZ_RESTRICTED_SECTION SYSTEMWIN32_CPP_SECTION_2 -#include AZ_RESTRICTED_FILE(SystemWin32_cpp) -#endif -#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED) -#undef AZ_RESTRICTED_SECTION_IMPLEMENTED -#else - _exit(1); -#endif + #if defined(AZ_RESTRICTED_PLATFORM) + #define AZ_RESTRICTED_SECTION SYSTEMWIN32_CPP_SECTION_2 + #include AZ_RESTRICTED_FILE(SystemWin32_cpp) + #endif + #if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED) + #undef AZ_RESTRICTED_SECTION_IMPLEMENTED + #else + _exit(1); + #endif #endif } diff --git a/Code/Legacy/CrySystem/ViewSystem/ViewSystem.cpp b/Code/Legacy/CrySystem/ViewSystem/ViewSystem.cpp index a82e78c08c..3280c8daa9 100644 --- a/Code/Legacy/CrySystem/ViewSystem/ViewSystem.cpp +++ b/Code/Legacy/CrySystem/ViewSystem/ViewSystem.cpp @@ -26,7 +26,7 @@ if (count > 0) \ { \ const size_t memSize = count * sizeof(IViewSystemListener*); \ - PREFAST_SUPPRESS_WARNING(6255) IViewSystemListener * *pArray = (IViewSystemListener**) alloca(memSize); \ + IViewSystemListener* *pArray = (IViewSystemListener**) alloca(memSize); \ memcpy(pArray, &*m_listeners.begin(), memSize); \ while (count--) \ { \ diff --git a/Code/Legacy/CrySystem/XML/xml.cpp b/Code/Legacy/CrySystem/XML/xml.cpp index 0493a64ca8..4fec4d3fd9 100644 --- a/Code/Legacy/CrySystem/XML/xml.cpp +++ b/Code/Legacy/CrySystem/XML/xml.cpp @@ -1390,7 +1390,7 @@ protected: { ((XmlParserImp*)userData)->onEndElement(name); } - static void characterData(void* userData, const char* s, int len) PREFAST_SUPPRESS_WARNING(6262) + static void characterData(void* userData, const char* s, int len) { char str[32700]; if (len > sizeof(str) - 1) diff --git a/Gems/LyShine/Code/Source/Animation/UiAnimationSystem.cpp b/Gems/LyShine/Code/Source/Animation/UiAnimationSystem.cpp index d61090f79d..c28c13ba94 100644 --- a/Gems/LyShine/Code/Source/Animation/UiAnimationSystem.cpp +++ b/Gems/LyShine/Code/Source/Animation/UiAnimationSystem.cpp @@ -26,12 +26,12 @@ ////////////////////////////////////////////////////////////////////////// // Serialization for anim nodes & param types #define REGISTER_NODE_TYPE(name) assert(g_animNodeEnumToStringMap.find(eUiAnimNodeType_ ## name) == g_animNodeEnumToStringMap.end()); \ - g_animNodeEnumToStringMap[eUiAnimNodeType_ ## name] = STRINGIFY(name); \ - g_animNodeStringToEnumMap[string(STRINGIFY(name))] = eUiAnimNodeType_ ## name; + g_animNodeEnumToStringMap[eUiAnimNodeType_ ## name] = AZ_STRINGIZE(name); \ + g_animNodeStringToEnumMap[string(AZ_STRINGIZE(name))] = eUiAnimNodeType_ ## name; #define REGISTER_PARAM_TYPE(name) assert(g_animParamEnumToStringMap.find(eUiAnimParamType_ ## name) == g_animParamEnumToStringMap.end()); \ - g_animParamEnumToStringMap[eUiAnimParamType_ ## name] = STRINGIFY(name); \ - g_animParamStringToEnumMap[string(STRINGIFY(name))] = eUiAnimParamType_ ## name; + g_animParamEnumToStringMap[eUiAnimParamType_ ## name] = AZ_STRINGIZE(name); \ + g_animParamStringToEnumMap[string(AZ_STRINGIZE(name))] = eUiAnimParamType_ ## name; namespace { diff --git a/Gems/Maestro/Code/Source/Cinematics/Movie.cpp b/Gems/Maestro/Code/Source/Cinematics/Movie.cpp index b781dd6c82..589a084426 100644 --- a/Gems/Maestro/Code/Source/Cinematics/Movie.cpp +++ b/Gems/Maestro/Code/Source/Cinematics/Movie.cpp @@ -74,12 +74,12 @@ static SMovieSequenceAutoComplete s_movieSequenceAutoComplete; ////////////////////////////////////////////////////////////////////////// // Serialization for anim nodes & param types #define REGISTER_NODE_TYPE(name) assert(g_animNodeEnumToStringMap.find(AnimNodeType::name) == g_animNodeEnumToStringMap.end()); \ - g_animNodeEnumToStringMap[AnimNodeType::name] = STRINGIFY(name); \ - g_animNodeStringToEnumMap[string(STRINGIFY(name))] = AnimNodeType::name; + g_animNodeEnumToStringMap[AnimNodeType::name] = AZ_STRINGIZE(name); \ + g_animNodeStringToEnumMap[string(AZ_STRINGIZE(name))] = AnimNodeType::name; #define REGISTER_PARAM_TYPE(name) assert(g_animParamEnumToStringMap.find(AnimParamType::name) == g_animParamEnumToStringMap.end()); \ - g_animParamEnumToStringMap[AnimParamType::name] = STRINGIFY(name); \ - g_animParamStringToEnumMap[string(STRINGIFY(name))] = AnimParamType::name; + g_animParamEnumToStringMap[AnimParamType::name] = AZ_STRINGIZE(name); \ + g_animParamStringToEnumMap[string(AZ_STRINGIZE(name))] = AnimParamType::name; namespace { From dcfeae1cc9ad9327552fbf48d78ca3bd594601f9 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 6 Aug 2021 16:24:06 -0700 Subject: [PATCH 168/803] warnings not previously detected (#2954) Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Gems/LyShine/Code/Editor/Animation/UiAnimUndoManager.cpp | 2 +- Gems/LyShine/Code/Editor/AssetTreeEntry.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Gems/LyShine/Code/Editor/Animation/UiAnimUndoManager.cpp b/Gems/LyShine/Code/Editor/Animation/UiAnimUndoManager.cpp index 82eb6091e6..025b8c94d8 100644 --- a/Gems/LyShine/Code/Editor/Animation/UiAnimUndoManager.cpp +++ b/Gems/LyShine/Code/Editor/Animation/UiAnimUndoManager.cpp @@ -59,7 +59,7 @@ public: virtual bool IsEmpty() const { return m_undoObjects.empty(); }; virtual void Undo(bool bUndo) { - for (int i = m_undoObjects.size() - 1; i >= 0; i--) + for (int i = aznumeric_cast(m_undoObjects.size()) - 1; i >= 0; i--) { m_undoObjects[i]->Undo(bUndo); } diff --git a/Gems/LyShine/Code/Editor/AssetTreeEntry.cpp b/Gems/LyShine/Code/Editor/AssetTreeEntry.cpp index caff5d2da0..5a281ba312 100644 --- a/Gems/LyShine/Code/Editor/AssetTreeEntry.cpp +++ b/Gems/LyShine/Code/Editor/AssetTreeEntry.cpp @@ -136,7 +136,7 @@ AssetTreeEntry* AssetTreeEntry::BuildAssetTree(const AZ::Data::AssetType& assetT // product name stored in db is in all lower case, but we want to preserve case here AzFramework::StringFunc::Path::Split(product->GetParent()->GetRelativePath().c_str(), nullptr, &path, &name); // find next character position after default slice path in order to generate hierarchical sub-menus matching the subfolders - int pos = AzFramework::StringFunc::Find(path.c_str(), pathToSearch.c_str()) + pathToSearch.length(); + const size_t pos = AzFramework::StringFunc::Find(path.c_str(), pathToSearch.c_str()) + pathToSearch.length(); assetTree->Insert(path.substr(pos), name, product->GetAssetId()); } return assetTree; From 360d0bdd0bde6fe56b1fdccc9bf017e221f3fd98 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 6 Aug 2021 16:42:38 -0700 Subject: [PATCH 169/803] removing more unused stuff Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../GridMate/Carrier/SocketDriver.cpp | 42 +++++----- Code/Legacy/CryCommon/AndroidSpecific.h | 13 --- Code/Legacy/CryCommon/AppleSpecific.h | 67 --------------- Code/Legacy/CryCommon/BaseTypes.h | 47 +++++------ Code/Legacy/CryCommon/BitFiddling.h | 40 --------- Code/Legacy/CryCommon/CompileTimeAssert.h | 56 ------------- Code/Legacy/CryCommon/CryArray.h | 2 +- Code/Legacy/CryCommon/CryCustomTypes.h | 4 +- Code/Legacy/CryCommon/CryHeaders.h | 2 +- Code/Legacy/CryCommon/CryLibrary.h | 1 - Code/Legacy/CryCommon/CryRandomInternal.h | 27 +++--- Code/Legacy/CryCommon/CryWindows.h | 19 ----- Code/Legacy/CryCommon/IMaterial.h | 2 +- Code/Legacy/CryCommon/ISystem.h | 83 +++++++++--------- Code/Legacy/CryCommon/ITexture.h | 4 +- Code/Legacy/CryCommon/Linux32Specific.h | 8 -- Code/Legacy/CryCommon/Linux64Specific.h | 8 -- Code/Legacy/CryCommon/LinuxSpecific.h | 84 ------------------- Code/Legacy/CryCommon/Linux_Win32Wrapper.h | 2 - Code/Legacy/CryCommon/MacSpecific.h | 34 -------- Code/Legacy/CryCommon/Options.h | 2 +- Code/Legacy/CryCommon/StringUtils.h | 4 +- Code/Legacy/CryCommon/UnicodeBinding.h | 42 +++++----- Code/Legacy/CryCommon/UnicodeEncoding.h | 4 +- Code/Legacy/CryCommon/UnicodeFunctions.h | 4 +- Code/Legacy/CryCommon/UnicodeIterator.h | 4 +- Code/Legacy/CryCommon/Win32specific.h | 8 -- Code/Legacy/CryCommon/Win64specific.h | 8 -- Code/Legacy/CryCommon/crycommon_files.cmake | 2 - Code/Legacy/CryCommon/iOSSpecific.h | 2 - Code/Legacy/CryCommon/platform.h | 1 - Code/Legacy/CryCommon/stridedptr.h | 4 +- Code/Legacy/CrySystem/CrySystem_precompiled.h | 2 +- .../CrySystem/LevelSystem/LevelSystem.cpp | 4 - Code/Legacy/CrySystem/XML/XMLBinaryReader.cpp | 2 +- Code/Legacy/CrySystem/XML/XMLBinaryWriter.cpp | 2 +- 36 files changed, 139 insertions(+), 501 deletions(-) delete mode 100644 Code/Legacy/CryCommon/CompileTimeAssert.h delete mode 100644 Code/Legacy/CryCommon/CryWindows.h diff --git a/Code/Framework/GridMate/GridMate/Carrier/SocketDriver.cpp b/Code/Framework/GridMate/GridMate/Carrier/SocketDriver.cpp index b75de6f383..a72c6b54f6 100644 --- a/Code/Framework/GridMate/GridMate/Carrier/SocketDriver.cpp +++ b/Code/Framework/GridMate/GridMate/Carrier/SocketDriver.cpp @@ -1528,7 +1528,7 @@ namespace GridMate if (0 != WSAIoctl( m_socket, SIO_GET_MULTIPLE_EXTENSION_FUNCTION_POINTER, &functionTableId, sizeof(GUID), (void**)&m_RIO_FN_TABLE, sizeof(m_RIO_FN_TABLE), &dwBytes, 0, 0)) { - AZ_Error("GridMate", false, "Could not initialize RIO: %u\n", ::WSAGetLastError()); + AZ_Error("GridMate", false, "Could not initialize RIO: %u\n", GridMate::Platform::GetSocketError()); return EC_SOCKET_CREATE; } else @@ -1543,13 +1543,13 @@ namespace GridMate if ((m_events[WakeupOnSend] = WSACreateEvent()) == WSA_INVALID_EVENT) { - AZ_Error("GridMate", false, "Failed WSACreateEvent(): %u\n", ::WSAGetLastError()); + AZ_Error("GridMate", false, "Failed WSACreateEvent(): %u\n", GridMate::Platform::GetSocketError()); return EC_SOCKET_CREATE; } if ((m_events[ReceiveEvent] = WSACreateEvent()) == WSA_INVALID_EVENT) { - AZ_Error("GridMate", false, "Failed WSACreateEvent(): %u\n", ::WSAGetLastError()); + AZ_Error("GridMate", false, "Failed WSACreateEvent(): %u\n", GridMate::Platform::GetSocketError()); return EC_SOCKET_CREATE; } RIO_NOTIFICATION_COMPLETION typeRecv; @@ -1559,13 +1559,13 @@ namespace GridMate m_RIORecvQueue = m_RIO_FN_TABLE.RIOCreateCompletionQueue(maxOutstandingReceive, &typeRecv); if (m_RIORecvQueue == RIO_INVALID_CQ) { - AZ_Error("GridMate", false, "Could not RIOCreateCompletionQueue: %u\n", ::WSAGetLastError()); + AZ_Error("GridMate", false, "Could not RIOCreateCompletionQueue: %u\n", GridMate::Platform::GetSocketError()); return EC_SOCKET_CREATE; } if ((m_events[SendEvent] = WSACreateEvent()) == WSA_INVALID_EVENT) { - AZ_Error("GridMate", false, "Failed WSACreateEvent(): %u\n", ::WSAGetLastError()); + AZ_Error("GridMate", false, "Failed WSACreateEvent(): %u\n", GridMate::Platform::GetSocketError()); return EC_SOCKET_CREATE; } RIO_NOTIFICATION_COMPLETION typeSend; @@ -1575,7 +1575,7 @@ namespace GridMate m_RIOSendQueue = m_RIO_FN_TABLE.RIOCreateCompletionQueue(maxOutstandingSend, &typeSend); if (m_RIOSendQueue == RIO_INVALID_CQ) { - AZ_Error("GridMate", false, "Could not RIOCreateCompletionQueue: %u\n", ::WSAGetLastError()); + AZ_Error("GridMate", false, "Could not RIOCreateCompletionQueue: %u\n", GridMate::Platform::GetSocketError()); return EC_SOCKET_CREATE; } @@ -1583,7 +1583,7 @@ namespace GridMate maxReceiveDataBuffers, maxOutstandingSend, maxSendDataBuffers, m_RIORecvQueue, m_RIOSendQueue, pContext); if (m_requestQueue == RIO_INVALID_RQ) { - AZ_Error("GridMate", m_requestQueue != NULL, "Could not RIOCreateRequestQueue: %u\n", ::WSAGetLastError()); + AZ_Error("GridMate", m_requestQueue != NULL, "Could not RIOCreateRequestQueue: %u\n", GridMate::Platform::GetSocketError()); return EC_SOCKET_CREATE; } @@ -1596,24 +1596,24 @@ namespace GridMate //Setup Recv raw buffer and RIO record if (nullptr == (m_rawRecvBuffer = AllocRIOBuffer(bufferSize, m_RIORecvBufferCount, &recvAllocated))) { - AZ_Error("GridMate", false, "Could not allocate buffer: %u\n", ::WSAGetLastError()); + AZ_Error("GridMate", false, "Could not allocate buffer: %u\n", GridMate::Platform::GetSocketError()); return EC_SOCKET_CREATE; } if (RIO_INVALID_BUFFERID == (recvBufferId = m_RIO_FN_TABLE.RIORegisterBuffer(m_rawRecvBuffer, bufferSize * m_RIORecvBufferCount))) { - AZ_Error("GridMate", false, "Could not register buffer: %u\n", ::WSAGetLastError()); + AZ_Error("GridMate", false, "Could not register buffer: %u\n", GridMate::Platform::GetSocketError()); return EC_SOCKET_CREATE; } //Setup Recv address raw buffer and RIO record if (nullptr == (m_rawRecvAddressBuffer = AllocRIOBuffer(sizeof(SOCKADDR_INET), m_RIORecvBufferCount, &recvAddrsAllocated))) { - AZ_Error("GridMate", false, "Could not allocate buffer: %u\n", ::WSAGetLastError()); + AZ_Error("GridMate", false, "Could not allocate buffer: %u\n", GridMate::Platform::GetSocketError()); return EC_SOCKET_CREATE; } if (RIO_INVALID_BUFFERID == (recvAddressBufferId = m_RIO_FN_TABLE.RIORegisterBuffer(m_rawRecvAddressBuffer, sizeof(SOCKADDR_INET) * m_RIORecvBufferCount))) { - AZ_Error("GridMate", false, "Could not register buffer: %u\n", ::WSAGetLastError()); + AZ_Error("GridMate", false, "Could not register buffer: %u\n", GridMate::Platform::GetSocketError()); return EC_SOCKET_CREATE; } @@ -1640,7 +1640,7 @@ namespace GridMate //Start Receive Handler if (false == m_RIO_FN_TABLE.RIOReceiveEx(m_requestQueue, &m_RIORecvBuffer[i], 1, NULL, &m_RIORecvAddressBuffer[i], NULL, NULL, 0, pBuffer)) { - AZ_Error("GridMate", false, "Could not RIOReceive: %u\n", ::WSAGetLastError()); + AZ_Error("GridMate", false, "Could not RIOReceive: %u\n", GridMate::Platform::GetSocketError()); return EC_SOCKET_CREATE; } } @@ -1650,25 +1650,25 @@ namespace GridMate //setup send raw buffer and RIO record if (nullptr == (m_rawSendBuffer = AllocRIOBuffer(bufferSize, m_RIOSendBufferCount, &sendAllocated))) { - AZ_Error("GridMate", false, "Could not allocate buffer: %u", ::WSAGetLastError()); + AZ_Error("GridMate", false, "Could not allocate buffer: %u", GridMate::Platform::GetSocketError()); return EC_SOCKET_CREATE; } if (RIO_INVALID_BUFFERID == (sendBufferId = m_RIO_FN_TABLE.RIORegisterBuffer(m_rawSendBuffer, m_RIOSendBufferCount * bufferSize))) { - AZ_Error("GridMate", false, "Could not register buffer: %u\n", ::WSAGetLastError()); + AZ_Error("GridMate", false, "Could not register buffer: %u\n", GridMate::Platform::GetSocketError()); return EC_SOCKET_CREATE; } //setup send address raw buffer and RIO record if (nullptr == (m_rawSendAddressBuffer = AllocRIOBuffer(sizeof(SOCKADDR_INET), m_RIOSendBufferCount, &sendAddrsAllocated))) { - AZ_Error("GridMate", false, "Could not allocate send address buffer: %u\n", ::WSAGetLastError()); + AZ_Error("GridMate", false, "Could not allocate send address buffer: %u\n", GridMate::Platform::GetSocketError()); return EC_SOCKET_CREATE; } if (RIO_INVALID_BUFFERID == (sendAddressBufferId = m_RIO_FN_TABLE.RIORegisterBuffer(m_rawSendAddressBuffer, m_RIOSendBufferCount * sizeof(SOCKADDR_INET)))) { - AZ_Error("GridMate", false, "Could not register buffer: %u\n", ::WSAGetLastError()); + AZ_Error("GridMate", false, "Could not register buffer: %u\n", GridMate::Platform::GetSocketError()); return EC_SOCKET_CREATE; } @@ -1726,7 +1726,7 @@ namespace GridMate if (!m_RIO_FN_TABLE.RIOSendEx(m_requestQueue, &m_RIOSendBuffer[m_workerNextSendBuffer], bufferCount, NULL, &m_RIOSendAddressBuffer[m_workerNextSendBuffer], NULL, NULL, 0, 0)) { - const DWORD lastError = ::WSAGetLastError(); + const DWORD lastError = GridMate::Platform::GetSocketError(); if (lastError == WSAENOBUFS) { continue; //spin until free @@ -1836,7 +1836,7 @@ namespace GridMate if (false == m_RIO_FN_TABLE.RIOReceiveEx(m_requestQueue, &m_RIORecvBuffer[m_RIONextRecvBuffer], bufferCount, NULL, &m_RIORecvAddressBuffer[m_RIONextRecvBuffer], NULL, NULL, 0, 0)) { - AZ_Error("GridMate", false, "Could not RIOReceive: %u\n", ::WSAGetLastError()); + AZ_Error("GridMate", false, "Could not RIOReceive: %u\n", GridMate::Platform::GetSocketError()); } if (recvd) @@ -1867,7 +1867,7 @@ namespace GridMate { if (!WSAResetEvent(m_events[Index - WSA_WAIT_EVENT_0])) { - AZ_Assert(false, "WSAResetEvent failed with error = %d\n", ::WSAGetLastError()); + AZ_Assert(false, "WSAResetEvent failed with error = %d\n", GridMate::Platform::GetSocketError()); } }; @@ -1926,7 +1926,7 @@ namespace GridMate } else if (isFailed(Index)) { - AZ_Assert(false, "WSAWaitForMultipleEvents failed with error = %d\n", ::WSAGetLastError()); + AZ_Assert(false, "WSAWaitForMultipleEvents failed with error = %d\n", GridMate::Platform::GetSocketError()); return false; } else @@ -1945,7 +1945,7 @@ namespace GridMate { if (!SetEvent(m_events[WakeupOnSend])) //Wake thread { - AZ_Assert(false, "SetEvent failed with error = %d\n", ::WSAGetLastError()); + AZ_Assert(false, "SetEvent failed with error = %d\n", GridMate::Platform::GetSocketError()); } } diff --git a/Code/Legacy/CryCommon/AndroidSpecific.h b/Code/Legacy/CryCommon/AndroidSpecific.h index a0f57553ca..cf4359ba47 100644 --- a/Code/Legacy/CryCommon/AndroidSpecific.h +++ b/Code/Legacy/CryCommon/AndroidSpecific.h @@ -30,15 +30,6 @@ #define MOBILE #endif -// Force all allocations to be aligned to TARGET_DEFAULT_ALIGN. -// This is because malloc on Android 32 bit returns memory that is not aligned -// to what some structs/classes need. -#define CRY_FORCE_MALLOC_NEW_ALIGN - -#define RC_EXECUTABLE "rc" -#define USE_CRT 1 -#define SIZEOF_PTR 4 - ////////////////////////////////////////////////////////////////////////// // Standard includes. ////////////////////////////////////////////////////////////////////////// @@ -120,10 +111,6 @@ typedef unsigned char byte; #define DEFINE_ALIGNED_DATA(type, name, alignment) \ type __attribute__ ((aligned(alignment))) name; -#define DEFINE_ALIGNED_DATA_STATIC(type, name, alignment) \ - static type __attribute__ ((aligned(alignment))) name; -#define DEFINE_ALIGNED_DATA_CONST(type, name, alignment) \ - const type __attribute__ ((aligned(alignment))) name; #include "LinuxSpecific.h" // these functions do not exist int the wchar.h header diff --git a/Code/Legacy/CryCommon/AppleSpecific.h b/Code/Legacy/CryCommon/AppleSpecific.h index ed76de8986..87aea0fbb5 100644 --- a/Code/Legacy/CryCommon/AppleSpecific.h +++ b/Code/Legacy/CryCommon/AppleSpecific.h @@ -17,9 +17,6 @@ #pragma diagnostic ignore "-W#pragma-messages" #endif - -#define RC_EXECUTABLE "rc" - ////////////////////////////////////////////////////////////////////////// // Standard includes. ////////////////////////////////////////////////////////////////////////// @@ -260,10 +257,6 @@ typedef uint64 __uint64; #define DEFINE_ALIGNED_DATA(type, name, alignment) \ type __attribute__ ((aligned(alignment))) name; -#define DEFINE_ALIGNED_DATA_STATIC(type, name, alignment) \ - static type __attribute__ ((aligned(alignment))) name; -#define DEFINE_ALIGNED_DATA_CONST(type, name, alignment) \ - const type __attribute__ ((aligned(alignment))) name; #define BST_UNCHECKED 0x0000 @@ -296,17 +289,6 @@ enum IDCONTINUE = 11 }; -#define ES_MULTILINE 0x0004L -#define ES_AUTOVSCROLL 0x0040L -#define ES_AUTOHSCROLL 0x0080L -#define ES_WANTRETURN 0x1000L - -#define LB_ERR (-1) - -#define LB_ADDSTRING 0x0180 -#define LB_GETCOUNT 0x018B -#define LB_SETTOPINDEX 0x0197 - #define MB_OK 0x00000000L #define MB_OKCANCEL 0x00000001L #define MB_ABORTRETRYIGNORE 0x00000002L @@ -326,22 +308,16 @@ enum #define MB_APPLMODAL 0x00000000L -#define MF_STRING 0x00000000L - #define MK_LBUTTON 0x0001 #define MK_RBUTTON 0x0002 #define MK_SHIFT 0x0004 #define MK_CONTROL 0x0008 #define MK_MBUTTON 0x0010 -#define MK_ALT ( 0x20 ) - #define SM_MOUSEPRESENT 0x00000000L #define SM_CMOUSEBUTTONS 43 -#define USER_TIMER_MINIMUM 0x0000000A - #define VK_TAB 0x09 #define VK_SHIFT 0x10 #define VK_MENU 0x12 @@ -349,11 +325,6 @@ enum #define VK_SPACE 0x20 #define VK_DELETE 0x2E -#define VK_NUMPAD1 0x61 -#define VK_NUMPAD2 0x62 -#define VK_NUMPAD3 0x63 -#define VK_NUMPAD4 0x64 - #define VK_OEM_COMMA 0xBC // ',' any country #define VK_OEM_PERIOD 0xBE // '.' any country #define VK_OEM_3 0xC0 // '`~' for US @@ -496,36 +467,6 @@ typedef HANDLE HMENU; #endif //__cplusplus -inline char* _fullpath(char* absPath, const char* relPath, size_t maxLength) -{ - char path[PATH_MAX]; - - if (realpath(relPath, path) == NULL) - { - return NULL; - } - const size_t len = std::min(strlen(path), maxLength - 1); - memcpy(absPath, path, len); - absPath[len] = 0; - return absPath; -} - -typedef union _LARGE_INTEGER -{ - struct - { - DWORD LowPart; - LONG HighPart; - }; - struct - { - DWORD LowPart; - LONG HighPart; - } u; - - long long QuadPart; -} LARGE_INTEGER; - extern bool QueryPerformanceCounter(LARGE_INTEGER*); extern bool QueryPerformanceFrequency(LARGE_INTEGER* frequency); @@ -566,14 +507,6 @@ inline int closesocket(int s) return ::close(s); } -inline int WSAGetLastError() -{ - return errno; -} - -//we take the definition of the pthread_t type directly from the pthread file -#define THREADID_NULL 0 - template char (*RtlpNumberOf( T (&)[N] ))[N]; diff --git a/Code/Legacy/CryCommon/BaseTypes.h b/Code/Legacy/CryCommon/BaseTypes.h index e8b6ae8ab7..0c588184a5 100644 --- a/Code/Legacy/CryCommon/BaseTypes.h +++ b/Code/Legacy/CryCommon/BaseTypes.h @@ -11,12 +11,9 @@ #define CRYINCLUDE_CRYCOMMON_BASETYPES_H #pragma once -#include "CompileTimeAssert.h" - - -COMPILE_TIME_ASSERT(sizeof(char) == 1); -COMPILE_TIME_ASSERT(sizeof(float) == 4); -COMPILE_TIME_ASSERT(sizeof(int) >= 4); +static_assert(sizeof(char) == 1); +static_assert(sizeof(float) == 4); +static_assert(sizeof(int) >= 4); typedef unsigned char uchar; @@ -36,35 +33,35 @@ typedef signed long slong; typedef unsigned long long ulonglong; typedef signed long long slonglong; -COMPILE_TIME_ASSERT(sizeof(uchar) == sizeof(schar)); -COMPILE_TIME_ASSERT(sizeof(ushort) == sizeof(sshort)); -COMPILE_TIME_ASSERT(sizeof(uint) == sizeof(sint)); -COMPILE_TIME_ASSERT(sizeof(ulong) == sizeof(slong)); -COMPILE_TIME_ASSERT(sizeof(ulonglong) == sizeof(slonglong)); +static_assert(sizeof(uchar) == sizeof(schar)); +static_assert(sizeof(ushort) == sizeof(sshort)); +static_assert(sizeof(uint) == sizeof(sint)); +static_assert(sizeof(ulong) == sizeof(slong)); +static_assert(sizeof(ulonglong) == sizeof(slonglong)); -COMPILE_TIME_ASSERT(sizeof(uchar) <= sizeof(ushort)); -COMPILE_TIME_ASSERT(sizeof(ushort) <= sizeof(uint)); -COMPILE_TIME_ASSERT(sizeof(uint) <= sizeof(ulong)); -COMPILE_TIME_ASSERT(sizeof(ulong) <= sizeof(ulonglong)); +static_assert(sizeof(uchar) <= sizeof(ushort)); +static_assert(sizeof(ushort) <= sizeof(uint)); +static_assert(sizeof(uint) <= sizeof(ulong)); +static_assert(sizeof(ulong) <= sizeof(ulonglong)); typedef schar int8; typedef schar sint8; typedef uchar uint8; -COMPILE_TIME_ASSERT(sizeof(uint8) == 1); -COMPILE_TIME_ASSERT(sizeof(sint8) == 1); +static_assert(sizeof(uint8) == 1); +static_assert(sizeof(sint8) == 1); typedef sshort int16; typedef sshort sint16; typedef ushort uint16; -COMPILE_TIME_ASSERT(sizeof(uint16) == 2); -COMPILE_TIME_ASSERT(sizeof(sint16) == 2); +static_assert(sizeof(uint16) == 2); +static_assert(sizeof(sint16) == 2); typedef sint int32; typedef sint sint32; typedef uint uint32; -COMPILE_TIME_ASSERT(sizeof(uint32) == 4); -COMPILE_TIME_ASSERT(sizeof(sint32) == 4); +static_assert(sizeof(uint32) == 4); +static_assert(sizeof(sint32) == 4); typedef slonglong int64; @@ -72,14 +69,14 @@ typedef slonglong int64; #define O3DE_INT64_DEFINED typedef slonglong sint64; typedef ulonglong uint64; -COMPILE_TIME_ASSERT(sizeof(uint64) == 8); -COMPILE_TIME_ASSERT(sizeof(sint64) == 8); +static_assert(sizeof(uint64) == 8); +static_assert(sizeof(sint64) == 8); #endif typedef float f32; typedef double f64; -COMPILE_TIME_ASSERT(sizeof(f32) == 4); -COMPILE_TIME_ASSERT(sizeof(f64) == 8); +static_assert(sizeof(f32) == 4); +static_assert(sizeof(f64) == 8); #endif // CRYINCLUDE_CRYCOMMON_BASETYPES_H diff --git a/Code/Legacy/CryCommon/BitFiddling.h b/Code/Legacy/CryCommon/BitFiddling.h index 342aad9a82..36173c5e53 100644 --- a/Code/Legacy/CryCommon/BitFiddling.h +++ b/Code/Legacy/CryCommon/BitFiddling.h @@ -12,7 +12,6 @@ #pragma once -#include "CompileTimeAssert.h" #include // Section dictionary @@ -188,45 +187,6 @@ ILINE int32 Isel32(int32 v, int32 alt) return ((static_cast(v) >> 31) & alt) | ((static_cast(~v) >> 31) & v); } -template -struct CompileTimeIntegerLog2 -{ - static const uint32 result = 1 + CompileTimeIntegerLog2<(ILOG >> 1)>::result; -}; -template <> -struct CompileTimeIntegerLog2<1> -{ - static const uint32 result = 0; -}; -template <> -struct CompileTimeIntegerLog2<0>; // keep it undefined, we cannot represent "minus infinity" result - -COMPILE_TIME_ASSERT(CompileTimeIntegerLog2<1>::result == 0); -COMPILE_TIME_ASSERT(CompileTimeIntegerLog2<2>::result == 1); -COMPILE_TIME_ASSERT(CompileTimeIntegerLog2<3>::result == 1); -COMPILE_TIME_ASSERT(CompileTimeIntegerLog2<4>::result == 2); -COMPILE_TIME_ASSERT(CompileTimeIntegerLog2<5>::result == 2); -COMPILE_TIME_ASSERT(CompileTimeIntegerLog2<255>::result == 7); -COMPILE_TIME_ASSERT(CompileTimeIntegerLog2<256>::result == 8); -COMPILE_TIME_ASSERT(CompileTimeIntegerLog2<257>::result == 8); - -template -struct CompileTimeIntegerLog2_RoundUp -{ - static const uint32 result = CompileTimeIntegerLog2::result + ((ILOG & (ILOG - 1)) != 0); -}; -template <> -struct CompileTimeIntegerLog2_RoundUp<0>; // we can return 0, but let's keep it undefined (same as CompileTimeIntegerLog2<0>) - -COMPILE_TIME_ASSERT(CompileTimeIntegerLog2_RoundUp<1>::result == 0); -COMPILE_TIME_ASSERT(CompileTimeIntegerLog2_RoundUp<2>::result == 1); -COMPILE_TIME_ASSERT(CompileTimeIntegerLog2_RoundUp<3>::result == 2); -COMPILE_TIME_ASSERT(CompileTimeIntegerLog2_RoundUp<4>::result == 2); -COMPILE_TIME_ASSERT(CompileTimeIntegerLog2_RoundUp<5>::result == 3); -COMPILE_TIME_ASSERT(CompileTimeIntegerLog2_RoundUp<255>::result == 8); -COMPILE_TIME_ASSERT(CompileTimeIntegerLog2_RoundUp<256>::result == 8); -COMPILE_TIME_ASSERT(CompileTimeIntegerLog2_RoundUp<257>::result == 9); - // Character-to-bitfield mapping inline uint32 AlphaBit(char c) diff --git a/Code/Legacy/CryCommon/CompileTimeAssert.h b/Code/Legacy/CryCommon/CompileTimeAssert.h deleted file mode 100644 index 80a2ecf6bf..0000000000 --- a/Code/Legacy/CryCommon/CompileTimeAssert.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -// Inspired by the Boost library's BOOST_STATIC_ASSERT(), -// see http://www.boost.org/doc/libs/1_49_0/doc/html/boost_staticassert/how.html -// or http://www.boost.org/libs/static_assert - -#ifndef CRYINCLUDE_CRYCOMMON_COMPILETIMEASSERT_H -#define CRYINCLUDE_CRYCOMMON_COMPILETIMEASSERT_H -#pragma once - -#if defined(__cplusplus) -/* -template -struct COMPILE_TIME_ASSERT_FAIL; - -template <> -struct COMPILE_TIME_ASSERT_FAIL -{ -}; - -template -struct COMPILE_TIME_ASSERT_TEST -{ - enum { dummy = i }; -}; - -#define COMPILE_TIME_ASSERT_BUILD_NAME2(x, y) x##y -#define COMPILE_TIME_ASSERT_BUILD_NAME1(x, y) COMPILE_TIME_ASSERT_BUILD_NAME2(x, y) -#define COMPILE_TIME_ASSERT_BUILD_NAME(x, y) COMPILE_TIME_ASSERT_BUILD_NAME1(x, y) - -#ifndef __RECODE__ - #define COMPILE_TIME_ASSERT(expr) \ - typedef COMPILE_TIME_ASSERT_TEST)> \ - COMPILE_TIME_ASSERT_BUILD_NAME(compile_time_assert_test_, __LINE__) - // note: for MS Visual Studio we could use __COUNTER__ instead of __LINE__ -#else - #define COMPILE_TIME_ASSERT(expr) -#endif // __RECODE__ - -#else - -#define COMPILE_TIME_ASSERT(expr) -*/ -#endif - -#define COMPILE_TIME_ASSERT_MSG(expr, msg) static_assert(expr, msg) -#define COMPILE_TIME_ASSERT(expr) COMPILE_TIME_ASSERT_MSG(expr, "Compile Time Assert") - - -#endif // CRYINCLUDE_CRYCOMMON_COMPILETIMEASSERT_H diff --git a/Code/Legacy/CryCommon/CryArray.h b/Code/Legacy/CryCommon/CryArray.h index 5b4684fdd2..ac935e5c45 100644 --- a/Code/Legacy/CryCommon/CryArray.h +++ b/Code/Legacy/CryCommon/CryArray.h @@ -771,7 +771,7 @@ namespace NArray AP& allocator() { - COMPILE_TIME_ASSERT(sizeof(AP) == sizeof(A)); + static_assert(sizeof(AP) == sizeof(A)); return *(AP*)this; } const AP& allocator() const diff --git a/Code/Legacy/CryCommon/CryCustomTypes.h b/Code/Legacy/CryCommon/CryCustomTypes.h index 9594f5a333..3b5b62e2f6 100644 --- a/Code/Legacy/CryCommon/CryCustomTypes.h +++ b/Code/Legacy/CryCommon/CryCustomTypes.h @@ -708,8 +708,8 @@ protected: static inline S FromFloat(float fIn) { - COMPILE_TIME_ASSERT(sizeof(S) <= 4); - COMPILE_TIME_ASSERT(nEXP_BITS > 0 && nEXP_BITS <= 8 && nEXP_BITS < sizeof(S) * 8 - 4); + static_assert(sizeof(S) <= 4); + static_assert(nEXP_BITS > 0 && nEXP_BITS <= 8 && nEXP_BITS < sizeof(S) * 8 - 4); // Clamp to allowed range. float fClamped = clamp_tpl(fIn * fROUNDER(), fMIN(), fMAX()); diff --git a/Code/Legacy/CryCommon/CryHeaders.h b/Code/Legacy/CryCommon/CryHeaders.h index 6b4ea0ba3a..4d037b52d9 100644 --- a/Code/Legacy/CryCommon/CryHeaders.h +++ b/Code/Legacy/CryCommon/CryHeaders.h @@ -17,7 +17,7 @@ #ifdef MAX_SUB_MATERIALS // This checks that the values are in sync in the different files. -COMPILE_TIME_ASSERT(MAX_SUB_MATERIALS == 128); +static_assert(MAX_SUB_MATERIALS == 128); #else #define MAX_SUB_MATERIALS 128 #endif diff --git a/Code/Legacy/CryCommon/CryLibrary.h b/Code/Legacy/CryCommon/CryLibrary.h index ca1ca5d067..787085af00 100644 --- a/Code/Legacy/CryCommon/CryLibrary.h +++ b/Code/Legacy/CryCommon/CryLibrary.h @@ -63,7 +63,6 @@ using DetachEnvironmentFunction = void(*)(); #if !defined(WIN32_LEAN_AND_MEAN) #define WIN32_LEAN_AND_MEAN #endif - #include HMODULE CryLoadLibrary(const char* libName); diff --git a/Code/Legacy/CryCommon/CryRandomInternal.h b/Code/Legacy/CryCommon/CryRandomInternal.h index 9499ba0774..ca74041189 100644 --- a/Code/Legacy/CryCommon/CryRandomInternal.h +++ b/Code/Legacy/CryCommon/CryRandomInternal.h @@ -13,7 +13,6 @@ #include // std::numeric_limits #include // std::make_unsigned #include "BaseTypes.h" // uint32, uint64 -#include "CompileTimeAssert.h" #include "Cry_Vector2.h" #include "Cry_Vector3.h" #include "Cry_Vector4.h" @@ -24,10 +23,10 @@ namespace CryRandom_Internal template struct BoundedRandomUint { - COMPILE_TIME_ASSERT(std::numeric_limits::is_integer); - COMPILE_TIME_ASSERT(!std::numeric_limits::is_signed); - COMPILE_TIME_ASSERT(sizeof(T) == size); - COMPILE_TIME_ASSERT(sizeof(T) <= sizeof(uint32)); + static_assert(std::numeric_limits::is_integer); + static_assert(!std::numeric_limits::is_signed); + static_assert(sizeof(T) == size); + static_assert(sizeof(T) <= sizeof(uint32)); inline static T Get(R& randomGenerator, const T maxValue) { @@ -41,9 +40,9 @@ namespace CryRandom_Internal template struct BoundedRandomUint { - COMPILE_TIME_ASSERT(std::numeric_limits::is_integer); - COMPILE_TIME_ASSERT(!std::numeric_limits::is_signed); - COMPILE_TIME_ASSERT(sizeof(T) == sizeof(uint64)); + static_assert(std::numeric_limits::is_integer); + static_assert(!std::numeric_limits::is_signed); + static_assert(sizeof(T) == sizeof(uint64)); inline static T Get(R& randomGenerator, const T maxValue) { @@ -65,11 +64,11 @@ namespace CryRandom_Internal template struct BoundedRandom { - COMPILE_TIME_ASSERT(std::numeric_limits::is_integer); + static_assert(std::numeric_limits::is_integer); typedef typename std::make_unsigned::type UT; - COMPILE_TIME_ASSERT(sizeof(T) == sizeof(UT)); - COMPILE_TIME_ASSERT(std::numeric_limits::is_integer); - COMPILE_TIME_ASSERT(!std::numeric_limits::is_signed); + static_assert(sizeof(T) == sizeof(UT)); + static_assert(std::numeric_limits::is_integer); + static_assert(!std::numeric_limits::is_signed); inline static T Get(R& randomGenerator, T minValue, T maxValue) { @@ -84,7 +83,7 @@ namespace CryRandom_Internal template struct BoundedRandom { - COMPILE_TIME_ASSERT(!std::numeric_limits::is_integer); + static_assert(!std::numeric_limits::is_integer); inline static T Get(R& randomGenerator, const T minValue, const T maxValue) { @@ -139,7 +138,7 @@ namespace CryRandom_Internal inline VT GetRandomUnitVector(R& randomGenerator) { typedef typename VT::value_type T; - COMPILE_TIME_ASSERT(!std::numeric_limits::is_integer); + static_assert(!std::numeric_limits::is_integer); VT res; T lenSquared; diff --git a/Code/Legacy/CryCommon/CryWindows.h b/Code/Legacy/CryCommon/CryWindows.h deleted file mode 100644 index 77684384c6..0000000000 --- a/Code/Legacy/CryCommon/CryWindows.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - -// Description : Specific header to handle Windows.h include - - -#ifndef CRYINCLUDE_CRYCOMMON_CRYWINDOWS_H -#define CRYINCLUDE_CRYCOMMON_CRYWINDOWS_H -#pragma once - -#include - -#endif // CRYINCLUDE_CRYCOMMON_CRYWINDOWS_H diff --git a/Code/Legacy/CryCommon/IMaterial.h b/Code/Legacy/CryCommon/IMaterial.h index f1967324d8..c5cd5712dc 100644 --- a/Code/Legacy/CryCommon/IMaterial.h +++ b/Code/Legacy/CryCommon/IMaterial.h @@ -41,7 +41,7 @@ struct IRenderMesh; #ifdef MAX_SUB_MATERIALS // This checks that the values are in sync in the different files. -COMPILE_TIME_ASSERT(MAX_SUB_MATERIALS == 128); +static_assert(MAX_SUB_MATERIALS == 128); #else #define MAX_SUB_MATERIALS 128 #endif diff --git a/Code/Legacy/CryCommon/ISystem.h b/Code/Legacy/CryCommon/ISystem.h index 7cea690687..2820a2fd8d 100644 --- a/Code/Legacy/CryCommon/ISystem.h +++ b/Code/Legacy/CryCommon/ISystem.h @@ -24,7 +24,6 @@ #endif #include "CryAssert.h" -#include "CompileTimeAssert.h" #include @@ -1428,10 +1427,10 @@ namespace Detail # define DeclareConstIntCVar(name, defaultValue) enum : int { name = (defaultValue) } # define DeclareStaticConstIntCVar(name, defaultValue) enum : int { name = (defaultValue) } -# define DefineConstIntCVarName(strname, name, defaultValue, flags, help) { COMPILE_TIME_ASSERT((int)(defaultValue) == (int)(name)); REGISTER_DUMMY_CVAR(int, strname, defaultValue); } -# define DefineConstIntCVar(name, defaultValue, flags, help) { COMPILE_TIME_ASSERT((int)(defaultValue) == (int)(name)); REGISTER_DUMMY_CVAR(int, (#name), defaultValue); } +# define DefineConstIntCVarName(strname, name, defaultValue, flags, help) { static_assert((int)(defaultValue) == (int)(name)); REGISTER_DUMMY_CVAR(int, strname, defaultValue); } +# define DefineConstIntCVar(name, defaultValue, flags, help) { static_assert((int)(defaultValue) == (int)(name)); REGISTER_DUMMY_CVAR(int, (#name), defaultValue); } // DefineConstIntCVar2 is deprecated, any such instance can be converted to the 3 variant by removing the quotes around the first parameter -# define DefineConstIntCVar3(name, _var_, defaultValue, flags, help) { COMPILE_TIME_ASSERT((int)(defaultValue) == (int)(_var_)); REGISTER_DUMMY_CVAR(int, name, defaultValue); } +# define DefineConstIntCVar3(name, _var_, defaultValue, flags, help) { static_assert((int)(defaultValue) == (int)(_var_)); REGISTER_DUMMY_CVAR(int, name, defaultValue); } # define AllocateConstIntCVar(scope, name) # define DefineConstFloatCVar(name, flags, help) { REGISTER_DUMMY_CVAR(float, (#name), name ## Default); } @@ -1543,33 +1542,33 @@ static void AssertConsoleExists(void) #define ILLEGAL_DEV_FLAGS (VF_NET_SYNCED | VF_CHEAT | VF_CHEAT_ALWAYS_CHECK | VF_CHEAT_NOCHECK | VF_READONLY | VF_CONST_CVAR) #if defined(_RELEASE) -#define REGISTER_CVAR_DEV_ONLY(_var, _def_val, _flags, _comment) NULL; COMPILE_TIME_ASSERT(((_flags) & ILLEGAL_DEV_FLAGS) == 0); _var = _def_val -#define REGISTER_CVAR_CB_DEV_ONLY(_var, _def_val, _flags, _comment, _onchangefunction) NULL; COMPILE_TIME_ASSERT(((_flags) & ILLEGAL_DEV_FLAGS) == 0); _var = _def_val /* _onchangefunction consumed; callback not available */ -#define REGISTER_STRING_DEV_ONLY(_name, _def_val, _flags, _comment) NULL; COMPILE_TIME_ASSERT(((_flags) & ILLEGAL_DEV_FLAGS) == 0) /* consumed; pure cvar not available */ -#define REGISTER_STRING_CB_DEV_ONLY(_name, _def_val, _flags, _comment, _onchangefunction) NULL; COMPILE_TIME_ASSERT(((_flags) & ILLEGAL_DEV_FLAGS) == 0) /* consumed; pure cvar not available */ -#define REGISTER_INT_DEV_ONLY(_name, _def_val, _flags, _comment) NULL; COMPILE_TIME_ASSERT(((_flags) & ILLEGAL_DEV_FLAGS) == 0) /* consumed; pure cvar not available */ -#define REGISTER_INT_CB_DEV_ONLY(_name, _def_val, _flags, _comment, _onchangefunction) NULL; COMPILE_TIME_ASSERT(((_flags) & ILLEGAL_DEV_FLAGS) == 0) /* consumed; pure cvar not available */ -#define REGISTER_INT64_DEV_ONLY(_name, _def_val, _flags, _comment) NULL; COMPILE_TIME_ASSERT(((_flags) & ILLEGAL_DEV_FLAGS) == 0) /* consumed; pure cvar not available */ -#define REGISTER_FLOAT_DEV_ONLY(_name, _def_val, _flags, _comment) NULL; COMPILE_TIME_ASSERT(((_flags) & ILLEGAL_DEV_FLAGS) == 0) /* consumed; pure cvar not available */ -#define REGISTER_CVAR2_DEV_ONLY(_name, _var, _def_val, _flags, _comment) NULL; COMPILE_TIME_ASSERT(((_flags) & ILLEGAL_DEV_FLAGS) == 0); *(_var) = _def_val -#define REGISTER_CVAR2_CB_DEV_ONLY(_name, _var, _def_val, _flags, _comment, _onchangefunction) NULL; COMPILE_TIME_ASSERT(((_flags) & ILLEGAL_DEV_FLAGS) == 0); *(_var) = _def_val -#define REGISTER_CVAR3_DEV_ONLY(_name, _var, _def_val, _flags, _comment) NULL; COMPILE_TIME_ASSERT(((_flags) & ILLEGAL_DEV_FLAGS) == 0); _var = _def_val -#define REGISTER_CVAR3_CB_DEV_ONLY(_name, _var, _def_val, _flags, _comment, _onchangefunction) NULL; COMPILE_TIME_ASSERT(((_flags) & ILLEGAL_DEV_FLAGS) == 0); _var = _def_val +#define REGISTER_CVAR_DEV_ONLY(_var, _def_val, _flags, _comment) NULL; static_assert(((_flags) & ILLEGAL_DEV_FLAGS) == 0); _var = _def_val +#define REGISTER_CVAR_CB_DEV_ONLY(_var, _def_val, _flags, _comment, _onchangefunction) NULL; static_assert(((_flags) & ILLEGAL_DEV_FLAGS) == 0); _var = _def_val /* _onchangefunction consumed; callback not available */ +#define REGISTER_STRING_DEV_ONLY(_name, _def_val, _flags, _comment) NULL; static_assert(((_flags) & ILLEGAL_DEV_FLAGS) == 0) /* consumed; pure cvar not available */ +#define REGISTER_STRING_CB_DEV_ONLY(_name, _def_val, _flags, _comment, _onchangefunction) NULL; static_assert(((_flags) & ILLEGAL_DEV_FLAGS) == 0) /* consumed; pure cvar not available */ +#define REGISTER_INT_DEV_ONLY(_name, _def_val, _flags, _comment) NULL; static_assert(((_flags) & ILLEGAL_DEV_FLAGS) == 0) /* consumed; pure cvar not available */ +#define REGISTER_INT_CB_DEV_ONLY(_name, _def_val, _flags, _comment, _onchangefunction) NULL; static_assert(((_flags) & ILLEGAL_DEV_FLAGS) == 0) /* consumed; pure cvar not available */ +#define REGISTER_INT64_DEV_ONLY(_name, _def_val, _flags, _comment) NULL; static_assert(((_flags) & ILLEGAL_DEV_FLAGS) == 0) /* consumed; pure cvar not available */ +#define REGISTER_FLOAT_DEV_ONLY(_name, _def_val, _flags, _comment) NULL; static_assert(((_flags) & ILLEGAL_DEV_FLAGS) == 0) /* consumed; pure cvar not available */ +#define REGISTER_CVAR2_DEV_ONLY(_name, _var, _def_val, _flags, _comment) NULL; static_assert(((_flags) & ILLEGAL_DEV_FLAGS) == 0); *(_var) = _def_val +#define REGISTER_CVAR2_CB_DEV_ONLY(_name, _var, _def_val, _flags, _comment, _onchangefunction) NULL; static_assert(((_flags) & ILLEGAL_DEV_FLAGS) == 0); *(_var) = _def_val +#define REGISTER_CVAR3_DEV_ONLY(_name, _var, _def_val, _flags, _comment) NULL; static_assert(((_flags) & ILLEGAL_DEV_FLAGS) == 0); _var = _def_val +#define REGISTER_CVAR3_CB_DEV_ONLY(_name, _var, _def_val, _flags, _comment, _onchangefunction) NULL; static_assert(((_flags) & ILLEGAL_DEV_FLAGS) == 0); _var = _def_val #define REGISTER_COMMAND_DEV_ONLY(_name, _func, _flags, _comment) /* consumed; command not available */ #else -#define REGISTER_CVAR_DEV_ONLY(_var, _def_val, _flags, _comment) REGISTER_CVAR(_var, _def_val, ((_flags) | VF_DEV_ONLY), _comment); COMPILE_TIME_ASSERT(((_flags) & ILLEGAL_DEV_FLAGS) == 0) -#define REGISTER_CVAR_CB_DEV_ONLY(_var, _def_val, _flags, _comment, _onchangefunction) REGISTER_CVAR_CB(_var, _def_val, ((_flags) | VF_DEV_ONLY), _comment, _onchangefunction); COMPILE_TIME_ASSERT(((_flags) & ILLEGAL_DEV_FLAGS) == 0) -#define REGISTER_STRING_DEV_ONLY(_name, _def_val, _flags, _comment) REGISTER_STRING(_name, _def_val, ((_flags) | VF_DEV_ONLY), _comment); COMPILE_TIME_ASSERT(((_flags) & ILLEGAL_DEV_FLAGS) == 0) -#define REGISTER_STRING_CB_DEV_ONLY(_name, _def_val, _flags, _comment, _onchangefunction) REGISTER_STRING_CB(_name, _def_val, ((_flags) | VF_DEV_ONLY), _comment, _onchangefunction); COMPILE_TIME_ASSERT(((_flags) & ILLEGAL_DEV_FLAGS) == 0) -#define REGISTER_INT_DEV_ONLY(_name, _def_val, _flags, _comment) REGISTER_INT(_name, _def_val, ((_flags) | VF_DEV_ONLY), _comment); COMPILE_TIME_ASSERT(((_flags) & ILLEGAL_DEV_FLAGS) == 0) -#define REGISTER_INT_CB_DEV_ONLY(_name, _def_val, _flags, _comment, _onchangefunction) REGISTER_INT_CB(_name, _def_val, ((_flags) | VF_DEV_ONLY), _comment, _onchangefunction); COMPILE_TIME_ASSERT(((_flags) & ILLEGAL_DEV_FLAGS) == 0) -#define REGISTER_INT64_DEV_ONLY(_name, _def_val, _flags, _comment) REGISTER_INT64(_name, _def_val, ((_flags) | VF_DEV_ONLY), _comment); COMPILE_TIME_ASSERT(((_flags) & ILLEGAL_DEV_FLAGS) == 0) -#define REGISTER_FLOAT_DEV_ONLY(_name, _def_val, _flags, _comment) REGISTER_FLOAT(_name, _def_val, ((_flags) | VF_DEV_ONLY), _comment); COMPILE_TIME_ASSERT(((_flags) & ILLEGAL_DEV_FLAGS) == 0) -#define REGISTER_CVAR2_DEV_ONLY(_name, _var, _def_val, _flags, _comment) REGISTER_CVAR2(_name, _var, _def_val, ((_flags) | VF_DEV_ONLY), _comment); COMPILE_TIME_ASSERT(((_flags) & ILLEGAL_DEV_FLAGS) == 0) -#define REGISTER_CVAR2_CB_DEV_ONLY(_name, _var, _def_val, _flags, _comment, _onchangefunction) REGISTER_CVAR2_CB(_name, _var, _def_val, ((_flags) | VF_DEV_ONLY), _comment, _onchangefunction); COMPILE_TIME_ASSERT(((_flags) & ILLEGAL_DEV_FLAGS) == 0) -#define REGISTER_CVAR3_DEV_ONLY(_name, _var, _def_val, _flags, _comment) REGISTER_CVAR3(_name, _var, _def_val, ((_flags) | VF_DEV_ONLY), _comment); COMPILE_TIME_ASSERT(((_flags) & ILLEGAL_DEV_FLAGS) == 0) -#define REGISTER_CVAR3_CB_DEV_ONLY(_name, _var, _def_val, _flags, _comment, _onchangefunction) REGISTER_CVAR3_CB(_name, _var, _def_val, ((_flags) | VF_DEV_ONLY), _comment, _onchangefunction); COMPILE_TIME_ASSERT(((_flags) & ILLEGAL_DEV_FLAGS) == 0) -#define REGISTER_COMMAND_DEV_ONLY(_name, _func, _flags, _comment) REGISTER_COMMAND(_name, _func, ((_flags) | VF_DEV_ONLY), _comment); COMPILE_TIME_ASSERT(((_flags) & ILLEGAL_DEV_FLAGS) == 0) +#define REGISTER_CVAR_DEV_ONLY(_var, _def_val, _flags, _comment) REGISTER_CVAR(_var, _def_val, ((_flags) | VF_DEV_ONLY), _comment); static_assert(((_flags) & ILLEGAL_DEV_FLAGS) == 0) +#define REGISTER_CVAR_CB_DEV_ONLY(_var, _def_val, _flags, _comment, _onchangefunction) REGISTER_CVAR_CB(_var, _def_val, ((_flags) | VF_DEV_ONLY), _comment, _onchangefunction); static_assert(((_flags) & ILLEGAL_DEV_FLAGS) == 0) +#define REGISTER_STRING_DEV_ONLY(_name, _def_val, _flags, _comment) REGISTER_STRING(_name, _def_val, ((_flags) | VF_DEV_ONLY), _comment); static_assert(((_flags) & ILLEGAL_DEV_FLAGS) == 0) +#define REGISTER_STRING_CB_DEV_ONLY(_name, _def_val, _flags, _comment, _onchangefunction) REGISTER_STRING_CB(_name, _def_val, ((_flags) | VF_DEV_ONLY), _comment, _onchangefunction); static_assert(((_flags) & ILLEGAL_DEV_FLAGS) == 0) +#define REGISTER_INT_DEV_ONLY(_name, _def_val, _flags, _comment) REGISTER_INT(_name, _def_val, ((_flags) | VF_DEV_ONLY), _comment); static_assert(((_flags) & ILLEGAL_DEV_FLAGS) == 0) +#define REGISTER_INT_CB_DEV_ONLY(_name, _def_val, _flags, _comment, _onchangefunction) REGISTER_INT_CB(_name, _def_val, ((_flags) | VF_DEV_ONLY), _comment, _onchangefunction); static_assert(((_flags) & ILLEGAL_DEV_FLAGS) == 0) +#define REGISTER_INT64_DEV_ONLY(_name, _def_val, _flags, _comment) REGISTER_INT64(_name, _def_val, ((_flags) | VF_DEV_ONLY), _comment); static_assert(((_flags) & ILLEGAL_DEV_FLAGS) == 0) +#define REGISTER_FLOAT_DEV_ONLY(_name, _def_val, _flags, _comment) REGISTER_FLOAT(_name, _def_val, ((_flags) | VF_DEV_ONLY), _comment); static_assert(((_flags) & ILLEGAL_DEV_FLAGS) == 0) +#define REGISTER_CVAR2_DEV_ONLY(_name, _var, _def_val, _flags, _comment) REGISTER_CVAR2(_name, _var, _def_val, ((_flags) | VF_DEV_ONLY), _comment); static_assert(((_flags) & ILLEGAL_DEV_FLAGS) == 0) +#define REGISTER_CVAR2_CB_DEV_ONLY(_name, _var, _def_val, _flags, _comment, _onchangefunction) REGISTER_CVAR2_CB(_name, _var, _def_val, ((_flags) | VF_DEV_ONLY), _comment, _onchangefunction); static_assert(((_flags) & ILLEGAL_DEV_FLAGS) == 0) +#define REGISTER_CVAR3_DEV_ONLY(_name, _var, _def_val, _flags, _comment) REGISTER_CVAR3(_name, _var, _def_val, ((_flags) | VF_DEV_ONLY), _comment); static_assert(((_flags) & ILLEGAL_DEV_FLAGS) == 0) +#define REGISTER_CVAR3_CB_DEV_ONLY(_name, _var, _def_val, _flags, _comment, _onchangefunction) REGISTER_CVAR3_CB(_name, _var, _def_val, ((_flags) | VF_DEV_ONLY), _comment, _onchangefunction); static_assert(((_flags) & ILLEGAL_DEV_FLAGS) == 0) +#define REGISTER_COMMAND_DEV_ONLY(_name, _func, _flags, _comment) REGISTER_COMMAND(_name, _func, ((_flags) | VF_DEV_ONLY), _comment); static_assert(((_flags) & ILLEGAL_DEV_FLAGS) == 0) #endif // defined(_RELEASE) // //////////////////////////////////////////////////////////////////////////////// @@ -1586,19 +1585,19 @@ static void AssertConsoleExists(void) // TODO Registering all cvars for Dedicated server as well. Currently CrySystems have no concept of Dedicated server with cmake. // If we introduce server specific targets for CrySystems, we can add DEDICATED_SERVER flags to those and add the flag back in here. #if defined(_RELEASE) -#define REGISTER_CVAR_DEDI_ONLY(_var, _def_val, _flags, _comment) REGISTER_CVAR(_var, _def_val, ((_flags) | VF_DEDI_ONLY), _comment); COMPILE_TIME_ASSERT(((_flags) & ILLEGAL_DEV_FLAGS) == 0) -#define REGISTER_CVAR_CB_DEDI_ONLY(_var, _def_val, _flags, _comment, _onchangefunction) REGISTER_CVAR_CB(_var, _def_val, ((_flags) | VF_DEDI_ONLY), _comment, _onchangefunction); COMPILE_TIME_ASSERT(((_flags) & ILLEGAL_DEV_FLAGS) == 0) -#define REGISTER_STRING_DEDI_ONLY(_name, _def_val, _flags, _comment) REGISTER_STRING(_name, _def_val, ((_flags) | VF_DEDI_ONLY), _comment); COMPILE_TIME_ASSERT(((_flags) & ILLEGAL_DEV_FLAGS) == 0) -#define REGISTER_STRING_CB_DEDI_ONLY(_name, _def_val, _flags, _comment, _onchangefunction) REGISTER_STRING_CB(_name, _def_val, ((_flags) | VF_DEDI_ONLY), _comment, _onchangefunction); COMPILE_TIME_ASSERT(((_flags) & ILLEGAL_DEV_FLAGS) == 0) -#define REGISTER_INT_DEDI_ONLY(_name, _def_val, _flags, _comment) REGISTER_INT(_name, _def_val, ((_flags) | VF_DEDI_ONLY), _comment); COMPILE_TIME_ASSERT(((_flags) & ILLEGAL_DEV_FLAGS) == 0) -#define REGISTER_INT_CB_DEDI_ONLY(_name, _def_val, _flags, _comment, _onchangefunction) REGISTER_INT_CB(_name, _def_val, ((_flags) | VF_DEDI_ONLY), _comment, _onchangefunction); COMPILE_TIME_ASSERT(((_flags) & ILLEGAL_DEV_FLAGS) == 0) -#define REGISTER_INT64_DEDI_ONLY(_name, _def_val, _flags, _comment) REGISTER_INT64(_name, _def_val, ((_flags) | VF_DEDI_ONLY), _comment); COMPILE_TIME_ASSERT(((_flags) & ILLEGAL_DEV_FLAGS) == 0) -#define REGISTER_FLOAT_DEDI_ONLY(_name, _def_val, _flags, _comment) REGISTER_FLOAT(_name, _def_val, ((_flags) | VF_DEDI_ONLY), _comment); COMPILE_TIME_ASSERT(((_flags) & ILLEGAL_DEV_FLAGS) == 0) -#define REGISTER_CVAR2_DEDI_ONLY(_name, _var, _def_val, _flags, _comment) REGISTER_CVAR2(_name, _var, _def_val, ((_flags) | VF_DEDI_ONLY), _comment); COMPILE_TIME_ASSERT(((_flags) & ILLEGAL_DEV_FLAGS) == 0) -#define REGISTER_CVAR2_CB_DEDI_ONLY(_name, _var, _def_val, _flags, _comment, _onchangefunction) REGISTER_CVAR2_CB(_name, _var, _def_val, ((_flags) | VF_DEDI_ONLY), _comment, _onchangefunction); COMPILE_TIME_ASSERT(((_flags) & ILLEGAL_DEV_FLAGS) == 0) -#define REGISTER_CVAR3_DEDI_ONLY(_name, _var, _def_val, _flags, _comment) REGISTER_CVAR3(_name, _var, _def_val, ((_flags) | VF_DEDI_ONLY), _comment); COMPILE_TIME_ASSERT(((_flags) & ILLEGAL_DEV_FLAGS) == 0) -#define REGISTER_CVAR3_CB_DEDI_ONLY(_name, _var, _def_val, _flags, _comment, _onchangefunction) REGISTER_CVAR3_CB(_name, _var, _def_val, ((_flags) | VF_DEDI_ONLY), _comment, _onchangefunction); COMPILE_TIME_ASSERT(((_flags) & ILLEGAL_DEV_FLAGS) == 0) -#define REGISTER_COMMAND_DEDI_ONLY(_name, _func, _flags, _comment) REGISTER_COMMAND(_name, _func, ((_flags) | VF_DEDI_ONLY), _comment); COMPILE_TIME_ASSERT(((_flags) & ILLEGAL_DEV_FLAGS) == 0) +#define REGISTER_CVAR_DEDI_ONLY(_var, _def_val, _flags, _comment) REGISTER_CVAR(_var, _def_val, ((_flags) | VF_DEDI_ONLY), _comment); static_assert(((_flags) & ILLEGAL_DEV_FLAGS) == 0) +#define REGISTER_CVAR_CB_DEDI_ONLY(_var, _def_val, _flags, _comment, _onchangefunction) REGISTER_CVAR_CB(_var, _def_val, ((_flags) | VF_DEDI_ONLY), _comment, _onchangefunction); static_assert(((_flags) & ILLEGAL_DEV_FLAGS) == 0) +#define REGISTER_STRING_DEDI_ONLY(_name, _def_val, _flags, _comment) REGISTER_STRING(_name, _def_val, ((_flags) | VF_DEDI_ONLY), _comment); static_assert(((_flags) & ILLEGAL_DEV_FLAGS) == 0) +#define REGISTER_STRING_CB_DEDI_ONLY(_name, _def_val, _flags, _comment, _onchangefunction) REGISTER_STRING_CB(_name, _def_val, ((_flags) | VF_DEDI_ONLY), _comment, _onchangefunction); static_assert(((_flags) & ILLEGAL_DEV_FLAGS) == 0) +#define REGISTER_INT_DEDI_ONLY(_name, _def_val, _flags, _comment) REGISTER_INT(_name, _def_val, ((_flags) | VF_DEDI_ONLY), _comment); static_assert(((_flags) & ILLEGAL_DEV_FLAGS) == 0) +#define REGISTER_INT_CB_DEDI_ONLY(_name, _def_val, _flags, _comment, _onchangefunction) REGISTER_INT_CB(_name, _def_val, ((_flags) | VF_DEDI_ONLY), _comment, _onchangefunction); static_assert(((_flags) & ILLEGAL_DEV_FLAGS) == 0) +#define REGISTER_INT64_DEDI_ONLY(_name, _def_val, _flags, _comment) REGISTER_INT64(_name, _def_val, ((_flags) | VF_DEDI_ONLY), _comment); static_assert(((_flags) & ILLEGAL_DEV_FLAGS) == 0) +#define REGISTER_FLOAT_DEDI_ONLY(_name, _def_val, _flags, _comment) REGISTER_FLOAT(_name, _def_val, ((_flags) | VF_DEDI_ONLY), _comment); static_assert(((_flags) & ILLEGAL_DEV_FLAGS) == 0) +#define REGISTER_CVAR2_DEDI_ONLY(_name, _var, _def_val, _flags, _comment) REGISTER_CVAR2(_name, _var, _def_val, ((_flags) | VF_DEDI_ONLY), _comment); static_assert(((_flags) & ILLEGAL_DEV_FLAGS) == 0) +#define REGISTER_CVAR2_CB_DEDI_ONLY(_name, _var, _def_val, _flags, _comment, _onchangefunction) REGISTER_CVAR2_CB(_name, _var, _def_val, ((_flags) | VF_DEDI_ONLY), _comment, _onchangefunction); static_assert(((_flags) & ILLEGAL_DEV_FLAGS) == 0) +#define REGISTER_CVAR3_DEDI_ONLY(_name, _var, _def_val, _flags, _comment) REGISTER_CVAR3(_name, _var, _def_val, ((_flags) | VF_DEDI_ONLY), _comment); static_assert(((_flags) & ILLEGAL_DEV_FLAGS) == 0) +#define REGISTER_CVAR3_CB_DEDI_ONLY(_name, _var, _def_val, _flags, _comment, _onchangefunction) REGISTER_CVAR3_CB(_name, _var, _def_val, ((_flags) | VF_DEDI_ONLY), _comment, _onchangefunction); static_assert(((_flags) & ILLEGAL_DEV_FLAGS) == 0) +#define REGISTER_COMMAND_DEDI_ONLY(_name, _func, _flags, _comment) REGISTER_COMMAND(_name, _func, ((_flags) | VF_DEDI_ONLY), _comment); static_assert(((_flags) & ILLEGAL_DEV_FLAGS) == 0) #else #define REGISTER_CVAR_DEDI_ONLY(_var, _def_val, _flags, _comment) REGISTER_CVAR_DEV_ONLY(_var, _def_val, ((_flags) | VF_DEDI_ONLY), _comment) #define REGISTER_CVAR_CB_DEDI_ONLY(_var, _def_val, _flags, _comment, _onchangefunction) REGISTER_CVAR_CB_DEV_ONLY(_var, _def_val, ((_flags) | VF_DEDI_ONLY), _comment, _onchangefunction) diff --git a/Code/Legacy/CryCommon/ITexture.h b/Code/Legacy/CryCommon/ITexture.h index 5b9b43ceb5..170e3b6709 100644 --- a/Code/Legacy/CryCommon/ITexture.h +++ b/Code/Legacy/CryCommon/ITexture.h @@ -314,8 +314,8 @@ public: void GetMemoryUsage([[maybe_unused]] ICrySizer* pSizer) const { - COMPILE_TIME_ASSERT(eTT_MaxTexType <= 255); - COMPILE_TIME_ASSERT(eTF_MaxFormat <= 255); + static_assert(eTT_MaxTexType <= 255); + static_assert(eTF_MaxFormat <= 255); /*LATER*/ } diff --git a/Code/Legacy/CryCommon/Linux32Specific.h b/Code/Legacy/CryCommon/Linux32Specific.h index e66838f431..6812ddb818 100644 --- a/Code/Legacy/CryCommon/Linux32Specific.h +++ b/Code/Legacy/CryCommon/Linux32Specific.h @@ -18,10 +18,6 @@ #define _CPU_X86 //#define _CPU_SSE -#define RC_EXECUTABLE "rc" -#define USE_CRT 1 -#define SIZEOF_PTR 4 - ////////////////////////////////////////////////////////////////////////// // Standard includes. ////////////////////////////////////////////////////////////////////////// @@ -97,10 +93,6 @@ typedef unsigned char byte; #define DEFINE_ALIGNED_DATA(type, name, alignment) \ type __attribute__ ((aligned(alignment))) name; -#define DEFINE_ALIGNED_DATA_STATIC(type, name, alignment) \ - static type __attribute__ ((aligned(alignment))) name; -#define DEFINE_ALIGNED_DATA_CONST(type, name, alignment) \ - const type __attribute__ ((aligned(alignment))) name; #include "LinuxSpecific.h" diff --git a/Code/Legacy/CryCommon/Linux64Specific.h b/Code/Legacy/CryCommon/Linux64Specific.h index 0aa9321025..4dcb5f1e84 100644 --- a/Code/Legacy/CryCommon/Linux64Specific.h +++ b/Code/Legacy/CryCommon/Linux64Specific.h @@ -20,10 +20,6 @@ #define _CPU_AMD64 #define _CPU_SSE -#define RC_EXECUTABLE "rc" -#define USE_CRT 1 -#define SIZEOF_PTR 8 - ////////////////////////////////////////////////////////////////////////// // Standard includes. ////////////////////////////////////////////////////////////////////////// @@ -103,10 +99,6 @@ typedef uint8 byte; #define DEFINE_ALIGNED_DATA(type, name, alignment) \ type __attribute__ ((aligned(alignment))) name; -#define DEFINE_ALIGNED_DATA_STATIC(type, name, alignment) \ - static type __attribute__ ((aligned(alignment))) name; -#define DEFINE_ALIGNED_DATA_CONST(type, name, alignment) \ - const type __attribute__ ((aligned(alignment))) name; #include "LinuxSpecific.h" diff --git a/Code/Legacy/CryCommon/LinuxSpecific.h b/Code/Legacy/CryCommon/LinuxSpecific.h index cbffae5957..a587350cb2 100644 --- a/Code/Legacy/CryCommon/LinuxSpecific.h +++ b/Code/Legacy/CryCommon/LinuxSpecific.h @@ -182,7 +182,6 @@ typedef int64 __int64; typedef uint64 __uint64; #endif -#define THREADID_NULL -1 typedef unsigned long int threadID; #define TRUE 1 @@ -213,27 +212,6 @@ typedef unsigned long int threadID; #define _wtof(str) wcstod(str, 0) -/*static unsigned char toupper(unsigned char c) -{ - return c & ~0x40; -} -*/ -typedef union _LARGE_INTEGER -{ - struct - { - DWORD LowPart; - LONG HighPart; - }; - struct - { - DWORD LowPart; - LONG HighPart; - } u; - long long QuadPart; -} LARGE_INTEGER; - - // stdlib.h stuff #define _MAX_DRIVE 3 // max. length of drive component #define _MAX_DIR 256 // max. length of path component @@ -257,21 +235,6 @@ typedef union _LARGE_INTEGER #define _O_SEQUENTIAL 0x0020 /* file access is primarily sequential */ #define _O_RANDOM 0x0010 /* file access is primarily random */ -// curses.h stubs for PDcurses keys -#define PADENTER KEY_MAX + 1 -#define CTL_HOME KEY_MAX + 2 -#define CTL_END KEY_MAX + 3 -#define CTL_PGDN KEY_MAX + 4 -#define CTL_PGUP KEY_MAX + 5 - -// stubs for virtual keys, isn't used on Linux -#define VK_UP 0 -#define VK_DOWN 0 -#define VK_RIGHT 0 -#define VK_LEFT 0 -#define VK_CONTROL 0 -#define VK_SCROLL 0 - enum { IDOK = 1, @@ -285,17 +248,6 @@ enum IDCONTINUE = 11 }; -#define ES_MULTILINE 0x0004L -#define ES_AUTOVSCROLL 0x0040L -#define ES_AUTOHSCROLL 0x0080L -#define ES_WANTRETURN 0x1000L - -#define LB_ERR (-1) - -#define LB_ADDSTRING 0x0180 -#define LB_GETCOUNT 0x018B -#define LB_SETTOPINDEX 0x0197 - #define MB_OK 0x00000000L #define MB_OKCANCEL 0x00000001L #define MB_ABORTRETRYIGNORE 0x00000002L @@ -315,22 +267,16 @@ enum #define MB_APPLMODAL 0x00000000L -#define MF_STRING 0x00000000L - #define MK_LBUTTON 0x0001 #define MK_RBUTTON 0x0002 #define MK_SHIFT 0x0004 #define MK_CONTROL 0x0008 #define MK_MBUTTON 0x0010 -#define MK_ALT ( 0x20 ) - #define SM_MOUSEPRESENT 0x00000000L #define SM_CMOUSEBUTTONS 43 -#define USER_TIMER_MINIMUM 0x0000000A - #define VK_TAB 0x09 #define VK_SHIFT 0x10 #define VK_MENU 0x12 @@ -338,11 +284,6 @@ enum #define VK_SPACE 0x20 #define VK_DELETE 0x2E -#define VK_NUMPAD1 0x61 -#define VK_NUMPAD2 0x62 -#define VK_NUMPAD3 0x63 -#define VK_NUMPAD4 0x64 - #define VK_OEM_COMMA 0xBC // ',' any country #define VK_OEM_PERIOD 0xBE // '.' any country #define VK_OEM_3 0xC0 // '`~' for US @@ -529,36 +470,11 @@ inline int64 CryGetTicksPerSec() inline int _CrtCheckMemory() { return 1; }; -inline char* _fullpath(char* absPath, const char* relPath, size_t maxLength) -{ - char path[PATH_MAX]; - - if (realpath(relPath, path) == NULL) - { - return NULL; - } - const size_t len = std::min(strlen(path), maxLength - 1); - memcpy(absPath, path, len); - absPath[len] = 0; - return absPath; -} - typedef void* HGLRC; typedef void* HDC; typedef void* PROC; typedef void* PIXELFORMATDESCRIPTOR; -#define SCOPED_ENABLE_FLOAT_EXCEPTIONS - -// Linux_Win32Wrapper.h now included directly by platform.h -//#include "Linux_Win32Wrapper.h" - -#define closesocket close -inline int WSAGetLastError() -{ - return errno; -} - template char (*RtlpNumberOf( T (&)[N] ))[N]; diff --git a/Code/Legacy/CryCommon/Linux_Win32Wrapper.h b/Code/Legacy/CryCommon/Linux_Win32Wrapper.h index 23cd7faf7f..2de17e6b28 100644 --- a/Code/Legacy/CryCommon/Linux_Win32Wrapper.h +++ b/Code/Legacy/CryCommon/Linux_Win32Wrapper.h @@ -490,8 +490,6 @@ extern void adaptFilenameToLinux(char* rAdjustedFilename); extern const int comparePathNames(const char* cpFirst, const char* cpSecond, unsigned int len);//returns 0 if identical extern void replaceDoublePathFilename(char* szFileName);//removes "\.\" to "\" and "/./" to "/" -////////////////////////////////////////////////////////////////////////// -extern char* _fullpath(char* absPath, const char* relPath, size_t maxLength); ////////////////////////////////////////////////////////////////////////// extern void _makepath(char* path, const char* drive, const char* dir, const char* filename, const char* ext); diff --git a/Code/Legacy/CryCommon/MacSpecific.h b/Code/Legacy/CryCommon/MacSpecific.h index 30bcd6c6db..0533a1b556 100644 --- a/Code/Legacy/CryCommon/MacSpecific.h +++ b/Code/Legacy/CryCommon/MacSpecific.h @@ -24,40 +24,6 @@ #define _CPU_SSE #define PLATFORM_64BIT -#define USE_CRT 1 -#define SIZEOF_PTR 8 - typedef uint64_t threadID; - -// curses.h stubs for PDcurses keys -#define PADENTER KEY_MAX + 1 -#define CTL_HOME KEY_MAX + 2 -#define CTL_END KEY_MAX + 3 -#define CTL_PGDN KEY_MAX + 4 -#define CTL_PGUP KEY_MAX + 5 - -// stubs for virtual keys, isn't used on Mac -#define VK_UP 0 -#define VK_DOWN 0 -#define VK_RIGHT 0 -#define VK_LEFT 0 -#define VK_CONTROL 0 -#define VK_SCROLL 0 - -#define MAC_NOT_IMPLEMENTED assert(false); - - -typedef enum -{ - eDAContinue, - eDAIgnore, - eDAIgnoreAll, - eDABreak, - eDAStop, - eDAReportAsBug -} EDialogAction; - -extern EDialogAction MacOSXHandleAssert(const char* condition, const char* file, int line, const char* reason, bool); - #endif // CRYINCLUDE_CRYCOMMON_MACSPECIFIC_H diff --git a/Code/Legacy/CryCommon/Options.h b/Code/Legacy/CryCommon/Options.h index 925f1f747e..935c8bd371 100644 --- a/Code/Legacy/CryCommon/Options.h +++ b/Code/Legacy/CryCommon/Options.h @@ -80,7 +80,7 @@ private: typedef Struc TThis; typedef Int TInt; \ TInt Mask() const { return *(const TInt*)this; } \ TInt& Mask() { return *(TInt*)this; } \ - Struc(TInt init = 0) { COMPILE_TIME_ASSERT(sizeof(TThis) == sizeof(TInt)); Mask() = init; } \ + Struc(TInt init = 0) { static_assert(sizeof(TThis) == sizeof(TInt)); Mask() = init; } \ #define BIT_VAR(Var) \ TInt _##Var : 1; \ diff --git a/Code/Legacy/CryCommon/StringUtils.h b/Code/Legacy/CryCommon/StringUtils.h index ffd1001f95..d6c3d829d2 100644 --- a/Code/Legacy/CryCommon/StringUtils.h +++ b/Code/Legacy/CryCommon/StringUtils.h @@ -65,7 +65,7 @@ namespace CryStringUtils_Internal template inline bool strcpy_with_clamp(TChar* const dst, size_t const dst_size_in_bytes, const TChar* const src, size_t const src_size_in_bytes) { - COMPILE_TIME_ASSERT(sizeof(TChar) == sizeof(char) || sizeof(TChar) == sizeof(wchar_t)); + static_assert(sizeof(TChar) == sizeof(char) || sizeof(TChar) == sizeof(wchar_t)); if (!dst || dst_size_in_bytes < sizeof(TChar)) { @@ -97,7 +97,7 @@ namespace CryStringUtils_Internal template inline bool strcat_with_clamp(TChar* const dst, size_t const dst_size_in_bytes, const TChar* const src, size_t const src_size_in_bytes) { - COMPILE_TIME_ASSERT(sizeof(TChar) == sizeof(char) || sizeof(TChar) == sizeof(wchar_t)); + static_assert(sizeof(TChar) == sizeof(char) || sizeof(TChar) == sizeof(wchar_t)); if (!dst || dst_size_in_bytes < sizeof(TChar)) { diff --git a/Code/Legacy/CryCommon/UnicodeBinding.h b/Code/Legacy/CryCommon/UnicodeBinding.h index e6e82aaf49..7a058650b5 100644 --- a/Code/Legacy/CryCommon/UnicodeBinding.h +++ b/Code/Legacy/CryCommon/UnicodeBinding.h @@ -211,7 +211,7 @@ namespace Unicode >::type >::type CharType; static const size_t FixedSize = extent::value; - COMPILE_TIME_ASSERT(!is_array::value || FixedSize > 0); + static_assert(!is_array::value || FixedSize > 0); static const bool isConstArray = is_array::value && is_const::type>::value; static const bool isBufferArray = is_array::value && !isConstArray; static const bool isPointer = is_pointer::value; @@ -393,7 +393,7 @@ namespace Unicode sizeof(CharType) == 1 ? eEncoding_UTF8 : sizeof(CharType) == 2 ? eEncoding_UTF16 : eEncoding_UTF32; - COMPILE_TIME_ASSERT(value != eEncoding_UTF32 || sizeof(CharType) == 4); + static_assert(value != eEncoding_UTF32 || sizeof(CharType) == 4); }; // SBindCharacter: @@ -408,7 +408,7 @@ namespace Unicode template struct SBindCharacter { - COMPILE_TIME_ASSERT(is_arithmetic::value); + static_assert(is_arithmetic::value); typedef typename remove_cv::type UnqualifiedType; typedef typename conditional::type type; }; @@ -417,7 +417,7 @@ namespace Unicode { typedef typename conditional::type type; typedef typename SDependentType::type ActuallyQChar; // Force two-phase name lookup on QChar. - COMPILE_TIME_ASSERT(sizeof(ActuallyQChar) == sizeof(type)); // In case Qt ever changes QChar. + static_assert(sizeof(ActuallyQChar) == sizeof(type)); // In case Qt ever changes QChar. }; // SBindPointer: @@ -425,7 +425,7 @@ namespace Unicode template struct SBindPointer { - COMPILE_TIME_ASSERT(is_pointer::value || is_array::value); + static_assert(is_pointer::value || is_array::value); typedef typename conditional< is_pointer::value, typename remove_pointer::type, @@ -458,8 +458,8 @@ namespace Unicode { // Allow casts from pointer-to-integral to unrelated pointer-to-integral, provided they are of the same size. typedef typename remove_pointer::type TargetChar; - COMPILE_TIME_ASSERT(is_integral::value && is_integral::value); - COMPILE_TIME_ASSERT(sizeof(SourceChar) == sizeof(TargetChar)); + static_assert(is_integral::value && is_integral::value); + static_assert(sizeof(SourceChar) == sizeof(TargetChar)); return reinterpret_cast(ptr); } template @@ -467,8 +467,8 @@ namespace Unicode { // Allow casts from pointer-to-QChar to unrelated pointer-to-integral, provided they are of the same size. typedef typename remove_pointer::type TargetChar; - COMPILE_TIME_ASSERT(is_integral::value); - COMPILE_TIME_ASSERT(sizeof(SourceChar) == sizeof(TargetChar)); + static_assert(is_integral::value); + static_assert(sizeof(SourceChar) == sizeof(TargetChar)); return reinterpret_cast(ptr); } template @@ -612,7 +612,7 @@ namespace Unicode template inline void Feed(const InputStringType& in, Sink& out, integral_constant) { - COMPILE_TIME_ASSERT(is_array::value && extent::value > 0); + static_assert(is_array::value && extent::value > 0); typedef typename SBindPointer::type PointerType; const size_t length = extent::value - 1; PointerType ptr = SafeCast(in); @@ -630,7 +630,7 @@ namespace Unicode template inline void Feed(const InputStringType& in, Sink& out, integral_constant) { - COMPILE_TIME_ASSERT(is_array::value && extent::value > 0); + static_assert(is_array::value && extent::value > 0); typedef typename SBindPointer::type PointerType; typedef typename SBindPointer::BoundCharType CharType; const size_t length = extent::value; @@ -652,7 +652,7 @@ namespace Unicode template inline void Feed(const InputStringType& in, Sink& out, integral_constant) { - COMPILE_TIME_ASSERT(is_pointer::value); + static_assert(is_pointer::value); typedef typename SBindPointer::type PointerType; typedef typename SBindPointer::BoundCharType CharType; PointerType ptr = SafeCast(in); @@ -677,7 +677,7 @@ namespace Unicode template inline void Feed(const InputCharType& in, Sink& out, integral_constant) { - COMPILE_TIME_ASSERT(is_arithmetic::value); + static_assert(is_arithmetic::value); const uint32 item = static_cast(in); out(item); } @@ -711,7 +711,7 @@ namespace Unicode template inline size_t EncodedLength(const InputStringType& in, integral_constant) { - COMPILE_TIME_ASSERT(is_array::value && extent::value > 0); + static_assert(is_array::value && extent::value > 0); return extent::value - 1; } @@ -720,7 +720,7 @@ namespace Unicode template inline size_t EncodedLength(const InputStringType& in, integral_constant) { - COMPILE_TIME_ASSERT(is_array::value && extent::value > 0); + static_assert(is_array::value && extent::value > 0); typedef typename remove_extent::type CharType; return SCharacterTrait::StrNLen(in, extent::value); } @@ -738,7 +738,7 @@ namespace Unicode template inline size_t EncodedLength(const InputStringType& in, integral_constant) { - COMPILE_TIME_ASSERT(is_pointer::value); + static_assert(is_pointer::value); typedef typename remove_pointer::type CharType; return in ? SCharacterTrait::StrLen(in) : 0; } @@ -748,7 +748,7 @@ namespace Unicode template inline size_t EncodedLength([[maybe_unused]] const InputCharType& in, integral_constant) { - COMPILE_TIME_ASSERT(is_arithmetic::value); + static_assert(is_arithmetic::value); return 1; } @@ -775,7 +775,7 @@ namespace Unicode template inline const void* EncodedPointer(const InputStringType& in, integral_constant) { - COMPILE_TIME_ASSERT(is_array::value && extent::value > 0); + static_assert(is_array::value && extent::value > 0); return in; // We can just let the array type decay to a pointer. } @@ -784,7 +784,7 @@ namespace Unicode template inline const void* EncodedPointer(const InputStringType& in, integral_constant) { - COMPILE_TIME_ASSERT(is_array::value && extent::value > 0); + static_assert(is_array::value && extent::value > 0); return in; // We can just let the array type decay to a pointer. } @@ -793,7 +793,7 @@ namespace Unicode template inline const void* EncodedPointer(const InputStringType& in, integral_constant) { - COMPILE_TIME_ASSERT(is_pointer::value); + static_assert(is_pointer::value); return in; // Implied } @@ -802,7 +802,7 @@ namespace Unicode template inline const void* EncodedPointer(const InputCharType& in, integral_constant) { - COMPILE_TIME_ASSERT(is_arithmetic::value); + static_assert(is_arithmetic::value); return ∈ // Take the address of the parameter (which is kept on the stack of the caller). } diff --git a/Code/Legacy/CryCommon/UnicodeEncoding.h b/Code/Legacy/CryCommon/UnicodeEncoding.h index a3e20b639c..fb2d398cb6 100644 --- a/Code/Legacy/CryCommon/UnicodeEncoding.h +++ b/Code/Legacy/CryCommon/UnicodeEncoding.h @@ -17,7 +17,7 @@ #pragma once #include "BaseTypes.h" // For uint8, uint16, uint32 -#include "CompileTimeAssert.h" // For COMPILE_TIME_ASSERT macro + namespace Unicode { // Supported encoding/conversion types. @@ -631,7 +631,7 @@ namespace Unicode struct SRecoveryFallbackHelper { // A compilation error here means RecoveryMethod value was unexpected here - COMPILE_TIME_ASSERT( + static_assert( RecoveryMethod == eErrorRecovery_FallbackLatin1ThenDiscard || RecoveryMethod == eErrorRecovery_FallbackLatin1ThenReplace || RecoveryMethod == eErrorRecovery_FallbackWin1252ThenDiscard || diff --git a/Code/Legacy/CryCommon/UnicodeFunctions.h b/Code/Legacy/CryCommon/UnicodeFunctions.h index 48debe9706..31fc7991c3 100644 --- a/Code/Legacy/CryCommon/UnicodeFunctions.h +++ b/Code/Legacy/CryCommon/UnicodeFunctions.h @@ -266,7 +266,7 @@ namespace Unicode inline size_t LengthSafe(const InputStringType& source) { // SRequire a safe recovery method. - COMPILE_TIME_ASSERT(SIsSafeEncoding::value); + static_assert(SIsSafeEncoding::value); // Bind methods. const EBind bindMethod = SBindObject::value; @@ -379,7 +379,7 @@ namespace Unicode inline size_t ConvertSafe(OutputStringType& target, const InputStringType& source) { // SRequire a safe recovery method. - COMPILE_TIME_ASSERT(SIsSafeEncoding::value); + static_assert(SIsSafeEncoding::value); // Bind methods. const EBind inputBindMethod = SBindObject::value; diff --git a/Code/Legacy/CryCommon/UnicodeIterator.h b/Code/Legacy/CryCommon/UnicodeIterator.h index d939eaa721..c28378ea44 100644 --- a/Code/Legacy/CryCommon/UnicodeIterator.h +++ b/Code/Legacy/CryCommon/UnicodeIterator.h @@ -27,7 +27,7 @@ namespace Unicode template inline void MoveNext(BaseIterator& it, const BoundsChecker& checker, const integral_constant) { - COMPILE_TIME_ASSERT( + static_assert( Encoding == eEncoding_ASCII || Encoding == eEncoding_UTF32 || Encoding == eEncoding_Latin1 || @@ -88,7 +88,7 @@ namespace Unicode template inline void MovePrev(BaseIterator& it, const BoundsChecker& checker, const integral_constant) { - COMPILE_TIME_ASSERT( + static_assert( Encoding == eEncoding_ASCII || Encoding == eEncoding_UTF32 || Encoding == eEncoding_Latin1 || diff --git a/Code/Legacy/CryCommon/Win32specific.h b/Code/Legacy/CryCommon/Win32specific.h index 0519bb1022..62d32138b4 100644 --- a/Code/Legacy/CryCommon/Win32specific.h +++ b/Code/Legacy/CryCommon/Win32specific.h @@ -23,10 +23,7 @@ #define ILINE __forceinline #endif -#define RC_EXECUTABLE "rc.exe" #define DEPRECATED __declspec(deprecated) -#define TYPENAME(x) typeid(x).name() -#define SIZEOF_PTR 4 #ifndef _WIN32_WINNT # define _WIN32_WINNT 0x501 @@ -54,8 +51,6 @@ ////////////////////////////////////////////////////////////////////////// #include "BaseTypes.h" -#define THREADID_NULL -1 - typedef unsigned char BYTE; typedef unsigned int threadID; typedef unsigned long DWORD; @@ -111,14 +106,11 @@ int64 CryGetTicksPerSec(); __declspec(align(num)) #define DEFINE_ALIGNED_DATA(type, name, alignment) _declspec(align(alignment)) type name; -#define DEFINE_ALIGNED_DATA_STATIC(type, name, alignment) static _declspec(align(alignment)) type name; -#define DEFINE_ALIGNED_DATA_CONST(type, name, alignment) const _declspec(align(alignment)) type name; #ifndef FILE_ATTRIBUTE_NORMAL #define FILE_ATTRIBUTE_NORMAL 0x00000080 #endif -#define FP16_TERRAIN #define TARGET_DEFAULT_ALIGN (0x4U) diff --git a/Code/Legacy/CryCommon/Win64specific.h b/Code/Legacy/CryCommon/Win64specific.h index b1e86f9250..47c9c1aad9 100644 --- a/Code/Legacy/CryCommon/Win64specific.h +++ b/Code/Legacy/CryCommon/Win64specific.h @@ -19,10 +19,7 @@ #define _CPU_SSE #define ILINE __forceinline -#define RC_EXECUTABLE "rc.exe" #define DEPRECATED __declspec(deprecated) -#define TYPENAME(x) typeid(x).name() -#define SIZEOF_PTR 8 #ifndef _WIN32_WINNT # define _WIN32_WINNT 0x501 @@ -51,7 +48,6 @@ ////////////////////////////////////////////////////////////////////////// #include "BaseTypes.h" -#define THREADID_NULL -1 typedef long LONG; typedef unsigned char BYTE; typedef unsigned long threadID; @@ -93,10 +89,6 @@ int64 CryGetTicksPerSec(); __declspec(align(num)) #define DEFINE_ALIGNED_DATA(type, name, alignment) _declspec(align(alignment)) type name; -#define DEFINE_ALIGNED_DATA_STATIC(type, name, alignment) static _declspec(align(alignment)) type name; -#define DEFINE_ALIGNED_DATA_CONST(type, name, alignment) const _declspec(align(alignment)) type name; - -#define SIZEOF_PTR 8 #ifndef FILE_ATTRIBUTE_NORMAL #define FILE_ATTRIBUTE_NORMAL 0x00000080 diff --git a/Code/Legacy/CryCommon/crycommon_files.cmake b/Code/Legacy/CryCommon/crycommon_files.cmake index 0392f11c89..18cbd16f4b 100644 --- a/Code/Legacy/CryCommon/crycommon_files.cmake +++ b/Code/Legacy/CryCommon/crycommon_files.cmake @@ -68,7 +68,6 @@ set(FILES LCGRandom.h CryTypeInfo.cpp BaseTypes.h - CompileTimeAssert.h MemoryAccess.h AnimKey.h BitFiddling.h @@ -165,7 +164,6 @@ set(FILES CryThread_windows.h CryThreadImpl_pthreads.h CryThreadImpl_windows.h - CryWindows.h Linux32Specific.h Linux64Specific.h Linux_Win32Wrapper.h diff --git a/Code/Legacy/CryCommon/iOSSpecific.h b/Code/Legacy/CryCommon/iOSSpecific.h index d2503a7441..ac2461b55b 100644 --- a/Code/Legacy/CryCommon/iOSSpecific.h +++ b/Code/Legacy/CryCommon/iOSSpecific.h @@ -47,11 +47,9 @@ #define VK_SCROLL 0 -//#define USE_CRT 1 #if !defined(PLATFORM_64BIT) #error "IOS build only supports the 64bit architecture" #else -#define SIZEOF_PTR 8 typedef uint64_t threadID; #endif diff --git a/Code/Legacy/CryCommon/platform.h b/Code/Legacy/CryCommon/platform.h index fb96056beb..9ff461543f 100644 --- a/Code/Legacy/CryCommon/platform.h +++ b/Code/Legacy/CryCommon/platform.h @@ -263,7 +263,6 @@ ILINE DestinationType alias_cast(SourceType pPtr) #define assert CRY_ASSERT #endif -#include "CompileTimeAssert.h" ////////////////////////////////////////////////////////////////////////// // Platform dependent functions that emulate Win32 API. // Mostly used only for debugging! diff --git a/Code/Legacy/CryCommon/stridedptr.h b/Code/Legacy/CryCommon/stridedptr.h index 737a1e40b7..8a74aa97b1 100644 --- a/Code/Legacy/CryCommon/stridedptr.h +++ b/Code/Legacy/CryCommon/stridedptr.h @@ -66,9 +66,9 @@ private: # if !defined(eLittleEndian) # error eLittleEndian is not defined, please include CryEndian.h. # endif - COMPILE_TIME_ASSERT(metautils::is_const::value || !metautils::is_const::value); + static_assert(metautils::is_const::value || !metautils::is_const::value); // note: we allow xint32 -> xint16 converting - COMPILE_TIME_ASSERT( + static_assert( (metautils::is_same::type, typename metautils::remove_const::type>::value || ((metautils::is_same::type, sint32>::value || metautils::is_same::type, uint32>::value || diff --git a/Code/Legacy/CrySystem/CrySystem_precompiled.h b/Code/Legacy/CrySystem/CrySystem_precompiled.h index f59adccb7b..daf1c335e4 100644 --- a/Code/Legacy/CrySystem/CrySystem_precompiled.h +++ b/Code/Legacy/CrySystem/CrySystem_precompiled.h @@ -68,7 +68,7 @@ #endif #ifdef WIN32 -#include +#include #include #undef GetCharWidth #undef GetUserName diff --git a/Code/Legacy/CrySystem/LevelSystem/LevelSystem.cpp b/Code/Legacy/CrySystem/LevelSystem/LevelSystem.cpp index ffaf0e7210..b1fd9de7c0 100644 --- a/Code/Legacy/CrySystem/LevelSystem/LevelSystem.cpp +++ b/Code/Legacy/CrySystem/LevelSystem/LevelSystem.cpp @@ -33,10 +33,6 @@ #include -#ifdef WIN32 -#include -#endif - namespace LegacyLevelSystem { static constexpr const char* ArchiveExtension = ".pak"; diff --git a/Code/Legacy/CrySystem/XML/XMLBinaryReader.cpp b/Code/Legacy/CrySystem/XML/XMLBinaryReader.cpp index bd31fb3ba4..be44c4b212 100644 --- a/Code/Legacy/CrySystem/XML/XMLBinaryReader.cpp +++ b/Code/Legacy/CrySystem/XML/XMLBinaryReader.cpp @@ -194,7 +194,7 @@ void XMLBinary::XMLBinaryReader::CheckHeader(const BinaryFileHeader& header, siz // Check the signature of the file to make sure that it is a binary XML file. { static const char signature[] = "CryXmlB"; - COMPILE_TIME_ASSERT(sizeof(signature) == sizeof(header.szSignature)); + static_assert(sizeof(signature) == sizeof(header.szSignature)); if (memcmp(header.szSignature, signature, sizeof(header.szSignature)) != 0) { result = eResult_NotBinXml; diff --git a/Code/Legacy/CrySystem/XML/XMLBinaryWriter.cpp b/Code/Legacy/CrySystem/XML/XMLBinaryWriter.cpp index 1500717ddc..9490e9aae0 100644 --- a/Code/Legacy/CrySystem/XML/XMLBinaryWriter.cpp +++ b/Code/Legacy/CrySystem/XML/XMLBinaryWriter.cpp @@ -109,7 +109,7 @@ bool XMLBinary::CXMLBinaryWriter::WriteNode(IDataWriter* pFile, XmlNodeRef node, BinaryFileHeader header; static const char signature[] = "CryXmlB"; - COMPILE_TIME_ASSERT(sizeof(signature) == sizeof(header.szSignature)); + static_assert(sizeof(signature) == sizeof(header.szSignature)); memcpy(header.szSignature, signature, sizeof(header.szSignature)); nTheoreticalPosition += sizeof(header); align(nTheoreticalPosition, nAlignment); From 51271fa15bec613f96c269d0cf1487e9ed524876 Mon Sep 17 00:00:00 2001 From: Kyle B Date: Fri, 6 Aug 2021 16:57:00 -0700 Subject: [PATCH 170/803] Created group for Lod component data Signed-off-by: Kyle B --- .../Atom/Feature/Mesh/MeshFeatureProcessor.h | 18 +--- .../Mesh/MeshFeatureProcessorInterface.h | 16 +--- .../Code/Mocks/MockMeshFeatureProcessor.h | 8 +- .../Code/Source/Mesh/MeshFeatureProcessor.cpp | 86 +++---------------- .../Code/Include/Atom/RPI.Public/Culling.h | 16 +++- .../RPI/Code/Source/RPI.Public/Culling.cpp | 6 +- .../CommonFeatures/Mesh/MeshComponentBus.h | 3 + .../Code/Source/Mesh/EditorMeshComponent.cpp | 40 +++++---- .../Source/Mesh/MeshComponentController.cpp | 73 ++++++++++++---- .../Source/Mesh/MeshComponentController.h | 29 +++++-- .../Code/Source/AtomActorInstance.cpp | 30 +++++-- .../Code/Source/AtomActorInstance.h | 2 + 12 files changed, 167 insertions(+), 160 deletions(-) diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h index 08f2dde474..daf4a493c2 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h @@ -63,12 +63,8 @@ namespace AZ void SetRayTracingData(); void SetSortKey(RHI::DrawItemSortKey sortKey); RHI::DrawItemSortKey GetSortKey() const; - void SetLodOverride(RPI::Cullable::LodOverride lodOverride); - RPI::Cullable::LodOverride GetLodOverride() const; - void SetMinimumScreenCoverage(float minimumScreenCoverage); - float GetMinimumScreenCoverage() const; - void SetQualityDecayRate(float qualityDecayRate); - float GetQualityDecayRate() const; + void SetMeshLodConfiguration(RPI::Cullable::LodConfiguration meshLodConfig); + RPI::Cullable::LodConfiguration GetMeshLodConfiguration() const; void UpdateDrawPackets(bool forceUpdate = false); void BuildCullable(); void UpdateCullBounds(const TransformServiceFeatureProcessor* transformService); @@ -159,14 +155,8 @@ namespace AZ void SetSortKey(const MeshHandle& meshHandle, RHI::DrawItemSortKey sortKey) override; RHI::DrawItemSortKey GetSortKey(const MeshHandle& meshHandle) override; - void SetLodOverride(const MeshHandle& meshHandle, RPI::Cullable::LodOverride lodOverride) override; - RPI::Cullable::LodOverride GetLodOverride(const MeshHandle& meshHandle) override; - - void SetMinimumScreenCoverage(const MeshHandle& meshHandle, float minimumScreenCoverage) override; - float GetMinimumScreenCoverage(const MeshHandle& meshHandle) override; - - void SetQualityDecayRate(const MeshHandle& meshHandle, float qualityDecayRate) override; - float GetQualityDecayRate(const MeshHandle& meshHandle) override; + void SetMeshLodConfiguration(const MeshHandle& meshHandle, RPI::Cullable::LodConfiguration meshLodConfig); + RPI::Cullable::LodConfiguration GetMeshLodConfiguration(const MeshHandle& meshHandle) const; void SetExcludeFromReflectionCubeMaps(const MeshHandle& meshHandle, bool excludeFromReflectionCubeMaps) override; void SetRayTracingEnabled(const MeshHandle& meshHandle, bool rayTracingEnabled) override; diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessorInterface.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessorInterface.h index dd64472161..8c7a200ff5 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessorInterface.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessorInterface.h @@ -94,18 +94,10 @@ namespace AZ virtual void SetSortKey(const MeshHandle& meshHandle, RHI::DrawItemSortKey sortKey) = 0; //! Gets the sort key for a given mesh handle. virtual RHI::DrawItemSortKey GetSortKey(const MeshHandle& meshHandle) = 0; - //! Sets an LOD override for a given mesh handle. This LOD will always be rendered instead being automatically determined. - virtual void SetLodOverride(const MeshHandle& meshHandle, RPI::Cullable::LodOverride lodOverride) = 0; - //! Gets the LOD override for a given mesh handle. - virtual RPI::Cullable::LodOverride GetLodOverride(const MeshHandle& meshHandle) = 0; - //! Sets the minimum screen percentage for a given mesh handle. This property is the minimum screen percentage the object can take up before culled. - virtual void SetMinimumScreenCoverage(const MeshHandle& meshHandle, float minimumScreenCoverage) = 0; - //! Gets the minimum screen percentage for a given mesh handle. - virtual float GetMinimumScreenCoverage(const MeshHandle& meshHandle) = 0; - //! Sets the quality decay rate. This property is the speed at which the quality of the mesh with degrade if you are linearly moving away. - virtual void SetQualityDecayRate(const MeshHandle& meshHandle, float qualityDecayRate) = 0; - //! Gets the quality decay rate. - virtual float GetQualityDecayRate(const MeshHandle& meshHandle) = 0; + //! Sets LOD mesh configurations to be used in the Mesh Feature Processor + virtual void SetMeshLodConfiguration(const MeshHandle& meshHandle, RPI::Cullable::LodConfiguration meshLodConfig) = 0; + //! Gets the LOD mesh configurations being used in the Mesh Feature Processor + virtual RPI::Cullable::LodConfiguration GetMeshLodConfiguration(const MeshHandle& meshHandle) const = 0; //! Sets the option to exclude this mesh from baked reflection probe cubemaps virtual void SetExcludeFromReflectionCubeMaps(const MeshHandle& meshHandle, bool excludeFromReflectionCubeMaps) = 0; //! Sets the option to exclude this mesh from raytracing diff --git a/Gems/Atom/Feature/Common/Code/Mocks/MockMeshFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Mocks/MockMeshFeatureProcessor.h index 0eea0df514..0c03e767e7 100644 --- a/Gems/Atom/Feature/Common/Code/Mocks/MockMeshFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Mocks/MockMeshFeatureProcessor.h @@ -33,12 +33,8 @@ namespace UnitTest MOCK_CONST_METHOD1(GetLocalAabb, AZ::Aabb(const MeshHandle&)); MOCK_METHOD2(SetSortKey, void (const MeshHandle&, AZ::RHI::DrawItemSortKey)); MOCK_CONST_METHOD1(GetSortKey, AZ::RHI::DrawItemSortKey(const MeshHandle&)); - MOCK_METHOD2(SetLodOverride, void(const MeshHandle&, AZ::RPI::Cullable::LodOverride)); - MOCK_CONST_METHOD1(GetLodOverride, AZ::RPI::Cullable::LodOverride(const MeshHandle&)); - MOCK_METHOD2(SetMinimumScreenCoverage, void(const MeshHandle&, float)); - MOCK_CONST_METHOD1(GetMinimumScreenCoverage, float(const MeshHandle&)); - MOCK_METHOD2(SetQualityDecayRate, void(const MeshHandle&, float)); - MOCK_CONST_METHOD1(GetQualityDecayRate, float(const MeshHandle&)); + MOCK_METHOD2(SetMeshLodConfiguration, void(const MeshHandle&, RPI::Cullable::LodConfiguration)); + MOCK_CONST_METHOD1(GetMeshLodConfiguration, RPI::Cullable::LodConfiguration(const MeshHandle&)); MOCK_METHOD2(AcquireMesh, MeshHandle (const AZ::Render::MeshHandleDescriptor&, const AZ::Render::MaterialAssignmentMap&)); MOCK_METHOD2(AcquireMesh, MeshHandle (const AZ::Render::MeshHandleDescriptor&, const AZ::Data::Instance&)); MOCK_METHOD2(SetRayTracingEnabled, void (const MeshHandle&, bool)); diff --git a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp index 166c5610b1..679e64e283 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp @@ -359,66 +359,24 @@ namespace AZ } } - void MeshFeatureProcessor::SetLodOverride(const MeshHandle& meshHandle, RPI::Cullable::LodOverride lodOverride) + void MeshFeatureProcessor::SetMeshLodConfiguration(const MeshHandle& meshHandle, RPI::Cullable::LodConfiguration meshLodConfig) { if (meshHandle.IsValid()) { - meshHandle->SetLodOverride(lodOverride); + meshHandle->SetMeshLodConfiguration(meshLodConfig); } } - RPI::Cullable::LodOverride MeshFeatureProcessor::GetLodOverride(const MeshHandle& meshHandle) + RPI::Cullable::LodConfiguration MeshFeatureProcessor::GetMeshLodConfiguration(const MeshHandle& meshHandle) const { if (meshHandle.IsValid()) { - return meshHandle->GetLodOverride(); + return meshHandle->GetMeshLodConfiguration(); } else { AZ_Assert(false, "Invalid mesh handle"); - return 0; - } - } - - void MeshFeatureProcessor::SetMinimumScreenCoverage(const MeshHandle& meshHandle, float minimumScreenCoverage) - { - if (meshHandle.IsValid()) - { - meshHandle->SetMinimumScreenCoverage(minimumScreenCoverage); - } - } - - float MeshFeatureProcessor::GetMinimumScreenCoverage(const MeshHandle& meshHandle) - { - if (meshHandle.IsValid()) - { - return meshHandle->GetMinimumScreenCoverage(); - } - else - { - AZ_Assert(false, "Invalid mesh handle"); - return 0; - } - } - - void MeshFeatureProcessor::SetQualityDecayRate(const MeshHandle& meshHandle, float qualityDecayRate) - { - if (meshHandle.IsValid()) - { - meshHandle->SetQualityDecayRate(qualityDecayRate); - } - } - - float MeshFeatureProcessor::GetQualityDecayRate(const MeshHandle& meshHandle) - { - if (meshHandle.IsValid()) - { - return meshHandle->GetQualityDecayRate(); - } - else - { - AZ_Assert(false, "Invalid mesh handle"); - return 0; + return {0,0,0.0f,0.0f}; } } @@ -1033,34 +991,14 @@ namespace AZ return m_sortKey; } - void MeshDataInstance::SetLodOverride(RPI::Cullable::LodOverride lodOverride) + void MeshDataInstance::SetMeshLodConfiguration(RPI::Cullable::LodConfiguration meshLodConfig) { - m_cullable.m_lodData.m_lodOverride = lodOverride; + m_cullable.m_lodData.m_lodConfiguration = meshLodConfig; } - RPI::Cullable::LodOverride MeshDataInstance::GetLodOverride() const + RPI::Cullable::LodConfiguration MeshDataInstance::GetMeshLodConfiguration() const { - return m_cullable.m_lodData.m_lodOverride; - } - - void MeshDataInstance::SetMinimumScreenCoverage(float minimumScreenCoverage) - { - m_cullable.m_lodData.m_minimumScreenCoverage = minimumScreenCoverage; - } - - float MeshDataInstance::GetMinimumScreenCoverage() const - { - return m_cullable.m_lodData.m_minimumScreenCoverage; - } - - void MeshDataInstance::SetQualityDecayRate(float qualityDecayRate) - { - m_cullable.m_lodData.m_qualityDecayRate = qualityDecayRate; - } - - float MeshDataInstance::GetQualityDecayRate() const - { - return m_cullable.m_lodData.m_qualityDecayRate; + return m_cullable.m_lodData.m_lodConfiguration; } void MeshDataInstance::UpdateDrawPackets(bool forceUpdate /*= false*/) @@ -1110,18 +1048,18 @@ namespace AZ else { //every other lod: use the previous lod's min - lod.m_screenCoverageMax = AZStd::GetMax(lodData.m_lods[lodIndex - 1].m_screenCoverageMin, lodData.m_minimumScreenCoverage); + lod.m_screenCoverageMax = AZStd::GetMax(lodData.m_lods[lodIndex - 1].m_screenCoverageMin, lodData.m_lodConfiguration.m_minimumScreenCoverage); } if (lodIndex < lodAssets.size() - 1) { //first and middle lods: compute a stepdown value for the min - lod.m_screenCoverageMin = AZStd::GetMax(lodData.m_qualityDecayRate * lod.m_screenCoverageMax, lodData.m_minimumScreenCoverage); + lod.m_screenCoverageMin = AZStd::GetMax(lodData.m_lodConfiguration.m_qualityDecayRate * lod.m_screenCoverageMax, lodData.m_lodConfiguration.m_minimumScreenCoverage); } else { //last lod: use MinimumScreenCoverage for the min - lod.m_screenCoverageMin = lodData.m_minimumScreenCoverage; + lod.m_screenCoverageMin = lodData.m_lodConfiguration.m_minimumScreenCoverage; } lod.m_drawPackets.clear(); diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Culling.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Culling.h index 4a39a21e0b..e89e180540 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Culling.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Culling.h @@ -70,8 +70,18 @@ namespace AZ }; CullData m_cullData; + using LodType = uint8_t; using LodOverride = uint8_t; static constexpr uint8_t NoLodOverride = AZStd::numeric_limits::max(); + static constexpr uint8_t DefaultLodType = AZStd::numeric_limits::max(); + + struct LodConfiguration + { + LodType m_lodType; + LodOverride m_lodOverride; + float m_minimumScreenCoverage; + float m_qualityDecayRate; + }; struct LodData { @@ -89,11 +99,11 @@ namespace AZ float m_lodSelectionRadius = 1.0f; // the minimum possibe area a sphere enclosing a mesh projected onto the screen should have before it is culled. - float m_minimumScreenCoverage = 1.0f / 1080.0f; //For default, mesh should cover at least a screen pixel at 1080p to be drawn + static constexpr float DefaultMinimumScreenCoverage = 1.0f / 1080.0f; //For default, mesh should cover at least a screen pixel at 1080p to be drawn // The screen area decay between 0 and 1, i.e. closer to 1 -> lose quality immediately, closer to 0 -> never lose quality - float m_qualityDecayRate = 0.5f; + static constexpr float DefaultQualityDecayRate = 0.5f; - LodOverride m_lodOverride = NoLodOverride; + LodConfiguration m_lodConfiguration = { DefaultLodType, NoLodOverride, DefaultMinimumScreenCoverage, DefaultQualityDecayRate }; }; LodData m_lodData; diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Culling.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Culling.cpp index e192e71fc4..f22d5c7224 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Culling.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Culling.cpp @@ -672,7 +672,7 @@ namespace AZ } }; - if (lodData.m_lodOverride == Cullable::NoLodOverride) + if (lodData.m_lodConfiguration.m_lodOverride == Cullable::NoLodOverride) { for (const Cullable::LodData::Lod& lod : lodData.m_lods) { @@ -683,9 +683,9 @@ namespace AZ } } } - else if(lodData.m_lodOverride < lodData.m_lods.size()) + else if(lodData.m_lodConfiguration.m_lodOverride < lodData.m_lods.size()) { - addLodToDrawPacket(lodData.m_lods.at(lodData.m_lodOverride)); + addLodToDrawPacket(lodData.m_lods.at(lodData.m_lodConfiguration.m_lodOverride)); } return numVisibleDrawPackets; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Mesh/MeshComponentBus.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Mesh/MeshComponentBus.h index baef507b7a..cc9c78d356 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Mesh/MeshComponentBus.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Mesh/MeshComponentBus.h @@ -36,6 +36,9 @@ namespace AZ virtual void SetSortKey(RHI::DrawItemSortKey sortKey) = 0; virtual RHI::DrawItemSortKey GetSortKey() const = 0; + virtual void SetLodType(RPI::Cullable::LodType lodType) = 0; + virtual RPI::Cullable::LodType GetLodType() const = 0; + virtual void SetLodOverride(RPI::Cullable::LodOverride lodOverride) = 0; virtual RPI::Cullable::LodOverride GetLodOverride() const = 0; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp index 3308767de9..0719d9f2bb 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp @@ -71,24 +71,28 @@ namespace AZ "MeshComponentConfig", "") ->ClassElement(AZ::Edit::ClassElements::EditorData, "") ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->DataElement(AZ::Edit::UIHandlers::Default, &MeshComponentConfig::m_modelAsset, "Mesh Asset", "Mesh asset reference") - ->DataElement(AZ::Edit::UIHandlers::Default, &MeshComponentConfig::m_sortKey, "Sort Key", "Transparent meshes are drawn by sort key then depth. Used this to force certain transparent meshes to draw before or after others.") - ->DataElement(AZ::Edit::UIHandlers::ComboBox, &MeshComponentConfig::m_lodOverride, "Lod Override", "Allows the rendered LOD to be overridden instead of being calculated automatically.") - ->Attribute(AZ::Edit::Attributes::EnumValues, &MeshComponentConfig::GetLodOverrideValues) - ->Attribute(AZ::Edit::Attributes::Visibility, &MeshComponentConfig::IsAssetSet) - ->DataElement(AZ::Edit::UIHandlers::Slider, &MeshComponentConfig::m_minimumScreenCoverage, "Minimum Screen Coverage", "Minimum proportion of screen area an entitiy takes up, after that the entitiy is culled.") - ->Attribute(AZ::Edit::Attributes::Min, 0.f) - ->Attribute(AZ::Edit::Attributes::Max, 1.f) - ->Attribute(AZ::Edit::Attributes::Suffix, " percent") - ->DataElement(AZ::Edit::UIHandlers::Slider, &MeshComponentConfig::m_qualityDecayRate, "Quality Decay Rate", - "Rate at which mesh quality decays (0 -> always stay highest quality, 1 -> quality falls off to lowest quality immediately).") - ->Attribute(AZ::Edit::Attributes::Min, 0.f) - ->Attribute(AZ::Edit::Attributes::Max, 1.f) - ->DataElement(AZ::Edit::UIHandlers::CheckBox, &MeshComponentConfig::m_excludeFromReflectionCubeMaps, "Exclude from reflection cubemaps", "Mesh will not be visible in baked reflection probe cubemaps") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) - ->DataElement(AZ::Edit::UIHandlers::CheckBox, &MeshComponentConfig::m_useForwardPassIblSpecular, "Use Forward Pass IBL Specular", - "Renders IBL specular reflections in the forward pass, using only the most influential probe (based on the position of the entity) and the global IBL cubemap. Can reduce rendering costs, but only recommended for static objects that are affected by at most one reflection probe.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) + ->DataElement(AZ::Edit::UIHandlers::Default, &MeshComponentConfig::m_modelAsset, "Mesh Asset", "Mesh asset reference") + ->DataElement(AZ::Edit::UIHandlers::Default, &MeshComponentConfig::m_sortKey, "Sort Key", "Transparent meshes are drawn by sort key then depth. Used this to force certain transparent meshes to draw before or after others.") + ->Attribute(AZ::Edit::Attributes::Visibility, &MeshComponentConfig::IsAssetSet) + ->DataElement(AZ::Edit::UIHandlers::CheckBox, &MeshComponentConfig::m_excludeFromReflectionCubeMaps, "Exclude from reflection cubemaps", "Mesh will not be visible in baked reflection probe cubemaps") + ->Attribute(AZ::Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) + ->DataElement(AZ::Edit::UIHandlers::CheckBox, &MeshComponentConfig::m_useForwardPassIblSpecular, "Use Forward Pass IBL Specular", + "Renders IBL specular reflections in the forward pass, using only the most influential probe (based on the position of the entity) and the global IBL cubemap. Can reduce rendering costs, but only recommended for static objects that are affected by at most one reflection probe.") + ->Attribute(AZ::Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) + ->ClassElement(AZ::Edit::ClassElements::Group, "Lod Configuration") + ->Attribute(AZ::Edit::Attributes::AutoExpand, false) + ->DataElement(AZ::Edit::UIHandlers::ComboBox, &MeshComponentConfig::m_lodType, "Lod Type", "Lod Method.") + ->Attribute(AZ::Edit::Attributes::EnumValues, &MeshComponentConfig::GetLodTypeValues) + ->DataElement(AZ::Edit::UIHandlers::ComboBox, &MeshComponentConfig::m_lodOverride, "Lod Override", "Allows the rendered LOD to be overridden instead of being calculated automatically.") + ->Attribute(AZ::Edit::Attributes::EnumValues, &MeshComponentConfig::GetLodOverrideValues) + ->DataElement(AZ::Edit::UIHandlers::Slider, &MeshComponentConfig::m_minimumScreenCoverage, "Minimum Screen Coverage", "Minimum proportion of screen area an entitiy takes up, after that the entitiy is culled.") + ->Attribute(AZ::Edit::Attributes::Min, 0.f) + ->Attribute(AZ::Edit::Attributes::Max, 1.f) + ->Attribute(AZ::Edit::Attributes::Suffix, " percent") + ->DataElement(AZ::Edit::UIHandlers::Slider, &MeshComponentConfig::m_qualityDecayRate, "Quality Decay Rate", + "Rate at which mesh quality decays (0 -> always stay highest quality, 1 -> quality falls off to lowest quality immediately).") + ->Attribute(AZ::Edit::Attributes::Min, 0.f) + ->Attribute(AZ::Edit::Attributes::Max, 1.f) ; } } diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp index 5fde185e4c..adcf570899 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp @@ -39,11 +39,12 @@ namespace AZ ->Version(1) ->Field("ModelAsset", &MeshComponentConfig::m_modelAsset) ->Field("SortKey", &MeshComponentConfig::m_sortKey) + ->Field("ExcludeFromReflectionCubeMaps", &MeshComponentConfig::m_excludeFromReflectionCubeMaps) + ->Field("UseForwardPassIBLSpecular", &MeshComponentConfig::m_useForwardPassIblSpecular) + ->Field("LodType", &MeshComponentConfig::m_lodType) ->Field("LodOverride", &MeshComponentConfig::m_lodOverride) ->Field("MinimumScreenCoverage", &MeshComponentConfig::m_minimumScreenCoverage) - ->Field("QualityDecayRate", &MeshComponentConfig::m_qualityDecayRate) - ->Field("ExcludeFromReflectionCubeMaps", &MeshComponentConfig::m_excludeFromReflectionCubeMaps) - ->Field("UseForwardPassIBLSpecular", &MeshComponentConfig::m_useForwardPassIblSpecular); + ->Field("QualityDecayRate", &MeshComponentConfig::m_qualityDecayRate); } } @@ -85,6 +86,13 @@ namespace AZ return values; } + AZStd::vector> MeshComponentConfig::GetLodTypeValues() + { + return { + {RPI::Cullable::DefaultLodType, "Default"} + }; + } + MeshComponentController::~MeshComponentController() { // Release memory, disconnect from buses in the right order and broadcast events so that other components are aware. @@ -109,6 +117,11 @@ namespace AZ ->Attribute(AZ::Script::Attributes::Category, "render") ->Attribute(AZ::Script::Attributes::Module, "render"); + behaviorContext->ConstantProperty("DefaultLodType", BehaviorConstant(RPI::Cullable::DefaultLodType)) + ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) + ->Attribute(AZ::Script::Attributes::Category, "render") + ->Attribute(AZ::Script::Attributes::Module, "render"); + behaviorContext->EBus("RenderMeshComponentRequestBus") ->Event("GetModelAssetId", &MeshComponentRequestBus::Events::GetModelAssetId) ->Event("SetModelAssetId", &MeshComponentRequestBus::Events::SetModelAssetId) @@ -116,6 +129,8 @@ namespace AZ ->Event("SetModelAssetPath", &MeshComponentRequestBus::Events::SetModelAssetPath) ->Event("SetSortKey", &MeshComponentRequestBus::Events::SetSortKey) ->Event("GetSortKey", &MeshComponentRequestBus::Events::GetSortKey) + ->Event("SetLodType", &MeshComponentRequestBus::Events::SetLodType) + ->Event("GetLodType", &MeshComponentRequestBus::Events::GetLodType) ->Event("SetLodOverride", &MeshComponentRequestBus::Events::SetLodOverride) ->Event("GetLodOverride", &MeshComponentRequestBus::Events::GetLodOverride) ->Event("SetMinimumScreenCoverage", &MeshComponentRequestBus::Events::SetMinimumScreenCoverage) @@ -125,6 +140,7 @@ namespace AZ ->VirtualProperty("ModelAssetId", "GetModelAssetId", "SetModelAssetId") ->VirtualProperty("ModelAssetPath", "GetModelAssetPath", "SetModelAssetPath") ->VirtualProperty("SortKey", "GetSortKey", "SetSortKey") + ->VirtualProperty("LodType", "GetLodType", "SetLodType") ->VirtualProperty("LodOverride", "GetLodOverride", "SetLodOverride") ->VirtualProperty("MinimumScreenCoverage", "GetMinimumScreenCoverage", "SetMinimumScreenCoverage") ->VirtualProperty("QualityDecayRate", "GetQualityDecayRate", "SetQualityDecayRate") @@ -332,9 +348,7 @@ namespace AZ m_meshFeatureProcessor->SetTransform(m_meshHandle, transform, m_cachedNonUniformScale); m_meshFeatureProcessor->SetSortKey(m_meshHandle, m_configuration.m_sortKey); - m_meshFeatureProcessor->SetLodOverride(m_meshHandle, m_configuration.m_lodOverride); - m_meshFeatureProcessor->SetMinimumScreenCoverage(m_meshHandle, m_configuration.m_minimumScreenCoverage); - m_meshFeatureProcessor->SetQualityDecayRate(m_meshHandle, m_configuration.m_qualityDecayRate); + m_meshFeatureProcessor->SetMeshLodConfiguration(m_meshHandle, GetMeshLodConfiguration()); m_meshFeatureProcessor->SetExcludeFromReflectionCubeMaps(m_meshHandle, m_configuration.m_excludeFromReflectionCubeMaps); m_meshFeatureProcessor->SetVisible(m_meshHandle, m_isVisible); @@ -425,37 +439,66 @@ namespace AZ return m_meshFeatureProcessor->GetSortKey(m_meshHandle); } + RPI::Cullable::LodConfiguration MeshComponentController::GetMeshLodConfiguration() const + { + return { + m_configuration.m_lodType, + m_configuration.m_lodOverride, + m_configuration.m_minimumScreenCoverage, + m_configuration.m_qualityDecayRate + }; + } + // ----------------------- + void MeshComponentController::SetLodType(RPI::Cullable::LodType lodType) + { + RPI::Cullable::LodConfiguration lodConfig = GetMeshLodConfiguration(); + lodConfig.m_lodType = lodType; + m_meshFeatureProcessor->SetMeshLodConfiguration(m_meshHandle, lodConfig); + } + + RPI::Cullable::LodType MeshComponentController::GetLodType() const + { + RPI::Cullable::LodConfiguration lodConfig = m_meshFeatureProcessor->GetMeshLodConfiguration(m_meshHandle); + return lodConfig.m_lodType; + } + void MeshComponentController::SetLodOverride(RPI::Cullable::LodOverride lodOverride) { - m_configuration.m_lodOverride = lodOverride; // Save for serialization - m_meshFeatureProcessor->SetLodOverride(m_meshHandle, lodOverride); + RPI::Cullable::LodConfiguration lodConfig = GetMeshLodConfiguration(); + lodConfig.m_lodOverride = lodOverride; + m_meshFeatureProcessor->SetMeshLodConfiguration(m_meshHandle, lodConfig); } RPI::Cullable::LodOverride MeshComponentController::GetLodOverride() const { - return m_meshFeatureProcessor->GetSortKey(m_meshHandle); + RPI::Cullable::LodConfiguration lodConfig = m_meshFeatureProcessor->GetMeshLodConfiguration(m_meshHandle); + return lodConfig.m_lodOverride; } void MeshComponentController::SetMinimumScreenCoverage(float minimumScreenCoverage) { - m_configuration.m_minimumScreenCoverage = minimumScreenCoverage; - m_meshFeatureProcessor->SetMinimumScreenCoverage(m_meshHandle, minimumScreenCoverage); + RPI::Cullable::LodConfiguration lodConfig = GetMeshLodConfiguration(); + lodConfig.m_minimumScreenCoverage = minimumScreenCoverage; + m_meshFeatureProcessor->SetMeshLodConfiguration(m_meshHandle, lodConfig); } float MeshComponentController::GetMinimumScreenCoverage() const { - return m_meshFeatureProcessor->GetMinimumScreenCoverage(m_meshHandle); + RPI::Cullable::LodConfiguration lodConfig = m_meshFeatureProcessor->GetMeshLodConfiguration(m_meshHandle); + return lodConfig.m_minimumScreenCoverage; } void MeshComponentController::SetQualityDecayRate(float qualityDecayRate) { - m_configuration.m_qualityDecayRate = qualityDecayRate; - m_meshFeatureProcessor->SetQualityDecayRate(m_meshHandle, qualityDecayRate); + RPI::Cullable::LodConfiguration lodConfig = GetMeshLodConfiguration(); + lodConfig.m_qualityDecayRate = qualityDecayRate; + m_meshFeatureProcessor->SetMeshLodConfiguration(m_meshHandle, lodConfig); } float MeshComponentController::GetQualityDecayRate() const { - return m_meshFeatureProcessor->GetQualityDecayRate(m_meshHandle); + RPI::Cullable::LodConfiguration lodConfig = m_meshFeatureProcessor->GetMeshLodConfiguration(m_meshHandle); + return lodConfig.m_qualityDecayRate; } void MeshComponentController::SetVisibility(bool visible) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h index 888d4bb154..1b479ed3eb 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h @@ -30,6 +30,9 @@ namespace AZ { namespace Render { + + + //! A configuration structure for the MeshComponentController class MeshComponentConfig final : public AZ::ComponentConfig @@ -42,14 +45,17 @@ namespace AZ // Editor helper functions bool IsAssetSet(); AZStd::vector> GetLodOverrideValues(); + AZStd::vector> GetLodTypeValues(); Data::Asset m_modelAsset = { AZ::Data::AssetLoadBehavior::QueueLoad }; RHI::DrawItemSortKey m_sortKey = 0; - RPI::Cullable::LodOverride m_lodOverride = RPI::Cullable::NoLodOverride; - float m_minimumScreenCoverage = 1.0f / 1080.0f; - float m_qualityDecayRate = 0.5f; bool m_excludeFromReflectionCubeMaps = false; bool m_useForwardPassIblSpecular = false; + + RPI::Cullable::LodType m_lodType = RPI::Cullable::DefaultLodType; + RPI::Cullable::LodOverride m_lodOverride = RPI::Cullable::NoLodOverride; + float m_minimumScreenCoverage = RPI::Cullable::LodData::DefaultMinimumScreenCoverage; + float m_qualityDecayRate = RPI::Cullable::LodData::DefaultQualityDecayRate; }; class MeshComponentController final @@ -96,14 +102,17 @@ namespace AZ void SetSortKey(RHI::DrawItemSortKey sortKey) override; RHI::DrawItemSortKey GetSortKey() const override; - void SetLodOverride(RPI::Cullable::LodOverride lodOverride) override; - RPI::Cullable::LodOverride GetLodOverride() const override; + void SetLodType(RPI::Cullable::LodType lodType) override; + RPI::Cullable::LodType GetLodType() const override; - void SetMinimumScreenCoverage(float minimumScreenCoverage) override; - float GetMinimumScreenCoverage() const override; + virtual void SetLodOverride(RPI::Cullable::LodOverride lodOverride); + virtual RPI::Cullable::LodOverride GetLodOverride() const; - void SetQualityDecayRate(float qualityDecayRate) override; - float GetQualityDecayRate() const override; + virtual void SetMinimumScreenCoverage(float minimumScreenCoverage); + virtual float GetMinimumScreenCoverage() const; + + virtual void SetQualityDecayRate(float qualityDecayRate); + virtual float GetQualityDecayRate() const; void SetVisibility(bool visible) override; bool GetVisibility() const override; @@ -137,6 +146,8 @@ namespace AZ void UnregisterModel(); void RefreshModelRegistration(); + RPI::Cullable::LodConfiguration MeshComponentController::GetMeshLodConfiguration() const; + void HandleNonUniformScaleChange(const AZ::Vector3& nonUniformScale); Render::MeshFeatureProcessorInterface* m_meshFeatureProcessor = nullptr; diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp index 63912aa8a6..e2debacb83 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp @@ -404,35 +404,53 @@ namespace AZ { return m_meshFeatureProcessor->GetSortKey(*m_meshHandle); } + + void AtomActorInstance::SetLodType(RPI::Cullable::LodType lodType) + { + RPI::Cullable::LodConfiguration config = m_meshFeatureProcessor->GetMeshLodConfiguration(*m_meshHandle); + config.m_lodType = lodType; + m_meshFeatureProcessor->SetMeshLodConfiguration(*m_meshHandle, config); + } + + RPI::Cullable::LodType AtomActorInstance::GetLodType() const + { + return m_meshFeatureProcessor->GetMeshLodConfiguration(*m_meshHandle).m_lodType; + } void AtomActorInstance::SetLodOverride(RPI::Cullable::LodOverride lodOverride) { - m_meshFeatureProcessor->SetLodOverride(*m_meshHandle, lodOverride); + RPI::Cullable::LodConfiguration config = m_meshFeatureProcessor->GetMeshLodConfiguration(*m_meshHandle); + config.m_lodOverride = lodOverride; + m_meshFeatureProcessor->SetMeshLodConfiguration(*m_meshHandle, config); } RPI::Cullable::LodOverride AtomActorInstance::GetLodOverride() const { - return m_meshFeatureProcessor->GetLodOverride(*m_meshHandle); + return m_meshFeatureProcessor->GetMeshLodConfiguration(*m_meshHandle).m_lodOverride; } void AtomActorInstance::SetMinimumScreenCoverage(float minimumScreenCoverage) { - m_meshFeatureProcessor->SetMinimumScreenCoverage(*m_meshHandle, minimumScreenCoverage); + RPI::Cullable::LodConfiguration config = m_meshFeatureProcessor->GetMeshLodConfiguration(*m_meshHandle); + config.m_minimumScreenCoverage = minimumScreenCoverage; + m_meshFeatureProcessor->SetMeshLodConfiguration(*m_meshHandle, config); } float AtomActorInstance::GetMinimumScreenCoverage() const { - return m_meshFeatureProcessor->GetMinimumScreenCoverage(*m_meshHandle); + return m_meshFeatureProcessor->GetMeshLodConfiguration(*m_meshHandle).m_minimumScreenCoverage; } void AtomActorInstance::SetQualityDecayRate(float qualityDecayRate) { - m_meshFeatureProcessor->SetQualityDecayRate(*m_meshHandle, qualityDecayRate); + RPI::Cullable::LodConfiguration config = m_meshFeatureProcessor->GetMeshLodConfiguration(*m_meshHandle); + config.m_qualityDecayRate = qualityDecayRate; + m_meshFeatureProcessor->SetMeshLodConfiguration(*m_meshHandle, config); } float AtomActorInstance::GetQualityDecayRate() const { - return m_meshFeatureProcessor->GetQualityDecayRate(*m_meshHandle); + return m_meshFeatureProcessor->GetMeshLodConfiguration(*m_meshHandle).m_qualityDecayRate; } void AtomActorInstance::SetVisibility(bool visible) diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.h b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.h index bd9afc668e..bf832e9def 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.h +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.h @@ -138,6 +138,8 @@ namespace AZ AZ::Data::Instance GetModel() const override; void SetSortKey(RHI::DrawItemSortKey sortKey) override; RHI::DrawItemSortKey GetSortKey() const override; + void SetLodType(RPI::Cullable::LodType lodType) override; + RPI::Cullable::LodType GetLodType() const override; void SetLodOverride(RPI::Cullable::LodOverride lodOverride) override; RPI::Cullable::LodOverride GetLodOverride() const override; void SetMinimumScreenCoverage(float minimumScreenCoverage) override; From 2f5927f1ac43c3f082cd3b3e69084d9d2c14554e Mon Sep 17 00:00:00 2001 From: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> Date: Fri, 6 Aug 2021 17:45:54 -0700 Subject: [PATCH 171/803] [redcode/crythread-2nd-pass] remove dependency on cry threads in the remote console runtime Signed-off-by: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> --- .../RemoteConsole/Core/RemoteConsoleCore.cpp | 88 +++++++++++-------- .../RemoteConsole/Core/RemoteConsoleCore.h | 42 ++++++--- 2 files changed, 84 insertions(+), 46 deletions(-) diff --git a/Code/Tools/RemoteConsole/Core/RemoteConsoleCore.cpp b/Code/Tools/RemoteConsole/Core/RemoteConsoleCore.cpp index d4ef5b3ba8..94ae4cbfbf 100644 --- a/Code/Tools/RemoteConsole/Core/RemoteConsoleCore.cpp +++ b/Code/Tools/RemoteConsole/Core/RemoteConsoleCore.cpp @@ -93,40 +93,63 @@ bool RCON_IsRemoteAllowedToConnect(const AZ::AzSock::AzSocketAddress& connectee) ///////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////// +void SRemoteThreadedObject::Start(const char* name) +{ + AZStd::thread_desc desc; + desc.m_name = name; + auto function = AZStd::bind(&SRemoteThreadedObject::ThreadFunction, this); + m_thread = AZStd::thread(function, &desc); +} + +void SRemoteThreadedObject::WaitForThread() +{ + if (m_thread.joinable()) + { + m_thread.join(); + } +} + +void SRemoteThreadedObject::ThreadFunction() +{ + Run(); + Terminate(); +} + +///////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////// void SRemoteServer::StartServer() { StopServer(); m_bAcceptClients = true; - Start(0, kServerThreadName); + Start(kServerThreadName); } ///////////////////////////////////////////////////////////////////////////////////////////// void SRemoteServer::StopServer() { - Stop(); m_bAcceptClients = false; AZ::AzSock::CloseSocket(m_socket); m_socket = SOCKET_ERROR; - m_lock.Lock(); - for (TClients::iterator it = m_clients.begin(); it != m_clients.end(); ++it) { - it->pClient->StopClient(); + AZStd::lock_guard lock(m_mutex); + for (TClients::iterator it = m_clients.begin(); it != m_clients.end(); ++it) + { + it->pClient->StopClient(); + } } - m_lock.Unlock(); - m_stopEvent.Wait(); - m_stopEvent.Set(); -} + AZStd::unique_lock lock(m_mutex); + m_stopCondition.wait(lock, [this] { return m_clients.empty(); });} ///////////////////////////////////////////////////////////////////////////////////////////// void SRemoteServer::ClientDone(SRemoteClient* pClient) { - m_lock.Lock(); + AZStd::lock_guard lock(m_mutex); for (TClients::iterator it = m_clients.begin(); it != m_clients.end(); ++it) { if (it->pClient == pClient) { - it->pClient->Stop(); delete it->pClient; delete it->pEvents; m_clients.erase(it); @@ -136,9 +159,8 @@ void SRemoteServer::ClientDone(SRemoteClient* pClient) if (m_clients.empty()) { - m_stopEvent.Set(); + m_stopCondition.notify_all(); } - m_lock.Unlock(); } ///////////////////////////////////////////////////////////////////////////////////////////// @@ -149,7 +171,6 @@ void SRemoteServer::Terminate() ///////////////////////////////////////////////////////////////////////////////////////////// void SRemoteServer::Run() { - SetName(kServerThreadName); AZ_TRAIT_REMOTECONSOLE_SET_THREAD_AFFINITY AZSOCKET sClient; @@ -232,12 +253,10 @@ void SRemoteServer::Run() continue; } - m_lock.Lock(); - m_stopEvent.Reset(); + AZStd::lock_guard lock(m_mutex); SRemoteClient* pClient = new SRemoteClient(this); m_clients.push_back(SRemoteClientInfo(pClient)); pClient->StartClient(sClient); - m_lock.Unlock(); } AZ::AzSock::CloseSocket(m_socket); CryLog("Remote console terminating.\n"); @@ -247,43 +266,42 @@ void SRemoteServer::Run() ///////////////////////////////////////////////////////////////////////////////////////////// void SRemoteServer::AddEvent(IRemoteEvent* pEvent) { - m_lock.Lock(); + AZStd::lock_guard lock(m_mutex); for (TClients::iterator it = m_clients.begin(); it != m_clients.end(); ++it) { it->pEvents->push_back(pEvent->Clone()); } - m_lock.Unlock(); delete pEvent; } ///////////////////////////////////////////////////////////////////////////////////////////// void SRemoteServer::GetEvents(TEventBuffer& buffer) { - m_lock.Lock(); + AZStd::lock_guard lock(m_mutex); buffer = m_eventBuffer; m_eventBuffer.clear(); - m_lock.Unlock(); } ///////////////////////////////////////////////////////////////////////////////////////////// bool SRemoteServer::WriteBuffer(SRemoteClient* pClient, char* buffer, int& size) { - m_lock.Lock(); IRemoteEvent* pEvent = nullptr; - for (TClients::iterator it = m_clients.begin(); it != m_clients.end(); ++it) { - if (it->pClient == pClient) + AZStd::lock_guard lock(m_mutex); + for (TClients::iterator it = m_clients.begin(); it != m_clients.end(); ++it) { - TEventBuffer* pEvents = it->pEvents; - if (!pEvents->empty()) + if (it->pClient == pClient) { - pEvent = pEvents->front(); - pEvents->pop_front(); + TEventBuffer* pEvents = it->pEvents; + if (!pEvents->empty()) + { + pEvent = pEvents->front(); + pEvents->pop_front(); + } + break; } - break; } } - m_lock.Unlock(); const bool res = (pEvent != nullptr); if (pEvent) { @@ -297,7 +315,7 @@ bool SRemoteServer::WriteBuffer(SRemoteClient* pClient, char* buffer, int& size bool SRemoteServer::ReadBuffer(const char* buffer, int data) { bool result = true; - + // Sometimes multiple events can come in a single buffer, so make sure we look // at the entire thing. int bytesRemaining = data; @@ -306,15 +324,14 @@ bool SRemoteServer::ReadBuffer(const char* buffer, int data) { // Create the event from the current sub string in the buffer. IRemoteEvent* event = SRemoteEventFactory::GetInst()->CreateEventFromBuffer(curBuffer, bytesRemaining); - + result &= (event != nullptr); if (event) { if (event->GetType() != eCET_Noop) { - m_lock.Lock(); + AZStd::lock_guard lock(m_mutex); m_eventBuffer.push_back(event); - m_lock.Unlock(); } else { @@ -337,7 +354,7 @@ bool SRemoteServer::ReadBuffer(const char* buffer, int data) void SRemoteClient::StartClient(AZSOCKET socket) { m_socket = socket; - Start(0, kClientThreadName); + Start(kClientThreadName); } ///////////////////////////////////////////////////////////////////////////////////////////// @@ -356,7 +373,6 @@ void SRemoteClient::Terminate() ///////////////////////////////////////////////////////////////////////////////////////////// void SRemoteClient::Run() { - SetName(kClientThreadName); AZ_TRAIT_REMOTECONSOLE_SET_THREAD_AFFINITY char szBuff[kDefaultBufferSize]; diff --git a/Code/Tools/RemoteConsole/Core/RemoteConsoleCore.h b/Code/Tools/RemoteConsole/Core/RemoteConsoleCore.h index 45c3bf62d9..7e22be5735 100644 --- a/Code/Tools/RemoteConsole/Core/RemoteConsoleCore.h +++ b/Code/Tools/RemoteConsole/Core/RemoteConsoleCore.h @@ -11,9 +11,11 @@ #include #include #include +#include +#include +#include #include -#include extern const int defaultRemoteConsolePort; @@ -146,6 +148,30 @@ private: typedef AZStd::list TEventBuffer; + +///////////////////////////////////////////////////////////////////////////////////////////// +// SRemoteThreadedObject +// +// Simple runnable-like threaded object +// +///////////////////////////////////////////////////////////////////////////////////////////// +struct SRemoteThreadedObject +{ + virtual ~SRemoteThreadedObject() = default; + + void Start(const char* name); + + void WaitForThread(); + + virtual void Run() = 0; + virtual void Terminate() = 0; + +private: + void ThreadFunction(); + + AZStd::thread m_thread; +}; + ///////////////////////////////////////////////////////////////////////////////////////////// // SRemoteServer // @@ -154,10 +180,10 @@ typedef AZStd::list TEventBuffer; ///////////////////////////////////////////////////////////////////////////////////////////// struct SRemoteClient; struct SRemoteServer - : public CrySimpleThread<> + : public SRemoteThreadedObject { SRemoteServer() - : m_socket(AZ_SOCKET_INVALID) { m_stopEvent.Set(); } + : m_socket(AZ_SOCKET_INVALID) {} void StartServer(); void StopServer(); @@ -165,10 +191,8 @@ struct SRemoteServer void AddEvent(IRemoteEvent* pEvent); void GetEvents(TEventBuffer& buffer); - // CrySimpleThread void Terminate() override; void Run() override; - // ~CrySimpleThread private: bool WriteBuffer(SRemoteClient* pClient, char* buffer, int& size); @@ -189,9 +213,9 @@ private: typedef AZStd::vector TClients; TClients m_clients; AZSOCKET m_socket; - CryMutex m_lock; + AZStd::recursive_mutex m_mutex; TEventBuffer m_eventBuffer; - CryEvent m_stopEvent; + AZStd::condition_variable_any m_stopCondition; volatile bool m_bAcceptClients; friend struct SRemoteClient; }; @@ -204,7 +228,7 @@ private: // ///////////////////////////////////////////////////////////////////////////////////////////// struct SRemoteClient - : public CrySimpleThread<> + : public SRemoteThreadedObject { SRemoteClient(SRemoteServer* pServer) : m_pServer(pServer) @@ -213,10 +237,8 @@ struct SRemoteClient void StartClient(AZSOCKET socket); void StopClient(); - // CrySimpleThread void Terminate() override; void Run() override; - // ~CrySimpleThread private: bool RecvPackage(char* buffer, int& size); From 3e7d7d150e72015fb57b3c4f2ef15bf5b95a45aa Mon Sep 17 00:00:00 2001 From: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> Date: Fri, 6 Aug 2021 18:22:28 -0700 Subject: [PATCH 172/803] [redcode/crythread-2nd-pass] removed CryThread_dummy.h Signed-off-by: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> --- Code/Legacy/CryCommon/CryThread.h | 1 - Code/Legacy/CryCommon/CryThread_dummy.h | 152 -------------------- Code/Legacy/CryCommon/crycommon_files.cmake | 1 - 3 files changed, 154 deletions(-) delete mode 100644 Code/Legacy/CryCommon/CryThread_dummy.h diff --git a/Code/Legacy/CryCommon/CryThread.h b/Code/Legacy/CryCommon/CryThread.h index 5929bed352..b7b6a3adfd 100644 --- a/Code/Legacy/CryCommon/CryThread.h +++ b/Code/Legacy/CryCommon/CryThread.h @@ -175,7 +175,6 @@ class CrySimpleThread; #undef AZ_RESTRICTED_SECTION_IMPLEMENTED #else // Put other platform specific includes here! -#include #endif #if !defined _CRYTHREAD_CONDLOCK_GLITCH diff --git a/Code/Legacy/CryCommon/CryThread_dummy.h b/Code/Legacy/CryCommon/CryThread_dummy.h deleted file mode 100644 index d97b6c5b55..0000000000 --- a/Code/Legacy/CryCommon/CryThread_dummy.h +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - -#ifndef CRYINCLUDE_CRYCOMMON_CRYTHREAD_DUMMY_H -#define CRYINCLUDE_CRYCOMMON_CRYTHREAD_DUMMY_H -#pragma once - -#include - -////////////////////////////////////////////////////////////////////////// -CryEvent::CryEvent() {} -CryEvent::~CryEvent() {} -void CryEvent::Reset() {} -void CryEvent::Set() {} -void CryEvent::Wait() const {} -bool CryEvent::Wait(const uint32 timeoutMillis) const {} -typedef CryEvent CryEventTimed; - -////////////////////////////////////////////////////////////////////////// -class _DummyLock -{ -public: - _DummyLock(); - - void Lock(); - bool TryLock(); - void Unlock(); - -#if defined(AZ_DEBUG_BUILD) - bool IsLocked(); -#endif -}; - -template<> -class CryLock - : public _DummyLock -{ - CryLock(const CryLock&); - void operator = (const CryLock&); - -public: - CryLock(); -}; - -template<> -class CryLock - : public _DummyLock -{ - CryLock(const CryLock&); - void operator = (const CryLock&); - -public: - CryLock(); -}; - -template<> -class CryCondLock - : public CryLock -{ -}; - -template<> -class CryCondLock - : public CryLock -{ -}; - -template<> -class CryCond< CryLock > -{ - typedef CryLock LockT; - CryCond(const CryCond&); - void operator = (const CryCond&); - -public: - CryCond(); - - void Notify(); - void NotifySingle(); - void Wait(LockT&); - bool TimedWait(LockT &, uint32); -}; - -template<> -class CryCond< CryLock > -{ - typedef CryLock LockT; - CryCond(const CryCond&); - void operator = (const CryCond&); - -public: - CryCond(); - - void Notify(); - void NotifySingle(); - void Wait(LockT&); - bool TimedWait(LockT &, uint32); -}; - -class _DummyRWLock -{ -public: - _DummyRWLock() { } - - void RLock(); - bool TryRLock(); - void WLock(); - bool TryWLock(); - void Lock() { WLock(); } - bool TryLock() { return TryWLock(); } - void Unlock(); -}; - -template -class CrySimpleThread - : public CryRunnable -{ -public: - typedef void (* ThreadFunction)(void*); - - CrySimpleThread(); - virtual ~CrySimpleThread(); -#if !defined(NO_THREADINFO) - CryThreadInfo& GetInfo(); -#endif - const char* GetName(); - void SetName(const char*); - - virtual void Run(); - virtual void Cancel(); - virtual void Start(Runnable&, unsigned = 0, const char* = NULL); - virtual void Start(unsigned = 0, const char* = NULL); - void StartFunction(ThreadFunction, void* = NULL, unsigned = 0); - - void Exit(); - void Join(); - unsigned SetCpuMask(unsigned); - unsigned GetCpuMask(); - - void Stop(); - bool IsStarted() const; - bool IsRunning() const; -}; - -#endif // CRYINCLUDE_CRYCOMMON_CRYTHREAD_DUMMY_H - diff --git a/Code/Legacy/CryCommon/crycommon_files.cmake b/Code/Legacy/CryCommon/crycommon_files.cmake index 0392f11c89..b4dac2ec08 100644 --- a/Code/Legacy/CryCommon/crycommon_files.cmake +++ b/Code/Legacy/CryCommon/crycommon_files.cmake @@ -160,7 +160,6 @@ set(FILES CryAssert_Mac.h CryLibrary.cpp CryLibrary.h - CryThread_dummy.h CryThread_pthreads.h CryThread_windows.h CryThreadImpl_pthreads.h From 64cff38f8294338371555ef737008be3879f2a28 Mon Sep 17 00:00:00 2001 From: antonmic <56370189+antonmic@users.noreply.github.com> Date: Sun, 8 Aug 2021 16:46:42 -0700 Subject: [PATCH 173/803] Addressing PR feedback and fixed a small issue with the draw item count display Signed-off-by: antonmic <56370189+antonmic@users.noreply.github.com> --- .../Code/Include/Atom/RHI/ShaderResourceGroupDebug.h | 12 +++++++++++- .../RHI/Code/Source/RHI.Reflect/ConstantsLayout.cpp | 6 +++--- Gems/Atom/RHI/Code/Source/RHI/ConstantsData.cpp | 12 ++++++------ .../RHI/Code/Source/RHI/ShaderResourceGroupDebug.cpp | 6 +++--- .../RPI/Code/Source/RPI.Public/Pass/RasterPass.cpp | 4 +++- 5 files changed, 26 insertions(+), 14 deletions(-) diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/ShaderResourceGroupDebug.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/ShaderResourceGroupDebug.h index b81f9e0c0b..d9ea77d823 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/ShaderResourceGroupDebug.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/ShaderResourceGroupDebug.h @@ -14,8 +14,18 @@ namespace AZ struct DrawItem; class ShaderResourceGroup; + /// Given a ShaderResourceGroup and a reference ConstantsData input, this function will fetch the ConstantsData on the SRG and compare it + /// to the reference ConstantsData. It will print the names of any constants that are different between the two. + /// The parameter updateReferenceData can be used to set the reference data to the SRG's constant data after the comparison. This is + /// useful for keeping track of differences in between calls to the function, such as between frames. void PrintConstantDataDiff(const ShaderResourceGroup& shaderResourceGroup, ConstantsData& referenceData, bool updateReferenceData = false); - void PrintConstantDataDiff(const DrawItem& drawItem, ConstantsData& referenceData, u32 srgBindingSlot, bool updateReferenceData = false); + + /// Given a DrawItem, an SRG binding slot on that draw item and a reference ConstantsData input, this function will fetch the ConstantsData + /// from the draw item's SRG at the binding slot and compare it to the reference ConstantsData. It will print the names of any constants + /// that are different between the two. + /// The parameter updateReferenceData can be used to set the reference data to the draw item's constant data after the comparison. This is + /// useful for keeping track of differences in between calls to the function, such as between frames. + void PrintConstantDataDiff(const DrawItem& drawItem, ConstantsData& referenceData, uint32_t srgBindingSlot, bool updateReferenceData = false); } } diff --git a/Gems/Atom/RHI/Code/Source/RHI.Reflect/ConstantsLayout.cpp b/Gems/Atom/RHI/Code/Source/RHI.Reflect/ConstantsLayout.cpp index f14d1d4c4e..8be053e4ef 100644 --- a/Gems/Atom/RHI/Code/Source/RHI.Reflect/ConstantsLayout.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI.Reflect/ConstantsLayout.cpp @@ -151,11 +151,11 @@ namespace AZ void ConstantsLayout::DebugPrintNames(AZStd::array_view constantList) const { AZStd::string output; - for (const ShaderInputConstantIndex& constandIdx : constantList) + for (const ShaderInputConstantIndex& constantIdx : constantList) { - if (constandIdx.GetIndex() < m_inputs.size()) + if (constantIdx.GetIndex() < m_inputs.size()) { - output += m_inputs[constandIdx.GetIndex()].m_name.GetCStr(); + output += m_inputs[constantIdx.GetIndex()].m_name.GetCStr(); output += " - "; } } diff --git a/Gems/Atom/RHI/Code/Source/RHI/ConstantsData.cpp b/Gems/Atom/RHI/Code/Source/RHI/ConstantsData.cpp index d4caa3dd66..1524883e54 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/ConstantsData.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/ConstantsData.cpp @@ -408,26 +408,26 @@ namespace AZ bool ConstantsData::ConstantIsEqual(const ConstantsData& other, ShaderInputConstantIndex inputIndex) const { - AZStd::array_view myConstans = GetConstantRaw(inputIndex); - AZStd::array_view otherConstans = other.GetConstantRaw(inputIndex); + AZStd::array_view myConstant = GetConstantRaw(inputIndex); + AZStd::array_view otherConstant = other.GetConstantRaw(inputIndex); // If they point to the same data, they are equal - if (myConstans == otherConstans) + if (myConstant == otherConstant) { return true; } // If they point to data of different size, they are not equal - if (myConstans.size() != otherConstans.size()) + if (myConstant.size() != otherConstant.size()) { return false; } // If they point to differing data of same size, compare the data // Note: due to small size of data this loop will be faster than a mem compare - for(uint32_t i = 0; i < myConstans.size(); ++i) + for(uint32_t i = 0; i < myConstant.size(); ++i) { - if (myConstans[i] != otherConstans[i]) + if (myConstant[i] != otherConstant[i]) { return false; } diff --git a/Gems/Atom/RHI/Code/Source/RHI/ShaderResourceGroupDebug.cpp b/Gems/Atom/RHI/Code/Source/RHI/ShaderResourceGroupDebug.cpp index 4bd8d0aab8..54399eba88 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/ShaderResourceGroupDebug.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/ShaderResourceGroupDebug.cpp @@ -36,10 +36,10 @@ namespace AZ } } - void PrintConstantDataDiff(const DrawItem& drawItem, ConstantsData& referenceData, u32 srgBindingSlot, bool updateReferenceData) + void PrintConstantDataDiff(const DrawItem& drawItem, ConstantsData& referenceData, uint32_t srgBindingSlot, bool updateReferenceData) { - s32 srgIndex = -1; - for (u32 i = 0; i < drawItem.m_shaderResourceGroupCount; ++i) + int srgIndex = -1; + for (uint32_t i = 0; i < drawItem.m_shaderResourceGroupCount; ++i) { if (drawItem.m_shaderResourceGroups[i]->GetBindingSlot() == srgBindingSlot) { diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RasterPass.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RasterPass.cpp index 13f2215c8b..2e61542c36 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RasterPass.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RasterPass.cpp @@ -166,11 +166,14 @@ namespace AZ // clean up data m_drawListView = {}; m_combinedDrawList.clear(); + m_drawItemCount = 0; // draw list from view was sorted and if it's the only draw list then we can use it directly if (viewDrawList.size() > 0 && drawLists.size() == 0) { m_drawListView = viewDrawList; + m_drawItemCount += viewDrawList.size(); + PassSystemInterface::Get()->IncrementFrameDrawItemCount(m_drawItemCount); return; } @@ -178,7 +181,6 @@ namespace AZ drawLists.push_back(viewDrawList); // combine draw items from mutiple draw lists to one draw list and sort it. - m_drawItemCount = 0; for (auto drawList : drawLists) { m_drawItemCount += drawList.size(); From 5f1e973b3f6953233869544de32bdbc856d9bf63 Mon Sep 17 00:00:00 2001 From: antonmic <56370189+antonmic@users.noreply.github.com> Date: Sun, 8 Aug 2021 23:34:09 -0700 Subject: [PATCH 174/803] Removing condition from View SRG compilation Signed-off-by: antonmic <56370189+antonmic@users.noreply.github.com> --- .../RPI/Code/Include/Atom/RPI.Public/View.h | 6 -- Gems/Atom/RPI/Code/Source/RPI.Public/View.cpp | 94 ++++++++----------- 2 files changed, 39 insertions(+), 61 deletions(-) diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/View.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/View.h index c654952cf4..cdaf59ff75 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/View.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/View.h @@ -110,9 +110,6 @@ namespace AZ //! Value returned is 1.0f when an area equal to the viewport height squared is covered. Useful for accurate LOD decisions. float CalculateSphereAreaInClipSpace(const AZ::Vector3& sphereWorldPosition, float sphereRadius) const; - //! Invalidate the view srg to rebuild the srg. - void InvalidateSrg(); - const AZ::Name& GetName() const { return m_name; } const UsageFlags GetUsageFlags() { return m_usageFlags; } @@ -192,9 +189,6 @@ namespace AZ // Clip space offset for camera jitter with taa Vector2 m_clipSpaceOffset = Vector2(0.0f, 0.0f); - // Flags whether view matrices are dirty which requires rebuild srg - bool m_needBuildSrg = true; - MatrixChangedEvent m_onWorldToClipMatrixChange; MatrixChangedEvent m_onWorldToViewMatrixChange; diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/View.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/View.cpp index 4984186b4e..1937afc240 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/View.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/View.cpp @@ -126,8 +126,6 @@ namespace AZ m_onWorldToViewMatrixChange.Signal(m_worldToViewMatrix); m_onWorldToClipMatrixChange.Signal(m_worldToClipMatrix); - - InvalidateSrg(); } AZ::Transform View::GetCameraTransform() const @@ -170,8 +168,6 @@ namespace AZ m_onWorldToViewMatrixChange.Signal(m_worldToViewMatrix); } m_onWorldToClipMatrixChange.Signal(m_worldToClipMatrix); - - InvalidateSrg(); } void View::SetViewToClipMatrix(const AZ::Matrix4x4& viewToClip) @@ -202,14 +198,11 @@ namespace AZ m_unprojectionConstants.SetW(float(tanHalfFovY)); m_onWorldToClipMatrixChange.Signal(m_worldToClipMatrix); - - InvalidateSrg(); } void View::SetClipSpaceOffset(float xOffset, float yOffset) { m_clipSpaceOffset.Set(xOffset, yOffset); - InvalidateSrg(); } const AZ::Matrix4x4& View::GetWorldToViewMatrix() const @@ -362,58 +355,49 @@ namespace AZ return -0.25f * cotHalfFovYSq * AZ::Constants::Pi * radiusSq * sqrt(fabsf((distanceSq - radiusSq)/radiusSqSubDepthSq))/radiusSqSubDepthSq; } - void View::InvalidateSrg() - { - m_needBuildSrg = true; - } - void View::UpdateSrg() { - if (m_needBuildSrg) + if (m_clipSpaceOffset.IsZero()) { - if (m_clipSpaceOffset.IsZero()) - { - Matrix4x4 worldToClipPrevMatrix = m_viewToClipPrevMatrix * m_worldToViewPrevMatrix; - m_shaderResourceGroup->SetConstant(m_worldToClipPrevMatrixConstantIndex, worldToClipPrevMatrix); - m_shaderResourceGroup->SetConstant(m_viewProjectionMatrixConstantIndex, m_worldToClipMatrix); - m_shaderResourceGroup->SetConstant(m_projectionMatrixConstantIndex, m_viewToClipMatrix); - m_shaderResourceGroup->SetConstant(m_clipToWorldMatrixConstantIndex, m_clipToWorldMatrix); - m_shaderResourceGroup->SetConstant(m_projectionMatrixInverseConstantIndex, m_viewToClipMatrix.GetInverseFull()); - } - else - { - // Offset the current and previous frame clip matricies - Matrix4x4 offsetViewToClipMatrix = m_viewToClipMatrix; - offsetViewToClipMatrix.SetElement(0, 2, m_clipSpaceOffset.GetX()); - offsetViewToClipMatrix.SetElement(1, 2, m_clipSpaceOffset.GetY()); - - Matrix4x4 offsetViewToClipPrevMatrix = m_viewToClipPrevMatrix; - offsetViewToClipPrevMatrix.SetElement(0, 2, m_clipSpaceOffset.GetX()); - offsetViewToClipPrevMatrix.SetElement(1, 2, m_clipSpaceOffset.GetY()); - - // Build other matricies dependent on the view to clip matricies - Matrix4x4 offsetWorldToClipMatrix = offsetViewToClipMatrix * m_worldToViewMatrix; - Matrix4x4 offsetWorldToClipPrevMatrix = offsetViewToClipPrevMatrix * m_worldToViewPrevMatrix; - - Matrix4x4 offsetClipToViewMatrix = offsetViewToClipMatrix.GetInverseFull(); - Matrix4x4 offsetClipToWorldMatrix = m_viewToWorldMatrix * offsetClipToViewMatrix; - - m_shaderResourceGroup->SetConstant(m_worldToClipPrevMatrixConstantIndex, offsetWorldToClipPrevMatrix); - m_shaderResourceGroup->SetConstant(m_viewProjectionMatrixConstantIndex, offsetWorldToClipMatrix); - m_shaderResourceGroup->SetConstant(m_projectionMatrixConstantIndex, offsetViewToClipMatrix); - m_shaderResourceGroup->SetConstant(m_clipToWorldMatrixConstantIndex, offsetClipToWorldMatrix); - m_shaderResourceGroup->SetConstant(m_projectionMatrixInverseConstantIndex, offsetViewToClipMatrix.GetInverseFull()); - } - - m_shaderResourceGroup->SetConstant(m_worldPositionConstantIndex, m_position); - m_shaderResourceGroup->SetConstant(m_viewMatrixConstantIndex, m_worldToViewMatrix); - m_shaderResourceGroup->SetConstant(m_viewMatrixInverseConstantIndex, m_worldToViewMatrix.GetInverseFull()); - m_shaderResourceGroup->SetConstant(m_zConstantsConstantIndex, m_nearZ_farZ_farZTimesNearZ_farZMinusNearZ); - m_shaderResourceGroup->SetConstant(m_unprojectionConstantsIndex, m_unprojectionConstants); - - m_shaderResourceGroup->Compile(); - m_needBuildSrg = false; + Matrix4x4 worldToClipPrevMatrix = m_viewToClipPrevMatrix * m_worldToViewPrevMatrix; + m_shaderResourceGroup->SetConstant(m_worldToClipPrevMatrixConstantIndex, worldToClipPrevMatrix); + m_shaderResourceGroup->SetConstant(m_viewProjectionMatrixConstantIndex, m_worldToClipMatrix); + m_shaderResourceGroup->SetConstant(m_projectionMatrixConstantIndex, m_viewToClipMatrix); + m_shaderResourceGroup->SetConstant(m_clipToWorldMatrixConstantIndex, m_clipToWorldMatrix); + m_shaderResourceGroup->SetConstant(m_projectionMatrixInverseConstantIndex, m_viewToClipMatrix.GetInverseFull()); } + else + { + // Offset the current and previous frame clip matricies + Matrix4x4 offsetViewToClipMatrix = m_viewToClipMatrix; + offsetViewToClipMatrix.SetElement(0, 2, m_clipSpaceOffset.GetX()); + offsetViewToClipMatrix.SetElement(1, 2, m_clipSpaceOffset.GetY()); + + Matrix4x4 offsetViewToClipPrevMatrix = m_viewToClipPrevMatrix; + offsetViewToClipPrevMatrix.SetElement(0, 2, m_clipSpaceOffset.GetX()); + offsetViewToClipPrevMatrix.SetElement(1, 2, m_clipSpaceOffset.GetY()); + + // Build other matricies dependent on the view to clip matricies + Matrix4x4 offsetWorldToClipMatrix = offsetViewToClipMatrix * m_worldToViewMatrix; + Matrix4x4 offsetWorldToClipPrevMatrix = offsetViewToClipPrevMatrix * m_worldToViewPrevMatrix; + + Matrix4x4 offsetClipToViewMatrix = offsetViewToClipMatrix.GetInverseFull(); + Matrix4x4 offsetClipToWorldMatrix = m_viewToWorldMatrix * offsetClipToViewMatrix; + + m_shaderResourceGroup->SetConstant(m_worldToClipPrevMatrixConstantIndex, offsetWorldToClipPrevMatrix); + m_shaderResourceGroup->SetConstant(m_viewProjectionMatrixConstantIndex, offsetWorldToClipMatrix); + m_shaderResourceGroup->SetConstant(m_projectionMatrixConstantIndex, offsetViewToClipMatrix); + m_shaderResourceGroup->SetConstant(m_clipToWorldMatrixConstantIndex, offsetClipToWorldMatrix); + m_shaderResourceGroup->SetConstant(m_projectionMatrixInverseConstantIndex, offsetViewToClipMatrix.GetInverseFull()); + } + + m_shaderResourceGroup->SetConstant(m_worldPositionConstantIndex, m_position); + m_shaderResourceGroup->SetConstant(m_viewMatrixConstantIndex, m_worldToViewMatrix); + m_shaderResourceGroup->SetConstant(m_viewMatrixInverseConstantIndex, m_worldToViewMatrix.GetInverseFull()); + m_shaderResourceGroup->SetConstant(m_zConstantsConstantIndex, m_nearZ_farZ_farZTimesNearZ_farZMinusNearZ); + m_shaderResourceGroup->SetConstant(m_unprojectionConstantsIndex, m_unprojectionConstants); + + m_shaderResourceGroup->Compile(); m_viewToClipPrevMatrix = m_viewToClipMatrix; m_worldToViewPrevMatrix = m_worldToViewMatrix; From 4beb66c9caee9e9f1c3bce290c3ccc851ebe75d4 Mon Sep 17 00:00:00 2001 From: antonmic <56370189+antonmic@users.noreply.github.com> Date: Sun, 8 Aug 2021 23:37:54 -0700 Subject: [PATCH 175/803] Making pass files declare dependency on shader files (part 01) Signed-off-by: antonmic <56370189+antonmic@users.noreply.github.com> --- .../Code/Source/Editor/ShaderAssetBuilder.cpp | 3 +- .../Editor/ShaderVariantAssetBuilder.cpp | 2 +- .../Source/RPI.Builders/Pass/PassBuilder.cpp | 197 ++++++++++++++---- .../Source/RPI.Builders/Pass/PassBuilder.h | 1 - 4 files changed, 159 insertions(+), 44 deletions(-) diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderAssetBuilder.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderAssetBuilder.cpp index b1a3de2794..606502fb22 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderAssetBuilder.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderAssetBuilder.cpp @@ -139,8 +139,7 @@ namespace AZ AssetBuilderSDK::JobDescriptor jobDescriptor; jobDescriptor.m_priority = 2; - // [GFX TODO][ATOM-2830] Set 'm_critical' back to 'false' once proper fix for Atom startup issues are in - jobDescriptor.m_critical = true; + jobDescriptor.m_critical = false; jobDescriptor.m_jobKey = ShaderAssetBuilderJobKey; jobDescriptor.SetPlatformIdentifier(platformInfo.m_identifier.c_str()); jobDescriptor.m_jobParameters.emplace(ShaderAssetBuildTimestampParam, AZStd::to_string(shaderAssetBuildTimestamp)); diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp index 1da4623774..ee02ae8452 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp @@ -321,7 +321,7 @@ namespace AZ AssetBuilderSDK::JobDescriptor jobDescriptor; jobDescriptor.m_priority = -5000; - jobDescriptor.m_critical = false; + jobDescriptor.m_critical = true; jobDescriptor.m_jobKey = ShaderVariantAssetBuilderJobKey; jobDescriptor.SetPlatformIdentifier(info.m_identifier.data()); diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Pass/PassBuilder.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/Pass/PassBuilder.cpp index 652130dea2..f582f3ba04 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Pass/PassBuilder.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Pass/PassBuilder.cpp @@ -37,7 +37,7 @@ namespace AZ { AssetBuilderSDK::AssetBuilderDesc builder; builder.m_name = PassBuilderJobKey; - builder.m_version = 12; // ATOM-15472 + builder.m_version = 13; // antonmic: making .pass files declare dependency on shaders they reference builder.m_busId = azrtti_typeid(); builder.m_createJobFunction = AZStd::bind(&PassBuilder::CreateJobs, this, AZStd::placeholders::_1, AZStd::placeholders::_2); builder.m_processJobFunction = AZStd::bind(&PassBuilder::ProcessJob, this, AZStd::placeholders::_1, AZStd::placeholders::_2); @@ -65,35 +65,66 @@ namespace AZ m_isShuttingDown = true; } - void PassBuilder::CreateJobs(const AssetBuilderSDK::CreateJobsRequest& request, AssetBuilderSDK::CreateJobsResponse& response) const + // --- Code related to dependency shader asset handling --- + + struct FindPassReferenceAssetParams { - if (m_isShuttingDown) + void* passAssetObject; + Uuid passAssetUuid; + SerializeContext* serializeContext; + AZStd::string_view passAssetSourceFile; // File path of the pass asset + AZStd::string_view dependencySourceFile; // File pass of the asset the pass asset depends on + const char* jobKey; // Job key for adding job dependency + }; + + //! Adds all relevant dependencies for a referenced source file, considering that the path might be relative to the original file location or a full asset path. + //! This will usually include multiple source dependencies and a single job dependency, but will include only source dependencies if the file is not found. + //! Note the AssetBuilderSDK::JobDependency::m_platformIdentifier will not be set by this function. The calling code must set this value before passing back + //! to the AssetBuilderSDK::CreateJobsResponse. + void AddPossibleDependencies( + FindPassReferenceAssetParams& params, + AssetBuilderSDK::CreateJobsResponse& response, + AssetBuilderSDK::JobDescriptor& job) + { + bool dependencyFileFound = false; + + AZStd::vector possibleDependencies = RPI::AssetUtils::GetPossibleDepenencyPaths(params.passAssetSourceFile, params.dependencySourceFile); + for (auto& file : possibleDependencies) { - response.m_result = AssetBuilderSDK::CreateJobsResultCode::ShuttingDown; - return; + AssetBuilderSDK::SourceFileDependency sourceFileDependency; + sourceFileDependency.m_sourceFileDependencyPath = file; + response.m_sourceFileDependencyList.push_back(sourceFileDependency); + + // The first path found is the highest priority, and will have a job dependency, as this is the one + // the builder will actually use + if (!dependencyFileFound) + { + AZ::Data::AssetInfo sourceInfo; + AZStd::string watchFolder; + AzToolsFramework::AssetSystemRequestBus::BroadcastResult(dependencyFileFound, &AzToolsFramework::AssetSystem::AssetSystemRequest::GetSourceInfoBySourcePath, file.c_str(), sourceInfo, watchFolder); + + if (dependencyFileFound) + { + AssetBuilderSDK::JobDependency jobDependency; + jobDependency.m_jobKey = params.jobKey; + jobDependency.m_type = AssetBuilderSDK::JobDependencyType::Order; + jobDependency.m_sourceFile.m_sourceFileDependencyPath = file; + job.m_jobDependencyList.push_back(jobDependency); + } + } } - - for (const AssetBuilderSDK::PlatformInfo& platformInfo : request.m_enabledPlatforms) - { - AssetBuilderSDK::JobDescriptor job; - job.m_jobKey = PassBuilderJobKey; - job.SetPlatformIdentifier(platformInfo.m_identifier.c_str()); - - // Passes are a critical part of the rendering system - job.m_critical = true; - - response.m_createJobOutputs.push_back(job); - } - - response.m_result = AssetBuilderSDK::CreateJobsResultCode::Success; } // Helper function to find all assetId's and object references - bool PassBuilder::FindPassReferencedAssets(void* objectPtr, Uuid passAssetUuid, SerializeContext* context, AZStd::unordered_set &referencedAssetList) const + bool FindPassReferencedAssets(FindPassReferenceAssetParams& params, + AZStd::unordered_set& referencedAssetList, + AssetBuilderSDK::CreateJobsResponse& response, + AssetBuilderSDK::JobDescriptor& job, + bool jobCreationPhase) { SerializeContext::ErrorHandler errorLogger; errorLogger.Reset(); - + bool foundProblems = false; // This callback will check whether the given element is an asset reference. If so, it will add it to the list of asset references @@ -103,26 +134,34 @@ namespace AZ if (classData->m_typeId == azrtti_typeid()) { AssetReference* assetReference = reinterpret_cast(ptr); - + // If the asset id isn't already provided, get it using the source file path if (!assetReference->m_assetId.IsValid() && !assetReference->m_filePath.empty()) { - AZStd::string path = assetReference->m_filePath; + const AZStd::string& path = assetReference->m_filePath; uint32_t subId = 0; - auto assetIdOutcome = AssetUtils::MakeAssetId(path, subId); - - if (assetIdOutcome) + if (jobCreationPhase) { - assetReference->m_assetId = assetIdOutcome.GetValue(); + params.dependencySourceFile = path; + AddPossibleDependencies(params, response, job); } - else + else // Process Job Phase { - AZ_Error(PassBuilderName, false, "Could not get AssetId for [%s]", assetReference->m_filePath.c_str()); - foundProblems = true; + auto assetIdOutcome = AssetUtils::MakeAssetId(path, subId); + + if (assetIdOutcome) + { + assetReference->m_assetId = assetIdOutcome.GetValue(); + } + else + { + AZ_Error(PassBuilderName, false, "Could not get AssetId for [%s]", assetReference->m_filePath.c_str()); + foundProblems = true; + } } } - + // If the asset ID is valid, add it as a dependency if (assetReference->m_assetId.IsValid()) { @@ -136,16 +175,16 @@ namespace AZ SerializeContext::EnumerateInstanceCallContext callContext( AZStd::move(beginCallback), nullptr, - context, + params.serializeContext, SerializeContext::ENUM_ACCESS_FOR_READ, &errorLogger ); // Recursively iterate over all elements in the object to find asset references with the above callback - context->EnumerateInstance( + params.serializeContext->EnumerateInstance( &callContext - , objectPtr - , passAssetUuid + , params.passAssetObject + , params.passAssetUuid , nullptr , nullptr ); @@ -153,6 +192,73 @@ namespace AZ return !foundProblems; } + // --- Code related to dependency shader asset handling --- + + void PassBuilder::CreateJobs(const AssetBuilderSDK::CreateJobsRequest& request, AssetBuilderSDK::CreateJobsResponse& response) const + { + if (m_isShuttingDown) + { + response.m_result = AssetBuilderSDK::CreateJobsResultCode::ShuttingDown; + return; + } + + AssetBuilderSDK::JobDescriptor job; + + // Get serialization context + SerializeContext* serializeContext = nullptr; + ComponentApplicationBus::BroadcastResult(serializeContext, &ComponentApplicationBus::Events::GetSerializeContext); + if (!serializeContext) + { + AZ_Assert(false, "No serialize context"); + return; + } + + // Load PassAsset + AZStd::string fullPath; + AzFramework::StringFunc::Path::ConstructFull(request.m_watchFolder.c_str(), request.m_sourceFile.c_str(), fullPath, true); + + PassAsset passAsset; + AZ::Outcome loadResult = JsonSerializationUtils::LoadObjectFromFile(passAsset, fullPath); + + if (!loadResult.IsSuccess()) + { + AZ_Error(PassBuilderName, false, "Failed to load pass asset [%s]", request.m_sourceFile.c_str()); + AZ_Error(PassBuilderName, false, "Loading issues: %s", loadResult.GetError().data()); + return; + } + + // Find all Asset IDs we depend on + AZStd::unordered_set dependentList; + Uuid passAssetUuid = AzTypeInfo::Uuid(); + + FindPassReferenceAssetParams params; + params.passAssetObject = &passAsset; + params.passAssetSourceFile = request.m_sourceFile; + params.passAssetUuid = passAssetUuid; + params.serializeContext = serializeContext; + params.jobKey = "Shader Asset"; + + if (!FindPassReferencedAssets(params, dependentList, response, job, true)) + { + return; + } + + for (const AssetBuilderSDK::PlatformInfo& platformInfo : request.m_enabledPlatforms) + { + job.m_jobKey = PassBuilderJobKey; + job.SetPlatformIdentifier(platformInfo.m_identifier.c_str()); + + // Passes are a critical part of the rendering system + job.m_critical = true; + + response.m_createJobOutputs.push_back(job); + } + + response.m_result = AssetBuilderSDK::CreateJobsResultCode::Success; + } + + + void PassBuilder::ProcessJob(const AssetBuilderSDK::ProcessJobRequest& request, AssetBuilderSDK::ProcessJobResponse& response) const { // Handle job cancellation and shutdown cases @@ -164,9 +270,9 @@ namespace AZ } // Get serialization context - SerializeContext* context = nullptr; - ComponentApplicationBus::BroadcastResult(context, &ComponentApplicationBus::Events::GetSerializeContext); - if (!context) + SerializeContext* serializeContext = nullptr; + ComponentApplicationBus::BroadcastResult(serializeContext, &ComponentApplicationBus::Events::GetSerializeContext); + if (!serializeContext) { AZ_Assert(false, "No serialize context"); return; @@ -186,7 +292,18 @@ namespace AZ // Find all Asset IDs we depend on AZStd::unordered_set dependentList; Uuid passAssetUuid = AzTypeInfo::Uuid(); - if (!FindPassReferencedAssets(&passAsset, passAssetUuid, context, dependentList)) + + FindPassReferenceAssetParams params; + params.passAssetObject = &passAsset; + params.passAssetSourceFile = request.m_sourceFile; + params.passAssetUuid = passAssetUuid; + params.serializeContext = serializeContext; + params.jobKey = "Shader Asset"; + + AssetBuilderSDK::CreateJobsResponse dummyResponse; + AssetBuilderSDK::JobDescriptor dummyJob; + + if (!FindPassReferencedAssets(params, dependentList, dummyResponse, dummyJob, false)) { return; } @@ -198,7 +315,7 @@ namespace AZ AzFramework::StringFunc::Path::ConstructFull(request.m_tempDirPath.c_str(), destFileName.c_str(), destPath, true); // Save the asset to binary format for production - bool result = Utils::SaveObjectToFile(destPath, DataStream::ST_BINARY, &passAsset, passAssetUuid, context); + bool result = Utils::SaveObjectToFile(destPath, DataStream::ST_BINARY, &passAsset, passAssetUuid, serializeContext); if (result == false) { AZ_Error(PassBuilderName, false, "Failed to save asset to %s", destPath.c_str()); diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Pass/PassBuilder.h b/Gems/Atom/RPI/Code/Source/RPI.Builders/Pass/PassBuilder.h index 6130ae8edc..8c159efc56 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Pass/PassBuilder.h +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Pass/PassBuilder.h @@ -37,7 +37,6 @@ namespace AZ void RegisterBuilder(); private: - bool FindPassReferencedAssets(void* objectPtr, Uuid passAssetUuid, SerializeContext* context, AZStd::unordered_set &referencedAssetList) const; bool m_isShuttingDown = false; }; From 733dc31518f106972b5d2e902c8ce49c08a84cac Mon Sep 17 00:00:00 2001 From: Benjamin Jillich Date: Thu, 5 Aug 2021 16:37:47 +0200 Subject: [PATCH 176/803] Fixed emfx unit tests Signed-off-by: Benjamin Jillich --- .../RCExt/Actor/ActorGroupExporter.cpp | 2 -- .../Code/EMotionFX/Rendering/Common/Camera.h | 1 + .../EMotionFX/Rendering/Common/RenderUtil.cpp | 24 ++++++++++--------- .../Rendering/Common/ScaleManipulator.h | 2 +- Gems/EMotionFX/Code/EMotionFX/Source/Actor.h | 2 +- .../Code/EMotionFX/Source/ActorInstance.cpp | 2 +- .../Source/RenderPlugin/RenderWidget.cpp | 2 +- .../Components/EditorActorComponent.cpp | 4 ++-- .../Code/Tests/Integration/CanAddActor.cpp | 2 +- .../Code/Tests/TestAssetCode/ActorFactory.h | 2 +- .../Code/Tests/TestAssets/Rin/rin.actor | 4 ++-- 11 files changed, 24 insertions(+), 23 deletions(-) diff --git a/Gems/EMotionFX/Code/EMotionFX/Pipeline/RCExt/Actor/ActorGroupExporter.cpp b/Gems/EMotionFX/Code/EMotionFX/Pipeline/RCExt/Actor/ActorGroupExporter.cpp index ba8168476c..a498ed2cb7 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Pipeline/RCExt/Actor/ActorGroupExporter.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Pipeline/RCExt/Actor/ActorGroupExporter.cpp @@ -49,8 +49,6 @@ namespace EMotionFX if (serializeContext) { // Increasing the version number of the actor group exporter will make sure all actor products will be force re-generated. - // Version history: - // v3: Introduced Actor_Nodes2 (replaced Actor_Nodes) and Actor_Node2 (replaced Actor_Node) serializeContext->Class()->Version(3); } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/Camera.h b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/Camera.h index 0c7b19384e..6a95621b0d 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/Camera.h +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/Camera.h @@ -11,6 +11,7 @@ #include #include +#include #include #include #include "MCommonConfig.h" diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RenderUtil.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RenderUtil.cpp index 8464cb2b2a..9c0a4af895 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RenderUtil.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RenderUtil.cpp @@ -240,8 +240,8 @@ namespace MCommon // render selection gizmo around the given AABB void RenderUtil::RenderSelection(const AZ::Aabb& box, const MCore::RGBAColor& color, bool directlyRender) { - const AZ::Vector3 min = box.GetMin(); - const AZ::Vector3 max = box.GetMax(); + const AZ::Vector3& min = box.GetMin(); + const AZ::Vector3& max = box.GetMax(); const float radius = AZ::Vector3(box.GetMax() - box.GetMin()).GetLength() * 0.5f; const float scale = radius * 0.1f; const AZ::Vector3 up = AZ::Vector3(0.0f, 1.0f, 0.0f) * scale; @@ -249,15 +249,17 @@ namespace MCommon const AZ::Vector3 front = AZ::Vector3(0.0f, 0.0f, 1.0f) * scale; // generate our vertices - AZ::Vector3 p[8]; - p[0].Set(min.GetX(), min.GetY(), min.GetZ()); - p[1].Set(max.GetX(), min.GetY(), min.GetZ()); - p[2].Set(max.GetX(), min.GetY(), max.GetZ()); - p[3].Set(min.GetX(), min.GetY(), max.GetZ()); - p[4].Set(min.GetX(), max.GetY(), min.GetZ()); - p[5].Set(max.GetX(), max.GetY(), min.GetZ()); - p[6].Set(max.GetX(), max.GetY(), max.GetZ()); - p[7].Set(min.GetX(), max.GetY(), max.GetZ()); + const AZStd::array p + { + AZ::Vector3{min.GetX(), min.GetY(), min.GetZ()}, + AZ::Vector3{max.GetX(), min.GetY(), min.GetZ()}, + AZ::Vector3{max.GetX(), min.GetY(), max.GetZ()}, + AZ::Vector3{min.GetX(), min.GetY(), max.GetZ()}, + AZ::Vector3{min.GetX(), max.GetY(), min.GetZ()}, + AZ::Vector3{max.GetX(), max.GetY(), min.GetZ()}, + AZ::Vector3{max.GetX(), max.GetY(), max.GetZ()}, + AZ::Vector3{min.GetX(), max.GetY(), max.GetZ()}, + }; // render the box RenderLine(p[0], p[0] + up, color); diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/ScaleManipulator.h b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/ScaleManipulator.h index 8cfd3ec541..6d2f167893 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/ScaleManipulator.h +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/ScaleManipulator.h @@ -8,7 +8,7 @@ #pragma once -// include the Core system +#include #include #include #include "MCommonConfig.h" diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Actor.h b/Gems/EMotionFX/Code/EMotionFX/Source/Actor.h index 1c1173a9a2..faf5b6b94d 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Actor.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Actor.h @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include #include diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.cpp index 162d826ca4..b80aab3c50 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.cpp @@ -635,7 +635,7 @@ namespace EMotionFX } // Expand the bounding volume by a tolerance area in case set. - if (m_boundsExpandBy > 0.0f) + if (!AZ::IsClose(m_boundsExpandBy, 0.0f)) { const AZ::Vector3 center = m_aabb.GetCenter(); const AZ::Vector3 halfExtents = m_aabb.GetExtents() * 0.5f; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderWidget.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderWidget.cpp index fb0ce4fdbf..25ae2ba2d4 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderWidget.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderWidget.cpp @@ -6,7 +6,6 @@ * */ -// include the required headers #include "RenderWidget.h" #include "RenderPlugin.h" #include @@ -21,6 +20,7 @@ #include "../EMStudioManager.h" #include "../MainWindow.h" #include +#include namespace EMStudio diff --git a/Gems/EMotionFX/Code/Source/Integration/Editor/Components/EditorActorComponent.cpp b/Gems/EMotionFX/Code/Source/Integration/Editor/Components/EditorActorComponent.cpp index ed5333da9c..160cbe8ee4 100644 --- a/Gems/EMotionFX/Code/Source/Integration/Editor/Components/EditorActorComponent.cpp +++ b/Gems/EMotionFX/Code/Source/Integration/Editor/Components/EditorActorComponent.cpp @@ -67,7 +67,7 @@ namespace EMotionFX "The method used to compute the Actor bounding box. NOTE: ordered by least expensive to compute to most expensive to compute.") ->EnumAttribute(ActorInstance::BOUNDS_STATIC_BASED, "Static (Recommended)") ->EnumAttribute(ActorInstance::BOUNDS_NODE_BASED, "Bone position-based") - ->EnumAttribute(ActorInstance::BOUNDS_MESH_BASED, "Mesh vertex-based (Expensive)") + ->EnumAttribute(ActorInstance::BOUNDS_MESH_BASED, "Mesh vertex-based (VERY EXPENSIVE)") ->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ::Edit::PropertyRefreshLevels::EntireTree) ->DataElement(AZ::Edit::UIHandlers::Default, &ActorComponent::BoundingBoxConfiguration::m_expandBy, "Expand by", @@ -75,7 +75,7 @@ namespace EMotionFX "This can be used to add a tolerance area to the calculated bounding box to avoid clipping the character too early. " "A static bounding box together with the expansion is the recommended way for maximum performance. (Default = 25%)") ->Attribute(AZ::Edit::Attributes::Suffix, " %") - ->Attribute(AZ::Edit::Attributes::Min, 0.0f) + ->Attribute(AZ::Edit::Attributes::Min, -100.0f + AZ::Constants::Tolerance) ->DataElement(AZ::Edit::UIHandlers::Default, &ActorComponent::BoundingBoxConfiguration::m_autoUpdateBounds, "Automatically update bounds?", "If true, bounds are automatically updated based on some frequency. Otherwise bounds are computed only at creation or when triggered manually") diff --git a/Gems/EMotionFX/Code/Tests/Integration/CanAddActor.cpp b/Gems/EMotionFX/Code/Tests/Integration/CanAddActor.cpp index 3c529c93dd..9b18ca5862 100644 --- a/Gems/EMotionFX/Code/Tests/Integration/CanAddActor.cpp +++ b/Gems/EMotionFX/Code/Tests/Integration/CanAddActor.cpp @@ -40,7 +40,7 @@ namespace EMotionFX } // Ensure the Actor is correct - ASSERT_TRUE(GetActorManager().FindActorByName("rinactor")); + ASSERT_TRUE(GetActorManager().FindActorByName("rinActor")); EXPECT_EQ(GetActorManager().GetNumActors(), 1); } } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/Tests/TestAssetCode/ActorFactory.h b/Gems/EMotionFX/Code/Tests/TestAssetCode/ActorFactory.h index 73519e079e..198fe4ce49 100644 --- a/Gems/EMotionFX/Code/Tests/TestAssetCode/ActorFactory.h +++ b/Gems/EMotionFX/Code/Tests/TestAssetCode/ActorFactory.h @@ -22,7 +22,7 @@ namespace EMotionFX actor->SetID(0); actor->GetSkeleton()->UpdateNodeIndexValues(0); actor->ResizeTransformData(); - actor->PostCreateInit(/*makeGeomLodsCompatibleWithSkeletalLODs=*/false, /*generateOBBs=*/false, /*convertUnitType=*/false); + actor->PostCreateInit(/*makeGeomLodsCompatibleWithSkeletalLODs=*/false, /*convertUnitType=*/false); return actor; } }; diff --git a/Gems/EMotionFX/Code/Tests/TestAssets/Rin/rin.actor b/Gems/EMotionFX/Code/Tests/TestAssets/Rin/rin.actor index 5a79fd5f48..20d4ffef85 100644 --- a/Gems/EMotionFX/Code/Tests/TestAssets/Rin/rin.actor +++ b/Gems/EMotionFX/Code/Tests/TestAssets/Rin/rin.actor @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7db74f39a261bb70e1fdbdd546c337107809cdbdd1fc52568a0d30358b0f83d7 -size 30005 +oid sha256:55ecbc78a913c808cd007326b51dfc98b943b196b77fd6dc16aff0892b112e74 +size 16948 From 659e486cd791f7da4d1cf12fdd08fa2048bdb8b2 Mon Sep 17 00:00:00 2001 From: hultonha <82228511+hultonha@users.noreply.github.com> Date: Mon, 9 Aug 2021 11:56:19 +0100 Subject: [PATCH 177/803] Add an integration test to validate pick mode crash (#2935) * add an integration test to validate pick mode crash Signed-off-by: hultonha * update to test after review feedback Signed-off-by: hultonha --- .../UnitTest/AzToolsFrameworkTestHelpers.cpp | 29 +++++++++++++ .../UnitTest/AzToolsFrameworkTestHelpers.h | 26 ++++++----- .../Framework/AzToolsFramework/CMakeLists.txt | 2 + ...EditorTransformComponentSelectionTests.cpp | 43 +++++++++++++++++++ 4 files changed, 89 insertions(+), 11 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.cpp index 5ffbe1b4f3..1bec929223 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.cpp @@ -65,6 +65,35 @@ namespace UnitTest } } + bool FocusInteractionWidget::event(QEvent* event) + { + using AzToolsFramework::EditorInteractionSystemViewportSelectionRequestBus; + + auto eventType = event->type(); + + switch (eventType) + { + case QEvent::MouseButtonPress: + EditorInteractionSystemViewportSelectionRequestBus::Event( + AzToolsFramework::GetEntityContextId(), &EditorInteractionSystemViewportSelectionRequestBus::Events::SetDefaultHandler); + return true; + case QEvent::FocusIn: + case QEvent::FocusOut: + { + bool handled = false; + AzToolsFramework::ViewportInteraction::MouseInteraction mouseInteraction; + EditorInteractionSystemViewportSelectionRequestBus::EventResult( + handled, AzToolsFramework::GetEntityContextId(), + &EditorInteractionSystemViewportSelectionRequestBus::Events::InternalHandleMouseViewportInteraction, + AzToolsFramework::ViewportInteraction::MouseInteractionEvent( + mouseInteraction, AzToolsFramework::ViewportInteraction::MouseEvent::Down)); + return handled; + } + } + + return QWidget::event(event); + } + void TestEditorActions::Connect() { using AzToolsFramework::GetEntityContextId; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h index 7967f58bf6..3c413fd21e 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h @@ -8,6 +8,7 @@ #pragma once +#if !defined(Q_MOC_RUN) #include #include #include @@ -31,6 +32,7 @@ #include #include #include +#endif // !defined(Q_MOC_RUN) #include @@ -40,7 +42,7 @@ AZ_POP_DISABLE_WARNING #define AUTO_RESULT_IF_SETTING_TRUE(_settingName, _result) \ { \ - bool settingValue = true; \ + bool settingValue = true; \ if (auto* registry = AZ::SettingsRegistry::Get()) \ { \ registry->Get(settingValue, _settingName); \ @@ -51,23 +53,16 @@ AZ_POP_DISABLE_WARNING EXPECT_TRUE(_result); \ return; \ } \ - } - -namespace AZ -{ - class Entity; - class EntityId; - -} // namespace AZ + } namespace UnitTest { constexpr AZStd::string_view prefabSystemSetting = "/Amazon/Preferences/EnablePrefabSystem"; /// Test widget to store QActions generated by EditorTransformComponentSelection. - class TestWidget - : public QWidget + class TestWidget : public QWidget { + Q_OBJECT public: TestWidget() : QWidget() @@ -79,6 +74,15 @@ namespace UnitTest bool eventFilter(QObject* watched, QEvent* event) override; }; + /// Widget used to trigger a viewport interaction event while a focus change is happening. + class FocusInteractionWidget : public QWidget + { + Q_OBJECT + public: + FocusInteractionWidget(QWidget* parent = nullptr) : QWidget(parent) {} + bool event(QEvent* event) override; + }; + /// Stores actions registered for either normal mode (regular viewport) editing and /// component mode editing. class TestEditorActions diff --git a/Code/Framework/AzToolsFramework/CMakeLists.txt b/Code/Framework/AzToolsFramework/CMakeLists.txt index a2138b8a0e..62f4f43d93 100644 --- a/Code/Framework/AzToolsFramework/CMakeLists.txt +++ b/Code/Framework/AzToolsFramework/CMakeLists.txt @@ -50,6 +50,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) ly_add_target( NAME AzToolsFrameworkTestCommon STATIC NAMESPACE AZ + AUTOMOC FILES_CMAKE AzToolsFramework/aztoolsframeworktestcommon_files.cmake INCLUDE_DIRECTORIES @@ -68,6 +69,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) ly_add_target( NAME AzToolsFramework.Tests ${PAL_TRAIT_TEST_TARGET_TYPE} NAMESPACE AZ + AUTOMOC FILES_CMAKE Tests/aztoolsframeworktests_files.cmake INCLUDE_DIRECTORIES diff --git a/Code/Framework/AzToolsFramework/Tests/EditorTransformComponentSelectionTests.cpp b/Code/Framework/AzToolsFramework/Tests/EditorTransformComponentSelectionTests.cpp index f45b3c3b09..895c91b0a4 100644 --- a/Code/Framework/AzToolsFramework/Tests/EditorTransformComponentSelectionTests.cpp +++ b/Code/Framework/AzToolsFramework/Tests/EditorTransformComponentSelectionTests.cpp @@ -31,8 +31,10 @@ #include #include #include +#include #include #include +#include namespace AZ { @@ -188,6 +190,47 @@ namespace UnitTest /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // EditorTransformComponentSelection Tests + TEST_F(EditorTransformComponentSelectionFixture, Focus_is_not_changed_while_switching_viewport_interaction_request_instance) + { + // setup a dummy widget and make it the active window to ensure focus in/out events are fired + auto dummyWidget = AZStd::make_unique(); + QApplication::setActiveWindow(dummyWidget.get()); + + // note: it is important to make sure the focus widget is parented to the dummy widget to have focus in/out events fire + auto focusWidget = AZStd::make_unique(dummyWidget.get()); + + const auto previousFocusWidget = QApplication::focusWidget(); + + // Given + // setup viewport ui system + AzToolsFramework::ViewportUi::ViewportUiManager viewportUiManager; + viewportUiManager.ConnectViewportUiBus(AzToolsFramework::ViewportUi::DefaultViewportId); + viewportUiManager.InitializeViewportUi(&m_editorActions.m_defaultWidget, focusWidget.get()); + + // begin EditorPickEntitySelection + using AzToolsFramework::EditorInteractionSystemViewportSelectionRequestBus; + EditorInteractionSystemViewportSelectionRequestBus::Event( + AzToolsFramework::GetEntityContextId(), &EditorInteractionSystemViewportSelectionRequestBus::Events::SetHandler, + [](const AzToolsFramework::EditorVisibleEntityDataCache* entityDataCache) + { + return AZStd::make_unique(entityDataCache); + }); + + // When + // a mouse event is sent to the focus widget (set to be the render overlay in the viewport ui system) + QTest::mouseClick(focusWidget.get(), Qt::MouseButton::LeftButton); + + // Then + // focus should not change + EXPECT_FALSE(focusWidget->hasFocus()); + EXPECT_EQ(previousFocusWidget, QApplication::focusWidget()); + + // clean up + viewportUiManager.DisconnectViewportUiBus(); + focusWidget.reset(); + dummyWidget.reset(); + } + TEST_F(EditorTransformComponentSelectionFixture, ManipulatorOrientationIsResetWhenEntityOrientationIsReset) { using AzToolsFramework::EditorTransformComponentSelectionRequestBus; From 12505da6fcf9e3970dc97e4ae43b93bac587908a Mon Sep 17 00:00:00 2001 From: John Jones-Steele Date: Mon, 9 Aug 2021 16:01:18 +0100 Subject: [PATCH 178/803] Changed locale handling and added tests Signed-off-by: John Jones-Steele --- Code/Editor/CryEdit.cpp | 3 -- .../Application/AzQtApplication.cpp | 2 - .../AzQtComponents/Gallery/main.cpp | 2 - .../Tests/FloatToStringConversionTests.cpp | 40 +++++++++++++++++++ .../ProjectManager/Source/Application.cpp | 2 - 5 files changed, 40 insertions(+), 9 deletions(-) diff --git a/Code/Editor/CryEdit.cpp b/Code/Editor/CryEdit.cpp index cd1dd4fe47..47ad7e5381 100644 --- a/Code/Editor/CryEdit.cpp +++ b/Code/Editor/CryEdit.cpp @@ -1626,9 +1626,6 @@ BOOL CCryEditApp::InitInstance() ReflectedVarInit::setupReflection(serializeContext); RegisterReflectedVarHandlers(); - - QLocale::setDefault(QLocale(QLocale::English, QLocale::UnitedStates)); - CreateSplashScreen(); // Register the application's document templates. Document templates diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Application/AzQtApplication.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Application/AzQtApplication.cpp index 594a339448..9dece6e26a 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Application/AzQtApplication.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Application/AzQtApplication.cpp @@ -22,8 +22,6 @@ namespace AzQtComponents QApplication::setApplicationName("O3DE Tools Application"); AzQtComponents::PrepareQtPaths(); - - QLocale::setDefault(QLocale(QLocale::English, QLocale::UnitedStates)); } void AzQtApplication::InitializeDpiScaling() diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/main.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/main.cpp index 51ca2b349f..fc8af9e8ce 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Gallery/main.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Gallery/main.cpp @@ -134,8 +134,6 @@ int main(int argc, char **argv) QApplication::setOrganizationDomain("o3de.org"); QApplication::setApplicationName("O3DEWidgetGallery"); - QLocale::setDefault(QLocale(QLocale::English, QLocale::UnitedStates)); - QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough); diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Tests/FloatToStringConversionTests.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Tests/FloatToStringConversionTests.cpp index da4d8de4cd..a0a8155475 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Tests/FloatToStringConversionTests.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Tests/FloatToStringConversionTests.cpp @@ -64,3 +64,43 @@ TEST(AzQtComponents, FloatToString_TruncateShowThousandsSeparatorOnlyOneDecimal) int numDecimalPlaces = 2; EXPECT_EQ(AzQtComponents::toString(1000.000, numDecimalPlaces, testLocal, showThousandsSeparator), "1,000.0"); } + +TEST(AzQtComponents, FloatToString_Truncate2DecimalsWithLocale) +{ + QLocale testLocal{ QLocale() }; + + const bool showThousandsSeparator = false; + const int numDecimalPlaces = 2; + QString testString = "0" + QString(testLocal.decimalPoint()) + "12"; + EXPECT_EQ(AzQtComponents::toString(0.1234, numDecimalPlaces, testLocal, showThousandsSeparator), testString); +} + +TEST(AzQtComponents, FloatToString_AllZerosButOneWithLocale) +{ + QLocale testLocal{ QLocale() }; + + const bool showThousandsSeparator = false; + const int numDecimalPlaces = 2; + QString testString = "1" + QString(testLocal.decimalPoint()) + "0"; + EXPECT_EQ(AzQtComponents::toString(1.0000, numDecimalPlaces, testLocal, showThousandsSeparator), testString); +} + +TEST(AzQtComponents, FloatToString_TruncateShowThousandsSeparatorTruncateNoRoundWithLocale) +{ + QLocale testLocal{ QLocale() }; + + const bool showThousandsSeparator = true; + const int numDecimalPlaces = 3; + QString testString = "1" + QString(testLocal.groupSeparator()) + "000" + QString(testLocal.decimalPoint()) + "123"; + EXPECT_EQ(AzQtComponents::toString(1000.1236, numDecimalPlaces, testLocal, showThousandsSeparator), testString); +} + +TEST(AzQtComponents, FloatToString_TruncateShowThousandsSeparatorOnlyOneDecimalWithLocale) +{ + QLocale testLocal{ QLocale() }; + + const bool showThousandsSeparator = true; + int numDecimalPlaces = 2; + QString testString = "1" + QString(testLocal.groupSeparator()) + "000" + QString(testLocal.decimalPoint()) + "0"; + EXPECT_EQ(AzQtComponents::toString(1000.000, numDecimalPlaces, testLocal, showThousandsSeparator), testString); +} diff --git a/Code/Tools/ProjectManager/Source/Application.cpp b/Code/Tools/ProjectManager/Source/Application.cpp index bdcb59897b..c977698152 100644 --- a/Code/Tools/ProjectManager/Source/Application.cpp +++ b/Code/Tools/ProjectManager/Source/Application.cpp @@ -56,8 +56,6 @@ namespace O3DE::ProjectManager QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); QCoreApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings); - QLocale::setDefault(QLocale(QLocale::English, QLocale::UnitedStates)); - QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough); AzQtComponents::Utilities::HandleDpiAwareness(AzQtComponents::Utilities::SystemDpiAware); From 3b60862237ace01f572fd1d333a28a8e0021070c Mon Sep 17 00:00:00 2001 From: John Jones-Steele Date: Mon, 9 Aug 2021 16:30:49 +0100 Subject: [PATCH 179/803] Fixed order of tests Signed-off-by: John Jones-Steele --- .../AzQtComponents/Tests/FloatToStringConversionTests.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Tests/FloatToStringConversionTests.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Tests/FloatToStringConversionTests.cpp index a0a8155475..21db675324 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Tests/FloatToStringConversionTests.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Tests/FloatToStringConversionTests.cpp @@ -72,7 +72,7 @@ TEST(AzQtComponents, FloatToString_Truncate2DecimalsWithLocale) const bool showThousandsSeparator = false; const int numDecimalPlaces = 2; QString testString = "0" + QString(testLocal.decimalPoint()) + "12"; - EXPECT_EQ(AzQtComponents::toString(0.1234, numDecimalPlaces, testLocal, showThousandsSeparator), testString); + EXPECT_EQ(testString, AzQtComponents::toString(0.1234, numDecimalPlaces, testLocal, showThousandsSeparator)); } TEST(AzQtComponents, FloatToString_AllZerosButOneWithLocale) @@ -82,7 +82,7 @@ TEST(AzQtComponents, FloatToString_AllZerosButOneWithLocale) const bool showThousandsSeparator = false; const int numDecimalPlaces = 2; QString testString = "1" + QString(testLocal.decimalPoint()) + "0"; - EXPECT_EQ(AzQtComponents::toString(1.0000, numDecimalPlaces, testLocal, showThousandsSeparator), testString); + EXPECT_EQ(testString, AzQtComponents::toString(1.0000, numDecimalPlaces, testLocal, showThousandsSeparator)); } TEST(AzQtComponents, FloatToString_TruncateShowThousandsSeparatorTruncateNoRoundWithLocale) @@ -92,7 +92,7 @@ TEST(AzQtComponents, FloatToString_TruncateShowThousandsSeparatorTruncateNoRound const bool showThousandsSeparator = true; const int numDecimalPlaces = 3; QString testString = "1" + QString(testLocal.groupSeparator()) + "000" + QString(testLocal.decimalPoint()) + "123"; - EXPECT_EQ(AzQtComponents::toString(1000.1236, numDecimalPlaces, testLocal, showThousandsSeparator), testString); + EXPECT_EQ(testString, AzQtComponents::toString(1000.1236, numDecimalPlaces, testLocal, showThousandsSeparator)); } TEST(AzQtComponents, FloatToString_TruncateShowThousandsSeparatorOnlyOneDecimalWithLocale) @@ -102,5 +102,5 @@ TEST(AzQtComponents, FloatToString_TruncateShowThousandsSeparatorOnlyOneDecimalW const bool showThousandsSeparator = true; int numDecimalPlaces = 2; QString testString = "1" + QString(testLocal.groupSeparator()) + "000" + QString(testLocal.decimalPoint()) + "0"; - EXPECT_EQ(AzQtComponents::toString(1000.000, numDecimalPlaces, testLocal, showThousandsSeparator), testString); + EXPECT_EQ(testString, AzQtComponents::toString(1000.000, numDecimalPlaces, testLocal, showThousandsSeparator)); } From 8884227fe6cdf0dd5235ac041e68247229d287cd Mon Sep 17 00:00:00 2001 From: Chris Burel Date: Mon, 24 May 2021 12:03:11 -0700 Subject: [PATCH 180/803] Remove MCore::Array This translates all usages of MCore::Array to AZStd::vector. It is designed to be as minimal of a change as possible (no changing to range-for loops or other C++11 stuff). We can decide to submit this wholesale, or submit it to a separate branch that we can then integrate individual files from once we're ready to do a specific class's transition. It does not completely solve the `uint32`->`size_t` transition. One important finding from doing this: `MCore::Array` uses a `memcpy` when it reallocates. `AZStd::vector` will use the contained type's copy or move constructor, per element. This is a significant change in behavior. If you have type, `SomeStruct` that defines a destructor, that type is copyable and not movable. So if you have a `MCore::Array`, and you call `Add(); Add(); Add()`, that reallocates 3 times, copying the contents using `memcpy`, and never invokes `SomeStruct`'s copy constructor or destructor. Translating that to `AZStd::vector` and calling `push_back(); push_back(); push_back();` will still reallocate 3 times, but it sees that `SomeStruct` is non-movable, and uses the copy constructor to make the copies, and then the destructor on the previous values. This call to the destructor wasn't there before, and can cause things to be deleted that weren't before. The solution to this is to make that struct be a move-only type. Where possible, this was done by changing that type to use `AZStd::unique_ptr` instead of a raw pointer, to get the proper move behavior. Where that is not possible (types that inherit from `MCore::MemoryObject`), a hand-written move constructor was created. In general: GetLength() becomes size() GetMaxLength() becomes capacity() GetIsEmpty() becomes empty() Reserve() becomes reserve() ReserveExact() becomes reserve() Resize() becomes resize() ResizeFast() becomes resize_no_construct() Add() becomes emplace_back() AddExact() becomes emplace_back() AddEmpty() becomes emplace_back() AddEmptyExact() becomes emplace_back() GetPtr() becomes data() GetItem() becomes at() Shrink() becomes shrink_to_fit() GetFirst() becomes front() GetLast() becomes back() Remove() becomes erase() RemoveFirst() becomes erase() RemoveLast() becomes pop_back() RemoveByValue() becomes if (const auto it = AZStd::find(...); it != end(container)) container.erase(it); Insert() becomes emplace() Swap() becomes swap() Clear(true) becomes clear(); shrink_to_fit() Clear() becomes clear(); shrink_to_fit() Clear(false) becomes clear() Swap() becomes swap() Find() becomes AZStd::find MoveElements() becomes AZStd::move SetMemoryCategory() is removed Signed-off-by: Chris Burel --- .../CommandSystem/Source/ActorCommands.h | 2 +- .../Source/AnimGraphNodeCommands.cpp | 4 +- .../Source/AnimGraphParameterCommands.cpp | 2 +- .../Source/AnimGraphParameterCommands.h | 2 +- .../Source/MotionEventCommands.cpp | 6 +- .../Source/MotionEventCommands.h | 2 +- .../Source/SelectionCommands.cpp | 6 +- .../CommandSystem/Source/SelectionCommands.h | 2 +- .../Exporters/ExporterLib/Exporter/Exporter.h | 5 +- .../ExporterLib/Exporter/MaterialExport.cpp | 10 +- .../ExporterLib/Exporter/NodeExport.cpp | 24 +- .../EMotionFX/Rendering/Common/RenderUtil.cpp | 22 +- .../EMotionFX/Rendering/Common/RenderUtil.h | 20 +- .../Rendering/OpenGL2/Source/GBuffer.cpp | 2 +- .../Rendering/OpenGL2/Source/GLActor.cpp | 33 +- .../Rendering/OpenGL2/Source/GLRenderUtil.cpp | 17 +- .../Rendering/OpenGL2/Source/GLRenderUtil.h | 4 +- .../Rendering/OpenGL2/Source/GLSLShader.cpp | 53 +- .../Rendering/OpenGL2/Source/GLSLShader.h | 18 +- .../OpenGL2/Source/GraphicsManager.cpp | 6 +- .../OpenGL2/Source/GraphicsManager.h | 2 +- .../Rendering/OpenGL2/Source/Material.h | 2 +- .../OpenGL2/Source/PostProcessShader.cpp | 2 +- .../Rendering/OpenGL2/Source/ShaderCache.cpp | 15 +- .../OpenGL2/Source/StandardMaterial.cpp | 12 +- .../OpenGL2/Source/StandardMaterial.h | 2 +- .../Rendering/OpenGL2/Source/TextureCache.cpp | 19 +- .../Rendering/OpenGL2/Source/TextureCache.h | 4 +- .../Rendering/OpenGL2/Source/glactor.h | 14 +- .../Rendering/OpenGL2/Source/shadercache.h | 4 +- .../EMotionFX/Code/EMotionFX/Source/Actor.cpp | 182 ++-- Gems/EMotionFX/Code/EMotionFX/Source/Actor.h | 59 +- .../Code/EMotionFX/Source/ActorInstance.cpp | 68 +- .../Code/EMotionFX/Source/ActorInstance.h | 14 +- .../Code/EMotionFX/Source/ActorManager.cpp | 43 +- .../Code/EMotionFX/Source/ActorManager.h | 12 +- .../Code/EMotionFX/Source/AnimGraph.cpp | 20 +- .../Code/EMotionFX/Source/AnimGraph.h | 8 +- .../Source/AnimGraphGameControllerSettings.h | 8 +- .../EMotionFX/Source/AnimGraphInstance.cpp | 44 +- .../Code/EMotionFX/Source/AnimGraphInstance.h | 6 +- .../Code/EMotionFX/Source/AnimGraphManager.h | 2 +- .../Code/EMotionFX/Source/AnimGraphNode.cpp | 12 +- .../Code/EMotionFX/Source/AnimGraphNode.h | 6 +- .../Code/EMotionFX/Source/AnimGraphObject.cpp | 4 +- .../Code/EMotionFX/Source/AnimGraphObject.h | 4 +- .../EMotionFX/Source/AnimGraphPosePool.cpp | 36 +- .../Code/EMotionFX/Source/AnimGraphPosePool.h | 12 +- .../Source/AnimGraphRefCountedDataPool.cpp | 38 +- .../Source/AnimGraphRefCountedDataPool.h | 12 +- .../Source/AnimGraphReferenceNode.cpp | 2 +- .../EMotionFX/Source/AnimGraphReferenceNode.h | 2 +- .../Source/AnimGraphStateMachine.cpp | 2 +- .../EMotionFX/Source/AnimGraphStateMachine.h | 2 +- .../Source/AnimGraphStateTransition.cpp | 4 +- .../Source/AnimGraphStateTransition.h | 2 +- .../EMotionFX/Source/DualQuatSkinDeformer.h | 2 +- .../EMotionFX/Source/EMotionFXManager.cpp | 13 +- .../Code/EMotionFX/Source/EMotionFXManager.h | 8 +- .../Code/EMotionFX/Source/EventManager.h | 2 +- .../Source/Importer/ChunkProcessors.cpp | 14 +- .../Source/Importer/ChunkProcessors.h | 4 +- .../EMotionFX/Source/Importer/Importer.cpp | 75 +- .../Code/EMotionFX/Source/Importer/Importer.h | 20 +- .../EMotionFX/Source/KeyTrackLinearDynamic.h | 11 +- .../Source/KeyTrackLinearDynamic.inl | 14 - Gems/EMotionFX/Code/EMotionFX/Source/Mesh.cpp | 112 ++- Gems/EMotionFX/Code/EMotionFX/Source/Mesh.h | 18 +- Gems/EMotionFX/Code/EMotionFX/Source/Mesh.inl | 8 +- .../EMotionFX/Source/MeshDeformerStack.cpp | 40 +- .../Code/EMotionFX/Source/MeshDeformerStack.h | 6 +- .../EMotionFX/Source/MorphMeshDeformer.cpp | 21 +- .../Code/EMotionFX/Source/MorphMeshDeformer.h | 4 +- .../Code/EMotionFX/Source/MorphSetup.cpp | 41 +- .../Code/EMotionFX/Source/MorphSetup.h | 6 +- .../EMotionFX/Source/MorphSetupInstance.cpp | 5 +- .../EMotionFX/Source/MorphSetupInstance.h | 6 +- .../Code/EMotionFX/Source/MorphTarget.cpp | 7 +- .../Code/EMotionFX/Source/MorphTarget.h | 5 - .../EMotionFX/Source/MorphTargetStandard.cpp | 25 +- .../EMotionFX/Source/MorphTargetStandard.h | 6 +- .../Code/EMotionFX/Source/MotionGroup.cpp | 277 ------ .../Code/EMotionFX/Source/MotionInstance.cpp | 4 +- .../Code/EMotionFX/Source/MotionInstance.h | 2 +- .../EMotionFX/Source/MotionInstancePool.cpp | 64 +- .../EMotionFX/Source/MotionInstancePool.h | 6 +- .../EMotionFX/Source/MotionLayerSystem.cpp | 43 +- .../Code/EMotionFX/Source/MotionLayerSystem.h | 4 +- .../Code/EMotionFX/Source/MotionManager.cpp | 57 +- .../Code/EMotionFX/Source/MotionManager.h | 10 +- .../Code/EMotionFX/Source/MotionQueue.cpp | 15 +- .../Code/EMotionFX/Source/MotionQueue.h | 6 +- .../Code/EMotionFX/Source/MotionSystem.cpp | 50 +- .../Code/EMotionFX/Source/MotionSystem.h | 8 +- .../EMotionFX/Source/MultiThreadScheduler.cpp | 33 +- .../EMotionFX/Source/MultiThreadScheduler.h | 14 +- Gems/EMotionFX/Code/EMotionFX/Source/Node.cpp | 49 +- Gems/EMotionFX/Code/EMotionFX/Source/Node.h | 12 +- .../Code/EMotionFX/Source/NodeMap.cpp | 28 +- .../EMotionFX/Code/EMotionFX/Source/NodeMap.h | 6 +- .../Code/EMotionFX/Source/Recorder.cpp | 121 ++- .../Code/EMotionFX/Source/Recorder.h | 109 +-- .../Source/RepositioningLayerPass.cpp | 1 - .../EMotionFX/Source/RepositioningLayerPass.h | 4 +- .../Code/EMotionFX/Source/Skeleton.cpp | 34 +- .../Code/EMotionFX/Source/Skeleton.h | 10 +- .../EMotionFX/Source/StandardMaterial.cpp | 31 +- .../Code/EMotionFX/Source/StandardMaterial.h | 4 +- .../Code/EMotionFX/Source/SubMesh.cpp | 19 +- .../EMotionFX/Code/EMotionFX/Source/SubMesh.h | 12 +- .../Code/EMotionFX/Source/ThreadData.h | 2 +- .../EMStudioSDK/Source/EMStudioManager.cpp | 9 +- .../EMStudioSDK/Source/EMStudioManager.h | 4 +- .../EMStudioSDK/Source/FileManager.h | 2 +- .../EMStudioSDK/Source/MainWindow.cpp | 15 +- .../EMStudioSDK/Source/MainWindow.h | 6 +- .../Source/NodeHierarchyWidget.cpp | 37 +- .../EMStudioSDK/Source/NodeHierarchyWidget.h | 11 +- .../Source/NodeSelectionWindow.cpp | 4 +- .../EMStudioSDK/Source/NodeSelectionWindow.h | 6 +- .../Source/NotificationWindowManager.cpp | 19 +- .../Source/NotificationWindowManager.h | 8 +- .../Source/RenderPlugin/RenderPlugin.cpp | 55 +- .../Source/RenderPlugin/RenderPlugin.h | 6 +- .../RenderPlugin/RenderUpdateCallback.cpp | 10 +- .../Source/RenderPlugin/RenderWidget.cpp | 22 +- .../Source/RenderPlugin/RenderWidget.h | 8 +- .../Source/AnimGraph/AnimGraphPlugin.cpp | 6 +- .../Source/AnimGraph/AnimGraphPlugin.h | 2 +- .../AnimGraph/BlendGraphWidgetCallback.cpp | 409 --------- .../AnimGraph/BlendGraphWidgetCallback.h | 53 -- .../AnimGraph/BlendNodeSelectionWindow.h | 2 +- .../Source/AnimGraph/BlendTreeVisualNode.cpp | 13 +- .../Source/AnimGraph/GameControllerWindow.cpp | 24 +- .../Source/AnimGraph/GameControllerWindow.h | 8 +- .../Source/AnimGraph/GraphNode.cpp | 64 +- .../Source/AnimGraph/GraphNode.h | 23 +- .../Source/AnimGraph/NodeGraph.cpp | 26 +- .../Source/AnimGraph/NodeGroupWindow.cpp | 43 +- .../Source/AnimGraph/NodeGroupWindow.h | 11 +- .../AnimGraph/ParameterSelectionWindow.h | 2 +- .../Source/AnimGraph/StateGraphNode.cpp | 5 +- .../Attachments/AttachmentNodesWindow.cpp | 10 +- .../Attachments/AttachmentNodesWindow.h | 2 +- .../Source/Attachments/AttachmentsWindow.cpp | 6 +- .../Source/Attachments/AttachmentsWindow.h | 2 +- .../Source/LogWindow/LogWindowCallback.cpp | 13 +- .../MotionSetManagementWindow.cpp | 4 +- .../MotionSetManagementWindow.h | 2 +- .../MotionWindow/MotionExtractionWindow.cpp | 4 +- .../MotionWindow/MotionExtractionWindow.h | 2 +- .../Source/NodeGroups/NodeGroupWidget.cpp | 20 +- .../Source/NodeGroups/NodeGroupWidget.h | 2 +- .../Source/NodeWindow/NodeWindowPlugin.cpp | 4 +- .../SceneManager/ActorPropertiesWindow.cpp | 24 - .../SceneManager/ActorPropertiesWindow.h | 1 - .../Source/SceneManager/MirrorSetupWindow.cpp | 2 +- .../Source/SceneManager/MirrorSetupWindow.h | 4 +- .../Source/TimeView/TimeViewPlugin.cpp | 54 +- .../Source/TimeView/TimeViewPlugin.h | 14 +- .../Source/TimeView/TrackDataHeaderWidget.h | 2 +- .../Source/TimeView/TrackDataWidget.cpp | 52 +- .../Source/TimeView/TrackDataWidget.h | 6 +- .../Source/TimeView/TrackHeaderWidget.cpp | 2 +- Gems/EMotionFX/Code/MCore/Source/Array.h | 799 ------------------ Gems/EMotionFX/Code/MCore/Source/Config.h | 19 +- Gems/EMotionFX/Code/MCore/Source/HashTable.h | 239 ------ .../EMotionFX/Code/MCore/Source/HashTable.inl | 338 -------- .../Code/MCore/Source/LogManager.cpp | 68 +- Gems/EMotionFX/Code/MCore/Source/LogManager.h | 12 +- .../Code/MCore/Source/MCoreCommandManager.h | 2 +- Gems/EMotionFX/Code/MCore/mcore_files.cmake | 3 - .../Code/MysticQt/Source/DialogStack.cpp | 126 ++- .../Code/MysticQt/Source/DialogStack.h | 33 +- .../Code/MysticQt/Source/MysticQtManager.cpp | 16 +- .../Code/MysticQt/Source/MysticQtManager.h | 4 +- .../Platform/Windows/platform_windows.cmake | 4 + .../Source/Editor/ActorJointBrowseEdit.cpp | 18 - .../Code/Source/Editor/ActorJointBrowseEdit.h | 3 - .../PropertyWidgets/ActorGoalNodeHandler.cpp | 10 +- .../Code/Source/Editor/SkeletonModel.cpp | 4 +- .../Tests/AnimGraphParameterCommandsTests.cpp | 1 - .../Code/Tests/BoolLogicNodeTests.cpp | 2 +- Gems/EMotionFX/Code/Tests/Mocks/AnimGraph.h | 2 +- .../Code/Tests/Mocks/AnimGraphInstance.h | 2 +- Gems/EMotionFX/Code/Tests/Mocks/Node.h | 2 +- .../EMotionFX/Code/Tests/SkeletalLODTests.cpp | 4 +- .../Code/Tests/UI/LODSkinnedMeshTests.cpp | 1 - .../Vector2ToVector3CompatibilityTests.cpp | 2 +- 189 files changed, 1489 insertions(+), 3798 deletions(-) delete mode 100644 Gems/EMotionFX/Code/EMotionFX/Source/MotionGroup.cpp delete mode 100644 Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendGraphWidgetCallback.cpp delete mode 100644 Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendGraphWidgetCallback.h delete mode 100644 Gems/EMotionFX/Code/MCore/Source/Array.h delete mode 100644 Gems/EMotionFX/Code/MCore/Source/HashTable.h delete mode 100644 Gems/EMotionFX/Code/MCore/Source/HashTable.inl diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ActorCommands.h b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ActorCommands.h index 75d92d5f27..eec9f7a5c5 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ActorCommands.h +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ActorCommands.h @@ -25,7 +25,7 @@ namespace CommandSystem AZStd::string mOldAttachmentNodes; AZStd::string mOldExcludedFromBoundsNodes; AZStd::string mOldName; - MCore::Array mOldMirrorSetup; + AZStd::vector mOldMirrorSetup; bool mOldDirtyFlag; void SetIsAttachmentNode(EMotionFX::Actor* actor, bool isAttachmentNode); diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphNodeCommands.cpp b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphNodeCommands.cpp index fe41312701..ed871fc03f 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphNodeCommands.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphNodeCommands.cpp @@ -1204,10 +1204,10 @@ namespace CommandSystem if (parentNode) { // Gather the number of nodes with the same type as the one we're trying to remove. - MCore::Array outNodes; + AZStd::vector outNodes; const AZ::TypeId nodeType = azrtti_typeid(node); parentNode->CollectChildNodesOfType(nodeType, &outNodes); - const uint32 numTypeNodes = outNodes.GetLength(); + const uint32 numTypeNodes = outNodes.size(); // Gather the number of already removed nodes with the same type as the one we're trying to remove. const size_t numTotalDeletedNodes = nodeList.size(); diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphParameterCommands.cpp b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphParameterCommands.cpp index 41a6a26b89..38a545465b 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphParameterCommands.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphParameterCommands.cpp @@ -865,7 +865,7 @@ namespace CommandSystem parameter->GetName().c_str(), parameterContents.c_str()); - if (insertAtIndex != MCORE_INVALIDINDEX32) + if (insertAtIndex != InvalidIndex32) { outResult += AZStd::string::format(" -index \"%i\"", insertAtIndex); } diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphParameterCommands.h b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphParameterCommands.h index b70e8d24d2..8b55130677 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphParameterCommands.h +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphParameterCommands.h @@ -81,6 +81,6 @@ namespace CommandSystem COMMANDSYSTEM_API void ClearParametersCommand(EMotionFX::AnimGraph* animGraph, MCore::CommandGroup* commandGroup = nullptr); // Construct the create parameter command string using the the given information. - COMMANDSYSTEM_API void ConstructCreateParameterCommand(AZStd::string& outResult, EMotionFX::AnimGraph* animGraph, const EMotionFX::Parameter* parameter, uint32 insertAtIndex = MCORE_INVALIDINDEX32); + COMMANDSYSTEM_API void ConstructCreateParameterCommand(AZStd::string& outResult, EMotionFX::AnimGraph* animGraph, const EMotionFX::Parameter* parameter, uint32 insertAtIndex = InvalidIndex32); } // namespace CommandSystem diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MotionEventCommands.cpp b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MotionEventCommands.cpp index 8ee207713c..76ba6f37b7 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MotionEventCommands.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MotionEventCommands.cpp @@ -1178,7 +1178,7 @@ namespace CommandSystem // remove motion event - void CommandHelperRemoveMotionEvents(uint32 motionID, const char* trackName, const MCore::Array& eventNumbers, MCore::CommandGroup* commandGroup) + void CommandHelperRemoveMotionEvents(uint32 motionID, const char* trackName, const AZStd::vector& eventNumbers, MCore::CommandGroup* commandGroup) { // find the motion by id EMotionFX::Motion* motion = EMotionFX::GetMotionManager().FindMotionByID(motionID); @@ -1191,7 +1191,7 @@ namespace CommandSystem MCore::CommandGroup internalCommandGroup("Remove motion events"); // get the number of events to remove and iterate through them - const int32 numEvents = eventNumbers.GetLength(); + const int32 numEvents = eventNumbers.size(); for (int32 i = 0; i < numEvents; ++i) { // remove the events from back to front @@ -1221,7 +1221,7 @@ namespace CommandSystem // remove motion event - void CommandHelperRemoveMotionEvents(const char* trackName, const MCore::Array& eventNumbers, MCore::CommandGroup* commandGroup) + void CommandHelperRemoveMotionEvents(const char* trackName, const AZStd::vector& eventNumbers, MCore::CommandGroup* commandGroup) { EMotionFX::Motion* motion = GetCommandManager()->GetCurrentSelection().GetSingleMotion(); if (motion == nullptr) diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MotionEventCommands.h b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MotionEventCommands.h index 30caae2713..269a0322c0 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MotionEventCommands.h +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MotionEventCommands.h @@ -222,6 +222,6 @@ namespace CommandSystem void COMMANDSYSTEM_API CommandHelperAddMotionEvent(const char* trackName, float startTime, float endTime, const EMotionFX::EventDataSet& eventDatas = EMotionFX::EventDataSet {}, MCore::CommandGroup* commandGroup = nullptr); void COMMANDSYSTEM_API CommandHelperRemoveMotionEvent(const char* trackName, uint32 eventNr, MCore::CommandGroup* commandGroup = nullptr); void COMMANDSYSTEM_API CommandHelperRemoveMotionEvent(uint32 motionID, const char* trackName, uint32 eventNr, MCore::CommandGroup* commandGroup = nullptr); - void COMMANDSYSTEM_API CommandHelperRemoveMotionEvents(const char* trackName, const MCore::Array& eventNumbers, MCore::CommandGroup* commandGroup = nullptr); + void COMMANDSYSTEM_API CommandHelperRemoveMotionEvents(const char* trackName, const AZStd::vector& eventNumbers, MCore::CommandGroup* commandGroup = nullptr); void COMMANDSYSTEM_API CommandHelperMotionEventTrackChanged(uint32 eventNr, float startTime, float endTime, const char* oldTrackName, const char* newTrackName); } // namespace CommandSystem diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/SelectionCommands.cpp b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/SelectionCommands.cpp index 7f0fcfa9d0..f6d03d2983 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/SelectionCommands.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/SelectionCommands.cpp @@ -33,10 +33,10 @@ namespace CommandSystem : MCore::Command(s_toggleLockSelectionCmdName, orgCommand) { } - void SelectActorInstancesUsingCommands(const MCore::Array& selectedActorInstances) + void SelectActorInstancesUsingCommands(const AZStd::vector& selectedActorInstances) { SelectionList& selection = GetCommandManager()->GetCurrentSelection(); - const uint32 numSelectedActorInstances = selectedActorInstances.GetLength(); + const uint32 numSelectedActorInstances = selectedActorInstances.size(); // check if the current selection is equal to the desired actor instances selection list bool nothingChanged = true; @@ -52,7 +52,7 @@ namespace CommandSystem for (uint32 i = 0; i < selection.GetNumSelectedActorInstances(); ++i) { EMotionFX::ActorInstance* actorInstance = selection.GetActorInstance(i); - if (selectedActorInstances.Find(actorInstance) == MCORE_INVALIDINDEX32) + if (AZStd::find(begin(selectedActorInstances), end(selectedActorInstances), actorInstance) == end(selectedActorInstances)) { nothingChanged = false; break; diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/SelectionCommands.h b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/SelectionCommands.h index d48bc3d3b6..0c1fad6588 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/SelectionCommands.h +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/SelectionCommands.h @@ -44,7 +44,7 @@ public: MCORE_DEFINECOMMAND_1_END // helper functions - void COMMANDSYSTEM_API SelectActorInstancesUsingCommands(const MCore::Array& selectedActorInstances); + void COMMANDSYSTEM_API SelectActorInstancesUsingCommands(const AZStd::vector& selectedActorInstances); bool COMMANDSYSTEM_API CheckIfHasMotionSelectionParameter(const MCore::CommandLine& parameters); bool COMMANDSYSTEM_API CheckIfHasAnimGraphSelectionParameter(const MCore::CommandLine& parameters); bool COMMANDSYSTEM_API CheckIfHasActorSelectionParameter(const MCore::CommandLine& parameters, bool ignoreInstanceParameters = false); diff --git a/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/Exporter.h b/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/Exporter.h index e302f3ffe2..09c0646509 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/Exporter.h +++ b/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/Exporter.h @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include @@ -100,9 +99,9 @@ namespace ExporterLib // nodes void SaveNodes(MCore::Stream* file, EMotionFX::Actor* actor, MCore::Endian::EEndianType targetEndianType); void SaveNodeGroup(MCore::Stream* file, EMotionFX::NodeGroup* nodeGroup, MCore::Endian::EEndianType targetEndianType); - void SaveNodeGroups(MCore::Stream* file, const MCore::Array& nodeGroups, MCore::Endian::EEndianType targetEndianType); + void SaveNodeGroups(MCore::Stream* file, const AZStd::vector& nodeGroups, MCore::Endian::EEndianType targetEndianType); void SaveNodeGroups(MCore::Stream* file, EMotionFX::Actor* actor, MCore::Endian::EEndianType targetEndianType); - void SaveNodeMotionSources(MCore::Stream* file, EMotionFX::Actor* actor, MCore::Array* mirrorInfo, MCore::Endian::EEndianType targetEndianType); + void SaveNodeMotionSources(MCore::Stream* file, EMotionFX::Actor* actor, AZStd::vector* mirrorInfo, MCore::Endian::EEndianType targetEndianType); void SaveAttachmentNodes(MCore::Stream* file, EMotionFX::Actor* actor, MCore::Endian::EEndianType targetEndianType); void SaveAttachmentNodes(MCore::Stream* file, EMotionFX::Actor* actor, const AZStd::vector& attachmentNodes, MCore::Endian::EEndianType targetEndianType); diff --git a/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/MaterialExport.cpp b/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/MaterialExport.cpp index 4adee9af84..8bd005af6c 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/MaterialExport.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/MaterialExport.cpp @@ -199,10 +199,10 @@ namespace ExporterLib // save the given materials - void SaveMaterials(MCore::Stream* file, MCore::Array& materials, uint32 lodLevel, MCore::Endian::EEndianType targetEndianType) + void SaveMaterials(MCore::Stream* file, AZStd::vector& materials, uint32 lodLevel, MCore::Endian::EEndianType targetEndianType) { // get the number of materials - const uint32 numMaterials = materials.GetLength(); + const uint32 numMaterials = materials.size(); // chunk header EMotionFX::FileFormat::FileChunk chunkHeader; @@ -269,15 +269,15 @@ namespace ExporterLib const uint32 numMaterials = actor->GetNumMaterials(lodLevel); // create our materials array and reserve some elements - MCore::Array materials; - materials.Reserve(numMaterials); + AZStd::vector materials; + materials.reserve(numMaterials); // iterate through the materials for (uint32 j = 0; j < numMaterials; j++) { // get the base material EMotionFX::Material* baseMaterial = actor->GetMaterial(lodLevel, j); - materials.Add(baseMaterial); + materials.emplace_back(baseMaterial); } // save the materials diff --git a/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/NodeExport.cpp b/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/NodeExport.cpp index 79861be4b8..80efb54606 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/NodeExport.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/NodeExport.cpp @@ -227,13 +227,13 @@ namespace ExporterLib } - void SaveNodeGroups(MCore::Stream* file, const MCore::Array& nodeGroups, MCore::Endian::EEndianType targetEndianType) + void SaveNodeGroups(MCore::Stream* file, const AZStd::vector& nodeGroups, MCore::Endian::EEndianType targetEndianType) { uint32 i; MCORE_ASSERT(file); // get the number of node groups - const uint32 numGroups = nodeGroups.GetLength(); + const uint32 numGroups = nodeGroups.size(); if (numGroups == 0) { @@ -286,13 +286,13 @@ namespace ExporterLib const uint32 numGroups = actor->GetNumNodeGroups(); // create the node group array and reserve some elements - MCore::Array nodeGroups; - nodeGroups.Reserve(numGroups); + AZStd::vector nodeGroups; + nodeGroups.reserve(numGroups); // iterate through the node groups and add them to the array for (uint32 i = 0; i < numGroups; ++i) { - nodeGroups.Add(actor->GetNodeGroup(i)); + nodeGroups.emplace_back(actor->GetNodeGroup(i)); } // save the node groups @@ -300,7 +300,7 @@ namespace ExporterLib } - void SaveNodeMotionSources(MCore::Stream* file, EMotionFX::Actor* actor, MCore::Array* nodeMirrorInfos, MCore::Endian::EEndianType targetEndianType) + void SaveNodeMotionSources(MCore::Stream* file, EMotionFX::Actor* actor, AZStd::vector* nodeMirrorInfos, MCore::Endian::EEndianType targetEndianType) { MCORE_ASSERT(file); @@ -311,7 +311,7 @@ namespace ExporterLib MCORE_ASSERT(nodeMirrorInfos); - const uint32 numNodes = nodeMirrorInfos->GetLength(); + const uint32 numNodes = nodeMirrorInfos->size(); // chunk information EMotionFX::FileFormat::FileChunk chunkHeader; @@ -342,7 +342,7 @@ namespace ExporterLib for (uint32 i = 0; i < numNodes; ++i) { // get the motion node source - uint16 nodeMotionSource = nodeMirrorInfos->GetItem(i).mSourceNode; + uint16 nodeMotionSource = nodeMirrorInfos->at(i).mSourceNode; //if (actor && nodeMotionSource != MCORE_INVALIDINDEX16) //LogInfo(" + '%s' (NodeNr=%i) -> '%s' (NodeNr=%i)", actor->GetNode( i )->GetName(), i, actor->GetNode( nodeMotionSource )->GetName(), nodeMotionSource); @@ -355,14 +355,14 @@ namespace ExporterLib // write all axes for (uint32 i = 0; i < numNodes; ++i) { - uint8 axis = static_cast(nodeMirrorInfos->GetItem(i).mAxis); + uint8 axis = static_cast(nodeMirrorInfos->at(i).mAxis); file->Write(&axis, sizeof(uint8)); } // write all flags for (uint32 i = 0; i < numNodes; ++i) { - uint8 flags = static_cast(nodeMirrorInfos->GetItem(i).mFlags); + uint8 flags = static_cast(nodeMirrorInfos->at(i).mFlags); file->Write(&flags, sizeof(uint8)); } } @@ -430,7 +430,7 @@ namespace ExporterLib MCore::LogInfo("============================================================"); // get all nodes that are affected by the skin - MCore::Array bones; + AZStd::vector bones; if (actor) { actor->ExtractBoneList(0, &bones); @@ -455,7 +455,7 @@ namespace ExporterLib } // is the attachment node a skinned one? - if (bones.Find(node->GetNodeIndex()) != MCORE_INVALIDINDEX32) + if (AZStd::find(begin(bones), end(bones), node->GetNodeIndex()) != end(bones)) { MCore::LogWarning("Attachment node '%s' (NodeNr=%i) is used by a skin. Skinning will look incorrectly when using motion mirroring.", node->GetName(), nodeNr); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RenderUtil.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RenderUtil.cpp index 9c0a4af895..e17fffbdb5 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RenderUtil.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RenderUtil.cpp @@ -51,8 +51,6 @@ namespace MCommon mArrowHeadMesh = CreateArrowHead(1.0f, 0.5f); mUnitCubeMesh = CreateCube(1.0f); mFont = new VectorFont(this); - - mTriangleVertices.SetMemoryCategory(MEMCATEGORY_MCOMMON); } @@ -106,14 +104,14 @@ namespace MCommon void RenderUtil::RenderTriangles() { // check if we have to render anything and skip directly in case there are no triangles - if (mTriangleVertices.GetIsEmpty()) + if (mTriangleVertices.empty()) { return; } // render the triangles and clear the array RenderTriangles(mTriangleVertices); - mTriangleVertices.Clear(false); + mTriangleVertices.clear(); } @@ -655,7 +653,7 @@ namespace MCommon // render the advanced skeleton - void RenderUtil::RenderSkeleton(EMotionFX::ActorInstance* actorInstance, const MCore::Array& boneList, const AZStd::unordered_set* visibleJointIndices, const AZStd::unordered_set* selectedJointIndices, const MCore::RGBAColor& color, const MCore::RGBAColor& selectedColor) + void RenderUtil::RenderSkeleton(EMotionFX::ActorInstance* actorInstance, const AZStd::vector& boneList, const AZStd::unordered_set* visibleJointIndices, const AZStd::unordered_set* selectedJointIndices, const MCore::RGBAColor& color, const MCore::RGBAColor& selectedColor) { // check if our render util supports rendering meshes, if not render the fallback skeleton using lines only if (GetIsMeshRenderingSupported() == false) @@ -680,7 +678,7 @@ namespace MCommon const AZ::u32 parentIndex = joint->GetParentIndex(); // check if this node has a parent and is a bone, if not skip it - if (parentIndex == MCORE_INVALIDINDEX32 || boneList.Find(jointIndex) == MCORE_INVALIDINDEX32) + if (parentIndex == MCORE_INVALIDINDEX32 || AZStd::find(begin(boneList), end(boneList), jointIndex) == end(boneList)) { continue; } @@ -717,7 +715,7 @@ namespace MCommon // render node orientations - void RenderUtil::RenderNodeOrientations(EMotionFX::ActorInstance* actorInstance, const MCore::Array& boneList, const AZStd::unordered_set* visibleJointIndices, const AZStd::unordered_set* selectedJointIndices, float scale, bool scaleBonesOnLength) + void RenderUtil::RenderNodeOrientations(EMotionFX::ActorInstance* actorInstance, const AZStd::vector& boneList, const AZStd::unordered_set* visibleJointIndices, const AZStd::unordered_set* selectedJointIndices, float scale, bool scaleBonesOnLength) { // get the actor and the transform data const float unitScale = 1.0f / (float)MCore::Distance::ConvertValue(1.0f, MCore::Distance::UNITTYPE_METERS, EMotionFX::GetEMotionFX().GetUnitType()); @@ -739,7 +737,7 @@ namespace MCommon (visibleJointIndices->find(jointIndex) != visibleJointIndices->end())) { // either scale the bones based on their length or use the normal size - if (scaleBonesOnLength && parentIndex != MCORE_INVALIDINDEX32 && boneList.Find(jointIndex) != MCORE_INVALIDINDEX32) + if (scaleBonesOnLength && parentIndex != MCORE_INVALIDINDEX32 && AZStd::find(begin(boneList), end(boneList), jointIndex) != end(boneList)) { static const float axisBoneScale = 50.0f; axisRenderingSettings.mSize = GetBoneScale(actorInstance, joint) * constPreScale * axisBoneScale; @@ -1711,9 +1709,9 @@ namespace MCommon } // fast access to the trajectory trace particles - const MCore::Array& traceParticles = trajectoryPath->mTraceParticles; - const int32 numTraceParticles = traceParticles.GetLength(); - if (traceParticles.GetIsEmpty()) + const AZStd::vector& traceParticles = trajectoryPath->mTraceParticles; + const int32 numTraceParticles = traceParticles.size(); + if (traceParticles.empty()) { return; } @@ -1858,7 +1856,7 @@ namespace MCommon } // remove all particles while keeping the data in memory - trajectoryPath->mTraceParticles.Clear(false); + trajectoryPath->mTraceParticles.clear(); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RenderUtil.h b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RenderUtil.h index f63d41e812..8fb8f524c4 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RenderUtil.h +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RenderUtil.h @@ -191,7 +191,7 @@ namespace MCommon * @param[in] color The desired skeleton color. * @param[in] selectedColor The color of the selected bones. */ - void RenderSkeleton(EMotionFX::ActorInstance* actorInstance, const MCore::Array& boneList, const AZStd::unordered_set* visibleJointIndices = nullptr, const AZStd::unordered_set* selectedJointIndices = nullptr, const MCore::RGBAColor& color = MCore::RGBAColor(1.0f, 0.0f, 0.0f, 1.0f), const MCore::RGBAColor& selectedColor = MCore::RGBAColor(1.0f, 0.647f, 0.0f)); + void RenderSkeleton(EMotionFX::ActorInstance* actorInstance, const AZStd::vector& boneList, const AZStd::unordered_set* visibleJointIndices = nullptr, const AZStd::unordered_set* selectedJointIndices = nullptr, const MCore::RGBAColor& color = MCore::RGBAColor(1.0f, 0.0f, 0.0f, 1.0f), const MCore::RGBAColor& selectedColor = MCore::RGBAColor(1.0f, 0.647f, 0.0f)); /** * Render node orientations. @@ -202,7 +202,7 @@ namespace MCommon * @param[in] scale The scaling value in units. Axes of normal nodes will use the scaling value as unit length, skinned bones will use the scaling value as multiplier. * @param[in] scaleBonesOnLength Automatically scales the bone orientations based on the bone length. This means finger node orientations will be rendered smaller than foot bones as the bone length is a lot smaller as well. */ - void RenderNodeOrientations(EMotionFX::ActorInstance* actorInstance, const MCore::Array& boneList, const AZStd::unordered_set* visibleJointIndices = nullptr, const AZStd::unordered_set* selectedJointIndices = nullptr, float scale = 1.0f, bool scaleBonesOnLength = true); + void RenderNodeOrientations(EMotionFX::ActorInstance* actorInstance, const AZStd::vector& boneList, const AZStd::unordered_set* visibleJointIndices = nullptr, const AZStd::unordered_set* selectedJointIndices = nullptr, float scale = 1.0f, bool scaleBonesOnLength = true); /** * Render the bind pose of the given actor. @@ -570,17 +570,17 @@ namespace MCommon MCORE_INLINE void AddTriangle(const AZ::Vector3& posA, const AZ::Vector3& posB, const AZ::Vector3& posC, const AZ::Vector3& normalA, const AZ::Vector3& normalB, const AZ::Vector3& normalC, uint32 color) { - mTriangleVertices.Add(TriangleVertex(posA, normalA, color)); - mTriangleVertices.Add(TriangleVertex(posB, normalB, color)); - mTriangleVertices.Add(TriangleVertex(posC, normalC, color)); + mTriangleVertices.emplace_back(TriangleVertex(posA, normalA, color)); + mTriangleVertices.emplace_back(TriangleVertex(posB, normalB, color)); + mTriangleVertices.emplace_back(TriangleVertex(posC, normalC, color)); - if (mTriangleVertices.GetLength() + 2 >= mNumMaxTriangleVertices) + if (mTriangleVertices.size() + 2 >= mNumMaxTriangleVertices) { RenderTriangles(); } } - virtual void RenderTriangles(const MCore::Array& triangleVertices) { MCORE_UNUSED(triangleVertices); } + virtual void RenderTriangles(const AZStd::vector& triangleVertices) { MCORE_UNUSED(triangleVertices); } void RenderTriangles(); //--------------------------------------------------------------------------------------------- @@ -609,13 +609,13 @@ namespace MCommon struct TrajectoryTracePath { - MCore::Array mTraceParticles; + AZStd::vector mTraceParticles; EMotionFX::ActorInstance* mActorInstance; float mTimePassed; TrajectoryTracePath() { - mTraceParticles.Reserve(250); + mTraceParticles.reserve(250); mTimePassed = 0.0f; mActorInstance = NULL; } @@ -812,7 +812,7 @@ namespace MCommon static uint32 mNumMaxMeshIndices; /**< The maximum capacity of the util mesh index buffer */ // helper variables for rendering triangles - MCore::Array mTriangleVertices; + AZStd::vector mTriangleVertices; static uint32 mNumMaxTriangleVertices; /**< The maximum capacity of the triangle vertex buffer */ }; } // namespace MCommon diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GBuffer.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GBuffer.cpp index c4091de594..3e2a25fe80 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GBuffer.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GBuffer.cpp @@ -10,7 +10,7 @@ #include #include -#include +#include #include "GBuffer.h" #include "RenderTexture.h" #include "GLSLShader.h" diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLActor.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLActor.cpp index d727300dd5..7a78b5749d 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLActor.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLActor.cpp @@ -27,15 +27,6 @@ namespace RenderGL mActor = nullptr; mEnableGPUSkinning = true; - mMaterials.SetMemoryCategory(MEMCATEGORY_RENDERING); - - mHomoMaterials.SetMemoryCategory(MEMCATEGORY_RENDERING); - - for (uint32 i = 0; i < 3; i++) - { - mIndexBuffers[i].SetMemoryCategory(MEMCATEGORY_RENDERING); - } - mSkyColor = MCore::RGBAColor(0.55f, 0.55f, 0.55f); mGroundColor = MCore::RGBAColor(0.117f, 0.015f, 0.07f); } @@ -71,14 +62,14 @@ namespace RenderGL for (uint32 a = 0; a < 3; ++a) { // get rid of the given vertex buffers - const uint32 numVertexBuffers = mVertexBuffers[a].GetLength(); + const uint32 numVertexBuffers = mVertexBuffers[a].size(); for (i = 0; i < numVertexBuffers; ++i) { delete mVertexBuffers[a][i]; } // get rid of the given index buffers - const uint32 numIndexBuffers = mIndexBuffers[a].GetLength(); + const uint32 numIndexBuffers = mIndexBuffers[a].size(); for (i = 0; i < numIndexBuffers; ++i) { delete mIndexBuffers[a][i]; @@ -86,10 +77,10 @@ namespace RenderGL } // delete all materials - const uint32 numLOD = mMaterials.GetLength(); + const uint32 numLOD = mMaterials.size(); for (uint32 l = 0; l < numLOD; l++) { - const uint32 numMaterials = mMaterials[l].GetLength(); + const uint32 numMaterials = mMaterials[l].size(); for (uint32 n = 0; n < numMaterials; n++) { delete mMaterials[l][n]->mMaterial; @@ -126,13 +117,13 @@ namespace RenderGL const uint32 numNodes = actor->GetNumNodes(); // set the pre-allocation amount for the number of materials - mMaterials.Resize(numGeometryLODLevels); + mMaterials.resize(numGeometryLODLevels); // resize the vertex and index buffers for (uint32 a = 0; a < 3; ++a) { - mVertexBuffers[a].Resize(numGeometryLODLevels); - mIndexBuffers[a].Resize(numGeometryLODLevels); + mVertexBuffers[a].resize(numGeometryLODLevels); + mIndexBuffers[a].resize(numGeometryLODLevels); mPrimitives[a].Resize(numGeometryLODLevels); // reset the vertex and index buffers @@ -143,7 +134,7 @@ namespace RenderGL } } - mHomoMaterials.Resize(numGeometryLODLevels); + mHomoMaterials.resize(numGeometryLODLevels); mDynamicNodes.Resize (numGeometryLODLevels); EMotionFX::Skeleton* skeleton = actor->GetSkeleton(); @@ -206,7 +197,7 @@ namespace RenderGL // add to material list MaterialPrimitives* materialPrims = mMaterials[lodLevel][newPrimitive.mMaterialIndex]; - materialPrims->mPrimitives[meshType].Add(newPrimitive); + materialPrims->mPrimitives[meshType].emplace_back(newPrimitive); totalNumIndices[meshType] += newPrimitive.mNumTriangles * 3; totalNumVerts[meshType] += subMesh->GetNumVertices(); @@ -373,7 +364,7 @@ namespace RenderGL { EMotionFX::Material* emfxMaterial = mActor->GetMaterial(lodLevel, m); Material* material = InitMaterial(emfxMaterial); - mMaterials[lodLevel].Add( new MaterialPrimitives(material) ); + mMaterials[lodLevel].emplace_back( new MaterialPrimitives(material) ); } } @@ -412,7 +403,7 @@ namespace RenderGL void GLActor::RenderMeshes(EMotionFX::ActorInstance* actorInstance, EMotionFX::Mesh::EMeshType meshType, uint32 renderFlags) { const uint32 lodLevel = actorInstance->GetLODLevel(); - const uint32 numMaterials = mMaterials[lodLevel].GetLength(); + const uint32 numMaterials = mMaterials[lodLevel].size(); if (numMaterials == 0) { @@ -437,7 +428,7 @@ namespace RenderGL for (uint32 n = 0; n < numMaterials; n++) { const MaterialPrimitives* materialPrims = mMaterials[lodLevel][n]; - const uint32 numPrimitives = materialPrims->mPrimitives[meshType].GetLength(); + const uint32 numPrimitives = materialPrims->mPrimitives[meshType].size(); if (numPrimitives == 0) { continue; diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLRenderUtil.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLRenderUtil.cpp index feb2cd22ee..2ef39bd7c5 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLRenderUtil.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLRenderUtil.cpp @@ -110,7 +110,6 @@ namespace RenderGL mTextures = new TextureEntry[mMaxNumTextures]; // text rendering - mTextEntries.SetMemoryCategory(MEMCATEGORY_RENDERING); } @@ -164,12 +163,12 @@ namespace RenderGL delete[] mTextures; // get rid of texture entries - const uint32 numTextEntries = mTextEntries.GetLength(); + const uint32 numTextEntries = mTextEntries.size(); for (uint32 i = 0; i < numTextEntries; ++i) { delete mTextEntries[i]; } - mTextEntries.Clear(); + mTextEntries.clear(); } @@ -481,10 +480,10 @@ namespace RenderGL } - void GLRenderUtil::RenderTriangles(const MCore::Array& triangleVertices) + void GLRenderUtil::RenderTriangles(const AZStd::vector& triangleVertices) { // check if there are any triangles to render, if not return directly - if (triangleVertices.GetIsEmpty()) + if (triangleVertices.empty()) { return; } @@ -492,7 +491,7 @@ namespace RenderGL glDisable(GL_CULL_FACE); // get the number of vertices to render - const uint32 numVertices = triangleVertices.GetLength(); + const uint32 numVertices = triangleVertices.size(); MCORE_ASSERT(numVertices <= mNumMaxTriangleVertices); // lock the vertex buffer @@ -552,7 +551,7 @@ namespace RenderGL textEntry->mFontSize = fontSize; textEntry->mCentered = centered; - mTextEntries.Add(textEntry); + mTextEntries.emplace_back(textEntry); } @@ -560,7 +559,7 @@ namespace RenderGL { static AZ::Debug::Timer timer; const float timeDelta = static_cast(timer.StampAndGetDeltaTimeInSeconds()); - for (uint32 i = 0; i < mTextEntries.GetLength(); ) + for (uint32 i = 0; i < mTextEntries.size(); ) { TextEntry* textEntry = mTextEntries[i]; RenderText(static_cast(textEntry->mX), static_cast(textEntry->mY), textEntry->mText.c_str(), textEntry->mColor, textEntry->mFontSize, textEntry->mCentered); @@ -569,7 +568,7 @@ namespace RenderGL if (textEntry->mLifeTime < 0.0f) { delete textEntry; - mTextEntries.Remove(i); + mTextEntries.erase(AZStd::next(begin(mTextEntries), i)); } else { diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLRenderUtil.h b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLRenderUtil.h index c8888bc527..672a8c524f 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLRenderUtil.h +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLRenderUtil.h @@ -54,7 +54,7 @@ namespace RenderGL // triangle rendering void RenderTriangle(const AZ::Vector3& v1, const AZ::Vector3& v2, const AZ::Vector3& v3, const MCore::RGBAColor& color) override; - void RenderTriangles(const MCore::Array& triangleVertices) override; + void RenderTriangles(const AZStd::vector& triangleVertices) override; // text rendering (do not use until really needed, needs to do runtime allocations) void RenderTextPeriod(uint32 x, uint32 y, const char* text, float lifeTime, const MCore::RGBAColor& color = MCore::RGBAColor(1.0f, 1.0f, 1.0f), float fontSize = 11.0f, bool centered = false); @@ -108,7 +108,7 @@ namespace RenderGL bool mCentered; }; - MCore::Array mTextEntries; + AZStd::vector mTextEntries; TextureEntry* mTextures; uint32 mNumTextures; uint32 mMaxNumTextures; diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLSLShader.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLSLShader.cpp index 02aad3aa04..451246a8e2 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLSLShader.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLSLShader.cpp @@ -36,16 +36,11 @@ namespace RenderGL mPixelShader = 0; mTextureUnit = 0; - mUniforms.SetMemoryCategory(MEMCATEGORY_RENDERING); - mAttributes.SetMemoryCategory(MEMCATEGORY_RENDERING); - mActivatedAttribs.SetMemoryCategory(MEMCATEGORY_RENDERING); - mActivatedTextures.SetMemoryCategory(MEMCATEGORY_RENDERING); - // pre-alloc data for uniforms and attributes - mUniforms.Reserve(10); - mAttributes.Reserve(10); - mActivatedAttribs.Reserve(10); - mActivatedTextures.Reserve(10); + mUniforms.reserve(10); + mAttributes.reserve(10); + mActivatedAttribs.reserve(10); + mActivatedTextures.reserve(10); } @@ -70,14 +65,14 @@ namespace RenderGL // Deactivate void GLSLShader::Deactivate() { - const uint32 numAttribs = mActivatedAttribs.GetLength(); + const uint32 numAttribs = mActivatedAttribs.size(); for (uint32 i = 0; i < numAttribs; ++i) { const uint32 index = mActivatedAttribs[i]; glDisableVertexAttribArray(mAttributes[index].mLocation); } - const uint32 numTextures = mActivatedTextures.GetLength(); + const uint32 numTextures = mActivatedTextures.size(); for (uint32 i = 0; i < numTextures; ++i) { const uint32 index = mActivatedTextures[i]; @@ -86,8 +81,8 @@ namespace RenderGL glBindTexture(GL_TEXTURE_2D, 0); } - mActivatedAttribs.Clear(false); - mActivatedTextures.Clear(false); + mActivatedAttribs.clear(); + mActivatedTextures.clear(); } bool GLSLShader::Validate() @@ -129,7 +124,7 @@ namespace RenderGL text = "#version 120\n"; // build define string - const uint32 numDefines = mDefines.GetLength(); + const uint32 numDefines = mDefines.size(); for (uint32 n = 0; n < numDefines; ++n) { text += AZStd::string::format("#define %s\n", mDefines[n].c_str()); @@ -180,10 +175,10 @@ namespace RenderGL AZStd::invoke(func, static_cast(this), object, logLen, &logWritten, text.data()); // if there are any defines, print that out too - if (mDefines.GetLength() > 0) + if (mDefines.size() > 0) { AZStd::string dStr; - const uint32 numDefines = mDefines.GetLength(); + const uint32 numDefines = mDefines.size(); for (uint32 n = 0; n < numDefines; ++n) { if (n < numDefines - 1) @@ -209,7 +204,7 @@ namespace RenderGL // Init - bool GLSLShader::Init(AZ::IO::PathView vertexFileName, AZ::IO::PathView pixelFileName, MCore::Array& defines) + bool GLSLShader::Init(AZ::IO::PathView vertexFileName, AZ::IO::PathView pixelFileName, AZStd::vector& defines) { initializeOpenGLFunctions(); /*const char* args[] = { "unroll all", @@ -276,9 +271,9 @@ namespace RenderGL // FindAttributeIndex - uint32 GLSLShader::FindAttributeIndex(const char* name) + size_t GLSLShader::FindAttributeIndex(const char* name) { - const uint32 numAttribs = mAttributes.GetLength(); + const uint32 numAttribs = mAttributes.size(); for (uint32 i = 0; i < numAttribs; ++i) { if (AzFramework::StringFunc::Equal(mAttributes[i].mName.c_str(), name, false /* no case */)) @@ -296,14 +291,14 @@ namespace RenderGL // the parameter wasn't cached, try to retrieve it const GLint loc = glGetAttribLocation(mProgram, name); - mAttributes.Add(ShaderParameter(name, loc, true)); + mAttributes.emplace_back(name, loc, true); if (loc < 0) { return MCORE_INVALIDINDEX32; } - return mAttributes.GetLength() - 1; + return mAttributes.size() - 1; } @@ -334,9 +329,9 @@ namespace RenderGL // FindUniformIndex - uint32 GLSLShader::FindUniformIndex(const char* name) + size_t GLSLShader::FindUniformIndex(const char* name) { - const uint32 numUniforms = mUniforms.GetLength(); + const uint32 numUniforms = mUniforms.size(); for (uint32 i = 0; i < numUniforms; ++i) { if (AzFramework::StringFunc::Equal(mUniforms[i].mName.c_str(), name, false /* no case */)) @@ -352,14 +347,14 @@ namespace RenderGL // the parameter wasn't cached, try to retrieve it const GLint loc = glGetUniformLocation(mProgram, name); - mUniforms.Add(ShaderParameter(name, loc, false)); + mUniforms.emplace_back(name, loc, false); if (loc < 0) { return MCORE_INVALIDINDEX32; } - return mUniforms.GetLength() - 1; + return mUniforms.size() - 1; } @@ -377,7 +372,7 @@ namespace RenderGL glEnableVertexAttribArray(param->mLocation); glVertexAttribPointer(param->mLocation, dim, type, GL_FALSE, stride, (GLvoid*)offset); - mActivatedAttribs.Add(index); + mActivatedAttribs.emplace_back(index); } @@ -532,7 +527,7 @@ namespace RenderGL glBindTexture(GL_TEXTURE_2D, texture->GetID()); glUniform1i(mUniforms[index].mLocation, mUniforms[index].mTextureUnit); - mActivatedTextures.Add(index); + mActivatedTextures.emplace_back(index); } @@ -563,7 +558,7 @@ namespace RenderGL glBindTexture(GL_TEXTURE_2D, textureID); glUniform1i(mUniforms[index].mLocation, mUniforms[index].mTextureUnit); - mActivatedTextures.Add(index); + mActivatedTextures.emplace_back(index); } @@ -571,7 +566,7 @@ namespace RenderGL bool GLSLShader::CheckIfIsDefined(const char* attributeName) { // get the number of defines and iterate through them - const uint32 numDefines = mDefines.GetLength(); + const uint32 numDefines = mDefines.size(); for (uint32 i = 0; i < numDefines; ++i) { // compare the given attribute with the current define and return if they are equal diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLSLShader.h b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLSLShader.h index 6a6854e29f..6eb77b69c2 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLSLShader.h +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLSLShader.h @@ -14,7 +14,7 @@ #include "Shader.h" // include OpenGL -#include +#include #include #include @@ -42,7 +42,7 @@ namespace RenderGL MCORE_INLINE unsigned int GetProgram() const { return mProgram; } bool CheckIfIsDefined(const char* attributeName); - bool Init(AZ::IO::PathView vertexFileName, AZ::IO::PathView pixelFileName, MCore::Array& defines); + bool Init(AZ::IO::PathView vertexFileName, AZ::IO::PathView pixelFileName, AZStd::vector& defines); void SetAttribute(const char* name, uint32 dim, uint32 type, uint32 stride, size_t offset) override; void SetUniform(const char* name, float value) override; @@ -73,8 +73,8 @@ namespace RenderGL bool mIsAttribute; }; - uint32 FindAttributeIndex(const char* name); - uint32 FindUniformIndex(const char* name); + size_t FindAttributeIndex(const char* name); + size_t FindUniformIndex(const char* name); ShaderParameter* FindAttribute(const char* name); ShaderParameter* FindUniform(const char* name); @@ -84,11 +84,11 @@ namespace RenderGL AZ::IO::Path mFileName; - MCore::Array mActivatedAttribs; - MCore::Array mActivatedTextures; - MCore::Array mUniforms; - MCore::Array mAttributes; - MCore::Array mDefines; + AZStd::vector mActivatedAttribs; + AZStd::vector mActivatedTextures; + AZStd::vector mUniforms; + AZStd::vector mAttributes; + AZStd::vector mDefines; unsigned int mVertexShader; unsigned int mPixelShader; diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GraphicsManager.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GraphicsManager.cpp index db03a694a8..78b5813770 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GraphicsManager.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GraphicsManager.cpp @@ -403,20 +403,20 @@ namespace RenderGL // LoadShader GLSLShader* GraphicsManager::LoadShader(AZ::IO::PathView vertexFileName, AZ::IO::PathView pixelFileName) { - MCore::Array defines; + AZStd::vector defines; return LoadShader(vertexFileName, pixelFileName, defines); } // LoadShader - GLSLShader* GraphicsManager::LoadShader(AZ::IO::PathView vertexFileName, AZ::IO::PathView pixelFileName, MCore::Array& defines) + GLSLShader* GraphicsManager::LoadShader(AZ::IO::PathView vertexFileName, AZ::IO::PathView pixelFileName, AZStd::vector& defines) { const AZ::IO::Path vertexPath {vertexFileName.empty() ? AZ::IO::Path{} : mShaderPath / vertexFileName}; const AZ::IO::Path pixelPath {pixelFileName.empty() ? AZ::IO::Path{} : mShaderPath / pixelFileName}; // construct the lookup string for the shader cache AZStd::string cacheLookupStr = vertexPath.Native() + pixelPath.Native(); - const uint32 numDefines = defines.GetLength(); + const uint32 numDefines = defines.size(); for (uint32 n = 0; n < numDefines; n++) { cacheLookupStr += AZStd::string::format("#%s", defines[n].c_str()); diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GraphicsManager.h b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GraphicsManager.h index 674d428382..e13e643938 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GraphicsManager.h +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GraphicsManager.h @@ -62,7 +62,7 @@ namespace RenderGL bool GetIsPostProcessingEnabled() const { return mPostProcessing; } PostProcessShader* LoadPostProcessShader(AZ::IO::PathView filename); GLSLShader* LoadShader(AZ::IO::PathView vertexFileName, AZ::IO::PathView pixelFileName); - GLSLShader* LoadShader(AZ::IO::PathView vertexFileName, AZ::IO::PathView pixelFileName, MCore::Array& defines); + GLSLShader* LoadShader(AZ::IO::PathView vertexFileName, AZ::IO::PathView pixelFileName, AZStd::vector& defines); MCORE_INLINE void SetGBuffer(GBuffer* gBuffer) { mGBuffer = gBuffer; } MCORE_INLINE GBuffer* GetGBuffer() { return mGBuffer; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/Material.h b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/Material.h index 1cebe2d87b..ed5ab18609 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/Material.h +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/Material.h @@ -40,7 +40,7 @@ namespace RenderGL uint32 mNumVertices; /**< The number of vertices in the primitive. */ uint32 mMaterialIndex; /**< The material index which is mapped to the primitive. */ - MCore::Array mBoneNodeIndices;/**< Mapping from local bones 0-50 to nodes. */ + AZStd::vector mBoneNodeIndices;/**< Mapping from local bones 0-50 to nodes. */ }; diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/PostProcessShader.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/PostProcessShader.cpp index 7492f3e845..84c369bcbc 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/PostProcessShader.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/PostProcessShader.cpp @@ -81,7 +81,7 @@ namespace RenderGL // Init bool PostProcessShader::Init(AZ::IO::PathView filename) { - MCore::Array defines; + AZStd::vector defines; return GLSLShader::Init(nullptr, filename, defines); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/ShaderCache.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/ShaderCache.cpp index 604ad4dcaf..26acd0e77d 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/ShaderCache.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/ShaderCache.cpp @@ -15,8 +15,7 @@ namespace RenderGL // constructor ShaderCache::ShaderCache() { - mEntries.SetMemoryCategory(MEMCATEGORY_RENDERING); - mEntries.Reserve(128); + mEntries.reserve(128); } @@ -31,7 +30,7 @@ namespace RenderGL void ShaderCache::Release() { // delete all shaders - const uint32 numEntries = mEntries.GetLength(); + const uint32 numEntries = mEntries.size(); for (uint32 i = 0; i < numEntries; ++i) { mEntries[i].mName.clear(); @@ -39,23 +38,21 @@ namespace RenderGL } // clear all entries - mEntries.Clear(); + mEntries.clear(); } // add the shader to the cache (assume there are no duplicate names) void ShaderCache::AddShader(AZStd::string_view filename, Shader* shader) { - mEntries.AddEmpty(); - mEntries.GetLast().mName = filename; - mEntries.GetLast().mShader = shader; + mEntries.emplace_back(Entry{filename, shader}); } // try to locate a shader based on its name Shader* ShaderCache::FindShader(AZStd::string_view filename) const { - const uint32 numEntries = mEntries.GetLength(); + const uint32 numEntries = mEntries.size(); for (uint32 i = 0; i < numEntries; ++i) { if (AzFramework::StringFunc::Equal(mEntries[i].mName, filename, false /* no case */)) // non-case-sensitive name compare @@ -72,7 +69,7 @@ namespace RenderGL // check if we have a given shader in the cache bool ShaderCache::CheckIfHasShader(Shader* shader) const { - const uint32 numEntries = mEntries.GetLength(); + const uint32 numEntries = mEntries.size(); for (uint32 i = 0; i < numEntries; ++i) { if (mEntries[i].mShader == shader) diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/StandardMaterial.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/StandardMaterial.cpp index a782cfcd42..46c7e5c13e 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/StandardMaterial.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/StandardMaterial.cpp @@ -28,8 +28,6 @@ namespace RenderGL mSpecularMap = GetGraphicsManager()->GetTextureCache()->GetWhiteTexture(); mNormalMap = GetGraphicsManager()->GetTextureCache()->GetDefaultNormalTexture(); - mShaders.SetMemoryCategory(MEMCATEGORY_RENDERING); - SetAttribute(LIGHTING, true); SetAttribute(SKINNING, false); SetAttribute(SHADOWS, false); @@ -266,7 +264,7 @@ namespace RenderGL const AZ::Matrix3x4* skinningMatrices = transformData->GetSkinningMatrices(); // multiple each transform by its inverse bind pose - const uint32 numBones = primitive->mBoneNodeIndices.GetLength(); + const uint32 numBones = primitive->mBoneNodeIndices.size(); for (uint32 i = 0; i < numBones; ++i) { const uint32 nodeNr = primitive->mBoneNodeIndices[i]; @@ -307,7 +305,7 @@ namespace RenderGL mActiveShader = nullptr; // get the number of shaders and iterate through them - const uint32 numShaders = mShaders.GetLength(); + const uint32 numShaders = mShaders.size(); for (uint32 i = 0; i < numShaders; ++i) { if (mShaders[i] == nullptr) @@ -351,18 +349,18 @@ namespace RenderGL // if this function gets called at runtime something is wrong, go bug hunting! // construct an array of string attributes - MCore::Array defines; + AZStd::vector defines; for (uint32 n = 0; n < NUM_ATTRIBUTES; ++n) { if (mAttributes[n]) { - defines.Add(AttributeToString((EAttribute)n)); + defines.emplace_back(AttributeToString((EAttribute)n)); } } // compile shader and add it to the list of shaders mActiveShader = GetGraphicsManager()->LoadShader("StandardMaterial_VS.glsl", "StandardMaterial_PS.glsl", defines); - mShaders.Add(mActiveShader); + mShaders.emplace_back(mActiveShader); } mAttributesUpdated = false; diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/StandardMaterial.h b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/StandardMaterial.h index 34386c7241..d9eb23b50a 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/StandardMaterial.h +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/StandardMaterial.h @@ -45,7 +45,7 @@ namespace RenderGL bool mAttributesUpdated; GLSLShader* mActiveShader; - MCore::Array mShaders; + AZStd::vector mShaders; AZ::Matrix4x4 mBoneMatrices[200]; EMotionFX::Material* mMaterial; diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/TextureCache.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/TextureCache.cpp index 4723d166a7..7ef5b49c67 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/TextureCache.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/TextureCache.cpp @@ -47,8 +47,7 @@ namespace RenderGL mWhiteTexture = nullptr; mDefaultNormalTexture = nullptr; - mEntries.SetMemoryCategory(MEMCATEGORY_RENDERING); - mEntries.Reserve(128); + mEntries.reserve(128); } @@ -74,14 +73,14 @@ namespace RenderGL void TextureCache::Release() { // delete all textures - const uint32 numEntries = mEntries.GetLength(); + const uint32 numEntries = mEntries.size(); for (uint32 i = 0; i < numEntries; ++i) { delete mEntries[i].mTexture; } // clear all entries - mEntries.Clear(); + mEntries.clear(); // delete the white texture delete mWhiteTexture; @@ -95,9 +94,7 @@ namespace RenderGL // add the texture to the cache (assume there are no duplicate names) void TextureCache::AddTexture(const char* filename, Texture* texture) { - mEntries.AddEmpty(); - mEntries.GetLast().mName = filename; - mEntries.GetLast().mTexture = texture; + mEntries.emplace_back(Entry{filename, texture}); } @@ -105,7 +102,7 @@ namespace RenderGL Texture* TextureCache::FindTexture(const char* filename) const { // get the number of entries and iterate through them - const uint32 numEntries = mEntries.GetLength(); + const uint32 numEntries = mEntries.size(); for (uint32 i = 0; i < numEntries; ++i) { if (AzFramework::StringFunc::Equal(mEntries[i].mName.c_str(), filename, false /* no case */)) // non-case-sensitive name compare @@ -123,7 +120,7 @@ namespace RenderGL bool TextureCache::CheckIfHasTexture(Texture* texture) const { // get the number of entries and iterate through them - const uint32 numEntries = mEntries.GetLength(); + const uint32 numEntries = mEntries.size(); for (uint32 i = 0; i < numEntries; ++i) { if (mEntries[i].mTexture == texture) @@ -139,13 +136,13 @@ namespace RenderGL // remove an item from the cache void TextureCache::RemoveTexture(Texture* texture) { - const uint32 numEntries = mEntries.GetLength(); + const uint32 numEntries = mEntries.size(); for (uint32 i = 0; i < numEntries; ++i) { if (mEntries[i].mTexture == texture) { delete mEntries[i].mTexture; - mEntries.Remove(i); + mEntries.erase(AZStd::next(begin(mEntries), i)); return; } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/TextureCache.h b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/TextureCache.h index bae46bd75b..43d0f1a635 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/TextureCache.h +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/TextureCache.h @@ -10,7 +10,7 @@ #define __RENDERGL_TEXTURECACHE_H #include -#include +#include #include "RenderGLConfig.h" #include @@ -72,7 +72,7 @@ namespace RenderGL Texture* mTexture; }; - MCore::Array mEntries; + AZStd::vector mEntries; Texture* mWhiteTexture; Texture* mDefaultNormalTexture; }; diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/glactor.h b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/glactor.h index ff20861c08..4de5d7198a 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/glactor.h +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/glactor.h @@ -61,10 +61,10 @@ namespace RenderGL struct RENDERGL_API MaterialPrimitives { Material* mMaterial; - MCore::Array mPrimitives[3]; + AZStd::vector mPrimitives[3]; - MaterialPrimitives() { mMaterial = nullptr; mPrimitives[0].Reserve(64); mPrimitives[1].Reserve(64); mPrimitives[2].Reserve(64); } - MaterialPrimitives(Material* mat) { mMaterial = mat; mPrimitives[0].Reserve(64); mPrimitives[1].Reserve(64); mPrimitives[2].Reserve(64); } + MaterialPrimitives() { mMaterial = nullptr; mPrimitives[0].reserve(64); mPrimitives[1].reserve(64); mPrimitives[2].reserve(64); } + MaterialPrimitives(Material* mat) { mMaterial = mat; mPrimitives[0].reserve(64); mPrimitives[1].reserve(64); mPrimitives[2].reserve(64); } }; AZStd::string mTexturePath; @@ -85,12 +85,12 @@ namespace RenderGL EMotionFX::Mesh::EMeshType ClassifyMeshType(EMotionFX::Node* node, EMotionFX::Mesh* mesh, uint32 lodLevel); - MCore::Array< MCore::Array > mMaterials; + AZStd::vector< AZStd::vector > mMaterials; MCore::Array2D mDynamicNodes; MCore::Array2D mPrimitives[3]; - MCore::Array mHomoMaterials; - MCore::Array mVertexBuffers[3]; - MCore::Array mIndexBuffers[3]; + AZStd::vector mHomoMaterials; + AZStd::vector mVertexBuffers[3]; + AZStd::vector mIndexBuffers[3]; MCore::RGBAColor mGroundColor; MCore::RGBAColor mSkyColor; diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/shadercache.h b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/shadercache.h index 25a91026f8..08bf9dfa58 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/shadercache.h +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/shadercache.h @@ -11,7 +11,7 @@ #include "Shader.h" #include -#include +#include namespace RenderGL @@ -42,7 +42,7 @@ namespace RenderGL }; // - MCore::Array mEntries; // the shader cache entries + AZStd::vector mEntries; // the shader cache entries }; } // namespace RenderGL diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp index 68b9d62e8e..541ab65071 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp @@ -49,14 +49,10 @@ namespace EMotionFX { AZ_CLASS_ALLOCATOR_IMPL(Actor, ActorAllocator, 0) - Actor::LODLevel::LODLevel() - { - } - Actor::MeshLODData::MeshLODData() { // Create the default LOD level - m_lodLevels.push_back({}); + m_lodLevels.emplace_back(); } Actor::NodeLODInfo::NodeLODInfo() @@ -77,11 +73,6 @@ namespace EMotionFX { SetName(name); - // setup the array memory categories - mMaterials.SetMemoryCategory(EMFX_MEMCATEGORY_ACTORS); - mDependencies.SetMemoryCategory(EMFX_MEMCATEGORY_ACTORS); - mMorphSetups.SetMemoryCategory(EMFX_MEMCATEGORY_ACTORS); - mSkeleton = Skeleton::Create(); mMotionExtractionNode = MCORE_INVALIDINDEX32; @@ -105,11 +96,10 @@ namespace EMotionFX #endif // EMFX_DEVELOPMENT_BUILD // make sure we have at least allocated the first LOD of materials and facial setups - mMaterials.Reserve(4); // reserve space for 4 lods - mMorphSetups.Reserve(4); // - mMaterials.AddEmpty(); - mMaterials[0].SetMemoryCategory(EMFX_MEMCATEGORY_ACTORS); - mMorphSetups.Add(nullptr); + mMaterials.reserve(4); // reserve space for 4 lods + mMorphSetups.reserve(4); // + mMaterials.emplace_back(); + mMorphSetups.emplace_back(nullptr); GetEventManager().OnCreateActor(this); ActorNotificationBus::Broadcast(&ActorNotificationBus::Events::OnActorCreated, this); @@ -120,7 +110,7 @@ namespace EMotionFX ActorNotificationBus::Broadcast(&ActorNotificationBus::Events::OnActorDestroyed, this); GetEventManager().OnDeleteActor(this); - mNodeMirrorInfos.Clear(true); + mNodeMirrorInfos.clear(); RemoveAllMaterials(); RemoveAllMorphSetups(); @@ -158,12 +148,12 @@ namespace EMotionFX } // clone the materials - result->mMaterials.Resize(mMaterials.GetLength()); - for (uint32 i = 0; i < mMaterials.GetLength(); ++i) + result->mMaterials.resize(mMaterials.size()); + for (uint32 i = 0; i < mMaterials.size(); ++i) { // get the number of materials in the current LOD - const uint32 numMaterials = mMaterials[i].GetLength(); - result->mMaterials[i].Reserve(numMaterials); + const uint32 numMaterials = mMaterials[i].size(); + result->mMaterials[i].reserve(numMaterials); for (uint32 m = 0; m < numMaterials; ++m) { // retrieve the current material @@ -190,10 +180,10 @@ namespace EMotionFX result->SetNumLODLevels(static_cast(numLodLevels)); for (size_t lodLevel = 0; lodLevel < numLodLevels; ++lodLevel) { - const MCore::Array& nodeInfos = m_meshLodData.m_lodLevels[lodLevel].mNodeInfos; - MCore::Array& resultNodeInfos = resultMeshLodData.m_lodLevels[lodLevel].mNodeInfos; + const AZStd::vector& nodeInfos = m_meshLodData.m_lodLevels[lodLevel].mNodeInfos; + AZStd::vector& resultNodeInfos = resultMeshLodData.m_lodLevels[lodLevel].mNodeInfos; - resultNodeInfos.Resize(numNodes); + resultNodeInfos.resize(numNodes); for (uint32 n = 0; n < numNodes; ++n) { NodeLODInfo& resultNodeInfo = resultNodeInfos[n]; @@ -204,8 +194,8 @@ namespace EMotionFX } // clone the morph setups - result->mMorphSetups.Resize(mMorphSetups.GetLength()); - for (uint32 i = 0; i < mMorphSetups.GetLength(); ++i) + result->mMorphSetups.resize(mMorphSetups.size()); + for (uint32 i = 0; i < mMorphSetups.size(); ++i) { if (mMorphSetups[i]) { @@ -241,7 +231,7 @@ namespace EMotionFX void Actor::AllocateNodeMirrorInfos() { const uint32 numNodes = mSkeleton->GetNumNodes(); - mNodeMirrorInfos.Resize(numNodes); + mNodeMirrorInfos.resize(numNodes); // init the data for (uint32 i = 0; i < numNodes; ++i) @@ -255,19 +245,20 @@ namespace EMotionFX // remove the node mirror info void Actor::RemoveNodeMirrorInfos() { - mNodeMirrorInfos.Clear(true); + mNodeMirrorInfos.clear(); + mNodeMirrorInfos.shrink_to_fit(); } // check if we have our axes detected bool Actor::GetHasMirrorAxesDetected() const { - if (mNodeMirrorInfos.GetLength() == 0) + if (mNodeMirrorInfos.size() == 0) { return false; } - for (uint32 i = 0; i < mNodeMirrorInfos.GetLength(); ++i) + for (uint32 i = 0; i < mNodeMirrorInfos.size(); ++i) { if (mNodeMirrorInfos[i].mAxis == MCORE_INVALIDINDEX8) { @@ -283,17 +274,17 @@ namespace EMotionFX void Actor::RemoveAllMaterials() { // for all LODs - for (uint32 i = 0; i < mMaterials.GetLength(); ++i) + for (uint32 i = 0; i < mMaterials.size(); ++i) { // delete all materials - const uint32 numMats = mMaterials[i].GetLength(); + const uint32 numMats = mMaterials[i].size(); for (uint32 m = 0; m < numMats; ++m) { mMaterials[i][m]->Destroy(); } } - mMaterials.Clear(); + mMaterials.clear(); } @@ -305,8 +296,7 @@ namespace EMotionFX lodLevels.emplace_back(); LODLevel& newLOD = lodLevels.back(); const uint32 numNodes = mSkeleton->GetNumNodes(); - newLOD.mNodeInfos.SetMemoryCategory(EMFX_MEMCATEGORY_ACTORS); - newLOD.mNodeInfos.Resize(numNodes); + newLOD.mNodeInfos.resize(numNodes); const size_t numLODs = lodLevels.size(); const size_t lodIndex = numLODs - 1; @@ -329,11 +319,10 @@ namespace EMotionFX } // create a new material array for the new LOD level - mMaterials.Resize(static_cast(lodLevels.size())); - mMaterials[static_cast(lodIndex)].SetMemoryCategory(EMFX_MEMCATEGORY_ACTORS); + mMaterials.resize(lodLevels.size()); // create an empty morph setup for the new LOD level - mMorphSetups.Add(nullptr); + mMorphSetups.emplace_back(nullptr); // copy data from the previous LOD level if wanted if (copyFromLastLODLevel && numLODs > 0) @@ -347,12 +336,11 @@ namespace EMotionFX { AZStd::vector& lodLevels = m_meshLodData.m_lodLevels; - lodLevels.insert(lodLevels.begin()+insertAt, {}); + lodLevels.emplace(lodLevels.begin()+insertAt); LODLevel& newLOD = lodLevels[insertAt]; const uint32 lodIndex = insertAt; const uint32 numNodes = mSkeleton->GetNumNodes(); - newLOD.mNodeInfos.SetMemoryCategory(EMFX_MEMCATEGORY_ACTORS); - newLOD.mNodeInfos.Resize(numNodes); + newLOD.mNodeInfos.resize(numNodes); // get the number of nodes, iterate through them, create a new LOD level and copy over the meshes from the last LOD level for (uint32 i = 0; i < numNodes; ++i) @@ -363,11 +351,10 @@ namespace EMotionFX } // create a new material array for the new LOD level - mMaterials.Insert(insertAt); - mMaterials[lodIndex].SetMemoryCategory(EMFX_MEMCATEGORY_ACTORS); + mMaterials.emplace(AZStd::next(begin(mMaterials), insertAt)); // create an empty morph setup for the new LOD level - mMorphSetups.Insert(insertAt, nullptr); + mMorphSetups.emplace(AZStd::next(begin(mMorphSetups), insertAt), nullptr); } // replace existing LOD level with the current actor @@ -424,12 +411,12 @@ namespace EMotionFX // copy the materials const uint32 numMaterials = copyActor->GetNumMaterials(copyLODLevel); - for (uint32 i = 0; i < mMaterials[replaceLODLevel].GetLength(); ++i) + for (uint32 i = 0; i < mMaterials[replaceLODLevel].size(); ++i) { mMaterials[replaceLODLevel][i]->Destroy(); } - mMaterials[replaceLODLevel].Clear(); - mMaterials[replaceLODLevel].Reserve(numMaterials); + mMaterials[replaceLODLevel].clear(); + mMaterials[replaceLODLevel].reserve(numMaterials); for (uint32 i = 0; i < numMaterials; ++i) { AddMaterial(replaceLODLevel, copyActor->GetMaterial(copyLODLevel, i)->Clone()); @@ -457,15 +444,11 @@ namespace EMotionFX m_meshLodData.m_lodLevels.resize(numLODs); // reserve space for the materials - mMaterials.Resize(numLODs); - for (uint32 i = 0; i < numLODs; ++i) - { - mMaterials[i].SetMemoryCategory(EMFX_MEMCATEGORY_ACTORS); - } + mMaterials.resize(numLODs); if (adjustMorphSetup) { - mMorphSetups.Resize(numLODs); + mMorphSetups.resize(numLODs); for (uint32 i = 0; i < numLODs; ++i) { mMorphSetups[i] = nullptr; @@ -639,7 +622,7 @@ namespace EMotionFX // verify if the skinning will look correctly in the given geometry LOD for a given skeletal LOD level - void Actor::VerifySkinning(MCore::Array& conflictNodeFlags, uint32 skeletalLODLevel, uint32 geometryLODLevel) + void Actor::VerifySkinning(AZStd::vector& conflictNodeFlags, uint32 skeletalLODLevel, uint32 geometryLODLevel) { uint32 n; @@ -647,13 +630,13 @@ namespace EMotionFX const uint32 numNodes = mSkeleton->GetNumNodes(); // check if the conflict node flag array's size is set to the number of nodes inside the actor - if (conflictNodeFlags.GetLength() != numNodes) + if (conflictNodeFlags.size() != numNodes) { - conflictNodeFlags.Resize(numNodes); + conflictNodeFlags.resize(numNodes); } // reset the conflict node array to zero which means we don't have any conflicting nodes yet - MCore::MemSet(conflictNodeFlags.GetPtr(), 0, numNodes * sizeof(int8)); + MCore::MemSet(conflictNodeFlags.data(), 0, numNodes * sizeof(int8)); // iterate over the all nodes in the actor for (n = 0; n < numNodes; ++n) @@ -791,7 +774,7 @@ namespace EMotionFX const uint32 numLODs = GetNumLODLevels(); // for all LODs, get rid of all the morph setups for each geometry LOD - for (i = 0; i < mMorphSetups.GetLength(); ++i) + for (i = 0; i < mMorphSetups.size(); ++i) { if (mMorphSetups[i]) { @@ -882,11 +865,11 @@ namespace EMotionFX // remove the given material and reassign all material numbers of the submeshes void Actor::RemoveMaterial(uint32 lodLevel, uint32 index) { - MCORE_ASSERT(lodLevel < mMaterials.GetLength()); + MCORE_ASSERT(lodLevel < mMaterials.size()); // first of all remove the given material mMaterials[lodLevel][index]->Destroy(); - mMaterials[lodLevel].Remove(index); + mMaterials[lodLevel].erase(AZStd::next(begin(mMaterials[lodLevel]), index)); } @@ -930,10 +913,10 @@ namespace EMotionFX // extract a bone list - void Actor::ExtractBoneList(uint32 lodLevel, MCore::Array* outBoneList) const + void Actor::ExtractBoneList(uint32 lodLevel, AZStd::vector* outBoneList) const { // clear the existing items - outBoneList->Clear(); + outBoneList->clear(); // for all nodes const uint32 numNodes = mSkeleton->GetNumNodes(); @@ -966,9 +949,9 @@ namespace EMotionFX uint32 nodeNr = skinningLayer->GetInfluence(v, i)->GetNodeNr(); // check if it is already in the bone list, if not, add it - if (outBoneList->Contains(nodeNr) == false) + if (AZStd::find(begin(*outBoneList), end(*outBoneList), nodeNr) == end(*outBoneList)) { - outBoneList->Add(nodeNr); + outBoneList->emplace_back(nodeNr); } } } @@ -984,7 +967,7 @@ namespace EMotionFX for (uint32 i = 0; i < numDependencies; ++i) { // add it to the actor instance - mDependencies.Add(*actor->GetDependency(i)); + mDependencies.emplace_back(*actor->GetDependency(i)); // recursive into the actor we are dependent on RecursiveAddDependencies(actor->GetDependency(i)->mActor); @@ -1083,7 +1066,7 @@ namespace EMotionFX } // allocate the data if we haven't already - if (mNodeMirrorInfos.GetLength() == 0) + if (mNodeMirrorInfos.size() == 0) { AllocateNodeMirrorInfos(); } @@ -1101,7 +1084,7 @@ namespace EMotionFX bool Actor::MapNodeMotionSource(uint16 sourceNodeIndex, uint16 targetNodeIndex) { // allocate the data if we haven't already - if (mNodeMirrorInfos.GetLength() == 0) + if (mNodeMirrorInfos.size() == 0) { AllocateNodeMirrorInfos(); } @@ -1267,17 +1250,17 @@ namespace EMotionFX // generate a path from the current node towards the root - void Actor::GenerateUpdatePathToRoot(uint32 endNodeIndex, MCore::Array& outPath) const + void Actor::GenerateUpdatePathToRoot(uint32 endNodeIndex, AZStd::vector& outPath) const { - outPath.Clear(false); - outPath.Reserve(32); + outPath.clear(); + outPath.reserve(32); // start at the end effector Node* currentNode = mSkeleton->GetNode(endNodeIndex); while (currentNode) { // add the current node to the update list - outPath.Add(currentNode->GetNodeIndex()); + outPath.emplace_back(currentNode->GetNodeIndex()); // move up the hierarchy, towards the root and end node currentNode = currentNode->GetParentNode(); @@ -1361,7 +1344,7 @@ namespace EMotionFX ReinitializeMeshDeformers(); // make sure our world space bind pose is updated too - if (mMorphSetups.GetLength() > 0 && mMorphSetups[0]) + if (mMorphSetups.size() > 0 && mMorphSetups[0]) { mSkeleton->GetBindPose()->ResizeNumMorphs(mMorphSetups[0]->GetNumMorphTargets()); } @@ -1594,7 +1577,7 @@ namespace EMotionFX Pose pose; pose.LinkToActor(this); - const uint32 numNodes = mNodeMirrorInfos.GetLength(); + const uint32 numNodes = mNodeMirrorInfos.size(); for (uint32 i = 0; i < numNodes; ++i) { const uint16 motionSource = (GetHasMirrorInfo()) ? GetNodeMirrorInfo(i).mSourceNode : static_cast(i); @@ -1723,21 +1706,21 @@ namespace EMotionFX // get the array of node mirror infos - const MCore::Array& Actor::GetNodeMirrorInfos() const + const AZStd::vector& Actor::GetNodeMirrorInfos() const { return mNodeMirrorInfos; } // get the array of node mirror infos - MCore::Array& Actor::GetNodeMirrorInfos() + AZStd::vector& Actor::GetNodeMirrorInfos() { return mNodeMirrorInfos; } // set the node mirror infos directly - void Actor::SetNodeMirrorInfos(const MCore::Array& mirrorInfos) + void Actor::SetNodeMirrorInfos(const AZStd::vector& mirrorInfos) { mNodeMirrorInfos = mirrorInfos; } @@ -1862,7 +1845,7 @@ namespace EMotionFX AZStd::vector& lodLevels = m_meshLodData.m_lodLevels; for (LODLevel& lodLevel : lodLevels) { - lodLevel.mNodeInfos.Resize(numNodes); + lodLevel.mNodeInfos.resize(numNodes); } Pose* bindPose = mSkeleton->GetBindPose(); @@ -1878,7 +1861,7 @@ namespace EMotionFX AZStd::vector& lodLevels = m_meshLodData.m_lodLevels; for (LODLevel& lodLevel : lodLevels) { - lodLevel.mNodeInfos.AddEmpty(); + lodLevel.mNodeInfos.emplace_back(); } mSkeleton->GetBindPose()->LinkToActor(this, Pose::FLAG_LOCALTRANSFORMREADY, false); @@ -1909,7 +1892,7 @@ namespace EMotionFX AZStd::vector& lodLevels = m_meshLodData.m_lodLevels; for (LODLevel& lodLevel : lodLevels) { - lodLevel.mNodeInfos.Remove(nr); + lodLevel.mNodeInfos.erase(AZStd::next(begin(lodLevel.mNodeInfos), nr)); } } @@ -1920,20 +1903,20 @@ namespace EMotionFX AZStd::vector& lodLevels = m_meshLodData.m_lodLevels; for (LODLevel& lodLevel : lodLevels) { - lodLevel.mNodeInfos.Clear(); + lodLevel.mNodeInfos.clear(); } } void Actor::ReserveMaterials(uint32 lodLevel, uint32 numMaterials) { - mMaterials[lodLevel].Reserve(numMaterials); + mMaterials[lodLevel].reserve(numMaterials); } // get a material Material* Actor::GetMaterial(uint32 lodLevel, uint32 nr) const { - MCORE_ASSERT(lodLevel < mMaterials.GetLength()); - MCORE_ASSERT(nr < mMaterials[lodLevel].GetLength()); + MCORE_ASSERT(lodLevel < mMaterials.size()); + MCORE_ASSERT(nr < mMaterials[lodLevel].size()); return mMaterials[lodLevel][nr]; } @@ -1941,10 +1924,10 @@ namespace EMotionFX // get a material by name uint32 Actor::FindMaterialIndexByName(uint32 lodLevel, const char* name) const { - MCORE_ASSERT(lodLevel < mMaterials.GetLength()); + MCORE_ASSERT(lodLevel < mMaterials.size()); // search through all materials - const uint32 numMaterials = mMaterials[lodLevel].GetLength(); + const uint32 numMaterials = mMaterials[lodLevel].size(); for (uint32 i = 0; i < numMaterials; ++i) { if (mMaterials[lodLevel][i]->GetNameString() == name) @@ -1960,27 +1943,26 @@ namespace EMotionFX // set a material void Actor::SetMaterial(uint32 lodLevel, uint32 nr, Material* mat) { - MCORE_ASSERT(lodLevel < mMaterials.GetLength()); - MCORE_ASSERT(nr < mMaterials[lodLevel].GetLength()); + MCORE_ASSERT(lodLevel < mMaterials.size()); + MCORE_ASSERT(nr < mMaterials[lodLevel].size()); mMaterials[lodLevel][nr] = mat; } void Actor::AddMaterial(uint32 lodLevel, Material* mat) { - MCORE_ASSERT(lodLevel < mMaterials.GetLength()); - mMaterials[lodLevel].Add(mat); + MCORE_ASSERT(lodLevel < mMaterials.size()); + mMaterials[lodLevel].emplace_back(mat); } - uint32 Actor::GetNumMaterials(uint32 lodLevel) const + size_t Actor::GetNumMaterials(uint32 lodLevel) const { - MCORE_ASSERT(lodLevel < mMaterials.GetLength()); - return mMaterials[lodLevel].GetLength(); + MCORE_ASSERT(lodLevel < mMaterials.size()); + return mMaterials[lodLevel].size(); } - uint32 Actor::GetNumLODLevels() const + size_t Actor::GetNumLODLevels() const { - const AZStd::vector& lodLevels = m_meshLodData.m_lodLevels; - return static_cast(lodLevels.size()); + return m_meshLodData.m_lodLevels.size(); } @@ -2022,7 +2004,7 @@ namespace EMotionFX void Actor::AddDependency(const Dependency& dependency) { - mDependencies.Add(dependency); + mDependencies.emplace_back(dependency); } @@ -2459,8 +2441,8 @@ namespace EMotionFX const AZ::u32 numSubMeshes = mesh->GetNumSubMeshes(); for (AZ::u32 subMeshIndex = 0; subMeshIndex < numSubMeshes; ++subMeshIndex) { - const MCore::Array& subMeshJoints = mesh->GetSubMesh(subMeshIndex)->GetBonesArray(); - const AZ::u32 numSubMeshJoints = subMeshJoints.GetLength(); + const AZStd::vector& subMeshJoints = mesh->GetSubMesh(subMeshIndex)->GetBonesArray(); + const AZ::u32 numSubMeshJoints = subMeshJoints.size(); for (AZ::u32 i = 0; i < numSubMeshJoints; ++i) { InsertJointAndParents(subMeshJoints[i], includedJointIndices); @@ -2678,13 +2660,13 @@ namespace EMotionFX // Remove all the materials and add them back based on the meshAsset. Eventually we will remove all the material from Actor and // GLActor. RemoveAllMaterials(); - mMaterials.Resize(static_cast(numLODLevels)); + mMaterials.resize(numLODLevels); for (size_t lodLevel = 0; lodLevel < numLODLevels; ++lodLevel) { const AZ::Data::Asset& lodAsset = lodAssets[lodLevel]; - lodLevels[lodLevel].mNodeInfos.Resize(numNodes); + lodLevels[lodLevel].mNodeInfos.resize(numNodes); // Create a single mesh for the actor. Mesh* mesh = Mesh::CreateFromModelLod(lodAsset, m_skinToSkeletonIndexMap); @@ -2798,7 +2780,7 @@ namespace EMotionFX const AZStd::array_view>& lodAssets = m_meshAsset->GetLodAssets(); const size_t numLODLevels = lodAssets.size(); - AZ_Assert(mMorphSetups.GetLength() == numLODLevels, "There needs to be a morph setup for every single LOD level."); + AZ_Assert(mMorphSetups.size() == numLODLevels, "There needs to be a morph setup for every single LOD level."); for (size_t lodLevel = 0; lodLevel < numLODLevels; ++lodLevel) { diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Actor.h b/Gems/EMotionFX/Code/EMotionFX/Source/Actor.h index faf5b6b94d..0894d22c4c 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Actor.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Actor.h @@ -22,7 +22,7 @@ // include MCore related files #include -#include +#include #include #include @@ -188,7 +188,7 @@ namespace EMotionFX * @param endNodeIndex The node index to generate the path to. * @param outPath the array that will contain the path. */ - void GenerateUpdatePathToRoot(uint32 endNodeIndex, MCore::Array& outPath) const; + void GenerateUpdatePathToRoot(uint32 endNodeIndex, AZStd::vector& outPath) const; /** * Set the motion extraction node. @@ -245,7 +245,7 @@ namespace EMotionFX * @param outBoneList The array of indices to nodes that will be filled with the nodes that are bones. When the outBoneList array * already contains items, the array will first be cleared, so all existing contents will be lost. */ - void ExtractBoneList(uint32 lodLevel, MCore::Array* outBoneList) const; + void ExtractBoneList(uint32 lodLevel, AZStd::vector* outBoneList) const; //------------------------------------------------ void SetPhysicsSetup(const AZStd::shared_ptr& physicsSetup); @@ -313,7 +313,7 @@ namespace EMotionFX * @param lodLevel The LOD level to get the number of material from. * @result The number of materials this actor has/uses. */ - uint32 GetNumMaterials(uint32 lodLevel) const; + size_t GetNumMaterials(uint32 lodLevel) const; /** * Removes all materials from this actor. @@ -367,7 +367,7 @@ namespace EMotionFX * Get the number of LOD levels inside this actor. * @result The number of LOD levels. This value is at least 1, since the full detail LOD is always there. */ - uint32 GetNumLODLevels() const; + size_t GetNumLODLevels() const; //-------------------------------------------------------------------------- @@ -438,7 +438,7 @@ namespace EMotionFX * disabled nodes from the given skeletal LOD level. * @param geometryLODLevel The geometry LOD level to test the skeletal LOD against with. */ - void VerifySkinning(MCore::Array& conflictNodeFlags, uint32 skeletalLODLevel, uint32 geometryLODLevel); + void VerifySkinning(AZStd::vector& conflictNodeFlags, uint32 skeletalLODLevel, uint32 geometryLODLevel); /** * Checks if the given material is used by a given mesh. @@ -522,7 +522,7 @@ namespace EMotionFX * Get the number of dependencies. * @result The number of dependencies that this actor has on other actors. */ - MCORE_INLINE uint32 GetNumDependencies() const { return mDependencies.GetLength(); } + MCORE_INLINE size_t GetNumDependencies() const { return mDependencies.size(); } /** * Get a given dependency. @@ -658,7 +658,7 @@ namespace EMotionFX */ MCORE_INLINE const NodeMirrorInfo& GetNodeMirrorInfo(uint32 nodeIndex) const { return mNodeMirrorInfos[nodeIndex]; } - MCORE_INLINE bool GetHasMirrorInfo() const { return (mNodeMirrorInfos.GetLength() != 0); } + MCORE_INLINE bool GetHasMirrorInfo() const { return (mNodeMirrorInfos.size() != 0); } //--------------------------------------------------------------- @@ -749,9 +749,9 @@ namespace EMotionFX void PostCreateInit(bool makeGeomLodsCompatibleWithSkeletalLODs = true, bool convertUnitType = true); void AutoDetectMirrorAxes(); - const MCore::Array& GetNodeMirrorInfos() const; - MCore::Array& GetNodeMirrorInfos(); - void SetNodeMirrorInfos(const MCore::Array& mirrorInfos); + const AZStd::vector& GetNodeMirrorInfos() const; + AZStd::vector& GetNodeMirrorInfos(); + void SetNodeMirrorInfos(const AZStd::vector& mirrorInfos); bool GetHasMirrorAxesDetected() const; MCORE_INLINE const AZStd::vector& GetInverseBindPoseTransforms() const { return mInvBindPoseTransforms; } @@ -861,15 +861,38 @@ namespace EMotionFX MeshDeformerStack* mStack; NodeLODInfo(); + NodeLODInfo(const NodeLODInfo&) = delete; + NodeLODInfo(NodeLODInfo&& rhs) + { + if (&rhs == this) + { + return; + } + mMesh = rhs.mMesh; + mStack = rhs.mStack; + rhs.mMesh = nullptr; + rhs.mStack = nullptr; + } + NodeLODInfo& operator=(const NodeLODInfo&) = delete; + NodeLODInfo& operator=(NodeLODInfo&& rhs) + { + if (&rhs == this) + { + return *this; + } + mMesh = rhs.mMesh; + mStack = rhs.mStack; + rhs.mMesh = nullptr; + rhs.mStack = nullptr; + return *this; + } ~NodeLODInfo(); }; // a lod level struct EMFX_API LODLevel { - MCore::Array mNodeInfos; - - LODLevel(); + AZStd::vector mNodeInfos; }; struct MeshLODData @@ -896,12 +919,12 @@ namespace EMotionFX Node* FindMeshJoint(const AZ::Data::Asset& lodModelAsset) const; Skeleton* mSkeleton; /**< The skeleton, containing the nodes and bind pose. */ - MCore::Array mDependencies; /**< The dependencies on other actors (shared meshes and transforms). */ + AZStd::vector mDependencies; /**< The dependencies on other actors (shared meshes and transforms). */ AZStd::string mName; /**< The name of the actor. */ AZStd::string mFileName; /**< The filename of the actor. */ - MCore::Array mNodeMirrorInfos; /**< The array of node mirror info. */ - MCore::Array< MCore::Array< Material* > > mMaterials; /**< A collection of materials (for each lod). */ - MCore::Array< MorphSetup* > mMorphSetups; /**< A morph setup for each geometry LOD. */ + AZStd::vector mNodeMirrorInfos; /**< The array of node mirror info. */ + AZStd::vector< AZStd::vector< Material* > > mMaterials; /**< A collection of materials (for each lod). */ + AZStd::vector< MorphSetup* > mMorphSetups; /**< A morph setup for each geometry LOD. */ MCore::SmallArray mNodeGroups; /**< The set of node groups. */ AZStd::shared_ptr m_physicsSetup; /**< Hit detection, ragdoll and cloth colliders, joint limits and rigid bodies. */ AZStd::shared_ptr m_simulatedObjectSetup; /**< Setup for simulated objects */ diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.cpp index b80aab3c50..34af57026a 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.cpp @@ -45,11 +45,7 @@ namespace EMotionFX { MCORE_ASSERT(actor); - // set the memory categories - mAttachments.SetMemoryCategory(EMFX_MEMCATEGORY_ACTORINSTANCES); - mDependencies.SetMemoryCategory(EMFX_MEMCATEGORY_ACTORINSTANCES); - mEnabledNodes.SetMemoryCategory(EMFX_MEMCATEGORY_ACTORINSTANCES); - mEnabledNodes.Reserve(actor->GetNumNodes()); + mEnabledNodes.reserve(actor->GetNumNodes()); // set the actor and create the motion system mBoolFlags = 0; @@ -174,7 +170,7 @@ namespace EMotionFX // delete all attachments // actor instances that are attached will be detached, and not deleted from memory - const uint32 numAttachments = mAttachments.GetLength(); + const uint32 numAttachments = mAttachments.size(); for (uint32 i = 0; i < numAttachments; ++i) { ActorInstance* attachmentActorInstance = mAttachments[i]->GetAttachmentActorInstance(); @@ -187,7 +183,7 @@ namespace EMotionFX } mAttachments[i]->Destroy(); } - mAttachments.Clear(); + mAttachments.clear(); if (mMorphSetup) { @@ -396,7 +392,7 @@ namespace EMotionFX // Update the mesh deformers. const Skeleton* skeleton = mActor->GetSkeleton(); - const uint32 numNodes = mEnabledNodes.GetLength(); + const uint32 numNodes = mEnabledNodes.size(); for (uint32 i = 0; i < numNodes; ++i) { const uint16 nodeNr = mEnabledNodes[i]; @@ -416,7 +412,7 @@ namespace EMotionFX // Update the mesh morph deformers. const Skeleton* skeleton = mActor->GetSkeleton(); - const uint32 numNodes = mEnabledNodes.GetLength(); + const uint32 numNodes = mEnabledNodes.size(); for (uint32 i = 0; i < numNodes; ++i) { const uint16 nodeNr = mEnabledNodes[i]; @@ -448,7 +444,7 @@ namespace EMotionFX GetActorManager().GetScheduler()->RecursiveRemoveActorInstance(root); // add the attachment - mAttachments.Add(attachment); + mAttachments.emplace_back(attachment); ActorInstance* attachmentActorInstance = attachment->GetAttachmentActorInstance(); if (attachmentActorInstance) { @@ -468,7 +464,7 @@ namespace EMotionFX uint32 ActorInstance::FindAttachmentNr(ActorInstance* actorInstance) { // for all attachments - const uint32 numAttachments = mAttachments.GetLength(); + const uint32 numAttachments = mAttachments.size(); for (uint32 i = 0; i < numAttachments; ++i) { if (mAttachments[i]->GetAttachmentActorInstance() == actorInstance) @@ -498,7 +494,7 @@ namespace EMotionFX // remove an attachment void ActorInstance::RemoveAttachment(uint32 nr, bool delFromMem) { - MCORE_ASSERT(nr < mAttachments.GetLength()); + MCORE_ASSERT(nr < mAttachments.size()); // first remove the current attachment tree from the scheduler ActorInstance* root = FindAttachmentRoot(); @@ -528,7 +524,7 @@ namespace EMotionFX } // remove it from the attachment list - mAttachments.Remove(nr); + mAttachments.erase(AZStd::next(begin(mAttachments), nr)); // and re-add the root to the scheduler GetActorManager().GetScheduler()->RecursiveInsertActorInstance(root, 0); @@ -544,9 +540,9 @@ namespace EMotionFX void ActorInstance::RemoveAllAttachments(bool delFromMem) { // keep removing the last attachment until there are none left - while (mAttachments.GetLength()) + while (mAttachments.size()) { - RemoveAttachment(mAttachments.GetLength() - 1, delFromMem); + RemoveAttachment(mAttachments.size() - 1, delFromMem); } } @@ -554,19 +550,19 @@ namespace EMotionFX void ActorInstance::UpdateDependencies() { // get rid of existing dependencies - mDependencies.Clear(); + mDependencies.clear(); // add the main dependency Actor::Dependency mainDependency; mainDependency.mActor = mActor; mainDependency.mAnimGraph = (mAnimGraphInstance) ? mAnimGraphInstance->GetAnimGraph() : nullptr; - mDependencies.Add(mainDependency); + mDependencies.emplace_back(mainDependency); // add all dependencies stored inside the actor const uint32 numDependencies = mActor->GetNumDependencies(); for (uint32 i = 0; i < numDependencies; ++i) { - mDependencies.Add(*mActor->GetDependency(i)); + mDependencies.emplace_back(*mActor->GetDependency(i)); } } @@ -574,7 +570,7 @@ namespace EMotionFX void ActorInstance::UpdateAttachments() { // update all attachments - const uint32 numAttachments = mAttachments.GetLength(); + const uint32 numAttachments = mAttachments.size(); for (uint32 i = 0; i < numAttachments; ++i) { mAttachments[i]->Update(); @@ -1089,7 +1085,7 @@ namespace EMotionFX void ActorInstance::EnableNode(uint16 nodeIndex) { // if this node already is at an enabled state, do nothing - if (mEnabledNodes.Contains(nodeIndex)) + if (AZStd::find(begin(mEnabledNodes), end(mEnabledNodes), nodeIndex) != end(mEnabledNodes)) { return; } @@ -1105,16 +1101,16 @@ namespace EMotionFX uint32 parentIndex = skeleton->GetNode(curNode)->GetParentIndex(); if (parentIndex != MCORE_INVALIDINDEX32) { - const uint32 parentArrayIndex = mEnabledNodes.Find(static_cast(parentIndex)); - if (parentArrayIndex != MCORE_INVALIDINDEX32) + const auto parentArrayIter = AZStd::find(begin(mEnabledNodes), end(mEnabledNodes), static_cast(parentIndex)); + if (parentArrayIter != end(mEnabledNodes)) { - if (parentArrayIndex + 1 >= mEnabledNodes.GetLength()) + if (parentArrayIter + 1 == end(mEnabledNodes)) { - mEnabledNodes.Add(nodeIndex); + mEnabledNodes.emplace_back(nodeIndex); } else { - mEnabledNodes.Insert(parentArrayIndex + 1, nodeIndex); + mEnabledNodes.emplace(parentArrayIter + 1, nodeIndex); } found = true; } @@ -1125,7 +1121,7 @@ namespace EMotionFX } else // if we're dealing with a root node, insert it in the front of the array { - mEnabledNodes.Insert(0, nodeIndex); + mEnabledNodes.emplace(AZStd::next(begin(mEnabledNodes), 0), nodeIndex); found = true; } } while (found == false); @@ -1135,14 +1131,18 @@ namespace EMotionFX void ActorInstance::DisableNode(uint16 nodeIndex) { // try to remove the node from the array - mEnabledNodes.RemoveByValue(nodeIndex); + const auto it = AZStd::find(begin(mEnabledNodes), end(mEnabledNodes), nodeIndex); + if (it != end(mEnabledNodes)) + { + mEnabledNodes.erase(it); + } } // enable all nodes void ActorInstance::EnableAllNodes() { const uint32 numNodes = mActor->GetNumNodes(); - mEnabledNodes.Resize(numNodes); + mEnabledNodes.resize(numNodes); for (uint32 i = 0; i < numNodes; ++i) { mEnabledNodes[i] = static_cast(i); @@ -1152,7 +1152,7 @@ namespace EMotionFX // disable all nodes void ActorInstance::DisableAllNodes() { - mEnabledNodes.Clear(); + mEnabledNodes.clear(); } // change the skeletal LOD level @@ -1587,9 +1587,9 @@ namespace EMotionFX m_aabb = aabb; } - uint32 ActorInstance::GetNumAttachments() const + size_t ActorInstance::GetNumAttachments() const { - return mAttachments.GetLength(); + return mAttachments.size(); } Attachment* ActorInstance::GetAttachment(uint32 nr) const @@ -1612,9 +1612,9 @@ namespace EMotionFX return mSelfAttachment; } - uint32 ActorInstance::GetNumDependencies() const + size_t ActorInstance::GetNumDependencies() const { - return mDependencies.GetLength(); + return mDependencies.size(); } Actor::Dependency* ActorInstance::GetDependency(uint32 nr) @@ -1779,7 +1779,7 @@ namespace EMotionFX SetIsVisible(isVisible); // recurse to all child attachments - const uint32 numAttachments = mAttachments.GetLength(); + const uint32 numAttachments = mAttachments.size(); for (uint32 i = 0; i < numAttachments; ++i) { mAttachments[i]->GetAttachmentActorInstance()->RecursiveSetIsVisible(isVisible); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.h b/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.h index 4488a1386f..4b605afc3b 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.h @@ -599,7 +599,7 @@ namespace EMotionFX * Get the number of attachments that have been added to this actor instance. * @result The number of attachments added to this actor instance. */ - uint32 GetNumAttachments() const; + size_t GetNumAttachments() const; /** * Get a specific attachment. @@ -664,7 +664,7 @@ namespace EMotionFX * Get the number of dependencies that this actor instance has on other actors. * @result The number of dependencies. */ - uint32 GetNumDependencies() const; + size_t GetNumDependencies() const; /** * Get a given dependency. @@ -788,13 +788,13 @@ namespace EMotionFX * Get direct access to the array of enabled nodes. * @result A read only reference to the array of enabled nodes. The values inside of this array are the node numbers of the enabled nodes. */ - MCORE_INLINE const MCore::Array& GetEnabledNodes() const { return mEnabledNodes; } + MCORE_INLINE const AZStd::vector& GetEnabledNodes() const { return mEnabledNodes; } /** * Get the number of enabled nodes inside this actor instance. * @result The number of nodes that have been enabled and are being updated. */ - MCORE_INLINE uint32 GetNumEnabledNodes() const { return mEnabledNodes.GetLength(); } + MCORE_INLINE size_t GetNumEnabledNodes() const { return mEnabledNodes.size(); } /** * Get the node number of a given enabled node. @@ -873,10 +873,10 @@ namespace EMotionFX Transform mParentWorldTransform = Transform::CreateIdentity(); Transform mTrajectoryDelta = Transform::CreateIdentityWithZeroScale(); - MCore::Array mAttachments; /**< The attachments linked to this actor instance. */ - MCore::Array mDependencies; /**< The actor dependencies, which specify which Actor objects this instance is dependent on. */ + AZStd::vector mAttachments; /**< The attachments linked to this actor instance. */ + AZStd::vector mDependencies; /**< The actor dependencies, which specify which Actor objects this instance is dependent on. */ MorphSetupInstance* mMorphSetup; /**< The morph setup instance. */ - MCore::Array mEnabledNodes; /**< The list of nodes that are enabled. */ + AZStd::vector mEnabledNodes; /**< The list of nodes that are enabled. */ Actor* mActor; /**< A pointer to the parent actor where this is an instance from. */ ActorInstance* mAttachedTo; /**< Specifies the actor where this actor is attached to, or nullptr when it is no attachment. */ diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/ActorManager.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/ActorManager.cpp index e40a0dde5b..a8584163ed 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/ActorManager.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/ActorManager.cpp @@ -27,17 +27,13 @@ namespace EMotionFX { mScheduler = nullptr; - // set memory categories - mActorInstances.SetMemoryCategory(EMFX_MEMCATEGORY_ACTORMANAGER); - mRootActorInstances.SetMemoryCategory(EMFX_MEMCATEGORY_ACTORMANAGER); - // setup the default scheduler SetScheduler(MultiThreadScheduler::Create()); // reserve memory m_actors.reserve(512); - mActorInstances.Reserve(1024); - mRootActorInstances.Reserve(1024); + mActorInstances.reserve(1024); + mRootActorInstances.reserve(1024); } @@ -79,8 +75,8 @@ namespace EMotionFX void ActorManager::UnregisterAllActorInstances() { LockActorInstances(); - mActorInstances.Clear(); - mRootActorInstances.Clear(); + mActorInstances.clear(); + mRootActorInstances.clear(); if (mScheduler) { mScheduler->Clear(); @@ -104,7 +100,7 @@ namespace EMotionFX mScheduler = scheduler; // adjust all visibility flags to false for all actor instances - const uint32 numActorInstances = mActorInstances.GetLength(); + const uint32 numActorInstances = mActorInstances.size(); for (uint32 i = 0; i < numActorInstances; ++i) { mActorInstances[i]->SetIsVisible(false); @@ -139,7 +135,7 @@ namespace EMotionFX { LockActorInstances(); - mActorInstances.Add(actorInstance); + mActorInstances.emplace_back(actorInstance); UpdateActorInstanceStatus(actorInstance, false); UnlockActorInstances(); @@ -213,7 +209,7 @@ namespace EMotionFX LockActorInstances(); // get the number of actor instances and iterate through them - const uint32 numActorInstances = mActorInstances.GetLength(); + const uint32 numActorInstances = mActorInstances.size(); for (uint32 i = 0; i < numActorInstances; ++i) { if (mActorInstances[i] == actorInstance) @@ -233,7 +229,7 @@ namespace EMotionFX uint32 ActorManager::FindActorInstanceIndex(ActorInstance* actorInstance) const { // get the number of actor instances and iterate through them - const uint32 numActorInstances = mActorInstances.GetLength(); + const uint32 numActorInstances = mActorInstances.size(); for (uint32 i = 0; i < numActorInstances; ++i) { if (mActorInstances[i] == actorInstance) @@ -251,7 +247,7 @@ namespace EMotionFX ActorInstance* ActorManager::FindActorInstanceByID(uint32 id) const { // get the number of actor instances and iterate through them - const uint32 numActorInstances = mActorInstances.GetLength(); + const uint32 numActorInstances = mActorInstances.size(); for (uint32 i = 0; i < numActorInstances; ++i) { if (mActorInstances[i]->GetID() == id) @@ -349,15 +345,18 @@ namespace EMotionFX if (actorInstance->GetAttachedTo() == nullptr) { // make sure it's in the root list - if (mRootActorInstances.Contains(actorInstance) == false) + if (AZStd::find(begin(mRootActorInstances), end(mRootActorInstances), actorInstance) == end(mRootActorInstances)) { - mRootActorInstances.Add(actorInstance); + mRootActorInstances.emplace_back(actorInstance); } } else // no root actor instance { // remove it from the root list - mRootActorInstances.RemoveByValue(actorInstance); + if (const auto it = AZStd::find(begin(mRootActorInstances), end(mRootActorInstances), actorInstance); it != end(mRootActorInstances)) + { + mRootActorInstances.erase(it); + } mScheduler->RecursiveRemoveActorInstance(actorInstance); } @@ -374,10 +373,16 @@ namespace EMotionFX LockActorInstances(); // remove the actor instance from the list - mActorInstances.RemoveByValue(instance); + if (const auto it = AZStd::find(begin(mActorInstances), end(mActorInstances), instance); it != end(mActorInstances)) + { + mActorInstances.erase(it); + } // remove it from the list of roots, if it is in there - mRootActorInstances.RemoveByValue(instance); + if (const auto it = AZStd::find(begin(mRootActorInstances), end(mRootActorInstances), instance); it != end(mRootActorInstances)) + { + mRootActorInstances.erase(it); + } // remove it from the schedule mScheduler->RemoveActorInstance(instance); @@ -416,7 +421,7 @@ namespace EMotionFX } - const MCore::Array& ActorManager::GetActorInstanceArray() const + const AZStd::vector& ActorManager::GetActorInstanceArray() const { return mActorInstances; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/ActorManager.h b/Gems/EMotionFX/Code/EMotionFX/Source/ActorManager.h index 280cc33498..34b290cfff 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/ActorManager.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/ActorManager.h @@ -14,7 +14,7 @@ #include "BaseObject.h" #include "MemoryCategories.h" #include -#include +#include #include @@ -124,7 +124,7 @@ namespace EMotionFX * Get the number of actor instances that currently are registered. * @result The number of registered actor instances. */ - MCORE_INLINE uint32 GetNumActorInstances() const { return mActorInstances.GetLength(); } + MCORE_INLINE size_t GetNumActorInstances() const { return mActorInstances.size(); } /** * Get a given registered actor instance. @@ -137,7 +137,7 @@ namespace EMotionFX * Get the array of actor instances. * @result The const reference to the actor instance array. */ - const MCore::Array& GetActorInstanceArray() const; + const AZStd::vector& GetActorInstanceArray() const; /** * Find the given actor instance inside the actor manager and return its index. @@ -201,7 +201,7 @@ namespace EMotionFX * horse is the root attachment instance. * @result Returns the number of root actor instances. */ - MCORE_INLINE uint32 GetNumRootActorInstances() const { return mRootActorInstances.GetLength(); } + MCORE_INLINE size_t GetNumRootActorInstances() const { return mRootActorInstances.size(); } /** * Get a given root actor instance. @@ -255,9 +255,9 @@ namespace EMotionFX void UnlockActors(); private: - MCore::Array mActorInstances; /**< The registered actor instances. */ + AZStd::vector mActorInstances; /**< The registered actor instances. */ AZStd::vector> m_actors; /**< The registered actors. */ - MCore::Array mRootActorInstances; /**< Root actor instances (roots of all attachment chains). */ + AZStd::vector mRootActorInstances; /**< Root actor instances (roots of all attachment chains). */ ActorUpdateScheduler* mScheduler; /**< The update scheduler to use. */ MCore::MutexRecursive mActorLock; /**< The multithread lock for touching the actors array. */ MCore::MutexRecursive mActorInstanceLock; /**< The multithread lock for touching the actor instances array. */ diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraph.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraph.cpp index 7a9001433a..f049c498f6 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraph.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraph.cpp @@ -36,8 +36,6 @@ namespace EMotionFX AnimGraph::AnimGraph() : mGameControllerSettings(aznew AnimGraphGameControllerSettings()) { - mNodes.SetMemoryCategory(EMFX_MEMCATEGORY_ANIMGRAPH); - mID = MCore::GetIDGenerator().GenerateID(); mDirtyFlag = false; mAutoUnregister = true; @@ -50,7 +48,7 @@ namespace EMotionFX #endif // EMFX_DEVELOPMENT_BUILD // reserve some memory - mNodes.Reserve(1024); + mNodes.reserve(1024); // automatically register the anim graph GetAnimGraphManager().AddAnimGraph(this); @@ -628,7 +626,7 @@ namespace EMotionFX mRootStateMachine->RecursiveCollectNodesOfType(nodeType, outNodes); } - void AnimGraph::RecursiveCollectTransitionConditionsOfType(const AZ::TypeId& conditionType, MCore::Array* outConditions) const + void AnimGraph::RecursiveCollectTransitionConditionsOfType(const AZ::TypeId& conditionType, AZStd::vector* outConditions) const { mRootStateMachine->RecursiveCollectTransitionConditionsOfType(conditionType, outConditions); } @@ -725,8 +723,8 @@ namespace EMotionFX if (azrtti_istypeof(object)) { AnimGraphNode* node = static_cast(object); - node->SetNodeIndex(mNodes.GetLength()); - mNodes.Add(node); + node->SetNodeIndex(mNodes.size()); + mNodes.emplace_back(node); } // create a unique data for this added object in the animgraph instances as well @@ -765,7 +763,7 @@ namespace EMotionFX AnimGraphNode* node = static_cast(object); const uint32 nodeIndex = node->GetNodeIndex(); - const uint32 numNodes = mNodes.GetLength(); + const uint32 numNodes = mNodes.size(); for (uint32 i = nodeIndex + 1; i < numNodes; ++i) { AnimGraphNode* curNode = mNodes[i]; @@ -774,7 +772,7 @@ namespace EMotionFX } // remove the object from the array - mNodes.Remove(nodeIndex); + mNodes.erase(AZStd::next(begin(mNodes), nodeIndex)); } } @@ -789,14 +787,14 @@ namespace EMotionFX // reserve space for a given amount of nodes void AnimGraph::ReserveNumNodes(uint32 numNodes) { - mNodes.Reserve(numNodes); + mNodes.reserve(numNodes); } // Calculate number of motion nodes in the graph uint32 AnimGraph::CalcNumMotionNodes() const { - const uint32 numNodes = mNodes.GetLength(); + const uint32 numNodes = mNodes.size(); uint32 numMotionNodes = 0; for (uint32 i = 0; i < numNodes; ++i) { @@ -1029,7 +1027,7 @@ namespace EMotionFX void AnimGraph::RemoveInvalidConnections(bool logWarnings) { // Iterate over all nodes - const AZ::u32 numNodes = mNodes.GetLength(); + const AZ::u32 numNodes = mNodes.size(); for (AZ::u32 i = 0; i < numNodes; ++i) { AnimGraphNode* node = mNodes[i]; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraph.h b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraph.h index e7c775d644..ab1cfd926f 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraph.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraph.h @@ -20,7 +20,7 @@ #include #include #include -#include +#include namespace EMotionFX { @@ -65,7 +65,7 @@ namespace EMotionFX AnimGraphStateTransition* RecursiveFindTransitionById(AnimGraphConnectionId transitionId) const; void RecursiveCollectNodesOfType(const AZ::TypeId& nodeType, AZStd::vector* outNodes) const; // note: outNodes is NOT cleared internally, nodes are added to the array - void RecursiveCollectTransitionConditionsOfType(const AZ::TypeId& conditionType, MCore::Array* outConditions) const; // note: outNodes is NOT cleared internally, nodes are added to the array + void RecursiveCollectTransitionConditionsOfType(const AZ::TypeId& conditionType, AZStd::vector* outConditions) const; // note: outNodes is NOT cleared internally, nodes are added to the array // Collects all objects of type and/or derived type void RecursiveCollectObjectsOfType(const AZ::TypeId& objectType, AZStd::vector& outObjects); @@ -381,7 +381,7 @@ namespace EMotionFX AnimGraphObject* GetObject(uint32 index) const { return mObjects[index]; } void ReserveNumObjects(uint32 numObjects); - uint32 GetNumNodes() const { return mNodes.GetLength(); } + size_t GetNumNodes() const { return mNodes.size(); } AnimGraphNode* GetNode(uint32 index) const { return mNodes[index]; } void ReserveNumNodes(uint32 numNodes); uint32 CalcNumMotionNodes() const; @@ -417,7 +417,7 @@ namespace EMotionFX AZStd::unordered_map m_valueParameterIndexByName; /**< Cached version of parameter index by name to accelerate lookups. */ AZStd::vector mNodeGroups; AZStd::vector mObjects; - MCore::Array mNodes; + AZStd::vector mNodes; AZStd::vector m_animGraphInstances; AZStd::string mFileName; AnimGraphStateMachine* mRootStateMachine; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphGameControllerSettings.h b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphGameControllerSettings.h index e00fef8601..715b280690 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphGameControllerSettings.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphGameControllerSettings.h @@ -10,7 +10,7 @@ #include #include -#include +#include #include #include @@ -48,12 +48,11 @@ namespace EMotionFX struct EMFX_API ParameterInfo final { - AZ_RTTI(AnimGraphGameControllerSettings::ParameterInfo, "{C3220DB3-54FA-4719-80F0-CEAE5859C641}"); + AZ_TYPE_INFO(AnimGraphGameControllerSettings::ParameterInfo, "{C3220DB3-54FA-4719-80F0-CEAE5859C641}"); AZ_CLASS_ALLOCATOR_DECL ParameterInfo(); ParameterInfo(const char* parameterName); - virtual ~ParameterInfo() = default; static void Reflect(AZ::ReflectContext* context); @@ -66,12 +65,11 @@ namespace EMotionFX struct EMFX_API ButtonInfo final { - AZ_RTTI(AnimGraphGameControllerSettings::ButtonInfo, "{94027445-C44F-4310-9DF2-1A2F39518578}"); + AZ_TYPE_INFO(AnimGraphGameControllerSettings::ButtonInfo, "{94027445-C44F-4310-9DF2-1A2F39518578}"); AZ_CLASS_ALLOCATOR_DECL ButtonInfo(); ButtonInfo(AZ::u32 buttonIndex); - virtual ~ButtonInfo() = default; static void Reflect(AZ::ReflectContext* context); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphInstance.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphInstance.cpp index 46764744a8..1082bc112b 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphInstance.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphInstance.cpp @@ -57,8 +57,6 @@ namespace EMotionFX mInitSettings = *initSettings; } - mParamValues.SetMemoryCategory(EMFX_MEMCATEGORY_ANIMGRAPH_INSTANCE); - mObjectFlags.SetMemoryCategory(EMFX_MEMCATEGORY_ANIMGRAPH_INSTANCE); m_eventHandlersByEventType.resize(EVENT_TYPE_ANIM_GRAPH_INSTANCE_LAST_EVENT - EVENT_TYPE_ANIM_GRAPH_INSTANCE_FIRST_EVENT + 1); // init the internal attributes (create them) @@ -145,7 +143,7 @@ namespace EMotionFX { if (delFromMem) { - const uint32 numParams = mParamValues.GetLength(); + const uint32 numParams = mParamValues.size(); for (uint32 i = 0; i < numParams; ++i) { if (mParamValues[i]) @@ -155,7 +153,7 @@ namespace EMotionFX } } - mParamValues.Clear(); + mParamValues.clear(); } @@ -268,10 +266,10 @@ namespace EMotionFX RemoveAllParameters(true); const ValueParameterVector& valueParameters = mAnimGraph->RecursivelyGetValueParameters(); - mParamValues.Resize(static_cast(valueParameters.size())); + mParamValues.resize(static_cast(valueParameters.size())); // init the values - const uint32 numParams = mParamValues.GetLength(); + const uint32 numParams = mParamValues.size(); for (uint32 i = 0; i < numParams; ++i) { mParamValues[i] = valueParameters[i]->ConstructDefaultValueAsAttribute(); @@ -284,22 +282,22 @@ namespace EMotionFX { // check how many parameters we need to add const ValueParameterVector& valueParameters = mAnimGraph->RecursivelyGetValueParameters(); - const int32 numToAdd = static_cast(valueParameters.size()) - mParamValues.GetLength(); + const int32 numToAdd = static_cast(valueParameters.size()) - mParamValues.size(); if (numToAdd <= 0) { return; } // make sure we have the right space pre-allocated - mParamValues.Reserve(static_cast(valueParameters.size())); + mParamValues.reserve(static_cast(valueParameters.size())); // add the remaining parameters - const uint32 startIndex = mParamValues.GetLength(); + const uint32 startIndex = mParamValues.size(); for (int32 i = 0; i < numToAdd; ++i) { const uint32 index = startIndex + i; - mParamValues.AddEmpty(); - mParamValues.GetLast() = valueParameters[index]->ConstructDefaultValueAsAttribute(); + mParamValues.emplace_back(); + mParamValues.back() = valueParameters[index]->ConstructDefaultValueAsAttribute(); } } @@ -315,7 +313,7 @@ namespace EMotionFX } } - mParamValues.Remove(index); + mParamValues.erase(AZStd::next(begin(mParamValues), index)); } @@ -333,7 +331,7 @@ namespace EMotionFX void AnimGraphInstance::ReInitParameterValues() { - const AZ::u32 parameterValueCount = mParamValues.GetLength(); + const AZ::u32 parameterValueCount = mParamValues.size(); for (AZ::u32 i = 0; i < parameterValueCount; ++i) { ReInitParameterValue(i); @@ -503,15 +501,15 @@ namespace EMotionFX // add the last anim graph parameter to this instance void AnimGraphInstance::AddParameterValue() { - mParamValues.Add(nullptr); - ReInitParameterValue(mParamValues.GetLength() - 1); + mParamValues.emplace_back(nullptr); + ReInitParameterValue(mParamValues.size() - 1); } // add the parameter of the animgraph, at a given index void AnimGraphInstance::InsertParameterValue(uint32 index) { - mParamValues.Insert(index, nullptr); + mParamValues.emplace(AZStd::next(begin(mParamValues), index), nullptr); ReInitParameterValue(index); } @@ -658,7 +656,7 @@ namespace EMotionFX void AnimGraphInstance::AddUniqueObjectData() { m_uniqueDatas.emplace_back(nullptr); - mObjectFlags.Add(0); + mObjectFlags.emplace_back(0); } // remove the given unique data object @@ -676,7 +674,7 @@ namespace EMotionFX } m_uniqueDatas.erase(m_uniqueDatas.begin() + index); - mObjectFlags.Remove(index); + mObjectFlags.erase(AZStd::next(begin(mObjectFlags), index)); } @@ -684,7 +682,7 @@ namespace EMotionFX { AnimGraphObjectData* data = m_uniqueDatas[index]; m_uniqueDatas.erase(m_uniqueDatas.begin() + index); - mObjectFlags.Remove(static_cast(index)); + mObjectFlags.erase(AZStd::next(begin(mObjectFlags), static_cast(index))); if (delFromMem && data) { data->Destroy(); @@ -707,7 +705,7 @@ namespace EMotionFX } m_uniqueDatas.clear(); - mObjectFlags.Clear(); + mObjectFlags.clear(); } @@ -813,7 +811,7 @@ namespace EMotionFX { const uint32 numObjects = mAnimGraph->GetNumObjects(); m_uniqueDatas.resize(numObjects); - mObjectFlags.Resize(numObjects); + mObjectFlags.resize(numObjects); for (uint32 i = 0; i < numObjects; ++i) { m_uniqueDatas[i] = nullptr; @@ -934,7 +932,7 @@ namespace EMotionFX // reset all node flags void AnimGraphInstance::ResetFlagsForAllObjects(uint32 flagsToDisable) { - const uint32 numObjects = mObjectFlags.GetLength(); + const uint32 numObjects = mObjectFlags.size(); for (uint32 i = 0; i < numObjects; ++i) { mObjectFlags[i] &= ~flagsToDisable; @@ -967,7 +965,7 @@ namespace EMotionFX // reset all node flags void AnimGraphInstance::ResetFlagsForAllObjects() { - MCore::MemSet(mObjectFlags.GetPtr(), 0, sizeof(uint32) * mObjectFlags.GetLength()); + MCore::MemSet(mObjectFlags.data(), 0, sizeof(uint32) * mObjectFlags.size()); for (AnimGraphInstance* childInstance : m_childAnimGraphInstances) { diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphInstance.h b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphInstance.h index 97d076d244..417883d16f 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphInstance.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphInstance.h @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include @@ -302,9 +302,9 @@ namespace EMotionFX ActorInstance* mActorInstance; AnimGraphInstance* m_parentAnimGraphInstance; // If this anim graph instance is in a reference node, it will have a parent anim graph instance. AZStd::vector m_childAnimGraphInstances; // If this anim graph instance contains reference nodes, the anim graph instances will be listed here. - MCore::Array mParamValues; // a value for each AnimGraph parameter (the control parameters) + AZStd::vector mParamValues; // a value for each AnimGraph parameter (the control parameters) AZStd::vector m_uniqueDatas; // unique object data - MCore::Array mObjectFlags; // the object flags + AZStd::vector mObjectFlags; // the object flags using EventHandlerVector = AZStd::vector; AZStd::vector m_eventHandlersByEventType; /**< The event handler to use to process events organized by EventTypes. */ AZStd::vector m_internalAttributes; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphManager.h b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphManager.h index 9f04517982..4973437b8e 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphManager.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphManager.h @@ -11,7 +11,7 @@ #include "EMotionFXConfig.h" #include #include "BaseObject.h" -#include +#include #include "AnimGraphObject.h" #include diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNode.cpp index 44d048c03c..f9896cf677 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNode.cpp @@ -1287,14 +1287,14 @@ namespace EMotionFX // collect child nodes of the given type - void AnimGraphNode::CollectChildNodesOfType(const AZ::TypeId& nodeType, MCore::Array* outNodes) const + void AnimGraphNode::CollectChildNodesOfType(const AZ::TypeId& nodeType, AZStd::vector* outNodes) const { for (AnimGraphNode* childNode : mChildNodes) { // check the current node type and add it to the output array in case they are the same if (azrtti_typeid(childNode) == nodeType) { - outNodes->Add(childNode); + outNodes->emplace_back(childNode); } } } @@ -1324,7 +1324,7 @@ namespace EMotionFX } } - void AnimGraphNode::RecursiveCollectTransitionConditionsOfType(const AZ::TypeId& conditionType, MCore::Array* outConditions) const + void AnimGraphNode::RecursiveCollectTransitionConditionsOfType(const AZ::TypeId& conditionType, AZStd::vector* outConditions) const { // check if the current node is a state machine if (azrtti_typeid(this) == azrtti_typeid()) @@ -1346,7 +1346,7 @@ namespace EMotionFX AnimGraphTransitionCondition* condition = transition->GetCondition(j); if (azrtti_typeid(condition) == conditionType) { - outConditions->Add(condition); + outConditions->emplace_back(condition); } } } @@ -1601,9 +1601,9 @@ namespace EMotionFX // collect internal objects - void AnimGraphNode::RecursiveCollectObjects(MCore::Array& outObjects) const + void AnimGraphNode::RecursiveCollectObjects(AZStd::vector& outObjects) const { - outObjects.Add(const_cast(this)); + outObjects.emplace_back(const_cast(this)); for (const AnimGraphNode* childNode : mChildNodes) { diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNode.h b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNode.h index c469631335..7377f27d7c 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNode.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNode.h @@ -270,7 +270,7 @@ namespace EMotionFX virtual bool RecursiveDetectCycles(AZStd::unordered_set& nodes) const; - void CollectChildNodesOfType(const AZ::TypeId& nodeType, MCore::Array* outNodes) const; // note: outNodes is NOT cleared internally, nodes are added to the array + void CollectChildNodesOfType(const AZ::TypeId& nodeType, AZStd::vector* outNodes) const; // note: outNodes is NOT cleared internally, nodes are added to the array /** * Collect child nodes of the given type. This will only iterate through the child nodes and isn't a recursive process. @@ -280,7 +280,7 @@ namespace EMotionFX void CollectChildNodesOfType(const AZ::TypeId& nodeType, AZStd::vector& outNodes) const; void RecursiveCollectNodesOfType(const AZ::TypeId& nodeType, AZStd::vector* outNodes) const; // note: outNodes is NOT cleared internally, nodes are added to the array - void RecursiveCollectTransitionConditionsOfType(const AZ::TypeId& conditionType, MCore::Array* outConditions) const; // note: outNodes is NOT cleared internally, nodes are added to the array + void RecursiveCollectTransitionConditionsOfType(const AZ::TypeId& conditionType, AZStd::vector* outConditions) const; // note: outNodes is NOT cleared internally, nodes are added to the array virtual void RecursiveCollectObjectsOfType(const AZ::TypeId& objectType, AZStd::vector& outObjects) const; @@ -916,7 +916,7 @@ namespace EMotionFX void SetHasError(AnimGraphObjectData* uniqueData, bool hasError); // collect internal objects - void RecursiveCollectObjects(MCore::Array& outObjects) const override; + void RecursiveCollectObjects(AZStd::vector& outObjects) const override; virtual void RecursiveSetUniqueDataFlag(AnimGraphInstance* animGraphInstance, uint32 flag, bool enabled); void FilterEvents(AnimGraphInstance* animGraphInstance, EEventMode eventMode, AnimGraphNode* nodeA, AnimGraphNode* nodeB, float localWeight, AnimGraphRefCountedData* refData); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphObject.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphObject.cpp index a56e8d246e..c687dcadb1 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphObject.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphObject.cpp @@ -116,9 +116,9 @@ namespace EMotionFX // collect internal objects - void AnimGraphObject::RecursiveCollectObjects(MCore::Array& outObjects) const + void AnimGraphObject::RecursiveCollectObjects(AZStd::vector& outObjects) const { - outObjects.Add(const_cast(this)); + outObjects.emplace_back(const_cast(this)); } void AnimGraphObject::InvalidateUniqueDatas() diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphObject.h b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphObject.h index c3d6968a2d..2f01b572e3 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphObject.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphObject.h @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include #include #include @@ -153,7 +153,7 @@ namespace EMotionFX uint32 SaveUniqueData(AnimGraphInstance* animGraphInstance, uint8* outputBuffer) const; // save and return number of bytes written, when outputBuffer is nullptr only return num bytes it would write uint32 LoadUniqueData(AnimGraphInstance* animGraphInstance, const uint8* dataBuffer); // load and return number of bytes read, when dataBuffer is nullptr, 0 should be returned - virtual void RecursiveCollectObjects(MCore::Array& outObjects) const; + virtual void RecursiveCollectObjects(AZStd::vector& outObjects) const; bool GetHasErrorFlag(AnimGraphInstance* animGraphInstance) const; void SetHasErrorFlag(AnimGraphInstance* animGraphInstance, bool hasError); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphPosePool.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphPosePool.cpp index f30d742a24..5f139d9c49 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphPosePool.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphPosePool.cpp @@ -16,10 +16,8 @@ namespace EMotionFX // constructor AnimGraphPosePool::AnimGraphPosePool() { - mPoses.SetMemoryCategory(EMFX_MEMCATEGORY_ANIMGRAPH_POSEPOOL); - mFreePoses.SetMemoryCategory(EMFX_MEMCATEGORY_ANIMGRAPH_POSEPOOL); - mPoses.Reserve(12); - mFreePoses.Reserve(12); + mPoses.reserve(12); + mFreePoses.reserve(12); Resize(8); mMaxUsed = 0; } @@ -29,22 +27,22 @@ namespace EMotionFX AnimGraphPosePool::~AnimGraphPosePool() { // delete all poses - const uint32 numPoses = mPoses.GetLength(); + const uint32 numPoses = mPoses.size(); for (uint32 i = 0; i < numPoses; ++i) { delete mPoses[i]; } - mPoses.Clear(); + mPoses.clear(); // clear the free array - mFreePoses.Clear(); + mFreePoses.clear(); } // resize the number of poses in the pool void AnimGraphPosePool::Resize(uint32 numPoses) { - const uint32 numOldPoses = mPoses.GetLength(); + const uint32 numOldPoses = mPoses.size(); // if we will remove poses int32 difference = numPoses - numOldPoses; @@ -54,10 +52,10 @@ namespace EMotionFX difference = abs(difference); for (int32 i = 0; i < difference; ++i) { - AnimGraphPose* pose = mPoses[mFreePoses.GetLength() - 1]; - MCORE_ASSERT(mFreePoses.Contains(pose)); // make sure the pose is not already in use + AnimGraphPose* pose = mPoses.back(); + MCORE_ASSERT(AZStd::find(begin(mFreePoses), end(mFreePoses), pose) == end(mFreePoses)); // make sure the pose is not already in use delete pose; - mPoses.Remove(mFreePoses.GetLength() - 1); + mPoses.erase(mFreePoses.end() - 1); } } else // we want to add new poses @@ -65,8 +63,8 @@ namespace EMotionFX for (int32 i = 0; i < difference; ++i) { AnimGraphPose* newPose = new AnimGraphPose(); - mPoses.Add(newPose); - mFreePoses.Add(newPose); + mPoses.emplace_back(newPose); + mFreePoses.emplace_back(newPose); } } } @@ -76,21 +74,21 @@ namespace EMotionFX AnimGraphPose* AnimGraphPosePool::RequestPose(const ActorInstance* actorInstance) { // if we have no free poses left, allocate a new one - if (mFreePoses.GetLength() == 0) + if (mFreePoses.size() == 0) { AnimGraphPose* newPose = new AnimGraphPose(); newPose->LinkToActorInstance(actorInstance); - mPoses.Add(newPose); + mPoses.emplace_back(newPose); mMaxUsed = MCore::Max(mMaxUsed, GetNumUsedPoses()); newPose->SetIsInUse(true); return newPose; } // request the last free pose - AnimGraphPose* pose = mFreePoses[mFreePoses.GetLength() - 1]; + AnimGraphPose* pose = mFreePoses[mFreePoses.size() - 1]; //if (pose->GetActorInstance() != actorInstance) pose->LinkToActorInstance(actorInstance); - mFreePoses.RemoveLast(); // remove it from the list of free poses + mFreePoses.pop_back(); // remove it from the list of free poses mMaxUsed = MCore::Max(mMaxUsed, GetNumUsedPoses()); pose->SetIsInUse(true); return pose; @@ -101,7 +99,7 @@ namespace EMotionFX void AnimGraphPosePool::FreePose(AnimGraphPose* pose) { //MCORE_ASSERT( mPoses.Contains(pose) ); - mFreePoses.Add(pose); + mFreePoses.emplace_back(pose); pose->SetIsInUse(false); } @@ -109,7 +107,7 @@ namespace EMotionFX // free all poses void AnimGraphPosePool::FreeAllPoses() { - const uint32 numPoses = mPoses.GetLength(); + const uint32 numPoses = mPoses.size(); for (uint32 i = 0; i < numPoses; ++i) { AnimGraphPose* curPose = mPoses[i]; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphPosePool.h b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphPosePool.h index 2c792e2005..8f7a38be97 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphPosePool.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphPosePool.h @@ -10,7 +10,7 @@ // include required headers #include "EMotionFXConfig.h" -#include +#include @@ -41,15 +41,15 @@ namespace EMotionFX void FreeAllPoses(); - MCORE_INLINE uint32 GetNumFreePoses() const { return mFreePoses.GetLength(); } - MCORE_INLINE uint32 GetNumPoses() const { return mPoses.GetLength(); } - MCORE_INLINE uint32 GetNumUsedPoses() const { return (mPoses.GetLength() - mFreePoses.GetLength()); } + MCORE_INLINE size_t GetNumFreePoses() const { return mFreePoses.size(); } + MCORE_INLINE size_t GetNumPoses() const { return mPoses.size(); } + MCORE_INLINE size_t GetNumUsedPoses() const { return (mPoses.size() - mFreePoses.size()); } MCORE_INLINE uint32 GetNumMaxUsedPoses() const { return mMaxUsed; } MCORE_INLINE void ResetMaxUsedPoses() { mMaxUsed = 0; } private: - MCore::Array mPoses; - MCore::Array mFreePoses; + AZStd::vector mPoses; + AZStd::vector mFreePoses; uint32 mMaxUsed; }; } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphRefCountedDataPool.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphRefCountedDataPool.cpp index 6f77868ad7..289a9c4982 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphRefCountedDataPool.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphRefCountedDataPool.cpp @@ -8,6 +8,8 @@ // include required headers #include "AnimGraphRefCountedDataPool.h" +#include +#include namespace EMotionFX @@ -15,10 +17,8 @@ namespace EMotionFX // constructor AnimGraphRefCountedDataPool::AnimGraphRefCountedDataPool() { - mItems.SetMemoryCategory(EMFX_MEMCATEGORY_ANIMGRAPH_REFCOUNTEDDATA); - mFreeItems.SetMemoryCategory(EMFX_MEMCATEGORY_ANIMGRAPH_REFCOUNTEDDATA); - mItems.Reserve(32); - mFreeItems.Reserve(32); + mItems.reserve(32); + mFreeItems.reserve(32); Resize(16); mMaxUsed = 0; } @@ -28,22 +28,22 @@ namespace EMotionFX AnimGraphRefCountedDataPool::~AnimGraphRefCountedDataPool() { // delete all items - const uint32 numItems = mItems.GetLength(); + const uint32 numItems = mItems.size(); for (uint32 i = 0; i < numItems; ++i) { delete mItems[i]; } - mItems.Clear(); + mItems.clear(); // clear the free array - mFreeItems.Clear(); + mFreeItems.clear(); } // resize the number of items in the pool void AnimGraphRefCountedDataPool::Resize(uint32 numItems) { - const uint32 numOldItems = mItems.GetLength(); + const uint32 numOldItems = mItems.size(); // if we will remove Items int32 difference = numItems - numOldItems; @@ -53,10 +53,10 @@ namespace EMotionFX difference = abs(difference); for (int32 i = 0; i < difference; ++i) { - AnimGraphRefCountedData* item = mItems[mFreeItems.GetLength() - 1]; - MCORE_ASSERT(mFreeItems.Contains(item)); // make sure the Item is not already in use + AnimGraphRefCountedData* item = mItems.back(); + MCORE_ASSERT(AZStd::find(begin(mFreeItems), end(mFreeItems), item) != end(mFreeItems)); // make sure the Item is not already in use delete item; - mItems.Remove(mFreeItems.GetLength() - 1); + mItems.erase(mItems.end() - 1); } } else // we want to add new Items @@ -64,8 +64,8 @@ namespace EMotionFX for (int32 i = 0; i < difference; ++i) { AnimGraphRefCountedData* newItem = new AnimGraphRefCountedData(); - mItems.Add(newItem); - mFreeItems.Add(newItem); + mItems.emplace_back(newItem); + mFreeItems.emplace_back(newItem); } } } @@ -75,17 +75,17 @@ namespace EMotionFX AnimGraphRefCountedData* AnimGraphRefCountedDataPool::RequestNew() { // if we have no free items left, allocate a new one - if (mFreeItems.GetLength() == 0) + if (mFreeItems.size() == 0) { AnimGraphRefCountedData* newItem = new AnimGraphRefCountedData(); - mItems.Add(newItem); + mItems.emplace_back(newItem); mMaxUsed = MCore::Max(mMaxUsed, GetNumUsedItems()); return newItem; } // request the last free item - AnimGraphRefCountedData* item = mFreeItems[mFreeItems.GetLength() - 1]; - mFreeItems.RemoveLast(); // remove it from the list of free Items + AnimGraphRefCountedData* item = mFreeItems[mFreeItems.size() - 1]; + mFreeItems.pop_back(); // remove it from the list of free Items mMaxUsed = MCore::Max(mMaxUsed, GetNumUsedItems()); return item; } @@ -94,7 +94,7 @@ namespace EMotionFX // free the item again void AnimGraphRefCountedDataPool::Free(AnimGraphRefCountedData* item) { - MCORE_ASSERT(mItems.Contains(item)); - mFreeItems.Add(item); + MCORE_ASSERT(AZStd::find(begin(mItems), end(mItems), item) != end(mItems)); + mFreeItems.emplace_back(item); } } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphRefCountedDataPool.h b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphRefCountedDataPool.h index b3b287fb37..33590766ff 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphRefCountedDataPool.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphRefCountedDataPool.h @@ -11,7 +11,7 @@ // include required headers #include "EMotionFXConfig.h" #include "AnimGraphRefCountedData.h" -#include +#include namespace EMotionFX @@ -34,15 +34,15 @@ namespace EMotionFX AnimGraphRefCountedData* RequestNew(); void Free(AnimGraphRefCountedData* item); - MCORE_INLINE uint32 GetNumFreeItems() const { return mFreeItems.GetLength(); } - MCORE_INLINE uint32 GetNumItems() const { return mItems.GetLength(); } - MCORE_INLINE uint32 GetNumUsedItems() const { return (mItems.GetLength() - mFreeItems.GetLength()); } + MCORE_INLINE size_t GetNumFreeItems() const { return mFreeItems.size(); } + MCORE_INLINE size_t GetNumItems() const { return mItems.size(); } + MCORE_INLINE size_t GetNumUsedItems() const { return (mItems.size() - mFreeItems.size()); } MCORE_INLINE uint32 GetNumMaxUsedItems() const { return mMaxUsed; } MCORE_INLINE void ResetMaxUsedItems() { mMaxUsed = 0; } private: - MCore::Array mItems; - MCore::Array mFreeItems; + AZStd::vector mItems; + AZStd::vector mFreeItems; uint32 mMaxUsed; }; } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphReferenceNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphReferenceNode.cpp index 57500b01d9..e6f6bb0985 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphReferenceNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphReferenceNode.cpp @@ -499,7 +499,7 @@ namespace EMotionFX } - void AnimGraphReferenceNode::RecursiveCollectObjects(MCore::Array& outObjects) const + void AnimGraphReferenceNode::RecursiveCollectObjects(AZStd::vector& outObjects) const { AnimGraphNode::RecursiveCollectObjects(outObjects); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphReferenceNode.h b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphReferenceNode.h index 23bb6ac138..db4dc0ea3e 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphReferenceNode.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphReferenceNode.h @@ -98,7 +98,7 @@ namespace EMotionFX void RecursiveCollectActiveNodes(AnimGraphInstance* animGraphInstance, AZStd::vector* outNodes, const AZ::TypeId& nodeType) const override; AnimGraphPose* GetMainOutputPose(AnimGraphInstance* animGraphInstance) const override; - void RecursiveCollectObjects(MCore::Array& outObjects) const override; + void RecursiveCollectObjects(AZStd::vector& outObjects) const override; void RecursiveCollectObjectsAffectedBy(AnimGraph* animGraph, AZStd::vector& outObjects) const override; bool RecursiveDetectCycles(AZStd::unordered_set& nodes) const override; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphStateMachine.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphStateMachine.cpp index 2db1d920ef..a191ae9e13 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphStateMachine.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphStateMachine.cpp @@ -1277,7 +1277,7 @@ namespace EMotionFX return result; } - void AnimGraphStateMachine::RecursiveCollectObjects(MCore::Array& outObjects) const + void AnimGraphStateMachine::RecursiveCollectObjects(AZStd::vector& outObjects) const { for (const AnimGraphStateTransition* transition : mTransitions) { diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphStateMachine.h b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphStateMachine.h index 7c0a5a14f9..8583a8a6e3 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphStateMachine.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphStateMachine.h @@ -95,7 +95,7 @@ namespace EMotionFX AnimGraphPose* GetMainOutputPose(AnimGraphInstance* animGraphInstance) const override { return GetOutputPose(animGraphInstance, OUTPUTPORT_POSE)->GetValue(); } - void RecursiveCollectObjects(MCore::Array& outObjects) const override; + void RecursiveCollectObjects(AZStd::vector& outObjects) const override; void RecursiveCollectObjectsOfType(const AZ::TypeId& objectType, AZStd::vector& outObjects) const override; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphStateTransition.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphStateTransition.cpp index 15d6f6bd3a..de3fa990bf 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphStateTransition.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphStateTransition.cpp @@ -663,14 +663,14 @@ namespace EMotionFX } // add all sub objects - void AnimGraphStateTransition::RecursiveCollectObjects(MCore::Array& outObjects) const + void AnimGraphStateTransition::RecursiveCollectObjects(AZStd::vector& outObjects) const { for (const AnimGraphTransitionCondition* condition : mConditions) { condition->RecursiveCollectObjects(outObjects); } - outObjects.Add(const_cast(this)); + outObjects.emplace_back(const_cast(this)); } // calculate the blend weight, based on the type of smoothing diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphStateTransition.h b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphStateTransition.h index 5e8d5446ef..c9347111bb 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphStateTransition.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphStateTransition.h @@ -120,7 +120,7 @@ namespace EMotionFX AnimGraphObjectData* CreateUniqueData(AnimGraphInstance* animGraphInstance) override { return aznew UniqueData(this, animGraphInstance); } void InvalidateUniqueData(AnimGraphInstance* animGraphInstance) override; - void RecursiveCollectObjects(MCore::Array& outObjects) const override; + void RecursiveCollectObjects(AZStd::vector& outObjects) const override; void ExtractMotion(AnimGraphInstance* animGraphInstance, AnimGraphRefCountedData* sourceData, Transform* outTransform, Transform* outTransformMirrored) const; void OnStartTransition(AnimGraphInstance* animGraphInstance); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/DualQuatSkinDeformer.h b/Gems/EMotionFX/Code/EMotionFX/Source/DualQuatSkinDeformer.h index 1775eb4789..b1f3387df7 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/DualQuatSkinDeformer.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/DualQuatSkinDeformer.h @@ -97,7 +97,7 @@ namespace EMotionFX * This is the number of different bones that the skinning information of the mesh where this deformer works on uses. * @result The number of bones. */ - MCORE_INLINE uint32 GetNumLocalBones() const { return static_cast(m_bones.size()); } + MCORE_INLINE size_t GetNumLocalBones() const { return m_bones.size(); } /** * Get the node number of a given local bone. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/EMotionFXManager.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/EMotionFXManager.cpp index ba81cc41b5..d58b4286b9 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/EMotionFXManager.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/EMotionFXManager.cpp @@ -107,7 +107,6 @@ namespace EMotionFX // constructor EMotionFXManager::EMotionFXManager() { - mThreadDatas.SetMemoryCategory(EMFX_MEMCATEGORY_EMOTIONFXMANAGER); // build the low version string AZStd::string lowVersionString; BuildLowVersionString(lowVersionString); @@ -174,11 +173,11 @@ namespace EMotionFX mEventManager = nullptr; // delete the thread datas - for (uint32 i = 0; i < mThreadDatas.GetLength(); ++i) + for (uint32 i = 0; i < mThreadDatas.size(); ++i) { mThreadDatas[i]->Destroy(); } - mThreadDatas.Clear(); + mThreadDatas.clear(); } @@ -477,19 +476,19 @@ namespace EMotionFX numThreads = 1; } - if (mThreadDatas.GetLength() == numThreads) + if (mThreadDatas.size() == numThreads) { return; } // get rid of old data - for (uint32 i = 0; i < mThreadDatas.GetLength(); ++i) + for (uint32 i = 0; i < mThreadDatas.size(); ++i) { mThreadDatas[i]->Destroy(); } - mThreadDatas.Clear(false); // force calling constructors again to reset everything - mThreadDatas.Resize(numThreads); + mThreadDatas.clear(); // force calling constructors again to reset everything + mThreadDatas.resize(numThreads); for (uint32 i = 0; i < numThreads; ++i) { diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/EMotionFXManager.h b/Gems/EMotionFX/Code/EMotionFX/Source/EMotionFXManager.h index 824cc95850..45bf59c94c 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/EMotionFXManager.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/EMotionFXManager.h @@ -10,7 +10,7 @@ // include the required headers #include "EMotionFXConfig.h" -#include +#include #include #include "ThreadData.h" #include "BaseObject.h" @@ -268,13 +268,13 @@ namespace EMotionFX * @param threadIndex The thread index, which must be between [0..GetNumThreads()-1]. * @return The unique thread data for this thread. */ - MCORE_INLINE ThreadData* GetThreadData(uint32 threadIndex) const { MCORE_ASSERT(threadIndex < mThreadDatas.GetLength()); return mThreadDatas[threadIndex]; } + MCORE_INLINE ThreadData* GetThreadData(uint32 threadIndex) const { MCORE_ASSERT(threadIndex < mThreadDatas.size()); return mThreadDatas[threadIndex]; } /** * Get the number of threads that are internally created. * @return The number of threads that we have internally created. */ - MCORE_INLINE uint32 GetNumThreads() const { return mThreadDatas.GetLength(); } + MCORE_INLINE size_t GetNumThreads() const { return mThreadDatas.size(); } /** * Shrink the memory pools, to reduce memory usage. @@ -354,7 +354,7 @@ namespace EMotionFX Recorder* mRecorder; /**< The recorder. */ MotionInstancePool* mMotionInstancePool; /**< The motion instance pool. */ DebugDraw* mDebugDraw; /**< The debug drawing system. */ - MCore::Array mThreadDatas; /**< The per thread data. */ + AZStd::vector mThreadDatas; /**< The per thread data. */ MCore::Distance::EUnitType mUnitType; /**< The unit type, on default it is MCore::Distance::UNITTYPE_METERS. */ float mGlobalSimulationSpeed; /**< The global simulation speed, default is 1.0. */ bool m_isInEditorMode; /**< True when the runtime requires to support an editor. Optimizations can be made if there is no need for editor support. */ diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/EventManager.h b/Gems/EMotionFX/Code/EMotionFX/Source/EventManager.h index 5f87b66388..cf47eff346 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/EventManager.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/EventManager.h @@ -11,7 +11,7 @@ // include the required headers #include "EMotionFXConfig.h" #include "BaseObject.h" -#include +#include #include #include "MemoryCategories.h" #include "MotionInstance.h" diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ChunkProcessors.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ChunkProcessors.cpp index 9f6429abd7..18ec99b435 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ChunkProcessors.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ChunkProcessors.cpp @@ -280,7 +280,7 @@ namespace EMotionFX mStringStorageSize = 0; } - const char* SharedHelperData::ReadString(MCore::Stream* file, MCore::Array* sharedData, MCore::Endian::EEndianType endianType) + const char* SharedHelperData::ReadString(MCore::Stream* file, AZStd::vector* sharedData, MCore::Endian::EEndianType endianType) { MCORE_ASSERT(file); MCORE_ASSERT(sharedData); @@ -904,9 +904,9 @@ namespace EMotionFX // read all tracks AZStd::string trackName; - MCore::Array typeStrings; - MCore::Array paramStrings; - MCore::Array mirrorTypeStrings; + AZStd::vector typeStrings; + AZStd::vector paramStrings; + AZStd::vector mirrorTypeStrings; for (uint32 t = 0; t < fileEventTable.mNumTracks; ++t) { // read the motion event table header @@ -934,9 +934,9 @@ namespace EMotionFX } // the even type and parameter strings - typeStrings.Resize(fileTrack.mNumTypeStrings); - paramStrings.Resize(fileTrack.mNumParamStrings); - mirrorTypeStrings.Resize(fileTrack.mNumMirrorTypeStrings); + typeStrings.resize(fileTrack.mNumTypeStrings); + paramStrings.resize(fileTrack.mNumParamStrings); + mirrorTypeStrings.resize(fileTrack.mNumMirrorTypeStrings); // read all type strings if (GetLogging()) diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ChunkProcessors.h b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ChunkProcessors.h index 56822c6940..66a2193b71 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ChunkProcessors.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ChunkProcessors.h @@ -9,7 +9,7 @@ #pragma once #include "../EMotionFXConfig.h" -#include +#include #include #include "../MemoryCategories.h" #include "../BaseObject.h" @@ -94,7 +94,7 @@ namespace EMotionFX * @param endianType The endian type to read the string in. * @return The actual string. */ - static const char* ReadString(MCore::Stream* file, MCore::Array* sharedData, MCore::Endian::EEndianType endianType); + static const char* ReadString(MCore::Stream* file, AZStd::vector* sharedData, MCore::Endian::EEndianType endianType); public: uint32 mFileHighVersion; /**< The high file version. For example 3 in case of v3.10. */ diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/Importer.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/Importer.cpp index 82da9ccd86..069182883c 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/Importer.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/Importer.cpp @@ -47,9 +47,6 @@ namespace EMotionFX Importer::Importer() : BaseObject() { - // set the memory category - mChunkProcessors.SetMemoryCategory(EMFX_MEMCATEGORY_IMPORTER); - // register all standard chunks RegisterStandardChunks(); @@ -63,7 +60,7 @@ namespace EMotionFX Importer::~Importer() { // remove all chunk processors - const uint32 numProcessors = mChunkProcessors.GetLength(); + const uint32 numProcessors = mChunkProcessors.size(); for (uint32 i = 0; i < numProcessors; ++i) { mChunkProcessors[i]->Destroy(); @@ -110,7 +107,6 @@ namespace EMotionFX MCore::LogError("Unsupported endian type used! (endian type = %d)", header.mEndianType); return false; } - ; // yes, it is a valid actor file! return true; @@ -150,7 +146,6 @@ namespace EMotionFX MCore::LogError("Unsupported endian type used! (endian type = %d)", header.mEndianType); return false; } - ; // yes, it is a valid motion file! return true; @@ -291,8 +286,7 @@ namespace EMotionFX MCORE_ASSERT(f->GetIsOpen()); // create the shared data - MCore::Array sharedData; - sharedData.SetMemoryCategory(EMFX_MEMCATEGORY_IMPORTER); + AZStd::vector sharedData; PrepareSharedData(sharedData); // verify if this is a valid actor file or not @@ -360,7 +354,7 @@ namespace EMotionFX // get rid of shared data ResetSharedData(sharedData); - sharedData.Clear(); + sharedData.clear(); // return the created actor return actor; @@ -461,8 +455,7 @@ namespace EMotionFX MCORE_ASSERT(f->GetIsOpen()); // create the shared data - MCore::Array sharedData; - sharedData.SetMemoryCategory(EMFX_MEMCATEGORY_IMPORTER); + AZStd::vector sharedData; PrepareSharedData(sharedData); // verify if this is a valid actor file or not @@ -513,7 +506,7 @@ namespace EMotionFX // get rid of shared data ResetSharedData(sharedData); - sharedData.Clear(); + sharedData.clear(); return motion; } @@ -671,8 +664,7 @@ namespace EMotionFX } // create the shared data - MCore::Array sharedData; - sharedData.SetMemoryCategory(EMFX_MEMCATEGORY_IMPORTER); + AZStd::vector sharedData; PrepareSharedData(sharedData); //----------------------------------------------- @@ -710,7 +702,7 @@ namespace EMotionFX // get rid of shared data ResetSharedData(sharedData); - sharedData.Clear(); + sharedData.clear(); // return the created actor return nodeMap; @@ -722,26 +714,26 @@ namespace EMotionFX void Importer::RegisterChunkProcessor(ChunkProcessor* processorToRegister) { MCORE_ASSERT(processorToRegister); - mChunkProcessors.Add(processorToRegister); + mChunkProcessors.emplace_back(processorToRegister); } // add shared data object to the importer - void Importer::AddSharedData(MCore::Array& sharedData, SharedData* data) + void Importer::AddSharedData(AZStd::vector& sharedData, SharedData* data) { MCORE_ASSERT(data); - sharedData.Add(data); + sharedData.emplace_back(data); } // search for shared data - SharedData* Importer::FindSharedData(MCore::Array* sharedDataArray, uint32 type) + SharedData* Importer::FindSharedData(AZStd::vector* sharedDataArray, uint32 type) { // for all shared data - const uint32 numSharedData = sharedDataArray->GetLength(); + const uint32 numSharedData = sharedDataArray->size(); for (uint32 i = 0; i < numSharedData; ++i) { - SharedData* sharedData = sharedDataArray->GetItem(i); + SharedData* sharedData = sharedDataArray->at(i); // check if it's the type we are searching for if (sharedData->GetType() == type) @@ -772,7 +764,7 @@ namespace EMotionFX mLogDetails = detailLoggingActive; // set the processors logging flag - const int32 numProcessors = mChunkProcessors.GetLength(); + const int32 numProcessors = mChunkProcessors.size(); for (int32 i = 0; i < numProcessors; i++) { ChunkProcessor* processor = mChunkProcessors[i]; @@ -787,7 +779,7 @@ namespace EMotionFX } - void Importer::PrepareSharedData(MCore::Array& sharedData) + void Importer::PrepareSharedData(AZStd::vector& sharedData) { // create standard shared objects AddSharedData(sharedData, SharedHelperData::Create()); @@ -795,16 +787,16 @@ namespace EMotionFX // reset shared objects so that the importer is ready for use again - void Importer::ResetSharedData(MCore::Array& sharedData) + void Importer::ResetSharedData(AZStd::vector& sharedData) { - const int32 numSharedData = sharedData.GetLength(); + const int32 numSharedData = sharedData.size(); for (int32 i = 0; i < numSharedData; i++) { SharedData* data = sharedData[i]; data->Reset(); data->Destroy(); } - sharedData.Clear(); + sharedData.clear(); } @@ -812,7 +804,7 @@ namespace EMotionFX ChunkProcessor* Importer::FindChunk(uint32 chunkID, uint32 version) const { // for all chunk processors - const uint32 numProcessors = mChunkProcessors.GetLength(); + const uint32 numProcessors = mChunkProcessors.size(); for (uint32 i = 0; i < numProcessors; ++i) { ChunkProcessor* processor = mChunkProcessors[i]; @@ -833,7 +825,7 @@ namespace EMotionFX void Importer::RegisterStandardChunks() { // reserve space for 75 chunk processors - mChunkProcessors.Reserve(75); + mChunkProcessors.reserve(75); // shared processors RegisterChunkProcessor(aznew ChunkProcessorMotionEventTrackTable()); @@ -912,12 +904,12 @@ namespace EMotionFX bool mustSkip = false; // check if we specified to ignore this chunk - if (actorSettings && actorSettings->mChunkIDsToIgnore.Contains(chunk.mChunkID)) + if (actorSettings && AZStd::find(begin(actorSettings->mChunkIDsToIgnore), end(actorSettings->mChunkIDsToIgnore), chunk.mChunkID) != end(actorSettings->mChunkIDsToIgnore)) { mustSkip = true; } - if (skelMotionSettings && skelMotionSettings->mChunkIDsToIgnore.Contains(chunk.mChunkID)) + if (skelMotionSettings && AZStd::find(begin(skelMotionSettings->mChunkIDsToIgnore), end(skelMotionSettings->mChunkIDsToIgnore), chunk.mChunkID) != end(skelMotionSettings->mChunkIDsToIgnore)) { mustSkip = true; } @@ -963,20 +955,29 @@ namespace EMotionFX void Importer::ValidateActorSettings(ActorSettings* settings) { // After atom: Make sure we are not loading the tangents and bitangents - if (!settings->mLayerIDsToIgnore.Contains(Mesh::ATTRIB_TANGENTS)) + if (AZStd::find(begin(settings->mLayerIDsToIgnore), end(settings->mLayerIDsToIgnore), Mesh::ATTRIB_TANGENTS) == end(settings->mLayerIDsToIgnore)) { - settings->mLayerIDsToIgnore.Add(Mesh::ATTRIB_TANGENTS); + settings->mLayerIDsToIgnore.emplace_back(Mesh::ATTRIB_TANGENTS); } - if (!settings->mLayerIDsToIgnore.Contains(Mesh::ATTRIB_BITANGENTS)) + if (AZStd::find(begin(settings->mLayerIDsToIgnore), end(settings->mLayerIDsToIgnore), Mesh::ATTRIB_BITANGENTS) == end(settings->mLayerIDsToIgnore)) { - settings->mLayerIDsToIgnore.Add(Mesh::ATTRIB_BITANGENTS); + settings->mLayerIDsToIgnore.emplace_back(Mesh::ATTRIB_BITANGENTS); } // make sure we load at least the position and normals and org vertex numbers - settings->mLayerIDsToIgnore.RemoveByValue(Mesh::ATTRIB_ORGVTXNUMBERS); - settings->mLayerIDsToIgnore.RemoveByValue(Mesh::ATTRIB_NORMALS); - settings->mLayerIDsToIgnore.RemoveByValue(Mesh::ATTRIB_POSITIONS); + if(const auto it = AZStd::find(begin(settings->mLayerIDsToIgnore), end(settings->mLayerIDsToIgnore), Mesh::ATTRIB_ORGVTXNUMBERS); it != end(settings->mLayerIDsToIgnore)) + { + settings->mLayerIDsToIgnore.erase(it); + } + if(const auto it = AZStd::find(begin(settings->mLayerIDsToIgnore), end(settings->mLayerIDsToIgnore), Mesh::ATTRIB_NORMALS); it != end(settings->mLayerIDsToIgnore)) + { + settings->mLayerIDsToIgnore.erase(it); + } + if(const auto it = AZStd::find(begin(settings->mLayerIDsToIgnore), end(settings->mLayerIDsToIgnore), Mesh::ATTRIB_POSITIONS); it != end(settings->mLayerIDsToIgnore)) + { + settings->mLayerIDsToIgnore.erase(it); + } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/Importer.h b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/Importer.h index 2b12f93a1a..a708e7f017 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/Importer.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/Importer.h @@ -9,7 +9,7 @@ #pragma once #include "../EMotionFXConfig.h" -#include +#include #include #include #include @@ -82,8 +82,8 @@ namespace EMotionFX bool mLoadSimulatedObjects = true; /**< Set to false if you wish to disable loading of simulated objects. */ bool mOptimizeForServer = false; /**< Set to true if you witsh to optimize this actor to be used on server. */ uint32 mThreadIndex = 0; - MCore::Array mChunkIDsToIgnore; /**< Add chunk ID's to this array. Chunks with these ID's will not be processed. */ - MCore::Array mLayerIDsToIgnore; /**< Add vertex attribute layer ID's to ignore. */ + AZStd::vector mChunkIDsToIgnore; /**< Add chunk ID's to this array. Chunks with these ID's will not be processed. */ + AZStd::vector mLayerIDsToIgnore; /**< Add vertex attribute layer ID's to ignore. */ /** * If the actor need to be optimized for server, will overwrite a few other actor settings. @@ -105,7 +105,7 @@ namespace EMotionFX bool mForceLoading = false; /**< Set to true in case you want to load the motion even if a motion with the given filename is already inside the motion manager. */ bool mLoadMotionEvents = true; /**< Set to false if you wish to disable loading of motion events. */ bool mUnitTypeConvert = true; /**< Set to false to disable automatic unit type conversion (between cm, meters, etc). On default this is enabled. */ - MCore::Array mChunkIDsToIgnore; /**< Add the ID's of the chunks you wish to ignore. */ + AZStd::vector mChunkIDsToIgnore; /**< Add the ID's of the chunks you wish to ignore. */ }; /** @@ -133,7 +133,7 @@ namespace EMotionFX Motion* mMotion = nullptr; Importer::ActorSettings* mActorSettings = nullptr; Importer::MotionSettings* mMotionSettings = nullptr; - MCore::Array* mSharedData = nullptr; + AZStd::vector* mSharedData = nullptr; MCore::Endian::EEndianType mEndianType = MCore::Endian::ENDIAN_LITTLE; NodeMap* mNodeMap = nullptr; @@ -312,7 +312,7 @@ namespace EMotionFX * @param type The shared data ID to search for. * @return A pointer to the shared data object, or nullptr when no shared data of this type has been found. */ - static SharedData* FindSharedData(MCore::Array* sharedDataArray, uint32 type); + static SharedData* FindSharedData(AZStd::vector* sharedDataArray, uint32 type); /** * Enable or disable logging. @@ -355,7 +355,7 @@ namespace EMotionFX private: - MCore::Array mChunkProcessors; /**< The registered chunk processors. */ + AZStd::vector mChunkProcessors; /**< The registered chunk processors. */ bool mLoggingActive; /**< Contains if the importer should perform logging or not or not. */ bool mLogDetails; /**< Contains if the importer should perform detail-logging or not. */ @@ -414,19 +414,19 @@ namespace EMotionFX * @param sharedData The array which holds the shared data objects. * @param data A pointer to your shared data object. */ - static void AddSharedData(MCore::Array& sharedData, SharedData* data); + static void AddSharedData(AZStd::vector& sharedData, SharedData* data); /* * Precreate the standard shared data objects. * @param sharedData The shared data array to work on. */ - static void PrepareSharedData(MCore::Array& sharedData); + static void PrepareSharedData(AZStd::vector& sharedData); /** * Reset all shared data objects. * Resetting these objects will clear/empty their internal data. */ - static void ResetSharedData(MCore::Array& sharedData); + static void ResetSharedData(AZStd::vector& sharedData); /** * Find the chunk processor which has a given ID and version number. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/KeyTrackLinearDynamic.h b/Gems/EMotionFX/Code/EMotionFX/Source/KeyTrackLinearDynamic.h index 2635e12a71..8c5c56895a 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/KeyTrackLinearDynamic.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/KeyTrackLinearDynamic.h @@ -41,22 +41,13 @@ namespace EMotionFX public: AZ_TYPE_INFO_LEGACY(EMotionFX::KeyTrackLinear, "{8C6EB52A-9720-467B-9D96-B4B967A113D1}", StorageType) - /** - * Default constructor. - */ - KeyTrackLinearDynamic(); + KeyTrackLinearDynamic() = default; /** - * Constructor. * @param nrKeys The number of keyframes which the keytrack contains (preallocates this amount of keyframes). */ KeyTrackLinearDynamic(uint32 nrKeys); - /** - * Destructor. - */ - ~KeyTrackLinearDynamic(); - static void Reflect(AZ::ReflectContext* context); /** diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/KeyTrackLinearDynamic.inl b/Gems/EMotionFX/Code/EMotionFX/Source/KeyTrackLinearDynamic.inl index b28c9973fc..94abe4d707 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/KeyTrackLinearDynamic.inl +++ b/Gems/EMotionFX/Code/EMotionFX/Source/KeyTrackLinearDynamic.inl @@ -6,13 +6,6 @@ * */ -// default constructor -template -KeyTrackLinearDynamic::KeyTrackLinearDynamic() -{ -} - - // extended constructor template KeyTrackLinearDynamic::KeyTrackLinearDynamic(uint32 nrKeys) @@ -21,13 +14,6 @@ KeyTrackLinearDynamic::KeyTrackLinearDynamic(uint32 nrK } -// destructor -template -KeyTrackLinearDynamic::~KeyTrackLinearDynamic() -{ - ClearKeys(); -} - template void KeyTrackLinearDynamic::Reflect(AZ::ReflectContext* context) { diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.cpp index 3ece1e24af..36fc898ed1 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.cpp @@ -36,11 +36,6 @@ namespace EMotionFX mIndices = nullptr; mPolyVertexCounts = nullptr; mIsCollisionMesh = false; - - // set memory categories of the arrays - mSubMeshes.SetMemoryCategory(EMFX_MEMCATEGORY_GEOMETRY_MESHES); - mVertexAttributes.SetMemoryCategory(EMFX_MEMCATEGORY_GEOMETRY_MESHES); - mSharedVertexAttributes.SetMemoryCategory(EMFX_MEMCATEGORY_GEOMETRY_MESHES); } // allocation constructor @@ -54,11 +49,6 @@ namespace EMotionFX mPolyVertexCounts = nullptr; mIsCollisionMesh = isCollisionMesh; - // set memory categories of the arrays - mSubMeshes.SetMemoryCategory(EMFX_MEMCATEGORY_GEOMETRY_MESHES); - mVertexAttributes.SetMemoryCategory(EMFX_MEMCATEGORY_GEOMETRY_MESHES); - mSharedVertexAttributes.SetMemoryCategory(EMFX_MEMCATEGORY_GEOMETRY_MESHES); - // allocate the mesh data Allocate(numVerts, numIndices, numPolygons, numOrgVerts); } @@ -384,7 +374,7 @@ namespace EMotionFX // copy all original data over the output data void Mesh::ResetToOriginalData() { - const uint32 numLayers = mVertexAttributes.GetLength(); + const uint32 numLayers = mVertexAttributes.size(); for (uint32 i = 0; i < numLayers; ++i) { mVertexAttributes[i]->ResetToOriginalData(); @@ -402,12 +392,12 @@ namespace EMotionFX RemoveAllVertexAttributeLayers(); // get rid of all sub meshes - const uint32 numSubMeshes = mSubMeshes.GetLength(); + const uint32 numSubMeshes = mSubMeshes.size(); for (uint32 i = 0; i < numSubMeshes; ++i) { mSubMeshes[i]->Destroy(); } - mSubMeshes.Clear(); + mSubMeshes.clear(); if (mIndices) { @@ -668,10 +658,10 @@ namespace EMotionFX // creates an array of pointers to bones used by this face - void Mesh::GatherBonesForFace(uint32 startIndexOfFace, MCore::Array& outBones, Actor* actor) + void Mesh::GatherBonesForFace(uint32 startIndexOfFace, AZStd::vector& outBones, Actor* actor) { // get rid of existing data - outBones.Clear(); + outBones.clear(); // try to locate the skinning attribute information SkinningInfoVertexAttributeLayer* skinningLayer = (SkinningInfoVertexAttributeLayer*)FindSharedVertexAttributeLayer(SkinningInfoVertexAttributeLayer::TYPE_ID); @@ -703,9 +693,9 @@ namespace EMotionFX Node* bone = skeleton->GetNode(skinningLayer->GetInfluence(originalVertex, n)->GetNodeNr()); // if it isn't yet in the output array with bones, add it - if (outBones.Find(bone) == MCORE_INVALIDINDEX32) + if (AZStd::find(begin(outBones), end(outBones), bone) == end(outBones)) { - outBones.Add(bone); + outBones.emplace_back(bone); } } } @@ -818,7 +808,7 @@ namespace EMotionFX void Mesh::RemoveSubMesh(uint32 nr, bool delFromMem) { SubMesh* subMesh = mSubMeshes[nr]; - mSubMeshes.Remove(nr); + mSubMeshes.erase(AZStd::next(begin(mSubMeshes), nr)); if (delFromMem) { subMesh->Destroy(); @@ -829,7 +819,7 @@ namespace EMotionFX // insert a given submesh void Mesh::InsertSubMesh(uint32 insertIndex, SubMesh* subMesh) { - mSubMeshes.Insert(insertIndex, subMesh); + mSubMeshes.emplace(AZStd::next(begin(mSubMeshes), insertIndex), subMesh); } @@ -839,7 +829,7 @@ namespace EMotionFX uint32 numLayers = 0; // check the types of all vertex attribute layers - const uint32 numAttributes = mVertexAttributes.GetLength(); + const uint32 numAttributes = mVertexAttributes.size(); for (uint32 i = 0; i < numAttributes; ++i) { if (mVertexAttributes[i]->GetType() == type) @@ -862,21 +852,21 @@ namespace EMotionFX VertexAttributeLayer* Mesh::GetSharedVertexAttributeLayer(uint32 layerNr) { - MCORE_ASSERT(layerNr < mSharedVertexAttributes.GetLength()); + MCORE_ASSERT(layerNr < mSharedVertexAttributes.size()); return mSharedVertexAttributes[layerNr]; } void Mesh::AddSharedVertexAttributeLayer(VertexAttributeLayer* layer) { - MCORE_ASSERT(mSharedVertexAttributes.Contains(layer) == false); - mSharedVertexAttributes.Add(layer); + MCORE_ASSERT(AZStd::find(begin(mSharedVertexAttributes), end(mSharedVertexAttributes), layer) == end(mSharedVertexAttributes)); + mSharedVertexAttributes.emplace_back(layer); } - uint32 Mesh::GetNumSharedVertexAttributeLayers() const + size_t Mesh::GetNumSharedVertexAttributeLayers() const { - return mSharedVertexAttributes.GetLength(); + return mSharedVertexAttributes.size(); } @@ -885,7 +875,7 @@ namespace EMotionFX uint32 layerCounter = 0; // check all vertex attributes of our first vertex, and find where the specific attribute is - const uint32 numLayers = mSharedVertexAttributes.GetLength(); + const uint32 numLayers = mSharedVertexAttributes.size(); for (uint32 i = 0; i < numLayers; ++i) { VertexAttributeLayer* layer = mSharedVertexAttributes[i]; @@ -922,10 +912,10 @@ namespace EMotionFX // delete all shared attribute layers void Mesh::RemoveAllSharedVertexAttributeLayers() { - while (mSharedVertexAttributes.GetLength()) + while (mSharedVertexAttributes.size()) { - mSharedVertexAttributes.GetLast()->Destroy(); - mSharedVertexAttributes.RemoveLast(); + mSharedVertexAttributes.back()->Destroy(); + mSharedVertexAttributes.pop_back(); } } @@ -933,29 +923,29 @@ namespace EMotionFX // remove a layer by its index void Mesh::RemoveSharedVertexAttributeLayer(uint32 layerNr) { - MCORE_ASSERT(layerNr < mSharedVertexAttributes.GetLength()); + MCORE_ASSERT(layerNr < mSharedVertexAttributes.size()); mSharedVertexAttributes[layerNr]->Destroy(); - mSharedVertexAttributes.Remove(layerNr); + mSharedVertexAttributes.erase(AZStd::next(begin(mSharedVertexAttributes), layerNr)); } - uint32 Mesh::GetNumVertexAttributeLayers() const + size_t Mesh::GetNumVertexAttributeLayers() const { - return mVertexAttributes.GetLength(); + return mVertexAttributes.size(); } VertexAttributeLayer* Mesh::GetVertexAttributeLayer(uint32 layerNr) { - MCORE_ASSERT(layerNr < mVertexAttributes.GetLength()); + MCORE_ASSERT(layerNr < mVertexAttributes.size()); return mVertexAttributes[layerNr]; } void Mesh::AddVertexAttributeLayer(VertexAttributeLayer* layer) { - MCORE_ASSERT(mVertexAttributes.Contains(layer) == false); - mVertexAttributes.Add(layer); + MCORE_ASSERT(AZStd::find(begin(mVertexAttributes), end(mVertexAttributes), layer) == end(mVertexAttributes)); + mVertexAttributes.emplace_back(layer); } @@ -965,7 +955,7 @@ namespace EMotionFX uint32 layerCounter = 0; // check all vertex attributes of our first vertex, and find where the specific attribute is - const uint32 numLayers = mVertexAttributes.GetLength(); + const uint32 numLayers = mVertexAttributes.size(); for (uint32 i = 0; i < numLayers; ++i) { VertexAttributeLayer* layer = mVertexAttributes[i]; @@ -989,7 +979,7 @@ namespace EMotionFX uint32 Mesh::FindVertexAttributeLayerNumberByName(uint32 layerTypeID, const char* name) const { // check all vertex attributes of our first vertex, and find where the specific attribute is - const uint32 numLayers = mVertexAttributes.GetLength(); + const uint32 numLayers = mVertexAttributes.size(); for (uint32 i = 0; i < numLayers; ++i) { VertexAttributeLayer* layer = mVertexAttributes[i]; @@ -1035,19 +1025,19 @@ namespace EMotionFX void Mesh::RemoveAllVertexAttributeLayers() { - while (mVertexAttributes.GetLength()) + while (mVertexAttributes.size()) { - mVertexAttributes.GetLast()->Destroy(); - mVertexAttributes.RemoveLast(); + mVertexAttributes.back()->Destroy(); + mVertexAttributes.pop_back(); } } void Mesh::RemoveVertexAttributeLayer(uint32 layerNr) { - MCORE_ASSERT(layerNr < mVertexAttributes.GetLength()); + MCORE_ASSERT(layerNr < mVertexAttributes.size()); mVertexAttributes[layerNr]->Destroy(); - mVertexAttributes.Remove(layerNr); + mVertexAttributes.erase(AZStd::next(begin(mVertexAttributes), layerNr)); } @@ -1064,24 +1054,24 @@ namespace EMotionFX // copy the submesh data uint32 i; - const uint32 numSubMeshes = mSubMeshes.GetLength(); - clone->mSubMeshes.Resize(numSubMeshes); + const uint32 numSubMeshes = mSubMeshes.size(); + clone->mSubMeshes.resize(numSubMeshes); for (i = 0; i < numSubMeshes; ++i) { clone->mSubMeshes[i] = mSubMeshes[i]->Clone(clone); } // clone the shared vertex attributes - const uint32 numSharedAttributes = mSharedVertexAttributes.GetLength(); - clone->mSharedVertexAttributes.Resize(numSharedAttributes); + const uint32 numSharedAttributes = mSharedVertexAttributes.size(); + clone->mSharedVertexAttributes.resize(numSharedAttributes); for (i = 0; i < numSharedAttributes; ++i) { clone->mSharedVertexAttributes[i] = mSharedVertexAttributes[i]->Clone(); } // clone the non-shared vertex attributes - const uint32 numAttributes = mVertexAttributes.GetLength(); - clone->mVertexAttributes.Resize(numAttributes); + const uint32 numAttributes = mVertexAttributes.size(); + clone->mVertexAttributes.resize(numAttributes); for (i = 0; i < numAttributes; ++i) { clone->mVertexAttributes[i] = mVertexAttributes[i]->Clone(); @@ -1105,7 +1095,7 @@ namespace EMotionFX } // swap all vertex attribute layers - const uint32 numLayers = mVertexAttributes.GetLength(); + const uint32 numLayers = mVertexAttributes.size(); for (uint32 i = 0; i < numLayers; ++i) { mVertexAttributes[i]->SwapAttributes(vertexA, vertexB); @@ -1229,7 +1219,7 @@ namespace EMotionFX for (uint32 w = 0; w < numVertsToRemove; ++w) { // adjust all submesh start index offsets changed - for (uint32 s = 0; s < mSubMeshes.GetLength();) + for (uint32 s = 0; s < mSubMeshes.size();) { SubMesh* subMesh = mSubMeshes[s]; @@ -1249,7 +1239,7 @@ namespace EMotionFX // remove the submesh if it's empty if (subMesh->GetNumVertices() == 0 && removeEmptySubMeshes) { - mSubMeshes.Remove(s); + mSubMeshes.erase(AZStd::next(begin(mSubMeshes), s)); } else { @@ -1283,7 +1273,7 @@ namespace EMotionFX uint32 numRemoved = 0; // for all the submeshes - for (uint32 i = 0; i < mSubMeshes.GetLength();) + for (uint32 i = 0; i < mSubMeshes.size();) { SubMesh* subMesh = mSubMeshes[i]; @@ -1305,7 +1295,7 @@ namespace EMotionFX // remove or skip if (mustRemove) { - mSubMeshes.Remove(i); + mSubMeshes.erase(AZStd::next(begin(mSubMeshes), i)); numRemoved++; } else @@ -1966,7 +1956,7 @@ namespace EMotionFX void Mesh::ReserveVertexAttributeLayerSpace(uint32 numLayers) { - mVertexAttributes.Reserve(numLayers); + mVertexAttributes.reserve(numLayers); } @@ -2003,7 +1993,7 @@ namespace EMotionFX // find by name uint32 Mesh::FindVertexAttributeLayerIndexByName(const char* name) const { - const uint32 numLayers = mVertexAttributes.GetLength(); + const uint32 numLayers = mVertexAttributes.size(); for (uint32 i = 0; i < numLayers; ++i) { if (mVertexAttributes[i]->GetNameString() == name) @@ -2019,7 +2009,7 @@ namespace EMotionFX // find by name as string uint32 Mesh::FindVertexAttributeLayerIndexByNameString(const AZStd::string& name) const { - const uint32 numLayers = mVertexAttributes.GetLength(); + const uint32 numLayers = mVertexAttributes.size(); for (uint32 i = 0; i < numLayers; ++i) { if (mVertexAttributes[i]->GetNameString() == name) @@ -2035,7 +2025,7 @@ namespace EMotionFX // find by name ID uint32 Mesh::FindVertexAttributeLayerIndexByNameID(uint32 nameID) const { - const uint32 numLayers = mVertexAttributes.GetLength(); + const uint32 numLayers = mVertexAttributes.size(); for (uint32 i = 0; i < numLayers; ++i) { if (mVertexAttributes[i]->GetNameID() == nameID) @@ -2051,7 +2041,7 @@ namespace EMotionFX // find by name uint32 Mesh::FindSharedVertexAttributeLayerIndexByName(const char* name) const { - const uint32 numLayers = mSharedVertexAttributes.GetLength(); + const uint32 numLayers = mSharedVertexAttributes.size(); for (uint32 i = 0; i < numLayers; ++i) { if (mSharedVertexAttributes[i]->GetNameString() == name) @@ -2067,7 +2057,7 @@ namespace EMotionFX // find by name as string uint32 Mesh::FindSharedVertexAttributeLayerIndexByNameString(const AZStd::string& name) const { - const uint32 numLayers = mSharedVertexAttributes.GetLength(); + const uint32 numLayers = mSharedVertexAttributes.size(); for (uint32 i = 0; i < numLayers; ++i) { if (mSharedVertexAttributes[i]->GetNameString() == name) @@ -2083,7 +2073,7 @@ namespace EMotionFX // find by name ID uint32 Mesh::FindSharedVertexAttributeLayerIndexByNameID(uint32 nameID) const { - const uint32 numLayers = mSharedVertexAttributes.GetLength(); + const uint32 numLayers = mSharedVertexAttributes.size(); for (uint32 i = 0; i < numLayers; ++i) { if (mSharedVertexAttributes[i]->GetNameID() == nameID) diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.h b/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.h index cb929dc7db..a0a99f2961 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.h @@ -18,7 +18,7 @@ #include "Transform.h" #include -#include +#include #include #include @@ -235,7 +235,7 @@ namespace EMotionFX * Get the number of sub meshes currently in the mesh. * @result The number of sub meshes. */ - MCORE_INLINE uint32 GetNumSubMeshes() const; + MCORE_INLINE size_t GetNumSubMeshes() const; /** * Get a given SubMesh. @@ -257,7 +257,7 @@ namespace EMotionFX * Do not forget to use SetSubMesh() to initialize all submeshes! * @param numSubMeshes The number of submeshes to use. */ - MCORE_INLINE void SetNumSubMeshes(uint32 numSubMeshes) { mSubMeshes.Resize(numSubMeshes); } + MCORE_INLINE void SetNumSubMeshes(uint32 numSubMeshes) { mSubMeshes.resize(numSubMeshes); } /** * Remove a given submesh from this mesh. @@ -293,7 +293,7 @@ namespace EMotionFX * This value is the same for all shared vertices. * @result The number of shared vertex attributes for every vertex. */ - uint32 GetNumSharedVertexAttributeLayers() const; + size_t GetNumSharedVertexAttributeLayers() const; /** * Find and return the shared vertex attribute layer of a given type. @@ -338,7 +338,7 @@ namespace EMotionFX * This value is the same for all vertices. * @result The number of vertex attributes for every vertex. */ - uint32 GetNumVertexAttributeLayers() const; + size_t GetNumVertexAttributeLayers() const; /** * Get the vertex attribute data of a given layer. @@ -447,7 +447,7 @@ namespace EMotionFX * @param outBones The array to store the pointers to the bones in. Any existing array contents will be cleared when it enters the method. * @param actor The actor to search the bones in. */ - void GatherBonesForFace(uint32 startIndexOfFace, MCore::Array& outBones, Actor* actor); + void GatherBonesForFace(uint32 startIndexOfFace, AZStd::vector& outBones, Actor* actor); /** * Calculates the maximum number of bone influences for a given face. @@ -653,7 +653,7 @@ namespace EMotionFX protected: - MCore::Array mSubMeshes; /**< The collection of sub meshes. */ + AZStd::vector mSubMeshes; /**< The collection of sub meshes. */ uint32* mIndices; /**< The array of indices, which define the faces. */ uint8* mPolyVertexCounts; /**< The number of vertices for each polygon, where the length of this array equals the number of polygons. */ uint32 mNumPolygons; /**< The number of polygons in this mesh. */ @@ -666,13 +666,13 @@ namespace EMotionFX * The array of shared vertex attribute layers. * The number of attributes in each shared layer will be equal to the value returned by Mesh::GetNumOrgVertices(). */ - MCore::Array< VertexAttributeLayer* > mSharedVertexAttributes; + AZStd::vector< VertexAttributeLayer* > mSharedVertexAttributes; /** * The array of non-shared vertex attribute layers. * The number of attributes in each shared layer will be equal to the value returned by Mesh::GetNumVertices(). */ - MCore::Array< VertexAttributeLayer* > mVertexAttributes; + AZStd::vector< VertexAttributeLayer* > mVertexAttributes; /** * Default constructor. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.inl b/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.inl index 850d9d1f17..4ee52eaf19 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.inl +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.inl @@ -24,22 +24,22 @@ MCORE_INLINE uint32 Mesh::GetNumPolygons() const } -MCORE_INLINE uint32 Mesh::GetNumSubMeshes() const +MCORE_INLINE size_t Mesh::GetNumSubMeshes() const { - return mSubMeshes.GetLength(); + return mSubMeshes.size(); } MCORE_INLINE SubMesh* Mesh::GetSubMesh(uint32 nr) const { - MCORE_ASSERT(nr < mSubMeshes.GetLength()); + MCORE_ASSERT(nr < mSubMeshes.size()); return mSubMeshes[nr]; } MCORE_INLINE void Mesh::AddSubMesh(SubMesh* subMesh) { - mSubMeshes.Add(subMesh); + mSubMeshes.emplace_back(subMesh); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MeshDeformerStack.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MeshDeformerStack.cpp index c50aca4325..c4fae4d3bb 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MeshDeformerStack.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MeshDeformerStack.cpp @@ -22,20 +22,19 @@ namespace EMotionFX : BaseObject() { mMesh = mesh; - mDeformers.SetMemoryCategory(EMFX_MEMCATEGORY_GEOMETRY_DEFORMERS); } // destructor MeshDeformerStack::~MeshDeformerStack() { - const uint32 numDeformers = mDeformers.GetLength(); + const uint32 numDeformers = mDeformers.size(); for (uint32 i = 0; i < numDeformers; ++i) { mDeformers[i]->Destroy(); } - mDeformers.Clear(); + mDeformers.clear(); // reset mMesh = nullptr; @@ -60,7 +59,7 @@ namespace EMotionFX void MeshDeformerStack::Update(ActorInstance* actorInstance, Node* node, float timeDelta, bool forceUpdateDisabledDeformers) { // if we have deformers in the stack - const uint32 numDeformers = mDeformers.GetLength(); + const uint32 numDeformers = mDeformers.size(); if (numDeformers > 0) { bool firstEnabled = true; @@ -92,7 +91,7 @@ namespace EMotionFX { bool resetDone = false; // if we have deformers in the stack - const uint32 numDeformers = mDeformers.GetLength(); + const uint32 numDeformers = mDeformers.size(); // iterate through the deformers and update them for (uint32 i = 0; i < numDeformers; ++i) { @@ -118,7 +117,7 @@ namespace EMotionFX void MeshDeformerStack::ReinitializeDeformers(Actor* actor, Node* node, uint32 lodLevel) { // if we have deformers in the stack - const uint32 numDeformers = mDeformers.GetLength(); + const uint32 numDeformers = mDeformers.size(); // iterate through the deformers and reinitialize them for (uint32 i = 0; i < numDeformers; ++i) @@ -131,21 +130,26 @@ namespace EMotionFX void MeshDeformerStack::AddDeformer(MeshDeformer* meshDeformer) { // add the object into the stack - mDeformers.Add(meshDeformer); + mDeformers.emplace_back(meshDeformer); } void MeshDeformerStack::InsertDeformer(uint32 pos, MeshDeformer* meshDeformer) { // add the object into the stack - mDeformers.Insert(pos, meshDeformer); + mDeformers.emplace(AZStd::next(begin(mDeformers), pos), meshDeformer); } bool MeshDeformerStack::RemoveDeformer(MeshDeformer* meshDeformer) { // delete the object - return mDeformers.RemoveByValue(meshDeformer); + if (const auto it = AZStd::find(begin(mDeformers), end(mDeformers), meshDeformer); it != end(mDeformers)) + { + mDeformers.erase(it); + return true; + } + return false; } @@ -155,7 +159,7 @@ namespace EMotionFX MeshDeformerStack* newStack = aznew MeshDeformerStack(mesh); // clone all deformers - const uint32 numDeformers = mDeformers.GetLength(); + const uint32 numDeformers = mDeformers.size(); for (uint32 i = 0; i < numDeformers; ++i) { newStack->AddDeformer(mDeformers[i]->Clone(mesh)); @@ -166,15 +170,15 @@ namespace EMotionFX } - uint32 MeshDeformerStack::GetNumDeformers() const + size_t MeshDeformerStack::GetNumDeformers() const { - return mDeformers.GetLength(); + return mDeformers.size(); } MeshDeformer* MeshDeformerStack::GetDeformer(uint32 nr) const { - MCORE_ASSERT(nr < mDeformers.GetLength()); + MCORE_ASSERT(nr < mDeformers.size()); return mDeformers[nr]; } @@ -183,7 +187,7 @@ namespace EMotionFX uint32 MeshDeformerStack::RemoveAllDeformersByType(uint32 deformerTypeID) { uint32 numRemoved = 0; - for (uint32 a = 0; a < mDeformers.GetLength(); ) + for (uint32 a = 0; a < mDeformers.size(); ) { MeshDeformer* deformer = mDeformers[a]; if (deformer->GetType() == deformerTypeID) @@ -205,7 +209,7 @@ namespace EMotionFX // remove all the deformers void MeshDeformerStack::RemoveAllDeformers() { - for (uint32 i = 0; i < mDeformers.GetLength(); ++i) + for (uint32 i = 0; i < mDeformers.size(); ++i) { // retrieve the current deformer MeshDeformer* deformer = mDeformers[i]; @@ -221,7 +225,7 @@ namespace EMotionFX uint32 MeshDeformerStack::EnableAllDeformersByType(uint32 deformerTypeID, bool enabled) { uint32 numChanged = 0; - const uint32 numDeformers = mDeformers.GetLength(); + const uint32 numDeformers = mDeformers.size(); for (uint32 a = 0; a < numDeformers; ++a) { MeshDeformer* deformer = mDeformers[a]; @@ -239,7 +243,7 @@ namespace EMotionFX // check if the stack contains a deformer of a specified type bool MeshDeformerStack::CheckIfHasDeformerOfType(uint32 deformerTypeID) const { - const uint32 numDeformers = mDeformers.GetLength(); + const uint32 numDeformers = mDeformers.size(); for (uint32 a = 0; a < numDeformers; ++a) { if (mDeformers[a]->GetType() == deformerTypeID) @@ -258,7 +262,7 @@ namespace EMotionFX uint32 count = 0; // for all deformers - const uint32 numDeformers = mDeformers.GetLength(); + const uint32 numDeformers = mDeformers.size(); for (uint32 a = 0; a < numDeformers; ++a) { // if this is a deformer of the type we search for diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MeshDeformerStack.h b/Gems/EMotionFX/Code/EMotionFX/Source/MeshDeformerStack.h index 902eecf0d2..020e2b2b75 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MeshDeformerStack.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MeshDeformerStack.h @@ -12,7 +12,7 @@ #include "EMotionFXConfig.h" #include "MeshDeformer.h" #include "BaseObject.h" -#include +#include namespace EMotionFX @@ -134,7 +134,7 @@ namespace EMotionFX * Get the number of deformers in the stack. * @result The number of deformers in the stack. */ - uint32 GetNumDeformers() const; + size_t GetNumDeformers() const; /** * Get a given deformer. @@ -159,7 +159,7 @@ namespace EMotionFX MeshDeformer* FindDeformerByType(uint32 deformerTypeID, uint32 occurrence = 0) const; private: - MCore::Array mDeformers; /**< The stack of deformers. */ + AZStd::vector mDeformers; /**< The stack of deformers. */ Mesh* mMesh; /**< Pointer to the mesh to which the modifier stack belongs to.*/ /** diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MorphMeshDeformer.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MorphMeshDeformer.cpp index c609f908d1..41b1475927 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MorphMeshDeformer.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MorphMeshDeformer.cpp @@ -26,7 +26,6 @@ namespace EMotionFX MorphMeshDeformer::MorphMeshDeformer(Mesh* mesh) : MeshDeformer(mesh) { - mDeformPasses.SetMemoryCategory(EMFX_MEMCATEGORY_GEOMETRY_DEFORMERS); } @@ -64,8 +63,8 @@ namespace EMotionFX MorphMeshDeformer* result = aznew MorphMeshDeformer(mesh); // copy the deform passes - result->mDeformPasses.Resize(mDeformPasses.GetLength()); - for (uint32 i = 0; i < mDeformPasses.GetLength(); ++i) + result->mDeformPasses.resize(mDeformPasses.size()); + for (uint32 i = 0; i < mDeformPasses.size(); ++i) { DeformPass& pass = result->mDeformPasses[i]; pass.mDeformDataNr = mDeformPasses[i].mDeformDataNr; @@ -89,7 +88,7 @@ namespace EMotionFX const uint32 lodLevel = actorInstance->GetLODLevel(); // apply all deform passes - const uint32 numPasses = mDeformPasses.GetLength(); + const uint32 numPasses = mDeformPasses.size(); for (uint32 i = 0; i < numPasses; ++i) { // find the morph target @@ -198,7 +197,7 @@ namespace EMotionFX void MorphMeshDeformer::Reinitialize(Actor* actor, Node* node, uint32 lodLevel) { // clear the deform passes, but don't free the currently allocated/reserved memory - mDeformPasses.Clear(false); + mDeformPasses.clear(); // get the morph setup MorphSetup* morphSetup = actor->GetMorphSetup(lodLevel); @@ -219,8 +218,8 @@ namespace EMotionFX if (deformData->mNodeIndex == node->GetNodeIndex()) { // add an empty deform pass and fill it afterwards - mDeformPasses.AddEmpty(); - const uint32 deformPassIndex = mDeformPasses.GetLength() - 1; + mDeformPasses.emplace_back(); + const uint32 deformPassIndex = mDeformPasses.size() - 1; mDeformPasses[deformPassIndex].mDeformDataNr = j; mDeformPasses[deformPassIndex].mMorphTarget = morphTarget; } @@ -231,18 +230,18 @@ namespace EMotionFX void MorphMeshDeformer::AddDeformPass(const DeformPass& deformPass) { - mDeformPasses.Add(deformPass); + mDeformPasses.emplace_back(deformPass); } - uint32 MorphMeshDeformer::GetNumDeformPasses() const + size_t MorphMeshDeformer::GetNumDeformPasses() const { - return mDeformPasses.GetLength(); + return mDeformPasses.size(); } void MorphMeshDeformer::ReserveDeformPasses(uint32 numPasses) { - mDeformPasses.Reserve(numPasses); + mDeformPasses.reserve(numPasses); } } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MorphMeshDeformer.h b/Gems/EMotionFX/Code/EMotionFX/Source/MorphMeshDeformer.h index 6cbf4cae5b..ae56ecc96d 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MorphMeshDeformer.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MorphMeshDeformer.h @@ -122,7 +122,7 @@ namespace EMotionFX * Get the number of deform passes. * @result The number of deform passes. */ - uint32 GetNumDeformPasses() const; + size_t GetNumDeformPasses() const; /** * Pre-allocate space for the deform passes. @@ -132,7 +132,7 @@ namespace EMotionFX void ReserveDeformPasses(uint32 numPasses); private: - MCore::Array mDeformPasses; /**< The deform passes. Each pass basically represents a morph target. */ + AZStd::vector mDeformPasses; /**< The deform passes. Each pass basically represents a morph target. */ /** * Default constructor. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MorphSetup.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MorphSetup.cpp index 0c9f4f8cd7..386f73ae23 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MorphSetup.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MorphSetup.cpp @@ -10,6 +10,7 @@ #include "MorphSetup.h" #include "MorphTarget.h" #include +#include #include namespace EMotionFX @@ -17,14 +18,6 @@ namespace EMotionFX AZ_CLASS_ALLOCATOR_IMPL(MorphSetup, DeformerAllocator, 0) - // constructor - MorphSetup::MorphSetup() - : BaseObject() - { - mMorphTargets.SetMemoryCategory(EMFX_MEMCATEGORY_GEOMETRY_PMORPHTARGETS); - } - - // destructor MorphSetup::~MorphSetup() { @@ -42,7 +35,7 @@ namespace EMotionFX // add a morph target void MorphSetup::AddMorphTarget(MorphTarget* morphTarget) { - mMorphTargets.Add(morphTarget); + mMorphTargets.emplace_back(morphTarget); } @@ -54,14 +47,18 @@ namespace EMotionFX mMorphTargets[nr]->Destroy(); } - mMorphTargets.Remove(nr); + mMorphTargets.erase(AZStd::next(begin(mMorphTargets), nr)); } // remove a morph target void MorphSetup::RemoveMorphTarget(MorphTarget* morphTarget, bool delFromMem) { - mMorphTargets.RemoveByValue(morphTarget); + const auto* foundMorphTarget = AZStd::find(begin(mMorphTargets), end(mMorphTargets), morphTarget); + if (foundMorphTarget != end(mMorphTargets)) + { + mMorphTargets.erase(foundMorphTarget); + } if (delFromMem) { @@ -73,13 +70,13 @@ namespace EMotionFX // remove all morph targets void MorphSetup::RemoveAllMorphTargets() { - const uint32 numTargets = mMorphTargets.GetLength(); + const uint32 numTargets = mMorphTargets.size(); for (uint32 i = 0; i < numTargets; ++i) { mMorphTargets[i]->Destroy(); } - mMorphTargets.Clear(); + mMorphTargets.clear(); } @@ -87,7 +84,7 @@ namespace EMotionFX MorphTarget* MorphSetup::FindMorphTargetByID(uint32 id) const { // linear search, and check IDs - const uint32 numTargets = mMorphTargets.GetLength(); + const uint32 numTargets = mMorphTargets.size(); for (uint32 i = 0; i < numTargets; ++i) { if (mMorphTargets[i]->GetID() == id) @@ -105,7 +102,7 @@ namespace EMotionFX uint32 MorphSetup::FindMorphTargetNumberByID(uint32 id) const { // linear search, and check IDs - const uint32 numTargets = mMorphTargets.GetLength(); + const uint32 numTargets = mMorphTargets.size(); for (uint32 i = 0; i < numTargets; ++i) { if (mMorphTargets[i]->GetID() == id) @@ -121,7 +118,7 @@ namespace EMotionFX uint32 MorphSetup::FindMorphTargetIndexByName(const char* name) const { - const uint32 numTargets = mMorphTargets.GetLength(); + const uint32 numTargets = mMorphTargets.size(); for (uint32 i = 0; i < numTargets; ++i) { if (mMorphTargets[i]->GetNameString() == name) @@ -136,7 +133,7 @@ namespace EMotionFX uint32 MorphSetup::FindMorphTargetIndexByNameNoCase(const char* name) const { - const uint32 numTargets = mMorphTargets.GetLength(); + const uint32 numTargets = mMorphTargets.size(); for (uint32 i = 0; i < numTargets; ++i) { if (AzFramework::StringFunc::Equal(mMorphTargets[i]->GetNameString().c_str(), name, false /* no case */)) @@ -152,7 +149,7 @@ namespace EMotionFX // find a morph target by name (case sensitive) MorphTarget* MorphSetup::FindMorphTargetByName(const char* name) const { - const uint32 numTargets = mMorphTargets.GetLength(); + const uint32 numTargets = mMorphTargets.size(); for (uint32 i = 0; i < numTargets; ++i) { if (mMorphTargets[i]->GetNameString() == name) @@ -168,7 +165,7 @@ namespace EMotionFX // find a morph target by name (not case sensitive) MorphTarget* MorphSetup::FindMorphTargetByNameNoCase(const char* name) const { - const uint32 numTargets = mMorphTargets.GetLength(); + const uint32 numTargets = mMorphTargets.size(); for (uint32 i = 0; i < numTargets; ++i) { if (AzFramework::StringFunc::Equal(mMorphTargets[i]->GetNameString().c_str(), name, false /* no case */)) @@ -188,7 +185,7 @@ namespace EMotionFX MorphSetup* clone = MorphSetup::Create(); // clone all morph targets - const uint32 numMorphTargets = mMorphTargets.GetLength(); + const uint32 numMorphTargets = mMorphTargets.size(); for (uint32 i = 0; i < numMorphTargets; ++i) { clone->AddMorphTarget(mMorphTargets[i]->Clone()); @@ -201,7 +198,7 @@ namespace EMotionFX void MorphSetup::ReserveMorphTargets(uint32 numMorphTargets) { - mMorphTargets.Reserve(numMorphTargets); + mMorphTargets.reserve(numMorphTargets); } @@ -215,7 +212,7 @@ namespace EMotionFX } // scale the morph targets - const uint32 numMorphTargets = mMorphTargets.GetLength(); + const uint32 numMorphTargets = mMorphTargets.size(); for (uint32 i = 0; i < numMorphTargets; ++i) { mMorphTargets[i]->Scale(scaleFactor); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MorphSetup.h b/Gems/EMotionFX/Code/EMotionFX/Source/MorphSetup.h index 6a19a0247c..c7c04ae636 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MorphSetup.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MorphSetup.h @@ -40,7 +40,7 @@ namespace EMotionFX * Get the number of morph targets inside this morph setup. * @result The number of morph targets. */ - MCORE_INLINE uint32 GetNumMorphTargets() const { return mMorphTargets.GetLength(); } + MCORE_INLINE size_t GetNumMorphTargets() const { return mMorphTargets.size(); } /** * Get a given morph target. @@ -137,12 +137,12 @@ namespace EMotionFX protected: - MCore::Array mMorphTargets; /**< The collection of morph targets. */ + AZStd::vector mMorphTargets; /**< The collection of morph targets. */ /** * The constructor. */ - MorphSetup(); + MorphSetup() = default; /** * The destructor. Automatically removes all morph targets from memory. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MorphSetupInstance.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MorphSetupInstance.cpp index f27051d7e2..456056d00f 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MorphSetupInstance.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MorphSetupInstance.cpp @@ -20,7 +20,6 @@ namespace EMotionFX MorphSetupInstance::MorphSetupInstance() : BaseObject() { - mMorphTargets.SetMemoryCategory(EMFX_MEMCATEGORY_GEOMETRY_PMORPHTARGETS); Init(nullptr); } @@ -63,7 +62,7 @@ namespace EMotionFX // allocate the number of morph targets const uint32 numMorphTargets = morphSetup->GetNumMorphTargets(); - mMorphTargets.Resize(numMorphTargets); + mMorphTargets.resize(numMorphTargets); // update the ID values for (uint32 i = 0; i < numMorphTargets; ++i) @@ -77,7 +76,7 @@ namespace EMotionFX uint32 MorphSetupInstance::FindMorphTargetIndexByID(uint32 id) const { // try to locate the morph target with the given ID - const uint32 numTargets = mMorphTargets.GetLength(); + const uint32 numTargets = mMorphTargets.size(); for (uint32 i = 0; i < numTargets; ++i) { if (mMorphTargets[i].GetID() == id) diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MorphSetupInstance.h b/Gems/EMotionFX/Code/EMotionFX/Source/MorphSetupInstance.h index 7cc0c0dbd0..e597cb7a63 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MorphSetupInstance.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MorphSetupInstance.h @@ -11,7 +11,7 @@ // include the required headers #include "EMotionFXConfig.h" #include "BaseObject.h" -#include +#include namespace EMotionFX @@ -123,7 +123,7 @@ namespace EMotionFX * This should always be equal to the number of morph targets in the highest detail. * @result The number of morph targets. */ - MCORE_INLINE uint32 GetNumMorphTargets() const { return mMorphTargets.GetLength(); } + MCORE_INLINE size_t GetNumMorphTargets() const { return mMorphTargets.size(); } /** * Get a specific morph target. @@ -149,7 +149,7 @@ namespace EMotionFX MorphTarget* FindMorphTargetByID(uint32 id); private: - MCore::Array mMorphTargets; /**< The unique morph target information. */ + AZStd::vector mMorphTargets; /**< The unique morph target information. */ /** * The default constructor. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MorphTarget.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MorphTarget.cpp index 0a62253464..3bb84881ff 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MorphTarget.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MorphTarget.cpp @@ -11,6 +11,7 @@ #include "Node.h" #include "MorphTarget.h" #include +#include #include namespace EMotionFX @@ -31,12 +32,6 @@ namespace EMotionFX } - // destructor - MorphTarget::~MorphTarget() - { - } - - // convert the given phoneme name to a phoneme set MorphTarget::EPhonemeSet MorphTarget::FindPhonemeSet(const AZStd::string& phonemeName) { diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MorphTarget.h b/Gems/EMotionFX/Code/EMotionFX/Source/MorphTarget.h index 726f7d81bc..829d6f5be6 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MorphTarget.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MorphTarget.h @@ -286,10 +286,5 @@ namespace EMotionFX * @param name The unique name of the morph target. */ MorphTarget(const char* name); - - /** - * The destructor. - */ - virtual ~MorphTarget(); }; } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MorphTargetStandard.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MorphTargetStandard.cpp index 6d2dc08d4b..d1c23ba04d 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MorphTargetStandard.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MorphTargetStandard.cpp @@ -177,7 +177,7 @@ namespace EMotionFX const float normalizedWeight = CalcNormalizedWeight(newWeight); // convert in range of 0..1 // calculate the new transformations for all nodes of this morph target - const uint32 numTransforms = mTransforms.GetLength(); + const uint32 numTransforms = mTransforms.size(); for (uint32 i = 0; i < numTransforms; ++i) { // if this is the node that gets modified by this transform @@ -214,7 +214,7 @@ namespace EMotionFX } // check all transforms - const uint32 numTransforms = mTransforms.GetLength(); + const uint32 numTransforms = mTransforms.size(); for (uint32 i = 0; i < numTransforms; ++i) { if (mTransforms[i].mNodeIndex == nodeIndex) @@ -239,7 +239,7 @@ namespace EMotionFX Transform newTransform; // calculate the new transformations for all nodes of this morph target - const uint32 numTransforms = mTransforms.GetLength(); + const uint32 numTransforms = mTransforms.size(); for (uint32 i = 0; i < numTransforms; ++i) { // try to find the node @@ -277,9 +277,9 @@ namespace EMotionFX } } - uint32 MorphTargetStandard::GetNumDeformDatas() const + size_t MorphTargetStandard::GetNumDeformDatas() const { - return static_cast(mDeformDatas.size()); + return mDeformDatas.size(); } MorphTargetStandard::DeformData* MorphTargetStandard::GetDeformData(uint32 nr) const @@ -294,12 +294,13 @@ namespace EMotionFX void MorphTargetStandard::AddTransformation(const Transformation& transform) { - mTransforms.Add(transform); + mTransforms.emplace_back(transform); } - uint32 MorphTargetStandard::GetNumTransformations() const + // get the number of transformations in this morph target + size_t MorphTargetStandard::GetNumTransformations() const { - return mTransforms.GetLength(); + return mTransforms.size(); } MorphTargetStandard::Transformation& MorphTargetStandard::GetTransformation(uint32 nr) @@ -321,7 +322,7 @@ namespace EMotionFX // now clone the deform datas clone->mDeformDatas.resize(mDeformDatas.size()); - for (size_t i = 0; i < mDeformDatas.size(); ++i) + for (uint32 i = 0; i < mDeformDatas.size(); ++i) { clone->mDeformDatas[i] = mDeformDatas[i]->Clone(); } @@ -404,7 +405,7 @@ namespace EMotionFX // pre-allocate memory for the transformations void MorphTargetStandard::ReserveTransformations(uint32 numTransforms) { - mTransforms.Reserve(numTransforms); + mTransforms.reserve(numTransforms); } void MorphTargetStandard::RemoveDeformData(uint32 index, bool delFromMem) @@ -419,7 +420,7 @@ namespace EMotionFX void MorphTargetStandard::RemoveTransformation(uint32 index) { - mTransforms.Remove(index); + mTransforms.erase(AZStd::next(begin(mTransforms), index)); } @@ -433,7 +434,7 @@ namespace EMotionFX } // scale the transformations - const uint32 numTransformations = mTransforms.GetLength(); + const uint32 numTransformations = mTransforms.size(); for (uint32 i = 0; i < numTransformations; ++i) { Transformation& transform = mTransforms[i]; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MorphTargetStandard.h b/Gems/EMotionFX/Code/EMotionFX/Source/MorphTargetStandard.h index 2d8a20ec11..cda878efbb 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MorphTargetStandard.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MorphTargetStandard.h @@ -175,7 +175,7 @@ namespace EMotionFX * Get the number of deform data objects. * @result The number of deform data objects. */ - uint32 GetNumDeformDatas() const; + size_t GetNumDeformDatas() const; /** * Get a given deform data object. @@ -200,7 +200,7 @@ namespace EMotionFX * Get the number of transformations which are part of this bones morph target. * @result The number of tranformations. */ - uint32 GetNumTransformations() const; + size_t GetNumTransformations() const; /** * Get a given transformation and it's corresponding node id to which the transformation belongs to. @@ -260,7 +260,7 @@ namespace EMotionFX void Scale(float scaleFactor) override; private: - MCore::Array mTransforms; /**< The relative transformations for the given nodes, in local space. The rotation however is absolute. */ + AZStd::vector mTransforms; /**< The relative transformations for the given nodes, in local space. The rotation however is absolute. */ AZStd::vector mDeformDatas; /**< The deformation data objects. */ /** diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MotionGroup.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MotionGroup.cpp deleted file mode 100644 index 8b3a874c3b..0000000000 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MotionGroup.cpp +++ /dev/null @@ -1,277 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -// include required headers -#include "MotionGroup.h" -#include "MotionInstance.h" -#include "ActorInstance.h" -#include "EMotionFXManager.h" -#include "MotionInstancePool.h" -#include "AnimGraphPose.h" -#include - - -namespace EMotionFX -{ - AZ_CLASS_ALLOCATOR_IMPL(MotionGroup, MotionAllocator, 0) - - - // default constructor - MotionGroup::MotionGroup() - : BaseObject() - { - mParentMotionInstance = nullptr; - } - - - // extended constructor - MotionGroup::MotionGroup(MotionInstance* parentMotionInstance) - : BaseObject() - { - LinkToMotionInstance(parentMotionInstance); - } - - - // destructor - MotionGroup::~MotionGroup() - { - RemoveAllMotionInstances(); - } - - - // creation - MotionGroup* MotionGroup::Create() - { - return aznew MotionGroup(); - } - - - // creation - MotionGroup* MotionGroup::Create(MotionInstance* parentMotionInstance) - { - return aznew MotionGroup(parentMotionInstance); - } - - - // link to a motion instance - void MotionGroup::LinkToMotionInstance(MotionInstance* parentMotionInstance) - { - mParentMotionInstance = parentMotionInstance; - } - - - // add a motion to the group - MotionInstance* MotionGroup::AddMotion(Motion* motion, PlayBackInfo* playInfo, uint32 startNodeIndex) - { - MCORE_ASSERT(mParentMotionInstance); // use LinkToMotionInstance before - - // create the new motion instance - MotionInstance* newInstance = GetMotionInstancePool().RequestNew(motion, mParentMotionInstance->GetActorInstance()); - - // initialize the motion instance settings - if (playInfo == nullptr) // if no playinfo specified, use default playback settings - { - PlayBackInfo info; - newInstance->InitFromPlayBackInfo(info); - } - else - { - newInstance->InitFromPlayBackInfo(*playInfo); - } - - // add it to the motion instance array - mMotionInstances.Add(newInstance); - - return newInstance; - } - - - // remove all motion instances from the group and from memory - void MotionGroup::RemoveAllMotionInstances() - { - // remove all motion instances from memory - const uint32 numInstances = mMotionInstances.GetLength(); - for (uint32 i = 0; i < numInstances; ++i) - { - GetMotionInstancePool().Free(mMotionInstances[i]); - } - - mMotionInstances.Clear(); - } - - - // remove a given motion by its motion instance - void MotionGroup::RemoveMotionInstance(MotionInstance* instance) - { - if (mMotionInstances.RemoveByValue(instance)) - { - GetMotionInstancePool().Free(instance); - } - } - - - // remove all motion instances using a given motion - void MotionGroup::RemoveMotion(Motion* motion) - { - // for all the motion instances - for (uint32 i = 0; i < mMotionInstances.GetLength();) - { - // if this motion instance uses the given motion - if (mMotionInstances[i]->GetMotion() == motion) - { - // remove it from memory and from the array - GetMotionInstancePool().Free(mMotionInstances[i]); - mMotionInstances.Remove(i); - } - else - { - i++; - } - } - } - - - // remove a motion instance by its index - void MotionGroup::RemoveMotionInstance(uint32 index) - { - MCORE_ASSERT(index < mMotionInstances.GetLength()); - - // remove it from memory and from the array - GetMotionInstancePool().Free(mMotionInstances[index]); - mMotionInstances.Remove(index); - } - - - // update the motion instances - void MotionGroup::Update(float timePassed) - { - // update the motion instances - const uint32 numInstances = mMotionInstances.GetLength(); - for (uint32 i = 0; i < numInstances; ++i) - { - mMotionInstances[i]->Update(timePassed); - } - } - - - // perform the blending and output it in the outPose buffer - void MotionGroup::Output(const Pose* inPose, Pose* outPose) - { - uint32 i; - - // calculate the total weight - float totalWeight = 0.0f; - const uint32 numInstances = mMotionInstances.GetLength(); - for (i = 0; i < numInstances; ++i) - { - totalWeight += mMotionInstances[i]->GetWeight(); - } - - // calculate the inverse of the total weight so that we can replace divides by multiplies, which is faster - float invTotalWeight; - if (totalWeight < 0.0001f) - { - invTotalWeight = 0.0f; - } - else - { - invTotalWeight = 1.0f / totalWeight; - } - - const ActorInstance* actorInstance = inPose->GetActorInstance(); - const uint32 threadIndex = actorInstance->GetThreadIndex(); - AnimGraphPosePool& posePool = GetEMotionFX().GetThreadData(threadIndex)->GetPosePool(); - AnimGraphPose* groupAnimGraphPose = posePool.RequestPose(actorInstance); - - // get the group blend pose and make sure it's big enough - Pose* groupBlendPose = &groupAnimGraphPose->GetPose();//mParentMotionInstance->GetActorInstance()->GetActor()->GetGroupBlendPose(); - MCORE_ASSERT(groupBlendPose->GetNumTransforms() == inPose->GetNumTransforms()); - - // blend using the normalized weights - for (i = 0; i < numInstances; ++i) - { - // calculate the normalized weight - const float normalizedWeight = mMotionInstances[i]->GetWeight() * invTotalWeight; - - // output the motion output into the group blend buffer - mMotionInstances[i]->GetMotion()->Update(inPose, groupBlendPose, mMotionInstances[i]); - - // if it's the first motion instance in the group - if (i == 0) - { - // blend all transforms - // TODO: use only enabled nodes - const uint32 numTransforms = outPose->GetNumTransforms(); - for (uint32 t = 0; t < numTransforms; ++t) - { - Transform& transform = groupBlendPose->GetLocalSpaceTransformDirect(t); - Transform& outTransform = outPose->GetLocalSpaceTransformDirect(t); - transform.mRotation.Normalize(); - - EMFX_SCALECODE - ( - //transform.mScaleRotation.Normalize(); - outTransform.mScale = transform.mScale * normalizedWeight; - //outTransform.mScaleRotation = transform.mScaleRotation * normalizedWeight; - ) - - outTransform.mPosition = transform.mPosition * normalizedWeight; - outTransform.mRotation = transform.mRotation * normalizedWeight; - } - } - else - { - // blend all transforms - // TODO: use only enabled nodes - const uint32 numTransforms = outPose->GetNumTransforms(); - for (uint32 t = 0; t < numTransforms; ++t) - { - Transform& transform = groupBlendPose->GetLocalSpaceTransformDirect(t); - Transform& outTransform = outPose->GetLocalSpaceTransformDirect(t); - - outTransform.mPosition += transform.mPosition * normalizedWeight; - - EMFX_SCALECODE - ( - outTransform.mScale += transform.mScale * normalizedWeight; - - // make sure we use the correct hemisphere - //if (outTransform.mScaleRotation.Dot( transform.mScaleRotation ) < 0.0f) - //transform.mScaleRotation = -transform.mScaleRotation; - - //outTransform.mScaleRotation += transform.mScaleRotation * normalizedWeight; - ) - - // make sure we use the correct hemisphere - if (outTransform.mRotation.Dot(transform.mRotation) < 0.0f) - { - transform.mRotation = -transform.mRotation; - } - - outTransform.mRotation += transform.mRotation * normalizedWeight; - } - } - } // for all motion instances in the group - - // normalize the quaternions - const uint32 numTransforms = outPose->GetNumTransforms(); - for (uint32 t = 0; t < numTransforms; ++t) - { - Transform& outTransform = outPose->GetLocalSpaceTransformDirect(t); - outTransform.mRotation.Normalize(); - - //EMFX_SCALECODE - //( - //outTransform.mScaleRotation.Normalize(); - //) - } - - // free the pose - posePool.FreePose(groupAnimGraphPose); - } -} // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MotionInstance.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MotionInstance.cpp index bbadff74f2..292aef9d54 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MotionInstance.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MotionInstance.cpp @@ -819,7 +819,7 @@ namespace EMotionFX } // calculate a world space transformation for a given node by sampling the motion at a given time - void MotionInstance::CalcGlobalTransform(const MCore::Array& hierarchyPath, float timeValue, Transform* outTransform) const + void MotionInstance::CalcGlobalTransform(const AZStd::vector& hierarchyPath, float timeValue, Transform* outTransform) const { Actor* actor = m_actorInstance->GetActor(); Skeleton* skeleton = actor->GetSkeleton(); @@ -829,7 +829,7 @@ namespace EMotionFX outTransform->Identity(); // iterate from root towards the node (so backwards in the array) - for (int32 i = hierarchyPath.GetLength() - 1; i >= 0; --i) + for (int32 i = hierarchyPath.size() - 1; i >= 0; --i) { // get the current node index const AZ::u32 nodeIndex = hierarchyPath[i]; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MotionInstance.h b/Gems/EMotionFX/Code/EMotionFX/Source/MotionInstance.h index 5c7ed822e3..d0f2d1d3fb 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MotionInstance.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MotionInstance.h @@ -821,7 +821,7 @@ namespace EMotionFX void CalcRelativeTransform(Node* rootNode, float curTime, float oldTime, Transform* outTransform) const; bool ExtractMotion(Transform& outTrajectoryDelta); - void CalcGlobalTransform(const MCore::Array& hierarchyPath, float timeValue, Transform* outTransform) const; + void CalcGlobalTransform(const AZStd::vector& hierarchyPath, float timeValue, Transform* outTransform) const; void ResetTimes(); AZ_DEPRECATED(void CalcNewTimeAfterUpdate(float timePassed, float* outNewTime) const, "MotionInstance::CalcNewTimeAfterUpdate has been deprecated, please use MotionInstance::CalcPlayStateAfterUpdate(timeDelta).m_currentTime instead."); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MotionInstancePool.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MotionInstancePool.cpp index 0277843cf9..f2abc5f5de 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MotionInstancePool.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MotionInstancePool.cpp @@ -42,8 +42,6 @@ namespace EMotionFX // constructor MotionInstancePool::Pool::Pool() { - mFreeList.SetMemoryCategory(EMFX_MEMCATEGORY_MOTIONINSTANCEPOOL); - mSubPools.SetMemoryCategory(EMFX_MEMCATEGORY_MOTIONINSTANCEPOOL); mPoolType = POOLTYPE_DYNAMIC; mData = nullptr; mNumInstances = 0; @@ -59,7 +57,7 @@ namespace EMotionFX { MCore::Free(mData); mData = nullptr; - mFreeList.Clear(); + mFreeList.clear(); } else if (mPoolType == POOLTYPE_DYNAMIC) @@ -67,14 +65,14 @@ namespace EMotionFX MCORE_ASSERT(mData == nullptr); // delete all subpools - const uint32 numSubPools = mSubPools.GetLength(); + const uint32 numSubPools = mSubPools.size(); for (uint32 s = 0; s < numSubPools; ++s) { delete mSubPools[s]; } - mSubPools.Clear(); + mSubPools.clear(); - mFreeList.Clear(); + mFreeList.clear(); } else { @@ -142,7 +140,7 @@ namespace EMotionFX if (poolType == POOLTYPE_STATIC) { mPool->mData = (uint8*)MCore::Allocate(numInitialInstances * sizeof(MotionInstance), EMFX_MEMCATEGORY_MOTIONINSTANCEPOOL);// alloc space - mPool->mFreeList.ResizeFast(numInitialInstances); + mPool->mFreeList.resize_no_construct(numInitialInstances); for (uint32 i = 0; i < numInitialInstances; ++i) { void* memLocation = (void*)(mPool->mData + i * sizeof(MotionInstance)); @@ -153,20 +151,20 @@ namespace EMotionFX else // if we have a dynamic pool if (poolType == POOLTYPE_DYNAMIC) { - mPool->mSubPools.Reserve(32); + mPool->mSubPools.reserve(32); SubPool* subPool = new SubPool(); subPool->mData = (uint8*)MCore::Allocate(numInitialInstances * sizeof(MotionInstance), EMFX_MEMCATEGORY_MOTIONINSTANCEPOOL);// alloc space subPool->mNumInstances = numInitialInstances; - mPool->mFreeList.ResizeFast(numInitialInstances); + mPool->mFreeList.resize_no_construct(numInitialInstances); for (uint32 i = 0; i < numInitialInstances; ++i) { mPool->mFreeList[i].mAddress = (void*)(subPool->mData + i * sizeof(MotionInstance)); mPool->mFreeList[i].mSubPool = subPool; } - mPool->mSubPools.Add(subPool); + mPool->mSubPools.emplace_back(subPool); } else { @@ -186,9 +184,9 @@ namespace EMotionFX } // if there is are free items left - if (mPool->mFreeList.GetLength() > 0) + if (mPool->mFreeList.size() > 0) { - const MemLocation& location = mPool->mFreeList.GetLast(); + const MemLocation& location = mPool->mFreeList.back(); MotionInstance* result = MotionInstance::Create(location.mAddress, motion, actorInstance); if (location.mSubPool) @@ -197,7 +195,7 @@ namespace EMotionFX } result->SetSubPool(location.mSubPool); - mPool->mFreeList.RemoveLast(); // remove it from the free list + mPool->mFreeList.pop_back(); // remove it from the free list mPool->mNumUsedInstances++; return result; } @@ -212,14 +210,14 @@ namespace EMotionFX subPool->mData = (uint8*)MCore::Allocate(numInstances * sizeof(MotionInstance), EMFX_MEMCATEGORY_MOTIONINSTANCEPOOL);// alloc space subPool->mNumInstances = numInstances; - const uint32 startIndex = mPool->mFreeList.GetLength(); + const uint32 startIndex = mPool->mFreeList.size(); //mPool->mFreeList.Reserve( numInstances * 2 ); - if (mPool->mFreeList.GetMaxLength() < mPool->mNumInstances) + if (mPool->mFreeList.capacity() < mPool->mNumInstances) { - mPool->mFreeList.Reserve(mPool->mNumInstances + mPool->mFreeList.GetMaxLength() / 2); + mPool->mFreeList.reserve(mPool->mNumInstances + mPool->mFreeList.capacity() / 2); } - mPool->mFreeList.ResizeFast(startIndex + numInstances); + mPool->mFreeList.resize_no_construct(startIndex + numInstances); for (uint32 i = 0; i < numInstances; ++i) { void* memAddress = (void*)(subPool->mData + i * sizeof(MotionInstance)); @@ -227,16 +225,16 @@ namespace EMotionFX mPool->mFreeList[i + startIndex].mSubPool = subPool; } - mPool->mSubPools.Add(subPool); + mPool->mSubPools.emplace_back(subPool); - const MemLocation& location = mPool->mFreeList.GetLast(); + const MemLocation& location = mPool->mFreeList.back(); MotionInstance* result = MotionInstance::Create(location.mAddress, motion, actorInstance); if (location.mSubPool) { location.mSubPool->mNumInUse++; } result->SetSubPool(location.mSubPool); - mPool->mFreeList.RemoveLast(); // remove it from the free list + mPool->mFreeList.pop_back(); // remove it from the free list mPool->mNumUsedInstances++; return result; } @@ -276,9 +274,9 @@ namespace EMotionFX motionInstance->GetSubPool()->mNumInUse--; } - mPool->mFreeList.AddEmpty(); - mPool->mFreeList.GetLast().mAddress = motionInstance; - mPool->mFreeList.GetLast().mSubPool = motionInstance->GetSubPool(); + mPool->mFreeList.emplace_back(); + mPool->mFreeList.back().mAddress = motionInstance; + mPool->mFreeList.back().mSubPool = motionInstance->GetSubPool(); mPool->mNumUsedInstances--; motionInstance->DecreaseReferenceCount(); @@ -292,7 +290,7 @@ namespace EMotionFX Lock(); MCore::LogInfo("EMotionFX::MotionInstancePool::LogMemoryStats() - Logging motion instance pool info"); - const uint32 numFree = mPool->mFreeList.GetLength(); + const uint32 numFree = mPool->mFreeList.size(); uint32 numUsed = mPool->mNumUsedInstances; uint32 memUsage = 0; uint32 usedMemUsage = 0; @@ -320,12 +318,12 @@ namespace EMotionFX totalUsedInstancesMemUsage += usedMemUsage; totalMemUsage += memUsage; totalMemUsage += sizeof(Pool); - totalMemUsage += mPool->mFreeList.CalcMemoryUsage(false); + totalMemUsage += mPool->mFreeList.capacity() * sizeof(decltype(mPool->mFreeList)::value_type); MCore::LogInfo("Pool:"); if (mPool->mPoolType == POOLTYPE_DYNAMIC) { - MCore::LogInfo(" - Num SubPools: %d", mPool->mSubPools.GetLength()); + MCore::LogInfo(" - Num SubPools: %d", mPool->mSubPools.size()); } MCore::LogInfo(" - Num Instances: %d", mPool->mNumInstances); MCore::LogInfo(" - Num Free: %d", numFree); @@ -377,17 +375,17 @@ namespace EMotionFX { Lock(); - for (uint32 i = 0; i < mPool->mSubPools.GetLength(); ) + for (uint32 i = 0; i < mPool->mSubPools.size(); ) { SubPool* subPool = mPool->mSubPools[i]; if (subPool->mNumInUse == 0) { // remove all free allocations - for (uint32 a = 0; a < mPool->mFreeList.GetLength(); ) + for (uint32 a = 0; a < mPool->mFreeList.size(); ) { if (mPool->mFreeList[a].mSubPool == subPool) { - mPool->mFreeList.Remove(a); + mPool->mFreeList.erase(AZStd::next(begin(mPool->mFreeList), a)); } else { @@ -396,7 +394,7 @@ namespace EMotionFX } mPool->mNumInstances -= subPool->mNumInstances; - mPool->mSubPools.Remove(i); + mPool->mSubPools.erase(AZStd::next(begin(mPool->mSubPools), i)); delete subPool; } else @@ -405,11 +403,11 @@ namespace EMotionFX } } - mPool->mSubPools.Shrink(); + mPool->mSubPools.shrink_to_fit(); //mPool->mFreeList.Shrink(); - if ((mPool->mFreeList.GetMaxLength() - mPool->mFreeList.GetLength()) > 4096) + if ((mPool->mFreeList.capacity() - mPool->mFreeList.size()) > 4096) { - mPool->mFreeList.ReserveExact(mPool->mFreeList.GetLength() + 4096); + mPool->mFreeList.reserve(mPool->mFreeList.size() + 4096); } Unlock(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MotionInstancePool.h b/Gems/EMotionFX/Code/EMotionFX/Source/MotionInstancePool.h index 0fd658915e..8cb675bb08 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MotionInstancePool.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MotionInstancePool.h @@ -11,7 +11,7 @@ // include the required headers #include "EMotionFXConfig.h" #include "BaseObject.h" -#include +#include #include @@ -91,8 +91,8 @@ namespace EMotionFX uint32 mNumInstances; uint32 mNumUsedInstances; uint32 mSubPoolSize; - MCore::Array mFreeList; - MCore::Array mSubPools; + AZStd::vector mFreeList; + AZStd::vector mSubPools; EPoolType mPoolType; }; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MotionLayerSystem.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MotionLayerSystem.cpp index 14e6b582b4..9cda792890 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MotionLayerSystem.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MotionLayerSystem.cpp @@ -22,8 +22,6 @@ namespace EMotionFX MotionLayerSystem::MotionLayerSystem(ActorInstance* actorInstance) : MotionSystem(actorInstance) { - mLayerPasses.SetMemoryCategory(EMFX_MEMCATEGORY_MOTIONS_MOTIONSYSTEMS); - // set the motion based actor repositioning layer pass mRepositioningPass = RepositioningLayerPass::Create(this); } @@ -50,7 +48,7 @@ namespace EMotionFX void MotionLayerSystem::RemoveAllLayerPasses(bool delFromMem) { // delete all layer passes - const uint32 numLayerPasses = mLayerPasses.GetLength(); + const uint32 numLayerPasses = mLayerPasses.size(); for (uint32 i = 0; i < numLayerPasses; ++i) { if (delFromMem) @@ -59,7 +57,7 @@ namespace EMotionFX } } - mLayerPasses.Clear(); + mLayerPasses.clear(); } @@ -67,23 +65,23 @@ namespace EMotionFX void MotionLayerSystem::StartMotion(MotionInstance* motion, PlayBackInfo* info) { // check if we have any motions playing already - const uint32 numMotionInstances = mMotionInstances.GetLength(); + const uint32 numMotionInstances = mMotionInstances.size(); if (numMotionInstances > 0) { // find the right location in the motion instance array to insert this motion instance uint32 insertPos = FindInsertPos(motion->GetPriorityLevel()); if (insertPos != MCORE_INVALIDINDEX32) { - mMotionInstances.Insert(insertPos, motion); + mMotionInstances.emplace(AZStd::next(begin(mMotionInstances), insertPos), motion); } else { - mMotionInstances.Add(motion); + mMotionInstances.emplace_back(motion); } } else // no motions are playing, so just add it { - mMotionInstances.Add(motion); + mMotionInstances.emplace_back(motion); } // trigger an event @@ -101,7 +99,7 @@ namespace EMotionFX // find the location where to insert a new motion with a given priority uint32 MotionLayerSystem::FindInsertPos(uint32 priorityLevel) const { - const uint32 numInstances = mMotionInstances.GetLength(); + const uint32 numInstances = mMotionInstances.size(); for (uint32 i = 0; i < numInstances; ++i) { if (mMotionInstances[i]->GetPriorityLevel() <= priorityLevel) @@ -127,7 +125,7 @@ namespace EMotionFX mMotionQueue->Update(); // process all layer passes - const uint32 numPasses = mLayerPasses.GetLength(); + const uint32 numPasses = mLayerPasses.size(); for (uint32 i = 0; i < numPasses; ++i) { mLayerPasses[i]->Process(); @@ -153,7 +151,7 @@ namespace EMotionFX // update the motion tree void MotionLayerSystem::UpdateMotionTree() { - for (uint32 i = 0; i < mMotionInstances.GetLength(); ++i) + for (uint32 i = 0; i < mMotionInstances.size(); ++i) { MotionInstance* source = mMotionInstances[i]; @@ -235,7 +233,7 @@ namespace EMotionFX if (source->GetCanOverwrite()) { // remove all motions that got overwritten by the current one - const uint32 numToRemove = mMotionInstances.GetLength() - (i + 1); + const uint32 numToRemove = mMotionInstances.size() - (i + 1); for (uint32 a = 0; a < numToRemove; ++a) { RemoveMotionInstance(mMotionInstances[i + 1]); @@ -253,7 +251,7 @@ namespace EMotionFX uint32 numRemoved = 0; // start from the bottom up - for (uint32 i = mMotionInstances.GetLength() - 1; i != MCORE_INVALIDINDEX32;) + for (uint32 i = mMotionInstances.size() - 1; i != MCORE_INVALIDINDEX32;) { MotionInstance* curInstance = mMotionInstances[i]; @@ -276,7 +274,7 @@ namespace EMotionFX MotionInstance* MotionLayerSystem::FindFirstNonMixingMotionInstance() const { // if there aren't any motion instances, return nullptr - const uint32 numInstances = mMotionInstances.GetLength(); + const uint32 numInstances = mMotionInstances.size(); if (numInstances == 0) { return nullptr; @@ -306,7 +304,7 @@ namespace EMotionFX Pose* tempActorPose = &tempAnimGraphPose->GetPose(); - const uint32 numMotionInstances = mMotionInstances.GetLength(); + const uint32 numMotionInstances = mMotionInstances.size(); if (numMotionInstances > 0) { if (numMotionInstances > 1) @@ -396,14 +394,14 @@ namespace EMotionFX // add a new pass void MotionLayerSystem::AddLayerPass(LayerPass* newPass) { - mLayerPasses.Add(newPass); + mLayerPasses.emplace_back(newPass); } // get the number of layer passes - uint32 MotionLayerSystem::GetNumLayerPasses() const + size_t MotionLayerSystem::GetNumLayerPasses() const { - return mLayerPasses.GetLength(); + return mLayerPasses.size(); } @@ -415,14 +413,17 @@ namespace EMotionFX mLayerPasses[nr]->Destroy(); } - mLayerPasses.Remove(nr); + mLayerPasses.erase(AZStd::next(begin(mLayerPasses), nr)); } // remove a given pass void MotionLayerSystem::RemoveLayerPass(LayerPass* pass, bool delFromMem) { - mLayerPasses.RemoveByValue(pass); + if (const auto it = AZStd::find(begin(mLayerPasses), end(mLayerPasses), pass); it != end(mLayerPasses)) + { + mLayerPasses.erase(it); + } if (delFromMem) { @@ -434,7 +435,7 @@ namespace EMotionFX // insert a layer pass at a given position void MotionLayerSystem::InsertLayerPass(uint32 insertPos, LayerPass* pass) { - mLayerPasses.Insert(insertPos, pass); + mLayerPasses.emplace(AZStd::next(begin(mLayerPasses), insertPos), pass); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MotionLayerSystem.h b/Gems/EMotionFX/Code/EMotionFX/Source/MotionLayerSystem.h index ff4761d49c..e207f48fd5 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MotionLayerSystem.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MotionLayerSystem.h @@ -140,7 +140,7 @@ namespace EMotionFX * Get the number of layer passes currently added to this motion layer system. * @result The number of layer passes. */ - uint32 GetNumLayerPasses() const; + size_t GetNumLayerPasses() const; /** * Remove a given layer pass by index. @@ -179,7 +179,7 @@ namespace EMotionFX private: - MCore::Array mLayerPasses; /**< The layer passes. */ + AZStd::vector mLayerPasses; /**< The layer passes. */ RepositioningLayerPass* mRepositioningPass; /**< The motion based actor repositioning layer pass. */ /** diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MotionManager.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MotionManager.cpp index 13ac1956fa..b193c58175 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MotionManager.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MotionManager.cpp @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include @@ -42,11 +42,8 @@ namespace EMotionFX MotionManager::MotionManager() : BaseObject() { - mMotions.SetMemoryCategory(EMFX_MEMCATEGORY_MOTIONS_MOTIONMANAGER); - mMotionSets.SetMemoryCategory(EMFX_MEMCATEGORY_MOTIONS_MOTIONMANAGER); - // reserve space for 400 motions - mMotions.Reserve(400); + mMotions.reserve(400); m_motionDataFactory = aznew MotionDataFactory(); } @@ -69,13 +66,13 @@ namespace EMotionFX if (delFromMemory) { // destroy all motion sets, they will internally call RemoveMotionSetWithoutLock(this) in their destructor - while (mMotionSets.GetLength() > 0) + while (mMotionSets.size() > 0) { delete mMotionSets[0]; } // destroy all motions, they will internally call RemoveMotionWithoutLock(this) in their destructor - while (mMotions.GetLength() > 0) + while (mMotions.size() > 0) { mMotions[0]->Destroy(); } @@ -84,12 +81,12 @@ namespace EMotionFX { // wait with execution until we can set the lock mSetLock.Lock(); - mMotionSets.Clear(); + mMotionSets.clear(); mSetLock.Unlock(); // clear the arrays without destroying the memory of the entries mLock.Lock(); - mMotions.Clear(); + mMotions.clear(); mLock.Unlock(); } } @@ -99,7 +96,7 @@ namespace EMotionFX Motion* MotionManager::FindMotionByName(const char* motionName, bool isTool) const { // get the number of motions and iterate through them - const uint32 numMotions = mMotions.GetLength(); + const uint32 numMotions = mMotions.size(); for (uint32 i = 0; i < numMotions; ++i) { if (mMotions[i]->GetIsOwnedByRuntime() == isTool) @@ -122,7 +119,7 @@ namespace EMotionFX Motion* MotionManager::FindMotionByFileName(const char* fileName, bool isTool) const { // get the number of motions and iterate through them - const uint32 numMotions = mMotions.GetLength(); + const uint32 numMotions = mMotions.size(); for (uint32 i = 0; i < numMotions; ++i) { if (mMotions[i]->GetIsOwnedByRuntime() == isTool) @@ -145,7 +142,7 @@ namespace EMotionFX MotionSet* MotionManager::FindMotionSetByFileName(const char* fileName, bool isTool) const { // get the number of motion sets and iterate through them - const uint32 numMotionSets = mMotionSets.GetLength(); + const uint32 numMotionSets = mMotionSets.size(); for (uint32 i = 0; i < numMotionSets; ++i) { MotionSet* motionSet = mMotionSets[i]; @@ -169,7 +166,7 @@ namespace EMotionFX MotionSet* MotionManager::FindMotionSetByName(const char* name, bool isOwnedByRuntime) const { // get the number of motion sets and iterate through them - const uint32 numMotionSets = mMotionSets.GetLength(); + const uint32 numMotionSets = mMotionSets.size(); for (uint32 i = 0; i < numMotionSets; ++i) { MotionSet* motionSet = mMotionSets[i]; @@ -192,7 +189,7 @@ namespace EMotionFX uint32 MotionManager::FindMotionIndexByName(const char* motionName, bool isTool) const { // get the number of motions and iterate through them - const uint32 numMotions = mMotions.GetLength(); + const uint32 numMotions = mMotions.size(); for (uint32 i = 0; i < numMotions; ++i) { if (mMotions[i]->GetIsOwnedByRuntime() == isTool) @@ -215,7 +212,7 @@ namespace EMotionFX uint32 MotionManager::FindMotionSetIndexByName(const char* name, bool isTool) const { // get the number of motions and iterate through them - const uint32 numMotionSets = mMotionSets.GetLength(); + const uint32 numMotionSets = mMotionSets.size(); for (uint32 i = 0; i < numMotionSets; ++i) { MotionSet* motionSet = mMotionSets[i]; @@ -240,7 +237,7 @@ namespace EMotionFX uint32 MotionManager::FindMotionIndexByID(uint32 id) const { // get the number of motions and iterate through them - const uint32 numMotions = mMotions.GetLength(); + const uint32 numMotions = mMotions.size(); for (uint32 i = 0; i < numMotions; ++i) { if (mMotions[i]->GetID() == id) @@ -257,7 +254,7 @@ namespace EMotionFX uint32 MotionManager::FindMotionSetIndexByID(uint32 id) const { // get the number of motion sets and iterate through them - const uint32 numMotionSets = mMotionSets.GetLength(); + const uint32 numMotionSets = mMotionSets.size(); for (uint32 i = 0; i < numMotionSets; ++i) { // compare the motion names @@ -275,7 +272,7 @@ namespace EMotionFX Motion* MotionManager::FindMotionByID(uint32 id) const { // get the number of motions and iterate through them - const uint32 numMotions = mMotions.GetLength(); + const uint32 numMotions = mMotions.size(); for (uint32 i = 0; i < numMotions; ++i) { if (mMotions[i]->GetID() == id) @@ -292,7 +289,7 @@ namespace EMotionFX MotionSet* MotionManager::FindMotionSetByID(uint32 id) const { // get the number of motion sets and iterate through them - const uint32 numMotionSets = mMotionSets.GetLength(); + const uint32 numMotionSets = mMotionSets.size(); for (uint32 i = 0; i < numMotionSets; ++i) { if (mMotionSets[i]->GetID() == id) @@ -309,7 +306,7 @@ namespace EMotionFX uint32 MotionManager::FindMotionSetIndex(MotionSet* motionSet) const { // get the number of motion sets and iterate through them - const uint32 numMotionSets = mMotionSets.GetLength(); + const uint32 numMotionSets = mMotionSets.size(); for (uint32 i = 0; i < numMotionSets; ++i) { if (mMotionSets[i] == motionSet) @@ -326,7 +323,7 @@ namespace EMotionFX uint32 MotionManager::FindMotionIndex(Motion* motion) const { // get the number of motions and iterate through them - const uint32 numMotions = mMotions.GetLength(); + const uint32 numMotions = mMotions.size(); for (uint32 i = 0; i < numMotions; ++i) { // compare the motions @@ -345,7 +342,7 @@ namespace EMotionFX { // wait with execution until we can set the lock mLock.Lock(); - mMotions.Add(motion); + mMotions.emplace_back(motion); mLock.Unlock(); } @@ -386,7 +383,7 @@ namespace EMotionFX uint32 MotionManager::FindMotionIndexByFileName(const char* fileName, bool isTool) const { // get the number of motions and iterate through them - const uint32 numMotions = mMotions.GetLength(); + const uint32 numMotions = mMotions.size(); for (uint32 i = 0; i < numMotions; ++i) { if (mMotions[i]->GetIsOwnedByRuntime() == isTool) @@ -494,7 +491,7 @@ namespace EMotionFX } // Reset all motion entries in the motion sets of the current motion. - const uint32 numMotionSets = mMotionSets.GetLength(); + const uint32 numMotionSets = mMotionSets.size(); for (i = 0; i < numMotionSets; ++i) { MotionSet* motionSet = mMotionSets[i]; @@ -525,11 +522,11 @@ namespace EMotionFX // which unregisters the motion from the motion manager motion->SetAutoUnregister(false); motion->Destroy(); - mMotions.Remove(index); // only remove the motion from the motion manager without destroying its memory + mMotions.erase(AZStd::next(begin(mMotions), index)); // only remove the motion from the motion manager without destroying its memory } else { - mMotions.Remove(index); // only remove the motion from the motion manager without destroying its memory + mMotions.erase(AZStd::next(begin(mMotions), index)); // only remove the motion from the motion manager without destroying its memory } return true; @@ -540,7 +537,7 @@ namespace EMotionFX void MotionManager::AddMotionSet(MotionSet* motionSet) { MCore::LockGuard lock(mLock); - mMotionSets.Add(motionSet); + mMotionSets.emplace_back(motionSet); } @@ -578,7 +575,7 @@ namespace EMotionFX delete motionSet; } - mMotionSets.Remove(index); + mMotionSets.erase(AZStd::next(begin(mMotionSets), index)); return true; } @@ -606,7 +603,7 @@ namespace EMotionFX uint32 result = 0; // get the number of motion sets and iterate through them - const uint32 numMotionSets = mMotionSets.GetLength(); + const uint32 numMotionSets = mMotionSets.size(); for (uint32 i = 0; i < numMotionSets; ++i) { // sum up the root motion sets @@ -626,7 +623,7 @@ namespace EMotionFX uint32 currentIndex = 0; // get the number of motion sets and iterate through them - const uint32 numMotionSets = mMotionSets.GetLength(); + const uint32 numMotionSets = mMotionSets.size(); for (uint32 i = 0; i < numMotionSets; ++i) { // get the current motion set diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MotionManager.h b/Gems/EMotionFX/Code/EMotionFX/Source/MotionManager.h index 78d8b0eaa7..98555da9f7 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MotionManager.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MotionManager.h @@ -10,7 +10,7 @@ #include #include -#include +#include #include #include #include @@ -50,7 +50,7 @@ namespace EMotionFX * Get the number of motions in the motion manager. * @return The number of registered motions. */ - MCORE_INLINE uint32 GetNumMotions() const { return mMotions.GetLength(); } + MCORE_INLINE size_t GetNumMotions() const { return mMotions.size(); } /** * Remove the motion with the given name from the motion manager. @@ -160,7 +160,7 @@ namespace EMotionFX * Get the number of motion sets in the motion manager. * @return The number of registered motion sets. */ - MCORE_INLINE uint32 GetNumMotionSets() const { return mMotionSets.GetLength(); } + MCORE_INLINE size_t GetNumMotionSets() const { return mMotionSets.size(); } /** * Calculate the number of root motion sets. @@ -233,8 +233,8 @@ namespace EMotionFX const MotionDataFactory& GetMotionDataFactory() const; private: - MCore::Array mMotions; /**< The array of motions. */ - MCore::Array mMotionSets; /**< The array of motion sets. */ + AZStd::vector mMotions; /**< The array of motions. */ + AZStd::vector mMotionSets; /**< The array of motion sets. */ MCore::Mutex mLock; /**< Motion lock. */ MCore::Mutex mSetLock; /**< The motion set multithread lock. */ MotionDataFactory* m_motionDataFactory = nullptr; /**< The motion data factory. */ diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MotionQueue.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MotionQueue.cpp index d3a76f7967..ea8826fe9a 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MotionQueue.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MotionQueue.cpp @@ -26,7 +26,6 @@ namespace EMotionFX { MCORE_ASSERT(actorInstance && motionSystem); - mEntries.SetMemoryCategory(EMFX_MEMCATEGORY_MOTIONS_MISC); mActorInstance = actorInstance; mMotionSystem = motionSystem; } @@ -54,7 +53,7 @@ namespace EMotionFX GetMotionInstancePool().Free(mEntries[nr].mMotion); } - mEntries.Remove(nr); + mEntries.erase(AZStd::next(begin(mEntries), nr)); } @@ -168,7 +167,7 @@ namespace EMotionFX void MotionQueue::ClearAllEntries() { - while (mEntries.GetLength()) + while (mEntries.size()) { RemoveEntry(0); } @@ -177,26 +176,26 @@ namespace EMotionFX void MotionQueue::AddEntry(const MotionQueue::QueueEntry& motion) { - mEntries.Add(motion); + mEntries.emplace_back(motion); } - uint32 MotionQueue::GetNumEntries() const + size_t MotionQueue::GetNumEntries() const { - return mEntries.GetLength(); + return mEntries.size(); } MotionQueue::QueueEntry& MotionQueue::GetFirstEntry() { - MCORE_ASSERT(mEntries.GetLength() > 0); + MCORE_ASSERT(mEntries.size() > 0); return mEntries[0]; } void MotionQueue::RemoveFirstEntry() { - mEntries.RemoveFirst(); + mEntries.erase(mEntries.begin()); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MotionQueue.h b/Gems/EMotionFX/Code/EMotionFX/Source/MotionQueue.h index 5480f5c40d..9978a16bc6 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MotionQueue.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MotionQueue.h @@ -12,7 +12,7 @@ #include "EMotionFXConfig.h" #include "BaseObject.h" #include "PlayBackInfo.h" -#include +#include namespace EMotionFX @@ -79,7 +79,7 @@ namespace EMotionFX * Get the number of entries currently in the queue. * @result The number of entries currently scheduled in the queue. */ - uint32 GetNumEntries() const; + size_t GetNumEntries() const; /** * Get the first entry. @@ -133,7 +133,7 @@ namespace EMotionFX void PlayNextMotion(); private: - MCore::Array mEntries; /**< The motion queue entries. */ + AZStd::vector mEntries; /**< The motion queue entries. */ MotionSystem* mMotionSystem; /**< Motion system access pointer. */ ActorInstance* mActorInstance; /**< The actor instance where this queue works on. */ diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MotionSystem.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MotionSystem.cpp index 364ad28d3d..fcd243c95f 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MotionSystem.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MotionSystem.cpp @@ -29,7 +29,6 @@ namespace EMotionFX { MCORE_ASSERT(actorInstance); - mMotionInstances.SetMemoryCategory(EMFX_MEMCATEGORY_MOTIONS_MOTIONSYSTEMS); mActorInstance = actorInstance; mMotionQueue = nullptr; @@ -46,11 +45,11 @@ namespace EMotionFX GetEventManager().OnDeleteMotionSystem(this); // delete the motion infos - while (mMotionInstances.GetLength()) + while (mMotionInstances.size()) { //delete mMotionInstances.GetLast(); - GetMotionInstancePool().Free(mMotionInstances.GetLast()); - mMotionInstances.RemoveLast(); + GetMotionInstancePool().Free(mMotionInstances.back()); + mMotionInstances.pop_back(); } // get rid of the motion queue @@ -138,7 +137,14 @@ namespace EMotionFX bool MotionSystem::RemoveMotionInstance(MotionInstance* instance) { // remove the motion instance from the actor - const bool isSuccess = mMotionInstances.RemoveByValue(instance); + const bool isSuccess = [this, instance] { + if(const auto it = AZStd::find(begin(mMotionInstances), end(mMotionInstances), instance); it != end(mMotionInstances)) + { + mMotionInstances.erase(it); + return true; + } + return false; + }(); // delete the motion instance from memory if (isSuccess) @@ -167,7 +173,7 @@ namespace EMotionFX // stop all the motions that are currently playing void MotionSystem::StopAllMotions() { - const uint32 numInstances = mMotionInstances.GetLength(); + const uint32 numInstances = mMotionInstances.size(); for (uint32 i = 0; i < numInstances; ++i) { mMotionInstances[i]->Stop(); @@ -178,7 +184,7 @@ namespace EMotionFX // stop all motion instances of a given motion void MotionSystem::StopAllMotions(Motion* motion) { - const uint32 numInstances = mMotionInstances.GetLength(); + const uint32 numInstances = mMotionInstances.size(); for (uint32 i = 0; i < numInstances; ++i) { if (mMotionInstances[i]->GetMotion()->GetID() == motion->GetID()) @@ -190,16 +196,16 @@ namespace EMotionFX // remove the given motion - void MotionSystem::RemoveMotion(uint32 nr, bool deleteMem) + void MotionSystem::RemoveMotion(size_t nr, bool deleteMem) { - MCORE_ASSERT(nr < mMotionInstances.GetLength()); + MCORE_ASSERT(nr < mMotionInstances.size()); if (deleteMem) { GetEMotionFX().GetMotionInstancePool()->Free(mMotionInstances[nr]); } - mMotionInstances.Remove(nr); + mMotionInstances.erase(AZStd::next(begin(mMotionInstances), nr)); } @@ -208,15 +214,15 @@ namespace EMotionFX { MCORE_ASSERT(motion); - uint32 nr = mMotionInstances.Find(motion); - MCORE_ASSERT(nr != MCORE_INVALIDINDEX32); + const auto it = AZStd::find(begin(mMotionInstances), end(mMotionInstances), motion); + MCORE_ASSERT(it != end(mMotionInstances)); - if (nr == MCORE_INVALIDINDEX32) + if (it == end(mMotionInstances)) { return; } - RemoveMotion(nr, delMem); + RemoveMotion(AZStd::distance(begin(mMotionInstances), it), delMem); } @@ -224,7 +230,7 @@ namespace EMotionFX void MotionSystem::UpdateMotionInstances(float timePassed) { // update all the motion infos - const uint32 numInstances = mMotionInstances.GetLength(); + const uint32 numInstances = mMotionInstances.size(); for (uint32 i = 0; i < numInstances; ++i) { mMotionInstances[i]->Update(timePassed); @@ -242,7 +248,7 @@ namespace EMotionFX } // for all motion instances currently playing in this actor - const uint32 numInstances = mMotionInstances.GetLength(); + const uint32 numInstances = mMotionInstances.size(); for (uint32 i = 0; i < numInstances; ++i) { // check if this one is the one we are searching for, if so, return that it is still valid @@ -269,7 +275,7 @@ namespace EMotionFX } // for all motion instances currently playing in this actor - const uint32 numInstances = mMotionInstances.GetLength(); + const uint32 numInstances = mMotionInstances.size(); for (uint32 i = 0; i < numInstances; ++i) { const MotionInstance* motionInstance = mMotionInstances[i]; @@ -294,15 +300,15 @@ namespace EMotionFX // return given motion instance MotionInstance* MotionSystem::GetMotionInstance(uint32 nr) const { - MCORE_ASSERT(nr < mMotionInstances.GetLength()); + MCORE_ASSERT(nr < mMotionInstances.size()); return mMotionInstances[nr]; } // return number of motion instances - uint32 MotionSystem::GetNumMotionInstances() const + size_t MotionSystem::GetNumMotionInstances() const { - return mMotionInstances.GetLength(); + return mMotionInstances.size(); } @@ -350,12 +356,12 @@ namespace EMotionFX void MotionSystem::AddMotionInstance(MotionInstance* instance) { - mMotionInstances.Add(instance); + mMotionInstances.emplace_back(instance); } bool MotionSystem::GetIsPlaying() const { - return (mMotionInstances.GetLength() > 0); + return (mMotionInstances.size() > 0); } } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MotionSystem.h b/Gems/EMotionFX/Code/EMotionFX/Source/MotionSystem.h index c0cbb779df..dd7ba26170 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MotionSystem.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MotionSystem.h @@ -11,7 +11,7 @@ // include the required headers #include "EMotionFXConfig.h" #include "BaseObject.h" -#include +#include namespace EMotionFX @@ -76,7 +76,7 @@ namespace EMotionFX * @param nr The motion to remove. * @param deleteMem If true the allocated memory of the motion will be deleted. */ - void RemoveMotion(uint32 nr, bool deleteMem = true); + void RemoveMotion(size_t nr, bool deleteMem = true); /** * Remove a given motion. @@ -122,7 +122,7 @@ namespace EMotionFX * @result The number of active motion instances inside this actor. * @see IsValidMotionInstance */ - uint32 GetNumMotionInstances() const; + size_t GetNumMotionInstances() const; /** * Checks if a given motion instance is still valid. @@ -215,7 +215,7 @@ namespace EMotionFX protected: - MCore::Array mMotionInstances; /**< The collection of motion instances. */ + AZStd::vector mMotionInstances; /**< The collection of motion instances. */ ActorInstance* mActorInstance; /**< The actor instance where this motion system belongs to. */ MotionQueue* mMotionQueue; /**< The motion queue. */ diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MultiThreadScheduler.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MultiThreadScheduler.cpp index 9af9ddf71f..bd339ecb36 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MultiThreadScheduler.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MultiThreadScheduler.cpp @@ -30,9 +30,8 @@ namespace EMotionFX MultiThreadScheduler::MultiThreadScheduler() : ActorUpdateScheduler() { - mSteps.SetMemoryCategory(EMFX_MEMCATEGORY_UPDATESCHEDULERS); mCleanTimer = 0.0f; // time passed since last schedule cleanup, in seconds - mSteps.Reserve(1000); + mSteps.reserve(1000); } @@ -53,7 +52,7 @@ namespace EMotionFX void MultiThreadScheduler::Clear() { Lock(); - mSteps.Clear(); + mSteps.clear(); Unlock(); } @@ -79,7 +78,7 @@ namespace EMotionFX void MultiThreadScheduler::Print() { // for all steps - const uint32 numSteps = mSteps.GetLength(); + const uint32 numSteps = mSteps.size(); for (uint32 i = 0; i < numSteps; ++i) { AZ_Printf("EMotionFX", "STEP %.3d - %d", i, mSteps[i].mActorInstances.size()); @@ -92,7 +91,7 @@ namespace EMotionFX void MultiThreadScheduler::RemoveEmptySteps() { // process all steps - for (uint32 s = 0; s < mSteps.GetLength(); ) + for (uint32 s = 0; s < mSteps.size(); ) { // if the step isn't empty if (mSteps[s].mActorInstances.size() > 0) @@ -101,7 +100,7 @@ namespace EMotionFX } else // otherwise remove it { - mSteps.Remove(s); + mSteps.erase(AZStd::next(begin(mSteps), s)); } } } @@ -112,7 +111,7 @@ namespace EMotionFX { MCore::LockGuardRecursive guard(mMutex); - uint32 numSteps = mSteps.GetLength(); + uint32 numSteps = mSteps.size(); if (numSteps == 0) { return; @@ -124,7 +123,7 @@ namespace EMotionFX { mCleanTimer = 0.0f; RemoveEmptySteps(); - numSteps = mSteps.GetLength(); + numSteps = mSteps.size(); } //----------------------------------------------------------- @@ -216,7 +215,7 @@ namespace EMotionFX bool MultiThreadScheduler::FindNextFreeItem(ActorInstance* actorInstance, uint32 startStep, uint32* outStepNr) { // try out all steps - const uint32 numSteps = mSteps.GetLength(); + const uint32 numSteps = mSteps.size(); for (uint32 s = startStep; s < numSteps; ++s) { // if there is a conflicting dependency, skip this step @@ -236,7 +235,7 @@ namespace EMotionFX bool MultiThreadScheduler::HasActorInstanceInSteps(const ActorInstance* actorInstance) const { - const uint32 numSteps = mSteps.GetLength(); + const uint32 numSteps = mSteps.size(); for (uint32 s = 0; s < numSteps; ++s) { const ScheduleStep& step = mSteps[s]; @@ -258,9 +257,9 @@ namespace EMotionFX uint32 outStep = startStep; if (!FindNextFreeItem(instance, startStep, &outStep)) { - mSteps.Reserve(10); - mSteps.AddEmpty(); - outStep = mSteps.GetLength() - 1; + mSteps.reserve(10); + mSteps.emplace_back(); + outStep = mSteps.size() - 1; } // pre-allocate step size @@ -269,9 +268,9 @@ namespace EMotionFX mSteps[outStep].mActorInstances.reserve(mSteps[outStep].mActorInstances.size() + 10); } - if (mSteps[outStep].mDependencies.GetLength() % 5 == 0) + if (mSteps[outStep].mDependencies.size() % 5 == 0) { - mSteps[outStep].mDependencies.Reserve(mSteps[outStep].mDependencies.GetLength() + 5); + mSteps[outStep].mDependencies.reserve(mSteps[outStep].mDependencies.size() + 5); } // add the actor instance and its dependencies @@ -298,7 +297,7 @@ namespace EMotionFX MCore::LockGuardRecursive guard(mMutex); // for all scheduler steps, starting from the specified start step number - const uint32 numSteps = mSteps.GetLength(); + const uint32 numSteps = mSteps.size(); for (uint32 s = startStep; s < numSteps; ++s) { ScheduleStep& step = mSteps[s]; @@ -312,7 +311,7 @@ namespace EMotionFX if (step.mActorInstances.size() < numActorInstancesPreRemove) { // clear the dependencies (but don't delete the memory) - step.mDependencies.Clear(false); + step.mDependencies.clear(); // calculate the new dependencies for this step for (ActorInstance* stepActorInstance : step.mActorInstances) diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MultiThreadScheduler.h b/Gems/EMotionFX/Code/EMotionFX/Source/MultiThreadScheduler.h index 75a5a6519a..4deebae866 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MultiThreadScheduler.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MultiThreadScheduler.h @@ -50,16 +50,8 @@ namespace EMotionFX */ struct EMFX_API ScheduleStep { - MCore::Array mDependencies; /**< The dependencies of this scheduler step. No actor instances with the same dependencies are allowed to be added to this step. */ + AZStd::vector mDependencies; /**< The dependencies of this scheduler step. No actor instances with the same dependencies are allowed to be added to this step. */ AZStd::vector mActorInstances; /**< The actor instances used inside this step. Each array entry will execute in another thread. */ - - /** - * The constructor. - */ - ScheduleStep() - { - mDependencies.SetMemoryCategory(EMFX_MEMCATEGORY_UPDATESCHEDULERS); - } }; /** @@ -128,10 +120,10 @@ namespace EMotionFX void Unlock(); const ScheduleStep& GetScheduleStep(uint32 index) const { return mSteps[index]; } - uint32 GetNumScheduleSteps() const { return mSteps.GetLength(); } + size_t GetNumScheduleSteps() const { return mSteps.size(); } protected: - MCore::Array< ScheduleStep > mSteps; /**< An array of update steps, that together form the schedule. */ + AZStd::vector< ScheduleStep > mSteps; /**< An array of update steps, that together form the schedule. */ float mCleanTimer; /**< The time passed since the last automatic call to the Optimize method. */ MCore::MutexRecursive mMutex; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Node.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Node.cpp index 8ab7fa540d..a712ffe337 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Node.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Node.cpp @@ -20,10 +20,6 @@ namespace EMotionFX Node::Node(const char* name, Skeleton* skeleton) : BaseObject() { - // set the array memory categories - mAttributes.SetMemoryCategory(EMFX_MEMCATEGORY_NODES); - mChildIndices.SetMemoryCategory(EMFX_MEMCATEGORY_NODES); - mParentIndex = MCORE_INVALIDINDEX32; mNodeIndex = MCORE_INVALIDINDEX32; // hasn't been set yet mSkeletalLODs = 0xFFFFFFFF; // set all bits of the integer to 1, which enables this node in all LOD levels on default @@ -45,10 +41,6 @@ namespace EMotionFX Node::Node(uint32 nameID, Skeleton* skeleton) : BaseObject() { - // set the array memory categories - mAttributes.SetMemoryCategory(EMFX_MEMCATEGORY_NODES); - mChildIndices.SetMemoryCategory(EMFX_MEMCATEGORY_NODES); - mParentIndex = MCORE_INVALIDINDEX32; mNodeIndex = MCORE_INVALIDINDEX32; // hasn't been set yet mSkeletalLODs = 0xFFFFFFFF;// set all bits of the integer to 1, which enables this node in all LOD levels on default @@ -167,8 +159,8 @@ namespace EMotionFX result->mSemanticNameID = mSemanticNameID; // copy the node attributes - result->mAttributes.Reserve(mAttributes.GetLength()); - for (uint32 i = 0; i < mAttributes.GetLength(); i++) + result->mAttributes.reserve(mAttributes.size()); + for (uint32 i = 0; i < mAttributes.size(); i++) { result->AddAttribute(mAttributes[i]->Clone()); } @@ -181,10 +173,10 @@ namespace EMotionFX // removes all attributes void Node::RemoveAllAttributes() { - while (mAttributes.GetLength()) + while (mAttributes.size()) { - mAttributes.GetLast()->Destroy(); - mAttributes.RemoveLast(); + mAttributes.back()->Destroy(); + mAttributes.pop_back(); } } @@ -213,7 +205,7 @@ namespace EMotionFX numNodes++; // recurse down the hierarchy - const uint32 numChildNodes = mChildIndices.GetLength(); + const uint32 numChildNodes = mChildIndices.size(); for (uint32 i = 0; i < numChildNodes; ++i) { mSkeleton->GetNode(mChildIndices[i])->RecursiveCountChildNodes(numNodes); @@ -405,20 +397,20 @@ namespace EMotionFX void Node::AddAttribute(NodeAttribute* attribute) { - mAttributes.Add(attribute); + mAttributes.emplace_back(attribute); } - uint32 Node::GetNumAttributes() const + size_t Node::GetNumAttributes() const { - return mAttributes.GetLength(); + return mAttributes.size(); } NodeAttribute* Node::GetAttribute(uint32 attributeNr) { // make sure we are in range - MCORE_ASSERT(attributeNr < mAttributes.GetLength()); + MCORE_ASSERT(attributeNr < mAttributes.size()); // return the attribute return mAttributes[attributeNr]; @@ -428,7 +420,7 @@ namespace EMotionFX uint32 Node::FindAttributeNumber(uint32 attributeTypeID) const { // check all attributes, and find where the specific attribute is - const uint32 numAttributes = mAttributes.GetLength(); + const uint32 numAttributes = mAttributes.size(); for (uint32 i = 0; i < numAttributes; ++i) { if (mAttributes[i]->GetType() == attributeTypeID) @@ -445,7 +437,7 @@ namespace EMotionFX NodeAttribute* Node::GetAttributeByType(uint32 attributeType) { // check all attributes - const uint32 numAttributes = mAttributes.GetLength(); + const uint32 numAttributes = mAttributes.size(); for (uint32 i = 0; i < numAttributes; ++i) { if (mAttributes[i]->GetType() == attributeType) @@ -462,13 +454,13 @@ namespace EMotionFX // remove the given attribute void Node::RemoveAttribute(uint32 index) { - mAttributes.Remove(index); + mAttributes.erase(AZStd::next(begin(mAttributes), index)); } void Node::AddChild(uint32 nodeIndex) { - mChildIndices.AddExact(nodeIndex); + mChildIndices.emplace_back(nodeIndex); } @@ -480,31 +472,34 @@ namespace EMotionFX void Node::SetNumChildNodes(uint32 numChildNodes) { - mChildIndices.Resize(numChildNodes); + mChildIndices.resize(numChildNodes); } void Node::PreAllocNumChildNodes(uint32 numChildNodes) { - mChildIndices.Reserve(numChildNodes); + mChildIndices.reserve(numChildNodes); } void Node::RemoveChild(uint32 nodeIndex) { - mChildIndices.RemoveByValue(nodeIndex); + if (const auto it = AZStd::find(begin(mChildIndices), end(mChildIndices), nodeIndex); it != end(mChildIndices)) + { + mChildIndices.erase(it); + } } void Node::RemoveAllChildNodes() { - mChildIndices.Clear(); + mChildIndices.clear(); } bool Node::GetHasChildNodes() const { - return (mChildIndices.GetLength() > 0); + return (mChildIndices.size() > 0); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Node.h b/Gems/EMotionFX/Code/EMotionFX/Source/Node.h index b8618018d2..73e8a41c01 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Node.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Node.h @@ -12,7 +12,7 @@ #include #include "EMotionFXConfig.h" #include "BaseObject.h" -#include +#include #include namespace EMotionFX @@ -168,7 +168,7 @@ namespace EMotionFX * Get the number of child nodes attached to this node. * @result The number of child nodes. */ - MCORE_INLINE uint32 GetNumChildNodes() const { return mChildIndices.GetLength(); } + MCORE_INLINE size_t GetNumChildNodes() const { return mChildIndices.size(); } /** * Get the number of child nodes down the hierarchy of this node. @@ -189,7 +189,7 @@ namespace EMotionFX * @param nodeIndex The node to check whether it is a child or not. * @result True if the given node is a child, false if not. */ - MCORE_INLINE bool CheckIfIsChildNode(uint32 nodeIndex) const { return (mChildIndices.Find(nodeIndex) != MCORE_INVALIDINDEX32); } + MCORE_INLINE bool CheckIfIsChildNode(uint32 nodeIndex) const { return (AZStd::find(begin(mChildIndices), end(mChildIndices), nodeIndex) != end(mChildIndices)); } /** * Add a child to this node. @@ -262,7 +262,7 @@ namespace EMotionFX * Get the number of node attributes. * @result The number of node attributes for this node. */ - uint32 GetNumAttributes() const; + size_t GetNumAttributes() const; /** * Get a given node attribute. @@ -421,8 +421,8 @@ namespace EMotionFX uint32 mNameID; /**< The ID, which is generated from the name. You can use this for fast compares between nodes. */ uint32 mSemanticNameID; /**< The semantic name ID, for example "LeftHand" or "RightFoot" or so, this can be used for retargeting. */ Skeleton* mSkeleton; /**< The skeleton where this node belongs to. */ - MCore::Array mChildIndices; /**< The indices that point to the child nodes. */ - MCore::Array mAttributes; /**< The node attributes. */ + AZStd::vector mChildIndices; /**< The indices that point to the child nodes. */ + AZStd::vector mAttributes; /**< The node attributes. */ uint8 mNodeFlags; /**< The node flags are used to store boolean attributes of the node as single bits. */ /** diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/NodeMap.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/NodeMap.cpp index 8f2e752917..edc1ea37cd 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/NodeMap.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/NodeMap.cpp @@ -41,14 +41,14 @@ namespace EMotionFX // preallocate space void NodeMap::Reserve(uint32 numEntries) { - mEntries.Reserve(numEntries); + mEntries.reserve(numEntries); } // resize the entries array void NodeMap::Resize(uint32 numEntries) { - mEntries.Resize(numEntries); + mEntries.resize(numEntries); } @@ -101,15 +101,15 @@ namespace EMotionFX void NodeMap::AddEntry(const char* firstName, const char* secondName) { MCORE_ASSERT(GetHasEntry(firstName) == false); // prevent duplicates - mEntries.AddEmpty(); - SetEntry(mEntries.GetLength() - 1, firstName, secondName); + mEntries.emplace_back(); + SetEntry(mEntries.size() - 1, firstName, secondName); } // remove a given entry by its index void NodeMap::RemoveEntryByIndex(uint32 entryIndex) { - mEntries.Remove(entryIndex); + mEntries.erase(AZStd::next(begin(mEntries), entryIndex)); } @@ -122,7 +122,7 @@ namespace EMotionFX return; } - mEntries.Remove(entryIndex); + mEntries.erase(AZStd::next(begin(mEntries), entryIndex)); } @@ -135,7 +135,7 @@ namespace EMotionFX return; } - mEntries.Remove(entryIndex); + mEntries.erase(AZStd::next(begin(mEntries), entryIndex)); } @@ -211,7 +211,7 @@ namespace EMotionFX uint32 numBytes = sizeof(FileFormat::NodeMapChunk); // for all entries - const uint32 numEntries = mEntries.GetLength(); + const uint32 numEntries = mEntries.size(); for (uint32 i = 0; i < numEntries; ++i) { numBytes += CalcFileStringSize(GetFirstNameString(i)); @@ -265,7 +265,7 @@ namespace EMotionFX // the main info FileFormat::NodeMapChunk nodeMapChunk{}; - nodeMapChunk.mNumEntries = mEntries.GetLength(); + nodeMapChunk.mNumEntries = mEntries.size(); MCore::Endian::ConvertUnsignedInt32To(&nodeMapChunk.mNumEntries, targetEndianType); if (f.Write(&nodeMapChunk, sizeof(FileFormat::NodeMapChunk)) == 0) { @@ -282,7 +282,7 @@ namespace EMotionFX } // for all entries - const uint32 numEntries = mEntries.GetLength(); + const uint32 numEntries = mEntries.size(); for (uint32 i = 0; i < numEntries; ++i) { if (WriteFileString(&f, GetFirstNameString(i), targetEndianType) == false) @@ -320,9 +320,9 @@ namespace EMotionFX // get the number of entries - uint32 NodeMap::GetNumEntries() const + size_t NodeMap::GetNumEntries() const { - return mEntries.GetLength(); + return mEntries.size(); } @@ -364,7 +364,7 @@ namespace EMotionFX // find an entry index by its name uint32 NodeMap::FindEntryIndexByName(const char* firstName) const { - const uint32 numEntries = mEntries.GetLength(); + const uint32 numEntries = mEntries.size(); for (uint32 i = 0; i < numEntries; ++i) { const AZStd::string& firstNameEntry = GetFirstName(i); @@ -381,7 +381,7 @@ namespace EMotionFX // find an entry index by its name ID uint32 NodeMap::FindEntryIndexByNameID(uint32 firstNameID) const { - const uint32 numEntries = mEntries.GetLength(); + const uint32 numEntries = mEntries.size(); for (uint32 i = 0; i < numEntries; ++i) { if (mEntries[i].mFirstNameID == firstNameID) diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/NodeMap.h b/Gems/EMotionFX/Code/EMotionFX/Source/NodeMap.h index d033d0a36f..6db38efc32 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/NodeMap.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/NodeMap.h @@ -11,7 +11,7 @@ // include required files #include "EMotionFXConfig.h" #include "BaseObject.h" -#include +#include #include #include @@ -54,7 +54,7 @@ namespace EMotionFX void Resize(uint32 numEntries); // get data - uint32 GetNumEntries() const; + size_t GetNumEntries() const; const char* GetFirstName(uint32 entryIndex) const; const char* GetSecondName(uint32 entryIndex) const; const AZStd::string& GetFirstNameString(uint32 entryIndex) const; @@ -88,7 +88,7 @@ namespace EMotionFX bool Save(const char* fileName, MCore::Endian::EEndianType targetEndianType) const; private: - MCore::Array mEntries; /**< The array of entries. */ + AZStd::vector mEntries; /**< The array of entries. */ AZStd::string mFileName; /**< The filename. */ Actor* mSourceActor; /**< The source actor. */ diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Recorder.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Recorder.cpp index 6c2c070e50..41c7c1e929 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Recorder.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Recorder.cpp @@ -7,6 +7,7 @@ */ #include +#include #include "Recorder.h" #include "RecorderBus.h" #include "ActorInstance.h" @@ -101,7 +102,6 @@ namespace EMotionFX mLastRecordTime = 0.0f; mCurrentPlayTime = 0.0f; - mObjects.SetMemoryCategory(EMFX_MEMCATEGORY_RECORDER); EMotionFX::ActorInstanceNotificationBus::Handler::BusConnect(); } @@ -345,7 +345,7 @@ namespace EMotionFX if (mRecordSettings.mRecordMorphs) { const uint32 numMorphs = actorInstance->GetMorphSetupInstance()->GetNumMorphTargets(); - actorInstanceData.mMorphTracks.Resize(numMorphs); + actorInstanceData.mMorphTracks.resize(numMorphs); for (uint32 m = 0; m < numMorphs; ++m) { actorInstanceData.mMorphTracks[m].Reserve(256); @@ -547,32 +547,31 @@ namespace EMotionFX const AnimGraph* animGraph = animGraphInstance->GetAnimGraph(); // add a new frame - MCore::Array& frames = animGraphInstanceData.mFrames; - if (frames.GetLength() > 0) + AZStd::vector& frames = animGraphInstanceData.mFrames; + if (frames.size() > 0) { - const uint32 byteOffset = frames.GetLast().mByteOffset + frames.GetLast().mNumBytes; - frames.AddEmpty(); - frames.GetLast().mByteOffset = byteOffset; - frames.GetLast().mNumBytes = 0; + const uint32 byteOffset = frames.back().mByteOffset + frames.back().mNumBytes; + frames.emplace_back(); + frames.back().mByteOffset = byteOffset; + frames.back().mNumBytes = 0; } else { - frames.AddEmpty(); - frames.GetLast().mByteOffset = 0; - frames.GetLast().mNumBytes = 0; + frames.emplace_back(); + frames.back().mByteOffset = 0; + frames.back().mNumBytes = 0; } // get the current frame - AnimGraphAnimFrame& currentFrame = frames.GetLast(); + AnimGraphAnimFrame& currentFrame = frames.back(); currentFrame.mTimeValue = mRecordTime; // save the parameter values const uint32 numParams = static_cast(animGraphInstance->GetAnimGraph()->GetNumValueParameters()); - currentFrame.mParameterValues.SetMemoryCategory(EMFX_MEMCATEGORY_RECORDER); - currentFrame.mParameterValues.Resize(numParams); + currentFrame.mParameterValues.resize(numParams); for (uint32 p = 0; p < numParams; ++p) { - currentFrame.mParameterValues[p] = animGraphInstance->GetParameterValue(p)->Clone(); + currentFrame.mParameterValues[p] = AZStd::unique_ptr(animGraphInstance->GetParameterValue(p)->Clone()); } // recursively save all unique datas @@ -595,19 +594,19 @@ namespace EMotionFX bool Recorder::SaveUniqueData(AnimGraphInstance* animGraphInstance, AnimGraphObject* object, AnimGraphInstanceData& animGraphInstanceData) { // get the current frame's data pointer - AnimGraphAnimFrame& currentFrame = animGraphInstanceData.mFrames.GetLast(); + AnimGraphAnimFrame& currentFrame = animGraphInstanceData.mFrames.back(); const uint32 frameOffset = currentFrame.mByteOffset; // prepare the objects array - mObjects.Clear(false); - mObjects.Reserve(1024); + mObjects.clear(); + mObjects.reserve(1024); // collect the objects we are going to save for this frame object->RecursiveCollectObjects(mObjects); // resize the object infos array - const uint32 numObjects = mObjects.GetLength(); - currentFrame.mObjectInfos.Resize(numObjects); + const uint32 numObjects = mObjects.size(); + currentFrame.mObjectInfos.resize(numObjects); // calculate how much memory we need for this frame uint32 requiredFrameBytes = 0; @@ -773,7 +772,7 @@ namespace EMotionFX { const size_t index = iterator - recordedActorInstances.begin(); const ActorInstanceData& actorInstanceData = *m_actorInstanceDatas[index]; - const uint32 numMorphs = actorInstanceData.mMorphTracks.GetLength(); + const uint32 numMorphs = actorInstanceData.mMorphTracks.size(); if (numMorphs == actorInstance->GetMorphSetupInstance()->GetNumMorphTargets()) { for (uint32 i = 0; i < numMorphs; ++i) @@ -848,27 +847,27 @@ namespace EMotionFX AnimGraphInstance* animGraphInstance = animGraphInstanceData.mAnimGraphInstance; // get the real frame number (clamped) - const uint32 realFrameNumber = MCore::Min(frameNumber, animGraphInstanceData.mFrames.GetLength() - 1); + const uint32 realFrameNumber = MCore::Min(frameNumber, animGraphInstanceData.mFrames.size() - 1); const AnimGraphAnimFrame& currentFrame = animGraphInstanceData.mFrames[realFrameNumber]; // get the data and objects buffers const uint32 byteOffset = currentFrame.mByteOffset; const uint8* frameDataBuffer = &animGraphInstanceData.mDataBuffer[byteOffset]; - const MCore::Array& frameObjects = currentFrame.mObjectInfos; + const AZStd::vector& frameObjects = currentFrame.mObjectInfos; // first lets update all parameter values - MCORE_ASSERT(currentFrame.mParameterValues.GetLength() == animGraphInstance->GetAnimGraph()->GetNumParameters()); - const uint32 numParameters = currentFrame.mParameterValues.GetLength(); + MCORE_ASSERT(currentFrame.mParameterValues.size() == animGraphInstance->GetAnimGraph()->GetNumParameters()); + const uint32 numParameters = currentFrame.mParameterValues.size(); for (uint32 p = 0; p < numParameters; ++p) { // make sure the parameters are of the same type MCORE_ASSERT(animGraphInstance->GetParameterValue(p)->GetType() == currentFrame.mParameterValues[p]->GetType()); - animGraphInstance->GetParameterValue(p)->InitFrom(currentFrame.mParameterValues[p]); + animGraphInstance->GetParameterValue(p)->InitFrom(currentFrame.mParameterValues[p].get()); } // process all objects for this frame uint32 totalBytesRead = 0; - const uint32 numObjects = frameObjects.GetLength(); + const uint32 numObjects = frameObjects.size(); for (uint32 a = 0; a < numObjects; ++a) { const AnimGraphAnimObjectInfo& objectInfo = frameObjects[a]; @@ -917,11 +916,11 @@ namespace EMotionFX animGraphInstance->CollectActiveAnimGraphNodes(&mActiveNodes); // get the history items as shortcut - MCore::Array& historyItems = actorInstanceData->mNodeHistoryItems; + AZStd::vector& historyItems = actorInstanceData->mNodeHistoryItems; // finalize items const size_t numActiveNodes = mActiveNodes.size(); - const uint32 numHistoryItems = historyItems.GetLength(); + const uint32 numHistoryItems = historyItems.size(); for (uint32 h = 0; h < numHistoryItems; ++h) { NodeHistoryItem* curItem = historyItems[h]; @@ -1023,7 +1022,7 @@ namespace EMotionFX } } - historyItems.Add(item); + historyItems.emplace_back(item); } // add the weight key and update infos @@ -1053,8 +1052,8 @@ namespace EMotionFX // try to find a given node history item Recorder::NodeHistoryItem* Recorder::FindNodeHistoryItem(const ActorInstanceData& actorInstanceData, AnimGraphNode* node, float recordTime) const { - const MCore::Array& historyItems = actorInstanceData.mNodeHistoryItems; - const uint32 numItems = historyItems.GetLength(); + const AZStd::vector& historyItems = actorInstanceData.mNodeHistoryItems; + const uint32 numItems = historyItems.size(); for (uint32 i = 0; i < numItems; ++i) { NodeHistoryItem* curItem = historyItems[i]; @@ -1076,8 +1075,8 @@ namespace EMotionFX // find a free track uint32 Recorder::FindFreeNodeHistoryItemTrack(const ActorInstanceData& actorInstanceData, NodeHistoryItem* item) const { - const MCore::Array& historyItems = actorInstanceData.mNodeHistoryItems; - const uint32 numItems = historyItems.GetLength(); + const AZStd::vector& historyItems = actorInstanceData.mNodeHistoryItems; + const uint32 numItems = historyItems.size(); bool found = false; uint32 trackIndex = 0; @@ -1144,8 +1143,8 @@ namespace EMotionFX uint32 Recorder::CalcMaxNodeHistoryTrackIndex(const ActorInstanceData& actorInstanceData) const { uint32 result = 0; - const MCore::Array& historyItems = actorInstanceData.mNodeHistoryItems; - const uint32 numItems = historyItems.GetLength(); + const AZStd::vector& historyItems = actorInstanceData.mNodeHistoryItems; + const uint32 numItems = historyItems.size(); for (uint32 i = 0; i < numItems; ++i) { NodeHistoryItem* curItem = historyItems[i]; @@ -1163,8 +1162,8 @@ namespace EMotionFX uint32 Recorder::CalcMaxEventHistoryTrackIndex(const ActorInstanceData& actorInstanceData) const { uint32 result = 0; - const MCore::Array& historyItems = actorInstanceData.mEventHistoryItems; - const uint32 numItems = historyItems.GetLength(); + const AZStd::vector& historyItems = actorInstanceData.mEventHistoryItems; + const uint32 numItems = historyItems.size(); for (uint32 i = 0; i < numItems; ++i) { EventHistoryItem* curItem = historyItems[i]; @@ -1210,10 +1209,10 @@ namespace EMotionFX animGraphInstance->CollectActiveAnimGraphNodes(&mActiveNodes); // get the history items as shortcut - const MCore::Array& historyItems = actorInstanceData->mNodeHistoryItems; + const AZStd::vector& historyItems = actorInstanceData->mNodeHistoryItems; // finalize all items - const uint32 numItems = historyItems.GetLength(); + const uint32 numItems = historyItems.size(); for (uint32 i = 0; i < numItems; ++i) { // remove unneeded key frames @@ -1246,7 +1245,7 @@ namespace EMotionFX const AnimGraphEventBuffer& eventBuffer = animGraphInstance->GetEventBuffer(); // iterate over all events - MCore::Array& historyItems = actorInstanceData->mEventHistoryItems; + AZStd::vector& historyItems = actorInstanceData->mEventHistoryItems; const uint32 numEvents = eventBuffer.GetNumEvents(); for (uint32 i = 0; i < numEvents; ++i) { @@ -1271,7 +1270,7 @@ namespace EMotionFX item->mTrackIndex = FindFreeEventHistoryItemTrack(*actorInstanceData, item); - historyItems.Add(item); + historyItems.emplace_back(item); } item->mEndTime = mRecordTime; @@ -1284,8 +1283,8 @@ namespace EMotionFX Recorder::EventHistoryItem* Recorder::FindEventHistoryItem(const ActorInstanceData& actorInstanceData, const EventInfo& eventInfo, float recordTime) { MCORE_UNUSED(recordTime); - const MCore::Array& historyItems = actorInstanceData.mEventHistoryItems; - const uint32 numItems = historyItems.GetLength(); + const AZStd::vector& historyItems = actorInstanceData.mEventHistoryItems; + const uint32 numItems = historyItems.size(); for (uint32 i = 0; i < numItems; ++i) { EventHistoryItem* curItem = historyItems[i]; @@ -1303,8 +1302,8 @@ namespace EMotionFX // find a free event track index uint32 Recorder::FindFreeEventHistoryItemTrack(const ActorInstanceData& actorInstanceData, EventHistoryItem* item) const { - const MCore::Array& historyItems = actorInstanceData.mEventHistoryItems; - const uint32 numItems = historyItems.GetLength(); + const AZStd::vector& historyItems = actorInstanceData.mEventHistoryItems; + const uint32 numItems = historyItems.size(); bool found = false; uint32 trackIndex = 0; while (found == false) @@ -1341,7 +1340,7 @@ namespace EMotionFX // find the frame number for a time value - uint32 Recorder::FindAnimGraphDataFrameNumber(float timeValue) const + size_t Recorder::FindAnimGraphDataFrameNumber(float timeValue) const { // check if we recorded any actor instances at all if (m_actorInstanceDatas.empty()) @@ -1357,7 +1356,7 @@ namespace EMotionFX return MCORE_INVALIDINDEX32; } - const uint32 numFrames = animGraphData->mFrames.GetLength(); + const uint32 numFrames = animGraphData->mFrames.size(); if (numFrames == 0) { return MCORE_INVALIDINDEX32; @@ -1373,9 +1372,9 @@ namespace EMotionFX return 0; } - if (timeValue > animGraphData->mFrames.GetLast().mTimeValue) + if (timeValue > animGraphData->mFrames.back().mTimeValue) { - return animGraphData->mFrames.GetLength() - 1; + return animGraphData->mFrames.size() - 1; } for (uint32 i = 0; i < numFrames - 1; ++i) @@ -1459,11 +1458,11 @@ namespace EMotionFX // extract sorted active items - void Recorder::ExtractNodeHistoryItems(const ActorInstanceData& actorInstanceData, float timeValue, bool sort, EValueType valueType, MCore::Array* outItems, MCore::Array* outMap) + void Recorder::ExtractNodeHistoryItems(const ActorInstanceData& actorInstanceData, float timeValue, bool sort, EValueType valueType, AZStd::vector* outItems, AZStd::vector* outMap) { // clear the map array const uint32 maxIndex = CalcMaxNodeHistoryTrackIndex(actorInstanceData); - outItems->Resize(maxIndex + 1); + outItems->resize(maxIndex + 1); for (uint32 i = 0; i <= maxIndex; ++i) { ExtractedNodeHistoryItem item; @@ -1471,12 +1470,12 @@ namespace EMotionFX item.mValue = 0.0f; item.mKeyTrackSampleTime = 0.0f; item.mNodeHistoryItem = nullptr; - outItems->SetElem(i, item); + outItems->emplace(AZStd::next(begin(*outItems), i), AZStd::move(item)); } // find all node history items - const MCore::Array& historyItems = actorInstanceData.mNodeHistoryItems; - const uint32 numItems = historyItems.GetLength(); + const AZStd::vector& historyItems = actorInstanceData.mNodeHistoryItems; + const uint32 numItems = historyItems.size(); for (uint32 i = 0; i < numItems; ++i) { NodeHistoryItem* curItem = historyItems[i]; @@ -1506,25 +1505,25 @@ namespace EMotionFX item.mValue = curItem->mGlobalWeights.GetValueAtTime(item.mKeyTrackSampleTime, nullptr, nullptr, mRecordSettings.mInterpolate); } - outItems->SetElem(curItem->mTrackIndex, item); + outItems->emplace(AZStd::next(begin(*outItems), curItem->mTrackIndex), item); } } // build the map - outMap->Resize(maxIndex + 1); + outMap->resize(maxIndex + 1); for (uint32 i = 0; i <= maxIndex; ++i) { - outMap->SetElem(i, i); + outMap->emplace(AZStd::next(begin(*outMap), i), i); } // sort if desired if (sort) { - outItems->Sort(); + AZStd::sort(begin(*outItems), end(*outItems)); for (uint32 i = 0; i <= maxIndex; ++i) { - outMap->SetElem(outItems->GetItem(i).mTrackIndex, i); + outMap->emplace(AZStd::next(begin(*outMap), outItems->at(i).mTrackIndex), i); } } } @@ -1539,7 +1538,7 @@ namespace EMotionFX const size_t maxNumTracks = static_cast(CalcMaxNodeHistoryTrackIndex()) + 1; trackFlags.resize(maxNumTracks); - const uint32 numNodeHistoryItems = actorInstanceData.mNodeHistoryItems.GetLength(); + const uint32 numNodeHistoryItems = actorInstanceData.mNodeHistoryItems.size(); for (uint32 i = 0; i < numNodeHistoryItems; ++i) { EMotionFX::Recorder::NodeHistoryItem* item = actorInstanceData.mNodeHistoryItems[i]; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Recorder.h b/Gems/EMotionFX/Code/EMotionFX/Source/Recorder.h index 3c9ec5ece8..02a61627a4 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Recorder.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Recorder.h @@ -15,7 +15,7 @@ #include "BaseObject.h" #include #include "MCore/Source/Color.h" -#include +#include #include #include #include @@ -201,43 +201,59 @@ namespace EMotionFX struct EMFX_API AnimGraphAnimFrame { - float mTimeValue; - uint32 mByteOffset; - uint32 mNumBytes; - MCore::Array mObjectInfos; - MCore::Array mParameterValues; - - AnimGraphAnimFrame() - { - mTimeValue = 0.0f; - mByteOffset = 0; - mNumBytes = 0; - } - - ~AnimGraphAnimFrame() - { - const uint32 numParams = mParameterValues.GetLength(); - for (uint32 i = 0; i < numParams; ++i) - { - delete mParameterValues[i]; - } - } + float mTimeValue = 0.0f; + uint32 mByteOffset = 0; + uint32 mNumBytes = 0; + AZStd::vector mObjectInfos{}; + AZStd::vector> mParameterValues{}; }; struct EMFX_API AnimGraphInstanceData { - AnimGraphInstance* mAnimGraphInstance; - uint32 mNumFrames; - uint32 mDataBufferSize; - uint8* mDataBuffer; - MCore::Array mFrames; + AnimGraphInstance* mAnimGraphInstance = nullptr; + uint32 mNumFrames = 0; + uint32 mDataBufferSize = 0; + uint8* mDataBuffer = nullptr; + AZStd::vector mFrames{}; - AnimGraphInstanceData() + AnimGraphInstanceData() = default; + AnimGraphInstanceData(const AnimGraphInstanceData&) = delete; + AnimGraphInstanceData(AnimGraphInstanceData&& rhs) { - mAnimGraphInstance = nullptr; - mNumFrames = 0; - mDataBufferSize = 0; - mDataBuffer = nullptr; + if (&rhs == this) + { + return; + } + mAnimGraphInstance = rhs.mAnimGraphInstance; + mNumFrames = rhs.mNumFrames; + mDataBufferSize = rhs.mDataBufferSize; + mDataBuffer = rhs.mDataBuffer; + mFrames = AZStd::move(rhs.mFrames); + rhs.mAnimGraphInstance = nullptr; + rhs.mNumFrames = 0; + rhs.mDataBufferSize = 0; + rhs.mDataBuffer = nullptr; + rhs.mFrames = {}; + } + + AnimGraphInstanceData& operator=(const AnimGraphInstanceData&) = delete; + AnimGraphInstanceData& operator=(AnimGraphInstanceData&& rhs) + { + if (&rhs == this) + { + return *this; + } + mAnimGraphInstance = rhs.mAnimGraphInstance; + mNumFrames = rhs.mNumFrames; + mDataBufferSize = rhs.mDataBufferSize; + mDataBuffer = rhs.mDataBuffer; + mFrames = AZStd::move(rhs.mFrames); + rhs.mAnimGraphInstance = nullptr; + rhs.mNumFrames = 0; + rhs.mDataBufferSize = 0; + rhs.mDataBuffer = nullptr; + rhs.mFrames = {}; + return *this; } ~AnimGraphInstanceData() @@ -254,19 +270,16 @@ namespace EMotionFX ActorInstance* mActorInstance; // the actor instance this data is about AnimGraphInstanceData* mAnimGraphData; // the anim graph instance data AZStd::vector m_transformTracks; // the transformation tracks, one for each node - MCore::Array mNodeHistoryItems; // node history items - MCore::Array mEventHistoryItems; // event history item + AZStd::vector mNodeHistoryItems; // node history items + AZStd::vector mEventHistoryItems; // event history item TransformTracks mActorLocalTransform; // the actor instance's local transformation - MCore::Array< KeyTrackLinearDynamic > mMorphTracks; // morph animation data + AZStd::vector< KeyTrackLinearDynamic > mMorphTracks; // morph animation data ActorInstanceData() { - mNodeHistoryItems.SetMemoryCategory(EMFX_MEMCATEGORY_RECORDER); - mEventHistoryItems.SetMemoryCategory(EMFX_MEMCATEGORY_RECORDER); - mMorphTracks.SetMemoryCategory(EMFX_MEMCATEGORY_RECORDER); - mNodeHistoryItems.Reserve(64); - mEventHistoryItems.Reserve(1024); - mMorphTracks.Reserve(32); + mNodeHistoryItems.reserve(64); + mEventHistoryItems.reserve(1024); + mMorphTracks.reserve(32); mAnimGraphData = nullptr; mActorInstance = nullptr; } @@ -274,20 +287,20 @@ namespace EMotionFX ~ActorInstanceData() { // clear the node history items - const uint32 numMotionItems = mNodeHistoryItems.GetLength(); + const uint32 numMotionItems = mNodeHistoryItems.size(); for (uint32 i = 0; i < numMotionItems; ++i) { delete mNodeHistoryItems[i]; } - mNodeHistoryItems.Clear(); + mNodeHistoryItems.clear(); // clear the event history items - const uint32 numEventItems = mEventHistoryItems.GetLength(); + const uint32 numEventItems = mEventHistoryItems.size(); for (uint32 i = 0; i < numEventItems; ++i) { delete mEventHistoryItems[i]; } - mEventHistoryItems.Clear(); + mEventHistoryItems.clear(); delete mAnimGraphData; } @@ -345,7 +358,7 @@ namespace EMotionFX AZ::u32 CalcMaxNumActiveMotions(const ActorInstanceData& actorInstanceData) const; AZ::u32 CalcMaxNumActiveMotions() const; - void ExtractNodeHistoryItems(const ActorInstanceData& actorInstanceData, float timeValue, bool sort, EValueType valueType, MCore::Array* outItems, MCore::Array* outMap); + void ExtractNodeHistoryItems(const ActorInstanceData& actorInstanceData, float timeValue, bool sort, EValueType valueType, AZStd::vector* outItems, AZStd::vector* outMap); void StartPlayBack(); void StopPlayBack(); @@ -360,7 +373,7 @@ namespace EMotionFX RecordSettings mRecordSettings; AZStd::vector m_actorInstanceDatas; AZStd::vector m_timeDeltas; // The value of the time deltas whenever a key is made - MCore::Array mObjects; + AZStd::vector mObjects; AZStd::vector mActiveNodes; /**< A temp array to store active animgraph nodes in. */ MCore::Mutex mLock; AZ::TypeId m_sessionUuid; @@ -396,6 +409,6 @@ namespace EMotionFX void FinalizeAllNodeHistoryItems(); EventHistoryItem* FindEventHistoryItem(const ActorInstanceData& actorInstanceData, const EventInfo& eventInfo, float recordTime); uint32 FindFreeEventHistoryItemTrack(const ActorInstanceData& actorInstanceData, EventHistoryItem* item) const; - uint32 FindAnimGraphDataFrameNumber(float timeValue) const; + size_t FindAnimGraphDataFrameNumber(float timeValue) const; }; } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/RepositioningLayerPass.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/RepositioningLayerPass.cpp index afa3d8099d..68c2f2a5c3 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/RepositioningLayerPass.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/RepositioningLayerPass.cpp @@ -26,7 +26,6 @@ namespace EMotionFX RepositioningLayerPass::RepositioningLayerPass(MotionLayerSystem* motionLayerSystem) : LayerPass(motionLayerSystem) { - mHierarchyPath.SetMemoryCategory(EMFX_MEMCATEGORY_MOTIONS_MOTIONSYSTEMS); mLastReposNode = MCORE_INVALIDINDEX32; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/RepositioningLayerPass.h b/Gems/EMotionFX/Code/EMotionFX/Source/RepositioningLayerPass.h index a704f83e21..05f09d6329 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/RepositioningLayerPass.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/RepositioningLayerPass.h @@ -11,7 +11,7 @@ // include required headers #include "EMotionFXConfig.h" #include "LayerPass.h" -#include +#include namespace EMotionFX @@ -59,7 +59,7 @@ namespace EMotionFX private: - MCore::Array mHierarchyPath; /**< The path of node indices to the repositioning node. */ + AZStd::vector mHierarchyPath; /**< The path of node indices to the repositioning node. */ uint32 mLastReposNode; /**< The last repositioning node index that was used. When this changes, the hierarchy path has to be updated. */ /** diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Skeleton.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Skeleton.cpp index e1c6ca88f7..5860a0b452 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Skeleton.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Skeleton.cpp @@ -22,8 +22,6 @@ namespace EMotionFX // constructor Skeleton::Skeleton() { - m_nodes.SetMemoryCategory(EMFX_MEMCATEGORY_SKELETON); - m_rootNodes.SetMemoryCategory(EMFX_MEMCATEGORY_SKELETON); } @@ -46,7 +44,7 @@ namespace EMotionFX { Skeleton* result = Skeleton::Create(); - const uint32 numNodes = m_nodes.GetLength(); + const uint32 numNodes = m_nodes.size(); result->ReserveNodes(numNodes); result->m_rootNodes = m_rootNodes; @@ -65,14 +63,14 @@ namespace EMotionFX // reserve memory void Skeleton::ReserveNodes(uint32 numNodes) { - m_nodes.Reserve(numNodes); + m_nodes.reserve(numNodes); } // add a node void Skeleton::AddNode(Node* node) { - m_nodes.Add(node); + m_nodes.emplace_back(node); m_nodesMap[node->GetNameString()] = node; } @@ -86,7 +84,7 @@ namespace EMotionFX m_nodes[nodeIndex]->Destroy(); } - m_nodes.Remove(nodeIndex); + m_nodes.erase(AZStd::next(begin(m_nodes), nodeIndex)); } @@ -95,14 +93,14 @@ namespace EMotionFX { if (delFromMem) { - const uint32 numNodes = m_nodes.GetLength(); + const uint32 numNodes = m_nodes.size(); for (uint32 i = 0; i < numNodes; ++i) { m_nodes[i]->Destroy(); } } - m_nodes.Clear(); + m_nodes.clear(); m_nodesMap.clear(); m_bindPose.Clear(); } @@ -134,7 +132,7 @@ namespace EMotionFX Node* Skeleton::FindNodeByNameNoCase(const char* name) const { // check the names for all nodes - const uint32 numNodes = m_nodes.GetLength(); + const uint32 numNodes = m_nodes.size(); for (uint32 i = 0; i < numNodes; ++i) { if (AzFramework::StringFunc::Equal(m_nodes[i]->GetNameString().c_str(), name, false /* no case */)) @@ -151,7 +149,7 @@ namespace EMotionFX Node* Skeleton::FindNodeByID(uint32 id) const { // check the ID's for all nodes - const uint32 numNodes = m_nodes.GetLength(); + const uint32 numNodes = m_nodes.size(); for (uint32 i = 0; i < numNodes; ++i) { if (m_nodes[i]->GetID() == id) @@ -180,8 +178,8 @@ namespace EMotionFX // set the number of nodes void Skeleton::SetNumNodes(uint32 numNodes) { - uint32 oldLength = m_nodes.GetLength(); - m_nodes.Resize(numNodes); + uint32 oldLength = m_nodes.size(); + m_nodes.resize(numNodes); for (uint32 i = oldLength; i < numNodes; ++i) { m_nodes[i] = nullptr; @@ -193,7 +191,7 @@ namespace EMotionFX // update the node indices void Skeleton::UpdateNodeIndexValues(uint32 startNode) { - const uint32 numNodes = m_nodes.GetLength(); + const uint32 numNodes = m_nodes.size(); for (uint32 i = startNode; i < numNodes; ++i) { m_nodes[i]->SetNodeIndex(i); @@ -204,35 +202,35 @@ namespace EMotionFX // reserve memory for the root nodes array void Skeleton::ReserveRootNodes(uint32 numNodes) { - m_rootNodes.Reserve(numNodes); + m_rootNodes.reserve(numNodes); } // add a root node void Skeleton::AddRootNode(uint32 nodeIndex) { - m_rootNodes.Add(nodeIndex); + m_rootNodes.emplace_back(nodeIndex); } // remove a given root node void Skeleton::RemoveRootNode(uint32 nr) { - m_rootNodes.Remove(nr); + m_rootNodes.erase(AZStd::next(begin(m_rootNodes), nr)); } // remove all root nodes void Skeleton::RemoveAllRootNodes() { - m_rootNodes.Clear(); + m_rootNodes.clear(); } // log all node names void Skeleton::LogNodes() { - const uint32 numNodes = m_nodes.GetLength(); + const uint32 numNodes = m_nodes.size(); for (uint32 i = 0; i < numNodes; ++i) { MCore::LogInfo("%d = '%s'", i, m_nodes[i]->GetName()); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Skeleton.h b/Gems/EMotionFX/Code/EMotionFX/Source/Skeleton.h index 1b9c09749c..e5887df0f6 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Skeleton.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Skeleton.h @@ -12,7 +12,7 @@ #include "EMotionFXConfig.h" #include "BaseObject.h" #include "Pose.h" -#include +#include namespace EMotionFX @@ -32,7 +32,7 @@ namespace EMotionFX Skeleton* Clone(); - MCORE_INLINE uint32 GetNumNodes() const { return m_nodes.GetLength(); } + MCORE_INLINE size_t GetNumNodes() const { return m_nodes.size(); } MCORE_INLINE Node* GetNode(uint32 index) const { return m_nodes[index]; } void ReserveNodes(uint32 numNodes); @@ -103,7 +103,7 @@ namespace EMotionFX * Get the number of root nodes in the actor. A root node is a node without any parent. * @result The number of root nodes inside the actor. */ - MCORE_INLINE uint32 GetNumRootNodes() const { return m_rootNodes.GetLength(); } + MCORE_INLINE size_t GetNumRootNodes() const { return m_rootNodes.size(); } /** * Get the node number/index of a given root node. @@ -144,9 +144,9 @@ namespace EMotionFX uint32 CalcHierarchyDepthForNode(uint32 nodeIndex) const; private: - MCore::Array m_nodes; /**< The nodes, including root nodes. */ + AZStd::vector m_nodes; /**< The nodes, including root nodes. */ mutable AZStd::unordered_map m_nodesMap; - MCore::Array m_rootNodes; /**< The root nodes only. */ + AZStd::vector m_rootNodes; /**< The root nodes only. */ Pose m_bindPose; /**< The bind pose. */ Skeleton(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/StandardMaterial.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/StandardMaterial.cpp index 8147116048..98a192936e 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/StandardMaterial.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/StandardMaterial.cpp @@ -356,8 +356,6 @@ namespace EMotionFX mIOR = 1.5f; mDoubleSided = true; mWireFrame = false; - - mLayers.SetMemoryCategory(EMFX_MEMCATEGORY_GEOMETRY_MATERIALS); } @@ -398,8 +396,8 @@ namespace EMotionFX standardMaterial->mWireFrame = mWireFrame; // copy the layers - const uint32 numLayers = mLayers.GetLength(); - standardMaterial->mLayers.Resize(numLayers); + const uint32 numLayers = mLayers.size(); + standardMaterial->mLayers.resize(numLayers); for (uint32 i = 0; i < numLayers; ++i) { standardMaterial->mLayers[i] = StandardMaterialLayer::Create(); @@ -420,7 +418,10 @@ namespace EMotionFX { layer->Destroy(); } - mLayers.RemoveByValue(layer); + if (const auto it = AZStd::find(begin(mLayers), end(mLayers), layer); it != end(mLayers)) + { + mLayers.erase(it); + } } } @@ -547,52 +548,52 @@ namespace EMotionFX StandardMaterialLayer* StandardMaterial::AddLayer(StandardMaterialLayer* layer) { - mLayers.Add(layer); + mLayers.emplace_back(layer); return layer; } - uint32 StandardMaterial::GetNumLayers() const + size_t StandardMaterial::GetNumLayers() const { - return mLayers.GetLength(); + return mLayers.size(); } StandardMaterialLayer* StandardMaterial::GetLayer(uint32 nr) { - MCORE_ASSERT(nr < mLayers.GetLength()); + MCORE_ASSERT(nr < mLayers.size()); return mLayers[nr]; } void StandardMaterial::RemoveLayer(uint32 nr, bool delFromMem) { - MCORE_ASSERT(nr < mLayers.GetLength()); + MCORE_ASSERT(nr < mLayers.size()); if (delFromMem) { mLayers[nr]->Destroy(); } - mLayers.Remove(nr); + mLayers.erase(AZStd::next(begin(mLayers), nr)); } void StandardMaterial::RemoveAllLayers() { - const uint32 numLayers = mLayers.GetLength(); + const uint32 numLayers = mLayers.size(); for (uint32 i = 0; i < numLayers; ++i) { mLayers[i]->Destroy(); } - mLayers.Clear(); + mLayers.clear(); } uint32 StandardMaterial::FindLayer(uint32 layerType) const { // search through all layers - const uint32 numLayers = mLayers.GetLength(); + const uint32 numLayers = mLayers.size(); for (uint32 i = 0; i < numLayers; ++i) { if (mLayers[i]->GetType() == layerType) @@ -607,6 +608,6 @@ namespace EMotionFX void StandardMaterial::ReserveLayers(uint32 numLayers) { - mLayers.Reserve(numLayers); + mLayers.reserve(numLayers); } } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/StandardMaterial.h b/Gems/EMotionFX/Code/EMotionFX/Source/StandardMaterial.h index 659157d96d..de637cf3df 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/StandardMaterial.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/StandardMaterial.h @@ -415,7 +415,7 @@ namespace EMotionFX * Get the number of texture layers in this material. * @result The number of layers. */ - uint32 GetNumLayers() const; + size_t GetNumLayers() const; /** * Get a specific layer. @@ -471,7 +471,7 @@ namespace EMotionFX protected: - MCore::Array< StandardMaterialLayer* > mLayers; /**< StandardMaterial layers. */ + AZStd::vector< StandardMaterialLayer* > mLayers; /**< StandardMaterial layers. */ MCore::RGBAColor mAmbient; /**< Ambient color. */ MCore::RGBAColor mDiffuse; /**< Diffuse color. */ MCore::RGBAColor mSpecular; /**< Specular color. */ diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/SubMesh.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/SubMesh.cpp index df7a38486a..fa60ed4033 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/SubMesh.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/SubMesh.cpp @@ -30,7 +30,6 @@ namespace EMotionFX mStartPolygon = startPolygon; mMaterial = materialIndex; - mBones.SetMemoryCategory(EMFX_MEMCATEGORY_GEOMETRY_MESHES); SetNumBones(numBones); } @@ -51,7 +50,7 @@ namespace EMotionFX // clone the submesh SubMesh* SubMesh::Clone(Mesh* newParentMesh) { - SubMesh* clone = aznew SubMesh(newParentMesh, mStartVertex, mStartIndex, mStartPolygon, mNumVertices, mNumIndices, mNumPolygons, mMaterial, mBones.GetLength()); + SubMesh* clone = aznew SubMesh(newParentMesh, mStartVertex, mStartIndex, mStartPolygon, mNumVertices, mNumIndices, mNumPolygons, mMaterial, mBones.size()); clone->mBones = mBones; return clone; } @@ -61,7 +60,7 @@ namespace EMotionFX void SubMesh::RemapBone(uint16 oldNodeNr, uint16 newNodeNr) { // get the number of bones stored inside the submesh - const uint32 numBones = mBones.GetLength(); + const uint32 numBones = mBones.size(); // iterate through all bones and remap the bones for (uint32 i = 0; i < numBones; ++i) @@ -79,7 +78,7 @@ namespace EMotionFX void SubMesh::ReinitBonesArray(SkinningInfoVertexAttributeLayer* skinLayer) { // clear the bones array - mBones.Clear(false); + mBones.clear(); // get shortcuts to the original vertex numbers const uint32* orgVertices = (uint32*)mParentMesh->FindOriginalVertexData(Mesh::ATTRIB_ORGVTXNUMBERS); @@ -101,9 +100,9 @@ namespace EMotionFX const uint32 nodeNr = influence->GetNodeNr(); // put the node index in the bones array in case it isn't in already - if (mBones.Contains(nodeNr) == false) + if (AZStd::find(begin(mBones), end(mBones), nodeNr) == end(mBones)) { - mBones.Add(nodeNr); + mBones.emplace_back(nodeNr); } } } @@ -231,7 +230,7 @@ namespace EMotionFX uint32 SubMesh::FindBoneIndex(uint32 nodeNr) const { - const uint32 numBones = mBones.GetLength(); + const uint32 numBones = mBones.size(); for (uint32 i = 0; i < numBones; ++i) { if (mBones[i] == nodeNr) @@ -247,7 +246,7 @@ namespace EMotionFX // remove the given bone void SubMesh::RemoveBone(uint16 index) { - mBones.Remove(index); + mBones.erase(AZStd::next(begin(mBones), index)); } @@ -255,11 +254,11 @@ namespace EMotionFX { if (numBones == 0) { - mBones.Clear(); + mBones.clear(); } else { - mBones.Resize(numBones); + mBones.resize(numBones); } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/SubMesh.h b/Gems/EMotionFX/Code/EMotionFX/Source/SubMesh.h index df798536da..1cec56efc6 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/SubMesh.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/SubMesh.h @@ -11,7 +11,7 @@ // include the required headers #include "EMotionFXConfig.h" #include "BaseObject.h" -#include +#include namespace EMotionFX @@ -191,7 +191,7 @@ namespace EMotionFX * Get the number of bones used by this submesh. * @result The number of bones used by this submesh. */ - MCORE_INLINE uint32 GetNumBones() const { return mBones.GetLength(); } + MCORE_INLINE size_t GetNumBones() const { return mBones.size(); } /** * Get the node index for a given bone. @@ -205,21 +205,21 @@ namespace EMotionFX * Each integer in the array represents the node number that acts as bone on this submesh. * @result A pointer to the array of bones used by this submesh. */ - MCORE_INLINE uint32* GetBones() { return mBones.GetPtr(); } + MCORE_INLINE uint32* GetBones() { return mBones.data(); } /** * Get direct access to the bones array. * Each integer in the array represents the node number that acts as bone on this submesh. * @result A read only reference to the array of bones used by this submesh. */ - MCORE_INLINE const MCore::Array& GetBonesArray() const { return mBones; } + MCORE_INLINE const AZStd::vector& GetBonesArray() const { return mBones; } /** * Get direct access to the bones array. * Each integer in the array represents the node number that acts as bone on this submesh. * @result A reference to the array of bones used by this submesh. */ - MCORE_INLINE MCore::Array& GetBonesArray() { return mBones; } + MCORE_INLINE AZStd::vector& GetBonesArray() { return mBones; } /** * Reinitialize the bones. @@ -268,7 +268,7 @@ namespace EMotionFX protected: - MCore::Array mBones; /**< The collection of bones. These are stored as node numbers that point into the actor. */ + AZStd::vector mBones; /**< The collection of bones. These are stored as node numbers that point into the actor. */ uint32 mStartVertex; /**< The start vertex number in the vertex data arrays of the parent mesh. */ uint32 mStartIndex; /**< The start index number in the index array of the parent mesh. */ uint32 mStartPolygon; /**< The start polygon number in the polygon vertex count array of the parent mesh. */ diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/ThreadData.h b/Gems/EMotionFX/Code/EMotionFX/Source/ThreadData.h index 1cee75200c..cf66a1543e 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/ThreadData.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/ThreadData.h @@ -13,7 +13,7 @@ #include "BaseObject.h" #include "AnimGraphPosePool.h" #include "AnimGraphRefCountedDataPool.h" -#include +#include namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioManager.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioManager.cpp index 93073891de..c0867139e7 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioManager.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioManager.cpp @@ -432,7 +432,7 @@ namespace EMStudio } // add and return the manipulator - mTransformationManipulators.Add(manipulator); + mTransformationManipulators.emplace_back(manipulator); return manipulator; } @@ -440,12 +440,15 @@ namespace EMStudio // remove the given gizmo from the array void EMStudioManager::RemoveTransformationManipulator(MCommon::TransformationManipulator* manipulator) { - mTransformationManipulators.RemoveByValue(manipulator); + if (const auto it = AZStd::find(begin(mTransformationManipulators), end(mTransformationManipulators), manipulator); it != end(mTransformationManipulators)) + { + mTransformationManipulators.erase(it); + } } // returns the gizmo array - MCore::Array* EMStudioManager::GetTransformationManipulators() + AZStd::vector* EMStudioManager::GetTransformationManipulators() { return &mTransformationManipulators; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioManager.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioManager.h index c485d15b01..62c4b5e115 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioManager.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioManager.h @@ -104,7 +104,7 @@ namespace EMStudio // functions for adding/removing gizmos MCommon::TransformationManipulator* AddTransformationManipulator(MCommon::TransformationManipulator* manipulator); void RemoveTransformationManipulator(MCommon::TransformationManipulator* manipulator); - MCore::Array* GetTransformationManipulators(); + AZStd::vector* GetTransformationManipulators(); void ClearScene(); // remove animgraphs, animgraph instances and actors @@ -115,7 +115,7 @@ namespace EMStudio MCORE_INLINE bool GetSkipSourceControlCommands() { return m_skipSourceControlCommands; } MCORE_INLINE void SetSkipSourceControlCommands(bool skip) { m_skipSourceControlCommands = skip; } private: - MCore::Array mTransformationManipulators; + AZStd::vector mTransformationManipulators; QPointer mMainWindow; QApplication* mApp; PluginManager* mPluginManager; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/FileManager.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/FileManager.h index e27a9c23b5..baf721d2ce 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/FileManager.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/FileManager.h @@ -21,7 +21,7 @@ #include #include "EMStudioConfig.h" #include -#include +#include #include #include #include diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindow.cpp index b3e47725c7..c1c48b3480 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindow.cpp @@ -6,6 +6,7 @@ * */ +#include #include #include #include @@ -1089,14 +1090,14 @@ namespace EMStudio const uint32 numPlugins = pluginManager->GetNumPlugins(); // add each plugin name in an array to sort them - MCore::Array sortedPlugins; - sortedPlugins.Reserve(numPlugins); + AZStd::vector sortedPlugins; + sortedPlugins.reserve(numPlugins); for (uint32 p = 0; p < numPlugins; ++p) { EMStudioPlugin* plugin = pluginManager->GetPlugin(p); - sortedPlugins.Add(plugin->GetName()); + sortedPlugins.emplace_back(plugin->GetName()); } - sortedPlugins.Sort(); + AZStd::sort(begin(sortedPlugins), end(sortedPlugins)); // clear the window menu mCreateWindowMenu->clear(); @@ -1839,7 +1840,7 @@ namespace EMStudio dir.setSorting(QDir::Name); // add each layout - mLayoutNames.Clear(); + mLayoutNames.clear(); AZStd::string filename; const QFileInfoList list = dir.entryInfoList(); const int listSize = list.size(); @@ -1856,12 +1857,12 @@ namespace EMStudio if (extension == "layout") { AzFramework::StringFunc::Path::GetFileName(filename.c_str(), filename); - mLayoutNames.Add(filename); + mLayoutNames.emplace_back(filename); } } // add each menu - const uint32 numLayoutNames = mLayoutNames.GetLength(); + const uint32 numLayoutNames = mLayoutNames.size(); for (uint32 i = 0; i < numLayoutNames; ++i) { QAction* action = mLayoutsMenu->addAction(mLayoutNames[i].c_str()); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindow.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindow.h index a8909380ef..7217259bcb 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindow.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindow.h @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include #include @@ -148,7 +148,7 @@ namespace EMStudio FileManager* GetFileManager() const { return mFileManager; } PreferencesWindow* GetPreferencesWindow() const { return mPreferencesWindow; } - uint32 GetNumLayouts() const { return mLayoutNames.GetLength(); } + size_t GetNumLayouts() const { return mLayoutNames.size(); } const char* GetLayoutName(uint32 index) const { return mLayoutNames[index].c_str(); } const char* GetCurrentLayoutName() const; @@ -195,7 +195,7 @@ namespace EMStudio MysticQt::KeyboardShortcutManager* mShortcutManager; // layouts (application modes) - MCore::Array mLayoutNames; + AZStd::vector mLayoutNames; bool mLayoutLoaded; // menu actions diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NodeHierarchyWidget.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NodeHierarchyWidget.cpp index 6d0355ead0..4aaebc3e3e 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NodeHierarchyWidget.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NodeHierarchyWidget.cpp @@ -51,8 +51,6 @@ namespace EMStudio mMeshIcon = new QIcon(meshIconFilename); mCharacterIcon = new QIcon(iconFilename("Character.svg")); - mActorInstanceIDs.SetMemoryCategory(MEMCATEGORY_EMSTUDIOSDK); - QVBoxLayout* layout = new QVBoxLayout(); layout->setMargin(0); @@ -142,7 +140,7 @@ namespace EMStudio } - void NodeHierarchyWidget::Update(const MCore::Array& actorInstanceIDs, CommandSystem::SelectionList* selectionList) + void NodeHierarchyWidget::Update(const AZStd::vector& actorInstanceIDs, CommandSystem::SelectionList* selectionList) { mActorInstanceIDs = actorInstanceIDs; ConvertFromSelectionList(selectionList); @@ -153,7 +151,7 @@ namespace EMStudio void NodeHierarchyWidget::Update(uint32 actorInstanceID, CommandSystem::SelectionList* selectionList) { - mActorInstanceIDs.Clear(); + mActorInstanceIDs.clear(); if (actorInstanceID == MCORE_INVALIDINDEX32) { @@ -169,12 +167,12 @@ namespace EMStudio continue; } - mActorInstanceIDs.Add(actorInstance->GetID()); + mActorInstanceIDs.emplace_back(actorInstance->GetID()); } } else { - mActorInstanceIDs.Add(actorInstanceID); + mActorInstanceIDs.emplace_back(actorInstanceID); } Update(mActorInstanceIDs, selectionList); @@ -189,7 +187,7 @@ namespace EMStudio mHierarchy->clear(); // get the number actor instances and iterate over them - const uint32 numActorInstances = mActorInstanceIDs.GetLength(); + const uint32 numActorInstances = mActorInstanceIDs.size(); for (uint32 i = 0; i < numActorInstances; ++i) { // get the actor instance by its id @@ -267,7 +265,7 @@ namespace EMStudio AZStd::to_lower(nodeName.begin(), nodeName.end()); EMotionFX::Mesh* mesh = actorInstance->GetActor()->GetMesh(actorInstance->GetLODLevel(), nodeIndex); const bool isMeshNode = (mesh); - const bool isBone = (mBoneList.Find(nodeIndex) != MCORE_INVALIDINDEX32); + const bool isBone = (AZStd::find(begin(mBoneList), end(mBoneList), nodeIndex) != end(mBoneList)); const bool isNode = (isMeshNode == false && isBone == false); return CheckIfNodeVisible(nodeName, isMeshNode, isBone, isNode); @@ -296,7 +294,7 @@ namespace EMStudio const uint32 numChildren = node->GetNumChildNodes(); EMotionFX::Mesh* mesh = actor->GetMesh(actorInstance->GetLODLevel(), nodeIndex); const bool isMeshNode = (mesh); - const bool isBone = (mBoneList.Find(nodeIndex) != MCORE_INVALIDINDEX32); + const bool isBone = (AZStd::find(begin(mBoneList), end(mBoneList), nodeIndex) != end(mBoneList)); const bool isNode = (isMeshNode == false && isBone == false); if (CheckIfNodeVisible(nodeName, isMeshNode, isBone, isNode)) @@ -563,7 +561,6 @@ namespace EMStudio UpdateSelection(); emit OnDoubleClicked(m_selectedNodes); - emit OnDoubleClicked(GetSelectedItemsAsMCoreArray()); } @@ -634,7 +631,6 @@ namespace EMStudio void NodeHierarchyWidget::FireSelectionDoneSignal() { emit OnSelectionDone(m_selectedNodes); - emit OnSelectionDone(GetSelectedItemsAsMCoreArray()); } @@ -645,23 +641,6 @@ namespace EMStudio } - MCore::Array NodeHierarchyWidget::GetSelectedItemsAsMCoreArray() - { - AZStd::vector& selectedItems = GetSelectedItems(); - MCore::Array result; - - const AZ::u32 numSelectedItems = static_cast(selectedItems.size()); - result.Resize(numSelectedItems); - - for (AZ::u32 i = 0; i < numSelectedItems; ++i) - { - result[i] = selectedItems[i]; - } - - return result; - } - - // check if the node with the given name is selected in the window bool NodeHierarchyWidget::CheckIfNodeSelected(const char* nodeName, uint32 actorInstanceID) { @@ -706,7 +685,7 @@ namespace EMStudio m_selectedNodes.clear(); // get the number actor instances and iterate over them - const uint32 numActorInstances = mActorInstanceIDs.GetLength(); + const uint32 numActorInstances = mActorInstanceIDs.size(); for (uint32 i = 0; i < numActorInstances; ++i) { // add the actor to the node hierarchy widget diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NodeHierarchyWidget.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NodeHierarchyWidget.h index 3f0ca1a639..b55062f57b 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NodeHierarchyWidget.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NodeHierarchyWidget.h @@ -68,7 +68,7 @@ namespace EMStudio void SetSelectionMode(bool useSingleSelection); void Update(uint32 actorInstanceID, CommandSystem::SelectionList* selectionList = nullptr); - void Update(const MCore::Array& actorInstanceIDs, CommandSystem::SelectionList* selectionList = nullptr); + void Update(const AZStd::vector& actorInstanceIDs, CommandSystem::SelectionList* selectionList = nullptr); void FireSelectionDoneSignal(); MCORE_INLINE QTreeWidget* GetTreeWidget() { return mHierarchy; } MCORE_INLINE AzQtComponents::FilteredSearchWidget* GetSearchWidget() { return m_searchWidget; } @@ -78,7 +78,6 @@ namespace EMStudio bool CheckIfNodeVisible(const AZStd::string& nodeName, bool isMeshNode, bool isBone, bool isNode); // this calls UpdateSelection() and then returns the member array containing the selected items - MCore::Array GetSelectedItemsAsMCoreArray(); AZStd::vector& GetSelectedItems(); const AZStd::string& GetSearchWidgetText() const { return m_searchWidgetText; } @@ -98,10 +97,6 @@ namespace EMStudio Q_DECLARE_FLAGS(FilterTypes, FilterType) signals: - // Deprecated - void OnSelectionDone(MCore::Array selectedNodes); - void OnDoubleClicked(MCore::Array selectedNodes); - void OnSelectionDone(AZStd::vector selectedNodes); void OnDoubleClicked(AZStd::vector selectedNodes); @@ -138,8 +133,8 @@ namespace EMStudio QIcon* mNodeIcon; QIcon* mMeshIcon; QIcon* mCharacterIcon; - MCore::Array mBoneList; - MCore::Array mActorInstanceIDs; + AZStd::vector mBoneList; + AZStd::vector mActorInstanceIDs; AZStd::string mItemName; AZStd::string mActorInstanceIDString; bool mUseSingleSelection; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NodeSelectionWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NodeSelectionWindow.cpp index 4033ae55a8..e0d562ee0f 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NodeSelectionWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NodeSelectionWindow.cpp @@ -49,7 +49,7 @@ namespace EMStudio connect(mOKButton, &QPushButton::clicked, this, &NodeSelectionWindow::accept); connect(mCancelButton, &QPushButton::clicked, this, &NodeSelectionWindow::reject); connect(this, &NodeSelectionWindow::accepted, this, &NodeSelectionWindow::OnAccept); - connect(mHierarchyWidget, static_cast)>(&NodeHierarchyWidget::OnDoubleClicked), this, &NodeSelectionWindow::OnDoubleClicked); + connect(mHierarchyWidget, static_cast)>(&NodeHierarchyWidget::OnDoubleClicked), this, &NodeSelectionWindow::OnDoubleClicked); // connect the window activation signal to refresh if reactivated //connect( this, SIGNAL(visibilityChanged(bool)), this, SLOT(OnVisibilityChanged(bool)) ); @@ -63,7 +63,7 @@ namespace EMStudio } - void NodeSelectionWindow::OnDoubleClicked(MCore::Array selection) + void NodeSelectionWindow::OnDoubleClicked(AZStd::vector selection) { MCORE_UNUSED(selection); accept(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NodeSelectionWindow.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NodeSelectionWindow.h index af106c50ce..46eabf7b58 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NodeSelectionWindow.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NodeSelectionWindow.h @@ -30,7 +30,7 @@ namespace EMStudio * Example: * connect( mNodeSelectionWindow, SIGNAL(rejected()), this, SLOT(UserWantsToCancel_1()) ); * connect( mNodeSelectionWindow->GetNodeHierarchyWidget()->GetTreeWidget(), SIGNAL(itemSelectionChanged()), this, SLOT(SelectionChanged_2()) ); - * connect( mNodeSelectionWindow->GetNodeHierarchyWidget(), SIGNAL(OnSelectionDone(MCore::Array)), this, SLOT(FinishedSelectionAndPressedOK_3(MCore::Array)) ); + * connect( mNodeSelectionWindow->GetNodeHierarchyWidget(), SIGNAL(OnSelectionDone(AZStd::vector)), this, SLOT(FinishedSelectionAndPressedOK_3(AZStd::vector)) ); */ class EMSTUDIO_API NodeSelectionWindow : public QDialog @@ -43,11 +43,11 @@ namespace EMStudio MCORE_INLINE NodeHierarchyWidget* GetNodeHierarchyWidget() { return mHierarchyWidget; } void Update(uint32 actorInstanceID, CommandSystem::SelectionList* selectionList = nullptr) { mHierarchyWidget->Update(actorInstanceID, selectionList); } - void Update(const MCore::Array& actorInstanceIDs, CommandSystem::SelectionList* selectionList = nullptr) { mHierarchyWidget->Update(actorInstanceIDs, selectionList); } + void Update(const AZStd::vector& actorInstanceIDs, CommandSystem::SelectionList* selectionList = nullptr) { mHierarchyWidget->Update(actorInstanceIDs, selectionList); } public slots: void OnAccept(); - void OnDoubleClicked(MCore::Array selection); + void OnDoubleClicked(AZStd::vector selection); private: NodeHierarchyWidget* mHierarchyWidget; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NotificationWindowManager.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NotificationWindowManager.cpp index a42bc1d54b..9eb2c7f23e 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NotificationWindowManager.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NotificationWindowManager.cpp @@ -33,7 +33,7 @@ namespace EMStudio // compute the height of all notification windows with the spacing int allNotificationWindowsHeight = 0; - const uint32 numNotificationWindows = mNotificationWindows.GetLength(); + const uint32 numNotificationWindows = mNotificationWindows.size(); for (uint32 i = 0; i < numNotificationWindows; ++i) { allNotificationWindowsHeight += mNotificationWindows[i]->geometry().height() + notificationWindowSpacing; @@ -45,7 +45,7 @@ namespace EMStudio notificationWindow->move(mainWindowBottomRight.x() - notificationWindowGeometry.width() - notificationWindowMainWindowPadding, mainWindowBottomRight.y() - allNotificationWindowsHeight - notificationWindowGeometry.height() - notificationWindowMainWindowPadding); // add the notification window in the array - mNotificationWindows.Add(notificationWindow); + mNotificationWindows.emplace_back(notificationWindow); } @@ -53,25 +53,24 @@ namespace EMStudio void NotificationWindowManager::RemoveNotificationWindow(NotificationWindow* notificationWindow) { // find the notification window - const uint32 index = mNotificationWindows.Find(notificationWindow); + auto windowIt = AZStd::find(begin(mNotificationWindows), end(mNotificationWindows), notificationWindow); // if not found, stop here - if (index == MCORE_INVALIDINDEX32) + if (windowIt == end(mNotificationWindows)) { return; } // move down each notification window after this one, spacing is added on the height const int notificationWindowHeight = notificationWindow->geometry().height() + notificationWindowSpacing; - const uint32 numNotificationWindows = mNotificationWindows.GetLength(); - for (uint32 i = index + 1; i < numNotificationWindows; ++i) + for (auto it = windowIt + 1; it != end(mNotificationWindows); ++it) { - const QPoint pos = mNotificationWindows[i]->pos(); - mNotificationWindows[i]->move(pos.x(), pos.y() + notificationWindowHeight); + const QPoint pos = (*it)->pos(); + (*it)->move(pos.x(), pos.y() + notificationWindowHeight); } // remove the notification window - mNotificationWindows.Remove(index); + mNotificationWindows.erase(windowIt); } @@ -83,7 +82,7 @@ namespace EMStudio // move each notification window int currentNotificationWindowHeight = notificationWindowMainWindowPadding; - const uint32 numNotificationWindows = mNotificationWindows.GetLength(); + const uint32 numNotificationWindows = mNotificationWindows.size(); for (uint32 i = 0; i < numNotificationWindows; ++i) { // add the height of the notification window diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NotificationWindowManager.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NotificationWindowManager.h index f71f60fde6..8817f3d451 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NotificationWindowManager.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NotificationWindowManager.h @@ -11,7 +11,7 @@ #if !defined(Q_MOC_RUN) #include "EMStudioConfig.h" #include "NotificationWindow.h" -#include +#include #endif @@ -35,9 +35,9 @@ namespace EMStudio return mNotificationWindows[index]; } - MCORE_INLINE uint32 GetNumNotificationWindow() const + MCORE_INLINE size_t GetNumNotificationWindow() const { - return mNotificationWindows.GetLength(); + return mNotificationWindows.size(); } void OnMovedOrResized(); @@ -53,7 +53,7 @@ namespace EMStudio } private: - MCore::Array mNotificationWindows; + AZStd::vector mNotificationWindows; int32 mVisibleTime; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.cpp index ef281b8301..abbb9b7d81 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.cpp @@ -27,8 +27,6 @@ namespace EMStudio RenderPlugin::RenderPlugin() : DockWidgetPlugin() { - mActors.SetMemoryCategory(MEMCATEGORY_EMSTUDIOSDK_RENDERPLUGINBASE); - mIsVisible = true; mRenderUtil = nullptr; mUpdateCallback = nullptr; @@ -130,7 +128,7 @@ namespace EMStudio void RenderPlugin::CleanEMStudioActors() { // get rid of the actors - const uint32 numActors = mActors.GetLength(); + const uint32 numActors = mActors.size(); for (uint32 i = 0; i < numActors; ++i) { if (mActors[i]) @@ -138,7 +136,7 @@ namespace EMStudio delete mActors[i]; } } - mActors.Clear(); + mActors.clear(); } @@ -159,7 +157,7 @@ namespace EMStudio // get rid of the emstudio actor delete emstudioActor; - mActors.Remove(index); + mActors.erase(AZStd::next(begin(mActors), index)); return true; } @@ -168,8 +166,8 @@ namespace EMStudio MCommon::TransformationManipulator* RenderPlugin::GetActiveManipulator(MCommon::Camera* camera, int32 mousePosX, int32 mousePosY) { // get the current manipulator - MCore::Array* transformationManipulators = GetManager()->GetTransformationManipulators(); - const uint32 numGizmos = transformationManipulators->GetLength(); + AZStd::vector* transformationManipulators = GetManager()->GetTransformationManipulators(); + const uint32 numGizmos = transformationManipulators->size(); // init the active manipulator to nullptr MCommon::TransformationManipulator* activeManipulator = nullptr; @@ -180,7 +178,7 @@ namespace EMStudio for (uint32 i = 0; i < numGizmos; ++i) { // get the current manipulator and check if it exists - MCommon::TransformationManipulator* currentManipulator = transformationManipulators->GetItem(i); + MCommon::TransformationManipulator* currentManipulator = transformationManipulators->at(i); if (currentManipulator == nullptr || currentManipulator->GetIsVisible() == false) { continue; @@ -319,7 +317,7 @@ namespace EMStudio RenderPlugin::EMStudioRenderActor* RenderPlugin::FindEMStudioActor(EMotionFX::ActorInstance* actorInstance, bool doubleCheckInstance) { // get the number of emstudio actors and iterate through them - const uint32 numEMStudioRenderActors = mActors.GetLength(); + const uint32 numEMStudioRenderActors = mActors.size(); for (uint32 i = 0; i < numEMStudioRenderActors; ++i) { EMStudioRenderActor* EMStudioRenderActor = mActors[i]; @@ -331,7 +329,7 @@ namespace EMStudio if (doubleCheckInstance) { // now double check if the actor instance really is in the array of instances of this emstudio actor - const uint32 numActorInstances = EMStudioRenderActor->mActorInstances.GetLength(); + const uint32 numActorInstances = EMStudioRenderActor->mActorInstances.size(); for (uint32 a = 0; a < numActorInstances; ++a) { if (EMStudioRenderActor->mActorInstances[a] == actorInstance) @@ -359,7 +357,7 @@ namespace EMStudio return nullptr; } - const uint32 numEMStudioRenderActors = mActors.GetLength(); + const uint32 numEMStudioRenderActors = mActors.size(); for (uint32 i = 0; i < numEMStudioRenderActors; ++i) { EMStudioRenderActor* EMStudioRenderActor = mActors[i]; @@ -378,7 +376,7 @@ namespace EMStudio uint32 RenderPlugin::FindEMStudioActorIndex(EMStudioRenderActor* EMStudioRenderActor) { // get the number of emstudio actors and iterate through them - const uint32 numEMStudioRenderActors = mActors.GetLength(); + const uint32 numEMStudioRenderActors = mActors.size(); for (uint32 i = 0; i < numEMStudioRenderActors; ++i) { // compare the two emstudio actors and return the current index in case of success @@ -407,7 +405,7 @@ namespace EMStudio void RenderPlugin::AddEMStudioActor(EMStudioRenderActor* emstudioActor) { // add the actor to the list and return success - mActors.Add(emstudioActor); + mActors.emplace_back(emstudioActor); } @@ -440,8 +438,7 @@ namespace EMStudio } } - // 2. Remove invalid, not ready or unused emstudio actors - for (uint32 i = 0; i < mActors.GetLength(); ++i) + for (uint32 i = 0; i < mActors.size(); ++i) { EMStudioRenderActor* emstudioActor = mActors[i]; EMotionFX::Actor* actor = emstudioActor->mActor; @@ -479,7 +476,7 @@ namespace EMStudio if (!emstudioActor) { - for (uint32 j = 0; j < mActors.GetLength(); ++j) + for (uint32 j = 0; j < mActors.size(); ++j) { EMStudioRenderActor* currentEMStudioActor = mActors[j]; if (actor == currentEMStudioActor->mActor) @@ -496,19 +493,17 @@ namespace EMStudio actorInstance->SetCustomData(emstudioActor->mRenderActor); // add the actor instance to the emstudio actor instances in case it is not in yet - if (emstudioActor->mActorInstances.Find(actorInstance) == MCORE_INVALIDINDEX32) + if (AZStd::find(begin(emstudioActor->mActorInstances), end(emstudioActor->mActorInstances), actorInstance) == end(emstudioActor->mActorInstances)) { - emstudioActor->mActorInstances.Add(actorInstance); + emstudioActor->mActorInstances.emplace_back(actorInstance); } } } // 4. Unlink invalid actor instances from the emstudio actors - for (uint32 i = 0; i < mActors.GetLength(); ++i) + for (EMStudioRenderActor* emstudioActor : mActors) { - EMStudioRenderActor* emstudioActor = mActors[i]; - - for (uint32 j = 0; j < emstudioActor->mActorInstances.GetLength();) + for (uint32 j = 0; j < emstudioActor->mActorInstances.size();) { EMotionFX::ActorInstance* emstudioActorInstance = emstudioActor->mActorInstances[j]; bool found = false; @@ -524,7 +519,7 @@ namespace EMStudio if (found == false) { - emstudioActor->mActorInstances.Remove(j); + emstudioActor->mActorInstances.erase(AZStd::next(begin(emstudioActor->mActorInstances), j)); } else { @@ -571,7 +566,7 @@ namespace EMStudio RenderPlugin::EMStudioRenderActor::~EMStudioRenderActor() { // get the number of actor instances and iterate through them - const uint32 numActorInstances = mActorInstances.GetLength(); + const uint32 numActorInstances = mActorInstances.size(); for (uint32 i = 0; i < numActorInstances; ++i) { EMotionFX::ActorInstance* actorInstance = mActorInstances[i]; @@ -1038,7 +1033,7 @@ namespace EMStudio MCommon::RenderUtil::TrajectoryTracePath* tracePath = new MCommon::RenderUtil::TrajectoryTracePath(); tracePath->mActorInstance = actorInstance; - tracePath->mTraceParticles.Reserve(512); + tracePath->mTraceParticles.reserve(512); m_trajectoryTracePaths.emplace_back(tracePath); return tracePath; @@ -1079,13 +1074,13 @@ namespace EMStudio const EMotionFX::Transform& worldTM = actorInstance->GetWorldSpaceTransform(); bool distanceTraveledEnough = false; - if (trajectoryPath->mTraceParticles.GetIsEmpty()) + if (trajectoryPath->mTraceParticles.empty()) { distanceTraveledEnough = true; } else { - const uint32 numParticles = trajectoryPath->mTraceParticles.GetLength(); + const uint32 numParticles = trajectoryPath->mTraceParticles.size(); const EMotionFX::Transform& oldWorldTM = trajectoryPath->mTraceParticles[numParticles - 1].mWorldTM; const AZ::Vector3& oldPos = oldWorldTM.mPosition; @@ -1109,7 +1104,7 @@ namespace EMStudio // create the particle, fill its data and add it to the trajectory trace path MCommon::RenderUtil::TrajectoryPathParticle trajectoryParticle; trajectoryParticle.mWorldTM = worldTM; - trajectoryPath->mTraceParticles.Add(trajectoryParticle); + trajectoryPath->mTraceParticles.emplace_back(trajectoryParticle); // reset the time passed as we just added a new particle trajectoryPath->mTimePassed = 0.0f; @@ -1117,9 +1112,9 @@ namespace EMStudio } // make sure we don't have too many items in our array - if (trajectoryPath->mTraceParticles.GetLength() > 50) + if (trajectoryPath->mTraceParticles.size() > 50) { - trajectoryPath->mTraceParticles.RemoveFirst(); + trajectoryPath->mTraceParticles.erase(begin(trajectoryPath->mTraceParticles)); } } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.h index 7fa0a880d0..27e5504e72 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.h @@ -53,9 +53,9 @@ namespace EMStudio MCORE_MEMORYOBJECTCATEGORY(RenderPlugin::EMStudioRenderActor, MCore::MCORE_DEFAULT_ALIGNMENT, MEMCATEGORY_EMSTUDIOSDK_RENDERPLUGINBASE); EMotionFX::Actor* mActor; - MCore::Array mBoneList; + AZStd::vector mBoneList; RenderGL::GLActor* mRenderActor; - MCore::Array mActorInstances; + AZStd::vector mActorInstances; float mNormalsScaleMultiplier; float mCharacterHeight; float mOffsetFromTrajectoryNode; @@ -203,7 +203,7 @@ namespace EMStudio RenderUpdateCallback* mUpdateCallback; RenderOptions mRenderOptions; - MCore::Array mActors; + AZStd::vector mActors; // view widgets AZStd::vector m_viewWidgets; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderUpdateCallback.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderUpdateCallback.cpp index 6de228fa52..24b4471280 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderUpdateCallback.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderUpdateCallback.cpp @@ -84,13 +84,13 @@ namespace EMStudio const EMotionFX::Transform globalTM = transformData->GetCurrentPose()->GetWorldSpaceTransform(motionExtractionNode->GetNodeIndex()).ProjectedToGroundPlane(); bool distanceTraveledEnough = false; - if (trajectoryPath->mTraceParticles.GetIsEmpty()) + if (trajectoryPath->mTraceParticles.empty()) { distanceTraveledEnough = true; } else { - const uint32 numParticles = trajectoryPath->mTraceParticles.GetLength(); + const uint32 numParticles = trajectoryPath->mTraceParticles.size(); const EMotionFX::Transform& oldGlobalTM = trajectoryPath->mTraceParticles[numParticles - 1].mWorldTM; const AZ::Vector3& oldPos = oldGlobalTM.mPosition; @@ -115,7 +115,7 @@ namespace EMStudio // create the particle, fill its data and add it to the trajectory trace path MCommon::RenderUtil::TrajectoryPathParticle trajectoryParticle; trajectoryParticle.mWorldTM = globalTM; - trajectoryPath->mTraceParticles.Add(trajectoryParticle); + trajectoryPath->mTraceParticles.emplace_back(trajectoryParticle); // reset the time passed as we just added a new particle trajectoryPath->mTimePassed = 0.0f; @@ -123,9 +123,9 @@ namespace EMStudio } // make sure we don't have too many items in our array - if (trajectoryPath->mTraceParticles.GetLength() > 50) + if (trajectoryPath->mTraceParticles.size() > 50) { - trajectoryPath->mTraceParticles.RemoveFirst(); + trajectoryPath->mTraceParticles.erase(begin(trajectoryPath->mTraceParticles)); } } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderWidget.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderWidget.cpp index 25ae2ba2d4..b123f62ac5 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderWidget.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderWidget.cpp @@ -38,8 +38,6 @@ namespace EMStudio //mLines.SetMemoryCategory(MEMCATEGORY_EMSTUDIOSDK_RENDERPLUGINBASE); //mLines.Reserve(2048); - mSelectedActorInstances.SetMemoryCategory(MEMCATEGORY_EMSTUDIOSDK_RENDERPLUGINBASE); - // camera used to render the little axis on the bottom left mAxisFakeCamera = new MCommon::OrthographicCamera(MCommon::OrthographicCamera::VIEWMODE_FRONT); @@ -255,13 +253,13 @@ namespace EMStudio } // update size/bounding volumes volumes of all existing gizmos - const MCore::Array* transformationManipulators = GetManager()->GetTransformationManipulators(); + const AZStd::vector* transformationManipulators = GetManager()->GetTransformationManipulators(); // render all visible gizmos - const uint32 numGizmos = transformationManipulators->GetLength(); + const uint32 numGizmos = transformationManipulators->size(); for (uint32 i = 0; i < numGizmos; ++i) { - MCommon::TransformationManipulator* activeManipulator = transformationManipulators->GetItem(i); + MCommon::TransformationManipulator* activeManipulator = transformationManipulators->at(i); if (activeManipulator == nullptr) { continue; @@ -619,7 +617,7 @@ namespace EMStudio } } - mSelectedActorInstances.Clear(false); + mSelectedActorInstances.clear(); if (ctrlPressed) { @@ -627,13 +625,13 @@ namespace EMStudio const uint32 numSelectedActorInstances = selection.GetNumSelectedActorInstances(); for (uint32 i = 0; i < numSelectedActorInstances; ++i) { - mSelectedActorInstances.Add(selection.GetActorInstance(i)); + mSelectedActorInstances.emplace_back(selection.GetActorInstance(i)); } } if (selectedActorInstance) { - mSelectedActorInstances.Add(selectedActorInstance); + mSelectedActorInstances.emplace_back(selectedActorInstance); } CommandSystem::SelectActorInstancesUsingCommands(mSelectedActorInstances); @@ -1008,14 +1006,14 @@ namespace EMStudio return; } - MCore::Array* transformationManipulators = GetManager()->GetTransformationManipulators(); - const uint32 numGizmos = transformationManipulators->GetLength(); + AZStd::vector* transformationManipulators = GetManager()->GetTransformationManipulators(); + const uint32 numGizmos = transformationManipulators->size(); // render all visible gizmos for (uint32 i = 0; i < numGizmos; ++i) { // update the gizmos - MCommon::TransformationManipulator* activeManipulator = transformationManipulators->GetItem(i); + MCommon::TransformationManipulator* activeManipulator = transformationManipulators->at(i); // update the gizmos if there is an active manipulator if (activeManipulator == nullptr) @@ -1048,7 +1046,7 @@ namespace EMStudio } // render custom triangles - const uint32 numTriangles = mTriangles.GetLength(); + const uint32 numTriangles = mTriangles.size(); for (uint32 i = 0; i < numTriangles; ++i) { const Triangle& curTri = mTriangles[i]; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderWidget.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderWidget.h index 10722f744a..d2ec5d71ea 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderWidget.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderWidget.h @@ -98,8 +98,8 @@ namespace EMStudio virtual void Update() = 0; // line rendering helper functions - MCORE_INLINE void AddTriangle(const AZ::Vector3& posA, const AZ::Vector3& posB, const AZ::Vector3& posC, const AZ::Vector3& normalA, const AZ::Vector3& normalB, const AZ::Vector3& normalC, uint32 color) { mTriangles.Add(Triangle(posA, posB, posC, normalA, normalB, normalC, color)); } - MCORE_INLINE void ClearTriangles() { mTriangles.Clear(false); } + MCORE_INLINE void AddTriangle(const AZ::Vector3& posA, const AZ::Vector3& posB, const AZ::Vector3& posC, const AZ::Vector3& normalA, const AZ::Vector3& normalB, const AZ::Vector3& normalC, uint32 color) { mTriangles.emplace_back(Triangle(posA, posB, posC, normalA, normalB, normalC, color)); } + MCORE_INLINE void ClearTriangles() { mTriangles.clear(); } void RenderTriangles(); // helper rendering functions @@ -139,10 +139,10 @@ namespace EMStudio RenderPlugin* mPlugin; RenderViewWidget* mViewWidget; - MCore::Array mTriangles; + AZStd::vector mTriangles; EventHandler mEventHandler; - MCore::Array mSelectedActorInstances; + AZStd::vector mSelectedActorInstances; MCommon::TransformationManipulator* mActiveTransformManip; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphPlugin.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphPlugin.cpp index 20d4b04acc..5026af3b06 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphPlugin.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphPlugin.cpp @@ -808,11 +808,11 @@ namespace EMStudio const AZStd::string& paramName = animGraphInstance->GetAnimGraph()->FindParameter(paramIndex)->GetName(); // iterate over all gizmos that are active - MCore::Array* gizmos = manager->GetTransformationManipulators(); - const uint32 numGizmos = gizmos->GetLength(); + AZStd::vector* gizmos = manager->GetTransformationManipulators(); + const uint32 numGizmos = gizmos->size(); for (uint32 i = 0; i < numGizmos; ++i) { - MCommon::TransformationManipulator* gizmo = gizmos->GetItem(i); + MCommon::TransformationManipulator* gizmo = gizmos->at(i); // check the gizmo name if (paramName == gizmo->GetName()) diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphPlugin.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphPlugin.h index c741b0cc6e..ad4098308d 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphPlugin.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphPlugin.h @@ -17,7 +17,7 @@ #include "../../../../EMStudioSDK/Source/EMStudioManager.h" #include -#include +#include #include #include diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendGraphWidgetCallback.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendGraphWidgetCallback.cpp deleted file mode 100644 index 42550753ca..0000000000 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendGraphWidgetCallback.cpp +++ /dev/null @@ -1,409 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -// include the required headers -#include "BlendGraphWidgetCallback.h" -//#include "GraphNode.h" -#include "AnimGraphPlugin.h" -#include "NodeGraph.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -namespace EMStudio -{ - // constructor - BlendGraphWidgetCallback::BlendGraphWidgetCallback(BlendGraphWidget* widget) - : GraphWidgetCallback(widget) - { - mBlendGraphWidget = widget; - - mFont.setPixelSize(12); - mTextOptions.setAlignment(Qt::AlignCenter); - mFontMetrics = new QFontMetrics(mFont); - } - - - // destructor - BlendGraphWidgetCallback::~BlendGraphWidgetCallback() - { - delete mFontMetrics; - } - - - void BlendGraphWidgetCallback::DrawOverlay(QPainter& painter) - { - // get the plugin and return directly in case we're not showing the processed nodes - AnimGraphPlugin* plugin = mBlendGraphWidget->GetPlugin(); - //if (plugin->GetShowProcessed() == false) - // return; - - // if we're going to display some visualization information - // if (plugin->GetDisplayPlaySpeeds() || plugin->GetDisplayGlobalWeights() || plugin->GetDisplaySyncStatus()) - if (plugin->GetDisplayFlags() != 0) - { - // get the active graph and the corresponding emfx node and return if they are invalid or in case the opened node is no blend tree - NodeGraph* activeGraph = mBlendGraphWidget->GetActiveGraph(); - EMotionFX::AnimGraphNode* currentNode = mBlendGraphWidget->GetCurrentNode(); - if (activeGraph == nullptr || currentNode == nullptr) - { - return; - } - - // get the currently selected actor instance and its anim graph instance and return if they are not valid - EMotionFX::ActorInstance* actorInstance = GetCommandManager()->GetCurrentSelection().GetSingleActorInstance(); - if (actorInstance == nullptr || actorInstance->GetAnimGraphInstance() == nullptr) - { - return; - } - - EMotionFX::AnimGraphInstance* animGraphInstance = actorInstance->GetAnimGraphInstance(); - - // get the number of nodes and iterate through them - const uint32 numNodes = activeGraph->GetNumNodes(); - for (uint32 i = 0; i < numNodes; ++i) - { - GraphNode* graphNode = activeGraph->GetNode(i); - EMotionFX::AnimGraphNode* emfxNode = currentNode->RecursiveFindNodeById(graphNode->GetId()); - - // skip invisible graph nodes - if (graphNode->GetIsVisible() == false) - { - continue; - } - - // make sure the corresponding anim graph node is valid - if (emfxNode == nullptr) - { - continue; - } - - // skip non-processed nodes and nodes that have no output pose - if (emfxNode->GetHasOutputPose() == false || graphNode->GetIsProcessed() == false) - { - continue; - } - - if (graphNode->GetIsHighlighted()) - { - continue; - } - - // get the unique data - EMotionFX::AnimGraphNodeData* uniqueData = emfxNode->FindUniqueNodeData(animGraphInstance); - - // draw the background darkened rect - uint32 requiredHeight = 5; - const uint32 rectWidth = 155; - const uint32 heightSpacing = 11; - if (plugin->GetIsDisplayFlagEnabled(AnimGraphPlugin::DISPLAYFLAG_PLAYSPEED)) - { - requiredHeight += heightSpacing; - } - if (plugin->GetIsDisplayFlagEnabled(AnimGraphPlugin::DISPLAYFLAG_GLOBALWEIGHT)) - { - requiredHeight += heightSpacing; - } - if (plugin->GetIsDisplayFlagEnabled(AnimGraphPlugin::DISPLAYFLAG_SYNCSTATUS)) - { - requiredHeight += heightSpacing; - } - if (plugin->GetIsDisplayFlagEnabled(AnimGraphPlugin::DISPLAYFLAG_PLAYPOSITION)) - { - requiredHeight += heightSpacing; - } - const QRect& nodeRect = graphNode->GetFinalRect(); - QRect textRect(nodeRect.center().x() - rectWidth / 2, nodeRect.center().y() - requiredHeight / 2, rectWidth, requiredHeight); - const uint32 alpha = (graphNode->GetIsHighlighted()) ? 225 : 175; - const QColor backgroundColor(0, 0, 0, alpha); - painter.setBrush(backgroundColor); - painter.setPen(Qt::black); - painter.drawRect(textRect); - - QColor textColor(255, 255, 0); - //textColor = graphNode->GetBaseColor(); - if (graphNode->GetIsHighlighted()) - { - textColor = QColor(0, 255, 0); - } - - painter.setPen(textColor); - painter.setFont(mFont); - - QPoint textPosition = textRect.topLeft(); - textPosition.setX(textPosition.x() + 3); - textPosition.setY(textPosition.y() + 11); - - // add the playspeed - if (plugin->GetIsDisplayFlagEnabled(AnimGraphPlugin::DISPLAYFLAG_PLAYSPEED)) - { - mQtTempString.sprintf("Play Speed = %.2f", emfxNode->GetPlaySpeed(animGraphInstance)); - painter.drawText(textPosition, mQtTempString); - textPosition.setY(textPosition.y() + heightSpacing); - } - - // add the global weight - if (plugin->GetIsDisplayFlagEnabled(AnimGraphPlugin::DISPLAYFLAG_GLOBALWEIGHT)) - { - mQtTempString.sprintf("Global Weight = %.2f", uniqueData->GetGlobalWeight()); - painter.drawText(textPosition, mQtTempString); - textPosition.setY(textPosition.y() + heightSpacing); - } - - // add the sync - if (plugin->GetIsDisplayFlagEnabled(AnimGraphPlugin::DISPLAYFLAG_SYNCSTATUS)) - { - mQtTempString.sprintf("Synced = %s", animGraphInstance->GetIsSynced(emfxNode->GetObjectIndex()) ? "Yes" : "No"); - painter.drawText(textPosition, mQtTempString); - textPosition.setY(textPosition.y() + heightSpacing); - } - - // add the play position - if (plugin->GetIsDisplayFlagEnabled(AnimGraphPlugin::DISPLAYFLAG_PLAYPOSITION)) - { - mQtTempString.sprintf("Play Time = %.3f / %.3f", uniqueData->GetCurrentPlayTime(), uniqueData->GetDuration()); - painter.drawText(textPosition, mQtTempString); - textPosition.setY(textPosition.y() + heightSpacing); - } - } - } - - - const EMotionFX::ActorInstance* actorInstance = GetCommandManager()->GetCurrentSelection().GetSingleActorInstance(); - if (!actorInstance) - { - return; - } - - EMotionFX::AnimGraphInstance* animGraphInstance = actorInstance->GetAnimGraphInstance(); - if (!animGraphInstance) - { - return; - } - - // get the active graph and the corresponding emfx node and return if they are invalid or in case the opened node is no blend tree - NodeGraph* activeGraph = mBlendGraphWidget->GetActiveGraph(); - EMotionFX::AnimGraphNode* currentNode = mBlendGraphWidget->GetCurrentNode(); - - if (!activeGraph || !currentNode || azrtti_typeid(currentNode) != azrtti_typeid()) - { - return; - } - - const EMotionFX::AnimGraph* simulatedAnimGraph = animGraphInstance->GetAnimGraph(); - const EMotionFX::AnimGraph* renderedAnimGraph = currentNode->GetAnimGraph(); - if (simulatedAnimGraph != renderedAnimGraph) - { - AzFramework::StringFunc::Path::GetFileName(simulatedAnimGraph->GetFileName(), m_tempStringA); - AzFramework::StringFunc::Path::GetFileName(renderedAnimGraph->GetFileName(), m_tempStringB); - - m_tempStringC = AZStd::string::format("Simulated anim graph on character (%s) differs from the currently shown one (%s).", m_tempStringA.c_str(), m_tempStringB.c_str()); - GraphNode::RenderText(painter, m_tempStringC.c_str(), QColor(255, 0, 0), mFont, *mFontMetrics, Qt::AlignLeft, QRect(8, 0, 50, 20)); - } - - if (activeGraph->GetScale() < 0.5f) - { - return; - } - - // get the number of nodes and iterate through them - const uint32 numNodes = activeGraph->GetNumNodes(); - for (uint32 i = 0; i < numNodes; ++i) - { - GraphNode* graphNode = activeGraph->GetNode(i); - EMotionFX::AnimGraphNode* emfxNode = currentNode->RecursiveFindNodeById(graphNode->GetId()); - - // make sure the corresponding anim graph node is valid - if (emfxNode == nullptr) - { - continue; - } - - // iterate through all connections connected to this node - const uint32 numConnections = graphNode->GetNumConnections(); - for (uint32 c = 0; c < numConnections; ++c) - { - NodeConnection* visualConnection = graphNode->GetConnection(c); - - // get the source and target nodes - GraphNode* sourceNode = visualConnection->GetSourceNode(); - EMotionFX::AnimGraphNode* emfxSourceNode = currentNode->RecursiveFindNodeById(sourceNode->GetId()); - GraphNode* targetNode = visualConnection->GetTargetNode(); - EMotionFX::AnimGraphNode* emfxTargetNode = currentNode->RecursiveFindNodeById(targetNode->GetId()); - - //QColor color(255,0,255); - QColor color = visualConnection->GetTargetNode()->GetInputPort(visualConnection->GetInputPortNr())->GetColor(); - - // only show values for connections that are processed - if (visualConnection->GetIsProcessed() == false) - { - continue; - } - - const uint32 inputPortNr = visualConnection->GetInputPortNr(); - const uint32 outputPortNr = visualConnection->GetOutputPortNr(); - MCore::Attribute* attribute = emfxSourceNode->GetOutputValue(animGraphInstance, outputPortNr); - - // fill the string with data - m_tempStringA.clear(); - switch (attribute->GetType()) - { - // float attributes - case MCore::AttributeFloat::TYPE_ID: - { - MCore::AttributeFloat* floatAttribute = static_cast(attribute); - m_tempStringA = AZStd::string::format("%.2f", floatAttribute->GetValue()); - break; - } - - // vector 2 attributes - case MCore::AttributeVector2::TYPE_ID: - { - MCore::AttributeVector2* vecAttribute = static_cast(attribute); - AZ::Vector2 vec = vecAttribute->GetValue(); - m_tempStringA = AZStd::string::format("(%.2f, %.2f)", static_cast(vec.GetX()), static_cast(vec.GetY())); - break; - } - - // vector 3 attributes - case MCore::AttributeVector3::TYPE_ID: - { - MCore::AttributeVector3* vecAttribute = static_cast(attribute); - AZ::PackedVector3f vec = vecAttribute->GetValue(); - m_tempStringA = AZStd::string::format("(%.2f, %.2f, %.2f)", static_cast(vec.GetX()), static_cast(vec.GetY()), static_cast(vec.GetZ())); - break; - } - - // vector 4 attributes - case MCore::AttributeVector4::TYPE_ID: - { - MCore::AttributeVector4* vecAttribute = static_cast(attribute); - AZ::Vector4 vec = vecAttribute->GetValue(); - m_tempStringA = AZStd::string::format("(%.2f, %.2f, %.2f, %.2f)", static_cast(vec.GetX()), static_cast(vec.GetY()), static_cast(vec.GetZ()), static_cast(vec.GetW())); - break; - } - - // boolean attributes - case MCore::AttributeBool::TYPE_ID: - { - MCore::AttributeBool* boolAttribute = static_cast(attribute); - m_tempStringA = AZStd::string::format("%s", AZStd::to_string(boolAttribute->GetValue()).c_str()); - break; - } - - // rotation attributes - case MCore::AttributeQuaternion::TYPE_ID: - { - MCore::AttributeQuaternion* quatAttribute = static_cast(attribute); - const AZ::Vector3 eulerAngles = quatAttribute->GetValue().ToEuler(); - m_tempStringA = AZStd::string::format("(%.2f, %.2f, %.2f)", static_cast(eulerAngles.GetX()), static_cast(eulerAngles.GetY()), static_cast(eulerAngles.GetZ())); - break; - } - - - // pose attribute - case EMotionFX::AttributePose::TYPE_ID: - { - // handle blend 2 nodes - if (azrtti_typeid(emfxTargetNode) == azrtti_typeid()) - { - // type-cast the target node to our blend node - EMotionFX::BlendTreeBlend2Node* blendNode = static_cast(emfxTargetNode); - - // get the weight from the input port - float weight = blendNode->GetInputNumberAsFloat(animGraphInstance, EMotionFX::BlendTreeBlend2Node::INPUTPORT_WEIGHT); - weight = MCore::Clamp(weight, 0.0f, 1.0f); - - // map the weight to the connection - if (inputPortNr == 0) - { - m_tempStringA = AZStd::string::format("%.2f", 1.0f - weight); - } - else - { - m_tempStringA = AZStd::string::format("%.2f", weight); - } - } - - // handle blend N nodes - if (azrtti_typeid(emfxTargetNode) == azrtti_typeid()) - { - // type-cast the target node to our blend node - EMotionFX::BlendTreeBlendNNode* blendNode = static_cast(emfxTargetNode); - - // get two nodes that we receive input poses from, and get the blend weight - float weight; - EMotionFX::AnimGraphNode* nodeA; - EMotionFX::AnimGraphNode* nodeB; - uint32 poseIndexA; - uint32 poseIndexB; - blendNode->FindBlendNodes(animGraphInstance, &nodeA, &nodeB, &poseIndexA, &poseIndexB, &weight); - - // map the weight to the connection - if (inputPortNr == poseIndexA) - { - m_tempStringA = AZStd::string::format("%.2f", 1.0f - weight); - } - else - { - m_tempStringA = AZStd::string::format("%.2f", weight); - } - } - break; - } - - default: - { - attribute->ConvertToString(m_mcoreTempString); - m_tempStringA = m_mcoreTempString.c_str(); - } - } - - // only display the value in case it is not empty - if (!m_tempStringA.empty()) - { - QPoint connectionAttachPoint = visualConnection->CalcFinalRect().center(); - - int halfTextHeight = 6; - int textWidth = mFontMetrics->width(m_tempStringA.c_str()); - int halfTextWidth = textWidth / 2; - - QRect textRect(connectionAttachPoint.x() - halfTextWidth - 1, connectionAttachPoint.y() - halfTextHeight, textWidth + 4, halfTextHeight * 2); - QPoint textPosition = textRect.bottomLeft(); - textPosition.setY(textPosition.y() - 1); - textPosition.setX(textPosition.x() + 2); - - const QColor backgroundColor(30, 30, 30); - - // draw the background rect for the text - painter.setBrush(backgroundColor); - painter.setPen(Qt::black); - painter.drawRect(textRect); - - // draw the text - painter.setPen(color); - painter.setFont(mFont); - // OLD: - //painter.drawText( textPosition, mTempString.c_str() ); - // NEW: - GraphNode::RenderText(painter, m_tempStringA.c_str(), color, mFont, *mFontMetrics, Qt::AlignCenter, textRect); - } - } - } - } -} // namespace EMStudio - -#include diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendGraphWidgetCallback.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendGraphWidgetCallback.h deleted file mode 100644 index 399c679a29..0000000000 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendGraphWidgetCallback.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -#ifndef __EMSTUDIO_BLENDGRAPHWIDGETCALLBACK_H -#define __EMSTUDIO_BLENDGRAPHWIDGETCALLBACK_H - -// include required headers -#if !defined(Q_MOC_RUN) -#include -#include "../StandardPluginsConfig.h" -#include "GraphWidgetCallback.h" -#include "BlendGraphWidget.h" -#include -#include -#include -#endif - - -namespace EMStudio -{ - // blend graph widget callback - class BlendGraphWidgetCallback - : public GraphWidgetCallback - { - MCORE_MEMORYOBJECTCATEGORY(BlendGraphWidgetCallback, EMFX_DEFAULT_ALIGNMENT, MEMCATEGORY_STANDARDPLUGINS_ANIMGRAPH); - - public: - BlendGraphWidgetCallback(BlendGraphWidget* widget); - virtual ~BlendGraphWidgetCallback(); - - void DrawOverlay(QPainter& painter); - - private: - BlendGraphWidget* mBlendGraphWidget; - - QFont mFont; - QString mQtTempString; - QTextOption mTextOptions; - QFontMetrics* mFontMetrics; - AZStd::string m_tempStringA; - AZStd::string m_tempStringB; - AZStd::string m_tempStringC; - AZStd::string m_mcoreTempString; - }; -} // namespace EMStudio - - -#endif diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendNodeSelectionWindow.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendNodeSelectionWindow.h index 048d79a696..4ec48bbffb 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendNodeSelectionWindow.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendNodeSelectionWindow.h @@ -29,7 +29,7 @@ namespace EMStudio * Example: * connect( mNodeSelectionWindow, SIGNAL(rejected()), this, SLOT(UserWantsToCancel_1()) ); * connect( mNodeSelectionWindow->GetNodeHierarchyWidget()->GetTreeWidget(), SIGNAL(itemSelectionChanged()), this, SLOT(SelectionChanged_2()) ); - * connect( mNodeSelectionWindow->GetNodeHierarchyWidget(), SIGNAL(OnSelectionDone(MCore::Array)), this, SLOT(FinishedSelectionAndPressedOK_3(MCore::Array)) ); + * connect( mNodeSelectionWindow->GetNodeHierarchyWidget(), SIGNAL(OnSelectionDone(AZStd::vector)), this, SLOT(FinishedSelectionAndPressedOK_3(AZStd::vector)) ); */ class BlendNodeSelectionWindow : public QDialog diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendTreeVisualNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendTreeVisualNode.cpp index 2f86196068..43225692ac 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendTreeVisualNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendTreeVisualNode.cpp @@ -40,7 +40,7 @@ namespace EMStudio // add all input ports const AZStd::vector& inPorts = mEMFXNode->GetInputPorts(); const uint32 numInputs = static_cast(inPorts.size()); - mInputPorts.Reserve(numInputs); + mInputPorts.reserve(numInputs); for (uint32 i = 0; i < numInputs; ++i) { NodePort* port = AddInputPort(false); @@ -53,7 +53,7 @@ namespace EMStudio // add all output ports const AZStd::vector& outPorts = mEMFXNode->GetOutputPorts(); const uint32 numOutputs = static_cast(outPorts.size()); - mOutputPorts.Reserve(numOutputs); + mOutputPorts.reserve(numOutputs); for (uint32 i = 0; i < numOutputs; ++i) { NodePort* port = AddOutputPort(false); @@ -112,7 +112,6 @@ namespace EMStudio default: return QColor(50, 250, 250); } - ; } @@ -303,7 +302,7 @@ namespace EMStudio { // draw the input ports QColor portBrushColor, portPenColor; - const uint32 numInputs = mInputPorts.GetLength(); + const uint32 numInputs = mInputPorts.size(); for (uint32 i = 0; i < numInputs; ++i) { // get the input port and the corresponding rect @@ -322,7 +321,7 @@ namespace EMStudio if (GetHasVisualOutputPorts()) { // draw the output ports - const uint32 numOutputs = mOutputPorts.GetLength(); + const uint32 numOutputs = mOutputPorts.size(); for (uint32 i = 0; i < numOutputs; ++i) { // get the output port and the corresponding rect @@ -456,7 +455,7 @@ namespace EMStudio painter.setFont(mPortNameFont); // draw input port text - const uint32 numInputs = mInputPorts.GetLength(); + const uint32 numInputs = mInputPorts.size(); for (uint32 i = 0; i < numInputs; ++i) { NodePort* inputPort = &mInputPorts[i]; @@ -469,7 +468,7 @@ namespace EMStudio } // draw output port text - const uint32 numOutputs = mOutputPorts.GetLength(); + const uint32 numOutputs = mOutputPorts.size(); for (uint32 i = 0; i < numOutputs; ++i) { NodePort* outputPort = &mOutputPorts[i]; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GameControllerWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GameControllerWindow.cpp index 47bb9660a8..5ce488ee70 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GameControllerWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GameControllerWindow.cpp @@ -346,11 +346,11 @@ namespace EMStudio // add all parameters // uint32 startRow = 0; - mParameterInfos.Clear(); + mParameterInfos.clear(); const EMotionFX::ValueParameterVector& parameters = animGraph->RecursivelyGetValueParameters(); const size_t numParameters = parameters.size(); - mParameterInfos.Reserve(static_cast(numParameters)); + mParameterInfos.reserve(static_cast(numParameters)); for (size_t parameterIndex = 0; parameterIndex < numParameters; ++parameterIndex) { @@ -478,7 +478,7 @@ namespace EMStudio paramInfo.mMode = modeComboBox; paramInfo.mInvert = invertCheckbox; paramInfo.mValue = valueEdit; - mParameterInfos.Add(paramInfo); + mParameterInfos.emplace_back(paramInfo); // update the interface UpdateParameterInterface(¶mInfo); @@ -490,7 +490,7 @@ namespace EMStudio mButtonGridLayout->setMargin(0); // clear the button infos - mButtonInfos.Clear(); + mButtonInfos.clear(); // get the number of buttons and iterate through them #if AZ_TRAIT_EMOTIONFX_HAS_GAME_CONTROLLER @@ -520,15 +520,15 @@ namespace EMStudio modeComboBox->setCurrentIndex(settingsInfo->m_mode); mButtonGridLayout->addWidget(modeComboBox, i, 1); - mButtonInfos.Add(ButtonInfo(i, modeComboBox)); + mButtonInfos.emplace_back(ButtonInfo(i, modeComboBox)); // reinit the dynamic part of the button layout ReInitButtonInterface(i); } // real time preview of the controller - mPreviewLabels.Clear(); - mPreviewLabels.Resize(GameController::NUM_ELEMENTS + 1); + mPreviewLabels.clear(); + mPreviewLabels.resize(GameController::NUM_ELEMENTS + 1); QVBoxLayout* realtimePreviewLayout = new QVBoxLayout(); QGridLayout* previewGridLayout = new QGridLayout(); previewGridLayout->setAlignment(Qt::AlignTop); @@ -701,7 +701,7 @@ namespace EMStudio GameControllerWindow::ButtonInfo* GameControllerWindow::FindButtonInfo(QWidget* widget) { // get the number of button infos and iterate through them - const uint32 numButtonInfos = mButtonInfos.GetLength(); + const uint32 numButtonInfos = mButtonInfos.size(); for (uint32 i = 0; i < numButtonInfos; ++i) { if (mButtonInfos[i].mWidget == widget) @@ -718,7 +718,7 @@ namespace EMStudio GameControllerWindow::ParameterInfo* GameControllerWindow::FindParamInfoByModeComboBox(QComboBox* comboBox) { // get the number of parameter infos and iterate through them - const uint32 numParamInfos = mParameterInfos.GetLength(); + const uint32 numParamInfos = mParameterInfos.size(); for (uint32 i = 0; i < numParamInfos; ++i) { if (mParameterInfos[i].mMode == comboBox) @@ -736,7 +736,7 @@ namespace EMStudio GameControllerWindow::ParameterInfo* GameControllerWindow::FindButtonInfoByAttributeInfo(const EMotionFX::Parameter* parameter) { // get the number of parameter infos and iterate through them - const uint32 numParamInfos = mParameterInfos.GetLength(); + const uint32 numParamInfos = mParameterInfos.size(); for (uint32 i = 0; i < numParamInfos; ++i) { if (mParameterInfos[i].mParameter == parameter) @@ -1154,7 +1154,7 @@ namespace EMStudio GameControllerWindow::ParameterInfo* GameControllerWindow::FindParamInfoByAxisComboBox(QComboBox* comboBox) { // get the number of parameter infos and iterate through them - const uint32 numParamInfos = mParameterInfos.GetLength(); + const uint32 numParamInfos = mParameterInfos.size(); for (uint32 i = 0; i < numParamInfos; ++i) { if (mParameterInfos[i].mAxis == comboBox) @@ -1232,7 +1232,7 @@ namespace EMStudio GameControllerWindow::ParameterInfo* GameControllerWindow::FindParamInfoByCheckBox(QCheckBox* checkBox) { // get the number of parameter infos and iterate through them - const uint32 numParamInfos = mParameterInfos.GetLength(); + const uint32 numParamInfos = mParameterInfos.size(); for (uint32 i = 0; i < numParamInfos; ++i) { if (mParameterInfos[i].mInvert == checkBox) diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GameControllerWindow.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GameControllerWindow.h index 7236842ef0..c9ea776337 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GameControllerWindow.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GameControllerWindow.h @@ -14,7 +14,7 @@ #include -#include +#include #include #include #include @@ -154,9 +154,9 @@ namespace EMStudio void UpdateGameControllerComboBox(); AnimGraphPlugin* mPlugin; - MCore::Array mPreviewLabels; - MCore::Array mParameterInfos; - MCore::Array mButtonInfos; + AZStd::vector mPreviewLabels; + AZStd::vector mParameterInfos; + AZStd::vector mButtonInfos; QBasicTimer mInterfaceTimer; QBasicTimer mGameControllerTimer; AZ::Debug::Timer mDeltaTimer; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GraphNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GraphNode.cpp index fe2e5894c4..6bf1c4d45a 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GraphNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GraphNode.cpp @@ -25,10 +25,6 @@ namespace EMStudio GraphNode::GraphNode(const QModelIndex& modelIndex, const char* name, uint32 numInputs, uint32 numOutputs) : m_modelIndex(modelIndex) { - mConnections.SetMemoryCategory(MEMCATEGORY_STANDARDPLUGINS_ANIMGRAPH); - mInputPorts.SetMemoryCategory(MEMCATEGORY_STANDARDPLUGINS_ANIMGRAPH); - mOutputPorts.SetMemoryCategory(MEMCATEGORY_STANDARDPLUGINS_ANIMGRAPH); - mRect = QRect(0, 0, 200, 128); mBaseColor = QColor(74, 63, 238); mVisualizeColor = QColor(0, 255, 0); @@ -66,8 +62,8 @@ namespace EMStudio mTextOptionsAlignRight.setAlignment(Qt::AlignRight | Qt::AlignVCenter); mTextOptionsAlignLeft.setAlignment(Qt::AlignLeft | Qt::AlignVCenter); - mInputPorts.Resize(numInputs); - mOutputPorts.Resize(numOutputs); + mInputPorts.resize(numInputs); + mOutputPorts.resize(numOutputs); // initialize the port metrics mPortFontMetrics = new QFontMetrics(mPortNameFont); @@ -123,8 +119,8 @@ namespace EMStudio mInfoText.prepare(QTransform(), mSubTitleFont); // input ports - const uint32 numInputs = mInputPorts.GetLength(); - mInputPortText.Resize(numInputs); + const uint32 numInputs = mInputPorts.size(); + mInputPortText.resize(numInputs); for (uint32 i = 0; i < numInputs; ++i) { QStaticText& staticText = mInputPortText[i]; @@ -136,8 +132,8 @@ namespace EMStudio } // output ports - const uint32 numOutputs = mOutputPorts.GetLength(); - mOutputPortText.Resize(numOutputs); + const uint32 numOutputs = mOutputPorts.size(); + mOutputPortText.resize(numOutputs); for (uint32 i = 0; i < numOutputs; ++i) { QStaticText& staticText = mOutputPortText[i]; @@ -241,13 +237,13 @@ namespace EMStudio // remove all node connections void GraphNode::RemoveAllConnections() { - const uint32 numConnections = mConnections.GetLength(); + const uint32 numConnections = mConnections.size(); for (uint32 i = 0; i < numConnections; ++i) { delete mConnections[i]; } - mConnections.Clear(); + mConnections.clear(); } @@ -338,7 +334,7 @@ namespace EMStudio // update the input ports and reset the port highlight flags uint32 i; - const uint32 numInputPorts = mInputPorts.GetLength(); + const uint32 numInputPorts = mInputPorts.size(); for (i = 0; i < numInputPorts; ++i) { mInputPorts[i].SetRect(CalcInputPortRect(i)); @@ -346,7 +342,7 @@ namespace EMStudio } // update the output ports and reset the port highlight flags - const uint32 numOutputPorts = mOutputPorts.GetLength(); + const uint32 numOutputPorts = mOutputPorts.size(); for (i = 0; i < numOutputPorts; ++i) { mOutputPorts[i].SetRect(CalcOutputPortRect(i)); @@ -574,7 +570,7 @@ namespace EMStudio // draw the input ports QColor portBrushColor, portPenColor; - const uint32 numInputs = mInputPorts.GetLength(); + const uint32 numInputs = mInputPorts.size(); for (uint32 i = 0; i < numInputs; ++i) { // get the input port and the corresponding rect @@ -599,7 +595,7 @@ namespace EMStudio if (GetHasVisualOutputPorts()) { // draw the output ports - const uint32 numOutputs = mOutputPorts.GetLength(); + const uint32 numOutputs = mOutputPorts.size(); for (uint32 i = 0; i < numOutputs; ++i) { // get the output port and the corresponding rect @@ -827,7 +823,7 @@ namespace EMStudio const bool alwaysColor = GetAlwaysColor(); // for all connections - const uint32 numConnections = mConnections.GetLength(); + const uint32 numConnections = mConnections.size(); for (uint32 c = 0; c < numConnections; ++c) { NodeConnection* nodeConnection = mConnections[c]; @@ -922,7 +918,7 @@ namespace EMStudio { if (mIsCollapsed == false) { - uint32 numPorts = MCore::Max(mInputPorts.GetLength(), mOutputPorts.GetLength()); + uint32 numPorts = MCore::Max(mInputPorts.size(), mOutputPorts.size()); uint32 result = (numPorts * 15) + 34; return MCore::Math::Align(result, 10); } @@ -939,7 +935,7 @@ namespace EMStudio // calc the maximum input port width uint32 maxInputWidth = 0; uint32 width; - const uint32 numInputPorts = mInputPorts.GetLength(); + const uint32 numInputPorts = mInputPorts.size(); for (uint32 i = 0; i < numInputPorts; ++i) { const NodePort* nodePort = &mInputPorts[i]; @@ -956,7 +952,7 @@ namespace EMStudio // calc the maximum output port width uint32 width; uint32 maxOutputWidth = 0; - const uint32 numOutputPorts = mOutputPorts.GetLength(); + const uint32 numOutputPorts = mOutputPorts.size(); for (uint32 i = 0; i < numOutputPorts; ++i) { width = mPortFontMetrics->horizontalAdvance(mOutputPorts[i].GetName()); @@ -1052,40 +1048,40 @@ namespace EMStudio // remove all input ports void GraphNode::RemoveAllInputPorts() { - mInputPorts.Clear(false); + mInputPorts.clear(); } // remove all output ports void GraphNode::RemoveAllOutputPorts() { - mOutputPorts.Clear(false); + mOutputPorts.clear(); } // add a new input port NodePort* GraphNode::AddInputPort(bool updateTextPixMap) { - mInputPorts.AddEmpty(); - mInputPorts.GetLast().SetNode(this); + mInputPorts.emplace_back(); + mInputPorts.back().SetNode(this); if (updateTextPixMap) { UpdateTextPixmap(); } - return &mInputPorts.GetLast(); + return &mInputPorts.back(); } // add a new output port NodePort* GraphNode::AddOutputPort(bool updateTextPixMap) { - mOutputPorts.AddEmpty(); - mOutputPorts.GetLast().SetNode(this); + mOutputPorts.emplace_back(); + mOutputPorts.back().SetNode(this); if (updateTextPixMap) { UpdateTextPixmap(); } - return &mOutputPorts.GetLast(); + return &mOutputPorts.back(); } /* @@ -1129,7 +1125,7 @@ namespace EMStudio // check the input ports if (includeInputPorts) { - const uint32 numInputPorts = mInputPorts.GetLength(); + const uint32 numInputPorts = mInputPorts.size(); for (i = 0; i < numInputPorts; ++i) { QRect rect = CalcInputPortRect(i); @@ -1143,7 +1139,7 @@ namespace EMStudio } // check the output ports - const uint32 numOutputPorts = mOutputPorts.GetLength(); + const uint32 numOutputPorts = mOutputPorts.size(); for (i = 0; i < numOutputPorts; ++i) { QRect rect = CalcOutputPortRect(i); @@ -1161,7 +1157,7 @@ namespace EMStudio // remove a given connection bool GraphNode::RemoveConnection(const void* connection, bool removeFromMemory) { - const uint32 numConnections = mConnections.GetLength(); + const uint32 numConnections = mConnections.size(); for (uint32 i = 0; i < numConnections; ++i) { // if this is the connection we're searching for @@ -1171,7 +1167,7 @@ namespace EMStudio { delete mConnections[i]; } - mConnections.Remove(i); + mConnections.erase(AZStd::next(begin(mConnections), i)); return true; } } @@ -1182,7 +1178,7 @@ namespace EMStudio // Remove a given connection by model index bool GraphNode::RemoveConnection(const QModelIndex& modelIndex, bool removeFromMemory) { - const uint32 numConnections = mConnections.GetLength(); + const uint32 numConnections = mConnections.size(); for (uint32 i = 0; i < numConnections; ++i) { // if this is the connection we're searching for @@ -1192,7 +1188,7 @@ namespace EMStudio { delete mConnections[i]; } - mConnections.Remove(i); + mConnections.erase(AZStd::next(begin(mConnections), i)); return true; } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GraphNode.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GraphNode.h index 42c5c7e123..ba6be3de28 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GraphNode.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GraphNode.h @@ -9,7 +9,7 @@ #pragma once #include -#include +#include #include #include #include "../StandardPluginsConfig.h" @@ -44,7 +44,6 @@ namespace EMStudio public: NodePort() : mIsHighlighted(false) { mNode = nullptr; mNameID = MCORE_INVALIDINDEX32; mColor.setRgb(50, 150, 250); } - ~NodePort() {} MCORE_INLINE void SetName(const char* name) { mNameID = MCore::GetStringIdPool().GenerateIdForString(name); OnNameChanged(); } MCORE_INLINE const char* GetName() const { return MCore::GetStringIdPool().GetName(mNameID).c_str(); } @@ -85,10 +84,10 @@ namespace EMStudio const QModelIndex& GetModelIndex() const { return m_modelIndex; } MCORE_INLINE void UpdateNameAndPorts() { mNameAndPortsUpdated = false; } - MCORE_INLINE MCore::Array& GetConnections() { return mConnections; } - MCORE_INLINE uint32 GetNumConnections() { return mConnections.GetLength(); } + MCORE_INLINE AZStd::vector& GetConnections() { return mConnections; } + MCORE_INLINE size_t GetNumConnections() { return mConnections.size(); } MCORE_INLINE NodeConnection* GetConnection(uint32 index) { return mConnections[index]; } - MCORE_INLINE NodeConnection* AddConnection(NodeConnection* con) { mConnections.Add(con); return con; } + MCORE_INLINE NodeConnection* AddConnection(NodeConnection* con) { mConnections.emplace_back(con); return con; } MCORE_INLINE void SetParentGraph(NodeGraph* graph) { mParentGraph = graph; } MCORE_INLINE NodeGraph* GetParentGraph() { return mParentGraph; } MCORE_INLINE NodePort* GetInputPort(uint32 index) { return &mInputPorts[index]; } @@ -135,8 +134,8 @@ namespace EMStudio MCORE_INLINE float GetOpacity() const { return mOpacity; } MCORE_INLINE void SetOpacity(float opacity) { mOpacity = opacity; } - uint32 GetNumInputPorts() const { return mInputPorts.GetLength(); } - uint32 GetNumOutputPorts() const { return mOutputPorts.GetLength(); } + size_t GetNumInputPorts() const { return mInputPorts.size(); } + size_t GetNumOutputPorts() const { return mOutputPorts.size(); } NodePort* AddInputPort(bool updateTextPixMap); NodePort* AddOutputPort(bool updateTextPixMap); @@ -227,7 +226,7 @@ namespace EMStudio QColor mBorderColor; QColor mVisualizeColor; QColor mHasChildIndicatorColor; - MCore::Array mConnections; + AZStd::vector mConnections; float mOpacity; bool mIsVisible; static QColor mPortHighlightColor; @@ -251,15 +250,15 @@ namespace EMStudio QStaticText mSubTitleText; QStaticText mInfoText; - MCore::Array mInputPortText; - MCore::Array mOutputPortText; + AZStd::vector mInputPortText; + AZStd::vector mOutputPortText; int32 mRequiredWidth; bool mNameAndPortsUpdated; NodeGraph* mParentGraph; - MCore::Array mInputPorts; - MCore::Array mOutputPorts; + AZStd::vector mInputPorts; + AZStd::vector mOutputPorts; bool mConFromOutputOnly; bool mIsDeletable; bool mIsCollapsed; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGraph.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGraph.cpp index 761baaffcf..39a9a0630d 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGraph.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGraph.cpp @@ -2013,8 +2013,8 @@ namespace EMStudio // So we have to rely on the UI data. for (const GraphNodeByModelIndex::value_type& target : m_graphNodeByModelIndex) { - MCore::Array& connections = target.second->GetConnections(); - const uint32 connectionsCount = connections.GetLength(); + AZStd::vector& connections = target.second->GetConnections(); + const uint32 connectionsCount = connections.size(); for (uint32 i = 0; i < connectionsCount; ++i) { if (connections[i]->GetType() == StateConnection::TYPE_ID) @@ -2023,7 +2023,7 @@ namespace EMStudio if (visualStateConnection->GetModelIndex() == modelIndex) { delete connections[i]; - connections.Remove(i); + connections.erase(AZStd::next(begin(connections), i)); break; } } @@ -2086,8 +2086,8 @@ namespace EMStudio GraphNode* targetGraphNode = FindGraphNode(targetNode); bool foundConnection = false; - MCore::Array& connections = targetGraphNode->GetConnections(); - const uint32 connectionsCount = connections.GetLength(); + AZStd::vector& connections = targetGraphNode->GetConnections(); + const uint32 connectionsCount = connections.size(); for (uint32 i = 0; i < connectionsCount; ++i) { if (connections[i]->GetType() == StateConnection::TYPE_ID) @@ -2110,13 +2110,11 @@ namespace EMStudio { GraphNode* visualNode = indexAndGraphNode.second.get(); - MCore::Array& connections2 = visualNode->GetConnections(); - const uint32 connectionsCount2 = connections2.GetLength(); - for (uint32 i = 0; i < connectionsCount2; ++i) + for (NodeConnection* connection : visualNode->GetConnections()) { - if (connections2[i]->GetType() == StateConnection::TYPE_ID) + if (connection->GetType() == StateConnection::TYPE_ID) { - StateConnection* visualStateConnection = static_cast(connections2[i]); + StateConnection* visualStateConnection = static_cast(connection); if (visualStateConnection->GetModelIndex() == modelIndex) { // Transfer ownership from the previous visual node to where we relinked the transition to. @@ -2176,8 +2174,8 @@ namespace EMStudio // We have to rely on the UI data. for (const GraphNodeByModelIndex::value_type& target : m_graphNodeByModelIndex) { - MCore::Array& connections = target.second->GetConnections(); - const uint32 connectionsCount = connections.GetLength(); + AZStd::vector& connections = target.second->GetConnections(); + const uint32 connectionsCount = connections.size(); for (uint32 i = 0; i < connectionsCount; ++i) { if (connections[i]->GetType() == StateConnection::TYPE_ID) @@ -2205,8 +2203,8 @@ namespace EMStudio GraphNode* target = FindGraphNode(parentModelIndex); if (target) { - MCore::Array& connections = target->GetConnections(); - const uint32 connectionsCount = connections.GetLength(); + AZStd::vector& connections = target->GetConnections(); + const uint32 connectionsCount = connections.size(); for (uint32 i = 0; i < connectionsCount; ++i) { if (connections[i]->GetType() == NodeConnection::TYPE_ID) diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGroupWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGroupWindow.cpp index 8ab7aa8d72..51b170c5aa 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGroupWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGroupWindow.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -160,8 +161,6 @@ namespace EMStudio mTableWidget = nullptr; mAddAction = nullptr; - mWidgetTable.SetMemoryCategory(MEMCATEGORY_STANDARDPLUGINS_ANIMGRAPH); - // create and register the command callbacks mCreateCallback = new CommandAnimGraphAddNodeGroupCallback(false); mRemoveCallback = new CommandAnimGraphRemoveNodeGroupCallback(false); @@ -280,7 +279,7 @@ namespace EMStudio void NodeGroupWindow::Init() { // selected node groups array - MCore::Array selectedNodeGroups; + AZStd::vector selectedNodeGroups; // get the current selection const QList selectedItems = mTableWidget->selectedItems(); @@ -289,19 +288,19 @@ namespace EMStudio const uint32 numSelectedItems = selectedItems.count(); // filter the items - selectedNodeGroups.Reserve(numSelectedItems); + selectedNodeGroups.reserve(numSelectedItems); for (uint32 i = 0; i < numSelectedItems; ++i) { const uint32 rowIndex = selectedItems[i]->row(); const AZStd::string nodeGroupName = FromQtString(mTableWidget->item(rowIndex, 2)->text()); - if (selectedNodeGroups.Find(nodeGroupName) == MCORE_INVALIDINDEX32) + if (AZStd::find(begin(selectedNodeGroups), end(selectedNodeGroups), nodeGroupName) == end(selectedNodeGroups)) { - selectedNodeGroups.Add(nodeGroupName); + selectedNodeGroups.emplace_back(nodeGroupName); } } // clear the lookup array - mWidgetTable.Clear(false); + mWidgetTable.clear(); // get the anim graph EMotionFX::AnimGraph* animGraph = mPlugin->GetActiveAnimGraph(); @@ -331,7 +330,7 @@ namespace EMStudio EMotionFX::AnimGraphNodeGroup* nodeGroup = animGraph->GetNodeGroup(i); // check if the node group is selected - const bool itemSelected = selectedNodeGroups.Find(nodeGroup->GetNameString().c_str()) != MCORE_INVALIDINDEX32; + const bool itemSelected = AZStd::find(begin(selectedNodeGroups), end(selectedNodeGroups), nodeGroup->GetNameString()) != end(selectedNodeGroups); // get the color and convert to Qt color AZ::Color color; @@ -365,7 +364,7 @@ namespace EMStudio colorLayout->addWidget(colorWidget); colorLayoutWidget->setLayout(colorLayout); - mWidgetTable.Add(WidgetLookup(colorWidget, i)); + mWidgetTable.emplace_back(WidgetLookup{colorWidget, i}); connect(colorWidget, &AzQtComponents::ColorLabel::colorChanged, this, &NodeGroupWindow::OnColorChanged); // add the color label in the table @@ -456,7 +455,7 @@ namespace EMStudio uint32 NodeGroupWindow::FindGroupIndexByWidget(QObject* widget) const { // for all table entries - const uint32 numWidgets = mWidgetTable.GetLength(); + const uint32 numWidgets = mWidgetTable.size(); for (uint32 i = 0; i < numWidgets; ++i) { if (mWidgetTable[i].mWidget == widget) // this is button we search for @@ -582,23 +581,23 @@ namespace EMStudio } // filter the items - MCore::Array rowIndices; - rowIndices.Reserve(numSelectedItems); + AZStd::vector rowIndices; + rowIndices.reserve(numSelectedItems); for (uint32 i = 0; i < numSelectedItems; ++i) { const uint32 rowIndex = selectedItems[i]->row(); - if (rowIndices.Find(rowIndex) == MCORE_INVALIDINDEX32) + if (AZStd::find(begin(rowIndices), end(rowIndices), rowIndex) == end(rowIndices)) { - rowIndices.Add(rowIndex); + rowIndices.emplace_back(rowIndex); } } // sort the rows // it's used to select the next row - rowIndices.Sort(); + AZStd::sort(begin(rowIndices), end(rowIndices)); // get the number of selected rows - const uint32 numRowIndices = rowIndices.GetLength(); + const uint32 numRowIndices = rowIndices.size(); // set the command group name AZStd::string commandGroupName; @@ -731,14 +730,14 @@ namespace EMStudio } // filter the items - MCore::Array rowIndices; - rowIndices.Reserve(numSelectedItems); + AZStd::vector rowIndices; + rowIndices.reserve(numSelectedItems); for (uint32 i = 0; i < numSelectedItems; ++i) { const uint32 rowIndex = selectedItems[i]->row(); - if (rowIndices.Find(rowIndex) == MCORE_INVALIDINDEX32) + if (AZStd::find(begin(rowIndices), end(rowIndices), rowIndex) == end(rowIndices)) { - rowIndices.Add(rowIndex); + rowIndices.emplace_back(rowIndex); } } @@ -746,14 +745,14 @@ namespace EMStudio QMenu menu(this); // add rename if only one selected - if (rowIndices.GetLength() == 1) + if (rowIndices.size() == 1) { QAction* renameAction = menu.addAction("Rename Selected Node Group"); connect(renameAction, &QAction::triggered, this, &NodeGroupWindow::OnRenameSelectedNodeGroup); } // at least one selected, remove action is possible - if (rowIndices.GetLength() > 0) + if (rowIndices.size() > 0) { menu.addSeparator(); QAction* removeAction = menu.addAction("Remove Selected Node Groups"); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGroupWindow.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGroupWindow.h index 4dd55a733f..5f0354b223 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGroupWindow.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGroupWindow.h @@ -10,7 +10,7 @@ #if !defined(Q_MOC_RUN) #include -#include +#include #include @@ -104,15 +104,8 @@ namespace EMStudio struct WidgetLookup { - MCORE_MEMORYOBJECTCATEGORY(NodeGroupWindow::WidgetLookup, EMFX_DEFAULT_ALIGNMENT, MEMCATEGORY_STANDARDPLUGINS_ANIMGRAPH); QObject* mWidget; uint32 mGroupIndex; - - WidgetLookup(QObject* widget, uint32 index) - { - mWidget = widget; - mGroupIndex = index; - } }; AnimGraphPlugin* mPlugin; @@ -121,6 +114,6 @@ namespace EMStudio QAction* mAddAction; AzQtComponents::FilteredSearchWidget* m_searchWidget; AZStd::string m_searchWidgetText; - MCore::Array mWidgetTable; + AZStd::vector mWidgetTable; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ParameterSelectionWindow.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ParameterSelectionWindow.h index 6e0bad9d10..25e717f473 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ParameterSelectionWindow.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ParameterSelectionWindow.h @@ -28,7 +28,7 @@ namespace EMStudio * Example: * connect( mParameterSelectionWindow, SIGNAL(rejected()), this, SLOT(UserWantsToCancel_1()) ); * connect( mParameterSelectionWindow->GetNodeHierarchyWidget()->GetTreeWidget(), SIGNAL(itemSelectionChanged()), this, SLOT(SelectionChanged_2()) ); - * connect( mParameterSelectionWindow->GetNodeHierarchyWidget(), SIGNAL(OnSelectionDone(MCore::Array)), this, SLOT(FinishedSelectionAndPressedOK_3(MCore::Array)) ); + * connect( mParameterSelectionWindow->GetNodeHierarchyWidget(), SIGNAL(OnSelectionDone(AZStd::vector)), this, SLOT(FinishedSelectionAndPressedOK_3(AZStd::vector)) ); */ class ParameterSelectionWindow : public QDialog diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/StateGraphNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/StateGraphNode.cpp index 2cb9b8334d..0c4f8b8138 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/StateGraphNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/StateGraphNode.cpp @@ -649,8 +649,8 @@ namespace EMStudio // mTextOptions.setAlignment( Qt::AlignCenter ); - mInputPorts.Resize(1); - mOutputPorts.Resize(4); + mInputPorts.resize(1); + mOutputPorts.resize(4); } StateGraphNode::~StateGraphNode() @@ -856,7 +856,6 @@ namespace EMStudio MCORE_ASSERT(false); return QRect(); } - ; //MCore::LOG("CalcOutputPortRect: (%i, %i, %i, %i)", rect.top(), rect.left(), rect.bottom(), rect.right()); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentNodesWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentNodesWindow.cpp index 2cf03ca998..3b24552035 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentNodesWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentNodesWindow.cpp @@ -110,8 +110,8 @@ namespace EMStudio connect(mAddNodesButton, &QToolButton::clicked, this, &AttachmentNodesWindow::SelectNodesButtonPressed); connect(mRemoveNodesButton, &QToolButton::clicked, this, &AttachmentNodesWindow::RemoveNodesButtonPressed); connect(mNodeTable, &QTableWidget::itemSelectionChanged, this, &AttachmentNodesWindow::OnItemSelectionChanged); - connect(mNodeSelectionWindow->GetNodeHierarchyWidget(), static_cast)>(&NodeHierarchyWidget::OnSelectionDone), this, &AttachmentNodesWindow::NodeSelectionFinished); - connect(mNodeSelectionWindow->GetNodeHierarchyWidget(), static_cast)>(&NodeHierarchyWidget::OnDoubleClicked), this, &AttachmentNodesWindow::NodeSelectionFinished); + connect(mNodeSelectionWindow->GetNodeHierarchyWidget(), &NodeHierarchyWidget::OnSelectionDone, this, &AttachmentNodesWindow::NodeSelectionFinished); + connect(mNodeSelectionWindow->GetNodeHierarchyWidget(), &NodeHierarchyWidget::OnDoubleClicked, this, &AttachmentNodesWindow::NodeSelectionFinished); } @@ -322,10 +322,10 @@ namespace EMStudio // add / select nodes - void AttachmentNodesWindow::NodeSelectionFinished(MCore::Array selectionList) + void AttachmentNodesWindow::NodeSelectionFinished(AZStd::vector selectionList) { // return if no nodes are selected - if (selectionList.GetLength() == 0) + if (selectionList.size() == 0) { return; } @@ -333,7 +333,7 @@ namespace EMStudio // generate node list string AZStd::string nodeList; nodeList.reserve(16384); - const uint32 numSelectedNodes = selectionList.GetLength(); + const uint32 numSelectedNodes = selectionList.size(); for (uint32 i = 0; i < numSelectedNodes; ++i) { nodeList += AZStd::string::format("%s;", selectionList[i].GetNodeName()); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentNodesWindow.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentNodesWindow.h index 89bc06be7f..3a3c3f096e 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentNodesWindow.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentNodesWindow.h @@ -57,7 +57,7 @@ namespace EMStudio // the slots void SelectNodesButtonPressed(); void RemoveNodesButtonPressed(); - void NodeSelectionFinished(MCore::Array selectionList); + void NodeSelectionFinished(AZStd::vector selectionList); void OnItemSelectionChanged(); private: diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentsWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentsWindow.cpp index 2498ec1b0e..c78d37dd7b 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentsWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentsWindow.cpp @@ -204,7 +204,7 @@ namespace EMStudio connect(mOpenDeformableAttachmentButton, &QToolButton::clicked, this, &AttachmentsWindow::OnOpenDeformableAttachmentButtonClicked); connect(mRemoveButton, &QToolButton::clicked, this, &AttachmentsWindow::OnRemoveButtonClicked); connect(mClearButton, &QToolButton::clicked, this, &AttachmentsWindow::OnClearButtonClicked); - connect(mNodeSelectionWindow->GetNodeHierarchyWidget(), static_cast)>(&NodeHierarchyWidget::OnSelectionDone), this, &AttachmentsWindow::OnAttachmentNodesSelected); + connect(mNodeSelectionWindow->GetNodeHierarchyWidget(), &NodeHierarchyWidget::OnSelectionDone, this, &AttachmentsWindow::OnAttachmentNodesSelected); connect(mNodeSelectionWindow, &NodeSelectionWindow::rejected, this, &AttachmentsWindow::OnCancelAttachmentNodeSelection); connect(mNodeSelectionWindow->GetNodeHierarchyWidget()->GetTreeWidget(), &QTreeWidget::itemSelectionChanged, this, &AttachmentsWindow::OnNodeChanged); connect(mEscapeShortcut, &QShortcut::activated, this, &AttachmentsWindow::OnEscapeButtonPressed); @@ -766,10 +766,10 @@ namespace EMStudio // called when the node selection is done - void AttachmentsWindow::OnAttachmentNodesSelected(MCore::Array selection) + void AttachmentsWindow::OnAttachmentNodesSelected(AZStd::vector selection) { // check if selection is valid - if (selection.GetLength() != 1) + if (selection.size() != 1) { MCore::LogDebug("No valid attachment selected."); return; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentsWindow.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentsWindow.h index dd00ae6cb0..b3bd45fb22 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentsWindow.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentsWindow.h @@ -78,7 +78,7 @@ namespace EMStudio void OnDroppedAttachmentsActors(); void OnDroppedDeformableActors(); void OnVisibilityChanged(int visibility); - void OnAttachmentNodesSelected(MCore::Array selection); + void OnAttachmentNodesSelected(AZStd::vector selection); void OnCancelAttachmentNodeSelection(); void OnEscapeButtonPressed(); void OnUpdateButtonsEnabled(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/LogWindow/LogWindowCallback.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/LogWindow/LogWindowCallback.cpp index b4bef2faea..51c7e1d8de 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/LogWindow/LogWindowCallback.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/LogWindow/LogWindowCallback.cpp @@ -6,6 +6,7 @@ * */ +#include #include "LogWindowCallback.h" #include #include @@ -289,22 +290,22 @@ namespace EMStudio } // filter the items - MCore::Array rowIndices; - rowIndices.Reserve(numSelectedItems); + AZStd::vector rowIndices; + rowIndices.reserve(numSelectedItems); for (uint32 i = 0; i < numSelectedItems; ++i) { const uint32 rowIndex = items[i]->row(); - if (rowIndices.Find(rowIndex) == MCORE_INVALIDINDEX32) + if (AZStd::find(begin(rowIndices), end(rowIndices), rowIndex) == end(rowIndices)) { - rowIndices.Add(rowIndex); + rowIndices.emplace_back(rowIndex); } } // sort the array to copy the item in order - rowIndices.Sort(); + AZStd::sort(begin(rowIndices), end(rowIndices)); // get the number of selected rows - const uint32 numSelectedRows = rowIndices.GetLength(); + const uint32 numSelectedRows = rowIndices.size(); // genereate the clipboard text QString clipboardText; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetManagementWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetManagementWindow.cpp index 53b60c715f..441c9555a7 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetManagementWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetManagementWindow.cpp @@ -33,7 +33,7 @@ namespace EMStudio { - MotionSetManagementRemoveMotionsFailedWindow::MotionSetManagementRemoveMotionsFailedWindow(QWidget* parent, const MCore::Array& motions) + MotionSetManagementRemoveMotionsFailedWindow::MotionSetManagementRemoveMotionsFailedWindow(QWidget* parent, const AZStd::vector& motions) : QDialog(parent) { // set the window title @@ -70,7 +70,7 @@ namespace EMStudio tableWidget->verticalHeader()->setVisible(false); // set the number of rows - const uint32 numMotions = motions.GetLength(); + const uint32 numMotions = motions.size(); tableWidget->setRowCount(numMotions); // add each motion in the table diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetManagementWindow.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetManagementWindow.h index f5b354c5a4..368f5bd9c7 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetManagementWindow.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetManagementWindow.h @@ -43,7 +43,7 @@ namespace EMStudio MCORE_MEMORYOBJECTCATEGORY(MotionSetManagementRemoveMotionsFailedWindow, MCore::MCORE_DEFAULT_ALIGNMENT, MEMCATEGORY_STANDARDPLUGINS); public: - MotionSetManagementRemoveMotionsFailedWindow(QWidget* parent, const MCore::Array& motions); + MotionSetManagementRemoveMotionsFailedWindow(QWidget* parent, const AZStd::vector& motions); }; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionWindow/MotionExtractionWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionWindow/MotionExtractionWindow.cpp index 9910384133..ac284a5777 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionWindow/MotionExtractionWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionWindow/MotionExtractionWindow.cpp @@ -130,7 +130,7 @@ namespace EMStudio // create the node selection windows mMotionExtractionNodeSelectionWindow = new NodeSelectionWindow(this, true); - connect(mMotionExtractionNodeSelectionWindow->GetNodeHierarchyWidget(), static_cast)>(&NodeHierarchyWidget::OnSelectionDone), this, &MotionExtractionWindow::OnMotionExtractionNodeSelected); + connect(mMotionExtractionNodeSelectionWindow->GetNodeHierarchyWidget(), &NodeHierarchyWidget::OnSelectionDone, this, &MotionExtractionWindow::OnMotionExtractionNodeSelected); // set some layout for our window mMainVerticalLayout = new QVBoxLayout(); @@ -393,7 +393,7 @@ namespace EMStudio } - void MotionExtractionWindow::OnMotionExtractionNodeSelected(MCore::Array selection) + void MotionExtractionWindow::OnMotionExtractionNodeSelected(AZStd::vector selection) { // get the selected node name uint32 actorID; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionWindow/MotionExtractionWindow.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionWindow/MotionExtractionWindow.h index efe89c49dc..cb7371a74d 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionWindow/MotionExtractionWindow.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionWindow/MotionExtractionWindow.h @@ -53,7 +53,7 @@ namespace EMStudio void OnMotionExtractionFlagsUpdated(); void OnSelectMotionExtractionNode(); - void OnMotionExtractionNodeSelected(MCore::Array selection); + void OnMotionExtractionNodeSelected(AZStd::vector selection); private: // callbacks diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeGroups/NodeGroupWidget.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeGroups/NodeGroupWidget.cpp index 39ee1c4f5b..481718ab66 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeGroups/NodeGroupWidget.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeGroups/NodeGroupWidget.cpp @@ -9,6 +9,7 @@ // inlude required headers #include "NodeGroupWidget.h" #include "../../../../EMStudioSDK/Source/EMStudioManager.h" +#include "AzCore/std/iterator.h" #include #include @@ -127,11 +128,8 @@ namespace EMStudio connect(mAddNodesButton, &QPushButton::clicked, this, &NodeGroupWidget::SelectNodesButtonPressed); connect(mRemoveNodesButton, &QPushButton::clicked, this, &NodeGroupWidget::RemoveNodesButtonPressed); connect(mNodeTable, &QTableWidget::itemSelectionChanged, this, &NodeGroupWidget::OnItemSelectionChanged); - //connect( mEnabledOnDefaultCheckbox, SIGNAL(clicked()), this, SLOT(EnabledOnDefaultChanged()) ); - //connect( mNodeGroupNameEdit, SIGNAL(editingFinished()), this, SLOT(NodeGroupNameEditingFinished()) ); - //connect( mNodeGroupNameEdit, SIGNAL(textChanged(QString)), this, SLOT(NodeGroupNameEditChanged(QString)) ); - connect(mNodeSelectionWindow->GetNodeHierarchyWidget(), static_cast)>(&NodeHierarchyWidget::OnSelectionDone), this, &NodeGroupWidget::NodeSelectionFinished); - connect(mNodeSelectionWindow->GetNodeHierarchyWidget(), static_cast)>(&NodeHierarchyWidget::OnDoubleClicked), this, &NodeGroupWidget::NodeSelectionFinished); + connect(mNodeSelectionWindow->GetNodeHierarchyWidget(), &NodeHierarchyWidget::OnSelectionDone, this, &NodeGroupWidget::NodeSelectionFinished); + connect(mNodeSelectionWindow->GetNodeHierarchyWidget(), &NodeHierarchyWidget::OnDoubleClicked, this, &NodeGroupWidget::NodeSelectionFinished); } @@ -334,21 +332,21 @@ namespace EMStudio // add / select nodes - void NodeGroupWidget::NodeSelectionFinished(MCore::Array selectionList) + void NodeGroupWidget::NodeSelectionFinished(AZStd::vector selectionList) { // return if no nodes are selected - if (selectionList.GetLength() == 0) + if (selectionList.size() == 0) { return; } // generate node list string AZStd::vector nodeList; - const uint32 selectionListSize = selectionList.GetLength(); - for (uint32 i = 0; i < selectionListSize; ++i) + nodeList.reserve(selectionList.size()); + AZStd::transform(begin(selectionList), end(selectionList), AZStd::back_inserter(nodeList), [](const auto& item) { - nodeList.emplace_back(selectionList[i].GetNodeName()); - } + return item.GetNodeName(); + }); AZStd::string outResult; auto* command = aznew CommandSystem::CommandAdjustNodeGroup( diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeGroups/NodeGroupWidget.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeGroups/NodeGroupWidget.h index 2b4cad06de..f128fd8082 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeGroups/NodeGroupWidget.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeGroups/NodeGroupWidget.h @@ -45,7 +45,7 @@ namespace EMStudio public slots: void SelectNodesButtonPressed(); void RemoveNodesButtonPressed(); - void NodeSelectionFinished(MCore::Array selectionList); + void NodeSelectionFinished(AZStd::vector selectionList); void OnItemSelectionChanged(); private: diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/NodeWindowPlugin.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/NodeWindowPlugin.cpp index 0c1778aa23..3d7e44dac3 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/NodeWindowPlugin.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/NodeWindowPlugin.cpp @@ -292,7 +292,7 @@ namespace EMStudio m_visibleNodeIndices.reserve(numNodes); // extract the bones from the actor - MCore::Array boneList; + AZStd::vector boneList; actor->ExtractBoneList(actorInstance->GetLODLevel(), &boneList); // iterate through all nodes and check if the node is visible @@ -308,7 +308,7 @@ namespace EMStudio const uint32 nodeIndex = node->GetNodeIndex(); EMotionFX::Mesh* mesh = actor->GetMesh(actorInstance->GetLODLevel(), nodeIndex); const bool isMeshNode = (mesh); - const bool isBone = (boneList.Find(nodeIndex) != MCORE_INVALIDINDEX32); + const bool isBone = (AZStd::find(begin(boneList), end(boneList), nodeIndex) != end(boneList)); const bool isNode = (isMeshNode == false && isBone == false); if (((showMeshes && isMeshNode) || diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/ActorPropertiesWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/ActorPropertiesWindow.cpp index 04fbc9e412..cc5811b1f7 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/ActorPropertiesWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/ActorPropertiesWindow.cpp @@ -215,30 +215,6 @@ namespace EMStudio mNameEdit->setText(mActor->GetName()); } - void ActorPropertiesWindow::GetNodeName(const MCore::Array& selection, AZStd::string* outNodeName, uint32* outActorID) - { - outNodeName->clear(); - *outActorID = MCORE_INVALIDINDEX32; - - if (selection.GetLength() != 1 || selection[0].GetNodeNameString().empty()) - { - AZ_Warning("EMotionFX", false, "Cannot adjust motion extraction node. No valid node selected."); - return; - } - - const uint32 actorInstanceID = selection[0].mActorInstanceID; - const char* nodeName = selection[0].GetNodeName(); - EMotionFX::ActorInstance* actorInstance = EMotionFX::GetActorManager().FindActorInstanceByID(actorInstanceID); - if (actorInstance == nullptr) - { - return; - } - - EMotionFX::Actor* actor = actorInstance->GetActor(); - *outActorID = actor->GetID(); - *outNodeName = nodeName; - } - void ActorPropertiesWindow::GetNodeName(const AZStd::vector& joints, AZStd::string* outNodeName, uint32* outActorID) { outNodeName->clear(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/ActorPropertiesWindow.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/ActorPropertiesWindow.h index d969a12148..67568d80b0 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/ActorPropertiesWindow.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/ActorPropertiesWindow.h @@ -45,7 +45,6 @@ namespace EMStudio void Init(); // helper functions - static void GetNodeName(const MCore::Array& selection, AZStd::string* outNodeName, uint32* outActorID); static void GetNodeName(const AZStd::vector& joints, AZStd::string* outNodeName, uint32* outActorID); public slots: diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/MirrorSetupWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/MirrorSetupWindow.cpp index 6260e68284..271f277ed1 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/MirrorSetupWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/MirrorSetupWindow.cpp @@ -525,7 +525,7 @@ namespace EMStudio typeItem->setIcon(*mMeshIcon); } else - if (mCurrentBoneList.Contains(node->GetNodeIndex())) + if (AZStd::find(begin(mCurrentBoneList), end(mCurrentBoneList), node->GetNodeIndex()) != end(mCurrentBoneList)) { typeItem->setIcon(*mBoneIcon); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/MirrorSetupWindow.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/MirrorSetupWindow.h index 47c321a1e7..13bb98334c 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/MirrorSetupWindow.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/MirrorSetupWindow.h @@ -12,7 +12,7 @@ #if !defined(Q_MOC_RUN) #include "../StandardPluginsConfig.h" #include -#include +#include #include #include #include @@ -79,7 +79,7 @@ namespace EMStudio QIcon* mNodeIcon; QIcon* mMeshIcon; QIcon* mMappedIcon; - MCore::Array mCurrentBoneList; + AZStd::vector mCurrentBoneList; AZStd::vector mSourceBoneList; AZStd::vector mMap; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeViewPlugin.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeViewPlugin.cpp index 04628a6343..e909e9ead3 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeViewPlugin.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeViewPlugin.cpp @@ -107,7 +107,7 @@ namespace EMStudio delete mZoomOutCursor; // get rid of the motion infos - const uint32 numMotionInfos = mMotionInfos.GetLength(); + const uint32 numMotionInfos = mMotionInfos.size(); for (uint32 i = 0; i < numMotionInfos; ++i) { delete mMotionInfos[i]; @@ -285,7 +285,7 @@ namespace EMStudio // add a new track void TimeViewPlugin::AddTrack(TimeTrack* track) { - mTracks.Add(track); + mTracks.emplace_back(track); SetRedrawFlag(); } @@ -294,20 +294,20 @@ namespace EMStudio void TimeViewPlugin::RemoveAllTracks() { // get the number of time tracks and iterate through them - const uint32 numTracks = mTracks.GetLength(); + const uint32 numTracks = mTracks.size(); for (uint32 i = 0; i < numTracks; ++i) { delete mTracks[i]; } - mTracks.Clear(); + mTracks.clear(); SetRedrawFlag(); } TimeTrack* TimeViewPlugin::FindTrackByElement(TimeTrackElement* element) const { // get the number of time tracks and iterate through them - const uint32 numTracks = mTracks.GetLength(); + const uint32 numTracks = mTracks.size(); for (uint32 i = 0; i < numTracks; ++i) { TimeTrack* timeTrack = mTracks[i]; @@ -328,7 +328,7 @@ namespace EMStudio AZ::Outcome TimeViewPlugin::FindTrackIndex(const TimeTrack* track) const { - const AZ::u32 numTracks = mTracks.GetLength(); + const AZ::u32 numTracks = mTracks.size(); for (AZ::u32 i = 0; i < numTracks; ++i) { if (mTracks[i] == track) @@ -472,7 +472,7 @@ namespace EMStudio TimeTrackElement* TimeViewPlugin::GetElementAt(int32 x, int32 y) { // for all tracks - const uint32 numTracks = mTracks.GetLength(); + const uint32 numTracks = mTracks.size(); for (uint32 i = 0; i < numTracks; ++i) { // check if the absolute pixel is inside @@ -491,7 +491,7 @@ namespace EMStudio TimeTrack* TimeViewPlugin::GetTrackAt(int32 y) { // for all tracks - const uint32 numTracks = mTracks.GetLength(); + const uint32 numTracks = mTracks.size(); for (uint32 i = 0; i < numTracks; ++i) { // check if the absolute pixel is inside @@ -509,7 +509,7 @@ namespace EMStudio void TimeViewPlugin::UnselectAllElements() { // for all tracks - const uint32 numTracks = mTracks.GetLength(); + const uint32 numTracks = mTracks.size(); for (uint32 t = 0; t < numTracks; ++t) { TimeTrack* track = mTracks[t]; @@ -603,7 +603,7 @@ namespace EMStudio } // for all tracks - const uint32 numTracks = mTracks.GetLength(); + const uint32 numTracks = mTracks.size(); for (uint32 t = 0; t < numTracks; ++t) { TimeTrack* track = mTracks[t]; @@ -646,7 +646,7 @@ namespace EMStudio void TimeViewPlugin::RenderElementTimeHandles(QPainter& painter, uint32 dataWindowHeight, const QPen& pen) { // for all tracks - const uint32 numTracks = mTracks.GetLength(); + const uint32 numTracks = mTracks.size(); for (uint32 t = 0; t < numTracks; ++t) { TimeTrack* track = mTracks[t]; @@ -682,7 +682,7 @@ namespace EMStudio void TimeViewPlugin::DisableAllToolTips() { // for all tracks - const uint32 numTracks = mTracks.GetLength(); + const uint32 numTracks = mTracks.size(); for (uint32 t = 0; t < numTracks; ++t) { TimeTrack* track = mTracks[t]; @@ -703,7 +703,7 @@ namespace EMStudio bool TimeViewPlugin::FindResizePoint(int32 x, int32 y, TimeTrackElement** outElement, uint32* outID) { // for all tracks - const uint32 numTracks = mTracks.GetLength(); + const uint32 numTracks = mTracks.size(); for (uint32 t = 0; t < numTracks; ++t) { TimeTrack* track = mTracks[t]; @@ -1179,7 +1179,7 @@ namespace EMStudio void TimeViewPlugin::UpdateSelection() { - mSelectedEvents.Clear(false); + mSelectedEvents.clear(); if (!mMotion) { return; @@ -1221,7 +1221,7 @@ namespace EMStudio selectionItem.mMotion = mMotion; selectionItem.mTrackNr = trackNr.GetValue(); selectionItem.mEventNr = element->GetElementNumber(); - mSelectedEvents.Add(selectionItem); + mSelectedEvents.emplace_back(selectionItem); } } } @@ -1298,7 +1298,7 @@ namespace EMStudio } // Select the element if in mSelectedEvents. - const AZ::u32 numSelectedEvents = mSelectedEvents.GetLength(); + const AZ::u32 numSelectedEvents = mSelectedEvents.size(); for (AZ::u32 selectedEventIndex = 0; selectedEventIndex < numSelectedEvents; ++selectedEventIndex) { const EventSelectionItem& selectionItem = mSelectedEvents[selectedEventIndex]; @@ -1447,7 +1447,7 @@ namespace EMStudio // find the motion info for the given motion id TimeViewPlugin::MotionInfo* TimeViewPlugin::FindMotionInfo(uint32 motionID) { - const uint32 numMotionInfos = mMotionInfos.GetLength(); + const uint32 numMotionInfos = mMotionInfos.size(); for (uint32 i = 0; i < numMotionInfos; ++i) { MotionInfo* motionInfo = mMotionInfos[i]; @@ -1462,12 +1462,12 @@ namespace EMStudio MotionInfo* motionInfo = new MotionInfo(); motionInfo->mMotionID = motionID; motionInfo->mInitialized = false; - mMotionInfos.Add(motionInfo); + mMotionInfos.emplace_back(motionInfo); return motionInfo; } - void TimeViewPlugin::Select(const MCore::Array& selection) + void TimeViewPlugin::Select(const AZStd::vector& selection) { uint32 i; @@ -1488,7 +1488,7 @@ namespace EMStudio } } - const uint32 numSelectedEvents = selection.GetLength(); + const uint32 numSelectedEvents = selection.size(); for (i = 0; i < numSelectedEvents; ++i) { const EventSelectionItem* selectionItem = &selection[i]; @@ -1643,7 +1643,7 @@ namespace EMStudio // get the motion event table // MotionEventTable& eventTable = mMotion->GetEventTable(); - MCore::Array eventNumbers; + AZStd::vector eventNumbers; // get the number of tracks in the time view and iterate through them const uint32 numTracks = GetNumTracks(); @@ -1656,7 +1656,7 @@ namespace EMStudio continue; } - eventNumbers.Clear(false); + eventNumbers.clear(); // get the number of elements in the track and iterate through them const uint32 numTrackElements = track->GetNumElements(); @@ -1666,7 +1666,7 @@ namespace EMStudio if (element->GetIsSelected() && element->GetIsVisible()) { - eventNumbers.Add(j); + eventNumbers.emplace_back(j); } } @@ -1702,7 +1702,7 @@ namespace EMStudio // get the motion event table // MotionEventTable& eventTable = mMotion->GetEventTable(); - MCore::Array eventNumbers; + AZStd::vector eventNumbers; // get the number of tracks in the time view and iterate through them const uint32 numTracks = GetNumTracks(); @@ -1715,7 +1715,7 @@ namespace EMStudio continue; } - eventNumbers.Clear(false); + eventNumbers.clear(); // get the number of elements in the track and iterate through them const uint32 numTrackElements = track->GetNumElements(); @@ -1724,7 +1724,7 @@ namespace EMStudio TimeTrackElement* element = track->GetElement(j); if (element->GetIsVisible()) { - eventNumbers.Add(j); + eventNumbers.emplace_back(j); } } @@ -1928,7 +1928,7 @@ namespace EMStudio { if (mMotion) { - const uint32 numTracks = mTracks.GetLength(); + const uint32 numTracks = mTracks.size(); for (uint32 i = 0; i < numTracks; ++i) { TimeTrack* track = mTracks[i]; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeViewPlugin.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeViewPlugin.h index db3a7dec8a..386117d3a3 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeViewPlugin.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeViewPlugin.h @@ -36,8 +36,6 @@ namespace EMStudio struct EventSelectionItem { - MCORE_MEMORYOBJECTCATEGORY(EventSelectionItem, MCore::MCORE_DEFAULT_ALIGNMENT, MEMCATEGORY_STANDARDPLUGINS); - EMotionFX::MotionEvent* GetMotionEvent(); EMotionFX::MotionEventTrack* GetEventTrack(); @@ -118,7 +116,7 @@ namespace EMStudio void AddTrack(TimeTrack* track); void RemoveAllTracks(); TimeTrack* GetTrack(uint32 index) { return mTracks[index]; } - uint32 GetNumTracks() const { return mTracks.GetLength(); } + size_t GetNumTracks() const { return mTracks.size(); } AZ::Outcome FindTrackIndex(const TimeTrack* track) const; TimeTrack* FindTrackByElement(TimeTrackElement* element) const; @@ -153,10 +151,10 @@ namespace EMStudio void ZoomRect(const QRect& rect); - uint32 GetNumSelectedEvents() { return mSelectedEvents.GetLength(); } + size_t GetNumSelectedEvents() { return mSelectedEvents.size(); } EventSelectionItem GetSelectedEvent(uint32 index) const { return mSelectedEvents[index]; } - void Select(const MCore::Array& selection); + void Select(const AZStd::vector& selection); MCORE_INLINE EMotionFX::Motion* GetMotion() const { return mMotion; } void SetRedrawFlag(); @@ -220,7 +218,7 @@ namespace EMStudio MotionEventsPlugin* mMotionEventsPlugin; MotionListWindow* mMotionListWindow; MotionSetsWindowPlugin* m_motionSetPlugin; - MCore::Array mSelectedEvents; + AZStd::vector mSelectedEvents; EMotionFX::Recorder::ActorInstanceData* mActorInstanceData; EMotionFX::Recorder::NodeHistoryItem* mNodeHistoryItem; @@ -238,8 +236,8 @@ namespace EMStudio MotionInfo* FindMotionInfo(uint32 motionID); void UpdateCurrentMotionInfo(); - MCore::Array mMotionInfos; - MCore::Array mTracks; + AZStd::vector mMotionInfos; + AZStd::vector mTracks; double mPixelsPerSecond; // pixels per second double mScrollX; // horizontal scroll offset diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackDataHeaderWidget.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackDataHeaderWidget.h index 6b932dca57..30fa3a741e 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackDataHeaderWidget.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackDataHeaderWidget.h @@ -10,7 +10,7 @@ #if !defined(Q_MOC_RUN) #include -#include +#include #include "../StandardPluginsConfig.h" #include #include diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackDataWidget.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackDataWidget.cpp index b1bad30b28..fc60867864 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackDataWidget.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackDataWidget.cpp @@ -341,7 +341,7 @@ namespace EMStudio painter.setRenderHint(QPainter::Antialiasing, true); // get the history items shortcut - const MCore::Array& historyItems = actorInstanceData->mNodeHistoryItems; + const AZStd::vector& historyItems = actorInstanceData->mNodeHistoryItems; int32 windowWidth = geometry().width(); RecorderGroup* recorderGroup = mPlugin->GetTimeViewToolBar()->GetRecorderGroup(); @@ -369,7 +369,7 @@ namespace EMStudio const uint32 graphContentsCode = mPlugin->mTrackHeaderWidget->mGraphContentsComboBox->currentIndex(); - const uint32 numItems = historyItems.GetLength(); + const uint32 numItems = historyItems.size(); for (uint32 i = 0; i < numItems; ++i) { EMotionFX::Recorder::NodeHistoryItem* curItem = historyItems[i]; @@ -456,7 +456,7 @@ namespace EMStudio // display the values and names uint32 offset = 0; - const uint32 numActiveItems = mActiveItems.GetLength(); + const uint32 numActiveItems = mActiveItems.size(); for (uint32 i = 0; i < numActiveItems; ++i) { EMotionFX::Recorder::NodeHistoryItem* curItem = mActiveItems[i].mNodeHistoryItem; @@ -516,7 +516,7 @@ namespace EMStudio } // get the history items shortcut - const MCore::Array& historyItems = actorInstanceData->mEventHistoryItems; + const AZStd::vector& historyItems = actorInstanceData->mEventHistoryItems; QRect clipRect = rect; clipRect.setRight(aznumeric_cast(mPlugin->TimeToPixel(animationLength))); @@ -528,7 +528,7 @@ namespace EMStudio const float tickHeight = 16; QPointF tickPoints[6]; - const uint32 numItems = historyItems.GetLength(); + const uint32 numItems = historyItems.size(); for (uint32 i = 0; i < numItems; ++i) { EMotionFX::Recorder::EventHistoryItem* curItem = historyItems[i]; @@ -620,7 +620,7 @@ namespace EMStudio } // get the history items shortcut - const MCore::Array& historyItems = actorInstanceData->mNodeHistoryItems; + const AZStd::vector& historyItems = actorInstanceData->mNodeHistoryItems; int32 windowWidth = geometry().width(); // calculate the remapped track list, based on sorted global weight, with the most influencing track on top @@ -639,7 +639,7 @@ namespace EMStudio // for all history items QRectF itemRect; - const uint32 numItems = historyItems.GetLength(); + const uint32 numItems = historyItems.size(); for (uint32 i = 0; i < numItems; ++i) { EMotionFX::Recorder::NodeHistoryItem* curItem = historyItems[i]; @@ -923,7 +923,7 @@ namespace EMStudio visibleEndTime = mPlugin->PixelToTime(width); //mPlugin->CalcTime( width, &visibleEndTime, nullptr, nullptr, nullptr, nullptr ); // for all tracks - const uint32 numTracks = mPlugin->mTracks.GetLength(); + const uint32 numTracks = mPlugin->mTracks.size(); for (uint32 i = 0; i < numTracks; ++i) { TimeTrack* track = mPlugin->mTracks[i]; @@ -1916,7 +1916,7 @@ namespace EMStudio return; } - MCore::Array eventNumbers; + AZStd::vector eventNumbers; // calculate the number of selected events const uint32 numEvents = timeTrack->GetNumElements(); @@ -1927,7 +1927,7 @@ namespace EMStudio // increase the counter in case the element is selected if (element->GetIsSelected()) { - eventNumbers.Add(i); + eventNumbers.emplace_back(i); } } @@ -1950,13 +1950,13 @@ namespace EMStudio return; } - MCore::Array eventNumbers; + AZStd::vector eventNumbers; // construct an array with the event numbers const uint32 numEvents = timeTrack->GetNumElements(); for (uint32 i = 0; i < numEvents; ++i) { - eventNumbers.Add(i); + eventNumbers.emplace_back(i); } // remove the motion events @@ -2315,7 +2315,7 @@ namespace EMStudio // if we recorded node history mNodeHistoryRect = QRect(); - if (actorInstanceData && actorInstanceData->mNodeHistoryItems.GetLength() > 0) + if (actorInstanceData && actorInstanceData->mNodeHistoryItems.size() > 0) { const uint32 height = (recorder.CalcMaxNodeHistoryTrackIndex(*actorInstanceData) + 1) * (mNodeHistoryItemHeight + 3) + mNodeRectsStartHeight; mNodeHistoryRect.setTop(mNodeRectsStartHeight); @@ -2325,7 +2325,7 @@ namespace EMStudio } mEventHistoryTotalHeight = 0; - if (actorInstanceData && actorInstanceData->mEventHistoryItems.GetLength() > 0) + if (actorInstanceData && actorInstanceData->mEventHistoryItems.size() > 0) { mEventHistoryTotalHeight = (recorder.CalcMaxEventHistoryTrackIndex(*actorInstanceData) + 1) * 20; } @@ -2353,10 +2353,10 @@ namespace EMStudio // get the history items shortcut - const MCore::Array& historyItems = actorInstanceData->mNodeHistoryItems; + const AZStd::vector& historyItems = actorInstanceData->mNodeHistoryItems; QRect rect; - const uint32 numItems = historyItems.GetLength(); + const uint32 numItems = historyItems.size(); for (uint32 i = 0; i < numItems; ++i) { EMotionFX::Recorder::NodeHistoryItem* curItem = historyItems[i]; @@ -2462,20 +2462,20 @@ namespace EMStudio EMotionFX::AnimGraphNode* node = animGraph->RecursiveFindNodeById(item->mNodeId); if (node) { - MCore::Array nodePath; + AZStd::vector nodePath; EMotionFX::AnimGraphNode* curNode = node->GetParentNode(); while (curNode) { - nodePath.Insert(0, curNode); + nodePath.emplace(0, curNode); curNode = curNode->GetParentNode(); } AZStd::string nodePathString; nodePathString.reserve(256); - for (uint32 i = 0; i < nodePath.GetLength(); ++i) + for (uint32 i = 0; i < nodePath.size(); ++i) { nodePathString += nodePath[i]->GetName(); - if (i != nodePath.GetLength() - 1) + if (i != nodePath.size() - 1) { nodePathString += " > "; } @@ -2551,11 +2551,11 @@ namespace EMStudio return nullptr; } - const MCore::Array& historyItems = actorInstanceData->mEventHistoryItems; + const AZStd::vector& historyItems = actorInstanceData->mEventHistoryItems; const float tickHalfWidth = 7; const float tickHeight = 16; - const uint32 numItems = historyItems.GetLength(); + const uint32 numItems = historyItems.size(); for (uint32 i = 0; i < numItems; ++i) { EMotionFX::Recorder::EventHistoryItem* curItem = historyItems[i]; @@ -2648,20 +2648,20 @@ namespace EMStudio outString += AZStd::string::format("

Emitted By: 

"); outString += AZStd::string::format("

%s

", node->GetName()); - MCore::Array nodePath; + AZStd::vector nodePath; EMotionFX::AnimGraphNode* curNode = node->GetParentNode(); while (curNode) { - nodePath.Insert(0, curNode); + nodePath.emplace(0, curNode); curNode = curNode->GetParentNode(); } AZStd::string nodePathString; nodePathString.reserve(256); - for (uint32 i = 0; i < nodePath.GetLength(); ++i) + for (uint32 i = 0; i < nodePath.size(); ++i) { nodePathString += nodePath[i]->GetName(); - if (i != nodePath.GetLength() - 1) + if (i != nodePath.size() - 1) { nodePathString += " > "; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackDataWidget.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackDataWidget.h index 75968d1995..2709927254 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackDataWidget.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackDataWidget.h @@ -10,7 +10,7 @@ #if !defined(Q_MOC_RUN) #include -#include +#include #include "../StandardPluginsConfig.h" #include #include @@ -136,8 +136,8 @@ namespace EMStudio uint32 mNodeRectsStartHeight; double mOldCurrentTime; - MCore::Array mActiveItems; - MCore::Array mTrackRemap; + AZStd::vector mActiveItems; + AZStd::vector mTrackRemap; // copy and paste struct CopyElement diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackHeaderWidget.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackHeaderWidget.cpp index 963d188aa6..363a278b8e 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackHeaderWidget.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackHeaderWidget.cpp @@ -173,7 +173,7 @@ namespace EMStudio setVisible(true); mStackWidget->setVisible(false); - const uint32 numTracks = mPlugin->mTracks.GetLength(); + const uint32 numTracks = mPlugin->mTracks.size(); if (numTracks == 0) { return; diff --git a/Gems/EMotionFX/Code/MCore/Source/Array.h b/Gems/EMotionFX/Code/MCore/Source/Array.h deleted file mode 100644 index ef2f58119c..0000000000 --- a/Gems/EMotionFX/Code/MCore/Source/Array.h +++ /dev/null @@ -1,799 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -#pragma once - -#include "StandardHeaders.h" -#include "MCoreSystem.h" -#include "Algorithms.h" -#include "MemoryManager.h" - -#include - -namespace MCore -{ - /** - * Dynamic array template. - * This array template allows dynamic sizing. It also stores the memory category of the data. - * It can theoretically store 4294967296 items (maximum uint32 value). - */ - template - class Array - { - public: - /** - * The memory block ID, used inside the memory manager. - * This will make all arrays remain in the same memory blocks, which is more efficient in a lot of cases. - * However, array data can still remain in other blocks. - */ - enum - { - MEMORYBLOCK_ID = 2 - }; - - /** - * Default constructor. - * Initializes the array so it's empty and has no memory allocated. - */ - MCORE_INLINE Array() - : mData(nullptr) - , mLength(0) - , mMaxLength(0) - , mMemCategory(MCORE_MEMCATEGORY_ARRAY) {} - - /** - * Constructor which creates a given number of elements. - * @param elems The element data. - * @param num The number of elements in 'elems'. - * @param memCategory The memory category the array is in. - */ - MCORE_INLINE explicit Array(T* elems, uint32 num, uint16 memCategory = MCORE_MEMCATEGORY_ARRAY) - : mLength(num) - , mMaxLength(AllocSize(num)) - , mMemCategory(memCategory) - { - mData = (T*)MCore::Allocate(mMaxLength * sizeof(T), mMemCategory, MEMORYBLOCK_ID, MCORE_FILE, MCORE_LINE); - for (uint32 i = 0; i < mLength; ++i) - { - Construct(i, elems[i]); - } - } - - /** - * Constructor which initializes the length of the array on a given number. - * @param initSize The number of ellements to allocate space for. - * @param memCategory The memory category the array is in. - */ - MCORE_INLINE explicit Array(uint32 initSize, uint16 memCategory = MCORE_MEMCATEGORY_ARRAY) - : mData(nullptr) - , mLength(initSize) - , mMaxLength(initSize) - , mMemCategory(memCategory) - { - if (mMaxLength > 0) - { - mData = (T*)MCore::Allocate(mMaxLength * sizeof(T), mMemCategory, MEMORYBLOCK_ID, MCORE_FILE, MCORE_LINE); - for (uint32 i = 0; i < mLength; ++i) - { - Construct(i); - } - } - } - - /** - * Copy constructor. - * @param other The other array to copy the data from. - */ - Array(const Array& other) - : mData(nullptr) - , mLength(0) - , mMaxLength(0) - , mMemCategory(MCORE_MEMCATEGORY_ARRAY) { *this = other; } - - /** - * Move constructor. - * @param other The array to move the data from. - */ - Array(Array&& other) { mData = other.mData; mLength = other.mLength; mMaxLength = other.mMaxLength; mMemCategory = other.mMemCategory; other.mData = nullptr; other.mLength = 0; other.mMaxLength = 0; } - - /** - * Destructor. Deletes all entry data. - * However, if you store pointers to objects, these objects won't be deleted.
- * Example:
- *
-         * Array< Object* > data;
-         * for (uint32 i=0; i<10; i++)
-         *    data.Add( new Object() );
-         * 
- * Now when the array 'data' will be destructed, it will NOT free up the memory of the integers which you allocated by hand, using new. - * In order to free up this memory, you can do this: - *
-         * for (uint32 i=0; i
-         */
-        ~Array()
-        {
-            for (uint32 i = 0; i < mLength; ++i)
-            {
-                Destruct(i);
-            }
-            if (mData)
-            {
-                MCore::Free(mData);
-            }
-        }
-
-        /**
-         * Get the memory category ID where allocations made by this array belong to.
-         * On default the memory category is 0, which means unknown.
-         * @result The memory category ID.
-         */
-        MCORE_INLINE uint16 GetMemoryCategory() const                           { return mMemCategory; }
-
-        /**
-         * Set the memory category ID, where allocations made by this array will belong to.
-         * On default, after construction of the array, the category ID is 0, which means it is unknown.
-         * @param categoryID The memory category ID where this arrays allocations belong to.
-         */
-        MCORE_INLINE void SetMemoryCategory(uint16 categoryID)                  { mMemCategory = categoryID; }
-
-        /**
-         * Get a pointer to the first element.
-         * @result A pointer to the first element.
-         */
-        MCORE_INLINE T* GetPtr()                                                { return mData; }
-
-        /**
-         * Get a pointer to the first element.
-         * @result A pointer to the first element.
-         */
-        MCORE_INLINE T* GetPtr() const                                          { return mData; }
-
-        /**
-         * Get a given item/element.
-         * @param pos The item/element number.
-         * @result A reference to the element.
-         */
-        MCORE_INLINE T& GetItem(uint32 pos)                                     { return mData[pos]; }
-
-        /**
-         * Get the first element.
-         * @result A reference to the first element.
-         */
-        MCORE_INLINE T& GetFirst()                                              { return mData[0]; }
-
-        /**
-         * Get the last element.
-         * @result A reference to the last element.
-         */
-        MCORE_INLINE T& GetLast()                                               { return mData[mLength - 1]; }
-
-        /**
-         * Get a read-only pointer to the first element.
-         * @result A read-only pointer to the first element.
-         */
-        MCORE_INLINE const T* GetReadPtr() const                                { return mData; }
-
-        /**
-         * Get a read-only reference to a given element number.
-         * @param pos The element number.
-         * @result A read-only reference to the given element.
-         */
-        MCORE_INLINE const T& GetItem(uint32 pos) const                         { return mData[pos]; }
-
-        /**
-         * Get a read-only reference to the first element.
-         * @result A read-only reference to the first element.
-         */
-        MCORE_INLINE const T& GetFirst() const                                  { return mData[0]; }
-
-        /**
-         * Get a read-only reference to the last element.
-         * @result A read-only reference to the last element.
-         */
-        MCORE_INLINE const T& GetLast() const                                   { return mData[mLength - 1]; }
-
-        /**
-         * Check if the array is empty or not.
-         * @result Returns true when there are no elements in the array, otherwise false is returned.
-         */
-        MCORE_INLINE bool GetIsEmpty() const                                    { return (mLength == 0); }
-
-        /**
-         * Checks if the passed index is in the array's range.
-         * @param index The index to check.
-         * @return True if the passed index is valid, false if not.
-         */
-        MCORE_INLINE bool GetIsValidIndex(uint32 index) const                   { return (index < mLength); }
-
-        /**
-         * Get the number of elements in the array.
-         * @result The number of elements in the array.
-         */
-        MCORE_INLINE uint32 GetLength() const                                   { return mLength; }
-
-        /**
-         * Get the maximum number of elements. This is the number of elements there currently is space for to store.
-         * However, never use this to make for-loops to iterate through all elements. Use GetLength() instead for that.
-         * This purely has to do with pre-allocating, to reduce the number of reallocs.
-         * @result The maximum array length.
-         */
-        MCORE_INLINE uint32 GetMaxLength() const                                { return mMaxLength; }
-
-        /**
-         * Calculates the memory usage used by this array.
-         * @param includeMembers Include the class members in the calculation? (default=true).
-         * @result The number of bytes allocated by this array.
-         */
-        MCORE_INLINE uint32 CalcMemoryUsage(bool includeMembers = true) const
-        {
-            uint32 result = mMaxLength * sizeof(T);
-            if (includeMembers)
-            {
-                result += sizeof(MCore::Array);
-            }
-            return result;
-        }
-
-        /**
-         * Set a given element to a given value.
-         * @param pos The element number.
-         * @param value The value to store at that element number.
-         */
-        MCORE_INLINE void SetElem(uint32 pos, const T& value)                   { mData[pos] = value; }
-
-        /**
-         * Add a given element to the back of the array.
-         * @param x The element to add.
-         */
-        MCORE_INLINE void Add(const T& x)                                       { Grow(++mLength); Construct(mLength - 1, x); }
-
-        /**
-         * Add a given element to the back of the array, but without pre-allocation caching.
-         * @param x The element to add.
-         */
-        MCORE_INLINE void AddExact(const T& x)                                  { GrowExact(++mLength); Construct(mLength - 1, x); }
-
-        /**
-         * Add a given array to the back of this array.
-         * @param a The array to add.
-         */
-        MCORE_INLINE void Add(const Array& a)
-        {
-            uint32 l = mLength;
-            Grow(mLength + a.mLength);
-            for (uint32 i = 0; i < a.GetLength(); ++i)
-            {
-                Construct(l + i, a[i]);
-            }
-        }                                                                                                                                                                                   // TODO: a.GetLength() can be precaled before loop?
-
-        /**
-         * Add an empty (default constructed) element to the back of the array.
-         */
-        MCORE_INLINE void AddEmpty()                                            { Grow(++mLength); Construct(mLength - 1); }
-
-        /**
-         * Add an empty (default constructed) element to the back of the array, but without pre-allocation caching.
-         */
-        MCORE_INLINE void AddEmptyExact()                                       { GrowExact(++mLength); Construct(mLength - 1); }
-
-        /**
-         * Remove the first array element.
-         */
-        MCORE_INLINE void RemoveFirst()
-        {
-            if (mLength > 0)
-            {
-                Remove((uint32)0);
-            }
-        }
-
-        /**
-         * Remove the last array element.
-         */
-        MCORE_INLINE void RemoveLast()
-        {
-            if (mLength > 0)
-            {
-                Destruct(--mLength);
-            }
-        }
-
-        /**
-         * Insert an empty element (default constructed) at a given position in the array.
-         * @param pos The position to create the empty element.
-         */
-        MCORE_INLINE void Insert(uint32 pos)                                    { Grow(mLength + 1); MoveElements(pos + 1, pos, mLength - pos - 1); Construct(pos); }
-
-        /**
-         * Insert a given element at a given position in the array.
-         * @param pos The position to insert the empty element.
-         * @param x The element to store at this position.
-         */
-        MCORE_INLINE void Insert(uint32 pos, const T& x)                        { Grow(mLength + 1); MoveElements(pos + 1, pos, mLength - pos - 1); Construct(pos, x); }
-
-        /**
-         * Remove an element at a given position.
-         * @param pos The element number to remove.
-         */
-        MCORE_INLINE void Remove(uint32 pos)
-        {
-            AZ_Assert(pos < mLength, "Array index out of bounds");
-            Destruct(pos);
-            if (mLength > 1)
-            {
-                MoveElements(pos, pos + 1, mLength - pos - 1);
-            }
-            mLength--;
-        }
-
-        /**
-         * Remove a given number of elements starting at a given position in the array.
-         * @param pos The start element, so to start removing from.
-         * @param num The number of elements to remove from this position.
-         */
-        MCORE_INLINE void Remove(uint32 pos, uint32 num)
-        {
-            for (uint32 i = pos; i < pos + num; ++i)
-            {
-                Destruct(i);
-            }
-            MoveElements(pos, pos + num, mLength - pos - num);
-            mLength -= num;
-        }
-
-        /**
-         * Remove a given element with a given value.
-         * Only the first element with the given value will be removed.
-         * @param item The item/element to remove.
-         */
-        MCORE_INLINE bool RemoveByValue(const T& item)
-        {
-            const uint32 index = Find(item);
-            if (index == MCORE_INVALIDINDEX32)
-            {
-                return false;
-            }
-            Remove(index);
-            return true;
-        }
-
-        /**
-         * Remove a given element in the array and place the last element in the array at the created empty position.
-         * So if we have an array with the following characters : ABCDEFG
- * And we perform a SwapRemove(2), we will remove element C and place the last element (G) at the empty created position where C was located. - * So we will get this:
- * AB.DEFG [where . is empty, after we did the SwapRemove(2)]
- * ABGDEF [this is the result. G has been moved to the empty position]. - */ - MCORE_INLINE void SwapRemove(uint32 pos) - { - Destruct(pos); - if (pos != mLength - 1) - { - Construct(pos, mData[mLength - 1]); - Destruct(mLength - 1); - } - mLength--; - } // remove element at and place the last element of the array in that position - - /** - * Swap two elements. - * @param pos1 The first element number. - * @param pos2 The second element number. - */ - MCORE_INLINE void Swap(uint32 pos1, uint32 pos2) - { - if (pos1 != pos2) - { - MCore::Swap(GetItem(pos1), GetItem(pos2)); - } - } - - /** - * Clear the array contents. So GetLength() will return 0 after performing this method. - * @param clearMem If set to true (default) the allocated memory will also be released. If set to false, GetMaxLength() will still return the number of elements - * which the array contained before calling the Clear() method. - */ - MCORE_INLINE void Clear(bool clearMem = true) - { - for (uint32 i = 0; i < mLength; ++i) - { - Destruct(i); - } - mLength = 0; - if (clearMem) - { - Free(); - } - } - - /** - * Make sure the array has enough space to store a given number of elements. - * @param newLength The number of elements we want to make sure that will fit in the array. - */ - MCORE_INLINE void AssureSize(uint32 newLength) - { - if (mLength >= newLength) - { - return; - } - uint32 oldLen = mLength; - Grow(newLength); - for (uint32 i = oldLen; i < newLength; ++i) - { - Construct(i); - } - } - - /** - * Make sure this array has enough allocated storage to grow to a given number of elements elements without having to realloc. - * @param minLength The minimum length the array should have (actually the minimum maxLength, because this has no influence on what GetLength() will return). - */ - MCORE_INLINE void Reserve(uint32 minLength) - { - if (mMaxLength < minLength) - { - Realloc(minLength); - } - } - - /** - * The same as Reserve, except that this also can shrink the memory to the specified size if more has been allocated already. - * If the current length is larger than the specified minLength nothing will happen. - * @param minLength The minimum length the array should have. - */ - MCORE_INLINE void ReserveExact(uint32 minLength) - { - if (mLength > minLength) - { - return; - } - Realloc(minLength); - } - - /** - * Make the array as small as possible. So remove all extra pre-allocated data, so that the array consumes the least possible amount of memory. - */ - MCORE_INLINE void Shrink() - { - if (mLength == mMaxLength) - { - return; - } - Realloc(mLength); - } - - /** - * Check if the array contains a given element. - * @param x The element to check. - * @result Returns true when the array contains the element, otherwise false is returned. - */ - MCORE_INLINE bool Contains(const T& x) const { return (Find(x) != MCORE_INVALIDINDEX32); } - - /** - * Find the position of a given element. - * @param x The element to find. - * @result Returns the index in the array, ranging from [0 to GetLength()-1] when found, otherwise MCORE_INVALIDINDEX32 is returned. - */ - MCORE_INLINE uint32 Find(const T& x) const - { - for (uint32 i = 0; i < mLength; ++i) - { - if (mData[i] == x) - { - return i; - } - } - return MCORE_INVALIDINDEX32; - } - - - // sort function and standard sort function - typedef int32 (MCORE_CDECL * CmpFunc)(const T& itemA, const T& itemB); - static int32 MCORE_CDECL StdCmp(const T& itemA, const T& itemB) - { - if (itemA < itemB) - { - return -1; - } - else if (itemA == itemB) - { - return 0; - } - else - { - return 1; - } - } - static int32 MCORE_CDECL StdPtrObjCmp(const T& itemA, const T& itemB) - { - if (*itemA < *itemB) - { - return -1; - } - else if (*itemA == *itemB) - { - return 0; - } - else - { - return 1; - } - } - - /** - * Sort the complete array using a given sort function. - * @param cmp The sort function to use. - */ - MCORE_INLINE void Sort(CmpFunc cmp) { InnerSort(0, mLength - 1, cmp); } - - /** - * Sort a given part of the array using a given sort function. - * The default parameters are set so that it will sort the compelete array with a default compare function (which uses the < and > operators). - * The method will sort all elements between the given 'first' and 'last' element (first and last are also included in the sort). - * @param first The first element to start sorting. - * @param last The last element to sort (when set to MCORE_INVALIDINDEX32, GetLength()-1 will be used). - * @param cmp The compare function. - */ - MCORE_INLINE void Sort(uint32 first = 0, uint32 last = MCORE_INVALIDINDEX32, CmpFunc cmp = StdCmp) - { - if (last == MCORE_INVALIDINDEX32) - { - last = mLength - 1; - } - InnerSort(first, last, cmp); - } - - /** - * Performs a sort on a given part of the array. - * @param first The first element to start the sorting at. - * @param last The last element to end the sorting. - * @param cmp The compare function. - */ - MCORE_INLINE void InnerSort(int32 first, int32 last, CmpFunc cmp) - { - if (first >= last) - { - return; - } - int32 split = Partition(first, last, cmp); - InnerSort(first, split - 1, cmp); - InnerSort(split + 1, last, cmp); - } - - // resize in a fast way that doesn't call constructors or destructors - void ResizeFast(uint32 newLength) - { - if (mLength == newLength) - { - return; - } - - if (newLength > mLength) - { - GrowExact(newLength); - } - - mLength = newLength; - } - - /** - * Resize the array to a given size. - * This does not mean an actual realloc will be made. This will only happen when the new length is bigger than the maxLength of the array. - * @param newLength The new length the array should be. - * @result returns false if the allocation/reallocation of the array failed - */ - bool Resize(uint32 newLength) - { - if (mLength == newLength) - { - return true; - } - - // check for growing or shrinking array - if (newLength > mLength) - { - // growing array, construct empty elements at end of array - const uint32 oldLen = mLength; - GrowExact(newLength); - if (mData == nullptr) - { - return false; - } - for (uint32 i = oldLen; i < newLength; ++i) - { - Construct(i); - } - } - else - { - // shrinking array, destruct elements at end of array - for (uint32 i = newLength; i < mLength; ++i) - { - Destruct(i); - } - - mLength = newLength; - } - return true; - } - - /** - * Move "numElements" elements starting from the source index, to the dest index. - * Please note that the array has to be large enough. You can't move data past the end of the array. - * @param destIndex The destination index. - * @param sourceIndex The source index, where the source elements start. - * @param numElements The number of elements to move. - */ - MCORE_INLINE void MoveElements(uint32 destIndex, uint32 sourceIndex, uint32 numElements) - { - if (numElements > 0) - { - MCore::MemMove(mData + destIndex, mData + sourceIndex, numElements * sizeof(T)); - } - } - - // operators - bool operator==(const Array& other) const - { - if (mLength != other.mLength) - { - return false; - } - for (uint32 i = 0; i < mLength; ++i) - { - if (mData[i] != other.mData[i]) - { - return false; - } - } - return true; - } - //Array& operator= (const Array& other) { if (&other != this) { Clear(); mMemCategory = other.mMemCategory; Grow(other.mLength); for (uint32 i=0; i& operator= (const Array& other) - { - if (&other != this) - { - Clear(false); - mMemCategory = other.mMemCategory; - Grow(other.mLength); - for (uint32 i = 0; i < mLength; ++i) - { - Construct(i, other.mData[i]); - } - } - return *this; - } - Array& operator= (Array&& other) - { - AZ_Assert(&other != this, "Cannot assign array to itself."); - if (mData) - { - MCore::Free(mData); - } - mData = other.mData; - mMemCategory = other.mMemCategory; - mLength = other.mLength; - mMaxLength = other.mMaxLength; - other.mData = nullptr; - other.mLength = 0; - other.mMaxLength = 0; - return *this; - } - //Array& operator+ (const Array& other) const { Array newArray; newArray.Grow(mLength+other.mLength); uint32 i; for (i=0; i& operator+=(const T& other) { Add(other); return *this; } - Array& operator+=(const Array& other) { Add(other); return *this; } - MCORE_INLINE T& operator[](uint32 index) { AZ_Assert(index < mLength, "Array index out of bounds"); return mData[index]; } - MCORE_INLINE const T& operator[](uint32 index) const { AZ_Assert(index < mLength, "Array index out of bounds"); return mData[index]; } - - private: - T* mData; /**< The element data. */ - uint32 mLength; /**< The number of used elements in the array. */ - uint32 mMaxLength; /**< The number of elements that we have allocated memory for. */ - uint16 mMemCategory; /**< The memory category ID. */ - - // private functions - MCORE_INLINE void Grow(uint32 newLength) - { - mLength = newLength; - if (mMaxLength >= newLength) - { - return; - } - Realloc(AllocSize(newLength)); - } - MCORE_INLINE void GrowExact(uint32 newLength) - { - mLength = newLength; - if (mMaxLength < newLength) - { - Realloc(newLength); - } - } - MCORE_INLINE uint32 AllocSize(uint32 num) { return 1 + num /*+num/8*/; } - MCORE_INLINE void Alloc(uint32 num) { mData = (T*)MCore::Allocate(num * sizeof(T), mMemCategory, MEMORYBLOCK_ID, MCORE_FILE, MCORE_LINE); } - MCORE_INLINE void Realloc(uint32 newSize) - { - if (newSize == 0) - { - this->Free(); - return; - } - if (mData) - { - mData = (T*)MCore::Realloc(mData, newSize * sizeof(T), mMemCategory, MEMORYBLOCK_ID, MCORE_FILE, MCORE_LINE); - } - else - { - mData = (T*)MCore::Allocate(newSize * sizeof(T), mMemCategory, MEMORYBLOCK_ID, MCORE_FILE, MCORE_LINE); - } - - mMaxLength = newSize; - } - MCORE_INLINE void Free() - { - mLength = 0; - mMaxLength = 0; - if (mData) - { - MCore::Free(mData); - mData = nullptr; - } - } - MCORE_INLINE void Construct(uint32 index, const T& original) { ::new(mData + index)T(original); } // copy-construct an element at which is a copy of - MCORE_INLINE void Construct(uint32 index) { ::new(mData + index)T; } // construct an element at place - MCORE_INLINE void Destruct(uint32 index) - { - #if (MCORE_COMPILER == MCORE_COMPILER_MSVC) - MCORE_UNUSED(index); // work around an MSVC compiler bug, where it triggers a warning that parameter 'index' is unused - #endif - (mData + index)->~T(); - } // destruct an element at - - // partition part of array (for sorting) - int32 Partition(int32 left, int32 right, CmpFunc cmp) - { - ::MCore::Swap(mData[left], mData[ (left + right) >> 1 ]); - - T& target = mData[right]; - int32 i = left - 1; - int32 j = right; - - bool neverQuit = true; // workaround to disable a "warning C4127: conditional expression is constant" - while (neverQuit) - { - while (i < j) - { - if (cmp(mData[++i], target) >= 0) - { - break; - } - } - while (j > i) - { - if (cmp(mData[--j], target) <= 0) - { - break; - } - } - if (i >= j) - { - break; - } - ::MCore::Swap(mData[i], mData[j]); - } - - ::MCore::Swap(mData[i], mData[right]); - return i; - } - }; -} // namespace MCore diff --git a/Gems/EMotionFX/Code/MCore/Source/Config.h b/Gems/EMotionFX/Code/MCore/Source/Config.h index d01bab61fc..c753a45ec3 100644 --- a/Gems/EMotionFX/Code/MCore/Source/Config.h +++ b/Gems/EMotionFX/Code/MCore/Source/Config.h @@ -8,6 +8,7 @@ #pragma once +#include #include #include @@ -275,23 +276,35 @@ typedef uintptr_t uintPointer; // mark as unused to prevent compiler warnings #define MCORE_UNUSED(x) static_cast(x) +namespace MCore +{ + template + inline static constexpr IndexType InvalidIndexT = static_cast(-1); + + inline static constexpr const size_t InvalidIndex = InvalidIndexT; + inline static constexpr const AZ::u64 InvalidIndex64 = InvalidIndexT; + inline static constexpr const AZ::u32 InvalidIndex32 = InvalidIndexT; + inline static constexpr const AZ::u16 InvalidIndex16 = InvalidIndexT; + inline static constexpr const AZ::u8 InvalidIndex8 = InvalidIndexT; +} // namespace MCore + /** * Often there are functions that allow you to search for objects. Such functions return some index value that points * inside for example the array of objects. However, in case the object we are searching for cannot be found, some * value has to be returned that identifies that the object cannot be found. The MCORE_INVALIDINDEX32 value is used * used as this value. The real value is 0xFFFFFFFF. */ -#define MCORE_INVALIDINDEX32 0xFFFFFFFF +#define MCORE_INVALIDINDEX32 MCore::InvalidIndex32 /** * The 16 bit index variant of MCORE_INVALIDINDEX32. * The real value is 0xFFFF. */ -#define MCORE_INVALIDINDEX16 0xFFFF +#define MCORE_INVALIDINDEX16 MCore::InvalidIndex16 /** * The 8 bit index variant of MCORE_INVALIDINDEX32. * The real value is 0xFF. */ -#define MCORE_INVALIDINDEX8 0xFF +#define MCORE_INVALIDINDEX8 MCore::InvalidIndex8 diff --git a/Gems/EMotionFX/Code/MCore/Source/HashTable.h b/Gems/EMotionFX/Code/MCore/Source/HashTable.h deleted file mode 100644 index 5310935f50..0000000000 --- a/Gems/EMotionFX/Code/MCore/Source/HashTable.h +++ /dev/null @@ -1,239 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -#pragma once - -// include the needed headers -#include "StandardHeaders.h" -#include "Array.h" -#include "FastMath.h" -#include "HashFunctions.h" - - -namespace MCore -{ - /** - * The Hash Table template. - * Hash tables can be used to speedup searching of specific values based on a key. - * The table has an array of table elements, which each can contain multiple hash table entries. - * Each entry is identified by a unique key, which can be of any type, as long as the == operator is specified. - * Next to a unique key, every entry contains a value. The hash table implementation contains methods to add new - * entries and to retrieve the value for a given key. Hashing is used to speedup this search. - * The hash value of a given key is calculated based on a specified hashing function that you pass to the constructor. - * This hash function will return a non-negative (so positive) integer based on the input key. - * Performance tests have shown that you need at least 100 entries to make it faster than linear searches. This however - * also depends on the speed of your hash function and some other factors. But it is a good practise to replace your - * linear searches by a hash table when you have more than 100 items to search through. The more items to search through - * the bigger the advantage of hashing over linear searches will be. Here follows a small table that shows how much faster your - * searches can be compared to linear searches. - */ - template - class HashTable - { - public: - /** - * A hash table entry, which contains a unique key and a value for this key. - */ - class Entry - { - friend class HashTable; - MCORE_MEMORYOBJECTCATEGORY(HashTable, MCORE_DEFAULT_ALIGNMENT, MCORE_MEMCATEGORY_HASHTABLE) - - public: - /** - * The constructor. - * @param key The unique key of this entry. - * @param value The value linked to this key. - */ - MCORE_INLINE Entry(const Key& key, const Value& value) - : mKey(key) - , mValue(value) {} - - /** - * Set the value of this entry. - * @param value The value to set for this entry. - */ - MCORE_INLINE void SetValue(const Value& value) { mValue = value; } - - /** - * Get the value of this entry. - * @result The value that is linked to the key of this entry. - */ - MCORE_INLINE const Value& GetValue() const { return mValue; } - - /** - * Get the key of this entry. - * @result The unique key of this entry. - */ - MCORE_INLINE const Key& GetKey() const { return mKey; } - - private: - Key mKey; /**< The unique key. */ - Value mValue; /**< The value that is linked to the given key. */ - }; - - - /** - * The default constructor. - * This creates an empty hash table. You need to call the Init function before you can use the table. - * @see Init - */ - HashTable(); - - /** - * The extended constructor, which also initializes the table automatically. - * You do NOT need to call the Init function anymore when you use this constructor. - * @param maxElements The maximum number of table elements. The higher the value, the more gain when dealing with many entries. - * Values between 100 and 1000 are often good numbers, depending on the number of entries you are dealing with. - */ - HashTable(uint32 maxElements); - - /** - * Copy constructor. - * @param other The table to create a copy of. - */ - HashTable(const HashTable& other); - - /** - * The destructor. - * This automatically clears all table entries. - * The hash function object that was passed to the extended constructor or the Init function will be - * deleted from memory automatically. - */ - ~HashTable(); - - /** - * Clear the hash table. - * This removes all entries from the table. If you like to use the table again later on you will need to - * call the Init function again. - * This also automatically deletes the hash function object, that you passed to the extended constructor or init function, from memory. - * @see Init - */ - void Clear(); - - /** - * Locate an entry with a given key. - * When the entry cannot be found, this method will NOT modify the outElementNr and outEntryNr parameters. - * @param key The key to search for. - * @param outElementNr A pointer to an integer in which this method will store the table element number, in case the entry is found. - * @param outEntryNr A pointer to an integer in which this method will store the entry number (index) into the table element array, in case the entry is found. - * @result Returns true when the entry with the given key could be found, otherwise false is returned. - */ - MCORE_INLINE bool FindEntry(const Key& key, uint32* outElementNr, uint32* outEntryNr) const; - - /** - * Initialize the hash table. - * @param maxElements The maximum number of table elements. The higher the value, the more gain when dealing with many entries. - * Values between 100 and 1000 are often good numbers, depending on the number of entries you are dealing with. - */ - void Init(uint32 maxElements); - - /** - * Add an entry to the hash table. - * It is VERY important that the key is unique and does NOT already exist within this table! - * @param key The unique key of the entry. - * @param value The value that is linked to this key. - */ - void Add(const Key& key, const Value& value); - - /** - * Get a value from the table. - * @param inKey The key of the entry which contains the value. - * @param outValue A pointer to an object where this method will write the value of the entry in. - * @result Returns true when the value has been retrieved successfully. False will be returned when no entry with the specified - * key could be located. - */ - MCORE_INLINE bool GetValue(const Key& inKey, Value* outValue) const; - - /** - * Set the value that is linked to a given key. - * @param key The unique key of the entry to set the value for. - * @param value The value to link to the specified key. - * @result Returns true when the value has been set successfully, or false when there is no entry with the specified key inside this table. - */ - MCORE_INLINE bool SetValue(const Key& key, const Value& value); - - /** - * Check if this hash table contains an entry with a specified key. - * @param key The key of the entry to search for. - * @result Returns true when this hash table contains an entry with the specified key, otherwise false is returned. - */ - MCORE_INLINE bool Contains(const Key& key) const; - - /** - * Remove the entry which has the specified key. - * @param key The key of the entry to remove. - * @result Returns true when the entry with the specified key has been removed successfully, otherwise false is returned, which means - * that there is no entry with the specified key. - */ - bool Remove(const Key& key); - - /** - * Get the number of table elements. - * @result The number of table elements. - */ - MCORE_INLINE uint32 GetNumTableElements() const; - - /** - * Get the number of entries in a given table element. - * @param tableElementNr The table element number to get the number of entries for. - * @result The number of entries for the specified table entry. - */ - MCORE_INLINE uint32 GetNumEntries(uint32 tableElementNr) const; - - /** - * Get the total number of entries inside the table. - * @result The total number of stored entries inside the table. - */ - uint32 GetTotalNumEntries() const; - - /** - * Calculate the load balance, which is a percentage that represents how many percent of the - * table elements are used. If the returned value equals 50, then it means that 50 percent of the - * table elements are storing entries. The other 50% are then not used. - * When you have added many entries (more than then the number of table elements), and the load balance - * is not 100% or anywhere near it, it means your hash function is very inefficient, because it does not spread - * the entries over the entire hash table, which might mean that there is some nasty clustering going on, which can - * greatly decrease performance. - * @result A floating point value in range of 0..100, which respresents the percentage of table elements that is in use. - */ - float CalcLoadBalance() const; - - /** - * Calculate the average number of entries per used table element. - * The more entries per table element, the slower your searches will be. - * The optimal value returned by this function would therefore be 1. - * @result The average number of entries per table element. - */ - float CalcAverageNumEntries() const; - - /** - * Get a given entry from the table, when you know its location in the table. - * @param tableElementNr The table element number. - * @param entryNr The entry number inside this table element. - * @result The reference to the entry, with write access. - */ - MCORE_INLINE Entry& GetEntry(uint32 tableElementNr, uint32 entryNr); - - /** - * The assignment operator. - * This clones the entire table. - * @param other The table to create a copy of. - * @result The copied version of the specified table. - */ - HashTable& operator = (const HashTable& other); - - protected: - MCore::Array< MCore::Array* > mElements; /**< The table elements, where nullptr means the element is empty. */ - uint32 mTotalNumEntries; /**< The cached number of entries in the table. */ - }; - - - // include the inline code -#include "HashTable.inl" -} // namespace MCore diff --git a/Gems/EMotionFX/Code/MCore/Source/HashTable.inl b/Gems/EMotionFX/Code/MCore/Source/HashTable.inl deleted file mode 100644 index 580f5e964c..0000000000 --- a/Gems/EMotionFX/Code/MCore/Source/HashTable.inl +++ /dev/null @@ -1,338 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -// default constructor -template -HashTable::HashTable() -{ - mElements.SetMemoryCategory(MCORE_MEMCATEGORY_HASHTABLE); - mTotalNumEntries = 0; -} - - -// extended constructor -template -HashTable::HashTable(uint32 maxElements) -{ - mElements.SetMemoryCategory(MCORE_MEMCATEGORY_HASHTABLE); - mTotalNumEntries = 0; - Init(maxElements); -} - - -// copy constructor -template -HashTable::HashTable(const HashTable& other) - : mTotalNumEntries(0) -{ - *this = other; -} - - -// destructor -template -HashTable::~HashTable() -{ - Clear(); -} - - -// clear the table -template -void HashTable::Clear() -{ - // get rid of existing elements - const uint32 numElems = mElements.GetLength(); - for (uint32 i = 0; i < numElems; ++i) - { - if (mElements[i]) - { - delete mElements[i]; - } - } - - // clear the array - mElements.Clear(); - - mTotalNumEntries = 0; -} - - -// find the entry with a given key -template -bool HashTable::FindEntry(const Key& key, uint32* outElementNr, uint32* outEntryNr) const -{ - // calculate the hash value - uint32 hashResult = Hash(key) % mElements.GetLength(); - - // check if the we have an entry at this hash position - if (mElements[hashResult] == nullptr) - { - return false; - } - - // search inside the array of entries - const uint32 numElements = mElements[hashResult]->GetLength(); - for (uint32 i = 0; i < numElements; ++i) - { - // if we found the one we are searching for - if (mElements[hashResult]->GetItem(i).mKey == key) - { - *outElementNr = hashResult; - *outEntryNr = i; - return true; - } - } - - return false; -} - - -// initialize the table at a given maximum amount of elements -template -void HashTable::Init(uint32 maxElements) -{ - // get rid of existing elements - Clear(); - - // resize the array - mElements.Resize(maxElements); - mElements.Shrink(); - - // reset all the elements - for (uint32 i = 0; i < maxElements; ++i) - { - mElements[i] = nullptr; - } -} - - -// add an entry to the table -template -void HashTable::Add(const Key& key, const Value& value) -{ - // calculate the hash value - uint32 hashResult = Hash(key) % mElements.GetLength(); - - // make sure there isn't already an element with this key - MCORE_ASSERT(Contains(key) == false); - - // if the array isn't allocated yet, do so - if (mElements[hashResult] == nullptr) - { - mElements[hashResult] = new MCore::Array< Entry >(); - mElements[hashResult]->SetMemoryCategory(MCORE_MEMCATEGORY_HASHTABLE); - } - - // add the entry to the array - mElements[hashResult]->Add(Entry(key, value)); - - // increase the total number of entries - mTotalNumEntries++; -} - - -// get a value -template -bool HashTable::GetValue(const Key& inKey, Value* outValue) const -{ - // try to find the element - uint32 elementNr, entryNr; - if (FindEntry(inKey, &elementNr, &entryNr)) - { - *outValue = mElements[elementNr]->GetItem(entryNr).mValue; - return true; - } - - // nothing found - return false; -} - - -// check if there is an entry using the specified key -template -bool HashTable::Contains(const Key& key) const -{ - uint32 elementNr, entryNr; - return FindEntry(key, &elementNr, &entryNr); -} - - -template -bool HashTable::Remove(const Key& key) -{ - uint32 elementNr, entryNr; - if (FindEntry(key, &elementNr, &entryNr)) - { - // remove the element - mElements[elementNr]->Remove(entryNr); - - // remove the array if it is empty - if (mElements[elementNr]->GetLength() == 0) - { - delete mElements[elementNr]; - mElements[elementNr] = nullptr; - } - - // decrease the total number of entries - mTotalNumEntries--; - - // yeah, we successfully removed it - return true; - } - - // the element wasn't found, so cannot be removed - return false; -} - - -// get the number of table elements -template -uint32 HashTable::GetNumTableElements() const -{ - return mElements.GetLength(); -} - - -// get the get the number of entries for a given table element -template -uint32 HashTable::GetNumEntries(uint32 tableElementNr) const -{ - if (mElements[tableElementNr] == nullptr) - { - return 0; - } - - return mElements[tableElementNr]->GetLength(); -} - - -// get the number of entries in the table -template -uint32 HashTable::GetTotalNumEntries() const -{ - return mTotalNumEntries; -} - - -// calculate the load balance -template -float HashTable::CalcLoadBalance() const -{ - uint32 numUsedElements = 0; - - // traverse all elements - const uint32 numElements = mElements.GetLength(); - for (uint32 i = 0; i < numElements; ++i) - { - if (mElements[i]) - { - numUsedElements++; - } - } - - if (numUsedElements == 0) - { - return 0; - } - - return (numUsedElements / (float)numElements) * 100.0f; -} - - -template -float HashTable::CalcAverageNumEntries() const -{ - uint32 numEntries = 0; - uint32 numUsedElements = 0; - - // traverse all elements - const uint32 numElements = mElements.GetLength(); - for (uint32 i = 0; i < numElements; ++i) - { - if (mElements[i]) - { - numUsedElements++; - numEntries += mElements[i]->GetLength(); - } - } - - if (numEntries == 0) - { - return 0; - } - - return numEntries / (float)numUsedElements; -} - - -// update the value of the entry with a given key -template -bool HashTable::SetValue(const Key& key, const Value& value) -{ - // try to find the element - uint32 elementNr, entryNr; - if (FindEntry(key, &elementNr, &entryNr)) - { - mElements[elementNr]->GetItem(entryNr).mValue = value; - return true; - } - - // nothing found - return false; -} - - -// get a given entry -template -MCORE_INLINE typename HashTable::Entry& HashTable::GetEntry(uint32 tableElementNr, uint32 entryNr) -{ - MCORE_ASSERT(tableElementNr < mElements.GetLength()); // make sure the values are in range - MCORE_ASSERT(mElements[tableElementNr]); // this table element must have entries - MCORE_ASSERT(entryNr < mElements[tableElementNr]->GetLength()); // - - return mElements[tableElementNr]->GetItem(entryNr); -} - - -// operator = -template -HashTable& HashTable::operator = (const HashTable& other) -{ - if (&other == this) - { - return *this; - } - - // get rid of old data - Clear(); - - // copy the number of entries - mTotalNumEntries = other.mTotalNumEntries; - - // resize the element array - mElements.Resize(other.mElements.GetLength()); - - // copy the element entries - const uint32 numElements = mElements.GetLength(); - for (uint32 i = 0; i < numElements; ++i) - { - if (other.mElements[i]) - { - // create the array and copy the entries - mElements[i] = new MCore::Array< Entry >(); - *mElements[i] = *other.mElements[i]; - } - else - { - mElements[i] = nullptr; - } - } - - return *this; -} diff --git a/Gems/EMotionFX/Code/MCore/Source/LogManager.cpp b/Gems/EMotionFX/Code/MCore/Source/LogManager.cpp index a4e0a71cee..ecf4eb9168 100644 --- a/Gems/EMotionFX/Code/MCore/Source/LogManager.cpp +++ b/Gems/EMotionFX/Code/MCore/Source/LogManager.cpp @@ -10,8 +10,6 @@ #include #include "LogManager.h" -#include - namespace MCore { // static mutex @@ -60,8 +58,6 @@ namespace MCore // constructor LogManager::LogManager() { - mLogCallbacks.SetMemoryCategory(MCORE_MEMCATEGORY_LOGMANAGER); - // initialize the enabled log levels InitLogLevels(); } @@ -82,7 +78,7 @@ namespace MCore LockGuard lock(mMutex); // add the callback to the stack - mLogCallbacks.Add(callback); + mLogCallbacks.emplace_back(callback); // collect the enabled log levels InitLogLevels(); @@ -90,16 +86,16 @@ namespace MCore // remove a specific log callback from the stack - void LogManager::RemoveLogCallback(uint32 index) + void LogManager::RemoveLogCallback(size_t index) { - MCORE_ASSERT(mLogCallbacks.GetIsValidIndex(index)); + MCORE_ASSERT(index < mLogCallbacks.size()); LockGuard lock(mMutex); // delete it from memory delete mLogCallbacks[index]; // remove the callback from the stack - mLogCallbacks.Remove(index); + mLogCallbacks.erase(AZStd::next(begin(mLogCallbacks), index)); // collect the enabled log levels InitLogLevels(); @@ -110,25 +106,16 @@ namespace MCore { LockGuard lock(mMutex); - // iterate through all log callbacks - for (uint32 i = 0; i < mLogCallbacks.GetLength(); ) + // Put all the callbacks of the type to be removed at the end of the vector + mLogCallbacks.erase(AZStd::remove_if(begin(mLogCallbacks), end(mLogCallbacks), [type](const LogCallback* callback) { - LogCallback* callback = mLogCallbacks[i]; - - // check if we are dealing with a log file if (callback->GetType() == type) { - // get rid of the callback instance delete callback; - - // remove the callback from the stack - mLogCallbacks.Remove(i); + return true; } - else - { - i++; - } - } + return false; + })); // collect the enabled log levels InitLogLevels(); @@ -141,13 +128,12 @@ namespace MCore LockGuard lock(mMutex); // get rid of the callbacks - const uint32 num = mLogCallbacks.GetLength(); - for (uint32 i = 0; i < num; ++i) + for (auto* logCallback : mLogCallbacks) { - delete mLogCallbacks[i]; + delete logCallback; } - mLogCallbacks.Clear(true); + mLogCallbacks.clear(); // collect the enabled log levels InitLogLevels(); @@ -155,15 +141,15 @@ namespace MCore // retrieve a pointer to the given log callback - LogCallback* LogManager::GetLogCallback(uint32 index) + LogCallback* LogManager::GetLogCallback(size_t index) { return mLogCallbacks[index]; } // return number of log callbacks in the stack - uint32 LogManager::GetNumLogCallbacks() const + size_t LogManager::GetNumLogCallbacks() const { - return mLogCallbacks.GetLength(); + return mLogCallbacks.size(); } // collect all enabled log levels @@ -173,10 +159,9 @@ namespace MCore int32 logLevels = LogCallback::LOGLEVEL_NONE; // enable all log levels that are enabled by any of the callbacks - const uint32 num = mLogCallbacks.GetLength(); - for (uint32 i = 0; i < num; ++i) + for (auto* logCallback : mLogCallbacks) { - logLevels |= (int32)mLogCallbacks[i]->GetLogLevels(); + logLevels |= (int32)logCallback->GetLogLevels(); } mLogLevels = (LogCallback::ELogLevel)logLevels; @@ -187,10 +172,9 @@ namespace MCore void LogManager::SetLogLevels(LogCallback::ELogLevel logLevels) { // iterate through all log callbacks and set it to the given log levels - const uint32 num = mLogCallbacks.GetLength(); - for (uint32 i = 0; i < num; ++i) + for (auto* logCallback : mLogCallbacks) { - mLogCallbacks[i]->SetLogLevels(logLevels); + logCallback->SetLogLevels(logLevels); } // force set the log manager's log levels to the given one as well @@ -204,23 +188,21 @@ namespace MCore LockGuard lock(mMutex); // iterate through all callbacks - const uint32 num = mLogCallbacks.GetLength(); - for (uint32 i = 0; i < num; ++i) + for (auto* logCallback : mLogCallbacks) { - if (mLogCallbacks[i]->GetLogLevels() & logLevel) + if (logCallback->GetLogLevels() & logLevel) { - mLogCallbacks[i]->Log(message, logLevel); + logCallback->Log(message, logLevel); } } } // find the index of a given callback - uint32 LogManager::FindLogCallback(LogCallback* callback) const + size_t LogManager::FindLogCallback(LogCallback* callback) const { // iterate through all callbacks - const uint32 num = mLogCallbacks.GetLength(); - for (uint32 i = 0; i < num; ++i) + for (size_t i = 0; i < mLogCallbacks.size(); ++i) { if (mLogCallbacks[i] == callback) { @@ -228,7 +210,7 @@ namespace MCore } } - return MCORE_INVALIDINDEX32; + return InvalidIndex; } diff --git a/Gems/EMotionFX/Code/MCore/Source/LogManager.h b/Gems/EMotionFX/Code/MCore/Source/LogManager.h index 1f8ac34cae..d5e2316436 100644 --- a/Gems/EMotionFX/Code/MCore/Source/LogManager.h +++ b/Gems/EMotionFX/Code/MCore/Source/LogManager.h @@ -10,8 +10,8 @@ // include the required headers #include +#include #include "StandardHeaders.h" -#include "Array.h" #include "MultiThreadManager.h" @@ -187,7 +187,7 @@ namespace MCore * Remove the given callback from the stack. * @param index The index of the callback to remove. */ - void RemoveLogCallback(uint32 index); + void RemoveLogCallback(size_t index); /** * Remove all given log callbacks by type from the stack. @@ -205,20 +205,20 @@ namespace MCore * @param index The index of the callback. * @return A pointer to the callback. */ - LogCallback* GetLogCallback(uint32 index); + LogCallback* GetLogCallback(size_t index); /** * Find the index of a given callback. * @param callback The callback object to find. * @result Returns the index value, or MCORE_INVALIDINDEX32 when not found. */ - uint32 FindLogCallback(LogCallback* callback) const; + size_t FindLogCallback(LogCallback* callback) const; /** * Return the number of log callbacks managed by this class. * @return Number of log callbacks. */ - uint32 GetNumLogCallbacks() const; + size_t GetNumLogCallbacks() const; /** * Force set the log levels of all callbacks in the log manager. @@ -252,7 +252,7 @@ namespace MCore static Mutex mGlobalMutex; /**< The multithread mutex, used by some global Log functions. */ private: - Array mLogCallbacks; /**< A collection of log callback instances. */ + AZStd::vector mLogCallbacks; /**< A collection of log callback instances. */ LogCallback::ELogLevel mLogLevels; /**< The log levels that will pass one of the callbacks. All messages from log flags which are disabled won't be logged. */ Mutex mMutex; /**< The mutex for logging locally. */ }; diff --git a/Gems/EMotionFX/Code/MCore/Source/MCoreCommandManager.h b/Gems/EMotionFX/Code/MCore/Source/MCoreCommandManager.h index dfa99523fb..3a6aaf33c6 100644 --- a/Gems/EMotionFX/Code/MCore/Source/MCoreCommandManager.h +++ b/Gems/EMotionFX/Code/MCore/Source/MCoreCommandManager.h @@ -11,7 +11,7 @@ #include #include #include "StandardHeaders.h" -#include +#include #include "Command.h" #include "CommandGroup.h" diff --git a/Gems/EMotionFX/Code/MCore/mcore_files.cmake b/Gems/EMotionFX/Code/MCore/mcore_files.cmake index 43a41b4a11..65b0cf6ca6 100644 --- a/Gems/EMotionFX/Code/MCore/mcore_files.cmake +++ b/Gems/EMotionFX/Code/MCore/mcore_files.cmake @@ -13,7 +13,6 @@ set(FILES Source/Algorithms.h Source/Algorithms.inl Source/AlignedArray.h - Source/Array.h Source/Array2D.h Source/Array2D.inl Source/Attribute.cpp @@ -79,8 +78,6 @@ set(FILES Source/FileSystem.cpp Source/FileSystem.h Source/HashFunctions.h - Source/HashTable.h - Source/HashTable.inl Source/IDGenerator.cpp Source/IDGenerator.h Source/LogManager.cpp diff --git a/Gems/EMotionFX/Code/MysticQt/Source/DialogStack.cpp b/Gems/EMotionFX/Code/MysticQt/Source/DialogStack.cpp index 75d97fa065..36c0edf986 100644 --- a/Gems/EMotionFX/Code/MysticQt/Source/DialogStack.cpp +++ b/Gems/EMotionFX/Code/MysticQt/Source/DialogStack.cpp @@ -50,32 +50,10 @@ namespace MysticQt }; - // the constructor - DialogStack::Dialog::Dialog() - { - mButton = nullptr; - mFrame = nullptr; - mWidget = nullptr; - mDialogWidget = nullptr; - mSplitter = nullptr; - mClosable = true; - } - - - // destructor - DialogStack::Dialog::~Dialog() - { - delete mDialogWidget; - } - - // the constructor DialogStack::DialogStack(QWidget* parent) : QScrollArea(parent) { - // set the memory category of the dialog array - mDialogs.SetMemoryCategory(MEMCATEGORY_MYSTICQT); - // set the object name setObjectName("DialogStack"); @@ -102,7 +80,7 @@ namespace MysticQt void DialogStack::Clear() { // destroy the dialogs - mDialogs.Clear(); + mDialogs.clear(); // update the scroll bars UpdateScrollBars(); @@ -123,7 +101,7 @@ namespace MysticQt // add the dialog widget // the splitter is hierarchical : {a, {b, c}} QSplitter* dialogSplitter; - if (mDialogs.GetLength() == 0) + if (mDialogs.empty()) { // add the dialog widget dialogSplitter = mRootSplitter; @@ -138,10 +116,10 @@ namespace MysticQt else { // check if one space is free on the last splitter - if (mDialogs.GetLast().mSplitter->count() == 1) + if (mDialogs.back().mSplitter->count() == 1) { // add the dialog widget - dialogSplitter = mDialogs.GetLast().mSplitter; + dialogSplitter = mDialogs.back().mSplitter; dialogSplitter->addWidget(dialogWidget); // stretch if needed @@ -151,16 +129,16 @@ namespace MysticQt } // less space used by the splitter when the last dialog is closed - if (mDialogs.GetLast().mFrame->isHidden()) + if (mDialogs.back().mFrame->isHidden()) { - mDialogs.GetLast().mSplitter->handle(1)->setFixedHeight(1); - mDialogs.GetLast().mSplitter->setStyleSheet("QSplitter::handle{ height: 1px; background: transparent; }"); + mDialogs.back().mSplitter->handle(1)->setFixedHeight(1); + mDialogs.back().mSplitter->setStyleSheet("QSplitter::handle{ height: 1px; background: transparent; }"); } // disable the splitter - if (mDialogs.GetLast().mFrame->isHidden()) + if (mDialogs.back().mFrame->isHidden()) { - mDialogs.GetLast().mSplitter->handle(1)->setDisabled(true); + mDialogs.back().mSplitter->handle(1)->setDisabled(true); } } else // already two dialogs in the splitter @@ -171,24 +149,24 @@ namespace MysticQt dialogSplitter->setChildrenCollapsible(false); // add the current last dialog and the new dialog after - dialogSplitter->addWidget(mDialogs.GetLast().mDialogWidget); + dialogSplitter->addWidget(mDialogs.back().mDialogWidget.get()); dialogSplitter->addWidget(dialogWidget); // stretch if needed - if (mDialogs.GetLast().mMaximizeSize && mDialogs.GetLast().mStretchWhenMaximize) + if (mDialogs.back().mMaximizeSize && mDialogs.back().mStretchWhenMaximize) { dialogSplitter->setStretchFactor(0, 1); } // less space used by the splitter when the last dialog is closed - if (mDialogs.GetLast().mFrame->isHidden()) + if (mDialogs.back().mFrame->isHidden()) { dialogSplitter->handle(1)->setFixedHeight(1); dialogSplitter->setStyleSheet("QSplitter::handle{ height: 1px; background: transparent; }"); } // disable the splitter - if (mDialogs.GetLast().mFrame->isHidden()) + if (mDialogs.back().mFrame->isHidden()) { dialogSplitter->handle(1)->setDisabled(true); } @@ -200,24 +178,27 @@ namespace MysticQt } // replace the last dialog by the new splitter - mDialogs.GetLast().mSplitter->addWidget(dialogSplitter); + mDialogs.back().mSplitter->addWidget(dialogSplitter); // disable the splitter - const uint32 lastDialogIndex = mDialogs.GetLength() - 1; - if (mDialogs[lastDialogIndex - 1].mFrame->isHidden()) + if (mDialogs.size() > 1) { - mDialogs.GetLast().mSplitter->handle(1)->setDisabled(true); - } + const auto previousDialogIt = mDialogs.end() - 2; + if (previousDialogIt->mFrame->isHidden()) + { + mDialogs.back().mSplitter->handle(1)->setDisabled(true); + } - // stretch the splitter if needed - // the correct behavior is found after experimentations - if ((mDialogs.GetLast().mMaximizeSize && mDialogs.GetLast().mStretchWhenMaximize) || (mDialogs[lastDialogIndex - 1].mMaximizeSize && mDialogs[lastDialogIndex - 1].mStretchWhenMaximize == false)) - { - mDialogs.GetLast().mSplitter->setStretchFactor(1, 1); + // stretch the splitter if needed + // the correct behavior is found after experimentations + if ((mDialogs.back().mMaximizeSize && mDialogs.back().mStretchWhenMaximize) || (previousDialogIt->mMaximizeSize && previousDialogIt->mStretchWhenMaximize == false)) + { + mDialogs.back().mSplitter->setStretchFactor(1, 1); + } } // set the new splitter of the last dialog - mDialogs.GetLast().mSplitter = dialogSplitter; + mDialogs.back().mSplitter = dialogSplitter; } } @@ -280,17 +261,20 @@ namespace MysticQt dialogWidget->adjustSize(); // register it, so that we know which frame is linked to which header button - mDialogs.AddEmpty(); - mDialogs.GetLast().mButton = headerButton; - mDialogs.GetLast().mFrame = frame; - mDialogs.GetLast().mWidget = widget; - mDialogs.GetLast().mDialogWidget = dialogWidget; - mDialogs.GetLast().mSplitter = dialogSplitter; - mDialogs.GetLast().mClosable = closable; - mDialogs.GetLast().mMaximizeSize = maximizeSize; - mDialogs.GetLast().mStretchWhenMaximize = stretchWhenMaximize; - mDialogs.GetLast().mLayout = layout; - mDialogs.GetLast().mDialogLayout = dialogLayout; + mDialogs.emplace_back(Dialog{ + /*.mButton =*/ headerButton, + /*.mFrame =*/ frame, + /*.mWidget =*/ widget, + /*.mDialogWidget =*/ AZStd::unique_ptr{dialogWidget}, + /*.mSplitter =*/ dialogSplitter, + /*.mClosable =*/ closable, + /*.mMaximizeSize =*/ maximizeSize, + /*.mStretchWhenMaximize =*/ stretchWhenMaximize, + /*.mMinimumHeightBeforeClose =*/ 0, + /*.mMaximumHeightBeforeClose =*/ 0, + /*.mLayout =*/ layout, + /*.mDialogLayout =*/ dialogLayout, + }); // check if the dialog is closed if (closed) @@ -319,7 +303,7 @@ namespace MysticQt bool DialogStack::Remove(QWidget* widget) { - const uint32 numDialogs = mDialogs.GetLength(); + const uint32 numDialogs = mDialogs.size(); for (uint32 i = 0; i < numDialogs; ++i) { QLayout* layout = mDialogs[i].mFrame->layout(); @@ -333,7 +317,7 @@ namespace MysticQt // TODO : shift all dialogs needed as explained on the previous comment mDialogs[i].mDialogWidget->hide(); mDialogs[i].mDialogWidget->deleteLater(); - mDialogs.Remove(i); + mDialogs.erase(AZStd::next(begin(mDialogs), i)); // update the scroll bars UpdateScrollBars(); @@ -367,7 +351,7 @@ namespace MysticQt // find the dialog that goes with the given button uint32 DialogStack::FindDialog(QPushButton* pushButton) { - const uint32 numDialogs = mDialogs.GetLength(); + const uint32 numDialogs = mDialogs.size(); for (uint32 i = 0; i < numDialogs; ++i) { if (mDialogs[i].mButton == pushButton) @@ -401,20 +385,20 @@ namespace MysticQt button->setIcon(GetMysticQt()->FindIcon("Images/Icons/ArrowDownGray.png")); // more space used by the splitter when the dialog is open - if (dialogIndex < (mDialogs.GetLength() - 1)) + if (dialogIndex < (mDialogs.size() - 1)) { mDialogs[dialogIndex].mSplitter->handle(1)->setFixedHeight(4); mDialogs[dialogIndex].mSplitter->setStyleSheet("QSplitter::handle{ height: 4px; background: transparent; }"); } // enable the splitter - if (dialogIndex < (mDialogs.GetLength() - 1)) + if (dialogIndex < (mDialogs.size() - 1)) { mDialogs[dialogIndex].mSplitter->handle(1)->setEnabled(true); } // maximize the size if it's needed - if (mDialogs.GetLength() > 1) + if (mDialogs.size() > 1) { if (mDialogs[dialogIndex].mMaximizeSize) { @@ -440,7 +424,7 @@ namespace MysticQt } // special case if it's not the last dialog - if (dialogIndex < (mDialogs.GetLength() - 1)) + if (dialogIndex < (mDialogs.size() - 1)) { // if the next dialog is closed, it's needed to expand to the max too if (mDialogs[dialogIndex + 1].mFrame->isHidden()) @@ -489,27 +473,27 @@ namespace MysticQt button->setIcon(GetMysticQt()->FindIcon("Images/Icons/ArrowRightGray.png")); // less space used by the splitter when the dialog is closed - if (dialogIndex < (mDialogs.GetLength() - 1)) + if (dialogIndex < (mDialogs.size() - 1)) { mDialogs[dialogIndex].mSplitter->handle(1)->setFixedHeight(1); mDialogs[dialogIndex].mSplitter->setStyleSheet("QSplitter::handle{ height: 1px; background: transparent; }"); } // disable the splitter - if (dialogIndex < (mDialogs.GetLength() - 1)) + if (dialogIndex < (mDialogs.size() - 1)) { mDialogs[dialogIndex].mSplitter->handle(1)->setDisabled(true); } // set the first splitter to the min if needed - if (dialogIndex < (mDialogs.GetLength() - 1)) + if (dialogIndex < (mDialogs.size() - 1)) { static_cast(mDialogs[dialogIndex].mSplitter)->MoveFirstSplitterToMin(); } // maximize the first needed to avoid empty space bool findPreviousMaximizedDialogNeeded = true; - const uint32 numDialogs = mDialogs.GetLength(); + const uint32 numDialogs = mDialogs.size(); for (uint32 i = dialogIndex + 1; i < numDialogs; ++i) { if (mDialogs[i].mMaximizeSize && mDialogs[i].mFrame->isHidden() == false) @@ -636,7 +620,7 @@ namespace MysticQt QScrollArea::resizeEvent(event); // maximize the first dialog needed - const uint32 numDialogs = mDialogs.GetLength(); + const uint32 numDialogs = mDialogs.size(); const int32 lastDialogIndex = static_cast(numDialogs) - 1; for (int32 i = lastDialogIndex; i >= 0; --i) { @@ -655,7 +639,7 @@ namespace MysticQt // replace an internal widget void DialogStack::ReplaceWidget(QWidget* oldWidget, QWidget* newWidget) { - for (uint32 i = 0; i < mDialogs.GetLength(); ++i) + for (uint32 i = 0; i < mDialogs.size(); ++i) { // go next if the widget is not the same if (mDialogs[i].mWidget != oldWidget) @@ -693,7 +677,7 @@ namespace MysticQt mDialogs[i].mDialogWidget->setFixedHeight(dialogHeight); // set the first splitter to the min if needed - if (i < (mDialogs.GetLength() - 1)) + if (i < (mDialogs.size() - 1)) { static_cast(mDialogs[i].mSplitter)->MoveFirstSplitterToMin(); } diff --git a/Gems/EMotionFX/Code/MysticQt/Source/DialogStack.h b/Gems/EMotionFX/Code/MysticQt/Source/DialogStack.h index ddd0796a6d..d5850a8cbf 100644 --- a/Gems/EMotionFX/Code/MysticQt/Source/DialogStack.h +++ b/Gems/EMotionFX/Code/MysticQt/Source/DialogStack.h @@ -11,10 +11,11 @@ // #if !defined(Q_MOC_RUN) +#include #include "MysticQtConfig.h" #include #include -#include +#include #endif // forward declarations @@ -36,7 +37,6 @@ namespace MysticQt : public QScrollArea { Q_OBJECT - MCORE_MEMORYOBJECTCATEGORY(DialogStack, MCore::MCORE_DEFAULT_ALIGNMENT, MEMCATEGORY_MYSTICQT); public: DialogStack(QWidget* parent = nullptr); @@ -61,21 +61,18 @@ namespace MysticQt private: struct Dialog { - MCORE_MEMORYOBJECTCATEGORY(DialogStack::Dialog, MCore::MCORE_DEFAULT_ALIGNMENT, MEMCATEGORY_MYSTICQT); - Dialog(); - ~Dialog(); - QPushButton* mButton; - QWidget* mFrame; - QWidget* mWidget; - QWidget* mDialogWidget; - QSplitter* mSplitter; - bool mClosable; - bool mMaximizeSize; - bool mStretchWhenMaximize; - int mMinimumHeightBeforeClose; - int mMaximumHeightBeforeClose; - QLayout* mLayout; - QLayout* mDialogLayout; + QPushButton* mButton = nullptr; + QWidget* mFrame = nullptr; + QWidget* mWidget = nullptr; + AZStd::unique_ptr mDialogWidget = nullptr; + QSplitter* mSplitter = nullptr; + bool mClosable = true; + bool mMaximizeSize = false; + bool mStretchWhenMaximize = false; + int mMinimumHeightBeforeClose = 0; + int mMaximumHeightBeforeClose = 0; + QLayout* mLayout = nullptr; + QLayout* mDialogLayout = nullptr; }; private: @@ -86,7 +83,7 @@ namespace MysticQt private: QSplitter* mRootSplitter; - MCore::Array mDialogs; + AZStd::vector mDialogs; int32 mPrevMouseX; int32 mPrevMouseY; }; diff --git a/Gems/EMotionFX/Code/MysticQt/Source/MysticQtManager.cpp b/Gems/EMotionFX/Code/MysticQt/Source/MysticQtManager.cpp index 4020fd66ff..016664e017 100644 --- a/Gems/EMotionFX/Code/MysticQt/Source/MysticQtManager.cpp +++ b/Gems/EMotionFX/Code/MysticQt/Source/MysticQtManager.cpp @@ -30,12 +30,11 @@ namespace MysticQt MysticQtManager::~MysticQtManager() { // get the number of icons and destroy them - const uint32 numIcons = mIcons.GetLength(); - for (uint32 i = 0; i < numIcons; ++i) + for (IconData* mIcon : mIcons) { - delete mIcons[i]; + delete mIcon; } - mIcons.Clear(); + mIcons.clear(); } @@ -58,18 +57,17 @@ namespace MysticQt const QIcon& MysticQtManager::FindIcon(const char* filename) { // get the number of icons and iterate through them - const uint32 numIcons = mIcons.GetLength(); - for (uint32 i = 0; i < numIcons; ++i) + for (IconData* mIcon : mIcons) { - if (AzFramework::StringFunc::Equal(mIcons[i]->mFileName.c_str(), filename, false /* no case */)) + if (AzFramework::StringFunc::Equal(mIcon->mFileName.c_str(), filename, false /* no case */)) { - return *(mIcons[i]->mIcon); + return *(mIcon->mIcon); } } // we haven't found it IconData* iconData = new IconData(filename); - mIcons.Add(iconData); + mIcons.emplace_back(iconData); return *(iconData->mIcon); } diff --git a/Gems/EMotionFX/Code/MysticQt/Source/MysticQtManager.h b/Gems/EMotionFX/Code/MysticQt/Source/MysticQtManager.h index 8f7dad06bf..e0be07796e 100644 --- a/Gems/EMotionFX/Code/MysticQt/Source/MysticQtManager.h +++ b/Gems/EMotionFX/Code/MysticQt/Source/MysticQtManager.h @@ -12,7 +12,7 @@ // include required files #if !defined(Q_MOC_RUN) #include -#include +#include #include "MysticQtConfig.h" #include #endif @@ -74,7 +74,7 @@ namespace MysticQt }; QWidget* mMainWindow; - MCore::Array mIcons; + AZStd::vector mIcons; AZStd::string mAppDir; AZStd::string mDataDir; diff --git a/Gems/EMotionFX/Code/Platform/Windows/platform_windows.cmake b/Gems/EMotionFX/Code/Platform/Windows/platform_windows.cmake index 7a325ca97e..98a5170e23 100644 --- a/Gems/EMotionFX/Code/Platform/Windows/platform_windows.cmake +++ b/Gems/EMotionFX/Code/Platform/Windows/platform_windows.cmake @@ -5,3 +5,7 @@ # SPDX-License-Identifier: Apache-2.0 OR MIT # # + +if (PAL_TRAIT_COMPILER_ID STREQUAL "MSVC") + set(LY_COMPILE_OPTIONS PUBLIC /wd4267) +endif() diff --git a/Gems/EMotionFX/Code/Source/Editor/ActorJointBrowseEdit.cpp b/Gems/EMotionFX/Code/Source/Editor/ActorJointBrowseEdit.cpp index fb359eb671..a5d7a67f51 100644 --- a/Gems/EMotionFX/Code/Source/Editor/ActorJointBrowseEdit.cpp +++ b/Gems/EMotionFX/Code/Source/Editor/ActorJointBrowseEdit.cpp @@ -64,7 +64,6 @@ namespace EMStudio m_previouslySelectedJoints = m_selectedJoints; m_jointSelectionWindow = new NodeSelectionWindow(this, m_singleJointSelection); - connect(m_jointSelectionWindow->GetNodeHierarchyWidget(), qOverload>(&NodeHierarchyWidget::OnSelectionDone), this, &ActorJointBrowseEdit::OnSelectionDoneMCoreArray); connect(m_jointSelectionWindow, &NodeSelectionWindow::rejected, this, &ActorJointBrowseEdit::OnSelectionRejected); connect(m_jointSelectionWindow->GetNodeHierarchyWidget()->GetTreeWidget(), &QTreeWidget::itemSelectionChanged, this, &ActorJointBrowseEdit::OnSelectionChanged); @@ -118,12 +117,6 @@ namespace EMStudio emit SelectionDone(selectedJoints); } - void ActorJointBrowseEdit::OnSelectionDoneMCoreArray(const MCore::Array& selectedJoints) - { - AZStd::vector convertedSelection = FromMCoreArray(selectedJoints); - OnSelectionDone(convertedSelection); - } - void ActorJointBrowseEdit::OnSelectionChanged() { if (m_jointSelectionWindow) @@ -175,15 +168,4 @@ namespace EMStudio return nullptr; } - AZStd::vector ActorJointBrowseEdit::FromMCoreArray(const MCore::Array& in) const - { - const AZ::u32 numItems = in.GetLength(); - AZStd::vector result(static_cast(numItems)); - for (AZ::u32 i = 0; i < numItems; ++i) - { - result[static_cast(i)] = in[i]; - } - - return result; - } } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/Source/Editor/ActorJointBrowseEdit.h b/Gems/EMotionFX/Code/Source/Editor/ActorJointBrowseEdit.h index 770c000b1b..adae07dfc2 100644 --- a/Gems/EMotionFX/Code/Source/Editor/ActorJointBrowseEdit.h +++ b/Gems/EMotionFX/Code/Source/Editor/ActorJointBrowseEdit.h @@ -51,7 +51,6 @@ namespace EMStudio private slots: void OnBrowseButtonClicked(); void OnSelectionDone(const AZStd::vector& selectedJoints); - void OnSelectionDoneMCoreArray(const MCore::Array& selectedJoints); void OnSelectionChanged(); void OnSelectionRejected(); void OnTextEdited(const QString& text); @@ -59,8 +58,6 @@ namespace EMStudio private: void UpdatePlaceholderText(); - AZStd::vector FromMCoreArray(const MCore::Array& in) const; - AZStd::vector m_previouslySelectedJoints; /// Selected joints before selection window opened. AZStd::vector m_selectedJoints; NodeSelectionWindow* m_jointSelectionWindow = nullptr; diff --git a/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/ActorGoalNodeHandler.cpp b/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/ActorGoalNodeHandler.cpp index a05fbc9fa3..8cbee5924b 100644 --- a/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/ActorGoalNodeHandler.cpp +++ b/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/ActorGoalNodeHandler.cpp @@ -103,13 +103,13 @@ namespace EMotionFX } - MCore::Array actorInstanceIDs; + AZStd::vector actorInstanceIDs; // Add the current actor instance and all the ones it is attached to EMotionFX::ActorInstance* currentInstance = actorInstance; while (currentInstance) { - actorInstanceIDs.Add(currentInstance->GetID()); + actorInstanceIDs.emplace_back(currentInstance->GetID()); EMotionFX::Attachment* attachment = currentInstance->GetSelfAttachment(); if (attachment) { @@ -133,10 +133,10 @@ namespace EMotionFX AZStd::string selectedNodeName = newSelection[0].GetNodeName(); AZ::u32 selectedActorInstanceId = newSelection[0].mActorInstanceID; - uint32 parentDepth = actorInstanceIDs.Find(selectedActorInstanceId); - AZ_Assert(parentDepth != MCORE_INVALIDINDEX32, "Cannot get parent depth. The selected actor instance was not shown in the selection window."); + const auto parentDepth = AZStd::find(begin(actorInstanceIDs), end(actorInstanceIDs), selectedActorInstanceId); + AZ_Assert(parentDepth != end(actorInstanceIDs), "Cannot get parent depth. The selected actor instance was not shown in the selection window."); - m_goalNode = AZStd::make_pair(selectedNodeName, parentDepth); + m_goalNode = {AZStd::move(selectedNodeName), static_cast(AZStd::distance(begin(actorInstanceIDs), parentDepth))}; UpdateInterface(); emit SelectionChanged(); diff --git a/Gems/EMotionFX/Code/Source/Editor/SkeletonModel.cpp b/Gems/EMotionFX/Code/Source/Editor/SkeletonModel.cpp index d71e0e1acf..5a4f14921d 100644 --- a/Gems/EMotionFX/Code/Source/Editor/SkeletonModel.cpp +++ b/Gems/EMotionFX/Code/Source/Editor/SkeletonModel.cpp @@ -620,7 +620,7 @@ namespace EMotionFX const AZ::u32 numNodes = skeleton->GetNumNodes(); m_nodeInfos.resize(numNodes); - AZStd::vector > boneListPerLodLevel; + AZStd::vector > boneListPerLodLevel; boneListPerLodLevel.resize(numLodLevels); for (AZ::u32 lodLevel = 0; lodLevel < numLodLevels; ++lodLevel) { @@ -635,7 +635,7 @@ namespace EMotionFX nodeInfo.m_isBone = false; for (AZ::u32 lodLevel = 0; lodLevel < numLodLevels; ++lodLevel) { - if (boneListPerLodLevel[lodLevel].Find(nodeIndex) != MCORE_INVALIDINDEX32) + if (AZStd::find(begin(boneListPerLodLevel[lodLevel]), end(boneListPerLodLevel[lodLevel]), nodeIndex) != end(boneListPerLodLevel[lodLevel])) { nodeInfo.m_isBone = true; break; diff --git a/Gems/EMotionFX/Code/Tests/AnimGraphParameterCommandsTests.cpp b/Gems/EMotionFX/Code/Tests/AnimGraphParameterCommandsTests.cpp index 9dd6e61b3c..2f5a661850 100644 --- a/Gems/EMotionFX/Code/Tests/AnimGraphParameterCommandsTests.cpp +++ b/Gems/EMotionFX/Code/Tests/AnimGraphParameterCommandsTests.cpp @@ -62,7 +62,6 @@ namespace AnimGraphParameterCommandsTests using ::MCore::GetStringIdPool; using ::MCore::ReflectionSerializer; using ::MCore::LogWarning; - using ::MCore::Array; } // namespace MCore namespace EMotionFX diff --git a/Gems/EMotionFX/Code/Tests/BoolLogicNodeTests.cpp b/Gems/EMotionFX/Code/Tests/BoolLogicNodeTests.cpp index b64c2a212f..9d2e1a11c6 100644 --- a/Gems/EMotionFX/Code/Tests/BoolLogicNodeTests.cpp +++ b/Gems/EMotionFX/Code/Tests/BoolLogicNodeTests.cpp @@ -22,7 +22,7 @@ #include #include #include -#include +#include namespace EMotionFX { diff --git a/Gems/EMotionFX/Code/Tests/Mocks/AnimGraph.h b/Gems/EMotionFX/Code/Tests/Mocks/AnimGraph.h index d3225759a1..90da8d5890 100644 --- a/Gems/EMotionFX/Code/Tests/Mocks/AnimGraph.h +++ b/Gems/EMotionFX/Code/Tests/Mocks/AnimGraph.h @@ -24,7 +24,7 @@ namespace EMotionFX MOCK_CONST_METHOD1(RecursiveFindNodeById, AnimGraphNode*(AnimGraphNodeId)); MOCK_CONST_METHOD1(RecursiveFindTransitionById, AnimGraphStateTransition*(AnimGraphConnectionId)); MOCK_CONST_METHOD2(RecursiveCollectNodesOfType, void(const AZ::TypeId& nodeType, AZStd::vector* outNodes)); - MOCK_CONST_METHOD2(RecursiveCollectTransitionConditionsOfType, void(const AZ::TypeId& conditionType, MCore::Array* outConditions)); + MOCK_CONST_METHOD2(RecursiveCollectTransitionConditionsOfType, void(const AZ::TypeId& conditionType, AZStd::vector* outConditions)); MOCK_METHOD2(RecursiveCollectObjectsOfType, void(const AZ::TypeId& objectType, AZStd::vector& outObjects)); MOCK_METHOD2(RecursiveCollectObjectsAffectedBy, void(AnimGraph* animGraph, AZStd::vector& outObjects)); //uint32 RecursiveCalcNumNodes() const; diff --git a/Gems/EMotionFX/Code/Tests/Mocks/AnimGraphInstance.h b/Gems/EMotionFX/Code/Tests/Mocks/AnimGraphInstance.h index 705bef9602..711392f6cf 100644 --- a/Gems/EMotionFX/Code/Tests/Mocks/AnimGraphInstance.h +++ b/Gems/EMotionFX/Code/Tests/Mocks/AnimGraphInstance.h @@ -99,7 +99,7 @@ namespace EMotionFX //void OnStateEnd(AnimGraphNode* state); //void OnStartTransition(AnimGraphStateTransition* transition); //void OnEndTransition(AnimGraphStateTransition* transition); - //void CollectActiveAnimGraphNodes(MCore::Array* outNodes, const AZ::TypeId& nodeType = AZ::TypeId::CreateNull()); + //void CollectActiveAnimGraphNodes(AZStd::vector* outNodes, const AZ::TypeId& nodeType = AZ::TypeId::CreateNull()); //void CollectActiveNetTimeSyncNodes(AZStd::vector* outNodes); //uint32 GetObjectFlags(uint32 objectIndex) const; //void SetObjectFlags(uint32 objectIndex, uint32 flags); diff --git a/Gems/EMotionFX/Code/Tests/Mocks/Node.h b/Gems/EMotionFX/Code/Tests/Mocks/Node.h index 712eb257d5..9479883487 100644 --- a/Gems/EMotionFX/Code/Tests/Mocks/Node.h +++ b/Gems/EMotionFX/Code/Tests/Mocks/Node.h @@ -28,7 +28,7 @@ namespace EMotionFX MOCK_METHOD1(SetParentIndex, void(uint32 parentNodeIndex)); MOCK_CONST_METHOD0(GetParentIndex, uint32()); MOCK_CONST_METHOD0(GetParentNode, Node*()); - MOCK_CONST_METHOD2(RecursiveCollectParents, void(MCore::Array& parents, bool clearParentsArray)); + MOCK_CONST_METHOD2(RecursiveCollectParents, void(AZStd::vector& parents, bool clearParentsArray)); MOCK_METHOD1(SetName, void(const char* name)); MOCK_CONST_METHOD0(GetName, const char*()); MOCK_CONST_METHOD0(GetNameString, const AZStd::string&()); diff --git a/Gems/EMotionFX/Code/Tests/SkeletalLODTests.cpp b/Gems/EMotionFX/Code/Tests/SkeletalLODTests.cpp index 1af95b0a6a..28f139fe39 100644 --- a/Gems/EMotionFX/Code/Tests/SkeletalLODTests.cpp +++ b/Gems/EMotionFX/Code/Tests/SkeletalLODTests.cpp @@ -46,8 +46,8 @@ namespace EMotionFX const Actor* actor = actorInstance->GetActor(); const Skeleton* skeleton = actor->GetSkeleton(); - const MCore::Array& enabledJoints = actorInstance->GetEnabledNodes(); - const AZ::u32 numEnabledJoints = enabledJoints.GetLength(); + const AZStd::vector& enabledJoints = actorInstance->GetEnabledNodes(); + const AZ::u32 numEnabledJoints = enabledJoints.size(); EXPECT_EQ(actorInstance->GetNumEnabledNodes(), actor->GetNumNodes() - static_cast(disabledJointNames.size())) << "The enabled joints on the actor instance are not in sync with the enabledJoints."; diff --git a/Gems/EMotionFX/Code/Tests/UI/LODSkinnedMeshTests.cpp b/Gems/EMotionFX/Code/Tests/UI/LODSkinnedMeshTests.cpp index 9a11d1bd4b..65bb056654 100644 --- a/Gems/EMotionFX/Code/Tests/UI/LODSkinnedMeshTests.cpp +++ b/Gems/EMotionFX/Code/Tests/UI/LODSkinnedMeshTests.cpp @@ -90,7 +90,6 @@ namespace EMotionFX Mesh* lodMesh = actor->GetMesh(0, 0); StandardMaterial* dummyMat = StandardMaterial::Create("Dummy Material"); actor->AddMaterial(0, dummyMat); // owns the material - actor->SetNumLODLevels(numLODs); for (int i = 1; i < numLODs; ++i) { diff --git a/Gems/EMotionFX/Code/Tests/Vector2ToVector3CompatibilityTests.cpp b/Gems/EMotionFX/Code/Tests/Vector2ToVector3CompatibilityTests.cpp index 201fb856a4..26702af550 100644 --- a/Gems/EMotionFX/Code/Tests/Vector2ToVector3CompatibilityTests.cpp +++ b/Gems/EMotionFX/Code/Tests/Vector2ToVector3CompatibilityTests.cpp @@ -25,7 +25,7 @@ #include #include #include -#include +#include namespace EMotionFX { From 0a56c175193a70b9fecac3739a1cb2af71cf7583 Mon Sep 17 00:00:00 2001 From: Chris Burel Date: Mon, 24 May 2021 12:03:40 -0700 Subject: [PATCH 181/803] Remove unused MCore::AbstractData class Signed-off-by: Chris Burel --- .../Code/MCore/Source/AbstractData.h | 107 ------------------ Gems/EMotionFX/Code/MCore/mcore_files.cmake | 1 - 2 files changed, 108 deletions(-) delete mode 100644 Gems/EMotionFX/Code/MCore/Source/AbstractData.h diff --git a/Gems/EMotionFX/Code/MCore/Source/AbstractData.h b/Gems/EMotionFX/Code/MCore/Source/AbstractData.h deleted file mode 100644 index c11173f99a..0000000000 --- a/Gems/EMotionFX/Code/MCore/Source/AbstractData.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -#pragma once - -// include required headers -#include "StandardHeaders.h" - - -namespace MCore -{ - /** - * The abstract data class, which represents a continuous block of memory. - * Anything can be stored inside this piece of memory. - */ - class MCORE_API AbstractData - { - public: - AbstractData() - : mData(nullptr) - , mNumBytes(0) - , mMaxNumBytes(0) { } - AbstractData(uint32 numBytes) - : mData(nullptr) - , mNumBytes(0) - , mMaxNumBytes(0) { Resize(numBytes); } - AbstractData(void* data, uint32 numBytes) - : mData(nullptr) - , mNumBytes(0) - , mMaxNumBytes(0) { InitFrom(data, numBytes); } - AbstractData(const AbstractData& other) - : mData(nullptr) - , mNumBytes(0) - , mMaxNumBytes(0) { InitFrom(other.GetPointer(), other.GetNumBytes()); } - ~AbstractData() { Release(); } - - void Release() { MCore::Free(mData); mData = nullptr; mNumBytes = 0; mMaxNumBytes = 0; } - void Clear() { mNumBytes = 0; } - void Resize(uint32 numBytes) - { - // if we need to empty it - if (numBytes == 0) - { - mNumBytes = 0; - return; - } - - //Release(); - if (mMaxNumBytes < numBytes) - { - mData = MCore::Realloc(mData, numBytes, MCORE_MEMCATEGORY_ABSTRACTDATA); - mNumBytes = numBytes; - mMaxNumBytes = numBytes; - } - else - { - mNumBytes = numBytes; - } - } - - void Reserve(uint32 numBytes) - { - if (mMaxNumBytes < numBytes) - { - mData = MCore::Realloc(mData, numBytes, MCORE_MEMCATEGORY_ABSTRACTDATA); - mMaxNumBytes = numBytes; - } - } - - void Shrink() - { - if (mMaxNumBytes > mNumBytes) - { - mData = MCore::Realloc(mData, mNumBytes, MCORE_MEMCATEGORY_ABSTRACTDATA); - mMaxNumBytes = mNumBytes; - } - } - - MCORE_INLINE void* GetPointer() const { return mData; } - MCORE_INLINE void* GetPointer() { return mData; } - MCORE_INLINE void CopyDataFrom(const void* data) { MCORE_ASSERT(mData); MCore::MemCopy(mData, data, mNumBytes); } - MCORE_INLINE void InitFrom(const void* data, uint32 numBytes) - { - Resize(numBytes); - if (numBytes == 0) - { - return; - } - MCORE_ASSERT(mData); - MCore::MemCopy(mData, data, mNumBytes); - } - MCORE_INLINE uint32 GetNumBytes() const { return mNumBytes; } - MCORE_INLINE uint32 GetMaxNumBytes() const { return mMaxNumBytes; } - - MCORE_INLINE const AbstractData& operator=(const AbstractData& other) { InitFrom(other.GetPointer(), other.GetNumBytes()); return *this; } - - private: - void* mData; - uint32 mNumBytes; - uint32 mMaxNumBytes; - }; -} // namespace MCore diff --git a/Gems/EMotionFX/Code/MCore/mcore_files.cmake b/Gems/EMotionFX/Code/MCore/mcore_files.cmake index 65b0cf6ca6..6352bac4ba 100644 --- a/Gems/EMotionFX/Code/MCore/mcore_files.cmake +++ b/Gems/EMotionFX/Code/MCore/mcore_files.cmake @@ -8,7 +8,6 @@ set(FILES Source/AABB.h - Source/AbstractData.h Source/Algorithms.cpp Source/Algorithms.h Source/Algorithms.inl From c3ff3f342d594df853c10c33efc2a557a40fef78 Mon Sep 17 00:00:00 2001 From: Chris Burel Date: Mon, 24 May 2021 12:03:41 -0700 Subject: [PATCH 182/803] Update StringIdPool to use AZ::u32 instead of uint32 Signed-off-by: Chris Burel --- .../Code/MCore/Source/StringIdPool.cpp | 22 +++++-------------- .../Code/MCore/Source/StringIdPool.h | 21 +++++------------- 2 files changed, 12 insertions(+), 31 deletions(-) diff --git a/Gems/EMotionFX/Code/MCore/Source/StringIdPool.cpp b/Gems/EMotionFX/Code/MCore/Source/StringIdPool.cpp index 7c934084ce..279a7aec1e 100644 --- a/Gems/EMotionFX/Code/MCore/Source/StringIdPool.cpp +++ b/Gems/EMotionFX/Code/MCore/Source/StringIdPool.cpp @@ -29,10 +29,9 @@ namespace MCore { Lock(); - const size_t numStrings = mStrings.size(); - for (size_t i = 0; i < numStrings; ++i) + for (AZStd::basic_string*& mString : mStrings) { - delete mStrings[i]; + delete mString; } mStrings.clear(); @@ -69,24 +68,15 @@ namespace MCore } - const AZStd::string& StringIdPool::GetName(uint32 id) + const AZStd::string& StringIdPool::GetName(AZ::u32 id) { Lock(); - MCORE_ASSERT(id != MCORE_INVALIDINDEX32); + MCORE_ASSERT(id != InvalidIndex32); const AZStd::string* stringAddress = mStrings[id]; Unlock(); return *stringAddress; } - const AZStd::string& StringIdPool::GetStringById(AZ::u32 id) - { - Lock(); - MCORE_ASSERT(id != MCORE_INVALIDINDEX32); - AZStd::string* stringAddress = mStrings[id]; - Unlock(); - return *stringAddress; - } - void StringIdPool::Reserve(size_t numStrings) { @@ -132,8 +122,8 @@ namespace MCore size_t Save(const void* classPtr, AZ::IO::GenericStream& stream, bool /*isDataBigEndian = false*/) { // Look up the string to save - const uint32 index = static_cast(classPtr)->m_index; - if (index == MCORE_INVALIDINDEX32) + const AZ::u32 index = static_cast(classPtr)->m_index; + if (index == InvalidIndex32) { return 0; } diff --git a/Gems/EMotionFX/Code/MCore/Source/StringIdPool.h b/Gems/EMotionFX/Code/MCore/Source/StringIdPool.h index 30ea434331..9f58adf028 100644 --- a/Gems/EMotionFX/Code/MCore/Source/StringIdPool.h +++ b/Gems/EMotionFX/Code/MCore/Source/StringIdPool.h @@ -50,14 +50,7 @@ namespace MCore * @param id The unique id to search for the name. * @return The name of the given object. */ - const AZStd::string& GetName(uint32 id); - - /** - * Return the name of the given id. - * @param id The unique id to search for the name. - * @return The name of the given object. - */ - const AZStd::string& GetStringById(AZ::u32 id); + const AZStd::string& GetName(AZ::u32 id); /** * Reserve space for a given amount of strings. @@ -84,17 +77,15 @@ namespace MCore /** * The StringIdPoolIndex is a helper class to aid with serialization of * class members that store indexes into the StringIdPool. Members of this - * type will serialize to a string, and deserialize to a uint32, while + * type will serialize to a string, and deserialize to a AZ::u32, while * allowing the StringIdPool to deduplicate the strings. */ struct StringIdPoolIndex { - AZ::u32 m_index; + AZ::u32 m_index{}; - StringIdPoolIndex() : m_index(0) {} - StringIdPoolIndex(uint32 index) : m_index(index) {} - operator uint32() const { return m_index; } - bool operator==(uint32 rhs) const { return m_index == rhs; } + operator AZ::u32() const { return m_index; } + bool operator==(AZ::u32 rhs) const { return m_index == rhs; } static void Reflect(AZ::ReflectContext* context); }; @@ -104,4 +95,4 @@ namespace MCore namespace AZ { AZ_TYPE_INFO_SPECIALIZE(MCore::StringIdPoolIndex, "{C374F051-8323-49DB-A1BD-C6B6CF0333C0}") -} +} // namespace AZ From db622de75fedeb5d6f6227cf72333a5f54ffb956 Mon Sep 17 00:00:00 2001 From: Chris Burel Date: Mon, 24 May 2021 12:03:43 -0700 Subject: [PATCH 183/803] Convert MCore Algorithms to use size_t Signed-off-by: Chris Burel --- .../Code/MCore/Source/Algorithms.cpp | 93 ++----------------- Gems/EMotionFX/Code/MCore/Source/Algorithms.h | 17 +--- 2 files changed, 8 insertions(+), 102 deletions(-) diff --git a/Gems/EMotionFX/Code/MCore/Source/Algorithms.cpp b/Gems/EMotionFX/Code/MCore/Source/Algorithms.cpp index d1a4e6b30e..dd82385092 100644 --- a/Gems/EMotionFX/Code/MCore/Source/Algorithms.cpp +++ b/Gems/EMotionFX/Code/MCore/Source/Algorithms.cpp @@ -253,10 +253,10 @@ namespace MCore // check if a given point is inside a 2d convex/concave polygon // it does this by checking how many times a line intersects with the poly (how many times it goes inside and outside again) - bool PointInPoly(AZ::Vector2* verts, uint32 numVerts, const AZ::Vector2& point) + bool PointInPoly(AZ::Vector2* verts, size_t numVerts, const AZ::Vector2& point) { - uint32 c = 0; - for (uint32 i = 0, j = numVerts - 1; i < numVerts; j = i++) + bool c = false; + for (size_t i = 0, j = numVerts - 1; i < numVerts; j = i++) { if (((verts[i].GetY() > point.GetY()) != (verts[j].GetY() > point.GetY())) && (point.GetX() < (verts[j].GetX() - verts[i].GetX()) * (point.GetY() - verts[i].GetY()) / (verts[j].GetY() - verts[i].GetY()) + verts[i].GetX())) { @@ -264,7 +264,7 @@ namespace MCore } } - return (c > 0); + return c; } @@ -291,11 +291,11 @@ namespace MCore // check if the test point is inside the polygon - AZ::Vector2 ClosestPointToPoly(const AZ::Vector2* polyPoints, uint32 numPoints, const AZ::Vector2& testPoint) + AZ::Vector2 ClosestPointToPoly(const AZ::Vector2* polyPoints, size_t numPoints, const AZ::Vector2& testPoint) { AZ::Vector2 result; float closestDist = FLT_MAX; - for (uint32 i = 0; i < numPoints; ++i) + for (size_t i = 0; i < numPoints; ++i) { AZ::Vector2 edgePointA; AZ::Vector2 edgePointB; @@ -336,85 +336,4 @@ namespace MCore return result; } - - - // static CRC lookup table - /*static uint32 CRC32Table[256] = - { - 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, - 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, - 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, - 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, - 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, - 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, - 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, - 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, - 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, - 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, - 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, - 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, - 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, - 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, - 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, - 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, - - 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, - 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, - 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, - 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, - 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, - 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, - 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, - 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, - 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, - 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, - 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, - 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, - 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, - 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, - 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, - 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, - - 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, - 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, - 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, - 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, - 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, - 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, - 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, - 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, - 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, - 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, - 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, - 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, - 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, - 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, - 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, - 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, - - 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, - 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, - 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, - 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, - 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, - 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, - 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, - 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, - 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, - 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, - 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, - 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, - 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, - 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, - 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, - 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D, - }; - - - - // calculate the CRC32 - void CalcCRC32(uint8 byteValue, uint32& CRC) - { - CRC = ((CRC) >> 8) ^ MCore::CRC32Table[(byteValue) ^ ((CRC) & 0x000000FF)]; - }*/ } // namespace MCore diff --git a/Gems/EMotionFX/Code/MCore/Source/Algorithms.h b/Gems/EMotionFX/Code/MCore/Source/Algorithms.h index 2776614087..c67ad950de 100644 --- a/Gems/EMotionFX/Code/MCore/Source/Algorithms.h +++ b/Gems/EMotionFX/Code/MCore/Source/Algorithms.h @@ -58,24 +58,11 @@ namespace MCore AZ::Vector3 MCORE_API StereographicUnproject(const AZ::Vector2& uv); // - bool MCORE_API PointInPoly(AZ::Vector2* verts, uint32 numVerts, const AZ::Vector2& point); + bool MCORE_API PointInPoly(AZ::Vector2* verts, size_t numVerts, const AZ::Vector2& point); float MCORE_API DistanceToEdge(const AZ::Vector2& edgePointA, const AZ::Vector2& edgePointB, const AZ::Vector2& testPoint); - AZ::Vector2 MCORE_API ClosestPointToPoly(const AZ::Vector2* polyPoints, uint32 numPoints, const AZ::Vector2& testPoint); + AZ::Vector2 MCORE_API ClosestPointToPoly(const AZ::Vector2* polyPoints, size_t numPoints, const AZ::Vector2& testPoint); - /** - * Calculates the CRC value of a given byte. - * It inputs and modifies the current CRC value passed as parameter. - * @param byteValue The byte value to generate the CRC for. - * @param CRC The CRC value to modify. - * - * The calculation performed is: - *
-     * CRC = ((CRC) >> 8) ^ MCore::CRC32Table[(byteValue) ^ ((CRC) & 0x000000FF)];
-     * 
- */ - //void MCORE_API CalcCRC32(uint8 byteValue, uint32& CRC); - /** * Calculate the cube root, which basically is pow(x, 1/3). * This also allows negative and zero values. From a04a0965ccabbea7054b94a307a7126f4121f682 Mon Sep 17 00:00:00 2001 From: Chris Burel Date: Mon, 24 May 2021 12:03:44 -0700 Subject: [PATCH 184/803] Convert AlignedArray uint32->size_t Signed-off-by: Chris Burel --- .../Code/MCore/Source/AlignedArray.h | 122 +++++++++--------- 1 file changed, 61 insertions(+), 61 deletions(-) diff --git a/Gems/EMotionFX/Code/MCore/Source/AlignedArray.h b/Gems/EMotionFX/Code/MCore/Source/AlignedArray.h index 00663ffca9..ef1d157e03 100644 --- a/Gems/EMotionFX/Code/MCore/Source/AlignedArray.h +++ b/Gems/EMotionFX/Code/MCore/Source/AlignedArray.h @@ -19,7 +19,7 @@ namespace MCore /** * Dynamic array template, using aligned memory allocations. * This array template allows dynamic sizing. It also stores the memory category of the data. - * It can theoretically store 4294967296 items (maximum uint32 value). + * It can theoretically store 18446744073709551614 items (maximum size_t value - 1 for the invalid index). */ template class AlignedArray @@ -51,13 +51,13 @@ namespace MCore * @param num The number of elements in 'elems'. * @param memCategory The memory category the array is in. */ - MCORE_INLINE explicit AlignedArray(T* elems, uint32 num, uint16 memCategory = MCORE_MEMCATEGORY_ARRAY) + MCORE_INLINE explicit AlignedArray(T* elems, size_t num, uint16 memCategory = MCORE_MEMCATEGORY_ARRAY) : mLength(num) , mMaxLength(AllocSize(num)) , mMemCategory(memCategory) { mData = (T*)AlignedAllocate(mMaxLength * sizeof(T), alignment, mMemCategory, MEMORYBLOCK_ID, MCORE_FILE, MCORE_LINE); - for (uint32 i = 0; i < mLength; ++i) + for (size_t i = 0; i < mLength; ++i) { Construct(i, elems[i]); } @@ -68,7 +68,7 @@ namespace MCore * @param initSize The number of ellements to allocate space for. * @param memCategory The memory category the array is in. */ - MCORE_INLINE explicit AlignedArray(uint32 initSize, uint16 memCategory = MCORE_MEMCATEGORY_ARRAY) + MCORE_INLINE explicit AlignedArray(size_t initSize, uint16 memCategory = MCORE_MEMCATEGORY_ARRAY) : mData(nullptr) , mLength(initSize) , mMaxLength(initSize) @@ -77,7 +77,7 @@ namespace MCore if (mMaxLength > 0) { mData = (T*)AlignedAllocate(mMaxLength * sizeof(T), alignment, mMemCategory, MEMORYBLOCK_ID, MCORE_FILE, MCORE_LINE); - for (uint32 i = 0; i < mLength; ++i) + for (size_t i = 0; i < mLength; ++i) { Construct(i); } @@ -106,20 +106,20 @@ namespace MCore * Example:
*
          * AlignedArray< Object*, 16 > data;
-         * for (uint32 i=0; i<10; i++)
+         * for (size_t i=0; i<10; i++)
          *    data.Add( new Object() );
          * 
* Now when the array 'data' will be destructed, it will NOT free up the memory of the integers which you allocated by hand, using new. * In order to free up this memory, you can do this: *
-         * for (uint32 i=0; i
          */
         ~AlignedArray()
         {
-            for (uint32 i = 0; i < mLength; ++i)
+            for (size_t i = 0; i < mLength; ++i)
             {
                 Destruct(i);
             }
@@ -160,7 +160,7 @@ namespace MCore
          * @param pos The item/element number.
          * @result A reference to the element.
          */
-        MCORE_INLINE T& GetItem(uint32 pos)                                     { return mData[pos]; }
+        MCORE_INLINE T& GetItem(size_t pos)                                     { return mData[pos]; }
 
         /**
          * Get the first element.
@@ -185,7 +185,7 @@ namespace MCore
          * @param pos The element number.
          * @result A read-only reference to the given element.
          */
-        MCORE_INLINE const T& GetItem(uint32 pos) const                         { return mData[pos]; }
+        MCORE_INLINE const T& GetItem(size_t pos) const                         { return mData[pos]; }
 
         /**
          * Get a read-only reference to the first element.
@@ -210,13 +210,13 @@ namespace MCore
          * @param index The index to check.
          * @return True if the passed index is valid, false if not.
          */
-        MCORE_INLINE bool GetIsValidIndex(uint32 index) const                   { return (index < mLength); }
+        MCORE_INLINE bool GetIsValidIndex(size_t index) const                   { return (index < mLength); }
 
         /**
          * Get the number of elements in the array.
          * @result The number of elements in the array.
          */
-        MCORE_INLINE uint32 GetLength() const                                   { return mLength; }
+        MCORE_INLINE size_t GetLength() const                                   { return mLength; }
 
         /**
          * Get the maximum number of elements. This is the number of elements there currently is space for to store.
@@ -224,16 +224,16 @@ namespace MCore
          * This purely has to do with pre-allocating, to reduce the number of reallocs.
          * @result The maximum array length.
          */
-        MCORE_INLINE uint32 GetMaxLength() const                                { return mMaxLength; }
+        MCORE_INLINE size_t GetMaxLength() const                                { return mMaxLength; }
 
         /**
          * Calculates the memory usage used by this array.
          * @param includeMembers Include the class members in the calculation? (default=true).
          * @result The number of bytes allocated by this array.
          */
-        MCORE_INLINE uint32 CalcMemoryUsage(bool includeMembers = true) const
+        MCORE_INLINE size_t CalcMemoryUsage(bool includeMembers = true) const
         {
-            uint32 result = mMaxLength * sizeof(T);
+            size_t result = mMaxLength * sizeof(T);
             if (includeMembers)
             {
                 result += sizeof(AlignedArray);
@@ -246,7 +246,7 @@ namespace MCore
          * @param pos The element number.
          * @param value The value to store at that element number.
          */
-        MCORE_INLINE void SetElem(uint32 pos, const T& value)                   { mData[pos] = value; }
+        MCORE_INLINE void SetElem(size_t pos, const T& value)                   { mData[pos] = value; }
 
         /**
          * Add a given element to the back of the array.
@@ -266,9 +266,9 @@ namespace MCore
          */
         MCORE_INLINE void Add(const AlignedArray& a)
         {
-            uint32 l = mLength;
+            size_t l = mLength;
             Grow(mLength + a.mLength);
-            for (uint32 i = 0; i < a.GetLength(); ++i)
+            for (size_t i = 0; i < a.GetLength(); ++i)
             {
                 Construct(l + i, a[i]);
             }
@@ -291,7 +291,7 @@ namespace MCore
         {
             if (mLength > 0)
             {
-                Remove((uint32)0);
+                Remove(0);
             }
         }
 
@@ -310,20 +310,20 @@ namespace MCore
          * Insert an empty element (default constructed) at a given position in the array.
          * @param pos The position to create the empty element.
          */
-        MCORE_INLINE void Insert(uint32 pos)                                    { Grow(mLength + 1); MoveElements(pos + 1, pos, mLength - pos - 1); Construct(pos); }
+        MCORE_INLINE void Insert(size_t pos)                                    { Grow(mLength + 1); MoveElements(pos + 1, pos, mLength - pos - 1); Construct(pos); }
 
         /**
          * Insert a given element at a given position in the array.
          * @param pos The position to insert the empty element.
          * @param x The element to store at this position.
          */
-        MCORE_INLINE void Insert(uint32 pos, const T& x)                        { Grow(mLength + 1); MoveElements(pos + 1, pos, mLength - pos - 1); Construct(pos, x); }
+        MCORE_INLINE void Insert(size_t pos, const T& x)                        { Grow(mLength + 1); MoveElements(pos + 1, pos, mLength - pos - 1); Construct(pos, x); }
 
         /**
          * Remove an element at a given position.
          * @param pos The element number to remove.
          */
-        MCORE_INLINE void Remove(uint32 pos)
+        MCORE_INLINE void Remove(size_t pos)
         {
             Destruct(pos);
             if (mLength > 1)
@@ -338,9 +338,9 @@ namespace MCore
          * @param pos The start element, so to start removing from.
          * @param num The number of elements to remove from this position.
          */
-        MCORE_INLINE void Remove(uint32 pos, uint32 num)
+        MCORE_INLINE void Remove(size_t pos, size_t num)
         {
-            for (uint32 i = pos; i < pos + num; ++i)
+            for (size_t i = pos; i < pos + num; ++i)
             {
                 Destruct(i);
             }
@@ -355,8 +355,8 @@ namespace MCore
          */
         MCORE_INLINE bool RemoveByValue(const T& item)
         {
-            uint32 index = Find(item);
-            if (index == MCORE_INVALIDINDEX32)
+            size_t index = Find(item);
+            if (index == InvalidIndex)
             {
                 return false;
             }
@@ -372,7 +372,7 @@ namespace MCore
          * AB.DEFG [where . is empty, after we did the SwapRemove(2)]
* ABGDEF [this is the result. G has been moved to the empty position]. */ - MCORE_INLINE void SwapRemove(uint32 pos) + MCORE_INLINE void SwapRemove(size_t pos) { Destruct(pos); if (pos != mLength - 1) @@ -388,7 +388,7 @@ namespace MCore * @param pos1 The first element number. * @param pos2 The second element number. */ - MCORE_INLINE void Swap(uint32 pos1, uint32 pos2) + MCORE_INLINE void Swap(size_t pos1, size_t pos2) { if (pos1 != pos2) { @@ -403,7 +403,7 @@ namespace MCore */ MCORE_INLINE void Clear(bool clearMem = true) { - for (uint32 i = 0; i < mLength; ++i) + for (size_t i = 0; i < mLength; ++i) { Destruct(i); } @@ -418,15 +418,15 @@ namespace MCore * Make sure the array has enough space to store a given number of elements. * @param newLength The number of elements we want to make sure that will fit in the array. */ - MCORE_INLINE void AssureSize(uint32 newLength) + MCORE_INLINE void AssureSize(size_t newLength) { if (mLength >= newLength) { return; } - uint32 oldLen = mLength; + size_t oldLen = mLength; Grow(newLength); - for (uint32 i = oldLen; i < newLength; ++i) + for (size_t i = oldLen; i < newLength; ++i) { Construct(i); } @@ -436,7 +436,7 @@ namespace MCore * Make sure this array has enough allocated storage to grow to a given number of elements elements without having to realloc. * @param minLength The minimum length the array should have (actually the minimum maxLength, because this has no influence on what GetLength() will return). */ - MCORE_INLINE void Reserve(uint32 minLength) + MCORE_INLINE void Reserve(size_t minLength) { if (mMaxLength < minLength) { @@ -462,23 +462,23 @@ namespace MCore * @param x The element to check. * @result Returns true when the array contains the element, otherwise false is returned. */ - MCORE_INLINE bool Contains(const T& x) const { return (Find(x) != MCORE_INVALIDINDEX32); } + MCORE_INLINE bool Contains(const T& x) const { return (Find(x) != InvalidIndex); } /** * Find the position of a given element. * @param x The element to find. - * @result Returns the index in the array, ranging from [0 to GetLength()-1] when found, otherwise MCORE_INVALIDINDEX32 is returned. + * @result Returns the index in the array, ranging from [0 to GetLength()-1] when found, otherwise InvalidIndex is returned. */ - MCORE_INLINE uint32 Find(const T& x) const + MCORE_INLINE size_t Find(const T& x) const { - for (uint32 i = 0; i < mLength; ++i) + for (size_t i = 0; i < mLength; ++i) { if (mData[i] == x) { return i; } } - return MCORE_INVALIDINDEX32; + return InvalidIndex; } /** @@ -533,12 +533,12 @@ namespace MCore * The default parameters are set so that it will sort the compelete array with a default compare function (which uses the < and > operators). * The method will sort all elements between the given 'first' and 'last' element (first and last are also included in the sort). * @param first The first element to start sorting. - * @param last The last element to sort (when set to MCORE_INVALIDINDEX32, GetLength()-1 will be used). + * @param last The last element to sort (when set to InvalidIndex, GetLength()-1 will be used). * @param cmp The compare function. */ - MCORE_INLINE void Sort(uint32 first = 0, uint32 last = MCORE_INVALIDINDEX32, CmpFunc cmp = StdCmp) + MCORE_INLINE void Sort(size_t first = 0, size_t last = InvalidIndex, CmpFunc cmp = StdCmp) { - if (last == MCORE_INVALIDINDEX32) + if (last == InvalidIndex) { last = mLength - 1; } @@ -563,7 +563,7 @@ namespace MCore } // resize in a fast way that doesn't call constructors or destructors - void ResizeFast(uint32 newLength) + void ResizeFast(size_t newLength) { if (mLength == newLength) { @@ -583,7 +583,7 @@ namespace MCore * This does not mean an actual realloc will be made. This will only happen when the new length is bigger than the maxLength of the array. * @param newLength The new length the array should be. */ - void Resize(uint32 newLength) + void Resize(size_t newLength) { if (mLength == newLength) { @@ -594,9 +594,9 @@ namespace MCore if (newLength > mLength) { // growing array, construct empty elements at end of array - const uint32 oldLen = mLength; + const size_t oldLen = mLength; GrowExact(newLength); - for (uint32 i = oldLen; i < newLength; ++i) + for (size_t i = oldLen; i < newLength; ++i) { Construct(i); } @@ -604,7 +604,7 @@ namespace MCore else { // shrinking array, destruct elements at end of array - for (uint32 i = newLength; i < mLength; ++i) + for (size_t i = newLength; i < mLength; ++i) { Destruct(i); } @@ -620,7 +620,7 @@ namespace MCore * @param sourceIndex The source index, where the source elements start. * @param numElements The number of elements to move. */ - MCORE_INLINE void MoveElements(uint32 destIndex, uint32 sourceIndex, uint32 numElements) + MCORE_INLINE void MoveElements(size_t destIndex, size_t sourceIndex, size_t numElements) { if (numElements > 0) { @@ -635,7 +635,7 @@ namespace MCore { return false; } - for (uint32 i = 0; i < mLength; ++i) + for (size_t i = 0; i < mLength; ++i) { if (mData[i] != other.mData[i]) { @@ -651,7 +651,7 @@ namespace MCore Clear(false); mMemCategory = other.mMemCategory; Grow(other.mLength); - for (uint32 i = 0; i < mLength; ++i) + for (size_t i = 0; i < mLength; ++i) { Construct(i, other.mData[i]); } @@ -676,17 +676,17 @@ namespace MCore } AlignedArray& operator+=(const T& other) { Add(other); return *this; } AlignedArray& operator+=(const AlignedArray& other) { Add(other); return *this; } - MCORE_INLINE T& operator[](uint32 index) { MCORE_ASSERT(index < mLength); return mData[index]; } - MCORE_INLINE const T& operator[](uint32 index) const { MCORE_ASSERT(index < mLength); return mData[index]; } + MCORE_INLINE T& operator[](size_t index) { MCORE_ASSERT(index < mLength); return mData[index]; } + MCORE_INLINE const T& operator[](size_t index) const { MCORE_ASSERT(index < mLength); return mData[index]; } private: T* mData; /**< The element data. */ - uint32 mLength; /**< The number of used elements in the array. */ - uint32 mMaxLength; /**< The number of elements that we have allocated memory for. */ + size_t mLength; /**< The number of used elements in the array. */ + size_t mMaxLength; /**< The number of elements that we have allocated memory for. */ uint16 mMemCategory; /**< The memory category ID. */ // private functions - MCORE_INLINE void Grow(uint32 newLength) + MCORE_INLINE void Grow(size_t newLength) { mLength = newLength; if (mMaxLength >= newLength) @@ -695,7 +695,7 @@ namespace MCore } Realloc(AllocSize(newLength)); } - MCORE_INLINE void GrowExact(uint32 newLength) + MCORE_INLINE void GrowExact(size_t newLength) { mLength = newLength; if (mMaxLength < newLength) @@ -703,9 +703,9 @@ namespace MCore Realloc(newLength); } } - MCORE_INLINE uint32 AllocSize(uint32 num) { return 1 + num /*+num/8*/; } - MCORE_INLINE void Alloc(uint32 num) { mData = (T*)AlignedAllocate(num * sizeof(T), alignment, mMemCategory, MEMORYBLOCK_ID, MCORE_FILE, MCORE_LINE); } - MCORE_INLINE void Realloc(uint32 newSize) + MCORE_INLINE size_t AllocSize(size_t num) { return 1 + num /*+num/8*/; } + MCORE_INLINE void Alloc(size_t num) { mData = (T*)AlignedAllocate(num * sizeof(T), alignment, mMemCategory, MEMORYBLOCK_ID, MCORE_FILE, MCORE_LINE); } + MCORE_INLINE void Realloc(size_t newSize) { if (newSize == 0) { @@ -733,9 +733,9 @@ namespace MCore mData = nullptr; } } - MCORE_INLINE void Construct(uint32 index, const T& original) { ::new(mData + index)T(original); } // copy-construct an element at which is a copy of - MCORE_INLINE void Construct(uint32 index) { ::new(mData + index)T; } // construct an element at place - MCORE_INLINE void Destruct(uint32 index) + MCORE_INLINE void Construct(size_t index, const T& original) { ::new(mData + index)T(original); } // copy-construct an element at which is a copy of + MCORE_INLINE void Construct(size_t index) { ::new(mData + index)T; } // construct an element at place + MCORE_INLINE void Destruct(size_t index) { #if (MCORE_COMPILER == MCORE_COMPILER_MSVC) MCORE_UNUSED(index); // work around an MSVC compiler bug, where it triggers a warning that parameter 'index' is unused From b8695742d976f2294e650c8e794f4643c934194e Mon Sep 17 00:00:00 2001 From: Chris Burel Date: Mon, 24 May 2021 12:03:46 -0700 Subject: [PATCH 185/803] Convert MCore Attribute classes uint32 -> size_t Signed-off-by: Chris Burel --- .../Source/AnimGraphAttributeTypes.h | 8 ++--- .../EMotionFX/Code/MCore/Source/Attribute.cpp | 4 +-- Gems/EMotionFX/Code/MCore/Source/Attribute.h | 12 ++++---- .../Code/MCore/Source/AttributeBool.h | 6 ++-- .../Code/MCore/Source/AttributeColor.h | 6 ++-- .../Code/MCore/Source/AttributeFactory.cpp | 29 ++++++++----------- .../Code/MCore/Source/AttributeFactory.h | 6 ++-- .../Code/MCore/Source/AttributeFloat.h | 6 ++-- .../Code/MCore/Source/AttributeInt32.h | 6 ++-- .../Code/MCore/Source/AttributePointer.h | 4 +-- .../Code/MCore/Source/AttributeQuaternion.h | 6 ++-- .../Code/MCore/Source/AttributeString.h | 4 +-- .../Code/MCore/Source/AttributeVector2.h | 6 ++-- .../Code/MCore/Source/AttributeVector3.h | 6 ++-- .../Code/MCore/Source/AttributeVector4.h | 6 ++-- 15 files changed, 54 insertions(+), 61 deletions(-) diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphAttributeTypes.h b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphAttributeTypes.h index 9f7b33a66d..d63d67be43 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphAttributeTypes.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphAttributeTypes.h @@ -68,8 +68,8 @@ namespace EMotionFX } bool InitFromString(const AZStd::string& valueString) override { MCORE_UNUSED(valueString); return false; } // unsupported bool ConvertToString(AZStd::string& outString) const override { MCORE_UNUSED(outString); return false; } // unsupported - uint32 GetClassSize() const override { return sizeof(AttributePose); } - uint32 GetDefaultInterfaceType() const override { return MCore::ATTRIBUTE_INTERFACETYPE_DEFAULT; } + size_t GetClassSize() const override { return sizeof(AttributePose); } + AZ::u32 GetDefaultInterfaceType() const override { return MCore::ATTRIBUTE_INTERFACETYPE_DEFAULT; } private: AnimGraphPose* mValue; @@ -116,8 +116,8 @@ namespace EMotionFX } bool InitFromString(const AZStd::string& valueString) override { MCORE_UNUSED(valueString); return false; } // unsupported bool ConvertToString(AZStd::string& outString) const override { MCORE_UNUSED(outString); return false; } // unsupported - uint32 GetClassSize() const override { return sizeof(AttributeMotionInstance); } - uint32 GetDefaultInterfaceType() const override { return MCore::ATTRIBUTE_INTERFACETYPE_DEFAULT; } + size_t GetClassSize() const override { return sizeof(AttributeMotionInstance); } + AZ::u32 GetDefaultInterfaceType() const override { return MCore::ATTRIBUTE_INTERFACETYPE_DEFAULT; } private: MotionInstance* mValue; diff --git a/Gems/EMotionFX/Code/MCore/Source/Attribute.cpp b/Gems/EMotionFX/Code/MCore/Source/Attribute.cpp index ed2bc1a535..416d493453 100644 --- a/Gems/EMotionFX/Code/MCore/Source/Attribute.cpp +++ b/Gems/EMotionFX/Code/MCore/Source/Attribute.cpp @@ -8,12 +8,10 @@ #include "Attribute.h" #include "AttributeFactory.h" -#include "AttributeString.h" -#include "StringConversions.h" namespace MCore { - Attribute::Attribute(uint32 typeID) + Attribute::Attribute(AZ::u32 typeID) { mTypeID = typeID; } diff --git a/Gems/EMotionFX/Code/MCore/Source/Attribute.h b/Gems/EMotionFX/Code/MCore/Source/Attribute.h index c245e7d778..3b9b4459aa 100644 --- a/Gems/EMotionFX/Code/MCore/Source/Attribute.h +++ b/Gems/EMotionFX/Code/MCore/Source/Attribute.h @@ -28,7 +28,7 @@ namespace MCore class AttributeSettings; // the attribute interface types - enum : uint32 + enum : AZ::u32 { ATTRIBUTE_INTERFACETYPE_FLOATSPINNER = 0, // MCore::AttributeFloat ATTRIBUTE_INTERFACETYPE_FLOATSLIDER = 1, // MCore::AttributeFloat @@ -55,20 +55,20 @@ namespace MCore virtual Attribute* Clone() const = 0; virtual const char* GetTypeString() const = 0; - MCORE_INLINE uint32 GetType() const { return mTypeID; } + MCORE_INLINE AZ::u32 GetType() const { return mTypeID; } virtual bool InitFromString(const AZStd::string& valueString) = 0; virtual bool ConvertToString(AZStd::string& outString) const = 0; virtual bool InitFrom(const Attribute* other) = 0; - virtual uint32 GetClassSize() const = 0; - virtual uint32 GetDefaultInterfaceType() const = 0; + virtual size_t GetClassSize() const = 0; + virtual AZ::u32 GetDefaultInterfaceType() const = 0; Attribute& operator=(const Attribute& other); virtual void NetworkSerialize(EMotionFX::Network::AnimGraphSnapshotChunkSerializer&) {}; protected: - uint32 mTypeID; /**< The unique type ID of the attribute class. */ + AZ::u32 mTypeID; /**< The unique type ID of the attribute class. */ - Attribute(uint32 typeID); + Attribute(AZ::u32 typeID); }; } // namespace MCore diff --git a/Gems/EMotionFX/Code/MCore/Source/AttributeBool.h b/Gems/EMotionFX/Code/MCore/Source/AttributeBool.h index 9a923b5fda..3be04c3ce1 100644 --- a/Gems/EMotionFX/Code/MCore/Source/AttributeBool.h +++ b/Gems/EMotionFX/Code/MCore/Source/AttributeBool.h @@ -39,7 +39,7 @@ namespace MCore MCORE_INLINE void SetValue(bool value) { mValue = value; } MCORE_INLINE uint8* GetRawDataPointer() { return reinterpret_cast(&mValue); } - MCORE_INLINE uint32 GetRawDataSize() const { return sizeof(bool); } + MCORE_INLINE size_t GetRawDataSize() const { return sizeof(bool); } // overloaded from the attribute base class Attribute* Clone() const override { return AttributeBool::Create(mValue); } @@ -50,8 +50,8 @@ namespace MCore return AzFramework::StringFunc::LooksLikeBool(valueString.c_str(), &mValue); } bool ConvertToString(AZStd::string& outString) const override { outString = AZStd::string::format("%d", (mValue) ? 1 : 0); return true; } - uint32 GetClassSize() const override { return sizeof(AttributeBool); } - uint32 GetDefaultInterfaceType() const override { return ATTRIBUTE_INTERFACETYPE_CHECKBOX; } + size_t GetClassSize() const override { return sizeof(AttributeBool); } + AZ::u32 GetDefaultInterfaceType() const override { return ATTRIBUTE_INTERFACETYPE_CHECKBOX; } private: bool mValue; /**< The boolean value, false on default. */ diff --git a/Gems/EMotionFX/Code/MCore/Source/AttributeColor.h b/Gems/EMotionFX/Code/MCore/Source/AttributeColor.h index 6287239bf8..4ad488af47 100644 --- a/Gems/EMotionFX/Code/MCore/Source/AttributeColor.h +++ b/Gems/EMotionFX/Code/MCore/Source/AttributeColor.h @@ -42,7 +42,7 @@ namespace MCore MCORE_INLINE void SetValue(const RGBAColor& value) { mValue = value; } MCORE_INLINE uint8* GetRawDataPointer() { return reinterpret_cast(&mValue); } - MCORE_INLINE uint32 GetRawDataSize() const { return sizeof(RGBAColor); } + MCORE_INLINE size_t GetRawDataSize() const { return sizeof(RGBAColor); } // overloaded from the attribute base class Attribute* Clone() const override { return AttributeColor::Create(mValue); } @@ -67,8 +67,8 @@ namespace MCore return true; } bool ConvertToString(AZStd::string& outString) const override { AZStd::to_string(outString, AZ::Vector4(mValue.r, mValue.g, mValue.b, mValue.a)); return true; } - uint32 GetClassSize() const override { return sizeof(AttributeColor); } - uint32 GetDefaultInterfaceType() const override { return ATTRIBUTE_INTERFACETYPE_COLOR; } + size_t GetClassSize() const override { return sizeof(AttributeColor); } + AZ::u32 GetDefaultInterfaceType() const override { return ATTRIBUTE_INTERFACETYPE_COLOR; } private: RGBAColor mValue; /**< The color value. */ diff --git a/Gems/EMotionFX/Code/MCore/Source/AttributeFactory.cpp b/Gems/EMotionFX/Code/MCore/Source/AttributeFactory.cpp index d0129bdb03..53b91dbb98 100644 --- a/Gems/EMotionFX/Code/MCore/Source/AttributeFactory.cpp +++ b/Gems/EMotionFX/Code/MCore/Source/AttributeFactory.cpp @@ -54,8 +54,8 @@ namespace MCore void AttributeFactory::RegisterAttribute(Attribute* attribute) { // check first if the type hasn't already been registered - const uint32 attribIndex = FindAttributeIndexByType(attribute->GetType()); - if (attribIndex != MCORE_INVALIDINDEX32) + const size_t attribIndex = FindAttributeIndexByType(attribute->GetType()); + if (attribIndex != InvalidIndex) { MCore::LogWarning("MCore::AttributeFactory::RegisterAttribute() - There is already an attribute of the same type registered (typeID %d vs %d - typeString '%s' vs '%s')", attribute->GetType(), mRegistered[attribIndex]->GetType(), attribute->GetTypeString(), mRegistered[attribIndex]->GetTypeString()); return; @@ -68,8 +68,8 @@ namespace MCore void AttributeFactory::UnregisterAttribute(Attribute* attribute, bool delFromMem) { // check first if the type hasn't already been registered - const uint32 attribIndex = FindAttributeIndexByType(attribute->GetType()); - if (attribIndex == MCORE_INVALIDINDEX32) + const size_t attribIndex = FindAttributeIndexByType(attribute->GetType()); + if (attribIndex == InvalidIndex) { MCore::LogWarning("MCore::AttributeFactory::UnregisterAttribute() - No attribute with the given type found (typeID=%d - typeString='%s'", attribute->GetType(), attribute->GetTypeString()); return; @@ -84,26 +84,21 @@ namespace MCore } - uint32 AttributeFactory::FindAttributeIndexByType(uint32 typeID) const + size_t AttributeFactory::FindAttributeIndexByType(size_t typeID) const { - const size_t numAttributes = mRegistered.size(); - for (size_t i = 0; i < numAttributes; ++i) + const auto foundAttribute = AZStd::find_if(begin(mRegistered), end(mRegistered), [typeID](const Attribute* registeredAttribute) { - if (mRegistered[i]->GetType() == typeID) // we found one with the same type - { - return static_cast(i); - } - } + return registeredAttribute->GetType() == typeID; + }); - // no attribute of this type found - return MCORE_INVALIDINDEX32; + return foundAttribute != end(mRegistered) ? AZStd::distance(begin(mRegistered), foundAttribute) : InvalidIndex; } - Attribute* AttributeFactory::CreateAttributeByType(uint32 typeID) const + Attribute* AttributeFactory::CreateAttributeByType(size_t typeID) const { - const uint32 attribIndex = FindAttributeIndexByType(typeID); - if (attribIndex == MCORE_INVALIDINDEX32) + const size_t attribIndex = FindAttributeIndexByType(typeID); + if (attribIndex == InvalidIndex) { return nullptr; } diff --git a/Gems/EMotionFX/Code/MCore/Source/AttributeFactory.h b/Gems/EMotionFX/Code/MCore/Source/AttributeFactory.h index 596ac24902..02bd5b0e1b 100644 --- a/Gems/EMotionFX/Code/MCore/Source/AttributeFactory.h +++ b/Gems/EMotionFX/Code/MCore/Source/AttributeFactory.h @@ -31,10 +31,10 @@ namespace MCore void RegisterStandardTypes(); size_t GetNumRegisteredAttributes() const { return mRegistered.size(); } - Attribute* GetRegisteredAttribute(uint32 index) const { return mRegistered[index]; } + Attribute* GetRegisteredAttribute(size_t index) const { return mRegistered[index]; } - uint32 FindAttributeIndexByType(uint32 typeID) const; - Attribute* CreateAttributeByType(uint32 typeID) const; + size_t FindAttributeIndexByType(size_t typeID) const; + Attribute* CreateAttributeByType(size_t typeID) const; private: AZStd::vector mRegistered; diff --git a/Gems/EMotionFX/Code/MCore/Source/AttributeFloat.h b/Gems/EMotionFX/Code/MCore/Source/AttributeFloat.h index ef650a1430..fee4494ba5 100644 --- a/Gems/EMotionFX/Code/MCore/Source/AttributeFloat.h +++ b/Gems/EMotionFX/Code/MCore/Source/AttributeFloat.h @@ -40,7 +40,7 @@ namespace MCore MCORE_INLINE void SetValue(float value) { mValue = value; } MCORE_INLINE uint8* GetRawDataPointer() { return reinterpret_cast(&mValue); } - MCORE_INLINE uint32 GetRawDataSize() const { return sizeof(float); } + MCORE_INLINE size_t GetRawDataSize() const { return sizeof(float); } // overloaded from the attribute base class Attribute* Clone() const override { return AttributeFloat::Create(mValue); } @@ -51,8 +51,8 @@ namespace MCore return AzFramework::StringFunc::LooksLikeFloat(valueString.c_str(), &mValue); } bool ConvertToString(AZStd::string& outString) const override { outString = AZStd::string::format("%.8f", mValue); return true; } - uint32 GetClassSize() const override { return sizeof(AttributeFloat); } - uint32 GetDefaultInterfaceType() const override { return ATTRIBUTE_INTERFACETYPE_FLOATSPINNER; } + size_t GetClassSize() const override { return sizeof(AttributeFloat); } + AZ::u32 GetDefaultInterfaceType() const override { return ATTRIBUTE_INTERFACETYPE_FLOATSPINNER; } private: float mValue; /**< The float value. */ diff --git a/Gems/EMotionFX/Code/MCore/Source/AttributeInt32.h b/Gems/EMotionFX/Code/MCore/Source/AttributeInt32.h index f13246d438..b1fd1da686 100644 --- a/Gems/EMotionFX/Code/MCore/Source/AttributeInt32.h +++ b/Gems/EMotionFX/Code/MCore/Source/AttributeInt32.h @@ -40,7 +40,7 @@ namespace MCore MCORE_INLINE void SetValue(int32 value) { mValue = value; } MCORE_INLINE uint8* GetRawDataPointer() { return reinterpret_cast(&mValue); } - MCORE_INLINE uint32 GetRawDataSize() const { return sizeof(int32); } + MCORE_INLINE size_t GetRawDataSize() const { return sizeof(int32); } // overloaded from the attribute base class Attribute* Clone() const override { return AttributeInt32::Create(mValue); } @@ -51,8 +51,8 @@ namespace MCore return AzFramework::StringFunc::LooksLikeInt(valueString.c_str(), &mValue); } bool ConvertToString(AZStd::string& outString) const override { outString = AZStd::string::format("%d", mValue); return true; } - uint32 GetClassSize() const override { return sizeof(AttributeInt32); } - uint32 GetDefaultInterfaceType() const override { return ATTRIBUTE_INTERFACETYPE_INTSPINNER; } + size_t GetClassSize() const override { return sizeof(AttributeInt32); } + AZ::u32 GetDefaultInterfaceType() const override { return ATTRIBUTE_INTERFACETYPE_INTSPINNER; } private: int32 mValue; /**< The signed integer value. */ diff --git a/Gems/EMotionFX/Code/MCore/Source/AttributePointer.h b/Gems/EMotionFX/Code/MCore/Source/AttributePointer.h index 8f7a6cbc65..98eb5f602b 100644 --- a/Gems/EMotionFX/Code/MCore/Source/AttributePointer.h +++ b/Gems/EMotionFX/Code/MCore/Source/AttributePointer.h @@ -53,8 +53,8 @@ namespace MCore } bool InitFromString(const AZStd::string& valueString) override { MCORE_UNUSED(valueString); MCORE_ASSERT(false); return false; } // currently unsupported bool ConvertToString(AZStd::string& outString) const override { MCORE_UNUSED(outString); MCORE_ASSERT(false); return false; } // currently unsupported - uint32 GetClassSize() const override { return sizeof(AttributePointer); } - uint32 GetDefaultInterfaceType() const override { return ATTRIBUTE_INTERFACETYPE_DEFAULT; } + size_t GetClassSize() const override { return sizeof(AttributePointer); } + AZ::u32 GetDefaultInterfaceType() const override { return ATTRIBUTE_INTERFACETYPE_DEFAULT; } private: void* mValue; /**< The pointer value. */ diff --git a/Gems/EMotionFX/Code/MCore/Source/AttributeQuaternion.h b/Gems/EMotionFX/Code/MCore/Source/AttributeQuaternion.h index 3380cac957..39d9243197 100644 --- a/Gems/EMotionFX/Code/MCore/Source/AttributeQuaternion.h +++ b/Gems/EMotionFX/Code/MCore/Source/AttributeQuaternion.h @@ -39,7 +39,7 @@ namespace MCore static AttributeQuaternion* Create(const AZ::Quaternion& value); MCORE_INLINE uint8* GetRawDataPointer() { return reinterpret_cast(&mValue); } - MCORE_INLINE uint32 GetRawDataSize() const { return sizeof(AZ::Quaternion); } + MCORE_INLINE size_t GetRawDataSize() const { return sizeof(AZ::Quaternion); } // adjust values MCORE_INLINE const AZ::Quaternion& GetValue() const { return mValue; } @@ -68,8 +68,8 @@ namespace MCore return true; } bool ConvertToString(AZStd::string& outString) const override { AZStd::to_string(outString, mValue); return true; } - uint32 GetClassSize() const override { return sizeof(AttributeQuaternion); } - uint32 GetDefaultInterfaceType() const override { return ATTRIBUTE_INTERFACETYPE_DEFAULT; } + size_t GetClassSize() const override { return sizeof(AttributeQuaternion); } + AZ::u32 GetDefaultInterfaceType() const override { return ATTRIBUTE_INTERFACETYPE_DEFAULT; } private: AZ::Quaternion mValue; /**< The Quaternion value. */ diff --git a/Gems/EMotionFX/Code/MCore/Source/AttributeString.h b/Gems/EMotionFX/Code/MCore/Source/AttributeString.h index 4f3f8df6f9..a05c057023 100644 --- a/Gems/EMotionFX/Code/MCore/Source/AttributeString.h +++ b/Gems/EMotionFX/Code/MCore/Source/AttributeString.h @@ -36,7 +36,7 @@ namespace MCore static AttributeString* Create(const char* value = ""); MCORE_INLINE uint8* GetRawDataPointer() { return reinterpret_cast(mValue.data()); } - MCORE_INLINE uint32 GetRawDataSize() const { return static_cast(mValue.size()); } + MCORE_INLINE size_t GetRawDataSize() const { return mValue.size(); } // adjust values MCORE_INLINE const char* AsChar() const { return mValue.c_str(); } @@ -57,7 +57,7 @@ namespace MCore } bool InitFromString(const AZStd::string& valueString) override { mValue = valueString; return true; } bool ConvertToString(AZStd::string& outString) const override { outString = mValue; return true; } - uint32 GetClassSize() const override { return sizeof(AttributeString); } + size_t GetClassSize() const override { return sizeof(AttributeString); } uint32 GetDefaultInterfaceType() const override { return ATTRIBUTE_INTERFACETYPE_STRING; } private: diff --git a/Gems/EMotionFX/Code/MCore/Source/AttributeVector2.h b/Gems/EMotionFX/Code/MCore/Source/AttributeVector2.h index b82c7778f7..826899186a 100644 --- a/Gems/EMotionFX/Code/MCore/Source/AttributeVector2.h +++ b/Gems/EMotionFX/Code/MCore/Source/AttributeVector2.h @@ -43,7 +43,7 @@ namespace MCore static AttributeVector2* Create(float x, float y); MCORE_INLINE uint8* GetRawDataPointer() { return reinterpret_cast(&mValue); } - MCORE_INLINE uint32 GetRawDataSize() const { return sizeofVector2; } + MCORE_INLINE size_t GetRawDataSize() const { return sizeofVector2; } // adjust values MCORE_INLINE const AZ::Vector2& GetValue() const { return mValue; } @@ -66,8 +66,8 @@ namespace MCore return AzFramework::StringFunc::LooksLikeVector2(valueString.c_str(), &mValue); } bool ConvertToString(AZStd::string& outString) const override { AZStd::to_string(outString, mValue); return true; } - uint32 GetClassSize() const override { return sizeof(AttributeVector2); } - uint32 GetDefaultInterfaceType() const override { return ATTRIBUTE_INTERFACETYPE_VECTOR2; } + size_t GetClassSize() const override { return sizeof(AttributeVector2); } + AZ::u32 GetDefaultInterfaceType() const override { return ATTRIBUTE_INTERFACETYPE_VECTOR2; } private: AZ::Vector2 mValue; /**< The Vector2 value. */ diff --git a/Gems/EMotionFX/Code/MCore/Source/AttributeVector3.h b/Gems/EMotionFX/Code/MCore/Source/AttributeVector3.h index ea6b820944..066962fb8f 100644 --- a/Gems/EMotionFX/Code/MCore/Source/AttributeVector3.h +++ b/Gems/EMotionFX/Code/MCore/Source/AttributeVector3.h @@ -38,7 +38,7 @@ namespace MCore static AttributeVector3* Create(float x, float y, float z); MCORE_INLINE uint8* GetRawDataPointer() { return reinterpret_cast(&mValue); } - MCORE_INLINE uint32 GetRawDataSize() const { return sizeof(AZ::Vector3); } + MCORE_INLINE size_t GetRawDataSize() const { return sizeof(AZ::Vector3); } // adjust values MCORE_INLINE const AZ::Vector3& GetValue() const { return mValue; } @@ -67,8 +67,8 @@ namespace MCore return true; } bool ConvertToString(AZStd::string& outString) const override { AZStd::to_string(outString, mValue); return true; } - uint32 GetClassSize() const override { return sizeof(AttributeVector3); } - uint32 GetDefaultInterfaceType() const override { return ATTRIBUTE_INTERFACETYPE_VECTOR3; } + size_t GetClassSize() const override { return sizeof(AttributeVector3); } + AZ::u32 GetDefaultInterfaceType() const override { return ATTRIBUTE_INTERFACETYPE_VECTOR3; } private: AZ::Vector3 mValue; /**< The Vector3 value. */ diff --git a/Gems/EMotionFX/Code/MCore/Source/AttributeVector4.h b/Gems/EMotionFX/Code/MCore/Source/AttributeVector4.h index 93dc4a527b..7b20e92a6b 100644 --- a/Gems/EMotionFX/Code/MCore/Source/AttributeVector4.h +++ b/Gems/EMotionFX/Code/MCore/Source/AttributeVector4.h @@ -39,7 +39,7 @@ namespace MCore static AttributeVector4* Create(float x, float y, float z, float w); MCORE_INLINE uint8* GetRawDataPointer() { return reinterpret_cast(&mValue); } - MCORE_INLINE uint32 GetRawDataSize() const { return sizeof(AZ::Vector4); } + MCORE_INLINE size_t GetRawDataSize() const { return sizeof(AZ::Vector4); } // adjust values MCORE_INLINE const AZ::Vector4& GetValue() const { return mValue; } @@ -63,8 +63,8 @@ namespace MCore } bool ConvertToString(AZStd::string& outString) const override { AZStd::to_string(outString, mValue); return true; } // void ConvertCoordinateSystem() { GetCoordinateSystem().ConvertVector4(&mValue); } - uint32 GetClassSize() const override { return sizeof(AttributeVector4); } - uint32 GetDefaultInterfaceType() const override { return ATTRIBUTE_INTERFACETYPE_VECTOR4; } + size_t GetClassSize() const override { return sizeof(AttributeVector4); } + AZ::u32 GetDefaultInterfaceType() const override { return ATTRIBUTE_INTERFACETYPE_VECTOR4; } private: AZ::Vector4 mValue; /**< The Vector4 value. */ From d712c54e206cf4733908991a01aa7ade08d2e071 Mon Sep 17 00:00:00 2001 From: Chris Burel Date: Mon, 24 May 2021 12:03:47 -0700 Subject: [PATCH 186/803] Convert BoundingSphere to use `int32_t` to match `AZ::Vector3::GetElement`'s signature Signed-off-by: Chris Burel --- Gems/EMotionFX/Code/MCore/Source/BoundingSphere.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gems/EMotionFX/Code/MCore/Source/BoundingSphere.cpp b/Gems/EMotionFX/Code/MCore/Source/BoundingSphere.cpp index f462e5499f..959cebe16d 100644 --- a/Gems/EMotionFX/Code/MCore/Source/BoundingSphere.cpp +++ b/Gems/EMotionFX/Code/MCore/Source/BoundingSphere.cpp @@ -46,7 +46,7 @@ namespace MCore { float distance = 0.0f; - for (uint32 t = 0; t < 3; ++t) + for (int32_t t = 0; t < 3; ++t) { const AZ::Vector3& minVec = b.GetMin(); if (mCenter.GetElement(t) < minVec.GetElement(t)) @@ -79,7 +79,7 @@ namespace MCore bool BoundingSphere::Contains(const AABB& b) const { float distance = 0.0f; - for (uint32 t = 0; t < 3; ++t) + for (int32_t t = 0; t < 3; ++t) { const AZ::Vector3& maxVec = b.GetMax(); if (mCenter.GetElement(t) < maxVec.GetElement(t)) From 889cdd8c0aa30ebbd45ea55dbb7da9f6d2a45c08 Mon Sep 17 00:00:00 2001 From: Chris Burel Date: Mon, 24 May 2021 12:03:49 -0700 Subject: [PATCH 187/803] Convert MCore::Command uint32 -> size_t Signed-off-by: Chris Burel --- .../EMStudioSDK/Source/MainWindow.cpp | 6 ++-- Gems/EMotionFX/Code/MCore/Source/Command.cpp | 36 +++++-------------- Gems/EMotionFX/Code/MCore/Source/Command.h | 8 ++--- 3 files changed, 16 insertions(+), 34 deletions(-) diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindow.cpp index c1c48b3480..7303c8d559 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindow.cpp @@ -163,9 +163,9 @@ namespace EMStudio {} ~UndoMenuCallback() = default; - void OnRemoveCommand([[maybe_unused]] uint32 historyIndex) override { m_mainWindow->UpdateUndoRedo(); } - void OnSetCurrentCommand([[maybe_unused]] uint32 index) override { m_mainWindow->UpdateUndoRedo(); } - void OnAddCommandToHistory([[maybe_unused]] uint32 historyIndex, [[maybe_unused]] MCore::CommandGroup* group, [[maybe_unused]] MCore::Command* command, [[maybe_unused]] const MCore::CommandLine& commandLine) override { m_mainWindow->UpdateUndoRedo(); } + void OnRemoveCommand([[maybe_unused]] size_t historyIndex) override { m_mainWindow->UpdateUndoRedo(); } + void OnSetCurrentCommand([[maybe_unused]] size_t index) override { m_mainWindow->UpdateUndoRedo(); } + void OnAddCommandToHistory([[maybe_unused]] size_t historyIndex, [[maybe_unused]] MCore::CommandGroup* group, [[maybe_unused]] MCore::Command* command, [[maybe_unused]] const MCore::CommandLine& commandLine) override { m_mainWindow->UpdateUndoRedo(); } void OnPreExecuteCommand([[maybe_unused]] MCore::CommandGroup* group, [[maybe_unused]] MCore::Command* command, [[maybe_unused]] const MCore::CommandLine& commandLine) override {} void OnPostExecuteCommand([[maybe_unused]] MCore::CommandGroup* group, [[maybe_unused]] MCore::Command* command, [[maybe_unused]] const MCore::CommandLine& commandLine, [[maybe_unused]] bool wasSuccess, [[maybe_unused]] const AZStd::string& outResult) override {} diff --git a/Gems/EMotionFX/Code/MCore/Source/Command.cpp b/Gems/EMotionFX/Code/MCore/Source/Command.cpp index 39e9fde965..8845e7c278 100644 --- a/Gems/EMotionFX/Code/MCore/Source/Command.cpp +++ b/Gems/EMotionFX/Code/MCore/Source/Command.cpp @@ -8,6 +8,7 @@ // include the required headers #include "Command.h" +#include #include @@ -81,9 +82,9 @@ namespace MCore } - uint32 Command::GetNumCallbacks() const + size_t Command::GetNumCallbacks() const { - return static_cast(mCallbacks.size()); + return mCallbacks.size(); } @@ -123,37 +124,18 @@ namespace MCore // calculate the number of registered pre-execute callbacks - uint32 Command::CalcNumPreCommandCallbacks() const + size_t Command::CalcNumPreCommandCallbacks() const { - uint32 result = 0; - - const size_t numCallbacks = mCallbacks.size(); - for (size_t i = 0; i < numCallbacks; ++i) + return AZStd::accumulate(begin(mCallbacks), end(mCallbacks), size_t{0}, [](size_t total, const Callback* callback) { - if (mCallbacks[i]->GetExecutePreCommand()) - { - result++; - } - } - - return result; + return callback->GetExecutePreCommand() ? total + 1 : total; + }); } // calculate the number of registered post-execute callbacks - uint32 Command::CalcNumPostCommandCallbacks() const + size_t Command::CalcNumPostCommandCallbacks() const { - uint32 result = 0; - - const size_t numCallbacks = mCallbacks.size(); - for (size_t i = 0; i < numCallbacks; ++i) - { - if (mCallbacks[i]->GetExecutePreCommand() == false) - { - result++; - } - } - - return result; + return mCallbacks.size() - CalcNumPreCommandCallbacks(); } } // namespace MCore diff --git a/Gems/EMotionFX/Code/MCore/Source/Command.h b/Gems/EMotionFX/Code/MCore/Source/Command.h index 7309c5dc91..d6bfb3a0d7 100644 --- a/Gems/EMotionFX/Code/MCore/Source/Command.h +++ b/Gems/EMotionFX/Code/MCore/Source/Command.h @@ -279,26 +279,26 @@ namespace MCore * Get the number of registered/added command callbacks. * @result The number of command callbacks that have been added. */ - uint32 GetNumCallbacks() const; + size_t GetNumCallbacks() const; /** * Calculate the number of registered pre-execute callbacks. * @result The number of registered pre-execute callbacks. */ - uint32 CalcNumPreCommandCallbacks() const; + size_t CalcNumPreCommandCallbacks() const; /** * Calculate the number of registered post-execute callbacks. * @result The number of registered post-execute callbacks. */ - uint32 CalcNumPostCommandCallbacks() const; + size_t CalcNumPostCommandCallbacks() const; /** * Get a given command callback. * @param index The callback number, which must be in range of [0..GetNumCallbacks()-1]. * @result A pointer to the command callback object. */ - MCORE_INLINE Command::Callback* GetCallback(uint32 index) { return mCallbacks[index]; } + MCORE_INLINE Command::Callback* GetCallback(size_t index) { return mCallbacks[index]; } /** * Add (register) a command callback. From a86e2ddf245dfff9ea67df4918729de157956dd5 Mon Sep 17 00:00:00 2001 From: Chris Burel Date: Mon, 24 May 2021 12:03:51 -0700 Subject: [PATCH 188/803] Convert MCore::CommandLine uint32 -> size_t Signed-off-by: Chris Burel --- .../Code/MCore/Source/CommandLine.cpp | 105 +++++++++--------- .../EMotionFX/Code/MCore/Source/CommandLine.h | 10 +- 2 files changed, 55 insertions(+), 60 deletions(-) diff --git a/Gems/EMotionFX/Code/MCore/Source/CommandLine.cpp b/Gems/EMotionFX/Code/MCore/Source/CommandLine.cpp index 25ae5f548f..ae536101e6 100644 --- a/Gems/EMotionFX/Code/MCore/Source/CommandLine.cpp +++ b/Gems/EMotionFX/Code/MCore/Source/CommandLine.cpp @@ -26,8 +26,8 @@ namespace MCore void CommandLine::GetValue(const char* paramName, const char* defaultValue, AZStd::string* outResult) const { // try to find the parameter index - const uint32 paramIndex = FindParameterIndex(paramName); - if (paramIndex == MCORE_INVALIDINDEX32) + const size_t paramIndex = FindParameterIndex(paramName); + if (paramIndex == InvalidIndex) { *outResult = defaultValue; return; @@ -49,8 +49,8 @@ namespace MCore void CommandLine::GetValue(const char* paramName, const char* defaultValue, AZStd::string& outResult) const { // Try to find the parameter index. - const uint32 paramIndex = FindParameterIndex(paramName); - if (paramIndex == MCORE_INVALIDINDEX32) + const size_t paramIndex = FindParameterIndex(paramName); + if (paramIndex == InvalidIndex) { outResult = defaultValue; return; @@ -72,8 +72,8 @@ namespace MCore int32 CommandLine::GetValueAsInt(const char* paramName, int32 defaultValue) const { // try to find the parameter index - const uint32 paramIndex = FindParameterIndex(paramName); - if (paramIndex == MCORE_INVALIDINDEX32) + const size_t paramIndex = FindParameterIndex(paramName); + if (paramIndex == InvalidIndex) { return defaultValue; } @@ -93,8 +93,8 @@ namespace MCore float CommandLine::GetValueAsFloat(const char* paramName, float defaultValue) const { // try to find the parameter index - const uint32 paramIndex = FindParameterIndex(paramName); - if (paramIndex == MCORE_INVALIDINDEX32) + const size_t paramIndex = FindParameterIndex(paramName); + if (paramIndex == InvalidIndex) { return defaultValue; } @@ -114,8 +114,8 @@ namespace MCore bool CommandLine::GetValueAsBool(const char* paramName, bool defaultValue) const { // try to find the parameter index - const uint32 paramIndex = FindParameterIndex(paramName); - if (paramIndex == MCORE_INVALIDINDEX32) + const size_t paramIndex = FindParameterIndex(paramName); + if (paramIndex == InvalidIndex) { return defaultValue; } @@ -135,8 +135,8 @@ namespace MCore AZ::Vector3 CommandLine::GetValueAsVector3(const char* paramName, const AZ::Vector3& defaultValue) const { // try to find the parameter index - const uint32 paramIndex = FindParameterIndex(paramName); - if (paramIndex == MCORE_INVALIDINDEX32) + const size_t paramIndex = FindParameterIndex(paramName); + if (paramIndex == InvalidIndex) { return defaultValue; } @@ -157,8 +157,8 @@ namespace MCore AZ::Vector4 CommandLine::GetValueAsVector4(const char* paramName, const AZ::Vector4& defaultValue) const { // try to find the parameter index - const uint32 paramIndex = FindParameterIndex(paramName); - if (paramIndex == MCORE_INVALIDINDEX32) + const size_t paramIndex = FindParameterIndex(paramName); + if (paramIndex == InvalidIndex) { return defaultValue; } @@ -178,8 +178,8 @@ namespace MCore void CommandLine::GetValue(const char* paramName, Command* command, AZStd::string* outResult) const { // try to find the parameter index - const uint32 paramIndex = FindParameterIndex(paramName); - if (paramIndex == MCORE_INVALIDINDEX32) + const size_t paramIndex = FindParameterIndex(paramName); + if (paramIndex == InvalidIndex) { command->GetOriginalCommand()->GetSyntax().GetDefaultValue(paramName, *outResult); return; @@ -198,8 +198,8 @@ namespace MCore AZ::Outcome CommandLine::GetValueIfExists(const char* paramName, Command* command) const { AZ_UNUSED(command); - const uint32 paramIndex = FindParameterIndex(paramName); - if (paramIndex != MCORE_INVALIDINDEX32) + const size_t paramIndex = FindParameterIndex(paramName); + if (paramIndex != InvalidIndex) { return AZ::Success(m_parameters[paramIndex].mValue); } @@ -211,8 +211,8 @@ namespace MCore const AZStd::string& CommandLine::GetValue(const char* paramName, Command* command) const { // Try to find the parameter index. - const uint32 paramIndex = FindParameterIndex(paramName); - if (paramIndex == MCORE_INVALIDINDEX32) + const size_t paramIndex = FindParameterIndex(paramName); + if (paramIndex == InvalidIndex) { return command->GetOriginalCommand()->GetSyntax().GetDefaultValue(paramName); } @@ -226,8 +226,8 @@ namespace MCore int32 CommandLine::GetValueAsInt(const char* paramName, Command* command) const { // try to find the parameter index - const uint32 paramIndex = FindParameterIndex(paramName); - if (paramIndex == MCORE_INVALIDINDEX32) + const size_t paramIndex = FindParameterIndex(paramName); + if (paramIndex == InvalidIndex) { AZStd::string result; if (command->GetOriginalCommand()->GetSyntax().GetDefaultValue(paramName, result)) @@ -236,7 +236,7 @@ namespace MCore } else { - return MCORE_INVALIDINDEX32; + return InvalidIndexT; } } @@ -248,8 +248,8 @@ namespace MCore float CommandLine::GetValueAsFloat(const char* paramName, Command* command) const { // try to find the parameter index - const uint32 paramIndex = FindParameterIndex(paramName); - if (paramIndex == MCORE_INVALIDINDEX32) + const size_t paramIndex = FindParameterIndex(paramName); + if (paramIndex == InvalidIndex) { AZStd::string result; if (command->GetOriginalCommand()->GetSyntax().GetDefaultValue(paramName, result)) @@ -271,8 +271,8 @@ namespace MCore bool CommandLine::GetValueAsBool(const char* paramName, Command* command) const { // try to find the parameter index - const uint32 paramIndex = FindParameterIndex(paramName); - if (paramIndex == MCORE_INVALIDINDEX32) + const size_t paramIndex = FindParameterIndex(paramName); + if (paramIndex == InvalidIndex) { AZStd::string result; if (command->GetOriginalCommand()->GetSyntax().GetDefaultValue(paramName, result)) @@ -294,8 +294,8 @@ namespace MCore AZ::Vector3 CommandLine::GetValueAsVector3(const char* paramName, Command* command) const { // try to find the parameter index - const uint32 paramIndex = FindParameterIndex(paramName); - if (paramIndex == MCORE_INVALIDINDEX32) + const size_t paramIndex = FindParameterIndex(paramName); + if (paramIndex == InvalidIndex) { AZStd::string result; if (command->GetOriginalCommand()->GetSyntax().GetDefaultValue(paramName, result)) @@ -317,8 +317,8 @@ namespace MCore AZ::Vector4 CommandLine::GetValueAsVector4(const char* paramName, Command* command) const { // try to find the parameter index - const uint32 paramIndex = FindParameterIndex(paramName); - if (paramIndex == MCORE_INVALIDINDEX32) + const size_t paramIndex = FindParameterIndex(paramName); + if (paramIndex == InvalidIndex) { AZStd::string result; if (command->GetOriginalCommand()->GetSyntax().GetDefaultValue(paramName, result)) @@ -337,21 +337,21 @@ namespace MCore // get the number of parameters - uint32 CommandLine::GetNumParameters() const + size_t CommandLine::GetNumParameters() const { - return static_cast(m_parameters.size()); + return m_parameters.size(); } // get the parameter name for a given parameter - const AZStd::string& CommandLine::GetParameterName(uint32 nr) const + const AZStd::string& CommandLine::GetParameterName(size_t nr) const { return m_parameters[nr].mName; } // get the parameter value for a given parameter number - const AZStd::string& CommandLine::GetParameterValue(uint32 nr) const + const AZStd::string& CommandLine::GetParameterValue(size_t nr) const { return m_parameters[nr].mValue; } @@ -361,8 +361,8 @@ namespace MCore bool CommandLine::CheckIfHasValue(const char* paramName) const { // try to find the parameter index - const uint32 paramIndex = FindParameterIndex(paramName); - if (paramIndex == MCORE_INVALIDINDEX32) + const size_t paramIndex = FindParameterIndex(paramName); + if (paramIndex == InvalidIndex) { return false; } @@ -373,42 +373,37 @@ namespace MCore // try to find a given parameter's index into the parameter array - uint32 CommandLine::FindParameterIndex(const char* paramName) const + size_t CommandLine::FindParameterIndex(const char* paramName) const { // compare all parameter names on a non-case sensitive way - const size_t numParams = m_parameters.size(); - for (size_t i = 0; i < numParams; ++i) + const auto foundParameter = AZStd::find_if(begin(m_parameters), end(m_parameters), [paramName](const Parameter& parameter) { - if (AzFramework::StringFunc::Equal(m_parameters[i].mName.c_str(), paramName, false /* no case */)) - { - return static_cast(i); - } - } + return AzFramework::StringFunc::Equal(parameter.mName, paramName, false /* no case */); + }); - // not found - return MCORE_INVALIDINDEX32; + return foundParameter != end(m_parameters) ? AZStd::distance(begin(m_parameters), foundParameter) : InvalidIndex; } // check if we have a parameter with a given name defined bool CommandLine::CheckIfHasParameter(const char* paramName) const { - return (FindParameterIndex(paramName) != MCORE_INVALIDINDEX32); + return (FindParameterIndex(paramName) != InvalidIndex); } bool CommandLine::CheckIfHasParameter(const AZStd::string& paramName) const { - return (FindParameterIndex(paramName.c_str()) != MCORE_INVALIDINDEX32); + return (FindParameterIndex(paramName.c_str()) != InvalidIndex); } // extract the next parameter, starting from a given offset - bool CommandLine::ExtractNextParam(const AZStd::string& paramString, AZStd::string& outParamName, AZStd::string& outParamValue, uint32* inOutStartOffset) + bool CommandLine::ExtractNextParam(const AZStd::string& paramString, AZStd::string& outParamName, AZStd::string& outParamValue, size_t* inOutStartOffset) { outParamName.clear(); outParamValue.clear(); // check if we already reached the end of the string - uint32 offset = *inOutStartOffset; + size_t offset = *inOutStartOffset; if (offset >= paramString.size()) { return false; @@ -416,8 +411,8 @@ namespace MCore // filter out the next parameter AZStd::string::const_iterator iterator = paramString.begin() + offset; - uint32 paramNameStart = MCORE_INVALIDINDEX32; - uint32 paramValueStart = MCORE_INVALIDINDEX32; + size_t paramNameStart = InvalidIndex; + size_t paramValueStart = InvalidIndex; bool readingParamName = false; bool readingParamValue = false; bool foundNextParam = false; @@ -528,7 +523,7 @@ namespace MCore // extract all parameters AZStd::string paramName; AZStd::string paramValue; - uint32 offset = 0; + size_t offset = 0; while (ExtractNextParam(commandLine, paramName, paramValue, &offset)) { // if the parameter name is empty then it isn't a real parameter @@ -545,7 +540,7 @@ namespace MCore { const size_t numParameters = m_parameters.size(); LogInfo("Command line '%s' has %d parameters", debugName, numParameters); - for (uint32 i = 0; i < numParameters; ++i) + for (size_t i = 0; i < numParameters; ++i) { LogInfo("Param %d (name='%s' value='%s'", i, m_parameters[i].mName.c_str(), m_parameters[i].mValue.c_str()); } diff --git a/Gems/EMotionFX/Code/MCore/Source/CommandLine.h b/Gems/EMotionFX/Code/MCore/Source/CommandLine.h index 8eef67ca3c..8a4e5172e8 100644 --- a/Gems/EMotionFX/Code/MCore/Source/CommandLine.h +++ b/Gems/EMotionFX/Code/MCore/Source/CommandLine.h @@ -207,21 +207,21 @@ namespace MCore * to the extended constructor or to the SetCommandLine function. * @result The number of parameters that have been detected. */ - uint32 GetNumParameters() const; + size_t GetNumParameters() const; /** * Get the name of a given parameter. * @param nr The parameter number, which must be in range of [0 .. GetNumParameters()-1]. * @result The name of the parameter. */ - const AZStd::string& GetParameterName(uint32 nr) const; + const AZStd::string& GetParameterName(size_t nr) const; /** * Get the value for a given parameter. * @param nr The parameter number, which must be in range of [0 .. GetNumParameters()-1]. * @return The value of the parameter, or "" (an empty string) when no value has been specified. */ - const AZStd::string& GetParameterValue(uint32 nr) const; + const AZStd::string& GetParameterValue(size_t nr) const; /** * Find the parameter index for a parameter with a specific name. @@ -229,7 +229,7 @@ namespace MCore * @param paramName The name of the parameter to search for. * @result The index/number of the parameter, or MCORE_INVALIDINDEX32 when no parameter with the specific name has been found. */ - uint32 FindParameterIndex(const char* paramName) const; + size_t FindParameterIndex(const char* paramName) const; /** * Check whether a given parameter has a value specified or not. @@ -278,6 +278,6 @@ namespace MCore AZStd::vector m_parameters; /**< The parameters that have been detected in the command line string. */ // extract the next parameter, starting from a given offset - bool ExtractNextParam(const AZStd::string& paramString, AZStd::string& outParamName, AZStd::string& outParamValue, uint32* inOutStartOffset); + bool ExtractNextParam(const AZStd::string& paramString, AZStd::string& outParamName, AZStd::string& outParamValue, size_t* inOutStartOffset); }; } // namespace MCore From f4442425ed2a0bdcaa6e0b70f995f069e8af8325 Mon Sep 17 00:00:00 2001 From: Chris Burel Date: Mon, 24 May 2021 12:03:52 -0700 Subject: [PATCH 189/803] Convert CommandManagerCallback uint32 -> size_t Signed-off-by: Chris Burel --- .../EMStudioSDK/Source/EMStudioManager.h | 6 +-- .../EMStudioSDK/Source/MainWindow.h | 6 +-- .../ActionHistory/ActionHistoryCallback.cpp | 40 +++++++------------ .../ActionHistory/ActionHistoryCallback.h | 6 +-- .../MCore/Source/CommandManagerCallback.h | 6 +-- 5 files changed, 27 insertions(+), 37 deletions(-) diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioManager.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioManager.h index 62c4b5e115..915c45bc18 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioManager.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioManager.h @@ -146,9 +146,9 @@ namespace EMStudio void OnPostExecuteCommand(MCore::CommandGroup* group, MCore::Command* command, const MCore::CommandLine& commandLine, bool wasSuccess, const AZStd::string& outResult) override; void OnPreExecuteCommandGroup(MCore::CommandGroup* group, bool undo) override { MCORE_UNUSED(group); MCORE_UNUSED(undo); } void OnPostExecuteCommandGroup(MCore::CommandGroup* group, bool wasSuccess) override { MCORE_UNUSED(group); MCORE_UNUSED(wasSuccess); } - void OnAddCommandToHistory(uint32 historyIndex, MCore::CommandGroup* group, MCore::Command* command, const MCore::CommandLine& commandLine) override { MCORE_UNUSED(historyIndex); MCORE_UNUSED(group); MCORE_UNUSED(command); MCORE_UNUSED(commandLine); } - void OnRemoveCommand(uint32 historyIndex) override { MCORE_UNUSED(historyIndex); } - void OnSetCurrentCommand(uint32 index) override { MCORE_UNUSED(index); } + void OnAddCommandToHistory(size_t historyIndex, MCore::CommandGroup* group, MCore::Command* command, const MCore::CommandLine& commandLine) override { MCORE_UNUSED(historyIndex); MCORE_UNUSED(group); MCORE_UNUSED(command); MCORE_UNUSED(commandLine); } + void OnRemoveCommand(size_t historyIndex) override { MCORE_UNUSED(historyIndex); } + void OnSetCurrentCommand(size_t index) override { MCORE_UNUSED(index); } }; EventProcessingCallback* mEventProcessingCallback; }; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindow.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindow.h index 7217259bcb..d49d47452b 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindow.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindow.h @@ -296,9 +296,9 @@ namespace EMStudio void OnPreUndoCommand(MCore::Command* command, const MCore::CommandLine& commandLine); void OnPreExecuteCommandGroup(MCore::CommandGroup* /*group*/, bool /*undo*/) override { } void OnPostExecuteCommandGroup(MCore::CommandGroup* /*group*/, bool /*wasSuccess*/) override { } - void OnAddCommandToHistory(uint32 /*historyIndex*/, MCore::CommandGroup* /*group*/, MCore::Command* /*command*/, const MCore::CommandLine& /*commandLine*/) override { } - void OnRemoveCommand(uint32 /*historyIndex*/) override { } - void OnSetCurrentCommand(uint32 /*index*/) override { } + void OnAddCommandToHistory(size_t /*historyIndex*/, MCore::CommandGroup* /*group*/, MCore::Command* /*command*/, const MCore::CommandLine& /*commandLine*/) override { } + void OnRemoveCommand(size_t /*historyIndex*/) override { } + void OnSetCurrentCommand(size_t /*index*/) override { } void OnShowErrorReport(const AZStd::vector& errors) override; private: AZStd::vector m_skipClearRecorderCommands; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/ActionHistory/ActionHistoryCallback.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/ActionHistory/ActionHistoryCallback.cpp index 0d36f19c5a..e99838b7bb 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/ActionHistory/ActionHistoryCallback.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/ActionHistory/ActionHistoryCallback.cpp @@ -125,7 +125,7 @@ namespace EMStudio } // Add a new item to the history. - void ActionHistoryCallback::OnAddCommandToHistory(uint32 historyIndex, MCore::CommandGroup* group, MCore::Command* command, const MCore::CommandLine& commandLine) + void ActionHistoryCallback::OnAddCommandToHistory(size_t historyIndex, MCore::CommandGroup* group, MCore::Command* command, const MCore::CommandLine& commandLine) { MCORE_UNUSED(commandLine); mTempString = MCore::CommandManager::CommandHistoryEntry::ToString(group, command, mIndex++).c_str(); @@ -135,28 +135,28 @@ namespace EMStudio } // Remove an item from the history. - void ActionHistoryCallback::OnRemoveCommand(uint32 historyIndex) + void ActionHistoryCallback::OnRemoveCommand(size_t historyIndex) { // Remove the item. mIsRemoving = true; - delete mList->takeItem(historyIndex); + delete mList->takeItem(aznumeric_caster(historyIndex)); mIsRemoving = false; } // Set the current command. - void ActionHistoryCallback::OnSetCurrentCommand(uint32 index) + void ActionHistoryCallback::OnSetCurrentCommand(size_t index) { if (mIsRemoving) { return; } - if (index == MCORE_INVALIDINDEX32) + if (index == InvalidIndex) { mList->setCurrentRow(-1); // Darken all history items. - const int numCommands = static_cast(GetCommandManager()->GetNumHistoryItems()); + const int numCommands = mList->count(); for (int i = 0; i < numCommands; ++i) { mList->item(i)->setForeground(m_darkenedBrush); @@ -165,19 +165,19 @@ namespace EMStudio } // get the list of selected items - mList->setCurrentRow(index); + mList->setCurrentRow(aznumeric_caster(index)); // Get the current history index. const uint32 historyIndex = GetCommandManager()->GetHistoryIndex(); - if (historyIndex == MCORE_INVALIDINDEX32) + if (historyIndex == InvalidIndex) { AZStd::string outResult; - const uint32 numRedos = index + 1; - for (uint32 i = 0; i < numRedos; ++i) + const size_t numRedos = index + 1; + for (size_t i = 0; i < numRedos; ++i) { outResult.clear(); const bool result = GetCommandManager()->Redo(outResult); - if (outResult.size() > 0) + if (!outResult.empty()) { if (!result) { @@ -195,7 +195,7 @@ namespace EMStudio // try to undo outResult.clear(); const bool result = GetCommandManager()->Undo(outResult); - if (outResult.size() > 0) + if (!outResult.empty()) { if (!result) { @@ -212,7 +212,7 @@ namespace EMStudio { outResult.clear(); const bool result = GetCommandManager()->Redo(outResult); - if (outResult.size() > 0) + if (!outResult.empty()) { if (!result) { @@ -222,13 +222,6 @@ namespace EMStudio } } - // Darken disabled commands. - const uint32 orgIndex = index; - if (index == MCORE_INVALIDINDEX32) - { - index = 0; - } - const int numCommands = static_cast(GetCommandManager()->GetNumHistoryItems()); for (int i = index; i < numCommands; ++i) { @@ -236,12 +229,9 @@ namespace EMStudio } // Color enabled ones. - if (orgIndex != MCORE_INVALIDINDEX32) + for (int i = 0; i <= static_cast(index); ++i) { - for (int i = 0; i <= static_cast(index); ++i) - { - mList->item(index)->setForeground(m_brush); - } + mList->item(i)->setForeground(m_brush); } } } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/ActionHistory/ActionHistoryCallback.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/ActionHistory/ActionHistoryCallback.h index ba7c5314b1..0433b22d5d 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/ActionHistory/ActionHistoryCallback.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/ActionHistory/ActionHistoryCallback.h @@ -37,11 +37,11 @@ namespace EMStudio void OnPreExecuteCommand(MCore::CommandGroup* group, MCore::Command* command, const MCore::CommandLine& commandLine) override; void OnPostExecuteCommand(MCore::CommandGroup* group, MCore::Command* command, const MCore::CommandLine& commandLine, bool wasSuccess, const AZStd::string& outResult) override; - void OnAddCommandToHistory(uint32 historyIndex, MCore::CommandGroup* group, MCore::Command* command, const MCore::CommandLine& commandLine) override; + void OnAddCommandToHistory(size_t historyIndex, MCore::CommandGroup* group, MCore::Command* command, const MCore::CommandLine& commandLine) override; void OnPreExecuteCommandGroup(MCore::CommandGroup* group, bool undo) override; void OnPostExecuteCommandGroup(MCore::CommandGroup* group, bool wasSuccess) override; - void OnRemoveCommand(uint32 historyIndex) override; - void OnSetCurrentCommand(uint32 index) override; + void OnRemoveCommand(size_t historyIndex) override; + void OnSetCurrentCommand(size_t index) override; private: QListWidget* mList; diff --git a/Gems/EMotionFX/Code/MCore/Source/CommandManagerCallback.h b/Gems/EMotionFX/Code/MCore/Source/CommandManagerCallback.h index e08abde94d..b604465c75 100644 --- a/Gems/EMotionFX/Code/MCore/Source/CommandManagerCallback.h +++ b/Gems/EMotionFX/Code/MCore/Source/CommandManagerCallback.h @@ -83,19 +83,19 @@ namespace MCore * @param command The command that is linked with this history item. * @param commandLine The command line that is linked to this history item. */ - virtual void OnAddCommandToHistory(uint32 historyIndex, CommandGroup* group, Command* command, const CommandLine& commandLine) = 0; + virtual void OnAddCommandToHistory(size_t historyIndex, CommandGroup* group, Command* command, const CommandLine& commandLine) = 0; /** * This callback is executed when a command is being removed from the command history. * @param historyIndex The history index of the command that is being removed. */ - virtual void OnRemoveCommand(uint32 historyIndex) = 0; + virtual void OnRemoveCommand(size_t historyIndex) = 0; /** * This callback is executed when we step back or forth in the command history. * @param index The new history index which will be the current state the system will be in. */ - virtual void OnSetCurrentCommand(uint32 index) = 0; + virtual void OnSetCurrentCommand(size_t index) = 0; /** * This callback is executed before the error array is getting cleared and the interfaces shall show some error reporting window or something similar. From 38217651c5e0ee3a8cde0f09d7ab3b766ed9b04d Mon Sep 17 00:00:00 2001 From: Chris Burel Date: Mon, 24 May 2021 12:03:54 -0700 Subject: [PATCH 190/803] Convert CommandSyntax uint32->size_t Signed-off-by: Chris Burel --- .../Code/MCore/Source/CommandSyntax.cpp | 62 +++++++++---------- .../Code/MCore/Source/CommandSyntax.h | 18 +++--- 2 files changed, 37 insertions(+), 43 deletions(-) diff --git a/Gems/EMotionFX/Code/MCore/Source/CommandSyntax.cpp b/Gems/EMotionFX/Code/MCore/Source/CommandSyntax.cpp index 676366ff8a..fb10da4eb4 100644 --- a/Gems/EMotionFX/Code/MCore/Source/CommandSyntax.cpp +++ b/Gems/EMotionFX/Code/MCore/Source/CommandSyntax.cpp @@ -8,6 +8,7 @@ // include the required headers #include "CommandSyntax.h" +#include #include "LogManager.h" #include "Algorithms.h" #include "StringConversions.h" @@ -15,7 +16,7 @@ namespace MCore { // the constructor - CommandSyntax::CommandSyntax(uint32 numParamsToReserve) + CommandSyntax::CommandSyntax(size_t numParamsToReserve) { ReserveParameters(numParamsToReserve); } @@ -29,7 +30,7 @@ namespace MCore // reserve parameter space - void CommandSyntax::ReserveParameters(uint32 numParamsToReserve) + void CommandSyntax::ReserveParameters(size_t numParamsToReserve) { if (numParamsToReserve > 0) { @@ -65,28 +66,28 @@ namespace MCore // check if this param is a required one or not - bool CommandSyntax::GetParamRequired(uint32 index) const + bool CommandSyntax::GetParamRequired(size_t index) const { return m_parameters[index].mRequired; } // get the parameter name - const char* CommandSyntax::GetParamName(uint32 index) const + const char* CommandSyntax::GetParamName(size_t index) const { return m_parameters[index].mName.c_str(); } // get the parameter description - const char* CommandSyntax::GetParamDescription(uint32 index) const + const char* CommandSyntax::GetParamDescription(size_t index) const { return m_parameters[index].mDescription.c_str(); } // get the parameter type string - const char* CommandSyntax::GetParamTypeString(uint32 index) const + const char* CommandSyntax::GetParamTypeString(size_t index) const { return GetParamTypeString(m_parameters[index]); } @@ -135,29 +136,23 @@ namespace MCore // check if we have a given parameter with a given name in this syntax bool CommandSyntax::CheckIfHasParameter(const char* parameter) const { - return (FindParameterIndex(parameter) != MCORE_INVALIDINDEX32); + return (FindParameterIndex(parameter) != InvalidIndex); } // find the parameter index of a given parameter name - uint32 CommandSyntax::FindParameterIndex(const char* parameter) const + size_t CommandSyntax::FindParameterIndex(const char* parameter) const { - // try to find the parameter with the given name - const size_t numParams = m_parameters.size(); - for (size_t i = 0; i < numParams; ++i) + const auto foundParameter = AZStd::find_if(begin(m_parameters), end(m_parameters), [parameter](const Parameter& p) { - if (AzFramework::StringFunc::Equal(m_parameters[i].mName.c_str(), parameter, false /* no case */)) - { - return static_cast(i); - } - } - - return MCORE_INVALIDINDEX32; + return AzFramework::StringFunc::Equal(p.mName, parameter, false /* no case */); + }); + return foundParameter != end(m_parameters) ? AZStd::distance(begin(m_parameters), foundParameter) : InvalidIndex; } // get the default value for a given parameter - const AZStd::string& CommandSyntax::GetDefaultValue(uint32 index) const + const AZStd::string& CommandSyntax::GetDefaultValue(size_t index) const { return m_parameters[index].mDefaultValue; } @@ -165,8 +160,8 @@ namespace MCore const AZStd::string& CommandSyntax::GetDefaultValue(const char* paramName) const { - const uint32 index = FindParameterIndex(paramName); - if (index != MCORE_INVALIDINDEX32) + const size_t index = FindParameterIndex(paramName); + if (index != InvalidIndex) { return m_parameters[index].mDefaultValue; } @@ -179,8 +174,8 @@ namespace MCore // get the default value for a given parameter name bool CommandSyntax::GetDefaultValue(const char* paramName, AZStd::string& outDefaultValue) const { - const uint32 index = FindParameterIndex(paramName); - if (index == MCORE_INVALIDINDEX32) + const size_t index = FindParameterIndex(paramName); + if (index == InvalidIndex) { return false; } @@ -215,8 +210,8 @@ namespace MCore else { // find the parameter index - const uint32 paramIndex = commandLine.FindParameterIndex(parameter.mName.c_str()); - if (paramIndex != MCORE_INVALIDINDEX32) + const size_t paramIndex = commandLine.FindParameterIndex(parameter.mName.c_str()); + if (paramIndex != InvalidIndex) { const AZStd::string& value = commandLine.GetParameterValue(paramIndex); const AZStd::string& paramName = parameter.mName; @@ -282,13 +277,13 @@ namespace MCore } } } - } // if (paramIndex != MCORE_INVALIDINDEX32) + } // if (paramIndex != InvalidIndex) } } // now add parameters that we specified but that are not defined in the syntax - const uint32 numCommandLineParams = commandLine.GetNumParameters(); - for (uint32 p = 0; p < numCommandLineParams; ++p) + const size_t numCommandLineParams = commandLine.GetNumParameters(); + for (size_t p = 0; p < numCommandLineParams; ++p) { if (CheckIfHasParameter(commandLine.GetParameterName(p).c_str()) == false) { @@ -305,14 +300,13 @@ namespace MCore void CommandSyntax::LogSyntax() { // find the longest command name - uint32 offset = 0; - for (const Parameter& parameter : m_parameters) + size_t offset = AZStd::minmax_element(begin(m_parameters), end(m_parameters), [](const Parameter& left, const Parameter& right) { - offset = MCore::Max(static_cast(parameter.mName.size()), offset); - } + return left.mName.size() < right.mName.size(); + }).second->mName.size(); - uint32 offset2 = offset; - uint32 offset3 = offset; + size_t offset2 = offset; + size_t offset3 = offset; // log the header AZStd::string header = "Name"; diff --git a/Gems/EMotionFX/Code/MCore/Source/CommandSyntax.h b/Gems/EMotionFX/Code/MCore/Source/CommandSyntax.h index a077f0212a..730dd9047a 100644 --- a/Gems/EMotionFX/Code/MCore/Source/CommandSyntax.h +++ b/Gems/EMotionFX/Code/MCore/Source/CommandSyntax.h @@ -63,7 +63,7 @@ namespace MCore * The constructor. * @param numParamsToReserve The amount of parameters to pre-allocate memory for. This can reduce the number of reallocs needed when registering new paramters. */ - CommandSyntax(uint32 numParamsToReserve = 5); + CommandSyntax(size_t numParamsToReserve = 5); /** * The destructor. @@ -74,7 +74,7 @@ namespace MCore * Reserve space for a given number of parameters, to prevent memory reallocs when adding new parameters. * @param numParamsToReserve The number of parameters to reserve space for. */ - void ReserveParameters(uint32 numParamsToReserve); + void ReserveParameters(size_t numParamsToReserve); /** * Add a new optional parameter to this syntax. @@ -99,28 +99,28 @@ namespace MCore * @param index The parameter number to check. * @result Returns true when the parameter is required, or false when it is optional. */ - bool GetParamRequired(uint32 index) const; + bool GetParamRequired(size_t index) const; /** * Get the name of a given parameter. * @param index The parameter number to get the name for. * @result The string containing the name of the parameter. */ - const char* GetParamName(uint32 index) const; + const char* GetParamName(size_t index) const; /** * Get the description of a given parameter. * @param index The parameter number to get the description for. * @result A string containing the description of the parameter. */ - const char* GetParamDescription(uint32 index) const; + const char* GetParamDescription(size_t index) const; /** * Get the default value for a given parameter. * @param index The parameter number to get the default value from. * @result The string containing the default value. */ - const AZStd::string& GetDefaultValue(uint32 index) const; + const AZStd::string& GetDefaultValue(size_t index) const; /** * Get the default value for a parameter with a given name. @@ -141,7 +141,7 @@ namespace MCore * Get the number of parameters registered to this syntax. * @result The number of added/registered parameters. */ - MCORE_INLINE uint32 GetNumParameters() const { return static_cast(m_parameters.size()); } + MCORE_INLINE size_t GetNumParameters() const { return m_parameters.size(); } /** * Get the parameter type string of a given parameter. @@ -149,7 +149,7 @@ namespace MCore * @param index The parameter number to get the type string for. * @result The parameter type string. */ - const char* GetParamTypeString(uint32 index) const; + const char* GetParamTypeString(size_t index) const; const char* GetParamTypeString(const Parameter& parameter) const; /** @@ -189,7 +189,7 @@ namespace MCore * @param parameter The name of the parameter, non-case-sensitive. * @result Returns the index of the parameter, in range of [0..GetNumParameters()-1], or MCORE_INVALIDINDEX32 in case it hasn't been found. */ - uint32 FindParameterIndex(const char* parameter) const; + size_t FindParameterIndex(const char* parameter) const; /** * Log the currently registered syntax using MCore::LogInfo(...). From 24fa61f59e8d71939627742d3406aab703275e6e Mon Sep 17 00:00:00 2001 From: Chris Burel Date: Mon, 24 May 2021 12:03:55 -0700 Subject: [PATCH 191/803] Convert DiskFile to not need uint32 Signed-off-by: Chris Burel --- Gems/EMotionFX/Code/MCore/Source/DiskFile.cpp | 59 ++++++------------- 1 file changed, 19 insertions(+), 40 deletions(-) diff --git a/Gems/EMotionFX/Code/MCore/Source/DiskFile.cpp b/Gems/EMotionFX/Code/MCore/Source/DiskFile.cpp index f1fd5543a8..27e94489e6 100644 --- a/Gems/EMotionFX/Code/MCore/Source/DiskFile.cpp +++ b/Gems/EMotionFX/Code/MCore/Source/DiskFile.cpp @@ -43,47 +43,26 @@ namespace MCore Close(); } - //String fileMode; - char fileMode[4]; - uint32 numChars = 0; - - if (mode == READ) + const char* fileMode = [mode]() -> const char* { - fileMode[0] = 'r'; - numChars = 1; - } // open for reading, file must exist - if (mode == WRITE) - { - fileMode[0] = 'w'; - numChars = 1; - } // open for writing, file will be overwritten if it already exists - if (mode == READWRITE) - { - fileMode[0] = 'r'; - fileMode[1] = '+'; - numChars = 2; - } // open for reading and writing, file must exist - if (mode == READWRITECREATE) - { - fileMode[0] = 'w'; - fileMode[1] = '+'; - numChars = 2; - } // open for reading and writing, file will be overwritten when already exists, or created when it doesn't - if (mode == APPEND) - { - fileMode[0] = 'a'; - numChars = 1; - } // open for writing at the end of the file, file will be created when it doesn't exist - if (mode == READWRITEAPPEND) - { - fileMode[0] = 'a'; - fileMode[1] = '+'; - numChars = 2; - } // open for reading and appending (writing), file will be created if it doesn't exist - - // construct the filemode string - fileMode[numChars++] = 'b'; // open in binary mode - fileMode[numChars++] = '\0'; + switch(mode) + { + case READ: // open for reading, file must exist + return "rb"; + case WRITE: // open for writing, file will be overwritten if it already exists + return "wb"; + case READWRITE: // open for reading and writing, file must exist + return "r+b"; + case READWRITECREATE: // open for reading and writing, file will be overwritten when already exists, or created when it doesn't + return "w+b"; + case APPEND: // open for writing at the end of the file, file will be created when it doesn't exist + return "ab"; + case READWRITEAPPEND: // open for reading and appending (writing), file will be created if it doesn't exist + return "a+b"; + default: + return ""; + } + }(); // set the file mode we used mFileMode = mode; From 5a4b0f5770e7eeae1a5ce5898b5b963b3886cd44 Mon Sep 17 00:00:00 2001 From: Chris Burel Date: Mon, 24 May 2021 12:03:57 -0700 Subject: [PATCH 192/803] Convert Math::Align to a template, so it doesn't depend on the uint32 type Signed-off-by: Chris Burel --- .../Source/AnimGraph/GraphNode.cpp | 40 ++++++++----------- .../Source/AnimGraph/GraphNode.h | 8 ++-- Gems/EMotionFX/Code/MCore/Source/FastMath.h | 15 ++----- Gems/EMotionFX/Code/MCore/Source/FastMath.inl | 15 ++----- 4 files changed, 26 insertions(+), 52 deletions(-) diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GraphNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GraphNode.cpp index 6bf1c4d45a..f0c06bc7e0 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GraphNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GraphNode.cpp @@ -918,8 +918,8 @@ namespace EMStudio { if (mIsCollapsed == false) { - uint32 numPorts = MCore::Max(mInputPorts.size(), mOutputPorts.size()); - uint32 result = (numPorts * 15) + 34; + int32 numPorts = aznumeric_caster(AZStd::max(mInputPorts.size(), mOutputPorts.size())); + int32 result = (numPorts * 15) + 34; return MCore::Math::Align(result, 10); } else @@ -930,33 +930,26 @@ namespace EMStudio // calc the max input port width - uint32 GraphNode::CalcMaxInputPortWidth() const + int GraphNode::CalcMaxInputPortWidth() const { // calc the maximum input port width - uint32 maxInputWidth = 0; - uint32 width; - const uint32 numInputPorts = mInputPorts.size(); - for (uint32 i = 0; i < numInputPorts; ++i) + int maxInputWidth = 0; + for (const NodePort& nodePort : mInputPorts) { - const NodePort* nodePort = &mInputPorts[i]; - width = mPortFontMetrics->horizontalAdvance(nodePort->GetName()); - maxInputWidth = MCore::Max(maxInputWidth, width); + maxInputWidth = AZStd::max(maxInputWidth, mPortFontMetrics->horizontalAdvance(nodePort.GetName())); } return maxInputWidth; } // calculate the max output port width - uint32 GraphNode::CalcMaxOutputPortWidth() const + int GraphNode::CalcMaxOutputPortWidth() const { // calc the maximum output port width - uint32 width; - uint32 maxOutputWidth = 0; - const uint32 numOutputPorts = mOutputPorts.size(); - for (uint32 i = 0; i < numOutputPorts; ++i) + int maxOutputWidth = 0; + for (const NodePort& nodePort : mOutputPorts) { - width = mPortFontMetrics->horizontalAdvance(mOutputPorts[i].GetName()); - maxOutputWidth = MCore::Max(maxOutputWidth, width); + maxOutputWidth = AZStd::max(maxOutputWidth, mPortFontMetrics->horizontalAdvance(nodePort.GetName())); } return maxOutputWidth; @@ -974,18 +967,17 @@ namespace EMStudio mMaxInputWidth = CalcMaxInputPortWidth(); mMaxOutputWidth = CalcMaxOutputPortWidth(); - const uint32 infoWidth = mInfoFontMetrics->horizontalAdvance(mElidedNodeInfo); - const uint32 totalPortWidth = mMaxInputWidth + mMaxOutputWidth + 40 + infoWidth; + const int infoWidth = mInfoFontMetrics->horizontalAdvance(mElidedNodeInfo); + const int totalPortWidth = mMaxInputWidth + mMaxOutputWidth + 40 + infoWidth; // make sure the node is at least 100 units in width - uint32 headerWidth = mHeaderFontMetrics->horizontalAdvance(mElidedName) + 40; - headerWidth = MCore::Max(headerWidth, 100); - - mRequiredWidth = MCore::Max(headerWidth, totalPortWidth); - mNameAndPortsUpdated = true; + const int headerWidth = AZStd::max(mHeaderFontMetrics->horizontalAdvance(mElidedName) + 40, 100); + mRequiredWidth = AZStd::max(headerWidth, totalPortWidth); mRequiredWidth = MCore::Math::Align(mRequiredWidth, 10); + mNameAndPortsUpdated = true; + return mRequiredWidth; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GraphNode.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GraphNode.h index ba6be3de28..061444f9d1 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GraphNode.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GraphNode.h @@ -150,8 +150,8 @@ namespace EMStudio virtual int32 CalcRequiredHeight() const; virtual int32 CalcRequiredWidth(); - virtual uint32 CalcMaxInputPortWidth() const; - virtual uint32 CalcMaxOutputPortWidth() const; + virtual int CalcMaxInputPortWidth() const; + virtual int CalcMaxOutputPortWidth() const; bool GetIsInside(const QPoint& globalPoint) const; bool GetIsSelected() const; @@ -273,8 +273,8 @@ namespace EMStudio bool mHasVisualGraph; bool mHasVisualOutputPorts; - uint32 mMaxInputWidth; // will be calculated automatically in CalcRequiredWidth() - uint32 mMaxOutputWidth; // will be calculated automatically in CalcRequiredWidth() + int mMaxInputWidth; // will be calculated automatically in CalcRequiredWidth() + int mMaxOutputWidth; // will be calculated automatically in CalcRequiredWidth() // has child node indicator QPolygonF mSubstPoly; diff --git a/Gems/EMotionFX/Code/MCore/Source/FastMath.h b/Gems/EMotionFX/Code/MCore/Source/FastMath.h index 22637d5b5b..e1bac33306 100644 --- a/Gems/EMotionFX/Code/MCore/Source/FastMath.h +++ b/Gems/EMotionFX/Code/MCore/Source/FastMath.h @@ -300,24 +300,15 @@ namespace MCore static MCORE_INLINE float SafeFMod(float x, float y); /** - * Align a given uint32 value to a given alignment. - * For example when the input value of inOutValue contains a value of 50, and the alignment is set to 16, then the - * value is modified to be 64. - * @param inOutValue The input value to align. This will also be the output, so the value is modified. - * @param alignment The alignment to use, for example 16, 32 or 64, etc. - */ - static MCORE_INLINE void Align(uint32* inOutValue, uint32 alignment); - - - /** - * Align a given uint32 value to a given alignment. + * Align a given size_t value to a given alignment. * For example when the input value of inOutValue contains a value of 50, and the alignment is set to 16, then the * aligned return value would be 64. * @param inValue The input value, which would be 50 in our above example. * @param alignment The alignment touse, which would be 16 in our above example. * @result The value returned is the input value aligned to the given alignment. In our example it would return a value of 64. */ - static MCORE_INLINE uint32 Align(uint32 inValue, uint32 alignment); + template + static MCORE_INLINE T Align(T inValue, T alignment); /** * Multiply a float value by its sign. diff --git a/Gems/EMotionFX/Code/MCore/Source/FastMath.inl b/Gems/EMotionFX/Code/MCore/Source/FastMath.inl index 31365761b9..d672d59985 100644 --- a/Gems/EMotionFX/Code/MCore/Source/FastMath.inl +++ b/Gems/EMotionFX/Code/MCore/Source/FastMath.inl @@ -310,19 +310,10 @@ MCORE_INLINE float Math::FastSqrt(float x) // align a value -MCORE_INLINE void Math::Align(uint32* inOutValue, uint32 alignment) +template +MCORE_INLINE T Math::Align(T inValue, T alignment) { - const uint32 modValue = *inOutValue % alignment; - if (modValue > 0) - { - *inOutValue += alignment - modValue; - } -} - -// align a value -MCORE_INLINE uint32 Math::Align(uint32 inValue, uint32 alignment) -{ - const uint32 modValue = inValue % alignment; + const T modValue = inValue % alignment; if (modValue > 0) { return inValue + (alignment - modValue); From ce139d6ae96c795349a624d4cb8fc51d1b8bf627 Mon Sep 17 00:00:00 2001 From: Chris Burel Date: Mon, 24 May 2021 12:03:59 -0700 Subject: [PATCH 193/803] Remove unused HashFunctions functions Signed-off-by: Chris Burel --- .../Code/MCore/Source/HashFunctions.h | 80 ------------------- Gems/EMotionFX/Code/MCore/mcore_files.cmake | 1 - 2 files changed, 81 deletions(-) delete mode 100644 Gems/EMotionFX/Code/MCore/Source/HashFunctions.h diff --git a/Gems/EMotionFX/Code/MCore/Source/HashFunctions.h b/Gems/EMotionFX/Code/MCore/Source/HashFunctions.h deleted file mode 100644 index 66f4a7bf73..0000000000 --- a/Gems/EMotionFX/Code/MCore/Source/HashFunctions.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -#pragma once - -// include required headers -#include "StandardHeaders.h" -#include "Vector.h" -#include - - -namespace MCore -{ - /** - * The hash function. - * The hash function must return an non-negative (so positive) integer, based on a key value. - * Use partial template specialization to implement hashing functions for different data types. - */ - template - MCORE_INLINE uint32 Hash(const Key& key) - { - MCORE_ASSERT(false); // you should implement this function - MCORE_UNUSED(key); - //#pragma message (MCORE_ERROR "You should implement the Hash function for some specific Key type that you used") - return 0; - } - - - template<> - MCORE_INLINE uint32 Hash(const AZStd::string& key) - { - uint32 result = 0; - const size_t length = key.size(); - for (size_t i = 0; i < length; ++i) - { - result = (result << 4) + key[i]; - const uint32 g = result & 0xf0000000L; - if (g != 0) - { - result ^= g >> 24; - } - result &= ~g; - } - - return result; - } - - - template<> - MCORE_INLINE uint32 Hash(const int32& key) - { - return (uint32)Math::Abs(static_cast(key)); - } - - - template<> - MCORE_INLINE uint32 Hash(const uint32& key) - { - return key; - } - - - template<> - MCORE_INLINE uint32 Hash(const float& key) - { - return (uint32)Math::Abs(key * 12345.0f); - } - - - template<> - MCORE_INLINE uint32 Hash(const AZ::Vector3& key) - { - return (uint32)Math::Abs(key.GetX() * 101.0f + key.GetY() * 1002.0f + key.GetZ() * 10003.0f); - } -} // namespace MCore diff --git a/Gems/EMotionFX/Code/MCore/mcore_files.cmake b/Gems/EMotionFX/Code/MCore/mcore_files.cmake index 6352bac4ba..47b35e004b 100644 --- a/Gems/EMotionFX/Code/MCore/mcore_files.cmake +++ b/Gems/EMotionFX/Code/MCore/mcore_files.cmake @@ -76,7 +76,6 @@ set(FILES Source/File.h Source/FileSystem.cpp Source/FileSystem.h - Source/HashFunctions.h Source/IDGenerator.cpp Source/IDGenerator.h Source/LogManager.cpp From 387a1faf233b7e24c453cde46078cb540c38b749 Mon Sep 17 00:00:00 2001 From: Chris Burel Date: Mon, 24 May 2021 12:04:00 -0700 Subject: [PATCH 194/803] Convert IDGenerator uint32 -> size_t Signed-off-by: Chris Burel --- Gems/EMotionFX/Code/MCore/Source/IDGenerator.cpp | 8 ++++---- Gems/EMotionFX/Code/MCore/Source/IDGenerator.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Gems/EMotionFX/Code/MCore/Source/IDGenerator.cpp b/Gems/EMotionFX/Code/MCore/Source/IDGenerator.cpp index 33dcf1e74d..7e4ff9b16e 100644 --- a/Gems/EMotionFX/Code/MCore/Source/IDGenerator.cpp +++ b/Gems/EMotionFX/Code/MCore/Source/IDGenerator.cpp @@ -15,8 +15,8 @@ namespace MCore { // constructor IDGenerator::IDGenerator() + : mNextID{0} { - mNextID.SetValue(0); } @@ -27,10 +27,10 @@ namespace MCore // get a unique id - uint32 IDGenerator::GenerateID() + size_t IDGenerator::GenerateID() { - const uint32 result = mNextID.Increment(); - MCORE_ASSERT(result != MCORE_INVALIDINDEX32); // reached the limit + const size_t result = mNextID++; + MCORE_ASSERT(result != InvalidIndex); // reached the limit return result; } } // namespace MCore diff --git a/Gems/EMotionFX/Code/MCore/Source/IDGenerator.h b/Gems/EMotionFX/Code/MCore/Source/IDGenerator.h index 04f43a4995..1418b7d3d1 100644 --- a/Gems/EMotionFX/Code/MCore/Source/IDGenerator.h +++ b/Gems/EMotionFX/Code/MCore/Source/IDGenerator.h @@ -28,10 +28,10 @@ namespace MCore * This is thread safe. * @return The unique id. */ - uint32 GenerateID(); + size_t GenerateID(); private: - AtomicUInt32 mNextID; /**< The id used for the next GenerateID() call. */ + AZStd::atomic mNextID; /**< The id used for the next GenerateID() call. */ /** * Default constructor. From 916b3a94d6b167b36983b05353daabf64078d743 Mon Sep 17 00:00:00 2001 From: Chris Burel Date: Mon, 24 May 2021 12:04:02 -0700 Subject: [PATCH 195/803] Convert MCoreCommandManager uint32 -> size_t Signed-off-by: Chris Burel --- .../Code/MCore/Source/MCoreCommandManager.cpp | 44 +++++++++---------- .../Code/MCore/Source/MCoreCommandManager.h | 16 +++---- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/Gems/EMotionFX/Code/MCore/Source/MCoreCommandManager.cpp b/Gems/EMotionFX/Code/MCore/Source/MCoreCommandManager.cpp index cd64af15c6..657c5e0303 100644 --- a/Gems/EMotionFX/Code/MCore/Source/MCoreCommandManager.cpp +++ b/Gems/EMotionFX/Code/MCore/Source/MCoreCommandManager.cpp @@ -15,7 +15,7 @@ namespace MCore { - CommandManager::CommandHistoryEntry::CommandHistoryEntry(CommandGroup* group, Command* command, const CommandLine& parameters, AZ::u32 historyItemNr) + CommandManager::CommandHistoryEntry::CommandHistoryEntry(CommandGroup* group, Command* command, const CommandLine& parameters, size_t historyItemNr) { mCommandGroup = group; mExecutedCommand = command; @@ -28,15 +28,15 @@ namespace MCore // remark: the mCommand and mCommandGroup are automatically deleted after popping from the history } - AZStd::string CommandManager::CommandHistoryEntry::ToString(CommandGroup* group, Command* command, AZ::u32 historyItemNr) + AZStd::string CommandManager::CommandHistoryEntry::ToString(CommandGroup* group, Command* command, size_t historyItemNr) { if (group) { - return AZStd::string::format("%.3d - %s", historyItemNr, group->GetGroupName()); + return AZStd::string::format("%.3zu - %s", historyItemNr, group->GetGroupName()); } else if (command) { - return AZStd::string::format("%.3d - %s", historyItemNr, command->GetHistoryName()); + return AZStd::string::format("%.3zu - %s", historyItemNr, command->GetHistoryName()); } return ""; @@ -88,7 +88,7 @@ namespace MCore if (mCommandHistory.size() >= mMaxHistoryEntries) { PopCommandHistory(); - mHistoryIndex = static_cast(mCommandHistory.size()) - 1; + mHistoryIndex = static_cast(mCommandHistory.size()) - 1; } if (!mCommandHistory.empty()) @@ -137,7 +137,7 @@ namespace MCore if (mCommandHistory.size() >= mMaxHistoryEntries) { PopCommandHistory(); - mHistoryIndex = static_cast(mCommandHistory.size()) - 1; + mHistoryIndex = static_cast(mCommandHistory.size()) - 1; } // remove unneeded commands @@ -540,7 +540,7 @@ namespace MCore break; } } - if (static_cast(i) < relativeIndex) + if (static_cast(i) < relativeIndex) { MCore::LogError("Execution of command '%s' failed, command trying to access results from %d commands back, but there are only %d", commandString.c_str(), relativeIndex, i - 1); hadError = true; @@ -689,11 +689,11 @@ namespace MCore void CommandManager::ExecuteUndoCallbacks(Command* command, const CommandLine& parameters, bool preUndo) { Command* orgCommand = command->GetOriginalCommand(); - uint32 numFailed = 0; + size_t numFailed = 0; // get the number of callbacks and iterate through them - const uint32 numCommandCallbacks = orgCommand->GetNumCallbacks(); - for (uint32 i = 0; i < numCommandCallbacks; ++i) + const size_t numCommandCallbacks = orgCommand->GetNumCallbacks(); + for (size_t i = 0; i < numCommandCallbacks; ++i) { // get the current callback Command::Callback* callback = orgCommand->GetCallback(i); @@ -734,11 +734,11 @@ namespace MCore void CommandManager::ExecuteCommandCallbacks(Command* command, const CommandLine& parameters, bool preCommand) { Command* orgCommand = command->GetOriginalCommand(); - uint32 numFailed = 0; + size_t numFailed = 0; // get the number of callbacks and iterate through them - const uint32 numCommandCallbacks = orgCommand->GetNumCallbacks(); - for (uint32 i = 0; i < numCommandCallbacks; ++i) + const size_t numCommandCallbacks = orgCommand->GetNumCallbacks(); + for (size_t i = 0; i < numCommandCallbacks; ++i) { // get the current callback Command::Callback* callback = orgCommand->GetCallback(i); @@ -799,8 +799,8 @@ namespace MCore managerCallback->OnPreExecuteCommandGroup(group, true); } - const int32 numCommands = static_cast(group->GetNumCommands() - 1); - for (int32 g = numCommands; g >= 0; --g) + const ptrdiff_t numCommands = static_cast(group->GetNumCommands()) - 1; + for (ptrdiff_t g = numCommands; g >= 0; --g) { Command* groupCommand = group->GetCommand(g); if (groupCommand == nullptr) @@ -1130,8 +1130,8 @@ namespace MCore // print the command history entries for (size_t i = 0; i < numHistoryEntries; ++i) { - AZStd::string text = AZStd::string::format("%.3zu: name='%s', num parameters=%u", i, mCommandHistory[i].mExecutedCommand->GetName(), mCommandHistory[i].mParameters.GetNumParameters()); - if (i == (uint32)mHistoryIndex) + AZStd::string text = AZStd::string::format("%.3zu: name='%s', num parameters=%zu", i, mCommandHistory[i].mExecutedCommand->GetName(), mCommandHistory[i].mParameters.GetNumParameters()); + if (i == mHistoryIndex) { LogDetailedInfo("-> %s", text.c_str()); } @@ -1180,15 +1180,15 @@ namespace MCore } // set the max num history items - void CommandManager::SetMaxHistoryItems(uint32 maxItems) + void CommandManager::SetMaxHistoryItems(size_t maxItems) { - maxItems = AZStd::max(1u, maxItems); + maxItems = AZStd::max(size_t{1}, maxItems); mMaxHistoryEntries = maxItems; while (mCommandHistory.size() > mMaxHistoryEntries) { PopCommandHistory(); - mHistoryIndex = static_cast(mCommandHistory.size()) - 1; + mHistoryIndex = static_cast(mCommandHistory.size()) - 1; } } @@ -1197,7 +1197,7 @@ namespace MCore return mMaxHistoryEntries; } - int32 CommandManager::GetHistoryIndex() const + ptrdiff_t CommandManager::GetHistoryIndex() const { return mHistoryIndex; } @@ -1229,7 +1229,7 @@ namespace MCore mHistoryIndex = -1; } - const CommandLine& CommandManager::GetHistoryCommandLine(uint32 historyIndex) const + const CommandLine& CommandManager::GetHistoryCommandLine(size_t historyIndex) const { return mCommandHistory[historyIndex].mParameters; } diff --git a/Gems/EMotionFX/Code/MCore/Source/MCoreCommandManager.h b/Gems/EMotionFX/Code/MCore/Source/MCoreCommandManager.h index 3a6aaf33c6..566c3d17fd 100644 --- a/Gems/EMotionFX/Code/MCore/Source/MCoreCommandManager.h +++ b/Gems/EMotionFX/Code/MCore/Source/MCoreCommandManager.h @@ -48,17 +48,17 @@ namespace MCore * @param command The command instance that has been created at execution time. When set to nullptr it will assume it is a group, and it will use the group you specified. * @param parameters The command arguments. */ - CommandHistoryEntry(CommandGroup* group, Command* command, const CommandLine& parameters, AZ::u32 historyItemNr); + CommandHistoryEntry(CommandGroup* group, Command* command, const CommandLine& parameters, size_t historyItemNr); ~CommandHistoryEntry(); - static AZStd::string ToString(CommandGroup* group, Command* command, AZ::u32 historyItemNr); + static AZStd::string ToString(CommandGroup* group, Command* command, size_t historyItemNr); AZStd::string ToString() const; CommandGroup* mCommandGroup; /**< A pointer to the command group, or nullptr when no group is used (in that case it uses a single command). */ Command* mExecutedCommand; /**< A pointer to the command object, or nullptr when no command is used (in that case it uses a group). */ CommandLine mParameters; /**< The used command arguments, unused in case no command is used (in that case it uses a group). */ - AZ::u32 m_historyItemNr; /**< The global history item number. This number will neither change depending on the size of the history queue nor with undo/redo. */ + size_t m_historyItemNr; /**< The global history item number. This number will neither change depending on the size of the history queue nor with undo/redo. */ }; @@ -183,7 +183,7 @@ namespace MCore * On default this value is 100. This means it will remember the last 100 executed commands, which can then be undo-ed and redo-ed. * @param maxItems The maximum number of items to remember. */ - void SetMaxHistoryItems(uint32 maxItems); + void SetMaxHistoryItems(size_t maxItems); /** * Get the maximum number of history items that the manager will remember. @@ -197,7 +197,7 @@ namespace MCore * This value will be in range of [0..GetMaxHistoryItems()-1]. * @result The current history index. */ - int32 GetHistoryIndex() const; + ptrdiff_t GetHistoryIndex() const; /** * Get the number of history items stored. @@ -225,7 +225,7 @@ namespace MCore * @param historyIndex The history index number, which must be in range of [0..GetNumHistoryItems()-1]. * @result A reference to the command line that was used when executing this command. */ - const CommandLine& GetHistoryCommandLine(uint32 historyIndex) const; + const CommandLine& GetHistoryCommandLine(size_t historyIndex) const; /** * Get the total number of registered commands. @@ -302,8 +302,8 @@ namespace MCore AZStd::vector mErrors; /**< List of errors that happened during command execution. */ AZStd::vector mCommands; /**< A flat array of registered commands, for easy traversal. */ size_t mMaxHistoryEntries; /**< The maximum remembered commands in the command history. */ - int32 mHistoryIndex; /**< The command history iterator. The current position in the undo/redo history. */ - AZ::u32 m_totalNumHistoryItems; /**< The number of history items since the application start. This number will neither change depending on the size of the history queue nor with undo/redo. */ + ptrdiff_t mHistoryIndex; /**< The command history iterator. The current position in the undo/redo history. */ + size_t m_totalNumHistoryItems; /**< The number of history items since the application start. This number will neither change depending on the size of the history queue nor with undo/redo. */ int m_commandsInExecution; /**< The number of commands currently in execution. */ /** From 88a9a4fb5d6037abf8804ddf94442a2e44b23221 Mon Sep 17 00:00:00 2001 From: Chris Burel Date: Mon, 24 May 2021 12:04:03 -0700 Subject: [PATCH 196/803] Correct signature of MCore::MemSet to match memset Signed-off-by: Chris Burel --- Gems/EMotionFX/Code/MCore/Source/MemoryManager.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/EMotionFX/Code/MCore/Source/MemoryManager.h b/Gems/EMotionFX/Code/MCore/Source/MemoryManager.h index 84db9ed20c..7129dffe24 100644 --- a/Gems/EMotionFX/Code/MCore/Source/MemoryManager.h +++ b/Gems/EMotionFX/Code/MCore/Source/MemoryManager.h @@ -133,7 +133,7 @@ public: * @param numBytes The number of bytes to fill. * @result The address as specified in the first parameter. */ - MCORE_INLINE void* MemSet(void* address, const uint32 value, size_t numBytes) + MCORE_INLINE void* MemSet(void* address, const int value, size_t numBytes) { return memset(address, value, numBytes); } From 404ab514397e5ed704aca0b13b326a2ae489608d Mon Sep 17 00:00:00 2001 From: Chris Burel Date: Mon, 24 May 2021 12:04:06 -0700 Subject: [PATCH 197/803] uint32 -> size_t Signed-off-by: Chris Burel --- Gems/EMotionFX/Code/MCore/Source/ReflectionSerializer.cpp | 4 ++-- Gems/EMotionFX/Code/MCore/Source/StringConversions.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gems/EMotionFX/Code/MCore/Source/ReflectionSerializer.cpp b/Gems/EMotionFX/Code/MCore/Source/ReflectionSerializer.cpp index 7dbbfcdcd6..b13260b01f 100644 --- a/Gems/EMotionFX/Code/MCore/Source/ReflectionSerializer.cpp +++ b/Gems/EMotionFX/Code/MCore/Source/ReflectionSerializer.cpp @@ -363,8 +363,8 @@ namespace MCore bool ReflectionSerializer::Deserialize(const AZ::TypeId& classTypeId, void* classPtr, const MCore::CommandLine& sourceCommandLine) { bool someError = false; - const uint32 numParameters = sourceCommandLine.GetNumParameters(); - for (uint32 i = 0; i < numParameters; ++i) + const size_t numParameters = sourceCommandLine.GetNumParameters(); + for (size_t i = 0; i < numParameters; ++i) { someError |= !DeserializeIntoMember(classTypeId, classPtr, sourceCommandLine.GetParameterName(i).c_str(), sourceCommandLine.GetParameterValue(i).c_str()); } diff --git a/Gems/EMotionFX/Code/MCore/Source/StringConversions.cpp b/Gems/EMotionFX/Code/MCore/Source/StringConversions.cpp index 249ba8e77d..c6b84a9e04 100644 --- a/Gems/EMotionFX/Code/MCore/Source/StringConversions.cpp +++ b/Gems/EMotionFX/Code/MCore/Source/StringConversions.cpp @@ -46,7 +46,7 @@ namespace MCore AzFramework::StringFunc::TrimWhiteSpace(nameWithoutLastDigits, false /* leading */, true /* trailing */); // generate the unique name - uint32 nameIndex = 0; + size_t nameIndex = 0; AZStd::string uniqueName = nameWithoutLastDigits + "0"; while (validationFunction(uniqueName) == false) { From 85c96c75969ec85a06e30d0defb05a8923bfbe99 Mon Sep 17 00:00:00 2001 From: Chris Burel Date: Mon, 24 May 2021 12:04:08 -0700 Subject: [PATCH 198/803] Remove `static_cast` from MemoryFile Signed-off-by: Chris Burel --- Gems/EMotionFX/Code/MCore/Source/MemoryFile.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Gems/EMotionFX/Code/MCore/Source/MemoryFile.cpp b/Gems/EMotionFX/Code/MCore/Source/MemoryFile.cpp index 811dcbde42..09021a105a 100644 --- a/Gems/EMotionFX/Code/MCore/Source/MemoryFile.cpp +++ b/Gems/EMotionFX/Code/MCore/Source/MemoryFile.cpp @@ -172,9 +172,9 @@ namespace MCore { const size_t numRead = length - ((mCurrentPos + length) - ((uint8*)mMemoryStart + mLength)); MCore::MemCopy(data, mCurrentPos, numRead); - Forward(static_cast(numRead)); + Forward(numRead); MCore::LogWarning("MCore::MemoryFile::Read() - We can only read %d bytes of the %d bytes requested, as we are reading past the end of the memory file!", numRead, length); - return static_cast(numRead); + return numRead; } MCore::MemCopy(data, mCurrentPos, length); @@ -186,7 +186,7 @@ namespace MCore // returns the filesize in bytes size_t MemoryFile::GetFileSize() const { - return static_cast(mUsedLength); // TODO: convert to size_t later + return mUsedLength; } From 0999a7f6e4b28982b692bba6d98765937f3f8a89 Mon Sep 17 00:00:00 2001 From: Scott Romero <24445312+AMZN-ScottR@users.noreply.github.com> Date: Mon, 9 Aug 2021 08:48:51 -0700 Subject: [PATCH 199/803] [development] s3 upload script now replicates directory structure relative to search root (#2947) Previously the script was using the full local path as the artifact key when uploading to s3. This was causing the installer artifacts to be uploaded incorrectly and non-functional for normal use. Signed-off-by: AMZN-ScottR 24445312+AMZN-ScottR@users.noreply.github.com --- scripts/build/tools/upload_to_s3.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/scripts/build/tools/upload_to_s3.py b/scripts/build/tools/upload_to_s3.py index 57ac9c4e76..b80170df52 100755 --- a/scripts/build/tools/upload_to_s3.py +++ b/scripts/build/tools/upload_to_s3.py @@ -25,6 +25,7 @@ import re import json import time import boto3 +import pathlib from optparse import OptionParser @@ -97,8 +98,15 @@ def get_files_to_upload(base_dir, regex, search_subdirectories): return regex_files_to_upload -def s3_upload_file(client, file, bucket, key_prefix=None, extra_args=None, max_retry=1): - key = file if key_prefix is None else f'{key_prefix}/{file}' +def s3_upload_file(client, base_dir, file, bucket, key_prefix=None, extra_args=None, max_retry=1): + try: + # replicate the local folder structure relative to search root in the bucket path + s3_file_path = pathlib.Path(file).relative_to(base_dir).as_posix() + except ValueError as err: + print(f'Unexpected file error: {err}') + return False + + key = s3_file_path if key_prefix is None else f'{key_prefix}/{s3_file_path}' error_message = None for x in range(max_retry): @@ -140,7 +148,7 @@ if __name__ == "__main__": failure = [] success = [] for file in files_to_upload: - if not s3_upload_file(client, file, options.bucket, options.key_prefix, extra_args, 2): + if not s3_upload_file(client, options.base_dir, file, options.bucket, options.key_prefix, extra_args, 2): failure.append(file) else: success.append(file) From 86d0ba7e6b2b16f9136f4e8586e0f0e7f87ba6bb Mon Sep 17 00:00:00 2001 From: John Jones-Steele Date: Mon, 9 Aug 2021 17:00:53 +0100 Subject: [PATCH 200/803] Minor changes to tests Signed-off-by: John Jones-Steele --- .../Tests/FloatToStringConversionTests.cpp | 48 +++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Tests/FloatToStringConversionTests.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Tests/FloatToStringConversionTests.cpp index 21db675324..39593a1c58 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Tests/FloatToStringConversionTests.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Tests/FloatToStringConversionTests.cpp @@ -13,94 +13,94 @@ TEST(AzQtComponents, FloatToString_Truncate2Decimals) { - QLocale testLocal(QLocale::English, QLocale::UnitedStates); + QLocale testLocale(QLocale::English, QLocale::UnitedStates); const bool showThousandsSeparator = false; const int numDecimalPlaces = 2; - EXPECT_EQ(AzQtComponents::toString(0.1234, numDecimalPlaces, testLocal, showThousandsSeparator), "0.12"); + EXPECT_EQ(AzQtComponents::toString(0.1234, numDecimalPlaces, testLocale, showThousandsSeparator), "0.12"); } TEST(AzQtComponents, FloatToString_AllZerosButOne) { - QLocale testLocal(QLocale::English, QLocale::UnitedStates); + QLocale testLocale(QLocale::English, QLocale::UnitedStates); const bool showThousandsSeparator = false; int numDecimalPlaces = 2; - EXPECT_EQ(AzQtComponents::toString(1.0000, numDecimalPlaces, testLocal, showThousandsSeparator), "1.0"); + EXPECT_EQ(AzQtComponents::toString(1.0000, numDecimalPlaces, testLocale, showThousandsSeparator), "1.0"); } TEST(AzQtComponents, FloatToString_TruncateAllZerosButOne) { - QLocale testLocal(QLocale::English, QLocale::UnitedStates); + QLocale testLocale(QLocale::English, QLocale::UnitedStates); const bool showThousandsSeparator = false; int numDecimalPlaces = 2; - EXPECT_EQ(AzQtComponents::toString(1.0001, numDecimalPlaces, testLocal, showThousandsSeparator), "1.0"); + EXPECT_EQ(AzQtComponents::toString(1.0001, numDecimalPlaces, testLocale, showThousandsSeparator), "1.0"); } TEST(AzQtComponents, FloatToString_TruncateNotRound) { - QLocale testLocal(QLocale::English, QLocale::UnitedStates); + QLocale testLocale(QLocale::English, QLocale::UnitedStates); const bool showThousandsSeparator = false; int numDecimalPlaces = 3; - EXPECT_EQ(AzQtComponents::toString(0.1236, numDecimalPlaces, testLocal, showThousandsSeparator), "0.123"); + EXPECT_EQ(AzQtComponents::toString(0.1236, numDecimalPlaces, testLocale, showThousandsSeparator), "0.123"); } TEST(AzQtComponents, FloatToString_TruncateShowThousandsSeparatorTruncateNoRound) { - QLocale testLocal(QLocale::English, QLocale::UnitedStates); + QLocale testLocale(QLocale::English, QLocale::UnitedStates); const bool showThousandsSeparator = true; int numDecimalPlaces = 3; - EXPECT_EQ(AzQtComponents::toString(1000.1236, numDecimalPlaces, testLocal, showThousandsSeparator), "1,000.123"); + EXPECT_EQ(AzQtComponents::toString(1000.1236, numDecimalPlaces, testLocale, showThousandsSeparator), "1,000.123"); } TEST(AzQtComponents, FloatToString_TruncateShowThousandsSeparatorOnlyOneDecimal) { - QLocale testLocal(QLocale::English, QLocale::UnitedStates); + QLocale testLocale(QLocale::English, QLocale::UnitedStates); const bool showThousandsSeparator = true; int numDecimalPlaces = 2; - EXPECT_EQ(AzQtComponents::toString(1000.000, numDecimalPlaces, testLocal, showThousandsSeparator), "1,000.0"); + EXPECT_EQ(AzQtComponents::toString(1000.000, numDecimalPlaces, testLocale, showThousandsSeparator), "1,000.0"); } TEST(AzQtComponents, FloatToString_Truncate2DecimalsWithLocale) { - QLocale testLocal{ QLocale() }; + QLocale testLocale{ QLocale() }; const bool showThousandsSeparator = false; const int numDecimalPlaces = 2; - QString testString = "0" + QString(testLocal.decimalPoint()) + "12"; - EXPECT_EQ(testString, AzQtComponents::toString(0.1234, numDecimalPlaces, testLocal, showThousandsSeparator)); + QString testString = "0" + QString(testLocale.decimalPoint()) + "12"; + EXPECT_EQ(testString, AzQtComponents::toString(0.1234, numDecimalPlaces, testLocale, showThousandsSeparator)); } TEST(AzQtComponents, FloatToString_AllZerosButOneWithLocale) { - QLocale testLocal{ QLocale() }; + QLocale testLocale{ QLocale() }; const bool showThousandsSeparator = false; const int numDecimalPlaces = 2; - QString testString = "1" + QString(testLocal.decimalPoint()) + "0"; - EXPECT_EQ(testString, AzQtComponents::toString(1.0000, numDecimalPlaces, testLocal, showThousandsSeparator)); + QString testString = "1" + QString(testLocale.decimalPoint()) + "0"; + EXPECT_EQ(testString, AzQtComponents::toString(1.0000, numDecimalPlaces, testLocale, showThousandsSeparator)); } TEST(AzQtComponents, FloatToString_TruncateShowThousandsSeparatorTruncateNoRoundWithLocale) { - QLocale testLocal{ QLocale() }; + QLocale testLocale{ QLocale() }; const bool showThousandsSeparator = true; const int numDecimalPlaces = 3; - QString testString = "1" + QString(testLocal.groupSeparator()) + "000" + QString(testLocal.decimalPoint()) + "123"; - EXPECT_EQ(testString, AzQtComponents::toString(1000.1236, numDecimalPlaces, testLocal, showThousandsSeparator)); + QString testString = "1" + QString(testLocale.groupSeparator()) + "000" + QString(testLocale.decimalPoint()) + "123"; + EXPECT_EQ(testString, AzQtComponents::toString(1000.1236, numDecimalPlaces, testLocale, showThousandsSeparator)); } TEST(AzQtComponents, FloatToString_TruncateShowThousandsSeparatorOnlyOneDecimalWithLocale) { - QLocale testLocal{ QLocale() }; + QLocale testLocale{ QLocale() }; const bool showThousandsSeparator = true; int numDecimalPlaces = 2; - QString testString = "1" + QString(testLocal.groupSeparator()) + "000" + QString(testLocal.decimalPoint()) + "0"; - EXPECT_EQ(testString, AzQtComponents::toString(1000.000, numDecimalPlaces, testLocal, showThousandsSeparator)); + QString testString = "1" + QString(testLocale.groupSeparator()) + "000" + QString(testLocale.decimalPoint()) + "0"; + EXPECT_EQ(testString, AzQtComponents::toString(1000.000, numDecimalPlaces, testLocale, showThousandsSeparator)); } From 382ca192c8f729b8038ca4ccd40b89aa1c425e80 Mon Sep 17 00:00:00 2001 From: Chris Burel Date: Mon, 24 May 2021 12:04:10 -0700 Subject: [PATCH 201/803] Fix Node/Skeleton uint32->size_t Signed-off-by: Chris Burel --- .../Source/AnimGraphTriggerActionCommands.cpp | 16 +- .../Source/MotionEventCommands.cpp | 6 +- .../ExporterLib/Exporter/EndianConversion.cpp | 5 + .../Exporters/ExporterLib/Exporter/Exporter.h | 3 +- .../ExporterLib/Exporter/FileHeaderExport.cpp | 12 +- .../Exporter/MorphTargetExport.cpp | 2 +- .../Rendering/OpenGL2/Source/GLActor.cpp | 22 +- .../Rendering/OpenGL2/Source/Material.h | 6 +- .../EMotionFX/Code/EMotionFX/Source/Actor.cpp | 323 +++++++++--------- Gems/EMotionFX/Code/EMotionFX/Source/Actor.h | 54 +-- .../Code/EMotionFX/Source/ActorInstance.cpp | 8 +- .../Source/BlendTreeBlend2AdditiveNode.cpp | 2 +- .../Source/BlendTreeBlend2LegacyNode.cpp | 2 +- .../EMotionFX/Source/BlendTreeBlend2Node.cpp | 2 +- .../EMotionFX/Source/BlendTreeFootIKNode.cpp | 2 +- .../EMotionFX/Source/BlendTreeFootIKNode.h | 4 +- .../EMotionFX/Source/DualQuatSkinDeformer.h | 2 +- .../Source/Importer/ChunkProcessors.cpp | 24 +- Gems/EMotionFX/Code/EMotionFX/Source/Mesh.cpp | 2 +- Gems/EMotionFX/Code/EMotionFX/Source/Mesh.h | 4 +- Gems/EMotionFX/Code/EMotionFX/Source/Mesh.inl | 2 +- Gems/EMotionFX/Code/EMotionFX/Source/Node.cpp | 236 ++++--------- Gems/EMotionFX/Code/EMotionFX/Source/Node.h | 58 ++-- .../Code/EMotionFX/Source/NodeAttribute.h | 2 +- Gems/EMotionFX/Code/EMotionFX/Source/Pose.cpp | 34 +- Gems/EMotionFX/Code/EMotionFX/Source/Pose.h | 26 +- .../Code/EMotionFX/Source/RagdollInstance.cpp | 4 +- .../Code/EMotionFX/Source/Recorder.cpp | 4 +- .../EMotionFX/Source/SimulatedObjectSetup.cpp | 2 +- .../Code/EMotionFX/Source/Skeleton.cpp | 80 ++--- .../Code/EMotionFX/Source/Skeleton.h | 28 +- .../Code/EMotionFX/Source/SoftSkinDeformer.h | 2 +- .../Code/EMotionFX/Source/SpringSolver.cpp | 46 +-- .../Code/EMotionFX/Source/SpringSolver.h | 22 +- .../EMotionFX/Code/EMotionFX/Source/SubMesh.h | 10 +- .../Attachments/AttachmentNodesWindow.cpp | 8 +- .../Source/NodeGroups/NodeGroupWidget.cpp | 2 +- Gems/EMotionFX/Code/MCore/Source/Endian.h | 6 + Gems/EMotionFX/Code/MCore/Source/Endian.inl | 38 +++ .../Platform/Windows/platform_windows.cmake | 4 - .../Code/Source/Editor/SkeletonModel.cpp | 11 +- .../Tests/AdditiveMotionSamplingTests.cpp | 14 +- .../Code/Tests/AnimGraphMotionNodeTests.cpp | 30 +- .../Code/Tests/BlendTreeFootIKNodeTests.cpp | 4 +- .../Tests/BlendTreeMirrorPoseNodeTests.cpp | 12 +- .../BlendTreeSimulatedObjectNodeTests.cpp | 4 +- .../Tests/BlendTreeTwoLinkIKNodeTests.cpp | 22 +- .../Code/Tests/Mocks/CommandManagerCallback.h | 6 +- .../Code/Tests/MotionExtractionTests.cpp | 10 +- Gems/EMotionFX/Code/Tests/PoseTests.cpp | 34 +- .../Tests/SimulatedObjectSerializeTests.cpp | 4 +- .../Code/Tests/TestAssetCode/JackActor.cpp | 2 +- 52 files changed, 592 insertions(+), 676 deletions(-) diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphTriggerActionCommands.cpp b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphTriggerActionCommands.cpp index 8b04a80085..d5f43348f6 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphTriggerActionCommands.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphTriggerActionCommands.cpp @@ -58,7 +58,7 @@ namespace CommandSystem CommandAnimGraphAddTransitionAction::CommandAnimGraphAddTransitionAction(MCore::Command* orgCommand) : MCore::Command(s_commandName, orgCommand) - , m_oldActionIndex(MCORE_INVALIDINDEX32) + , m_oldActionIndex(InvalidIndex) { } @@ -105,14 +105,14 @@ namespace CommandSystem } // get the location where to add the new action - size_t insertAt = MCORE_INVALIDINDEX32; + size_t insertAt = InvalidIndex; if (parameters.CheckIfHasParameter("insertAt")) { insertAt = parameters.GetValueAsInt("insertAt", this); } // add it to the transition - if (insertAt == MCORE_INVALIDINDEX32) + if (insertAt == InvalidIndex) { actionSetup.AddAction(newAction); } @@ -214,7 +214,7 @@ namespace CommandSystem : MCore::Command(s_commandName, orgCommand) { m_oldActionType = AZ::TypeId::CreateNull(); - m_oldActionIndex = MCORE_INVALIDINDEX32; + m_oldActionIndex = InvalidIndex; } bool CommandAnimGraphRemoveTransitionAction::Execute(const MCore::CommandLine& parameters, AZStd::string& outResult) @@ -331,7 +331,7 @@ namespace CommandSystem CommandAnimGraphAddStateAction::CommandAnimGraphAddStateAction(MCore::Command* orgCommand) : MCore::Command(s_commandName, orgCommand) - , m_oldActionIndex(MCORE_INVALIDINDEX32) + , m_oldActionIndex(InvalidIndex) { } @@ -385,14 +385,14 @@ namespace CommandSystem } // get the location where to add the new action - size_t insertAt = MCORE_INVALIDINDEX32; + size_t insertAt = InvalidIndex; if (parameters.CheckIfHasParameter("insertAt")) { insertAt = parameters.GetValueAsInt("insertAt", this); } // add it to the transition - if (insertAt == MCORE_INVALIDINDEX32) + if (insertAt == InvalidIndex) { actionSetup.AddAction(newAction); } @@ -501,7 +501,7 @@ namespace CommandSystem : MCore::Command(s_commandName, orgCommand) { m_oldActionType = AZ::TypeId::CreateNull(); - m_oldActionIndex = MCORE_INVALIDINDEX32; + m_oldActionIndex = InvalidIndex; } bool CommandAnimGraphRemoveStateAction::Execute(const MCore::CommandLine& parameters, AZStd::string& outResult) diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MotionEventCommands.cpp b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MotionEventCommands.cpp index 76ba6f37b7..e4b8d38147 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MotionEventCommands.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MotionEventCommands.cpp @@ -293,7 +293,7 @@ namespace CommandSystem CommandRemoveMotionEventTrack::CommandRemoveMotionEventTrack(MCore::Command* orgCommand) : MCore::Command("RemoveMotionEventTrack", orgCommand) { - mOldTrackIndex = MCORE_INVALIDINDEX32; + mOldTrackIndex = InvalidIndex; } @@ -586,9 +586,9 @@ namespace CommandSystem } // add the motion event and check if everything worked fine - mMotionEventNr = eventTrack->AddEvent(m_startTime, m_endTime, AZStd::move(m_eventDatas.value_or(EMotionFX::EventDataSet()))); + mMotionEventNr = eventTrack->AddEvent(m_startTime, m_endTime, m_eventDatas.value_or(EMotionFX::EventDataSet())); - if (mMotionEventNr == MCORE_INVALIDINDEX32) + if (mMotionEventNr == InvalidIndex) { outResult = AZStd::string::format("Cannot create motion event. The returned motion event index is not valid."); return false; diff --git a/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/EndianConversion.cpp b/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/EndianConversion.cpp index a513710c83..153ec6e701 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/EndianConversion.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/EndianConversion.cpp @@ -88,6 +88,11 @@ namespace ExporterLib MCore::Endian::ConvertUnsignedInt32(value, EXPLIB_PLATFORM_ENDIAN, targetEndianType); } + void ConvertUnsignedInt(uint64* value, MCore::Endian::EEndianType targetEndianType) + { + MCore::Endian::ConvertUnsignedInt64(value, EXPLIB_PLATFORM_ENDIAN, targetEndianType); + } + void ConvertInt(int* value, MCore::Endian::EEndianType targetEndianType) { diff --git a/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/Exporter.h b/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/Exporter.h index 09c0646509..290f9d4470 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/Exporter.h +++ b/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/Exporter.h @@ -57,6 +57,7 @@ namespace ExporterLib // endian conversion void ConvertUnsignedInt(uint32* value, MCore::Endian::EEndianType targetEndianType); + void ConvertUnsignedInt(uint64* value, MCore::Endian::EEndianType targetEndianType); void ConvertInt(int* value, MCore::Endian::EEndianType targetEndianType); void ConvertUnsignedShort(uint16* value, MCore::Endian::EEndianType targetEndianType); void ConvertFloat(float* value, MCore::Endian::EEndianType targetEndianType); @@ -113,7 +114,7 @@ namespace ExporterLib // actors const char* GetActorExtension(bool includingDot = true); void SaveActorHeader(MCore::Stream* file, MCore::Endian::EEndianType targetEndianType); - void SaveActorFileInfo(MCore::Stream* file, uint32 numLODLevels, uint32 motionExtractionNodeIndex, uint32 retargetRootNodeIndex, const char* sourceApp, const char* orgFileName, const char* actorName, MCore::Distance::EUnitType unitType, MCore::Endian::EEndianType targetEndianType, bool optimizeSkeleton); + void SaveActorFileInfo(MCore::Stream* file, uint64 numLODLevels, uint64 motionExtractionNodeIndex, uint64 retargetRootNodeIndex, const char* sourceApp, const char* orgFileName, const char* actorName, MCore::Distance::EUnitType unitType, MCore::Endian::EEndianType targetEndianType, bool optimizeSkeleton); void SaveActor(MCore::MemoryFile* file, const EMotionFX::Actor* actor, MCore::Endian::EEndianType targetEndianType, const AZStd::optional meshAssetId = AZStd::nullopt); bool SaveActor(AZStd::string& filename, const EMotionFX::Actor* actor, MCore::Endian::EEndianType targetEndianType, const AZStd::optional meshAssetId = AZStd::nullopt); diff --git a/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/FileHeaderExport.cpp b/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/FileHeaderExport.cpp index 5a7f8d13e0..bafc899d4e 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/FileHeaderExport.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/FileHeaderExport.cpp @@ -38,9 +38,9 @@ namespace ExporterLib void SaveActorFileInfo(MCore::Stream* file, - uint32 numLODLevels, - uint32 motionExtractionNodeIndex, - uint32 retargetRootNodeIndex, + uint64 numLODLevels, + uint64 motionExtractionNodeIndex, + uint64 retargetRootNodeIndex, const char* sourceApp, const char* orgFileName, const char* actorName, @@ -62,9 +62,9 @@ namespace ExporterLib EMotionFX::FileFormat::Actor_Info3 infoChunk; memset(&infoChunk, 0, sizeof(EMotionFX::FileFormat::Actor_Info3)); - infoChunk.mNumLODs = numLODLevels; - infoChunk.mMotionExtractionNodeIndex = motionExtractionNodeIndex; - infoChunk.mRetargetRootNodeIndex = retargetRootNodeIndex; + infoChunk.mNumLODs = aznumeric_caster(numLODLevels); + infoChunk.mMotionExtractionNodeIndex = aznumeric_caster(motionExtractionNodeIndex); + infoChunk.mRetargetRootNodeIndex = aznumeric_caster(retargetRootNodeIndex); infoChunk.mExporterHighVersion = static_cast(EMotionFX::GetEMotionFX().GetHighVersion()); infoChunk.mExporterLowVersion = static_cast(EMotionFX::GetEMotionFX().GetLowVersion()); infoChunk.mUnitType = static_cast(unitType); diff --git a/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/MorphTargetExport.cpp b/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/MorphTargetExport.cpp index b2d88295b4..eefa92f21d 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/MorphTargetExport.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/MorphTargetExport.cpp @@ -168,7 +168,7 @@ namespace ExporterLib { // rename the morph target AZStd::string morphTargetName; - morphTargetName = AZStd::string::format("Morph Target %d", MCore::GetIDGenerator().GenerateID()); + morphTargetName = AZStd::string::format("Morph Target %zu", MCore::GetIDGenerator().GenerateID()); MCore::LogWarning("The morph target has an empty name. The morph target will be automatically renamed to '%s'.", morphTargetName.c_str()); morphTarget->SetName(morphTargetName.c_str()); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLActor.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLActor.cpp index 7a78b5749d..5a7d2032a7 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLActor.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLActor.cpp @@ -113,8 +113,8 @@ namespace RenderGL mTexturePath = texturePath; // get the number of nodes and geometry LOD levels - const uint32 numGeometryLODLevels = actor->GetNumLODLevels(); - const uint32 numNodes = actor->GetNumNodes(); + const size_t numGeometryLODLevels = actor->GetNumLODLevels(); + const size_t numNodes = actor->GetNumNodes(); // set the pre-allocation amount for the number of materials mMaterials.resize(numGeometryLODLevels); @@ -149,7 +149,7 @@ namespace RenderGL uint32 totalNumIndices[3] = { 0, 0, 0 }; // iterate through all nodes - for (uint32 n = 0; n < numNodes; ++n) + for (size_t n = 0; n < numNodes; ++n) { // get the current node EMotionFX::Node* node = skeleton->GetNode(n); @@ -171,7 +171,7 @@ namespace RenderGL EMotionFX::Mesh::EMeshType meshType = ClassifyMeshType(node, mesh, lodLevel); // get the number of submeshes and iterate through them - const uint32 numSubMeshes = mesh->GetNumSubMeshes(); + const size_t numSubMeshes = mesh->GetNumSubMeshes(); for (uint32 s = 0; s < numSubMeshes; ++s) { // get the current submesh @@ -278,7 +278,7 @@ namespace RenderGL for (uint32 lodLevel = 0; lodLevel < numGeometryLODLevels; ++lodLevel) { // iterate through all nodes - for (uint32 n = 0; n < numNodes; ++n) + for (size_t n = 0; n < numNodes; ++n) { // get the current node EMotionFX::Node* node = skeleton->GetNode(n); @@ -577,8 +577,8 @@ namespace RenderGL EMotionFX::Skeleton* skeleton = mActor->GetSkeleton(); // get the number of nodes and iterate through them - const uint32 numNodes = mActor->GetNumNodes(); - for (uint32 n = 0; n < numNodes; ++n) + const size_t numNodes = mActor->GetNumNodes(); + for (size_t n = 0; n < numNodes; ++n) { // get the current node EMotionFX::Node* node = skeleton->GetNode(n); @@ -703,7 +703,7 @@ namespace RenderGL } // get the number of nodes - const uint32 numNodes = mActor->GetNumNodes(); + const size_t numNodes = mActor->GetNumNodes(); if (numNodes == 0) { return; @@ -722,7 +722,7 @@ namespace RenderGL uint32 globalVert = 0; // iterate through all nodes - for (uint32 n = 0; n < numNodes; ++n) + for (size_t n = 0; n < numNodes; ++n) { // get the current node EMotionFX::Node* node = skeleton->GetNode(n); @@ -793,7 +793,7 @@ namespace RenderGL } // get the number of dynamic nodes - const uint32 numNodes = mActor->GetNumNodes(); + const size_t numNodes = mActor->GetNumNodes(); if (numNodes == 0) { return; @@ -812,7 +812,7 @@ namespace RenderGL uint32 globalVert = 0; // iterate through all nodes - for (uint32 n = 0; n < numNodes; ++n) + for (size_t n = 0; n < numNodes; ++n) { // get the current node EMotionFX::Node* node = skeleton->GetNode(n); diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/Material.h b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/Material.h index ed5ab18609..9c0522a6da 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/Material.h +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/Material.h @@ -29,18 +29,18 @@ namespace RenderGL mNumTriangles = 0; mNumVertices = 0; - mNodeIndex = MCORE_INVALIDINDEX32; + mNodeIndex = InvalidIndex; mMaterialIndex = MCORE_INVALIDINDEX32; } - uint32 mNodeIndex; /**< The index of the node to which this primitive belongs to. */ + size_t mNodeIndex; /**< The index of the node to which this primitive belongs to. */ uint32 mVertexOffset; uint32 mIndexOffset; /**< The starting index. */ uint32 mNumTriangles; /**< The number of triangles in the primitive. */ uint32 mNumVertices; /**< The number of vertices in the primitive. */ uint32 mMaterialIndex; /**< The material index which is mapped to the primitive. */ - AZStd::vector mBoneNodeIndices;/**< Mapping from local bones 0-50 to nodes. */ + AZStd::vector mBoneNodeIndices;/**< Mapping from local bones 0-50 to nodes. */ }; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp index 541ab65071..d8377f2d0e 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp @@ -75,8 +75,8 @@ namespace EMotionFX mSkeleton = Skeleton::Create(); - mMotionExtractionNode = MCORE_INVALIDINDEX32; - mRetargetRootNode = MCORE_INVALIDINDEX32; + mMotionExtractionNode = InvalidIndex; + mRetargetRootNode = InvalidIndex; mThreadIndex = 0; mCustomData = nullptr; mID = MCore::GetIDGenerator().GenerateID(); @@ -172,7 +172,7 @@ namespace EMotionFX result->mSkeleton = mSkeleton->Clone(); // clone lod data - const uint32 numNodes = mSkeleton->GetNumNodes(); + const size_t numNodes = mSkeleton->GetNumNodes(); const size_t numLodLevels = m_meshLodData.m_lodLevels.size(); MeshLODData& resultMeshLodData = result->m_meshLodData; @@ -184,7 +184,7 @@ namespace EMotionFX AZStd::vector& resultNodeInfos = resultMeshLodData.m_lodLevels[lodLevel].mNodeInfos; resultNodeInfos.resize(numNodes); - for (uint32 n = 0; n < numNodes; ++n) + for (size_t n = 0; n < numNodes; ++n) { NodeLODInfo& resultNodeInfo = resultNodeInfos[n]; const NodeLODInfo& sourceNodeInfo = nodeInfos[n]; @@ -230,11 +230,11 @@ namespace EMotionFX // init node mirror info void Actor::AllocateNodeMirrorInfos() { - const uint32 numNodes = mSkeleton->GetNumNodes(); + const size_t numNodes = mSkeleton->GetNumNodes(); mNodeMirrorInfos.resize(numNodes); // init the data - for (uint32 i = 0; i < numNodes; ++i) + for (size_t i = 0; i < numNodes; ++i) { mNodeMirrorInfos[i].mSourceNode = static_cast(i); mNodeMirrorInfos[i].mAxis = MCORE_INVALIDINDEX8; @@ -253,20 +253,15 @@ namespace EMotionFX // check if we have our axes detected bool Actor::GetHasMirrorAxesDetected() const { - if (mNodeMirrorInfos.size() == 0) + if (mNodeMirrorInfos.empty()) { return false; } - for (uint32 i = 0; i < mNodeMirrorInfos.size(); ++i) + return AZStd::all_of(begin(mNodeMirrorInfos), end(mNodeMirrorInfos), [](const NodeMirrorInfo& nodeMirrorInfo) { - if (mNodeMirrorInfos[i].mAxis == MCORE_INVALIDINDEX8) - { - return false; - } - } - - return true; + return nodeMirrorInfo.mAxis != MCORE_INVALIDINDEX8; + }); } @@ -274,13 +269,12 @@ namespace EMotionFX void Actor::RemoveAllMaterials() { // for all LODs - for (uint32 i = 0; i < mMaterials.size(); ++i) + for (AZStd::vector& mMaterial : mMaterials) { // delete all materials - const uint32 numMats = mMaterials[i].size(); - for (uint32 m = 0; m < numMats; ++m) + for (Material* m : mMaterial) { - mMaterials[i][m]->Destroy(); + m->Destroy(); } } @@ -295,7 +289,7 @@ namespace EMotionFX lodLevels.emplace_back(); LODLevel& newLOD = lodLevels.back(); - const uint32 numNodes = mSkeleton->GetNumNodes(); + const size_t numNodes = mSkeleton->GetNumNodes(); newLOD.mNodeInfos.resize(numNodes); const size_t numLODs = lodLevels.size(); @@ -339,11 +333,11 @@ namespace EMotionFX lodLevels.emplace(lodLevels.begin()+insertAt); LODLevel& newLOD = lodLevels[insertAt]; const uint32 lodIndex = insertAt; - const uint32 numNodes = mSkeleton->GetNumNodes(); + const size_t numNodes = mSkeleton->GetNumNodes(); newLOD.mNodeInfos.resize(numNodes); // get the number of nodes, iterate through them, create a new LOD level and copy over the meshes from the last LOD level - for (uint32 i = 0; i < numNodes; ++i) + for (size_t i = 0; i < numNodes; ++i) { NodeLODInfo& lodInfo = lodLevels[lodIndex].mNodeInfos[i]; lodInfo.mMesh = nullptr; @@ -366,8 +360,8 @@ namespace EMotionFX const LODLevel& sourceLOD = copyLodLevels[copyLODLevel]; LODLevel& targetLOD = lodLevels[replaceLODLevel]; - const uint32 numNodes = mSkeleton->GetNumNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = mSkeleton->GetNumNodes(); + for (size_t i = 0; i < numNodes; ++i) { Node* node = mSkeleton->GetNode(i); Node* copyNode = copyActor->GetSkeleton()->FindNodeByID(node->GetID()); @@ -410,14 +404,14 @@ namespace EMotionFX } // copy the materials - const uint32 numMaterials = copyActor->GetNumMaterials(copyLODLevel); - for (uint32 i = 0; i < mMaterials[replaceLODLevel].size(); ++i) + const size_t numMaterials = copyActor->GetNumMaterials(copyLODLevel); + for (Material* i : mMaterials[replaceLODLevel]) { - mMaterials[replaceLODLevel][i]->Destroy(); + i->Destroy(); } mMaterials[replaceLODLevel].clear(); mMaterials[replaceLODLevel].reserve(numMaterials); - for (uint32 i = 0; i < numMaterials; ++i) + for (size_t i = 0; i < numMaterials; ++i) { AddMaterial(replaceLODLevel, copyActor->GetMaterial(copyLODLevel, i)->Clone()); } @@ -449,22 +443,19 @@ namespace EMotionFX if (adjustMorphSetup) { mMorphSetups.resize(numLODs); - for (uint32 i = 0; i < numLODs; ++i) - { - mMorphSetups[i] = nullptr; - } + AZStd::fill(begin(mMorphSetups), AZStd::next(begin(mMorphSetups), numLODs), nullptr); } } // removes all node meshes and stacks void Actor::RemoveAllNodeMeshes() { - const uint32 numNodes = mSkeleton->GetNumNodes(); + const size_t numNodes = mSkeleton->GetNumNodes(); AZStd::vector& lodLevels = m_meshLodData.m_lodLevels; for (LODLevel& lodLevel : lodLevels) { - for (uint32 i = 0; i < numNodes; ++i) + for (size_t i = 0; i < numNodes; ++i) { NodeLODInfo& info = lodLevel.mNodeInfos[i]; MCore::Destroy(info.mMesh); @@ -482,8 +473,8 @@ namespace EMotionFX uint32 totalVerts = 0; uint32 totalIndices = 0; - const uint32 numNodes = mSkeleton->GetNumNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = mSkeleton->GetNumNodes(); + for (size_t i = 0; i < numNodes; ++i) { Mesh* mesh = GetMesh(lodLevel, i); if (!mesh) @@ -520,8 +511,8 @@ namespace EMotionFX uint32 totalIndices = 0; // for all nodes - const uint32 numNodes = mSkeleton->GetNumNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = mSkeleton->GetNumNodes(); + for (size_t i = 0; i < numNodes; ++i) { Mesh* mesh = GetMesh(lodLevel, i); @@ -564,8 +555,8 @@ namespace EMotionFX uint32 totalIndices = 0; // for all nodes - const uint32 numNodes = mSkeleton->GetNumNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = mSkeleton->GetNumNodes(); + for (size_t i = 0; i < numNodes; ++i) { Mesh* mesh = GetMesh(lodLevel, i); @@ -605,8 +596,8 @@ namespace EMotionFX { uint32 maxInfluences = 0; - const uint32 numNodes = mSkeleton->GetNumNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = mSkeleton->GetNumNodes(); + for (size_t i = 0; i < numNodes; ++i) { Mesh* mesh = GetMesh(lodLevel, i); if (!mesh) @@ -627,7 +618,7 @@ namespace EMotionFX uint32 n; // get the number of nodes - const uint32 numNodes = mSkeleton->GetNumNodes(); + const size_t numNodes = mSkeleton->GetNumNodes(); // check if the conflict node flag array's size is set to the number of nodes inside the actor if (conflictNodeFlags.size() != numNodes) @@ -694,8 +685,8 @@ namespace EMotionFX // Get the vertex counts for the influences. (e.g. 500 vertices have 1 skinning influence, 300 vertices have 2 skinning influences etc.) AZStd::vector meshVertexCounts; - const uint32 numNodes = GetNumNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = GetNumNodes(); + for (size_t i = 0; i < numNodes; ++i) { Mesh* mesh = GetMesh(lodLevel, i); if (!mesh) @@ -716,11 +707,11 @@ namespace EMotionFX } // check if there is any mesh available - bool Actor::CheckIfHasMeshes(uint32 lodLevel) const + bool Actor::CheckIfHasMeshes(size_t lodLevel) const { // check if any of the nodes has a mesh - const uint32 numNodes = mSkeleton->GetNumNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = mSkeleton->GetNumNodes(); + for (size_t i = 0; i < numNodes; ++i) { if (GetMesh(lodLevel, i)) { @@ -735,8 +726,8 @@ namespace EMotionFX bool Actor::CheckIfHasSkinnedMeshes(AZ::u32 lodLevel) const { - const AZ::u32 numNodes = mSkeleton->GetNumNodes(); - for (AZ::u32 i = 0; i < numNodes; ++i) + const size_t numNodes = mSkeleton->GetNumNodes(); + for (size_t i = 0; i < numNodes; ++i) { const Mesh* mesh = GetMesh(lodLevel, i); if (mesh && mesh->FindSharedVertexAttributeLayer(SkinningInfoVertexAttributeLayer::TYPE_ID)) @@ -768,13 +759,11 @@ namespace EMotionFX // remove all morph setups void Actor::RemoveAllMorphSetups(bool deleteMeshDeformers) { - uint32 i; - // get the number of lod levels - const uint32 numLODs = GetNumLODLevels(); + const size_t numLODs = GetNumLODLevels(); // for all LODs, get rid of all the morph setups for each geometry LOD - for (i = 0; i < mMorphSetups.size(); ++i) + for (uint32 i = 0; i < mMorphSetups.size(); ++i) { if (mMorphSetups[i]) { @@ -788,8 +777,8 @@ namespace EMotionFX if (deleteMeshDeformers) { // for all nodes - const uint32 numNodes = mSkeleton->GetNumNodes(); - for (i = 0; i < numNodes; ++i) + const size_t numNodes = mSkeleton->GetNumNodes(); + for (size_t i = 0; i < numNodes; ++i) { // process all LOD levels for (uint32 lod = 0; lod < numLODs; ++lod) @@ -825,8 +814,8 @@ namespace EMotionFX } // iterate through the submeshes - const uint32 numSubMeshes = mesh->GetNumSubMeshes(); - for (uint32 s = 0; s < numSubMeshes; ++s) + const size_t numSubMeshes = mesh->GetNumSubMeshes(); + for (size_t s = 0; s < numSubMeshes; ++s) { // if the submesh material index is the same as the material index we search for, then it is being used if (mesh->GetSubMesh(s)->GetMaterial() == materialIndex) @@ -843,18 +832,14 @@ namespace EMotionFX bool Actor::CheckIfIsMaterialUsed(uint32 lodLevel, uint32 index) const { // iterate through all nodes of the actor and check its meshes - const uint32 numNodes = mSkeleton->GetNumNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = mSkeleton->GetNumNodes(); + for (size_t i = 0; i < numNodes; ++i) { // if the mesh is in LOD range check if it uses the material if (CheckIfIsMaterialUsed(GetMesh(lodLevel, i), index)) { return true; } - - // same for the collision mesh - //if (CheckIfIsMaterialUsed( GetCollisionMesh(lodLevel, i), index )) - //return true; } // return false, this means that no mesh uses the given material @@ -883,14 +868,14 @@ namespace EMotionFX uint32 maxNumChilds = 0; // traverse through all root nodes - const uint32 numRootNodes = mSkeleton->GetNumRootNodes(); - for (uint32 i = 0; i < numRootNodes; ++i) + const size_t numRootNodes = mSkeleton->GetNumRootNodes(); + for (size_t i = 0; i < numRootNodes; ++i) { // get the given root node from the actor Node* rootNode = mSkeleton->GetNode(mSkeleton->GetRootNodeIndex(i)); // get the number of child nodes recursively - const uint32 numChildNodes = rootNode->GetNumChildNodesRecursive(); + const size_t numChildNodes = rootNode->GetNumChildNodesRecursive(); // if the number of child nodes of this node is bigger than the current max number // this is our new candidate for the repositioning node @@ -919,8 +904,8 @@ namespace EMotionFX outBoneList->clear(); // for all nodes - const uint32 numNodes = mSkeleton->GetNumNodes(); - for (uint32 n = 0; n < numNodes; ++n) + const size_t numNodes = mSkeleton->GetNumNodes(); + for (size_t n = 0; n < numNodes; ++n) { Mesh* mesh = GetMesh(lodLevel, n); @@ -946,7 +931,7 @@ namespace EMotionFX for (uint32 i = 0; i < numInfluences; ++i) { // get the node number of the bone - uint32 nodeNr = skinningLayer->GetInfluence(v, i)->GetNodeNr(); + uint16 nodeNr = skinningLayer->GetInfluence(v, i)->GetNodeNr(); // check if it is already in the bone list, if not, add it if (AZStd::find(begin(*outBoneList), end(*outBoneList), nodeNr) == end(*outBoneList)) @@ -963,8 +948,8 @@ namespace EMotionFX void Actor::RecursiveAddDependencies(const Actor* actor) { // process all dependencies of the given actor - const uint32 numDependencies = actor->GetNumDependencies(); - for (uint32 i = 0; i < numDependencies; ++i) + const size_t numDependencies = actor->GetNumDependencies(); + for (size_t i = 0; i < numDependencies; ++i) { // add it to the actor instance mDependencies.emplace_back(*actor->GetDependency(i)); @@ -995,8 +980,8 @@ namespace EMotionFX AZStd::string nameB; // search through all nodes to find the best match - const uint32 numNodes = mSkeleton->GetNumNodes(); - for (uint32 n = 0; n < numNodes; ++n) + const size_t numNodes = mSkeleton->GetNumNodes(); + for (size_t n = 0; n < numNodes; ++n) { // get the node name const char* name = mSkeleton->GetNode(n)->GetName(); @@ -1052,21 +1037,21 @@ namespace EMotionFX bool Actor::MapNodeMotionSource(const char* sourceNodeName, const char* destNodeName) { // find the source node index - const uint32 sourceNodeIndex = mSkeleton->FindNodeByNameNoCase(sourceNodeName)->GetNodeIndex(); - if (sourceNodeIndex == MCORE_INVALIDINDEX32) + const size_t sourceNodeIndex = mSkeleton->FindNodeByNameNoCase(sourceNodeName)->GetNodeIndex(); + if (sourceNodeIndex == InvalidIndex) { return false; } // find the dest node index - const uint32 destNodeIndex = mSkeleton->FindNodeByNameNoCase(destNodeName)->GetNodeIndex(); - if (destNodeIndex == MCORE_INVALIDINDEX32) + const size_t destNodeIndex = mSkeleton->FindNodeByNameNoCase(destNodeName)->GetNodeIndex(); + if (destNodeIndex == InvalidIndex) { return false; } // allocate the data if we haven't already - if (mNodeMirrorInfos.size() == 0) + if (mNodeMirrorInfos.empty()) { AllocateNodeMirrorInfos(); } @@ -1084,7 +1069,7 @@ namespace EMotionFX bool Actor::MapNodeMotionSource(uint16 sourceNodeIndex, uint16 targetNodeIndex) { // allocate the data if we haven't already - if (mNodeMirrorInfos.size() == 0) + if (mNodeMirrorInfos.empty()) { AllocateNodeMirrorInfos(); } @@ -1104,8 +1089,8 @@ namespace EMotionFX void Actor::MatchNodeMotionSources(const char* subStringA, const char* subStringB) { // try to map all nodes - const uint32 numNodes = mSkeleton->GetNumNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = mSkeleton->GetNumNodes(); + for (size_t i = 0; i < numNodes; ++i) { Node* node = mSkeleton->GetNode(i); @@ -1137,14 +1122,14 @@ namespace EMotionFX // find the first active parent node in a given skeletal LOD - uint32 Actor::FindFirstActiveParentBone(uint32 skeletalLOD, uint32 startNodeIndex) const + size_t Actor::FindFirstActiveParentBone(uint32 skeletalLOD, size_t startNodeIndex) const { - uint32 curNodeIndex = startNodeIndex; + size_t curNodeIndex = startNodeIndex; do { curNodeIndex = mSkeleton->GetNode(curNodeIndex)->GetParentIndex(); - if (curNodeIndex == MCORE_INVALIDINDEX32) + if (curNodeIndex == InvalidIndex) { return curNodeIndex; } @@ -1153,9 +1138,9 @@ namespace EMotionFX { return curNodeIndex; } - } while (curNodeIndex != MCORE_INVALIDINDEX32); + } while (curNodeIndex != InvalidIndex); - return MCORE_INVALIDINDEX32; + return InvalidIndex; } // make the geometry LOD levels compatible with the skeletal LOD levels @@ -1169,8 +1154,8 @@ namespace EMotionFX for (size_t geomLod = 0; geomLod < numGeomLODs; ++geomLod) { // for all nodes - const uint32 numNodes = mSkeleton->GetNumNodes(); - for (uint32 n = 0; n < numNodes; ++n) + const size_t numNodes = mSkeleton->GetNumNodes(); + for (size_t n = 0; n < numNodes; ++n) { Node* node = mSkeleton->GetNode(n); @@ -1192,8 +1177,8 @@ namespace EMotionFX const uint32* orgVertices = (uint32*)mesh->FindOriginalVertexData(Mesh::ATTRIB_ORGVTXNUMBERS); // for all submeshes - const uint32 numSubMeshes = mesh->GetNumSubMeshes(); - for (uint32 s = 0; s < numSubMeshes; ++s) + const size_t numSubMeshes = mesh->GetNumSubMeshes(); + for (size_t s = 0; s < numSubMeshes; ++s) { SubMesh* subMesh = mesh->GetSubMesh(s); @@ -1214,8 +1199,8 @@ namespace EMotionFX if (mSkeleton->GetNode(influence->GetNodeNr())->GetSkeletalLODStatus(static_cast(geomLod)) == false) { // find the first parent bone that is enabled in this LOD - const uint32 newNodeIndex = FindFirstActiveParentBone(static_cast(geomLod), influence->GetNodeNr()); - if (newNodeIndex == MCORE_INVALIDINDEX32) + const size_t newNodeIndex = FindFirstActiveParentBone(geomLod, influence->GetNodeNr()); + if (newNodeIndex == InvalidIndex) { MCore::LogWarning("EMotionFX::Actor::MakeGeomLODsCompatibleWithSkeletalLODs() - Failed to find an enabled parent for node '%s' in skeletal LOD %d of actor '%s' (0x%x)", node->GetName(), geomLod, GetFileName(), this); continue; @@ -1250,7 +1235,7 @@ namespace EMotionFX // generate a path from the current node towards the root - void Actor::GenerateUpdatePathToRoot(uint32 endNodeIndex, AZStd::vector& outPath) const + void Actor::GenerateUpdatePathToRoot(size_t endNodeIndex, AZStd::vector& outPath) const { outPath.clear(); outPath.reserve(32); @@ -1279,7 +1264,7 @@ namespace EMotionFX } } - void Actor::SetMotionExtractionNodeIndex(uint32 nodeIndex) + void Actor::SetMotionExtractionNodeIndex(size_t nodeIndex) { mMotionExtractionNode = nodeIndex; ActorNotificationBus::Broadcast(&ActorNotificationBus::Events::OnMotionExtractionNodeChanged, this, GetMotionExtractionNode()); @@ -1287,7 +1272,7 @@ namespace EMotionFX Node* Actor::GetMotionExtractionNode() const { - if (mMotionExtractionNode != MCORE_INVALIDINDEX32 && + if (mMotionExtractionNode != InvalidIndex && mMotionExtractionNode < mSkeleton->GetNumNodes()) { return mSkeleton->GetNode(mMotionExtractionNode); @@ -1298,9 +1283,9 @@ namespace EMotionFX void Actor::ReinitializeMeshDeformers() { - const uint32 numLODLevels = GetNumLODLevels(); - const uint32 numNodes = mSkeleton->GetNumNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numLODLevels = GetNumLODLevels(); + const size_t numNodes = mSkeleton->GetNumNodes(); + for (size_t i = 0; i < numNodes; ++i) { Node* node = mSkeleton->GetNode(i); @@ -1327,9 +1312,9 @@ namespace EMotionFX // calculate the inverse bind pose matrices const Pose* bindPose = GetBindPose(); - const uint32 numNodes = mSkeleton->GetNumNodes(); + const size_t numNodes = mSkeleton->GetNumNodes(); mInvBindPoseTransforms.resize(numNodes); - for (uint32 i = 0; i < numNodes; ++i) + for (size_t i = 0; i < numNodes; ++i) { mInvBindPoseTransforms[i] = bindPose->GetModelSpaceTransform(i).Inversed(); } @@ -1509,7 +1494,7 @@ namespace EMotionFX outPoints.clear(); const uint32 geomLODLevel = 0; - const uint32 numNodes = mSkeleton->GetNumNodes(); + const size_t numNodes = mSkeleton->GetNumNodes(); for (int nodeIndex = 0; nodeIndex < numNodes; nodeIndex++) { @@ -1532,8 +1517,8 @@ namespace EMotionFX AZ::Vector3* positions = (AZ::Vector3*)mesh->FindVertexData(EMotionFX::Mesh::ATTRIB_POSITIONS); // for all submeshes - const uint32 numSubMeshes = mesh->GetNumSubMeshes(); - for (uint32 subMeshIndex = 0; subMeshIndex < numSubMeshes; ++subMeshIndex) + const size_t numSubMeshes = mesh->GetNumSubMeshes(); + for (size_t subMeshIndex = 0; subMeshIndex < numSubMeshes; ++subMeshIndex) { SubMesh* subMesh = mesh->GetSubMesh(subMeshIndex); @@ -1545,10 +1530,10 @@ namespace EMotionFX const uint32 orgVertex = orgVertices[startVertex + vertexIndex]; // for all skinning influences of the vertex - const uint32 numInfluences = static_cast(layer->GetNumInfluences(orgVertex)); + const size_t numInfluences = layer->GetNumInfluences(orgVertex); float maxWeight = 0.0f; - uint32 maxWeightNodeIndex = 0; - for (uint32 i = 0; i < numInfluences; ++i) + size_t maxWeightNodeIndex = 0; + for (size_t i = 0; i < numInfluences; ++i) { SkinInfluence* influence = layer->GetInfluence(orgVertex, i); float weight = influence->GetWeight(); @@ -1577,8 +1562,8 @@ namespace EMotionFX Pose pose; pose.LinkToActor(this); - const uint32 numNodes = mNodeMirrorInfos.size(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = mNodeMirrorInfos.size(); + for (size_t i = 0; i < numNodes; ++i) { const uint16 motionSource = (GetHasMirrorInfo()) ? GetNodeMirrorInfo(i).mSourceNode : static_cast(i); @@ -1699,9 +1684,6 @@ namespace EMotionFX //MCore::LogInfo("best for %s = %f (axis=%d) (flags=%d)", mNodes[i]->GetName(), minDist, bestAxis, bestFlags); } } - - //for (uint32 i=0; iGetName(), mNodeMirrorInfos[i].mAxis, mNodeMirrorInfos[i].mFlags); } @@ -1766,10 +1748,10 @@ namespace EMotionFX uint16 result = MCORE_INVALIDINDEX16; // find nodes that have the mirrored transform - const uint32 numNodes = mSkeleton->GetNumNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = mSkeleton->GetNumNodes(); + for (size_t i = 0; i < numNodes; ++i) { - const Transform curNodeTransform = pose.GetModelSpaceTransform(i); + const Transform& curNodeTransform = pose.GetModelSpaceTransform(i); if (i != nodeIndex) { // only check the translation for now @@ -1791,8 +1773,8 @@ namespace EMotionFX if (numMatches == 1) { - const uint32 hierarchyDepth = mSkeleton->CalcHierarchyDepthForNode(nodeIndex); - const uint32 matchingHierarchyDepth = mSkeleton->CalcHierarchyDepthForNode(result); + const size_t hierarchyDepth = mSkeleton->CalcHierarchyDepthForNode(nodeIndex); + const size_t matchingHierarchyDepth = mSkeleton->CalcHierarchyDepthForNode(result); if (hierarchyDepth != matchingHierarchyDepth) { return MCORE_INVALIDINDEX16; @@ -1838,7 +1820,7 @@ namespace EMotionFX *mSkeleton->GetBindPose() = *other->GetSkeleton()->GetBindPose(); } - void Actor::SetNumNodes(uint32 numNodes) + void Actor::SetNumNodes(size_t numNodes) { mSkeleton->SetNumNodes(numNodes); @@ -1868,13 +1850,13 @@ namespace EMotionFX mSkeleton->GetBindPose()->SetLocalSpaceTransform(mSkeleton->GetNumNodes() - 1, Transform::CreateIdentity()); } - Node* Actor::AddNode(uint32 nodeIndex, const char* name, uint32 parentIndex) + Node* Actor::AddNode(size_t nodeIndex, const char* name, size_t parentIndex) { Node* node = Node::Create(name, GetSkeleton()); node->SetNodeIndex(nodeIndex); node->SetParentIndex(parentIndex); AddNode(node); - if (parentIndex == MCORE_INVALIDINDEX32) + if (parentIndex == InvalidIndex) { GetSkeleton()->AddRootNode(node->GetNodeIndex()); } @@ -1885,7 +1867,7 @@ namespace EMotionFX return node; } - void Actor::RemoveNode(uint32 nr, bool delMem) + void Actor::RemoveNode(size_t nr, bool delMem) { mSkeleton->RemoveNode(nr, delMem); @@ -2169,20 +2151,20 @@ namespace EMotionFX //--------------------------------- - Mesh* Actor::GetMesh(uint32 lodLevel, uint32 nodeIndex) const + Mesh* Actor::GetMesh(size_t lodLevel, size_t nodeIndex) const { const AZStd::vector& lodLevels = m_meshLodData.m_lodLevels; return lodLevels[lodLevel].mNodeInfos[nodeIndex].mMesh; } - MeshDeformerStack* Actor::GetMeshDeformerStack(uint32 lodLevel, uint32 nodeIndex) const + MeshDeformerStack* Actor::GetMeshDeformerStack(uint32 lodLevel, size_t nodeIndex) const { const AZStd::vector& lodLevels = m_meshLodData.m_lodLevels; return lodLevels[lodLevel].mNodeInfos[nodeIndex].mStack; } // set the mesh for a given node in a given LOD - void Actor::SetMesh(uint32 lodLevel, uint32 nodeIndex, Mesh* mesh) + void Actor::SetMesh(uint32 lodLevel, size_t nodeIndex, Mesh* mesh) { AZStd::vector& lodLevels = m_meshLodData.m_lodLevels; lodLevels[lodLevel].mNodeInfos[nodeIndex].mMesh = mesh; @@ -2190,14 +2172,14 @@ namespace EMotionFX // set the mesh deformer stack for a given node in a given LOD - void Actor::SetMeshDeformerStack(uint32 lodLevel, uint32 nodeIndex, MeshDeformerStack* stack) + void Actor::SetMeshDeformerStack(uint32 lodLevel, size_t nodeIndex, MeshDeformerStack* stack) { AZStd::vector& lodLevels = m_meshLodData.m_lodLevels; lodLevels[lodLevel].mNodeInfos[nodeIndex].mStack = stack; } // check if the mesh has a skinning deformer (either linear or dual quat) - bool Actor::CheckIfHasSkinningDeformer(uint32 lodLevel, uint32 nodeIndex) const + bool Actor::CheckIfHasSkinningDeformer(uint32 lodLevel, size_t nodeIndex) const { // check if there is a mesh Mesh* mesh = GetMesh(lodLevel, nodeIndex); @@ -2217,7 +2199,7 @@ namespace EMotionFX } // remove the mesh for a given node in a given LOD - void Actor::RemoveNodeMeshForLOD(uint32 lodLevel, uint32 nodeIndex, bool destroyMesh) + void Actor::RemoveNodeMeshForLOD(uint32 lodLevel, size_t nodeIndex, bool destroyMesh) { AZStd::vector& lodLevels = m_meshLodData.m_lodLevels; @@ -2273,8 +2255,8 @@ namespace EMotionFX // scale the bind pose positions Pose* bindPose = GetBindPose(); - const uint32 numNodes = GetNumNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = GetNumNodes(); + for (size_t i = 0; i < numNodes; ++i) { Transform transform = bindPose->GetLocalSpaceTransform(i); transform.mPosition *= scaleFactor; @@ -2283,7 +2265,7 @@ namespace EMotionFX bindPose->ForceUpdateFullModelSpacePose(); // calculate the inverse bind pose matrices - for (uint32 i = 0; i < numNodes; ++i) + for (size_t i = 0; i < numNodes; ++i) { mInvBindPoseTransforms[i] = bindPose->GetModelSpaceTransform(i).Inversed(); } @@ -2293,10 +2275,10 @@ namespace EMotionFX m_staticAabb.SetMax(m_staticAabb.GetMax() * scaleFactor); // update mesh data for all LOD levels - const uint32 numLODs = GetNumLODLevels(); - for (uint32 lod = 0; lod < numLODs; ++lod) + const size_t numLODs = GetNumLODLevels(); + for (size_t lod = 0; lod < numLODs; ++lod) { - for (uint32 i = 0; i < numNodes; ++i) + for (size_t i = 0; i < numNodes; ++i) { Mesh* mesh = GetMesh(lod, i); if (mesh) @@ -2344,8 +2326,8 @@ namespace EMotionFX // Try to figure out which axis points "up" for the motion extraction node. Actor::EAxis Actor::FindBestMatchingMotionExtractionAxis() const { - MCORE_ASSERT(mMotionExtractionNode != MCORE_INVALIDINDEX32); - if (mMotionExtractionNode == MCORE_INVALIDINDEX32) + MCORE_ASSERT(mMotionExtractionNode != InvalidIndex); + if (mMotionExtractionNode == InvalidIndex) { return AXIS_Y; } @@ -2380,7 +2362,7 @@ namespace EMotionFX } - void Actor::SetRetargetRootNodeIndex(uint32 nodeIndex) + void Actor::SetRetargetRootNodeIndex(size_t nodeIndex) { mRetargetRootNode = nodeIndex; } @@ -2388,10 +2370,10 @@ namespace EMotionFX void Actor::SetRetargetRootNode(Node* node) { - mRetargetRootNode = node ? node->GetNodeIndex() : MCORE_INVALIDINDEX32; + mRetargetRootNode = node ? node->GetNodeIndex() : InvalidIndex; } - void Actor::InsertJointAndParents(AZ::u32 jointIndex, AZStd::unordered_set& includedJointIndices) + void Actor::InsertJointAndParents(size_t jointIndex, AZStd::unordered_set& includedJointIndices) { // If our joint is already in, then we can skip things. if (includedJointIndices.find(jointIndex) != includedJointIndices.end()) @@ -2400,8 +2382,8 @@ namespace EMotionFX } // Add the parent. - const AZ::u32 parentIndex = mSkeleton->GetNode(jointIndex)->GetParentIndex(); - if (parentIndex != InvalidIndex32) + const size_t parentIndex = mSkeleton->GetNode(jointIndex)->GetParentIndex(); + if (parentIndex != InvalidIndex) { InsertJointAndParents(parentIndex, includedJointIndices); } @@ -2412,10 +2394,10 @@ namespace EMotionFX void Actor::AutoSetupSkeletalLODsBasedOnSkinningData(const AZStd::vector& alwaysIncludeJoints) { - AZStd::unordered_set includedJointIndices; + AZStd::unordered_set includedJointIndices; - const AZ::u32 numLODs = GetNumLODLevels(); - for (AZ::u32 lod = 0; lod < numLODs; ++lod) + const size_t numLODs = GetNumLODLevels(); + for (size_t lod = 0; lod < numLODs; ++lod) { includedJointIndices.clear(); @@ -2425,8 +2407,8 @@ namespace EMotionFX continue; } - const AZ::u32 numJoints = mSkeleton->GetNumNodes(); - for (AZ::u32 jointIndex = 0; jointIndex < numJoints; ++jointIndex) + const size_t numJoints = mSkeleton->GetNumNodes(); + for (size_t jointIndex = 0; jointIndex < numJoints; ++jointIndex) { const Mesh* mesh = GetMesh(lod, jointIndex); if (!mesh) @@ -2438,14 +2420,13 @@ namespace EMotionFX InsertJointAndParents(jointIndex, includedJointIndices); // Look at the joints registered in the submeshes. - const AZ::u32 numSubMeshes = mesh->GetNumSubMeshes(); - for (AZ::u32 subMeshIndex = 0; subMeshIndex < numSubMeshes; ++subMeshIndex) + const size_t numSubMeshes = mesh->GetNumSubMeshes(); + for (size_t subMeshIndex = 0; subMeshIndex < numSubMeshes; ++subMeshIndex) { - const AZStd::vector& subMeshJoints = mesh->GetSubMesh(subMeshIndex)->GetBonesArray(); - const AZ::u32 numSubMeshJoints = subMeshJoints.size(); - for (AZ::u32 i = 0; i < numSubMeshJoints; ++i) + const AZStd::vector& subMeshJoints = mesh->GetSubMesh(subMeshIndex)->GetBonesArray(); + for (size_t subMeshJoint : subMeshJoints) { - InsertJointAndParents(subMeshJoints[i], includedJointIndices); + InsertJointAndParents(subMeshJoint, includedJointIndices); } } } // for all joints @@ -2456,7 +2437,7 @@ namespace EMotionFX // Force joints in our "always include list" to be included. for (const AZStd::string& jointName : alwaysIncludeJoints) { - AZ::u32 jointIndex = InvalidIndex32; + size_t jointIndex = InvalidIndex; if (!mSkeleton->FindNodeAndIndexByName(jointName, jointIndex)) { if (!jointName.empty()) @@ -2470,14 +2451,14 @@ namespace EMotionFX } // Disable all joints first. - for (AZ::u32 jointIndex = 0; jointIndex < numJoints; ++jointIndex) + for (size_t jointIndex = 0; jointIndex < numJoints; ++jointIndex) { mSkeleton->GetNode(jointIndex)->SetSkeletalLODStatus(lod, false); } // Enable all our included joints in this skeletal LOD. AZ_TracePrintf("EMotionFX", "[LOD %d] Enabled joints = %zd\n", lod, includedJointIndices.size()); - for (AZ::u32 jointIndex : includedJointIndices) + for (size_t jointIndex : includedJointIndices) { mSkeleton->GetNode(jointIndex)->SetSkeletalLODStatus(lod, true); } @@ -2485,7 +2466,7 @@ namespace EMotionFX else // When we have an empty include list, enable everything. { AZ_TracePrintf("EMotionFX", "[LOD %d] Enabled joints = %zd\n", lod, mSkeleton->GetNumNodes()); - for (AZ::u32 i = 0; i < mSkeleton->GetNumNodes(); ++i) + for (size_t i = 0; i < mSkeleton->GetNumNodes(); ++i) { mSkeleton->GetNode(i)->SetSkeletalLODStatus(lod, true); } @@ -2496,17 +2477,17 @@ namespace EMotionFX void Actor::PrintSkeletonLODs() { - const AZ::u32 numLODs = GetNumLODLevels(); - for (AZ::u32 lod = 0; lod < numLODs; ++lod) + const size_t numLODs = GetNumLODLevels(); + for (size_t lod = 0; lod < numLODs; ++lod) { AZ_TracePrintf("EMotionFX", "[LOD %d]:", lod); - const AZ::u32 numJoints = mSkeleton->GetNumNodes(); - for (AZ::u32 jointIndex = 0; jointIndex < numJoints; ++jointIndex) + const size_t numJoints = mSkeleton->GetNumNodes(); + for (size_t jointIndex = 0; jointIndex < numJoints; ++jointIndex) { const Node* joint = mSkeleton->GetNode(jointIndex); if (joint->GetSkeletalLODStatus(lod)) { - AZ_TracePrintf("EMotionFX", "\t%s (index=%d)", joint->GetName(), jointIndex); + AZ_TracePrintf("EMotionFX", "\t%s (index=%zu)", joint->GetName(), jointIndex); } } } @@ -2530,7 +2511,7 @@ namespace EMotionFX // 3) In actor skeleton, remove every node that hasn't been marked. // 4) Meanwhile, build a map that represent the child-parent relationship. // 5) After the node index changed, we use the map in 4) to restore the child-parent relationship. - AZ::u32 numNodes = mSkeleton->GetNumNodes(); + size_t numNodes = mSkeleton->GetNumNodes(); AZStd::vector flags; AZStd::unordered_map childParentMap; flags.resize(numNodes); @@ -2554,7 +2535,7 @@ namespace EMotionFX } // Search the actor skeleton to find all the critical nodes. - for (AZ::u32 i = 0; i < numNodes; ++i) + for (size_t i = 0; i < numNodes; ++i) { Node* node = mSkeleton->GetNode(i); if (node->GetIsCritical() && nodesToKeep.find(node) == nodesToKeep.end()) @@ -2584,7 +2565,7 @@ namespace EMotionFX } // Remove all the nodes that haven't been marked - for (AZ::u32 nodeIndex = numNodes - 1; nodeIndex > 0; nodeIndex--) + for (size_t nodeIndex = numNodes - 1; nodeIndex > 0; nodeIndex--) { if (!flags[nodeIndex]) { @@ -2597,7 +2578,7 @@ namespace EMotionFX // After the node index changed, the parent index become invalid. First, clear all information about children because // it's not valid anymore. - for (AZ::u32 nodeIndex = 0; nodeIndex < mSkeleton->GetNumNodes(); ++nodeIndex) + for (size_t nodeIndex = 0; nodeIndex < mSkeleton->GetNumNodes(); ++nodeIndex) { Node* node = mSkeleton->GetNode(nodeIndex); node->RemoveAllChildNodes(); @@ -2654,8 +2635,8 @@ namespace EMotionFX const size_t numLODLevels = lodAssets.size(); lodLevels.clear(); - SetNumLODLevels(static_cast(numLODLevels), /*adjustMorphSetup=*/false); - const uint32 numNodes = mSkeleton->GetNumNodes(); + SetNumLODLevels(numLODLevels, /*adjustMorphSetup=*/false); + const size_t numNodes = mSkeleton->GetNumNodes(); // Remove all the materials and add them back based on the meshAsset. Eventually we will remove all the material from Actor and // GLActor. @@ -2679,7 +2660,7 @@ namespace EMotionFX continue; } - const AZ::u32 jointIndex = meshJoint->GetNodeIndex(); + const size_t jointIndex = meshJoint->GetNodeIndex(); NodeLODInfo& jointInfo = lodLevels[lodLevel].mNodeInfos[jointIndex]; jointInfo.mMesh = mesh; @@ -2690,8 +2671,8 @@ namespace EMotionFX } // Add the skinning deformers - const AZ::u32 numLayers = mesh->GetNumSharedVertexAttributeLayers(); - for (AZ::u32 layerNr = 0; layerNr < numLayers; ++layerNr) + const size_t numLayers = mesh->GetNumSharedVertexAttributeLayers(); + for (size_t layerNr = 0; layerNr < numLayers; ++layerNr) { EMotionFX::VertexAttributeLayer* vertexAttributeLayer = mesh->GetSharedVertexAttributeLayer(layerNr); if (vertexAttributeLayer->GetType() != EMotionFX::SkinningInfoVertexAttributeLayer::TYPE_ID) @@ -2703,7 +2684,7 @@ namespace EMotionFX static_cast(vertexAttributeLayer); const AZ::u32 numOrgVerts = skinLayer->GetNumAttributes(); AZStd::set localJointIndices = skinLayer->CalcLocalJointIndices(numOrgVerts); - const AZ::u32 numLocalJoints = static_cast(localJointIndices.size()); + const size_t numLocalJoints = localJointIndices.size(); // The information about if we want to use dual quat skinning is baked into the mesh chunk and we don't have access to that // anymore. Default to dual quat skinning. @@ -2801,7 +2782,7 @@ namespace EMotionFX continue; } - const AZ::u32 jointIndex = meshJoint->GetNodeIndex(); + const size_t jointIndex = meshJoint->GetNodeIndex(); NodeLODInfo& jointInfo = lodLevels[lodLevel].mNodeInfos[jointIndex]; Mesh* mesh = jointInfo.mMesh; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Actor.h b/Gems/EMotionFX/Code/EMotionFX/Source/Actor.h index 0894d22c4c..21b97c0bd6 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Actor.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Actor.h @@ -131,14 +131,14 @@ namespace EMotionFX /** * Add a node to this actor. */ - Node* AddNode(uint32 nodeIndex, const char* name, uint32 parentIndex = MCORE_INVALIDINDEX32); + Node* AddNode(size_t nodeIndex, const char* name, size_t parentIndex = InvalidIndex); /** * Remove a given node. * @param nr The node to remove. * @param delMem If true the allocated memory of the node will be deleted. */ - void RemoveNode(uint32 nr, bool delMem = true); + void RemoveNode(size_t nr, bool delMem = true); /** * Remove all nodes from memory. @@ -188,7 +188,7 @@ namespace EMotionFX * @param endNodeIndex The node index to generate the path to. * @param outPath the array that will contain the path. */ - void GenerateUpdatePathToRoot(uint32 endNodeIndex, AZStd::vector& outPath) const; + void GenerateUpdatePathToRoot(size_t endNodeIndex, AZStd::vector& outPath) const; /** * Set the motion extraction node. @@ -206,7 +206,7 @@ namespace EMotionFX * You can set the node to MCORE_INVALIDINDEX32 in case you want to disable motion extraction. * @param nodeIndex The motion extraction node, or MCORE_INVALIDINDEX32 to disable it. */ - void SetMotionExtractionNodeIndex(uint32 nodeIndex); + void SetMotionExtractionNodeIndex(size_t nodeIndex); /** * Get the motion extraction node. @@ -218,7 +218,7 @@ namespace EMotionFX * Get the motion extraction node index. * @result The motion extraction node index, or MCORE_INVALIDINDEX32 when it has not been set. */ - MCORE_INLINE uint32 GetMotionExtractionNodeIndex() const { return mMotionExtractionNode; } + MCORE_INLINE size_t GetMotionExtractionNodeIndex() const { return mMotionExtractionNode; } //--------------------------------------------------------------------- @@ -227,7 +227,7 @@ namespace EMotionFX * @param lodLevel The LOD level to check for. * @result Returns true when this actor contains nodes that have meshes in the given LOD, otherwise false is returned. */ - bool CheckIfHasMeshes(uint32 lodLevel) const; + bool CheckIfHasMeshes(size_t lodLevel) const; /** * Check if we have skinned meshes. @@ -529,8 +529,8 @@ namespace EMotionFX * @param nr The dependency number, which must be in range of [0..GetNumDependencies()-1]. * @result A pointer to the dependency. */ - MCORE_INLINE Dependency* GetDependency(uint32 nr) { return &mDependencies[nr]; } - MCORE_INLINE const Dependency* GetDependency(uint32 nr) const { return &mDependencies[nr]; } + MCORE_INLINE Dependency* GetDependency(size_t nr) { return &mDependencies[nr]; } + MCORE_INLINE const Dependency* GetDependency(size_t nr) const { return &mDependencies[nr]; } /** * Recursively add dependencies that this actor has on other actors. @@ -649,14 +649,14 @@ namespace EMotionFX * @param nodeIndex The node index to get the info for. * @result A reference to the mirror info. */ - MCORE_INLINE NodeMirrorInfo& GetNodeMirrorInfo(uint32 nodeIndex) { return mNodeMirrorInfos[nodeIndex]; } + MCORE_INLINE NodeMirrorInfo& GetNodeMirrorInfo(size_t nodeIndex) { return mNodeMirrorInfos[nodeIndex]; } /** * Get the mirror info for a given node. * @param nodeIndex The node index to get the info for. * @result A reference to the mirror info. */ - MCORE_INLINE const NodeMirrorInfo& GetNodeMirrorInfo(uint32 nodeIndex) const { return mNodeMirrorInfos[nodeIndex]; } + MCORE_INLINE const NodeMirrorInfo& GetNodeMirrorInfo(size_t nodeIndex) const { return mNodeMirrorInfos[nodeIndex]; } MCORE_INLINE bool GetHasMirrorInfo() const { return (mNodeMirrorInfos.size() != 0); } @@ -735,7 +735,7 @@ namespace EMotionFX * @param startNodeIndex The node to start looking at, for example the node index of the finger bone. * @result Returns the index of the first active node, when moving up the hierarchy towards the root node. Returns MCORE_INVALIDINDEX32 when not found. */ - uint32 FindFirstActiveParentBone(uint32 skeletalLOD, uint32 startNodeIndex) const; + size_t FindFirstActiveParentBone(uint32 skeletalLOD, size_t startNodeIndex) const; /** * Make the geometry LOD levels compatible with the skinning LOD levels. @@ -763,7 +763,7 @@ namespace EMotionFX * @param jointIndex The joint number, which must be in range of [0..GetNumNodes()-1]. * @result The inverse of the bind pose transform. */ - MCORE_INLINE const Transform& GetInverseBindPoseTransform(uint32 nodeIndex) const { return mInvBindPoseTransforms[nodeIndex]; } + MCORE_INLINE const Transform& GetInverseBindPoseTransform(size_t nodeIndex) const { return mInvBindPoseTransforms[nodeIndex]; } void ReleaseTransformData(); void ResizeTransformData(); @@ -776,8 +776,8 @@ namespace EMotionFX void SetThreadIndex(uint32 index) { mThreadIndex = index; } uint32 GetThreadIndex() const { return mThreadIndex; } - Mesh* GetMesh(uint32 lodLevel, uint32 nodeIndex) const; - MeshDeformerStack* GetMeshDeformerStack(uint32 lodLevel, uint32 nodeIndex) const; + Mesh* GetMesh(size_t lodLevel, size_t nodeIndex) const; + MeshDeformerStack* GetMeshDeformerStack(uint32 lodLevel, size_t nodeIndex) const; /** Finds the mesh points for which the specified node is the node with the highest influence. * This is a pretty expensive function which is only intended for use in the editor. @@ -788,17 +788,17 @@ namespace EMotionFX void FindMostInfluencedMeshPoints(const Node* node, AZStd::vector& outPoints) const; MCORE_INLINE Skeleton* GetSkeleton() const { return mSkeleton; } - MCORE_INLINE uint32 GetNumNodes() const { return mSkeleton->GetNumNodes(); } + MCORE_INLINE size_t GetNumNodes() const { return mSkeleton->GetNumNodes(); } - void SetMesh(uint32 lodLevel, uint32 nodeIndex, Mesh* mesh); - void SetMeshDeformerStack(uint32 lodLevel, uint32 nodeIndex, MeshDeformerStack* stack); + void SetMesh(uint32 lodLevel, size_t nodeIndex, Mesh* mesh); + void SetMeshDeformerStack(uint32 lodLevel, size_t nodeIndex, MeshDeformerStack* stack); - bool CheckIfHasMorphDeformer(uint32 lodLevel, uint32 nodeIndex) const; - bool CheckIfHasSkinningDeformer(uint32 lodLevel, uint32 nodeIndex) const; + bool CheckIfHasMorphDeformer(uint32 lodLevel, size_t nodeIndex) const; + bool CheckIfHasSkinningDeformer(uint32 lodLevel, size_t nodeIndex) const; - void RemoveNodeMeshForLOD(uint32 lodLevel, uint32 nodeIndex, bool destroyMesh = true); + void RemoveNodeMeshForLOD(uint32 lodLevel, size_t nodeIndex, bool destroyMesh = true); - void SetNumNodes(uint32 numNodes); + void SetNumNodes(size_t numNodes); void SetUnitType(MCore::Distance::EUnitType unitType); MCore::Distance::EUnitType GetUnitType() const; @@ -808,9 +808,9 @@ namespace EMotionFX EAxis FindBestMatchingMotionExtractionAxis() const; - MCORE_INLINE uint32 GetRetargetRootNodeIndex() const { return mRetargetRootNode; } - MCORE_INLINE Node* GetRetargetRootNode() const { return (mRetargetRootNode != MCORE_INVALIDINDEX32) ? mSkeleton->GetNode(mRetargetRootNode) : nullptr; } - void SetRetargetRootNodeIndex(uint32 nodeIndex); + MCORE_INLINE size_t GetRetargetRootNodeIndex() const { return mRetargetRootNode; } + MCORE_INLINE Node* GetRetargetRootNode() const { return (mRetargetRootNode != InvalidIndex) ? mSkeleton->GetNode(mRetargetRootNode) : nullptr; } + void SetRetargetRootNodeIndex(size_t nodeIndex); void SetRetargetRootNode(Node* node); void AutoSetupSkeletalLODsBasedOnSkinningData(const AZStd::vector& alwaysIncludeJoints); @@ -846,7 +846,7 @@ namespace EMotionFX void Finalize(LoadRequirement loadReq = LoadRequirement::AllowAsyncLoad); private: - void InsertJointAndParents(AZ::u32 jointIndex, AZStd::unordered_set& includedJointIndices); + void InsertJointAndParents(size_t jointIndex, AZStd::unordered_set& includedJointIndices); AZStd::unordered_map ConstructSkinToSkeletonIndexMap(const AZ::Data::Asset& skinMetaAsset); void ConstructMeshes(); @@ -932,8 +932,8 @@ namespace EMotionFX MCore::Distance::EUnitType mFileUnitType; /**< The unit type used on export. */ AZStd::vector mInvBindPoseTransforms; /**< The inverse world space bind pose transforms. */ void* mCustomData; /**< Some custom data, for example a pointer to your own game character class which is linked to this actor. */ - uint32 mMotionExtractionNode; /**< The motion extraction node. This is the node from which to transfer a filtered part of the motion onto the actor instance. Can also be MCORE_INVALIDINDEX32 when motion extraction is disabled. */ - uint32 mRetargetRootNode; /**< The retarget root node, which controls the height displacement of the character. This is most likely the hip or pelvis node. */ + size_t mMotionExtractionNode; /**< The motion extraction node. This is the node from which to transfer a filtered part of the motion onto the actor instance. Can also be MCORE_INVALIDINDEX32 when motion extraction is disabled. */ + size_t mRetargetRootNode; /**< The retarget root node, which controls the height displacement of the character. This is most likely the hip or pelvis node. */ uint32 mID; /**< The unique identification number for the actor. */ uint32 mThreadIndex; /**< The thread number we are running on, which is a value starting at 0, up to the number of threads in the job system. */ AZ::Aabb m_staticAabb; /**< The static AABB. */ diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.cpp index 34af57026a..eaa09f92c0 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.cpp @@ -1356,7 +1356,7 @@ namespace EMotionFX void ActorInstance::MotionExtractionCompensate(Transform& inOutMotionExtractionNodeTransform, EMotionExtractionFlags motionExtractionFlags) const { - MCORE_ASSERT(mActor->GetMotionExtractionNodeIndex() != MCORE_INVALIDINDEX32); + MCORE_ASSERT(mActor->GetMotionExtractionNodeIndex() != InvalidIndex); Transform bindPoseTransform = mTransformData->GetBindPose()->GetLocalSpaceTransform(mActor->GetMotionExtractionNodeIndex()); MotionExtractionCompensate(inOutMotionExtractionNodeTransform, bindPoseTransform, motionExtractionFlags); @@ -1365,8 +1365,8 @@ namespace EMotionFX // Remove the trajectory transform from the motion extraction node to prevent double transformation. void ActorInstance::MotionExtractionCompensate(EMotionExtractionFlags motionExtractionFlags) { - const uint32 motionExtractIndex = mActor->GetMotionExtractionNodeIndex(); - if (motionExtractIndex == MCORE_INVALIDINDEX32) + const size_t motionExtractIndex = mActor->GetMotionExtractionNodeIndex(); + if (motionExtractIndex == InvalidIndex) { return; } @@ -1396,7 +1396,7 @@ namespace EMotionFX // Apply the motion extraction delta transform to the actor instance. void ActorInstance::ApplyMotionExtractionDelta(const Transform& trajectoryDelta) { - if (mActor->GetMotionExtractionNodeIndex() == MCORE_INVALIDINDEX32) + if (mActor->GetMotionExtractionNodeIndex() == InvalidIndex) { return; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlend2AdditiveNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlend2AdditiveNode.cpp index 703838f22b..e6ce8c6119 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlend2AdditiveNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlend2AdditiveNode.cpp @@ -443,7 +443,7 @@ namespace EMotionFX FilterEvents(animGraphInstance, eventMode, nodeA, nodeB, weight, data); // Output motion extraction deltas. - if (animGraphInstance->GetActorInstance()->GetActor()->GetMotionExtractionNodeIndex() != MCORE_INVALIDINDEX32) + if (animGraphInstance->GetActorInstance()->GetActor()->GetMotionExtractionNodeIndex() != InvalidIndex) { UpdateMotionExtraction(animGraphInstance, nodeA, nodeB, weight, uniqueData); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlend2LegacyNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlend2LegacyNode.cpp index c94bf09eb5..7e2fdd4736 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlend2LegacyNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlend2LegacyNode.cpp @@ -461,7 +461,7 @@ namespace EMotionFX eventMode = EVENTMODE_BOTHNODES; } FilterEvents(animGraphInstance, eventMode, nodeA, nodeB, weight, data); - if (animGraphInstance->GetActorInstance()->GetActor()->GetMotionExtractionNodeIndex() != MCORE_INVALIDINDEX32) + if (animGraphInstance->GetActorInstance()->GetActor()->GetMotionExtractionNodeIndex() != InvalidIndex) { UpdateMotionExtraction(animGraphInstance, nodeA, nodeB, weight, uniqueData); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlend2Node.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlend2Node.cpp index 3cfff94f72..f3b9ee2014 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlend2Node.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlend2Node.cpp @@ -405,7 +405,7 @@ namespace EMotionFX FilterEvents(animGraphInstance, m_eventMode, nodeA, nodeB, weight, data); - if (animGraphInstance->GetActorInstance()->GetActor()->GetMotionExtractionNodeIndex() != MCORE_INVALIDINDEX32) + if (animGraphInstance->GetActorInstance()->GetActor()->GetMotionExtractionNodeIndex() != InvalidIndex) { UpdateMotionExtraction(animGraphInstance, nodeA, nodeB, weight, uniqueData); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeFootIKNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeFootIKNode.cpp index 4e4f0ed4e4..8e0e67e95a 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeFootIKNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeFootIKNode.cpp @@ -1021,7 +1021,7 @@ namespace EMotionFX // Adjust the hip position by moving it up or down if that would result in a more natural look. float hipHeightAdjustment = 0.0f; - if (GetAdjustHip(animGraphInstance) && uniqueData->m_hipJointIndex != MCORE_INVALIDINDEX32) + if (GetAdjustHip(animGraphInstance) && uniqueData->m_hipJointIndex != InvalidIndex) { hipHeightAdjustment = AdjustHip(animGraphInstance, uniqueData, inputPose->GetPose(), outputPose->GetPose(), intersectionResults, true /* allowHipAdjust */); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeFootIKNode.h b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeFootIKNode.h index ed2d8113f4..0e46f156af 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeFootIKNode.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeFootIKNode.h @@ -87,7 +87,7 @@ namespace EMotionFX struct Leg { - AZ::u32 m_jointIndices[4]; // Use LegJointId as index into this array. + size_t m_jointIndices[4]; // Use LegJointId as index into this array. AZ::u8 m_flags = static_cast(LegFlags::FirstUpdate); AZ::Vector3 m_footLockPosition = AZ::Vector3::CreateZero(); AZ::Quaternion m_footLockRotation; @@ -138,7 +138,7 @@ namespace EMotionFX float m_hipCorrectionTarget = 0.0f; float m_curHipCorrection = 0.0f; float m_timeDelta = 0.0f; - AZ::u32 m_hipJointIndex = MCORE_INVALIDINDEX32; + size_t m_hipJointIndex = InvalidIndex; AnimGraphEventBuffer m_eventBuffer; }; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/DualQuatSkinDeformer.h b/Gems/EMotionFX/Code/EMotionFX/Source/DualQuatSkinDeformer.h index b1f3387df7..fc1c986b68 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/DualQuatSkinDeformer.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/DualQuatSkinDeformer.h @@ -111,7 +111,7 @@ namespace EMotionFX * This does not alter the value returned by GetNumLocalBones(). * @param numBones The number of bones to pre-allocate space for. */ - MCORE_INLINE void ReserveLocalBones(uint32 numBones) { m_bones.reserve(numBones); } + MCORE_INLINE void ReserveLocalBones(size_t numBones) { m_bones.reserve(numBones); } protected: /** diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ChunkProcessors.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ChunkProcessors.cpp index 18ec99b435..b6b0b091a2 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ChunkProcessors.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ChunkProcessors.cpp @@ -1165,6 +1165,10 @@ namespace EMotionFX } actor->SetMotionExtractionNodeIndex(fileInformation.mMotionExtractionNodeIndex); + if (fileInformation.mMotionExtractionNodeIndex != MCORE_INVALIDINDEX32) + { + actor->SetMotionExtractionNodeIndex(fileInformation.mMotionExtractionNodeIndex); + } // actor->SetRetargetOffset( fileInformation.mRetargetRootOffset ); actor->SetUnitType(static_cast(fileInformation.mUnitType)); actor->SetFileUnitType(actor->GetUnitType()); @@ -1211,8 +1215,14 @@ namespace EMotionFX MCore::LogDetailedInfo(" + UnitType = %d", fileInformation.mUnitType); } - actor->SetMotionExtractionNodeIndex(fileInformation.mMotionExtractionNodeIndex); - actor->SetRetargetRootNodeIndex(fileInformation.mRetargetRootNodeIndex); + if (fileInformation.mMotionExtractionNodeIndex != MCORE_INVALIDINDEX32) + { + actor->SetMotionExtractionNodeIndex(fileInformation.mMotionExtractionNodeIndex); + } + if (fileInformation.mRetargetRootNodeIndex != MCORE_INVALIDINDEX32) + { + actor->SetRetargetRootNodeIndex(fileInformation.mRetargetRootNodeIndex); + } actor->SetUnitType(static_cast(fileInformation.mUnitType)); actor->SetFileUnitType(actor->GetUnitType()); @@ -1258,8 +1268,14 @@ namespace EMotionFX MCore::LogDetailedInfo(" + UnitType = %d", fileInformation.mUnitType); } - actor->SetMotionExtractionNodeIndex(fileInformation.mMotionExtractionNodeIndex); - actor->SetRetargetRootNodeIndex(fileInformation.mRetargetRootNodeIndex); + if (fileInformation.mMotionExtractionNodeIndex != MCORE_INVALIDINDEX32) + { + actor->SetMotionExtractionNodeIndex(fileInformation.mMotionExtractionNodeIndex); + } + if (fileInformation.mRetargetRootNodeIndex != MCORE_INVALIDINDEX32) + { + actor->SetRetargetRootNodeIndex(fileInformation.mRetargetRootNodeIndex); + } actor->SetUnitType(static_cast(fileInformation.mUnitType)); actor->SetFileUnitType(actor->GetUnitType()); actor->SetOptimizeSkeleton(fileInformation.mOptimizeSkeleton == 0? false : true); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.cpp index 36fc898ed1..1203e3762a 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.cpp @@ -850,7 +850,7 @@ namespace EMotionFX //--------------------------------------------------------------- - VertexAttributeLayer* Mesh::GetSharedVertexAttributeLayer(uint32 layerNr) + VertexAttributeLayer* Mesh::GetSharedVertexAttributeLayer(size_t layerNr) { MCORE_ASSERT(layerNr < mSharedVertexAttributes.size()); return mSharedVertexAttributes[layerNr]; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.h b/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.h index a0a99f2961..4a86a9875d 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.h @@ -242,7 +242,7 @@ namespace EMotionFX * @param nr The SubMesh number to get. * @result A pointer to the SubMesh. */ - MCORE_INLINE SubMesh* GetSubMesh(uint32 nr) const; + MCORE_INLINE SubMesh* GetSubMesh(size_t nr) const; /** * Set the value for a given submesh. @@ -279,7 +279,7 @@ namespace EMotionFX * @param layerNr The layer number to get the attributes from. Must be below the value returned by GetNumSharedVertexAttributeLayers(). * @result A pointer to the array of shared vertex attributes. You can typecast this pointer if you know the type of the vertex attributes. */ - VertexAttributeLayer* GetSharedVertexAttributeLayer(uint32 layerNr); + VertexAttributeLayer* GetSharedVertexAttributeLayer(size_t layerNr); /** * Adds a new layer of shared vertex attributes. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.inl b/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.inl index 4ee52eaf19..6a29a3de69 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.inl +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.inl @@ -30,7 +30,7 @@ MCORE_INLINE size_t Mesh::GetNumSubMeshes() const } -MCORE_INLINE SubMesh* Mesh::GetSubMesh(uint32 nr) const +MCORE_INLINE SubMesh* Mesh::GetSubMesh(size_t nr) const { MCORE_ASSERT(nr < mSubMeshes.size()); return mSubMeshes[nr]; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Node.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Node.cpp index a712ffe337..5474087574 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Node.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Node.cpp @@ -20,11 +20,11 @@ namespace EMotionFX Node::Node(const char* name, Skeleton* skeleton) : BaseObject() { - mParentIndex = MCORE_INVALIDINDEX32; - mNodeIndex = MCORE_INVALIDINDEX32; // hasn't been set yet + mParentIndex = InvalidIndex; + mNodeIndex = InvalidIndex; // hasn't been set yet mSkeletalLODs = 0xFFFFFFFF; // set all bits of the integer to 1, which enables this node in all LOD levels on default mSkeleton = skeleton; - mSemanticNameID = MCORE_INVALIDINDEX32; + mSemanticNameID = InvalidIndex; mNodeFlags = FLAG_INCLUDEINBOUNDSCALC; if (name) @@ -33,20 +33,20 @@ namespace EMotionFX } else { - mNameID = MCORE_INVALIDINDEX32; + mNameID = InvalidIndex; } } - Node::Node(uint32 nameID, Skeleton* skeleton) + Node::Node(size_t nameID, Skeleton* skeleton) : BaseObject() { - mParentIndex = MCORE_INVALIDINDEX32; - mNodeIndex = MCORE_INVALIDINDEX32; // hasn't been set yet + mParentIndex = InvalidIndex; + mNodeIndex = InvalidIndex; // hasn't been set yet mSkeletalLODs = 0xFFFFFFFF;// set all bits of the integer to 1, which enables this node in all LOD levels on default mSkeleton = skeleton; mNameID = nameID; - mSemanticNameID = MCORE_INVALIDINDEX32; + mSemanticNameID = InvalidIndex; mNodeFlags = FLAG_INCLUDEINBOUNDSCALC; } @@ -69,82 +69,12 @@ namespace EMotionFX // create a node - Node* Node::Create(uint32 nameID, Skeleton* skeleton) + Node* Node::Create(size_t nameID, Skeleton* skeleton) { return aznew Node(nameID, skeleton); } - /* - // create a clone of this node - Node* Node::Clone(Actor* actor) const - { - Node* result = Node::Create(GetName(), actor); - - // copy attributes - result->mParentIndex = mParentIndex; - result->mNodeIndex = mNodeIndex; - result->mNameID = mNameID; - result->mSkeletalLODs = mSkeletalLODs; - //result->mMotionLODs = mMotionLODs; - result->mChildIndices = mChildIndices; - //result->mImportanceFactor = mImportanceFactor; - result->mNodeFlags = mNodeFlags; - result->mSemanticNameID = mSemanticNameID; - - // copy the node attributes - for (uint32 i=0; iAddAttribute( mAttributes[i]->Clone() ); - - // copy the meshes - const uint32 numLODs = mLODs.GetLength(); - if (result->mLODs.GetLength() < numLODs) - result->mLODs.Resize( numLODs ); - - for (uint32 i=0; imLODs[i].mMesh = realMesh->Clone(actor, result); - else - result->mLODs[i].mMesh = nullptr; - } - - // copy the collision meshes - for (uint32 i=0; imLODs[i].mColMesh = realMesh->Clone(actor, result); - else - result->mLODs[i].mColMesh = nullptr; - } - - // clone node stacks - for (uint32 i=0; imLODs[i].mStack = realStack->Clone(result->mLODs[i].mMesh, actor); - else - result->mLODs[i].mStack = nullptr; - } - - // clone node collision stacks if desired - for (uint32 i=0; imLODs[i].mColStack = realStack->Clone(result->mLODs[i].mColMesh, actor); - else - result->mLODs[i].mColStack = nullptr; - } - - // return the resulting clone - return result; - } - */ - // create a clone of this node Node* Node::Clone(Skeleton* skeleton) const { @@ -160,9 +90,9 @@ namespace EMotionFX // copy the node attributes result->mAttributes.reserve(mAttributes.size()); - for (uint32 i = 0; i < mAttributes.size(); i++) + for (const NodeAttribute* mAttribute : mAttributes) { - result->AddAttribute(mAttributes[i]->Clone()); + result->AddAttribute(mAttribute->Clone()); } // return the resulting clone @@ -173,7 +103,7 @@ namespace EMotionFX // removes all attributes void Node::RemoveAllAttributes() { - while (mAttributes.size()) + while (!mAttributes.empty()) { mAttributes.back()->Destroy(); mAttributes.pop_back(); @@ -182,16 +112,15 @@ namespace EMotionFX // get the total number of children - uint32 Node::GetNumChildNodesRecursive() const + size_t Node::GetNumChildNodesRecursive() const { // the number of total child nodes which include the childs of the childs, too - uint32 result = 0; + size_t result = 0; // retrieve the number of child nodes of the actual node - const uint32 numChildNodes = GetNumChildNodes(); - for (uint32 i = 0; i < numChildNodes; ++i) + for (size_t childIndex : mChildIndices) { - mSkeleton->GetNode(mChildIndices[i])->RecursiveCountChildNodes(result); + mSkeleton->GetNode(childIndex)->RecursiveCountChildNodes(result); } return result; @@ -199,22 +128,21 @@ namespace EMotionFX // recursively count the number of nodes down the hierarchy - void Node::RecursiveCountChildNodes(uint32& numNodes) + void Node::RecursiveCountChildNodes(size_t& numNodes) { // increase the counter numNodes++; // recurse down the hierarchy - const uint32 numChildNodes = mChildIndices.size(); - for (uint32 i = 0; i < numChildNodes; ++i) + for (size_t childIndex : mChildIndices) { - mSkeleton->GetNode(mChildIndices[i])->RecursiveCountChildNodes(numNodes); + mSkeleton->GetNode(childIndex)->RecursiveCountChildNodes(numNodes); } } // recursively go through the parents until a root node is reached and store all parents inside an array - void Node::RecursiveCollectParents(AZStd::vector& parents, bool clearParentsArray) const + void Node::RecursiveCollectParents(AZStd::vector& parents, bool clearParentsArray) const { if (clearParentsArray) { @@ -222,12 +150,12 @@ namespace EMotionFX } // loop until we reached a root node - Node* node = const_cast(this); + const Node* node = this; while (node) { // get the parent index and add it to the list of parents if the current node is not a root node - const uint32 parentIndex = node->GetParentIndex(); - if (parentIndex != MCORE_INVALIDINDEX32) + const size_t parentIndex = node->GetParentIndex(); + if (parentIndex != InvalidIndex) { // check if the parent is already in our array, if not add it so that we only store each node once if (AZStd::find(begin(parents), end(parents), parentIndex) == end(parents)) @@ -243,55 +171,29 @@ namespace EMotionFX // remove the given attribute of the given type from the node - void Node::RemoveAttributeByType(uint32 attributeTypeID, uint32 occurrence) + void Node::RemoveAttributeByType(uint32 attributeTypeID, size_t occurrence) { - // retrieve the number of attributes inside this node - const uint32 numAttributes = GetNumAttributes(); - - // counts the number of occurrences of the attribute to search for - uint32 numOccurredAttibutes = 0; - - // iterate through all node attributes - for (uint32 i = 0; i < numAttributes; ++i) + const auto foundAttribute = AZStd::find_if(begin(mAttributes), end(mAttributes), [attributeTypeID, occurrence, currentOccurrence = size_t{0}] (const NodeAttribute* attribute) mutable { - // get the current node attribute - NodeAttribute* nodeAttribute = GetAttribute(i); - - // check the type of the current node attribute and compare the two - if (nodeAttribute->GetType() == attributeTypeID) + if (attribute->GetType() == attributeTypeID) { - // increase the occurrence counter - numOccurredAttibutes++; - - // check if the found attribute is the one we searched - if (occurrence < numOccurredAttibutes) - { - // remove the attribute and return - RemoveAttribute(i); - return; - } + ++currentOccurrence; + return occurrence < currentOccurrence; } - } + return false; + }); + + mAttributes.erase(foundAttribute); } // remove all attributes of the given type from the node - uint32 Node::RemoveAllAttributesByType(uint32 attributeTypeID) + size_t Node::RemoveAllAttributesByType(uint32 attributeTypeID) { - uint32 attributeNumber = MCORE_INVALIDINDEX32; - uint32 numAttributesRemoved = 0; - - // try to find a node of the given attribute type - while ((attributeNumber = FindAttributeNumber(attributeTypeID)) != MCORE_INVALIDINDEX32) + return AZStd::erase_if(mAttributes, [attributeTypeID](const NodeAttribute* attribute) { - // remove the attribute we found and go again - RemoveAttribute(attributeNumber); - - // increase the number of removed attributes - numAttributesRemoved++; - } - - return numAttributesRemoved; + return attribute->GetType() == attributeTypeID; + }); } @@ -299,23 +201,23 @@ namespace EMotionFX // recursively find the root node (expensive call) Node* Node::FindRoot() const { - uint32 parentIndex = mParentIndex; - Node* curNode = const_cast(this); + size_t parentIndex = mParentIndex; + const Node* curNode = this; - while (parentIndex != MCORE_INVALIDINDEX32) + while (parentIndex != InvalidIndex) { curNode = mSkeleton->GetNode(parentIndex); parentIndex = curNode->GetParentIndex(); } - return curNode; + return const_cast(curNode); } // get the parent node, or nullptr when it doesn't exist Node* Node::GetParentNode() const { - if (mParentIndex != MCORE_INVALIDINDEX32) + if (mParentIndex != InvalidIndex) { return mSkeleton->GetNode(mParentIndex); } @@ -333,7 +235,7 @@ namespace EMotionFX } else { - mNameID = MCORE_INVALIDINDEX32; + mNameID = InvalidIndex; } } @@ -347,12 +249,12 @@ namespace EMotionFX } else { - mSemanticNameID = MCORE_INVALIDINDEX32; + mSemanticNameID = InvalidIndex; } } - void Node::SetParentIndex(uint32 parentNodeIndex) + void Node::SetParentIndex(size_t parentNodeIndex) { mParentIndex = parentNodeIndex; } @@ -389,7 +291,7 @@ namespace EMotionFX // returns true if this is a root node, so if it has no parents bool Node::GetIsRootNode() const { - return (mParentIndex == MCORE_INVALIDINDEX32); + return (mParentIndex == InvalidIndex); } @@ -407,7 +309,7 @@ namespace EMotionFX } - NodeAttribute* Node::GetAttribute(uint32 attributeNr) + NodeAttribute* Node::GetAttribute(size_t attributeNr) { // make sure we are in range MCORE_ASSERT(attributeNr < mAttributes.size()); @@ -417,72 +319,60 @@ namespace EMotionFX } - uint32 Node::FindAttributeNumber(uint32 attributeTypeID) const + size_t Node::FindAttributeNumber(uint32 attributeTypeID) const { // check all attributes, and find where the specific attribute is - const uint32 numAttributes = mAttributes.size(); - for (uint32 i = 0; i < numAttributes; ++i) + const auto foundAttribute = AZStd::find_if(begin(mAttributes), end(mAttributes), [attributeTypeID](const NodeAttribute* attribute) { - if (mAttributes[i]->GetType() == attributeTypeID) - { - return i; - } - } - - // not found - return MCORE_INVALIDINDEX32; + return attribute->GetType() == attributeTypeID; + }); + return foundAttribute != end(mAttributes) ? AZStd::distance(begin(mAttributes), foundAttribute) : InvalidIndex; } NodeAttribute* Node::GetAttributeByType(uint32 attributeType) { // check all attributes - const uint32 numAttributes = mAttributes.size(); - for (uint32 i = 0; i < numAttributes; ++i) + const auto foundAttribute = AZStd::find_if(begin(mAttributes), end(mAttributes), [attributeType](const NodeAttribute* attribute) { - if (mAttributes[i]->GetType() == attributeType) - { - return mAttributes[i]; - } - } - - // not found - return nullptr; + return attribute->GetType() == attributeType; + }); + return foundAttribute != end(mAttributes) ? *foundAttribute : nullptr; } // remove the given attribute - void Node::RemoveAttribute(uint32 index) + void Node::RemoveAttribute(size_t index) { mAttributes.erase(AZStd::next(begin(mAttributes), index)); } - void Node::AddChild(uint32 nodeIndex) + void Node::AddChild(size_t nodeIndex) { mChildIndices.emplace_back(nodeIndex); } - void Node::SetChild(uint32 childNr, uint32 childNodeIndex) + void Node::SetChild(size_t childNr, size_t childNodeIndex) { mChildIndices[childNr] = childNodeIndex; } - void Node::SetNumChildNodes(uint32 numChildNodes) + void Node::SetNumChildNodes(size_t numChildNodes) { mChildIndices.resize(numChildNodes); } - void Node::PreAllocNumChildNodes(uint32 numChildNodes) + void Node::PreAllocNumChildNodes(size_t numChildNodes) { mChildIndices.reserve(numChildNodes); } - void Node::RemoveChild(uint32 nodeIndex) + void Node::RemoveChild(size_t nodeIndex) { if (const auto it = AZStd::find(begin(mChildIndices), end(mChildIndices), nodeIndex); it != end(mChildIndices)) { @@ -499,11 +389,11 @@ namespace EMotionFX bool Node::GetHasChildNodes() const { - return (mChildIndices.size() > 0); + return !mChildIndices.empty(); } - void Node::SetNodeIndex(uint32 index) + void Node::SetNodeIndex(size_t index) { mNodeIndex = index; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Node.h b/Gems/EMotionFX/Code/EMotionFX/Source/Node.h index 73e8a41c01..fe22a12c8d 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Node.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Node.h @@ -70,7 +70,7 @@ namespace EMotionFX * @param nameID The name ID, generated using the MCore::GetStringIdPool(). * @param skeleton The skeleton where this node will belong to, you still need to manually add it to the skeleton though. */ - static Node* Create(uint32 nameID, Skeleton* skeleton); + static Node* Create(size_t nameID, Skeleton* skeleton); /** * Clone the node. @@ -85,14 +85,14 @@ namespace EMotionFX * In that case this node is a root node. * @param parentNodeIndex The node index of the node where to link this node to. */ - void SetParentIndex(uint32 parentNodeIndex); + void SetParentIndex(size_t parentNodeIndex); /** * Get the parent node's index. * This is either a valid index, or MCORE_INVALIDINDEX32 in case there is no parent node. * @result The index of the parent node, or MCORE_INVALIDINDEX32 in case this node has no parent. */ - MCORE_INLINE uint32 GetParentIndex() const { return mParentIndex; } + MCORE_INLINE size_t GetParentIndex() const { return mParentIndex; } /** * Get the parent node as node pointer. @@ -105,7 +105,7 @@ namespace EMotionFX * @param parents The array to which parent and the parents of the parents of the node will be added. * @param clearParentsArray When true the given parents array will be cleared before filling it. */ - void RecursiveCollectParents(AZStd::vector& parents, bool clearParentsArray = true) const; + void RecursiveCollectParents(AZStd::vector& parents, bool clearParentsArray = true) const; /** * Set the node name. @@ -155,14 +155,14 @@ namespace EMotionFX * same ID number. * @result The node ID number, which can be used for fast compares between nodes. */ - MCORE_INLINE uint32 GetID() const { return mNameID; } + MCORE_INLINE size_t GetID() const { return mNameID; } /** * Get the semantic name ID. * To get the name you can also use GetSemanticName() and GetSemanticNameString(). * @result The semantic name ID. */ - MCORE_INLINE uint32 GetSemanticID() const { return mSemanticNameID; } + MCORE_INLINE size_t GetSemanticID() const { return mSemanticNameID; } /** * Get the number of child nodes attached to this node. @@ -175,48 +175,48 @@ namespace EMotionFX * The current node is not included in the count. * @return The total number of nodes down the hierarchy of this node. */ - uint32 GetNumChildNodesRecursive() const; + size_t GetNumChildNodesRecursive() const; /** * Get a given child's node index. * @param nr The child number. * @result The index of the child node, which is a node number inside the actor. */ - MCORE_INLINE uint32 GetChildIndex(uint32 nr) const { return mChildIndices[nr]; } + MCORE_INLINE size_t GetChildIndex(size_t nr) const { return mChildIndices[nr]; } /** * Checks if the given node is a child of this node. * @param nodeIndex The node to check whether it is a child or not. * @result True if the given node is a child, false if not. */ - MCORE_INLINE bool CheckIfIsChildNode(uint32 nodeIndex) const { return (AZStd::find(begin(mChildIndices), end(mChildIndices), nodeIndex) != end(mChildIndices)); } + MCORE_INLINE bool CheckIfIsChildNode(size_t nodeIndex) const { return (AZStd::find(begin(mChildIndices), end(mChildIndices), nodeIndex) != end(mChildIndices)); } /** * Add a child to this node. * @param nodeIndex The index of the child node to add. */ - void AddChild(uint32 nodeIndex); + void AddChild(size_t nodeIndex); /** * Set the value for a given child node. * @param childNr The child number, which must be in range of [0..GetNumChildNodes()-1]. * @param childNodeIndex The node index for this child. */ - void SetChild(uint32 childNr, uint32 childNodeIndex); + void SetChild(size_t childNr, size_t childNodeIndex); /** * Resize the array of child nodes. * This will grow the child node array so that the value returned by GetNumChildNodes() will return the same value as you specify as parameter here. * @param numChildNodes The number of child nodes to create. Be sure to initialize all of the child nodes using SetChild() though! */ - void SetNumChildNodes(uint32 numChildNodes); + void SetNumChildNodes(size_t numChildNodes); /** * Preallocate the array of child nodes. * Unlike SetNumChildNodes, this will NOT grow the child node array as reported by GetNumChildNodes(). However, it internally pre-allocates memory to make the AddChild() calls faster. * @param numChildNodes The number of child nodes to pre-allocate space for. */ - void PreAllocNumChildNodes(uint32 numChildNodes); + void PreAllocNumChildNodes(size_t numChildNodes); /** * Removes a given child (does not delete it from memory though). @@ -224,7 +224,7 @@ namespace EMotionFX * So you have to adjust the parent pointer of the child node manually. * @param nodeIndex The index of the child to remove. */ - void RemoveChild(uint32 nodeIndex); + void RemoveChild(size_t nodeIndex); /** * Removes all child nodes (not from memory though but just clears the childs pointers in this node). @@ -273,7 +273,7 @@ namespace EMotionFX * @result A pointer to the node attribute. * @see FindNodeAttributeNumber */ - NodeAttribute* GetAttribute(uint32 attributeNr); + NodeAttribute* GetAttribute(size_t attributeNr); /** * Get a given node attribute of a given type. @@ -289,7 +289,7 @@ namespace EMotionFX * @param attributeTypeID The attribute type ID (returned by NodeAttribute::GetType()). * @result The first located attribute number which is of the given type, or MCORE_INVALIDINDEX32 when the attribute of this type could not be located. */ - uint32 FindAttributeNumber(uint32 attributeTypeID) const; + size_t FindAttributeNumber(uint32 attributeTypeID) const; /** * Removes all node attributes from this node. @@ -301,7 +301,7 @@ namespace EMotionFX * Remove the given node attribute from this node. * @param index The index of the node attribute to remove. */ - void RemoveAttribute(uint32 index); + void RemoveAttribute(size_t index); /** * Remove the given node attribute from this node which occurs at the given position. @@ -311,14 +311,14 @@ namespace EMotionFX * @param occurrence The number of node attributes which will be skipped until we reached the * node to remove. */ - void RemoveAttributeByType(uint32 attributeTypeID, uint32 occurrence = 0); + void RemoveAttributeByType(uint32 attributeTypeID, size_t occurrence = 0); /** * Removes all node attributes from this node of the given type. * @param attributeTypeID The attribute type ID (returned by NodeAttribute::GetType()). * @result The number of attributes that have been removed. */ - uint32 RemoveAllAttributesByType(uint32 attributeTypeID); + size_t RemoveAllAttributesByType(uint32 attributeTypeID); //-------------------------------------------- @@ -328,7 +328,7 @@ namespace EMotionFX * So Actor::GetNode( nodeIndex ) will return this node. * @param index The index to use. */ - void SetNodeIndex(uint32 index); + void SetNodeIndex(size_t index); /** * Get the node index value. @@ -336,7 +336,7 @@ namespace EMotionFX * So Actor::GetNode( nodeIndex ) will return this node. * @result The index of the node. */ - MCORE_INLINE uint32 GetNodeIndex() const { return mNodeIndex; } + MCORE_INLINE size_t GetNodeIndex() const { return mNodeIndex; } //------------------------------ @@ -364,7 +364,7 @@ namespace EMotionFX * @param lodLevel The skeletal LOD level to check. * @result Returns true when this node is enabled in the specified LOD level. Otherwise false is returned. */ - MCORE_INLINE bool GetSkeletalLODStatus(uint32 lodLevel) const { return (mSkeletalLODs & (1 << lodLevel)) != 0; } + MCORE_INLINE bool GetSkeletalLODStatus(size_t lodLevel) const { return (mSkeletalLODs & (1 << lodLevel)) != 0; } //-------------------------------------------- @@ -415,13 +415,13 @@ namespace EMotionFX void SetIsAttachmentNode(bool isAttachmentNode); private: - uint32 mNodeIndex; /**< The node index, which is the index into the array of nodes inside the Skeleton class. */ - uint32 mParentIndex; /**< The parent node index, or MCORE_INVALIDINDEX32 when there is no parent. */ + size_t mNodeIndex; /**< The node index, which is the index into the array of nodes inside the Skeleton class. */ + size_t mParentIndex; /**< The parent node index, or MCORE_INVALIDINDEX32 when there is no parent. */ uint32 mSkeletalLODs; /**< The skeletal LOD status values. Each bit represents if this node is enabled or disabled in the given LOD. */ - uint32 mNameID; /**< The ID, which is generated from the name. You can use this for fast compares between nodes. */ - uint32 mSemanticNameID; /**< The semantic name ID, for example "LeftHand" or "RightFoot" or so, this can be used for retargeting. */ + size_t mNameID; /**< The ID, which is generated from the name. You can use this for fast compares between nodes. */ + size_t mSemanticNameID; /**< The semantic name ID, for example "LeftHand" or "RightFoot" or so, this can be used for retargeting. */ Skeleton* mSkeleton; /**< The skeleton where this node belongs to. */ - AZStd::vector mChildIndices; /**< The indices that point to the child nodes. */ + AZStd::vector mChildIndices; /**< The indices that point to the child nodes. */ AZStd::vector mAttributes; /**< The node attributes. */ uint8 mNodeFlags; /**< The node flags are used to store boolean attributes of the node as single bits. */ @@ -437,7 +437,7 @@ namespace EMotionFX * @param nameID The name ID, generated using the MCore::GetStringIdPool(). * @param skeleton The skeleton where this node will belong to. */ - Node(uint32 nameID, Skeleton* skeleton); + Node(size_t nameID, Skeleton* skeleton); /** * The destructor. @@ -450,6 +450,6 @@ namespace EMotionFX * Recursively count the number of nodes down the hierarchy of this node. * @param numNodes The integer containing the current node count. This counter will be increased during recursion. */ - void RecursiveCountChildNodes(uint32& numNodes); + void RecursiveCountChildNodes(size_t& numNodes); }; } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/NodeAttribute.h b/Gems/EMotionFX/Code/EMotionFX/Source/NodeAttribute.h index 30bfbe280c..6fb310d15d 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/NodeAttribute.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/NodeAttribute.h @@ -42,7 +42,7 @@ namespace EMotionFX * Clone the node attribute. * @result Returns a pointer to a newly created exact copy of the node attribute. */ - virtual NodeAttribute* Clone() = 0; + virtual NodeAttribute* Clone() const = 0; protected: /** diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Pose.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Pose.cpp index e42393212d..08581e919e 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Pose.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Pose.cpp @@ -114,16 +114,16 @@ namespace EMotionFX } // - void Pose::SetNumTransforms(uint32 numTransforms) + void Pose::SetNumTransforms(size_t numTransforms) { // resize the buffers mLocalSpaceTransforms.ResizeFast(numTransforms); mModelSpaceTransforms.ResizeFast(numTransforms); - const uint32 oldSize = mFlags.GetLength(); + const size_t oldSize = mFlags.GetLength(); mFlags.ResizeFast(numTransforms); - for (uint32 i = oldSize; i < numTransforms; ++i) + for (size_t i = oldSize; i < numTransforms; ++i) { mFlags[i] = 0; SetLocalSpaceTransform(i, Transform::CreateIdentity()); @@ -257,7 +257,7 @@ namespace EMotionFX // recursively update - void Pose::UpdateModelSpaceTransform(uint32 nodeIndex) const + void Pose::UpdateModelSpaceTransform(size_t nodeIndex) const { Skeleton* skeleton = mActor->GetSkeleton(); @@ -286,7 +286,7 @@ namespace EMotionFX // update the local transform - void Pose::UpdateLocalSpaceTransform(uint32 nodeIndex) const + void Pose::UpdateLocalSpaceTransform(size_t nodeIndex) const { const uint32 flags = mFlags[nodeIndex]; if (flags & FLAG_LOCALTRANSFORMREADY) @@ -316,28 +316,28 @@ namespace EMotionFX // get the local transform - const Transform& Pose::GetLocalSpaceTransform(uint32 nodeIndex) const + const Transform& Pose::GetLocalSpaceTransform(size_t nodeIndex) const { UpdateLocalSpaceTransform(nodeIndex); return mLocalSpaceTransforms[nodeIndex]; } - const Transform& Pose::GetModelSpaceTransform(uint32 nodeIndex) const + const Transform& Pose::GetModelSpaceTransform(size_t nodeIndex) const { UpdateModelSpaceTransform(nodeIndex); return mModelSpaceTransforms[nodeIndex]; } - Transform Pose::GetWorldSpaceTransform(uint32 nodeIndex) const + Transform Pose::GetWorldSpaceTransform(size_t nodeIndex) const { UpdateModelSpaceTransform(nodeIndex); return mModelSpaceTransforms[nodeIndex].Multiplied(mActorInstance->GetWorldSpaceTransform()); } - void Pose::GetWorldSpaceTransform(uint32 nodeIndex, Transform* outResult) const + void Pose::GetWorldSpaceTransform(size_t nodeIndex, Transform* outResult) const { UpdateModelSpaceTransform(nodeIndex); *outResult = mModelSpaceTransforms[nodeIndex]; @@ -346,7 +346,7 @@ namespace EMotionFX // calculate a local transform - void Pose::GetLocalSpaceTransform(uint32 nodeIndex, Transform* outResult) const + void Pose::GetLocalSpaceTransform(size_t nodeIndex, Transform* outResult) const { if ((mFlags[nodeIndex] & FLAG_LOCALTRANSFORMREADY) == false) { @@ -357,7 +357,7 @@ namespace EMotionFX } - void Pose::GetModelSpaceTransform(uint32 nodeIndex, Transform* outResult) const + void Pose::GetModelSpaceTransform(size_t nodeIndex, Transform* outResult) const { UpdateModelSpaceTransform(nodeIndex); *outResult = mModelSpaceTransforms[nodeIndex]; @@ -365,7 +365,7 @@ namespace EMotionFX // set the local transform - void Pose::SetLocalSpaceTransform(uint32 nodeIndex, const Transform& newTransform, bool invalidateGlobalTransforms) + void Pose::SetLocalSpaceTransform(size_t nodeIndex, const Transform& newTransform, bool invalidateGlobalTransforms) { mLocalSpaceTransforms[nodeIndex] = newTransform; mFlags[nodeIndex] |= FLAG_LOCALTRANSFORMREADY; @@ -382,7 +382,7 @@ namespace EMotionFX // mark all child nodes recursively as dirty - void Pose::RecursiveInvalidateModelSpaceTransforms(const Actor* actor, uint32 nodeIndex) + void Pose::RecursiveInvalidateModelSpaceTransforms(const Actor* actor, size_t nodeIndex) { // if this model space transform ain't ready yet assume all child nodes are also not if ((mFlags[nodeIndex] & FLAG_MODELTRANSFORMREADY) == false) @@ -396,15 +396,15 @@ namespace EMotionFX // recurse through all child nodes Skeleton* skeleton = actor->GetSkeleton(); Node* node = skeleton->GetNode(nodeIndex); - const uint32 numChildNodes = node->GetNumChildNodes(); - for (uint32 i = 0; i < numChildNodes; ++i) + const size_t numChildNodes = node->GetNumChildNodes(); + for (size_t i = 0; i < numChildNodes; ++i) { RecursiveInvalidateModelSpaceTransforms(actor, node->GetChildIndex(i)); } } - void Pose::SetModelSpaceTransform(uint32 nodeIndex, const Transform& newTransform, bool invalidateChildGlobalTransforms) + void Pose::SetModelSpaceTransform(size_t nodeIndex, const Transform& newTransform, bool invalidateChildGlobalTransforms) { mModelSpaceTransforms[nodeIndex] = newTransform; @@ -423,7 +423,7 @@ namespace EMotionFX } - void Pose::SetWorldSpaceTransform(uint32 nodeIndex, const Transform& newTransform, bool invalidateChildGlobalTransforms) + void Pose::SetWorldSpaceTransform(size_t nodeIndex, const Transform& newTransform, bool invalidateChildGlobalTransforms) { mModelSpaceTransforms[nodeIndex] = newTransform.Multiplied(mActorInstance->GetWorldSpaceTransformInversed()); mFlags[nodeIndex] &= ~FLAG_LOCALTRANSFORMREADY; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Pose.h b/Gems/EMotionFX/Code/EMotionFX/Source/Pose.h index ae3cfc7031..ef9653e728 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Pose.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Pose.h @@ -53,7 +53,7 @@ namespace EMotionFX void LinkToActorInstance(const ActorInstance* actorInstance, uint8 initialFlags = 0); void LinkToActor(const Actor* actor, uint8 initialFlags = 0, bool clearAllFlags = true); - void SetNumTransforms(uint32 numTransforms); + void SetNumTransforms(size_t numTransforms); void ApplyMorphWeightsToActorInstance(); void ZeroMorphWeights(); @@ -63,20 +63,20 @@ namespace EMotionFX void ForceUpdateFullLocalSpacePose(); void ForceUpdateFullModelSpacePose(); - const Transform& GetLocalSpaceTransform(uint32 nodeIndex) const; - const Transform& GetModelSpaceTransform(uint32 nodeIndex) const; - Transform GetWorldSpaceTransform(uint32 nodeIndex) const; + const Transform& GetLocalSpaceTransform(size_t nodeIndex) const; + const Transform& GetModelSpaceTransform(size_t nodeIndex) const; + Transform GetWorldSpaceTransform(size_t nodeIndex) const; - void GetLocalSpaceTransform(uint32 nodeIndex, Transform* outResult) const; - void GetModelSpaceTransform(uint32 nodeIndex, Transform* outResult) const; - void GetWorldSpaceTransform(uint32 nodeIndex, Transform* outResult) const; + void GetLocalSpaceTransform(size_t nodeIndex, Transform* outResult) const; + void GetModelSpaceTransform(size_t nodeIndex, Transform* outResult) const; + void GetWorldSpaceTransform(size_t nodeIndex, Transform* outResult) const; - void SetLocalSpaceTransform(uint32 nodeIndex, const Transform& newTransform, bool invalidateModelSpaceTransforms = true); - void SetModelSpaceTransform(uint32 nodeIndex, const Transform& newTransform, bool invalidateChildModelSpaceTransforms = true); - void SetWorldSpaceTransform(uint32 nodeIndex, const Transform& newTransform, bool invalidateChildModelSpaceTransforms = true); + void SetLocalSpaceTransform(size_t nodeIndex, const Transform& newTransform, bool invalidateModelSpaceTransforms = true); + void SetModelSpaceTransform(size_t nodeIndex, const Transform& newTransform, bool invalidateChildModelSpaceTransforms = true); + void SetWorldSpaceTransform(size_t nodeIndex, const Transform& newTransform, bool invalidateChildModelSpaceTransforms = true); - void UpdateModelSpaceTransform(uint32 nodeIndex) const; - void UpdateLocalSpaceTransform(uint32 nodeIndex) const; + void UpdateModelSpaceTransform(size_t nodeIndex) const; + void UpdateLocalSpaceTransform(size_t nodeIndex) const; void CompensateForMotionExtraction(EMotionExtractionFlags motionExtractionFlags = (EMotionExtractionFlags)0); void CompensateForMotionExtractionDirect(EMotionExtractionFlags motionExtractionFlags = (EMotionExtractionFlags)0); @@ -202,7 +202,7 @@ namespace EMotionFX const Actor* mActor; const Skeleton* mSkeleton; - void RecursiveInvalidateModelSpaceTransforms(const Actor* actor, uint32 nodeIndex); + void RecursiveInvalidateModelSpaceTransforms(const Actor* actor, size_t nodeIndex); /** * Perform a non-mixed blend into the specified destination pose. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/RagdollInstance.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/RagdollInstance.cpp index 98b4275791..93d4cd19d1 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/RagdollInstance.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/RagdollInstance.cpp @@ -67,7 +67,7 @@ namespace EMotionFX } else { - m_ragdollNodeIndices[jointIndex] = MCORE_INVALIDINDEX32; + m_ragdollNodeIndices[jointIndex] = InvalidIndex; } } @@ -256,7 +256,7 @@ namespace EMotionFX const AZ::Outcome RagdollInstance::GetRagdollNodeIndex(size_t jointIndex) const { const size_t ragdollNodeIndex = m_ragdollNodeIndices[jointIndex]; - if (ragdollNodeIndex == MCORE_INVALIDINDEX32) + if (ragdollNodeIndex == InvalidIndex) { return AZ::Failure(); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Recorder.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Recorder.cpp index 41c7c1e929..923c74aa02 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Recorder.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Recorder.cpp @@ -930,7 +930,7 @@ namespace EMotionFX } // check if we have an active node for the given item - size_t index = MCORE_INVALIDINDEX32; + size_t index = InvalidIndex; for (size_t x = 0; x < numActiveNodes; ++x) { if (mActiveNodes[x]->GetId() == curItem->mNodeId) @@ -941,7 +941,7 @@ namespace EMotionFX } // the node got deactivated, finalize the item - if (index == MCORE_INVALIDINDEX32) + if (index == InvalidIndex) { curItem->mGlobalWeights.Optimize(0.0001f); curItem->mLocalWeights.Optimize(0.0001f); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/SimulatedObjectSetup.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/SimulatedObjectSetup.cpp index 8c98bad5a4..006be1d9a5 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/SimulatedObjectSetup.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/SimulatedObjectSetup.cpp @@ -280,7 +280,7 @@ namespace EMotionFX { if (m_object) { - return m_object->GetSimulatedRootJointIndex(this) != MCORE_INVALIDINDEX32; + return m_object->GetSimulatedRootJointIndex(this) != InvalidIndex; } return false; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Skeleton.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Skeleton.cpp index 5860a0b452..24983c3a71 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Skeleton.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Skeleton.cpp @@ -44,14 +44,13 @@ namespace EMotionFX { Skeleton* result = Skeleton::Create(); - const uint32 numNodes = m_nodes.size(); - result->ReserveNodes(numNodes); + result->ReserveNodes(m_nodes.size()); result->m_rootNodes = m_rootNodes; // clone the nodes - for (uint32 i = 0; i < numNodes; ++i) + for (const Node* node : m_nodes) { - result->AddNode(m_nodes[i]->Clone(result)); + result->AddNode(node->Clone(result)); } result->m_bindPose = m_bindPose; @@ -61,7 +60,7 @@ namespace EMotionFX // reserve memory - void Skeleton::ReserveNodes(uint32 numNodes) + void Skeleton::ReserveNodes(size_t numNodes) { m_nodes.reserve(numNodes); } @@ -76,7 +75,7 @@ namespace EMotionFX // remove a node - void Skeleton::RemoveNode(uint32 nodeIndex, bool delFromMem) + void Skeleton::RemoveNode(size_t nodeIndex, bool delFromMem) { m_nodesMap.erase(m_nodes[nodeIndex]->GetNameString()); if (delFromMem) @@ -93,10 +92,9 @@ namespace EMotionFX { if (delFromMem) { - const uint32 numNodes = m_nodes.size(); - for (uint32 i = 0; i < numNodes; ++i) + for (Node* node : m_nodes) { - m_nodes[i]->Destroy(); + node->Destroy(); } } @@ -132,38 +130,28 @@ namespace EMotionFX Node* Skeleton::FindNodeByNameNoCase(const char* name) const { // check the names for all nodes - const uint32 numNodes = m_nodes.size(); - for (uint32 i = 0; i < numNodes; ++i) + const auto foundNode = AZStd::find_if(begin(m_nodes), end(m_nodes), [name](const Node* node) { - if (AzFramework::StringFunc::Equal(m_nodes[i]->GetNameString().c_str(), name, false /* no case */)) - { - return m_nodes[i]; - } - } - - return nullptr; + return AzFramework::StringFunc::Equal(node->GetNameString(), name, false /* no case */); + }); + return foundNode != end(m_nodes) ? *foundNode : nullptr; } // search for a node on ID - Node* Skeleton::FindNodeByID(uint32 id) const + Node* Skeleton::FindNodeByID(size_t id) const { // check the ID's for all nodes - const uint32 numNodes = m_nodes.size(); - for (uint32 i = 0; i < numNodes; ++i) + const auto foundNode = AZStd::find_if(begin(m_nodes), end(m_nodes), [id](const Node* node) { - if (m_nodes[i]->GetID() == id) - { - return m_nodes[i]; - } - } - - return nullptr; + return node->GetID() == id; + }); + return foundNode != end(m_nodes) ? *foundNode : nullptr; } // set a given node - void Skeleton::SetNode(uint32 index, Node* node) + void Skeleton::SetNode(size_t index, Node* node) { if (m_nodes[index]) { @@ -176,11 +164,11 @@ namespace EMotionFX // set the number of nodes - void Skeleton::SetNumNodes(uint32 numNodes) + void Skeleton::SetNumNodes(size_t numNodes) { - uint32 oldLength = m_nodes.size(); + size_t oldLength = m_nodes.size(); m_nodes.resize(numNodes); - for (uint32 i = oldLength; i < numNodes; ++i) + for (size_t i = oldLength; i < numNodes; ++i) { m_nodes[i] = nullptr; } @@ -189,10 +177,10 @@ namespace EMotionFX // update the node indices - void Skeleton::UpdateNodeIndexValues(uint32 startNode) + void Skeleton::UpdateNodeIndexValues(size_t startNode) { - const uint32 numNodes = m_nodes.size(); - for (uint32 i = startNode; i < numNodes; ++i) + const size_t numNodes = m_nodes.size(); + for (size_t i = startNode; i < numNodes; ++i) { m_nodes[i]->SetNodeIndex(i); } @@ -200,21 +188,21 @@ namespace EMotionFX // reserve memory for the root nodes array - void Skeleton::ReserveRootNodes(uint32 numNodes) + void Skeleton::ReserveRootNodes(size_t numNodes) { m_rootNodes.reserve(numNodes); } // add a root node - void Skeleton::AddRootNode(uint32 nodeIndex) + void Skeleton::AddRootNode(size_t nodeIndex) { m_rootNodes.emplace_back(nodeIndex); } // remove a given root node - void Skeleton::RemoveRootNode(uint32 nr) + void Skeleton::RemoveRootNode(size_t nr) { m_rootNodes.erase(AZStd::next(begin(m_rootNodes), nr)); } @@ -230,8 +218,8 @@ namespace EMotionFX // log all node names void Skeleton::LogNodes() { - const uint32 numNodes = m_nodes.size(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = m_nodes.size(); + for (size_t i = 0; i < numNodes; ++i) { MCore::LogInfo("%d = '%s'", i, m_nodes[i]->GetName()); } @@ -239,10 +227,10 @@ namespace EMotionFX // calculate the hierarchy depth for a given node - uint32 Skeleton::CalcHierarchyDepthForNode(uint32 nodeIndex) const + size_t Skeleton::CalcHierarchyDepthForNode(size_t nodeIndex) const { - uint32 result = 0; - Node* curNode = m_nodes[nodeIndex]; + size_t result = 0; + const Node* curNode = m_nodes[nodeIndex]; while (curNode->GetParentNode()) { result++; @@ -253,18 +241,18 @@ namespace EMotionFX } - Node* Skeleton::FindNodeAndIndexByName(const AZStd::string& name, AZ::u32& outIndex) const + Node* Skeleton::FindNodeAndIndexByName(const AZStd::string& name, size_t& outIndex) const { if (name.empty()) { - outIndex = MCORE_INVALIDINDEX32; + outIndex = InvalidIndex; return nullptr; } Node* joint = FindNodeByNameNoCase(name.c_str()); if (!joint) { - outIndex = MCORE_INVALIDINDEX32; + outIndex = InvalidIndex; return nullptr; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Skeleton.h b/Gems/EMotionFX/Code/EMotionFX/Source/Skeleton.h index e5887df0f6..01d3e9dee8 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Skeleton.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Skeleton.h @@ -33,11 +33,11 @@ namespace EMotionFX Skeleton* Clone(); MCORE_INLINE size_t GetNumNodes() const { return m_nodes.size(); } - MCORE_INLINE Node* GetNode(uint32 index) const { return m_nodes[index]; } + MCORE_INLINE Node* GetNode(size_t index) const { return m_nodes[index]; } - void ReserveNodes(uint32 numNodes); + void ReserveNodes(size_t numNodes); void AddNode(Node* node); - void RemoveNode(uint32 nodeIndex, bool delFromMem = true); + void RemoveNode(size_t nodeIndex, bool delFromMem = true); void RemoveAllNodes(bool delFromMem = true); MCORE_INLINE const Pose* GetBindPose() const { return &m_bindPose; } @@ -57,7 +57,7 @@ namespace EMotionFX * @param outIndex This will contain the resulting index, or MCORE_INVALIDINDEX32 in case not found. * @result This returns a pointer to the joint or nullptr when not found. In case of a nullptr, the outIndex will be set to MCORE_INVALIDINDEX32 as well. */ - Node* FindNodeAndIndexByName(const AZStd::string& name, AZ::u32& outIndex) const; + Node* FindNodeAndIndexByName(const AZStd::string& name, size_t& outIndex) const; /** * Search for a node by name (non case sensitive), returns nullptr when no node can be found. @@ -75,21 +75,21 @@ namespace EMotionFX * @param id The ID to search for. * @return A pointer to the node, or nullptr when no node with the given ID found. */ - Node* FindNodeByID(uint32 id) const; + Node* FindNodeByID(size_t id) const; /** * Set the value of a given node. * @param index The node number, which must be in range of [0..GetNumNodes()-1]. * @param node The node value to set at this index. */ - void SetNode(uint32 index, Node* node); + void SetNode(size_t index, Node* node); /** * Set the number of nodes. * This resizes the array of pointers to nodes, but doesn't actually create the nodes. * @param numNodes The number of nodes to allocate space for. */ - void SetNumNodes(uint32 numNodes); + void SetNumNodes(size_t numNodes); /** * Update all the node index values that are returned by the Node::GetNodeIndex() method. @@ -97,7 +97,7 @@ namespace EMotionFX * the nodes have to be updated. As node number 5 could become node number 4 in the example case. * @param startNode The node number to start updating from. */ - void UpdateNodeIndexValues(uint32 startNode = 0); + void UpdateNodeIndexValues(size_t startNode = 0); /** * Get the number of root nodes in the actor. A root node is a node without any parent. @@ -110,28 +110,28 @@ namespace EMotionFX * @param nr The root node number, which must be in range of [0..GetNumRootNodes()-1]. * @result The node index of the given root node. */ - MCORE_INLINE uint32 GetRootNodeIndex(uint32 nr) const { return m_rootNodes[nr]; } + MCORE_INLINE size_t GetRootNodeIndex(size_t nr) const { return m_rootNodes[nr]; } /** * Pre-allocate space for the root nodes array. * This does not alter the value returned by GetNumRootNodes() though. * @param numNodes The absolute number of nodes to pre-allocate space for. */ - void ReserveRootNodes(uint32 numNodes); + void ReserveRootNodes(size_t numNodes); /** * Add a root node to the actor. * This doesn't modify the node itself, but it will add the node to the list of root nodes. * @param nodeIndex The node number/index to add and mark as root node inside the actor. */ - void AddRootNode(uint32 nodeIndex); + void AddRootNode(size_t nodeIndex); /** * Remove a given root node from the list of root nodes stored inside the actor. * This doesn't really remove the node itself, but it just unregisters it as root node inside the actor. * @param nr The root node to remove, which must be in range of [0..GetNumRootNodes()-1]. */ - void RemoveRootNode(uint32 nr); + void RemoveRootNode(size_t nr); /** * Removes all root nodes from the actor. @@ -141,12 +141,12 @@ namespace EMotionFX void RemoveAllRootNodes(); void LogNodes(); - uint32 CalcHierarchyDepthForNode(uint32 nodeIndex) const; + size_t CalcHierarchyDepthForNode(size_t nodeIndex) const; private: AZStd::vector m_nodes; /**< The nodes, including root nodes. */ mutable AZStd::unordered_map m_nodesMap; - AZStd::vector m_rootNodes; /**< The root nodes only. */ + AZStd::vector m_rootNodes; /**< The root nodes only. */ Pose m_bindPose; /**< The bind pose. */ Skeleton(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/SoftSkinDeformer.h b/Gems/EMotionFX/Code/EMotionFX/Source/SoftSkinDeformer.h index 497f38f764..33596e6809 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/SoftSkinDeformer.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/SoftSkinDeformer.h @@ -114,7 +114,7 @@ namespace EMotionFX * This does not alter the value returned by GetNumLocalBones(). * @param numBones The number of bones to pre-allocate space for. */ - MCORE_INLINE void ReserveLocalBones(uint32 numBones) { mNodeNumbers.reserve(numBones); mBoneMatrices.reserve(numBones); } + MCORE_INLINE void ReserveLocalBones(size_t numBones) { mNodeNumbers.reserve(numBones); mBoneMatrices.reserve(numBones); } protected: diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/SpringSolver.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/SpringSolver.cpp index adaea2e6c2..8765a0e991 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/SpringSolver.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/SpringSolver.cpp @@ -47,7 +47,7 @@ namespace EMotionFX m_collisionObjects.reserve(3); } - void SpringSolver::CreateCollider(AZ::u32 skeletonJointIndex, const AzPhysics::ShapeColliderPair& shapePair) + void SpringSolver::CreateCollider(size_t skeletonJointIndex, const AzPhysics::ShapeColliderPair& shapePair) { const Physics::ShapeConfiguration* shapeConfig = shapePair.second.get(); if (!shapeConfig) @@ -77,7 +77,7 @@ namespace EMotionFX { if (exclusionColliderTag == colliderTag) { - const AZ::u32 colliderIndex = aznumeric_caster(m_collisionObjects.size() - 1); + const size_t colliderIndex = m_collisionObjects.size() - 1; particle.m_colliderExclusions.emplace_back(colliderIndex); break; } @@ -105,7 +105,7 @@ namespace EMotionFX if (shapePair.first->m_tag == colliderTag) { // Make sure we can find the joint in the skeleton. - AZ::u32 skeletonJointIndex; + size_t skeletonJointIndex; if (!actor->GetSkeleton()->FindNodeAndIndexByName(nodeConfig.m_name, skeletonJointIndex)) { AZ_Warning("EMotionFX", false, "Cannot find joint '%s' to attach the collider to. Skipping this collider inside simulation '%s'.", nodeConfig.m_name.c_str(), m_name.c_str()); @@ -176,7 +176,7 @@ namespace EMotionFX } } - void SpringSolver::CheckAndExcludeCollider(AZ::u32 colliderIndex, const SimulatedJoint* joint) + void SpringSolver::CheckAndExcludeCollider(size_t colliderIndex, const SimulatedJoint* joint) { const size_t particleIndex = FindParticle(joint->GetSkeletonJointIndex()); AZ_Assert(particleIndex != InvalidIndex, "Expected particle to be found for this joint."); @@ -208,7 +208,7 @@ namespace EMotionFX const size_t numColliders = m_collisionObjects.size(); for (size_t colliderIndex = 0; colliderIndex < numColliders; ++colliderIndex) { - CheckAndExcludeCollider(static_cast(colliderIndex), joint); + CheckAndExcludeCollider(colliderIndex, joint); } break; } @@ -221,7 +221,7 @@ namespace EMotionFX { if (m_collisionObjects[colliderIndex].m_jointIndex == joint->GetSkeletonJointIndex()) { - CheckAndExcludeCollider(static_cast(colliderIndex), joint); + CheckAndExcludeCollider(colliderIndex, joint); } } break; @@ -235,13 +235,13 @@ namespace EMotionFX { if (joint->GetSkeletonJointIndex() == m_collisionObjects[colliderIndex].m_jointIndex) { - CheckAndExcludeCollider(static_cast(colliderIndex), joint); + CheckAndExcludeCollider(colliderIndex, joint); } const SimulatedJoint* parentJoint = joint->FindParentSimulatedJoint(); if (parentJoint && parentJoint->GetSkeletonJointIndex() == m_collisionObjects[colliderIndex].m_jointIndex) { - CheckAndExcludeCollider(static_cast(colliderIndex), joint); + CheckAndExcludeCollider(colliderIndex, joint); } const size_t numChildJoints = joint->CalculateNumChildSimulatedJoints(); @@ -250,7 +250,7 @@ namespace EMotionFX const SimulatedJoint* childJoint = joint->FindChildSimulatedJoint(childIndex); if (m_collisionObjects[colliderIndex].m_jointIndex == childJoint->GetSkeletonJointIndex()) { - CheckAndExcludeCollider(static_cast(colliderIndex), joint); + CheckAndExcludeCollider(colliderIndex, joint); } } } @@ -271,8 +271,8 @@ namespace EMotionFX SpringSolver::Particle* SpringSolver::AddJoint(const SimulatedJoint* joint) { AZ_Assert(joint, "Expected the joint be a valid pointer."); - const AZ::u32 jointIndex = joint->GetSkeletonJointIndex(); - if (jointIndex == InvalidIndex32) + const size_t jointIndex = joint->GetSkeletonJointIndex(); + if (jointIndex == InvalidIndex) { return nullptr; } @@ -409,8 +409,8 @@ namespace EMotionFX // Initialize all rest lengths. for (Spring& spring : m_springs) { - const AZ::u32 jointIndexA = m_particles[spring.m_particleA].m_joint->GetSkeletonJointIndex(); - const AZ::u32 jointIndexB = m_particles[spring.m_particleB].m_joint->GetSkeletonJointIndex(); + const size_t jointIndexA = m_particles[spring.m_particleA].m_joint->GetSkeletonJointIndex(); + const size_t jointIndexB = m_particles[spring.m_particleB].m_joint->GetSkeletonJointIndex(); const Pose* bindPose = m_actorInstance->GetTransformData()->GetBindPose(); const float restLength = (bindPose->GetModelSpaceTransform(jointIndexB).mPosition - bindPose->GetModelSpaceTransform(jointIndexA).mPosition).GetLength(); if (restLength > AZ::Constants::FloatEpsilon) @@ -526,7 +526,7 @@ namespace EMotionFX return m_gravity; } - size_t SpringSolver::FindParticle(AZ::u32 jointIndex) const + size_t SpringSolver::FindParticle(size_t jointIndex) const { const size_t numParticles = m_particles.size(); for (size_t i = 0; i < numParticles; ++i) @@ -564,14 +564,14 @@ namespace EMotionFX particle.m_joint = joint; particle.m_pos = m_actorInstance->GetTransformData()->GetBindPose()->GetModelSpaceTransform(joint->GetSkeletonJointIndex()).mPosition; particle.m_oldPos = particle.m_pos; - particle.m_parentParticleIndex = static_cast(m_parentParticle); + particle.m_parentParticleIndex = m_parentParticle; m_particles.emplace_back(particle); return m_particles.size() - 1; } - bool SpringSolver::AddSupportSpring(AZ::u32 nodeA, AZ::u32 nodeB, float restLength) + bool SpringSolver::AddSupportSpring(size_t nodeA, size_t nodeB, float restLength) { - if (nodeA == InvalidIndex32 || nodeB == InvalidIndex32) + if (nodeA == InvalidIndex || nodeB == InvalidIndex) { return false; } @@ -608,7 +608,7 @@ namespace EMotionFX return AddSupportSpring(nodeA->GetNodeIndex(), nodeB->GetNodeIndex(), restLength); } - bool SpringSolver::RemoveJoint(AZ::u32 jointIndex) + bool SpringSolver::RemoveJoint(size_t jointIndex) { const size_t particleIndex = FindParticle(jointIndex); if (particleIndex == InvalidIndex) @@ -646,7 +646,7 @@ namespace EMotionFX return RemoveJoint(node->GetNodeIndex()); } - bool SpringSolver::RemoveSupportSpring(AZ::u32 jointIndexA, AZ::u32 jointIndexB) + bool SpringSolver::RemoveSupportSpring(size_t jointIndexA, size_t jointIndexB) { const size_t particleA = FindParticle(jointIndexA); if (particleA == InvalidIndex) @@ -833,7 +833,7 @@ namespace EMotionFX // Apply cone limit when needed. if (particleB.m_joint->GetConeAngleLimit() < 180.0f - 0.001f) { - if (particleB.m_parentParticleIndex != InvalidIndex32) + if (particleB.m_parentParticleIndex != InvalidIndex) { particleB.m_limitDir = particleB.m_pos - m_particles[particleB.m_parentParticleIndex].m_pos; } @@ -1008,7 +1008,7 @@ namespace EMotionFX { for (CollisionObject& colObject : m_collisionObjects) { - if (colObject.m_jointIndex != InvalidIndex32) + if (colObject.m_jointIndex != InvalidIndex) { const Transform jointWorldTransform = pose.GetWorldSpaceTransform(colObject.m_jointIndex); colObject.m_globalStart = jointWorldTransform.TransformPoint(colObject.m_start); @@ -1028,7 +1028,7 @@ namespace EMotionFX { for (CollisionObject& colObject : m_collisionObjects) { - if (colObject.m_jointIndex != InvalidIndex32) + if (colObject.m_jointIndex != InvalidIndex) { const Transform& jointTransform = pose.GetModelSpaceTransform(colObject.m_jointIndex); colObject.m_globalStart = jointTransform.TransformPoint(colObject.m_start); @@ -1072,7 +1072,7 @@ namespace EMotionFX for (size_t colliderIndex = 0; colliderIndex < numColliders; ++colliderIndex) { // Skip colliders in the exclusion list. - if (AZStd::find(particle.m_colliderExclusions.begin(), particle.m_colliderExclusions.end(), static_cast(colliderIndex)) != particle.m_colliderExclusions.end()) + if (AZStd::find(particle.m_colliderExclusions.begin(), particle.m_colliderExclusions.end(), colliderIndex) != particle.m_colliderExclusions.end()) { continue; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/SpringSolver.h b/Gems/EMotionFX/Code/EMotionFX/Source/SpringSolver.h index 6d4b2e8128..ce77d1c655 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/SpringSolver.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/SpringSolver.h @@ -54,8 +54,8 @@ namespace EMotionFX AZ::Vector3 m_force = AZ::Vector3::CreateZero(); /**< The internal force, which contains the gravity and other pulling and pushing forces. */ AZ::Vector3 m_externalForce = AZ::Vector3::CreateZero(); /**< A user defined external force, which is added on top of the internal force. Can be used to simulate wind etc. */ AZ::Vector3 m_limitDir = AZ::Vector3::CreateZero(); /**< The joint limit direction vector, used for the cone angle limit. This is the center direction of the cone. */ - AZStd::vector m_colliderExclusions; /**< Index values inside the collider array. Colliders listed in this list should be ignored durin collision detection. */ - AZ::u32 m_parentParticleIndex = ~0U; /**< The parent particle index. */ + AZStd::vector m_colliderExclusions; /**< Index values inside the collider array. Colliders listed in this list should be ignored durin collision detection. */ + size_t m_parentParticleIndex = InvalidIndex; /**< The parent particle index. */ }; class EMFX_API CollisionObject @@ -76,7 +76,7 @@ namespace EMotionFX private: CollisionType m_type = CollisionType::Sphere; /**< The collision primitive type (a sphere, or capsule, etc). */ - AZ::u32 m_jointIndex = ~0U; /**< The joint index to attach to, or ~0 for non-attached. */ + size_t m_jointIndex = InvalidIndex; /**< The joint index to attach to, or ~0 for non-attached. */ AZ::Vector3 m_globalStart = AZ::Vector3::CreateZero(); /**< The world space start position, or the world space center in case of a sphere. */ AZ::Vector3 m_globalEnd = AZ::Vector3::CreateZero(); /**< The world space end position. This is ignored in case of a sphere. */ AZ::Vector3 m_start = AZ::Vector3::CreateZero(); /**< The start of the primitive. In case of a sphere the center, in case of a capsule the start of the capsule. */ @@ -108,7 +108,7 @@ namespace EMotionFX AZ_INLINE Particle& GetParticle(size_t index) { return m_particles[index]; } AZ_INLINE size_t GetNumParticles() const { return m_particles.size(); } - AZ_INLINE Spring& GetSpring(AZ::u32 index) { return m_springs[index]; } + AZ_INLINE Spring& GetSpring(size_t index) { return m_springs[index]; } AZ_INLINE size_t GetNumSprings() const { return m_springs.size(); } void SetParentParticle(size_t parentParticleIndex) { m_parentParticle = parentParticleIndex; } @@ -119,12 +119,12 @@ namespace EMotionFX size_t GetNumIterations() const; Particle* AddJoint(const SimulatedJoint* joint); - bool AddSupportSpring(AZ::u32 nodeA, AZ::u32 nodeB, float restLength = -1.0f); + bool AddSupportSpring(size_t nodeA, size_t nodeB, float restLength = -1.0f); bool AddSupportSpring(AZStd::string_view nodeNameA, AZStd::string_view nodeNameB, float restLength = -1.0f); - bool RemoveJoint(AZ::u32 jointIndex); + bool RemoveJoint(size_t jointIndex); bool RemoveJoint(AZStd::string_view nodeName); - bool RemoveSupportSpring(AZ::u32 jointIndexA, AZ::u32 jointIndexB); + bool RemoveSupportSpring(size_t jointIndexA, size_t jointIndexB); bool RemoveSupportSpring(AZStd::string_view nodeNameA, AZStd::string_view nodeNameB); void SetStiffnessFactor(float factor) { m_stiffnessFactor = factor; } @@ -135,19 +135,19 @@ namespace EMotionFX float GetGravityFactor() const { return m_gravityFactor; } float GetDampingFactor() const { return m_dampingFactor; } - size_t FindParticle(AZ::u32 jointIndex) const; + size_t FindParticle(size_t jointIndex) const; Particle* FindParticle(AZStd::string_view nodeName); AZ_INLINE void RemoveCollisionObject(size_t index) { m_collisionObjects.erase(m_collisionObjects.begin() + index); } AZ_INLINE void RemoveAllCollisionObjects() { m_collisionObjects.clear(); } - AZ_INLINE CollisionObject& GetCollisionObject(AZ::u32 index) { return m_collisionObjects[index]; } + AZ_INLINE CollisionObject& GetCollisionObject(size_t index) { return m_collisionObjects[index]; } AZ_INLINE size_t GetNumCollisionObjects() const { return m_collisionObjects.size(); } AZ_INLINE bool GetCollisionEnabled() const { return m_collisionDetection; } AZ_INLINE void SetCollisionEnabled(bool enabled) { m_collisionDetection = enabled; } private: void InitColliders(const InitSettings& initSettings); - void CreateCollider(AZ::u32 skeletonJointIndex, const AzPhysics::ShapeColliderPair& shapePair); + void CreateCollider(size_t skeletonJointIndex, const AzPhysics::ShapeColliderPair& shapePair); void InitColliderFromColliderSetupShape(CollisionObject& collider); void InitCollidersFromColliderSetupShapes(); bool RecursiveAddJoint(const SimulatedJoint* joint, size_t parentParticleIndex); @@ -166,7 +166,7 @@ namespace EMotionFX bool PerformCollision(AZ::Vector3& inOutPos, float jointRadius, const Particle& particle); void PerformConeLimit(Particle& particleA, Particle& particleB, const AZ::Vector3& inputDir); bool CheckIsJointInsideCollider(const CollisionObject& colObject, const Particle& particle) const; - void CheckAndExcludeCollider(AZ::u32 colliderIndex, const SimulatedJoint* joint); + void CheckAndExcludeCollider(size_t colliderIndex, const SimulatedJoint* joint); void UpdateFixedParticles(const Pose& pose); void Stabilize(const Pose& inputPose, Pose& pose, size_t numFrames=5); void InitAutoColliderExclusion(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/SubMesh.h b/Gems/EMotionFX/Code/EMotionFX/Source/SubMesh.h index 1cec56efc6..9455b6b7df 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/SubMesh.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/SubMesh.h @@ -198,28 +198,28 @@ namespace EMotionFX * @param index The bone number, which must be in range of [0..GetNumBones()-1]. * @result The node index value for the given bone. */ - MCORE_INLINE uint32 GetBone(uint32 index) const { return mBones[index]; } + MCORE_INLINE size_t GetBone(size_t index) const { return mBones[index]; } /** * Get direct access to the bone values, by getting a pointer to the first bone index. * Each integer in the array represents the node number that acts as bone on this submesh. * @result A pointer to the array of bones used by this submesh. */ - MCORE_INLINE uint32* GetBones() { return mBones.data(); } + MCORE_INLINE size_t* GetBones() { return mBones.data(); } /** * Get direct access to the bones array. * Each integer in the array represents the node number that acts as bone on this submesh. * @result A read only reference to the array of bones used by this submesh. */ - MCORE_INLINE const AZStd::vector& GetBonesArray() const { return mBones; } + MCORE_INLINE const AZStd::vector& GetBonesArray() const { return mBones; } /** * Get direct access to the bones array. * Each integer in the array represents the node number that acts as bone on this submesh. * @result A reference to the array of bones used by this submesh. */ - MCORE_INLINE AZStd::vector& GetBonesArray() { return mBones; } + MCORE_INLINE AZStd::vector& GetBonesArray() { return mBones; } /** * Reinitialize the bones. @@ -268,7 +268,7 @@ namespace EMotionFX protected: - AZStd::vector mBones; /**< The collection of bones. These are stored as node numbers that point into the actor. */ + AZStd::vector mBones; /**< The collection of bones. These are stored as node numbers that point into the actor. */ uint32 mStartVertex; /**< The start vertex number in the vertex data arrays of the parent mesh. */ uint32 mStartIndex; /**< The start index number in the index array of the parent mesh. */ uint32 mStartPolygon; /**< The start polygon number in the polygon vertex count array of the parent mesh. */ diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentNodesWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentNodesWindow.cpp index 3b24552035..d84b22f5d5 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentNodesWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentNodesWindow.cpp @@ -144,11 +144,11 @@ namespace EMStudio mRemoveNodesButton->setEnabled((mNodeTable->rowCount() != 0) && (mNodeTable->selectedItems().size() != 0)); // counter for attachment nodes - uint16 numAttachmentNodes = 0; + size_t numAttachmentNodes = 0; // set the row count - const uint16 numNodes = mActor->GetNumNodes(); - for (uint16 i = 0; i < numNodes; ++i) + const size_t numNodes = mActor->GetNumNodes(); + for (size_t i = 0; i < numNodes; ++i) { // get the nodegroup EMotionFX::Node* node = mActor->GetSkeleton()->GetNode(i); @@ -162,7 +162,7 @@ namespace EMStudio mNodeTable->setRowCount(numAttachmentNodes); // set header items for the table - QTableWidgetItem* nameHeaderItem = new QTableWidgetItem(AZStd::string::format("Attachment Nodes (%i / %i)", numAttachmentNodes, mActor->GetNumNodes()).c_str()); + QTableWidgetItem* nameHeaderItem = new QTableWidgetItem(AZStd::string::format("Attachment Nodes (%zu / %zu)", numAttachmentNodes, mActor->GetNumNodes()).c_str()); nameHeaderItem->setTextAlignment(Qt::AlignVCenter | Qt::AlignCenter); mNodeTable->setHorizontalHeaderItem(0, nameHeaderItem); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeGroups/NodeGroupWidget.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeGroups/NodeGroupWidget.cpp index 481718ab66..552a6d45e7 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeGroups/NodeGroupWidget.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeGroups/NodeGroupWidget.cpp @@ -168,7 +168,7 @@ namespace EMStudio mNodeTable->setRowCount(mNodeGroup->GetNumNodes()); // set header items for the table - AZStd::string headerText = AZStd::string::format("%s Nodes (%i / %i)", ((mNodeGroup->GetIsEnabledOnDefault()) ? "Enabled" : "Disabled"), mNodeGroup->GetNumNodes(), mActor->GetNumNodes()); + AZStd::string headerText = AZStd::string::format("%s Nodes (%i / %zu)", ((mNodeGroup->GetIsEnabledOnDefault()) ? "Enabled" : "Disabled"), mNodeGroup->GetNumNodes(), mActor->GetNumNodes()); QTableWidgetItem* nameHeaderItem = new QTableWidgetItem(headerText.c_str()); nameHeaderItem->setTextAlignment(Qt::AlignVCenter | Qt::AlignCenter); mNodeTable->setHorizontalHeaderItem(0, nameHeaderItem); diff --git a/Gems/EMotionFX/Code/MCore/Source/Endian.h b/Gems/EMotionFX/Code/MCore/Source/Endian.h index 296f53a208..ba93fbed97 100644 --- a/Gems/EMotionFX/Code/MCore/Source/Endian.h +++ b/Gems/EMotionFX/Code/MCore/Source/Endian.h @@ -53,6 +53,8 @@ namespace MCore */ static MCORE_INLINE void ConvertUnsignedInt32(uint32* value, uint32 count = 1); + static MCORE_INLINE void ConvertUnsignedInt64(uint64* value, uint32 count = 1); + /** * Swap the endian of one or more shorts. * @param value The value to convert the endian for. @@ -178,6 +180,8 @@ namespace MCore */ static MCORE_INLINE void ConvertUnsignedInt32(uint32* value, EEndianType sourceEndianType, uint32 count = 1); + static MCORE_INLINE void ConvertUnsignedInt64(uint64* value, EEndianType sourceEndianType, uint32 count = 1); + /** * Convert one or more 16 bit short values into the endian used by our current platform. * @param value The value(s) to convert. The number of values to follow at the specified address must be at least the number @@ -273,6 +277,8 @@ namespace MCore */ static MCORE_INLINE void ConvertUnsignedInt32(uint32* value, EEndianType sourceEndianType, EEndianType targetEndianType, uint32 count = 1); + static MCORE_INLINE void ConvertUnsignedInt64(uint64* value, EEndianType sourceEndianType, EEndianType targetEndianType, uint32 count = 1); + /** * Convert an 16 bit short into another endian type. * @param value A pointer to the object to convert/modify. diff --git a/Gems/EMotionFX/Code/MCore/Source/Endian.inl b/Gems/EMotionFX/Code/MCore/Source/Endian.inl index bafd816398..e0dd5acb0a 100644 --- a/Gems/EMotionFX/Code/MCore/Source/Endian.inl +++ b/Gems/EMotionFX/Code/MCore/Source/Endian.inl @@ -28,6 +28,17 @@ MCORE_INLINE void Endian::ConvertUnsignedInt32(uint32* value, uint32 count) } } +MCORE_INLINE void Endian::ConvertUnsignedInt64(uint64* value, uint32 count) +{ + for (uint32 i = 0; i < count; ++i) + { + uint64 arg = *value; + *value = (arg >> 56) + ((arg >> 40) & 0xFF00) + ((arg >> 24) & 0xFF0000) + ((arg >> 8) & 0xFF000000) + + ((arg & 0xFF000000) << 8) + ((arg & 0xFF0000) << 24) + ((arg & 0xFF00) << 40) + (arg << 56); + value++; + } +} + // swap bytes for a short MCORE_INLINE void Endian::ConvertSignedInt16(int16* value, uint32 count) @@ -168,6 +179,20 @@ MCORE_INLINE void Endian::ConvertUnsignedInt32(uint32* value, Endian::EEndianTyp ; } +MCORE_INLINE void Endian::ConvertUnsignedInt64(uint64* value, Endian::EEndianType sourceEndianType, uint32 count) +{ + // convert into the new endian, depending on the platform we are running on + switch (sourceEndianType) + { + case ENDIAN_LITTLE: + MCORE_FROM_LITTLE_ENDIAN64((uint8*)value, count); + break; + case ENDIAN_BIG: + MCORE_FROM_BIG_ENDIAN64 ((uint8*)value, count); + break; + } +} + // convert a short MCORE_INLINE void Endian::ConvertSignedInt16(int16* value, EEndianType sourceEndianType, uint32 count) @@ -364,6 +389,19 @@ MCORE_INLINE void Endian::ConvertUnsignedInt32(uint32* value, EEndianType source ConvertUnsignedInt32(value, count); } +// convert an uint64 into another endian type +MCORE_INLINE void Endian::ConvertUnsignedInt64(uint64* value, EEndianType sourceEndianType, EEndianType targetEndianType, uint32 count) +{ + // if we don't need to convert anything + if (sourceEndianType == targetEndianType) + { + return; + } + + // perform conversion + ConvertUnsignedInt64(value, count); +} + // convert a short into another endian type MCORE_INLINE void Endian::ConvertSignedInt16(int16* value, EEndianType sourceEndianType, EEndianType targetEndianType, uint32 count) diff --git a/Gems/EMotionFX/Code/Platform/Windows/platform_windows.cmake b/Gems/EMotionFX/Code/Platform/Windows/platform_windows.cmake index 98a5170e23..7a325ca97e 100644 --- a/Gems/EMotionFX/Code/Platform/Windows/platform_windows.cmake +++ b/Gems/EMotionFX/Code/Platform/Windows/platform_windows.cmake @@ -5,7 +5,3 @@ # SPDX-License-Identifier: Apache-2.0 OR MIT # # - -if (PAL_TRAIT_COMPILER_ID STREQUAL "MSVC") - set(LY_COMPILE_OPTIONS PUBLIC /wd4267) -endif() diff --git a/Gems/EMotionFX/Code/Source/Editor/SkeletonModel.cpp b/Gems/EMotionFX/Code/Source/Editor/SkeletonModel.cpp index 5a4f14921d..8530521458 100644 --- a/Gems/EMotionFX/Code/Source/Editor/SkeletonModel.cpp +++ b/Gems/EMotionFX/Code/Source/Editor/SkeletonModel.cpp @@ -632,15 +632,10 @@ namespace EMotionFX NodeInfo& nodeInfo = m_nodeInfos[nodeIndex]; // Is bone? - nodeInfo.m_isBone = false; - for (AZ::u32 lodLevel = 0; lodLevel < numLodLevels; ++lodLevel) + nodeInfo.m_isBone = AZStd::any_of(begin(boneListPerLodLevel), end(boneListPerLodLevel), [nodeIndex](const AZStd::vector& lodLevel) { - if (AZStd::find(begin(boneListPerLodLevel[lodLevel]), end(boneListPerLodLevel[lodLevel]), nodeIndex) != end(boneListPerLodLevel[lodLevel])) - { - nodeInfo.m_isBone = true; - break; - } - } + return AZStd::find(begin(lodLevel), end(lodLevel), nodeIndex) != end(lodLevel); + }); // Has mesh? nodeInfo.m_hasMesh = false; diff --git a/Gems/EMotionFX/Code/Tests/AdditiveMotionSamplingTests.cpp b/Gems/EMotionFX/Code/Tests/AdditiveMotionSamplingTests.cpp index ae8b42441a..4171598801 100644 --- a/Gems/EMotionFX/Code/Tests/AdditiveMotionSamplingTests.cpp +++ b/Gems/EMotionFX/Code/Tests/AdditiveMotionSamplingTests.cpp @@ -27,10 +27,10 @@ namespace EMotionFX void CreateSubMotionLikeBindPose(const std::string& name) { const Skeleton* skeleton = m_actor->GetSkeleton(); - AZ::u32 jointIndex = InvalidIndex32; + size_t jointIndex = InvalidIndex; const Node* node = skeleton->FindNodeAndIndexByName(name.c_str(), jointIndex); ASSERT_NE(node, nullptr); - ASSERT_NE(jointIndex, InvalidIndex32); + ASSERT_NE(jointIndex, InvalidIndex); const Pose* bindPose = m_actorInstance->GetTransformData()->GetBindPose(); const Transform& transform = bindPose->GetLocalSpaceTransform(jointIndex); @@ -41,7 +41,7 @@ namespace EMotionFX { // Find and store the joint index. const Skeleton* skeleton = m_actor->GetSkeleton(); - AZ::u32 jointIndex = InvalidIndex32; + size_t jointIndex = InvalidIndex; const Node* node = skeleton->FindNodeAndIndexByName(name.c_str(), jointIndex); ASSERT_NE(node, nullptr); ASSERT_NE(jointIndex, InvalidIndex32); @@ -91,9 +91,9 @@ namespace EMotionFX protected: Motion* m_motion = nullptr; MotionInstance* m_motionInstance = nullptr; // Automatically deleted internally when deleting the actor instance. - std::vector m_jointIndices; + std::vector m_jointIndices; std::vector m_jointNames { "l_upLeg", "l_loLeg", "l_ankle" }; - AZ::u32 m_footIndex = InvalidIndex32; + size_t m_footIndex = InvalidIndex; }; TEST_F(MotionSamplingFixture, SampleAdditiveJoint) @@ -102,7 +102,7 @@ namespace EMotionFX // Sample the joints that exist in our actor skeleton as well as inside the motion data. const Pose* bindPose = m_actorInstance->GetTransformData()->GetBindPose(); - for (AZ::u32 jointIndex : m_jointIndices) + for (size_t jointIndex : m_jointIndices) { // Sample the motion. Transform transform = Transform::CreateZero(); // Set all to Zero, not identity as this methods might return identity and we want to verify that. @@ -140,7 +140,7 @@ namespace EMotionFX // Test if the joints that exist in both motion and actor have the expected transforms. const Pose* bindPose = m_actorInstance->GetTransformData()->GetBindPose(); - for (AZ::u32 jointIndex : m_jointIndices) + for (size_t jointIndex : m_jointIndices) { const Transform& transform = pose.GetLocalSpaceTransform(jointIndex); const Transform& bindTransform = bindPose->GetLocalSpaceTransform(jointIndex); diff --git a/Gems/EMotionFX/Code/Tests/AnimGraphMotionNodeTests.cpp b/Gems/EMotionFX/Code/Tests/AnimGraphMotionNodeTests.cpp index 6fa1d962ab..2a199f5e8b 100644 --- a/Gems/EMotionFX/Code/Tests/AnimGraphMotionNodeTests.cpp +++ b/Gems/EMotionFX/Code/Tests/AnimGraphMotionNodeTests.cpp @@ -118,16 +118,16 @@ namespace EMotionFX } protected: - AZ::u32 m_l_handIndex = InvalidIndex32; - AZ::u32 m_l_loArmIndex = InvalidIndex32; - AZ::u32 m_l_loLegIndex = InvalidIndex32; - AZ::u32 m_l_ankleIndex = InvalidIndex32; - AZ::u32 m_r_handIndex = InvalidIndex32; - AZ::u32 m_r_loArmIndex = InvalidIndex32; - AZ::u32 m_r_loLegIndex = InvalidIndex32; - AZ::u32 m_r_ankleIndex = InvalidIndex32; - AZ::u32 m_jack_rootIndex = InvalidIndex32; - AZ::u32 m_bip01__pelvisIndex = InvalidIndex32; + size_t m_l_handIndex = InvalidIndex; + size_t m_l_loArmIndex = InvalidIndex; + size_t m_l_loLegIndex = InvalidIndex; + size_t m_l_ankleIndex = InvalidIndex; + size_t m_r_handIndex = InvalidIndex; + size_t m_r_loArmIndex = InvalidIndex; + size_t m_r_loLegIndex = InvalidIndex; + size_t m_r_ankleIndex = InvalidIndex; + size_t m_jack_rootIndex = InvalidIndex; + size_t m_bip01__pelvisIndex = InvalidIndex; AnimGraphMotionNode* m_motionNode = nullptr; BlendTree* m_blendTree = nullptr; BlendTreeFloatConstantNode* m_fltConstNode = nullptr; @@ -351,7 +351,7 @@ namespace EMotionFX AZ::Vector3 rootFinalPosUnderSpeed1 = m_jackPose->GetModelSpaceTransform(m_jack_rootIndex).mPosition; std::vector speedFactors = { 2.0f, 3.0f, 10.0f, 100.0f }; std::vector playTimes = { 0.6f, 0.4f, 0.11f, 0.011f }; - for (AZ::u32 i = 0; i < 4; i++) + for (size_t i = 0; i < 4; i++) { m_motionNode->Rewind(m_animGraphInstance); m_fltConstNode->SetValue(speedFactors[i]); @@ -385,7 +385,7 @@ namespace EMotionFX rootFinalPosUnderSpeed1 = m_jackPose->GetModelSpaceTransform(m_jack_rootIndex).mPosition; // Similar test to using the InPlace input port. - for (AZ::u32 i = 0; i < 4; i++) + for (size_t i = 0; i < 4; i++) { m_motionNode->Rewind(m_animGraphInstance); m_motionNode->SetMotionPlaySpeed(speedFactors[i]); @@ -426,7 +426,7 @@ namespace EMotionFX // In randomized index mode, all motions should at least appear once over 10 loops. bool motion1Displayed = false; bool motion2Displayed = false; - for (AZ::u32 i = 0; i < 20; i++) + for (size_t i = 0; i < 20; i++) { // Run the test loop multiple times to make sure all the motion index is picked. uniqueData->mReload = true; @@ -460,7 +460,7 @@ namespace EMotionFX uint32 currentMotionIndex = uniqueData->mActiveMotionIndex; // In randomized no repeat index mode, motions should change in each loop. - for (AZ::u32 i = 0; i < 10; i++) + for (size_t i = 0; i < 10; i++) { uniqueData->mReload = true; m_motionNode->Reinit(); @@ -476,7 +476,7 @@ namespace EMotionFX m_motionNode->SetIndexMode(AnimGraphMotionNode::INDEXMODE_SEQUENTIAL); // In sequential index mode, motions should increase its index each time and wrap around. Basically iterating over the list of motions. - for (AZ::u32 i = 0; i < 10; i++) + for (size_t i = 0; i < 10; i++) { uniqueData->mReload = true; m_motionNode->Reinit(); diff --git a/Gems/EMotionFX/Code/Tests/BlendTreeFootIKNodeTests.cpp b/Gems/EMotionFX/Code/Tests/BlendTreeFootIKNodeTests.cpp index 5fddb5a94b..48350ce071 100644 --- a/Gems/EMotionFX/Code/Tests/BlendTreeFootIKNodeTests.cpp +++ b/Gems/EMotionFX/Code/Tests/BlendTreeFootIKNodeTests.cpp @@ -136,10 +136,10 @@ namespace EMotionFX void ValidateFootHeight(BlendTreeFootIKNode::LegId legId, const char* jointName, float height, float tolerance) { // Check the left foot height. - AZ::u32 footIndex; + size_t footIndex = InvalidIndex; Skeleton* skeleton = m_actor->GetSkeleton(); skeleton->FindNodeAndIndexByName(jointName, footIndex); - ASSERT_NE(footIndex, MCORE_INVALIDINDEX32); + ASSERT_NE(footIndex, InvalidIndex); EMotionFX::Transform transform = m_actorInstance->GetTransformData()->GetCurrentPose()->GetWorldSpaceTransform(footIndex); const BlendTreeFootIKNode::UniqueData* uniqueData = static_cast(m_animGraphInstance->FindOrCreateUniqueNodeData(m_ikNode)); const float correction = (m_actorInstance->GetWorldSpaceTransform().mRotation.TransformVector(AZ::Vector3(0.0f, 0.0f, uniqueData->m_legs[legId].m_footHeight))).GetZ(); diff --git a/Gems/EMotionFX/Code/Tests/BlendTreeMirrorPoseNodeTests.cpp b/Gems/EMotionFX/Code/Tests/BlendTreeMirrorPoseNodeTests.cpp index 53e0e7de77..9851409a94 100644 --- a/Gems/EMotionFX/Code/Tests/BlendTreeMirrorPoseNodeTests.cpp +++ b/Gems/EMotionFX/Code/Tests/BlendTreeMirrorPoseNodeTests.cpp @@ -111,12 +111,12 @@ namespace EMotionFX TEST_F(BlendTreeMirrorPoseNodeFixture, OutputsCorrectPose) { GetEMotionFX().Update(1.0f / 60.0f); - AZ::u32 l_upArmIndex; - AZ::u32 r_upArmIndex; - AZ::u32 l_loArmIndex; - AZ::u32 r_loArmIndex; - AZ::u32 l_handIndex; - AZ::u32 r_handIndex; + size_t l_upArmIndex; + size_t r_upArmIndex; + size_t l_loArmIndex; + size_t r_loArmIndex; + size_t l_handIndex; + size_t r_handIndex; m_jackSkeleton->FindNodeAndIndexByName("l_upArm", l_upArmIndex); m_jackSkeleton->FindNodeAndIndexByName("r_upArm", r_upArmIndex); m_jackSkeleton->FindNodeAndIndexByName("l_loArm", l_loArmIndex); diff --git a/Gems/EMotionFX/Code/Tests/BlendTreeSimulatedObjectNodeTests.cpp b/Gems/EMotionFX/Code/Tests/BlendTreeSimulatedObjectNodeTests.cpp index a53a3d7e0b..df2f644eb4 100644 --- a/Gems/EMotionFX/Code/Tests/BlendTreeSimulatedObjectNodeTests.cpp +++ b/Gems/EMotionFX/Code/Tests/BlendTreeSimulatedObjectNodeTests.cpp @@ -47,7 +47,7 @@ namespace EMotionFX ASSERT_EQ(jointNames.size(), 3); for (size_t i= 0; i < 3; ++i) { - AZ::u32 jointIndex = InvalidIndex32; + size_t jointIndex = InvalidIndex; const Node* node = skeleton->FindNodeAndIndexByName(jointNames[i].c_str(), jointIndex); ASSERT_NE(node, nullptr); m_jointIndices[i] = jointIndex; @@ -116,7 +116,7 @@ namespace EMotionFX FloatSliderParameter* m_weightParameter = nullptr; BlendTreeSimulatedObjectNode* m_simNode = nullptr; BlendTreeParameterNode* m_parameterNode = nullptr; - AZ::u32 m_jointIndices[3] { InvalidIndex32, InvalidIndex32, InvalidIndex32 }; + size_t m_jointIndices[3] { InvalidIndex, InvalidIndex, InvalidIndex }; }; TEST_F(BlendTreeSimulatedObjectNodeFixture, TransformsCheck) diff --git a/Gems/EMotionFX/Code/Tests/BlendTreeTwoLinkIKNodeTests.cpp b/Gems/EMotionFX/Code/Tests/BlendTreeTwoLinkIKNodeTests.cpp index 91b7687a02..820e6d9fa4 100644 --- a/Gems/EMotionFX/Code/Tests/BlendTreeTwoLinkIKNodeTests.cpp +++ b/Gems/EMotionFX/Code/Tests/BlendTreeTwoLinkIKNodeTests.cpp @@ -147,7 +147,7 @@ namespace EMotionFX // Remeber specific joint's original position to compare with its new position later const Pose* jackPose = m_actorInstance->GetTransformData()->GetCurrentPose(); - AZ::u32 testJointIndex; + size_t testJointIndex; m_jackSkeleton->FindNodeAndIndexByName(m_param.testJointName, testJointIndex); const AZ::Vector3& testJointPos = jackPose->GetModelSpaceTransform(testJointIndex).mPosition; @@ -187,7 +187,7 @@ namespace EMotionFX ParamSetValue("WeightParam", weight); const Pose* jackPose = m_actorInstance->GetTransformData()->GetCurrentPose(); - AZ::u32 testJointIndex; + size_t testJointIndex; m_jackSkeleton->FindNodeAndIndexByName(m_param.testJointName, testJointIndex); const AZ::Vector3& testJointPos = jackPose->GetModelSpaceTransform(testJointIndex).mPosition; @@ -202,7 +202,7 @@ namespace EMotionFX // Unique data only updates once unless reset mMustUpdate to true again BlendTreeTwoLinkIKNode::UniqueData* uniqueData = static_cast(m_animGraphInstance->FindOrCreateUniqueNodeData(m_twoLinkIKNode)); uniqueData->Invalidate(); - AZ::u32 alignToNodeIndex; + size_t alignToNodeIndex; m_jackSkeleton->FindNodeAndIndexByName(nodeName, alignToNodeIndex); GetEMotionFX().Update(1.0f / 60.0f); @@ -234,9 +234,9 @@ namespace EMotionFX ParamSetValue("WeightParam", weight); const Pose* jackPose = m_actorInstance->GetTransformData()->GetCurrentPose(); - AZ::u32 testJointIndex; - AZ::u32 linkedJoint0Index; - AZ::u32 linkedJoint1Index; + size_t testJointIndex; + size_t linkedJoint0Index; + size_t linkedJoint1Index; m_jackSkeleton->FindNodeAndIndexByName(m_param.testJointName, testJointIndex); m_jackSkeleton->FindNodeAndIndexByName(m_param.linkedJointNames[0], linkedJoint0Index); m_jackSkeleton->FindNodeAndIndexByName(m_param.linkedJointNames[1], linkedJoint1Index); @@ -287,7 +287,7 @@ namespace EMotionFX ParamSetValue("GoalPosParam", AZ::Vector3(0.0f, 1.0f, 1.0f)); const Pose* jackPose = m_actorInstance->GetTransformData()->GetCurrentPose(); - AZ::u32 testJointIndex; + size_t testJointIndex; m_jackSkeleton->FindNodeAndIndexByName(m_param.testJointName, testJointIndex); const AZ::Quaternion testJointRotation = jackPose->GetModelSpaceTransform(testJointIndex).mRotation; @@ -334,8 +334,8 @@ namespace EMotionFX GetEMotionFX().Update(1.0f / 60.0f); Pose* jackPose = m_actorInstance->GetTransformData()->GetCurrentPose(); - AZ::u32 testBendJointIndex; - AZ::u32 testJointIndex; + size_t testBendJointIndex; + size_t testJointIndex; AZStd::string& bendLoArm = m_param.linkedJointNames[0]; m_jackSkeleton->FindNodeAndIndexByName(bendLoArm, testBendJointIndex); m_jackSkeleton->FindNodeAndIndexByName(m_param.testJointName, testJointIndex); @@ -395,8 +395,8 @@ namespace EMotionFX GetEMotionFX().Update(1.0f / 60.0f); const Pose* jackPose = m_actorInstance->GetTransformData()->GetCurrentPose(); - AZ::u32 testJointIndex; - AZ::u32 testBendJointIndex; + size_t testJointIndex; + size_t testBendJointIndex; AZStd::string& bendLoArm = m_param.linkedJointNames[0]; m_jackSkeleton->FindNodeAndIndexByName(m_param.testJointName, testJointIndex); m_jackSkeleton->FindNodeAndIndexByName(bendLoArm, testBendJointIndex); diff --git a/Gems/EMotionFX/Code/Tests/Mocks/CommandManagerCallback.h b/Gems/EMotionFX/Code/Tests/Mocks/CommandManagerCallback.h index 7f9a8d6530..0e805b72e1 100644 --- a/Gems/EMotionFX/Code/Tests/Mocks/CommandManagerCallback.h +++ b/Gems/EMotionFX/Code/Tests/Mocks/CommandManagerCallback.h @@ -21,8 +21,8 @@ namespace MCore MOCK_METHOD2(OnPreExecuteCommandGroup, void(MCore::CommandGroup*, bool)); MOCK_METHOD2(OnPostExecuteCommandGroup, void(MCore::CommandGroup*, bool)); - MOCK_METHOD4(OnAddCommandToHistory, void(uint32, MCore::CommandGroup*, MCore::Command*, const MCore::CommandLine&)); - MOCK_METHOD1(OnRemoveCommand, void(uint32)); - MOCK_METHOD1(OnSetCurrentCommand, void(uint32)); + MOCK_METHOD4(OnAddCommandToHistory, void(size_t, MCore::CommandGroup*, MCore::Command*, const MCore::CommandLine&)); + MOCK_METHOD1(OnRemoveCommand, void(size_t)); + MOCK_METHOD1(OnSetCurrentCommand, void(size_t)); }; } // namespace MCore diff --git a/Gems/EMotionFX/Code/Tests/MotionExtractionTests.cpp b/Gems/EMotionFX/Code/Tests/MotionExtractionTests.cpp index e1839d8d9f..85c0e4201f 100644 --- a/Gems/EMotionFX/Code/Tests/MotionExtractionTests.cpp +++ b/Gems/EMotionFX/Code/Tests/MotionExtractionTests.cpp @@ -119,8 +119,8 @@ namespace EMotionFX } protected: - AZ::u32 m_jack_rootIndex = MCORE_INVALIDINDEX32; - AZ::u32 m_jack_hipIndex = MCORE_INVALIDINDEX32; + size_t m_jack_rootIndex = InvalidIndex; + size_t m_jack_hipIndex = InvalidIndex; AnimGraphMotionNode* m_motionNode = nullptr; BlendTree* m_blendTree = nullptr; Motion* m_motion = nullptr; @@ -243,7 +243,7 @@ namespace EMotionFX // The expected delta used is the distance of the jack walk forward motion will move in 1 complete duration const float expectedDelta = ExtractLastFramePos().GetY(); - for (AZ::u32 paramIndex = 0; paramIndex < m_param.durationMultipliers.size(); paramIndex++) + for (size_t paramIndex = 0; paramIndex < m_param.durationMultipliers.size(); paramIndex++) { // Test motion extraction under different durations/time deltas const float motionDuration = 1.066f * m_param.durationMultipliers[paramIndex]; @@ -262,7 +262,7 @@ namespace EMotionFX const AZ::Quaternion actorRotation(0.0f, 0.0f, -1.0f, 1.0f); m_actorInstance->SetLocalSpaceRotation(actorRotation.GetNormalized()); GetEMotionFX().Update(0.0f); - for (AZ::u32 paramIndex = 0; paramIndex < m_param.durationMultipliers.size(); paramIndex++) + for (size_t paramIndex = 0; paramIndex < m_param.durationMultipliers.size(); paramIndex++) { const float motionDuration = 1.066f * m_param.durationMultipliers[paramIndex]; const float originalPositionX = m_actorInstance->GetWorldSpaceTransform().mPosition.GetX(); @@ -290,7 +290,7 @@ namespace EMotionFX const AZ::Quaternion diagonalRotation = m_reverse ? AZ::Quaternion(0.0f, 0.0f, 0.5f, 1.0f) : AZ::Quaternion(0.0f, 0.0f, -0.5f, 1.0f); m_actorInstance->SetLocalSpaceRotation(diagonalRotation.GetNormalized()); GetEMotionFX().Update(0.0f); - for (AZ::u32 paramIndex = 0; paramIndex < m_param.durationMultipliers.size(); paramIndex++) + for (size_t paramIndex = 0; paramIndex < m_param.durationMultipliers.size(); paramIndex++) { const float originalPositionX = m_actorInstance->GetWorldSpaceTransform().mPosition.GetX(); const float originalPositionY = m_actorInstance->GetWorldSpaceTransform().mPosition.GetY(); diff --git a/Gems/EMotionFX/Code/Tests/PoseTests.cpp b/Gems/EMotionFX/Code/Tests/PoseTests.cpp index 0957176813..1785a4d512 100644 --- a/Gems/EMotionFX/Code/Tests/PoseTests.cpp +++ b/Gems/EMotionFX/Code/Tests/PoseTests.cpp @@ -742,7 +742,7 @@ namespace EMotionFX pose.LinkToActorInstance(m_actorInstance); pose.InitFromBindPose(m_actor.get()); - AZ::u32 jointIndex = InvalidIndex32; + size_t jointIndex = InvalidIndex; Node* joint = m_actor->GetSkeleton()->FindNodeAndIndexByName("joint4", jointIndex); ASSERT_NE(joint, nullptr) << "Can't find the joint named 'joint4'."; @@ -779,7 +779,7 @@ namespace EMotionFX Pose destPose; destPose.LinkToActorInstance(m_actorInstance); destPose.InitFromBindPose(m_actor.get()); - for (AZ::u32 i = 0; i < m_actor->GetSkeleton()->GetNumNodes(); ++i) + for (size_t i = 0; i < m_actor->GetSkeleton()->GetNumNodes(); ++i) { const float floatI = static_cast(i); Transform transform(AZ::Vector3(0.0f, 0.0f, -floatI), @@ -798,7 +798,7 @@ namespace EMotionFX blendedPose.Blend(&destPose, blendWeight); // Check the blended result. - for (AZ::u32 i = 0; i < m_actor->GetSkeleton()->GetNumNodes(); ++i) + for (size_t i = 0; i < m_actor->GetSkeleton()->GetNumNodes(); ++i) { const Transform& sourceTransform = sourcePose->GetLocalSpaceTransform(i); const Transform& destTransform = destPose.GetLocalSpaceTransform(i); @@ -820,7 +820,7 @@ namespace EMotionFX Pose sourcePose; sourcePose.LinkToActorInstance(m_actorInstance); sourcePose.InitFromBindPose(m_actor.get()); - for (AZ::u32 i = 0; i < m_actor->GetSkeleton()->GetNumNodes(); ++i) + for (size_t i = 0; i < m_actor->GetSkeleton()->GetNumNodes(); ++i) { const float floatI = static_cast(i); Transform transform(AZ::Vector3(floatI, 0.0f, 0.0f), @@ -837,7 +837,7 @@ namespace EMotionFX Pose destPose; destPose.LinkToActorInstance(m_actorInstance); destPose.InitFromBindPose(m_actor.get()); - for (AZ::u32 i = 0; i < m_actor->GetSkeleton()->GetNumNodes(); ++i) + for (size_t i = 0; i < m_actor->GetSkeleton()->GetNumNodes(); ++i) { const float floatI = static_cast(i); Transform transform(AZ::Vector3(0.0f, 0.0f, -floatI), @@ -856,7 +856,7 @@ namespace EMotionFX blendedPose.InitFromPose(&sourcePose); blendedPose.BlendAdditiveUsingBindPose(&destPose, blendWeight); - for (AZ::u32 i = 0; i < m_actor->GetSkeleton()->GetNumNodes(); ++i) + for (size_t i = 0; i < m_actor->GetSkeleton()->GetNumNodes(); ++i) { const Transform& bindPoseTransform = bindPose->GetLocalSpaceTransform(i); const Transform& sourceTransform = sourcePose.GetLocalSpaceTransform(i); @@ -897,7 +897,7 @@ namespace EMotionFX poseB.LinkToActorInstance(m_actorInstance); poseB.InitFromBindPose(m_actor.get()); - for (AZ::u32 i = 0; i < m_actor->GetSkeleton()->GetNumNodes(); ++i) + for (size_t i = 0; i < m_actor->GetSkeleton()->GetNumNodes(); ++i) { const float floatI = static_cast(i); const Transform transformA(AZ::Vector3(floatI, 0.0f, 0.0f), @@ -920,7 +920,7 @@ namespace EMotionFX default: { ASSERT_TRUE(false) << "Case not handled."; } } - for (AZ::u32 i = 0; i < m_actor->GetSkeleton()->GetNumNodes(); ++i) + for (size_t i = 0; i < m_actor->GetSkeleton()->GetNumNodes(); ++i) { const Transform& transformA = poseA.GetLocalSpaceTransform(i); const Transform& transformB = poseB.GetLocalSpaceTransform(i); @@ -960,7 +960,7 @@ namespace EMotionFX poseB.LinkToActorInstance(m_actorInstance); poseB.InitFromBindPose(m_actor.get()); - for (AZ::u32 i = 0; i < m_actor->GetSkeleton()->GetNumNodes(); ++i) + for (size_t i = 0; i < m_actor->GetSkeleton()->GetNumNodes(); ++i) { const float floatI = static_cast(i); const Transform transformA(AZ::Vector3(floatI, 0.0f, 0.0f), AZ::Quaternion::CreateIdentity()); @@ -982,7 +982,7 @@ namespace EMotionFX poseSum.InitFromPose(&poseA); poseSum.Sum(&poseB, weight); - for (AZ::u32 i = 0; i < m_actor->GetSkeleton()->GetNumNodes(); ++i) + for (size_t i = 0; i < m_actor->GetSkeleton()->GetNumNodes(); ++i) { const Transform& transformA = poseA.GetLocalSpaceTransform(i); const Transform& transformB = poseB.GetLocalSpaceTransform(i); @@ -1012,7 +1012,7 @@ namespace EMotionFX poseB.LinkToActorInstance(m_actorInstance); poseB.InitFromBindPose(m_actor.get()); - for (AZ::u32 i = 0; i < m_actor->GetSkeleton()->GetNumNodes(); ++i) + for (size_t i = 0; i < m_actor->GetSkeleton()->GetNumNodes(); ++i) { const float floatI = static_cast(i); const Transform transformA(AZ::Vector3(floatI, floatI, floatI), AZ::Quaternion::CreateIdentity()); @@ -1026,7 +1026,7 @@ namespace EMotionFX poseRel.InitFromPose(&poseA); poseRel.MakeRelativeTo(poseB); - for (AZ::u32 i = 0; i < m_actor->GetSkeleton()->GetNumNodes(); ++i) + for (size_t i = 0; i < m_actor->GetSkeleton()->GetNumNodes(); ++i) { const Transform& transformRel = poseRel.GetLocalSpaceTransform(i); @@ -1095,7 +1095,7 @@ namespace EMotionFX } poseB.InitFromBindPose(m_actor.get()); - for (AZ::u32 i = 0; i < m_actor->GetSkeleton()->GetNumNodes(); ++i) + for (size_t i = 0; i < m_actor->GetSkeleton()->GetNumNodes(); ++i) { const float floatI = static_cast(i); const Transform transformA(AZ::Vector3(floatI, 0.0f, 0.0f), @@ -1133,7 +1133,7 @@ namespace EMotionFX default: { ASSERT_TRUE(false) << "Case not handled."; } } - for (AZ::u32 i = 0; i < m_actor->GetSkeleton()->GetNumNodes(); ++i) + for (size_t i = 0; i < m_actor->GetSkeleton()->GetNumNodes(); ++i) { const Transform& transformA = poseA.GetLocalSpaceTransform(i); const Transform& transformB = poseB.GetLocalSpaceTransform(i); @@ -1222,7 +1222,7 @@ namespace EMotionFX pose.Zero(); // Check if local space transforms are correctly zeroed. - for (AZ::u32 i = 0; i < m_actor->GetSkeleton()->GetNumNodes(); ++i) + for (size_t i = 0; i < m_actor->GetSkeleton()->GetNumNodes(); ++i) { EXPECT_EQ(pose.GetLocalSpaceTransform(i), Transform::CreateZero()); } @@ -1244,7 +1244,7 @@ namespace EMotionFX AZ::SimpleLcgRandom random; random.SetSeed(875960); - for (AZ::u32 i = 0; i < m_actor->GetSkeleton()->GetNumNodes(); ++i) + for (size_t i = 0; i < m_actor->GetSkeleton()->GetNumNodes(); ++i) { Transform transformRandomRot(AZ::Vector3::CreateZero(), CreateRandomUnnormalizedQuaternion(random)); @@ -1255,7 +1255,7 @@ namespace EMotionFX pose.NormalizeQuaternions(); - for (AZ::u32 i = 0; i < m_actor->GetSkeleton()->GetNumNodes(); ++i) + for (size_t i = 0; i < m_actor->GetSkeleton()->GetNumNodes(); ++i) { CheckIfRotationIsNormalized(pose.GetLocalSpaceTransform(i).mRotation); } diff --git a/Gems/EMotionFX/Code/Tests/SimulatedObjectSerializeTests.cpp b/Gems/EMotionFX/Code/Tests/SimulatedObjectSerializeTests.cpp index 5f48cc145f..9ba4e4f6cb 100644 --- a/Gems/EMotionFX/Code/Tests/SimulatedObjectSerializeTests.cpp +++ b/Gems/EMotionFX/Code/Tests/SimulatedObjectSerializeTests.cpp @@ -32,7 +32,7 @@ namespace EMotionFX Skeleton* skeleton = m_actor->GetSkeleton(); for (const AZStd::string& name : jointNames) { - AZ::u32 skeletonJointIndex; + size_t skeletonJointIndex; const Node* skeletonJoint = skeleton->FindNodeAndIndexByName(name, skeletonJointIndex); ASSERT_NE(skeletonJoint, nullptr); ASSERT_NE(skeletonJointIndex, MCORE_INVALIDINDEX32); @@ -63,7 +63,7 @@ namespace EMotionFX ASSERT_FLOAT_EQ(loadedObject->GetStiffnessFactor(), 4.0f); for (size_t i = 0; i < jointNames.size(); ++i) { - const SimulatedJoint* loadedJoint = loadedObject->GetSimulatedJoint(static_cast(i)); + const SimulatedJoint* loadedJoint = loadedObject->GetSimulatedJoint(i); ASSERT_STREQ(skeleton->GetNode(loadedJoint->GetSkeletonJointIndex())->GetName(), jointNames[i].c_str()); ASSERT_FLOAT_EQ(loadedJoint->GetDamping(), 0.1f); ASSERT_FLOAT_EQ(loadedJoint->GetMass(), 2.0f); diff --git a/Gems/EMotionFX/Code/Tests/TestAssetCode/JackActor.cpp b/Gems/EMotionFX/Code/Tests/TestAssetCode/JackActor.cpp index 414879568e..96461826c7 100644 --- a/Gems/EMotionFX/Code/Tests/TestAssetCode/JackActor.cpp +++ b/Gems/EMotionFX/Code/Tests/TestAssetCode/JackActor.cpp @@ -14,7 +14,7 @@ namespace EMotionFX JackNoMeshesActor::JackNoMeshesActor(const char* name) : Actor(name) { - uint32 nodeId = 0; + size_t nodeId = 0; auto root = AddNode(nodeId++, "jack_root"); auto Bip01__pelvis = AddNode(nodeId++, "Bip01__pelvis", root->GetNodeIndex()); auto l_upLeg = AddNode(nodeId++, "l_upLeg", Bip01__pelvis->GetNodeIndex()); From 225798480ce9326a54b0a481937b352694ea4579 Mon Sep 17 00:00:00 2001 From: Chris Burel Date: Mon, 24 May 2021 12:04:11 -0700 Subject: [PATCH 202/803] Fix Actor lod levels and material indexes uint32->size_t Signed-off-by: Chris Burel --- .../ExporterLib/Exporter/NodeExport.cpp | 2 +- .../EMotionFX/Rendering/Common/RenderUtil.cpp | 24 +-- .../EMotionFX/Rendering/Common/RenderUtil.h | 4 +- .../EMotionFX/Code/EMotionFX/Source/Actor.cpp | 152 +++++++--------- Gems/EMotionFX/Code/EMotionFX/Source/Actor.h | 58 +++---- .../Code/EMotionFX/Source/ActorInstance.h | 2 +- .../EMotionFX/Source/DualQuatSkinDeformer.cpp | 2 +- .../EMotionFX/Source/DualQuatSkinDeformer.h | 2 +- Gems/EMotionFX/Code/EMotionFX/Source/Mesh.cpp | 22 +-- Gems/EMotionFX/Code/EMotionFX/Source/Mesh.h | 4 +- .../Code/EMotionFX/Source/MeshDeformer.cpp | 2 +- .../Code/EMotionFX/Source/MeshDeformer.h | 2 +- .../EMotionFX/Source/MeshDeformerStack.cpp | 6 +- .../Code/EMotionFX/Source/MeshDeformerStack.h | 2 +- .../EMotionFX/Source/MorphMeshDeformer.cpp | 2 +- .../Code/EMotionFX/Source/MorphMeshDeformer.h | 2 +- .../Code/EMotionFX/Source/MorphSetup.cpp | 2 +- .../Code/EMotionFX/Source/MorphSetup.h | 4 +- .../Code/EMotionFX/Source/MorphTarget.h | 4 +- .../EMotionFX/Source/MorphTargetStandard.cpp | 8 +- .../EMotionFX/Source/MorphTargetStandard.h | 10 +- Gems/EMotionFX/Code/EMotionFX/Source/Node.cpp | 10 +- Gems/EMotionFX/Code/EMotionFX/Source/Node.h | 8 +- .../Code/EMotionFX/Source/NodeMap.cpp | 87 ++++------ .../EMotionFX/Code/EMotionFX/Source/NodeMap.h | 34 ++-- Gems/EMotionFX/Code/EMotionFX/Source/Pose.cpp | 2 +- Gems/EMotionFX/Code/EMotionFX/Source/Pose.h | 30 ++-- .../EMotionFX/Source/SoftSkinDeformer.cpp | 2 +- .../Code/EMotionFX/Source/SoftSkinDeformer.h | 2 +- .../Source/NodeHierarchyWidget.cpp | 16 +- .../EMStudioSDK/Source/NodeHierarchyWidget.h | 2 +- .../Source/RenderPlugin/RenderPlugin.h | 2 +- .../Source/NodeWindow/MeshInfo.cpp | 16 +- .../Source/NodeWindow/MeshInfo.h | 2 +- .../Source/NodeWindow/NodeWindowPlugin.cpp | 8 +- .../Source/NodeWindow/SubMeshInfo.cpp | 2 +- .../Source/NodeWindow/SubMeshInfo.h | 4 +- .../Source/SceneManager/MirrorSetupWindow.cpp | 162 ++++++------------ .../Source/SceneManager/MirrorSetupWindow.h | 8 +- .../Code/Source/Editor/SkeletonModel.cpp | 14 +- 40 files changed, 311 insertions(+), 416 deletions(-) diff --git a/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/NodeExport.cpp b/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/NodeExport.cpp index 80efb54606..4f6e5a5c52 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/NodeExport.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/NodeExport.cpp @@ -430,7 +430,7 @@ namespace ExporterLib MCore::LogInfo("============================================================"); // get all nodes that are affected by the skin - AZStd::vector bones; + AZStd::vector bones; if (actor) { actor->ExtractBoneList(0, &bones); diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RenderUtil.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RenderUtil.cpp index e17fffbdb5..34ab2a8a69 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RenderUtil.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RenderUtil.cpp @@ -653,7 +653,7 @@ namespace MCommon // render the advanced skeleton - void RenderUtil::RenderSkeleton(EMotionFX::ActorInstance* actorInstance, const AZStd::vector& boneList, const AZStd::unordered_set* visibleJointIndices, const AZStd::unordered_set* selectedJointIndices, const MCore::RGBAColor& color, const MCore::RGBAColor& selectedColor) + void RenderUtil::RenderSkeleton(EMotionFX::ActorInstance* actorInstance, const AZStd::vector& boneList, const AZStd::unordered_set* visibleJointIndices, const AZStd::unordered_set* selectedJointIndices, const MCore::RGBAColor& color, const MCore::RGBAColor& selectedColor) { // check if our render util supports rendering meshes, if not render the fallback skeleton using lines only if (GetIsMeshRenderingSupported() == false) @@ -670,15 +670,15 @@ namespace MCommon // iterate through all enabled nodes MCore::RGBAColor tempColor; - const uint32 numEnabled = actorInstance->GetNumEnabledNodes(); - for (uint32 i = 0; i < numEnabled; ++i) + const size_t numEnabled = actorInstance->GetNumEnabledNodes(); + for (size_t i = 0; i < numEnabled; ++i) { EMotionFX::Node* joint = skeleton->GetNode(actorInstance->GetEnabledNode(i)); - const AZ::u32 jointIndex = joint->GetNodeIndex(); - const AZ::u32 parentIndex = joint->GetParentIndex(); + const size_t jointIndex = joint->GetNodeIndex(); + const size_t parentIndex = joint->GetParentIndex(); // check if this node has a parent and is a bone, if not skip it - if (parentIndex == MCORE_INVALIDINDEX32 || AZStd::find(begin(boneList), end(boneList), jointIndex) == end(boneList)) + if (parentIndex == InvalidIndex || AZStd::find(begin(boneList), end(boneList), jointIndex) == end(boneList)) { continue; } @@ -715,7 +715,7 @@ namespace MCommon // render node orientations - void RenderUtil::RenderNodeOrientations(EMotionFX::ActorInstance* actorInstance, const AZStd::vector& boneList, const AZStd::unordered_set* visibleJointIndices, const AZStd::unordered_set* selectedJointIndices, float scale, bool scaleBonesOnLength) + void RenderUtil::RenderNodeOrientations(EMotionFX::ActorInstance* actorInstance, const AZStd::vector& boneList, const AZStd::unordered_set* visibleJointIndices, const AZStd::unordered_set* selectedJointIndices, float scale, bool scaleBonesOnLength) { // get the actor and the transform data const float unitScale = 1.0f / (float)MCore::Distance::ConvertValue(1.0f, MCore::Distance::UNITTYPE_METERS, EMotionFX::GetEMotionFX().GetUnitType()); @@ -726,18 +726,18 @@ namespace MCommon const float constPreScale = scale * unitScale * 3.0f; AxisRenderingSettings axisRenderingSettings; - const uint32 numEnabled = actorInstance->GetNumEnabledNodes(); - for (uint32 i = 0; i < numEnabled; ++i) + const size_t numEnabled = actorInstance->GetNumEnabledNodes(); + for (size_t i = 0; i < numEnabled; ++i) { EMotionFX::Node* joint = skeleton->GetNode(actorInstance->GetEnabledNode(i)); - const AZ::u32 jointIndex = joint->GetNodeIndex(); - const AZ::u32 parentIndex = joint->GetParentIndex(); + const size_t jointIndex = joint->GetNodeIndex(); + const size_t parentIndex = joint->GetParentIndex(); if (!visibleJointIndices || visibleJointIndices->empty() || (visibleJointIndices->find(jointIndex) != visibleJointIndices->end())) { // either scale the bones based on their length or use the normal size - if (scaleBonesOnLength && parentIndex != MCORE_INVALIDINDEX32 && AZStd::find(begin(boneList), end(boneList), jointIndex) != end(boneList)) + if (scaleBonesOnLength && parentIndex != InvalidIndex && AZStd::find(begin(boneList), end(boneList), jointIndex) != end(boneList)) { static const float axisBoneScale = 50.0f; axisRenderingSettings.mSize = GetBoneScale(actorInstance, joint) * constPreScale * axisBoneScale; diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RenderUtil.h b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RenderUtil.h index 8fb8f524c4..d62816fa65 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RenderUtil.h +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RenderUtil.h @@ -191,7 +191,7 @@ namespace MCommon * @param[in] color The desired skeleton color. * @param[in] selectedColor The color of the selected bones. */ - void RenderSkeleton(EMotionFX::ActorInstance* actorInstance, const AZStd::vector& boneList, const AZStd::unordered_set* visibleJointIndices = nullptr, const AZStd::unordered_set* selectedJointIndices = nullptr, const MCore::RGBAColor& color = MCore::RGBAColor(1.0f, 0.0f, 0.0f, 1.0f), const MCore::RGBAColor& selectedColor = MCore::RGBAColor(1.0f, 0.647f, 0.0f)); + void RenderSkeleton(EMotionFX::ActorInstance* actorInstance, const AZStd::vector& boneList, const AZStd::unordered_set* visibleJointIndices = nullptr, const AZStd::unordered_set* selectedJointIndices = nullptr, const MCore::RGBAColor& color = MCore::RGBAColor(1.0f, 0.0f, 0.0f, 1.0f), const MCore::RGBAColor& selectedColor = MCore::RGBAColor(1.0f, 0.647f, 0.0f)); /** * Render node orientations. @@ -202,7 +202,7 @@ namespace MCommon * @param[in] scale The scaling value in units. Axes of normal nodes will use the scaling value as unit length, skinned bones will use the scaling value as multiplier. * @param[in] scaleBonesOnLength Automatically scales the bone orientations based on the bone length. This means finger node orientations will be rendered smaller than foot bones as the bone length is a lot smaller as well. */ - void RenderNodeOrientations(EMotionFX::ActorInstance* actorInstance, const AZStd::vector& boneList, const AZStd::unordered_set* visibleJointIndices = nullptr, const AZStd::unordered_set* selectedJointIndices = nullptr, float scale = 1.0f, bool scaleBonesOnLength = true); + void RenderNodeOrientations(EMotionFX::ActorInstance* actorInstance, const AZStd::vector& boneList, const AZStd::unordered_set* visibleJointIndices = nullptr, const AZStd::unordered_set* selectedJointIndices = nullptr, float scale = 1.0f, bool scaleBonesOnLength = true); /** * Render the bind pose of the given actor. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp index d8377f2d0e..77ce4435bc 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp @@ -79,7 +79,7 @@ namespace EMotionFX mRetargetRootNode = InvalidIndex; mThreadIndex = 0; mCustomData = nullptr; - mID = MCore::GetIDGenerator().GenerateID(); + mID = aznumeric_caster(MCore::GetIDGenerator().GenerateID()); mUnitType = GetEMotionFX().GetUnitType(); mFileUnitType = mUnitType; m_staticAabb = AZ::Aabb::CreateNull(); @@ -149,21 +149,13 @@ namespace EMotionFX // clone the materials result->mMaterials.resize(mMaterials.size()); - for (uint32 i = 0; i < mMaterials.size(); ++i) + for (size_t i = 0; i < mMaterials.size(); ++i) { // get the number of materials in the current LOD - const uint32 numMaterials = mMaterials[i].size(); - result->mMaterials[i].reserve(numMaterials); - for (uint32 m = 0; m < numMaterials; ++m) + result->mMaterials[i].reserve(mMaterials[i].size()); + for (const Material* material : mMaterials[i]) { - // retrieve the current material - Material* material = mMaterials[i][m]; - - // clone the material - Material* clone = material->Clone(); - - // add the cloned material to the cloned actor - result->AddMaterial(i, clone); + result->AddMaterial(i, material->Clone()); } } @@ -195,7 +187,7 @@ namespace EMotionFX // clone the morph setups result->mMorphSetups.resize(mMorphSetups.size()); - for (uint32 i = 0; i < mMorphSetups.size(); ++i) + for (size_t i = 0; i < mMorphSetups.size(); ++i) { if (mMorphSetups[i]) { @@ -326,13 +318,13 @@ namespace EMotionFX } // insert a LOD level at a given position - void Actor::InsertLODLevel(uint32 insertAt) + void Actor::InsertLODLevel(size_t insertAt) { AZStd::vector& lodLevels = m_meshLodData.m_lodLevels; lodLevels.emplace(lodLevels.begin()+insertAt); LODLevel& newLOD = lodLevels[insertAt]; - const uint32 lodIndex = insertAt; + const size_t lodIndex = insertAt; const size_t numNodes = mSkeleton->GetNumNodes(); newLOD.mNodeInfos.resize(numNodes); @@ -352,7 +344,7 @@ namespace EMotionFX } // replace existing LOD level with the current actor - void Actor::CopyLODLevel(Actor* copyActor, uint32 copyLODLevel, uint32 replaceLODLevel, bool copySkeletalLODFlags) + void Actor::CopyLODLevel(Actor* copyActor, size_t copyLODLevel, size_t replaceLODLevel, bool copySkeletalLODFlags) { AZStd::vector& lodLevels = m_meshLodData.m_lodLevels; AZStd::vector& copyLodLevels = copyActor->m_meshLodData.m_lodLevels; @@ -433,7 +425,7 @@ namespace EMotionFX } // preallocate memory for all LOD levels - void Actor::SetNumLODLevels(uint32 numLODs, bool adjustMorphSetup) + void Actor::SetNumLODLevels(size_t numLODs, bool adjustMorphSetup) { m_meshLodData.m_lodLevels.resize(numLODs); @@ -467,7 +459,7 @@ namespace EMotionFX } - void Actor::CalcMeshTotals(uint32 lodLevel, uint32* outNumPolygons, uint32* outNumVertices, uint32* outNumIndices) const + void Actor::CalcMeshTotals(size_t lodLevel, uint32* outNumPolygons, uint32* outNumVertices, uint32* outNumIndices) const { uint32 totalPolys = 0; uint32 totalVerts = 0; @@ -504,7 +496,7 @@ namespace EMotionFX } - void Actor::CalcStaticMeshTotals(uint32 lodLevel, uint32* outNumVertices, uint32* outNumIndices) + void Actor::CalcStaticMeshTotals(size_t lodLevel, uint32* outNumVertices, uint32* outNumIndices) { // the totals uint32 totalVerts = 0; @@ -548,7 +540,7 @@ namespace EMotionFX } - void Actor::CalcDeformableMeshTotals(uint32 lodLevel, uint32* outNumVertices, uint32* outNumIndices) + void Actor::CalcDeformableMeshTotals(size_t lodLevel, uint32* outNumVertices, uint32* outNumIndices) { // the totals uint32 totalVerts = 0; @@ -592,9 +584,9 @@ namespace EMotionFX } - uint32 Actor::CalcMaxNumInfluences(uint32 lodLevel) const + size_t Actor::CalcMaxNumInfluences(size_t lodLevel) const { - uint32 maxInfluences = 0; + size_t maxInfluences = 0; const size_t numNodes = mSkeleton->GetNumNodes(); for (size_t i = 0; i < numNodes; ++i) @@ -605,7 +597,7 @@ namespace EMotionFX continue; } - maxInfluences = MCore::Max(maxInfluences, mesh->CalcMaxNumInfluences()); + maxInfluences = AZStd::max(maxInfluences, mesh->CalcMaxNumInfluences()); } return maxInfluences; @@ -613,10 +605,8 @@ namespace EMotionFX // verify if the skinning will look correctly in the given geometry LOD for a given skeletal LOD level - void Actor::VerifySkinning(AZStd::vector& conflictNodeFlags, uint32 skeletalLODLevel, uint32 geometryLODLevel) + void Actor::VerifySkinning(AZStd::vector& conflictNodeFlags, size_t skeletalLODLevel, size_t geometryLODLevel) { - uint32 n; - // get the number of nodes const size_t numNodes = mSkeleton->GetNumNodes(); @@ -630,7 +620,7 @@ namespace EMotionFX MCore::MemSet(conflictNodeFlags.data(), 0, numNodes * sizeof(int8)); // iterate over the all nodes in the actor - for (n = 0; n < numNodes; ++n) + for (size_t n = 0; n < numNodes; ++n) { // get the current node and the pointer to the mesh for the given lod level Node* node = mSkeleton->GetNode(n); @@ -672,19 +662,15 @@ namespace EMotionFX } - uint32 Actor::CalcMaxNumInfluences(uint32 lodLevel, AZStd::vector& outVertexCounts) const + size_t Actor::CalcMaxNumInfluences(size_t lodLevel, AZStd::vector& outVertexCounts) const { - uint32 maxInfluences = 0; - // Reset the values. outVertexCounts.resize(CalcMaxNumInfluences(lodLevel) + 1); - for (size_t k = 0; k < outVertexCounts.size(); ++k) - { - outVertexCounts[k] = 0; - } + AZStd::fill(begin(outVertexCounts), end(outVertexCounts), 0); // Get the vertex counts for the influences. (e.g. 500 vertices have 1 skinning influence, 300 vertices have 2 skinning influences etc.) - AZStd::vector meshVertexCounts; + size_t maxInfluences = 0; + AZStd::vector meshVertexCounts; const size_t numNodes = GetNumNodes(); for (size_t i = 0; i < numNodes; ++i) { @@ -694,8 +680,8 @@ namespace EMotionFX continue; } - const uint32 meshMaxInfluences = mesh->CalcMaxNumInfluences(meshVertexCounts); - maxInfluences = MCore::Max(maxInfluences, meshMaxInfluences); + const size_t meshMaxInfluences = mesh->CalcMaxNumInfluences(meshVertexCounts); + maxInfluences = AZStd::max(maxInfluences, meshMaxInfluences); for (size_t j = 0; j < meshVertexCounts.size(); ++j) { @@ -724,7 +710,7 @@ namespace EMotionFX } - bool Actor::CheckIfHasSkinnedMeshes(AZ::u32 lodLevel) const + bool Actor::CheckIfHasSkinnedMeshes(size_t lodLevel) const { const size_t numNodes = mSkeleton->GetNumNodes(); for (size_t i = 0; i < numNodes; ++i) @@ -763,14 +749,14 @@ namespace EMotionFX const size_t numLODs = GetNumLODLevels(); // for all LODs, get rid of all the morph setups for each geometry LOD - for (uint32 i = 0; i < mMorphSetups.size(); ++i) + for (MorphSetup* mMorphSetup : mMorphSetups) { - if (mMorphSetups[i]) + if (mMorphSetup) { - mMorphSetups[i]->Destroy(); + mMorphSetup->Destroy(); } - mMorphSetups[i] = nullptr; + mMorphSetup = nullptr; } // remove all modifiers from the stacks for each lod in all nodes @@ -781,7 +767,7 @@ namespace EMotionFX for (size_t i = 0; i < numNodes; ++i) { // process all LOD levels - for (uint32 lod = 0; lod < numLODs; ++lod) + for (size_t lod = 0; lod < numLODs; ++lod) { // if we have a modifier stack MeshDeformerStack* stack = GetMeshDeformerStack(lod, i); @@ -805,7 +791,7 @@ namespace EMotionFX // check if the material is used by the given mesh - bool Actor::CheckIfIsMaterialUsed(Mesh* mesh, uint32 materialIndex) const + bool Actor::CheckIfIsMaterialUsed(Mesh* mesh, size_t materialIndex) const { // check if the mesh is valid if (mesh == nullptr) @@ -829,7 +815,7 @@ namespace EMotionFX // check if the material is used by a mesh of this actor - bool Actor::CheckIfIsMaterialUsed(uint32 lodLevel, uint32 index) const + bool Actor::CheckIfIsMaterialUsed(size_t lodLevel, size_t index) const { // iterate through all nodes of the actor and check its meshes const size_t numNodes = mSkeleton->GetNumNodes(); @@ -848,7 +834,7 @@ namespace EMotionFX // remove the given material and reassign all material numbers of the submeshes - void Actor::RemoveMaterial(uint32 lodLevel, uint32 index) + void Actor::RemoveMaterial(size_t lodLevel, size_t index) { MCORE_ASSERT(lodLevel < mMaterials.size()); @@ -865,7 +851,7 @@ namespace EMotionFX // the maximum number of children of a root node, the node with the most children // will become our repositioning node - uint32 maxNumChilds = 0; + size_t maxNumChilds = 0; // traverse through all root nodes const size_t numRootNodes = mSkeleton->GetNumRootNodes(); @@ -898,7 +884,7 @@ namespace EMotionFX // extract a bone list - void Actor::ExtractBoneList(uint32 lodLevel, AZStd::vector* outBoneList) const + void Actor::ExtractBoneList(size_t lodLevel, AZStd::vector* outBoneList) const { // clear the existing items outBoneList->clear(); @@ -927,8 +913,8 @@ namespace EMotionFX for (uint32 v = 0; v < numOrgVerts; ++v) { // for all influences for this vertex - const uint32 numInfluences = aznumeric_cast(skinningLayer->GetNumInfluences(v)); - for (uint32 i = 0; i < numInfluences; ++i) + const size_t numInfluences = skinningLayer->GetNumInfluences(v); + for (size_t i = 0; i < numInfluences; ++i) { // get the node number of the bone uint16 nodeNr = skinningLayer->GetInfluence(v, i)->GetNodeNr(); @@ -1122,7 +1108,7 @@ namespace EMotionFX // find the first active parent node in a given skeletal LOD - size_t Actor::FindFirstActiveParentBone(uint32 skeletalLOD, size_t startNodeIndex) const + size_t Actor::FindFirstActiveParentBone(size_t skeletalLOD, size_t startNodeIndex) const { size_t curNodeIndex = startNodeIndex; @@ -1290,7 +1276,7 @@ namespace EMotionFX Node* node = mSkeleton->GetNode(i); // iterate through all LOD levels - for (uint32 lodLevel = 0; lodLevel < numLODLevels; ++lodLevel) + for (size_t lodLevel = 0; lodLevel < numLODLevels; ++lodLevel) { // reinit the mesh deformer stacks MeshDeformerStack* stack = GetMeshDeformerStack(lodLevel, i); @@ -1493,10 +1479,10 @@ namespace EMotionFX { outPoints.clear(); - const uint32 geomLODLevel = 0; + const size_t geomLODLevel = 0; const size_t numNodes = mSkeleton->GetNumNodes(); - for (int nodeIndex = 0; nodeIndex < numNodes; nodeIndex++) + for (size_t nodeIndex = 0; nodeIndex < numNodes; nodeIndex++) { // check if this node has a mesh, if not we can skip it Mesh* mesh = GetMesh(geomLODLevel, nodeIndex); @@ -1744,7 +1730,7 @@ namespace EMotionFX const Transform nodeTransform = pose.GetModelSpaceTransform(nodeIndex); const Transform mirroredTransform = nodeTransform.Mirrored(AZ::Vector3(1.0f, 0.0f, 0.0f)); - uint32 numMatches = 0; + size_t numMatches = 0; uint16 result = MCORE_INVALIDINDEX16; // find nodes that have the mirrored transform @@ -1793,8 +1779,8 @@ namespace EMotionFX Pose& bindPose = *mSkeleton->GetBindPose(); bindPose.LinkToActor(this, Pose::FLAG_LOCALTRANSFORMREADY, false); - const AZ::u32 numMorphs = bindPose.GetNumMorphWeights(); - for (AZ::u32 i = 0; i < numMorphs; ++i) + const size_t numMorphs = bindPose.GetNumMorphWeights(); + for (size_t i = 0; i < numMorphs; ++i) { bindPose.SetMorphWeight(i, 0.0f); } @@ -1889,13 +1875,13 @@ namespace EMotionFX } } - void Actor::ReserveMaterials(uint32 lodLevel, uint32 numMaterials) + void Actor::ReserveMaterials(size_t lodLevel, size_t numMaterials) { mMaterials[lodLevel].reserve(numMaterials); } // get a material - Material* Actor::GetMaterial(uint32 lodLevel, uint32 nr) const + Material* Actor::GetMaterial(size_t lodLevel, size_t nr) const { MCORE_ASSERT(lodLevel < mMaterials.size()); MCORE_ASSERT(nr < mMaterials[lodLevel].size()); @@ -1904,41 +1890,29 @@ namespace EMotionFX // get a material by name - uint32 Actor::FindMaterialIndexByName(uint32 lodLevel, const char* name) const + size_t Actor::FindMaterialIndexByName(size_t lodLevel, const char* name) const { - MCORE_ASSERT(lodLevel < mMaterials.size()); - // search through all materials - const uint32 numMaterials = mMaterials[lodLevel].size(); - for (uint32 i = 0; i < numMaterials; ++i) + const auto foundMaterial = AZStd::find_if(mMaterials[lodLevel].begin(), mMaterials[lodLevel].end(), [name](const Material* material) { - if (mMaterials[lodLevel][i]->GetNameString() == name) - { - return i; - } - } - - // no material found - return MCORE_INVALIDINDEX32; + return material->GetNameString() == name; + }); + return foundMaterial != mMaterials[lodLevel].end() ? AZStd::distance(mMaterials[lodLevel].begin(), foundMaterial) : InvalidIndex; } // set a material - void Actor::SetMaterial(uint32 lodLevel, uint32 nr, Material* mat) + void Actor::SetMaterial(size_t lodLevel, size_t nr, Material* mat) { - MCORE_ASSERT(lodLevel < mMaterials.size()); - MCORE_ASSERT(nr < mMaterials[lodLevel].size()); mMaterials[lodLevel][nr] = mat; } - void Actor::AddMaterial(uint32 lodLevel, Material* mat) + void Actor::AddMaterial(size_t lodLevel, Material* mat) { - MCORE_ASSERT(lodLevel < mMaterials.size()); mMaterials[lodLevel].emplace_back(mat); } - size_t Actor::GetNumMaterials(uint32 lodLevel) const + size_t Actor::GetNumMaterials(size_t lodLevel) const { - MCORE_ASSERT(lodLevel < mMaterials.size()); return mMaterials[lodLevel].size(); } @@ -1990,7 +1964,7 @@ namespace EMotionFX } - void Actor::SetMorphSetup(uint32 lodLevel, MorphSetup* setup) + void Actor::SetMorphSetup(size_t lodLevel, MorphSetup* setup) { mMorphSetups[lodLevel] = setup; } @@ -2157,14 +2131,14 @@ namespace EMotionFX return lodLevels[lodLevel].mNodeInfos[nodeIndex].mMesh; } - MeshDeformerStack* Actor::GetMeshDeformerStack(uint32 lodLevel, size_t nodeIndex) const + MeshDeformerStack* Actor::GetMeshDeformerStack(size_t lodLevel, size_t nodeIndex) const { const AZStd::vector& lodLevels = m_meshLodData.m_lodLevels; return lodLevels[lodLevel].mNodeInfos[nodeIndex].mStack; } // set the mesh for a given node in a given LOD - void Actor::SetMesh(uint32 lodLevel, size_t nodeIndex, Mesh* mesh) + void Actor::SetMesh(size_t lodLevel, size_t nodeIndex, Mesh* mesh) { AZStd::vector& lodLevels = m_meshLodData.m_lodLevels; lodLevels[lodLevel].mNodeInfos[nodeIndex].mMesh = mesh; @@ -2172,14 +2146,14 @@ namespace EMotionFX // set the mesh deformer stack for a given node in a given LOD - void Actor::SetMeshDeformerStack(uint32 lodLevel, size_t nodeIndex, MeshDeformerStack* stack) + void Actor::SetMeshDeformerStack(size_t lodLevel, size_t nodeIndex, MeshDeformerStack* stack) { AZStd::vector& lodLevels = m_meshLodData.m_lodLevels; lodLevels[lodLevel].mNodeInfos[nodeIndex].mStack = stack; } // check if the mesh has a skinning deformer (either linear or dual quat) - bool Actor::CheckIfHasSkinningDeformer(uint32 lodLevel, size_t nodeIndex) const + bool Actor::CheckIfHasSkinningDeformer(size_t lodLevel, size_t nodeIndex) const { // check if there is a mesh Mesh* mesh = GetMesh(lodLevel, nodeIndex); @@ -2199,7 +2173,7 @@ namespace EMotionFX } // remove the mesh for a given node in a given LOD - void Actor::RemoveNodeMeshForLOD(uint32 lodLevel, size_t nodeIndex, bool destroyMesh) + void Actor::RemoveNodeMeshForLOD(size_t lodLevel, size_t nodeIndex, bool destroyMesh) { AZStd::vector& lodLevels = m_meshLodData.m_lodLevels; @@ -2289,7 +2263,7 @@ namespace EMotionFX } // scale morph target data - for (uint32 lod = 0; lod < numLODs; ++lod) + for (size_t lod = 0; lod < numLODs; ++lod) { MorphSetup* morphSetup = GetMorphSetup(lod); if (morphSetup) @@ -2819,8 +2793,8 @@ namespace EMotionFX AZ_Assert(morphTargetDeltaView.data(), "Unable to find MORPHTARGET_VERTEXDELTAS buffer"); const AZ::RPI::PackedCompressedMorphTargetDelta* vertexDeltas = reinterpret_cast(morphTargetDeltaView.data()); - const AZ::u32 numMorphTargets = morphSetup->GetNumMorphTargets(); - for (AZ::u32 mtIndex = 0; mtIndex < numMorphTargets; ++mtIndex) + const size_t numMorphTargets = morphSetup->GetNumMorphTargets(); + for (size_t mtIndex = 0; mtIndex < numMorphTargets; ++mtIndex) { MorphTargetStandard* morphTarget = static_cast(morphSetup->GetMorphTarget(mtIndex)); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Actor.h b/Gems/EMotionFX/Code/EMotionFX/Source/Actor.h index 21b97c0bd6..efcfa52413 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Actor.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Actor.h @@ -234,7 +234,7 @@ namespace EMotionFX * @param lodLevel The LOD level to check for. * @result Returns true when skinned meshes are present in the specified LOD level, otherwise false is returned. */ - bool CheckIfHasSkinnedMeshes(AZ::u32 lodLevel) const; + bool CheckIfHasSkinnedMeshes(size_t lodLevel) const; /** * Extract a list with nodes that represent bones. @@ -245,7 +245,7 @@ namespace EMotionFX * @param outBoneList The array of indices to nodes that will be filled with the nodes that are bones. When the outBoneList array * already contains items, the array will first be cleared, so all existing contents will be lost. */ - void ExtractBoneList(uint32 lodLevel, AZStd::vector* outBoneList) const; + void ExtractBoneList(size_t lodLevel, AZStd::vector* outBoneList) const; //------------------------------------------------ void SetPhysicsSetup(const AZStd::shared_ptr& physicsSetup); @@ -261,7 +261,7 @@ namespace EMotionFX * @param lodLevel The geometry LOD level to work on. * @param numMaterials The amount of materials to pre-allocate space for. */ - void ReserveMaterials(uint32 lodLevel, uint32 numMaterials); + void ReserveMaterials(size_t lodLevel, size_t numMaterials); /** * Get a given material. @@ -269,7 +269,7 @@ namespace EMotionFX * @param nr The material number to get. * @result A pointer to the material. */ - Material* GetMaterial(uint32 lodLevel, uint32 nr) const; + Material* GetMaterial(size_t lodLevel, size_t nr) const; /** * Find the material number/index of the material with the specified name. @@ -279,7 +279,7 @@ namespace EMotionFX * @result Returns the material number/index, which you can use to GetMaterial. When no material with the given name * can be found, a value of MCORE_INVALIDINDEX32 is returned. */ - uint32 FindMaterialIndexByName(uint32 lodLevel, const char* name) const; + size_t FindMaterialIndexByName(size_t lodLevel, const char* name) const; /** * Set a given material. @@ -287,14 +287,14 @@ namespace EMotionFX * @param nr The material number to set. * @param mat The material to set at this index. */ - void SetMaterial(uint32 lodLevel, uint32 nr, Material* mat); + void SetMaterial(size_t lodLevel, size_t nr, Material* mat); /** * Add a material to the back of the material list. * @param lodLevel The LOD level add the material to. * @param mat The material to add to the back of the list. */ - void AddMaterial(uint32 lodLevel, Material* mat); + void AddMaterial(size_t lodLevel, Material* mat); /** * Remove the given material from the material list and reassign all material numbers of the sub meshes @@ -306,14 +306,14 @@ namespace EMotionFX * @param lodLevel The LOD level add the material to. * @param index The material index of the material to remove. */ - void RemoveMaterial(uint32 lodLevel, uint32 index); + void RemoveMaterial(size_t lodLevel, size_t index); /** * Get the number of materials. * @param lodLevel The LOD level to get the number of material from. * @result The number of materials this actor has/uses. */ - size_t GetNumMaterials(uint32 lodLevel) const; + size_t GetNumMaterials(size_t lodLevel) const; /** * Removes all materials from this actor. @@ -329,7 +329,7 @@ namespace EMotionFX * @param index The material number to check. * @result Returns true when there are meshes using the material, otherwise false is returned. */ - bool CheckIfIsMaterialUsed(uint32 lodLevel, uint32 index) const; + bool CheckIfIsMaterialUsed(size_t lodLevel, size_t index) const; //------------------------------------------------ @@ -348,20 +348,20 @@ namespace EMotionFX * @param[in] copySkeletalLODFlags Copy over the skeletal LOD flags in case of true, skip them in case of false. * @param[in] delLODActorFromMem When set to true, the method will automatically delete the given copyActor from memory. */ - void CopyLODLevel(Actor* copyActor, uint32 copyLODLevel, uint32 replaceLODLevel, bool copySkeletalLODFlags); + void CopyLODLevel(Actor* copyActor, size_t copyLODLevel, size_t replaceLODLevel, bool copySkeletalLODFlags); /** * Insert LOD level at the given position. * This function will not copy any meshes, deformer, morph targets or materials but just insert an empty LOD level. * @param[in] insertAt The position to insert the new LOD level. */ - void InsertLODLevel(uint32 insertAt); + void InsertLODLevel(size_t insertAt); /** * Set the number of LOD levels. * This will be called by the importer. Do not use manually. */ - void SetNumLODLevels(uint32 numLODs, bool adjustMorphSetup = true); + void SetNumLODLevels(size_t numLODs, bool adjustMorphSetup = true); /** * Get the number of LOD levels inside this actor. @@ -385,7 +385,7 @@ namespace EMotionFX * @param outNumVertices The integer to write the number of vertices in. * @param outNumIndices The integer to write the number of indices in. */ - void CalcMeshTotals(uint32 lodLevel, uint32* outNumPolygons, uint32* outNumVertices, uint32* outNumIndices) const; + void CalcMeshTotals(size_t lodLevel, uint32* outNumPolygons, uint32* outNumVertices, uint32* outNumIndices) const; /** * Calculates the total number of vertices and indices of all STATIC node meshes for the given LOD. @@ -394,7 +394,7 @@ namespace EMotionFX * @param outNumVertices The integer to write the number of vertices in. * @param outNumIndices The integer to write the number of indices in. */ - void CalcStaticMeshTotals(uint32 lodLevel, uint32* outNumVertices, uint32* outNumIndices); + void CalcStaticMeshTotals(size_t lodLevel, uint32* outNumVertices, uint32* outNumIndices); /** * Calculates the total number of vertices and indices of all DEFORMABLE node meshes for the given LOD. @@ -404,7 +404,7 @@ namespace EMotionFX * @param outNumVertices The integer to write the number of vertices in. * @param outNumIndices The integer to write the number of indices in. */ - void CalcDeformableMeshTotals(uint32 lodLevel, uint32* outNumVertices, uint32* outNumIndices); + void CalcDeformableMeshTotals(size_t lodLevel, uint32* outNumVertices, uint32* outNumIndices); /** * Calculates the maximum number of bone influences. @@ -412,7 +412,7 @@ namespace EMotionFX * @param lodLevel The LOD level, where 0 is the highest detail LOD level. This value must be in range of [0..GetNumLODLevels()-1]. * @result The maximum number of influences. This will be 0 for non-softskinned objects. */ - uint32 CalcMaxNumInfluences(uint32 lodLevel) const; + size_t CalcMaxNumInfluences(size_t lodLevel) const; /** * Calculates the maximum number of bone influences. @@ -424,7 +424,7 @@ namespace EMotionFX * @param lodLevel The detail level to calculate the results for. A value of 0 is the highest detail. * @result The maximum number of vertex/bone influences. This will be 0 for rigid, non-skinned objects. */ - uint32 CalcMaxNumInfluences(uint32 lodLevel, AZStd::vector& outVertexCounts) const; + size_t CalcMaxNumInfluences(size_t lodLevel, AZStd::vector& outVertexCounts) const; /** * Verify if the skinning will look correctly in the given geometry LOD for a given skeletal LOD level. @@ -438,7 +438,7 @@ namespace EMotionFX * disabled nodes from the given skeletal LOD level. * @param geometryLODLevel The geometry LOD level to test the skeletal LOD against with. */ - void VerifySkinning(AZStd::vector& conflictNodeFlags, uint32 skeletalLODLevel, uint32 geometryLODLevel); + void VerifySkinning(AZStd::vector& conflictNodeFlags, size_t skeletalLODLevel, size_t geometryLODLevel); /** * Checks if the given material is used by a given mesh. @@ -446,7 +446,7 @@ namespace EMotionFX * @param materialIndex The index of the material to check. * @return True if one of the submeshes of the given mesh uses the given material, false if not. */ - bool CheckIfIsMaterialUsed(Mesh* mesh, uint32 materialIndex) const; + bool CheckIfIsMaterialUsed(Mesh* mesh, size_t materialIndex) const; //------------------ @@ -546,7 +546,7 @@ namespace EMotionFX * @result A smart pointer object to the morph setup. Use the MCore::Pointer::GetPointer() to get the actual pointer. * That GetPointer() method will return nullptr when there is no morph setup for the given LOD level. */ - MCORE_INLINE MorphSetup* GetMorphSetup(uint32 geomLODLevel) const { return mMorphSetups[geomLODLevel]; } + MCORE_INLINE MorphSetup* GetMorphSetup(size_t geomLODLevel) const { return mMorphSetups[geomLODLevel]; } /** * Remove all morph setups. Morph setups contain all morph targtets. @@ -561,7 +561,7 @@ namespace EMotionFX * @param lodLevel The LOD level, which must be in range of [0..GetNumLODLevels()-1]. * @param setup The morph setup for this LOD. */ - void SetMorphSetup(uint32 lodLevel, MorphSetup* setup); + void SetMorphSetup(size_t lodLevel, MorphSetup* setup); /** * Get the number of node groups inside this actor object. @@ -735,7 +735,7 @@ namespace EMotionFX * @param startNodeIndex The node to start looking at, for example the node index of the finger bone. * @result Returns the index of the first active node, when moving up the hierarchy towards the root node. Returns MCORE_INVALIDINDEX32 when not found. */ - size_t FindFirstActiveParentBone(uint32 skeletalLOD, size_t startNodeIndex) const; + size_t FindFirstActiveParentBone(size_t skeletalLOD, size_t startNodeIndex) const; /** * Make the geometry LOD levels compatible with the skinning LOD levels. @@ -777,7 +777,7 @@ namespace EMotionFX uint32 GetThreadIndex() const { return mThreadIndex; } Mesh* GetMesh(size_t lodLevel, size_t nodeIndex) const; - MeshDeformerStack* GetMeshDeformerStack(uint32 lodLevel, size_t nodeIndex) const; + MeshDeformerStack* GetMeshDeformerStack(size_t lodLevel, size_t nodeIndex) const; /** Finds the mesh points for which the specified node is the node with the highest influence. * This is a pretty expensive function which is only intended for use in the editor. @@ -790,13 +790,13 @@ namespace EMotionFX MCORE_INLINE Skeleton* GetSkeleton() const { return mSkeleton; } MCORE_INLINE size_t GetNumNodes() const { return mSkeleton->GetNumNodes(); } - void SetMesh(uint32 lodLevel, size_t nodeIndex, Mesh* mesh); - void SetMeshDeformerStack(uint32 lodLevel, size_t nodeIndex, MeshDeformerStack* stack); + void SetMesh(size_t lodLevel, size_t nodeIndex, Mesh* mesh); + void SetMeshDeformerStack(size_t lodLevel, size_t nodeIndex, MeshDeformerStack* stack); - bool CheckIfHasMorphDeformer(uint32 lodLevel, size_t nodeIndex) const; - bool CheckIfHasSkinningDeformer(uint32 lodLevel, size_t nodeIndex) const; + bool CheckIfHasMorphDeformer(size_t lodLevel, size_t nodeIndex) const; + bool CheckIfHasSkinningDeformer(size_t lodLevel, size_t nodeIndex) const; - void RemoveNodeMeshForLOD(uint32 lodLevel, size_t nodeIndex, bool destroyMesh = true); + void RemoveNodeMeshForLOD(size_t lodLevel, size_t nodeIndex, bool destroyMesh = true); void SetNumNodes(size_t numNodes); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.h b/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.h index 4b605afc3b..c6bd84c0c8 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.h @@ -801,7 +801,7 @@ namespace EMotionFX * @param index An index in the array of enabled nodes. This must be in range of [0..GetNumEnabledNodes()-1]. * @result The node number, which relates to Actor::GetNode( returnValue ). */ - MCORE_INLINE uint16 GetEnabledNode(uint32 index) const { return mEnabledNodes[index]; } + MCORE_INLINE uint16 GetEnabledNode(size_t index) const { return mEnabledNodes[index]; } /** * Enable all nodes inside the actor instance. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/DualQuatSkinDeformer.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/DualQuatSkinDeformer.cpp index 2daaac6a85..34e336bf2f 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/DualQuatSkinDeformer.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/DualQuatSkinDeformer.cpp @@ -294,7 +294,7 @@ namespace EMotionFX } // initialize the mesh deformer - void DualQuatSkinDeformer::Reinitialize(Actor* actor, Node* node, uint32 lodLevel) + void DualQuatSkinDeformer::Reinitialize(Actor* actor, Node* node, size_t lodLevel) { MCORE_UNUSED(actor); MCORE_UNUSED(node); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/DualQuatSkinDeformer.h b/Gems/EMotionFX/Code/EMotionFX/Source/DualQuatSkinDeformer.h index fc1c986b68..d3bec012f6 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/DualQuatSkinDeformer.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/DualQuatSkinDeformer.h @@ -68,7 +68,7 @@ namespace EMotionFX * @param node The node where the mesh belongs to during this initialization. * @param lodLevel The LOD level of the mesh the mesh deformer works on. */ - void Reinitialize(Actor* actor, Node* node, uint32 lodLevel) override; + void Reinitialize(Actor* actor, Node* node, size_t lodLevel) override; /** * Creates an exact clone (copy) of this deformer, and returns a pointer to it. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.cpp index 1203e3762a..c86cc66b61 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.cpp @@ -740,7 +740,7 @@ namespace EMotionFX // returns the maximum number of weights/influences for this mesh - uint32 Mesh::CalcMaxNumInfluences() const + size_t Mesh::CalcMaxNumInfluences() const { // try to locate the skinning attribute information SkinningInfoVertexAttributeLayer* skinningLayer = (SkinningInfoVertexAttributeLayer*)FindSharedVertexAttributeLayer(SkinningInfoVertexAttributeLayer::TYPE_ID); @@ -760,37 +760,33 @@ namespace EMotionFX } // return the maximum number of influences - return aznumeric_cast(maxInfluences); + return maxInfluences; } // returns the maximum number of weights/influences for this mesh plus some extra information - uint32 Mesh::CalcMaxNumInfluences(AZStd::vector& outVertexCounts) const + size_t Mesh::CalcMaxNumInfluences(AZStd::vector& outVertexCounts) const { - size_t maxInfluences = 0; - // Reset values. outVertexCounts.resize(CalcMaxNumInfluences() + 1); - for (size_t j = 0; j < outVertexCounts.size(); ++j) - { - outVertexCounts[j] = 0; - } + AZStd::fill(begin(outVertexCounts), end(outVertexCounts), 0); // Does the mesh have a skinning layer? If no we can quit directly as this means there are only unskinned vertices. SkinningInfoVertexAttributeLayer* skinningLayer = (SkinningInfoVertexAttributeLayer*)FindSharedVertexAttributeLayer(SkinningInfoVertexAttributeLayer::TYPE_ID); if (!skinningLayer) { outVertexCounts[0] = GetNumVertices(); - return aznumeric_cast(maxInfluences); + return 0; } - uint32* orgVerts = (uint32*)FindVertexData(Mesh::ATTRIB_ORGVTXNUMBERS); + const uint32* orgVerts = (uint32*)FindVertexData(Mesh::ATTRIB_ORGVTXNUMBERS); // Get the vertex counts for the influences. + size_t maxInfluences = 0; const uint32 numVerts = GetNumVertices(); for (uint32 i = 0; i < numVerts; ++i) { - uint32 orgVertex = orgVerts[i]; + const uint32 orgVertex = orgVerts[i]; // Increase the number of vertices for the given influence value. const size_t numInfluences = skinningLayer->GetNumInfluences(orgVertex); @@ -800,7 +796,7 @@ namespace EMotionFX maxInfluences = AZStd::max(maxInfluences, numInfluences); } - return aznumeric_cast(maxInfluences); + return maxInfluences; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.h b/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.h index 4a86a9875d..420bac0f33 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.h @@ -462,7 +462,7 @@ namespace EMotionFX * This is calculated by for each vertex checking the number of bone influences, and take the maximum of that amount. * @result The maximum number of influences. This will be 0 for non-softskinned objects. */ - uint32 CalcMaxNumInfluences() const; + size_t CalcMaxNumInfluences() const; /** * Calculates the maximum number of bone influences. @@ -472,7 +472,7 @@ namespace EMotionFX * which are effected by 4 bones. * @result The maximum number of influences. This will be 0 for non-softskinned objects. */ - uint32 CalcMaxNumInfluences(AZStd::vector& outVertexCounts) const; + size_t CalcMaxNumInfluences(AZStd::vector& outVertexCounts) const; /** * Extract a list of positions of the original vertices. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MeshDeformer.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MeshDeformer.cpp index a7d628b8c3..b269fdecdd 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MeshDeformer.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MeshDeformer.cpp @@ -45,7 +45,7 @@ namespace EMotionFX // reinitialize the mesh deformer - void MeshDeformer::Reinitialize(Actor* actor, Node* node, uint32 lodLevel) + void MeshDeformer::Reinitialize(Actor* actor, Node* node, size_t lodLevel) { MCORE_UNUSED(actor); MCORE_UNUSED(node); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MeshDeformer.h b/Gems/EMotionFX/Code/EMotionFX/Source/MeshDeformer.h index 6b379eda1d..78bdc842e9 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MeshDeformer.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MeshDeformer.h @@ -49,7 +49,7 @@ namespace EMotionFX * @param node The node where the mesh belongs to during this initialization. * @param lodLevel The LOD level of the mesh the mesh deformer works on. */ - virtual void Reinitialize(Actor* actor, Node* node, uint32 lodLevel); + virtual void Reinitialize(Actor* actor, Node* node, size_t lodLevel); /** * Creates an exact clone (copy) of this deformer, and returns a pointer to it. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MeshDeformerStack.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MeshDeformerStack.cpp index c4fae4d3bb..82245a505f 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MeshDeformerStack.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MeshDeformerStack.cpp @@ -114,13 +114,13 @@ namespace EMotionFX // reinitialize mesh deformers - void MeshDeformerStack::ReinitializeDeformers(Actor* actor, Node* node, uint32 lodLevel) + void MeshDeformerStack::ReinitializeDeformers(Actor* actor, Node* node, size_t lodLevel) { // if we have deformers in the stack - const uint32 numDeformers = mDeformers.size(); + const size_t numDeformers = mDeformers.size(); // iterate through the deformers and reinitialize them - for (uint32 i = 0; i < numDeformers; ++i) + for (size_t i = 0; i < numDeformers; ++i) { mDeformers[i]->Reinitialize(actor, node, lodLevel); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MeshDeformerStack.h b/Gems/EMotionFX/Code/EMotionFX/Source/MeshDeformerStack.h index 020e2b2b75..0b1ce6fbcb 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MeshDeformerStack.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MeshDeformerStack.h @@ -74,7 +74,7 @@ namespace EMotionFX * @param node The node to use for the reinitialize, so the node where the mesh belongs to during this initialization. * @param lodLevel The LOD level the mesh deformers work on. */ - void ReinitializeDeformers(Actor* actor, Node* node, uint32 lodLevel); + void ReinitializeDeformers(Actor* actor, Node* node, size_t lodLevel); /** * Add a given deformer to the back of the stack. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MorphMeshDeformer.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MorphMeshDeformer.cpp index 41b1475927..b40ff27ce0 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MorphMeshDeformer.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MorphMeshDeformer.cpp @@ -194,7 +194,7 @@ namespace EMotionFX // initialize the mesh deformer - void MorphMeshDeformer::Reinitialize(Actor* actor, Node* node, uint32 lodLevel) + void MorphMeshDeformer::Reinitialize(Actor* actor, Node* node, size_t lodLevel) { // clear the deform passes, but don't free the currently allocated/reserved memory mDeformPasses.clear(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MorphMeshDeformer.h b/Gems/EMotionFX/Code/EMotionFX/Source/MorphMeshDeformer.h index ae56ecc96d..303c379248 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MorphMeshDeformer.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MorphMeshDeformer.h @@ -103,7 +103,7 @@ namespace EMotionFX * @param node The node where the mesh belongs to during this initialization. * @param lodLevel The LOD level of the mesh the mesh deformer works on. */ - void Reinitialize(Actor* actor, Node* node, uint32 lodLevel) override; + void Reinitialize(Actor* actor, Node* node, size_t lodLevel) override; /** * Creates an exact clone (copy) of this deformer, and returns a pointer to it. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MorphSetup.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MorphSetup.cpp index 386f73ae23..0b27ee634e 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MorphSetup.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MorphSetup.cpp @@ -196,7 +196,7 @@ namespace EMotionFX } - void MorphSetup::ReserveMorphTargets(uint32 numMorphTargets) + void MorphSetup::ReserveMorphTargets(size_t numMorphTargets) { mMorphTargets.reserve(numMorphTargets); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MorphSetup.h b/Gems/EMotionFX/Code/EMotionFX/Source/MorphSetup.h index c7c04ae636..45c55d301c 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MorphSetup.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MorphSetup.h @@ -34,7 +34,7 @@ namespace EMotionFX * This does not influence the return value of GetNumMorphTargets(). * @param numMorphTargets The number of morph targets to pre-allocate space for. */ - void ReserveMorphTargets(uint32 numMorphTargets); + void ReserveMorphTargets(size_t numMorphTargets); /** * Get the number of morph targets inside this morph setup. @@ -47,7 +47,7 @@ namespace EMotionFX * @param nr The morph target number, must be in range of [0..GetNumMorphTargets()-1]. * @result A pointer to the morph target. */ - MCORE_INLINE MorphTarget* GetMorphTarget(uint32 nr) const { return mMorphTargets[nr]; } + MCORE_INLINE MorphTarget* GetMorphTarget(size_t nr) const { return mMorphTargets[nr]; } /** * Add a morph target to this morph setup. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MorphTarget.h b/Gems/EMotionFX/Code/EMotionFX/Source/MorphTarget.h index 829d6f5be6..3e32229691 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MorphTarget.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MorphTarget.h @@ -68,7 +68,7 @@ namespace EMotionFX * @param scale This must contain the initial scale, and will be modified inside this method as well. * @param weight The absolute weight value. */ - virtual void ApplyTransformation(ActorInstance* actorInstance, uint32 nodeIndex, AZ::Vector3& position, AZ::Quaternion& rotation, AZ::Vector3& scale, float weight) = 0; + virtual void ApplyTransformation(ActorInstance* actorInstance, size_t nodeIndex, AZ::Vector3& position, AZ::Quaternion& rotation, AZ::Vector3& scale, float weight) = 0; /** * Get the unique ID of this morph target. @@ -212,7 +212,7 @@ namespace EMotionFX * @param nodeIndex The node number to perform the check on. * @result Returns true if the given node will be modified by this morph target, otherwise false is returned. */ - virtual bool Influences(uint32 nodeIndex) const = 0; + virtual bool Influences(size_t nodeIndex) const = 0; /** * Calculate the range based weight value from a normalized weight value given by a facial animation key frame. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MorphTargetStandard.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MorphTargetStandard.cpp index d1c23ba04d..4ee07c38f2 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MorphTargetStandard.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MorphTargetStandard.cpp @@ -170,7 +170,7 @@ namespace EMotionFX // apply the relative transformation to the specified node // store the result in the position, rotation and scale parameters - void MorphTargetStandard::ApplyTransformation(ActorInstance* actorInstance, uint32 nodeIndex, AZ::Vector3& position, AZ::Quaternion& rotation, AZ::Vector3& scale, float weight) + void MorphTargetStandard::ApplyTransformation(ActorInstance* actorInstance, size_t nodeIndex, AZ::Vector3& position, AZ::Quaternion& rotation, AZ::Vector3& scale, float weight) { // calculate the normalized weight (in range of 0..1) const float newWeight = MCore::Clamp(weight, mRangeMin, mRangeMax); // make sure its within the range @@ -202,7 +202,7 @@ namespace EMotionFX // check if this morph target influences the specified node or not - bool MorphTargetStandard::Influences(uint32 nodeIndex) const + bool MorphTargetStandard::Influences(size_t nodeIndex) const { // check if there is a deform data object, which works on the specified node for (const DeformData* deformData : mDeformDatas) @@ -338,7 +338,7 @@ namespace EMotionFX //--------------------------------------------------- // constructor - MorphTargetStandard::DeformData::DeformData(uint32 nodeIndex, uint32 numVerts) + MorphTargetStandard::DeformData::DeformData(size_t nodeIndex, uint32 numVerts) { mNodeIndex = nodeIndex; mNumVerts = numVerts; @@ -356,7 +356,7 @@ namespace EMotionFX // create - MorphTargetStandard::DeformData* MorphTargetStandard::DeformData::Create(uint32 nodeIndex, uint32 numVerts) + MorphTargetStandard::DeformData* MorphTargetStandard::DeformData::Create(size_t nodeIndex, uint32 numVerts) { return aznew MorphTargetStandard::DeformData(nodeIndex, numVerts); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MorphTargetStandard.h b/Gems/EMotionFX/Code/EMotionFX/Source/MorphTargetStandard.h index cda878efbb..d519e98f57 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MorphTargetStandard.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MorphTargetStandard.h @@ -66,7 +66,7 @@ namespace EMotionFX uint32 mVertexNr; /**< The vertex number inside the mesh to apply this to. */ }; - static DeformData* Create(uint32 nodeIndex, uint32 numVerts); + static DeformData* Create(size_t nodeIndex, uint32 numVerts); // creates a clone DeformData* Clone(); @@ -74,7 +74,7 @@ namespace EMotionFX public: VertexDelta* mDeltas; /**< The delta values. */ uint32 mNumVerts; /**< The number of vertices in the mDeltas and mVertexNumbers arrays. */ - uint32 mNodeIndex; /**< The node which this data works on. */ + size_t mNodeIndex; /**< The node which this data works on. */ float mMinValue; /**< The compression/decompression minimum value for the delta positions. */ float mMaxValue; /**< The compression/decompression maximum value for the delta positions. */ @@ -83,7 +83,7 @@ namespace EMotionFX * @param nodeIndex The node number on which the deformations should work. * @param numVerts The number of vertices modified by this deform. */ - DeformData(uint32 nodeIndex, uint32 numVerts); + DeformData(size_t nodeIndex, uint32 numVerts); /** * The destructor. @@ -155,14 +155,14 @@ namespace EMotionFX * @param scale The input scale to which relative adjustments will be applied. * @param weight The absolute weight value. */ - void ApplyTransformation(ActorInstance* actorInstance, uint32 nodeIndex, AZ::Vector3& position, AZ::Quaternion& rotation, AZ::Vector3& scale, float weight) override; + void ApplyTransformation(ActorInstance* actorInstance, size_t nodeIndex, AZ::Vector3& position, AZ::Quaternion& rotation, AZ::Vector3& scale, float weight) override; /** * Checks if this morph target would influence the given node. * @param nodeIndex The node to perform the check with. * @result Returns true if the given node will be modified by this morph target, otherwise false is returned. */ - bool Influences(uint32 nodeIndex) const override; + bool Influences(size_t nodeIndex) const override; /** * Apply the relative deformations for this morph target to the given actor instance. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Node.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Node.cpp index 5474087574..8f14fcc2b1 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Node.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Node.cpp @@ -400,22 +400,22 @@ namespace EMotionFX - void Node::SetSkeletalLODLevelBits(uint32 bitValues) + void Node::SetSkeletalLODLevelBits(size_t bitValues) { mSkeletalLODs = bitValues; } - void Node::SetSkeletalLODStatus(uint32 lodLevel, bool enabled) + void Node::SetSkeletalLODStatus(size_t lodLevel, bool enabled) { - MCORE_ASSERT(lodLevel <= 31); + MCORE_ASSERT(lodLevel <= 63); if (enabled) { - mSkeletalLODs |= (1 << lodLevel); + mSkeletalLODs |= (1ull << lodLevel); } else { - mSkeletalLODs &= ~(1 << lodLevel); + mSkeletalLODs &= ~(1ull << lodLevel); } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Node.h b/Gems/EMotionFX/Code/EMotionFX/Source/Node.h index fe22a12c8d..9aa01201d2 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Node.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Node.h @@ -346,7 +346,7 @@ namespace EMotionFX * Bit 0 represents LOD 0, bit 1 represents LOD 1, etc. * @param bitValues The unsigned 32-bits integer that contains the settings for each LOD. */ - void SetSkeletalLODLevelBits(uint32 bitValues); + void SetSkeletalLODLevelBits(size_t bitValues); /** * Set the skeletal LOD status for a given LOD level. @@ -357,14 +357,14 @@ namespace EMotionFX * @param lodLevel The skeletal LOD level to change the settings for. This must be in range of [0..31]. * @param enabled Set to true when you wish the node to be enabled in the given LOD, or false when you wish to disable it in the given LOD. */ - void SetSkeletalLODStatus(uint32 lodLevel, bool enabled); + void SetSkeletalLODStatus(size_t lodLevel, bool enabled); /** * Get the skeletal LOD status for this node at a given skeletal LOD. * @param lodLevel The skeletal LOD level to check. * @result Returns true when this node is enabled in the specified LOD level. Otherwise false is returned. */ - MCORE_INLINE bool GetSkeletalLODStatus(size_t lodLevel) const { return (mSkeletalLODs & (1 << lodLevel)) != 0; } + MCORE_INLINE bool GetSkeletalLODStatus(size_t lodLevel) const { return (mSkeletalLODs & (1ull << lodLevel)) != 0; } //-------------------------------------------- @@ -417,7 +417,7 @@ namespace EMotionFX private: size_t mNodeIndex; /**< The node index, which is the index into the array of nodes inside the Skeleton class. */ size_t mParentIndex; /**< The parent node index, or MCORE_INVALIDINDEX32 when there is no parent. */ - uint32 mSkeletalLODs; /**< The skeletal LOD status values. Each bit represents if this node is enabled or disabled in the given LOD. */ + size_t mSkeletalLODs; /**< The skeletal LOD status values. Each bit represents if this node is enabled or disabled in the given LOD. */ size_t mNameID; /**< The ID, which is generated from the name. You can use this for fast compares between nodes. */ size_t mSemanticNameID; /**< The semantic name ID, for example "LeftHand" or "RightFoot" or so, this can be used for retargeting. */ Skeleton* mSkeleton; /**< The skeleton where this node belongs to. */ diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/NodeMap.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/NodeMap.cpp index edc1ea37cd..e708d255d3 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/NodeMap.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/NodeMap.cpp @@ -39,35 +39,35 @@ namespace EMotionFX // preallocate space - void NodeMap::Reserve(uint32 numEntries) + void NodeMap::Reserve(size_t numEntries) { mEntries.reserve(numEntries); } // resize the entries array - void NodeMap::Resize(uint32 numEntries) + void NodeMap::Resize(size_t numEntries) { mEntries.resize(numEntries); } // modify the first name of a given entry - void NodeMap::SetFirstName(uint32 entryIndex, const char* name) + void NodeMap::SetFirstName(size_t entryIndex, const char* name) { mEntries[entryIndex].mFirstNameID = MCore::GetStringIdPool().GenerateIdForString(name); } // modify the second name - void NodeMap::SetSecondName(uint32 entryIndex, const char* name) + void NodeMap::SetSecondName(size_t entryIndex, const char* name) { mEntries[entryIndex].mSecondNameID = MCore::GetStringIdPool().GenerateIdForString(name); } // modify a given entry - void NodeMap::SetEntry(uint32 entryIndex, const char* firstName, const char* secondName) + void NodeMap::SetEntry(size_t entryIndex, const char* firstName, const char* secondName) { mEntries[entryIndex].mFirstNameID = MCore::GetStringIdPool().GenerateIdForString(firstName); mEntries[entryIndex].mSecondNameID = MCore::GetStringIdPool().GenerateIdForString(secondName); @@ -78,8 +78,8 @@ namespace EMotionFX void NodeMap::SetEntry(const char* firstName, const char* secondName, bool addIfNotExists) { // check if there is already an entry for this name - const uint32 entryIndex = FindEntryIndexByName(firstName); - if (entryIndex == MCORE_INVALIDINDEX32) + const size_t entryIndex = FindEntryIndexByName(firstName); + if (entryIndex == InvalidIndex) { // if there is no such entry yet, and we also don't want to add a new one, then there is nothing to do if (addIfNotExists == false) @@ -107,7 +107,7 @@ namespace EMotionFX // remove a given entry by its index - void NodeMap::RemoveEntryByIndex(uint32 entryIndex) + void NodeMap::RemoveEntryByIndex(size_t entryIndex) { mEntries.erase(AZStd::next(begin(mEntries), entryIndex)); } @@ -116,8 +116,8 @@ namespace EMotionFX // remove a given entry by its name void NodeMap::RemoveEntryByName(const char* firstName) { - const uint32 entryIndex = FindEntryIndexByName(firstName); - if (entryIndex == MCORE_INVALIDINDEX32) + const size_t entryIndex = FindEntryIndexByName(firstName); + if (entryIndex == InvalidIndex) { return; } @@ -127,10 +127,10 @@ namespace EMotionFX // remove a given entry by its name ID - void NodeMap::RemoveEntryByNameID(uint32 firstNameID) + void NodeMap::RemoveEntryByNameID(size_t firstNameID) { - const uint32 entryIndex = FindEntryIndexByNameID(firstNameID); - if (entryIndex == MCORE_INVALIDINDEX32) + const size_t entryIndex = FindEntryIndexByNameID(firstNameID); + if (entryIndex == InvalidIndex) { return; } @@ -208,18 +208,18 @@ namespace EMotionFX uint32 NodeMap::CalcFileChunkSize() const { // add the node map info header - uint32 numBytes = sizeof(FileFormat::NodeMapChunk); + size_t numBytes = sizeof(FileFormat::NodeMapChunk); // for all entries - const uint32 numEntries = mEntries.size(); - for (uint32 i = 0; i < numEntries; ++i) + const size_t numEntries = mEntries.size(); + for (size_t i = 0; i < numEntries; ++i) { numBytes += CalcFileStringSize(GetFirstNameString(i)); numBytes += CalcFileStringSize(GetSecondNameString(i)); } // return the number of bytes - return numBytes; + return aznumeric_caster(numBytes); } @@ -265,7 +265,7 @@ namespace EMotionFX // the main info FileFormat::NodeMapChunk nodeMapChunk{}; - nodeMapChunk.mNumEntries = mEntries.size(); + nodeMapChunk.mNumEntries = aznumeric_caster(mEntries.size()); MCore::Endian::ConvertUnsignedInt32To(&nodeMapChunk.mNumEntries, targetEndianType); if (f.Write(&nodeMapChunk, sizeof(FileFormat::NodeMapChunk)) == 0) { @@ -282,7 +282,7 @@ namespace EMotionFX } // for all entries - const uint32 numEntries = mEntries.size(); + const uint32 numEntries = aznumeric_caster(mEntries.size()); for (uint32 i = 0; i < numEntries; ++i) { if (WriteFileString(&f, GetFirstNameString(i), targetEndianType) == false) @@ -327,28 +327,28 @@ namespace EMotionFX // get the first name as char pointer - const char* NodeMap::GetFirstName(uint32 entryIndex) const + const char* NodeMap::GetFirstName(size_t entryIndex) const { return MCore::GetStringIdPool().GetName(mEntries[entryIndex].mFirstNameID).c_str(); } // get the second node name as char pointer - const char* NodeMap::GetSecondName(uint32 entryIndex) const + const char* NodeMap::GetSecondName(size_t entryIndex) const { return MCore::GetStringIdPool().GetName(mEntries[entryIndex].mSecondNameID).c_str(); } // get the first node name as string - const AZStd::string& NodeMap::GetFirstNameString(uint32 entryIndex) const + const AZStd::string& NodeMap::GetFirstNameString(size_t entryIndex) const { return MCore::GetStringIdPool().GetName(mEntries[entryIndex].mFirstNameID); } // get the second node name as string - const AZStd::string& NodeMap::GetSecondNameString(uint32 entryIndex) const + const AZStd::string& NodeMap::GetSecondNameString(size_t entryIndex) const { return MCore::GetStringIdPool().GetName(mEntries[entryIndex].mSecondNameID); } @@ -357,48 +357,37 @@ namespace EMotionFX // check if we already have an entry for this name bool NodeMap::GetHasEntry(const char* firstName) const { - return (FindEntryIndexByName(firstName) != MCORE_INVALIDINDEX32); + return (FindEntryIndexByName(firstName) != InvalidIndex); } // find an entry index by its name - uint32 NodeMap::FindEntryIndexByName(const char* firstName) const + size_t NodeMap::FindEntryIndexByName(const char* firstName) const { - const uint32 numEntries = mEntries.size(); - for (uint32 i = 0; i < numEntries; ++i) + const auto foundEntry = AZStd::find_if(begin(mEntries), end(mEntries), [firstName](const MapEntry& entry) { - const AZStd::string& firstNameEntry = GetFirstName(i); - if (firstNameEntry == firstName) - { - return i; - } - } - - return MCORE_INVALIDINDEX32; + return MCore::GetStringIdPool().GetName(entry.mFirstNameID) == firstName; + }); + return foundEntry != end(mEntries) ? AZStd::distance(begin(mEntries), foundEntry) : InvalidIndex; } // find an entry index by its name ID - uint32 NodeMap::FindEntryIndexByNameID(uint32 firstNameID) const + size_t NodeMap::FindEntryIndexByNameID(size_t firstNameID) const { - const uint32 numEntries = mEntries.size(); - for (uint32 i = 0; i < numEntries; ++i) + const auto foundEntry = AZStd::find_if(begin(mEntries), end(mEntries), [firstNameID](const MapEntry& entry) { - if (mEntries[i].mFirstNameID == firstNameID) - { - return i; - } - } - - return MCORE_INVALIDINDEX32; + return entry.mFirstNameID == firstNameID; + }); + return foundEntry != end(mEntries) ? AZStd::distance(begin(mEntries), foundEntry) : InvalidIndex; } // find the second name for a given first name const char* NodeMap::FindSecondName(const char* firstName) const { - const uint32 entryIndex = FindEntryIndexByName(firstName); - if (entryIndex == MCORE_INVALIDINDEX32) + const size_t entryIndex = FindEntryIndexByName(firstName); + if (entryIndex == InvalidIndex) { return nullptr; } @@ -410,8 +399,8 @@ namespace EMotionFX // find the second name based on a first given name void NodeMap::FindSecondName(const char* firstName, AZStd::string* outString) { - const uint32 entryIndex = FindEntryIndexByName(firstName); - if (entryIndex == MCORE_INVALIDINDEX32) + const size_t entryIndex = FindEntryIndexByName(firstName); + if (entryIndex == InvalidIndex) { outString->clear(); return; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/NodeMap.h b/Gems/EMotionFX/Code/EMotionFX/Source/NodeMap.h index 6db38efc32..ae66a243bb 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/NodeMap.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/NodeMap.h @@ -39,41 +39,37 @@ namespace EMotionFX public: struct MapEntry { - uint32 mFirstNameID; /**< The first name ID, which is the primary key in the map. */ - uint32 mSecondNameID; /**< The second name ID. */ - - MapEntry() - : mFirstNameID(MCORE_INVALIDINDEX32) - , mSecondNameID(MCORE_INVALIDINDEX32) {} + size_t mFirstNameID = InvalidIndex; /**< The first name ID, which is the primary key in the map. */ + size_t mSecondNameID = InvalidIndex; /**< The second name ID. */ }; static NodeMap* Create(); // prealloc space in the map - void Reserve(uint32 numEntries); - void Resize(uint32 numEntries); + void Reserve(size_t numEntries); + void Resize(size_t numEntries); // get data size_t GetNumEntries() const; - const char* GetFirstName(uint32 entryIndex) const; - const char* GetSecondName(uint32 entryIndex) const; - const AZStd::string& GetFirstNameString(uint32 entryIndex) const; - const AZStd::string& GetSecondNameString(uint32 entryIndex) const; + const char* GetFirstName(size_t entryIndex) const; + const char* GetSecondName(size_t entryIndex) const; + const AZStd::string& GetFirstNameString(size_t entryIndex) const; + const AZStd::string& GetSecondNameString(size_t entryIndex) const; bool GetHasEntry(const char* firstName) const; - uint32 FindEntryIndexByName(const char* firstName) const; - uint32 FindEntryIndexByNameID(uint32 firstNameID) const; + size_t FindEntryIndexByName(const char* firstName) const; + size_t FindEntryIndexByNameID(size_t firstNameID) const; const char* FindSecondName(const char* firstName) const; void FindSecondName(const char* firstName, AZStd::string* outString); // set/modify - void SetFirstName(uint32 entryIndex, const char* name); - void SetSecondName(uint32 entryIndex, const char* name); - void SetEntry(uint32 entryIndex, const char* firstName, const char* secondName); + void SetFirstName(size_t entryIndex, const char* name); + void SetSecondName(size_t entryIndex, const char* name); + void SetEntry(size_t entryIndex, const char* firstName, const char* secondName); void AddEntry(const char* firstName, const char* secondName); void SetEntry(const char* firstName, const char* secondName, bool addIfNotExists); - void RemoveEntryByIndex(uint32 entryIndex); + void RemoveEntryByIndex(size_t entryIndex); void RemoveEntryByName(const char* firstName); - void RemoveEntryByNameID(uint32 firstNameID); + void RemoveEntryByNameID(size_t firstNameID); // filename void SetFileName(const char* fileName); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Pose.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Pose.cpp index 08581e919e..326e0e0448 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Pose.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Pose.cpp @@ -1334,7 +1334,7 @@ namespace EMotionFX } - void Pose::ResizeNumMorphs(uint32 numMorphTargets) + void Pose::ResizeNumMorphs(size_t numMorphTargets) { mMorphWeights.Resize(numMorphTargets); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Pose.h b/Gems/EMotionFX/Code/EMotionFX/Source/Pose.h index ef9653e728..be5f24f8e4 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Pose.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Pose.h @@ -100,24 +100,24 @@ namespace EMotionFX MCORE_INLINE const Transform* GetLocalSpaceTransforms() const { return mLocalSpaceTransforms.GetReadPtr(); } MCORE_INLINE const Transform* GetModelSpaceTransforms() const { return mModelSpaceTransforms.GetReadPtr(); } - MCORE_INLINE uint32 GetNumTransforms() const { return mLocalSpaceTransforms.GetLength(); } + MCORE_INLINE size_t GetNumTransforms() const { return mLocalSpaceTransforms.GetLength(); } MCORE_INLINE const ActorInstance* GetActorInstance() const { return mActorInstance; } MCORE_INLINE const Actor* GetActor() const { return mActor; } MCORE_INLINE const Skeleton* GetSkeleton() const { return mSkeleton; } - MCORE_INLINE Transform& GetLocalSpaceTransformDirect(uint32 nodeIndex) { return mLocalSpaceTransforms[nodeIndex]; } - MCORE_INLINE Transform& GetModelSpaceTransformDirect(uint32 nodeIndex) { return mModelSpaceTransforms[nodeIndex]; } - MCORE_INLINE const Transform& GetLocalSpaceTransformDirect(uint32 nodeIndex) const { return mLocalSpaceTransforms[nodeIndex]; } - MCORE_INLINE const Transform& GetModelSpaceTransformDirect(uint32 nodeIndex) const { return mModelSpaceTransforms[nodeIndex]; } - MCORE_INLINE void SetLocalSpaceTransformDirect(uint32 nodeIndex, const Transform& transform){ mLocalSpaceTransforms[nodeIndex] = transform; mFlags[nodeIndex] |= FLAG_LOCALTRANSFORMREADY; } - MCORE_INLINE void SetModelSpaceTransformDirect(uint32 nodeIndex, const Transform& transform){ mModelSpaceTransforms[nodeIndex] = transform; mFlags[nodeIndex] |= FLAG_MODELTRANSFORMREADY; } - MCORE_INLINE void InvalidateLocalSpaceTransform(uint32 nodeIndex) { mFlags[nodeIndex] &= ~FLAG_LOCALTRANSFORMREADY; } - MCORE_INLINE void InvalidateModelSpaceTransform(uint32 nodeIndex) { mFlags[nodeIndex] &= ~FLAG_MODELTRANSFORMREADY; } + MCORE_INLINE Transform& GetLocalSpaceTransformDirect(size_t nodeIndex) { return mLocalSpaceTransforms[nodeIndex]; } + MCORE_INLINE Transform& GetModelSpaceTransformDirect(size_t nodeIndex) { return mModelSpaceTransforms[nodeIndex]; } + MCORE_INLINE const Transform& GetLocalSpaceTransformDirect(size_t nodeIndex) const { return mLocalSpaceTransforms[nodeIndex]; } + MCORE_INLINE const Transform& GetModelSpaceTransformDirect(size_t nodeIndex) const { return mModelSpaceTransforms[nodeIndex]; } + MCORE_INLINE void SetLocalSpaceTransformDirect(size_t nodeIndex, const Transform& transform){ mLocalSpaceTransforms[nodeIndex] = transform; mFlags[nodeIndex] |= FLAG_LOCALTRANSFORMREADY; } + MCORE_INLINE void SetModelSpaceTransformDirect(size_t nodeIndex, const Transform& transform){ mModelSpaceTransforms[nodeIndex] = transform; mFlags[nodeIndex] |= FLAG_MODELTRANSFORMREADY; } + MCORE_INLINE void InvalidateLocalSpaceTransform(size_t nodeIndex) { mFlags[nodeIndex] &= ~FLAG_LOCALTRANSFORMREADY; } + MCORE_INLINE void InvalidateModelSpaceTransform(size_t nodeIndex) { mFlags[nodeIndex] &= ~FLAG_MODELTRANSFORMREADY; } - MCORE_INLINE void SetMorphWeight(uint32 index, float weight) { mMorphWeights[index] = weight; } - MCORE_INLINE float GetMorphWeight(uint32 index) const { return mMorphWeights[index]; } - MCORE_INLINE uint32 GetNumMorphWeights() const { return mMorphWeights.GetLength(); } - void ResizeNumMorphs(uint32 numMorphTargets); + MCORE_INLINE void SetMorphWeight(size_t index, float weight) { mMorphWeights[index] = weight; } + MCORE_INLINE float GetMorphWeight(size_t index) const { return mMorphWeights[index]; } + MCORE_INLINE size_t GetNumMorphWeights() const { return mMorphWeights.GetLength(); } + void ResizeNumMorphs(size_t numMorphTargets); /** * Blend this pose into a specified destination pose. @@ -168,8 +168,8 @@ namespace EMotionFX Pose& operator=(const Pose& other); - MCORE_INLINE uint8 GetFlags(uint32 nodeIndex) const { return mFlags[nodeIndex]; } - MCORE_INLINE void SetFlags(uint32 nodeIndex, uint8 flags) { mFlags[nodeIndex] = flags; } + MCORE_INLINE uint8 GetFlags(size_t nodeIndex) const { return mFlags[nodeIndex]; } + MCORE_INLINE void SetFlags(size_t nodeIndex, uint8 flags) { mFlags[nodeIndex] = flags; } bool HasPoseData(const AZ::TypeId& typeId) const; PoseData* GetPoseDataByType(const AZ::TypeId& typeId) const; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/SoftSkinDeformer.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/SoftSkinDeformer.cpp index c1a8bbd65c..a8fd925123 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/SoftSkinDeformer.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/SoftSkinDeformer.cpp @@ -202,7 +202,7 @@ namespace EMotionFX // initialize the mesh deformer - void SoftSkinDeformer::Reinitialize(Actor* actor, Node* node, uint32 lodLevel) + void SoftSkinDeformer::Reinitialize(Actor* actor, Node* node, size_t lodLevel) { MCORE_UNUSED(actor); MCORE_UNUSED(node); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/SoftSkinDeformer.h b/Gems/EMotionFX/Code/EMotionFX/Source/SoftSkinDeformer.h index 33596e6809..ab2d805ff1 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/SoftSkinDeformer.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/SoftSkinDeformer.h @@ -71,7 +71,7 @@ namespace EMotionFX * @param node The node where the mesh belongs to during this initialization. * @param lodLevel The LOD level of the mesh the mesh deformer works on. */ - void Reinitialize(Actor* actor, Node* node, uint32 lodLevel) override; + void Reinitialize(Actor* actor, Node* node, size_t lodLevel) override; /** * Creates an exact clone (copy) of this deformer, and returns a pointer to it. diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NodeHierarchyWidget.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NodeHierarchyWidget.cpp index 4aaebc3e3e..4dabd18e5c 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NodeHierarchyWidget.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NodeHierarchyWidget.cpp @@ -210,7 +210,7 @@ namespace EMStudio EMotionFX::Actor* actor = actorInstance->GetActor(); AZStd::string actorName; AzFramework::StringFunc::Path::GetFileName(actor->GetFileNameString().c_str(), actorName); - const uint32 numNodes = actor->GetNumNodes(); + const size_t numNodes = actor->GetNumNodes(); // extract the bones from the actor actor->ExtractBoneList(actorInstance->GetLODLevel(), &mBoneList); @@ -240,11 +240,11 @@ namespace EMStudio mHierarchy->addTopLevelItem(rootItem); // get the number of root nodes and iterate through them - const uint32 numRootNodes = actor->GetSkeleton()->GetNumRootNodes(); + const size_t numRootNodes = actor->GetSkeleton()->GetNumRootNodes(); for (uint32 i = 0; i < numRootNodes; ++i) { // get the root node index and the corresponding node - const uint32 rootNodeIndex = actor->GetSkeleton()->GetRootNodeIndex(i); + const size_t rootNodeIndex = actor->GetSkeleton()->GetRootNodeIndex(i); EMotionFX::Node* rootNode = actor->GetSkeleton()->GetNode(rootNodeIndex); // recursively add all the nodes to the hierarchy @@ -260,7 +260,7 @@ namespace EMStudio return false; } - const uint32 nodeIndex = node->GetNodeIndex(); + const size_t nodeIndex = node->GetNodeIndex(); AZStd::string nodeName = node->GetNameString(); AZStd::to_lower(nodeName.begin(), nodeName.end()); EMotionFX::Mesh* mesh = actorInstance->GetActor()->GetMesh(actorInstance->GetLODLevel(), nodeIndex); @@ -288,10 +288,10 @@ namespace EMStudio void NodeHierarchyWidget::RecursivelyAddChilds(QTreeWidgetItem* parent, EMotionFX::Actor* actor, EMotionFX::ActorInstance* actorInstance, EMotionFX::Node* node) { - const uint32 nodeIndex = node->GetNodeIndex(); + const size_t nodeIndex = node->GetNodeIndex(); AZStd::string nodeName = node->GetNameString(); AZStd::to_lower(nodeName.begin(), nodeName.end()); - const uint32 numChildren = node->GetNumChildNodes(); + const size_t numChildren = node->GetNumChildNodes(); EMotionFX::Mesh* mesh = actor->GetMesh(actorInstance->GetLODLevel(), nodeIndex); const bool isMeshNode = (mesh); const bool isBone = (AZStd::find(begin(mBoneList), end(mBoneList), nodeIndex) != end(mBoneList)); @@ -352,7 +352,7 @@ namespace EMStudio for (uint32 i = 0; i < numChildren; ++i) { // get the node index and the corresponding node - const uint32 childIndex = node->GetChildIndex(i); + const size_t childIndex = node->GetChildIndex(i); EMotionFX::Node* child = actor->GetSkeleton()->GetNode(childIndex); // recursively add all the nodes to the hierarchy @@ -365,7 +365,7 @@ namespace EMStudio for (uint32 i = 0; i < numChildren; ++i) { // get the node index and the corresponding node - const uint32 childIndex = node->GetChildIndex(i); + const size_t childIndex = node->GetChildIndex(i); EMotionFX::Node* child = actor->GetSkeleton()->GetNode(childIndex); // recursively add all the nodes to the hierarchy diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NodeHierarchyWidget.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NodeHierarchyWidget.h index b55062f57b..e4dd215819 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NodeHierarchyWidget.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NodeHierarchyWidget.h @@ -133,7 +133,7 @@ namespace EMStudio QIcon* mNodeIcon; QIcon* mMeshIcon; QIcon* mCharacterIcon; - AZStd::vector mBoneList; + AZStd::vector mBoneList; AZStd::vector mActorInstanceIDs; AZStd::string mItemName; AZStd::string mActorInstanceIDString; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.h index 27e5504e72..f55604b38c 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.h @@ -53,7 +53,7 @@ namespace EMStudio MCORE_MEMORYOBJECTCATEGORY(RenderPlugin::EMStudioRenderActor, MCore::MCORE_DEFAULT_ALIGNMENT, MEMCATEGORY_EMSTUDIOSDK_RENDERPLUGINBASE); EMotionFX::Actor* mActor; - AZStd::vector mBoneList; + AZStd::vector mBoneList; RenderGL::GLActor* mRenderActor; AZStd::vector mActorInstances; float mNormalsScaleMultiplier; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/MeshInfo.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/MeshInfo.cpp index 88e6a64964..49b1d1b8f3 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/MeshInfo.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/MeshInfo.cpp @@ -33,7 +33,7 @@ namespace EMStudio if (m_orgVerticesCount) { - m_vertexDupeRatio = mesh->GetNumVertices() / (float)mesh->GetNumOrgVertices(); + m_vertexDupeRatio = (float)mesh->GetNumVertices() / (float)mesh->GetNumOrgVertices(); } else { @@ -44,15 +44,15 @@ namespace EMStudio mesh->CalcMaxNumInfluences(m_verticesByInfluences); // sub meshes - const uint32 numSubMeshes = mesh->GetNumSubMeshes(); - for (uint32 i = 0; i < numSubMeshes; ++i) + const size_t numSubMeshes = mesh->GetNumSubMeshes(); + for (size_t i = 0; i < numSubMeshes; ++i) { EMotionFX::SubMesh* subMesh = mesh->GetSubMesh(i); m_submeshes.emplace_back(actor, lodLevel, subMesh); } // vertex attribute layers - const uint32 numVertexAttributeLayers = mesh->GetNumVertexAttributeLayers(); + const size_t numVertexAttributeLayers = mesh->GetNumVertexAttributeLayers(); AZStd::string tmpString; for (uint32 i = 0; i < numVertexAttributeLayers; ++i) { @@ -89,7 +89,7 @@ namespace EMStudio tmpString = AZStd::string::format("Unknown data (TypeID=%d)", attributeLayerType); } - if (attributeLayer->GetNameString().size() > 0) + if (!attributeLayer->GetNameString().empty()) { tmpString += AZStd::string::format(" [%s]", attributeLayer->GetName()); } @@ -99,8 +99,8 @@ namespace EMStudio // shared vertex attribute layers - const uint32 numSharedVertexAttributeLayers = mesh->GetNumSharedVertexAttributeLayers(); - for (uint32 i = 0; i < numSharedVertexAttributeLayers; ++i) + const size_t numSharedVertexAttributeLayers = mesh->GetNumSharedVertexAttributeLayers(); + for (size_t i = 0; i < numSharedVertexAttributeLayers; ++i) { EMotionFX::VertexAttributeLayer* attributeLayer = mesh->GetSharedVertexAttributeLayer(i); @@ -114,7 +114,7 @@ namespace EMStudio tmpString = AZStd::string::format("Unknown data (TypeID=%d)", attributeLayerType); } - if (attributeLayer->GetNameString().size() > 0) + if (!attributeLayer->GetNameString().empty()) { tmpString += AZStd::string::format(" [%s]", attributeLayer->GetName()); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/MeshInfo.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/MeshInfo.h index b8e9d0fc61..28215e59c9 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/MeshInfo.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/MeshInfo.h @@ -44,7 +44,7 @@ namespace EMStudio bool m_isQuadMesh; unsigned int m_orgVerticesCount; float m_vertexDupeRatio; - AZStd::vector m_verticesByInfluences; + AZStd::vector m_verticesByInfluences; AZStd::vector m_submeshes; AZStd::vector m_attributeLayers; AZStd::vector m_sharedAttributeLayers; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/NodeWindowPlugin.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/NodeWindowPlugin.cpp index 3d7e44dac3..7b47b8cb43 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/NodeWindowPlugin.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/NodeWindowPlugin.cpp @@ -286,18 +286,18 @@ namespace EMStudio // get access to the actor and the number of nodes EMotionFX::Actor* actor = actorInstance->GetActor(); - const uint32 numNodes = actor->GetNumNodes(); + const size_t numNodes = actor->GetNumNodes(); // reserve memory for the visible node indices m_visibleNodeIndices.reserve(numNodes); // extract the bones from the actor - AZStd::vector boneList; + AZStd::vector boneList; actor->ExtractBoneList(actorInstance->GetLODLevel(), &boneList); // iterate through all nodes and check if the node is visible AZStd::string nodeName; - for (uint32 i = 0; i < numNodes; ++i) + for (size_t i = 0; i < numNodes; ++i) { EMotionFX::Node* node = actor->GetSkeleton()->GetNode(i); @@ -305,7 +305,7 @@ namespace EMStudio nodeName = node->GetNameString(); AZStd::to_lower(nodeName.begin(), nodeName.end()); - const uint32 nodeIndex = node->GetNodeIndex(); + const size_t nodeIndex = node->GetNodeIndex(); EMotionFX::Mesh* mesh = actor->GetMesh(actorInstance->GetLODLevel(), nodeIndex); const bool isMeshNode = (mesh); const bool isBone = (AZStd::find(begin(boneList), end(boneList), nodeIndex) != end(boneList)); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/SubMeshInfo.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/SubMeshInfo.cpp index 151254715e..d8a9926c33 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/SubMeshInfo.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/SubMeshInfo.cpp @@ -19,7 +19,7 @@ namespace EMStudio { AZ_CLASS_ALLOCATOR_IMPL(SubMeshInfo, EMStudio::UIAllocator, 0) - SubMeshInfo::SubMeshInfo(EMotionFX::Actor* actor, unsigned int lodLevel, EMotionFX::SubMesh* subMesh) + SubMeshInfo::SubMeshInfo(EMotionFX::Actor* actor, size_t lodLevel, EMotionFX::SubMesh* subMesh) { // In EMFX studio, we are not using the subMesh index - they all uses the default material. m_materialName = actor->GetMaterial(lodLevel, 0)->GetNameString(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/SubMeshInfo.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/SubMeshInfo.h index 3a6340d48c..bb5d5eda15 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/SubMeshInfo.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/SubMeshInfo.h @@ -26,7 +26,7 @@ namespace EMStudio AZ_CLASS_ALLOCATOR_DECL SubMeshInfo() {} - SubMeshInfo(EMotionFX::Actor* actor, unsigned int lodLevel, EMotionFX::SubMesh* subMesh); + SubMeshInfo(EMotionFX::Actor* actor, size_t lodLevel, EMotionFX::SubMesh* subMesh); ~SubMeshInfo() = default; static void Reflect(AZ::ReflectContext* context); @@ -36,7 +36,7 @@ namespace EMStudio unsigned int m_verticesCount; unsigned int m_indicesCount; unsigned int m_polygonsCount; - unsigned int m_bonesCount; + size_t m_bonesCount; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/MirrorSetupWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/MirrorSetupWindow.cpp index 271f277ed1..fc01f68efe 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/MirrorSetupWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/MirrorSetupWindow.cpp @@ -329,7 +329,7 @@ namespace EMStudio MCORE_ASSERT(node); // remove the mapping for this node - PerformMapping(node->GetNodeIndex(), MCORE_INVALIDINDEX32); + PerformMapping(node->GetNodeIndex(), InvalidIndex); } @@ -443,10 +443,7 @@ namespace EMStudio { const size_t numNodes = aznumeric_caster(currentActor->GetNumNodes()); mMap.resize(numNodes); - for (uint32 i = 0; i < numNodes; ++i) - { - mMap[i] = MCORE_INVALIDINDEX32; - } + AZStd::fill(mMap.begin(), mMap.end(), InvalidIndex); } } @@ -490,11 +487,11 @@ namespace EMStudio // fill the left list widget QString currentName; - const uint32 numNodes = actor->GetNumNodes(); + const size_t numNodes = actor->GetNumNodes(); // count the number of rows - uint32 numRows = 0; - for (uint32 i = 0; i < numNodes; ++i) + int numRows = 0; + for (size_t i = 0; i < numNodes; ++i) { currentName = actor->GetSkeleton()->GetNode(i)->GetName(); if (currentName.contains(filterString, Qt::CaseInsensitive) || filterString.isEmpty()) @@ -505,15 +502,15 @@ namespace EMStudio mCurrentList->setRowCount(numRows); // fill the rows - uint32 rowIndex = 0; - for (uint32 i = 0; i < numNodes; ++i) + int rowIndex = 0; + for (size_t i = 0; i < numNodes; ++i) { EMotionFX::Node* node = actor->GetSkeleton()->GetNode(i); currentName = node->GetName(); if (currentName.contains(filterString, Qt::CaseInsensitive) || filterString.isEmpty()) { // mark if there is a mapping or not - const bool mapped = (mMap[node->GetNodeIndex()] != MCORE_INVALIDINDEX32); + const bool mapped = (mMap[node->GetNodeIndex()] != InvalidIndex); QTableWidgetItem* mappedItem = new QTableWidgetItem(); mappedItem->setIcon(mapped ? *mMappedIcon : QIcon()); mCurrentList->setItem(rowIndex, 0, mappedItem); @@ -524,8 +521,7 @@ namespace EMStudio { typeItem->setIcon(*mMeshIcon); } - else - if (AZStd::find(begin(mCurrentBoneList), end(mCurrentBoneList), node->GetNodeIndex()) != end(mCurrentBoneList)) + else if (AZStd::find(begin(mCurrentBoneList), end(mCurrentBoneList), node->GetNodeIndex()) != end(mCurrentBoneList)) { typeItem->setIcon(*mBoneIcon); } @@ -559,11 +555,11 @@ namespace EMStudio // fill the left list widget QString name; - const uint32 numNodes = actor->GetNumNodes(); + const size_t numNodes = actor->GetNumNodes(); // count the number of rows - uint32 numRows = 0; - for (uint32 i = 0; i < numNodes; ++i) + int numRows = 0; + for (size_t i = 0; i < numNodes; ++i) { name = actor->GetSkeleton()->GetNode(i)->GetName(); if (name.contains(filterString, Qt::CaseInsensitive) || filterString.isEmpty()) @@ -574,8 +570,8 @@ namespace EMStudio mSourceList->setRowCount(numRows); // fill the rows - uint32 rowIndex = 0; - for (uint32 i = 0; i < numNodes; ++i) + int rowIndex = 0; + for (size_t i = 0; i < numNodes; ++i) { EMotionFX::Node* node = actor->GetSkeleton()->GetNode(i); name = node->GetName(); @@ -593,8 +589,7 @@ namespace EMStudio { typeItem->setIcon(*mMeshIcon); } - else - if (AZStd::find(mSourceBoneList.begin(), mSourceBoneList.end(), node->GetNodeIndex()) != mSourceBoneList.end()) + else if (AZStd::find(mSourceBoneList.begin(), mSourceBoneList.end(), node->GetNodeIndex()) != mSourceBoneList.end()) { typeItem->setIcon(*mBoneIcon); } @@ -629,9 +624,9 @@ namespace EMStudio // fill the table QString currentName; QString sourceName; - const uint32 numNodes = currentActor->GetNumNodes(); + const int numNodes = aznumeric_caster(currentActor->GetNumNodes()); mMappingTable->setRowCount(numNodes); - for (uint32 i = 0; i < numNodes; ++i) + for (int i = 0; i < numNodes; ++i) { currentName = currentActor->GetSkeleton()->GetNode(i)->GetName(); @@ -639,7 +634,7 @@ namespace EMStudio mMappingTable->setItem(i, 0, currentTableItem); mMappingTable->setRowHeight(i, 21); - if (mMap[i] != MCORE_INVALIDINDEX32) + if (mMap[i] != InvalidIndex) { sourceName = sourceActor->GetSkeleton()->GetNode(mMap[i])->GetName(); currentTableItem = new QTableWidgetItem(sourceName); @@ -650,8 +645,6 @@ namespace EMStudio mMappingTable->setItem(i, 1, new QTableWidgetItem()); } } - //mMappingTable->resizeColumnsToContents(); - //mMappingTable->setColumnWidth(0, mMappingTable->columnWidth(0) + 25); } @@ -694,12 +687,12 @@ namespace EMStudio // perform the mapping - void MirrorSetupWindow::PerformMapping(uint32 currentNodeIndex, uint32 sourceNodeIndex) + void MirrorSetupWindow::PerformMapping(size_t currentNodeIndex, size_t sourceNodeIndex) { EMotionFX::Actor* currentActor = GetSelectedActor(); // update the map - const uint32 oldSourceIndex = mMap[currentNodeIndex]; + const size_t oldSourceIndex = mMap[currentNodeIndex]; mMap[currentNodeIndex] = sourceNodeIndex; // update the current table @@ -707,9 +700,7 @@ namespace EMStudio const QList currentListItems = mCurrentList->findItems(curName, Qt::MatchExactly); for (int32 i = 0; i < currentListItems.count(); ++i) { - const uint32 rowIndex = currentListItems[i]->row(); - //if (rowIndex != mCurrentList->currentRow()) - // continue; + const int rowIndex = currentListItems[i]->row(); QTableWidgetItem* mappedItem = mCurrentList->item(rowIndex, 0); if (!mappedItem) @@ -718,7 +709,7 @@ namespace EMStudio mCurrentList->setItem(rowIndex, 0, mappedItem); } - if (sourceNodeIndex == MCORE_INVALIDINDEX32) + if (sourceNodeIndex == InvalidIndex) { mappedItem->setIcon(QIcon()); } @@ -729,16 +720,14 @@ namespace EMStudio } // update source table - if (sourceNodeIndex != MCORE_INVALIDINDEX32) + if (sourceNodeIndex != InvalidIndex) { const bool stillUsed = AZStd::find(mMap.begin(), mMap.end(), sourceNodeIndex) != mMap.end(); const QString sourceName = currentActor->GetSkeleton()->GetNode(sourceNodeIndex)->GetName(); const QList sourceListItems = mSourceList->findItems(sourceName, Qt::MatchExactly); for (int32 i = 0; i < sourceListItems.count(); ++i) { - const uint32 rowIndex = sourceListItems[i]->row(); - //if (rowIndex != mSourceList->currentRow()) - // continue; + const int rowIndex = sourceListItems[i]->row(); QTableWidgetItem* mappedItem = mSourceList->item(rowIndex, 0); if (!mappedItem) @@ -759,16 +748,14 @@ namespace EMStudio } else // we're clearing it { - if (oldSourceIndex != MCORE_INVALIDINDEX32) + if (oldSourceIndex != InvalidIndex) { const bool stillUsed = AZStd::find(mMap.begin(), mMap.end(), sourceNodeIndex) != mMap.end(); const QString sourceName = currentActor->GetSkeleton()->GetNode(oldSourceIndex)->GetName(); const QList sourceListItems = mSourceList->findItems(sourceName, Qt::MatchExactly); for (int32 i = 0; i < sourceListItems.count(); ++i) { - const uint32 rowIndex = sourceListItems[i]->row(); - //if (rowIndex != mSourceList->currentRow()) - // continue; + const int rowIndex = sourceListItems[i]->row(); QTableWidgetItem* mappedItem = mSourceList->item(rowIndex, 0); if (!mappedItem) @@ -790,14 +777,14 @@ namespace EMStudio } // update the mapping table - QTableWidgetItem* item = mMappingTable->item(currentNodeIndex, 1); - if (!item && sourceNodeIndex != MCORE_INVALIDINDEX32) + QTableWidgetItem* item = mMappingTable->item(aznumeric_caster(currentNodeIndex), 1); + if (!item && sourceNodeIndex != InvalidIndex) { item = new QTableWidgetItem(); - mMappingTable->setItem(currentNodeIndex, 1, item); + mMappingTable->setItem(aznumeric_caster(currentNodeIndex), 1, item); } - if (sourceNodeIndex == MCORE_INVALIDINDEX32) + if (sourceNodeIndex == InvalidIndex) { if (item) { @@ -893,15 +880,12 @@ namespace EMStudio } // now update our mapping data - const uint32 numNodes = currentActor->GetNumNodes(); - for (uint32 i = 0; i < numNodes; ++i) - { - mMap[i] = MCORE_INVALIDINDEX32; - } + const size_t numNodes = currentActor->GetNumNodes(); + AZStd::fill(mMap.begin(), AZStd::next(mMap.begin(), numNodes), InvalidIndex); // now apply the map we loaded to the data we have here - const uint32 numEntries = nodeMap->GetNumEntries(); - for (uint32 i = 0; i < numEntries; ++i) + const size_t numEntries = nodeMap->GetNumEntries(); + for (size_t i = 0; i < numEntries; ++i) { // find the current node EMotionFX::Node* currentNode = currentActor->GetSkeleton()->FindNodeByName(nodeMap->GetFirstName(i)); @@ -963,12 +947,12 @@ namespace EMStudio // create an emfx node map object EMotionFX::NodeMap* map = EMotionFX::NodeMap::Create(); - const uint32 numNodes = currentActor->GetNumNodes(); + const size_t numNodes = currentActor->GetNumNodes(); map->Reserve(numNodes); - for (uint32 i = 0; i < numNodes; ++i) + for (size_t i = 0; i < numNodes; ++i) { // skip unmapped entries - if (mMap[i] == MCORE_INVALIDINDEX32) + if (mMap[i] == InvalidIndex) { continue; } @@ -1033,16 +1017,11 @@ namespace EMStudio return true; } - const uint32 numNodes = currentActor->GetNumNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = currentActor->GetNumNodes(); + return AZStd::all_of(mMap.begin(), AZStd::next(mMap.begin(), numNodes), [](const size_t nodeIndex) { - if (mMap[i] != MCORE_INVALIDINDEX32) - { - return false; - } - } - - return true; + return nodeIndex != InvalidIndex; + }); } @@ -1081,20 +1060,13 @@ namespace EMStudio return; } - // show a warning that we will overwrite the table entries - //if (QMessageBox::warning(this, "Overwrite Mapping?", "Are you sure you want to possibly overwrite items in the mapping?\nAll or some existing mapping information might be lost.", QMessageBox::Cancel|QMessageBox::Yes) != QMessageBox::Yes) - //return; - - // - // currentActor->MatchNodeMotionSources( FromQtString(mLeftEdit->text()), FromQtString(mRightEdit->text()) ); - // update the table and map uint32 numGuessed = 0; - const uint32 numNodes = currentActor->GetNumNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = currentActor->GetNumNodes(); + for (size_t i = 0; i < numNodes; ++i) { // skip already setup mappings - if (mMap[i] != MCORE_INVALIDINDEX32) + if (mMap[i] != InvalidIndex) { continue; } @@ -1110,28 +1082,6 @@ namespace EMStudio // update the actor UpdateActorMotionSources(); - /* - // try a geometrical mapping - EMotionFX::Pose pose; - pose.InitFromLocalBindSpaceTransforms( currentActor ); - - // for all nodes in the current actor - uint32 numGuessed = 0; - const uint32 numNodes = currentActor->GetNumNodes(); - for (uint32 i=0; iFindBestMirrorMatchForNode( static_cast(i), pose ); - if (matchIndex != MCORE_INVALIDINDEX16) - { - mMap[i] = matchIndex; - numGuessed++; - } - } - */ Reinit(false); // show some results @@ -1148,17 +1098,7 @@ namespace EMStudio { return; } - /* - const uint32 numNodes = currentActor->GetNumNodes(); - for (uint32 i=0; i( mMap[i] ); - } - */ // apply the current map as command ApplyCurrentMapAsCommand(); } @@ -1172,8 +1112,8 @@ namespace EMStudio return; } - const uint32 numNodes = actor->GetNumNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = actor->GetNumNodes(); + for (size_t i = 0; i < numNodes; ++i) { if (actor->GetHasMirrorInfo()) { @@ -1184,12 +1124,12 @@ namespace EMStudio } else { - mMap[i] = MCORE_INVALIDINDEX32; + mMap[i] = InvalidIndex; } } else { - mMap[i] = MCORE_INVALIDINDEX32; + mMap[i] = InvalidIndex; } } } @@ -1207,10 +1147,10 @@ namespace EMStudio // apply mirror changes AZStd::string commandString = AZStd::string::format("AdjustActor -actorID %d -mirrorSetup \"", currentActor->GetID()); - for (uint32 i = 0; i < currentActor->GetNumNodes(); ++i) + for (size_t i = 0; i < currentActor->GetNumNodes(); ++i) { - uint32 sourceNode = mMap[i]; - if (sourceNode != MCORE_INVALIDINDEX32 && sourceNode != i) + size_t sourceNode = mMap[i]; + if (sourceNode != InvalidIndex && sourceNode != i) { commandString += currentActor->GetSkeleton()->GetNode(i)->GetName(); commandString += ","; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/MirrorSetupWindow.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/MirrorSetupWindow.h index 13bb98334c..660359ba4a 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/MirrorSetupWindow.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/MirrorSetupWindow.h @@ -79,14 +79,14 @@ namespace EMStudio QIcon* mNodeIcon; QIcon* mMeshIcon; QIcon* mMappedIcon; - AZStd::vector mCurrentBoneList; - AZStd::vector mSourceBoneList; - AZStd::vector mMap; + AZStd::vector mCurrentBoneList; + AZStd::vector mSourceBoneList; + AZStd::vector mMap; void FillCurrentListWidget(EMotionFX::Actor* actor, const QString& filterString); void FillSourceListWidget(EMotionFX::Actor* actor, const QString& filterString); void FillMappingTable(EMotionFX::Actor* currentActor, EMotionFX::Actor* sourceActor); - void PerformMapping(uint32 currentNodeIndex, uint32 sourceNodeIndex); + void PerformMapping(size_t currentNodeIndex, size_t sourceNodeIndex); void RemoveCurrentSelectedMapping(); void keyPressEvent(QKeyEvent* event); void keyReleaseEvent(QKeyEvent* event); diff --git a/Gems/EMotionFX/Code/Source/Editor/SkeletonModel.cpp b/Gems/EMotionFX/Code/Source/Editor/SkeletonModel.cpp index 8530521458..95e08eab77 100644 --- a/Gems/EMotionFX/Code/Source/Editor/SkeletonModel.cpp +++ b/Gems/EMotionFX/Code/Source/Editor/SkeletonModel.cpp @@ -615,31 +615,31 @@ namespace EMotionFX return; } - const AZ::u32 numLodLevels = actor->GetNumLODLevels(); + const size_t numLodLevels = actor->GetNumLODLevels(); const Skeleton* skeleton = actor->GetSkeleton(); - const AZ::u32 numNodes = skeleton->GetNumNodes(); + const size_t numNodes = skeleton->GetNumNodes(); m_nodeInfos.resize(numNodes); - AZStd::vector > boneListPerLodLevel; + AZStd::vector > boneListPerLodLevel; boneListPerLodLevel.resize(numLodLevels); - for (AZ::u32 lodLevel = 0; lodLevel < numLodLevels; ++lodLevel) + for (size_t lodLevel = 0; lodLevel < numLodLevels; ++lodLevel) { actor->ExtractBoneList(lodLevel, &boneListPerLodLevel[lodLevel]); } - for (AZ::u32 nodeIndex = 0; nodeIndex < numNodes; ++nodeIndex) + for (size_t nodeIndex = 0; nodeIndex < numNodes; ++nodeIndex) { NodeInfo& nodeInfo = m_nodeInfos[nodeIndex]; // Is bone? - nodeInfo.m_isBone = AZStd::any_of(begin(boneListPerLodLevel), end(boneListPerLodLevel), [nodeIndex](const AZStd::vector& lodLevel) + nodeInfo.m_isBone = AZStd::any_of(begin(boneListPerLodLevel), end(boneListPerLodLevel), [nodeIndex](const AZStd::vector& lodLevel) { return AZStd::find(begin(lodLevel), end(lodLevel), nodeIndex) != end(lodLevel); }); // Has mesh? nodeInfo.m_hasMesh = false; - for (AZ::u32 lodLevel = 0; lodLevel < numLodLevels; ++lodLevel) + for (size_t lodLevel = 0; lodLevel < numLodLevels; ++lodLevel) { if (actor->GetMesh(lodLevel, nodeIndex)) { From 7a8f96873816fcd9cf7c42b22ea38bb12150f254 Mon Sep 17 00:00:00 2001 From: Chris Burel Date: Mon, 24 May 2021 12:04:13 -0700 Subject: [PATCH 203/803] Convert Pose uint32 -> size_t Signed-off-by: Chris Burel --- .../EMotionFX/Source/MorphSetupInstance.cpp | 22 +- .../EMotionFX/Source/MorphSetupInstance.h | 8 +- Gems/EMotionFX/Code/EMotionFX/Source/Pose.cpp | 317 ++++++++---------- Gems/EMotionFX/Code/EMotionFX/Source/Pose.h | 2 +- 4 files changed, 156 insertions(+), 193 deletions(-) diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MorphSetupInstance.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MorphSetupInstance.cpp index 456056d00f..df4aaa0e7c 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MorphSetupInstance.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MorphSetupInstance.cpp @@ -61,7 +61,7 @@ namespace EMotionFX } // allocate the number of morph targets - const uint32 numMorphTargets = morphSetup->GetNumMorphTargets(); + const size_t numMorphTargets = morphSetup->GetNumMorphTargets(); mMorphTargets.resize(numMorphTargets); // update the ID values @@ -73,27 +73,21 @@ namespace EMotionFX // try to locate the morph target by ID - uint32 MorphSetupInstance::FindMorphTargetIndexByID(uint32 id) const + size_t MorphSetupInstance::FindMorphTargetIndexByID(uint32 id) const { // try to locate the morph target with the given ID - const uint32 numTargets = mMorphTargets.size(); - for (uint32 i = 0; i < numTargets; ++i) + const auto foundElement = AZStd::find_if(mMorphTargets.begin(), mMorphTargets.end(), [id](const MorphTarget& morphTarget) { - if (mMorphTargets[i].GetID() == id) - { - return i; - } - } - - // there is no such morph target with the given ID - return MCORE_INVALIDINDEX32; + return morphTarget.GetID() == id; + }); + return foundElement != mMorphTargets.end() ? AZStd::distance(mMorphTargets.begin(), foundElement) : InvalidIndex; } MorphSetupInstance::MorphTarget* MorphSetupInstance::FindMorphTargetByID(uint32 id) { - const uint32 index = FindMorphTargetIndexByID(id); - if (index != MCORE_INVALIDINDEX32) + const size_t index = FindMorphTargetIndexByID(id); + if (index != InvalidIndex) { return &mMorphTargets[index]; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MorphSetupInstance.h b/Gems/EMotionFX/Code/EMotionFX/Source/MorphSetupInstance.h index e597cb7a63..e93ed7cf6d 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MorphSetupInstance.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MorphSetupInstance.h @@ -130,16 +130,16 @@ namespace EMotionFX * @param nr The morph target number, which must be in range of [0..GetNumMorphTargets()-1]. * @result A pointer to the morph target inside this class. */ - MCORE_INLINE MorphTarget* GetMorphTarget(uint32 nr) { return &mMorphTargets[nr]; } + MCORE_INLINE MorphTarget* GetMorphTarget(size_t nr) { return &mMorphTargets[nr]; } - MCORE_INLINE const MorphTarget* GetMorphTarget(uint32 nr) const { return &mMorphTargets[nr]; } + MCORE_INLINE const MorphTarget* GetMorphTarget(size_t nr) const { return &mMorphTargets[nr]; } /** * Find a given morph target number by its ID. * @param id The ID value to search for. - * @result Returns the morph target number in range of [0..GetNumMorphTargets()-1], or MCORE_INVALIDINDEX32 when not found. + * @result Returns the morph target number in range of [0..GetNumMorphTargets()-1], or InvalidIndex when not found. */ - uint32 FindMorphTargetIndexByID(uint32 id) const; + size_t FindMorphTargetIndexByID(uint32 id) const; /** * Find the morph target by its ID. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Pose.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Pose.cpp index 326e0e0448..096b32b041 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Pose.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Pose.cpp @@ -60,7 +60,7 @@ namespace EMotionFX mSkeleton = mActor->GetSkeleton(); // resize the buffers - const uint32 numTransforms = mActor->GetSkeleton()->GetNumNodes(); + const size_t numTransforms = mActor->GetSkeleton()->GetNumNodes(); mLocalSpaceTransforms.ResizeFast(numTransforms); mModelSpaceTransforms.ResizeFast(numTransforms); mFlags.ResizeFast(numTransforms); @@ -84,15 +84,15 @@ namespace EMotionFX mSkeleton = actor->GetSkeleton(); // resize the buffers - const uint32 numTransforms = mActor->GetSkeleton()->GetNumNodes(); + const size_t numTransforms = mActor->GetSkeleton()->GetNumNodes(); mLocalSpaceTransforms.ResizeFast(numTransforms); mModelSpaceTransforms.ResizeFast(numTransforms); - const uint32 oldSize = mFlags.GetLength(); + const size_t oldSize = mFlags.GetLength(); mFlags.ResizeFast(numTransforms); if (oldSize < numTransforms && clearAllFlags == false) { - for (uint32 i = oldSize; i < numTransforms; ++i) + for (size_t i = oldSize; i < numTransforms; ++i) { mFlags[i] = initialFlags; } @@ -189,35 +189,15 @@ namespace EMotionFX } - /* - // initialize this pose from some given set of local space transformations - void Pose::InitFromLocalBindSpaceTransforms(Actor* actor) - { - // link to an actor - LinkToActor(actor); - - // reset all flags - MCore::MemSet( (uint8*)mFlags.GetPtr(), FLAG_LOCALTRANSFORMREADY, sizeof(uint8)*mFlags.GetLength() ); - - // copy over the local transforms - MCore::MemCopy((uint8*)mLocalTransforms.GetPtr(), (uint8*)actor->GetBindPose().GetLocalTransforms(), sizeof(Transform)*mLocalTransforms.GetLength()); - - // reset the morph targets - const uint32 numMorphWeights = mMorphWeights.GetLength(); - for (uint32 i=0; iGetSkeleton(); - const uint32 numNodes = skeleton->GetNumNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = skeleton->GetNumNodes(); + for (size_t i = 0; i < numNodes; ++i) { - const uint32 parentIndex = skeleton->GetNode(i)->GetParentIndex(); - if (parentIndex != MCORE_INVALIDINDEX32) + const size_t parentIndex = skeleton->GetNode(i)->GetParentIndex(); + if (parentIndex != InvalidIndex) { GetModelSpaceTransform(parentIndex, &mLocalSpaceTransforms[i]); mLocalSpaceTransforms[i].Inverse(); @@ -238,11 +218,11 @@ namespace EMotionFX { // iterate from root towards child nodes recursively, updating all model space transforms on the way Skeleton* skeleton = mActor->GetSkeleton(); - const uint32 numNodes = skeleton->GetNumNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = skeleton->GetNumNodes(); + for (size_t i = 0; i < numNodes; ++i) { - const uint32 parentIndex = skeleton->GetNode(i)->GetParentIndex(); - if (parentIndex != MCORE_INVALIDINDEX32) + const size_t parentIndex = skeleton->GetNode(i)->GetParentIndex(); + if (parentIndex != InvalidIndex) { mModelSpaceTransforms[parentIndex].PreMultiply(mLocalSpaceTransforms[i], &mModelSpaceTransforms[i]); } @@ -261,8 +241,8 @@ namespace EMotionFX { Skeleton* skeleton = mActor->GetSkeleton(); - const uint32 parentIndex = skeleton->GetNode(nodeIndex)->GetParentIndex(); - if (parentIndex != MCORE_INVALIDINDEX32 && !(mFlags[parentIndex] & FLAG_MODELTRANSFORMREADY)) + const size_t parentIndex = skeleton->GetNode(nodeIndex)->GetParentIndex(); + if (parentIndex != InvalidIndex && !(mFlags[parentIndex] & FLAG_MODELTRANSFORMREADY)) { UpdateModelSpaceTransform(parentIndex); } @@ -271,7 +251,7 @@ namespace EMotionFX if ((mFlags[nodeIndex] & FLAG_MODELTRANSFORMREADY) == false) { const Transform& localTransform = GetLocalSpaceTransform(nodeIndex); - if (parentIndex != MCORE_INVALIDINDEX32) + if (parentIndex != InvalidIndex) { mModelSpaceTransforms[parentIndex].PreMultiply(localTransform, &mModelSpaceTransforms[nodeIndex]); } @@ -288,19 +268,17 @@ namespace EMotionFX // update the local transform void Pose::UpdateLocalSpaceTransform(size_t nodeIndex) const { - const uint32 flags = mFlags[nodeIndex]; + const uint8 flags = mFlags[nodeIndex]; if (flags & FLAG_LOCALTRANSFORMREADY) { return; } MCORE_ASSERT(flags & FLAG_MODELTRANSFORMREADY); // the model space transform has to be updated already, otherwise we cannot possibly calculate the local space one - //if ((flags & FLAG_GLOBALTRANSFORMREADY) == false) - // DebugBreak(); Skeleton* skeleton = mActor->GetSkeleton(); - const uint32 parentIndex = skeleton->GetNode(nodeIndex)->GetParentIndex(); - if (parentIndex != MCORE_INVALIDINDEX32) + const size_t parentIndex = skeleton->GetNode(nodeIndex)->GetParentIndex(); + if (parentIndex != InvalidIndex) { GetModelSpaceTransform(parentIndex, &mLocalSpaceTransforms[nodeIndex]); mLocalSpaceTransforms[nodeIndex].Inverse(); @@ -441,8 +419,8 @@ namespace EMotionFX // invalidate all local transforms void Pose::InvalidateAllLocalSpaceTransforms() { - const uint32 numFlags = mFlags.GetLength(); - for (uint32 i = 0; i < numFlags; ++i) + const size_t numFlags = mFlags.GetLength(); + for (size_t i = 0; i < numFlags; ++i) { mFlags[i] &= ~FLAG_LOCALTRANSFORMREADY; } @@ -451,8 +429,8 @@ namespace EMotionFX void Pose::InvalidateAllModelSpaceTransforms() { - const uint32 numFlags = mFlags.GetLength(); - for (uint32 i = 0; i < numFlags; ++i) + const size_t numFlags = mFlags.GetLength(); + for (size_t i = 0; i < numFlags; ++i) { mFlags[i] &= ~FLAG_MODELTRANSFORMREADY; } @@ -461,8 +439,8 @@ namespace EMotionFX void Pose::InvalidateAllLocalAndModelSpaceTransforms() { - const uint32 numFlags = mFlags.GetLength(); - for (uint32 i = 0; i < numFlags; ++i) + const size_t numFlags = mFlags.GetLength(); + for (size_t i = 0; i < numFlags; ++i) { mFlags[i] &= ~(FLAG_LOCALTRANSFORMREADY | FLAG_MODELTRANSFORMREADY); } @@ -472,8 +450,8 @@ namespace EMotionFX Transform Pose::CalcTrajectoryTransform() const { MCORE_ASSERT(mActor); - const uint32 motionExtractionNodeIndex = mActor->GetMotionExtractionNodeIndex(); - if (motionExtractionNodeIndex == MCORE_INVALIDINDEX32) + const size_t motionExtractionNodeIndex = mActor->GetMotionExtractionNodeIndex(); + if (motionExtractionNodeIndex == InvalidIndex) { return Transform::CreateIdentity(); } @@ -485,8 +463,8 @@ namespace EMotionFX void Pose::UpdateAllLocalSpaceTranforms() { Skeleton* skeleton = mActor->GetSkeleton(); - const uint32 numNodes = skeleton->GetNumNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = skeleton->GetNumNodes(); + for (size_t i = 0; i < numNodes; ++i) { UpdateLocalSpaceTransform(i); } @@ -496,8 +474,8 @@ namespace EMotionFX void Pose::UpdateAllModelSpaceTranforms() { Skeleton* skeleton = mActor->GetSkeleton(); - const uint32 numNodes = skeleton->GetNumNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = skeleton->GetNumNodes(); + for (size_t i = 0; i < numNodes; ++i) { UpdateModelSpaceTransform(i); } @@ -532,11 +510,10 @@ namespace EMotionFX { if (weight > 0.0f) { - uint32 nodeNr; - const uint32 numNodes = actorInstance->GetNumEnabledNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = actorInstance->GetNumEnabledNodes(); + for (size_t i = 0; i < numNodes; ++i) { - nodeNr = actorInstance->GetEnabledNode(i); + const uint16 nodeNr = actorInstance->GetEnabledNode(i); Transform transform = GetLocalSpaceTransform(nodeNr); transform.Blend(destPose->GetLocalSpaceTransform(nodeNr), weight); outPose->SetLocalSpaceTransform(nodeNr, transform, false); @@ -553,10 +530,10 @@ namespace EMotionFX } // blend the morph weights - const uint32 numMorphs = mMorphWeights.GetLength(); + const size_t numMorphs = mMorphWeights.GetLength(); MCORE_ASSERT(actorInstance->GetMorphSetupInstance()->GetNumMorphTargets() == numMorphs); MCORE_ASSERT(numMorphs == destPose->GetNumMorphWeights()); - for (uint32 i = 0; i < numMorphs; ++i) + for (size_t i = 0; i < numMorphs; ++i) { mMorphWeights[i] = MCore::LinearInterpolate(mMorphWeights[i], destPose->mMorphWeights[i], weight); } @@ -565,12 +542,11 @@ namespace EMotionFX { TransformData* transformData = instance->GetActorInstance()->GetTransformData(); const Pose* bindPose = transformData->GetBindPose(); - uint32 nodeNr; Transform result; - const uint32 numNodes = actorInstance->GetNumEnabledNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = actorInstance->GetNumEnabledNodes(); + for (size_t i = 0; i < numNodes; ++i) { - nodeNr = actorInstance->GetEnabledNode(i); + const uint16 nodeNr = actorInstance->GetEnabledNode(i); const Transform& base = bindPose->GetLocalSpaceTransform(nodeNr); BlendTransformAdditiveUsingBindPose(base, GetLocalSpaceTransform(nodeNr), destPose->GetLocalSpaceTransform(nodeNr), weight, &result); outPose->SetLocalSpaceTransform(nodeNr, result, false); @@ -578,10 +554,10 @@ namespace EMotionFX outPose->InvalidateAllModelSpaceTransforms(); // blend the morph weights - const uint32 numMorphs = mMorphWeights.GetLength(); + const size_t numMorphs = mMorphWeights.GetLength(); MCORE_ASSERT(actorInstance->GetMorphSetupInstance()->GetNumMorphTargets() == numMorphs); MCORE_ASSERT(numMorphs == destPose->GetNumMorphWeights()); - for (uint32 i = 0; i < numMorphs; ++i) + for (size_t i = 0; i < numMorphs; ++i) { mMorphWeights[i] += destPose->mMorphWeights[i] * weight; } @@ -614,11 +590,10 @@ namespace EMotionFX // blend all transforms if (!additive) { - uint32 nodeNr; - const uint32 numNodes = actorInstance->GetNumEnabledNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = actorInstance->GetNumEnabledNodes(); + for (size_t i = 0; i < numNodes; ++i) { - nodeNr = actorInstance->GetEnabledNode(i); + const uint16 nodeNr = actorInstance->GetEnabledNode(i); // try to find the motion link // if we cannot find it, this node/transform is not influenced by the motion, so we skip it @@ -635,10 +610,10 @@ namespace EMotionFX outPose->InvalidateAllModelSpaceTransforms(); // blend the morph weights - const uint32 numMorphs = mMorphWeights.GetLength(); + const size_t numMorphs = mMorphWeights.GetLength(); MCORE_ASSERT(actorInstance->GetMorphSetupInstance()->GetNumMorphTargets() == numMorphs); MCORE_ASSERT(numMorphs == destPose->GetNumMorphWeights()); - for (uint32 i = 0; i < numMorphs; ++i) + for (size_t i = 0; i < numMorphs; ++i) { mMorphWeights[i] = MCore::LinearInterpolate(mMorphWeights[i], destPose->mMorphWeights[i], weight); } @@ -646,11 +621,10 @@ namespace EMotionFX else { Pose* bindPose = transformData->GetBindPose(); - uint32 nodeNr; - const uint32 numNodes = actorInstance->GetNumEnabledNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = actorInstance->GetNumEnabledNodes(); + for (size_t i = 0; i < numNodes; ++i) { - nodeNr = actorInstance->GetEnabledNode(i); + const uint16 nodeNr = actorInstance->GetEnabledNode(i); // try to find the motion link // if we cannot find it, this node/transform is not influenced by the motion, so we skip it @@ -666,10 +640,10 @@ namespace EMotionFX outPose->InvalidateAllModelSpaceTransforms(); // blend the morph weights - const uint32 numMorphs = mMorphWeights.GetLength(); + const size_t numMorphs = mMorphWeights.GetLength(); MCORE_ASSERT(actorInstance->GetMorphSetupInstance()->GetNumMorphTargets() == numMorphs); MCORE_ASSERT(numMorphs == destPose->GetNumMorphWeights()); - for (uint32 i = 0; i < numMorphs; ++i) + for (size_t i = 0; i < numMorphs; ++i) { mMorphWeights[i] += destPose->mMorphWeights[i] * weight; } @@ -767,32 +741,31 @@ namespace EMotionFX { if (mActorInstance) { - uint32 nodeNr; - const uint32 numNodes = mActorInstance->GetNumEnabledNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = mActorInstance->GetNumEnabledNodes(); + for (size_t i = 0; i < numNodes; ++i) { - nodeNr = mActorInstance->GetEnabledNode(i); + const uint16 nodeNr = mActorInstance->GetEnabledNode(i); mLocalSpaceTransforms[nodeNr].Zero(); } - const uint32 numMorphs = mMorphWeights.GetLength(); + const size_t numMorphs = mMorphWeights.GetLength(); MCORE_ASSERT(mActorInstance->GetMorphSetupInstance()->GetNumMorphTargets() == numMorphs); - for (uint32 i = 0; i < numMorphs; ++i) + for (size_t i = 0; i < numMorphs; ++i) { mMorphWeights[i] = 0.0f; } } else { - const uint32 numNodes = mActor->GetSkeleton()->GetNumNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = mActor->GetSkeleton()->GetNumNodes(); + for (size_t i = 0; i < numNodes; ++i) { mLocalSpaceTransforms[i].Zero(); } - const uint32 numMorphs = mMorphWeights.GetLength(); + const size_t numMorphs = mMorphWeights.GetLength(); MCORE_ASSERT(mActor->GetMorphSetup(0)->GetNumMorphTargets() == numMorphs); - for (uint32 i = 0; i < numMorphs; ++i) + for (size_t i = 0; i < numMorphs; ++i) { mMorphWeights[i] = 0.0f; } @@ -807,19 +780,18 @@ namespace EMotionFX { if (mActorInstance) { - uint32 nodeNr; - const uint32 numNodes = mActorInstance->GetNumEnabledNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = mActorInstance->GetNumEnabledNodes(); + for (size_t i = 0; i < numNodes; ++i) { - nodeNr = mActorInstance->GetEnabledNode(i); + const uint16 nodeNr = mActorInstance->GetEnabledNode(i); UpdateLocalSpaceTransform(nodeNr); mLocalSpaceTransforms[nodeNr].mRotation.Normalize(); } } else { - const uint32 numNodes = mActor->GetSkeleton()->GetNumNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = mActor->GetSkeleton()->GetNumNodes(); + for (size_t i = 0; i < numNodes; ++i) { UpdateLocalSpaceTransform(i); mLocalSpaceTransforms[i].mRotation.Normalize(); @@ -833,11 +805,10 @@ namespace EMotionFX { if (mActorInstance) { - uint32 nodeNr; - const uint32 numNodes = mActorInstance->GetNumEnabledNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = mActorInstance->GetNumEnabledNodes(); + for (size_t i = 0; i < numNodes; ++i) { - nodeNr = mActorInstance->GetEnabledNode(i); + const uint16 nodeNr = mActorInstance->GetEnabledNode(i); Transform& transform = const_cast(GetLocalSpaceTransform(nodeNr)); const Transform& otherTransform = other->GetLocalSpaceTransform(nodeNr); @@ -845,18 +816,18 @@ namespace EMotionFX } // blend the morph weights - const uint32 numMorphs = mMorphWeights.GetLength(); + const size_t numMorphs = mMorphWeights.GetLength(); MCORE_ASSERT(mActorInstance->GetMorphSetupInstance()->GetNumMorphTargets() == numMorphs); MCORE_ASSERT(numMorphs == other->GetNumMorphWeights()); - for (uint32 i = 0; i < numMorphs; ++i) + for (size_t i = 0; i < numMorphs; ++i) { mMorphWeights[i] += other->mMorphWeights[i] * weight; } } else { - const uint32 numNodes = mActor->GetSkeleton()->GetNumNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = mActor->GetSkeleton()->GetNumNodes(); + for (size_t i = 0; i < numNodes; ++i) { Transform& transform = const_cast(GetLocalSpaceTransform(i)); const Transform& otherTransform = other->GetLocalSpaceTransform(i); @@ -864,10 +835,10 @@ namespace EMotionFX } // blend the morph weights - const uint32 numMorphs = mMorphWeights.GetLength(); + const size_t numMorphs = mMorphWeights.GetLength(); MCORE_ASSERT(mActor->GetMorphSetup(0)->GetNumMorphTargets() == numMorphs); MCORE_ASSERT(numMorphs == other->GetNumMorphWeights()); - for (uint32 i = 0; i < numMorphs; ++i) + for (size_t i = 0; i < numMorphs; ++i) { mMorphWeights[i] += other->mMorphWeights[i] * weight; } @@ -882,20 +853,19 @@ namespace EMotionFX { if (mActorInstance) { - uint32 nodeNr; - const uint32 numNodes = mActorInstance->GetNumEnabledNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = mActorInstance->GetNumEnabledNodes(); + for (size_t i = 0; i < numNodes; ++i) { - nodeNr = mActorInstance->GetEnabledNode(i); + const uint16 nodeNr = mActorInstance->GetEnabledNode(i); Transform& curTransform = const_cast(GetLocalSpaceTransform(nodeNr)); curTransform.Blend(destPose->GetLocalSpaceTransform(nodeNr), weight); } // blend the morph weights - const uint32 numMorphs = mMorphWeights.GetLength(); + const size_t numMorphs = mMorphWeights.GetLength(); MCORE_ASSERT(mActorInstance->GetMorphSetupInstance()->GetNumMorphTargets() == numMorphs); MCORE_ASSERT(numMorphs == destPose->GetNumMorphWeights()); - for (uint32 i = 0; i < numMorphs; ++i) + for (size_t i = 0; i < numMorphs; ++i) { mMorphWeights[i] = MCore::LinearInterpolate(mMorphWeights[i], destPose->mMorphWeights[i], weight); } @@ -908,18 +878,18 @@ namespace EMotionFX } else { - const uint32 numNodes = mActor->GetSkeleton()->GetNumNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = mActor->GetSkeleton()->GetNumNodes(); + for (size_t i = 0; i < numNodes; ++i) { Transform& curTransform = const_cast(GetLocalSpaceTransform(i)); curTransform.Blend(destPose->GetLocalSpaceTransform(i), weight); } // blend the morph weights - const uint32 numMorphs = mMorphWeights.GetLength(); + const size_t numMorphs = mMorphWeights.GetLength(); MCORE_ASSERT(mActor->GetMorphSetup(0)->GetNumMorphTargets() == numMorphs); MCORE_ASSERT(numMorphs == destPose->GetNumMorphWeights()); - for (uint32 i = 0; i < numMorphs; ++i) + for (size_t i = 0; i < numMorphs; ++i) { mMorphWeights[i] = MCore::LinearInterpolate(mMorphWeights[i], destPose->mMorphWeights[i], weight); } @@ -940,27 +910,27 @@ namespace EMotionFX AZ_Assert(mLocalSpaceTransforms.GetLength() == other.mLocalSpaceTransforms.GetLength(), "Poses must be of the same size"); if (mActorInstance) { - const uint32 numNodes = mActorInstance->GetNumEnabledNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = mActorInstance->GetNumEnabledNodes(); + for (size_t i = 0; i < numNodes; ++i) { - uint16 nodeNr = mActorInstance->GetEnabledNode(i); + const uint16 nodeNr = mActorInstance->GetEnabledNode(i); Transform& transform = const_cast(GetLocalSpaceTransform(nodeNr)); transform = transform.CalcRelativeTo(other.GetLocalSpaceTransform(nodeNr)); } } else { - const uint32 numNodes = mLocalSpaceTransforms.GetLength(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = mLocalSpaceTransforms.GetLength(); + for (size_t i = 0; i < numNodes; ++i) { Transform& transform = const_cast(GetLocalSpaceTransform(i)); transform = transform.CalcRelativeTo(other.GetLocalSpaceTransform(i)); } } - const uint32 numMorphs = mMorphWeights.GetLength(); + const size_t numMorphs = mMorphWeights.GetLength(); AZ_Assert(numMorphs == other.GetNumMorphWeights(), "Number of morphs in the pose doesn't match the number of morphs inside the provided input pose."); - for (uint32 i = 0; i < numMorphs; ++i) + for (size_t i = 0; i < numMorphs; ++i) { mMorphWeights[i] -= other.mMorphWeights[i]; } @@ -993,8 +963,8 @@ namespace EMotionFX AZ_Assert(mLocalSpaceTransforms.GetLength() == additivePose.mLocalSpaceTransforms.GetLength(), "Poses must be of the same size"); if (mActorInstance) { - const uint32 numNodes = mActorInstance->GetNumEnabledNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = mActorInstance->GetNumEnabledNodes(); + for (size_t i = 0; i < numNodes; ++i) { uint16 nodeNr = mActorInstance->GetEnabledNode(i); Transform& transform = const_cast(GetLocalSpaceTransform(nodeNr)); @@ -1010,8 +980,8 @@ namespace EMotionFX } else { - const uint32 numNodes = mLocalSpaceTransforms.GetLength(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = mLocalSpaceTransforms.GetLength(); + for (size_t i = 0; i < numNodes; ++i) { Transform& transform = const_cast(GetLocalSpaceTransform(i)); const Transform& additiveTransform = additivePose.GetLocalSpaceTransform(i); @@ -1025,9 +995,9 @@ namespace EMotionFX } } - const uint32 numMorphs = mMorphWeights.GetLength(); + const size_t numMorphs = mMorphWeights.GetLength(); AZ_Assert(numMorphs == additivePose.GetNumMorphWeights(), "Number of morphs in the pose doesn't match the number of morphs inside the provided input pose."); - for (uint32 i = 0; i < numMorphs; ++i) + for (size_t i = 0; i < numMorphs; ++i) { mMorphWeights[i] += additivePose.mMorphWeights[i] * weight; } @@ -1043,8 +1013,8 @@ namespace EMotionFX AZ_Assert(mLocalSpaceTransforms.GetLength() == additivePose.mLocalSpaceTransforms.GetLength(), "Poses must be of the same size"); if (mActorInstance) { - const uint32 numNodes = mActorInstance->GetNumEnabledNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = mActorInstance->GetNumEnabledNodes(); + for (size_t i = 0; i < numNodes; ++i) { uint16 nodeNr = mActorInstance->GetEnabledNode(i); Transform& transform = const_cast(GetLocalSpaceTransform(nodeNr)); @@ -1060,8 +1030,8 @@ namespace EMotionFX } else { - const uint32 numNodes = mLocalSpaceTransforms.GetLength(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = mLocalSpaceTransforms.GetLength(); + for (size_t i = 0; i < numNodes; ++i) { Transform& transform = const_cast(GetLocalSpaceTransform(i)); const Transform& additiveTransform = additivePose.GetLocalSpaceTransform(i); @@ -1075,9 +1045,9 @@ namespace EMotionFX } } - const uint32 numMorphs = mMorphWeights.GetLength(); + const size_t numMorphs = mMorphWeights.GetLength(); AZ_Assert(numMorphs == additivePose.GetNumMorphWeights(), "Number of morphs in the pose doesn't match the number of morphs inside the provided input pose."); - for (uint32 i = 0; i < numMorphs; ++i) + for (size_t i = 0; i < numMorphs; ++i) { mMorphWeights[i] += additivePose.mMorphWeights[i]; } @@ -1092,8 +1062,8 @@ namespace EMotionFX AZ_Assert(mLocalSpaceTransforms.GetLength() == refPose.mLocalSpaceTransforms.GetLength(), "Poses must be of the same size"); if (mActorInstance) { - const uint32 numNodes = mActorInstance->GetNumEnabledNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = mActorInstance->GetNumEnabledNodes(); + for (size_t i = 0; i < numNodes; ++i) { uint16 nodeNr = mActorInstance->GetEnabledNode(i); Transform& transform = const_cast(GetLocalSpaceTransform(nodeNr)); @@ -1108,8 +1078,8 @@ namespace EMotionFX } else { - const uint32 numNodes = mLocalSpaceTransforms.GetLength(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = mLocalSpaceTransforms.GetLength(); + for (size_t i = 0; i < numNodes; ++i) { Transform& transform = const_cast(GetLocalSpaceTransform(i)); const Transform& refTransform = refPose.GetLocalSpaceTransform(i); @@ -1122,9 +1092,9 @@ namespace EMotionFX } } - const uint32 numMorphs = mMorphWeights.GetLength(); + const size_t numMorphs = mMorphWeights.GetLength(); AZ_Assert(numMorphs == refPose.GetNumMorphWeights(), "Number of morphs in the pose doesn't match the number of morphs inside the provided input pose."); - for (uint32 i = 0; i < numMorphs; ++i) + for (size_t i = 0; i < numMorphs; ++i) { mMorphWeights[i] -= refPose.mMorphWeights[i]; } @@ -1143,20 +1113,19 @@ namespace EMotionFX Pose* bindPose = transformData->GetBindPose(); Transform result; - uint32 nodeNr; - const uint32 numNodes = mActorInstance->GetNumEnabledNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = mActorInstance->GetNumEnabledNodes(); + for (size_t i = 0; i < numNodes; ++i) { - nodeNr = mActorInstance->GetEnabledNode(i); + const uint16 nodeNr = mActorInstance->GetEnabledNode(i); BlendTransformAdditiveUsingBindPose(bindPose->GetLocalSpaceTransform(nodeNr), GetLocalSpaceTransform(nodeNr), destPose->GetLocalSpaceTransform(nodeNr), weight, &result); SetLocalSpaceTransform(nodeNr, result, false); } // blend the morph weights - const uint32 numMorphs = mMorphWeights.GetLength(); + const size_t numMorphs = mMorphWeights.GetLength(); MCORE_ASSERT(mActorInstance->GetMorphSetupInstance()->GetNumMorphTargets() == numMorphs); MCORE_ASSERT(numMorphs == destPose->GetNumMorphWeights()); - for (uint32 i = 0; i < numMorphs; ++i) + for (size_t i = 0; i < numMorphs; ++i) { mMorphWeights[i] += destPose->mMorphWeights[i] * weight; } @@ -1167,18 +1136,18 @@ namespace EMotionFX Pose* bindPose = transformData->GetBindPose(); Transform result; - const uint32 numNodes = mActor->GetSkeleton()->GetNumNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = mActor->GetSkeleton()->GetNumNodes(); + for (size_t i = 0; i < numNodes; ++i) { BlendTransformAdditiveUsingBindPose(bindPose->GetLocalSpaceTransform(i), GetLocalSpaceTransform(i), destPose->GetLocalSpaceTransform(i), weight, &result); SetLocalSpaceTransform(i, result, false); } // blend the morph weights - const uint32 numMorphs = mMorphWeights.GetLength(); + const size_t numMorphs = mMorphWeights.GetLength(); MCORE_ASSERT(mActor->GetMorphSetup(0)->GetNumMorphTargets() == numMorphs); MCORE_ASSERT(numMorphs == destPose->GetNumMorphWeights()); - for (uint32 i = 0; i < numMorphs; ++i) + for (size_t i = 0; i < numMorphs; ++i) { mMorphWeights[i] += destPose->mMorphWeights[i] * weight; } @@ -1284,8 +1253,8 @@ namespace EMotionFX // compensate for motion extraction, basically making it in-place void Pose::CompensateForMotionExtractionDirect(EMotionExtractionFlags motionExtractionFlags) { - const uint32 motionExtractionNodeIndex = mActor->GetMotionExtractionNodeIndex(); - if (motionExtractionNodeIndex != MCORE_INVALIDINDEX32) + const size_t motionExtractionNodeIndex = mActor->GetMotionExtractionNodeIndex(); + if (motionExtractionNodeIndex != InvalidIndex) { Transform motionExtractionNodeTransform = GetLocalSpaceTransformDirect(motionExtractionNodeIndex); mActorInstance->MotionExtractionCompensate(motionExtractionNodeTransform, motionExtractionFlags); @@ -1297,8 +1266,8 @@ namespace EMotionFX // compensate for motion extraction, basically making it in-place void Pose::CompensateForMotionExtraction(EMotionExtractionFlags motionExtractionFlags) { - const uint32 motionExtractionNodeIndex = mActor->GetMotionExtractionNodeIndex(); - if (motionExtractionNodeIndex != MCORE_INVALIDINDEX32) + const size_t motionExtractionNodeIndex = mActor->GetMotionExtractionNodeIndex(); + if (motionExtractionNodeIndex != InvalidIndex) { Transform motionExtractionNodeTransform = GetLocalSpaceTransform(motionExtractionNodeIndex); mActorInstance->MotionExtractionCompensate(motionExtractionNodeTransform, motionExtractionFlags); @@ -1311,8 +1280,8 @@ namespace EMotionFX void Pose::ApplyMorphWeightsToActorInstance() { MorphSetupInstance* morphSetupInstance = mActorInstance->GetMorphSetupInstance(); - const uint32 numMorphs = morphSetupInstance->GetNumMorphTargets(); - for (uint32 m = 0; m < numMorphs; ++m) + const size_t numMorphs = morphSetupInstance->GetNumMorphTargets(); + for (size_t m = 0; m < numMorphs; ++m) { MorphSetupInstance::MorphTarget* morphTarget = morphSetupInstance->GetMorphTarget(m); if (morphTarget->GetIsInManualMode() == false) @@ -1326,8 +1295,8 @@ namespace EMotionFX // zero all morph weights void Pose::ZeroMorphWeights() { - const uint32 numMorphs = mMorphWeights.GetLength(); - for (uint32 m = 0; m < numMorphs; ++m) + const size_t numMorphs = mMorphWeights.GetLength(); + for (size_t m = 0; m < numMorphs; ++m) { mMorphWeights[m] = 0.0f; } @@ -1345,10 +1314,10 @@ namespace EMotionFX AZ_Assert(mLocalSpaceTransforms.GetLength() == other.mLocalSpaceTransforms.GetLength(), "Poses must be of the same size"); if (mActorInstance) { - const uint32 numNodes = mActorInstance->GetNumEnabledNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = mActorInstance->GetNumEnabledNodes(); + for (size_t i = 0; i < numNodes; ++i) { - uint16 nodeNr = mActorInstance->GetEnabledNode(i); + const uint16 nodeNr = mActorInstance->GetEnabledNode(i); Transform& transform = const_cast(GetLocalSpaceTransform(nodeNr)); Transform otherTransform = other.GetLocalSpaceTransform(nodeNr); transform = otherTransform * transform; @@ -1356,8 +1325,8 @@ namespace EMotionFX } else { - const uint32 numNodes = mLocalSpaceTransforms.GetLength(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = mLocalSpaceTransforms.GetLength(); + for (size_t i = 0; i < numNodes; ++i) { Transform& transform = const_cast(GetLocalSpaceTransform(i)); Transform otherTransform = other.GetLocalSpaceTransform(i); @@ -1375,8 +1344,8 @@ namespace EMotionFX AZ_Assert(mLocalSpaceTransforms.GetLength() == other.mLocalSpaceTransforms.GetLength(), "Poses must be of the same size"); if (mActorInstance) { - const uint32 numNodes = mActorInstance->GetNumEnabledNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = mActorInstance->GetNumEnabledNodes(); + for (size_t i = 0; i < numNodes; ++i) { uint16 nodeNr = mActorInstance->GetEnabledNode(i); Transform& transform = const_cast(GetLocalSpaceTransform(nodeNr)); @@ -1385,8 +1354,8 @@ namespace EMotionFX } else { - const uint32 numNodes = mLocalSpaceTransforms.GetLength(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = mLocalSpaceTransforms.GetLength(); + for (size_t i = 0; i < numNodes; ++i) { Transform& transform = const_cast(GetLocalSpaceTransform(i)); transform.Multiply(other.GetLocalSpaceTransform(i)); @@ -1403,8 +1372,8 @@ namespace EMotionFX AZ_Assert(mLocalSpaceTransforms.GetLength() == other.mLocalSpaceTransforms.GetLength(), "Poses must be of the same size"); if (mActorInstance) { - const uint32 numNodes = mActorInstance->GetNumEnabledNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = mActorInstance->GetNumEnabledNodes(); + for (size_t i = 0; i < numNodes; ++i) { uint16 nodeNr = mActorInstance->GetEnabledNode(i); Transform& transform = const_cast(GetLocalSpaceTransform(nodeNr)); @@ -1415,8 +1384,8 @@ namespace EMotionFX } else { - const uint32 numNodes = mLocalSpaceTransforms.GetLength(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = mLocalSpaceTransforms.GetLength(); + for (size_t i = 0; i < numNodes; ++i) { Transform& transform = const_cast(GetLocalSpaceTransform(i)); Transform otherTransform = other.GetLocalSpaceTransform(i); @@ -1430,7 +1399,7 @@ namespace EMotionFX } - Transform Pose::GetMeshNodeWorldSpaceTransform(AZ::u32 lodLevel, AZ::u32 nodeIndex) const + Transform Pose::GetMeshNodeWorldSpaceTransform(size_t lodLevel, size_t nodeIndex) const { if (!mActorInstance) { @@ -1461,12 +1430,12 @@ namespace EMotionFX Pose& unmirroredPose = tempPose->GetPose(); unmirroredPose = *this; - const AZ::u32 numNodes = mActorInstance->GetNumEnabledNodes(); - for (AZ::u32 i = 0; i < numNodes; ++i) + const size_t numNodes = mActorInstance->GetNumEnabledNodes(); + for (size_t i = 0; i < numNodes; ++i) { - const AZ::u32 nodeNumber = mActorInstance->GetEnabledNode(i); - const AZ::u32 jointDataIndex = jointLinks[nodeNumber]; - if (jointDataIndex == InvalidIndex32) + const size_t nodeNumber = mActorInstance->GetEnabledNode(i); + const size_t jointDataIndex = jointLinks[nodeNumber]; + if (jointDataIndex == InvalidIndex) { continue; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Pose.h b/Gems/EMotionFX/Code/EMotionFX/Source/Pose.h index be5f24f8e4..58dcb59ee4 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Pose.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Pose.h @@ -90,7 +90,7 @@ namespace EMotionFX * @param The LOD level, which must be in range of 0..mActor->GetNumLODLevels(). * @param nodeIndex The index of the node. If this node happens to have no mesh the regular current world space transform is returned. */ - Transform GetMeshNodeWorldSpaceTransform(AZ::u32 lodLevel, AZ::u32 nodeIndex) const; + Transform GetMeshNodeWorldSpaceTransform(size_t lodLevel, size_t nodeIndex) const; void InvalidateAllLocalSpaceTransforms(); void InvalidateAllModelSpaceTransforms(); From 8314f8caf3d58999c866c5b4afc58954474a61fb Mon Sep 17 00:00:00 2001 From: Chris Burel Date: Mon, 24 May 2021 12:04:14 -0700 Subject: [PATCH 204/803] Update ActorInstance uint32->size_t Signed-off-by: Chris Burel --- .../Code/EMotionFX/Source/ActorInstance.cpp | 191 +++++++----------- .../Code/EMotionFX/Source/ActorInstance.h | 42 ++-- .../Code/EMotionFX/Source/SubMesh.cpp | 41 +--- .../EMotionFX/Code/EMotionFX/Source/SubMesh.h | 14 +- 4 files changed, 115 insertions(+), 173 deletions(-) diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.cpp index eaa09f92c0..65eb038dbf 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.cpp @@ -94,8 +94,8 @@ namespace EMotionFX } // disable nodes that are disabled in LOD 0 Skeleton* skeleton = mActor->GetSkeleton(); - const uint32 numNodes = skeleton->GetNumNodes(); - for (uint32 n = 0; n < numNodes; ++n) + const size_t numNodes = skeleton->GetNumNodes(); + for (size_t n = 0; n < numNodes; ++n) { if (skeleton->GetNode(n)->GetSkeletalLODStatus(0) == false) { @@ -170,8 +170,8 @@ namespace EMotionFX // delete all attachments // actor instances that are attached will be detached, and not deleted from memory - const uint32 numAttachments = mAttachments.size(); - for (uint32 i = 0; i < numAttachments; ++i) + const size_t numAttachments = mAttachments.size(); + for (size_t i = 0; i < numAttachments; ++i) { ActorInstance* attachmentActorInstance = mAttachments[i]->GetAttachmentActorInstance(); if (attachmentActorInstance) @@ -375,10 +375,10 @@ namespace EMotionFX AZ::Matrix3x4* skinningMatrices = mTransformData->GetSkinningMatrices(); const Pose* pose = mTransformData->GetCurrentPose(); - const uint32 numNodes = GetNumEnabledNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = GetNumEnabledNodes(); + for (size_t i = 0; i < numNodes; ++i) { - const uint32 nodeNumber = GetEnabledNode(i); + const size_t nodeNumber = GetEnabledNode(i); Transform skinningTransform = mActor->GetInverseBindPoseTransform(nodeNumber); skinningTransform.Multiply(pose->GetModelSpaceTransform(nodeNumber)); skinningMatrices[nodeNumber] = AZ::Matrix3x4::CreateFromTransform(skinningTransform.ToAZTransform()); @@ -392,10 +392,8 @@ namespace EMotionFX // Update the mesh deformers. const Skeleton* skeleton = mActor->GetSkeleton(); - const uint32 numNodes = mEnabledNodes.size(); - for (uint32 i = 0; i < numNodes; ++i) + for (uint16 nodeNr : mEnabledNodes) { - const uint16 nodeNr = mEnabledNodes[i]; Node* node = skeleton->GetNode(nodeNr); MeshDeformerStack* stack = mActor->GetMeshDeformerStack(mLODLevel, nodeNr); if (stack) @@ -412,10 +410,8 @@ namespace EMotionFX // Update the mesh morph deformers. const Skeleton* skeleton = mActor->GetSkeleton(); - const uint32 numNodes = mEnabledNodes.size(); - for (uint32 i = 0; i < numNodes; ++i) + for (uint16 nodeNr : mEnabledNodes) { - const uint16 nodeNr = mEnabledNodes[i]; Node* node = skeleton->GetNode(nodeNr); MeshDeformerStack* stack = mActor->GetMeshDeformerStack(mLODLevel, nodeNr); if (stack) @@ -461,27 +457,23 @@ namespace EMotionFX } // try to find the attachment number for a given actor instance - uint32 ActorInstance::FindAttachmentNr(ActorInstance* actorInstance) + size_t ActorInstance::FindAttachmentNr(ActorInstance* actorInstance) { // for all attachments - const uint32 numAttachments = mAttachments.size(); - for (uint32 i = 0; i < numAttachments; ++i) + const auto foundAttachment = AZStd::find_if(mAttachments.begin(), mAttachments.end(), [actorInstance](const Attachment* attachment) { - if (mAttachments[i]->GetAttachmentActorInstance() == actorInstance) - { - return i; - } - } + return attachment->GetAttachmentActorInstance() == actorInstance; + }); - return MCORE_INVALIDINDEX32; + return foundAttachment == mAttachments.end() ? AZStd::distance(mAttachments.begin(), foundAttachment) : InvalidIndex; } // remove an attachment by actor instance pointer bool ActorInstance::RemoveAttachment(ActorInstance* actorInstance, bool delFromMem) { // try to find the attachment - const uint32 attachmentNr = FindAttachmentNr(actorInstance); - if (attachmentNr == MCORE_INVALIDINDEX32) + const size_t attachmentNr = FindAttachmentNr(actorInstance); + if (attachmentNr == InvalidIndex) { return false; } @@ -492,7 +484,7 @@ namespace EMotionFX } // remove an attachment - void ActorInstance::RemoveAttachment(uint32 nr, bool delFromMem) + void ActorInstance::RemoveAttachment(size_t nr, bool delFromMem) { MCORE_ASSERT(nr < mAttachments.size()); @@ -559,8 +551,8 @@ namespace EMotionFX mDependencies.emplace_back(mainDependency); // add all dependencies stored inside the actor - const uint32 numDependencies = mActor->GetNumDependencies(); - for (uint32 i = 0; i < numDependencies; ++i) + const size_t numDependencies = mActor->GetNumDependencies(); + for (size_t i = 0; i < numDependencies; ++i) { mDependencies.emplace_back(*mActor->GetDependency(i)); } @@ -569,11 +561,9 @@ namespace EMotionFX // set the attachment matrices void ActorInstance::UpdateAttachments() { - // update all attachments - const uint32 numAttachments = mAttachments.size(); - for (uint32 i = 0; i < numAttachments; ++i) + for (Attachment* mAttachment : mAttachments) { - mAttachments[i]->Update(); + mAttachment->Update(); } } @@ -604,7 +594,7 @@ namespace EMotionFX } // update the bounding volume - void ActorInstance::UpdateBounds(uint32 geomLODLevel, EBoundsType boundsType, uint32 itemFrequency) + void ActorInstance::UpdateBounds(size_t geomLODLevel, EBoundsType boundsType, uint32 itemFrequency) { // depending on the bounding volume update type switch (boundsType) @@ -650,11 +640,10 @@ namespace EMotionFX const Skeleton* skeleton = mActor->GetSkeleton(); // for all nodes, encapsulate the world space positions - uint16 nodeNr; - const uint32 numNodes = GetNumEnabledNodes(); - for (uint32 i = 0; i < numNodes; i += nodeFrequency) + const size_t numNodes = GetNumEnabledNodes(); + for (size_t i = 0; i < numNodes; i += nodeFrequency) { - nodeNr = GetEnabledNode(i); + const uint16 nodeNr = GetEnabledNode(i); if (skeleton->GetNode(nodeNr)->GetIncludeInBoundsCalc()) { outResult->AddPoint(pose->GetWorldSpaceTransform(nodeNr).mPosition); @@ -663,7 +652,7 @@ namespace EMotionFX } // calculate the AABB that contains all world space vertices of all meshes - void ActorInstance::CalcMeshBasedAabb(uint32 geomLODLevel, AZ::Aabb* outResult, uint32 vertexFrequency) + void ActorInstance::CalcMeshBasedAabb(size_t geomLODLevel, AZ::Aabb* outResult, uint32 vertexFrequency) { *outResult = AZ::Aabb::CreateNull(); @@ -671,8 +660,8 @@ namespace EMotionFX const Skeleton* skeleton = mActor->GetSkeleton(); // for all nodes, encapsulate the world space positions - const uint32 numNodes = GetNumEnabledNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = GetNumEnabledNodes(); + for (size_t i = 0; i < numNodes; ++i) { const uint16 nodeNr = GetEnabledNode(i); Node* node = skeleton->GetNode(nodeNr); @@ -728,8 +717,8 @@ namespace EMotionFX // apply all morph targets //bool allZero = true; - const uint32 numTargets = morphSetup->GetNumMorphTargets(); - for (uint32 i = 0; i < numTargets; ++i) + const size_t numTargets = morphSetup->GetNumMorphTargets(); + for (size_t i = 0; i < numTargets; ++i) { // get the morph target MorphTarget* morphTarget = morphSetup->GetMorphTarget(i); @@ -749,32 +738,19 @@ namespace EMotionFX morphTarget->Apply(this, weight); } } - - /* - // enable or disable all morph deformers if the weights are all zero - const uint32 numNodes = mActor->GetNumNodes(); - for (uint32 n=0; nGetNode(n); - MeshDeformerStack* stack = node->GetMeshDeformerStack( mGeometryLODLevel ).GetPointer(); - if (stack == nullptr) - continue; - - stack->EnableAllDeformersByType( MorphMeshDeformer::TYPE_ID, !allZero ); - }*/ } //--------------------- // check intersection with a ray, but don't get the intersection point or closest intersecting node - Node* ActorInstance::IntersectsCollisionMesh(uint32 lodLevel, const MCore::Ray& ray) const + Node* ActorInstance::IntersectsCollisionMesh(size_t lodLevel, const MCore::Ray& ray) const { const Skeleton* skeleton = mActor->GetSkeleton(); const Pose* pose = mTransformData->GetCurrentPose(); // for all nodes - const uint32 numNodes = GetNumEnabledNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = GetNumEnabledNodes(); + for (size_t i = 0; i < numNodes; ++i) { const uint16 nodeNr = GetEnabledNode(i); @@ -802,7 +778,7 @@ namespace EMotionFX return nullptr; } - Node* ActorInstance::IntersectsCollisionMesh(uint32 lodLevel, const MCore::Ray& ray, AZ::Vector3* outIntersect, AZ::Vector3* outNormal, AZ::Vector2* outUV, float* outBaryU, float* outBaryV, uint32* outIndices) const + Node* ActorInstance::IntersectsCollisionMesh(size_t lodLevel, const MCore::Ray& ray, AZ::Vector3* outIntersect, AZ::Vector3* outNormal, AZ::Vector2* outUV, float* outBaryU, float* outBaryV, uint32* outIndices) const { Node* closestNode = nullptr; AZ::Vector3 point; @@ -817,11 +793,10 @@ namespace EMotionFX const Pose* pose = mTransformData->GetCurrentPose(); // check all nodes - uint16 nodeNr; - const uint32 numNodes = GetNumEnabledNodes(); - for (uint32 i = 0; i < numNodes; i++) + const size_t numNodes = GetNumEnabledNodes(); + for (size_t i = 0; i < numNodes; i++) { - nodeNr = GetEnabledNode(i); + const uint16 nodeNr = GetEnabledNode(i); Node* curNode = skeleton->GetNode(nodeNr); Mesh* mesh = mActor->GetMesh(lodLevel, nodeNr); if (mesh == nullptr) @@ -917,17 +892,16 @@ namespace EMotionFX } // check intersection with a ray, but don't get the intersection point or closest intersecting node - Node* ActorInstance::IntersectsMesh(uint32 lodLevel, const MCore::Ray& ray) const + Node* ActorInstance::IntersectsMesh(size_t lodLevel, const MCore::Ray& ray) const { const Pose* pose = mTransformData->GetCurrentPose(); const Skeleton* skeleton = mActor->GetSkeleton(); // for all nodes - uint16 nodeNr; - const uint32 numNodes = GetNumEnabledNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = GetNumEnabledNodes(); + for (size_t i = 0; i < numNodes; ++i) { - nodeNr = GetEnabledNode(i); + const uint16 nodeNr = GetEnabledNode(i); Node* node = skeleton->GetNode(nodeNr); // check if there is a mesh for this node @@ -968,7 +942,7 @@ namespace EMotionFX } // intersection test that returns the closest intersection - Node* ActorInstance::IntersectsMesh(uint32 lodLevel, const MCore::Ray& ray, AZ::Vector3* outIntersect, AZ::Vector3* outNormal, AZ::Vector2* outUV, float* outBaryU, float* outBaryV, uint32* outIndices) const + Node* ActorInstance::IntersectsMesh(size_t lodLevel, const MCore::Ray& ray, AZ::Vector3* outIntersect, AZ::Vector3* outNormal, AZ::Vector2* outUV, float* outBaryU, float* outBaryV, uint32* outIndices) const { Node* closestNode = nullptr; AZ::Vector3 point; @@ -983,11 +957,10 @@ namespace EMotionFX const Skeleton* skeleton = mActor->GetSkeleton(); // check all nodes - uint16 nodeNr; - const uint32 numNodes = GetNumEnabledNodes(); - for (uint32 i = 0; i < numNodes; i++) + const size_t numNodes = GetNumEnabledNodes(); + for (size_t i = 0; i < numNodes; i++) { - nodeNr = GetEnabledNode(i); + const uint16 nodeNr = GetEnabledNode(i); Node* curNode = skeleton->GetNode(nodeNr); Mesh* mesh = mActor->GetMesh(lodLevel, nodeNr); if (mesh == nullptr) @@ -1094,12 +1067,12 @@ namespace EMotionFX // find the location where to insert (as the flattened hierarchy needs to be preserved in the array) bool found = false; - uint32 curNode = nodeIndex; + size_t curNode = nodeIndex; do { // get the parent of the current node - uint32 parentIndex = skeleton->GetNode(curNode)->GetParentIndex(); - if (parentIndex != MCORE_INVALIDINDEX32) + size_t parentIndex = skeleton->GetNode(curNode)->GetParentIndex(); + if (parentIndex != InvalidIndex) { const auto parentArrayIter = AZStd::find(begin(mEnabledNodes), end(mEnabledNodes), static_cast(parentIndex)); if (parentArrayIter != end(mEnabledNodes)) @@ -1141,12 +1114,8 @@ namespace EMotionFX // enable all nodes void ActorInstance::EnableAllNodes() { - const uint32 numNodes = mActor->GetNumNodes(); - mEnabledNodes.resize(numNodes); - for (uint32 i = 0; i < numNodes; ++i) - { - mEnabledNodes[i] = static_cast(i); - } + mEnabledNodes.resize(mActor->GetNumNodes()); + std::iota(mEnabledNodes.begin(), mEnabledNodes.end(), 0); } // disable all nodes @@ -1156,10 +1125,10 @@ namespace EMotionFX } // change the skeletal LOD level - void ActorInstance::SetSkeletalLODLevelNodeFlags(uint32 level) + void ActorInstance::SetSkeletalLODLevelNodeFlags(size_t level) { - // make sure the lod level is in range of 0..31 - const uint32 newLevel = MCore::Clamp(level, 0, 31); + // make sure the lod level is in range of 0..63 + const size_t newLevel = MCore::Clamp(level, 0, 63); // if the lod level is the same as it currently is, do nothing if (newLevel == mLODLevel) @@ -1170,8 +1139,8 @@ namespace EMotionFX Skeleton* skeleton = mActor->GetSkeleton(); // change the state of all nodes that need state changes - const uint32 numNodes = GetNumNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = GetNumNodes(); + for (size_t i = 0; i < numNodes; ++i) { Node* node = skeleton->GetNode(i); @@ -1194,7 +1163,7 @@ namespace EMotionFX } } - void ActorInstance::SetLODLevel(uint32 level) + void ActorInstance::SetLODLevel(size_t level) { m_requestedLODLevel = level; } @@ -1208,14 +1177,7 @@ namespace EMotionFX SetSkeletalLODLevelNodeFlags(m_requestedLODLevel); // Make sure the LOD level is valid and update it. - mLODLevel = MCore::Clamp(m_requestedLODLevel, 0, mActor->GetNumLODLevels() - 1); - - /*// update the transform data - MorphSetup* morphSetup = mActor->GetMorphSetup(mLODLevel); - if (morphSetup) - mTransformData->SetNumMorphWeights( morphSetup->GetNumMorphTargets() ); - else - mTransformData->SetNumMorphWeights( 0 );*/ + mLODLevel = MCore::Clamp(m_requestedLODLevel, 0, mActor->GetNumLODLevels() - 1); } } @@ -1224,8 +1186,8 @@ namespace EMotionFX { // change the state of all nodes that need state changes Skeleton* skeleton = mActor->GetSkeleton(); - const uint32 numNodes = skeleton->GetNumNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = skeleton->GetNumNodes(); + for (size_t i = 0; i < numNodes; ++i) { Node* node = skeleton->GetNode(i); @@ -1242,15 +1204,15 @@ namespace EMotionFX } // calculate the number of disabled nodes for a given skeletal lod level - uint32 ActorInstance::CalcNumDisabledNodes(uint32 skeletalLODLevel) const + size_t ActorInstance::CalcNumDisabledNodes(size_t skeletalLODLevel) const { uint32 numDisabledNodes = 0; - Skeleton* skeleton = mActor->GetSkeleton(); + const Skeleton* skeleton = mActor->GetSkeleton(); // get the number of nodes and iterate through them - const uint32 numNodes = GetNumNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = GetNumNodes(); + for (size_t i = 0; i < numNodes; ++i) { // get the current node Node* node = skeleton->GetNode(i); @@ -1266,14 +1228,14 @@ namespace EMotionFX } // calculate the number of skeletal LOD levels - uint32 ActorInstance::CalcNumSkeletalLODLevels() const + size_t ActorInstance::CalcNumSkeletalLODLevels() const { - uint32 numSkeletalLODLevels = 0; + size_t numSkeletalLODLevels = 0; // iterate over all skeletal LOD levels - uint32 currentNumDisabledNodes = 0; - uint32 previousNumDisabledNodes = MCORE_INVALIDINDEX32; - for (uint32 i = 0; i < 32; ++i) + size_t currentNumDisabledNodes = 0; + size_t previousNumDisabledNodes = InvalidIndex; + for (size_t i = 0; i < sizeof(size_t) * 8; ++i) { // get the number of disabled nodes in the current skeletal LOD level currentNumDisabledNodes = CalcNumDisabledNodes(i); @@ -1471,7 +1433,7 @@ namespace EMotionFX return mActor; } - void ActorInstance::SetID(uint32 id) + void ActorInstance::SetID(size_t id) { mID = id; } @@ -1481,7 +1443,7 @@ namespace EMotionFX return mMotionSystem; } - uint32 ActorInstance::GetLODLevel() const + size_t ActorInstance::GetLODLevel() const { return mLODLevel; } @@ -1592,7 +1554,7 @@ namespace EMotionFX return mAttachments.size(); } - Attachment* ActorInstance::GetAttachment(uint32 nr) const + Attachment* ActorInstance::GetAttachment(size_t nr) const { return mAttachments[nr]; } @@ -1617,7 +1579,7 @@ namespace EMotionFX return mDependencies.size(); } - Actor::Dependency* ActorInstance::GetDependency(uint32 nr) + Actor::Dependency* ActorInstance::GetDependency(size_t nr) { return &mDependencies[nr]; } @@ -1779,10 +1741,9 @@ namespace EMotionFX SetIsVisible(isVisible); // recurse to all child attachments - const uint32 numAttachments = mAttachments.size(); - for (uint32 i = 0; i < numAttachments; ++i) + for (Attachment* mAttachment : mAttachments) { - mAttachments[i]->GetAttachmentActorInstance()->RecursiveSetIsVisible(isVisible); + mAttachment->GetAttachmentActorInstance()->RecursiveSetIsVisible(isVisible); } } @@ -1846,8 +1807,8 @@ namespace EMotionFX } // Iterate down the chain of attachments. - const AZ::u32 numAttachments = GetNumAttachments(); - for (AZ::u32 i = 0; i < numAttachments; ++i) + const size_t numAttachments = GetNumAttachments(); + for (size_t i = 0; i < numAttachments; ++i) { if (GetAttachment(i)->GetAttachmentActorInstance()->RecursiveHasAttachment(attachmentInstance)) { diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.h b/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.h index c6bd84c0c8..620ecc29c5 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.h @@ -75,13 +75,13 @@ namespace EMotionFX * Get the unique identification number for the actor instance. * @return The unique identification number. */ - MCORE_INLINE uint32 GetID() const { return mID; } + MCORE_INLINE size_t GetID() const { return mID; } /** * Set the unique identification number for the actor instance. * @param[in] id The unique identification number. */ - void SetID(uint32 id); + void SetID(size_t id); /** * Get the motion system of this actor instance. @@ -181,7 +181,7 @@ namespace EMotionFX * @param[in] skeletalLODLevel The skeletal LOD level to calculate the number of disabled nodes for. * @return The number of disabled nodes for the given skeletal LOD level. */ - uint32 CalcNumDisabledNodes(uint32 skeletalLODLevel) const; + size_t CalcNumDisabledNodes(size_t skeletalLODLevel) const; /** * Calculate the number of used skeletal LOD levels. Each actor instance alsways has 32 skeletal LOD levels while in most cases @@ -189,7 +189,7 @@ namespace EMotionFX * relative to the previous LOD level. * @return The number of actually used skeletal LOD levels. */ - uint32 CalcNumSkeletalLODLevels() const; + size_t CalcNumSkeletalLODLevels() const; /** * Get the current used geometry and skeletal detail level. @@ -199,13 +199,13 @@ namespace EMotionFX * are needed. * @result The current LOD level. */ - uint32 GetLODLevel() const; + size_t GetLODLevel() const; /** * Set the current geometry and skeletal detail level, where 0 is the highest detail. * @param level The LOD level. Values higher than [GetNumGeometryLODLevels()-1] will be clamped to the maximum LOD. */ - void SetLODLevel(uint32 level); + void SetLODLevel(size_t level); //-------------------------------- @@ -423,7 +423,7 @@ namespace EMotionFX * 4th vertex will be included in the bounds calculation, so only processing 25% of the total number of vertices. The same goes for * node based bounds, but then it will process every 4th node. Of course higher values produce less accurate results, but are faster to process. */ - void UpdateBounds(uint32 geomLODLevel, EBoundsType boundsType = BOUNDS_NODE_BASED, uint32 itemFrequency = 1); + void UpdateBounds(size_t geomLODLevel, EBoundsType boundsType = BOUNDS_NODE_BASED, uint32 itemFrequency = 1); /** * Update the base static axis aligned bounding box shape. @@ -465,7 +465,7 @@ namespace EMotionFX * @param vertexFrequency This includes every "vertexFrequency"-th vertex. So for example a value of 2 would skip every second vertex and * so will process half of the vertices. A value of 4 would process only each 4th vertex, etc. */ - void CalcMeshBasedAabb(uint32 geomLODLevel, AZ::Aabb* outResult, uint32 vertexFrequency = 1); + void CalcMeshBasedAabb(size_t geomLODLevel, AZ::Aabb* outResult, uint32 vertexFrequency = 1); /** * Get the axis aligned bounding box. @@ -568,7 +568,7 @@ namespace EMotionFX * When you set this to false, it will not be deleted from memory, but only removed from the array of attachments * that is stored locally inside this actor instance. */ - void RemoveAttachment(uint32 nr, bool delFromMem = true); + void RemoveAttachment(size_t nr, bool delFromMem = true); /** * Remove all attachments from this actor instance. @@ -593,7 +593,7 @@ namespace EMotionFX * @result Returns the attachment number, in range of [0..GetNumAttachments()-1], or MCORE_INVALIDINDEX32 when no attachment * using the specified actor instance can be found. */ - uint32 FindAttachmentNr(ActorInstance* actorInstance); + size_t FindAttachmentNr(ActorInstance* actorInstance); /** * Get the number of attachments that have been added to this actor instance. @@ -606,7 +606,7 @@ namespace EMotionFX * @param nr The attachment number, which must be in range of [0..GetNumAttachments()-1]. * @result A pointer to the attachment. */ - Attachment* GetAttachment(uint32 nr) const; + Attachment* GetAttachment(size_t nr) const; /** * Check whether this actor instance also is an attachment or not. @@ -671,7 +671,7 @@ namespace EMotionFX * @param nr The dependency number to get, which must be in range of [0..GetNumDependencies()]. * @result A pointer to the dependency. */ - Actor::Dependency* GetDependency(uint32 nr); + Actor::Dependency* GetDependency(size_t nr); /** * Get the morph setup instance. @@ -692,7 +692,7 @@ namespace EMotionFX * @param ray The ray to check. * @return A pointer to the node we detected the first intersection with (doesn't have to be the closest), or nullptr when no intersection found. */ - Node* IntersectsCollisionMesh(uint32 lodLevel, const MCore::Ray& ray) const; + Node* IntersectsCollisionMesh(size_t lodLevel, const MCore::Ray& ray) const; /** * Check for an intersection between the collision mesh of this actor and a given ray, and calculate the closest intersection point. @@ -711,7 +711,7 @@ namespace EMotionFX * A value of nullptr is allowed, which will skip storing the resulting triangle indices. * @return A pointer to the node we detected the closest intersection with, or nullptr when no intersection found. */ - Node* IntersectsCollisionMesh(uint32 lodLevel, const MCore::Ray& ray, AZ::Vector3* outIntersect, AZ::Vector3* outNormal = nullptr, AZ::Vector2* outUV = nullptr, float* outBaryU = nullptr, float* outBaryV = nullptr, uint32* outIndices = nullptr) const; + Node* IntersectsCollisionMesh(size_t lodLevel, const MCore::Ray& ray, AZ::Vector3* outIntersect, AZ::Vector3* outNormal = nullptr, AZ::Vector2* outUV = nullptr, float* outBaryU = nullptr, float* outBaryV = nullptr, uint32* outIndices = nullptr) const; /** * Check for an intersection between the real mesh (if present) of this actor and a given ray. @@ -721,7 +721,7 @@ namespace EMotionFX * @param ray The ray to test with. * @return Returns a pointer to itself when an intersection occurred, or nullptr when no intersection found. */ - Node* IntersectsMesh(uint32 lodLevel, const MCore::Ray& ray) const; + Node* IntersectsMesh(size_t lodLevel, const MCore::Ray& ray) const; /** * Checks for an intersection between the real mesh (if present) of this actor and a given ray. @@ -741,7 +741,7 @@ namespace EMotionFX * A value of nullptr is allowed, which will skip storing the resulting triangle indices. * @return A pointer to the node we detected the closest intersection with, or nullptr when no intersection found. */ - Node* IntersectsMesh(uint32 lodLevel, const MCore::Ray& ray, AZ::Vector3* outIntersect, AZ::Vector3* outNormal = nullptr, AZ::Vector2* outUV = nullptr, float* outBaryU = nullptr, float* outBaryV = nullptr, uint32* outStartIndex = nullptr) const; + Node* IntersectsMesh(size_t lodLevel, const MCore::Ray& ray, AZ::Vector3* outIntersect, AZ::Vector3* outNormal = nullptr, AZ::Vector2* outUV = nullptr, float* outBaryU = nullptr, float* outBaryV = nullptr, uint32* outStartIndex = nullptr) const; void SetRagdoll(Physics::Ragdoll* ragdoll); RagdollInstance* GetRagdollInstance() const; @@ -856,7 +856,7 @@ namespace EMotionFX float GetMotionSamplingTimer() const; float GetMotionSamplingRate() const; - MCORE_INLINE uint32 GetNumNodes() const { return mActor->GetSkeleton()->GetNumNodes(); } + MCORE_INLINE size_t GetNumNodes() const { return mActor->GetSkeleton()->GetNumNodes(); } void UpdateVisualizeScale(); // not automatically called on creation for performance reasons (this method relatively is slow as it updates all meshes) float GetVisualizeScale() const; @@ -892,10 +892,10 @@ namespace EMotionFX float mMotionSamplingRate; /**< The motion sampling rate in seconds, where 0.1 would mean to update 10 times per second. A value of 0 or lower means to update every frame. */ float mMotionSamplingTimer; /**< The time passed since the last time we sampled motions/anim graphs. */ float mVisualizeScale; /**< Some visualization scale factor when rendering for example normals, to be at a nice size, relative to the character. */ - uint32 mLODLevel; /**< The current LOD level, where 0 is the highest detail. */ - uint32 m_requestedLODLevel; /**< Requested LOD level. The actual LOD level will be updated as soon as all transforms for the requested LOD level are ready. */ + size_t mLODLevel; /**< The current LOD level, where 0 is the highest detail. */ + size_t m_requestedLODLevel; /**< Requested LOD level. The actual LOD level will be updated as soon as all transforms for the requested LOD level are ready. */ uint32 mBoundsUpdateItemFreq; /**< The bounds update item counter step size. A value of 1 means every vertex/node, a value of 2 means every second vertex/node, etc. */ - uint32 mID; /**< The unique identification number for the actor instance. */ + size_t mID; /**< The unique identification number for the actor instance. */ uint32 mThreadIndex; /**< The thread index. This specifies the thread number this actor instance is being processed in. */ EBoundsType mBoundsUpdateType; /**< The bounds update type (node based, mesh based or collision mesh based). */ float m_boundsExpandBy = 0.25f; /**< Expand bounding box by normalized percentage. (Default: 25% greater than the calculated bounding box) */ @@ -1002,7 +1002,7 @@ namespace EMotionFX * are needed. * @param level The skeletal detail LOD level. Values higher than 31 will be automatically clamped to 31. */ - void SetSkeletalLODLevelNodeFlags(uint32 level); + void SetSkeletalLODLevelNodeFlags(size_t level); /* * Update the LOD level in case a change was requested. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/SubMesh.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/SubMesh.cpp index fa60ed4033..d18006527f 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/SubMesh.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/SubMesh.cpp @@ -19,7 +19,7 @@ namespace EMotionFX // constructor - SubMesh::SubMesh(Mesh* parentMesh, uint32 startVertex, uint32 startIndex, uint32 startPolygon, uint32 numVerts, uint32 numIndices, uint32 numPolygons, uint32 materialIndex, uint32 numBones) + SubMesh::SubMesh(Mesh* parentMesh, uint32 startVertex, uint32 startIndex, uint32 startPolygon, uint32 numVerts, uint32 numIndices, uint32 numPolygons, uint32 materialIndex, size_t numBones) { mParentMesh = parentMesh; mNumVertices = numVerts; @@ -41,7 +41,7 @@ namespace EMotionFX // create - SubMesh* SubMesh::Create(Mesh* parentMesh, uint32 startVertex, uint32 startIndex, uint32 startPolygon, uint32 numVerts, uint32 numIndices, uint32 numPolygons, uint32 materialIndex, uint32 numBones) + SubMesh* SubMesh::Create(Mesh* parentMesh, uint32 startVertex, uint32 startIndex, uint32 startPolygon, uint32 numVerts, uint32 numIndices, uint32 numPolygons, uint32 materialIndex, size_t numBones) { return aznew SubMesh(parentMesh, startVertex, startIndex, startPolygon, numVerts, numIndices, numPolygons, materialIndex, numBones); } @@ -57,20 +57,9 @@ namespace EMotionFX // remap bone (oldNodeNr) to bone (newNodeNr) - void SubMesh::RemapBone(uint16 oldNodeNr, uint16 newNodeNr) + void SubMesh::RemapBone(size_t oldNodeNr, size_t newNodeNr) { - // get the number of bones stored inside the submesh - const uint32 numBones = mBones.size(); - - // iterate through all bones and remap the bones - for (uint32 i = 0; i < numBones; ++i) - { - // remap the bone - if (mBones[i] == oldNodeNr) - { - mBones[i] = newNodeNr; - } - } + AZStd::replace(mBones.begin(), mBones.end(), oldNodeNr, newNodeNr); } @@ -97,7 +86,7 @@ namespace EMotionFX { // if the bone is disabled SkinInfluence* influence = skinLayer->GetInfluence(orgVertex, i); - const uint32 nodeNr = influence->GetNodeNr(); + const uint16 nodeNr = influence->GetNodeNr(); // put the node index in the bones array in case it isn't in already if (AZStd::find(begin(mBones), end(mBones), nodeNr) == end(mBones)) @@ -228,29 +217,21 @@ namespace EMotionFX } - uint32 SubMesh::FindBoneIndex(uint32 nodeNr) const + size_t SubMesh::FindBoneIndex(size_t nodeNr) const { - const uint32 numBones = mBones.size(); - for (uint32 i = 0; i < numBones; ++i) - { - if (mBones[i] == nodeNr) - { - return i; - } - } - - return MCORE_INVALIDINDEX32; + const auto foundBone = AZStd::find(mBones.begin(), mBones.end(), nodeNr); + return foundBone != mBones.end() ? AZStd::distance(mBones.begin(), foundBone) : InvalidIndex; } // remove the given bone - void SubMesh::RemoveBone(uint16 index) + void SubMesh::RemoveBone(size_t index) { mBones.erase(AZStd::next(begin(mBones), index)); } - void SubMesh::SetNumBones(uint32 numBones) + void SubMesh::SetNumBones(size_t numBones) { if (numBones == 0) { @@ -263,7 +244,7 @@ namespace EMotionFX } - void SubMesh::SetBone(uint32 index, uint32 nodeIndex) + void SubMesh::SetBone(size_t index, size_t nodeIndex) { mBones[index] = nodeIndex; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/SubMesh.h b/Gems/EMotionFX/Code/EMotionFX/Source/SubMesh.h index 9455b6b7df..d234a9e4c1 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/SubMesh.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/SubMesh.h @@ -55,7 +55,7 @@ namespace EMotionFX * @param materialIndex The material. * @param numBones The number of bones inside the submesh. */ - static SubMesh* Create(Mesh* parentMesh, uint32 startVertex, uint32 startIndex, uint32 startPolygon, uint32 numVerts, uint32 numIndices, uint32 numPolygons, uint32 materialIndex, uint32 numBones); + static SubMesh* Create(Mesh* parentMesh, uint32 startVertex, uint32 startIndex, uint32 startPolygon, uint32 numVerts, uint32 numIndices, uint32 numPolygons, uint32 materialIndex, size_t numBones); /** * Get the start index. This is the offset in the index array of the parent mesh where the index data for this @@ -178,14 +178,14 @@ namespace EMotionFX * Set the number of bones that is being used by this submesh. * @param numBones The number of bones used by the submesh. */ - void SetNumBones(uint32 numBones); + void SetNumBones(size_t numBones); /** * Set the index of a given bone. * @param index The bone number, which must be in range of [0..GetNumBones()-1]. * @param nodeIndex The node index number that acts as bone on this submesh. */ - void SetBone(uint32 index, uint32 nodeIndex); + void SetBone(size_t index, size_t nodeIndex); /** * Get the number of bones used by this submesh. @@ -236,20 +236,20 @@ namespace EMotionFX * @result The bone number inside the submesh, which is in range of [0..GetNumBones()-1]. * A value of MCORE_INVALIDINDEX32 is returned when the specified node isn't used as bone inside this submesh. */ - uint32 FindBoneIndex(uint32 nodeNr) const; + size_t FindBoneIndex(size_t nodeNr) const; /** * Remap bone to a new bone. This will overwrite the given old bones with the new one. * @param oldNodeNr The node number to be searched and replaced. * @param newNodeNr The node number with which the old bones will be replaced with. */ - void RemapBone(uint16 oldNodeNr, uint16 newNodeNr); + void RemapBone(size_t oldNodeNr, size_t newNodeNr); /** * Remove the given bone from the bones list. * @param index The index of the bone to be removed in range of [0..GetNumBones()-1]. */ - void RemoveBone(uint16 index); + void RemoveBone(size_t index); /** * Clone the submesh. @@ -290,7 +290,7 @@ namespace EMotionFX * @param materialIndex The material. * @param numBones The number of bones inside the submesh. */ - SubMesh(Mesh* parentMesh, uint32 startVertex, uint32 startIndex, uint32 startPolygon, uint32 numVerts, uint32 numIndices, uint32 numPolygons, uint32 materialIndex, uint32 numBones); + SubMesh(Mesh* parentMesh, uint32 startVertex, uint32 startIndex, uint32 startPolygon, uint32 numVerts, uint32 numIndices, uint32 numPolygons, uint32 materialIndex, size_t numBones); /** * Destructor. From 4034195bdcce34f041298402a3477f28b5125114 Mon Sep 17 00:00:00 2001 From: Chris Burel Date: Mon, 24 May 2021 12:04:16 -0700 Subject: [PATCH 205/803] Convert EMotionFX runtime uint32 -> size_t This allows the EMotionFX runtime to compile with `/we4267` enabled, which emits a warning when converting from `size_t` to a smaller type. All tests for the runtime have been updated accordingly, and they pass. In instances where a range-for loop could be used, or a std algorithm, that was used instead of using `size_t numItems = vec.size()` and a for loop. Casts to `uint32` were removed where possible. Some places remain, like in the file formats. Signed-off-by: Chris Burel --- .../CommandSystem/Source/ActorCommands.cpp | 93 +++-- .../CommandSystem/Source/ActorCommands.h | 8 +- .../Source/ActorInstanceCommands.cpp | 22 +- .../Source/ActorInstanceCommands.h | 4 +- .../Source/AnimGraphCommands.cpp | 30 +- .../Source/AnimGraphConnectionCommands.cpp | 44 +-- .../Source/AnimGraphConnectionCommands.h | 16 +- .../Source/AnimGraphNodeCommands.cpp | 71 ++-- .../Source/AnimGraphNodeGroupCommands.cpp | 26 +- .../Source/AnimGraphParameterCommands.cpp | 22 +- .../Source/AnimGraphParameterCommands.h | 4 +- .../Source/AttachmentCommands.cpp | 10 +- .../CommandSystem/Source/MetaData.cpp | 19 +- .../CommandSystem/Source/MotionCommands.cpp | 47 ++- .../CommandSystem/Source/MotionCommands.h | 6 +- .../Source/MotionEventCommands.cpp | 38 +- .../Source/MotionEventCommands.h | 18 +- .../Source/MotionSetCommands.cpp | 55 ++- .../Source/SelectionCommands.cpp | 38 +- .../CommandSystem/Source/SelectionList.cpp | 63 ++- .../CommandSystem/Source/SelectionList.h | 38 +- .../Source/SimulatedObjectCommands.cpp | 20 +- .../Source/SimulatedObjectCommands.h | 23 +- .../Exporters/ExporterLib/Exporter/Exporter.h | 4 +- .../Exporter/MorphTargetExport.cpp | 47 ++- .../ExporterLib/Exporter/NodeExport.cpp | 89 ++--- .../EMotionFX/Code/EMotionFX/Source/Actor.cpp | 9 +- .../Code/EMotionFX/Source/ActorInstance.cpp | 6 +- .../Code/EMotionFX/Source/ActorInstance.h | 6 +- .../Code/EMotionFX/Source/ActorManager.cpp | 67 +--- .../Code/EMotionFX/Source/ActorManager.h | 18 +- .../EMotionFX/Source/ActorUpdateScheduler.h | 18 +- .../Code/EMotionFX/Source/AnimGraph.cpp | 83 ++-- .../Code/EMotionFX/Source/AnimGraph.h | 40 +- .../Source/AnimGraphAttributeTypes.cpp | 2 +- .../Source/AnimGraphAttributeTypes.h | 2 +- .../EMotionFX/Source/AnimGraphEventBuffer.cpp | 12 +- .../EMotionFX/Source/AnimGraphEventBuffer.h | 10 +- .../EMotionFX/Source/AnimGraphInstance.cpp | 131 +++---- .../Code/EMotionFX/Source/AnimGraphInstance.h | 66 ++-- .../EMotionFX/Source/AnimGraphManager.cpp | 24 +- .../Code/EMotionFX/Source/AnimGraphManager.h | 8 +- .../Source/AnimGraphMotionCondition.cpp | 4 +- .../Code/EMotionFX/Source/AnimGraphNode.cpp | 302 ++++++-------- .../Code/EMotionFX/Source/AnimGraphNode.h | 170 ++++---- .../EMotionFX/Source/AnimGraphNodeData.cpp | 4 +- .../Code/EMotionFX/Source/AnimGraphNodeData.h | 6 +- .../EMotionFX/Source/AnimGraphNodeGroup.cpp | 14 +- .../EMotionFX/Source/AnimGraphNodeGroup.h | 12 +- .../Code/EMotionFX/Source/AnimGraphObject.cpp | 6 +- .../Code/EMotionFX/Source/AnimGraphObject.h | 12 +- .../Code/EMotionFX/Source/AnimGraphPose.h | 2 +- .../EMotionFX/Source/AnimGraphPosePool.cpp | 29 +- .../Code/EMotionFX/Source/AnimGraphPosePool.h | 8 +- .../Source/AnimGraphRefCountedDataPool.cpp | 25 +- .../Source/AnimGraphRefCountedDataPool.h | 8 +- .../Source/AnimGraphReferenceNode.cpp | 6 +- .../EMotionFX/Source/AnimGraphSnapshot.cpp | 18 +- .../Source/AnimGraphStateMachine.cpp | 14 +- .../EMotionFX/Source/AnimGraphStateMachine.h | 2 +- .../Source/AnimGraphStateTransition.cpp | 4 +- .../EMotionFX/Source/AnimGraphSyncTrack.cpp | 32 +- .../Code/EMotionFX/Source/AttachmentNode.cpp | 6 +- .../Code/EMotionFX/Source/AttachmentNode.h | 8 +- .../Code/EMotionFX/Source/AttachmentSkin.cpp | 14 +- .../Code/EMotionFX/Source/AttachmentSkin.h | 12 +- .../Code/EMotionFX/Source/BlendTree.cpp | 4 +- .../Source/BlendTreeAccumTransformNode.cpp | 2 +- .../Source/BlendTreeAccumTransformNode.h | 2 +- .../Source/BlendTreeBlend2AdditiveNode.cpp | 2 +- .../Source/BlendTreeBlend2LegacyNode.cpp | 4 +- .../EMotionFX/Source/BlendTreeBlend2Node.cpp | 2 +- .../Source/BlendTreeBlend2NodeBase.cpp | 2 +- .../Source/BlendTreeBlend2NodeBase.h | 2 +- .../EMotionFX/Source/BlendTreeFootIKNode.cpp | 20 +- .../Source/BlendTreeGetTransformNode.cpp | 6 +- .../Source/BlendTreeGetTransformNode.h | 2 +- .../EMotionFX/Source/BlendTreeLookAtNode.cpp | 8 +- .../EMotionFX/Source/BlendTreeLookAtNode.h | 2 +- .../Source/BlendTreeMaskLegacyNode.cpp | 24 +- .../Source/BlendTreeMaskLegacyNode.h | 2 +- .../EMotionFX/Source/BlendTreeMaskNode.cpp | 26 +- .../Code/EMotionFX/Source/BlendTreeMaskNode.h | 6 +- .../Source/BlendTreeMirrorPoseNode.cpp | 6 +- .../Source/BlendTreeMorphTargetNode.cpp | 10 +- .../Source/BlendTreeMorphTargetNode.h | 4 +- .../EMotionFX/Source/BlendTreeRagdollNode.cpp | 4 +- .../BlendTreeRagdollStrengthModifierNode.h | 2 +- .../Source/BlendTreeSetTransformNode.cpp | 6 +- .../Source/BlendTreeSetTransformNode.h | 2 +- .../Source/BlendTreeTransformNode.cpp | 2 +- .../EMotionFX/Source/BlendTreeTransformNode.h | 2 +- .../Source/BlendTreeTwoLinkIKNode.cpp | 38 +- .../EMotionFX/Source/BlendTreeTwoLinkIKNode.h | 12 +- .../Code/EMotionFX/Source/DebugDraw.cpp | 10 +- .../EMotionFX/Source/DualQuatSkinDeformer.cpp | 8 +- .../EMotionFX/Source/DualQuatSkinDeformer.h | 10 +- .../Source/Importer/ChunkProcessors.cpp | 9 +- .../EMotionFX/Source/Importer/Importer.cpp | 49 +-- .../Code/EMotionFX/Source/KeyFrameFinder.h | 4 +- .../Code/EMotionFX/Source/KeyFrameFinder.inl | 14 +- .../EMotionFX/Source/KeyTrackLinearDynamic.h | 28 +- .../Source/KeyTrackLinearDynamic.inl | 97 ++--- Gems/EMotionFX/Code/EMotionFX/Source/Mesh.cpp | 370 +++++------------- Gems/EMotionFX/Code/EMotionFX/Source/Mesh.h | 46 +-- .../Code/EMotionFX/Source/MeshDeformer.h | 2 +- .../EMotionFX/Source/MeshDeformerStack.cpp | 118 ++---- .../Code/EMotionFX/Source/MeshDeformerStack.h | 10 +- .../EMotionFX/Source/MorphMeshDeformer.cpp | 40 +- .../Code/EMotionFX/Source/MorphMeshDeformer.h | 8 +- .../Code/EMotionFX/Source/MorphSetup.cpp | 105 ++--- .../Code/EMotionFX/Source/MorphSetup.h | 10 +- .../Code/EMotionFX/Source/MorphTarget.cpp | 2 +- .../Code/EMotionFX/Source/MorphTarget.h | 4 +- .../EMotionFX/Source/MorphTargetStandard.cpp | 79 ++-- .../EMotionFX/Source/MorphTargetStandard.h | 16 +- .../Code/EMotionFX/Source/Motion.cpp | 2 +- .../Source/MotionData/MotionData.cpp | 26 +- .../EMotionFX/Source/MotionData/MotionData.h | 16 +- .../MotionData/NonUniformMotionData.cpp | 24 +- .../Source/MotionData/NonUniformMotionData.h | 2 +- .../Source/MotionData/UniformMotionData.cpp | 26 +- .../Source/MotionData/UniformMotionData.h | 2 +- .../Code/EMotionFX/Source/MotionInstance.cpp | 10 +- .../Code/EMotionFX/Source/MotionInstance.h | 6 +- .../EMotionFX/Source/MotionInstancePool.cpp | 33 +- .../EMotionFX/Source/MotionInstancePool.h | 12 +- .../EMotionFX/Source/MotionLayerSystem.cpp | 77 ++-- .../Code/EMotionFX/Source/MotionLayerSystem.h | 14 +- .../Code/EMotionFX/Source/MotionManager.cpp | 314 ++++----------- .../Code/EMotionFX/Source/MotionManager.h | 26 +- .../Code/EMotionFX/Source/MotionQueue.cpp | 6 +- .../Code/EMotionFX/Source/MotionQueue.h | 4 +- .../Code/EMotionFX/Source/MotionSet.cpp | 66 +--- .../Code/EMotionFX/Source/MotionSet.h | 8 +- .../Code/EMotionFX/Source/MotionSystem.cpp | 77 +--- .../Code/EMotionFX/Source/MotionSystem.h | 2 +- .../EMotionFX/Source/MultiThreadScheduler.cpp | 64 ++- .../EMotionFX/Source/MultiThreadScheduler.h | 10 +- Gems/EMotionFX/Code/EMotionFX/Source/Node.cpp | 14 +- Gems/EMotionFX/Code/EMotionFX/Source/Node.h | 12 +- .../Code/EMotionFX/Source/NodeGroup.cpp | 2 +- .../Code/EMotionFX/Source/NodeGroup.h | 2 +- .../Code/EMotionFX/Source/NodeMap.cpp | 4 +- .../EMotionFX/Code/EMotionFX/Source/NodeMap.h | 8 +- .../Code/EMotionFX/Source/PhysicsSetup.cpp | 6 +- Gems/EMotionFX/Code/EMotionFX/Source/Pose.cpp | 2 +- .../Code/EMotionFX/Source/PoseDataRagdoll.cpp | 2 +- .../Code/EMotionFX/Source/RagdollInstance.cpp | 22 +- .../Code/EMotionFX/Source/RagdollInstance.h | 8 +- .../Code/EMotionFX/Source/Recorder.cpp | 245 +++++------- .../Code/EMotionFX/Source/Recorder.h | 63 ++- .../Source/RepositioningLayerPass.cpp | 6 +- .../EMotionFX/Source/RepositioningLayerPass.h | 4 +- .../EMotionFX/Source/SimulatedObjectSetup.cpp | 60 +-- .../EMotionFX/Source/SimulatedObjectSetup.h | 22 +- .../Source/SingleThreadScheduler.cpp | 19 +- .../EMotionFX/Source/SingleThreadScheduler.h | 6 +- .../SkinningInfoVertexAttributeLayer.cpp | 10 +- .../Source/SkinningInfoVertexAttributeLayer.h | 2 +- .../EMotionFX/Source/SoftSkinDeformer.cpp | 10 +- .../Code/EMotionFX/Source/SoftSkinDeformer.h | 20 +- .../EMotionFX/Source/StandardMaterial.cpp | 30 +- .../Code/EMotionFX/Source/StandardMaterial.h | 10 +- .../Code/EMotionFX/Source/TransformData.cpp | 14 +- .../Code/EMotionFX/Source/TransformData.h | 14 +- .../EMStudioSDK/Source/PluginManager.cpp | 117 ++---- .../EMStudioSDK/Source/PluginManager.h | 14 +- .../Source/TimeView/TimeTrack.cpp | 44 +-- .../Source/TimeView/TimeTrack.h | 10 +- .../Integration/AnimGraphComponentBus.h | 44 +-- .../Code/MCore/Source/MultiThreadManager.h | 16 + .../Code/MCore/Source/StringIdPool.cpp | 4 +- .../Integration/Components/ActorComponent.cpp | 14 +- .../Components/AnimGraphComponent.cpp | 122 +++--- .../Components/AnimGraphComponent.h | 32 +- .../Integration/System/SystemComponent.cpp | 8 +- .../Code/Tests/AnimGraphComponentBusTests.cpp | 82 ++-- .../Code/Tests/AnimGraphEventTests.cpp | 4 +- .../Tests/AnimGraphNodeEventFilterTests.cpp | 2 +- .../Tests/AnimGraphNodeProcessingTests.cpp | 2 +- .../Tests/AnimGraphParameterActionTests.cpp | 13 +- ...nimGraphParameterConditionCommandTests.cpp | 2 +- .../Code/Tests/AnimGraphRefCountTests.cpp | 4 +- .../Code/Tests/AnimGraphSyncTrackTests.cpp | 8 +- .../Code/Tests/AnimGraphTagConditionTests.cpp | 5 +- .../Tests/AnimGraphVector2ConditionTests.cpp | 13 +- .../Code/Tests/BlendTreeFootIKNodeTests.cpp | 18 +- .../Code/Tests/BlendTreeMaskNodeTests.cpp | 10 +- .../Code/Tests/BlendTreeRagdollNodeTests.cpp | 2 +- .../CanAddSimpleMotionComponent.cpp | 2 +- .../Tests/Integration/PoseComparisonTests.cpp | 18 +- .../Code/Tests/KeyTrackLinearTests.cpp | 16 +- Gems/EMotionFX/Code/Tests/Mocks/AnimGraph.h | 2 +- .../Code/Tests/Mocks/AnimGraphInstance.h | 28 +- .../Code/Tests/Mocks/AnimGraphNode.h | 4 +- Gems/EMotionFX/Code/Tests/Mocks/Node.h | 44 +-- .../Code/Tests/Mocks/SimulatedJoint.h | 4 +- .../Code/Tests/Mocks/SimulatedObject.h | 12 +- Gems/EMotionFX/Code/Tests/Mocks/Skeleton.h | 4 +- .../Code/Tests/MorphTargetRuntimeTests.cpp | 2 +- .../Code/Tests/MotionEventTrackTests.cpp | 2 +- .../Code/Tests/NonUniformMotionDataTests.cpp | 22 +- Gems/EMotionFX/Code/Tests/PoseTests.cpp | 102 ++--- .../Code/Tests/Prefabs/LeftArmSkeleton.h | 2 +- .../Code/Tests/QuaternionParameterTests.cpp | 4 +- .../Tests/SimulatedObjectCommandTests.cpp | 20 +- .../Tests/SimulatedObjectSerializeTests.cpp | 2 +- .../EMotionFX/Code/Tests/SkeletalLODTests.cpp | 14 +- .../Code/Tests/UniformMotionDataTests.cpp | 22 +- .../Code/Tests/Vector3ParameterTests.cpp | 6 +- 211 files changed, 2440 insertions(+), 3244 deletions(-) diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ActorCommands.cpp b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ActorCommands.cpp index 52a4ec6a0b..85d9c699e1 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ActorCommands.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ActorCommands.cpp @@ -67,21 +67,21 @@ namespace CommandSystem } else { - EMotionFX::Node* node = skeleton->FindNodeByName(motionExtractionNodeName.c_str()); + EMotionFX::Node* node = skeleton->FindNodeByName(motionExtractionNodeName); actor->SetMotionExtractionNode(node); } // Inform all animgraph nodes about this. - const uint32 numAnimGraphs = EMotionFX::GetAnimGraphManager().GetNumAnimGraphs(); - for (uint32 i = 0; i < numAnimGraphs; ++i) + const size_t numAnimGraphs = EMotionFX::GetAnimGraphManager().GetNumAnimGraphs(); + for (size_t i = 0; i < numAnimGraphs; ++i) { EMotionFX::AnimGraph* animGraph = EMotionFX::GetAnimGraphManager().GetAnimGraph(i); if (animGraph->GetIsOwnedByRuntime()) { continue; } - const uint32 numObjects = animGraph->GetNumObjects(); - for (uint32 n = 0; n < numObjects; ++n) + const size_t numObjects = animGraph->GetNumObjects(); + for (size_t n = 0; n < numObjects; ++n) { animGraph->GetObject(n)->OnActorMotionExtractionNodeChanged(); } @@ -100,7 +100,7 @@ namespace CommandSystem } else { - EMotionFX::Node* node = skeleton->FindNodeByName(retargetRootNodeName.c_str()); + EMotionFX::Node* node = skeleton->FindNodeByName(retargetRootNodeName); actor->SetRetargetRootNode(node); } } @@ -120,8 +120,8 @@ namespace CommandSystem { // Store old attachment nodes for undo. mOldAttachmentNodes = ""; - const uint32 numNodes = actor->GetNumNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = actor->GetNumNodes(); + for (size_t i = 0; i < numNodes; ++i) { EMotionFX::Node* node = skeleton->GetNode(i); if (!node) @@ -150,9 +150,9 @@ namespace CommandSystem // Remove the given nodes from the attachment node list by unsetting the flag. if (AzFramework::StringFunc::Equal(nodeAction.c_str(), "remove")) { - for (size_t i = 0; i < numNodeNames; ++i) + for (const AZStd::string& nodeName : nodeNames) { - EMotionFX::Node* node = skeleton->FindNodeByName(nodeNames[i].c_str()); + EMotionFX::Node* node = skeleton->FindNodeByName(nodeName); if (!node) { continue; @@ -164,9 +164,9 @@ namespace CommandSystem // Add the given nodes to the attachment node list by setting attachment flag. else if (AzFramework::StringFunc::Equal(nodeAction.c_str(), "add")) { - for (size_t i = 0; i < numNodeNames; ++i) + for (const AZStd::string& nodeName : nodeNames) { - EMotionFX::Node* node = skeleton->FindNodeByName(nodeNames[i].c_str()); + EMotionFX::Node* node = skeleton->FindNodeByName(nodeName); if (!node) { continue; @@ -181,9 +181,9 @@ namespace CommandSystem SetIsAttachmentNode(actor, false); // Set attachment node flag based on selection list. - for (size_t i = 0; i < numNodeNames; ++i) + for (const AZStd::string& nodeName : nodeNames) { - EMotionFX::Node* node = skeleton->FindNodeByName(nodeNames[i].c_str()); + EMotionFX::Node* node = skeleton->FindNodeByName(nodeName); if (!node) { continue; @@ -199,8 +199,8 @@ namespace CommandSystem { // Store old nodes for undo. mOldExcludedFromBoundsNodes = ""; - const uint32 numNodes = actor->GetNumNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = actor->GetNumNodes(); + for (size_t i = 0; i < numNodes; ++i) { EMotionFX::Node* node = skeleton->GetNode(i); if (!node) @@ -229,9 +229,9 @@ namespace CommandSystem // Remove the selected nodes from the bounding volume calculations. if (AzFramework::StringFunc::Equal(nodeAction.c_str(), "remove")) { - for (size_t i = 0; i < numNodeNames; ++i) + for (const AZStd::string& nodeName : nodeNames) { - EMotionFX::Node* node = skeleton->FindNodeByName(nodeNames[i].c_str()); + EMotionFX::Node* node = skeleton->FindNodeByName(nodeName); if (!node) { continue; @@ -243,9 +243,9 @@ namespace CommandSystem // Add the given nodes to the bounding volume calculations. if (AzFramework::StringFunc::Equal(nodeAction.c_str(), "add")) { - for (size_t i = 0; i < numNodeNames; ++i) + for (const AZStd::string& nodeName : nodeNames) { - EMotionFX::Node* node = skeleton->FindNodeByName(nodeNames[i].c_str()); + EMotionFX::Node* node = skeleton->FindNodeByName(nodeName); if (!node) { continue; @@ -260,9 +260,9 @@ namespace CommandSystem SetIsExcludedFromBoundsNode(actor, false); // Remove the nodes from bounding volume calculation based on the selection. - for (size_t i = 0; i < numNodeNames; ++i) + for (const AZStd::string& nodeName : nodeNames) { - EMotionFX::Node* node = skeleton->FindNodeByName(nodeNames[i].c_str()); + EMotionFX::Node* node = skeleton->FindNodeByName(nodeName); if (!node) { continue; @@ -294,19 +294,18 @@ namespace CommandSystem AzFramework::StringFunc::Tokenize(mirrorSetupString.c_str(), pairs, ";", false, true); // Parse the mirror setup string, which is like "nodeA,nodeB;nodeC,nodeD;". - const size_t numPairs = pairs.size(); - for (size_t p = 0; p < numPairs; ++p) + for (const AZStd::string& pair : pairs) { // Split the pairs into the node names. AZStd::vector pairValues; - AzFramework::StringFunc::Tokenize(pairs[p].c_str(), pairValues, ",", false, true); + AzFramework::StringFunc::Tokenize(pair.c_str(), pairValues, ",", false, true); if (pairValues.size() != 2) { continue; } - EMotionFX::Node* nodeA = actor->GetSkeleton()->FindNodeByName(pairValues[0].c_str()); - EMotionFX::Node* nodeB = actor->GetSkeleton()->FindNodeByName(pairValues[1].c_str()); + EMotionFX::Node* nodeA = actor->GetSkeleton()->FindNodeByName(pairValues[0]); + EMotionFX::Node* nodeB = actor->GetSkeleton()->FindNodeByName(pairValues[1]); if (nodeA && nodeB) { actor->GetNodeMirrorInfo(nodeA->GetNodeIndex()).mSourceNode = static_cast(nodeB->GetNodeIndex()); @@ -411,8 +410,8 @@ namespace CommandSystem // Static function to set all IsAttachmentNode flags of the actor to the given value. void CommandAdjustActor::SetIsAttachmentNode(EMotionFX::Actor* actor, bool isAttachmentNode) { - const uint32 numNodes = actor->GetNumNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = actor->GetNumNodes(); + for (size_t i = 0; i < numNodes; ++i) { EMotionFX::Node* node = actor->GetSkeleton()->GetNode(i); if (!node) @@ -428,8 +427,8 @@ namespace CommandSystem // Static function to set all IsAttachmentNode flags of the actor to the given value. void CommandAdjustActor::SetIsExcludedFromBoundsNode(EMotionFX::Actor* actor, bool excludedFromBounds) { - const uint32 numNodes = actor->GetNumNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = actor->GetNumNodes(); + for (size_t i = 0; i < numNodes; ++i) { EMotionFX::Node* node = actor->GetSkeleton()->GetNode(i); if (!node) @@ -476,12 +475,12 @@ namespace CommandSystem return false; } - const uint32 numNodes = actor->GetNumNodes(); + const size_t numNodes = actor->GetNumNodes(); EMotionFX::Skeleton* skeleton = actor->GetSkeleton(); // Store the old nodes for the undo. mOldNodeList = ""; - for (uint32 i = 0; i < numNodes; ++i) + for (size_t i = 0; i < numNodes; ++i) { EMotionFX::Mesh* mesh = actor->GetMesh(lod, i); if (mesh && mesh->GetIsCollisionMesh()) @@ -504,7 +503,7 @@ namespace CommandSystem AzFramework::StringFunc::Tokenize(nodeList.c_str(), nodeNames, ";", false, true); // Update the collision mesh flags. - for (uint32 i = 0; i < numNodes; ++i) + for (size_t i = 0; i < numNodes; ++i) { const EMotionFX::Node* node = skeleton->GetNode(i); EMotionFX::Mesh* mesh = actor->GetMesh(lod, i); @@ -574,7 +573,7 @@ namespace CommandSystem { MCORE_UNUSED(parameters); - const uint32 numSelectedActorInstances = GetCommandManager()->GetCurrentSelection().GetNumSelectedActorInstances(); + const size_t numSelectedActorInstances = GetCommandManager()->GetCurrentSelection().GetNumSelectedActorInstances(); if (numSelectedActorInstances == 0) { outResult = "Cannot reset actor instances to bind pose. No actor instance selected."; @@ -582,7 +581,7 @@ namespace CommandSystem } // Iterate through all selected actor instances and reset them to bind pose. - for (uint32 i = 0; i < numSelectedActorInstances; ++i) + for (size_t i = 0; i < numSelectedActorInstances; ++i) { EMotionFX::ActorInstance* actorInstance = GetCommandManager()->GetCurrentSelection().GetActorInstance(i); @@ -792,8 +791,8 @@ namespace CommandSystem } // get number of actors and instances - const uint32 numActors = EMotionFX::GetActorManager().GetNumActors(); - const uint32 numActorInstances = EMotionFX::GetActorManager().GetNumActorInstances(); + const size_t numActors = EMotionFX::GetActorManager().GetNumActors(); + const size_t numActorInstances = EMotionFX::GetActorManager().GetNumActorInstances(); // create the command group MCore::CommandGroup internalCommandGroup("Clear scene"); @@ -811,7 +810,7 @@ namespace CommandSystem if (deleteActors || deleteActorInstances) { // get rid of all actor instances - for (uint32 i = 0; i < numActorInstances; ++i) + for (size_t i = 0; i < numActorInstances; ++i) { // get pointer to the current actor instance EMotionFX::ActorInstance* actorInstance = EMotionFX::GetActorManager().GetActorInstance(i); @@ -847,7 +846,7 @@ namespace CommandSystem if (deleteActors) { // iterate through all available actors - for (uint32 i = 0; i < numActors; ++i) + for (size_t i = 0; i < numActors; ++i) { // get the current actor EMotionFX::Actor* actor = EMotionFX::GetActorManager().GetActor(i); @@ -903,7 +902,7 @@ namespace CommandSystem // walk over the meshes and check which of them we want to set as collision mesh - void PrepareCollisionMeshesNodesString(EMotionFX::Actor* actor, uint32 lod, AZStd::string* outNodeNames) + void PrepareCollisionMeshesNodesString(EMotionFX::Actor* actor, size_t lod, AZStd::string* outNodeNames) { // reset the resulting string outNodeNames->clear(); @@ -922,8 +921,8 @@ namespace CommandSystem } // get the number of nodes and iterate through them - const uint32 numNodes = actor->GetNumNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = actor->GetNumNodes(); + for (size_t i = 0; i < numNodes; ++i) { EMotionFX::Mesh* mesh = actor->GetMesh(lod, i); if (mesh && mesh->GetIsCollisionMesh()) @@ -951,8 +950,8 @@ namespace CommandSystem } // get the number of nodes and iterate through them - const uint32 numNodes = actor->GetNumNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = actor->GetNumNodes(); + for (size_t i = 0; i < numNodes; ++i) { EMotionFX::Node* node = actor->GetSkeleton()->GetNode(i); @@ -1054,8 +1053,8 @@ namespace CommandSystem } // update the static aabb's of all actor instances - const uint32 numActorInstances = EMotionFX::GetActorManager().GetNumActorInstances(); - for (uint32 i = 0; i < numActorInstances; ++i) + const size_t numActorInstances = EMotionFX::GetActorManager().GetNumActorInstances(); + for (size_t i = 0; i < numActorInstances; ++i) { EMotionFX::ActorInstance* actorInstance = EMotionFX::GetActorManager().GetActorInstance(i); if (actorInstance->GetActor() != actor) diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ActorCommands.h b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ActorCommands.h index eec9f7a5c5..94c6e0ff42 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ActorCommands.h +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ActorCommands.h @@ -19,9 +19,9 @@ namespace CommandSystem { // Adjust the given actor. MCORE_DEFINECOMMAND_START(CommandAdjustActor, "Adjust actor", true) - uint32 mOldMotionExtractionNodeIndex; - uint32 mOldRetargetRootNodeIndex; - uint32 mOldTrajectoryNodeIndex; + size_t mOldMotionExtractionNodeIndex; + size_t mOldRetargetRootNodeIndex; + size_t mOldTrajectoryNodeIndex; AZStd::string mOldAttachmentNodes; AZStd::string mOldExcludedFromBoundsNodes; AZStd::string mOldName; @@ -71,6 +71,6 @@ public: // Helper functions ////////////////////////////////////////////////////////////////////////////////////////////////////////// void COMMANDSYSTEM_API ClearScene(bool deleteActors = true, bool deleteActorInstances = true, MCore::CommandGroup* commandGroup = nullptr); - void COMMANDSYSTEM_API PrepareCollisionMeshesNodesString(EMotionFX::Actor* actor, uint32 lod, AZStd::string* outNodeNames); + void COMMANDSYSTEM_API PrepareCollisionMeshesNodesString(EMotionFX::Actor* actor, size_t lod, AZStd::string* outNodeNames); void COMMANDSYSTEM_API PrepareExcludedNodesString(EMotionFX::Actor* actor, AZStd::string* outNodeNames); } // namespace CommandSystem diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ActorInstanceCommands.cpp b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ActorInstanceCommands.cpp index 24cca2e416..60f03f170e 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ActorInstanceCommands.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ActorInstanceCommands.cpp @@ -141,7 +141,7 @@ namespace CommandSystem // add the actor instance to the selection if (select) { - GetCommandManager()->ExecuteCommandInsideCommand(AZStd::string::format("Select -actorInstanceID %i", newInstance->GetID()).c_str(), outResult); + GetCommandManager()->ExecuteCommandInsideCommand(AZStd::string::format("Select -actorInstanceID %u", newInstance->GetID()).c_str(), outResult); if (EMotionFX::GetActorManager().GetNumActorInstances() == 1 && GetCommandManager()->GetLockSelection() == false) { @@ -561,7 +561,7 @@ namespace CommandSystem { // get the selection and number of selected actor instances const SelectionList& selection = GetCommandManager()->GetCurrentSelection(); - const uint32 numActorInstances = selection.GetNumSelectedActorInstances(); + const size_t numActorInstances = selection.GetNumSelectedActorInstances(); // create the command group MCore::CommandGroup commandGroup("Clone actor instances", numActorInstances); @@ -570,7 +570,7 @@ namespace CommandSystem commandGroup.AddCommandString("Unselect -actorInstanceID SELECT_ALL -actorID SELECT_ALL"); // iterate over the selected instances and clone them - for (uint32 i = 0; i < numActorInstances; ++i) + for (size_t i = 0; i < numActorInstances; ++i) { // get the current actor instance EMotionFX::ActorInstance* actorInstance = selection.GetActorInstance(i); @@ -612,14 +612,14 @@ namespace CommandSystem { // get the selection and number of selected actor instances const SelectionList& selection = GetCommandManager()->GetCurrentSelection(); - const uint32 numActorInstances = selection.GetNumSelectedActorInstances(); + const size_t numActorInstances = selection.GetNumSelectedActorInstances(); // create the command group MCore::CommandGroup commandGroup("Remove actor instances", numActorInstances); AZStd::string tempString; // iterate over the selected instances and clone them - for (uint32 i = 0; i < numActorInstances; ++i) + for (size_t i = 0; i < numActorInstances; ++i) { // get the current actor instance EMotionFX::ActorInstance* actorInstance = selection.GetActorInstance(i); @@ -645,7 +645,7 @@ namespace CommandSystem { // get the selection and number of selected actor instances const SelectionList& selection = GetCommandManager()->GetCurrentSelection(); - const uint32 numActorInstances = selection.GetNumSelectedActorInstances(); + const size_t numActorInstances = selection.GetNumSelectedActorInstances(); // create the command group AZStd::string outResult; @@ -653,7 +653,7 @@ namespace CommandSystem MCore::CommandGroup commandGroup("Hide actor instances", numActorInstances * 2); // iterate over the selected instances - for (uint32 i = 0; i < numActorInstances; ++i) + for (size_t i = 0; i < numActorInstances; ++i) { // get the current actor instance EMotionFX::ActorInstance* actorInstance = selection.GetActorInstance(i); @@ -685,7 +685,7 @@ namespace CommandSystem { // get the selection and number of selected actor instances const SelectionList& selection = GetCommandManager()->GetCurrentSelection(); - const uint32 numActorInstances = selection.GetNumSelectedActorInstances(); + const size_t numActorInstances = selection.GetNumSelectedActorInstances(); // create the command group AZStd::string outResult; @@ -693,7 +693,7 @@ namespace CommandSystem MCore::CommandGroup commandGroup("Unhide actor instances", numActorInstances * 2); // iterate over the selected instances - for (uint32 i = 0; i < numActorInstances; ++i) + for (size_t i = 0; i < numActorInstances; ++i) { // get the current actor instance EMotionFX::ActorInstance* actorInstance = selection.GetActorInstance(i); @@ -722,7 +722,7 @@ namespace CommandSystem { // get the selection and number of selected actor instances SelectionList selection = GetCommandManager()->GetCurrentSelection(); - const uint32 numActorInstances = selection.GetNumSelectedActorInstances(); + const size_t numActorInstances = selection.GetNumSelectedActorInstances(); // create the command group AZStd::string outResult; @@ -730,7 +730,7 @@ namespace CommandSystem MCore::CommandGroup commandGroup("Unselect all actor instances", numActorInstances + 1); // iterate over the selected instances and clone them - for (uint32 i = 0; i < numActorInstances; ++i) + for (size_t i = 0; i < numActorInstances; ++i) { // get the current actor instance EMotionFX::ActorInstance* actorInstance = selection.GetActorInstance(i); diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ActorInstanceCommands.h b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ActorInstanceCommands.h index 553fdbf0e6..69509822fe 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ActorInstanceCommands.h +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ActorInstanceCommands.h @@ -31,7 +31,7 @@ public: AZ::Vector3 mOldPosition; AZ::Quaternion mOldRotation; AZ::Vector3 mOldScale; - uint32 mOldLODLevel; + size_t mOldLODLevel; bool mOldIsVisible; bool mOldDoRender; bool mOldWorkspaceDirtyFlag; @@ -44,7 +44,7 @@ public: AZ::Vector3 mOldPosition; AZ::Quaternion mOldRotation; AZ::Vector3 mOldScale; - uint32 mOldLODLevel; + size_t mOldLODLevel; bool mOldIsVisible; bool mOldDoRender; bool mOldWorkspaceDirtyFlag; diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphCommands.cpp b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphCommands.cpp index fdc4e4d0e5..1458107bcf 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphCommands.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphCommands.cpp @@ -77,8 +77,8 @@ namespace CommandSystem } // Check if the anim graph got already loaded via the command system. - const AZ::u32 numAnimGraphs = EMotionFX::GetAnimGraphManager().GetNumAnimGraphs(); - for (AZ::u32 i = 0; i < numAnimGraphs; ++i) + const size_t numAnimGraphs = EMotionFX::GetAnimGraphManager().GetNumAnimGraphs(); + for (size_t i = 0; i < numAnimGraphs; ++i) { EMotionFX::AnimGraph* animGraph = EMotionFX::GetAnimGraphManager().GetAnimGraph(i); if (animGraph->GetFileNameString() == filename && @@ -312,7 +312,7 @@ namespace CommandSystem // remove all anim graphs, to do so we will iterate over them and issue an internal command for // that specific ID. This way we don't need to add complexity to this command to deal with all // the anim graph's undo data - for (uint32 i = 0; i < EMotionFX::GetAnimGraphManager().GetNumAnimGraphs();) + for (size_t i = 0; i < EMotionFX::GetAnimGraphManager().GetNumAnimGraphs();) { EMotionFX::AnimGraph* animGraph = EMotionFX::GetAnimGraphManager().GetAnimGraph(i); if (!animGraph->GetIsOwnedByRuntime() && !animGraph->GetIsOwnedByAsset()) @@ -354,7 +354,7 @@ namespace CommandSystem // remove the given anim graph m_oldFileNamesAndIds.emplace_back(animGraph->GetFileName(), animGraph->GetID()); - uint32 oldIndex = EMotionFX::GetAnimGraphManager().FindAnimGraphIndex(animGraph); + size_t oldIndex = EMotionFX::GetAnimGraphManager().FindAnimGraphIndex(animGraph); // iterate through all anim graph instances and remove the ones that depend on the anim graph to be removed for (size_t i = 0; i < EMotionFX::GetAnimGraphManager().GetNumAnimGraphInstances(); ) @@ -375,15 +375,9 @@ namespace CommandSystem EMotionFX::GetAnimGraphManager().RemoveAnimGraph(animGraph); // Reselect the anim graph at the index of the removed one if possible. - const int numAnimGraphs = EMotionFX::GetAnimGraphManager().GetNumAnimGraphs(); - for (int indexToSelect = oldIndex; indexToSelect >= 0; indexToSelect--) + const size_t numAnimGraphs = EMotionFX::GetAnimGraphManager().GetNumAnimGraphs(); + for (size_t indexToSelect = oldIndex; indexToSelect < numAnimGraphs; indexToSelect--) { - // Is the index to select in a valid range? - if (indexToSelect >= numAnimGraphs) - { - break; - } - EMotionFX::AnimGraph* selectionCandidate = EMotionFX::GetAnimGraphManager().GetAnimGraph(indexToSelect); if (!selectionCandidate->GetIsOwnedByRuntime()) { @@ -521,8 +515,8 @@ namespace CommandSystem EMotionFX::MotionSystem* motionSystem = actorInstance->GetMotionSystem(); // remove all motion instances from this motion system - const uint32 numMotionInstances = motionSystem->GetNumMotionInstances(); - for (uint32 j = 0; j < numMotionInstances; ++j) + const size_t numMotionInstances = motionSystem->GetNumMotionInstances(); + for (size_t j = 0; j < numMotionInstances; ++j) { EMotionFX::MotionInstance* motionInstance = motionSystem->GetMotionInstance(j); motionSystem->RemoveMotionInstance(motionInstance); @@ -665,8 +659,8 @@ namespace CommandSystem EMotionFX::MotionSystem* motionSystem = actorInstance->GetMotionSystem(); // remove all motion instances from this motion system - const uint32 numMotionInstances = motionSystem->GetNumMotionInstances(); - for (uint32 j = 0; j < numMotionInstances; ++j) + const size_t numMotionInstances = motionSystem->GetNumMotionInstances(); + for (size_t j = 0; j < numMotionInstances; ++j) { EMotionFX::MotionInstance* motionInstance = motionSystem->GetMotionInstance(j); motionSystem->RemoveMotionInstance(motionInstance); @@ -791,8 +785,8 @@ namespace CommandSystem if (reload) { // Remove all anim graphs with the given filename. - const AZ::u32 numAnimGraphs = EMotionFX::GetAnimGraphManager().GetNumAnimGraphs(); - for (AZ::u32 j = 0; j < numAnimGraphs; ++j) + const size_t numAnimGraphs = EMotionFX::GetAnimGraphManager().GetNumAnimGraphs(); + for (size_t j = 0; j < numAnimGraphs; ++j) { const EMotionFX::AnimGraph* animGraph = EMotionFX::GetAnimGraphManager().GetAnimGraph(j); diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphConnectionCommands.cpp b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphConnectionCommands.cpp index 25e3924e0d..7707d8fa8b 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphConnectionCommands.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphConnectionCommands.cpp @@ -124,10 +124,10 @@ namespace CommandSystem // in case the source port got specified by name, overwrite the source port number if (!mSourcePortName.empty()) { - mSourcePort = sourceNode->FindOutputPortIndex(mSourcePortName.c_str()); + mSourcePort = sourceNode->FindOutputPortIndex(mSourcePortName); // in case we want to add this connection to a parameter node while the parameter name doesn't exist, still return true so that copy paste doesn't fail - if (azrtti_typeid(sourceNode) == azrtti_typeid() && mSourcePort == -1) + if (azrtti_typeid(sourceNode) == azrtti_typeid() && mSourcePort == InvalidIndex) { m_connectionId.SetInvalid(); return true; @@ -157,13 +157,13 @@ namespace CommandSystem } // verify port ranges - if (mSourcePort >= static_cast(sourceNode->GetOutputPorts().size()) || mSourcePort < 0) + if (mSourcePort >= sourceNode->GetOutputPorts().size()) { outResult = AZStd::string::format("The output port number is not valid for the given node. Node '%s' only has %zu output ports.", sourceNode->GetName(), sourceNode->GetOutputPorts().size()); return false; } - if (mTargetPort >= static_cast(targetNode->GetInputPorts().size()) || mTargetPort < 0) + if (mTargetPort >= targetNode->GetInputPorts().size()) { outResult = AZStd::string::format("The input port number is not valid for the given node. Node '%s' only has %zu input ports.", targetNode->GetName(), targetNode->GetInputPorts().size()); return false; @@ -345,7 +345,7 @@ namespace CommandSystem } // delete the connection - const AZStd::string commandString = AZStd::string::format("AnimGraphRemoveConnection -animGraphID %i -targetNode \"%s\" -targetPort %d -sourceNode \"%s\" -sourcePort %d -id %s", + const AZStd::string commandString = AZStd::string::format("AnimGraphRemoveConnection -animGraphID %i -targetNode \"%s\" -targetPort %zu -sourceNode \"%s\" -sourcePort %zu -id %s", animGraph->GetID(), targetNode->GetName(), mTargetPort, @@ -356,7 +356,7 @@ namespace CommandSystem // execute the command without putting it in the history if (!GetCommandManager()->ExecuteCommandInsideCommand(commandString, outResult)) { - if (outResult.size() > 0) + if (!outResult.empty()) { MCore::LogError(outResult.c_str()); } @@ -414,8 +414,8 @@ namespace CommandSystem CommandAnimGraphRemoveConnection::CommandAnimGraphRemoveConnection(MCore::Command* orgCommand) : MCore::Command("AnimGraphRemoveConnection", orgCommand) { - mSourcePort = MCORE_INVALIDINDEX32; - mTargetPort = MCORE_INVALIDINDEX32; + mSourcePort = InvalidIndex; + mTargetPort = InvalidIndex; mTransitionType = AZ::TypeId::CreateNull(); mStartOffsetX = 0; mStartOffsetY = 0; @@ -603,7 +603,7 @@ namespace CommandSystem return false; } - AZStd::string commandString = AZStd::string::format("AnimGraphCreateConnection -animGraphID %i -sourceNode \"%s\" -targetNode \"%s\" -sourcePort %d -targetPort %d -startOffsetX %d -startOffsetY %d -endOffsetX %d -endOffsetY %d -id %s -transitionType \"%s\" -updateUniqueData %s", + AZStd::string commandString = AZStd::string::format("AnimGraphCreateConnection -animGraphID %i -sourceNode \"%s\" -targetNode \"%s\" -sourcePort %zu -targetPort %zu -startOffsetX %d -startOffsetY %d -endOffsetX %d -endOffsetY %d -id %s -transitionType \"%s\" -updateUniqueData %s", animGraph->GetID(), mSourceNodeName.c_str(), mTargetNodeName.c_str(), @@ -623,7 +623,7 @@ namespace CommandSystem if (!GetCommandManager()->ExecuteCommandInsideCommand(commandString, outResult)) { - if (outResult.size() > 0) + if (!outResult.empty()) { MCore::LogError(outResult.c_str()); } @@ -634,8 +634,8 @@ namespace CommandSystem mTargetNodeId.SetInvalid(); mSourceNodeId.SetInvalid(); m_connectionId.SetInvalid(); - mSourcePort = MCORE_INVALIDINDEX32; - mTargetPort = MCORE_INVALIDINDEX32; + mSourcePort = InvalidIndex; + mTargetPort = InvalidIndex; mStartOffsetX = 0; mStartOffsetY = 0; mEndOffsetX = 0; @@ -970,8 +970,8 @@ namespace CommandSystem // Delete the connections that start from the given node. if (parentNode) { - const uint32 numChildNodes = parentNode->GetNumChildNodes(); - for (uint32 i = 0; i < numChildNodes; ++i) + const size_t numChildNodes = parentNode->GetNumChildNodes(); + for (size_t i = 0; i < numChildNodes; ++i) { EMotionFX::AnimGraphNode* childNode = parentNode->GetChildNode(i); if (childNode == node) @@ -979,8 +979,8 @@ namespace CommandSystem continue; } - const uint32 numChildConnections = childNode->GetNumConnections(); - for (uint32 j = 0; j < numChildConnections; ++j) + const size_t numChildConnections = childNode->GetNumConnections(); + for (size_t j = 0; j < numChildConnections; ++j) { EMotionFX::BlendTreeConnection* childConnection = childNode->GetConnection(j); @@ -994,8 +994,8 @@ namespace CommandSystem } // Delete the connections that end in the given node. - const uint32 numConnections = node->GetNumConnections(); - for (uint32 i = 0; i < numConnections; ++i) + const size_t numConnections = node->GetNumConnections(); + for (size_t i = 0; i < numConnections; ++i) { EMotionFX::BlendTreeConnection* connection = node->GetConnection(i); DeleteConnection(commandGroup, node, connection, connectionList); @@ -1004,8 +1004,8 @@ namespace CommandSystem // Recursively delete all connections. if (recursive) { - const uint32 numChildNodes = node->GetNumChildNodes(); - for (uint32 i = 0; i < numChildNodes; ++i) + const size_t numChildNodes = node->GetNumChildNodes(); + for (size_t i = 0; i < numChildNodes; ++i) { EMotionFX::AnimGraphNode* childNode = node->GetChildNode(i); DeleteNodeConnections(commandGroup, childNode, node, connectionList, recursive); @@ -1194,8 +1194,8 @@ namespace CommandSystem // Recursively delete all transitions. if (recursive) { - const uint32 numChildNodes = state->GetNumChildNodes(); - for (uint32 i = 0; i < numChildNodes; ++i) + const size_t numChildNodes = state->GetNumChildNodes(); + for (size_t i = 0; i < numChildNodes; ++i) { EMotionFX::AnimGraphNode* childNode = state->GetChildNode(i); DeleteStateTransitions(commandGroup, childNode, state, transitionList, recursive); diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphConnectionCommands.h b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphConnectionCommands.h index 2bcebb630a..d0ef5549e0 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphConnectionCommands.h +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphConnectionCommands.h @@ -35,8 +35,8 @@ namespace CommandSystem int32 mStartOffsetY; int32 mEndOffsetX; int32 mEndOffsetY; - int32 mSourcePort; - int32 mTargetPort; + size_t mSourcePort; + size_t mTargetPort; AZStd::string mSourcePortName; AZStd::string mTargetPortName; bool mOldDirtyFlag; @@ -47,8 +47,8 @@ namespace CommandSystem EMotionFX::AnimGraphNodeId GetTargetNodeId() const { return mTargetNodeId; } EMotionFX::AnimGraphNodeId GetSourceNodeId() const { return mSourceNodeId; } AZ::TypeId GetTransitionType() const { return mTransitionType; } - int32 GetSourcePort() const { return mSourcePort; } - int32 GetTargetPort() const { return mTargetPort; } + size_t GetSourcePort() const { return mSourcePort; } + size_t GetTargetPort() const { return mTargetPort; } int32 GetStartOffsetX() const { return mStartOffsetX; } int32 GetStartOffsetY() const { return mStartOffsetY; } int32 GetEndOffsetX() const { return mEndOffsetX; } @@ -69,8 +69,8 @@ namespace CommandSystem int32 mStartOffsetY; int32 mEndOffsetX; int32 mEndOffsetY; - int32 mSourcePort; - int32 mTargetPort; + size_t mSourcePort; + size_t mTargetPort; bool mOldDirtyFlag; AZStd::string mOldContents; @@ -78,8 +78,8 @@ namespace CommandSystem EMotionFX::AnimGraphNodeId GetTargetNodeID() const { return mTargetNodeId; } EMotionFX::AnimGraphNodeId GetSourceNodeID() const { return mSourceNodeId; } AZ::TypeId GetTransitionType() const { return mTransitionType; } - int32 GetSourcePort() const { return mSourcePort; } - int32 GetTargetPort() const { return mTargetPort; } + size_t GetSourcePort() const { return mSourcePort; } + size_t GetTargetPort() const { return mTargetPort; } int32 GetStartOffsetX() const { return mStartOffsetX; } int32 GetStartOffsetY() const { return mStartOffsetY; } int32 GetEndOffsetX() const { return mEndOffsetX; } diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphNodeCommands.cpp b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphNodeCommands.cpp index ed871fc03f..6142fe151e 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphNodeCommands.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphNodeCommands.cpp @@ -370,8 +370,8 @@ namespace CommandSystem animGraph->RecursiveInvalidateUniqueDatas(); // init new node for all anim graph instances belonging to it - const uint32 numActorInstances = EMotionFX::GetActorManager().GetNumActorInstances(); - for (uint32 i = 0; i < numActorInstances; ++i) + const size_t numActorInstances = EMotionFX::GetActorManager().GetNumActorInstances(); + for (size_t i = 0; i < numActorInstances; ++i) { EMotionFX::AnimGraphInstance* animGraphInstance = EMotionFX::GetActorManager().GetActorInstance(i)->GetAnimGraphInstance(); if (animGraphInstance && animGraphInstance->GetAnimGraph() == animGraph) @@ -416,7 +416,7 @@ namespace CommandSystem const AZStd::string commandString = AZStd::string::format("AnimGraphRemoveNode -animGraphID %i -name \"%s\"", animGraph->GetID(), node->GetName()); if (GetCommandManager()->ExecuteCommandInsideCommand(commandString, outResult) == false) { - if (outResult.size() > 0) + if (!outResult.empty()) { MCore::LogError(outResult.c_str()); } @@ -743,8 +743,8 @@ namespace CommandSystem //-------------------------- // Find alternative entry state. EMotionFX::AnimGraphNode* newEntryState = nullptr; - uint32 numStates = stateMachine->GetNumChildNodes(); - for (uint32 s = 0; s < numStates; ++s) + size_t numStates = stateMachine->GetNumChildNodes(); + for (size_t s = 0; s < numStates; ++s) { EMotionFX::AnimGraphNode* childNode = stateMachine->GetChildNode(s); if (childNode != emfxNode) @@ -848,7 +848,7 @@ namespace CommandSystem if (!GetCommandManager()->ExecuteCommandGroupInsideCommand(group, outResult)) { - if (outResult.size() > 0) + if (!outResult.empty()) { MCore::LogError(outResult.c_str()); } @@ -870,7 +870,7 @@ namespace CommandSystem ); if (GetCommandManager()->ExecuteCommandInsideCommand(command, outResult) == false) { - if (outResult.size() > 0) + if (!outResult.empty()) { MCore::LogError(outResult.c_str()); } @@ -1207,16 +1207,15 @@ namespace CommandSystem AZStd::vector outNodes; const AZ::TypeId nodeType = azrtti_typeid(node); parentNode->CollectChildNodesOfType(nodeType, &outNodes); - const uint32 numTypeNodes = outNodes.size(); + const size_t numTypeNodes = outNodes.size(); // Gather the number of already removed nodes with the same type as the one we're trying to remove. - const size_t numTotalDeletedNodes = nodeList.size(); - uint32 numTypeDeletedNodes = 0; - for (size_t i = 0; i < numTotalDeletedNodes; ++i) + size_t numTypeDeletedNodes = 0; + for (const EMotionFX::AnimGraphNode* i : nodeList) { // Check if the nodes have the same parent, meaning they are in the same graph plus check if they have the same type // if that both is the same we can increase the number of deleted nodes for the graph where the current node is in. - if (nodeList[i]->GetParentNode() == parentNode && azrtti_typeid(nodeList[i]) == nodeType) + if (i->GetParentNode() == parentNode && azrtti_typeid(i) == nodeType) { numTypeDeletedNodes++; } @@ -1242,8 +1241,8 @@ namespace CommandSystem // 2. Delete all child nodes recursively before deleting the node. // Get the number of child nodes, iterate through them and recursively call the function. - const uint32 numChildNodes = node->GetNumChildNodes(); - for (uint32 i = 0; i < numChildNodes; ++i) + const size_t numChildNodes = node->GetNumChildNodes(); + for (size_t i = 0; i < numChildNodes; ++i) { EMotionFX::AnimGraphNode* childNode = node->GetChildNode(i); DeleteNode(commandGroup, animGraph, childNode, nodeList, connectionList, transitionList, true, false, false); @@ -1268,10 +1267,9 @@ namespace CommandSystem void DeleteNodes(MCore::CommandGroup* commandGroup, EMotionFX::AnimGraph* animGraph, const AZStd::vector& nodeNames, AZStd::vector& nodeList, AZStd::vector& connectionList, AZStd::vector& transitionList, bool autoChangeEntryStates) { - const size_t numNodeNames = nodeNames.size(); - for (size_t i = 0; i < numNodeNames; ++i) + for (const AZStd::string& nodeName : nodeNames) { - EMotionFX::AnimGraphNode* node = animGraph->RecursiveFindNodeByName(nodeNames[i].c_str()); + EMotionFX::AnimGraphNode* node = animGraph->RecursiveFindNodeByName(nodeName.c_str()); // Add the delete node commands to the command group. DeleteNode(commandGroup, animGraph, node, nodeList, connectionList, transitionList, true, true, autoChangeEntryStates); @@ -1385,8 +1383,8 @@ namespace CommandSystem } // Recurse through the child nodes. - const uint32 numChildNodes = node->GetNumChildNodes(); - for (uint32 i = 0; i < numChildNodes; ++i) + const size_t numChildNodes = node->GetNumChildNodes(); + for (size_t i = 0; i < numChildNodes; ++i) { EMotionFX::AnimGraphNode* childNode = node->GetChildNode(i); CopyAnimGraphNodeCommand(commandGroup, targetAnimGraph, node, childNode, @@ -1404,8 +1402,8 @@ namespace CommandSystem } // Recurse through the child nodes. - const uint32 numChildNodes = node->GetNumChildNodes(); - for (uint32 i = 0; i < numChildNodes; ++i) + const size_t numChildNodes = node->GetNumChildNodes(); + for (size_t i = 0; i < numChildNodes; ++i) { EMotionFX::AnimGraphNode* childNode = node->GetChildNode(i); CopyAnimGraphConnectionsCommand(commandGroup, targetAnimGraph, childNode, @@ -1436,8 +1434,8 @@ namespace CommandSystem } else { - const uint32 numConnections = node->GetNumConnections(); - for (uint32 i = 0; i < numConnections; ++i) + const size_t numConnections = node->GetNumConnections(); + for (size_t i = 0; i < numConnections; ++i) { EMotionFX::BlendTreeConnection* connection = node->GetConnection(i); CopyBlendTreeConnection(commandGroup, targetAnimGraph, node, connection, @@ -1455,29 +1453,14 @@ namespace CommandSystem } // Remove all nodes that are child nodes of other selected nodes. - for (size_t i = 0; i < nodesToCopy.size();) + AZStd::erase_if(nodesToCopy, [&nodesToCopy](const EMotionFX::AnimGraphNode* node) { - EMotionFX::AnimGraphNode* node = nodesToCopy[i]; - - bool removeNode = false; - for (size_t j = 0; j < nodesToCopy.size(); ++j) + const auto found = AZStd::find_if(begin(nodesToCopy), end(nodesToCopy), [node](const EMotionFX::AnimGraphNode* parent) { - if (node != nodesToCopy[j] && node->RecursiveIsParentNode(nodesToCopy[j])) - { - removeNode = true; - break; - } - } - - if (removeNode) - { - nodesToCopy.erase(nodesToCopy.begin() + i); - } - else - { - i++; - } - } + return node != parent && node->RecursiveIsParentNode(parent); + }); + return found != end(nodesToCopy); + }); // In case we are in cut and paste mode and delete the cut nodes. if (cutMode) diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphNodeGroupCommands.cpp b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphNodeGroupCommands.cpp index f5f913f0ca..a11af1399d 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphNodeGroupCommands.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphNodeGroupCommands.cpp @@ -71,9 +71,9 @@ namespace CommandSystem { AZStd::vector result; - const uint32 numNodes = nodeGroup->GetNumNodes(); + const size_t numNodes = nodeGroup->GetNumNodes(); result.reserve(numNodes); - for (uint32 i = 0; i < numNodes; ++i) + for (size_t i = 0; i < numNodes; ++i) { result.push_back(nodeGroup->GetNode(i)); } @@ -91,8 +91,8 @@ namespace CommandSystem } // find the node group index - const uint32 groupIndex = animGraph->FindNodeGroupIndexByName(m_name.c_str()); - if (groupIndex == MCORE_INVALIDINDEX32) + const size_t groupIndex = animGraph->FindNodeGroupIndexByName(m_name.c_str()); + if (groupIndex == InvalidIndex) { outResult = AZStd::string::format("Node group \"%s\" can not be found.", m_name.c_str()); return false; @@ -149,8 +149,8 @@ namespace CommandSystem } // remove the node from all node groups - const uint32 numNodeGroups = animGraph->GetNumNodeGroups(); - for (uint32 n = 0; n < numNodeGroups; ++n) + const size_t numNodeGroups = animGraph->GetNumNodeGroups(); + for (size_t n = 0; n < numNodeGroups; ++n) { animGraph->GetNodeGroup(n)->RemoveNodeById(animGraphNode->GetId()); } @@ -173,8 +173,8 @@ namespace CommandSystem } // remove the node from all node groups - const uint32 numNodeGroups = animGraph->GetNumNodeGroups(); - for (uint32 n = 0; n < numNodeGroups; ++n) + const size_t numNodeGroups = animGraph->GetNumNodeGroups(); + for (size_t n = 0; n < numNodeGroups; ++n) { animGraph->GetNodeGroup(n)->RemoveNodeById(animGraphNode->GetId()); } @@ -404,10 +404,10 @@ namespace CommandSystem parameters.GetValue("name", this, groupName); // find the node group index and remove it - const uint32 groupIndex = animGraph->FindNodeGroupIndexByName(groupName.c_str()); - if (groupIndex == MCORE_INVALIDINDEX32) + const size_t groupIndex = animGraph->FindNodeGroupIndexByName(groupName.c_str()); + if (groupIndex == InvalidIndex) { - outResult = AZStd::string::format("Cannot add node group to anim graph. Node group index %u is invalid.", groupIndex); + outResult = AZStd::string::format("Cannot add node group to anim graph. Node group index %zu is invalid.", groupIndex); return false; } @@ -487,7 +487,7 @@ namespace CommandSystem void ClearNodeGroups(EMotionFX::AnimGraph* animGraph, MCore::CommandGroup* commandGroup) { // get number of node groups - const uint32 numNodeGroups = animGraph->GetNumNodeGroups(); + const size_t numNodeGroups = animGraph->GetNumNodeGroups(); if (numNodeGroups == 0) { return; @@ -498,7 +498,7 @@ namespace CommandSystem // get rid of all node groups AZStd::string commandString; - for (uint32 i = 0; i < numNodeGroups; ++i) + for (size_t i = 0; i < numNodeGroups; ++i) { // get pointer to the current actor instance EMotionFX::AnimGraphNodeGroup* nodeGroup = animGraph->GetNodeGroup(i); diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphParameterCommands.cpp b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphParameterCommands.cpp index 38a545465b..b0c03e4df2 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphParameterCommands.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphParameterCommands.cpp @@ -170,7 +170,7 @@ namespace CommandSystem for (size_t i = 0; i < numInstances; ++i) { EMotionFX::AnimGraphInstance* animGraphInstance = animGraph->GetAnimGraphInstance(i); - animGraphInstance->InsertParameterValue(static_cast(valueParameterIndex.GetValue())); + animGraphInstance->InsertParameterValue(valueParameterIndex.GetValue()); } AZStd::vector affectedObjects; @@ -316,7 +316,7 @@ namespace CommandSystem { EMotionFX::AnimGraphInstance* animGraphInstance = animGraph->GetAnimGraphInstance(i); // Remove the parameter. - animGraphInstance->RemoveParameterValue(static_cast(valueParameterIndex.GetValue())); + animGraphInstance->RemoveParameterValue(valueParameterIndex.GetValue()); } // Save the current dirty flag and tell the anim graph that something got changed. @@ -521,13 +521,13 @@ namespace CommandSystem // Update all corresponding anim graph instances. const size_t numInstances = animGraph->GetNumAnimGraphInstances(); - for (uint32 i = 0; i < numInstances; ++i) + for (size_t i = 0; i < numInstances; ++i) { EMotionFX::AnimGraphInstance* animGraphInstance = animGraph->GetAnimGraphInstance(i); // reinit the modified parameters if (mOldType != azrtti_typeid()) { - animGraphInstance->ReInitParameterValue(static_cast(valueParameterIndex.GetValue())); + animGraphInstance->ReInitParameterValue(valueParameterIndex.GetValue()); } else { @@ -773,7 +773,7 @@ namespace CommandSystem { EMotionFX::AnimGraphInstance* animGraphInstance = animGraph->GetAnimGraphInstance(i); // Move the parameter from original position to the new position - animGraphInstance->MoveParameterValue(static_cast(valueIndexBeforeMove.GetValue()), static_cast(valueIndexAfterMove.GetValue())); + animGraphInstance->MoveParameterValue(valueIndexBeforeMove.GetValue(), valueIndexAfterMove.GetValue()); } EMotionFX::ValueParameterVector valueParametersAfterChange = animGraph->RecursivelyGetValueParameters(); @@ -853,7 +853,7 @@ namespace CommandSystem //-------------------------------------------------------------------------------- // Construct create parameter command strings //-------------------------------------------------------------------------------- - void ConstructCreateParameterCommand(AZStd::string& outResult, EMotionFX::AnimGraph* animGraph, const EMotionFX::Parameter* parameter, uint32 insertAtIndex) + void ConstructCreateParameterCommand(AZStd::string& outResult, EMotionFX::AnimGraph* animGraph, const EMotionFX::Parameter* parameter, size_t insertAtIndex) { // Build the command string. AZStd::string parameterContents; @@ -865,9 +865,9 @@ namespace CommandSystem parameter->GetName().c_str(), parameterContents.c_str()); - if (insertAtIndex != InvalidIndex32) + if (insertAtIndex != InvalidIndex) { - outResult += AZStd::string::format(" -index \"%i\"", insertAtIndex); + outResult += AZStd::string::format(" -index \"%zu\"", insertAtIndex); } } @@ -920,11 +920,11 @@ namespace CommandSystem AZStd::vector> outgoingConnectionsFromThisPort; for (const EMotionFX::AnimGraphNode* parameterNode : parameterNodes) { - const AZ::u32 sourcePortIndex = parameterNode->FindOutputPortIndex(parameterName); + const size_t sourcePortIndex = parameterNode->FindOutputPortIndex(parameterName); parameterNode->CollectOutgoingConnections(outgoingConnectionsFromThisPort, sourcePortIndex); // outgoingConnectionsFromThisPort will be cleared inside the function. const size_t numConnections = outgoingConnectionsFromThisPort.size(); - for (uint32 i = 0; i < numConnections; ++i) + for (size_t i = 0; i < numConnections; ++i) { const EMotionFX::AnimGraphNode* targetNode = outgoingConnectionsFromThisPort[i].second; const EMotionFX::BlendTreeConnection* connection = outgoingConnectionsFromThisPort[i].first; @@ -999,7 +999,7 @@ namespace CommandSystem // 3. Remove the actual parameters. size_t numIterations = parameterNamesToRemove.size(); - for (uint32 i = 0; i < numIterations; ++i) + for (size_t i = 0; i < numIterations; ++i) { commandString = AZStd::string::format("AnimGraphRemoveParameter -animGraphID %i -name \"%s\"", animGraph->GetID(), parameterNamesToRemove[i].c_str()); if (i != 0 && i != numIterations - 1) diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphParameterCommands.h b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphParameterCommands.h index 8b55130677..f93a93d0f9 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphParameterCommands.h +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphParameterCommands.h @@ -59,8 +59,6 @@ namespace CommandSystem struct COMMANDSYSTEM_API ParameterConnectionItem { - uint32 mTargetNodePort; - void SetParameterNodeName(const char* name) { mParameterNodeNameID = MCore::GetStringIdPool().GenerateIdForString(name); } void SetTargetNodeName(const char* name) { mTargetNodeNameID = MCore::GetStringIdPool().GenerateIdForString(name); } void SetParameterName(const char* name) { mParameterNameID = MCore::GetStringIdPool().GenerateIdForString(name); } @@ -81,6 +79,6 @@ namespace CommandSystem COMMANDSYSTEM_API void ClearParametersCommand(EMotionFX::AnimGraph* animGraph, MCore::CommandGroup* commandGroup = nullptr); // Construct the create parameter command string using the the given information. - COMMANDSYSTEM_API void ConstructCreateParameterCommand(AZStd::string& outResult, EMotionFX::AnimGraph* animGraph, const EMotionFX::Parameter* parameter, uint32 insertAtIndex = InvalidIndex32); + COMMANDSYSTEM_API void ConstructCreateParameterCommand(AZStd::string& outResult, EMotionFX::AnimGraph* animGraph, const EMotionFX::Parameter* parameter, size_t insertAtIndex = InvalidIndex); } // namespace CommandSystem diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AttachmentCommands.cpp b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AttachmentCommands.cpp index 23c429b04a..a22cf18149 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AttachmentCommands.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AttachmentCommands.cpp @@ -139,13 +139,11 @@ namespace CommandSystem { EMotionFX::AttachmentNode* newAttachment = EMotionFX::AttachmentNode::Create(attachToActorInstance, node->GetNodeIndex(), attachment); attachToActorInstance->AddAttachment(newAttachment); - //attachToActorInstance->AddAttachment( node->GetNodeIndex(), attachment ); } else { attachToActorInstance->RemoveAttachment(attachment, true); } - // attachToActorInstance->RemoveAttachment( attachment, false ); return true; } @@ -300,10 +298,10 @@ namespace CommandSystem bool CommandAddDeformableAttachment::AddAttachment(MCore::Command* command, const MCore::CommandLine& parameters, AZStd::string& outResult, bool remove) { uint32 attachToActorID = parameters.GetValueAsInt("attachToID", command); - uint32 attachToActorIndex = parameters.GetValueAsInt("attachToIndex", command); + size_t attachToActorIndex = parameters.GetValueAsInt("attachToIndex", command); // in case we only specified an attach to index, get the id from that - if (attachToActorIndex != MCORE_INVALIDINDEX32 && attachToActorID == MCORE_INVALIDINDEX32) + if (attachToActorIndex != InvalidIndex && attachToActorID == MCORE_INVALIDINDEX32) { if (EMotionFX::GetActorManager().GetNumActorInstances() <= attachToActorIndex) { @@ -315,11 +313,11 @@ namespace CommandSystem } uint32 attachmentID = parameters.GetValueAsInt("attachmentID", command); - uint32 attachmentIndex = parameters.GetValueAsInt("attachmentIndex", command); + size_t attachmentIndex = parameters.GetValueAsInt("attachmentIndex", command); if (attachmentID == MCORE_INVALIDINDEX32) { // in case we only specified an attachment index, get the id from that - if (attachmentIndex != MCORE_INVALIDINDEX32) + if (attachmentIndex != InvalidIndex) { EMotionFX::ActorInstance* actorInstance = EMotionFX::GetActorManager().GetActorInstance(attachmentIndex); attachmentID = actorInstance->GetID(); diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MetaData.cpp b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MetaData.cpp index 506f47fcac..aade6e8358 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MetaData.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MetaData.cpp @@ -71,8 +71,8 @@ namespace CommandSystem void MetaData::GeneratePhonemeMetaData(EMotionFX::Actor* actor, AZStd::string& outMetaDataString) { - const AZ::u32 numLODLevels = actor->GetNumLODLevels(); - for (AZ::u32 lodLevel = 0; lodLevel < numLODLevels; ++lodLevel) + const size_t numLODLevels = actor->GetNumLODLevels(); + for (size_t lodLevel = 0; lodLevel < numLODLevels; ++lodLevel) { EMotionFX::MorphSetup* morphSetup = actor->GetMorphSetup(lodLevel); if (!morphSetup) @@ -80,8 +80,8 @@ namespace CommandSystem continue; } - const uint32 numMorphTargets = morphSetup->GetNumMorphTargets(); - for (uint32 i = 0; i < numMorphTargets; ++i) + const size_t numMorphTargets = morphSetup->GetNumMorphTargets(); + for (size_t i = 0; i < numMorphTargets; ++i) { EMotionFX::MorphTarget* morphTarget = morphSetup->GetMorphTarget(i); if (!morphTarget) @@ -89,7 +89,7 @@ namespace CommandSystem continue; } - outMetaDataString += AZStd::string::format("AdjustMorphTarget -actorID $(ACTORID) -lodLevel %i -name \"%s\" -phonemeAction \"replace\" ", lodLevel, morphTarget->GetName()); + outMetaDataString += AZStd::string::format("AdjustMorphTarget -actorID $(ACTORID) -lodLevel %zu -name \"%s\" -phonemeAction \"replace\" ", lodLevel, morphTarget->GetName()); outMetaDataString += AZStd::string::format("-phonemeSets \"%s\" ", morphTarget->GetPhonemeSetString(morphTarget->GetPhonemeSets()).c_str()); outMetaDataString += AZStd::string::format("-rangeMin %f -rangeMax %f\n", morphTarget->GetRangeMin(), morphTarget->GetRangeMax()); } @@ -101,8 +101,8 @@ namespace CommandSystem { AZStd::string attachmentNodeNameList; - const AZ::u32 numNodes = actor->GetNumNodes(); - for (AZ::u32 i = 0; i < numNodes; ++i) + const size_t numNodes = actor->GetNumNodes(); + for (size_t i = 0; i < numNodes; ++i) { EMotionFX::Node* node = actor->GetSkeleton()->GetNode(i); if (!node) @@ -233,10 +233,9 @@ namespace CommandSystem // Construct a new command group and fill it with all meta data commands. MCore::CommandGroup commandGroup; - const size_t numTokens = tokens.size(); - for (size_t i = 0; i < numTokens; ++i) + for (const AZStd::string& token : tokens) { - commandGroup.AddCommandString(tokens[i].c_str()); + commandGroup.AddCommandString(token); } // Execute the command group and apply the meta data. diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MotionCommands.cpp b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MotionCommands.cpp index 5655f2f293..677b4ec5ff 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MotionCommands.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MotionCommands.cpp @@ -200,7 +200,7 @@ namespace CommandSystem m_oldData.clear(); // check if there is any actor instance selected and if not return false so that the command doesn't get called and doesn't get inside the action history - const uint32 numSelectedActorInstances = GetCommandManager()->GetCurrentSelection().GetNumSelectedActorInstances(); + const size_t numSelectedActorInstances = GetCommandManager()->GetCurrentSelection().GetNumSelectedActorInstances(); // verify if we actually have selected an actor instance if (numSelectedActorInstances == 0) @@ -236,7 +236,7 @@ namespace CommandSystem CommandParametersToPlaybackInfo(this, parameters, &playbackInfo); // iterate through all actor instances and start playing all selected motions - for (uint32 i = 0; i < numSelectedActorInstances; ++i) + for (size_t i = 0; i < numSelectedActorInstances; ++i) { EMotionFX::ActorInstance* actorInstance = GetCommandManager()->GetCurrentSelection().GetActorInstance(i); @@ -467,8 +467,8 @@ namespace CommandSystem MCORE_UNUSED(outResult); // iterate through the motion instances and modify them - const uint32 numSelectedMotionInstances = GetCommandManager()->GetCurrentSelection().GetNumSelectedMotionInstances(); - for (uint32 i = 0; i < numSelectedMotionInstances; ++i) + const size_t numSelectedMotionInstances = GetCommandManager()->GetCurrentSelection().GetNumSelectedMotionInstances(); + for (size_t i = 0; i < numSelectedMotionInstances; ++i) { // get the current selected motion instance and adjust it based on the parameters EMotionFX::MotionInstance* selectedMotionInstance = GetCommandManager()->GetCurrentSelection().GetMotionInstance(i); @@ -618,7 +618,7 @@ namespace CommandSystem //mOldData.Clear(); // get the number of selected actor instances - const uint32 numSelectedActorInstances = GetCommandManager()->GetCurrentSelection().GetNumSelectedActorInstances(); + const size_t numSelectedActorInstances = GetCommandManager()->GetCurrentSelection().GetNumSelectedActorInstances(); // check if there is any actor instance selected and if not return false so that the command doesn't get called and doesn't get inside the action history if (numSelectedActorInstances == 0) @@ -645,7 +645,7 @@ namespace CommandSystem } // iterate through all actor instances and stop all selected motion instances - for (uint32 i = 0; i < numSelectedActorInstances; ++i) + for (size_t i = 0; i < numSelectedActorInstances; ++i) { // get the actor instance and the corresponding motion system EMotionFX::ActorInstance* actorInstance = GetCommandManager()->GetCurrentSelection().GetActorInstance(i); @@ -665,8 +665,8 @@ namespace CommandSystem } // get the number of motion instances and iterate through them - const uint32 numMotionInstances = motionSystem->GetNumMotionInstances(); - for (uint32 j = 0; j < numMotionInstances; ++j) + const size_t numMotionInstances = motionSystem->GetNumMotionInstances(); + for (size_t j = 0; j < numMotionInstances; ++j) { EMotionFX::MotionInstance* motionInstance = motionSystem->GetMotionInstance(j); @@ -720,8 +720,8 @@ namespace CommandSystem //mOldData.Clear(); // iterate through all actor instances and stop all selected motion instances - const uint32 numActorInstances = EMotionFX::GetActorManager().GetNumActorInstances(); - for (uint32 i = 0; i < numActorInstances; ++i) + const size_t numActorInstances = EMotionFX::GetActorManager().GetNumActorInstances(); + for (size_t i = 0; i < numActorInstances; ++i) { // get the actor instance and the corresponding motion system EMotionFX::ActorInstance* actorInstance = EMotionFX::GetActorManager().GetActorInstance(i); @@ -741,8 +741,8 @@ namespace CommandSystem } // get the number of motion instances and iterate through them - const uint32 numMotionInstances = motionSystem->GetNumMotionInstances(); - for (uint32 j = 0; j < numMotionInstances; ++j) + const size_t numMotionInstances = motionSystem->GetNumMotionInstances(); + for (size_t j = 0; j < numMotionInstances; ++j) { // get the motion instance and stop it EMotionFX::MotionInstance* motionInstance = motionSystem->GetMotionInstance(j); @@ -974,8 +974,8 @@ namespace CommandSystem } // make sure the motion is not part of any motion set - const uint32 numMotionSets = EMotionFX::GetMotionManager().GetNumMotionSets(); - for (uint32 i = 0; i < numMotionSets; ++i) + const size_t numMotionSets = EMotionFX::GetMotionManager().GetNumMotionSets(); + for (size_t i = 0; i < numMotionSets; ++i) { // get the current motion set and check if the motion we want to remove is used by it EMotionFX::MotionSet* motionSet = EMotionFX::GetMotionManager().GetMotionSet(i); @@ -1185,13 +1185,12 @@ namespace CommandSystem const size_t numFileNames = filenames.size(); const AZStd::string commandGroupName = AZStd::string::format("%s %zu motion%s", reload ? "Reload" : "Load", numFileNames, (numFileNames > 1) ? "s" : ""); - MCore::CommandGroup commandGroup(commandGroupName, static_cast(numFileNames * 2)); + MCore::CommandGroup commandGroup(commandGroupName, numFileNames * 2); AZStd::string command; const EMotionFX::MotionManager& motionManager = EMotionFX::GetMotionManager(); - for (size_t i = 0; i < numFileNames; ++i) + for (const AZStd::string& filename : filenames) { - const AZStd::string& filename = filenames[i]; const EMotionFX::Motion* motion = motionManager.FindMotionByFileName(filename.c_str()); if (reload && motion) @@ -1234,11 +1233,11 @@ namespace CommandSystem void ClearMotions(MCore::CommandGroup* commandGroup, bool forceRemove) { // iterate through the motions and put them into some array - const uint32 numMotions = EMotionFX::GetMotionManager().GetNumMotions(); + const size_t numMotions = EMotionFX::GetMotionManager().GetNumMotions(); AZStd::vector motionsToRemove; motionsToRemove.reserve(numMotions); - for (uint32 i = 0; i < numMotions; ++i) + for (size_t i = 0; i < numMotions; ++i) { EMotionFX::Motion* motion = EMotionFX::GetMotionManager().GetMotion(i); @@ -1283,10 +1282,8 @@ namespace CommandSystem // Iterate through all motions and remove them. AZStd::string commandString; - for (uint32 i = 0; i < numMotions; ++i) + for (const EMotionFX::Motion* motion : motions) { - EMotionFX::Motion* motion = motions[i]; - if (motion->GetIsOwnedByRuntime()) { continue; @@ -1294,10 +1291,10 @@ namespace CommandSystem // Is the motion part of a motion set? bool isUsed = false; - const uint32 numMotionSets = EMotionFX::GetMotionManager().GetNumMotionSets(); - for (uint32 j = 0; j < numMotionSets; ++j) + const size_t numMotionSets = EMotionFX::GetMotionManager().GetNumMotionSets(); + for (size_t i = 0; i < numMotionSets; ++i) { - EMotionFX::MotionSet* motionSet = EMotionFX::GetMotionManager().GetMotionSet(j); + EMotionFX::MotionSet* motionSet = EMotionFX::GetMotionManager().GetMotionSet(i); EMotionFX::MotionSet::MotionEntry* motionEntry = motionSet->FindMotionEntry(motion); if (motionEntry) diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MotionCommands.h b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MotionCommands.h index 2dbee2ad4a..2e68d7b2cc 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MotionCommands.h +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MotionCommands.h @@ -38,9 +38,9 @@ namespace CommandSystem bool SetCommandParameters(const MCore::CommandLine& parameters); - void SetMotionID(int32 motionID) { m_motionID = motionID; } + void SetMotionID(uint32 motionID) { m_motionID = motionID; } protected: - int32 m_motionID = 0; + uint32 m_motionID = 0; }; // Adjust motion command. @@ -83,7 +83,7 @@ namespace CommandSystem public: uint32 mOldMotionID; AZStd::string mOldFileName; - uint32 mOldIndex; + size_t mOldIndex; bool mOldWorkspaceDirtyFlag; MCORE_DEFINECOMMAND_END diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MotionEventCommands.cpp b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MotionEventCommands.cpp index e4b8d38147..b1d896ccd4 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MotionEventCommands.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MotionEventCommands.cpp @@ -956,7 +956,7 @@ namespace CommandSystem } // get the event index and check if it is in range - if (m_eventNr < 0 || m_eventNr >= eventTrack->GetNumEvents()) + if (m_eventNr >= eventTrack->GetNumEvents()) { return AZ::Failure(); } @@ -1006,7 +1006,7 @@ namespace CommandSystem // remove event track - void CommandRemoveEventTrack(EMotionFX::Motion* motion, uint32 trackIndex) + void CommandRemoveEventTrack(EMotionFX::Motion* motion, size_t trackIndex) { if (!motion) { @@ -1035,7 +1035,7 @@ namespace CommandSystem // remove event track - void CommandRemoveEventTrack(uint32 trackIndex) + void CommandRemoveEventTrack(size_t trackIndex) { EMotionFX::Motion* motion = GetCommandManager()->GetCurrentSelection().GetSingleMotion(); CommandRemoveEventTrack(motion, trackIndex); @@ -1043,7 +1043,7 @@ namespace CommandSystem // rename event track - void CommandRenameEventTrack(EMotionFX::Motion* motion, uint32 trackIndex, const char* newName) + void CommandRenameEventTrack(EMotionFX::Motion* motion, size_t trackIndex, const char* newName) { // make sure the motion is valid if (motion == nullptr) @@ -1065,7 +1065,7 @@ namespace CommandSystem // rename event track - void CommandRenameEventTrack(uint32 trackIndex, const char* newName) + void CommandRenameEventTrack(size_t trackIndex, const char* newName) { EMotionFX::Motion* motion = GetCommandManager()->GetCurrentSelection().GetSingleMotion(); CommandRenameEventTrack(motion, trackIndex, newName); @@ -1073,7 +1073,7 @@ namespace CommandSystem // enable or disable event track - void CommandEnableEventTrack(EMotionFX::Motion* motion, uint32 trackIndex, bool isEnabled) + void CommandEnableEventTrack(EMotionFX::Motion* motion, size_t trackIndex, bool isEnabled) { // make sure the motion is valid if (motion == nullptr) @@ -1098,7 +1098,7 @@ namespace CommandSystem // enable or disable event track - void CommandEnableEventTrack(uint32 trackIndex, bool isEnabled) + void CommandEnableEventTrack(size_t trackIndex, bool isEnabled) { EMotionFX::Motion* motion = GetCommandManager()->GetCurrentSelection().GetSingleMotion(); CommandEnableEventTrack(motion, trackIndex, isEnabled); @@ -1114,7 +1114,7 @@ namespace CommandSystem // remove motion event - void CommandHelperRemoveMotionEvent(EMotionFX::Motion* motion, const char* trackName, uint32 eventNr, MCore::CommandGroup* commandGroup) + void CommandHelperRemoveMotionEvent(EMotionFX::Motion* motion, const char* trackName, size_t eventNr, MCore::CommandGroup* commandGroup) { // make sure the motion is valid if (motion == nullptr) @@ -1127,7 +1127,7 @@ namespace CommandSystem // execute the create motion event command AZStd::string command; - command = AZStd::string::format("RemoveMotionEvent -motionID %i -eventTrackName \"%s\" -eventNr %i", motion->GetID(), trackName, eventNr); + command = AZStd::string::format("RemoveMotionEvent -motionID %i -eventTrackName \"%s\" -eventNr %zu", motion->GetID(), trackName, eventNr); // add the command to the command group if (commandGroup == nullptr) @@ -1152,7 +1152,7 @@ namespace CommandSystem // remove motion event - void CommandHelperRemoveMotionEvent(uint32 motionID, const char* trackName, uint32 eventNr, MCore::CommandGroup* commandGroup) + void CommandHelperRemoveMotionEvent(uint32 motionID, const char* trackName, size_t eventNr, MCore::CommandGroup* commandGroup) { // find the motion by id EMotionFX::Motion* motion = EMotionFX::GetMotionManager().FindMotionByID(motionID); @@ -1165,7 +1165,7 @@ namespace CommandSystem } // remove motion event - void CommandHelperRemoveMotionEvent(const char* trackName, uint32 eventNr, MCore::CommandGroup* commandGroup) + void CommandHelperRemoveMotionEvent(const char* trackName, size_t eventNr, MCore::CommandGroup* commandGroup) { EMotionFX::Motion* motion = GetCommandManager()->GetCurrentSelection().GetSingleMotion(); if (motion == nullptr) @@ -1178,7 +1178,7 @@ namespace CommandSystem // remove motion event - void CommandHelperRemoveMotionEvents(uint32 motionID, const char* trackName, const AZStd::vector& eventNumbers, MCore::CommandGroup* commandGroup) + void CommandHelperRemoveMotionEvents(uint32 motionID, const char* trackName, const AZStd::vector& eventNumbers, MCore::CommandGroup* commandGroup) { // find the motion by id EMotionFX::Motion* motion = EMotionFX::GetMotionManager().FindMotionByID(motionID); @@ -1191,11 +1191,11 @@ namespace CommandSystem MCore::CommandGroup internalCommandGroup("Remove motion events"); // get the number of events to remove and iterate through them - const int32 numEvents = eventNumbers.size(); - for (int32 i = 0; i < numEvents; ++i) + const size_t numEvents = eventNumbers.size(); + for (size_t i = 0; i < numEvents; ++i) { // remove the events from back to front - uint32 eventNr = eventNumbers[numEvents - 1 - i]; + size_t eventNr = eventNumbers[numEvents - 1 - i]; // add the command to the command group if (commandGroup == nullptr) @@ -1221,7 +1221,7 @@ namespace CommandSystem // remove motion event - void CommandHelperRemoveMotionEvents(const char* trackName, const AZStd::vector& eventNumbers, MCore::CommandGroup* commandGroup) + void CommandHelperRemoveMotionEvents(const char* trackName, const AZStd::vector& eventNumbers, MCore::CommandGroup* commandGroup) { EMotionFX::Motion* motion = GetCommandManager()->GetCurrentSelection().GetSingleMotion(); if (motion == nullptr) @@ -1233,7 +1233,7 @@ namespace CommandSystem } - void CommandHelperMotionEventTrackChanged(EMotionFX::Motion* motion, uint32 eventNr, float startTime, float endTime, const char* oldTrackName, const char* newTrackName) + void CommandHelperMotionEventTrackChanged(EMotionFX::Motion* motion, size_t eventNr, float startTime, float endTime, const char* oldTrackName, const char* newTrackName) { // get the motion event track EMotionFX::MotionEventTable* eventTable = motion->GetEventTable(); @@ -1256,7 +1256,7 @@ namespace CommandSystem // get the motion event EMotionFX::MotionEvent& motionEvent = eventTrack->GetEvent(eventNr); - commandGroup.AddCommandString(AZStd::string::format("RemoveMotionEvent -motionID %i -eventTrackName \"%s\" -eventNr %i", motion->GetID(), oldTrackName, eventNr)); + commandGroup.AddCommandString(AZStd::string::format("RemoveMotionEvent -motionID %i -eventTrackName \"%s\" -eventNr %zu", motion->GetID(), oldTrackName, eventNr)); CommandHelperAddMotionEvent(motion, newTrackName, startTime, endTime, motionEvent.GetEventDatas(), &commandGroup); // execute the command group @@ -1267,7 +1267,7 @@ namespace CommandSystem } - void CommandHelperMotionEventTrackChanged(uint32 eventNr, float startTime, float endTime, const char* oldTrackName, const char* newTrackName) + void CommandHelperMotionEventTrackChanged(size_t eventNr, float startTime, float endTime, const char* oldTrackName, const char* newTrackName) { EMotionFX::Motion* motion = GetCommandManager()->GetCurrentSelection().GetSingleMotion(); CommandHelperMotionEventTrackChanged(motion, eventNr, startTime, endTime, oldTrackName, newTrackName); diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MotionEventCommands.h b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MotionEventCommands.h index 269a0322c0..629e1e72c5 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MotionEventCommands.h +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MotionEventCommands.h @@ -55,7 +55,7 @@ namespace CommandSystem private: AZStd::string m_eventTrackName; - AZStd::optional m_eventTrackIndex; + AZStd::optional m_eventTrackIndex; AZStd::optional m_isEnabled; }; @@ -215,13 +215,13 @@ namespace CommandSystem // Command helpers ////////////////////////////////////////////////////////////////////////////////////////////////////////// void COMMANDSYSTEM_API CommandAddEventTrack(); - void COMMANDSYSTEM_API CommandRemoveEventTrack(uint32 trackIndex); - void COMMANDSYSTEM_API CommandRemoveEventTrack(EMotionFX::Motion* motion, uint32 trackIndex); - void COMMANDSYSTEM_API CommandRenameEventTrack(uint32 trackIndex, const char* newName); - void COMMANDSYSTEM_API CommandEnableEventTrack(uint32 trackIndex, bool isEnabled); + void COMMANDSYSTEM_API CommandRemoveEventTrack(size_t trackIndex); + void COMMANDSYSTEM_API CommandRemoveEventTrack(EMotionFX::Motion* motion, size_t trackIndex); + void COMMANDSYSTEM_API CommandRenameEventTrack(size_t trackIndex, const char* newName); + void COMMANDSYSTEM_API CommandEnableEventTrack(size_t trackIndex, bool isEnabled); void COMMANDSYSTEM_API CommandHelperAddMotionEvent(const char* trackName, float startTime, float endTime, const EMotionFX::EventDataSet& eventDatas = EMotionFX::EventDataSet {}, MCore::CommandGroup* commandGroup = nullptr); - void COMMANDSYSTEM_API CommandHelperRemoveMotionEvent(const char* trackName, uint32 eventNr, MCore::CommandGroup* commandGroup = nullptr); - void COMMANDSYSTEM_API CommandHelperRemoveMotionEvent(uint32 motionID, const char* trackName, uint32 eventNr, MCore::CommandGroup* commandGroup = nullptr); - void COMMANDSYSTEM_API CommandHelperRemoveMotionEvents(const char* trackName, const AZStd::vector& eventNumbers, MCore::CommandGroup* commandGroup = nullptr); - void COMMANDSYSTEM_API CommandHelperMotionEventTrackChanged(uint32 eventNr, float startTime, float endTime, const char* oldTrackName, const char* newTrackName); + void COMMANDSYSTEM_API CommandHelperRemoveMotionEvent(const char* trackName, size_t eventNr, MCore::CommandGroup* commandGroup = nullptr); + void COMMANDSYSTEM_API CommandHelperRemoveMotionEvent(uint32 motionID, const char* trackName, size_t eventNr, MCore::CommandGroup* commandGroup = nullptr); + void COMMANDSYSTEM_API CommandHelperRemoveMotionEvents(const char* trackName, const AZStd::vector& eventNumbers, MCore::CommandGroup* commandGroup = nullptr); + void COMMANDSYSTEM_API CommandHelperMotionEventTrackChanged(size_t eventNr, float startTime, float endTime, const char* oldTrackName, const char* newTrackName); } // namespace CommandSystem diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MotionSetCommands.cpp b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MotionSetCommands.cpp index 6c38a7b0db..051a0e0797 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MotionSetCommands.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MotionSetCommands.cpp @@ -159,8 +159,8 @@ namespace CommandSystem AZStd::to_string(outResult, motionSet->GetID()); // Recursively update attributes of all nodes. - const uint32 numAnimGraphs = EMotionFX::GetAnimGraphManager().GetNumAnimGraphs(); - for (uint32 i = 0; i < numAnimGraphs; ++i) + const size_t numAnimGraphs = EMotionFX::GetAnimGraphManager().GetNumAnimGraphs(); + for (size_t i = 0; i < numAnimGraphs; ++i) { EMotionFX::AnimGraph* animGraph = EMotionFX::GetAnimGraphManager().GetAnimGraph(i); @@ -266,8 +266,8 @@ namespace CommandSystem EMotionFX::GetMotionManager().RemoveMotionSet(motionSet, true); // Recursively update attributes of all nodes. - const uint32 numAnimGraphs = EMotionFX::GetAnimGraphManager().GetNumAnimGraphs(); - for (uint32 i = 0; i < numAnimGraphs; ++i) + const size_t numAnimGraphs = EMotionFX::GetAnimGraphManager().GetNumAnimGraphs(); + for (size_t i = 0; i < numAnimGraphs; ++i) { EMotionFX::AnimGraph* animGraph = EMotionFX::GetAnimGraphManager().GetAnimGraph(i); @@ -471,8 +471,8 @@ namespace CommandSystem motionSet->SetDirtyFlag(true); // Recursively update attributes of all nodes. - const uint32 numAnimGraphs = EMotionFX::GetAnimGraphManager().GetNumAnimGraphs(); - for (uint32 i = 0; i < numAnimGraphs; ++i) + const size_t numAnimGraphs = EMotionFX::GetAnimGraphManager().GetNumAnimGraphs(); + for (size_t i = 0; i < numAnimGraphs; ++i) { EMotionFX::AnimGraph* animGraph = EMotionFX::GetAnimGraphManager().GetAnimGraph(i); @@ -554,18 +554,15 @@ namespace CommandSystem m_oldMotionFilenamesAndIds.clear(); // Get the motion ids from the parameter. - const AZStd::string motionIdsString = parameters.GetValue("motionIds", this); + const AZStd::string& motionIdsString = parameters.GetValue("motionIds", this); AZStd::vector tokens; AzFramework::StringFunc::Tokenize(motionIdsString.c_str(), tokens, ";", false, true); // Iterate over all motion ids and remove the corresponding motion entries. AZStd::string failedToRemoveMotionIdsString; - const size_t tokenCount = tokens.size(); - for (size_t i = 0; i < tokenCount; ++i) + for (const AZStd::string& motionId : tokens) { - const AZStd::string& motionId = tokens[i]; - - // Get the motion entry by id string. + // Get the motion entry by id string. EMotionFX::MotionSet::MotionEntry* motionEntry = motionSet->FindMotionEntryById(motionId); if (!motionEntry) { @@ -594,8 +591,8 @@ namespace CommandSystem motionSet->SetDirtyFlag(true); // Recursively update attributes of all nodes. - const uint32 numAnimGraphs = EMotionFX::GetAnimGraphManager().GetNumAnimGraphs(); - for (uint32 i = 0; i < numAnimGraphs; ++i) + const size_t numAnimGraphs = EMotionFX::GetAnimGraphManager().GetNumAnimGraphs(); + for (size_t i = 0; i < numAnimGraphs; ++i) { EMotionFX::AnimGraph* animGraph = EMotionFX::GetAnimGraphManager().GetAnimGraph(i); @@ -673,8 +670,8 @@ namespace CommandSystem void CommandMotionSetAdjustMotion::UpdateMotionNodes(const char* oldID, const char* newID) { // iterate through the anim graphs and update all motion nodes - const uint32 numAnimGraphs = EMotionFX::GetAnimGraphManager().GetNumAnimGraphs(); - for (uint32 i = 0; i < numAnimGraphs; ++i) + const size_t numAnimGraphs = EMotionFX::GetAnimGraphManager().GetNumAnimGraphs(); + for (size_t i = 0; i < numAnimGraphs; ++i) { // get the current anim graph EMotionFX::AnimGraph* animGraph = EMotionFX::GetAnimGraphManager().GetAnimGraph(i); @@ -790,8 +787,8 @@ namespace CommandSystem } // Recursively update attributes of all nodes. - const uint32 numAnimGraphs = EMotionFX::GetAnimGraphManager().GetNumAnimGraphs(); - for (uint32 i = 0; i < numAnimGraphs; ++i) + const size_t numAnimGraphs = EMotionFX::GetAnimGraphManager().GetNumAnimGraphs(); + for (size_t i = 0; i < numAnimGraphs; ++i) { EMotionFX::AnimGraph* animGraph = EMotionFX::GetAnimGraphManager().GetAnimGraph(i); @@ -1058,8 +1055,8 @@ namespace CommandSystem } // Iterate through the child motion sets and recursively remove them. - const uint32 numChildSets = motionSet->GetNumChildSets(); - for (uint32 i = 0; i < numChildSets; ++i) + const size_t numChildSets = motionSet->GetNumChildSets(); + for (size_t i = 0; i < numChildSets; ++i) { EMotionFX::MotionSet* childSet = motionSet->GetChildSet(i); RecursivelyRemoveMotionSets(childSet, commandGroup, toBeRemoved); @@ -1077,9 +1074,9 @@ namespace CommandSystem MCore::CommandGroup internalCommandGroup("Clear motion sets"); // Iterate through all root motion sets and remove them. - const uint32 numMotionSets = EMotionFX::GetMotionManager().GetNumMotionSets(); + const size_t numMotionSets = EMotionFX::GetMotionManager().GetNumMotionSets(); AZStd::set toBeRemoved; - for (uint32 i = 0; i < numMotionSets; ++i) + for (size_t i = 0; i < numMotionSets; ++i) { // Is the given motion set a root one? Only process root motion sets in the loop and remove all others recursively. EMotionFX::MotionSet* motionSet = EMotionFX::GetMotionManager().GetMotionSet(i); @@ -1139,10 +1136,10 @@ namespace CommandSystem // Iterate over all filenames and load the motion sets. AZStd::string commandString; AZStd::set toBeRemoved; - for (size_t i = 0; i < numFilenames; ++i) + for (const AZStd::string& filename : filenames) { // In case we want to reload the same motion set remove the old version first. - EMotionFX::MotionSet* motionSet = EMotionFX::GetMotionManager().FindMotionSetByFileName(filenames[i].c_str()); + EMotionFX::MotionSet* motionSet = EMotionFX::GetMotionManager().FindMotionSetByFileName(filename.c_str()); if (reload && !clearUpfront && motionSet) { @@ -1150,15 +1147,15 @@ namespace CommandSystem } // Construct the load motion set command and add it to the group. - commandString = AZStd::string::format("LoadMotionSet -filename \"%s\"", filenames[i].c_str()); + commandString = AZStd::string::format("LoadMotionSet -filename \"%s\"", filename.c_str()); commandGroup.AddCommandString(commandString); // iterate over each actor instance and re-active the motion set if (motionSet) { - int32 commandIndex = 1; - const uint32 numActorInstances = EMotionFX::GetActorManager().GetNumActorInstances(); - for (uint32 j = 0; j < numActorInstances; ++j) + size_t commandIndex = 1; + const size_t numActorInstances = EMotionFX::GetActorManager().GetNumActorInstances(); + for (size_t j = 0; j < numActorInstances; ++j) { EMotionFX::ActorInstance* actorInstance = EMotionFX::GetActorManager().GetActorInstance(j); if (!actorInstance) @@ -1174,7 +1171,7 @@ namespace CommandSystem EMotionFX::MotionSet* currentActiveMotionSet = animGraphInstance->GetMotionSet(); if (currentActiveMotionSet == motionSet) { - commandString = AZStd::string::format("ActivateAnimGraph -actorInstanceID %d -animGraphID %d -motionSetID %%LASTRESULT%d%%", + commandString = AZStd::string::format("ActivateAnimGraph -actorInstanceID %d -animGraphID %d -motionSetID %%LASTRESULT%zu%%", actorInstance->GetID(), animGraphInstance->GetAnimGraph()->GetID(), commandIndex); diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/SelectionCommands.cpp b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/SelectionCommands.cpp index f6d03d2983..72c7338512 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/SelectionCommands.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/SelectionCommands.cpp @@ -36,11 +36,11 @@ namespace CommandSystem void SelectActorInstancesUsingCommands(const AZStd::vector& selectedActorInstances) { SelectionList& selection = GetCommandManager()->GetCurrentSelection(); - const uint32 numSelectedActorInstances = selectedActorInstances.size(); + const size_t numSelectedActorInstances = selectedActorInstances.size(); // check if the current selection is equal to the desired actor instances selection list bool nothingChanged = true; - for (uint32 i = 0; i < numSelectedActorInstances; ++i) + for (size_t i = 0; i < numSelectedActorInstances; ++i) { EMotionFX::ActorInstance* actorInstance = selectedActorInstances[i]; if (selection.CheckIfHasActorInstance(actorInstance) == false) @@ -49,7 +49,7 @@ namespace CommandSystem break; } } - for (uint32 i = 0; i < selection.GetNumSelectedActorInstances(); ++i) + for (size_t i = 0; i < selection.GetNumSelectedActorInstances(); ++i) { EMotionFX::ActorInstance* actorInstance = selection.GetActorInstance(i); if (AZStd::find(begin(selectedActorInstances), end(selectedActorInstances), actorInstance) == end(selectedActorInstances)) @@ -70,7 +70,7 @@ namespace CommandSystem // add the newly selected actor instances AZStd::string commandString; - for (uint32 a = 0; a < numSelectedActorInstances; ++a) + for (size_t a = 0; a < numSelectedActorInstances; ++a) { EMotionFX::ActorInstance* actorInstance = selectedActorInstances[a]; commandString = AZStd::string::format("Select -actorInstanceID %i -actorID %i", actorInstance->GetID(), actorInstance->GetActor()->GetID()); @@ -166,10 +166,10 @@ namespace CommandSystem // return false; SelectionList& selection = GetCommandManager()->GetCurrentSelection(); - const uint32 numActors = EMotionFX::GetActorManager().GetNumActors(); - const uint32 numActorInstances = EMotionFX::GetActorManager().GetNumActorInstances(); - const uint32 numMotions = EMotionFX::GetMotionManager().GetNumMotions(); - const uint32 numAnimGraphs = EMotionFX::GetAnimGraphManager().GetNumAnimGraphs(); + const size_t numActors = EMotionFX::GetActorManager().GetNumActors(); + const size_t numActorInstances = EMotionFX::GetActorManager().GetNumActorInstances(); + const size_t numMotions = EMotionFX::GetMotionManager().GetNumMotions(); + const size_t numAnimGraphs = EMotionFX::GetAnimGraphManager().GetNumAnimGraphs(); AZStd::string valueString; @@ -180,7 +180,7 @@ namespace CommandSystem if (AzFramework::StringFunc::Equal(valueString.c_str(), "SELECT_ALL", false /* no case */)) { // iterate through all available actors and add them to the selection - for (uint32 i = 0; i < numActors; ++i) + for (size_t i = 0; i < numActors; ++i) { EMotionFX::Actor* actor = EMotionFX::GetActorManager().GetActor(i); @@ -240,7 +240,7 @@ namespace CommandSystem } // iterate through all available actors and add them to the selection - for (uint32 i = 0; i < numActors; ++i) + for (size_t i = 0; i < numActors; ++i) { EMotionFX::Actor* actor = EMotionFX::GetActorManager().GetActor(i); @@ -271,7 +271,7 @@ namespace CommandSystem if (AzFramework::StringFunc::Equal(valueString.c_str(), "SELECT_ALL", false /* no case */)) { // iterate through all available actor instances and add them to the selection - for (uint32 i = 0; i < numActorInstances; ++i) + for (size_t i = 0; i < numActorInstances; ++i) { EMotionFX::ActorInstance* actorInstance = EMotionFX::GetActorManager().GetActorInstance(i); @@ -330,7 +330,7 @@ namespace CommandSystem } // iterate through all available motions and add them to the selection - for (uint32 i = 0; i < numMotions; ++i) + for (size_t i = 0; i < numMotions; ++i) { // get the current motion EMotionFX::Motion* motion = EMotionFX::GetMotionManager().GetMotion(i); @@ -362,7 +362,7 @@ namespace CommandSystem if (AzFramework::StringFunc::Equal(valueString.c_str(), "SELECT_ALL", false /* no case */)) { // iterate through all available motions and add them to the selection - for (uint32 i = 0; i < numMotions; ++i) + for (size_t i = 0; i < numMotions; ++i) { // get the current motion EMotionFX::Motion* motion = EMotionFX::GetMotionManager().GetMotion(i); @@ -385,7 +385,7 @@ namespace CommandSystem else { // get the motion index from the string and check if it is valid - const uint32 motionIndex = parameters.GetValueAsInt("motionIndex", command); + const size_t motionIndex = parameters.GetValueAsInt("motionIndex", command); if (motionIndex >= numMotions) { if (numMotions == 0) @@ -394,7 +394,7 @@ namespace CommandSystem } else { - outResult = AZStd::string::format("Motion index '%i' is not valid. Valid range is [0, %i].", motionIndex, numMotions - 1); + outResult = AZStd::string::format("Motion index '%zu' is not valid. Valid range is [0, %zu].", motionIndex, numMotions - 1); } return false; @@ -427,7 +427,7 @@ namespace CommandSystem if (AzFramework::StringFunc::Equal(valueString.c_str(), "SELECT_ALL", false /* no case */)) { // iterate through all available motions and add them to the selection - for (uint32 i = 0; i < numAnimGraphs; ++i) + for (size_t i = 0; i < numAnimGraphs; ++i) { // get the current anim graph EMotionFX::AnimGraph* animGraph = EMotionFX::GetAnimGraphManager().GetAnimGraph(i); @@ -450,7 +450,7 @@ namespace CommandSystem else { // get the anim graph index from the string and check if it is valid - const uint32 animGraphIndex = parameters.GetValueAsInt("animGraphIndex", command); + const size_t animGraphIndex = parameters.GetValueAsInt("animGraphIndex", command); if (animGraphIndex >= numAnimGraphs) { if (numAnimGraphs == 0) @@ -459,7 +459,7 @@ namespace CommandSystem } else { - outResult = AZStd::string::format("Anim graph index '%i' is not valid. Valid range is [0, %i].", animGraphIndex, numAnimGraphs - 1); + outResult = AZStd::string::format("Anim graph index '%zu' is not valid. Valid range is [0, %zu].", animGraphIndex, numAnimGraphs - 1); } return false; @@ -492,7 +492,7 @@ namespace CommandSystem if (AzFramework::StringFunc::Equal(valueString.c_str(), "SELECT_ALL", false /* no case */)) { // iterate through all available motions and add them to the selection - for (uint32 i = 0; i < numAnimGraphs; ++i) + for (size_t i = 0; i < numAnimGraphs; ++i) { // get the current anim graph EMotionFX::AnimGraph* animGraph = EMotionFX::GetAnimGraphManager().GetAnimGraph(i); diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/SelectionList.cpp b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/SelectionList.cpp index a6ff4de440..5910ae84f7 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/SelectionList.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/SelectionList.cpp @@ -25,14 +25,14 @@ namespace CommandSystem EMotionFX::ActorNotificationBus::Handler::BusDisconnect(); } - uint32 SelectionList::GetNumTotalItems() const + size_t SelectionList::GetNumTotalItems() const { - return static_cast(mSelectedNodes.size() + + return mSelectedNodes.size() + mSelectedActors.size() + mSelectedActorInstances.size() + mSelectedMotions.size() + mSelectedMotionInstances.size() + - mSelectedAnimGraphs.size()); + mSelectedAnimGraphs.size(); } bool SelectionList::GetIsEmpty() const @@ -113,48 +113,46 @@ namespace CommandSystem // add a complete selection list to this one void SelectionList::Add(SelectionList& selection) { - uint32 i; - // get the number of selected objects - const uint32 numSelectedNodes = selection.GetNumSelectedNodes(); - const uint32 numSelectedActors = selection.GetNumSelectedActors(); - const uint32 numSelectedActorInstances = selection.GetNumSelectedActorInstances(); - const uint32 numSelectedMotions = selection.GetNumSelectedMotions(); - const uint32 numSelectedMotionInstances = selection.GetNumSelectedMotionInstances(); - const uint32 numSelectedAnimGraphs = selection.GetNumSelectedAnimGraphs(); + const size_t numSelectedNodes = selection.GetNumSelectedNodes(); + const size_t numSelectedActors = selection.GetNumSelectedActors(); + const size_t numSelectedActorInstances = selection.GetNumSelectedActorInstances(); + const size_t numSelectedMotions = selection.GetNumSelectedMotions(); + const size_t numSelectedMotionInstances = selection.GetNumSelectedMotionInstances(); + const size_t numSelectedAnimGraphs = selection.GetNumSelectedAnimGraphs(); // iterate through all nodes and select them - for (i = 0; i < numSelectedNodes; ++i) + for (size_t i = 0; i < numSelectedNodes; ++i) { AddNode(selection.GetNode(i)); } // iterate through all actors and select them - for (i = 0; i < numSelectedActors; ++i) + for (size_t i = 0; i < numSelectedActors; ++i) { AddActor(selection.GetActor(i)); } // iterate through all actor instances and select them - for (i = 0; i < numSelectedActorInstances; ++i) + for (size_t i = 0; i < numSelectedActorInstances; ++i) { AddActorInstance(selection.GetActorInstance(i)); } // iterate through all motions and select them - for (i = 0; i < numSelectedMotions; ++i) + for (size_t i = 0; i < numSelectedMotions; ++i) { AddMotion(selection.GetMotion(i)); } // iterate through all motion instances and select them - for (i = 0; i < numSelectedMotionInstances; ++i) + for (size_t i = 0; i < numSelectedMotionInstances; ++i) { AddMotionInstance(selection.GetMotionInstance(i)); } // iterate through all anim graphs and select them - for (i = 0; i < numSelectedAnimGraphs; ++i) + for (size_t i = 0; i < numSelectedAnimGraphs; ++i) { AddAnimGraph(selection.GetAnimGraph(i)); } @@ -164,53 +162,46 @@ namespace CommandSystem // log the current selection void SelectionList::Log() { - uint32 i; - // get the number of selected objects - const uint32 numSelectedNodes = GetNumSelectedNodes(); - const uint32 numSelectedActorInstances = GetNumSelectedActorInstances(); - const uint32 numSelectedActors = GetNumSelectedActors(); - const uint32 numSelectedMotions = GetNumSelectedMotions(); - const uint32 numSelectedMotionInstances = GetNumSelectedMotionInstances(); - const uint32 numSelectedAnimGraphs = GetNumSelectedAnimGraphs(); + const size_t numSelectedNodes = GetNumSelectedNodes(); + const size_t numSelectedActorInstances = GetNumSelectedActorInstances(); + const size_t numSelectedActors = GetNumSelectedActors(); + const size_t numSelectedMotions = GetNumSelectedMotions(); + const size_t numSelectedAnimGraphs = GetNumSelectedAnimGraphs(); MCore::LogInfo("SelectionList:"); // iterate through all nodes and select them MCore::LogInfo(" - Nodes (%i)", numSelectedNodes); - for (i = 0; i < numSelectedNodes; ++i) + for (size_t i = 0; i < numSelectedNodes; ++i) { MCore::LogInfo(" + Node #%.3d: name='%s'", i, GetNode(i)->GetName()); } // iterate through all actors and select them MCore::LogInfo(" - Actors (%i)", numSelectedActors); - for (i = 0; i < numSelectedActors; ++i) + for (size_t i = 0; i < numSelectedActors; ++i) { MCore::LogInfo(" + Actor #%.3d: name='%s'", i, GetActor(i)->GetName()); } // iterate through all actor instances and select them MCore::LogInfo(" - Actor instances (%i)", numSelectedActorInstances); - for (i = 0; i < numSelectedActorInstances; ++i) + for (size_t i = 0; i < numSelectedActorInstances; ++i) { MCore::LogInfo(" + Actor instance #%.3d: name='%s'", i, GetActorInstance(i)->GetActor()->GetName()); } // iterate through all motions and select them MCore::LogInfo(" - Motions (%i)", numSelectedMotions); - for (i = 0; i < numSelectedMotions; ++i) + for (size_t i = 0; i < numSelectedMotions; ++i) { MCore::LogInfo(" + Motion #%.3d: name='%s'", i, GetMotion(i)->GetName()); } - // iterate through all motion instances and select them - MCore::LogInfo(" - Motion instances (%i)", numSelectedMotionInstances); - //for (i=0; iGetFileName()); } @@ -367,8 +358,8 @@ namespace CommandSystem void SelectionList::OnActorDestroyed(EMotionFX::Actor* actor) { const EMotionFX::Skeleton* skeleton = actor->GetSkeleton(); - const AZ::u32 numJoints = skeleton->GetNumNodes(); - for (AZ::u32 i = 0; i < numJoints; ++i) + const size_t numJoints = skeleton->GetNumNodes(); + for (size_t i = 0; i < numJoints; ++i) { EMotionFX::Node* joint = skeleton->GetNode(i); RemoveNode(joint); diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/SelectionList.h b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/SelectionList.h index 2b317fdee7..6dd1d2d4e2 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/SelectionList.h +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/SelectionList.h @@ -45,42 +45,42 @@ namespace CommandSystem * Get the number of selected nodes. * @return The number of selected nodes. */ - MCORE_INLINE uint32 GetNumSelectedNodes() const { return static_cast(mSelectedNodes.size()); } + MCORE_INLINE size_t GetNumSelectedNodes() const { return mSelectedNodes.size(); } /** * Get the number of selected actors */ - MCORE_INLINE uint32 GetNumSelectedActors() const { return static_cast(mSelectedActors.size()); } + MCORE_INLINE size_t GetNumSelectedActors() const { return mSelectedActors.size(); } /** * Get the number of selected actor instances. * @return The number of selected actor instances. */ - MCORE_INLINE uint32 GetNumSelectedActorInstances() const { return static_cast(mSelectedActorInstances.size()); } + MCORE_INLINE size_t GetNumSelectedActorInstances() const { return mSelectedActorInstances.size(); } /** * Get the number of selected motion instances. * @return The number of selected motion instances. */ - MCORE_INLINE uint32 GetNumSelectedMotionInstances() const { return static_cast(mSelectedMotionInstances.size()); } + MCORE_INLINE size_t GetNumSelectedMotionInstances() const { return mSelectedMotionInstances.size(); } /** * Get the number of selected motions. * @return The number of selected motions. */ - MCORE_INLINE uint32 GetNumSelectedMotions() const { return static_cast(mSelectedMotions.size()); } + MCORE_INLINE size_t GetNumSelectedMotions() const { return mSelectedMotions.size(); } /** * Get the number of selected anim graphs. * @return The number of selected anim graphs. */ - MCORE_INLINE uint32 GetNumSelectedAnimGraphs() const { return static_cast(mSelectedAnimGraphs.size()); } + MCORE_INLINE size_t GetNumSelectedAnimGraphs() const { return mSelectedAnimGraphs.size(); } /** * Get the total number of selected objects. * @return The number of selected nodes, actors and motions. */ - MCORE_INLINE uint32 GetNumTotalItems() const; + MCORE_INLINE size_t GetNumTotalItems() const; /** * Check whether or not the selection list contains any objects. @@ -139,7 +139,7 @@ namespace CommandSystem * @param index The index of the node to get from the selection list. * @return A pointer to the given node from the selection list. */ - MCORE_INLINE EMotionFX::Node* GetNode(uint32 index) const { return mSelectedNodes[index]; } + MCORE_INLINE EMotionFX::Node* GetNode(size_t index) const { return mSelectedNodes[index]; } /** * Get the first node from the selection list. @@ -159,7 +159,7 @@ namespace CommandSystem * @param index The index of the actor to get from the selection list. * @return A pointer to the given actor from the selection list. */ - MCORE_INLINE EMotionFX::Actor* GetActor(uint32 index) const { return mSelectedActors[index]; } + MCORE_INLINE EMotionFX::Actor* GetActor(size_t index) const { return mSelectedActors[index]; } /** * Get the first actor from the selection list. @@ -179,7 +179,7 @@ namespace CommandSystem * @param index The index of the actor instance to get from the selection list. * @return A pointer to the given actor instance from the selection list. */ - MCORE_INLINE EMotionFX::ActorInstance* GetActorInstance(uint32 index) const { return mSelectedActorInstances[index]; } + MCORE_INLINE EMotionFX::ActorInstance* GetActorInstance(size_t index) const { return mSelectedActorInstances[index]; } /** * Get the first actor instance from the selection list. @@ -199,7 +199,7 @@ namespace CommandSystem * @param index The index of the anim graph to get from the selection list. * @return A pointer to the given anim graph from the selection list. */ - MCORE_INLINE EMotionFX::AnimGraph* GetAnimGraph(uint32 index) const { return mSelectedAnimGraphs[index]; } + MCORE_INLINE EMotionFX::AnimGraph* GetAnimGraph(size_t index) const { return mSelectedAnimGraphs[index]; } /** * Get the first anim graph from the selection list. @@ -231,7 +231,7 @@ namespace CommandSystem * @param index The index of the motion to get from the selection list. * @return A pointer to the given motion from the selection list. */ - MCORE_INLINE EMotionFX::Motion* GetMotion(uint32 index) const { return mSelectedMotions[index]; } + MCORE_INLINE EMotionFX::Motion* GetMotion(size_t index) const { return mSelectedMotions[index]; } /** * Get the first motion from the selection list. @@ -257,7 +257,7 @@ namespace CommandSystem * @param index The index of the motion instance to get from the selection list. * @return A pointer to the given motion instance from the selection list. */ - MCORE_INLINE EMotionFX::MotionInstance* GetMotionInstance(uint32 index) const { return mSelectedMotionInstances[index]; } + MCORE_INLINE EMotionFX::MotionInstance* GetMotionInstance(size_t index) const { return mSelectedMotionInstances[index]; } /** * Get the first motion instance from the selection list. @@ -276,37 +276,37 @@ namespace CommandSystem * Remove the given node from the selection list. * @param index The index of the node to be removed from the selection list. */ - MCORE_INLINE void RemoveNode(uint32 index) { mSelectedNodes.erase(mSelectedNodes.begin() + index); } + MCORE_INLINE void RemoveNode(size_t index) { mSelectedNodes.erase(mSelectedNodes.begin() + index); } /** * Remove the given actor instance from the selection list. * @param index The index of the actor instance to be removed from the selection list. */ - MCORE_INLINE void RemoveActor(uint32 index) { mSelectedActors.erase(mSelectedActors.begin() + index); } + MCORE_INLINE void RemoveActor(size_t index) { mSelectedActors.erase(mSelectedActors.begin() + index); } /** * Remove the given actor instance from the selection list. * @param index The index of the actor instance to be removed from the selection list. */ - MCORE_INLINE void RemoveActorInstance(uint32 index) { mSelectedActorInstances.erase(mSelectedActorInstances.begin() + index); } + MCORE_INLINE void RemoveActorInstance(size_t index) { mSelectedActorInstances.erase(mSelectedActorInstances.begin() + index); } /** * Remove the given motion from the selection list. * @param index The index of the motion to be removed from the selection list. */ - MCORE_INLINE void RemoveMotion(uint32 index) { mSelectedMotions.erase(mSelectedMotions.begin() + index); } + MCORE_INLINE void RemoveMotion(size_t index) { mSelectedMotions.erase(mSelectedMotions.begin() + index); } /** * Remove the given motion instance from the selection list. * @param index The index of the motion instance to be removed from the selection list. */ - MCORE_INLINE void RemoveMotionInstance(uint32 index) { mSelectedMotionInstances.erase(mSelectedMotionInstances.begin() + index); } + MCORE_INLINE void RemoveMotionInstance(size_t index) { mSelectedMotionInstances.erase(mSelectedMotionInstances.begin() + index); } /** * Remove the given anim graph from the selection list. * @param index The index of the anim graph to remove from the selection list. */ - MCORE_INLINE void RemoveAnimGraph(uint32 index) { mSelectedAnimGraphs.erase(mSelectedAnimGraphs.begin() + index); } + MCORE_INLINE void RemoveAnimGraph(size_t index) { mSelectedAnimGraphs.erase(mSelectedAnimGraphs.begin() + index); } /** * Remove the given node from the selection list. diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/SimulatedObjectCommands.cpp b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/SimulatedObjectCommands.cpp index a3e98b16f8..c35b724f63 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/SimulatedObjectCommands.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/SimulatedObjectCommands.cpp @@ -34,20 +34,20 @@ namespace EMotionFX /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // CommandSimulatedObjectHelpers /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - void CommandSimulatedObjectHelpers::JointIndicesToString(const AZStd::vector& jointIndices, AZStd::string& outJointIndicesString) + void CommandSimulatedObjectHelpers::JointIndicesToString(const AZStd::vector& jointIndices, AZStd::string& outJointIndicesString) { outJointIndicesString.clear(); - for (AZ::u32 jointIndex : jointIndices) + for (size_t jointIndex : jointIndices) { if (!outJointIndicesString.empty()) { outJointIndicesString += ';'; } - outJointIndicesString += AZStd::string::format("%d", jointIndex); + outJointIndicesString += AZStd::string::format("%zu", jointIndex); } } - void CommandSimulatedObjectHelpers::StringToJointIndices(const AZStd::string& jointIndicesString, AZStd::vector& outJointIndices) + void CommandSimulatedObjectHelpers::StringToJointIndices(const AZStd::string& jointIndicesString, AZStd::vector& outJointIndices) { outJointIndices.clear(); AZStd::vector jointIndicesStrings; @@ -86,7 +86,7 @@ namespace EMotionFX return CommandSystem::GetCommandManager()->ExecuteCommandOrAddToGroup(command, commandGroup, executeInsideCommand); } - bool CommandSimulatedObjectHelpers::AddSimulatedJoints(AZ::u32 actorId, const AZStd::vector& jointIndices, size_t objectIndex, bool addChildren, + bool CommandSimulatedObjectHelpers::AddSimulatedJoints(AZ::u32 actorId, const AZStd::vector& jointIndices, size_t objectIndex, bool addChildren, MCore::CommandGroup* commandGroup, bool executeInsideCommand) { AZStd::string jointIndicesStr; @@ -102,7 +102,7 @@ namespace EMotionFX return CommandSystem::GetCommandManager()->ExecuteCommandOrAddToGroup(command, commandGroup, executeInsideCommand); } - bool CommandSimulatedObjectHelpers::RemoveSimulatedJoints(AZ::u32 actorId, const AZStd::vector& jointIndices, size_t objectIndex, bool removeChildren, + bool CommandSimulatedObjectHelpers::RemoveSimulatedJoints(AZ::u32 actorId, const AZStd::vector& jointIndices, size_t objectIndex, bool removeChildren, MCore::CommandGroup* commandGroup, bool executeInsideCommand) { AZStd::string jointIndicesStr; @@ -737,7 +737,7 @@ namespace EMotionFX } else { - for (AZ::u32 jointIndex: m_jointIndices) + for (size_t jointIndex: m_jointIndices) { object->AddSimulatedJointAndChildren(jointIndex); } @@ -878,7 +878,7 @@ namespace EMotionFX // and having to deal with merging two object. Since we are rebuilding the simulated object model when removing joints anyway, it's more convenient to serialize the whole object. m_oldContents = MCore::ReflectionSerializer::Serialize(object).GetValue(); - for (AZ::u32 jointIndex : m_jointIndices) + for (size_t jointIndex : m_jointIndices) { if (!object->FindSimulatedJointBySkeletonJointIndex(jointIndex)) { @@ -1235,8 +1235,8 @@ namespace EMotionFX bool CommandAdjustSimulatedJoint::SetCommandParameters(const MCore::CommandLine& parameters) { ParameterMixinActorId::SetCommandParameters(parameters); - m_objectIndex = static_cast(parameters.GetValueAsInt(s_objectIndexParameterName, this)); - m_jointIndex = static_cast(parameters.GetValueAsInt(s_jointIndexParameterName, this)); + m_objectIndex = parameters.GetValueAsInt(s_objectIndexParameterName, this); + m_jointIndex = parameters.GetValueAsInt(s_jointIndexParameterName, this); if (parameters.CheckIfHasParameter(s_coneAngleLimitParameterName)) { diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/SimulatedObjectCommands.h b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/SimulatedObjectCommands.h index cfb7e10f9a..b9a017d2e4 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/SimulatedObjectCommands.h +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/SimulatedObjectCommands.h @@ -16,6 +16,7 @@ #include #include #include +#include namespace AZ @@ -34,11 +35,11 @@ namespace EMotionFX public: static bool AddSimulatedObject(AZ::u32 actorId, AZStd::optional name = AZStd::nullopt, MCore::CommandGroup* commandGroup = nullptr, bool executeInsideCommand = false); static bool RemoveSimulatedObject(AZ::u32 actorId, size_t objectIndex, MCore::CommandGroup* commandGroup = nullptr, bool executeInsideCommand = false); - static bool AddSimulatedJoints(AZ::u32 actorId, const AZStd::vector& jointIndices, size_t objectIndex, bool addChildren, MCore::CommandGroup* commandGroup = nullptr, bool executeInsideCommand = false); - static bool RemoveSimulatedJoints(AZ::u32 actorId, const AZStd::vector& jointIndices, size_t objectIndex, bool removeChildren, MCore::CommandGroup* commandGroup = nullptr, bool executeInsideCommand = false); + static bool AddSimulatedJoints(AZ::u32 actorId, const AZStd::vector& jointIndices, size_t objectIndex, bool addChildren, MCore::CommandGroup* commandGroup = nullptr, bool executeInsideCommand = false); + static bool RemoveSimulatedJoints(AZ::u32 actorId, const AZStd::vector& jointIndices, size_t objectIndex, bool removeChildren, MCore::CommandGroup* commandGroup = nullptr, bool executeInsideCommand = false); - static void JointIndicesToString(const AZStd::vector& jointIndices, AZStd::string& outJointIndicesString); - static void StringToJointIndices(const AZStd::string& jointIndicesString, AZStd::vector& outJointIndices); + static void JointIndicesToString(const AZStd::vector& jointIndices, AZStd::string& outJointIndicesString); + static void StringToJointIndices(const AZStd::string& jointIndicesString, AZStd::vector& outJointIndices); static void ReplaceTag(const Actor* actor, const PhysicsSetup::ColliderConfigType colliderType, const AZStd::string& oldTag, const AZStd::string& newTag, MCore::CommandGroup& outCommandGroup); @@ -203,8 +204,8 @@ namespace EMotionFX const char* GetDescription() const override { return "Add simulated joints to a simulated object"; } MCore::Command* Create() override { return aznew CommandAddSimulatedJoints(this); } - const AZStd::vector& GetJointIndices() const { return m_jointIndices; } - void SetJointIndices(AZStd::vector newJointIndices) { m_jointIndices = AZStd::move(newJointIndices); } + const AZStd::vector& GetJointIndices() const { return m_jointIndices; } + void SetJointIndices(AZStd::vector newJointIndices) { m_jointIndices = AZStd::move(newJointIndices); } size_t GetObjectIndex() { return m_objectIndex; } void SetObjectIndex(size_t newObjectIndex ) { m_objectIndex = newObjectIndex; } @@ -215,8 +216,8 @@ namespace EMotionFX static const char* s_addChildrenParameterName; static const char* s_contentsParameterName; private: - size_t m_objectIndex = MCORE_INVALIDINDEX32; - AZStd::vector m_jointIndices; + size_t m_objectIndex = InvalidIndex; + AZStd::vector m_jointIndices; AZStd::optional m_contents; bool m_addChildren = false; bool m_oldDirtyFlag = false; @@ -245,7 +246,7 @@ namespace EMotionFX const char* GetDescription() const override { return "Remove simulated joints from a simulated object"; } MCore::Command* Create() override { return aznew CommandRemoveSimulatedJoints(this); } - const AZStd::vector& GetJointIndices() const { return m_jointIndices; } + const AZStd::vector& GetJointIndices() const { return m_jointIndices; } size_t GetObjectIndex() { return m_objectIndex; } static const char* s_commandName; @@ -254,8 +255,8 @@ namespace EMotionFX static const char* s_removeChildrenParameterName; private: - size_t m_objectIndex = MCORE_INVALIDINDEX32; - AZStd::vector m_jointIndices; + size_t m_objectIndex = InvalidIndex; + AZStd::vector m_jointIndices; AZStd::optional m_oldContents; bool m_removeChildren = false; bool m_oldDirtyFlag = false; diff --git a/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/Exporter.h b/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/Exporter.h index 290f9d4470..9cd3efc6ba 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/Exporter.h +++ b/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/Exporter.h @@ -107,8 +107,8 @@ namespace ExporterLib void SaveAttachmentNodes(MCore::Stream* file, EMotionFX::Actor* actor, const AZStd::vector& attachmentNodes, MCore::Endian::EEndianType targetEndianType); // morph targets - void SaveMorphTarget(MCore::Stream* file, EMotionFX::Actor* actor, EMotionFX::MorphTarget* inputMorphTarget, uint32 lodLevel, MCore::Endian::EEndianType targetEndianType); - void SaveMorphTargets(MCore::Stream* file, EMotionFX::Actor* actor, uint32 lodLevel, MCore::Endian::EEndianType targetEndianType); + void SaveMorphTarget(MCore::Stream* file, EMotionFX::Actor* actor, EMotionFX::MorphTarget* inputMorphTarget, size_t lodLevel, MCore::Endian::EEndianType targetEndianType); + void SaveMorphTargets(MCore::Stream* file, EMotionFX::Actor* actor, size_t lodLevel, MCore::Endian::EEndianType targetEndianType); void SaveMorphTargets(MCore::Stream* file, EMotionFX::Actor* actor, MCore::Endian::EEndianType targetEndianType); // actors diff --git a/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/MorphTargetExport.cpp b/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/MorphTargetExport.cpp index eefa92f21d..723669d3f1 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/MorphTargetExport.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/MorphTargetExport.cpp @@ -20,7 +20,7 @@ namespace ExporterLib { // save the given morph target - void SaveMorphTarget(MCore::Stream* file, EMotionFX::Actor* actor, EMotionFX::MorphTarget* inputMorphTarget, uint32 lodLevel, MCore::Endian::EEndianType targetEndianType) + void SaveMorphTarget(MCore::Stream* file, EMotionFX::Actor* actor, EMotionFX::MorphTarget* inputMorphTarget, size_t lodLevel, MCore::Endian::EEndianType targetEndianType) { MCORE_ASSERT(file); MCORE_ASSERT(actor); @@ -28,12 +28,12 @@ namespace ExporterLib MCORE_ASSERT(inputMorphTarget->GetType() == EMotionFX::MorphTargetStandard::TYPE_ID); EMotionFX::MorphTargetStandard* morphTarget = (EMotionFX::MorphTargetStandard*)inputMorphTarget; - const uint32 numTransformations = morphTarget->GetNumTransformations(); + const size_t numTransformations = morphTarget->GetNumTransformations(); // copy over the information to the chunk EMotionFX::FileFormat::Actor_MorphTarget morphTargetChunk; - morphTargetChunk.mLOD = lodLevel; - morphTargetChunk.mNumTransformations = numTransformations; + morphTargetChunk.mLOD = aznumeric_caster(lodLevel); + morphTargetChunk.mNumTransformations = aznumeric_caster(numTransformations); morphTargetChunk.mRangeMin = morphTarget->GetRangeMin(); morphTargetChunk.mRangeMax = morphTarget->GetRangeMax(); morphTargetChunk.mPhonemeSets = morphTarget->GetPhonemeSets(); @@ -60,7 +60,7 @@ namespace ExporterLib SaveString(morphTarget->GetName(), file, targetEndianType); // create and write the transformations - for (uint32 i = 0; i < numTransformations; i++) + for (size_t i = 0; i < numTransformations; i++) { EMotionFX::MorphTargetStandard::Transformation transform = morphTarget->GetTransformation(i); EMotionFX::Node* node = actor->GetSkeleton()->GetNode(transform.mNodeIndex); @@ -73,7 +73,7 @@ namespace ExporterLib // create and fill the transformation EMotionFX::FileFormat::Actor_MorphTargetTransform transformChunk; - transformChunk.mNodeIndex = transform.mNodeIndex; + transformChunk.mNodeIndex = aznumeric_caster(transform.mNodeIndex); CopyVector(transformChunk.mPosition, AZ::PackedVector3f(transform.mPosition)); CopyVector(transformChunk.mScale, AZ::PackedVector3f(transform.mScale)); CopyQuaternion(transformChunk.mRotation, transform.mRotation); @@ -99,12 +99,12 @@ namespace ExporterLib // get the size of the chunk for the given morph target - uint32 GetMorphTargetChunkSize(EMotionFX::MorphTarget* inputMorphTarget) + size_t GetMorphTargetChunkSize(EMotionFX::MorphTarget* inputMorphTarget) { MCORE_ASSERT(inputMorphTarget->GetType() == EMotionFX::MorphTargetStandard::TYPE_ID); EMotionFX::MorphTargetStandard* morphTarget = (EMotionFX::MorphTargetStandard*)inputMorphTarget; - uint32 totalSize = 0; + size_t totalSize = 0; totalSize += sizeof(EMotionFX::FileFormat::Actor_MorphTarget); totalSize += GetStringChunkSize(morphTarget->GetName()); totalSize += sizeof(EMotionFX::FileFormat::Actor_MorphTargetTransform) * morphTarget->GetNumTransformations(); @@ -114,14 +114,14 @@ namespace ExporterLib // get the size of the chunk for the complete morph setup - uint32 GetMorphSetupChunkSize(EMotionFX::MorphSetup* morphSetup) + size_t GetMorphSetupChunkSize(EMotionFX::MorphSetup* morphSetup) { // get the number of morph targets - const uint32 numMorphTargets = morphSetup->GetNumMorphTargets(); + const size_t numMorphTargets = morphSetup->GetNumMorphTargets(); // calculate the size of the chunk - uint32 totalSize = sizeof(EMotionFX::FileFormat::Actor_MorphTargets); - for (uint32 i = 0; i < numMorphTargets; ++i) + size_t totalSize = sizeof(EMotionFX::FileFormat::Actor_MorphTargets); + for (size_t i = 0; i < numMorphTargets; ++i) { totalSize += GetMorphTargetChunkSize(morphSetup->GetMorphTarget(i)); } @@ -129,15 +129,14 @@ namespace ExporterLib return totalSize; } - uint32 GetNumSavedMorphTargets(EMotionFX::MorphSetup* morphSetup) + size_t GetNumSavedMorphTargets(EMotionFX::MorphSetup* morphSetup) { return morphSetup->GetNumMorphTargets(); } // save all morph targets for a given LOD level - void SaveMorphTargets(MCore::Stream* file, EMotionFX::Actor* actor, uint32 lodLevel, MCore::Endian::EEndianType targetEndianType) + void SaveMorphTargets(MCore::Stream* file, EMotionFX::Actor* actor, size_t lodLevel, MCore::Endian::EEndianType targetEndianType) { - uint32 i; MCORE_ASSERT(file); MCORE_ASSERT(actor); @@ -148,7 +147,7 @@ namespace ExporterLib } // get the number of morph targets we need to save to the file and check if there are any at all - const uint32 numSavedMorphTargets = GetNumSavedMorphTargets(morphSetup); + const size_t numSavedMorphTargets = GetNumSavedMorphTargets(morphSetup); if (numSavedMorphTargets <= 0) { MCore::LogInfo("No morph targets to be saved in morph setup. Skipping writing morph targets."); @@ -156,10 +155,10 @@ namespace ExporterLib } // get the number of morph targets - const uint32 numMorphTargets = morphSetup->GetNumMorphTargets(); + const size_t numMorphTargets = morphSetup->GetNumMorphTargets(); // check if all morph targets have a valid name and rename them in case they are empty - for (i = 0; i < numMorphTargets; ++i) + for (size_t i = 0; i < numMorphTargets; ++i) { EMotionFX::MorphTarget* morphTarget = morphSetup->GetMorphTarget(i); @@ -177,7 +176,7 @@ namespace ExporterLib // fill in the chunk header EMotionFX::FileFormat::FileChunk chunkHeader; chunkHeader.mChunkID = EMotionFX::FileFormat::ACTOR_CHUNK_STDPMORPHTARGETS; - chunkHeader.mSizeInBytes = GetMorphSetupChunkSize(morphSetup); + chunkHeader.mSizeInBytes = aznumeric_caster(GetMorphSetupChunkSize(morphSetup)); chunkHeader.mVersion = 2; // endian convert the chunk and write it to the file @@ -186,8 +185,8 @@ namespace ExporterLib // fill in the chunk header EMotionFX::FileFormat::Actor_MorphTargets morphTargetsChunk; - morphTargetsChunk.mNumMorphTargets = numSavedMorphTargets; - morphTargetsChunk.mLOD = lodLevel; + morphTargetsChunk.mNumMorphTargets = aznumeric_caster(numSavedMorphTargets); + morphTargetsChunk.mLOD = aznumeric_caster(lodLevel); MCore::LogDetailedInfo("============================================================"); MCore::LogInfo("Morph Targets (%i, LOD=%d)", morphTargetsChunk.mNumMorphTargets, morphTargetsChunk.mLOD); @@ -199,7 +198,7 @@ namespace ExporterLib file->Write(&morphTargetsChunk, sizeof(EMotionFX::FileFormat::Actor_MorphTargets)); // save morph targets - for (i = 0; i < numMorphTargets; ++i) + for (size_t i = 0; i < numMorphTargets; ++i) { SaveMorphTarget(file, actor, morphSetup->GetMorphTarget(i), lodLevel, targetEndianType); } @@ -209,8 +208,8 @@ namespace ExporterLib void SaveMorphTargets(MCore::Stream* file, EMotionFX::Actor* actor, MCore::Endian::EEndianType targetEndianType) { // get the number of LOD levels and save the morph targets for each - const uint32 numLODLevels = actor->GetNumLODLevels(); - for (uint32 i = 0; i < numLODLevels; ++i) + const size_t numLODLevels = actor->GetNumLODLevels(); + for (size_t i = 0; i < numLODLevels; ++i) { SaveMorphTargets(file, actor, i, targetEndianType); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/NodeExport.cpp b/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/NodeExport.cpp index 4f6e5a5c52..e7f0fa011e 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/NodeExport.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/NodeExport.cpp @@ -24,12 +24,10 @@ namespace ExporterLib MCORE_ASSERT(actor); MCORE_ASSERT(node); - uint32 l; - // get some information from the node - const uint32 nodeIndex = node->GetNodeIndex(); - const uint32 parentIndex = node->GetParentIndex(); - const uint32 numChilds = node->GetNumChildNodes(); + const size_t nodeIndex = node->GetNodeIndex(); + const size_t parentIndex = node->GetParentIndex(); + const size_t numChilds = node->GetNumChildNodes(); const EMotionFX::Transform& transform = actor->GetBindPose()->GetLocalSpaceTransform(nodeIndex); AZ::PackedVector3f position = AZ::PackedVector3f(transform.mPosition); AZ::Quaternion rotation = transform.mRotation.GetNormalized(); @@ -48,12 +46,12 @@ namespace ExporterLib CopyQuaternion(nodeChunk.mLocalQuat, rotation); CopyVector(nodeChunk.mLocalScale, scale); - nodeChunk.mNumChilds = numChilds; - nodeChunk.mParentIndex = parentIndex; + nodeChunk.mNumChilds = aznumeric_caster(numChilds); + nodeChunk.mParentIndex = aznumeric_caster(parentIndex); // calculate and copy over the skeletal LODs uint32 skeletalLODs = 0; - for (l = 0; l < 32; ++l) + for (uint32 l = 0; l < 32; ++l) { if (node->GetSkeletalLODStatus(l)) { @@ -84,7 +82,7 @@ namespace ExporterLib // log the node chunk information MCore::LogDetailedInfo("- Node: name='%s' index=%i", actor->GetSkeleton()->GetNode(nodeIndex)->GetName(), nodeIndex); - if (parentIndex == MCORE_INVALIDINDEX32) + if (parentIndex == InvalidIndex) { MCore::LogDetailedInfo(" + Parent: Has no parent(root)."); } @@ -105,7 +103,7 @@ namespace ExporterLib // log skeletal lods AZStd::string lodString = " + Skeletal LODs: "; - for (l = 0; l < 32; ++l) + for (uint32 l = 0; l < 32; ++l) { int32 flag = node->GetSkeletalLODStatus(l); lodString += AZStd::to_string(flag); @@ -129,10 +127,8 @@ namespace ExporterLib void SaveNodes(MCore::Stream* file, EMotionFX::Actor* actor, MCore::Endian::EEndianType targetEndianType) { - uint32 i; - // get the number of nodes - const uint32 numNodes = actor->GetNumNodes(); + const size_t numNodes = actor->GetNumNodes(); MCore::LogDetailedInfo("============================================================"); MCore::LogInfo("Nodes (%i)", actor->GetNumNodes()); @@ -144,8 +140,8 @@ namespace ExporterLib chunkHeader.mVersion = 2; // get the nodes chunk size - chunkHeader.mSizeInBytes = sizeof(EMotionFX::FileFormat::Actor_Nodes2) + numNodes * sizeof(EMotionFX::FileFormat::Actor_Node2); - for (i = 0; i < numNodes; i++) + chunkHeader.mSizeInBytes = aznumeric_caster(sizeof(EMotionFX::FileFormat::Actor_Nodes2) + numNodes * sizeof(EMotionFX::FileFormat::Actor_Node2)); + for (size_t i = 0; i < numNodes; i++) { chunkHeader.mSizeInBytes += GetStringChunkSize(actor->GetSkeleton()->GetNode(i)->GetName()); } @@ -156,8 +152,8 @@ namespace ExporterLib // nodes chunk EMotionFX::FileFormat::Actor_Nodes2 nodesChunk; - nodesChunk.mNumNodes = numNodes; - nodesChunk.mNumRootNodes = actor->GetSkeleton()->GetNumRootNodes(); + nodesChunk.mNumNodes = aznumeric_caster(numNodes); + nodesChunk.mNumRootNodes = aznumeric_caster(actor->GetSkeleton()->GetNumRootNodes()); // endian conversion and write it ConvertUnsignedInt(&nodesChunk.mNumNodes, targetEndianType); @@ -166,21 +162,20 @@ namespace ExporterLib file->Write(&nodesChunk, sizeof(EMotionFX::FileFormat::Actor_Nodes2)); // write the nodes - for (uint32 n = 0; n < numNodes; n++) + for (size_t n = 0; n < numNodes; n++) { SaveNode(file, actor, actor->GetSkeleton()->GetNode(n), targetEndianType); } } - void SaveNodeGroup(MCore::Stream* file, EMotionFX::NodeGroup* nodeGroup, MCore::Endian::EEndianType targetEndianType) + void SaveNodeGroup(MCore::Stream* file, const EMotionFX::NodeGroup* nodeGroup, MCore::Endian::EEndianType targetEndianType) { - uint32 i; MCORE_ASSERT(file); MCORE_ASSERT(nodeGroup); // get the number of nodes in the node group - const uint32 numNodes = nodeGroup->GetNumNodes(); + const size_t numNodes = nodeGroup->GetNumNodes(); // the node group chunk EMotionFX::FileFormat::Actor_NodeGroup groupChunk; @@ -194,7 +189,7 @@ namespace ExporterLib MCore::LogDetailedInfo("- Group: name='%s'", nodeGroup->GetName()); MCore::LogDetailedInfo(" + DisabledOnDefault: %i", groupChunk.mDisabledOnDefault); AZStd::string nodesString; - for (i = 0; i < numNodes; ++i) + for (size_t i = 0; i < numNodes; ++i) { nodesString += AZStd::to_string(nodeGroup->GetNode(static_cast(i))); if (i < numNodes - 1) @@ -214,7 +209,7 @@ namespace ExporterLib SaveString(nodeGroup->GetNameString(), file, targetEndianType); // write the node numbers - for (i = 0; i < numNodes; ++i) + for (size_t i = 0; i < numNodes; ++i) { uint16 nodeNumber = nodeGroup->GetNode(static_cast(i)); if (nodeNumber == MCORE_INVALIDINDEX16) @@ -229,11 +224,10 @@ namespace ExporterLib void SaveNodeGroups(MCore::Stream* file, const AZStd::vector& nodeGroups, MCore::Endian::EEndianType targetEndianType) { - uint32 i; MCORE_ASSERT(file); // get the number of node groups - const uint32 numGroups = nodeGroups.size(); + const size_t numGroups = nodeGroups.size(); if (numGroups == 0) { @@ -251,11 +245,11 @@ namespace ExporterLib // calculate the chunk size chunkHeader.mSizeInBytes = sizeof(uint16); - for (i = 0; i < numGroups; ++i) + for (const EMotionFX::NodeGroup* nodeGroup : nodeGroups) { chunkHeader.mSizeInBytes += sizeof(EMotionFX::FileFormat::Actor_NodeGroup); - chunkHeader.mSizeInBytes += GetStringChunkSize(nodeGroups[i]->GetNameString()); - chunkHeader.mSizeInBytes += sizeof(uint16) * nodeGroups[i]->GetNumNodes(); + chunkHeader.mSizeInBytes += GetStringChunkSize(nodeGroup->GetNameString()); + chunkHeader.mSizeInBytes += sizeof(uint16) * nodeGroup->GetNumNodes(); } // endian conversion @@ -270,9 +264,9 @@ namespace ExporterLib file->Write(&numGroupsChunk, sizeof(uint16)); // iterate through all groups - for (i = 0; i < numGroups; ++i) + for (const EMotionFX::NodeGroup* nodeGroup : nodeGroups) { - SaveNodeGroup(file, nodeGroups[i], targetEndianType); + SaveNodeGroup(file, nodeGroup, targetEndianType); } } @@ -311,12 +305,12 @@ namespace ExporterLib MCORE_ASSERT(nodeMirrorInfos); - const uint32 numNodes = nodeMirrorInfos->size(); + const size_t numNodes = nodeMirrorInfos->size(); // chunk information EMotionFX::FileFormat::FileChunk chunkHeader; chunkHeader.mChunkID = EMotionFX::FileFormat::ACTOR_CHUNK_NODEMOTIONSOURCES; - chunkHeader.mSizeInBytes = sizeof(EMotionFX::FileFormat::Actor_NodeMotionSources2) + (numNodes * sizeof(uint16)) + (numNodes * sizeof(uint8) * 2); + chunkHeader.mSizeInBytes = aznumeric_caster(sizeof(EMotionFX::FileFormat::Actor_NodeMotionSources2) + (numNodes * sizeof(uint16)) + (numNodes * sizeof(uint8) * 2)); chunkHeader.mVersion = 1; // endian conversion and write it @@ -326,7 +320,7 @@ namespace ExporterLib // the node motion sources chunk data EMotionFX::FileFormat::Actor_NodeMotionSources2 nodeMotionSourcesChunk; - nodeMotionSourcesChunk.mNumNodes = numNodes; + nodeMotionSourcesChunk.mNumNodes = aznumeric_caster(numNodes); // convert endian and save to the file ConvertUnsignedInt(&nodeMotionSourcesChunk.mNumNodes, targetEndianType); @@ -339,13 +333,10 @@ namespace ExporterLib MCore::LogInfo("============================================================"); // write all node motion sources and convert endian - for (uint32 i = 0; i < numNodes; ++i) + for (const EMotionFX::Actor::NodeMirrorInfo& nodeMirrorInfo : *nodeMirrorInfos) { // get the motion node source - uint16 nodeMotionSource = nodeMirrorInfos->at(i).mSourceNode; - - //if (actor && nodeMotionSource != MCORE_INVALIDINDEX16) - //LogInfo(" + '%s' (NodeNr=%i) -> '%s' (NodeNr=%i)", actor->GetNode( i )->GetName(), i, actor->GetNode( nodeMotionSource )->GetName(), nodeMotionSource); + uint16 nodeMotionSource = nodeMirrorInfo.mSourceNode; // convert endian and save to the file ConvertUnsignedShort(&nodeMotionSource, targetEndianType); @@ -353,16 +344,16 @@ namespace ExporterLib } // write all axes - for (uint32 i = 0; i < numNodes; ++i) + for (const EMotionFX::Actor::NodeMirrorInfo& nodeMirrorInfo : *nodeMirrorInfos) { - uint8 axis = static_cast(nodeMirrorInfos->at(i).mAxis); + uint8 axis = static_cast(nodeMirrorInfo.mAxis); file->Write(&axis, sizeof(uint8)); } // write all flags - for (uint32 i = 0; i < numNodes; ++i) + for (const EMotionFX::Actor::NodeMirrorInfo& nodeMirrorInfo : *nodeMirrorInfos) { - uint8 flags = static_cast(nodeMirrorInfos->at(i).mFlags); + uint8 flags = static_cast(nodeMirrorInfo.mFlags); file->Write(&flags, sizeof(uint8)); } } @@ -371,14 +362,14 @@ namespace ExporterLib void SaveAttachmentNodes(MCore::Stream* file, EMotionFX::Actor* actor, MCore::Endian::EEndianType targetEndianType) { // get the number of nodes - const uint32 numNodes = actor->GetNumNodes(); + const size_t numNodes = actor->GetNumNodes(); // create our attachment nodes array and preallocate memory AZStd::vector attachmentNodes; attachmentNodes.reserve(numNodes); // iterate through the nodes and collect all attachments - for (uint32 i = 0; i < numNodes; ++i) + for (size_t i = 0; i < numNodes; ++i) { // get the current node, check if it is an attachment and add it to the attachment array in that case EMotionFX::Node* node = actor->GetSkeleton()->GetNode(i); @@ -403,12 +394,12 @@ namespace ExporterLib } // get the number of attachment nodes - const uint32 numAttachmentNodes = static_cast(attachmentNodes.size()); + const size_t numAttachmentNodes = attachmentNodes.size(); // chunk information EMotionFX::FileFormat::FileChunk chunkHeader; chunkHeader.mChunkID = EMotionFX::FileFormat::ACTOR_CHUNK_ATTACHMENTNODES; - chunkHeader.mSizeInBytes = sizeof(EMotionFX::FileFormat::Actor_AttachmentNodes) + numAttachmentNodes * sizeof(uint16); + chunkHeader.mSizeInBytes = aznumeric_caster(sizeof(EMotionFX::FileFormat::Actor_AttachmentNodes) + numAttachmentNodes * sizeof(uint16)); chunkHeader.mVersion = 1; // endian conversion and write it @@ -418,7 +409,7 @@ namespace ExporterLib // the attachment nodes chunk data EMotionFX::FileFormat::Actor_AttachmentNodes attachmentNodesChunk; - attachmentNodesChunk.mNumNodes = numAttachmentNodes; + attachmentNodesChunk.mNumNodes = aznumeric_caster(numAttachmentNodes); // convert endian and save to the file ConvertUnsignedInt(&attachmentNodesChunk.mNumNodes, targetEndianType); @@ -437,11 +428,9 @@ namespace ExporterLib } // write all attachment nodes and convert endian - for (uint32 i = 0; i < numAttachmentNodes; ++i) + for (uint16 nodeNr : attachmentNodes) { // get the attachment node index - uint16 nodeNr = attachmentNodes[i]; - if (actor && nodeNr != MCORE_INVALIDINDEX16) { EMotionFX::Node* node = actor->GetSkeleton()->GetNode(nodeNr); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp index 77ce4435bc..5d3f5e6ec8 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp @@ -1446,8 +1446,8 @@ namespace EMotionFX { // Optional, not all actors have morph targets. const size_t numLODLevels = m_meshAsset->GetLodAssets().size(); - mMorphSetups.Resize(static_cast(numLODLevels)); - for (AZ::u32 i = 0; i < numLODLevels; ++i) + mMorphSetups.resize(numLODLevels); + for (size_t i = 0; i < numLODLevels; ++i) { mMorphSetups[i] = nullptr; } @@ -2657,8 +2657,7 @@ namespace EMotionFX EMotionFX::SkinningInfoVertexAttributeLayer* skinLayer = static_cast(vertexAttributeLayer); const AZ::u32 numOrgVerts = skinLayer->GetNumAttributes(); - AZStd::set localJointIndices = skinLayer->CalcLocalJointIndices(numOrgVerts); - const size_t numLocalJoints = localJointIndices.size(); + const size_t numLocalJoints = skinLayer->CalcLocalJointIndices(numOrgVerts).size(); // The information about if we want to use dual quat skinning is baked into the mesh chunk and we don't have access to that // anymore. Default to dual quat skinning. @@ -2721,7 +2720,7 @@ namespace EMotionFX AZ_Assert(node, "Cannot find joint named %s in the skeleton while it is used by the skin.", pair.first.c_str()); continue; } - result.emplace(pair.second, node->GetNodeIndex()); + result.emplace(pair.second, aznumeric_caster(node->GetNodeIndex())); } return result; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.cpp index 65eb038dbf..126d376ae4 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.cpp @@ -57,7 +57,7 @@ namespace EMotionFX mAttachedTo = nullptr; mSelfAttachment = nullptr; mCustomData = nullptr; - mID = MCore::GetIDGenerator().GenerateID(); + mID = aznumeric_caster(MCore::GetIDGenerator().GenerateID()); mVisualizeScale = 1.0f; mMotionSamplingRate = 0.0f; mMotionSamplingTimer = 0.0f; @@ -465,7 +465,7 @@ namespace EMotionFX return attachment->GetAttachmentActorInstance() == actorInstance; }); - return foundAttachment == mAttachments.end() ? AZStd::distance(mAttachments.begin(), foundAttachment) : InvalidIndex; + return foundAttachment != mAttachments.end() ? AZStd::distance(mAttachments.begin(), foundAttachment) : InvalidIndex; } // remove an attachment by actor instance pointer @@ -1433,7 +1433,7 @@ namespace EMotionFX return mActor; } - void ActorInstance::SetID(size_t id) + void ActorInstance::SetID(uint32 id) { mID = id; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.h b/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.h index 620ecc29c5..05a8136326 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.h @@ -75,13 +75,13 @@ namespace EMotionFX * Get the unique identification number for the actor instance. * @return The unique identification number. */ - MCORE_INLINE size_t GetID() const { return mID; } + MCORE_INLINE uint32 GetID() const { return mID; } /** * Set the unique identification number for the actor instance. * @param[in] id The unique identification number. */ - void SetID(size_t id); + void SetID(uint32 id); /** * Get the motion system of this actor instance. @@ -895,7 +895,7 @@ namespace EMotionFX size_t mLODLevel; /**< The current LOD level, where 0 is the highest detail. */ size_t m_requestedLODLevel; /**< Requested LOD level. The actual LOD level will be updated as soon as all transforms for the requested LOD level are ready. */ uint32 mBoundsUpdateItemFreq; /**< The bounds update item counter step size. A value of 1 means every vertex/node, a value of 2 means every second vertex/node, etc. */ - size_t mID; /**< The unique identification number for the actor instance. */ + uint32 mID; /**< The unique identification number for the actor instance. */ uint32 mThreadIndex; /**< The thread index. This specifies the thread number this actor instance is being processed in. */ EBoundsType mBoundsUpdateType; /**< The bounds update type (node based, mesh based or collision mesh based). */ float m_boundsExpandBy = 0.25f; /**< Expand bounding box by normalized percentage. (Default: 25% greater than the calculated bounding box) */ diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/ActorManager.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/ActorManager.cpp index a8584163ed..b96a4b4962 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/ActorManager.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/ActorManager.cpp @@ -100,8 +100,8 @@ namespace EMotionFX mScheduler = scheduler; // adjust all visibility flags to false for all actor instances - const uint32 numActorInstances = mActorInstances.size(); - for (uint32 i = 0; i < numActorInstances; ++i) + const size_t numActorInstances = mActorInstances.size(); + for (size_t i = 0; i < numActorInstances; ++i) { mActorInstances[i]->SetIsVisible(false); } @@ -116,7 +116,7 @@ namespace EMotionFX LockActors(); // check if we already registered - if (FindActorIndex(actor.get()) != MCORE_INVALIDINDEX32) + if (FindActorIndex(actor.get()) != InvalidIndex) { MCore::LogWarning("EMotionFX::ActorManager::RegisterActor() - The actor at location 0x%x has already been registered as actor, most likely already by the LoadActor of the importer.", actor.get()); UnlockActors(); @@ -168,38 +168,38 @@ namespace EMotionFX // find the leader actor record for a given actor - uint32 ActorManager::FindActorIndex(Actor* actor) const + size_t ActorManager::FindActorIndex(Actor* actor) const { const auto found = AZStd::find_if(m_actors.begin(), m_actors.end(), [actor](const AZStd::shared_ptr& a) { return a.get() == actor; }); - return (found != m_actors.end()) ? static_cast(AZStd::distance(m_actors.begin(), found)) : MCORE_INVALIDINDEX32; + return (found != m_actors.end()) ? AZStd::distance(m_actors.begin(), found) : InvalidIndex; } // find the actor for a given actor name - uint32 ActorManager::FindActorIndexByName(const char* actorName) const + size_t ActorManager::FindActorIndexByName(const char* actorName) const { const auto found = AZStd::find_if(m_actors.begin(), m_actors.end(), [actorName](const AZStd::shared_ptr& a) { return a->GetNameString() == actorName; }); - return (found != m_actors.end()) ? static_cast(AZStd::distance(m_actors.begin(), found)) : MCORE_INVALIDINDEX32; + return (found != m_actors.end()) ? AZStd::distance(m_actors.begin(), found) : InvalidIndex; } // find the actor for a given actor filename - uint32 ActorManager::FindActorIndexByFileName(const char* filename) const + size_t ActorManager::FindActorIndexByFileName(const char* filename) const { const auto found = AZStd::find_if(m_actors.begin(), m_actors.end(), [filename](const AZStd::shared_ptr& a) { return a->GetFileNameString() == filename; }); - return (found != m_actors.end()) ? static_cast(AZStd::distance(m_actors.begin(), found)) : MCORE_INVALIDINDEX32; + return (found != m_actors.end()) ? AZStd::distance(m_actors.begin(), found) : InvalidIndex; } @@ -209,55 +209,28 @@ namespace EMotionFX LockActorInstances(); // get the number of actor instances and iterate through them - const uint32 numActorInstances = mActorInstances.size(); - for (uint32 i = 0; i < numActorInstances; ++i) - { - if (mActorInstances[i] == actorInstance) - { - UnlockActorInstances(); - return true; - } - } - - // in case we haven't found it return failure + const bool foundActor = AZStd::find(begin(mActorInstances), end(mActorInstances), actorInstance) != end(mActorInstances); UnlockActorInstances(); - return false; + return foundActor; } // find the given actor instance inside the actor manager and return its index - uint32 ActorManager::FindActorInstanceIndex(ActorInstance* actorInstance) const + size_t ActorManager::FindActorInstanceIndex(ActorInstance* actorInstance) const { - // get the number of actor instances and iterate through them - const uint32 numActorInstances = mActorInstances.size(); - for (uint32 i = 0; i < numActorInstances; ++i) - { - if (mActorInstances[i] == actorInstance) - { - return i; - } - } - - // in case we haven't found it return failure - return MCORE_INVALIDINDEX32; + const auto foundActorInstance = AZStd::find(begin(mActorInstances), end(mActorInstances), actorInstance); + return foundActorInstance != end(mActorInstances) ? AZStd::distance(begin(mActorInstances), foundActorInstance) : InvalidIndex; } // find the actor instance by the identification number ActorInstance* ActorManager::FindActorInstanceByID(uint32 id) const { - // get the number of actor instances and iterate through them - const uint32 numActorInstances = mActorInstances.size(); - for (uint32 i = 0; i < numActorInstances; ++i) + const auto foundActorInstance = AZStd::find_if(begin(mActorInstances), end(mActorInstances), [id](const ActorInstance* actorInstance) { - if (mActorInstances[i]->GetID() == id) - { - return mActorInstances[i]; - } - } - - // in case we haven't found it return failure - return nullptr; + return actorInstance->GetID() == id; + }); + return foundActorInstance != end(mActorInstances) ? *foundActorInstance : nullptr; } @@ -284,7 +257,7 @@ namespace EMotionFX // unregister a given actor instance - void ActorManager::UnregisterActorInstance(uint32 nr) + void ActorManager::UnregisterActorInstance(size_t nr) { UnregisterActorInstance(mActorInstances[nr]); } @@ -415,7 +388,7 @@ namespace EMotionFX } - Actor* ActorManager::GetActor(uint32 nr) const + Actor* ActorManager::GetActor(size_t nr) const { return m_actors[nr].get(); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/ActorManager.h b/Gems/EMotionFX/Code/EMotionFX/Source/ActorManager.h index 34b290cfff..a7f12111ce 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/ActorManager.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/ActorManager.h @@ -67,7 +67,7 @@ namespace EMotionFX * This does not include the clones that have been optionally created. * @result The number of registered actors. */ - MCORE_INLINE uint32 GetNumActors() const { return static_cast(m_actors.size()); } + MCORE_INLINE size_t GetNumActors() const { return m_actors.size(); } /** * Get a given actor. @@ -77,7 +77,7 @@ namespace EMotionFX * @param nr The actor number, which must be in range of [0..GetNumActors()-1]. * @result A reference to the actor object that contains the array of Actor objects. */ - Actor* GetActor(uint32 nr) const; + Actor* GetActor(size_t nr) const; /** * Find the given actor by name. @@ -99,7 +99,7 @@ namespace EMotionFX * @param actor The actor object you once passed to RegisterActor. * @result Returns the actor number, which is in range of [0..GetNumActors()-1], or returns MCORE_INVALIDINDEX32 when not found. */ - uint32 FindActorIndex(Actor* actor) const; + size_t FindActorIndex(Actor* actor) const; /** * Find the actor number for a given actor name. @@ -107,7 +107,7 @@ namespace EMotionFX * @param actorName The name of the actor. * @result Returns the actor number, which is in range of [0..GetNumActors()-1], or returns MCORE_INVALIDINDEX32 when not found. */ - uint32 FindActorIndexByName(const char* actorName) const; + size_t FindActorIndexByName(const char* actorName) const; /** * Find the actor number for a given actor filename. @@ -115,7 +115,7 @@ namespace EMotionFX * @param filename The filename of the actor. * @result Returns the actor number, which is in range of [0..GetNumActors()-1], or returns MCORE_INVALIDINDEX32 when not found. */ - uint32 FindActorIndexByFileName(const char* filename) const; + size_t FindActorIndexByFileName(const char* filename) const; // register the actor instance void RegisterActorInstance(ActorInstance* actorInstance); @@ -131,7 +131,7 @@ namespace EMotionFX * @param nr The actor instance number, which must be in range of [0..GetNumActorInstances()-1]. * @result A pointer to the actor instance. */ - MCORE_INLINE ActorInstance* GetActorInstance(uint32 nr) const { return mActorInstances[nr]; } + MCORE_INLINE ActorInstance* GetActorInstance(size_t nr) const { return mActorInstances[nr]; } /** * Get the array of actor instances. @@ -144,7 +144,7 @@ namespace EMotionFX * @param actorInstance A pointer to the actor instance to be searched. * @result The actor instance index for the actor manager, MCORE_INVALIDINDEX32 in case the actor instance hasn't been found. */ - uint32 FindActorInstanceIndex(ActorInstance* actorInstance) const; + size_t FindActorInstanceIndex(ActorInstance* actorInstance) const; /** * Find an actor instance inside the actor manager by its id. @@ -192,7 +192,7 @@ namespace EMotionFX * When you delete an actor instance, it automatically will unregister itself from the manager. * @param nr The actor instance number, which has to be in range of [0..GetNumActorInstances()-1]. */ - void UnregisterActorInstance(uint32 nr); + void UnregisterActorInstance(size_t nr); /** * Get the number of root actor instances. @@ -211,7 +211,7 @@ namespace EMotionFX * @param nr The root actor instance number, which must be in range of [0..GetNumRootActorInstances()-1]. * @result A pointer to the actor instance that is a root. */ - MCORE_INLINE ActorInstance* GetRootActorInstance(uint32 nr) const { return mRootActorInstances[nr]; } + MCORE_INLINE ActorInstance* GetRootActorInstance(size_t nr) const { return mRootActorInstances[nr]; } /** * Get the currently used actor update scheduler. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/ActorUpdateScheduler.h b/Gems/EMotionFX/Code/EMotionFX/Source/ActorUpdateScheduler.h index 2ad6beeacf..18fd7ff233 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/ActorUpdateScheduler.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/ActorUpdateScheduler.h @@ -63,14 +63,14 @@ namespace EMotionFX * @param actorInstance The actor instance to insert. * @param startStep An offset in the schedule where to start trying to insert the actor instances. */ - virtual void RecursiveInsertActorInstance(ActorInstance* actorInstance, uint32 startStep = 0) = 0; + virtual void RecursiveInsertActorInstance(ActorInstance* actorInstance, size_t startStep = 0) = 0; /** * Recursively remove an actor instance and its attachments from the schedule. * @param actorInstance The actor instance to remove. * @param startStep An offset in the schedule where to start trying to remove from. */ - virtual void RecursiveRemoveActorInstance(ActorInstance* actorInstance, uint32 startStep = 0) = 0; + virtual void RecursiveRemoveActorInstance(ActorInstance* actorInstance, size_t startStep = 0) = 0; /** * Remove a single actor instance from the schedule. This will not remove its attachments. @@ -78,16 +78,16 @@ namespace EMotionFX * @param startStep An offset in the schedule where to start trying to remove from. * @result Returns the offset in the schedule where the actor instance was removed. */ - virtual uint32 RemoveActorInstance(ActorInstance* actorInstance, uint32 startStep = 0) = 0; + virtual size_t RemoveActorInstance(ActorInstance* actorInstance, size_t startStep = 0) = 0; - uint32 GetNumUpdatedActorInstances() const { return mNumUpdated.GetValue(); } - uint32 GetNumVisibleActorInstances() const { return mNumVisible.GetValue(); } - uint32 GetNumSampledActorInstances() const { return mNumSampled.GetValue(); } + size_t GetNumUpdatedActorInstances() const { return mNumUpdated.GetValue(); } + size_t GetNumVisibleActorInstances() const { return mNumVisible.GetValue(); } + size_t GetNumSampledActorInstances() const { return mNumSampled.GetValue(); } protected: - MCore::AtomicUInt32 mNumUpdated; - MCore::AtomicUInt32 mNumVisible; - MCore::AtomicUInt32 mNumSampled; + MCore::AtomicSizeT mNumUpdated; + MCore::AtomicSizeT mNumVisible; + MCore::AtomicSizeT mNumSampled; /** * The constructor. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraph.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraph.cpp index f049c498f6..38fb6380e9 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraph.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraph.cpp @@ -7,6 +7,7 @@ */ #include +#include #include #include #include @@ -36,7 +37,7 @@ namespace EMotionFX AnimGraph::AnimGraph() : mGameControllerSettings(aznew AnimGraphGameControllerSettings()) { - mID = MCore::GetIDGenerator().GenerateID(); + mID = aznumeric_caster(MCore::GetIDGenerator().GenerateID()); mDirtyFlag = false; mAutoUnregister = true; mRetarget = false; @@ -344,12 +345,12 @@ namespace EMotionFX AZStd::string AnimGraph::GenerateNodeName(const AZStd::unordered_set& nameReserveList, const char* prefix) const { AZStd::string result; - uint32 number = 0; + size_t number = 0; bool found = false; while (found == false) { // build the string - result = AZStd::string::format("%s%d", prefix, number++); + result = AZStd::string::format("%s%zu", prefix, number++); // if there is no such state machine yet if (!RecursiveFindNodeByName(result.c_str()) && nameReserveList.find(result) == nameReserveList.end()) @@ -362,7 +363,7 @@ namespace EMotionFX } - uint32 AnimGraph::RecursiveCalcNumNodes() const + size_t AnimGraph::RecursiveCalcNumNodes() const { return mRootStateMachine->RecursiveCalcNumNodes(); } @@ -385,9 +386,9 @@ namespace EMotionFX } - void AnimGraph::RecursiveCalcStatistics(Statistics& outStatistics, AnimGraphNode* animGraphNode, uint32 currentHierarchyDepth) const + void AnimGraph::RecursiveCalcStatistics(Statistics& outStatistics, AnimGraphNode* animGraphNode, size_t currentHierarchyDepth) const { - outStatistics.m_maxHierarchyDepth = MCore::Max(currentHierarchyDepth, outStatistics.m_maxHierarchyDepth); + outStatistics.m_maxHierarchyDepth = AZStd::max(currentHierarchyDepth, outStatistics.m_maxHierarchyDepth); // Are we dealing with a state machine? If yes, increase the number of transitions, states etc. in the statistics. if (azrtti_typeid(animGraphNode) == azrtti_typeid()) @@ -395,12 +396,12 @@ namespace EMotionFX AnimGraphStateMachine* stateMachine = static_cast(animGraphNode); outStatistics.m_numStateMachines++; - const AZ::u32 numTransitions = static_cast(stateMachine->GetNumTransitions()); + const size_t numTransitions = stateMachine->GetNumTransitions(); outStatistics.m_numTransitions += numTransitions; outStatistics.m_numStates += stateMachine->GetNumChildNodes(); - for (uint32 i = 0; i < numTransitions; ++i) + for (size_t i = 0; i < numTransitions; ++i) { AnimGraphStateTransition* transition = stateMachine->GetTransition(i); @@ -409,12 +410,12 @@ namespace EMotionFX outStatistics.m_numWildcardTransitions++; } - outStatistics.m_numTransitionConditions += static_cast(transition->GetNumConditions()); + outStatistics.m_numTransitionConditions += transition->GetNumConditions(); } } - const uint32 numChildNodes = animGraphNode->GetNumChildNodes(); - for (uint32 i = 0; i < numChildNodes; ++i) + const size_t numChildNodes = animGraphNode->GetNumChildNodes(); + for (size_t i = 0; i < numChildNodes; ++i) { RecursiveCalcStatistics(outStatistics, animGraphNode->GetChildNode(i), currentHierarchyDepth + 1); } @@ -422,7 +423,7 @@ namespace EMotionFX // recursively calculate the number of node connections - uint32 AnimGraph::RecursiveCalcNumNodeConnections() const + size_t AnimGraph::RecursiveCalcNumNodeConnections() const { return mRootStateMachine->RecursiveCalcNumNodeConnections(); } @@ -491,7 +492,7 @@ namespace EMotionFX // get a pointer to the given node group - AnimGraphNodeGroup* AnimGraph::GetNodeGroup(uint32 index) const + AnimGraphNodeGroup* AnimGraph::GetNodeGroup(size_t index) const { return mNodeGroups[index]; } @@ -514,19 +515,13 @@ namespace EMotionFX // find the node group index by name - uint32 AnimGraph::FindNodeGroupIndexByName(const char* groupName) const + size_t AnimGraph::FindNodeGroupIndexByName(const char* groupName) const { - const size_t numNodeGroups = mNodeGroups.size(); - for (size_t i = 0; i < numNodeGroups; ++i) + const auto foundNodeGroup = AZStd::find_if(begin(mNodeGroups), end(mNodeGroups), [groupName](const AnimGraphNodeGroup* nodeGroup) { - // compare the node names and return the index in case they are equal - if (mNodeGroups[i]->GetNameString() == groupName) - { - return static_cast(i); - } - } - - return MCORE_INVALIDINDEX32; + return nodeGroup->GetNameString() == groupName; + }); + return foundNodeGroup != end(mNodeGroups) ? AZStd::distance(begin(mNodeGroups), foundNodeGroup) : InvalidIndex; } @@ -538,7 +533,7 @@ namespace EMotionFX // remove the node group at the given index from the anim graph - void AnimGraph::RemoveNodeGroup(uint32 index, bool delFromMem) + void AnimGraph::RemoveNodeGroup(size_t index, bool delFromMem) { // destroy the object if (delFromMem) @@ -569,9 +564,9 @@ namespace EMotionFX // get the number of node groups - uint32 AnimGraph::GetNumNodeGroups() const + size_t AnimGraph::GetNumNodeGroups() const { - return static_cast(mNodeGroups.size()); + return mNodeGroups.size(); } @@ -716,7 +711,7 @@ namespace EMotionFX MCore::LockGuard lock(mLock); // assign the index and add it to the objects array - object->SetObjectIndex(static_cast(mObjects.size())); + object->SetObjectIndex(mObjects.size()); mObjects.push_back(object); // if it's a node, add it to the nodes array as well @@ -761,10 +756,10 @@ namespace EMotionFX if (azrtti_istypeof(object)) { AnimGraphNode* node = static_cast(object); - const uint32 nodeIndex = node->GetNodeIndex(); + const size_t nodeIndex = node->GetNodeIndex(); - const uint32 numNodes = mNodes.size(); - for (uint32 i = nodeIndex + 1; i < numNodes; ++i) + const size_t numNodes = mNodes.size(); + for (size_t i = nodeIndex + 1; i < numNodes; ++i) { AnimGraphNode* curNode = mNodes[i]; MCORE_ASSERT(i == curNode->GetNodeIndex()); @@ -778,32 +773,26 @@ namespace EMotionFX // reserve space for a given amount of objects - void AnimGraph::ReserveNumObjects(uint32 numObjects) + void AnimGraph::ReserveNumObjects(size_t numObjects) { mObjects.reserve(numObjects); } // reserve space for a given amount of nodes - void AnimGraph::ReserveNumNodes(uint32 numNodes) + void AnimGraph::ReserveNumNodes(size_t numNodes) { mNodes.reserve(numNodes); } // Calculate number of motion nodes in the graph - uint32 AnimGraph::CalcNumMotionNodes() const + size_t AnimGraph::CalcNumMotionNodes() const { - const uint32 numNodes = mNodes.size(); - uint32 numMotionNodes = 0; - for (uint32 i = 0; i < numNodes; ++i) + return AZStd::accumulate(begin(mNodes), end(mNodes), size_t{0}, [](size_t total, const AnimGraphNode* node) { - if (azrtti_istypeof(mNodes[i])) - { - numMotionNodes++; - } - } - return numMotionNodes; + return total + azrtti_istypeof(node); + }); } @@ -831,7 +820,7 @@ namespace EMotionFX // decrease internal attribute indices by one, for values higher than the given parameter - void AnimGraph::DecreaseInternalAttributeIndices(uint32 decreaseEverythingHigherThan) + void AnimGraph::DecreaseInternalAttributeIndices(size_t decreaseEverythingHigherThan) { for (AnimGraphObject* object : mObjects) { @@ -1027,11 +1016,9 @@ namespace EMotionFX void AnimGraph::RemoveInvalidConnections(bool logWarnings) { // Iterate over all nodes - const AZ::u32 numNodes = mNodes.size(); - for (AZ::u32 i = 0; i < numNodes; ++i) + for (AnimGraphNode* node : mNodes) { - AnimGraphNode* node = mNodes[i]; - for (AZ::u32 c = 0; c < node->GetNumConnections();) + for (size_t c = 0; c < node->GetNumConnections();) { BlendTreeConnection* connection = node->GetConnection(c); if (!connection->GetSourceNode()) // Invalid source node. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraph.h b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraph.h index ab1cfd926f..a356b031aa 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraph.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraph.h @@ -72,24 +72,24 @@ namespace EMotionFX void RecursiveCollectObjectsAffectedBy(AnimGraph* animGraph, AZStd::vector& outObjects); - uint32 RecursiveCalcNumNodes() const; + size_t RecursiveCalcNumNodes() const; struct Statistics { - AZ::u32 m_maxHierarchyDepth; - AZ::u32 m_numStateMachines; - AZ::u32 m_numStates; - AZ::u32 m_numTransitions; - AZ::u32 m_numWildcardTransitions; - AZ::u32 m_numTransitionConditions; + size_t m_maxHierarchyDepth; + size_t m_numStateMachines; + size_t m_numStates; + size_t m_numTransitions; + size_t m_numWildcardTransitions; + size_t m_numTransitionConditions; Statistics(); }; void RecursiveCalcStatistics(Statistics& outStatistics) const; - uint32 RecursiveCalcNumNodeConnections() const; + size_t RecursiveCalcNumNodeConnections() const; - void DecreaseInternalAttributeIndices(uint32 decreaseEverythingHigherThan); + void DecreaseInternalAttributeIndices(size_t decreaseEverythingHigherThan); AZStd::string GenerateNodeName(const AZStd::unordered_set& nameReserveList, const char* prefix = "Node") const; @@ -313,13 +313,13 @@ namespace EMotionFX * Get the number of node groups. * @result The number of node groups. */ - uint32 GetNumNodeGroups() const; + size_t GetNumNodeGroups() const; /** * Get a pointer to the given node group. * @param index The node group index, which must be in range of [0..GetNumNodeGroups()-1]. */ - AnimGraphNodeGroup* GetNodeGroup(uint32 index) const; + AnimGraphNodeGroup* GetNodeGroup(size_t index) const; /** * Find a node group based on the name and return a pointer. @@ -333,7 +333,7 @@ namespace EMotionFX * @param groupName The group name to search for. * @result The index of the node group inside this anim graph, MCORE_INVALIDINDEX32 in case the node group wasn't found. */ - uint32 FindNodeGroupIndexByName(const char* groupName) const; + size_t FindNodeGroupIndexByName(const char* groupName) const; /** * Add the given node group. @@ -346,7 +346,7 @@ namespace EMotionFX * @param index The node group index to remove. This value must be in range of [0..GetNumNodeGroups()-1]. * @param delFromMem Set to true (default) when you wish to also delete the specified group from memory. */ - void RemoveNodeGroup(uint32 index, bool delFromMem = true); + void RemoveNodeGroup(size_t index, bool delFromMem = true); /** * Remove all node groups. @@ -377,14 +377,14 @@ namespace EMotionFX void AddObject(AnimGraphObject* object); // registers the object in the array and modifies the object's object index value void RemoveObject(AnimGraphObject* object); // doesn't actually remove it from memory, just removes it from the list - uint32 GetNumObjects() const { return static_cast(mObjects.size()); } - AnimGraphObject* GetObject(uint32 index) const { return mObjects[index]; } - void ReserveNumObjects(uint32 numObjects); + size_t GetNumObjects() const { return mObjects.size(); } + AnimGraphObject* GetObject(size_t index) const { return mObjects[index]; } + void ReserveNumObjects(size_t numObjects); size_t GetNumNodes() const { return mNodes.size(); } - AnimGraphNode* GetNode(uint32 index) const { return mNodes[index]; } - void ReserveNumNodes(uint32 numNodes); - uint32 CalcNumMotionNodes() const; + AnimGraphNode* GetNode(size_t index) const { return mNodes[index]; } + void ReserveNumNodes(size_t numNodes); + size_t CalcNumMotionNodes() const; size_t GetNumAnimGraphInstances() const { return m_animGraphInstances.size(); } AnimGraphInstance* GetAnimGraphInstance(size_t index) const { return m_animGraphInstances[index]; } @@ -405,7 +405,7 @@ namespace EMotionFX void RemoveInvalidConnections(bool logWarnings=false); private: - void RecursiveCalcStatistics(Statistics& outStatistics, AnimGraphNode* animGraphNode, uint32 currentHierarchyDepth = 0) const; + void RecursiveCalcStatistics(Statistics& outStatistics, AnimGraphNode* animGraphNode, size_t currentHierarchyDepth = 0) const; void OnRetargetingEnabledChanged(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphAttributeTypes.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphAttributeTypes.cpp index 069da49e27..497fd4c65c 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphAttributeTypes.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphAttributeTypes.cpp @@ -53,7 +53,7 @@ namespace EMotionFX //--------------------------------------------------------------------------------------------------------------------- - void AnimGraphPropertyUtils::ReinitJointIndices(const Actor* actor, const AZStd::vector& jointNames, AZStd::vector& outJointIndices) + void AnimGraphPropertyUtils::ReinitJointIndices(const Actor* actor, const AZStd::vector& jointNames, AZStd::vector& outJointIndices) { const Skeleton* skeleton = actor->GetSkeleton(); const size_t jointCount = jointNames.size(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphAttributeTypes.h b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphAttributeTypes.h index d63d67be43..e0f6712145 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphAttributeTypes.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphAttributeTypes.h @@ -132,7 +132,7 @@ namespace EMotionFX class AnimGraphPropertyUtils { public: - static void ReinitJointIndices(const Actor* actor, const AZStd::vector& jointNames, AZStd::vector& outJointIndices); + static void ReinitJointIndices(const Actor* actor, const AZStd::vector& jointNames, AZStd::vector& outJointIndices); }; } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphEventBuffer.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphEventBuffer.cpp index 7a241ec18e..0403e277b6 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphEventBuffer.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphEventBuffer.cpp @@ -76,12 +76,12 @@ namespace EMotionFX } } - void AnimGraphEventBuffer::Reserve(uint32 numEvents) + void AnimGraphEventBuffer::Reserve(size_t numEvents) { m_events.reserve(numEvents); } - void AnimGraphEventBuffer::Resize(uint32 numEvents) + void AnimGraphEventBuffer::Resize(size_t numEvents) { m_events.resize(numEvents); } @@ -93,12 +93,12 @@ namespace EMotionFX void AnimGraphEventBuffer::AddAllEventsFrom(const AnimGraphEventBuffer& eventBuffer) { - const AZ::u32 numEventsToCopy = eventBuffer.GetNumEvents(); - const uint32 numPrevEvents = GetNumEvents(); + const size_t numEventsToCopy = eventBuffer.GetNumEvents(); + const size_t numPrevEvents = GetNumEvents(); Resize(GetNumEvents() + numEventsToCopy); - for (uint32 i = 0; i < numEventsToCopy; ++i) + for (size_t i = 0; i < numEventsToCopy; ++i) { SetEvent(numPrevEvents + i, eventBuffer.GetEvent(i)); } @@ -109,7 +109,7 @@ namespace EMotionFX m_events.clear(); } - void AnimGraphEventBuffer::SetEvent(uint32 index, const EventInfo& eventInfo) + void AnimGraphEventBuffer::SetEvent(size_t index, const EventInfo& eventInfo) { m_events[index] = eventInfo; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphEventBuffer.h b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphEventBuffer.h index b2d049cf66..b21fa0b44a 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphEventBuffer.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphEventBuffer.h @@ -38,8 +38,8 @@ namespace EMotionFX AnimGraphEventBuffer& operator=(const AnimGraphEventBuffer&) = default; AnimGraphEventBuffer& operator=(AnimGraphEventBuffer&&) = default; - void Reserve(uint32 numEvents); - void Resize(uint32 numEvents); + void Reserve(size_t numEvents); + void Resize(size_t numEvents); void AddEvent(const EventInfo& newEvent); void AddAllEventsFrom(const AnimGraphEventBuffer& eventBuffer); @@ -49,11 +49,11 @@ namespace EMotionFX m_events.emplace_back(AZStd::forward(args)...); } - void SetEvent(uint32 index, const EventInfo& eventInfo); + void SetEvent(size_t index, const EventInfo& eventInfo); void Clear(); - MCORE_INLINE uint32 GetNumEvents() const { return static_cast(m_events.size()); } - MCORE_INLINE const EventInfo& GetEvent(uint32 index) const { return m_events[index]; } + MCORE_INLINE size_t GetNumEvents() const { return m_events.size(); } + MCORE_INLINE const EventInfo& GetEvent(size_t index) const { return m_events[index]; } void TriggerEvents() const; void UpdateWeights(AnimGraphInstance* animGraphInstance); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphInstance.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphInstance.cpp index 1082bc112b..c31f584498 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphInstance.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphInstance.cpp @@ -143,12 +143,11 @@ namespace EMotionFX { if (delFromMem) { - const uint32 numParams = mParamValues.size(); - for (uint32 i = 0; i < numParams; ++i) + for (MCore::Attribute* mParamValue : mParamValues) { - if (mParamValues[i]) + if (mParamValue) { - delete mParamValues[i]; + delete mParamValue; } } } @@ -172,12 +171,12 @@ namespace EMotionFX } - uint32 AnimGraphInstance::AddInternalAttribute(MCore::Attribute* attribute) + size_t AnimGraphInstance::AddInternalAttribute(MCore::Attribute* attribute) { MCore::LockGuard lock(mMutex); m_internalAttributes.emplace_back(attribute); - return static_cast(m_internalAttributes.size() - 1); + return m_internalAttributes.size() - 1; } @@ -266,11 +265,11 @@ namespace EMotionFX RemoveAllParameters(true); const ValueParameterVector& valueParameters = mAnimGraph->RecursivelyGetValueParameters(); - mParamValues.resize(static_cast(valueParameters.size())); + mParamValues.resize(valueParameters.size()); // init the values - const uint32 numParams = mParamValues.size(); - for (uint32 i = 0; i < numParams; ++i) + const size_t numParams = mParamValues.size(); + for (size_t i = 0; i < numParams; ++i) { mParamValues[i] = valueParameters[i]->ConstructDefaultValueAsAttribute(); } @@ -282,28 +281,27 @@ namespace EMotionFX { // check how many parameters we need to add const ValueParameterVector& valueParameters = mAnimGraph->RecursivelyGetValueParameters(); - const int32 numToAdd = static_cast(valueParameters.size()) - mParamValues.size(); + const ptrdiff_t numToAdd = aznumeric_cast(valueParameters.size()) - mParamValues.size(); if (numToAdd <= 0) { return; } // make sure we have the right space pre-allocated - mParamValues.reserve(static_cast(valueParameters.size())); + mParamValues.reserve(valueParameters.size()); // add the remaining parameters - const uint32 startIndex = mParamValues.size(); - for (int32 i = 0; i < numToAdd; ++i) + const size_t startIndex = mParamValues.size(); + for (ptrdiff_t i = 0; i < numToAdd; ++i) { - const uint32 index = startIndex + i; - mParamValues.emplace_back(); - mParamValues.back() = valueParameters[index]->ConstructDefaultValueAsAttribute(); + const size_t index = startIndex + i; + mParamValues.emplace_back(valueParameters[index]->ConstructDefaultValueAsAttribute()); } } // remove a parameter value - void AnimGraphInstance::RemoveParameterValue(uint32 index, bool delFromMem) + void AnimGraphInstance::RemoveParameterValue(size_t index, bool delFromMem) { if (delFromMem) { @@ -318,7 +316,7 @@ namespace EMotionFX // reinitialize the parameter - void AnimGraphInstance::ReInitParameterValue(uint32 index) + void AnimGraphInstance::ReInitParameterValue(size_t index) { if (mParamValues[index]) { @@ -331,8 +329,8 @@ namespace EMotionFX void AnimGraphInstance::ReInitParameterValues() { - const AZ::u32 parameterValueCount = mParamValues.size(); - for (AZ::u32 i = 0; i < parameterValueCount; ++i) + const size_t parameterValueCount = mParamValues.size(); + for (size_t i = 0; i < parameterValueCount; ++i) { ReInitParameterValue(i); } @@ -440,8 +438,8 @@ namespace EMotionFX else { // get the number of child nodes, iterate through them and call the function recursively in case we are dealing with a blend tree or another node - const uint32 numChildNodes = node->GetNumChildNodes(); - for (uint32 i = 0; i < numChildNodes; ++i) + const size_t numChildNodes = node->GetNumChildNodes(); + for (size_t i = 0; i < numChildNodes; ++i) { RecursiveSwitchToEntryState(node->GetChildNode(i)); } @@ -470,8 +468,8 @@ namespace EMotionFX } // get the number of child nodes, iterate through them and call the function recursively - const uint32 numChildNodes = node->GetNumChildNodes(); - for (uint32 i = 0; i < numChildNodes; ++i) + const size_t numChildNodes = node->GetNumChildNodes(); + for (size_t i = 0; i < numChildNodes; ++i) { RecursiveResetCurrentState(node->GetChildNode(i)); } @@ -494,7 +492,7 @@ namespace EMotionFX return nullptr; } - return mParamValues[static_cast(paramIndex.GetValue())]; + return mParamValues[paramIndex.GetValue()]; } @@ -507,7 +505,7 @@ namespace EMotionFX // add the parameter of the animgraph, at a given index - void AnimGraphInstance::InsertParameterValue(uint32 index) + void AnimGraphInstance::InsertParameterValue(size_t index) { mParamValues.emplace(AZStd::next(begin(mParamValues), index), nullptr); ReInitParameterValue(index); @@ -515,7 +513,7 @@ namespace EMotionFX // move the parameter from old index to new index - void AnimGraphInstance::MoveParameterValue(uint32 oldIndex, uint32 newIndex) + void AnimGraphInstance::MoveParameterValue(size_t oldIndex, size_t newIndex) { MCore::Attribute* oldAttribute = mParamValues[oldIndex]; @@ -523,18 +521,18 @@ namespace EMotionFX // otherwise, move to the left of new index if (oldIndex > newIndex) { - for (uint32 paramIndex = oldIndex; paramIndex > newIndex; paramIndex--) + for (size_t paramIndex = oldIndex; paramIndex > newIndex; paramIndex--) { - const uint32 prevIndex = paramIndex - 1; + const size_t prevIndex = paramIndex - 1; mParamValues[paramIndex] = mParamValues[prevIndex]; } mParamValues[newIndex] = oldAttribute; } else { - for (uint32 paramIndex = oldIndex; paramIndex < newIndex; paramIndex++) + for (size_t paramIndex = oldIndex; paramIndex < newIndex; paramIndex++) { - const uint32 nexIndex = paramIndex + 1; + const size_t nexIndex = paramIndex + 1; mParamValues[paramIndex] = mParamValues[nexIndex]; } mParamValues[newIndex] = oldAttribute; @@ -609,7 +607,7 @@ namespace EMotionFX // find an actor instance based on a parent depth value - ActorInstance* AnimGraphInstance::FindActorInstanceFromParentDepth(uint32 parentDepth) const + ActorInstance* AnimGraphInstance::FindActorInstanceFromParentDepth(size_t parentDepth) const { // start with the actor instance this anim graph instance is working on ActorInstance* curInstance = mActorInstance; @@ -619,7 +617,7 @@ namespace EMotionFX } // repeat until we are at the root - uint32 depth = 1; + size_t depth = 1; while (curInstance) { // get the attachment object @@ -667,7 +665,7 @@ namespace EMotionFX return; } - const uint32 index = uniqueData->GetObject()->GetObjectIndex(); + const size_t index = uniqueData->GetObject()->GetObjectIndex(); if (delFromMem && m_uniqueDatas[index]) { m_uniqueDatas[index]->Destroy(); @@ -682,7 +680,7 @@ namespace EMotionFX { AnimGraphObjectData* data = m_uniqueDatas[index]; m_uniqueDatas.erase(m_uniqueDatas.begin() + index); - mObjectFlags.erase(AZStd::next(begin(mObjectFlags), static_cast(index))); + mObjectFlags.erase(AZStd::next(begin(mObjectFlags), index)); if (delFromMem && data) { data->Destroy(); @@ -809,10 +807,10 @@ namespace EMotionFX // init the hashmap void AnimGraphInstance::InitUniqueDatas() { - const uint32 numObjects = mAnimGraph->GetNumObjects(); + const size_t numObjects = mAnimGraph->GetNumObjects(); m_uniqueDatas.resize(numObjects); mObjectFlags.resize(numObjects); - for (uint32 i = 0; i < numObjects; ++i) + for (size_t i = 0; i < numObjects; ++i) { m_uniqueDatas[i] = nullptr; mObjectFlags[i] = 0; @@ -932,10 +930,9 @@ namespace EMotionFX // reset all node flags void AnimGraphInstance::ResetFlagsForAllObjects(uint32 flagsToDisable) { - const uint32 numObjects = mObjectFlags.size(); - for (uint32 i = 0; i < numObjects; ++i) + for (uint32& mObjectFlag : mObjectFlags) { - mObjectFlags[i] &= ~flagsToDisable; + mObjectFlag &= ~flagsToDisable; } } @@ -943,8 +940,8 @@ namespace EMotionFX // reset all node pose ref counts void AnimGraphInstance::ResetPoseRefCountsForAllNodes() { - const uint32 numNodes = mAnimGraph->GetNumNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = mAnimGraph->GetNumNodes(); + for (size_t i = 0; i < numNodes; ++i) { mAnimGraph->GetNode(i)->ResetPoseRefCount(this); } @@ -954,8 +951,8 @@ namespace EMotionFX // reset all node pose ref counts void AnimGraphInstance::ResetRefDataRefCountsForAllNodes() { - const uint32 numNodes = mAnimGraph->GetNumNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = mAnimGraph->GetNumNodes(); + for (size_t i = 0; i < numNodes; ++i) { mAnimGraph->GetNode(i)->ResetRefDataRefCount(this); } @@ -977,8 +974,8 @@ namespace EMotionFX // reset flags for all nodes void AnimGraphInstance::ResetFlagsForAllNodes(uint32 flagsToDisable) { - const uint32 numNodes = mAnimGraph->GetNumNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = mAnimGraph->GetNumNodes(); + for (size_t i = 0; i < numNodes; ++i) { AnimGraphNode* node = mAnimGraph->GetNode(i); mObjectFlags[node->GetObjectIndex()] &= ~flagsToDisable; @@ -986,8 +983,8 @@ namespace EMotionFX if (GetEMotionFX().GetIsInEditorMode()) { // reset all connections - const uint32 numConnections = node->GetNumConnections(); - for (uint32 c = 0; c < numConnections; ++c) + const size_t numConnections = node->GetNumConnections(); + for (size_t c = 0; c < numConnections; ++c) { node->GetConnection(c)->SetIsVisited(false); } @@ -1024,7 +1021,7 @@ namespace EMotionFX AnimGraphObjectData* AnimGraphInstance::FindOrCreateUniqueObjectData(const AnimGraphObject* object) { - const AZ::u32 objectIndex = object->GetObjectIndex(); + const size_t objectIndex = object->GetObjectIndex(); AnimGraphObjectData* uniqueData = m_uniqueDatas[objectIndex]; if (uniqueData) { @@ -1062,8 +1059,8 @@ namespace EMotionFX // init all internal attributes void AnimGraphInstance::InitInternalAttributes() { - const uint32 numNodes = mAnimGraph->GetNumNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = mAnimGraph->GetNumNodes(); + for (size_t i = 0; i < numNodes; ++i) { mAnimGraph->GetNode(i)->InitInternalAttributes(this); } @@ -1258,8 +1255,8 @@ namespace EMotionFX const uint32 threadIndex = mActorInstance->GetThreadIndex(); AnimGraphRefCountedDataPool& refDataPool = GetEMotionFX().GetThreadData(threadIndex)->GetRefCountedDataPool(); - const uint32 numNodes = mAnimGraph->GetNumNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = mAnimGraph->GetNumNodes(); + for (size_t i = 0; i < numNodes; ++i) { const AnimGraphNode* node = mAnimGraph->GetNode(i); AnimGraphNodeData* nodeData = static_cast(m_uniqueDatas[node->GetObjectIndex()]); @@ -1292,7 +1289,7 @@ namespace EMotionFX } } - bool AnimGraphInstance::GetParameterValueAsFloat(uint32 paramIndex, float* outValue) + bool AnimGraphInstance::GetParameterValueAsFloat(size_t paramIndex, float* outValue) { MCore::AttributeFloat* floatAttribute = GetParameterValueChecked(paramIndex); if (floatAttribute) @@ -1318,7 +1315,7 @@ namespace EMotionFX return false; } - bool AnimGraphInstance::GetParameterValueAsBool(uint32 paramIndex, bool* outValue) + bool AnimGraphInstance::GetParameterValueAsBool(size_t paramIndex, bool* outValue) { float floatValue; if (GetParameterValueAsFloat(paramIndex, &floatValue)) @@ -1331,7 +1328,7 @@ namespace EMotionFX } - bool AnimGraphInstance::GetParameterValueAsInt(uint32 paramIndex, int32* outValue) + bool AnimGraphInstance::GetParameterValueAsInt(size_t paramIndex, int32* outValue) { float floatValue; if (GetParameterValueAsFloat(paramIndex, &floatValue)) @@ -1344,7 +1341,7 @@ namespace EMotionFX } - bool AnimGraphInstance::GetVector2ParameterValue(uint32 paramIndex, AZ::Vector2* outValue) + bool AnimGraphInstance::GetVector2ParameterValue(size_t paramIndex, AZ::Vector2* outValue) { MCore::AttributeVector2* param = GetParameterValueChecked(paramIndex); if (param) @@ -1357,7 +1354,7 @@ namespace EMotionFX } - bool AnimGraphInstance::GetVector3ParameterValue(uint32 paramIndex, AZ::Vector3* outValue) + bool AnimGraphInstance::GetVector3ParameterValue(size_t paramIndex, AZ::Vector3* outValue) { MCore::AttributeVector3* param = GetParameterValueChecked(paramIndex); if (param) @@ -1370,7 +1367,7 @@ namespace EMotionFX } - bool AnimGraphInstance::GetVector4ParameterValue(uint32 paramIndex, AZ::Vector4* outValue) + bool AnimGraphInstance::GetVector4ParameterValue(size_t paramIndex, AZ::Vector4* outValue) { MCore::AttributeVector4* param = GetParameterValueChecked(paramIndex); if (param) @@ -1383,7 +1380,7 @@ namespace EMotionFX } - bool AnimGraphInstance::GetRotationParameterValue(uint32 paramIndex, AZ::Quaternion* outRotation) + bool AnimGraphInstance::GetRotationParameterValue(size_t paramIndex, AZ::Quaternion* outRotation) { MCore::AttributeQuaternion* param = GetParameterValueChecked(paramIndex); if (param) @@ -1428,7 +1425,7 @@ namespace EMotionFX return false; } - return GetParameterValueAsFloat(static_cast(index.GetValue()), outValue); + return GetParameterValueAsFloat(index.GetValue(), outValue); } @@ -1440,7 +1437,7 @@ namespace EMotionFX return false; } - return GetParameterValueAsBool(static_cast(index.GetValue()), outValue); + return GetParameterValueAsBool(index.GetValue(), outValue); } @@ -1452,7 +1449,7 @@ namespace EMotionFX return false; } - return GetParameterValueAsInt(static_cast(index.GetValue()), outValue); + return GetParameterValueAsInt(index.GetValue(), outValue); } @@ -1464,7 +1461,7 @@ namespace EMotionFX return false; } - return GetVector2ParameterValue(static_cast(index.GetValue()), outValue); + return GetVector2ParameterValue(index.GetValue(), outValue); } @@ -1476,7 +1473,7 @@ namespace EMotionFX return false; } - return GetVector3ParameterValue(static_cast(index.GetValue()), outValue); + return GetVector3ParameterValue(index.GetValue(), outValue); } @@ -1488,7 +1485,7 @@ namespace EMotionFX return false; } - return GetVector4ParameterValue(static_cast(index.GetValue()), outValue); + return GetVector4ParameterValue(index.GetValue(), outValue); } @@ -1500,7 +1497,7 @@ namespace EMotionFX return false; } - return GetRotationParameterValue(static_cast(index.GetValue()), outRotation); + return GetRotationParameterValue(index.GetValue(), outRotation); } } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphInstance.h b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphInstance.h index 417883d16f..9366fcff86 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphInstance.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphInstance.h @@ -95,28 +95,28 @@ namespace EMotionFX bool GetVector4ParameterValue(const char* paramName, AZ::Vector4* outValue); bool GetRotationParameterValue(const char* paramName, AZ::Quaternion* outRotation); - bool GetParameterValueAsFloat(uint32 paramIndex, float* outValue); - bool GetParameterValueAsBool(uint32 paramIndex, bool* outValue); - bool GetParameterValueAsInt(uint32 paramIndex, int32* outValue); - bool GetVector2ParameterValue(uint32 paramIndex, AZ::Vector2* outValue); - bool GetVector3ParameterValue(uint32 paramIndex, AZ::Vector3* outValue); - bool GetVector4ParameterValue(uint32 paramIndex, AZ::Vector4* outValue); - bool GetRotationParameterValue(uint32 paramIndex, AZ::Quaternion* outRotation); + bool GetParameterValueAsFloat(size_t paramIndex, float* outValue); + bool GetParameterValueAsBool(size_t paramIndex, bool* outValue); + bool GetParameterValueAsInt(size_t paramIndex, int32* outValue); + bool GetVector2ParameterValue(size_t paramIndex, AZ::Vector2* outValue); + bool GetVector3ParameterValue(size_t paramIndex, AZ::Vector3* outValue); + bool GetVector4ParameterValue(size_t paramIndex, AZ::Vector4* outValue); + bool GetRotationParameterValue(size_t paramIndex, AZ::Quaternion* outRotation); void SetMotionSet(MotionSet* motionSet); void CreateParameterValues(); void AddMissingParameterValues(); // add the missing parameters that the anim graph has to this anim graph instance - void ReInitParameterValue(uint32 index); + void ReInitParameterValue(size_t index); void ReInitParameterValues(); - void RemoveParameterValue(uint32 index, bool delFromMem = true); + void RemoveParameterValue(size_t index, bool delFromMem = true); void AddParameterValue(); // add the last anim graph parameter to this instance - void InsertParameterValue(uint32 index); // add the parameter of the animgraph, at a given index - void MoveParameterValue(uint32 oldIndex, uint32 newIndex); // move the parameter from old index to new index + void InsertParameterValue(size_t index); // add the parameter of the animgraph, at a given index + void MoveParameterValue(size_t oldIndex, size_t newIndex); // move the parameter from old index to new index void RemoveAllParameters(bool delFromMem); template - MCORE_INLINE T* GetParameterValueChecked(uint32 index) const + MCORE_INLINE T* GetParameterValueChecked(size_t index) const { MCore::Attribute* baseAttrib = mParamValues[index]; if (baseAttrib->GetType() == T::TYPE_ID) @@ -126,7 +126,7 @@ namespace EMotionFX return nullptr; } - MCORE_INLINE MCore::Attribute* GetParameterValue(uint32 index) const { return mParamValues[index]; } + MCORE_INLINE MCore::Attribute* GetParameterValue(size_t index) const { return mParamValues[index]; } MCore::Attribute* FindParameter(const AZStd::string& name) const; AZ::Outcome FindParameterIndex(const AZStd::string& name) const; @@ -160,7 +160,7 @@ namespace EMotionFX void RemoveAllInternalAttributes(); void ReserveInternalAttributes(size_t totalNumInternalAttributes); void RemoveInternalAttribute(size_t index, bool delFromMem = true); // removes the internal attribute (does not update any indices of other attributes) - uint32 AddInternalAttribute(MCore::Attribute* attribute); // returns the index of the new added attribute + size_t AddInternalAttribute(MCore::Attribute* attribute); // returns the index of the new added attribute AnimGraphObjectData* FindOrCreateUniqueObjectData(const AnimGraphObject* object); AnimGraphNodeData* FindOrCreateUniqueNodeData(const AnimGraphNode* node); @@ -195,7 +195,7 @@ namespace EMotionFX void SetIsOwnedByRuntime(bool isOwnedByRuntime); bool GetIsOwnedByRuntime() const; - ActorInstance* FindActorInstanceFromParentDepth(uint32 parentDepth) const; + ActorInstance* FindActorInstanceFromParentDepth(size_t parentDepth) const; void SetVisualizeScale(float scale); float GetVisualizeScale() const; @@ -237,11 +237,11 @@ namespace EMotionFX void CollectActiveAnimGraphNodes(AZStd::vector* outNodes, const AZ::TypeId& nodeType = AZ::TypeId::CreateNull()); // MCORE_INVALIDINDEX32 means all node types void CollectActiveNetTimeSyncNodes(AZStd::vector* outNodes); - MCORE_INLINE uint32 GetObjectFlags(uint32 objectIndex) const { return mObjectFlags[objectIndex]; } - MCORE_INLINE void SetObjectFlags(uint32 objectIndex, uint32 flags) { mObjectFlags[objectIndex] = flags; } - MCORE_INLINE void EnableObjectFlags(uint32 objectIndex, uint32 flagsToEnable) { mObjectFlags[objectIndex] |= flagsToEnable; } - MCORE_INLINE void DisableObjectFlags(uint32 objectIndex, uint32 flagsToDisable) { mObjectFlags[objectIndex] &= ~flagsToDisable; } - MCORE_INLINE void SetObjectFlags(uint32 objectIndex, uint32 flags, bool enabled) + MCORE_INLINE uint32 GetObjectFlags(size_t objectIndex) const { return mObjectFlags[objectIndex]; } + MCORE_INLINE void SetObjectFlags(size_t objectIndex, uint32 flags) { mObjectFlags[objectIndex] = flags; } + MCORE_INLINE void EnableObjectFlags(size_t objectIndex, uint32 flagsToEnable) { mObjectFlags[objectIndex] |= flagsToEnable; } + MCORE_INLINE void DisableObjectFlags(size_t objectIndex, uint32 flagsToDisable) { mObjectFlags[objectIndex] &= ~flagsToDisable; } + MCORE_INLINE void SetObjectFlags(size_t objectIndex, uint32 flags, bool enabled) { if (enabled) { @@ -252,25 +252,25 @@ namespace EMotionFX mObjectFlags[objectIndex] &= ~flags; } } - MCORE_INLINE bool GetIsObjectFlagEnabled(uint32 objectIndex, uint32 flag) const { return (mObjectFlags[objectIndex] & flag) != 0; } + MCORE_INLINE bool GetIsObjectFlagEnabled(size_t objectIndex, uint32 flag) const { return (mObjectFlags[objectIndex] & flag) != 0; } - MCORE_INLINE bool GetIsOutputReady(uint32 objectIndex) const { return (mObjectFlags[objectIndex] & OBJECTFLAGS_OUTPUT_READY) != 0; } - MCORE_INLINE void SetIsOutputReady(uint32 objectIndex, bool isReady) { SetObjectFlags(objectIndex, OBJECTFLAGS_OUTPUT_READY, isReady); } + MCORE_INLINE bool GetIsOutputReady(size_t objectIndex) const { return (mObjectFlags[objectIndex] & OBJECTFLAGS_OUTPUT_READY) != 0; } + MCORE_INLINE void SetIsOutputReady(size_t objectIndex, bool isReady) { SetObjectFlags(objectIndex, OBJECTFLAGS_OUTPUT_READY, isReady); } - MCORE_INLINE bool GetIsSynced(uint32 objectIndex) const { return (mObjectFlags[objectIndex] & OBJECTFLAGS_SYNCED) != 0; } - MCORE_INLINE void SetIsSynced(uint32 objectIndex, bool isSynced) { SetObjectFlags(objectIndex, OBJECTFLAGS_SYNCED, isSynced); } + MCORE_INLINE bool GetIsSynced(size_t objectIndex) const { return (mObjectFlags[objectIndex] & OBJECTFLAGS_SYNCED) != 0; } + MCORE_INLINE void SetIsSynced(size_t objectIndex, bool isSynced) { SetObjectFlags(objectIndex, OBJECTFLAGS_SYNCED, isSynced); } - MCORE_INLINE bool GetIsResynced(uint32 objectIndex) const { return (mObjectFlags[objectIndex] & OBJECTFLAGS_RESYNC) != 0; } - MCORE_INLINE void SetIsResynced(uint32 objectIndex, bool isResynced) { SetObjectFlags(objectIndex, OBJECTFLAGS_RESYNC, isResynced); } + MCORE_INLINE bool GetIsResynced(size_t objectIndex) const { return (mObjectFlags[objectIndex] & OBJECTFLAGS_RESYNC) != 0; } + MCORE_INLINE void SetIsResynced(size_t objectIndex, bool isResynced) { SetObjectFlags(objectIndex, OBJECTFLAGS_RESYNC, isResynced); } - MCORE_INLINE bool GetIsUpdateReady(uint32 objectIndex) const { return (mObjectFlags[objectIndex] & OBJECTFLAGS_UPDATE_READY) != 0; } - MCORE_INLINE void SetIsUpdateReady(uint32 objectIndex, bool isReady) { SetObjectFlags(objectIndex, OBJECTFLAGS_UPDATE_READY, isReady); } + MCORE_INLINE bool GetIsUpdateReady(size_t objectIndex) const { return (mObjectFlags[objectIndex] & OBJECTFLAGS_UPDATE_READY) != 0; } + MCORE_INLINE void SetIsUpdateReady(size_t objectIndex, bool isReady) { SetObjectFlags(objectIndex, OBJECTFLAGS_UPDATE_READY, isReady); } - MCORE_INLINE bool GetIsTopDownUpdateReady(uint32 objectIndex) const { return (mObjectFlags[objectIndex] & OBJECTFLAGS_TOPDOWNUPDATE_READY) != 0; } - MCORE_INLINE void SetIsTopDownUpdateReady(uint32 objectIndex, bool isReady) { SetObjectFlags(objectIndex, OBJECTFLAGS_TOPDOWNUPDATE_READY, isReady); } + MCORE_INLINE bool GetIsTopDownUpdateReady(size_t objectIndex) const { return (mObjectFlags[objectIndex] & OBJECTFLAGS_TOPDOWNUPDATE_READY) != 0; } + MCORE_INLINE void SetIsTopDownUpdateReady(size_t objectIndex, bool isReady) { SetObjectFlags(objectIndex, OBJECTFLAGS_TOPDOWNUPDATE_READY, isReady); } - MCORE_INLINE bool GetIsPostUpdateReady(uint32 objectIndex) const { return (mObjectFlags[objectIndex] & OBJECTFLAGS_POSTUPDATE_READY) != 0; } - MCORE_INLINE void SetIsPostUpdateReady(uint32 objectIndex, bool isReady) { SetObjectFlags(objectIndex, OBJECTFLAGS_POSTUPDATE_READY, isReady); } + MCORE_INLINE bool GetIsPostUpdateReady(size_t objectIndex) const { return (mObjectFlags[objectIndex] & OBJECTFLAGS_POSTUPDATE_READY) != 0; } + MCORE_INLINE void SetIsPostUpdateReady(size_t objectIndex, bool isReady) { SetObjectFlags(objectIndex, OBJECTFLAGS_POSTUPDATE_READY, isReady); } const InitSettings& GetInitSettings() const; const AnimGraphEventBuffer& GetEventBuffer() const; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphManager.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphManager.cpp index 8e25f6f0a8..fc74d747c6 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphManager.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphManager.cpp @@ -128,8 +128,8 @@ namespace EMotionFX MCore::LockGuardRecursive lock(mAnimGraphLock); // find the index of the anim graph and return false in case the pointer is not valid - const uint32 animGraphIndex = FindAnimGraphIndex(animGraph); - if (animGraphIndex == MCORE_INVALIDINDEX32) + const size_t animGraphIndex = FindAnimGraphIndex(animGraph); + if (animGraphIndex == InvalidIndex) { return false; } @@ -156,8 +156,8 @@ namespace EMotionFX animGraphInstance->RemoveAllObjectData(true); // Remove all links to the anim graph instance that will get removed. - const uint32 numActorInstances = GetActorManager().GetNumActorInstances(); - for (uint32 i = 0; i < numActorInstances; ++i) + const size_t numActorInstances = GetActorManager().GetNumActorInstances(); + for (size_t i = 0; i < numActorInstances; ++i) { ActorInstance* actorInstance = GetActorManager().GetActorInstance(i); if (animGraphInstance == actorInstance->GetAnimGraphInstance()) @@ -182,8 +182,8 @@ namespace EMotionFX MCore::LockGuardRecursive lock(mAnimGraphInstanceLock); // find the index of the anim graph instance and return false in case the pointer is not valid - const uint32 instanceIndex = FindAnimGraphInstanceIndex(animGraphInstance); - if (instanceIndex == MCORE_INVALIDINDEX32) + const size_t instanceIndex = FindAnimGraphInstanceIndex(animGraphInstance); + if (instanceIndex == InvalidIndex) { return false; } @@ -218,33 +218,33 @@ namespace EMotionFX } - uint32 AnimGraphManager::FindAnimGraphIndex(AnimGraph* animGraph) const + size_t AnimGraphManager::FindAnimGraphIndex(AnimGraph* animGraph) const { MCore::LockGuardRecursive lock(mAnimGraphLock); auto iterator = AZStd::find(mAnimGraphs.begin(), mAnimGraphs.end(), animGraph); if (iterator == mAnimGraphs.end()) { - return MCORE_INVALIDINDEX32; + return InvalidIndex; } const size_t index = iterator - mAnimGraphs.begin(); - return static_cast(index); + return index; } - uint32 AnimGraphManager::FindAnimGraphInstanceIndex(AnimGraphInstance* animGraphInstance) const + size_t AnimGraphManager::FindAnimGraphInstanceIndex(AnimGraphInstance* animGraphInstance) const { MCore::LockGuardRecursive lock(mAnimGraphInstanceLock); auto iterator = AZStd::find(mAnimGraphInstances.begin(), mAnimGraphInstances.end(), animGraphInstance); if (iterator == mAnimGraphInstances.end()) { - return MCORE_INVALIDINDEX32; + return InvalidIndex; } const size_t index = iterator - mAnimGraphInstances.begin(); - return static_cast(index); + return index; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphManager.h b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphManager.h index 4973437b8e..55ee6599fd 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphManager.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphManager.h @@ -48,11 +48,11 @@ namespace EMotionFX bool RemoveAnimGraph(AnimGraph* animGraph, bool delFromMemory = true); void RemoveAllAnimGraphs(bool delFromMemory = true); - MCORE_INLINE uint32 GetNumAnimGraphs() const { MCore::LockGuardRecursive lock(mAnimGraphLock); return static_cast(mAnimGraphs.size()); } - MCORE_INLINE AnimGraph* GetAnimGraph(uint32 index) const { MCore::LockGuardRecursive lock(mAnimGraphLock); return mAnimGraphs[index]; } + MCORE_INLINE size_t GetNumAnimGraphs() const { MCore::LockGuardRecursive lock(mAnimGraphLock); return mAnimGraphs.size(); } + MCORE_INLINE AnimGraph* GetAnimGraph(size_t index) const { MCore::LockGuardRecursive lock(mAnimGraphLock); return mAnimGraphs[index]; } AnimGraph* GetFirstAnimGraph() const; - uint32 FindAnimGraphIndex(AnimGraph* animGraph) const; + size_t FindAnimGraphIndex(AnimGraph* animGraph) const; AnimGraph* FindAnimGraphByFileName(const char* filename, bool isTool = true) const; AnimGraph* FindAnimGraphByID(uint32 animGraphID) const; @@ -67,7 +67,7 @@ namespace EMotionFX size_t GetNumAnimGraphInstances() const { MCore::LockGuardRecursive lock(mAnimGraphInstanceLock); return mAnimGraphInstances.size(); } AnimGraphInstance* GetAnimGraphInstance(size_t index) const { MCore::LockGuardRecursive lock(mAnimGraphInstanceLock); return mAnimGraphInstances[index]; } - uint32 FindAnimGraphInstanceIndex(AnimGraphInstance* animGraphInstance) const; + size_t FindAnimGraphInstanceIndex(AnimGraphInstance* animGraphInstance) const; void SetAnimGraphVisualizationEnabled(bool enabled); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphMotionCondition.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphMotionCondition.cpp index 425b48ce2e..9303ea96c5 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphMotionCondition.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphMotionCondition.cpp @@ -156,10 +156,10 @@ namespace EMotionFX case FUNCTION_EVENT: { const EMotionFX::AnimGraphEventBuffer& eventBuffer = animGraphInstance->GetEventBuffer(); - const uint32 numEvents = eventBuffer.GetNumEvents(); + const size_t numEvents = eventBuffer.GetNumEvents(); // Check if the triggered motion event is of the given type and parameter from the motion condition. - for (uint32 i = 0; i < numEvents; ++i) + for (size_t i = 0; i < numEvents; ++i) { const EMotionFX::EventInfo& eventInfo = eventBuffer.GetEvent(i); const EventDataSet& eventDatas = eventInfo.mEvent->GetEventDatas(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNode.cpp index f9896cf677..e73f8cf731 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNode.cpp @@ -50,7 +50,7 @@ namespace EMotionFX AnimGraphNode::AnimGraphNode() : AnimGraphObject(nullptr) , m_id(AnimGraphNodeId::Create()) - , mNodeIndex(MCORE_INVALIDINDEX32) + , mNodeIndex(InvalidIndex) , mDisabled(false) , mParentNode(nullptr) , mCustomData(nullptr) @@ -256,7 +256,7 @@ namespace EMotionFX // remove a given node - void AnimGraphNode::RemoveChildNode(uint32 index, bool delFromMem) + void AnimGraphNode::RemoveChildNode(size_t index, bool delFromMem) { // remove the node from its node group AnimGraphNodeGroup* nodeGroup = mAnimGraph->FindNodeGroupForNode(mChildNodes[index]); @@ -287,7 +287,7 @@ namespace EMotionFX if (iterator != mChildNodes.end()) { - const uint32 index = static_cast(iterator - mChildNodes.begin()); + const size_t index = AZStd::distance(mChildNodes.begin(), iterator); RemoveChildNode(index, delFromMem); } } @@ -384,77 +384,50 @@ namespace EMotionFX // find a child node index by name - uint32 AnimGraphNode::FindChildNodeIndex(const char* name) const + size_t AnimGraphNode::FindChildNodeIndex(const char* name) const { - const size_t numChildNodes = mChildNodes.size(); - for (size_t i = 0; i < numChildNodes; ++i) + const auto foundChildNode = AZStd::find_if(begin(mChildNodes), end(mChildNodes), [name](const AnimGraphNode* childNode) { - // compare the node name with the parameter and return the relative child node index in case they are equal - if (AzFramework::StringFunc::Equal(mChildNodes[i]->GetNameString().c_str(), name, true /* case sensitive */)) - { - return static_cast(i); - } - } - - // failure, return invalid index - return MCORE_INVALIDINDEX32; + return childNode->GetNameString() == name; + }); + return foundChildNode != end(mChildNodes) ? AZStd::distance(begin(mChildNodes), foundChildNode) : InvalidIndex; } // find a child node index - uint32 AnimGraphNode::FindChildNodeIndex(AnimGraphNode* node) const + size_t AnimGraphNode::FindChildNodeIndex(AnimGraphNode* node) const { - const auto iterator = AZStd::find(mChildNodes.begin(), mChildNodes.end(), node); - if (iterator == mChildNodes.end()) - { - return MCORE_INVALIDINDEX32; - } - - const size_t index = iterator - mChildNodes.begin(); - return static_cast(index); + const auto foundChildNode = AZStd::find(mChildNodes.begin(), mChildNodes.end(), node); + return foundChildNode != end(mChildNodes) ? AZStd::distance(begin(mChildNodes), foundChildNode) : InvalidIndex; } AnimGraphNode* AnimGraphNode::FindFirstChildNodeOfType(const AZ::TypeId& nodeType) const { - for (AnimGraphNode* childNode : mChildNodes) + const auto foundChild = AZStd::find_if(begin(mChildNodes), end(mChildNodes), [nodeType](const AnimGraphNode* childNode) { - if (azrtti_typeid(childNode) == nodeType) - { - return childNode; - } - } - - return nullptr; + return azrtti_typeid(childNode) == nodeType; + }); + return foundChild != end(mChildNodes) ? *foundChild : nullptr; } bool AnimGraphNode::HasChildNodeOfType(const AZ::TypeId& nodeType) const { - for (const AnimGraphNode* childNode : mChildNodes) + return AZStd::any_of(begin(mChildNodes), end(mChildNodes), [nodeType](const AnimGraphNode* childNode) { - if (azrtti_typeid(childNode) == nodeType) - { - return true; - } - } - - return false; + return azrtti_typeid(childNode) == nodeType; + }); } // does this node has a specific incoming connection? bool AnimGraphNode::GetHasConnection(AnimGraphNode* sourceNode, uint16 sourcePort, uint16 targetPort) const { - for (const BlendTreeConnection* connection : mConnections) + return AZStd::any_of(begin(mConnections), end(mConnections), [sourceNode, sourcePort, targetPort](const BlendTreeConnection* connection) { - if (connection->GetSourceNode() == sourceNode && connection->GetSourcePort() == sourcePort && connection->GetTargetPort() == targetPort) - { - return true; - } - } - - return false; + return connection->GetSourceNode() == sourceNode && connection->GetSourcePort() == sourcePort && connection->GetTargetPort() == targetPort; + }); } // remove a given connection @@ -537,55 +510,43 @@ namespace EMotionFX // initialize the input ports - void AnimGraphNode::InitInputPorts(uint32 numPorts) + void AnimGraphNode::InitInputPorts(size_t numPorts) { mInputPorts.resize(numPorts); } // initialize the output ports - void AnimGraphNode::InitOutputPorts(uint32 numPorts) + void AnimGraphNode::InitOutputPorts(size_t numPorts) { mOutputPorts.resize(numPorts); } // find a given output port number - uint32 AnimGraphNode::FindOutputPortIndex(const AZStd::string& name) const + size_t AnimGraphNode::FindOutputPortIndex(const AZStd::string& name) const { - const size_t numPorts = mOutputPorts.size(); - for (size_t i = 0; i < numPorts; ++i) + const auto foundPort = AZStd::find_if(begin(mOutputPorts), end(mOutputPorts), [&name](const Port& port) { - // if the port name is equal to the name we are searching for, return the index - if (mOutputPorts[i].GetNameString() == name) - { - return static_cast(i); - } - } - - return MCORE_INVALIDINDEX32; + return port.GetNameString() == name; + }); + return foundPort != end(mOutputPorts) ? AZStd::distance(begin(mOutputPorts), foundPort) : InvalidIndex; } // find a given input port number - uint32 AnimGraphNode::FindInputPortIndex(const AZStd::string& name) const + size_t AnimGraphNode::FindInputPortIndex(const AZStd::string& name) const { - const size_t numPorts = mInputPorts.size(); - for (size_t i = 0; i < numPorts; ++i) + const auto foundPort = AZStd::find_if(begin(mInputPorts), end(mInputPorts), [&name](const Port& port) { - // if the port name is equal to the name we are searching for, return the index - if (mInputPorts[i].GetNameString() == name) - { - return static_cast(i); - } - } - - return MCORE_INVALIDINDEX32; + return port.GetNameString() == name; + }); + return foundPort != end(mInputPorts) ? AZStd::distance(begin(mInputPorts), foundPort) : InvalidIndex; } // add an output port and return its index - uint32 AnimGraphNode::AddOutputPort() + size_t AnimGraphNode::AddOutputPort() { const size_t currentSize = mOutputPorts.size(); mOutputPorts.emplace_back(); @@ -594,7 +555,7 @@ namespace EMotionFX // add an input port, and return its index - uint32 AnimGraphNode::AddInputPort() + size_t AnimGraphNode::AddInputPort() { const size_t currentSize = mInputPorts.size(); mInputPorts.emplace_back(); @@ -603,7 +564,7 @@ namespace EMotionFX // setup a port name - void AnimGraphNode::SetInputPortName(uint32 portIndex, const char* name) + void AnimGraphNode::SetInputPortName(size_t portIndex, const char* name) { MCORE_ASSERT(portIndex < mInputPorts.size()); mInputPorts[portIndex].mNameID = MCore::GetStringIdPool().GenerateIdForString(name); @@ -611,7 +572,7 @@ namespace EMotionFX // setup a port name - void AnimGraphNode::SetOutputPortName(uint32 portIndex, const char* name) + void AnimGraphNode::SetOutputPortName(size_t portIndex, const char* name) { MCORE_ASSERT(portIndex < mOutputPorts.size()); mOutputPorts[portIndex].mNameID = MCore::GetStringIdPool().GenerateIdForString(name); @@ -619,9 +580,9 @@ namespace EMotionFX // get the total number of children - uint32 AnimGraphNode::RecursiveCalcNumNodes() const + size_t AnimGraphNode::RecursiveCalcNumNodes() const { - uint32 result = 0; + size_t result = 0; for (const AnimGraphNode* childNode : mChildNodes) { childNode->RecursiveCountChildNodes(result); @@ -632,7 +593,7 @@ namespace EMotionFX // recursively count the number of nodes down the hierarchy - void AnimGraphNode::RecursiveCountChildNodes(uint32& numNodes) const + void AnimGraphNode::RecursiveCountChildNodes(size_t& numNodes) const { // increase the counter numNodes++; @@ -645,16 +606,16 @@ namespace EMotionFX // recursively calculate the number of node connections - uint32 AnimGraphNode::RecursiveCalcNumNodeConnections() const + size_t AnimGraphNode::RecursiveCalcNumNodeConnections() const { - uint32 result = 0; + size_t result = 0; RecursiveCountNodeConnections(result); return result; } // recursively calculate the number of node connections - void AnimGraphNode::RecursiveCountNodeConnections(uint32& numConnections) const + void AnimGraphNode::RecursiveCountNodeConnections(size_t& numConnections) const { // add the connections to our counter numConnections += GetNumConnections(); @@ -667,11 +628,11 @@ namespace EMotionFX // setup an output port to output a given local pose - void AnimGraphNode::SetupOutputPortAsPose(const char* name, uint32 outputPortNr, uint32 portID) + void AnimGraphNode::SetupOutputPortAsPose(const char* name, size_t outputPortNr, uint32 portID) { // check if we already registered this port ID - const uint32 duplicatePort = FindOutputPortByID(portID); - if (duplicatePort != MCORE_INVALIDINDEX32) + const size_t duplicatePort = FindOutputPortByID(portID); + if (duplicatePort != InvalidIndex) { MCore::LogError("EMotionFX::AnimGraphNode::SetOutputPortAsPose() - There is already a port with the same ID (portID=%d existingPort='%s' newPort='%s' node='%s')", portID, mOutputPorts[duplicatePort].GetName(), name, RTTI_GetTypeName()); } @@ -684,11 +645,11 @@ namespace EMotionFX // setup an output port to output a given motion instance - void AnimGraphNode::SetupOutputPortAsMotionInstance(const char* name, uint32 outputPortNr, uint32 portID) + void AnimGraphNode::SetupOutputPortAsMotionInstance(const char* name, size_t outputPortNr, uint32 portID) { // check if we already registered this port ID - const uint32 duplicatePort = FindOutputPortByID(portID); - if (duplicatePort != MCORE_INVALIDINDEX32) + const size_t duplicatePort = FindOutputPortByID(portID); + if (duplicatePort != InvalidIndex) { MCore::LogError("EMotionFX::AnimGraphNode::SetOutputPortAsMotionInstance() - There is already a port with the same ID (portID=%d existingPort='%s' newPort='%s' node='%s')", portID, mOutputPorts[duplicatePort].GetName(), name, RTTI_GetTypeName()); } @@ -701,11 +662,11 @@ namespace EMotionFX // setup an output port - void AnimGraphNode::SetupOutputPort(const char* name, uint32 outputPortNr, uint32 attributeTypeID, uint32 portID) + void AnimGraphNode::SetupOutputPort(const char* name, size_t outputPortNr, uint32 attributeTypeID, uint32 portID) { // check if we already registered this port ID - const uint32 duplicatePort = FindOutputPortByID(portID); - if (duplicatePort != MCORE_INVALIDINDEX32) + const size_t duplicatePort = FindOutputPortByID(portID); + if (duplicatePort != InvalidIndex) { MCore::LogError("EMotionFX::AnimGraphNode::SetOutputPort() - There is already a port with the same ID (portID=%d existingPort='%s' newPort='%s' name='%s')", portID, mOutputPorts[duplicatePort].GetName(), name, RTTI_GetTypeName()); } @@ -716,26 +677,26 @@ namespace EMotionFX mOutputPorts[outputPortNr].mPortID = portID; } - void AnimGraphNode::SetupInputPortAsVector3(const char* name, uint32 inputPortNr, uint32 portID) + void AnimGraphNode::SetupInputPortAsVector3(const char* name, size_t inputPortNr, uint32 portID) { SetupInputPort(name, inputPortNr, AZStd::vector{MCore::AttributeVector3::TYPE_ID, MCore::AttributeVector2::TYPE_ID, MCore::AttributeVector4::TYPE_ID}, portID); } - void AnimGraphNode::SetupInputPortAsVector2(const char* name, uint32 inputPortNr, uint32 portID) + void AnimGraphNode::SetupInputPortAsVector2(const char* name, size_t inputPortNr, uint32 portID) { SetupInputPort(name, inputPortNr, AZStd::vector{MCore::AttributeVector2::TYPE_ID, MCore::AttributeVector3::TYPE_ID}, portID); } - void AnimGraphNode::SetupInputPortAsVector4(const char* name, uint32 inputPortNr, uint32 portID) + void AnimGraphNode::SetupInputPortAsVector4(const char* name, size_t inputPortNr, uint32 portID) { SetupInputPort(name, inputPortNr, AZStd::vector{MCore::AttributeVector4::TYPE_ID, MCore::AttributeVector3::TYPE_ID}, portID); } - void AnimGraphNode::SetupInputPort(const char* name, uint32 inputPortNr, const AZStd::vector& attributeTypeIDs, uint32 portID) + void AnimGraphNode::SetupInputPort(const char* name, size_t inputPortNr, const AZStd::vector& attributeTypeIDs, uint32 portID) { // Check if we already registered this port ID - const uint32 duplicatePort = FindInputPortByID(portID); - if (duplicatePort != MCORE_INVALIDINDEX32) + const size_t duplicatePort = FindInputPortByID(portID); + if (duplicatePort != InvalidIndex) { MCore::LogError("EMotionFX::AnimGraphNode::SetInputPortAsNumber() - There is already a port with the same ID (portID=%d existingPort='%s' newPort='%s' node='%s')", portID, MCore::GetStringIdPool().GetName(mInputPorts[duplicatePort].mNameID).c_str(), name, RTTI_GetTypeName()); } @@ -747,11 +708,11 @@ namespace EMotionFX } // setup an input port as a number (float/int/bool) - void AnimGraphNode::SetupInputPortAsNumber(const char* name, uint32 inputPortNr, uint32 portID) + void AnimGraphNode::SetupInputPortAsNumber(const char* name, size_t inputPortNr, uint32 portID) { // check if we already registered this port ID - const uint32 duplicatePort = FindInputPortByID(portID); - if (duplicatePort != MCORE_INVALIDINDEX32) + const size_t duplicatePort = FindInputPortByID(portID); + if (duplicatePort != InvalidIndex) { MCore::LogError("EMotionFX::AnimGraphNode::SetInputPortAsNumber() - There is already a port with the same ID (portID=%d existingPort='%s' newPort='%s' node='%s')", portID, mInputPorts[duplicatePort].GetName(), name, RTTI_GetTypeName()); } @@ -764,11 +725,11 @@ namespace EMotionFX mInputPorts[inputPortNr].mPortID = portID; } - void AnimGraphNode::SetupInputPortAsBool(const char* name, uint32 inputPortNr, uint32 portID) + void AnimGraphNode::SetupInputPortAsBool(const char* name, size_t inputPortNr, uint32 portID) { // check if we already registered this port ID - const uint32 duplicatePort = FindInputPortByID(portID); - if (duplicatePort != MCORE_INVALIDINDEX32) + const size_t duplicatePort = FindInputPortByID(portID); + if (duplicatePort != InvalidIndex) { MCore::LogError("EMotionFX::AnimGraphNode::SetInputPortAsBool() - There is already a port with the same ID (portID=%d existingPort='%s' newPort='%s' node='%s')", portID, mInputPorts[duplicatePort].GetName(), name, RTTI_GetTypeName()); } @@ -782,11 +743,11 @@ namespace EMotionFX } // setup a given input port in a generic way - void AnimGraphNode::SetupInputPort(const char* name, uint32 inputPortNr, uint32 attributeTypeID, uint32 portID) + void AnimGraphNode::SetupInputPort(const char* name, size_t inputPortNr, uint32 attributeTypeID, uint32 portID) { // check if we already registered this port ID - const uint32 duplicatePort = FindInputPortByID(portID); - if (duplicatePort != MCORE_INVALIDINDEX32) + const size_t duplicatePort = FindInputPortByID(portID); + if (duplicatePort != InvalidIndex) { MCore::LogError("EMotionFX::AnimGraphNode::SetInputPort() - There is already a port with the same ID (portID=%d existingPort='%s' newPort='%s' node='%s')", portID, mInputPorts[duplicatePort].GetName(), name, RTTI_GetTypeName()); } @@ -834,7 +795,7 @@ namespace EMotionFX } // get the input value for a given port - const MCore::Attribute* AnimGraphNode::GetInputValue(AnimGraphInstance* animGraphInstance, uint32 inputPort) const + const MCore::Attribute* AnimGraphNode::GetInputValue(AnimGraphInstance* animGraphInstance, size_t inputPort) const { MCORE_UNUSED(animGraphInstance); @@ -961,8 +922,8 @@ namespace EMotionFX syncMode, weight, outLeaderFactor, outFollowerFactor, outPlaySpeed); } - void AnimGraphNode::CalcSyncFactors(float leaderPlaySpeed, const AnimGraphSyncTrack* leaderSyncTrack, uint32 leaderSyncTrackIndex, float leaderDuration, - float followerPlaySpeed, const AnimGraphSyncTrack* followerSyncTrack, uint32 followerSyncTrackIndex, float followerDuration, + void AnimGraphNode::CalcSyncFactors(float leaderPlaySpeed, const AnimGraphSyncTrack* leaderSyncTrack, size_t leaderSyncTrackIndex, float leaderDuration, + float followerPlaySpeed, const AnimGraphSyncTrack* followerSyncTrack, size_t followerSyncTrackIndex, float followerDuration, ESyncMode syncMode, float weight, float* outLeaderFactor, float* outFollowerFactor, float* outPlaySpeed) { // exit if we don't want to sync or we have no leader node to sync to @@ -986,7 +947,7 @@ namespace EMotionFX if (leaderSyncTrack && followerSyncTrack && leaderSyncTrack->GetNumEvents() > 0 && followerSyncTrack->GetNumEvents() > 0) { // if the sync indices are invalid, act like no syncing - if (leaderSyncTrackIndex == MCORE_INVALIDINDEX32 || followerSyncTrackIndex == MCORE_INVALIDINDEX32) + if (leaderSyncTrackIndex == InvalidIndex || followerSyncTrackIndex == InvalidIndex) { *outLeaderFactor = 1.0f; *outFollowerFactor = 1.0f; @@ -995,13 +956,13 @@ namespace EMotionFX // get the segment lengths // TODO: handle motion clip start and end - uint32 leaderSyncIndexNext = leaderSyncTrackIndex + 1; + size_t leaderSyncIndexNext = leaderSyncTrackIndex + 1; if (leaderSyncIndexNext >= leaderSyncTrack->GetNumEvents()) { leaderSyncIndexNext = 0; } - uint32 followerSyncIndexNext = followerSyncTrackIndex + 1; + size_t followerSyncIndexNext = followerSyncTrackIndex + 1; if (followerSyncIndexNext >= followerSyncTrack->GetNumEvents()) { followerSyncIndexNext = 0; @@ -1032,8 +993,8 @@ namespace EMotionFX OnChangeMotionSet(animGraphInstance, newMotionSet); // get the number of child nodes, iterate through them and recursively call this function - const uint32 numChildNodes = GetNumChildNodes(); - for (uint32 i = 0; i < numChildNodes; ++i) + const size_t numChildNodes = GetNumChildNodes(); + for (size_t i = 0; i < numChildNodes; ++i) { mChildNodes[i]->RecursiveOnChangeMotionSet(animGraphInstance, newMotionSet); } @@ -1086,7 +1047,7 @@ namespace EMotionFX startEventIndex = 0; } - if (startEventIndex == MCORE_INVALIDINDEX32) + if (startEventIndex == InvalidIndex) { startEventIndex = syncTrackB->GetNumEvents() - 1; } @@ -1118,8 +1079,8 @@ namespace EMotionFX } // update the sync indices - uniqueDataA->SetSyncIndex(static_cast(firstIndexA)); - uniqueDataB->SetSyncIndex(static_cast(secondIndexA)); + uniqueDataA->SetSyncIndex(firstIndexA); + uniqueDataB->SetSyncIndex(secondIndexA); // calculate the segment lengths const float firstSegmentLength = syncTrackA->CalcSegmentLength(firstIndexA, firstIndexB); @@ -1194,7 +1155,7 @@ namespace EMotionFX // check if the given node is the parent or the parent of the parent etc. of the node - bool AnimGraphNode::RecursiveIsParentNode(AnimGraphNode* node) const + bool AnimGraphNode::RecursiveIsParentNode(const AnimGraphNode* node) const { // if we're dealing with a root node we can directly return failure if (!mParentNode) @@ -1217,22 +1178,15 @@ namespace EMotionFX bool AnimGraphNode::RecursiveIsChildNode(AnimGraphNode* node) const { // check if the given node is a child node of the current node - if (FindChildNodeIndex(node) != MCORE_INVALIDINDEX32) + if (FindChildNodeIndex(node) != InvalidIndex) { return true; } - // get the number of child nodes, iterate through them and compare if the node is a child of the child nodes of this node - for (const AnimGraphNode* childNode : mChildNodes) + return AZStd::any_of(begin(mChildNodes), end(mChildNodes), [node](const AnimGraphNode* childNode) { - if (childNode->RecursiveIsChildNode(node)) - { - return true; - } - } - - // failure, the node isn't a child or a child of a child node - return false; + return childNode->RecursiveIsChildNode(node); + }); } @@ -1425,60 +1379,44 @@ namespace EMotionFX // find the input port, based on the port name AnimGraphNode::Port* AnimGraphNode::FindInputPortByName(const AZStd::string& portName) { - for (Port& port : mInputPorts) + const auto foundPort = AZStd::find_if(begin(mInputPorts), end(mInputPorts), [&portName](const Port& port) { - if (port.GetNameString() == portName) - { - return &port; - } - } - return nullptr; + return port.GetNameString() == portName; + }); + return foundPort != end(mInputPorts) ? foundPort : nullptr; } // find the output port, based on the port name AnimGraphNode::Port* AnimGraphNode::FindOutputPortByName(const AZStd::string& portName) { - for (Port& port : mOutputPorts) + const auto foundPort = AZStd::find_if(begin(mOutputPorts), end(mOutputPorts), [&portName](const Port& port) { - if (port.GetNameString() == portName) - { - return &port; - } - } - return nullptr; + return port.GetNameString() == portName; + }); + return foundPort != end(mOutputPorts) ? foundPort : nullptr; } // find the input port index, based on the port id - uint32 AnimGraphNode::FindInputPortByID(uint32 portID) const + size_t AnimGraphNode::FindInputPortByID(uint32 portID) const { - const size_t numPorts = mInputPorts.size(); - for (size_t i = 0; i < numPorts; ++i) + const auto foundPort = AZStd::find_if(begin(mInputPorts), end(mInputPorts), [portID](const Port& port) { - if (mInputPorts[i].mPortID == portID) - { - return static_cast(i); - } - } - - return MCORE_INVALIDINDEX32; + return port.mPortID == portID; + }); + return foundPort != end(mInputPorts) ? AZStd::distance(begin(mInputPorts), foundPort) : InvalidIndex; } // find the output port index, based on the port id - uint32 AnimGraphNode::FindOutputPortByID(uint32 portID) const + size_t AnimGraphNode::FindOutputPortByID(uint32 portID) const { - const size_t numPorts = mOutputPorts.size(); - for (size_t i = 0; i < numPorts; ++i) + const auto foundPort = AZStd::find_if(begin(mOutputPorts), end(mOutputPorts), [portID](const Port& port) { - if (mOutputPorts[i].mPortID == portID) - { - return static_cast(i); - } - } - - return MCORE_INVALIDINDEX32; + return port.mPortID == portID; + }); + return foundPort != end(mOutputPorts) ? AZStd::distance(begin(mOutputPorts), foundPort) : InvalidIndex; } @@ -1521,7 +1459,7 @@ namespace EMotionFX } - void AnimGraphNode::CollectOutgoingConnections(AZStd::vector >& outConnections, const uint32 portIndex) const + void AnimGraphNode::CollectOutgoingConnections(AZStd::vector >& outConnections, const size_t portIndex) const { outConnections.clear(); @@ -1553,8 +1491,8 @@ namespace EMotionFX BlendTreeConnection* AnimGraphNode::FindConnection(uint16 port) const { // get the number of connections and iterate through them - const uint32 numConnections = GetNumConnections(); - for (uint32 i = 0; i < numConnections; ++i) + const size_t numConnections = GetNumConnections(); + for (size_t i = 0; i < numConnections; ++i) { // get the current connection and check if the connection is connected to the given port BlendTreeConnection* connection = GetConnection(i); @@ -1644,7 +1582,7 @@ namespace EMotionFX // iterate over all incoming connections bool syncTrackFound = false; - size_t connectionIndex = MCORE_INVALIDINDEX32; + size_t connectionIndex = InvalidIndex; const size_t numConnections = mConnections.size(); for (size_t i = 0; i < numConnections; ++i) { @@ -1662,7 +1600,7 @@ namespace EMotionFX } } - if (connectionIndex != MCORE_INVALIDINDEX32) + if (connectionIndex != InvalidIndex) { uniqueData->Init(animGraphInstance, mConnections[connectionIndex]->GetSourceNode()); } @@ -1752,7 +1690,7 @@ namespace EMotionFX { // Post process all incoming nodes. bool poseFound = false; - size_t connectionIndex = MCORE_INVALIDINDEX32; + size_t connectionIndex = InvalidIndex; AZ::u16 minTargetPortIndex = MCORE_INVALIDINDEX16; const size_t numConnections = mConnections.size(); for (size_t i = 0; i < numConnections; ++i) @@ -1786,7 +1724,7 @@ namespace EMotionFX RequestRefDatas(animGraphInstance); AnimGraphNodeData* uniqueData = FindOrCreateUniqueNodeData(animGraphInstance); - if (poseFound && connectionIndex != MCORE_INVALIDINDEX32) + if (poseFound && connectionIndex != InvalidIndex) { const BlendTreeConnection* connection = mConnections[connectionIndex]; AnimGraphNode* sourceNode = connection->GetSourceNode(); @@ -1894,8 +1832,8 @@ namespace EMotionFX { AnimGraphRefCountedData* refDataNodeB = nodeB ? nodeB->FindOrCreateUniqueNodeData(animGraphInstance)->GetRefCountedData() : nullptr; - const uint32 numEventsA = refDataNodeA ? refDataNodeA->GetEventBuffer().GetNumEvents() : 0; - const uint32 numEventsB = refDataNodeB ? refDataNodeB->GetEventBuffer().GetNumEvents() : 0; + const size_t numEventsA = refDataNodeA ? refDataNodeA->GetEventBuffer().GetNumEvents() : 0; + const size_t numEventsB = refDataNodeB ? refDataNodeB->GetEventBuffer().GetNumEvents() : 0; // resize to the right number of events already AnimGraphEventBuffer& eventBuffer = refData->GetEventBuffer(); @@ -1905,7 +1843,7 @@ namespace EMotionFX if (refDataNodeA) { const AnimGraphEventBuffer& eventBufferA = refDataNodeA->GetEventBuffer(); - for (uint32 i = 0; i < numEventsA; ++i) + for (size_t i = 0; i < numEventsA; ++i) { eventBuffer.SetEvent(i, eventBufferA.GetEvent(i)); } @@ -1914,7 +1852,7 @@ namespace EMotionFX if (refDataNodeB) { const AnimGraphEventBuffer& eventBufferB = refDataNodeB->GetEventBuffer(); - for (uint32 i = 0; i < numEventsB; ++i) + for (size_t i = 0; i < numEventsB; ++i) { eventBuffer.SetEvent(numEventsA + i, eventBufferB.GetEvent(i)); } @@ -2075,7 +2013,7 @@ namespace EMotionFX { if (mOutputPorts[i].mCompatibleTypes[0] == AttributePose::TYPE_ID) { - MCore::Attribute* attribute = GetOutputAttribute(animGraphInstance, static_cast(i)); + MCore::Attribute* attribute = GetOutputAttribute(animGraphInstance, i); MCORE_ASSERT(attribute->GetType() == AttributePose::TYPE_ID); AttributePose* poseAttribute = static_cast(attribute); @@ -2103,7 +2041,7 @@ namespace EMotionFX { if (mOutputPorts[i].mCompatibleTypes[0] == AttributePose::TYPE_ID) { - MCore::Attribute* attribute = GetOutputAttribute(animGraphInstance, static_cast(i)); + MCore::Attribute* attribute = GetOutputAttribute(animGraphInstance, i); MCORE_ASSERT(attribute->GetType() == AttributePose::TYPE_ID); AnimGraphPose* pose = posePool.RequestPose(actorInstance); @@ -2352,8 +2290,8 @@ namespace EMotionFX // for all output ports for (Port& port : mOutputPorts) { - const uint32 internalAttributeIndex = port.mAttributeIndex; - if (internalAttributeIndex != MCORE_INVALIDINDEX32) + const size_t internalAttributeIndex = port.mAttributeIndex; + if (internalAttributeIndex != InvalidIndex) { const size_t numInstances = mAnimGraph->GetNumAnimGraphInstances(); for (size_t i = 0; i < numInstances; ++i) @@ -2363,18 +2301,18 @@ namespace EMotionFX } mAnimGraph->DecreaseInternalAttributeIndices(internalAttributeIndex); - port.mAttributeIndex = MCORE_INVALIDINDEX32; + port.mAttributeIndex = InvalidIndex; } } } // decrease values higher than a given param value - void AnimGraphNode::DecreaseInternalAttributeIndices(uint32 decreaseEverythingHigherThan) + void AnimGraphNode::DecreaseInternalAttributeIndices(size_t decreaseEverythingHigherThan) { for (Port& port : mOutputPorts) { - if (port.mAttributeIndex > decreaseEverythingHigherThan && port.mAttributeIndex != MCORE_INVALIDINDEX32) + if (port.mAttributeIndex > decreaseEverythingHigherThan && port.mAttributeIndex != InvalidIndex) { port.mAttributeIndex--; } @@ -2498,7 +2436,7 @@ namespace EMotionFX } - void AnimGraphNode::ReserveChildNodes(uint32 numChildNodes) + void AnimGraphNode::ReserveChildNodes(size_t numChildNodes) { mChildNodes.reserve(numChildNodes); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNode.h b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNode.h index 7377f27d7c..89f4db2e5d 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNode.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNode.h @@ -60,7 +60,7 @@ namespace EMotionFX uint32 mCompatibleTypes[4]; // four possible compatible types uint32 mPortID; // the unique port ID (unique inside the node input or output port lists) uint32 mNameID; // the name of the port (using the StringIdPool) - uint32 mAttributeIndex; // the index into the animgraph instance global attributes array + size_t mAttributeIndex; // the index into the animgraph instance global attributes array MCORE_INLINE const char* GetName() const { return MCore::GetStringIdPool().GetName(mNameID).c_str(); } MCORE_INLINE const AZStd::string& GetNameString() const { return MCore::GetStringIdPool().GetName(mNameID); } @@ -97,22 +97,22 @@ namespace EMotionFX bool CheckIfIsCompatibleWith(const Port& otherPort) const { // check the data types - for (uint32 myCompatibleTypeindex = 0; myCompatibleTypeindex < 4; ++myCompatibleTypeindex) + for (uint32 mCompatibleType : mCompatibleTypes) { // If there aren't any more compatibility types and we haven't found a compatible one so far, return false - if (mCompatibleTypes[myCompatibleTypeindex] == 0) + if (mCompatibleType == 0) { return false; } - for (uint32 otherCompatibleTypeIndex = 0; otherCompatibleTypeIndex < 4; ++otherCompatibleTypeIndex) + for (uint32 otherCompatibleTypeIndex : otherPort.mCompatibleTypes) { - if (otherPort.mCompatibleTypes[otherCompatibleTypeIndex] == mCompatibleTypes[myCompatibleTypeindex]) + if (otherCompatibleTypeIndex == mCompatibleType) { return true; } // If there aren't any more compatibility types and we haven't found a compatible one so far, return false - if (otherPort.mCompatibleTypes[otherCompatibleTypeIndex] == 0) + if (otherCompatibleTypeIndex == 0) { break; } @@ -141,7 +141,7 @@ namespace EMotionFX : mConnection(nullptr) , mPortID(MCORE_INVALIDINDEX32) , mNameID(MCORE_INVALIDINDEX32) - , mAttributeIndex(MCORE_INVALIDINDEX32) { ClearCompatibleTypes(); } + , mAttributeIndex(InvalidIndex) { ClearCompatibleTypes(); } virtual ~Port() { } }; @@ -173,7 +173,7 @@ namespace EMotionFX void InitInternalAttributes(AnimGraphInstance* animGraphInstance) override; void RemoveInternalAttributesForAllInstances() override; - void DecreaseInternalAttributeIndices(uint32 decreaseEverythingHigherThan) override; + void DecreaseInternalAttributeIndices(size_t decreaseEverythingHigherThan) override; void OutputAllIncomingNodes(AnimGraphInstance* animGraphInstance); void UpdateAllIncomingNodes(AnimGraphInstance* animGraphInstance, float timePassedInSeconds); @@ -217,8 +217,8 @@ namespace EMotionFX virtual void SetCurrentPlayTime(AnimGraphInstance* animGraphInstance, float timeInSeconds) { FindOrCreateUniqueNodeData(animGraphInstance)->SetCurrentPlayTime(timeInSeconds); } virtual float GetCurrentPlayTime(AnimGraphInstance* animGraphInstance) const { return FindOrCreateUniqueNodeData(animGraphInstance)->GetCurrentPlayTime(); } - MCORE_INLINE uint32 GetSyncIndex(AnimGraphInstance* animGraphInstance) const { return FindOrCreateUniqueNodeData(animGraphInstance)->GetSyncIndex(); } - MCORE_INLINE void SetSyncIndex(AnimGraphInstance* animGraphInstance, uint32 syncIndex) { FindOrCreateUniqueNodeData(animGraphInstance)->SetSyncIndex(syncIndex); } + MCORE_INLINE size_t GetSyncIndex(AnimGraphInstance* animGraphInstance) const { return FindOrCreateUniqueNodeData(animGraphInstance)->GetSyncIndex(); } + MCORE_INLINE void SetSyncIndex(AnimGraphInstance* animGraphInstance, size_t syncIndex) { FindOrCreateUniqueNodeData(animGraphInstance)->SetSyncIndex(syncIndex); } virtual void SetPlaySpeed(AnimGraphInstance* animGraphInstance, float speedFactor) { FindOrCreateUniqueNodeData(animGraphInstance)->SetPlaySpeed(speedFactor); } virtual float GetPlaySpeed(AnimGraphInstance* animGraphInstance) const { return FindOrCreateUniqueNodeData(animGraphInstance)->GetPlaySpeed(); } @@ -235,8 +235,8 @@ namespace EMotionFX void HierarchicalSyncAllInputNodes(AnimGraphInstance* animGraphInstance, AnimGraphNodeData* uniqueDataOfThisNode); static void CalcSyncFactors(AnimGraphInstance* animGraphInstance, const AnimGraphNode* leaderNode, const AnimGraphNode* followerNode, ESyncMode syncMode, float weight, float* outLeaderFactor, float* outFollowerFactor, float* outPlaySpeed); - static void CalcSyncFactors(float leaderPlaySpeed, const AnimGraphSyncTrack* leaderSyncTrack, uint32 leaderSyncTrackIndex, float leaderDuration, - float followerPlaySpeed, const AnimGraphSyncTrack* followerSyncTrack, uint32 followerSyncTrackIndex, float followerDuration, + static void CalcSyncFactors(float leaderPlaySpeed, const AnimGraphSyncTrack* leaderSyncTrack, size_t leaderSyncTrackIndex, float leaderDuration, + float followerPlaySpeed, const AnimGraphSyncTrack* followerSyncTrack, size_t followerSyncTrackIndex, float followerDuration, ESyncMode syncMode, float weight, float* outLeaderFactor, float* outFollowerFactor, float* outPlaySpeed); void RequestPoses(AnimGraphInstance* animGraphInstance); @@ -315,10 +315,10 @@ namespace EMotionFX MCORE_INLINE AnimGraphNodeId GetId() const { return m_id; } void SetId(AnimGraphNodeId id) { m_id = id; } - const MCore::Attribute* GetInputValue(AnimGraphInstance* instance, uint32 inputPort) const; + const MCore::Attribute* GetInputValue(AnimGraphInstance* instance, size_t inputPort) const; - uint32 FindInputPortByID(uint32 portID) const; - uint32 FindOutputPortByID(uint32 portID) const; + size_t FindInputPortByID(uint32 portID) const; + size_t FindOutputPortByID(uint32 portID) const; Port* FindInputPortByName(const AZStd::string& portName); Port* FindOutputPortByName(const AZStd::string& portName); @@ -360,9 +360,9 @@ namespace EMotionFX * node of the outgoing connection. The BlendTreeConnection itself contains the pointer to the source node. The * vector will be cleared upfront. */ - void CollectOutgoingConnections(AZStd::vector>& outConnections, const uint32 portIndex) const; + void CollectOutgoingConnections(AZStd::vector>& outConnections, const size_t portIndex) const; - MCORE_INLINE bool GetInputNumberAsBool(AnimGraphInstance* animGraphInstance, uint32 inputPortNr) const + MCORE_INLINE bool GetInputNumberAsBool(AnimGraphInstance* animGraphInstance, size_t inputPortNr) const { const MCore::Attribute* attribute = GetInputAttribute(animGraphInstance, inputPortNr); if (attribute == nullptr) @@ -383,7 +383,7 @@ namespace EMotionFX return false; } - MCORE_INLINE float GetInputNumberAsFloat(AnimGraphInstance* animGraphInstance, uint32 inputPortNr) const + MCORE_INLINE float GetInputNumberAsFloat(AnimGraphInstance* animGraphInstance, size_t inputPortNr) const { const MCore::Attribute* attribute = GetInputAttribute(animGraphInstance, inputPortNr); if (attribute == nullptr) @@ -404,7 +404,7 @@ namespace EMotionFX return 0.0f; } - MCORE_INLINE int32 GetInputNumberAsInt32(AnimGraphInstance* animGraphInstance, uint32 inputPortNr) const + MCORE_INLINE int32 GetInputNumberAsInt32(AnimGraphInstance* animGraphInstance, size_t inputPortNr) const { const MCore::Attribute* attribute = GetInputAttribute(animGraphInstance, inputPortNr); if (attribute == nullptr) @@ -425,7 +425,7 @@ namespace EMotionFX return 0; } - MCORE_INLINE uint32 GetInputNumberAsUint32(AnimGraphInstance* animGraphInstance, uint32 inputPortNr) const + MCORE_INLINE uint32 GetInputNumberAsUint32(AnimGraphInstance* animGraphInstance, size_t inputPortNr) const { const MCore::Attribute* attribute = GetInputAttribute(animGraphInstance, inputPortNr); if (attribute == nullptr) @@ -446,7 +446,7 @@ namespace EMotionFX return 0; } - MCORE_INLINE AnimGraphNode* GetInputNode(uint32 portNr) + MCORE_INLINE AnimGraphNode* GetInputNode(size_t portNr) { const BlendTreeConnection* con = mInputPorts[portNr].mConnection; if (con == nullptr) @@ -456,7 +456,7 @@ namespace EMotionFX return con->GetSourceNode(); } - MCORE_INLINE MCore::Attribute* GetInputAttribute(AnimGraphInstance* animGraphInstance, uint32 portNr) const + MCORE_INLINE MCore::Attribute* GetInputAttribute(AnimGraphInstance* animGraphInstance, size_t portNr) const { const BlendTreeConnection* con = mInputPorts[portNr].mConnection; if (con == nullptr) @@ -466,7 +466,7 @@ namespace EMotionFX return con->GetSourceNode()->GetOutputValue(animGraphInstance, con->GetSourcePort()); } - MCORE_INLINE MCore::AttributeFloat* GetInputFloat(AnimGraphInstance* animGraphInstance, uint32 portNr) const + MCORE_INLINE MCore::AttributeFloat* GetInputFloat(AnimGraphInstance* animGraphInstance, size_t portNr) const { MCore::Attribute* attrib = GetInputAttribute(animGraphInstance, portNr); if (attrib == nullptr) @@ -477,7 +477,7 @@ namespace EMotionFX return static_cast(attrib); } - MCORE_INLINE MCore::AttributeInt32* GetInputInt32(AnimGraphInstance* animGraphInstance, uint32 portNr) const + MCORE_INLINE MCore::AttributeInt32* GetInputInt32(AnimGraphInstance* animGraphInstance, size_t portNr) const { MCore::Attribute* attrib = GetInputAttribute(animGraphInstance, portNr); if (attrib == nullptr) @@ -488,7 +488,7 @@ namespace EMotionFX return static_cast(attrib); } - MCORE_INLINE MCore::AttributeString* GetInputString(AnimGraphInstance* animGraphInstance, uint32 portNr) const + MCORE_INLINE MCore::AttributeString* GetInputString(AnimGraphInstance* animGraphInstance, size_t portNr) const { MCore::Attribute* attrib = GetInputAttribute(animGraphInstance, portNr); if (attrib == nullptr) @@ -499,7 +499,7 @@ namespace EMotionFX return static_cast(attrib); } - MCORE_INLINE MCore::AttributeBool* GetInputBool(AnimGraphInstance* animGraphInstance, uint32 portNr) const + MCORE_INLINE MCore::AttributeBool* GetInputBool(AnimGraphInstance* animGraphInstance, size_t portNr) const { MCore::Attribute* attrib = GetInputAttribute(animGraphInstance, portNr); if (attrib == nullptr) @@ -510,7 +510,7 @@ namespace EMotionFX return static_cast(attrib); } - MCORE_INLINE bool TryGetInputVector4(AnimGraphInstance* animGraphInstance, uint32 portNr, AZ::Vector4& outResult) const + MCORE_INLINE bool TryGetInputVector4(AnimGraphInstance* animGraphInstance, size_t portNr, AZ::Vector4& outResult) const { MCore::Attribute* attrib = GetInputAttribute(animGraphInstance, portNr); if (attrib == nullptr) @@ -540,7 +540,7 @@ namespace EMotionFX return false; } - MCORE_INLINE bool TryGetInputVector2(AnimGraphInstance* animGraphInstance, uint32 portNr, AZ::Vector2& outResult) const + MCORE_INLINE bool TryGetInputVector2(AnimGraphInstance* animGraphInstance, size_t portNr, AZ::Vector2& outResult) const { MCore::Attribute* attrib = GetInputAttribute(animGraphInstance, portNr); if (attrib == nullptr) @@ -568,7 +568,7 @@ namespace EMotionFX return false; } - MCORE_INLINE bool TryGetInputVector3(AnimGraphInstance* animGraphInstance, uint32 portNr, AZ::Vector3& outResult) const + MCORE_INLINE bool TryGetInputVector3(AnimGraphInstance* animGraphInstance, size_t portNr, AZ::Vector3& outResult) const { MCore::Attribute* attrib = GetInputAttribute(animGraphInstance, portNr); if (attrib == nullptr) @@ -606,7 +606,7 @@ namespace EMotionFX return false; } - MCORE_INLINE MCore::AttributeQuaternion* GetInputQuaternion(AnimGraphInstance* animGraphInstance, uint32 portNr) const + MCORE_INLINE MCore::AttributeQuaternion* GetInputQuaternion(AnimGraphInstance* animGraphInstance, size_t portNr) const { MCore::Attribute* attrib = GetInputAttribute(animGraphInstance, portNr); if (attrib == nullptr) @@ -617,7 +617,7 @@ namespace EMotionFX return static_cast(attrib); } - MCORE_INLINE MCore::AttributeColor* GetInputColor(AnimGraphInstance* animGraphInstance, uint32 portNr) const + MCORE_INLINE MCore::AttributeColor* GetInputColor(AnimGraphInstance* animGraphInstance, size_t portNr) const { MCore::Attribute* attrib = GetInputAttribute(animGraphInstance, portNr); if (attrib == nullptr) @@ -627,7 +627,7 @@ namespace EMotionFX MCORE_ASSERT(attrib->GetType() == MCore::AttributeColor::TYPE_ID); return static_cast(attrib); } - MCORE_INLINE AttributeMotionInstance* GetInputMotionInstance(AnimGraphInstance* animGraphInstance, uint32 portNr) const + MCORE_INLINE AttributeMotionInstance* GetInputMotionInstance(AnimGraphInstance* animGraphInstance, size_t portNr) const { MCore::Attribute* attrib = GetInputAttribute(animGraphInstance, portNr); if (attrib == nullptr) @@ -637,7 +637,7 @@ namespace EMotionFX MCORE_ASSERT(attrib->GetType() == AttributeMotionInstance::TYPE_ID); return static_cast(attrib); } - MCORE_INLINE AttributePose* GetInputPose(AnimGraphInstance* animGraphInstance, uint32 portNr) const + MCORE_INLINE AttributePose* GetInputPose(AnimGraphInstance* animGraphInstance, size_t portNr) const { MCore::Attribute* attrib = GetInputAttribute(animGraphInstance, portNr); if (attrib == nullptr) @@ -648,8 +648,8 @@ namespace EMotionFX return static_cast(attrib); } - MCORE_INLINE MCore::Attribute* GetOutputAttribute(AnimGraphInstance* animGraphInstance, uint32 outputPortIndex) const { return mOutputPorts[outputPortIndex].GetAttribute(animGraphInstance); } - MCORE_INLINE MCore::AttributeFloat* GetOutputNumber(AnimGraphInstance* animGraphInstance, uint32 outputPortIndex) const + MCORE_INLINE MCore::Attribute* GetOutputAttribute(AnimGraphInstance* animGraphInstance, size_t outputPortIndex) const { return mOutputPorts[outputPortIndex].GetAttribute(animGraphInstance); } + MCORE_INLINE MCore::AttributeFloat* GetOutputNumber(AnimGraphInstance* animGraphInstance, size_t outputPortIndex) const { if (mOutputPorts[outputPortIndex].GetAttribute(animGraphInstance) == nullptr) { @@ -658,7 +658,7 @@ namespace EMotionFX MCORE_ASSERT(mOutputPorts[outputPortIndex].mCompatibleTypes[0] == MCore::AttributeFloat::TYPE_ID); return static_cast(mOutputPorts[outputPortIndex].GetAttribute(animGraphInstance)); } - MCORE_INLINE MCore::AttributeFloat* GetOutputFloat(AnimGraphInstance* animGraphInstance, uint32 outputPortIndex) const + MCORE_INLINE MCore::AttributeFloat* GetOutputFloat(AnimGraphInstance* animGraphInstance, size_t outputPortIndex) const { if (mOutputPorts[outputPortIndex].GetAttribute(animGraphInstance) == nullptr) { @@ -667,7 +667,7 @@ namespace EMotionFX MCORE_ASSERT(mOutputPorts[outputPortIndex].mCompatibleTypes[0] == MCore::AttributeFloat::TYPE_ID); return static_cast(mOutputPorts[outputPortIndex].GetAttribute(animGraphInstance)); } - MCORE_INLINE MCore::AttributeInt32* GetOutputInt32(AnimGraphInstance* animGraphInstance, uint32 outputPortIndex) const + MCORE_INLINE MCore::AttributeInt32* GetOutputInt32(AnimGraphInstance* animGraphInstance, size_t outputPortIndex) const { if (mOutputPorts[outputPortIndex].GetAttribute(animGraphInstance) == nullptr) { @@ -676,7 +676,7 @@ namespace EMotionFX MCORE_ASSERT(mOutputPorts[outputPortIndex].mCompatibleTypes[0] == MCore::AttributeInt32::TYPE_ID); return static_cast(mOutputPorts[outputPortIndex].GetAttribute(animGraphInstance)); } - MCORE_INLINE MCore::AttributeString* GetOutputString(AnimGraphInstance* animGraphInstance, uint32 outputPortIndex) const + MCORE_INLINE MCore::AttributeString* GetOutputString(AnimGraphInstance* animGraphInstance, size_t outputPortIndex) const { if (mOutputPorts[outputPortIndex].GetAttribute(animGraphInstance) == nullptr) { @@ -685,7 +685,7 @@ namespace EMotionFX MCORE_ASSERT(mOutputPorts[outputPortIndex].mCompatibleTypes[0] == MCore::AttributeString::TYPE_ID); return static_cast(mOutputPorts[outputPortIndex].GetAttribute(animGraphInstance)); } - MCORE_INLINE MCore::AttributeBool* GetOutputBool(AnimGraphInstance* animGraphInstance, uint32 outputPortIndex) const + MCORE_INLINE MCore::AttributeBool* GetOutputBool(AnimGraphInstance* animGraphInstance, size_t outputPortIndex) const { if (mOutputPorts[outputPortIndex].GetAttribute(animGraphInstance) == nullptr) { @@ -694,7 +694,7 @@ namespace EMotionFX MCORE_ASSERT(mOutputPorts[outputPortIndex].mCompatibleTypes[0] == MCore::AttributeBool::TYPE_ID); return static_cast(mOutputPorts[outputPortIndex].GetAttribute(animGraphInstance)); } - MCORE_INLINE MCore::AttributeVector2* GetOutputVector2(AnimGraphInstance* animGraphInstance, uint32 outputPortIndex) const + MCORE_INLINE MCore::AttributeVector2* GetOutputVector2(AnimGraphInstance* animGraphInstance, size_t outputPortIndex) const { if (mOutputPorts[outputPortIndex].GetAttribute(animGraphInstance) == nullptr) { @@ -703,7 +703,7 @@ namespace EMotionFX MCORE_ASSERT(mOutputPorts[outputPortIndex].mCompatibleTypes[0] == MCore::AttributeVector2::TYPE_ID); return static_cast(mOutputPorts[outputPortIndex].GetAttribute(animGraphInstance)); } - MCORE_INLINE MCore::AttributeVector3* GetOutputVector3(AnimGraphInstance* animGraphInstance, uint32 outputPortIndex) const + MCORE_INLINE MCore::AttributeVector3* GetOutputVector3(AnimGraphInstance* animGraphInstance, size_t outputPortIndex) const { if (mOutputPorts[outputPortIndex].GetAttribute(animGraphInstance) == nullptr) { @@ -712,7 +712,7 @@ namespace EMotionFX MCORE_ASSERT(mOutputPorts[outputPortIndex].mCompatibleTypes[0] == MCore::AttributeVector3::TYPE_ID); return static_cast(mOutputPorts[outputPortIndex].GetAttribute(animGraphInstance)); } - MCORE_INLINE MCore::AttributeVector4* GetOutputVector4(AnimGraphInstance* animGraphInstance, uint32 outputPortIndex) const + MCORE_INLINE MCore::AttributeVector4* GetOutputVector4(AnimGraphInstance* animGraphInstance, size_t outputPortIndex) const { if (mOutputPorts[outputPortIndex].GetAttribute(animGraphInstance) == nullptr) { @@ -721,7 +721,7 @@ namespace EMotionFX MCORE_ASSERT(mOutputPorts[outputPortIndex].mCompatibleTypes[0] == MCore::AttributeVector4::TYPE_ID); return static_cast(mOutputPorts[outputPortIndex].GetAttribute(animGraphInstance)); } - MCORE_INLINE MCore::AttributeQuaternion* GetOutputQuaternion(AnimGraphInstance* animGraphInstance, uint32 outputPortIndex) const + MCORE_INLINE MCore::AttributeQuaternion* GetOutputQuaternion(AnimGraphInstance* animGraphInstance, size_t outputPortIndex) const { if (mOutputPorts[outputPortIndex].GetAttribute(animGraphInstance) == nullptr) { @@ -730,7 +730,7 @@ namespace EMotionFX MCORE_ASSERT(mOutputPorts[outputPortIndex].mCompatibleTypes[0] == MCore::AttributeQuaternion::TYPE_ID); return static_cast(mOutputPorts[outputPortIndex].GetAttribute(animGraphInstance)); } - MCORE_INLINE MCore::AttributeColor* GetOutputColor(AnimGraphInstance* animGraphInstance, uint32 outputPortIndex) const + MCORE_INLINE MCore::AttributeColor* GetOutputColor(AnimGraphInstance* animGraphInstance, size_t outputPortIndex) const { if (mOutputPorts[outputPortIndex].GetAttribute(animGraphInstance) == nullptr) { @@ -739,7 +739,7 @@ namespace EMotionFX MCORE_ASSERT(mOutputPorts[outputPortIndex].mCompatibleTypes[0] == MCore::AttributeColor::TYPE_ID); return static_cast(mOutputPorts[outputPortIndex].GetAttribute(animGraphInstance)); } - MCORE_INLINE AttributePose* GetOutputPose(AnimGraphInstance* animGraphInstance, uint32 outputPortIndex) const + MCORE_INLINE AttributePose* GetOutputPose(AnimGraphInstance* animGraphInstance, size_t outputPortIndex) const { if (mOutputPorts[outputPortIndex].GetAttribute(animGraphInstance) == nullptr) { @@ -748,7 +748,7 @@ namespace EMotionFX MCORE_ASSERT(mOutputPorts[outputPortIndex].mCompatibleTypes[0] == AttributePose::TYPE_ID); return static_cast(mOutputPorts[outputPortIndex].GetAttribute(animGraphInstance)); } - MCORE_INLINE AttributeMotionInstance* GetOutputMotionInstance(AnimGraphInstance* animGraphInstance, uint32 outputPortIndex) const + MCORE_INLINE AttributeMotionInstance* GetOutputMotionInstance(AnimGraphInstance* animGraphInstance, size_t outputPortIndex) const { if (mOutputPorts[outputPortIndex].GetAttribute(animGraphInstance) == nullptr) { @@ -758,18 +758,18 @@ namespace EMotionFX return static_cast(mOutputPorts[outputPortIndex].GetAttribute(animGraphInstance)); } - void SetupInputPortAsNumber(const char* name, uint32 inputPortNr, uint32 portID); - void SetupInputPortAsBool(const char* name, uint32 inputPortNr, uint32 portID); - void SetupInputPort(const char* name, uint32 inputPortNr, uint32 attributeTypeID, uint32 portID); + void SetupInputPortAsNumber(const char* name, size_t inputPortNr, uint32 portID); + void SetupInputPortAsBool(const char* name, size_t inputPortNr, uint32 portID); + void SetupInputPort(const char* name, size_t inputPortNr, uint32 attributeTypeID, uint32 portID); - void SetupInputPortAsVector3(const char* name, uint32 inputPortNr, uint32 portID); - void SetupInputPortAsVector2(const char* name, uint32 inputPortNr, uint32 portID); - void SetupInputPortAsVector4(const char* name, uint32 inputPortNr, uint32 portID); - void SetupInputPort(const char* name, uint32 inputPortNr, const AZStd::vector& attributeTypeIDs, uint32 portID); + void SetupInputPortAsVector3(const char* name, size_t inputPortNr, uint32 portID); + void SetupInputPortAsVector2(const char* name, size_t inputPortNr, uint32 portID); + void SetupInputPortAsVector4(const char* name, size_t inputPortNr, uint32 portID); + void SetupInputPort(const char* name, size_t inputPortNr, const AZStd::vector& attributeTypeIDs, uint32 portID); - void SetupOutputPort(const char* name, uint32 portIndex, uint32 attributeTypeID, uint32 portID); - void SetupOutputPortAsPose(const char* name, uint32 outputPortNr, uint32 portID); - void SetupOutputPortAsMotionInstance(const char* name, uint32 outputPortNr, uint32 portID); + void SetupOutputPort(const char* name, size_t portIndex, uint32 attributeTypeID, uint32 portID); + void SetupOutputPortAsPose(const char* name, size_t outputPortNr, uint32 portID); + void SetupOutputPortAsMotionInstance(const char* name, size_t outputPortNr, uint32 portID); bool GetHasConnection(AnimGraphNode* sourceNode, uint16 sourcePort, uint16 targetPort) const; BlendTreeConnection* FindConnection(const AnimGraphNode* sourceNode, uint16 sourcePort, uint16 targetPort) const; @@ -801,24 +801,24 @@ namespace EMotionFX const AZStd::vector& GetOutputPorts() const { return mOutputPorts; } void SetInputPorts(const AZStd::vector& inputPorts) { mInputPorts = inputPorts; } void SetOutputPorts(const AZStd::vector& outputPorts) { mOutputPorts = outputPorts; } - void InitInputPorts(uint32 numPorts); - void InitOutputPorts(uint32 numPorts); - void SetInputPortName(uint32 portIndex, const char* name); - void SetOutputPortName(uint32 portIndex, const char* name); - uint32 FindOutputPortIndex(const AZStd::string& name) const; - uint32 FindInputPortIndex(const AZStd::string& name) const; - uint32 AddOutputPort(); - uint32 AddInputPort(); + void InitInputPorts(size_t numPorts); + void InitOutputPorts(size_t numPorts); + void SetInputPortName(size_t portIndex, const char* name); + void SetOutputPortName(size_t portIndex, const char* name); + size_t FindOutputPortIndex(const AZStd::string& name) const; + size_t FindInputPortIndex(const AZStd::string& name) const; + size_t AddOutputPort(); + size_t AddInputPort(); virtual bool GetIsStateTransitionNode() const { return false; } - MCORE_INLINE MCore::Attribute* GetOutputValue(AnimGraphInstance* animGraphInstance, uint32 portIndex) const { return animGraphInstance->GetInternalAttribute(mOutputPorts[portIndex].mAttributeIndex); } - MCORE_INLINE Port& GetInputPort(uint32 index) { return mInputPorts[index]; } - MCORE_INLINE Port& GetOutputPort(uint32 index) { return mOutputPorts[index]; } - MCORE_INLINE const Port& GetInputPort(uint32 index) const { return mInputPorts[index]; } - MCORE_INLINE const Port& GetOutputPort(uint32 index) const { return mOutputPorts[index]; } + MCORE_INLINE MCore::Attribute* GetOutputValue(AnimGraphInstance* animGraphInstance, size_t portIndex) const { return animGraphInstance->GetInternalAttribute(mOutputPorts[portIndex].mAttributeIndex); } + MCORE_INLINE Port& GetInputPort(size_t index) { return mInputPorts[index]; } + MCORE_INLINE Port& GetOutputPort(size_t index) { return mOutputPorts[index]; } + MCORE_INLINE const Port& GetInputPort(size_t index) const { return mInputPorts[index]; } + MCORE_INLINE const Port& GetOutputPort(size_t index) const { return mOutputPorts[index]; } void RelinkPortConnections(); - MCORE_INLINE uint32 GetNumConnections() const { return static_cast(mConnections.size()); } - MCORE_INLINE BlendTreeConnection* GetConnection(uint32 index) const { return mConnections[index]; } + MCORE_INLINE size_t GetNumConnections() const { return mConnections.size(); } + MCORE_INLINE BlendTreeConnection* GetConnection(size_t index) const { return mConnections[index]; } const AZStd::vector& GetConnections() const { return mConnections; } AZ_FORCE_INLINE AnimGraphNode* GetParentNode() const { return mParentNode; } @@ -829,7 +829,7 @@ namespace EMotionFX * @param[in] node The parent node we try to search. * @result True in case the given node is the parent or the parent of the parent etc. of the node, false in case the given node wasn't found in any of the parents. */ - virtual bool RecursiveIsParentNode(AnimGraphNode* node) const; + virtual bool RecursiveIsParentNode(const AnimGraphNode* node) const; /** * Check if the given node is a child or a child of a child etc. of the node. @@ -857,14 +857,14 @@ namespace EMotionFX * @param[in] name The name of the node to search. * @return The index of the child node with the given name in case of success, in the other case MCORE_INVALIDINDEX32 will be returned. */ - uint32 FindChildNodeIndex(const char* name) const; + size_t FindChildNodeIndex(const char* name) const; /** * Find child node index. This will only iterate through the child nodes and isn't a recursive process. * @param[in] node A pointer to the node for which we want to find the child node index. * @return The index of the child node in case of success, in the other case MCORE_INVALIDINDEX32 will be returned. */ - uint32 FindChildNodeIndex(AnimGraphNode* node) const; + size_t FindChildNodeIndex(AnimGraphNode* node) const; AnimGraphNode* FindFirstChildNodeOfType(const AZ::TypeId& nodeType) const; @@ -875,22 +875,22 @@ namespace EMotionFX */ bool HasChildNodeOfType(const AZ::TypeId& nodeType) const; - uint32 RecursiveCalcNumNodes() const; - uint32 RecursiveCalcNumNodeConnections() const; + size_t RecursiveCalcNumNodes() const; + size_t RecursiveCalcNumNodeConnections() const; void CopyBaseNodeTo(AnimGraphNode* node) const; - MCORE_INLINE uint32 GetNumChildNodes() const { return static_cast(mChildNodes.size()); } - MCORE_INLINE AnimGraphNode* GetChildNode(uint32 index) const { return mChildNodes[index]; } + MCORE_INLINE size_t GetNumChildNodes() const { return mChildNodes.size(); } + MCORE_INLINE AnimGraphNode* GetChildNode(size_t index) const { return mChildNodes[index]; } const AZStd::vector& GetChildNodes() const { return mChildNodes; } void SetNodeInfo(const AZStd::string& info); const AZStd::string& GetNodeInfo() const; void AddChildNode(AnimGraphNode* node); - void ReserveChildNodes(uint32 numChildNodes); + void ReserveChildNodes(size_t numChildNodes); - void RemoveChildNode(uint32 index, bool delFromMem = true); + void RemoveChildNode(size_t index, bool delFromMem = true); void RemoveChildNodeByPointer(AnimGraphNode* node, bool delFromMem = true); void RemoveAllChildNodes(bool delFromMem = true); bool CheckIfHasChildOfType(const AZ::TypeId& nodeType) const; // non-recursive @@ -924,8 +924,8 @@ namespace EMotionFX bool GetCanVisualize(AnimGraphInstance* animGraphInstance) const; - MCORE_INLINE uint32 GetNodeIndex() const { return mNodeIndex; } - MCORE_INLINE void SetNodeIndex(uint32 index) { mNodeIndex = index; } + MCORE_INLINE size_t GetNodeIndex() const { return mNodeIndex; } + MCORE_INLINE void SetNodeIndex(size_t index) { mNodeIndex = index; } void ResetPoseRefCount(AnimGraphInstance* animGraphInstance); MCORE_INLINE void IncreasePoseRefCount(AnimGraphInstance* animGraphInstance) { FindOrCreateUniqueNodeData(animGraphInstance)->IncreasePoseRefCount(); } @@ -944,7 +944,7 @@ namespace EMotionFX static void Reflect(AZ::ReflectContext* context); protected: - uint32 mNodeIndex; + size_t mNodeIndex; AZ::u64 m_id; AZStd::vector mConnections; AZStd::vector mInputPorts; @@ -967,7 +967,7 @@ namespace EMotionFX virtual void PostUpdate(AnimGraphInstance* animGraphInstance, float timePassedInSeconds); void Update(AnimGraphInstance* animGraphInstance, float timePassedInSeconds) override; - void RecursiveCountChildNodes(uint32& numNodes) const; - void RecursiveCountNodeConnections(uint32& numConnections) const; + void RecursiveCountChildNodes(size_t& numNodes) const; + void RecursiveCountNodeConnections(size_t& numConnections) const; }; } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNodeData.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNodeData.cpp index f8f2b0a98c..a787dd25a2 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNodeData.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNodeData.cpp @@ -26,7 +26,7 @@ namespace EMotionFX , mPreSyncTime(0.0f) , mGlobalWeight(1.0f) , mLocalWeight(1.0f) - , mSyncIndex(MCORE_INVALIDINDEX32) + , mSyncIndex(InvalidIndex) , mPoseRefCount(0) , mRefDataRefCount(0) , mInheritFlags(0) @@ -55,7 +55,7 @@ namespace EMotionFX mLocalWeight = 1.0f; mInheritFlags = 0; m_isMirrorMotion = false; - mSyncIndex = MCORE_INVALIDINDEX32; + mSyncIndex = InvalidIndex; mSyncTrack = nullptr; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNodeData.h b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNodeData.h index a3bfc34606..68d49ca511 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNodeData.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNodeData.h @@ -54,8 +54,8 @@ namespace EMotionFX MCORE_INLINE AnimGraphNode* GetNode() const { return reinterpret_cast(mObject); } MCORE_INLINE void SetNode(AnimGraphNode* node) { mObject = reinterpret_cast(node); } - MCORE_INLINE void SetSyncIndex(uint32 syncIndex) { mSyncIndex = syncIndex; } - MCORE_INLINE uint32 GetSyncIndex() const { return mSyncIndex; } + MCORE_INLINE void SetSyncIndex(size_t syncIndex) { mSyncIndex = syncIndex; } + MCORE_INLINE size_t GetSyncIndex() const { return mSyncIndex; } MCORE_INLINE void SetCurrentPlayTime(float absoluteTime) { mCurrentTime = absoluteTime; } MCORE_INLINE float GetCurrentPlayTime() const { return mCurrentTime; } @@ -108,7 +108,7 @@ namespace EMotionFX float mPreSyncTime; float mGlobalWeight; float mLocalWeight; - uint32 mSyncIndex; /**< The last used sync track index. */ + size_t mSyncIndex; /**< The last used sync track index. */ uint8 mPoseRefCount; uint8 mRefDataRefCount; uint8 mInheritFlags; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNodeGroup.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNodeGroup.cpp index 3d93476c6a..a14401d3c8 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNodeGroup.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNodeGroup.cpp @@ -30,7 +30,7 @@ namespace EMotionFX } - AnimGraphNodeGroup::AnimGraphNodeGroup(const char* groupName, uint32 numNodes) + AnimGraphNodeGroup::AnimGraphNodeGroup(const char* groupName, size_t numNodes) { SetName(groupName); SetNumNodes(numNodes); @@ -100,28 +100,28 @@ namespace EMotionFX // set the number of nodes - void AnimGraphNodeGroup::SetNumNodes(uint32 numNodes) + void AnimGraphNodeGroup::SetNumNodes(size_t numNodes) { mNodeIds.resize(numNodes); } // get the number of nodes - uint32 AnimGraphNodeGroup::GetNumNodes() const + size_t AnimGraphNodeGroup::GetNumNodes() const { - return static_cast(mNodeIds.size()); + return mNodeIds.size(); } // set a given node to a given node number - void AnimGraphNodeGroup::SetNode(uint32 index, AnimGraphNodeId nodeId) + void AnimGraphNodeGroup::SetNode(size_t index, AnimGraphNodeId nodeId) { mNodeIds[index] = nodeId; } // get the node number of a given index - AnimGraphNodeId AnimGraphNodeGroup::GetNode(uint32 index) const + AnimGraphNodeId AnimGraphNodeGroup::GetNode(size_t index) const { return mNodeIds[index]; } @@ -147,7 +147,7 @@ namespace EMotionFX // remove a given array element from the list of nodes - void AnimGraphNodeGroup::RemoveNodeByGroupIndex(uint32 index) + void AnimGraphNodeGroup::RemoveNodeByGroupIndex(size_t index) { mNodeIds.erase(mNodeIds.begin() + index); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNodeGroup.h b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNodeGroup.h index a3aa0ec9a6..611cfd6824 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNodeGroup.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNodeGroup.h @@ -41,7 +41,7 @@ namespace EMotionFX * @param numNodes The number of nodes to create inside the group. This will have all uninitialized values for the node ids in the group, so be sure that you * set them all to some valid node index using the AnimGraphNodeGroup::SetNode(...) method. This constructor automatically calls the SetNumNodes(...) method. */ - AnimGraphNodeGroup(const char* groupName, uint32 numNodes); + AnimGraphNodeGroup(const char* groupName, size_t numNodes); /** * The destructor. @@ -96,13 +96,13 @@ namespace EMotionFX * This will resize the array of node ids. Don't forget to initialize the node values after increasing the number of nodes. * @param numNodes The number of nodes that are inside this group. */ - void SetNumNodes(uint32 numNodes); + void SetNumNodes(size_t numNodes); /** * Get the number of nodes that remain inside this group. * @result The number of nodes inside this group. */ - uint32 GetNumNodes() const; + size_t GetNumNodes() const; /** * Set the value of a given node. @@ -110,14 +110,14 @@ namespace EMotionFX * @param nodeID The value for the given node. This is the node id where this group will belong to. * To get access to the actual node object use AnimGraph::RecursiveFindNodeByID( nodeID ). */ - void SetNode(uint32 index, AnimGraphNodeId nodeId); + void SetNode(size_t index, AnimGraphNodeId nodeId); /** * Get the node id for a given node inside the group. * @param index The node number inside this group, which must be in range of [0..GetNumNodes()-1]. * @result The node id, which points inside the Actor object. Use AnimGraph::RecursiveFindNodeByID( nodeID ) to get access to the node information. */ - AnimGraphNodeId GetNode(uint32 index) const; + AnimGraphNodeId GetNode(size_t index) const; /** * Check if the node with the given id is inside the node group. @@ -149,7 +149,7 @@ namespace EMotionFX * @param index The node index in the group. So for example an index value of 5 will remove the sixth node from the group. * The index value must be in range of [0..GetNumNodes() - 1]. */ - void RemoveNodeByGroupIndex(uint32 index); + void RemoveNodeByGroupIndex(size_t index); /** * Clear the node group. This removes all nodes. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphObject.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphObject.cpp index c687dcadb1..7b4afbd38a 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphObject.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphObject.cpp @@ -89,7 +89,7 @@ namespace EMotionFX // save and return number of bytes written, when outputBuffer is nullptr only return num bytes it would write - uint32 AnimGraphObject::SaveUniqueData(AnimGraphInstance* animGraphInstance, uint8* outputBuffer) const + size_t AnimGraphObject::SaveUniqueData(AnimGraphInstance* animGraphInstance, uint8* outputBuffer) const { AnimGraphObjectData* data = animGraphInstance->FindOrCreateUniqueObjectData(this); if (data) @@ -103,7 +103,7 @@ namespace EMotionFX // load and return number of bytes read, when dataBuffer is nullptr, 0 should be returned - uint32 AnimGraphObject::LoadUniqueData(AnimGraphInstance* animGraphInstance, const uint8* dataBuffer) + size_t AnimGraphObject::LoadUniqueData(AnimGraphInstance* animGraphInstance, const uint8* dataBuffer) { AnimGraphObjectData* data = animGraphInstance->FindOrCreateUniqueObjectData(this); if (data) @@ -220,7 +220,7 @@ namespace EMotionFX // decrease internal attribute indices for index values higher than the specified parameter - void AnimGraphObject::DecreaseInternalAttributeIndices(uint32 decreaseEverythingHigherThan) + void AnimGraphObject::DecreaseInternalAttributeIndices(size_t decreaseEverythingHigherThan) { MCORE_UNUSED(decreaseEverythingHigherThan); // currently no implementation for the base object type, but this will come later diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphObject.h b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphObject.h index 2f01b572e3..32905d66a7 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphObject.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphObject.h @@ -134,7 +134,7 @@ namespace EMotionFX void InitInternalAttributesForAllInstances(); // does the init for all anim graph instances in the parent animgraph virtual void InitInternalAttributes(AnimGraphInstance* animGraphInstance); virtual void RemoveInternalAttributesForAllInstances(); - virtual void DecreaseInternalAttributeIndices(uint32 decreaseEverythingHigherThan); + virtual void DecreaseInternalAttributeIndices(size_t decreaseEverythingHigherThan); virtual void Update(AnimGraphInstance* animGraphInstance, float timePassedInSeconds); @@ -144,14 +144,14 @@ namespace EMotionFX virtual void RecursiveOnChangeMotionSet(AnimGraphInstance* animGraphInstance, MotionSet* newMotionSet) { MCORE_UNUSED(animGraphInstance); MCORE_UNUSED(newMotionSet); } virtual void OnActorMotionExtractionNodeChanged() {} - MCORE_INLINE uint32 GetObjectIndex() const { return mObjectIndex; } - MCORE_INLINE void SetObjectIndex(size_t index) { mObjectIndex = static_cast(index); } + MCORE_INLINE size_t GetObjectIndex() const { return mObjectIndex; } + MCORE_INLINE void SetObjectIndex(size_t index) { mObjectIndex = index; } MCORE_INLINE AnimGraph* GetAnimGraph() const { return mAnimGraph; } MCORE_INLINE void SetAnimGraph(AnimGraph* animGraph) { mAnimGraph = animGraph; } - uint32 SaveUniqueData(AnimGraphInstance* animGraphInstance, uint8* outputBuffer) const; // save and return number of bytes written, when outputBuffer is nullptr only return num bytes it would write - uint32 LoadUniqueData(AnimGraphInstance* animGraphInstance, const uint8* dataBuffer); // load and return number of bytes read, when dataBuffer is nullptr, 0 should be returned + size_t SaveUniqueData(AnimGraphInstance* animGraphInstance, uint8* outputBuffer) const; // save and return number of bytes written, when outputBuffer is nullptr only return num bytes it would write + size_t LoadUniqueData(AnimGraphInstance* animGraphInstance, const uint8* dataBuffer); // load and return number of bytes read, when dataBuffer is nullptr, 0 should be returned virtual void RecursiveCollectObjects(AZStd::vector& outObjects) const; @@ -167,7 +167,7 @@ namespace EMotionFX protected: AnimGraph* mAnimGraph; - uint32 mObjectIndex; + size_t mObjectIndex; }; } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphPose.h b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphPose.h index 122749e714..a2b21aec6a 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphPose.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphPose.h @@ -39,7 +39,7 @@ namespace EMotionFX void LinkToActorInstance(const ActorInstance* actorInstance); void InitFromBindPose(const ActorInstance* actorInstance); - MCORE_INLINE uint32 GetNumNodes() const { return mPose.GetNumTransforms(); } + MCORE_INLINE size_t GetNumNodes() const { return mPose.GetNumTransforms(); } MCORE_INLINE const Pose& GetPose() const { return mPose; } MCORE_INLINE Pose& GetPose() { return mPose; } MCORE_INLINE void SetPose(const Pose& pose) { mPose = pose; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphPosePool.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphPosePool.cpp index 5f139d9c49..3314ff0a17 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphPosePool.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphPosePool.cpp @@ -27,10 +27,9 @@ namespace EMotionFX AnimGraphPosePool::~AnimGraphPosePool() { // delete all poses - const uint32 numPoses = mPoses.size(); - for (uint32 i = 0; i < numPoses; ++i) + for (AnimGraphPose* mPose : mPoses) { - delete mPoses[i]; + delete mPose; } mPoses.clear(); @@ -40,17 +39,16 @@ namespace EMotionFX // resize the number of poses in the pool - void AnimGraphPosePool::Resize(uint32 numPoses) + void AnimGraphPosePool::Resize(size_t numPoses) { - const uint32 numOldPoses = mPoses.size(); + const size_t numOldPoses = mPoses.size(); // if we will remove poses - int32 difference = numPoses - numOldPoses; - if (difference < 0) + if (numPoses < numOldPoses) { // remove the last poses - difference = abs(difference); - for (int32 i = 0; i < difference; ++i) + const size_t numToRemove = numOldPoses - numPoses; + for (size_t i = 0; i < numToRemove; ++i) { AnimGraphPose* pose = mPoses.back(); MCORE_ASSERT(AZStd::find(begin(mFreePoses), end(mFreePoses), pose) == end(mFreePoses)); // make sure the pose is not already in use @@ -60,7 +58,8 @@ namespace EMotionFX } else // we want to add new poses { - for (int32 i = 0; i < difference; ++i) + const size_t numToAdd = numPoses - numOldPoses; + for (size_t i = 0; i < numToAdd; ++i) { AnimGraphPose* newPose = new AnimGraphPose(); mPoses.emplace_back(newPose); @@ -74,12 +73,12 @@ namespace EMotionFX AnimGraphPose* AnimGraphPosePool::RequestPose(const ActorInstance* actorInstance) { // if we have no free poses left, allocate a new one - if (mFreePoses.size() == 0) + if (mFreePoses.empty()) { AnimGraphPose* newPose = new AnimGraphPose(); newPose->LinkToActorInstance(actorInstance); mPoses.emplace_back(newPose); - mMaxUsed = MCore::Max(mMaxUsed, GetNumUsedPoses()); + mMaxUsed = AZStd::max(mMaxUsed, GetNumUsedPoses()); newPose->SetIsInUse(true); return newPose; } @@ -89,7 +88,7 @@ namespace EMotionFX //if (pose->GetActorInstance() != actorInstance) pose->LinkToActorInstance(actorInstance); mFreePoses.pop_back(); // remove it from the list of free poses - mMaxUsed = MCore::Max(mMaxUsed, GetNumUsedPoses()); + mMaxUsed = AZStd::max(mMaxUsed, GetNumUsedPoses()); pose->SetIsInUse(true); return pose; } @@ -107,10 +106,8 @@ namespace EMotionFX // free all poses void AnimGraphPosePool::FreeAllPoses() { - const uint32 numPoses = mPoses.size(); - for (uint32 i = 0; i < numPoses; ++i) + for (AnimGraphPose* curPose : mPoses) { - AnimGraphPose* curPose = mPoses[i]; if (curPose->GetIsInUse()) { FreePose(curPose); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphPosePool.h b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphPosePool.h index 8f7a38be97..8148d88926 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphPosePool.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphPosePool.h @@ -34,7 +34,7 @@ namespace EMotionFX AnimGraphPosePool(); ~AnimGraphPosePool(); - void Resize(uint32 numPoses); + void Resize(size_t numPoses); AnimGraphPose* RequestPose(const ActorInstance* actorInstance); void FreePose(AnimGraphPose* pose); @@ -43,13 +43,13 @@ namespace EMotionFX MCORE_INLINE size_t GetNumFreePoses() const { return mFreePoses.size(); } MCORE_INLINE size_t GetNumPoses() const { return mPoses.size(); } - MCORE_INLINE size_t GetNumUsedPoses() const { return (mPoses.size() - mFreePoses.size()); } - MCORE_INLINE uint32 GetNumMaxUsedPoses() const { return mMaxUsed; } + MCORE_INLINE size_t GetNumUsedPoses() const { return mPoses.size() - mFreePoses.size(); } + MCORE_INLINE size_t GetNumMaxUsedPoses() const { return mMaxUsed; } MCORE_INLINE void ResetMaxUsedPoses() { mMaxUsed = 0; } private: AZStd::vector mPoses; AZStd::vector mFreePoses; - uint32 mMaxUsed; + size_t mMaxUsed; }; } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphRefCountedDataPool.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphRefCountedDataPool.cpp index 289a9c4982..f4e7402fdf 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphRefCountedDataPool.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphRefCountedDataPool.cpp @@ -28,10 +28,9 @@ namespace EMotionFX AnimGraphRefCountedDataPool::~AnimGraphRefCountedDataPool() { // delete all items - const uint32 numItems = mItems.size(); - for (uint32 i = 0; i < numItems; ++i) + for (AnimGraphRefCountedData*& mItem : mItems) { - delete mItems[i]; + delete mItem; } mItems.clear(); @@ -41,17 +40,16 @@ namespace EMotionFX // resize the number of items in the pool - void AnimGraphRefCountedDataPool::Resize(uint32 numItems) + void AnimGraphRefCountedDataPool::Resize(size_t numItems) { - const uint32 numOldItems = mItems.size(); + const size_t numOldItems = mItems.size(); // if we will remove Items - int32 difference = numItems - numOldItems; - if (difference < 0) + if (numItems < numOldItems) { // remove the last Items - difference = abs(difference); - for (int32 i = 0; i < difference; ++i) + const size_t numToRemove = numOldItems - numItems; + for (size_t i = 0; i < numToRemove; ++i) { AnimGraphRefCountedData* item = mItems.back(); MCORE_ASSERT(AZStd::find(begin(mFreeItems), end(mFreeItems), item) != end(mFreeItems)); // make sure the Item is not already in use @@ -61,7 +59,8 @@ namespace EMotionFX } else // we want to add new Items { - for (int32 i = 0; i < difference; ++i) + const size_t numToAdd = numItems - numOldItems; + for (size_t i = 0; i < numToAdd; ++i) { AnimGraphRefCountedData* newItem = new AnimGraphRefCountedData(); mItems.emplace_back(newItem); @@ -75,18 +74,18 @@ namespace EMotionFX AnimGraphRefCountedData* AnimGraphRefCountedDataPool::RequestNew() { // if we have no free items left, allocate a new one - if (mFreeItems.size() == 0) + if (mFreeItems.empty()) { AnimGraphRefCountedData* newItem = new AnimGraphRefCountedData(); mItems.emplace_back(newItem); - mMaxUsed = MCore::Max(mMaxUsed, GetNumUsedItems()); + mMaxUsed = AZStd::max(mMaxUsed, GetNumUsedItems()); return newItem; } // request the last free item AnimGraphRefCountedData* item = mFreeItems[mFreeItems.size() - 1]; mFreeItems.pop_back(); // remove it from the list of free Items - mMaxUsed = MCore::Max(mMaxUsed, GetNumUsedItems()); + mMaxUsed = AZStd::max(mMaxUsed, GetNumUsedItems()); return item; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphRefCountedDataPool.h b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphRefCountedDataPool.h index 33590766ff..d05ea5b5a1 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphRefCountedDataPool.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphRefCountedDataPool.h @@ -29,20 +29,20 @@ namespace EMotionFX AnimGraphRefCountedDataPool(); ~AnimGraphRefCountedDataPool(); - void Resize(uint32 numItems); + void Resize(size_t numItems); AnimGraphRefCountedData* RequestNew(); void Free(AnimGraphRefCountedData* item); MCORE_INLINE size_t GetNumFreeItems() const { return mFreeItems.size(); } MCORE_INLINE size_t GetNumItems() const { return mItems.size(); } - MCORE_INLINE size_t GetNumUsedItems() const { return (mItems.size() - mFreeItems.size()); } - MCORE_INLINE uint32 GetNumMaxUsedItems() const { return mMaxUsed; } + MCORE_INLINE size_t GetNumUsedItems() const { return mItems.size() - mFreeItems.size(); } + MCORE_INLINE size_t GetNumMaxUsedItems() const { return mMaxUsed; } MCORE_INLINE void ResetMaxUsedItems() { mMaxUsed = 0; } private: AZStd::vector mItems; AZStd::vector mFreeItems; - uint32 mMaxUsed; + size_t mMaxUsed; }; } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphReferenceNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphReferenceNode.cpp index e6f6bb0985..a1f9af2935 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphReferenceNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphReferenceNode.cpp @@ -56,7 +56,7 @@ namespace EMotionFX // to the non-existing old anim graph, while the new one is about to be loaded asynchronously. // In case the asset already got destroyed (AnimGraphAssetHandler::DestroyAsset()), it removed all anim graph instances already. - if (GetAnimGraphManager().FindAnimGraphInstanceIndex(m_referencedAnimGraphInstance) != InvalidIndex32) + if (GetAnimGraphManager().FindAnimGraphInstanceIndex(m_referencedAnimGraphInstance) != InvalidIndex) { m_referencedAnimGraphInstance->Destroy(); } @@ -375,8 +375,8 @@ namespace EMotionFX // Release any left over ref data for the referenced anim graph instance. const uint32 threadIndex = referencedAnimGraphInstance->GetActorInstance()->GetThreadIndex(); AnimGraphRefCountedDataPool& refDataPool = GetEMotionFX().GetThreadData(threadIndex)->GetRefCountedDataPool(); - const uint32 numReferencedNodes = referencedAnimGraph->GetNumNodes(); - for (uint32 i = 0; i < numReferencedNodes; ++i) + const size_t numReferencedNodes = referencedAnimGraph->GetNumNodes(); + for (size_t i = 0; i < numReferencedNodes; ++i) { const AnimGraphNode* node = referencedAnimGraph->GetNode(i); AnimGraphNodeData* nodeData = static_cast(referencedAnimGraphInstance->GetUniqueObjectData(node->GetObjectIndex())); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphSnapshot.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphSnapshot.cpp index 110a35781e..089f5a7df8 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphSnapshot.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphSnapshot.cpp @@ -41,7 +41,7 @@ namespace EMotionFX const size_t numValueParameters = instance.GetAnimGraph()->GetNumValueParameters(); for (size_t i = 0; i < numValueParameters; ++i) { - m_parameters.emplace_back(instance.GetParameterValue(static_cast(i))->Clone()); + m_parameters.emplace_back(instance.GetParameterValue(i)->Clone()); } } @@ -62,7 +62,7 @@ namespace EMotionFX return m_parameters; } - void AnimGraphSnapshot::SetActiveNodes(const AZStd::vector& activeNodes) + void AnimGraphSnapshot::SetActiveNodes(const NodeIndexContainer& activeNodes) { if (m_activeStateNodes != activeNodes) { @@ -71,7 +71,7 @@ namespace EMotionFX } } - const AZStd::vector& AnimGraphSnapshot::GetActiveNodes() const + const NodeIndexContainer& AnimGraphSnapshot::GetActiveNodes() const { return m_activeStateNodes; } @@ -94,7 +94,7 @@ namespace EMotionFX for (size_t i = 0; i < numParams; ++i) { - m_parameters[i]->InitFrom(instance.GetParameterValue(static_cast(i))); + m_parameters[i]->InitFrom(instance.GetParameterValue(i)); } } @@ -111,7 +111,7 @@ namespace EMotionFX AnimGraphNode* currentState = stateMachine->GetCurrentState(&instance); AZ_Assert(currentState, "There should always be a valid current state."); - m_activeStateNodes.emplace_back(currentState->GetNodeIndex()); + m_activeStateNodes.emplace_back(aznumeric_caster(currentState->GetNodeIndex())); } } @@ -123,9 +123,9 @@ namespace EMotionFX for (const AnimGraphNode* animGraphNode : tempGraphNodes) { - const AZ::u32 nodeIndex = animGraphNode->GetNodeIndex(); + const size_t nodeIndex = animGraphNode->GetNodeIndex(); float normalizedPlaytime = animGraphNode->GetCurrentPlayTime(&instance) / animGraphNode->GetDuration(&instance); - m_motionNodePlaytimes.emplace_back(nodeIndex, normalizedPlaytime); + m_motionNodePlaytimes.emplace_back(aznumeric_caster(nodeIndex), normalizedPlaytime); } } @@ -135,14 +135,14 @@ namespace EMotionFX for (size_t i = 0; i < numParams; ++i) { - MCore::Attribute* attribute = instance.GetParameterValue(static_cast(i)); + MCore::Attribute* attribute = instance.GetParameterValue(i); attribute->InitFrom(m_parameters[i]); } } void AnimGraphSnapshot::RestoreActiveNodes(AnimGraphInstance& instance) { - for (const AZ::u32 nodeIndex : m_activeStateNodes) + for (const size_t nodeIndex : m_activeStateNodes) { AnimGraphNode* node = instance.GetAnimGraph()->GetNode(nodeIndex); AnimGraphNode* parent = node->GetParentNode(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphStateMachine.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphStateMachine.cpp index a191ae9e13..3ad6ae8b8b 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphStateMachine.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphStateMachine.cpp @@ -36,7 +36,7 @@ namespace EMotionFX AnimGraphStateMachine::AnimGraphStateMachine() : AnimGraphNode() , mEntryState(nullptr) - , mEntryStateNodeNr(MCORE_INVALIDINDEX32) + , mEntryStateNodeNr(InvalidIndex) , m_entryStateId(AnimGraphNodeId::InvalidId) , m_alwaysStartInEntryState(true) { @@ -204,7 +204,6 @@ namespace EMotionFX bool requestInterruption = false; const bool isTransitioning = IsTransitioning(animGraphInstance); AnimGraphStateTransition* latestActiveTransition = GetLatestActiveTransition(uniqueData); - const AnimGraphNodeId sourceNodeId = sourceNode->GetId(); for (AnimGraphStateTransition* curTransition : mTransitions) { @@ -423,7 +422,6 @@ namespace EMotionFX AnimGraphNode* targetState = transition->GetTargetNode(); AnimGraphStateTransition* latestActiveTransition = GetLatestActiveTransition(uniqueData); const bool isLatestTransition = (latestActiveTransition == transition); - const bool isDone = transition->GetIsDone(animGraphInstance); EventManager& eventManager = GetEventManager(); // End transition and emit transition events. @@ -973,7 +971,7 @@ namespace EMotionFX // Legacy file format way. if (!mEntryState) { - if (mEntryStateNodeNr != MCORE_INVALIDINDEX32 && mEntryStateNodeNr < GetNumChildNodes()) + if (mEntryStateNodeNr != InvalidIndex && mEntryStateNodeNr < GetNumChildNodes()) { mEntryState = GetChildNode(mEntryStateNodeNr); } @@ -1095,11 +1093,11 @@ namespace EMotionFX AZ_Assert(stateMachine, "Unique data linked to incorrect node type."); // check if any of the active states are invalid and reset them if they are - if (mCurrentState && stateMachine->FindChildNodeIndex(mCurrentState) == MCORE_INVALIDINDEX32) + if (mCurrentState && stateMachine->FindChildNodeIndex(mCurrentState) == InvalidIndex) { mCurrentState = nullptr; } - if (mPreviousState && stateMachine->FindChildNodeIndex(mPreviousState) == MCORE_INVALIDINDEX32) + if (mPreviousState && stateMachine->FindChildNodeIndex(mPreviousState) == InvalidIndex) { mPreviousState = nullptr; } @@ -1113,8 +1111,8 @@ namespace EMotionFX const bool isTransitionValid = transition && stateMachine->FindTransitionIndex(transition).IsSuccess() && - stateMachine->FindChildNodeIndex(transition->GetSourceNode(GetAnimGraphInstance())) != MCORE_INVALIDINDEX32 && - stateMachine->FindChildNodeIndex(transition->GetTargetNode()) != MCORE_INVALIDINDEX32; + stateMachine->FindChildNodeIndex(transition->GetSourceNode(GetAnimGraphInstance())) != InvalidIndex && + stateMachine->FindChildNodeIndex(transition->GetTargetNode()) != InvalidIndex; if (!isTransitionValid) { diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphStateMachine.h b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphStateMachine.h index 8583a8a6e3..1f8d1eb591 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphStateMachine.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphStateMachine.h @@ -267,7 +267,7 @@ namespace EMotionFX private: AZStd::vector mTransitions; /**< The higher the index, the older the active transtion, the more time passed since it got started. Index = 0 is the most recent transition and the one with the highest global influence.*/ AnimGraphNode* mEntryState; /**< A pointer to the initial state, so the state where the machine starts. */ - uint32 mEntryStateNodeNr; /**< Used only in the legacy file format. Remove after the legacy file format will be removed. */ + size_t mEntryStateNodeNr; /**< Used only in the legacy file format. Remove after the legacy file format will be removed. */ AZ::u64 m_entryStateId; /**< The node id of the entry state. */ bool m_alwaysStartInEntryState; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphStateTransition.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphStateTransition.cpp index de3fa990bf..747188ead2 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphStateTransition.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphStateTransition.cpp @@ -117,8 +117,8 @@ namespace EMotionFX continue; } - const AZ::u32 numNodes = nodeGroup->GetNumNodes(); - for (AZ::u32 i = 0; i < numNodes; ++i) + const size_t numNodes = nodeGroup->GetNumNodes(); + for (size_t i = 0; i < numNodes; ++i) { AnimGraphNodeId nodeId = nodeGroup->GetNode(i); AnimGraphNode* node = stateMachine->FindChildNodeById(nodeId); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphSyncTrack.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphSyncTrack.cpp index 6c0bd18548..c6ccf038dd 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphSyncTrack.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphSyncTrack.cpp @@ -114,8 +114,8 @@ namespace EMotionFX const size_t numEvents = m_events.size(); if (numEvents == 0 || timeInSeconds > GetDuration() || timeInSeconds < 0.0f) { - *outIndexA = MCORE_INVALIDINDEX32; - *outIndexB = MCORE_INVALIDINDEX32; + *outIndexA = InvalidIndex; + *outIndexB = InvalidIndex; return false; } @@ -189,7 +189,7 @@ namespace EMotionFX } // actually we didn't find this combination - return MCORE_INVALIDINDEX32; + return InvalidIndex; } @@ -200,8 +200,8 @@ namespace EMotionFX const size_t numEvents = m_events.size(); if (numEvents == 0) { - *outIndexA = MCORE_INVALIDINDEX32; - *outIndexB = MCORE_INVALIDINDEX32; + *outIndexA = InvalidIndex; + *outIndexB = InvalidIndex; return false; } @@ -217,8 +217,8 @@ namespace EMotionFX } else { - *outIndexA = MCORE_INVALIDINDEX32; - *outIndexB = MCORE_INVALIDINDEX32; + *outIndexA = InvalidIndex; + *outIndexB = InvalidIndex; return false; } } @@ -271,15 +271,15 @@ namespace EMotionFX // if we didn't find a single hit we won't find any other if (found == false) { - *outIndexA = MCORE_INVALIDINDEX32; - *outIndexB = MCORE_INVALIDINDEX32; + *outIndexA = InvalidIndex; + *outIndexB = InvalidIndex; return false; } } // we didn't find it - *outIndexA = MCORE_INVALIDINDEX32; - *outIndexB = MCORE_INVALIDINDEX32; + *outIndexA = InvalidIndex; + *outIndexB = InvalidIndex; return false; } @@ -307,8 +307,8 @@ namespace EMotionFX current = AdvanceAndWrapIterator(current, forward, m_events.cbegin(), m_events.cend()); } while (current != start); - *outIndexA = MCORE_INVALIDINDEX32; - *outIndexB = MCORE_INVALIDINDEX32; + *outIndexA = InvalidIndex; + *outIndexB = InvalidIndex; return false; }; @@ -319,13 +319,13 @@ namespace EMotionFX const size_t numEvents = m_events.size(); if (numEvents == 0) { - *outIndexA = MCORE_INVALIDINDEX32; - *outIndexB = MCORE_INVALIDINDEX32; + *outIndexA = InvalidIndex; + *outIndexB = InvalidIndex; return false; } // if the sync index is not set, start at the first pair (which starts from the last sync key) - if (syncIndex == MCORE_INVALIDINDEX32) + if (syncIndex == InvalidIndex) { if (forward) { diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AttachmentNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AttachmentNode.cpp index 2afc50278c..d35314860f 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AttachmentNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AttachmentNode.cpp @@ -19,7 +19,7 @@ namespace EMotionFX { AZ_CLASS_ALLOCATOR_IMPL(AttachmentNode, AttachmentAllocator, 0) - AttachmentNode::AttachmentNode(ActorInstance* attachToActorInstance, AZ::u32 attachToNodeIndex, ActorInstance* attachment, bool managedExternally) + AttachmentNode::AttachmentNode(ActorInstance* attachToActorInstance, size_t attachToNodeIndex, ActorInstance* attachment, bool managedExternally) : Attachment(attachToActorInstance, attachment) , m_attachedToNode(attachToNodeIndex) , m_isManagedExternally(managedExternally) @@ -33,7 +33,7 @@ namespace EMotionFX } - AttachmentNode* AttachmentNode::Create(ActorInstance* attachToActorInstance, AZ::u32 attachToNodeIndex, ActorInstance* attachment, bool managedExternally) + AttachmentNode* AttachmentNode::Create(ActorInstance* attachToActorInstance, size_t attachToNodeIndex, ActorInstance* attachment, bool managedExternally) { return aznew AttachmentNode(attachToActorInstance, attachToNodeIndex, attachment, managedExternally); } @@ -55,7 +55,7 @@ namespace EMotionFX } - uint32 AttachmentNode::GetAttachToNodeIndex() const + size_t AttachmentNode::GetAttachToNodeIndex() const { return m_attachedToNode; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AttachmentNode.h b/Gems/EMotionFX/Code/EMotionFX/Source/AttachmentNode.h index 5bef33a90b..f88bcea648 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AttachmentNode.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AttachmentNode.h @@ -44,7 +44,7 @@ namespace EMotionFX * @param attachment The actor instance that you want to attach to this node (for example a gun). * @param managedExternally Specify whether the parent transform (where we are attached to) propagates into the attachment actor instance. */ - static AttachmentNode* Create(ActorInstance* attachToActorInstance, AZ::u32 attachToNodeIndex, ActorInstance* attachment, bool managedExternally = false); + static AttachmentNode* Create(ActorInstance* attachToActorInstance, size_t attachToNodeIndex, ActorInstance* attachment, bool managedExternally = false); /** * Get the attachment type ID. @@ -72,7 +72,7 @@ namespace EMotionFX * This node is part of the actor from which the actor instance returned by GetAttachToActorInstance() is created. * @result The node index where we will attach this attachment to. */ - AZ::u32 GetAttachToNodeIndex() const; + size_t GetAttachToNodeIndex() const; /** * Check whether the transformations of the attachment are modified by using a parent-child relationship in forward kinematics. @@ -97,7 +97,7 @@ namespace EMotionFX protected: - AZ::u32 m_attachedToNode; /**< The node where the attachment is linked to. */ + size_t m_attachedToNode; /**< The node where the attachment is linked to. */ bool m_isManagedExternally; /**< Is this attachment basically managed (transformation wise) by something else? (like an Attachment component). The default is false. */ /** @@ -107,7 +107,7 @@ namespace EMotionFX * @param attachment The actor instance that you want to attach to this node (for example a gun). * @param managedExternally Specify whether the parent transform (where we are attached to) propagates into the attachment actor instance. */ - AttachmentNode(ActorInstance* attachToActorInstance, AZ::u32 attachToNodeIndex, ActorInstance* attachment, bool managedExternally = false); + AttachmentNode(ActorInstance* attachToActorInstance, size_t attachToNodeIndex, ActorInstance* attachment, bool managedExternally = false); /** * The destructor. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AttachmentSkin.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AttachmentSkin.cpp index f2f761e849..db66e1c50a 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AttachmentSkin.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AttachmentSkin.cpp @@ -53,12 +53,12 @@ namespace EMotionFX } // Iterate over the morph targets inside the attachment, and try to locate them inside the actor instance we are attaching to. - const AZ::u32 numTargetMorphs = targetMorphSetup->GetNumMorphTargets(); - m_morphMap.reserve(static_cast(numTargetMorphs)); - for (AZ::u32 i = 0; i < numTargetMorphs; ++i) + const size_t numTargetMorphs = targetMorphSetup->GetNumMorphTargets(); + m_morphMap.reserve(numTargetMorphs); + for (size_t i = 0; i < numTargetMorphs; ++i) { - const AZ::u32 sourceMorphIndex = sourceMorphSetup->FindMorphTargetNumberByID(targetMorphSetup->GetMorphTarget(i)->GetID()); - if (sourceMorphIndex == MCORE_INVALIDINDEX32) + const size_t sourceMorphIndex = sourceMorphSetup->FindMorphTargetNumberByID(targetMorphSetup->GetMorphTarget(i)->GetID()); + if (sourceMorphIndex == InvalidIndex) { continue; } @@ -82,9 +82,9 @@ namespace EMotionFX Skeleton* attachmentSkeleton = m_attachment->GetActor()->GetSkeleton(); Skeleton* skeleton = m_actorInstance->GetActor()->GetSkeleton(); - const uint32 numNodes = attachmentSkeleton->GetNumNodes(); + const size_t numNodes = attachmentSkeleton->GetNumNodes(); m_jointMap.reserve(numNodes); - for (uint32 i = 0; i < numNodes; ++i) + for (size_t i = 0; i < numNodes; ++i) { Node* attachmentNode = attachmentSkeleton->GetNode(i); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AttachmentSkin.h b/Gems/EMotionFX/Code/EMotionFX/Source/AttachmentSkin.h index acbf975054..26302c50c1 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AttachmentSkin.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AttachmentSkin.h @@ -37,14 +37,14 @@ namespace EMotionFX */ struct EMFX_API JointMapping { - AZ::u32 m_sourceJoint; /**< The source joint in the actor where this is attached to. */ - AZ::u32 m_targetJoint; /**< The target joint in the attachment actor instance. */ + size_t m_sourceJoint; /**< The source joint in the actor where this is attached to. */ + size_t m_targetJoint; /**< The target joint in the attachment actor instance. */ }; struct EMFX_API MorphMapping { - AZ::u32 m_sourceMorphIndex; /**< The source morph target index. The source is the actor instance we are attaching to. */ - AZ::u32 m_targetMorphIndex; /**< The target morph target index. The target is the attachment actor instance. */ + size_t m_sourceMorphIndex; /**< The source morph target index. The source is the actor instance we are attaching to. */ + size_t m_targetMorphIndex; /**< The target morph target index. The target is the attachment actor instance. */ }; /** @@ -92,14 +92,14 @@ namespace EMotionFX * @param nodeIndex The joint index inside the actor instance that represents the attachment. * @result A reference to the mapping information for this joint. */ - MCORE_INLINE JointMapping& GetJointMapping(uint32 nodeIndex) { return m_jointMap[nodeIndex]; } + MCORE_INLINE JointMapping& GetJointMapping(size_t nodeIndex) { return m_jointMap[nodeIndex]; } /** * Get the mapping for a given joint. * @param nodeIndex The joint index inside the actor instance that represents the attachment. * @result A reference to the mapping information for this joint. */ - MCORE_INLINE const JointMapping& GetJointMapping(uint32 nodeIndex) const { return m_jointMap[nodeIndex]; } + MCORE_INLINE const JointMapping& GetJointMapping(size_t nodeIndex) const { return m_jointMap[nodeIndex]; } protected: AZStd::vector m_jointMap; /**< Specifies which joints we need to copy transforms from and to. */ diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTree.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTree.cpp index 1952ba9b2a..809a5d1c31 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTree.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTree.cpp @@ -356,8 +356,8 @@ namespace EMotionFX void BlendTree::RecursiveFindCycles(AnimGraphNode* nextNode, AZStd::unordered_set& visitedNodes, AZStd::unordered_set >& cycleConnections) const { AZStd::unordered_map > sourceNodesAndConnections; - const uint32 numConnections = nextNode->GetNumConnections(); - for (uint32 j = 0; j < numConnections; ++j) + const size_t numConnections = nextNode->GetNumConnections(); + for (size_t j = 0; j < numConnections; ++j) { AnimGraphNode* sourceNode = nextNode->GetConnection(j)->GetSourceNode(); sourceNodesAndConnections[sourceNode].emplace_back(nextNode->GetConnection(j)); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeAccumTransformNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeAccumTransformNode.cpp index 60e5f837b0..ffbf38c48a 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeAccumTransformNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeAccumTransformNode.cpp @@ -49,7 +49,7 @@ namespace EMotionFX } else { - mNodeIndex = InvalidIndex32; + mNodeIndex = InvalidIndex; SetHasError(true); } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeAccumTransformNode.h b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeAccumTransformNode.h index 86ad69ec69..d8ca76aaa8 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeAccumTransformNode.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeAccumTransformNode.h @@ -84,7 +84,7 @@ namespace EMotionFX public: Transform mAdditiveTransform = Transform::CreateIdentity(); - uint32 mNodeIndex = InvalidIndex32; + size_t mNodeIndex = InvalidIndex; float mDeltaTime = 0.0f; }; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlend2AdditiveNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlend2AdditiveNode.cpp index e6ce8c6119..f16d2f6943 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlend2AdditiveNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlend2AdditiveNode.cpp @@ -214,7 +214,7 @@ namespace EMotionFX for (size_t n = 0; n < numNodes; ++n) { const float finalWeight = blendWeight;// * uniqueData->mWeights[n]; - const uint32 nodeIndex = uniqueData->mMask[n]; + const size_t nodeIndex = uniqueData->mMask[n]; transform = outputLocalPose.GetLocalSpaceTransform(nodeIndex); transform.ApplyAdditive(additivePose.GetLocalSpaceTransform(nodeIndex), finalWeight); outputLocalPose.SetLocalSpaceTransform(nodeIndex, transform); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlend2LegacyNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlend2LegacyNode.cpp index 7e2fdd4736..78fbd91dd1 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlend2LegacyNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlend2LegacyNode.cpp @@ -237,7 +237,7 @@ namespace EMotionFX for (size_t n = 0; n < numNodes; ++n) { const float finalWeight = blendWeight /* * uniqueData->mWeights[n]*/; - const uint32 nodeIndex = uniqueData->mMask[n]; + const size_t nodeIndex = uniqueData->mMask[n]; transform = outputLocalPose.GetLocalSpaceTransform(nodeIndex); transform.Blend(localMaskPose.GetLocalSpaceTransform(nodeIndex), finalWeight); outputLocalPose.SetLocalSpaceTransform(nodeIndex, transform); @@ -250,7 +250,7 @@ namespace EMotionFX for (size_t n = 0; n < numNodes; ++n) { const float finalWeight = blendWeight /* * uniqueData->mWeights[n]*/; - const uint32 nodeIndex = uniqueData->mMask[n]; + const size_t nodeIndex = uniqueData->mMask[n]; transform = outputLocalPose.GetLocalSpaceTransform(nodeIndex); transform.BlendAdditive(localMaskPose.GetLocalSpaceTransform(nodeIndex), bindPose->GetLocalSpaceTransform(nodeIndex), finalWeight); outputLocalPose.SetLocalSpaceTransform(nodeIndex, transform); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlend2Node.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlend2Node.cpp index f3b9ee2014..dfa7be26f8 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlend2Node.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlend2Node.cpp @@ -217,7 +217,7 @@ namespace EMotionFX for (size_t n = 0; n < numNodes; ++n) { const float finalWeight = blendWeight /* * uniqueData->mWeights[n]*/; - const uint32 nodeIndex = uniqueData->mMask[n]; + const size_t nodeIndex = uniqueData->mMask[n]; transform = outputLocalPose.GetLocalSpaceTransform(nodeIndex); transform.Blend(localMaskPose.GetLocalSpaceTransform(nodeIndex), finalWeight); outputLocalPose.SetLocalSpaceTransform(nodeIndex, transform); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlend2NodeBase.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlend2NodeBase.cpp index 1a33ee1d85..2876605b0a 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlend2NodeBase.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlend2NodeBase.cpp @@ -116,7 +116,7 @@ namespace EMotionFX *outWeight = MCore::Clamp(*outWeight, 0.0f, 1.0f); UniqueData* uniqueData = static_cast(animGraphInstance->FindOrCreateUniqueObjectData(this)); - if (uniqueData->mMask.size() > 0) + if (!uniqueData->mMask.empty()) { *outBlendNodeA = connectionA->GetSourceNode(); *outBlendNodeB = connectionB->GetSourceNode(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlend2NodeBase.h b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlend2NodeBase.h index d67238705d..217e2a2e23 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlend2NodeBase.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlend2NodeBase.h @@ -54,7 +54,7 @@ namespace EMotionFX void Update() override; public: - AZStd::vector mMask; + AZStd::vector mMask; AnimGraphNode* mSyncTrackNode; }; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeFootIKNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeFootIKNode.cpp index 8e0e67e95a..97d7d4baa0 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeFootIKNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeFootIKNode.cpp @@ -270,8 +270,8 @@ namespace EMotionFX // Generate the ray start and end position. void BlendTreeFootIKNode::GenerateRayStartEnd(LegId legId, LegJointId jointId, AnimGraphInstance* animGraphInstance, UniqueData* uniqueData, const Pose& inputPose, AZ::Vector3& outRayStart, AZ::Vector3& outRayEnd) const { - const AZ::u32 jointIndex = uniqueData->m_legs[legId].m_jointIndices[jointId]; - AZ_Assert(jointIndex != MCORE_INVALIDINDEX32, "Expecting the joint index to be valid."); + const size_t jointIndex = uniqueData->m_legs[legId].m_jointIndices[jointId]; + AZ_Assert(jointIndex != InvalidIndex, "Expecting the joint index to be valid."); const float rayLength = GetRaycastLength(animGraphInstance); const AZ::Vector3 upVector = animGraphInstance->GetActorInstance()->GetWorldSpaceTransform().mRotation @@ -412,8 +412,8 @@ namespace EMotionFX const float weight = leg.m_weight * solveParams.m_weight; if (!solveParams.m_forceIKDisabled && leg.IsFlagEnabled(LegFlags::IkEnabled) && weight > AZ::Constants::FloatEpsilon) { - const AZ::u32 footIndex = leg.m_jointIndices[LegJointId::Foot]; - const AZ::u32 toeIndex = leg.m_jointIndices[LegJointId::Toe]; + const size_t footIndex = leg.m_jointIndices[LegJointId::Foot]; + const size_t toeIndex = leg.m_jointIndices[LegJointId::Toe]; // When both foot and toe are on the floor float distToToeTarget = 0.01f; @@ -523,9 +523,9 @@ namespace EMotionFX void BlendTreeFootIKNode::SolveLegIK(LegId legId, const IKSolveParameters& solveParams) { Leg& leg = solveParams.m_uniqueData->m_legs[legId]; - const AZ::u32 upperLegIndex = leg.m_jointIndices[LegJointId::UpperLeg]; - const AZ::u32 kneeIndex = leg.m_jointIndices[LegJointId::Knee]; - const AZ::u32 footIndex = leg.m_jointIndices[LegJointId::Foot]; + const size_t upperLegIndex = leg.m_jointIndices[LegJointId::UpperLeg]; + const size_t kneeIndex = leg.m_jointIndices[LegJointId::Knee]; + const size_t footIndex = leg.m_jointIndices[LegJointId::Foot]; // Calculate the world space transforms of the joints inside the leg. Transform inputGlobalTransforms[4]; @@ -701,7 +701,7 @@ namespace EMotionFX { for (size_t i = 1; i < 4; ++i) { - const AZ::u32 nodeIndex = leg.m_jointIndices[Toe - i]; + const size_t nodeIndex = leg.m_jointIndices[Toe - i]; solveParams.m_outputPose->UpdateLocalSpaceTransform(nodeIndex); Transform finalTransform = solveParams.m_inputPose->GetLocalSpaceTransform(nodeIndex); finalTransform.Blend(solveParams.m_outputPose->GetLocalSpaceTransform(nodeIndex), weight); @@ -924,8 +924,8 @@ namespace EMotionFX } const AnimGraphEventBuffer& eventBuffer = uniqueData->m_eventBuffer; - const AZ::u32 numEvents = eventBuffer.GetNumEvents(); - for (AZ::u32 i = 0; i < numEvents; ++i) + const size_t numEvents = eventBuffer.GetNumEvents(); + for (size_t i = 0; i < numEvents; ++i) { const EventInfo& eventInfo = eventBuffer.GetEvent(i); const MotionEvent* motionEvent = eventInfo.mEvent; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeGetTransformNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeGetTransformNode.cpp index 4947836da8..fd04a43251 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeGetTransformNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeGetTransformNode.cpp @@ -36,7 +36,7 @@ namespace EMotionFX BlendTreeGetTransformNode* transformNode = azdynamic_cast(mObject); AZ_Assert(transformNode, "Unique data linked to incorrect node type."); - m_nodeIndex = InvalidIndex32; + m_nodeIndex = InvalidIndex; const AZStd::string& nodeName = transformNode->GetNodeName(); const int actorInstanceParentDepth = transformNode->GetActorInstanceParentDepth(); @@ -106,7 +106,7 @@ namespace EMotionFX if (GetEMotionFX().GetIsInEditorMode()) { - SetHasError(uniqueData, uniqueData->m_nodeIndex == MCORE_INVALIDINDEX32); + SetHasError(uniqueData, uniqueData->m_nodeIndex == InvalidIndex); } // make sure we have at least an input pose, otherwise output the bind pose @@ -117,7 +117,7 @@ namespace EMotionFX } Pose* pose = nullptr; - if (uniqueData->m_nodeIndex != MCORE_INVALIDINDEX32) + if (uniqueData->m_nodeIndex != InvalidIndex) { if (m_actorNode.second == 0) { diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeGetTransformNode.h b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeGetTransformNode.h index 83e07103d8..ab441fab62 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeGetTransformNode.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeGetTransformNode.h @@ -64,7 +64,7 @@ namespace EMotionFX void Update() override; public: - AZ::u32 m_nodeIndex = InvalidIndex32; + size_t m_nodeIndex = InvalidIndex; }; BlendTreeGetTransformNode(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeLookAtNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeLookAtNode.cpp index 895739b315..f904f35ba4 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeLookAtNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeLookAtNode.cpp @@ -40,7 +40,7 @@ namespace EMotionFX const ActorInstance* actorInstance = mAnimGraphInstance->GetActorInstance(); const Actor* actor = actorInstance->GetActor(); - mNodeIndex = InvalidIndex32; + mNodeIndex = InvalidIndex; SetHasError(true); const AZStd::string& targetJointName = lookAtNode->GetTargetNodeName(); @@ -177,7 +177,7 @@ namespace EMotionFX ActorInstance* actorInstance = animGraphInstance->GetActorInstance(); // get a shortcut to the local transform object - const uint32 nodeIndex = uniqueData->mNodeIndex; + const size_t nodeIndex = uniqueData->mNodeIndex; Pose& outTransformPose = outputPose->GetPose(); Transform globalTransform = outTransformPose.GetWorldSpaceTransform(nodeIndex); @@ -203,10 +203,10 @@ namespace EMotionFX if (m_limitsEnabled) { // calculate the delta between the bind pose rotation and current target rotation and constraint that to our limits - const uint32 parentIndex = skeleton->GetNode(nodeIndex)->GetParentIndex(); + const size_t parentIndex = skeleton->GetNode(nodeIndex)->GetParentIndex(); AZ::Quaternion parentRotationGlobal; AZ::Quaternion bindRotationLocal; - if (parentIndex != MCORE_INVALIDINDEX32) + if (parentIndex != InvalidIndex) { parentRotationGlobal = inputPose->GetPose().GetWorldSpaceTransform(parentIndex).mRotation; bindRotationLocal = actorInstance->GetTransformData()->GetBindPose()->GetLocalSpaceTransform(parentIndex).mRotation; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeLookAtNode.h b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeLookAtNode.h index a7494b2514..4da3855dd1 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeLookAtNode.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeLookAtNode.h @@ -65,7 +65,7 @@ namespace EMotionFX public: AZ::Quaternion mRotationQuat = AZ::Quaternion::CreateIdentity(); float mTimeDelta = 0.0f; - uint32 mNodeIndex = InvalidIndex32; + size_t mNodeIndex = InvalidIndex; bool mFirstUpdate = true; }; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeMaskLegacyNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeMaskLegacyNode.cpp index ac85704381..88da8346d0 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeMaskLegacyNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeMaskLegacyNode.cpp @@ -54,7 +54,7 @@ namespace EMotionFX , m_outputEvents3(true) { // setup the input ports - InitInputPorts(static_cast(m_numMasks)); + InitInputPorts(m_numMasks); SetupInputPort("Pose 0", INPUTPORT_POSE_0, AttributePose::TYPE_ID, PORTID_INPUT_POSE_0); SetupInputPort("Pose 1", INPUTPORT_POSE_1, AttributePose::TYPE_ID, PORTID_INPUT_POSE_1); SetupInputPort("Pose 2", INPUTPORT_POSE_2, AttributePose::TYPE_ID, PORTID_INPUT_POSE_2); @@ -104,7 +104,7 @@ namespace EMotionFX UniqueData* uniqueData = static_cast(FindOrCreateUniqueNodeData(animGraphInstance)); // for all input ports - for (uint32 i = 0; i < m_numMasks; ++i) + for (size_t i = 0; i < m_numMasks; ++i) { // if there is no connection plugged in if (mInputPorts[INPUTPORT_POSE_0 + i].mConnection == nullptr) @@ -121,7 +121,7 @@ namespace EMotionFX outputPose = GetOutputPose(animGraphInstance, OUTPUTPORT_RESULT)->GetValue(); outputPose->InitFromBindPose(animGraphInstance->GetActorInstance()); - for (uint32 i = 0; i < m_numMasks; ++i) + for (size_t i = 0; i < m_numMasks; ++i) { // if there is no connection plugged in if (mInputPorts[INPUTPORT_POSE_0 + i].mConnection == nullptr) @@ -139,10 +139,9 @@ namespace EMotionFX if (numNodes > 0) { // for all nodes in the mask, output their transforms - for (size_t n = 0; n < numNodes; ++n) + for (size_t nodeIndex : uniqueData->mMasks[i]) { - const uint32 nodeIndex = uniqueData->mMasks[i][n]; - outputLocalPose.SetLocalSpaceTransform(nodeIndex, localPose.GetLocalSpaceTransform(nodeIndex)); + outputLocalPose.SetLocalSpaceTransform(nodeIndex, localPose.GetLocalSpaceTransform(nodeIndex)); } } else @@ -183,7 +182,7 @@ namespace EMotionFX void BlendTreeMaskLegacyNode::PostUpdate(AnimGraphInstance* animGraphInstance, float timePassedInSeconds) { // post update all incoming nodes - for (uint32 i = 0; i < m_numMasks; ++i) + for (size_t i = 0; i < m_numMasks; ++i) { // if the port has no input, skip it AnimGraphNode* inputNode = GetInputNode(INPUTPORT_POSE_0 + i); @@ -203,7 +202,7 @@ namespace EMotionFX data->ClearEventBuffer(); data->ZeroTrajectoryDelta(); - for (uint32 i = 0; i < m_numMasks; ++i) + for (size_t i = 0; i < m_numMasks; ++i) { // if the port has no input, skip it AnimGraphNode* inputNode = GetInputNode(INPUTPORT_POSE_0 + i); @@ -217,9 +216,8 @@ namespace EMotionFX if (numNodes > 0) { // for all nodes in the mask, output their transforms - for (size_t n = 0; n < numNodes; ++n) + for (size_t nodeIndex : uniqueData->mMasks[i]) { - const uint32 nodeIndex = uniqueData->mMasks[i][n]; if (nodeIndex == animGraphInstance->GetActorInstance()->GetActor()->GetMotionExtractionNodeIndex()) { AnimGraphRefCountedData* sourceData = inputNode->FindOrCreateUniqueNodeData(animGraphInstance)->GetRefCountedData(); @@ -244,14 +242,14 @@ namespace EMotionFX // get the input event buffer const AnimGraphEventBuffer& inputEventBuffer = inputNode->FindOrCreateUniqueNodeData(animGraphInstance)->GetRefCountedData()->GetEventBuffer(); AnimGraphEventBuffer& outputEventBuffer = data->GetEventBuffer(); - const uint32 startIndex = outputEventBuffer.GetNumEvents(); + const size_t startIndex = outputEventBuffer.GetNumEvents(); // resize the buffer already, so that we don't do this for every event outputEventBuffer.Resize(outputEventBuffer.GetNumEvents() + inputEventBuffer.GetNumEvents()); // copy over all the events - const uint32 numInputEvents = inputEventBuffer.GetNumEvents(); - for (uint32 e = 0; e < numInputEvents; ++e) + const size_t numInputEvents = inputEventBuffer.GetNumEvents(); + for (size_t e = 0; e < numInputEvents; ++e) { outputEventBuffer.SetEvent(startIndex + e, inputEventBuffer.GetEvent(e)); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeMaskLegacyNode.h b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeMaskLegacyNode.h index d2f50f918d..0cddd9610a 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeMaskLegacyNode.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeMaskLegacyNode.h @@ -53,7 +53,7 @@ namespace EMotionFX void Update() override; public: - AZStd::vector< AZStd::vector > mMasks; + AZStd::vector< AZStd::vector > mMasks; }; BlendTreeMaskLegacyNode(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeMaskNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeMaskNode.cpp index 8b65f76dbd..d43ac3b033 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeMaskNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeMaskNode.cpp @@ -36,10 +36,10 @@ namespace EMotionFX const Actor* actor = mAnimGraphInstance->GetActorInstance()->GetActor(); const size_t numMaskInstances = maskNode->GetNumUsedMasks(); m_maskInstances.resize(numMaskInstances); - AZ::u32 maskInstanceIndex = 0; + size_t maskInstanceIndex = 0; m_motionExtractionInputPortNr.reset(); - const AZ::u32 motionExtractionJointIndex = mAnimGraphInstance->GetActorInstance()->GetActor()->GetMotionExtractionNodeIndex(); + const size_t motionExtractionJointIndex = mAnimGraphInstance->GetActorInstance()->GetActor()->GetMotionExtractionNodeIndex(); const AZStd::vector& masks = maskNode->GetMasks(); const size_t numMasks = masks.size(); @@ -48,7 +48,7 @@ namespace EMotionFX const Mask& mask = masks[i]; if (!mask.m_jointNames.empty()) { - const AZ::u32 inputPortNr = INPUTPORT_START + static_cast(i); + const size_t inputPortNr = INPUTPORT_START + i; // Get the joint indices by joint names and cache them in the unique data // so that we don't have to look them up at runtime. @@ -57,7 +57,7 @@ namespace EMotionFX maskInstance.m_inputPortNr = inputPortNr; // Check if the motion extraction node is part of this mask and cache the mask index in that case. - for (AZ::u32 jointIndex : maskInstance.m_jointIndices) + for (size_t jointIndex : maskInstance.m_jointIndices) { if (jointIndex == motionExtractionJointIndex) { @@ -77,16 +77,16 @@ namespace EMotionFX m_masks.resize(s_numMasks); // Setup the input ports. - InitInputPorts(1 + static_cast(s_numMasks)); // Base pose and the input poses for the masks. + InitInputPorts(1 + s_numMasks); // Base pose and the input poses for the masks. SetupInputPort("Base Pose", INPUTPORT_BASEPOSE, AttributePose::TYPE_ID, INPUTPORT_BASEPOSE); for (size_t i = 0; i < s_numMasks; ++i) { - const AZ::u32 portNr = static_cast(i + INPUTPORT_START); + const uint32 portId = static_cast(i) + INPUTPORT_START; SetupInputPort( AZStd::string::format("Pose %zu", i).c_str(), - portNr, + portId, AttributePose::TYPE_ID, - portNr); + portId); } // Setup the output ports. @@ -176,14 +176,14 @@ namespace EMotionFX // Iterate over the non-empty masks and copy over its transforms. for (const UniqueData::MaskInstance& maskInstance : uniqueData->m_maskInstances) { - const AZ::u32 inputPortNr = maskInstance.m_inputPortNr; + const size_t inputPortNr = maskInstance.m_inputPortNr; AnimGraphNode* inputNode = GetInputNode(inputPortNr); if (inputNode) { OutputIncomingNode(animGraphInstance, inputNode); const Pose& inputPose = GetInputPose(animGraphInstance, inputPortNr)->GetValue()->GetPose(); - for (AZ::u32 jointIndex : maskInstance.m_jointIndices) + for (size_t jointIndex : maskInstance.m_jointIndices) { outputPose.SetLocalSpaceTransform(jointIndex, inputPose.GetLocalSpaceTransform(jointIndex)); } @@ -238,11 +238,9 @@ namespace EMotionFX data->SetEventBuffer(basePoseNodeUniqueData->GetRefCountedData()->GetEventBuffer()); } - const size_t numMaskInstances = uniqueData->m_maskInstances.size(); - for (size_t i = 0; i < numMaskInstances; ++i) + for (const UniqueData::MaskInstance& maskInstance : uniqueData->m_maskInstances) { - const UniqueData::MaskInstance& maskInstance = uniqueData->m_maskInstances[i]; - const AZ::u32 inputPortNr = maskInstance.m_inputPortNr; + const size_t inputPortNr = maskInstance.m_inputPortNr; AnimGraphNode* inputNode = GetInputNode(inputPortNr); if (!inputNode) { diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeMaskNode.h b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeMaskNode.h index 7577995434..258e8a475d 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeMaskNode.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeMaskNode.h @@ -49,12 +49,12 @@ namespace EMotionFX public: struct MaskInstance { - AZ::u32 m_inputPortNr; - AZStd::vector m_jointIndices; + size_t m_inputPortNr; + AZStd::vector m_jointIndices; }; AZStd::vector m_maskInstances; - AZStd::optional m_motionExtractionInputPortNr; + AZStd::optional m_motionExtractionInputPortNr; }; BlendTreeMaskNode(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeMirrorPoseNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeMirrorPoseNode.cpp index 9ab1dbf817..04199c18ca 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeMirrorPoseNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeMirrorPoseNode.cpp @@ -164,11 +164,11 @@ namespace EMotionFX Transform outputTransform; // for all enabled nodes - const uint32 numNodes = actorInstance->GetNumEnabledNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = actorInstance->GetNumEnabledNodes(); + for (size_t i = 0; i < numNodes; ++i) { // get the node index that we sample the motion data from - const uint32 nodeIndex = actorInstance->GetEnabledNode(i); + const uint16 nodeIndex = actorInstance->GetEnabledNode(i); const Actor::NodeMirrorInfo& mirrorInfo = actor->GetNodeMirrorInfo(nodeIndex); // build the mirror plane normal, based on the mirror axis for this node diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeMorphTargetNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeMorphTargetNode.cpp index 7420c005a9..ad88909e29 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeMorphTargetNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeMorphTargetNode.cpp @@ -95,9 +95,11 @@ namespace EMotionFX void BlendTreeMorphTargetNode::UpdateMorphIndices(ActorInstance* actorInstance, UniqueData* uniqueData, bool forceUpdate) { // Check if our LOD level changed, if not, we don't need to refresh it. - const uint32 lodLevel = actorInstance->GetLODLevel(); + const size_t lodLevel = actorInstance->GetLODLevel(); if (!forceUpdate && uniqueData->m_lastLodLevel == lodLevel) + { return; + } // Convert the morph target name into an index for fast lookup. if (!m_morphTargetNames.empty()) @@ -111,7 +113,7 @@ namespace EMotionFX } else { - uniqueData->m_morphTargetIndex = MCORE_INVALIDINDEX32; + uniqueData->m_morphTargetIndex = InvalidIndex; } uniqueData->m_lastLodLevel = lodLevel; @@ -133,7 +135,7 @@ namespace EMotionFX } else { - SetHasError(uniqueData, uniqueData->m_morphTargetIndex == MCORE_INVALIDINDEX32); + SetHasError(uniqueData, uniqueData->m_morphTargetIndex == InvalidIndex); } } @@ -160,7 +162,7 @@ namespace EMotionFX } // Try to modify the morph target weight with the value we specified as input. - if (!mDisabled && uniqueData->m_morphTargetIndex != MCORE_INVALIDINDEX32) + if (!mDisabled && uniqueData->m_morphTargetIndex != InvalidIndex) { // If we have an input to the weight port, read that value use that value to overwrite the pose value with. if (mInputPorts[INPUTPORT_WEIGHT].mConnection) diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeMorphTargetNode.h b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeMorphTargetNode.h index 693ebcaef5..daa41c2a24 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeMorphTargetNode.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeMorphTargetNode.h @@ -48,8 +48,8 @@ namespace EMotionFX void Update() override; public: - uint32 m_lastLodLevel = InvalidIndex32; - uint32 m_morphTargetIndex = InvalidIndex32; + size_t m_lastLodLevel = InvalidIndex; + size_t m_morphTargetIndex = InvalidIndex; }; BlendTreeMorphTargetNode(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeRagdollNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeRagdollNode.cpp index 4cf82cc77b..f62d569a16 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeRagdollNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeRagdollNode.cpp @@ -241,8 +241,8 @@ namespace EMotionFX // Copy ragdoll transforms (world space) and reconstruct the rest of the skeleton using the target input pose. // If the current node is part of the ragdoll, copy the world transforms from the ragdoll node to the pose and recalculate the local transform. // In case the current node is not part of the ragdoll, update the world transforms based on the local transform from the bind pose. - const AZ::u32 jointCount = skeleton->GetNumNodes(); - for (AZ::u32 jointIndex = 0; jointIndex < jointCount; ++jointIndex) + const size_t jointCount = skeleton->GetNumNodes(); + for (size_t jointIndex = 0; jointIndex < jointCount; ++jointIndex) { Node* joint = skeleton->GetNode(jointIndex); const AZ::Outcome ragdollNodeIndex = ragdollInstance->GetRagdollNodeIndex(jointIndex); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeRagdollStrengthModifierNode.h b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeRagdollStrengthModifierNode.h index 763ccd812c..05891a488f 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeRagdollStrengthModifierNode.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeRagdollStrengthModifierNode.h @@ -62,7 +62,7 @@ namespace EMotionFX void Update() override; public: - AZStd::vector m_modifiedJointIndices; + AZStd::vector m_modifiedJointIndices; }; BlendTreeRagdollStrenghModifierNode(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeSetTransformNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeSetTransformNode.cpp index b922eb9b59..0817b95614 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeSetTransformNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeSetTransformNode.cpp @@ -38,7 +38,7 @@ namespace EMotionFX ActorInstance* actorInstance = mAnimGraphInstance->GetActorInstance(); Actor* actor = actorInstance->GetActor(); - m_nodeIndex = InvalidIndex32; + m_nodeIndex = InvalidIndex; const AZStd::string& jointName = transformNode->GetJointName(); if (!jointName.empty()) @@ -106,7 +106,7 @@ namespace EMotionFX if (GetEMotionFX().GetIsInEditorMode()) { - SetHasError(uniqueData, uniqueData->m_nodeIndex == MCORE_INVALIDINDEX32); + SetHasError(uniqueData, uniqueData->m_nodeIndex == InvalidIndex); } OutputAllIncomingNodes(animGraphInstance); @@ -129,7 +129,7 @@ namespace EMotionFX if (GetIsEnabled()) { // get the local transform from our node - if (uniqueData->m_nodeIndex != MCORE_INVALIDINDEX32) + if (uniqueData->m_nodeIndex != InvalidIndex) { Transform outputTransform; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeSetTransformNode.h b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeSetTransformNode.h index be088a2c46..de60fa57f7 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeSetTransformNode.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeSetTransformNode.h @@ -66,7 +66,7 @@ namespace EMotionFX void Update() override; public: - uint32 m_nodeIndex = InvalidIndex32; + size_t m_nodeIndex = InvalidIndex; }; BlendTreeSetTransformNode(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeTransformNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeTransformNode.cpp index e8005cee28..07f3256a35 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeTransformNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeTransformNode.cpp @@ -41,7 +41,7 @@ namespace EMotionFX const AZStd::string& targetJointName = transformNode->GetTargetJointName(); - mNodeIndex = InvalidIndex32; + mNodeIndex = InvalidIndex; SetHasError(true); if (!targetJointName.empty()) diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeTransformNode.h b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeTransformNode.h index 7d685c2528..1d337fa6a1 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeTransformNode.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeTransformNode.h @@ -70,7 +70,7 @@ namespace EMotionFX void Update() override; public: - uint32 mNodeIndex = InvalidIndex32; + size_t mNodeIndex = InvalidIndex; }; BlendTreeTransformNode(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeTwoLinkIKNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeTwoLinkIKNode.cpp index 1cfafb11d1..1054cef095 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeTwoLinkIKNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeTwoLinkIKNode.cpp @@ -39,12 +39,12 @@ namespace EMotionFX const Skeleton* skeleton = actor->GetSkeleton(); // don't update the next time again - mNodeIndexA = InvalidIndex32; - mNodeIndexB = InvalidIndex32; - mNodeIndexC = InvalidIndex32; - mAlignNodeIndex = InvalidIndex32; - mBendDirNodeIndex = InvalidIndex32; - mEndEffectorNodeIndex = InvalidIndex32; + mNodeIndexA = InvalidIndex; + mNodeIndexB = InvalidIndex; + mNodeIndexC = InvalidIndex; + mAlignNodeIndex = InvalidIndex; + mBendDirNodeIndex = InvalidIndex; + mEndEffectorNodeIndex = InvalidIndex; SetHasError(true); // Find the end joint. @@ -62,14 +62,14 @@ namespace EMotionFX // Get the second joint. mNodeIndexB = jointC->GetParentIndex(); - if (mNodeIndexB == InvalidIndex32) + if (mNodeIndexB == InvalidIndex) { return; } // Get the third joint. mNodeIndexA = skeleton->GetNode(mNodeIndexB)->GetParentIndex(); - if (mNodeIndexA == InvalidIndex32) + if (mNodeIndexA == InvalidIndex) { return; } @@ -260,15 +260,15 @@ namespace EMotionFX } // get the node indices - const uint32 nodeIndexA = uniqueData->mNodeIndexA; - const uint32 nodeIndexB = uniqueData->mNodeIndexB; - const uint32 nodeIndexC = uniqueData->mNodeIndexC; - const uint32 bendDirIndex = uniqueData->mBendDirNodeIndex; - uint32 alignNodeIndex = uniqueData->mAlignNodeIndex; - uint32 endEffectorNodeIndex = uniqueData->mEndEffectorNodeIndex; + const size_t nodeIndexA = uniqueData->mNodeIndexA; + const size_t nodeIndexB = uniqueData->mNodeIndexB; + const size_t nodeIndexC = uniqueData->mNodeIndexC; + const size_t bendDirIndex = uniqueData->mBendDirNodeIndex; + size_t alignNodeIndex = uniqueData->mAlignNodeIndex; + size_t endEffectorNodeIndex = uniqueData->mEndEffectorNodeIndex; // use the end node as end effector node if no goal node has been specified - if (endEffectorNodeIndex == MCORE_INVALIDINDEX32) + if (endEffectorNodeIndex == InvalidIndex) { endEffectorNodeIndex = nodeIndexC; } @@ -289,7 +289,7 @@ namespace EMotionFX EMotionFX::Transform alignNodeTransform; // adjust the gizmo offset value - if (alignNodeIndex != MCORE_INVALIDINDEX32) + if (alignNodeIndex != InvalidIndex) { // update the alignment actor instance alignInstance = animGraphInstance->FindActorInstanceFromParentDepth(m_alignToNode.second); @@ -322,7 +322,7 @@ namespace EMotionFX } else { - alignNodeIndex = MCORE_INVALIDINDEX32; // we were not able to get the align instance, so set the align node index to the invalid index + alignNodeIndex = InvalidIndex; // we were not able to get the align instance, so set the align node index to the invalid index } } else if (GetEMotionFX().GetIsInEditorMode()) @@ -350,7 +350,7 @@ namespace EMotionFX AZ::Vector3 bendDir; if (m_extractBendDir) { - if (bendDirIndex != MCORE_INVALIDINDEX32) + if (bendDirIndex != InvalidIndex) { bendDir = outTransformPose.GetWorldSpaceTransform(bendDirIndex).mPosition - globalTransformA.mPosition; } @@ -386,7 +386,7 @@ namespace EMotionFX const MCore::AttributeQuaternion* inputGoalRot = GetInputQuaternion(animGraphInstance, INPUTPORT_GOALROT); // if we don't want to align the rotation and position to another given node - if (alignNodeIndex == MCORE_INVALIDINDEX32) + if (alignNodeIndex == InvalidIndex) { AZ::Quaternion newRotation = AZ::Quaternion::CreateIdentity(); // identity quat if (inputGoalRot) diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeTwoLinkIKNode.h b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeTwoLinkIKNode.h index 7a1a858804..807eb4044e 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeTwoLinkIKNode.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeTwoLinkIKNode.h @@ -60,12 +60,12 @@ namespace EMotionFX void Update() override; public: - uint32 mNodeIndexA = InvalidIndex32; - uint32 mNodeIndexB = InvalidIndex32; - uint32 mNodeIndexC = InvalidIndex32; - uint32 mEndEffectorNodeIndex = InvalidIndex32; - uint32 mAlignNodeIndex = InvalidIndex32; - uint32 mBendDirNodeIndex = InvalidIndex32; + size_t mNodeIndexA = InvalidIndex; + size_t mNodeIndexB = InvalidIndex; + size_t mNodeIndexC = InvalidIndex; + size_t mEndEffectorNodeIndex = InvalidIndex; + size_t mAlignNodeIndex = InvalidIndex; + size_t mBendDirNodeIndex = InvalidIndex; }; BlendTreeTwoLinkIKNode(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/DebugDraw.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/DebugDraw.cpp index 72c52edc66..8f1346f543 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/DebugDraw.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/DebugDraw.cpp @@ -110,12 +110,12 @@ namespace EMotionFX { const Skeleton* skeleton = m_actorInstance->GetActor()->GetSkeleton(); - const AZ::u32 numNodes = m_actorInstance->GetNumEnabledNodes(); - for (AZ::u32 i = 0; i < numNodes; ++i) + const size_t numNodes = m_actorInstance->GetNumEnabledNodes(); + for (size_t i = 0; i < numNodes; ++i) { - const AZ::u32 nodeIndex = m_actorInstance->GetEnabledNode(i); - const AZ::u32 parentIndex = skeleton->GetNode(nodeIndex)->GetParentIndex(); - if (parentIndex != MCORE_INVALIDINDEX32) + const size_t nodeIndex = m_actorInstance->GetEnabledNode(i); + const size_t parentIndex = skeleton->GetNode(nodeIndex)->GetParentIndex(); + if (parentIndex != InvalidIndex) { const AZ::Vector3& startPos = pose.GetWorldSpaceTransform(nodeIndex).mPosition; const AZ::Vector3& endPos = pose.GetWorldSpaceTransform(parentIndex).mPosition; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/DualQuatSkinDeformer.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/DualQuatSkinDeformer.cpp index 34e336bf2f..c107ae88f7 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/DualQuatSkinDeformer.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/DualQuatSkinDeformer.cpp @@ -33,7 +33,7 @@ namespace EMotionFX { } - AZ::Outcome DualQuatSkinDeformer::FindLocalBoneIndex(uint32 nodeIndex) const + AZ::Outcome DualQuatSkinDeformer::FindLocalBoneIndex(size_t nodeIndex) const { const size_t numBones = m_bones.size(); for (size_t i = 0; i < numBones; ++i) @@ -62,7 +62,7 @@ namespace EMotionFX return SUBTYPE_ID; } - MeshDeformer* DualQuatSkinDeformer::Clone(Mesh* mesh) + MeshDeformer* DualQuatSkinDeformer::Clone(Mesh* mesh) const { // create the new cloned deformer DualQuatSkinDeformer* result = aznew DualQuatSkinDeformer(mesh); @@ -84,7 +84,7 @@ namespace EMotionFX // pre-calculate the skinning matrices for (BoneInfo& boneInfo : m_bones) { - const uint32 nodeIndex = boneInfo.mNodeNr; + const size_t nodeIndex = boneInfo.mNodeNr; const Transform skinTransform = actor->GetInverseBindPoseTransform(nodeIndex) * pose->GetModelSpaceTransform(nodeIndex); boneInfo.mDualQuat.FromRotationTranslation(skinTransform.mRotation, skinTransform.mPosition); } @@ -327,7 +327,7 @@ namespace EMotionFX AZ::Outcome boneIndexOutcome = FindLocalBoneIndex(influence->GetNodeNr()); if (boneIndexOutcome.IsSuccess()) { - influence->SetBoneNr(static_cast(boneIndexOutcome.GetValue())); + influence->SetBoneNr(aznumeric_caster(boneIndexOutcome.GetValue())); } else { diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/DualQuatSkinDeformer.h b/Gems/EMotionFX/Code/EMotionFX/Source/DualQuatSkinDeformer.h index d3bec012f6..154885ea7d 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/DualQuatSkinDeformer.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/DualQuatSkinDeformer.h @@ -75,7 +75,7 @@ namespace EMotionFX * @param mesh The mesh to apply the deformer on. * @result A pointer to the newly created clone of this deformer. */ - MeshDeformer* Clone(Mesh* mesh) override; + MeshDeformer* Clone(Mesh* mesh) const override; /** * Returns the unique type ID of the deformer. @@ -104,7 +104,7 @@ namespace EMotionFX * @param index The local bone number, which must be in range of [0..GetNumLocalBones()-1]. * @result The node number, which is in range of [0..Actor::GetNumNodes()-1], depending on the actor where this deformer works on. */ - MCORE_INLINE uint32 GetLocalBone(uint32 index) const { return m_bones[index].mNodeNr; } + MCORE_INLINE size_t GetLocalBone(size_t index) const { return m_bones[index].mNodeNr; } /** * Pre-allocate space for a given number of local bones. @@ -119,11 +119,11 @@ namespace EMotionFX */ struct EMFX_API BoneInfo { - uint32 mNodeNr; /**< The node number. */ + size_t mNodeNr; /**< The node number. */ MCore::DualQuaternion mDualQuat; /**< The dual quat of the pre-calculated matrix that contains the "globalMatrix * inverse(bindPoseMatrix)". */ MCORE_INLINE BoneInfo() - : mNodeNr(MCORE_INVALIDINDEX32) {} + : mNodeNr(InvalidIndex) {} }; AZStd::vector m_bones; /**< The array of bone information used for pre-calculation. */ @@ -155,6 +155,6 @@ namespace EMotionFX * @param nodeIndex The node number to search for. * @result The index inside the mBones member array, which uses the given node. */ - AZ::Outcome FindLocalBoneIndex(uint32 nodeIndex) const; + AZ::Outcome FindLocalBoneIndex(size_t nodeIndex) const; }; } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ChunkProcessors.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ChunkProcessors.cpp index b6b0b091a2..604dfb8bb9 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ChunkProcessors.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ChunkProcessors.cpp @@ -1907,7 +1907,6 @@ namespace EMotionFX const MCore::Endian::EEndianType endianType = importParams.mEndianType; Actor* actor = importParams.mActor; - uint32 i; MCORE_ASSERT(actor); Skeleton* skeleton = actor->GetSkeleton(); @@ -1920,7 +1919,7 @@ namespace EMotionFX const uint32 numAttachmentNodes = attachmentNodesChunk.mNumNodes; // read all node attachment nodes - for (i = 0; i < numAttachmentNodes; ++i) + for (uint32 i = 0; i < numAttachmentNodes; ++i) { // get the attachment node index and endian convert it uint16 nodeNr; @@ -1940,8 +1939,8 @@ namespace EMotionFX { MCore::LogDetailedInfo("- Attachment Nodes (%i):", numAttachmentNodes); - const uint32 numNodes = actor->GetNumNodes(); - for (i = 0; i < numNodes; ++i) + const size_t numNodes = actor->GetNumNodes(); + for (size_t i = 0; i < numNodes; ++i) { // get the current node Node* node = skeleton->GetNode(i); @@ -1949,7 +1948,7 @@ namespace EMotionFX // only log the attachment nodes if (node->GetIsAttachmentNode()) { - MCore::LogDetailedInfo(" + '%s' (%i)", node->GetName(), node->GetNodeIndex()); + MCore::LogDetailedInfo(" + '%s' (%zu)", node->GetName(), node->GetNodeIndex()); } } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/Importer.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/Importer.cpp index 069182883c..e710192afd 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/Importer.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/Importer.cpp @@ -60,10 +60,9 @@ namespace EMotionFX Importer::~Importer() { // remove all chunk processors - const uint32 numProcessors = mChunkProcessors.size(); - for (uint32 i = 0; i < numProcessors; ++i) + for (ChunkProcessor* mChunkProcessor : mChunkProcessors) { - mChunkProcessors[i]->Destroy(); + mChunkProcessor->Destroy(); } } @@ -730,20 +729,11 @@ namespace EMotionFX SharedData* Importer::FindSharedData(AZStd::vector* sharedDataArray, uint32 type) { // for all shared data - const uint32 numSharedData = sharedDataArray->size(); - for (uint32 i = 0; i < numSharedData; ++i) + const auto foundSharedData = AZStd::find_if(begin(*sharedDataArray), end(*sharedDataArray), [type](const SharedData* sharedData) { - SharedData* sharedData = sharedDataArray->at(i); - - // check if it's the type we are searching for - if (sharedData->GetType() == type) - { - return sharedData; - } - } - - // nothing found - return nullptr; + return sharedData->GetType() == type; + }); + return foundSharedData != end(*sharedDataArray) ? *foundSharedData : nullptr; } @@ -764,11 +754,9 @@ namespace EMotionFX mLogDetails = detailLoggingActive; // set the processors logging flag - const int32 numProcessors = mChunkProcessors.size(); - for (int32 i = 0; i < numProcessors; i++) + for (ChunkProcessor* processor : mChunkProcessors) { - ChunkProcessor* processor = mChunkProcessors[i]; - processor->SetLogging((mLoggingActive && detailLoggingActive)); // only enable if logging is also enabled + processor->SetLogging(mLoggingActive && detailLoggingActive); // only enable if logging is also enabled } } @@ -789,10 +777,8 @@ namespace EMotionFX // reset shared objects so that the importer is ready for use again void Importer::ResetSharedData(AZStd::vector& sharedData) { - const int32 numSharedData = sharedData.size(); - for (int32 i = 0; i < numSharedData; i++) + for (SharedData* data : sharedData) { - SharedData* data = sharedData[i]; data->Reset(); data->Destroy(); } @@ -804,20 +790,11 @@ namespace EMotionFX ChunkProcessor* Importer::FindChunk(uint32 chunkID, uint32 version) const { // for all chunk processors - const uint32 numProcessors = mChunkProcessors.size(); - for (uint32 i = 0; i < numProcessors; ++i) + const auto foundProcessor = AZStd::find_if(begin(mChunkProcessors), end(mChunkProcessors), [chunkID, version](const ChunkProcessor* processor) { - ChunkProcessor* processor = mChunkProcessors[i]; - - // if this chunk is the type we are searching for AND it can process our chunk version, return it - if (processor->GetChunkID() == chunkID && processor->GetVersion() == version) - { - return processor; - } - } - - // nothing found - return nullptr; + return processor->GetChunkID() == chunkID && processor->GetVersion() == version; + }); + return foundProcessor != end(mChunkProcessors) ? *foundProcessor : nullptr; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/KeyFrameFinder.h b/Gems/EMotionFX/Code/EMotionFX/Source/KeyFrameFinder.h index 760913ddd4..5d06964a88 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/KeyFrameFinder.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/KeyFrameFinder.h @@ -43,9 +43,9 @@ namespace EMotionFX * @param timeValue The time value you want to calculate a value at. * @param keyTrack The keyframe array to perform the search on. * @param numKeys The number of keyframes stored inside the keyTrack parameter buffer. - * @result The key number, or MCORE_INVALIDINDEX32 when no valid key could be found. + * @result The key number, or InvalidIndex when no valid key could be found. */ - static uint32 FindKey(float timeValue, const KeyFrame* keyTrack, uint32 numKeys); + static size_t FindKey(float timeValue, const KeyFrame* keyTrack, size_t numKeys); }; // include inline code diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/KeyFrameFinder.inl b/Gems/EMotionFX/Code/EMotionFX/Source/KeyFrameFinder.inl index 4e9668638f..bc9b4cadba 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/KeyFrameFinder.inl +++ b/Gems/EMotionFX/Code/EMotionFX/Source/KeyFrameFinder.inl @@ -23,29 +23,29 @@ KeyFrameFinder::~KeyFrameFinder() // returns the keyframe number to use for interpolation template -uint32 KeyFrameFinder::FindKey(float timeValue, const KeyFrame* keyTrack, uint32 numKeys) +size_t KeyFrameFinder::FindKey(float timeValue, const KeyFrame* keyTrack, size_t numKeys) { - // if we haven't got any keys, return MCORE_INVALIDINDEX32, which means no key found + // if we haven't got any keys, return InvalidIndex, which means no key found if (numKeys == 0) { - return MCORE_INVALIDINDEX32; + return InvalidIndex; } - uint32 low = 0; - uint32 high = numKeys - 1; + size_t low = 0; + size_t high = numKeys - 1; float lowValue = keyTrack[low].GetTime(); float highValue = keyTrack[high].GetTime(); // these can go if you're sure the value is going to be valid (between the min and max key's values) if (timeValue < lowValue || timeValue >= highValue) { - return MCORE_INVALIDINDEX32; + return InvalidIndex; } for (;; ) { // calculate the interpolated index - const uint32 mid = low + (int)((timeValue - lowValue) / (highValue - lowValue) * (high - low)); + const size_t mid = low + (int)((timeValue - lowValue) / (highValue - lowValue) * (high - low)); if (keyTrack[mid].GetTime() <= timeValue) { diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/KeyTrackLinearDynamic.h b/Gems/EMotionFX/Code/EMotionFX/Source/KeyTrackLinearDynamic.h index 8c5c56895a..5f8f7b49d0 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/KeyTrackLinearDynamic.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/KeyTrackLinearDynamic.h @@ -46,7 +46,7 @@ namespace EMotionFX /** * @param nrKeys The number of keyframes which the keytrack contains (preallocates this amount of keyframes). */ - KeyTrackLinearDynamic(uint32 nrKeys); + KeyTrackLinearDynamic(size_t nrKeys); static void Reflect(AZ::ReflectContext* context); @@ -54,14 +54,14 @@ namespace EMotionFX * Reserve space for a given number of keys. This pre-allocates data, so that adding keys doesn't always do a reallocation. * @param numKeys The number of keys to reserve space for. This is the absolute number of keys, NOT the number to reserve extra. */ - void Reserve(uint32 numKeys); + void Reserve(size_t numKeys); /** * Calculate the memory usage, in bytes. * @param includeMembers Specifies whether to include member variables of the keytrack class itself or not (default=true). * @result The number of bytes used by this keytrack. */ - uint32 CalcMemoryUsage(bool includeMembers = true) const; + size_t CalcMemoryUsage(bool includeMembers = true) const; /** * Initialize all keyframes in this keytrack. @@ -81,7 +81,7 @@ namespace EMotionFX * @param currentTime The global time, in seconds. This time value has to be between the time value of the startKey and the one after that. * @result The interpolated value. */ - MCORE_INLINE ReturnType Interpolate(uint32 startKey, float currentTime) const; + MCORE_INLINE ReturnType Interpolate(size_t startKey, float currentTime) const; /** * Add a key to the track (at the back). @@ -107,7 +107,7 @@ namespace EMotionFX * recalculated when the key structure has changed. * @param keyNr The keyframe number, must be in range of [0..GetNumKeys()-1]. */ - MCORE_INLINE void RemoveKey(uint32 keyNr); + MCORE_INLINE void RemoveKey(size_t keyNr); /** * Clear all keys. @@ -133,14 +133,14 @@ namespace EMotionFX * @param interpolate Should we interpolate between the keyframes? * @result Returns the value at the specified time. */ - ReturnType GetValueAtTime(float currentTime, uint32* cachedKey = nullptr, uint8* outWasCacheHit = nullptr, bool interpolate = true) const; + ReturnType GetValueAtTime(float currentTime, size_t* cachedKey = nullptr, uint8* outWasCacheHit = nullptr, bool interpolate = true) const; /** * Get a given keyframe. * @param nr The index, so the keyframe number. * @result A pointer to the keyframe. */ - MCORE_INLINE KeyFrame* GetKey(uint32 nr); + MCORE_INLINE KeyFrame* GetKey(size_t nr); /** * Returns the first keyframe. @@ -159,7 +159,7 @@ namespace EMotionFX * @param nr The index, so the keyframe number. * @result A pointer to the keyframe. */ - MCORE_INLINE const KeyFrame* GetKey(uint32 nr) const; + MCORE_INLINE const KeyFrame* GetKey(size_t nr) const; /** * Returns the first keyframe. @@ -190,7 +190,7 @@ namespace EMotionFX * Returns the number of keyframes in this track. * @result The number of currently stored keyframes. */ - MCORE_INLINE uint32 GetNumKeys() const; + MCORE_INLINE size_t GetNumKeys() const; /** * Find a key at a given time. @@ -205,7 +205,7 @@ namespace EMotionFX * @param curTime The time to retreive the key for. * @result Returns the key number or MCORE_INVALIDINDEX32 when not found. */ - MCORE_INLINE uint32 FindKeyNumber(float curTime) const; + MCORE_INLINE size_t FindKeyNumber(float curTime) const; /** * Make the keytrack loopable, by adding a new keyframe at the end of the keytrack. @@ -228,7 +228,7 @@ namespace EMotionFX * @param maxError The maximum allowed error value. The higher you set this value, the more keyframes will be removed. * @result The method returns the number of removed keyframes. */ - uint32 Optimize(float maxError); + size_t Optimize(float maxError); /** * Pre-allocate a given number of keys. @@ -236,7 +236,7 @@ namespace EMotionFX * However, newly created keys will be uninitialized. * @param numKeys The number of keys to allocate. */ - void SetNumKeys(uint32 numKeys); + void SetNumKeys(size_t numKeys); /** * Set the value of a key. @@ -245,7 +245,7 @@ namespace EMotionFX * @param time The time value, in seconds. * @param value The value of the key. */ - MCORE_INLINE void SetKey(uint32 keyNr, float time, const ReturnType& value); + MCORE_INLINE void SetKey(size_t keyNr, float time, const ReturnType& value); /** * Set the storage type value of a key. @@ -254,7 +254,7 @@ namespace EMotionFX * @param time The time value, in seconds. * @param value The storage type value of the key. */ - MCORE_INLINE void SetStorageTypeKey(uint32 keyNr, float time, const StorageType& value); + MCORE_INLINE void SetStorageTypeKey(size_t keyNr, float time, const StorageType& value); protected: AZStd::vector> mKeys; /**< The collection of keys which form the track. */ diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/KeyTrackLinearDynamic.inl b/Gems/EMotionFX/Code/EMotionFX/Source/KeyTrackLinearDynamic.inl index 94abe4d707..806a45b69a 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/KeyTrackLinearDynamic.inl +++ b/Gems/EMotionFX/Code/EMotionFX/Source/KeyTrackLinearDynamic.inl @@ -8,7 +8,7 @@ // extended constructor template -KeyTrackLinearDynamic::KeyTrackLinearDynamic(uint32 nrKeys) +KeyTrackLinearDynamic::KeyTrackLinearDynamic(size_t nrKeys) { SetNumKeys(nrKeys); } @@ -53,17 +53,16 @@ void KeyTrackLinearDynamic::Init() // if it's not equal to zero, we have to correct it (and all other keys as well) if (minTime > 0.0f) { - const size_t numKeys = mKeys.size(); - for (uint32 i = 0; i < numKeys; ++i) + for (KeyFrame& key : mKeys) { - mKeys[i].SetTime(mKeys[i].GetTime() - minTime); + key.SetTime(key.GetTime() - minTime); } } } template -MCORE_INLINE KeyFrame* KeyTrackLinearDynamic::GetKey(uint32 nr) +MCORE_INLINE KeyFrame* KeyTrackLinearDynamic::GetKey(size_t nr) { MCORE_ASSERT(nr < mKeys.size()); return &mKeys[nr]; @@ -73,20 +72,20 @@ MCORE_INLINE KeyFrame* KeyTrackLinearDynamic MCORE_INLINE KeyFrame* KeyTrackLinearDynamic::GetFirstKey() { - return (mKeys.size() > 0) ? &mKeys[0] : nullptr; + return !mKeys.empty() ? &mKeys[0] : nullptr; } template MCORE_INLINE KeyFrame* KeyTrackLinearDynamic::GetLastKey() { - return (mKeys.size() > 0) ? &mKeys.back() : nullptr; + return !mKeys.empty() ? &mKeys.back() : nullptr; } template -MCORE_INLINE const KeyFrame* KeyTrackLinearDynamic::GetKey(uint32 nr) const +MCORE_INLINE const KeyFrame* KeyTrackLinearDynamic::GetKey(size_t nr) const { MCORE_ASSERT(nr < mKeys.size()); return &mKeys[nr]; @@ -96,14 +95,14 @@ MCORE_INLINE const KeyFrame* KeyTrackLinearDynamic MCORE_INLINE const KeyFrame* KeyTrackLinearDynamic::GetFirstKey() const { - return (mKeys.size() > 0) ? &mKeys[0] : nullptr; + return !mKeys.empty() ? &mKeys[0] : nullptr; } template MCORE_INLINE const KeyFrame* KeyTrackLinearDynamic::GetLastKey() const { - return (mKeys.size() > 0) ? &mKeys.back() : nullptr; + return !mKeys.empty() ? &mKeys.back() : nullptr; } @@ -124,9 +123,9 @@ MCORE_INLINE float KeyTrackLinearDynamic::GetLastTime() template -MCORE_INLINE uint32 KeyTrackLinearDynamic::GetNumKeys() const +MCORE_INLINE size_t KeyTrackLinearDynamic::GetNumKeys() const { - return static_cast(mKeys.size()); + return mKeys.size(); } @@ -134,7 +133,7 @@ template MCORE_INLINE void KeyTrackLinearDynamic::AddKey(float time, const ReturnType& value, bool smartPreAlloc) { #ifdef MCORE_DEBUG - if (mKeys.size() > 0) + if (!mKeys.empty()) { MCORE_ASSERT(time >= mKeys.back().GetTime()); } @@ -154,7 +153,7 @@ MCORE_INLINE void KeyTrackLinearDynamic::AddKey(float t // find a key at a given time template -MCORE_INLINE uint32 KeyTrackLinearDynamic::FindKeyNumber(float curTime) const +MCORE_INLINE size_t KeyTrackLinearDynamic::FindKeyNumber(float curTime) const { return KeyFrameFinder::FindKey(curTime, &mKeys.front(), static_cast(mKeys.size())); } @@ -165,36 +164,36 @@ template MCORE_INLINE KeyFrame* KeyTrackLinearDynamic::FindKey(float curTime) const { // find the key number - const uint32 keyNumber = KeyFrameFinder::FindKey(curTime, &mKeys.front(), mKeys.size()); + const size_t keyNumber = KeyFrameFinder::FindKey(curTime, &mKeys.front(), mKeys.size()); // if no key was found - return (keyNumber != MCORE_INVALIDINDEX32) ? &mKeys[keyNumber] : nullptr; + return (keyNumber != InvalidIndex) ? &mKeys[keyNumber] : nullptr; } // returns the interpolated value at a given time template -ReturnType KeyTrackLinearDynamic::GetValueAtTime(float currentTime, uint32* cachedKey, uint8* outWasCacheHit, bool interpolate) const +ReturnType KeyTrackLinearDynamic::GetValueAtTime(float currentTime, size_t* cachedKey, uint8* outWasCacheHit, bool interpolate) const { MCORE_ASSERT(currentTime >= 0.0); - MCORE_ASSERT(mKeys.size() > 0); + MCORE_ASSERT(!mKeys.empty()); // make a local copy of the cached key value - uint32 localCachedKey = (cachedKey) ? *cachedKey : MCORE_INVALIDINDEX32; + size_t localCachedKey = (cachedKey) ? *cachedKey : InvalidIndex; // find the first key to start interpolating from (between this one and the next) - uint32 keyNumber = MCORE_INVALIDINDEX32; + size_t keyNumber = InvalidIndex; // prevent searching in the set of keyframes when a cached key is available // of course we need to check first if the cached key is actually still valid or not - if (localCachedKey == MCORE_INVALIDINDEX32) // no cached key has been set, so simply perform a search + if (localCachedKey == InvalidIndex) // no cached key has been set, so simply perform a search { if (outWasCacheHit) { *outWasCacheHit = 0; } - keyNumber = KeyFrameFinder::FindKey(currentTime, &mKeys.front(), static_cast(mKeys.size())); + keyNumber = KeyFrameFinder::FindKey(currentTime, &mKeys.front(), mKeys.size()); if (cachedKey) { @@ -208,7 +207,7 @@ ReturnType KeyTrackLinearDynamic::GetValueAtTime(float { if (mKeys.size() > 2) { - localCachedKey = static_cast(mKeys.size()) - 3; + localCachedKey = mKeys.size() - 3; } else { @@ -243,7 +242,7 @@ ReturnType KeyTrackLinearDynamic::GetValueAtTime(float *outWasCacheHit = 0; } - keyNumber = KeyFrameFinder::FindKey(currentTime, &mKeys.front(), static_cast(mKeys.size())); + keyNumber = KeyFrameFinder::FindKey(currentTime, &mKeys.front(), mKeys.size()); if (cachedKey) { @@ -254,7 +253,7 @@ ReturnType KeyTrackLinearDynamic::GetValueAtTime(float } // if no key could be found - if (keyNumber == MCORE_INVALIDINDEX32) + if (keyNumber == InvalidIndex) { // if there are no keys at all, simply return an empty object if (mKeys.size() == 0) @@ -287,7 +286,7 @@ ReturnType KeyTrackLinearDynamic::GetValueAtTime(float // perform interpolation template -MCORE_INLINE ReturnType KeyTrackLinearDynamic::Interpolate(uint32 startKey, float currentTime) const +MCORE_INLINE ReturnType KeyTrackLinearDynamic::Interpolate(size_t startKey, float currentTime) const { // get the keys to interpolate between const KeyFrame& firstKey = mKeys[startKey]; @@ -303,7 +302,7 @@ MCORE_INLINE ReturnType KeyTrackLinearDynamic::Interpol template <> -MCORE_INLINE AZ::Quaternion KeyTrackLinearDynamic::Interpolate(uint32 startKey, float currentTime) const +MCORE_INLINE AZ::Quaternion KeyTrackLinearDynamic::Interpolate(size_t startKey, float currentTime) const { // get the keys to interpolate between const KeyFrame& firstKey = mKeys[startKey]; @@ -318,7 +317,7 @@ MCORE_INLINE AZ::Quaternion KeyTrackLinearDynamic -MCORE_INLINE AZ::Quaternion KeyTrackLinearDynamic::Interpolate(uint32 startKey, float currentTime) const +MCORE_INLINE AZ::Quaternion KeyTrackLinearDynamic::Interpolate(size_t startKey, float currentTime) const { // get the keys to interpolate between const KeyFrame& firstKey = mKeys[startKey]; @@ -341,7 +340,7 @@ void KeyTrackLinearDynamic::AddKeySorted(float time, co { if (mKeys.capacity() == mKeys.size()) { - const uint32 numToReserve = static_cast(mKeys.size() / 4); + const size_t numToReserve = mKeys.size() / 4; mKeys.reserve(mKeys.capacity() + numToReserve); } } @@ -371,13 +370,13 @@ void KeyTrackLinearDynamic::AddKeySorted(float time, co } // quickly find the location to insert, and insert it - const uint32 place = KeyFrameFinder::FindKey(keyTime, &mKeys.front(), static_cast(mKeys.size())); + const size_t place = KeyFrameFinder::FindKey(keyTime, &mKeys.front(), mKeys.size()); mKeys.insert(mKeys.begin() + place + 1, KeyFrame(time, value)); } template -MCORE_INLINE void KeyTrackLinearDynamic::RemoveKey(uint32 keyNr) +MCORE_INLINE void KeyTrackLinearDynamic::RemoveKey(size_t keyNr) { mKeys.erase(AZStd::next(mKeys.begin(), keyNr)); } @@ -404,7 +403,7 @@ void KeyTrackLinearDynamic::MakeLoopable(float fadeTime // optimize the keytrack template -uint32 KeyTrackLinearDynamic::Optimize(float maxError) +size_t KeyTrackLinearDynamic::Optimize(float maxError) { // if there aren't at least two keys, return, because we never remove the first and last key frames // and we'd need at least two keyframes to interpolate between @@ -419,8 +418,8 @@ uint32 KeyTrackLinearDynamic::Optimize(float maxError) keyTrackCopy.Init(); // while we want to continue optimizing - uint32 i = 1; - uint32 numRemoved = 0; // the number of removed keys + size_t i = 1; + size_t numRemoved = 0; // the number of removed keys do { // get the time of the current keyframe (starting from the second towards the last one) @@ -459,7 +458,7 @@ uint32 KeyTrackLinearDynamic::Optimize(float maxError) // pre-alloc keys template -void KeyTrackLinearDynamic::SetNumKeys(uint32 numKeys) +void KeyTrackLinearDynamic::SetNumKeys(size_t numKeys) { // resize the array of keys mKeys.resize(numKeys); @@ -468,7 +467,7 @@ void KeyTrackLinearDynamic::SetNumKeys(uint32 numKeys) // set a given key template -MCORE_INLINE void KeyTrackLinearDynamic::SetKey(uint32 keyNr, float time, const ReturnType& value) +MCORE_INLINE void KeyTrackLinearDynamic::SetKey(size_t keyNr, float time, const ReturnType& value) { // adjust the value and time of the key mKeys[keyNr].SetValue(value); @@ -478,7 +477,7 @@ MCORE_INLINE void KeyTrackLinearDynamic::SetKey(uint32 // set a given key template -MCORE_INLINE void KeyTrackLinearDynamic::SetStorageTypeKey(uint32 keyNr, float time, const StorageType& value) +MCORE_INLINE void KeyTrackLinearDynamic::SetStorageTypeKey(size_t keyNr, float time, const StorageType& value) { // adjust the value and time of the key mKeys[keyNr].SetStorageTypeValue(value); @@ -490,31 +489,17 @@ MCORE_INLINE void KeyTrackLinearDynamic::SetStorageType template MCORE_INLINE bool KeyTrackLinearDynamic::CheckIfIsAnimated(const ReturnType& initialPose, float maxError) const { - // empty keytracks are never animated - if (mKeys.size() == 0) + return !mKeys.empty() && AZStd::any_of(begin(mKeys), end(mKeys), [&initialPose, maxError](const auto& key) { - return false; - } - - // get the number of keyframes and iterate through them - const uint32 numKeyFrames = GetNumKeys(); - for (uint32 i = 0; i < numKeyFrames; ++i) - { - // if the sampled value is not within the given maximum distance/error of the initial pose, it means we have an animated track - if (MCore::Compare::CheckIfIsClose(initialPose, GetKey(i)->GetValue(), maxError) == false) - { - return true; - } - } - - return false; + return !MCore::Compare::CheckIfIsClose(initialPose, key.GetValue(), maxError); + }); } // reserve memory for keys template -MCORE_INLINE void KeyTrackLinearDynamic::Reserve(uint32 numKeys) +MCORE_INLINE void KeyTrackLinearDynamic::Reserve(size_t numKeys) { mKeys.reserve(numKeys); } @@ -522,7 +507,7 @@ MCORE_INLINE void KeyTrackLinearDynamic::Reserve(uint32 // calculate memory usage template -uint32 KeyTrackLinearDynamic::CalcMemoryUsage(bool includeMembers) const +size_t KeyTrackLinearDynamic::CalcMemoryUsage([[maybe_unused]] bool includeMembers) const { return 0; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.cpp index c86cc66b61..d946344622 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.cpp @@ -256,7 +256,7 @@ namespace EMotionFX { // Atom stores the skin indices as uint16, but the buffer itself is a buffer of uint32 with two id's per element size_t influenceCount = elementCountInBytes / sizeof(AZ::u16); - maxSkinInfluences = static_cast(influenceCount / modelVertexCount); + maxSkinInfluences = aznumeric_caster(influenceCount / modelVertexCount); AZ_Assert(maxSkinInfluences > 0 && maxSkinInfluences < 100, "Expect max skin influences in a reasonable value range."); AZ_Assert(influenceCount % modelVertexCount == 0, "Expect an equal number of influences for each vertex."); AZ_Assert(bufferAssetViewDescriptor.m_elementSize == 4, "Expect skin joint indices to be stored in a raw 32-bit per element buffer"); @@ -269,7 +269,7 @@ namespace EMotionFX { // Atom stores joint weights as float (range 0 - 1) size_t influenceCount = elementCountInBytes / sizeof(float); - maxSkinInfluences = static_cast(influenceCount / modelVertexCount); + maxSkinInfluences = aznumeric_caster(influenceCount / modelVertexCount); AZ_Assert(maxSkinInfluences > 0 && maxSkinInfluences < 100, "Expect max skin influences in a reasonable value range."); skinWeights = static_cast(bufferData) + bufferAssetViewDescriptor.m_elementOffset; } @@ -278,7 +278,7 @@ namespace EMotionFX // Add the original vertex layer VertexAttributeLayerAbstractData* originalVertexData = VertexAttributeLayerAbstractData::Create(modelVertexCount, Mesh::ATTRIB_ORGVTXNUMBERS, sizeof(AZ::u32), false); AZ::u32* originalVertexDataRaw = static_cast(originalVertexData->GetData()); - for (size_t i = 0; i < modelVertexCount; ++i) + for (AZ::u32 i = 0; i < modelVertexCount; ++i) { originalVertexDataRaw[i] = static_cast(i); } @@ -374,10 +374,9 @@ namespace EMotionFX // copy all original data over the output data void Mesh::ResetToOriginalData() { - const uint32 numLayers = mVertexAttributes.size(); - for (uint32 i = 0; i < numLayers; ++i) + for (VertexAttributeLayer* mVertexAttribute : mVertexAttributes) { - mVertexAttributes[i]->ResetToOriginalData(); + mVertexAttribute->ResetToOriginalData(); } } @@ -392,10 +391,9 @@ namespace EMotionFX RemoveAllVertexAttributeLayers(); // get rid of all sub meshes - const uint32 numSubMeshes = mSubMeshes.size(); - for (uint32 i = 0; i < numSubMeshes; ++i) + for (SubMesh* subMesh : mSubMeshes) { - mSubMeshes[i]->Destroy(); + subMesh->Destroy(); } mSubMeshes.clear(); @@ -495,15 +493,14 @@ namespace EMotionFX } // calculate the number of tangent layers that are already available - uint32 i, f; AZ::Vector4* tangents = nullptr; AZ::Vector4* orgTangents = nullptr; AZ::Vector3* bitangents = nullptr; AZ::Vector3* orgBitangents = nullptr; - const uint32 numTangentLayers = CalcNumAttributeLayers(Mesh::ATTRIB_TANGENTS); + const size_t numTangentLayers = CalcNumAttributeLayers(Mesh::ATTRIB_TANGENTS); // make sure we have tangent data allocated for all uv layers before the given one - for (i = numTangentLayers; i <= uvSet; ++i) + for (size_t i = numTangentLayers; i <= uvSet; ++i) { // add a new tangent layer AddVertexAttributeLayer(VertexAttributeLayerAbstractData::Create(mNumVertices, Mesh::ATTRIB_TANGENTS, sizeof(AZ::Vector4), true)); @@ -548,7 +545,7 @@ namespace EMotionFX AZ::Vector3 curBitangent; // calculate for every vertex the tangent and bitangent - for (i = 0; i < mNumVertices; ++i) + for (uint32 i = 0; i < mNumVertices; ++i) { orgTangents[i] = AZ::Vector4::CreateZero(); tangents[i] = AZ::Vector4::CreateZero(); @@ -564,7 +561,7 @@ namespace EMotionFX uint32 polyStartIndex = 0; uint32 indexA, indexB, indexC; const uint32 numPolygons = GetNumPolygons(); - for (f = 0; f < numPolygons; f++) + for (uint32 f = 0; f < numPolygons; f++) { const uint32 numPolyVerts = vertCounts[f]; @@ -572,7 +569,7 @@ namespace EMotionFX // triangle has got 3 polygon vertices -> 1 triangle // quad has got 4 polygon vertices -> 2 triangles // pentagon has got 5 polygon vertices -> 3 triangles - for (i = 2; i < numPolyVerts; i++) + for (uint32 i = 2; i < numPolyVerts; i++) { indexA = indices[polyStartIndex]; indexB = indices[polyStartIndex + i]; @@ -604,7 +601,7 @@ namespace EMotionFX } // calculate the per vertex tangents now, fixing up orthogonality and handling mirroring of the bitangent - for (i = 0; i < mNumVertices; ++i) + for (uint32 i = 0; i < mNumVertices; ++i) { // get the normal AZ::Vector3 normal(normals[i]); @@ -801,7 +798,7 @@ namespace EMotionFX // remove a given submesh - void Mesh::RemoveSubMesh(uint32 nr, bool delFromMem) + void Mesh::RemoveSubMesh(size_t nr, bool delFromMem) { SubMesh* subMesh = mSubMeshes[nr]; mSubMeshes.erase(AZStd::next(begin(mSubMeshes), nr)); @@ -813,22 +810,21 @@ namespace EMotionFX // insert a given submesh - void Mesh::InsertSubMesh(uint32 insertIndex, SubMesh* subMesh) + void Mesh::InsertSubMesh(size_t insertIndex, SubMesh* subMesh) { mSubMeshes.emplace(AZStd::next(begin(mSubMeshes), insertIndex), subMesh); } // count the given type of vertex attribute layers - uint32 Mesh::CalcNumAttributeLayers(uint32 type) const + size_t Mesh::CalcNumAttributeLayers(uint32 type) const { - uint32 numLayers = 0; + size_t numLayers = 0; // check the types of all vertex attribute layers - const uint32 numAttributes = mVertexAttributes.size(); - for (uint32 i = 0; i < numAttributes; ++i) + for (auto* vertexAttribute : mVertexAttributes) { - if (mVertexAttributes[i]->GetType() == type) + if (vertexAttribute->GetType() == type) { numLayers++; } @@ -839,7 +835,7 @@ namespace EMotionFX // get the number of UV layers - uint32 Mesh::CalcNumUVLayers() const + size_t Mesh::CalcNumUVLayers() const { return CalcNumAttributeLayers(Mesh::ATTRIB_UVCOORDS); } @@ -866,36 +862,21 @@ namespace EMotionFX } - uint32 Mesh::FindSharedVertexAttributeLayerNumber(uint32 layerTypeID, uint32 occurrence) const + size_t Mesh::FindSharedVertexAttributeLayerNumber(uint32 layerTypeID, size_t occurrence) const { - uint32 layerCounter = 0; - - // check all vertex attributes of our first vertex, and find where the specific attribute is - const uint32 numLayers = mSharedVertexAttributes.size(); - for (uint32 i = 0; i < numLayers; ++i) + const auto foundLayer = AZStd::find_if(begin(mSharedVertexAttributes), end(mSharedVertexAttributes), [layerTypeID, occurrence](const VertexAttributeLayer* layer) mutable { - VertexAttributeLayer* layer = mSharedVertexAttributes[i]; - if (layer->GetType() == layerTypeID) - { - if (occurrence == layerCounter) - { - return i; - } - - layerCounter++; - } - } - - // not found - return MCORE_INVALIDINDEX32; + return layer->GetType() == layerTypeID && occurrence-- == 0; + }); + return foundLayer != end(mSharedVertexAttributes) ? AZStd::distance(begin(mSharedVertexAttributes), foundLayer) : InvalidIndex; } // find the vertex attribute layer and return a pointer - VertexAttributeLayer* Mesh::FindSharedVertexAttributeLayer(uint32 layerTypeID, uint32 occurence) const + VertexAttributeLayer* Mesh::FindSharedVertexAttributeLayer(uint32 layerTypeID, size_t occurence) const { - uint32 layerNr = FindSharedVertexAttributeLayerNumber(layerTypeID, occurence); - if (layerNr == MCORE_INVALIDINDEX32) + size_t layerNr = FindSharedVertexAttributeLayerNumber(layerTypeID, occurence); + if (layerNr == InvalidIndex) { return nullptr; } @@ -917,7 +898,7 @@ namespace EMotionFX // remove a layer by its index - void Mesh::RemoveSharedVertexAttributeLayer(uint32 layerNr) + void Mesh::RemoveSharedVertexAttributeLayer(size_t layerNr) { MCORE_ASSERT(layerNr < mSharedVertexAttributes.size()); mSharedVertexAttributes[layerNr]->Destroy(); @@ -931,7 +912,7 @@ namespace EMotionFX } - VertexAttributeLayer* Mesh::GetVertexAttributeLayer(uint32 layerNr) + VertexAttributeLayer* Mesh::GetVertexAttributeLayer(size_t layerNr) { MCORE_ASSERT(layerNr < mVertexAttributes.size()); return mVertexAttributes[layerNr]; @@ -946,58 +927,33 @@ namespace EMotionFX // find the layer number - uint32 Mesh::FindVertexAttributeLayerNumber(uint32 layerTypeID, uint32 occurrence) const + size_t Mesh::FindVertexAttributeLayerNumber(uint32 layerTypeID, size_t occurrence) const { - uint32 layerCounter = 0; - - // check all vertex attributes of our first vertex, and find where the specific attribute is - const uint32 numLayers = mVertexAttributes.size(); - for (uint32 i = 0; i < numLayers; ++i) + const auto foundLayer = AZStd::find_if(begin(mVertexAttributes), end(mVertexAttributes), [layerTypeID, occurrence](const VertexAttributeLayer* layer) mutable { - VertexAttributeLayer* layer = mVertexAttributes[i]; - if (layer->GetType() == layerTypeID) - { - if (occurrence == layerCounter) - { - return i; - } - - layerCounter++; - } - } - - // not found - return MCORE_INVALIDINDEX32; + return layer->GetType() == layerTypeID && occurrence-- == 0; + }); + return foundLayer != end(mVertexAttributes) ? AZStd::distance(begin(mVertexAttributes), foundLayer) : InvalidIndex; } // find the layer number - uint32 Mesh::FindVertexAttributeLayerNumberByName(uint32 layerTypeID, const char* name) const + size_t Mesh::FindVertexAttributeLayerNumberByName(uint32 layerTypeID, const char* name) const { - // check all vertex attributes of our first vertex, and find where the specific attribute is - const uint32 numLayers = mVertexAttributes.size(); - for (uint32 i = 0; i < numLayers; ++i) + const auto foundLayer = AZStd::find_if(begin(mVertexAttributes), end(mVertexAttributes), [layerTypeID, name](const VertexAttributeLayer* layer) { - VertexAttributeLayer* layer = mVertexAttributes[i]; - if (layer->GetType() == layerTypeID) - { - if (layer->GetNameString() == name) - { - return i; - } - } - } - - return MCORE_INVALIDINDEX32; + return layer->GetType() == layerTypeID && layer->GetNameString() == name; + }); + return foundLayer != end(mVertexAttributes) ? AZStd::distance(begin(mVertexAttributes), foundLayer) : InvalidIndex; } // find the vertex attribute layer and return a pointer - VertexAttributeLayer* Mesh::FindVertexAttributeLayer(uint32 layerTypeID, uint32 occurence) const + VertexAttributeLayer* Mesh::FindVertexAttributeLayer(uint32 layerTypeID, size_t occurence) const { - const uint32 layerNr = FindVertexAttributeLayerNumber(layerTypeID, occurence); - if (layerNr == MCORE_INVALIDINDEX32) + const size_t layerNr = FindVertexAttributeLayerNumber(layerTypeID, occurence); + if (layerNr == InvalidIndex) { return nullptr; } @@ -1009,8 +965,8 @@ namespace EMotionFX // find the vertex attribute layer and return a pointer VertexAttributeLayer* Mesh::FindVertexAttributeLayerByName(uint32 layerTypeID, const char* name) const { - const uint32 layerNr = FindVertexAttributeLayerNumberByName(layerTypeID, name); - if (layerNr == MCORE_INVALIDINDEX32) + const size_t layerNr = FindVertexAttributeLayerNumberByName(layerTypeID, name); + if (layerNr == InvalidIndex) { return nullptr; } @@ -1029,7 +985,7 @@ namespace EMotionFX } - void Mesh::RemoveVertexAttributeLayer(uint32 layerNr) + void Mesh::RemoveVertexAttributeLayer(size_t layerNr) { MCORE_ASSERT(layerNr < mVertexAttributes.size()); mVertexAttributes[layerNr]->Destroy(); @@ -1049,26 +1005,25 @@ namespace EMotionFX MCore::MemCopy(clone->mPolyVertexCounts, mPolyVertexCounts, sizeof(uint8) * mNumPolygons); // copy the submesh data - uint32 i; - const uint32 numSubMeshes = mSubMeshes.size(); + const size_t numSubMeshes = mSubMeshes.size(); clone->mSubMeshes.resize(numSubMeshes); - for (i = 0; i < numSubMeshes; ++i) + for (size_t i = 0; i < numSubMeshes; ++i) { clone->mSubMeshes[i] = mSubMeshes[i]->Clone(clone); } // clone the shared vertex attributes - const uint32 numSharedAttributes = mSharedVertexAttributes.size(); + const size_t numSharedAttributes = mSharedVertexAttributes.size(); clone->mSharedVertexAttributes.resize(numSharedAttributes); - for (i = 0; i < numSharedAttributes; ++i) + for (size_t i = 0; i < numSharedAttributes; ++i) { clone->mSharedVertexAttributes[i] = mSharedVertexAttributes[i]->Clone(); } // clone the non-shared vertex attributes - const uint32 numAttributes = mVertexAttributes.size(); + const size_t numAttributes = mVertexAttributes.size(); clone->mVertexAttributes.resize(numAttributes); - for (i = 0; i < numAttributes; ++i) + for (size_t i = 0; i < numAttributes; ++i) { clone->mVertexAttributes[i] = mVertexAttributes[i]->Clone(); } @@ -1091,92 +1046,13 @@ namespace EMotionFX } // swap all vertex attribute layers - const uint32 numLayers = mVertexAttributes.size(); - for (uint32 i = 0; i < numLayers; ++i) + const size_t numLayers = mVertexAttributes.size(); + for (size_t i = 0; i < numLayers; ++i) { mVertexAttributes[i]->SwapAttributes(vertexA, vertexB); } } - /* - // remove indexed null triangles (triangles that use 2 or 3 of the same vertices, so which are invisible) - uint32 Mesh::RemoveIndexedNullTriangles(bool removeEmptySubMeshes) - { - uint32 numRemoved = 0; - uint32 i; - - // for all triangles - uint32 numIndices = mNumIndices; - uint32 offset = 0; - for (i=0; i 0) - MCore::MemMove(((uint8*)mIndices + (offset * sizeof(uint32))), ((uint8*)mIndices + (offset+3)*sizeof(uint32)), numBytesToMove); - - numRemoved++; - numIndices -= 3; - - // adjust all submesh start index offsets changed - //const uint32 numSubMeshes = mSubMeshes.GetLength(); - for (uint32 s=0; sGetStartIndex() <= offset && mSubMeshes[s+1]->GetStartIndex() > offset) - subMesh->SetNumIndices( subMesh->GetNumIndices() - 3 ); - } - else - { - if (subMesh->GetStartIndex() <= offset) - subMesh->SetNumIndices( subMesh->GetNumIndices() - 3 ); - } - - // now find out if we need to adjust the index offset of the submesh - if (subMesh->GetStartIndex() >= offset) - { - if (subMesh->GetStartIndex() != offset) - subMesh->SetStartIndex( subMesh->GetStartIndex() - 3 ); - } - - - // remove the submesh if it's empty - if (subMesh->GetNumIndices() == 0 && removeEmptySubMeshes) - mSubMeshes.Remove(s); - else - s++; - - } - } // if we gotta remove - else - offset += 3; - } - - // reallocate the array, if we removed anything - if (numIndices != mNumIndices) - mIndices = (uint32*)MCore::AlignedRealloc(mIndices, sizeof(uint32) * numIndices, mNumIndices*sizeof(uint32), 32, EMFX_MEMCATEGORY_GEOMETRY_MESHES, Mesh::MEMORYBLOCK_ID); - - // update the number of indices - MCORE_ASSERT(numRemoved == (mNumIndices - numIndices) / 3); - mNumIndices = numIndices; - - // return the number of removed triangles - return numRemoved; - } - */ - // remove vertex data from the mesh void Mesh::RemoveVertices(uint32 startVertexNr, uint32 endVertexNr, bool changeIndexBuffer, bool removeEmptySubMeshes) { @@ -1201,8 +1077,8 @@ namespace EMotionFX mNumVertices -= numVertsToRemove; // remove the attributes from the vertex attribute layers - const uint32 numLayers = GetNumVertexAttributeLayers(); - for (uint32 i = 0; i < numLayers; ++i) + const size_t numLayers = GetNumVertexAttributeLayers(); + for (size_t i = 0; i < numLayers; ++i) { GetVertexAttributeLayer(i)->RemoveAttributes(startVertexNr, endVertexNr); } @@ -1215,7 +1091,7 @@ namespace EMotionFX for (uint32 w = 0; w < numVertsToRemove; ++w) { // adjust all submesh start index offsets changed - for (uint32 s = 0; s < mSubMeshes.size();) + for (size_t s = 0; s < mSubMeshes.size();) { SubMesh* subMesh = mSubMeshes[s]; @@ -1264,12 +1140,12 @@ namespace EMotionFX // remove empty submeshes - uint32 Mesh::RemoveEmptySubMeshes(bool onlyRemoveOnZeroVertsAndTriangles) + size_t Mesh::RemoveEmptySubMeshes(bool onlyRemoveOnZeroVertsAndTriangles) { - uint32 numRemoved = 0; + size_t numRemoved = 0; // for all the submeshes - for (uint32 i = 0; i < mSubMeshes.size();) + for (size_t i = 0; i < mSubMeshes.size();) { SubMesh* subMesh = mSubMeshes[i]; @@ -1306,7 +1182,7 @@ namespace EMotionFX // find vertex data - void* Mesh::FindVertexData(uint32 layerID, uint32 occurrence) const + void* Mesh::FindVertexData(uint32 layerID, size_t occurrence) const { VertexAttributeLayer* layer = FindVertexAttributeLayer(layerID, occurrence); if (layer) @@ -1333,7 +1209,7 @@ namespace EMotionFX // find original vertex data - void* Mesh::FindOriginalVertexData(uint32 layerID, uint32 occurrence) const + void* Mesh::FindOriginalVertexData(uint32 layerID, size_t occurrence) const { VertexAttributeLayer* layer = FindVertexAttributeLayer(layerID, occurrence); if (layer) @@ -1518,8 +1394,6 @@ namespace EMotionFX // log debugging information void Mesh::Log() { - uint32 i; - // get all current data // uint32* indices = GetIndices(); // never returns nullptr //uint32* orgVerts = (uint32*) FindVertexData( Mesh::ATTRIB_ORGVTXNUMBERS ); // never returns nullptr @@ -1556,8 +1430,8 @@ namespace EMotionFX LogDebug(" + Position: %f %f %f, Normal: %f %f %f", positions[i].x, positions[i].y, positions[i].z, normals[i].x, normals[i].y, normals[i].z); */ // iterate through all of its submeshes - const uint32 numSubMeshes = GetNumSubMeshes(); - for (uint32 s = 0; s < numSubMeshes; ++s) + const size_t numSubMeshes = GetNumSubMeshes(); + for (size_t s = 0; s < numSubMeshes; ++s) { // get the current submesh SubMesh* subMesh = GetSubMesh(s); @@ -1589,11 +1463,11 @@ namespace EMotionFX // output the bones used by this submesh MCore::LogDebug(" - Bone list:"); - const uint32 numBones = subMesh->GetNumBones(); - for (i = 0; i < numBones; ++i) + const size_t numBones = subMesh->GetNumBones(); + for (size_t j = 0; j < numBones; ++j) { - const uint32 nodeNr = subMesh->GetBone(i); - MCore::LogDebug(" + NodeNr %d", nodeNr); + const size_t nodeNr = subMesh->GetBone(j); + MCore::LogDebug(" + NodeNr %zu", nodeNr); } } } @@ -1627,7 +1501,7 @@ namespace EMotionFX // in that case use CPU skinning Mesh* mesh = actor->GetMesh(lodLevel, nodeIndex); Node* node = actor->GetSkeleton()->GetNode(nodeIndex); - uint32 meshMaxInfluences = mesh->CalcMaxNumInfluences(); + size_t meshMaxInfluences = mesh->CalcMaxNumInfluences(); if (meshMaxInfluences > maxInfluences) { MCore::LogWarning("*** PERFORMANCE WARNING *** Mesh for node '%s' in geometry LOD %d uses more than %d (%d) bones. Forcing CPU deforms for this mesh.", node->GetName(), lodLevel, maxInfluences, meshMaxInfluences); @@ -1636,8 +1510,8 @@ namespace EMotionFX // check if there is any submesh with more than the given number of bones, which would mean we cannot skin on the GPU // then force CPU skinning as well - const uint32 numSubMeshes = mesh->GetNumSubMeshes(); - for (uint32 i = 0; i < numSubMeshes; ++i) + const size_t numSubMeshes = mesh->GetNumSubMeshes(); + for (size_t i = 0; i < numSubMeshes; ++i) { if (mesh->GetSubMesh(i)->GetNumBones() > maxBonesPerSubMesh) { @@ -1959,18 +1833,14 @@ namespace EMotionFX // scale all positional data void Mesh::Scale(float scaleFactor) { - // all unique layers - const uint32 numLayers = GetNumVertexAttributeLayers(); - for (uint32 i = 0; i < numLayers; ++i) + for (VertexAttributeLayer* layer : mVertexAttributes) { - GetVertexAttributeLayer(i)->Scale(scaleFactor); + layer->Scale(scaleFactor); } - // scale all shared layers - const uint32 numSharedLayers = GetNumSharedVertexAttributeLayers(); - for (uint32 i = 0; i < numSharedLayers; ++i) + for (VertexAttributeLayer* layer : mSharedVertexAttributes) { - GetSharedVertexAttributeLayer(i)->Scale(scaleFactor); + layer->Scale(scaleFactor); } // scale the positional data @@ -1987,97 +1857,67 @@ namespace EMotionFX // find by name - uint32 Mesh::FindVertexAttributeLayerIndexByName(const char* name) const + size_t Mesh::FindVertexAttributeLayerIndexByName(const char* name) const { - const uint32 numLayers = mVertexAttributes.size(); - for (uint32 i = 0; i < numLayers; ++i) + const auto foundLayer = AZStd::find_if(begin(mVertexAttributes), end(mVertexAttributes), [name](const VertexAttributeLayer* layer) { - if (mVertexAttributes[i]->GetNameString() == name) - { - return i; - } - } - - return MCORE_INVALIDINDEX32; + return layer->GetNameString() == name; + }); + return foundLayer != end(mVertexAttributes) ? AZStd::distance(begin(mVertexAttributes), foundLayer) : InvalidIndex; } // find by name as string - uint32 Mesh::FindVertexAttributeLayerIndexByNameString(const AZStd::string& name) const + size_t Mesh::FindVertexAttributeLayerIndexByNameString(const AZStd::string& name) const { - const uint32 numLayers = mVertexAttributes.size(); - for (uint32 i = 0; i < numLayers; ++i) + const auto foundLayer = AZStd::find_if(begin(mVertexAttributes), end(mVertexAttributes), [name](const VertexAttributeLayer* layer) { - if (mVertexAttributes[i]->GetNameString() == name) - { - return i; - } - } - - return MCORE_INVALIDINDEX32; + return layer->GetNameString() == name; + }); + return foundLayer != end(mVertexAttributes) ? AZStd::distance(begin(mVertexAttributes), foundLayer) : InvalidIndex; } // find by name ID - uint32 Mesh::FindVertexAttributeLayerIndexByNameID(uint32 nameID) const + size_t Mesh::FindVertexAttributeLayerIndexByNameID(uint32 nameID) const { - const uint32 numLayers = mVertexAttributes.size(); - for (uint32 i = 0; i < numLayers; ++i) + const auto foundLayer = AZStd::find_if(begin(mVertexAttributes), end(mVertexAttributes), [nameID](const VertexAttributeLayer* layer) { - if (mVertexAttributes[i]->GetNameID() == nameID) - { - return i; - } - } - - return MCORE_INVALIDINDEX32; + return layer->GetNameID() == nameID; + }); + return foundLayer != end(mVertexAttributes) ? AZStd::distance(begin(mVertexAttributes), foundLayer) : InvalidIndex; } // find by name - uint32 Mesh::FindSharedVertexAttributeLayerIndexByName(const char* name) const + size_t Mesh::FindSharedVertexAttributeLayerIndexByName(const char* name) const { - const uint32 numLayers = mSharedVertexAttributes.size(); - for (uint32 i = 0; i < numLayers; ++i) + const auto foundLayer = AZStd::find_if(begin(mSharedVertexAttributes), end(mSharedVertexAttributes), [name](const VertexAttributeLayer* layer) { - if (mSharedVertexAttributes[i]->GetNameString() == name) - { - return i; - } - } - - return MCORE_INVALIDINDEX32; + return layer->GetNameString() == name; + }); + return foundLayer != end(mSharedVertexAttributes) ? AZStd::distance(begin(mSharedVertexAttributes), foundLayer) : InvalidIndex; } // find by name as string - uint32 Mesh::FindSharedVertexAttributeLayerIndexByNameString(const AZStd::string& name) const + size_t Mesh::FindSharedVertexAttributeLayerIndexByNameString(const AZStd::string& name) const { - const uint32 numLayers = mSharedVertexAttributes.size(); - for (uint32 i = 0; i < numLayers; ++i) + const auto foundLayer = AZStd::find_if(begin(mSharedVertexAttributes), end(mSharedVertexAttributes), [name](const VertexAttributeLayer* layer) { - if (mSharedVertexAttributes[i]->GetNameString() == name) - { - return i; - } - } - - return MCORE_INVALIDINDEX32; + return layer->GetNameString() == name; + }); + return foundLayer != end(mSharedVertexAttributes) ? AZStd::distance(begin(mSharedVertexAttributes), foundLayer) : InvalidIndex; } // find by name ID - uint32 Mesh::FindSharedVertexAttributeLayerIndexByNameID(uint32 nameID) const + size_t Mesh::FindSharedVertexAttributeLayerIndexByNameID(uint32 nameID) const { - const uint32 numLayers = mSharedVertexAttributes.size(); - for (uint32 i = 0; i < numLayers; ++i) + const auto foundLayer = AZStd::find_if(begin(mSharedVertexAttributes), end(mSharedVertexAttributes), [nameID](const VertexAttributeLayer* layer) { - if (mSharedVertexAttributes[i]->GetNameID() == nameID) - { - return i; - } - } - - return MCORE_INVALIDINDEX32; + return layer->GetNameID() == nameID; + }); + return foundLayer != end(mSharedVertexAttributes) ? AZStd::distance(begin(mSharedVertexAttributes), foundLayer) : InvalidIndex; } } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.h b/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.h index 420bac0f33..d9c09d66bb 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.h @@ -171,7 +171,7 @@ namespace EMotionFX * It is recommended NOT to put this function inside a loop, because it is not very fast. * @result The number of UV layers/sets currently present inside this mesh. */ - uint32 CalcNumUVLayers() const; + size_t CalcNumUVLayers() const; /** * Calculate the number of vertex attribute layers of the given type. @@ -179,7 +179,7 @@ namespace EMotionFX * @param[in] type The type of the vertex attribute layer to count. * @result The number of layers/sets currently present inside this mesh. */ - uint32 CalcNumAttributeLayers(uint32 type) const; + size_t CalcNumAttributeLayers(uint32 type) const; /** * Get the number of original vertices. This can be lower compared to the value returned by GetNumVertices(). @@ -249,7 +249,7 @@ namespace EMotionFX * @param nr The submesh number, which must be in range of [0..GetNumSubMeshes()-1]. * @param subMesh The submesh to use. */ - MCORE_INLINE void SetSubMesh(uint32 nr, SubMesh* subMesh) { mSubMeshes[nr] = subMesh; } + MCORE_INLINE void SetSubMesh(size_t nr, SubMesh* subMesh) { mSubMeshes[nr] = subMesh; } /** * Set the number of submeshes. @@ -257,21 +257,21 @@ namespace EMotionFX * Do not forget to use SetSubMesh() to initialize all submeshes! * @param numSubMeshes The number of submeshes to use. */ - MCORE_INLINE void SetNumSubMeshes(uint32 numSubMeshes) { mSubMeshes.resize(numSubMeshes); } + MCORE_INLINE void SetNumSubMeshes(size_t numSubMeshes) { mSubMeshes.resize(numSubMeshes); } /** * Remove a given submesh from this mesh. * @param nr The submesh index number to remove, which must be in range of 0..GetNumSubMeshes()-1. * @param delFromMem Set to true when you want to delete the submesh from memory as well, otherwise set to false. */ - void RemoveSubMesh(uint32 nr, bool delFromMem = true); + void RemoveSubMesh(size_t nr, bool delFromMem = true); /** * Insert a submesh into the array of submeshes. * @param insertIndex The position in the submesh array to insert this new submesh. * @param subMesh A pointer to the submesh to insert into this mesh. */ - void InsertSubMesh(uint32 insertIndex, SubMesh* subMesh); + void InsertSubMesh(size_t insertIndex, SubMesh* subMesh); /** * Get the shared vertex attribute data of a given layer. @@ -306,7 +306,7 @@ namespace EMotionFX * @result The vertex attribute layer index number that you can pass to GetSharedVertexAttributeLayer. A value of MCORE_INVALIDINDEX32 is returned * when no result could be found. */ - uint32 FindSharedVertexAttributeLayerNumber(uint32 layerTypeID, uint32 occurrence = 0) const; + size_t FindSharedVertexAttributeLayerNumber(uint32 layerTypeID, size_t occurrence = 0) const; /** * Find and return the shared vertex attribute layer of a given type. @@ -318,7 +318,7 @@ namespace EMotionFX * want the second layer of the given type, etc. * @result A pointer to the vertex attribute layer, or nullptr when none could be found. */ - VertexAttributeLayer* FindSharedVertexAttributeLayer(uint32 layerTypeID, uint32 occurence = 0) const; + VertexAttributeLayer* FindSharedVertexAttributeLayer(uint32 layerTypeID, size_t occurence = 0) const; /** * Removes all shared vertex attributes for all shared vertices. @@ -331,7 +331,7 @@ namespace EMotionFX * Automatically deletes the data from memory. * @param layerNr The layer number to remove, must be below the value returned by GetNumSharedVertexAttributeLayers(). */ - void RemoveSharedVertexAttributeLayer(uint32 layerNr); + void RemoveSharedVertexAttributeLayer(size_t layerNr); /** * Get the number of vertex attributes. @@ -346,7 +346,7 @@ namespace EMotionFX * @param layerNr The layer number to get the attributes from. Must be below the value returned by GetNumVertexAttributeLayers(). * @result A pointer to the array of vertex attributes. You can typecast this pointer if you know the type of the vertex attributes. */ - VertexAttributeLayer* GetVertexAttributeLayer(uint32 layerNr); + VertexAttributeLayer* GetVertexAttributeLayer(size_t layerNr); /** * Adds a new layer of vertex attributes. @@ -373,9 +373,9 @@ namespace EMotionFX * @result The vertex attribute layer index number that you can pass to GetSharedVertexAttributeLayer. A value of MCORE_INVALIDINDEX32 os returned * when no result could be found. */ - uint32 FindVertexAttributeLayerNumber(uint32 layerTypeID, uint32 occurrence = 0) const; + size_t FindVertexAttributeLayerNumber(uint32 layerTypeID, size_t occurrence = 0) const; - uint32 FindVertexAttributeLayerNumberByName(uint32 layerTypeID, const char* name) const; + size_t FindVertexAttributeLayerNumberByName(uint32 layerTypeID, const char* name) const; VertexAttributeLayer* FindVertexAttributeLayerByName(uint32 layerTypeID, const char* name) const; @@ -389,15 +389,15 @@ namespace EMotionFX * want the second layer of the given type, etc. * @result A pointer to the vertex attribute layer, or nullptr when none could be found. */ - VertexAttributeLayer* FindVertexAttributeLayer(uint32 layerTypeID, uint32 occurence = 0) const; + VertexAttributeLayer* FindVertexAttributeLayer(uint32 layerTypeID, size_t occurence = 0) const; - uint32 FindVertexAttributeLayerIndexByName(const char* name) const; - uint32 FindVertexAttributeLayerIndexByNameString(const AZStd::string& name) const; - uint32 FindVertexAttributeLayerIndexByNameID(uint32 nameID) const; + size_t FindVertexAttributeLayerIndexByName(const char* name) const; + size_t FindVertexAttributeLayerIndexByNameString(const AZStd::string& name) const; + size_t FindVertexAttributeLayerIndexByNameID(uint32 nameID) const; - uint32 FindSharedVertexAttributeLayerIndexByName(const char* name) const; - uint32 FindSharedVertexAttributeLayerIndexByNameString(const AZStd::string& name) const; - uint32 FindSharedVertexAttributeLayerIndexByNameID(uint32 nameID) const; + size_t FindSharedVertexAttributeLayerIndexByName(const char* name) const; + size_t FindSharedVertexAttributeLayerIndexByNameString(const AZStd::string& name) const; + size_t FindSharedVertexAttributeLayerIndexByNameID(uint32 nameID) const; /** * Removes all vertex attributes for all vertices. @@ -410,7 +410,7 @@ namespace EMotionFX * Automatically deletes the data from memory. * @param layerNr The layer number to remove, must be below the value returned by GetNumVertexAttributeLayers(). */ - void RemoveVertexAttributeLayer(uint32 layerNr); + void RemoveVertexAttributeLayer(size_t layerNr); //--------------------------------------------------- @@ -517,7 +517,7 @@ namespace EMotionFX * @param onlyRemoveOnZeroVertsAndTriangles Only remove when both the number of vertices and number of indices/triangles are zero. * @result Returns the number of removed submeshes. */ - uint32 RemoveEmptySubMeshes(bool onlyRemoveOnZeroVertsAndTriangles = true); + size_t RemoveEmptySubMeshes(bool onlyRemoveOnZeroVertsAndTriangles = true); /** * Find specific current vertex data in the mesh. This contains the vertex data after mesh deformers have been @@ -538,7 +538,7 @@ namespace EMotionFX * when there are multiple layers of the same type. An example is a mesh having multiple UV layers. * @result A void pointer to the layer data. You have to typecast yourself. */ - void* FindVertexData(uint32 layerID, uint32 occurrence = 0) const; + void* FindVertexData(uint32 layerID, size_t occurrence = 0) const; void* FindVertexDataByName(uint32 layerID, const char* name) const; @@ -561,7 +561,7 @@ namespace EMotionFX * when there are multiple layers of the same type. An example is a mesh having multiple UV layers. * @result A void pointer to the layer data. You have to typecast yourself. */ - void* FindOriginalVertexData(uint32 layerID, uint32 occurrence = 0) const; + void* FindOriginalVertexData(uint32 layerID, size_t occurrence = 0) const; void* FindOriginalVertexDataByName(uint32 layerID, const char* name) const; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MeshDeformer.h b/Gems/EMotionFX/Code/EMotionFX/Source/MeshDeformer.h index 78bdc842e9..e1caeaf5a9 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MeshDeformer.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MeshDeformer.h @@ -56,7 +56,7 @@ namespace EMotionFX * @param mesh The mesh to apply the cloned deformer on. * @result A pointer to the newly created clone of this deformer. */ - virtual MeshDeformer* Clone(Mesh* mesh) = 0; + virtual MeshDeformer* Clone(Mesh* mesh) const = 0; /** * Returns the type identification number of the deformer class. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MeshDeformerStack.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MeshDeformerStack.cpp index 82245a505f..ee204cf298 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MeshDeformerStack.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MeshDeformerStack.cpp @@ -28,10 +28,9 @@ namespace EMotionFX // destructor MeshDeformerStack::~MeshDeformerStack() { - const uint32 numDeformers = mDeformers.size(); - for (uint32 i = 0; i < numDeformers; ++i) + for (MeshDeformer* deformer : mDeformers) { - mDeformers[i]->Destroy(); + deformer->Destroy(); } mDeformers.clear(); @@ -58,30 +57,25 @@ namespace EMotionFX // update the mesh deformer stack void MeshDeformerStack::Update(ActorInstance* actorInstance, Node* node, float timeDelta, bool forceUpdateDisabledDeformers) { - // if we have deformers in the stack - const uint32 numDeformers = mDeformers.size(); - if (numDeformers > 0) + bool firstEnabled = true; + + // iterate through the deformers and update them + for (MeshDeformer* deformer : mDeformers) { - bool firstEnabled = true; - - // iterate through the deformers and update them - for (uint32 i = 0; i < numDeformers; ++i) + // if the deformer is enabled + if (deformer->GetIsEnabled() || forceUpdateDisabledDeformers) { - // if the deformer is enabled - if (mDeformers[i]->GetIsEnabled() || forceUpdateDisabledDeformers) + // if this is the first enabled deformer + if (firstEnabled) { - // if this is the first enabled deformer - if (firstEnabled) - { - firstEnabled = false; + firstEnabled = false; - // reset all output vertex data to the original vertex data - mMesh->ResetToOriginalData(); - } - - // update the mesh deformer - mDeformers[i]->Update(actorInstance, node, timeDelta); + // reset all output vertex data to the original vertex data + mMesh->ResetToOriginalData(); } + + // update the mesh deformer + deformer->Update(actorInstance, node, timeDelta); } } } @@ -90,13 +84,10 @@ namespace EMotionFX void MeshDeformerStack::UpdateByModifierType(ActorInstance* actorInstance, Node* node, float timeDelta, uint32 typeID, bool resetMesh, bool forceUpdateDisabledDeformers) { bool resetDone = false; - // if we have deformers in the stack - const uint32 numDeformers = mDeformers.size(); - // iterate through the deformers and update them - for (uint32 i = 0; i < numDeformers; ++i) + for (MeshDeformer* deformer : mDeformers) { // if the deformer of the correct type and is enabled - if (mDeformers[i]->GetType() == typeID && (mDeformers[i]->GetIsEnabled() || forceUpdateDisabledDeformers)) + if (deformer->GetType() == typeID && (deformer->GetIsEnabled() || forceUpdateDisabledDeformers)) { // if this is the first enabled deformer if (resetMesh && !resetDone) @@ -107,7 +98,7 @@ namespace EMotionFX } // update the mesh deformer - mDeformers[i]->Update(actorInstance, node, timeDelta); + deformer->Update(actorInstance, node, timeDelta); } } } @@ -134,7 +125,7 @@ namespace EMotionFX } - void MeshDeformerStack::InsertDeformer(uint32 pos, MeshDeformer* meshDeformer) + void MeshDeformerStack::InsertDeformer(size_t pos, MeshDeformer* meshDeformer) { // add the object into the stack mDeformers.emplace(AZStd::next(begin(mDeformers), pos), meshDeformer); @@ -159,10 +150,9 @@ namespace EMotionFX MeshDeformerStack* newStack = aznew MeshDeformerStack(mesh); // clone all deformers - const uint32 numDeformers = mDeformers.size(); - for (uint32 i = 0; i < numDeformers; ++i) + for (const MeshDeformer* deformer : mDeformers) { - newStack->AddDeformer(mDeformers[i]->Clone(mesh)); + newStack->AddDeformer(deformer->Clone(mesh)); } // return a pointer to the clone @@ -176,7 +166,7 @@ namespace EMotionFX } - MeshDeformer* MeshDeformerStack::GetDeformer(uint32 nr) const + MeshDeformer* MeshDeformerStack::GetDeformer(size_t nr) const { MCORE_ASSERT(nr < mDeformers.size()); return mDeformers[nr]; @@ -184,10 +174,10 @@ namespace EMotionFX // remove all the deformers of a given type - uint32 MeshDeformerStack::RemoveAllDeformersByType(uint32 deformerTypeID) + size_t MeshDeformerStack::RemoveAllDeformersByType(uint32 deformerTypeID) { - uint32 numRemoved = 0; - for (uint32 a = 0; a < mDeformers.size(); ) + size_t numRemoved = 0; + for (size_t a = 0; a < mDeformers.size(); ) { MeshDeformer* deformer = mDeformers[a]; if (deformer->GetType() == deformerTypeID) @@ -209,12 +199,10 @@ namespace EMotionFX // remove all the deformers void MeshDeformerStack::RemoveAllDeformers() { - for (uint32 i = 0; i < mDeformers.size(); ++i) + for (MeshDeformer* deformer : mDeformers) { // retrieve the current deformer - MeshDeformer* deformer = mDeformers[i]; - - // remove the deformer + // remove the deformer RemoveDeformer(deformer); deformer->Destroy(); } @@ -222,14 +210,12 @@ namespace EMotionFX // enabled or disable all controllers of a given type - uint32 MeshDeformerStack::EnableAllDeformersByType(uint32 deformerTypeID, bool enabled) + size_t MeshDeformerStack::EnableAllDeformersByType(uint32 deformerTypeID, bool enabled) { - uint32 numChanged = 0; - const uint32 numDeformers = mDeformers.size(); - for (uint32 a = 0; a < numDeformers; ++a) + size_t numChanged = 0; + for (MeshDeformer* deformer : mDeformers) { - MeshDeformer* deformer = mDeformers[a]; - if (deformer->GetType() == deformerTypeID) + if (deformer->GetType() == deformerTypeID) { deformer->SetIsEnabled(enabled); numChanged++; @@ -243,44 +229,20 @@ namespace EMotionFX // check if the stack contains a deformer of a specified type bool MeshDeformerStack::CheckIfHasDeformerOfType(uint32 deformerTypeID) const { - const uint32 numDeformers = mDeformers.size(); - for (uint32 a = 0; a < numDeformers; ++a) + return AZStd::any_of(begin(mDeformers), end(mDeformers), [deformerTypeID](const MeshDeformer* deformer) { - if (mDeformers[a]->GetType() == deformerTypeID) - { - return true; - } - } - - return false; + return deformer->GetType() == deformerTypeID; + }); } // find a deformer by type ID - MeshDeformer* MeshDeformerStack::FindDeformerByType(uint32 deformerTypeID, uint32 occurrence) const + MeshDeformer* MeshDeformerStack::FindDeformerByType(uint32 deformerTypeID, size_t occurrence) const { - uint32 count = 0; - - // for all deformers - const uint32 numDeformers = mDeformers.size(); - for (uint32 a = 0; a < numDeformers; ++a) + const auto foundDeformer = AZStd::find_if(begin(mDeformers), end(mDeformers), [deformerTypeID, iter = occurrence](const MeshDeformer* deformer) mutable { - // if this is a deformer of the type we search for - if (mDeformers[a]->GetType() == deformerTypeID) - { - // if its the one we want - if (count == occurrence) - { - return mDeformers[a]; - } - else - { - count++; - } - } - } - - // none found - return nullptr; + return deformer->GetType() == deformerTypeID && iter-- == 0; + }); + return foundDeformer != end(mDeformers) ? *foundDeformer : nullptr; } } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MeshDeformerStack.h b/Gems/EMotionFX/Code/EMotionFX/Source/MeshDeformerStack.h index 0b1ce6fbcb..ae63a1e495 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MeshDeformerStack.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MeshDeformerStack.h @@ -87,7 +87,7 @@ namespace EMotionFX * @param pos The position to insert the deformer. * @param meshDeformer The deformer to store at this position. */ - void InsertDeformer(uint32 pos, MeshDeformer* meshDeformer); + void InsertDeformer(size_t pos, MeshDeformer* meshDeformer); /** * Remove a given deformer. @@ -101,7 +101,7 @@ namespace EMotionFX * @param deformerTypeID The type ID of the deformer, which is returned by MeshDeformer::GetType(). * @result Returns the number of deformers that have been removed. */ - uint32 RemoveAllDeformersByType(uint32 deformerTypeID); + size_t RemoveAllDeformersByType(uint32 deformerTypeID); /** * Remove all deformers from this mesh deformer stack. @@ -115,7 +115,7 @@ namespace EMotionFX * @param enabled Set to true when you want to enable these deformers, or false if you want to disable them. * @result Returns the number of deformers that have been enabled or disabled. */ - uint32 EnableAllDeformersByType(uint32 deformerTypeID, bool enabled); + size_t EnableAllDeformersByType(uint32 deformerTypeID, bool enabled); /** * Creates an exact clone (copy) of this deformer stack, including all deformers (which will also be cloned). @@ -141,7 +141,7 @@ namespace EMotionFX * @param nr The deformer number to get. * @result A pointer to the deformer. */ - MeshDeformer* GetDeformer(uint32 nr) const; + MeshDeformer* GetDeformer(size_t nr) const; /** * Check if the stack contains a deformer of a given type. @@ -156,7 +156,7 @@ namespace EMotionFX * @param occurrence In case there are multiple controllers of the same type, 0 means it returns the first one, 1 means the second, etc. * @result A pointer to the mesh deformer of the given type, or nullptr when not found. */ - MeshDeformer* FindDeformerByType(uint32 deformerTypeID, uint32 occurrence = 0) const; + MeshDeformer* FindDeformerByType(uint32 deformerTypeID, size_t occurrence = 0) const; private: AZStd::vector mDeformers; /**< The stack of deformers. */ diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MorphMeshDeformer.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MorphMeshDeformer.cpp index b40ff27ce0..561e94b35b 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MorphMeshDeformer.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MorphMeshDeformer.cpp @@ -57,14 +57,14 @@ namespace EMotionFX // clone this class - MeshDeformer* MorphMeshDeformer::Clone(Mesh* mesh) + MeshDeformer* MorphMeshDeformer::Clone(Mesh* mesh) const { // create the new cloned deformer MorphMeshDeformer* result = aznew MorphMeshDeformer(mesh); // copy the deform passes result->mDeformPasses.resize(mDeformPasses.size()); - for (uint32 i = 0; i < mDeformPasses.size(); ++i) + for (size_t i = 0; i < mDeformPasses.size(); ++i) { DeformPass& pass = result->mDeformPasses[i]; pass.mDeformDataNr = mDeformPasses[i].mDeformDataNr; @@ -85,21 +85,20 @@ namespace EMotionFX // get the actor instance and its LOD level Actor* actor = actorInstance->GetActor(); - const uint32 lodLevel = actorInstance->GetLODLevel(); + const size_t lodLevel = actorInstance->GetLODLevel(); // apply all deform passes - const uint32 numPasses = mDeformPasses.size(); - for (uint32 i = 0; i < numPasses; ++i) + for (DeformPass& mDeformPasse : mDeformPasses) { // find the morph target - MorphTargetStandard* morphTarget = (MorphTargetStandard*)actor->GetMorphSetup(lodLevel)->FindMorphTargetByID(mDeformPasses[i].mMorphTarget->GetID()); + MorphTargetStandard* morphTarget = (MorphTargetStandard*)actor->GetMorphSetup(lodLevel)->FindMorphTargetByID(mDeformPasse.mMorphTarget->GetID()); if (morphTarget == nullptr) { continue; } // get the deform data and number of vertices to deform - MorphTargetStandard::DeformData* deformData = morphTarget->GetDeformData(mDeformPasses[i].mDeformDataNr); + MorphTargetStandard::DeformData* deformData = morphTarget->GetDeformData(mDeformPasse.mDeformDataNr); const uint32 numDeformVerts = deformData->mNumVerts; // this mesh deformer can't work on this mesh, because the deformdata number of vertices is bigger than the @@ -121,7 +120,7 @@ namespace EMotionFX const bool nearZero = (MCore::Math::Abs(weight) < 0.0001f); // we are near zero, and the previous frame as well, so we can return - if (nearZero && mDeformPasses[i].mLastNearZero) + if (nearZero && mDeformPasse.mLastNearZero) { continue; } @@ -129,11 +128,11 @@ namespace EMotionFX // update the flag if (nearZero) { - mDeformPasses[i].mLastNearZero = true; + mDeformPasse.mLastNearZero = true; } else { - mDeformPasses[i].mLastNearZero = false; // we moved away from zero influence + mDeformPasse.mLastNearZero = false; // we moved away from zero influence } // output data @@ -150,10 +149,9 @@ namespace EMotionFX if (tangents && bitangents) { // process all vertices that we need to deform - uint32 vtxNr; for (uint32 v = 0; v < numDeformVerts; ++v) { - vtxNr = deltas[v].mVertexNr; + uint32 vtxNr = deltas[v].mVertexNr; positions [vtxNr] = positions[vtxNr] + deltas[v].mPosition.ToVector3(minValue, maxValue) * weight; normals [vtxNr] = normals[vtxNr] + deltas[v].mNormal.ToVector3(-2.0f, 2.0f) * weight; @@ -165,10 +163,9 @@ namespace EMotionFX } else if (tangents && !bitangents) // tangents but no bitangents { - uint32 vtxNr; for (uint32 v = 0; v < numDeformVerts; ++v) { - vtxNr = deltas[v].mVertexNr; + uint32 vtxNr = deltas[v].mVertexNr; positions[vtxNr] = positions[vtxNr] + deltas[v].mPosition.ToVector3(minValue, maxValue) * weight; normals [vtxNr] = normals[vtxNr] + deltas[v].mNormal.ToVector3(-2.0f, 2.0f) * weight; @@ -180,10 +177,9 @@ namespace EMotionFX else // no tangents { // process all vertices that we need to deform - uint32 vtxNr; for (uint32 v = 0; v < numDeformVerts; ++v) { - vtxNr = deltas[v].mVertexNr; + uint32 vtxNr = deltas[v].mVertexNr; positions[vtxNr] = positions[vtxNr] + deltas[v].mPosition.ToVector3(minValue, maxValue) * weight; normals[vtxNr] = normals[vtxNr] + deltas[v].mNormal.ToVector3(-2.0f, 2.0f) * weight; @@ -203,15 +199,15 @@ namespace EMotionFX MorphSetup* morphSetup = actor->GetMorphSetup(lodLevel); // get the number of morph targets and iterate through them - const uint32 numMorphTargets = morphSetup->GetNumMorphTargets(); - for (uint32 i = 0; i < numMorphTargets; ++i) + const size_t numMorphTargets = morphSetup->GetNumMorphTargets(); + for (size_t i = 0; i < numMorphTargets; ++i) { // get the morph target MorphTargetStandard* morphTarget = static_cast(morphSetup->GetMorphTarget(i)); // get the number of deform datas and add one deform pass per deform data - const uint32 numDeformDatas = morphTarget->GetNumDeformDatas(); - for (uint32 j = 0; j < numDeformDatas; ++j) + const size_t numDeformDatas = morphTarget->GetNumDeformDatas(); + for (size_t j = 0; j < numDeformDatas; ++j) { // get the deform data and only add it to our deformer in case it belongs to our mesh MorphTargetStandard::DeformData* deformData = morphTarget->GetDeformData(j); @@ -219,7 +215,7 @@ namespace EMotionFX { // add an empty deform pass and fill it afterwards mDeformPasses.emplace_back(); - const uint32 deformPassIndex = mDeformPasses.size() - 1; + const size_t deformPassIndex = mDeformPasses.size() - 1; mDeformPasses[deformPassIndex].mDeformDataNr = j; mDeformPasses[deformPassIndex].mMorphTarget = morphTarget; } @@ -240,7 +236,7 @@ namespace EMotionFX } - void MorphMeshDeformer::ReserveDeformPasses(uint32 numPasses) + void MorphMeshDeformer::ReserveDeformPasses(size_t numPasses) { mDeformPasses.reserve(numPasses); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MorphMeshDeformer.h b/Gems/EMotionFX/Code/EMotionFX/Source/MorphMeshDeformer.h index 303c379248..882d4bdfeb 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MorphMeshDeformer.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MorphMeshDeformer.h @@ -55,7 +55,7 @@ namespace EMotionFX struct EMFX_API DeformPass { MorphTargetStandard* mMorphTarget; /**< The morph target working on the mesh. */ - uint32 mDeformDataNr; /**< An index inside the deform datas of the standard morph target. */ + size_t mDeformDataNr; /**< An index inside the deform datas of the standard morph target. */ bool mLastNearZero; /**< Was the last frame's weight near zero? */ /** @@ -64,7 +64,7 @@ namespace EMotionFX */ DeformPass() : mMorphTarget(nullptr) - , mDeformDataNr(MCORE_INVALIDINDEX32) + , mDeformDataNr(InvalidIndex) , mLastNearZero(false) {} }; @@ -110,7 +110,7 @@ namespace EMotionFX * @param mesh The mesh to apply the deformer on. * @result A pointer to the newly created clone of this deformer. */ - MeshDeformer* Clone(Mesh* mesh) override; + MeshDeformer* Clone(Mesh* mesh) const override; /** * Add a deform pass. @@ -129,7 +129,7 @@ namespace EMotionFX * This does not influence the return value of GetNumDeformPasses(). * @param numPasses The number of passes to pre-allocate space for. */ - void ReserveDeformPasses(uint32 numPasses); + void ReserveDeformPasses(size_t numPasses); private: AZStd::vector mDeformPasses; /**< The deform passes. Each pass basically represents a morph target. */ diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MorphSetup.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MorphSetup.cpp index 0b27ee634e..069e7c971a 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MorphSetup.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MorphSetup.cpp @@ -40,7 +40,7 @@ namespace EMotionFX // remove a morph target - void MorphSetup::RemoveMorphTarget(uint32 nr, bool delFromMem) + void MorphSetup::RemoveMorphTarget(size_t nr, bool delFromMem) { if (delFromMem) { @@ -70,10 +70,9 @@ namespace EMotionFX // remove all morph targets void MorphSetup::RemoveAllMorphTargets() { - const uint32 numTargets = mMorphTargets.size(); - for (uint32 i = 0; i < numTargets; ++i) + for (MorphTarget*& mMorphTarget : mMorphTargets) { - mMorphTargets[i]->Destroy(); + mMorphTarget->Destroy(); } mMorphTargets.clear(); @@ -83,98 +82,64 @@ namespace EMotionFX // get a morph target by ID MorphTarget* MorphSetup::FindMorphTargetByID(uint32 id) const { - // linear search, and check IDs - const uint32 numTargets = mMorphTargets.size(); - for (uint32 i = 0; i < numTargets; ++i) + const auto foundMorphTarget = AZStd::find_if(begin(mMorphTargets), end(mMorphTargets), [id](const MorphTarget* morphTarget) { - if (mMorphTargets[i]->GetID() == id) - { - return mMorphTargets[i]; - } - } - - // nothing found - return nullptr; + return morphTarget->GetID() == id; + }); + return foundMorphTarget != end(mMorphTargets) ? *foundMorphTarget : nullptr; } // get a morph target number by ID - uint32 MorphSetup::FindMorphTargetNumberByID(uint32 id) const + size_t MorphSetup::FindMorphTargetNumberByID(uint32 id) const { - // linear search, and check IDs - const uint32 numTargets = mMorphTargets.size(); - for (uint32 i = 0; i < numTargets; ++i) + const auto foundMorphTarget = AZStd::find_if(begin(mMorphTargets), end(mMorphTargets), [id](const MorphTarget* morphTarget) { - if (mMorphTargets[i]->GetID() == id) - { - return i; - } - } - - // nothing found - return MCORE_INVALIDINDEX32; + return morphTarget->GetID() == id; + }); + return foundMorphTarget != end(mMorphTargets) ? AZStd::distance(begin(mMorphTargets), foundMorphTarget) : InvalidIndex; } - uint32 MorphSetup::FindMorphTargetIndexByName(const char* name) const + size_t MorphSetup::FindMorphTargetIndexByName(const char* name) const { - const uint32 numTargets = mMorphTargets.size(); - for (uint32 i = 0; i < numTargets; ++i) + const auto foundMorphTarget = AZStd::find_if(begin(mMorphTargets), end(mMorphTargets), [name](const MorphTarget* morphTarget) { - if (mMorphTargets[i]->GetNameString() == name) - { - return i; - } - } - - return MCORE_INVALIDINDEX32; + return morphTarget->GetNameString() == name; + }); + return foundMorphTarget != end(mMorphTargets) ? AZStd::distance(begin(mMorphTargets), foundMorphTarget) : InvalidIndex; } - uint32 MorphSetup::FindMorphTargetIndexByNameNoCase(const char* name) const + size_t MorphSetup::FindMorphTargetIndexByNameNoCase(const char* name) const { - const uint32 numTargets = mMorphTargets.size(); - for (uint32 i = 0; i < numTargets; ++i) + const auto foundMorphTarget = AZStd::find_if(begin(mMorphTargets), end(mMorphTargets), [name](const MorphTarget* morphTarget) { - if (AzFramework::StringFunc::Equal(mMorphTargets[i]->GetNameString().c_str(), name, false /* no case */)) - { - return i; - } - } - - return MCORE_INVALIDINDEX32; + return AzFramework::StringFunc::Equal(morphTarget->GetNameString().c_str(), name, false /* no case */); + }); + return foundMorphTarget != end(mMorphTargets) ? AZStd::distance(begin(mMorphTargets), foundMorphTarget) : InvalidIndex; } // find a morph target by name (case sensitive) MorphTarget* MorphSetup::FindMorphTargetByName(const char* name) const { - const uint32 numTargets = mMorphTargets.size(); - for (uint32 i = 0; i < numTargets; ++i) + const auto foundMorphTarget = AZStd::find_if(begin(mMorphTargets), end(mMorphTargets), [name](const MorphTarget* morphTarget) { - if (mMorphTargets[i]->GetNameString() == name) - { - return mMorphTargets[i]; - } - } - - return nullptr; + return morphTarget->GetNameString() == name; + }); + return foundMorphTarget != end(mMorphTargets) ? *foundMorphTarget : nullptr; } // find a morph target by name (not case sensitive) MorphTarget* MorphSetup::FindMorphTargetByNameNoCase(const char* name) const { - const uint32 numTargets = mMorphTargets.size(); - for (uint32 i = 0; i < numTargets; ++i) + const auto foundMorphTarget = AZStd::find_if(begin(mMorphTargets), end(mMorphTargets), [name](const MorphTarget* morphTarget) { - if (AzFramework::StringFunc::Equal(mMorphTargets[i]->GetNameString().c_str(), name, false /* no case */)) - { - return mMorphTargets[i]; - } - } - - return nullptr; + return AzFramework::StringFunc::Equal(morphTarget->GetNameString().c_str(), name, false /* no case */); + }); + return foundMorphTarget != end(mMorphTargets) ? *foundMorphTarget : nullptr; } @@ -185,10 +150,9 @@ namespace EMotionFX MorphSetup* clone = MorphSetup::Create(); // clone all morph targets - const uint32 numMorphTargets = mMorphTargets.size(); - for (uint32 i = 0; i < numMorphTargets; ++i) + for (const MorphTarget* morphTarget : mMorphTargets) { - clone->AddMorphTarget(mMorphTargets[i]->Clone()); + clone->AddMorphTarget(morphTarget->Clone()); } // return the cloned morph setup @@ -212,10 +176,9 @@ namespace EMotionFX } // scale the morph targets - const uint32 numMorphTargets = mMorphTargets.size(); - for (uint32 i = 0; i < numMorphTargets; ++i) + for (MorphTarget* mMorphTarget : mMorphTargets) { - mMorphTargets[i]->Scale(scaleFactor); + mMorphTarget->Scale(scaleFactor); } } } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MorphSetup.h b/Gems/EMotionFX/Code/EMotionFX/Source/MorphSetup.h index 45c55d301c..23a5789e03 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MorphSetup.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MorphSetup.h @@ -61,7 +61,7 @@ namespace EMotionFX * @param delFromMem When set to true, the morph target will be deleted from memory as well. When false, it will * only be removed from the array of morph targets inside this class. */ - void RemoveMorphTarget(uint32 nr, bool delFromMem = true); + void RemoveMorphTarget(size_t nr, bool delFromMem = true); /** * Remove a given morph target. @@ -89,24 +89,24 @@ namespace EMotionFX * Find a morph target index by its unique ID, which has been calculated based on its name. * All morph targets with the same ID will also have the same name. * @param id The ID to search for. - * @result The morph target number, or MCORE_INVALIDINDEX32 when not found. You can use the returned number with the method + * @result The morph target number, or InvalidIndex when not found. You can use the returned number with the method * GetMorphTarget(nr) in order to convert it into a direct pointer to the morph target. */ - uint32 FindMorphTargetNumberByID(uint32 id) const; + size_t FindMorphTargetNumberByID(uint32 id) const; /** * Find a morph target index by its name. * Please remember that this is case sensitive. * @result The index of the morph target that you can pass to GetMorphTarget(index). */ - uint32 FindMorphTargetIndexByName(const char* name) const; + size_t FindMorphTargetIndexByName(const char* name) const; /** * Find a morph target index by its name. * Please remember that this is case insensitive. * @result The index of the morph target that you can pass to GetMorphTarget(index). */ - uint32 FindMorphTargetIndexByNameNoCase(const char* name) const; + size_t FindMorphTargetIndexByNameNoCase(const char* name) const; /** * Find a morph target by its name. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MorphTarget.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MorphTarget.cpp index 3bb84881ff..9ccafbb5f3 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MorphTarget.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MorphTarget.cpp @@ -211,7 +211,7 @@ namespace EMotionFX // copy the base class members to the target class - void MorphTarget::CopyBaseClassMemberValues(MorphTarget* target) + void MorphTarget::CopyBaseClassMemberValues(MorphTarget* target) const { target->mNameID = mNameID; target->mRangeMin = mRangeMin; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MorphTarget.h b/Gems/EMotionFX/Code/EMotionFX/Source/MorphTarget.h index 3e32229691..35e2f620ae 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MorphTarget.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MorphTarget.h @@ -259,14 +259,14 @@ namespace EMotionFX * Creates an exact clone of this morph target. * @result Returns a pointer to an exact clone of this morph target. */ - virtual MorphTarget* Clone() = 0; + virtual MorphTarget* Clone() const = 0; /** * Copy the morph target base class members over to another morph target. * This can be used when implementing your own Clone method for your own morph target. * @param target The morph target to copy the data from. */ - void CopyBaseClassMemberValues(MorphTarget* target); + void CopyBaseClassMemberValues(MorphTarget* target) const; /** * Scale all transform and positional data. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MorphTargetStandard.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MorphTargetStandard.cpp index 4ee07c38f2..7612fd73d7 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MorphTargetStandard.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MorphTargetStandard.cpp @@ -82,11 +82,11 @@ namespace EMotionFX // Transform* targetData = targetPose->GetBindPoseLocalTransforms(); // check for transformation changes - const uint32 numPoseNodes = targetSkeleton->GetNumNodes(); - for (uint32 i = 0; i < numPoseNodes; ++i) + const size_t numPoseNodes = targetSkeleton->GetNumNodes(); + for (size_t i = 0; i < numPoseNodes; ++i) { // get a node id (both nodes will have the same id since they represent their names) - const uint32 nodeID = targetSkeleton->GetNode(i)->GetID(); + const size_t nodeID = targetSkeleton->GetNode(i)->GetID(); // try to find the node with the same name inside the neutral pose actor Node* neutralNode = neutralSkeleton->FindNodeByID(nodeID); @@ -96,8 +96,8 @@ namespace EMotionFX } // get the node indices of both nodes - const uint32 neutralNodeIndex = neutralNode->GetNodeIndex(); - const uint32 targetNodeIndex = targetSkeleton->GetNode(i)->GetNodeIndex(); + const size_t neutralNodeIndex = neutralNode->GetNodeIndex(); + const size_t targetNodeIndex = targetSkeleton->GetNode(i)->GetNodeIndex(); // skip bones in the bone list //if (mCaptureMeshDeforms) @@ -177,21 +177,20 @@ namespace EMotionFX const float normalizedWeight = CalcNormalizedWeight(newWeight); // convert in range of 0..1 // calculate the new transformations for all nodes of this morph target - const uint32 numTransforms = mTransforms.size(); - for (uint32 i = 0; i < numTransforms; ++i) + for (const Transformation& mTransform : mTransforms) { // if this is the node that gets modified by this transform - if (mTransforms[i].mNodeIndex != nodeIndex) + if (mTransform.mNodeIndex != nodeIndex) { continue; } - position += mTransforms[i].mPosition * newWeight; - scale += mTransforms[i].mScale * newWeight; + position += mTransform.mPosition * newWeight; + scale += mTransform.mScale * newWeight; // rotate additively const AZ::Quaternion& orgRot = actorInstance->GetTransformData()->GetBindPose()->GetLocalSpaceTransform(nodeIndex).mRotation; - const AZ::Quaternion rot = orgRot.NLerp(mTransforms[i].mRotation, normalizedWeight); + const AZ::Quaternion rot = orgRot.NLerp(mTransform.mRotation, normalizedWeight); rotation = rotation * (orgRot.GetInverseFull() * rot); rotation.Normalize(); @@ -204,27 +203,16 @@ namespace EMotionFX // check if this morph target influences the specified node or not bool MorphTargetStandard::Influences(size_t nodeIndex) const { - // check if there is a deform data object, which works on the specified node - for (const DeformData* deformData : mDeformDatas) - { - if (deformData->mNodeIndex == nodeIndex) + return + AZStd::any_of(begin(mDeformDatas), end(mDeformDatas), [nodeIndex](const DeformData* deformData) { - return true; - } - } - - // check all transforms - const uint32 numTransforms = mTransforms.size(); - for (uint32 i = 0; i < numTransforms; ++i) - { - if (mTransforms[i].mNodeIndex == nodeIndex) + return deformData->mNodeIndex == nodeIndex; + }) + || + AZStd::any_of(begin(mTransforms), end(mTransforms), [nodeIndex](const Transformation& transform) { - return true; - } - } - - // this morph target doesn't influence the given node - return false; + return transform.mNodeIndex == nodeIndex; + }); } @@ -239,27 +227,26 @@ namespace EMotionFX Transform newTransform; // calculate the new transformations for all nodes of this morph target - const uint32 numTransforms = mTransforms.size(); - for (uint32 i = 0; i < numTransforms; ++i) + for (const Transformation& transform : mTransforms) { // try to find the node - const uint32 nodeIndex = mTransforms[i].mNodeIndex; + const size_t nodeIndex = transform.mNodeIndex; // init the transform data newTransform = transformData->GetCurrentPose()->GetLocalSpaceTransform(nodeIndex); // calc new position and scale (delta based targetTransform) - newTransform.mPosition += mTransforms[i].mPosition * newWeight; + newTransform.mPosition += transform.mPosition * newWeight; EMFX_SCALECODE ( - newTransform.mScale += mTransforms[i].mScale * newWeight; + newTransform.mScale += transform.mScale * newWeight; // newTransform.mScaleRotation.Identity(); ) // rotate additively const AZ::Quaternion& orgRot = transformData->GetBindPose()->GetLocalSpaceTransform(nodeIndex).mRotation; - const AZ::Quaternion rot = orgRot.NLerp(mTransforms[i].mRotation, normalizedWeight); + const AZ::Quaternion rot = orgRot.NLerp(transform.mRotation, normalizedWeight); newTransform.mRotation = newTransform.mRotation * (orgRot.GetInverseFull() * rot); newTransform.mRotation.Normalize(); /* @@ -282,7 +269,7 @@ namespace EMotionFX return mDeformDatas.size(); } - MorphTargetStandard::DeformData* MorphTargetStandard::GetDeformData(uint32 nr) const + MorphTargetStandard::DeformData* MorphTargetStandard::GetDeformData(size_t nr) const { return mDeformDatas[nr]; } @@ -303,14 +290,14 @@ namespace EMotionFX return mTransforms.size(); } - MorphTargetStandard::Transformation& MorphTargetStandard::GetTransformation(uint32 nr) + MorphTargetStandard::Transformation& MorphTargetStandard::GetTransformation(size_t nr) { return mTransforms[nr]; } // clone this morph target - MorphTarget* MorphTargetStandard::Clone() + MorphTarget* MorphTargetStandard::Clone() const { // create the clone and copy its base class values MorphTargetStandard* clone = aznew MorphTargetStandard(""); // use an empty dummy name, as we will copy over the ID generated from it anyway @@ -397,18 +384,18 @@ namespace EMotionFX } // pre-alloc memory for the deform datas - void MorphTargetStandard::ReserveDeformDatas(uint32 numDeformDatas) + void MorphTargetStandard::ReserveDeformDatas(size_t numDeformDatas) { mDeformDatas.reserve(numDeformDatas); } // pre-allocate memory for the transformations - void MorphTargetStandard::ReserveTransformations(uint32 numTransforms) + void MorphTargetStandard::ReserveTransformations(size_t numTransforms) { mTransforms.reserve(numTransforms); } - void MorphTargetStandard::RemoveDeformData(uint32 index, bool delFromMem) + void MorphTargetStandard::RemoveDeformData(size_t index, bool delFromMem) { if (delFromMem) { @@ -418,7 +405,7 @@ namespace EMotionFX } - void MorphTargetStandard::RemoveTransformation(uint32 index) + void MorphTargetStandard::RemoveTransformation(size_t index) { mTransforms.erase(AZStd::next(begin(mTransforms), index)); } @@ -434,11 +421,9 @@ namespace EMotionFX } // scale the transformations - const uint32 numTransformations = mTransforms.size(); - for (uint32 i = 0; i < numTransformations; ++i) + for (Transformation& transform : mTransforms) { - Transformation& transform = mTransforms[i]; - transform.mPosition *= scaleFactor; + transform.mPosition *= scaleFactor; } // scale the deform datas (packed per vertex morph deltas) diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MorphTargetStandard.h b/Gems/EMotionFX/Code/EMotionFX/Source/MorphTargetStandard.h index d519e98f57..2ea1c43906 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MorphTargetStandard.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MorphTargetStandard.h @@ -104,7 +104,7 @@ namespace EMotionFX AZ::Quaternion mScaleRotation; /**< The scale rotation, as absolute value. */ AZ::Vector3 mPosition; /**< The position as a delta, so the difference between the original and target position. */ AZ::Vector3 mScale; /**< The scale as a delta, so the difference between the original and target scale. */ - uint32 mNodeIndex; /**< The node number to apply this on. */ + size_t mNodeIndex; /**< The node number to apply this on. */ } MCORE_ALIGN_POST(16); @@ -182,7 +182,7 @@ namespace EMotionFX * @param nr The deform data number, which must be in range of [0..GetNumDeformDatas()-1]. * @result A pointer to the deform data object. */ - DeformData* GetDeformData(uint32 nr) const; + DeformData* GetDeformData(size_t nr) const; /** * Add a given deform data to the array of deform data objects. @@ -207,13 +207,13 @@ namespace EMotionFX * @param nr The transformation number, must be in range of [0..GetNumTransformations()-1]. * @result A reference to the transformation. */ - Transformation& GetTransformation(uint32 nr); + Transformation& GetTransformation(size_t nr); /** * Creates an exact clone of this morph target. * @result Returns a pointer to an exact clone of this morph target. */ - MorphTarget* Clone() override; + MorphTarget* Clone() const override; /** * Remove all deform data objects from memory as well as from the class. @@ -230,27 +230,27 @@ namespace EMotionFX * @param index The deform data to remove. The index must be in range of [0, GetNumDeformDatas()]. * @param delFromMem Set to true (default) when you wish to also delete the specified deform data from memory. */ - void RemoveDeformData(uint32 index, bool delFromMem = true); + void RemoveDeformData(size_t index, bool delFromMem = true); /** * Remove the given transformation. * @param index The transformation to remove. The index must be in range of [0, GetNumTransformations()]. */ - void RemoveTransformation(uint32 index); + void RemoveTransformation(size_t index); /** * Reserve (pre-allocate) space in the array of deform datas. * This does NOT change the value returned by GetNumDeformDatas(). * @param numDeformDatas The absolute number of deform datas to pre-allocate space for. */ - void ReserveDeformDatas(uint32 numDeformDatas); + void ReserveDeformDatas(size_t numDeformDatas); /** * Reserve (pre-allocate) space in the array of transformations. * This does NOT change the value returned by GetNumTransformations(). * @param numTransforms The absolute number of transformations to pre-allocate space for. */ - void ReserveTransformations(uint32 numTransforms); + void ReserveTransformations(size_t numTransforms); /** * Scale all transform and positional data. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Motion.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Motion.cpp index c10740acb5..382a640e65 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Motion.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Motion.cpp @@ -30,7 +30,7 @@ namespace EMotionFX Motion::Motion(const char* name) : BaseObject() { - mID = MCore::GetIDGenerator().GenerateID(); + mID = aznumeric_caster(MCore::GetIDGenerator().GenerateID()); m_eventTable = AZStd::make_unique(); mUnitType = GetEMotionFX().GetUnitType(); mFileUnitType = mUnitType; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MotionData/MotionData.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MotionData/MotionData.cpp index 5f394fb791..7421495c60 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MotionData/MotionData.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MotionData/MotionData.cpp @@ -76,13 +76,13 @@ namespace EMotionFX { auto data = AZStd::make_unique(); const Skeleton* skeleton = actor->GetSkeleton(); - const AZ::u32 numJoints = skeleton->GetNumNodes(); - AZStd::vector& jointLinks = data->GetJointDataLinks(); + const size_t numJoints = skeleton->GetNumNodes(); + AZStd::vector& jointLinks = data->GetJointDataLinks(); jointLinks.resize(numJoints); - for (AZ::u32 i = 0; i < numJoints; ++i) + for (size_t i = 0; i < numJoints; ++i) { const AZ::Outcome findResult = FindJointIndexByNameId(skeleton->GetNode(i)->GetID()); - jointLinks[i] = findResult.IsSuccess() ? static_cast(findResult.GetValue()) : InvalidIndex32; + jointLinks[i] = findResult.IsSuccess() ? findResult.GetValue() : InvalidIndex; } return AZStd::move(data); } @@ -186,7 +186,7 @@ namespace EMotionFX return FindFloatIndexByNameId(MCore::GetStringIdPool().GenerateIdForString(name)); } - AZ::Outcome MotionData::FindJointIndexByNameId(AZ::u32 id) const + AZ::Outcome MotionData::FindJointIndexByNameId(size_t id) const { return FindIndexIf(m_staticJointData, [id](const StaticJointData& item) { return item.m_nameId == id; }); } @@ -453,12 +453,12 @@ namespace EMotionFX m_sampleRate = 30.0f; } - void MotionData::BasicRetarget(const ActorInstance* actorInstance, const MotionLinkData* motionLinkData, AZ::u32 jointIndex, Transform& inOutTransform) const + void MotionData::BasicRetarget(const ActorInstance* actorInstance, const MotionLinkData* motionLinkData, size_t jointIndex, Transform& inOutTransform) const { AZ_Assert(motionLinkData, "Expecting valid motionLinkData pointer."); const Pose* bindPose = actorInstance->GetTransformData()->GetBindPose(); - const AZStd::vector& jointLinks = motionLinkData->GetJointDataLinks(); + const AZStd::vector& jointLinks = motionLinkData->GetJointDataLinks(); // Special case handling on translation of root nodes. // Scale the translation amount based on the height difference between the bind pose height of the @@ -466,13 +466,13 @@ namespace EMotionFX // All other nodes get their translation data displaced based on the position difference between the // parent relative space positions in the actor instance's bind pose and the motion bind pose. const Actor* actor = actorInstance->GetActor(); - const AZ::u32 retargetRootIndex = actor->GetRetargetRootNodeIndex(); + const size_t retargetRootIndex = actor->GetRetargetRootNodeIndex(); const Node* joint = actor->GetSkeleton()->GetNode(jointIndex); bool needsDisplacement = true; - if ((retargetRootIndex == jointIndex || joint->GetIsRootNode()) && retargetRootIndex != InvalidIndex32) + if ((retargetRootIndex == jointIndex || joint->GetIsRootNode()) && retargetRootIndex != InvalidIndex) { - const AZ::u32 retargetRootDataIndex = jointLinks[actor->GetRetargetRootNodeIndex()]; - if (retargetRootDataIndex != InvalidIndex32) + const size_t retargetRootDataIndex = jointLinks[actor->GetRetargetRootNodeIndex()]; + if (retargetRootDataIndex != InvalidIndex) { const float subMotionHeight = m_staticJointData[retargetRootDataIndex].m_bindTransform.mPosition.GetZ(); if (AZ::GetAbs(subMotionHeight) >= AZ::Constants::FloatEpsilon) @@ -484,8 +484,8 @@ namespace EMotionFX } } - const AZ::u16 jointDataIndex = jointLinks[jointIndex]; - if (jointDataIndex != InvalidIndex16) + const size_t jointDataIndex = jointLinks[jointIndex]; + if (jointDataIndex != InvalidIndex) { const Transform& bindPoseTransform = bindPose->GetLocalSpaceTransform(jointIndex); const Transform& motionBindPose = m_staticJointData[jointDataIndex].m_bindTransform; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MotionData/MotionData.h b/Gems/EMotionFX/Code/EMotionFX/Source/MotionData/MotionData.h index 54c618bb86..fe831f1df0 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MotionData/MotionData.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MotionData/MotionData.h @@ -48,13 +48,13 @@ namespace EMotionFX MotionLinkData& operator=(MotionLinkData&&) = default; virtual ~MotionLinkData() = default; - AZStd::vector& GetJointDataLinks() { return m_jointDataLinks; } - const AZStd::vector& GetJointDataLinks() const { return m_jointDataLinks; } - bool IsJointActive(size_t jointIndex) const { return (m_jointDataLinks[jointIndex] != InvalidIndex32); } - AZ::u32 GetJointDataLink(size_t jointIndex) const { return m_jointDataLinks[jointIndex]; } + AZStd::vector& GetJointDataLinks() { return m_jointDataLinks; } + const AZStd::vector& GetJointDataLinks() const { return m_jointDataLinks; } + bool IsJointActive(size_t jointIndex) const { return (m_jointDataLinks[jointIndex] != InvalidIndex); } + size_t GetJointDataLink(size_t jointIndex) const { return m_jointDataLinks[jointIndex]; } protected: - AZStd::vector m_jointDataLinks; + AZStd::vector m_jointDataLinks; }; class EMFX_API MotionLinkCache @@ -162,7 +162,7 @@ namespace EMotionFX virtual const char* GetSceneSettingsName() const = 0; // Sampling - virtual Transform SampleJointTransform(const SampleSettings& settings, AZ::u32 jointSkeletonIndex) const = 0; + virtual Transform SampleJointTransform(const SampleSettings& settings, size_t jointSkeletonIndex) const = 0; virtual void SamplePose(const SampleSettings& settings, Pose* outputPose) const = 0; virtual float SampleMorph(float sampleTime, size_t morphDataIndex) const = 0; virtual float SampleFloat(float sampleTime, size_t morphDataIndex) const = 0; @@ -211,7 +211,7 @@ namespace EMotionFX void SetDuration(float duration); virtual void SetSampleRate(float sampleRate); - AZ::Outcome FindJointIndexByNameId(AZ::u32 nameId) const; + AZ::Outcome FindJointIndexByNameId(size_t nameId) const; AZ::Outcome FindMorphIndexByNameId(AZ::u32 nameId) const; AZ::Outcome FindFloatIndexByNameId(AZ::u32 nameId) const; @@ -265,7 +265,7 @@ namespace EMotionFX static void CalculateInterpolationIndicesNonUniform(const AZStd::vector& timeValues, float sampleTime, size_t& indexA, size_t& indexB, float& t); static void CalculateInterpolationIndicesUniform(float sampleTime, float sampleSpacing, float duration, size_t numSamples, size_t& indexA, size_t& indexB, float& t); - void BasicRetarget(const ActorInstance* actorInstance, const MotionLinkData* motionLinkData, AZ::u32 jointIndex, Transform& inOutTransform) const; + void BasicRetarget(const ActorInstance* actorInstance, const MotionLinkData* motionLinkData, size_t jointIndex, Transform& inOutTransform) const; bool IsAdditive() const; void SetAdditive(bool isAdditive); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MotionData/NonUniformMotionData.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MotionData/NonUniformMotionData.cpp index a2f224a752..619a962d7e 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MotionData/NonUniformMotionData.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MotionData/NonUniformMotionData.cpp @@ -74,14 +74,14 @@ namespace EMotionFX return values[indexA].ToQuaternion().NLerp(values[indexB].ToQuaternion(), t); } - Transform NonUniformMotionData::SampleJointTransform(const SampleSettings& settings, AZ::u32 jointSkeletonIndex) const + Transform NonUniformMotionData::SampleJointTransform(const SampleSettings& settings, size_t jointSkeletonIndex) const { const Actor* actor = settings.m_actorInstance->GetActor(); const MotionLinkData* motionLinkData = FindMotionLinkData(actor); const Skeleton* skeleton = actor->GetSkeleton(); - const AZ::u32 jointDataIndex = motionLinkData->GetJointDataLinks()[jointSkeletonIndex]; - if (m_additive && jointDataIndex == InvalidIndex32) + const size_t jointDataIndex = motionLinkData->GetJointDataLinks()[jointSkeletonIndex]; + if (m_additive && jointDataIndex == InvalidIndex) { return Transform::CreateIdentity(); } @@ -89,7 +89,7 @@ namespace EMotionFX // Sample the interpolated data. Transform result; const bool inPlace = (settings.m_inPlace && skeleton->GetNode(jointSkeletonIndex)->GetIsRootNode()); - if (jointDataIndex != InvalidIndex32 && !inPlace) + if (jointDataIndex != InvalidIndex && !inPlace) { const JointData& jointData = m_jointData[jointDataIndex]; result.mPosition = (!jointData.m_positionTrack.m_times.empty()) ? CalculateInterpolatedValue(jointData.m_positionTrack, settings.m_sampleTime) : m_staticJointData[jointDataIndex].m_staticTransform.mPosition; @@ -141,16 +141,16 @@ namespace EMotionFX const ActorInstance* actorInstance = settings.m_actorInstance; const Skeleton* skeleton = actor->GetSkeleton(); const Pose* bindPose = actorInstance->GetTransformData()->GetBindPose(); - const AZ::u32 numNodes = actorInstance->GetNumEnabledNodes(); - for (AZ::u32 i = 0; i < numNodes; ++i) + const size_t numNodes = actorInstance->GetNumEnabledNodes(); + for (size_t i = 0; i < numNodes; ++i) { - const AZ::u32 jointIndex = actorInstance->GetEnabledNode(i); - const AZ::u32 jointDataIndex = motionLinkData->GetJointDataLinks()[jointIndex]; + const uint16 jointIndex = actorInstance->GetEnabledNode(i); + const size_t jointDataIndex = motionLinkData->GetJointDataLinks()[jointIndex]; const bool inPlace = (settings.m_inPlace && skeleton->GetNode(jointIndex)->GetIsRootNode()); // Sample the interpolated data. Transform result; - if (jointDataIndex != InvalidIndex32 && !inPlace) + if (jointDataIndex != InvalidIndex && !inPlace) { const JointData& jointData = m_jointData[jointDataIndex]; result.mPosition = (!jointData.m_positionTrack.m_times.empty()) ? CalculateInterpolatedValue(jointData.m_positionTrack, settings.m_sampleTime) : m_staticJointData[jointDataIndex].m_staticTransform.mPosition; @@ -161,7 +161,7 @@ namespace EMotionFX } else { - if (m_additive && jointDataIndex == InvalidIndex32) + if (m_additive && jointDataIndex == InvalidIndex) { result = Transform::CreateIdentity(); } @@ -195,8 +195,8 @@ namespace EMotionFX // Output morph target weights. const MorphSetupInstance* morphSetup = actorInstance->GetMorphSetupInstance(); - const AZ::u32 numMorphTargets = morphSetup->GetNumMorphTargets(); - for (AZ::u32 i = 0; i < numMorphTargets; ++i) + const size_t numMorphTargets = morphSetup->GetNumMorphTargets(); + for (size_t i = 0; i < numMorphTargets; ++i) { const AZ::u32 morphTargetId = morphSetup->GetMorphTarget(i)->GetID(); const AZ::Outcome morphIndex = FindMorphIndexByNameId(morphTargetId); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MotionData/NonUniformMotionData.h b/Gems/EMotionFX/Code/EMotionFX/Source/MotionData/NonUniformMotionData.h index 648693120e..b5d8a05c44 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MotionData/NonUniformMotionData.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MotionData/NonUniformMotionData.h @@ -55,7 +55,7 @@ namespace EMotionFX AZ::u32 GetStreamSaveVersion() const override; const char* GetSceneSettingsName() const override; - Transform SampleJointTransform(const SampleSettings& settings, AZ::u32 jointSkeletonIndex) const override; + Transform SampleJointTransform(const SampleSettings& settings, size_t jointSkeletonIndex) const override; void SamplePose(const SampleSettings& settings, Pose* outputPose) const override; Transform SampleJointTransform(float sampleTime, size_t jointDataIndex) const override; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MotionData/UniformMotionData.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MotionData/UniformMotionData.cpp index d029a5de73..44ed629756 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MotionData/UniformMotionData.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MotionData/UniformMotionData.cpp @@ -130,13 +130,13 @@ namespace EMotionFX } } - Transform UniformMotionData::SampleJointTransform(const SampleSettings& settings, AZ::u32 jointSkeletonIndex) const + Transform UniformMotionData::SampleJointTransform(const SampleSettings& settings, size_t jointSkeletonIndex) const { const Actor* actor = settings.m_actorInstance->GetActor(); const MotionLinkData* motionLinkData = FindMotionLinkData(actor); - const AZ::u32 transformDataIndex = motionLinkData->GetJointDataLinks()[jointSkeletonIndex]; - if (m_additive && transformDataIndex == InvalidIndex32) + const size_t transformDataIndex = motionLinkData->GetJointDataLinks()[jointSkeletonIndex]; + if (m_additive && transformDataIndex == InvalidIndex) { return Transform::CreateIdentity(); } @@ -152,7 +152,7 @@ namespace EMotionFX // Sample the interpolated data. Transform result; - if (transformDataIndex != InvalidIndex32 && !inPlace) + if (transformDataIndex != InvalidIndex && !inPlace) { const StaticJointData& staticJointData = m_staticJointData[transformDataIndex]; const JointData& jointData = m_jointData[transformDataIndex]; @@ -208,20 +208,20 @@ namespace EMotionFX size_t indexB; CalculateInterpolationIndicesUniform(settings.m_sampleTime, m_sampleSpacing, m_duration, m_numSamples, indexA, indexB, t); - const AZStd::vector& jointLinks = motionLinkData->GetJointDataLinks(); + const AZStd::vector& jointLinks = motionLinkData->GetJointDataLinks(); const ActorInstance* actorInstance = settings.m_actorInstance; const Skeleton* skeleton = actor->GetSkeleton(); const Pose* bindPose = actorInstance->GetTransformData()->GetBindPose(); - const AZ::u32 numNodes = actorInstance->GetNumEnabledNodes(); - for (AZ::u32 i = 0; i < numNodes; ++i) + const size_t numNodes = actorInstance->GetNumEnabledNodes(); + for (size_t i = 0; i < numNodes; ++i) { - const AZ::u32 skeletonJointIndex = actorInstance->GetEnabledNode(i); + const size_t skeletonJointIndex = actorInstance->GetEnabledNode(i); const bool inPlace = (settings.m_inPlace && skeleton->GetNode(skeletonJointIndex)->GetIsRootNode()); // Sample the interpolated data. Transform result; - const AZ::u32 jointDataIndex = jointLinks[skeletonJointIndex]; - if (jointDataIndex != InvalidIndex32 && !inPlace) + const size_t jointDataIndex = jointLinks[skeletonJointIndex]; + if (jointDataIndex != InvalidIndex && !inPlace) { const StaticJointData& staticJointData = m_staticJointData[jointDataIndex]; const JointData& jointData = m_jointData[jointDataIndex]; @@ -234,7 +234,7 @@ namespace EMotionFX } else { - if (m_additive && jointDataIndex == InvalidIndex32) + if (m_additive && jointDataIndex == InvalidIndex) { result = Transform::CreateIdentity(); } @@ -268,8 +268,8 @@ namespace EMotionFX // Output morph target weights. const MorphSetupInstance* morphSetup = actorInstance->GetMorphSetupInstance(); - const AZ::u32 numMorphTargets = morphSetup->GetNumMorphTargets(); - for (AZ::u32 i = 0; i < numMorphTargets; ++i) + const size_t numMorphTargets = morphSetup->GetNumMorphTargets(); + for (size_t i = 0; i < numMorphTargets; ++i) { const AZ::u32 morphTargetId = morphSetup->GetMorphTarget(i)->GetID(); const AZ::Outcome morphIndex = FindMorphIndexByNameId(morphTargetId); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MotionData/UniformMotionData.h b/Gems/EMotionFX/Code/EMotionFX/Source/MotionData/UniformMotionData.h index ada4b91d95..40674cf2d1 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MotionData/UniformMotionData.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MotionData/UniformMotionData.h @@ -53,7 +53,7 @@ namespace EMotionFX const char* GetSceneSettingsName() const override; // Overloaded. - Transform SampleJointTransform(const SampleSettings& settings, AZ::u32 jointSkeletonIndex) const override; + Transform SampleJointTransform(const SampleSettings& settings, size_t jointSkeletonIndex) const override; void SamplePose(const SampleSettings& settings, Pose* outputPose) const override; float SampleMorph(float sampleTime, size_t morphDataIndex) const override; float SampleFloat(float sampleTime, size_t floatDataIndex) const override; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MotionInstance.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MotionInstance.cpp index 292aef9d54..3cefe9e513 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MotionInstance.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MotionInstance.cpp @@ -33,7 +33,7 @@ namespace EMotionFX m_motion = motion; m_actorInstance = actorInstance; - m_id = MCore::GetIDGenerator().GenerateID(); + m_id = aznumeric_caster(MCore::GetIDGenerator().GenerateID()); SetDeleteOnZeroWeight(true); SetCanOverwrite(true); @@ -819,7 +819,7 @@ namespace EMotionFX } // calculate a world space transformation for a given node by sampling the motion at a given time - void MotionInstance::CalcGlobalTransform(const AZStd::vector& hierarchyPath, float timeValue, Transform* outTransform) const + void MotionInstance::CalcGlobalTransform(const AZStd::vector& hierarchyPath, float timeValue, Transform* outTransform) const { Actor* actor = m_actorInstance->GetActor(); Skeleton* skeleton = actor->GetSkeleton(); @@ -829,10 +829,10 @@ namespace EMotionFX outTransform->Identity(); // iterate from root towards the node (so backwards in the array) - for (int32 i = hierarchyPath.size() - 1; i >= 0; --i) + for (auto iter = rbegin(hierarchyPath); iter != rend(hierarchyPath); ++iter) { // get the current node index - const AZ::u32 nodeIndex = hierarchyPath[i]; + const size_t nodeIndex = *iter; m_motion->CalcNodeTransform(this, &subMotionTransform, actor, skeleton->GetNode(nodeIndex), timeValue, GetRetargetingEnabled()); // multiply parent transform with the current node's transform @@ -879,7 +879,7 @@ namespace EMotionFX } // get the motion extraction node index - const AZ::u32 motionExtractionNodeIndex = motionExtractNode->GetNodeIndex(); + const size_t motionExtractionNodeIndex = motionExtractNode->GetNodeIndex(); // get the current and previous time value from the motion instance float curTimeValue = GetCurrentTime(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MotionInstance.h b/Gems/EMotionFX/Code/EMotionFX/Source/MotionInstance.h index d0f2d1d3fb..59bd08d248 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MotionInstance.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MotionInstance.h @@ -696,13 +696,13 @@ namespace EMotionFX * Get the event handler at the given index. * @result A pointer to the event handler at the given index. */ - MotionInstanceEventHandler* GetEventHandler(AZ::u32 index) const; + MotionInstanceEventHandler* GetEventHandler(size_t index) const; /** * Get the number of event handlers. * @result The number of event handlers assigned to the motion instance. */ - AZ::u32 GetNumEventHandlers() const; + size_t GetNumEventHandlers() const; //-------------------------------- @@ -821,7 +821,7 @@ namespace EMotionFX void CalcRelativeTransform(Node* rootNode, float curTime, float oldTime, Transform* outTransform) const; bool ExtractMotion(Transform& outTrajectoryDelta); - void CalcGlobalTransform(const AZStd::vector& hierarchyPath, float timeValue, Transform* outTransform) const; + void CalcGlobalTransform(const AZStd::vector& hierarchyPath, float timeValue, Transform* outTransform) const; void ResetTimes(); AZ_DEPRECATED(void CalcNewTimeAfterUpdate(float timePassed, float* outNewTime) const, "MotionInstance::CalcNewTimeAfterUpdate has been deprecated, please use MotionInstance::CalcPlayStateAfterUpdate(timeDelta).m_currentTime instead."); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MotionInstancePool.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MotionInstancePool.cpp index f2abc5f5de..d31d81fe7a 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MotionInstancePool.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MotionInstancePool.cpp @@ -65,10 +65,9 @@ namespace EMotionFX MCORE_ASSERT(mData == nullptr); // delete all subpools - const uint32 numSubPools = mSubPools.size(); - for (uint32 s = 0; s < numSubPools; ++s) + for (SubPool* mSubPool : mSubPools) { - delete mSubPools[s]; + delete mSubPool; } mSubPools.clear(); @@ -114,7 +113,7 @@ namespace EMotionFX // init the motion instance pool - void MotionInstancePool::Init(uint32 numInitialInstances, EPoolType poolType, uint32 subPoolSize) + void MotionInstancePool::Init(size_t numInitialInstances, EPoolType poolType, size_t subPoolSize) { if (mPool) { @@ -141,7 +140,7 @@ namespace EMotionFX { mPool->mData = (uint8*)MCore::Allocate(numInitialInstances * sizeof(MotionInstance), EMFX_MEMCATEGORY_MOTIONINSTANCEPOOL);// alloc space mPool->mFreeList.resize_no_construct(numInitialInstances); - for (uint32 i = 0; i < numInitialInstances; ++i) + for (size_t i = 0; i < numInitialInstances; ++i) { void* memLocation = (void*)(mPool->mData + i * sizeof(MotionInstance)); mPool->mFreeList[i].mAddress = memLocation; @@ -158,7 +157,7 @@ namespace EMotionFX subPool->mNumInstances = numInitialInstances; mPool->mFreeList.resize_no_construct(numInitialInstances); - for (uint32 i = 0; i < numInitialInstances; ++i) + for (size_t i = 0; i < numInitialInstances; ++i) { mPool->mFreeList[i].mAddress = (void*)(subPool->mData + i * sizeof(MotionInstance)); mPool->mFreeList[i].mSubPool = subPool; @@ -203,14 +202,14 @@ namespace EMotionFX // we have no more free attributes left if (mPool->mPoolType == POOLTYPE_DYNAMIC) // we're dynamic, so we can just create new ones { - const uint32 numInstances = mPool->mSubPoolSize; + const size_t numInstances = mPool->mSubPoolSize; mPool->mNumInstances += numInstances; SubPool* subPool = new SubPool(); subPool->mData = (uint8*)MCore::Allocate(numInstances * sizeof(MotionInstance), EMFX_MEMCATEGORY_MOTIONINSTANCEPOOL);// alloc space subPool->mNumInstances = numInstances; - const uint32 startIndex = mPool->mFreeList.size(); + const size_t startIndex = mPool->mFreeList.size(); //mPool->mFreeList.Reserve( numInstances * 2 ); if (mPool->mFreeList.capacity() < mPool->mNumInstances) { @@ -218,7 +217,7 @@ namespace EMotionFX } mPool->mFreeList.resize_no_construct(startIndex + numInstances); - for (uint32 i = 0; i < numInstances; ++i) + for (size_t i = 0; i < numInstances; ++i) { void* memAddress = (void*)(subPool->mData + i * sizeof(MotionInstance)); mPool->mFreeList[i + startIndex].mAddress = memAddress; @@ -290,12 +289,12 @@ namespace EMotionFX Lock(); MCore::LogInfo("EMotionFX::MotionInstancePool::LogMemoryStats() - Logging motion instance pool info"); - const uint32 numFree = mPool->mFreeList.size(); - uint32 numUsed = mPool->mNumUsedInstances; - uint32 memUsage = 0; - uint32 usedMemUsage = 0; - uint32 totalMemUsage = 0; - uint32 totalUsedInstancesMemUsage = 0; + const size_t numFree = mPool->mFreeList.size(); + size_t numUsed = mPool->mNumUsedInstances; + size_t memUsage = 0; + size_t usedMemUsage = 0; + size_t totalMemUsage = 0; + size_t totalUsedInstancesMemUsage = 0; if (mPool->mPoolType == POOLTYPE_STATIC) { @@ -375,13 +374,13 @@ namespace EMotionFX { Lock(); - for (uint32 i = 0; i < mPool->mSubPools.size(); ) + for (size_t i = 0; i < mPool->mSubPools.size(); ) { SubPool* subPool = mPool->mSubPools[i]; if (subPool->mNumInUse == 0) { // remove all free allocations - for (uint32 a = 0; a < mPool->mFreeList.size(); ) + for (size_t a = 0; a < mPool->mFreeList.size(); ) { if (mPool->mFreeList[a].mSubPool == subPool) { diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MotionInstancePool.h b/Gems/EMotionFX/Code/EMotionFX/Source/MotionInstancePool.h index 8cb675bb08..e257640e33 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MotionInstancePool.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MotionInstancePool.h @@ -41,7 +41,7 @@ namespace EMotionFX static MotionInstancePool* Create(); - void Init(uint32 numInitialInstances = 256, EPoolType poolType = POOLTYPE_DYNAMIC, uint32 subPoolSize = 512); // auto called on EMotion FX init + void Init(size_t numInitialInstances = 256, EPoolType poolType = POOLTYPE_DYNAMIC, size_t subPoolSize = 512); // auto called on EMotion FX init // with lock MotionInstance* RequestNew(Motion* motion, ActorInstance* actorInstance); @@ -69,8 +69,8 @@ namespace EMotionFX ~SubPool(); uint8* mData; - uint32 mNumInstances; - uint32 mNumInUse; + size_t mNumInstances; + size_t mNumInUse; }; struct EMFX_API MemLocation @@ -88,9 +88,9 @@ namespace EMotionFX ~Pool(); uint8* mData; - uint32 mNumInstances; - uint32 mNumUsedInstances; - uint32 mSubPoolSize; + size_t mNumInstances; + size_t mNumUsedInstances; + size_t mSubPoolSize; AZStd::vector mFreeList; AZStd::vector mSubPools; EPoolType mPoolType; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MotionLayerSystem.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MotionLayerSystem.cpp index 9cda792890..4c3ba95e59 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MotionLayerSystem.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MotionLayerSystem.cpp @@ -6,6 +6,7 @@ * */ +#include #include #include #include @@ -48,12 +49,11 @@ namespace EMotionFX void MotionLayerSystem::RemoveAllLayerPasses(bool delFromMem) { // delete all layer passes - const uint32 numLayerPasses = mLayerPasses.size(); - for (uint32 i = 0; i < numLayerPasses; ++i) + for (LayerPass* mLayerPasse : mLayerPasses) { if (delFromMem) { - mLayerPasses[i]->Destroy(); + mLayerPasse->Destroy(); } } @@ -65,12 +65,12 @@ namespace EMotionFX void MotionLayerSystem::StartMotion(MotionInstance* motion, PlayBackInfo* info) { // check if we have any motions playing already - const uint32 numMotionInstances = mMotionInstances.size(); + const size_t numMotionInstances = mMotionInstances.size(); if (numMotionInstances > 0) { // find the right location in the motion instance array to insert this motion instance - uint32 insertPos = FindInsertPos(motion->GetPriorityLevel()); - if (insertPos != MCORE_INVALIDINDEX32) + size_t insertPos = FindInsertPos(motion->GetPriorityLevel()); + if (insertPos != InvalidIndex) { mMotionInstances.emplace(AZStd::next(begin(mMotionInstances), insertPos), motion); } @@ -97,18 +97,13 @@ namespace EMotionFX // find the location where to insert a new motion with a given priority - uint32 MotionLayerSystem::FindInsertPos(uint32 priorityLevel) const + size_t MotionLayerSystem::FindInsertPos(size_t priorityLevel) const { - const uint32 numInstances = mMotionInstances.size(); - for (uint32 i = 0; i < numInstances; ++i) + const auto* foundInsertPosition = AZStd::lower_bound(begin(mMotionInstances), end(mMotionInstances), priorityLevel, [](const MotionInstance* motionInstance, size_t level) { - if (mMotionInstances[i]->GetPriorityLevel() <= priorityLevel) - { - return i; - } - } - - return MCORE_INVALIDINDEX32; + return motionInstance->GetPriorityLevel() < level; + }); + return foundInsertPosition != end(mMotionInstances) ? AZStd::distance(begin(mMotionInstances), foundInsertPosition) : InvalidIndex; } @@ -125,10 +120,9 @@ namespace EMotionFX mMotionQueue->Update(); // process all layer passes - const uint32 numPasses = mLayerPasses.size(); - for (uint32 i = 0; i < numPasses; ++i) + for (LayerPass* mLayerPasse : mLayerPasses) { - mLayerPasses[i]->Process(); + mLayerPasse->Process(); } // process the repositioning as last @@ -151,7 +145,7 @@ namespace EMotionFX // update the motion tree void MotionLayerSystem::UpdateMotionTree() { - for (uint32 i = 0; i < mMotionInstances.size(); ++i) + for (size_t i = 0; i < mMotionInstances.size(); ++i) { MotionInstance* source = mMotionInstances[i]; @@ -233,8 +227,8 @@ namespace EMotionFX if (source->GetCanOverwrite()) { // remove all motions that got overwritten by the current one - const uint32 numToRemove = mMotionInstances.size() - (i + 1); - for (uint32 a = 0; a < numToRemove; ++a) + const size_t numToRemove = mMotionInstances.size() - (i + 1); + for (size_t a = 0; a < numToRemove; ++a) { RemoveMotionInstance(mMotionInstances[i + 1]); } @@ -246,14 +240,14 @@ namespace EMotionFX // remove all layers below a given layer - uint32 MotionLayerSystem::RemoveLayersBelow(MotionInstance* source) + size_t MotionLayerSystem::RemoveLayersBelow(MotionInstance* source) { - uint32 numRemoved = 0; + size_t numRemoved = 0; // start from the bottom up - for (uint32 i = mMotionInstances.size() - 1; i != MCORE_INVALIDINDEX32;) + for (auto iter = rbegin(mMotionInstances); iter != rend(mMotionInstances); ++iter) { - MotionInstance* curInstance = mMotionInstances[i]; + MotionInstance* curInstance = *iter; // if we reached the current motion instance we are done if (curInstance == source) @@ -263,7 +257,6 @@ namespace EMotionFX numRemoved++; RemoveMotionInstance(curInstance); - i--; } return numRemoved; @@ -274,21 +267,11 @@ namespace EMotionFX MotionInstance* MotionLayerSystem::FindFirstNonMixingMotionInstance() const { // if there aren't any motion instances, return nullptr - const uint32 numInstances = mMotionInstances.size(); - if (numInstances == 0) + const auto foundMotionInstance = AZStd::find_if(begin(mMotionInstances), end(mMotionInstances), [](const MotionInstance* motionInstance) { - return nullptr; - } - - for (uint32 i = 0; i < numInstances; ++i) - { - if (mMotionInstances[i]->GetIsMixing() == false) - { - return mMotionInstances[i]; - } - } - - return nullptr; + return !motionInstance->GetIsMixing(); + }); + return foundMotionInstance != end(mMotionInstances) ? *foundMotionInstance : nullptr; } @@ -304,7 +287,7 @@ namespace EMotionFX Pose* tempActorPose = &tempAnimGraphPose->GetPose(); - const uint32 numMotionInstances = mMotionInstances.size(); + const size_t numMotionInstances = mMotionInstances.size(); if (numMotionInstances > 0) { if (numMotionInstances > 1) @@ -314,10 +297,10 @@ namespace EMotionFX finalPose->InitFromBindPose(mActorInstance); // blend the layers - for (uint32 i = numMotionInstances - 1; i != MCORE_INVALIDINDEX32; --i) + for (auto iter = rbegin(mMotionInstances); iter != rend(mMotionInstances); ++iter) { // skip inactive motion instances - MotionInstance* instance = mMotionInstances[i]; // the motion to be blended + MotionInstance* instance = *iter; // the motion to be blended if (instance->GetIsActive() == false || instance->GetWeight() < 0.0001f) { continue; @@ -406,7 +389,7 @@ namespace EMotionFX // remove a given pass - void MotionLayerSystem::RemoveLayerPass(uint32 nr, bool delFromMem) + void MotionLayerSystem::RemoveLayerPass(size_t nr, bool delFromMem) { if (delFromMem) { @@ -433,7 +416,7 @@ namespace EMotionFX // insert a layer pass at a given position - void MotionLayerSystem::InsertLayerPass(uint32 insertPos, LayerPass* pass) + void MotionLayerSystem::InsertLayerPass(size_t insertPos, LayerPass* pass) { mLayerPasses.emplace(AZStd::next(begin(mLayerPasses), insertPos), pass); } @@ -465,7 +448,7 @@ namespace EMotionFX } - LayerPass* MotionLayerSystem::GetLayerPass(uint32 index) const + LayerPass* MotionLayerSystem::GetLayerPass(size_t index) const { return mLayerPasses[index]; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MotionLayerSystem.h b/Gems/EMotionFX/Code/EMotionFX/Source/MotionLayerSystem.h index e207f48fd5..be14780341 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MotionLayerSystem.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MotionLayerSystem.h @@ -95,7 +95,7 @@ namespace EMotionFX * @param source The layer to remove all layers below from. So this does not remove the source layer itself. * @result Returns the number of removed layers. */ - uint32 RemoveLayersBelow(MotionInstance* source); + size_t RemoveLayersBelow(MotionInstance* source); /** * Update the motion tree. @@ -118,11 +118,11 @@ namespace EMotionFX /** * Find the location where to insert a motion layer with a given priority level. - * When MCORE_INVALIDINDEX32 is returned, it needs to be inserted at the bottom of the motion tree. + * When InvalidIndex is returned, it needs to be inserted at the bottom of the motion tree. * @param priorityLevel The priority level of the motion instance you want to insert. - * @result The insert pos in the list of motion instances, or MCORE_INVALIDINDEX32 when the new layer has to be inserted at the bottom of the tree. + * @result The insert pos in the list of motion instances, or InvalidIndex when the new layer has to be inserted at the bottom of the tree. */ - uint32 FindInsertPos(uint32 priorityLevel) const; + size_t FindInsertPos(size_t priorityLevel) const; /** * Remove all layer passes. @@ -147,7 +147,7 @@ namespace EMotionFX * @param nr The layer pass number to remove. * @param delFromMem When set to true, the layer passes will also be deleted from memory. */ - void RemoveLayerPass(uint32 nr, bool delFromMem = true); + void RemoveLayerPass(size_t nr, bool delFromMem = true); /** * Remove a given layer pass by pointer. @@ -161,7 +161,7 @@ namespace EMotionFX * @param insertPos The index position to insert the layer pass. * @param pass The layer pass to insert. */ - void InsertLayerPass(uint32 insertPos, LayerPass* pass); + void InsertLayerPass(size_t insertPos, LayerPass* pass); /** * Deletes the motion based actor repositioning layer pass, which is always there on default. @@ -175,7 +175,7 @@ namespace EMotionFX * @param index The layer pass number, which must be in range of [0..GetNumLayerPasses()-1]. * @result A pointer to the layer pass object. */ - LayerPass* GetLayerPass(uint32 index) const; + LayerPass* GetLayerPass(size_t index) const; private: diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MotionManager.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MotionManager.cpp index b193c58175..1954d23dc3 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MotionManager.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MotionManager.cpp @@ -95,245 +95,137 @@ namespace EMotionFX // find the motion and return a pointer, nullptr if the motion is not in Motion* MotionManager::FindMotionByName(const char* motionName, bool isTool) const { - // get the number of motions and iterate through them - const uint32 numMotions = mMotions.size(); - for (uint32 i = 0; i < numMotions; ++i) + const auto foundMotion = AZStd::find_if(begin(mMotions), end(mMotions), [motionName, isTool](const auto& motion) { - if (mMotions[i]->GetIsOwnedByRuntime() == isTool) - { - continue; - } - - // compare the motion names - if (mMotions[i]->GetNameString() == motionName) - { - return mMotions[i]; - } - } - - return nullptr; + return motion->GetIsOwnedByRuntime() != isTool && motion->GetNameString() == motionName; + }); + return foundMotion != end(mMotions) ? *foundMotion : nullptr; } // find the motion and return a pointer, nullptr if the motion is not in Motion* MotionManager::FindMotionByFileName(const char* fileName, bool isTool) const { - // get the number of motions and iterate through them - const uint32 numMotions = mMotions.size(); - for (uint32 i = 0; i < numMotions; ++i) + const auto foundMotion = AZStd::find_if(begin(mMotions), end(mMotions), [fileName, isTool](const auto& motion) { - if (mMotions[i]->GetIsOwnedByRuntime() == isTool) - { - continue; - } - - // compare the motion names - if (AzFramework::StringFunc::Equal(mMotions[i]->GetFileNameString().c_str(), fileName, false /* no case */)) - { - return mMotions[i]; - } - } - - return nullptr; + return motion->GetIsOwnedByRuntime() != isTool && + AzFramework::StringFunc::Equal(motion->GetFileNameString().c_str(), fileName, false /* no case */); + }); + return foundMotion != end(mMotions) ? *foundMotion : nullptr; } // find the motion set by filename and return a pointer, nullptr if the motion set is not in yet MotionSet* MotionManager::FindMotionSetByFileName(const char* fileName, bool isTool) const { - // get the number of motion sets and iterate through them - const uint32 numMotionSets = mMotionSets.size(); - for (uint32 i = 0; i < numMotionSets; ++i) + const auto foundMotionSet = AZStd::find_if(begin(mMotionSets), end(mMotionSets), [fileName, isTool](const auto& motionSet) { - MotionSet* motionSet = mMotionSets[i]; - if (motionSet->GetIsOwnedByRuntime() == isTool) - { - continue; - } - - // compare the motion set filenames - if (AzFramework::StringFunc::Equal(motionSet->GetFilename(), fileName)) - { - return motionSet; - } - } - - return nullptr; + return motionSet->GetIsOwnedByRuntime() != isTool && + AzFramework::StringFunc::Equal(motionSet->GetFilename(), fileName); + }); + return foundMotionSet != end(mMotionSets) ? *foundMotionSet : nullptr; } // find the motion set and return a pointer, nullptr if the motion set has not been found MotionSet* MotionManager::FindMotionSetByName(const char* name, bool isOwnedByRuntime) const { - // get the number of motion sets and iterate through them - const uint32 numMotionSets = mMotionSets.size(); - for (uint32 i = 0; i < numMotionSets; ++i) + const auto foundMotionSet = AZStd::find_if(begin(mMotionSets), end(mMotionSets), [name, isOwnedByRuntime](const auto& motionSet) { - MotionSet* motionSet = mMotionSets[i]; - - if (motionSet->GetIsOwnedByRuntime() == isOwnedByRuntime) - { - // compare the motion set names - if (AzFramework::StringFunc::Equal(motionSet->GetName(), name)) - { - return motionSet; - } - } - } - - return nullptr; + return motionSet->GetIsOwnedByRuntime() == isOwnedByRuntime && + AzFramework::StringFunc::Equal(motionSet->GetName(), name); + }); + return foundMotionSet != end(mMotionSets) ? *foundMotionSet : nullptr; } // find the motion index for the given motion - uint32 MotionManager::FindMotionIndexByName(const char* motionName, bool isTool) const + size_t MotionManager::FindMotionIndexByName(const char* motionName, bool isTool) const { - // get the number of motions and iterate through them - const uint32 numMotions = mMotions.size(); - for (uint32 i = 0; i < numMotions; ++i) + const auto foundMotion = AZStd::find_if(begin(mMotions), end(mMotions), [motionName, isTool](const auto& motion) { - if (mMotions[i]->GetIsOwnedByRuntime() == isTool) - { - continue; - } - - // compare the motion names - if (mMotions[i]->GetNameString() == motionName) - { - return i; - } - } - - return MCORE_INVALIDINDEX32; + return motion->GetIsOwnedByRuntime() != isTool && motion->GetNameString() == motionName; + }); + return foundMotion != end(mMotions) ? AZStd::distance(begin(mMotions), foundMotion) : InvalidIndex; } // find the motion set index for the given motion - uint32 MotionManager::FindMotionSetIndexByName(const char* name, bool isTool) const + size_t MotionManager::FindMotionSetIndexByName(const char* name, bool isTool) const { - // get the number of motions and iterate through them - const uint32 numMotionSets = mMotionSets.size(); - for (uint32 i = 0; i < numMotionSets; ++i) + const auto foundMotionSet = AZStd::find_if(begin(mMotionSets), end(mMotionSets), [name, isTool](const MotionSet* motionSet) { - MotionSet* motionSet = mMotionSets[i]; - - if (motionSet->GetIsOwnedByRuntime() == isTool) - { - continue; - } - - // compare the motion set names - if (AzFramework::StringFunc::Equal(motionSet->GetName(), name)) - { - return i; - } - } - - return MCORE_INVALIDINDEX32; + return motionSet->GetIsOwnedByRuntime() != isTool && + AzFramework::StringFunc::Equal(motionSet->GetName(), name); + }); + return foundMotionSet != end(mMotionSets) ? AZStd::distance(begin(mMotionSets), foundMotionSet) : InvalidIndex; } // find the motion index for the given motion - uint32 MotionManager::FindMotionIndexByID(uint32 id) const + size_t MotionManager::FindMotionIndexByID(uint32 id) const { - // get the number of motions and iterate through them - const uint32 numMotions = mMotions.size(); - for (uint32 i = 0; i < numMotions; ++i) + const auto foundMotion = AZStd::find_if(begin(mMotions), end(mMotions), [id](const Motion* motion) { - if (mMotions[i]->GetID() == id) - { - return i; - } - } - - return MCORE_INVALIDINDEX32; + return motion->GetID() == id; + }); + return foundMotion != end(mMotions) ? AZStd::distance(begin(mMotions), foundMotion) : InvalidIndex; + // get the number of motions and iterate through them } // find the motion set index - uint32 MotionManager::FindMotionSetIndexByID(uint32 id) const + size_t MotionManager::FindMotionSetIndexByID(uint32 id) const { - // get the number of motion sets and iterate through them - const uint32 numMotionSets = mMotionSets.size(); - for (uint32 i = 0; i < numMotionSets; ++i) + const auto foundMotionSet = AZStd::find_if(begin(mMotionSets), end(mMotionSets), [id](const MotionSet* motionSet) { - // compare the motion names - if (mMotionSets[i]->GetID() == id) - { - return i; - } - } - - return MCORE_INVALIDINDEX32; + return motionSet->GetID() == id; + }); + return foundMotionSet != end(mMotionSets) ? AZStd::distance(begin(mMotionSets), foundMotionSet) : InvalidIndex; } // find the motion and return a pointer, nullptr if the motion is not in Motion* MotionManager::FindMotionByID(uint32 id) const { - // get the number of motions and iterate through them - const uint32 numMotions = mMotions.size(); - for (uint32 i = 0; i < numMotions; ++i) + const auto foundMotion = AZStd::find_if(begin(mMotions), end(mMotions), [id](const Motion* motion) { - if (mMotions[i]->GetID() == id) - { - return mMotions[i]; - } - } - - return nullptr; + return motion->GetID() == id; + }); + return foundMotion != end(mMotions) ? *foundMotion : nullptr; } // find the motion set with the given and return it, nullptr if the motion set won't be found MotionSet* MotionManager::FindMotionSetByID(uint32 id) const { - // get the number of motion sets and iterate through them - const uint32 numMotionSets = mMotionSets.size(); - for (uint32 i = 0; i < numMotionSets; ++i) + const auto foundMotionSet = AZStd::find_if(begin(mMotionSets), end(mMotionSets), [id](const MotionSet* motionSet) { - if (mMotionSets[i]->GetID() == id) - { - return mMotionSets[i]; - } - } - - return nullptr; + return motionSet->GetID() == id; + }); + return foundMotionSet != end(mMotionSets) ? *foundMotionSet : nullptr; } // find the motion set index and return it - uint32 MotionManager::FindMotionSetIndex(MotionSet* motionSet) const + size_t MotionManager::FindMotionSetIndex(MotionSet* motionSet) const { - // get the number of motion sets and iterate through them - const uint32 numMotionSets = mMotionSets.size(); - for (uint32 i = 0; i < numMotionSets; ++i) + const auto foundMotionSet = AZStd::find_if(begin(mMotionSets), end(mMotionSets), [motionSet](const MotionSet* ms) { - if (mMotionSets[i] == motionSet) - { - return i; - } - } - - return MCORE_INVALIDINDEX32; + return ms == motionSet; + }); + return foundMotionSet != end(mMotionSets) ? AZStd::distance(begin(mMotionSets), foundMotionSet) : InvalidIndex; } // find the motion index for the given motion - uint32 MotionManager::FindMotionIndex(Motion* motion) const + size_t MotionManager::FindMotionIndex(Motion* motion) const { - // get the number of motions and iterate through them - const uint32 numMotions = mMotions.size(); - for (uint32 i = 0; i < numMotions; ++i) + const auto foundMotion = AZStd::find_if(begin(mMotions), end(mMotions), [motion](const Motion* m) { - // compare the motions - if (motion == mMotions[i]) - { - return i; - } - } - - return MCORE_INVALIDINDEX32; + return m == motion; + }); + return foundMotion != end(mMotions) ? AZStd::distance(begin(mMotions), foundMotion) : InvalidIndex; } @@ -380,25 +272,13 @@ namespace EMotionFX // find the index by filename - uint32 MotionManager::FindMotionIndexByFileName(const char* fileName, bool isTool) const + size_t MotionManager::FindMotionIndexByFileName(const char* fileName, bool isTool) const { - // get the number of motions and iterate through them - const uint32 numMotions = mMotions.size(); - for (uint32 i = 0; i < numMotions; ++i) + const auto foundMotion = AZStd::find_if(begin(mMotions), end(mMotions), [fileName, isTool](const Motion* motion) { - if (mMotions[i]->GetIsOwnedByRuntime() == isTool) - { - continue; - } - - // compare the motions - if (mMotions[i]->GetFileNameString() == fileName) - { - return i; - } - } - - return MCORE_INVALIDINDEX32; + return motion->GetIsOwnedByRuntime() != isTool && motion->GetFileNameString() == fileName; + }); + return foundMotion != end(mMotions) ? AZStd::distance(begin(mMotions), foundMotion) : InvalidIndex; } @@ -419,8 +299,8 @@ namespace EMotionFX AnimGraphInstance* animGraphInstance = animGraph->GetAnimGraphInstance(b); // reset all motion nodes that use this motion - const uint32 numNodes = animGraph->GetNumNodes(); - for (uint32 m = 0; m < numNodes; ++m) + const size_t numNodes = animGraph->GetNumNodes(); + for (size_t m = 0; m < numNodes; ++m) { AnimGraphNode* node = animGraph->GetNode(m); AnimGraphNodeData* uniqueData = static_cast(animGraphInstance->GetUniqueObjectData(node->GetObjectIndex())); @@ -453,26 +333,25 @@ namespace EMotionFX // remove the motion with the given index from the motion manager - bool MotionManager::RemoveMotionWithoutLock(uint32 index, bool delFromMemory) + bool MotionManager::RemoveMotionWithoutLock(size_t index, bool delFromMemory) { - if (index == MCORE_INVALIDINDEX32) + if (index == InvalidIndex) { return false; } - uint32 i; Motion* motion = mMotions[index]; // stop all motion instances of the motion to delete - const uint32 numActorInstances = GetActorManager().GetNumActorInstances(); - for (i = 0; i < numActorInstances; ++i) + const size_t numActorInstances = GetActorManager().GetNumActorInstances(); + for (size_t i = 0; i < numActorInstances; ++i) { ActorInstance* actorInstance = GetActorManager().GetActorInstance(i); MotionSystem* motionSystem = actorInstance->GetMotionSystem(); MCORE_ASSERT(actorInstance->GetMotionSystem()); // instances and iterate through the motion instances - for (uint32 j = 0; j < motionSystem->GetNumMotionInstances(); ) + for (size_t j = 0; j < motionSystem->GetNumMotionInstances(); ) { MotionInstance* motionInstance = motionSystem->GetMotionInstance(j); @@ -491,11 +370,8 @@ namespace EMotionFX } // Reset all motion entries in the motion sets of the current motion. - const uint32 numMotionSets = mMotionSets.size(); - for (i = 0; i < numMotionSets; ++i) + for (const MotionSet* motionSet : mMotionSets) { - MotionSet* motionSet = mMotionSets[i]; - const EMotionFX::MotionSet::MotionEntries& motionEntries = motionSet->GetMotionEntries(); for (const auto& item : motionEntries) { @@ -509,8 +385,8 @@ namespace EMotionFX } // stop all motion instances of the motion to delete inside the motion nodes and reset their unique data - const uint32 numAnimGraphs = GetAnimGraphManager().GetNumAnimGraphs(); - for (i = 0; i < numAnimGraphs; ++i) + const size_t numAnimGraphs = GetAnimGraphManager().GetNumAnimGraphs(); + for (size_t i = 0; i < numAnimGraphs; ++i) { AnimGraph* animGraph = GetAnimGraphManager().GetAnimGraph(i); ResetMotionNodes(animGraph, motion); @@ -542,9 +418,9 @@ namespace EMotionFX // remove the motion set with the given index from the motion manager - bool MotionManager::RemoveMotionSetWithoutLock(uint32 index, bool delFromMemory) + bool MotionManager::RemoveMotionSetWithoutLock(size_t index, bool delFromMemory) { - if (index == MCORE_INVALIDINDEX32) + if (index == InvalidIndex) { return false; } @@ -598,16 +474,15 @@ namespace EMotionFX // calculate the number of root motion sets - uint32 MotionManager::CalcNumRootMotionSets() const + size_t MotionManager::CalcNumRootMotionSets() const { - uint32 result = 0; + size_t result = 0; // get the number of motion sets and iterate through them - const uint32 numMotionSets = mMotionSets.size(); - for (uint32 i = 0; i < numMotionSets; ++i) + for (const MotionSet* mMotionSet : mMotionSets) { // sum up the root motion sets - if (mMotionSets[i]->GetParentSet() == nullptr) + if (mMotionSet->GetParentSet() == nullptr) { result++; } @@ -618,32 +493,13 @@ namespace EMotionFX // find the given root motion set - MotionSet* MotionManager::FindRootMotionSet(uint32 index) + MotionSet* MotionManager::FindRootMotionSet(size_t index) { - uint32 currentIndex = 0; - - // get the number of motion sets and iterate through them - const uint32 numMotionSets = mMotionSets.size(); - for (uint32 i = 0; i < numMotionSets; ++i) + auto foundRootMotionSet = AZStd::find_if(begin(mMotionSets), end(mMotionSets), [iter = index](const MotionSet* motionSet) mutable { - // get the current motion set - MotionSet* motionSet = mMotionSets[i]; - - // check if we are dealing with a root motion set and skip all others - if (mMotionSets[i]->GetParentSet()) - { - continue; - } - - // compare the indices and return in case we reached it, if not increase the counter - if (currentIndex == index) - { - return motionSet; - } - currentIndex++; - } - - return nullptr; + return motionSet->GetParentSet() == nullptr && iter-- == 0; + }); + return foundRootMotionSet != end(mMotionSets) ? *foundRootMotionSet : nullptr; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MotionManager.h b/Gems/EMotionFX/Code/EMotionFX/Source/MotionManager.h index 98555da9f7..2aad2f72d9 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MotionManager.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MotionManager.h @@ -44,7 +44,7 @@ namespace EMotionFX * @param[in] index The index of the motion. The index must be in range [0, GetNumMotions()-1]. * @return A pointer to the given motion set. */ - MCORE_INLINE Motion* GetMotion(uint32 index) const { return mMotions[index]; } + MCORE_INLINE Motion* GetMotion(size_t index) const { return mMotions[index]; } /** * Get the number of motions in the motion manager. @@ -119,7 +119,7 @@ namespace EMotionFX * @param[in] isTool Set when calling this function from the tools environment (default). * @return The index of the motion with the given name. MCORE_INVALIDINDEX32 in case the motion has not been found. */ - uint32 FindMotionIndexByName(const char* motionName, bool isTool = true) const; + size_t FindMotionIndexByName(const char* motionName, bool isTool = true) const; /** * Find the motion index by file name. @@ -127,21 +127,21 @@ namespace EMotionFX * @param[in] isTool Set when calling this function from the tools environment (default). * @return The index of the motion with the given name. MCORE_INVALIDINDEX32 in case the motion has not been found. */ - uint32 FindMotionIndexByFileName(const char* fileName, bool isTool = true) const; + size_t FindMotionIndexByFileName(const char* fileName, bool isTool = true) const; /** * Find the motion index by id. * @param[in] id The id of the motion. * @return The index of the motion with the given id. MCORE_INVALIDINDEX32 in case the motion has not been found. */ - uint32 FindMotionIndexByID(uint32 id) const; + size_t FindMotionIndexByID(uint32 id) const; /** * Find the index for the given motion. * @param[in] motion A pointer to the motion to search. * @return The index of the motion. MCORE_INVALIDINDEX32 in case the motion has not been found. */ - uint32 FindMotionIndex(Motion* motion) const; + size_t FindMotionIndex(Motion* motion) const; /** * Add a motion set to the motion manager. @@ -154,7 +154,7 @@ namespace EMotionFX * @param[in] index The index of the motion set. The index must be in range [0, GetNumMotionSets()-1]. * @return A pointer to the given motion set. */ - MCORE_INLINE MotionSet* GetMotionSet(uint32 index) const { return mMotionSets[index]; } + MCORE_INLINE MotionSet* GetMotionSet(size_t index) const { return mMotionSets[index]; } /** * Get the number of motion sets in the motion manager. @@ -167,14 +167,14 @@ namespace EMotionFX * This will iterate over all motion sets, check if they have a parent and sum all the root ones. * @return The number of root motion sets. */ - uint32 CalcNumRootMotionSets() const; + size_t CalcNumRootMotionSets() const; /** * Find the root motion set with the given index. * @param[in] index The index of the root motion set. The index must be in range [0, CalcNumRootMotionSets()-1]. * @return A pointer to the given motion set. */ - MotionSet* FindRootMotionSet(uint32 index); + MotionSet* FindRootMotionSet(size_t index); /** * Find motion set by name. @@ -205,21 +205,21 @@ namespace EMotionFX * @param[in] isTool Set when calling this function from the tools environment (default). * @return The index of the motion set with the given name. MCORE_INVALIDINDEX32 in case the motion has not been found. */ - uint32 FindMotionSetIndexByName(const char* name, bool isTool = true) const; + size_t FindMotionSetIndexByName(const char* name, bool isTool = true) const; /** * Find motion set index by id. * @param[in] id The id of the motion set. * @return The index of the motion set with the given id. MCORE_INVALIDINDEX32 in case the motion has not been found. */ - uint32 FindMotionSetIndexByID(uint32 id) const; + size_t FindMotionSetIndexByID(uint32 id) const; /** * Find motion set index for the given motion set. * @param[in] motionSet A pointer to the motion set to search. * @return The index for the given motion set. MCORE_INVALIDINDEX32 in case the motion has not been found. */ - uint32 FindMotionSetIndex(MotionSet* motionSet) const; + size_t FindMotionSetIndex(MotionSet* motionSet) const; bool RemoveMotionSetByName(const char* motionName, bool delFromMemory = true, bool isTool = true); bool RemoveMotionSetByID(uint32 id, bool delFromMemory = true); @@ -249,9 +249,9 @@ namespace EMotionFX * When set to false, it will not be deleted from memory, but only removed from the array of motions. * @return True in case the motion has been removed successfully. False in case the motion has not been found or the removal failed. */ - bool RemoveMotionWithoutLock(uint32 index, bool delFromMemory = true); + bool RemoveMotionWithoutLock(size_t index, bool delFromMemory = true); - bool RemoveMotionSetWithoutLock(uint32 index, bool delFromMemory = true); + bool RemoveMotionSetWithoutLock(size_t index, bool delFromMemory = true); MotionManager(); ~MotionManager() override; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MotionQueue.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MotionQueue.cpp index ea8826fe9a..10b52b1f8b 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MotionQueue.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MotionQueue.cpp @@ -46,7 +46,7 @@ namespace EMotionFX // remove a given entry from the queue - void MotionQueue::RemoveEntry(uint32 nr) + void MotionQueue::RemoveEntry(size_t nr) { if (mMotionSystem->RemoveMotionInstance(mEntries[nr].mMotion) == false) { @@ -61,7 +61,7 @@ namespace EMotionFX void MotionQueue::Update() { // get the number of entries - uint32 numEntries = GetNumEntries(); + size_t numEntries = GetNumEntries(); // if there are entries in the queue if (numEntries == 0) @@ -199,7 +199,7 @@ namespace EMotionFX } - MotionQueue::QueueEntry& MotionQueue::GetEntry(uint32 nr) + MotionQueue::QueueEntry& MotionQueue::GetEntry(size_t nr) { return mEntries[nr]; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MotionQueue.h b/Gems/EMotionFX/Code/EMotionFX/Source/MotionQueue.h index 9978a16bc6..aa30ccab46 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MotionQueue.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MotionQueue.h @@ -99,13 +99,13 @@ namespace EMotionFX * @param nr The queue entry number to get. * @result A reference to the queue entry, with write access. */ - QueueEntry& GetEntry(uint32 nr); + QueueEntry& GetEntry(size_t nr); /** * Remove a given entry from the queue. * @param nr The entry number to remove from the queue. */ - void RemoveEntry(uint32 nr); + void RemoveEntry(size_t nr); /** * Updates the motion queue. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MotionSet.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MotionSet.cpp index fe086b1c25..d8880f6fcc 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MotionSet.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MotionSet.cpp @@ -6,6 +6,8 @@ * */ +#include +#include #include #include #include @@ -151,7 +153,7 @@ namespace EMotionFX , m_autoUnregister(true) , m_dirtyFlag(false) { - m_id = MCore::GetIDGenerator().GenerateID(); + m_id = aznumeric_caster(MCore::GetIDGenerator().GenerateID()); m_callback = aznew MotionSetCallback(this); #if defined(EMFX_DEVELOPMENT_BUILD) @@ -320,18 +322,16 @@ namespace EMotionFX } } - void MotionSet::ReserveMotionEntries(uint32 numMotionEntries) + void MotionSet::ReserveMotionEntries(size_t numMotionEntries) { MCore::LockGuardRecursive lock(m_mutex); - // Not supported yet by the AZStd::unordered_map. - //m_motionEntries.reserve(numMotionEntries); - MCORE_UNUSED(numMotionEntries); + m_motionEntries.reserve(numMotionEntries); } // Find the motion entry for a given motion. - MotionSet::MotionEntry* MotionSet::FindMotionEntry(Motion* motion) const + MotionSet::MotionEntry* MotionSet::FindMotionEntry(const Motion* motion) const { MCore::LockGuardRecursive lock(m_mutex); @@ -642,23 +642,10 @@ namespace EMotionFX { MCore::LockGuardRecursive lock(m_mutex); - // Is the given motion set dirty? - if (m_dirtyFlag) + return m_dirtyFlag || AZStd::any_of(begin(m_childSets), end(m_childSets), [](const MotionSet* childSet) { - return true; - } - - // Is any of the child motion sets dirty? - for (MotionSet* childSet : m_childSets) - { - if (childSet->GetDirtyFlag()) - { - return true; - } - } - - // Neither the given set nor any of the child sets is dirty. - return false; + return childSet->GetDirtyFlag(); + }); } @@ -735,38 +722,25 @@ namespace EMotionFX } - uint32 MotionSet::GetNumChildSets() const + size_t MotionSet::GetNumChildSets() const { MCore::LockGuardRecursive lock(m_mutex); - uint32 childSetSize = 0; - for (const MotionSet* motionSet : m_childSets) + return AZStd::accumulate(begin(m_childSets), end(m_childSets), size_t{0}, [](size_t total, const MotionSet* motionSet) { - if (!motionSet->GetIsOwnedByRuntime()) - { - ++childSetSize; - } - } - return childSetSize; + return total + motionSet->GetIsOwnedByRuntime(); + }); } - MotionSet* MotionSet::GetChildSet(uint32 index) const + MotionSet* MotionSet::GetChildSet(size_t index) const { MCore::LockGuardRecursive lock(m_mutex); - uint32 currentIndex = 0; - for (MotionSet* motionSet : m_childSets) + const auto foundChildSet = AZStd::find_if(begin(m_childSets), end(m_childSets), [iter = index](const MotionSet* motionSet) mutable { - if (!motionSet->GetIsOwnedByRuntime()) - { - if (currentIndex == index) - { - return motionSet; - } - ++currentIndex; - } - } - return nullptr; + return !motionSet->GetIsOwnedByRuntime() && iter-- == 0; + }); + return foundChildSet != end(m_childSets) ? *foundChildSet : nullptr; } void MotionSet::RecursiveGetMotionSets(AZStd::vector& childMotionSets, bool isOwnedByRuntime) const @@ -903,8 +877,8 @@ namespace EMotionFX void MotionSet::RecursiveRewireParentSets(MotionSet* motionSet) { - const AZ::u32 numChildSets = motionSet->GetNumChildSets(); - for (AZ::u32 i = 0; i < numChildSets; ++i) + const size_t numChildSets = motionSet->GetNumChildSets(); + for (size_t i = 0; i < numChildSets; ++i) { MotionSet* childSet = motionSet->GetChildSet(i); childSet->m_parentSet = motionSet; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MotionSet.h b/Gems/EMotionFX/Code/EMotionFX/Source/MotionSet.h index c7402df130..c49dd444f3 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MotionSet.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MotionSet.h @@ -231,7 +231,7 @@ namespace EMotionFX * This will NOT grow the motion entries array as reported by GetNumMotionEntries(). However, it internally pre-allocates memory to make the AddMotionEntry() calls faster. * @param[in] numMotionEntries The number of motion entries to peallocate */ - void ReserveMotionEntries(uint32 numMotionEntries); + void ReserveMotionEntries(size_t numMotionEntries); /** * Remove all motion entries from the motion set. @@ -249,7 +249,7 @@ namespace EMotionFX * @param[in] motion A pointer to the motion. * @result A pointer to the motion entry for the given motion. nullptr in case no motion entry has been found. */ - MotionEntry* FindMotionEntry(Motion* motion) const; + MotionEntry* FindMotionEntry(const Motion* motion) const; MotionEntry* FindMotionEntryById(const AZStd::string& motionId) const; @@ -293,14 +293,14 @@ namespace EMotionFX * Get the number of child motion sets. * @result The number of child sets. */ - uint32 GetNumChildSets() const; + size_t GetNumChildSets() const; /** * Get the given child motion set. * @param[in] index The index of the child set to get. The index must be in range [0, GetNumChildSets()]. * @result A pointer to the child set at the given index. */ - MotionSet* GetChildSet(uint32 index) const; + MotionSet* GetChildSet(size_t index) const; /** * Gets child motion sets recursively. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MotionSystem.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MotionSystem.cpp index fcd243c95f..7619187d23 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MotionSystem.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MotionSystem.cpp @@ -45,7 +45,7 @@ namespace EMotionFX GetEventManager().OnDeleteMotionSystem(this); // delete the motion infos - while (mMotionInstances.size()) + while (!mMotionInstances.empty()) { //delete mMotionInstances.GetLast(); GetMotionInstancePool().Free(mMotionInstances.back()); @@ -173,10 +173,9 @@ namespace EMotionFX // stop all the motions that are currently playing void MotionSystem::StopAllMotions() { - const uint32 numInstances = mMotionInstances.size(); - for (uint32 i = 0; i < numInstances; ++i) + for (MotionInstance* motionInstance : mMotionInstances) { - mMotionInstances[i]->Stop(); + motionInstance->Stop(); } } @@ -184,12 +183,11 @@ namespace EMotionFX // stop all motion instances of a given motion void MotionSystem::StopAllMotions(Motion* motion) { - const uint32 numInstances = mMotionInstances.size(); - for (uint32 i = 0; i < numInstances; ++i) + for (MotionInstance* motionInstance : mMotionInstances) { - if (mMotionInstances[i]->GetMotion()->GetID() == motion->GetID()) + if (motionInstance->GetMotion()->GetID() == motion->GetID()) { - mMotionInstances[i]->Stop(); + motionInstance->Stop(); } } } @@ -230,10 +228,9 @@ namespace EMotionFX void MotionSystem::UpdateMotionInstances(float timePassed) { // update all the motion infos - const uint32 numInstances = mMotionInstances.size(); - for (uint32 i = 0; i < numInstances; ++i) + for (MotionInstance* motionInstance : mMotionInstances) { - mMotionInstances[i]->Update(timePassed); + motionInstance->Update(timePassed); } } @@ -241,64 +238,26 @@ namespace EMotionFX // check if the given motion instance still exists within the actor, so if it hasn't been deleted from memory yet bool MotionSystem::CheckIfIsValidMotionInstance(MotionInstance* instance) const { - // if it's a null pointer, just return - if (instance == nullptr) + return instance && AZStd::any_of(begin(mMotionInstances), end(mMotionInstances), [instance](const MotionInstance* motionInstance) { - return false; - } - - // for all motion instances currently playing in this actor - const uint32 numInstances = mMotionInstances.size(); - for (uint32 i = 0; i < numInstances; ++i) - { - // check if this one is the one we are searching for, if so, return that it is still valid - if (mMotionInstances[i] == instance) // if the memory object appears to be valid - { - if (mMotionInstances[i]->GetID() == instance->GetID()) // check if the id is the same, as a new motion theoretically could have received the same memory address - { - return true; - } - } - } - - // it's not found, this means it has already been deleted from memory and is not valid anymore - return false; + return motionInstance->GetID() == instance->GetID(); + }); } // check if there is a motion instance playing, which is an instance of a specified motion bool MotionSystem::CheckIfIsPlayingMotion(Motion* motion, bool ignorePausedMotions) const { - if (!motion) + return motion && AZStd::any_of(begin(mMotionInstances), end(mMotionInstances), [motion, ignorePausedMotions](const MotionInstance* motionInstance) { - return false; - } - - // for all motion instances currently playing in this actor - const uint32 numInstances = mMotionInstances.size(); - for (uint32 i = 0; i < numInstances; ++i) - { - const MotionInstance* motionInstance = mMotionInstances[i]; - - if (ignorePausedMotions && motionInstance->GetIsPaused()) - { - continue; - } - - // check if the motion instance is an instance of the motion we are searching for - if (motionInstance->GetMotion()->GetID() == motion->GetID()) - { - return true; - } - } - - // it's not found, this means it has already been deleted from memory and is not valid anymore - return false; + return !(ignorePausedMotions && motionInstance->GetIsPaused()) && + motionInstance->GetMotion()->GetID() == motion->GetID(); + }); } // return given motion instance - MotionInstance* MotionSystem::GetMotionInstance(uint32 nr) const + MotionInstance* MotionSystem::GetMotionInstance(size_t nr) const { MCORE_ASSERT(nr < mMotionInstances.size()); return mMotionInstances[nr]; @@ -330,7 +289,7 @@ namespace EMotionFX MCORE_ASSERT(motionQueue); // copy entries from the given queue to the motion system's one - for (uint32 i = 0; i < motionQueue->GetNumEntries(); ++i) + for (size_t i = 0; i < motionQueue->GetNumEntries(); ++i) { mMotionQueue->AddEntry(motionQueue->GetEntry(i)); } @@ -362,6 +321,6 @@ namespace EMotionFX bool MotionSystem::GetIsPlaying() const { - return (mMotionInstances.size() > 0); + return !mMotionInstances.empty(); } } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MotionSystem.h b/Gems/EMotionFX/Code/EMotionFX/Source/MotionSystem.h index dd7ba26170..109cf5d41f 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MotionSystem.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MotionSystem.h @@ -104,7 +104,7 @@ namespace EMotionFX * @result A pointer to the motion instance. * @see IsValidMotionInstance */ - MotionInstance* GetMotionInstance(uint32 nr) const; + MotionInstance* GetMotionInstance(size_t nr) const; /** * Recursively search for the first non mixing motion and return the motion instance. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MultiThreadScheduler.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MultiThreadScheduler.cpp index bd339ecb36..3cc4d027a8 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MultiThreadScheduler.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MultiThreadScheduler.cpp @@ -78,10 +78,10 @@ namespace EMotionFX void MultiThreadScheduler::Print() { // for all steps - const uint32 numSteps = mSteps.size(); - for (uint32 i = 0; i < numSteps; ++i) + const size_t numSteps = mSteps.size(); + for (size_t i = 0; i < numSteps; ++i) { - AZ_Printf("EMotionFX", "STEP %.3d - %d", i, mSteps[i].mActorInstances.size()); + AZ_Printf("EMotionFX", "STEP %.3zu - %zu", i, mSteps[i].mActorInstances.size()); } AZ_Printf("EMotionFX", "---------"); @@ -91,14 +91,13 @@ namespace EMotionFX void MultiThreadScheduler::RemoveEmptySteps() { // process all steps - for (uint32 s = 0; s < mSteps.size(); ) + for (size_t s = 0; s < mSteps.size(); ) { - // if the step isn't empty - if (mSteps[s].mActorInstances.size() > 0) + if (!mSteps[s].mActorInstances.empty()) { s++; } - else // otherwise remove it + else { mSteps.erase(AZStd::next(begin(mSteps), s)); } @@ -111,7 +110,7 @@ namespace EMotionFX { MCore::LockGuardRecursive guard(mMutex); - uint32 numSteps = mSteps.size(); + size_t numSteps = mSteps.size(); if (numSteps == 0) { return; @@ -130,8 +129,8 @@ namespace EMotionFX // propagate root actor instance visibility to their attachments const ActorManager& actorManager = GetActorManager(); - const uint32 numRootActorInstances = actorManager.GetNumRootActorInstances(); - for (uint32 i = 0; i < numRootActorInstances; ++i) + const size_t numRootActorInstances = actorManager.GetNumRootActorInstances(); + for (size_t i = 0; i < numRootActorInstances; ++i) { ActorInstance* rootInstance = actorManager.GetRootActorInstance(i); if (rootInstance->GetIsEnabled() == false) @@ -147,22 +146,17 @@ namespace EMotionFX mNumVisible.SetValue(0); mNumSampled.SetValue(0); - for (uint32 s = 0; s < numSteps; ++s) + for (const ScheduleStep& currentStep : mSteps) { - const ScheduleStep& currentStep = mSteps[s]; - - // skip empty steps - const size_t numStepEntries = currentStep.mActorInstances.size(); - if (numStepEntries == 0) + if (currentStep.mActorInstances.empty()) { continue; } // process the actor instances in the current step in parallel - AZ::JobCompletion jobCompletion; - for (uint32 c = 0; c < numStepEntries; ++c) + AZ::JobCompletion jobCompletion; + for (ActorInstance* actorInstance : currentStep.mActorInstances) { - ActorInstance* actorInstance = currentStep.mActorInstances[c]; if (actorInstance->GetIsEnabled() == false) { continue; @@ -212,11 +206,11 @@ namespace EMotionFX // find the next free spot in the schedule - bool MultiThreadScheduler::FindNextFreeItem(ActorInstance* actorInstance, uint32 startStep, uint32* outStepNr) + bool MultiThreadScheduler::FindNextFreeItem(ActorInstance* actorInstance, size_t startStep, size_t* outStepNr) { // try out all steps - const uint32 numSteps = mSteps.size(); - for (uint32 s = startStep; s < numSteps; ++s) + const size_t numSteps = mSteps.size(); + for (size_t s = startStep; s < numSteps; ++s) { // if there is a conflicting dependency, skip this step if (CheckIfHasMatchingDependency(actorInstance, &mSteps[s])) @@ -235,8 +229,8 @@ namespace EMotionFX bool MultiThreadScheduler::HasActorInstanceInSteps(const ActorInstance* actorInstance) const { - const uint32 numSteps = mSteps.size(); - for (uint32 s = 0; s < numSteps; ++s) + const size_t numSteps = mSteps.size(); + for (size_t s = 0; s < numSteps; ++s) { const ScheduleStep& step = mSteps[s]; if (AZStd::find(step.mActorInstances.begin(), step.mActorInstances.end(), actorInstance) != step.mActorInstances.end()) @@ -248,13 +242,13 @@ namespace EMotionFX return false; } - void MultiThreadScheduler::RecursiveInsertActorInstance(ActorInstance* instance, uint32 startStep) + void MultiThreadScheduler::RecursiveInsertActorInstance(ActorInstance* instance, size_t startStep) { MCore::LockGuardRecursive guard(mMutex); AZ_Assert(!HasActorInstanceInSteps(instance), "Expected the actor instance not being part of another step already."); // find the first free location that doesn't conflict - uint32 outStep = startStep; + size_t outStep = startStep; if (!FindNextFreeItem(instance, startStep, &outStep)) { mSteps.reserve(10); @@ -279,8 +273,8 @@ namespace EMotionFX AddDependenciesToStep(instance, &mSteps[outStep]); // recursively add all attachments too - const uint32 numAttachments = instance->GetNumAttachments(); - for (uint32 i = 0; i < numAttachments; ++i) + const size_t numAttachments = instance->GetNumAttachments(); + for (size_t i = 0; i < numAttachments; ++i) { ActorInstance* attachment = instance->GetAttachment(i)->GetAttachmentActorInstance(); if (attachment) @@ -292,13 +286,13 @@ namespace EMotionFX // remove the actor instance from the schedule (excluding attachments) - uint32 MultiThreadScheduler::RemoveActorInstance(ActorInstance* actorInstance, uint32 startStep) + size_t MultiThreadScheduler::RemoveActorInstance(ActorInstance* actorInstance, size_t startStep) { MCore::LockGuardRecursive guard(mMutex); // for all scheduler steps, starting from the specified start step number - const uint32 numSteps = mSteps.size(); - for (uint32 s = startStep; s < numSteps; ++s) + const size_t numSteps = mSteps.size(); + for (size_t s = startStep; s < numSteps; ++s) { ScheduleStep& step = mSteps[s]; @@ -330,16 +324,16 @@ namespace EMotionFX // remove the actor instance (including all of its attachments) - void MultiThreadScheduler::RecursiveRemoveActorInstance(ActorInstance* actorInstance, uint32 startStep) + void MultiThreadScheduler::RecursiveRemoveActorInstance(ActorInstance* actorInstance, size_t startStep) { MCore::LockGuardRecursive guard(mMutex); // remove the actual actor instance - const uint32 step = RemoveActorInstance(actorInstance, startStep); + const size_t step = RemoveActorInstance(actorInstance, startStep); // recursively remove all attachments as well - const uint32 numAttachments = actorInstance->GetNumAttachments(); - for (uint32 i = 0; i < numAttachments; ++i) + const size_t numAttachments = actorInstance->GetNumAttachments(); + for (size_t i = 0; i < numAttachments; ++i) { ActorInstance* attachment = actorInstance->GetAttachment(i)->GetAttachmentActorInstance(); if (attachment) diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MultiThreadScheduler.h b/Gems/EMotionFX/Code/EMotionFX/Source/MultiThreadScheduler.h index 4deebae866..6d5a7251e5 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MultiThreadScheduler.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MultiThreadScheduler.h @@ -99,14 +99,14 @@ namespace EMotionFX * @param actorInstance The actor instance to insert. * @param startStep An offset in the schedule where to start trying to insert the actor instances. */ - void RecursiveInsertActorInstance(ActorInstance* actorInstance, uint32 startStep = 0) override; + void RecursiveInsertActorInstance(ActorInstance* actorInstance, size_t startStep = 0) override; /** * Recursively remove an actor instance and its attachments from the schedule. * @param actorInstance The actor instance to remove. * @param startStep An offset in the schedule where to start trying to remove from. */ - void RecursiveRemoveActorInstance(ActorInstance* actorInstance, uint32 startStep = 0) override; + void RecursiveRemoveActorInstance(ActorInstance* actorInstance, size_t startStep = 0) override; /** * Remove a single actor instance from the schedule. This will not remove its attachments. @@ -114,12 +114,12 @@ namespace EMotionFX * @param startStep An offset in the schedule where to start trying to remove from. * @result Returns the offset in the schedule where the actor instance was removed. */ - uint32 RemoveActorInstance(ActorInstance* actorInstance, uint32 startStep = 0) override; + size_t RemoveActorInstance(ActorInstance* actorInstance, size_t startStep = 0) override; void Lock(); void Unlock(); - const ScheduleStep& GetScheduleStep(uint32 index) const { return mSteps[index]; } + const ScheduleStep& GetScheduleStep(size_t index) const { return mSteps[index]; } size_t GetNumScheduleSteps() const { return mSteps.size(); } protected: @@ -156,7 +156,7 @@ namespace EMotionFX * @param outStepNr This will contain the step number in which we can insert the actor instance. * @result Returns false when there is no step where we can insert in. A new step will have to be added. */ - bool FindNextFreeItem(ActorInstance* actorInstance, uint32 startStep, uint32* outStepNr); + bool FindNextFreeItem(ActorInstance* actorInstance, size_t startStep, size_t* outStepNr); /** * Add the dependencies of a given actor instance to a specified scheduler step. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Node.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Node.cpp index 8f14fcc2b1..1144cc3f42 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Node.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Node.cpp @@ -24,7 +24,7 @@ namespace EMotionFX mNodeIndex = InvalidIndex; // hasn't been set yet mSkeletalLODs = 0xFFFFFFFF; // set all bits of the integer to 1, which enables this node in all LOD levels on default mSkeleton = skeleton; - mSemanticNameID = InvalidIndex; + mSemanticNameID = InvalidIndex32; mNodeFlags = FLAG_INCLUDEINBOUNDSCALC; if (name) @@ -33,12 +33,12 @@ namespace EMotionFX } else { - mNameID = InvalidIndex; + mNameID = InvalidIndex32; } } - Node::Node(size_t nameID, Skeleton* skeleton) + Node::Node(uint32 nameID, Skeleton* skeleton) : BaseObject() { mParentIndex = InvalidIndex; @@ -46,7 +46,7 @@ namespace EMotionFX mSkeletalLODs = 0xFFFFFFFF;// set all bits of the integer to 1, which enables this node in all LOD levels on default mSkeleton = skeleton; mNameID = nameID; - mSemanticNameID = InvalidIndex; + mSemanticNameID = InvalidIndex32; mNodeFlags = FLAG_INCLUDEINBOUNDSCALC; } @@ -69,7 +69,7 @@ namespace EMotionFX // create a node - Node* Node::Create(size_t nameID, Skeleton* skeleton) + Node* Node::Create(uint32 nameID, Skeleton* skeleton) { return aznew Node(nameID, skeleton); } @@ -235,7 +235,7 @@ namespace EMotionFX } else { - mNameID = InvalidIndex; + mNameID = InvalidIndex32; } } @@ -249,7 +249,7 @@ namespace EMotionFX } else { - mSemanticNameID = InvalidIndex; + mSemanticNameID = InvalidIndex32; } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Node.h b/Gems/EMotionFX/Code/EMotionFX/Source/Node.h index 9aa01201d2..19d9f53ff8 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Node.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Node.h @@ -70,7 +70,7 @@ namespace EMotionFX * @param nameID The name ID, generated using the MCore::GetStringIdPool(). * @param skeleton The skeleton where this node will belong to, you still need to manually add it to the skeleton though. */ - static Node* Create(size_t nameID, Skeleton* skeleton); + static Node* Create(uint32 nameID, Skeleton* skeleton); /** * Clone the node. @@ -155,14 +155,14 @@ namespace EMotionFX * same ID number. * @result The node ID number, which can be used for fast compares between nodes. */ - MCORE_INLINE size_t GetID() const { return mNameID; } + MCORE_INLINE uint32 GetID() const { return mNameID; } /** * Get the semantic name ID. * To get the name you can also use GetSemanticName() and GetSemanticNameString(). * @result The semantic name ID. */ - MCORE_INLINE size_t GetSemanticID() const { return mSemanticNameID; } + MCORE_INLINE uint32 GetSemanticID() const { return mSemanticNameID; } /** * Get the number of child nodes attached to this node. @@ -418,8 +418,8 @@ namespace EMotionFX size_t mNodeIndex; /**< The node index, which is the index into the array of nodes inside the Skeleton class. */ size_t mParentIndex; /**< The parent node index, or MCORE_INVALIDINDEX32 when there is no parent. */ size_t mSkeletalLODs; /**< The skeletal LOD status values. Each bit represents if this node is enabled or disabled in the given LOD. */ - size_t mNameID; /**< The ID, which is generated from the name. You can use this for fast compares between nodes. */ - size_t mSemanticNameID; /**< The semantic name ID, for example "LeftHand" or "RightFoot" or so, this can be used for retargeting. */ + uint32 mNameID; /**< The ID, which is generated from the name. You can use this for fast compares between nodes. */ + uint32 mSemanticNameID; /**< The semantic name ID, for example "LeftHand" or "RightFoot" or so, this can be used for retargeting. */ Skeleton* mSkeleton; /**< The skeleton where this node belongs to. */ AZStd::vector mChildIndices; /**< The indices that point to the child nodes. */ AZStd::vector mAttributes; /**< The node attributes. */ @@ -437,7 +437,7 @@ namespace EMotionFX * @param nameID The name ID, generated using the MCore::GetStringIdPool(). * @param skeleton The skeleton where this node will belong to. */ - Node(size_t nameID, Skeleton* skeleton); + Node(uint32 nameID, Skeleton* skeleton); /** * The destructor. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/NodeGroup.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/NodeGroup.cpp index e22ad5f064..cd2139ec9a 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/NodeGroup.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/NodeGroup.cpp @@ -68,7 +68,7 @@ namespace EMotionFX // get the node number of a given index - uint16 NodeGroup::GetNode(uint16 index) + uint16 NodeGroup::GetNode(uint16 index) const { return mNodes[index]; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/NodeGroup.h b/Gems/EMotionFX/Code/EMotionFX/Source/NodeGroup.h index dfe876c86a..b3e82e648b 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/NodeGroup.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/NodeGroup.h @@ -82,7 +82,7 @@ namespace EMotionFX * @param index The node number inside this group, which must be in range of [0..GetNumNodes()-1]. * @result The node number, which points inside the Actor object. Use Actor::GetNode( returnValue ) to get access to the node information. */ - uint16 GetNode(uint16 index); + uint16 GetNode(uint16 index) const; /** * Enable all nodes that remain inside this group, for a given actor instance. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/NodeMap.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/NodeMap.cpp index e708d255d3..fb2fbd9ed7 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/NodeMap.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/NodeMap.cpp @@ -127,7 +127,7 @@ namespace EMotionFX // remove a given entry by its name ID - void NodeMap::RemoveEntryByNameID(size_t firstNameID) + void NodeMap::RemoveEntryByNameID(uint32 firstNameID) { const size_t entryIndex = FindEntryIndexByNameID(firstNameID); if (entryIndex == InvalidIndex) @@ -373,7 +373,7 @@ namespace EMotionFX // find an entry index by its name ID - size_t NodeMap::FindEntryIndexByNameID(size_t firstNameID) const + size_t NodeMap::FindEntryIndexByNameID(uint32 firstNameID) const { const auto foundEntry = AZStd::find_if(begin(mEntries), end(mEntries), [firstNameID](const MapEntry& entry) { diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/NodeMap.h b/Gems/EMotionFX/Code/EMotionFX/Source/NodeMap.h index ae66a243bb..3fe2c94386 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/NodeMap.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/NodeMap.h @@ -39,8 +39,8 @@ namespace EMotionFX public: struct MapEntry { - size_t mFirstNameID = InvalidIndex; /**< The first name ID, which is the primary key in the map. */ - size_t mSecondNameID = InvalidIndex; /**< The second name ID. */ + uint32 mFirstNameID = InvalidIndex32; /**< The first name ID, which is the primary key in the map. */ + uint32 mSecondNameID = InvalidIndex32; /**< The second name ID. */ }; static NodeMap* Create(); @@ -57,7 +57,7 @@ namespace EMotionFX const AZStd::string& GetSecondNameString(size_t entryIndex) const; bool GetHasEntry(const char* firstName) const; size_t FindEntryIndexByName(const char* firstName) const; - size_t FindEntryIndexByNameID(size_t firstNameID) const; + size_t FindEntryIndexByNameID(uint32 firstNameID) const; const char* FindSecondName(const char* firstName) const; void FindSecondName(const char* firstName, AZStd::string* outString); @@ -69,7 +69,7 @@ namespace EMotionFX void SetEntry(const char* firstName, const char* secondName, bool addIfNotExists); void RemoveEntryByIndex(size_t entryIndex); void RemoveEntryByName(const char* firstName); - void RemoveEntryByNameID(size_t firstNameID); + void RemoveEntryByNameID(uint32 firstNameID); // filename void SetFileName(const char* fileName); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/PhysicsSetup.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/PhysicsSetup.cpp index 0b799bcb1b..dbe57cdd34 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/PhysicsSetup.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/PhysicsSetup.cpp @@ -496,7 +496,7 @@ namespace EMotionFX : Transform::CreateIdentity(); // if there are child nodes, point the bone direction to the average of their positions - const uint32 numChildNodes = node->GetNumChildNodes(); + const size_t numChildNodes = node->GetNumChildNodes(); if (numChildNodes > 0) { AZ::Vector3 meanChildPosition = AZ::Vector3::CreateZero(); @@ -504,9 +504,9 @@ namespace EMotionFX // weight by the number of descendants of each child node, so that things like jiggle bones and twist bones // have little influence on the bone direction. float totalSubChildren = 0.0f; - for (uint32 childNumber = 0; childNumber < numChildNodes; childNumber++) + for (size_t childNumber = 0; childNumber < numChildNodes; childNumber++) { - const uint32 childIndex = node->GetChildIndex(childNumber); + const size_t childIndex = node->GetChildIndex(childNumber); const Node* childNode = skeleton->GetNode(childIndex); const float numSubChildren = static_cast(1 + childNode->GetNumChildNodesRecursive()); totalSubChildren += numSubChildren; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Pose.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Pose.cpp index 096b32b041..b9f223eded 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Pose.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Pose.cpp @@ -1424,7 +1424,7 @@ namespace EMotionFX const Actor* actor = mActorInstance->GetActor(); const TransformData* transformData = mActorInstance->GetTransformData(); const Pose* bindPose = transformData->GetBindPose(); - const AZStd::vector& jointLinks = motionLinkData->GetJointDataLinks(); + const AZStd::vector& jointLinks = motionLinkData->GetJointDataLinks(); AnimGraphPose* tempPose = GetEMotionFX().GetThreadData(mActorInstance->GetThreadIndex())->GetPosePool().RequestPose(mActorInstance); Pose& unmirroredPose = tempPose->GetPose(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/PoseDataRagdoll.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/PoseDataRagdoll.cpp index 5ef490cd2c..e5c3aa7d8c 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/PoseDataRagdoll.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/PoseDataRagdoll.cpp @@ -158,7 +158,7 @@ namespace EMotionFX // Blend node states. Both, the destination pose as well as the current pose hold used ragdoll pose datas. for (size_t i = 0; i < nodeStateCount; ++i) { - const AZ::u32 jointIndex = ragdollInstance->GetJointIndex(i); + const size_t jointIndex = ragdollInstance->GetJointIndex(i); const Transform& localTransform = m_pose->GetLocalSpaceTransform(jointIndex); const Transform& destLocalTransform = destPose->GetLocalSpaceTransform(jointIndex); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/RagdollInstance.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/RagdollInstance.cpp index 93d4cd19d1..87221c0bd2 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/RagdollInstance.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/RagdollInstance.cpp @@ -45,14 +45,14 @@ namespace EMotionFX const Actor* actor = m_actorInstance->GetActor(); const Skeleton* skeleton = actor->GetSkeleton(); const AZStd::shared_ptr& physicsSetup = actor->GetPhysicsSetup(); - const AZ::u32 jointCount = skeleton->GetNumNodes(); + const size_t jointCount = skeleton->GetNumNodes(); const Physics::RagdollConfiguration& ragdollConfig = physicsSetup->GetRagdollConfig(); const size_t ragdollNodeCount = ragdollConfig.m_nodes.size(); m_ragdollNodeIndices.resize(jointCount); m_jointIndicesByRagdollNodeIndices.resize(ragdollNodeCount); - for (AZ::u32 jointIndex = 0; jointIndex < jointCount; ++jointIndex) + for (size_t jointIndex = 0; jointIndex < jointCount; ++jointIndex) { const Node* joint = skeleton->GetNode(jointIndex); @@ -72,7 +72,7 @@ namespace EMotionFX } // Find and store the ragdoll root joint by iterating the skeleton top-down until we find the first node which is part of the ragdoll. - for (AZ::u32 jointIndex = 0; jointIndex < jointCount; ++jointIndex) + for (size_t jointIndex = 0; jointIndex < jointCount; ++jointIndex) { Node* joint = skeleton->GetNode(jointIndex); const AZ::Outcome ragdollNodeIndex = GetRagdollNodeIndex(jointIndex); @@ -162,7 +162,7 @@ namespace EMotionFX AZ_Assert(ragdollNodeCount == m_ragdoll->GetNumNodes(), "Ragdoll node index to animation skeleton joint index mapping not up to date. Expected the same number of joint indices than ragdoll nodes."); for (size_t ragdollNodeIndex = 0; ragdollNodeIndex < ragdollNodeCount; ++ragdollNodeIndex) { - const AZ::u32 jointIndex = GetJointIndex(ragdollNodeIndex); + const size_t jointIndex = GetJointIndex(ragdollNodeIndex); Physics::RagdollNodeState& ragdollNodeState = m_targetState[ragdollNodeIndex]; if (ragdollNodeState.m_simulationType == Physics::SimulationType::Kinematic) @@ -264,7 +264,7 @@ namespace EMotionFX return AZ::Success(ragdollNodeIndex); } - AZ::u32 RagdollInstance::GetJointIndex(size_t ragdollNodeIndex) const + size_t RagdollInstance::GetJointIndex(size_t ragdollNodeIndex) const { return m_jointIndicesByRagdollNodeIndices[ragdollNodeIndex]; } @@ -330,7 +330,7 @@ namespace EMotionFX return m_velocityEvaluator.get(); } - void RagdollInstance::GetWorldSpaceTransform(const Pose* pose, AZ::u32 jointIndex, AZ::Vector3& outPosition, AZ::Quaternion& outRotation) + void RagdollInstance::GetWorldSpaceTransform(const Pose* pose, size_t jointIndex, AZ::Vector3& outPosition, AZ::Quaternion& outRotation) { const Transform& globalTransform = pose->GetModelSpaceTransform(jointIndex); const AZ::Quaternion actorInstanceRotation = m_actorInstance->GetLocalSpaceTransform().mRotation; @@ -357,7 +357,7 @@ namespace EMotionFX for (size_t ragdollNodeIndex = 0; ragdollNodeIndex < ragdollNodeCount; ++ragdollNodeIndex) { - const AZ::u32 jointIndex = m_jointIndicesByRagdollNodeIndices[ragdollNodeIndex]; + const size_t jointIndex = m_jointIndicesByRagdollNodeIndices[ragdollNodeIndex]; const Node* joint = skeleton->GetNode(jointIndex); Physics::RagdollNodeState& ragdollNodeState = outRagdollState[ragdollNodeIndex]; @@ -433,9 +433,9 @@ namespace EMotionFX } const EMotionFX::TransformData* transformData = m_actorInstance->GetTransformData(); - const AZ::u32 transformCount = transformData->GetNumTransforms(); + const size_t transformCount = transformData->GetNumTransforms(); const EMotionFX::Skeleton* skeleton = m_actorInstance->GetActor()->GetSkeleton(); - const AZ::u32 jointCount = skeleton->GetNumNodes(); + const size_t jointCount = skeleton->GetNumNodes(); const RagdollInstance* ragdollInstance = m_actorInstance->GetRagdollInstance(); const Physics::Ragdoll* ragdoll = ragdollInstance->GetRagdoll(); @@ -459,7 +459,7 @@ namespace EMotionFX const size_t ragdollNodeCount = ragdoll->GetNumNodes(); for (size_t i = 0; i < ragdollNodeCount; ++i) { - const AZ::u32 jointIndex = ragdollInstance->GetJointIndex(i); + const size_t jointIndex = ragdollInstance->GetJointIndex(i); const Physics::RagdollNodeState& targetJointPose = ragdollTargetPose[i]; if (targetJointPose.m_simulationType == Physics::SimulationType::Dynamic) @@ -468,7 +468,7 @@ namespace EMotionFX } } - for (AZ::u32 jointIndex = 0; jointIndex < jointCount; ++jointIndex) + for (size_t jointIndex = 0; jointIndex < jointCount; ++jointIndex) { const Node* joint = skeleton->GetNode(jointIndex); const AZ::Outcome ragdollJointIndex = ragdollInstance->GetRagdollNodeIndex(jointIndex); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/RagdollInstance.h b/Gems/EMotionFX/Code/EMotionFX/Source/RagdollInstance.h index 0f249bd1b8..a78ec08da7 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/RagdollInstance.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/RagdollInstance.h @@ -60,7 +60,7 @@ namespace EMotionFX * @param[in] ragdollNodeIndex The index of the ragdoll node [0, Physics::Ragdoll::GetNumNodes()-1]. * @result The index of the joint in the animation skeleton. */ - AZ::u32 GetJointIndex(size_t ragdollNodeIndex) const; + size_t GetJointIndex(size_t ragdollNodeIndex) const; const AZ::Vector3& GetCurrentPos() const; const AZ::Vector3& GetLastPos() const; @@ -83,7 +83,7 @@ namespace EMotionFX void SetVelocityEvaluator(RagdollVelocityEvaluator* evaluator); RagdollVelocityEvaluator* GetVelocityEvaluator() const; - void GetWorldSpaceTransform(const Pose* pose, AZ::u32 jointIndex, AZ::Vector3& outPosition, AZ::Quaternion& outRotation); + void GetWorldSpaceTransform(const Pose* pose, size_t jointIndex, AZ::Vector3& outPosition, AZ::Quaternion& outRotation); void FindNextRagdollParentForJoint(Node* joint, Node*& outParentJoint, AZ::Outcome& outRagdollParentNodeIndex) const; typedef const AZStd::function& DrawLineFunction; @@ -93,8 +93,8 @@ namespace EMotionFX void ReadRagdollStateFromActorInstance(Physics::RagdollState& outRagdollState, AZ::Vector3& outRagdollPos, AZ::Quaternion& outRagdollRot); void ReadRagdollState(Physics::RagdollState& outRagdollState, AZ::Vector3& outRagdollPos, AZ::Quaternion& outRagdollRot); - AZStd::vector m_ragdollNodeIndices; /**< Stores the ragdoll node indices for each joint in the animation skeleton, MCORE_INVALIDINDEX32 in case a given joint is not part of the ragdoll. [0, Actor::GetNumNodes()-1] */ - AZStd::vector m_jointIndicesByRagdollNodeIndices; /**< Stores the animation skeleton joint indices for each ragdoll node. [0, Physics::Ragdoll::GetNumNodes()-1] */ + AZStd::vector m_ragdollNodeIndices; /**< Stores the ragdoll node indices for each joint in the animation skeleton, InvalidIndex in case a given joint is not part of the ragdoll. [0, Actor::GetNumNodes()-1] */ + AZStd::vector m_jointIndicesByRagdollNodeIndices; /**< Stores the animation skeleton joint indices for each ragdoll node. [0, Physics::Ragdoll::GetNumNodes()-1] */ ActorInstance* m_actorInstance; Node* m_ragdollRootJoint; Physics::Ragdoll* m_ragdoll; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Recorder.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Recorder.cpp index 923c74aa02..3eb32f24ce 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Recorder.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Recorder.cpp @@ -231,9 +231,9 @@ namespace EMotionFX // Add all actor instances if we did not specify them explicitly. if (mRecordSettings.m_actorInstances.empty()) { - const uint32 numActorInstances = GetActorManager().GetNumActorInstances(); + const size_t numActorInstances = GetActorManager().GetNumActorInstances(); mRecordSettings.m_actorInstances.resize(numActorInstances); - for (uint32 i = 0; i < numActorInstances; ++i) + for (size_t i = 0; i < numActorInstances; ++i) { ActorInstance* actorInstance = GetActorManager().GetActorInstance(i); mRecordSettings.m_actorInstances[i] = actorInstance; @@ -324,9 +324,9 @@ namespace EMotionFX if (mRecordSettings.mRecordTransforms) { // for all nodes in the actor instance - const uint32 numNodes = actorInstance->GetNumNodes(); + const size_t numNodes = actorInstance->GetNumNodes(); actorInstanceData.m_transformTracks.resize(numNodes); - for (uint32 n = 0; n < numNodes; ++n) + for (size_t n = 0; n < numNodes; ++n) { actorInstanceData.m_transformTracks[n].mPositions.Reserve(mRecordSettings.mNumPreAllocTransformKeys); actorInstanceData.m_transformTracks[n].mRotations.Reserve(mRecordSettings.mNumPreAllocTransformKeys); @@ -344,9 +344,9 @@ namespace EMotionFX // if recording morph targets, resize the morphs array if (mRecordSettings.mRecordMorphs) { - const uint32 numMorphs = actorInstance->GetMorphSetupInstance()->GetNumMorphTargets(); + const size_t numMorphs = actorInstance->GetMorphSetupInstance()->GetNumMorphTargets(); actorInstanceData.mMorphTracks.resize(numMorphs); - for (uint32 m = 0; m < numMorphs; ++m) + for (size_t m = 0; m < numMorphs; ++m) { actorInstanceData.mMorphTracks[m].Reserve(256); } @@ -387,8 +387,8 @@ namespace EMotionFX continue; } - const uint32 numNodes = actorInstance->GetNumNodes(); - for (uint32 n = 0; n < numNodes; ++n) + const size_t numNodes = actorInstance->GetNumNodes(); + for (size_t n = 0; n < numNodes; ++n) { actorInstanceData->m_transformTracks[n].mPositions.Shrink(); actorInstanceData->m_transformTracks[n].mRotations.Shrink(); @@ -470,14 +470,14 @@ namespace EMotionFX void Recorder::RecordMorphs() { // for all actor instances - const uint32 numActorInstances = static_cast(m_actorInstanceDatas.size()); - for (uint32 i = 0; i < numActorInstances; ++i) + const size_t numActorInstances = m_actorInstanceDatas.size(); + for (size_t i = 0; i < numActorInstances; ++i) { ActorInstanceData& actorInstanceData = *m_actorInstanceDatas[i]; ActorInstance* actorInstance = actorInstanceData.mActorInstance; - const uint32 numMorphs = actorInstance->GetMorphSetupInstance()->GetNumMorphTargets(); - for (uint32 m = 0; m < numMorphs; ++m) + const size_t numMorphs = actorInstance->GetMorphSetupInstance()->GetNumMorphTargets(); + for (size_t m = 0; m < numMorphs; ++m) { KeyTrackLinearDynamic& morphTrack = actorInstanceData.mMorphTracks[i]; // morph animation data morphTrack.AddKey(mRecordTime, actorInstance->GetMorphSetupInstance()->GetMorphTarget(i)->GetWeight()); @@ -513,8 +513,8 @@ namespace EMotionFX const TransformData* transformData = actorInstance->GetTransformData(); { - const uint32 numNodes = actorInstance->GetNumNodes(); - for (uint32 n = 0; n < numNodes; ++n) + const size_t numNodes = actorInstance->GetNumNodes(); + for (size_t n = 0; n < numNodes; ++n) { const Transform& localTransform = transformData->GetCurrentPose()->GetLocalSpaceTransform(n); @@ -548,9 +548,9 @@ namespace EMotionFX // add a new frame AZStd::vector& frames = animGraphInstanceData.mFrames; - if (frames.size() > 0) + if (!frames.empty()) { - const uint32 byteOffset = frames.back().mByteOffset + frames.back().mNumBytes; + const size_t byteOffset = frames.back().mByteOffset + frames.back().mNumBytes; frames.emplace_back(); frames.back().mByteOffset = byteOffset; frames.back().mNumBytes = 0; @@ -567,9 +567,9 @@ namespace EMotionFX currentFrame.mTimeValue = mRecordTime; // save the parameter values - const uint32 numParams = static_cast(animGraphInstance->GetAnimGraph()->GetNumValueParameters()); + const size_t numParams = animGraphInstance->GetAnimGraph()->GetNumValueParameters(); currentFrame.mParameterValues.resize(numParams); - for (uint32 p = 0; p < numParams; ++p) + for (size_t p = 0; p < numParams; ++p) { currentFrame.mParameterValues[p] = AZStd::unique_ptr(animGraphInstance->GetParameterValue(p)->Clone()); } @@ -595,7 +595,7 @@ namespace EMotionFX { // get the current frame's data pointer AnimGraphAnimFrame& currentFrame = animGraphInstanceData.mFrames.back(); - const uint32 frameOffset = currentFrame.mByteOffset; + const size_t frameOffset = currentFrame.mByteOffset; // prepare the objects array mObjects.clear(); @@ -605,14 +605,14 @@ namespace EMotionFX object->RecursiveCollectObjects(mObjects); // resize the object infos array - const uint32 numObjects = mObjects.size(); + const size_t numObjects = mObjects.size(); currentFrame.mObjectInfos.resize(numObjects); // calculate how much memory we need for this frame - uint32 requiredFrameBytes = 0; - for (uint32 i = 0; i < numObjects; ++i) + size_t requiredFrameBytes = 0; + for (const AnimGraphObject* animGraphObject : mObjects) { - requiredFrameBytes += mObjects[i]->SaveUniqueData(animGraphInstance, nullptr); + requiredFrameBytes += animGraphObject->SaveUniqueData(animGraphInstance, nullptr); } // make sure we have at least the given amount of space in the buffer we are going to write the frame data to @@ -623,7 +623,7 @@ namespace EMotionFX uint8* dataPointer = &animGraphInstanceData.mDataBuffer[frameOffset]; // save all the unique datas for the objects - for (uint32 i = 0; i < numObjects; ++i) + for (size_t i = 0; i < numObjects; ++i) { // store the object info AnimGraphObject* curObject = mObjects[i]; @@ -631,7 +631,7 @@ namespace EMotionFX currentFrame.mObjectInfos[i].mFrameByteOffset = currentFrame.mNumBytes; // write the unique data - const uint32 numBytesWritten = curObject->SaveUniqueData(animGraphInstance, dataPointer); + const size_t numBytesWritten = curObject->SaveUniqueData(animGraphInstance, dataPointer); // increase some offsets/pointers currentFrame.mNumBytes += numBytesWritten; @@ -646,7 +646,7 @@ namespace EMotionFX // make sure our anim graph anim buffer is big enough to hold a specified amount of bytes - bool Recorder::AssureAnimGraphBufferSize(AnimGraphInstanceData& animGraphInstanceData, uint32 numBytes) + bool Recorder::AssureAnimGraphBufferSize(AnimGraphInstanceData& animGraphInstanceData, size_t numBytes) { // if the buffer is big enough, do nothing if (animGraphInstanceData.mDataBufferSize >= numBytes) @@ -655,7 +655,7 @@ namespace EMotionFX } // we need to reallocate to grow the buffer - const uint32 newNumBytes = animGraphInstanceData.mDataBufferSize + (numBytes - animGraphInstanceData.mDataBufferSize) * 100; // allocate 100 frames ahead + const size_t newNumBytes = animGraphInstanceData.mDataBufferSize + (numBytes - animGraphInstanceData.mDataBufferSize) * 100; // allocate 100 frames ahead void* newBuffer = MCore::Realloc(animGraphInstanceData.mDataBuffer, newNumBytes, EMFX_MEMCATEGORY_RECORDER); MCORE_ASSERT(newBuffer); if (newBuffer) @@ -770,15 +770,14 @@ namespace EMotionFX const auto iterator = AZStd::find(recordedActorInstances.begin(), recordedActorInstances.end(), actorInstance); if (iterator != recordedActorInstances.end()) { - const size_t index = iterator - recordedActorInstances.begin(); + const size_t index = AZStd::distance(recordedActorInstances.begin(), iterator); const ActorInstanceData& actorInstanceData = *m_actorInstanceDatas[index]; - const uint32 numMorphs = actorInstanceData.mMorphTracks.size(); + const size_t numMorphs = actorInstanceData.mMorphTracks.size(); if (numMorphs == actorInstance->GetMorphSetupInstance()->GetNumMorphTargets()) { - for (uint32 i = 0; i < numMorphs; ++i) + for (size_t i = 0; i < numMorphs; ++i) { actorInstance->GetMorphSetupInstance()->GetMorphTarget(i)->SetWeight(actorInstanceData.mMorphTracks[i].GetValueAtTime(timeInSeconds)); - // actorInstance->GetMorphSetupInstance()->GetMorphTarget(i)->SetManualMode(true); } } } @@ -811,8 +810,8 @@ namespace EMotionFX // for all nodes in the actor instance Transform outTransform; - const uint32 numNodes = actorInstance->GetNumNodes(); - for (uint32 n = 0; n < numNodes; ++n) + const size_t numNodes = actorInstance->GetNumNodes(); + for (size_t n = 0; n < numNodes; ++n) { outTransform = transformData->GetCurrentPose()->GetLocalSpaceTransform(n); const TransformTracks& track = actorInstanceData.m_transformTracks[n]; @@ -837,8 +836,8 @@ namespace EMotionFX void Recorder::SampleAndApplyAnimGraphStates(float timeInSeconds, const AnimGraphInstanceData& animGraphInstanceData) const { // find out the frame number - const uint32 frameNumber = FindAnimGraphDataFrameNumber(timeInSeconds); - if (frameNumber == MCORE_INVALIDINDEX32) + const size_t frameNumber = FindAnimGraphDataFrameNumber(timeInSeconds); + if (frameNumber == InvalidIndex) { return; } @@ -847,18 +846,18 @@ namespace EMotionFX AnimGraphInstance* animGraphInstance = animGraphInstanceData.mAnimGraphInstance; // get the real frame number (clamped) - const uint32 realFrameNumber = MCore::Min(frameNumber, animGraphInstanceData.mFrames.size() - 1); + const size_t realFrameNumber = AZStd::min(frameNumber, animGraphInstanceData.mFrames.size() - 1); const AnimGraphAnimFrame& currentFrame = animGraphInstanceData.mFrames[realFrameNumber]; // get the data and objects buffers - const uint32 byteOffset = currentFrame.mByteOffset; + const size_t byteOffset = currentFrame.mByteOffset; const uint8* frameDataBuffer = &animGraphInstanceData.mDataBuffer[byteOffset]; const AZStd::vector& frameObjects = currentFrame.mObjectInfos; // first lets update all parameter values MCORE_ASSERT(currentFrame.mParameterValues.size() == animGraphInstance->GetAnimGraph()->GetNumParameters()); - const uint32 numParameters = currentFrame.mParameterValues.size(); - for (uint32 p = 0; p < numParameters; ++p) + const size_t numParameters = currentFrame.mParameterValues.size(); + for (size_t p = 0; p < numParameters; ++p) { // make sure the parameters are of the same type MCORE_ASSERT(animGraphInstance->GetParameterValue(p)->GetType() == currentFrame.mParameterValues[p]->GetType()); @@ -866,12 +865,12 @@ namespace EMotionFX } // process all objects for this frame - uint32 totalBytesRead = 0; - const uint32 numObjects = frameObjects.size(); - for (uint32 a = 0; a < numObjects; ++a) + size_t totalBytesRead = 0; + const size_t numObjects = frameObjects.size(); + for (size_t a = 0; a < numObjects; ++a) { const AnimGraphAnimObjectInfo& objectInfo = frameObjects[a]; - const uint32 numBytesRead = objectInfo.mObject->LoadUniqueData(animGraphInstance, &frameDataBuffer[objectInfo.mFrameByteOffset]); + const size_t numBytesRead = objectInfo.mObject->LoadUniqueData(animGraphInstance, &frameDataBuffer[objectInfo.mFrameByteOffset]); totalBytesRead += numBytesRead; } @@ -885,19 +884,13 @@ namespace EMotionFX != mRecordSettings.m_actorInstances.end(); } - uint32 Recorder::FindActorInstanceDataIndex(ActorInstance* actorInstance) const + size_t Recorder::FindActorInstanceDataIndex(ActorInstance* actorInstance) const { - // for all actor instances - const uint32 numActorInstances = static_cast(m_actorInstanceDatas.size()); - for (uint32 a = 0; a < numActorInstances; ++a) + const auto found = AZStd::find_if(begin(m_actorInstanceDatas), end(m_actorInstanceDatas), [actorInstance](const ActorInstanceData* data) { - if (m_actorInstanceDatas[a]->mActorInstance == actorInstance) - { - return a; - } - } - - return MCORE_INVALIDINDEX32; + return data->mActorInstance == actorInstance; + }); + return found != end(m_actorInstanceDatas) ? AZStd::distance(begin(m_actorInstanceDatas), found) : InvalidIndex; } void Recorder::UpdateNodeHistoryItems() @@ -919,29 +912,21 @@ namespace EMotionFX AZStd::vector& historyItems = actorInstanceData->mNodeHistoryItems; // finalize items - const size_t numActiveNodes = mActiveNodes.size(); - const uint32 numHistoryItems = historyItems.size(); - for (uint32 h = 0; h < numHistoryItems; ++h) + for (NodeHistoryItem* curItem : historyItems) { - NodeHistoryItem* curItem = historyItems[h]; if (curItem->mIsFinalized) { continue; } // check if we have an active node for the given item - size_t index = InvalidIndex; - for (size_t x = 0; x < numActiveNodes; ++x) + const bool haveActiveNode = AZStd::find_if(begin(mActiveNodes), end(mActiveNodes), [curItem](const AnimGraphNode* activeNode) { - if (mActiveNodes[x]->GetId() == curItem->mNodeId) - { - index = x; - break; - } - } + return activeNode->GetId() == curItem->mNodeId; + }) != end(mActiveNodes); // the node got deactivated, finalize the item - if (index == InvalidIndex) + if (haveActiveNode) { curItem->mGlobalWeights.Optimize(0.0001f); curItem->mLocalWeights.Optimize(0.0001f); @@ -953,9 +938,8 @@ namespace EMotionFX } // iterate over all active nodes - for (size_t i = 0; i < numActiveNodes; ++i) + for (const AnimGraphNode* activeNode : mActiveNodes) { - AnimGraphNode* activeNode = mActiveNodes[i]; if (activeNode == animGraphInstance->GetRootNode()) // skip the root node { continue; @@ -1013,7 +997,7 @@ namespace EMotionFX // get the motion instance if (typeID == azrtti_typeid()) { - AnimGraphMotionNode* motionNode = static_cast(activeNode); + const AnimGraphMotionNode* motionNode = static_cast(activeNode); MotionInstance* motionInstance = motionNode->FindMotionInstance(animGraphInstance); if (motionInstance) { @@ -1050,13 +1034,11 @@ namespace EMotionFX // try to find a given node history item - Recorder::NodeHistoryItem* Recorder::FindNodeHistoryItem(const ActorInstanceData& actorInstanceData, AnimGraphNode* node, float recordTime) const + Recorder::NodeHistoryItem* Recorder::FindNodeHistoryItem(const ActorInstanceData& actorInstanceData, const AnimGraphNode* node, float recordTime) const { const AZStd::vector& historyItems = actorInstanceData.mNodeHistoryItems; - const uint32 numItems = historyItems.size(); - for (uint32 i = 0; i < numItems; ++i) + for (NodeHistoryItem* curItem : historyItems) { - NodeHistoryItem* curItem = historyItems[i]; if (curItem->mNodeId == node->GetId() && curItem->mStartTime <= recordTime && curItem->mIsFinalized == false) { return curItem; @@ -1073,21 +1055,19 @@ namespace EMotionFX // find a free track - uint32 Recorder::FindFreeNodeHistoryItemTrack(const ActorInstanceData& actorInstanceData, NodeHistoryItem* item) const + size_t Recorder::FindFreeNodeHistoryItemTrack(const ActorInstanceData& actorInstanceData, NodeHistoryItem* item) const { const AZStd::vector& historyItems = actorInstanceData.mNodeHistoryItems; - const uint32 numItems = historyItems.size(); bool found = false; - uint32 trackIndex = 0; + size_t trackIndex = 0; while (found == false) { bool hasCollision = false; - for (uint32 i = 0; i < numItems; ++i) + for (const NodeHistoryItem* curItem : historyItems) { - NodeHistoryItem* curItem = historyItems[i]; - if (curItem->mTrackIndex != trackIndex) + if (curItem->mTrackIndex != trackIndex) { continue; } @@ -1108,12 +1088,6 @@ namespace EMotionFX hasCollision = true; break; } - /* - if (MCore::Compare::CheckIfIsClose(item->mStartTime, curItem->mStartTime, 0.001f) || MCore::Compare::CheckIfIsClose(item->mStartTime, curItem->mEndTime, 0.001f)) - { - hasCollision = true; - break; - }*/ } else // if the current item is still active and has no real end time yet { @@ -1140,14 +1114,12 @@ namespace EMotionFX // find the maximum track index - uint32 Recorder::CalcMaxNodeHistoryTrackIndex(const ActorInstanceData& actorInstanceData) const + size_t Recorder::CalcMaxNodeHistoryTrackIndex(const ActorInstanceData& actorInstanceData) const { - uint32 result = 0; + size_t result = 0; const AZStd::vector& historyItems = actorInstanceData.mNodeHistoryItems; - const uint32 numItems = historyItems.size(); - for (uint32 i = 0; i < numItems; ++i) + for (const NodeHistoryItem* curItem : historyItems) { - NodeHistoryItem* curItem = historyItems[i]; if (curItem->mTrackIndex > result) { result = curItem->mTrackIndex; @@ -1159,14 +1131,12 @@ namespace EMotionFX // find the maximum event track index - uint32 Recorder::CalcMaxEventHistoryTrackIndex(const ActorInstanceData& actorInstanceData) const + size_t Recorder::CalcMaxEventHistoryTrackIndex(const ActorInstanceData& actorInstanceData) const { - uint32 result = 0; + size_t result = 0; const AZStd::vector& historyItems = actorInstanceData.mEventHistoryItems; - const uint32 numItems = historyItems.size(); - for (uint32 i = 0; i < numItems; ++i) + for (const EventHistoryItem* curItem : historyItems) { - EventHistoryItem* curItem = historyItems[i]; if (curItem->mTrackIndex > result) { result = curItem->mTrackIndex; @@ -1178,14 +1148,14 @@ namespace EMotionFX // find the maximum track index - uint32 Recorder::CalcMaxNodeHistoryTrackIndex() const + size_t Recorder::CalcMaxNodeHistoryTrackIndex() const { - uint32 result = 0; + size_t result = 0; // for all actor instances for (const ActorInstanceData* actorInstanceData : m_actorInstanceDatas) { - result = MCore::Max(result, CalcMaxNodeHistoryTrackIndex(*actorInstanceData)); + result = AZStd::max(result, CalcMaxNodeHistoryTrackIndex(*actorInstanceData)); } return result; @@ -1212,16 +1182,15 @@ namespace EMotionFX const AZStd::vector& historyItems = actorInstanceData->mNodeHistoryItems; // finalize all items - const uint32 numItems = historyItems.size(); - for (uint32 i = 0; i < numItems; ++i) + for (NodeHistoryItem* historyItem : historyItems) { // remove unneeded key frames - if (historyItems[i]->mIsFinalized == false) + if (historyItem->mIsFinalized == false) { - historyItems[i]->mGlobalWeights.Optimize(0.0001f); - historyItems[i]->mLocalWeights.Optimize(0.0001f); - historyItems[i]->mPlayTimes.Optimize(0.0001f); - historyItems[i]->mIsFinalized = true; + historyItem->mGlobalWeights.Optimize(0.0001f); + historyItem->mLocalWeights.Optimize(0.0001f); + historyItem->mPlayTimes.Optimize(0.0001f); + historyItem->mIsFinalized = true; } } } @@ -1246,8 +1215,8 @@ namespace EMotionFX // iterate over all events AZStd::vector& historyItems = actorInstanceData->mEventHistoryItems; - const uint32 numEvents = eventBuffer.GetNumEvents(); - for (uint32 i = 0; i < numEvents; ++i) + const size_t numEvents = eventBuffer.GetNumEvents(); + for (size_t i = 0; i < numEvents; ++i) { const EventInfo& eventInfo = eventBuffer.GetEvent(i); if (eventInfo.m_eventState == EventInfo::EventInfo::ACTIVE) @@ -1284,11 +1253,8 @@ namespace EMotionFX { MCORE_UNUSED(recordTime); const AZStd::vector& historyItems = actorInstanceData.mEventHistoryItems; - const uint32 numItems = historyItems.size(); - for (uint32 i = 0; i < numItems; ++i) + for (const EventHistoryItem* curItem : historyItems) { - EventHistoryItem* curItem = historyItems[i]; - if (curItem->mStartTime < eventInfo.mTimeValue) { continue; @@ -1300,19 +1266,17 @@ namespace EMotionFX // find a free event track index - uint32 Recorder::FindFreeEventHistoryItemTrack(const ActorInstanceData& actorInstanceData, EventHistoryItem* item) const + size_t Recorder::FindFreeEventHistoryItemTrack(const ActorInstanceData& actorInstanceData, EventHistoryItem* item) const { const AZStd::vector& historyItems = actorInstanceData.mEventHistoryItems; - const uint32 numItems = historyItems.size(); bool found = false; - uint32 trackIndex = 0; + size_t trackIndex = 0; while (found == false) { bool hasCollision = false; - for (uint32 i = 0; i < numItems; ++i) + for (const EventHistoryItem* curItem : historyItems) { - EventHistoryItem* curItem = historyItems[i]; if (curItem->mTrackIndex != trackIndex) { continue; @@ -1353,15 +1317,14 @@ namespace EMotionFX const AnimGraphInstanceData* animGraphData = actorInstanceData.mAnimGraphData; if (animGraphData == nullptr) { - return MCORE_INVALIDINDEX32; + return InvalidIndex; } - const uint32 numFrames = animGraphData->mFrames.size(); + const size_t numFrames = animGraphData->mFrames.size(); if (numFrames == 0) { - return MCORE_INVALIDINDEX32; + return InvalidIndex; } - else if (numFrames == 1) { return 0; @@ -1377,7 +1340,7 @@ namespace EMotionFX return animGraphData->mFrames.size() - 1; } - for (uint32 i = 0; i < numFrames - 1; ++i) + for (size_t i = 0; i < numFrames - 1; ++i) { const AnimGraphAnimFrame& curFrame = animGraphData->mFrames[i]; const AnimGraphAnimFrame& nextFrame = animGraphData->mFrames[i + 1]; @@ -1387,7 +1350,7 @@ namespace EMotionFX } } - return MCORE_INVALIDINDEX32; + return InvalidIndex; } void Recorder::RemoveActorInstanceFromRecording(ActorInstance* actorInstance) @@ -1401,7 +1364,7 @@ namespace EMotionFX recordedActorInstances.end()); // Remove the actual recorded data. - for (uint32 i = 0; i < m_actorInstanceDatas.size();) + for (size_t i = 0; i < m_actorInstanceDatas.size();) { if (m_actorInstanceDatas[i]->mActorInstance == actorInstance) { @@ -1458,12 +1421,12 @@ namespace EMotionFX // extract sorted active items - void Recorder::ExtractNodeHistoryItems(const ActorInstanceData& actorInstanceData, float timeValue, bool sort, EValueType valueType, AZStd::vector* outItems, AZStd::vector* outMap) + void Recorder::ExtractNodeHistoryItems(const ActorInstanceData& actorInstanceData, float timeValue, bool sort, EValueType valueType, AZStd::vector* outItems, AZStd::vector* outMap) const { // clear the map array - const uint32 maxIndex = CalcMaxNodeHistoryTrackIndex(actorInstanceData); + const size_t maxIndex = CalcMaxNodeHistoryTrackIndex(actorInstanceData); outItems->resize(maxIndex + 1); - for (uint32 i = 0; i <= maxIndex; ++i) + for (size_t i = 0; i <= maxIndex; ++i) { ExtractedNodeHistoryItem item; item.mTrackIndex = i; @@ -1475,10 +1438,8 @@ namespace EMotionFX // find all node history items const AZStd::vector& historyItems = actorInstanceData.mNodeHistoryItems; - const uint32 numItems = historyItems.size(); - for (uint32 i = 0; i < numItems; ++i) + for (NodeHistoryItem* curItem : historyItems) { - NodeHistoryItem* curItem = historyItems[i]; if (curItem->mStartTime <= timeValue && curItem->mEndTime > timeValue) { ExtractedNodeHistoryItem item; @@ -1511,7 +1472,7 @@ namespace EMotionFX // build the map outMap->resize(maxIndex + 1); - for (uint32 i = 0; i <= maxIndex; ++i) + for (size_t i = 0; i <= maxIndex; ++i) { outMap->emplace(AZStd::next(begin(*outMap), i), i); } @@ -1521,7 +1482,7 @@ namespace EMotionFX { AZStd::sort(begin(*outItems), end(*outItems)); - for (uint32 i = 0; i <= maxIndex; ++i) + for (size_t i = 0; i <= maxIndex; ++i) { outMap->emplace(AZStd::next(begin(*outMap), outItems->at(i).mTrackIndex), i); } @@ -1529,17 +1490,17 @@ namespace EMotionFX } - AZ::u32 Recorder::CalcMaxNumActiveMotions(const ActorInstanceData& actorInstanceData) const + size_t Recorder::CalcMaxNumActiveMotions(const ActorInstanceData& actorInstanceData) const { - AZ::u32 result = 0; + size_t result = 0; // Array of flags that each iteration will use to determine if a given track has already been counted in or not. AZStd::vector trackFlags; const size_t maxNumTracks = static_cast(CalcMaxNodeHistoryTrackIndex()) + 1; trackFlags.resize(maxNumTracks); - const uint32 numNodeHistoryItems = actorInstanceData.mNodeHistoryItems.size(); - for (uint32 i = 0; i < numNodeHistoryItems; ++i) + const size_t numNodeHistoryItems = actorInstanceData.mNodeHistoryItems.size(); + for (size_t i = 0; i < numNodeHistoryItems; ++i) { EMotionFX::Recorder::NodeHistoryItem* item = actorInstanceData.mNodeHistoryItems[i]; @@ -1556,10 +1517,10 @@ namespace EMotionFX } // We at least have a single active motion. - AZ::u32 intermediateResult = 1; + size_t intermediateResult = 1; trackFlags[item->mTrackIndex] = true; - for (uint32 j = 0; j < numNodeHistoryItems; ++j) + for (size_t j = 0; j < numNodeHistoryItems; ++j) { EMotionFX::Recorder::NodeHistoryItem* innerItem = actorInstanceData.mNodeHistoryItems[j]; @@ -1586,20 +1547,20 @@ namespace EMotionFX } } - result = MCore::Max(result, intermediateResult); + result = AZStd::max(result, intermediateResult); } return result; } - AZ::u32 Recorder::CalcMaxNumActiveMotions() const + size_t Recorder::CalcMaxNumActiveMotions() const { - AZ::u32 result = 0; + size_t result = 0; for (const ActorInstanceData* actorInstanceData : m_actorInstanceDatas) { - result = MCore::Max(result, CalcMaxNumActiveMotions(*actorInstanceData)); + result = AZStd::max(result, CalcMaxNumActiveMotions(*actorInstanceData)); } return result; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Recorder.h b/Gems/EMotionFX/Code/EMotionFX/Source/Recorder.h index 02a61627a4..a727750d1f 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Recorder.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Recorder.h @@ -63,7 +63,7 @@ namespace EMotionFX AZStd::unordered_set mNodeHistoryTypesToIgnore; /**< The array of type node type IDs to NOT capture. Empty array means nothing to ignore. */ uint32 mFPS; /**< The rate at which to sample (default=15). */ uint32 mNumPreAllocTransformKeys; /**< Pre-allocate space for this amount of transformation keys per node per actor instance (default=32). */ - uint32 mInitialAnimGraphAnimBytes; /**< The number of bytes to allocate to store the anim graph recording (default=2*1024*1024, which is 2mb). This is only used when actually recording anim graph internal state animation. */ + size_t mInitialAnimGraphAnimBytes; /**< The number of bytes to allocate to store the anim graph recording (default=2*1024*1024, which is 2mb). This is only used when actually recording anim graph internal state animation. */ bool mRecordTransforms; /**< Record transformations? (default=true). */ bool mRecordAnimGraphStates; /**< Record the anim graph internal state? (default=false). */ bool mRecordNodeHistory; /**< Record the node history? (default=false). */ @@ -95,8 +95,8 @@ namespace EMotionFX struct EMFX_API EventHistoryItem { EventInfo mEventInfo; - uint32 mEventIndex; /**< The index to use in combination with GetEventManager().GetEvent(index). */ - uint32 mTrackIndex; + size_t mEventIndex; /**< The index to use in combination with GetEventManager().GetEvent(index). */ + size_t mTrackIndex; AnimGraphNodeId mEmitterNodeId; uint32 mAnimGraphID; AZ::Color mColor; @@ -106,8 +106,8 @@ namespace EMotionFX EventHistoryItem() { - mEventIndex = MCORE_INVALIDINDEX32; - mTrackIndex = MCORE_INVALIDINDEX32; + mEventIndex = InvalidIndex; + mTrackIndex = InvalidIndex; mEmitterNodeId = AnimGraphNodeId(); mAnimGraphID = MCORE_INVALIDINDEX32; @@ -130,7 +130,7 @@ namespace EMotionFX KeyTrackLinearDynamic mLocalWeights; // the local weights at given time values KeyTrackLinearDynamic mPlayTimes; // normalized time values (current time in the node/motion) uint32 mMotionID; // the ID of the Motion object used - uint32 mTrackIndex; // the track index + size_t mTrackIndex; // the track index uint32 mCachedKey; // a cached key AnimGraphNodeId mNodeId; // animgraph node Id AnimGraphInstance* mAnimGraphInstance; // the anim graph instance this node was recorded from @@ -146,7 +146,7 @@ namespace EMotionFX mStartTime = 0.0f; mEndTime = 0.0f; mMotionID = MCORE_INVALIDINDEX32; - mTrackIndex = MCORE_INVALIDINDEX32; + mTrackIndex = InvalidIndex; mCachedKey = MCORE_INVALIDINDEX32; mNodeId = AnimGraphNodeId(); mAnimGraphInstance = nullptr; @@ -169,7 +169,7 @@ namespace EMotionFX struct EMFX_API ExtractedNodeHistoryItem { NodeHistoryItem* mNodeHistoryItem; - uint32 mTrackIndex; + size_t mTrackIndex; float mValue; float mKeyTrackSampleTime; @@ -194,7 +194,7 @@ namespace EMotionFX struct EMFX_API AnimGraphAnimObjectInfo { - uint32 mFrameByteOffset; + size_t mFrameByteOffset; AnimGraphObject* mObject; }; @@ -202,8 +202,8 @@ namespace EMotionFX struct EMFX_API AnimGraphAnimFrame { float mTimeValue = 0.0f; - uint32 mByteOffset = 0; - uint32 mNumBytes = 0; + size_t mByteOffset = 0; + size_t mNumBytes = 0; AZStd::vector mObjectInfos{}; AZStd::vector> mParameterValues{}; }; @@ -211,8 +211,8 @@ namespace EMotionFX struct EMFX_API AnimGraphInstanceData { AnimGraphInstance* mAnimGraphInstance = nullptr; - uint32 mNumFrames = 0; - uint32 mDataBufferSize = 0; + size_t mNumFrames = 0; + size_t mDataBufferSize = 0; uint8* mDataBuffer = nullptr; AZStd::vector mFrames{}; @@ -287,18 +287,16 @@ namespace EMotionFX ~ActorInstanceData() { // clear the node history items - const uint32 numMotionItems = mNodeHistoryItems.size(); - for (uint32 i = 0; i < numMotionItems; ++i) + for (NodeHistoryItem* nodeHistoryItem : mNodeHistoryItems) { - delete mNodeHistoryItems[i]; + delete nodeHistoryItem; } mNodeHistoryItems.clear(); // clear the event history items - const uint32 numEventItems = mEventHistoryItems.size(); - for (uint32 i = 0; i < numEventItems; ++i) + for (auto & eventHistoryItem : mEventHistoryItems) { - delete mEventHistoryItems[i]; + delete eventHistoryItem; } mEventHistoryItems.clear(); @@ -315,7 +313,6 @@ namespace EMotionFX static Recorder* Create(); - void Reserve(uint32 numTransformKeys); bool HasRecording() const; void Clear(); void StartRecording(const RecordSettings& settings); @@ -348,17 +345,17 @@ namespace EMotionFX const AZStd::vector& GetTimeDeltas() { return m_timeDeltas; } MCORE_INLINE size_t GetNumActorInstanceDatas() const { return m_actorInstanceDatas.size(); } - MCORE_INLINE ActorInstanceData& GetActorInstanceData(uint32 index) { return *m_actorInstanceDatas[index]; } - MCORE_INLINE const ActorInstanceData& GetActorInstanceData(uint32 index) const { return *m_actorInstanceDatas[index]; } - uint32 FindActorInstanceDataIndex(ActorInstance* actorInstance) const; + MCORE_INLINE ActorInstanceData& GetActorInstanceData(size_t index) { return *m_actorInstanceDatas[index]; } + MCORE_INLINE const ActorInstanceData& GetActorInstanceData(size_t index) const { return *m_actorInstanceDatas[index]; } + size_t FindActorInstanceDataIndex(ActorInstance* actorInstance) const; - uint32 CalcMaxNodeHistoryTrackIndex(const ActorInstanceData& actorInstanceData) const; - uint32 CalcMaxNodeHistoryTrackIndex() const; - uint32 CalcMaxEventHistoryTrackIndex(const ActorInstanceData& actorInstanceData) const; - AZ::u32 CalcMaxNumActiveMotions(const ActorInstanceData& actorInstanceData) const; - AZ::u32 CalcMaxNumActiveMotions() const; + size_t CalcMaxNodeHistoryTrackIndex(const ActorInstanceData& actorInstanceData) const; + size_t CalcMaxNodeHistoryTrackIndex() const; + size_t CalcMaxEventHistoryTrackIndex(const ActorInstanceData& actorInstanceData) const; + size_t CalcMaxNumActiveMotions(const ActorInstanceData& actorInstanceData) const; + size_t CalcMaxNumActiveMotions() const; - void ExtractNodeHistoryItems(const ActorInstanceData& actorInstanceData, float timeValue, bool sort, EValueType valueType, AZStd::vector* outItems, AZStd::vector* outMap); + void ExtractNodeHistoryItems(const ActorInstanceData& actorInstanceData, float timeValue, bool sort, EValueType valueType, AZStd::vector* outItems, AZStd::vector* outMap) const; void StartPlayBack(); void StopPlayBack(); @@ -403,12 +400,12 @@ namespace EMotionFX // /param numBytes bytes. Returns true if the buffer is big enough // after the operation, false otherwise. False indicates there's not // enough memory to accommodate the request - bool AssureAnimGraphBufferSize(AnimGraphInstanceData& animGraphInstanceData, uint32 numBytes); - NodeHistoryItem* FindNodeHistoryItem(const ActorInstanceData& actorInstanceData, AnimGraphNode* node, float recordTime) const; - uint32 FindFreeNodeHistoryItemTrack(const ActorInstanceData& actorInstanceData, NodeHistoryItem* item) const; + bool AssureAnimGraphBufferSize(AnimGraphInstanceData& animGraphInstanceData, size_t numBytes); + NodeHistoryItem* FindNodeHistoryItem(const ActorInstanceData& actorInstanceData, const AnimGraphNode* node, float recordTime) const; + size_t FindFreeNodeHistoryItemTrack(const ActorInstanceData& actorInstanceData, NodeHistoryItem* item) const; void FinalizeAllNodeHistoryItems(); EventHistoryItem* FindEventHistoryItem(const ActorInstanceData& actorInstanceData, const EventInfo& eventInfo, float recordTime); - uint32 FindFreeEventHistoryItemTrack(const ActorInstanceData& actorInstanceData, EventHistoryItem* item) const; + size_t FindFreeEventHistoryItemTrack(const ActorInstanceData& actorInstanceData, EventHistoryItem* item) const; size_t FindAnimGraphDataFrameNumber(float timeValue) const; }; } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/RepositioningLayerPass.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/RepositioningLayerPass.cpp index 68c2f2a5c3..6bbf60700b 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/RepositioningLayerPass.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/RepositioningLayerPass.cpp @@ -26,7 +26,7 @@ namespace EMotionFX RepositioningLayerPass::RepositioningLayerPass(MotionLayerSystem* motionLayerSystem) : LayerPass(motionLayerSystem) { - mLastReposNode = MCORE_INVALIDINDEX32; + mLastReposNode = InvalidIndex; } @@ -77,8 +77,8 @@ namespace EMotionFX // Bottom up traversal of the layers. bool firstBlend = true; - const uint32 numMotionInstances = mMotionSystem->GetNumMotionInstances(); - for (uint32 i = numMotionInstances - 1; i != MCORE_INVALIDINDEX32; --i) + const size_t numMotionInstances = mMotionSystem->GetNumMotionInstances(); + for (size_t i = numMotionInstances - 1; i != InvalidIndex; --i) { MotionInstance* motionInstance = mMotionSystem->GetMotionInstance(i); if (!motionInstance->GetMotionExtractionEnabled()) diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/RepositioningLayerPass.h b/Gems/EMotionFX/Code/EMotionFX/Source/RepositioningLayerPass.h index 05f09d6329..4df680092a 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/RepositioningLayerPass.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/RepositioningLayerPass.h @@ -59,8 +59,8 @@ namespace EMotionFX private: - AZStd::vector mHierarchyPath; /**< The path of node indices to the repositioning node. */ - uint32 mLastReposNode; /**< The last repositioning node index that was used. When this changes, the hierarchy path has to be updated. */ + AZStd::vector mHierarchyPath; /**< The path of node indices to the repositioning node. */ + size_t mLastReposNode; /**< The last repositioning node index that was used. When this changes, the hierarchy path has to be updated. */ /** * The constructor. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/SimulatedObjectSetup.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/SimulatedObjectSetup.cpp index 006be1d9a5..8615ac623b 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/SimulatedObjectSetup.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/SimulatedObjectSetup.cpp @@ -98,7 +98,7 @@ namespace EMotionFX } } - SimulatedJoint::SimulatedJoint(SimulatedObject* object, AZ::u32 skeletonJointIndex) + SimulatedJoint::SimulatedJoint(SimulatedObject* object, size_t skeletonJointIndex) : m_object(object) , m_jointIndex(skeletonJointIndex) { @@ -163,7 +163,7 @@ namespace EMotionFX { return nullptr; } - const AZ::u32 parentIndex = skeletonJoint->GetParentIndex(); + const size_t parentIndex = skeletonJoint->GetParentIndex(); return m_object->FindSimulatedJointBySkeletonJointIndex(parentIndex); } @@ -176,11 +176,11 @@ namespace EMotionFX { return nullptr; } - const AZ::u32 childCount = skeletonJoint->GetNumChildNodes(); + const size_t childCount = skeletonJoint->GetNumChildNodes(); size_t count = 0; - for (AZ::u32 i = 0; i < childCount; ++i) + for (size_t i = 0; i < childCount; ++i) { - const AZ::u32 skeletonChildJointIndex = skeletonJoint->GetChildIndex(i); + const size_t skeletonChildJointIndex = skeletonJoint->GetChildIndex(i); if (m_object->FindSimulatedJointBySkeletonJointIndex(skeletonChildJointIndex)) { if (count == childIndex) @@ -214,11 +214,11 @@ namespace EMotionFX { return 0; } - const AZ::u32 childCount = skeletonJoint->GetNumChildNodes(); + const size_t childCount = skeletonJoint->GetNumChildNodes(); size_t count = 0; - for (AZ::u32 i = 0; i < childCount; ++i) + for (size_t i = 0; i < childCount; ++i) { - const AZ::u32 childIndex = skeletonJoint->GetChildIndex(i); + const size_t childIndex = skeletonJoint->GetChildIndex(i); if (m_object->FindSimulatedJointBySkeletonJointIndex(childIndex)) { count++; @@ -239,7 +239,7 @@ namespace EMotionFX return sum; } - AZ::u32 SimulatedJoint::CalculateChildIndex() const + size_t SimulatedJoint::CalculateChildIndex() const { const Actor* actor = m_object->GetSimulatedObjectSetup()->GetActor(); const SimulatedJoint* parentJoint = FindParentSimulatedJoint(); @@ -250,11 +250,11 @@ namespace EMotionFX { return 0; } - const AZ::u32 numChildSkeletonJoints = parentSkeletonJoint->GetNumChildNodes(); - AZ::u32 childSimulatedJointIndex = 0; - for (AZ::u32 i = 0; i < numChildSkeletonJoints; ++i) + const size_t numChildSkeletonJoints = parentSkeletonJoint->GetNumChildNodes(); + size_t childSimulatedJointIndex = 0; + for (size_t i = 0; i < numChildSkeletonJoints; ++i) { - AZ::u32 childJointIndex = parentSkeletonJoint->GetChildIndex(i); + size_t childJointIndex = parentSkeletonJoint->GetChildIndex(i); SimulatedJoint* childSimulatedJoint = m_object->FindSimulatedJointBySkeletonJointIndex(childJointIndex); if (childSimulatedJoint) { @@ -271,8 +271,8 @@ namespace EMotionFX } // If the simuated joint doesn't have a parent joint, it should be a root joint. - AZ::u32 rootJointIndex = static_cast(m_object->GetSimulatedRootJointIndex(this)); - AZ_Error("EMotionFX", rootJointIndex != MCORE_INVALIDINDEX32, "This joint should be a root joint."); + size_t rootJointIndex = m_object->GetSimulatedRootJointIndex(this); + AZ_Error("EMotionFX", rootJointIndex != InvalidIndex, "This joint should be a root joint."); return rootJointIndex; } @@ -320,7 +320,7 @@ namespace EMotionFX m_rootJoints.clear(); } - SimulatedJoint* SimulatedObject::FindSimulatedJointBySkeletonJointIndex(AZ::u32 skeletonJointIndex) const + SimulatedJoint* SimulatedObject::FindSimulatedJointBySkeletonJointIndex(size_t skeletonJointIndex) const { for (SimulatedJoint* joint : m_joints) { @@ -348,10 +348,10 @@ namespace EMotionFX const auto found = AZStd::find(m_rootJoints.begin(), m_rootJoints.end(), rootJoint); if (found != m_rootJoints.end()) { - return static_cast(AZStd::distance(m_rootJoints.begin(), found)); + return AZStd::distance(m_rootJoints.begin(), found); } - return MCORE_INVALIDINDEX32; + return InvalidIndex; } void SimulatedObject::Reflect(AZ::ReflectContext* context) @@ -430,13 +430,13 @@ namespace EMotionFX BuildRootJointList(); } - SimulatedJoint* SimulatedObject::AddSimulatedJoint(AZ::u32 jointIndex) + SimulatedJoint* SimulatedObject::AddSimulatedJoint(size_t jointIndex) { AddSimulatedJoints({ jointIndex }); return FindSimulatedJointBySkeletonJointIndex(jointIndex); } - void SimulatedObject::AddSimulatedJoints(AZStd::vector jointIndexes) + void SimulatedObject::AddSimulatedJoints(AZStd::vector jointIndexes) { AZStd::sort(jointIndexes.begin(), jointIndexes.end()); @@ -445,10 +445,10 @@ namespace EMotionFX BuildRootJointList(); } - void SimulatedObject::AddSimulatedJointAndChildren(AZ::u32 jointIndex) + void SimulatedObject::AddSimulatedJointAndChildren(size_t jointIndex) { - AZStd::vector jointsToAdd; - AZStd::queue toVisit; + AZStd::vector jointsToAdd; + AZStd::queue toVisit; toVisit.emplace(jointIndex); const Skeleton* skeleton = m_simulatedObjectSetup->GetActor()->GetSkeleton(); @@ -456,7 +456,7 @@ namespace EMotionFX // Collect all the joint indices to add while (!toVisit.empty()) { - const AZ::u32 currentIndex = toVisit.front(); + const size_t currentIndex = toVisit.front(); toVisit.pop(); jointsToAdd.emplace_back(currentIndex); @@ -467,7 +467,7 @@ namespace EMotionFX const size_t childNodeCount = node->GetNumChildNodes(); for (size_t i = 0; i < childNodeCount; ++i) { - const AZ::u32 childNodeIndex = node->GetChildIndex(static_cast(i)); + const size_t childNodeIndex = node->GetChildIndex(i); toVisit.emplace(childNodeIndex); } } @@ -484,7 +484,7 @@ namespace EMotionFX BuildRootJointList(); } - void SimulatedObject::MergeAndMakeJoints(const AZStd::vector& jointsToAdd) + void SimulatedObject::MergeAndMakeJoints(const AZStd::vector& jointsToAdd) { AZStd::vector newJointList; @@ -537,7 +537,7 @@ namespace EMotionFX return AZStd::string::format("%zu joint%s selected", jointCounts, jointCounts == 1? "" : "s"); } - void SimulatedObject::RemoveSimulatedJoint(AZ::u32 jointIndex, bool removeChildren) + void SimulatedObject::RemoveSimulatedJoint(size_t jointIndex, bool removeChildren) { // If we order the joints storage so that the leaf node always comes late than its parent, we can do the remove in one iteration. bool removed = false; @@ -578,7 +578,7 @@ namespace EMotionFX size_t childNodeCount = node->GetNumChildNodes(); for (size_t i = 0; i < childNodeCount; ++i) { - const AZ::u32 childNodeIndex = node->GetChildIndex(static_cast(i)); + const size_t childNodeIndex = node->GetChildIndex(i); if (FindSimulatedJointBySkeletonJointIndex(childNodeIndex)) { RemoveSimulatedJoint(childNodeIndex, true); @@ -602,12 +602,12 @@ namespace EMotionFX currentParents.emplace(current); toCheck.erase(toCheck.find(joint)); - while (current && current->GetSkeletonJointIndex() != MCORE_INVALIDINDEX32 && !((seenJoints.find(current) != seenJoints.end()) || (toCheck.find(current) != toCheck.end()))) + while (current && current->GetSkeletonJointIndex() != InvalidIndex && !((seenJoints.find(current) != seenJoints.end()) || (toCheck.find(current) != toCheck.end()))) { current = current->FindParentSimulatedJoint(); } - if (!current || current->GetSkeletonJointIndex() == MCORE_INVALIDINDEX32) + if (!current || current->GetSkeletonJointIndex() == InvalidIndex) { // We reached the top of the model without seeing any other // model index (or parent thereof) in modelIndices. This is a diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/SimulatedObjectSetup.h b/Gems/EMotionFX/Code/EMotionFX/Source/SimulatedObjectSetup.h index 6d052172bc..57deef4cad 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/SimulatedObjectSetup.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/SimulatedObjectSetup.h @@ -50,7 +50,7 @@ namespace EMotionFX }; SimulatedJoint() = default; - SimulatedJoint(SimulatedObject* object, AZ::u32 skeletonJointIndex); + SimulatedJoint(SimulatedObject* object, size_t skeletonJointIndex); ~SimulatedJoint() override = default; SimulatedJoint* FindParentSimulatedJoint() const; @@ -58,12 +58,12 @@ namespace EMotionFX AZ::Outcome CalculateSimulatedJointIndex() const; size_t CalculateNumChildSimulatedJoints() const; size_t CalculateNumChildSimulatedJointsRecursive() const; - AZ::u32 CalculateChildIndex() const; + size_t CalculateChildIndex() const; bool InitAfterLoading(SimulatedObject* object); void SetSimulatedObject(SimulatedObject* object) { m_object = object; } - void SetSkeletonJointIndex(AZ::u32 jointIndex) { m_jointIndex = jointIndex; } + void SetSkeletonJointIndex(size_t jointIndex) { m_jointIndex = jointIndex; } void SetConeAngleLimit(float degrees) { m_coneAngleLimit = degrees; } void SetMass(float mass) { m_mass = mass; } void SetCollisionRadius(float radius) @@ -81,7 +81,7 @@ namespace EMotionFX void SetGeometricAutoExclusion(bool enabled) { m_autoExcludeGeometric = enabled; } SimulatedObject* GetSimulatedObject() const { return m_object; } - AZ::u32 GetSkeletonJointIndex() const { return m_jointIndex; } + size_t GetSkeletonJointIndex() const { return m_jointIndex; } float GetConeAngleLimit() const { return m_coneAngleLimit; } float GetMass() const { return m_mass; } float GetCollisionRadius() const { return m_radius; } @@ -101,7 +101,7 @@ namespace EMotionFX AZ::Crc32 GetPinnedOptionVisibility() const; SimulatedObject* m_object = nullptr; /**< The simulated object we belong to. */ - AZ::u32 m_jointIndex = 0; /**< The joint index inside the skeleton of the actor. */ + size_t m_jointIndex = 0; /**< The joint index inside the skeleton of the actor. */ AZStd::string m_jointName; /**< The joint name in the actor skeleton. */ float m_coneAngleLimit = 60.0f; /**< The conic angular limit, in degrees. A value of 180 means there are no limits. */ float m_mass = 1.0f; /**< The mass of the joint. */ @@ -129,12 +129,12 @@ namespace EMotionFX void Clear(); - SimulatedJoint* FindSimulatedJointBySkeletonJointIndex(AZ::u32 skeletonJointIndex) const; + SimulatedJoint* FindSimulatedJointBySkeletonJointIndex(size_t skeletonJointIndex) const; bool ContainsSimulatedJoint(const SimulatedJoint* joint) const; - SimulatedJoint* AddSimulatedJoint(AZ::u32 jointIndex); - void AddSimulatedJoints(AZStd::vector jointIndexes); - void AddSimulatedJointAndChildren(AZ::u32 jointIndex); - void RemoveSimulatedJoint(AZ::u32 jointIndex, bool removeChildren = false); + SimulatedJoint* AddSimulatedJoint(size_t jointIndex); + void AddSimulatedJoints(AZStd::vector jointIndexes); + void AddSimulatedJointAndChildren(size_t jointIndex); + void RemoveSimulatedJoint(size_t jointIndex, bool removeChildren = false); size_t GetNumSimulatedJoints() const { return m_joints.size(); } SimulatedJoint* GetSimulatedRootJoint(size_t rootIndex) const; @@ -167,7 +167,7 @@ namespace EMotionFX void SetSimulatedObjectSetup(SimulatedObjectSetup* setup) { m_simulatedObjectSetup = setup; } void BuildRootJointList(); void SortJointList(); - void MergeAndMakeJoints(const AZStd::vector& jointsToAdd); + void MergeAndMakeJoints(const AZStd::vector& jointsToAdd); AZStd::string GetJointsTextOverride() const; AZStd::string GetColliderTag(int index) const; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/SingleThreadScheduler.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/SingleThreadScheduler.cpp index a8c78ee823..0e871499df 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/SingleThreadScheduler.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/SingleThreadScheduler.cpp @@ -50,8 +50,8 @@ namespace EMotionFX mNumSampled.SetValue(0); // propagate root actor instance visibility to their attachments - const uint32 numRootActorInstances = GetActorManager().GetNumRootActorInstances(); - for (uint32 i = 0; i < numRootActorInstances; ++i) + const size_t numRootActorInstances = GetActorManager().GetNumRootActorInstances(); + for (size_t i = 0; i < numRootActorInstances; ++i) { ActorInstance* rootInstance = actorManager.GetRootActorInstance(i); if (rootInstance->GetIsEnabled() == false) @@ -62,17 +62,8 @@ namespace EMotionFX rootInstance->RecursiveSetIsVisible(rootInstance->GetIsVisible()); } - /* // make sure parents of attachments are updated as well - const uint32 numActorInstances = actorManager.GetNumActorInstances(); - for (uint32 i=0; iGetIsVisible()) - actorInstance->RecursiveSetIsVisibleTowardsRoot( true ); - }*/ - // process all root actor instances, and execute them and their attachments - for (uint32 i = 0; i < numRootActorInstances; ++i) + for (size_t i = 0; i < numRootActorInstances; ++i) { ActorInstance* rootActorInstance = actorManager.GetRootActorInstance(i); if (rootActorInstance->GetIsEnabled() == false) @@ -117,8 +108,8 @@ namespace EMotionFX actorInstance->UpdateTransformations(timePassedInSeconds, isVisible, sampleMotions); // recursively process the attachments - const uint32 numAttachments = actorInstance->GetNumAttachments(); - for (uint32 i = 0; i < numAttachments; ++i) + const size_t numAttachments = actorInstance->GetNumAttachments(); + for (size_t i = 0; i < numAttachments; ++i) { ActorInstance* attachment = actorInstance->GetAttachment(i)->GetAttachmentActorInstance(); if (attachment && attachment->GetIsEnabled()) diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/SingleThreadScheduler.h b/Gems/EMotionFX/Code/EMotionFX/Source/SingleThreadScheduler.h index 76b496e6d8..49f1725cc0 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/SingleThreadScheduler.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/SingleThreadScheduler.h @@ -73,14 +73,14 @@ namespace EMotionFX * @param actorInstance The actor instance to insert. * @param startStep An offset in the schedule where to start trying to insert the actor instances. */ - void RecursiveInsertActorInstance(ActorInstance* actorInstance, uint32 startStep = 0) override { MCORE_UNUSED(actorInstance); MCORE_UNUSED(startStep); } + void RecursiveInsertActorInstance(ActorInstance* actorInstance, size_t startStep = 0) override { MCORE_UNUSED(actorInstance); MCORE_UNUSED(startStep); } /** * Recursively remove an actor instance and its attachments from the schedule. * @param actorInstance The actor instance to remove. * @param startStep An offset in the schedule where to start trying to remove from. */ - void RecursiveRemoveActorInstance(ActorInstance* actorInstance, uint32 startStep = 0) override { MCORE_UNUSED(actorInstance); MCORE_UNUSED(startStep); } + void RecursiveRemoveActorInstance(ActorInstance* actorInstance, size_t startStep = 0) override { MCORE_UNUSED(actorInstance); MCORE_UNUSED(startStep); } /** * Remove a single actor instance from the schedule. This will not remove its attachments. @@ -88,7 +88,7 @@ namespace EMotionFX * @param startStep An offset in the schedule where to start trying to remove from. * @result Returns the offset in the schedule where the actor instance was removed. */ - uint32 RemoveActorInstance(ActorInstance* actorInstance, uint32 startStep = 0) override { MCORE_UNUSED(actorInstance); MCORE_UNUSED(startStep); return 0; } + size_t RemoveActorInstance(ActorInstance* actorInstance, size_t startStep = 0) override { MCORE_UNUSED(actorInstance); MCORE_UNUSED(startStep); return 0; } protected: /** diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/SkinningInfoVertexAttributeLayer.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/SkinningInfoVertexAttributeLayer.cpp index 3ccfa85ca8..4483d98e40 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/SkinningInfoVertexAttributeLayer.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/SkinningInfoVertexAttributeLayer.cpp @@ -308,20 +308,20 @@ namespace EMotionFX GetInfluence(attributeNr, 0)->SetWeight(1.0f); } - AZStd::set SkinningInfoVertexAttributeLayer::CalcLocalJointIndices(AZ::u32 numOrgVertices) + AZStd::set SkinningInfoVertexAttributeLayer::CalcLocalJointIndices(AZ::u32 numOrgVertices) { - AZStd::set result; + AZStd::set result; for (AZ::u32 i = 0; i < numOrgVertices; i++) { // now we have located the skinning information for this vertex, we can see if our bones array // already contains the bone it uses by traversing all influences for this vertex, and checking // if the bone of that influence already is in the array with used bones - const uint32 numInfluences = static_cast(GetNumInfluences(i)); - for (uint32 a = 0; a < numInfluences; ++a) + const size_t numInfluences = GetNumInfluences(i); + for (size_t a = 0; a < numInfluences; ++a) { EMotionFX::SkinInfluence* influence = GetInfluence(i, a); - const AZ::u32 jointNr = influence->GetNodeNr(); + const uint16 jointNr = influence->GetNodeNr(); result.emplace(jointNr); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/SkinningInfoVertexAttributeLayer.h b/Gems/EMotionFX/Code/EMotionFX/Source/SkinningInfoVertexAttributeLayer.h index c2a77ba13b..48eeabac77 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/SkinningInfoVertexAttributeLayer.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/SkinningInfoVertexAttributeLayer.h @@ -171,7 +171,7 @@ namespace EMotionFX * @param numOrgVertices The number of original vertices in the mesh. * @result Vector of unique joint indices used by the skinning info layer. */ - AZStd::set CalcLocalJointIndices(AZ::u32 numOrgVertices); + AZStd::set CalcLocalJointIndices(AZ::u32 numOrgVertices); /** * Clone the vertex attribute layer. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/SoftSkinDeformer.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/SoftSkinDeformer.cpp index a8fd925123..004e415501 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/SoftSkinDeformer.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/SoftSkinDeformer.cpp @@ -61,7 +61,7 @@ namespace EMotionFX // clone this class - MeshDeformer* SoftSkinDeformer::Clone(Mesh* mesh) + MeshDeformer* SoftSkinDeformer::Clone(Mesh* mesh) const { // create the new cloned deformer SoftSkinDeformer* result = aznew SoftSkinDeformer(mesh); @@ -89,7 +89,7 @@ namespace EMotionFX const size_t numBones = mBoneMatrices.size(); for (size_t i = 0; i < numBones; i++) { - const uint32 nodeIndex = mNodeNumbers[i]; + const size_t nodeIndex = mNodeNumbers[i]; mBoneMatrices[i] = skinningMatrices[nodeIndex]; } @@ -240,15 +240,15 @@ namespace EMotionFX SkinInfluence* influence = skinningLayer->GetInfluence(i, a); // get the bone index in the array - uint32 boneIndex = FindLocalBoneIndex(influence->GetNodeNr()); + size_t boneIndex = FindLocalBoneIndex(influence->GetNodeNr()); // if the bone is not found in our array - if (boneIndex == MCORE_INVALIDINDEX32) + if (boneIndex == InvalidIndex) { // add the bone to the array of bones in this deformer mNodeNumbers.emplace_back(influence->GetNodeNr()); mBoneMatrices.emplace_back(mat); - boneIndex = static_cast(mBoneMatrices.size()) - 1; + boneIndex = mBoneMatrices.size() - 1; } // set the bone number in the influence diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/SoftSkinDeformer.h b/Gems/EMotionFX/Code/EMotionFX/Source/SoftSkinDeformer.h index ab2d805ff1..466f1702a7 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/SoftSkinDeformer.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/SoftSkinDeformer.h @@ -78,7 +78,7 @@ namespace EMotionFX * @param mesh The mesh to apply the deformer on. * @result A pointer to the newly created clone of this deformer. */ - MeshDeformer* Clone(Mesh* mesh) override; + MeshDeformer* Clone(Mesh* mesh) const override; /** * Returns the unique type ID of the deformer. @@ -107,7 +107,7 @@ namespace EMotionFX * @param index The local bone number, which must be in range of [0..GetNumLocalBones()-1]. * @result The node number, which is in range of [0..Actor::GetNumNodes()-1], depending on the actor where this deformer works on. */ - MCORE_INLINE uint32 GetLocalBone(uint32 index) const { return mNodeNumbers[index]; } + MCORE_INLINE size_t GetLocalBone(size_t index) const { return mNodeNumbers[index]; } /** * Pre-allocate space for a given number of local bones. @@ -119,7 +119,7 @@ namespace EMotionFX protected: AZStd::vector mBoneMatrices; - AZStd::vector mNodeNumbers; + AZStd::vector mNodeNumbers; /** * Default constructor. @@ -137,18 +137,10 @@ namespace EMotionFX * @param nodeIndex The node number to search for. * @result The index inside the mBones member array, which uses the given node. */ - MCORE_INLINE uint32 FindLocalBoneIndex(uint32 nodeIndex) const + MCORE_INLINE size_t FindLocalBoneIndex(size_t nodeIndex) const { - const size_t numBones = mNodeNumbers.size(); - for (size_t i = 0; i < numBones; ++i) - { - if (mNodeNumbers[i] == nodeIndex) - { - return static_cast(i); - } - } - - return MCORE_INVALIDINDEX32; + const auto foundBoneIndex = AZStd::find(begin(mNodeNumbers), end(mNodeNumbers), nodeIndex); + return foundBoneIndex != end(mNodeNumbers) ? AZStd::distance(begin(mNodeNumbers), foundBoneIndex) : InvalidIndex; } void SkinVertexRange(uint32 startVertex, uint32 endVertex, AZ::Vector3* positions, AZ::Vector3* normals, AZ::Vector4* tangents, AZ::Vector3* bitangents, uint32* orgVerts, SkinningInfoVertexAttributeLayer* layer); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/StandardMaterial.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/StandardMaterial.cpp index 98a192936e..4ee3a24056 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/StandardMaterial.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/StandardMaterial.cpp @@ -396,9 +396,9 @@ namespace EMotionFX standardMaterial->mWireFrame = mWireFrame; // copy the layers - const uint32 numLayers = mLayers.size(); + const size_t numLayers = mLayers.size(); standardMaterial->mLayers.resize(numLayers); - for (uint32 i = 0; i < numLayers; ++i) + for (size_t i = 0; i < numLayers; ++i) { standardMaterial->mLayers[i] = StandardMaterialLayer::Create(); standardMaterial->mLayers[i]->InitFrom(mLayers[i]); @@ -559,14 +559,14 @@ namespace EMotionFX } - StandardMaterialLayer* StandardMaterial::GetLayer(uint32 nr) + StandardMaterialLayer* StandardMaterial::GetLayer(size_t nr) { MCORE_ASSERT(nr < mLayers.size()); return mLayers[nr]; } - void StandardMaterial::RemoveLayer(uint32 nr, bool delFromMem) + void StandardMaterial::RemoveLayer(size_t nr, bool delFromMem) { MCORE_ASSERT(nr < mLayers.size()); if (delFromMem) @@ -580,33 +580,27 @@ namespace EMotionFX void StandardMaterial::RemoveAllLayers() { - const uint32 numLayers = mLayers.size(); - for (uint32 i = 0; i < numLayers; ++i) + for (StandardMaterialLayer* mLayer : mLayers) { - mLayers[i]->Destroy(); + mLayer->Destroy(); } mLayers.clear(); } - uint32 StandardMaterial::FindLayer(uint32 layerType) const + size_t StandardMaterial::FindLayer(uint32 layerType) const { // search through all layers - const uint32 numLayers = mLayers.size(); - for (uint32 i = 0; i < numLayers; ++i) + const auto foundLayer = AZStd::find_if(begin(mLayers), end(mLayers), [layerType](const StandardMaterialLayer* layer) { - if (mLayers[i]->GetType() == layerType) - { - return i; - } - } - - return MCORE_INVALIDINDEX32; + return layer->GetType() == layerType; + }); + return foundLayer != end(mLayers) ? AZStd::distance(begin(mLayers), foundLayer) : InvalidIndex; } - void StandardMaterial::ReserveLayers(uint32 numLayers) + void StandardMaterial::ReserveLayers(size_t numLayers) { mLayers.reserve(numLayers); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/StandardMaterial.h b/Gems/EMotionFX/Code/EMotionFX/Source/StandardMaterial.h index de637cf3df..05f8154a72 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/StandardMaterial.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/StandardMaterial.h @@ -403,7 +403,7 @@ namespace EMotionFX * This does not influence the return value of GetNumLayers(). * @param numLayers The number of layers to pre-allocate space for. */ - void ReserveLayers(uint32 numLayers); + void ReserveLayers(size_t numLayers); /** * Add a given layer to this material. @@ -422,14 +422,14 @@ namespace EMotionFX * @param nr The material layer number to get. * @result A pointer to the material layer. */ - StandardMaterialLayer* GetLayer(uint32 nr); + StandardMaterialLayer* GetLayer(size_t nr); /** * Remove a specified material layer (also deletes it from memory). * @param nr The material layer number to remove. * @param delFromMem Set to true if it should be deleted from memory as well. */ - void RemoveLayer(uint32 nr, bool delFromMem = true); + void RemoveLayer(size_t nr, bool delFromMem = true); /** * Removes all material layers from this material (includes deletion from memory). @@ -442,14 +442,14 @@ namespace EMotionFX * Find the layer number which is of the given type. * If you for example want to search for a diffuse layer, you make a call like: * - * uint32 layerNumber = material->FindLayer( StandardMaterialLayer::LAYERTYPE_DIFFUSE ); + * size_t layerNumber = material->FindLayer( StandardMaterialLayer::LAYERTYPE_DIFFUSE ); * * This will return a value the layer number, which can be accessed with the GetLayer(layerNumber) method. * A value of MCORE_INVALIDINDEX32 will be returned in case no layer of the specified type could be found. * @param layerType The layer type you want to search on, for a list of valid types, see the enum inside StandardMaterialLayer. * @result Returns the layer number or MCORE_INVALIDINDEX32 when it could not be found. */ - uint32 FindLayer(uint32 layerType) const; + size_t FindLayer(uint32 layerType) const; /** * Creates a clone of the material, including it's layers. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/TransformData.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/TransformData.cpp index 7701771952..5164f97c01 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/TransformData.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/TransformData.cpp @@ -72,7 +72,7 @@ namespace EMotionFX mPose.LinkToActorInstance(actorInstance); // release all memory if we want to resize to zero nodes - const uint32 numNodes = actorInstance->GetNumNodes(); + const size_t numNodes = actorInstance->GetNumNodes(); if (numNodes == 0) { Release(); @@ -93,7 +93,7 @@ namespace EMotionFX } // now initialize the data with the actor transforms - for (uint32 i = 0; i < numNodes; ++i) + for (size_t i = 0; i < numNodes; ++i) { mSkinningMatrices[i] = AZ::Matrix3x4::CreateIdentity(); } @@ -119,27 +119,27 @@ namespace EMotionFX EMFX_SCALECODE ( // set the scaling value for the node and all child nodes - void TransformData::SetBindPoseLocalScaleInherit(uint32 nodeIndex, const AZ::Vector3& scale) + void TransformData::SetBindPoseLocalScaleInherit(size_t nodeIndex, const AZ::Vector3& scale) { const ActorInstance* actorInstance = mPose.GetActorInstance(); const Actor* actor = actorInstance->GetActor(); // get the node index and the number of children of the given node const Node* node = actor->GetSkeleton()->GetNode(nodeIndex); - const uint32 numChilds = node->GetNumChildNodes(); + const size_t numChilds = node->GetNumChildNodes(); // set the new scale for the given node SetBindPoseLocalScale(nodeIndex, scale); // iterate through the children and set their scale recursively - for (uint32 i = 0; i < numChilds; ++i) + for (size_t i = 0; i < numChilds; ++i) { SetBindPoseLocalScaleInherit(node->GetChildIndex(i), scale); } } // update the local space scale - void TransformData::SetBindPoseLocalScale(uint32 nodeIndex, const AZ::Vector3& scale) + void TransformData::SetBindPoseLocalScale(size_t nodeIndex, const AZ::Vector3& scale) { Transform newTransform = mBindPose->GetLocalSpaceTransform(nodeIndex); newTransform.mScale = scale; @@ -148,7 +148,7 @@ namespace EMotionFX ) // EMFX_SCALECODE // set the number of morph weights - void TransformData::SetNumMorphWeights(uint32 numMorphWeights) + void TransformData::SetNumMorphWeights(size_t numMorphWeights) { mPose.ResizeNumMorphs(numMorphWeights); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/TransformData.h b/Gems/EMotionFX/Code/EMotionFX/Source/TransformData.h index fa0d430871..d4e70134a3 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/TransformData.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/TransformData.h @@ -81,14 +81,14 @@ namespace EMotionFX * Reset the local space transform of a given node to its bind pose local space transform. * @param nodeIndex The node number, which must be in range of [0..GetNumTransforms()-1]. */ - void ResetToBindPoseTransformation(uint32 nodeIndex) { mPose.SetLocalSpaceTransform(nodeIndex, mBindPose->GetLocalSpaceTransform(nodeIndex)); } + void ResetToBindPoseTransformation(size_t nodeIndex) { mPose.SetLocalSpaceTransform(nodeIndex, mBindPose->GetLocalSpaceTransform(nodeIndex)); } /** * Reset all local space transforms to the local space transforms of the bind pose. */ void ResetToBindPoseTransformations() { - for (uint32 i = 0; i < mNumTransforms; ++i) + for (size_t i = 0; i < mNumTransforms; ++i) { mPose.SetLocalSpaceTransform(i, mBindPose->GetLocalSpaceTransform(i)); } @@ -96,23 +96,23 @@ namespace EMotionFX EMFX_SCALECODE ( - void SetBindPoseLocalScaleInherit(uint32 nodeIndex, const AZ::Vector3& scale); - void SetBindPoseLocalScale(uint32 nodeIndex, const AZ::Vector3& scale); + void SetBindPoseLocalScaleInherit(size_t nodeIndex, const AZ::Vector3& scale); + void SetBindPoseLocalScale(size_t nodeIndex, const AZ::Vector3& scale); ) MCORE_INLINE const ActorInstance* GetActorInstance() const { return mPose.GetActorInstance(); } - MCORE_INLINE uint32 GetNumTransforms() const { return mNumTransforms; } + MCORE_INLINE size_t GetNumTransforms() const { return mNumTransforms; } void MakeBindPoseTransformsUnique(); - void SetNumMorphWeights(uint32 numMorphWeights); + void SetNumMorphWeights(size_t numMorphWeights); private: Pose mPose; /**< The current pose. */ Pose* mBindPose; /**< The bind pose, which can be unique or point to the bind pose in the actor. */ AZ::Matrix3x4* mSkinningMatrices; /**< The matrices used for skinning. They are the offset to the bind pose. */ - uint32 mNumTransforms; /**< The number of transforms, which is equal to the number of nodes in the linked actor instance. */ + size_t mNumTransforms; /**< The number of transforms, which is equal to the number of nodes in the linked actor instance. */ bool mHasUniqueBindPose; /**< Do we have a unique bind pose (when set to true) or do we use the one from the Actor object (when set to false)? */ /** diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/PluginManager.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/PluginManager.cpp index 7a90e4d979..d0e8730e52 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/PluginManager.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/PluginManager.cpp @@ -8,6 +8,7 @@ // include required headers #include +#include #include "EMStudioManager.h" #include #include "PluginManager.h" @@ -80,25 +81,15 @@ namespace EMStudio mPlugins.clear(); // delete all active plugins - const int32 numActivePlugins = static_cast(mActivePlugins.size()); - if (numActivePlugins > 0) + for (auto plugin = mActivePlugins.rbegin(); plugin != mActivePlugins.rend(); ++plugin) { - // iterate from back to front, destructing the plugins and removing them directly from the array of active plugins - for (int32 a = numActivePlugins - 1; a >= 0; a--) + for (EMStudioPlugin* pluginToNotify : mActivePlugins) { - EMStudioPlugin* plugin = mActivePlugins[a]; - - const int32 currentNumPlugins = static_cast(mActivePlugins.size()); - for (int32 p = 0; p < currentNumPlugins; ++p) - { - mActivePlugins[p]->OnBeforeRemovePlugin(plugin->GetClassID()); - } - - mActivePlugins.erase(mActivePlugins.begin() + a); - delete plugin; + pluginToNotify->OnBeforeRemovePlugin((*plugin)->GetClassID()); } - MCORE_ASSERT(mActivePlugins.empty()); + delete *plugin; + mActivePlugins.pop_back(); } } @@ -114,8 +105,8 @@ namespace EMStudio EMStudioPlugin* PluginManager::CreateWindowOfType(const char* pluginType, const char* objectName) { // try to locate the plugin type - const uint32 pluginIndex = FindPluginByTypeString(pluginType); - if (pluginIndex == MCORE_INVALIDINDEX32) + const size_t pluginIndex = FindPluginByTypeString(pluginType); + if (pluginIndex == InvalidIndex) { return nullptr; } @@ -138,32 +129,22 @@ namespace EMStudio // find a given plugin by its name (type string) - uint32 PluginManager::FindPluginByTypeString(const char* pluginType) const + size_t PluginManager::FindPluginByTypeString(const char* pluginType) const { - const size_t numPlugins = mPlugins.size(); - for (size_t i = 0; i < numPlugins; ++i) + const auto foundPlugin = AZStd::find_if(begin(mPlugins), end(mPlugins), [pluginType](const EMStudioPlugin* plugin) { - if (AzFramework::StringFunc::Equal(pluginType, mPlugins[i]->GetName())) - { - return static_cast(i); - } - } - - return MCORE_INVALIDINDEX32; + return AzFramework::StringFunc::Equal(pluginType, plugin->GetName()); + }); + return foundPlugin != end(mPlugins) ? AZStd::distance(begin(mPlugins), foundPlugin) : InvalidIndex; } EMStudioPlugin* PluginManager::GetActivePluginByTypeString(const char* pluginType) const { - const size_t numPlugins = mActivePlugins.size(); - for (size_t i = 0; i < numPlugins; ++i) + const auto foundPlugin = AZStd::find_if(begin(mActivePlugins), end(mActivePlugins), [pluginType](const EMStudioPlugin* plugin) { - if (AzFramework::StringFunc::Equal(pluginType, mActivePlugins[i]->GetName())) - { - return mActivePlugins[i]; - } - } - - return nullptr; + return AzFramework::StringFunc::Equal(pluginType, plugin->GetName()); + }); + return foundPlugin != end(mActivePlugins) ? *foundPlugin : nullptr; } // generate a unique object name @@ -185,81 +166,47 @@ namespace EMStudio ); // check if we have a conflict with a current plugin - bool hasConflict = false; - const size_t numActivePlugins = mActivePlugins.size(); - for (size_t i = 0; i < numActivePlugins; ++i) + const bool hasConflict = AZStd::any_of(begin(mActivePlugins), end(mActivePlugins), [&randomString](EMStudioPlugin* plugin) { - EMStudioPlugin* plugin = mActivePlugins[i]; - - // if the object name of a current plugin is equal to the one - if (plugin->GetHasWindowWithObjectName(randomString)) - { - hasConflict = true; - break; - } - } + return plugin->GetHasWindowWithObjectName(randomString); + }); if (hasConflict == false) { return randomString.c_str(); } } - - //return QString("INVALID"); } // find the number of active plugins of a given type - uint32 PluginManager::GetNumActivePluginsOfType(const char* pluginType) const + size_t PluginManager::GetNumActivePluginsOfType(const char* pluginType) const { - uint32 total = 0; - - // check all active plugins to see if they are from the given type - const size_t numActivePlugins = mActivePlugins.size(); - for (size_t i = 0; i < numActivePlugins; ++i) + return AZStd::accumulate(mActivePlugins.begin(), mActivePlugins.end(), size_t{0}, [pluginType](size_t total, const EMStudioPlugin* plugin) { - if (AzFramework::StringFunc::Equal(pluginType, mActivePlugins[i]->GetName())) - { - total++; - } - } - - return total; + return total + AzFramework::StringFunc::Equal(pluginType, plugin->GetName()); + }); } // find the first active plugin of a given type EMStudioPlugin* PluginManager::FindActivePlugin(uint32 classID) const { - const size_t numActivePlugins = mActivePlugins.size(); - for (size_t i = 0; i < numActivePlugins; ++i) + const auto foundPlugin = AZStd::find_if(begin(mActivePlugins), end(mActivePlugins), [classID](const EMStudioPlugin* plugin) { - if (mActivePlugins[i]->GetClassID() == classID) - { - return mActivePlugins[i]; - } - } - - return nullptr; + return plugin->GetClassID() == classID; + }); + return foundPlugin != end(mActivePlugins) ? *foundPlugin : nullptr; } // find the number of active plugins of a given type - uint32 PluginManager::GetNumActivePluginsOfType(uint32 classID) const + size_t PluginManager::GetNumActivePluginsOfType(uint32 classID) const { - uint32 total = 0; - - // check all active plugins to see if they are from the given type - const size_t numActivePlugins = mActivePlugins.size(); - for (size_t i = 0; i < numActivePlugins; ++i) + return AZStd::accumulate(mActivePlugins.begin(), mActivePlugins.end(), size_t{0}, [classID](size_t total, const EMStudioPlugin* plugin) { - if (mActivePlugins[i]->GetClassID() == classID) - { - total++; - } - } - - return total; + return total + (plugin->GetClassID() == classID); + }); } } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/PluginManager.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/PluginManager.h index 6b511e2a04..2937c3b387 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/PluginManager.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/PluginManager.h @@ -36,7 +36,7 @@ namespace EMStudio void RegisterPlugin(EMStudioPlugin* plugin); EMStudioPlugin* CreateWindowOfType(const char* pluginType, const char* objectName = nullptr); - uint32 FindPluginByTypeString(const char* pluginType) const; + size_t FindPluginByTypeString(const char* pluginType) const; EMStudioPlugin* GetActivePluginByTypeString(const char* pluginType) const; // Reqire that PluginType is a subclass of EMStudioPlugin @@ -47,15 +47,15 @@ namespace EMStudio } EMStudioPlugin* FindActivePlugin(uint32 classID) const; // find first active plugin, or nullptr when not found - MCORE_INLINE uint32 GetNumPlugins() const { return static_cast(mPlugins.size()); } - MCORE_INLINE EMStudioPlugin* GetPlugin(const uint32 index) { return mPlugins[index]; } + MCORE_INLINE size_t GetNumPlugins() const { return mPlugins.size(); } + MCORE_INLINE EMStudioPlugin* GetPlugin(const size_t index) { return mPlugins[index]; } - MCORE_INLINE uint32 GetNumActivePlugins() const { return static_cast(mActivePlugins.size()); } - MCORE_INLINE EMStudioPlugin* GetActivePlugin(const uint32 index) { return mActivePlugins[index]; } + MCORE_INLINE size_t GetNumActivePlugins() const { return mActivePlugins.size(); } + MCORE_INLINE EMStudioPlugin* GetActivePlugin(const size_t index) { return mActivePlugins[index]; } MCORE_INLINE const PluginVector& GetActivePlugins() { return mActivePlugins; } - uint32 GetNumActivePluginsOfType(const char* pluginType) const; - uint32 GetNumActivePluginsOfType(uint32 classID) const; + size_t GetNumActivePluginsOfType(const char* pluginType) const; + size_t GetNumActivePluginsOfType(uint32 classID) const; void RemoveActivePlugin(EMStudioPlugin* plugin); QString GenerateObjectName() const; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeTrack.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeTrack.cpp index 26c85cf377..ea41b0ab65 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeTrack.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeTrack.cpp @@ -6,6 +6,7 @@ * */ +#include #include "TimeTrack.h" #include "TimeViewPlugin.h" #include @@ -203,26 +204,17 @@ namespace EMStudio // calculate the number of selected elements - uint32 TimeTrack::CalcNumSelectedElements() const + size_t TimeTrack::CalcNumSelectedElements() const { if (mVisible == false) { return 0; } - uint32 result = 0; - - // for all elements - const size_t numElems = mElements.size(); - for (size_t i = 0; i < numElems; ++i) + return AZStd::accumulate(begin(mElements), end(mElements), size_t{0}, [](size_t total, const TimeTrackElement* element) { - if (mElements[i]->GetIsSelected()) - { - result++; - } - } - - return result; + return total + element->GetIsSelected(); + }); } @@ -234,28 +226,20 @@ namespace EMStudio return nullptr; } - // get the number of elements and iterate through them - const size_t numElems = mElements.size(); - for (size_t i = 0; i < numElems; ++i) + const auto foundElement = AZStd::find_if(begin(mElements), end(mElements), [](const TimeTrackElement* element) { - // return the first selected element that we find - if (mElements[i]->GetIsSelected()) - { - return mElements[i]; - } - } - - // no selected element found - return nullptr; + return element->GetIsSelected(); + }); + return foundElement != end(mElements) ? *foundElement : nullptr; } // select elements in a given range, unselect all other - void TimeTrack::RangeSelectElements(uint32 elementStartNr, uint32 elementEndNr) + void TimeTrack::RangeSelectElements(size_t elementStartNr, size_t elementEndNr) { // make sure the start number is actually the smaller one of the two values - const uint32 startNr = MCore::Min(elementStartNr, elementEndNr); - const uint32 endNr = MCore::Max(elementStartNr, elementEndNr); + const size_t startNr = AZStd::min(elementStartNr, elementEndNr); + const size_t endNr = AZStd::max(elementStartNr, elementEndNr); // get the number of elements and iterate through them const size_t numElems = mElements.size(); @@ -281,11 +265,9 @@ namespace EMStudio void TimeTrack::SelectElementsInRect(const QRect& rect, bool overwriteCurSelection, bool select, bool toggleMode) { // get the number of elements and iterate through them - const size_t numElems = mElements.size(); - for (size_t i = 0; i < numElems; ++i) + for (TimeTrackElement* element : mElements) { // get the current element and the corresponding rect - TimeTrackElement* element = mElements[i]; QRect elementRect = element->CalcRect(); if (elementRect.intersects(rect)) diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeTrack.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeTrack.h index 4e8731ecad..4046ebf55f 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeTrack.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeTrack.h @@ -45,8 +45,8 @@ namespace EMStudio // @param startTime The time in seconds of the left border of the visible area in the widget. void RenderData(QPainter& painter, uint32 width, int32 startY, double startTime, double endTime, double animationLength, double clipStartTime, double clipEndTime); - MCORE_INLINE uint32 GetNumElements() const { return static_cast(mElements.size()); } - MCORE_INLINE TimeTrackElement* GetElement(uint32 index) const { return mElements[static_cast(index)]; } + MCORE_INLINE size_t GetNumElements() const { return mElements.size(); } + MCORE_INLINE TimeTrackElement* GetElement(size_t index) const { return mElements[index]; } void AddElement(TimeTrackElement* elem) { elem->SetTrack(this); mElements.push_back(elem); } void RemoveElement(TimeTrackElement* elem, bool delFromMem = true) { @@ -56,7 +56,7 @@ namespace EMStudio delete elem; } } - void RemoveElement(uint32 index, bool delFromMem = true) + void RemoveElement(size_t index, bool delFromMem = true) { if (delFromMem) { @@ -70,9 +70,9 @@ namespace EMStudio mElements.resize(count); } - uint32 CalcNumSelectedElements() const; + size_t CalcNumSelectedElements() const; TimeTrackElement* GetFirstSelectedElement() const; - void RangeSelectElements(uint32 elementStartNr, uint32 elementEndNr); + void RangeSelectElements(size_t elementStartNr, size_t elementEndNr); void SelectElementsInRect(const QRect& rect, bool overwriteCurSelection, bool select, bool toggleMode); MCORE_INLINE TimeViewPlugin* GetPlugin() { return mPlugin; } diff --git a/Gems/EMotionFX/Code/Include/Integration/AnimGraphComponentBus.h b/Gems/EMotionFX/Code/Include/Integration/AnimGraphComponentBus.h index ac5c74fe7c..3ee0069efd 100644 --- a/Gems/EMotionFX/Code/Include/Integration/AnimGraphComponentBus.h +++ b/Gems/EMotionFX/Code/Include/Integration/AnimGraphComponentBus.h @@ -44,47 +44,47 @@ namespace EMotionFX /// Retrieving the index and using it to set parameter values is more performant than setting by name. /// \param parameterName - name of parameter for which to retrieve the index. /// \return parameter index - virtual AZ::u32 FindParameterIndex(const char* parameterName) = 0; + virtual size_t FindParameterIndex(const char* parameterName) = 0; /// Retrieve parameter name for a given parameter index. /// \param parameterName - index of parameter for which to retrieve the name. /// \return parameter name - virtual const char* FindParameterName(AZ::u32 parameterIndex) = 0; + virtual const char* FindParameterName(size_t parameterIndex) = 0; /// Updates a anim graph property given a float value. /// \param parameterIndex - index of parameter to set /// \param value - value to set - virtual void SetParameterFloat(AZ::u32 parameterIndex, float value) = 0; + virtual void SetParameterFloat(size_t parameterIndex, float value) = 0; /// Updates a anim graph property given a boolean value. /// \param parameterIndex - index of parameter to set /// \param value - value to set - virtual void SetParameterBool(AZ::u32 parameterIndex, bool value) = 0; + virtual void SetParameterBool(size_t parameterIndex, bool value) = 0; /// Updates a anim graph property given a string value. /// \param parameterIndex - index of parameter to set /// \param value - value to set - virtual void SetParameterString(AZ::u32 parameterIndex, const char* value) = 0; + virtual void SetParameterString(size_t parameterIndex, const char* value) = 0; /// Updates a anim graph property given a Vector2 value. /// \param parameterIndex - index of parameter to set /// \param value - value to set - virtual void SetParameterVector2(AZ::u32 parameterIndex, const AZ::Vector2& value) = 0; + virtual void SetParameterVector2(size_t parameterIndex, const AZ::Vector2& value) = 0; /// Updates a anim graph property given a Vector3 value. /// \param parameterIndex - index of parameter to set /// \param value - value to set - virtual void SetParameterVector3(AZ::u32 parameterIndex, const AZ::Vector3& value) = 0; + virtual void SetParameterVector3(size_t parameterIndex, const AZ::Vector3& value) = 0; /// Updates a anim graph property given euler rotation values. /// \param parameterIndex - index of parameter to set /// \param value - value to set - virtual void SetParameterRotationEuler(AZ::u32 parameterIndex, const AZ::Vector3& value) = 0; + virtual void SetParameterRotationEuler(size_t parameterIndex, const AZ::Vector3& value) = 0; /// Updates a anim graph property given a quaternion value. /// \param parameterIndex - index of parameter to set /// \param value - value to set - virtual void SetParameterRotation(AZ::u32 parameterIndex, const AZ::Quaternion& value) = 0; + virtual void SetParameterRotation(size_t parameterIndex, const AZ::Quaternion& value) = 0; /// Updates a anim graph property given a float value. @@ -127,31 +127,31 @@ namespace EMotionFX /// Retrieves a anim graph property as a float value. /// \param parameterIndex - index of parameter to set - virtual float GetParameterFloat(AZ::u32 parameterIndex) = 0; + virtual float GetParameterFloat(size_t parameterIndex) = 0; /// Retrieves a anim graph property as a boolean value. /// \param parameterIndex - index of parameter to set - virtual bool GetParameterBool(AZ::u32 parameterIndex) = 0; + virtual bool GetParameterBool(size_t parameterIndex) = 0; /// Retrieves a anim graph property given a string value. /// \param parameterIndex - index of parameter to set - virtual AZStd::string GetParameterString(AZ::u32 parameterIndex) = 0; + virtual AZStd::string GetParameterString(size_t parameterIndex) = 0; /// Retrieves a anim graph property as a Vector2 value. /// \param parameterIndex - index of parameter to set - virtual AZ::Vector2 GetParameterVector2(AZ::u32 parameterIndex) = 0; + virtual AZ::Vector2 GetParameterVector2(size_t parameterIndex) = 0; /// Retrieves a anim graph property as a Vector3 value. /// \param parameterIndex - index of parameter to set - virtual AZ::Vector3 GetParameterVector3(AZ::u32 parameterIndex) = 0; + virtual AZ::Vector3 GetParameterVector3(size_t parameterIndex) = 0; /// Retrieves a anim graph property given as euler rotation values. /// \param parameterIndex - index of parameter to set - virtual AZ::Vector3 GetParameterRotationEuler(AZ::u32 parameterIndex) = 0; + virtual AZ::Vector3 GetParameterRotationEuler(size_t parameterIndex) = 0; /// Retrieves a anim graph property as a quaternion value. /// \param parameterIndex - index of parameter to set - virtual AZ::Quaternion GetParameterRotation(AZ::u32 parameterIndex) = 0; + virtual AZ::Quaternion GetParameterRotation(size_t parameterIndex) = 0; /// Retrieves a anim graph property as a float value. /// \param parameterName - name of parameter to get @@ -241,42 +241,42 @@ namespace EMotionFX /// \param parameterIndex - index of changed parameter /// \param beforeValue - value before the change /// \param afterValue - value after the change - virtual void OnAnimGraphFloatParameterChanged(EMotionFX::AnimGraphInstance* /*animGraphInstance*/, [[maybe_unused]] AZ::u32 parameterIndex, [[maybe_unused]] float beforeValue, [[maybe_unused]] float afterValue) {}; + virtual void OnAnimGraphFloatParameterChanged(EMotionFX::AnimGraphInstance* /*animGraphInstance*/, [[maybe_unused]] size_t parameterIndex, [[maybe_unused]] float beforeValue, [[maybe_unused]] float afterValue) {}; /// Notifies listeners when a bool parameter changes /// \param animGraphInstance - pointer to anim graph instance /// \param parameterIndex - index of changed parameter /// \param beforeValue - value before the change /// \param afterValue - value after the change - virtual void OnAnimGraphBoolParameterChanged(EMotionFX::AnimGraphInstance* /*animGraphInstance*/, [[maybe_unused]] AZ::u32 parameterIndex, [[maybe_unused]] bool beforeValue, [[maybe_unused]] bool afterValue) {}; + virtual void OnAnimGraphBoolParameterChanged(EMotionFX::AnimGraphInstance* /*animGraphInstance*/, [[maybe_unused]] size_t parameterIndex, [[maybe_unused]] bool beforeValue, [[maybe_unused]] bool afterValue) {}; /// Notifies listeners when a string parameter changes /// \param animGraphInstance - pointer to anim graph instance /// \param parameterIndex - index of changed parameter /// \param beforeValue - value before the change /// \param afterValue - value after the change - virtual void OnAnimGraphStringParameterChanged(EMotionFX::AnimGraphInstance* /*animGraphInstance*/, [[maybe_unused]] AZ::u32 parameterIndex, [[maybe_unused]] const char* beforeValue, [[maybe_unused]] const char* afterValue) {}; + virtual void OnAnimGraphStringParameterChanged(EMotionFX::AnimGraphInstance* /*animGraphInstance*/, [[maybe_unused]] size_t parameterIndex, [[maybe_unused]] const char* beforeValue, [[maybe_unused]] const char* afterValue) {}; /// Notifies listeners when a vector2 parameter changes /// \param animGraphInstance - pointer to anim graph instance /// \param parameterIndex - index of changed parameter /// \param beforeValue - value before the change /// \param afterValue - value after the change - virtual void OnAnimGraphVector2ParameterChanged(EMotionFX::AnimGraphInstance* /*animGraphInstance*/, [[maybe_unused]] AZ::u32 parameterIndex, [[maybe_unused]] const AZ::Vector2& beforeValue, [[maybe_unused]] const AZ::Vector2& afterValue) {}; + virtual void OnAnimGraphVector2ParameterChanged(EMotionFX::AnimGraphInstance* /*animGraphInstance*/, [[maybe_unused]] size_t parameterIndex, [[maybe_unused]] const AZ::Vector2& beforeValue, [[maybe_unused]] const AZ::Vector2& afterValue) {}; /// Notifies listeners when a vector3 parameter changes /// \param animGraphInstance - pointer to anim graph instance /// \param parameterIndex - index of changed parameter /// \param beforeValue - value before the change /// \param afterValue - value after the change - virtual void OnAnimGraphVector3ParameterChanged(EMotionFX::AnimGraphInstance* /*animGraphInstance*/, [[maybe_unused]] AZ::u32 parameterIndex, [[maybe_unused]] const AZ::Vector3& beforeValue, [[maybe_unused]] const AZ::Vector3& afterValue) {}; + virtual void OnAnimGraphVector3ParameterChanged(EMotionFX::AnimGraphInstance* /*animGraphInstance*/, [[maybe_unused]] size_t parameterIndex, [[maybe_unused]] const AZ::Vector3& beforeValue, [[maybe_unused]] const AZ::Vector3& afterValue) {}; /// Notifies listeners when a rotation parameter changes /// \param animGraphInstance - pointer to anim graph instance /// \param parameterIndex - index of changed parameter /// \param beforeValue - value before the change /// \param afterValue - value after the change - virtual void OnAnimGraphRotationParameterChanged(EMotionFX::AnimGraphInstance* /*animGraphInstance*/, [[maybe_unused]] AZ::u32 parameterIndex, [[maybe_unused]] const AZ::Quaternion& beforeValue, [[maybe_unused]] const AZ::Quaternion& afterValue) {}; + virtual void OnAnimGraphRotationParameterChanged(EMotionFX::AnimGraphInstance* /*animGraphInstance*/, [[maybe_unused]] size_t parameterIndex, [[maybe_unused]] const AZ::Quaternion& beforeValue, [[maybe_unused]] const AZ::Quaternion& afterValue) {}; /// Notifies listeners when an another anim graph trying to sync this graph /// \param animGraphInstance - pointer to the follower anim graph instance diff --git a/Gems/EMotionFX/Code/MCore/Source/MultiThreadManager.h b/Gems/EMotionFX/Code/MCore/Source/MultiThreadManager.h index b97f7b2f22..a4fe6eaa10 100644 --- a/Gems/EMotionFX/Code/MCore/Source/MultiThreadManager.h +++ b/Gems/EMotionFX/Code/MCore/Source/MultiThreadManager.h @@ -104,6 +104,22 @@ namespace MCore }; + class MCORE_API AtomicSizeT + { + public: + MCORE_INLINE AtomicSizeT() { SetValue(0); } + + MCORE_INLINE void SetValue(size_t value) { mAtomic.store(value); } + MCORE_INLINE size_t GetValue() const { size_t value = mAtomic.load(); return value; } + + MCORE_INLINE size_t Increment() { return mAtomic++; } + MCORE_INLINE size_t Decrement() { return mAtomic--; } + + private: + AZStd::atomic mAtomic; + }; + + class MCORE_API Thread { public: diff --git a/Gems/EMotionFX/Code/MCore/Source/StringIdPool.cpp b/Gems/EMotionFX/Code/MCore/Source/StringIdPool.cpp index 279a7aec1e..4e89072f70 100644 --- a/Gems/EMotionFX/Code/MCore/Source/StringIdPool.cpp +++ b/Gems/EMotionFX/Code/MCore/Source/StringIdPool.cpp @@ -43,7 +43,7 @@ namespace MCore AZ::u32 StringIdPool::GenerateIdForStringWithoutLock(const AZStd::string& objectName) { // Try to insert it, if we hit a collision, we have the element. - auto iterator = mStringToIndex.emplace(objectName, static_cast(mStrings.size())); + auto iterator = mStringToIndex.emplace(objectName, aznumeric_caster(mStrings.size())); if (!iterator.second) { // could not insert, we have the element @@ -148,7 +148,7 @@ namespace MCore /// Convert binary data to text. size_t DataToText(AZ::IO::GenericStream& in, AZ::IO::GenericStream& out, bool /*isDataBigEndian = false*/) { - size_t dataSize = static_cast(in.GetLength()); + AZ::u64 dataSize = in.GetLength(); AZStd::string outText; outText.resize(dataSize); diff --git a/Gems/EMotionFX/Code/Source/Integration/Components/ActorComponent.cpp b/Gems/EMotionFX/Code/Source/Integration/Components/ActorComponent.cpp index b033e46a87..9f996f46fd 100644 --- a/Gems/EMotionFX/Code/Source/Integration/Components/ActorComponent.cpp +++ b/Gems/EMotionFX/Code/Source/Integration/Components/ActorComponent.cpp @@ -722,10 +722,10 @@ namespace EMotionFX { AZ_Assert(m_actorInstance, "The actor instance needs to be valid."); - const AZ::u32 index = static_cast(jointIndex); - const AZ::u32 numNodes = m_actorInstance->GetActor()->GetNumNodes(); + const size_t index = jointIndex; + const size_t numNodes = m_actorInstance->GetActor()->GetNumNodes(); - AZ_Error("EMotionFX", index < numNodes, "GetJointTransform: The joint index %d is out of bounds [0;%d]. Entity: %s", + AZ_Error("EMotionFX", index < numNodes, "GetJointTransform: The joint index %zu is out of bounds [0;%zu]. Entity: %s", index, numNodes, GetEntity()->GetName().c_str()); if (index >= numNodes) @@ -762,10 +762,10 @@ namespace EMotionFX { AZ_Assert(m_actorInstance, "The actor instance needs to be valid."); - const AZ::u32 index = static_cast(jointIndex); - const AZ::u32 numNodes = m_actorInstance->GetActor()->GetNumNodes(); + const size_t index = jointIndex; + const size_t numNodes = m_actorInstance->GetActor()->GetNumNodes(); - AZ_Error("EMotionFX", index < numNodes, "GetJointTransformComponents: The joint index %d is out of bounds [0;%d]. Entity: %s", + AZ_Error("EMotionFX", index < numNodes, "GetJointTransformComponents: The joint index %zu is out of bounds [0;%zu]. Entity: %s", index, numNodes, GetEntity()->GetName().c_str()); if (index >= numNodes) @@ -870,7 +870,7 @@ namespace EMotionFX Node* node = jointName ? m_actorInstance->GetActor()->GetSkeleton()->FindNodeByName(jointName) : m_actorInstance->GetActor()->GetSkeleton()->GetNode(0); if (node) { - const AZ::u32 jointIndex = node->GetNodeIndex(); + const size_t jointIndex = node->GetNodeIndex(); Attachment* attachment = AttachmentNode::Create(m_actorInstance.get(), jointIndex, targetActorInstance, true /* Managed externally, by this component. */); m_actorInstance->AddAttachment(attachment); } diff --git a/Gems/EMotionFX/Code/Source/Integration/Components/AnimGraphComponent.cpp b/Gems/EMotionFX/Code/Source/Integration/Components/AnimGraphComponent.cpp index 10046728ab..704b746e3f 100644 --- a/Gems/EMotionFX/Code/Source/Integration/Components/AnimGraphComponent.cpp +++ b/Gems/EMotionFX/Code/Source/Integration/Components/AnimGraphComponent.cpp @@ -43,32 +43,32 @@ namespace EMotionFX Call(FN_OnAnimGraphInstanceDestroyed, animGraphInstance); } - void OnAnimGraphFloatParameterChanged(EMotionFX::AnimGraphInstance* animGraphInstance, AZ::u32 parameterIndex, float beforeValue, float afterValue) override + void OnAnimGraphFloatParameterChanged(EMotionFX::AnimGraphInstance* animGraphInstance, size_t parameterIndex, float beforeValue, float afterValue) override { Call(FN_OnAnimGraphFloatParameterChanged, animGraphInstance, parameterIndex, beforeValue, afterValue); } - void OnAnimGraphBoolParameterChanged(EMotionFX::AnimGraphInstance* animGraphInstance, AZ::u32 parameterIndex, bool beforeValue, bool afterValue) override + void OnAnimGraphBoolParameterChanged(EMotionFX::AnimGraphInstance* animGraphInstance, size_t parameterIndex, bool beforeValue, bool afterValue) override { Call(FN_OnAnimGraphBoolParameterChanged, animGraphInstance, parameterIndex, beforeValue, afterValue); } - void OnAnimGraphStringParameterChanged(EMotionFX::AnimGraphInstance* animGraphInstance, AZ::u32 parameterIndex, const char* beforeValue, const char* afterValue) override + void OnAnimGraphStringParameterChanged(EMotionFX::AnimGraphInstance* animGraphInstance, size_t parameterIndex, const char* beforeValue, const char* afterValue) override { Call(FN_OnAnimGraphStringParameterChanged, animGraphInstance, parameterIndex, beforeValue, afterValue); } - void OnAnimGraphVector2ParameterChanged(EMotionFX::AnimGraphInstance* animGraphInstance, AZ::u32 parameterIndex, const AZ::Vector2& beforeValue, const AZ::Vector2& afterValue) override + void OnAnimGraphVector2ParameterChanged(EMotionFX::AnimGraphInstance* animGraphInstance, size_t parameterIndex, const AZ::Vector2& beforeValue, const AZ::Vector2& afterValue) override { Call(FN_OnAnimGraphVector2ParameterChanged, animGraphInstance, parameterIndex, beforeValue, afterValue); } - void OnAnimGraphVector3ParameterChanged(EMotionFX::AnimGraphInstance* animGraphInstance, AZ::u32 parameterIndex, const AZ::Vector3& beforeValue, const AZ::Vector3& afterValue) override + void OnAnimGraphVector3ParameterChanged(EMotionFX::AnimGraphInstance* animGraphInstance, size_t parameterIndex, const AZ::Vector3& beforeValue, const AZ::Vector3& afterValue) override { Call(FN_OnAnimGraphVector3ParameterChanged, animGraphInstance, parameterIndex, beforeValue, afterValue); } - void OnAnimGraphRotationParameterChanged(EMotionFX::AnimGraphInstance* animGraphInstance, AZ::u32 parameterIndex, const AZ::Quaternion& beforeValue, const AZ::Quaternion& afterValue) override + void OnAnimGraphRotationParameterChanged(EMotionFX::AnimGraphInstance* animGraphInstance, size_t parameterIndex, const AZ::Quaternion& beforeValue, const AZ::Quaternion& afterValue) override { Call(FN_OnAnimGraphVector3ParameterChanged, animGraphInstance, parameterIndex, beforeValue, afterValue); } @@ -138,7 +138,7 @@ namespace EMotionFX auto* behaviorContext = azrtti_cast(context); if (behaviorContext) { - behaviorContext->Constant("InvalidParameterIndex", BehaviorConstant(static_cast(MCORE_INVALIDINDEX32))); + behaviorContext->Constant("InvalidParameterIndex", BehaviorConstant(InvalidIndex)); behaviorContext->EBus("AnimGraphComponentRequestBus") // General API @@ -546,24 +546,24 @@ namespace EMotionFX } ////////////////////////////////////////////////////////////////////////// - AZ::u32 AnimGraphComponent::FindParameterIndex(const char* parameterName) + size_t AnimGraphComponent::FindParameterIndex(const char* parameterName) { if (m_animGraphInstance) { const AZ::Outcome parameterIndex = m_animGraphInstance->FindParameterIndex(parameterName); if (parameterIndex.IsSuccess()) { - return static_cast(parameterIndex.GetValue()); + return parameterIndex.GetValue(); } } - return MCORE_INVALIDINDEX32; + return InvalidIndex; } ////////////////////////////////////////////////////////////////////////// - const char* AnimGraphComponent::FindParameterName(AZ::u32 parameterIndex) + const char* AnimGraphComponent::FindParameterName(size_t parameterIndex) { - if (parameterIndex == MCORE_INVALIDINDEX32 || !m_animGraphInstance || !m_animGraphInstance->GetAnimGraph()) + if (parameterIndex == InvalidIndex || !m_animGraphInstance || !m_animGraphInstance->GetAnimGraph()) { return ""; } @@ -572,11 +572,11 @@ namespace EMotionFX ////////////////////////////////////////////////////////////////////////// - void AnimGraphComponent::SetParameterFloat(AZ::u32 parameterIndex, float value) + void AnimGraphComponent::SetParameterFloat(size_t parameterIndex, float value) { - if (parameterIndex == MCORE_INVALIDINDEX32) + if (parameterIndex == InvalidIndex) { - AZ_Warning("EMotionFX", false, "Invalid anim graph parameter index: %u", parameterIndex); + AZ_Warning("EMotionFX", false, "Invalid anim graph parameter index: %zu", parameterIndex); return; } @@ -610,7 +610,7 @@ namespace EMotionFX } default: { - AZ_Warning("EMotionFX", false, "Anim graph parameter index: %u can not be set as float, is of type: %s", parameterIndex, param->GetTypeString()); + AZ_Warning("EMotionFX", false, "Anim graph parameter index: %zu can not be set as float, is of type: %s", parameterIndex, param->GetTypeString()); return; } } @@ -627,11 +627,11 @@ namespace EMotionFX } ////////////////////////////////////////////////////////////////////////// - void AnimGraphComponent::SetParameterBool(AZ::u32 parameterIndex, bool value) + void AnimGraphComponent::SetParameterBool(size_t parameterIndex, bool value) { - if (parameterIndex == MCORE_INVALIDINDEX32) + if (parameterIndex == InvalidIndex) { - AZ_Warning("EMotionFX", false, "Invalid anim graph parameter index: %u", parameterIndex); + AZ_Warning("EMotionFX", false, "Invalid anim graph parameter index: %zu", parameterIndex); return; } @@ -665,7 +665,7 @@ namespace EMotionFX } default: { - AZ_Warning("EMotionFX", false, "Anim graph parameter index: %u can not be set as bool, is of type: %s", parameterIndex, param->GetTypeString()); + AZ_Warning("EMotionFX", false, "Anim graph parameter index: %zu can not be set as bool, is of type: %s", parameterIndex, param->GetTypeString()); return; } } @@ -682,11 +682,11 @@ namespace EMotionFX } ////////////////////////////////////////////////////////////////////////// - void AnimGraphComponent::SetParameterString(AZ::u32 parameterIndex, const char* value) + void AnimGraphComponent::SetParameterString(size_t parameterIndex, const char* value) { - if (parameterIndex == MCORE_INVALIDINDEX32) + if (parameterIndex == InvalidIndex) { - AZ_Warning("EMotionFX", false, "Invalid anim graph parameter index: %u", parameterIndex); + AZ_Warning("EMotionFX", false, "Invalid anim graph parameter index: %zu", parameterIndex); return; } @@ -713,17 +713,17 @@ namespace EMotionFX } else { - AZ_Warning("EMotionFX", false, "Anim graph parameter index: %u is not a string", parameterIndex); + AZ_Warning("EMotionFX", false, "Anim graph parameter index: %zu is not a string", parameterIndex); } } } ////////////////////////////////////////////////////////////////////////// - void AnimGraphComponent::SetParameterVector2(AZ::u32 parameterIndex, const AZ::Vector2& value) + void AnimGraphComponent::SetParameterVector2(size_t parameterIndex, const AZ::Vector2& value) { - if (parameterIndex == MCORE_INVALIDINDEX32) + if (parameterIndex == InvalidIndex) { - AZ_Warning("EMotionFX", false, "Invalid anim graph parameter index: %u", parameterIndex); + AZ_Warning("EMotionFX", false, "Invalid anim graph parameter index: %zu", parameterIndex); return; } @@ -746,17 +746,17 @@ namespace EMotionFX } else { - AZ_Warning("EMotionFX", false, "Anim graph parameter index: %u is not a vector2", parameterIndex); + AZ_Warning("EMotionFX", false, "Anim graph parameter index: %zu is not a vector2", parameterIndex); } } } ////////////////////////////////////////////////////////////////////////// - void AnimGraphComponent::SetParameterVector3(AZ::u32 parameterIndex, const AZ::Vector3& value) + void AnimGraphComponent::SetParameterVector3(size_t parameterIndex, const AZ::Vector3& value) { - if (parameterIndex == MCORE_INVALIDINDEX32) + if (parameterIndex == InvalidIndex) { - AZ_Warning("EMotionFX", false, "Invalid anim graph parameter index: %u", parameterIndex); + AZ_Warning("EMotionFX", false, "Invalid anim graph parameter index: %zu", parameterIndex); return; } @@ -779,17 +779,17 @@ namespace EMotionFX } else { - AZ_Warning("EMotionFX", false, "Anim graph parameter index: %u is not a vector3", parameterIndex); + AZ_Warning("EMotionFX", false, "Anim graph parameter index: %zu is not a vector3", parameterIndex); } } } ////////////////////////////////////////////////////////////////////////// - void AnimGraphComponent::SetParameterRotationEuler(AZ::u32 parameterIndex, const AZ::Vector3& value) + void AnimGraphComponent::SetParameterRotationEuler(size_t parameterIndex, const AZ::Vector3& value) { - if (parameterIndex == MCORE_INVALIDINDEX32) + if (parameterIndex == InvalidIndex) { - AZ_Warning("EMotionFX", false, "Invalid anim graph parameter index: %u", parameterIndex); + AZ_Warning("EMotionFX", false, "Invalid anim graph parameter index: %zu", parameterIndex); return; } @@ -808,7 +808,7 @@ namespace EMotionFX break; } default: - AZ_Warning("EMotionFX", false, "Anim graph parameter index: %u can not be set as rotation euler, is of type: %s", parameterIndex, param->GetTypeString()); + AZ_Warning("EMotionFX", false, "Anim graph parameter index: %zu can not be set as rotation euler, is of type: %s", parameterIndex, param->GetTypeString()); return; } @@ -824,11 +824,11 @@ namespace EMotionFX } ////////////////////////////////////////////////////////////////////////// - void AnimGraphComponent::SetParameterRotation(AZ::u32 parameterIndex, const AZ::Quaternion& value) + void AnimGraphComponent::SetParameterRotation(size_t parameterIndex, const AZ::Quaternion& value) { - if (parameterIndex == MCORE_INVALIDINDEX32) + if (parameterIndex == InvalidIndex) { - AZ_Warning("EMotionFX", false, "Invalid anim graph parameter index: %u", parameterIndex); + AZ_Warning("EMotionFX", false, "Invalid anim graph parameter index: %zu", parameterIndex); return; } @@ -847,7 +847,7 @@ namespace EMotionFX break; } default: - AZ_Warning("EMotionFX", false, "Anim graph parameter index: %u can not be set as rotation, is of type: %s", parameterIndex, param->GetTypeString()); + AZ_Warning("EMotionFX", false, "Anim graph parameter index: %zu can not be set as rotation, is of type: %s", parameterIndex, param->GetTypeString()); return; } @@ -986,11 +986,11 @@ namespace EMotionFX } ////////////////////////////////////////////////////////////////////////// - float AnimGraphComponent::GetParameterFloat(AZ::u32 parameterIndex) + float AnimGraphComponent::GetParameterFloat(size_t parameterIndex) { - if (parameterIndex == MCORE_INVALIDINDEX32) + if (parameterIndex == InvalidIndex) { - AZ_Warning("EMotionFX", false, "Invalid anim graph parameter index: %u", parameterIndex); + AZ_Warning("EMotionFX", false, "Invalid anim graph parameter index: %zu", parameterIndex); return 0.f; } @@ -1003,11 +1003,11 @@ namespace EMotionFX } ////////////////////////////////////////////////////////////////////////// - bool AnimGraphComponent::GetParameterBool(AZ::u32 parameterIndex) + bool AnimGraphComponent::GetParameterBool(size_t parameterIndex) { - if (parameterIndex == MCORE_INVALIDINDEX32) + if (parameterIndex == InvalidIndex) { - AZ_Warning("EMotionFX", false, "Invalid anim graph parameter index: %u", parameterIndex); + AZ_Warning("EMotionFX", false, "Invalid anim graph parameter index: %zu", parameterIndex); return false; } @@ -1020,11 +1020,11 @@ namespace EMotionFX } ////////////////////////////////////////////////////////////////////////// - AZStd::string AnimGraphComponent::GetParameterString(AZ::u32 parameterIndex) + AZStd::string AnimGraphComponent::GetParameterString(size_t parameterIndex) { - if (parameterIndex == MCORE_INVALIDINDEX32) + if (parameterIndex == InvalidIndex) { - AZ_Warning("EMotionFX", false, "Invalid anim graph parameter index: %u", parameterIndex); + AZ_Warning("EMotionFX", false, "Invalid anim graph parameter index: %zu", parameterIndex); return AZStd::string(); } @@ -1040,11 +1040,11 @@ namespace EMotionFX } ////////////////////////////////////////////////////////////////////////// - AZ::Vector2 AnimGraphComponent::GetParameterVector2(AZ::u32 parameterIndex) + AZ::Vector2 AnimGraphComponent::GetParameterVector2(size_t parameterIndex) { - if (parameterIndex == MCORE_INVALIDINDEX32) + if (parameterIndex == InvalidIndex) { - AZ_Warning("EMotionFX", false, "Invalid anim graph parameter index: %u", parameterIndex); + AZ_Warning("EMotionFX", false, "Invalid anim graph parameter index: %zu", parameterIndex); return AZ::Vector2::CreateZero(); } @@ -1058,11 +1058,11 @@ namespace EMotionFX } ////////////////////////////////////////////////////////////////////////// - AZ::Vector3 AnimGraphComponent::GetParameterVector3(AZ::u32 parameterIndex) + AZ::Vector3 AnimGraphComponent::GetParameterVector3(size_t parameterIndex) { - if (parameterIndex == MCORE_INVALIDINDEX32) + if (parameterIndex == InvalidIndex) { - AZ_Warning("EMotionFX", false, "Invalid anim graph parameter index: %u", parameterIndex); + AZ_Warning("EMotionFX", false, "Invalid anim graph parameter index: %zu", parameterIndex); return AZ::Vector3::CreateZero(); } @@ -1076,11 +1076,11 @@ namespace EMotionFX } ////////////////////////////////////////////////////////////////////////// - AZ::Vector3 AnimGraphComponent::GetParameterRotationEuler(AZ::u32 parameterIndex) + AZ::Vector3 AnimGraphComponent::GetParameterRotationEuler(size_t parameterIndex) { - if (parameterIndex == MCORE_INVALIDINDEX32) + if (parameterIndex == InvalidIndex) { - AZ_Warning("EMotionFX", false, "Invalid anim graph parameter index: %u", parameterIndex); + AZ_Warning("EMotionFX", false, "Invalid anim graph parameter index: %zu", parameterIndex); return AZ::Vector3::CreateZero(); } @@ -1094,11 +1094,11 @@ namespace EMotionFX } ////////////////////////////////////////////////////////////////////////// - AZ::Quaternion AnimGraphComponent::GetParameterRotation(AZ::u32 parameterIndex) + AZ::Quaternion AnimGraphComponent::GetParameterRotation(size_t parameterIndex) { - if (parameterIndex == MCORE_INVALIDINDEX32) + if (parameterIndex == InvalidIndex) { - AZ_Warning("EMotionFX", false, "Invalid anim graph parameter index: %u", parameterIndex); + AZ_Warning("EMotionFX", false, "Invalid anim graph parameter index: %zu", parameterIndex); return AZ::Quaternion::CreateZero(); } diff --git a/Gems/EMotionFX/Code/Source/Integration/Components/AnimGraphComponent.h b/Gems/EMotionFX/Code/Source/Integration/Components/AnimGraphComponent.h index 52b57ce76e..474d0cb6c5 100644 --- a/Gems/EMotionFX/Code/Source/Integration/Components/AnimGraphComponent.h +++ b/Gems/EMotionFX/Code/Source/Integration/Components/AnimGraphComponent.h @@ -104,15 +104,15 @@ namespace EMotionFX ////////////////////////////////////////////////////////////////////////// // AnimGraphComponentRequestBus::Handler EMotionFX::AnimGraphInstance* GetAnimGraphInstance() override; - AZ::u32 FindParameterIndex(const char* parameterName) override; - const char* FindParameterName(AZ::u32 parameterIndex) override; - void SetParameterFloat(AZ::u32 parameterIndex, float value) override; - void SetParameterBool(AZ::u32 parameterIndex, bool value) override; - void SetParameterString(AZ::u32 parameterIndex, const char* value) override; - void SetParameterVector2(AZ::u32 parameterIndex, const AZ::Vector2& value) override; - void SetParameterVector3(AZ::u32 parameterIndex, const AZ::Vector3& value) override; - void SetParameterRotationEuler(AZ::u32 parameterIndex, const AZ::Vector3& value) override; - void SetParameterRotation(AZ::u32 parameterIndex, const AZ::Quaternion& value) override; + size_t FindParameterIndex(const char* parameterName) override; + const char* FindParameterName(size_t parameterIndex) override; + void SetParameterFloat(size_t parameterIndex, float value) override; + void SetParameterBool(size_t parameterIndex, bool value) override; + void SetParameterString(size_t parameterIndex, const char* value) override; + void SetParameterVector2(size_t parameterIndex, const AZ::Vector2& value) override; + void SetParameterVector3(size_t parameterIndex, const AZ::Vector3& value) override; + void SetParameterRotationEuler(size_t parameterIndex, const AZ::Vector3& value) override; + void SetParameterRotation(size_t parameterIndex, const AZ::Quaternion& value) override; void SetNamedParameterFloat(const char* parameterName, float value) override; void SetNamedParameterBool(const char* parameterName, bool value) override; void SetNamedParameterString(const char* parameterName, const char* value) override; @@ -121,13 +121,13 @@ namespace EMotionFX void SetNamedParameterRotationEuler(const char* parameterName, const AZ::Vector3& value) override; void SetNamedParameterRotation(const char* parameterName, const AZ::Quaternion& value) override; void SetVisualizeEnabled(bool enabled) override; - float GetParameterFloat(AZ::u32 parameterIndex) override; - bool GetParameterBool(AZ::u32 parameterIndex) override; - AZStd::string GetParameterString(AZ::u32 parameterIndex) override; - AZ::Vector2 GetParameterVector2(AZ::u32 parameterIndex) override; - AZ::Vector3 GetParameterVector3(AZ::u32 parameterIndex) override; - AZ::Vector3 GetParameterRotationEuler(AZ::u32 parameterIndex) override; - AZ::Quaternion GetParameterRotation(AZ::u32 parameterIndex) override; + float GetParameterFloat(size_t parameterIndex) override; + bool GetParameterBool(size_t parameterIndex) override; + AZStd::string GetParameterString(size_t parameterIndex) override; + AZ::Vector2 GetParameterVector2(size_t parameterIndex) override; + AZ::Vector3 GetParameterVector3(size_t parameterIndex) override; + AZ::Vector3 GetParameterRotationEuler(size_t parameterIndex) override; + AZ::Quaternion GetParameterRotation(size_t parameterIndex) override; float GetNamedParameterFloat(const char* parameterName) override; bool GetNamedParameterBool(const char* parameterName) override; AZStd::string GetNamedParameterString(const char* parameterName) override; diff --git a/Gems/EMotionFX/Code/Source/Integration/System/SystemComponent.cpp b/Gems/EMotionFX/Code/Source/Integration/System/SystemComponent.cpp index c1b7be1239..78aa3b4426 100644 --- a/Gems/EMotionFX/Code/Source/Integration/System/SystemComponent.cpp +++ b/Gems/EMotionFX/Code/Source/Integration/System/SystemComponent.cpp @@ -619,8 +619,8 @@ namespace EMotionFX } // Process the plugins. - const AZ::u32 numPlugins = pluginManager->GetNumActivePlugins(); - for (AZ::u32 i = 0; i < numPlugins; ++i) + const size_t numPlugins = pluginManager->GetNumActivePlugins(); + for (size_t i = 0; i < numPlugins; ++i) { EMStudio::EMStudioPlugin* plugin = pluginManager->GetActivePlugin(i); plugin->ProcessFrame(delta); @@ -677,8 +677,8 @@ namespace EMotionFX const float timeDelta = delta; const ActorManager* actorManager = GetEMotionFX().GetActorManager(); - const AZ::u32 numActorInstances = actorManager->GetNumActorInstances(); - for (AZ::u32 i = 0; i < numActorInstances; ++i) + const size_t numActorInstances = actorManager->GetNumActorInstances(); + for (size_t i = 0; i < numActorInstances; ++i) { const ActorInstance* actorInstance = actorManager->GetActorInstance(i); diff --git a/Gems/EMotionFX/Code/Tests/AnimGraphComponentBusTests.cpp b/Gems/EMotionFX/Code/Tests/AnimGraphComponentBusTests.cpp index 35d63c3c53..b40088e01f 100644 --- a/Gems/EMotionFX/Code/Tests/AnimGraphComponentBusTests.cpp +++ b/Gems/EMotionFX/Code/Tests/AnimGraphComponentBusTests.cpp @@ -52,12 +52,12 @@ namespace EMotionFX MOCK_METHOD1(OnAnimGraphInstanceCreated, void(EMotionFX::AnimGraphInstance*)); MOCK_METHOD1(OnAnimGraphInstanceDestroyed, void(EMotionFX::AnimGraphInstance*)); - MOCK_METHOD4(OnAnimGraphFloatParameterChanged, void(EMotionFX::AnimGraphInstance*, AZ::u32, float, float)); - MOCK_METHOD4(OnAnimGraphBoolParameterChanged, void(EMotionFX::AnimGraphInstance*, AZ::u32, bool, bool)); - MOCK_METHOD4(OnAnimGraphStringParameterChanged, void(EMotionFX::AnimGraphInstance*, AZ::u32, const char*, const char*)); - MOCK_METHOD4(OnAnimGraphVector2ParameterChanged, void(EMotionFX::AnimGraphInstance*, AZ::u32, const AZ::Vector2&, const AZ::Vector2&)); - MOCK_METHOD4(OnAnimGraphVector3ParameterChanged, void(EMotionFX::AnimGraphInstance*, AZ::u32, const AZ::Vector3&, const AZ::Vector3&)); - MOCK_METHOD4(OnAnimGraphRotationParameterChanged, void(EMotionFX::AnimGraphInstance*, AZ::u32, const AZ::Quaternion&, const AZ::Quaternion&)); + MOCK_METHOD4(OnAnimGraphFloatParameterChanged, void(EMotionFX::AnimGraphInstance*, size_t, float, float)); + MOCK_METHOD4(OnAnimGraphBoolParameterChanged, void(EMotionFX::AnimGraphInstance*, size_t, bool, bool)); + MOCK_METHOD4(OnAnimGraphStringParameterChanged, void(EMotionFX::AnimGraphInstance*, size_t, const char*, const char*)); + MOCK_METHOD4(OnAnimGraphVector2ParameterChanged, void(EMotionFX::AnimGraphInstance*, size_t, const AZ::Vector2&, const AZ::Vector2&)); + MOCK_METHOD4(OnAnimGraphVector3ParameterChanged, void(EMotionFX::AnimGraphInstance*, size_t, const AZ::Vector3&, const AZ::Vector3&)); + MOCK_METHOD4(OnAnimGraphRotationParameterChanged, void(EMotionFX::AnimGraphInstance*, size_t, const AZ::Quaternion&, const AZ::Quaternion&)); }; class AnimGraphComponentBusTests @@ -143,7 +143,7 @@ namespace EMotionFX Integration::ActorComponent* m_actorComponent = nullptr; Integration::AnimGraphComponent* m_animGraphComponent = nullptr; AnimGraphInstance* m_animGraphInstance = nullptr; - AZ::u32 m_parameterIndex = InvalidIndex32; + size_t m_parameterIndex = InvalidIndex; std::string m_parameterName; }; @@ -164,7 +164,11 @@ namespace EMotionFX PrepareParameterTest(aznew FloatSliderParameter()); - EXPECT_CALL(testBus, OnAnimGraphFloatParameterChanged(m_animGraphInstance, m_parameterIndex, testing::_, 3.0f)); + { + testing::InSequence parameterChangedCallSequence; + EXPECT_CALL(testBus, OnAnimGraphFloatParameterChanged(m_animGraphInstance, m_parameterIndex, testing::_, 3.0f)); + EXPECT_CALL(testBus, OnAnimGraphFloatParameterChanged(m_animGraphInstance, m_parameterIndex, 3.0f, 4.0f)); + } // SetParameterFloat/GetParameterFloat() test Integration::AnimGraphComponentRequestBus::Event(m_entityId, &Integration::AnimGraphComponentRequestBus::Events::SetParameterFloat, m_parameterIndex, 3.0f); @@ -172,8 +176,6 @@ namespace EMotionFX Integration::AnimGraphComponentRequestBus::EventResult(newValue, m_entityId, &Integration::AnimGraphComponentRequestBus::Events::GetParameterFloat, m_parameterIndex); EXPECT_EQ(newValue, 3.0f) << "Expected a parameter value of 3.0."; - EXPECT_CALL(testBus, OnAnimGraphFloatParameterChanged(m_animGraphInstance, m_parameterIndex, 3.0f, 4.0f)); - // SetNamedParameterFloat/GetNamedParameterFloat() test Integration::AnimGraphComponentRequestBus::Event(m_entityId, &Integration::AnimGraphComponentRequestBus::Events::SetNamedParameterFloat, m_parameterName.c_str(), 4.0f); Integration::AnimGraphComponentRequestBus::EventResult(newValue, m_entityId, &Integration::AnimGraphComponentRequestBus::Events::GetNamedParameterFloat, m_parameterName.c_str()); @@ -187,7 +189,12 @@ namespace EMotionFX PrepareParameterTest(aznew BoolParameter()); - EXPECT_CALL(testBus, OnAnimGraphBoolParameterChanged(m_animGraphInstance, m_parameterIndex, testing::_, true)); + { + testing::InSequence parameterChangedCallSequence; + EXPECT_CALL(testBus, OnAnimGraphBoolParameterChanged(m_animGraphInstance, m_parameterIndex, testing::_, true)); + EXPECT_CALL(testBus, OnAnimGraphBoolParameterChanged(m_animGraphInstance, m_parameterIndex, true, false)); + } + // SetParameterBool/GetParameterBool() test Integration::AnimGraphComponentRequestBus::Event(m_entityId, &Integration::AnimGraphComponentRequestBus::Events::SetParameterBool, m_parameterIndex, true); @@ -195,8 +202,6 @@ namespace EMotionFX Integration::AnimGraphComponentRequestBus::EventResult(newValue, m_entityId, &Integration::AnimGraphComponentRequestBus::Events::GetParameterBool, m_parameterIndex); EXPECT_EQ(newValue, true) << "Expected true as parameter value."; - EXPECT_CALL(testBus, OnAnimGraphBoolParameterChanged(m_animGraphInstance, m_parameterIndex, true, false)); - // SetNamedParameterBool/GetNamedParameterBool() test Integration::AnimGraphComponentRequestBus::Event(m_entityId, &Integration::AnimGraphComponentRequestBus::Events::SetNamedParameterBool, m_parameterName.c_str(), false); Integration::AnimGraphComponentRequestBus::EventResult(newValue, m_entityId, &Integration::AnimGraphComponentRequestBus::Events::GetNamedParameterBool, m_parameterName.c_str()); @@ -210,7 +215,8 @@ namespace EMotionFX PrepareParameterTest(aznew StringParameter()); - EXPECT_CALL(testBus, OnAnimGraphStringParameterChanged(m_animGraphInstance, m_parameterIndex, testing::_, testing::_)); + EXPECT_CALL(testBus, OnAnimGraphStringParameterChanged(m_animGraphInstance, m_parameterIndex, testing::_, testing::_)) + .Times(2); // SetParameterString/GetParameterString() test Integration::AnimGraphComponentRequestBus::Event(m_entityId, &Integration::AnimGraphComponentRequestBus::Events::SetParameterString, m_parameterIndex, "Test String"); @@ -218,8 +224,6 @@ namespace EMotionFX Integration::AnimGraphComponentRequestBus::EventResult(newValue, m_entityId, &Integration::AnimGraphComponentRequestBus::Events::GetParameterString, m_parameterIndex); EXPECT_STREQ(newValue.c_str(), "Test String") << "Expected the test string parameter."; - EXPECT_CALL(testBus, OnAnimGraphStringParameterChanged(m_animGraphInstance, m_parameterIndex, testing::_, testing::_)); - // SetNamedParameterString/GetNamedParameterString() test Integration::AnimGraphComponentRequestBus::Event(m_entityId, &Integration::AnimGraphComponentRequestBus::Events::SetNamedParameterString, m_parameterName.c_str(), "Yet Another String"); Integration::AnimGraphComponentRequestBus::EventResult(newValue, m_entityId, &Integration::AnimGraphComponentRequestBus::Events::GetNamedParameterString, m_parameterName.c_str()); @@ -233,7 +237,11 @@ namespace EMotionFX PrepareParameterTest(aznew Vector2Parameter()); - EXPECT_CALL(testBus, OnAnimGraphVector2ParameterChanged(m_animGraphInstance, m_parameterIndex, testing::_, AZ::Vector2(1.0f, 2.0f))); + { + testing::InSequence parameterChangedCallSequence; + EXPECT_CALL(testBus, OnAnimGraphVector2ParameterChanged(m_animGraphInstance, m_parameterIndex, testing::_, AZ::Vector2(1.0f, 2.0f))); + EXPECT_CALL(testBus, OnAnimGraphVector2ParameterChanged(m_animGraphInstance, m_parameterIndex, AZ::Vector2(1.0f, 2.0f), AZ::Vector2(3.0f, 4.0f))); + } // SetParameterVector2/GetParameterVector2() test Integration::AnimGraphComponentRequestBus::Event(m_entityId, &Integration::AnimGraphComponentRequestBus::Events::SetParameterVector2, m_parameterIndex, AZ::Vector2(1.0f, 2.0f)); @@ -241,8 +249,6 @@ namespace EMotionFX Integration::AnimGraphComponentRequestBus::EventResult(newValue, m_entityId, &Integration::AnimGraphComponentRequestBus::Events::GetParameterVector2, m_parameterIndex); EXPECT_EQ(newValue, AZ::Vector2(1.0f, 2.0f)); - EXPECT_CALL(testBus, OnAnimGraphVector2ParameterChanged(m_animGraphInstance, m_parameterIndex, AZ::Vector2(1.0f, 2.0f), AZ::Vector2(3.0f, 4.0f))); - // SetNamedParameterVector2/GetNamedParameterVector2() test Integration::AnimGraphComponentRequestBus::Event(m_entityId, &Integration::AnimGraphComponentRequestBus::Events::SetNamedParameterVector2, m_parameterName.c_str(), AZ::Vector2(3.0f, 4.0f)); Integration::AnimGraphComponentRequestBus::EventResult(newValue, m_entityId, &Integration::AnimGraphComponentRequestBus::Events::GetNamedParameterVector2, m_parameterName.c_str()); @@ -256,7 +262,11 @@ namespace EMotionFX PrepareParameterTest(aznew Vector3Parameter()); - EXPECT_CALL(testBus, OnAnimGraphVector3ParameterChanged(m_animGraphInstance, m_parameterIndex, testing::_, AZ::Vector3(1.0f, 2.0f, 3.0f))); + { + testing::InSequence parameterChangedCallSequence; + EXPECT_CALL(testBus, OnAnimGraphVector3ParameterChanged(m_animGraphInstance, m_parameterIndex, testing::_, AZ::Vector3(1.0f, 2.0f, 3.0f))); + EXPECT_CALL(testBus, OnAnimGraphVector3ParameterChanged(m_animGraphInstance, m_parameterIndex, AZ::Vector3(1.0f, 2.0f, 3.0f), AZ::Vector3(4.0f, 5.0f, 6.0f))); + } // SetParameterVector3/GetParameterVector3() test Integration::AnimGraphComponentRequestBus::Event(m_entityId, &Integration::AnimGraphComponentRequestBus::Events::SetParameterVector3, m_parameterIndex, AZ::Vector3(1.0f, 2.0f, 3.0f)); @@ -264,8 +274,6 @@ namespace EMotionFX Integration::AnimGraphComponentRequestBus::EventResult(newValue, m_entityId, &Integration::AnimGraphComponentRequestBus::Events::GetParameterVector3, m_parameterIndex); EXPECT_EQ(newValue, AZ::Vector3(1.0f, 2.0f, 3.0f)); - EXPECT_CALL(testBus, OnAnimGraphVector3ParameterChanged(m_animGraphInstance, m_parameterIndex, AZ::Vector3(1.0f, 2.0f, 3.0f), AZ::Vector3(4.0f, 5.0f, 6.0f))); - // SetNamedParameterVector3/GetNamedParameterVector3() test Integration::AnimGraphComponentRequestBus::Event(m_entityId, &Integration::AnimGraphComponentRequestBus::Events::SetNamedParameterVector3, m_parameterName.c_str(), AZ::Vector3(4.0f, 5.0f, 6.0f)); Integration::AnimGraphComponentRequestBus::EventResult(newValue, m_entityId, &Integration::AnimGraphComponentRequestBus::Events::GetNamedParameterVector3, m_parameterName.c_str()); @@ -279,7 +287,8 @@ namespace EMotionFX PrepareParameterTest(aznew RotationParameter()); - EXPECT_CALL(testBus, OnAnimGraphRotationParameterChanged(m_animGraphInstance, m_parameterIndex, testing::_, testing::_)); + EXPECT_CALL(testBus, OnAnimGraphRotationParameterChanged(m_animGraphInstance, m_parameterIndex, testing::_, testing::_)) + .Times(2); // SetParameterRotationEuler/GetParameterRotationEuler() test AZ::Vector3 expectedEuler(AZ::DegToRad(30.0f), AZ::DegToRad(20.0f), 0.0f); @@ -288,8 +297,6 @@ namespace EMotionFX Integration::AnimGraphComponentRequestBus::EventResult(newValue, m_entityId, &Integration::AnimGraphComponentRequestBus::Events::GetParameterRotationEuler, m_parameterIndex); EXPECT_TRUE(newValue.IsClose(expectedEuler, 0.001f)); - EXPECT_CALL(testBus, OnAnimGraphRotationParameterChanged(m_animGraphInstance, m_parameterIndex, testing::_, testing::_)); - // SetNamedParameterRotationEuler/GetNamedParameterRotationEuler() test expectedEuler = AZ::Vector3(AZ::DegToRad(45.0f), 0.0f, AZ::DegToRad(30.0f)); Integration::AnimGraphComponentRequestBus::Event(m_entityId, &Integration::AnimGraphComponentRequestBus::Events::SetNamedParameterRotationEuler, m_parameterName.c_str(), expectedEuler); @@ -299,30 +306,33 @@ namespace EMotionFX TEST_F(AnimGraphComponentBusTests, RotationParameter) { - AZ::Vector3 expected(AZ::DegToRad(30.0f), AZ::DegToRad(20.0f), 0.0f); - AZ::Quaternion expectedQuat = MCore::AzEulerAnglesToAzQuat(expected); + const AZ::Vector3 firstExpected(AZ::DegToRad(30.0f), AZ::DegToRad(20.0f), 0.0f); + const AZ::Quaternion firstExpectedQuat = MCore::AzEulerAnglesToAzQuat(firstExpected); + const AZ::Vector3 secondExpected = AZ::Vector3(AZ::DegToRad(45.0f), 0.0f, AZ::DegToRad(30.0f)); + const AZ::Quaternion secondExpectedQuat = MCore::AzEulerAnglesToAzQuat(secondExpected); + AnimGraphComponentNotificationTestBus testBus(m_entityId); EXPECT_CALL(testBus, OnAnimGraphInstanceCreated(testing::_)); PrepareParameterTest(aznew RotationParameter()); - EXPECT_CALL(testBus, OnAnimGraphRotationParameterChanged(m_animGraphInstance, m_parameterIndex, testing::_, expectedQuat)); + { + testing::InSequence parameterChangedCallSequence; + EXPECT_CALL(testBus, OnAnimGraphRotationParameterChanged(m_animGraphInstance, m_parameterIndex, testing::_, firstExpectedQuat)); + EXPECT_CALL(testBus, OnAnimGraphRotationParameterChanged(m_animGraphInstance, m_parameterIndex, testing::_, secondExpectedQuat)); + } // SetParameterRotation/GetParameterRotation() test - Integration::AnimGraphComponentRequestBus::Event(m_entityId, &Integration::AnimGraphComponentRequestBus::Events::SetParameterRotation, m_parameterIndex, expectedQuat); + Integration::AnimGraphComponentRequestBus::Event(m_entityId, &Integration::AnimGraphComponentRequestBus::Events::SetParameterRotation, m_parameterIndex, firstExpectedQuat); AZ::Quaternion newValue; Integration::AnimGraphComponentRequestBus::EventResult(newValue, m_entityId, &Integration::AnimGraphComponentRequestBus::Events::GetParameterRotation, m_parameterIndex); - EXPECT_TRUE(newValue.IsClose(expectedQuat, 0.001f)); - - expected = AZ::Vector3(AZ::DegToRad(45.0f), 0.0f, AZ::DegToRad(30.0f)); - expectedQuat = MCore::AzEulerAnglesToAzQuat(expected); - EXPECT_CALL(testBus, OnAnimGraphRotationParameterChanged(m_animGraphInstance, m_parameterIndex, testing::_, expectedQuat)); + EXPECT_TRUE(newValue.IsClose(firstExpectedQuat, 0.001f)); // SetNamedParameterRotation/GetNamedParameterRotation() test - Integration::AnimGraphComponentRequestBus::Event(m_entityId, &Integration::AnimGraphComponentRequestBus::Events::SetNamedParameterRotation, m_parameterName.c_str(), expectedQuat); + Integration::AnimGraphComponentRequestBus::Event(m_entityId, &Integration::AnimGraphComponentRequestBus::Events::SetNamedParameterRotation, m_parameterName.c_str(), secondExpectedQuat); Integration::AnimGraphComponentRequestBus::EventResult(newValue, m_entityId, &Integration::AnimGraphComponentRequestBus::Events::GetNamedParameterRotation, m_parameterName.c_str()); - EXPECT_TRUE(newValue.IsClose(expectedQuat, 0.001f)); + EXPECT_TRUE(newValue.IsClose(secondExpectedQuat, 0.001f)); } TEST_F(AnimGraphComponentBusTests, OnAnimGraphInstanceDestroyed) diff --git a/Gems/EMotionFX/Code/Tests/AnimGraphEventTests.cpp b/Gems/EMotionFX/Code/Tests/AnimGraphEventTests.cpp index 8479bda94c..1b88092917 100644 --- a/Gems/EMotionFX/Code/Tests/AnimGraphEventTests.cpp +++ b/Gems/EMotionFX/Code/Tests/AnimGraphEventTests.cpp @@ -63,8 +63,8 @@ namespace EMotionFX MotionSet::MotionEntry* motionEntry = AddMotionEntry("testMotion", 1.0); // Assign a motion to all our motion nodes - const AZ::u32 numStates = m_rootStateMachine->GetNumChildNodes(); - for (AZ::u32 i = 0; i < numStates; ++i) + const size_t numStates = m_rootStateMachine->GetNumChildNodes(); + for (size_t i = 0; i < numStates; ++i) { AnimGraphMotionNode* motionNode = azdynamic_cast(m_rootStateMachine->GetChildNode(i)); if (motionNode) diff --git a/Gems/EMotionFX/Code/Tests/AnimGraphNodeEventFilterTests.cpp b/Gems/EMotionFX/Code/Tests/AnimGraphNodeEventFilterTests.cpp index 67f6fa860e..eb1da8f0a3 100644 --- a/Gems/EMotionFX/Code/Tests/AnimGraphNodeEventFilterTests.cpp +++ b/Gems/EMotionFX/Code/Tests/AnimGraphNodeEventFilterTests.cpp @@ -86,7 +86,7 @@ namespace EMotionFX AnimGraphMotionNode* motionNode = aznew AnimGraphMotionNode(); motionNode->SetName(AZStd::string::format("MotionNode%zu", i).c_str()); m_blendTree->AddChildNode(motionNode); - m_blend2Node->AddConnection(motionNode, AnimGraphMotionNode::PORTID_OUTPUT_POSE, static_cast(i)); + m_blend2Node->AddConnection(motionNode, AnimGraphMotionNode::PORTID_OUTPUT_POSE, aznumeric_caster(i)); m_motionNodes.push_back(motionNode); } diff --git a/Gems/EMotionFX/Code/Tests/AnimGraphNodeProcessingTests.cpp b/Gems/EMotionFX/Code/Tests/AnimGraphNodeProcessingTests.cpp index 4a85d452a3..32b82ab5b8 100644 --- a/Gems/EMotionFX/Code/Tests/AnimGraphNodeProcessingTests.cpp +++ b/Gems/EMotionFX/Code/Tests/AnimGraphNodeProcessingTests.cpp @@ -69,7 +69,7 @@ namespace EMotionFX AnimGraphMotionNode* motionNode = aznew AnimGraphMotionNode(); motionNode->SetName(AZStd::string::format("MotionNode%zu", i).c_str()); m_blendTree->AddChildNode(motionNode); - m_blendNNode->AddConnection(motionNode, AnimGraphMotionNode::PORTID_OUTPUT_POSE, static_cast(i)); + m_blendNNode->AddConnection(motionNode, AnimGraphMotionNode::PORTID_OUTPUT_POSE, aznumeric_caster(i)); m_motionNodes.push_back(motionNode); } m_blendNNode->UpdateParamWeights(); diff --git a/Gems/EMotionFX/Code/Tests/AnimGraphParameterActionTests.cpp b/Gems/EMotionFX/Code/Tests/AnimGraphParameterActionTests.cpp index d49cc5568e..8d51069782 100644 --- a/Gems/EMotionFX/Code/Tests/AnimGraphParameterActionTests.cpp +++ b/Gems/EMotionFX/Code/Tests/AnimGraphParameterActionTests.cpp @@ -110,7 +110,7 @@ namespace EMotionFX { AZStd::unique_ptr newParameter(EMotionFX::ParameterFactory::Create(azrtti_typeid())); newParameter->SetName("Parameter1"); - CommandSystem::ConstructCreateParameterCommand(commandString, m_animGraph.get(), newParameter.get(), MCORE_INVALIDINDEX32); + CommandSystem::ConstructCreateParameterCommand(commandString, m_animGraph.get(), newParameter.get(), InvalidIndex); EXPECT_TRUE(commandManager.ExecuteCommand(commandString, result)) << result.c_str(); } @@ -119,7 +119,7 @@ namespace EMotionFX { AZStd::unique_ptr newParameter(EMotionFX::ParameterFactory::Create(azrtti_typeid())); newParameter->SetName(parameterName); - CommandSystem::ConstructCreateParameterCommand(commandString, m_animGraph.get(), newParameter.get(), MCORE_INVALIDINDEX32); + CommandSystem::ConstructCreateParameterCommand(commandString, m_animGraph.get(), newParameter.get(), InvalidIndex); EXPECT_TRUE(commandManager.ExecuteCommand(commandString, result)) << result.c_str(); } @@ -127,7 +127,8 @@ namespace EMotionFX action->Reinit(); AZ::Outcome parameterIndex = m_animGraph->FindValueParameterIndexByName(parameterName); - EXPECT_TRUE(parameterIndex.IsSuccess() && parameterIndex.GetValue() == 1) << "Parameter2 should be at the 2nd position."; + ASSERT_TRUE(parameterIndex.IsSuccess()); + EXPECT_EQ(parameterIndex.GetValue(), 1) << "Parameter2 should be at the 2nd position."; // 1. Move Parameter2 from the 2nd place to the 1st place. commandString = AZStd::string::format("AnimGraphMoveParameter -animGraphID %d -name \"%s\" -index %d ", @@ -136,19 +137,19 @@ namespace EMotionFX 0); EXPECT_TRUE(commandManager.ExecuteCommand(commandString, result)) << result.c_str(); parameterIndex = m_animGraph->FindValueParameterIndexByName(parameterName); - EXPECT_TRUE(parameterIndex.IsSuccess() && parameterIndex.GetValue() == 0) << "Parameter2 should now be at the 1st position."; + ASSERT_TRUE(parameterIndex.IsSuccess() && parameterIndex.GetValue() == 0) << "Parameter2 should now be at the 1st position."; EXPECT_EQ(parameterIndex.GetValue(), action->GetParameterIndex().GetValue()) << "The action should now refer to the 1st parameter in the anim graph."; // 2. Undo. EXPECT_TRUE(commandManager.Undo(result)) << result.c_str(); parameterIndex = m_animGraph->FindValueParameterIndexByName(parameterName); - EXPECT_TRUE(parameterIndex.IsSuccess() && parameterIndex.GetValue() == 1) << "Parameter2 should now be back at the 2nd position."; + ASSERT_TRUE(parameterIndex.IsSuccess() && parameterIndex.GetValue() == 1) << "Parameter2 should now be back at the 2nd position."; EXPECT_EQ(parameterIndex.GetValue(), action->GetParameterIndex().GetValue()) << "The action should now refer to the 2nd parameter in the anim graph."; // 3. Redo. EXPECT_TRUE(commandManager.Redo(result)) << result.c_str(); parameterIndex = m_animGraph->FindValueParameterIndexByName(parameterName); - EXPECT_TRUE(parameterIndex.IsSuccess() && parameterIndex.GetValue() == 0) << "Parameter2 should now be back at the 1st position."; + ASSERT_TRUE(parameterIndex.IsSuccess() && parameterIndex.GetValue() == 0) << "Parameter2 should now be back at the 1st position."; EXPECT_EQ(parameterIndex.GetValue(), action->GetParameterIndex().GetValue()) << "The action should now refer to the 1st parameter in the anim graph."; } } diff --git a/Gems/EMotionFX/Code/Tests/AnimGraphParameterConditionCommandTests.cpp b/Gems/EMotionFX/Code/Tests/AnimGraphParameterConditionCommandTests.cpp index d8dd1c7343..0d420b6881 100644 --- a/Gems/EMotionFX/Code/Tests/AnimGraphParameterConditionCommandTests.cpp +++ b/Gems/EMotionFX/Code/Tests/AnimGraphParameterConditionCommandTests.cpp @@ -47,7 +47,7 @@ namespace EMotionFX newParameter->SetName(parameterName); CommandSystem::ConstructCreateParameterCommand(commandString, m_animGraph.get(), newParameter.get(), - MCORE_INVALIDINDEX32); + InvalidIndex); EXPECT_TRUE(commandManager.ExecuteCommand(commandString, result)) << result.c_str(); } diff --git a/Gems/EMotionFX/Code/Tests/AnimGraphRefCountTests.cpp b/Gems/EMotionFX/Code/Tests/AnimGraphRefCountTests.cpp index 28e2536989..8b51f5b814 100644 --- a/Gems/EMotionFX/Code/Tests/AnimGraphRefCountTests.cpp +++ b/Gems/EMotionFX/Code/Tests/AnimGraphRefCountTests.cpp @@ -39,8 +39,8 @@ namespace EMotionFX const uint32 threadIndex = this->m_actorInstance->GetThreadIndex(); // Check if data and pose ref counts are back to 0 for all nodes. - const uint32 numNodes = this->m_animGraph->GetNumNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = this->m_animGraph->GetNumNodes(); + for (size_t i = 0; i < numNodes; ++i) { const AnimGraphNode* node = this->m_animGraph->GetNode(i); diff --git a/Gems/EMotionFX/Code/Tests/AnimGraphSyncTrackTests.cpp b/Gems/EMotionFX/Code/Tests/AnimGraphSyncTrackTests.cpp index fedd77bb24..d23638c9ea 100644 --- a/Gems/EMotionFX/Code/Tests/AnimGraphSyncTrackTests.cpp +++ b/Gems/EMotionFX/Code/Tests/AnimGraphSyncTrackTests.cpp @@ -95,8 +95,8 @@ namespace EMotionFX { MakeNoEvents, 0.5f, - MCORE_INVALIDINDEX32, - MCORE_INVALIDINDEX32 + InvalidIndex, + InvalidIndex }, { MakeOneEvent, @@ -267,8 +267,8 @@ namespace EMotionFX 0, // startingIndex 0, // inEventAIndex 1, // inEventBIndex - MCORE_INVALIDINDEX32, // expectedEventA - MCORE_INVALIDINDEX32, // expectedEventB + InvalidIndex, // expectedEventA + InvalidIndex, // expectedEventB false, // mirrorInput false, // mirrorOutput true // forward diff --git a/Gems/EMotionFX/Code/Tests/AnimGraphTagConditionTests.cpp b/Gems/EMotionFX/Code/Tests/AnimGraphTagConditionTests.cpp index 6d085894f5..8312912f47 100644 --- a/Gems/EMotionFX/Code/Tests/AnimGraphTagConditionTests.cpp +++ b/Gems/EMotionFX/Code/Tests/AnimGraphTagConditionTests.cpp @@ -38,7 +38,7 @@ namespace EMotionFX { const AZStd::string& parameterName = parameterNames[i]; AZ::Outcome parameterIndex = animGraph->FindValueParameterIndexByName(parameterName); - EXPECT_TRUE(parameterIndex.IsSuccess()) << "Parameter " << parameterName.c_str() << " does not exist in the anim graph."; + ASSERT_TRUE(parameterIndex.IsSuccess()) << "Parameter " << parameterName.c_str() << " does not exist in the anim graph."; EXPECT_EQ(parameterIndex.GetValue(), parameterIndices[i]) << "Index for parameter " << parameterName.c_str() << "out of date."; } } @@ -115,7 +115,8 @@ namespace EMotionFX { const AZStd::string parameterName = "Tag3"; AZ::Outcome parameterIndex = m_animGraph->FindValueParameterIndexByName(parameterName); - EXPECT_TRUE(parameterIndex.IsSuccess() && parameterIndex.GetValue() == 2) << "Tag3 should be at the 3rd position after removing Tag1."; + ASSERT_TRUE(parameterIndex.IsSuccess()); + EXPECT_EQ(parameterIndex.GetValue(), 2) << "Tag3 should be at the 3rd position after removing Tag1."; // Move Tag3 from the 3rd place to the 1st place. commandString = AZStd::string::format("AnimGraphMoveParameter -animGraphID %d -name \"%s\" -index %d", diff --git a/Gems/EMotionFX/Code/Tests/AnimGraphVector2ConditionTests.cpp b/Gems/EMotionFX/Code/Tests/AnimGraphVector2ConditionTests.cpp index 7e85700a33..5e850b7cf0 100644 --- a/Gems/EMotionFX/Code/Tests/AnimGraphVector2ConditionTests.cpp +++ b/Gems/EMotionFX/Code/Tests/AnimGraphVector2ConditionTests.cpp @@ -45,7 +45,7 @@ namespace EMotionFX { AZStd::unique_ptr newParameter(EMotionFX::ParameterFactory::Create(azrtti_typeid())); newParameter->SetName("Float Slider Parameter"); - CommandSystem::ConstructCreateParameterCommand(commandString, m_animGraph.get(), newParameter.get(), MCORE_INVALIDINDEX32); + CommandSystem::ConstructCreateParameterCommand(commandString, m_animGraph.get(), newParameter.get(), InvalidIndex); EXPECT_TRUE(commandManager.ExecuteCommand(commandString, result)) << result.c_str(); } @@ -54,7 +54,7 @@ namespace EMotionFX { AZStd::unique_ptr newParameter(EMotionFX::ParameterFactory::Create(azrtti_typeid())); newParameter->SetName(parameterName); - CommandSystem::ConstructCreateParameterCommand(commandString, m_animGraph.get(), newParameter.get(), MCORE_INVALIDINDEX32); + CommandSystem::ConstructCreateParameterCommand(commandString, m_animGraph.get(), newParameter.get(), InvalidIndex); EXPECT_TRUE(commandManager.ExecuteCommand(commandString, result)) << result.c_str(); } @@ -62,7 +62,8 @@ namespace EMotionFX condition->Reinit(); AZ::Outcome parameterIndex = m_animGraph->FindValueParameterIndexByName(parameterName); - EXPECT_TRUE(parameterIndex.IsSuccess() && parameterIndex.GetValue() == 1) << "The Vector2 parameter should be at the 2nd position."; + ASSERT_TRUE(parameterIndex.IsSuccess()); + EXPECT_EQ(parameterIndex.GetValue(), 1) << "The Vector2 parameter should be at the 2nd position."; // 1. Move the Vector2 parameter from the 2nd place to the 1st place. commandString = AZStd::string::format("AnimGraphMoveParameter -animGraphID %d -name \"%s\" -index %d ", @@ -71,19 +72,19 @@ namespace EMotionFX 0); EXPECT_TRUE(commandManager.ExecuteCommand(commandString, result)) << result.c_str(); parameterIndex = m_animGraph->FindValueParameterIndexByName(parameterName); - EXPECT_TRUE(parameterIndex.IsSuccess() && parameterIndex.GetValue() == 0) << "The Vector2 parameter should now be at the 1st position."; + ASSERT_TRUE(parameterIndex.IsSuccess() && parameterIndex.GetValue() == 0) << "The Vector2 parameter should now be at the 1st position."; EXPECT_EQ(parameterIndex.GetValue(), condition->GetParameterIndex().GetValue()) << "The Vector2 condition should now refer to the 1st parameter in the anim graph."; // 2. Undo. EXPECT_TRUE(commandManager.Undo(result)) << result.c_str(); parameterIndex = m_animGraph->FindValueParameterIndexByName(parameterName); - EXPECT_TRUE(parameterIndex.IsSuccess() && parameterIndex.GetValue() == 1) << "The Vector2 parameter should now be back at the 2nd position."; + ASSERT_TRUE(parameterIndex.IsSuccess() && parameterIndex.GetValue() == 1) << "The Vector2 parameter should now be back at the 2nd position."; EXPECT_EQ(parameterIndex.GetValue(), condition->GetParameterIndex().GetValue()) << "The Vector2 condition should now refer to the 2nd parameter in the anim graph."; // 3. Redo. EXPECT_TRUE(commandManager.Redo(result)) << result.c_str(); parameterIndex = m_animGraph->FindValueParameterIndexByName(parameterName); - EXPECT_TRUE(parameterIndex.IsSuccess() && parameterIndex.GetValue() == 0) << "The Vector2 parameter should now be back at the 1st position."; + ASSERT_TRUE(parameterIndex.IsSuccess() && parameterIndex.GetValue() == 0) << "The Vector2 parameter should now be back at the 1st position."; EXPECT_EQ(parameterIndex.GetValue(), condition->GetParameterIndex().GetValue()) << "The Vector2 condition should now refer to the 1st parameter in the anim graph."; } } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/Tests/BlendTreeFootIKNodeTests.cpp b/Gems/EMotionFX/Code/Tests/BlendTreeFootIKNodeTests.cpp index 48350ce071..609d291800 100644 --- a/Gems/EMotionFX/Code/Tests/BlendTreeFootIKNodeTests.cpp +++ b/Gems/EMotionFX/Code/Tests/BlendTreeFootIKNodeTests.cpp @@ -209,15 +209,15 @@ namespace EMotionFX BlendTreeFootIKNode::UniqueData* uniqueData = static_cast(m_animGraphInstance->FindOrCreateUniqueNodeData(m_ikNode)); ASSERT_TRUE(uniqueData != nullptr); ASSERT_TRUE(!uniqueData->GetHasError()); - ASSERT_NE(uniqueData->m_legs[BlendTreeFootIKNode::LegId::Left].m_jointIndices[BlendTreeFootIKNode::LegJointId::UpperLeg], MCORE_INVALIDINDEX32); - ASSERT_NE(uniqueData->m_legs[BlendTreeFootIKNode::LegId::Left].m_jointIndices[BlendTreeFootIKNode::LegJointId::Knee], MCORE_INVALIDINDEX32); - ASSERT_NE(uniqueData->m_legs[BlendTreeFootIKNode::LegId::Left].m_jointIndices[BlendTreeFootIKNode::LegJointId::Foot], MCORE_INVALIDINDEX32); - ASSERT_NE(uniqueData->m_legs[BlendTreeFootIKNode::LegId::Left].m_jointIndices[BlendTreeFootIKNode::LegJointId::Toe], MCORE_INVALIDINDEX32); - ASSERT_NE(uniqueData->m_legs[BlendTreeFootIKNode::LegId::Right].m_jointIndices[BlendTreeFootIKNode::LegJointId::UpperLeg], MCORE_INVALIDINDEX32); - ASSERT_NE(uniqueData->m_legs[BlendTreeFootIKNode::LegId::Right].m_jointIndices[BlendTreeFootIKNode::LegJointId::Knee], MCORE_INVALIDINDEX32); - ASSERT_NE(uniqueData->m_legs[BlendTreeFootIKNode::LegId::Right].m_jointIndices[BlendTreeFootIKNode::LegJointId::Foot], MCORE_INVALIDINDEX32); - ASSERT_NE(uniqueData->m_legs[BlendTreeFootIKNode::LegId::Right].m_jointIndices[BlendTreeFootIKNode::LegJointId::Toe], MCORE_INVALIDINDEX32); - ASSERT_NE(uniqueData->m_hipJointIndex, MCORE_INVALIDINDEX32); + ASSERT_NE(uniqueData->m_legs[BlendTreeFootIKNode::LegId::Left].m_jointIndices[BlendTreeFootIKNode::LegJointId::UpperLeg], InvalidIndex); + ASSERT_NE(uniqueData->m_legs[BlendTreeFootIKNode::LegId::Left].m_jointIndices[BlendTreeFootIKNode::LegJointId::Knee], InvalidIndex); + ASSERT_NE(uniqueData->m_legs[BlendTreeFootIKNode::LegId::Left].m_jointIndices[BlendTreeFootIKNode::LegJointId::Foot], InvalidIndex); + ASSERT_NE(uniqueData->m_legs[BlendTreeFootIKNode::LegId::Left].m_jointIndices[BlendTreeFootIKNode::LegJointId::Toe], InvalidIndex); + ASSERT_NE(uniqueData->m_legs[BlendTreeFootIKNode::LegId::Right].m_jointIndices[BlendTreeFootIKNode::LegJointId::UpperLeg], InvalidIndex); + ASSERT_NE(uniqueData->m_legs[BlendTreeFootIKNode::LegId::Right].m_jointIndices[BlendTreeFootIKNode::LegJointId::Knee], InvalidIndex); + ASSERT_NE(uniqueData->m_legs[BlendTreeFootIKNode::LegId::Right].m_jointIndices[BlendTreeFootIKNode::LegJointId::Foot], InvalidIndex); + ASSERT_NE(uniqueData->m_legs[BlendTreeFootIKNode::LegId::Right].m_jointIndices[BlendTreeFootIKNode::LegJointId::Toe], InvalidIndex); + ASSERT_NE(uniqueData->m_hipJointIndex, InvalidIndex); // Make sure the weights are fully active. ASSERT_FLOAT_EQ(uniqueData->m_legs[BlendTreeFootIKNode::LegId::Left].m_weight, 1.0f); diff --git a/Gems/EMotionFX/Code/Tests/BlendTreeMaskNodeTests.cpp b/Gems/EMotionFX/Code/Tests/BlendTreeMaskNodeTests.cpp index 29c6269639..e63fd2c2c7 100644 --- a/Gems/EMotionFX/Code/Tests/BlendTreeMaskNodeTests.cpp +++ b/Gems/EMotionFX/Code/Tests/BlendTreeMaskNodeTests.cpp @@ -68,8 +68,8 @@ namespace EMotionFX Pose& outputPose = outputAnimGraphPose->GetPose(); // Output the assigned value of the node for each joint so that we can identify from which input each joint is coming from. - const AZ::u32 numJoints = outputPose.GetNumTransforms(); - for (AZ::u32 i = 0; i < numJoints; ++i) + const size_t numJoints = outputPose.GetNumTransforms(); + for (size_t i = 0; i < numJoints; ++i) { Transform transform = outputPose.GetLocalSpaceTransform(i); transform.mPosition = AZ::Vector3(m_identificationValue, m_identificationValue, m_identificationValue); @@ -113,7 +113,7 @@ namespace EMotionFX return result; } - AZ::Outcome FindMaskIndexForJoint(AZ::u32 jointIndex) const + AZ::Outcome FindMaskIndexForJoint(size_t jointIndex) const { const MaskNodeTestParam& param = GetParam(); Skeleton* skeleton = m_actor->GetSkeleton(); @@ -216,12 +216,12 @@ namespace EMotionFX GetEMotionFX().Update(0.0f); Skeleton* skeleton = m_actor->GetSkeleton(); - const AZ::u32 numJoints = skeleton->GetNumNodes(); + const size_t numJoints = skeleton->GetNumNodes(); TransformData* transformData = m_actorInstance->GetTransformData(); Pose* pose = transformData->GetCurrentPose(); // Iterate through the joints and make sure their transforms originate according to the mask setup. - for (AZ::u32 jointIndex = 0; jointIndex < numJoints; jointIndex++) + for (size_t jointIndex = 0; jointIndex < numJoints; jointIndex++) { const Node* joint = skeleton->GetNode(jointIndex); const char* jointName = joint->GetName(); diff --git a/Gems/EMotionFX/Code/Tests/BlendTreeRagdollNodeTests.cpp b/Gems/EMotionFX/Code/Tests/BlendTreeRagdollNodeTests.cpp index 8fedda5577..85504675db 100644 --- a/Gems/EMotionFX/Code/Tests/BlendTreeRagdollNodeTests.cpp +++ b/Gems/EMotionFX/Code/Tests/BlendTreeRagdollNodeTests.cpp @@ -127,7 +127,7 @@ namespace EMotionFX m_actorInstance->SetRagdoll(&testRagdoll); RagdollInstance* ragdollInstance = m_actorInstance->GetRagdollInstance(); const AZ::Outcome rootNodeIndex = ragdollInstance->GetRootRagdollNodeIndex(); - EXPECT_TRUE(rootNodeIndex.IsSuccess()) << "No root node for the ragdoll found."; + ASSERT_TRUE(rootNodeIndex.IsSuccess()) << "No root node for the ragdoll found."; EXPECT_EQ(ragdollInstance->GetRagdollRootNode()->GetNameString(), ragdollRootNodeName) << "Wrong ragdoll root node."; // Create an anim graph with a ragdoll node. diff --git a/Gems/EMotionFX/Code/Tests/Integration/CanAddSimpleMotionComponent.cpp b/Gems/EMotionFX/Code/Tests/Integration/CanAddSimpleMotionComponent.cpp index 74aea6ea50..09542a9761 100644 --- a/Gems/EMotionFX/Code/Tests/Integration/CanAddSimpleMotionComponent.cpp +++ b/Gems/EMotionFX/Code/Tests/Integration/CanAddSimpleMotionComponent.cpp @@ -66,7 +66,7 @@ namespace EMotionFX entity->GetId(), AZ::ComponentTypeList{azrtti_typeid()} ); - EXPECT_TRUE(componentOutcome.IsSuccess()) << componentOutcome.GetError().c_str(); + ASSERT_TRUE(componentOutcome.IsSuccess()) << componentOutcome.GetError().c_str(); bool hasComponent = false; AzToolsFramework::EditorComponentAPIBus::BroadcastResult( diff --git a/Gems/EMotionFX/Code/Tests/Integration/PoseComparisonTests.cpp b/Gems/EMotionFX/Code/Tests/Integration/PoseComparisonTests.cpp index dff4f4162c..d50b72cb4d 100644 --- a/Gems/EMotionFX/Code/Tests/Integration/PoseComparisonTests.cpp +++ b/Gems/EMotionFX/Code/Tests/Integration/PoseComparisonTests.cpp @@ -90,11 +90,11 @@ namespace EMotionFX bool MatchAndExplain(const KeyTrackLinearDynamic& got, ::testing::MatchResultListener* result_listener) const override { - const uint32 gotSize = got.GetNumKeys(); - const uint32 expectedSize = m_expected.GetNumKeys(); - const uint32 commonSize = AZStd::min(gotSize, expectedSize); + const size_t gotSize = got.GetNumKeys(); + const size_t expectedSize = m_expected.GetNumKeys(); + const size_t commonSize = AZStd::min(gotSize, expectedSize); - for (uint32 i = 0; i != commonSize; ++i) + for (size_t i = 0; i != commonSize; ++i) { const KeyFrame* gotKey = got.GetKey(i); const KeyFrame* expectedKey = m_expected.GetKey(i); @@ -104,9 +104,9 @@ namespace EMotionFX *result_listener << "where the value pair at index #" << i << " don't match\n"; const uint32 numContextLines = 2; - const uint32 beginContextLines = i > numContextLines ? i - numContextLines : 0; - const uint32 endContextLines = i > commonSize - numContextLines - 1 ? commonSize : i + numContextLines + 1; - for (uint32 contextIndex = beginContextLines; contextIndex < endContextLines; ++contextIndex) + const size_t beginContextLines = i > numContextLines ? i - numContextLines : 0; + const size_t endContextLines = i > commonSize - numContextLines - 1 ? commonSize : i + numContextLines + 1; + for (size_t contextIndex = beginContextLines; contextIndex < endContextLines; ++contextIndex) { const bool contextLineMatches = ::testing::Matches(innerMatcher)(::testing::make_tuple(got.GetKey(contextIndex), m_expected.GetKey(contextIndex))); if (!contextLineMatches) @@ -222,7 +222,7 @@ namespace EMotionFX { const Recorder::TransformTracks& gotTrack = gotTracks[trackNum]; const Recorder::TransformTracks& expectedTrack = expectedTracks[trackNum]; - const char* nodeName = gotActorInstanceData.mActorInstance->GetActor()->GetSkeleton()->GetNode(static_cast(trackNum))->GetName(); + const char* nodeName = gotActorInstanceData.mActorInstance->GetActor()->GetSkeleton()->GetNode(trackNum)->GetName(); EXPECT_THAT(gotTrack.mPositions, MatchesKeyTrack(expectedTrack.mPositions, nodeName)); EXPECT_THAT(gotTrack.mRotations, MatchesKeyTrack(expectedTrack.mRotations, nodeName)); @@ -285,7 +285,7 @@ namespace EMotionFX { const Recorder::TransformTracks& gotTrack = gotTracks[trackNum]; const Recorder::TransformTracks& expectedTrack = expectedTracks[trackNum]; - const char* nodeName = gotActorInstanceData.mActorInstance->GetActor()->GetSkeleton()->GetNode(static_cast(trackNum))->GetName(); + const char* nodeName = gotActorInstanceData.mActorInstance->GetActor()->GetSkeleton()->GetNode(trackNum)->GetName(); EXPECT_THAT(gotTrack.mPositions, MatchesKeyTrack(expectedTrack.mPositions, nodeName)); EXPECT_THAT(gotTrack.mRotations, MatchesKeyTrack(expectedTrack.mRotations, nodeName)); diff --git a/Gems/EMotionFX/Code/Tests/KeyTrackLinearTests.cpp b/Gems/EMotionFX/Code/Tests/KeyTrackLinearTests.cpp index bf7eee3afc..ae6150734e 100644 --- a/Gems/EMotionFX/Code/Tests/KeyTrackLinearTests.cpp +++ b/Gems/EMotionFX/Code/Tests/KeyTrackLinearTests.cpp @@ -32,9 +32,9 @@ namespace EMotionFX void LogFloatTrack(KeyTrackLinearDynamic& track) { AZ_Printf("EMotionFX", "----------\n"); - for (AZ::u32 i=0; i < track.GetNumKeys(); ++i) + for (size_t i=0; i < track.GetNumKeys(); ++i) { - AZ_Printf("EMotionFX", "#%d = time:%f value:%f\n", i, track.GetKey(i)->GetTime(), track.GetKey(i)->GetValue()); + AZ_Printf("EMotionFX", "#%zu = time:%f value:%f\n", i, track.GetKey(i)->GetTime(), track.GetKey(i)->GetValue()); } } @@ -185,16 +185,16 @@ namespace EMotionFX EMotionFX::KeyTrackLinearDynamic track; FillFloatTrackZeroToThree(track); - ASSERT_EQ(track.FindKeyNumber(-1.0f), MCORE_INVALIDINDEX32); + ASSERT_EQ(track.FindKeyNumber(-1.0f), InvalidIndex); ASSERT_EQ(track.FindKeyNumber(0.0f), 0); ASSERT_EQ(track.FindKeyNumber(1.0f), 1); ASSERT_EQ(track.FindKeyNumber(2.0f), 2); ASSERT_EQ(track.FindKeyNumber(2.4f), 2); ASSERT_EQ(track.FindKeyNumber(2.8f), 2); ASSERT_EQ(track.FindKeyNumber(2.999f), 2); - ASSERT_EQ(track.FindKeyNumber(3.0f), MCORE_INVALIDINDEX32); - ASSERT_EQ(track.FindKeyNumber(3.001f), MCORE_INVALIDINDEX32); - ASSERT_EQ(track.FindKeyNumber(4.0f), MCORE_INVALIDINDEX32); + ASSERT_EQ(track.FindKeyNumber(3.0f), InvalidIndex); + ASSERT_EQ(track.FindKeyNumber(3.001f), InvalidIndex); + ASSERT_EQ(track.FindKeyNumber(4.0f), InvalidIndex); } TEST_F(KeyTrackLinearDynamicFixture, KeyTrackSetNumKeys) @@ -231,7 +231,7 @@ namespace EMotionFX track.AddKey(2.01f, 1.0001f); track.AddKey(3.0f, 3.0f); track.Init(); - const uint32 numKeysRemoved = track.Optimize(0.001f); + const size_t numKeysRemoved = track.Optimize(0.001f); ASSERT_EQ(numKeysRemoved, 1); ASSERT_EQ(track.GetNumKeys(), 4); ASSERT_FLOAT_EQ(track.GetKey(0)->GetTime(), 0.0f); @@ -252,7 +252,7 @@ namespace EMotionFX ASSERT_FLOAT_EQ(track.GetValueAtTime(4.0f), 3.0f); uint8 cacheHit = 0; - uint32 cached = 0; + size_t cached = 0; ASSERT_FLOAT_EQ(track.GetValueAtTime(0.0f, &cached, &cacheHit), 0.0f); ASSERT_EQ(cached, 0); ASSERT_EQ(cacheHit, 1); diff --git a/Gems/EMotionFX/Code/Tests/Mocks/AnimGraph.h b/Gems/EMotionFX/Code/Tests/Mocks/AnimGraph.h index 90da8d5890..00eca16f44 100644 --- a/Gems/EMotionFX/Code/Tests/Mocks/AnimGraph.h +++ b/Gems/EMotionFX/Code/Tests/Mocks/AnimGraph.h @@ -30,7 +30,7 @@ namespace EMotionFX //uint32 RecursiveCalcNumNodes() const; //void RecursiveCalcStatistics(Statistics& outStatistics) const; //uint32 RecursiveCalcNumNodeConnections() const; - //void DecreaseInternalAttributeIndices(uint32 decreaseEverythingHigherThan); + //void DecreaseInternalAttributeIndices(size_t decreaseEverythingHigherThan); //AZStd::string GenerateNodeName(const AZStd::unordered_set& nameReserveList, const char* prefix = "Node") const; MOCK_CONST_METHOD0(GetNumParameters, size_t()); MOCK_CONST_METHOD0(GetNumValueParameters, size_t()); diff --git a/Gems/EMotionFX/Code/Tests/Mocks/AnimGraphInstance.h b/Gems/EMotionFX/Code/Tests/Mocks/AnimGraphInstance.h index 711392f6cf..e04f19fa95 100644 --- a/Gems/EMotionFX/Code/Tests/Mocks/AnimGraphInstance.h +++ b/Gems/EMotionFX/Code/Tests/Mocks/AnimGraphInstance.h @@ -27,27 +27,27 @@ namespace EMotionFX //bool GetVector3ParameterValue(const char* paramName, AZ::Vector3* outValue); //bool GetVector4ParameterValue(const char* paramName, AZ::Vector4* outValue); //bool GetRotationParameterValue(const char* paramName, MCore::Quaternion* outRotation); - //bool GetParameterValueAsFloat(uint32 paramIndex, float* outValue); - //bool GetParameterValueAsBool(uint32 paramIndex, bool* outValue); - //bool GetParameterValueAsInt(uint32 paramIndex, int32* outValue); - //bool GetVector2ParameterValue(uint32 paramIndex, AZ::Vector2* outValue); - //bool GetVector3ParameterValue(uint32 paramIndex, AZ::Vector3* outValue); - //bool GetVector4ParameterValue(uint32 paramIndex, AZ::Vector4* outValue); - //bool GetRotationParameterValue(uint32 paramIndex, MCore::Quaternion* outRotation); + //bool GetParameterValueAsFloat(size_t paramIndex, float* outValue); + //bool GetParameterValueAsBool(size_t paramIndex, bool* outValue); + //bool GetParameterValueAsInt(size_t paramIndex, int32* outValue); + //bool GetVector2ParameterValue(size_t paramIndex, AZ::Vector2* outValue); + //bool GetVector3ParameterValue(size_t paramIndex, AZ::Vector3* outValue); + //bool GetVector4ParameterValue(size_t paramIndex, AZ::Vector4* outValue); + //bool GetRotationParameterValue(size_t paramIndex, MCore::Quaternion* outRotation); //void SetMotionSet(MotionSet* motionSet); //void CreateParameterValues(); MOCK_METHOD0(AddMissingParameterValues, void()); - MOCK_METHOD1(ReInitParameterValue, void(uint32 index)); + MOCK_METHOD1(ReInitParameterValue, void(size_t index)); MOCK_METHOD0(ReInitParameterValues, void()); - MOCK_METHOD2(RemoveParameterValueImpl, void(uint32 index, bool delFromMem)); - virtual void RemoveParameterValue(uint32 index, bool delFromMem = true) { RemoveParameterValueImpl(index, delFromMem); } + MOCK_METHOD2(RemoveParameterValueImpl, void(size_t index, bool delFromMem)); + virtual void RemoveParameterValue(size_t index, bool delFromMem = true) { RemoveParameterValueImpl(index, delFromMem); } //void AddParameterValue(); - MOCK_METHOD2(MoveParameterValue, void(uint32 oldIndex, uint32 newIndex)); - MOCK_METHOD1(InsertParameterValue, void(uint32 index)); + MOCK_METHOD2(MoveParameterValue, void(size_t oldIndex, size_t newIndex)); + MOCK_METHOD1(InsertParameterValue, void(size_t index)); //void RemoveAllParameters(bool delFromMem); //template - //T* GetParameterValueChecked(uint32 index) const; - //MCore::Attribute* GetParameterValue(uint32 index) const; + //T* GetParameterValueChecked(size_t index) const; + //MCore::Attribute* GetParameterValue(size_t index) const; //MCore::Attribute* FindParameter(const AZStd::string& name) const; //AZ::Outcome FindParameterIndex(const AZStd::string& name) const; //bool SwitchToState(const char* stateName); diff --git a/Gems/EMotionFX/Code/Tests/Mocks/AnimGraphNode.h b/Gems/EMotionFX/Code/Tests/Mocks/AnimGraphNode.h index 85b80b2e60..9c73694d2a 100644 --- a/Gems/EMotionFX/Code/Tests/Mocks/AnimGraphNode.h +++ b/Gems/EMotionFX/Code/Tests/Mocks/AnimGraphNode.h @@ -15,8 +15,8 @@ namespace EMotionFX AZ_RTTI(AnimGraphNode, "{7F1C0E1D-4D32-4A6D-963C-20193EA28F95}", AnimGraphObject) MOCK_CONST_METHOD1(CollectOutgoingConnections, void(AZStd::vector>& outConnections)); - MOCK_CONST_METHOD2(CollectOutgoingConnections, void(AZStd::vector>& outConnections, const uint32 portIndex)); + MOCK_CONST_METHOD2(CollectOutgoingConnections, void(AZStd::vector>& outConnections, const size_t portIndex)); - MOCK_CONST_METHOD1(FindOutputPortIndex, uint32(const AZStd::string& name)); + MOCK_CONST_METHOD1(FindOutputPortIndex, size_t(const AZStd::string& name)); }; } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/Tests/Mocks/Node.h b/Gems/EMotionFX/Code/Tests/Mocks/Node.h index 9479883487..6c46cc95bb 100644 --- a/Gems/EMotionFX/Code/Tests/Mocks/Node.h +++ b/Gems/EMotionFX/Code/Tests/Mocks/Node.h @@ -25,10 +25,10 @@ namespace EMotionFX static Node* Create(const char* name, Skeleton* skeleton); static Node* Create(uint32 nameID, Skeleton* skeleton); MOCK_CONST_METHOD1(Clone, Node*(Skeleton* skeleton)); - MOCK_METHOD1(SetParentIndex, void(uint32 parentNodeIndex)); - MOCK_CONST_METHOD0(GetParentIndex, uint32()); + MOCK_METHOD1(SetParentIndex, void(size_t parentNodeIndex)); + MOCK_CONST_METHOD0(GetParentIndex, size_t()); MOCK_CONST_METHOD0(GetParentNode, Node*()); - MOCK_CONST_METHOD2(RecursiveCollectParents, void(AZStd::vector& parents, bool clearParentsArray)); + MOCK_CONST_METHOD2(RecursiveCollectParents, void(AZStd::vector& parents, bool clearParentsArray)); MOCK_METHOD1(SetName, void(const char* name)); MOCK_CONST_METHOD0(GetName, const char*()); MOCK_CONST_METHOD0(GetNameString, const AZStd::string&()); @@ -37,33 +37,33 @@ namespace EMotionFX MOCK_CONST_METHOD0(GetSemanticNameString, const AZStd::string&()); MOCK_CONST_METHOD0(GetID, uint32()); MOCK_CONST_METHOD0(GetSemanticID, uint32()); - MOCK_CONST_METHOD0(GetNumChildNodes, uint32()); - MOCK_CONST_METHOD0(GetNumChildNodesRecursive, uint32()); - MOCK_CONST_METHOD1(GetChildIndex, uint32(uint32 nr)); - MOCK_CONST_METHOD1(CheckIfIsChildNode, bool(uint32 nodeIndex)); - MOCK_METHOD1(AddChild, void(uint32 nodeIndex)); - MOCK_METHOD2(SetChild, void(uint32 childNr, uint32 childNodeIndex)); - MOCK_METHOD1(SetNumChildNodes, void(uint32 numChildNodes)); - MOCK_METHOD1(PreAllocNumChildNodes, void(uint32 numChildNodes)); - MOCK_METHOD1(RemoveChild, void(uint32 nodeIndex)); + MOCK_CONST_METHOD0(GetNumChildNodes, size_t()); + MOCK_CONST_METHOD0(GetNumChildNodesRecursive, size_t()); + MOCK_CONST_METHOD1(GetChildIndex, size_t(size_t nr)); + MOCK_CONST_METHOD1(CheckIfIsChildNode, bool(size_t nodeIndex)); + MOCK_METHOD1(AddChild, void(size_t nodeIndex)); + MOCK_METHOD2(SetChild, void(size_t childNr, size_t childNodeIndex)); + MOCK_METHOD1(SetNumChildNodes, void(size_t numChildNodes)); + MOCK_METHOD1(PreAllocNumChildNodes, void(size_t numChildNodes)); + MOCK_METHOD1(RemoveChild, void(size_t nodeIndex)); MOCK_METHOD0(RemoveAllChildNodes, void()); MOCK_CONST_METHOD0(GetIsRootNode, bool()); MOCK_CONST_METHOD0(GetHasChildNodes, bool()); MOCK_CONST_METHOD0(FindRoot, Node*()); MOCK_METHOD1(AddAttribute, void(NodeAttribute* attribute)); - MOCK_CONST_METHOD0(GetNumAttributes, uint32()); - MOCK_METHOD1(GetAttribute, NodeAttribute*(uint32 attributeNr)); + MOCK_CONST_METHOD0(GetNumAttributes, size_t()); + MOCK_METHOD1(GetAttribute, NodeAttribute*(size_t attributeNr)); MOCK_METHOD1(GetAttributeByType, NodeAttribute*(uint32 attributeType)); - MOCK_CONST_METHOD1(FindAttributeNumber, uint32(uint32 attributeTypeID)); + MOCK_CONST_METHOD1(FindAttributeNumber, size_t(uint32 attributeTypeID)); MOCK_METHOD0(RemoveAllAttributes, void()); - MOCK_METHOD1(RemoveAttribute, void(uint32 index)); - MOCK_METHOD2(RemoveAttributeByType, void(uint32 attributeTypeID, uint32 occurrence)); - MOCK_METHOD1(RemoveAllAttributesByType, uint32(uint32 attributeTypeID)); - MOCK_METHOD1(SetNodeIndex, void(uint32 index)); - MOCK_CONST_METHOD0(GetNodeIndex, uint32()); + MOCK_METHOD1(RemoveAttribute, void(size_t index)); + MOCK_METHOD2(RemoveAttributeByType, void(uint32 attributeTypeID, size_t occurrence)); + MOCK_METHOD1(RemoveAllAttributesByType, size_t(uint32 attributeTypeID)); + MOCK_METHOD1(SetNodeIndex, void(size_t index)); + MOCK_CONST_METHOD0(GetNodeIndex, size_t()); MOCK_METHOD1(SetSkeletalLODLevelBits, void(uint32 bitValues)); - MOCK_METHOD2(SetSkeletalLODStatus, void(uint32 lodLevel, bool enabled)); - MOCK_CONST_METHOD1(GetSkeletalLODStatus, bool(uint32 lodLevel)); + MOCK_METHOD2(SetSkeletalLODStatus, void(size_t lodLevel, bool enabled)); + MOCK_CONST_METHOD1(GetSkeletalLODStatus, bool(size_t lodLevel)); MOCK_CONST_METHOD0(GetIncludeInBoundsCalc, bool()); MOCK_METHOD1(SetIncludeInBoundsCalc, void(bool includeThisNode)); MOCK_CONST_METHOD0(GetIsAttachmentNode, bool()); diff --git a/Gems/EMotionFX/Code/Tests/Mocks/SimulatedJoint.h b/Gems/EMotionFX/Code/Tests/Mocks/SimulatedJoint.h index bb1b8aef68..5f2f78cf25 100644 --- a/Gems/EMotionFX/Code/Tests/Mocks/SimulatedJoint.h +++ b/Gems/EMotionFX/Code/Tests/Mocks/SimulatedJoint.h @@ -26,7 +26,7 @@ namespace EMotionFX SimulatedJoint([[maybe_unused]] const SimulatedJoint& simulatedJoint) {} MOCK_METHOD1(SetSimulatedObject, void (SimulatedObject* object)); - MOCK_METHOD1(SetSkeletonJointIndex, void (AZ::u32 jointIndex)); + MOCK_METHOD1(SetSkeletonJointIndex, void (size_t jointIndex)); MOCK_METHOD1(SetConeAngleLimit, void (float degrees)); MOCK_METHOD1(SetMass, void (float mass)); MOCK_METHOD1(SetStiffness, void (float stiffness)); @@ -36,7 +36,7 @@ namespace EMotionFX MOCK_METHOD1(SetPinned, void (bool pinned)); MOCK_METHOD1(InitAfterLoading, bool (SimulatedObject* object)); - MOCK_CONST_METHOD0(GetSkeletonJointIndex, AZ::u32()); + MOCK_CONST_METHOD0(GetSkeletonJointIndex, size_t()); MOCK_CONST_METHOD0(GetConeAngleLimit, float()); MOCK_CONST_METHOD0(GetMass, float()); MOCK_CONST_METHOD0(GetStiffness, float()); diff --git a/Gems/EMotionFX/Code/Tests/Mocks/SimulatedObject.h b/Gems/EMotionFX/Code/Tests/Mocks/SimulatedObject.h index a9d69ea8af..320871ed7f 100644 --- a/Gems/EMotionFX/Code/Tests/Mocks/SimulatedObject.h +++ b/Gems/EMotionFX/Code/Tests/Mocks/SimulatedObject.h @@ -18,14 +18,14 @@ namespace EMotionFX { public: AZ_TYPE_INFO(SimulatedObject, "{8CF0F474-69DC-4DE3-AF19-002F19DA27DB}"); - MOCK_CONST_METHOD1(FindSimulatedJointBySkeletonJointIndex, SimulatedJoint*(AZ::u32)); + MOCK_CONST_METHOD1(FindSimulatedJointBySkeletonJointIndex, SimulatedJoint*(size_t)); - MOCK_METHOD1(AddSimulatedJointAndChildren, void(AZ::u32)); - MOCK_METHOD1(AddSimulatedJoint, SimulatedJoint*(AZ::u32)); - MOCK_METHOD1(AddSimulatedJoints, void(AZStd::vector joints)); + MOCK_METHOD1(AddSimulatedJointAndChildren, void(size_t)); + MOCK_METHOD1(AddSimulatedJoint, SimulatedJoint*(size_t)); + MOCK_METHOD1(AddSimulatedJoints, void(AZStd::vector joints)); - MOCK_METHOD2(RemoveSimulatedJoint, void(AZ::u32, bool)); - MOCK_METHOD1(RemoveSimulatedJoint, void(AZ::u32)); + MOCK_METHOD2(RemoveSimulatedJoint, void(size_t, bool)); + MOCK_METHOD1(RemoveSimulatedJoint, void(size_t)); MOCK_CONST_METHOD0(GetNumSimulatedJoints, size_t()); MOCK_CONST_METHOD1(SetSimulatedJoints, void(const AZStd::vector& joints)); diff --git a/Gems/EMotionFX/Code/Tests/Mocks/Skeleton.h b/Gems/EMotionFX/Code/Tests/Mocks/Skeleton.h index b6aa4309f8..987718a157 100644 --- a/Gems/EMotionFX/Code/Tests/Mocks/Skeleton.h +++ b/Gems/EMotionFX/Code/Tests/Mocks/Skeleton.h @@ -11,8 +11,8 @@ namespace EMotionFX class Skeleton { public: - MOCK_CONST_METHOD1(GetNode, Node*(uint32 index)); + MOCK_CONST_METHOD1(GetNode, Node*(size_t index)); MOCK_CONST_METHOD1(FindNodeByName, Node*(const char* name)); - MOCK_CONST_METHOD0(GetNumNodes, uint32()); + MOCK_CONST_METHOD0(GetNumNodes, size_t()); }; } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/Tests/MorphTargetRuntimeTests.cpp b/Gems/EMotionFX/Code/Tests/MorphTargetRuntimeTests.cpp index 24afc7af47..10f735ca24 100644 --- a/Gems/EMotionFX/Code/Tests/MorphTargetRuntimeTests.cpp +++ b/Gems/EMotionFX/Code/Tests/MorphTargetRuntimeTests.cpp @@ -116,7 +116,7 @@ namespace EMotionFX // InitAfterLoading() is called morphTargetNode->AddConnection( parameterNode, - parameterNode->FindOutputPortIndex("FloatParam"), + aznumeric_caster(parameterNode->FindOutputPortIndex("FloatParam")), BlendTreeMorphTargetNode::PORTID_INPUT_WEIGHT ); finalNode->AddConnection( diff --git a/Gems/EMotionFX/Code/Tests/MotionEventTrackTests.cpp b/Gems/EMotionFX/Code/Tests/MotionEventTrackTests.cpp index c1fa8f3be4..a857efb2ca 100644 --- a/Gems/EMotionFX/Code/Tests/MotionEventTrackTests.cpp +++ b/Gems/EMotionFX/Code/Tests/MotionEventTrackTests.cpp @@ -191,7 +191,7 @@ namespace EMotionFX } EXPECT_EQ(m_buffer->GetNumEvents(), expectedEvents.size()) << "Number of events is incorrect"; - for (uint32 i = 0; i < AZStd::min(m_buffer->GetNumEvents(), static_cast(expectedEvents.size())); ++i) + for (size_t i = 0; i < AZStd::min(m_buffer->GetNumEvents(), expectedEvents.size()); ++i) { const EventInfo& gotEvent = m_buffer->GetEvent(i); const EventInfo& expectedEvent = expectedEvents[i]; diff --git a/Gems/EMotionFX/Code/Tests/NonUniformMotionDataTests.cpp b/Gems/EMotionFX/Code/Tests/NonUniformMotionDataTests.cpp index 7498eed311..02256e1e12 100644 --- a/Gems/EMotionFX/Code/Tests/NonUniformMotionDataTests.cpp +++ b/Gems/EMotionFX/Code/Tests/NonUniformMotionDataTests.cpp @@ -185,15 +185,15 @@ namespace EMotionFX EXPECT_FALSE(motionData.FindJointIndexByName("Blah").IsSuccess()); EXPECT_FALSE(motionData.FindMorphIndexByName("Blah").IsSuccess()); EXPECT_FALSE(motionData.FindFloatIndexByName("Blah").IsSuccess()); - EXPECT_TRUE(motionData.FindJointIndexByName("Joint1").IsSuccess()); - EXPECT_TRUE(motionData.FindJointIndexByName("Joint2").IsSuccess()); - EXPECT_TRUE(motionData.FindJointIndexByName("Joint3").IsSuccess()); - EXPECT_TRUE(motionData.FindMorphIndexByName("Morph1").IsSuccess()); - EXPECT_TRUE(motionData.FindMorphIndexByName("Morph2").IsSuccess()); - EXPECT_TRUE(motionData.FindMorphIndexByName("Morph3").IsSuccess()); - EXPECT_TRUE(motionData.FindFloatIndexByName("Float1").IsSuccess()); - EXPECT_TRUE(motionData.FindFloatIndexByName("Float2").IsSuccess()); - EXPECT_TRUE(motionData.FindFloatIndexByName("Float3").IsSuccess()); + ASSERT_TRUE(motionData.FindJointIndexByName("Joint1").IsSuccess()); + ASSERT_TRUE(motionData.FindJointIndexByName("Joint2").IsSuccess()); + ASSERT_TRUE(motionData.FindJointIndexByName("Joint3").IsSuccess()); + ASSERT_TRUE(motionData.FindMorphIndexByName("Morph1").IsSuccess()); + ASSERT_TRUE(motionData.FindMorphIndexByName("Morph2").IsSuccess()); + ASSERT_TRUE(motionData.FindMorphIndexByName("Morph3").IsSuccess()); + ASSERT_TRUE(motionData.FindFloatIndexByName("Float1").IsSuccess()); + ASSERT_TRUE(motionData.FindFloatIndexByName("Float2").IsSuccess()); + ASSERT_TRUE(motionData.FindFloatIndexByName("Float3").IsSuccess()); EXPECT_EQ(motionData.FindJointIndexByName("Joint1").GetValue(), 0); EXPECT_EQ(motionData.FindJointIndexByName("Joint2").GetValue(), 1); EXPECT_EQ(motionData.FindJointIndexByName("Joint3").GetValue(), 2); @@ -663,7 +663,7 @@ namespace EMotionFX // Test morph sampling. AZ::Outcome index = motionData.FindMorphIndexByName("Morph1"); - EXPECT_TRUE(index.IsSuccess()); + ASSERT_TRUE(index.IsSuccess()); if (index.IsSuccess()) { float result = -1.0f; @@ -693,7 +693,7 @@ namespace EMotionFX // Test float sampling. index = motionData.FindFloatIndexByName("Float1"); - EXPECT_TRUE(index.IsSuccess()); + ASSERT_TRUE(index.IsSuccess()); if (index.IsSuccess()) { float result = -1.0f; diff --git a/Gems/EMotionFX/Code/Tests/PoseTests.cpp b/Gems/EMotionFX/Code/Tests/PoseTests.cpp index 1785a4d512..0dd592cda7 100644 --- a/Gems/EMotionFX/Code/Tests/PoseTests.cpp +++ b/Gems/EMotionFX/Code/Tests/PoseTests.cpp @@ -74,8 +74,8 @@ namespace EMotionFX void CompareFlags(const Pose& pose, uint8 expectedFlags) { - const AZ::u32 numTransforms = pose.GetNumTransforms(); - for (AZ::u32 i = 0; i < numTransforms; ++i) + const size_t numTransforms = pose.GetNumTransforms(); + for (size_t i = 0; i < numTransforms; ++i) { EXPECT_EQ(pose.GetFlags(i), expectedFlags); } @@ -83,10 +83,10 @@ namespace EMotionFX void CompareFlags(const Pose& poseA, const Pose& poseB) { - const AZ::u32 numTransforms = poseA.GetNumTransforms(); + const size_t numTransforms = poseA.GetNumTransforms(); EXPECT_EQ(numTransforms, poseB.GetNumTransforms()); - for (AZ::u32 i = 0; i < numTransforms; ++i) + for (size_t i = 0; i < numTransforms; ++i) { EXPECT_EQ(poseA.GetFlags(i), poseB.GetFlags(i)); } @@ -94,10 +94,10 @@ namespace EMotionFX void CompareMorphTargets(const Pose& poseA, const Pose& poseB) { - const AZ::u32 numMorphWeights = poseA.GetNumMorphWeights(); + const size_t numMorphWeights = poseA.GetNumMorphWeights(); EXPECT_EQ(numMorphWeights, poseB.GetNumMorphWeights()); - for (AZ::u32 i = 0; i < numMorphWeights; ++i) + for (size_t i = 0; i < numMorphWeights; ++i) { EXPECT_EQ(poseA.GetMorphWeight(i), poseB.GetMorphWeight(i)); } @@ -113,10 +113,10 @@ namespace EMotionFX void ComparePoseTransforms(const Pose& poseA, const Pose& poseB) { - const AZ::u32 numTransforms = poseA.GetNumTransforms(); + const size_t numTransforms = poseA.GetNumTransforms(); EXPECT_EQ(numTransforms, poseB.GetNumTransforms()); - for (AZ::u32 i = 0; i < numTransforms; ++i) + for (size_t i = 0; i < numTransforms; ++i) { const Transform& localA = poseA.GetLocalSpaceTransform(i); const Transform& localB = poseB.GetLocalSpaceTransform(i); @@ -140,7 +140,7 @@ namespace EMotionFX public: AZStd::unique_ptr m_actor; ActorInstance* m_actorInstance = nullptr; - const AZ::u32 m_numMorphTargets = 5; + const size_t m_numMorphTargets = 5; const float m_testOffset = 10.0f; }; @@ -184,8 +184,8 @@ namespace EMotionFX Pose pose; pose.LinkToActor(m_actor.get()); - const AZ::u32 numTransforms = pose.GetNumTransforms(); - for (AZ::u32 i = 0; i < numTransforms; ++i) + const size_t numTransforms = pose.GetNumTransforms(); + for (size_t i = 0; i < numTransforms; ++i) { pose.SetFlags(i, Pose::FLAG_LOCALTRANSFORMREADY); EXPECT_EQ(pose.GetFlags(i), Pose::FLAG_LOCALTRANSFORMREADY); @@ -270,7 +270,7 @@ namespace EMotionFX AZ::SimpleLcgRandom random; random.SetSeed(875960); - for (AZ::u32 i = 0; i < m_numMorphTargets; ++i) + for (size_t i = 0; i < m_numMorphTargets; ++i) { // Zero all weights on the morph instance. morphInstance->GetMorphTarget(i)->SetWeight(0.0f); @@ -284,7 +284,7 @@ namespace EMotionFX pose.ApplyMorphWeightsToActorInstance(); // Check if all weights got correctly forwarded from the pose to the actor instance. - for (AZ::u32 i = 0; i < m_numMorphTargets; ++i) + for (size_t i = 0; i < m_numMorphTargets; ++i) { EXPECT_EQ(pose.GetMorphWeight(i), morphInstance->GetMorphTarget(i)->GetWeight()); } @@ -297,7 +297,7 @@ namespace EMotionFX EXPECT_EQ(pose.GetNumMorphWeights(), m_numMorphTargets); // Set and get tests. - for (AZ::u32 i = 0; i < m_numMorphTargets; ++i) + for (size_t i = 0; i < m_numMorphTargets; ++i) { const float newWeight = static_cast(i); pose.SetMorphWeight(i, newWeight); @@ -306,7 +306,7 @@ namespace EMotionFX // Zero weights test. pose.ZeroMorphWeights(); - for (AZ::u32 i = 0; i < m_numMorphTargets; ++i) + for (size_t i = 0; i < m_numMorphTargets; ++i) { EXPECT_EQ(pose.GetMorphWeight(i), 0.0f); } @@ -326,7 +326,7 @@ namespace EMotionFX { Pose pose; pose.LinkToActor(m_actor.get()); - const AZ::u32 jointIndex = 0; + const size_t jointIndex = 0; // Set the new transform. Transform newTransform(AZ::Vector3(1.0f, 2.0f, 3.0f), AZ::Quaternion(0.1f, 0.2f, 0.3f, 0.4f), AZ::Vector3(4.0f, 5.0f, 6.0f)); @@ -337,7 +337,7 @@ namespace EMotionFX // All model space transforms should be invalidated. // The model space transform of the node doesn't get automatically updated and // all child node model transforms are invalidated along with the joint. - for (AZ::u32 i = jointIndex; i < m_actor->GetNumNodes(); ++i) + for (size_t i = jointIndex; i < m_actor->GetNumNodes(); ++i) { EXPECT_FALSE(pose.GetFlags(i) & Pose::FLAG_MODELTRANSFORMREADY); } @@ -355,7 +355,7 @@ namespace EMotionFX { Pose pose; pose.LinkToActor(m_actor.get()); - const AZ::u32 jointIndex = 0; + const size_t jointIndex = 0; Transform newTransform(AZ::Vector3(1.0f, 2.0f, 3.0f), AZ::Quaternion(0.1f, 0.2f, 0.3f, 0.4f), AZ::Vector3(4.0f, 5.0f, 6.0f)); pose.SetLocalSpaceTransformDirect(jointIndex, newTransform); @@ -367,7 +367,7 @@ namespace EMotionFX { Pose pose; pose.LinkToActor(m_actor.get()); - const AZ::u32 jointIndex = 0; + const size_t jointIndex = 0; // Set the new transform. Transform newTransform(AZ::Vector3(1.0f, 2.0f, 3.0f), AZ::Quaternion(0.1f, 0.2f, 0.3f, 0.4f), AZ::Vector3(4.0f, 5.0f, 6.0f)); @@ -381,7 +381,7 @@ namespace EMotionFX EXPECT_TRUE(pose.GetFlags(jointIndex) & Pose::FLAG_LOCALTRANSFORMREADY); // All child model space transforms should be invalidated as they haven't been updated yet. - for (AZ::u32 i = jointIndex + 1; i < m_actor->GetNumNodes(); ++i) + for (size_t i = jointIndex + 1; i < m_actor->GetNumNodes(); ++i) { EXPECT_FALSE(pose.GetFlags(i) & Pose::FLAG_MODELTRANSFORMREADY); } @@ -398,7 +398,7 @@ namespace EMotionFX { Pose pose; pose.LinkToActor(m_actor.get()); - const AZ::u32 jointIndex = 0; + const size_t jointIndex = 0; Transform newTransform(AZ::Vector3(1.0f, 2.0f, 3.0f), AZ::Quaternion(0.1f, 0.2f, 0.3f, 0.4f), AZ::Vector3(4.0f, 5.0f, 6.0f)); pose.SetModelSpaceTransformDirect(jointIndex, newTransform); @@ -415,7 +415,7 @@ namespace EMotionFX const Transform newTransform(AZ::Vector3(1.0f, 1.0f, 1.0f), AZ::Quaternion::CreateIdentity()); // Iterate through the joints, adjust their local space transforms and check if the model space transform adjusts automatically, accordingly. - for (AZ::u32 i = 0; i < m_actor->GetSkeleton()->GetNumNodes(); ++i) + for (size_t i = 0; i < m_actor->GetSkeleton()->GetNumNodes(); ++i) { pose.SetLocalSpaceTransform(i, newTransform); EXPECT_EQ(pose.GetLocalSpaceTransform(i), newTransform); @@ -433,7 +433,7 @@ namespace EMotionFX const Transform newTransform(AZ::Vector3(1.0f, 1.0f, 1.0f), AZ::Quaternion::CreateIdentity()); // Same as the previous test, but this time we use the direct call which does not automatically invalidate the model space transform. - for (AZ::u32 i = 0; i < m_actor->GetSkeleton()->GetNumNodes(); ++i) + for (size_t i = 0; i < m_actor->GetSkeleton()->GetNumNodes(); ++i) { const Transform oldModelSpaceTransform = pose.GetModelSpaceTransform(i); @@ -458,7 +458,7 @@ namespace EMotionFX pose.InitFromBindPose(m_actor.get()); // Similar to previous test, model space and local space operations are switched. - for (AZ::u32 i = 0; i < m_actor->GetSkeleton()->GetNumNodes(); ++i) + for (size_t i = 0; i < m_actor->GetSkeleton()->GetNumNodes(); ++i) { const Transform oldLocalSpaceTransform = pose.GetLocalSpaceTransform(i); const Transform newTransform(Transform(AZ::Vector3(0.0f, 0.0f, static_cast((i + 1) * m_testOffset)), AZ::Quaternion::CreateIdentity())); @@ -482,7 +482,7 @@ namespace EMotionFX pose.LinkToActor(m_actor.get()); pose.InitFromBindPose(m_actor.get()); - for (AZ::u32 i = 0; i < m_actor->GetSkeleton()->GetNumNodes(); ++i) + for (size_t i = 0; i < m_actor->GetSkeleton()->GetNumNodes(); ++i) { const Transform oldLocalSpaceTransform = pose.GetLocalSpaceTransform(i); const Transform newTransform(Transform(AZ::Vector3(0.0f, 0.0f, static_cast((i + 1) * m_testOffset)), AZ::Quaternion::CreateIdentity())); @@ -503,13 +503,13 @@ namespace EMotionFX } else { - for (AZ::u32 i = 0; i < m_actor->GetSkeleton()->GetNumNodes(); ++i) + for (size_t i = 0; i < m_actor->GetSkeleton()->GetNumNodes(); ++i) { pose.UpdateLocalSpaceTransform(i); } } - for (AZ::u32 i = 0; i < m_actor->GetSkeleton()->GetNumNodes(); ++i) + for (size_t i = 0; i < m_actor->GetSkeleton()->GetNumNodes(); ++i) { // Get the local space transform without auto-updating them, to see if update call worked. EXPECT_EQ(pose.GetLocalSpaceTransformDirect(i), Transform(AZ::Vector3(0.0f, 0.0f, m_testOffset), AZ::Quaternion::CreateIdentity())); @@ -522,7 +522,7 @@ namespace EMotionFX pose.LinkToActor(m_actor.get()); pose.InitFromBindPose(m_actor.get()); - for (AZ::u32 i = 0; i < m_actor->GetSkeleton()->GetNumNodes(); ++i) + for (size_t i = 0; i < m_actor->GetSkeleton()->GetNumNodes(); ++i) { const Transform oldLocalSpaceTransform = pose.GetLocalSpaceTransform(i); const Transform newTransform(AZ::Vector3(0.0f, 0.0f, static_cast((i + 1) * m_testOffset)), AZ::Quaternion::CreateIdentity()); @@ -536,7 +536,7 @@ namespace EMotionFX // Update all local space transforms regardless of the invalidate flag. pose.ForceUpdateFullLocalSpacePose(); - for (AZ::u32 i = 0; i < m_actor->GetSkeleton()->GetNumNodes(); ++i) + for (size_t i = 0; i < m_actor->GetSkeleton()->GetNumNodes(); ++i) { // Get the local space transform without auto-updating them, to see if update call worked. EXPECT_EQ(pose.GetLocalSpaceTransformDirect(i), Transform(AZ::Vector3(0.0f, 0.0f, m_testOffset), AZ::Quaternion::CreateIdentity())); @@ -549,7 +549,7 @@ namespace EMotionFX pose.LinkToActor(m_actor.get()); pose.InitFromBindPose(m_actor.get()); - for (AZ::u32 i = 0; i < m_actor->GetSkeleton()->GetNumNodes(); ++i) + for (size_t i = 0; i < m_actor->GetSkeleton()->GetNumNodes(); ++i) { const Transform oldModelSpaceTransform = pose.GetModelSpaceTransform(i); const Transform newTransform(AZ::Vector3(0.0f, 0.0f, m_testOffset), AZ::Quaternion::CreateIdentity()); @@ -567,13 +567,13 @@ namespace EMotionFX } else { - for (AZ::u32 i = 0; i < m_actor->GetSkeleton()->GetNumNodes(); ++i) + for (size_t i = 0; i < m_actor->GetSkeleton()->GetNumNodes(); ++i) { pose.UpdateModelSpaceTransform(i); } } - for (AZ::u32 i = 0; i < m_actor->GetSkeleton()->GetNumNodes(); ++i) + for (size_t i = 0; i < m_actor->GetSkeleton()->GetNumNodes(); ++i) { // Get the model space transform without auto-updating them, to see if the update call worked. EXPECT_EQ(pose.GetModelSpaceTransformDirect(i), @@ -587,7 +587,7 @@ namespace EMotionFX pose.LinkToActor(m_actor.get()); pose.InitFromBindPose(m_actor.get()); - for (AZ::u32 i = 0; i < m_actor->GetSkeleton()->GetNumNodes(); ++i) + for (size_t i = 0; i < m_actor->GetSkeleton()->GetNumNodes(); ++i) { const Transform oldModelSpaceTransform = pose.GetModelSpaceTransform(i); const Transform newTransform(AZ::Vector3(0.0f, 0.0f, m_testOffset), AZ::Quaternion::CreateIdentity()); @@ -601,7 +601,7 @@ namespace EMotionFX // Update all model space transforms regardless of the invalidate flag. pose.ForceUpdateFullModelSpacePose(); - for (AZ::u32 i = 0; i < m_actor->GetSkeleton()->GetNumNodes(); ++i) + for (size_t i = 0; i < m_actor->GetSkeleton()->GetNumNodes(); ++i) { // Get the model space transform without auto-updating them, to see if the ForceUpdateFullModelSpacePose() worked. EXPECT_EQ(pose.GetModelSpaceTransformDirect(i), Transform(AZ::Vector3(0.0f, 0.0f, static_cast((i + 1) * m_testOffset)), AZ::Quaternion::CreateIdentity())); @@ -618,7 +618,7 @@ namespace EMotionFX m_actorInstance->SetLocalSpaceTransform(offsetTransform); m_actorInstance->UpdateWorldTransform(); - for (AZ::u32 i = 0; i < m_actor->GetSkeleton()->GetNumNodes(); ++i) + for (size_t i = 0; i < m_actor->GetSkeleton()->GetNumNodes(); ++i) { pose.SetLocalSpaceTransform(i, offsetTransform); @@ -638,8 +638,8 @@ namespace EMotionFX TEST_F(PoseTests, GetMeshNodeWorldSpaceTransform) { - const AZ::u32 lodLevel = 0; - const AZ::u32 jointIndex = 0; + const size_t lodLevel = 0; + const size_t jointIndex = 0; Pose pose; // If there is no actor instance linked, expect the identity transform. @@ -677,8 +677,8 @@ namespace EMotionFX TEST_P(PoseTestsBoolParam, CompensateForMotionExtraction) { - const AZ::u32 motionExtractionJointIndex = m_actor->GetMotionExtractionNodeIndex(); - ASSERT_NE(motionExtractionJointIndex, MCORE_INVALIDINDEX32) + const size_t motionExtractionJointIndex = m_actor->GetMotionExtractionNodeIndex(); + ASSERT_NE(motionExtractionJointIndex, InvalidIndex) << "Motion extraction joint not set for the test actor."; Pose pose; @@ -715,8 +715,8 @@ namespace EMotionFX TEST_F(PoseTests, CalcTrajectoryTransform) { - const AZ::u32 motionExtractionJointIndex = m_actor->GetMotionExtractionNodeIndex(); - ASSERT_NE(motionExtractionJointIndex, MCORE_INVALIDINDEX32) + const size_t motionExtractionJointIndex = m_actor->GetMotionExtractionNodeIndex(); + ASSERT_NE(motionExtractionJointIndex, InvalidIndex) << "Motion extraction joint not set for the test actor."; Pose pose; @@ -969,8 +969,8 @@ namespace EMotionFX poseB.SetLocalSpaceTransform(i, transformB); } - const AZ::u32 numMorphWeights = poseA.GetNumMorphWeights(); - for (AZ::u32 i = 0; i < numMorphWeights; ++i) + const size_t numMorphWeights = poseA.GetNumMorphWeights(); + for (size_t i = 0; i < numMorphWeights; ++i) { const float floatI = static_cast(i); poseA.SetMorphWeight(i, floatI); @@ -993,7 +993,7 @@ namespace EMotionFX EXPECT_THAT(transformResult, IsClose(expectedResult)); } - for (AZ::u32 i = 0; i < numMorphWeights; ++i) + for (size_t i = 0; i < numMorphWeights; ++i) { EXPECT_FLOAT_EQ(poseSum.GetMorphWeight(i), poseA.GetMorphWeight(i) + poseB.GetMorphWeight(i) * weight); @@ -1106,8 +1106,8 @@ namespace EMotionFX poseB.SetLocalSpaceTransform(i, transformB); } - const AZ::u32 numMorphWeights = poseA.GetNumMorphWeights(); - for (AZ::u32 i = 0; i < numMorphWeights; ++i) + const size_t numMorphWeights = poseA.GetNumMorphWeights(); + for (size_t i = 0; i < numMorphWeights; ++i) { const float floatI = static_cast(i); poseA.SetMorphWeight(i, floatI); @@ -1183,7 +1183,7 @@ namespace EMotionFX { case 0: { - for (AZ::u32 i = 0; i < numMorphWeights; ++i) + for (size_t i = 0; i < numMorphWeights; ++i) { EXPECT_FLOAT_EQ(poseResult.GetMorphWeight(i), poseA.GetMorphWeight(i) - poseB.GetMorphWeight(i)); @@ -1192,7 +1192,7 @@ namespace EMotionFX } case 1: { - for (AZ::u32 i = 0; i < numMorphWeights; ++i) + for (size_t i = 0; i < numMorphWeights; ++i) { EXPECT_FLOAT_EQ(poseResult.GetMorphWeight(i), poseA.GetMorphWeight(i) + poseB.GetMorphWeight(i)); @@ -1201,7 +1201,7 @@ namespace EMotionFX } case 2: { - for (AZ::u32 i = 0; i < numMorphWeights; ++i) + for (size_t i = 0; i < numMorphWeights; ++i) { EXPECT_FLOAT_EQ(poseResult.GetMorphWeight(i), poseA.GetMorphWeight(i) + poseB.GetMorphWeight(i) * weight); @@ -1228,8 +1228,8 @@ namespace EMotionFX } // Check if morph target weights are all zero. - const AZ::u32 numMorphWeights = pose.GetNumMorphWeights(); - for (AZ::u32 i = 0; i < numMorphWeights; ++i) + const size_t numMorphWeights = pose.GetNumMorphWeights(); + for (size_t i = 0; i < numMorphWeights; ++i) { EXPECT_EQ(pose.GetMorphWeight(i), 0.0f); } diff --git a/Gems/EMotionFX/Code/Tests/Prefabs/LeftArmSkeleton.h b/Gems/EMotionFX/Code/Tests/Prefabs/LeftArmSkeleton.h index 7cbcf24322..2af9da3306 100644 --- a/Gems/EMotionFX/Code/Tests/Prefabs/LeftArmSkeleton.h +++ b/Gems/EMotionFX/Code/Tests/Prefabs/LeftArmSkeleton.h @@ -30,7 +30,7 @@ namespace EMotionFX leftPinky2Index = 11, leftPinky3Index = 12, numJoints = 13, - INVALID = MCORE_INVALIDINDEX32 + INVALID = InvalidIndex }; PrefabLeftArmSkeleton() diff --git a/Gems/EMotionFX/Code/Tests/QuaternionParameterTests.cpp b/Gems/EMotionFX/Code/Tests/QuaternionParameterTests.cpp index db45a4a35f..a60a8eb3c8 100644 --- a/Gems/EMotionFX/Code/Tests/QuaternionParameterTests.cpp +++ b/Gems/EMotionFX/Code/Tests/QuaternionParameterTests.cpp @@ -97,7 +97,7 @@ namespace EMotionFX TEST_P(QuaternionParameterFixture, ParameterOutputsCorrectQuaternion) { // Parameter node needs to connect to another node, otherwise it will not update. - m_twoLinkIKNode->AddConnection(m_paramNode, m_paramNode->FindOutputPortIndex("quaternionTest"), BlendTreeTwoLinkIKNode::PORTID_INPUT_GOALROT); + m_twoLinkIKNode->AddConnection(m_paramNode, aznumeric_caster(m_paramNode->FindOutputPortIndex("quaternionTest")), BlendTreeTwoLinkIKNode::PORTID_INPUT_GOALROT); GetEMotionFX().Update(1.0f / 60.0f); // Check correct output for quaternion parameter. @@ -112,7 +112,7 @@ namespace EMotionFX TEST_P(QuaternionParameterFixture, QuaternionSetValueOutputsCorrectQuaternion) { - m_twoLinkIKNode->AddConnection(m_paramNode, m_paramNode->FindOutputPortIndex("quaternionTest"), BlendTreeTwoLinkIKNode::PORTID_INPUT_GOALROT); + m_twoLinkIKNode->AddConnection(m_paramNode, aznumeric_caster(m_paramNode->FindOutputPortIndex("quaternionTest")), BlendTreeTwoLinkIKNode::PORTID_INPUT_GOALROT); GetEMotionFX().Update(1.0f / 60.0f); // Shuffle the Quaternion parameter values to check changing quaternion values will be processed correctly. diff --git a/Gems/EMotionFX/Code/Tests/SimulatedObjectCommandTests.cpp b/Gems/EMotionFX/Code/Tests/SimulatedObjectCommandTests.cpp index 7337160d3f..4bac70c13d 100644 --- a/Gems/EMotionFX/Code/Tests/SimulatedObjectCommandTests.cpp +++ b/Gems/EMotionFX/Code/Tests/SimulatedObjectCommandTests.cpp @@ -32,7 +32,7 @@ namespace EMotionFX return object->GetNumSimulatedJoints(); } - size_t CountChildJoints(const Actor* actor, size_t objectIndex, AZ::u32 jointIndex) + size_t CountChildJoints(const Actor* actor, size_t objectIndex, size_t jointIndex) { const AZStd::shared_ptr& simulatedObjectSetup = actor->GetSimulatedObjectSetup(); const SimulatedObject* object = simulatedObjectSetup->GetSimulatedObject(objectIndex); @@ -55,7 +55,7 @@ namespace EMotionFX CommandSystem::CommandManager commandManager; MCore::CommandGroup commandGroup; - const AZ::u32 actorId = m_actor->GetID(); + const uint32 actorId = m_actor->GetID(); const AZStd::vector jointNames = GetTestJointNames(); // 1. Add simulated object. @@ -106,11 +106,11 @@ namespace EMotionFX // --l_ankle // --l_ball const Skeleton* skeleton = m_actor->GetSkeleton(); - const AZ::u32 l_upLegIdx = skeleton->FindNodeByName("l_upLeg")->GetNodeIndex(); - const AZ::u32 l_upLegRollIdx = skeleton->FindNodeByName("l_upLegRoll")->GetNodeIndex(); - const AZ::u32 l_loLegIdx = skeleton->FindNodeByName("l_loLeg")->GetNodeIndex(); - const AZ::u32 l_ankleIdx = skeleton->FindNodeByName("l_ankle")->GetNodeIndex(); - const AZ::u32 l_ballIdx = skeleton->FindNodeByName("l_ball")->GetNodeIndex(); + const size_t l_upLegIdx = skeleton->FindNodeByName("l_upLeg")->GetNodeIndex(); + const size_t l_upLegRollIdx = skeleton->FindNodeByName("l_upLegRoll")->GetNodeIndex(); + const size_t l_loLegIdx = skeleton->FindNodeByName("l_loLeg")->GetNodeIndex(); + const size_t l_ankleIdx = skeleton->FindNodeByName("l_ankle")->GetNodeIndex(); + const size_t l_ballIdx = skeleton->FindNodeByName("l_ball")->GetNodeIndex(); CommandSimulatedObjectHelpers::AddSimulatedJoints(actorId, {l_upLegIdx, l_upLegRollIdx, l_loLegIdx, l_ankleIdx, l_ballIdx}, 0, false, &commandGroup); EXPECT_TRUE(commandManager.ExecuteCommandGroup(commandGroup, result)); const AZStd::string serialized3_2 = SerializeSimulatedObjectSetup(m_actor.get()); @@ -172,7 +172,7 @@ namespace EMotionFX CommandSystem::CommandManager commandManager; MCore::CommandGroup commandGroup; - const AZ::u32 actorId = m_actor->GetID(); + const uint32 actorId = m_actor->GetID(); const AZStd::vector jointNames = GetTestJointNames(); // 1. Add simulated object @@ -183,8 +183,8 @@ namespace EMotionFX // 2. Add r_upLeg simulated joints const Skeleton* skeleton = m_actor->GetSkeleton(); - const AZ::u32 r_upLegIdx = skeleton->FindNodeByName("r_upLeg")->GetNodeIndex(); - const AZ::u32 r_loLegIdx = skeleton->FindNodeByName("r_loLeg")->GetNodeIndex(); + const size_t r_upLegIdx = skeleton->FindNodeByName("r_upLeg")->GetNodeIndex(); + const size_t r_loLegIdx = skeleton->FindNodeByName("r_loLeg")->GetNodeIndex(); CommandSimulatedObjectHelpers::AddSimulatedJoints(actorId, { r_upLegIdx, r_loLegIdx }, 0, false); EXPECT_EQ(2, CountSimulatedJoints(m_actor.get(), 0)); const AZStd::string serializedUpLeg = SerializeSimulatedObjectSetup(m_actor.get()); diff --git a/Gems/EMotionFX/Code/Tests/SimulatedObjectSerializeTests.cpp b/Gems/EMotionFX/Code/Tests/SimulatedObjectSerializeTests.cpp index 9ba4e4f6cb..c261f63bc1 100644 --- a/Gems/EMotionFX/Code/Tests/SimulatedObjectSerializeTests.cpp +++ b/Gems/EMotionFX/Code/Tests/SimulatedObjectSerializeTests.cpp @@ -35,7 +35,7 @@ namespace EMotionFX size_t skeletonJointIndex; const Node* skeletonJoint = skeleton->FindNodeAndIndexByName(name, skeletonJointIndex); ASSERT_NE(skeletonJoint, nullptr); - ASSERT_NE(skeletonJointIndex, MCORE_INVALIDINDEX32); + ASSERT_NE(skeletonJointIndex, InvalidIndex); SimulatedJoint* simulatedJoint = object->AddSimulatedJoint(skeletonJointIndex); simulatedJoint->SetDamping(0.1f); diff --git a/Gems/EMotionFX/Code/Tests/SkeletalLODTests.cpp b/Gems/EMotionFX/Code/Tests/SkeletalLODTests.cpp index 28f139fe39..1252eb36ae 100644 --- a/Gems/EMotionFX/Code/Tests/SkeletalLODTests.cpp +++ b/Gems/EMotionFX/Code/Tests/SkeletalLODTests.cpp @@ -26,7 +26,7 @@ namespace EMotionFX DisableJointsForLOD(m_disabledJointNames, 1); } - void DisableJointsForLOD(const std::vector& jointNames, AZ::u32 lodLevel) + void DisableJointsForLOD(const std::vector& jointNames, size_t lodLevel) { const Skeleton* skeleton = m_actor->GetSkeleton(); for (const std::string& jointName : jointNames) @@ -38,7 +38,7 @@ namespace EMotionFX } } - static void VerifySkeletalLODFlags(const ActorInstance* actorInstance, const std::vector& disabledJointNames, AZ::u32 lodLevel) + static void VerifySkeletalLODFlags(const ActorInstance* actorInstance, const std::vector& disabledJointNames, size_t lodLevel) { EXPECT_EQ(actorInstance->GetLODLevel(), lodLevel) << "Please note that setting the LOD level is delayed and happend with the next UpdateTransforms()."; @@ -47,12 +47,12 @@ namespace EMotionFX const Skeleton* skeleton = actor->GetSkeleton(); const AZStd::vector& enabledJoints = actorInstance->GetEnabledNodes(); - const AZ::u32 numEnabledJoints = enabledJoints.size(); - EXPECT_EQ(actorInstance->GetNumEnabledNodes(), actor->GetNumNodes() - static_cast(disabledJointNames.size())) + const size_t numEnabledJoints = enabledJoints.size(); + EXPECT_EQ(actorInstance->GetNumEnabledNodes(), actor->GetNumNodes() - disabledJointNames.size()) << "The enabled joints on the actor instance are not in sync with the enabledJoints."; - const AZ::u32 numJoints = skeleton->GetNumNodes(); - for (AZ::u32 i = 0; i < numJoints; ++i) + const size_t numJoints = skeleton->GetNumNodes(); + for (size_t i = 0; i < numJoints; ++i) { const Node* joint = skeleton->GetNode(i); @@ -63,7 +63,7 @@ namespace EMotionFX // Check if the enabled joints on the actor instance is in sync. bool foundInEnabledJoints = false; - for (AZ::u32 j = 0; j < numEnabledJoints; ++j) + for (size_t j = 0; j < numEnabledJoints; ++j) { const AZ::u16 enabledJointIndex = actorInstance->GetEnabledNode(j); const Node* enabledJoint = skeleton->GetNode(enabledJointIndex); diff --git a/Gems/EMotionFX/Code/Tests/UniformMotionDataTests.cpp b/Gems/EMotionFX/Code/Tests/UniformMotionDataTests.cpp index 79bb4627d0..7433a403e1 100644 --- a/Gems/EMotionFX/Code/Tests/UniformMotionDataTests.cpp +++ b/Gems/EMotionFX/Code/Tests/UniformMotionDataTests.cpp @@ -243,15 +243,15 @@ namespace EMotionFX EXPECT_FALSE(motionData.FindJointIndexByName("Blah").IsSuccess()); EXPECT_FALSE(motionData.FindMorphIndexByName("Blah").IsSuccess()); EXPECT_FALSE(motionData.FindFloatIndexByName("Blah").IsSuccess()); - EXPECT_TRUE(motionData.FindJointIndexByName("Joint1").IsSuccess()); - EXPECT_TRUE(motionData.FindJointIndexByName("Joint2").IsSuccess()); - EXPECT_TRUE(motionData.FindJointIndexByName("Joint3").IsSuccess()); - EXPECT_TRUE(motionData.FindMorphIndexByName("Morph1").IsSuccess()); - EXPECT_TRUE(motionData.FindMorphIndexByName("Morph2").IsSuccess()); - EXPECT_TRUE(motionData.FindMorphIndexByName("Morph3").IsSuccess()); - EXPECT_TRUE(motionData.FindFloatIndexByName("Float1").IsSuccess()); - EXPECT_TRUE(motionData.FindFloatIndexByName("Float2").IsSuccess()); - EXPECT_TRUE(motionData.FindFloatIndexByName("Float3").IsSuccess()); + ASSERT_TRUE(motionData.FindJointIndexByName("Joint1").IsSuccess()); + ASSERT_TRUE(motionData.FindJointIndexByName("Joint2").IsSuccess()); + ASSERT_TRUE(motionData.FindJointIndexByName("Joint3").IsSuccess()); + ASSERT_TRUE(motionData.FindMorphIndexByName("Morph1").IsSuccess()); + ASSERT_TRUE(motionData.FindMorphIndexByName("Morph2").IsSuccess()); + ASSERT_TRUE(motionData.FindMorphIndexByName("Morph3").IsSuccess()); + ASSERT_TRUE(motionData.FindFloatIndexByName("Float1").IsSuccess()); + ASSERT_TRUE(motionData.FindFloatIndexByName("Float2").IsSuccess()); + ASSERT_TRUE(motionData.FindFloatIndexByName("Float3").IsSuccess()); EXPECT_EQ(motionData.FindJointIndexByName("Joint1").GetValue(), 0); EXPECT_EQ(motionData.FindJointIndexByName("Joint2").GetValue(), 1); EXPECT_EQ(motionData.FindJointIndexByName("Joint3").GetValue(), 2); @@ -320,7 +320,7 @@ namespace EMotionFX // Test morph sampling. AZ::Outcome index = motionData.FindMorphIndexByName("Morph1"); - EXPECT_TRUE(index.IsSuccess()); + ASSERT_TRUE(index.IsSuccess()); if (index.IsSuccess()) { float result = -1.0f; @@ -352,7 +352,7 @@ namespace EMotionFX // Test float sampling. index = motionData.FindFloatIndexByName("Float1"); - EXPECT_TRUE(index.IsSuccess()); + ASSERT_TRUE(index.IsSuccess()); if (index.IsSuccess()) { float result = -1.0f; diff --git a/Gems/EMotionFX/Code/Tests/Vector3ParameterTests.cpp b/Gems/EMotionFX/Code/Tests/Vector3ParameterTests.cpp index 4dea530624..c98117abd3 100644 --- a/Gems/EMotionFX/Code/Tests/Vector3ParameterTests.cpp +++ b/Gems/EMotionFX/Code/Tests/Vector3ParameterTests.cpp @@ -71,7 +71,7 @@ namespace EMotionFX void ParamSetValue(const AZStd::string& paramName, const inputType& value) { const AZ::Outcome parameterIndex = m_animGraphInstance->FindParameterIndex(paramName); - MCore::Attribute* param = m_animGraphInstance->GetParameterValue(static_cast(parameterIndex.GetValue())); + MCore::Attribute* param = m_animGraphInstance->GetParameterValue(parameterIndex.GetValue()); paramType* typeParam = static_cast(param); typeParam->SetValue(value); } @@ -97,7 +97,7 @@ namespace EMotionFX TEST_P(Vector3ParameterFixture, ParameterOutputsCorrectVector3Floats) { // Parameter node needs to connect to another node, otherwise it will not be updated - m_twoLinkIKNode->AddConnection(m_paramNode, m_paramNode->FindOutputPortIndex("vec3Test"), BlendTreeTwoLinkIKNode::PORTID_INPUT_GOALPOS); + m_twoLinkIKNode->AddConnection(m_paramNode, aznumeric_caster(m_paramNode->FindOutputPortIndex("vec3Test")), BlendTreeTwoLinkIKNode::PORTID_INPUT_GOALPOS); GetEMotionFX().Update(1.0f / 60.0f); // Check correct output for vector3 parameter. @@ -111,7 +111,7 @@ namespace EMotionFX TEST_P(Vector3ParameterFixture, Vec3SetValueOutputsCorrectVector3Floats) { - m_twoLinkIKNode->AddConnection(m_paramNode, m_paramNode->FindOutputPortIndex("vec3Test"), BlendTreeTwoLinkIKNode::PORTID_INPUT_GOALPOS); + m_twoLinkIKNode->AddConnection(m_paramNode, aznumeric_caster(m_paramNode->FindOutputPortIndex("vec3Test")), BlendTreeTwoLinkIKNode::PORTID_INPUT_GOALPOS); GetEMotionFX().Update(1.0f / 60.0f); // Shuffle the vector3 parameter values to check changing vector3 values will be processed correctly. From 120ee641447aae95c0f65c691282c3f6e60d104d Mon Sep 17 00:00:00 2001 From: Chris Burel Date: Wed, 2 Jun 2021 16:33:36 -0700 Subject: [PATCH 206/803] Convert EMotionFX editor uint32 -> size_t Signed-off-by: Chris Burel --- .../SceneAPIExt/Rules/MetaDataRule.cpp | 8 +- .../EMotionFX/Rendering/Common/RenderUtil.cpp | 62 ++--- .../EMotionFX/Rendering/Common/RenderUtil.h | 8 +- .../Rendering/OpenGL2/Source/GLActor.cpp | 121 ++++----- .../Rendering/OpenGL2/Source/GLRenderUtil.cpp | 27 +- .../Rendering/OpenGL2/Source/GLRenderUtil.h | 2 +- .../Rendering/OpenGL2/Source/GLSLShader.cpp | 108 ++++---- .../Rendering/OpenGL2/Source/GLSLShader.h | 8 +- .../OpenGL2/Source/GraphicsManager.cpp | 5 +- .../Rendering/OpenGL2/Source/ShaderCache.cpp | 33 +-- .../OpenGL2/Source/StandardMaterial.cpp | 29 +-- .../Rendering/OpenGL2/Source/TextureCache.cpp | 63 ++--- .../Rendering/OpenGL2/Source/glactor.h | 12 +- .../AnimGraphGameControllerSettings.cpp | 33 +-- .../Source/AnimGraphGameControllerSettings.h | 4 +- .../Code/EMotionFX/Source/AnimGraphNode.cpp | 2 +- .../Code/EMotionFX/Source/EventHandler.h | 2 +- Gems/EMotionFX/Code/EMotionFX/Source/Mesh.cpp | 2 +- Gems/EMotionFX/Code/EMotionFX/Source/Mesh.h | 2 +- .../Code/EMotionFX/Source/Recorder.h | 4 +- .../EMStudioSDK/Source/Commands.cpp | 4 +- .../EMStudioSDK/Source/EMStudioManager.cpp | 8 +- .../EMStudioSDK/Source/EMStudioManager.h | 12 +- .../EMStudioSDK/Source/FileManager.cpp | 20 +- .../EMStudioSDK/Source/FileManager.h | 4 +- .../EMStudioSDK/Source/LayoutManager.cpp | 6 +- .../EMStudioSDK/Source/MainWindow.cpp | 67 +++-- .../Source/MorphTargetSelectionWindow.cpp | 4 +- .../Source/MotionSetHierarchyWidget.cpp | 18 +- .../Source/NodeHierarchyWidget.cpp | 79 ++---- .../Source/NotificationWindowManager.cpp | 14 +- .../RenderPlugin/ManipulatorCallbacks.cpp | 28 +-- .../Source/RenderPlugin/RenderPlugin.cpp | 144 ++++------- .../Source/RenderPlugin/RenderPlugin.h | 6 +- .../RenderPlugin/RenderUpdateCallback.cpp | 12 +- .../Source/RenderPlugin/RenderWidget.cpp | 42 ++-- .../Source/ResetSettingsDialog.cpp | 4 +- .../EMStudioSDK/Source/Workspace.cpp | 34 +-- .../ActionHistory/ActionHistoryCallback.cpp | 20 +- .../AnimGraph/AnimGraphActionManager.cpp | 12 +- .../Source/AnimGraph/AnimGraphEditor.cpp | 26 +- .../Source/AnimGraph/AnimGraphEditor.h | 2 +- .../Source/AnimGraph/AnimGraphModel.cpp | 42 ++-- .../AnimGraph/AnimGraphModelCallbacks.cpp | 2 +- .../Source/AnimGraph/AnimGraphPlugin.cpp | 81 +++--- .../Source/AnimGraph/AnimGraphPlugin.h | 4 +- .../Source/AnimGraph/BlendGraphViewWidget.cpp | 8 +- .../Source/AnimGraph/BlendGraphWidget.cpp | 16 +- .../Source/AnimGraph/BlendGraphWidget.h | 4 +- .../Source/AnimGraph/BlendTreeVisualNode.cpp | 28 +-- .../Source/AnimGraph/ContextMenu.cpp | 10 +- .../Source/AnimGraph/GameController.cpp | 2 +- .../Source/AnimGraph/GameController.h | 2 +- .../Source/AnimGraph/GameControllerWindow.cpp | 109 +++----- .../Source/AnimGraph/GraphNode.cpp | 236 +++++------------- .../Source/AnimGraph/GraphNode.h | 22 +- .../Source/AnimGraph/NodeConnection.cpp | 2 +- .../Source/AnimGraph/NodeConnection.h | 14 +- .../Source/AnimGraph/NodeGraph.cpp | 179 ++++++------- .../Source/AnimGraph/NodeGraph.h | 18 +- .../Source/AnimGraph/NodeGraphWidget.cpp | 39 ++- .../Source/AnimGraph/NodeGraphWidget.h | 6 +- .../Source/AnimGraph/NodeGroupWindow.cpp | 69 +++-- .../Source/AnimGraph/NodeGroupWindow.h | 4 +- .../Source/AnimGraph/ParameterWindow.cpp | 16 +- .../AnimGraph/StateFilterSelectionWindow.cpp | 6 +- .../Source/AnimGraph/StateGraphNode.cpp | 4 +- .../Source/AnimGraph/StateGraphNode.h | 6 +- .../Attachments/AttachmentNodesWindow.cpp | 35 ++- .../AttachmentsHierarchyWindow.cpp | 12 +- .../Source/Attachments/AttachmentsWindow.cpp | 60 ++--- .../Source/LogWindow/LogWindowCallback.cpp | 18 +- .../Source/LogWindow/LogWindowPlugin.cpp | 4 +- .../PhonemeSelectionWindow.cpp | 38 ++- .../PhonemeSelectionWindow.h | 4 +- .../MotionSetManagementWindow.cpp | 99 ++++---- .../MotionSetsWindow/MotionSetWindow.cpp | 100 ++++---- .../Source/MotionSetsWindow/MotionSetWindow.h | 6 +- .../MotionSetsWindowPlugin.cpp | 14 +- .../MotionWindow/MotionExtractionWindow.cpp | 12 +- .../Source/MotionWindow/MotionListWindow.cpp | 43 ++-- .../MotionWindow/MotionRetargetingWindow.cpp | 8 +- .../MotionWindow/MotionWindowPlugin.cpp | 156 +++--------- .../Source/NodeGroups/NodeGroupWidget.cpp | 7 +- .../Source/NodeGroups/NodeGroupWidget.h | 2 +- .../Source/NodeWindow/ActorInfo.cpp | 2 +- .../Source/NodeWindow/ActorInfo.h | 2 +- .../Source/NodeWindow/MeshInfo.cpp | 2 +- .../Source/NodeWindow/MeshInfo.h | 4 +- .../Source/NodeWindow/NodeInfo.cpp | 14 +- .../Source/NodeWindow/NodeWindowPlugin.h | 4 +- .../SceneManager/ActorPropertiesWindow.cpp | 12 +- .../Source/SceneManager/ActorsWindow.cpp | 75 +++--- .../Source/SceneManager/ActorsWindow.h | 2 +- .../SceneManager/SceneManagerPlugin.cpp | 8 +- .../Source/TimeView/PlaybackControlsGroup.cpp | 4 +- .../Source/TimeView/PlaybackOptionsGroup.cpp | 6 +- .../Source/TimeView/TimeTrack.cpp | 11 +- .../Source/TimeView/TimeTrack.h | 4 +- .../Source/TimeView/TimeTrackElement.cpp | 2 +- .../Source/TimeView/TimeTrackElement.h | 8 +- .../Source/TimeView/TimeViewPlugin.cpp | 205 ++++++--------- .../Source/TimeView/TimeViewPlugin.h | 10 +- .../Source/TimeView/TimeViewToolBar.cpp | 24 +- .../Source/TimeView/TrackDataWidget.cpp | 187 ++++++-------- .../Source/TimeView/TrackDataWidget.h | 6 +- .../Source/TimeView/TrackHeaderWidget.cpp | 12 +- .../Source/TimeView/TrackHeaderWidget.h | 12 +- .../Code/MysticQt/Source/DialogStack.cpp | 209 +++++++--------- .../Code/MysticQt/Source/DialogStack.h | 13 +- .../Source/KeyboardShortcutManager.cpp | 2 +- .../Source/Editor/ActorJointBrowseEdit.cpp | 4 +- .../Source/Editor/ColliderContainerWidget.cpp | 10 +- .../Ragdoll/RagdollNodeInspectorPlugin.cpp | 16 +- .../SimulatedObject/SimulatedObjectWidget.cpp | 14 +- .../Source/Editor/SimulatedObjectHelpers.cpp | 8 +- .../Source/Editor/SimulatedObjectModel.cpp | 8 +- .../Code/Source/Editor/SimulatedObjectModel.h | 2 +- .../Code/Source/Editor/SkeletonModel.cpp | 36 +-- .../Integration/Components/ActorComponent.h | 4 +- .../Components/SimpleLODComponent.cpp | 19 +- .../Components/SimpleLODComponent.h | 4 +- .../Components/EditorActorComponent.cpp | 10 +- .../Editor/Components/EditorActorComponent.h | 4 +- .../Components/EditorSimpleLODComponent.cpp | 4 +- 125 files changed, 1503 insertions(+), 2128 deletions(-) diff --git a/Gems/EMotionFX/Code/EMotionFX/Pipeline/SceneAPIExt/Rules/MetaDataRule.cpp b/Gems/EMotionFX/Code/EMotionFX/Pipeline/SceneAPIExt/Rules/MetaDataRule.cpp index 6d0daf784b..8aefdbe1ff 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Pipeline/SceneAPIExt/Rules/MetaDataRule.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Pipeline/SceneAPIExt/Rules/MetaDataRule.cpp @@ -163,10 +163,10 @@ namespace EMotionFX createMotionEventCommand->SetStartTime(commandLine.GetValueAsFloat("startTime", 0.0f)); createMotionEventCommand->SetEndTime(commandLine.GetValueAsFloat("endTime", 0.0f)); - const AZ::u32 eventTypeIndex = commandLine.FindParameterIndex("eventType"); - const AZ::u32 parametersIndex = commandLine.FindParameterIndex("parameters"); - const AZ::u32 mirrorTypeIndex = commandLine.FindParameterIndex("mirrorType"); - if (eventTypeIndex == MCORE_INVALIDINDEX32 || parametersIndex == MCORE_INVALIDINDEX32 || mirrorTypeIndex == MCORE_INVALIDINDEX32) + const size_t eventTypeIndex = commandLine.FindParameterIndex("eventType"); + const size_t parametersIndex = commandLine.FindParameterIndex("parameters"); + const size_t mirrorTypeIndex = commandLine.FindParameterIndex("mirrorType"); + if (eventTypeIndex == InvalidIndex || parametersIndex == InvalidIndex || mirrorTypeIndex == InvalidIndex) { // Note: We have noticed some bad data issue in internal assets. The parameters could contain \r\n inside of the parameter string, which would result in the mirror type missing. // Those are already been fixed in the command line object code, but we don't want to support the bad data in here by creating another loophole. Instead, we want the user to fix diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RenderUtil.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RenderUtil.cpp index 34ab2a8a69..34dba922ca 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RenderUtil.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RenderUtil.cpp @@ -314,7 +314,7 @@ namespace MCommon // render the given types of AABBs of a actor instance void RenderUtil::RenderAabbs(EMotionFX::ActorInstance* actorInstance, const AABBRenderSettings& renderSettings, bool directlyRender) { - const uint32 lodLevel = actorInstance->GetLODLevel(); + const size_t lodLevel = actorInstance->GetLODLevel(); // handle the node based AABB if (renderSettings.mNodeBasedAABB) @@ -365,19 +365,19 @@ namespace MCommon // render a simple line based skeleton - void RenderUtil::RenderSimpleSkeleton(EMotionFX::ActorInstance* actorInstance, const AZStd::unordered_set* visibleJointIndices, - const AZStd::unordered_set* selectedJointIndices, const MCore::RGBAColor& color, const MCore::RGBAColor& selectedColor, + void RenderUtil::RenderSimpleSkeleton(EMotionFX::ActorInstance* actorInstance, const AZStd::unordered_set* visibleJointIndices, + const AZStd::unordered_set* selectedJointIndices, const MCore::RGBAColor& color, const MCore::RGBAColor& selectedColor, float jointSphereRadius, bool directlyRender) { const EMotionFX::Actor* actor = actorInstance->GetActor(); const EMotionFX::Skeleton* skeleton = actor->GetSkeleton(); const EMotionFX::Pose* pose = actorInstance->GetTransformData()->GetCurrentPose(); - const uint32 numNodes = actorInstance->GetNumEnabledNodes(); - for (uint32 n = 0; n < numNodes; ++n) + const size_t numNodes = actorInstance->GetNumEnabledNodes(); + for (size_t n = 0; n < numNodes; ++n) { const EMotionFX::Node* joint = skeleton->GetNode(actorInstance->GetEnabledNode(n)); - const AZ::u32 jointIndex = joint->GetNodeIndex(); + const size_t jointIndex = joint->GetNodeIndex(); if (!visibleJointIndices || visibleJointIndices->empty() || (visibleJointIndices->find(jointIndex) != visibleJointIndices->end())) @@ -385,8 +385,8 @@ namespace MCommon const AZ::Vector3 currentJointPos = pose->GetWorldSpaceTransform(jointIndex).mPosition; const bool jointSelected = selectedJointIndices->find(jointIndex) != selectedJointIndices->end(); - const AZ::u32 parentIndex = joint->GetParentIndex(); - if (parentIndex != MCORE_INVALIDINDEX32) + const size_t parentIndex = joint->GetParentIndex(); + if (parentIndex != InvalidIndex) { const bool parentSelected = selectedJointIndices->find(parentIndex) != selectedJointIndices->end(); const AZ::Vector3 parentJointPos = pose->GetWorldSpaceTransform(parentIndex).mPosition; @@ -419,7 +419,7 @@ namespace MCommon AZ::Vector3* normals = (AZ::Vector3*)mesh->FindVertexData(EMotionFX::Mesh::ATTRIB_NORMALS); MCore::RGBAColor* vertexColors = (MCore::RGBAColor*)mesh->FindVertexData(EMotionFX::Mesh::ATTRIB_COLORS128); - const uint32 numSubMeshes = mesh->GetNumSubMeshes(); + const size_t numSubMeshes = mesh->GetNumSubMeshes(); for (uint32 subMeshIndex = 0; subMeshIndex < numSubMeshes; ++subMeshIndex) { EMotionFX::SubMesh* subMesh = mesh->GetSubMesh(subMeshIndex); @@ -481,7 +481,7 @@ namespace MCommon // render face normals if (faceNormals) { - const uint32 numSubMeshes = mesh->GetNumSubMeshes(); + const size_t numSubMeshes = mesh->GetNumSubMeshes(); for (uint32 subMeshIndex = 0; subMeshIndex < numSubMeshes; ++subMeshIndex) { EMotionFX::SubMesh* subMesh = mesh->GetSubMesh(subMeshIndex); @@ -513,7 +513,7 @@ namespace MCommon // render vertex normals if (vertexNormals) { - const uint32 numSubMeshes = mesh->GetNumSubMeshes(); + const size_t numSubMeshes = mesh->GetNumSubMeshes(); for (uint32 subMeshIndex = 0; subMeshIndex < numSubMeshes; ++subMeshIndex) { EMotionFX::SubMesh* subMesh = mesh->GetSubMesh(subMeshIndex); @@ -634,11 +634,11 @@ namespace MCommon EMotionFX::TransformData* transformData = actorInstance->GetTransformData(); const EMotionFX::Pose* pose = transformData->GetCurrentPose(); - const uint32 nodeIndex = node->GetNodeIndex(); - const uint32 parentIndex = node->GetParentIndex(); + const size_t nodeIndex = node->GetNodeIndex(); + const size_t parentIndex = node->GetParentIndex(); const AZ::Vector3 nodeWorldPos = pose->GetWorldSpaceTransform(nodeIndex).mPosition; - if (parentIndex != MCORE_INVALIDINDEX32) + if (parentIndex != InvalidIndex) { const AZ::Vector3 parentWorldPos = pose->GetWorldSpaceTransform(parentIndex).mPosition; const AZ::Vector3 bone = parentWorldPos - nodeWorldPos; @@ -653,7 +653,7 @@ namespace MCommon // render the advanced skeleton - void RenderUtil::RenderSkeleton(EMotionFX::ActorInstance* actorInstance, const AZStd::vector& boneList, const AZStd::unordered_set* visibleJointIndices, const AZStd::unordered_set* selectedJointIndices, const MCore::RGBAColor& color, const MCore::RGBAColor& selectedColor) + void RenderUtil::RenderSkeleton(EMotionFX::ActorInstance* actorInstance, const AZStd::vector& boneList, const AZStd::unordered_set* visibleJointIndices, const AZStd::unordered_set* selectedJointIndices, const MCore::RGBAColor& color, const MCore::RGBAColor& selectedColor) { // check if our render util supports rendering meshes, if not render the fallback skeleton using lines only if (GetIsMeshRenderingSupported() == false) @@ -715,7 +715,7 @@ namespace MCommon // render node orientations - void RenderUtil::RenderNodeOrientations(EMotionFX::ActorInstance* actorInstance, const AZStd::vector& boneList, const AZStd::unordered_set* visibleJointIndices, const AZStd::unordered_set* selectedJointIndices, float scale, bool scaleBonesOnLength) + void RenderUtil::RenderNodeOrientations(EMotionFX::ActorInstance* actorInstance, const AZStd::vector& boneList, const AZStd::unordered_set* visibleJointIndices, const AZStd::unordered_set* selectedJointIndices, float scale, bool scaleBonesOnLength) { // get the actor and the transform data const float unitScale = 1.0f / (float)MCore::Distance::ConvertValue(1.0f, MCore::Distance::UNITTYPE_METERS, EMotionFX::GetEMotionFX().GetUnitType()); @@ -775,11 +775,11 @@ namespace MCommon AxisRenderingSettings axisRenderingSettings; // iterate through all enabled nodes - const uint32 numEnabled = actorInstance->GetNumEnabledNodes(); - for (uint32 i = 0; i < numEnabled; ++i) + const size_t numEnabled = actorInstance->GetNumEnabledNodes(); + for (size_t i = 0; i < numEnabled; ++i) { EMotionFX::Node* node = skeleton->GetNode(actorInstance->GetEnabledNode(i)); - const uint32 nodeIndex = node->GetNodeIndex(); + const size_t nodeIndex = node->GetNodeIndex(); // render node orientation const EMotionFX::Transform worldTransform = pose->GetWorldSpaceTransform(nodeIndex); @@ -789,8 +789,8 @@ namespace MCommon // skip root nodes for the line based skeleton rendering, you could also use curNode->IsRootNode() // but we use the parent index here, as we will reuse it - uint32 parentIndex = node->GetParentIndex(); - if (parentIndex != MCORE_INVALIDINDEX32) + size_t parentIndex = node->GetParentIndex(); + if (parentIndex != InvalidIndex) { const AZ::Vector3 endPos = pose->GetWorldSpaceTransform(parentIndex).mPosition; RenderLine(worldTransform.mPosition, endPos, color); @@ -1582,8 +1582,8 @@ namespace MCommon AZ::Aabb finalAABB = AZ::Aabb::CreateNull(); // get the number of actor instances and iterate through them - const uint32 numActorInstances = EMotionFX::GetActorManager().GetNumActorInstances(); - for (uint32 i = 0; i < numActorInstances; ++i) + const size_t numActorInstances = EMotionFX::GetActorManager().GetNumActorInstances(); + for (size_t i = 0; i < numActorInstances; ++i) { // get the actor instance and update its transformations and meshes EMotionFX::ActorInstance* actorInstance = EMotionFX::GetActorManager().GetActorInstance(i); @@ -1673,10 +1673,10 @@ namespace MCommon void RenderUtil::RenderTrajectory(EMotionFX::ActorInstance* actorInstance, const MCore::RGBAColor& innerColor, const MCore::RGBAColor& borderColor, float scale) { EMotionFX::Actor* actor = actorInstance->GetActor(); - const uint32 nodeIndex = actor->GetMotionExtractionNodeIndex(); + const size_t nodeIndex = actor->GetMotionExtractionNodeIndex(); // in case the motion extraction node is not set, return directly - if (nodeIndex == MCORE_INVALIDINDEX32) + if (nodeIndex == InvalidIndex) { return; } @@ -1710,7 +1710,7 @@ namespace MCommon // fast access to the trajectory trace particles const AZStd::vector& traceParticles = trajectoryPath->mTraceParticles; - const int32 numTraceParticles = traceParticles.size(); + const size_t numTraceParticles = traceParticles.size(); if (traceParticles.empty()) { return; @@ -1781,7 +1781,7 @@ namespace MCommon MCore::RGBAColor color = innerColor; // render the path from the arrow head towards the tail - for (int32 i = numTraceParticles - 1; i > 0; i--) + for (size_t i = numTraceParticles - 1; i > 0; i--) { // calculate the normalized distance to the head, this value also represents the alpha value as it fades away while getting closer to the end float normalizedDistance = (float)i / numTraceParticles; @@ -1883,18 +1883,18 @@ namespace MCommon // render node names for all enabled nodes - void RenderUtil::RenderNodeNames(EMotionFX::ActorInstance* actorInstance, Camera* camera, uint32 screenWidth, uint32 screenHeight, const MCore::RGBAColor& color, const MCore::RGBAColor& selectedColor, const AZStd::unordered_set& visibleJointIndices, const AZStd::unordered_set& selectedJointIndices) + void RenderUtil::RenderNodeNames(EMotionFX::ActorInstance* actorInstance, Camera* camera, uint32 screenWidth, uint32 screenHeight, const MCore::RGBAColor& color, const MCore::RGBAColor& selectedColor, const AZStd::unordered_set& visibleJointIndices, const AZStd::unordered_set& selectedJointIndices) { const EMotionFX::Actor* actor = actorInstance->GetActor(); const EMotionFX::Skeleton* skeleton = actor->GetSkeleton(); const EMotionFX::TransformData* transformData = actorInstance->GetTransformData(); const EMotionFX::Pose* pose = transformData->GetCurrentPose(); - const AZ::u32 numEnabledNodes = actorInstance->GetNumEnabledNodes(); + const size_t numEnabledNodes = actorInstance->GetNumEnabledNodes(); - for (uint32 i = 0; i < numEnabledNodes; ++i) + for (size_t i = 0; i < numEnabledNodes; ++i) { const EMotionFX::Node* joint = skeleton->GetNode(actorInstance->GetEnabledNode(i)); - const AZ::u32 jointIndex = joint->GetNodeIndex(); + const size_t jointIndex = joint->GetNodeIndex(); const AZ::Vector3 worldPos = pose->GetWorldSpaceTransform(jointIndex).mPosition; // check if the current enabled node is along the visible nodes and render it if that is the case diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RenderUtil.h b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RenderUtil.h index d62816fa65..6e870c870e 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RenderUtil.h +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RenderUtil.h @@ -177,7 +177,7 @@ namespace MCommon * @param[in] directlyRender Will call the RenderLines() function internally in case it is set to true. If false * you have to make sure to call RenderLines() manually at the end of your custom render frame function. */ - void RenderSimpleSkeleton(EMotionFX::ActorInstance* actorInstance, const AZStd::unordered_set* visibleJointIndices = nullptr, const AZStd::unordered_set* selectedJointIndices = nullptr, + void RenderSimpleSkeleton(EMotionFX::ActorInstance* actorInstance, const AZStd::unordered_set* visibleJointIndices = nullptr, const AZStd::unordered_set* selectedJointIndices = nullptr, const MCore::RGBAColor& color = MCore::RGBAColor(1.0f, 1.0f, 0.0f, 1.0f), const MCore::RGBAColor& selectedColor = MCore::RGBAColor(1.0f, 0.647f, 0.0f), float jointSphereRadius = 0.1f, bool directlyRender = false); @@ -191,7 +191,7 @@ namespace MCommon * @param[in] color The desired skeleton color. * @param[in] selectedColor The color of the selected bones. */ - void RenderSkeleton(EMotionFX::ActorInstance* actorInstance, const AZStd::vector& boneList, const AZStd::unordered_set* visibleJointIndices = nullptr, const AZStd::unordered_set* selectedJointIndices = nullptr, const MCore::RGBAColor& color = MCore::RGBAColor(1.0f, 0.0f, 0.0f, 1.0f), const MCore::RGBAColor& selectedColor = MCore::RGBAColor(1.0f, 0.647f, 0.0f)); + void RenderSkeleton(EMotionFX::ActorInstance* actorInstance, const AZStd::vector& boneList, const AZStd::unordered_set* visibleJointIndices = nullptr, const AZStd::unordered_set* selectedJointIndices = nullptr, const MCore::RGBAColor& color = MCore::RGBAColor(1.0f, 0.0f, 0.0f, 1.0f), const MCore::RGBAColor& selectedColor = MCore::RGBAColor(1.0f, 0.647f, 0.0f)); /** * Render node orientations. @@ -202,7 +202,7 @@ namespace MCommon * @param[in] scale The scaling value in units. Axes of normal nodes will use the scaling value as unit length, skinned bones will use the scaling value as multiplier. * @param[in] scaleBonesOnLength Automatically scales the bone orientations based on the bone length. This means finger node orientations will be rendered smaller than foot bones as the bone length is a lot smaller as well. */ - void RenderNodeOrientations(EMotionFX::ActorInstance* actorInstance, const AZStd::vector& boneList, const AZStd::unordered_set* visibleJointIndices = nullptr, const AZStd::unordered_set* selectedJointIndices = nullptr, float scale = 1.0f, bool scaleBonesOnLength = true); + void RenderNodeOrientations(EMotionFX::ActorInstance* actorInstance, const AZStd::vector& boneList, const AZStd::unordered_set* visibleJointIndices = nullptr, const AZStd::unordered_set* selectedJointIndices = nullptr, float scale = 1.0f, bool scaleBonesOnLength = true); /** * Render the bind pose of the given actor. @@ -224,7 +224,7 @@ namespace MCommon * @param[in] visibleJointIndices List of visible joint indices. nullptr in case all joints should be rendered. * @param[in] selectedJointIndices List of selected joint indices. nullptr in case selection should not be considered. */ - void RenderNodeNames(EMotionFX::ActorInstance* actorInstance, MCommon::Camera* camera, uint32 screenWidth, uint32 screenHeight, const MCore::RGBAColor& color, const MCore::RGBAColor& selectedColor, const AZStd::unordered_set& visibleJointIndices, const AZStd::unordered_set& selectedJointIndices); + void RenderNodeNames(EMotionFX::ActorInstance* actorInstance, MCommon::Camera* camera, uint32 screenWidth, uint32 screenHeight, const MCore::RGBAColor& color, const MCore::RGBAColor& selectedColor, const AZStd::unordered_set& visibleJointIndices, const AZStd::unordered_set& selectedJointIndices); /** * Render a sphere. diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLActor.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLActor.cpp index 5a7d2032a7..f7f21629a3 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLActor.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLActor.cpp @@ -56,42 +56,36 @@ namespace RenderGL // get rid of the allocated memory void GLActor::Cleanup() { - uint32 i; - // get rid of all index and vertex buffers - for (uint32 a = 0; a < 3; ++a) + for (AZStd::vector& vertexBuffers : mVertexBuffers) { - // get rid of the given vertex buffers - const uint32 numVertexBuffers = mVertexBuffers[a].size(); - for (i = 0; i < numVertexBuffers; ++i) + for (VertexBuffer* vertexBuffer : vertexBuffers) { - delete mVertexBuffers[a][i]; + delete vertexBuffer; } - - // get rid of the given index buffers - const uint32 numIndexBuffers = mIndexBuffers[a].size(); - for (i = 0; i < numIndexBuffers; ++i) + } + for (AZStd::vector& indexBuffers : mIndexBuffers) + { + for (IndexBuffer* indexBuffer : indexBuffers) { - delete mIndexBuffers[a][i]; + delete indexBuffer; } } // delete all materials - const uint32 numLOD = mMaterials.size(); - for (uint32 l = 0; l < numLOD; l++) + for (AZStd::vector& materialsPerLod : mMaterials) { - const uint32 numMaterials = mMaterials[l].size(); - for (uint32 n = 0; n < numMaterials; n++) + for (MaterialPrimitives* materialPrimitives : materialsPerLod) { - delete mMaterials[l][n]->mMaterial; - delete mMaterials[l][n]; + delete materialPrimitives->mMaterial; + delete materialPrimitives; } } } // customize the classify mesh type function - EMotionFX::Mesh::EMeshType GLActor::ClassifyMeshType(EMotionFX::Node* node, EMotionFX::Mesh* mesh, uint32 lodLevel) + EMotionFX::Mesh::EMeshType GLActor::ClassifyMeshType(EMotionFX::Node* node, EMotionFX::Mesh* mesh, size_t lodLevel) { MCORE_ASSERT(node && mesh); return mesh->ClassifyMeshType(lodLevel, mActor, node->GetNodeIndex(), !mEnableGPUSkinning, 4, 200); @@ -120,18 +114,19 @@ namespace RenderGL mMaterials.resize(numGeometryLODLevels); // resize the vertex and index buffers - for (uint32 a = 0; a < 3; ++a) + for (AZStd::vector& vertexBuffers : mVertexBuffers) { - mVertexBuffers[a].resize(numGeometryLODLevels); - mIndexBuffers[a].resize(numGeometryLODLevels); - mPrimitives[a].Resize(numGeometryLODLevels); - - // reset the vertex and index buffers - for (uint32 n = 0; n < numGeometryLODLevels; ++n) - { - mVertexBuffers[a][n] = nullptr; - mIndexBuffers [a][n] = nullptr; - } + vertexBuffers.resize(numGeometryLODLevels); + AZStd::fill(begin(vertexBuffers), end(vertexBuffers), nullptr); + } + for (AZStd::vector& indexBuffers : mIndexBuffers) + { + indexBuffers.resize(numGeometryLODLevels); + AZStd::fill(begin(indexBuffers), end(indexBuffers), nullptr); + } + for (MCore::Array2D& primitives : mPrimitives) + { + primitives.Resize(numGeometryLODLevels); } mHomoMaterials.resize(numGeometryLODLevels); @@ -140,7 +135,7 @@ namespace RenderGL EMotionFX::Skeleton* skeleton = actor->GetSkeleton(); // iterate through the lod levels - for (uint32 lodLevel = 0; lodLevel < numGeometryLODLevels; ++lodLevel) + for (size_t lodLevel = 0; lodLevel < numGeometryLODLevels; ++lodLevel) { InitMaterials(lodLevel); @@ -172,7 +167,7 @@ namespace RenderGL // get the number of submeshes and iterate through them const size_t numSubMeshes = mesh->GetNumSubMeshes(); - for (uint32 s = 0; s < numSubMeshes; ++s) + for (size_t s = 0; s < numSubMeshes; ++s) { // get the current submesh EMotionFX::SubMesh* subMesh = mesh->GetSubMesh(s); @@ -212,7 +207,7 @@ namespace RenderGL } // create the dynamic vertex buffers - const uint32 numDynamicBytes = sizeof(StandardVertex) * totalNumVerts[EMotionFX::Mesh::MESHTYPE_CPU_DEFORMED]; + const size_t numDynamicBytes = sizeof(StandardVertex) * totalNumVerts[EMotionFX::Mesh::MESHTYPE_CPU_DEFORMED]; if (numDynamicBytes > 0) { mVertexBuffers[EMotionFX::Mesh::MESHTYPE_CPU_DEFORMED][lodLevel] = new VertexBuffer(); @@ -230,7 +225,7 @@ namespace RenderGL } // create the static vertex buffers - const uint32 numStaticBytes = sizeof(StandardVertex) * totalNumVerts[EMotionFX::Mesh::MESHTYPE_STATIC]; + const size_t numStaticBytes = sizeof(StandardVertex) * totalNumVerts[EMotionFX::Mesh::MESHTYPE_STATIC]; if (numStaticBytes > 0) { mVertexBuffers[EMotionFX::Mesh::MESHTYPE_STATIC][lodLevel] = new VertexBuffer(); @@ -248,7 +243,7 @@ namespace RenderGL } // create the skinned vertex buffers - const uint32 numSkinnedBytes = sizeof(SkinnedVertex) * totalNumVerts[EMotionFX::Mesh::MESHTYPE_GPU_DEFORMED]; + const size_t numSkinnedBytes = sizeof(SkinnedVertex) * totalNumVerts[EMotionFX::Mesh::MESHTYPE_GPU_DEFORMED]; if (numSkinnedBytes > 0) { mVertexBuffers[EMotionFX::Mesh::MESHTYPE_GPU_DEFORMED][lodLevel] = new VertexBuffer(); @@ -275,7 +270,7 @@ namespace RenderGL if (gpuSkinning) { // iterate through all geometry LOD levels - for (uint32 lodLevel = 0; lodLevel < numGeometryLODLevels; ++lodLevel) + for (size_t lodLevel = 0; lodLevel < numGeometryLODLevels; ++lodLevel) { // iterate through all nodes for (size_t n = 0; n < numNodes; ++n) @@ -312,8 +307,8 @@ namespace RenderGL EMotionFX::MeshDeformerStack* stack = actor->GetMeshDeformerStack(lodLevel, n); if (stack) { - const uint32 numDeformers = stack->GetNumDeformers(); - for (uint32 d=0; dGetNumDeformers(); + for (size_t d=0; dGetDeformer(d); deformer->SetIsEnabled(false); @@ -356,11 +351,11 @@ namespace RenderGL // initialize materials - void GLActor::InitMaterials(uint32 lodLevel) + void GLActor::InitMaterials(size_t lodLevel) { // get the number of materials and iterate through them - const uint32 numMaterials = mActor->GetNumMaterials(lodLevel); - for (uint32 m = 0; m < numMaterials; ++m) + const size_t numMaterials = mActor->GetNumMaterials(lodLevel); + for (size_t m = 0; m < numMaterials; ++m) { EMotionFX::Material* emfxMaterial = mActor->GetMaterial(lodLevel, m); Material* material = InitMaterial(emfxMaterial); @@ -402,8 +397,8 @@ namespace RenderGL // render meshes of the given type void GLActor::RenderMeshes(EMotionFX::ActorInstance* actorInstance, EMotionFX::Mesh::EMeshType meshType, uint32 renderFlags) { - const uint32 lodLevel = actorInstance->GetLODLevel(); - const uint32 numMaterials = mMaterials[lodLevel].size(); + const size_t lodLevel = actorInstance->GetLODLevel(); + const size_t numMaterials = mMaterials[lodLevel].size(); if (numMaterials == 0) { @@ -425,11 +420,9 @@ namespace RenderGL mIndexBuffers[meshType][lodLevel]->Activate(); // render all the primitives in each material - for (uint32 n = 0; n < numMaterials; n++) + for (const MaterialPrimitives* materialPrims : mMaterials[lodLevel]) { - const MaterialPrimitives* materialPrims = mMaterials[lodLevel][n]; - const uint32 numPrimitives = materialPrims->mPrimitives[meshType].size(); - if (numPrimitives == 0) + if (materialPrims->mPrimitives[meshType].empty()) { continue; } @@ -450,9 +443,9 @@ namespace RenderGL material->Activate(activationFlags); // render all primitives - for (uint32 i = 0; i < numPrimitives; ++i) + for (const Primitive& primitive : materialPrims->mPrimitives[meshType]) { - material->Render(actorInstance, &materialPrims->mPrimitives[meshType][i]); + material->Render(actorInstance, &primitive); } material->Deactivate(); @@ -464,7 +457,7 @@ namespace RenderGL void GLActor::UpdateDynamicVertices(EMotionFX::ActorInstance* actorInstance) { // get the number of dynamic nodes - const uint32 lodLevel = actorInstance->GetLODLevel(); + const size_t lodLevel = actorInstance->GetLODLevel(); const size_t numNodes = mDynamicNodes.GetNumElements(lodLevel); if (numNodes == 0) { @@ -491,7 +484,7 @@ namespace RenderGL { // get the node and its mesh const size_t nodeIndex = mDynamicNodes.GetElement(lodLevel, n); - EMotionFX::Mesh* mesh = mActor->GetMesh(lodLevel, aznumeric_cast(nodeIndex)); + EMotionFX::Mesh* mesh = mActor->GetMesh(lodLevel, nodeIndex); // is the mesh valid? if (mesh == nullptr) @@ -536,7 +529,7 @@ namespace RenderGL // fill the index buffers with data - void GLActor::FillIndexBuffers(uint32 lodLevel) + void GLActor::FillIndexBuffers(size_t lodLevel) { // initialize the index buffers uint32* staticIndices = nullptr; @@ -597,7 +590,6 @@ namespace RenderGL } // get the mesh type and the indices - //const uint32 numIndices = mesh->GetNumIndices(); uint32* indices = mesh->GetIndices(); uint8* vertCounts = mesh->GetPolygonVertexCounts(); EMotionFX::Mesh::EMeshType meshType = ClassifyMeshType(node, mesh, lodLevel); @@ -621,9 +613,6 @@ namespace RenderGL polyStartIndex += numPolyVerts; } - //for (uint32 i=0; iGetNumVertices(); break; } @@ -644,10 +633,6 @@ namespace RenderGL polyStartIndex += numPolyVerts; } - // fill in static index buffers - //for (uint32 i=0; iGetNumVertices(); break; } @@ -668,10 +653,6 @@ namespace RenderGL polyStartIndex += numPolyVerts; } - // fill in gpu skinned index buffers - //for (uint32 i=0; iGetNumVertices(); break; } @@ -695,7 +676,7 @@ namespace RenderGL // fill the static vertex buffer - void GLActor::FillStaticVertexBuffers(uint32 lodLevel) + void GLActor::FillStaticVertexBuffers(size_t lodLevel) { if (mVertexBuffers[EMotionFX::Mesh::MESHTYPE_STATIC][lodLevel] == nullptr) { @@ -785,7 +766,7 @@ namespace RenderGL // fill the GPU skinned vertex buffer - void GLActor::FillGPUSkinnedVertexBuffers(uint32 lodLevel) + void GLActor::FillGPUSkinnedVertexBuffers(size_t lodLevel) { if (mVertexBuffers[EMotionFX::Mesh::MESHTYPE_GPU_DEFORMED][lodLevel] == nullptr) { @@ -849,8 +830,8 @@ namespace RenderGL assert(skinningInfo); // get the number of submeshes and iterate through them - const uint32 numSubMeshes = mesh->GetNumSubMeshes(); - for (uint32 s = 0; s < numSubMeshes; ++s) + const size_t numSubMeshes = mesh->GetNumSubMeshes(); + for (size_t s = 0; s < numSubMeshes; ++s) { // get the current submesh and the start vertex EMotionFX::SubMesh* subMesh = mesh->GetSubMesh(s); @@ -877,9 +858,9 @@ namespace RenderGL // get the influence and its weight and set the indices EMotionFX::SkinInfluence* influence = skinningInfo->GetInfluence(orgVertex, i); skinnedVertices[globalVert].mWeights[i] = influence->GetWeight(); - const uint32 boneIndex = subMesh->FindBoneIndex(influence->GetNodeNr()); + const size_t boneIndex = subMesh->FindBoneIndex(influence->GetNodeNr()); skinnedVertices[globalVert].mBoneIndices[i] = static_cast(boneIndex); - MCORE_ASSERT(boneIndex != MCORE_INVALIDINDEX32); + MCORE_ASSERT(boneIndex != InvalidIndex); } // reset remaining weights and offsets diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLRenderUtil.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLRenderUtil.cpp index 2ef39bd7c5..c67ec180ed 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLRenderUtil.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLRenderUtil.cpp @@ -37,16 +37,11 @@ namespace RenderGL mCurrentLineVB = 0; - for (uint32 i = 0; i < MAX_LINE_VERTEXBUFFERS; ++i) - { - mLineVertexBuffers[i] = nullptr; - } - // initialize the vertex buffers and the shader used for line rendering - for (uint32 i = 0; i < MAX_LINE_VERTEXBUFFERS; ++i) + for (VertexBuffer*& lineVertexBuffer : mLineVertexBuffers) { - mLineVertexBuffers[i] = new VertexBuffer(); - if (mLineVertexBuffers[i]->Init(sizeof(LineVertex), mNumMaxLineVertices, USAGE_DYNAMIC) == false) + lineVertexBuffer = new VertexBuffer(); + if (lineVertexBuffer->Init(sizeof(LineVertex), mNumMaxLineVertices, USAGE_DYNAMIC) == false) { MCore::LogError("[OpenGL] Failed to create render utility line vertex buffer."); CleanUp(); @@ -139,10 +134,10 @@ namespace RenderGL // destroy the allocated memory void GLRenderUtil::CleanUp() { - for (uint32 i = 0; i < MAX_LINE_VERTEXBUFFERS; ++i) + for (VertexBuffer*& lineVertexBuffer : mLineVertexBuffers) { - delete mLineVertexBuffers[i]; - mLineVertexBuffers[i] = nullptr; + delete lineVertexBuffer; + lineVertexBuffer = nullptr; } delete mMeshVertexBuffer; @@ -163,10 +158,9 @@ namespace RenderGL delete[] mTextures; // get rid of texture entries - const uint32 numTextEntries = mTextEntries.size(); - for (uint32 i = 0; i < numTextEntries; ++i) + for (TextEntry* mTextEntrie : mTextEntries) { - delete mTextEntries[i]; + delete mTextEntrie; } mTextEntries.clear(); } @@ -244,9 +238,6 @@ namespace RenderGL glPopAttrib(); - //const float renderTime = time.GetTime(); - //LOG("numTextures=%i, renderTime=%.3fms", mNumTextures, renderTime*1000); - mNumTextures = 0; } @@ -491,7 +482,7 @@ namespace RenderGL glDisable(GL_CULL_FACE); // get the number of vertices to render - const uint32 numVertices = triangleVertices.size(); + const uint32 numVertices = aznumeric_caster(triangleVertices.size()); MCORE_ASSERT(numVertices <= mNumMaxTriangleVertices); // lock the vertex buffer diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLRenderUtil.h b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLRenderUtil.h index 672a8c524f..0f323ab00c 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLRenderUtil.h +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLRenderUtil.h @@ -74,7 +74,7 @@ namespace RenderGL #define MAX_LINE_VERTEXBUFFERS 2 GraphicsManager* mGraphicsManager; - VertexBuffer* mLineVertexBuffers[MAX_LINE_VERTEXBUFFERS]; + VertexBuffer* mLineVertexBuffers[MAX_LINE_VERTEXBUFFERS]{}; uint16 mCurrentLineVB; GLSLShader* mLineShader; GLSLShader* mMeshShader; diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLSLShader.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLSLShader.cpp index 451246a8e2..b1a5c4699d 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLSLShader.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLSLShader.cpp @@ -6,6 +6,7 @@ * */ +#include #include #include #include "GLSLShader.h" @@ -65,17 +66,13 @@ namespace RenderGL // Deactivate void GLSLShader::Deactivate() { - const uint32 numAttribs = mActivatedAttribs.size(); - for (uint32 i = 0; i < numAttribs; ++i) + for (const size_t index : mActivatedAttribs) { - const uint32 index = mActivatedAttribs[i]; glDisableVertexAttribArray(mAttributes[index].mLocation); } - const uint32 numTextures = mActivatedTextures.size(); - for (uint32 i = 0; i < numTextures; ++i) + for (const size_t index : mActivatedTextures) { - const uint32 index = mActivatedTextures[i]; assert(mUniforms[index].mType == GL_SAMPLER_2D); glActiveTexture(GL_TEXTURE0 + mUniforms[index].mTextureUnit); glBindTexture(GL_TEXTURE_2D, 0); @@ -124,10 +121,9 @@ namespace RenderGL text = "#version 120\n"; // build define string - const uint32 numDefines = mDefines.size(); - for (uint32 n = 0; n < numDefines; ++n) + for (const AZStd::string& define : mDefines) { - text += AZStd::string::format("#define %s\n", mDefines[n].c_str()); + text += AZStd::string::format("#define %s\n", define.c_str()); } // read file into a big string @@ -175,20 +171,16 @@ namespace RenderGL AZStd::invoke(func, static_cast(this), object, logLen, &logWritten, text.data()); // if there are any defines, print that out too - if (mDefines.size() > 0) + if (!mDefines.empty()) { AZStd::string dStr; - const uint32 numDefines = mDefines.size(); - for (uint32 n = 0; n < numDefines; ++n) + for (const AZStd::string& define : mDefines) { - if (n < numDefines - 1) + if (!dStr.empty()) { - dStr += mDefines[n] + " "; - } - else - { - dStr += mDefines[n]; + dStr.append(" "); } + dStr.append(define); } MCore::LogDetailedInfo("[GLSL] Compiling shader '%s', with defines %s", mFileName.c_str(), dStr.c_str()); @@ -260,8 +252,8 @@ namespace RenderGL // FindAttribute GLSLShader::ShaderParameter* GLSLShader::FindAttribute(const char* name) { - const uint32 index = FindAttributeIndex(name); - if (index == MCORE_INVALIDINDEX32) + const size_t index = FindAttributeIndex(name); + if (index == InvalidIndex) { return nullptr; } @@ -273,20 +265,16 @@ namespace RenderGL // FindAttributeIndex size_t GLSLShader::FindAttributeIndex(const char* name) { - const uint32 numAttribs = mAttributes.size(); - for (uint32 i = 0; i < numAttribs; ++i) + const auto foundAttribute = AZStd::find_if(begin(mAttributes), end(mAttributes), [name](const auto& attribute) { - if (AzFramework::StringFunc::Equal(mAttributes[i].mName.c_str(), name, false /* no case */)) - { + return AzFramework::StringFunc::Equal(attribute.mName.c_str(), name, false /* no case */) && // if we don't have a valid parameter location, an attribute by this name doesn't exist // we just cached the fact that it doesn't exist, instead of failing glGetAttribLocation every time - if (mAttributes[i].mLocation >= 0) - { - return i; - } - - return MCORE_INVALIDINDEX32; - } + attribute.mLocation >= 0; + }); + if (foundAttribute != end(mAttributes)) + { + return AZStd::distance(begin(mAttributes), foundAttribute); } // the parameter wasn't cached, try to retrieve it @@ -295,7 +283,7 @@ namespace RenderGL if (loc < 0) { - return MCORE_INVALIDINDEX32; + return InvalidIndex; } return mAttributes.size() - 1; @@ -303,12 +291,12 @@ namespace RenderGL // FindAttributeLocation - uint32 GLSLShader::FindAttributeLocation(const char* name) + size_t GLSLShader::FindAttributeLocation(const char* name) { ShaderParameter* p = FindAttribute(name); if (p == nullptr) { - return MCORE_INVALIDINDEX32; + return InvalidIndex; } return p->mLocation; @@ -318,8 +306,8 @@ namespace RenderGL // FindUniform GLSLShader::ShaderParameter* GLSLShader::FindUniform(const char* name) { - const uint32 index = FindUniformIndex(name); - if (index == MCORE_INVALIDINDEX32) + const size_t index = FindUniformIndex(name); + if (index == InvalidIndex) { return nullptr; } @@ -331,18 +319,14 @@ namespace RenderGL // FindUniformIndex size_t GLSLShader::FindUniformIndex(const char* name) { - const uint32 numUniforms = mUniforms.size(); - for (uint32 i = 0; i < numUniforms; ++i) + const auto foundUniform = AZStd::find_if(begin(mUniforms), end(mUniforms), [name](const auto& uniform) { - if (AzFramework::StringFunc::Equal(mUniforms[i].mName.c_str(), name, false /* no case */)) - { - if (mUniforms[i].mLocation >= 0) - { - return i; - } - - return MCORE_INVALIDINDEX32; - } + return AzFramework::StringFunc::Equal(uniform.mName.c_str(), name, false /* no case */) && + uniform.mLocation >= 0; + }); + if (foundUniform != end(mUniforms)) + { + return AZStd::distance(begin(mUniforms), foundUniform); } // the parameter wasn't cached, try to retrieve it @@ -351,7 +335,7 @@ namespace RenderGL if (loc < 0) { - return MCORE_INVALIDINDEX32; + return InvalidIndex; } return mUniforms.size() - 1; @@ -361,8 +345,8 @@ namespace RenderGL // SetAttribute void GLSLShader::SetAttribute(const char* name, uint32 dim, uint32 type, uint32 stride, size_t offset) { - const uint32 index = FindAttributeIndex(name); - if (index == MCORE_INVALIDINDEX32) + const size_t index = FindAttributeIndex(name); + if (index == InvalidIndex) { return; } @@ -503,8 +487,8 @@ namespace RenderGL // SetUniform void GLSLShader::SetUniform(const char* name, Texture* texture) { - const uint32 index = FindUniformIndex(name); - if (index == MCORE_INVALIDINDEX32) + const size_t index = FindUniformIndex(name); + if (index == InvalidIndex) { return; } @@ -534,8 +518,8 @@ namespace RenderGL // link a texture to a given uniform void GLSLShader::SetUniformTextureID(const char* name, uint32 textureID) { - const uint32 index = FindUniformIndex(name); - if (index == MCORE_INVALIDINDEX32) + const size_t index = FindUniformIndex(name); + if (index == InvalidIndex) { return; } @@ -563,20 +547,12 @@ namespace RenderGL // check if the given attribute string is defined in the shader - bool GLSLShader::CheckIfIsDefined(const char* attributeName) + bool GLSLShader::CheckIfIsDefined(const char* attributeName) const { // get the number of defines and iterate through them - const uint32 numDefines = mDefines.size(); - for (uint32 i = 0; i < numDefines; ++i) + return AZStd::any_of(begin(mDefines), end(mDefines), [attributeName](const AZStd::string& define) { - // compare the given attribute with the current define and return if they are equal - if (AzFramework::StringFunc::Equal(mDefines[i].c_str(), attributeName, false /* no case */)) - { - return true; - } - } - - // we haven't found the attribute, return failure - return false; + return AzFramework::StringFunc::Equal(define.c_str(), attributeName, false /* no case */); + }); } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLSLShader.h b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLSLShader.h index 6eb77b69c2..0db7948e8f 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLSLShader.h +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLSLShader.h @@ -36,11 +36,11 @@ namespace RenderGL void Deactivate() override; bool Validate() override; - uint32 FindAttributeLocation(const char* name); + size_t FindAttributeLocation(const char* name); uint32 GetType() const override; MCORE_INLINE unsigned int GetProgram() const { return mProgram; } - bool CheckIfIsDefined(const char* attributeName); + bool CheckIfIsDefined(const char* attributeName) const; bool Init(AZ::IO::PathView vertexFileName, AZ::IO::PathView pixelFileName, AZStd::vector& defines); void SetAttribute(const char* name, uint32 dim, uint32 type, uint32 stride, size_t offset) override; @@ -84,8 +84,8 @@ namespace RenderGL AZ::IO::Path mFileName; - AZStd::vector mActivatedAttribs; - AZStd::vector mActivatedTextures; + AZStd::vector mActivatedAttribs; + AZStd::vector mActivatedTextures; AZStd::vector mUniforms; AZStd::vector mAttributes; AZStd::vector mDefines; diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GraphicsManager.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GraphicsManager.cpp index 78b5813770..4802477e08 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GraphicsManager.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GraphicsManager.cpp @@ -416,10 +416,9 @@ namespace RenderGL // construct the lookup string for the shader cache AZStd::string cacheLookupStr = vertexPath.Native() + pixelPath.Native(); - const uint32 numDefines = defines.size(); - for (uint32 n = 0; n < numDefines; n++) + for (const AZStd::string& define : defines) { - cacheLookupStr += AZStd::string::format("#%s", defines[n].c_str()); + cacheLookupStr += AZStd::string::format("#%s", define.c_str()); } // check if the shader is already in the cache diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/ShaderCache.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/ShaderCache.cpp index 26acd0e77d..b02ab99505 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/ShaderCache.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/ShaderCache.cpp @@ -30,11 +30,10 @@ namespace RenderGL void ShaderCache::Release() { // delete all shaders - const uint32 numEntries = mEntries.size(); - for (uint32 i = 0; i < numEntries; ++i) + for (Entry& entry : mEntries) { - mEntries[i].mName.clear(); - delete mEntries[i].mShader; + entry.mName.clear(); + delete entry.mShader; } // clear all entries @@ -52,32 +51,20 @@ namespace RenderGL // try to locate a shader based on its name Shader* ShaderCache::FindShader(AZStd::string_view filename) const { - const uint32 numEntries = mEntries.size(); - for (uint32 i = 0; i < numEntries; ++i) + const auto foundShader = AZStd::find_if(begin(mEntries), end(mEntries), [filename](const Entry& entry) { - if (AzFramework::StringFunc::Equal(mEntries[i].mName, filename, false /* no case */)) // non-case-sensitive name compare - { - return mEntries[i].mShader; - } - } - - // not found - return nullptr; + return AzFramework::StringFunc::Equal(entry.mName, filename, false /* no case */); + }); + return foundShader != end(mEntries) ? foundShader->mShader : nullptr; } // check if we have a given shader in the cache bool ShaderCache::CheckIfHasShader(Shader* shader) const { - const uint32 numEntries = mEntries.size(); - for (uint32 i = 0; i < numEntries; ++i) + return AZStd::any_of(begin(mEntries), end(mEntries), [shader](const Entry& entry) { - if (mEntries[i].mShader == shader) - { - return true; - } - } - - return false; + return entry.mShader == shader; + }); } } // namespace RenderGL diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/StandardMaterial.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/StandardMaterial.cpp index 46c7e5c13e..18281f286b 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/StandardMaterial.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/StandardMaterial.cpp @@ -183,8 +183,8 @@ namespace RenderGL EMotionFX::StandardMaterial* stdMaterial = static_cast(material); // get the number of material layers and iterate through them - const uint32 numLayers = stdMaterial->GetNumLayers(); - for (uint32 i = 0; i < numLayers; ++i) + const size_t numLayers = stdMaterial->GetNumLayers(); + for (size_t i = 0; i < numLayers; ++i) { EMotionFX::StandardMaterialLayer* layer = stdMaterial->GetLayer(i); switch (layer->GetType()) @@ -232,11 +232,9 @@ namespace RenderGL // void StandardMaterial::SetAttribute(EAttribute attribute, bool enabled) { - const uint32 index = (uint32)attribute; - - if (mAttributes[index] != enabled) + if (mAttributes[attribute] != enabled) { - mAttributes[index] = enabled; + mAttributes[attribute] = enabled; mAttributesUpdated = true; } } @@ -264,15 +262,15 @@ namespace RenderGL const AZ::Matrix3x4* skinningMatrices = transformData->GetSkinningMatrices(); // multiple each transform by its inverse bind pose - const uint32 numBones = primitive->mBoneNodeIndices.size(); - for (uint32 i = 0; i < numBones; ++i) + const size_t numBones = primitive->mBoneNodeIndices.size(); + for (size_t i = 0; i < numBones; ++i) { - const uint32 nodeNr = primitive->mBoneNodeIndices[i]; + const size_t nodeNr = primitive->mBoneNodeIndices[i]; const AZ::Matrix3x4& skinTransform = skinningMatrices[nodeNr]; mBoneMatrices[i] = AZ::Matrix4x4::CreateFromMatrix3x4(skinTransform); } - mActiveShader->SetUniform("matBones", mBoneMatrices, numBones); + mActiveShader->SetUniform("matBones", mBoneMatrices, aznumeric_caster(numBones)); } const MCommon::Camera* camera = GetGraphicsManager()->GetCamera(); @@ -305,10 +303,9 @@ namespace RenderGL mActiveShader = nullptr; // get the number of shaders and iterate through them - const uint32 numShaders = mShaders.size(); - for (uint32 i = 0; i < numShaders; ++i) + for (GLSLShader* shader : mShaders) { - if (mShaders[i] == nullptr) + if (shader == nullptr) { continue; } @@ -319,7 +316,7 @@ namespace RenderGL { if (mAttributes[n]) { - if (mShaders[i]->CheckIfIsDefined(AttributeToString((EAttribute)n)) == false) + if (shader->CheckIfIsDefined(AttributeToString((EAttribute)n)) == false) { match = false; break; @@ -327,7 +324,7 @@ namespace RenderGL } else { - if (mShaders[i]->CheckIfIsDefined(AttributeToString((EAttribute)n))) + if (shader->CheckIfIsDefined(AttributeToString((EAttribute)n))) { match = false; break; @@ -338,7 +335,7 @@ namespace RenderGL // in case we have found a matching shader update the active shader if (match) { - mActiveShader = mShaders[i]; + mActiveShader = shader; break; } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/TextureCache.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/TextureCache.cpp index 7ef5b49c67..dfdce36284 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/TextureCache.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/TextureCache.cpp @@ -73,10 +73,9 @@ namespace RenderGL void TextureCache::Release() { // delete all textures - const uint32 numEntries = mEntries.size(); - for (uint32 i = 0; i < numEntries; ++i) + for (Entry& entry : mEntries) { - delete mEntries[i].mTexture; + delete entry.mTexture; } // clear all entries @@ -102,17 +101,11 @@ namespace RenderGL Texture* TextureCache::FindTexture(const char* filename) const { // get the number of entries and iterate through them - const uint32 numEntries = mEntries.size(); - for (uint32 i = 0; i < numEntries; ++i) + const auto foundEntry = AZStd::find_if(begin(mEntries), end(mEntries), [filename](const Entry& entry) { - if (AzFramework::StringFunc::Equal(mEntries[i].mName.c_str(), filename, false /* no case */)) // non-case-sensitive name compare - { - return mEntries[i].mTexture; - } - } - - // not found - return nullptr; + return AzFramework::StringFunc::Equal(entry.mName.c_str(), filename, false /* no case */); + }); + return foundEntry != end(mEntries) ? foundEntry->mTexture : nullptr; } @@ -120,31 +113,25 @@ namespace RenderGL bool TextureCache::CheckIfHasTexture(Texture* texture) const { // get the number of entries and iterate through them - const uint32 numEntries = mEntries.size(); - for (uint32 i = 0; i < numEntries; ++i) + return AZStd::any_of(begin(mEntries), end(mEntries), [texture](const Entry& entry) { - if (mEntries[i].mTexture == texture) - { - return true; - } - } - - return false; + return entry.mTexture == texture; + }); } // remove an item from the cache void TextureCache::RemoveTexture(Texture* texture) { - const uint32 numEntries = mEntries.size(); - for (uint32 i = 0; i < numEntries; ++i) + const auto foundEntry = AZStd::find_if(begin(mEntries), end(mEntries), [texture](const Entry& entry) { - if (mEntries[i].mTexture == texture) - { - delete mEntries[i].mTexture; - mEntries.erase(AZStd::next(begin(mEntries), i)); - return; - } + return entry.mTexture == texture; + }); + + if (foundEntry != end(mEntries)) + { + delete foundEntry->mTexture; + mEntries.erase(foundEntry); } } @@ -154,12 +141,12 @@ namespace RenderGL GLuint textureID; glGenTextures(1, &textureID); - uint32 width = 2; - uint32 height = 2; + constexpr GLsizei width = 2; + constexpr GLsizei height = 2; uint32 imageBuffer[4]; - for (uint32 i = 0; i < 4; ++i) { - imageBuffer[i] = MCore::RGBA(255, 255, 255, 255); // actually abgr + using AZStd::begin, AZStd::end; + AZStd::fill(begin(imageBuffer), end(imageBuffer), MCore::RGBA(255, 255, 255, 255)); // actually abgr } glBindTexture(GL_TEXTURE_2D, textureID); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); @@ -180,12 +167,12 @@ namespace RenderGL GLuint textureID; glGenTextures(1, &textureID); - uint32 width = 2; - uint32 height = 2; + constexpr GLsizei width = 2; + constexpr GLsizei height = 2; uint32 imageBuffer[4]; - for (uint32 i = 0; i < 4; ++i) { - imageBuffer[i] = MCore::RGBA(255, 128, 128, 255); // opengl wants abgr + using AZStd::begin, AZStd::end; + AZStd::fill(begin(imageBuffer), end(imageBuffer), MCore::RGBA(255, 128, 128, 255)); // opengl wants abgr } glBindTexture(GL_TEXTURE_2D, textureID); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/glactor.h b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/glactor.h index 4de5d7198a..0b87477114 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/glactor.h +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/glactor.h @@ -75,18 +75,18 @@ namespace RenderGL void RenderMeshes(EMotionFX::ActorInstance* actorInstance, EMotionFX::Mesh::EMeshType meshType, uint32 renderFlags); void RenderShadowMap(EMotionFX::Mesh::EMeshType meshType); - void InitMaterials(uint32 lodLevel); + void InitMaterials(size_t lodLevel); Material* InitMaterial(EMotionFX::Material* emfxMaterial); - void FillIndexBuffers(uint32 lodLevel); - void FillStaticVertexBuffers(uint32 lodLevel); - void FillGPUSkinnedVertexBuffers(uint32 lodLevel); + void FillIndexBuffers(size_t lodLevel); + void FillStaticVertexBuffers(size_t lodLevel); + void FillGPUSkinnedVertexBuffers(size_t lodLevel); void UpdateDynamicVertices(EMotionFX::ActorInstance* actorInstance); - EMotionFX::Mesh::EMeshType ClassifyMeshType(EMotionFX::Node* node, EMotionFX::Mesh* mesh, uint32 lodLevel); + EMotionFX::Mesh::EMeshType ClassifyMeshType(EMotionFX::Node* node, EMotionFX::Mesh* mesh, size_t lodLevel); AZStd::vector< AZStd::vector > mMaterials; - MCore::Array2D mDynamicNodes; + MCore::Array2D mDynamicNodes; MCore::Array2D mPrimitives[3]; AZStd::vector mHomoMaterials; AZStd::vector mVertexBuffers[3]; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphGameControllerSettings.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphGameControllerSettings.cpp index 83df46b74d..6f2d6083a1 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphGameControllerSettings.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphGameControllerSettings.cpp @@ -230,50 +230,35 @@ namespace EMotionFX size_t AnimGraphGameControllerSettings::FindPresetIndexByName(const char* presetName) const { - const size_t presetCount = m_presets.size(); - for (size_t i = 0; i < presetCount; ++i) + const auto foundPreset = AZStd::find_if(begin(m_presets), end(m_presets), [presetName](const Preset* preset) { - if (m_presets[i]->GetNameString() == presetName) - { - return i; - } - } - - // return failure - return MCORE_INVALIDINDEX32; + return preset->GetNameString() == presetName; + }); + return foundPreset != end(m_presets) ? AZStd::distance(begin(m_presets), foundPreset) : InvalidIndex; } size_t AnimGraphGameControllerSettings::FindPresetIndex(Preset* preset) const { - const size_t presetCount = m_presets.size(); - for (size_t i = 0; i < presetCount; ++i) - { - if (m_presets[i] == preset) - { - return i; - } - } - - // return failure - return MCORE_INVALIDINDEX32; + const auto foundPreset = AZStd::find(begin(m_presets), end(m_presets), preset); + return foundPreset != end(m_presets) ? AZStd::distance(begin(m_presets), foundPreset) : InvalidIndex; } void AnimGraphGameControllerSettings::SetActivePreset(Preset* preset) { - m_activePresetIndex = static_cast(FindPresetIndex(preset)); + m_activePresetIndex = FindPresetIndex(preset); } - uint32 AnimGraphGameControllerSettings::GetActivePresetIndex() const + size_t AnimGraphGameControllerSettings::GetActivePresetIndex() const { if (m_activePresetIndex < m_presets.size()) { return m_activePresetIndex; } - return MCORE_INVALIDINDEX32; + return InvalidIndex; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphGameControllerSettings.h b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphGameControllerSettings.h index 715b280690..f543246599 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphGameControllerSettings.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphGameControllerSettings.h @@ -153,7 +153,7 @@ namespace EMotionFX Preset* GetPreset(size_t index) const; size_t GetNumPresets() const; - uint32 GetActivePresetIndex() const; + size_t GetActivePresetIndex() const; Preset* GetActivePreset() const; void SetActivePreset(Preset* preset); @@ -164,6 +164,6 @@ namespace EMotionFX private: AZStd::vector m_presets; - AZ::u32 m_activePresetIndex; + size_t m_activePresetIndex; }; } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNode.cpp index e73f8cf731..67c3f276cc 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNode.cpp @@ -550,7 +550,7 @@ namespace EMotionFX { const size_t currentSize = mOutputPorts.size(); mOutputPorts.emplace_back(); - return static_cast(currentSize); + return currentSize; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/EventHandler.h b/Gems/EMotionFX/Code/EMotionFX/Source/EventHandler.h index 19024bb351..c0b7696205 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/EventHandler.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/EventHandler.h @@ -330,7 +330,7 @@ namespace EMotionFX virtual void OnStateEnd(AnimGraphInstance* animGraphInstance, AnimGraphNode* state) { MCORE_UNUSED(animGraphInstance); MCORE_UNUSED(state); } virtual void OnStartTransition(AnimGraphInstance* animGraphInstance, AnimGraphStateTransition* transition) { MCORE_UNUSED(animGraphInstance); MCORE_UNUSED(transition); } virtual void OnEndTransition(AnimGraphInstance* animGraphInstance, AnimGraphStateTransition* transition) { MCORE_UNUSED(animGraphInstance); MCORE_UNUSED(transition); } - virtual void OnSetVisualManipulatorOffset(AnimGraphInstance* animGraphInstance, uint32 paramIndex, const AZ::Vector3& offset) { MCORE_UNUSED(animGraphInstance); MCORE_UNUSED(paramIndex); MCORE_UNUSED(offset); } + virtual void OnSetVisualManipulatorOffset(AnimGraphInstance* animGraphInstance, size_t paramIndex, const AZ::Vector3& offset) { MCORE_UNUSED(animGraphInstance); MCORE_UNUSED(paramIndex); MCORE_UNUSED(offset); } virtual void OnInputPortsChanged(AnimGraphNode* node, const AZStd::vector& newInputPorts, const AZStd::string& memberName, const AZStd::vector& memberValue) { AZ_UNUSED(node); AZ_UNUSED(newInputPorts); AZ_UNUSED(memberName); AZ_UNUSED(memberValue); } virtual void OnOutputPortsChanged(AnimGraphNode* node, const AZStd::vector& newOutputPorts, const AZStd::string& memberName, const AZStd::vector& memberValue) { AZ_UNUSED(node); AZ_UNUSED(newOutputPorts); AZ_UNUSED(memberName); AZ_UNUSED(memberValue); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.cpp index d946344622..135a37200c 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.cpp @@ -1474,7 +1474,7 @@ namespace EMotionFX // check for a given mesh how we categorize it - Mesh::EMeshType Mesh::ClassifyMeshType(uint32 lodLevel, Actor* actor, uint32 nodeIndex, bool forceCPUSkinning, uint32 maxInfluences, uint32 maxBonesPerSubMesh) const + Mesh::EMeshType Mesh::ClassifyMeshType(size_t lodLevel, Actor* actor, size_t nodeIndex, bool forceCPUSkinning, uint32 maxInfluences, uint32 maxBonesPerSubMesh) const { // get the mesh deformer stack for the given node at the given detail level MeshDeformerStack* deformerStack = actor->GetMeshDeformerStack(lodLevel, nodeIndex); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.h b/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.h index d9c09d66bb..b38a1445f6 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.h @@ -596,7 +596,7 @@ namespace EMotionFX * @param maxBonesPerSubMesh The maximum number of bones per submesh can be processed on hardware. If there will be more bones per submesh the mesh will be processed in software which will be very slow. * @return The mesh type meaning if the given mesh is static like a cube or building or if is deformed by the GPU or CPU. */ - EMeshType ClassifyMeshType(uint32 lodLevel, Actor* actor, uint32 nodeIndex, bool forceCPUSkinning, uint32 maxInfluences, uint32 maxBonesPerSubMesh) const; + EMeshType ClassifyMeshType(size_t lodLevel, Actor* actor, size_t nodeIndex, bool forceCPUSkinning, uint32 maxInfluences, uint32 maxBonesPerSubMesh) const; /** * Debug log information. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Recorder.h b/Gems/EMotionFX/Code/EMotionFX/Source/Recorder.h index a727750d1f..7d76b09483 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Recorder.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Recorder.h @@ -131,7 +131,7 @@ namespace EMotionFX KeyTrackLinearDynamic mPlayTimes; // normalized time values (current time in the node/motion) uint32 mMotionID; // the ID of the Motion object used size_t mTrackIndex; // the track index - uint32 mCachedKey; // a cached key + size_t mCachedKey; // a cached key AnimGraphNodeId mNodeId; // animgraph node Id AnimGraphInstance* mAnimGraphInstance; // the anim graph instance this node was recorded from AZ::Color mColor; // the node viz color @@ -147,7 +147,7 @@ namespace EMotionFX mEndTime = 0.0f; mMotionID = MCORE_INVALIDINDEX32; mTrackIndex = InvalidIndex; - mCachedKey = MCORE_INVALIDINDEX32; + mCachedKey = InvalidIndex; mNodeId = AnimGraphNodeId(); mAnimGraphInstance = nullptr; mAnimGraphID = MCORE_INVALIDINDEX32; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/Commands.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/Commands.cpp index 4fb82ec3e1..b46fa645d1 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/Commands.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/Commands.cpp @@ -396,8 +396,8 @@ namespace EMStudio { motionSet->SetDirtyFlag(dirtyFlag); - const uint32 numChildSets = motionSet->GetNumChildSets(); - for (uint32 i = 0; i < numChildSets; ++i) + const size_t numChildSets = motionSet->GetNumChildSets(); + for (size_t i = 0; i < numChildSets; ++i) { EMotionFX::MotionSet* childSet = motionSet->GetChildSet(i); RecursiveSetDirtyFlag(childSet, dirtyFlag); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioManager.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioManager.cpp index c0867139e7..2f557ad290 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioManager.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioManager.cpp @@ -177,7 +177,7 @@ namespace EMStudio #endif // EMFX_EMSTUDIOLYEMBEDDED // Give a chance to every plugin to reflect data - const uint32 numPlugins = mPluginManager->GetNumPlugins(); + const size_t numPlugins = mPluginManager->GetNumPlugins(); if (numPlugins) { AZ::SerializeContext* serializeContext = nullptr; @@ -188,7 +188,7 @@ namespace EMStudio } else { - for (uint32 i = 0; i < numPlugins; ++i) + for (size_t i = 0; i < numPlugins; ++i) { EMStudioPlugin* plugin = mPluginManager->GetPlugin(i); plugin->Reflect(serializeContext); @@ -320,12 +320,12 @@ namespace EMStudio } - void EMStudioManager::SetVisibleJointIndices(const AZStd::unordered_set& visibleJointIndices) + void EMStudioManager::SetVisibleJointIndices(const AZStd::unordered_set& visibleJointIndices) { m_visibleJointIndices = visibleJointIndices; } - void EMStudioManager::SetSelectedJointIndices(const AZStd::unordered_set& selectedJointIndices) + void EMStudioManager::SetSelectedJointIndices(const AZStd::unordered_set& selectedJointIndices) { m_selectedJointIndices = selectedJointIndices; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioManager.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioManager.h index 915c45bc18..95dbd3012a 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioManager.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioManager.h @@ -93,11 +93,11 @@ namespace EMStudio void LogInfo(); // in case the array is empty, all nodes are shown - void SetVisibleJointIndices(const AZStd::unordered_set& visibleJointIndices); - const AZStd::unordered_set& GetVisibleJointIndices() const { return m_visibleJointIndices; } + void SetVisibleJointIndices(const AZStd::unordered_set& visibleJointIndices); + const AZStd::unordered_set& GetVisibleJointIndices() const { return m_visibleJointIndices; } - void SetSelectedJointIndices(const AZStd::unordered_set& selectedJointIndices); - const AZStd::unordered_set& GetSelectedJointIndices() const { return m_selectedJointIndices; } + void SetSelectedJointIndices(const AZStd::unordered_set& selectedJointIndices); + const AZStd::unordered_set& GetSelectedJointIndices() const { return m_selectedJointIndices; } Workspace* GetWorkspace() { return &mWorkspace; } @@ -123,8 +123,8 @@ namespace EMStudio NotificationWindowManager* mNotificationWindowManager; CommandSystem::CommandManager* mCommandManager; AZStd::string mCompileDate; - AZStd::unordered_set m_visibleJointIndices; - AZStd::unordered_set m_selectedJointIndices; + AZStd::unordered_set m_visibleJointIndices; + AZStd::unordered_set m_selectedJointIndices; Workspace mWorkspace; bool mAutoLoadLastWorkspace; AZStd::string mHTMLLinkString; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/FileManager.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/FileManager.cpp index 76febd63cf..dcb7c46fe5 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/FileManager.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/FileManager.cpp @@ -89,8 +89,8 @@ namespace EMStudio if (AzFramework::StringFunc::Equal(extension.c_str(), "motion")) { - const AZ::u32 motionCount = EMotionFX::GetMotionManager().GetNumMotions(); - for (AZ::u32 i = 0; i < motionCount; ++i) + const size_t motionCount = EMotionFX::GetMotionManager().GetNumMotions(); + for (size_t i = 0; i < motionCount; ++i) { EMotionFX::Motion* motion = EMotionFX::GetMotionManager().GetMotion(i); if (motion->GetIsOwnedByRuntime()) @@ -107,8 +107,8 @@ namespace EMStudio if (AzFramework::StringFunc::Equal(extension.c_str(), "actor")) { - const AZ::u32 actorCount = EMotionFX::GetActorManager().GetNumActors(); - for (AZ::u32 i = 0; i < actorCount; ++i) + const size_t actorCount = EMotionFX::GetActorManager().GetNumActors(); + for (size_t i = 0; i < actorCount; ++i) { EMotionFX::Actor* actor = EMotionFX::GetActorManager().GetActor(i); if (actor->GetIsOwnedByRuntime()) @@ -202,8 +202,8 @@ namespace EMStudio if (AzFramework::StringFunc::Equal(extension.c_str(), "motionset")) { - const AZ::u32 motionSetCount = EMotionFX::GetMotionManager().GetNumMotionSets(); - for (AZ::u32 i = 0; i < motionSetCount; ++i) + const size_t motionSetCount = EMotionFX::GetMotionManager().GetNumMotionSets(); + for (size_t i = 0; i < motionSetCount; ++i) { EMotionFX::MotionSet* motionSet = EMotionFX::GetMotionManager().GetMotionSet(i); if (motionSet->GetIsOwnedByRuntime()) @@ -220,8 +220,8 @@ namespace EMStudio if (AzFramework::StringFunc::Equal(extension.c_str(), "animgraph")) { - const AZ::u32 animGraphCount = EMotionFX::GetAnimGraphManager().GetNumAnimGraphs(); - for (AZ::u32 i = 0; i < animGraphCount; ++i) + const size_t animGraphCount = EMotionFX::GetAnimGraphManager().GetNumAnimGraphs(); + for (size_t i = 0; i < animGraphCount; ++i) { EMotionFX::AnimGraph* animGraph = EMotionFX::GetAnimGraphManager().GetAnimGraph(i); if (animGraph->GetIsOwnedByRuntime()) @@ -570,7 +570,7 @@ namespace EMStudio } - void FileManager::SaveMotionSet(const char* filename, EMotionFX::MotionSet* motionSet, MCore::CommandGroup* commandGroup) + void FileManager::SaveMotionSet(const char* filename, const EMotionFX::MotionSet* motionSet, MCore::CommandGroup* commandGroup) { const AZStd::string command = AZStd::string::format("SaveMotionSet -motionSetID %i -filename \"%s\"", motionSet->GetID(), filename); @@ -595,7 +595,7 @@ namespace EMStudio } - void FileManager::SaveMotionSet(QWidget* parent, EMotionFX::MotionSet* motionSet, MCore::CommandGroup* commandGroup) + void FileManager::SaveMotionSet(QWidget* parent, const EMotionFX::MotionSet* motionSet, MCore::CommandGroup* commandGroup) { AZStd::string filename = motionSet->GetFilename(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/FileManager.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/FileManager.h index baf721d2ce..50dfce390a 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/FileManager.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/FileManager.h @@ -82,8 +82,8 @@ namespace EMStudio // motion set file dialogs AZStd::string LoadMotionSetFileDialog(QWidget* parent); AZStd::string SaveMotionSetFileDialog(QWidget* parent); - void SaveMotionSet(QWidget* parent, EMotionFX::MotionSet* motionSet, MCore::CommandGroup* commandGroup = nullptr); - void SaveMotionSet(const char* filename, EMotionFX::MotionSet* motionSet, MCore::CommandGroup* commandGroup = nullptr); + void SaveMotionSet(QWidget* parent, const EMotionFX::MotionSet* motionSet, MCore::CommandGroup* commandGroup = nullptr); + void SaveMotionSet(const char* filename, const EMotionFX::MotionSet* motionSet, MCore::CommandGroup* commandGroup = nullptr); // motion file dialogs AZStd::string LoadMotionFileDialog(QWidget* parent); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/LayoutManager.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/LayoutManager.cpp index bc2b98bd99..eed352ad7c 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/LayoutManager.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/LayoutManager.cpp @@ -127,7 +127,7 @@ namespace EMStudio header.mLayoutVersionHigh = 0; header.mLayoutVersionLow = 1; - header.mNumPlugins = GetPluginManager()->GetNumActivePlugins(); + header.mNumPlugins = aznumeric_caster(GetPluginManager()->GetNumActivePlugins()); if (file.write((char*)&header, sizeof(LayoutHeader)) == -1) { MCore::LogWarning("Failed to write layout header to layout file '%s'", filename); @@ -339,8 +339,8 @@ namespace EMStudio GetMainWindow()->UpdateCreateWindowMenu(); // update Window->Create menu // Trigger the OnAfterLoadLayout callbacks. - const uint32 numActivePlugins = pluginManager->GetNumActivePlugins(); - for (uint32 p = 0; p < numActivePlugins; ++p) + const size_t numActivePlugins = pluginManager->GetNumActivePlugins(); + for (size_t p = 0; p < numActivePlugins; ++p) { GetPluginManager()->GetActivePlugin(p)->OnAfterLoadLayout(); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindow.cpp index 7303c8d559..c5781ebf12 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindow.cpp @@ -1037,8 +1037,8 @@ namespace EMStudio // enable the actor save selected menu only if one actor or actor instance is selected // it's needed to check here because if one actor is removed it's not selected anymore const CommandSystem::SelectionList& selectionList = GetCommandManager()->GetCurrentSelection(); - const uint32 numSelectedActors = selectionList.GetNumSelectedActors(); - const uint32 numSelectedActorInstances = selectionList.GetNumSelectedActorInstances(); + const size_t numSelectedActors = selectionList.GetNumSelectedActors(); + const size_t numSelectedActorInstances = selectionList.GetNumSelectedActorInstances(); if ((numSelectedActors > 0) || (numSelectedActorInstances > 0)) { EnableSaveSelectedActorsMenu(); @@ -1087,12 +1087,12 @@ namespace EMStudio PluginManager* pluginManager = GetPluginManager(); // get the number of plugins - const uint32 numPlugins = pluginManager->GetNumPlugins(); + const size_t numPlugins = pluginManager->GetNumPlugins(); // add each plugin name in an array to sort them AZStd::vector sortedPlugins; sortedPlugins.reserve(numPlugins); - for (uint32 p = 0; p < numPlugins; ++p) + for (size_t p = 0; p < numPlugins; ++p) { EMStudioPlugin* plugin = pluginManager->GetPlugin(p); sortedPlugins.emplace_back(plugin->GetName()); @@ -1103,10 +1103,10 @@ namespace EMStudio mCreateWindowMenu->clear(); // for all registered plugins, create a menu items - for (uint32 p = 0; p < numPlugins; ++p) + for (size_t p = 0; p < numPlugins; ++p) { // get the plugin - const uint32 pluginIndex = pluginManager->FindPluginByTypeString(sortedPlugins[p].c_str()); + const size_t pluginIndex = pluginManager->FindPluginByTypeString(sortedPlugins[p].c_str()); EMStudioPlugin* plugin = pluginManager->GetPlugin(pluginIndex); // don't add invisible plugins to the list @@ -1222,8 +1222,8 @@ namespace EMStudio generalPropertyWidget->AddInstance(&mOptions, azrtti_typeid(mOptions)); PluginManager* pluginManager = GetPluginManager(); - const uint32 numPlugins = pluginManager->GetNumActivePlugins(); - for (uint32 i = 0; i < numPlugins; ++i) + const size_t numPlugins = pluginManager->GetNumActivePlugins(); + for (size_t i = 0; i < numPlugins; ++i) { EMStudioPlugin* currentPlugin = pluginManager->GetActivePlugin(i); PluginOptions* pluginOptions = currentPlugin->GetOptions(); @@ -1769,21 +1769,21 @@ namespace EMStudio { // get the current selection list const CommandSystem::SelectionList& selectionList = GetCommandManager()->GetCurrentSelection(); - const uint32 numSelectedActors = selectionList.GetNumSelectedActors(); - const uint32 numSelectedActorInstances = selectionList.GetNumSelectedActorInstances(); + const size_t numSelectedActors = selectionList.GetNumSelectedActors(); + const size_t numSelectedActorInstances = selectionList.GetNumSelectedActorInstances(); // create the saving actor array AZStd::vector savingActors; savingActors.reserve(numSelectedActors + numSelectedActorInstances); // add all selected actors to the list - for (uint32 i = 0; i < numSelectedActors; ++i) + for (size_t i = 0; i < numSelectedActors; ++i) { savingActors.push_back(selectionList.GetActor(i)); } // check all actors of all selected actor instances and put them in the list if they are not in yet - for (uint32 i = 0; i < numSelectedActorInstances; ++i) + for (size_t i = 0; i < numSelectedActorInstances; ++i) { EMotionFX::Actor* actor = selectionList.GetActorInstance(i)->GetActor(); @@ -1862,15 +1862,14 @@ namespace EMStudio } // add each menu - const uint32 numLayoutNames = mLayoutNames.size(); - for (uint32 i = 0; i < numLayoutNames; ++i) + for (const AZStd::string& layoutName : mLayoutNames) { - QAction* action = mLayoutsMenu->addAction(mLayoutNames[i].c_str()); + QAction* action = mLayoutsMenu->addAction(layoutName.c_str()); connect(action, &QAction::triggered, this, &MainWindow::OnLoadLayout); } // add the separator only if at least one layout - if (numLayoutNames > 0) + if (!mLayoutNames.empty()) { mLayoutsMenu->addSeparator(); } @@ -1880,22 +1879,22 @@ namespace EMStudio connect(saveCurrentAction, &QAction::triggered, this, &MainWindow::OnLayoutSaveAs); // remove menu is needed only if at least one layout - if (numLayoutNames > 0) + if (!mLayoutNames.empty()) { // add the remove menu QMenu* removeMenu = mLayoutsMenu->addMenu("Remove"); removeMenu->setObjectName("RemoveMenu"); // add each layout in the remove menu - for (uint32 i = 0; i < numLayoutNames; ++i) + for (const AZStd::string& layoutName : mLayoutNames) { // User cannot remove the default layout. This layout is referenced in the qrc file, removing it will // cause compiling issue too. - if (mLayoutNames[i] == "AnimGraph") + if (layoutName == "AnimGraph") { continue; } - QAction* action = removeMenu->addAction(mLayoutNames[i].c_str()); + QAction* action = removeMenu->addAction(layoutName.c_str()); connect(action, &QAction::triggered, this, &MainWindow::OnRemoveLayout); } } @@ -1905,9 +1904,9 @@ namespace EMStudio // update the combo box mApplicationMode->clear(); - for (uint32 i = 0; i < numLayoutNames; ++i) + for (const AZStd::string& layoutName : mLayoutNames) { - mApplicationMode->addItem(mLayoutNames[i].c_str()); + mApplicationMode->addItem(layoutName.c_str()); } // update the current selection of combo box @@ -2055,7 +2054,7 @@ namespace EMStudio const bool result = GetCommandManager()->Undo(outResult); // log the results if there are any - if (outResult.size() > 0) + if (!outResult.empty()) { if (result == false) { @@ -2080,7 +2079,7 @@ namespace EMStudio const bool result = GetCommandManager()->Redo(outResult); // log the results if there are any - if (outResult.size() > 0) + if (!outResult.empty()) { if (result == false) { @@ -2279,8 +2278,8 @@ namespace EMStudio // for all registered plugins, call the after load workspace callback PluginManager* pluginManager = GetPluginManager(); - const uint32 numPlugins = pluginManager->GetNumActivePlugins(); - for (uint32 p = 0; p < numPlugins; ++p) + const size_t numPlugins = pluginManager->GetNumActivePlugins(); + for (size_t p = 0; p < numPlugins; ++p) { EMStudioPlugin* plugin = pluginManager->GetActivePlugin(p); plugin->OnAfterLoadProject(); @@ -2320,8 +2319,8 @@ namespace EMStudio MCore::CommandGroup commandGroup("Animgraph and motion set activation"); AZStd::string commandString; - const uint32 numActorInstances = EMotionFX::GetActorManager().GetNumActorInstances(); - for (uint32 i = 0; i < numActorInstances; ++i) + const size_t numActorInstances = EMotionFX::GetActorManager().GetNumActorInstances(); + for (size_t i = 0; i < numActorInstances; ++i) { EMotionFX::ActorInstance* actorInstance = EMotionFX::GetActorManager().GetActorInstance(i); if (!actorInstance || actorFilename != actorInstance->GetActor()->GetFileName()) @@ -2465,8 +2464,8 @@ namespace EMStudio // for all registered plugins, call the after load actors callback PluginManager* pluginManager = GetPluginManager(); - const uint32 numPlugins = pluginManager->GetNumActivePlugins(); - for (uint32 p = 0; p < numPlugins; ++p) + const size_t numPlugins = pluginManager->GetNumActivePlugins(); + for (size_t p = 0; p < numPlugins; ++p) { EMStudioPlugin* plugin = pluginManager->GetActivePlugin(p); plugin->OnAfterLoadActors(); @@ -2757,8 +2756,8 @@ namespace EMStudio } else if (dirtyObjects[i].mAnimGraph) { - const uint32 animGraphIndex = EMotionFX::GetAnimGraphManager().FindAnimGraphIndex(dirtyObjects[i].mAnimGraph); - command = AZStd::string::format("SaveAnimGraph -index %i -filename \"%s\" -updateFilename false -updateDirtyFlag false -sourceControl false", animGraphIndex, newFileFilename.c_str()); + const size_t animGraphIndex = EMotionFX::GetAnimGraphManager().FindAnimGraphIndex(dirtyObjects[i].mAnimGraph); + command = AZStd::string::format("SaveAnimGraph -index %zu -filename \"%s\" -updateFilename false -updateDirtyFlag false -sourceControl false", animGraphIndex, newFileFilename.c_str()); commandGroup.AddCommandString(command); } else if (dirtyObjects[i].mWorkspace) @@ -2803,8 +2802,8 @@ namespace EMStudio PluginManager* pluginManager = GetPluginManager(); // get the number of active plugins, iterate through them and call the process frame method - const uint32 numPlugins = pluginManager->GetNumActivePlugins(); - for (uint32 p = 0; p < numPlugins; ++p) + const size_t numPlugins = pluginManager->GetNumActivePlugins(); + for (size_t p = 0; p < numPlugins; ++p) { EMStudioPlugin* plugin = pluginManager->GetActivePlugin(p); if (plugin->GetPluginType() == EMStudioPlugin::PLUGINTYPE_RENDERING) diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MorphTargetSelectionWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MorphTargetSelectionWindow.cpp index 47b282824a..e189b98dcf 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MorphTargetSelectionWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MorphTargetSelectionWindow.cpp @@ -90,8 +90,8 @@ namespace EMStudio mSelection = selection; - const uint32 numMorphTargets = morphSetup->GetNumMorphTargets(); - for (uint32 i = 0; i < numMorphTargets; ++i) + const size_t numMorphTargets = morphSetup->GetNumMorphTargets(); + for (size_t i = 0; i < numMorphTargets; ++i) { EMotionFX::MorphTarget* morphTarget = morphSetup->GetMorphTarget(i); const uint32 morphTargetID = morphTarget->GetID(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MotionSetHierarchyWidget.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MotionSetHierarchyWidget.cpp index 7b125e9e63..a5e3a64f1f 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MotionSetHierarchyWidget.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MotionSetHierarchyWidget.cpp @@ -116,8 +116,8 @@ namespace EMStudio else { // add all root motion sets - const uint32 numMotionSets = EMotionFX::GetMotionManager().GetNumMotionSets(); - for (uint32 i = 0; i < numMotionSets; ++i) + const size_t numMotionSets = EMotionFX::GetMotionManager().GetNumMotionSets(); + for (size_t i = 0; i < numMotionSets; ++i) { EMotionFX::MotionSet* motionSet = EMotionFX::GetMotionManager().GetMotionSet(i); @@ -185,8 +185,8 @@ namespace EMStudio } // add all child sets - const uint32 numChildSets = motionSet->GetNumChildSets(); - for (uint32 i = 0; i < numChildSets; ++i) + const size_t numChildSets = motionSet->GetNumChildSets(); + for (size_t i = 0; i < numChildSets; ++i) { RecursiveAddMotionSet(motionSetItem, motionSet->GetChildSet(i), selectionList); } @@ -303,21 +303,19 @@ namespace EMStudio { // Get the selected items in the tree widget. QList selectedItems = mHierarchy->selectedItems(); - const uint32 numSelectedItems = selectedItems.count(); // Reset the selection. mSelected.clear(); - mSelected.reserve(numSelectedItems); + mSelected.reserve(selectedItems.size()); AZStd::string motionId; - for (uint32 i = 0; i < numSelectedItems; ++i) + for (const QTreeWidgetItem* item : selectedItems) { - QTreeWidgetItem* item = selectedItems[i]; - motionId = item->text(0).toUtf8().data(); + motionId = item->text(0).toUtf8().data(); // Extract the motion set id. QString motionSetIdAsString = item->whatsThis(0); - const AZ::u32 motionSetId = AzFramework::StringFunc::ToInt(motionSetIdAsString.toUtf8().data()); + const uint32 motionSetId = AzFramework::StringFunc::ToInt(motionSetIdAsString.toUtf8().data()); // Find the motion set based on the id. EMotionFX::MotionSet* motionSet = EMotionFX::GetMotionManager().FindMotionSetByID(motionSetId); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NodeHierarchyWidget.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NodeHierarchyWidget.cpp index 4dabd18e5c..55f7324b75 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NodeHierarchyWidget.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NodeHierarchyWidget.cpp @@ -156,8 +156,8 @@ namespace EMStudio if (actorInstanceID == MCORE_INVALIDINDEX32) { // get the number actor instances and iterate over them - const uint32 numActorInstances = EMotionFX::GetActorManager().GetNumActorInstances(); - for (uint32 i = 0; i < numActorInstances; ++i) + const size_t numActorInstances = EMotionFX::GetActorManager().GetNumActorInstances(); + for (size_t i = 0; i < numActorInstances; ++i) { // add the actor to the node hierarchy widget EMotionFX::ActorInstance* actorInstance = EMotionFX::GetActorManager().GetActorInstance(i); @@ -187,11 +187,10 @@ namespace EMStudio mHierarchy->clear(); // get the number actor instances and iterate over them - const uint32 numActorInstances = mActorInstanceIDs.size(); - for (uint32 i = 0; i < numActorInstances; ++i) + for (const uint32 mActorInstanceID : mActorInstanceIDs) { // get the actor instance by its id - EMotionFX::ActorInstance* actorInstance = EMotionFX::GetActorManager().FindActorInstanceByID(mActorInstanceIDs[i]); + EMotionFX::ActorInstance* actorInstance = EMotionFX::GetActorManager().FindActorInstanceByID(mActorInstanceID); if (actorInstance) { AddActorInstance(actorInstance); @@ -241,7 +240,7 @@ namespace EMStudio // get the number of root nodes and iterate through them const size_t numRootNodes = actor->GetSkeleton()->GetNumRootNodes(); - for (uint32 i = 0; i < numRootNodes; ++i) + for (size_t i = 0; i < numRootNodes; ++i) { // get the root node index and the corresponding node const size_t rootNodeIndex = actor->GetSkeleton()->GetRootNodeIndex(i); @@ -349,7 +348,7 @@ namespace EMStudio parent->addChild(item); // iterate through all children - for (uint32 i = 0; i < numChildren; ++i) + for (size_t i = 0; i < numChildren; ++i) { // get the node index and the corresponding node const size_t childIndex = node->GetChildIndex(i); @@ -362,7 +361,7 @@ namespace EMStudio else { // iterate through all children - for (uint32 i = 0; i < numChildren; ++i) + for (size_t i = 0; i < numChildren; ++i) { // get the node index and the corresponding node const size_t childIndex = node->GetChildIndex(i); @@ -470,8 +469,8 @@ namespace EMStudio } // get the number of children and iterate through them - const uint32 numChilds = item->childCount(); - for (uint32 i = 0; i < numChilds; ++i) + const int numChilds = item->childCount(); + for (int i = 0; i < numChilds; ++i) { RecursiveRemoveUnselectedItems(item->child(i)); } @@ -480,33 +479,20 @@ namespace EMStudio void NodeHierarchyWidget::UpdateSelection() { - uint32 i; - - //LOG("================================Update Selection!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); - //LOG("NumSelectedNodes=%i", mSelectedNodes.GetLength()); - //String debugString; - //debugString.Reserve(10000); - //for (uint32 s=0; s selectedItems = mHierarchy->selectedItems(); - const uint32 numSelectedItems = selectedItems.count(); // remove the unselected tree widget items from the selected nodes - const uint32 numTopLevelItems = mHierarchy->topLevelItemCount(); - for (i = 0; i < numTopLevelItems; ++i) + const int numTopLevelItems = mHierarchy->topLevelItemCount(); + for (int i = 0; i < numTopLevelItems; ++i) { RecursiveRemoveUnselectedItems(mHierarchy->topLevelItem(i)); } // iterate through all selected items - for (i = 0; i < numSelectedItems; ++i) + for (const QTreeWidgetItem* item : selectedItems) { - QTreeWidgetItem* item = selectedItems[i]; - - // get the item name + // get the item name FromQtString(item->text(0), &mItemName); FromQtString(item->whatsThis(0), &mActorInstanceIDString); @@ -644,32 +630,20 @@ namespace EMStudio // check if the node with the given name is selected in the window bool NodeHierarchyWidget::CheckIfNodeSelected(const char* nodeName, uint32 actorInstanceID) { - for (const SelectionItem& selectedItem : m_selectedNodes) + return AZStd::any_of(begin(m_selectedNodes), end(m_selectedNodes), [nodeName, actorInstanceID](const SelectionItem& selectedItem) { - if (selectedItem.mActorInstanceID == actorInstanceID && selectedItem.GetNodeNameString() == nodeName) - { - return true; - } - } - - // failure, not found in the selected nodes array - return false; + return selectedItem.mActorInstanceID == actorInstanceID && selectedItem.GetNodeNameString() == nodeName; + }); } // check if the actor instance with the given id is selected in the window bool NodeHierarchyWidget::CheckIfActorInstanceSelected(uint32 actorInstanceID) { - for (const SelectionItem& selectedItem : m_selectedNodes) + return AZStd::any_of(begin(m_selectedNodes), end(m_selectedNodes), [actorInstanceID](const SelectionItem& selectedItem) { - if (selectedItem.mActorInstanceID == actorInstanceID && selectedItem.GetNodeNameString().empty()) - { - return true; - } - } - - // failure, not found in the selected nodes array - return false; + return selectedItem.mActorInstanceID == actorInstanceID && selectedItem.GetNodeNameString().empty(); + }); } @@ -685,15 +659,12 @@ namespace EMStudio m_selectedNodes.clear(); // get the number actor instances and iterate over them - const uint32 numActorInstances = mActorInstanceIDs.size(); - for (uint32 i = 0; i < numActorInstances; ++i) + for (const uint32 actorInstanceID : mActorInstanceIDs) { // add the actor to the node hierarchy widget - const uint32 actorInstanceID = mActorInstanceIDs[i]; - // get the number of selected nodes and iterate through them - const uint32 numSelectedNodes = selectionList->GetNumSelectedNodes(); - for (uint32 n = 0; n < numSelectedNodes; ++n) + const size_t numSelectedNodes = selectionList->GetNumSelectedNodes(); + for (size_t n = 0; n < numSelectedNodes; ++n) { const EMotionFX::Node* joint = selectionList->GetNode(n); if (joint) @@ -725,12 +696,6 @@ namespace EMStudio return mFilterState.testFlag(FilterType::Bones); } - /* - void NodeHierarchyWidget::OnVisibilityChanged(bool isVisible) - { - if (isVisible) - Update(); - }*/ } // namespace EMStudio #include diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NotificationWindowManager.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NotificationWindowManager.cpp index 9eb2c7f23e..d203e4386b 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NotificationWindowManager.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NotificationWindowManager.cpp @@ -33,10 +33,9 @@ namespace EMStudio // compute the height of all notification windows with the spacing int allNotificationWindowsHeight = 0; - const uint32 numNotificationWindows = mNotificationWindows.size(); - for (uint32 i = 0; i < numNotificationWindows; ++i) + for (const NotificationWindow* mNotificationWindow : mNotificationWindows) { - allNotificationWindowsHeight += mNotificationWindows[i]->geometry().height() + notificationWindowSpacing; + allNotificationWindowsHeight += mNotificationWindow->geometry().height() + notificationWindowSpacing; } // move the notification window @@ -82,16 +81,15 @@ namespace EMStudio // move each notification window int currentNotificationWindowHeight = notificationWindowMainWindowPadding; - const uint32 numNotificationWindows = mNotificationWindows.size(); - for (uint32 i = 0; i < numNotificationWindows; ++i) + for (NotificationWindow* mNotificationWindow : mNotificationWindows) { // add the height of the notification window - currentNotificationWindowHeight += mNotificationWindows[i]->geometry().height(); + currentNotificationWindowHeight += mNotificationWindow->geometry().height(); // move the notification window const QPoint mainWindowBottomRight = mainWindow->geometry().bottomRight(); - const QRect& notificationWindowGeometry = mNotificationWindows[i]->geometry(); - mNotificationWindows[i]->move(mainWindowBottomRight.x() - notificationWindowGeometry.width() - notificationWindowMainWindowPadding, mainWindowBottomRight.y() - currentNotificationWindowHeight); + const QRect& notificationWindowGeometry = mNotificationWindow->geometry(); + mNotificationWindow->move(mainWindowBottomRight.x() - notificationWindowGeometry.width() - notificationWindowMainWindowPadding, mainWindowBottomRight.y() - currentNotificationWindowHeight); // spacing is added after to avoid spacing on the bottom of the first notification window currentNotificationWindowHeight += notificationWindowSpacing; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/ManipulatorCallbacks.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/ManipulatorCallbacks.cpp index df54968f0c..750de85344 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/ManipulatorCallbacks.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/ManipulatorCallbacks.cpp @@ -21,8 +21,8 @@ namespace EMStudio ManipulatorCallback::Update(value); // update the position, if actorinstance is still valid - uint32 actorInstanceID = EMotionFX::GetActorManager().FindActorInstanceIndex(mActorInstance); - if (actorInstanceID != MCORE_INVALIDINDEX32) + size_t actorInstanceID = EMotionFX::GetActorManager().FindActorInstanceIndex(mActorInstance); + if (actorInstanceID != InvalidIndex) { mActorInstance->SetLocalSpacePosition(value); } @@ -31,8 +31,8 @@ namespace EMStudio void TranslateManipulatorCallback::UpdateOldValues() { // update the rotation, if actorinstance is still valid - uint32 actorInstanceID = EMotionFX::GetActorManager().FindActorInstanceIndex(mActorInstance); - if (actorInstanceID != MCORE_INVALIDINDEX32) + size_t actorInstanceID = EMotionFX::GetActorManager().FindActorInstanceIndex(mActorInstance); + if (actorInstanceID != InvalidIndex) { mOldValueVec = mActorInstance->GetLocalSpaceTransform().mPosition; } @@ -66,8 +66,8 @@ namespace EMStudio void RotateManipulatorCallback::Update(const AZ::Quaternion& value) { // update the rotation, if actorinstance is still valid - uint32 actorInstanceID = EMotionFX::GetActorManager().FindActorInstanceIndex(mActorInstance); - if (actorInstanceID != MCORE_INVALIDINDEX32) + size_t actorInstanceID = EMotionFX::GetActorManager().FindActorInstanceIndex(mActorInstance); + if (actorInstanceID != InvalidIndex) { // temporarily update the actor instance mActorInstance->SetLocalSpaceRotation(value * mActorInstance->GetLocalSpaceTransform().mRotation.GetNormalized()); @@ -80,8 +80,8 @@ namespace EMStudio void RotateManipulatorCallback::UpdateOldValues() { // update the rotation, if actorinstance is still valid - uint32 actorInstanceID = EMotionFX::GetActorManager().FindActorInstanceIndex(mActorInstance); - if (actorInstanceID != MCORE_INVALIDINDEX32) + size_t actorInstanceID = EMotionFX::GetActorManager().FindActorInstanceIndex(mActorInstance); + if (actorInstanceID != InvalidIndex) { mOldValueQuat = mActorInstance->GetLocalSpaceTransform().mRotation; } @@ -117,8 +117,8 @@ namespace EMStudio AZ::Vector3 ScaleManipulatorCallback::GetCurrValueVec() { - uint32 actorInstanceID = EMotionFX::GetActorManager().FindActorInstanceIndex(mActorInstance); - if (actorInstanceID != MCORE_INVALIDINDEX32) + size_t actorInstanceID = EMotionFX::GetActorManager().FindActorInstanceIndex(mActorInstance); + if (actorInstanceID != InvalidIndex) { #ifndef EMFX_SCALE_DISABLED return mActorInstance->GetLocalSpaceTransform().mScale; @@ -137,8 +137,8 @@ namespace EMStudio EMFX_SCALECODE ( // update the position, if actorinstance is still valid - uint32 actorInstanceID = EMotionFX::GetActorManager().FindActorInstanceIndex(mActorInstance); - if (actorInstanceID != MCORE_INVALIDINDEX32) + size_t actorInstanceID = EMotionFX::GetActorManager().FindActorInstanceIndex(mActorInstance); + if (actorInstanceID != InvalidIndex) { float minScale = 0.001f; const AZ::Vector3 scale = AZ::Vector3( @@ -159,8 +159,8 @@ namespace EMStudio EMFX_SCALECODE ( // update the rotation, if actorinstance is still valid - uint32 actorInstanceID = EMotionFX::GetActorManager().FindActorInstanceIndex(mActorInstance); - if (actorInstanceID != MCORE_INVALIDINDEX32) + size_t actorInstanceID = EMotionFX::GetActorManager().FindActorInstanceIndex(mActorInstance); + if (actorInstanceID != InvalidIndex) { mOldValueVec = mActorInstance->GetLocalSpaceTransform().mScale; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.cpp index abbb9b7d81..506605fec4 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.cpp @@ -128,12 +128,11 @@ namespace EMStudio void RenderPlugin::CleanEMStudioActors() { // get rid of the actors - const uint32 numActors = mActors.size(); - for (uint32 i = 0; i < numActors; ++i) + for (EMStudioRenderActor* mActor : mActors) { - if (mActors[i]) + if (mActor) { - delete mActors[i]; + delete mActor; } } mActors.clear(); @@ -152,8 +151,8 @@ namespace EMStudio } // get the index of the emstudio actor, we can be sure it is valid as else the emstudioActor pointer would be nullptr already - const uint32 index = FindEMStudioActorIndex(emstudioActor); - MCORE_ASSERT(index != MCORE_INVALIDINDEX32); + const size_t index = FindEMStudioActorIndex(emstudioActor); + MCORE_ASSERT(index != InvalidIndex); // get rid of the emstudio actor delete emstudioActor; @@ -167,7 +166,6 @@ namespace EMStudio { // get the current manipulator AZStd::vector* transformationManipulators = GetManager()->GetTransformationManipulators(); - const uint32 numGizmos = transformationManipulators->size(); // init the active manipulator to nullptr MCommon::TransformationManipulator* activeManipulator = nullptr; @@ -175,10 +173,9 @@ namespace EMStudio bool activeManipulatorFound = false; // iterate over all gizmos and search for the hit one that is closest to the camera - for (uint32 i = 0; i < numGizmos; ++i) + for (MCommon::TransformationManipulator* currentManipulator : *transformationManipulators) { // get the current manipulator and check if it exists - MCommon::TransformationManipulator* currentManipulator = transformationManipulators->at(i); if (currentManipulator == nullptr || currentManipulator->GetIsVisible() == false) { continue; @@ -275,8 +272,8 @@ namespace EMStudio const AZ::Vector3 jointPosition = pose->GetWorldSpaceTransform(joint->GetNodeIndex()).mPosition; aabb.AddPoint(jointPosition); - const AZ::u32 childCount = joint->GetNumChildNodes(); - for (AZ::u32 i = 0; i < childCount; ++i) + const size_t childCount = joint->GetNumChildNodes(); + for (size_t i = 0; i < childCount; ++i) { EMotionFX::Node* childJoint = skeleton->GetNode(joint->GetChildIndex(i)); const AZ::Vector3 childPosition = pose->GetWorldSpaceTransform(childJoint->GetNodeIndex()).mPosition; @@ -314,80 +311,49 @@ namespace EMStudio } // try to locate the helper actor for a given instance - RenderPlugin::EMStudioRenderActor* RenderPlugin::FindEMStudioActor(EMotionFX::ActorInstance* actorInstance, bool doubleCheckInstance) + RenderPlugin::EMStudioRenderActor* RenderPlugin::FindEMStudioActor(const EMotionFX::ActorInstance* actorInstance, bool doubleCheckInstance) const { - // get the number of emstudio actors and iterate through them - const uint32 numEMStudioRenderActors = mActors.size(); - for (uint32 i = 0; i < numEMStudioRenderActors; ++i) + const auto foundActor = AZStd::find_if(begin(mActors), end(mActors), [actorInstance, doubleCheckInstance](const EMStudioRenderActor* renderActor) { - EMStudioRenderActor* EMStudioRenderActor = mActors[i]; - // is the parent actor of the instance the same as the one in the emstudio actor? - if (EMStudioRenderActor->mActor == actorInstance->GetActor()) + if (renderActor->mActor == actorInstance->GetActor()) { // double check if the actor instance is in the actor instance array inside the emstudio actor if (doubleCheckInstance) { // now double check if the actor instance really is in the array of instances of this emstudio actor - const uint32 numActorInstances = EMStudioRenderActor->mActorInstances.size(); - for (uint32 a = 0; a < numActorInstances; ++a) - { - if (EMStudioRenderActor->mActorInstances[a] == actorInstance) - { - return EMStudioRenderActor; - } - } - } - else - { - return EMStudioRenderActor; + const auto foundActorInstance = AZStd::find(begin(renderActor->mActorInstances), end(renderActor->mActorInstances), actorInstance); + return foundActorInstance != end(renderActor->mActorInstances); } + return true; } - } - - return nullptr; + return false; + }); + return foundActor != end(mActors) ? *foundActor : nullptr; } // try to locate the helper actor for a given one - RenderPlugin::EMStudioRenderActor* RenderPlugin::FindEMStudioActor(EMotionFX::Actor* actor) + RenderPlugin::EMStudioRenderActor* RenderPlugin::FindEMStudioActor(const EMotionFX::Actor* actor) const { if (!actor) { return nullptr; } - const uint32 numEMStudioRenderActors = mActors.size(); - for (uint32 i = 0; i < numEMStudioRenderActors; ++i) + const auto foundActor = AZStd::find_if(begin(mActors), end(mActors), [match = actor](const EMStudioRenderActor* actor) { - EMStudioRenderActor* EMStudioRenderActor = mActors[i]; - - if (EMStudioRenderActor->mActor == actor) - { - return EMStudioRenderActor; - } - } - - return nullptr; + return actor->mActor == match; + }); + return foundActor != end(mActors) ? *foundActor : nullptr; } // get the index of the given emstudio actor - uint32 RenderPlugin::FindEMStudioActorIndex(EMStudioRenderActor* EMStudioRenderActor) + size_t RenderPlugin::FindEMStudioActorIndex(const EMStudioRenderActor* EMStudioRenderActor) const { - // get the number of emstudio actors and iterate through them - const uint32 numEMStudioRenderActors = mActors.size(); - for (uint32 i = 0; i < numEMStudioRenderActors; ++i) - { - // compare the two emstudio actors and return the current index in case of success - if (EMStudioRenderActor == mActors[i]) - { - return i; - } - } - - // the emstudio actor has not been found - return MCORE_INVALIDINDEX32; + const auto foundActor = AZStd::find(begin(mActors), end(mActors), EMStudioRenderActor); + return foundActor != end(mActors) ? AZStd::distance(begin(mActors), foundActor) : InvalidIndex; } @@ -417,8 +383,8 @@ namespace EMStudio } // 1. Create new emstudio actors - uint32 numActors = EMotionFX::GetActorManager().GetNumActors(); - for (uint32 i = 0; i < numActors; ++i) + size_t numActors = EMotionFX::GetActorManager().GetNumActors(); + for (size_t i = 0; i < numActors; ++i) { // get the current actor and the number of clones EMotionFX::Actor* actor = EMotionFX::GetActorManager().GetActor(i); @@ -438,13 +404,13 @@ namespace EMStudio } } - for (uint32 i = 0; i < mActors.size(); ++i) + for (size_t i = 0; i < mActors.size(); ++i) { EMStudioRenderActor* emstudioActor = mActors[i]; EMotionFX::Actor* actor = emstudioActor->mActor; bool found = false; - for (uint32 j = 0; j < numActors; ++j) + for (size_t j = 0; j < numActors; ++j) { EMotionFX::Actor* curActor = EMotionFX::GetActorManager().GetActor(j); if (actor == curActor) @@ -462,8 +428,8 @@ namespace EMStudio } // 3. Relink the actor instances with the emstudio actors - const uint32 numActorInstances = EMotionFX::GetActorManager().GetNumActorInstances(); - for (uint32 i = 0; i < numActorInstances; ++i) + const size_t numActorInstances = EMotionFX::GetActorManager().GetNumActorInstances(); + for (size_t i = 0; i < numActorInstances; ++i) { EMotionFX::ActorInstance* actorInstance = EMotionFX::GetActorManager().GetActorInstance(i); EMotionFX::Actor* actor = actorInstance->GetActor(); @@ -476,9 +442,8 @@ namespace EMStudio if (!emstudioActor) { - for (uint32 j = 0; j < mActors.size(); ++j) + for (EMStudioRenderActor* currentEMStudioActor : mActors) { - EMStudioRenderActor* currentEMStudioActor = mActors[j]; if (actor == currentEMStudioActor->mActor) { emstudioActor = currentEMStudioActor; @@ -503,12 +468,12 @@ namespace EMStudio // 4. Unlink invalid actor instances from the emstudio actors for (EMStudioRenderActor* emstudioActor : mActors) { - for (uint32 j = 0; j < emstudioActor->mActorInstances.size();) + for (size_t j = 0; j < emstudioActor->mActorInstances.size();) { EMotionFX::ActorInstance* emstudioActorInstance = emstudioActor->mActorInstances[j]; bool found = false; - for (uint32 k = 0; k < numActorInstances; ++k) + for (size_t k = 0; k < numActorInstances; ++k) { if (emstudioActorInstance == EMotionFX::GetActorManager().GetActorInstance(k)) { @@ -566,14 +531,11 @@ namespace EMStudio RenderPlugin::EMStudioRenderActor::~EMStudioRenderActor() { // get the number of actor instances and iterate through them - const uint32 numActorInstances = mActorInstances.size(); - for (uint32 i = 0; i < numActorInstances; ++i) + for (EMotionFX::ActorInstance* actorInstance : mActorInstances) { - EMotionFX::ActorInstance* actorInstance = mActorInstances[i]; - // only delete the actor instance in case it is still inside the actor manager // in case it is not present there anymore this means an undo command has already deleted it - if (EMotionFX::GetActorManager().FindActorInstanceIndex(actorInstance) != MCORE_INVALIDINDEX32) + if (EMotionFX::GetActorManager().FindActorInstanceIndex(actorInstance) != InvalidIndex) { //actorInstance->Destroy(); } @@ -587,13 +549,9 @@ namespace EMStudio // only delete the actor in case it is still inside the actor manager // in case it is not present there anymore this means an undo command has already deleted it - if (EMotionFX::GetActorManager().FindActorIndex(mActor) != MCORE_INVALIDINDEX32) - { - //mActor->Destroy(); - } - // in case the actor is not valid anymore make sure to unselect it to avoid bad pointers - else + if (EMotionFX::GetActorManager().FindActorIndex(mActor) == InvalidIndex) { + // in case the actor is not valid anymore make sure to unselect it to avoid bad pointers CommandSystem::SelectionList& selection = GetCommandManager()->GetCurrentSelection(); selection.RemoveActor(mActor); } @@ -810,8 +768,8 @@ namespace EMStudio void RenderPlugin::UpdateActorInstances(float timePassedInSeconds) { - const uint32 numActorInstances = EMotionFX::GetActorManager().GetNumActorInstances(); - for (uint32 i = 0; i < numActorInstances; ++i) + const size_t numActorInstances = EMotionFX::GetActorManager().GetNumActorInstances(); + for (size_t i = 0; i < numActorInstances; ++i) { EMotionFX::ActorInstance* actorInstance = EMotionFX::GetActorManager().GetActorInstance(i); @@ -889,8 +847,8 @@ namespace EMStudio } // get the number of actor instances and iterate through them - const uint32 numActorInstances = EMotionFX::GetActorManager().GetNumActorInstances(); - for (uint32 i = 0; i < numActorInstances; ++i) + const size_t numActorInstances = EMotionFX::GetActorManager().GetNumActorInstances(); + for (size_t i = 0; i < numActorInstances; ++i) { // get the actor instance and update its transformations and meshes EMotionFX::ActorInstance* actorInstance = EMotionFX::GetActorManager().GetActorInstance(i); @@ -1045,10 +1003,10 @@ namespace EMStudio { // get the current selection CommandSystem::SelectionList& selectionList = GetCommandManager()->GetCurrentSelection(); - const uint32 numSelectedActorInstances = selectionList.GetNumSelectedActorInstances(); + const size_t numSelectedActorInstances = selectionList.GetNumSelectedActorInstances(); // iterate through the actor instances and reset their trajectory path - for (uint32 i = 0; i < numSelectedActorInstances; ++i) + for (size_t i = 0; i < numSelectedActorInstances; ++i) { // get the actor instance and find the corresponding trajectory path EMotionFX::ActorInstance* actorInstance = selectionList.GetActorInstance(i); @@ -1080,7 +1038,7 @@ namespace EMStudio } else { - const uint32 numParticles = trajectoryPath->mTraceParticles.size(); + const size_t numParticles = trajectoryPath->mTraceParticles.size(); const EMotionFX::Transform& oldWorldTM = trajectoryPath->mTraceParticles[numParticles - 1].mWorldTM; const AZ::Vector3& oldPos = oldWorldTM.mPosition; @@ -1141,8 +1099,8 @@ namespace EMStudio RenderViewWidget* widget = GetActiveViewWidget(); RenderOptions* renderOptions = GetRenderOptions(); - const AZStd::unordered_set& visibleJointIndices = GetManager()->GetVisibleJointIndices(); - const AZStd::unordered_set& selectedJointIndices = GetManager()->GetSelectedJointIndices(); + const AZStd::unordered_set& visibleJointIndices = GetManager()->GetVisibleJointIndices(); + const AZStd::unordered_set& selectedJointIndices = GetManager()->GetSelectedJointIndices(); // render the AABBs if (widget->GetRenderFlag(RenderViewWidget::RENDER_AABB)) @@ -1219,12 +1177,12 @@ namespace EMStudio // iterate through all enabled nodes const EMotionFX::Pose* pose = actorInstance->GetTransformData()->GetCurrentPose(); - const uint32 geomLODLevel = actorInstance->GetLODLevel(); - const uint32 numEnabled = actorInstance->GetNumEnabledNodes(); - for (uint32 i = 0; i < numEnabled; ++i) + const size_t geomLODLevel = actorInstance->GetLODLevel(); + const size_t numEnabled = actorInstance->GetNumEnabledNodes(); + for (size_t i = 0; i < numEnabled; ++i) { EMotionFX::Node* node = emstudioActor->mActor->GetSkeleton()->GetNode(actorInstance->GetEnabledNode(i)); - const AZ::u32 nodeIndex = node->GetNodeIndex(); + const size_t nodeIndex = node->GetNodeIndex(); EMotionFX::Mesh* mesh = emstudioActor->mActor->GetMesh(geomLODLevel, nodeIndex); renderUtil->ResetCurrentMesh(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.h index f55604b38c..a99a64ef68 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.h @@ -106,9 +106,9 @@ namespace EMStudio PluginOptions* GetOptions() override { return &mRenderOptions; } // render actors - EMStudioRenderActor* FindEMStudioActor(EMotionFX::ActorInstance* actorInstance, bool doubleCheckInstance = true); - EMStudioRenderActor* FindEMStudioActor(EMotionFX::Actor* actor); - uint32 FindEMStudioActorIndex(EMStudioRenderActor* EMStudioRenderActor); + EMStudioRenderActor* FindEMStudioActor(const EMotionFX::ActorInstance* actorInstance, bool doubleCheckInstance = true) const; + EMStudioRenderActor* FindEMStudioActor(const EMotionFX::Actor* actor) const; + size_t FindEMStudioActorIndex(const EMStudioRenderActor* EMStudioRenderActor) const; void AddEMStudioActor(EMStudioRenderActor* emstudioActor); bool DestroyEMStudioActor(EMotionFX::Actor* actor); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderUpdateCallback.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderUpdateCallback.cpp index 24b4471280..3c146c528b 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderUpdateCallback.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderUpdateCallback.cpp @@ -90,7 +90,7 @@ namespace EMStudio } else { - const uint32 numParticles = trajectoryPath->mTraceParticles.size(); + const size_t numParticles = trajectoryPath->mTraceParticles.size(); const EMotionFX::Transform& oldGlobalTM = trajectoryPath->mTraceParticles[numParticles - 1].mWorldTM; const AZ::Vector3& oldPos = oldGlobalTM.mPosition; @@ -160,8 +160,8 @@ namespace EMStudio RenderViewWidget* widget = mPlugin->GetActiveViewWidget(); RenderOptions* renderOptions = mPlugin->GetRenderOptions(); - const AZStd::unordered_set& visibleJointIndices = GetManager()->GetVisibleJointIndices(); - const AZStd::unordered_set& selectedJointIndices = GetManager()->GetSelectedJointIndices(); + const AZStd::unordered_set& visibleJointIndices = GetManager()->GetVisibleJointIndices(); + const AZStd::unordered_set& selectedJointIndices = GetManager()->GetSelectedJointIndices(); // render the AABBs if (widget->GetRenderFlag(RenderViewWidget::RENDER_AABB)) @@ -216,9 +216,9 @@ namespace EMStudio { // iterate through all enabled nodes const EMotionFX::Pose* pose = actorInstance->GetTransformData()->GetCurrentPose(); - const uint32 geomLODLevel = actorInstance->GetLODLevel(); - const uint32 numEnabled = actorInstance->GetNumEnabledNodes(); - for (uint32 i = 0; i < numEnabled; ++i) + const size_t geomLODLevel = actorInstance->GetLODLevel(); + const size_t numEnabled = actorInstance->GetNumEnabledNodes(); + for (size_t i = 0; i < numEnabled; ++i) { EMotionFX::Node* node = emstudioActor->mActor->GetSkeleton()->GetNode(actorInstance->GetEnabledNode(i)); EMotionFX::Mesh* mesh = emstudioActor->mActor->GetMesh(geomLODLevel, node->GetNodeIndex()); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderWidget.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderWidget.cpp index b123f62ac5..56d27222bb 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderWidget.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderWidget.cpp @@ -256,10 +256,8 @@ namespace EMStudio const AZStd::vector* transformationManipulators = GetManager()->GetTransformationManipulators(); // render all visible gizmos - const uint32 numGizmos = transformationManipulators->size(); - for (uint32 i = 0; i < numGizmos; ++i) + for (MCommon::TransformationManipulator* activeManipulator : *transformationManipulators) { - MCommon::TransformationManipulator* activeManipulator = transformationManipulators->at(i); if (activeManipulator == nullptr) { continue; @@ -527,10 +525,10 @@ namespace EMStudio // handle visual mouse selection if (EMStudio::GetCommandManager()->GetLockSelection() == false && gizmoHit == false) // avoid selection operations when there is only one actor instance { - AZ::u32 editorActorInstanceCount = 0; + size_t editorActorInstanceCount = 0; const EMotionFX::ActorManager& actorManager = EMotionFX::GetActorManager(); - const AZ::u32 totalActorInstanceCount = actorManager.GetNumActorInstances(); - for (AZ::u32 i = 0; i < totalActorInstanceCount; ++i) + const size_t totalActorInstanceCount = actorManager.GetNumActorInstances(); + for (size_t i = 0; i < totalActorInstanceCount; ++i) { const EMotionFX::ActorInstance* actorInstance = actorManager.GetActorInstance(i); if (!actorInstance->GetIsOwnedByRuntime()) @@ -557,8 +555,8 @@ namespace EMStudio const MCore::Ray ray = mCamera->Unproject(mousePosX, mousePosY); // get the number of actor instances and iterate through them - const uint32 numActorInstances = EMotionFX::GetActorManager().GetNumActorInstances(); - for (uint32 i = 0; i < numActorInstances; ++i) + const size_t numActorInstances = EMotionFX::GetActorManager().GetNumActorInstances(); + for (size_t i = 0; i < numActorInstances; ++i) { EMotionFX::ActorInstance* actorInstance = EMotionFX::GetActorManager().GetActorInstance(i); if (actorInstance->GetIsVisible() == false || actorInstance->GetRender() == false || actorInstance->GetIsUsedForVisualization() || actorInstance->GetIsOwnedByRuntime()) @@ -622,8 +620,8 @@ namespace EMStudio if (ctrlPressed) { // add the old selection to the selected actor instances (selection mode = add) - const uint32 numSelectedActorInstances = selection.GetNumSelectedActorInstances(); - for (uint32 i = 0; i < numSelectedActorInstances; ++i) + const size_t numSelectedActorInstances = selection.GetNumSelectedActorInstances(); + for (size_t i = 0; i < numSelectedActorInstances; ++i) { mSelectedActorInstances.emplace_back(selection.GetActorInstance(i)); } @@ -922,8 +920,8 @@ namespace EMStudio AZ::Vector3 actorInstancePos; EMotionFX::Actor* followActor = followInstance->GetActor(); - const uint32 motionExtractionNodeIndex = followActor->GetMotionExtractionNodeIndex(); - if (motionExtractionNodeIndex != MCORE_INVALIDINDEX32) + const size_t motionExtractionNodeIndex = followActor->GetMotionExtractionNodeIndex(); + if (motionExtractionNodeIndex != InvalidIndex) { actorInstancePos = followInstance->GetWorldSpaceTransform().mPosition; RenderPlugin::EMStudioRenderActor* emstudioActor = mPlugin->FindEMStudioActor(followActor); @@ -1007,14 +1005,10 @@ namespace EMStudio } AZStd::vector* transformationManipulators = GetManager()->GetTransformationManipulators(); - const uint32 numGizmos = transformationManipulators->size(); // render all visible gizmos - for (uint32 i = 0; i < numGizmos; ++i) + for (MCommon::TransformationManipulator* activeManipulator : *transformationManipulators) { - // update the gizmos - MCommon::TransformationManipulator* activeManipulator = transformationManipulators->at(i); - // update the gizmos if there is an active manipulator if (activeManipulator == nullptr) { @@ -1046,11 +1040,9 @@ namespace EMStudio } // render custom triangles - const uint32 numTriangles = mTriangles.size(); - for (uint32 i = 0; i < numTriangles; ++i) + for (const Triangle& curTri : mTriangles) { - const Triangle& curTri = mTriangles[i]; - renderUtil->AddTriangle(curTri.mPosA, curTri.mPosB, curTri.mPosC, curTri.mNormalA, curTri.mNormalB, curTri.mNormalC, curTri.mColor); // TODO: make renderutil use uint32 colors instead + renderUtil->AddTriangle(curTri.mPosA, curTri.mPosB, curTri.mPosC, curTri.mNormalA, curTri.mNormalB, curTri.mNormalC, curTri.mColor); // TODO: make renderutil use uint32 colors instead } ClearTriangles(); @@ -1068,8 +1060,8 @@ namespace EMStudio } // render all custom plugin visuals - const uint32 numPlugins = GetPluginManager()->GetNumActivePlugins(); - for (uint32 i = 0; i < numPlugins; ++i) + const size_t numPlugins = GetPluginManager()->GetNumActivePlugins(); + for (size_t i = 0; i < numPlugins; ++i) { EMStudioPlugin* plugin = GetPluginManager()->GetActivePlugin(i); EMStudioPlugin::RenderInfo renderInfo(renderUtil, mCamera, mWidth, mHeight); @@ -1131,8 +1123,8 @@ namespace EMStudio ///// EMotionFX::GetEMotionFX().Update(0.0f); // render - const uint32 numActorInstances = EMotionFX::GetActorManager().GetNumActorInstances(); - for (uint32 i = 0; i < numActorInstances; ++i) + const size_t numActorInstances = EMotionFX::GetActorManager().GetNumActorInstances(); + for (size_t i = 0; i < numActorInstances; ++i) { EMotionFX::ActorInstance* actorInstance = EMotionFX::GetActorManager().GetActorInstance(i); if (actorInstance->GetRender() && actorInstance->GetIsVisible() && actorInstance->GetIsOwnedByRuntime() == false) diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/ResetSettingsDialog.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/ResetSettingsDialog.cpp index 94b5fadd79..2f45a89ea2 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/ResetSettingsDialog.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/ResetSettingsDialog.cpp @@ -29,8 +29,8 @@ namespace EMStudio template bool HasEntityInEditor(const ManagerType& manager, const GetNumFunc& getNumEntitiesFunc, const GetEntityFunc& getEntityFunc) { - const uint32 numEntities = (manager.*getNumEntitiesFunc)(); - for (uint32 i = 0; i < numEntities; ++i) + const size_t numEntities = (manager.*getNumEntitiesFunc)(); + for (size_t i = 0; i < numEntities; ++i) { const auto& entity = (manager.*getEntityFunc)(i); if (!entity->GetIsOwnedByRuntime()) diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/Workspace.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/Workspace.cpp index 9919c4cbb3..a791b17e25 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/Workspace.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/Workspace.cpp @@ -139,15 +139,15 @@ namespace EMStudio ActivationIndicesByActorInstance activationIndicesByActorInstance; int32 commandIndex = 0; - const uint32 numActorInstances = EMotionFX::GetActorManager().GetNumActorInstances(); + const size_t numActorInstances = EMotionFX::GetActorManager().GetNumActorInstances(); // actors - const uint32 numActors = EMotionFX::GetActorManager().GetNumActors(); - for (uint32 i = 0; i < numActors; ++i) + const size_t numActors = EMotionFX::GetActorManager().GetNumActors(); + for (size_t i = 0; i < numActors; ++i) { EMotionFX::Actor* actor = EMotionFX::GetActorManager().GetActor(i); - for (uint32 j = 0; j < numActorInstances; ++j) + for (size_t j = 0; j < numActorInstances; ++j) { EMotionFX::ActorInstance* actorInstance = EMotionFX::GetActorManager().GetActorInstance(j); if (actorInstance->GetActor() != actor) @@ -184,7 +184,7 @@ namespace EMStudio } // attachments - for (uint32 i = 0; i < numActorInstances; ++i) + for (size_t i = 0; i < numActorInstances; ++i) { EMotionFX::ActorInstance* actorInstance = EMotionFX::GetActorManager().GetActorInstance(i); @@ -197,23 +197,23 @@ namespace EMStudio { EMotionFX::Attachment* attachment = actorInstance->GetSelfAttachment(); EMotionFX::ActorInstance* attachedToActorInstance = attachment->GetAttachToActorInstance(); - const uint32 attachedToInstanceIndex = EMotionFX::GetActorManager().FindActorInstanceIndex(attachedToActorInstance); - const uint32 attachtmentInstanceIndex = EMotionFX::GetActorManager().FindActorInstanceIndex(actorInstance); + const size_t attachedToInstanceIndex = EMotionFX::GetActorManager().FindActorInstanceIndex(attachedToActorInstance); + const size_t attachtmentInstanceIndex = EMotionFX::GetActorManager().FindActorInstanceIndex(actorInstance); if (actorInstance->GetIsSkinAttachment()) { - commandString = AZStd::string::format("AddDeformableAttachment -attachmentIndex %d -attachToIndex %d\n", attachtmentInstanceIndex, attachedToInstanceIndex); + commandString = AZStd::string::format("AddDeformableAttachment -attachmentIndex %zu -attachToIndex %zu\n", attachtmentInstanceIndex, attachedToInstanceIndex); commands += commandString; ++commandIndex; } else { EMotionFX::AttachmentNode* attachmentSingleNode = static_cast(attachment); - const uint32 attachedToNodeIndex = attachmentSingleNode->GetAttachToNodeIndex(); + const size_t attachedToNodeIndex = attachmentSingleNode->GetAttachToNodeIndex(); EMotionFX::Actor* attachedToActor = attachedToActorInstance->GetActor(); EMotionFX::Node* attachedToNode = attachedToActor->GetSkeleton()->GetNode(attachedToNodeIndex); - commandString = AZStd::string::format("AddAttachment -attachmentIndex %d -attachToIndex %d -attachToNode \"%s\"\n", attachtmentInstanceIndex, attachedToInstanceIndex, attachedToNode->GetName()); + commandString = AZStd::string::format("AddAttachment -attachmentIndex %zu -attachToIndex %zu -attachToNode \"%s\"\n", attachtmentInstanceIndex, attachedToInstanceIndex, attachedToNode->GetName()); commands += commandString; ++commandIndex; } @@ -221,9 +221,9 @@ namespace EMStudio } // motion sets - const uint32 numRootMotionSets = EMotionFX::GetMotionManager().CalcNumRootMotionSets(); + const size_t numRootMotionSets = EMotionFX::GetMotionManager().CalcNumRootMotionSets(); AZStd::unordered_set motionsInMotionSets; - for (uint32 i = 0; i < numRootMotionSets; ++i) + for (size_t i = 0; i < numRootMotionSets; ++i) { EMotionFX::MotionSet* motionSet = EMotionFX::GetMotionManager().FindRootMotionSet(i); @@ -255,8 +255,8 @@ namespace EMStudio } // motions that are not in the above motion sets - const uint32 numMotions = EMotionFX::GetMotionManager().GetNumMotions(); - for (uint32 i = 0; i < numMotions; ++i) + const size_t numMotions = EMotionFX::GetMotionManager().GetNumMotions(); + for (size_t i = 0; i < numMotions; ++i) { EMotionFX::Motion* motion = EMotionFX::GetMotionManager().GetMotion(i); @@ -277,8 +277,8 @@ namespace EMStudio // We need to avoid storing two times the same anim graph. This could happen if the anim graph was loaded from a reference // node. We need to integrate the asset system into the AnimGraphManager AZStd::unordered_set animGraphFilenames; - const uint32 numAnimGraphs = EMotionFX::GetAnimGraphManager().GetNumAnimGraphs(); - for (uint32 i = 0; i < numAnimGraphs; ++i) + const size_t numAnimGraphs = EMotionFX::GetAnimGraphManager().GetNumAnimGraphs(); + for (size_t i = 0; i < numAnimGraphs; ++i) { EMotionFX::AnimGraph* animGraph = EMotionFX::GetAnimGraphManager().GetAnimGraph(i); @@ -317,7 +317,7 @@ namespace EMStudio } // activate anim graph for each actor instance - for (uint32 i = 0; i < numActorInstances; ++i) + for (size_t i = 0; i < numActorInstances; ++i) { EMotionFX::ActorInstance* actorInstance = EMotionFX::GetActorManager().GetActorInstance(i); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/ActionHistory/ActionHistoryCallback.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/ActionHistory/ActionHistoryCallback.cpp index e99838b7bb..ac23dd489b 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/ActionHistory/ActionHistoryCallback.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/ActionHistory/ActionHistoryCallback.cpp @@ -42,8 +42,8 @@ namespace EMStudio if (MCore::GetLogManager().GetLogLevels() & MCore::LogCallback::LOGLEVEL_DEBUG) { mTempString = command->GetName(); - const uint32 numParameters = commandLine.GetNumParameters(); - for (uint32 i = 0; i < numParameters; ++i) + const size_t numParameters = commandLine.GetNumParameters(); + for (size_t i = 0; i < numParameters; ++i) { mTempString += " -"; mTempString += commandLine.GetParameterName(i); @@ -130,8 +130,8 @@ namespace EMStudio MCORE_UNUSED(commandLine); mTempString = MCore::CommandManager::CommandHistoryEntry::ToString(group, command, mIndex++).c_str(); - mList->insertItem(historyIndex, new QListWidgetItem(mTempString.c_str(), mList)); - mList->setCurrentRow(historyIndex); + mList->insertItem(aznumeric_caster(historyIndex), new QListWidgetItem(mTempString.c_str(), mList)); + mList->setCurrentRow(aznumeric_caster(historyIndex)); } // Remove an item from the history. @@ -168,7 +168,7 @@ namespace EMStudio mList->setCurrentRow(aznumeric_caster(index)); // Get the current history index. - const uint32 historyIndex = GetCommandManager()->GetHistoryIndex(); + const size_t historyIndex = GetCommandManager()->GetHistoryIndex(); if (historyIndex == InvalidIndex) { AZStd::string outResult; @@ -189,8 +189,8 @@ namespace EMStudio else if (historyIndex > index) // if we need to perform undo's { AZStd::string outResult; - const int32 numUndos = historyIndex - index; - for (int32 i = 0; i < numUndos; ++i) + const ptrdiff_t numUndos = historyIndex - index; + for (ptrdiff_t i = 0; i < numUndos; ++i) { // try to undo outResult.clear(); @@ -207,8 +207,8 @@ namespace EMStudio else if (historyIndex < index) // if we need to redo commands { AZStd::string outResult; - const int32 numRedos = index - historyIndex; - for (int32 i = 0; i < numRedos; ++i) + const ptrdiff_t numRedos = index - historyIndex; + for (ptrdiff_t i = 0; i < numRedos; ++i) { outResult.clear(); const bool result = GetCommandManager()->Redo(outResult); @@ -223,7 +223,7 @@ namespace EMStudio } const int numCommands = static_cast(GetCommandManager()->GetNumHistoryItems()); - for (int i = index; i < numCommands; ++i) + for (int i = aznumeric_caster(index); i < numCommands; ++i) { mList->item(i)->setForeground(m_darkenedBrush); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphActionManager.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphActionManager.cpp index f545873106..9a4170d1b0 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphActionManager.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphActionManager.cpp @@ -210,8 +210,8 @@ namespace EMStudio defaultPlayBackInfo->mBlendOutTime = 0.0f; commandParameters = CommandSystem::CommandPlayMotion::PlayBackInfoToCommandParameters(defaultPlayBackInfo); - const AZ::u32 motionIndex = EMotionFX::GetMotionManager().FindMotionIndexByName(motion->GetName()); - commandString = AZStd::string::format("Select -motionIndex %d", motionIndex); + const size_t motionIndex = EMotionFX::GetMotionManager().FindMotionIndexByName(motion->GetName()); + commandString = AZStd::string::format("Select -motionIndex %zu", motionIndex); commandGroup.AddCommandString(commandString); commandString = AZStd::string::format("PlayMotion -filename \"%s\" %s", motion->GetFileName(), commandParameters.c_str()); @@ -472,8 +472,8 @@ namespace EMStudio const EMotionFX::MotionManager& motionManager = EMotionFX::GetMotionManager(); // In case no motion set was selected yet, use the first available. The activate graph callback will update the UI. - const AZ::u32 numMotionSets = motionManager.GetNumMotionSets(); - for (AZ::u32 i = 0; i < numMotionSets; ++i) + const size_t numMotionSets = motionManager.GetNumMotionSets(); + for (size_t i = 0; i < numMotionSets; ++i) { EMotionFX::MotionSet* currentMotionSet = motionManager.GetMotionSet(i); if (!currentMotionSet->GetIsOwnedByRuntime()) @@ -494,7 +494,7 @@ namespace EMStudio void AnimGraphActionManager::ActivateGraphForSelectedActors(EMotionFX::AnimGraph* animGraph, EMotionFX::MotionSet* motionSet) { const CommandSystem::SelectionList& selectionList = GetCommandManager()->GetCurrentSelection(); - const uint32 numActorInstances = selectionList.GetNumSelectedActorInstances(); + const size_t numActorInstances = selectionList.GetNumSelectedActorInstances(); if (numActorInstances == 0) { @@ -507,7 +507,7 @@ namespace EMStudio commandGroup.AddCommandString("RecorderClear -force true"); // Activate the anim graph each selected actor instance. - for (uint32 i = 0; i < numActorInstances; ++i) + for (size_t i = 0; i < numActorInstances; ++i) { EMotionFX::ActorInstance* actorInstance = selectionList.GetActorInstance(i); if (actorInstance->GetIsOwnedByRuntime()) diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphEditor.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphEditor.cpp index f02c8ed0bf..f6e308f07b 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphEditor.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphEditor.cpp @@ -125,7 +125,7 @@ namespace EMotionFX EMotionFX::MotionSet* AnimGraphEditor::GetSelectedMotionSet() { - const AZ::Outcome motionSetIndex = GetMotionSetIndex(m_motionSetComboBox->currentIndex()); + const AZ::Outcome motionSetIndex = GetMotionSetIndex(m_motionSetComboBox->currentIndex()); if (motionSetIndex.IsSuccess()) { return EMotionFX::GetMotionManager().GetMotionSet(motionSetIndex.GetValue()); @@ -149,8 +149,8 @@ namespace EMotionFX m_motionSetComboBox->clear(); // add each motion set name - const uint32 numMotionSets = EMotionFX::GetMotionManager().GetNumMotionSets(); - for (uint32 i = 0; i < numMotionSets; ++i) + const size_t numMotionSets = EMotionFX::GetMotionManager().GetNumMotionSets(); + for (size_t i = 0; i < numMotionSets; ++i) { EMotionFX::MotionSet* motionSet = EMotionFX::GetMotionManager().GetMotionSet(i); if (motionSet->GetIsOwnedByRuntime()) @@ -163,7 +163,7 @@ namespace EMotionFX // get the current selection list and the number of actor instances selected const CommandSystem::SelectionList& selectionList = CommandSystem::GetCommandManager()->GetCurrentSelection(); - const uint32 numActorInstances = selectionList.GetNumSelectedActorInstances(); + const size_t numActorInstances = selectionList.GetNumSelectedActorInstances(); // if actor instances are selected, set the used motion set if (numActorInstances > 0) @@ -172,7 +172,7 @@ namespace EMotionFX // this is used to check if multiple motion sets are used AZStd::vector usedMotionSets; AZStd::vector usedAnimGraphs; - for (uint32 i = 0; i < numActorInstances; ++i) + for (size_t i = 0; i < numActorInstances; ++i) { EMotionFX::ActorInstance* actorInstance = selectionList.GetActorInstance(i); if (actorInstance->GetIsOwnedByRuntime()) @@ -301,7 +301,7 @@ namespace EMotionFX { // get the current selection list and the number of actor instances selected const CommandSystem::SelectionList& selectionList = CommandSystem::GetCommandManager()->GetCurrentSelection(); - const uint32 numActorInstances = selectionList.GetNumSelectedActorInstances(); + const size_t numActorInstances = selectionList.GetNumSelectedActorInstances(); AnimGraphEditor::m_lastMotionSetText = m_motionSetComboBox->itemText(index); // if no one actor instance is selected, the combo box has no effect @@ -310,7 +310,7 @@ namespace EMotionFX return; } - const AZ::Outcome motionSetIndex = GetMotionSetIndex(index); + const AZ::Outcome motionSetIndex = GetMotionSetIndex(index); EMotionFX::MotionSet* motionSet = nullptr; if (motionSetIndex.IsSuccess()) @@ -323,7 +323,7 @@ namespace EMotionFX // update the motion set on each actor instance if one anim graph is activated AZStd::string commandString; - for (uint32 i = 0; i < numActorInstances; ++i) + for (size_t i = 0; i < numActorInstances; ++i) { // get the actor instance from the selection list and the anim graph instance EMotionFX::ActorInstance* actorInstance = selectionList.GetActorInstance(i); @@ -401,12 +401,12 @@ namespace EMotionFX } } - AZ::Outcome AnimGraphEditor::GetMotionSetIndex(int comboBoxIndex) const + AZ::Outcome AnimGraphEditor::GetMotionSetIndex(int comboBoxIndex) const { - const uint32 targetEditorMotionSetIndex = comboBoxIndex; - uint32 currentEditorMotionSet = 0; - const uint32 numMotionSets = EMotionFX::GetMotionManager().GetNumMotionSets(); - for (uint32 i = 0; i < numMotionSets; ++i) + const size_t targetEditorMotionSetIndex = comboBoxIndex; + size_t currentEditorMotionSet = 0; + const size_t numMotionSets = EMotionFX::GetMotionManager().GetNumMotionSets(); + for (size_t i = 0; i < numMotionSets; ++i) { const EMotionFX::MotionSet* motionSet = EMotionFX::GetMotionManager().GetMotionSet(i); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphEditor.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphEditor.h index be1e3745a9..1d17c46815 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphEditor.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphEditor.h @@ -51,7 +51,7 @@ namespace EMotionFX void OnMotionSetChanged(int index); private: - AZ::Outcome GetMotionSetIndex(int comboBoxIndex) const; + AZ::Outcome GetMotionSetIndex(int comboBoxIndex) const; MCORE_DEFINECOMMANDCALLBACK(UpdateMotionSetComboBoxCallback) diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphModel.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphModel.cpp index 36b915a5ce..6e68a761de 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphModel.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphModel.cpp @@ -152,8 +152,8 @@ namespace EMStudio // Since the UI could be loaded after anim graphs are added to the manager, we need to pull all the current ones // and add them to the model - const uint32 numAnimGraphs = EMotionFX::GetAnimGraphManager().GetNumAnimGraphs(); - for (uint32 i = 0; i < numAnimGraphs; ++i) + const size_t numAnimGraphs = EMotionFX::GetAnimGraphManager().GetNumAnimGraphs(); + for (size_t i = 0; i < numAnimGraphs; ++i) { EMotionFX::AnimGraph* animGraph = EMotionFX::GetAnimGraphManager().GetAnimGraph(i); if (!animGraph->GetIsOwnedByRuntime() && !animGraph->GetIsOwnedByAsset()) @@ -906,7 +906,7 @@ namespace EMStudio EMotionFX::AnimGraphInstance* animGraphInstance = modelItemData->m_animGraphInstance; EMotionFX::AnimGraphStateMachine* rootStateMachine = referencedAnimGraph->GetRootStateMachine(); - const uint32 rowCount = rootStateMachine->GetNumConnections() + rootStateMachine->GetNumChildNodes() + static_cast(rootStateMachine->GetNumTransitions()); + const int rowCount = aznumeric_caster(rootStateMachine->GetNumConnections() + rootStateMachine->GetNumChildNodes() + rootStateMachine->GetNumTransitions()); if (rowCount > 0) { const QModelIndex referenceNodeModelIndex = createIndex(modelItemData->m_row, 0, modelItemData); @@ -977,15 +977,15 @@ namespace EMStudio } int childRow = 0; - const uint32 connectionCount = node->GetNumConnections(); - for (uint32 i = 0; i < connectionCount; ++i) + const int connectionCount = aznumeric_caster(node->GetNumConnections()); + for (int i = 0; i < connectionCount; ++i) { m_modelItemDataSet.emplace(new ModelItemData(node->GetConnection(i), animGraphInstance, currentModelItemData, childRow + i)); } childRow += connectionCount; - const uint32 childNodeCount = node->GetNumChildNodes(); - for (uint32 i = 0; i < childNodeCount; ++i) + const int childNodeCount = aznumeric_caster(node->GetNumChildNodes()); + for (int i = 0; i < childNodeCount; ++i) { RecursivelyAddNode(animGraphInstance, node->GetChildNode(i), currentModelItemData, childRow + i); } @@ -995,12 +995,12 @@ namespace EMStudio if (nodeTypeId == azrtti_typeid()) { EMotionFX::AnimGraphStateMachine* stateMachine = static_cast(node); - const size_t childTransitionCount = stateMachine->GetNumTransitions(); - for (size_t i = 0; i < childTransitionCount; ++i) + const int childTransitionCount = aznumeric_caster(stateMachine->GetNumTransitions()); + for (int i = 0; i < childTransitionCount; ++i) { - AddTransition(animGraphInstance, stateMachine->GetTransition(i), currentModelItemData, childRow + static_cast(i)); + AddTransition(animGraphInstance, stateMachine->GetTransition(i), currentModelItemData, childRow + i); } - childRow += static_cast(childTransitionCount); + childRow += childTransitionCount; } else if (nodeTypeId == azrtti_typeid()) { @@ -1023,26 +1023,26 @@ namespace EMStudio EMotionFX::AnimGraphStateMachine* rootStateMachine = referencedAnimGraph->GetRootStateMachine(); EMotionFX::AnimGraphInstance* referencedAnimGraphInstance = referenceNode->GetReferencedAnimGraphInstance(animGraphInstance); - const uint32 rootConnectionCount = rootStateMachine->GetNumConnections(); - for (uint32 i = 0; i < rootConnectionCount; ++i) + const int rootConnectionCount = aznumeric_caster(rootStateMachine->GetNumConnections()); + for (int i = 0; i < rootConnectionCount; ++i) { m_modelItemDataSet.emplace(new ModelItemData(rootStateMachine->GetConnection(i), referencedAnimGraphInstance, referenceNodeModelItemData, row + i)); } row += rootConnectionCount; - const uint32 rootChildNodeCount = rootStateMachine->GetNumChildNodes(); - for (uint32 i = 0; i < rootChildNodeCount; ++i) + const int rootChildNodeCount = aznumeric_caster(rootStateMachine->GetNumChildNodes()); + for (int i = 0; i < rootChildNodeCount; ++i) { RecursivelyAddNode(referencedAnimGraphInstance, rootStateMachine->GetChildNode(i), referenceNodeModelItemData, row + i); } row += rootChildNodeCount; - const size_t rootChildTransitionCount = rootStateMachine->GetNumTransitions(); - for (size_t i = 0; i < rootChildTransitionCount; ++i) + const int rootChildTransitionCount = aznumeric_caster(rootStateMachine->GetNumTransitions()); + for (int i = 0; i < rootChildTransitionCount; ++i) { - AddTransition(referencedAnimGraphInstance, rootStateMachine->GetTransition(i), referenceNodeModelItemData, row + static_cast(i)); + AddTransition(referencedAnimGraphInstance, rootStateMachine->GetTransition(i), referenceNodeModelItemData, row + i); } - row += static_cast(rootChildTransitionCount); + row += rootChildTransitionCount; // Now we add the "alias" item ModelItemData* rootStateMachineItem = new ModelItemData(rootStateMachine, referencedAnimGraphInstance, nullptr, referenceNodeModelItemData->m_row); @@ -1424,8 +1424,8 @@ namespace EMStudio { AZStd::vector motionNodes; - const uint32 numAnimGraphs = EMotionFX::GetAnimGraphManager().GetNumAnimGraphs(); - for (uint32 i = 0; i < numAnimGraphs; ++i) + const size_t numAnimGraphs = EMotionFX::GetAnimGraphManager().GetNumAnimGraphs(); + for (size_t i = 0; i < numAnimGraphs; ++i) { EMotionFX::AnimGraph* animGraph = EMotionFX::GetAnimGraphManager().GetAnimGraph(i); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphModelCallbacks.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphModelCallbacks.cpp index 9ff47bb1fe..5de2b58905 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphModelCallbacks.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphModelCallbacks.cpp @@ -393,7 +393,7 @@ namespace EMStudio { // In this case is a BlendTreeConnection, we dont keep items in the model for it. We just // need to mark the target node as changed - EMotionFX::BlendTreeConnection* connection = targetNode->FindConnection(commandCreateConnection->GetTargetPort()); + EMotionFX::BlendTreeConnection* connection = targetNode->FindConnection(aznumeric_caster(commandCreateConnection->GetTargetPort())); return m_animGraphModel.ConnectionAdded(targetNode, connection); } else diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphPlugin.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphPlugin.cpp index 5026af3b06..62c0fe0a14 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphPlugin.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphPlugin.cpp @@ -112,8 +112,8 @@ namespace EMStudio void GetDirtyFileNames(AZStd::vector* outFileNames, AZStd::vector* outObjects) override { // get the number of anim graphs and iterate through them - const uint32 numAnimGraphs = EMotionFX::GetAnimGraphManager().GetNumAnimGraphs(); - for (uint32 i = 0; i < numAnimGraphs; ++i) + const size_t numAnimGraphs = EMotionFX::GetAnimGraphManager().GetNumAnimGraphs(); + for (size_t i = 0; i < numAnimGraphs; ++i) { // return in case we found a dirty file EMotionFX::AnimGraph* animGraph = EMotionFX::GetAnimGraphManager().GetAnimGraph(i); @@ -147,11 +147,9 @@ namespace EMStudio return DirtyFileManager::FINISHED; } - const size_t numObjects = objects.size(); - for (size_t i = 0; i < numObjects; ++i) + for (const SaveDirtyFilesCallback::ObjectPointer objPointer : objects) { // get the current object pointer and skip directly if the type check fails - ObjectPointer objPointer = objects[i]; if (objPointer.mAnimGraph == nullptr) { continue; @@ -429,19 +427,17 @@ namespace EMStudio void AnimGraphPlugin::SetOptionFlag(EDockWindowOptionFlag option, bool isEnabled) { - const uint32 optionIndex = (uint32)option; - if (mDockWindowActions[optionIndex]) + if (mDockWindowActions[option]) { - mDockWindowActions[optionIndex]->setChecked(isEnabled); + mDockWindowActions[option]->setChecked(isEnabled); } } void AnimGraphPlugin::SetOptionEnabled(EDockWindowOptionFlag option, bool isEnabled) { - const uint32 optionIndex = (uint32)option; - if (mDockWindowActions[optionIndex]) + if (mDockWindowActions[option]) { - mDockWindowActions[optionIndex]->setEnabled(isEnabled); + mDockWindowActions[option]->setEnabled(isEnabled); } } @@ -739,8 +735,8 @@ namespace EMStudio MCore::Ray ray(start, end); - const uint32 numActorInstances = EMotionFX::GetActorManager().GetNumActorInstances(); - for (uint32 i = 0; i < numActorInstances; ++i) + const size_t numActorInstances = EMotionFX::GetActorManager().GetNumActorInstances(); + for (size_t i = 0; i < numActorInstances; ++i) { EMotionFX::ActorInstance* actorInstance = EMotionFX::GetActorManager().GetActorInstance(i); @@ -787,20 +783,12 @@ namespace EMStudio result = true; } - /* - // collide with ground plane - MCore::Vector3 groundNormal(0.0f, 0.0f, 0.0f); - groundNormal[MCore::GetCoordinateSystem().GetUpIndex()] = 1.0f; - MCore::PlaneEq groundPlane( groundNormal, Vector3(0.0f, 0.0f, 0.0f) ); - bool result = MCore::Ray(start, end).Intersects( groundPlane, &(outIntersectInfo->mPosition) ); - outIntersectInfo->mNormal = groundNormal; - */ return result; } // set the gizmo offsets - void AnimGraphEventHandler::OnSetVisualManipulatorOffset(EMotionFX::AnimGraphInstance* animGraphInstance, uint32 paramIndex, const AZ::Vector3& offset) + void AnimGraphEventHandler::OnSetVisualManipulatorOffset(EMotionFX::AnimGraphInstance* animGraphInstance, size_t paramIndex, const AZ::Vector3& offset) { EMStudioManager* manager = GetManager(); @@ -808,13 +796,10 @@ namespace EMStudio const AZStd::string& paramName = animGraphInstance->GetAnimGraph()->FindParameter(paramIndex)->GetName(); // iterate over all gizmos that are active - AZStd::vector* gizmos = manager->GetTransformationManipulators(); - const uint32 numGizmos = gizmos->size(); - for (uint32 i = 0; i < numGizmos; ++i) + const AZStd::vector* gizmos = manager->GetTransformationManipulators(); + for (MCommon::TransformationManipulator* gizmo : *gizmos) { - MCommon::TransformationManipulator* gizmo = gizmos->at(i); - - // check the gizmo name + // check the gizmo name if (paramName == gizmo->GetName()) { gizmo->SetRenderOffset(offset); @@ -835,8 +820,8 @@ namespace EMStudio AZStd::vector > newConnections; // get the number of incoming connections and iterate through them - const uint32 numConnections = node->GetNumConnections(); - for (uint32 c = 0; c < numConnections; ++c) + const size_t numConnections = node->GetNumConnections(); + for (size_t c = 0; c < numConnections; ++c) { // get the connection and check if it is plugged into the node EMotionFX::BlendTreeConnection* connection = node->GetConnection(c); @@ -927,8 +912,8 @@ namespace EMStudio AZStd::vector, EMotionFX::AnimGraphNode*> > newConnections; // iterate through all nodes in the parent and check if any of these has a connection from our node - const uint32 numNodes = parentNode->GetNumChildNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = parentNode->GetNumChildNodes(); + for (size_t i = 0; i < numNodes; ++i) { // get the child node and skip it in case it is the parameter node itself EMotionFX::AnimGraphNode* childNode = parentNode->GetChildNode(i); @@ -938,8 +923,8 @@ namespace EMStudio } // get the number of outgoing connections and iterate through them - const uint32 numConnections = childNode->GetNumConnections(); - for (uint32 c = 0; c < numConnections; ++c) + const size_t numConnections = childNode->GetNumConnections(); + for (size_t c = 0; c < numConnections; ++c) { // get the connection and check if it is plugged into the parameter node EMotionFX::BlendTreeConnection* connection = childNode->GetConnection(c); @@ -1059,8 +1044,8 @@ namespace EMStudio bool AnimGraphPlugin::IsAnimGraphActive(EMotionFX::AnimGraph* animGraph) const { const CommandSystem::SelectionList& selectionList = GetCommandManager()->GetCurrentSelection(); - const uint32 numActorInstances = selectionList.GetNumSelectedActorInstances(); - for (uint32 i = 0; i < numActorInstances; ++i) + const size_t numActorInstances = selectionList.GetNumSelectedActorInstances(); + for (size_t i = 0; i < numActorInstances; ++i) { const EMotionFX::ActorInstance* actorInstance = selectionList.GetActorInstance(i); const EMotionFX::AnimGraphInstance* animGraphInstance = actorInstance->GetAnimGraphInstance(); @@ -1074,9 +1059,9 @@ namespace EMStudio } - void AnimGraphPlugin::SaveAnimGraph(const char* filename, uint32 animGraphIndex, MCore::CommandGroup* commandGroup) + void AnimGraphPlugin::SaveAnimGraph(const char* filename, size_t animGraphIndex, MCore::CommandGroup* commandGroup) { - const AZStd::string command = AZStd::string::format("SaveAnimGraph -index %i -filename \"%s\"", animGraphIndex, filename); + const AZStd::string command = AZStd::string::format("SaveAnimGraph -index %zu -filename \"%s\"", animGraphIndex, filename); if (commandGroup == nullptr) { @@ -1101,8 +1086,8 @@ namespace EMStudio void AnimGraphPlugin::SaveAnimGraph(EMotionFX::AnimGraph* animGraph, MCore::CommandGroup* commandGroup) { - const uint32 animGraphIndex = EMotionFX::GetAnimGraphManager().FindAnimGraphIndex(animGraph); - if (animGraphIndex == MCORE_INVALIDINDEX32) + const size_t animGraphIndex = EMotionFX::GetAnimGraphManager().FindAnimGraphIndex(animGraph); + if (animGraphIndex == InvalidIndex) { return; } @@ -1146,8 +1131,8 @@ namespace EMStudio return; } - const uint32 animGraphIndex = EMotionFX::GetAnimGraphManager().FindAnimGraphIndex(animGraph); - if (animGraphIndex == MCORE_INVALIDINDEX32) + const size_t animGraphIndex = EMotionFX::GetAnimGraphManager().FindAnimGraphIndex(animGraph); + if (animGraphIndex == InvalidIndex) { MCore::LogError("Cannot save anim graph. Anim graph index invalid."); return; @@ -1176,7 +1161,7 @@ namespace EMStudio } const CommandSystem::SelectionList& selectionList = GetCommandManager()->GetCurrentSelection(); - const uint32 numActorInstances = selectionList.GetNumSelectedActorInstances(); + const size_t numActorInstances = selectionList.GetNumSelectedActorInstances(); MCore::CommandGroup commandGroup("Load anim graph"); AZStd::string command; @@ -1202,10 +1187,10 @@ namespace EMStudio } else { - const uint32 numMotionSets = EMotionFX::GetMotionManager().GetNumMotionSets(); + const size_t numMotionSets = EMotionFX::GetMotionManager().GetNumMotionSets(); if (numMotionSets > 0) { - for (uint32 i = 0; i < numMotionSets; ++i) + for (size_t i = 0; i < numMotionSets; ++i) { EMotionFX::MotionSet* candidate = EMotionFX::GetMotionManager().GetMotionSet(i); if (candidate->GetIsOwnedByRuntime()) @@ -1222,7 +1207,7 @@ namespace EMStudio if (motionSet) { - for (uint32 i = 0; i < numActorInstances; ++i) + for (size_t i = 0; i < numActorInstances; ++i) { EMotionFX::ActorInstance* actorInstance = selectionList.GetActorInstance(i); if (actorInstance->GetIsOwnedByRuntime()) @@ -1254,8 +1239,8 @@ namespace EMStudio return; } - const uint32 animGraphIndex = EMotionFX::GetAnimGraphManager().FindAnimGraphIndex(animGraph); - assert(animGraphIndex != MCORE_INVALIDINDEX32); + const size_t animGraphIndex = EMotionFX::GetAnimGraphManager().FindAnimGraphIndex(animGraph); + assert(animGraphIndex != InvalidIndex); const AZStd::string filename = animGraph->GetFileName(); if (filename.empty()) diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphPlugin.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphPlugin.h index ad4098308d..af6fcde3d6 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphPlugin.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphPlugin.h @@ -76,7 +76,7 @@ namespace EMStudio AnimGraphEventHandler(AnimGraphPlugin* plugin); const AZStd::vector GetHandledEventTypes() const override { return { EMotionFX::EVENT_TYPE_ON_SET_VISUAL_MANIPULATOR_OFFSET, EMotionFX::EVENT_TYPE_ON_INPUT_PORTS_CHANGED, EMotionFX::EVENT_TYPE_ON_OUTPUT_PORTS_CHANGED, EMotionFX::EVENT_TYPE_ON_RAY_INTERSECTION_TEST, EMotionFX::EVENT_TYPE_ON_DELETE_ANIM_GRAPH, EMotionFX::EVENT_TYPE_ON_DELETE_ANIM_GRAPH_INSTANCE }; } - void OnSetVisualManipulatorOffset(EMotionFX::AnimGraphInstance* animGraphInstance, uint32 paramIndex, const AZ::Vector3& offset) override; + void OnSetVisualManipulatorOffset(EMotionFX::AnimGraphInstance* animGraphInstance, size_t paramIndex, const AZ::Vector3& offset) override; void OnInputPortsChanged(EMotionFX::AnimGraphNode* node, const AZStd::vector& newInputPorts, const AZStd::string& memberName, const AZStd::vector& memberValue) override; void OnOutputPortsChanged(EMotionFX::AnimGraphNode* node, const AZStd::vector& newOutputPorts, const AZStd::string& memberName, const AZStd::vector& memberValue) override; bool OnRayIntersectionTest(const AZ::Vector3& start, const AZ::Vector3& end, EMotionFX::IntersectionInfo* outIntersectInfo) override; @@ -135,7 +135,7 @@ namespace EMStudio void SetActiveAnimGraph(EMotionFX::AnimGraph* animGraph); EMotionFX::AnimGraph* GetActiveAnimGraph() { return mActiveAnimGraph; } - void SaveAnimGraph(const char* filename, uint32 animGraphIndex, MCore::CommandGroup* commandGroup = nullptr); + void SaveAnimGraph(const char* filename, size_t animGraphIndex, MCore::CommandGroup* commandGroup = nullptr); void SaveAnimGraph(EMotionFX::AnimGraph* animGraph, MCore::CommandGroup* commandGroup = nullptr); void SaveAnimGraphAs(EMotionFX::AnimGraph* animGraph, MCore::CommandGroup* commandGroup = nullptr); int SaveDirtyAnimGraph(EMotionFX::AnimGraph* animGraph, MCore::CommandGroup* commandGroup, bool askBeforeSaving, bool showCancelButton = true); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendGraphViewWidget.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendGraphViewWidget.cpp index 328f266cb1..037d75a9b9 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendGraphViewWidget.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendGraphViewWidget.cpp @@ -580,11 +580,11 @@ namespace EMStudio m_openMenu->addAction(m_actions[FILE_OPEN]); - const uint32 numAnimGraphs = EMotionFX::GetAnimGraphManager().GetNumAnimGraphs(); + const size_t numAnimGraphs = EMotionFX::GetAnimGraphManager().GetNumAnimGraphs(); if (numAnimGraphs > 0) { m_openMenu->addSeparator(); - for (uint32 i = 0; i < numAnimGraphs; ++i) + for (size_t i = 0; i < numAnimGraphs; ++i) { EMotionFX::AnimGraph* animGraph = EMotionFX::GetAnimGraphManager().GetAnimGraph(i); if (animGraph->GetIsOwnedByRuntime() == false) @@ -627,7 +627,7 @@ namespace EMStudio { // get the current selection list and the number of actor instances selected const CommandSystem::SelectionList& selectionList = GetCommandManager()->GetCurrentSelection(); - const uint32 numActorInstances = selectionList.GetNumSelectedActorInstances(); + const size_t numActorInstances = selectionList.GetNumSelectedActorInstances(); // Activate the new anim graph automatically (The shown anim graph should always be the activated one). if (numActorInstances > 0) @@ -656,7 +656,7 @@ namespace EMStudio if (motionSet) { // Activate anim graph on all actor instances in case there is a motion set. - for (uint32 i = 0; i < numActorInstances; ++i) + for (size_t i = 0; i < numActorInstances; ++i) { EMotionFX::ActorInstance* actorInstance = selectionList.GetActorInstance(i); commandGroup.AddCommandString(AZStd::string::format("ActivateAnimGraph -actorInstanceID %d -animGraphID %%LASTRESULT%% -motionSetID %d", actorInstance->GetID(), motionSet->GetID())); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendGraphWidget.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendGraphWidget.cpp index 8a4a338b6e..edf5579720 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendGraphWidget.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendGraphWidget.cpp @@ -810,7 +810,7 @@ namespace EMStudio // check if a connection is valid or not - bool BlendGraphWidget::CheckIfIsCreateConnectionValid(uint32 portNr, GraphNode* portNode, NodePort* port, bool isInputPort) + bool BlendGraphWidget::CheckIfIsCreateConnectionValid(AZ::u16 portNr, GraphNode* portNode, NodePort* port, bool isInputPort) { MCORE_UNUSED(port); MCORE_ASSERT(mActiveGraph); @@ -845,8 +845,8 @@ namespace EMStudio MCORE_ASSERT(sourceNode->GetType() == BlendTreeVisualNode::TYPE_ID); BlendTreeVisualNode* targetBlendNode; BlendTreeVisualNode* sourceBlendNode; - uint32 sourcePortNr; - uint32 targetPortNr; + AZ::u16 sourcePortNr; + AZ::u16 targetPortNr; // make sure the input always comes from the source node if (isInputPort) @@ -933,15 +933,15 @@ namespace EMStudio // create the connection - void BlendGraphWidget::OnCreateConnection(uint32 sourcePortNr, GraphNode* sourceNode, bool sourceIsInputPort, uint32 targetPortNr, GraphNode* targetNode, bool targetIsInputPort, const QPoint& startOffset, const QPoint& endOffset) + void BlendGraphWidget::OnCreateConnection(AZ::u16 sourcePortNr, GraphNode* sourceNode, bool sourceIsInputPort, AZ::u16 targetPortNr, GraphNode* targetNode, bool targetIsInputPort, const QPoint& startOffset, const QPoint& endOffset) { MCORE_UNUSED(targetIsInputPort); MCORE_ASSERT(mActiveGraph); GraphNode* realSourceNode; GraphNode* realTargetNode; - uint32 realInputPortNr; - uint32 realOutputPortNr; + AZ::u16 realInputPortNr; + AZ::u16 realOutputPortNr; if (sourceIsInputPort) { @@ -1357,8 +1357,8 @@ namespace EMStudio } // get the output and the input port numbers - const uint32 outputPortNr = connection->GetOutputPortNr(); - const uint32 inputPortNr = connection->GetInputPortNr(); + const AZ::u16 outputPortNr = connection->GetOutputPortNr(); + const AZ::u16 inputPortNr = connection->GetInputPortNr(); // show connection or state transition tooltip if (conditionFound == false) diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendGraphWidget.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendGraphWidget.h index 575e45731a..fa0801cdc1 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendGraphWidget.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendGraphWidget.h @@ -43,7 +43,7 @@ namespace EMStudio BlendGraphWidget(AnimGraphPlugin* plugin, QWidget* parent); // overloaded - bool CheckIfIsCreateConnectionValid(uint32 portNr, GraphNode* portNode, NodePort* port, bool isInputPort) override; + bool CheckIfIsCreateConnectionValid(AZ::u16 portNr, GraphNode* portNode, NodePort* port, bool isInputPort) override; bool CheckIfIsValidTransition(GraphNode* sourceState, GraphNode* targetState) override; bool CheckIfIsValidTransitionSource(GraphNode* sourceState) override; bool CreateConnectionMustBeCurved() override; @@ -60,7 +60,7 @@ namespace EMStudio void OnSetupVisualizeOptions(GraphNode* node) override; void ReplaceTransition(NodeConnection* connection, QPoint oldStartOffset, QPoint oldEndOffset, GraphNode* oldSourceNode, GraphNode* oldTargetNode, GraphNode* newSourceNode, GraphNode* newTargetNode) override; - void OnCreateConnection(uint32 sourcePortNr, GraphNode* sourceNode, bool sourceIsInputPort, uint32 targetPortNr, GraphNode* targetNode, bool targetIsInputPort, const QPoint& startOffset, const QPoint& endOffset) override; + void OnCreateConnection(AZ::u16 sourcePortNr, GraphNode* sourceNode, bool sourceIsInputPort, AZ::u16 targetPortNr, GraphNode* targetNode, bool targetIsInputPort, const QPoint& startOffset, const QPoint& endOffset) override; void DeleteSelectedItems(NodeGraph* nodeGraph); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendTreeVisualNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendTreeVisualNode.cpp index 43225692ac..0cf44af794 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendTreeVisualNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendTreeVisualNode.cpp @@ -39,9 +39,9 @@ namespace EMStudio // add all input ports const AZStd::vector& inPorts = mEMFXNode->GetInputPorts(); - const uint32 numInputs = static_cast(inPorts.size()); + const AZ::u16 numInputs = aznumeric_caster(inPorts.size()); mInputPorts.reserve(numInputs); - for (uint32 i = 0; i < numInputs; ++i) + for (AZ::u16 i = 0; i < numInputs; ++i) { NodePort* port = AddInputPort(false); port->SetNameID(inPorts[i].mNameID); @@ -52,9 +52,9 @@ namespace EMStudio { // add all output ports const AZStd::vector& outPorts = mEMFXNode->GetOutputPorts(); - const uint32 numOutputs = static_cast(outPorts.size()); + const AZ::u16 numOutputs = aznumeric_caster(outPorts.size()); mOutputPorts.reserve(numOutputs); - for (uint32 i = 0; i < numOutputs; ++i) + for (AZ::u16 i = 0; i < numOutputs; ++i) { NodePort* port = AddOutputPort(false); port->SetNameID(outPorts[i].mNameID); @@ -73,8 +73,8 @@ namespace EMStudio GraphNode* source = mParentGraph->FindGraphNode(connection->GetSourceNode()); GraphNode* target = this; - const uint32 sourcePort = connection->GetSourcePort(); - const uint32 targetPort = connection->GetTargetPort(); + const AZ::u16 sourcePort = connection->GetSourcePort(); + const AZ::u16 targetPort = connection->GetTargetPort(); NodeConnection* visualConnection = new NodeConnection(mParentGraph, childIndex, target, targetPort, source, sourcePort); target->AddConnection(visualConnection); @@ -302,8 +302,8 @@ namespace EMStudio { // draw the input ports QColor portBrushColor, portPenColor; - const uint32 numInputs = mInputPorts.size(); - for (uint32 i = 0; i < numInputs; ++i) + const AZ::u16 numInputs = aznumeric_caster(mInputPorts.size()); + for (AZ::u16 i = 0; i < numInputs; ++i) { // get the input port and the corresponding rect NodePort* inputPort = &mInputPorts[i]; @@ -321,8 +321,8 @@ namespace EMStudio if (GetHasVisualOutputPorts()) { // draw the output ports - const uint32 numOutputs = mOutputPorts.size(); - for (uint32 i = 0; i < numOutputs; ++i) + const AZ::u16 numOutputs = aznumeric_caster(mOutputPorts.size()); + for (AZ::u16 i = 0; i < numOutputs; ++i) { // get the output port and the corresponding rect NodePort* outputPort = &mOutputPorts[i]; @@ -455,8 +455,8 @@ namespace EMStudio painter.setFont(mPortNameFont); // draw input port text - const uint32 numInputs = mInputPorts.size(); - for (uint32 i = 0; i < numInputs; ++i) + const AZ::u16 numInputs = aznumeric_caster(mInputPorts.size()); + for (AZ::u16 i = 0; i < numInputs; ++i) { NodePort* inputPort = &mInputPorts[i]; const QRect& portRect = inputPort->GetRect(); @@ -468,8 +468,8 @@ namespace EMStudio } // draw output port text - const uint32 numOutputs = mOutputPorts.size(); - for (uint32 i = 0; i < numOutputs; ++i) + const AZ::u16 numOutputs = aznumeric_caster(mOutputPorts.size()); + for (AZ::u16 i = 0; i < numOutputs; ++i) { NodePort* outputPort = &mOutputPorts[i]; const QRect& portRect = outputPort->GetRect(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ContextMenu.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ContextMenu.cpp index aed7ec08bb..da092f93f6 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ContextMenu.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ContextMenu.cpp @@ -72,17 +72,17 @@ namespace EMStudio QMenu* nodeGroupMenu = new QMenu("Node Group", menu); bool isNodeInNoneGroup = true; QAction* noneNodeGroupAction = nodeGroupMenu->addAction("None"); - noneNodeGroupAction->setData(0); // this index is there to know it's the real none action in case one node group is also called like that + noneNodeGroupAction->setData(qulonglong(0)); // this index is there to know it's the real none action in case one node group is also called like that connect(noneNodeGroupAction, &QAction::triggered, this, &BlendGraphWidget::OnNodeGroupSelected); noneNodeGroupAction->setCheckable(true); - const uint32 numNodeGroups = animGraph->GetNumNodeGroups(); - for (uint32 i = 0; i < numNodeGroups; ++i) + const size_t numNodeGroups = animGraph->GetNumNodeGroups(); + for (size_t i = 0; i < numNodeGroups; ++i) { EMotionFX::AnimGraphNodeGroup* nodeGroup = animGraph->GetNodeGroup(i); QAction* nodeGroupAction = nodeGroupMenu->addAction(nodeGroup->GetName()); - nodeGroupAction->setData(i + 1); // index of the menu added, not used + nodeGroupAction->setData(qulonglong(i + 1)); // index of the menu added, not used connect(nodeGroupAction, &QAction::triggered, this, &BlendGraphWidget::OnNodeGroupSelected); nodeGroupAction->setCheckable(true); @@ -144,7 +144,7 @@ namespace EMStudio else { QMenu* previewMotionMenu = new QMenu("Preview Motions", menu); - for (uint32 i = 0; i < numMotions; ++i) + for (size_t i = 0; i < numMotions; ++i) { const char* motionId = motionNode->GetMotionId(i); QAction* previewMotionAction = previewMotionMenu->addAction(motionId); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GameController.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GameController.cpp index 7038441e4c..c1d0d25c9e 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GameController.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GameController.cpp @@ -559,7 +559,7 @@ const char* GameController::GetElementEnumName(uint32 index) } -uint32 GameController::FindElemendIDByName(const AZStd::string& elementEnumName) +uint32 GameController::FindElementIDByName(const AZStd::string& elementEnumName) { if (elementEnumName == "Pos X") { diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GameController.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GameController.h index d48ca7efd1..f1ee2e0e9d 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GameController.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GameController.h @@ -78,7 +78,7 @@ public: void SetDeadZone(float deadZone) { mDeadZone = deadZone; } MCORE_INLINE float GetDeadZone() const { return mDeadZone; } const char* GetElementEnumName(uint32 index); - uint32 FindElemendIDByName(const AZStd::string& elementEnumName); + uint32 FindElementIDByName(const AZStd::string& elementEnumName); MCORE_INLINE bool GetIsPresent(uint32 elementID) const { return mDeviceElements[elementID].mPresent; } MCORE_INLINE bool GetIsButtonPressed(uint8 buttonIndex) const diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GameControllerWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GameControllerWindow.cpp index 5ce488ee70..eeb765ce54 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GameControllerWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GameControllerWindow.cpp @@ -327,7 +327,7 @@ namespace EMStudio EMotionFX::AnimGraphGameControllerSettings& gameControllerSettings = animGraph->GetGameControllerSettings(); // in case there is no preset yet create a default one - uint32 numPresets = static_cast(gameControllerSettings.GetNumPresets()); + size_t numPresets = gameControllerSettings.GetNumPresets(); if (numPresets == 0) { EMotionFX::AnimGraphGameControllerSettings::Preset* preset = aznew EMotionFX::AnimGraphGameControllerSettings::Preset("Default"); @@ -345,14 +345,13 @@ namespace EMStudio mParameterGridLayout->setMargin(0); // add all parameters - // uint32 startRow = 0; mParameterInfos.clear(); const EMotionFX::ValueParameterVector& parameters = animGraph->RecursivelyGetValueParameters(); - const size_t numParameters = parameters.size(); - mParameterInfos.reserve(static_cast(numParameters)); + const int numParameters = aznumeric_caster(parameters.size()); + mParameterInfos.reserve(numParameters); - for (size_t parameterIndex = 0; parameterIndex < numParameters; ++parameterIndex) + for (int parameterIndex = 0; parameterIndex < numParameters; ++parameterIndex) { const EMotionFX::ValueParameter* parameter = parameters[parameterIndex]; @@ -599,16 +598,16 @@ namespace EMStudio mPresetComboBox->blockSignals(true); mPresetComboBox->clear(); // add the presets to the combo box - for (uint32 i = 0; i < numPresets; ++i) + for (size_t i = 0; i < numPresets; ++i) { mPresetComboBox->addItem(gameControllerSettings.GetPreset(i)->GetName()); } // select the active preset - const uint32 activePresetIndex = gameControllerSettings.GetActivePresetIndex(); - if (activePresetIndex != MCORE_INVALIDINDEX32) + const size_t activePresetIndex = gameControllerSettings.GetActivePresetIndex(); + if (activePresetIndex != InvalidIndex) { - mPresetComboBox->setCurrentIndex(activePresetIndex); + mPresetComboBox->setCurrentIndex(aznumeric_caster(activePresetIndex)); } mPresetComboBox->blockSignals(false); @@ -701,34 +700,22 @@ namespace EMStudio GameControllerWindow::ButtonInfo* GameControllerWindow::FindButtonInfo(QWidget* widget) { // get the number of button infos and iterate through them - const uint32 numButtonInfos = mButtonInfos.size(); - for (uint32 i = 0; i < numButtonInfos; ++i) + const auto foundButtonInfo = AZStd::find_if(begin(mButtonInfos), end(mButtonInfos), [widget](const ButtonInfo& buttonInfo) { - if (mButtonInfos[i].mWidget == widget) - { - return &mButtonInfos[i]; - } - } - - // return failure - return nullptr; + return buttonInfo.mWidget == widget; + }); + return foundButtonInfo != end(mButtonInfos) ? &(*foundButtonInfo) : nullptr; } GameControllerWindow::ParameterInfo* GameControllerWindow::FindParamInfoByModeComboBox(QComboBox* comboBox) { // get the number of parameter infos and iterate through them - const uint32 numParamInfos = mParameterInfos.size(); - for (uint32 i = 0; i < numParamInfos; ++i) + const auto foundParameterInfo = AZStd::find_if(begin(mParameterInfos), end(mParameterInfos), [comboBox](const ParameterInfo& parameterInfo) { - if (mParameterInfos[i].mMode == comboBox) - { - return &mParameterInfos[i]; - } - } - - // return failure - return nullptr; + return parameterInfo.mMode == comboBox; + }); + return foundParameterInfo != end(mParameterInfos) ? &(*foundParameterInfo) : nullptr; } @@ -736,17 +723,11 @@ namespace EMStudio GameControllerWindow::ParameterInfo* GameControllerWindow::FindButtonInfoByAttributeInfo(const EMotionFX::Parameter* parameter) { // get the number of parameter infos and iterate through them - const uint32 numParamInfos = mParameterInfos.size(); - for (uint32 i = 0; i < numParamInfos; ++i) + const auto foundParameterInfo = AZStd::find_if(begin(mParameterInfos), end(mParameterInfos), [parameter](const ParameterInfo& parameterInfo) { - if (mParameterInfos[i].mParameter == parameter) - { - return &mParameterInfos[i]; - } - } - - // return failure - return nullptr; + return parameterInfo.mParameter == parameter; + }); + return foundParameterInfo != end(mParameterInfos) ? &(*foundParameterInfo) : nullptr; } @@ -1053,12 +1034,12 @@ namespace EMStudio // get the game controller settings from the current anim graph EMotionFX::AnimGraphGameControllerSettings& gameControllerSettings = mAnimGraph->GetGameControllerSettings(); - uint32 presetNumber = static_cast(gameControllerSettings.GetNumPresets()); - mString = AZStd::string::format("Preset %d", presetNumber); - while (gameControllerSettings.FindPresetIndexByName(mString.c_str()) != MCORE_INVALIDINDEX32) + size_t presetNumber = gameControllerSettings.GetNumPresets(); + mString = AZStd::string::format("Preset %zu", presetNumber); + while (gameControllerSettings.FindPresetIndexByName(mString.c_str()) != InvalidIndex) { presetNumber++; - mString = AZStd::string::format("Preset %d", presetNumber); + mString = AZStd::string::format("Preset %zu", presetNumber); } EMotionFX::AnimGraphGameControllerSettings::Preset* preset = aznew EMotionFX::AnimGraphGameControllerSettings::Preset(mString.c_str()); @@ -1123,8 +1104,8 @@ namespace EMStudio // get the currently selected preset uint32 presetIndex = mPresetComboBox->currentIndex(); - uint32 newValueIndex = static_cast(gameControllerSettings.FindPresetIndexByName(newValue.c_str())); - if (newValueIndex == MCORE_INVALIDINDEX32) + size_t newValueIndex = gameControllerSettings.FindPresetIndexByName(newValue.c_str()); + if (newValueIndex == InvalidIndex) { EMotionFX::AnimGraphGameControllerSettings::Preset* preset = gameControllerSettings.GetPreset(presetIndex); preset->SetName(newValue.c_str()); @@ -1139,8 +1120,8 @@ namespace EMStudio EMotionFX::AnimGraphGameControllerSettings& gameControllerSettings = mAnimGraph->GetGameControllerSettings(); // check if there already is a preset with the currently entered name - uint32 presetIndex = static_cast(gameControllerSettings.FindPresetIndexByName(FromQtString(text).c_str())); - if (presetIndex != MCORE_INVALIDINDEX32 && presetIndex != gameControllerSettings.GetActivePresetIndex()) + size_t presetIndex = gameControllerSettings.FindPresetIndexByName(FromQtString(text).c_str()); + if (presetIndex != InvalidIndex && presetIndex != gameControllerSettings.GetActivePresetIndex()) { GetManager()->SetWidgetAsInvalidInput(mPresetNameLineEdit); } @@ -1153,18 +1134,11 @@ namespace EMStudio GameControllerWindow::ParameterInfo* GameControllerWindow::FindParamInfoByAxisComboBox(QComboBox* comboBox) { - // get the number of parameter infos and iterate through them - const uint32 numParamInfos = mParameterInfos.size(); - for (uint32 i = 0; i < numParamInfos; ++i) + const auto foundParameterInfo = AZStd::find_if(begin(mParameterInfos), end(mParameterInfos), [comboBox](const ParameterInfo& parameterInfo) { - if (mParameterInfos[i].mAxis == comboBox) - { - return &mParameterInfos[i]; - } - } - - // return failure - return nullptr; + return parameterInfo.mAxis == comboBox; + }); + return foundParameterInfo != end(mParameterInfos) ? &(*foundParameterInfo) : nullptr; } @@ -1195,7 +1169,7 @@ namespace EMStudio #if AZ_TRAIT_EMOTIONFX_HAS_GAME_CONTROLLER if (azrtti_istypeof(paramInfo->mParameter)) { - const uint32 elementID = mGameController->FindElemendIDByName(FromQtString(combo->currentText()).c_str()); + const uint32 elementID = mGameController->FindElementIDByName(FromQtString(combo->currentText()).c_str()); if (elementID >= MCORE_INVALIDINDEX8) { settingsInfo->m_axis = MCORE_INVALIDINDEX8; @@ -1231,18 +1205,11 @@ namespace EMStudio GameControllerWindow::ParameterInfo* GameControllerWindow::FindParamInfoByCheckBox(QCheckBox* checkBox) { - // get the number of parameter infos and iterate through them - const uint32 numParamInfos = mParameterInfos.size(); - for (uint32 i = 0; i < numParamInfos; ++i) + const auto foundParameterInfo = AZStd::find_if(begin(mParameterInfos), end(mParameterInfos), [checkBox](const ParameterInfo& parameterInfo) { - if (mParameterInfos[i].mInvert == checkBox) - { - return &mParameterInfos[i]; - } - } - - // return failure - return nullptr; + return parameterInfo.mInvert == checkBox; + }); + return foundParameterInfo != end(mParameterInfos) ? &(*foundParameterInfo) : nullptr; } @@ -1675,7 +1642,7 @@ namespace EMStudio MCore::AttributeBool* boolAttribute = nullptr; if (parameterIndex.IsSuccess()) { - MCore::Attribute* attribute = animGraphInstance->GetParameterValue(static_cast(parameterIndex.GetValue())); + MCore::Attribute* attribute = animGraphInstance->GetParameterValue(parameterIndex.GetValue()); if (attribute->GetType() == MCore::AttributeBool::TYPE_ID) { diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GraphNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GraphNode.cpp index f0c06bc7e0..f6b0b72bf6 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GraphNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GraphNode.cpp @@ -22,7 +22,7 @@ namespace EMStudio // constructor - GraphNode::GraphNode(const QModelIndex& modelIndex, const char* name, uint32 numInputs, uint32 numOutputs) + GraphNode::GraphNode(const QModelIndex& modelIndex, const char* name, AZ::u16 numInputs, AZ::u16 numOutputs) : m_modelIndex(modelIndex) { mRect = QRect(0, 0, 200, 128); @@ -119,9 +119,9 @@ namespace EMStudio mInfoText.prepare(QTransform(), mSubTitleFont); // input ports - const uint32 numInputs = mInputPorts.size(); + const size_t numInputs = mInputPorts.size(); mInputPortText.resize(numInputs); - for (uint32 i = 0; i < numInputs; ++i) + for (size_t i = 0; i < numInputs; ++i) { QStaticText& staticText = mInputPortText[i]; staticText.setTextFormat(Qt::PlainText); @@ -132,9 +132,9 @@ namespace EMStudio } // output ports - const uint32 numOutputs = mOutputPorts.size(); + const size_t numOutputs = mOutputPorts.size(); mOutputPortText.resize(numOutputs); - for (uint32 i = 0; i < numOutputs; ++i) + for (size_t i = 0; i < numOutputs; ++i) { QStaticText& staticText = mOutputPortText[i]; staticText.setTextFormat(Qt::PlainText); @@ -143,104 +143,15 @@ namespace EMStudio staticText.setText(mOutputPorts[i].GetName()); staticText.prepare(QTransform(), mPortNameFont); } - - //------------------------------------------- - /* - // create a new pixmap with the new and correct resolution - const uint32 nodeWidth = mRect.width(); - const uint32 nodeHeight = mRect.height(); - mTextPixmap = QPixmap(nodeWidth, nodeHeight); - - // make the pixmap fully transparent - mTextPixmap.fill(Qt::transparent); - - mTextPainter.begin( &mTextPixmap ); - - // setup colors - QColor textColor; - if (!GetIsSelected()) - { - if (mIsEnabled) - textColor = Qt::white; - else - textColor = QColor( 100, 100, 100 ); - } - else - textColor = QColor(255,128,0); - - // some rects we need for the text - QRect fullHeaderRect( 0, 0, mRect.width(), 25 ); - QRect headerRect( 0, 0, mRect.width(), 15 ); - QRect subHeaderRect( 0, 13, mRect.width(), 10 ); - - // draw header text - mTextPainter.setBrush( Qt::NoBrush ); - mTextPainter.setPen( textColor ); - mTextPainter.setFont( mHeaderFont ); - mTextPainter.drawText( headerRect, mElidedName, mTextOptionsCenter ); - - mTextPainter.setFont( mSubTitleFont ); - mTextPainter.drawText( subHeaderRect, mElidedSubTitle, mTextOptionsCenter ); - - if (mIsCollapsed == false) - { - // draw the info text - QRect textRect; - CalcInfoTextRect( textRect, true ); - mTextPainter.setPen( QColor(255,128,0) ); - mTextPainter.setFont( mInfoTextFont ); - mTextPainter.drawText( textRect, mElidedNodeInfo, mTextOptionsCenterHV ); - - mTextPainter.setPen( textColor ); - - // draw the input ports - mTextPainter.setPen( textColor ); - mTextPainter.setFont( mPortNameFont ); - const uint32 numInputs = mInputPorts.GetLength(); - for (uint32 i=0; iGetRect(); - - if (inputPort->GetNameID() == MCORE_INVALIDINDEX32) - continue; - - // draw the text - CalcInputPortTextRect(i, textRect, true); - mTextPainter.drawText( textRect, inputPort->GetName(), mTextOptionsAlignLeft ); - } - - // draw the output ports - const uint32 numOutputs = mOutputPorts.GetLength(); - for (uint32 i=0; iGetNameID() == MCORE_INVALIDINDEX32) - continue; - - const QRect& portRect = outputPort->GetRect(); - - // draw the text - CalcOutputPortTextRect(i, textRect, true); - mTextPainter.drawText( textRect, outputPort->GetName(), mTextOptionsAlignRight ); - } - } - - mTextPainter.end(); - */ } // remove all node connections void GraphNode::RemoveAllConnections() { - const uint32 numConnections = mConnections.size(); - for (uint32 i = 0; i < numConnections; ++i) + for (NodeConnection* mConnection : mConnections) { - delete mConnections[i]; + delete mConnection; } mConnections.clear(); @@ -333,17 +244,16 @@ namespace EMStudio mVisualizeRect.setCoords(mRect.right() - 13, mRect.top() + 6, mRect.right() - 5, mRect.top() + 14); // update the input ports and reset the port highlight flags - uint32 i; - const uint32 numInputPorts = mInputPorts.size(); - for (i = 0; i < numInputPorts; ++i) + const AZ::u16 numInputPorts = aznumeric_caster(mInputPorts.size()); + for (AZ::u16 i = 0; i < numInputPorts; ++i) { mInputPorts[i].SetRect(CalcInputPortRect(i)); mInputPorts[i].SetIsHighlighted(false); } // update the output ports and reset the port highlight flags - const uint32 numOutputPorts = mOutputPorts.size(); - for (i = 0; i < numOutputPorts; ++i) + const AZ::u16 numOutputPorts = aznumeric_caster(mOutputPorts.size()); + for (AZ::u16 i = 0; i < numOutputPorts; ++i) { mOutputPorts[i].SetRect(CalcOutputPortRect(i)); mOutputPorts[i].SetIsHighlighted(false); @@ -367,16 +277,15 @@ namespace EMStudio { // set the set highlight flags for the input ports bool highlightedPortFound = false; - for (i = 0; i < numInputPorts; ++i) + for (NodePort& inputPort : mInputPorts) { // get the input port and the corresponding rect - NodePort* inputPort = &mInputPorts[i]; - const QRect& portRect = inputPort->GetRect(); + const QRect& portRect = inputPort.GetRect(); // check if the mouse position is inside the port rect and break the loop in this case, as the mouse can be only over one port at the time if (portRect.contains(mousePos)) { - inputPort->SetIsHighlighted(true); + inputPort.SetIsHighlighted(true); highlightedPortFound = true; break; } @@ -386,16 +295,15 @@ namespace EMStudio if (highlightedPortFound == false) { // set the set highlight flags for the output ports - for (i = 0; i < numOutputPorts; ++i) + for (NodePort& outputPort : mOutputPorts) { // get the output port and the corresponding rect - NodePort* outputPort = &mOutputPorts[i]; - const QRect& portRect = outputPort->GetRect(); + const QRect& portRect = outputPort.GetRect(); // check if the mouse position is inside the port rect and break the loop in this case, as the mouse can be only over one port at the time if (portRect.contains(mousePos)) { - outputPort->SetIsHighlighted(true); + outputPort.SetIsHighlighted(true); break; } } @@ -403,8 +311,8 @@ namespace EMStudio } // Update the connections - const uint32 numConnections = GetNumConnections(); - for (uint32 c = 0; c < numConnections; ++c) + const size_t numConnections = GetNumConnections(); + for (size_t c = 0; c < numConnections; ++c) { GetConnection(c)->Update(visibleRect, mousePos); } @@ -570,8 +478,8 @@ namespace EMStudio // draw the input ports QColor portBrushColor, portPenColor; - const uint32 numInputs = mInputPorts.size(); - for (uint32 i = 0; i < numInputs; ++i) + const AZ::u16 numInputs = aznumeric_caster(mInputPorts.size()); + for (AZ::u16 i = 0; i < numInputs; ++i) { // get the input port and the corresponding rect NodePort* inputPort = &mInputPorts[i]; @@ -595,8 +503,8 @@ namespace EMStudio if (GetHasVisualOutputPorts()) { // draw the output ports - const uint32 numOutputs = mOutputPorts.size(); - for (uint32 i = 0; i < numOutputs; ++i) + const AZ::u16 numOutputs = aznumeric_caster(mOutputPorts.size()); + for (AZ::u16 i = 0; i < numOutputs; ++i) { // get the output port and the corresponding rect NodePort* outputPort = &mOutputPorts[i]; @@ -823,10 +731,8 @@ namespace EMStudio const bool alwaysColor = GetAlwaysColor(); // for all connections - const uint32 numConnections = mConnections.size(); - for (uint32 c = 0; c < numConnections; ++c) + for (NodeConnection* nodeConnection : mConnections) { - NodeConnection* nodeConnection = mConnections[c]; if (nodeConnection->GetIsVisible()) { float opacity = 1.0f; @@ -982,14 +888,14 @@ namespace EMStudio } // get the rect for a given input port - QRect GraphNode::CalcInputPortRect(uint32 portNr) + QRect GraphNode::CalcInputPortRect(AZ::u16 portNr) { return QRect(mRect.left() - 5, mRect.top() + 35 + portNr * 15, 8, 8); } // get the rect for a given output port - QRect GraphNode::CalcOutputPortRect(uint32 portNr) + QRect GraphNode::CalcOutputPortRect(AZ::u16 portNr) { return QRect(mRect.right() - 5, mRect.top() + 35 + portNr * 15, 8, 8); } @@ -1010,7 +916,7 @@ namespace EMStudio // calculate the text rect for the input port - void GraphNode::CalcInputPortTextRect(uint32 portNr, QRect& outRect, bool local) + void GraphNode::CalcInputPortTextRect(AZ::u16 portNr, QRect& outRect, bool local) { if (local == false) { @@ -1024,7 +930,7 @@ namespace EMStudio // calculate the text rect for the input port - void GraphNode::CalcOutputPortTextRect(uint32 portNr, QRect& outRect, bool local) + void GraphNode::CalcOutputPortTextRect(AZ::u16 portNr, QRect& outRect, bool local) { if (local == false) { @@ -1076,32 +982,10 @@ namespace EMStudio return &mOutputPorts.back(); } - /* - // update port text path - void GraphNode::UpdatePortTextPath() - { - mPortTextPath = QPainterPath(); - - QRect textRect; - const uint32 numInputs = mInputPorts.GetLength(); - for (uint32 i=0; iGetName()), mTextOptionsAlignLeft ); - mPortTextPath.addText( textRect.left(), textRect.center().y(), mPortNameFont, QString::fromWCharArray(inputPort->GetName())); - } - } - */ // remove all input ports - NodePort* GraphNode::FindPort(int32 x, int32 y, uint32* outPortNr, bool* outIsInputPort, bool includeInputPorts) + NodePort* GraphNode::FindPort(int32 x, int32 y, AZ::u16* outPortNr, bool* outIsInputPort, bool includeInputPorts) { - uint32 i; - // if the node is not visible at all skip directly if (mIsVisible == false) { @@ -1117,8 +1001,8 @@ namespace EMStudio // check the input ports if (includeInputPorts) { - const uint32 numInputPorts = mInputPorts.size(); - for (i = 0; i < numInputPorts; ++i) + const AZ::u16 numInputPorts = aznumeric_caster(mInputPorts.size()); + for (AZ::u16 i = 0; i < numInputPorts; ++i) { QRect rect = CalcInputPortRect(i); if (rect.contains(QPoint(x, y))) @@ -1131,8 +1015,8 @@ namespace EMStudio } // check the output ports - const uint32 numOutputPorts = mOutputPorts.size(); - for (i = 0; i < numOutputPorts; ++i) + const AZ::u16 numOutputPorts = aznumeric_caster(mOutputPorts.size()); + for (AZ::u16 i = 0; i < numOutputPorts; ++i) { QRect rect = CalcOutputPortRect(i); if (rect.contains(QPoint(x, y))) @@ -1149,42 +1033,44 @@ namespace EMStudio // remove a given connection bool GraphNode::RemoveConnection(const void* connection, bool removeFromMemory) { - const uint32 numConnections = mConnections.size(); - for (uint32 i = 0; i < numConnections; ++i) + const auto foundConnection = AZStd::find_if(begin(mConnections), end(mConnections), [match = connection](const NodeConnection* connection) { - // if this is the connection we're searching for - if (mConnections[i]->GetModelIndex().data(AnimGraphModel::ROLE_POINTER).value() == connection) - { - if (removeFromMemory) - { - delete mConnections[i]; - } - mConnections.erase(AZStd::next(begin(mConnections), i)); - return true; - } + return connection->GetModelIndex().data(AnimGraphModel::ROLE_POINTER).value() == match; + }); + + if (foundConnection == end(mConnections)) + { + return false; } - return false; + + if (removeFromMemory) + { + delete *foundConnection; + } + mConnections.erase(foundConnection); + return true; } // Remove a given connection by model index bool GraphNode::RemoveConnection(const QModelIndex& modelIndex, bool removeFromMemory) { - const uint32 numConnections = mConnections.size(); - for (uint32 i = 0; i < numConnections; ++i) + const auto foundConnection = AZStd::find_if(begin(mConnections), end(mConnections), [match = modelIndex](const NodeConnection* connection) { - // if this is the connection we're searching for - if (mConnections[i]->GetModelIndex() == modelIndex) - { - if (removeFromMemory) - { - delete mConnections[i]; - } - mConnections.erase(AZStd::next(begin(mConnections), i)); - return true; - } + return connection->GetModelIndex() == match; + }); + + if (foundConnection == end(mConnections)) + { + return false; } - return false; + + if (removeFromMemory) + { + delete *foundConnection; + } + mConnections.erase(foundConnection); + return true; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GraphNode.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GraphNode.h index 061444f9d1..125317408d 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GraphNode.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GraphNode.h @@ -78,7 +78,7 @@ namespace EMStudio TYPE_ID = 0x00000001 }; - GraphNode(const QModelIndex& modelIndex, const char* name, uint32 numInputs = 0, uint32 numOutputs = 0); + GraphNode(const QModelIndex& modelIndex, const char* name, AZ::u16 numInputs = 0, AZ::u16 numOutputs = 0); virtual ~GraphNode(); const QModelIndex& GetModelIndex() const { return m_modelIndex; } @@ -86,12 +86,12 @@ namespace EMStudio MCORE_INLINE void UpdateNameAndPorts() { mNameAndPortsUpdated = false; } MCORE_INLINE AZStd::vector& GetConnections() { return mConnections; } MCORE_INLINE size_t GetNumConnections() { return mConnections.size(); } - MCORE_INLINE NodeConnection* GetConnection(uint32 index) { return mConnections[index]; } + MCORE_INLINE NodeConnection* GetConnection(size_t index) { return mConnections[index]; } MCORE_INLINE NodeConnection* AddConnection(NodeConnection* con) { mConnections.emplace_back(con); return con; } MCORE_INLINE void SetParentGraph(NodeGraph* graph) { mParentGraph = graph; } MCORE_INLINE NodeGraph* GetParentGraph() { return mParentGraph; } - MCORE_INLINE NodePort* GetInputPort(uint32 index) { return &mInputPorts[index]; } - MCORE_INLINE NodePort* GetOutputPort(uint32 index) { return &mOutputPorts[index]; } + MCORE_INLINE NodePort* GetInputPort(AZ::u16 index) { return &mInputPorts[index]; } + MCORE_INLINE NodePort* GetOutputPort(AZ::u16 index) { return &mOutputPorts[index]; } MCORE_INLINE const QRect& GetRect() const { return mRect; } MCORE_INLINE const QRect& GetFinalRect() const { return mFinalRect; } MCORE_INLINE const QRect& GetVizRect() const { return mVisualizeRect; } @@ -134,8 +134,8 @@ namespace EMStudio MCORE_INLINE float GetOpacity() const { return mOpacity; } MCORE_INLINE void SetOpacity(float opacity) { mOpacity = opacity; } - size_t GetNumInputPorts() const { return mInputPorts.size(); } - size_t GetNumOutputPorts() const { return mOutputPorts.size(); } + AZ::u16 GetNumInputPorts() const { return aznumeric_caster(mInputPorts.size()); } + AZ::u16 GetNumOutputPorts() const { return aznumeric_caster(mOutputPorts.size()); } NodePort* AddInputPort(bool updateTextPixMap); NodePort* AddOutputPort(bool updateTextPixMap); @@ -173,9 +173,9 @@ namespace EMStudio virtual void RenderHasChildsIndicator(QPainter& painter, QPen* pen, QColor borderColor, QColor bgColor); virtual void RenderVisualizeRect(QPainter& painter, const QColor& bgColor, const QColor& bgColor2); - virtual QRect CalcInputPortRect(uint32 portNr); - virtual QRect CalcOutputPortRect(uint32 portNr); - virtual NodePort* FindPort(int32 x, int32 y, uint32* outPortNr, bool* outIsInputPort, bool includeInputPorts); + virtual QRect CalcInputPortRect(AZ::u16 portNr); + virtual QRect CalcOutputPortRect(AZ::u16 portNr); + virtual NodePort* FindPort(int32 x, int32 y, AZ::u16* outPortNr, bool* outIsInputPort, bool includeInputPorts); virtual bool GetAlwaysColor() const { return true; } virtual bool GetHasError() const { return true; } @@ -188,8 +188,8 @@ namespace EMStudio virtual void Sync() {} - void CalcOutputPortTextRect(uint32 portNr, QRect& outRect, bool local = false); - void CalcInputPortTextRect(uint32 portNr, QRect& outRect, bool local = false); + void CalcOutputPortTextRect(AZ::u16 portNr, QRect& outRect, bool local = false); + void CalcInputPortTextRect(AZ::u16 portNr, QRect& outRect, bool local = false); void CalcInfoTextRect(QRect& outRect, bool local = false); MCORE_INLINE void SetHasVisualOutputPorts(bool hasVisualOutputPorts) { mHasVisualOutputPorts = hasVisualOutputPorts; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeConnection.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeConnection.cpp index 85c8850ede..cefbb0d0af 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeConnection.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeConnection.cpp @@ -17,7 +17,7 @@ namespace EMStudio { // constructor - NodeConnection::NodeConnection(NodeGraph* parentGraph, const QModelIndex& modelIndex, GraphNode* targetNode, uint32 portNr, GraphNode* sourceNode, uint32 sourceOutputPortNr) + NodeConnection::NodeConnection(NodeGraph* parentGraph, const QModelIndex& modelIndex, GraphNode* targetNode, AZ::u16 portNr, GraphNode* sourceNode, AZ::u16 sourceOutputPortNr) : m_modelIndex(modelIndex) , m_parentGraph(parentGraph) { diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeConnection.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeConnection.h index bc7812388d..2e305dbd0c 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeConnection.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeConnection.h @@ -37,7 +37,7 @@ namespace EMStudio TYPE_ID = 0x00000001 }; - NodeConnection(NodeGraph* parentGraph, const QModelIndex& modelIndex, GraphNode* targetNode, uint32 portNr, GraphNode* sourceNode, uint32 sourceOutputPortNr); + NodeConnection(NodeGraph* parentGraph, const QModelIndex& modelIndex, GraphNode* targetNode, AZ::u16 portNr, GraphNode* sourceNode, AZ::u16 sourceOutputPortNr); virtual ~NodeConnection(); const QModelIndex& GetModelIndex() const { return m_modelIndex; } @@ -49,7 +49,7 @@ namespace EMStudio void UpdatePainterPath(); virtual void Update(const QRect& visibleRect, const QPoint& mousePos); - virtual uint32 GetType() { return TYPE_ID; } + virtual uint32 GetType() const { return TYPE_ID; } QRect CalcRect() const; QRect CalcFinalRect() const; @@ -62,8 +62,8 @@ namespace EMStudio MCORE_INLINE bool GetIsVisible() { return mIsVisible; } - MCORE_INLINE uint32 GetInputPortNr() const { return mPortNr; } - MCORE_INLINE uint32 GetOutputPortNr() const { return mSourcePortNr; } + MCORE_INLINE AZ::u16 GetInputPortNr() const { return mPortNr; } + MCORE_INLINE AZ::u16 GetOutputPortNr() const { return mSourcePortNr; } MCORE_INLINE GraphNode* GetSourceNode() { return mSourceNode; } MCORE_INLINE GraphNode* GetTargetNode() { return mTargetNode; } @@ -103,7 +103,7 @@ namespace EMStudio void SetSourceNode(GraphNode* node) { mSourceNode = node; } void SetTargetNode(GraphNode* node) { mTargetNode = node; } - void SetTargetPort(uint32 portIndex) { mPortNr = portIndex; } + void SetTargetPort(AZ::u16 portIndex) { mPortNr = portIndex; } protected: @@ -115,8 +115,8 @@ namespace EMStudio GraphNode* mSourceNode; // source node from which the connection comes GraphNode* mTargetNode; // the target node QPainterPath mPainterPath; - uint32 mPortNr; // input port where this is connected to - uint32 mSourcePortNr; // source output port number + AZ::u16 mPortNr; // input port where this is connected to + AZ::u16 mSourcePortNr; // source output port number bool mIsVisible; // is this connection visible? bool mIsProcessed; // is this connection processed? bool mIsDisabled; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGraph.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGraph.cpp index 39a9a0630d..37ec2cfd8b 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGraph.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGraph.cpp @@ -6,6 +6,7 @@ * */ +#include "AzCore/std/numeric.h" #include #include #include @@ -54,7 +55,7 @@ namespace EMStudio // init connection creation mConStartOffset = QPoint(0, 0); mConEndOffset = QPoint(0, 0); - mConPortNr = MCORE_INVALIDINDEX32; + mConPortNr = InvalidIndex16; mConIsInputPort = true; mConNode = nullptr; // nullptr when no connection is being created mConPort = nullptr; @@ -137,8 +138,8 @@ namespace EMStudio GraphNode* graphNode = indexAndGraphNode.second.get(); // get the number of connections and iterate through them - const uint32 numConnections = graphNode->GetNumConnections(); - for (uint32 c = 0; c < numConnections; ++c) + const size_t numConnections = graphNode->GetNumConnections(); + for (size_t c = 0; c < numConnections; ++c) { NodeConnection* connection = graphNode->GetConnection(c); if (connection->GetIsSelected()) @@ -271,8 +272,8 @@ namespace EMStudio EMotionFX::AnimGraphNode* emfxTargetNode = indexAndGraphNode.first.data(AnimGraphModel::ROLE_NODE_POINTER).value(); // iterate through all connections connected to this node - const uint32 numConnections = graphNode->GetNumConnections(); - for (uint32 c = 0; c < numConnections; ++c) + const size_t numConnections = graphNode->GetNumConnections(); + for (size_t c = 0; c < numConnections; ++c) { NodeConnection* visualConnection = graphNode->GetConnection(c); @@ -286,8 +287,8 @@ namespace EMStudio continue; } - const uint32 inputPortNr = visualConnection->GetInputPortNr(); - const uint32 outputPortNr = visualConnection->GetOutputPortNr(); + const AZ::u16 inputPortNr = visualConnection->GetInputPortNr(); + const AZ::u16 outputPortNr = visualConnection->GetOutputPortNr(); MCore::Attribute* attribute = emfxSourceNode->GetOutputValue(animGraphInstance, outputPortNr); // fill the string with data @@ -606,8 +607,8 @@ namespace EMStudio GraphNode* graphNode = indexAndGraphNode.second.get(); // iterate over all connections - const uint32 numConnections = graphNode->GetNumConnections(); - for (uint32 c = 0; c < numConnections; ++c) + const size_t numConnections = graphNode->GetNumConnections(); + for (size_t c = 0; c < numConnections; ++c) { NodeConnection* connection = graphNode->GetConnection(c); if (connection->CheckIfIsCloseTo(mousePos)) @@ -632,8 +633,8 @@ namespace EMStudio GraphNode* graphNode = indexAndGraphNode.second.get(); // iterate over all connections - const uint32 numConnections = graphNode->GetNumConnections(); - for (uint32 c = 0; c < numConnections; ++c) + const size_t numConnections = graphNode->GetNumConnections(); + for (size_t c = 0; c < numConnections; ++c) { NodeConnection* connection = graphNode->GetConnection(c); GraphNode* sourceNode = connection->GetSourceNode(); @@ -797,28 +798,6 @@ namespace EMStudio #endif RenderTitlebar(painter, width); - - // render FPS counter - //#ifdef GRAPH_PERFORMANCE_FRAMEDURATION - /* static MCore::AnsiString tempFPSString; - static MCore::Timer fpsTimer; - static double fpsTimeElapsed = 0.0; - static uint32 fpsNumFrames = 0; - static uint32 lastFPS = 0; - fpsTimeElapsed += fpsTimer.GetTimeDelta(); - fpsNumFrames++; - if (fpsTimeElapsed > 1.0f) - { - lastFPS = fpsNumFrames; - fpsTimeElapsed = 0.0; - fpsNumFrames = 0; - } - tempFPSString.Format( "%i FPS", lastFPS ); - painter.setPen( QColor(255, 255, 255) ); - painter.resetTransform(); - painter.drawText( 5, 20, tempFPSString.c_str() ); - */ - //#endif } void NodeGraph::RenderTitlebar(QPainter& painter, const QString& text, int32 width) @@ -898,8 +877,8 @@ namespace EMStudio AnimGraphModel::AddToItemSelection(newSelection, modelIndex, nodePreviouslySelected, nodeNewlySelected, toggleMode, overwriteCurSelection); - const uint32 numConnections = node->GetNumConnections(); - for (uint32 c = 0; c < numConnections; ++c) + const size_t numConnections = node->GetNumConnections(); + for (size_t c = 0; c < numConnections; ++c) { NodeConnection* connection = node->GetConnection(c); const bool connectionPreviouslySelected = std::find(oldSelectionModelIndices.begin(), oldSelectionModelIndices.end(), connection->GetModelIndex()) != oldSelectionModelIndices.end(); @@ -970,8 +949,8 @@ namespace EMStudio { GraphNode* node = indexAndGraphNode.second.get(); - const uint32 numConnections = node->GetNumConnections(); - for (uint32 c = 0; c < numConnections; ++c) + const size_t numConnections = node->GetNumConnections(); + for (size_t c = 0; c < numConnections; ++c) { NodeConnection* connection = node->GetConnection(c); const bool isNewlySelected = connection->CheckIfIsCloseTo(point); @@ -1217,20 +1196,12 @@ namespace EMStudio // calc the number of selected nodes - uint32 NodeGraph::CalcNumSelectedNodes() const + size_t NodeGraph::CalcNumSelectedNodes() const { - uint32 result = 0; - - for (const GraphNodeByModelIndex::value_type& indexAndGraphNode : m_graphNodeByModelIndex) + return AZStd::accumulate(begin(m_graphNodeByModelIndex), end(m_graphNodeByModelIndex), size_t{0}, [](size_t total, const auto& indexAndGraphNode) { - GraphNode* node = indexAndGraphNode.second.get(); - if (node->GetIsSelected()) - { - result++; - } - } - - return result; + return total + indexAndGraphNode.second->GetIsSelected(); + }); } @@ -1254,8 +1225,8 @@ namespace EMStudio if (includeConnections) { // for all connections - const uint32 numConnections = node->GetNumConnections(); - for (uint32 c = 0; c < numConnections; ++c) + const size_t numConnections = node->GetNumConnections(); + for (size_t c = 0; c < numConnections; ++c) { if (node->GetConnection(c)->GetIsSelected()) { @@ -1283,8 +1254,8 @@ namespace EMStudio result |= graphNode->GetRect(); // for all connections - const uint32 numConnections = graphNode->GetNumConnections(); - for (uint32 c = 0; c < numConnections; ++c) + const size_t numConnections = graphNode->GetNumConnections(); + for (size_t c = 0; c < numConnections; ++c) { result |= graphNode->GetConnection(c)->CalcRect(); } @@ -1499,7 +1470,7 @@ namespace EMStudio // find the port at a given location - NodePort* NodeGraph::FindPort(int32 x, int32 y, GraphNode** outNode, uint32* outPortNr, bool* outIsInputPort, bool includeInputPorts) + NodePort* NodeGraph::FindPort(int32 x, int32 y, GraphNode** outNode, AZ::u16* outPortNr, bool* outIsInputPort, bool includeInputPorts) { // get the number of nodes in the graph and iterate through them for (const GraphNodeByModelIndex::value_type& indexAndGraphNode : m_graphNodeByModelIndex) @@ -1527,7 +1498,7 @@ namespace EMStudio // start creating a connection - void NodeGraph::StartCreateConnection(uint32 portNr, bool isInputPort, GraphNode* portNode, NodePort* port, const QPoint& startOffset) + void NodeGraph::StartCreateConnection(AZ::u16 portNr, bool isInputPort, GraphNode* portNode, NodePort* port, const QPoint& startOffset) { mConPortNr = portNr; mConIsInputPort = isInputPort; @@ -1538,7 +1509,7 @@ namespace EMStudio // start relinking a connection - void NodeGraph::StartRelinkConnection(NodeConnection* connection, uint32 portNr, GraphNode* node) + void NodeGraph::StartRelinkConnection(NodeConnection* connection, AZ::u16 portNr, GraphNode* node) { mConPortNr = portNr; mConNode = node; @@ -1604,7 +1575,7 @@ namespace EMStudio // reset members void NodeGraph::StopRelinkConnection() { - mConPortNr = MCORE_INVALIDINDEX32; + mConPortNr = InvalidIndex16; mConNode = nullptr; mRelinkConnection = nullptr; mConIsValid = false; @@ -1616,7 +1587,7 @@ namespace EMStudio // reset members void NodeGraph::StopCreateConnection() { - mConPortNr = MCORE_INVALIDINDEX32; + mConPortNr = InvalidIndex16; mConIsInputPort = true; mConNode = nullptr; // nullptr when no connection is being created mConPort = nullptr; @@ -1640,8 +1611,8 @@ namespace EMStudio GraphNode* graphNode = indexAndGraphNode.second.get(); // get the number of connections and iterate through them - const uint32 numConnections = graphNode->GetNumConnections(); - for (uint32 j = 0; j < numConnections; ++j) + const size_t numConnections = graphNode->GetNumConnections(); + for (size_t j = 0; j < numConnections; ++j) { NodeConnection* connection = graphNode->GetConnection(j); @@ -1672,9 +1643,6 @@ namespace EMStudio { // gather some information from the connection NodeConnection* connection = GetRelinkConnection(); - //GraphNode* sourceNode = connection->GetSourceNode(); - //uint32 sourcePortNr = connection->GetOutputPortNr(); - //NodePort* port = sourceNode->GetOutputPort( connection->GetOutputPortNr() ); QPoint start = connection->GetSourceRect().center(); QPoint end = m_graphWidget->GetMousePos(); @@ -1701,8 +1669,8 @@ namespace EMStudio } // now check all ports to see if they would be valid - const uint32 numInputPorts = node->GetNumInputPorts(); - for (uint32 i = 0; i < numInputPorts; ++i) + const AZ::u16 numInputPorts = node->GetNumInputPorts(); + for (AZ::u16 i = 0; i < numInputPorts; ++i) { if (CheckIfIsRelinkConnectionValid(mRelinkConnection, node, i, true)) { @@ -1778,8 +1746,8 @@ namespace EMStudio } // now check all ports to see if they would be valid - const uint32 numInputPorts = node->GetNumInputPorts(); - for (uint32 i = 0; i < numInputPorts; ++i) + const AZ::u16 numInputPorts = node->GetNumInputPorts(); + for (AZ::u16 i = 0; i < numInputPorts; ++i) { if (m_graphWidget->CheckIfIsCreateConnectionValid(i, node, node->GetInputPort(i), true)) { @@ -1793,8 +1761,8 @@ namespace EMStudio } // now check all ports to see if they would be valid - const uint32 numOutputPorts = node->GetNumOutputPorts(); - for (uint32 a = 0; a < numOutputPorts; ++a) + const AZ::u16 numOutputPorts = node->GetNumOutputPorts(); + for (AZ::u16 a = 0; a < numOutputPorts; ++a) { if (m_graphWidget->CheckIfIsCreateConnectionValid(a, node, node->GetOutputPort(a), false)) { @@ -1864,10 +1832,10 @@ namespace EMStudio // check if this connection already exists - bool NodeGraph::CheckIfHasConnection(GraphNode* sourceNode, uint32 outputPortNr, GraphNode* targetNode, uint32 inputPortNr) const + bool NodeGraph::CheckIfHasConnection(GraphNode* sourceNode, AZ::u16 outputPortNr, GraphNode* targetNode, AZ::u16 inputPortNr) const { - const uint32 numConnections = targetNode->GetNumConnections(); - for (uint32 i = 0; i < numConnections; ++i) + const size_t numConnections = targetNode->GetNumConnections(); + for (size_t i = 0; i < numConnections; ++i) { NodeConnection* connection = targetNode->GetConnection(i); @@ -1888,15 +1856,15 @@ namespace EMStudio } - NodeConnection* NodeGraph::FindInputConnection(GraphNode* targetNode, uint32 targetPortNr) const + NodeConnection* NodeGraph::FindInputConnection(GraphNode* targetNode, AZ::u16 targetPortNr) const { - if (targetNode == nullptr || targetPortNr == MCORE_INVALIDINDEX32) + if (targetNode == nullptr || targetPortNr == InvalidIndex16) { return nullptr; } - const uint32 numConnections = targetNode->GetNumConnections(); - for (uint32 i = 0; i < numConnections; ++i) + const size_t numConnections = targetNode->GetNumConnections(); + for (size_t i = 0; i < numConnections; ++i) { NodeConnection* connection = targetNode->GetConnection(i); @@ -1967,8 +1935,8 @@ namespace EMStudio const QModelIndex parentModelIndex = modelIndex.model()->parent(modelIndex); EMotionFX::AnimGraphNode* parentNode = parentModelIndex.data(AnimGraphModel::ROLE_NODE_POINTER).value(); GraphNode* target = FindGraphNode(parentNode); - const uint32 sourcePort = connection->GetSourcePort(); - const uint32 targetPort = connection->GetTargetPort(); + const AZ::u16 sourcePort = connection->GetSourcePort(); + const AZ::u16 targetPort = connection->GetTargetPort(); NodeConnection* visualConnection = new NodeConnection(this, modelIndex, target, targetPort, source, sourcePort); target->AddConnection(visualConnection); break; @@ -2014,8 +1982,8 @@ namespace EMStudio for (const GraphNodeByModelIndex::value_type& target : m_graphNodeByModelIndex) { AZStd::vector& connections = target.second->GetConnections(); - const uint32 connectionsCount = connections.size(); - for (uint32 i = 0; i < connectionsCount; ++i) + const size_t connectionsCount = connections.size(); + for (size_t i = 0; i < connectionsCount; ++i) { if (connections[i]->GetType() == StateConnection::TYPE_ID) { @@ -2087,12 +2055,11 @@ namespace EMStudio bool foundConnection = false; AZStd::vector& connections = targetGraphNode->GetConnections(); - const uint32 connectionsCount = connections.size(); - for (uint32 i = 0; i < connectionsCount; ++i) + for (NodeConnection* connection : connections) { - if (connections[i]->GetType() == StateConnection::TYPE_ID) + if (connection->GetType() == StateConnection::TYPE_ID) { - StateConnection* visualStateConnection = static_cast(connections[i]); + StateConnection* visualStateConnection = static_cast(connection); if (visualStateConnection->GetModelIndex() == modelIndex) { SyncTransition(visualStateConnection, transition, targetGraphNode); @@ -2175,12 +2142,11 @@ namespace EMStudio for (const GraphNodeByModelIndex::value_type& target : m_graphNodeByModelIndex) { AZStd::vector& connections = target.second->GetConnections(); - const uint32 connectionsCount = connections.size(); - for (uint32 i = 0; i < connectionsCount; ++i) + for (NodeConnection* connection : connections) { - if (connections[i]->GetType() == StateConnection::TYPE_ID) + if (connection->GetType() == StateConnection::TYPE_ID) { - StateConnection* visualStateConnection = static_cast(connections[i]); + StateConnection* visualStateConnection = static_cast(connection); if (visualStateConnection->GetModelIndex() == modelIndex) { return visualStateConnection; @@ -2204,12 +2170,11 @@ namespace EMStudio if (target) { AZStd::vector& connections = target->GetConnections(); - const uint32 connectionsCount = connections.size(); - for (uint32 i = 0; i < connectionsCount; ++i) + for (NodeConnection* connection : connections) { - if (connections[i]->GetType() == NodeConnection::TYPE_ID) + if (connection->GetType() == NodeConnection::TYPE_ID) { - NodeConnection* visualNodeConnection = static_cast(connections[i]); + NodeConnection* visualNodeConnection = static_cast(connection); if (visualNodeConnection->GetModelIndex() == modelIndex) { return visualNodeConnection; @@ -2237,8 +2202,8 @@ namespace EMStudio graphNode->SetIsProcessed(graphNodeAnimGraphInstance->GetIsOutputReady(emfxNode->GetObjectIndex())); graphNode->SetIsUpdated(graphNodeAnimGraphInstance->GetIsUpdateReady(emfxNode->GetObjectIndex())); - const uint32 numConnections = graphNode->GetNumConnections(); - for (uint32 c = 0; c < numConnections; ++c) + const size_t numConnections = graphNode->GetNumConnections(); + for (size_t c = 0; c < numConnections; ++c) { NodeConnection* connection = graphNode->GetConnection(c); if (connection->GetType() == NodeConnection::TYPE_ID) @@ -2253,8 +2218,8 @@ namespace EMStudio graphNode->SetIsProcessed(false); graphNode->SetIsUpdated(false); - const uint32 numConnections = graphNode->GetNumConnections(); - for (uint32 c = 0; c < numConnections; ++c) + const size_t numConnections = graphNode->GetNumConnections(); + for (size_t c = 0; c < numConnections; ++c) { NodeConnection* connection = graphNode->GetConnection(c); if (connection->GetType() == NodeConnection::TYPE_ID) @@ -2264,8 +2229,8 @@ namespace EMStudio } } - const uint32 numConnections = graphNode->GetNumConnections(); - for (uint32 c = 0; c < numConnections; ++c) + const size_t numConnections = graphNode->GetNumConnections(); + for (size_t c = 0; c < numConnections; ++c) { NodeConnection* connection = graphNode->GetConnection(c); if (connection->GetType() == NodeConnection::TYPE_ID) @@ -2285,12 +2250,12 @@ namespace EMStudio } // check if a connection is valid or not - bool NodeGraph::CheckIfIsRelinkConnectionValid(NodeConnection* connection, GraphNode* newTargetNode, uint32 newTargetPortNr, bool isTargetInput) + bool NodeGraph::CheckIfIsRelinkConnectionValid(NodeConnection* connection, GraphNode* newTargetNode, AZ::u16 newTargetPortNr, bool isTargetInput) { GraphNode* targetNode = connection->GetSourceNode(); GraphNode* sourceNode = newTargetNode; - uint32 sourcePortNr = connection->GetOutputPortNr(); - uint32 targetPortNr = newTargetPortNr; + AZ::u16 sourcePortNr = connection->GetOutputPortNr(); + AZ::u16 targetPortNr = newTargetPortNr; // don't allow connection to itself if (sourceNode == targetNode) @@ -2341,8 +2306,8 @@ namespace EMStudio graphNode->ResetBorderColor(); // recurse through the inputs - const uint32 numConnections = startNode->GetNumConnections(); - for (uint32 i = 0; i < numConnections; ++i) + const size_t numConnections = startNode->GetNumConnections(); + for (size_t i = 0; i < numConnections; ++i) { EMotionFX::BlendTreeConnection* connection = startNode->GetConnection(i); RecursiveSetOpacity(connection->GetSourceNode(), opacity); @@ -2458,8 +2423,8 @@ namespace EMStudio // get the number of node groups and iterate through them QRect nodeRect; QRect groupRect; - const uint32 numNodeGroups = animGraph->GetNumNodeGroups(); - for (uint32 i = 0; i < numNodeGroups; ++i) + const size_t numNodeGroups = animGraph->GetNumNodeGroups(); + for (size_t i = 0; i < numNodeGroups; ++i) { // get the current node group EMotionFX::AnimGraphNodeGroup* nodeGroup = animGraph->GetNodeGroup(i); @@ -2471,7 +2436,7 @@ namespace EMStudio } // get the number of nodes inside the node group and skip the group in case there are no nodes in - const uint32 numNodes = nodeGroup->GetNumNodes(); + const size_t numNodes = nodeGroup->GetNumNodes(); if (numNodes == 0) { continue; @@ -2483,7 +2448,7 @@ namespace EMStudio int32 right = std::numeric_limits::lowest(); bool nodesInGroupDisplayed = false; - for (uint32 j = 0; j < numNodes; ++j) + for (size_t j = 0; j < numNodes; ++j) { // get the graph node by the id and skip it if the node is not inside the currently visible node graph const EMotionFX::AnimGraphNodeId nodeId = nodeGroup->GetNode(j); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGraph.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGraph.h index 8af772d95e..11490d8b49 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGraph.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGraph.h @@ -81,24 +81,24 @@ namespace EMStudio GraphNode* GetCreateConnectionNode() { return mConNode; } NodeConnection* GetRelinkConnection() { return mRelinkConnection; } - uint32 GetCreateConnectionPortNr() const { return mConPortNr; } + AZ::u16 GetCreateConnectionPortNr() const { return mConPortNr; } bool GetCreateConnectionIsInputPort() const { return mConIsInputPort; } const QPoint& GetCreateConnectionStartOffset() const { return mConStartOffset; } const QPoint& GetCreateConnectionEndOffset() const { return mConEndOffset; } void SetCreateConnectionEndOffset(const QPoint& offset){ mConEndOffset = offset; } - bool CheckIfHasConnection(GraphNode* sourceNode, uint32 outputPortNr, GraphNode* targetNode, uint32 inputPortNr) const; - NodeConnection* FindInputConnection(GraphNode* targetNode, uint32 targetPortNr) const; + bool CheckIfHasConnection(GraphNode* sourceNode, AZ::u16 outputPortNr, GraphNode* targetNode, AZ::u16 inputPortNr) const; + NodeConnection* FindInputConnection(GraphNode* targetNode, AZ::u16 targetPortNr) const; NodeConnection* FindConnection(const QPoint& mousePos); void SelectAllNodes(); void UnselectAllNodes(); - uint32 CalcNumSelectedNodes() const; + size_t CalcNumSelectedNodes() const; GraphNode* FindNode(const QPoint& globalPoint); - void StartCreateConnection(uint32 portNr, bool isInputPort, GraphNode* portNode, NodePort* port, const QPoint& startOffset); - void StartRelinkConnection(NodeConnection* connection, uint32 portNr, GraphNode* node); + void StartCreateConnection(AZ::u16 portNr, bool isInputPort, GraphNode* portNode, NodePort* port, const QPoint& startOffset); + void StartRelinkConnection(NodeConnection* connection, AZ::u16 portNr, GraphNode* node); void StopCreateConnection(); void StopRelinkConnection(); @@ -118,7 +118,7 @@ namespace EMStudio void SelectConnectionCloseTo(const QPoint& point, bool overwriteCurSelection = true, bool toggle = false); QRect CalcRectFromSelection(bool includeConnections = true) const; QRect CalcRectFromGraph() const; - NodePort* FindPort(int32 x, int32 y, GraphNode** outNode, uint32* outPortNr, bool* outIsInputPort, bool includeInputPorts = true); + NodePort* FindPort(int32 x, int32 y, GraphNode** outNode, AZ::u16* outPortNr, bool* outIsInputPort, bool includeInputPorts = true); // entry state helper functions void SetEntryNode(GraphNode* entryNode) { mEntryNode = entryNode; } @@ -157,7 +157,7 @@ namespace EMStudio void UpdateVisualGraphFlags(); - static bool CheckIfIsRelinkConnectionValid(NodeConnection* connection, GraphNode* newTargetNode, uint32 newTargetPortNr, bool isTargetInput); + static bool CheckIfIsRelinkConnectionValid(NodeConnection* connection, GraphNode* newTargetNode, AZ::u16 newTargetPortNr, bool isTargetInput); void RecursiveSetOpacity(EMotionFX::AnimGraphNode* startNode, float opacity); @@ -197,7 +197,7 @@ namespace EMStudio // connection info QPoint mConStartOffset; QPoint mConEndOffset; - uint32 mConPortNr; + AZ::u16 mConPortNr; bool mConIsInputPort; GraphNode* mConNode; // nullptr when no connection is being created NodeConnection* mRelinkConnection; // nullptr when not relinking a connection diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGraphWidget.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGraphWidget.cpp index 8b8e651837..d7afe634a1 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGraphWidget.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGraphWidget.cpp @@ -406,7 +406,7 @@ namespace EMStudio // check if we are clicking on a port GraphNode* portNode = nullptr; NodePort* port = nullptr; - uint32 portNr = MCORE_INVALIDINDEX32; + AZ::u16 portNr = InvalidIndex16; bool isInputPort = true; port = mActiveGraph->FindPort(globalPos.x(), globalPos.y(), &portNode, &portNr, &isInputPort); @@ -767,8 +767,8 @@ namespace EMStudio if (motionEntry && motionEntry->GetMotion()) { EMotionFX::Motion* motion = motionEntry->GetMotion(); - uint32 motionIndex = motionManager.FindMotionIndexByName(motion->GetName()); - commandString = AZStd::string::format("Select -motionIndex %d", motionIndex); + size_t motionIndex = motionManager.FindMotionIndexByName(motion->GetName()); + commandString = AZStd::string::format("Select -motionIndex %zu", motionIndex); commandGroup.AddCommandString(commandString); } } @@ -810,7 +810,7 @@ namespace EMStudio // check if we are clicking on an input port GraphNode* portNode = nullptr; NodePort* port = nullptr; - uint32 portNr = MCORE_INVALIDINDEX32; + AZ::u16 portNr = InvalidIndex16; bool isInputPort = true; port = mActiveGraph->FindPort(globalPos.x(), globalPos.y(), &portNode, &portNr, &isInputPort); if (port) @@ -824,18 +824,10 @@ namespace EMStudio if (actionFilter.m_editConnections && isInputPort && connection && portNode->GetType() != StateGraphNode::TYPE_ID) { - //connection->SetColor(); - //MCore::LOG("%s(%i)->%s(%i)", connection->GetSourceNode()->GetName(), connection->GetOutputPortNr(), connection->GetTargetNode()->GetName(), connection->GetInputPortNr()); - //GraphNode* createConNode = connection->GetSourceNode(); - //uint32 createConPortNr = connection->GetOutputPortNr(); - //NodePort* createConPort = createConNode->GetOutputPort( createConPortNr ); - //QPoint createConOffset = QPoint(0,0);//globalPos - createConNode->GetRect().topLeft(); connection->SetIsDashed(true); UpdateMouseCursor(mousePos, globalPos); - //mActiveGraph->StartCreateConnection( createConPortNr, !isInputPort, createConNode, createConPort, createConOffset ); mActiveGraph->StartRelinkConnection(connection, portNr, portNode); - //update(); return; } @@ -1054,7 +1046,7 @@ namespace EMStudio { if (mActiveGraph->GetIsCreateConnectionValid()) { - uint32 targetPortNr; + AZ::u16 targetPortNr; bool targetIsInputPort; GraphNode* targetNode; @@ -1096,7 +1088,7 @@ namespace EMStudio AZ_Assert(!mActiveGraph->IsInReferencedGraph(), "Expected to not be in a referenced graph"); // get the information from the current mouse position - uint32 newTargetPortNr; + AZ::u16 newTargetPortNr; bool newTargetIsInputPort; GraphNode* newTargetNode; NodePort* newTargetPort = mActiveGraph->FindPort(globalPos.x(), globalPos.y(), &newTargetNode, &newTargetPortNr, &newTargetIsInputPort); @@ -1119,10 +1111,10 @@ namespace EMStudio // get the information from the old connection which we want to relink GraphNode* sourceNode = relinkedConnection->GetSourceNode(); AZStd::string sourceNodeName = sourceNode->GetName(); - uint32 sourcePortNr = relinkedConnection->GetOutputPortNr(); + AZ::u16 sourcePortNr = relinkedConnection->GetOutputPortNr(); GraphNode* oldTargetNode = relinkedConnection->GetTargetNode(); AZStd::string oldTargetNodeName = oldTargetNode->GetName(); - uint32 oldTargetPortNr = relinkedConnection->GetInputPortNr(); + AZ::u16 oldTargetPortNr = relinkedConnection->GetInputPortNr(); if (NodeGraph::CheckIfIsRelinkConnectionValid(relinkedConnection, newTargetNode, newTargetPortNr, newTargetIsInputPort)) { @@ -1412,7 +1404,7 @@ namespace EMStudio } // check if we're hovering over a port - uint32 portNr; + AZ::u16 portNr; GraphNode* portNode; bool isInputPort; NodePort* nodePort = mActiveGraph->FindPort(globalMousePos.x(), globalMousePos.y(), &portNode, &portNr, &isInputPort); @@ -1432,7 +1424,7 @@ namespace EMStudio else // not hovering a node, simply check for ports { // check if we're hovering over a port - uint32 portNr; + AZ::u16 portNr; GraphNode* portNode; bool isInputPort; NodePort* nodePort = mActiveGraph->FindPort(globalMousePos.x(), globalMousePos.y(), &portNode, &portNr, &isInputPort); @@ -1551,21 +1543,18 @@ namespace EMStudio // return the number of selected nodes - uint32 NodeGraphWidget::CalcNumSelectedNodes() const + size_t NodeGraphWidget::CalcNumSelectedNodes() const { if (mActiveGraph) { return mActiveGraph->CalcNumSelectedNodes(); } - else - { - return 0; - } + return 0; } // is the given connection valid - bool NodeGraphWidget::CheckIfIsCreateConnectionValid(uint32 portNr, GraphNode* portNode, NodePort* port, bool isInputPort) + bool NodeGraphWidget::CheckIfIsCreateConnectionValid(AZ::u16 portNr, GraphNode* portNode, NodePort* port, bool isInputPort) { MCORE_UNUSED(portNr); MCORE_UNUSED(port); @@ -1608,7 +1597,7 @@ namespace EMStudio return true; } - void NodeGraphWidget::OnCreateConnection(uint32 sourcePortNr, GraphNode* sourceNode, bool sourceIsInputPort, uint32 targetPortNr, GraphNode* targetNode, bool targetIsInputPort, const QPoint& startOffset, const QPoint& endOffset) + void NodeGraphWidget::OnCreateConnection(AZ::u16 sourcePortNr, GraphNode* sourceNode, bool sourceIsInputPort, AZ::u16 targetPortNr, GraphNode* targetNode, bool targetIsInputPort, const QPoint& startOffset, const QPoint& endOffset) { AZ_UNUSED(sourcePortNr); AZ_UNUSED(sourceNode); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGraphWidget.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGraphWidget.h index 111a0f3e3a..d8b73ee5be 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGraphWidget.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGraphWidget.h @@ -59,7 +59,7 @@ namespace EMStudio MCORE_INLINE void SetMousePos(const QPoint& pos) { mMousePos = pos; } MCORE_INLINE void SetShowFPS(bool showFPS) { mShowFPS = showFPS; } - uint32 CalcNumSelectedNodes() const; + size_t CalcNumSelectedNodes() const; QPoint LocalToGlobal(const QPoint& inPoint) const; QPoint GlobalToLocal(const QPoint& inPoint) const; @@ -69,7 +69,7 @@ namespace EMStudio virtual bool PreparePainting() { return true; } - virtual bool CheckIfIsCreateConnectionValid(uint32 portNr, GraphNode* portNode, NodePort* port, bool isInputPort); + virtual bool CheckIfIsCreateConnectionValid(AZ::u16 portNr, GraphNode* portNode, NodePort* port, bool isInputPort); virtual bool CheckIfIsValidTransition(GraphNode* sourceState, GraphNode* targetState); virtual bool CheckIfIsValidTransitionSource(GraphNode* sourceState); virtual bool CreateConnectionMustBeCurved() { return true; } @@ -80,7 +80,7 @@ namespace EMStudio virtual void OnMoveStart() {} virtual void OnMoveNode(GraphNode* node, int32 x, int32 y) { MCORE_UNUSED(node); MCORE_UNUSED(x); MCORE_UNUSED(y); } virtual void OnMoveEnd() {} - virtual void OnCreateConnection(uint32 sourcePortNr, GraphNode* sourceNode, bool sourceIsInputPort, uint32 targetPortNr, GraphNode* targetNode, bool targetIsInputPort, const QPoint& startOffset, const QPoint& endOffset); + virtual void OnCreateConnection(AZ::u16 sourcePortNr, GraphNode* sourceNode, bool sourceIsInputPort, AZ::u16 targetPortNr, GraphNode* targetNode, bool targetIsInputPort, const QPoint& startOffset, const QPoint& endOffset); virtual void OnNodeCollapsed(GraphNode* node, bool isCollapsed) { MCORE_UNUSED(node); MCORE_UNUSED(isCollapsed); } virtual void OnShiftClickedNode(GraphNode* node) { MCORE_UNUSED(node); } virtual void OnVisualizeToggle(GraphNode* node, bool visualizeEnabled) { MCORE_UNUSED(node); MCORE_UNUSED(visualizeEnabled); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGroupWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGroupWindow.cpp index 51b170c5aa..3183bc8a0f 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGroupWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGroupWindow.cpp @@ -12,6 +12,7 @@ #include #include #include +#include "MCore/Source/Config.h" #include "NodeGroupWindow.h" #include "AnimGraphPlugin.h" #include "GraphNode.h" @@ -111,8 +112,8 @@ namespace EMStudio else { // find duplicate name in the anim graph other than this node group - const uint32 numNodeGroups = mAnimGraph->GetNumNodeGroups(); - for (uint32 i = 0; i < numNodeGroups; ++i) + const size_t numNodeGroups = mAnimGraph->GetNumNodeGroups(); + for (size_t i = 0; i < numNodeGroups; ++i) { EMotionFX::AnimGraphNodeGroup* nodeGroup = mAnimGraph->GetNodeGroup(i); if (nodeGroup->GetNameString() == convertedNewName) @@ -285,13 +286,13 @@ namespace EMStudio const QList selectedItems = mTableWidget->selectedItems(); // get the number of selected items - const uint32 numSelectedItems = selectedItems.count(); + const int numSelectedItems = selectedItems.count(); // filter the items selectedNodeGroups.reserve(numSelectedItems); - for (uint32 i = 0; i < numSelectedItems; ++i) + for (int i = 0; i < numSelectedItems; ++i) { - const uint32 rowIndex = selectedItems[i]->row(); + const int rowIndex = selectedItems[i]->row(); const AZStd::string nodeGroupName = FromQtString(mTableWidget->item(rowIndex, 2)->text()); if (AZStd::find(begin(selectedNodeGroups), end(selectedNodeGroups), nodeGroupName) == end(selectedNodeGroups)) { @@ -315,7 +316,7 @@ namespace EMStudio mTableWidget->blockSignals(true); // get the number of node groups - const uint32 numNodeGroups = animGraph->GetNumNodeGroups(); + const int numNodeGroups = aznumeric_caster(animGraph->GetNumNodeGroups()); // set table size and add header items mTableWidget->setRowCount(numNodeGroups); @@ -324,7 +325,7 @@ namespace EMStudio mTableWidget->setSortingEnabled(false); // add each node group - for (uint32 i = 0; i < numNodeGroups; ++i) + for (int i = 0; i < numNodeGroups; ++i) { // get a pointer to the node group EMotionFX::AnimGraphNodeGroup* nodeGroup = animGraph->GetNodeGroup(i); @@ -452,19 +453,13 @@ namespace EMStudio // find the index for the given widget - uint32 NodeGroupWindow::FindGroupIndexByWidget(QObject* widget) const + int NodeGroupWindow::FindGroupIndexByWidget(QObject* widget) const { - // for all table entries - const uint32 numWidgets = mWidgetTable.size(); - for (uint32 i = 0; i < numWidgets; ++i) + const auto foundGroup = AZStd::find_if(begin(mWidgetTable), end(mWidgetTable), [widget](const auto& tableEntry) { - if (mWidgetTable[i].mWidget == widget) // this is button we search for - { - return mWidgetTable[i].mGroupIndex; - } - } - - return MCORE_INVALIDINDEX32; + return tableEntry.mWidget == widget; + }); + return foundGroup != end(mWidgetTable) ? foundGroup->mGroupIndex : MCore::InvalidIndexT; } @@ -478,8 +473,8 @@ namespace EMStudio } // get the node group index by checking the widget lookup table - const uint32 groupIndex = row; - assert(groupIndex != MCORE_INVALIDINDEX32); + const int groupIndex = row; + assert(groupIndex != MCore::InvalidIndexT); // get a pointer to the node group EMotionFX::AnimGraphNodeGroup* nodeGroup = animGraph->GetNodeGroup(groupIndex); @@ -516,8 +511,8 @@ namespace EMStudio } // get the node group index by checking the widget lookup table - const uint32 groupIndex = FindGroupIndexByWidget(sender()); - assert(groupIndex != MCORE_INVALIDINDEX32); + const int groupIndex = FindGroupIndexByWidget(sender()); + assert(groupIndex != MCore::InvalidIndexT); // get a pointer to the node group EMotionFX::AnimGraphNodeGroup* nodeGroup = animGraph->GetNodeGroup(groupIndex); @@ -574,18 +569,18 @@ namespace EMStudio const QList selectedItems = mTableWidget->selectedItems(); // get the number of selected items - const uint32 numSelectedItems = selectedItems.count(); - if (numSelectedItems == 0) + const int numSelectedItems = selectedItems.count(); + if (selectedItems.empty()) { return; } // filter the items - AZStd::vector rowIndices; + AZStd::vector rowIndices; rowIndices.reserve(numSelectedItems); - for (uint32 i = 0; i < numSelectedItems; ++i) + for (int i = 0; i < numSelectedItems; ++i) { - const uint32 rowIndex = selectedItems[i]->row(); + const int rowIndex = selectedItems[i]->row(); if (AZStd::find(begin(rowIndices), end(rowIndices), rowIndex) == end(rowIndices)) { rowIndices.emplace_back(rowIndex); @@ -597,7 +592,7 @@ namespace EMStudio AZStd::sort(begin(rowIndices), end(rowIndices)); // get the number of selected rows - const uint32 numRowIndices = rowIndices.size(); + const size_t numRowIndices = rowIndices.size(); // set the command group name AZStd::string commandGroupName; @@ -607,7 +602,7 @@ namespace EMStudio } else { - commandGroupName = AZStd::string::format("Remove %d node groups", numRowIndices); + commandGroupName = AZStd::string::format("Remove %zu node groups", numRowIndices); } // create the command group @@ -615,7 +610,7 @@ namespace EMStudio // Add each command AZStd::string tempString; - for (uint32 i = 0; i < numRowIndices; ++i) + for (size_t i = 0; i < numRowIndices; ++i) { const AZStd::string nodeGroupName = FromQtString(mTableWidget->item(rowIndices[i], 2)->text()); if (i == 0 || i == numRowIndices - 1) @@ -636,7 +631,7 @@ namespace EMStudio } // selected the next row - if (rowIndices[0] > ((uint32)mTableWidget->rowCount() - 1)) + if (rowIndices[0] > (mTableWidget->rowCount() - 1)) { mTableWidget->selectRow(rowIndices[0] - 1); } @@ -723,18 +718,18 @@ namespace EMStudio const QList selectedItems = mTableWidget->selectedItems(); // get the number of selected items - const uint32 numSelectedItems = selectedItems.count(); - if (numSelectedItems == 0) + const int numSelectedItems = selectedItems.count(); + if (selectedItems.empty()) { return; } // filter the items - AZStd::vector rowIndices; + AZStd::vector rowIndices; rowIndices.reserve(numSelectedItems); - for (uint32 i = 0; i < numSelectedItems; ++i) + for (int i = 0; i < numSelectedItems; ++i) { - const uint32 rowIndex = selectedItems[i]->row(); + const int rowIndex = selectedItems[i]->row(); if (AZStd::find(begin(rowIndices), end(rowIndices), rowIndex) == end(rowIndices)) { rowIndices.emplace_back(rowIndex); @@ -752,7 +747,7 @@ namespace EMStudio } // at least one selected, remove action is possible - if (rowIndices.size() > 0) + if (!rowIndices.empty()) { menu.addSeparator(); QAction* removeAction = menu.addAction("Remove Selected Node Groups"); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGroupWindow.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGroupWindow.h index 5f0354b223..e19b831790 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGroupWindow.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGroupWindow.h @@ -91,7 +91,7 @@ namespace EMStudio void contextMenuEvent(QContextMenuEvent* event) override; - uint32 FindGroupIndexByWidget(QObject* widget) const; + int FindGroupIndexByWidget(QObject* widget) const; //bool ValidateName(EMotionFX::AnimGraphNodeGroup* nodeGroup, const char* newName) const; MCORE_DEFINECOMMANDCALLBACK(CommandAnimGraphAddNodeGroupCallback); @@ -105,7 +105,7 @@ namespace EMStudio struct WidgetLookup { QObject* mWidget; - uint32 mGroupIndex; + int mGroupIndex; }; AnimGraphPlugin* mPlugin; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ParameterWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ParameterWindow.cpp index f470b061c5..9664011083 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ParameterWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ParameterWindow.cpp @@ -865,14 +865,14 @@ namespace EMStudio AZStd::vector result; const CommandSystem::SelectionList& selectionList = GetCommandManager()->GetCurrentSelection(); - const uint32 numActorInstances = selectionList.GetNumSelectedActorInstances(); - for (uint32 i = 0; i < numActorInstances; ++i) + const size_t numActorInstances = selectionList.GetNumSelectedActorInstances(); + for (size_t i = 0; i < numActorInstances; ++i) { const EMotionFX::ActorInstance* actorInstance = selectionList.GetActorInstance(i); const EMotionFX::AnimGraphInstance* animGraphInstance = actorInstance->GetAnimGraphInstance(); if (animGraphInstance && animGraphInstance->GetAnimGraph() == m_animGraph) { - result.emplace_back(animGraphInstance->GetParameterValue(static_cast(parameterIndex))); + result.emplace_back(animGraphInstance->GetParameterValue(parameterIndex)); } } @@ -930,7 +930,7 @@ namespace EMStudio // Construct the create parameter command and add it to the command group. const AZStd::unique_ptr& parameter = createEditParameterDialog->GetParameter(); - CommandSystem::ConstructCreateParameterCommand(commandString, m_animGraph, parameter.get(), MCORE_INVALIDINDEX32); + CommandSystem::ConstructCreateParameterCommand(commandString, m_animGraph, parameter.get()); commandGroup.AddCommandString(commandString); const EMotionFX::GroupParameter* parentGroup = nullptr; @@ -1033,7 +1033,7 @@ namespace EMStudio { // Get the list of connections from the port whose type is // being changed - const uint32 sourcePortIndex = parameterNode->FindOutputPortIndex(parameter->GetName().c_str()); + const size_t sourcePortIndex = parameterNode->FindOutputPortIndex(parameter->GetName().c_str()); AZStd::vector> outgoingConnectionsFromThisPort; parameterNode->CollectOutgoingConnections(outgoingConnectionsFromThisPort, sourcePortIndex); @@ -1167,8 +1167,8 @@ namespace EMStudio } const EMotionFX::GroupParameterVector groupParameters = m_animGraph->RecursivelyGetGroupParameters(); const size_t logNumGroups = groupParameters.size(); - MCore::LogInfo("Group parameters: (%i)", logNumGroups); - for (uint32 g = 0; g < logNumGroups; ++g) + MCore::LogInfo("Group parameters: (%zu)", logNumGroups); + for (size_t g = 0; g < logNumGroups; ++g) { const EMotionFX::GroupParameter* groupParam = groupParameters[g]; MCore::LogInfo("Group parameter #%i: Name='%s'", g, groupParam->GetName().c_str()); @@ -1426,7 +1426,7 @@ namespace EMStudio const AZ::Outcome valueParameterIndex = m_animGraph->FindValueParameterIndex(valueParameter); if (valueParameterIndex.IsSuccess()) { - MCore::Attribute* instanceValue = animGraphInstance->GetParameterValue(static_cast(valueParameterIndex.GetValue())); + MCore::Attribute* instanceValue = animGraphInstance->GetParameterValue(valueParameterIndex.GetValue()); valueParameter->SetDefaultValueFromAttribute(instanceValue); m_animGraph->SetDirtyFlag(true); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/StateFilterSelectionWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/StateFilterSelectionWindow.cpp index 3a43d640e0..b7abf10da0 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/StateFilterSelectionWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/StateFilterSelectionWindow.cpp @@ -98,9 +98,9 @@ namespace EMStudio const EMotionFX::AnimGraph* animGraph = m_stateMachine->GetAnimGraph(); // get the number of nodes inside the active node, the number node groups and set table size and add header items - const uint32 numNodeGroups = animGraph->GetNumNodeGroups(); - const uint32 numNodes = m_stateMachine->GetNumChildNodes(); - const uint32 numRows = numNodeGroups + numNodes; + const size_t numNodeGroups = animGraph->GetNumNodeGroups(); + const size_t numNodes = m_stateMachine->GetNumChildNodes(); + const int numRows = aznumeric_caster(numNodeGroups + numNodes); mTableWidget->setRowCount(numRows); // Block signals for the table widget to not reach OnSelectionChanged() when adding rows as that diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/StateGraphNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/StateGraphNode.cpp index 0c4f8b8138..0ce567c366 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/StateGraphNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/StateGraphNode.cpp @@ -830,13 +830,13 @@ namespace EMStudio return MCore::Max(headerWidth, 100); } - QRect StateGraphNode::CalcInputPortRect(uint32 portNr) + QRect StateGraphNode::CalcInputPortRect(AZ::u16 portNr) { MCORE_UNUSED(portNr); return mRect.adjusted(10, 10, -10, -10); } - QRect StateGraphNode::CalcOutputPortRect(uint32 portNr) + QRect StateGraphNode::CalcOutputPortRect(AZ::u16 portNr) { switch (portNr) { diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/StateGraphNode.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/StateGraphNode.h index cf0f883199..cee57b4a4f 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/StateGraphNode.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/StateGraphNode.h @@ -54,7 +54,7 @@ namespace EMStudio bool CheckIfIsCloseToHead(const QPoint& point) const override; bool CheckIfIsCloseToTail(const QPoint& point) const override; - uint32 GetType() override { return TYPE_ID; } + uint32 GetType() const override { return TYPE_ID; } EMotionFX::AnimGraphTransitionCondition* FindCondition(const QPoint& mousePos); @@ -98,8 +98,8 @@ namespace EMStudio int32 CalcRequiredHeight() const override; int32 CalcRequiredWidth() override; - QRect CalcInputPortRect(uint32 portNr) override; - QRect CalcOutputPortRect(uint32 portNr) override; + QRect CalcInputPortRect(AZ::u16 portNr) override; + QRect CalcOutputPortRect(AZ::u16 portNr) override; void UpdateTextPixmap() override; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentNodesWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentNodesWindow.cpp index d84b22f5d5..78eab3d362 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentNodesWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentNodesWindow.cpp @@ -9,6 +9,7 @@ // inlude required headers #include "AttachmentNodesWindow.h" #include "../../../../EMStudioSDK/Source/EMStudioManager.h" +#include "AzCore/std/limits.h" #include #include @@ -144,11 +145,11 @@ namespace EMStudio mRemoveNodesButton->setEnabled((mNodeTable->rowCount() != 0) && (mNodeTable->selectedItems().size() != 0)); // counter for attachment nodes - size_t numAttachmentNodes = 0; + int numAttachmentNodes = 0; // set the row count - const size_t numNodes = mActor->GetNumNodes(); - for (size_t i = 0; i < numNodes; ++i) + const int numNodes = aznumeric_caster(mActor->GetNumNodes()); + for (int i = 0; i < numNodes; ++i) { // get the nodegroup EMotionFX::Node* node = mActor->GetSkeleton()->GetNode(i); @@ -162,7 +163,7 @@ namespace EMStudio mNodeTable->setRowCount(numAttachmentNodes); // set header items for the table - QTableWidgetItem* nameHeaderItem = new QTableWidgetItem(AZStd::string::format("Attachment Nodes (%zu / %zu)", numAttachmentNodes, mActor->GetNumNodes()).c_str()); + QTableWidgetItem* nameHeaderItem = new QTableWidgetItem(AZStd::string::format("Attachment Nodes (%d / %zu)", numAttachmentNodes, mActor->GetNumNodes()).c_str()); nameHeaderItem->setTextAlignment(Qt::AlignVCenter | Qt::AlignCenter); mNodeTable->setHorizontalHeaderItem(0, nameHeaderItem); @@ -250,8 +251,8 @@ namespace EMStudio mNodeSelectionList.Clear(); if (senderWidget == mSelectNodesButton) { - const uint32 numNodes = mActor->GetNumNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = mActor->GetNumNodes(); + for (size_t i = 0; i < numNodes; ++i) { EMotionFX::Node* node = mActor->GetSkeleton()->GetNode(i); if (node->GetIsAttachmentNode()) @@ -272,9 +273,9 @@ namespace EMStudio { // generate node list string AZStd::string nodeList; - uint32 lowestSelectedRow = MCORE_INVALIDINDEX32; - const uint32 numTableRows = mNodeTable->rowCount(); - for (uint32 i = 0; i < numTableRows; ++i) + int lowestSelectedRow = AZStd::numeric_limits::max(); + const int numTableRows = mNodeTable->rowCount(); + for (int i = 0; i < numTableRows; ++i) { // get the current table item QTableWidgetItem* item = mNodeTable->item(i, 0); @@ -287,9 +288,9 @@ namespace EMStudio if (item->isSelected()) { nodeList += AZStd::string::format("%s;", FromQtString(item->text()).c_str()); - if ((uint32)item->row() < lowestSelectedRow) + if (item->row() < lowestSelectedRow) { - lowestSelectedRow = (uint32)item->row(); + lowestSelectedRow = item->row(); } } } @@ -310,7 +311,7 @@ namespace EMStudio } // selected the next row - if (lowestSelectedRow > ((uint32)mNodeTable->rowCount() - 1)) + if (lowestSelectedRow > mNodeTable->rowCount() - 1) { mNodeTable->selectRow(lowestSelectedRow - 1); } @@ -324,8 +325,7 @@ namespace EMStudio // add / select nodes void AttachmentNodesWindow::NodeSelectionFinished(AZStd::vector selectionList) { - // return if no nodes are selected - if (selectionList.size() == 0) + if (selectionList.empty()) { return; } @@ -333,10 +333,9 @@ namespace EMStudio // generate node list string AZStd::string nodeList; nodeList.reserve(16384); - const uint32 numSelectedNodes = selectionList.size(); - for (uint32 i = 0; i < numSelectedNodes; ++i) + for (const SelectionItem& i : selectionList) { - nodeList += AZStd::string::format("%s;", selectionList[i].GetNodeName()); + nodeList += AZStd::string::format("%s;", i.GetNodeName()); } AzFramework::StringFunc::Strip(nodeList, MCore::CharacterConstants::semiColon, true /* case sensitive */, false /* beginning */, true /* ending */); @@ -364,7 +363,7 @@ namespace EMStudio // handle item selection changes of the node table void AttachmentNodesWindow::OnItemSelectionChanged() { - mRemoveNodesButton->setEnabled((mNodeTable->rowCount() != 0) && (mNodeTable->selectedItems().size() != 0)); + mRemoveNodesButton->setEnabled((mNodeTable->rowCount() != 0) && (!mNodeTable->selectedItems().empty())); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentsHierarchyWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentsHierarchyWindow.cpp index d7fd6727f8..536ff16f57 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentsHierarchyWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentsHierarchyWindow.cpp @@ -72,8 +72,8 @@ namespace EMStudio mHierarchy->clear(); // get the number of actor instances and iterate through them - const uint32 numActorInstances = EMotionFX::GetActorManager().GetNumActorInstances(); - for (uint32 i = 0; i < numActorInstances; ++i) + const size_t numActorInstances = EMotionFX::GetActorManager().GetNumActorInstances(); + for (size_t i = 0; i < numActorInstances; ++i) { EMotionFX::ActorInstance* actorInstance = EMotionFX::GetActorManager().GetActorInstance(i); @@ -96,8 +96,8 @@ namespace EMStudio mHierarchy->addTopLevelItem(item); // get the number of attachments and iterate through them - const uint32 numAttachments = actorInstance->GetNumAttachments(); - for (uint32 j = 0; j < numAttachments; ++j) + const size_t numAttachments = actorInstance->GetNumAttachments(); + for (size_t j = 0; j < numAttachments; ++j) { EMotionFX::Attachment* attachment = actorInstance->GetAttachment(j); MCORE_ASSERT(actorInstance == attachment->GetAttachToActorInstance()); @@ -124,8 +124,8 @@ namespace EMStudio parent->addChild(item); // get the number of attachments and iterate through them - const uint32 numAttachments = actorInstance->GetNumAttachments(); - for (uint32 i = 0; i < numAttachments; ++i) + const size_t numAttachments = actorInstance->GetNumAttachments(); + for (size_t i = 0; i < numAttachments; ++i) { EMotionFX::Attachment* attachment = actorInstance->GetAttachment(i); MCORE_ASSERT(actorInstance == attachment->GetAttachToActorInstance()); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentsWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentsWindow.cpp index c78d37dd7b..2ffc56d25b 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentsWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentsWindow.cpp @@ -8,6 +8,8 @@ // include required headers #include "AttachmentsWindow.h" +#include "AzCore/std/limits.h" +#include "MCore/Source/Config.h" #include #include #include @@ -236,13 +238,13 @@ namespace EMStudio } // the number of existing attachments - const uint32 numAttachments = mActorInstance->GetNumAttachments(); + const int numAttachments = aznumeric_caster(mActorInstance->GetNumAttachments()); // set table size and add header items mTableWidget->setRowCount(numAttachments); // loop trough all attachments and add them to the table - for (uint32 i = 0; i < numAttachments; ++i) + for (int i = 0; i < numAttachments; ++i) { EMotionFX::Attachment* attachment = mActorInstance->GetAttachment(i); if (attachment == nullptr) @@ -253,18 +255,11 @@ namespace EMStudio EMotionFX::ActorInstance* attachmentInstance = attachment->GetAttachmentActorInstance(); EMotionFX::Actor* attachmentActor = attachmentInstance->GetActor(); EMotionFX::Actor* attachedToActor = mActorInstance->GetActor(); - uint32 attachedToNodeIndex = MCORE_INVALIDINDEX32; - EMotionFX::Node* attachedToNode = nullptr; - - if (!attachment->GetIsInfluencedByMultipleJoints()) - { - attachedToNodeIndex = static_cast(attachment)->GetAttachToNodeIndex(); - } - - if (attachedToNodeIndex != MCORE_INVALIDINDEX32) - { - attachedToNode = attachedToActor->GetSkeleton()->GetNode(attachedToNodeIndex); - } + EMotionFX::Node* attachedToNode = + !attachment->GetIsInfluencedByMultipleJoints() + ? attachedToNode = attachedToActor->GetSkeleton()->GetNode( + static_cast(attachment)->GetAttachToNodeIndex()) + : nullptr; // create table items mTempString = AZStd::string::format("%i", attachmentInstance->GetID()); @@ -436,10 +431,10 @@ namespace EMStudio { EBUS_EVENT(AzFramework::ApplicationRequests::Bus, NormalizePathKeepCase, filename); - const uint32 actorIndex = EMotionFX::GetActorManager().FindActorIndexByFileName(filename.c_str()); + const size_t actorIndex = EMotionFX::GetActorManager().FindActorIndexByFileName(filename.c_str()); // create instance for the attachment - if (actorIndex == MCORE_INVALIDINDEX32) + if (actorIndex == InvalidIndex) { commandGroup.AddCommandString(AZStd::string::format("ImportActor -filename \"%s\"", filename.c_str()).c_str()); commandGroup.AddCommandString("CreateActorInstance -actorID %LASTRESULT%"); @@ -479,20 +474,18 @@ namespace EMStudio MCore::CommandGroup group(AZStd::string("Remove Attachment Actor").c_str()); // iterate trough all selected items - const uint32 numItems = items.length(); - for (uint32 i = 0; i < numItems; ++i) + for (const QTableWidgetItem* item : items) { - QTableWidgetItem* item = items[i]; if (item == nullptr || item->column() != 1) { continue; } // the attachment id - const uint32 id = GetIDFromTableRow(item->row()); + const int id = GetIDFromTableRow(item->row()); const AZStd::string nodeName = GetNodeNameFromTableRow(item->row()); - group.AddCommandString(AZStd::string::format("RemoveAttachment -attachmentID %i -attachToID %i -attachToNode \"%s\"", id, mActorInstance->GetID(), nodeName.c_str()).c_str()); + group.AddCommandString(AZStd::string::format("RemoveAttachment -attachmentID %d -attachToID %i -attachToNode \"%s\"", id, mActorInstance->GetID(), nodeName.c_str()).c_str()); } // execute the group command @@ -708,20 +701,19 @@ namespace EMStudio // remove selected attachments void AttachmentsWindow::OnRemoveButtonClicked() { - uint32 lowestSelectedRow = MCORE_INVALIDINDEX32; + int lowestSelectedRow = AZStd::numeric_limits::max(); const QList selectedItems = mTableWidget->selectedItems(); - const int numSelectedItems = selectedItems.size(); - for (int i = 0; i < numSelectedItems; ++i) + for (const QTableWidgetItem* selectedItem : selectedItems) { - if ((uint32)selectedItems[i]->row() < lowestSelectedRow) + if (selectedItem->row() < lowestSelectedRow) { - lowestSelectedRow = (uint32)selectedItems[i]->row(); + lowestSelectedRow = selectedItem->row(); } } RemoveTableItems(selectedItems); - if (lowestSelectedRow > ((uint32)mTableWidget->rowCount() - 1)) + if (lowestSelectedRow > (mTableWidget->rowCount() - 1)) { mTableWidget->selectRow(lowestSelectedRow - 1); } @@ -808,7 +800,7 @@ namespace EMStudio AZStd::string AttachmentsWindow::GetSelectedNodeName() { const QList items = mTableWidget->selectedItems(); - const uint32 numItems = items.length(); + const size_t numItems = items.length(); if (numItems < 1) { return AZStd::string(); @@ -845,7 +837,7 @@ namespace EMStudio QTableWidgetItem* item = mTableWidget->item(row, 1); if (item == nullptr) { - return MCORE_INVALIDINDEX32; + return MCore::InvalidIndexT; } AZStd::string id; @@ -861,7 +853,7 @@ namespace EMStudio QTableWidgetItem* item = mTableWidget->item(row, 4); if (item == nullptr) { - return AZStd::string(); + return {}; } return FromQtString(item->whatsThis()); @@ -872,11 +864,11 @@ namespace EMStudio int AttachmentsWindow::GetRowContainingWidget(const QWidget* widget) { // loop trough the table items and search for widget - const uint32 numRows = mTableWidget->rowCount(); - const uint32 numCols = mTableWidget->columnCount(); - for (uint32 i = 0; i < numRows; ++i) + const int numRows = mTableWidget->rowCount(); + const int numCols = mTableWidget->columnCount(); + for (int i = 0; i < numRows; ++i) { - for (uint32 j = 0; j < numCols; ++j) + for (int j = 0; j < numCols; ++j) { if (mTableWidget->cellWidget(i, j) == widget) { diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/LogWindow/LogWindowCallback.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/LogWindow/LogWindowCallback.cpp index 51c7e1d8de..fa039c1666 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/LogWindow/LogWindowCallback.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/LogWindow/LogWindowCallback.cpp @@ -281,7 +281,7 @@ namespace EMStudio const QList items = selectedItems(); // get the number of selected items - const uint32 numSelectedItems = items.count(); + const int numSelectedItems = items.count(); // check if nothing needed to be copied if (numSelectedItems == 0) @@ -290,11 +290,11 @@ namespace EMStudio } // filter the items - AZStd::vector rowIndices; + AZStd::vector rowIndices; rowIndices.reserve(numSelectedItems); - for (uint32 i = 0; i < numSelectedItems; ++i) + for (int i = 0; i < numSelectedItems; ++i) { - const uint32 rowIndex = items[i]->row(); + const int rowIndex = items[i]->row(); if (AZStd::find(begin(rowIndices), end(rowIndices), rowIndex) == end(rowIndices)) { rowIndices.emplace_back(rowIndex); @@ -305,12 +305,12 @@ namespace EMStudio AZStd::sort(begin(rowIndices), end(rowIndices)); // get the number of selected rows - const uint32 numSelectedRows = rowIndices.size(); + const size_t numSelectedRows = rowIndices.size(); // genereate the clipboard text QString clipboardText; - const uint32 lastIndex = numSelectedRows - 1; - for (uint32 i = 0; i < numSelectedRows; ++i) + const size_t lastIndex = numSelectedRows - 1; + for (size_t i = 0; i < numSelectedRows; ++i) { const QString time = item(rowIndices[i], 0)->text(); const QString message = item(rowIndices[i], 1)->text(); @@ -360,7 +360,7 @@ namespace EMStudio QMenu menu(this); // add actions - if (items.size() > 0) + if (!items.empty()) { QAction* copyAction = menu.addAction("Copy"); connect(copyAction, &QAction::triggered, this, &LogWindowCallback::Copy); @@ -370,7 +370,7 @@ namespace EMStudio QAction* selectAllAction = menu.addAction("Select All"); connect(selectAllAction, &QAction::triggered, this, &LogWindowCallback::SelectAll); } - if (items.size() > 0) + if (!items.empty()) { QAction* UnselectAllAction = menu.addAction("Unselect All"); connect(UnselectAllAction, &QAction::triggered, this, &LogWindowCallback::UnselectAll); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/LogWindow/LogWindowPlugin.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/LogWindow/LogWindowPlugin.cpp index 49bf04bf3b..a9a7c6a174 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/LogWindow/LogWindowPlugin.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/LogWindow/LogWindowPlugin.cpp @@ -28,8 +28,8 @@ namespace EMStudio LogWindowPlugin::~LogWindowPlugin() { // remove the callback from the log manager (automatically deletes from memory as well) - const uint32 index = MCore::GetLogManager().FindLogCallback(mLogCallback); - if (index != MCORE_INVALIDINDEX32) + const size_t index = MCore::GetLogManager().FindLogCallback(mLogCallback); + if (index != InvalidIndex) { MCore::GetLogManager().RemoveLogCallback(index); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/PhonemeSelectionWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/PhonemeSelectionWindow.cpp index 704351a4bb..910f8456e5 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/PhonemeSelectionWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/PhonemeSelectionWindow.cpp @@ -133,7 +133,7 @@ namespace EMStudio // constructor - PhonemeSelectionWindow::PhonemeSelectionWindow(EMotionFX::Actor* actor, uint32 lodLevel, EMotionFX::MorphTarget* morphTarget, QWidget* parent) + PhonemeSelectionWindow::PhonemeSelectionWindow(EMotionFX::Actor* actor, size_t lodLevel, EMotionFX::MorphTarget* morphTarget, QWidget* parent) : QDialog(parent) { // set the initial size @@ -327,14 +327,14 @@ namespace EMStudio mSelectedPhonemeSetsTable->clear(); // get number of morph targets - const uint32 numMorphTargets = mMorphSetup->GetNumMorphTargets(); + const size_t numMorphTargets = mMorphSetup->GetNumMorphTargets(); const uint32 numPhonemeSets = mMorphTarget->GetNumAvailablePhonemeSets(); - uint32 insertPosition = 0; - for (uint32 i = 1; i < numPhonemeSets; ++i) + int insertPosition = 0; + for (int i = 1; i < numPhonemeSets; ++i) { // check if another morph target already has this phoneme set. bool phonemeSetFound = false; - for (uint32 j = 0; j < numMorphTargets; ++j) + for (size_t j = 0; j < numMorphTargets; ++j) { EMotionFX::MorphTarget* morphTarget = mMorphSetup->GetMorphTarget(j); if (morphTarget->GetIsPhonemeSetEnabled((EMotionFX::MorphTarget::EPhonemeSet)(1 << i))) @@ -381,9 +381,9 @@ namespace EMStudio AzFramework::StringFunc::Tokenize(selectedPhonemeSets.c_str(), splittedPhonemeSets, MCore::CharacterConstants::comma, true /* keep empty strings */, true /* keep space strings */); - const uint32 numSelectedPhonemeSets = static_cast(splittedPhonemeSets.size()); + const int numSelectedPhonemeSets = aznumeric_caster(splittedPhonemeSets.size()); mSelectedPhonemeSetsTable->setRowCount(numSelectedPhonemeSets); - for (uint32 i = 0; i < numSelectedPhonemeSets; ++i) + for (int i = 0; i < numSelectedPhonemeSets; ++i) { // create dummy table widget item. const EMotionFX::MorphTarget::EPhonemeSet phonemeSet = mMorphTarget->FindPhonemeSet(splittedPhonemeSets[i].c_str()); @@ -425,7 +425,7 @@ namespace EMStudio QTableWidget* table = (QTableWidget*)sender(); // disable/enable buttons - bool selected = (table->selectedItems().size() > 0); + bool selected = !table->selectedItems().empty(); if (table == mPossiblePhonemeSetsTable) { mAddPhonemesButton->setDisabled(!selected); @@ -438,8 +438,8 @@ namespace EMStudio } // adjust selection state of the cell widgetsmActor - const uint32 numRows = table->rowCount(); - for (uint32 i = 0; i < numRows; ++i) + const int numRows = table->rowCount(); + for (int i = 0; i < numRows; ++i) { // get the table widget item and check if it exists QTableWidgetItem* item = table->item(i, 0); @@ -462,21 +462,20 @@ namespace EMStudio void PhonemeSelectionWindow::RemoveSelectedPhonemeSets() { QList selectedItems = mSelectedPhonemeSetsTable->selectedItems(); - const uint32 numSelectedItems = selectedItems.size(); - if (numSelectedItems == 0) + if (selectedItems.empty()) { return; } // create phoneme sets string from the selected phoneme sets AZStd::string phonemeSets; - for (uint32 i = 0; i < numSelectedItems; ++i) + for (const QTableWidgetItem* selectedItem : selectedItems) { - phonemeSets += AZStd::string::format("%s,", selectedItems[i]->text().toUtf8().data()); + phonemeSets += AZStd::string::format("%s,", selectedItem->text().toUtf8().data()); } // call command to remove selected the phoneme sets - const AZStd::string command = AZStd::string::format("AdjustMorphTarget -actorID %i -lodLevel %i -name \"%s\" -phonemeAction \"remove\" -phonemeSets \"%s\"", mActor->GetID(), mLODLevel, mMorphTarget->GetName(), phonemeSets.c_str()); + const AZStd::string command = AZStd::string::format("AdjustMorphTarget -actorID %i -lodLevel %zu -name \"%s\" -phonemeAction \"remove\" -phonemeSets \"%s\"", mActor->GetID(), mLODLevel, mMorphTarget->GetName(), phonemeSets.c_str()); AZStd::string result; if (!EMStudio::GetCommandManager()->ExecuteCommand(command, result)) @@ -494,21 +493,20 @@ namespace EMStudio void PhonemeSelectionWindow::AddSelectedPhonemeSets() { QList selectedItems = mSelectedPhonemeSetsTable->selectedItems(); - const uint32 numSelectedItems = selectedItems.size(); - if (numSelectedItems == 0) + if (selectedItems.empty()) { return; } // create phoneme sets string from the selected phoneme sets AZStd::string phonemeSets; - for (uint32 i = 0; i < numSelectedItems; ++i) + for (const QTableWidgetItem* selectedItem : selectedItems) { - phonemeSets += AZStd::string::format("%s,", selectedItems[i]->text().toUtf8().data()); + phonemeSets += AZStd::string::format("%s,", selectedItem->text().toUtf8().data()); } // call command to add the selected phoneme sets - const AZStd::string command = AZStd::string::format("AdjustMorphTarget -actorID %i -lodLevel %i -name \"%s\" -phonemeAction \"add\" -phonemeSets \"%s\"", mActor->GetID(), mLODLevel, mMorphTarget->GetName(), phonemeSets.c_str()); + const AZStd::string command = AZStd::string::format("AdjustMorphTarget -actorID %i -lodLevel %zu -name \"%s\" -phonemeAction \"add\" -phonemeSets \"%s\"", mActor->GetID(), mLODLevel, mMorphTarget->GetName(), phonemeSets.c_str()); AZStd::string result; if (!EMStudio::GetCommandManager()->ExecuteCommand(command, result)) diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/PhonemeSelectionWindow.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/PhonemeSelectionWindow.h index 70ce72a281..a6bffffb75 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/PhonemeSelectionWindow.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/PhonemeSelectionWindow.h @@ -117,7 +117,7 @@ namespace EMStudio MCORE_MEMORYOBJECTCATEGORY(PhonemeSelectionWindow, MCore::MCORE_DEFAULT_ALIGNMENT, MEMCATEGORY_EMSTUDIOSDK) public: - PhonemeSelectionWindow(EMotionFX::Actor* actor, uint32 lodLevel, EMotionFX::MorphTarget* morphTarget, QWidget* parent = nullptr); + PhonemeSelectionWindow(EMotionFX::Actor* actor, size_t lodLevel, EMotionFX::MorphTarget* morphTarget, QWidget* parent = nullptr); virtual ~PhonemeSelectionWindow(); void Init(); @@ -140,7 +140,7 @@ namespace EMStudio // the morph target EMotionFX::Actor* mActor; EMotionFX::MorphTarget* mMorphTarget; - uint32 mLODLevel; + size_t mLODLevel; EMotionFX::MorphSetup* mMorphSetup; // the dialogstacks diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetManagementWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetManagementWindow.cpp index 441c9555a7..5943263e3d 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetManagementWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetManagementWindow.cpp @@ -6,6 +6,8 @@ * */ +#include "AzCore/std/algorithm.h" +#include "AzCore/std/iterator.h" #include #include #include @@ -70,11 +72,11 @@ namespace EMStudio tableWidget->verticalHeader()->setVisible(false); // set the number of rows - const uint32 numMotions = motions.size(); + const int numMotions = aznumeric_caster(motions.size()); tableWidget->setRowCount(numMotions); // add each motion in the table - for (uint32 i = 0; i < numMotions; ++i) + for (int i = 0; i < numMotions; ++i) { // get the motion EMotionFX::Motion* motion = motions[i]; @@ -182,8 +184,8 @@ namespace EMStudio else { // find duplicate name in all motion sets other than this motion set - const uint32 numMotionSets = EMotionFX::GetMotionManager().GetNumMotionSets(); - for (uint32 i = 0; i < numMotionSets; ++i) + const size_t numMotionSets = EMotionFX::GetMotionManager().GetNumMotionSets(); + for (size_t i = 0; i < numMotionSets; ++i) { EMotionFX::MotionSet* motionSet = EMotionFX::GetMotionManager().GetMotionSet(i); @@ -359,8 +361,8 @@ namespace EMStudio } // Recursively add all child sets. - const uint32 numChildSets = motionSet->GetNumChildSets(); - for (uint32 i = 0; i < numChildSets; ++i) + const size_t numChildSets = motionSet->GetNumChildSets(); + for (size_t i = 0; i < numChildSets; ++i) { EMotionFX::MotionSet* childSet = motionSet->GetChildSet(i); RecursivelyAddSets(item, childSet, selectedSetIDs); @@ -372,16 +374,15 @@ namespace EMStudio { // Get the selected items in the motion set tree widget.. const QList selectedItems = mMotionSetsTree->selectedItems(); - const int numSelectedItems = selectedItems.count(); + const int numSelectedItems = selectedItems.size(); // Create and fill an array containing ids of all selected motion sets. AZStd::vector selectedMotionSetIDs; - selectedMotionSetIDs.resize(numSelectedItems); - for (int32 i = 0; i < numSelectedItems; ++i) + selectedMotionSetIDs.reserve(numSelectedItems); + AZStd::transform(selectedItems.begin(), selectedItems.end(), AZStd::back_inserter(selectedMotionSetIDs), [](const QTreeWidgetItem* selectedItem) { - const int motionSetId = AzFramework::StringFunc::ToInt(selectedItems[i]->whatsThis(0).toUtf8().data()); - selectedMotionSetIDs[i] = motionSetId; - } + return selectedItem->whatsThis(0).toUInt(); + }); // Set the sorting disabled to avoid index issues. mMotionSetsTree->setSortingEnabled(false); @@ -392,8 +393,8 @@ namespace EMStudio // Iterate through root motion sets and fill in the table recursively. AZStd::string tempString; - const uint32 numMotionSets = EMotionFX::GetMotionManager().GetNumMotionSets(); - for (uint32 i = 0; i < numMotionSets; ++i) + const size_t numMotionSets = EMotionFX::GetMotionManager().GetNumMotionSets(); + for (size_t i = 0; i < numMotionSets; ++i) { // Only process root motion sets. EMotionFX::MotionSet* motionSet = EMotionFX::GetMotionManager().GetMotionSet(i); @@ -446,8 +447,8 @@ namespace EMStudio } // get the number of children and iterate through them - const uint32 numChildSets = motionSet->GetNumChildSets(); - for (uint32 j = 0; j < numChildSets; ++j) + const size_t numChildSets = motionSet->GetNumChildSets(); + for (size_t j = 0; j < numChildSets; ++j) { // get the child set EMotionFX::MotionSet* childSet = motionSet->GetChildSet(j); @@ -468,7 +469,7 @@ namespace EMStudio void MotionSetManagementWindow::OnSelectionChanged() { const QList selectedItems = mMotionSetsTree->selectedItems(); - const uint32 numSelected = selectedItems.count(); + const size_t numSelected = selectedItems.count(); if (numSelected != 1) { mPlugin->SetSelectedSet(nullptr); @@ -547,7 +548,7 @@ namespace EMStudio const AZStd::string uniqueMotionSetName = MCore::GenerateUniqueString("MotionSet", [&](const AZStd::string& value) { - return (EMotionFX::GetMotionManager().FindMotionSetIndexByName(value.c_str()) == MCORE_INVALIDINDEX32); + return (EMotionFX::GetMotionManager().FindMotionSetIndexByName(value.c_str()) == InvalidIndex); }); // Construct the command string. @@ -585,7 +586,7 @@ namespace EMStudio uniqueMotionSetName = MCore::GenerateUniqueString("MotionSet", [&](const AZStd::string& value) { - return (EMotionFX::GetMotionManager().FindMotionSetIndexByName(value.c_str()) == MCORE_INVALIDINDEX32) && + return (EMotionFX::GetMotionManager().FindMotionSetIndexByName(value.c_str()) == InvalidIndex) && (parentMotionSetByName.find(value) == parentMotionSetByName.end()); }); @@ -649,16 +650,15 @@ namespace EMStudio { // Get the selected items from the motion set tree widget. const QList selectedItems = mMotionSetsTree->selectedItems(); - const int numSelectedItems = selectedItems.count(); - outSelectedMotionSets.resize(numSelectedItems); + outSelectedMotionSets.resize(selectedItems.size()); // Find the corresponding motion sets and add them to the array. - for (int32 i = 0; i < numSelectedItems; ++i) + AZStd::transform(selectedItems.begin(), selectedItems.end(), outSelectedMotionSets.begin(), [](const QTreeWidgetItem* selectedItem) { - const int motionSetId = AzFramework::StringFunc::ToInt(selectedItems[i]->whatsThis(0).toUtf8().data()); - outSelectedMotionSets[i] = EMotionFX::GetMotionManager().FindMotionSetByID(motionSetId); - } + const uint32 motionSetId = selectedItem->whatsThis(0).toUInt(); + return EMotionFX::GetMotionManager().FindMotionSetByID(motionSetId); + }); } @@ -681,8 +681,8 @@ namespace EMStudio } // Do the same for all child motion sets recursively. - const uint32 numChildSets = motionSet->GetNumChildSets(); - for (uint32 i = 0; i < numChildSets; ++i) + const size_t numChildSets = motionSet->GetNumChildSets(); + for (size_t i = 0; i < numChildSets; ++i) { EMotionFX::MotionSet* childSet = motionSet->GetChildSet(i); RecursiveIncreaseMotionsReferenceCount(childSet); @@ -693,8 +693,8 @@ namespace EMStudio void MotionSetManagementWindow::RecursiveRemoveMotionsFromSet(EMotionFX::MotionSet* motionSet, MCore::CommandGroup& commandGroup, AZStd::vector& failedRemoveMotions) { // Recursively remove motions from the all entries in the child motion sets. - const uint32 numChildSets = motionSet->GetNumChildSets(); - for (uint32 i = 0; i < numChildSets; ++i) + const size_t numChildSets = motionSet->GetNumChildSets(); + for (size_t i = 0; i < numChildSets; ++i) { EMotionFX::MotionSet* childSet = motionSet->GetChildSet(i); RecursiveRemoveMotionsFromSet(childSet, commandGroup, failedRemoveMotions); @@ -722,22 +722,18 @@ namespace EMStudio void MotionSetManagementWindow::OnRemoveSelectedMotionSets() { const QList selectedItems = mMotionSetsTree->selectedItems(); - const uint32 numSelected = selectedItems.count(); - if (numSelected <= 0) + if (selectedItems.empty()) { return; } // ask to remove motions - bool removeMotions; - if (QMessageBox::question(this, "Remove Motions From Project?", "Remove the motions from the project entirely? This would also remove them from the motion list. Pressing no will remove them from the motion set but keep them inside the motion list inside the motions window.", QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes) == QMessageBox::Yes) - { - removeMotions = true; - } - else - { - removeMotions = false; - } + const bool removeMotions = QMessageBox::question( + this, + "Remove Motions From Project?", + "Remove the motions from the project entirely? This would also remove them from the motion list. Pressing no will remove them from the motion set but keep them inside the motion list inside the motions window.", + QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes + ) == QMessageBox::Yes; // create our command group MCore::CommandGroup commandGroup("Remove motion sets"); @@ -747,10 +743,10 @@ namespace EMStudio // get the number of selected motion sets and iterate through them AZStd::set toBeRemoved; - for (int32 i = numSelected - 1; i >= 0; --i) + for (auto selectedItem = selectedItems.crbegin(); selectedItem != selectedItems.crend(); ++selectedItem) { // get the motion set ID - const uint32 motionSetID = AzFramework::StringFunc::ToInt(FromQtString(selectedItems[i]->whatsThis(0)).c_str()); + const uint32 motionSetID = (*selectedItem)->whatsThis(0).toInt(); // get the current motion set and only process the root sets EMotionFX::MotionSet* motionSet = EMotionFX::GetMotionManager().FindMotionSetByID(motionSetID); @@ -817,8 +813,8 @@ namespace EMStudio // Increase the reference counter if needed for each motion. AZStd::string commandString; - const uint32 numMotionSets = EMotionFX::GetMotionManager().GetNumMotionSets(); - for (uint32 i = 0; i < numMotionSets; ++i) + const size_t numMotionSets = EMotionFX::GetMotionManager().GetNumMotionSets(); + for (size_t i = 0; i < numMotionSets; ++i) { EMotionFX::MotionSet* motionSet = EMotionFX::GetMotionManager().GetMotionSet(i); @@ -850,7 +846,7 @@ namespace EMStudio if (removeMotions) { AZStd::string motionFileName; - for (uint32 i = 0; i < numMotionSets; ++i) + for (size_t i = 0; i < numMotionSets; ++i) { EMotionFX::MotionSet* motionSet = EMotionFX::GetMotionManager().GetMotionSet(i); @@ -902,7 +898,7 @@ namespace EMStudio rootItem = rootItem->parent(); } - const uint32 motionSetID = AzFramework::StringFunc::ToInt(FromQtString(rootItem->whatsThis(0)).c_str()); + const uint32 motionSetID = rootItem->whatsThis(0).toUInt(); EMotionFX::MotionSet* motionSet = EMotionFX::GetMotionManager().FindMotionSetByID(motionSetID); if (AZStd::find(selectedRootMotionSets.begin(), selectedRootMotionSets.end(), motionSet) == selectedRootMotionSets.end()) { @@ -948,7 +944,7 @@ namespace EMStudio } // Add the root motion set in the array if not already added. - const uint32 motionSetID = AzFramework::StringFunc::ToInt(FromQtString(rootItem->whatsThis(0)).c_str()); + const uint32 motionSetID = rootItem->whatsThis(0).toUInt(); EMotionFX::MotionSet* motionSet = EMotionFX::GetMotionManager().FindMotionSetByID(motionSetID); if (AZStd::find(selectedRootMotionSets.begin(), selectedRootMotionSets.end(), motionSet) == selectedRootMotionSets.end()) { @@ -961,12 +957,9 @@ namespace EMStudio commandGroup.SetReturnFalseAfterError(true); // Add each command. - const size_t numSelectedRootMotionSets = selectedRootMotionSets.size(); - for (size_t i = 0; i < numSelectedRootMotionSets; ++i) + for (const EMotionFX::MotionSet* motionSet : selectedRootMotionSets) { - EMotionFX::MotionSet* motionSet = selectedRootMotionSets[i]; - - // Show a file dialog in case the motion set hasn't been saved yet. + // Show a file dialog in case the motion set hasn't been saved yet. AZStd::string filename = motionSet->GetFilename(); if (filename.empty()) { @@ -1019,7 +1012,7 @@ namespace EMStudio } // Add the root motion set in the array if not already added. - const uint32 motionSetID = AzFramework::StringFunc::ToInt(FromQtString(rootItem->whatsThis(0)).c_str()); + const uint32 motionSetID = rootItem->whatsThis(0).toUInt(); EMotionFX::MotionSet* motionSet = EMotionFX::GetMotionManager().FindMotionSetByID(motionSetID); if (AZStd::find(selectedRootMotionSets.begin(), selectedRootMotionSets.end(), motionSet) == selectedRootMotionSets.end()) { diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetWindow.cpp index 10ceb2e43f..0ab738a259 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetWindow.cpp @@ -6,6 +6,7 @@ * */ +#include "AzCore/std/algorithm.h" #include "MotionSetsWindowPlugin.h" #include #include @@ -328,8 +329,8 @@ namespace EMStudio void MotionSetWindow::ReInit() { EMotionFX::MotionSet* selectedSet = mPlugin->GetSelectedSet(); - const uint32 selectedSetIndex = EMotionFX::GetMotionManager().FindMotionSetIndex(selectedSet); - if (selectedSetIndex != MCORE_INVALIDINDEX32) + const size_t selectedSetIndex = EMotionFX::GetMotionManager().FindMotionSetIndex(selectedSet); + if (selectedSetIndex != InvalidIndex) { UpdateMotionSetTable(m_tableWidget, mPlugin->GetSelectedSet()); } @@ -824,7 +825,7 @@ namespace EMStudio } const QList selectedItems = m_tableWidget->selectedItems(); - const uint32 numSelectedItems = selectedItems.count(); + const size_t numSelectedItems = selectedItems.count(); // Get the row indices from the selected items. AZStd::vector rowIndices; @@ -835,7 +836,7 @@ namespace EMStudio m_editAction->setEnabled(hasMotions); // Inform the time view plugin about the motion selection change. - const bool hasSelectedRows = rowIndices.size() > 0; + const bool hasSelectedRows = !rowIndices.empty(); if (hasSelectedRows) { QTableWidgetItem* firstSelectedItem = selectedItems[0]; @@ -847,8 +848,8 @@ namespace EMStudio { MCore::CommandGroup commandGroup("Select motion"); commandGroup.AddCommandString("Unselect -motionIndex SELECT_ALL"); - const AZ::u32 motionIndex = EMotionFX::GetMotionManager().FindMotionIndexByFileName(motion->GetFileName()); - commandGroup.AddCommandString(AZStd::string::format("Select -motionIndex %d", motionIndex)); + const size_t motionIndex = EMotionFX::GetMotionManager().FindMotionIndexByFileName(motion->GetFileName()); + commandGroup.AddCommandString(AZStd::string::format("Select -motionIndex %zu", motionIndex)); AZStd::string result; if (!EMStudio::GetCommandManager()->ExecuteCommandGroup(commandGroup, result, false)) @@ -913,7 +914,7 @@ namespace EMStudio // Build a list of unique string id values from all motion set entries. AZStd::vector idStrings; - idStrings.reserve(selectedSet->GetNumMotionEntries() + (uint32)numFileNames); + idStrings.reserve(selectedSet->GetNumMotionEntries() + numFileNames); selectedSet->BuildIdStringList(idStrings); AZStd::string parameterString; @@ -1133,16 +1134,16 @@ namespace EMStudio return; } - for (uint32 i = 0; i < numRowIndices; ++i) + for (const int rowIndex : rowIndices) { - QTableWidgetItem* idItem = m_tableWidget->item(rowIndices[i], 1); + QTableWidgetItem* idItem = m_tableWidget->item(rowIndex, 1); EMotionFX::MotionSet::MotionEntry* motionEntry = motionSet->FindMotionEntryById(idItem->text().toUtf8().data()); // Check if the motion exists in multiple motion sets. - const AZ::u32 numMotionSets = EMotionFX::GetMotionManager().GetNumMotionSets(); - AZ::u32 numMotionSetContainsMotion = 0; + const size_t numMotionSets = EMotionFX::GetMotionManager().GetNumMotionSets(); + size_t numMotionSetContainsMotion = 0; - for (AZ::u32 motionSetId = 0; motionSetId < numMotionSets; motionSetId++) + for (size_t motionSetId = 0; motionSetId < numMotionSets; motionSetId++) { EMotionFX::MotionSet* motionSet2 = EMotionFX::GetMotionManager().GetMotionSet(motionSetId); if (motionSet2->FindMotionEntryById(motionEntry->GetId())) @@ -1181,7 +1182,7 @@ namespace EMStudio if (removeMotion && motionEntry->GetMotion()) { // Calculcate how many motion sets except than the provided one use the given motion. - uint32 numExternalUses = CalcNumMotionEntriesUsingMotionExcluding(motionEntry->GetFilename(), motionSet); + size_t numExternalUses = CalcNumMotionEntriesUsingMotionExcluding(motionEntry->GetFilename(), motionSet); // Remove the motion in case it was only used by the given motion set. if (numExternalUses == 0) @@ -1199,15 +1200,14 @@ namespace EMStudio // Find the lowest row selected. int lowestRowSelected = -1; - for (uint32 i = 0; i < numRowIndices; ++i) + for (int selectedRowIndex : rowIndices) { - if (rowIndices[i] < lowestRowSelected) + if (selectedRowIndex < lowestRowSelected) { - lowestRowSelected = rowIndices[i]; + lowestRowSelected = selectedRowIndex; } } - MCore::CommandGroup commandGroup("Motion set remove motions"); // 1. Remove motion entries from the motion set. @@ -1371,7 +1371,7 @@ namespace EMStudio } // Calculcate how many motion sets except than the provided one use the given motion. - uint32 numExternalUses = CalcNumMotionEntriesUsingMotionExcluding(motionEntry->GetFilename(), motionSet); + size_t numExternalUses = CalcNumMotionEntriesUsingMotionExcluding(motionEntry->GetFilename(), motionSet); // Remove the motion in case it was only used by the given motion set. if (numExternalUses == 0) @@ -1407,9 +1407,6 @@ namespace EMStudio // get the current selection const QList selectedItems = m_tableWidget->selectedItems(); - // get the number of selected items - const uint32 numSelectedItems = selectedItems.count(); - // Get the row indices from the selected items. AZStd::vector rowIndices; GetRowIndices(selectedItems, rowIndices); @@ -1419,12 +1416,11 @@ namespace EMStudio // generate the motions IDs array AZStd::vector motionIDs; - const size_t numSelectedRows = rowIndices.size(); - if (numSelectedRows > 0) + if (!rowIndices.empty()) { - for (int i = 0; i < numSelectedRows; ++i) + for (const int rowIndex : rowIndices) { - QTableWidgetItem* item = m_tableWidget->item(rowIndices[i], 1); + QTableWidgetItem* item = m_tableWidget->item(rowIndex, 1); motionIDs.push_back(item->text().toUtf8().data()); } } @@ -1556,8 +1552,7 @@ namespace EMStudio const QList selectedItems = m_tableWidget->selectedItems(); // get the number of selected items - const uint32 numSelectedItems = selectedItems.count(); - if (numSelectedItems == 0) + if (selectedItems.empty()) { return; } @@ -1828,12 +1823,11 @@ namespace EMStudio // add each command AZStd::string commandString; - const size_t numValid = mValids.size(); - for (size_t i = 0; i < numValid; ++i) + for (size_t validID : mValids) { // get the motion ID and the modified ID - AZStd::string& motionID = mMotionIDs[mValids[i]]; - const AZStd::string& modifiedID = mModifiedMotionIDs[mMotionToModifiedMap[mValids[i]]]; + AZStd::string& motionID = mMotionIDs[validID]; + const AZStd::string& modifiedID = mModifiedMotionIDs[mMotionToModifiedMap[validID]]; commandString = AZStd::string::format("MotionSetAdjustMotion -motionSetID %i -idString \"%s\" -newIDString \"%s\" -updateMotionNodeStringIDs true", mMotionSet->GetID(), motionID.c_str(), modifiedID.c_str()); motionID = modifiedID; @@ -1954,9 +1948,6 @@ namespace EMStudio return; } - // found flags - uint32 numDuplicateFound = 0; - // Clear the arrays but keep the memory to avoid alloc. mValids.clear(); mModifiedMotionIDs.clear(); @@ -1974,7 +1965,7 @@ namespace EMStudio // Modify each ID using the operation in the modified array. AZStd::string newMotionID; AZStd::string tempString; - for (uint32 i = 0; i < numMotionIDs; ++i) + for (const AZStd::string& mMotionID : mMotionIDs) { // 0=Replace All, 1=Replace First, 2=Replace Last const int operationMode = mComboBox->currentIndex(); @@ -1984,7 +1975,7 @@ namespace EMStudio { case 0: { - tempString = mMotionIDs[i].c_str(); + tempString = mMotionID.c_str(); AzFramework::StringFunc::Replace(tempString, mStringALineEdit->text().toUtf8().data(), mStringBLineEdit->text().toUtf8().data(), true /* case sensitive */); newMotionID = tempString.c_str(); break; @@ -1992,7 +1983,7 @@ namespace EMStudio case 1: { - tempString = mMotionIDs[i].c_str(); + tempString = mMotionID.c_str(); AzFramework::StringFunc::Replace(tempString, mStringALineEdit->text().toUtf8().data(), mStringBLineEdit->text().toUtf8().data(), true /* case sensitive */, true /* replace first */, false /* replace last */); newMotionID = tempString.c_str(); break; @@ -2000,7 +1991,7 @@ namespace EMStudio case 2: { - tempString = mMotionIDs[i].c_str(); + tempString = mMotionID.c_str(); AzFramework::StringFunc::Replace(tempString, mStringALineEdit->text().toUtf8().data(), mStringBLineEdit->text().toUtf8().data(), true /* case sensitive */, false /* replace first */, true /* replace last */); newMotionID = tempString.c_str(); break; @@ -2008,17 +1999,20 @@ namespace EMStudio } // change the value in the array and add the mapping motion to modified - auto iterator = AZStd::find(mModifiedMotionIDs.begin(), mModifiedMotionIDs.end(), mMotionIDs[i]); + auto iterator = AZStd::find(mModifiedMotionIDs.begin(), mModifiedMotionIDs.end(), mMotionID); const size_t modifiedIndex = iterator - mModifiedMotionIDs.begin(); mModifiedMotionIDs[modifiedIndex] = newMotionID; - mMotionToModifiedMap.push_back(static_cast(modifiedIndex)); + mMotionToModifiedMap.push_back(modifiedIndex); } // disable the sorting mTableWidget->setSortingEnabled(false); + // found flags + size_t numDuplicateFound = 0; + // update each row - for (uint32 i = 0; i < numMotionIDs; ++i) + for (size_t i = 0; i < numMotionIDs; ++i) { // find the index in the motion set const AZStd::string& modifiedID = mModifiedMotionIDs[mMotionToModifiedMap[i]]; @@ -2028,9 +2022,9 @@ namespace EMStudio QTableWidgetItem* afterTableWidgetItem = new QTableWidgetItem(modifiedID.c_str()); // find duplicate - uint32 itemFoundCounter = 0; - const AZ::u32 numMotionEntries = static_cast(mMotionSet->GetNumMotionEntries()); - for (uint32 k = 0; k < numMotionEntries; ++k) + size_t itemFoundCounter = 0; + const size_t numMotionEntries = mMotionSet->GetNumMotionEntries(); + for (size_t k = 0; k < numMotionEntries; ++k) { if (mModifiedMotionIDs[k] == modifiedID) { @@ -2063,8 +2057,8 @@ namespace EMStudio } // set the text of the row - mTableWidget->setItem(i, 0, beforeTableWidgetItem); - mTableWidget->setItem(i, 1, afterTableWidgetItem); + mTableWidget->setItem(aznumeric_caster(i), 0, beforeTableWidgetItem); + mTableWidget->setItem(aznumeric_caster(i), 1, afterTableWidgetItem); } // enable the sorting @@ -2085,7 +2079,7 @@ namespace EMStudio } // enable or disable the apply button - mApplyButton->setEnabled((mValids.size() > 0) && (numDuplicateFound == 0)); + mApplyButton->setEnabled((!mValids.empty()) && (numDuplicateFound == 0)); // Reselect the remembered motions. mTableWidget->clearSelection(); @@ -2130,9 +2124,9 @@ namespace EMStudio const int numItems = items.size(); outRowIndices.reserve(numItems); - for (int i = 0; i < numItems; ++i) + for (const QTableWidgetItem* item : items) { - const int rowIndex = items[i]->row(); + const int rowIndex = item->row(); if (AZStd::find(outRowIndices.begin(), outRowIndices.end(), rowIndex) == outRowIndices.end()) { outRowIndices.push_back(rowIndex); @@ -2141,7 +2135,7 @@ namespace EMStudio } - uint32 MotionSetWindow::CalcNumMotionEntriesUsingMotionExcluding(const AZStd::string& motionFilename, EMotionFX::MotionSet* excludedMotionSet) + size_t MotionSetWindow::CalcNumMotionEntriesUsingMotionExcluding(const AZStd::string& motionFilename, EMotionFX::MotionSet* excludedMotionSet) { if (motionFilename.empty()) { @@ -2149,9 +2143,9 @@ namespace EMStudio } // Iterate through all available motion sets and count how many entries are refering to the given motion file. - AZ::u32 counter = 0; - const uint32 numMotionSets = EMotionFX::GetMotionManager().GetNumMotionSets(); - for (uint32 i = 0; i < numMotionSets; ++i) + size_t counter = 0; + const size_t numMotionSets = EMotionFX::GetMotionManager().GetNumMotionSets(); + for (size_t i = 0; i < numMotionSets; ++i) { EMotionFX::MotionSet* motionSet = EMotionFX::GetMotionManager().GetMotionSet(i); if (motionSet->GetIsOwnedByRuntime()) diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetWindow.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetWindow.h index 1827214e5d..33b3828e5a 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetWindow.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetWindow.h @@ -91,8 +91,8 @@ namespace EMStudio EMotionFX::MotionSet* mMotionSet; AZStd::vector mMotionIDs; AZStd::vector mModifiedMotionIDs; - AZStd::vector mMotionToModifiedMap; - AZStd::vector mValids; + AZStd::vector mMotionToModifiedMap; + AZStd::vector mValids; QTableWidget* mTableWidget; QLineEdit* mStringALineEdit; QLineEdit* mStringBLineEdit; @@ -184,7 +184,7 @@ namespace EMStudio EMotionFX::MotionSet::MotionEntry* FindMotionEntry(QTableWidgetItem* item) const; void GetRowIndices(const QList& items, AZStd::vector& outRowIndices); - uint32 CalcNumMotionEntriesUsingMotionExcluding(const AZStd::string& motionFilename, EMotionFX::MotionSet* excludedMotionSet); + size_t CalcNumMotionEntriesUsingMotionExcluding(const AZStd::string& motionFilename, EMotionFX::MotionSet* excludedMotionSet); private: QVBoxLayout* mVLayout = nullptr; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetsWindowPlugin.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetsWindowPlugin.cpp index 21f1eb58cd..3860edd009 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetsWindowPlugin.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetsWindowPlugin.cpp @@ -55,8 +55,8 @@ namespace EMStudio void GetDirtyFileNames(AZStd::vector* outFileNames, AZStd::vector* outObjects) override { - const uint32 numMotionSets = EMotionFX::GetMotionManager().GetNumMotionSets(); - for (uint32 i = 0; i < numMotionSets; ++i) + const size_t numMotionSets = EMotionFX::GetMotionManager().GetNumMotionSets(); + for (size_t i = 0; i < numMotionSets; ++i) { EMotionFX::MotionSet* motionSet = EMotionFX::GetMotionManager().GetMotionSet(i); @@ -226,7 +226,7 @@ namespace EMStudio EMotionFX::MotionSet* MotionSetsWindowPlugin::GetSelectedSet() const { - if (EMotionFX::GetMotionManager().FindMotionSetIndex(mSelectedSet) == MCORE_INVALIDINDEX32) + if (EMotionFX::GetMotionManager().FindMotionSetIndex(mSelectedSet) == InvalidIndex) { return nullptr; } @@ -238,7 +238,7 @@ namespace EMStudio void MotionSetsWindowPlugin::ReInit() { // Validate existence of selected motion set and reset selection in case selection is invalid. - if (EMotionFX::GetMotionManager().FindMotionSetIndex(mSelectedSet) == MCORE_INVALIDINDEX32) + if (EMotionFX::GetMotionManager().FindMotionSetIndex(mSelectedSet) == InvalidIndex) { mSelectedSet = nullptr; } @@ -488,7 +488,7 @@ namespace EMStudio // If motion entry is still not found, look through all motion sets not owned by runtime. const EMotionFX::MotionManager& motionManager = EMotionFX::GetMotionManager(); - for(AZ::u32 i = 0; i < motionManager.GetNumMotionSets(); ++i) + for(size_t i = 0; i < motionManager.GetNumMotionSets(); ++i) { motionSet = motionManager.GetMotionSet(i); if (motionSet->GetIsOwnedByRuntime()) @@ -680,9 +680,9 @@ namespace EMStudio // select the first motion set if (EMotionFX::GetMotionManager().GetNumMotionSets() > 0) { - const uint32 numMotionSets = EMotionFX::GetMotionManager().GetNumMotionSets(); + const size_t numMotionSets = EMotionFX::GetMotionManager().GetNumMotionSets(); - for (uint32 i = 0; i < numMotionSets; ++i) + for (size_t i = 0; i < numMotionSets; ++i) { EMotionFX::MotionSet* motionSet2 = EMotionFX::GetMotionManager().GetMotionSet(0); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionWindow/MotionExtractionWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionWindow/MotionExtractionWindow.cpp index ac284a5777..419535da81 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionWindow/MotionExtractionWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionWindow/MotionExtractionWindow.cpp @@ -182,7 +182,7 @@ namespace EMStudio const CommandSystem::SelectionList& selectionList = GetCommandManager()->GetCurrentSelection(); // Check if there actually is any motion selected. - const uint32 numSelectedMotions = selectionList.GetNumSelectedMotions(); + const size_t numSelectedMotions = selectionList.GetNumSelectedMotions(); const bool isEnabled = (numSelectedMotions != 0); EMotionFX::ActorInstance* actorInstance = GetCommandManager()->GetCurrentSelection().GetSingleActorInstance(); @@ -254,11 +254,11 @@ namespace EMStudio // Figure out if all selected motions use the same settings. bool allCaptureHeightEqual = true; - uint32 numCaptureHeight = 0; - const uint32 numMotions = selectionList.GetNumSelectedMotions(); + size_t numCaptureHeight = 0; + const size_t numMotions = selectionList.GetNumSelectedMotions(); bool curCaptureHeight = false; - for (uint32 i = 0; i < numMotions; ++i) + for (size_t i = 0; i < numMotions; ++i) { EMotionFX::Motion* curMotion = selectionList.GetMotion(i); EMotionFX::Motion* prevMotion = (i>0) ? selectionList.GetMotion(i-1) : nullptr; @@ -325,7 +325,7 @@ namespace EMStudio void MotionExtractionWindow::OnMotionExtractionFlagsUpdated() { const CommandSystem::SelectionList& selectionList = GetCommandManager()->GetCurrentSelection(); - const uint32 numSelectedMotions = selectionList.GetNumSelectedMotions(); + const size_t numSelectedMotions = selectionList.GetNumSelectedMotions(); EMotionFX::ActorInstance* actorInstance = selectionList.GetSingleActorInstance(); // Check if there is at least one motion selected and exactly one actor instance. @@ -353,7 +353,7 @@ namespace EMStudio // Iterate through all selected motions. AZStd::string command; - for (uint32 i = 0; i < numSelectedMotions; ++i) + for (size_t i = 0; i < numSelectedMotions; ++i) { // Get the current selected motion, check if it is a skeletal motion, skip directly elsewise. EMotionFX::Motion* motion = selectionList.GetMotion(i); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionWindow/MotionListWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionWindow/MotionListWindow.cpp index c6af7f2149..c909098dae 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionWindow/MotionListWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionWindow/MotionListWindow.cpp @@ -243,7 +243,7 @@ namespace EMStudio mMotionTable->setSortingEnabled(false); // insert the new row - const uint32 rowIndex = 0; + const int rowIndex = 0; mMotionTable->insertRow(rowIndex); mMotionTable->setRowHeight(rowIndex, 21); @@ -314,8 +314,8 @@ namespace EMStudio uint32 MotionListWindow::FindRowByMotionID(uint32 motionID) { // iterate through the rows and compare the motion IDs - const uint32 rowCount = mMotionTable->rowCount(); - for (uint32 i = 0; i < rowCount; ++i) + const int rowCount = mMotionTable->rowCount(); + for (int i = 0; i < rowCount; ++i) { if (GetMotionID(i) == motionID) { @@ -469,7 +469,7 @@ namespace EMStudio mMotionTable->clearSelection(); // iterate through the selected motions and select the corresponding rows in the table widget - const uint32 numSelectedMotions = selectionList.GetNumSelectedMotions(); + const size_t numSelectedMotions = selectionList.GetNumSelectedMotions(); for (uint32 i = 0; i < numSelectedMotions; ++i) { // get the index of the motion inside the motion manager (which is equal to the row in the motion table) and select the row at the motion index @@ -531,14 +531,14 @@ namespace EMStudio const QList selectedItems = mMotionTable->selectedItems(); // get the number of selected items - const uint32 numSelectedItems = selectedItems.count(); + const int numSelectedItems = selectedItems.count(); // filter the items - AZStd::vector rowIndices; + AZStd::vector rowIndices; rowIndices.reserve(numSelectedItems); - for (size_t i = 0; i < numSelectedItems; ++i) + for (int i = 0; i < numSelectedItems; ++i) { - const uint32 rowIndex = selectedItems[static_cast(i)]->row(); + const int rowIndex = selectedItems[i]->row(); if (AZStd::find(rowIndices.begin(), rowIndices.end(), rowIndex) == rowIndices.end()) { rowIndices.push_back(rowIndex); @@ -549,22 +549,20 @@ namespace EMStudio mSelectedMotionIDs.clear(); // get the number of selected items and iterate through them - const size_t numSelectedRows = rowIndices.size(); - mSelectedMotionIDs.reserve(numSelectedRows); - for (size_t i = 0; i < numSelectedRows; ++i) + mSelectedMotionIDs.reserve(rowIndices.size()); + for (const int rowIndex : rowIndices) { - mSelectedMotionIDs.push_back(GetMotionID(rowIndices[i])); + mSelectedMotionIDs.push_back(GetMotionID(rowIndex)); } // unselect all motions GetCommandManager()->GetCurrentSelection().ClearMotionSelection(); // get the number of selected motions and iterate through them - const size_t numSelectedMotions = mSelectedMotionIDs.size(); - for (size_t i = 0; i < numSelectedMotions; ++i) + for (uint32 selectedMotionID : mSelectedMotionIDs) { // find the motion by name in the motion library and select it - EMotionFX::Motion* motion = EMotionFX::GetMotionManager().FindMotionByID(mSelectedMotionIDs[i]); + EMotionFX::Motion* motion = EMotionFX::GetMotionManager().FindMotionByID(selectedMotionID); if (motion) { GetCommandManager()->GetCurrentSelection().AddMotion(motion); @@ -583,7 +581,7 @@ namespace EMStudio { // get the current selection const CommandSystem::SelectionList& selection = GetCommandManager()->GetCurrentSelection(); - const uint32 numSelectedMotions = selection.GetNumSelectedMotions(); + const size_t numSelectedMotions = selection.GetNumSelectedMotions(); if (numSelectedMotions == 0) { return; @@ -607,7 +605,6 @@ namespace EMStudio // Set the command group name based on the number of motions to add. AZStd::string groupName; - const size_t numSelectedMotionSets = selectedMotionSets.size(); if (numSelectedMotions > 1) { groupName = "Add motions in motion sets"; @@ -621,16 +618,14 @@ namespace EMStudio // add in each selected motion set AZStd::string motionName; - for (uint32 m = 0; m < numSelectedMotionSets; ++m) + for (const EMotionFX::MotionSet* motionSet : selectedMotionSets) { - EMotionFX::MotionSet* motionSet = selectedMotionSets[m]; - // Build a list of unique string id values from all motion set entries. AZStd::vector idStrings; motionSet->BuildIdStringList(idStrings); // add each selected motion in the motion set - for (uint32 i = 0; i < numSelectedMotions; ++i) + for (size_t i = 0; i < numSelectedMotions; ++i) { // remove the media root folder from the absolute motion filename so that we get the relative one to the media root folder motionName = selection.GetMotion(i)->GetFileName(); @@ -654,7 +649,7 @@ namespace EMStudio const CommandSystem::SelectionList& selection = GetCommandManager()->GetCurrentSelection(); // iterate through the selected motions and show them - for (uint32 i = 0; i < selection.GetNumSelectedMotions(); ++i) + for (size_t i = 0; i < selection.GetNumSelectedMotions(); ++i) { EMotionFX::Motion* motion = selection.GetMotion(i); AzQtComponents::ShowFileOnDesktop(motion->GetFileName()); @@ -777,8 +772,8 @@ namespace EMStudio // get the number of selected motions and return directly if there are no motions selected AZStd::string textData, command; - const uint32 numMotions = selectionList.GetNumSelectedMotions(); - for (uint32 i = 0; i < numMotions; ++i) + const size_t numMotions = selectionList.GetNumSelectedMotions(); + for (size_t i = 0; i < numMotions; ++i) { EMotionFX::Motion* motion = selectionList.GetMotion(i); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionWindow/MotionRetargetingWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionWindow/MotionRetargetingWindow.cpp index 5c0ab3d564..6596a7c868 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionWindow/MotionRetargetingWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionWindow/MotionRetargetingWindow.cpp @@ -67,8 +67,8 @@ namespace EMStudio MCore::CommandGroup commandGroup("Adjust default motion instances"); // get the number of selected motions and iterate through them - const uint32 numMotions = selection.GetNumSelectedMotions(); - for (uint32 i = 0; i < numMotions; ++i) + const size_t numMotions = selection.GetNumSelectedMotions(); + for (size_t i = 0; i < numMotions; ++i) { MotionWindowPlugin::MotionTableEntry* entry = mMotionWindowPlugin->FindMotionEntryByID(selection.GetMotion(i)->GetID()); if (entry == nullptr) @@ -108,7 +108,7 @@ namespace EMStudio const CommandSystem::SelectionList& selection = CommandSystem::GetCommandManager()->GetCurrentSelection(); // check if there actually is any motion selected - const uint32 numSelectedMotions = selection.GetNumSelectedMotions(); + const size_t numSelectedMotions = selection.GetNumSelectedMotions(); const bool isEnabled = (numSelectedMotions != 0); mMotionRetargetingButton->setEnabled(isEnabled); @@ -120,7 +120,7 @@ namespace EMStudio } // iterate through the selected motions - for (uint32 i = 0; i < numSelectedMotions; ++i) + for (size_t i = 0; i < numSelectedMotions; ++i) { MotionWindowPlugin::MotionTableEntry* entry = mMotionWindowPlugin->FindMotionEntryByID(selection.GetMotion(i)->GetID()); if (entry == nullptr) diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionWindow/MotionWindowPlugin.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionWindow/MotionWindowPlugin.cpp index 0a1fcb3b7a..1452d0ac93 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionWindow/MotionWindowPlugin.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionWindow/MotionWindowPlugin.cpp @@ -6,6 +6,7 @@ * */ +#include "AzCore/std/limits.h" #include #include #include @@ -53,8 +54,8 @@ namespace EMStudio void GetDirtyFileNames(AZStd::vector* outFileNames, AZStd::vector* outObjects) override { // get the number of motions and iterate through them - const uint32 numMotions = EMotionFX::GetMotionManager().GetNumMotions(); - for (uint32 i = 0; i < numMotions; ++i) + const size_t numMotions = EMotionFX::GetMotionManager().GetNumMotions(); + for (size_t i = 0; i < numMotions; ++i) { EMotionFX::Motion* motion = EMotionFX::GetMotionManager().GetMotion(i); @@ -272,11 +273,11 @@ namespace EMStudio } // iterate through the motions and put them into some array - const uint32 numMotions = EMotionFX::GetMotionManager().GetNumMotions(); + const size_t numMotions = EMotionFX::GetMotionManager().GetNumMotions(); AZStd::vector motionsToRemove; motionsToRemove.reserve(numMotions); - for (uint32 i = 0; i < numMotions; ++i) + for (size_t i = 0; i < numMotions; ++i) { EMotionFX::Motion* motion = EMotionFX::GetMotionManager().GetMotion(i); if (motion->GetIsOwnedByRuntime()) @@ -303,7 +304,7 @@ namespace EMStudio const CommandSystem::SelectionList& selection = GetCommandManager()->GetCurrentSelection(); // get the number of selected motions - const uint32 numMotions = selection.GetNumSelectedMotions(); + const size_t numMotions = selection.GetNumSelectedMotions(); if (numMotions == 0) { return; @@ -327,7 +328,7 @@ namespace EMStudio // Save all dirty motion files. EMotionFX::MotionManager& motionManager = EMotionFX::GetMotionManager(); - for (uint32 i = 0; i < numMotions; ++i) + for (size_t i = 0; i < numMotions; ++i) { // Look up the motion by ID, using our backup seleciton list. // So even if our selection list in EMotion FX gets modified, we still iterate over the original selection now. @@ -353,15 +354,11 @@ namespace EMStudio } // find the lowest row selected - uint32 lowestRowSelected = MCORE_INVALIDINDEX32; + int lowestRowSelected = AZStd::numeric_limits::max(); const QList selectedItems = mMotionListWindow->GetMotionTable()->selectedItems(); - const int numSelectedItems = selectedItems.size(); - for (int i = 0; i < numSelectedItems; ++i) + for (const QTableWidgetItem* selectedItem : selectedItems) { - if ((uint32)selectedItems[i]->row() < lowestRowSelected) - { - lowestRowSelected = (uint32)selectedItems[i]->row(); - } + lowestRowSelected = AZStd::min(lowestRowSelected, selectedItem->row()); } // construct the command group and remove the selected motions @@ -369,7 +366,7 @@ namespace EMStudio CommandSystem::RemoveMotions(motionsToRemove, &failedRemoveMotions); // selected the next row - if (lowestRowSelected > ((uint32)mMotionListWindow->GetMotionTable()->rowCount() - 1)) + if (lowestRowSelected > (mMotionListWindow->GetMotionTable()->rowCount() - 1)) { mMotionListWindow->GetMotionTable()->selectRow(lowestRowSelected - 1); } @@ -389,7 +386,7 @@ namespace EMStudio void MotionWindowPlugin::OnSave() { const CommandSystem::SelectionList& selectionList = GetCommandManager()->GetCurrentSelection(); - const AZ::u32 numMotions = selectionList.GetNumSelectedMotions(); + const size_t numMotions = selectionList.GetNumSelectedMotions(); if (numMotions == 0) { return; @@ -398,7 +395,7 @@ namespace EMStudio // Collect motion ids of the motion to be saved. AZStd::vector motionIds; motionIds.reserve(numMotions); - for (AZ::u32 i = 0; i < numMotions; ++i) + for (size_t i = 0; i < numMotions; ++i) { const EMotionFX::Motion* motion = selectionList.GetMotion(i); motionIds.push_back(motion->GetID()); @@ -462,11 +459,9 @@ namespace EMStudio void MotionWindowPlugin::ReInit() { - uint32 i; - // get the number of motions in the motion library and iterate through them - const uint32 numLibraryMotions = EMotionFX::GetMotionManager().GetNumMotions(); - for (i = 0; i < numLibraryMotions; ++i) + const size_t numLibraryMotions = EMotionFX::GetMotionManager().GetNumMotions(); + for (size_t i = 0; i < numLibraryMotions; ++i) { // check if we have already added this motion, if not add it EMotionFX::Motion* motion = EMotionFX::GetMotionManager().GetMotion(i); @@ -481,21 +476,16 @@ namespace EMStudio } // iterate through all motions inside the motion window plugin - i = 0; - while (i < mMotionEntries.size()) + AZStd::erase_if(mMotionEntries, [](MotionTableEntry* entry) { - MotionTableEntry* entry = mMotionEntries[i]; // check if the motion still is in the motion library, if not also remove it from the motion window plugin - if (EMotionFX::GetMotionManager().FindMotionIndexByID(entry->mMotionID) == MCORE_INVALIDINDEX32) + if (EMotionFX::GetMotionManager().FindMotionIndexByID(entry->mMotionID) == InvalidIndex) { - delete mMotionEntries[i]; - mMotionEntries.erase(mMotionEntries.begin() + i); + delete entry; + return true; } - else - { - i++; - } - } + return false; + }); // update the motion list window mMotionListWindow->ReInit(); @@ -511,10 +501,8 @@ namespace EMStudio void MotionWindowPlugin::UpdateInterface() { AZStd::vector& motionInstances = GetSelectedMotionInstances(); - const size_t numMotionInstances = motionInstances.size(); - for (size_t i = 0; i < numMotionInstances; ++i) + for (EMotionFX::MotionInstance* motionInstance : motionInstances) { - EMotionFX::MotionInstance* motionInstance = motionInstances[i]; EMotionFX::Motion* motion = motionInstance->GetMotion(); motionInstance->InitFromPlayBackInfo(*motion->GetDefaultPlayBackInfo(), false); @@ -537,8 +525,6 @@ namespace EMStudio mMotionNameLabel->setText(motion ? motion->GetName() : nullptr); } - const uint32 numMotions = EMotionFX::GetMotionManager().GetNumMotions(); - if (mSaveAction) { // related to the selected motions @@ -561,35 +547,30 @@ namespace EMStudio - void MotionWindowPlugin::VisibilityChanged(bool visible) + void MotionWindowPlugin::VisibilityChanged([[maybe_unused]] bool visible) { - if (visible) - { - //mMotionRetargetingWindow->UpdateSelection(); - //mMotionExtractionWindow->UpdateExtractionNodeLabel(); - } } AZStd::vector& MotionWindowPlugin::GetSelectedMotionInstances() { const CommandSystem::SelectionList& selectionList = CommandSystem::GetCommandManager()->GetCurrentSelection(); - const uint32 numSelectedActorInstances = selectionList.GetNumSelectedActorInstances(); - const uint32 numSelectedMotions = selectionList.GetNumSelectedMotions(); + const size_t numSelectedActorInstances = selectionList.GetNumSelectedActorInstances(); + const size_t numSelectedMotions = selectionList.GetNumSelectedMotions(); mInternalMotionInstanceSelection.clear(); - for (uint32 i = 0; i < numSelectedActorInstances; ++i) + for (size_t i = 0; i < numSelectedActorInstances; ++i) { EMotionFX::ActorInstance* actorInstance = selectionList.GetActorInstance(i); EMotionFX::MotionSystem* motionSystem = actorInstance->GetMotionSystem(); - const uint32 numMotionInstances = motionSystem->GetNumMotionInstances(); + const size_t numMotionInstances = motionSystem->GetNumMotionInstances(); - for (uint32 j = 0; j < numSelectedMotions; ++j) + for (size_t j = 0; j < numSelectedMotions; ++j) { EMotionFX::Motion* motion = selectionList.GetMotion(j); - for (uint32 k = 0; k < numMotionInstances; ++k) + for (size_t k = 0; k < numMotionInstances; ++k) { EMotionFX::MotionInstance* motionInstance = motionSystem->GetMotionInstance(k); if (motionInstance->GetMotion() == motion) @@ -606,17 +587,11 @@ namespace EMStudio MotionWindowPlugin::MotionTableEntry* MotionWindowPlugin::FindMotionEntryByID(uint32 motionID) { - const size_t numMotionEntries = mMotionEntries.size(); - for (size_t i = 0; i < numMotionEntries; ++i) + const auto foundEntry = AZStd::find_if(begin(mMotionEntries), end(mMotionEntries), [motionID](const MotionTableEntry* entry) { - MotionTableEntry* entry = mMotionEntries[i]; - if (entry->mMotionID == motionID) - { - return entry; - } - } - - return nullptr; + return entry->mMotionID == motionID; + }); + return foundEntry != end(mMotionEntries) ? *foundEntry : nullptr; } @@ -633,10 +608,8 @@ namespace EMStudio AZStd::string command, commandParameters; MCore::CommandGroup commandGroup("Play motions"); - const size_t numMotions = motions.size(); - for (size_t i = 0; i < numMotions; ++i) + for (EMotionFX::Motion* motion : motions) { - EMotionFX::Motion* motion = motions[i]; EMotionFX::PlayBackInfo* defaultPlayBackInfo = motion->GetDefaultPlayBackInfo(); // Don't blend in and out of the for previewing animations. We might only see a short bit of it for animations smaller than the blend in/out time. @@ -663,17 +636,17 @@ namespace EMStudio const CommandSystem::SelectionList& selection = CommandSystem::GetCommandManager()->GetCurrentSelection(); // get the number of selected motions - const uint32 numMotions = selection.GetNumSelectedMotions(); + const size_t numMotions = selection.GetNumSelectedMotions(); if (numMotions == 0) { return; } // create our remove motion command group - MCore::CommandGroup commandGroup(AZStd::string::format("Stop %u motion instances", numMotions).c_str()); + MCore::CommandGroup commandGroup(AZStd::string::format("Stop %zu motion instances", numMotions).c_str()); AZStd::string command; - for (uint32 i = 0; i < numMotions; ++i) + for (size_t i = 0; i < numMotions; ++i) { MotionWindowPlugin::MotionTableEntry* entry = FindMotionEntryByID(selection.GetMotion(i)->GetID()); if (entry == nullptr) @@ -703,61 +676,6 @@ namespace EMStudio { return; } - /* - if (mMotionRetargetingWindow->GetRenderMotionBindPose()) - { - const CommandSystem::SelectionList& selection = CommandSystem::GetCommandManager()->GetCurrentSelection(); - - // get the number of selected actor instances and iterate through them - const uint32 numActorInstances = selection.GetNumSelectedActorInstances(); - for (uint32 j = 0; j < numActorInstances; ++j) - { - EMotionFX::ActorInstance* actorInstance = selection.GetActorInstance(j); - EMotionFX::Actor* actor = actorInstance->GetActor(); - - // get the number of selected motions and iterate through them - const uint32 numMotions = selection.GetNumSelectedMotions(); - for (uint32 i = 0; i < numMotions; ++i) - { - EMotionFX::Motion* motion = selection.GetMotion(i); - if (motion->GetType() == EMotionFX::SkeletalMotion::TYPE_ID) - { - EMotionFX::SkeletalMotion* skeletalMotion = (EMotionFX::SkeletalMotion*)motion; - - EMotionFX::AnimGraphPosePool& posePool = EMotionFX::GetEMotionFX().GetThreadData(0)->GetPosePool(); - EMotionFX::AnimGraphPose* pose = posePool.RequestPose(m_actorInstance); - - skeletalMotion->CalcMotionBindPose(actor, pose->GetPose()); - - // for all nodes in the actor - const uint32 numNodes = actorInstance->GetNumEnabledNodes(); - for (uint32 n = 0; n < numNodes; ++n) - { - EMotionFX::Node* curNode = actor->GetSkeleton()->GetNode(actorInstance->GetEnabledNode(n)); - - // skip root nodes, you could also use curNode->IsRootNode() - // but we use the parent index here, as we will reuse it - uint32 parentIndex = curNode->GetParentIndex(); - if (parentIndex == MCORE_INVALIDINDEX32) - { - AZ::Vector3 startPos = mGlobalMatrices[curNode->GetNodeIndex()].GetTranslation(); - AZ::Vector3 endPos = startPos + AZ::Vector3(0.0f, 3.0f, 0.0f); - renderUtil->RenderLine(startPos, endPos, MCore::RGBAColor(0.0f, 1.0f, 1.0f)); - } - else - { - AZ::Vector3 startPos = mGlobalMatrices[curNode->GetNodeIndex()].GetTranslation(); - AZ::Vector3 endPos = mGlobalMatrices[parentIndex].GetTranslation(); - renderUtil->RenderLine(startPos, endPos, MCore::RGBAColor(0.0f, 1.0f, 1.0f)); - } - } - - posePool.FreePose(pose); - } - } - } - } - */ } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeGroups/NodeGroupWidget.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeGroups/NodeGroupWidget.cpp index 552a6d45e7..1a95899c32 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeGroups/NodeGroupWidget.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeGroups/NodeGroupWidget.cpp @@ -9,7 +9,8 @@ // inlude required headers #include "NodeGroupWidget.h" #include "../../../../EMStudioSDK/Source/EMStudioManager.h" -#include "AzCore/std/iterator.h" +#include +#include #include #include @@ -332,10 +333,10 @@ namespace EMStudio // add / select nodes - void NodeGroupWidget::NodeSelectionFinished(AZStd::vector selectionList) + void NodeGroupWidget::NodeSelectionFinished(const AZStd::vector& selectionList) { // return if no nodes are selected - if (selectionList.size() == 0) + if (selectionList.empty()) { return; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeGroups/NodeGroupWidget.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeGroups/NodeGroupWidget.h index f128fd8082..6861e77756 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeGroups/NodeGroupWidget.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeGroups/NodeGroupWidget.h @@ -45,7 +45,7 @@ namespace EMStudio public slots: void SelectNodesButtonPressed(); void RemoveNodesButtonPressed(); - void NodeSelectionFinished(AZStd::vector selectionList); + void NodeSelectionFinished(const AZStd::vector& selectionList); void OnItemSelectionChanged(); private: diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/ActorInfo.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/ActorInfo.cpp index 91b08b25de..6bd00a2b94 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/ActorInfo.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/ActorInfo.cpp @@ -40,7 +40,7 @@ namespace EMStudio } // global mesh information - const uint32 lodLevel = actorInstance->GetLODLevel(); + const size_t lodLevel = actorInstance->GetLODLevel(); uint32 numPolygons; actor->CalcMeshTotals(lodLevel, &numPolygons, &m_totalVertices, &m_totalIndices); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/ActorInfo.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/ActorInfo.h index 9c0155ee40..e1aa63b7dd 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/ActorInfo.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/ActorInfo.h @@ -35,7 +35,7 @@ namespace EMStudio private: AZStd::string m_name; AZStd::string m_unitType; - int m_nodeCount; + AZ::u64 m_nodeCount; AZStd::vector m_nodeGroups; unsigned int m_totalVertices; unsigned int m_totalIndices; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/MeshInfo.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/MeshInfo.cpp index 49b1d1b8f3..d4aec199d3 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/MeshInfo.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/MeshInfo.cpp @@ -20,7 +20,7 @@ namespace EMStudio { AZ_CLASS_ALLOCATOR_IMPL(MeshInfo, EMStudio::UIAllocator, 0) - MeshInfo::MeshInfo(EMotionFX::Actor* actor, [[maybe_unused]] EMotionFX::Node* node, unsigned int lodLevel, EMotionFX::Mesh* mesh) + MeshInfo::MeshInfo(EMotionFX::Actor* actor, [[maybe_unused]] EMotionFX::Node* node, size_t lodLevel, EMotionFX::Mesh* mesh) : m_lod(lodLevel) { // vertices, indices and polygons etc. diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/MeshInfo.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/MeshInfo.h index 28215e59c9..4e39e6dda1 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/MeshInfo.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/MeshInfo.h @@ -30,13 +30,13 @@ namespace EMStudio AZ_CLASS_ALLOCATOR_DECL MeshInfo() {} - MeshInfo(EMotionFX::Actor* actor, EMotionFX::Node* node, unsigned int lodLevel, EMotionFX::Mesh* mesh); + MeshInfo(EMotionFX::Actor* actor, EMotionFX::Node* node, size_t lodLevel, EMotionFX::Mesh* mesh); ~MeshInfo() = default; static void Reflect(AZ::ReflectContext* context); private: - unsigned int m_lod; + AZ::u64 m_lod; unsigned int m_verticesCount; unsigned int m_indicesCount; unsigned int m_polygonsCount; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/NodeInfo.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/NodeInfo.cpp index f91468b6d2..a402dc869e 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/NodeInfo.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/NodeInfo.cpp @@ -23,7 +23,7 @@ namespace EMStudio NodeInfo::NodeInfo(EMotionFX::ActorInstance* actorInstance, EMotionFX::Node* node) { - const uint32 nodeIndex = node->GetNodeIndex(); + const size_t nodeIndex = node->GetNodeIndex(); EMotionFX::Actor* actor = actorInstance->GetActor(); EMotionFX::TransformData* transformData = actorInstance->GetTransformData(); @@ -60,24 +60,24 @@ namespace EMStudio } // children - const uint32 numChildren = node->GetNumChildNodes(); - for (uint32 i = 0; i < numChildren; ++i) + const size_t numChildren = node->GetNumChildNodes(); + for (size_t i = 0; i < numChildren; ++i) { EMotionFX::Node* child = actor->GetSkeleton()->GetNode(node->GetChildIndex(i)); m_childNodeNames.emplace_back(child->GetNameString()); } // attributes - const uint32 numAttributes = node->GetNumAttributes(); - for (uint32 i = 0; i < numAttributes; ++i) + const size_t numAttributes = node->GetNumAttributes(); + for (size_t i = 0; i < numAttributes; ++i) { EMotionFX::NodeAttribute* nodeAttribute = node->GetAttribute(i); m_attributeTypes.emplace_back(nodeAttribute->GetTypeString()); } // meshes - const uint32 numLODLevels = actor->GetNumLODLevels(); - for (uint32 i = 0; i < numLODLevels; ++i) + const size_t numLODLevels = actor->GetNumLODLevels(); + for (size_t i = 0; i < numLODLevels; ++i) { EMotionFX::Mesh* mesh = actor->GetMesh(i, node->GetNodeIndex()); if (mesh) diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/NodeWindowPlugin.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/NodeWindowPlugin.h index 7b1655bd05..582e9e9eac 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/NodeWindowPlugin.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/NodeWindowPlugin.h @@ -82,8 +82,8 @@ namespace EMStudio AZStd::string mString; AZStd::string mTempGroupName; - AZStd::unordered_set m_visibleNodeIndices; - AZStd::unordered_set m_selectedNodeIndices; + AZStd::unordered_set m_visibleNodeIndices; + AZStd::unordered_set m_selectedNodeIndices; AZStd::unique_ptr m_actorInfo; AZStd::unique_ptr m_nodeInfo; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/ActorPropertiesWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/ActorPropertiesWindow.cpp index cc5811b1f7..4e8e51b601 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/ActorPropertiesWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/ActorPropertiesWindow.cpp @@ -126,8 +126,8 @@ namespace EMStudio { mActor = actor; - const uint32 numActorInstances = EMotionFX::GetActorManager().GetNumActorInstances(); - for (uint32 i = 0; i < numActorInstances; ++i) + const size_t numActorInstances = EMotionFX::GetActorManager().GetNumActorInstances(); + for (size_t i = 0; i < numActorInstances; ++i) { EMotionFX::ActorInstance* currentInstance = EMotionFX::GetActorManager().GetActorInstance(i); if (currentInstance->GetActor() == actor) @@ -198,8 +198,8 @@ namespace EMStudio AZStd::vector jointsExcludedFromBounds; if (mActorInstance) { - const uint32 numNodes = mActor->GetNumNodes(); - for (uint32 i = 0; i < numNodes; ++i) + const size_t numNodes = mActor->GetNumNodes(); + for (size_t i = 0; i < numNodes; ++i) { EMotionFX::Node* node = mActor->GetSkeleton()->GetNode(i); if (!node->GetIncludeInBoundsCalc()) @@ -395,10 +395,10 @@ namespace EMStudio EMotionFX::Actor* actor = actorInstance->GetActor(); EMotionFX::Skeleton* skeleton = actor->GetSkeleton(); - const uint32 numJoints = mActor->GetNumNodes(); + const size_t numJoints = mActor->GetNumNodes(); // Include all joints first. - for (uint32 i = 0; i < numJoints; ++i) + for (size_t i = 0; i < numJoints; ++i) { skeleton->GetNode(i)->SetIncludeInBoundsCalc(true); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/ActorsWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/ActorsWindow.cpp index 309d6fb441..5012ee2578 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/ActorsWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/ActorsWindow.cpp @@ -111,9 +111,9 @@ namespace EMStudio m_treeWidget->clear(); // iterate trough all actors and add them to the tree including their instances - const uint32 numActors = EMotionFX::GetActorManager().GetNumActors(); - const uint32 numActorInstances = EMotionFX::GetActorManager().GetNumActorInstances(); - for (uint32 i = 0; i < numActors; ++i) + const size_t numActors = EMotionFX::GetActorManager().GetNumActors(); + const size_t numActorInstances = EMotionFX::GetActorManager().GetNumActorInstances(); + for (size_t i = 0; i < numActors; ++i) { EMotionFX::Actor* actor = EMotionFX::GetActorManager().GetActor(i); @@ -153,7 +153,7 @@ namespace EMStudio // add as top level item m_treeWidget->addTopLevelItem(newItem); - for (uint32 k = 0; k < numActorInstances; ++k) + for (size_t k = 0; k < numActorInstances; ++k) { EMotionFX::ActorInstance* actorInstance = EMotionFX::GetActorManager().GetActorInstance(k); if (actorInstance->GetActor() == actor && !actorInstance->GetIsOwnedByRuntime()) @@ -188,8 +188,8 @@ namespace EMStudio // disable signals m_treeWidget->blockSignals(true); - const uint32 numTopLevelItems = m_treeWidget->topLevelItemCount(); - for (uint32 i = 0; i < numTopLevelItems; ++i) + const int numTopLevelItems = m_treeWidget->topLevelItemCount(); + for (int i = 0; i < numTopLevelItems; ++i) { bool atLeastOneInstanceVisible = false; QTreeWidgetItem* item = m_treeWidget->topLevelItem(i); @@ -199,8 +199,8 @@ namespace EMStudio item->setSelected(actorSelected); - const uint32 numChildren = item->childCount(); - for (uint32 j = 0; j < numChildren; ++j) + const int numChildren = item->childCount(); + for (int j = 0; j < numChildren; ++j) { QTreeWidgetItem* child = item->child(j); EMotionFX::ActorInstance* actorInstance = EMotionFX::GetActorManager().FindActorInstanceByID(GetIDFromTreeItem(child)); @@ -236,10 +236,8 @@ namespace EMStudio AZStd::vector toBeRemovedActors; const QList items = m_treeWidget->selectedItems(); - const uint32 numItems = items.length(); - for (uint32 i = 0; i < numItems; ++i) + for (const QTreeWidgetItem* item : items) { - QTreeWidgetItem* item = items[i]; if (!item) { continue; @@ -254,8 +252,8 @@ namespace EMStudio if (actor) { // remove actor instances - const uint32 numChildren = item->childCount(); - for (uint32 j = 0; j < numChildren; ++j) + const int numChildren = item->childCount(); + for (int j = 0; j < numChildren; ++j) { QTreeWidgetItem* child = item->child(j); @@ -326,11 +324,9 @@ namespace EMStudio // filter the list to keep the actor items only const QList items = m_treeWidget->selectedItems(); - const uint32 numItems = items.length(); - for (uint32 i = 0; i < numItems; ++i) + for (const QTreeWidgetItem* item : items) { // get the item and check if the item is valid - QTreeWidgetItem* item = items[i]; if (item == nullptr) { continue; @@ -384,8 +380,8 @@ namespace EMStudio if (!item->parent()) { - const uint32 numChildren = item->childCount(); - for (uint32 i = 0; i < numChildren; ++i) + const int numChildren = item->childCount(); + for (int i = 0; i < numChildren; ++i) { QTreeWidgetItem* child = item->child(i); @@ -422,8 +418,8 @@ namespace EMStudio } // get the selected items - const uint32 numTopItems = m_treeWidget->topLevelItemCount(); - for (uint32 i = 0; i < numTopItems; ++i) + const int numTopItems = m_treeWidget->topLevelItemCount(); + for (int i = 0; i < numTopItems; ++i) { // selection of the topLevelItems QTreeWidgetItem* topLevelItem = m_treeWidget->topLevelItem(i); @@ -439,8 +435,8 @@ namespace EMStudio } // loop trough the children and adjust selection there - uint32 numChilds = topLevelItem->childCount(); - for (uint32 j = 0; j < numChilds; ++j) + int numChilds = topLevelItem->childCount(); + for (int j = 0; j < numChilds; ++j) { QTreeWidgetItem* child = topLevelItem->child(j); if (child->isSelected()) @@ -486,20 +482,15 @@ namespace EMStudio void ActorsWindow::contextMenuEvent(QContextMenuEvent* event) { - const QList items = m_treeWidget->selectedItems(); - - // get number of selected items and top level items - const uint32 numSelected = items.size(); - const uint32 numTopItems = m_treeWidget->topLevelItemCount(); + const QList items = m_treeWidget->selectedItems(); // create the context menu QMenu menu(this); menu.setToolTipsVisible(true); bool actorSelected = false; - for (uint32 i = 0; i < numSelected; ++i) + for (const QTreeWidgetItem* item : items) { - QTreeWidgetItem* item = items[i]; if (item->parent() == nullptr) { actorSelected = true; @@ -518,7 +509,7 @@ namespace EMStudio } } - if (numSelected > 0) + if (!items.empty()) { if (instanceSelected) { @@ -546,7 +537,7 @@ namespace EMStudio connect(removeAction, &QAction::triggered, this, &ActorsWindow::OnRemoveButtonClicked); } - if (numTopItems > 0) + if (m_treeWidget->topLevelItemCount() > 0) { QAction* clearAction = menu.addAction("Remove all"); connect(clearAction, &QAction::triggered, this, &ActorsWindow::OnClearButtonClicked); @@ -596,24 +587,16 @@ namespace EMStudio // get number of selected items and top level items const QList items = m_treeWidget->selectedItems(); - const uint32 numSelected = items.size(); - const uint32 numTopItems = m_treeWidget->topLevelItemCount(); // check if at least one actor selected - bool actorSelected = false; - for (uint32 i = 0; i < numSelected; ++i) + const bool actorSelected = AZStd::any_of(items.begin(), items.end(), [](const QTreeWidgetItem* item) { - QTreeWidgetItem* item = items[i]; - if (item->parent() == nullptr) - { - actorSelected = true; - break; - } - } + return item->parent() == nullptr; + }); // set the enabled state of the buttons m_createInstanceAction->setEnabled(actorSelected); - m_saveAction->setEnabled(numSelected != 0); + m_saveAction->setEnabled(!items.empty()); } @@ -623,11 +606,9 @@ namespace EMStudio // create the instances of the selected actors const QList items = m_treeWidget->selectedItems(); - const uint32 numItems = items.length(); - for (uint32 i = 0; i < numItems; ++i) + for (const QTreeWidgetItem* item : items) { // check if parent or child item - QTreeWidgetItem* item = items[i]; if (item == nullptr || item->parent() == nullptr) { continue; @@ -652,7 +633,7 @@ namespace EMStudio } - uint32 ActorsWindow::GetIDFromTreeItem(QTreeWidgetItem* item) + uint32 ActorsWindow::GetIDFromTreeItem(const QTreeWidgetItem* item) { if (item == nullptr) { diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/ActorsWindow.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/ActorsWindow.h index 8608e59439..181120d515 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/ActorsWindow.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/ActorsWindow.h @@ -52,7 +52,7 @@ namespace EMStudio void keyReleaseEvent(QKeyEvent* event) override; void SetControlsEnabled(); - uint32 GetIDFromTreeItem(QTreeWidgetItem* item); + uint32 GetIDFromTreeItem(const QTreeWidgetItem* item); void SetVisibilityFlags(bool isVisible); private: diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/SceneManagerPlugin.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/SceneManagerPlugin.cpp index 820cb78d51..61b6c44dbb 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/SceneManagerPlugin.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/SceneManagerPlugin.cpp @@ -25,8 +25,8 @@ namespace EMStudio { void SaveDirtyActorFilesCallback::GetDirtyFileNames(AZStd::vector* outFileNames, AZStd::vector* outObjects) { - const uint32 numLeaderActors = EMotionFX::GetActorManager().GetNumActors(); - for (uint32 i = 0; i < numLeaderActors; ++i) + const size_t numLeaderActors = EMotionFX::GetActorManager().GetNumActors(); + for (size_t i = 0; i < numLeaderActors; ++i) { EMotionFX::Actor* actor = EMotionFX::GetActorManager().GetActor(i); @@ -49,11 +49,9 @@ namespace EMStudio { MCORE_UNUSED(filenamesToSave); - const size_t numObjects = objects.size(); - for (size_t i = 0; i < numObjects; ++i) + for (const ObjectPointer& objPointer : objects) { // get the current object pointer and skip directly if the type check fails - ObjectPointer objPointer = objects[i]; if (objPointer.mActor == nullptr) { continue; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/PlaybackControlsGroup.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/PlaybackControlsGroup.cpp index 88e398d1f1..9c4238f23d 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/PlaybackControlsGroup.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/PlaybackControlsGroup.cpp @@ -129,8 +129,8 @@ namespace EMStudio return false; } - const AZ::u32 numActorInstances = EMotionFX::GetActorManager().GetNumActorInstances(); - for (AZ::u32 i = 0; i < numActorInstances; ++i) + const size_t numActorInstances = EMotionFX::GetActorManager().GetNumActorInstances(); + for (size_t i = 0; i < numActorInstances; ++i) { EMotionFX::ActorInstance* actorInstance = EMotionFX::GetActorManager().GetActorInstance(i); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/PlaybackOptionsGroup.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/PlaybackOptionsGroup.cpp index c9d794d5d5..14e2c79b88 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/PlaybackOptionsGroup.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/PlaybackOptionsGroup.cpp @@ -81,7 +81,7 @@ namespace EMStudio { const CommandSystem::SelectionList& selection = CommandSystem::GetCommandManager()->GetCurrentSelection(); - const uint32 numSelectedMotions = selection.GetNumSelectedMotions(); + const size_t numSelectedMotions = selection.GetNumSelectedMotions(); const bool isEnabled = (numSelectedMotions == 1); m_loopForeverAction->setEnabled(isEnabled); @@ -98,8 +98,8 @@ namespace EMStudio MotionWindowPlugin* motionWindowPlugin = TimeViewToolBar::GetMotionWindowPlugin(); if (motionWindowPlugin) { - const uint32 numMotions = selection.GetNumSelectedMotions(); - for (uint32 i = 0; i < numMotions; ++i) + const size_t numMotions = selection.GetNumSelectedMotions(); + for (size_t i = 0; i < numMotions; ++i) { MotionWindowPlugin::MotionTableEntry* entry = motionWindowPlugin->FindMotionEntryByID(selection.GetMotion(i)->GetID()); if (!entry) diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeTrack.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeTrack.cpp index ea41b0ab65..0f276d640d 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeTrack.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeTrack.cpp @@ -163,10 +163,9 @@ namespace EMStudio { if (delFromMem) { - const size_t numElems = mElements.size(); - for (size_t i = 0; i < numElems; ++i) + for (TimeTrackElement* mElement : mElements) { - delete mElements[i]; + delete mElement; } } @@ -175,7 +174,7 @@ namespace EMStudio // get the track element at a given pixel - TimeTrackElement* TimeTrack::GetElementAt(int32 x, int32 y) + TimeTrackElement* TimeTrack::GetElementAt(int32 x, int32 y) const { if (mVisible == false) { @@ -183,11 +182,9 @@ namespace EMStudio } // for all elements - const size_t numElems = mElements.size(); - for (size_t i = 0; i < numElems; ++i) + for (TimeTrackElement* element : mElements) { // check if its inside - TimeTrackElement* element = mElements[i]; if (element->GetIsVisible() == false) { continue; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeTrack.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeTrack.h index 4046ebf55f..55dcae73c3 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeTrack.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeTrack.h @@ -78,7 +78,7 @@ namespace EMStudio MCORE_INLINE TimeViewPlugin* GetPlugin() { return mPlugin; } MCORE_INLINE void SetStartY(uint32 y) { mStartY = y; } MCORE_INLINE uint32 GetStartY() const { return mStartY; } - bool GetIsInside(uint32 y) { return (y >= mStartY) && (y <= (mStartY + mHeight)); } + bool GetIsInside(uint32 y) const { return (y >= mStartY) && (y <= (mStartY + mHeight)); } void SetName(const char* name) { mName = name; } const char* GetName() const { return mName.c_str(); } @@ -95,7 +95,7 @@ namespace EMStudio MCORE_INLINE bool GetIsHighlighted() const { return mIsHighlighted; } MCORE_INLINE void SetIsHighlighted(bool enabled) { mIsHighlighted = enabled; } - TimeTrackElement* GetElementAt(int32 x, int32 y); + TimeTrackElement* GetElementAt(int32 x, int32 y) const; protected: AZStd::string mName; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeTrackElement.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeTrackElement.cpp index f0834ae0f9..78e911eb0a 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeTrackElement.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeTrackElement.cpp @@ -27,7 +27,7 @@ namespace EMStudio int32 TimeTrackElement::mTickHalfWidth = 7; // constructor - TimeTrackElement::TimeTrackElement(const char* name, TimeTrack* timeTrack, uint32 elementNumber, QColor color) + TimeTrackElement::TimeTrackElement(const char* name, TimeTrack* timeTrack, size_t elementNumber, QColor color) { mTrack = timeTrack; mName = name; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeTrackElement.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeTrackElement.h index a6d7116487..1e0d38486b 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeTrackElement.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeTrackElement.h @@ -35,14 +35,14 @@ namespace EMStudio RESIZEPOINT_END = 1 }; - TimeTrackElement(const char* name, TimeTrack* timeTrack, uint32 elementNumber = MCORE_INVALIDINDEX32, QColor color = QColor(0, 0, 0)); + TimeTrackElement(const char* name, TimeTrack* timeTrack, size_t elementNumber = InvalidIndex, QColor color = QColor(0, 0, 0)); virtual ~TimeTrackElement(); MCORE_INLINE double GetStartTime() const { return mStartTime; } MCORE_INLINE double GetEndTime() const { return mEndTime; } MCORE_INLINE bool GetIsSelected() const { return mIsSelected; } MCORE_INLINE TimeTrack* GetTrack() { return mTrack; } - MCORE_INLINE uint32 GetElementNumber() const { return mElementNumber; } + MCORE_INLINE size_t GetElementNumber() const { return mElementNumber; } QColor GetColor() const { return mColor; } void SetIsSelected(bool selected) { mIsSelected = selected; } @@ -51,7 +51,7 @@ namespace EMStudio void SetName(const char* name) { mName = name; } void SetToolTip(const char* toolTip) { mToolTip = toolTip; } void SetTrack(TimeTrack* track) { mTrack = track; } - void SetElementNumber(uint32 elementNumber) { mElementNumber = elementNumber; } + void SetElementNumber(size_t elementNumber) { mElementNumber = elementNumber; } void SetColor(QColor color) { mColor = color; } const QString& GetName() const { return mName; } @@ -91,7 +91,7 @@ namespace EMStudio QString mName; QString mToolTip; QColor mColor; - uint32 mElementNumber; + size_t mElementNumber; QPoint mTickPoints[6]; bool mVisible; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeViewPlugin.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeViewPlugin.cpp index e909e9ead3..2ca600596a 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeViewPlugin.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeViewPlugin.cpp @@ -107,10 +107,9 @@ namespace EMStudio delete mZoomOutCursor; // get rid of the motion infos - const uint32 numMotionInfos = mMotionInfos.size(); - for (uint32 i = 0; i < numMotionInfos; ++i) + for (MotionInfo* mMotionInfo : mMotionInfos) { - delete mMotionInfos[i]; + delete mMotionInfo; } } @@ -294,10 +293,9 @@ namespace EMStudio void TimeViewPlugin::RemoveAllTracks() { // get the number of time tracks and iterate through them - const uint32 numTracks = mTracks.size(); - for (uint32 i = 0; i < numTracks; ++i) + for (TimeTrack* track : mTracks) { - delete mTracks[i]; + delete track; } mTracks.clear(); @@ -306,37 +304,29 @@ namespace EMStudio TimeTrack* TimeViewPlugin::FindTrackByElement(TimeTrackElement* element) const { - // get the number of time tracks and iterate through them - const uint32 numTracks = mTracks.size(); - for (uint32 i = 0; i < numTracks; ++i) + const auto foundTrack = AZStd::find_if(begin(mTracks), end(mTracks), [element](const TimeTrack* timeTrack) { - TimeTrack* timeTrack = mTracks[i]; - // get the number of time track elements and iterate through them - const uint32 numElements = timeTrack->GetNumElements(); - for (uint32 j = 0; j < numElements; ++j) + const size_t numElements = timeTrack->GetNumElements(); + for (size_t j = 0; j < numElements; ++j) { if (timeTrack->GetElement(j) == element) { - return timeTrack; + return true; } } - } - - return nullptr; + return false; + }); + return foundTrack != end(mTracks) ? *foundTrack : nullptr; } - AZ::Outcome TimeViewPlugin::FindTrackIndex(const TimeTrack* track) const + AZ::Outcome TimeViewPlugin::FindTrackIndex(const TimeTrack* track) const { - const AZ::u32 numTracks = mTracks.size(); - for (AZ::u32 i = 0; i < numTracks; ++i) + const auto foundTrack = AZStd::find(begin(mTracks), end(mTracks), track); + if (foundTrack != end(mTracks)) { - if (mTracks[i] == track) - { - return AZ::Success(i); - } + return AZ::Success(static_cast(AZStd::distance(begin(mTracks), foundTrack))); } - return AZ::Failure(); } @@ -472,11 +462,10 @@ namespace EMStudio TimeTrackElement* TimeViewPlugin::GetElementAt(int32 x, int32 y) { // for all tracks - const uint32 numTracks = mTracks.size(); - for (uint32 i = 0; i < numTracks; ++i) + for (const TimeTrack* track : mTracks) { // check if the absolute pixel is inside - TimeTrackElement* result = mTracks[i]->GetElementAt(aznumeric_cast(x + mScrollX), y); + TimeTrackElement* result = track->GetElementAt(aznumeric_cast(x + mScrollX), y); if (result) { return result; @@ -491,17 +480,11 @@ namespace EMStudio TimeTrack* TimeViewPlugin::GetTrackAt(int32 y) { // for all tracks - const uint32 numTracks = mTracks.size(); - for (uint32 i = 0; i < numTracks; ++i) + const auto foundTrack = AZStd::find_if(begin(mTracks), end(mTracks), [y](const TimeTrack* track) { - // check if the absolute pixel is inside - if (mTracks[i]->GetIsInside(y)) - { - return mTracks[i]; - } - } - - return nullptr; + return track->GetIsInside(y); + }); + return foundTrack != end(mTracks) ? *foundTrack : nullptr; } @@ -509,14 +492,11 @@ namespace EMStudio void TimeViewPlugin::UnselectAllElements() { // for all tracks - const uint32 numTracks = mTracks.size(); - for (uint32 t = 0; t < numTracks; ++t) + for (TimeTrack* track : mTracks) { - TimeTrack* track = mTracks[t]; - // for all elements, deselect it - const uint32 numElems = track->GetNumElements(); - for (uint32 i = 0; i < numElems; ++i) + const size_t numElems = track->GetNumElements(); + for (size_t i = 0; i < numElems; ++i) { track->GetElement(i)->SetIsSelected(false); } @@ -603,18 +583,16 @@ namespace EMStudio } // for all tracks - const uint32 numTracks = mTracks.size(); - for (uint32 t = 0; t < numTracks; ++t) + for (TimeTrack* track : mTracks) { - TimeTrack* track = mTracks[t]; if (track->GetIsVisible() == false || track->GetIsEnabled() == false) { continue; } // for all elements - const uint32 numElems = track->GetNumElements(); - for (uint32 i = 0; i < numElems; ++i) + const size_t numElems = track->GetNumElements(); + for (size_t i = 0; i < numElems; ++i) { // don't snap to itself TimeTrackElement* element = track->GetElement(i); @@ -646,20 +624,18 @@ namespace EMStudio void TimeViewPlugin::RenderElementTimeHandles(QPainter& painter, uint32 dataWindowHeight, const QPen& pen) { // for all tracks - const uint32 numTracks = mTracks.size(); - for (uint32 t = 0; t < numTracks; ++t) + for (const TimeTrack* track : mTracks) { - TimeTrack* track = mTracks[t]; if (track->GetIsVisible() == false) { continue; } // for all elements - const uint32 numElems = track->GetNumElements(); - for (uint32 i = 0; i < numElems; ++i) + const size_t numElems = track->GetNumElements(); + for (size_t i = 0; i < numElems; ++i) { - TimeTrackElement* elem = track->GetElement(i); + const TimeTrackElement* elem = track->GetElement(i); // if the element has to show its time handles, do it if (elem->GetShowTimeHandles()) @@ -682,14 +658,11 @@ namespace EMStudio void TimeViewPlugin::DisableAllToolTips() { // for all tracks - const uint32 numTracks = mTracks.size(); - for (uint32 t = 0; t < numTracks; ++t) + for (const TimeTrack* track : mTracks) { - TimeTrack* track = mTracks[t]; - - // for all elements - const uint32 numElems = track->GetNumElements(); - for (uint32 i = 0; i < numElems; ++i) + // for all elements + const size_t numElems = track->GetNumElements(); + for (size_t i = 0; i < numElems; ++i) { TimeTrackElement* elem = track->GetElement(i); elem->SetShowToolTip(false); @@ -703,18 +676,16 @@ namespace EMStudio bool TimeViewPlugin::FindResizePoint(int32 x, int32 y, TimeTrackElement** outElement, uint32* outID) { // for all tracks - const uint32 numTracks = mTracks.size(); - for (uint32 t = 0; t < numTracks; ++t) + for (const TimeTrack* track : mTracks) { - TimeTrack* track = mTracks[t]; - if (track->GetIsVisible() == false) + if (track->GetIsVisible() == false) { continue; } // for all elements - const uint32 numElems = track->GetNumElements(); - for (uint32 i = 0; i < numElems; ++i) + const size_t numElems = track->GetNumElements(); + for (size_t i = 0; i < numElems; ++i) { TimeTrackElement* elem = track->GetElement(i); @@ -1189,8 +1160,8 @@ namespace EMStudio const EMotionFX::MotionEventTable* eventTable = mMotion->GetEventTable(); // get the number of tracks in the time view and iterate through them - const uint32 numTracks = GetNumTracks(); - for (uint32 trackIndex = 0; trackIndex < numTracks; ++trackIndex) + const size_t numTracks = GetNumTracks(); + for (size_t trackIndex = 0; trackIndex < numTracks; ++trackIndex) { // get the current time view track const TimeTrack* track = GetTrack(trackIndex); @@ -1206,8 +1177,8 @@ namespace EMStudio } // get the number of elements in the track and iterate through them - const uint32 numTrackElements = track->GetNumElements(); - for (uint32 elementIndex = 0; elementIndex < numTrackElements; ++elementIndex) + const size_t numTrackElements = track->GetNumElements(); + for (size_t elementIndex = 0; elementIndex < numTrackElements; ++elementIndex) { TimeTrackElement* element = track->GetElement(elementIndex); if (element->GetIsVisible() == false) @@ -1230,7 +1201,7 @@ namespace EMStudio void TimeViewPlugin::ReInit() { - if (EMotionFX::GetMotionManager().FindMotionIndex(mMotion) == MCORE_INVALIDINDEX32) + if (EMotionFX::GetMotionManager().FindMotionIndex(mMotion) == InvalidIndex) { // set the motion first back to nullptr mMotion = nullptr; @@ -1289,7 +1260,7 @@ namespace EMStudio TimeTrackElement* element = nullptr; if (eventIndex < timeTrack->GetNumElements()) { - element = timeTrack->GetElement(static_cast(eventIndex)); + element = timeTrack->GetElement(eventIndex); } else { @@ -1298,15 +1269,13 @@ namespace EMStudio } // Select the element if in mSelectedEvents. - const AZ::u32 numSelectedEvents = mSelectedEvents.size(); - for (AZ::u32 selectedEventIndex = 0; selectedEventIndex < numSelectedEvents; ++selectedEventIndex) + for (const EventSelectionItem& selectionItem : mSelectedEvents) { - const EventSelectionItem& selectionItem = mSelectedEvents[selectedEventIndex]; if (mMotion != selectionItem.mMotion) { continue; } - if (selectionItem.mTrackNr == static_cast(trackIndex) && selectionItem.mEventNr == static_cast(eventIndex)) + if (selectionItem.mTrackNr == trackIndex && selectionItem.mEventNr == eventIndex) { element->SetIsSelected(true); break; @@ -1334,7 +1303,7 @@ namespace EMStudio element->SetIsVisible(true); element->SetName(text.c_str()); element->SetColor(qColor); - element->SetElementNumber(static_cast(eventIndex)); + element->SetElementNumber(eventIndex); element->SetStartTime(motionEvent.GetStartTime()); element->SetEndTime(motionEvent.GetEndTime()); @@ -1400,14 +1369,14 @@ namespace EMStudio } else // mMotion == nullptr { - const uint32 numEventTracks = GetNumTracks(); - for (uint32 trackIndex = 0; trackIndex < numEventTracks; ++trackIndex) + const size_t numEventTracks = GetNumTracks(); + for (size_t trackIndex = 0; trackIndex < numEventTracks; ++trackIndex) { TimeTrack* timeTrack = GetTrack(trackIndex); timeTrack->SetIsVisible(false); - const uint32 numMotionEvents = timeTrack->GetNumElements(); - for (uint32 j = 0; j < numMotionEvents; ++j) + const size_t numMotionEvents = timeTrack->GetNumElements(); + for (size_t j = 0; j < numMotionEvents; ++j) { TimeTrackElement* element = timeTrack->GetElement(j); element->SetIsVisible(false); @@ -1447,15 +1416,13 @@ namespace EMStudio // find the motion info for the given motion id TimeViewPlugin::MotionInfo* TimeViewPlugin::FindMotionInfo(uint32 motionID) { - const uint32 numMotionInfos = mMotionInfos.size(); - for (uint32 i = 0; i < numMotionInfos; ++i) + const auto foundMotionInfo = AZStd::find_if(begin(mMotionInfos), end(mMotionInfos), [motionID](const MotionInfo* motionInfo) { - MotionInfo* motionInfo = mMotionInfos[i]; - - if (motionInfo->mMotionID == motionID) - { - return motionInfo; - } + return motionInfo->mMotionID == motionID; + }); + if (foundMotionInfo != end(mMotionInfos)) + { + return *foundMotionInfo; } // we haven't found a motion info for the given id yet, so create a new one @@ -1469,31 +1436,27 @@ namespace EMStudio void TimeViewPlugin::Select(const AZStd::vector& selection) { - uint32 i; - mSelectedEvents = selection; // get the number of tracks in the time view and iterate through them - const uint32 numTracks = GetNumTracks(); - for (i = 0; i < numTracks; ++i) + const size_t numTracks = GetNumTracks(); + for (size_t i = 0; i < numTracks; ++i) { TimeTrack* track = GetTrack(i); // get the number of elements in the track and iterate through them - const uint32 numTrackElements = track->GetNumElements(); - for (uint32 j = 0; j < numTrackElements; ++j) + const size_t numTrackElements = track->GetNumElements(); + for (size_t j = 0; j < numTrackElements; ++j) { TimeTrackElement* element = track->GetElement(j); element->SetIsSelected(false); } } - const uint32 numSelectedEvents = selection.size(); - for (i = 0; i < numSelectedEvents; ++i) + for (const EventSelectionItem& selectionItem : selection) { - const EventSelectionItem* selectionItem = &selection[i]; - TimeTrack* track = GetTrack(static_cast(selectionItem->mTrackNr)); - TimeTrackElement* element = track->GetElement(selectionItem->mEventNr); + TimeTrack* track = GetTrack(selectionItem.mTrackNr); + TimeTrackElement* element = track->GetElement(selectionItem.mEventNr); element->SetIsSelected(true); } @@ -1583,8 +1546,8 @@ namespace EMStudio } // get the motion event number by getting the time track element number - uint32 motionEventNr = element->GetElementNumber(); - if (motionEventNr == MCORE_INVALIDINDEX32) + size_t motionEventNr = element->GetElementNumber(); + if (motionEventNr == InvalidIndex) { return; } @@ -1636,18 +1599,18 @@ namespace EMStudio return; } - if (EMotionFX::GetMotionManager().FindMotionIndex(mMotion) == MCORE_INVALIDINDEX32) + if (EMotionFX::GetMotionManager().FindMotionIndex(mMotion) == InvalidIndex) { return; } // get the motion event table // MotionEventTable& eventTable = mMotion->GetEventTable(); - AZStd::vector eventNumbers; + AZStd::vector eventNumbers; // get the number of tracks in the time view and iterate through them - const uint32 numTracks = GetNumTracks(); - for (uint32 i = 0; i < numTracks; ++i) + const size_t numTracks = GetNumTracks(); + for (size_t i = 0; i < numTracks; ++i) { // get the current time view track TimeTrack* track = GetTrack(i); @@ -1659,8 +1622,8 @@ namespace EMStudio eventNumbers.clear(); // get the number of elements in the track and iterate through them - const uint32 numTrackElements = track->GetNumElements(); - for (uint32 j = 0; j < numTrackElements; ++j) + const size_t numTrackElements = track->GetNumElements(); + for (size_t j = 0; j < numTrackElements; ++j) { TimeTrackElement* element = track->GetElement(j); @@ -1695,18 +1658,18 @@ namespace EMStudio return; } - if (EMotionFX::GetMotionManager().FindMotionIndex(mMotion) == MCORE_INVALIDINDEX32) + if (EMotionFX::GetMotionManager().FindMotionIndex(mMotion) == InvalidIndex) { return; } // get the motion event table // MotionEventTable& eventTable = mMotion->GetEventTable(); - AZStd::vector eventNumbers; + AZStd::vector eventNumbers; // get the number of tracks in the time view and iterate through them - const uint32 numTracks = GetNumTracks(); - for (uint32 i = 0; i < numTracks; ++i) + const size_t numTracks = GetNumTracks(); + for (size_t i = 0; i < numTracks; ++i) { // get the current time view track TimeTrack* track = GetTrack(i); @@ -1718,8 +1681,8 @@ namespace EMStudio eventNumbers.clear(); // get the number of elements in the track and iterate through them - const uint32 numTrackElements = track->GetNumElements(); - for (uint32 j = 0; j < numTrackElements; ++j) + const size_t numTrackElements = track->GetNumElements(); + for (size_t j = 0; j < numTrackElements; ++j) { TimeTrackElement* element = track->GetElement(j); if (element->GetIsVisible()) @@ -1885,8 +1848,8 @@ namespace EMStudio if (actorInstance) { // find the actor instance data for this actor instance - const uint32 actorInstanceDataIndex = recorder.FindActorInstanceDataIndex(actorInstance); - if (actorInstanceDataIndex != MCORE_INVALIDINDEX32) + const size_t actorInstanceDataIndex = recorder.FindActorInstanceDataIndex(actorInstance); + if (actorInstanceDataIndex != InvalidIndex) { RecorderGroup* recorderGroup = mTimeViewToolBar->GetRecorderGroup(); const bool displayNodeActivity = recorderGroup->GetDisplayNodeActivity(); @@ -1928,11 +1891,9 @@ namespace EMStudio { if (mMotion) { - const uint32 numTracks = mTracks.size(); - for (uint32 i = 0; i < numTracks; ++i) + for (const TimeTrack* track : mTracks) { - TimeTrack* track = mTracks[i]; - if (track->GetIsVisible() == false) + if (track->GetIsVisible() == false) { continue; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeViewPlugin.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeViewPlugin.h index 386117d3a3..e6af4e1ae1 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeViewPlugin.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeViewPlugin.h @@ -39,7 +39,7 @@ namespace EMStudio EMotionFX::MotionEvent* GetMotionEvent(); EMotionFX::MotionEventTrack* GetEventTrack(); - uint32 mEventNr;// the motion event index in its track + size_t mEventNr;// the motion event index in its track size_t mTrackNr;// the corresponding track in which the event is in EMotionFX::Motion* mMotion;// the parent motion of the event track }; @@ -115,9 +115,9 @@ namespace EMStudio void AddTrack(TimeTrack* track); void RemoveAllTracks(); - TimeTrack* GetTrack(uint32 index) { return mTracks[index]; } + TimeTrack* GetTrack(size_t index) { return mTracks[index]; } size_t GetNumTracks() const { return mTracks.size(); } - AZ::Outcome FindTrackIndex(const TimeTrack* track) const; + AZ::Outcome FindTrackIndex(const TimeTrack* track) const; TimeTrack* FindTrackByElement(TimeTrackElement* element) const; void UnselectAllElements(); @@ -152,7 +152,7 @@ namespace EMStudio void ZoomRect(const QRect& rect); size_t GetNumSelectedEvents() { return mSelectedEvents.size(); } - EventSelectionItem GetSelectedEvent(uint32 index) const { return mSelectedEvents[index]; } + EventSelectionItem GetSelectedEvent(size_t index) const { return mSelectedEvents[index]; } void Select(const AZStd::vector& selection); @@ -180,7 +180,7 @@ namespace EMStudio void OnCenterOnCurTime(); void OnShowNodeHistoryNodeInGraph(); void OnClickNodeHistoryNode(); - void MotionEventTrackChanged(uint32 eventNr, float startTime, float endTime, const char* oldTrackName, const char* newTrackName) { UnselectAllElements(); CommandSystem::CommandHelperMotionEventTrackChanged(eventNr, startTime, endTime, oldTrackName, newTrackName); } + void MotionEventTrackChanged(size_t eventNr, float startTime, float endTime, const char* oldTrackName, const char* newTrackName) { UnselectAllElements(); CommandSystem::CommandHelperMotionEventTrackChanged(eventNr, startTime, endTime, oldTrackName, newTrackName); } void OnManualTimeChange(float timeValue); signals: diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeViewToolBar.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeViewToolBar.cpp index 8a503ef1f7..618d5f2bf5 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeViewToolBar.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeViewToolBar.cpp @@ -100,12 +100,12 @@ namespace EMStudio } const CommandSystem::SelectionList& selectionList = GetCommandManager()->GetCurrentSelection(); - const uint32 numSelectedMotions = selectionList.GetNumSelectedMotions(); + const size_t numSelectedMotions = selectionList.GetNumSelectedMotions(); AZStd::vector motionsToPlay; motionsToPlay.reserve(numSelectedMotions); - for (uint32 i = 0; i < numSelectedMotions; ++i) + for (size_t i = 0; i < numSelectedMotions; ++i) { EMotionFX::Motion* motion = selectionList.GetMotion(i); @@ -212,11 +212,9 @@ namespace EMStudio case RecorderGroup::Default: { const AZStd::vector& motionInstances = MotionWindowPlugin::GetSelectedMotionInstances(); - const size_t numMotionInstances = motionInstances.size(); - for (size_t i = 0; i < numMotionInstances; ++i) + for (EMotionFX::MotionInstance* motionInstance : motionInstances) { - EMotionFX::MotionInstance* motionInstance = motionInstances[i]; - motionInstance->SetCurrentTime(motionInstance->GetDuration()); + motionInstance->SetCurrentTime(motionInstance->GetDuration()); } break; } @@ -244,11 +242,9 @@ namespace EMStudio case RecorderGroup::Default: { const AZStd::vector& motionInstances = MotionWindowPlugin::GetSelectedMotionInstances(); - const size_t numMotionInstances = motionInstances.size(); - for (size_t i = 0; i < numMotionInstances; ++i) + for (EMotionFX::MotionInstance* motionInstance : motionInstances) { - EMotionFX::MotionInstance* motionInstance = motionInstances[i]; - motionInstance->Rewind(); + motionInstance->Rewind(); } break; } @@ -276,8 +272,8 @@ namespace EMStudio // Check if at least one actor instance has an anim graph playing. bool activateAnimGraph = true; const CommandSystem::SelectionList& selectionList = GetCommandManager()->GetCurrentSelection(); - const uint32 numActorInstances = selectionList.GetNumSelectedActorInstances(); - for (uint32 i = 0; i < numActorInstances; ++i) + const size_t numActorInstances = selectionList.GetNumSelectedActorInstances(); + for (size_t i = 0; i < numActorInstances; ++i) { EMotionFX::ActorInstance* actorInstance = selectionList.GetActorInstance(i); if (!actorInstance->GetIsOwnedByRuntime() && actorInstance->GetAnimGraphInstance()) @@ -370,8 +366,8 @@ namespace EMStudio MCore::CommandGroup commandGroup("Adjust default motion instances"); // get the number of selected motions and iterate through them - const uint32 numMotions = selection.GetNumSelectedMotions(); - for (uint32 i = 0; i < numMotions; ++i) + const size_t numMotions = selection.GetNumSelectedMotions(); + for (size_t i = 0; i < numMotions; ++i) { MotionWindowPlugin* plugin = GetMotionWindowPlugin(); MotionWindowPlugin::MotionTableEntry* entry = plugin ? plugin->FindMotionEntryByID(selection.GetMotion(i)->GetID()) : nullptr; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackDataWidget.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackDataWidget.cpp index fc60867864..bbfae05dff 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackDataWidget.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackDataWidget.cpp @@ -199,7 +199,7 @@ namespace EMStudio } } - void TrackDataWidget::RemoveTrack(AZ::u32 trackIndex) + void TrackDataWidget::RemoveTrack(size_t trackIndex) { mPlugin->SetRedrawFlag(); CommandSystem::CommandRemoveEventTrack(trackIndex); @@ -250,8 +250,8 @@ namespace EMStudio } // find the actor instance data for this actor instance - const uint32 actorInstanceDataIndex = recorder.FindActorInstanceDataIndex(actorInstance); - if (actorInstanceDataIndex == MCORE_INVALIDINDEX32) // it doesn't exist, so we didn't record anything for this actor instance + const size_t actorInstanceDataIndex = recorder.FindActorInstanceDataIndex(actorInstance); + if (actorInstanceDataIndex == InvalidIndex) // it doesn't exist, so we didn't record anything for this actor instance { return; } @@ -369,11 +369,8 @@ namespace EMStudio const uint32 graphContentsCode = mPlugin->mTrackHeaderWidget->mGraphContentsComboBox->currentIndex(); - const uint32 numItems = historyItems.size(); - for (uint32 i = 0; i < numItems; ++i) + for (EMotionFX::Recorder::NodeHistoryItem* curItem : historyItems) { - EMotionFX::Recorder::NodeHistoryItem* curItem = historyItems[i]; - double startTimePixel = mPlugin->TimeToPixel(curItem->mStartTime); double endTimePixel = mPlugin->TimeToPixel(curItem->mEndTime); @@ -455,11 +452,10 @@ namespace EMStudio recorder.ExtractNodeHistoryItems(*actorInstanceData, aznumeric_cast(mPlugin->mCurTime), true, (EMotionFX::Recorder::EValueType)graphContentsCode, &mActiveItems, &mTrackRemap); // display the values and names - uint32 offset = 0; - const uint32 numActiveItems = mActiveItems.size(); - for (uint32 i = 0; i < numActiveItems; ++i) + int offset = 0; + for (const EMotionFX::Recorder::ExtractedNodeHistoryItem& mActiveItem : mActiveItems) { - EMotionFX::Recorder::NodeHistoryItem* curItem = mActiveItems[i].mNodeHistoryItem; + EMotionFX::Recorder::NodeHistoryItem* curItem = mActiveItem.mNodeHistoryItem; if (curItem == nullptr) { continue; @@ -473,7 +469,7 @@ namespace EMStudio mTempString += curItem->mName.c_str(); } - if (showMotionFiles && curItem->mMotionFileName.size() > 0) + if (showMotionFiles && !curItem->mMotionFileName.empty()) { if (!mTempString.empty()) { @@ -485,14 +481,14 @@ namespace EMStudio if (!mTempString.empty()) { - mTempString += AZStd::string::format(" = %.4f", mActiveItems[i].mValue); + mTempString += AZStd::string::format(" = %.4f", mActiveItem.mValue); } else { - mTempString = AZStd::string::format("%.4f", mActiveItems[i].mValue); + mTempString = AZStd::string::format("%.4f", mActiveItem.mValue); } - const AZ::Color colorCode = (useNodeColors) ? mActiveItems[i].mNodeHistoryItem->mTypeColor : mActiveItems[i].mNodeHistoryItem->mColor; + const AZ::Color colorCode = (useNodeColors) ? mActiveItem.mNodeHistoryItem->mTypeColor : mActiveItem.mNodeHistoryItem->mColor; QColor color; color.setRgbF(colorCode.GetR(), colorCode.GetG(), colorCode.GetB(), colorCode.GetA()); @@ -528,11 +524,8 @@ namespace EMStudio const float tickHeight = 16; QPointF tickPoints[6]; - const uint32 numItems = historyItems.size(); - for (uint32 i = 0; i < numItems; ++i) + for (const EMotionFX::Recorder::EventHistoryItem* curItem : historyItems) { - EMotionFX::Recorder::EventHistoryItem* curItem = historyItems[i]; - float height = aznumeric_cast((curItem->mTrackIndex * 20) + mEventsStartHeight); double startTimePixel = mPlugin->TimeToPixel(curItem->mStartTime); @@ -628,31 +621,28 @@ namespace EMStudio const bool sorted = recorderGroup->GetSortNodeActivity(); const bool useNodeColors = recorderGroup->GetUseNodeTypeColors(); - const uint32 graphContentsCode = mPlugin->mTrackHeaderWidget->mNodeContentsComboBox->currentIndex(); + const int graphContentsCode = mPlugin->mTrackHeaderWidget->mNodeContentsComboBox->currentIndex(); recorder.ExtractNodeHistoryItems(*actorInstanceData, aznumeric_cast(mPlugin->mCurTime), sorted, (EMotionFX::Recorder::EValueType)graphContentsCode, &mActiveItems, &mTrackRemap); const bool showNodeNames = mPlugin->mTrackHeaderWidget->mNodeNamesCheckBox->isChecked(); const bool showMotionFiles = mPlugin->mTrackHeaderWidget->mMotionFilesCheckBox->isChecked(); const bool interpolate = recorder.GetRecordSettings().mInterpolate; - const uint32 nodeContentsCode = mPlugin->mTrackHeaderWidget->mNodeContentsComboBox->currentIndex(); + const int nodeContentsCode = mPlugin->mTrackHeaderWidget->mNodeContentsComboBox->currentIndex(); // for all history items QRectF itemRect; - const uint32 numItems = historyItems.size(); - for (uint32 i = 0; i < numItems; ++i) + for (EMotionFX::Recorder::NodeHistoryItem* curItem : historyItems) { - EMotionFX::Recorder::NodeHistoryItem* curItem = historyItems[i]; - // draw the background rect double startTimePixel = mPlugin->TimeToPixel(curItem->mStartTime); double endTimePixel = mPlugin->TimeToPixel(curItem->mEndTime); - const uint32 trackIndex = mTrackRemap[ curItem->mTrackIndex ]; + const size_t trackIndex = mTrackRemap[ curItem->mTrackIndex ]; itemRect.setLeft(startTimePixel); itemRect.setRight(endTimePixel - 1); - itemRect.setTop((mNodeRectsStartHeight + (trackIndex * (mNodeHistoryItemHeight + 3)) + 3) /* - mPlugin->mScrollY*/); + itemRect.setTop((mNodeRectsStartHeight + (aznumeric_cast(trackIndex) * (mNodeHistoryItemHeight + 3)) + 3)); itemRect.setBottom(itemRect.top() + mNodeHistoryItemHeight); if (!rect.intersects(itemRect.toRect())) @@ -698,7 +688,7 @@ namespace EMStudio int32 widthInPixels = aznumeric_cast(endTimePixel - startTimePixel); if (widthInPixels > 0) { - EMotionFX::KeyTrackLinearDynamic* keyTrack = &curItem->mGlobalWeights; // init on global weights + const EMotionFX::KeyTrackLinearDynamic* keyTrack = &curItem->mGlobalWeights; // init on global weights if (nodeContentsCode == 1) { keyTrack = &curItem->mLocalWeights; @@ -774,7 +764,7 @@ namespace EMStudio mTempString += curItem->mName.c_str(); } - if (showMotionFiles && curItem->mMotionFileName.size() > 0) + if (showMotionFiles && !curItem->mMotionFileName.empty()) { if (!mTempString.empty()) { @@ -810,8 +800,8 @@ namespace EMStudio } // handle highlighting - const uint32 numTracks = mPlugin->GetNumTracks(); - for (uint32 i = 0; i < numTracks; ++i) + const size_t numTracks = mPlugin->GetNumTracks(); + for (size_t i = 0; i < numTracks; ++i) { TimeTrack* track = mPlugin->GetTrack(i); @@ -825,8 +815,8 @@ namespace EMStudio TimeTrackElement* mouseCursorElement = mPlugin->GetElementAt(localCursorPos.x(), localCursorPos.y()); // get the number of elements, iterate through them and disable the highlight flag - const uint32 numElements = track->GetNumElements(); - for (uint32 e = 0; e < numElements; ++e) + const size_t numElements = track->GetNumElements(); + for (size_t e = 0; e < numElements; ++e) { TimeTrackElement* element = track->GetElement(e); @@ -845,8 +835,8 @@ namespace EMStudio track->SetIsHighlighted(false); // get the number of elements, iterate through them and disable the highlight flag - const uint32 numElements = track->GetNumElements(); - for (uint32 e = 0; e < numElements; ++e) + const size_t numElements = track->GetNumElements(); + for (size_t e = 0; e < numElements; ++e) { TimeTrackElement* element = track->GetElement(e); element->SetIsHighlighted(false); @@ -923,35 +913,31 @@ namespace EMStudio visibleEndTime = mPlugin->PixelToTime(width); //mPlugin->CalcTime( width, &visibleEndTime, nullptr, nullptr, nullptr, nullptr ); // for all tracks - const uint32 numTracks = mPlugin->mTracks.size(); - for (uint32 i = 0; i < numTracks; ++i) + for (TimeTrack* track : mPlugin->mTracks) { - TimeTrack* track = mPlugin->mTracks[i]; track->SetStartY(yOffset); // path for making the cut elements a bit transparent if (mCutMode) { // disable cut mode for all elements on default - const uint32 numElements = track->GetNumElements(); - for (uint32 e = 0; e < numElements; ++e) + const size_t numElements = track->GetNumElements(); + for (size_t e = 0; e < numElements; ++e) { track->GetElement(e)->SetIsCut(false); } // get the number of copy elements and check if ours is in - const size_t numCopyElements = mCopyElements.size(); - for (size_t c = 0; c < numCopyElements; ++c) + for (const CopyElement& copyElement : mCopyElements) { // get the copy element and make sure we're in the right track - const CopyElement& copyElement = mCopyElements[c]; if (copyElement.m_trackName != track->GetName()) { continue; } // set the cut mode of the elements - for (uint32 e = 0; e < numElements; ++e) + for (size_t e = 0; e < numElements; ++e) { TimeTrackElement* element = track->GetElement(e); if (MCore::Compare::CheckIfIsClose(aznumeric_cast(element->GetStartTime()), copyElement.m_startTime, MCore::Math::epsilon) && @@ -1436,11 +1422,11 @@ namespace EMStudio if (shiftPressed) { // get the element number of the clicked element - const uint32 clickedElementNr = element->GetElementNumber(); + const size_t clickedElementNr = element->GetElementNumber(); // get the element number of the first previously selected element TimeTrackElement* firstSelectedElement = timeTrack->GetFirstSelectedElement(); - const uint32 firstSelectedNr = firstSelectedElement ? firstSelectedElement->GetElementNumber() : 0; + const size_t firstSelectedNr = firstSelectedElement ? firstSelectedElement->GetElementNumber() : 0; // range select timeTrack->RangeSelectElements(firstSelectedNr, clickedElementNr); @@ -1468,14 +1454,7 @@ namespace EMStudio } // if we're going to resize - if (mResizeElement && mResizeID != MCORE_INVALIDINDEX32) - { - mResizing = true; - } - else - { - mResizing = false; - } + mResizing = mResizeElement && mResizeID != InvalidIndex32; // store the last clicked position mMouseLeftClicked = true; @@ -1725,12 +1704,12 @@ namespace EMStudio TimeTrack* timeTrack = mPlugin->GetTrackAt(mContextMenuY); - uint32 numElements = 0; - uint32 numSelectedElements = 0; + size_t numElements = 0; + size_t numSelectedElements = 0; // calculate the number of selected and total events - const uint32 numTracks = mPlugin->GetNumTracks(); - for (uint32 i = 0; i < numTracks; ++i) + const size_t numTracks = mPlugin->GetNumTracks(); + for (size_t i = 0; i < numTracks; ++i) { // get the current time view track TimeTrack* track = mPlugin->GetTrack(i); @@ -1740,8 +1719,8 @@ namespace EMStudio } // get the number of elements in the track and iterate through them - const uint32 numTrackElements = track->GetNumElements(); - for (uint32 j = 0; j < numTrackElements; ++j) + const size_t numTrackElements = track->GetNumElements(); + for (size_t j = 0; j < numTrackElements; ++j) { TimeTrackElement* element = track->GetElement(j); numElements++; @@ -1756,7 +1735,7 @@ namespace EMStudio if (timeTrack) { numElements = timeTrack->GetNumElements(); - for (uint32 i = 0; i < numElements; ++i) + for (size_t i = 0; i < numElements; ++i) { TimeTrackElement* element = timeTrack->GetElement(i); @@ -1916,11 +1895,11 @@ namespace EMStudio return; } - AZStd::vector eventNumbers; + AZStd::vector eventNumbers; // calculate the number of selected events - const uint32 numEvents = timeTrack->GetNumElements(); - for (uint32 i = 0; i < numEvents; ++i) + const size_t numEvents = timeTrack->GetNumElements(); + for (size_t i = 0; i < numEvents; ++i) { TimeTrackElement* element = timeTrack->GetElement(i); @@ -1950,11 +1929,11 @@ namespace EMStudio return; } - AZStd::vector eventNumbers; + AZStd::vector eventNumbers; // construct an array with the event numbers - const uint32 numEvents = timeTrack->GetNumElements(); - for (uint32 i = 0; i < numEvents; ++i) + const size_t numEvents = timeTrack->GetNumElements(); + for (size_t i = 0; i < numEvents; ++i) { eventNumbers.emplace_back(i); } @@ -1974,7 +1953,7 @@ namespace EMStudio return; } - const AZ::Outcome trackIndexOutcome = mPlugin->FindTrackIndex(timeTrack); + const AZ::Outcome trackIndexOutcome = mPlugin->FindTrackIndex(timeTrack); if (trackIndexOutcome.IsSuccess()) { RemoveTrack(trackIndexOutcome.GetValue()); @@ -2010,9 +1989,9 @@ namespace EMStudio } // iterate through the elements - const uint32 numElements = timeTrack->GetNumElements(); + const size_t numElements = timeTrack->GetNumElements(); MCORE_ASSERT(numElements == eventTrack->GetNumEvents()); - for (uint32 i = 0; i < numElements; ++i) + for (size_t i = 0; i < numElements; ++i) { // get the element and skip all unselected ones const TimeTrackElement* element = timeTrack->GetElement(i); @@ -2146,7 +2125,7 @@ namespace EMStudio } // get the number of events and iterate through them - size_t eventNr = MCORE_INVALIDINDEX32; + size_t eventNr = InvalidIndex; const size_t numEvents = eventTrack->GetNumEvents(); for (eventNr = 0; eventNr < numEvents; ++eventNr) { @@ -2160,9 +2139,9 @@ namespace EMStudio } // remove event - if (eventNr != MCORE_INVALIDINDEX32) + if (eventNr != InvalidIndex) { - CommandSystem::CommandHelperRemoveMotionEvent(copyElement.m_motionID, copyElement.m_trackName.c_str(), static_cast(eventNr), &commandGroup); + CommandSystem::CommandHelperRemoveMotionEvent(copyElement.m_motionID, copyElement.m_trackName.c_str(), eventNr, &commandGroup); } } } @@ -2170,10 +2149,8 @@ namespace EMStudio const float offset = useLocation ? aznumeric_cast(mPlugin->PixelToTime(mContextMenuX, true)) - minEvent->m_startTime : 0.0f; // iterate through the elements to copy and add the new motion events - for (uint32 i = 0; i < numElements; ++i) + for (const CopyElement& copyElement : mCopyElements) { - const CopyElement& copyElement = mCopyElements[i]; - float startTime = copyElement.m_startTime + offset; float endTime = copyElement.m_endTime + offset; @@ -2226,8 +2203,8 @@ namespace EMStudio void TrackDataWidget::SelectElementsInRect(const QRect& rect, bool overwriteCurSelection, bool select, bool toggleMode) { // get the number of tracks and iterate through them - const uint32 numTracks = mPlugin->GetNumTracks(); - for (uint32 i = 0; i < numTracks; ++i) + const size_t numTracks = mPlugin->GetNumTracks(); + for (size_t i = 0; i < numTracks; ++i) { // get the current time track TimeTrack* track = mPlugin->GetTrack(i); @@ -2315,9 +2292,9 @@ namespace EMStudio // if we recorded node history mNodeHistoryRect = QRect(); - if (actorInstanceData && actorInstanceData->mNodeHistoryItems.size() > 0) + if (actorInstanceData && !actorInstanceData->mNodeHistoryItems.empty()) { - const uint32 height = (recorder.CalcMaxNodeHistoryTrackIndex(*actorInstanceData) + 1) * (mNodeHistoryItemHeight + 3) + mNodeRectsStartHeight; + const int height = aznumeric_caster((recorder.CalcMaxNodeHistoryTrackIndex(*actorInstanceData) + 1) * (mNodeHistoryItemHeight + 3) + mNodeRectsStartHeight); mNodeHistoryRect.setTop(mNodeRectsStartHeight); mNodeHistoryRect.setBottom(height); mNodeHistoryRect.setLeft(0); @@ -2325,9 +2302,9 @@ namespace EMStudio } mEventHistoryTotalHeight = 0; - if (actorInstanceData && actorInstanceData->mEventHistoryItems.size() > 0) + if (actorInstanceData && !actorInstanceData->mEventHistoryItems.empty()) { - mEventHistoryTotalHeight = (recorder.CalcMaxEventHistoryTrackIndex(*actorInstanceData) + 1) * 20; + mEventHistoryTotalHeight = aznumeric_caster((recorder.CalcMaxEventHistoryTrackIndex(*actorInstanceData) + 1) * 20); } } @@ -2348,7 +2325,7 @@ namespace EMStudio // make sure the mTrackRemap array is up to date RecorderGroup* recorderGroup = mPlugin->GetTimeViewToolBar()->GetRecorderGroup(); const bool sorted = recorderGroup->GetSortNodeActivity(); - const uint32 graphContentsCode = mPlugin->mTrackHeaderWidget->mNodeContentsComboBox->currentIndex(); + const int graphContentsCode = mPlugin->mTrackHeaderWidget->mNodeContentsComboBox->currentIndex(); EMotionFX::GetRecorder().ExtractNodeHistoryItems(*actorInstanceData, aznumeric_cast(mPlugin->mCurTime), sorted, (EMotionFX::Recorder::EValueType)graphContentsCode, &mActiveItems, &mTrackRemap); @@ -2356,11 +2333,8 @@ namespace EMStudio const AZStd::vector& historyItems = actorInstanceData->mNodeHistoryItems; QRect rect; - const uint32 numItems = historyItems.size(); - for (uint32 i = 0; i < numItems; ++i) + for (EMotionFX::Recorder::NodeHistoryItem* curItem : historyItems) { - EMotionFX::Recorder::NodeHistoryItem* curItem = historyItems[i]; - // draw the background rect double startTimePixel = mPlugin->TimeToPixel(curItem->mStartTime); double endTimePixel = mPlugin->TimeToPixel(curItem->mEndTime); @@ -2372,7 +2346,7 @@ namespace EMStudio rect.setLeft(aznumeric_cast(startTimePixel)); rect.setRight(aznumeric_cast(endTimePixel)); - rect.setTop((mNodeRectsStartHeight + (mTrackRemap[curItem->mTrackIndex] * (mNodeHistoryItemHeight + 3)) + 3)); + rect.setTop((mNodeRectsStartHeight + (aznumeric_cast(mTrackRemap[curItem->mTrackIndex]) * (mNodeHistoryItemHeight + 3)) + 3)); rect.setBottom(rect.top() + mNodeHistoryItemHeight); if (rect.contains(x, y)) @@ -2398,8 +2372,8 @@ namespace EMStudio } // find the actor instance data for this actor instance - const uint32 actorInstanceDataIndex = recorder.FindActorInstanceDataIndex(actorInstance); - if (actorInstanceDataIndex == MCORE_INVALIDINDEX32) // it doesn't exist, so we didn't record anything for this actor instance + const size_t actorInstanceDataIndex = recorder.FindActorInstanceDataIndex(actorInstance); + if (actorInstanceDataIndex == InvalidIndex) // it doesn't exist, so we didn't record anything for this actor instance { return nullptr; } @@ -2466,19 +2440,19 @@ namespace EMStudio EMotionFX::AnimGraphNode* curNode = node->GetParentNode(); while (curNode) { - nodePath.emplace(0, curNode); + nodePath.emplace(nodePath.begin(), curNode); curNode = curNode->GetParentNode(); } AZStd::string nodePathString; nodePathString.reserve(256); - for (uint32 i = 0; i < nodePath.size(); ++i) + for (const EMotionFX::AnimGraphNode* parentNode : nodePath) { - nodePathString += nodePath[i]->GetName(); - if (i != nodePath.size() - 1) + if (!nodePathString.empty()) { nodePathString += " > "; } + nodePathString += parentNode->GetName(); } outString += AZStd::string::format("

Node Path: 

"); @@ -2493,16 +2467,16 @@ namespace EMStudio if (node->GetNumChildNodes() > 0) { outString += AZStd::string::format("

Child Nodes: 

"); - outString += AZStd::string::format("

%d

", node->GetNumChildNodes()); + outString += AZStd::string::format("

%zu

", node->GetNumChildNodes()); outString += AZStd::string::format("

Recursive Children: 

"); - outString += AZStd::string::format("

%d

", node->RecursiveCalcNumNodes()); + outString += AZStd::string::format("

%zu

", node->RecursiveCalcNumNodes()); } } } // motion name - if (item->mMotionID != MCORE_INVALIDINDEX32 && item->mMotionFileName.size() > 0) + if (item->mMotionID != InvalidIndex32 && !item->mMotionFileName.empty()) { outString += AZStd::string::format("

Motion FileName: 

"); outString += AZStd::string::format("

%s

", item->mMotionFileName.c_str()); @@ -2555,14 +2529,10 @@ namespace EMStudio const float tickHalfWidth = 7; const float tickHeight = 16; - const uint32 numItems = historyItems.size(); - for (uint32 i = 0; i < numItems; ++i) + for (EMotionFX::Recorder::EventHistoryItem* curItem : historyItems) { - EMotionFX::Recorder::EventHistoryItem* curItem = historyItems[i]; - - float height = aznumeric_cast((curItem->mTrackIndex * 20) + mEventsStartHeight); + float height = aznumeric_caster((curItem->mTrackIndex * 20) + mEventsStartHeight); double startTimePixel = mPlugin->TimeToPixel(curItem->mStartTime); - //double endTimePixel = mPlugin->TimeToPixel( curItem->mEndTime ); const QRect rect(QPoint(aznumeric_cast(startTimePixel - tickHalfWidth), aznumeric_cast(height)), QSize(aznumeric_cast(tickHalfWidth * 2), aznumeric_cast(tickHeight))); if (rect.contains(QPoint(x, y))) @@ -2657,14 +2627,13 @@ namespace EMStudio } AZStd::string nodePathString; - nodePathString.reserve(256); - for (uint32 i = 0; i < nodePath.size(); ++i) + for (const EMotionFX::AnimGraphNode* parentNode : nodePath) { - nodePathString += nodePath[i]->GetName(); - if (i != nodePath.size() - 1) + if (!nodePathString.empty()) { nodePathString += " > "; } + nodePathString += parentNode->GetName(); } outString += AZStd::string::format("

Node Path: 

"); @@ -2679,10 +2648,10 @@ namespace EMStudio if (node->GetNumChildNodes() > 0) { outString += AZStd::string::format("

Child Nodes: 

"); - outString += AZStd::string::format("

%d

", node->GetNumChildNodes()); + outString += AZStd::string::format("

%zu

", node->GetNumChildNodes()); outString += AZStd::string::format("

Recursive Children: 

"); - outString += AZStd::string::format("

%d

", node->RecursiveCalcNumNodes()); + outString += AZStd::string::format("

%zu

", node->RecursiveCalcNumNodes()); } // show the motion info diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackDataWidget.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackDataWidget.h index 2709927254..48effb92d0 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackDataWidget.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackDataWidget.h @@ -50,7 +50,7 @@ namespace EMStudio void resizeGL(int w, int h) override; void paintGL() override; - void RemoveTrack(AZ::u32 trackIndex); + void RemoveTrack(size_t trackIndex); protected: //void paintEvent(QPaintEvent* event); @@ -70,7 +70,7 @@ namespace EMStudio void MotionEventChanged(TimeTrackElement* element, double startTime, double endTime); void TrackAdded(TimeTrack* track); void SelectionChanged(); - void ElementTrackChanged(uint32 eventNr, float startTime, float endTime, const char* oldTrackName, const char* newTrackName); + void ElementTrackChanged(size_t eventNr, float startTime, float endTime, const char* oldTrackName, const char* newTrackName); private slots: void OnRemoveElement() { RemoveMotionEvent(mContextMenuX, mContextMenuY); } @@ -137,7 +137,7 @@ namespace EMStudio double mOldCurrentTime; AZStd::vector mActiveItems; - AZStd::vector mTrackRemap; + AZStd::vector mTrackRemap; // copy and paste struct CopyElement diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackHeaderWidget.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackHeaderWidget.cpp index 363a278b8e..5b21d8c7b5 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackHeaderWidget.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackHeaderWidget.cpp @@ -173,8 +173,7 @@ namespace EMStudio setVisible(true); mStackWidget->setVisible(false); - const uint32 numTracks = mPlugin->mTracks.size(); - if (numTracks == 0) + if (mPlugin->mTracks.empty()) { return; } @@ -184,7 +183,8 @@ namespace EMStudio mTrackLayout->setMargin(0); mTrackLayout->setSpacing(1); - for (uint32 i = 0; i < numTracks; ++i) + const size_t numTracks = mPlugin->mTracks.size(); + for (size_t i = 0; i < numTracks; ++i) { TimeTrack* track = mPlugin->mTracks[i]; @@ -206,7 +206,7 @@ namespace EMStudio } - HeaderTrackWidget::HeaderTrackWidget(QWidget* parent, TimeViewPlugin* parentPlugin, TrackHeaderWidget* trackHeaderWidget, TimeTrack* timeTrack, uint32 trackIndex) + HeaderTrackWidget::HeaderTrackWidget(QWidget* parent, TimeViewPlugin* parentPlugin, TrackHeaderWidget* trackHeaderWidget, TimeTrack* timeTrack, size_t trackIndex) : QWidget(parent) { mPlugin = parentPlugin; @@ -309,8 +309,8 @@ namespace EMStudio AZStd::string name = mNameEdit->text().toUtf8().data(); bool nameUnique = true; - const uint32 numTracks = mPlugin->GetNumTracks(); - for (uint32 i = 0; i < numTracks; ++i) + const size_t numTracks = mPlugin->GetNumTracks(); + for (size_t i = 0; i < numTracks; ++i) { TimeTrack* track = mPlugin->GetTrack(i); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackHeaderWidget.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackHeaderWidget.h index ced87059a4..dae551d2bb 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackHeaderWidget.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackHeaderWidget.h @@ -46,14 +46,14 @@ namespace EMStudio MCORE_MEMORYOBJECTCATEGORY(HeaderTrackWidget, MCore::MCORE_DEFAULT_ALIGNMENT, MEMCATEGORY_STANDARDPLUGINS); public: - HeaderTrackWidget(QWidget* parent, TimeViewPlugin* parentPlugin, TrackHeaderWidget* trackHeaderWidget, TimeTrack* timeTrack, uint32 trackIndex); + HeaderTrackWidget(QWidget* parent, TimeViewPlugin* parentPlugin, TrackHeaderWidget* trackHeaderWidget, TimeTrack* timeTrack, size_t trackIndex); QCheckBox* mEnabledCheckbox; QLabel* mNameLabel; QLineEdit* mNameEdit; QPushButton* mRemoveButton; TimeTrack* mTrack; - uint32 mTrackIndex; + size_t mTrackIndex; TrackHeaderWidget* mHeaderTrackWidget; TimeViewPlugin* mPlugin; @@ -62,8 +62,8 @@ namespace EMStudio bool eventFilter(QObject* object, QEvent* event) override; signals: - void TrackNameChanged(const QString& text, int trackNr); - void EnabledStateChanged(bool checked, int trackNr); + void TrackNameChanged(const QString& text, size_t trackNr); + void EnabledStateChanged(bool checked, size_t trackNr); public slots: void NameChanged(); @@ -97,8 +97,8 @@ namespace EMStudio public slots: void OnAddTrackButtonClicked() { CommandSystem::CommandAddEventTrack(); } - void OnTrackNameChanged(const QString& text, int trackNr) { CommandSystem::CommandRenameEventTrack(trackNr, FromQtString(text).c_str()); } - void OnTrackEnabledStateChanged(bool enabled, int trackNr) { CommandSystem::CommandEnableEventTrack(trackNr, enabled); } + void OnTrackNameChanged(const QString& text, size_t trackNr) { CommandSystem::CommandRenameEventTrack(trackNr, FromQtString(text).c_str()); } + void OnTrackEnabledStateChanged(bool enabled, size_t trackNr) { CommandSystem::CommandEnableEventTrack(trackNr, enabled); } void OnDetailedNodesCheckBox(int state); void OnCheckBox(int state); void OnComboBoxIndexChanged(int state); diff --git a/Gems/EMotionFX/Code/MysticQt/Source/DialogStack.cpp b/Gems/EMotionFX/Code/MysticQt/Source/DialogStack.cpp index 36c0edf986..6a6d540519 100644 --- a/Gems/EMotionFX/Code/MysticQt/Source/DialogStack.cpp +++ b/Gems/EMotionFX/Code/MysticQt/Source/DialogStack.cpp @@ -8,6 +8,8 @@ // include the required headers #include "DialogStack.h" +#include "AzCore/std/iterator.h" +#include "AzCore/std/limits.h" #include "MysticQtManager.h" #include #include @@ -100,7 +102,7 @@ namespace MysticQt // add the dialog widget // the splitter is hierarchical : {a, {b, c}} - QSplitter* dialogSplitter; + DialogStackSplitter* dialogSplitter; if (mDialogs.empty()) { // add the dialog widget @@ -149,7 +151,7 @@ namespace MysticQt dialogSplitter->setChildrenCollapsible(false); // add the current last dialog and the new dialog after - dialogSplitter->addWidget(mDialogs.back().mDialogWidget.get()); + dialogSplitter->addWidget(mDialogs.back().mDialogWidget); dialogSplitter->addWidget(dialogWidget); // stretch if needed @@ -265,7 +267,7 @@ namespace MysticQt /*.mButton =*/ headerButton, /*.mFrame =*/ frame, /*.mWidget =*/ widget, - /*.mDialogWidget =*/ AZStd::unique_ptr{dialogWidget}, + /*.mDialogWidget =*/ dialogWidget, /*.mSplitter =*/ dialogSplitter, /*.mClosable =*/ closable, /*.mMaximizeSize =*/ maximizeSize, @@ -303,32 +305,27 @@ namespace MysticQt bool DialogStack::Remove(QWidget* widget) { - const uint32 numDialogs = mDialogs.size(); - for (uint32 i = 0; i < numDialogs; ++i) + const auto foundDialog = AZStd::find_if(begin(mDialogs), end(mDialogs), [widget](const Dialog& dialog) { - QLayout* layout = mDialogs[i].mFrame->layout(); - int index = layout->indexOf(widget); + return dialog.mFrame->layout()->indexOf(widget) != -1; + }); - // if the widget is located in the current layout, remove it - // all next dialogs has to be moved to the previous splitter and delete if the last splitter is empty - if (index != -1) - { - // remove the dialog - // TODO : shift all dialogs needed as explained on the previous comment - mDialogs[i].mDialogWidget->hide(); - mDialogs[i].mDialogWidget->deleteLater(); - mDialogs.erase(AZStd::next(begin(mDialogs), i)); - - // update the scroll bars - UpdateScrollBars(); - - // done - return true; - } + if (foundDialog == end(mDialogs)) + { + return false; } - // not found - return false; + // if the widget is located in the current layout, remove it + // all next dialogs has to be moved to the previous splitter and delete if the last splitter is empty + // TODO : shift all dialogs needed as explained on the previous comment + foundDialog->mDialogWidget->hide(); + foundDialog->mDialogWidget->deleteLater(); + mDialogs.erase(foundDialog); + + // update the scroll bars + UpdateScrollBars(); + + return true; } @@ -336,7 +333,7 @@ namespace MysticQt void DialogStack::OnHeaderButton() { QPushButton* button = (QPushButton*)sender(); - const uint32 dialogIndex = FindDialog(button); + const size_t dialogIndex = FindDialog(button); if (mDialogs[dialogIndex].mFrame->isHidden()) { Open(button); @@ -349,87 +346,85 @@ namespace MysticQt // find the dialog that goes with the given button - uint32 DialogStack::FindDialog(QPushButton* pushButton) + size_t DialogStack::FindDialog(QPushButton* pushButton) { - const uint32 numDialogs = mDialogs.size(); - for (uint32 i = 0; i < numDialogs; ++i) + const auto foundDialog = AZStd::find_if(begin(mDialogs), end(mDialogs), [pushButton](const Dialog& dialog) { - if (mDialogs[i].mButton == pushButton) - { - return i; - } - } - return MCORE_INVALIDINDEX32; + return dialog.mButton == pushButton; + }); + return foundDialog != end(mDialogs) ? AZStd::distance(begin(mDialogs), foundDialog) : MCore::InvalidIndex; } // open the dialog void DialogStack::Open(QPushButton* button) { - // find the dialog index - const uint32 dialogIndex = FindDialog(button); - if (dialogIndex == MCORE_INVALIDINDEX32) + const auto dialog = AZStd::find_if(begin(mDialogs), end(mDialogs), [button](const Dialog& dialog) + { + return dialog.mButton == button; + }); + if (dialog == end(mDialogs)) { return; } // show the widget inside the dialog - mDialogs[dialogIndex].mFrame->show(); + dialog->mFrame->show(); // set the previous minimum and maximum height before closed - mDialogs[dialogIndex].mDialogWidget->setMinimumHeight(mDialogs[dialogIndex].mMinimumHeightBeforeClose); - mDialogs[dialogIndex].mDialogWidget->setMaximumHeight(mDialogs[dialogIndex].mMaximumHeightBeforeClose); + dialog->mDialogWidget->setMinimumHeight(dialog->mMinimumHeightBeforeClose); + dialog->mDialogWidget->setMaximumHeight(dialog->mMaximumHeightBeforeClose); // change the stylesheet and the icon button->setStyleSheet(""); button->setIcon(GetMysticQt()->FindIcon("Images/Icons/ArrowDownGray.png")); // more space used by the splitter when the dialog is open - if (dialogIndex < (mDialogs.size() - 1)) + if (dialog != mDialogs.end() - 1) { - mDialogs[dialogIndex].mSplitter->handle(1)->setFixedHeight(4); - mDialogs[dialogIndex].mSplitter->setStyleSheet("QSplitter::handle{ height: 4px; background: transparent; }"); + dialog->mSplitter->handle(1)->setFixedHeight(4); + dialog->mSplitter->setStyleSheet("QSplitter::handle{ height: 4px; background: transparent; }"); } // enable the splitter - if (dialogIndex < (mDialogs.size() - 1)) + if (dialog != mDialogs.end() - 1) { - mDialogs[dialogIndex].mSplitter->handle(1)->setEnabled(true); + dialog->mSplitter->handle(1)->setEnabled(true); } // maximize the size if it's needed if (mDialogs.size() > 1) { - if (mDialogs[dialogIndex].mMaximizeSize) + if (dialog->mMaximizeSize) { // special case if it's the first dialog - if (dialogIndex == 0) + if (dialog == mDialogs.begin()) { // if it's the first dialog and stretching is enabled, it expand to the max, all others expand to the min - if (mDialogs[dialogIndex].mStretchWhenMaximize == false && mDialogs[dialogIndex + 1].mMaximizeSize && mDialogs[dialogIndex + 1].mFrame->isHidden() == false) + if (dialog->mStretchWhenMaximize == false && (dialog + 1)->mMaximizeSize && (dialog + 1)->mFrame->isHidden() == false) { - static_cast(mDialogs[dialogIndex].mSplitter)->MoveFirstSplitterToMin(); + static_cast(dialog->mSplitter)->MoveFirstSplitterToMin(); } else { - static_cast(mDialogs[dialogIndex].mSplitter)->MoveFirstSplitterToMax(); + static_cast(dialog->mSplitter)->MoveFirstSplitterToMax(); } } else // not the first dialog { // set the previous dialog to the min to have this dialog expanded to the top - if (mDialogs[dialogIndex - 1].mFrame->isHidden() || mDialogs[dialogIndex - 1].mMaximizeSize == false || (mDialogs[dialogIndex - 1].mMaximizeSize && mDialogs[dialogIndex - 1].mStretchWhenMaximize == false)) + if ((dialog - 1)->mFrame->isHidden() || (dialog - 1)->mMaximizeSize == false || ((dialog - 1)->mMaximizeSize && (dialog - 1)->mStretchWhenMaximize == false)) { - static_cast(mDialogs[dialogIndex - 1].mSplitter)->MoveFirstSplitterToMin(); + static_cast((dialog - 1)->mSplitter)->MoveFirstSplitterToMin(); } // special case if it's not the last dialog - if (dialogIndex < (mDialogs.size() - 1)) + if (dialog != mDialogs.end() - 1) { // if the next dialog is closed, it's needed to expand to the max too - if (mDialogs[dialogIndex + 1].mFrame->isHidden()) + if ((dialog + 1)->mFrame->isHidden()) { - static_cast(mDialogs[dialogIndex].mSplitter)->MoveFirstSplitterToMax(); + static_cast(dialog->mSplitter)->MoveFirstSplitterToMax(); } } } @@ -444,67 +439,58 @@ namespace MysticQt // close the dialog void DialogStack::Close(QPushButton* button) { - // find the dialog index - const uint32 dialogIndex = FindDialog(button); - if (dialogIndex == MCORE_INVALIDINDEX32) + const auto dialog = AZStd::find_if(begin(mDialogs), end(mDialogs), [button](const Dialog& dialog) + { + return dialog.mButton == button; + }); + if (dialog == end(mDialogs)) { return; } // only closable dialog can be closed - if (mDialogs[dialogIndex].mClosable == false) + if (dialog->mClosable == false) { return; } // keep the min and max height before close - mDialogs[dialogIndex].mMinimumHeightBeforeClose = mDialogs[dialogIndex].mDialogWidget->minimumHeight(); - mDialogs[dialogIndex].mMaximumHeightBeforeClose = mDialogs[dialogIndex].mDialogWidget->maximumHeight(); + dialog->mMinimumHeightBeforeClose = dialog->mDialogWidget->minimumHeight(); + dialog->mMaximumHeightBeforeClose = dialog->mDialogWidget->maximumHeight(); // hide the widget inside the dialog - mDialogs[dialogIndex].mFrame->hide(); + dialog->mFrame->hide(); // set the widget to fixed size to not have it possible to resize - mDialogs[dialogIndex].mDialogWidget->setMinimumHeight(mDialogs[dialogIndex].mButton->height()); - mDialogs[dialogIndex].mDialogWidget->setMaximumHeight(mDialogs[dialogIndex].mButton->height()); + dialog->mDialogWidget->setMinimumHeight(dialog->mButton->height()); + dialog->mDialogWidget->setMaximumHeight(dialog->mButton->height()); // change the stylesheet and the icon button->setStyleSheet("border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border: 1px solid rgb(40,40,40);"); // TODO: link to the real style sheets button->setIcon(GetMysticQt()->FindIcon("Images/Icons/ArrowRightGray.png")); // less space used by the splitter when the dialog is closed - if (dialogIndex < (mDialogs.size() - 1)) + if (dialog < mDialogs.end() - 1) { - mDialogs[dialogIndex].mSplitter->handle(1)->setFixedHeight(1); - mDialogs[dialogIndex].mSplitter->setStyleSheet("QSplitter::handle{ height: 1px; background: transparent; }"); - } - - // disable the splitter - if (dialogIndex < (mDialogs.size() - 1)) - { - mDialogs[dialogIndex].mSplitter->handle(1)->setDisabled(true); - } - - // set the first splitter to the min if needed - if (dialogIndex < (mDialogs.size() - 1)) - { - static_cast(mDialogs[dialogIndex].mSplitter)->MoveFirstSplitterToMin(); + dialog->mSplitter->handle(1)->setFixedHeight(1); + dialog->mSplitter->setStyleSheet("QSplitter::handle{ height: 1px; background: transparent; }"); + dialog->mSplitter->handle(1)->setDisabled(true); + static_cast(dialog->mSplitter)->MoveFirstSplitterToMin(); } // maximize the first needed to avoid empty space bool findPreviousMaximizedDialogNeeded = true; - const uint32 numDialogs = mDialogs.size(); - for (uint32 i = dialogIndex + 1; i < numDialogs; ++i) + for (auto curDialog = dialog + 1; curDialog != mDialogs.end(); ++curDialog) { - if (mDialogs[i].mMaximizeSize && mDialogs[i].mFrame->isHidden() == false) + if (curDialog->mMaximizeSize && curDialog->mFrame->isHidden() == false) { - if (i < (numDialogs - 1) && mDialogs[i + 1].mFrame->isHidden()) + if (curDialog != (mDialogs.end() - 1) && (curDialog + 1)->mFrame->isHidden()) { - static_cast(mDialogs[i].mSplitter)->MoveFirstSplitterToMax(); + static_cast(curDialog->mSplitter)->MoveFirstSplitterToMax(); } else { - static_cast(mDialogs[i - 1].mSplitter)->MoveFirstSplitterToMin(); + static_cast((curDialog - 1)->mSplitter)->MoveFirstSplitterToMin(); } findPreviousMaximizedDialogNeeded = false; break; @@ -512,11 +498,11 @@ namespace MysticQt } if (findPreviousMaximizedDialogNeeded) { - for (int32 i = dialogIndex - 1; i >= 0; --i) + for (auto curDialog = AZStd::make_reverse_iterator(dialog) + 1; curDialog != mDialogs.rend(); ++curDialog) { - if (mDialogs[i].mMaximizeSize && mDialogs[i].mFrame->isHidden() == false) + if (curDialog->mMaximizeSize && curDialog->mFrame->isHidden() == false) { - static_cast(mDialogs[i].mSplitter)->MoveFirstSplitterToMax(); + static_cast(curDialog->mSplitter)->MoveFirstSplitterToMax(); break; } } @@ -620,16 +606,15 @@ namespace MysticQt QScrollArea::resizeEvent(event); // maximize the first dialog needed - const uint32 numDialogs = mDialogs.size(); - const int32 lastDialogIndex = static_cast(numDialogs) - 1; - for (int32 i = lastDialogIndex; i >= 0; --i) + if (mDialogs.empty() || mDialogs.size() == 1) { - if (mDialogs[i].mMaximizeSize && mDialogs[i].mFrame->isHidden() == false) + return; + } + for (auto dialog = mDialogs.rbegin() + 1; dialog != mDialogs.rend(); ++dialog) + { + if (dialog->mMaximizeSize && dialog->mFrame->isHidden() == false) { - if (i < lastDialogIndex) - { - static_cast(mDialogs[i].mSplitter)->MoveFirstSplitterToMax(); - } + static_cast(dialog->mSplitter)->MoveFirstSplitterToMax(); break; } } @@ -639,54 +624,54 @@ namespace MysticQt // replace an internal widget void DialogStack::ReplaceWidget(QWidget* oldWidget, QWidget* newWidget) { - for (uint32 i = 0; i < mDialogs.size(); ++i) + for (auto dialog = mDialogs.begin(); dialog != mDialogs.end(); ++dialog) { // go next if the widget is not the same - if (mDialogs[i].mWidget != oldWidget) + if (dialog->mWidget != oldWidget) { continue; } // replace the widget - mDialogs[i].mFrame->layout()->replaceWidget(oldWidget, newWidget); - mDialogs[i].mWidget = newWidget; + dialog->mFrame->layout()->replaceWidget(oldWidget, newWidget); + dialog->mWidget = newWidget; // adjust size of the new widget newWidget->adjustSize(); // set the constraints - if (mDialogs[i].mMaximizeSize == false) + if (dialog->mMaximizeSize == false) { // get margins - const QMargins frameMargins = mDialogs[i].mLayout->contentsMargins(); - const QMargins dialogMargins = mDialogs[i].mDialogLayout->contentsMargins(); + const QMargins frameMargins = dialog->mLayout->contentsMargins(); + const QMargins dialogMargins = dialog->mDialogLayout->contentsMargins(); const int frameMarginTopBottom = frameMargins.top() + frameMargins.bottom(); const int dialogMarginTopBottom = dialogMargins.top() + dialogMargins.bottom(); const int allMarginsTopBottom = frameMarginTopBottom + dialogMarginTopBottom; // set the frame height - mDialogs[i].mFrame->setFixedHeight(newWidget->height() + frameMarginTopBottom); + dialog->mFrame->setFixedHeight(newWidget->height() + frameMarginTopBottom); // compute the dialog height - const int dialogHeight = newWidget->height() + allMarginsTopBottom + mDialogs[i].mButton->height(); + const int dialogHeight = newWidget->height() + allMarginsTopBottom + dialog->mButton->height(); // set the maximum height in case the dialog is not closed, if it's closed update the stored height - if (mDialogs[i].mFrame->isHidden() == false) + if (dialog->mFrame->isHidden() == false) { // set the dialog height - mDialogs[i].mDialogWidget->setFixedHeight(dialogHeight); + dialog->mDialogWidget->setFixedHeight(dialogHeight); // set the first splitter to the min if needed - if (i < (mDialogs.size() - 1)) + if (dialog != mDialogs.end() - 1) { - static_cast(mDialogs[i].mSplitter)->MoveFirstSplitterToMin(); + static_cast(dialog->mSplitter)->MoveFirstSplitterToMin(); } } else // dialog closed { // update the minimum and maximum stored height - mDialogs[i].mMinimumHeightBeforeClose = dialogHeight; - mDialogs[i].mMaximumHeightBeforeClose = dialogHeight; + dialog->mMinimumHeightBeforeClose = dialogHeight; + dialog->mMaximumHeightBeforeClose = dialogHeight; } } diff --git a/Gems/EMotionFX/Code/MysticQt/Source/DialogStack.h b/Gems/EMotionFX/Code/MysticQt/Source/DialogStack.h index d5850a8cbf..6bf810b281 100644 --- a/Gems/EMotionFX/Code/MysticQt/Source/DialogStack.h +++ b/Gems/EMotionFX/Code/MysticQt/Source/DialogStack.h @@ -11,7 +11,6 @@ // #if !defined(Q_MOC_RUN) -#include #include "MysticQtConfig.h" #include #include @@ -29,6 +28,8 @@ QT_FORWARD_DECLARE_CLASS(QSplitter) namespace MysticQt { + class DialogStackSplitter; + /** * * @@ -64,8 +65,8 @@ namespace MysticQt QPushButton* mButton = nullptr; QWidget* mFrame = nullptr; QWidget* mWidget = nullptr; - AZStd::unique_ptr mDialogWidget = nullptr; - QSplitter* mSplitter = nullptr; + QWidget* mDialogWidget = nullptr; + DialogStackSplitter* mSplitter = nullptr; bool mClosable = true; bool mMaximizeSize = false; bool mStretchWhenMaximize = false; @@ -76,14 +77,14 @@ namespace MysticQt }; private: - uint32 FindDialog(QPushButton* pushButton); + size_t FindDialog(QPushButton* pushButton); void Open(QPushButton* button); void Close(QPushButton* button); void UpdateScrollBars(); private: - QSplitter* mRootSplitter; - AZStd::vector mDialogs; + DialogStackSplitter* mRootSplitter; + AZStd::vector mDialogs; int32 mPrevMouseX; int32 mPrevMouseY; }; diff --git a/Gems/EMotionFX/Code/MysticQt/Source/KeyboardShortcutManager.cpp b/Gems/EMotionFX/Code/MysticQt/Source/KeyboardShortcutManager.cpp index 8fa5850407..6b381bf9d8 100644 --- a/Gems/EMotionFX/Code/MysticQt/Source/KeyboardShortcutManager.cpp +++ b/Gems/EMotionFX/Code/MysticQt/Source/KeyboardShortcutManager.cpp @@ -163,7 +163,7 @@ namespace MysticQt // iterate through the groups and save all actions for them for (const AZStd::unique_ptr& group : m_groups) { - settings->beginGroup(QString::fromUtf8(group->GetName().data(), static_cast(group->GetName().size()))); + settings->beginGroup(QString::fromUtf8(group->GetName().data(), aznumeric_caster(group->GetName().size()))); // iterate through the actions and save them for (const AZStd::unique_ptr& action : group->GetActions()) diff --git a/Gems/EMotionFX/Code/Source/Editor/ActorJointBrowseEdit.cpp b/Gems/EMotionFX/Code/Source/Editor/ActorJointBrowseEdit.cpp index a5d7a67f51..41253a513e 100644 --- a/Gems/EMotionFX/Code/Source/Editor/ActorJointBrowseEdit.cpp +++ b/Gems/EMotionFX/Code/Source/Editor/ActorJointBrowseEdit.cpp @@ -154,8 +154,8 @@ namespace EMStudio EMotionFX::Actor* actor = selectionList.GetSingleActor(); if (actor) { - const uint32 numActorInstances = EMotionFX::GetActorManager().GetNumActorInstances(); - for (uint32 i = 0; i < numActorInstances; ++i) + const size_t numActorInstances = EMotionFX::GetActorManager().GetNumActorInstances(); + for (size_t i = 0; i < numActorInstances; ++i) { EMotionFX::ActorInstance* actorInstance2 = EMotionFX::GetActorManager().GetActorInstance(i); if (actorInstance2->GetActor() == actor) diff --git a/Gems/EMotionFX/Code/Source/Editor/ColliderContainerWidget.cpp b/Gems/EMotionFX/Code/Source/Editor/ColliderContainerWidget.cpp index d62e82f438..ef76629780 100644 --- a/Gems/EMotionFX/Code/Source/Editor/ColliderContainerWidget.cpp +++ b/Gems/EMotionFX/Code/Source/Editor/ColliderContainerWidget.cpp @@ -553,7 +553,7 @@ namespace EMotionFX for (size_t i = numColliders; i < numAvailableColliderWidgets; ++i) { m_colliderWidgets[i]->hide(); - m_colliderWidgets[i]->Update(nullptr, nullptr, MCORE_INVALIDINDEX32, PhysicsSetup::ColliderConfigType::Unknown, AzPhysics::ShapeColliderPair()); + m_colliderWidgets[i]->Update(nullptr, nullptr, InvalidIndex, PhysicsSetup::ColliderConfigType::Unknown, AzPhysics::ShapeColliderPair()); } } @@ -616,7 +616,7 @@ namespace EMotionFX EMStudio::EMStudioPlugin::RenderInfo* renderInfo, const MCore::RGBAColor& colliderColor) { - const AZ::u32 nodeIndex = node->GetNodeIndex(); + const size_t nodeIndex = node->GetNodeIndex(); MCommon::RenderUtil* renderUtil = renderInfo->mRenderUtil; for (const auto& collider : colliders) @@ -681,11 +681,11 @@ namespace EMotionFX const bool oldLightingEnabled = renderUtil->GetLightingEnabled(); renderUtil->EnableLighting(false); - const AZStd::unordered_set& selectedJointIndices = EMStudio::GetManager()->GetSelectedJointIndices(); + const AZStd::unordered_set& selectedJointIndices = EMStudio::GetManager()->GetSelectedJointIndices(); const ActorManager* actorManager = GetEMotionFX().GetActorManager(); - const AZ::u32 actorInstanceCount = actorManager->GetNumActorInstances(); - for (AZ::u32 i = 0; i < actorInstanceCount; ++i) + const size_t actorInstanceCount = actorManager->GetNumActorInstances(); + for (size_t i = 0; i < actorInstanceCount; ++i) { const ActorInstance* actorInstance = actorManager->GetActorInstance(i); const Actor* actor = actorInstance->GetActor(); diff --git a/Gems/EMotionFX/Code/Source/Editor/Plugins/Ragdoll/RagdollNodeInspectorPlugin.cpp b/Gems/EMotionFX/Code/Source/Editor/Plugins/Ragdoll/RagdollNodeInspectorPlugin.cpp index bda6e68449..93c4e2cb67 100644 --- a/Gems/EMotionFX/Code/Source/Editor/Plugins/Ragdoll/RagdollNodeInspectorPlugin.cpp +++ b/Gems/EMotionFX/Code/Source/Editor/Plugins/Ragdoll/RagdollNodeInspectorPlugin.cpp @@ -436,8 +436,8 @@ namespace EMotionFX const bool oldLightingEnabled = renderUtil->GetLightingEnabled(); renderUtil->EnableLighting(false); - const AZ::u32 actorInstanceCount = GetActorManager().GetNumActorInstances(); - for (AZ::u32 i = 0; i < actorInstanceCount; ++i) + const size_t actorInstanceCount = GetActorManager().GetNumActorInstances(); + for (size_t i = 0; i < actorInstanceCount; ++i) { ActorInstance* actorInstance = GetActorManager().GetActorInstance(i); RenderRagdoll(actorInstance, renderColliders, renderJointLimits, renderPlugin, renderInfo); @@ -451,7 +451,7 @@ namespace EMotionFX { const Actor* actor = actorInstance->GetActor(); const Skeleton* skeleton = actor->GetSkeleton(); - const AZ::u32 numNodes = skeleton->GetNumNodes(); + const size_t numNodes = skeleton->GetNumNodes(); const AZStd::shared_ptr& physicsSetup = actor->GetPhysicsSetup(); const Physics::RagdollConfiguration& ragdollConfig = physicsSetup->GetRagdollConfig(); const AZStd::vector& ragdollNodes = ragdollConfig.m_nodes; @@ -462,12 +462,12 @@ namespace EMotionFX const MCore::RGBAColor defaultColor = renderOptions->GetRagdollColliderColor(); const MCore::RGBAColor selectedColor = renderOptions->GetSelectedRagdollColliderColor(); - const AZStd::unordered_set& selectedJointIndices = EMStudio::GetManager()->GetSelectedJointIndices(); + const AZStd::unordered_set& selectedJointIndices = EMStudio::GetManager()->GetSelectedJointIndices(); - for (AZ::u32 nodeIndex = 0; nodeIndex < numNodes; ++nodeIndex) + for (size_t nodeIndex = 0; nodeIndex < numNodes; ++nodeIndex) { const Node* joint = skeleton->GetNode(nodeIndex); - const AZ::u32 jointIndex = joint->GetNodeIndex(); + const size_t jointIndex = joint->GetNodeIndex(); AZ::Outcome ragdollNodeIndex = AZ::Failure(); if (ragdollInstance) @@ -535,8 +535,8 @@ namespace EMotionFX { const EMStudio::RenderOptions* renderOptions = renderPlugin->GetRenderOptions(); const MCore::RGBAColor violatedColor = renderOptions->GetViolatedJointLimitColor(); - const AZ::u32 nodeIndex = node->GetNodeIndex(); - const AZ::u32 parentNodeIndex = parentNode->GetNodeIndex(); + const size_t nodeIndex = node->GetNodeIndex(); + const size_t parentNodeIndex = parentNode->GetNodeIndex(); const Transform& actorInstanceWorldTransform = actorInstance->GetWorldSpaceTransform(); const Pose* currentPose = actorInstance->GetTransformData()->GetCurrentPose(); const AZ::Quaternion& parentOrientation = currentPose->GetModelSpaceTransform(parentNodeIndex).mRotation; diff --git a/Gems/EMotionFX/Code/Source/Editor/Plugins/SimulatedObject/SimulatedObjectWidget.cpp b/Gems/EMotionFX/Code/Source/Editor/Plugins/SimulatedObject/SimulatedObjectWidget.cpp index aa222c0405..bd57e24d08 100644 --- a/Gems/EMotionFX/Code/Source/Editor/Plugins/SimulatedObject/SimulatedObjectWidget.cpp +++ b/Gems/EMotionFX/Code/Source/Editor/Plugins/SimulatedObject/SimulatedObjectWidget.cpp @@ -84,7 +84,7 @@ namespace EMotionFX } else { - AZStd::unordered_set selectedJointIndices; + AZStd::unordered_set selectedJointIndices; for (const QModelIndex& index : selectedIndices) { const SimulatedJoint* joint = index.data(SimulatedObjectModel::ROLE_JOINT_PTR).value(); @@ -451,7 +451,7 @@ namespace EMotionFX { CommandAddSimulatedJoints* addSimulatedJointsCommand = static_cast(command); const size_t objectIndex = addSimulatedJointsCommand->GetObjectIndex(); - const AZStd::vector& jointIndices = addSimulatedJointsCommand->GetJointIndices(); + const AZStd::vector& jointIndices = addSimulatedJointsCommand->GetJointIndices(); SimulatedObjectWidget* simulatedObjectPlugin = static_cast(EMStudio::GetPluginManager()->FindActivePlugin(SimulatedObjectWidget::CLASS_ID)); if (simulatedObjectPlugin) @@ -491,13 +491,13 @@ namespace EMotionFX } const bool renderSimulatedJoints = activeViewWidget->GetRenderFlag(EMStudio::RenderViewWidget::RENDER_SIMULATEJOINTS); - const AZStd::unordered_set& selectedJointIndices = EMStudio::GetManager()->GetSelectedJointIndices(); + const AZStd::unordered_set& selectedJointIndices = EMStudio::GetManager()->GetSelectedJointIndices(); if (renderSimulatedJoints && !selectedJointIndices.empty()) { // Render the joint radius. const MCore::RGBAColor defaultColor = renderPlugin->GetRenderOptions()->GetSelectedSimulatedObjectColliderColor(); - const AZ::u32 actorInstanceCount = GetActorManager().GetNumActorInstances(); - for (AZ::u32 actorInstanceIndex = 0; actorInstanceIndex < actorInstanceCount; ++actorInstanceIndex) + const size_t actorInstanceCount = GetActorManager().GetNumActorInstances(); + for (size_t actorInstanceIndex = 0; actorInstanceIndex < actorInstanceCount; ++actorInstanceIndex) { ActorInstance* actorInstance = GetActorManager().GetActorInstance(actorInstanceIndex); const Actor* actor = actorInstance->GetActor(); @@ -511,7 +511,7 @@ namespace EMotionFX for (size_t simulatedJointIndex = 0; simulatedJointIndex < simulatedJointCount; ++simulatedJointIndex) { const SimulatedJoint* simulatedJoint = object->GetSimulatedJoint(simulatedJointIndex); - const AZ::u32 skeletonJointIndex = simulatedJoint->GetSkeletonJointIndex(); + const size_t skeletonJointIndex = simulatedJoint->GetSkeletonJointIndex(); if (selectedJointIndices.find(skeletonJointIndex) != selectedJointIndices.end()) { RenderJointRadius(simulatedJoint, actorInstance, AZ::Color(1.0f, 0.0f, 1.0f, 1.0f)); @@ -547,7 +547,7 @@ namespace EMotionFX return; } - AZ_Assert(joint->GetSkeletonJointIndex() != MCORE_INVALIDINDEX32, "Expected skeletal joint index to be valid."); + AZ_Assert(joint->GetSkeletonJointIndex() != InvalidIndex, "Expected skeletal joint index to be valid."); const EMotionFX::Transform jointTransform = actorInstance->GetTransformData()->GetCurrentPose()->GetWorldSpaceTransform(joint->GetSkeletonJointIndex()); DebugDraw& debugDraw = GetDebugDraw(); diff --git a/Gems/EMotionFX/Code/Source/Editor/SimulatedObjectHelpers.cpp b/Gems/EMotionFX/Code/Source/Editor/SimulatedObjectHelpers.cpp index 75a32444e2..2d87d6b603 100644 --- a/Gems/EMotionFX/Code/Source/Editor/SimulatedObjectHelpers.cpp +++ b/Gems/EMotionFX/Code/Source/Editor/SimulatedObjectHelpers.cpp @@ -45,7 +45,7 @@ namespace EMotionFX } const Actor* actor = modelIndices[0].data(SkeletonModel::ROLE_ACTOR_POINTER).value(); - AZStd::vector jointIndices; + AZStd::vector jointIndices; for (const QModelIndex& selectedIndex : modelIndices) { @@ -68,7 +68,7 @@ namespace EMotionFX void SimulatedObjectHelpers::RemoveSimulatedJoints(const QModelIndexList& modelIndices, bool removeChildren) { - AZStd::unordered_map>> objectToSkeletonJointIndices; + AZStd::unordered_map>> objectToSkeletonJointIndices; for (const QModelIndex& index : modelIndices) { @@ -80,7 +80,7 @@ namespace EMotionFX } const Actor* actor = index.data(SimulatedObjectModel::ROLE_ACTOR_PTR).value(); const size_t objectIndex = static_cast(index.data(SimulatedObjectModel::ROLE_OBJECT_INDEX).toInt()); - const AZ::u32 jointIndex = index.data(SimulatedObjectModel::ROLE_JOINT_PTR).value()->GetSkeletonJointIndex(); + const size_t jointIndex = index.data(SimulatedObjectModel::ROLE_JOINT_PTR).value()->GetSkeletonJointIndex(); objectToSkeletonJointIndices[objectIndex].first = actor; objectToSkeletonJointIndices[objectIndex].second.emplace_back(jointIndex); } @@ -92,7 +92,7 @@ namespace EMotionFX { const size_t objectIndex = objectIndexAndJointIndices.first; const Actor* actor = objectIndexAndJointIndices.second.first; - const AZStd::vector jointIndices = objectIndexAndJointIndices.second.second; + const AZStd::vector jointIndices = objectIndexAndJointIndices.second.second; CommandSimulatedObjectHelpers::RemoveSimulatedJoints(actor->GetID(), jointIndices, objectIndex, removeChildren, &commandGroup); } diff --git a/Gems/EMotionFX/Code/Source/Editor/SimulatedObjectModel.cpp b/Gems/EMotionFX/Code/Source/Editor/SimulatedObjectModel.cpp index 452ba2798a..f04ca3fede 100644 --- a/Gems/EMotionFX/Code/Source/Editor/SimulatedObjectModel.cpp +++ b/Gems/EMotionFX/Code/Source/Editor/SimulatedObjectModel.cpp @@ -171,7 +171,7 @@ namespace EMotionFX SimulatedJoint* parentJoint = childJoint->FindParentSimulatedJoint(); if (parentJoint) { - return createIndex(parentJoint->CalculateChildIndex(), 0, parentJoint); + return createIndex(aznumeric_caster(parentJoint->CalculateChildIndex()), 0, parentJoint); } else { @@ -377,7 +377,7 @@ namespace EMotionFX return QModelIndex(); } - void SimulatedObjectModel::AddJointsToSelection(QItemSelection& selection, size_t objectIndex, const AZStd::vector& jointIndices) + void SimulatedObjectModel::AddJointsToSelection(QItemSelection& selection, size_t objectIndex, const AZStd::vector& jointIndices) { if (!m_actor || !m_actor->GetSimulatedObjectSetup()) { @@ -392,12 +392,12 @@ namespace EMotionFX return; } - for (AZ::u32 jointIndex : jointIndices) + for (const size_t jointIndex : jointIndices) { SimulatedJoint* joint = object->FindSimulatedJointBySkeletonJointIndex(jointIndex); if (!joint) { - AZ_Warning("EMotionFX", false, "Simulated joint with joint index %d does not exist", jointIndex); + AZ_Warning("EMotionFX", false, "Simulated joint with joint index %zu does not exist", jointIndex); continue; } int row = static_cast(joint->CalculateChildIndex()); diff --git a/Gems/EMotionFX/Code/Source/Editor/SimulatedObjectModel.h b/Gems/EMotionFX/Code/Source/Editor/SimulatedObjectModel.h index 0873086850..46b9b811b3 100644 --- a/Gems/EMotionFX/Code/Source/Editor/SimulatedObjectModel.h +++ b/Gems/EMotionFX/Code/Source/Editor/SimulatedObjectModel.h @@ -75,7 +75,7 @@ namespace EMotionFX QModelIndex GetModelIndexByObjectIndex(size_t objectIndex); QModelIndex FindModelIndex(SimulatedObject* object); - void AddJointsToSelection(QItemSelection& selection, size_t objectIndex, const AZStd::vector& jointIndices); + void AddJointsToSelection(QItemSelection& selection, size_t objectIndex, const AZStd::vector& jointIndices); private: // Command callbacks. diff --git a/Gems/EMotionFX/Code/Source/Editor/SkeletonModel.cpp b/Gems/EMotionFX/Code/Source/Editor/SkeletonModel.cpp index 95e08eab77..49f68bcbc5 100644 --- a/Gems/EMotionFX/Code/Source/Editor/SkeletonModel.cpp +++ b/Gems/EMotionFX/Code/Source/Editor/SkeletonModel.cpp @@ -123,7 +123,7 @@ namespace EMotionFX return QModelIndex(); } - const AZ::u32 childNodeIndex = parentNode->GetChildIndex(row); + const size_t childNodeIndex = parentNode->GetChildIndex(row); Node* childNode = m_skeleton->GetNode(childNodeIndex); return createIndex(row, column, childNode); } @@ -135,7 +135,7 @@ namespace EMotionFX return QModelIndex(); } - const AZ::u32 rootNodeIndex = m_skeleton->GetRootNodeIndex(row); + const size_t rootNodeIndex = m_skeleton->GetRootNodeIndex(row); Node* rootNode = m_skeleton->GetNode(rootNodeIndex); return createIndex(row, column, rootNode); } @@ -157,8 +157,8 @@ namespace EMotionFX Node* grandParentNode = parentNode->GetParentNode(); if (grandParentNode) { - const AZ::u32 numChildNodes = grandParentNode->GetNumChildNodes(); - for (AZ::u32 i = 0; i < numChildNodes; ++i) + const int numChildNodes = aznumeric_caster(grandParentNode->GetNumChildNodes()); + for (int i = 0; i < numChildNodes; ++i) { const Node* grandParentChildNode = m_skeleton->GetNode(grandParentNode->GetChildIndex(i)); if (grandParentChildNode == parentNode) @@ -169,8 +169,8 @@ namespace EMotionFX } else { - const AZ::u32 numRootNodes = m_skeleton->GetNumRootNodes(); - for (AZ::u32 i = 0; i < numRootNodes; ++i) + const int numRootNodes = aznumeric_caster(m_skeleton->GetNumRootNodes()); + for (int i = 0; i < numRootNodes; ++i) { const Node* rootNode = m_skeleton->GetNode(m_skeleton->GetRootNodeIndex(i)); if (rootNode == parentNode) @@ -234,7 +234,7 @@ namespace EMotionFX Node* node = static_cast(index.internalPointer()); AZ_Assert(node, "Expected valid node pointer."); - const AZ::u32 nodeIndex = node->GetNodeIndex(); + const size_t nodeIndex = node->GetNodeIndex(); const NodeInfo& nodeInfo = m_nodeInfos[nodeIndex]; switch (role) @@ -389,7 +389,7 @@ namespace EMotionFX break; } case ROLE_NODE_INDEX: - return nodeIndex; + return qulonglong(nodeIndex); case ROLE_POINTER: return QVariant::fromValue(node); case ROLE_ACTOR_POINTER: @@ -474,7 +474,7 @@ namespace EMotionFX Node* node = static_cast(index.internalPointer()); AZ_Assert(node, "Expected valid node pointer."); - const AZ::u32 nodeIndex = node->GetNodeIndex(); + const size_t nodeIndex = node->GetNodeIndex(); const NodeInfo& nodeInfo = m_nodeInfos[nodeIndex]; if (nodeInfo.m_checkable) @@ -496,7 +496,7 @@ namespace EMotionFX const Node* node = static_cast(index.internalPointer()); AZ_Assert(node, "Expected valid node pointer."); - const AZ::u32 nodeIndex = node->GetNodeIndex(); + const size_t nodeIndex = node->GetNodeIndex(); NodeInfo& nodeInfo = m_nodeInfos[nodeIndex]; switch (role) @@ -525,8 +525,8 @@ namespace EMotionFX Node* parentNode = node->GetParentNode(); if (parentNode) { - const AZ::u32 numChildNodes = parentNode->GetNumChildNodes(); - for (AZ::u32 i = 0; i < numChildNodes; ++i) + const int numChildNodes = aznumeric_caster(parentNode->GetNumChildNodes()); + for (int i = 0; i < numChildNodes; ++i) { const Node* childNode = m_skeleton->GetNode(parentNode->GetChildIndex(i)); if (childNode == node) @@ -536,8 +536,8 @@ namespace EMotionFX } } - const AZ::u32 numRootNodes = m_skeleton->GetNumRootNodes(); - for (AZ::u32 i = 0; i < numRootNodes; ++i) + const int numRootNodes = aznumeric_caster(m_skeleton->GetNumRootNodes()); + for (int i = 0; i < numRootNodes; ++i) { const Node* rootNode = m_skeleton->GetNode(m_skeleton->GetRootNodeIndex(i)); if (rootNode == node) @@ -552,8 +552,8 @@ namespace EMotionFX QModelIndexList SkeletonModel::GetModelIndicesForFullSkeleton() const { QModelIndexList result; - const AZ::u32 jointCount = m_skeleton->GetNumNodes(); - for (AZ::u32 i = 0; i < jointCount; ++i) + const size_t jointCount = m_skeleton->GetNumNodes(); + for (size_t i = 0; i < jointCount; ++i) { Node* joint = m_skeleton->GetNode(i); result.push_back(GetModelIndex(joint)); @@ -585,8 +585,8 @@ namespace EMotionFX void SkeletonModel::ForEach(const AZStd::function& func) { QModelIndex modelIndex; - const AZ::u32 jointCount = m_skeleton->GetNumNodes(); - for (AZ::u32 i = 0; i < jointCount; ++i) + const size_t jointCount = m_skeleton->GetNumNodes(); + for (size_t i = 0; i < jointCount; ++i) { Node* joint = m_skeleton->GetNode(i); modelIndex = GetModelIndex(joint); diff --git a/Gems/EMotionFX/Code/Source/Integration/Components/ActorComponent.h b/Gems/EMotionFX/Code/Source/Integration/Components/ActorComponent.h index 2bf85692be..f834456e45 100644 --- a/Gems/EMotionFX/Code/Source/Integration/Components/ActorComponent.h +++ b/Gems/EMotionFX/Code/Source/Integration/Components/ActorComponent.h @@ -80,13 +80,13 @@ namespace EMotionFX AZ::Data::Asset m_actorAsset{AZ::Data::AssetLoadBehavior::NoLoad}; ///< Selected actor asset. ActorAsset::MaterialList m_materialPerLOD{}; ///< Material assignment per LOD. AZ::EntityId m_attachmentTarget{}; ///< Target entity this actor should attach to. - AZ::u32 m_attachmentJointIndex = MCORE_INVALIDINDEX32; ///< Index of joint on target skeleton for actor attachments. + size_t m_attachmentJointIndex = InvalidIndex; ///< Index of joint on target skeleton for actor attachments. AttachmentType m_attachmentType = AttachmentType::None; ///< Type of attachment. bool m_renderSkeleton = false; ///< Toggles debug rendering of the skeleton. bool m_renderCharacter = true; ///< Toggles rendering of the character. bool m_renderBounds = false; ///< Toggles rendering of the character bounds used for visibility testing. SkinningMethod m_skinningMethod = SkinningMethod::DualQuat; ///< The skinning method for this actor - AZ::u32 m_lodLevel = 0; + size_t m_lodLevel = 0; // Force updating the joints when it is out of camera view. By // default, joints level update (beside the root joint) on diff --git a/Gems/EMotionFX/Code/Source/Integration/Components/SimpleLODComponent.cpp b/Gems/EMotionFX/Code/Source/Integration/Components/SimpleLODComponent.cpp index 356f5f934a..5db0fae842 100644 --- a/Gems/EMotionFX/Code/Source/Integration/Components/SimpleLODComponent.cpp +++ b/Gems/EMotionFX/Code/Source/Integration/Components/SimpleLODComponent.cpp @@ -71,13 +71,13 @@ namespace EMotionFX m_lodDistances.clear(); } - void SimpleLODComponent::Configuration::GenerateDefaultValue(AZ::u32 numLODs) + void SimpleLODComponent::Configuration::GenerateDefaultValue(size_t numLODs) { if (numLODs != m_lodDistances.size()) { // Generate the default LOD (max) distance to 10, 20, 30.... m_lodDistances.resize(numLODs); - for (AZ::u32 i = 0; i < numLODs; ++i) + for (size_t i = 0; i < numLODs; ++i) { m_lodDistances[i] = i * 10.0f + 10.0f; } @@ -86,12 +86,9 @@ namespace EMotionFX if (numLODs != m_lodSampleRates.size()) { // Generate the default LOD Sample Rate to 140, 60, 45, 25, 15, 10 - const float defaultSampleRate[] = {140.0f, 60.0f, 45.0f, 25.0f, 15.0f, 10.0f}; + constexpr AZStd::array defaultSampleRate {140.0f, 60.0f, 45.0f, 25.0f, 15.0f, 10.0f}; m_lodSampleRates.resize(numLODs); - for (AZ::u32 i = 0; i < numLODs; ++i) - { - m_lodSampleRates[i] = defaultSampleRate[i]; - } + AZStd::copy(begin(defaultSampleRate), end(defaultSampleRate), begin(m_lodSampleRates)); } } @@ -171,7 +168,7 @@ namespace EMotionFX UpdateLodLevelByDistance(m_actorInstance, m_configuration, GetEntityId()); } - AZ::u32 SimpleLODComponent::GetLodByDistance(const AZStd::vector& distances, float distance) + size_t SimpleLODComponent::GetLodByDistance(const AZStd::vector& distances, float distance) { const size_t max = distances.size(); for (size_t i = 0; i < max; ++i) @@ -179,11 +176,11 @@ namespace EMotionFX const float rDistance = distances[i]; if (distance < rDistance) { - return static_cast(i); + return i; } } - return static_cast(max - 1); + return max - 1; } void SimpleLODComponent::UpdateLodLevelByDistance(EMotionFX::ActorInstance * actorInstance, const Configuration& configuration, AZ::EntityId entityId) @@ -204,7 +201,7 @@ namespace EMotionFX AZ::RPI::ViewportContextPtr defaultViewportContext = viewportContextManager->GetViewportContextByName(viewportContextManager->GetDefaultViewportContextName()); const float distance = worldPos.GetDistance(defaultViewportContext->GetCameraTransform().GetTranslation()); - const AZ::u32 lodByDistance = GetLodByDistance(configuration.m_lodDistances, distance); + const size_t lodByDistance = GetLodByDistance(configuration.m_lodDistances, distance); actorInstance->SetLODLevel(lodByDistance); if (configuration.m_enableLodSampling) diff --git a/Gems/EMotionFX/Code/Source/Integration/Components/SimpleLODComponent.h b/Gems/EMotionFX/Code/Source/Integration/Components/SimpleLODComponent.h index d8ccb9cd06..96bebdc660 100644 --- a/Gems/EMotionFX/Code/Source/Integration/Components/SimpleLODComponent.h +++ b/Gems/EMotionFX/Code/Source/Integration/Components/SimpleLODComponent.h @@ -44,7 +44,7 @@ namespace EMotionFX void Reset(); // Generate the default value based on LOD level. - void GenerateDefaultValue(AZ::u32 numLODs); + void GenerateDefaultValue(size_t numLODs); bool GetEnableLodSampling(); static void Reflect(AZ::ReflectContext* context); @@ -88,7 +88,7 @@ namespace EMotionFX // AZ::TickBus::Handler void OnTick(float deltaTime, AZ::ScriptTimePoint time) override; - static AZ::u32 GetLodByDistance(const AZStd::vector& distances, float distance); + static size_t GetLodByDistance(const AZStd::vector& distances, float distance); static void UpdateLodLevelByDistance(EMotionFX::ActorInstance* actorInstance, const Configuration& configuration, AZ::EntityId entityId); Configuration m_configuration; // Component configuration. diff --git a/Gems/EMotionFX/Code/Source/Integration/Editor/Components/EditorActorComponent.cpp b/Gems/EMotionFX/Code/Source/Integration/Editor/Components/EditorActorComponent.cpp index 160cbe8ee4..485b56c077 100644 --- a/Gems/EMotionFX/Code/Source/Integration/Editor/Components/EditorActorComponent.cpp +++ b/Gems/EMotionFX/Code/Source/Integration/Editor/Components/EditorActorComponent.cpp @@ -680,11 +680,11 @@ namespace EMotionFX bool isHit = false; // Iterate through the meshes in the actor, looking for the closest hit - const AZ::u32 lodLevel = m_actorInstance->GetLODLevel(); + const size_t lodLevel = m_actorInstance->GetLODLevel(); Actor* actor = m_actorAsset.Get()->GetActor(); - const uint32 numNodes = actor->GetNumNodes(); - const uint32 numLods = actor->GetNumLODLevels(); - for (uint32 nodeIndex = 0; nodeIndex < numNodes; ++nodeIndex) + const size_t numNodes = actor->GetNumNodes(); + const size_t numLods = actor->GetNumLODLevels(); + for (size_t nodeIndex = 0; nodeIndex < numNodes; ++nodeIndex) { Mesh* mesh = actor->GetMesh(lodLevel, nodeIndex); if (!mesh || mesh->GetIsCollisionMesh()) @@ -803,7 +803,7 @@ namespace EMotionFX Node* node = jointName ? targetActorInstance->GetActor()->GetSkeleton()->FindNodeByName(jointName) : targetActorInstance->GetActor()->GetSkeleton()->GetNode(0); if (node) { - const AZ::u32 jointIndex = node->GetNodeIndex(); + const size_t jointIndex = node->GetNodeIndex(); Attachment* attachment = AttachmentNode::Create(targetActorInstance, jointIndex, m_actorInstance.get(), true /* Managed externally, by this component. */); targetActorInstance->AddAttachment(attachment); } diff --git a/Gems/EMotionFX/Code/Source/Integration/Editor/Components/EditorActorComponent.h b/Gems/EMotionFX/Code/Source/Integration/Editor/Components/EditorActorComponent.h index 26df2b6e47..10c75860cf 100644 --- a/Gems/EMotionFX/Code/Source/Integration/Editor/Components/EditorActorComponent.h +++ b/Gems/EMotionFX/Code/Source/Integration/Editor/Components/EditorActorComponent.h @@ -158,8 +158,8 @@ namespace EMotionFX AttachmentType m_attachmentType; ///< Attachment type. AZ::EntityId m_attachmentTarget; ///< Target entity to attach to, if any. AZStd::string m_attachmentJointName; ///< Joint name on target to which to attach (if ActorAttachment). - AZ::u32 m_attachmentJointIndex; - AZ::u32 m_lodLevel; + size_t m_attachmentJointIndex; + size_t m_lodLevel; ActorComponent::BoundingBoxConfiguration m_bboxConfig; bool m_forceUpdateJointsOOV = false; // \todo attachmentTarget node nr diff --git a/Gems/EMotionFX/Code/Source/Integration/Editor/Components/EditorSimpleLODComponent.cpp b/Gems/EMotionFX/Code/Source/Integration/Editor/Components/EditorSimpleLODComponent.cpp index 030ca42ca1..384caf074b 100644 --- a/Gems/EMotionFX/Code/Source/Integration/Editor/Components/EditorSimpleLODComponent.cpp +++ b/Gems/EMotionFX/Code/Source/Integration/Editor/Components/EditorSimpleLODComponent.cpp @@ -88,7 +88,7 @@ namespace EMotionFX if (actorInstance) { m_actorInstance = actorInstance.get(); - const AZ::u32 numLODs = m_actorInstance->GetActor()->GetNumLODLevels(); + const size_t numLODs = m_actorInstance->GetActor()->GetNumLODLevels(); m_configuration.GenerateDefaultValue(numLODs); } else @@ -111,7 +111,7 @@ namespace EMotionFX if (m_actorInstance != actorInstance) { m_actorInstance = actorInstance; - const AZ::u32 numLODs = m_actorInstance->GetActor()->GetNumLODLevels(); + const size_t numLODs = m_actorInstance->GetActor()->GetNumLODLevels(); m_configuration.GenerateDefaultValue(numLODs); } } From 0547a1085a35f4952f744a55729cf1b5180465c9 Mon Sep 17 00:00:00 2001 From: Chris Burel Date: Thu, 3 Jun 2021 11:17:12 -0700 Subject: [PATCH 207/803] Add version converter for the game controller settings, since one of its field types has changed Signed-off-by: Chris Burel --- .../AnimGraphGameControllerSettings.cpp | 22 +++++++++++++++++-- .../Source/AnimGraphGameControllerSettings.h | 2 +- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphGameControllerSettings.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphGameControllerSettings.cpp index 6f2d6083a1..970e2e913c 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphGameControllerSettings.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphGameControllerSettings.cpp @@ -6,6 +6,8 @@ * */ +#include +#include #include #include @@ -181,7 +183,7 @@ namespace EMotionFX ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// AnimGraphGameControllerSettings::AnimGraphGameControllerSettings() - : m_activePresetIndex(MCORE_INVALIDINDEX32) + : m_activePresetIndex(InvalidIndex) { } @@ -369,6 +371,22 @@ namespace EMotionFX } + static bool AnimGraphGameControllerSettingsVersionConverter(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& element) + { + if (element.GetVersion() < 2) + { + constexpr AZStd::string_view activePresetIndex{"activePresetIndex"}; + if (AZ::SerializeContext::DataElementNode* presetIndexElement = element.FindSubElement(AZ::Crc32(activePresetIndex))) + { + uint32 value; + presetIndexElement->GetData(value); + presetIndexElement->Convert(context); + presetIndexElement->SetData(context, static_cast(value)); + } + } + return true; + } + void AnimGraphGameControllerSettings::Reflect(AZ::ReflectContext* context) { ParameterInfo::Reflect(context); @@ -383,7 +401,7 @@ namespace EMotionFX } serializeContext->Class() - ->Version(1) + ->Version(2, &AnimGraphGameControllerSettingsVersionConverter) ->Field("activePresetIndex", &AnimGraphGameControllerSettings::m_activePresetIndex) ->Field("presets", &AnimGraphGameControllerSettings::m_presets) ; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphGameControllerSettings.h b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphGameControllerSettings.h index f543246599..d36a448be4 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphGameControllerSettings.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphGameControllerSettings.h @@ -164,6 +164,6 @@ namespace EMotionFX private: AZStd::vector m_presets; - size_t m_activePresetIndex; + AZ::u64 m_activePresetIndex; }; } // namespace EMotionFX From 56025070247d4c0f7bb08379e19c6ab059bea0b3 Mon Sep 17 00:00:00 2001 From: Chris Burel Date: Fri, 25 Jun 2021 17:48:11 -0700 Subject: [PATCH 208/803] Fix EMotionFX Editor tests to compile with `-Wshorten-64-to-32` Signed-off-by: Chris Burel --- .../Code/Tests/MorphTargetPipelineTests.cpp | 8 ++++---- .../AnimGraph/CanEditAnimGraphNode.cpp | 2 +- .../Code/Tests/UI/AnimGraphUIFixture.cpp | 4 ++-- .../Tests/UI/CanAddMotionToAnimGraphNode.cpp | 4 ++-- .../Code/Tests/UI/CanAddMotionToMotionSet.cpp | 8 ++++---- .../Code/Tests/UI/CanAddReferenceNode.cpp | 2 +- .../Code/Tests/UI/CanEditParameters.cpp | 2 +- .../Code/Tests/UI/CanMorphManyShapes.cpp | 2 +- .../Tests/UI/CanRemoveMotionFromMotionSet.cpp | 16 ++++++++-------- Gems/EMotionFX/Code/Tests/UI/CanUseEditMenu.cpp | 6 +++--- Gems/EMotionFX/Code/Tests/UI/CanUseViewMenu.cpp | 2 +- Gems/EMotionFX/Code/Tests/UI/UIFixture.cpp | 4 ++-- 12 files changed, 30 insertions(+), 30 deletions(-) diff --git a/Gems/EMotionFX/Code/Tests/MorphTargetPipelineTests.cpp b/Gems/EMotionFX/Code/Tests/MorphTargetPipelineTests.cpp index c8aabc636a..0df39af8c5 100644 --- a/Gems/EMotionFX/Code/Tests/MorphTargetPipelineTests.cpp +++ b/Gems/EMotionFX/Code/Tests/MorphTargetPipelineTests.cpp @@ -151,8 +151,8 @@ namespace EMotionFX Skeleton* skeleton = actor->GetSkeleton(); EMotionFX::Mesh* mesh = nullptr; - const uint32 numNodes = skeleton->GetNumNodes(); - for (uint32 nodeNum = 0; nodeNum < numNodes; ++nodeNum) + const size_t numNodes = skeleton->GetNumNodes(); + for (size_t nodeNum = 0; nodeNum < numNodes; ++nodeNum) { if (mesh) { @@ -223,8 +223,8 @@ namespace EMotionFX return; } - const uint32 numMorphTargets = morphSetup->GetNumMorphTargets(); - for (uint32 morphTargetIndex = 0; morphTargetIndex < numMorphTargets; ++morphTargetIndex) + const size_t numMorphTargets = morphSetup->GetNumMorphTargets(); + for (size_t morphTargetIndex = 0; morphTargetIndex < numMorphTargets; ++morphTargetIndex) { const MorphTarget* morphTarget = morphSetup->GetMorphTarget(morphTargetIndex); EXPECT_STREQ(morphTarget->GetName(), selectedMorphTargets[morphTargetIndex].c_str()) << "Morph target's name is incorrect"; diff --git a/Gems/EMotionFX/Code/Tests/ProvidesUI/AnimGraph/CanEditAnimGraphNode.cpp b/Gems/EMotionFX/Code/Tests/ProvidesUI/AnimGraph/CanEditAnimGraphNode.cpp index 08b702abb4..fe1204dd3b 100644 --- a/Gems/EMotionFX/Code/Tests/ProvidesUI/AnimGraph/CanEditAnimGraphNode.cpp +++ b/Gems/EMotionFX/Code/Tests/ProvidesUI/AnimGraph/CanEditAnimGraphNode.cpp @@ -75,7 +75,7 @@ namespace EMotionFX ASSERT_TRUE(activeAnimGraph) << "An anim graph was not created with command: " << createAnimGraphCommand.c_str(); // Create a new AnimGraph Node - const AZ::u32 nodeCount = activeAnimGraph->GetNumNodes(); + const size_t nodeCount = activeAnimGraph->GetNumNodes(); EXPECT_TRUE(CommandSystem::GetCommandManager()->ExecuteCommand(createNodeCommand, result)) << result.c_str(); EXPECT_EQ(activeAnimGraph->GetNumNodes(), nodeCount + 1) << "Expected one more anim graph node after running command: " << createNodeCommand.c_str(); } diff --git a/Gems/EMotionFX/Code/Tests/UI/AnimGraphUIFixture.cpp b/Gems/EMotionFX/Code/Tests/UI/AnimGraphUIFixture.cpp index 33c3d0054f..d32c34ea62 100644 --- a/Gems/EMotionFX/Code/Tests/UI/AnimGraphUIFixture.cpp +++ b/Gems/EMotionFX/Code/Tests/UI/AnimGraphUIFixture.cpp @@ -82,7 +82,7 @@ namespace EMotionFX const AnimGraph* targetAnimGraph = (animGraph ? animGraph : m_animGraphPlugin->GetActiveAnimGraph()); //AnimGraph to add Node to const AZStd::string cmd = "AnimGraphCreateNode AnimGraphID " + AZStd::to_string(targetAnimGraph->GetID()) + " -type " + type + " " + args; - AZ::u32 nodeCount = targetAnimGraph->GetNumNodes(); //node count before creating a new node + size_t nodeCount = targetAnimGraph->GetNumNodes(); //node count before creating a new node AZStd::string result; EXPECT_TRUE(CommandSystem::GetCommandManager()->ExecuteCommand(cmd, result)) << result.c_str(); @@ -112,7 +112,7 @@ namespace EMotionFX const EMotionFX::AnimGraphNode* currentNode = GetActiveNodeGraph()->GetModelIndex().data(EMStudio::AnimGraphModel::ROLE_NODE_POINTER).value(); - const int numNodesAfter = currentNode->GetNumChildNodes(); + const size_t numNodesAfter = currentNode->GetNumChildNodes(); if (numNodesAfter == 0) { return nullptr; diff --git a/Gems/EMotionFX/Code/Tests/UI/CanAddMotionToAnimGraphNode.cpp b/Gems/EMotionFX/Code/Tests/UI/CanAddMotionToAnimGraphNode.cpp index 9dd041b2fd..dfd59d83ed 100644 --- a/Gems/EMotionFX/Code/Tests/UI/CanAddMotionToAnimGraphNode.cpp +++ b/Gems/EMotionFX/Code/Tests/UI/CanAddMotionToAnimGraphNode.cpp @@ -49,7 +49,7 @@ namespace EMotionFX ASSERT_TRUE(motionSetWindow) << "No motion set window found"; // Check there aren't any motion sets yet. - const AZ::u32 numMotionSets = EMotionFX::GetMotionManager().GetNumMotionSets(); + const size_t numMotionSets = EMotionFX::GetMotionManager().GetNumMotionSets(); EXPECT_EQ(numMotionSets, 0); // Find the action to create a new motion set and press it. @@ -58,7 +58,7 @@ namespace EMotionFX QTest::mouseClick(addMotionSetButton, Qt::LeftButton); // Make sure the new motion set has been created. - const AZ::u32 numMotionSetsAfterCreate = EMotionFX::GetMotionManager().GetNumMotionSets(); + const size_t numMotionSetsAfterCreate = EMotionFX::GetMotionManager().GetNumMotionSets(); ASSERT_EQ(numMotionSetsAfterCreate, numMotionSets + 1) << "Failed to create motion set."; EMotionFX::MotionSet* motionSet = EMotionFX::GetMotionManager().GetMotionSet(0); diff --git a/Gems/EMotionFX/Code/Tests/UI/CanAddMotionToMotionSet.cpp b/Gems/EMotionFX/Code/Tests/UI/CanAddMotionToMotionSet.cpp index 0e20d220d4..cd0cfea1dc 100644 --- a/Gems/EMotionFX/Code/Tests/UI/CanAddMotionToMotionSet.cpp +++ b/Gems/EMotionFX/Code/Tests/UI/CanAddMotionToMotionSet.cpp @@ -38,7 +38,7 @@ namespace EMotionFX ASSERT_TRUE(motionSetWindow) << "No motion set window found"; // Check there aren't any motion sets yet. - uint32 numMotionSets = EMotionFX::GetMotionManager().GetNumMotionSets(); + size_t numMotionSets = EMotionFX::GetMotionManager().GetNumMotionSets(); EXPECT_EQ(numMotionSets, 0); // Find the action to create a new motion set and press it. @@ -47,7 +47,7 @@ namespace EMotionFX QTest::mouseClick(addMotionSetButton, Qt::LeftButton); // Check there is now a motion set. - int numMotionSetsAfterCreate = EMotionFX::GetMotionManager().GetNumMotionSets(); + size_t numMotionSetsAfterCreate = EMotionFX::GetMotionManager().GetNumMotionSets(); ASSERT_EQ(numMotionSetsAfterCreate, 1); EMotionFX::MotionSet* motionSet = EMotionFX::GetMotionManager().GetMotionSet(0); @@ -56,7 +56,7 @@ namespace EMotionFX motionSetPlugin->SetSelectedSet(motionSet); // It should be empty at the moment. - int numMotions = static_cast(motionSet->GetNumMotionEntries()); + size_t numMotions = motionSet->GetNumMotionEntries(); EXPECT_EQ(numMotions, 0); // Find the action to add a motion to the set and press it. @@ -65,7 +65,7 @@ namespace EMotionFX QTest::mouseClick(addMotionButton, Qt::LeftButton); // There should now be a motion. - int numMotionsAfterCreate = static_cast(motionSet->GetNumMotionEntries()); + size_t numMotionsAfterCreate = motionSet->GetNumMotionEntries(); ASSERT_EQ(numMotionsAfterCreate, 1); AZStd::unordered_map motions = motionSet->GetMotionEntries(); diff --git a/Gems/EMotionFX/Code/Tests/UI/CanAddReferenceNode.cpp b/Gems/EMotionFX/Code/Tests/UI/CanAddReferenceNode.cpp index 46dae16f19..2e8851d80d 100644 --- a/Gems/EMotionFX/Code/Tests/UI/CanAddReferenceNode.cpp +++ b/Gems/EMotionFX/Code/Tests/UI/CanAddReferenceNode.cpp @@ -47,7 +47,7 @@ namespace EMotionFX addReferenceNodeAction->trigger(); // Check the expected node now exists. - int numNodesAfter= currentNode->GetNumChildNodes(); + size_t numNodesAfter = currentNode->GetNumChildNodes(); EXPECT_EQ(1, numNodesAfter); AnimGraphNode* newNode = currentNode->GetChildNode(0); diff --git a/Gems/EMotionFX/Code/Tests/UI/CanEditParameters.cpp b/Gems/EMotionFX/Code/Tests/UI/CanEditParameters.cpp index 82f509965c..b5ec8be715 100644 --- a/Gems/EMotionFX/Code/Tests/UI/CanEditParameters.cpp +++ b/Gems/EMotionFX/Code/Tests/UI/CanEditParameters.cpp @@ -74,7 +74,7 @@ namespace EMotionFX QTest::mouseClick(createButton, Qt::LeftButton); // Check we only have the one Parameter - int numParameters = static_cast(newGraph->GetNumParameters()); + size_t numParameters = newGraph->GetNumParameters(); EXPECT_EQ(numParameters, 1) << "Not just 1 parameter"; const RangedValueParameter* parameter = reinterpret_cast* >(newGraph->FindValueParameter(0)); diff --git a/Gems/EMotionFX/Code/Tests/UI/CanMorphManyShapes.cpp b/Gems/EMotionFX/Code/Tests/UI/CanMorphManyShapes.cpp index ba24c501ab..2ed0407d53 100644 --- a/Gems/EMotionFX/Code/Tests/UI/CanMorphManyShapes.cpp +++ b/Gems/EMotionFX/Code/Tests/UI/CanMorphManyShapes.cpp @@ -99,7 +99,7 @@ namespace EMotionFX // InitAfterLoading() is called morphTargetNode->AddConnection( parameterNode, - parameterNode->FindOutputPortIndex("FloatParam"), + aznumeric_caster(parameterNode->FindOutputPortIndex("FloatParam")), BlendTreeMorphTargetNode::PORTID_INPUT_WEIGHT ); finalNode->AddConnection( diff --git a/Gems/EMotionFX/Code/Tests/UI/CanRemoveMotionFromMotionSet.cpp b/Gems/EMotionFX/Code/Tests/UI/CanRemoveMotionFromMotionSet.cpp index c6bec666b1..5bd798ed28 100644 --- a/Gems/EMotionFX/Code/Tests/UI/CanRemoveMotionFromMotionSet.cpp +++ b/Gems/EMotionFX/Code/Tests/UI/CanRemoveMotionFromMotionSet.cpp @@ -41,7 +41,7 @@ namespace EMotionFX ASSERT_TRUE(motionSetWindow) << "No motion set window found"; // Check there aren't any motion sets yet. - const uint32 numMotionSets = EMotionFX::GetMotionManager().GetNumMotionSets(); + const size_t numMotionSets = EMotionFX::GetMotionManager().GetNumMotionSets(); EXPECT_EQ(numMotionSets, 0); // Find the action to create a new motion set and press it. @@ -50,7 +50,7 @@ namespace EMotionFX QTest::mouseClick(addMotionSetButton, Qt::LeftButton); // Check there is now a motion set. - const int numMotionSetsAfterCreate = EMotionFX::GetMotionManager().GetNumMotionSets(); + const size_t numMotionSetsAfterCreate = EMotionFX::GetMotionManager().GetNumMotionSets(); ASSERT_EQ(numMotionSetsAfterCreate, 1); EMotionFX::MotionSet* motionSet = EMotionFX::GetMotionManager().GetMotionSet(0); @@ -59,7 +59,7 @@ namespace EMotionFX motionSetPlugin->SetSelectedSet(motionSet); // It should be empty at the moment. - const int numMotions = static_cast(motionSet->GetNumMotionEntries()); + const size_t numMotions = motionSet->GetNumMotionEntries(); EXPECT_EQ(numMotions, 0); // Find the action to add a motion to the set and press it. @@ -68,7 +68,7 @@ namespace EMotionFX QTest::mouseClick(addMotionButton, Qt::LeftButton); // There should now be a motion. - const int numMotionsAfterCreate = static_cast(motionSet->GetNumMotionEntries()); + const size_t numMotionsAfterCreate = motionSet->GetNumMotionEntries(); ASSERT_EQ(numMotionsAfterCreate, 1); AZStd::unordered_map motions = motionSet->GetMotionEntries(); @@ -122,7 +122,7 @@ namespace EMotionFX ASSERT_TRUE(motionSetWindow) << "No motion set window found"; // Check there aren't any motion sets yet. - const uint32 numMotionSets = EMotionFX::GetMotionManager().GetNumMotionSets(); + const size_t numMotionSets = EMotionFX::GetMotionManager().GetNumMotionSets(); EXPECT_EQ(numMotionSets, 0); // Find the action to create a new motion set and press it. @@ -131,7 +131,7 @@ namespace EMotionFX QTest::mouseClick(addMotionSetButton, Qt::LeftButton); // Check there is now a motion set. - const int numMotionSetsAfterCreate = EMotionFX::GetMotionManager().GetNumMotionSets(); + const size_t numMotionSetsAfterCreate = EMotionFX::GetMotionManager().GetNumMotionSets(); ASSERT_EQ(numMotionSetsAfterCreate, 1); EMotionFX::MotionSet* motionSet = EMotionFX::GetMotionManager().GetMotionSet(0); @@ -140,7 +140,7 @@ namespace EMotionFX motionSetPlugin->SetSelectedSet(motionSet); // It should be empty at the moment. - const int numMotions = static_cast(motionSet->GetNumMotionEntries()); + const size_t numMotions = motionSet->GetNumMotionEntries(); EXPECT_EQ(numMotions, 0); // Find the action to add a motion to the set and press it twice. @@ -150,7 +150,7 @@ namespace EMotionFX QTest::mouseClick(addMotionButton, Qt::LeftButton); // There should now be two motion. - const int numMotionsAfterCreate = static_cast(motionSet->GetNumMotionEntries()); + const size_t numMotionsAfterCreate = motionSet->GetNumMotionEntries(); ASSERT_EQ(numMotionsAfterCreate, 2); AZStd::unordered_map motions = motionSet->GetMotionEntries(); diff --git a/Gems/EMotionFX/Code/Tests/UI/CanUseEditMenu.cpp b/Gems/EMotionFX/Code/Tests/UI/CanUseEditMenu.cpp index 673d39ae13..983cb6bc9a 100644 --- a/Gems/EMotionFX/Code/Tests/UI/CanUseEditMenu.cpp +++ b/Gems/EMotionFX/Code/Tests/UI/CanUseEditMenu.cpp @@ -41,7 +41,7 @@ namespace EMotionFX CommandSystem::CreateAnimGraphNode(/*commandGroup=*/nullptr, animGraph, azrtti_typeid(), "Reference", currentNode, 0, 0); // Check the expected node now exists. - uint32 numNodes = currentNode->GetNumChildNodes(); + size_t numNodes = currentNode->GetNumChildNodes(); EXPECT_EQ(1, numNodes); // Undo. @@ -49,7 +49,7 @@ namespace EMotionFX ASSERT_TRUE(undoAction); undoAction->trigger(); - const uint32 numNodesAfterUndo = currentNode->GetNumChildNodes(); + const size_t numNodesAfterUndo = currentNode->GetNumChildNodes(); ASSERT_EQ(numNodesAfterUndo, numNodes - 1); // Redo. @@ -57,7 +57,7 @@ namespace EMotionFX ASSERT_TRUE(redoAction); redoAction->trigger(); - const uint32 numNodesAfterRedo = currentNode->GetNumChildNodes(); + const size_t numNodesAfterRedo = currentNode->GetNumChildNodes(); ASSERT_EQ(numNodesAfterRedo, numNodesAfterUndo + 1); } } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/Tests/UI/CanUseViewMenu.cpp b/Gems/EMotionFX/Code/Tests/UI/CanUseViewMenu.cpp index 49667ee104..62914b83f0 100644 --- a/Gems/EMotionFX/Code/Tests/UI/CanUseViewMenu.cpp +++ b/Gems/EMotionFX/Code/Tests/UI/CanUseViewMenu.cpp @@ -106,7 +106,7 @@ namespace EMotionFX QList actions = viewMenu->findChildren(); int numActions = actions.size() - 1;// -1 as we don't want to include the view menu action itself. - const AZ::u32 numPlugins = pluginManager->GetNumPlugins(); + const size_t numPlugins = pluginManager->GetNumPlugins(); int visiblePlugins = 0; diff --git a/Gems/EMotionFX/Code/Tests/UI/UIFixture.cpp b/Gems/EMotionFX/Code/Tests/UI/UIFixture.cpp index 1425b87a6f..ea1f1c9148 100644 --- a/Gems/EMotionFX/Code/Tests/UI/UIFixture.cpp +++ b/Gems/EMotionFX/Code/Tests/UI/UIFixture.cpp @@ -73,8 +73,8 @@ namespace EMotionFX { // Plugins have to be created after both the QApplication object and // after the SystemComponent - const uint32 numPlugins = EMStudio::GetPluginManager()->GetNumPlugins(); - for (uint32 i = 0; i < numPlugins; ++i) + const size_t numPlugins = EMStudio::GetPluginManager()->GetNumPlugins(); + for (size_t i = 0; i < numPlugins; ++i) { EMStudio::EMStudioPlugin* plugin = EMStudio::GetPluginManager()->GetPlugin(i); EMStudio::GetPluginManager()->CreateWindowOfType(plugin->GetName()); From 2cfee517a0a68358caa97dd262b2111f251283b8 Mon Sep 17 00:00:00 2001 From: Chris Burel Date: Thu, 3 Jun 2021 11:18:24 -0700 Subject: [PATCH 209/803] Adjust EMotionFXAtom to work with the new EMotionFX size_t API Signed-off-by: Chris Burel --- .../EMotionFXAtom/Code/Source/ActorAsset.cpp | 14 +++---- .../Code/Source/AtomActorInstance.cpp | 42 +++++++++---------- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/ActorAsset.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/ActorAsset.cpp index 608635b395..ece2c2aca7 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/ActorAsset.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/ActorAsset.cpp @@ -58,8 +58,8 @@ namespace const AZ::RHI::Format BoneIndexFormat = AZ::RHI::Format::R32G32B32A32_UINT; const AZ::RHI::Format BoneWeightFormat = AZ::RHI::Format::R32G32B32A32_FLOAT; - const size_t LinearSkinningFloatsPerBone = 12; - const size_t DualQuaternionSkinningFloatsPerBone = 8; + const uint32_t LinearSkinningFloatsPerBone = 12; + const uint32_t DualQuaternionSkinningFloatsPerBone = 8; const uint32_t MaxSupportedSkinInfluences = 4; } @@ -266,7 +266,7 @@ namespace AZ } } - static void ProcessMorphsForLod(const EMotionFX::Actor* actor, const Data::Asset& morphBufferAsset, uint32_t lodIndex, const AZStd::string& fullFileName, SkinnedMeshInputLod& skinnedMeshLod) + static void ProcessMorphsForLod(const EMotionFX::Actor* actor, const Data::Asset& morphBufferAsset, size_t lodIndex, const AZStd::string& fullFileName, SkinnedMeshInputLod& skinnedMeshLod) { EMotionFX::MorphSetup* morphSetup = actor->GetMorphSetup(lodIndex); if (morphSetup) @@ -275,8 +275,8 @@ namespace AZ const AZStd::vector& metaDatas = actor->GetMorphTargetMetaAsset()->GetMorphTargets(); // Loop over all the EMotionFX morph targets - const AZ::u32 numMorphTargets = morphSetup->GetNumMorphTargets(); - for (AZ::u32 morphTargetIndex = 0; morphTargetIndex < numMorphTargets; ++morphTargetIndex) + const size_t numMorphTargets = morphSetup->GetNumMorphTargets(); + for (size_t morphTargetIndex = 0; morphTargetIndex < numMorphTargets; ++morphTargetIndex) { EMotionFX::MorphTargetStandard* morphTarget = static_cast(morphSetup->GetMorphTarget(morphTargetIndex)); for (const auto& metaData : metaDatas) @@ -288,7 +288,7 @@ namespace AZ if (metaData.m_morphTargetName == morphTarget->GetNameString() && metaData.m_numVertices > 0) { // The skinned mesh lod gets a unique morph for each meta, since each one has unique min/max delta values to use for decompression - AZStd::string morphString = AZStd::string::format("%s_Lod%u_Morph_%s", fullFileName.c_str(), lodIndex, metaData.m_meshNodeName.c_str()); + const AZStd::string morphString = AZStd::string::format("%s_Lod%zu_Morph_%s", fullFileName.c_str(), lodIndex, metaData.m_meshNodeName.c_str()); float minWeight = morphTarget->GetRangeMin(); float maxWeight = morphTarget->GetRangeMax(); @@ -574,7 +574,7 @@ namespace AZ AZStd::vector boneTransforms; GetBoneTransformsFromActorInstance(actorInstance, boneTransforms, skinningMethod); - size_t floatsPerBone = 0; + uint32_t floatsPerBone = 0; if (skinningMethod == EMotionFX::Integration::SkinningMethod::Linear) { floatsPerBone = LinearSkinningFloatsPerBone; diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp index 14e1f26bdd..c8a09ddaf8 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp @@ -131,14 +131,13 @@ namespace AZ const EMotionFX::Skeleton* skeleton = m_actorInstance->GetActor()->GetSkeleton(); const EMotionFX::Pose* pose = transformData->GetCurrentPose(); - const AZ::u32 transformCount = transformData->GetNumTransforms(); - const AZ::u32 lodLevel = m_actorInstance->GetLODLevel(); - const AZ::u32 numJoints = skeleton->GetNumNodes(); + const size_t lodLevel = m_actorInstance->GetLODLevel(); + const size_t numJoints = skeleton->GetNumNodes(); m_auxVertices.clear(); m_auxVertices.reserve(numJoints * 2); - for (AZ::u32 jointIndex = 0; jointIndex < numJoints; ++jointIndex) + for (size_t jointIndex = 0; jointIndex < numJoints; ++jointIndex) { const EMotionFX::Node* joint = skeleton->GetNode(jointIndex); if (!joint->GetSkeletalLODStatus(lodLevel)) @@ -146,8 +145,8 @@ namespace AZ continue; } - const AZ::u32 parentIndex = joint->GetParentIndex(); - if (parentIndex == InvalidIndex32) + const size_t parentIndex = joint->GetParentIndex(); + if (parentIndex == InvalidIndex) { continue; } @@ -162,7 +161,7 @@ namespace AZ const AZ::Color skeletonColor(0.604f, 0.804f, 0.196f, 1.0f); RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments lineArgs; lineArgs.m_verts = m_auxVertices.data(); - lineArgs.m_vertCount = static_cast(m_auxVertices.size()); + lineArgs.m_vertCount = aznumeric_caster(m_auxVertices.size()); lineArgs.m_colors = &skeletonColor; lineArgs.m_colorCount = 1; lineArgs.m_depthTest = RPI::AuxGeomDraw::DepthTest::Off; @@ -203,9 +202,9 @@ namespace AZ RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments lineArgs; lineArgs.m_verts = m_auxVertices.data(); - lineArgs.m_vertCount = static_cast(m_auxVertices.size()); + lineArgs.m_vertCount = aznumeric_caster(m_auxVertices.size()); lineArgs.m_colors = m_auxColors.data(); - lineArgs.m_colorCount = static_cast(m_auxColors.size()); + lineArgs.m_colorCount = aznumeric_caster(m_auxColors.size()); lineArgs.m_depthTest = RPI::AuxGeomDraw::DepthTest::Off; auxGeom->DrawLines(lineArgs); } @@ -450,13 +449,13 @@ namespace AZ AZ::u32 AtomActorInstance::GetJointCount() { - return m_actorInstance->GetActor()->GetSkeleton()->GetNumNodes(); + return aznumeric_caster(m_actorInstance->GetActor()->GetSkeleton()->GetNumNodes()); } const char* AtomActorInstance::GetJointNameByIndex(AZ::u32 jointIndex) { EMotionFX::Skeleton* skeleton = m_actorInstance->GetActor()->GetSkeleton(); - const AZ::u32 numNodes = skeleton->GetNumNodes(); + const size_t numNodes = skeleton->GetNumNodes(); if (jointIndex < numNodes) { return skeleton->GetNode(jointIndex)->GetName(); @@ -470,12 +469,12 @@ namespace AZ if (jointName) { EMotionFX::Skeleton* skeleton = m_actorInstance->GetActor()->GetSkeleton(); - const AZ::u32 numNodes = skeleton->GetNumNodes(); - for (AZ::u32 nodeIndex = 0; nodeIndex < numNodes; ++nodeIndex) + const size_t numNodes = skeleton->GetNumNodes(); + for (size_t nodeIndex = 0; nodeIndex < numNodes; ++nodeIndex) { if (0 == azstricmp(jointName, skeleton->GetNode(nodeIndex)->GetName())) { - return nodeIndex; + return aznumeric_caster(nodeIndex); } } } @@ -584,7 +583,8 @@ namespace AZ // Update the morph weights for every lod. This does not mean they will all be dispatched, but they will all have up to date weights // TODO: once culling is hooked up such that EMotionFX and Atom are always in sync about which lod to update, only update the currently visible lods [ATOM-13564] - for (uint32_t lodIndex = 0; lodIndex < m_actorInstance->GetActor()->GetNumLODLevels(); ++lodIndex) + const auto lodCount = aznumeric_cast(m_actorInstance->GetActor()->GetNumLODLevels()); + for (uint32_t lodIndex = 0; lodIndex < lodCount; ++lodIndex) { EMotionFX::MorphSetup* morphSetup = m_actorInstance->GetActor()->GetMorphSetup(lodIndex); if (morphSetup) @@ -593,9 +593,9 @@ namespace AZ m_wrinkleMasks.clear(); m_wrinkleMaskWeights.clear(); - uint32_t morphTargetCount = morphSetup->GetNumMorphTargets(); + size_t morphTargetCount = morphSetup->GetNumMorphTargets(); m_morphTargetWeights.clear(); - for (uint32_t morphTargetIndex = 0; morphTargetIndex < morphTargetCount; ++morphTargetIndex) + for (size_t morphTargetIndex = 0; morphTargetIndex < morphTargetCount; ++morphTargetIndex) { EMotionFX::MorphTarget* morphTarget = morphSetup->GetMorphTarget(morphTargetIndex); // check if we are dealing with a standard morph target @@ -611,7 +611,7 @@ namespace AZ // Each morph target is split into several deform datas, all of which share the same weight but have unique min/max delta values // and thus correspond with unique dispatches in the morph target pass - for (uint32_t deformDataIndex = 0; deformDataIndex < morphTargetStandard->GetNumDeformDatas(); ++deformDataIndex) + for (size_t deformDataIndex = 0; deformDataIndex < morphTargetStandard->GetNumDeformDatas(); ++deformDataIndex) { // Morph targets that don't deform any vertices (e.g. joint-based morph targets) are not registered in the render proxy. Skip adding their weights. const EMotionFX::MorphTargetStandard::DeformData* deformData = morphTargetStandard->GetDeformData(deformDataIndex); @@ -816,8 +816,8 @@ namespace AZ { const AZStd::vector& metaDatas = actor->GetMorphTargetMetaAsset()->GetMorphTargets(); // Loop over all the EMotionFX morph targets - uint32_t numMorphTargets = morphSetup->GetNumMorphTargets(); - for (uint32_t morphTargetIndex = 0; morphTargetIndex < numMorphTargets; ++morphTargetIndex) + size_t numMorphTargets = morphSetup->GetNumMorphTargets(); + for (size_t morphTargetIndex = 0; morphTargetIndex < numMorphTargets; ++morphTargetIndex) { EMotionFX::MorphTargetStandard* morphTarget = static_cast(morphSetup->GetMorphTarget(morphTargetIndex)); for (const RPI::MorphTargetMetaAsset::MorphTarget& metaData : metaDatas) @@ -861,7 +861,7 @@ namespace AZ // Set the weights for any active masks for (size_t i = 0; i < m_wrinkleMaskWeights.size(); ++i) { - wrinkleMaskObjectSrg->SetConstant(wrinkleMaskWeightsIndex, m_wrinkleMaskWeights[i], static_cast(i)); + wrinkleMaskObjectSrg->SetConstant(wrinkleMaskWeightsIndex, m_wrinkleMaskWeights[i], aznumeric_caster(i)); } AZ_Error("AtomActorInstance", m_wrinkleMaskWeights.size() <= s_maxActiveWrinkleMasks, "The skinning shader supports no more than %d active morph targets with wrinkle masks.", s_maxActiveWrinkleMasks); } From d57d263b5d158249b524620ec164f52cfd8621be Mon Sep 17 00:00:00 2001 From: Chris Burel Date: Tue, 6 Jul 2021 08:58:34 -0700 Subject: [PATCH 210/803] Fix format strings in EMotionFX to use the correct token for size_t Signed-off-by: Chris Burel --- .../CommandSystem/Source/ActorInstanceCommands.cpp | 2 +- .../StandardPlugins/Source/AnimGraph/BlendGraphWidget.cpp | 4 ++-- .../Source/Attachments/AttachmentsWindow.cpp | 2 +- .../Source/MorphTargetsWindow/MorphTargetEditWindow.cpp | 2 +- .../Source/MorphTargetsWindow/MorphTargetGroupWidget.cpp | 8 ++++---- .../Source/MorphTargetsWindow/PhonemeSelectionWindow.cpp | 2 +- .../Source/MotionSetsWindow/MotionSetWindow.cpp | 2 +- .../StandardPlugins/Source/TimeView/TimeViewPlugin.cpp | 2 +- Gems/EMotionFX/Code/Tests/Mocks/EventHandler.h | 2 +- 9 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ActorInstanceCommands.cpp b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ActorInstanceCommands.cpp index 60f03f170e..45603b298e 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ActorInstanceCommands.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ActorInstanceCommands.cpp @@ -492,7 +492,7 @@ namespace CommandSystem commandString = AZStd::string::format("CreateActorInstance -actorID %i -actorInstanceID %i", mOldActorID, actorInstanceID); commandGroup.AddCommandString(commandString.c_str()); - commandString = AZStd::string::format("AdjustActorInstance -actorInstanceID %i -pos \"%s\" -rot \"%s\" -scale \"%s\" -lodLevel %d -isVisible \"%s\" -doRender \"%s\"", + commandString = AZStd::string::format("AdjustActorInstance -actorInstanceID %i -pos \"%s\" -rot \"%s\" -scale \"%s\" -lodLevel %zu -isVisible \"%s\" -doRender \"%s\"", actorInstanceID, AZStd::to_string(mOldPosition).c_str(), AZStd::to_string(mOldRotation).c_str(), diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendGraphWidget.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendGraphWidget.cpp index edf5579720..5d57763ea6 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendGraphWidget.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendGraphWidget.cpp @@ -1475,10 +1475,10 @@ namespace EMStudio if (animGraphNode->GetCanHaveChildren()) { // child nodes - toolTipString += AZStd::string::format("Child Nodes:%i", animGraphNode->GetNumChildNodes()); + toolTipString += AZStd::string::format("Child Nodes:%zu", animGraphNode->GetNumChildNodes()); // recursive child nodes - toolTipString += AZStd::string::format("Recursive Child Nodes:%i", animGraphNode->RecursiveCalcNumNodes()); + toolTipString += AZStd::string::format("Recursive Child Nodes:%zu", animGraphNode->RecursiveCalcNumNodes()); } // states diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentsWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentsWindow.cpp index 2ffc56d25b..4b971f9c32 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentsWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentsWindow.cpp @@ -268,7 +268,7 @@ namespace EMStudio QTableWidgetItem* tableItemName = new QTableWidgetItem(mTempString.c_str()); mTempString = attachment->GetIsInfluencedByMultipleJoints() ? "Yes" : "No"; QTableWidgetItem* tableItemDeformable = new QTableWidgetItem(mTempString.c_str()); - mTempString = AZStd::string::format("%i", attachmentInstance->GetNumNodes()); + mTempString = AZStd::string::format("%zu", attachmentInstance->GetNumNodes()); QTableWidgetItem* tableItemNumNodes = new QTableWidgetItem(mTempString.c_str()); QTableWidgetItem* tableItemNodeName = new QTableWidgetItem(""); // set node name if exists diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/MorphTargetEditWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/MorphTargetEditWindow.cpp index 278159e4d0..a53ed94909 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/MorphTargetEditWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/MorphTargetEditWindow.cpp @@ -149,7 +149,7 @@ namespace EMStudio const float rangeMax = (float)mRangeMax->value(); AZStd::string result; - AZStd::string command = AZStd::string::format("AdjustMorphTarget -actorInstanceID %i -lodLevel %i -name \"%s\" -rangeMin %f -rangeMax %f", mActorInstance->GetID(), mActorInstance->GetLODLevel(), mMorphTarget->GetNameString().c_str(), rangeMin, rangeMax); + AZStd::string command = AZStd::string::format("AdjustMorphTarget -actorInstanceID %i -lodLevel %zu -name \"%s\" -rangeMin %f -rangeMax %f", mActorInstance->GetID(), mActorInstance->GetLODLevel(), mMorphTarget->GetNameString().c_str(), rangeMin, rangeMax); if (EMStudio::GetCommandManager()->ExecuteCommand(command, result) == false) { AZ_Error("EMotionFX", false, result.c_str()); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/MorphTargetGroupWidget.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/MorphTargetGroupWidget.cpp index 9d75f648b1..aee88f9394 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/MorphTargetGroupWidget.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/MorphTargetGroupWidget.cpp @@ -133,7 +133,7 @@ namespace EMStudio { EMotionFX::MorphTarget* morphTarget = mMorphTargets[i].mMorphTarget; - command = AZStd::string::format("AdjustMorphTarget -actorInstanceID %i -lodLevel %i -name \"%s\" -manualMode ", mActorInstance->GetID(), mActorInstance->GetLODLevel(), morphTarget->GetName()); + command = AZStd::string::format("AdjustMorphTarget -actorInstanceID %i -lodLevel %zu -name \"%s\" -manualMode ", mActorInstance->GetID(), mActorInstance->GetLODLevel(), morphTarget->GetName()); command += AZStd::to_string(value == Qt::Checked); commandGroup.AddCommandString(command); } @@ -159,7 +159,7 @@ namespace EMStudio { EMotionFX::MorphTarget* morphTarget = mMorphTargets[i].mMorphTarget; - command = AZStd::string::format("AdjustMorphTarget -actorInstanceID %i -lodLevel %i -name \"%s\" -weight %f", mActorInstance->GetID(), mActorInstance->GetLODLevel(), morphTarget->GetName(), morphTarget->CalcZeroInfluenceWeight()); + command = AZStd::string::format("AdjustMorphTarget -actorInstanceID %i -lodLevel %zu -name \"%s\" -weight %f", mActorInstance->GetID(), mActorInstance->GetLODLevel(), morphTarget->GetName(), morphTarget->CalcZeroInfluenceWeight()); commandGroup.AddCommandString(command); } @@ -179,7 +179,7 @@ namespace EMStudio EMotionFX::MorphTarget* morphTarget = mMorphTargets[morphTargetIndex].mMorphTarget; AZStd::string result; - const AZStd::string command = AZStd::string::format("AdjustMorphTarget -actorInstanceID %i -lodLevel %i -name \"%s\" -weight %f -manualMode %s", + const AZStd::string command = AZStd::string::format("AdjustMorphTarget -actorInstanceID %i -lodLevel %zu -name \"%s\" -weight %f -manualMode %s", mActorInstance->GetID(), mActorInstance->GetLODLevel(), morphTarget->GetName(), @@ -219,7 +219,7 @@ namespace EMStudio // execute command AZStd::string result; - const AZStd::string command = AZStd::string::format("AdjustMorphTarget -actorInstanceID %i -lodLevel %i -name \"%s\" -weight %f", mActorInstance->GetID(), mActorInstance->GetLODLevel(), morphTarget->GetName(), floatSlider->value()); + const AZStd::string command = AZStd::string::format("AdjustMorphTarget -actorInstanceID %i -lodLevel %zu -name \"%s\" -weight %f", mActorInstance->GetID(), mActorInstance->GetLODLevel(), morphTarget->GetName(), floatSlider->value()); if (EMStudio::GetCommandManager()->ExecuteCommand(command, result) == false) { AZ_Error("EMotionFX", false, result.c_str()); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/PhonemeSelectionWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/PhonemeSelectionWindow.cpp index 910f8456e5..5619398c67 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/PhonemeSelectionWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/PhonemeSelectionWindow.cpp @@ -523,7 +523,7 @@ namespace EMStudio // clear the selected phoneme sets void PhonemeSelectionWindow::ClearSelectedPhonemeSets() { - const AZStd::string command = AZStd::string::format("AdjustMorphTarget -actorID %i -lodLevel %i -name \"%s\" -phonemeAction \"clear\"", mActor->GetID(), mLODLevel, mMorphTarget->GetName()); + const AZStd::string command = AZStd::string::format("AdjustMorphTarget -actorID %i -lodLevel %zu -name \"%s\" -phonemeAction \"clear\"", mActor->GetID(), mLODLevel, mMorphTarget->GetName()); AZStd::string result; if (!EMStudio::GetCommandManager()->ExecuteCommand(command, result)) diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetWindow.cpp index 0ab738a259..19f28c36e0 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetWindow.cpp @@ -409,7 +409,7 @@ namespace EMStudio commandGroup.AddCommandString("Unselect -motionIndex SELECT_ALL"); - command = AZStd::string::format("Select -motionIndex %d", EMotionFX::GetMotionManager().FindMotionIndexByID(motion->GetID())); + command = AZStd::string::format("Select -motionIndex %zu", EMotionFX::GetMotionManager().FindMotionIndexByID(motion->GetID())); commandGroup.AddCommandString(command); EMotionFX::PlayBackInfo* defaultPlayBackInfo = motion->GetDefaultPlayBackInfo(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeViewPlugin.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeViewPlugin.cpp index 2ca600596a..6ff8ea3775 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeViewPlugin.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeViewPlugin.cpp @@ -1575,7 +1575,7 @@ namespace EMStudio // adjust the motion event AZStd::string outResult, command; - command = AZStd::string::format("AdjustMotionEvent -motionID %i -eventTrackName \"%s\" -eventNr %i -startTime %f -endTime %f", mMotion->GetID(), eventTrack->GetName(), motionEventNr, startTime, endTime); + command = AZStd::string::format("AdjustMotionEvent -motionID %i -eventTrackName \"%s\" -eventNr %zu -startTime %f -endTime %f", mMotion->GetID(), eventTrack->GetName(), motionEventNr, startTime, endTime); if (EMStudio::GetCommandManager()->ExecuteCommand(command.c_str(), outResult) == false) { MCore::LogError(outResult.c_str()); diff --git a/Gems/EMotionFX/Code/Tests/Mocks/EventHandler.h b/Gems/EMotionFX/Code/Tests/Mocks/EventHandler.h index 80e4a6ff21..1208082e67 100644 --- a/Gems/EMotionFX/Code/Tests/Mocks/EventHandler.h +++ b/Gems/EMotionFX/Code/Tests/Mocks/EventHandler.h @@ -58,7 +58,7 @@ namespace EMotionFX MOCK_METHOD2(OnStartTransition, void(AnimGraphInstance* animGraphInstance, AnimGraphStateTransition* transition)); MOCK_METHOD2(OnEndTransition, void(AnimGraphInstance* animGraphInstance, AnimGraphStateTransition* transition)); - MOCK_METHOD3(OnSetVisualManipulatorOffset, void(AnimGraphInstance* animGraphInstance, uint32 paramIndex, const AZ::Vector3& offset)); + MOCK_METHOD3(OnSetVisualManipulatorOffset, void(AnimGraphInstance* animGraphInstance, size_t paramIndex, const AZ::Vector3& offset)); MOCK_METHOD4(OnInputPortsChanged, void(AnimGraphNode* node, const AZStd::vector& newInputPorts, const AZStd::string& memberName, const AZStd::vector& memberValue)); MOCK_METHOD4(OnOutputPortsChanged, void(AnimGraphNode* node, const AZStd::vector& newOutputPorts, const AZStd::string& memberName, const AZStd::vector& memberValue)); MOCK_METHOD3(OnRenamedNode, void(AnimGraph* animGraph, AnimGraphNode* node, const AZStd::string& oldName)); From c34147d8619c3d21e3eb84d03e7db5923f18ea97 Mon Sep 17 00:00:00 2001 From: Chris Burel Date: Wed, 7 Jul 2021 15:12:36 -0700 Subject: [PATCH 211/803] Fix violation of -Wrange-loop-analysis Signed-off-by: Chris Burel --- .../StandardPlugins/Source/AnimGraph/AnimGraphPlugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphPlugin.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphPlugin.cpp index 62c0fe0a14..1a713f52fe 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphPlugin.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphPlugin.cpp @@ -147,7 +147,7 @@ namespace EMStudio return DirtyFileManager::FINISHED; } - for (const SaveDirtyFilesCallback::ObjectPointer objPointer : objects) + for (const SaveDirtyFilesCallback::ObjectPointer& objPointer : objects) { // get the current object pointer and skip directly if the type check fails if (objPointer.mAnimGraph == nullptr) From bf92c283a0891271b9f9ef42798749d8ad551e8f Mon Sep 17 00:00:00 2001 From: Chris Burel Date: Wed, 7 Jul 2021 12:15:20 -0700 Subject: [PATCH 212/803] Fix NvCloth tests to work with new EMotionFX API Signed-off-by: Chris Burel --- Gems/NvCloth/Code/Tests/ActorHelper.cpp | 6 +++--- Gems/NvCloth/Code/Tests/ActorHelper.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Gems/NvCloth/Code/Tests/ActorHelper.cpp b/Gems/NvCloth/Code/Tests/ActorHelper.cpp index 5520e8ac53..6742f60956 100644 --- a/Gems/NvCloth/Code/Tests/ActorHelper.cpp +++ b/Gems/NvCloth/Code/Tests/ActorHelper.cpp @@ -28,9 +28,9 @@ namespace UnitTest { } - AZ::u32 ActorHelper::AddJoint( + size_t ActorHelper::AddJoint( const AZStd::string& name, - const AZ::Transform localTransform, + const AZ::Transform& localTransform, const AZStd::string& parentName) { EMotionFX::Node* parentNode = GetSkeleton()->FindNodeByNameNoCase(parentName.c_str()); @@ -38,7 +38,7 @@ namespace UnitTest auto node = AddNode( GetNumNodes(), name.c_str(), - (parentNode) ? parentNode->GetNodeIndex() : MCORE_INVALIDINDEX32); + (parentNode) ? parentNode->GetNodeIndex() : InvalidIndex); GetBindPose()->SetLocalSpaceTransform(node->GetNodeIndex(), localTransform); diff --git a/Gems/NvCloth/Code/Tests/ActorHelper.h b/Gems/NvCloth/Code/Tests/ActorHelper.h index 82d53ae660..1e1145d995 100644 --- a/Gems/NvCloth/Code/Tests/ActorHelper.h +++ b/Gems/NvCloth/Code/Tests/ActorHelper.h @@ -23,9 +23,9 @@ namespace UnitTest explicit ActorHelper(const char* name); //! Adds a node to the skeleton. - AZ::u32 AddJoint( + size_t AddJoint( const AZStd::string& name, - const AZ::Transform localTransform = AZ::Transform::CreateIdentity(), + const AZ::Transform& localTransform = AZ::Transform::CreateIdentity(), const AZStd::string& parentName = ""); //! Adds a collider to the cloh configuration. From 04babd3cffeec6d398816c79711db61090b5330b Mon Sep 17 00:00:00 2001 From: Chris Burel Date: Tue, 13 Jul 2021 17:16:42 -0700 Subject: [PATCH 213/803] Fix misnamed range-for loop variables Signed-off-by: Chris Burel --- .../Rendering/OpenGL2/Source/GLRenderUtil.cpp | 4 ++-- Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp | 14 +++++++------- .../Code/EMotionFX/Source/ActorInstance.cpp | 8 ++++---- .../Code/EMotionFX/Source/AnimGraphInstance.cpp | 10 +++++----- .../Code/EMotionFX/Source/AnimGraphNode.h | 6 +++--- .../Code/EMotionFX/Source/AnimGraphPosePool.cpp | 4 ++-- .../Source/AnimGraphRefCountedDataPool.cpp | 4 ++-- .../Code/EMotionFX/Source/Importer/Importer.cpp | 4 ++-- Gems/EMotionFX/Code/EMotionFX/Source/Mesh.cpp | 4 ++-- .../Code/EMotionFX/Source/MorphMeshDeformer.cpp | 12 ++++++------ .../EMotionFX/Code/EMotionFX/Source/MorphSetup.cpp | 8 ++++---- .../Code/EMotionFX/Source/MorphTargetStandard.cpp | 10 +++++----- .../Code/EMotionFX/Source/MotionInstancePool.cpp | 4 ++-- .../Code/EMotionFX/Source/MotionLayerSystem.cpp | 8 ++++---- .../Code/EMotionFX/Source/MotionManager.cpp | 4 ++-- Gems/EMotionFX/Code/EMotionFX/Source/Node.cpp | 4 ++-- .../Code/EMotionFX/Source/StandardMaterial.cpp | 4 ++-- .../EMStudioSDK/Source/NodeHierarchyWidget.cpp | 4 ++-- .../Source/NotificationWindowManager.cpp | 12 ++++++------ .../Source/RenderPlugin/RenderPlugin.cpp | 6 +++--- .../StandardPlugins/Source/AnimGraph/GraphNode.cpp | 4 ++-- .../Source/MotionSetsWindow/MotionSetWindow.cpp | 10 +++++----- .../StandardPlugins/Source/TimeView/TimeTrack.cpp | 4 ++-- .../Source/TimeView/TimeViewPlugin.cpp | 4 ++-- .../Source/TimeView/TrackDataWidget.cpp | 10 +++++----- Gems/EMotionFX/Code/MCore/Source/StringIdPool.cpp | 4 ++-- .../Code/MysticQt/Source/MysticQtManager.cpp | 10 +++++----- 27 files changed, 90 insertions(+), 90 deletions(-) diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLRenderUtil.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLRenderUtil.cpp index c67ec180ed..d53a7b0f72 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLRenderUtil.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLRenderUtil.cpp @@ -158,9 +158,9 @@ namespace RenderGL delete[] mTextures; // get rid of texture entries - for (TextEntry* mTextEntrie : mTextEntries) + for (TextEntry* textEntry : mTextEntries) { - delete mTextEntrie; + delete textEntry; } mTextEntries.clear(); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp index 5d3f5e6ec8..6f1293e1a3 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp @@ -261,12 +261,12 @@ namespace EMotionFX void Actor::RemoveAllMaterials() { // for all LODs - for (AZStd::vector& mMaterial : mMaterials) + for (AZStd::vector& materials : mMaterials) { // delete all materials - for (Material* m : mMaterial) + for (Material* material : materials) { - m->Destroy(); + material->Destroy(); } } @@ -749,14 +749,14 @@ namespace EMotionFX const size_t numLODs = GetNumLODLevels(); // for all LODs, get rid of all the morph setups for each geometry LOD - for (MorphSetup* mMorphSetup : mMorphSetups) + for (MorphSetup* morphSetup : mMorphSetups) { - if (mMorphSetup) + if (morphSetup) { - mMorphSetup->Destroy(); + morphSetup->Destroy(); } - mMorphSetup = nullptr; + morphSetup = nullptr; } // remove all modifiers from the stacks for each lod in all nodes diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.cpp index 126d376ae4..f394dc4f5f 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.cpp @@ -561,9 +561,9 @@ namespace EMotionFX // set the attachment matrices void ActorInstance::UpdateAttachments() { - for (Attachment* mAttachment : mAttachments) + for (Attachment* attachment : mAttachments) { - mAttachment->Update(); + attachment->Update(); } } @@ -1741,9 +1741,9 @@ namespace EMotionFX SetIsVisible(isVisible); // recurse to all child attachments - for (Attachment* mAttachment : mAttachments) + for (Attachment* attachment : mAttachments) { - mAttachment->GetAttachmentActorInstance()->RecursiveSetIsVisible(isVisible); + attachment->GetAttachmentActorInstance()->RecursiveSetIsVisible(isVisible); } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphInstance.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphInstance.cpp index c31f584498..9ed0a0e527 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphInstance.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphInstance.cpp @@ -143,11 +143,11 @@ namespace EMotionFX { if (delFromMem) { - for (MCore::Attribute* mParamValue : mParamValues) + for (MCore::Attribute* paramValue : mParamValues) { - if (mParamValue) + if (paramValue) { - delete mParamValue; + delete paramValue; } } } @@ -930,9 +930,9 @@ namespace EMotionFX // reset all node flags void AnimGraphInstance::ResetFlagsForAllObjects(uint32 flagsToDisable) { - for (uint32& mObjectFlag : mObjectFlags) + for (uint32& objectFlag : mObjectFlags) { - mObjectFlag &= ~flagsToDisable; + objectFlag &= ~flagsToDisable; } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNode.h b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNode.h index 89f4db2e5d..31d85b6f48 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNode.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNode.h @@ -97,16 +97,16 @@ namespace EMotionFX bool CheckIfIsCompatibleWith(const Port& otherPort) const { // check the data types - for (uint32 mCompatibleType : mCompatibleTypes) + for (uint32 compatibleType : mCompatibleTypes) { // If there aren't any more compatibility types and we haven't found a compatible one so far, return false - if (mCompatibleType == 0) + if (compatibleType == 0) { return false; } for (uint32 otherCompatibleTypeIndex : otherPort.mCompatibleTypes) { - if (otherCompatibleTypeIndex == mCompatibleType) + if (otherCompatibleTypeIndex == compatibleType) { return true; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphPosePool.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphPosePool.cpp index 3314ff0a17..f7f3a6c0bf 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphPosePool.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphPosePool.cpp @@ -27,9 +27,9 @@ namespace EMotionFX AnimGraphPosePool::~AnimGraphPosePool() { // delete all poses - for (AnimGraphPose* mPose : mPoses) + for (AnimGraphPose* pose : mPoses) { - delete mPose; + delete pose; } mPoses.clear(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphRefCountedDataPool.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphRefCountedDataPool.cpp index f4e7402fdf..1a04f18375 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphRefCountedDataPool.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphRefCountedDataPool.cpp @@ -28,9 +28,9 @@ namespace EMotionFX AnimGraphRefCountedDataPool::~AnimGraphRefCountedDataPool() { // delete all items - for (AnimGraphRefCountedData*& mItem : mItems) + for (AnimGraphRefCountedData*& item : mItems) { - delete mItem; + delete item; } mItems.clear(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/Importer.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/Importer.cpp index e710192afd..e2cc633012 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/Importer.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/Importer.cpp @@ -60,9 +60,9 @@ namespace EMotionFX Importer::~Importer() { // remove all chunk processors - for (ChunkProcessor* mChunkProcessor : mChunkProcessors) + for (ChunkProcessor* chunkProcessor : mChunkProcessors) { - mChunkProcessor->Destroy(); + chunkProcessor->Destroy(); } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.cpp index 135a37200c..450a546c27 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.cpp @@ -374,9 +374,9 @@ namespace EMotionFX // copy all original data over the output data void Mesh::ResetToOriginalData() { - for (VertexAttributeLayer* mVertexAttribute : mVertexAttributes) + for (VertexAttributeLayer* vertexAttribute : mVertexAttributes) { - mVertexAttribute->ResetToOriginalData(); + vertexAttribute->ResetToOriginalData(); } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MorphMeshDeformer.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MorphMeshDeformer.cpp index 561e94b35b..e3fd1552b0 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MorphMeshDeformer.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MorphMeshDeformer.cpp @@ -88,17 +88,17 @@ namespace EMotionFX const size_t lodLevel = actorInstance->GetLODLevel(); // apply all deform passes - for (DeformPass& mDeformPasse : mDeformPasses) + for (DeformPass& deformPass : mDeformPasses) { // find the morph target - MorphTargetStandard* morphTarget = (MorphTargetStandard*)actor->GetMorphSetup(lodLevel)->FindMorphTargetByID(mDeformPasse.mMorphTarget->GetID()); + MorphTargetStandard* morphTarget = (MorphTargetStandard*)actor->GetMorphSetup(lodLevel)->FindMorphTargetByID(deformPass.mMorphTarget->GetID()); if (morphTarget == nullptr) { continue; } // get the deform data and number of vertices to deform - MorphTargetStandard::DeformData* deformData = morphTarget->GetDeformData(mDeformPasse.mDeformDataNr); + MorphTargetStandard::DeformData* deformData = morphTarget->GetDeformData(deformPass.mDeformDataNr); const uint32 numDeformVerts = deformData->mNumVerts; // this mesh deformer can't work on this mesh, because the deformdata number of vertices is bigger than the @@ -120,7 +120,7 @@ namespace EMotionFX const bool nearZero = (MCore::Math::Abs(weight) < 0.0001f); // we are near zero, and the previous frame as well, so we can return - if (nearZero && mDeformPasse.mLastNearZero) + if (nearZero && deformPass.mLastNearZero) { continue; } @@ -128,11 +128,11 @@ namespace EMotionFX // update the flag if (nearZero) { - mDeformPasse.mLastNearZero = true; + deformPass.mLastNearZero = true; } else { - mDeformPasse.mLastNearZero = false; // we moved away from zero influence + deformPass.mLastNearZero = false; // we moved away from zero influence } // output data diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MorphSetup.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MorphSetup.cpp index 069e7c971a..d4a70dd070 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MorphSetup.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MorphSetup.cpp @@ -70,9 +70,9 @@ namespace EMotionFX // remove all morph targets void MorphSetup::RemoveAllMorphTargets() { - for (MorphTarget*& mMorphTarget : mMorphTargets) + for (MorphTarget*& morphTarget : mMorphTargets) { - mMorphTarget->Destroy(); + morphTarget->Destroy(); } mMorphTargets.clear(); @@ -176,9 +176,9 @@ namespace EMotionFX } // scale the morph targets - for (MorphTarget* mMorphTarget : mMorphTargets) + for (MorphTarget* morphTarget : mMorphTargets) { - mMorphTarget->Scale(scaleFactor); + morphTarget->Scale(scaleFactor); } } } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MorphTargetStandard.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MorphTargetStandard.cpp index 7612fd73d7..c86815be80 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MorphTargetStandard.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MorphTargetStandard.cpp @@ -177,20 +177,20 @@ namespace EMotionFX const float normalizedWeight = CalcNormalizedWeight(newWeight); // convert in range of 0..1 // calculate the new transformations for all nodes of this morph target - for (const Transformation& mTransform : mTransforms) + for (const Transformation& transform : mTransforms) { // if this is the node that gets modified by this transform - if (mTransform.mNodeIndex != nodeIndex) + if (transform.mNodeIndex != nodeIndex) { continue; } - position += mTransform.mPosition * newWeight; - scale += mTransform.mScale * newWeight; + position += transform.mPosition * newWeight; + scale += transform.mScale * newWeight; // rotate additively const AZ::Quaternion& orgRot = actorInstance->GetTransformData()->GetBindPose()->GetLocalSpaceTransform(nodeIndex).mRotation; - const AZ::Quaternion rot = orgRot.NLerp(mTransform.mRotation, normalizedWeight); + const AZ::Quaternion rot = orgRot.NLerp(transform.mRotation, normalizedWeight); rotation = rotation * (orgRot.GetInverseFull() * rot); rotation.Normalize(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MotionInstancePool.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MotionInstancePool.cpp index d31d81fe7a..a10a4722eb 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MotionInstancePool.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MotionInstancePool.cpp @@ -65,9 +65,9 @@ namespace EMotionFX MCORE_ASSERT(mData == nullptr); // delete all subpools - for (SubPool* mSubPool : mSubPools) + for (SubPool* subPool : mSubPools) { - delete mSubPool; + delete subPool; } mSubPools.clear(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MotionLayerSystem.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MotionLayerSystem.cpp index 4c3ba95e59..b613ecc147 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MotionLayerSystem.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MotionLayerSystem.cpp @@ -49,11 +49,11 @@ namespace EMotionFX void MotionLayerSystem::RemoveAllLayerPasses(bool delFromMem) { // delete all layer passes - for (LayerPass* mLayerPasse : mLayerPasses) + for (LayerPass* layerPass : mLayerPasses) { if (delFromMem) { - mLayerPasse->Destroy(); + layerPass->Destroy(); } } @@ -120,9 +120,9 @@ namespace EMotionFX mMotionQueue->Update(); // process all layer passes - for (LayerPass* mLayerPasse : mLayerPasses) + for (LayerPass* layerPass : mLayerPasses) { - mLayerPasse->Process(); + layerPass->Process(); } // process the repositioning as last diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MotionManager.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MotionManager.cpp index 1954d23dc3..8472e46796 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MotionManager.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MotionManager.cpp @@ -479,10 +479,10 @@ namespace EMotionFX size_t result = 0; // get the number of motion sets and iterate through them - for (const MotionSet* mMotionSet : mMotionSets) + for (const MotionSet* motionSet : mMotionSets) { // sum up the root motion sets - if (mMotionSet->GetParentSet() == nullptr) + if (motionSet->GetParentSet() == nullptr) { result++; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Node.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Node.cpp index 1144cc3f42..4bb1d850c9 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Node.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Node.cpp @@ -90,9 +90,9 @@ namespace EMotionFX // copy the node attributes result->mAttributes.reserve(mAttributes.size()); - for (const NodeAttribute* mAttribute : mAttributes) + for (const NodeAttribute* attribute : mAttributes) { - result->AddAttribute(mAttribute->Clone()); + result->AddAttribute(attribute->Clone()); } // return the resulting clone diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/StandardMaterial.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/StandardMaterial.cpp index 4ee3a24056..5f5c439f7c 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/StandardMaterial.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/StandardMaterial.cpp @@ -580,9 +580,9 @@ namespace EMotionFX void StandardMaterial::RemoveAllLayers() { - for (StandardMaterialLayer* mLayer : mLayers) + for (StandardMaterialLayer* layer : mLayers) { - mLayer->Destroy(); + layer->Destroy(); } mLayers.clear(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NodeHierarchyWidget.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NodeHierarchyWidget.cpp index 55f7324b75..1aa8082f08 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NodeHierarchyWidget.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NodeHierarchyWidget.cpp @@ -187,10 +187,10 @@ namespace EMStudio mHierarchy->clear(); // get the number actor instances and iterate over them - for (const uint32 mActorInstanceID : mActorInstanceIDs) + for (const uint32 actorInstanceID : mActorInstanceIDs) { // get the actor instance by its id - EMotionFX::ActorInstance* actorInstance = EMotionFX::GetActorManager().FindActorInstanceByID(mActorInstanceID); + EMotionFX::ActorInstance* actorInstance = EMotionFX::GetActorManager().FindActorInstanceByID(actorInstanceID); if (actorInstance) { AddActorInstance(actorInstance); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NotificationWindowManager.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NotificationWindowManager.cpp index d203e4386b..e1c22ee60d 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NotificationWindowManager.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NotificationWindowManager.cpp @@ -33,9 +33,9 @@ namespace EMStudio // compute the height of all notification windows with the spacing int allNotificationWindowsHeight = 0; - for (const NotificationWindow* mNotificationWindow : mNotificationWindows) + for (const NotificationWindow* currentNotificationWindow : mNotificationWindows) { - allNotificationWindowsHeight += mNotificationWindow->geometry().height() + notificationWindowSpacing; + allNotificationWindowsHeight += currentNotificationWindow->geometry().height() + notificationWindowSpacing; } // move the notification window @@ -81,15 +81,15 @@ namespace EMStudio // move each notification window int currentNotificationWindowHeight = notificationWindowMainWindowPadding; - for (NotificationWindow* mNotificationWindow : mNotificationWindows) + for (NotificationWindow* notificationWindow : mNotificationWindows) { // add the height of the notification window - currentNotificationWindowHeight += mNotificationWindow->geometry().height(); + currentNotificationWindowHeight += notificationWindow->geometry().height(); // move the notification window const QPoint mainWindowBottomRight = mainWindow->geometry().bottomRight(); - const QRect& notificationWindowGeometry = mNotificationWindow->geometry(); - mNotificationWindow->move(mainWindowBottomRight.x() - notificationWindowGeometry.width() - notificationWindowMainWindowPadding, mainWindowBottomRight.y() - currentNotificationWindowHeight); + const QRect& notificationWindowGeometry = notificationWindow->geometry(); + notificationWindow->move(mainWindowBottomRight.x() - notificationWindowGeometry.width() - notificationWindowMainWindowPadding, mainWindowBottomRight.y() - currentNotificationWindowHeight); // spacing is added after to avoid spacing on the bottom of the first notification window currentNotificationWindowHeight += notificationWindowSpacing; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.cpp index 506605fec4..d3e9593add 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.cpp @@ -128,11 +128,11 @@ namespace EMStudio void RenderPlugin::CleanEMStudioActors() { // get rid of the actors - for (EMStudioRenderActor* mActor : mActors) + for (EMStudioRenderActor* actor : mActors) { - if (mActor) + if (actor) { - delete mActor; + delete actor; } } mActors.clear(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GraphNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GraphNode.cpp index f6b0b72bf6..4f29a15669 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GraphNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GraphNode.cpp @@ -149,9 +149,9 @@ namespace EMStudio // remove all node connections void GraphNode::RemoveAllConnections() { - for (NodeConnection* mConnection : mConnections) + for (NodeConnection* connection : mConnections) { - delete mConnection; + delete connection; } mConnections.clear(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetWindow.cpp index 19f28c36e0..3fd928c60c 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetWindow.cpp @@ -1965,7 +1965,7 @@ namespace EMStudio // Modify each ID using the operation in the modified array. AZStd::string newMotionID; AZStd::string tempString; - for (const AZStd::string& mMotionID : mMotionIDs) + for (const AZStd::string& motionID : mMotionIDs) { // 0=Replace All, 1=Replace First, 2=Replace Last const int operationMode = mComboBox->currentIndex(); @@ -1975,7 +1975,7 @@ namespace EMStudio { case 0: { - tempString = mMotionID.c_str(); + tempString = motionID.c_str(); AzFramework::StringFunc::Replace(tempString, mStringALineEdit->text().toUtf8().data(), mStringBLineEdit->text().toUtf8().data(), true /* case sensitive */); newMotionID = tempString.c_str(); break; @@ -1983,7 +1983,7 @@ namespace EMStudio case 1: { - tempString = mMotionID.c_str(); + tempString = motionID.c_str(); AzFramework::StringFunc::Replace(tempString, mStringALineEdit->text().toUtf8().data(), mStringBLineEdit->text().toUtf8().data(), true /* case sensitive */, true /* replace first */, false /* replace last */); newMotionID = tempString.c_str(); break; @@ -1991,7 +1991,7 @@ namespace EMStudio case 2: { - tempString = mMotionID.c_str(); + tempString = motionID.c_str(); AzFramework::StringFunc::Replace(tempString, mStringALineEdit->text().toUtf8().data(), mStringBLineEdit->text().toUtf8().data(), true /* case sensitive */, false /* replace first */, true /* replace last */); newMotionID = tempString.c_str(); break; @@ -1999,7 +1999,7 @@ namespace EMStudio } // change the value in the array and add the mapping motion to modified - auto iterator = AZStd::find(mModifiedMotionIDs.begin(), mModifiedMotionIDs.end(), mMotionID); + auto iterator = AZStd::find(mModifiedMotionIDs.begin(), mModifiedMotionIDs.end(), motionID); const size_t modifiedIndex = iterator - mModifiedMotionIDs.begin(); mModifiedMotionIDs[modifiedIndex] = newMotionID; mMotionToModifiedMap.push_back(modifiedIndex); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeTrack.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeTrack.cpp index 0f276d640d..c1c440d0d8 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeTrack.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeTrack.cpp @@ -163,9 +163,9 @@ namespace EMStudio { if (delFromMem) { - for (TimeTrackElement* mElement : mElements) + for (TimeTrackElement* element : mElements) { - delete mElement; + delete element; } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeViewPlugin.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeViewPlugin.cpp index 6ff8ea3775..6f8ab95891 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeViewPlugin.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeViewPlugin.cpp @@ -107,9 +107,9 @@ namespace EMStudio delete mZoomOutCursor; // get rid of the motion infos - for (MotionInfo* mMotionInfo : mMotionInfos) + for (MotionInfo* motionInfo : mMotionInfos) { - delete mMotionInfo; + delete motionInfo; } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackDataWidget.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackDataWidget.cpp index bbfae05dff..06569b3bf3 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackDataWidget.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackDataWidget.cpp @@ -453,9 +453,9 @@ namespace EMStudio // display the values and names int offset = 0; - for (const EMotionFX::Recorder::ExtractedNodeHistoryItem& mActiveItem : mActiveItems) + for (const EMotionFX::Recorder::ExtractedNodeHistoryItem& activeItem : mActiveItems) { - EMotionFX::Recorder::NodeHistoryItem* curItem = mActiveItem.mNodeHistoryItem; + EMotionFX::Recorder::NodeHistoryItem* curItem = activeItem.mNodeHistoryItem; if (curItem == nullptr) { continue; @@ -481,14 +481,14 @@ namespace EMStudio if (!mTempString.empty()) { - mTempString += AZStd::string::format(" = %.4f", mActiveItem.mValue); + mTempString += AZStd::string::format(" = %.4f", activeItem.mValue); } else { - mTempString = AZStd::string::format("%.4f", mActiveItem.mValue); + mTempString = AZStd::string::format("%.4f", activeItem.mValue); } - const AZ::Color colorCode = (useNodeColors) ? mActiveItem.mNodeHistoryItem->mTypeColor : mActiveItem.mNodeHistoryItem->mColor; + const AZ::Color colorCode = (useNodeColors) ? activeItem.mNodeHistoryItem->mTypeColor : activeItem.mNodeHistoryItem->mColor; QColor color; color.setRgbF(colorCode.GetR(), colorCode.GetG(), colorCode.GetB(), colorCode.GetA()); diff --git a/Gems/EMotionFX/Code/MCore/Source/StringIdPool.cpp b/Gems/EMotionFX/Code/MCore/Source/StringIdPool.cpp index 4e89072f70..dc08f628fe 100644 --- a/Gems/EMotionFX/Code/MCore/Source/StringIdPool.cpp +++ b/Gems/EMotionFX/Code/MCore/Source/StringIdPool.cpp @@ -29,9 +29,9 @@ namespace MCore { Lock(); - for (AZStd::basic_string*& mString : mStrings) + for (AZStd::basic_string*& string : mStrings) { - delete mString; + delete string; } mStrings.clear(); diff --git a/Gems/EMotionFX/Code/MysticQt/Source/MysticQtManager.cpp b/Gems/EMotionFX/Code/MysticQt/Source/MysticQtManager.cpp index 016664e017..3386e1a0d2 100644 --- a/Gems/EMotionFX/Code/MysticQt/Source/MysticQtManager.cpp +++ b/Gems/EMotionFX/Code/MysticQt/Source/MysticQtManager.cpp @@ -30,9 +30,9 @@ namespace MysticQt MysticQtManager::~MysticQtManager() { // get the number of icons and destroy them - for (IconData* mIcon : mIcons) + for (IconData* icon : mIcons) { - delete mIcon; + delete icon; } mIcons.clear(); } @@ -57,11 +57,11 @@ namespace MysticQt const QIcon& MysticQtManager::FindIcon(const char* filename) { // get the number of icons and iterate through them - for (IconData* mIcon : mIcons) + for (IconData* icon : mIcons) { - if (AzFramework::StringFunc::Equal(mIcon->mFileName.c_str(), filename, false /* no case */)) + if (AzFramework::StringFunc::Equal(icon->mFileName.c_str(), filename, false /* no case */)) { - return *(mIcon->mIcon); + return *(icon->mIcon); } } From f03df3e546277c278bd514bdecc06c3117c773a5 Mon Sep 17 00:00:00 2001 From: amzn-phist <52085794+amzn-phist@users.noreply.github.com> Date: Mon, 9 Aug 2021 11:51:06 -0500 Subject: [PATCH 214/803] Fix issues with audio localization bank switching (#2945) * Fix issues with locating and loading loc banks The code that initially checked the g_languageAudio cvar wasn't properly detecting when the cvar wasn't set. Fixed an issue discovering localized banks wasn't properly recursing into subdirectories. Simplified handling of audio language switching for Wwise. Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com> * Address feedback on PR Change .size() == 0 to .empty() Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com> --- Code/Legacy/CrySystem/SystemInit.cpp | 16 +++++++--------- .../Code/Source/Editor/AudioWwiseLoader.cpp | 6 ++++-- .../Code/Source/Engine/AudioSystemImpl_wwise.cpp | 11 +---------- 3 files changed, 12 insertions(+), 21 deletions(-) diff --git a/Code/Legacy/CrySystem/SystemInit.cpp b/Code/Legacy/CrySystem/SystemInit.cpp index cce3cf4aec..f24bcd2d41 100644 --- a/Code/Legacy/CrySystem/SystemInit.cpp +++ b/Code/Legacy/CrySystem/SystemInit.cpp @@ -896,16 +896,14 @@ void CSystem::InitLocalization() if (auto console = AZ::Interface::Get(); console != nullptr) { AZ::CVarFixedString languageAudio; - if (auto result = console->GetCvarValue("g_languageAudio", languageAudio); result == AZ::GetValueResult::Success) + console->GetCvarValue("g_languageAudio", languageAudio); + if (languageAudio.empty()) { - if (languageAudio.size() == 0) - { - console->PerformCommand(AZStd::string::format("g_languageAudio %s", language.c_str()).c_str()); - } - else - { - language.assign(languageAudio.data(), languageAudio.size()); - } + console->PerformCommand(AZStd::string::format("g_languageAudio %s", language.c_str()).c_str()); + } + else + { + language.assign(languageAudio.data(), languageAudio.size()); } } OpenLanguageAudioPak(language); diff --git a/Gems/AudioEngineWwise/Code/Source/Editor/AudioWwiseLoader.cpp b/Gems/AudioEngineWwise/Code/Source/Editor/AudioWwiseLoader.cpp index 616a30994c..19038dc54c 100644 --- a/Gems/AudioEngineWwise/Code/Source/Editor/AudioWwiseLoader.cpp +++ b/Gems/AudioEngineWwise/Code/Source/Editor/AudioWwiseLoader.cpp @@ -54,7 +54,9 @@ namespace AudioControls //-------------------------------------------------------------------------------------------// void CAudioWwiseLoader::LoadSoundBanks(const AZStd::string_view rootFolder, const AZStd::string_view subPath, bool isLocalized) { - auto foundFiles = Audio::FindFilesInPath(rootFolder, "*"); + AZ::IO::FixedMaxPath searchPath(rootFolder); + searchPath /= subPath; + auto foundFiles = Audio::FindFilesInPath(searchPath.Native(), "*"); bool isLocalizedLoaded = isLocalized; for (const auto& filePath : foundFiles) @@ -71,7 +73,7 @@ namespace AudioControls // same content (in the future we want to have a // consistency report to highlight if this is not the case) m_localizationFolder.assign(fileName.Native().data(), fileName.Native().size()); - LoadSoundBanks(rootFolder, m_localizationFolder, true); + LoadSoundBanks(searchPath.Native(), m_localizationFolder, true); isLocalizedLoaded = true; } } diff --git a/Gems/AudioEngineWwise/Code/Source/Engine/AudioSystemImpl_wwise.cpp b/Gems/AudioEngineWwise/Code/Source/Engine/AudioSystemImpl_wwise.cpp index 4095e3bf84..e4933728d4 100644 --- a/Gems/AudioEngineWwise/Code/Source/Engine/AudioSystemImpl_wwise.cpp +++ b/Gems/AudioEngineWwise/Code/Source/Engine/AudioSystemImpl_wwise.cpp @@ -2173,16 +2173,7 @@ namespace Audio { if (language) { - AZStd::string languageSubfolder; - - if (azstricmp(language, "english") == 0) - { - languageSubfolder = "english(us)"; - } - else - { - languageSubfolder = language; - } + AZStd::string languageSubfolder(language); languageSubfolder += "/"; From 12579e5d2e3e477a8bbc26cc5414102504df9e3e Mon Sep 17 00:00:00 2001 From: Nicholas Lawson <70027408+lawsonamzn@users.noreply.github.com> Date: Mon, 9 Aug 2021 10:05:25 -0700 Subject: [PATCH 215/803] Fixes incorrect build dependencies for tests (#2959) The serialize context tools were not being auto built by CI because of this. Added missing dependency on AzTestRunner. Also moved the AssetBundlerBatch dependency directly in there No reason to add it to additional_dependnecies, since its only used for conditional inclusions. Signed-off-by: lawsonamzn <70027408+lawsonamzn@users.noreply.github.com> --- AutomatedTesting/Gem/PythonTests/smoke/CMakeLists.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/AutomatedTesting/Gem/PythonTests/smoke/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/smoke/CMakeLists.txt index 600911e9f1..e84128ad1a 100644 --- a/AutomatedTesting/Gem/PythonTests/smoke/CMakeLists.txt +++ b/AutomatedTesting/Gem/PythonTests/smoke/CMakeLists.txt @@ -11,7 +11,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) if (PAL_TRAIT_BUILD_SERIALIZECONTEXTTOOLS) list(APPEND additional_dependencies AZ::SerializeContextTools) # test_CLITool_SerializeContextTools depends on it endif() - list(APPEND additional_dependencies AZ::AssetBundlerBatch) # test_CLITool_AssetBundlerBatch_Works depends on it ly_add_pytest( NAME AutomatedTesting::SmokeTest @@ -26,7 +25,9 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) Legacy::Editor AutomatedTesting.GameLauncher AutomatedTesting.Assets - ${aditional_dependencies} + AZ::AzTestRunner + AZ::AssetBundlerBatch + ${additional_dependencies} COMPONENT Smoke ) From fb3195d9962e5efe1002dc7a28179db74793b4da Mon Sep 17 00:00:00 2001 From: Artur K <96597+nemerle@users.noreply.github.com> Date: Mon, 9 Aug 2021 19:05:55 +0200 Subject: [PATCH 216/803] Reduce size of AllocationInfo struct to 64 bytes ( was 72 ) (#2771) Signed-off-by: nemerle <96597+nemerle@users.noreply.github.com> --- Code/Framework/AzCore/AzCore/Memory/AllocationRecords.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/Memory/AllocationRecords.h b/Code/Framework/AzCore/AzCore/Memory/AllocationRecords.h index a6e562e592..709e16174d 100644 --- a/Code/Framework/AzCore/AzCore/Memory/AllocationRecords.h +++ b/Code/Framework/AzCore/AzCore/Memory/AllocationRecords.h @@ -27,11 +27,10 @@ namespace AZ struct AllocationInfo { size_t m_byteSize{}; - unsigned int m_alignment{}; const char* m_name{}; - const char* m_fileName{}; int m_lineNum{}; + unsigned int m_alignment{}; void* m_namesBlock{}; ///< Memory block if m_name and m_fileName have been allocated specifically for this allocation record size_t m_namesBlockSize{}; @@ -41,7 +40,7 @@ namespace AZ }; // We use OSAllocator which uses system calls to allocate memory, they are not recorded or tracked! - typedef AZStd::unordered_map, AZStd::equal_to, OSStdAllocator> AllocationRecordsType; + using AllocationRecordsType = AZStd::unordered_map, AZStd::equal_to, OSStdAllocator>; /** * Records enumeration callback @@ -50,7 +49,7 @@ namespace AZ * \param unsigned char number of stack records/levels, if AllocationInfo::m_stackFrames != NULL. * \returns true if you want to continue traverse of the records and false if you want to stop. */ - typedef AZStd::function AllocationInfoCBType; + using AllocationInfoCBType = AZStd::function; /** * Example of records enumeration callback. */ From fceb29fa5f4ee42af1eb98c1517de2acf850f151 Mon Sep 17 00:00:00 2001 From: Nemerle Date: Fri, 6 Aug 2021 14:06:59 +0200 Subject: [PATCH 217/803] Editor: code style fixups in 2 files A few small fixes ( for range loops + one -> check) Signed-off-by: Nemerle --- Code/Editor/PluginManager.cpp | 22 +++++++++------------- Code/Editor/ResourceSelectorHost.cpp | 8 ++------ 2 files changed, 11 insertions(+), 19 deletions(-) diff --git a/Code/Editor/PluginManager.cpp b/Code/Editor/PluginManager.cpp index 5efd52a97e..1530641fa7 100644 --- a/Code/Editor/PluginManager.cpp +++ b/Code/Editor/PluginManager.cpp @@ -17,9 +17,8 @@ // Editor #include "Include/IPlugin.h" - -using TPfnCreatePluginInstance = IPlugin *(*)(PLUGIN_INIT_PARAM *pInitParam); -using TPfnQueryPluginSettings = void (*)(SPluginSettings &); +using TPfnCreatePluginInstance = IPlugin* (*)(PLUGIN_INIT_PARAM* pInitParam); +using TPfnQueryPluginSettings = void (*)(SPluginSettings&); CPluginManager::CPluginManager() { @@ -155,7 +154,7 @@ bool CPluginManager::LoadPlugins(const char* pPathWithMask) } #endif } - if (plugins.size() == 0) + if (plugins.empty()) { CLogFile::FormatLine("[Plugin Manager] Cannot find any plugins in plugin directory '%s'", strPath.toUtf8().data()); return false; @@ -269,13 +268,13 @@ void CPluginManager::RegisterPlugin(QLibrary* dllHandle, IPlugin* pPlugin) IPlugin* CPluginManager::GetPluginByGUID(const char* pGUID) { - for (auto it = m_plugins.begin(); it != m_plugins.end(); ++it) + for (const SPluginEntry& pluginEntry : m_plugins) { - const char* pPluginGuid = it->pPlugin->GetPluginGUID(); + const char* pPluginGuid = pluginEntry.pPlugin->GetPluginGUID(); if (pPluginGuid && !strcmp(pPluginGuid, pGUID)) { - return it->pPlugin; + return pluginEntry.pPlugin; } } @@ -332,14 +331,11 @@ IUIEvent* CPluginManager::GetEventByIDAndPluginID(uint8 aPluginID, uint8 aEventI bool CPluginManager::CanAllPluginsExitNow() { - for (auto it = m_plugins.begin(); it != m_plugins.end(); ++it) + for (const SPluginEntry& pluginEntry : m_plugins) { - if (it->pPlugin) + if (pluginEntry.pPlugin && !pluginEntry.pPlugin->CanExitNow()) { - if (!it->pPlugin->CanExitNow()) - { - return false; - } + return false; } } diff --git a/Code/Editor/ResourceSelectorHost.cpp b/Code/Editor/ResourceSelectorHost.cpp index af6c398fe7..39d36346e7 100644 --- a/Code/Editor/ResourceSelectorHost.cpp +++ b/Code/Editor/ResourceSelectorHost.cpp @@ -75,11 +75,7 @@ public: void SetGlobalSelection(const char* resourceType, const char* value) override { - if (!resourceType) - { - return; - } - if (!value) + if (!resourceType || !value) { return; } @@ -101,7 +97,7 @@ public: } private: - using TTypeMap = std::map>; + using TTypeMap = std::map>; TTypeMap m_typeMap; std::map m_globallySelectedResources; From b21b0e12e402c8c63de01d16d51d4c223edf294b Mon Sep 17 00:00:00 2001 From: Cynthia Lin <15116870+synicalsyntax@users.noreply.github.com> Date: Mon, 9 Aug 2021 10:32:31 -0700 Subject: [PATCH 218/803] fix: Switch local environment detection to depend on BUILD_NUMBER instead of CI (#2962) CI is only available on Jenkins v2.289.1, nightly builds are still run on Jenkins 2.277.4 Signed-off-by: Cynthia Lin --- Tools/LyTestTools/ly_test_tools/benchmark/data_aggregator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tools/LyTestTools/ly_test_tools/benchmark/data_aggregator.py b/Tools/LyTestTools/ly_test_tools/benchmark/data_aggregator.py index b5b75508ec..12681450de 100644 --- a/Tools/LyTestTools/ly_test_tools/benchmark/data_aggregator.py +++ b/Tools/LyTestTools/ly_test_tools/benchmark/data_aggregator.py @@ -22,7 +22,7 @@ class BenchmarkDataAggregator(object): def __init__(self, workspace, logger, test_suite): self.build_dir = workspace.paths.build_directory() self.results_dir = Path(workspace.paths.project(), 'user/Scripts/PerformanceBenchmarks') - self.test_suite = test_suite if os.environ.get('CI') else 'local' + self.test_suite = test_suite if os.environ.get('BUILD_NUMBER') else 'local' self.filebeat_client = FilebeatClient(logger) def _update_pass(self, pass_stats, entry): From 6bf6ae948526d9fb6b4f0641fe95ae423c9c5452 Mon Sep 17 00:00:00 2001 From: Artur K <96597+nemerle@users.noreply.github.com> Date: Mon, 9 Aug 2021 20:06:29 +0200 Subject: [PATCH 219/803] Editor code: tidy up BOOLs,NULLs and overrides pt5. (#2876) A few 'typedefs' replaced by 'using's This shouldn't have any functional changes at all, just c++17 modernization It's a part 5 of a split #2847 Signed-off-by: Nemerle Co-authored-by: Nemerle --- Code/Editor/AboutDialog.cpp | 2 +- Code/Editor/AnimationContext.cpp | 14 ++--- Code/Editor/BaseLibrary.cpp | 22 +++---- Code/Editor/BaseLibraryItem.cpp | 20 +++---- Code/Editor/BaseLibraryManager.cpp | 42 +++++++------- Code/Editor/CheckOutDialog.h | 2 +- Code/Editor/ConfigGroup.cpp | 12 ++-- Code/Editor/ConfigGroup.h | 4 +- Code/Editor/ControlMRU.cpp | 10 ++-- Code/Editor/CrtDebug.cpp | 2 +- Code/Editor/CryEdit.cpp | 76 ++++++++++++------------- Code/Editor/CryEdit.h | 24 ++++---- Code/Editor/CryEditDoc.cpp | 66 ++++++++++----------- Code/Editor/CryEditDoc.h | 10 ++-- Code/Editor/CryEditPy.cpp | 2 +- Code/Editor/CustomAspectRatioDlg.cpp | 2 +- Code/Editor/CustomResolutionDlg.cpp | 8 +-- Code/Editor/CustomizeKeyboardDialog.cpp | 4 +- Code/Editor/EditorDefs.h | 7 +-- Code/Editor/EditorFileMonitor.cpp | 2 +- Code/Editor/EditorFileMonitor.h | 2 +- Code/Editor/EditorPanelUtils.cpp | 46 +++++++-------- Code/Editor/EditorPreferencesDialog.cpp | 2 +- Code/Editor/ErrorReport.cpp | 4 +- Code/Editor/ErrorReportDialog.cpp | 16 +++--- Code/Editor/ErrorReportTableModel.cpp | 2 +- Code/Editor/GameEngine.cpp | 32 +++++------ Code/Editor/GameExporter.cpp | 4 +- Code/Editor/GenericSelectItemDialog.cpp | 2 +- Code/Editor/IEditor.h | 4 +- Code/Editor/IEditorImpl.cpp | 28 ++++----- Code/Editor/IEditorImpl.h | 8 +-- Code/Editor/IconManager.cpp | 10 ++-- Code/Editor/LayoutConfigDialog.cpp | 2 +- Code/Editor/LayoutWnd.cpp | 4 +- 35 files changed, 248 insertions(+), 249 deletions(-) diff --git a/Code/Editor/AboutDialog.cpp b/Code/Editor/AboutDialog.cpp index 8429e86553..f8abe67376 100644 --- a/Code/Editor/AboutDialog.cpp +++ b/Code/Editor/AboutDialog.cpp @@ -25,7 +25,7 @@ AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING #include AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING -CAboutDialog::CAboutDialog(QString versionText, QString richTextCopyrightNotice, QWidget* pParent /*=NULL*/) +CAboutDialog::CAboutDialog(QString versionText, QString richTextCopyrightNotice, QWidget* pParent /*=nullptr*/) : QDialog(pParent) , m_ui(new Ui::CAboutDialog) { diff --git a/Code/Editor/AnimationContext.cpp b/Code/Editor/AnimationContext.cpp index d557a8635c..6e146faacb 100644 --- a/Code/Editor/AnimationContext.cpp +++ b/Code/Editor/AnimationContext.cpp @@ -28,7 +28,7 @@ class CMovieCallback : public IMovieCallback { protected: - virtual void OnMovieCallback(ECallbackReason reason, [[maybe_unused]] IAnimNode* pNode) + void OnMovieCallback(ECallbackReason reason, [[maybe_unused]] IAnimNode* pNode) override { switch (reason) { @@ -48,7 +48,7 @@ protected: } } - void OnSetCamera(const SCameraParams& Params) + void OnSetCamera(const SCameraParams& Params) override { // Only switch camera when in Play mode. GUID camObjId = GUID_NULL; @@ -69,14 +69,14 @@ protected: } }; - bool IsSequenceCamUsed() const + bool IsSequenceCamUsed() const override { if (gEnv->IsEditorGameMode() == true) { return true; } - if (GetIEditor()->GetViewManager() == NULL) + if (GetIEditor()->GetViewManager() == nullptr) { return false; } @@ -103,7 +103,7 @@ public: CAnimationContextPostRender(CAnimationContext* pAC) : m_pAC(pAC){} - void OnPostRender() const { assert(m_pAC); m_pAC->OnPostRender(); } + void OnPostRender() const override { assert(m_pAC); m_pAC->OnPostRender(); } protected: CAnimationContext* m_pAC; @@ -221,7 +221,7 @@ void CAnimationContext::SetSequence(CTrackViewSequence* sequence, bool force, bo m_pSequence->UnBindFromEditorObjects(); } m_pSequence = sequence; - + // Notify a new sequence was just selected. Maestro::EditorSequenceNotificationBus::Broadcast(&Maestro::EditorSequenceNotificationBus::Events::OnSequenceSelected, m_pSequence ? m_pSequence->GetSequenceComponentEntityId() : AZ::EntityId()); @@ -337,7 +337,7 @@ void CAnimationContext::OnSequenceActivated(AZ::EntityId entityId) { // Hang onto this because SetSequence() will reset it. float lastTime = m_mostRecentSequenceTime; - + SetSequence(sequence, false, false); // Restore the current time. diff --git a/Code/Editor/BaseLibrary.cpp b/Code/Editor/BaseLibrary.cpp index ee1c85756d..7c920a7f04 100644 --- a/Code/Editor/BaseLibrary.cpp +++ b/Code/Editor/BaseLibrary.cpp @@ -24,10 +24,10 @@ class CUndoBaseLibrary : public IUndoObject { public: - CUndoBaseLibrary(CBaseLibrary* pLib, const QString& description, const QString& selectedItem = 0) + CUndoBaseLibrary(CBaseLibrary* pLib, const QString& description, const QString& selectedItem = QString()) : m_pLib(pLib) , m_description(description) - , m_redo(0) + , m_redo(nullptr) , m_selectedItem(selectedItem) { assert(m_pLib); @@ -36,16 +36,16 @@ public: m_pLib->Serialize(m_undo, false); } - virtual QString GetEditorObjectName() + QString GetEditorObjectName() override { return m_selectedItem; } protected: - virtual int GetSize() { return sizeof(CUndoBaseLibrary); } - virtual QString GetDescription() { return m_description; }; + int GetSize() override { return sizeof(CUndoBaseLibrary); } + QString GetDescription() override { return m_description; }; - virtual void Undo(bool bUndo) + void Undo(bool bUndo) override { if (bUndo) { @@ -57,7 +57,7 @@ protected: GetIEditor()->Notify(eNotify_OnDataBaseUpdate); } - virtual void Redo() + void Redo() override { m_pLib->Serialize(m_redo, true); m_pLib->SetModified(); @@ -107,7 +107,7 @@ void CBaseLibrary::RemoveAllItems() // Unregister item in case it was registered. It is ok if it wasn't. This is still safe to call. m_pManager->UnregisterItem(m_items[i]); // Clear library item. - m_items[i]->m_library = NULL; + m_items[i]->m_library = nullptr; } m_items.clear(); Release(); @@ -216,7 +216,7 @@ IDataBaseItem* CBaseLibrary::FindItem(const QString& name) return m_items[i]; } } - return NULL; + return nullptr; } bool CBaseLibrary::AddLibraryToSourceControl(const QString& fullPathName) const @@ -233,8 +233,8 @@ bool CBaseLibrary::AddLibraryToSourceControl(const QString& fullPathName) const bool CBaseLibrary::SaveLibrary(const char* name, bool saveEmptyLibrary) { - assert(name != NULL); - if (name == NULL) + assert(name != nullptr); + if (name == nullptr) { CryFatalError("The library you are attempting to save has no name specified."); return false; diff --git a/Code/Editor/BaseLibraryItem.cpp b/Code/Editor/BaseLibraryItem.cpp index fd310eaf9f..252510c951 100644 --- a/Code/Editor/BaseLibraryItem.cpp +++ b/Code/Editor/BaseLibraryItem.cpp @@ -16,7 +16,7 @@ #include -//undo object for multi-changes inside library item. such as set all variables to default values. +//undo object for multi-changes inside library item. such as set all variables to default values. //For example: change particle emitter shape will lead to multiple variable changes class CUndoBaseLibraryItem : public IUndoObject @@ -54,24 +54,24 @@ public: } protected: - virtual int GetSize() - { + int GetSize() override + { return m_size; } QString GetDescription() override - { - return m_description; + { + return m_description; } - virtual void Undo(bool bUndo) + void Undo(bool bUndo) override { //find the libItem IDataBaseItem *libItem = m_libMgr->FindItemByName(m_itemPath); if (libItem == nullptr) { //the undo stack is not reliable any more.. - assert(false); + assert(false); return; } @@ -95,7 +95,7 @@ protected: libItem->Serialize(m_undoCtx); } - virtual void Redo() + void Redo() override { //find the libItem IDataBaseItem *libItem = m_libMgr->FindItemByName(m_itemPath); @@ -124,7 +124,7 @@ private: ////////////////////////////////////////////////////////////////////////// CBaseLibraryItem::CBaseLibraryItem() { - m_library = 0; + m_library = nullptr; GenerateId(); m_bModified = false; } @@ -266,7 +266,7 @@ void CBaseLibraryItem::SetLibrary(CBaseLibrary* pLibrary) void CBaseLibraryItem::SetModified(bool bModified) { m_bModified = bModified; - if (m_bModified && m_library != NULL) + if (m_bModified && m_library != nullptr) { m_library->SetModified(bModified); } diff --git a/Code/Editor/BaseLibraryManager.cpp b/Code/Editor/BaseLibraryManager.cpp index 8e555cae8c..6dd7dc58a5 100644 --- a/Code/Editor/BaseLibraryManager.cpp +++ b/Code/Editor/BaseLibraryManager.cpp @@ -26,7 +26,7 @@ class CUndoBaseLibraryManager : public IUndoObject { public: - CUndoBaseLibraryManager(CBaseLibraryManager* pMngr, const QString& description, const QString& modifiedManager = 0) + CUndoBaseLibraryManager(CBaseLibraryManager* pMngr, const QString& description, const QString& modifiedManager = nullptr) : m_pMngr(pMngr) , m_description(description) , m_editorObject(modifiedManager) @@ -35,16 +35,16 @@ public: SerializeTo(m_undos); } - virtual QString GetEditorObjectName() + QString GetEditorObjectName() override { return m_editorObject; } protected: - virtual int GetSize() { return sizeof(CUndoBaseLibraryManager); } - virtual QString GetDescription() { return m_description; }; + int GetSize() override { return sizeof(CUndoBaseLibraryManager); } + QString GetDescription() override { return m_description; }; - virtual void Undo(bool bUndo) + void Undo(bool bUndo) override { if (bUndo) { @@ -55,7 +55,7 @@ protected: GetIEditor()->Notify(eNotify_OnDataBaseUpdate); } - virtual void Redo() + void Redo() override { m_pMngr->ClearAll(); UnserializeFrom(m_redos); @@ -84,7 +84,7 @@ private: for (int i = 0; i < m_pMngr->GetLibraryCount(); i++) { IDataBaseLibrary* library = m_pMngr->GetLibrary(i); - + const char* tag = library->IsLevelLibrary() ? LEVEL_LIBRARY_TAG : LIBRARY_TAG; XmlNodeRef node = GetIEditor()->GetSystem()->CreateXmlNode(tag); QString file = library->GetFilename().isEmpty() ? library->GetFilename() : library->GetName(); @@ -203,7 +203,7 @@ int CBaseLibraryManager::FindLibraryIndex(const QString& library) ////////////////////////////////////////////////////////////////////////// IDataBaseItem* CBaseLibraryManager::FindItem(REFGUID guid) const { - CBaseLibraryItem* pMtl = stl::find_in_map(m_itemsGuidMap, guid, (CBaseLibraryItem*)0); + CBaseLibraryItem* pMtl = stl::find_in_map(m_itemsGuidMap, guid, nullptr); return pMtl; } @@ -226,7 +226,7 @@ void CBaseLibraryManager::SplitFullItemName(const QString& fullItemName, QString IDataBaseItem* CBaseLibraryManager::FindItemByName(const QString& fullItemName) { AZStd::lock_guard lock(m_itemsNameMapMutex); - return stl::find_in_map(m_itemsNameMap, fullItemName, 0); + return stl::find_in_map(m_itemsNameMap, fullItemName, nullptr); } ////////////////////////////////////////////////////////////////////////// @@ -398,7 +398,7 @@ void CBaseLibraryManager::DeleteLibrary(const QString& library, bool forceDelete UnregisterItem((CBaseLibraryItem*)pLibrary->GetItem(j)); } pLibrary->RemoveAllItems(); - + if (pLibrary->IsLevelLibrary()) { m_pLevelLibrary = nullptr; @@ -420,7 +420,7 @@ IDataBaseLibrary* CBaseLibraryManager::GetLibrary(int index) const ////////////////////////////////////////////////////////////////////////// IDataBaseLibrary* CBaseLibraryManager::GetLevelLibrary() const { - IDataBaseLibrary* pLevelLib = NULL; + IDataBaseLibrary* pLevelLib = nullptr; for (int i = 0; i < GetLibraryCount(); i++) { @@ -531,9 +531,9 @@ QString CBaseLibraryManager::MakeUniqueItemName(const QString& srcName, const QS // search for strings in the database that might have a similar name (ignore case) IDataBaseItemEnumerator* pEnum = GetItemEnumerator(); - for (IDataBaseItem* pItem = pEnum->GetFirst(); pItem != NULL; pItem = pEnum->GetNext()) + for (IDataBaseItem* pItem = pEnum->GetFirst(); pItem != nullptr; pItem = pEnum->GetNext()) { - //Check if the item is in the target library first. + //Check if the item is in the target library first. IDataBaseLibrary* itemLibrary = pItem->GetLibrary(); QString itemLibraryName; if (itemLibrary) @@ -590,7 +590,7 @@ QString CBaseLibraryManager::MakeUniqueItemName(const QString& srcName, const QS void CBaseLibraryManager::Validate() { IDataBaseItemEnumerator* pEnum = GetItemEnumerator(); - for (IDataBaseItem* pItem = pEnum->GetFirst(); pItem != NULL; pItem = pEnum->GetNext()) + for (IDataBaseItem* pItem = pEnum->GetFirst(); pItem != nullptr; pItem = pEnum->GetNext()) { pItem->Validate(); } @@ -617,7 +617,7 @@ void CBaseLibraryManager::RegisterItem(CBaseLibraryItem* pItem, REFGUID newGuid) { return; } - CBaseLibraryItem* pOldItem = stl::find_in_map(m_itemsGuidMap, newGuid, (CBaseLibraryItem*)0); + CBaseLibraryItem* pOldItem = stl::find_in_map(m_itemsGuidMap, newGuid, nullptr); if (!pOldItem) { pItem->m_guid = newGuid; @@ -677,7 +677,7 @@ void CBaseLibraryManager::RegisterItem(CBaseLibraryItem* pItem) { return; } - CBaseLibraryItem* pOldItem = stl::find_in_map(m_itemsGuidMap, pItem->GetGUID(), (CBaseLibraryItem*)0); + CBaseLibraryItem* pOldItem = stl::find_in_map(m_itemsGuidMap, pItem->GetGUID(), nullptr); if (!pOldItem) { m_itemsGuidMap[pItem->GetGUID()] = pItem; @@ -789,7 +789,7 @@ QString CBaseLibraryManager::MakeFullItemName(IDataBaseLibrary* pLibrary, const void CBaseLibraryManager::GatherUsedResources(CUsedResources& resources) { IDataBaseItemEnumerator* pEnum = GetItemEnumerator(); - for (IDataBaseItem* pItem = pEnum->GetFirst(); pItem != NULL; pItem = pEnum->GetNext()) + for (IDataBaseItem* pItem = pEnum->GetFirst(); pItem != nullptr; pItem = pEnum->GetNext()) { pItem->GatherUsedResources(resources); } @@ -815,15 +815,15 @@ void CBaseLibraryManager::OnEditorNotifyEvent(EEditorNotifyEvent event) switch (event) { case eNotify_OnBeginNewScene: - SetSelectedItem(0); + SetSelectedItem(nullptr); ClearAll(); break; case eNotify_OnBeginSceneOpen: - SetSelectedItem(0); + SetSelectedItem(nullptr); ClearAll(); break; case eNotify_OnCloseScene: - SetSelectedItem(0); + SetSelectedItem(nullptr); ClearAll(); break; } @@ -913,7 +913,7 @@ void CBaseLibraryManager::ChangeLibraryOrder(IDataBaseLibrary* lib, unsigned int { return; } - + for (int i = 0; i < m_libs.size(); i++) { if (lib == m_libs[i]) diff --git a/Code/Editor/CheckOutDialog.h b/Code/Editor/CheckOutDialog.h index 7e7054ccdf..9ad64c57cf 100644 --- a/Code/Editor/CheckOutDialog.h +++ b/Code/Editor/CheckOutDialog.h @@ -34,7 +34,7 @@ public: CANCEL = QDialog::Rejected }; - CCheckOutDialog(const QString& file, QWidget* pParent = NULL); // standard constructor + CCheckOutDialog(const QString& file, QWidget* pParent = nullptr); // standard constructor virtual ~CCheckOutDialog(); // Dialog Data diff --git a/Code/Editor/ConfigGroup.cpp b/Code/Editor/ConfigGroup.cpp index 4e61c38f4b..c1e0abbf31 100644 --- a/Code/Editor/ConfigGroup.cpp +++ b/Code/Editor/ConfigGroup.cpp @@ -48,7 +48,7 @@ namespace Config } } - return NULL; + return nullptr; } const IConfigVar* CConfigGroup::GetVar(const char* szName) const @@ -63,7 +63,7 @@ namespace Config } } - return NULL; + return nullptr; } IConfigVar* CConfigGroup::GetVar(uint index) @@ -73,7 +73,7 @@ namespace Config return m_vars[index]; } - return NULL; + return nullptr; } const IConfigVar* CConfigGroup::GetVar(uint index) const @@ -83,7 +83,7 @@ namespace Config return m_vars[index]; } - return NULL; + return nullptr; } void CConfigGroup::SaveToXML(XmlNodeRef node) @@ -127,7 +127,7 @@ namespace Config case IConfigVar::eType_STRING: { - string currentValue = 0; + string currentValue = nullptr; var->Get(¤tValue); node->setAttr(szName, currentValue); break; @@ -186,7 +186,7 @@ namespace Config case IConfigVar::eType_STRING: { - string currentValue = 0; + string currentValue = nullptr; var->GetDefault(¤tValue); QString readValue(currentValue.c_str()); if (node->getAttr(szName, readValue)) diff --git a/Code/Editor/ConfigGroup.h b/Code/Editor/ConfigGroup.h index 35c0b8e47f..f772823ad8 100644 --- a/Code/Editor/ConfigGroup.h +++ b/Code/Editor/ConfigGroup.h @@ -37,11 +37,11 @@ namespace Config , m_description(szDescription) , m_type(varType) , m_flags(flags) - , m_ptr(NULL) + , m_ptr(nullptr) {}; virtual ~IConfigVar() = default; - + ILINE EType GetType() const { return m_type; diff --git a/Code/Editor/ControlMRU.cpp b/Code/Editor/ControlMRU.cpp index 47de13950f..a721876624 100644 --- a/Code/Editor/ControlMRU.cpp +++ b/Code/Editor/ControlMRU.cpp @@ -28,7 +28,7 @@ void CControlMRU::OnCalcDynamicSize(DWORD dwMode) CString* pArrNames = pRecentFileList->m_arrNames; - assert(pArrNames != NULL); + assert(pArrNames != nullptr); if (!pArrNames) { return; @@ -52,7 +52,7 @@ void CControlMRU::OnCalcDynamicSize(DWORD dwMode) if (m_pParent->IsCustomizeMode()) { m_dwHideFlags = 0; - SetEnabled(TRUE); + SetEnabled(true); return; } @@ -61,7 +61,7 @@ void CControlMRU::OnCalcDynamicSize(DWORD dwMode) SetCaption(CString(MAKEINTRESOURCE(IDS_NORECENTFILE_CAPTION))); SetDescription("No recently opened files"); m_dwHideFlags = 0; - SetEnabled(FALSE); + SetEnabled(false); return; } @@ -105,7 +105,7 @@ void CControlMRU::OnCalcDynamicSize(DWORD dwMode) int nId = iMRU + GetFirstMruID(); - CXTPControl* pControl = m_pControls->Add(xtpControlButton, nId, _T(""), m_nIndex + iLastValidMRU + 1, TRUE); + CXTPControl* pControl = m_pControls->Add(xtpControlButton, nId, _T(""), m_nIndex + iLastValidMRU + 1, true); assert(pControl); pControl->SetCaption(CXTPControlWindowList::ConstructCaption(strName, iLastValidMRU + 1)); @@ -130,6 +130,6 @@ void CControlMRU::OnCalcDynamicSize(DWORD dwMode) SetCaption(CString(MAKEINTRESOURCE(IDS_NORECENTFILE_CAPTION))); SetDescription("No recently opened files"); m_dwHideFlags = 0; - SetEnabled(FALSE); + SetEnabled(false); } } diff --git a/Code/Editor/CrtDebug.cpp b/Code/Editor/CrtDebug.cpp index a37b3d26e9..f9335373da 100644 --- a/Code/Editor/CrtDebug.cpp +++ b/Code/Editor/CrtDebug.cpp @@ -62,7 +62,7 @@ int crtAllocHook(int nAllocType, void* pvData, { if (nBlockUse == _CRT_BLOCK) { - return(TRUE); + return TRUE; } static int total_cnt = 0; diff --git a/Code/Editor/CryEdit.cpp b/Code/Editor/CryEdit.cpp index ae03b03af5..8cede89f8a 100644 --- a/Code/Editor/CryEdit.cpp +++ b/Code/Editor/CryEdit.cpp @@ -266,13 +266,13 @@ CCrySingleDocTemplate* CCryDocManager::SetDefaultTemplate(CCrySingleDocTemplate* // Copied from MFC to get rid of the silly ugly unoverridable doc-type pick dialog void CCryDocManager::OnFileNew() { - assert(m_pDefTemplate != NULL); + assert(m_pDefTemplate != nullptr); - m_pDefTemplate->OpenDocumentFile(NULL); + m_pDefTemplate->OpenDocumentFile(nullptr); // if returns NULL, the user has already been alerted } -BOOL CCryDocManager::DoPromptFileName(QString& fileName, [[maybe_unused]] UINT nIDSTitle, - [[maybe_unused]] DWORD lFlags, BOOL bOpenFileDialog, [[maybe_unused]] CDocTemplate* pTemplate) +bool CCryDocManager::DoPromptFileName(QString& fileName, [[maybe_unused]] UINT nIDSTitle, + [[maybe_unused]] DWORD lFlags, bool bOpenFileDialog, [[maybe_unused]] CDocTemplate* pTemplate) { CLevelFileDialog levelFileDialog(bOpenFileDialog); levelFileDialog.show(); @@ -286,15 +286,15 @@ BOOL CCryDocManager::DoPromptFileName(QString& fileName, [[maybe_unused]] UINT n return false; } -CCryEditDoc* CCryDocManager::OpenDocumentFile(LPCTSTR lpszFileName, BOOL bAddToMRU) +CCryEditDoc* CCryDocManager::OpenDocumentFile(LPCTSTR lpszFileName, bool bAddToMRU) { - assert(lpszFileName != NULL); + assert(lpszFileName != nullptr); // find the highest confidence auto pos = m_templateList.begin(); CCrySingleDocTemplate::Confidence bestMatch = CCrySingleDocTemplate::noAttempt; - CCrySingleDocTemplate* pBestTemplate = NULL; - CCryEditDoc* pOpenDocument = NULL; + CCrySingleDocTemplate* pBestTemplate = nullptr; + CCryEditDoc* pOpenDocument = nullptr; if (lpszFileName[0] == '\"') { @@ -311,7 +311,7 @@ CCryEditDoc* CCryDocManager::OpenDocumentFile(LPCTSTR lpszFileName, BOOL bAddToM auto pTemplate = *(pos++); CCrySingleDocTemplate::Confidence match; - assert(pOpenDocument == NULL); + assert(pOpenDocument == nullptr); match = pTemplate->MatchDocType(szPath.toUtf8().data(), pOpenDocument); if (match > bestMatch) { @@ -324,18 +324,18 @@ CCryEditDoc* CCryDocManager::OpenDocumentFile(LPCTSTR lpszFileName, BOOL bAddToM } } - if (pOpenDocument != NULL) + if (pOpenDocument != nullptr) { return pOpenDocument; } - if (pBestTemplate == NULL) + if (pBestTemplate == nullptr) { QMessageBox::critical(AzToolsFramework::GetActiveWindow(), QString(), QObject::tr("Failed to open document.")); - return NULL; + return nullptr; } - return pBestTemplate->OpenDocumentFile(szPath.toUtf8().data(), bAddToMRU, FALSE); + return pBestTemplate->OpenDocumentFile(szPath.toUtf8().data(), bAddToMRU, false); } ////////////////////////////////////////////////////////////////////////////// @@ -460,7 +460,7 @@ void CCryEditApp::RegisterActionHandlers() ON_COMMAND(ID_FILE_SAVE_LEVEL, OnFileSave) ON_COMMAND(ID_FILE_EXPORTOCCLUSIONMESH, OnFileExportOcclusionMesh) - // Project Manager + // Project Manager ON_COMMAND(ID_FILE_PROJECT_MANAGER_SETTINGS, OnOpenProjectManagerSettings) ON_COMMAND(ID_FILE_PROJECT_MANAGER_NEW, OnOpenProjectManagerNew) ON_COMMAND(ID_FILE_PROJECT_MANAGER_OPEN, OnOpenProjectManager) @@ -653,7 +653,7 @@ struct SharedData // // This function uses a technique similar to that described in KB // article Q141752 to locate the previous instance of the application. . -BOOL CCryEditApp::FirstInstance(bool bForceNewInstance) +bool CCryEditApp::FirstInstance(bool bForceNewInstance) { QSystemSemaphore sem(QString(O3DEApplicationName) + "_sem", 1); sem.acquire(); @@ -801,12 +801,12 @@ void CCryEditApp::InitDirectory() // Needed to work with custom memory manager. ////////////////////////////////////////////////////////////////////////// -CCryEditDoc* CCrySingleDocTemplate::OpenDocumentFile(LPCTSTR lpszPathName, BOOL bMakeVisible /*= true*/) +CCryEditDoc* CCrySingleDocTemplate::OpenDocumentFile(LPCTSTR lpszPathName, bool bMakeVisible /*= true*/) { return OpenDocumentFile(lpszPathName, true, bMakeVisible); } -CCryEditDoc* CCrySingleDocTemplate::OpenDocumentFile(LPCTSTR lpszPathName, BOOL bAddToMRU, [[maybe_unused]] BOOL bMakeVisible) +CCryEditDoc* CCrySingleDocTemplate::OpenDocumentFile(LPCTSTR lpszPathName, bool bAddToMRU, [[maybe_unused]] bool bMakeVisible) { CCryEditDoc* pCurDoc = GetIEditor()->GetDocument(); @@ -847,8 +847,8 @@ CCryEditDoc* CCrySingleDocTemplate::OpenDocumentFile(LPCTSTR lpszPathName, BOOL CCrySingleDocTemplate::Confidence CCrySingleDocTemplate::MatchDocType(LPCTSTR lpszPathName, CCryEditDoc*& rpDocMatch) { - assert(lpszPathName != NULL); - rpDocMatch = NULL; + assert(lpszPathName != nullptr); + rpDocMatch = nullptr; // go through all documents CCryEditDoc* pDoc = GetIEditor()->GetDocument(); @@ -1055,7 +1055,7 @@ AZ::Outcome CCryEditApp::InitGameSystem(HWND hwndForInputSy } ///////////////////////////////////////////////////////////////////////////// -BOOL CCryEditApp::CheckIfAlreadyRunning() +bool CCryEditApp::CheckIfAlreadyRunning() { bool bForceNewInstance = false; @@ -1299,7 +1299,7 @@ void CCryEditApp::InitLevel(const CEditCommandLineInfo& cmdInfo) } ///////////////////////////////////////////////////////////////////////////// -BOOL CCryEditApp::InitConsole() +bool CCryEditApp::InitConsole() { // Execute command from cmdline -exec_line if applicable if (!m_execLineCmd.isEmpty()) @@ -1431,7 +1431,7 @@ struct CCryEditApp::PythonOutputHandler AzToolsFramework::EditorPythonConsoleNotificationBus::Handler::BusConnect(); } - virtual ~PythonOutputHandler() + ~PythonOutputHandler() override { AzToolsFramework::EditorPythonConsoleNotificationBus::Handler::BusDisconnect(); } @@ -1463,7 +1463,7 @@ struct PythonTestOutputHandler final : public CCryEditApp::PythonOutputHandler { PythonTestOutputHandler() = default; - virtual ~PythonTestOutputHandler() = default; + ~PythonTestOutputHandler() override = default; void OnTraceMessage(AZStd::string_view message) override { @@ -1589,7 +1589,7 @@ void CCryEditApp::RunInitPythonScript(CEditCommandLineInfo& cmdInfo) ///////////////////////////////////////////////////////////////////////////// // CCryEditApp initialization -BOOL CCryEditApp::InitInstance() +bool CCryEditApp::InitInstance() { QElapsedTimer startupTimer; startupTimer.start(); @@ -1616,7 +1616,7 @@ BOOL CCryEditApp::InitInstance() { CAboutDialog aboutDlg(FormatVersion(m_pEditor->GetFileVersion()), FormatRichTextCopyrightNotice()); aboutDlg.exec(); - return FALSE; + return false; } // Reflect property control classes to the serialize context... @@ -1759,7 +1759,7 @@ BOOL CCryEditApp::InitInstance() } } - SetEditorWindowTitle(0, AZ::Utils::GetProjectName().c_str(), 0); + SetEditorWindowTitle(nullptr, AZ::Utils::GetProjectName().c_str(), nullptr); if (!GetIEditor()->IsInMatEditMode()) { m_pEditor->InitFinished(); @@ -1844,8 +1844,8 @@ void CCryEditApp::RegisterEventLoopHook(IEventLoopHook* pHook) void CCryEditApp::UnregisterEventLoopHook(IEventLoopHook* pHookToRemove) { - IEventLoopHook* pPrevious = 0; - for (IEventLoopHook* pHook = m_pEventLoopHook; pHook != 0; pHook = pHook->pNextHook) + IEventLoopHook* pPrevious = nullptr; + for (IEventLoopHook* pHook = m_pEventLoopHook; pHook != nullptr; pHook = pHook->pNextHook) { if (pHook == pHookToRemove) { @@ -1858,7 +1858,7 @@ void CCryEditApp::UnregisterEventLoopHook(IEventLoopHook* pHookToRemove) m_pEventLoopHook = pHookToRemove->pNextHook; } - pHookToRemove->pNextHook = 0; + pHookToRemove->pNextHook = nullptr; return; } } @@ -1881,7 +1881,7 @@ void CCryEditApp::LoadFile(QString fileName) if (MainWindow::instance() || m_pConsoleDialog) { - SetEditorWindowTitle(0, AZ::Utils::GetProjectName().c_str(), GetIEditor()->GetGameEngine()->GetLevelName()); + SetEditorWindowTitle(nullptr, AZ::Utils::GetProjectName().c_str(), GetIEditor()->GetGameEngine()->GetLevelName()); } GetIEditor()->SetModifiedFlag(false); @@ -1922,7 +1922,7 @@ void CCryEditApp::EnableAccelerator([[maybe_unused]] bool bEnable) CMainFrame *mainFrame = (CMainFrame*)m_pMainWnd; if (mainFrame->m_hAccelTable) DestroyAcceleratorTable( mainFrame->m_hAccelTable ); - mainFrame->m_hAccelTable = NULL; + mainFrame->m_hAccelTable = nullptr; mainFrame->LoadAccelTable( MAKEINTRESOURCE(IDR_GAMEACCELERATOR) ); CLogFile::WriteLine( "Disable Accelerators" ); } @@ -2259,7 +2259,7 @@ void CCryEditApp::EnableIdleProcessing() AZ_Assert(m_disableIdleProcessingCounter >= 0, "m_disableIdleProcessingCounter must be nonnegative"); } -BOOL CCryEditApp::OnIdle([[maybe_unused]] LONG lCount) +bool CCryEditApp::OnIdle([[maybe_unused]] LONG lCount) { if (0 == m_disableIdleProcessingCounter) { @@ -2267,7 +2267,7 @@ BOOL CCryEditApp::OnIdle([[maybe_unused]] LONG lCount) } else { - return 0; + return false; } } @@ -3142,7 +3142,7 @@ void CCryEditApp::OnCreateLevel() ////////////////////////////////////////////////////////////////////////// bool CCryEditApp::CreateLevel(bool& wasCreateLevelOperationCancelled) { - BOOL bIsDocModified = GetIEditor()->GetDocument()->IsModified(); + bool bIsDocModified = GetIEditor()->GetDocument()->IsModified(); if (GetIEditor()->GetDocument()->IsDocumentReady() && bIsDocModified) { QString str = QObject::tr("Level %1 has been changed. Save Level?").arg(GetIEditor()->GetGameEngine()->GetLevelName()); @@ -3230,11 +3230,11 @@ bool CCryEditApp::CreateLevel(bool& wasCreateLevelOperationCancelled) #ifdef WIN32 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, + nullptr, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), windowsErrorMessage.data(), - windowsErrorMessage.length(), NULL); + windowsErrorMessage.length(), nullptr); _getcwd(cwd.data(), cwd.length()); #else windowsErrorMessage = strerror(dw); @@ -3759,7 +3759,7 @@ bool CCryEditApp::IsInRegularEditorMode() void CCryEditApp::OnOpenQuickAccessBar() { - if (m_pQuickAccessBar == NULL) + if (m_pQuickAccessBar == nullptr) { return; } @@ -4107,7 +4107,7 @@ extern "C" int AZ_DLL_EXPORT CryEditMain(int argc, char* argv[]) int exitCode = 0; - BOOL didCryEditStart = CCryEditApp::instance()->InitInstance(); + bool didCryEditStart = CCryEditApp::instance()->InitInstance(); AZ_Error("Editor", didCryEditStart, "O3DE Editor did not initialize correctly, and will close." "\nThis could be because of incorrectly configured components, or missing required gems." "\nSee other errors for more details."); diff --git a/Code/Editor/CryEdit.h b/Code/Editor/CryEdit.h index 9406b37ea2..9e3dfc98ff 100644 --- a/Code/Editor/CryEdit.h +++ b/Code/Editor/CryEdit.h @@ -135,16 +135,16 @@ public: virtual void AddToRecentFileList(const QString& lpszPathName); ECreateLevelResult CreateLevel(const QString& levelName, QString& fullyQualifiedLevelName); static void InitDirectory(); - BOOL FirstInstance(bool bForceNewInstance = false); + bool FirstInstance(bool bForceNewInstance = false); void InitFromCommandLine(CEditCommandLineInfo& cmdInfo); - BOOL CheckIfAlreadyRunning(); + bool CheckIfAlreadyRunning(); //! @return successful outcome if initialization succeeded. or failed outcome with error message. AZ::Outcome InitGameSystem(HWND hwndForInputSystem); void CreateSplashScreen(); void InitPlugins(); bool InitGame(); - BOOL InitConsole(); + bool InitConsole(); int IdleProcessing(bool bBackground); bool IsWindowInForeground(); void RunInitPythonScript(CEditCommandLineInfo& cmdInfo); @@ -171,9 +171,9 @@ public: // Overrides // ClassWizard generated virtual function overrides public: - virtual BOOL InitInstance(); + virtual bool InitInstance(); virtual int ExitInstance(int exitCode = 0); - virtual BOOL OnIdle(LONG lCount); + virtual bool OnIdle(LONG lCount); virtual CCryEditDoc* OpenDocumentFile(LPCTSTR lpszFileName); CCryDocManager* GetDocManager() { return m_pDocManager; } @@ -347,7 +347,7 @@ private: // Disable warning for dll export since this member won't be used outside this class AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING AZ::IO::FileDescriptorRedirector m_stdoutRedirection = AZ::IO::FileDescriptorRedirector(1); // < 1 for STDOUT -AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING +AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING private: static inline constexpr const char* DefaultLevelTemplateName = "Prefabs/Default_Level.prefab"; @@ -420,7 +420,7 @@ public: }; ////////////////////////////////////////////////////////////////////////// -class CCrySingleDocTemplate +class CCrySingleDocTemplate : public QObject { private: @@ -448,8 +448,8 @@ public: ~CCrySingleDocTemplate() {}; // avoid creating another CMainFrame // close other type docs before opening any things - virtual CCryEditDoc* OpenDocumentFile(LPCTSTR lpszPathName, BOOL bAddToMRU, BOOL bMakeVisible); - virtual CCryEditDoc* OpenDocumentFile(LPCTSTR lpszPathName, BOOL bMakeVisible = TRUE); + virtual CCryEditDoc* OpenDocumentFile(LPCTSTR lpszPathName, bool bAddToMRU, bool bMakeVisible); + virtual CCryEditDoc* OpenDocumentFile(LPCTSTR lpszPathName, bool bMakeVisible = true); virtual Confidence MatchDocType(LPCTSTR lpszPathName, CCryEditDoc*& rpDocMatch); private: @@ -465,9 +465,9 @@ public: CCrySingleDocTemplate* SetDefaultTemplate(CCrySingleDocTemplate* pNew); // Copied from MFC to get rid of the silly ugly unoverridable doc-type pick dialog virtual void OnFileNew(); - virtual BOOL DoPromptFileName(QString& fileName, UINT nIDSTitle, - DWORD lFlags, BOOL bOpenFileDialog, CDocTemplate* pTemplate); - virtual CCryEditDoc* OpenDocumentFile(LPCTSTR lpszFileName, BOOL bAddToMRU); + virtual bool DoPromptFileName(QString& fileName, UINT nIDSTitle, + DWORD lFlags, bool bOpenFileDialog, CDocTemplate* pTemplate); + virtual CCryEditDoc* OpenDocumentFile(LPCTSTR lpszFileName, bool bAddToMRU); QVector m_templateList; }; diff --git a/Code/Editor/CryEditDoc.cpp b/Code/Editor/CryEditDoc.cpp index 56b617969e..e372baf365 100644 --- a/Code/Editor/CryEditDoc.cpp +++ b/Code/Editor/CryEditDoc.cpp @@ -97,7 +97,7 @@ namespace Internal { bool SaveLevel() { - if (!GetIEditor()->GetDocument()->DoSave(GetIEditor()->GetDocument()->GetActivePathName(), TRUE)) + if (!GetIEditor()->GetDocument()->DoSave(GetIEditor()->GetDocument()->GetActivePathName(), true)) { return false; } @@ -263,7 +263,7 @@ void CCryEditDoc::DeleteContents() GetIEditor()->GetObjectManager()->DeleteAllObjects(); // Load scripts data - SetModifiedFlag(FALSE); + SetModifiedFlag(false); SetModifiedModules(eModifiedNothing); // Clear error reports if open. CErrorReportDialog::Clear(); @@ -305,7 +305,7 @@ void CCryEditDoc::Save(TDocMultiArchive& arrXmlAr) { CAutoDocNotReady autoDocNotReady; - if (arrXmlAr[DMAS_GENERAL] != NULL) + if (arrXmlAr[DMAS_GENERAL] != nullptr) { (*arrXmlAr[DMAS_GENERAL]).root = XmlHelpers::CreateXmlNode("Level"); (*arrXmlAr[DMAS_GENERAL]).root->setAttr("WaterColor", m_waterColor); @@ -483,7 +483,7 @@ void CCryEditDoc::Load(TDocMultiArchive& arrXmlAr, const QString& szFilename) if (!pObj) { - pObj = GetIEditor()->GetObjectManager()->NewObject("SequenceObject", 0, fullname); + pObj = GetIEditor()->GetObjectManager()->NewObject("SequenceObject", nullptr, fullname); } } } @@ -667,7 +667,7 @@ int CCryEditDoc::GetModifiedModule() return m_modifiedModuleFlags; } -BOOL CCryEditDoc::CanCloseFrame() +bool CCryEditDoc::CanCloseFrame() { // Ask the base class to ask for saving, which also includes the save // status of the plugins. Additionaly we query if all the plugins can exit @@ -676,21 +676,21 @@ BOOL CCryEditDoc::CanCloseFrame() // are not serialized in the project file if (!SaveModified()) { - return FALSE; + return false; } if (!GetIEditor()->GetPluginManager()->CanAllPluginsExitNow()) { - return FALSE; + return false; } // If there is an export in process, exiting will corrupt it if (CGameExporter::GetCurrentExporter() != nullptr) { - return FALSE; + return false; } - return TRUE; + return true; } bool CCryEditDoc::SaveModified() @@ -735,7 +735,7 @@ bool CCryEditDoc::OnOpenDocument(const QString& lpszPathName) TOpenDocContext context; if (!BeforeOpenDocument(lpszPathName, context)) { - return FALSE; + return false; } return DoOpenDocument(context); } @@ -778,7 +778,7 @@ bool CCryEditDoc::BeforeOpenDocument(const QString& lpszPathName, TOpenDocContex context.absoluteLevelPath = absolutePath; context.absoluteSlicePath = ""; } - return TRUE; + return true; } bool CCryEditDoc::DoOpenDocument(TOpenDocContext& context) @@ -815,7 +815,7 @@ bool CCryEditDoc::DoOpenDocument(TOpenDocContext& context) if (!LoadXmlArchiveArray(arrXmlAr, levelFilePath, levelFolderAbsolutePath)) { m_bLoadFailed = true; - return FALSE; + return false; } } if (!LoadLevel(arrXmlAr, context.absoluteLevelPath)) @@ -827,7 +827,7 @@ bool CCryEditDoc::DoOpenDocument(TOpenDocContext& context) if (m_bLoadFailed) { - return FALSE; + return false; } // Load AZ entities for the editor. @@ -848,7 +848,7 @@ bool CCryEditDoc::DoOpenDocument(TOpenDocContext& context) if (m_bLoadFailed) { - return FALSE; + return false; } StartStreamingLoad(); @@ -865,7 +865,7 @@ bool CCryEditDoc::DoOpenDocument(TOpenDocContext& context) // level. SetLevelExported(true); - return TRUE; + return true; } bool CCryEditDoc::OnNewDocument() @@ -961,7 +961,7 @@ bool CCryEditDoc::BeforeSaveDocument(const QString& lpszPathName, TSaveDocContex bool bSaved(true); context.bSaved = bSaved; - return TRUE; + return true; } bool CCryEditDoc::HasLayerNameConflicts() const @@ -1046,7 +1046,7 @@ bool CCryEditDoc::AfterSaveDocument([[maybe_unused]] const QString& lpszPathName else { CLogFile::WriteLine("$3Document successfully saved"); - SetModifiedFlag(FALSE); + SetModifiedFlag(false); SetModifiedModules(eModifiedNothing); MainWindow::instance()->ResetAutoSaveTimers(); } @@ -1598,7 +1598,7 @@ bool CCryEditDoc::LoadLevel(TDocMultiArchive& arrXmlAr, const QString& absoluteC // Set level path directly *after* DeleteContents(), since that will unload the previous level and clear the level path. GetIEditor()->GetGameEngine()->SetLevelPath(folderPath); - SetModifiedFlag(TRUE); // dirty during de-serialize + SetModifiedFlag(true); // dirty during de-serialize SetModifiedModules(eModifiedAll); Load(arrXmlAr, absoluteCryFilePath); @@ -1608,7 +1608,7 @@ bool CCryEditDoc::LoadLevel(TDocMultiArchive& arrXmlAr, const QString& absoluteC { pIPak->GetResourceList(AZ::IO::IArchive::RFOM_NextLevel)->Clear(); } - SetModifiedFlag(FALSE); // start off with unmodified + SetModifiedFlag(false); // start off with unmodified SetModifiedModules(eModifiedNothing); SetDocumentReady(true); GetIEditor()->Notify(eNotify_OnEndLoad); @@ -1984,7 +1984,7 @@ void CCryEditDoc::OnStartLevelResourceList() gEnv->pCryPak->GetResourceList(AZ::IO::IArchive::RFOM_Level)->Clear(); } -BOOL CCryEditDoc::DoFileSave() +bool CCryEditDoc::DoFileSave() { if (GetEditMode() == CCryEditDoc::DocumentEditingMode::LevelEdit) { @@ -2002,15 +2002,15 @@ BOOL CCryEditDoc::DoFileSave() QString newLevelPath = filename.left(filename.lastIndexOf('/') + 1); GetIEditor()->GetDocument()->SetPathName(filename); GetIEditor()->GetGameEngine()->SetLevelPath(newLevelPath); - return TRUE; + return true; } } - return FALSE; + return false; } } if (!IsDocumentReady()) { - return FALSE; + return false; } return Internal::SaveLevel(); @@ -2065,7 +2065,7 @@ void CCryEditDoc::InitEmptyLevel(int /*resolution*/, int /*unitSize*/, bool /*bU GetISystem()->GetISystemEventDispatcher()->OnSystemEvent(ESYSTEM_EVENT_LEVEL_LOAD_END, 0, 0); GetIEditor()->Notify(eNotify_OnEndNewScene); - SetModifiedFlag(FALSE); + SetModifiedFlag(false); SetLevelExported(false); SetModifiedModules(eModifiedNothing); @@ -2079,13 +2079,13 @@ void CCryEditDoc::CreateDefaultLevelAssets([[maybe_unused]] int resolution, [[ma void CCryEditDoc::OnEnvironmentPropertyChanged(IVariable* pVar) { - if (pVar == NULL) + if (pVar == nullptr) { return; } XmlNodeRef node = GetEnvironmentTemplate(); - if (node == NULL) + if (node == nullptr) { return; } @@ -2103,7 +2103,7 @@ void CCryEditDoc::OnEnvironmentPropertyChanged(IVariable* pVar) XmlNodeRef groupNode = node->getChild(nGroup); - if (groupNode == NULL) + if (groupNode == nullptr) { return; } @@ -2114,7 +2114,7 @@ void CCryEditDoc::OnEnvironmentPropertyChanged(IVariable* pVar) } XmlNodeRef childNode = groupNode->getChild(nChild); - if (childNode == NULL) + if (childNode == nullptr) { return; } @@ -2141,7 +2141,7 @@ QString CCryEditDoc::GetCryIndexPath(const LPCTSTR levelFilePath) const return Path::AddPathSlash(levelPath + levelName + "_editor"); } -BOOL CCryEditDoc::LoadXmlArchiveArray(TDocMultiArchive& arrXmlAr, const QString& absoluteLevelPath, const QString& levelPath) +bool CCryEditDoc::LoadXmlArchiveArray(TDocMultiArchive& arrXmlAr, const QString& absoluteLevelPath, const QString& levelPath) { auto pIPak = GetIEditor()->GetSystem()->GetIPak(); @@ -2150,7 +2150,7 @@ BOOL CCryEditDoc::LoadXmlArchiveArray(TDocMultiArchive& arrXmlAr, const QString& CXmlArchive* pXmlAr = new CXmlArchive(); if (!pXmlAr) { - return FALSE; + return false; } CXmlArchive& xmlAr = *pXmlAr; @@ -2161,7 +2161,7 @@ BOOL CCryEditDoc::LoadXmlArchiveArray(TDocMultiArchive& arrXmlAr, const QString& bool openLevelPakFileSuccess = pIPak->OpenPack(levelPath.toUtf8().data(), absoluteLevelPath.toUtf8().data()); if (!openLevelPakFileSuccess) { - return FALSE; + return false; } CPakFile pakFile; @@ -2169,13 +2169,13 @@ BOOL CCryEditDoc::LoadXmlArchiveArray(TDocMultiArchive& arrXmlAr, const QString& pIPak->ClosePack(absoluteLevelPath.toUtf8().data()); if (!loadFromPakSuccess) { - return FALSE; + return false; } FillXmlArArray(arrXmlAr, &xmlAr); } - return TRUE; + return true; } void CCryEditDoc::ReleaseXmlArchiveArray(TDocMultiArchive& arrXmlAr) diff --git a/Code/Editor/CryEditDoc.h b/Code/Editor/CryEditDoc.h index d32e8e5bb1..a5b3334818 100644 --- a/Code/Editor/CryEditDoc.h +++ b/Code/Editor/CryEditDoc.h @@ -26,7 +26,7 @@ struct ICVar; // Filename of the temporary file used for the hold / fetch operation // conform to the "$tmp[0-9]_" naming convention -#define HOLD_FETCH_FILE "$tmp_hold" +#define HOLD_FETCH_FILE "$tmp_hold" class CCryEditDoc : public QObject @@ -36,7 +36,7 @@ class CCryEditDoc Q_PROPERTY(bool modified READ IsModified WRITE SetModifiedFlag); Q_PROPERTY(QString pathName READ GetLevelPathName WRITE SetPathName); Q_PROPERTY(QString title READ GetTitle WRITE SetTitle); - + public: // Create from serialization only enum DocumentEditingMode { @@ -82,7 +82,7 @@ public: // Create from serialization only bool DoSave(const QString& pathName, bool replace); SANDBOX_API bool Save(); - virtual BOOL DoFileSave(); + virtual bool DoFileSave(); bool SaveModified(); virtual bool BackupBeforeSave(bool bForce = false); @@ -102,7 +102,7 @@ public: // Create from serialization only bool IsLevelExported() const; void SetLevelExported(bool boExported = true); - BOOL CanCloseFrame(); + bool CanCloseFrame(); enum class FetchPolicy { @@ -144,7 +144,7 @@ protected: }; bool BeforeOpenDocument(const QString& lpszPathName, TOpenDocContext& context); bool DoOpenDocument(TOpenDocContext& context); - virtual BOOL LoadXmlArchiveArray(TDocMultiArchive& arrXmlAr, const QString& absoluteLevelPath, const QString& levelPath); + virtual bool LoadXmlArchiveArray(TDocMultiArchive& arrXmlAr, const QString& absoluteLevelPath, const QString& levelPath); virtual void ReleaseXmlArchiveArray(TDocMultiArchive& arrXmlAr); virtual void Load(TDocMultiArchive& arrXmlAr, const QString& szFilename); diff --git a/Code/Editor/CryEditPy.cpp b/Code/Editor/CryEditPy.cpp index e65af3a19b..21d2dcced9 100644 --- a/Code/Editor/CryEditPy.cpp +++ b/Code/Editor/CryEditPy.cpp @@ -359,7 +359,7 @@ namespace { AZ::TickBus::Handler::BusConnect(); } - ~Ticker() + ~Ticker() override { AZ::TickBus::Handler::BusDisconnect(); } diff --git a/Code/Editor/CustomAspectRatioDlg.cpp b/Code/Editor/CustomAspectRatioDlg.cpp index 16f50601d1..f24ff9ccdb 100644 --- a/Code/Editor/CustomAspectRatioDlg.cpp +++ b/Code/Editor/CustomAspectRatioDlg.cpp @@ -22,7 +22,7 @@ AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING #define MIN_ASPECT 1 #define MAX_ASPECT 16384 -CCustomAspectRatioDlg::CCustomAspectRatioDlg(int x, int y, QWidget* pParent /*=NULL*/) +CCustomAspectRatioDlg::CCustomAspectRatioDlg(int x, int y, QWidget* pParent /*=nullptr*/) : QDialog(pParent) , m_xDefault(x) , m_yDefault(y) diff --git a/Code/Editor/CustomResolutionDlg.cpp b/Code/Editor/CustomResolutionDlg.cpp index b970b80fe7..9e0e11e2e4 100644 --- a/Code/Editor/CustomResolutionDlg.cpp +++ b/Code/Editor/CustomResolutionDlg.cpp @@ -25,7 +25,7 @@ AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING #define MIN_RES 64 #define MAX_RES 8192 -CCustomResolutionDlg::CCustomResolutionDlg(int w, int h, QWidget* pParent /*=NULL*/) +CCustomResolutionDlg::CCustomResolutionDlg(int w, int h, QWidget* pParent /*=nullptr*/) : QDialog(pParent) , m_wDefault(w) , m_hDefault(h) @@ -50,12 +50,12 @@ void CCustomResolutionDlg::OnInitDialog() m_ui->m_height->setValue(m_hDefault); QString maxDimensionString; - QTextStream(&maxDimensionString) - << "Maximum Dimension: " << MAX_RES << Qt::endl + QTextStream(&maxDimensionString) + << "Maximum Dimension: " << MAX_RES << Qt::endl << Qt::endl << "Note: Dimensions over 8K may be" << Qt::endl << "unstable depending on hardware."; - + m_ui->m_maxDimension->setText(maxDimensionString); } diff --git a/Code/Editor/CustomizeKeyboardDialog.cpp b/Code/Editor/CustomizeKeyboardDialog.cpp index d6bea6860f..ce09f8d878 100644 --- a/Code/Editor/CustomizeKeyboardDialog.cpp +++ b/Code/Editor/CustomizeKeyboardDialog.cpp @@ -87,7 +87,7 @@ public: : QAbstractListModel(parent) { } - virtual ~MenuActionsModel() {} + ~MenuActionsModel() override {} int rowCount([[maybe_unused]] const QModelIndex& parent = QModelIndex()) const override { @@ -134,7 +134,7 @@ public: , m_action(nullptr) { } - virtual ~ActionShortcutsModel() {} + ~ActionShortcutsModel() override {} int rowCount([[maybe_unused]] const QModelIndex& parent = QModelIndex()) const override { diff --git a/Code/Editor/EditorDefs.h b/Code/Editor/EditorDefs.h index c98209befe..6614fa4d72 100644 --- a/Code/Editor/EditorDefs.h +++ b/Code/Editor/EditorDefs.h @@ -37,7 +37,6 @@ #pragma warning (disable : 4786) // identifier was truncated to 'number' characters in the debug information. #pragma warning (disable : 4244) // conversion from 'long' to 'float', possible loss of data #pragma warning (disable : 4018) // signed/unsigned mismatch -#pragma warning (disable : 4800) // BOOL bool conversion // Disable warning when a function returns a value inside an __asm block #pragma warning (disable : 4035) @@ -85,17 +84,17 @@ #endif #ifndef SAFE_DELETE -#define SAFE_DELETE(p) { if (p) { delete (p); (p) = NULL; } \ +#define SAFE_DELETE(p) { if (p) { delete (p); (p) = nullptr; } \ } #endif #ifndef SAFE_DELETE_ARRAY -#define SAFE_DELETE_ARRAY(p) { if (p) { delete[] (p); (p) = NULL; } \ +#define SAFE_DELETE_ARRAY(p) { if (p) { delete[] (p); (p) = nullptr; } \ } #endif #ifndef SAFE_RELEASE -#define SAFE_RELEASE(p) { if (p) { (p)->Release(); (p) = NULL; } \ +#define SAFE_RELEASE(p) { if (p) { (p)->Release(); (p) = nullptr; } \ } #endif diff --git a/Code/Editor/EditorFileMonitor.cpp b/Code/Editor/EditorFileMonitor.cpp index 96dc883ab0..5e539f78a8 100644 --- a/Code/Editor/EditorFileMonitor.cpp +++ b/Code/Editor/EditorFileMonitor.cpp @@ -162,7 +162,7 @@ QString RemoveGameName(const QString &filename) void CEditorFileMonitor::OnFileMonitorChange(const SFileChangeInfo& rChange) { CCryEditApp* app = CCryEditApp::instance(); - if (app == NULL || app->IsExiting()) + if (app == nullptr || app->IsExiting()) { return; } diff --git a/Code/Editor/EditorFileMonitor.h b/Code/Editor/EditorFileMonitor.h index ac33fee9f4..7474d5e43a 100644 --- a/Code/Editor/EditorFileMonitor.h +++ b/Code/Editor/EditorFileMonitor.h @@ -42,7 +42,7 @@ private: QString extension; SFileChangeCallback() - : pListener(NULL) + : pListener(nullptr) {} SFileChangeCallback(IFileChangeListener* pListener, const char* item, const char* extension) diff --git a/Code/Editor/EditorPanelUtils.cpp b/Code/Editor/EditorPanelUtils.cpp index 9091bb4c2f..b19bde4583 100644 --- a/Code/Editor/EditorPanelUtils.cpp +++ b/Code/Editor/EditorPanelUtils.cpp @@ -49,7 +49,7 @@ class CEditorPanelUtils_Impl { #pragma region Drag & Drop public: - virtual void SetViewportDragOperation(void(* dropCallback)(CViewport* viewport, int dragPointX, int dragPointY, void* custom), void* custom) override + void SetViewportDragOperation(void(* dropCallback)(CViewport* viewport, int dragPointX, int dragPointY, void* custom), void* custom) override { for (int i = 0; i < GetIEditor()->GetViewManager()->GetViewCount(); i++) { @@ -60,13 +60,13 @@ public: #pragma region Preview Window public: - virtual int PreviewWindow_GetDisplaySettingsDebugFlags(CDisplaySettings* settings) + int PreviewWindow_GetDisplaySettingsDebugFlags(CDisplaySettings* settings) override { CRY_ASSERT(settings); return settings->GetDebugFlags(); } - virtual void PreviewWindow_SetDisplaySettingsDebugFlags(CDisplaySettings* settings, int flags) + void PreviewWindow_SetDisplaySettingsDebugFlags(CDisplaySettings* settings, int flags) override { CRY_ASSERT(settings); settings->SetDebugFlags(flags); @@ -79,7 +79,7 @@ protected: bool m_hotkeysAreEnabled; public: - virtual bool HotKey_Import() override + bool HotKey_Import() override { QVector > keys; QString filepath = QFileDialog::getOpenFileName(nullptr, "Select shortcut configuration to load", @@ -143,7 +143,7 @@ public: return result; } - virtual void HotKey_Export() override + void HotKey_Export() override { auto settingDir = AZ::IO::FixedMaxPath(AZ::Utils::GetEnginePath()) / "Editor" / "Plugins" / "ParticleEditorPlugin" / "settings"; QString filepath = QFileDialog::getSaveFileName(nullptr, "Select shortcut configuration to load", settingDir.c_str(), "HotKey Config Files (*.hkxml)"); @@ -170,7 +170,7 @@ public: file.close(); } - virtual QKeySequence HotKey_GetShortcut(const char* path) override + QKeySequence HotKey_GetShortcut(const char* path) override { for (HotKey combo : hotkeys) { @@ -182,7 +182,7 @@ public: return QKeySequence(); } - virtual bool HotKey_IsPressed(const QKeyEvent* event, const char* path) override + bool HotKey_IsPressed(const QKeyEvent* event, const char* path) override { if (!m_hotkeysAreEnabled) { @@ -221,7 +221,7 @@ public: return false; } - virtual bool HotKey_IsPressed(const QShortcutEvent* event, const char* path) override + bool HotKey_IsPressed(const QShortcutEvent* event, const char* path) override { if (!m_hotkeysAreEnabled) { @@ -239,7 +239,7 @@ public: return false; } - virtual bool HotKey_LoadExisting() override + bool HotKey_LoadExisting() override { QSettings settings("O3DE", "O3DE"); QString group = "Hotkeys/"; @@ -275,7 +275,7 @@ public: return true; } - virtual void HotKey_SaveCurrent() override + void HotKey_SaveCurrent() override { QSettings settings("O3DE", "O3DE"); QString group = "Hotkeys/"; @@ -296,7 +296,7 @@ public: settings.sync(); } - virtual void HotKey_BuildDefaults() override + void HotKey_BuildDefaults() override { m_hotkeysAreEnabled = true; QVector > keys; @@ -356,17 +356,17 @@ public: } } - virtual void HotKey_SetKeys(QVector keys) override + void HotKey_SetKeys(QVector keys) override { hotkeys = keys; } - virtual QVector HotKey_GetKeys() override + QVector HotKey_GetKeys() override { return hotkeys; } - virtual QString HotKey_GetPressedHotkey(const QKeyEvent* event) override + QString HotKey_GetPressedHotkey(const QKeyEvent* event) override { if (!m_hotkeysAreEnabled) { @@ -381,7 +381,7 @@ public: } return ""; } - virtual QString HotKey_GetPressedHotkey(const QShortcutEvent* event) override + QString HotKey_GetPressedHotkey(const QShortcutEvent* event) override { if (!m_hotkeysAreEnabled) { @@ -398,12 +398,12 @@ public: } //building the default hotkey list re-enables hotkeys //do not use this when rebuilding the default list is a possibility. - virtual void HotKey_SetEnabled(bool val) override + void HotKey_SetEnabled(bool val) override { m_hotkeysAreEnabled = val; } - virtual bool HotKey_IsEnabled() const override + bool HotKey_IsEnabled() const override { return m_hotkeysAreEnabled; } @@ -457,13 +457,13 @@ protected: } public: - virtual void ToolTip_LoadConfigXML(QString filepath) override + void ToolTip_LoadConfigXML(QString filepath) override { XmlNodeRef node = GetIEditor()->GetSystem()->LoadXmlFromFile(filepath.toStdString().c_str()); ToolTip_ParseNode(node); } - virtual void ToolTip_BuildFromConfig(IQToolTip* tooltip, QString path, QString option, QString optionalData = "", bool isEnabled = true) + void ToolTip_BuildFromConfig(IQToolTip* tooltip, QString path, QString option, QString optionalData = "", bool isEnabled = true) override { AZ_Assert(tooltip, "tooltip cannot be null"); @@ -488,7 +488,7 @@ public: } } - virtual QString ToolTip_GetTitle(QString path, QString option) override + QString ToolTip_GetTitle(QString path, QString option) override { if (!option.isEmpty() && GetToolTip(path + "." + option).isValid) { @@ -501,7 +501,7 @@ public: return GetToolTip(path).title; } - virtual QString ToolTip_GetContent(QString path, QString option) override + QString ToolTip_GetContent(QString path, QString option) override { if (!option.isEmpty() && GetToolTip(path + "." + option).isValid) { @@ -514,7 +514,7 @@ public: return GetToolTip(path).content; } - virtual QString ToolTip_GetSpecialContentType(QString path, QString option) override + QString ToolTip_GetSpecialContentType(QString path, QString option) override { if (!option.isEmpty() && GetToolTip(path + "." + option).isValid) { @@ -527,7 +527,7 @@ public: return GetToolTip(path).specialContent; } - virtual QString ToolTip_GetDisabledContent(QString path, QString option) override + QString ToolTip_GetDisabledContent(QString path, QString option) override { if (!option.isEmpty() && GetToolTip(path + "." + option).isValid) { diff --git a/Code/Editor/EditorPreferencesDialog.cpp b/Code/Editor/EditorPreferencesDialog.cpp index 893b36b40c..c3fc4139f6 100644 --- a/Code/Editor/EditorPreferencesDialog.cpp +++ b/Code/Editor/EditorPreferencesDialog.cpp @@ -282,7 +282,7 @@ void EditorPreferencesDialog::CreatePages() { auto pUnknown = classes[i]; - IPreferencesPageCreator* pPageCreator = 0; + IPreferencesPageCreator* pPageCreator = nullptr; if (FAILED(pUnknown->QueryInterface(&pPageCreator))) { continue; diff --git a/Code/Editor/ErrorReport.cpp b/Code/Editor/ErrorReport.cpp index e1b2b8b6e4..7914511fbe 100644 --- a/Code/Editor/ErrorReport.cpp +++ b/Code/Editor/ErrorReport.cpp @@ -136,11 +136,11 @@ void CErrorReport::ReportError(CErrorRecord& err) } else { - if (err.pObject == NULL && m_pObject != NULL) + if (err.pObject == nullptr && m_pObject != nullptr) { err.pObject = m_pObject; } - else if (err.pItem == NULL && m_pItem != NULL) + else if (err.pItem == nullptr && m_pItem != nullptr) { err.pItem = m_pItem; } diff --git a/Code/Editor/ErrorReportDialog.cpp b/Code/Editor/ErrorReportDialog.cpp index 8b007207d6..2d551d6c8b 100644 --- a/Code/Editor/ErrorReportDialog.cpp +++ b/Code/Editor/ErrorReportDialog.cpp @@ -39,7 +39,7 @@ AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING ////////////////////////////////////////////////////////////////////////// -CErrorReportDialog* CErrorReportDialog::m_instance = 0; +CErrorReportDialog* CErrorReportDialog::m_instance = nullptr; // CErrorReportDialog dialog @@ -88,12 +88,12 @@ CErrorReportDialog::CErrorReportDialog(QWidget* parent) m_instance = this; //CErrorReport *report, //m_pErrorReport = report; - m_pErrorReport = 0; + m_pErrorReport = nullptr; } CErrorReportDialog::~CErrorReportDialog() { - m_instance = 0; + m_instance = nullptr; } ////////////////////////////////////////////////////////////////////////// @@ -141,7 +141,7 @@ void CErrorReportDialog::Clear() { if (m_instance) { - m_instance->SetReport(0); + m_instance->SetReport(nullptr); m_instance->UpdateErrors(); } } @@ -500,7 +500,7 @@ void CErrorReportDialog::OnReportItemDblClick(const QModelIndex& index) { bool bDone = false; const CErrorRecord* pError = index.data(Qt::UserRole).value(); - if (pError && pError->pObject != NULL) + if (pError && pError->pObject != nullptr) { CUndo undo("Select Object(s)"); // Clear other selection. @@ -563,7 +563,7 @@ void CErrorReportDialog::OnReportHyperlink(const QModelIndex& index) { const CErrorRecord* pError = index.data(Qt::UserRole).value(); bool bDone = false; - if (pError && pError->pObject != NULL) + if (pError && pError->pObject != nullptr) { CUndo undo("Select Object(s)"); // Clear other selection. @@ -593,8 +593,8 @@ void CErrorReportDialog::OnShowFieldChooser() CMainFrm* pMainFrm = (CMainFrame*)AfxGetMainWnd(); if (pMainFrm) { - BOOL bShow = !pMainFrm->m_wndFieldChooser.IsVisible(); - pMainFrm->ShowControlBar(&pMainFrm->m_wndFieldChooser, bShow, FALSE); + bool bShow = !pMainFrm->m_wndFieldChooser.IsVisible(); + pMainFrm->ShowControlBar(&pMainFrm->m_wndFieldChooser, bShow, false); } } */ diff --git a/Code/Editor/ErrorReportTableModel.cpp b/Code/Editor/ErrorReportTableModel.cpp index e7a1048a09..c0c24bb7ce 100644 --- a/Code/Editor/ErrorReportTableModel.cpp +++ b/Code/Editor/ErrorReportTableModel.cpp @@ -105,7 +105,7 @@ void CErrorReportTableModel::setErrorReport(CErrorReport* report) { m_errorRecords.clear(); } - if (report != 0) + if (report != nullptr) { const int count = report->GetErrorCount(); m_errorRecords.reserve(count); diff --git a/Code/Editor/GameEngine.cpp b/Code/Editor/GameEngine.cpp index 23966c1049..137d14c844 100644 --- a/Code/Editor/GameEngine.cpp +++ b/Code/Editor/GameEngine.cpp @@ -57,12 +57,12 @@ struct SSystemUserCallback : public ISystemUserCallback { SSystemUserCallback(IInitializeUIInfo* logo) : m_threadErrorHandler(this) { m_pLogo = logo; }; - virtual void OnSystemConnect(ISystem* pSystem) + void OnSystemConnect(ISystem* pSystem) override { ModuleInitISystem(pSystem, "Editor"); } - virtual bool OnError(const char* szErrorString) + bool OnError(const char* szErrorString) override { // since we show a message box, we have to use the GUI thread if (QThread::currentThread() != qApp->thread()) @@ -95,7 +95,7 @@ struct SSystemUserCallback int res = IDNO; - ICVar* pCVar = gEnv->pConsole ? gEnv->pConsole->GetCVar("sys_no_crash_dialog") : NULL; + ICVar* pCVar = gEnv->pConsole ? gEnv->pConsole->GetCVar("sys_no_crash_dialog") : nullptr; if (!pCVar || pCVar->GetIVal() == 0) { @@ -116,7 +116,7 @@ struct SSystemUserCallback return true; } - virtual bool OnSaveDocument() + bool OnSaveDocument() override { bool success = false; @@ -133,7 +133,7 @@ struct SSystemUserCallback return success; } - virtual bool OnBackupDocument() + bool OnBackupDocument() override { CCryEditDoc* level = GetIEditor() ? GetIEditor()->GetDocument() : nullptr; if (level) @@ -144,7 +144,7 @@ struct SSystemUserCallback return false; } - virtual void OnProcessSwitch() + void OnProcessSwitch() override { if (GetIEditor()->IsInGameMode()) { @@ -152,7 +152,7 @@ struct SSystemUserCallback } } - virtual void OnInitProgress(const char* sProgressMsg) + void OnInitProgress(const char* sProgressMsg) override { if (m_pLogo) { @@ -160,7 +160,7 @@ struct SSystemUserCallback } } - virtual int ShowMessage(const char* text, const char* caption, unsigned int uType) + int ShowMessage(const char* text, const char* caption, unsigned int uType) override { if (CCryEditApp::instance()->IsInAutotestMode()) { @@ -176,7 +176,7 @@ struct SSystemUserCallback return CryMessageBox(text, caption, uType); } - virtual void GetMemoryUsage(ICrySizer* pSizer) + void GetMemoryUsage(ICrySizer* pSizer) override { GetIEditor()->GetMemoryUsage(pSizer); } @@ -215,7 +215,7 @@ public: { AzFramework::AssetSystemConnectionNotificationsBus::Handler::BusConnect(); }; - ~AssetProcessConnectionStatus() + ~AssetProcessConnectionStatus() override { AzFramework::AssetSystemConnectionNotificationsBus::Handler::BusDisconnect(); } @@ -247,18 +247,18 @@ private: AZ_PUSH_DISABLE_WARNING(4273, "-Wunknown-warning-option") CGameEngine::CGameEngine() - : m_gameDll(0) + : m_gameDll(nullptr) , m_bIgnoreUpdates(false) , m_ePendingGameMode(ePGM_NotPending) , m_modalWindowDismisser(nullptr) AZ_POP_DISABLE_WARNING { - m_pISystem = NULL; + m_pISystem = nullptr; m_bLevelLoaded = false; m_bInGameMode = false; m_bSimulationMode = false; m_bSyncPlayerPosition = true; - m_hSystemHandle = 0; + m_hSystemHandle = nullptr; m_bJustCreated = false; m_levelName = "Untitled"; m_levelExtension = EditorUtils::LevelFile::GetDefaultFileExtension(); @@ -271,7 +271,7 @@ CGameEngine::~CGameEngine() { AZ_POP_DISABLE_WARNING GetIEditor()->UnregisterNotifyListener(this); - m_pISystem->GetIMovieSystem()->SetCallback(NULL); + m_pISystem->GetIMovieSystem()->SetCallback(nullptr); if (m_gameDll) { @@ -279,7 +279,7 @@ AZ_POP_DISABLE_WARNING } delete m_pISystem; - m_pISystem = NULL; + m_pISystem = nullptr; if (m_hSystemHandle) { @@ -866,7 +866,7 @@ void CGameEngine::OnEditorNotifyEvent(EEditorNotifyEvent event) { case eNotify_OnSplashScreenDestroyed: { - if (m_pSystemUserCallback != NULL) + if (m_pSystemUserCallback != nullptr) { m_pSystemUserCallback->OnSplashScreenDone(); } diff --git a/Code/Editor/GameExporter.cpp b/Code/Editor/GameExporter.cpp index 006eb9189c..feea94b34b 100644 --- a/Code/Editor/GameExporter.cpp +++ b/Code/Editor/GameExporter.cpp @@ -63,7 +63,7 @@ void SGameExporterSettings::SetHiQuality() nApplySS = 1; } -CGameExporter* CGameExporter::m_pCurrentExporter = NULL; +CGameExporter* CGameExporter::m_pCurrentExporter = nullptr; ////////////////////////////////////////////////////////////////////////// // CGameExporter @@ -76,7 +76,7 @@ CGameExporter::CGameExporter() CGameExporter::~CGameExporter() { - m_pCurrentExporter = NULL; + m_pCurrentExporter = nullptr; } ////////////////////////////////////////////////////////////////////////// diff --git a/Code/Editor/GenericSelectItemDialog.cpp b/Code/Editor/GenericSelectItemDialog.cpp index ef109336ef..3c51b38d0a 100644 --- a/Code/Editor/GenericSelectItemDialog.cpp +++ b/Code/Editor/GenericSelectItemDialog.cpp @@ -17,7 +17,7 @@ AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING // CGenericSelectItemDialog dialog -CGenericSelectItemDialog::CGenericSelectItemDialog(QWidget* pParent /*=NULL*/) +CGenericSelectItemDialog::CGenericSelectItemDialog(QWidget* pParent /*=nullptr*/) : QDialog(pParent) , ui(new Ui::CGenericSelectItemDialog) , m_initialized(false) diff --git a/Code/Editor/IEditor.h b/Code/Editor/IEditor.h index a56c8e81e9..f66dca412e 100644 --- a/Code/Editor/IEditor.h +++ b/Code/Editor/IEditor.h @@ -570,7 +570,7 @@ struct IEditor ////////////////////////////////////////////////////////////////////////// virtual class CLevelIndependentFileMan* GetLevelIndependentFileMan() = 0; //! Notify all views that data is changed. - virtual void UpdateViews(int flags = 0xFFFFFFFF, const AABB* updateRegion = NULL) = 0; + virtual void UpdateViews(int flags = 0xFFFFFFFF, const AABB* updateRegion = nullptr) = 0; virtual void ResetViews() = 0; //! Update information in track view dialog. virtual void ReloadTrackView() = 0; @@ -589,7 +589,7 @@ struct IEditor //! if bShow is true also returns a valid ITransformManipulator pointer. virtual ITransformManipulator* ShowTransformManipulator(bool bShow) = 0; //! Return a pointer to a ITransformManipulator pointer if shown. - //! NULL is manipulator is not shown. + //! nullptr if manipulator is not shown. virtual ITransformManipulator* GetTransformManipulator() = 0; //! Set constrain on specified axis for objects construction and modifications. //! @param axis one of AxisConstrains enumerations. diff --git a/Code/Editor/IEditorImpl.cpp b/Code/Editor/IEditorImpl.cpp index c09c0a8e62..d9c3af64b0 100644 --- a/Code/Editor/IEditorImpl.cpp +++ b/Code/Editor/IEditorImpl.cpp @@ -415,7 +415,7 @@ void CEditorImpl::Update() } if (IsInPreviewMode()) { - SetModifiedFlag(FALSE); + SetModifiedFlag(false); SetModifiedModule(eModifiedNothing); } @@ -550,7 +550,7 @@ QString CEditorImpl::GetResolvedUserFolder() void CEditorImpl::SetDataModified() { - GetDocument()->SetModifiedFlag(TRUE); + GetDocument()->SetModifiedFlag(true); } void CEditorImpl::SetStatusText(const QString& pszString) @@ -597,9 +597,9 @@ ITransformManipulator* CEditorImpl::ShowTransformManipulator(bool bShow) GetObjectManager()->GetGizmoManager()->RemoveGizmo(m_pAxisGizmo); m_pAxisGizmo->Release(); } - m_pAxisGizmo = 0; + m_pAxisGizmo = nullptr; } - return 0; + return nullptr; } ITransformManipulator* CEditorImpl::GetTransformManipulator() @@ -614,7 +614,7 @@ void CEditorImpl::SetAxisConstraints(AxisConstrains axisFlags) SetTerrainAxisIgnoreObjects(false); // Update all views. - UpdateViews(eUpdateObjects, NULL); + UpdateViews(eUpdateObjects, nullptr); } AxisConstrains CEditorImpl::GetAxisConstrains() @@ -637,15 +637,15 @@ void CEditorImpl::SetReferenceCoordSys(RefCoordSys refCoords) m_refCoordsSys = refCoords; // Update all views. - UpdateViews(eUpdateObjects, NULL); + UpdateViews(eUpdateObjects, nullptr); // Update the construction plane infos. CViewport* pViewport = GetActiveView(); if (pViewport) { //Pre and Post widget rendering calls are made here to make sure that the proper camera state is set. - //MakeConstructionPlane will make a call to ViewToWorldRay which needs the correct camera state - //in the CRenderViewport to be set. + //MakeConstructionPlane will make a call to ViewToWorldRay which needs the correct camera state + //in the CRenderViewport to be set. pViewport->PreWidgetRendering(); pViewport->MakeConstructionPlane(GetIEditor()->GetAxisConstrains()); @@ -671,7 +671,7 @@ CBaseObject* CEditorImpl::NewObject(const char* typeName, const char* fileName, editor->SetModifiedFlag(); editor->SetModifiedModule(eModifiedBrushes); } - CBaseObject* object = editor->GetObjectManager()->NewObject(typeName, 0, fileName, name); + CBaseObject* object = editor->GetObjectManager()->NewObject(typeName, nullptr, fileName, name); if (!object) { return nullptr; @@ -932,7 +932,7 @@ void CEditorImpl::CloseView(const GUID& classId) IDataBaseManager* CEditorImpl::GetDBItemManager([[maybe_unused]] EDataBaseItemType itemType) { - return 0; + return nullptr; } bool CEditorImpl::SelectColor(QColor& color, QWidget* parent) @@ -1109,7 +1109,7 @@ void CEditorImpl::DetectVersion() char ver[1024 * 8]; - GetModuleFileName(NULL, exe, _MAX_PATH); + GetModuleFileName(nullptr, exe, _MAX_PATH); int verSize = GetFileVersionInfoSize(exe, &dwHandle); if (verSize > 0) @@ -1431,7 +1431,7 @@ void CEditorImpl::NotifyExcept(EEditorNotifyEvent event, IEditorNotifyListener* { m_pAxisGizmo->Release(); } - m_pAxisGizmo = 0; + m_pAxisGizmo = nullptr; } if (event == eNotify_OnInit) @@ -1472,7 +1472,7 @@ ISourceControl* CEditorImpl::GetSourceControl() for (int i = 0; i < classes.size(); i++) { IClassDesc* pClass = classes[i]; - ISourceControl* pSCM = NULL; + ISourceControl* pSCM = nullptr; HRESULT hRes = pClass->QueryInterface(__uuidof(ISourceControl), (void**)&pSCM); if (!FAILED(hRes) && pSCM) { @@ -1482,7 +1482,7 @@ ISourceControl* CEditorImpl::GetSourceControl() } } - return 0; + return nullptr; } bool CEditorImpl::IsSourceControlAvailable() diff --git a/Code/Editor/IEditorImpl.h b/Code/Editor/IEditorImpl.h index 65389a212e..db963e83f1 100644 --- a/Code/Editor/IEditorImpl.h +++ b/Code/Editor/IEditorImpl.h @@ -22,7 +22,7 @@ #include #include -#include "Commands/CommandManager.h" +#include "Commands/CommandManager.h" #include "Include/IErrorReport.h" #include "ErrorReport.h" @@ -63,7 +63,7 @@ namespace AssetDatabase class AssetDatabaseLocationListener; } -class CEditorImpl +class CEditorImpl : public IEditor { Q_DECLARE_TR_FUNCTIONS(CEditorImpl) @@ -176,7 +176,7 @@ public: { return m_pSystem->GetIMovieSystem(); } - return NULL; + return nullptr; }; CPluginManager* GetPluginManager() { return m_pPluginManager; } @@ -210,7 +210,7 @@ public: RefCoordSys GetReferenceCoordSys(); XmlNodeRef FindTemplate(const QString& templateName); void AddTemplate(const QString& templateName, XmlNodeRef& tmpl); - + const QtViewPane* OpenView(QString sViewClassName, bool reuseOpened = true) override; /** diff --git a/Code/Editor/IconManager.cpp b/Code/Editor/IconManager.cpp index 7f6f7cd0ab..dc9eb56b88 100644 --- a/Code/Editor/IconManager.cpp +++ b/Code/Editor/IconManager.cpp @@ -81,7 +81,7 @@ void CIconManager::Reset() { m_objects[i]->Release(); } - m_objects[i] = 0; + m_objects[i] = nullptr; } for (i = 0; i < eIcon_COUNT; i++) { @@ -135,7 +135,7 @@ IStatObj* CIconManager::GetObject(EStatObject) ////////////////////////////////////////////////////////////////////////// QImage* CIconManager::GetIconBitmap(const char* filename, bool& bHaveAlpha, uint32 effects /*=0*/) { - QImage* pBitmap = 0; + QImage* pBitmap = nullptr; QString iconFilename = filename; @@ -160,11 +160,11 @@ QImage* CIconManager::GetIconBitmap(const char* filename, bool& bHaveAlpha, uint return pBitmap; } - BOOL bAlphaBitmap = FALSE; + bool bAlphaBitmap = false; QPixmap pm(iconFilename); bAlphaBitmap = pm.hasAlpha(); - bHaveAlpha = (bAlphaBitmap == TRUE); + bHaveAlpha = (bAlphaBitmap == true); if (!pm.isNull()) { pBitmap = new QImage; @@ -252,5 +252,5 @@ QImage* CIconManager::GetIconBitmap(const char* filename, bool& bHaveAlpha, uint return pBitmap; } - return NULL; + return nullptr; } diff --git a/Code/Editor/LayoutConfigDialog.cpp b/Code/Editor/LayoutConfigDialog.cpp index 6722a7d9d7..1074ebc23e 100644 --- a/Code/Editor/LayoutConfigDialog.cpp +++ b/Code/Editor/LayoutConfigDialog.cpp @@ -68,7 +68,7 @@ QVariant LayoutConfigModel::data(const QModelIndex& index, int role) const // CLayoutConfigDialog dialog -CLayoutConfigDialog::CLayoutConfigDialog(QWidget* pParent /*=NULL*/) +CLayoutConfigDialog::CLayoutConfigDialog(QWidget* pParent /*=nullptr*/) : QDialog(pParent) , m_model(new LayoutConfigModel(this)) , ui(new Ui::CLayoutConfigDialog) diff --git a/Code/Editor/LayoutWnd.cpp b/Code/Editor/LayoutWnd.cpp index a3550b39ba..7f73c313d9 100644 --- a/Code/Editor/LayoutWnd.cpp +++ b/Code/Editor/LayoutWnd.cpp @@ -98,7 +98,7 @@ CLayoutWnd::CLayoutWnd(QSettings* settings, QWidget* parent) , m_settings(settings) { m_bMaximized = false; - m_maximizedView = 0; + m_maximizedView = nullptr; m_layout = (EViewLayout) - 1; m_maximizedViewId = 0; @@ -729,7 +729,7 @@ void CLayoutWnd::OnDestroy() if (m_maximizedView) { delete m_maximizedView; - m_maximizedView = 0; + m_maximizedView = nullptr; } } From 635b9686c6915803d472a56740b1c1cf028c417d Mon Sep 17 00:00:00 2001 From: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> Date: Mon, 9 Aug 2021 11:18:38 -0700 Subject: [PATCH 220/803] [redcode/crythread-2nd-pass] removed CrySimpleThread and related code Signed-off-by: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> --- Code/Legacy/CryCommon/CryThread.h | 75 --- .../Legacy/CryCommon/CryThreadImpl_pthreads.h | 7 - Code/Legacy/CryCommon/CryThreadImpl_windows.h | 51 -- Code/Legacy/CryCommon/CryThread_pthreads.h | 440 ------------------ Code/Legacy/CryCommon/CryThread_windows.h | 206 -------- 5 files changed, 779 deletions(-) diff --git a/Code/Legacy/CryCommon/CryThread.h b/Code/Legacy/CryCommon/CryThread.h index b7b6a3adfd..fcd7be16ba 100644 --- a/Code/Legacy/CryCommon/CryThread.h +++ b/Code/Legacy/CryCommon/CryThread.h @@ -85,81 +85,6 @@ public: ////////////////////////////////////////////////////////////////////////// typedef CryAutoLock CryAutoCriticalSection; -///////////////////////////////////////////////////////////////////////////// -// -// Threads. - -// Base class for runnable objects. -// -// A runnable is an object with a Run() and a Cancel() method. The Run() -// method should perform the runnable's job. The Cancel() method may be -// called by another thread requesting early termination of the Run() method. -// The runnable may ignore the Cancel() call, the default implementation of -// Cancel() does nothing. -class CryRunnable -{ -public: - virtual ~CryRunnable() { } - virtual void Run() = 0; - virtual void Cancel() { } -}; - -// Class holding information about a thread. -// -// A reference to the thread information can be obtained by calling GetInfo() -// on the CrySimpleThread (or derived class) instance. -// -// NOTE: -// If the code is compiled with NO_THREADINFO defined, then the GetInfo() -// method will return a reference to a static dummy instance of this -// structure. It is currently undecided if NO_THREADINFO will be defined for -// release builds! - -struct CryThreadInfo -{ - // The symbolic name of the thread. - // - // You may set this name directly or through the SetName() method of - // CrySimpleThread (or derived class). - AZStd::string m_Name; - - - // A thread identification number. - // The number is unique but architecture specific. Do not assume anything - // about that number except for being unique. - // - // This field is filled when the thread is started (i.e. before the Run() - // method or thread routine is called). It is advised that you do not - // change this number manually. - uint32 m_ID; -}; - -// Simple thread class. -// -// CrySimpleThread is a simple wrapper around a system thread providing -// nothing but system-level functionality of a thread. There are two typical -// ways to use a simple thread: -// -// 1. Derive from the CrySimpleThread class and provide an implementation of -// the Run() (and optionally Cancel()) methods. -// 2. Specify a runnable object when the thread is started. The default -// runnable type is CryRunnable. -// -// The Runnable class specfied as the template argument must provide Run() -// and Cancel() methods compatible with the following signatures: -// -// void Runnable::Run(); -// void Runnable::Cancel(); -// -// If the Runnable does not support cancellation, then the Cancel() method -// should do nothing. -// -// The same instance of CrySimpleThread may be used for multiple thread -// executions /in sequence/, i.e. it is valid to re-start the thread by -// calling Start() after the thread has been joined by calling WaitForThread(). -template -class CrySimpleThread; - /////////////////////////////////////////////////////////////////////////////// // Include architecture specific code. #if AZ_LEGACY_CRYCOMMON_TRAIT_USE_PTHREADS diff --git a/Code/Legacy/CryCommon/CryThreadImpl_pthreads.h b/Code/Legacy/CryCommon/CryThreadImpl_pthreads.h index c94d4fca90..358d8f962f 100644 --- a/Code/Legacy/CryCommon/CryThreadImpl_pthreads.h +++ b/Code/Legacy/CryCommon/CryThreadImpl_pthreads.h @@ -14,13 +14,6 @@ #include "CryThread_pthreads.h" -#if PLATFORM_SUPPORTS_THREADLOCAL -THREADLOCAL CrySimpleThreadSelf -* CrySimpleThreadSelf::m_Self = NULL; -#else -TLS_DEFINE(CrySimpleThreadSelf*, g_CrySimpleThreadSelf) -#endif - ////////////////////////////////////////////////////////////////////////// // CryEvent(Timed) implementation diff --git a/Code/Legacy/CryCommon/CryThreadImpl_windows.h b/Code/Legacy/CryCommon/CryThreadImpl_windows.h index 5cf970414d..9d636fd41a 100644 --- a/Code/Legacy/CryCommon/CryThreadImpl_windows.h +++ b/Code/Legacy/CryCommon/CryThreadImpl_windows.h @@ -12,16 +12,6 @@ #include #include // for CreateSemaphore -struct SThreadNameDesc -{ - DWORD dwType; - LPCSTR szName; - DWORD dwThreadID; - DWORD dwFlags; -}; - -THREADLOCAL CrySimpleThreadSelf* CrySimpleThreadSelf::m_Self = NULL; - ////////////////////////////////////////////////////////////////////////// CryEvent::CryEvent() { @@ -302,44 +292,3 @@ void CryFastSemaphore::Release() m_Semaphore.Release(); } } - -////////////////////////////////////////////////////////////////////////// -CrySimpleThreadSelf::CrySimpleThreadSelf() - : m_thread(NULL) - , m_threadId(0) -{ -} - -////////////////////////////////////////////////////////////////////////// -void CrySimpleThreadSelf::WaitForThread() -{ - assert(m_thread); - PREFAST_ASSUME(m_thread); - if (GetCurrentThreadId() != m_threadId) - { - WaitForSingleObject((HANDLE)m_thread, INFINITE); - } -} - -CrySimpleThreadSelf::~CrySimpleThreadSelf() -{ - if (m_thread) - { - CloseHandle(m_thread); - } -} - -void CrySimpleThreadSelf::StartThread(unsigned (__stdcall * func)(void*), void* argList) -{ -#if defined(AZ_RESTRICTED_PLATFORM) - #include AZ_RESTRICTED_FILE(CryThreadImpl_windows_h) -#endif -#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED) -#undef AZ_RESTRICTED_SECTION_IMPLEMENTED -#else - m_thread = (void*)_beginthreadex(NULL, 0, func, argList, CREATE_SUSPENDED, &m_threadId); -#endif - assert(m_thread); - PREFAST_ASSUME(m_thread); - ResumeThread((HANDLE)m_thread); -} diff --git a/Code/Legacy/CryCommon/CryThread_pthreads.h b/Code/Legacy/CryCommon/CryThread_pthreads.h index 72b29344ec..9102c12c38 100644 --- a/Code/Legacy/CryCommon/CryThread_pthreads.h +++ b/Code/Legacy/CryCommon/CryThread_pthreads.h @@ -653,444 +653,4 @@ private: typedef CryEventTimed CryEvent; -#if !PLATFORM_SUPPORTS_THREADLOCAL -TLS_DECLARE(class CrySimpleThreadSelf*, g_CrySimpleThreadSelf); -#endif - -class CrySimpleThreadSelf -{ -protected: -#if PLATFORM_SUPPORTS_THREADLOCAL - - static CrySimpleThreadSelf* GetSelf() - { - return m_Self; - } - - static void SetSelf(CrySimpleThreadSelf* pSelf) - { - m_Self = pSelf; - } -private: - static THREADLOCAL CrySimpleThreadSelf* m_Self; - -#else - - static CrySimpleThreadSelf* GetSelf() - { - return TLS_GET(CrySimpleThreadSelf*, g_CrySimpleThreadSelf); - } - - static void SetSelf(CrySimpleThreadSelf* pSelf) - { - TLS_SET(g_CrySimpleThreadSelf, pSelf); - } - -#endif -}; - -template -class CrySimpleThread - : public CryRunnable - , protected CrySimpleThreadSelf -{ -public: - typedef void (* ThreadFunction)(void*); - typedef CryRunnable RunnableT; - - const volatile bool& GetStartedState() const { return m_bIsStarted; } - -private: -#if !defined(NO_THREADINFO) - CryThreadInfo m_Info; -#endif - pthread_t m_ThreadID; - unsigned m_CpuMask; - Runnable* m_Runnable; - struct - { - ThreadFunction m_ThreadFunction; - void* m_ThreadParameter; - } m_ThreadFunction; - volatile bool m_bIsStarted; - volatile bool m_bIsRunning; - -protected: - virtual void Terminate() - { - // This method must be empty. - // Derived classes overriding Terminate() are not required to call this - // method. - } - -private: -#if !defined(NO_THREADINFO) - static void SetThreadInfo(CrySimpleThread* self) - { - pthread_t thread = pthread_self(); - self->m_Info.m_ID = (uint32)(TRUNCATE_PTR)thread; -#if defined(APPLE) - pthread_setname_np(self->m_Info.m_Name.c_str()); -#endif - } -#else - static void SetThreadInfo(CrySimpleThread* self) { } -#endif - - static void* PthreadRunRunnable(void* thisPtr) - { - CrySimpleThread* const self = (CrySimpleThread*)thisPtr; - SetSelf(self); - self->m_bIsStarted = true; - self->m_bIsRunning = true; - SetThreadInfo(self); - self->m_Runnable->Run(); - self->m_bIsRunning = false; - self->Terminate(); - SetSelf(NULL); - return NULL; - } - - static void* PthreadRunThis(void* thisPtr) - { - CrySimpleThread* const self = (CrySimpleThread*)thisPtr; - SetSelf(self); - self->m_bIsStarted = true; - self->m_bIsRunning = true; - SetThreadInfo(self); - self->Run(); - self->m_bIsRunning = false; - self->Terminate(); - SetSelf(NULL); - return NULL; - } - - CrySimpleThread(const CrySimpleThread&); - void operator = (const CrySimpleThread&); - -public: - CrySimpleThread() - : m_CpuMask(0) - , m_bIsStarted(false) - , m_bIsRunning(false) - { - m_ThreadFunction.m_ThreadFunction = NULL; - m_ThreadFunction.m_ThreadParameter = NULL; -#if !defined(NO_THREADINFO) - m_Info.m_Name = ""; - m_Info.m_ID = 0; -#endif - memset(&m_ThreadID, 0, sizeof m_ThreadID); - m_Runnable = NULL; - } - - virtual ~CrySimpleThread() - { - if (IsStarted()) - { - // Note: We don't want to cache a pointer to ISystem and/or ILog to - // gain more freedom on when the threading classes are used (e.g. - // threads may be started very early in the initialization). - ISystem* pSystem = GetISystem(); - ILog* pLog = NULL; - if (pSystem != NULL) - { - pLog = pSystem->GetILog(); - } - if (pLog != NULL) - { - pLog->LogError("Runaway thread %s", GetName()); - } - Cancel(); - WaitForThread(); - } - } - -#if !defined(NO_THREADINFO) - CryThreadInfo& GetInfo() { return m_Info; } - const char* GetName() - { - return m_Info.m_Name.c_str(); - } - - // Set the name of the called thread. - // - // WIN32: - // If the thread is started, then the VC debugger is informed about the new - // thread name. If the thread is not started, then the VC debugger will be - // informed lated when the thread is started through one of the Start() - // methods. - // - // If the parameter Name is NULL, then the name of the thread is kept - // unchanged. This may be used to sent the current thread name to the VC - // debugger. - void SetName(const char* Name) - { - if (Name != NULL) - { - if (m_ThreadID) - { - RegisterThreadName(m_ThreadID, Name); - } - m_Info.m_Name = Name; - } -#if defined(WIN32) - if (IsStarted()) - { - // The VC debugger gets the information about a thread's name through - // the exception 0x406D1388. - struct - { - DWORD Type; - const char* Name; - DWORD ID; - DWORD Flags; - } Info = { 0x1000, NULL, 0, 0 }; - Info.ID = (DWORD)m_Info.m_ID; - __try - { - RaiseException( - 0x406D1388, 0, sizeof Info / sizeof(DWORD), (ULONG_PTR*)&Info); - } - __except (EXCEPTION_CONTINUE_EXECUTION) - { - } - } -#endif - } -#else -#if !defined(NO_THREADINFO) - CryThreadInfo& GetInfo() - { - static CryThreadInfo dummyInfo = { "", 0 }; - return dummyInfo; - } -#endif - const char* GetName() { return ""; } - void SetName(const char* Name) { } -#endif - - virtual void Run() - { - // This Run() implementation supports the void StartFunction() method. - // However, code using this class (or derived classes) should eventually - // be refactored to use one of the other Start() methods. This code will - // be removed some day and the default implementation of Run() will be - // empty. - if (m_ThreadFunction.m_ThreadFunction != NULL) - { - m_ThreadFunction.m_ThreadFunction(m_ThreadFunction.m_ThreadParameter); - } - } - - // Cancel the running thread. - // - // If the thread class is implemented as a derived class of CrySimpleThread, - // then the derived class should provide an appropriate implementation for - // this method. Calling the base class implementation is _not_ required. - // - // If the thread was started by specifying a Runnable (template argument), - // then the Cancel() call is passed on to the specified runnable. - // - // If the thread was started using the StartFunction() method, then the - // caller must find other means to inform the thread about the cancellation - // request. - virtual void Cancel() - { - if (IsStarted() && m_Runnable != NULL) - { - UnRegisterThreadName(m_ThreadID); - m_Runnable->Cancel(); - } - } - - virtual void Start(Runnable& runnable, unsigned cpuMask = 0, const char* name = NULL, int32 StackSize = (SIMPLE_THREAD_STACK_SIZE_KB * 1024)) - { -#if defined(LARGE_THREAD_STACK) - StackSize *= 4;//debug code needs a lot more than profile -#endif - assert(m_ThreadID == 0); - pthread_attr_t threadAttr; - pthread_attr_init(&threadAttr); - pthread_attr_setdetachstate(&threadAttr, PTHREAD_CREATE_JOINABLE); - pthread_attr_setstacksize(&threadAttr, StackSize); - if (name) - { - this->m_Info.m_Name = name; - } -#if CRYTHREAD_PTHREADS_H_TRAIT_SET_THREAD_NAME - threadAttr.name = (char*)name; -#endif - m_CpuMask = cpuMask; -#if defined(PTHREAD_NPTL) - if (cpuMask != ~0 && cpuMask != 0) - { - cpu_set_t cpuSet; - CPU_ZERO(&cpuSet); - for (int cpu = 0; cpu < sizeof(cpuMask) * 8; ++cpu) - { - if (cpuMask & (1 << cpu)) - { - CPU_SET(cpu, &cpuSet); - } - } - pthread_attr_setaffinity_np(&threadAttr, sizeof cpuSet, &cpuSet); - } -#elif defined(AZ_RESTRICTED_PLATFORM) - #define AZ_RESTRICTED_SECTION CRYTHREAD_PTHREADS_H_SECTION_START_RUNNABLE - #include AZ_RESTRICTED_FILE(CryThread_pthreads_h) -#endif - m_Runnable = &runnable; - int err = pthread_create( - &m_ThreadID, - &threadAttr, - PthreadRunRunnable, - this); - pthread_attr_destroy(&threadAttr); - RegisterThreadName(m_ThreadID, name); -#if defined(AZ_RESTRICTED_PLATFORM) - #define AZ_RESTRICTED_SECTION CRYTHREAD_PTHREADS_H_SECTION_START_RUNNABLE_CPUMASK_POSTCREATE - #include AZ_RESTRICTED_FILE(CryThread_pthreads_h) -#endif - assert(err == 0); - } - - virtual void Start(unsigned cpuMask = 0, const char* name = NULL, int32 Priority = THREAD_PRIORITY_NORMAL, int32 StackSize = (SIMPLE_THREAD_STACK_SIZE_KB * 1024)) - { -#if defined(LARGE_THREAD_STACK) - StackSize *= 4;//debug code needs a lot more than profile -#endif - assert(m_ThreadID == 0); - pthread_attr_t threadAttr; - sched_param schedParam; - pthread_attr_init(&threadAttr); - pthread_attr_getschedparam(&threadAttr, &schedParam); - schedParam.sched_priority = Priority; - pthread_attr_setschedparam(&threadAttr, &schedParam); - pthread_attr_setdetachstate(&threadAttr, PTHREAD_CREATE_JOINABLE); - pthread_attr_setstacksize(&threadAttr, StackSize); - if (name) - { - this->m_Info.m_Name = name; - } -#if CRYTHREAD_PTHREADS_H_TRAIT_SET_THREAD_NAME - threadAttr.name = (char*)name; -#endif - m_CpuMask = cpuMask; -#if defined(PTHREAD_NPTL) - if (cpuMask != ~0 && cpuMask != 0) - { - cpu_set_t cpuSet; - CPU_ZERO(&cpuSet); - for (int cpu = 0; cpu < sizeof(cpuMask) * 8; ++cpu) - { - if (cpuMask & (1 << cpu)) - { - CPU_SET(cpu, &cpuSet); - } - } - pthread_attr_setaffinity_np(&threadAttr, sizeof cpuSet, &cpuSet); - } -#elif defined(AZ_RESTRICTED_PLATFORM) - #define AZ_RESTRICTED_SECTION CRYTHREAD_PTHREADS_H_SECTION_START_CPUMASK - #include AZ_RESTRICTED_FILE(CryThread_pthreads_h) -#endif - int err = pthread_create( - &m_ThreadID, - &threadAttr, - PthreadRunThis, - this); - pthread_attr_destroy(&threadAttr); - RegisterThreadName(m_ThreadID, name); -#if defined(AZ_RESTRICTED_PLATFORM) - #define AZ_RESTRICTED_SECTION CRYTHREAD_PTHREADS_H_SECTION_START_CPUMASK_POSTCREATE - #include AZ_RESTRICTED_FILE(CryThread_pthreads_h) -#endif - assert(err == 0); - } - - void StartFunction( - ThreadFunction threadFunction, - void* threadParameter = NULL, - unsigned cpuMask = 0 - ) - { - m_ThreadFunction.m_ThreadFunction = threadFunction; - m_ThreadFunction.m_ThreadParameter = threadParameter; - Start(cpuMask); - } - - static CrySimpleThread* Self() - { - return reinterpret_cast*>(GetSelf()); - } - - void Exit() - { - assert(m_ThreadID == pthread_self()); - m_bIsRunning = false; - Terminate(); - SetSelf(NULL); - pthread_exit(NULL); - UnRegisterThreadName(m_ThreadID); - } - - void WaitForThread() - { - if (pthread_self() != m_ThreadID) - { - int err = pthread_join(m_ThreadID, NULL); - assert(err == 0); - } - m_bIsStarted = false; - memset(&m_ThreadID, 0, sizeof m_ThreadID); - } - - unsigned SetCpuMask(unsigned cpuMask) - { - int oldCpuMask = m_CpuMask; - if (cpuMask == m_CpuMask) - { - return oldCpuMask; - } - m_CpuMask = cpuMask; -#if defined(PTHREAD_NPTL) - cpu_set_t cpuSet; - CPU_ZERO(&cpuSet); - if (cpuMask != ~0 && cpuMask != 0) - { - for (int cpu = 0; cpu < sizeof(cpuMask) * 8; ++cpu) - { - if (cpuMask & (1 << cpu)) - { - CPU_SET(cpu, &cpuSet); - } - } - else - { - CPU_ZERO(&cpuSet); - for (int cpu = 0; i < sizeof(cpuSet) * 8; ++cpu) - { - CPU_SET(cpu, &cpuSet); - } - } - pthread_attr_setaffinity_np(&threadAttr, sizeof cpuSet, &cpuSet); -#elif defined(AZ_RESTRICTED_PLATFORM) - #define AZ_RESTRICTED_SECTION CRYTHREAD_PTHREADS_H_SECTION_SETCPUMASK - #include AZ_RESTRICTED_FILE(CryThread_pthreads_h) -#endif - return oldCpuMask; - } - - unsigned GetCpuMask() { return m_CpuMask; } - - void Stop() - { - m_bIsStarted = false; - } - - bool IsStarted() const { return m_bIsStarted; } - bool IsRunning() const { return m_bIsRunning; } - }; - #include "MemoryAccess.h" diff --git a/Code/Legacy/CryCommon/CryThread_windows.h b/Code/Legacy/CryCommon/CryThread_windows.h index cc09cc530b..87147549f7 100644 --- a/Code/Legacy/CryCommon/CryThread_windows.h +++ b/Code/Legacy/CryCommon/CryThread_windows.h @@ -179,209 +179,3 @@ private: CrySemaphore m_Semaphore; volatile int32 m_nCounter; }; - -////////////////////////////////////////////////////////////////////////// -class CrySimpleThreadSelf -{ -public: - CrySimpleThreadSelf(); - void WaitForThread(); - virtual ~CrySimpleThreadSelf(); -protected: - void StartThread(unsigned (__stdcall * func)(void*), void* argList); - static THREADLOCAL CrySimpleThreadSelf* m_Self; -private: - CrySimpleThreadSelf(const CrySimpleThreadSelf&); - CrySimpleThreadSelf& operator = (const CrySimpleThreadSelf&); -protected: - void* m_thread; - uint32 m_threadId; -}; - -template -class CrySimpleThread - : public CryRunnable - , public CrySimpleThreadSelf -{ -public: - typedef void (* ThreadFunction)(void*); - typedef CryRunnable RunnableT; - - void SetName(const char* Name) - { - m_name = Name; - } - const char* GetName() { return m_name; } - - const volatile bool& GetStartedState() const { return m_bIsStarted; } - -private: - Runnable* m_Runnable; - struct - { - ThreadFunction m_ThreadFunction; - void* m_ThreadParameter; - } m_ThreadFunction; - volatile bool m_bIsStarted; - volatile bool m_bIsRunning; - volatile bool m_bCreatedThread; - string m_name; - -protected: - virtual void Terminate() - { - // This method must be empty. - // Derived classes overriding Terminate() are not required to call this - // method. - } - -private: - static unsigned __stdcall RunRunnable(void* thisPtr) - { -#if defined(AZ_RESTRICTED_PLATFORM) - #define AZ_RESTRICTED_SECTION CRYTHREAD_WINDOWS_H_SECTION_1 - #include AZ_RESTRICTED_FILE(CryThread_windows_h) -#endif - CrySimpleThread* const self = (CrySimpleThread*)thisPtr; - self->m_bIsStarted = true; - self->m_bIsRunning = true; - - self->m_Runnable->Run(); - self->m_bIsRunning = false; - self->m_bCreatedThread = false; - self->Terminate(); - return 0; - } - - static unsigned __stdcall RunThis(void* thisPtr) - { -#if defined(AZ_RESTRICTED_PLATFORM) - #define AZ_RESTRICTED_SECTION CRYTHREAD_WINDOWS_H_SECTION_2 - #include AZ_RESTRICTED_FILE(CryThread_windows_h) -#endif - CrySimpleThread* const self = (CrySimpleThread*)thisPtr; - self->m_bIsStarted = true; - self->m_bIsRunning = true; - - self->Run(); - self->m_bIsRunning = false; - self->m_bCreatedThread = false; - self->Terminate(); - return 0; - } - - CrySimpleThread(const CrySimpleThread&); - void operator = (const CrySimpleThread&); - -public: - CrySimpleThread() - : m_bIsStarted(false) - , m_bIsRunning(false) - , m_bCreatedThread(false) - { - m_thread = NULL; - m_Runnable = NULL; - } - void* GetHandle() { return m_thread; } - - virtual ~CrySimpleThread() - { - if (IsStarted()) - { - if (gEnv && gEnv->pLog) - { - gEnv->pLog->LogError("Runaway thread %p '%s'", m_thread, m_name.c_str()); - } - } - - if (m_bCreatedThread) - { - Cancel(); - WaitForThread(); - } - } - - virtual void Run() - { - // This Run() implementation supports the void StartFunction() method. - // However, code using this class (or derived classes) should eventually - // be refactored to use one of the other Start() methods. This code will - // be removed some day and the default implementation of Run() will be - // empty. - if (m_ThreadFunction.m_ThreadFunction != NULL) - { - m_ThreadFunction.m_ThreadFunction(m_ThreadFunction.m_ThreadParameter); - } - } - - // Cancel the running thread. - // - // If the thread class is implemented as a derived class of CrySimpleThread, - // then the derived class should provide an appropriate implementation for - // this method. Calling the base class implementation is _not_ required. - // - // If the thread was started by specifying a Runnable (template argument), - // then the Cancel() call is passed on to the specified runnable. - // - // If the thread was started using the StartFunction() method, then the - // caller must find other means to inform the thread about the cancellation - // request. - virtual void Cancel() - { - if (IsStarted() && m_Runnable != NULL) - { - m_Runnable->Cancel(); - } - } - - virtual void Start(Runnable& runnable, [[maybe_unused]] unsigned cpuMask = 0, const char* = NULL, int32 = 0) - { - if (m_bCreatedThread) - { - // Don't start thread more than once! - return; - } - m_Runnable = &runnable; - m_bCreatedThread = true; - StartThread(RunRunnable, this); - } - - virtual void Start([[maybe_unused]] unsigned cpuMask = 0, const char* = NULL, int32 = 0, int32 = 0) - { - if (m_bCreatedThread) - { - // Don't start thread more than once! - return; - } - m_bCreatedThread = true; - StartThread(RunThis, this); - } - - void StartFunction( - ThreadFunction threadFunction, - void* threadParameter = NULL - ) - { - m_ThreadFunction.m_ThreadFunction = threadFunction; - m_ThreadFunction.m_ThreadParameter = threadParameter; - Start(); - } - - static CrySimpleThread* Self() - { - return reinterpret_cast*>(m_Self); - } - - void Exit() - { - assert(!"implemented"); - } - - void Stop() - { - m_bIsStarted = false; - } - - bool IsStarted() const { return m_bIsStarted; } - bool IsRunning() const { return m_bIsRunning; } -}; From bb88f1f9df98592129460f322cab9b661803606c Mon Sep 17 00:00:00 2001 From: michabr <82236305+michabr@users.noreply.github.com> Date: Mon, 9 Aug 2021 11:24:25 -0700 Subject: [PATCH 221/803] Fix input not working in Ctrl-G mode after UI Editor is opened (#2948) * Fix input not working in Ctrl-G mode after UI Editor is opened Signed-off-by: abrmich * Delete environment variable Signed-off-by: abrmich --- .../Keyboard/InputDeviceKeyboard_Windows.cpp | 22 ++++++++++++--- .../Mouse/InputDeviceMouse_Windows.cpp | 28 ++++++++++++++----- 2 files changed, 39 insertions(+), 11 deletions(-) diff --git a/Code/Framework/AzFramework/Platform/Windows/AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard_Windows.cpp b/Code/Framework/AzFramework/Platform/Windows/AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard_Windows.cpp index e92bbbc6e3..78364fbd0d 100644 --- a/Code/Framework/AzFramework/Platform/Windows/AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard_Windows.cpp +++ b/Code/Framework/AzFramework/Platform/Windows/AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard_Windows.cpp @@ -8,6 +8,7 @@ #include <../Common/WinAPI/AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard_WinAPI.h> #include +#include //////////////////////////////////////////////////////////////////////////////////////////////////// namespace @@ -29,7 +30,7 @@ namespace AzFramework { //////////////////////////////////////////////////////////////////////////////////////////// //! Count of the number instances of this class that have been created - static int s_instanceCount; + static AZ::EnvironmentVariable s_instanceCount; public: //////////////////////////////////////////////////////////////////////////////////////////// @@ -106,7 +107,7 @@ namespace AzFramework } //////////////////////////////////////////////////////////////////////////////////////////////// - int InputDeviceKeyboardWindows::s_instanceCount = 0; + AZ::EnvironmentVariable InputDeviceKeyboardWindows::s_instanceCount = nullptr; //////////////////////////////////////////////////////////////////////////////////////////////// InputDeviceKeyboardWindows::InputDeviceKeyboardWindows(InputDeviceKeyboard& inputDevice) @@ -116,8 +117,10 @@ namespace AzFramework , m_hasFocus(false) , m_hasTextEntryStarted(false) { - if (s_instanceCount++ == 0) + if (!s_instanceCount) { + s_instanceCount = AZ::Environment::CreateVariable("InputDeviceKeyboardInstanceCount", 1); + // Register for raw keyboard input RAWINPUTDEVICE rawInputDevice; rawInputDevice.usUsagePage = RAW_INPUT_KEYBOARD_USAGE_PAGE; @@ -128,6 +131,10 @@ namespace AzFramework AZ_Assert(result, "Failed to register raw input device: keyboard"); AZ_UNUSED(result); } + else + { + s_instanceCount.Set(s_instanceCount.Get() + 1); + } RawInputNotificationBusWindows::Handler::BusConnect(); } @@ -137,7 +144,8 @@ namespace AzFramework { RawInputNotificationBusWindows::Handler::BusDisconnect(); - if (--s_instanceCount == 0) + int instanceCount = s_instanceCount.Get(); + if (--instanceCount == 0) { // Deregister from raw keyboard input RAWINPUTDEVICE rawInputDevice; @@ -148,7 +156,13 @@ namespace AzFramework const BOOL result = RegisterRawInputDevices(&rawInputDevice, 1, sizeof(rawInputDevice)); AZ_Assert(result, "Failed to deregister raw input device: keyboard"); AZ_UNUSED(result); + + s_instanceCount.Reset(); } + else + { + s_instanceCount.Set(instanceCount); + } } //////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Code/Framework/AzFramework/Platform/Windows/AzFramework/Input/Devices/Mouse/InputDeviceMouse_Windows.cpp b/Code/Framework/AzFramework/Platform/Windows/AzFramework/Input/Devices/Mouse/InputDeviceMouse_Windows.cpp index 9452696cd2..464f49d620 100644 --- a/Code/Framework/AzFramework/Platform/Windows/AzFramework/Input/Devices/Mouse/InputDeviceMouse_Windows.cpp +++ b/Code/Framework/AzFramework/Platform/Windows/AzFramework/Input/Devices/Mouse/InputDeviceMouse_Windows.cpp @@ -7,6 +7,7 @@ */ #include +#include #include #include #include @@ -43,7 +44,7 @@ namespace AzFramework { //////////////////////////////////////////////////////////////////////////////////////////// //! Count of the number instances of this class that have been created - static int s_instanceCount; + static AZ::EnvironmentVariable s_instanceCount; public: //////////////////////////////////////////////////////////////////////////////////////////// @@ -125,7 +126,7 @@ namespace AzFramework } //////////////////////////////////////////////////////////////////////////////////////////////// - int InputDeviceMouseWindows::s_instanceCount = 0; + AZ::EnvironmentVariable InputDeviceMouseWindows::s_instanceCount = nullptr; //////////////////////////////////////////////////////////////////////////////////////////////// InputDeviceMouseWindows::InputDeviceMouseWindows(InputDeviceMouse& inputDevice) @@ -137,18 +138,24 @@ namespace AzFramework { memset(&m_lastClientRect, 0, sizeof(m_lastClientRect)); - if (s_instanceCount++ == 0) + if (!s_instanceCount) { + s_instanceCount = AZ::Environment::CreateVariable("InputDeviceMouseInstanceCount", 1); + // Register for raw mouse input RAWINPUTDEVICE rawInputDevice; rawInputDevice.usUsagePage = RAW_INPUT_MOUSE_USAGE_PAGE; - rawInputDevice.usUsage = RAW_INPUT_MOUSE_USAGE; - rawInputDevice.dwFlags = 0; - rawInputDevice.hwndTarget = 0; + rawInputDevice.usUsage = RAW_INPUT_MOUSE_USAGE; + rawInputDevice.dwFlags = 0; + rawInputDevice.hwndTarget = 0; const BOOL result = RegisterRawInputDevices(&rawInputDevice, 1, sizeof(rawInputDevice)); AZ_Assert(result, "Failed to register raw input device: mouse"); AZ_UNUSED(result); } + else + { + s_instanceCount.Set(s_instanceCount.Get() + 1); + } RawInputNotificationBusWindows::Handler::BusConnect(); } @@ -161,7 +168,8 @@ namespace AzFramework // Cleanup system cursor visibility and constraint SetSystemCursorState(SystemCursorState::Unknown); - if (--s_instanceCount == 0) + int instanceCount = s_instanceCount.Get(); + if (--instanceCount == 0) { // Deregister from raw mouse input RAWINPUTDEVICE rawInputDevice; @@ -172,6 +180,12 @@ namespace AzFramework const BOOL result = RegisterRawInputDevices(&rawInputDevice, 1, sizeof(rawInputDevice)); AZ_Assert(result, "Failed to deregister raw input device: mouse"); AZ_UNUSED(result); + + s_instanceCount.Reset(); + } + else + { + s_instanceCount.Set(instanceCount); } } From 6a2d5cd370ae0e35c47188531a3a7eb6d2197e1f Mon Sep 17 00:00:00 2001 From: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> Date: Mon, 9 Aug 2021 12:22:03 -0700 Subject: [PATCH 222/803] [redcode/crythread-2nd-pass] removed Cry-TLS macros from platform.h Signed-off-by: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> --- Code/Legacy/CryCommon/platform.h | 54 -------------------------------- 1 file changed, 54 deletions(-) diff --git a/Code/Legacy/CryCommon/platform.h b/Code/Legacy/CryCommon/platform.h index 6aad8dd043..851da316e0 100644 --- a/Code/Legacy/CryCommon/platform.h +++ b/Code/Legacy/CryCommon/platform.h @@ -277,18 +277,6 @@ #define PRINTF_EMPTY_FORMAT "" #endif -#if defined(IOS) -#define USE_PTHREAD_TLS -#endif - -// Storage class modifier for thread local storage. -// THEADLOCAL should NOT be defined to empty because that creates some -// really hard to find issues. -#if !defined(USE_PTHREAD_TLS) -# define THREADLOCAL AZ_TRAIT_COMPILER_THREAD_LOCAL -#endif //!defined(USE_PTHREAD_TLS) - - ////////////////////////////////////////////////////////////////////////// // define Read Write Barrier macro needed for lockless programming @@ -735,48 +723,6 @@ enum ETriState #define _MS_ALIGN(num) AZ_PUSH_DISABLE_WARNING(4324, "-Wunknown-warning-option") #endif -#if defined(WIN32) || defined(WIN64) -extern "C" { -__declspec(dllimport) unsigned long __stdcall TlsAlloc(); -__declspec(dllimport) void* __stdcall TlsGetValue(unsigned long dwTlsIndex); -__declspec(dllimport) int __stdcall TlsSetValue(unsigned long dwTlsIndex, void* lpTlsValue); -} - - #define TLS_DECLARE(type, var) extern int var##idx; - #define TLS_DEFINE(type, var) \ - int var##idx; \ - struct Init##var { \ - Init##var() { var##idx = TlsAlloc(); } \ - }; \ - Init##var g_init##var; - #define TLS_DEFINE_DEFAULT_VALUE(type, var, value) \ - int var##idx; \ - struct Init##var { \ - Init##var() { var##idx = TlsAlloc(); TlsSetValue(var##idx, reinterpret_cast(value)); } \ - }; \ - Init##var g_init##var; - #define TLS_GET(type, var) (type)TlsGetValue(var##idx) - #define TLS_SET(var, val) TlsSetValue(var##idx, reinterpret_cast(val)) -#elif defined(USE_PTHREAD_TLS) - #define TLS_DECLARE(_TYPE, _VAR) extern SCryPthreadTLS<_TYPE> _VAR##TLSKey; - #define TLS_DEFINE(_TYPE, _VAR) SCryPthreadTLS<_TYPE> _VAR##TLSKey; - #define TLS_DEFINE_DEFAULT_VALUE(_TYPE, _VAR, _DEFAULT) SCryPthreadTLS<_TYPE> _VAR##TLSKey = _DEFAULT; - #define TLS_GET(_TYPE, _VAR) _VAR##TLSKey.Get() - #define TLS_SET(_VAR, _VALUE) _VAR##TLSKey.Set(_VALUE) -#elif defined(THREADLOCAL) - #define TLS_DECLARE(type, var) extern THREADLOCAL type var; -#if defined(LINUX) || defined(MAC) - #define TLS_DEFINE(type, var) THREADLOCAL type var = 0; -#else - #define TLS_DEFINE(type, var) THREADLOCAL type var; -#endif // defined(LINUX) || defined(MAC) - #define TLS_DEFINE_DEFAULT_VALUE(type, var, value) THREADLOCAL type var = value; - #define TLS_GET(type, var) (var) - #define TLS_SET(var, val) (var = (val)) -#else // defined(THREADLOCAL) - #error "There's no support for thread local storage" -#endif - #if defined(AZ_RESTRICTED_PLATFORM) #define AZ_RESTRICTED_SECTION PLATFORM_H_SECTION_13 #include AZ_RESTRICTED_FILE(platform_h) From c7397fe4a2eea9cdb2ff3a5f59fc91f67e20ea29 Mon Sep 17 00:00:00 2001 From: Junbo Liang <68558268+junbo75@users.noreply.github.com> Date: Mon, 9 Aug 2021 13:00:43 -0700 Subject: [PATCH 223/803] Fix AWSTests.periodic failing on Linux due to a File Not Found error Signed-off-by: junbo --- AutomatedTesting/Gem/PythonTests/AWS/CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/AutomatedTesting/Gem/PythonTests/AWS/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/AWS/CMakeLists.txt index 1c555c1e17..a589a395c1 100644 --- a/AutomatedTesting/Gem/PythonTests/AWS/CMakeLists.txt +++ b/AutomatedTesting/Gem/PythonTests/AWS/CMakeLists.txt @@ -12,6 +12,11 @@ ################################################################################ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) + # Only enable AWS automated tests on Windows + if(NOT "${PAL_PLATFORM_NAME}" STREQUAL "Windows") + return() + endif() + # Enable after installing NodeJS and CDK on jenkins Windows AMI. ly_add_pytest( NAME AutomatedTesting::AWSTests From cb52418a92d083dd3e0de3e2edc538f08760fd15 Mon Sep 17 00:00:00 2001 From: lsemp3d <58790905+lsemp3d@users.noreply.github.com> Date: Mon, 9 Aug 2021 13:05:23 -0700 Subject: [PATCH 224/803] Open the EMFX editor even if no asset is specified Signed-off-by: lsemp3d <58790905+lsemp3d@users.noreply.github.com> --- .../Editor/Components/EditorAnimGraphComponent.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Gems/EMotionFX/Code/Source/Integration/Editor/Components/EditorAnimGraphComponent.cpp b/Gems/EMotionFX/Code/Source/Integration/Editor/Components/EditorAnimGraphComponent.cpp index eef41bc919..8721acbf3d 100644 --- a/Gems/EMotionFX/Code/Source/Integration/Editor/Components/EditorAnimGraphComponent.cpp +++ b/Gems/EMotionFX/Code/Source/Integration/Editor/Components/EditorAnimGraphComponent.cpp @@ -117,16 +117,16 @@ namespace EMotionFX void EditorAnimGraphComponent::LaunchAnimationEditor(const AZ::Data::AssetId& assetId, [[maybe_unused]] const AZ::Data::AssetType& assetType) { + // call to open must be done before LoadCharacter + const char* panelName = EMStudio::MainWindow::GetEMotionFXPaneName(); + EBUS_EVENT(AzToolsFramework::EditorRequests::Bus, OpenViewPane, panelName); + if (assetId.IsValid()) { AZ::Data::AssetId actorAssetId; actorAssetId.SetInvalid(); EditorActorComponentRequestBus::EventResult(actorAssetId, GetEntityId(), &EditorActorComponentRequestBus::Events::GetActorAssetId); - // call to open must be done before LoadCharacter - const char* panelName = EMStudio::MainWindow::GetEMotionFXPaneName(); - EBUS_EVENT(AzToolsFramework::EditorRequests::Bus, OpenViewPane, panelName); - EMStudio::MainWindow* mainWindow = EMStudio::GetMainWindow(); if (mainWindow) { From 89602aaa63a7dba0b1aea611750c4f5e2058fda4 Mon Sep 17 00:00:00 2001 From: Vincent Liu <5900509+onecent1101@users.noreply.github.com> Date: Mon, 9 Aug 2021 13:06:28 -0700 Subject: [PATCH 225/803] [SPEC-7931] Filter list_buckets results based on region during import (#2950) Filter s3 list_buckets results based on region correctly to improve resource import. Signed-off-by: onecent1101 --- .../tests/unit/utils/test_aws_utils.py | 44 +++++++++++++++++-- .../ResourceMappingTool/utils/aws_utils.py | 12 ++++- 2 files changed, 51 insertions(+), 5 deletions(-) diff --git a/Gems/AWSCore/Code/Tools/ResourceMappingTool/tests/unit/utils/test_aws_utils.py b/Gems/AWSCore/Code/Tools/ResourceMappingTool/tests/unit/utils/test_aws_utils.py index 397472d252..9dd4fbd5be 100755 --- a/Gems/AWSCore/Code/Tools/ResourceMappingTool/tests/unit/utils/test_aws_utils.py +++ b/Gems/AWSCore/Code/Tools/ResourceMappingTool/tests/unit/utils/test_aws_utils.py @@ -98,16 +98,52 @@ class TestAWSUtils(TestCase): mocked_s3_client.list_buckets.assert_called_once() assert not actual_buckets - def test_list_s3_buckets_return_expected_buckets(self) -> None: + def test_list_s3_buckets_return_empty_list_with_no_matching_region(self) -> None: + expected_region: str = "us-east-1" mocked_s3_client: MagicMock = self._mock_client.return_value expected_buckets: List[str] = [f"{TestAWSUtils._expected_bucket}1", f"{TestAWSUtils._expected_bucket}2"] mocked_s3_client.list_buckets.return_value = {"Buckets": [{"Name": expected_buckets[0]}, {"Name": expected_buckets[1]}]} + mocked_s3_client.get_bucket_location.side_effect = [{"LocationConstraint": "us-east-2"}, + {"LocationConstraint": "us-west-1"}] - actual_buckets: List[str] = aws_utils.list_s3_buckets() - self._mock_client.assert_called_once_with(aws_utils.AWSConstants.S3_SERVICE_NAME) + actual_buckets: List[str] = aws_utils.list_s3_buckets(expected_region) + self._mock_client.assert_called_once_with(aws_utils.AWSConstants.S3_SERVICE_NAME, + region_name=expected_region) mocked_s3_client.list_buckets.assert_called_once() - assert actual_buckets == expected_buckets + assert not actual_buckets + + def test_list_s3_buckets_return_expected_buckets_matching_region(self) -> None: + expected_region: str = "us-west-2" + mocked_s3_client: MagicMock = self._mock_client.return_value + expected_buckets: List[str] = [f"{TestAWSUtils._expected_bucket}1", f"{TestAWSUtils._expected_bucket}2"] + mocked_s3_client.list_buckets.return_value = {"Buckets": [{"Name": expected_buckets[0]}, + {"Name": expected_buckets[1]}]} + mocked_s3_client.get_bucket_location.side_effect = [{"LocationConstraint": "us-west-2"}, + {"LocationConstraint": "us-west-1"}] + + actual_buckets: List[str] = aws_utils.list_s3_buckets(expected_region) + self._mock_client.assert_called_once_with(aws_utils.AWSConstants.S3_SERVICE_NAME, + region_name=expected_region) + mocked_s3_client.list_buckets.assert_called_once() + assert len(actual_buckets) == 1 + assert actual_buckets[0] == expected_buckets[0] + + def test_list_s3_buckets_return_expected_iad_buckets(self) -> None: + expected_region: str = "us-east-1" + mocked_s3_client: MagicMock = self._mock_client.return_value + expected_buckets: List[str] = [f"{TestAWSUtils._expected_bucket}1", f"{TestAWSUtils._expected_bucket}2"] + mocked_s3_client.list_buckets.return_value = {"Buckets": [{"Name": expected_buckets[0]}, + {"Name": expected_buckets[1]}]} + mocked_s3_client.get_bucket_location.side_effect = [{"LocationConstraint": None}, + {"LocationConstraint": "us-west-1"}] + + actual_buckets: List[str] = aws_utils.list_s3_buckets(expected_region) + self._mock_client.assert_called_once_with(aws_utils.AWSConstants.S3_SERVICE_NAME, + region_name=expected_region) + mocked_s3_client.list_buckets.assert_called_once() + assert len(actual_buckets) == 1 + assert actual_buckets[0] == expected_buckets[0] def test_list_lambda_functions_return_empty_list(self) -> None: mocked_lambda_client: MagicMock = self._mock_client.return_value diff --git a/Gems/AWSCore/Code/Tools/ResourceMappingTool/utils/aws_utils.py b/Gems/AWSCore/Code/Tools/ResourceMappingTool/utils/aws_utils.py index dded35efed..0344834298 100755 --- a/Gems/AWSCore/Code/Tools/ResourceMappingTool/utils/aws_utils.py +++ b/Gems/AWSCore/Code/Tools/ResourceMappingTool/utils/aws_utils.py @@ -103,7 +103,17 @@ def list_s3_buckets(region: str = "") -> List[str]: bucket_names: List[str] = [] bucket: Dict[str, any] for bucket in response["Buckets"]: - bucket_names.append(bucket["Name"]) + try: + bucket_name: str = bucket["Name"] + location_response: Dict[str, any] = s3_client.get_bucket_location(Bucket=bucket_name) + # Buckets in Region us-east-1 have a LocationConstraint of null . + # https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/s3.html#S3.Client.get_bucket_location + if ((location_response["LocationConstraint"] == region) or + (not location_response["LocationConstraint"] and region == "us-east-1")): + bucket_names.append(bucket_name) + except ClientError as error: + raise RuntimeError(error_messages.AWS_SERVICE_REQUEST_CLIENT_ERROR_MESSAGE.format( + "get_bucket_location", error.response['Error']['Code'], error.response['Error']['Message'])) return bucket_names From cf7681df2741188679fbb397487d3bc46ad30d86 Mon Sep 17 00:00:00 2001 From: Nicholas Lawson <70027408+lawsonamzn@users.noreply.github.com> Date: Mon, 9 Aug 2021 13:16:24 -0700 Subject: [PATCH 226/803] Updates the zlib that O3DE uses to the one in 3p-package-source (#2861) * Updates o3de to use the new zlib packages. Packages were uploaded for every supported platform. Signed-off-by: lawsonamzn <70027408+lawsonamzn@users.noreply.github.com> --- cmake/3rdParty/Platform/Android/BuiltInPackages_android.cmake | 2 +- cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake | 4 +++- cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake | 2 +- cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake | 2 +- cmake/3rdParty/Platform/iOS/BuiltInPackages_ios.cmake | 2 +- 5 files changed, 7 insertions(+), 5 deletions(-) diff --git a/cmake/3rdParty/Platform/Android/BuiltInPackages_android.cmake b/cmake/3rdParty/Platform/Android/BuiltInPackages_android.cmake index d6e7172324..ab7432e09e 100644 --- a/cmake/3rdParty/Platform/Android/BuiltInPackages_android.cmake +++ b/cmake/3rdParty/Platform/Android/BuiltInPackages_android.cmake @@ -7,7 +7,6 @@ # # shared by other platforms: -ly_associate_package(PACKAGE_NAME zlib-1.2.8-rev2-multiplatform TARGETS zlib PACKAGE_HASH e6f34b8ac16acf881e3d666ef9fd0c1aee94c3f69283fb6524d35d6f858eebbb) ly_associate_package(PACKAGE_NAME md5-2.0-multiplatform TARGETS md5 PACKAGE_HASH 29e52ad22c78051551f78a40c2709594f0378762ae03b417adca3f4b700affdf) ly_associate_package(PACKAGE_NAME RapidJSON-1.1.0-multiplatform TARGETS RapidJSON PACKAGE_HASH 18b0aef4e6e849389916ff6de6682ab9c591ebe15af6ea6017014453c1119ea1) ly_associate_package(PACKAGE_NAME RapidXML-1.13-multiplatform TARGETS RapidXML PACKAGE_HASH 510b3c12f8872c54b34733e34f2f69dd21837feafa55bfefa445c98318d96ebf) @@ -28,3 +27,4 @@ ly_associate_package(PACKAGE_NAME googletest-1.8.1-rev4-android TARGETS goo ly_associate_package(PACKAGE_NAME googlebenchmark-1.5.0-rev2-android TARGETS GoogleBenchmark PACKAGE_HASH 20b46e572211a69d7d94ddad1c89ec37bb958711d6ad4025368ac89ea83078fb) ly_associate_package(PACKAGE_NAME libsamplerate-0.2.1-rev2-android TARGETS libsamplerate PACKAGE_HASH bf13662afe65d02bcfa16258a4caa9b875534978227d6f9f36c9cfa92b3fb12b) ly_associate_package(PACKAGE_NAME OpenSSL-1.1.1b-rev1-android TARGETS OpenSSL PACKAGE_HASH 4036d4019d722f0e1b7a1621bf60b5a17ca6a65c9c78fd8701cee1131eec8480) +ly_associate_package(PACKAGE_NAME zlib-1.2.11-rev1-android TARGETS zlib PACKAGE_HASH 832b163cae0cccbe4fddc5988f5725fac56ef7dba5bfe95bf8c71281fba2e12c) diff --git a/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake b/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake index 7bb2c61774..bb70a54d6f 100644 --- a/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake +++ b/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake @@ -7,7 +7,6 @@ # # shared by other platforms: -ly_associate_package(PACKAGE_NAME zlib-1.2.8-rev2-multiplatform TARGETS zlib PACKAGE_HASH e6f34b8ac16acf881e3d666ef9fd0c1aee94c3f69283fb6524d35d6f858eebbb) ly_associate_package(PACKAGE_NAME ilmbase-2.3.0-rev4-multiplatform TARGETS ilmbase PACKAGE_HASH 97547fdf1fbc4d81b8ccf382261f8c25514ed3b3c4f8fd493f0a4fa873bba348) ly_associate_package(PACKAGE_NAME hdf5-1.0.11-rev2-multiplatform TARGETS hdf5 PACKAGE_HASH 11d5e04df8a93f8c52a5684a4cacbf0d9003056360983ce34f8d7b601082c6bd) ly_associate_package(PACKAGE_NAME assimp-5.0.1-rev11-multiplatform TARGETS assimplib PACKAGE_HASH 1a9113788b893ef4a2ee63ac01eb71b981a92894a5a51175703fa225f5804dec) @@ -46,3 +45,6 @@ ly_associate_package(PACKAGE_NAME OpenSSL-1.1.1b-rev2-linux ly_associate_package(PACKAGE_NAME DirectXShaderCompilerDxc-1.6.2104-o3de-rev2-linux TARGETS DirectXShaderCompilerDxc PACKAGE_HASH 235606f98512c076a1ba84a8402ad24ac21945998abcea264e8e204678efc0ba) ly_associate_package(PACKAGE_NAME SPIRVCross-2021.04.29-rev1-linux TARGETS SPIRVCross PACKAGE_HASH 7889ee5460a688e9b910c0168b31445c0079d363affa07b25d4c8aeb608a0b80) ly_associate_package(PACKAGE_NAME azslc-1.7.23-rev2-linux TARGETS azslc PACKAGE_HASH 1ba84d8321a566d35a1e9aa7400211ba8e6d1c11c08e4be3c93e6e74b8f7aef1) +ly_associate_package(PACKAGE_NAME zlib-1.2.11-rev1-linux TARGETS zlib PACKAGE_HASH 6418e93b9f4e6188f3b62cbd3a7822e1c4398a716e786d1522b809a727d08ba9) + + diff --git a/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake b/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake index bdffbd5dc7..e66dfdaca1 100644 --- a/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake +++ b/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake @@ -7,7 +7,6 @@ # # shared by other platforms: -ly_associate_package(PACKAGE_NAME zlib-1.2.8-rev2-multiplatform TARGETS zlib PACKAGE_HASH e6f34b8ac16acf881e3d666ef9fd0c1aee94c3f69283fb6524d35d6f858eebbb) ly_associate_package(PACKAGE_NAME ilmbase-2.3.0-rev4-multiplatform TARGETS ilmbase PACKAGE_HASH 97547fdf1fbc4d81b8ccf382261f8c25514ed3b3c4f8fd493f0a4fa873bba348) ly_associate_package(PACKAGE_NAME hdf5-1.0.11-rev2-multiplatform TARGETS hdf5 PACKAGE_HASH 11d5e04df8a93f8c52a5684a4cacbf0d9003056360983ce34f8d7b601082c6bd) ly_associate_package(PACKAGE_NAME assimp-5.0.1-rev11-multiplatform TARGETS assimplib PACKAGE_HASH 1a9113788b893ef4a2ee63ac01eb71b981a92894a5a51175703fa225f5804dec) @@ -44,3 +43,4 @@ ly_associate_package(PACKAGE_NAME googlebenchmark-1.5.0-rev2-mac ly_associate_package(PACKAGE_NAME OpenSSL-1.1.1b-rev1-mac TARGETS OpenSSL PACKAGE_HASH 28adc1c0616ac0482b2a9d7b4a3a3635a1020e87b163f8aba687c501cf35f96c) ly_associate_package(PACKAGE_NAME qt-5.15.2-rev5-mac TARGETS Qt PACKAGE_HASH 9d25918351898b308ded3e9e571fff6f26311b2071aeafd00dd5b249fdf53f7e) ly_associate_package(PACKAGE_NAME libsamplerate-0.2.1-rev2-mac TARGETS libsamplerate PACKAGE_HASH b912af40c0ac197af9c43d85004395ba92a6a859a24b7eacd920fed5854a97fe) +ly_associate_package(PACKAGE_NAME zlib-1.2.11-rev1-mac TARGETS zlib PACKAGE_HASH 7fd8a77b3598423d9d6be5f8c60d52aecf346ab4224f563a5282db283aa0da02) diff --git a/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake b/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake index 0134a45565..4ac5fea18c 100644 --- a/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake +++ b/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake @@ -7,7 +7,6 @@ # # shared by other platforms: -ly_associate_package(PACKAGE_NAME zlib-1.2.8-rev2-multiplatform TARGETS zlib PACKAGE_HASH e6f34b8ac16acf881e3d666ef9fd0c1aee94c3f69283fb6524d35d6f858eebbb) ly_associate_package(PACKAGE_NAME ilmbase-2.3.0-rev4-multiplatform TARGETS ilmbase PACKAGE_HASH 97547fdf1fbc4d81b8ccf382261f8c25514ed3b3c4f8fd493f0a4fa873bba348) ly_associate_package(PACKAGE_NAME hdf5-1.0.11-rev2-multiplatform TARGETS hdf5 PACKAGE_HASH 11d5e04df8a93f8c52a5684a4cacbf0d9003056360983ce34f8d7b601082c6bd) ly_associate_package(PACKAGE_NAME assimp-5.0.1-rev11-multiplatform TARGETS assimplib PACKAGE_HASH 1a9113788b893ef4a2ee63ac01eb71b981a92894a5a51175703fa225f5804dec) @@ -52,3 +51,4 @@ ly_associate_package(PACKAGE_NAME OpenMesh-8.1-rev1-windows ly_associate_package(PACKAGE_NAME civetweb-1.8-rev1-windows TARGETS civetweb PACKAGE_HASH 36d0e58a59bcdb4dd70493fb1b177aa0354c945b06c30416348fd326cf323dd4) ly_associate_package(PACKAGE_NAME OpenSSL-1.1.1b-rev2-windows TARGETS OpenSSL PACKAGE_HASH 9af1c50343f89146b4053101a7aeb20513319a3fe2f007e356d7ce25f9241040) ly_associate_package(PACKAGE_NAME Crashpad-0.8.0-rev1-windows TARGETS Crashpad PACKAGE_HASH d162aa3070147bc0130a44caab02c5fe58606910252caf7f90472bd48d4e31e2) +ly_associate_package(PACKAGE_NAME zlib-1.2.11-rev1-windows TARGETS zlib PACKAGE_HASH 6fb46a0ef8c8614cde3517b50fca47f2a6d1fd059b21f3b8ff13e635ca7f2fa6) diff --git a/cmake/3rdParty/Platform/iOS/BuiltInPackages_ios.cmake b/cmake/3rdParty/Platform/iOS/BuiltInPackages_ios.cmake index b058183c5a..ac7a7427ca 100644 --- a/cmake/3rdParty/Platform/iOS/BuiltInPackages_ios.cmake +++ b/cmake/3rdParty/Platform/iOS/BuiltInPackages_ios.cmake @@ -7,7 +7,6 @@ # # shared by other platforms: -ly_associate_package(PACKAGE_NAME zlib-1.2.8-rev2-multiplatform TARGETS zlib PACKAGE_HASH e6f34b8ac16acf881e3d666ef9fd0c1aee94c3f69283fb6524d35d6f858eebbb) ly_associate_package(PACKAGE_NAME md5-2.0-multiplatform TARGETS md5 PACKAGE_HASH 29e52ad22c78051551f78a40c2709594f0378762ae03b417adca3f4b700affdf) ly_associate_package(PACKAGE_NAME RapidJSON-1.1.0-multiplatform TARGETS RapidJSON PACKAGE_HASH 18b0aef4e6e849389916ff6de6682ab9c591ebe15af6ea6017014453c1119ea1) ly_associate_package(PACKAGE_NAME RapidXML-1.13-multiplatform TARGETS RapidXML PACKAGE_HASH 510b3c12f8872c54b34733e34f2f69dd21837feafa55bfefa445c98318d96ebf) @@ -29,3 +28,4 @@ ly_associate_package(PACKAGE_NAME googletest-1.8.1-rev4-ios TARGETS googlet ly_associate_package(PACKAGE_NAME googlebenchmark-1.5.0-rev2-ios TARGETS GoogleBenchmark PACKAGE_HASH c2ffaed2b658892b1bcf81dee4b44cd1cb09fc78d55584ef5cb8ab87f2d8d1ae) ly_associate_package(PACKAGE_NAME libsamplerate-0.2.1-rev2-ios TARGETS libsamplerate PACKAGE_HASH 7656b961697f490d4f9c35d2e61559f6fc38c32102e542a33c212cd618fc2119) ly_associate_package(PACKAGE_NAME OpenSSL-1.1.1b-rev1-ios TARGETS OpenSSL PACKAGE_HASH cd0dfce3086a7172777c63dadbaf0ac3695b676119ecb6d0614b5fb1da03462f) +ly_associate_package(PACKAGE_NAME zlib-1.2.11-rev1-ios TARGETS zlib PACKAGE_HASH 20bfccf3b98bd9a7d3506cf344ac48135035eb517752bf9bede1e821f163608d) From 2e2bbe80b118e5481a8be0b275ec039cf4ee3a7e Mon Sep 17 00:00:00 2001 From: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> Date: Mon, 9 Aug 2021 13:19:41 -0700 Subject: [PATCH 227/803] [redcode/crythread-2nd-pass] removed CryEvent types Signed-off-by: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> --- .../Legacy/CryCommon/CryThreadImpl_pthreads.h | 47 ------------------- Code/Legacy/CryCommon/CryThreadImpl_windows.h | 39 --------------- Code/Legacy/CryCommon/CryThread_pthreads.h | 34 -------------- Code/Legacy/CryCommon/CryThread_windows.h | 30 ------------ 4 files changed, 150 deletions(-) diff --git a/Code/Legacy/CryCommon/CryThreadImpl_pthreads.h b/Code/Legacy/CryCommon/CryThreadImpl_pthreads.h index 358d8f962f..38838991a8 100644 --- a/Code/Legacy/CryCommon/CryThreadImpl_pthreads.h +++ b/Code/Legacy/CryCommon/CryThreadImpl_pthreads.h @@ -14,53 +14,6 @@ #include "CryThread_pthreads.h" - -////////////////////////////////////////////////////////////////////////// -// CryEvent(Timed) implementation -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -void CryEventTimed::Reset() -{ - m_lockNotify.Lock(); - m_flag = false; - m_lockNotify.Unlock(); -} - -////////////////////////////////////////////////////////////////////////// -void CryEventTimed::Set() -{ - m_lockNotify.Lock(); - m_flag = true; - m_cond.Notify(); - m_lockNotify.Unlock(); -} - -////////////////////////////////////////////////////////////////////////// -void CryEventTimed::Wait() -{ - m_lockNotify.Lock(); - if (!m_flag) - { - m_cond.Wait(m_lockNotify); - } - m_flag = false; - m_lockNotify.Unlock(); -} - -////////////////////////////////////////////////////////////////////////// -bool CryEventTimed::Wait(const uint32 timeoutMillis) -{ - bool bResult = true; - m_lockNotify.Lock(); - if (!m_flag) - { - bResult = m_cond.TimedWait(m_lockNotify, timeoutMillis); - } - m_flag = false; - m_lockNotify.Unlock(); - return bResult; -} - /////////////////////////////////////////////////////////////////////////////// // CryCriticalSection implementation /////////////////////////////////////////////////////////////////////////////// diff --git a/Code/Legacy/CryCommon/CryThreadImpl_windows.h b/Code/Legacy/CryCommon/CryThreadImpl_windows.h index 9d636fd41a..d81f3b0689 100644 --- a/Code/Legacy/CryCommon/CryThreadImpl_windows.h +++ b/Code/Legacy/CryCommon/CryThreadImpl_windows.h @@ -12,45 +12,6 @@ #include #include // for CreateSemaphore -////////////////////////////////////////////////////////////////////////// -CryEvent::CryEvent() -{ - m_handle = (void*)CreateEvent(NULL, FALSE, FALSE, NULL); -} - -////////////////////////////////////////////////////////////////////////// -CryEvent::~CryEvent() -{ - CloseHandle(m_handle); -} - -////////////////////////////////////////////////////////////////////////// -void CryEvent::Reset() -{ - ResetEvent(m_handle); -} - -////////////////////////////////////////////////////////////////////////// -void CryEvent::Set() -{ - SetEvent(m_handle); -} - -////////////////////////////////////////////////////////////////////////// -void CryEvent::Wait() const -{ - WaitForSingleObject(m_handle, INFINITE); -} - -////////////////////////////////////////////////////////////////////////// -bool CryEvent::Wait(const uint32 timeoutMillis) const -{ - if (WaitForSingleObject(m_handle, timeoutMillis) == WAIT_TIMEOUT) - { - return false; - } - return true; -} ////////////////////////////////////////////////////////////////////////// // CryLock_WinMutex diff --git a/Code/Legacy/CryCommon/CryThread_pthreads.h b/Code/Legacy/CryCommon/CryThread_pthreads.h index 9102c12c38..8dd4bfba6c 100644 --- a/Code/Legacy/CryCommon/CryThread_pthreads.h +++ b/Code/Legacy/CryCommon/CryThread_pthreads.h @@ -619,38 +619,4 @@ struct SCryPthreadTLS { }; - -////////////////////////////////////////////////////////////////////////// -// CryEvent(Timed) represent a synchronization event -////////////////////////////////////////////////////////////////////////// -class CryEventTimed -{ -public: - ILINE CryEventTimed(){m_flag = false; } - ILINE ~CryEventTimed(){} - - // Reset the event to the unsignalled state. - void Reset(); - // Set the event to the signalled state. - void Set(); - // Access a HANDLE to wait on. - void* GetHandle() const { return NULL; }; - // Wait indefinitely for the object to become signalled. - void Wait(); - // Wait, with a time limit, for the object to become signalled. - bool Wait(const uint32 timeoutMillis); - -private: - // Lock for synchronization of notifications. - CryCriticalSection m_lockNotify; -#if defined(LINUX) || defined(APPLE) - CryConditionVariableT< CryLockT > m_cond; -#else - CryConditionVariable m_cond; -#endif - volatile bool m_flag; -}; - -typedef CryEventTimed CryEvent; - #include "MemoryAccess.h" diff --git a/Code/Legacy/CryCommon/CryThread_windows.h b/Code/Legacy/CryCommon/CryThread_windows.h index 87147549f7..68908ab34a 100644 --- a/Code/Legacy/CryCommon/CryThread_windows.h +++ b/Code/Legacy/CryCommon/CryThread_windows.h @@ -17,36 +17,6 @@ #define CRYTHREAD_WINDOWS_H_SECTION_2 2 #endif -////////////////////////////////////////////////////////////////////////// -// CryEvent represent a synchronization event -////////////////////////////////////////////////////////////////////////// -class CryEvent -{ -public: - CryEvent(); - ~CryEvent(); - - // Reset the event to the unsignalled state. - void Reset(); - // Set the event to the signalled state. - void Set(); - // Access a HANDLE to wait on. - void* GetHandle() const { return m_handle; }; - // Wait indefinitely for the object to become signalled. - void Wait() const; - // Wait, with a time limit, for the object to become signalled. - bool Wait(const uint32 timeoutMillis) const; - -private: - CryEvent(const CryEvent&); - CryEvent& operator = (const CryEvent&); - -private: - void* m_handle; -}; - -typedef CryEvent CryEventTimed; - ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// From f47b8b534ba7abb2b24cd6cf29bb0a025c8ce2c3 Mon Sep 17 00:00:00 2001 From: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> Date: Mon, 9 Aug 2021 14:03:42 -0700 Subject: [PATCH 228/803] [redcode/crythread-2nd-pass] removed unused CryConditionVariable in CryEdit Signed-off-by: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> --- Code/Editor/CryEdit.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/Code/Editor/CryEdit.cpp b/Code/Editor/CryEdit.cpp index cd1dd4fe47..5a5b17f799 100644 --- a/Code/Editor/CryEdit.cpp +++ b/Code/Editor/CryEdit.cpp @@ -892,7 +892,6 @@ CCrySingleDocTemplate::Confidence CCrySingleDocTemplate::MatchDocType(LPCTSTR lp namespace { CryMutex g_splashScreenStateLock; - CryConditionVariable g_splashScreenStateChange; enum ESplashScreenState { eSplashScreenState_Init, eSplashScreenState_Started, eSplashScreenState_Destroy @@ -932,7 +931,6 @@ void CCryEditApp::ShowSplashScreen(CCryEditApp* app) g_splashScreenState = eSplashScreenState_Started; g_splashScreenStateLock.Unlock(); - g_splashScreenStateChange.Notify(); splashScreen->show(); // Make sure the initial paint of the splash screen occurs so we dont get stuck with a blank window From 2408f7dc37acdb302026743d08ce13238e5ec3a8 Mon Sep 17 00:00:00 2001 From: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> Date: Mon, 9 Aug 2021 14:49:29 -0700 Subject: [PATCH 229/803] [redcode/crythread-2nd-pass] removed more unused code from CryThread Signed-off-by: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> --- Code/Legacy/CryCommon/CryThreadImpl_windows.h | 177 -------- Code/Legacy/CryCommon/CryThread_pthreads.h | 423 ------------------ Code/Legacy/CryCommon/CryThread_windows.h | 56 --- 3 files changed, 656 deletions(-) diff --git a/Code/Legacy/CryCommon/CryThreadImpl_windows.h b/Code/Legacy/CryCommon/CryThreadImpl_windows.h index d81f3b0689..9157bde9bc 100644 --- a/Code/Legacy/CryCommon/CryThreadImpl_windows.h +++ b/Code/Legacy/CryCommon/CryThreadImpl_windows.h @@ -76,180 +76,3 @@ bool CryLock_CritSection::TryLock() { return TryEnterCriticalSection((CRITICAL_SECTION*)&m_cs) != FALSE; } - -////////////////////////////////////////////////////////////////////////// -// most of this is taken from http://www.cs.wustl.edu/~schmidt/win32-cv-1.html -////////////////////////////////////////////////////////////////////////// -CryConditionVariable::CryConditionVariable() -{ - m_waitersCount = 0; - m_wasBroadcast = 0; - m_sema = CreateSemaphore(NULL, 0, 0x7fffffff, NULL); - InitializeCriticalSection((CRITICAL_SECTION*)&m_waitersCountLock); - m_waitersDone = CreateEvent(NULL, FALSE, FALSE, NULL); -} - -////////////////////////////////////////////////////////////////////////// -CryConditionVariable::~CryConditionVariable() -{ - CloseHandle(m_sema); - DeleteCriticalSection((CRITICAL_SECTION*)&m_waitersCountLock); - CloseHandle(m_waitersDone); -} - -////////////////////////////////////////////////////////////////////////// -void CryConditionVariable::Wait(LockType& lock) -{ - EnterCriticalSection((CRITICAL_SECTION*)&m_waitersCountLock); - m_waitersCount++; - LeaveCriticalSection((CRITICAL_SECTION*)&m_waitersCountLock); - - SignalObjectAndWait(lock._get_win32_handle(), m_sema, INFINITE, FALSE); - - EnterCriticalSection((CRITICAL_SECTION*)&m_waitersCountLock); - m_waitersCount--; - bool lastWaiter = m_wasBroadcast && m_waitersCount == 0; - LeaveCriticalSection((CRITICAL_SECTION*)&m_waitersCountLock); - - if (lastWaiter) - { - SignalObjectAndWait(m_waitersDone, lock._get_win32_handle(), INFINITE, FALSE); - } - else - { - WaitForSingleObject(lock._get_win32_handle(), INFINITE); - } -} - -////////////////////////////////////////////////////////////////////////// -bool CryConditionVariable::TimedWait(LockType& lock, uint32 millis) -{ - EnterCriticalSection((CRITICAL_SECTION*)&m_waitersCountLock); - m_waitersCount++; - LeaveCriticalSection((CRITICAL_SECTION*)&m_waitersCountLock); - - bool ok = true; - if (WAIT_TIMEOUT == SignalObjectAndWait(lock._get_win32_handle(), m_sema, millis, FALSE)) - { - ok = false; - } - - EnterCriticalSection((CRITICAL_SECTION*)&m_waitersCountLock); - m_waitersCount--; - bool lastWaiter = m_wasBroadcast && m_waitersCount == 0; - LeaveCriticalSection((CRITICAL_SECTION*)&m_waitersCountLock); - - if (lastWaiter) - { - SignalObjectAndWait(m_waitersDone, lock._get_win32_handle(), INFINITE, FALSE); - } - else - { - WaitForSingleObject(lock._get_win32_handle(), INFINITE); - } - - return ok; -} - -////////////////////////////////////////////////////////////////////////// -void CryConditionVariable::NotifySingle() -{ - EnterCriticalSection((CRITICAL_SECTION*)&m_waitersCountLock); - bool haveWaiters = m_waitersCount > 0; - LeaveCriticalSection((CRITICAL_SECTION*)&m_waitersCountLock); - if (haveWaiters) - { - ReleaseSemaphore(m_sema, 1, 0); - } -} - -////////////////////////////////////////////////////////////////////////// -void CryConditionVariable::Notify() -{ - EnterCriticalSection((CRITICAL_SECTION*)&m_waitersCountLock); - bool haveWaiters = false; - if (m_waitersCount > 0) - { - m_wasBroadcast = 1; - haveWaiters = true; - } - if (haveWaiters) - { - ReleaseSemaphore(m_sema, m_waitersCount, 0); - LeaveCriticalSection((CRITICAL_SECTION*)&m_waitersCountLock); - WaitForSingleObject(m_waitersDone, INFINITE); - m_wasBroadcast = 0; - } - else - { - LeaveCriticalSection((CRITICAL_SECTION*)&m_waitersCountLock); - } -} - -////////////////////////////////////////////////////////////////////////// -CrySemaphore::CrySemaphore(int nMaximumCount, int nInitialCount) -{ - m_Semaphore = (void*)CreateSemaphore(NULL, nInitialCount, nMaximumCount, NULL); -} - -////////////////////////////////////////////////////////////////////////// -CrySemaphore::~CrySemaphore() -{ - CloseHandle((HANDLE)m_Semaphore); -} - -////////////////////////////////////////////////////////////////////////// -void CrySemaphore::Acquire() -{ - WaitForSingleObject((HANDLE)m_Semaphore, INFINITE); -} - -////////////////////////////////////////////////////////////////////////// -void CrySemaphore::Release() -{ - ReleaseSemaphore((HANDLE)m_Semaphore, 1, NULL); -} - -////////////////////////////////////////////////////////////////////////// -CryFastSemaphore::CryFastSemaphore(int nMaximumCount, int nInitialCount) - : m_Semaphore(nMaximumCount) - , m_nCounter(nInitialCount) -{ -} - -////////////////////////////////////////////////////////////////////////// -CryFastSemaphore::~CryFastSemaphore() -{ -} - -////////////////////////////////////////////////////////////////////////// -void CryFastSemaphore::Acquire() -{ - int nCount = ~0; - do - { - nCount = *const_cast(&m_nCounter); - } while (CryInterlockedCompareExchange(alias_cast(&m_nCounter), nCount - 1, nCount) != nCount); - - // if the count would have been 0 or below, go to kernel semaphore - if ((nCount - 1) < 0) - { - m_Semaphore.Acquire(); - } -} - -////////////////////////////////////////////////////////////////////////// -void CryFastSemaphore::Release() -{ - int nCount = ~0; - do - { - nCount = *const_cast(&m_nCounter); - } while (CryInterlockedCompareExchange(alias_cast(&m_nCounter), nCount + 1, nCount) != nCount); - - // wake up kernel semaphore if we have waiter - if (nCount < 0) - { - m_Semaphore.Release(); - } -} diff --git a/Code/Legacy/CryCommon/CryThread_pthreads.h b/Code/Legacy/CryCommon/CryThread_pthreads.h index 8dd4bfba6c..9e04784f3f 100644 --- a/Code/Legacy/CryCommon/CryThread_pthreads.h +++ b/Code/Legacy/CryCommon/CryThread_pthreads.h @@ -48,52 +48,12 @@ #undef AZ_RESTRICTED_SECTION_IMPLEMENTED #endif -#if !defined(RegisterThreadName) - #define RegisterThreadName(id, name) - #define UnRegisterThreadName(id) -#endif - #if defined(APPLE) || defined(ANDROID) // PTHREAD_MUTEX_FAST_NP is only defined by Pthreads-w32, thus not on MAC #define PTHREAD_MUTEX_FAST_NP PTHREAD_MUTEX_NORMAL #endif -// Define LARGE_THREAD_STACK to use larger than normal per-thread stack -#if defined(_DEBUG) && (defined(MAC) || defined(LINUX) || defined(AZ_PLATFORM_IOS)) -#define LARGE_THREAD_STACK -#endif - -#if defined(LINUX) -#undef RegisterThreadName -ILINE void RegisterThreadName(pthread_t id, const char* name) -{ - if ((!name) || (!id)) - { - return; - } - int ret; - // pthread names on linux are limited to 16 char - if (strlen(name) >= 16) - { - char thread_name[16]; - memcpy(thread_name, name, 15); - thread_name[15] = 0; - ret = pthread_setname_np(id, thread_name); - } - else - { - ret = pthread_setname_np(id, name); - } - if (ret != 0) - { - CryLog("Failed to set thread name for %" PRI_THREADID ", name: %s", id, name); - } -} -#endif - #if !defined _CRYTHREAD_HAVE_LOCK -template -class _PthreadCond; template class _PthreadLockBase; @@ -130,8 +90,6 @@ template class _PthreadLock : public _PthreadLockBase { - friend class _PthreadCond; - //#if defined(_DEBUG) public: //#endif @@ -218,9 +176,6 @@ public: #if !defined(LINUX) && !defined(APPLE) #define CRYTHREAD_PTHREADS_H_TRAIT_DEFINE_CRYMUTEX 1 #endif -#if !defined(LINUX) && !defined(APPLE) -#define CRYTHREAD_PTHREADS_H_TRAIT_SET_THREAD_NAME 1 -#endif #endif #if CRYTHREAD_PTHREADS_H_TRAIT_DEFINE_CRYMUTEX @@ -237,386 +192,8 @@ class CryMutex #endif #endif // CRYTHREAD_PTHREADS_TRAIT_DEFINE_CRYMUTEX -template -class _PthreadCond -{ - pthread_cond_t m_Cond; - -public: - _PthreadCond() { pthread_cond_init(&m_Cond, NULL); } - ~_PthreadCond() { pthread_cond_destroy(&m_Cond); } - void Notify() { pthread_cond_broadcast(&m_Cond); } - void NotifySingle() { pthread_cond_signal(&m_Cond); } - void Wait(LockClass& Lock) { pthread_cond_wait(&m_Cond, &Lock.m_Lock); } - bool TimedWait(LockClass& Lock, uint32 milliseconds) - { - struct timeval now; - struct timespec timeout; - int err; - - gettimeofday(&now, NULL); - while (true) - { - timeout.tv_sec = now.tv_sec + milliseconds / 1000; - uint64 nsec = (uint64)now.tv_usec * 1000 + (uint64)milliseconds * 1000000; - if (nsec >= 1000000000) - { - timeout.tv_sec += (long)(nsec / 1000000000); - nsec %= 1000000000; - } - timeout.tv_nsec = (long)nsec; -#if defined(AZ_RESTRICTED_PLATFORM) - #define AZ_RESTRICTED_SECTION CRYTHREAD_PTHREADS_H_SECTION_PTHREADCOND - #include AZ_RESTRICTED_FILE(CryThread_pthreads_h) -#endif -#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED) - #undef AZ_RESTRICTED_SECTION_IMPLEMENTED -#else - err = pthread_cond_timedwait(&m_Cond, &Lock.m_Lock, &timeout); - if (err == EINTR) - { - // Interrupted by a signal. - continue; - } - else if (err == ETIMEDOUT) - { - return false; - } -#endif - else - { - assert(err == 0); - } - break; - } - return true; - } - - // Get the POSIX pthread_cont_t. - // Warning: - // This method will not be available in the Win32 port of CryThread. - pthread_cond_t& Get_pthread_cond_t() { return m_Cond; } -}; - -#if AZ_LEGACY_CRYCOMMON_TRAIT_USE_PTHREADS -template -class CryConditionVariableT - : public _PthreadCond -{ -}; - -#if defined CRYLOCK_HAVE_FASTTLOCK -template<> -class CryConditionVariableT< CryLockT > - : public _PthreadCond< CryLockT > -{ - typedef CryLockT LockClass; - CryConditionVariableT(const CryConditionVariableT&); - CryConditionVariableT& operator = (const CryConditionVariableT&); - -public: - CryConditionVariableT() { } -}; -#endif // CRYLOCK_HAVE_FASTLOCK - -template<> -class CryConditionVariableT< CryLockT > - : public _PthreadCond< CryLockT > -{ - typedef CryLockT LockClass; - CryConditionVariableT(const CryConditionVariableT&); - CryConditionVariableT& operator = (const CryConditionVariableT&); - -public: - CryConditionVariableT() { } -}; - -#if !defined(_CRYTHREAD_CONDLOCK_GLITCH) -typedef CryConditionVariableT< CryLockT > CryConditionVariable; -#else -typedef CryConditionVariableT< CryLockT > CryConditionVariable; -#endif - #define _CRYTHREAD_HAVE_LOCK 1 -#else // LINUX MAC - -#if defined CRYLOCK_HAVE_FASTLOCK -template<> -class CryConditionVariable - : public _PthreadCond< CryLockT > -{ - typedef CryLockT LockClass; - CryConditionVariable(const CryConditionVariable&); - CryConditionVariable& operator = (const CryConditionVariable&); - -public: - CryConditionVariable() { } -}; -#endif // CRYLOCK_HAVE_FASTLOCK - -template<> -class CryConditionVariable - : public _PthreadCond< CryLockT > -{ - typedef CryLockT LockClass; - CryConditionVariable(const CryConditionVariable&); - CryConditionVariable& operator = (const CryConditionVariable&); - -public: - CryConditionVariable() { } -}; - -#define _CRYTHREAD_HAVE_LOCK 1 - -#endif // LINUX MAC #endif // !defined _CRYTHREAD_HAVE_LOCK -////////////////////////////////////////////////////////////////////////// -// Platform independet wrapper for a counting semaphore -class CrySemaphore -{ -public: - CrySemaphore(int nMaximumCount, int nInitialCount = 0); - ~CrySemaphore(); - - void Acquire(); - void Release(); - -private: -#if defined(APPLE) - // Apple only supports named semaphores so have to use sem_open/unlink/sem_close instead - // of sem_open/sem_destroy, passing in this array for the name. - char m_semaphoreName[L_tmpnam]; -#endif - sem_t* m_Semaphore; -}; - -////////////////////////////////////////////////////////////////////////// -inline CrySemaphore::CrySemaphore(int nMaximumCount, int nInitialCount) -{ -#if defined(AZ_RESTRICTED_PLATFORM) - #define AZ_RESTRICTED_SECTION CRYTHREAD_PTHREADS_H_SECTION_SEMAPHORE_CONSTRUCT - #include AZ_RESTRICTED_FILE(CryThread_pthreads_h) -#endif -#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED) - #undef AZ_RESTRICTED_SECTION_IMPLEMENTED -#elif defined(APPLE) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wdeprecated-declarations" - tmpnam(m_semaphoreName); -# pragma clang diagnostic pop - m_Semaphore = sem_open(m_semaphoreName, O_CREAT | O_EXCL, 0644, nInitialCount); -#else - m_Semaphore = new sem_t; - sem_init(m_Semaphore, 0, nInitialCount); -#endif -} - -////////////////////////////////////////////////////////////////////////// -inline CrySemaphore::~CrySemaphore() -{ -#if defined(AZ_RESTRICTED_PLATFORM) - #define AZ_RESTRICTED_SECTION CRYTHREAD_PTHREADS_H_SECTION_SEMAPHORE_DESTROY - #include AZ_RESTRICTED_FILE(CryThread_pthreads_h) -#endif -#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED) - #undef AZ_RESTRICTED_SECTION_IMPLEMENTED -#elif defined(APPLE) - sem_close(m_Semaphore); - sem_unlink(m_semaphoreName); -#else - sem_destroy(m_Semaphore); - delete m_Semaphore; -#endif -} - -////////////////////////////////////////////////////////////////////////// -inline void CrySemaphore::Acquire() -{ -#if defined(AZ_RESTRICTED_PLATFORM) - #define AZ_RESTRICTED_SECTION CRYTHREAD_PTHREADS_H_SECTION_SEMAPHORE_ACQUIRE - #include AZ_RESTRICTED_FILE(CryThread_pthreads_h) -#endif -#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED) - #undef AZ_RESTRICTED_SECTION_IMPLEMENTED -#else - while (sem_wait(m_Semaphore) != 0 && errno == EINTR) - { - ; - } -#endif -} - -////////////////////////////////////////////////////////////////////////// -inline void CrySemaphore::Release() -{ -#if defined(AZ_RESTRICTED_PLATFORM) - #define AZ_RESTRICTED_SECTION CRYTHREAD_PTHREADS_H_SECTION_SEMAPHORE_RELEASE - #include AZ_RESTRICTED_FILE(CryThread_pthreads_h) -#endif -#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED) - #undef AZ_RESTRICTED_SECTION_IMPLEMENTED -#else - sem_post(m_Semaphore); -#endif -} - -////////////////////////////////////////////////////////////////////////// -// Platform independet wrapper for a counting semaphore -// except that this version uses C-A-S only until a blocking call is needed -// -> No kernel call if there are object in the semaphore - -class CryFastSemaphore -{ -public: - CryFastSemaphore(int nMaximumCount, int nInitialCount = 0); - ~CryFastSemaphore(); - void Acquire(); - void Release(); - -private: - CrySemaphore m_Semaphore; - volatile int32 m_nCounter; -}; - -////////////////////////////////////////////////////////////////////////// -inline CryFastSemaphore::CryFastSemaphore(int nMaximumCount, int nInitialCount) - : m_Semaphore(nMaximumCount) - , m_nCounter(nInitialCount) -{ -} - -////////////////////////////////////////////////////////////////////////// -inline CryFastSemaphore::~CryFastSemaphore() -{ -} - -///////////////////////////////////////////////////////////////////////// -inline void CryFastSemaphore::Acquire() -{ - int nCount = ~0; - do - { - nCount = *const_cast(&m_nCounter); - } while (CryInterlockedCompareExchange(alias_cast(&m_nCounter), nCount - 1, nCount) != nCount); - - // if the count would have been 0 or below, go to kernel semaphore - if ((nCount - 1) < 0) - { - m_Semaphore.Acquire(); - } -} - -////////////////////////////////////////////////////////////////////////// -inline void CryFastSemaphore::Release() -{ - int nCount = ~0; - do - { - nCount = *const_cast(&m_nCounter); - } while (CryInterlockedCompareExchange(alias_cast(&m_nCounter), nCount + 1, nCount) != nCount); - - // wake up kernel semaphore if we have waiter - if (nCount < 0) - { - m_Semaphore.Release(); - } -} - -//////////////////////////////////////////////////////////////////////////////// -// Provide TLS implementation using pthreads for those platforms without __thread -//////////////////////////////////////////////////////////////////////////////// - -struct SCryPthreadTLSBase -{ - SCryPthreadTLSBase(void (*pDestructor)(void*)) - { - pthread_key_create(&m_kKey, pDestructor); - } - - ~SCryPthreadTLSBase() - { - pthread_key_delete(m_kKey); - } - - void* GetSpecific() - { - return pthread_getspecific(m_kKey); - } - - void SetSpecific(const void* pValue) - { - pthread_setspecific(m_kKey, pValue); - } - - pthread_key_t m_kKey; -}; - -template -struct SCryPthreadTLSImpl{}; - -template -struct SCryPthreadTLSImpl - : private SCryPthreadTLSBase -{ - SCryPthreadTLSImpl() - : SCryPthreadTLSBase(NULL) - { - } - - T Get() - { - void* pSpecific(GetSpecific()); - return *reinterpret_cast(&pSpecific); - } - - void Set(const T& kValue) - { - SetSpecific(*reinterpret_cast(&kValue)); - } -}; - -template -struct SCryPthreadTLSImpl - : private SCryPthreadTLSBase -{ - SCryPthreadTLSImpl() - : SCryPthreadTLSBase(&Destroy) - { - } - - T* GetPtr() - { - T* pPtr(static_cast(GetSpecific())); - if (pPtr == NULL) - { - pPtr = new T(); - SetSpecific(pPtr); - } - return pPtr; - } - - static void Destroy(void* pPointer) - { - delete static_cast(pPointer); - } - - const T& Get() - { - return *GetPtr(); - } - - void Set(const T& kValue) - { - *GetPtr() = kValue; - } -}; - -template -struct SCryPthreadTLS - : SCryPthreadTLSImpl -{ -}; - #include "MemoryAccess.h" diff --git a/Code/Legacy/CryCommon/CryThread_windows.h b/Code/Legacy/CryCommon/CryThread_windows.h index 68908ab34a..5f83aa48e0 100644 --- a/Code/Legacy/CryCommon/CryThread_windows.h +++ b/Code/Legacy/CryCommon/CryThread_windows.h @@ -93,59 +93,3 @@ class CryMutex { }; #define _CRYTHREAD_CONDLOCK_GLITCH 1 - -////////////////////////////////////////////////////////////////////////// -class CryConditionVariable -{ -public: - typedef CryMutex LockType; - - CryConditionVariable(); - ~CryConditionVariable(); - void Wait(LockType& lock); - bool TimedWait(LockType& lock, uint32 millis); - void NotifySingle(); - void Notify(); - -private: - CryConditionVariable(const CryConditionVariable&); - CryConditionVariable& operator = (const CryConditionVariable&); - -private: - int m_waitersCount; - CRY_CRITICAL_SECTION m_waitersCountLock; - void* m_sema; - void* m_waitersDone; - size_t m_wasBroadcast; -}; - -////////////////////////////////////////////////////////////////////////// -// Platform independet wrapper for a counting semaphore -class CrySemaphore -{ -public: - CrySemaphore(int nMaximumCount, int nInitialCount = 0); - ~CrySemaphore(); - void Acquire(); - void Release(); - -private: - void* m_Semaphore; -}; - -////////////////////////////////////////////////////////////////////////// -// Platform independet wrapper for a counting semaphore -// except that this version uses C-A-S only until a blocking call is needed -// -> No kernel call if there are object in the semaphore -class CryFastSemaphore -{ -public: - CryFastSemaphore(int nMaximumCount, int nInitialCount = 0); - ~CryFastSemaphore(); - void Acquire(); - void Release(); - -private: - CrySemaphore m_Semaphore; - volatile int32 m_nCounter; -}; From c1a0b5c686823fe8a8fc45ded52ef1020df84eec Mon Sep 17 00:00:00 2001 From: Cynthia Lin <15116870+synicalsyntax@users.noreply.github.com> Date: Mon, 9 Aug 2021 14:57:52 -0700 Subject: [PATCH 230/803] performance benchmarks: Aggregate and report CPU frame times. (#2939) * Add CaptureCpuFrameTime method to ProfilingCaptureSystemComponent for monitoring CPU performance. Signed-off-by: Cynthia Lin * ly_test_tools: Refactor benchmark data aggregator in preparation for CPU frame times. Signed-off-by: Cynthia Lin * performance benchmarks: Aggregate and report CPU frame times based on JSON data. Signed-off-by: Cynthia Lin * AutomatedTesting: Capture CPU frame time in AtomFeatureIntegrationBenchmark. Signed-off-by: Cynthia Lin --- ...GPUTest_AtomFeatureIntegrationBenchmark.py | 1 + .../atom_utils/benchmark_utils.py | 19 +++ .../atom_renderer/test_Atom_GPUTests.py | 2 + .../Atom/Feature/Utils/ProfilingCaptureBus.h | 8 + .../ProfilingCaptureSystemComponent.cpp | 110 ++++++++++++- .../Source/ProfilingCaptureSystemComponent.h | 2 + .../benchmark/data_aggregator.py | 149 ++++++++++++------ 7 files changed, 245 insertions(+), 46 deletions(-) diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_GPUTest_AtomFeatureIntegrationBenchmark.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_GPUTest_AtomFeatureIntegrationBenchmark.py index b899d7dcde..3aa9fe660c 100644 --- a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_GPUTest_AtomFeatureIntegrationBenchmark.py +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_GPUTest_AtomFeatureIntegrationBenchmark.py @@ -93,6 +93,7 @@ def run(): general.idle_wait_frames(100) for i in range(1, 101): benchmarker.capture_pass_timestamp(i) + benchmarker.capture_cpu_frame_time(i) general.exit_game_mode() helper.wait_for_condition(function=lambda: not general.is_in_game_mode(), timeout_in_seconds=2.0) general.log("Capturing complete.") diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/benchmark_utils.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/benchmark_utils.py index 21c7489ed3..b4fdfcb8a0 100644 --- a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/benchmark_utils.py +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/benchmark_utils.py @@ -61,6 +61,25 @@ class BenchmarkHelper(object): general.log('Failed to capture pass timestamps.') return self.capturedData + def capture_cpu_frame_time(self, frame_number): + """ + Capture CPU frame times and block further execution until it has been written to the disk. + """ + self.handler = azlmbr.atom.ProfilingCaptureNotificationBusHandler() + self.handler.connect() + self.handler.add_callback('OnCaptureCpuFrameTimeFinished', self.on_data_captured) + + self.done = False + self.capturedData = False + success = azlmbr.atom.ProfilingCaptureRequestBus( + azlmbr.bus.Broadcast, "CaptureCpuFrameTime", f'{self.output_path}/cpu_frame{frame_number}_time.json') + if success: + self.wait_until_data() + general.log('CPU frame time captured.') + else: + general.log('Failed to capture CPU frame time.') + return self.capturedData + def on_data_captured(self, parameters): # the parameters come in as a tuple if parameters[0]: diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_GPUTests.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_GPUTests.py index ede140c075..9165bced90 100644 --- a/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_GPUTests.py +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_GPUTests.py @@ -99,6 +99,7 @@ class TestPerformanceBenchmarkSuite(object): expected_lines = [ "Benchmark metadata captured.", "Pass timestamps captured.", + "CPU frame time captured.", "Capturing complete.", "Captured data successfully." ] @@ -106,6 +107,7 @@ class TestPerformanceBenchmarkSuite(object): unexpected_lines = [ "Failed to capture data.", "Failed to capture pass timestamps.", + "Failed to capture CPU frame time.", "Failed to capture benchmark metadata." ] diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/ProfilingCaptureBus.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/ProfilingCaptureBus.h index 15f15705c8..03f522ba44 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/ProfilingCaptureBus.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/ProfilingCaptureBus.h @@ -22,6 +22,9 @@ namespace AZ //! Dump the Timestamp from passes to a json file. virtual bool CapturePassTimestamp(const AZStd::string& outputFilePath) = 0; + //! Dump the Cpu frame time statistics to a json file. + virtual bool CaptureCpuFrameTime(const AZStd::string& outputFilePath) = 0; + //! Dump the PipelineStatistics from passes to a json file. virtual bool CapturePassPipelineStatistics(const AZStd::string& outputFilePath) = 0; @@ -44,6 +47,11 @@ namespace AZ //! @param info The output file path or error information which depends on the return. virtual void OnCaptureQueryTimestampFinished(bool result, const AZStd::string& info) = 0; + //! Notify when the current CpuFrameTimeStatistics capture is finished + //! @param result Set to true if it's finished successfully + //! @param info The output file path or error information which depends on the return. + virtual void OnCaptureCpuFrameTimeFinished(bool result, const AZStd::string& info) = 0; + //! Notify when the current PipelineStatistics query capture is finished //! @param result Set to true if it's finished successfully //! @param info The output file path or error information which depends on the return. diff --git a/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.cpp b/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.cpp index 0c4c4d9689..1e2d549e7a 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.cpp @@ -10,6 +10,9 @@ #include #include +#include +#include +#include #include #include @@ -34,6 +37,7 @@ namespace AZ public: AZ_EBUS_BEHAVIOR_BINDER(ProfilingCaptureNotificationBusHandler, "{E45E4F37-EC1F-4010-994B-4F80998BEF15}", AZ::SystemAllocator, OnCaptureQueryTimestampFinished, + OnCaptureCpuFrameTimeFinished, OnCaptureQueryPipelineStatisticsFinished, OnCaptureCpuProfilingStatisticsFinished, OnCaptureBenchmarkMetadataFinished @@ -44,6 +48,11 @@ namespace AZ Call(FN_OnCaptureQueryTimestampFinished, result, info); } + void OnCaptureCpuFrameTimeFinished(bool result, const AZStd::string& info) override + { + Call(FN_OnCaptureCpuFrameTimeFinished, result, info); + } + void OnCaptureQueryPipelineStatisticsFinished(bool result, const AZStd::string& info) override { Call(FN_OnCaptureQueryPipelineStatisticsFinished, result, info); @@ -95,6 +104,19 @@ namespace AZ AZStd::vector m_timestampEntries; }; + // Intermediate class to serialize CPU frame time statistics. + class CpuFrameTimeSerializer + { + public: + AZ_TYPE_INFO(Render::CpuFrameTimeSerializer, "{584B415E-8769-4757-AC64-EA57EDBCBC3E}"); + static void Reflect(AZ::ReflectContext* context); + + CpuFrameTimeSerializer() = default; + CpuFrameTimeSerializer(double frameTime); + + double m_frameTime; + }; + // Intermediate class to serialize pass' PipelineStatistics data. class PipelineStatisticsSerializer { @@ -248,6 +270,24 @@ namespace AZ } } + // --- CpuFrameTimeSerializer --- + + CpuFrameTimeSerializer::CpuFrameTimeSerializer(double frameTime) + { + m_frameTime = frameTime; + } + + void CpuFrameTimeSerializer::Reflect(AZ::ReflectContext* context) + { + if (auto* serializeContext = azrtti_cast(context)) + { + serializeContext->Class() + ->Version(1) + ->Field("frameTime", &CpuFrameTimeSerializer::m_frameTime) + ; + } + } + // --- PipelineStatisticsSerializer --- PipelineStatisticsSerializer::PipelineStatisticsSerializer(AZStd::vector&& passes) @@ -408,6 +448,7 @@ namespace AZ ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation) ->Attribute(AZ::Script::Attributes::Module, "atom") ->Event("CapturePassTimestamp", &ProfilingCaptureRequestBus::Events::CapturePassTimestamp) + ->Event("CaptureCpuFrameTime", &ProfilingCaptureRequestBus::Events::CaptureCpuFrameTime) ->Event("CapturePassPipelineStatistics", &ProfilingCaptureRequestBus::Events::CapturePassPipelineStatistics) ->Event("CaptureCpuProfilingStatistics", &ProfilingCaptureRequestBus::Events::CaptureCpuProfilingStatistics) ->Event("CaptureBenchmarkMetadata", &ProfilingCaptureRequestBus::Events::CaptureBenchmarkMetadata) @@ -417,6 +458,7 @@ namespace AZ } TimestampSerializer::Reflect(context); + CpuFrameTimeSerializer::Reflect(context); PipelineStatisticsSerializer::Reflect(context); CpuProfilingStatisticsSerializer::Reflect(context); BenchmarkMetadataSerializer::Reflect(context); @@ -484,6 +526,71 @@ namespace AZ return captureStarted; } + bool ProfilingCaptureSystemComponent::CaptureCpuFrameTime(const AZStd::string& outputFilePath) + { + AZ::RHI::RHISystemInterface::Get()->ModifyFrameSchedulerStatisticsFlags( + AZ::RHI::FrameSchedulerStatisticsFlags::GatherCpuTimingStatistics, true + ); + bool wasEnabled = RHI::CpuProfiler::Get()->IsProfilerEnabled(); + if (!wasEnabled) + { + RHI::CpuProfiler::Get()->SetProfilerEnabled(true); + } + + const bool captureStarted = m_cpuFrameTimeStatisticsCapture.StartCapture([this, outputFilePath, wasEnabled]() + { + JsonSerializerSettings serializationSettings; + serializationSettings.m_keepDefaults = true; + + double frameTime = 0.0; + const AZ::RHI::CpuTimingStatistics* stats = AZ::RHI::RHISystemInterface::Get()->GetCpuTimingStatistics(); + if (stats) + { + frameTime = stats->GetFrameToFrameTimeMilliseconds(); + } + else + { + AZStd::string warning = AZStd::string::format("Failed to get Cpu frame time"); + AZ_Warning("ProfilingCaptureSystemComponent", false, warning.c_str()); + } + + CpuFrameTimeSerializer serializer(frameTime); + const auto saveResult = JsonSerializationUtils::SaveObjectToFile(&serializer, + outputFilePath, (CpuFrameTimeSerializer*)nullptr, &serializationSettings); + + AZStd::string captureInfo = outputFilePath; + if (!saveResult.IsSuccess()) + { + captureInfo = AZStd::string::format("Failed to save Cpu frame time to file '%s'. Error: %s", + outputFilePath.c_str(), + saveResult.GetError().c_str()); + AZ_Warning("ProfilingCaptureSystemComponent", false, captureInfo.c_str()); + } + + // Disable the profiler again + if (!wasEnabled) + { + RHI::CpuProfiler::Get()->SetProfilerEnabled(false); + } + AZ::RHI::RHISystemInterface::Get()->ModifyFrameSchedulerStatisticsFlags( + AZ::RHI::FrameSchedulerStatisticsFlags::GatherCpuTimingStatistics, false + ); + + // Notify listeners that the Cpu frame time statistics capture has finished. + ProfilingCaptureNotificationBus::Broadcast(&ProfilingCaptureNotificationBus::Events::OnCaptureCpuFrameTimeFinished, + saveResult.IsSuccess(), + captureInfo); + }); + + // Start the TickBus. + if (captureStarted) + { + TickBus::Handler::BusConnect(); + } + + return captureStarted; + } + bool ProfilingCaptureSystemComponent::CapturePassPipelineStatistics(const AZStd::string& outputFilePath) { // Find the root pass. @@ -666,12 +773,13 @@ namespace AZ { // Update the delayed captures m_timestampCapture.UpdateCapture(); + m_cpuFrameTimeStatisticsCapture.UpdateCapture(); m_pipelineStatisticsCapture.UpdateCapture(); m_cpuProfilingStatisticsCapture.UpdateCapture(); m_benchmarkMetadataCapture.UpdateCapture(); // Disconnect from the TickBus if all capture states are set to idle. - if (m_timestampCapture.IsIdle() && m_pipelineStatisticsCapture.IsIdle() && m_cpuProfilingStatisticsCapture.IsIdle() && m_benchmarkMetadataCapture.IsIdle()) + if (m_timestampCapture.IsIdle() && m_pipelineStatisticsCapture.IsIdle() && m_cpuProfilingStatisticsCapture.IsIdle() && m_benchmarkMetadataCapture.IsIdle() && m_cpuFrameTimeStatisticsCapture.IsIdle()) { TickBus::Handler::BusDisconnect(); } diff --git a/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.h b/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.h index 6703076c6e..c401d27f30 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.h +++ b/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.h @@ -68,6 +68,7 @@ namespace AZ // ProfilingCaptureRequestBus overrides... bool CapturePassTimestamp(const AZStd::string& outputFilePath) override; + bool CaptureCpuFrameTime(const AZStd::string& outputFilePath) override; bool CapturePassPipelineStatistics(const AZStd::string& outputFilePath) override; bool CaptureCpuProfilingStatistics(const AZStd::string& outputFilePath) override; bool CaptureBenchmarkMetadata(const AZStd::string& benchmarkName, const AZStd::string& outputFilePath) override; @@ -81,6 +82,7 @@ namespace AZ AZStd::vector FindPasses(AZStd::vector&& passHierarchy) const; DelayedQueryCaptureHelper m_timestampCapture; + DelayedQueryCaptureHelper m_cpuFrameTimeStatisticsCapture; DelayedQueryCaptureHelper m_pipelineStatisticsCapture; DelayedQueryCaptureHelper m_cpuProfilingStatisticsCapture; DelayedQueryCaptureHelper m_benchmarkMetadataCapture; diff --git a/Tools/LyTestTools/ly_test_tools/benchmark/data_aggregator.py b/Tools/LyTestTools/ly_test_tools/benchmark/data_aggregator.py index 12681450de..0ac8c12f9b 100644 --- a/Tools/LyTestTools/ly_test_tools/benchmark/data_aggregator.py +++ b/Tools/LyTestTools/ly_test_tools/benchmark/data_aggregator.py @@ -18,31 +18,77 @@ class BenchmarkPathException(Exception): """Custom Exception class for invalid benchmark file paths.""" pass +class RunningStatistics(object): + def __init__(self): + ''' + Initializes a helper class for calculating running statstics. + ''' + self.count = 0 + self.total = 0 + self.max = 0 + self.min = float('inf') + + def update(self, value): + ''' + Updates the statistics with a new value. + + :param value: The new value to update the statistics with. + ''' + self.total += value + self.count += 1 + self.max = max(value, self.max) + self.min = min(value, self.min) + + def getAvg(self): + ''' + Returns the average of the running values. + ''' + return self.total / self.count + + def getMax(self): + ''' + Returns the maximum of the running values. + ''' + return self.max + + def getMin(self): + ''' + Returns the minimum of the running values. + ''' + return self.min + + def getCount(self): + return self.count + class BenchmarkDataAggregator(object): def __init__(self, workspace, logger, test_suite): + ''' + Initializes an aggregator for benchmark data. + + :param workspace: Workspace of the test suite the benchmark was run in + :param logger: Logger used by the test suite the benchmark was run in + :param test_suite: Name of the test suite the benchmark was run in + ''' self.build_dir = workspace.paths.build_directory() self.results_dir = Path(workspace.paths.project(), 'user/Scripts/PerformanceBenchmarks') self.test_suite = test_suite if os.environ.get('BUILD_NUMBER') else 'local' self.filebeat_client = FilebeatClient(logger) - def _update_pass(self, pass_stats, entry): + def _update_pass(self, gpu_pass_stats, entry): ''' - Modifies pass_stats dict keyed by pass name with the time recorded in a pass timestamp entry. + Modifies gpu_pass_stats dict keyed by pass name with the time recorded in a pass timestamp entry. - :param pass_stats: dict aggregating statistics from each pass (key: pass name, value: dict with stats) + :param gpu_pass_stats: dict aggregating statistics from each pass (key: pass name, value: dict with stats) :param entry: dict representing the timestamp entry of a pass :return: Time (in nanoseconds) recorded by this pass ''' name = entry['passName'] time_ns = entry['timestampResultInNanoseconds'] - pass_entry = pass_stats.get(name, { 'totalTime': 0, 'maxTime': 0 }) - - pass_entry['maxTime'] = max(time_ns, pass_entry['maxTime']) - pass_entry['totalTime'] += time_ns - pass_stats[name] = pass_entry + pass_entry = gpu_pass_stats.get(name, RunningStatistics()) + pass_entry.update(time_ns) + gpu_pass_stats[name] = pass_entry return time_ns - def _process_benchmark(self, benchmark_dir, benchmark_metadata): ''' Aggregates data from results from a single benchmark contained in a subdirectory of self.results_dir. @@ -50,8 +96,8 @@ class BenchmarkDataAggregator(object): :param benchmark_dir: Path of directory containing the benchmark results :param benchmark_metadata: Dict with benchmark metadata mutated with additional info from metadata file :return: Tuple with two indexes: - [0]: Dict aggregating statistics from frame times (key: stat name) - [1]: Dict aggregating statistics from pass times (key: pass name, value: dict with stats) + [0]: RunningStatistics for GPU frame times + [1]: Dict aggregating statistics from GPU pass times (key: pass name, value: RunningStatistics) ''' # Parse benchmark metadata metadata_file = benchmark_dir / 'benchmark_metadata.json' @@ -62,39 +108,47 @@ class BenchmarkDataAggregator(object): raise BenchmarkPathException(f'Metadata file could not be found at {metadata_file}') # data structures aggregating statistics from timestamp logs - frame_stats = { 'count': 0, 'totalTime': 0, 'maxTime': 0, 'minTime': float('inf') } - pass_stats = {} # key: pass name, value: dict with totalTime and maxTime keys + gpu_frame_stats = RunningStatistics() + cpu_frame_stats = RunningStatistics() + gpu_pass_stats = {} # key: pass name, value: RunningStatistics # this allows us to add additional data if necessary, e.g. frame_test_timestamps.json is_timestamp_file = lambda file: file.name.startswith('frame') and file.name.endswith('_timestamps.json') + is_frame_time_file = lambda file: file.name.startswith('cpu_frame') and file.name.endswith('_time.json') # parse benchmark files for file in benchmark_dir.iterdir(): - if file.is_dir() or not is_timestamp_file(file): + if file.is_dir(): continue - data = json.loads(file.read_text()) - entries = data['ClassData']['timestampEntries'] + if is_timestamp_file(file): + data = json.loads(file.read_text()) + entries = data['ClassData']['timestampEntries'] - frame_time = sum(self._update_pass(pass_stats, entry) for entry in entries) + frame_time = sum(self._update_pass(gpu_pass_stats, entry) for entry in entries) + gpu_frame_stats.update(frame_time) - frame_stats['totalTime'] += frame_time - frame_stats['maxTime'] = max(frame_time, frame_stats['maxTime']) - frame_stats['minTime'] = min(frame_time, frame_stats['minTime']) - frame_stats['count'] += 1 + if is_frame_time_file(file): + data = json.loads(file.read_text()) + frame_time = data['ClassData']['frameTime'] + cpu_frame_stats.update(frame_time) - if frame_stats['count'] < 1: - raise BenchmarkPathException(f'No frame timestamp logs were found in {benchmark_dir}') + if gpu_frame_stats.getCount() < 1: + raise BenchmarkPathException(f'No GPU frame timestamp logs were found in {benchmark_dir}') - return frame_stats, pass_stats + if cpu_frame_stats.getCount() < 1: + raise BenchmarkPathException(f'No CPU frame times were found in {benchmark_dir}') - def _generate_payloads(self, benchmark_metadata, frame_stats, pass_stats): + return gpu_frame_stats, gpu_pass_stats, cpu_frame_stats + + def _generate_payloads(self, benchmark_metadata, gpu_frame_stats, gpu_pass_stats, cpu_frame_stats): ''' Generates payloads to send to Filebeat based on aggregated stats and metadata. :param benchmark_metadata: Dict of benchmark metadata - :param frame_stats: Dict of aggregated frame statistics - :param pass_stats: Dict of aggregated pass statistics + :param gpu_frame_stats: RunningStatistics for GPU frame data + :param gpu_pass_stats: Dict of aggregated pass RunningStatistics + :param cpu_frame_stats: RunningStatistics for CPU frame data :return payloads: List of tuples, each with two indexes: [0]: Elasticsearch index suffix associated with the payload [1]: Payload dict to deliver to Filebeat @@ -103,33 +157,38 @@ class BenchmarkDataAggregator(object): payloads = [] # calculate statistics based on aggregated frame data - frame_time_avg = frame_stats['totalTime'] / frame_stats['count'] - frame_payload = { + gpu_frame_payload = { 'frameTime': { - 'avg': ns_to_ms(frame_time_avg), - 'max': ns_to_ms(frame_stats['maxTime']), - 'min': ns_to_ms(frame_stats['minTime']) + 'avg': ns_to_ms(gpu_frame_stats.getAvg()), + 'max': ns_to_ms(gpu_frame_stats.getMax()), + 'min': ns_to_ms(gpu_frame_stats.getMin()) + } + } + cpu_frame_payload = { + 'frameTime': { + 'avg': cpu_frame_stats.getAvg(), + 'max': cpu_frame_stats.getMax(), + 'min': cpu_frame_stats.getMin() } } # add benchmark metadata to payload - frame_payload.update(benchmark_metadata) - payloads.append(('frame_data', frame_payload)) + gpu_frame_payload.update(benchmark_metadata) + payloads.append(('gpu.frame_data', gpu_frame_payload)) + cpu_frame_payload.update(benchmark_metadata) + payloads.append(('cpu.frame_data', cpu_frame_payload)) # calculate statistics for each pass - for name, stat in pass_stats.items(): - avg_ms = ns_to_ms(stat['totalTime'] / frame_stats['count']) - max_ms = ns_to_ms(stat['maxTime']) - - pass_payload = { + for name, stat in gpu_pass_stats.items(): + gpu_pass_payload = { 'passName': name, 'passTime': { - 'avg': avg_ms, - 'max': max_ms + 'avg': ns_to_ms(stat.getAvg()), + 'max': ns_to_ms(stat.getMax()) } } # add benchmark metadata to payload - pass_payload.update(benchmark_metadata) - payloads.append(('pass_data', pass_payload)) + gpu_pass_payload.update(benchmark_metadata) + payloads.append(('gpu.pass_data', gpu_pass_payload)) return payloads @@ -153,8 +212,8 @@ class BenchmarkDataAggregator(object): 'gitCommitAndBuildDate': f'{git_commit_hash} {build_date}', 'RHI': rhi } - frame_stats, pass_stats = self._process_benchmark(benchmark_dir, benchmark_metadata) - payloads = self._generate_payloads(benchmark_metadata, frame_stats, pass_stats) + gpu_frame_stats, gpu_pass_stats, cpu_frame_stats = self._process_benchmark(benchmark_dir, benchmark_metadata) + payloads = self._generate_payloads(benchmark_metadata, gpu_frame_stats, gpu_pass_stats, cpu_frame_stats) for index_suffix, payload in payloads: self.filebeat_client.send_event( From 9afbd07a88be54c62515c8a368b6327f4367d141 Mon Sep 17 00:00:00 2001 From: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> Date: Mon, 9 Aug 2021 16:58:19 -0500 Subject: [PATCH 231/803] Added new feature to the register command to auto detect manifest file based on input path (#2967) * Added new feature to the register command to auto detect the correct o3de manifest file to write to based on the supplied registration path Updated the create-gem command to register the gem on creation. Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Added new feature to the register command to auto detect the correct o3de manifest file to write to based on the supplied registration path Updated the create-gem command to register the gem on creation. Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Fix incorrect variable reference in register_project_path Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Fixed o3de python package unit test The enable_gem, register and engine template test have been updated to account for the logic to register a gem after creation Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Added a --no-register arg to engine-template.py This allows registration of gems/projects using the create-project and create-gem commands to be skipped Prevented registration of a gems and projects in the engine_template command test Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Wrapped first parameter to find_ancestor_dir_containing_file with pathlib.PurePath Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> --- scripts/o3de/o3de/engine_template.py | 18 ++- scripts/o3de/o3de/register.py | 29 +++- scripts/o3de/o3de/utils.py | 51 ++++++- scripts/o3de/tests/unit_test_enable_gem.py | 2 +- .../o3de/tests/unit_test_engine_template.py | 7 +- scripts/o3de/tests/unit_test_register.py | 136 ++++++++++++++++++ 6 files changed, 233 insertions(+), 10 deletions(-) diff --git a/scripts/o3de/o3de/engine_template.py b/scripts/o3de/o3de/engine_template.py index 4f026e86d8..802641bd3a 100755 --- a/scripts/o3de/o3de/engine_template.py +++ b/scripts/o3de/o3de/engine_template.py @@ -1299,6 +1299,7 @@ def create_project(project_path: pathlib.Path, keep_license_text: bool = False, replace: list = None, force: bool = False, + no_register: bool = False, system_component_class_id: str = None, editor_system_component_class_id: str = None, module_id: str = None) -> int: @@ -1657,9 +1658,10 @@ def create_project(project_path: pathlib.Path, d.write('# {END_LICENSE}\n') - # Register the project with the global o3de_manifest.json and set the project.json "engine" field to match the + # Register the project with the either o3de_manifest.json or engine.json + # and set the project.json "engine" field to match the # engine.json "engine_name" field - return register.register(project_path=project_path) + return register.register(project_path=project_path) if not no_register else 0 def create_gem(gem_path: pathlib.Path, @@ -1676,6 +1678,7 @@ def create_gem(gem_path: pathlib.Path, keep_license_text: bool = False, replace: list = None, force: bool = False, + no_register: bool = False, system_component_class_id: str = None, editor_system_component_class_id: str = None, module_id: str = None) -> int: @@ -2035,7 +2038,8 @@ def create_gem(gem_path: pathlib.Path, d.write('#\n') d.write('# SPDX-License-Identifier: Apache-2.0 OR MIT\n') d.write('# {END_LICENSE}\n') - return 0 + # Register the gem with the either o3de_manifest.json, engine.json or project.json based on the gem path + return register.register(gem_path=gem_path) if not no_register else 0 def _run_create_template(args: argparse) -> int: @@ -2086,6 +2090,7 @@ def _run_create_project(args: argparse) -> int: args.keep_license_text, args.replace, args.force, + args.no_register, args.system_component_class_id, args.editor_system_component_class_id, args.module_id) @@ -2106,6 +2111,7 @@ def _run_create_gem(args: argparse) -> int: args.keep_license_text, args.replace, args.force, + args.no_register, args.system_component_class_id, args.editor_system_component_class_id, args.module_id) @@ -2370,6 +2376,9 @@ def add_args(subparsers) -> None: ' uuid Ex. {b60c92eb-3139-454b-a917-a9d3c5819594}') create_project_subparser.add_argument('-f', '--force', action='store_true', default=False, help='Copies over instantiated template directory even if it exist.') + create_project_subparser.add_argument('--no-register', action='store_true', default=False, + help='If the project template is instantiated successfully, it will not register the' + ' project with the global or engine manifest file.') create_project_subparser.set_defaults(func=_run_create_project) # creation of a gem from a template (like create from template but makes gem assumptions) @@ -2463,6 +2472,9 @@ def add_args(subparsers) -> None: ' default is a random uuid Ex. {b60c92eb-3139-454b-a917-a9d3c5819594}') create_gem_subparser.add_argument('-f', '--force', action='store_true', default=False, help='Copies over instantiated template directory even if it exist.') + create_gem_subparser.add_argument('--no-register', action='store_true', default=False, + help='If the gem template is instantiated successfully, it will not register the' + ' gem with the global, project or engine manifest file.') create_gem_subparser.set_defaults(func=_run_create_gem) diff --git a/scripts/o3de/o3de/register.py b/scripts/o3de/o3de/register.py index 7e182b5d2d..5822cc926c 100644 --- a/scripts/o3de/o3de/register.py +++ b/scripts/o3de/o3de/register.py @@ -285,14 +285,14 @@ def register_o3de_object_path(json_data: dict, manifest_data = None if engine_path: - manifest_data = manifest.get_engine_json_data(None, engine_path) + manifest_data = manifest.get_engine_json_data(engine_path=engine_path) if not manifest_data: logger.error(f'Cannot load engine.json data at path {engine_path}') return 1 save_path = engine_path / 'engine.json' elif project_path: - manifest_data = manifest.get_project_json_data(None, project_path) + manifest_data = manifest.get_project_json_data(project_path=project_path) if not manifest_data: logger.error(f'Cannot load project.json data at path {project_path}') return 1 @@ -367,6 +367,11 @@ def register_external_subdirectory(json_data: dict, :return An integer return code indicating whether registration or removal of the external subdirectory completed successfully """ + # If a project path or engine path has not been supplied auto detect which manifest to register the input path with + if not project_path and not engine_path: + project_path = utils.find_ancestor_dir_containing_file(pathlib.PurePath('project.json'), external_subdir_path) + if not project_path: + engine_path = utils.find_ancestor_dir_containing_file(pathlib.PurePath('engine.json'), external_subdir_path) return register_o3de_object_path(json_data, external_subdir_path, 'external_subdirectories', '', None, remove, engine_path, project_path) @@ -376,6 +381,11 @@ def register_gem_path(json_data: dict, remove: bool = False, engine_path: pathlib.Path = None, project_path: pathlib.Path = None) -> int: + # If a project path or engine path has not been supplied auto detect which manifest to register the input path with + if not project_path and not engine_path: + project_path = utils.find_ancestor_dir_containing_file(pathlib.PurePath('project.json'), gem_path) + if not project_path: + engine_path = utils.find_ancestor_dir_containing_file(pathlib.PurePath('engine.json'), gem_path) return register_o3de_object_path(json_data, gem_path, 'external_subdirectories', 'gem.json', validation.valid_o3de_gem_json, remove, engine_path, project_path) @@ -384,6 +394,11 @@ def register_project_path(json_data: dict, project_path: pathlib.Path, remove: bool = False, engine_path: pathlib.Path = None) -> int: + # If an engine path has not been supplied auto detect if the project should be register with the engine.json + # or the ~/.o3de/o3de_manifest.json + if not engine_path: + engine_path = utils.find_ancestor_dir_containing_file(pathlib.PurePath('engine.json'), project_path) + result = register_o3de_object_path(json_data, project_path, 'projects', 'project.json', validation.valid_o3de_project_json, remove, engine_path, None) @@ -419,6 +434,11 @@ def register_template_path(json_data: dict, template_path: pathlib.Path, remove: bool = False, engine_path: pathlib.Path = None) -> int: + # If a project path or engine path has not been supplied auto detect which manifest to register the input path + if not project_path and not engine_path: + project_path = utils.find_ancestor_dir_containing_file(pathlib.PurePath('project.json'), template_path) + if not project_path: + engine_path = utils.find_ancestor_dir_containing_file(pathlib.PurePath('engine.json'), template_path) return register_o3de_object_path(json_data, template_path, 'templates', 'template.json', validation.valid_o3de_template_json, remove, engine_path, None) @@ -427,6 +447,11 @@ def register_restricted_path(json_data: dict, restricted_path: pathlib.Path, remove: bool = False, engine_path: pathlib.Path = None) -> int: + # If a project path or engine path has not been supplied auto detect which manifest to register the input path + if not project_path and not engine_path: + project_path = utils.find_ancestor_dir_containing_file(pathlib.PurePath('project.json'), restricted_path) + if not project_path: + engine_path = utils.find_ancestor_dir_containing_file(pathlib.PurePath('engine.json'), restricted_path) return register_o3de_object_path(json_data, restricted_path, 'restricted', 'restricted.json', validation.valid_o3de_restricted_json, remove, engine_path, None) diff --git a/scripts/o3de/o3de/utils.py b/scripts/o3de/o3de/utils.py index 629a473b8a..18f80584cc 100755 --- a/scripts/o3de/o3de/utils.py +++ b/scripts/o3de/o3de/utils.py @@ -8,7 +8,7 @@ """ This file contains utility functions """ - +import sys import uuid import pathlib import shutil @@ -123,4 +123,51 @@ def download_zip_file(parsed_uri, download_zip_path: pathlib.Path) -> int: download_zip_path.unlink() return 1 - return 0 \ No newline at end of file + return 0 + + +def find_ancestor_file(target_file_name: pathlib.PurePath, start_path: pathlib.Path, + max_scan_up_range: int=0) -> pathlib.Path or None: + """ + Find a file with the given name in the ancestor directories by walking up the starting path until the file is found. + + :param target_file_name: Name of the file to find. + :param start_path: path to start looking for the file. + :param max_scan_up_range: maximum number of directories to scan upwards when searching for target file + if the value is 0, then there is no max + :return: Path to the file or None if not found. + """ + current_path = pathlib.Path(start_path) + candidate_path = current_path / target_file_name + + max_scan_up_range = max_scan_up_range if max_scan_up_range else sys.maxsize + + # Limit the number of directories to traverse, to avoid infinite loop in path cycles + for _ in range(max_scan_up_range): + if candidate_path.exists(): + # Found the file we wanted + break + + parent_path = current_path.parent + if parent_path == current_path: + # Only true when we are at the directory root, can't keep searching + break + candidate_path = parent_path / target_file_name + current_path = parent_path + + return candidate_path if candidate_path.exists() else None + +def find_ancestor_dir_containing_file(target_file_name: pathlib.PurePath, start_path: pathlib.Path, + max_scan_up_range: int=0) -> pathlib.Path or None: + """ + Find nearest ancestor directory that contains the file with the given name by walking up + from the starting path. + + :param target_file_name: Name of the file to find. + :param start_path: path to start looking for the file. + :param max_scan_up_range: maximum number of directories to scan upwards when searching for target file + if the value is 0, then there is no max + :return: Path to the directory containing file or None if not found. + """ + ancestor_file = find_ancestor_file(target_file_name, start_path, max_scan_up_range) + return ancestor_file.parent if ancestor_file else None diff --git a/scripts/o3de/tests/unit_test_enable_gem.py b/scripts/o3de/tests/unit_test_enable_gem.py index 9165fd5d08..c765f74731 100644 --- a/scripts/o3de/tests/unit_test_enable_gem.py +++ b/scripts/o3de/tests/unit_test_enable_gem.py @@ -124,7 +124,7 @@ class TestEnableGemCommand: return json.loads(TEST_O3DE_MANIFEST_JSON_PAYLOAD) return None - def get_project_json_data(json_data: pathlib.Path, project_path: pathlib.Path): + def get_project_json_data(project_path: pathlib.Path): return self.enable_gem.project_data def get_gem_json_data(gem_path: pathlib.Path, project_path: pathlib.Path): diff --git a/scripts/o3de/tests/unit_test_engine_template.py b/scripts/o3de/tests/unit_test_engine_template.py index 25c418b0ff..16ac24d74c 100755 --- a/scripts/o3de/tests/unit_test_engine_template.py +++ b/scripts/o3de/tests/unit_test_engine_template.py @@ -263,6 +263,7 @@ class TestCreateTemplate: s.write(templated_contents) template_dest_path = engine_root / instantiated_name + # Skip registeration in test with patch('uuid.uuid4', return_value=uuid.uuid5(uuid.NAMESPACE_DNS, instantiated_name)) as uuid4_mock: result = create_from_template_func(template_dest_path, template_path=template_default_folder, force=True, keep_license_text=keep_license_text, **create_from_template_kwargs) @@ -345,7 +346,7 @@ class TestCreateTemplate: template_json_contents = json.dumps(template_json_dict, indent=4) self.instantiate_template_wrapper(tmpdir, engine_template.create_project, 'TestProject', concrete_contents, templated_contents, keep_license_text, force, expect_failure, - template_json_contents, template_file_map, project_name='TestProject') + template_json_contents, template_file_map, project_name='TestProject', no_register=True) @pytest.mark.parametrize( @@ -379,6 +380,8 @@ class TestCreateTemplate: "isTemplated": True, "isOptional": False }) + #Convert dict back to string + template_json_contents = json.dumps(template_json_dict, indent=4) self.instantiate_template_wrapper(tmpdir, engine_template.create_gem, 'TestGem', concrete_contents, templated_contents, keep_license_text, force, expect_failure, - template_json_contents, gem_name='TestGem') + template_json_contents, template_file_map, gem_name='TestGem', no_register=True) diff --git a/scripts/o3de/tests/unit_test_register.py b/scripts/o3de/tests/unit_test_register.py index 075eef5079..36139c0afa 100644 --- a/scripts/o3de/tests/unit_test_register.py +++ b/scripts/o3de/tests/unit_test_register.py @@ -112,3 +112,139 @@ class TestRegisterThisEngine: result = register._run_register(args) assert result == expected_result + +TEST_GEM_JSON_PAYLOAD = ''' +{ + "gem_name": "TestGem", + "display_name": "TestGem", + "license": "What license TestGem uses goes here: i.e. https://opensource.org/licenses/MIT", + "origin": "The primary repo for TestGem goes here: i.e. http://www.mydomain.com", + "type": "Code", + "summary": "A short description of TestGem.", + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "TestGem" + ], + "icon_path": "preview.png", + "requirements": "" +} +''' + +TEST_PROJECT_JSON_PAYLOAD = ''' +{ + "project_name": "TestProject", + "engine": "o3de", + "external_subdirectories": [] +} +''' + +TEST_ENGINE_JSON_PAYLOAD = ''' +{ + "engine_name": "o3de", + "external_subdirectories": [], + "projects": [], + "templates": [] +} +''' + +TEST_O3DE_MANIFEST_JSON_PAYLOAD = ''' +{ + "o3de_manifest_name": "testuser", + "origin": "C:/Users/testuser/.o3de", + "default_engines_folder": "C:/Users/testuser/.o3de/Engines", + "default_projects_folder": "C:/Users/testuser/.o3de/Projects", + "default_gems_folder": "C:/Users/testuser/.o3de/Gems", + "default_templates_folder": "C:/Users/testuser/.o3de/Templates", + "default_restricted_folder": "C:/Users/testuser/.o3de/Restricted", + "default_third_party_folder": "C:/Users/testuser/.o3de/3rdParty", + "projects": [], + "external_subdirectories": [], + "templates": [], + "restricted": [], + "repos": [], + "engines": [], + "engines_path": {} +} +''' +@pytest.fixture(scope='class') +def init_register_gem_data(request): + request.cls.o3de_manifest_data = json.loads(TEST_O3DE_MANIFEST_JSON_PAYLOAD) + request.cls.project_data = json.loads(TEST_PROJECT_JSON_PAYLOAD) + request.cls.engine_data = json.loads(TEST_ENGINE_JSON_PAYLOAD) + + +@pytest.mark.usefixtures('init_register_gem_data') +class TestRegisterGem: + engine_path = pathlib.PurePath('o3de') + project_path = pathlib.PurePath('TestProject') + + @staticmethod + def get_gem_json_data(gem_path: pathlib.Path = None): + return json.loads(TEST_GEM_JSON_PAYLOAD) + + @pytest.mark.parametrize("gem_path, expected_manifest_file, expected_result", [ + pytest.param(pathlib.PurePath('TestGem'), pathlib.PurePath('o3de_manifest.json'), 0), + pytest.param(project_path / 'TestGem', pathlib.PurePath('project.json'), 0), + pytest.param(engine_path / 'TestGem', pathlib.PurePath('engine.json'), 0), + ]) + def test_register_gem_auto_detects_manifest_update(self, gem_path, expected_manifest_file,expected_result): + + def save_o3de_manifest(manifest_data: dict, manifest_path: pathlib.Path = None) -> bool: + if manifest_path == TestRegisterGem.project_path / 'project.json': + self.project_data = manifest_data + elif manifest_path == TestRegisterGem.engine_path / 'engine.json': + self.engine_data = manifest_data + else: + self.o3de_manifest_data = manifest_data + return True + + def load_o3de_manifest(manifest_path: pathlib.Path = None) -> dict: + if manifest_path == TestRegisterGem.project_path: + return self.project_data + elif manifest_path == TestRegisterGem.engine_path: + return self.engine_data + return self.o3de_manifest_data + + def get_engine_json_data(engine_path: pathlib.Path = None): + return json.loads(TEST_ENGINE_JSON_PAYLOAD) + + def get_project_json_data(project_path: pathlib.Path = None): + return json.loads(TEST_PROJECT_JSON_PAYLOAD) + + def find_ancestor_dir(target_file_name: pathlib.PurePath, start_path: pathlib.Path): + try: + if target_file_name == pathlib.PurePath('project.json')\ + and start_path.relative_to(TestRegisterGem.project_path): + return TestRegisterGem.project_path + except ValueError: + pass + try: + if target_file_name == pathlib.PurePath('engine.json')\ + and start_path.relative_to(TestRegisterGem.engine_path): + return TestRegisterGem.engine_path + except ValueError: + pass + return None + + with patch('o3de.manifest.load_o3de_manifest', side_effect=load_o3de_manifest) as _1,\ + patch('o3de.manifest.save_o3de_manifest', side_effect=save_o3de_manifest) as _2,\ + patch('o3de.manifest.get_engine_json_data', side_effect=get_engine_json_data) as _3,\ + patch('o3de.manifest.get_project_json_data', side_effect=get_project_json_data) as _4,\ + patch('o3de.manifest.get_gem_json_data', side_effect=TestRegisterGem.get_gem_json_data) as _5,\ + patch('o3de.utils.find_ancestor_dir_containing_file', side_effect=find_ancestor_dir) as _6,\ + patch('pathlib.Path.is_dir', return_value=True) as _7,\ + patch('o3de.validation.valid_o3de_gem_json', return_value=True) as _8: + result = register.register(gem_path=gem_path) + assert result == expected_result + + if expected_manifest_file == pathlib.PurePath('o3de_manifest.json'): + assert gem_path in map(lambda subdir: pathlib.PurePath(subdir), + self.o3de_manifest_data.get('external_subdirectories', [])) + elif expected_manifest_file == pathlib.PurePath('project.json'): + assert gem_path in map(lambda subdir: pathlib.PurePath(TestRegisterGem.project_path) / subdir, + self.project_data.get('external_subdirectories', [])) + elif expected_manifest_file == pathlib.PurePath('engine.json'): + assert gem_path in map(lambda subdir: pathlib.PurePath(TestRegisterGem.engine_path) / subdir, + self.engine_data.get('external_subdirectories', [])) From 8571e71d93f574254a8ead1a24ce4dc09b40414a Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Mon, 9 Aug 2021 15:42:55 -0700 Subject: [PATCH 232/803] Add JSON serializer support for the Lua component properties Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- .gitignore | 1 + .../AzCore/AzCore/Script/ScriptProperty.cpp | 50 ---------- .../AzCore/AzCore/Script/ScriptProperty.h | 28 ------ .../Script/ScriptPropertySerializer.cpp | 99 +++++++++++++++++++ .../AzCore/Script/ScriptPropertySerializer.h | 37 +++++++ .../AzCore/Script/ScriptSystemComponent.cpp | 19 ++-- .../DynamicSerializableField.cpp | 6 +- .../Serialization/DynamicSerializableField.h | 7 +- .../AzCore/AzCore/Slice/SliceComponent.h | 1 - .../AzCore/AzCore/azcore_files.cmake | 2 + .../ToolsComponents/ScriptEditorComponent.cpp | 10 -- .../Internal/VersionedProperty.cpp | 1 - 12 files changed, 160 insertions(+), 101 deletions(-) create mode 100644 Code/Framework/AzCore/AzCore/Script/ScriptPropertySerializer.cpp create mode 100644 Code/Framework/AzCore/AzCore/Script/ScriptPropertySerializer.h diff --git a/.gitignore b/.gitignore index 1b63c7698a..b73c89b1d9 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,4 @@ TestResults/** *.swatches /imgui.ini /scripts/project_manager/logs/ +/AutomatedTesting/Gem/PythonTests/scripting/TestResults diff --git a/Code/Framework/AzCore/AzCore/Script/ScriptProperty.cpp b/Code/Framework/AzCore/AzCore/Script/ScriptProperty.cpp index 8664842893..dbccda4de2 100644 --- a/Code/Framework/AzCore/AzCore/Script/ScriptProperty.cpp +++ b/Code/Framework/AzCore/AzCore/Script/ScriptProperty.cpp @@ -31,7 +31,6 @@ namespace AZ ScriptPropertyGenericClassArray::Reflect(reflection); ScriptPropertyAsset::Reflect(reflection); - ScriptPropertyEntityRef::Reflect(reflection); } template @@ -1358,53 +1357,4 @@ namespace AZ m_value = assetProperty->m_value; } } - - //////////////////////////// - // ScriptPropertyEntityRef - //////////////////////////// - void ScriptPropertyEntityRef::Reflect(AZ::ReflectContext* reflection) - { - AZ::SerializeContext* serializeContext = azrtti_cast(reflection); - - if (serializeContext) - { - serializeContext->Class()-> - Version(1)-> - Field("value", &AZ::ScriptPropertyEntityRef::m_value); - } } - - const AZ::Uuid& ScriptPropertyEntityRef::GetDataTypeUuid() const - { - return AZ::SerializeTypeInfo::GetUuid(); - } - - bool ScriptPropertyEntityRef::DoesTypeMatch(AZ::ScriptDataContext& context, int valueIndex) const - { - return context.IsRegisteredClass(valueIndex); - } - - AZ::ScriptPropertyEntityRef* ScriptPropertyEntityRef::Clone(const char* name) const - { - AZ::ScriptPropertyEntityRef* clonedValue = aznew AZ::ScriptPropertyEntityRef(name ? name : m_name.c_str()); - clonedValue->m_value = m_value; - return clonedValue; - } - - bool ScriptPropertyEntityRef::Write(AZ::ScriptContext& context) - { - AZ::ScriptValue::StackPush(context.NativeContext(), m_value); - return true; - } - - void ScriptPropertyEntityRef::CloneDataFrom(const AZ::ScriptProperty* scriptProperty) - { - const AZ::ScriptPropertyEntityRef* entityProperty = azrtti_cast(scriptProperty); - - AZ_Error("ScriptPropertyEntityRef", entityProperty, "Invalid call to CloneData. Types must match before clone attempt is made.\n"); - if (entityProperty) - { - m_value = entityProperty->m_value; - } - } -} diff --git a/Code/Framework/AzCore/AzCore/Script/ScriptProperty.h b/Code/Framework/AzCore/AzCore/Script/ScriptProperty.h index c12fa3e8f1..f38931127d 100644 --- a/Code/Framework/AzCore/AzCore/Script/ScriptProperty.h +++ b/Code/Framework/AzCore/AzCore/Script/ScriptProperty.h @@ -488,34 +488,6 @@ namespace AZ protected: void CloneDataFrom(const AZ::ScriptProperty* scriptProperty) override; }; - - class ScriptPropertyEntityRef - : public ScriptProperty - { - public: - AZ_CLASS_ALLOCATOR(ScriptPropertyEntityRef, AZ::SystemAllocator, 0); - AZ_RTTI(AZ::ScriptPropertyEntityRef, "{68EDE6C3-0A89-4C50-A86E-06C058C9F862}", ScriptProperty); - - static void Reflect(AZ::ReflectContext* reflection); - - ScriptPropertyEntityRef() {} - ScriptPropertyEntityRef(const char* name) - : ScriptProperty(name) {} - virtual ~ScriptPropertyEntityRef() = default; - const void* GetDataAddress() const override { return &m_value; } - const AZ::Uuid& GetDataTypeUuid() const override; - - bool DoesTypeMatch(AZ::ScriptDataContext& context, int valueIndex) const override; - - ScriptPropertyEntityRef* Clone(const char* name = nullptr) const override; - - bool Write(AZ::ScriptContext& context) override; - - AZ::EntityId m_value; - - protected: - void CloneDataFrom(const AZ::ScriptProperty* scriptProperty) override; - }; } #endif diff --git a/Code/Framework/AzCore/AzCore/Script/ScriptPropertySerializer.cpp b/Code/Framework/AzCore/AzCore/Script/ScriptPropertySerializer.cpp new file mode 100644 index 0000000000..ff889be116 --- /dev/null +++ b/Code/Framework/AzCore/AzCore/Script/ScriptPropertySerializer.cpp @@ -0,0 +1,99 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include +#include + +namespace AZ +{ + AZ_CLASS_ALLOCATOR_IMPL(ScriptPropertySerializer, SystemAllocator, 0); + + JsonSerializationResult::Result ScriptPropertySerializer::Load + ( void* outputValue + , [[maybe_unused]] const Uuid& outputValueTypeId + , const rapidjson::Value& inputValue + , JsonDeserializerContext& context) + { + namespace JSR = JsonSerializationResult; + + AZ_Assert(outputValueTypeId == azrtti_typeid(), "ScriptPropertySerializer Load against output typeID that was not DynamicSerializableField"); + AZ_Assert(outputValue, "ScriptPropertySerializer Load against null output"); + + auto outputVariable = reinterpret_cast(outputValue); + JsonSerializationResult::ResultCode result(JSR::Tasks::ReadField); + AZ::Uuid typeId = AZ::Uuid::CreateNull(); + + auto typeIdMember = inputValue.FindMember(JsonSerialization::TypeIdFieldIdentifier); + if (typeIdMember == inputValue.MemberEnd()) + { + return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Missing, AZStd::string::format("ScriptPropertySerializer::Load failed to load the %s member", JsonSerialization::TypeIdFieldIdentifier)); + } + + result.Combine(LoadTypeId(typeId, typeIdMember->value, context)); + if (typeId.IsNull()) + { + return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Catastrophic, "ScriptPropertySerializer::Load failed to load the AZ TypeId of the value"); + } + + AZStd::any storage = context.GetSerializeContext()->CreateAny(typeId); + if (storage.empty() || storage.type() != typeId) + { + return context.Report(result, "ScriptPropertySerializer::Load failed to load a value matched the reported AZ TypeId. The C++ declaration may have been deleted or changed."); + } + + DynamicSerializableField storageField; + storageField.m_data = AZStd::any_cast(&storage); + storageField.m_typeId = typeId; + outputVariable->CopyDataFrom(storageField, context.GetSerializeContext()); + + result.Combine(ContinueLoadingFromJsonObjectField(outputVariable->m_data, typeId, inputValue, "value", context)); + return context.Report(result, result.GetProcessing() != JSR::Processing::Halted + ? "ScriptPropertySerializer Load finished loading DynamicSerializableField" + : "ScriptPropertySerializer Load failed to load DynamicSerializableField"); + } + + JsonSerializationResult::Result ScriptPropertySerializer::Store + ( rapidjson::Value& outputValue + , const void* inputValue + , const void* defaultValue + , [[maybe_unused]] const Uuid& valueTypeId + , JsonSerializerContext& context) + { + namespace JSR = JsonSerializationResult; + + AZ_Assert(valueTypeId == azrtti_typeid(), "DynamicSerializableField Store against value typeID that was not DynamicSerializableField"); + AZ_Assert(inputValue, "DynamicSerializableField Store against null inputValue pointer "); + + auto inputScriptDataPtr = reinterpret_cast(inputValue); + auto inputFieldPtr = inputScriptDataPtr->m_data; + auto defaultScriptDataPtr = reinterpret_cast(defaultValue); + auto defaultFieldPtr = defaultScriptDataPtr ? &defaultScriptDataPtr->m_data : nullptr; + + if (defaultScriptDataPtr && inputScriptDataPtr->IsEqualTo(*defaultScriptDataPtr, context.GetSerializeContext())) + { + return context.Report(JSR::Tasks::WriteValue, JSR::Outcomes::DefaultsUsed, "ScriptPropertySerializer Store used defaults for DynamicSerializableField"); + } + + JSR::ResultCode result(JSR::Tasks::WriteValue); + outputValue.SetObject(); + + { + rapidjson::Value typeValue; + result.Combine(StoreTypeId(typeValue, inputScriptDataPtr->m_typeId, context)); + outputValue.AddMember(rapidjson::StringRef(JsonSerialization::TypeIdFieldIdentifier), AZStd::move(typeValue), context.GetJsonAllocator()); + } + + result.Combine(ContinueStoringToJsonObjectField(outputValue, "value", inputFieldPtr, defaultFieldPtr, inputScriptDataPtr->m_typeId, context)); + + return context.Report(result, result.GetProcessing() != JSR::Processing::Halted + ? "ScriptPropertySerializer Store finished saving DynamicSerializableField" + : "ScriptPropertySerializer Store failed to save DynamicSerializableField"); + } + +} diff --git a/Code/Framework/AzCore/AzCore/Script/ScriptPropertySerializer.h b/Code/Framework/AzCore/AzCore/Script/ScriptPropertySerializer.h new file mode 100644 index 0000000000..a3de3e761d --- /dev/null +++ b/Code/Framework/AzCore/AzCore/Script/ScriptPropertySerializer.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#pragma once + +#include +#include +#include + +namespace AZ +{ + class ScriptPropertySerializer + : public BaseJsonSerializer + { + public: + AZ_RTTI(ScriptPropertySerializer, "{C7BECA49-84EF-45E6-A89D-052D61766197}", BaseJsonSerializer); + AZ_CLASS_ALLOCATOR_DECL; + + private: + JsonSerializationResult::Result Load + ( void* outputValue + , const Uuid& outputValueTypeId + , const rapidjson::Value& inputValue + , JsonDeserializerContext& context) override; + + JsonSerializationResult::Result Store + ( rapidjson::Value& outputValue + , const void* inputValue + , const void* defaultValue + , const Uuid& valueTypeId, JsonSerializerContext& context) override; + }; +} diff --git a/Code/Framework/AzCore/AzCore/Script/ScriptSystemComponent.cpp b/Code/Framework/AzCore/AzCore/Script/ScriptSystemComponent.cpp index 6706d4f8d8..fa61a225c8 100644 --- a/Code/Framework/AzCore/AzCore/Script/ScriptSystemComponent.cpp +++ b/Code/Framework/AzCore/AzCore/Script/ScriptSystemComponent.cpp @@ -8,10 +8,8 @@ #if !defined(AZCORE_EXCLUDE_LUA) -#include - -#include #include +#include #include #include #include @@ -21,13 +19,16 @@ #include #include #include -#include #include #include #include - -#include +#include +#include #include +#include +#include +#include +#include using namespace AZ; @@ -921,6 +922,12 @@ void ScriptSystemComponent::Reflect(ReflectContext* reflection) } } + if (AZ::JsonRegistrationContext* jsonContext = azrtti_cast(reflection)) + { + jsonContext->Serializer() + ->HandlesType(); + } + if (BehaviorContext* behaviorContext = azrtti_cast(reflection)) { // reflect default entity diff --git a/Code/Framework/AzCore/AzCore/Serialization/DynamicSerializableField.cpp b/Code/Framework/AzCore/AzCore/Serialization/DynamicSerializableField.cpp index 16b6a2c48b..036c2df297 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/DynamicSerializableField.cpp +++ b/Code/Framework/AzCore/AzCore/Serialization/DynamicSerializableField.cpp @@ -98,14 +98,14 @@ namespace AZ return nullptr; } //------------------------------------------------------------------------- - void DynamicSerializableField::CopyDataFrom(const DynamicSerializableField& other) + void DynamicSerializableField::CopyDataFrom(const DynamicSerializableField& other, SerializeContext* useContext) { DestroyData(); m_typeId = other.m_typeId; - m_data = other.CloneData(); + m_data = other.CloneData(useContext); } //------------------------------------------------------------------------- - bool DynamicSerializableField::IsEqualTo(const DynamicSerializableField& other, SerializeContext* useContext) + bool DynamicSerializableField::IsEqualTo(const DynamicSerializableField& other, SerializeContext* useContext) const { if (other.m_typeId != m_typeId) { diff --git a/Code/Framework/AzCore/AzCore/Serialization/DynamicSerializableField.h b/Code/Framework/AzCore/AzCore/Serialization/DynamicSerializableField.h index 70a8924265..4b5a963b26 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/DynamicSerializableField.h +++ b/Code/Framework/AzCore/AzCore/Serialization/DynamicSerializableField.h @@ -9,6 +9,8 @@ #define AZCORE_DYNAMIC_SERIALIZABLE_FIELD_H #include +#include +#include namespace AZ { @@ -24,6 +26,7 @@ namespace AZ { public: AZ_TYPE_INFO(DynamicSerializableField, "{D761E0C2-A098-497C-B8EB-EA62F5ED896B}") + AZ_CLASS_ALLOCATOR(DynamicSerializableField, AZ::SystemAllocator, 0); DynamicSerializableField(); DynamicSerializableField(const DynamicSerializableField& serializableField); @@ -33,8 +36,8 @@ namespace AZ void DestroyData(SerializeContext* useContext = nullptr); void* CloneData(SerializeContext* useContext = nullptr) const; - void CopyDataFrom(const DynamicSerializableField& other); - bool IsEqualTo(const DynamicSerializableField& other, SerializeContext* useContext = nullptr); + void CopyDataFrom(const DynamicSerializableField& other, SerializeContext* useContext = nullptr); + bool IsEqualTo(const DynamicSerializableField& other, SerializeContext* useContext = nullptr) const; template void Set(T* object) diff --git a/Code/Framework/AzCore/AzCore/Slice/SliceComponent.h b/Code/Framework/AzCore/AzCore/Slice/SliceComponent.h index 86f41c6548..7a66167a96 100644 --- a/Code/Framework/AzCore/AzCore/Slice/SliceComponent.h +++ b/Code/Framework/AzCore/AzCore/Slice/SliceComponent.h @@ -13,7 +13,6 @@ #include #include #include -#include #include namespace AZ diff --git a/Code/Framework/AzCore/AzCore/azcore_files.cmake b/Code/Framework/AzCore/AzCore/azcore_files.cmake index 1e2a0b98a0..c33d678730 100644 --- a/Code/Framework/AzCore/AzCore/azcore_files.cmake +++ b/Code/Framework/AzCore/AzCore/azcore_files.cmake @@ -462,6 +462,8 @@ set(FILES Script/ScriptTimePoint.h Script/ScriptProperty.h Script/ScriptProperty.cpp + Script/ScriptPropertySerializer.h + Script/ScriptPropertySerializer.cpp Script/ScriptPropertyTable.h Script/ScriptPropertyTable.cpp Script/ScriptPropertyWatcherBus.h diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/ScriptEditorComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/ScriptEditorComponent.cpp index 1ae1a3605a..da12a4bd7a 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/ScriptEditorComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/ScriptEditorComponent.cpp @@ -1107,17 +1107,7 @@ namespace AzToolsFramework ElementAttribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)-> Attribute(AZ::Edit::Attributes::NameLabelOverride, &AZ::ScriptProperty::m_name); - ec->Class("Script Property Asset(asset)", "A script asset property")-> - ClassElement(AZ::Edit::ClassElements::EditorData, "ScriptPropertyEditorAsset's class attributes.")-> - Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)-> - DataElement("Asset", &AZ::ScriptPropertyAsset::m_value, "m_value", "An object")-> - Attribute(AZ::Edit::Attributes::NameLabelOverride, &AZ::ScriptProperty::m_name); - ec->Class("Script Property Entity(EntityRef)", "A script entity reference property")-> - ClassElement(AZ::Edit::ClassElements::EditorData, "ScriptPropertyEditorEntityRef's class attributes.")-> - Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)-> - DataElement("EntityRef", &AZ::ScriptPropertyEntityRef::m_value, "m_entity", "An entity reference")-> - Attribute(AZ::Edit::Attributes::NameLabelOverride, &AZ::ScriptProperty::m_name); } } } diff --git a/Gems/ScriptEvents/Code/Include/ScriptEvents/Internal/VersionedProperty.cpp b/Gems/ScriptEvents/Code/Include/ScriptEvents/Internal/VersionedProperty.cpp index 59f2ffe58c..e09bdc94a9 100644 --- a/Gems/ScriptEvents/Code/Include/ScriptEvents/Internal/VersionedProperty.cpp +++ b/Gems/ScriptEvents/Code/Include/ScriptEvents/Internal/VersionedProperty.cpp @@ -9,7 +9,6 @@ #include "VersionedProperty.h" #include -#include #include #include #include From f85e8124a9ee10e2e337877d2f67e9033fa8eff4 Mon Sep 17 00:00:00 2001 From: kberg-amzn Date: Mon, 9 Aug 2021 16:17:23 -0700 Subject: [PATCH 233/803] Fixes and cleanup for recent correction changes Signed-off-by: kberg-amzn --- .../Serialization/StringifySerializer.cpp | 26 -------- .../Serialization/StringifySerializer.h | 12 +--- .../LocalPredictionPlayerInputComponent.h | 5 -- .../Multiplayer/Components/NetBindComponent.h | 4 ++ .../Components/NetworkTransformComponent.h | 2 + .../LocalPredictionPlayerInputComponent.cpp | 66 ++----------------- .../Source/Components/NetBindComponent.cpp | 10 +++ .../Components/NetworkTransformComponent.cpp | 14 ++++ 8 files changed, 36 insertions(+), 103 deletions(-) diff --git a/Code/Framework/AzNetworking/AzNetworking/Serialization/StringifySerializer.cpp b/Code/Framework/AzNetworking/AzNetworking/Serialization/StringifySerializer.cpp index df018cb6ce..4f31dd0f33 100644 --- a/Code/Framework/AzNetworking/AzNetworking/Serialization/StringifySerializer.cpp +++ b/Code/Framework/AzNetworking/AzNetworking/Serialization/StringifySerializer.cpp @@ -10,19 +10,6 @@ namespace AzNetworking { - StringifySerializer::StringifySerializer(char delimeter, bool outputFieldNames, const AZStd::string& seperator) - : m_delimeter(delimeter) - , m_outputFieldNames(outputFieldNames) - , m_separator(seperator) - { - ; - } - - const AZStd::string& StringifySerializer::GetString() const - { - return m_string; - } - const StringifySerializer::ValueMap& StringifySerializer::GetValueMap() const { return m_valueMap; @@ -138,21 +125,8 @@ namespace AzNetworking bool StringifySerializer::ProcessData(const char* name, const T& value) { const AZStd::string keyString = m_prefix + name; - - if (!m_string.empty()) - { - // Only add delimeters after we have processed at least one element - m_string += m_delimeter; - } - - if (m_outputFieldNames) - { - m_string += keyString; - } - AZ::CVarFixedString valueString = AZ::ConsoleTypeHelpers::ValueToString(value); m_valueMap[keyString] = valueString.c_str(); - return true; } } diff --git a/Code/Framework/AzNetworking/AzNetworking/Serialization/StringifySerializer.h b/Code/Framework/AzNetworking/AzNetworking/Serialization/StringifySerializer.h index 379b5198c7..3ea0bfa412 100644 --- a/Code/Framework/AzNetworking/AzNetworking/Serialization/StringifySerializer.h +++ b/Code/Framework/AzNetworking/AzNetworking/Serialization/StringifySerializer.h @@ -22,10 +22,7 @@ namespace AzNetworking using ValueMap = AZStd::map; - StringifySerializer(char delimeter = ' ', bool outputFieldNames = true, const AZStd::string& seperator = "="); - - //! After serializing objects, get the serialized values as a single string. - const AZStd::string& GetString() const; + StringifySerializer() = default; //! After serializing objects, get the serialized values as a map of key/value pairs. const ValueMap& GetValueMap() const; @@ -60,15 +57,8 @@ namespace AzNetworking template bool ProcessData(const char* name, const T& value); - private: - - char m_delimeter; - bool m_outputFieldNames = true; - ValueMap m_valueMap; - AZStd::string m_string; AZStd::string m_prefix; - AZStd::string m_separator; AZStd::deque m_prefixSizeStack; }; } diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/LocalPredictionPlayerInputComponent.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/LocalPredictionPlayerInputComponent.h index 4e5d7f2d49..f26f043b85 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/Components/LocalPredictionPlayerInputComponent.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/LocalPredictionPlayerInputComponent.h @@ -14,8 +14,6 @@ namespace Multiplayer { - using CorrectionEvent = AZ::Event<>; - class LocalPredictionPlayerInputComponent : public LocalPredictionPlayerInputComponentBase { @@ -65,8 +63,6 @@ namespace Multiplayer ClientInputId GetLastInputId() const; HostFrameId GetInputFrameId(const NetworkInput& input) const; - void CorrectionEventAddHandle(CorrectionEvent::Handler& handler); - private: void OnMigrateStart(ClientInputId migratedInputId); @@ -86,7 +82,6 @@ namespace Multiplayer AZ::ScheduledEvent m_autonomousUpdateEvent; // Drives autonomous input collection AZ::ScheduledEvent m_updateBankedTimeEvent; // Drives authority bank time updates - CorrectionEvent m_correctionEvent; EntityMigrationStartEvent::Handler m_migrateStartHandler; EntityMigrationEndEvent::Handler m_migrateEndHandler; diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetBindComponent.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetBindComponent.h index c050495f1f..65bac09726 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetBindComponent.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetBindComponent.h @@ -36,6 +36,7 @@ namespace Multiplayer using EntityMigrationEndEvent = AZ::Event<>; using EntityServerMigrationEvent = AZ::Event; using EntityPreRenderEvent = AZ::Event; + using EntityCorrectionEvent = AZ::Event<>; //! @class NetBindComponent //! @brief Component that provides net-binding to a networked entity. @@ -118,6 +119,7 @@ namespace Multiplayer void NotifyMigrationEnd(); void NotifyServerMigration(HostId hostId, AzNetworking::ConnectionId connectionId); void NotifyPreRender(float deltaTime, float blendFactor); + void NotifyCorrection(); void AddEntityStopEventHandler(EntityStopEvent::Handler& eventHandler); void AddEntityDirtiedEventHandler(EntityDirtiedEvent::Handler& eventHandler); @@ -126,6 +128,7 @@ namespace Multiplayer void AddEntityMigrationEndEventHandler(EntityMigrationEndEvent::Handler& eventHandler); void AddEntityServerMigrationEventHandler(EntityServerMigrationEvent::Handler& eventHandler); void AddEntityPreRenderEventHandler(EntityPreRenderEvent::Handler& eventHandler); + void AddEntityCorrectionEventHandler(EntityCorrectionEvent::Handler& handler); bool SerializeEntityCorrection(AzNetworking::ISerializer& serializer); @@ -175,6 +178,7 @@ namespace Multiplayer EntityMigrationEndEvent m_entityMigrationEndEvent; EntityServerMigrationEvent m_entityServerMigrationEvent; EntityPreRenderEvent m_entityPreRenderEvent; + EntityCorrectionEvent m_entityCorrectionEvent; AZ::Event<> m_onRemove; RpcSendEvent::Handler m_handleLocalServerRpcMessageEventHandle; AZ::Event<>::Handler m_handleMarkedDirty; diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkTransformComponent.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkTransformComponent.h index 16aa8157aa..914aeaadd3 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkTransformComponent.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkTransformComponent.h @@ -30,6 +30,7 @@ namespace Multiplayer private: void OnPreRender(float deltaTime, float blendFactor); + void OnCorrection(); void OnRotationChangedEvent(const AZ::Quaternion& rotation); void OnTranslationChangedEvent(const AZ::Vector3& translation); @@ -47,6 +48,7 @@ namespace Multiplayer AZ::Event::Handler m_resetCountEventHandler; EntityPreRenderEvent::Handler m_entityPreRenderEventHandler; + EntityCorrectionEvent::Handler m_entityCorrectionEventHandler; Multiplayer::HostFrameId m_targetHostFrameId = HostFrameId(0); }; diff --git a/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp b/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp index 4185b01798..5b6b93a3aa 100644 --- a/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp @@ -32,21 +32,6 @@ namespace Multiplayer AZ_CVAR(AZ::TimeMs, sv_MinCorrectionTimeMs, AZ::TimeMs{ 100 }, nullptr, AZ::ConsoleFunctorFlags::Null, "Minimum time to wait between sending out corrections in order to avoid flooding corrections on high-latency connections"); AZ_CVAR(AZ::TimeMs, sv_InputUpdateTimeMs, AZ::TimeMs{ 5 }, nullptr, AZ::ConsoleFunctorFlags::Null, "Minimum time between component updates"); - // Debug helper functions - AZStd::string GetInputString(NetworkInput& input) - { - AzNetworking::StringifySerializer serializer(',', false); - input.Serialize(serializer); - return serializer.GetString(); - } - - AZStd::string GetCorrectionDataString(NetBindComponent* netBindComponent) - { - AzNetworking::StringifySerializer serializer(',', false); - netBindComponent->SerializeEntityCorrection(serializer); - return serializer.GetString(); - } - void PrintCorrectionDifferences(const AzNetworking::StringifySerializer& client, const AzNetworking::StringifySerializer& server) { const auto& clientMap = client.GetValueMap(); @@ -289,14 +274,7 @@ namespace Multiplayer ScopedAlterTime scopedTime(input.GetHostFrameId(), input.GetHostTimeMs(), input.GetHostBlendFactor(), invokingConnection->GetConnectionId()); GetNetBindComponent()->ProcessInput(input, clientInputRateSec); - AZLOG - ( - NET_Prediction, - "Migrated InputId=%d - i=[%s] o=[%s]", - aznumeric_cast(input.GetClientInputId()), - GetInputString(input).c_str(), - GetCorrectionDataString(GetNetBindComponent()).c_str() - ); + AZLOG(NET_Prediction, "Migrated InputId=%d", aznumeric_cast(input.GetClientInputId())); // Don't bother checking for corrections here, the next regular input will trigger any corrections if necessary // Also don't bother with any cheat detection here, because the input array is limited in size and at most and can only be sent once @@ -329,7 +307,7 @@ namespace Multiplayer // Apply the correction AzNetworking::TrackChangedSerializer serializer(correction.GetBuffer(), correction.GetSize()); GetNetBindComponent()->SerializeEntityCorrection(serializer); - m_correctionEvent.Signal(); + GetNetBindComponent()->NotifyCorrection(); #ifndef AZ_RELEASE_BUILD if (cl_EnableDesyncDebugging) @@ -350,14 +328,6 @@ namespace Multiplayer } #endif - AZLOG - ( - NET_Prediction, - "Corrected InputId=%d - o=[%s]", - aznumeric_cast(m_lastCorrectionInputId), - GetCorrectionDataString(GetNetBindComponent()).c_str() - ); - const uint32_t inputHistorySize = m_inputHistory.Size(); const uint32_t historicalDelta = aznumeric_cast(m_clientInputId - inputId); // Do not replay the move we just corrected, that was already processed by the server @@ -372,14 +342,7 @@ namespace Multiplayer ScopedAlterTime scopedTime(input.GetHostFrameId(), input.GetHostTimeMs(), input.GetHostBlendFactor(), invokingConnection->GetConnectionId()); GetNetBindComponent()->ReprocessInput(input, clientInputRateSec); - AZLOG - ( - NET_Prediction, - "Replayed InputId=%d - i=[%s] o=[%s]", - aznumeric_cast(input.GetClientInputId()), - GetInputString(input).c_str(), - GetCorrectionDataString(GetNetBindComponent()).c_str() - ); + AZLOG(NET_Prediction, "Replayed InputId=%d", aznumeric_cast(input.GetClientInputId())); } } @@ -402,11 +365,6 @@ namespace Multiplayer return (input.GetHostFrameId() == InvalidHostFrameId) ? m_serverMigrateFrameId : input.GetHostFrameId(); } - void LocalPredictionPlayerInputComponentController::CorrectionEventAddHandle(CorrectionEvent::Handler& handler) - { - handler.Connect(m_correctionEvent); - } - void LocalPredictionPlayerInputComponentController::OnMigrateStart(ClientInputId migratedInputId) { m_lastMigratedInputId = migratedInputId; @@ -480,14 +438,7 @@ namespace Multiplayer // Process the input for this frame GetNetBindComponent()->ProcessInput(input, inputRate); - AZLOG - ( - NET_Prediction, - "Processed InutId=%d - i=[%s] o=[%s]", - aznumeric_cast(m_clientInputId), - GetInputString(input).c_str(), - GetCorrectionDataString(GetNetBindComponent()).c_str() - ); + AZLOG(NET_Prediction, "Processed InputId=%d", aznumeric_cast(m_clientInputId)); // Generate a hash based on the current client predicted states AzNetworking::HashSerializer hashSerializer; @@ -553,14 +504,7 @@ namespace Multiplayer GetNetBindComponent()->ProcessInput(input, inputRate); } - AZLOG - ( - NET_Prediction, - "Forced InputId=%d - i=[%s] o=[%s]", - aznumeric_cast(input.GetClientInputId()), - GetInputString(input).c_str(), - GetCorrectionDataString(GetNetBindComponent()).c_str() - ); + AZLOG(NET_Prediction, "Forced InputId=%d", aznumeric_cast(input.GetClientInputId())); } // Decay our bank time window, in case the remote endpoint has suffered a more persistent shift in latency, this should cause the client to eventually recover diff --git a/Gems/Multiplayer/Code/Source/Components/NetBindComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetBindComponent.cpp index cbbbadeffa..070655e768 100644 --- a/Gems/Multiplayer/Code/Source/Components/NetBindComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/NetBindComponent.cpp @@ -408,6 +408,11 @@ namespace Multiplayer m_entityPreRenderEvent.Signal(deltaTime, blendFactor); } + void NetBindComponent::NotifyCorrection() + { + m_entityCorrectionEvent.Signal(); + } + void NetBindComponent::AddEntityStopEventHandler(EntityStopEvent::Handler& eventHandler) { eventHandler.Connect(m_entityStopEvent); @@ -443,6 +448,11 @@ namespace Multiplayer eventHandler.Connect(m_entityPreRenderEvent); } + void NetBindComponent::AddEntityCorrectionEventHandler(EntityCorrectionEvent::Handler& eventHandler) + { + eventHandler.Connect(m_entityCorrectionEvent); + } + bool NetBindComponent::SerializeEntityCorrection(AzNetworking::ISerializer& serializer) { m_predictableRecord.ResetConsumedBits(); diff --git a/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.cpp index df4d7618fa..fa08794c4d 100644 --- a/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.cpp @@ -31,6 +31,7 @@ namespace Multiplayer , m_scaleEventHandler([this](float scale) { OnScaleChangedEvent(scale); }) , m_resetCountEventHandler([this](const uint8_t&) { OnResetCountChangedEvent(); }) , m_entityPreRenderEventHandler([this](float deltaTime, float blendFactor) { OnPreRender(deltaTime, blendFactor); }) + , m_entityCorrectionEventHandler([this]() { OnCorrection(); }) { ; } @@ -47,6 +48,7 @@ namespace Multiplayer ScaleAddEvent(m_scaleEventHandler); ResetCountAddEvent(m_resetCountEventHandler); GetNetBindComponent()->AddEntityPreRenderEventHandler(m_entityPreRenderEventHandler); + GetNetBindComponent()->AddEntityCorrectionEventHandler(m_entityCorrectionEventHandler); // When coming into relevance, reset all blending factors so we don't interpolate to our start position OnResetCountChangedEvent(); @@ -119,6 +121,18 @@ namespace Multiplayer } } + void NetworkTransformComponent::OnCorrection() + { + // Snap to latest + OnResetCountChangedEvent(); + + // Hard set the entities transform + if (!GetTransformComponent()->GetWorldTM().IsClose(m_targetTransform)) + { + GetTransformComponent()->SetWorldTM(m_targetTransform); + } + } + NetworkTransformComponentController::NetworkTransformComponentController(NetworkTransformComponent& parent) : NetworkTransformComponentControllerBase(parent) From c6fdb76aedf74a760f314f8074a05743560e7927 Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Mon, 9 Aug 2021 16:33:54 -0700 Subject: [PATCH 234/803] Bump version number on LuaBuilderComponent Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- .../Code/Source/Builders/LuaBuilder/LuaBuilderComponent.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/LmbrCentral/Code/Source/Builders/LuaBuilder/LuaBuilderComponent.cpp b/Gems/LmbrCentral/Code/Source/Builders/LuaBuilder/LuaBuilderComponent.cpp index 5a787c480f..0ef02837da 100644 --- a/Gems/LmbrCentral/Code/Source/Builders/LuaBuilder/LuaBuilderComponent.cpp +++ b/Gems/LmbrCentral/Code/Source/Builders/LuaBuilder/LuaBuilderComponent.cpp @@ -25,7 +25,7 @@ void LuaBuilder::BuilderPluginComponent::Activate() { AssetBuilderSDK::AssetBuilderDesc builderDescriptor; builderDescriptor.m_name = "Lua Worker Builder"; - builderDescriptor.m_version = 6; + builderDescriptor.m_version = 7; builderDescriptor.m_analysisFingerprint = AZStd::string::format("%d", static_cast(AZ::ScriptAsset::AssetVersion)); builderDescriptor.m_patterns.push_back(AssetBuilderSDK::AssetBuilderPattern("*.lua", AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard)); builderDescriptor.m_busId = azrtti_typeid(); From 1837d0516968fa9373f5ff5c079effb1a208da0a Mon Sep 17 00:00:00 2001 From: Chris Burel Date: Mon, 9 Aug 2021 14:09:45 -0700 Subject: [PATCH 235/803] Rename EMotionFX class members to follow the `m_` naming convention Signed-off-by: Chris Burel --- .../EMotionFXAtom/Code/Source/ActorAsset.cpp | 4 +- .../Code/Source/AtomActorInstance.cpp | 6 +- .../CommandSystem/Source/ActorCommands.cpp | 102 +-- .../CommandSystem/Source/ActorCommands.h | 38 +- .../Source/ActorInstanceCommands.cpp | 82 +- .../Source/ActorInstanceCommands.h | 34 +- .../Source/AnimGraphCommands.cpp | 96 +- .../CommandSystem/Source/AnimGraphCommands.h | 20 +- .../Source/AnimGraphConnectionCommands.cpp | 186 ++-- .../Source/AnimGraphConnectionCommands.h | 94 +- .../AnimGraphGroupParameterCommands.cpp | 68 +- .../Source/AnimGraphGroupParameterCommands.h | 20 +- .../Source/AnimGraphNodeCommands.cpp | 178 ++-- .../Source/AnimGraphNodeCommands.h | 68 +- .../Source/AnimGraphNodeGroupCommands.cpp | 30 +- .../Source/AnimGraphNodeGroupCommands.h | 14 +- .../Source/AnimGraphParameterCommands.cpp | 100 +- .../Source/AnimGraphParameterCommands.h | 46 +- .../CommandSystem/Source/CommandManager.cpp | 4 +- .../CommandSystem/Source/CommandManager.h | 18 +- .../CommandSystem/Source/ImporterCommands.cpp | 40 +- .../CommandSystem/Source/ImporterCommands.h | 12 +- .../CommandSystem/Source/MetaData.cpp | 2 +- .../Source/MorphTargetCommands.cpp | 24 +- .../Source/MorphTargetCommands.h | 12 +- .../CommandSystem/Source/MotionCommands.cpp | 168 ++-- .../CommandSystem/Source/MotionCommands.h | 30 +- .../Source/MotionEventCommands.cpp | 20 +- .../Source/MotionEventCommands.h | 10 +- .../Source/MotionSetCommands.cpp | 82 +- .../CommandSystem/Source/MotionSetCommands.h | 26 +- .../Source/NodeGroupCommands.cpp | 22 +- .../CommandSystem/Source/NodeGroupCommands.h | 6 +- .../CommandSystem/Source/RagdollCommands.cpp | 4 +- .../Source/SelectionCommands.cpp | 18 +- .../CommandSystem/Source/SelectionCommands.h | 2 +- .../CommandSystem/Source/SelectionList.cpp | 80 +- .../CommandSystem/Source/SelectionList.h | 96 +- .../ExporterLib/Exporter/EndianConversion.cpp | 124 +-- .../ExporterLib/Exporter/ExporterActor.cpp | 18 +- .../ExporterLib/Exporter/FileHeaderExport.cpp | 91 +- .../ExporterLib/Exporter/MaterialExport.cpp | 298 ------ .../ExporterLib/Exporter/MeshExport.cpp | 270 ------ .../Exporter/MorphTargetExport.cpp | 68 +- .../Exporter/MotionEventExport.cpp | 6 +- .../ExporterLib/Exporter/NodeExport.cpp | 110 +-- .../Exporter/SkeletalMotionExport.cpp | 6 +- .../ExporterLib/Exporter/SkinExport.cpp | 186 ---- .../EMotionFX/Rendering/Common/Camera.cpp | 42 +- .../Code/EMotionFX/Rendering/Common/Camera.h | 40 +- .../EMotionFX/Rendering/Common/Camera.inl | 42 +- .../Rendering/Common/FirstPersonCamera.cpp | 26 +- .../Rendering/Common/FirstPersonCamera.h | 18 +- .../Rendering/Common/LookAtCamera.cpp | 8 +- .../EMotionFX/Rendering/Common/LookAtCamera.h | 12 +- .../Rendering/Common/OrbitCamera.cpp | 176 ++-- .../EMotionFX/Rendering/Common/OrbitCamera.h | 54 +- .../Rendering/Common/OrthographicCamera.cpp | 192 ++-- .../Rendering/Common/OrthographicCamera.h | 40 +- .../EMotionFX/Rendering/Common/RenderUtil.cpp | 545 ++++++----- .../EMotionFX/Rendering/Common/RenderUtil.h | 228 +++-- .../Rendering/Common/RotateManipulator.cpp | 371 ++++---- .../Rendering/Common/RotateManipulator.h | 54 +- .../Rendering/Common/ScaleManipulator.cpp | 294 +++--- .../Rendering/Common/ScaleManipulator.h | 44 +- .../Common/TransformationManipulator.h | 110 +-- .../Rendering/Common/TranslateManipulator.cpp | 254 +++--- .../Rendering/Common/TranslateManipulator.h | 32 +- .../Rendering/OpenGL2/Source/GBuffer.cpp | 141 ++- .../Rendering/OpenGL2/Source/GBuffer.h | 34 +- .../Rendering/OpenGL2/Source/GLActor.cpp | 230 ++--- .../Rendering/OpenGL2/Source/GLExtensions.cpp | 2 +- .../Rendering/OpenGL2/Source/GLExtensions.h | 2 +- .../Rendering/OpenGL2/Source/GLRenderUtil.cpp | 280 +++--- .../Rendering/OpenGL2/Source/GLRenderUtil.h | 48 +- .../Rendering/OpenGL2/Source/GLSLShader.cpp | 184 ++-- .../Rendering/OpenGL2/Source/GLSLShader.h | 34 +- .../OpenGL2/Source/GraphicsManager.cpp | 221 ++--- .../OpenGL2/Source/GraphicsManager.h | 200 ++-- .../Rendering/OpenGL2/Source/IndexBuffer.cpp | 26 +- .../Rendering/OpenGL2/Source/IndexBuffer.h | 8 +- .../Rendering/OpenGL2/Source/Material.cpp | 4 +- .../Rendering/OpenGL2/Source/Material.h | 48 +- .../OpenGL2/Source/PostProcessShader.cpp | 14 +- .../OpenGL2/Source/PostProcessShader.h | 2 +- .../OpenGL2/Source/RenderTexture.cpp | 66 +- .../Rendering/OpenGL2/Source/RenderTexture.h | 14 +- .../Rendering/OpenGL2/Source/ShaderCache.cpp | 22 +- .../OpenGL2/Source/StandardMaterial.cpp | 176 ++-- .../OpenGL2/Source/StandardMaterial.h | 18 +- .../Rendering/OpenGL2/Source/TextureCache.cpp | 60 +- .../Rendering/OpenGL2/Source/TextureCache.h | 26 +- .../Rendering/OpenGL2/Source/VertexBuffer.cpp | 26 +- .../Rendering/OpenGL2/Source/VertexBuffer.h | 8 +- .../Rendering/OpenGL2/Source/glactor.h | 42 +- .../Rendering/OpenGL2/Source/shadercache.h | 6 +- .../EMotionFX/Code/EMotionFX/Source/Actor.cpp | 651 +++++++------ Gems/EMotionFX/Code/EMotionFX/Source/Actor.h | 110 +-- .../Code/EMotionFX/Source/ActorInstance.cpp | 480 +++++----- .../Code/EMotionFX/Source/ActorInstance.h | 96 +- .../Code/EMotionFX/Source/ActorManager.cpp | 78 +- .../Code/EMotionFX/Source/ActorManager.h | 18 +- .../EMotionFX/Source/ActorUpdateScheduler.h | 12 +- .../Code/EMotionFX/Source/AnimGraph.cpp | 168 ++-- .../Code/EMotionFX/Source/AnimGraph.h | 32 +- .../Source/AnimGraphAttributeTypes.h | 32 +- .../Source/AnimGraphBindPoseNode.cpp | 2 +- .../EMotionFX/Source/AnimGraphEntryNode.cpp | 2 +- .../EMotionFX/Source/AnimGraphEventBuffer.cpp | 18 +- .../EMotionFX/Source/AnimGraphExitNode.cpp | 8 +- .../Source/AnimGraphGameControllerSettings.h | 12 +- .../EMotionFX/Source/AnimGraphHubNode.cpp | 2 +- .../EMotionFX/Source/AnimGraphInstance.cpp | 228 ++--- .../Code/EMotionFX/Source/AnimGraphInstance.h | 74 +- .../EMotionFX/Source/AnimGraphManager.cpp | 100 +- .../Code/EMotionFX/Source/AnimGraphManager.h | 20 +- .../Source/AnimGraphMotionCondition.cpp | 12 +- .../Source/AnimGraphMotionCondition.h | 2 +- .../EMotionFX/Source/AnimGraphMotionNode.cpp | 180 ++-- .../EMotionFX/Source/AnimGraphMotionNode.h | 8 +- .../Code/EMotionFX/Source/AnimGraphNode.cpp | 516 +++++------ .../Code/EMotionFX/Source/AnimGraphNode.h | 194 ++-- .../EMotionFX/Source/AnimGraphNodeData.cpp | 58 +- .../Code/EMotionFX/Source/AnimGraphNodeData.h | 90 +- .../EMotionFX/Source/AnimGraphNodeGroup.cpp | 58 +- .../EMotionFX/Source/AnimGraphNodeGroup.h | 8 +- .../Code/EMotionFX/Source/AnimGraphObject.cpp | 26 +- .../Code/EMotionFX/Source/AnimGraphObject.h | 12 +- .../EMotionFX/Source/AnimGraphObjectData.cpp | 6 +- .../EMotionFX/Source/AnimGraphObjectData.h | 30 +- .../Source/AnimGraphParameterAction.cpp | 12 +- .../Source/AnimGraphParameterCondition.cpp | 16 +- .../Source/AnimGraphPlayTimeCondition.cpp | 4 +- .../Code/EMotionFX/Source/AnimGraphPose.cpp | 14 +- .../Code/EMotionFX/Source/AnimGraphPose.h | 20 +- .../EMotionFX/Source/AnimGraphPosePool.cpp | 41 +- .../Code/EMotionFX/Source/AnimGraphPosePool.h | 16 +- .../Source/AnimGraphRefCountedData.h | 28 +- .../Source/AnimGraphRefCountedDataPool.cpp | 40 +- .../Source/AnimGraphRefCountedDataPool.h | 16 +- .../Source/AnimGraphReferenceNode.cpp | 58 +- .../EMotionFX/Source/AnimGraphSnapshot.cpp | 2 +- .../Source/AnimGraphStateCondition.cpp | 40 +- .../Source/AnimGraphStateCondition.h | 10 +- .../Source/AnimGraphStateMachine.cpp | 216 ++--- .../EMotionFX/Source/AnimGraphStateMachine.h | 18 +- .../Source/AnimGraphStateTransition.cpp | 174 ++-- .../Source/AnimGraphStateTransition.h | 32 +- .../EMotionFX/Source/AnimGraphSyncTrack.cpp | 2 +- .../Source/AnimGraphTagCondition.cpp | 2 +- .../Source/AnimGraphTimeCondition.cpp | 16 +- .../EMotionFX/Source/AnimGraphTimeCondition.h | 4 +- .../Source/AnimGraphTransitionCondition.cpp | 4 +- .../Source/AnimGraphTriggerAction.cpp | 4 +- .../Source/AnimGraphVector2Condition.cpp | 8 +- .../EMotionFX/Source/BlendSpace1DNode.cpp | 32 +- .../EMotionFX/Source/BlendSpace2DNode.cpp | 44 +- .../Code/EMotionFX/Source/BlendSpaceNode.cpp | 6 +- .../Code/EMotionFX/Source/BlendSpaceNode.h | 6 +- .../Source/BlendSpaceParamEvaluator.cpp | 40 +- .../Code/EMotionFX/Source/BlendTree.cpp | 26 +- .../Code/EMotionFX/Source/BlendTree.h | 4 +- .../Source/BlendTreeAccumTransformNode.cpp | 54 +- .../Source/BlendTreeAccumTransformNode.h | 6 +- .../Source/BlendTreeBlend2AdditiveNode.cpp | 32 +- .../Source/BlendTreeBlend2LegacyNode.cpp | 36 +- .../EMotionFX/Source/BlendTreeBlend2Node.cpp | 32 +- .../Source/BlendTreeBlend2NodeBase.cpp | 20 +- .../Source/BlendTreeBlend2NodeBase.h | 4 +- .../EMotionFX/Source/BlendTreeBlendNNode.cpp | 72 +- .../EMotionFX/Source/BlendTreeBlendNNode.h | 4 +- .../Source/BlendTreeBoolLogicNode.cpp | 12 +- .../EMotionFX/Source/BlendTreeConnection.cpp | 16 +- .../EMotionFX/Source/BlendTreeConnection.h | 18 +- .../Source/BlendTreeDirectionToWeightNode.cpp | 4 +- .../EMotionFX/Source/BlendTreeFinalNode.cpp | 8 +- .../Source/BlendTreeFloatConditionNode.cpp | 10 +- .../Source/BlendTreeFloatMath1Node.cpp | 8 +- .../Source/BlendTreeFloatMath2Node.cpp | 12 +- .../Source/BlendTreeFloatSwitchNode.cpp | 4 +- .../EMotionFX/Source/BlendTreeFootIKNode.cpp | 102 +-- .../Source/BlendTreeGetTransformNode.cpp | 12 +- .../EMotionFX/Source/BlendTreeLookAtNode.cpp | 62 +- .../EMotionFX/Source/BlendTreeLookAtNode.h | 8 +- .../Source/BlendTreeMaskLegacyNode.cpp | 40 +- .../Source/BlendTreeMaskLegacyNode.h | 6 +- .../EMotionFX/Source/BlendTreeMaskNode.cpp | 14 +- .../Source/BlendTreeMirrorPoseNode.cpp | 18 +- .../Source/BlendTreeMorphTargetNode.cpp | 12 +- .../Source/BlendTreeMotionFrameNode.cpp | 34 +- .../Source/BlendTreeMotionFrameNode.h | 8 +- .../Source/BlendTreeParameterNode.cpp | 36 +- .../Source/BlendTreePoseSubtractNode.cpp | 20 +- .../Source/BlendTreePoseSwitchNode.cpp | 34 +- .../Source/BlendTreePoseSwitchNode.h | 2 +- .../EMotionFX/Source/BlendTreeRagdollNode.cpp | 38 +- .../BlendTreeRagdollStrengthModifierNode.cpp | 8 +- .../Source/BlendTreeRangeRemapperNode.cpp | 6 +- .../EMotionFX/Source/BlendTreeRaycastNode.cpp | 2 +- .../Source/BlendTreeRotationLimitNode.cpp | 6 +- .../Source/BlendTreeRotationMath2Node.cpp | 12 +- .../Source/BlendTreeSetTransformNode.cpp | 16 +- .../Source/BlendTreeSimulatedObjectNode.cpp | 24 +- .../Source/BlendTreeSmoothingNode.cpp | 22 +- .../EMotionFX/Source/BlendTreeSmoothingNode.h | 4 +- .../Source/BlendTreeTransformNode.cpp | 28 +- .../EMotionFX/Source/BlendTreeTransformNode.h | 2 +- .../Source/BlendTreeTwoLinkIKNode.cpp | 120 +-- .../EMotionFX/Source/BlendTreeTwoLinkIKNode.h | 12 +- .../Source/BlendTreeVector3Math1Node.cpp | 4 +- .../Source/BlendTreeVector3Math2Node.cpp | 6 +- .../Source/BlendTreeVector4DecomposeNode.cpp | 2 +- .../EMotionFX/Source/CompressedKeyFrames.h | 40 +- .../EMotionFX/Source/ConstraintTransform.h | 10 +- .../ConstraintTransformRotationAngles.cpp | 60 +- .../ConstraintTransformRotationAngles.h | 10 +- .../Code/EMotionFX/Source/DebugDraw.cpp | 4 +- .../EMotionFX/Source/DualQuatSkinDeformer.cpp | 38 +- .../EMotionFX/Source/DualQuatSkinDeformer.h | 10 +- .../EMotionFX/Source/EMotionFXManager.cpp | 173 ++-- .../Code/EMotionFX/Source/EMotionFXManager.h | 79 +- .../Code/EMotionFX/Source/EventHandler.h | 14 +- .../Code/EMotionFX/Source/EventInfo.h | 28 +- .../Code/EMotionFX/Source/EventManager.cpp | 14 +- .../Code/EMotionFX/Source/EventManager.h | 54 +- .../Source/Importer/ActorFileFormat.h | 134 +-- .../Source/Importer/ChunkProcessors.cpp | 853 +++++++++--------- .../Source/Importer/ChunkProcessors.h | 26 +- .../EMotionFX/Source/Importer/Importer.cpp | 150 +-- .../Code/EMotionFX/Source/Importer/Importer.h | 64 +- .../Source/Importer/MotionFileFormat.h | 120 +-- .../Source/Importer/NodeMapFileFormat.h | 12 +- .../Source/Importer/SharedFileFormatStructs.h | 64 +- .../Code/EMotionFX/Source/KeyFrame.h | 4 +- .../Code/EMotionFX/Source/KeyFrame.inl | 22 +- .../EMotionFX/Source/KeyTrackLinearDynamic.h | 2 +- .../Source/KeyTrackLinearDynamic.inl | 137 ++- .../Code/EMotionFX/Source/LayerPass.h | 4 +- .../Code/EMotionFX/Source/Material.cpp | 6 +- .../Code/EMotionFX/Source/Material.h | 2 +- Gems/EMotionFX/Code/EMotionFX/Source/Mesh.cpp | 329 +++---- Gems/EMotionFX/Code/EMotionFX/Source/Mesh.h | 28 +- Gems/EMotionFX/Code/EMotionFX/Source/Mesh.inl | 31 +- .../Code/EMotionFX/Source/MeshDeformer.cpp | 8 +- .../Code/EMotionFX/Source/MeshDeformer.h | 4 +- .../EMotionFX/Source/MeshDeformerStack.cpp | 52 +- .../Code/EMotionFX/Source/MeshDeformerStack.h | 4 +- .../EMotionFX/Source/MorphMeshDeformer.cpp | 84 +- .../Code/EMotionFX/Source/MorphMeshDeformer.h | 14 +- .../Code/EMotionFX/Source/MorphSetup.cpp | 46 +- .../Code/EMotionFX/Source/MorphSetup.h | 6 +- .../EMotionFX/Source/MorphSetupInstance.cpp | 10 +- .../EMotionFX/Source/MorphSetupInstance.h | 32 +- .../Code/EMotionFX/Source/MorphTarget.cpp | 48 +- .../Code/EMotionFX/Source/MorphTarget.h | 10 +- .../EMotionFX/Source/MorphTargetStandard.cpp | 178 ++-- .../EMotionFX/Source/MorphTargetStandard.h | 34 +- .../Code/EMotionFX/Source/Motion.cpp | 66 +- Gems/EMotionFX/Code/EMotionFX/Source/Motion.h | 22 +- .../Source/MotionData/MotionData.cpp | 42 +- .../MotionData/NonUniformMotionData.cpp | 82 +- .../Source/MotionData/UniformMotionData.cpp | 70 +- .../EMotionFX/Source/MotionEventTrack.cpp | 24 +- .../Code/EMotionFX/Source/MotionEventTrack.h | 6 +- .../Code/EMotionFX/Source/MotionInstance.cpp | 78 +- .../Code/EMotionFX/Source/MotionInstance.h | 10 +- .../EMotionFX/Source/MotionInstancePool.cpp | 206 +++-- .../EMotionFX/Source/MotionInstancePool.h | 28 +- .../EMotionFX/Source/MotionLayerSystem.cpp | 100 +- .../Code/EMotionFX/Source/MotionLayerSystem.h | 4 +- .../Code/EMotionFX/Source/MotionManager.cpp | 122 +-- .../Code/EMotionFX/Source/MotionManager.h | 16 +- .../Code/EMotionFX/Source/MotionQueue.cpp | 34 +- .../Code/EMotionFX/Source/MotionQueue.h | 16 +- .../Code/EMotionFX/Source/MotionSystem.cpp | 91 +- .../Code/EMotionFX/Source/MotionSystem.h | 6 +- .../EMotionFX/Source/MultiThreadScheduler.cpp | 100 +- .../EMotionFX/Source/MultiThreadScheduler.h | 14 +- Gems/EMotionFX/Code/EMotionFX/Source/Node.cpp | 152 ++-- Gems/EMotionFX/Code/EMotionFX/Source/Node.h | 38 +- .../Code/EMotionFX/Source/NodeGroup.cpp | 46 +- .../Code/EMotionFX/Source/NodeGroup.h | 6 +- .../Code/EMotionFX/Source/NodeMap.cpp | 90 +- .../EMotionFX/Code/EMotionFX/Source/NodeMap.h | 10 +- .../Code/EMotionFX/Source/PhysicsSetup.cpp | 6 +- .../Code/EMotionFX/Source/PlayBackInfo.h | 142 +-- Gems/EMotionFX/Code/EMotionFX/Source/Pose.cpp | 519 +++++------ Gems/EMotionFX/Code/EMotionFX/Source/Pose.h | 54 +- .../Code/EMotionFX/Source/PoseDataRagdoll.cpp | 8 +- .../Code/EMotionFX/Source/RagdollInstance.cpp | 24 +- .../Code/EMotionFX/Source/Recorder.cpp | 570 ++++++------ .../Code/EMotionFX/Source/Recorder.h | 286 +++--- .../Source/RepositioningLayerPass.cpp | 10 +- .../EMotionFX/Source/RepositioningLayerPass.h | 4 +- .../Source/SingleThreadScheduler.cpp | 12 +- .../SkinningInfoVertexAttributeLayer.cpp | 30 +- .../Source/SkinningInfoVertexAttributeLayer.h | 38 +- .../EMotionFX/Source/SoftSkinDeformer.cpp | 56 +- .../Code/EMotionFX/Source/SoftSkinDeformer.h | 16 +- .../Code/EMotionFX/Source/SoftSkinManager.h | 2 - .../Code/EMotionFX/Source/SpringSolver.cpp | 36 +- .../EMotionFX/Source/StandardMaterial.cpp | 212 ++--- .../Code/EMotionFX/Source/StandardMaterial.h | 40 +- .../Code/EMotionFX/Source/SubMesh.cpp | 78 +- .../EMotionFX/Code/EMotionFX/Source/SubMesh.h | 28 +- .../Code/EMotionFX/Source/ThreadData.cpp | 8 +- .../Code/EMotionFX/Source/ThreadData.h | 14 +- .../Code/EMotionFX/Source/Transform.cpp | 290 +++--- .../Code/EMotionFX/Source/Transform.h | 6 +- .../Code/EMotionFX/Source/TransformData.cpp | 60 +- .../Code/EMotionFX/Source/TransformData.h | 30 +- .../EMotionFX/Source/VertexAttributeLayer.cpp | 14 +- .../EMotionFX/Source/VertexAttributeLayer.h | 10 +- .../VertexAttributeLayerAbstractData.cpp | 76 +- .../Source/VertexAttributeLayerAbstractData.h | 26 +- .../EMStudioSDK/Source/DockWidgetPlugin.cpp | 34 +- .../EMStudioSDK/Source/DockWidgetPlugin.h | 4 +- .../EMStudioSDK/Source/EMStudioManager.cpp | 108 +-- .../EMStudioSDK/Source/EMStudioManager.h | 60 +- .../EMStudioSDK/Source/EMStudioPlugin.h | 16 +- .../EMStudioSDK/Source/FileManager.cpp | 38 +- .../EMStudioSDK/Source/FileManager.h | 12 +- .../Source/KeyboardShortcutsWindow.cpp | 188 ++-- .../Source/KeyboardShortcutsWindow.h | 30 +- .../EMStudioSDK/Source/LayoutManager.cpp | 97 +- .../EMStudioSDK/Source/LayoutManager.h | 32 +- .../Source/LoadActorSettingsWindow.cpp | 166 ++-- .../Source/LoadActorSettingsWindow.h | 44 +- .../EMStudioSDK/Source/MainWindow.cpp | 552 ++++++------ .../EMStudioSDK/Source/MainWindow.h | 94 +- .../Source/MainWindowEventFilter.h | 4 +- .../Source/MorphTargetSelectionWindow.cpp | 50 +- .../Source/MorphTargetSelectionWindow.h | 8 +- .../Source/MotionEventPresetManager.cpp | 60 +- .../Source/MotionEventPresetManager.h | 22 +- .../Source/MotionSetHierarchyWidget.cpp | 96 +- .../Source/MotionSetHierarchyWidget.h | 20 +- .../Source/MotionSetSelectionWindow.cpp | 32 +- .../Source/MotionSetSelectionWindow.h | 12 +- .../Source/NodeHierarchyWidget.cpp | 153 ++-- .../EMStudioSDK/Source/NodeHierarchyWidget.h | 44 +- .../Source/NodeSelectionWindow.cpp | 26 +- .../EMStudioSDK/Source/NodeSelectionWindow.h | 22 +- .../EMStudioSDK/Source/NotificationWindow.cpp | 56 +- .../EMStudioSDK/Source/NotificationWindow.h | 8 +- .../Source/NotificationWindowManager.cpp | 14 +- .../Source/NotificationWindowManager.h | 14 +- .../EMStudioSDK/Source/PluginManager.cpp | 46 +- .../EMStudioSDK/Source/PluginManager.h | 14 +- .../EMStudioSDK/Source/RecoverFilesWindow.cpp | 68 +- .../EMStudioSDK/Source/RecoverFilesWindow.h | 4 +- .../Source/RemovePluginOnCloseDockWidget.cpp | 4 +- .../Source/RemovePluginOnCloseDockWidget.h | 2 +- .../RenderPlugin/ManipulatorCallbacks.cpp | 54 +- .../Source/RenderPlugin/RenderOptions.cpp | 14 +- .../Source/RenderPlugin/RenderOptions.h | 4 +- .../Source/RenderPlugin/RenderPlugin.cpp | 385 ++++---- .../Source/RenderPlugin/RenderPlugin.h | 98 +- .../RenderPlugin/RenderUpdateCallback.cpp | 72 +- .../RenderPlugin/RenderUpdateCallback.h | 4 +- .../Source/RenderPlugin/RenderViewWidget.cpp | 104 +-- .../Source/RenderPlugin/RenderViewWidget.h | 42 +- .../Source/RenderPlugin/RenderWidget.cpp | 440 +++++---- .../Source/RenderPlugin/RenderWidget.h | 100 +- .../Source/SaveChangedFilesManager.cpp | 117 ++- .../Source/SaveChangedFilesManager.h | 32 +- .../EMStudioSDK/Source/ToolBarPlugin.cpp | 36 +- .../EMStudioSDK/Source/ToolBarPlugin.h | 4 +- .../EMStudioSDK/Source/UnitScaleWindow.cpp | 28 +- .../EMStudioSDK/Source/UnitScaleWindow.h | 10 +- .../EMStudioSDK/Source/Workspace.cpp | 24 +- .../EMStudioSDK/Source/Workspace.h | 10 +- .../Source/OpenGLRender/GLWidget.cpp | 106 +-- .../Source/OpenGLRender/GLWidget.h | 12 +- .../OpenGLRender/OpenGLRenderPlugin.cpp | 12 +- .../Source/OpenGLRender/OpenGLRenderPlugin.h | 4 +- .../ActionHistory/ActionHistoryCallback.cpp | 96 +- .../ActionHistory/ActionHistoryCallback.h | 16 +- .../ActionHistory/ActionHistoryPlugin.cpp | 46 +- .../ActionHistory/ActionHistoryPlugin.h | 4 +- .../AnimGraph/AnimGraphActionManager.cpp | 4 +- .../Source/AnimGraph/AnimGraphEditor.cpp | 12 +- .../Source/AnimGraph/AnimGraphEditor.h | 4 +- .../AnimGraph/AnimGraphHierarchyWidget.h | 8 +- .../AnimGraph/AnimGraphModelCallbacks.cpp | 18 +- .../Source/AnimGraph/AnimGraphPlugin.cpp | 323 ++++--- .../Source/AnimGraph/AnimGraphPlugin.h | 98 +- .../Source/AnimGraph/AnimGraphVisualNode.cpp | 74 +- .../Source/AnimGraph/AnimGraphVisualNode.h | 12 +- .../Source/AnimGraph/AttributesWindow.cpp | 80 +- .../Source/AnimGraph/AttributesWindow.h | 18 +- .../Source/AnimGraph/BlendGraphViewWidget.cpp | 6 +- .../Source/AnimGraph/BlendGraphViewWidget.h | 2 +- .../Source/AnimGraph/BlendGraphWidget.cpp | 98 +- .../Source/AnimGraph/BlendGraphWidget.h | 6 +- .../AnimGraph/BlendNodeSelectionWindow.cpp | 26 +- .../AnimGraph/BlendNodeSelectionWindow.h | 16 +- .../Source/AnimGraph/BlendTreeVisualNode.cpp | 153 ++-- .../Source/AnimGraph/ContextMenu.cpp | 6 +- .../Source/AnimGraph/GameController.cpp | 285 +++--- .../Source/AnimGraph/GameController.h | 76 +- .../Source/AnimGraph/GameControllerWindow.cpp | 560 ++++++------ .../Source/AnimGraph/GameControllerWindow.h | 82 +- .../Source/AnimGraph/GraphNode.cpp | 491 +++++----- .../Source/AnimGraph/GraphNode.h | 254 +++--- .../Source/AnimGraph/GraphWidgetCallback.h | 4 +- .../Source/AnimGraph/NodeConnection.cpp | 101 +-- .../Source/AnimGraph/NodeConnection.h | 86 +- .../Source/AnimGraph/NodeGraph.cpp | 292 +++--- .../Source/AnimGraph/NodeGraph.h | 140 +-- .../Source/AnimGraph/NodeGraphWidget.cpp | 579 ++++++------ .../Source/AnimGraph/NodeGraphWidget.h | 68 +- .../Source/AnimGraph/NodeGroupWindow.cpp | 231 +++-- .../Source/AnimGraph/NodeGroupWindow.h | 28 +- .../Source/AnimGraph/NodePaletteWidget.cpp | 90 +- .../Source/AnimGraph/NodePaletteWidget.h | 16 +- .../AnimGraph/ParameterCreateEditDialog.cpp | 4 +- .../AnimGraph/ParameterCreateEditDialog.h | 2 +- .../ParameterEditor/ColorParameterEditor.cpp | 2 +- .../AnimGraph/ParameterSelectionWindow.cpp | 26 +- .../AnimGraph/ParameterSelectionWindow.h | 20 +- .../Source/AnimGraph/ParameterWidget.cpp | 88 +- .../Source/AnimGraph/ParameterWidget.h | 14 +- .../Source/AnimGraph/ParameterWindow.cpp | 208 ++--- .../Source/AnimGraph/ParameterWindow.h | 34 +- .../AnimGraph/StateFilterSelectionWindow.cpp | 72 +- .../AnimGraph/StateFilterSelectionWindow.h | 20 +- .../Source/AnimGraph/StateGraphNode.cpp | 135 ++- .../Source/AnimGraph/StateGraphNode.h | 4 +- .../Attachments/AttachmentNodesWindow.cpp | 148 +-- .../Attachments/AttachmentNodesWindow.h | 16 +- .../AttachmentsHierarchyWindow.cpp | 40 +- .../Attachments/AttachmentsHierarchyWindow.h | 2 +- .../Source/Attachments/AttachmentsPlugin.cpp | 118 +-- .../Source/Attachments/AttachmentsPlugin.h | 30 +- .../Source/Attachments/AttachmentsWindow.cpp | 357 ++++---- .../Source/Attachments/AttachmentsWindow.h | 46 +- .../Source/CommandBar/CommandBarPlugin.cpp | 14 +- .../CommandBrowser/CommandBrowserPlugin.cpp | 280 ------ .../CommandBrowser/CommandBrowserPlugin.h | 59 -- .../Source/LogWindow/LogWindowCallback.cpp | 38 +- .../Source/LogWindow/LogWindowCallback.h | 10 +- .../Source/LogWindow/LogWindowPlugin.cpp | 30 +- .../Source/LogWindow/LogWindowPlugin.h | 4 +- .../MorphTargetEditWindow.cpp | 76 +- .../MorphTargetEditWindow.h | 12 +- .../MorphTargetGroupWidget.cpp | 168 ++-- .../MorphTargetGroupWidget.h | 22 +- .../MorphTargetsWindowPlugin.cpp | 70 +- .../MorphTargetsWindowPlugin.h | 14 +- .../PhonemeSelectionWindow.cpp | 212 ++--- .../PhonemeSelectionWindow.h | 44 +- .../MotionEvents/MotionEventPresetsWidget.cpp | 78 +- .../MotionEvents/MotionEventPresetsWidget.h | 6 +- .../MotionEvents/MotionEventsPlugin.cpp | 133 ++- .../Source/MotionEvents/MotionEventsPlugin.h | 30 +- .../MotionSetManagementWindow.cpp | 138 ++- .../MotionSetManagementWindow.h | 13 +- .../MotionSetsWindow/MotionSetWindow.cpp | 328 ++++--- .../Source/MotionSetsWindow/MotionSetWindow.h | 38 +- .../MotionSetsWindowPlugin.cpp | 137 ++- .../MotionSetsWindow/MotionSetsWindowPlugin.h | 27 +- .../MotionWindow/MotionExtractionWindow.cpp | 162 ++-- .../MotionWindow/MotionExtractionWindow.h | 28 +- .../Source/MotionWindow/MotionListWindow.cpp | 152 ++-- .../Source/MotionWindow/MotionListWindow.h | 14 +- .../MotionWindow/MotionRetargetingWindow.cpp | 37 +- .../MotionWindow/MotionRetargetingWindow.h | 11 +- .../MotionWindow/MotionWindowPlugin.cpp | 198 ++-- .../Source/MotionWindow/MotionWindowPlugin.h | 36 +- .../NodeGroups/NodeGroupManagementWidget.cpp | 231 +++-- .../NodeGroups/NodeGroupManagementWidget.h | 22 +- .../Source/NodeGroups/NodeGroupWidget.cpp | 174 ++-- .../Source/NodeGroups/NodeGroupWidget.h | 20 +- .../Source/NodeGroups/NodeGroupsPlugin.cpp | 112 +-- .../Source/NodeGroups/NodeGroupsPlugin.h | 22 +- .../Source/NodeWindow/NodeInfo.cpp | 10 +- .../Source/NodeWindow/NodeWindowPlugin.cpp | 54 +- .../Source/NodeWindow/NodeWindowPlugin.h | 8 +- .../SceneManager/ActorPropertiesWindow.cpp | 92 +- .../SceneManager/ActorPropertiesWindow.h | 12 +- .../Source/SceneManager/MirrorSetupWindow.cpp | 399 ++++---- .../Source/SceneManager/MirrorSetupWindow.h | 34 +- .../SceneManager/SceneManagerPlugin.cpp | 160 ++-- .../Source/SceneManager/SceneManagerPlugin.h | 34 +- .../Source/TimeView/PlaybackOptionsGroup.cpp | 14 +- .../Source/TimeView/TimeInfoWidget.cpp | 80 +- .../Source/TimeView/TimeInfoWidget.h | 28 +- .../Source/TimeView/TimeTrack.cpp | 80 +- .../Source/TimeView/TimeTrack.h | 74 +- .../Source/TimeView/TimeTrackElement.cpp | 120 +-- .../Source/TimeView/TimeTrackElement.h | 94 +- .../Source/TimeView/TimeViewPlugin.cpp | 615 ++++++------- .../Source/TimeView/TimeViewPlugin.h | 122 +-- .../Source/TimeView/TimeViewToolBar.cpp | 100 +- .../Source/TimeView/TimeViewToolBar.h | 2 +- .../Source/TimeView/TrackDataHeaderWidget.cpp | 334 ++++--- .../Source/TimeView/TrackDataHeaderWidget.h | 36 +- .../Source/TimeView/TrackDataWidget.cpp | 842 +++++++++-------- .../Source/TimeView/TrackDataWidget.h | 84 +- .../Source/TimeView/TrackHeaderWidget.cpp | 256 +++--- .../Source/TimeView/TrackHeaderWidget.h | 40 +- .../standardplugins_files.cmake | 2 - .../Source/MainWindowEventFilter_Windows.cpp | 2 +- Gems/EMotionFX/Code/MCore/Source/AABB.h | 94 +- .../Code/MCore/Source/AlignedArray.h | 256 +++--- Gems/EMotionFX/Code/MCore/Source/Array2D.h | 42 +- Gems/EMotionFX/Code/MCore/Source/Array2D.inl | 102 +-- .../EMotionFX/Code/MCore/Source/Attribute.cpp | 2 +- Gems/EMotionFX/Code/MCore/Source/Attribute.h | 4 +- .../Code/MCore/Source/AttributeBool.cpp | 6 +- .../Code/MCore/Source/AttributeBool.h | 18 +- .../Code/MCore/Source/AttributeColor.h | 20 +- .../Code/MCore/Source/AttributeFactory.cpp | 20 +- .../Code/MCore/Source/AttributeFactory.h | 6 +- .../Code/MCore/Source/AttributeFloat.cpp | 6 +- .../Code/MCore/Source/AttributeFloat.h | 18 +- .../Code/MCore/Source/AttributeInt32.cpp | 6 +- .../Code/MCore/Source/AttributeInt32.h | 18 +- .../Code/MCore/Source/AttributePointer.h | 14 +- .../Code/MCore/Source/AttributeQuaternion.h | 20 +- .../Code/MCore/Source/AttributeString.h | 26 +- .../Code/MCore/Source/AttributeVector2.h | 20 +- .../Code/MCore/Source/AttributeVector3.h | 20 +- .../Code/MCore/Source/AttributeVector4.h | 21 +- .../Code/MCore/Source/AzCoreConversions.h | 6 +- .../Code/MCore/Source/BoundingSphere.cpp | 36 +- .../Code/MCore/Source/BoundingSphere.h | 50 +- Gems/EMotionFX/Code/MCore/Source/Color.cpp | 2 +- Gems/EMotionFX/Code/MCore/Source/Color.h | 142 +-- Gems/EMotionFX/Code/MCore/Source/Command.cpp | 30 +- Gems/EMotionFX/Code/MCore/Source/Command.h | 30 +- .../Code/MCore/Source/CommandGroup.cpp | 66 +- .../Code/MCore/Source/CommandGroup.h | 16 +- .../Code/MCore/Source/CommandLine.cpp | 54 +- .../EMotionFX/Code/MCore/Source/CommandLine.h | 4 +- .../Code/MCore/Source/CommandSyntax.cpp | 52 +- .../Code/MCore/Source/CommandSyntax.h | 12 +- .../Code/MCore/Source/CompressedFloat.h | 2 +- .../Code/MCore/Source/CompressedFloat.inl | 10 +- .../Code/MCore/Source/CompressedQuaternion.h | 2 +- .../MCore/Source/CompressedQuaternion.inl | 40 +- .../Code/MCore/Source/CompressedVector.h | 8 +- .../Code/MCore/Source/CompressedVector.inl | 14 +- Gems/EMotionFX/Code/MCore/Source/DiskFile.cpp | 58 +- Gems/EMotionFX/Code/MCore/Source/DiskFile.h | 6 +- Gems/EMotionFX/Code/MCore/Source/Distance.cpp | 6 +- Gems/EMotionFX/Code/MCore/Source/Distance.h | 88 +- .../Code/MCore/Source/DualQuaternion.cpp | 60 +- .../Code/MCore/Source/DualQuaternion.h | 51 +- .../Code/MCore/Source/DualQuaternion.inl | 18 +- .../Code/MCore/Source/FileSystem.cpp | 8 +- Gems/EMotionFX/Code/MCore/Source/FileSystem.h | 2 +- .../Code/MCore/Source/IDGenerator.cpp | 4 +- .../EMotionFX/Code/MCore/Source/IDGenerator.h | 2 +- .../Code/MCore/Source/LogManager.cpp | 62 +- Gems/EMotionFX/Code/MCore/Source/LogManager.h | 14 +- .../Code/MCore/Source/MCoreCommandManager.cpp | 260 +++--- .../Code/MCore/Source/MCoreCommandManager.h | 30 +- .../Code/MCore/Source/MCoreSystem.cpp | 124 +-- .../EMotionFX/Code/MCore/Source/MCoreSystem.h | 56 +- Gems/EMotionFX/Code/MCore/Source/Matrix4.cpp | 44 +- Gems/EMotionFX/Code/MCore/Source/Matrix4.h | 6 +- Gems/EMotionFX/Code/MCore/Source/Matrix4.inl | 6 +- .../Code/MCore/Source/MemoryFile.cpp | 87 +- Gems/EMotionFX/Code/MCore/Source/MemoryFile.h | 24 +- .../Code/MCore/Source/MemoryObject.cpp | 16 +- .../Code/MCore/Source/MemoryObject.h | 2 +- .../Code/MCore/Source/MemoryTracker.cpp | 280 +++--- .../Code/MCore/Source/MemoryTracker.h | 54 +- .../Code/MCore/Source/MultiThreadManager.h | 92 +- Gems/EMotionFX/Code/MCore/Source/PlaneEq.h | 42 +- Gems/EMotionFX/Code/MCore/Source/PlaneEq.inl | 16 +- Gems/EMotionFX/Code/MCore/Source/Random.cpp | 128 +-- Gems/EMotionFX/Code/MCore/Source/Random.h | 32 +- Gems/EMotionFX/Code/MCore/Source/Ray.cpp | 60 +- Gems/EMotionFX/Code/MCore/Source/Ray.h | 32 +- Gems/EMotionFX/Code/MCore/Source/SmallArray.h | 129 ++- .../Code/MCore/Source/StringIdPool.cpp | 24 +- .../Code/MCore/Source/StringIdPool.h | 6 +- .../Code/MysticQt/Source/DialogStack.cpp | 236 ++--- .../Code/MysticQt/Source/DialogStack.h | 32 +- .../Code/MysticQt/Source/MysticQtManager.cpp | 22 +- .../Code/MysticQt/Source/MysticQtManager.h | 32 +- .../Code/MysticQt/Source/RecentFiles.cpp | 6 +- .../MCore/Source/DiskFile_FileOffsetType.cpp | 20 +- .../WinAPI/MCore/Source/DiskFile_WinAPI.cpp | 20 +- .../Source/Editor/ColliderContainerWidget.cpp | 6 +- .../Code/Source/Editor/ObjectEditor.cpp | 4 +- .../Code/Source/Editor/ObjectEditor.h | 2 +- .../Cloth/ClothJointInspectorPlugin.cpp | 4 +- .../HitDetectionJointInspectorPlugin.cpp | 4 +- .../Ragdoll/RagdollNodeInspectorPlugin.cpp | 16 +- .../SimulatedObjectSelectionWindow.cpp | 6 +- .../SimulatedObjectSelectionWindow.h | 2 +- .../SimulatedObject/SimulatedObjectWidget.cpp | 12 +- .../SkeletonOutlinerPlugin.cpp | 4 +- .../PropertyWidgets/ActorGoalNodeHandler.cpp | 2 +- .../PropertyWidgets/AnimGraphNodeHandler.cpp | 2 +- .../BlendNParamWeightsHandler.cpp | 6 +- .../PropertyWidgets/LODSceneGraphWidget.h | 2 +- .../Source/Integration/Assets/ActorAsset.cpp | 2 +- .../Integration/Components/ActorComponent.cpp | 28 +- .../Components/SimpleMotionComponent.cpp | 24 +- .../Integration/System/PipelineComponent.cpp | 12 +- .../Integration/System/PipelineComponent.h | 2 +- .../Integration/System/SystemComponent.cpp | 26 +- .../Code/Tests/AnimGraphDeferredInitTests.cpp | 2 +- .../Code/Tests/AnimGraphMotionNodeTests.cpp | 184 ++-- .../Tests/AnimGraphNodeEventFilterTests.cpp | 24 +- ...AnimGraphStateMachineInterruptionTests.cpp | 144 +-- .../Tests/AnimGraphStateMachineSyncTests.cpp | 16 +- .../Code/Tests/AnimGraphSyncTrackTests.cpp | 86 +- .../AnimGraphTransitionConditionTests.cpp | 48 +- .../Tests/BlendTreeFloatMath1NodeTests.cpp | 2 +- .../Code/Tests/BlendTreeFootIKNodeTests.cpp | 6 +- .../Code/Tests/BlendTreeMaskNodeTests.cpp | 4 +- .../Tests/BlendTreeMirrorPoseNodeTests.cpp | 36 +- .../Tests/BlendTreeMotionFrameNodeTests.cpp | 6 +- .../Tests/BlendTreeRotationLimitNodeTests.cpp | 8 +- .../Tests/BlendTreeRotationMath2NodeTests.cpp | 16 +- .../BlendTreeSimulatedObjectNodeTests.cpp | 6 +- .../Tests/BlendTreeTransformNodeTests.cpp | 4 +- .../Tests/BlendTreeTwoLinkIKNodeTests.cpp | 138 +-- .../Code/Tests/BoolLogicNodeTests.cpp | 6 +- ...DeletionAndRestoreBlendTreeConnections.cpp | 4 +- .../Code/Tests/EmotionFXMathLibTests.cpp | 10 +- .../Tests/Integration/PoseComparisonFixture.h | 10 +- .../Tests/Integration/PoseComparisonTests.cpp | 42 +- Gems/EMotionFX/Code/Tests/Matchers.h | 42 +- .../Code/Tests/MorphTargetRuntimeTests.cpp | 2 +- .../Code/Tests/MotionEventTrackTests.cpp | 40 +- .../Code/Tests/MotionExtractionBusTests.cpp | 2 +- .../Code/Tests/MotionExtractionTests.cpp | 58 +- .../Code/Tests/MotionLayerSystemTests.cpp | 28 +- .../Code/Tests/MultiThreadSchedulerTests.cpp | 8 +- .../Code/Tests/NonUniformMotionDataTests.cpp | 36 +- Gems/EMotionFX/Code/Tests/PoseTests.cpp | 46 +- Gems/EMotionFX/Code/Tests/Printers.cpp | 6 +- .../Code/Tests/RandomMotionSelectionTests.cpp | 4 +- .../Code/Tests/SimulatedObjectSetupTests.cpp | 8 +- .../Code/Tests/SyncingSystemTests.cpp | 32 +- .../Code/Tests/TestAssetCode/SimpleActors.cpp | 6 +- .../Code/Tests/TransformUnitTests.cpp | 142 +-- .../Code/Tests/UI/CanMorphManyShapes.cpp | 8 +- .../Code/Tests/UI/ModalPopupHandler.cpp | 4 +- .../Code/Tests/UI/ModalPopupHandler.h | 2 +- .../Code/Tests/UniformMotionDataTests.cpp | 36 +- .../ClothComponentMesh/ActorClothSkinning.cpp | 2 +- 649 files changed, 20161 insertions(+), 21889 deletions(-) delete mode 100644 Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/MaterialExport.cpp delete mode 100644 Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/MeshExport.cpp delete mode 100644 Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/SkinExport.cpp delete mode 100644 Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/CommandBrowser/CommandBrowserPlugin.cpp delete mode 100644 Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/CommandBrowser/CommandBrowserPlugin.h diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/ActorAsset.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/ActorAsset.cpp index ece2c2aca7..8d247eaf45 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/ActorAsset.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/ActorAsset.cpp @@ -562,8 +562,8 @@ namespace AZ for (size_t i = 0; i < numBoneTransforms; ++i) { MCore::DualQuaternion dualQuat = MCore::DualQuaternion::ConvertFromTransform(AZ::Transform::CreateFromMatrix3x4(skinningMatrices[i])); - dualQuat.mReal.StoreToFloat4(&boneTransforms[i * DualQuaternionSkinningFloatsPerBone]); - dualQuat.mDual.StoreToFloat4(&boneTransforms[i * DualQuaternionSkinningFloatsPerBone + 4]); + dualQuat.m_real.StoreToFloat4(&boneTransforms[i * DualQuaternionSkinningFloatsPerBone]); + dualQuat.m_dual.StoreToFloat4(&boneTransforms[i * DualQuaternionSkinningFloatsPerBone + 4]); } } } diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp index c8a09ddaf8..d5a48b900d 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp @@ -151,10 +151,10 @@ namespace AZ continue; } - const AZ::Vector3 parentPos = pose->GetWorldSpaceTransform(parentIndex).mPosition; + const AZ::Vector3 parentPos = pose->GetWorldSpaceTransform(parentIndex).m_position; m_auxVertices.emplace_back(parentPos); - const AZ::Vector3 bonePos = pose->GetWorldSpaceTransform(jointIndex).mPosition; + const AZ::Vector3 bonePos = pose->GetWorldSpaceTransform(jointIndex).m_position; m_auxVertices.emplace_back(bonePos); } @@ -615,7 +615,7 @@ namespace AZ { // Morph targets that don't deform any vertices (e.g. joint-based morph targets) are not registered in the render proxy. Skip adding their weights. const EMotionFX::MorphTargetStandard::DeformData* deformData = morphTargetStandard->GetDeformData(deformDataIndex); - if (deformData->mNumVerts > 0) + if (deformData->m_numVerts > 0) { float weight = morphTargetSetupInstance->GetWeight(); m_morphTargetWeights.push_back(weight); diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ActorCommands.cpp b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ActorCommands.cpp index 85d9c699e1..da5366f6cf 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ActorCommands.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ActorCommands.cpp @@ -57,7 +57,7 @@ namespace CommandSystem // Set motion extraction node. if (parameters.CheckIfHasParameter("motionExtractionNodeName")) { - mOldMotionExtractionNodeIndex = actor->GetMotionExtractionNodeIndex(); + m_oldMotionExtractionNodeIndex = actor->GetMotionExtractionNodeIndex(); AZStd::string motionExtractionNodeName; parameters.GetValue("motionExtractionNodeName", this, motionExtractionNodeName); @@ -91,7 +91,7 @@ namespace CommandSystem // Set retarget root node. if (parameters.CheckIfHasParameter("retargetRootNodeName")) { - mOldRetargetRootNodeIndex = actor->GetRetargetRootNodeIndex(); + m_oldRetargetRootNodeIndex = actor->GetRetargetRootNodeIndex(); AZStd::string retargetRootNodeName = parameters.GetValue("retargetRootNodeName", this); if (retargetRootNodeName.empty() || retargetRootNodeName == "$NULL$") @@ -108,7 +108,7 @@ namespace CommandSystem // Set actor name. if (parameters.CheckIfHasParameter("name")) { - mOldName = actor->GetName(); + m_oldName = actor->GetName(); AZStd::string actorName; parameters.GetValue("name", this, actorName); @@ -119,7 +119,7 @@ namespace CommandSystem if (parameters.CheckIfHasParameter("attachmentNodes")) { // Store old attachment nodes for undo. - mOldAttachmentNodes = ""; + m_oldAttachmentNodes = ""; const size_t numNodes = actor->GetNumNodes(); for (size_t i = 0; i < numNodes; ++i) { @@ -132,8 +132,8 @@ namespace CommandSystem // Check if the node has the attachment flag enabled and add it. if (node->GetIsAttachmentNode()) { - mOldAttachmentNodes += node->GetName(); - mOldAttachmentNodes += ";"; + m_oldAttachmentNodes += node->GetName(); + m_oldAttachmentNodes += ";"; } } @@ -198,7 +198,7 @@ namespace CommandSystem if (parameters.CheckIfHasParameter("nodesExcludedFromBounds")) { // Store old nodes for undo. - mOldExcludedFromBoundsNodes = ""; + m_oldExcludedFromBoundsNodes = ""; const size_t numNodes = actor->GetNumNodes(); for (size_t i = 0; i < numNodes; ++i) { @@ -211,8 +211,8 @@ namespace CommandSystem // Check if the node has the attachment flag enabled and add it. if (!node->GetIncludeInBoundsCalc()) { - mOldExcludedFromBoundsNodes += node->GetName(); - mOldExcludedFromBoundsNodes += ";"; + m_oldExcludedFromBoundsNodes += node->GetName(); + m_oldExcludedFromBoundsNodes += ";"; } } @@ -276,7 +276,7 @@ namespace CommandSystem // Adjust the mirror setup. if (parameters.CheckIfHasParameter("mirrorSetup")) { - mOldMirrorSetup = actor->GetNodeMirrorInfos(); + m_oldMirrorSetup = actor->GetNodeMirrorInfos(); AZStd::string mirrorSetupString; parameters.GetValue("mirrorSetup", this, mirrorSetupString); @@ -308,8 +308,8 @@ namespace CommandSystem EMotionFX::Node* nodeB = actor->GetSkeleton()->FindNodeByName(pairValues[1]); if (nodeA && nodeB) { - actor->GetNodeMirrorInfo(nodeA->GetNodeIndex()).mSourceNode = static_cast(nodeB->GetNodeIndex()); - actor->GetNodeMirrorInfo(nodeB->GetNodeIndex()).mSourceNode = static_cast(nodeA->GetNodeIndex()); + actor->GetNodeMirrorInfo(nodeA->GetNodeIndex()).m_sourceNode = static_cast(nodeB->GetNodeIndex()); + actor->GetNodeMirrorInfo(nodeB->GetNodeIndex()).m_sourceNode = static_cast(nodeA->GetNodeIndex()); } } @@ -318,7 +318,7 @@ namespace CommandSystem } } - mOldDirtyFlag = actor->GetDirtyFlag(); + m_oldDirtyFlag = actor->GetDirtyFlag(); actor->SetDirtyFlag(true); return true; } @@ -338,29 +338,29 @@ namespace CommandSystem if (parameters.CheckIfHasParameter("motionExtractionNodeName")) { - actor->SetMotionExtractionNodeIndex(mOldMotionExtractionNodeIndex); + actor->SetMotionExtractionNodeIndex(m_oldMotionExtractionNodeIndex); } if (parameters.CheckIfHasParameter("retargetRootNodeName")) { - actor->SetRetargetRootNodeIndex(mOldRetargetRootNodeIndex); + actor->SetRetargetRootNodeIndex(m_oldRetargetRootNodeIndex); } if (parameters.CheckIfHasParameter("name")) { - actor->SetName(mOldName.c_str()); + actor->SetName(m_oldName.c_str()); } if (parameters.CheckIfHasParameter("mirrorSetup")) { - actor->SetNodeMirrorInfos(mOldMirrorSetup); + actor->SetNodeMirrorInfos(m_oldMirrorSetup); actor->AutoDetectMirrorAxes(); } // Set the attachment nodes. if (parameters.CheckIfHasParameter("attachmentNodes")) { - const AZStd::string command = AZStd::string::format("AdjustActor -actorID %i -nodeAction \"select\" -attachmentNodes \"%s\"", actorID, mOldAttachmentNodes.c_str()); + const AZStd::string command = AZStd::string::format("AdjustActor -actorID %i -nodeAction \"select\" -attachmentNodes \"%s\"", actorID, m_oldAttachmentNodes.c_str()); if (!GetCommandManager()->ExecuteCommandInsideCommand(command, outResult)) { @@ -372,7 +372,7 @@ namespace CommandSystem // Set the nodes that are not taken into account in the bounding volume calculations. if (parameters.CheckIfHasParameter("nodesExcludedFromBounds")) { - const AZStd::string command = AZStd::string::format("AdjustActor -actorID %i -nodeAction \"select\" -nodesExcludedFromBounds \"%s\"", actorID, mOldExcludedFromBoundsNodes.c_str()); + const AZStd::string command = AZStd::string::format("AdjustActor -actorID %i -nodeAction \"select\" -nodesExcludedFromBounds \"%s\"", actorID, m_oldExcludedFromBoundsNodes.c_str()); if (!GetCommandManager()->ExecuteCommandInsideCommand(command, outResult)) { @@ -382,7 +382,7 @@ namespace CommandSystem } // Set the dirty flag back to the old value. - actor->SetDirtyFlag(mOldDirtyFlag); + actor->SetDirtyFlag(m_oldDirtyFlag); return true; } @@ -479,18 +479,18 @@ namespace CommandSystem EMotionFX::Skeleton* skeleton = actor->GetSkeleton(); // Store the old nodes for the undo. - mOldNodeList = ""; + m_oldNodeList = ""; for (size_t i = 0; i < numNodes; ++i) { EMotionFX::Mesh* mesh = actor->GetMesh(lod, i); if (mesh && mesh->GetIsCollisionMesh()) { - if (!mOldNodeList.empty()) + if (!m_oldNodeList.empty()) { - mOldNodeList += ";"; + m_oldNodeList += ";"; } - mOldNodeList += skeleton->GetNode(i)->GetName(); + m_oldNodeList += skeleton->GetNode(i)->GetName(); } } @@ -517,7 +517,7 @@ namespace CommandSystem } // Save the current dirty flag and tell the actor that something changed. - mOldDirtyFlag = actor->GetDirtyFlag(); + m_oldDirtyFlag = actor->GetDirtyFlag(); actor->SetDirtyFlag(true); // Reinit the renderable actors. @@ -542,11 +542,11 @@ namespace CommandSystem const uint32 lod = parameters.GetValueAsInt("lod", MCORE_INVALIDINDEX32); // Undo command. - const AZStd::string command = AZStd::string::format("ActorSetCollisionMeshes -actorID %i -lod %i -nodeList %s", actorID, lod, mOldNodeList.c_str()); + const AZStd::string command = AZStd::string::format("ActorSetCollisionMeshes -actorID %i -lod %i -nodeList %s", actorID, lod, m_oldNodeList.c_str()); GetCommandManager()->ExecuteCommandInsideCommand(command, outResult); // Set the dirty flag back to the old value - actor->SetDirtyFlag(mOldDirtyFlag); + actor->SetDirtyFlag(m_oldDirtyFlag); return true; } @@ -686,7 +686,7 @@ namespace CommandSystem CommandRemoveActor::CommandRemoveActor(MCore::Command* orgCommand) : MCore::Command("RemoveActor", orgCommand) { - mPreviouslyUsedID = MCORE_INVALIDINDEX32; + m_previouslyUsedId = MCORE_INVALIDINDEX32; } @@ -725,10 +725,10 @@ namespace CommandSystem } // store the previously used id and the actor filename - mPreviouslyUsedID = actor->GetID(); - mOldFileName = actor->GetFileName(); - mOldDirtyFlag = actor->GetDirtyFlag(); - mOldWorkspaceDirtyFlag = GetCommandManager()->GetWorkspaceDirtyFlag(); + m_previouslyUsedId = actor->GetID(); + m_oldFileName = actor->GetFileName(); + m_oldDirtyFlag = actor->GetDirtyFlag(); + m_oldWorkspaceDirtyFlag = GetCommandManager()->GetWorkspaceDirtyFlag(); // get rid of the actor EMotionFX::GetActorManager().UnregisterActor(EMotionFX::GetActorManager().FindSharedActorByID(actor->GetID())); @@ -747,7 +747,7 @@ namespace CommandSystem { MCORE_UNUSED(parameters); - const AZStd::string command = AZStd::string::format("ImportActor -filename \"%s\" -actorID %i", mOldFileName.c_str(), mPreviouslyUsedID); + const AZStd::string command = AZStd::string::format("ImportActor -filename \"%s\" -actorID %i", m_oldFileName.c_str(), m_previouslyUsedId); if (!GetCommandManager()->ExecuteCommandInsideCommand(command, outResult)) { return false; @@ -761,7 +761,7 @@ namespace CommandSystem } // restore the workspace dirty flag - GetCommandManager()->SetWorkspaceDirtyFlag(mOldWorkspaceDirtyFlag); + GetCommandManager()->SetWorkspaceDirtyFlag(m_oldWorkspaceDirtyFlag); return true; } @@ -973,10 +973,10 @@ namespace CommandSystem CommandScaleActorData::CommandScaleActorData(MCore::Command* orgCommand) : MCore::Command("ScaleActorData", orgCommand) { - mActorID = MCORE_INVALIDINDEX32; - mScaleFactor = 1.0f; - mOldActorDirtyFlag = false; - mUseUnitType = false; + m_actorId = MCORE_INVALIDINDEX32; + m_scaleFactor = 1.0f; + m_oldActorDirtyFlag = false; + m_useUnitType = false; } @@ -1020,32 +1020,32 @@ namespace CommandSystem return false; } - mActorID = actor->GetID(); - mScaleFactor = parameters.GetValueAsFloat("scaleFactor", this); + m_actorId = actor->GetID(); + m_scaleFactor = parameters.GetValueAsFloat("scaleFactor", this); AZStd::string targetUnitTypeString; parameters.GetValue("unitType", this, &targetUnitTypeString); - mUseUnitType = parameters.CheckIfHasParameter("unitType"); + m_useUnitType = parameters.CheckIfHasParameter("unitType"); MCore::Distance::EUnitType targetUnitType; bool stringConvertSuccess = MCore::Distance::StringToUnitType(targetUnitTypeString, &targetUnitType); - if (mUseUnitType && stringConvertSuccess == false) + if (m_useUnitType && stringConvertSuccess == false) { outResult = AZStd::string::format("The passed unitType '%s' is not a valid unit type.", targetUnitTypeString.c_str()); return false; } MCore::Distance::EUnitType beforeUnitType = actor->GetUnitType(); - mOldUnitType = MCore::Distance::UnitTypeToString(beforeUnitType); + m_oldUnitType = MCore::Distance::UnitTypeToString(beforeUnitType); - mOldActorDirtyFlag = actor->GetDirtyFlag(); + m_oldActorDirtyFlag = actor->GetDirtyFlag(); actor->SetDirtyFlag(true); // perform the scaling - if (mUseUnitType == false) + if (m_useUnitType == false) { - actor->Scale(mScaleFactor); + actor->Scale(m_scaleFactor); } else { @@ -1083,21 +1083,21 @@ namespace CommandSystem { MCORE_UNUSED(parameters); - if (!mUseUnitType) + if (!m_useUnitType) { - const AZStd::string command = AZStd::string::format("ScaleActorData -id %d -scaleFactor %.8f", mActorID, 1.0f / mScaleFactor); + const AZStd::string command = AZStd::string::format("ScaleActorData -id %d -scaleFactor %.8f", m_actorId, 1.0f / m_scaleFactor); GetCommandManager()->ExecuteCommandInsideCommand(command, outResult); } else { - const AZStd::string command = AZStd::string::format("ScaleActorData -id %d -unitType \"%s\"", mActorID, mOldUnitType.c_str()); + const AZStd::string command = AZStd::string::format("ScaleActorData -id %d -unitType \"%s\"", m_actorId, m_oldUnitType.c_str()); GetCommandManager()->ExecuteCommandInsideCommand(command, outResult); } - EMotionFX::Actor* actor = EMotionFX::GetActorManager().FindActorByID(mActorID); + EMotionFX::Actor* actor = EMotionFX::GetActorManager().FindActorByID(m_actorId); if (actor) { - actor->SetDirtyFlag(mOldActorDirtyFlag); + actor->SetDirtyFlag(m_oldActorDirtyFlag); } return true; diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ActorCommands.h b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ActorCommands.h index 94c6e0ff42..6495577de7 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ActorCommands.h +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ActorCommands.h @@ -19,14 +19,14 @@ namespace CommandSystem { // Adjust the given actor. MCORE_DEFINECOMMAND_START(CommandAdjustActor, "Adjust actor", true) - size_t mOldMotionExtractionNodeIndex; - size_t mOldRetargetRootNodeIndex; - size_t mOldTrajectoryNodeIndex; - AZStd::string mOldAttachmentNodes; - AZStd::string mOldExcludedFromBoundsNodes; - AZStd::string mOldName; - AZStd::vector mOldMirrorSetup; - bool mOldDirtyFlag; + size_t m_oldMotionExtractionNodeIndex; + size_t m_oldRetargetRootNodeIndex; + size_t m_oldTrajectoryNodeIndex; + AZStd::string m_oldAttachmentNodes; + AZStd::string m_oldExcludedFromBoundsNodes; + AZStd::string m_oldName; + AZStd::vector m_oldMirrorSetup; + bool m_oldDirtyFlag; void SetIsAttachmentNode(EMotionFX::Actor* actor, bool isAttachmentNode); void SetIsExcludedFromBoundsNode(EMotionFX::Actor* actor, bool excludedFromBounds); @@ -34,8 +34,8 @@ namespace CommandSystem // Set the collision meshes of the given actor. MCORE_DEFINECOMMAND_START(CommandActorSetCollisionMeshes, "Actor set collison meshes", true) - AZStd::string mOldNodeList; - bool mOldDirtyFlag; + AZStd::string m_oldNodeList; + bool m_oldDirtyFlag; MCORE_DEFINECOMMAND_END // Reset actor instance to bind pose. @@ -50,21 +50,21 @@ namespace CommandSystem // Remove actor. MCORE_DEFINECOMMAND_START(CommandRemoveActor, "Remove actor", true) public: - uint32 mPreviouslyUsedID; - AZStd::string mOldFileName; - bool mOldDirtyFlag; - bool mOldWorkspaceDirtyFlag; + uint32 m_previouslyUsedId; + AZStd::string m_oldFileName; + bool m_oldDirtyFlag; + bool m_oldWorkspaceDirtyFlag; MCORE_DEFINECOMMAND_END // Scale actor data. MCORE_DEFINECOMMAND_START(CommandScaleActorData, "Scale actor data", true) public: - AZStd::string mOldUnitType; - uint32 mActorID; - float mScaleFactor; - bool mOldActorDirtyFlag; - bool mUseUnitType; + AZStd::string m_oldUnitType; + uint32 m_actorId; + float m_scaleFactor; + bool m_oldActorDirtyFlag; + bool m_useUnitType; MCORE_DEFINECOMMAND_END ////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ActorInstanceCommands.cpp b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ActorInstanceCommands.cpp index 45603b298e..ba25318944 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ActorInstanceCommands.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ActorInstanceCommands.cpp @@ -25,7 +25,7 @@ namespace CommandSystem CommandCreateActorInstance::CommandCreateActorInstance(MCore::Command* orgCommand) : MCore::Command("CreateActorInstance", orgCommand) { - mPreviouslyUsedID = MCORE_INVALIDINDEX32; + m_previouslyUsedId = MCORE_INVALIDINDEX32; } @@ -109,15 +109,15 @@ namespace CommandSystem } // in case of redoing the command set the previously used id - if (mPreviouslyUsedID != MCORE_INVALIDINDEX32) + if (m_previouslyUsedId != MCORE_INVALIDINDEX32) { - newInstance->SetID(mPreviouslyUsedID); + newInstance->SetID(m_previouslyUsedId); } - mPreviouslyUsedID = newInstance->GetID(); + m_previouslyUsedId = newInstance->GetID(); // setup the position, rotation and scale - AZ::Vector3 newPos = newInstance->GetLocalSpaceTransform().mPosition; + AZ::Vector3 newPos = newInstance->GetLocalSpaceTransform().m_position; if (parameters.CheckIfHasParameter("xPos")) { newPos.SetX(parameters.GetValueAsFloat("xPos", this)); @@ -155,7 +155,7 @@ namespace CommandSystem } // mark the workspace as dirty - mOldWorkspaceDirtyFlag = GetCommandManager()->GetWorkspaceDirtyFlag(); + m_oldWorkspaceDirtyFlag = GetCommandManager()->GetWorkspaceDirtyFlag(); GetCommandManager()->SetWorkspaceDirtyFlag(true); // return the id of the newly created actor instance @@ -174,7 +174,7 @@ namespace CommandSystem uint32 actorInstanceID = parameters.GetValueAsInt("actorInstanceID", MCORE_INVALIDINDEX32); if (actorInstanceID == MCORE_INVALIDINDEX32) { - actorInstanceID = mPreviouslyUsedID; + actorInstanceID = m_previouslyUsedId; } // find the actor intance based on the given id @@ -202,7 +202,7 @@ namespace CommandSystem } // restore the workspace dirty flag - GetCommandManager()->SetWorkspaceDirtyFlag(mOldWorkspaceDirtyFlag); + GetCommandManager()->SetWorkspaceDirtyFlag(m_oldWorkspaceDirtyFlag); // get rid of the actor instance if (actorInstance) @@ -274,7 +274,7 @@ namespace CommandSystem if (parameters.CheckIfHasParameter("pos")) { AZ::Vector3 value = parameters.GetValueAsVector3("pos", this); - mOldPosition = actorInstance->GetLocalSpaceTransform().mPosition; + m_oldPosition = actorInstance->GetLocalSpaceTransform().m_position; actorInstance->SetLocalSpacePosition(value); } @@ -282,7 +282,7 @@ namespace CommandSystem if (parameters.CheckIfHasParameter("rot")) { AZ::Vector4 value = parameters.GetValueAsVector4("rot", this); - mOldRotation = actorInstance->GetLocalSpaceTransform().mRotation; + m_oldRotation = actorInstance->GetLocalSpaceTransform().m_rotation; actorInstance->SetLocalSpaceRotation(AZ::Quaternion(value.GetX(), value.GetY(), value.GetZ(), value.GetW())); } @@ -292,7 +292,7 @@ namespace CommandSystem if (parameters.CheckIfHasParameter("scale")) { AZ::Vector3 value = parameters.GetValueAsVector3("scale", this); - mOldScale = actorInstance->GetLocalSpaceTransform().mScale; + m_oldScale = actorInstance->GetLocalSpaceTransform().m_scale; actorInstance->SetLocalSpaceScale(value); } ) @@ -301,7 +301,7 @@ namespace CommandSystem if (parameters.CheckIfHasParameter("lodLevel")) { uint32 value = parameters.GetValueAsInt("lodLevel", this); - mOldLODLevel = actorInstance->GetLODLevel(); + m_oldLodLevel = actorInstance->GetLODLevel(); actorInstance->SetLODLevel(value); } @@ -309,7 +309,7 @@ namespace CommandSystem if (parameters.CheckIfHasParameter("isVisible")) { bool value = parameters.GetValueAsBool("isVisible", this); - mOldIsVisible = actorInstance->GetIsVisible(); + m_oldIsVisible = actorInstance->GetIsVisible(); actorInstance->SetIsVisible(value); } @@ -317,12 +317,12 @@ namespace CommandSystem if (parameters.CheckIfHasParameter("doRender")) { bool value = parameters.GetValueAsBool("doRender", this); - mOldDoRender = actorInstance->GetRender(); + m_oldDoRender = actorInstance->GetRender(); actorInstance->SetRender(value); } // mark the workspace as dirty - mOldWorkspaceDirtyFlag = GetCommandManager()->GetWorkspaceDirtyFlag(); + m_oldWorkspaceDirtyFlag = GetCommandManager()->GetWorkspaceDirtyFlag(); GetCommandManager()->SetWorkspaceDirtyFlag(true); return true; @@ -345,13 +345,13 @@ namespace CommandSystem // set the position if (parameters.CheckIfHasParameter("pos")) { - actorInstance->SetLocalSpacePosition(mOldPosition); + actorInstance->SetLocalSpacePosition(m_oldPosition); } // set the rotation if (parameters.CheckIfHasParameter("rot")) { - actorInstance->SetLocalSpaceRotation(mOldRotation); + actorInstance->SetLocalSpaceRotation(m_oldRotation); } // set the scale @@ -359,30 +359,30 @@ namespace CommandSystem ( if (parameters.CheckIfHasParameter("scale")) { - actorInstance->SetLocalSpaceScale(mOldScale); + actorInstance->SetLocalSpaceScale(m_oldScale); } ) // set the LOD level if (parameters.CheckIfHasParameter("lodLevel")) { - actorInstance->SetLODLevel(mOldLODLevel); + actorInstance->SetLODLevel(m_oldLodLevel); } // set the visibility flag if (parameters.CheckIfHasParameter("isVisible")) { - actorInstance->SetIsVisible(mOldIsVisible); + actorInstance->SetIsVisible(m_oldIsVisible); } // set the rendering flag if (parameters.CheckIfHasParameter("doRender")) { - actorInstance->SetRender(mOldDoRender); + actorInstance->SetRender(m_oldDoRender); } // restore the workspace dirty flag - GetCommandManager()->SetWorkspaceDirtyFlag(mOldWorkspaceDirtyFlag); + GetCommandManager()->SetWorkspaceDirtyFlag(m_oldWorkspaceDirtyFlag); return true; } @@ -440,15 +440,15 @@ namespace CommandSystem } // store the old values before removing the instance - mOldPosition = actorInstance->GetLocalSpaceTransform().mPosition; - mOldRotation = actorInstance->GetLocalSpaceTransform().mRotation; + m_oldPosition = actorInstance->GetLocalSpaceTransform().m_position; + m_oldRotation = actorInstance->GetLocalSpaceTransform().m_rotation; EMFX_SCALECODE ( - mOldScale = actorInstance->GetLocalSpaceTransform().mScale; + m_oldScale = actorInstance->GetLocalSpaceTransform().m_scale; ) - mOldLODLevel = actorInstance->GetLODLevel(); - mOldIsVisible = actorInstance->GetIsVisible(); - mOldDoRender = actorInstance->GetRender(); + m_oldLodLevel = actorInstance->GetLODLevel(); + m_oldIsVisible = actorInstance->GetIsVisible(); + m_oldDoRender = actorInstance->GetRender(); // remove the actor instance from the selection if (GetCommandManager()->GetLockSelection()) @@ -458,7 +458,7 @@ namespace CommandSystem // get the id from the corresponding actor and save it for undo EMotionFX::Actor* actor = actorInstance->GetActor(); - mOldActorID = actor->GetID(); + m_oldActorId = actor->GetID(); // get rid of the actor instance if (actorInstance) @@ -467,7 +467,7 @@ namespace CommandSystem } // mark the workspace as dirty - mOldWorkspaceDirtyFlag = GetCommandManager()->GetWorkspaceDirtyFlag(); + m_oldWorkspaceDirtyFlag = GetCommandManager()->GetWorkspaceDirtyFlag(); GetCommandManager()->SetWorkspaceDirtyFlag(true); return true; @@ -489,17 +489,17 @@ namespace CommandSystem AZStd::string commandString; MCore::CommandGroup commandGroup("Undo remove actor instance", 2); - commandString = AZStd::string::format("CreateActorInstance -actorID %i -actorInstanceID %i", mOldActorID, actorInstanceID); + commandString = AZStd::string::format("CreateActorInstance -actorID %i -actorInstanceID %i", m_oldActorId, actorInstanceID); commandGroup.AddCommandString(commandString.c_str()); commandString = AZStd::string::format("AdjustActorInstance -actorInstanceID %i -pos \"%s\" -rot \"%s\" -scale \"%s\" -lodLevel %zu -isVisible \"%s\" -doRender \"%s\"", actorInstanceID, - AZStd::to_string(mOldPosition).c_str(), - AZStd::to_string(mOldRotation).c_str(), - AZStd::to_string(mOldScale).c_str(), - mOldLODLevel, - AZStd::to_string(mOldIsVisible).c_str(), - AZStd::to_string(mOldDoRender).c_str() + AZStd::to_string(m_oldPosition).c_str(), + AZStd::to_string(m_oldRotation).c_str(), + AZStd::to_string(m_oldScale).c_str(), + m_oldLodLevel, + AZStd::to_string(m_oldIsVisible).c_str(), + AZStd::to_string(m_oldDoRender).c_str() ); commandGroup.AddCommandString(commandString); @@ -507,7 +507,7 @@ namespace CommandSystem bool result = GetCommandManager()->ExecuteCommandGroupInsideCommand(commandGroup, outResult); // restore the workspace dirty flag - GetCommandManager()->SetWorkspaceDirtyFlag(mOldWorkspaceDirtyFlag); + GetCommandManager()->SetWorkspaceDirtyFlag(m_oldWorkspaceDirtyFlag); return result; } @@ -538,10 +538,10 @@ namespace CommandSystem return; } - const AZ::Vector3& pos = actorInstance->GetLocalSpaceTransform().mPosition; - const AZ::Quaternion& rot = actorInstance->GetLocalSpaceTransform().mRotation; + const AZ::Vector3& pos = actorInstance->GetLocalSpaceTransform().m_position; + const AZ::Quaternion& rot = actorInstance->GetLocalSpaceTransform().m_rotation; #ifndef EMFX_SCALE_DISABLED - const AZ::Vector3& scale = actorInstance->GetLocalSpaceTransform().mScale; + const AZ::Vector3& scale = actorInstance->GetLocalSpaceTransform().m_scale; #else const AZ::Vector3 scale = AZ::Vector3::CreateOne(); #endif diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ActorInstanceCommands.h b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ActorInstanceCommands.h index 69509822fe..604d88d037 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ActorInstanceCommands.h +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ActorInstanceCommands.h @@ -20,34 +20,34 @@ namespace CommandSystem // create a new actor instance MCORE_DEFINECOMMAND_START(CommandCreateActorInstance, "Create actor instance", true) public: - uint32 mPreviouslyUsedID; - bool mOldWorkspaceDirtyFlag; + uint32 m_previouslyUsedId; + bool m_oldWorkspaceDirtyFlag; MCORE_DEFINECOMMAND_END // adjust a given actor instance MCORE_DEFINECOMMAND_START(CommandAdjustActorInstance, "Adjust actor instance", true) public: - AZ::Vector3 mOldPosition; - AZ::Quaternion mOldRotation; - AZ::Vector3 mOldScale; - size_t mOldLODLevel; - bool mOldIsVisible; - bool mOldDoRender; - bool mOldWorkspaceDirtyFlag; + AZ::Vector3 m_oldPosition; + AZ::Quaternion m_oldRotation; + AZ::Vector3 m_oldScale; + size_t m_oldLodLevel; + bool m_oldIsVisible; + bool m_oldDoRender; + bool m_oldWorkspaceDirtyFlag; MCORE_DEFINECOMMAND_END // remove an actor instance MCORE_DEFINECOMMAND_START(CommandRemoveActorInstance, "Remove actor instance", true) - uint32 mOldActorID; - AZ::Vector3 mOldPosition; - AZ::Quaternion mOldRotation; - AZ::Vector3 mOldScale; - size_t mOldLODLevel; - bool mOldIsVisible; - bool mOldDoRender; - bool mOldWorkspaceDirtyFlag; + uint32 m_oldActorId; + AZ::Vector3 m_oldPosition; + AZ::Quaternion m_oldRotation; + AZ::Vector3 m_oldScale; + size_t m_oldLodLevel; + bool m_oldIsVisible; + bool m_oldDoRender; + bool m_oldWorkspaceDirtyFlag; MCORE_DEFINECOMMAND_END ////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphCommands.cpp b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphCommands.cpp index 1458107bcf..dbc25d7a60 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphCommands.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphCommands.cpp @@ -39,7 +39,7 @@ namespace CommandSystem CommandLoadAnimGraph::CommandLoadAnimGraph(MCore::Command* orgCommand) : MCore::Command("LoadAnimGraph", orgCommand) { - mOldAnimGraphID = MCORE_INVALIDINDEX32; + m_oldAnimGraphId = MCORE_INVALIDINDEX32; } @@ -107,11 +107,11 @@ namespace CommandSystem } // in case we are in a redo call assign the previously used id - if (mOldAnimGraphID != MCORE_INVALIDINDEX32) + if (m_oldAnimGraphId != MCORE_INVALIDINDEX32) { - animGraph->SetID(mOldAnimGraphID); + animGraph->SetID(m_oldAnimGraphId); } - mOldAnimGraphID = animGraph->GetID(); + m_oldAnimGraphId = animGraph->GetID(); animGraph->RecursiveInvalidateUniqueDatas(); @@ -126,7 +126,7 @@ namespace CommandSystem } // mark the workspace as dirty - mOldWorkspaceDirtyFlag = GetCommandManager()->GetWorkspaceDirtyFlag(); + m_oldWorkspaceDirtyFlag = GetCommandManager()->GetWorkspaceDirtyFlag(); GetCommandManager()->SetWorkspaceDirtyFlag(true); // automatically select the anim graph after loading it @@ -144,18 +144,18 @@ namespace CommandSystem MCORE_UNUSED(parameters); // get the anim graph the command created - EMotionFX::AnimGraph* animGraph = EMotionFX::GetAnimGraphManager().FindAnimGraphByID(mOldAnimGraphID); + EMotionFX::AnimGraph* animGraph = EMotionFX::GetAnimGraphManager().FindAnimGraphByID(m_oldAnimGraphId); if (animGraph == nullptr) { - outResult = AZStd::string::format("Cannot undo load anim graph command. Previously used anim graph id '%i' is not valid.", mOldAnimGraphID); + outResult = AZStd::string::format("Cannot undo load anim graph command. Previously used anim graph id '%i' is not valid.", m_oldAnimGraphId); return false; } // Remove the newly created anim graph. - const bool result = GetCommandManager()->ExecuteCommandInsideCommand(AZStd::string::format("RemoveAnimGraph -animGraphID %i", mOldAnimGraphID), outResult); + const bool result = GetCommandManager()->ExecuteCommandInsideCommand(AZStd::string::format("RemoveAnimGraph -animGraphID %i", m_oldAnimGraphId), outResult); // restore the workspace dirty flag - GetCommandManager()->SetWorkspaceDirtyFlag(mOldWorkspaceDirtyFlag); + GetCommandManager()->SetWorkspaceDirtyFlag(m_oldWorkspaceDirtyFlag); return result; } @@ -184,7 +184,7 @@ namespace CommandSystem CommandCreateAnimGraph::CommandCreateAnimGraph(MCore::Command* orgCommand) : MCore::Command("CreateAnimGraph", orgCommand) { - mPreviouslyUsedID = MCORE_INVALIDINDEX32; + m_previouslyUsedId = MCORE_INVALIDINDEX32; } @@ -221,11 +221,11 @@ namespace CommandSystem { animGraph->SetID(parameters.GetValueAsInt("animGraphID", this)); } - if (mPreviouslyUsedID != MCORE_INVALIDINDEX32) + if (m_previouslyUsedId != MCORE_INVALIDINDEX32) { - animGraph->SetID(mPreviouslyUsedID); + animGraph->SetID(m_previouslyUsedId); } - mPreviouslyUsedID = animGraph->GetID(); + m_previouslyUsedId = animGraph->GetID(); animGraph->RecursiveReinit(); animGraph->RecursiveInvalidateUniqueDatas(); @@ -238,7 +238,7 @@ namespace CommandSystem AZStd::to_string(outResult, animGraph->GetID()); // mark the workspace as dirty - mOldWorkspaceDirtyFlag = GetCommandManager()->GetWorkspaceDirtyFlag(); + m_oldWorkspaceDirtyFlag = GetCommandManager()->GetWorkspaceDirtyFlag(); GetCommandManager()->SetWorkspaceDirtyFlag(true); return true; @@ -251,18 +251,18 @@ namespace CommandSystem MCORE_UNUSED(parameters); // get the anim graph the command created - EMotionFX::AnimGraph* animGraph = EMotionFX::GetAnimGraphManager().FindAnimGraphByID(mPreviouslyUsedID); + EMotionFX::AnimGraph* animGraph = EMotionFX::GetAnimGraphManager().FindAnimGraphByID(m_previouslyUsedId); if (animGraph == nullptr) { - outResult = AZStd::string::format("Cannot undo create anim graph command. Previously used anim graph id '%i' is not valid.", mPreviouslyUsedID); + outResult = AZStd::string::format("Cannot undo create anim graph command. Previously used anim graph id '%i' is not valid.", m_previouslyUsedId); return false; } // remove the newly created anim graph again - const bool result = GetCommandManager()->ExecuteCommandInsideCommand(AZStd::string::format("RemoveAnimGraph -animGraphID %i", mPreviouslyUsedID), outResult); + const bool result = GetCommandManager()->ExecuteCommandInsideCommand(AZStd::string::format("RemoveAnimGraph -animGraphID %i", m_previouslyUsedId), outResult); // restore the workspace dirty flag - GetCommandManager()->SetWorkspaceDirtyFlag(mOldWorkspaceDirtyFlag); + GetCommandManager()->SetWorkspaceDirtyFlag(m_oldWorkspaceDirtyFlag); return result; } @@ -334,7 +334,7 @@ namespace CommandSystem if (someAnimGraphRemoved) { - mOldWorkspaceDirtyFlag = GetCommandManager()->GetWorkspaceDirtyFlag(); + m_oldWorkspaceDirtyFlag = GetCommandManager()->GetWorkspaceDirtyFlag(); GetCommandManager()->SetWorkspaceDirtyFlag(true); } @@ -388,7 +388,7 @@ namespace CommandSystem } // mark the workspace as dirty - mOldWorkspaceDirtyFlag = GetCommandManager()->GetWorkspaceDirtyFlag(); + m_oldWorkspaceDirtyFlag = GetCommandManager()->GetWorkspaceDirtyFlag(); GetCommandManager()->SetWorkspaceDirtyFlag(true); return true; @@ -414,7 +414,7 @@ namespace CommandSystem } // restore the workspace dirty flag - GetCommandManager()->SetWorkspaceDirtyFlag(mOldWorkspaceDirtyFlag); + GetCommandManager()->SetWorkspaceDirtyFlag(m_oldWorkspaceDirtyFlag); return result; } @@ -440,9 +440,9 @@ namespace CommandSystem CommandActivateAnimGraph::CommandActivateAnimGraph(MCore::Command* orgCommand) : MCore::Command(s_activateAnimGraphCmdName, orgCommand) { - mActorInstanceID = MCORE_INVALIDINDEX32; - mOldAnimGraphUsed = MCORE_INVALIDINDEX32; - mOldMotionSetUsed = MCORE_INVALIDINDEX32; + m_actorInstanceId = MCORE_INVALIDINDEX32; + m_oldAnimGraphUsed = MCORE_INVALIDINDEX32; + m_oldMotionSetUsed = MCORE_INVALIDINDEX32; } CommandActivateAnimGraph::~CommandActivateAnimGraph() @@ -509,7 +509,7 @@ namespace CommandSystem } // store the actor instance ID - mActorInstanceID = actorInstance->GetID(); + m_actorInstanceId = actorInstance->GetID(); // get the motion system from the actor instance EMotionFX::MotionSystem* motionSystem = actorInstance->GetMotionSystem(); @@ -533,9 +533,9 @@ namespace CommandSystem EMotionFX::MotionSet* animGraphInstanceMotionSet = animGraphInstance->GetMotionSet(); // store the currently used anim graph ID, motion set ID and the visualize scale - mOldAnimGraphUsed = animGraphInstanceAnimGraph->GetID(); - mOldMotionSetUsed = (animGraphInstanceMotionSet) ? animGraphInstanceMotionSet->GetID() : MCORE_INVALIDINDEX32; - mOldVisualizeScaleUsed = animGraphInstance->GetVisualizeScale(); + m_oldAnimGraphUsed = animGraphInstanceAnimGraph->GetID(); + m_oldMotionSetUsed = (animGraphInstanceMotionSet) ? animGraphInstanceMotionSet->GetID() : MCORE_INVALIDINDEX32; + m_oldVisualizeScaleUsed = animGraphInstance->GetVisualizeScale(); // check if the anim graph is valid if (animGraph) @@ -566,8 +566,8 @@ namespace CommandSystem else // no one anim graph instance set on the actor instance, create a new one { // store the currently used ID as invalid - mOldAnimGraphUsed = MCORE_INVALIDINDEX32; - mOldMotionSetUsed = MCORE_INVALIDINDEX32; + m_oldAnimGraphUsed = MCORE_INVALIDINDEX32; + m_oldMotionSetUsed = MCORE_INVALIDINDEX32; // check if the anim graph is valid if (animGraph) @@ -585,7 +585,7 @@ namespace CommandSystem AZStd::to_string(outResult, animGraph ? animGraph->GetID() : MCORE_INVALIDINDEX32); // mark the workspace as dirty - mOldWorkspaceDirtyFlag = GetCommandManager()->GetWorkspaceDirtyFlag(); + m_oldWorkspaceDirtyFlag = GetCommandManager()->GetWorkspaceDirtyFlag(); GetCommandManager()->SetWorkspaceDirtyFlag(true); AZStd::string resultString; @@ -598,12 +598,12 @@ namespace CommandSystem if (parameters.GetValueAsBool("startRecording", this)) { EMotionFX::Recorder::RecordSettings settings; - settings.mFPS = 1000000; - settings.mRecordTransforms = true; - settings.mRecordAnimGraphStates = true; - settings.mRecordNodeHistory = true; - settings.mRecordScale = true; - settings.mInitialAnimGraphAnimBytes = 4 * 1024 * 1024; // 4 mb + settings.m_fps = 1000000; + settings.m_recordTransforms = true; + settings.m_recordAnimGraphStates = true; + settings.m_recordNodeHistory = true; + settings.m_recordScale = true; + settings.m_initialAnimGraphAnimBytes = 4 * 1024 * 1024; // 4 mb EMotionFX::GetRecorder().StartRecording(settings); } @@ -616,41 +616,41 @@ namespace CommandSystem MCORE_UNUSED(parameters); // get the actor instance id and check if it is valid - EMotionFX::ActorInstance* actorInstance = EMotionFX::GetActorManager().FindActorInstanceByID(mActorInstanceID); + EMotionFX::ActorInstance* actorInstance = EMotionFX::GetActorManager().FindActorInstanceByID(m_actorInstanceId); if (actorInstance == nullptr) { - outResult = AZStd::string::format("Cannot undo activate anim graph. Actor instance id '%i' is not valid.", mActorInstanceID); + outResult = AZStd::string::format("Cannot undo activate anim graph. Actor instance id '%i' is not valid.", m_actorInstanceId); return false; } // get the anim graph, invalid index is a special case to allow the anim graph to be nullptr EMotionFX::AnimGraph* animGraph; - if (mOldAnimGraphUsed == MCORE_INVALIDINDEX32) + if (m_oldAnimGraphUsed == MCORE_INVALIDINDEX32) { animGraph = nullptr; } else { - animGraph = EMotionFX::GetAnimGraphManager().FindAnimGraphByID(mOldAnimGraphUsed); + animGraph = EMotionFX::GetAnimGraphManager().FindAnimGraphByID(m_oldAnimGraphUsed); if (animGraph == nullptr) { - outResult = AZStd::string::format("Cannot undo activate anim graph. Anim graph id '%i' is not valid.", mOldAnimGraphUsed); + outResult = AZStd::string::format("Cannot undo activate anim graph. Anim graph id '%i' is not valid.", m_oldAnimGraphUsed); return false; } } // get the motion set, invalid index is a special case to allow the motion set to be nullptr EMotionFX::MotionSet* motionSet; - if (mOldMotionSetUsed == MCORE_INVALIDINDEX32) + if (m_oldMotionSetUsed == MCORE_INVALIDINDEX32) { motionSet = nullptr; } else { - motionSet = EMotionFX::GetMotionManager().FindMotionSetByID(mOldMotionSetUsed); + motionSet = EMotionFX::GetMotionManager().FindMotionSetByID(m_oldMotionSetUsed); if (motionSet == nullptr) { - outResult = AZStd::string::format("Cannot undo activate anim graph. Motion set id '%i' is not valid.", mOldMotionSetUsed); + outResult = AZStd::string::format("Cannot undo activate anim graph. Motion set id '%i' is not valid.", m_oldMotionSetUsed); return false; } } @@ -683,7 +683,7 @@ namespace CommandSystem // create a new anim graph instance animGraphInstance = EMotionFX::AnimGraphInstance::Create(animGraph, actorInstance, motionSet); - animGraphInstance->SetVisualizeScale(mOldVisualizeScaleUsed); + animGraphInstance->SetVisualizeScale(m_oldVisualizeScaleUsed); actorInstance->SetAnimGraphInstance(animGraphInstance); animGraphInstance->RecursiveInvalidateUniqueDatas(); @@ -702,7 +702,7 @@ namespace CommandSystem { // create a new anim graph instance animGraphInstance = EMotionFX::AnimGraphInstance::Create(animGraph, actorInstance, motionSet); - animGraphInstance->SetVisualizeScale(mOldVisualizeScaleUsed); + animGraphInstance->SetVisualizeScale(m_oldVisualizeScaleUsed); actorInstance->SetAnimGraphInstance(animGraphInstance); animGraphInstance->RecursiveInvalidateUniqueDatas(); @@ -713,7 +713,7 @@ namespace CommandSystem AZStd::to_string(outResult, animGraph ? animGraph->GetID() : MCORE_INVALIDINDEX32); // restore the workspace dirty flag - GetCommandManager()->SetWorkspaceDirtyFlag(mOldWorkspaceDirtyFlag); + GetCommandManager()->SetWorkspaceDirtyFlag(m_oldWorkspaceDirtyFlag); AZStd::string resultString; GetCommandManager()->ExecuteCommandInsideCommand("Unselect -animGraphIndex SELECT_ALL", resultString); diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphCommands.h b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphCommands.h index 963e80fd8d..ae09420a29 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphCommands.h +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphCommands.h @@ -23,16 +23,16 @@ namespace CommandSystem public: using RelocateFilenameFunction = AZStd::function; RelocateFilenameFunction m_relocateFilenameFunction; - uint32 mOldAnimGraphID; - bool mOldWorkspaceDirtyFlag; + uint32 m_oldAnimGraphId; + bool m_oldWorkspaceDirtyFlag; MCORE_DEFINECOMMAND_END // create a new anim graph MCORE_DEFINECOMMAND_START(CommandCreateAnimGraph, "Create a anim graph", true) public: - uint32 mPreviouslyUsedID; - bool mOldWorkspaceDirtyFlag; + uint32 m_previouslyUsedId; + bool m_oldWorkspaceDirtyFlag; MCORE_DEFINECOMMAND_END @@ -40,18 +40,18 @@ public: MCORE_DEFINECOMMAND_START(CommandRemoveAnimGraph, "Remove a anim graph", true) public: AZStd::vector> m_oldFileNamesAndIds; - bool mOldWorkspaceDirtyFlag; + bool m_oldWorkspaceDirtyFlag; MCORE_DEFINECOMMAND_END // Activate the given anim graph. MCORE_DEFINECOMMAND_START(CommandActivateAnimGraph, "Activate a anim graph", true) public: - uint32 mActorInstanceID; - uint32 mOldAnimGraphUsed; - uint32 mOldMotionSetUsed; - float mOldVisualizeScaleUsed; - bool mOldWorkspaceDirtyFlag; + uint32 m_actorInstanceId; + uint32 m_oldAnimGraphUsed; + uint32 m_oldMotionSetUsed; + float m_oldVisualizeScaleUsed; + bool m_oldWorkspaceDirtyFlag; static const char* s_activateAnimGraphCmdName; MCORE_DEFINECOMMAND_END diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphConnectionCommands.cpp b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphConnectionCommands.cpp index 7707d8fa8b..b6a3870073 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphConnectionCommands.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphConnectionCommands.cpp @@ -63,7 +63,7 @@ namespace CommandSystem CommandAnimGraphCreateConnection::CommandAnimGraphCreateConnection(MCore::Command* orgCommand) : MCore::Command("AnimGraphCreateConnection", orgCommand) { - mTransitionType = AZ::TypeId::CreateNull(); + m_transitionType = AZ::TypeId::CreateNull(); } // destructor @@ -83,13 +83,13 @@ namespace CommandSystem } // store the anim graph id for undo - mAnimGraphID = animGraph->GetID(); + m_animGraphId = animGraph->GetID(); // get the transition type AZ::Outcome transitionTypeString = parameters.GetValueIfExists("transitionType", this); if (transitionTypeString.IsSuccess()) { - mTransitionType = AZ::TypeId::CreateString(transitionTypeString.GetValue().c_str()); + m_transitionType = AZ::TypeId::CreateString(transitionTypeString.GetValue().c_str()); } // get the node names @@ -116,18 +116,18 @@ namespace CommandSystem } // get the ports - mSourcePort = parameters.GetValueAsInt("sourcePort", 0); - mTargetPort = parameters.GetValueAsInt("targetPort", 0); - parameters.GetValue("sourcePortName", this, mSourcePortName); - parameters.GetValue("targetPortName", this, mTargetPortName); + m_sourcePort = parameters.GetValueAsInt("sourcePort", 0); + m_targetPort = parameters.GetValueAsInt("targetPort", 0); + parameters.GetValue("sourcePortName", this, m_sourcePortName); + parameters.GetValue("targetPortName", this, m_targetPortName); // in case the source port got specified by name, overwrite the source port number - if (!mSourcePortName.empty()) + if (!m_sourcePortName.empty()) { - mSourcePort = sourceNode->FindOutputPortIndex(mSourcePortName); + m_sourcePort = sourceNode->FindOutputPortIndex(m_sourcePortName); // in case we want to add this connection to a parameter node while the parameter name doesn't exist, still return true so that copy paste doesn't fail - if (azrtti_typeid(sourceNode) == azrtti_typeid() && mSourcePort == InvalidIndex) + if (azrtti_typeid(sourceNode) == azrtti_typeid() && m_sourcePort == InvalidIndex) { m_connectionId.SetInvalid(); return true; @@ -135,9 +135,9 @@ namespace CommandSystem } // in case the target port got specified by name, overwrite the target port number - if (!mTargetPortName.empty()) + if (!m_targetPortName.empty()) { - mTargetPort = targetNode->FindInputPortIndex(mTargetPortName.c_str()); + m_targetPort = targetNode->FindInputPortIndex(m_targetPortName.c_str()); } // get the parent of the source node @@ -157,27 +157,27 @@ namespace CommandSystem } // verify port ranges - if (mSourcePort >= sourceNode->GetOutputPorts().size()) + if (m_sourcePort >= sourceNode->GetOutputPorts().size()) { outResult = AZStd::string::format("The output port number is not valid for the given node. Node '%s' only has %zu output ports.", sourceNode->GetName(), sourceNode->GetOutputPorts().size()); return false; } - if (mTargetPort >= targetNode->GetInputPorts().size()) + if (m_targetPort >= targetNode->GetInputPorts().size()) { outResult = AZStd::string::format("The input port number is not valid for the given node. Node '%s' only has %zu input ports.", targetNode->GetName(), targetNode->GetInputPorts().size()); return false; } // check if connection already exists - if (targetNode->GetHasConnection(sourceNode, static_cast(mSourcePort), static_cast(mTargetPort))) + if (targetNode->GetHasConnection(sourceNode, static_cast(m_sourcePort), static_cast(m_targetPort))) { outResult = AZStd::string::format("The connection you are trying to create already exists!"); return false; } // create the connection and auto assign an id first of all - EMotionFX::BlendTreeConnection* connection = targetNode->AddConnection(sourceNode, static_cast(mSourcePort), static_cast(mTargetPort)); + EMotionFX::BlendTreeConnection* connection = targetNode->AddConnection(sourceNode, static_cast(m_sourcePort), static_cast(m_targetPort)); // Overwrite the connection id if specified by a command parameter. if (parameters.CheckIfHasParameter("id")) @@ -201,8 +201,8 @@ namespace CommandSystem if (azrtti_istypeof(targetNode)) { EMotionFX::BlendTreeBlendNNode* blendTreeBlendNNode = static_cast(targetNode); - mUpdateParamFlag = parameters.GetValueAsBool("updateParam", true); - if (mUpdateParamFlag) + m_updateParamFlag = parameters.GetValueAsBool("updateParam", true); + if (m_updateParamFlag) { blendTreeBlendNNode->UpdateParamWeights(); } @@ -214,17 +214,17 @@ namespace CommandSystem EMotionFX::AnimGraphStateMachine* machine = (EMotionFX::AnimGraphStateMachine*)targetNode->GetParentNode(); // try to create the anim graph node - EMotionFX::AnimGraphObject* object = EMotionFX::AnimGraphObjectFactory::Create(mTransitionType, animGraph); + EMotionFX::AnimGraphObject* object = EMotionFX::AnimGraphObjectFactory::Create(m_transitionType, animGraph); if (!object) { - outResult = AZStd::string::format("Cannot create transition of type %s", mTransitionType.ToString().c_str()); + outResult = AZStd::string::format("Cannot create transition of type %s", m_transitionType.ToString().c_str()); return false; } // check if this is really a transition if (!azrtti_istypeof(object)) { - outResult = AZStd::string::format("Cannot create state transition of type %s, because this object type is not inherited from AnimGraphStateTransition.", mTransitionType.ToString().c_str()); + outResult = AZStd::string::format("Cannot create state transition of type %s, because this object type is not inherited from AnimGraphStateTransition.", m_transitionType.ToString().c_str()); return false; } @@ -255,13 +255,13 @@ namespace CommandSystem transition->SetTargetNode(targetNode); // get the offsets - mStartOffsetX = parameters.GetValueAsInt("startOffsetX", 0); - mStartOffsetY = parameters.GetValueAsInt("startOffsetY", 0); - mEndOffsetX = parameters.GetValueAsInt("endOffsetX", 0); - mEndOffsetY = parameters.GetValueAsInt("endOffsetY", 0); + m_startOffsetX = parameters.GetValueAsInt("startOffsetX", 0); + m_startOffsetY = parameters.GetValueAsInt("startOffsetY", 0); + m_endOffsetX = parameters.GetValueAsInt("endOffsetX", 0); + m_endOffsetY = parameters.GetValueAsInt("endOffsetY", 0); if (parameters.CheckIfHasValue("startOffsetX") || parameters.CheckIfHasValue("startOffsetY") || parameters.CheckIfHasValue("endOffsetX") || parameters.CheckIfHasValue("endOffsetY")) { - transition->SetVisualOffsets(mStartOffsetX, mStartOffsetY, mEndOffsetX, mEndOffsetY); + transition->SetVisualOffsets(m_startOffsetX, m_startOffsetY, m_endOffsetX, m_endOffsetY); } transition->SetIsWildcardTransition(isWildcardTransition); @@ -290,19 +290,19 @@ namespace CommandSystem transition->Reinit(); } - mTargetNodeId.SetInvalid(); - mSourceNodeId.SetInvalid(); + m_targetNodeId.SetInvalid(); + m_sourceNodeId.SetInvalid(); if (targetNode) { - mTargetNodeId = targetNode->GetId(); + m_targetNodeId = targetNode->GetId(); } if (sourceNode) { - mSourceNodeId = sourceNode->GetId(); + m_sourceNodeId = sourceNode->GetId(); } // save the current dirty flag and tell the anim graph that something got changed - mOldDirtyFlag = animGraph->GetDirtyFlag(); + m_oldDirtyFlag = animGraph->GetDirtyFlag(); animGraph->SetDirtyFlag(true); // set the command result to the connection id @@ -319,16 +319,16 @@ namespace CommandSystem MCORE_UNUSED(parameters); // get the anim graph - EMotionFX::AnimGraph* animGraph = EMotionFX::GetAnimGraphManager().FindAnimGraphByID(mAnimGraphID); + EMotionFX::AnimGraph* animGraph = EMotionFX::GetAnimGraphManager().FindAnimGraphByID(m_animGraphId); if (animGraph == nullptr) { - outResult = AZStd::string::format("The anim graph with id '%i' does not exist anymore.", mAnimGraphID); + outResult = AZStd::string::format("The anim graph with id '%i' does not exist anymore.", m_animGraphId); return false; } // in case of a wildcard transition the source node is the invalid index, so that's all fine - EMotionFX::AnimGraphNode* sourceNode = animGraph->RecursiveFindNodeById(mSourceNodeId); - EMotionFX::AnimGraphNode* targetNode = animGraph->RecursiveFindNodeById(mTargetNodeId); + EMotionFX::AnimGraphNode* sourceNode = animGraph->RecursiveFindNodeById(m_sourceNodeId); + EMotionFX::AnimGraphNode* targetNode = animGraph->RecursiveFindNodeById(m_targetNodeId); // NOTE: When source node is a nullptr, we are dealing with a wildcard transition, so there a nullptr is allowed. if (!targetNode) @@ -348,9 +348,9 @@ namespace CommandSystem const AZStd::string commandString = AZStd::string::format("AnimGraphRemoveConnection -animGraphID %i -targetNode \"%s\" -targetPort %zu -sourceNode \"%s\" -sourcePort %zu -id %s", animGraph->GetID(), targetNode->GetName(), - mTargetPort, + m_targetPort, sourceNodeName.c_str(), - mSourcePort, + m_sourcePort, m_connectionId.ToString().c_str()); // execute the command without putting it in the history @@ -365,11 +365,11 @@ namespace CommandSystem } // reset the data used for undo and redo - mSourceNodeId.SetInvalid(); - mTargetNodeId.SetInvalid(); + m_sourceNodeId.SetInvalid(); + m_targetNodeId.SetInvalid(); // set the dirty flag back to the old value - animGraph->SetDirtyFlag(mOldDirtyFlag); + animGraph->SetDirtyFlag(m_oldDirtyFlag); return true; } @@ -414,13 +414,13 @@ namespace CommandSystem CommandAnimGraphRemoveConnection::CommandAnimGraphRemoveConnection(MCore::Command* orgCommand) : MCore::Command("AnimGraphRemoveConnection", orgCommand) { - mSourcePort = InvalidIndex; - mTargetPort = InvalidIndex; - mTransitionType = AZ::TypeId::CreateNull(); - mStartOffsetX = 0; - mStartOffsetY = 0; - mEndOffsetX = 0; - mEndOffsetY = 0; + m_sourcePort = InvalidIndex; + m_targetPort = InvalidIndex; + m_transitionType = AZ::TypeId::CreateNull(); + m_startOffsetX = 0; + m_startOffsetY = 0; + m_endOffsetX = 0; + m_endOffsetY = 0; } @@ -441,7 +441,7 @@ namespace CommandSystem } // store the anim graph id for undo - mAnimGraphID = animGraph->GetID(); + m_animGraphId = animGraph->GetID(); // get the node names AZStd::string sourceNodeName; @@ -466,19 +466,19 @@ namespace CommandSystem } // get the ids from the source and destination nodes - mSourceNodeId.SetInvalid(); - mSourceNodeName.clear(); + m_sourceNodeId.SetInvalid(); + m_sourceNodeName.clear(); if (sourceNode) { - mSourceNodeId = sourceNode->GetId(); - mSourceNodeName = sourceNode->GetName(); + m_sourceNodeId = sourceNode->GetId(); + m_sourceNodeName = sourceNode->GetName(); } - mTargetNodeId = targetNode->GetId(); - mTargetNodeName = targetNode->GetName(); + m_targetNodeId = targetNode->GetId(); + m_targetNodeName = targetNode->GetName(); // get the ports - mSourcePort = parameters.GetValueAsInt("sourcePort", 0); - mTargetPort = parameters.GetValueAsInt("targetPort", 0); + m_sourcePort = parameters.GetValueAsInt("sourcePort", 0); + m_targetPort = parameters.GetValueAsInt("targetPort", 0); // get the parent of the source node if (targetNode->GetParentNode() == nullptr) @@ -497,34 +497,34 @@ namespace CommandSystem } // verify port ranges - if (mSourcePort >= static_cast(sourceNode->GetOutputPorts().size()) || mSourcePort < 0) + if (m_sourcePort >= static_cast(sourceNode->GetOutputPorts().size()) || m_sourcePort < 0) { outResult = AZStd::string::format("The output port number is not valid for the given node. Node '%s' only has %zu output ports.", sourceNode->GetName(), sourceNode->GetOutputPorts().size()); return false; } - if (mTargetPort >= static_cast(targetNode->GetInputPorts().size()) || mTargetPort < 0) + if (m_targetPort >= static_cast(targetNode->GetInputPorts().size()) || m_targetPort < 0) { outResult = AZStd::string::format("The input port number is not valid for the given node. Node '%s' only has %zu input ports.", targetNode->GetName(), targetNode->GetInputPorts().size()); return false; } // check if connection already exists - if (!targetNode->GetHasConnection(sourceNode, static_cast(mSourcePort), static_cast(mTargetPort))) + if (!targetNode->GetHasConnection(sourceNode, static_cast(m_sourcePort), static_cast(m_targetPort))) { outResult = AZStd::string::format("The connection you are trying to remove doesn't exist!"); return false; } // get the connection ID and store it - EMotionFX::BlendTreeConnection* connection = targetNode->FindConnection(sourceNode, static_cast(mSourcePort), static_cast(mTargetPort)); + EMotionFX::BlendTreeConnection* connection = targetNode->FindConnection(sourceNode, static_cast(m_sourcePort), static_cast(m_targetPort)); if (connection) { m_connectionId = connection->GetId(); } // create the connection - targetNode->RemoveConnection(sourceNode, static_cast(mSourcePort), static_cast(mTargetPort)); + targetNode->RemoveConnection(sourceNode, static_cast(m_sourcePort), static_cast(m_targetPort)); if (azrtti_istypeof(targetNode)) { @@ -558,13 +558,13 @@ namespace CommandSystem // save the transition information for undo EMotionFX::AnimGraphStateTransition* transition = stateMachine->GetTransition(transitionIndex.GetValue()); - mStartOffsetX = transition->GetVisualStartOffsetX(); - mStartOffsetY = transition->GetVisualStartOffsetY(); - mEndOffsetX = transition->GetVisualEndOffsetX(); - mEndOffsetY = transition->GetVisualEndOffsetY(); - mTransitionType = azrtti_typeid(transition); + m_startOffsetX = transition->GetVisualStartOffsetX(); + m_startOffsetY = transition->GetVisualStartOffsetY(); + m_endOffsetX = transition->GetVisualEndOffsetX(); + m_endOffsetY = transition->GetVisualEndOffsetY(); + m_transitionType = azrtti_typeid(transition); m_connectionId = transition->GetId(); - mOldContents = MCore::ReflectionSerializer::Serialize(transition).GetValue(); + m_oldContents = MCore::ReflectionSerializer::Serialize(transition).GetValue(); // remove all unique datas for the transition itself animGraph->RemoveAllObjectData(transition, true); @@ -574,7 +574,7 @@ namespace CommandSystem } // save the current dirty flag and tell the anim graph that something got changed - mOldDirtyFlag = animGraph->GetDirtyFlag(); + m_oldDirtyFlag = animGraph->GetDirtyFlag(); animGraph->SetDirtyFlag(true); if(parameters.GetValueAsBool("updateUniqueData", true)) @@ -591,34 +591,34 @@ namespace CommandSystem const AZStd::string updateUniqueData = parameters.GetValue("updateUniqueData", this); // get the anim graph - EMotionFX::AnimGraph* animGraph = EMotionFX::GetAnimGraphManager().FindAnimGraphByID(mAnimGraphID); + EMotionFX::AnimGraph* animGraph = EMotionFX::GetAnimGraphManager().FindAnimGraphByID(m_animGraphId); if (animGraph == nullptr) { - outResult = AZStd::string::format("The anim graph with id '%i' does not exist anymore.", mAnimGraphID); + outResult = AZStd::string::format("The anim graph with id '%i' does not exist anymore.", m_animGraphId); return false; } - if (!mTargetNodeId.IsValid()) + if (!m_targetNodeId.IsValid()) { return false; } AZStd::string commandString = AZStd::string::format("AnimGraphCreateConnection -animGraphID %i -sourceNode \"%s\" -targetNode \"%s\" -sourcePort %zu -targetPort %zu -startOffsetX %d -startOffsetY %d -endOffsetX %d -endOffsetY %d -id %s -transitionType \"%s\" -updateUniqueData %s", animGraph->GetID(), - mSourceNodeName.c_str(), - mTargetNodeName.c_str(), - mSourcePort, - mTargetPort, - mStartOffsetX, mStartOffsetY, - mEndOffsetX, mEndOffsetY, + m_sourceNodeName.c_str(), + m_targetNodeName.c_str(), + m_sourcePort, + m_targetPort, + m_startOffsetX, m_startOffsetY, + m_endOffsetX, m_endOffsetY, m_connectionId.ToString().c_str(), - mTransitionType.ToString().c_str(), + m_transitionType.ToString().c_str(), updateUniqueData.c_str()); // add the old attributes - if (mOldContents.empty() == false) + if (m_oldContents.empty() == false) { - commandString += AZStd::string::format(" -contents {%s}", mOldContents.c_str()); + commandString += AZStd::string::format(" -contents {%s}", m_oldContents.c_str()); } if (!GetCommandManager()->ExecuteCommandInsideCommand(commandString, outResult)) @@ -631,18 +631,18 @@ namespace CommandSystem return false; } - mTargetNodeId.SetInvalid(); - mSourceNodeId.SetInvalid(); + m_targetNodeId.SetInvalid(); + m_sourceNodeId.SetInvalid(); m_connectionId.SetInvalid(); - mSourcePort = InvalidIndex; - mTargetPort = InvalidIndex; - mStartOffsetX = 0; - mStartOffsetY = 0; - mEndOffsetX = 0; - mEndOffsetY = 0; + m_sourcePort = InvalidIndex; + m_targetPort = InvalidIndex; + m_startOffsetX = 0; + m_startOffsetY = 0; + m_endOffsetX = 0; + m_endOffsetY = 0; // set the dirty flag back to the old value - animGraph->SetDirtyFlag(mOldDirtyFlag); + animGraph->SetDirtyFlag(m_oldDirtyFlag); return true; } @@ -839,7 +839,7 @@ namespace CommandSystem } // save the current dirty flag and tell the anim graph that something got changed - mOldDirtyFlag = animGraph->GetDirtyFlag(); + m_oldDirtyFlag = animGraph->GetDirtyFlag(); animGraph->SetDirtyFlag(true); transition->Reinit(); @@ -865,14 +865,14 @@ namespace CommandSystem } AdjustTransition(transition, - /*mOldDisabledFlag=*/AZStd::nullopt, - /*sourceNodeName=*/AZStd::nullopt, /*targetNodeName=*/AZStd::nullopt, + /*isDisabled=*/AZStd::nullopt, + /*sourceNode=*/AZStd::nullopt, /*targetNode=*/AZStd::nullopt, /*startOffsetX=*/AZStd::nullopt, /*startOffsetY=*/AZStd::nullopt, /*endOffsetX=*/AZStd::nullopt, /*endOffsetY=*/AZStd::nullopt, /*attributesString=*/AZStd::nullopt, /*serializedMembers=*/m_oldSerializedMembers.GetValue(), /*commandGroup*/nullptr, /*executeInsideCommand*/true); - animGraph->SetDirtyFlag(mOldDirtyFlag); + animGraph->SetDirtyFlag(m_oldDirtyFlag); return true; } diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphConnectionCommands.h b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphConnectionCommands.h index d0ef5549e0..2f0a03a191 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphConnectionCommands.h +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphConnectionCommands.h @@ -26,64 +26,64 @@ namespace CommandSystem { // create a connection MCORE_DEFINECOMMAND_START(CommandAnimGraphCreateConnection, "Connect two anim graph nodes", true) - uint32 mAnimGraphID; - EMotionFX::AnimGraphNodeId mTargetNodeId; - EMotionFX::AnimGraphNodeId mSourceNodeId; + uint32 m_animGraphId; + EMotionFX::AnimGraphNodeId m_targetNodeId; + EMotionFX::AnimGraphNodeId m_sourceNodeId; EMotionFX::AnimGraphConnectionId m_connectionId; - AZ::TypeId mTransitionType; - int32 mStartOffsetX; - int32 mStartOffsetY; - int32 mEndOffsetX; - int32 mEndOffsetY; - size_t mSourcePort; - size_t mTargetPort; - AZStd::string mSourcePortName; - AZStd::string mTargetPortName; - bool mOldDirtyFlag; - bool mUpdateParamFlag; + AZ::TypeId m_transitionType; + int32 m_startOffsetX; + int32 m_startOffsetY; + int32 m_endOffsetX; + int32 m_endOffsetY; + size_t m_sourcePort; + size_t m_targetPort; + AZStd::string m_sourcePortName; + AZStd::string m_targetPortName; + bool m_oldDirtyFlag; + bool m_updateParamFlag; public: EMotionFX::AnimGraphConnectionId GetConnectionId() const{ return m_connectionId; } - EMotionFX::AnimGraphNodeId GetTargetNodeId() const { return mTargetNodeId; } - EMotionFX::AnimGraphNodeId GetSourceNodeId() const { return mSourceNodeId; } - AZ::TypeId GetTransitionType() const { return mTransitionType; } - size_t GetSourcePort() const { return mSourcePort; } - size_t GetTargetPort() const { return mTargetPort; } - int32 GetStartOffsetX() const { return mStartOffsetX; } - int32 GetStartOffsetY() const { return mStartOffsetY; } - int32 GetEndOffsetX() const { return mEndOffsetX; } - int32 GetEndOffsetY() const { return mEndOffsetY; } + EMotionFX::AnimGraphNodeId GetTargetNodeId() const { return m_targetNodeId; } + EMotionFX::AnimGraphNodeId GetSourceNodeId() const { return m_sourceNodeId; } + AZ::TypeId GetTransitionType() const { return m_transitionType; } + size_t GetSourcePort() const { return m_sourcePort; } + size_t GetTargetPort() const { return m_targetPort; } + int32 GetStartOffsetX() const { return m_startOffsetX; } + int32 GetStartOffsetY() const { return m_startOffsetY; } + int32 GetEndOffsetX() const { return m_endOffsetX; } + int32 GetEndOffsetY() const { return m_endOffsetY; } MCORE_DEFINECOMMAND_END // remove a connection MCORE_DEFINECOMMAND_START(CommandAnimGraphRemoveConnection, "Remove a anim graph connection", true) - uint32 mAnimGraphID; - EMotionFX::AnimGraphNodeId mTargetNodeId; - AZStd::string mTargetNodeName; - EMotionFX::AnimGraphNodeId mSourceNodeId; - AZStd::string mSourceNodeName; + uint32 m_animGraphId; + EMotionFX::AnimGraphNodeId m_targetNodeId; + AZStd::string m_targetNodeName; + EMotionFX::AnimGraphNodeId m_sourceNodeId; + AZStd::string m_sourceNodeName; EMotionFX::AnimGraphConnectionId m_connectionId; - AZ::TypeId mTransitionType; - int32 mStartOffsetX; - int32 mStartOffsetY; - int32 mEndOffsetX; - int32 mEndOffsetY; - size_t mSourcePort; - size_t mTargetPort; - bool mOldDirtyFlag; - AZStd::string mOldContents; + AZ::TypeId m_transitionType; + int32 m_startOffsetX; + int32 m_startOffsetY; + int32 m_endOffsetX; + int32 m_endOffsetY; + size_t m_sourcePort; + size_t m_targetPort; + bool m_oldDirtyFlag; + AZStd::string m_oldContents; public: - EMotionFX::AnimGraphNodeId GetTargetNodeID() const { return mTargetNodeId; } - EMotionFX::AnimGraphNodeId GetSourceNodeID() const { return mSourceNodeId; } - AZ::TypeId GetTransitionType() const { return mTransitionType; } - size_t GetSourcePort() const { return mSourcePort; } - size_t GetTargetPort() const { return mTargetPort; } - int32 GetStartOffsetX() const { return mStartOffsetX; } - int32 GetStartOffsetY() const { return mStartOffsetY; } - int32 GetEndOffsetX() const { return mEndOffsetX; } - int32 GetEndOffsetY() const { return mEndOffsetY; } + EMotionFX::AnimGraphNodeId GetTargetNodeID() const { return m_targetNodeId; } + EMotionFX::AnimGraphNodeId GetSourceNodeID() const { return m_sourceNodeId; } + AZ::TypeId GetTransitionType() const { return m_transitionType; } + size_t GetSourcePort() const { return m_sourcePort; } + size_t GetTargetPort() const { return m_targetPort; } + int32 GetStartOffsetX() const { return m_startOffsetX; } + int32 GetStartOffsetY() const { return m_startOffsetY; } + int32 GetEndOffsetX() const { return m_endOffsetX; } + int32 GetEndOffsetY() const { return m_endOffsetY; } EMotionFX::AnimGraphConnectionId GetConnectionId() const{ return m_connectionId; } MCORE_DEFINECOMMAND_END @@ -127,7 +127,7 @@ namespace CommandSystem private: AZ::Outcome m_oldSerializedMembers; // Without actions and conditions. - bool mOldDirtyFlag = false; + bool m_oldDirtyFlag = false; }; ////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphGroupParameterCommands.cpp b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphGroupParameterCommands.cpp index a349059799..9131706b69 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphGroupParameterCommands.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphGroupParameterCommands.cpp @@ -54,7 +54,7 @@ namespace CommandSystem { // Get the parameter name. const AZStd::string& name = parameters.GetValue("name", this); - mOldName = name; + m_oldName = name; // Find the anim graph by using the id from command parameter. const uint32 animGraphID = parameters.GetValueAsInt("animGraphID", this); @@ -108,7 +108,7 @@ namespace CommandSystem } const size_t numParameters = parameterNames.size(); - mOldGroupParameterNames.resize(numParameters); + m_oldGroupParameterNames.resize(numParameters); EMotionFX::ValueParameterVector valueParametersBeforeChange = animGraph->RecursivelyGetValueParameters(); @@ -118,13 +118,13 @@ namespace CommandSystem const EMotionFX::Parameter* parameter = animGraph->FindParameterByName(parameterNames[i]); if (!parameter) { - mOldGroupParameterNames[i].clear(); + m_oldGroupParameterNames[i].clear(); continue; } // Save the group parameter (for undo) to which the parameter belonged before command execution. const EMotionFX::GroupParameter* parentParameter = animGraph->FindParentGroupParameter(parameter); - mOldGroupParameterNames[i] = parentParameter ? parentParameter->GetName() : ""; + m_oldGroupParameterNames[i] = parentParameter ? parentParameter->GetName() : ""; // Make sure the parameter is not in any other group. animGraph->TakeParameterFromParent(parameter); @@ -175,7 +175,7 @@ namespace CommandSystem } // save the current dirty flag and tell the anim graph that something got changed - mOldDirtyFlag = animGraph->GetDirtyFlag(); + m_oldDirtyFlag = animGraph->GetDirtyFlag(); animGraph->SetDirtyFlag(true); animGraph->RecursiveInvalidateUniqueDatas(); @@ -196,13 +196,13 @@ namespace CommandSystem MCore::CommandGroup commandGroup; - // Undo the group name as first step. All commands afterwards have to use mOldName as group name. + // Undo the group name as first step. All commands afterwards have to use m_oldName as group name. if (parameters.CheckIfHasParameter("newName")) { const AZStd::string& newName = parameters.GetValue("newName", this); const AZStd::string command = AZStd::string::format("AnimGraphAdjustGroupParameter -animGraphID %i -name \"%s\" -newName \"%s\"", - animGraph->GetID(), newName.c_str(), mOldName.c_str()); + animGraph->GetID(), newName.c_str(), m_oldName.c_str()); commandGroup.AddCommandString(command); } @@ -210,7 +210,7 @@ namespace CommandSystem if (parameters.CheckIfHasParameter("description")) { const AZStd::string command = AZStd::string::format("AnimGraphAdjustGroupParameter -animGraphID %i -name \"%s\" -description \"%s\"", - animGraph->GetID(), mOldName.c_str(), m_oldDescription.c_str()); + animGraph->GetID(), m_oldName.c_str(), m_oldDescription.c_str()); commandGroup.AddCommandString(command); } @@ -225,12 +225,12 @@ namespace CommandSystem AzFramework::StringFunc::Tokenize(parametersString.c_str(), parameterNames, ";", false, true); const size_t parameterCount = parameterNames.size(); - AZ_Assert(parameterCount == mOldGroupParameterNames.size(), "The number of parameter names has to match the saved group parameter info for undo."); + AZ_Assert(parameterCount == m_oldGroupParameterNames.size(), "The number of parameter names has to match the saved group parameter info for undo."); for (size_t i = 0; i < parameterCount; ++i) { const AZStd::string& parameterName = parameterNames[i]; - const AZStd::string& oldGroupName = mOldGroupParameterNames[i]; + const AZStd::string& oldGroupName = m_oldGroupParameterNames[i]; switch (action) { @@ -240,7 +240,7 @@ namespace CommandSystem { // An empty old group name means that the parameter was in the Default group before, so in this case just remove the parameter from the group. const AZStd::string command = AZStd::string::format("AnimGraphAdjustGroupParameter -animGraphID %i -name \"%s\" -action \"remove\" -parameterNames \"%s\"", - animGraph->GetID(), mOldName.c_str(), parameterName.c_str()); + animGraph->GetID(), m_oldName.c_str(), parameterName.c_str()); commandGroup.AddCommandString(command); } @@ -277,7 +277,7 @@ namespace CommandSystem } // Set the dirty flag back to the old value. - animGraph->SetDirtyFlag(mOldDirtyFlag); + animGraph->SetDirtyFlag(m_oldDirtyFlag); return true; } @@ -364,8 +364,8 @@ namespace CommandSystem } // save the current dirty flag and tell the anim graph that something got changed - mOldDirtyFlag = animGraph->GetDirtyFlag(); - mOldName = groupParameter->GetName(); + m_oldDirtyFlag = animGraph->GetDirtyFlag(); + m_oldName = groupParameter->GetName(); animGraph->SetDirtyFlag(true); animGraph->RecursiveInvalidateUniqueDatas(); @@ -385,7 +385,7 @@ namespace CommandSystem } // Construct and execute the command. - const AZStd::string command = AZStd::string::format("AnimGraphRemoveGroupParameter -animGraphID %i -name \"%s\"", animGraphID, mOldName.c_str()); + const AZStd::string command = AZStd::string::format("AnimGraphRemoveGroupParameter -animGraphID %i -name \"%s\"", animGraphID, m_oldName.c_str()); AZStd::string result; if (!GetCommandManager()->ExecuteCommandInsideCommand(command, result)) @@ -394,7 +394,7 @@ namespace CommandSystem } // Set the dirty flag back to the old value. - animGraph->SetDirtyFlag(mOldDirtyFlag); + animGraph->SetDirtyFlag(m_oldDirtyFlag); return true; } @@ -457,23 +457,23 @@ namespace CommandSystem } // read out information for the command undo - mOldName = parameter->GetName(); + m_oldName = parameter->GetName(); const EMotionFX::GroupParameter* parentGroup = animGraph->FindParentGroupParameter(parameter); if (parentGroup) { - mOldParent = parentGroup->GetName(); - mOldIndex = parentGroup->FindParameterIndex(parameter).GetValue(); + m_oldParent = parentGroup->GetName(); + m_oldIndex = parentGroup->FindParameterIndex(parameter).GetValue(); } else { - mOldParent = ""; - mOldIndex = animGraph->FindParameterIndex(parameter).GetValue(); + m_oldParent = ""; + m_oldIndex = animGraph->FindParameterIndex(parameter).GetValue(); } - mOldParameterNames.clear(); + m_oldParameterNames.clear(); // Collect all child parameters and move them to the default group. Keep the child hierarchy as it is. - // Add the immediate child ones to mOldParameterNames so they get moved back on undo + // Add the immediate child ones to m_oldParameterNames so they get moved back on undo const EMotionFX::GroupParameter* groupParameter = static_cast(parameter); const EMotionFX::ParameterVector childParameters = groupParameter->RecursivelyGetChildParameters(); AZStd::vector childParents; @@ -497,7 +497,7 @@ namespace CommandSystem const EMotionFX::GroupParameter* parent = childParents[i]; if (parent == groupParameter) { - mOldParameterNames += childParameters[i]->GetName() + ";"; + m_oldParameterNames += childParameters[i]->GetName() + ";"; animGraph->AddParameter(childParameters[i]); // add to default group } else @@ -505,9 +505,9 @@ namespace CommandSystem animGraph->AddParameter(childParameters[i], parent); // add to default group } } - if (!mOldParameterNames.empty()) + if (!m_oldParameterNames.empty()) { - mOldParameterNames.pop_back(); // remove trailing ";" + m_oldParameterNames.pop_back(); // remove trailing ";" } // remove the group parameter @@ -529,7 +529,7 @@ namespace CommandSystem } // save the current dirty flag and tell the anim graph that something got changed - mOldDirtyFlag = animGraph->GetDirtyFlag(); + m_oldDirtyFlag = animGraph->GetDirtyFlag(); animGraph->SetDirtyFlag(true); animGraph->RecursiveInvalidateUniqueDatas(); @@ -555,18 +555,18 @@ namespace CommandSystem command = AZStd::string::format("AnimGraphAddGroupParameter -animGraphID %i -name \"%s\" -index %zu -parent \"%s\" -updateUI %s", animGraph->GetID(), - mOldName.c_str(), - mOldIndex, - mOldParent.c_str(), + m_oldName.c_str(), + m_oldIndex, + m_oldParent.c_str(), updateWindow.c_str()); commandGroup.AddCommandString(command); - if (!mOldParameterNames.empty()) + if (!m_oldParameterNames.empty()) { command = AZStd::string::format("AnimGraphAdjustGroupParameter -animGraphID %i -name \"%s\" -parameterNames \"%s\" -action \"add\" -updateUI %s", animGraph->GetID(), - mOldName.c_str(), - mOldParameterNames.c_str(), + m_oldName.c_str(), + m_oldParameterNames.c_str(), updateWindow.c_str()); commandGroup.AddCommandString(command); } @@ -579,7 +579,7 @@ namespace CommandSystem } // Set the dirty flag back to the old value. - animGraph->SetDirtyFlag(mOldDirtyFlag); + animGraph->SetDirtyFlag(m_oldDirtyFlag); return true; } diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphGroupParameterCommands.h b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphGroupParameterCommands.h index 80e43818c7..3bdc7f3e0e 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphGroupParameterCommands.h +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphGroupParameterCommands.h @@ -27,25 +27,25 @@ namespace CommandSystem }; Action GetAction(const MCore::CommandLine& parameters); - AZStd::string mOldName; //! group parameter name before command execution. - AZStd::vector mOldGroupParameterNames; - bool mOldDirtyFlag; + AZStd::string m_oldName; //! group parameter name before command execution. + AZStd::vector m_oldGroupParameterNames; + bool m_oldDirtyFlag; AZStd::string m_oldDescription; MCORE_DEFINECOMMAND_END // Add a group parameter. MCORE_DEFINECOMMAND_START(CommandAnimGraphAddGroupParameter, "Add anim graph group parameter", true) - bool mOldDirtyFlag; - AZStd::string mOldName; + bool m_oldDirtyFlag; + AZStd::string m_oldName; MCORE_DEFINECOMMAND_END // Remove a group parameter. MCORE_DEFINECOMMAND_START(CommandAnimGraphRemoveGroupParameter, "Remove anim graph group parameter", true) - AZStd::string mOldName; - AZStd::string mOldParameterNames; - AZStd::string mOldParent; - size_t mOldIndex; - bool mOldDirtyFlag; + AZStd::string m_oldName; + AZStd::string m_oldParameterNames; + AZStd::string m_oldParent; + size_t m_oldIndex; + bool m_oldDirtyFlag; MCORE_DEFINECOMMAND_END // helper functions diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphNodeCommands.cpp b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphNodeCommands.cpp index 6142fe151e..d81d495a4d 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphNodeCommands.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphNodeCommands.cpp @@ -113,7 +113,7 @@ namespace CommandSystem return EMotionFX::AnimGraphNodeId::CreateFromString(nodeIdString); } - return mNodeId; + return m_nodeId; } void CommandAnimGraphCreateNode::DeleteGraphNode(EMotionFX::AnimGraphNode* node) @@ -142,7 +142,7 @@ namespace CommandSystem } // store the anim graph id for undo - mAnimGraphID = animGraph->GetID(); + m_animGraphId = animGraph->GetID(); // find the graph EMotionFX::AnimGraphNode* parentNode = nullptr; @@ -204,7 +204,7 @@ namespace CommandSystem EMotionFX::AnimGraphNode* node = static_cast(object); // store the node id for the callbacks - mNodeId = node->GetId(); + m_nodeId = node->GetId(); if (parameters.CheckIfHasParameter("contents")) { @@ -213,7 +213,7 @@ namespace CommandSystem MCore::ReflectionSerializer::DeserializeMembers(node, contents); // The deserialize method will deserialize back the old id - node->SetId(mNodeId); + node->SetId(m_nodeId); // Verify we have not serialized connections, child nodes and transitions AZ_Assert(node->GetNumConnections() == 0, "Unexpected serialized connections"); @@ -232,7 +232,7 @@ namespace CommandSystem const EMotionFX::AnimGraphNodeId nodeId = EMotionFX::AnimGraphNodeId::CreateFromString(nodeIdString); node->SetId(nodeId); - mNodeId = nodeId; + m_nodeId = nodeId; } // if the name is not empty, set it @@ -317,7 +317,7 @@ namespace CommandSystem node->SetIsCollapsed(collapsed); // store the anim graph id for undo - mAnimGraphID = animGraph->GetID(); + m_animGraphId = animGraph->GetID(); // check if the parent is valid if (parentNode) @@ -357,7 +357,7 @@ namespace CommandSystem } // save the current dirty flag and tell the anim graph that something got changed - mOldDirtyFlag = animGraph->GetDirtyFlag(); + m_oldDirtyFlag = animGraph->GetDirtyFlag(); animGraph->SetDirtyFlag(true); // return the node name @@ -397,21 +397,21 @@ namespace CommandSystem MCORE_UNUSED(parameters); // get the anim graph - EMotionFX::AnimGraph* animGraph = EMotionFX::GetAnimGraphManager().FindAnimGraphByID(mAnimGraphID); + EMotionFX::AnimGraph* animGraph = EMotionFX::GetAnimGraphManager().FindAnimGraphByID(m_animGraphId); if (animGraph == nullptr) { - outResult = AZStd::string::format("The anim graph with id '%i' does not exist anymore.", mAnimGraphID); + outResult = AZStd::string::format("The anim graph with id '%i' does not exist anymore.", m_animGraphId); return false; } // locate the node - EMotionFX::AnimGraphNode* node = animGraph->RecursiveFindNodeById(mNodeId); + EMotionFX::AnimGraphNode* node = animGraph->RecursiveFindNodeById(m_nodeId); if (node == nullptr) { return false; } - mNodeId.SetInvalid(); + m_nodeId.SetInvalid(); const AZStd::string commandString = AZStd::string::format("AnimGraphRemoveNode -animGraphID %i -name \"%s\"", animGraph->GetID(), node->GetName()); if (GetCommandManager()->ExecuteCommandInsideCommand(commandString, outResult) == false) @@ -424,7 +424,7 @@ namespace CommandSystem } // set the dirty flag back to the old value - animGraph->SetDirtyFlag(mOldDirtyFlag); + animGraph->SetDirtyFlag(m_oldDirtyFlag); return true; } @@ -463,8 +463,8 @@ namespace CommandSystem CommandAnimGraphAdjustNode::CommandAnimGraphAdjustNode(MCore::Command* orgCommand) : MCore::Command("AnimGraphAdjustNode", orgCommand) { - mOldPosX = 0; - mOldPosY = 0; + m_oldPosX = 0; + m_oldPosY = 0; } // destructor @@ -483,7 +483,7 @@ namespace CommandSystem } // store the anim graph id for undo - mAnimGraphID = animGraph->GetID(); + m_animGraphId = animGraph->GetID(); // get the name of the node AZStd::string name; @@ -506,8 +506,8 @@ namespace CommandSystem // get the x and y pos int32 xPos = node->GetVisualPosX(); int32 yPos = node->GetVisualPosY(); - mOldPosX = xPos; - mOldPosY = yPos; + m_oldPosX = xPos; + m_oldPosY = yPos; // get the new position values if (parameters.CheckIfHasParameter("xPos")) @@ -529,17 +529,17 @@ namespace CommandSystem { // find the node group the node was in before the name change EMotionFX::AnimGraphNodeGroup* nodeGroup = animGraph->FindNodeGroupForNode(node); - mNodeGroupName.clear(); + m_nodeGroupName.clear(); if (nodeGroup) { // remember the node group name for undo - mNodeGroupName = nodeGroup->GetName(); + m_nodeGroupName = nodeGroup->GetName(); // remove the node from the node group as its id is going to change nodeGroup->RemoveNodeById(node->GetId()); } - mOldName = node->GetName(); + m_oldName = node->GetName(); node->SetName(newName.c_str()); // as the id of the node changed after renaming it, we have to readd the node with the new id @@ -549,27 +549,27 @@ namespace CommandSystem } // call the post rename node event - EMotionFX::GetEventManager().OnRenamedNode(animGraph, node, mOldName.c_str()); + EMotionFX::GetEventManager().OnRenamedNode(animGraph, node, m_oldName.c_str()); } // remember and set the new value to the enabled flag - mOldEnabled = node->GetIsEnabled(); + m_oldEnabled = node->GetIsEnabled(); if (parameters.CheckIfHasParameter("enabled")) { node->SetIsEnabled(parameters.GetValueAsBool("enabled", this)); } // remember and set the new value to the visualization flag - mOldVisualized = node->GetIsVisualizationEnabled(); + m_oldVisualized = node->GetIsVisualizationEnabled(); if (parameters.CheckIfHasParameter("visualize")) { node->SetVisualization(parameters.GetValueAsBool("visualize", this)); } - mNodeId = node->GetId(); + m_nodeId = node->GetId(); // save the current dirty flag and tell the anim graph that something got changed - mOldDirtyFlag = animGraph->GetDirtyFlag(); + m_oldDirtyFlag = animGraph->GetDirtyFlag(); animGraph->SetDirtyFlag(true); // only update attributes in case it is wanted @@ -586,22 +586,22 @@ namespace CommandSystem bool CommandAnimGraphAdjustNode::Undo(const MCore::CommandLine& parameters, AZStd::string& outResult) { // get the anim graph - EMotionFX::AnimGraph* animGraph = EMotionFX::GetAnimGraphManager().FindAnimGraphByID(mAnimGraphID); + EMotionFX::AnimGraph* animGraph = EMotionFX::GetAnimGraphManager().FindAnimGraphByID(m_animGraphId); if (animGraph == nullptr) { - outResult = AZStd::string::format("The anim graph with id '%i' does not exist anymore.", mAnimGraphID); + outResult = AZStd::string::format("The anim graph with id '%i' does not exist anymore.", m_animGraphId); return false; } - EMotionFX::AnimGraphNode* node = animGraph->RecursiveFindNodeById(mNodeId); + EMotionFX::AnimGraphNode* node = animGraph->RecursiveFindNodeById(m_nodeId); if (node == nullptr) { - outResult = AZStd::string::format("Cannot find node with ID %s.", mNodeId.ToString().c_str()); + outResult = AZStd::string::format("Cannot find node with ID %s.", m_nodeId.ToString().c_str()); return false; } // restore the name - if (!mOldName.empty()) + if (!m_oldName.empty()) { AZStd::string currentName = node->GetName(); @@ -614,7 +614,7 @@ namespace CommandSystem nodeGroup->RemoveNodeById(node->GetId()); } - node->SetName(mOldName.c_str()); + node->SetName(m_oldName.c_str()); // as the id of the node changed after renaming it, we have to readd the node with the new id if (nodeGroup) @@ -626,12 +626,12 @@ namespace CommandSystem EMotionFX::GetEventManager().OnRenamedNode(animGraph, node, node->GetName()); } - mNodeId = node->GetId(); - node->SetVisualPos(mOldPosX, mOldPosY); + m_nodeId = node->GetId(); + node->SetVisualPos(m_oldPosX, m_oldPosY); // set the old values to the enabled flag and the visualization flag - node->SetIsEnabled(mOldEnabled); - node->SetVisualization(mOldVisualized); + node->SetIsEnabled(m_oldEnabled); + node->SetVisualization(m_oldVisualized); // do only for parameter nodes if (azrtti_typeid(node) == azrtti_typeid() && parameters.CheckIfHasParameter("parameterMask")) @@ -640,11 +640,11 @@ namespace CommandSystem EMotionFX::BlendTreeParameterNode* parameterNode = static_cast(node); // get the parameter mask attribute and update the mask - parameterNode->SetParameters(mOldParameterMask); + parameterNode->SetParameters(m_oldParameterMask); } // set the dirty flag back to the old value - animGraph->SetDirtyFlag(mOldDirtyFlag); + animGraph->SetDirtyFlag(m_oldDirtyFlag); node->Reinit(); animGraph->RecursiveInvalidateUniqueDatas(); @@ -681,7 +681,7 @@ namespace CommandSystem CommandAnimGraphRemoveNode::CommandAnimGraphRemoveNode(MCore::Command* orgCommand) : MCore::Command("AnimGraphRemoveNode", orgCommand) { - mIsEntryNode = false; + m_isEntryNode = false; } // destructor @@ -700,7 +700,7 @@ namespace CommandSystem } // store the anim graph id for undo - mAnimGraphID = animGraph->GetID(); + m_animGraphId = animGraph->GetID(); // find the emfx node AZStd::string name; @@ -712,20 +712,20 @@ namespace CommandSystem return false; } - mType = azrtti_typeid(emfxNode); - mName = emfxNode->GetName(); - mPosX = emfxNode->GetVisualPosX(); - mPosY = emfxNode->GetVisualPosY(); - mCollapsed = emfxNode->GetIsCollapsed(); - mOldContents = MCore::ReflectionSerializer::SerializeMembersExcept(emfxNode, { "childNodes", "connections", "transitions" }).GetValue(); - mNodeId = emfxNode->GetId(); + m_type = azrtti_typeid(emfxNode); + m_name = emfxNode->GetName(); + m_posX = emfxNode->GetVisualPosX(); + m_posY = emfxNode->GetVisualPosY(); + m_collapsed = emfxNode->GetIsCollapsed(); + m_oldContents = MCore::ReflectionSerializer::SerializeMembersExcept(emfxNode, { "childNodes", "connections", "transitions" }).GetValue(); + m_nodeId = emfxNode->GetId(); // remember the node group for the node for undo - mNodeGroupName.clear(); + m_nodeGroupName.clear(); EMotionFX::AnimGraphNodeGroup* nodeGroup = animGraph->FindNodeGroupForNode(emfxNode); if (nodeGroup) { - mNodeGroupName = nodeGroup->GetName(); + m_nodeGroupName = nodeGroup->GetName(); } // get the parent node @@ -737,7 +737,7 @@ namespace CommandSystem EMotionFX::AnimGraphStateMachine* stateMachine = static_cast(parentNode); if (stateMachine->GetEntryState() == emfxNode) { - mIsEntryNode = true; + m_isEntryNode = true; // Find a new entry node if we can //-------------------------- @@ -766,8 +766,8 @@ namespace CommandSystem } } - mParentName = parentNode->GetName(); - mParentNodeId = parentNode->GetId(); + m_parentName = parentNode->GetName(); + m_parentNodeId = parentNode->GetId(); // call the pre remove node event EMotionFX::GetEventManager().OnRemoveNode(animGraph, emfxNode); @@ -780,15 +780,15 @@ namespace CommandSystem } else { - mParentNodeId.SetInvalid(); - mParentName.clear(); + m_parentNodeId.SetInvalid(); + m_parentName.clear(); MCore::LogError("Cannot remove root state machine."); MCORE_ASSERT(false); return false; } // save the current dirty flag and tell the anim graph that something got changed - mOldDirtyFlag = animGraph->GetDirtyFlag(); + m_oldDirtyFlag = animGraph->GetDirtyFlag(); animGraph->SetDirtyFlag(true); animGraph->RecursiveInvalidateUniqueDatas(); @@ -801,34 +801,34 @@ namespace CommandSystem { MCORE_UNUSED(parameters); - EMotionFX::AnimGraph* animGraph = EMotionFX::GetAnimGraphManager().FindAnimGraphByID(mAnimGraphID); + EMotionFX::AnimGraph* animGraph = EMotionFX::GetAnimGraphManager().FindAnimGraphByID(m_animGraphId); if (!animGraph) { - outResult = AZStd::string::format("The anim graph with id '%i' does not exist anymore.", mAnimGraphID); + outResult = AZStd::string::format("The anim graph with id '%i' does not exist anymore.", m_animGraphId); return false; } // create the node again MCore::CommandGroup group("Recreating node"); AZStd::string commandString; - if (!mParentName.empty()) + if (!m_parentName.empty()) { commandString = AZStd::string::format("AnimGraphCreateNode -animGraphID %i -type \"%s\" -parentName \"%s\" -name \"%s\" -nodeId \"%s\" -xPos %d -yPos %d -collapsed %s -center false -contents {%s}", animGraph->GetID(), - mType.ToString().c_str(), - mParentName.c_str(), - mName.c_str(), - mNodeId.ToString().c_str(), - mPosX, - mPosY, - AZStd::to_string(mCollapsed).c_str(), - mOldContents.c_str()); + m_type.ToString().c_str(), + m_parentName.c_str(), + m_name.c_str(), + m_nodeId.ToString().c_str(), + m_posX, + m_posY, + AZStd::to_string(m_collapsed).c_str(), + m_oldContents.c_str()); group.AddCommandString(commandString); - if (mIsEntryNode) + if (m_isEntryNode) { - commandString = AZStd::string::format("AnimGraphSetEntryState -animGraphID %i -entryNodeName \"%s\"", animGraph->GetID(), mName.c_str()); + commandString = AZStd::string::format("AnimGraphSetEntryState -animGraphID %i -entryNodeName \"%s\"", animGraph->GetID(), m_name.c_str()); group.AddCommandString(commandString); } } @@ -836,13 +836,13 @@ namespace CommandSystem { commandString = AZStd::string::format("AnimGraphCreateNode -animGraphID %i -type \"%s\" -name \"%s\" -nodeId \"%s\" -xPos %d -yPos %d -collapsed %s -center false -contents {%s}", animGraph->GetID(), - mType.ToString().c_str(), - mName.c_str(), - mNodeId.ToString().c_str(), - mPosX, - mPosY, - AZStd::to_string(mCollapsed).c_str(), - mOldContents.c_str()); + m_type.ToString().c_str(), + m_name.c_str(), + m_nodeId.ToString().c_str(), + m_posX, + m_posY, + AZStd::to_string(m_collapsed).c_str(), + m_oldContents.c_str()); group.AddCommandString(commandString); } @@ -857,15 +857,15 @@ namespace CommandSystem } // add it to the old node group if it was assigned to one before - if (!mNodeGroupName.empty()) + if (!m_nodeGroupName.empty()) { auto* command = aznew CommandSystem::CommandAnimGraphAdjustNodeGroup( GetCommandManager()->FindCommand(CommandSystem::CommandAnimGraphAdjustNodeGroup::s_commandName), /*animGraphId = */ animGraph->GetID(), - /*name = */ mNodeGroupName, + /*name = */ m_nodeGroupName, /*visible = */ AZStd::nullopt, /*newName = */ AZStd::nullopt, - /*nodeNames = */ {{mName}}, + /*nodeNames = */ {{m_name}}, /*nodeAction = */ CommandSystem::CommandAnimGraphAdjustNodeGroup::NodeAction::Add ); if (GetCommandManager()->ExecuteCommandInsideCommand(command, outResult) == false) @@ -880,7 +880,7 @@ namespace CommandSystem } // set the dirty flag back to the old value - animGraph->SetDirtyFlag(mOldDirtyFlag); + animGraph->SetDirtyFlag(m_oldDirtyFlag); return true; } @@ -925,7 +925,7 @@ namespace CommandSystem } // store the anim graph id for undo - mAnimGraphID = animGraph->GetID(); + m_animGraphId = animGraph->GetID(); AZStd::string entryNodeName; parameters.GetValue("entryNodeName", this, entryNodeName); @@ -960,21 +960,21 @@ namespace CommandSystem EMotionFX::AnimGraphNode* oldEntryNode = stateMachine->GetEntryState(); if (oldEntryNode) { - mOldEntryStateNodeId = oldEntryNode->GetId(); + m_oldEntryStateNodeId = oldEntryNode->GetId(); } else { - mOldEntryStateNodeId.SetInvalid(); + m_oldEntryStateNodeId.SetInvalid(); } // store the id of the state machine - mOldStateMachineNodeId = stateMachineNode->GetId(); + m_oldStateMachineNodeId = stateMachineNode->GetId(); // set the new entry state for the state machine stateMachine->SetEntryState(entryNode); // save the current dirty flag and tell the anim graph that something got changed - mOldDirtyFlag = animGraph->GetDirtyFlag(); + m_oldDirtyFlag = animGraph->GetDirtyFlag(); animGraph->SetDirtyFlag(true); stateMachine->Reinit(); @@ -989,15 +989,15 @@ namespace CommandSystem MCORE_UNUSED(parameters); // get the anim graph - EMotionFX::AnimGraph* animGraph = EMotionFX::GetAnimGraphManager().FindAnimGraphByID(mAnimGraphID); + EMotionFX::AnimGraph* animGraph = EMotionFX::GetAnimGraphManager().FindAnimGraphByID(m_animGraphId); if (animGraph == nullptr) { - outResult = AZStd::string::format("The anim graph with id '%i' does not exist anymore.", mAnimGraphID); + outResult = AZStd::string::format("The anim graph with id '%i' does not exist anymore.", m_animGraphId); return false; } // get the state machine - EMotionFX::AnimGraphNode* stateMachineNode = animGraph->RecursiveFindNodeById(mOldStateMachineNodeId); + EMotionFX::AnimGraphNode* stateMachineNode = animGraph->RecursiveFindNodeById(m_oldStateMachineNodeId); if (stateMachineNode == nullptr || azrtti_typeid(stateMachineNode) != azrtti_typeid()) { outResult = "Cannot undo set entry node. Parent node is not a state machine or not valid at all."; @@ -1008,9 +1008,9 @@ namespace CommandSystem EMotionFX::AnimGraphStateMachine* stateMachine = (EMotionFX::AnimGraphStateMachine*)stateMachineNode; // find the entry anim graph node - if (mOldEntryStateNodeId.IsValid()) + if (m_oldEntryStateNodeId.IsValid()) { - EMotionFX::AnimGraphNode* entryNode = animGraph->RecursiveFindNodeById(mOldEntryStateNodeId); + EMotionFX::AnimGraphNode* entryNode = animGraph->RecursiveFindNodeById(m_oldEntryStateNodeId); if (!entryNode) { outResult = "Cannot undo set entry node. Old entry node cannot be found."; @@ -1027,7 +1027,7 @@ namespace CommandSystem } // set the dirty flag back to the old value - animGraph->SetDirtyFlag(mOldDirtyFlag); + animGraph->SetDirtyFlag(m_oldDirtyFlag); stateMachine->Reinit(); animGraph->RecursiveInvalidateUniqueDatas(); diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphNodeCommands.h b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphNodeCommands.h index 6a5a991809..4d02d55921 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphNodeCommands.h +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphNodeCommands.h @@ -25,60 +25,60 @@ public: EMotionFX::AnimGraphNodeId GetNodeId(const MCore::CommandLine& parameters); void DeleteGraphNode(EMotionFX::AnimGraphNode* node); - uint32 mAnimGraphID; - bool mOldDirtyFlag; - EMotionFX::AnimGraphNodeId mNodeId; + uint32 m_animGraphId; + bool m_oldDirtyFlag; + EMotionFX::AnimGraphNodeId m_nodeId; MCORE_DEFINECOMMAND_END // adjust a node MCORE_DEFINECOMMAND_START(CommandAnimGraphAdjustNode, "Adjust a anim graph node", true) - EMotionFX::AnimGraphNodeId mNodeId; - int32 mOldPosX; - int32 mOldPosY; - AZStd::string mOldName; - AZStd::string mOldParameterMask; - bool mOldDirtyFlag; - bool mOldEnabled; - bool mOldVisualized; - AZStd::string mNodeGroupName; + EMotionFX::AnimGraphNodeId m_nodeId; + int32 m_oldPosX; + int32 m_oldPosY; + AZStd::string m_oldName; + AZStd::string m_oldParameterMask; + bool m_oldDirtyFlag; + bool m_oldEnabled; + bool m_oldVisualized; + AZStd::string m_nodeGroupName; public: - EMotionFX::AnimGraphNodeId GetNodeId() const { return mNodeId; } - const AZStd::string& GetOldName() const { return mOldName; } - uint32 mAnimGraphID; + EMotionFX::AnimGraphNodeId GetNodeId() const { return m_nodeId; } + const AZStd::string& GetOldName() const { return m_oldName; } + uint32 m_animGraphId; MCORE_DEFINECOMMAND_END // remove a node MCORE_DEFINECOMMAND_START(CommandAnimGraphRemoveNode, "Remove a anim graph node", true) - EMotionFX::AnimGraphNodeId mNodeId; - uint32 mAnimGraphID; - EMotionFX::AnimGraphNodeId mParentNodeId; - AZ::TypeId mType; - AZStd::string mParentName; - AZStd::string mName; - AZStd::string mNodeGroupName; - int32 mPosX; - int32 mPosY; - AZStd::string mOldContents; - bool mCollapsed; - bool mOldDirtyFlag; - bool mIsEntryNode; + EMotionFX::AnimGraphNodeId m_nodeId; + uint32 m_animGraphId; + EMotionFX::AnimGraphNodeId m_parentNodeId; + AZ::TypeId m_type; + AZStd::string m_parentName; + AZStd::string m_name; + AZStd::string m_nodeGroupName; + int32 m_posX; + int32 m_posY; + AZStd::string m_oldContents; + bool m_collapsed; + bool m_oldDirtyFlag; + bool m_isEntryNode; public: - EMotionFX::AnimGraphNodeId GetNodeId() const { return mNodeId; } - EMotionFX::AnimGraphNodeId GetParentNodeId() const { return mParentNodeId; } + EMotionFX::AnimGraphNodeId GetNodeId() const { return m_nodeId; } + EMotionFX::AnimGraphNodeId GetParentNodeId() const { return m_parentNodeId; } MCORE_DEFINECOMMAND_END // set the entry state of a state machine MCORE_DEFINECOMMAND_START(CommandAnimGraphSetEntryState, "Set entry state", true) public: - uint32 mAnimGraphID; - EMotionFX::AnimGraphNodeId mOldEntryStateNodeId; - EMotionFX::AnimGraphNodeId mOldStateMachineNodeId; - bool mOldDirtyFlag; + uint32 m_animGraphId; + EMotionFX::AnimGraphNodeId m_oldEntryStateNodeId; + EMotionFX::AnimGraphNodeId m_oldStateMachineNodeId; + bool m_oldDirtyFlag; MCORE_DEFINECOMMAND_END diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphNodeGroupCommands.cpp b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphNodeGroupCommands.cpp index a11af1399d..0f04bb0e79 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphNodeGroupCommands.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphNodeGroupCommands.cpp @@ -334,8 +334,8 @@ namespace CommandSystem nodeGroup->SetColor(color.ToU32()); // save the current dirty flag and tell the anim graph that something got changed - mOldDirtyFlag = animGraph->GetDirtyFlag(); - mOldName = nodeGroup->GetName(); + m_oldDirtyFlag = animGraph->GetDirtyFlag(); + m_oldName = nodeGroup->GetName(); animGraph->SetDirtyFlag(true); return true; } @@ -349,7 +349,7 @@ namespace CommandSystem return false; } - AZStd::string commandString = AZStd::string::format("AnimGraphRemoveNodeGroup -animGraphID %i -name \"%s\"", animGraph->GetID(), mOldName.c_str()); + AZStd::string commandString = AZStd::string::format("AnimGraphRemoveNodeGroup -animGraphID %i -name \"%s\"", animGraph->GetID(), m_oldName.c_str()); // execute the command AZStd::string result; @@ -359,7 +359,7 @@ namespace CommandSystem } // set the dirty flag back to the old value - animGraph->SetDirtyFlag(mOldDirtyFlag); + animGraph->SetDirtyFlag(m_oldDirtyFlag); return true; } @@ -413,16 +413,16 @@ namespace CommandSystem // read out information for the command undo EMotionFX::AnimGraphNodeGroup* nodeGroup = animGraph->GetNodeGroup(groupIndex); - mOldName = nodeGroup->GetName(); - mOldColor = nodeGroup->GetColor(); - mOldIsVisible = nodeGroup->GetIsVisible(); - mOldNodeIds = CommandAnimGraphAdjustNodeGroup::CollectNodeIdsFromGroup(nodeGroup); + m_oldName = nodeGroup->GetName(); + m_oldColor = nodeGroup->GetColor(); + m_oldIsVisible = nodeGroup->GetIsVisible(); + m_oldNodeIds = CommandAnimGraphAdjustNodeGroup::CollectNodeIdsFromGroup(nodeGroup); // remove the node group animGraph->RemoveNodeGroup(groupIndex); // save the current dirty flag and tell the anim graph that something got changed - mOldDirtyFlag = animGraph->GetDirtyFlag(); + m_oldDirtyFlag = animGraph->GetDirtyFlag(); animGraph->SetDirtyFlag(true); return true; } @@ -439,17 +439,17 @@ namespace CommandSystem MCore::CommandGroup commandGroup; - commandGroup.AddCommandString(AZStd::string::format("AnimGraphAddNodeGroup -animGraphID %i -name \"%s\" -updateUI %s",animGraph->GetID(), mOldName.c_str(), updateWindow.c_str())); + commandGroup.AddCommandString(AZStd::string::format("AnimGraphAddNodeGroup -animGraphID %i -name \"%s\" -updateUI %s",animGraph->GetID(), m_oldName.c_str(), updateWindow.c_str())); auto* command = aznew CommandAnimGraphAdjustNodeGroup( GetCommandManager()->FindCommand(CommandAnimGraphAdjustNodeGroup::s_commandName), /*animGraphId = */ animGraph->GetID(), - /*name = */ mOldName, - /*visible = */ mOldIsVisible, + /*name = */ m_oldName, + /*visible = */ m_oldIsVisible, /*newName = */ AZStd::nullopt, - /*nodeNames = */ CommandAnimGraphAdjustNodeGroup::GenerateNodeNameVector(animGraph, mOldNodeIds), + /*nodeNames = */ CommandAnimGraphAdjustNodeGroup::GenerateNodeNameVector(animGraph, m_oldNodeIds), /*nodeAction = */ CommandAnimGraphAdjustNodeGroup::NodeAction::Add, - /*color = */ mOldColor + /*color = */ m_oldColor ); commandGroup.AddCommand(command); @@ -461,7 +461,7 @@ namespace CommandSystem } // set the dirty flag back to the old value - animGraph->SetDirtyFlag(mOldDirtyFlag); + animGraph->SetDirtyFlag(m_oldDirtyFlag); return true; } diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphNodeGroupCommands.h b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphNodeGroupCommands.h index 0fc497d2f1..014d3b0398 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphNodeGroupCommands.h +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphNodeGroupCommands.h @@ -83,18 +83,18 @@ namespace CommandSystem // add node group MCORE_DEFINECOMMAND_START(CommandAnimGraphAddNodeGroup, "Add anim graph node group", true) - bool mOldDirtyFlag; - AZStd::string mOldName; + bool m_oldDirtyFlag; + AZStd::string m_oldName; MCORE_DEFINECOMMAND_END // remove a node group MCORE_DEFINECOMMAND_START(CommandAnimGraphRemoveNodeGroup, "Remove anim graph node group", true) - AZStd::string mOldName; - bool mOldIsVisible; - AZ::u32 mOldColor; - AZStd::vector mOldNodeIds; - bool mOldDirtyFlag; + AZStd::string m_oldName; + bool m_oldIsVisible; + AZ::u32 m_oldColor; + AZStd::vector m_oldNodeIds; + bool m_oldDirtyFlag; MCORE_DEFINECOMMAND_END // helper function diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphParameterCommands.cpp b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphParameterCommands.cpp index b0c03e4df2..571b6c5e97 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphParameterCommands.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphParameterCommands.cpp @@ -188,7 +188,7 @@ namespace CommandSystem outResult = name.c_str(); // Save the current dirty flag and tell the anim graph that something got changed. - mOldDirtyFlag = animGraph->GetDirtyFlag(); + m_oldDirtyFlag = animGraph->GetDirtyFlag(); animGraph->SetDirtyFlag(true); return true; @@ -219,7 +219,7 @@ namespace CommandSystem } // Set the dirty flag back to the old value. - animGraph->SetDirtyFlag(mOldDirtyFlag); + animGraph->SetDirtyFlag(m_oldDirtyFlag); return true; } @@ -258,22 +258,22 @@ namespace CommandSystem bool CommandAnimGraphRemoveParameter::Execute(const MCore::CommandLine& parameters, AZStd::string& outResult) { // Get the parameter name. - parameters.GetValue("name", this, mName); + parameters.GetValue("name", this, m_name); // Find the anim graph by using the id from command parameter. const uint32 animGraphID = parameters.GetValueAsInt("animGraphID", this); EMotionFX::AnimGraph* animGraph = EMotionFX::GetAnimGraphManager().FindAnimGraphByID(animGraphID); if (!animGraph) { - outResult = AZStd::string::format("Cannot remove parameter '%s' from anim graph. Anim graph id '%i' is not valid.", mName.c_str(), animGraphID); + outResult = AZStd::string::format("Cannot remove parameter '%s' from anim graph. Anim graph id '%i' is not valid.", m_name.c_str(), animGraphID); return false; } // Check if there is a parameter with the given name. - const EMotionFX::Parameter* parameter = animGraph->FindParameterByName(mName); + const EMotionFX::Parameter* parameter = animGraph->FindParameterByName(m_name); if (!parameter) { - outResult = AZStd::string::format("Cannot remove parameter '%s' from anim graph. There is no parameter with the given name.", mName.c_str()); + outResult = AZStd::string::format("Cannot remove parameter '%s' from anim graph. There is no parameter with the given name.", m_name.c_str()); return false; } AZ_Assert(azrtti_typeid(parameter) != azrtti_typeid(), "CommmandAnimGraphRemoveParameter called for a group parameter"); @@ -284,13 +284,13 @@ namespace CommandSystem AZ_Assert(parameterIndex.IsSuccess(), "Expected valid parameter index"); // Store undo info before we remove it, so that we can recreate it later. - mType = azrtti_typeid(parameter); - mIndex = parameterIndex.GetValue(); - mParent = parentGroup ? parentGroup->GetName() : ""; - mContents = MCore::ReflectionSerializer::Serialize(parameter).GetValue(); + m_type = azrtti_typeid(parameter); + m_index = parameterIndex.GetValue(); + m_parent = parentGroup ? parentGroup->GetName() : ""; + m_contents = MCore::ReflectionSerializer::Serialize(parameter).GetValue(); AZ::Outcome valueParameterIndex = AZ::Failure(); - if (mType != azrtti_typeid()) + if (m_type != azrtti_typeid()) { valueParameterIndex = animGraph->FindValueParameterIndex(static_cast(parameter)); } @@ -299,7 +299,7 @@ namespace CommandSystem if (animGraph->RemoveParameter(const_cast(parameter))) { // Remove the parameter from all corresponding anim graph instances if it is a value parameter - if (mType != azrtti_typeid()) + if (m_type != azrtti_typeid()) { AZStd::vector affectedObjects; animGraph->RecursiveCollectObjectsOfType(azrtti_typeid(), affectedObjects); @@ -308,7 +308,7 @@ namespace CommandSystem for (EMotionFX::AnimGraphObject* affectedObject : affectedObjects) { EMotionFX::ObjectAffectedByParameterChanges* parameterDriven = azdynamic_cast(affectedObject); - parameterDriven->ParameterRemoved(mName); + parameterDriven->ParameterRemoved(m_name); } const size_t numInstances = animGraph->GetNumAnimGraphInstances(); @@ -320,7 +320,7 @@ namespace CommandSystem } // Save the current dirty flag and tell the anim graph that something got changed. - mOldDirtyFlag = animGraph->GetDirtyFlag(); + m_oldDirtyFlag = animGraph->GetDirtyFlag(); animGraph->SetDirtyFlag(true); } return true; @@ -336,7 +336,7 @@ namespace CommandSystem EMotionFX::AnimGraph* animGraph = EMotionFX::GetAnimGraphManager().FindAnimGraphByID(animGraphID); if (!animGraph) { - outResult = AZStd::string::format("Cannot undo remove parameter '%s' from anim graph. Anim graph id '%i' is not valid.", mName.c_str(), animGraphID); + outResult = AZStd::string::format("Cannot undo remove parameter '%s' from anim graph. Anim graph id '%i' is not valid.", m_name.c_str(), animGraphID); return false; } @@ -347,11 +347,11 @@ namespace CommandSystem commandString = AZStd::string::format("AnimGraphCreateParameter -animGraphID %i -name \"%s\" -index %zu -type \"%s\" -contents {%s} -parent \"%s\" -updateUI %s", animGraph->GetID(), - mName.c_str(), - mIndex, - mType.ToString().c_str(), - mContents.c_str(), - mParent.c_str(), + m_name.c_str(), + m_index, + m_type.ToString().c_str(), + m_contents.c_str(), + m_parent.c_str(), updateUI.c_str()); // The parameter will be restored to the right parent group because the index is absolute @@ -364,7 +364,7 @@ namespace CommandSystem } // Set the dirty flag back to the old value. - animGraph->SetDirtyFlag(mOldDirtyFlag); + animGraph->SetDirtyFlag(m_oldDirtyFlag); return true; } @@ -399,21 +399,21 @@ namespace CommandSystem bool CommandAnimGraphAdjustParameter::Execute(const MCore::CommandLine& parameters, AZStd::string& outResult) { // Get the parameter name. - parameters.GetValue("name", this, mOldName); + parameters.GetValue("name", this, m_oldName); // Find the anim graph by using the id from command parameter. const uint32 animGraphID = parameters.GetValueAsInt("animGraphID", this); EMotionFX::AnimGraph* animGraph = EMotionFX::GetAnimGraphManager().FindAnimGraphByID(animGraphID); if (!animGraph) { - outResult = AZStd::string::format("Cannot adjust parameter '%s'. Anim graph with id '%d' not found.", mOldName.c_str(), animGraphID); + outResult = AZStd::string::format("Cannot adjust parameter '%s'. Anim graph with id '%d' not found.", m_oldName.c_str(), animGraphID); return false; } - const EMotionFX::Parameter* parameter = animGraph->FindParameterByName(mOldName); + const EMotionFX::Parameter* parameter = animGraph->FindParameterByName(m_oldName); if (!parameter) { - outResult = AZStd::string::format("There is no parameter with the name '%s'.", mOldName.c_str()); + outResult = AZStd::string::format("There is no parameter with the name '%s'.", m_oldName.c_str()); return false; } AZ::Outcome oldValueParameterIndex = AZ::Failure(); @@ -426,15 +426,15 @@ namespace CommandSystem const EMotionFX::GroupParameter* currentParent = animGraph->FindParentGroupParameter(parameter); // Store the undo info. - mOldType = azrtti_typeid(parameter); - mOldContents = MCore::ReflectionSerializer::Serialize(parameter).GetValue(); + m_oldType = azrtti_typeid(parameter); + m_oldContents = MCore::ReflectionSerializer::Serialize(parameter).GetValue(); // Get the new name and check if it is valid. AZStd::string newName; parameters.GetValue("newName", this, newName); if (!newName.empty()) { - if (newName == mOldName) + if (newName == m_oldName) { newName.clear(); } @@ -461,10 +461,10 @@ namespace CommandSystem outResult = AZStd::string::format("The type is not a valid UUID type. Please use -help or use the command browser to see a list of valid options."); return false; } - if (type != mOldType) + if (type != m_oldType) { AZStd::unique_ptr newParameter(EMotionFX::ParameterFactory::Create(type)); - newParameter->SetName(newName.empty() ? mOldName : newName); + newParameter->SetName(newName.empty() ? m_oldName : newName); newParameter->SetDescription(parameter->GetDescription()); const AZ::Outcome paramIndexRelativeToParent = currentParent ? currentParent->FindRelativeParameterIndex(parameter) : animGraph->FindRelativeParameterIndex(parameter); @@ -472,7 +472,7 @@ namespace CommandSystem if (!animGraph->RemoveParameter(const_cast(parameter))) { - outResult = AZStd::string::format("Could not remove current parameter '%s' to change its type.", mOldName.c_str()); + outResult = AZStd::string::format("Could not remove current parameter '%s' to change its type.", m_oldName.c_str()); return false; } if (!animGraph->InsertParameter(paramIndexRelativeToParent.GetValue(), newParameter.get(), currentParent)) @@ -525,7 +525,7 @@ namespace CommandSystem { EMotionFX::AnimGraphInstance* animGraphInstance = animGraph->GetAnimGraphInstance(i); // reinit the modified parameters - if (mOldType != azrtti_typeid()) + if (m_oldType != azrtti_typeid()) { animGraphInstance->ReInitParameterValue(valueParameterIndex.GetValue()); } @@ -547,7 +547,7 @@ namespace CommandSystem for (EMotionFX::AnimGraphObject* affectedObject : affectedObjects) { EMotionFX::ObjectAffectedByParameterChanges* affectedObjectByParameterChanges = azdynamic_cast(affectedObject); - affectedObjectByParameterChanges->ParameterRenamed(mOldName, newName); + affectedObjectByParameterChanges->ParameterRenamed(m_oldName, newName); } } } @@ -561,16 +561,16 @@ namespace CommandSystem for (EMotionFX::AnimGraphObject* affectedObject : affectedObjects) { EMotionFX::ObjectAffectedByParameterChanges* affectedObjectByParameterChanges = azdynamic_cast(affectedObject); - affectedObjectByParameterChanges->ParameterRemoved(mOldName); + affectedObjectByParameterChanges->ParameterRemoved(m_oldName); affectedObjectByParameterChanges->ParameterAdded(newName); } } // Save the current dirty flag and tell the anim graph that something got changed. - mOldDirtyFlag = animGraph->GetDirtyFlag(); + m_oldDirtyFlag = animGraph->GetDirtyFlag(); animGraph->SetDirtyFlag(true); } - else if (mOldType != azrtti_typeid()) + else if (m_oldType != azrtti_typeid()) { AZ_Assert(oldValueParameterIndex.IsSuccess(), "Unable to find parameter index when changing parameter to a group"); @@ -582,11 +582,11 @@ namespace CommandSystem for (EMotionFX::AnimGraphObject* affectedObject : affectedObjects) { EMotionFX::ObjectAffectedByParameterChanges* affectedObjectByParameterChanges = azdynamic_cast(affectedObject); - affectedObjectByParameterChanges->ParameterRemoved(mOldName); + affectedObjectByParameterChanges->ParameterRemoved(m_oldName); } // Save the current dirty flag and tell the anim graph that something got changed. - mOldDirtyFlag = animGraph->GetDirtyFlag(); + m_oldDirtyFlag = animGraph->GetDirtyFlag(); animGraph->SetDirtyFlag(true); } @@ -638,15 +638,15 @@ namespace CommandSystem animGraph->GetID(), newName.c_str(), name.c_str(), - mOldType.ToString().c_str(), - mOldContents.c_str()); + m_oldType.ToString().c_str(), + m_oldContents.c_str()); if (!GetCommandManager()->ExecuteCommandInsideCommand(commandString, outResult)) { AZ_Error("EMotionFX", false, outResult.c_str()); } - animGraph->SetDirtyFlag(mOldDirtyFlag); + animGraph->SetDirtyFlag(m_oldDirtyFlag); return true; } @@ -728,13 +728,13 @@ namespace CommandSystem const EMotionFX::GroupParameter* currentParent = animGraph->FindParentGroupParameter(parameter); if (currentParent) { - mOldParent = currentParent->GetName(); - mOldIndex = currentParent->FindRelativeParameterIndex(parameter).GetValue(); + m_oldParent = currentParent->GetName(); + m_oldIndex = currentParent->FindRelativeParameterIndex(parameter).GetValue(); } else { - mOldParent.clear(); // means the root - mOldIndex = animGraph->FindRelativeParameterIndex(parameter).GetValue(); + m_oldParent.clear(); // means the root + m_oldIndex = animGraph->FindRelativeParameterIndex(parameter).GetValue(); } EMotionFX::ValueParameterVector valueParametersBeforeChange = animGraph->RecursivelyGetValueParameters(); @@ -789,7 +789,7 @@ namespace CommandSystem } // Save the current dirty flag and tell the anim graph that something got changed. - mOldDirtyFlag = animGraph->GetDirtyFlag(); + m_oldDirtyFlag = animGraph->GetDirtyFlag(); animGraph->SetDirtyFlag(true); return true; @@ -813,10 +813,10 @@ namespace CommandSystem AZStd::string commandString = AZStd::string::format("AnimGraphMoveParameter -animGraphID %i -name \"%s\" -index %zu", animGraphID, name.c_str(), - mOldIndex); - if (!mOldParent.empty()) + m_oldIndex); + if (!m_oldParent.empty()) { - commandString += AZStd::string::format(" -parent \"%s\"", mOldParent.c_str()); + commandString += AZStd::string::format(" -parent \"%s\"", m_oldParent.c_str()); } if (!GetCommandManager()->ExecuteCommandInsideCommand(commandString, outResult)) @@ -825,7 +825,7 @@ namespace CommandSystem return false; } - animGraph->SetDirtyFlag(mOldDirtyFlag); + animGraph->SetDirtyFlag(m_oldDirtyFlag); return true; } diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphParameterCommands.h b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphParameterCommands.h index f93a93d0f9..b1adbcbbab 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphParameterCommands.h +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/AnimGraphParameterCommands.h @@ -22,35 +22,35 @@ namespace CommandSystem { // Create a new anim graph parameter. MCORE_DEFINECOMMAND_START(CommandAnimGraphCreateParameter, "Create an anim graph parameter", true) - bool mOldDirtyFlag; + bool m_oldDirtyFlag; MCORE_DEFINECOMMAND_END // Remove a given anim graph parameter. MCORE_DEFINECOMMAND_START(CommandAnimGraphRemoveParameter, "Remove an anim graph parameter", true) - size_t mIndex; - AZ::TypeId mType; - AZStd::string mName; - AZStd::string mContents; - AZStd::string mParent; - bool mOldDirtyFlag; + size_t m_index; + AZ::TypeId m_type; + AZStd::string m_name; + AZStd::string m_contents; + AZStd::string m_parent; + bool m_oldDirtyFlag; MCORE_DEFINECOMMAND_END // Adjust a given anim graph parameter. MCORE_DEFINECOMMAND_START(CommandAnimGraphAdjustParameter, "Adjust an anim graph parameter", true) - AZ::TypeId mOldType; - AZStd::string mOldName; - AZStd::string mOldContents; - bool mOldDirtyFlag; + AZ::TypeId m_oldType; + AZStd::string m_oldName; + AZStd::string m_oldContents; + bool m_oldDirtyFlag; MCORE_DEFINECOMMAND_END // Move the parameter to another position. MCORE_DEFINECOMMAND_START(CommandAnimGraphMoveParameter, "Move an anim graph parameter", true) - AZStd::string mOldParent; - size_t mOldIndex; - bool mOldDirtyFlag; + AZStd::string m_oldParent; + size_t m_oldIndex; + bool m_oldDirtyFlag; MCORE_DEFINECOMMAND_END ////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -59,18 +59,18 @@ namespace CommandSystem struct COMMANDSYSTEM_API ParameterConnectionItem { - void SetParameterNodeName(const char* name) { mParameterNodeNameID = MCore::GetStringIdPool().GenerateIdForString(name); } - void SetTargetNodeName(const char* name) { mTargetNodeNameID = MCore::GetStringIdPool().GenerateIdForString(name); } - void SetParameterName(const char* name) { mParameterNameID = MCore::GetStringIdPool().GenerateIdForString(name); } + void SetParameterNodeName(const char* name) { m_parameterNodeNameId = MCore::GetStringIdPool().GenerateIdForString(name); } + void SetTargetNodeName(const char* name) { m_targetNodeNameId = MCore::GetStringIdPool().GenerateIdForString(name); } + void SetParameterName(const char* name) { m_parameterNameId = MCore::GetStringIdPool().GenerateIdForString(name); } - const char* GetParameterNodeName() const { return MCore::GetStringIdPool().GetName(mParameterNodeNameID).c_str(); } - const char* GetTargetNodeName() const { return MCore::GetStringIdPool().GetName(mTargetNodeNameID).c_str(); } - const char* GetParameterName() const { return MCore::GetStringIdPool().GetName(mParameterNameID).c_str(); } + const char* GetParameterNodeName() const { return MCore::GetStringIdPool().GetName(m_parameterNodeNameId).c_str(); } + const char* GetTargetNodeName() const { return MCore::GetStringIdPool().GetName(m_targetNodeNameId).c_str(); } + const char* GetParameterName() const { return MCore::GetStringIdPool().GetName(m_parameterNameId).c_str(); } private: - uint32 mParameterNodeNameID; - uint32 mTargetNodeNameID; - uint32 mParameterNameID; + uint32 m_parameterNodeNameId; + uint32 m_targetNodeNameId; + uint32 m_parameterNameId; }; COMMANDSYSTEM_API void RemoveConnectionsForParameter(EMotionFX::AnimGraph* animGraph, const char* parameterName, MCore::CommandGroup& commandGroup); diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/CommandManager.cpp b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/CommandManager.cpp index 893fea2224..be4626f592 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/CommandManager.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/CommandManager.cpp @@ -147,8 +147,8 @@ namespace CommandSystem RegisterCommand(new CommandRecorderClear()); gCommandManager = this; - mLockSelection = false; - mWorkspaceDirtyFlag = false; + m_lockSelection = false; + m_workspaceDirtyFlag = false; } CommandManager::~CommandManager() diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/CommandManager.h b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/CommandManager.h index b2c6986297..8fe7e05895 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/CommandManager.h +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/CommandManager.h @@ -33,28 +33,28 @@ namespace CommandSystem * Get current selection. * @return The selection list containing all selected actors, motions and nodes. */ - MCORE_INLINE SelectionList& GetCurrentSelection() { mCurrentSelection.MakeValid(); return mCurrentSelection; } + MCORE_INLINE SelectionList& GetCurrentSelection() { m_currentSelection.MakeValid(); return m_currentSelection; } /** * Set current selection. * @param selection The selection list containing all selected actors, motions and nodes. */ - MCORE_INLINE void SetCurrentSelection(SelectionList& selection) { mCurrentSelection.Clear(); mCurrentSelection.Add(selection); } + MCORE_INLINE void SetCurrentSelection(SelectionList& selection) { m_currentSelection.Clear(); m_currentSelection.Add(selection); } - MCORE_INLINE bool GetLockSelection() const { return mLockSelection; } - void SetLockSelection(bool lockSelection) { mLockSelection = lockSelection; } + MCORE_INLINE bool GetLockSelection() const { return m_lockSelection; } + void SetLockSelection(bool lockSelection) { m_lockSelection = lockSelection; } - void SetWorkspaceDirtyFlag(bool dirty) { mWorkspaceDirtyFlag = dirty; } - MCORE_INLINE bool GetWorkspaceDirtyFlag() const { return mWorkspaceDirtyFlag; } + void SetWorkspaceDirtyFlag(bool dirty) { m_workspaceDirtyFlag = dirty; } + MCORE_INLINE bool GetWorkspaceDirtyFlag() const { return m_workspaceDirtyFlag; } // Only true when user create or open a workspace. void SetUserOpenedWorkspaceFlag(bool flag); bool GetUserOpenedWorkspaceFlag() const { return m_userOpenedWorkspaceFlag; } private: - SelectionList mCurrentSelection; /**< The current selected actors, motions and nodes. */ - bool mLockSelection; - bool mWorkspaceDirtyFlag; + SelectionList m_currentSelection; /**< The current selected actors, motions and nodes. */ + bool m_lockSelection; + bool m_workspaceDirtyFlag; bool m_userOpenedWorkspaceFlag = false; }; diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ImporterCommands.cpp b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ImporterCommands.cpp index b86c23677c..168de93e38 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ImporterCommands.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ImporterCommands.cpp @@ -29,7 +29,7 @@ namespace CommandSystem CommandImportActor::CommandImportActor(MCore::Command* orgCommand) : MCore::Command("ImportActor", orgCommand) { - mPreviouslyUsedID = MCORE_INVALIDINDEX32; + m_previouslyUsedId = MCORE_INVALIDINDEX32; } @@ -77,10 +77,10 @@ namespace CommandSystem EMotionFX::Importer::ActorSettings settings; // extract default values from the command syntax automatically, if they aren't specified explicitly - settings.mLoadLimits = parameters.GetValueAsBool("loadLimits", this); - settings.mLoadMorphTargets = parameters.GetValueAsBool("loadMorphTargets", this); - settings.mLoadSkeletalLODs = parameters.GetValueAsBool("loadSkeletalLODs", this); - settings.mDualQuatSkinning = parameters.GetValueAsBool("dualQuatSkinning", this); + settings.m_loadLimits = parameters.GetValueAsBool("loadLimits", this); + settings.m_loadMorphTargets = parameters.GetValueAsBool("loadMorphTargets", this); + settings.m_loadSkeletalLoDs = parameters.GetValueAsBool("loadSkeletalLODs", this); + settings.m_dualQuatSkinning = parameters.GetValueAsBool("dualQuatSkinning", this); // try to load the actor AZStd::shared_ptr actor {EMotionFX::GetImporter().LoadActor(filename.c_str(), &settings)}; @@ -101,11 +101,11 @@ namespace CommandSystem } // in case we are in a redo call assign the previously used id - if (mPreviouslyUsedID != MCORE_INVALIDINDEX32) + if (m_previouslyUsedId != MCORE_INVALIDINDEX32) { - actor->SetID(mPreviouslyUsedID); + actor->SetID(m_previouslyUsedId); } - mPreviouslyUsedID = actor->GetID(); + m_previouslyUsedId = actor->GetID(); // select the actor automatically if (parameters.GetValueAsBool("autoSelect", this)) @@ -115,7 +115,7 @@ namespace CommandSystem // mark the workspace as dirty - mOldWorkspaceDirtyFlag = GetCommandManager()->GetWorkspaceDirtyFlag(); + m_oldWorkspaceDirtyFlag = GetCommandManager()->GetWorkspaceDirtyFlag(); GetCommandManager()->SetWorkspaceDirtyFlag(true); // return the id of the newly created actor @@ -134,7 +134,7 @@ namespace CommandSystem uint32 actorID = parameters.GetValueAsInt("actorID", MCORE_INVALIDINDEX32); if (actorID == MCORE_INVALIDINDEX32) { - actorID = mPreviouslyUsedID; + actorID = m_previouslyUsedId; } // check if we have to unselect the actors created by this command @@ -159,7 +159,7 @@ namespace CommandSystem GetCommandManager()->ExecuteCommandInsideCommand("UpdateRenderActors", updateRenderActorsResult); // restore the workspace dirty flag - GetCommandManager()->SetWorkspaceDirtyFlag(mOldWorkspaceDirtyFlag); + GetCommandManager()->SetWorkspaceDirtyFlag(m_oldWorkspaceDirtyFlag); return true; } @@ -203,7 +203,7 @@ namespace CommandSystem CommandImportMotion::CommandImportMotion(MCore::Command* orgCommand) : MCore::Command("ImportMotion", orgCommand) { - mOldMotionID = MCORE_INVALIDINDEX32; + m_oldMotionId = MCORE_INVALIDINDEX32; } @@ -255,7 +255,7 @@ namespace CommandSystem if (AzFramework::StringFunc::Equal(extension.c_str(), "motion", false /* no case */)) { EMotionFX::Importer::MotionSettings settings; - settings.mLoadMotionEvents = parameters.GetValueAsBool("loadMotionEvents", this); + settings.m_loadMotionEvents = parameters.GetValueAsBool("loadMotionEvents", this); motion = EMotionFX::GetImporter().LoadMotion(filename.c_str(), &settings); } @@ -273,12 +273,12 @@ namespace CommandSystem } // in case we are in a redo call assign the previously used id - if (mOldMotionID != MCORE_INVALIDINDEX32) + if (m_oldMotionId != MCORE_INVALIDINDEX32) { - motion->SetID(mOldMotionID); + motion->SetID(m_oldMotionId); } - mOldMotionID = motion->GetID(); - mOldFileName = motion->GetFileName(); + m_oldMotionId = motion->GetID(); + m_oldFileName = motion->GetFileName(); // set the motion name AZStd::string motionName; @@ -292,7 +292,7 @@ namespace CommandSystem } // mark the workspace as dirty - mOldWorkspaceDirtyFlag = GetCommandManager()->GetWorkspaceDirtyFlag(); + m_oldWorkspaceDirtyFlag = GetCommandManager()->GetWorkspaceDirtyFlag(); GetCommandManager()->SetWorkspaceDirtyFlag(true); // reset the dirty flag @@ -308,11 +308,11 @@ namespace CommandSystem // execute the group command AZStd::string commandString; - commandString = AZStd::string::format("RemoveMotion -filename \"%s\"", mOldFileName.c_str()); + commandString = AZStd::string::format("RemoveMotion -filename \"%s\"", m_oldFileName.c_str()); bool result = GetCommandManager()->ExecuteCommandInsideCommand(commandString.c_str(), outResult); // restore the workspace dirty flag - GetCommandManager()->SetWorkspaceDirtyFlag(mOldWorkspaceDirtyFlag); + GetCommandManager()->SetWorkspaceDirtyFlag(m_oldWorkspaceDirtyFlag); return result; } diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ImporterCommands.h b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ImporterCommands.h index 9eb27a06f6..6e8f4728c7 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ImporterCommands.h +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ImporterCommands.h @@ -21,17 +21,17 @@ namespace CommandSystem // add actor MCORE_DEFINECOMMAND_START(CommandImportActor, "Import actor", true) public: - uint32 mPreviouslyUsedID; - uint32 mOldIndex; - bool mOldWorkspaceDirtyFlag; + uint32 m_previouslyUsedId; + uint32 m_oldIndex; + bool m_oldWorkspaceDirtyFlag; MCORE_DEFINECOMMAND_END // add motion MCORE_DEFINECOMMAND_START(CommandImportMotion, "Import motion", true) public: - uint32 mOldMotionID; - AZStd::string mOldFileName; - bool mOldWorkspaceDirtyFlag; + uint32 m_oldMotionId; + AZStd::string m_oldFileName; + bool m_oldWorkspaceDirtyFlag; MCORE_DEFINECOMMAND_END } // namespace CommandSystem diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MetaData.cpp b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MetaData.cpp index aade6e8358..9a0913a5db 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MetaData.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MetaData.cpp @@ -153,7 +153,7 @@ namespace CommandSystem for (uint32 i = 0; i < actor->GetNumNodes(); ++i) { const EMotionFX::Actor::NodeMirrorInfo& mirrorInfo = actor->GetNodeMirrorInfo(i); - uint16 sourceNode = mirrorInfo.mSourceNode; + uint16 sourceNode = mirrorInfo.m_sourceNode; if (sourceNode != MCORE_INVALIDINDEX16 && sourceNode != static_cast(i)) { outMetaDataString += actor->GetSkeleton()->GetNode(i)->GetNameString(); diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MorphTargetCommands.cpp b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MorphTargetCommands.cpp index 0abec28850..0a48952bfc 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MorphTargetCommands.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MorphTargetCommands.cpp @@ -122,7 +122,7 @@ namespace CommandSystem if (parameters.CheckIfHasParameter("weight") && morphTargetInstance) { const float value = parameters.GetValueAsFloat("weight", this); - mOldWeight = morphTargetInstance->GetWeight(); + m_oldWeight = morphTargetInstance->GetWeight(); morphTargetInstance->SetWeight(value); } @@ -130,7 +130,7 @@ namespace CommandSystem if (parameters.CheckIfHasParameter("manualMode") && morphTargetInstance) { const bool value = parameters.GetValueAsBool("manualMode", this); - mOldManualModeEnabled = morphTargetInstance->GetIsInManualMode(); + m_oldManualModeEnabled = morphTargetInstance->GetIsInManualMode(); morphTargetInstance->SetManualMode(value); } @@ -138,7 +138,7 @@ namespace CommandSystem if (parameters.CheckIfHasParameter("rangeMin") && morphTarget) { const float value = parameters.GetValueAsFloat("rangeMin", this); - mOldRangeMin = morphTarget->GetRangeMin(); + m_oldRangeMin = morphTarget->GetRangeMin(); morphTarget->SetRangeMin(value); } @@ -146,7 +146,7 @@ namespace CommandSystem if (parameters.CheckIfHasParameter("rangeMax") && morphTarget) { const float value = parameters.GetValueAsFloat("rangeMax", this); - mOldRangeMax = morphTarget->GetRangeMax(); + m_oldRangeMax = morphTarget->GetRangeMax(); morphTarget->SetRangeMax(value); } @@ -159,7 +159,7 @@ namespace CommandSystem parameters.GetValue("phonemeSets", this, &phonemeSetsString); // store old phoneme sets - mOldPhonemeSets = morphTarget->GetPhonemeSets(); + m_oldPhonemeSets = morphTarget->GetPhonemeSets(); // remove the phoneme set if (AzFramework::StringFunc::Equal(valueString.c_str(), "remove", false /* no case */)) @@ -203,7 +203,7 @@ namespace CommandSystem } // save the current dirty flag and tell the actor that something got changed - mOldDirtyFlag = actor->GetDirtyFlag(); + m_oldDirtyFlag = actor->GetDirtyFlag(); actor->SetDirtyFlag(true); return true; } @@ -240,35 +240,35 @@ namespace CommandSystem // set the old weight of the morph target if (parameters.CheckIfHasParameter("weight") && morphTargetInstance) { - morphTargetInstance->SetWeight(mOldWeight); + morphTargetInstance->SetWeight(m_oldWeight); } // set the old manual mode if (parameters.CheckIfHasParameter("manualMode") && morphTargetInstance) { - morphTargetInstance->SetManualMode(mOldManualModeEnabled); + morphTargetInstance->SetManualMode(m_oldManualModeEnabled); } // set the old range min if (parameters.CheckIfHasParameter("rangeMin") && morphTarget) { - morphTarget->SetRangeMin(mOldRangeMin); + morphTarget->SetRangeMin(m_oldRangeMin); } // set the old range max if (parameters.CheckIfHasParameter("rangeMax") && morphTarget) { - morphTarget->SetRangeMax(mOldRangeMax); + morphTarget->SetRangeMax(m_oldRangeMax); } // set the old phoneme sets if (parameters.CheckIfHasParameter("phonemeAction") && morphTarget) { - morphTarget->SetPhonemeSets(mOldPhonemeSets); + morphTarget->SetPhonemeSets(m_oldPhonemeSets); } // set the dirty flag back to the old value - actor->SetDirtyFlag(mOldDirtyFlag); + actor->SetDirtyFlag(m_oldDirtyFlag); return true; } diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MorphTargetCommands.h b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MorphTargetCommands.h index 4ab06fe827..2ae284e907 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MorphTargetCommands.h +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MorphTargetCommands.h @@ -20,12 +20,12 @@ namespace CommandSystem { // adjust a given morph target of an actor MCORE_DEFINECOMMAND_START(CommandAdjustMorphTarget, "Adjust morph target", true) - float mOldWeight; - float mOldRangeMin; - float mOldRangeMax; - bool mOldManualModeEnabled; - EMotionFX::MorphTarget::EPhonemeSet mOldPhonemeSets; - bool mOldDirtyFlag; + float m_oldWeight; + float m_oldRangeMin; + float m_oldRangeMax; + bool m_oldManualModeEnabled; + EMotionFX::MorphTarget::EPhonemeSet m_oldPhonemeSets; + bool m_oldDirtyFlag; bool GetMorphTarget(EMotionFX::Actor* actor, EMotionFX::ActorInstance* actorInstance, uint32 lodLevel, const char* morphTargetName, EMotionFX::MorphTarget** outMorphTarget, EMotionFX::MorphSetupInstance::MorphTarget** outMorphTargetInstance, AZStd::string& outResult); MCORE_DEFINECOMMAND_END diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MotionCommands.cpp b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MotionCommands.cpp index 677b4ec5ff..2bec066549 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MotionCommands.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MotionCommands.cpp @@ -79,27 +79,27 @@ namespace CommandSystem AZStd::string CommandPlayMotion::PlayBackInfoToCommandParameters(const EMotionFX::PlayBackInfo* playbackInfo) { return AZStd::string::format("-blendInTime %f -blendOutTime %f -playSpeed %f -targetWeight %f -eventWeightThreshold %f -maxPlayTime %f -numLoops %i -priorityLevel %i -blendMode %i -playMode %i -mirrorMotion %s -mix %s -playNow %s -motionExtraction %s -retarget %s -freezeAtLastFrame %s -enableMotionEvents %s -blendOutBeforeEnded %s -canOverwrite %s -deleteOnZeroWeight %s -inPlace %s", - playbackInfo->mBlendInTime, - playbackInfo->mBlendOutTime, - playbackInfo->mPlaySpeed, - playbackInfo->mTargetWeight, - playbackInfo->mEventWeightThreshold, - playbackInfo->mMaxPlayTime, - playbackInfo->mNumLoops, - playbackInfo->mPriorityLevel, - static_cast(playbackInfo->mBlendMode), - static_cast(playbackInfo->mPlayMode), - AZStd::to_string(playbackInfo->mMirrorMotion).c_str(), - AZStd::to_string(playbackInfo->mMix).c_str(), - AZStd::to_string(playbackInfo->mPlayNow).c_str(), - AZStd::to_string(playbackInfo->mMotionExtractionEnabled).c_str(), - AZStd::to_string(playbackInfo->mRetarget).c_str(), - AZStd::to_string(playbackInfo->mFreezeAtLastFrame).c_str(), - AZStd::to_string(playbackInfo->mEnableMotionEvents).c_str(), - AZStd::to_string(playbackInfo->mBlendOutBeforeEnded).c_str(), - AZStd::to_string(playbackInfo->mCanOverwrite).c_str(), - AZStd::to_string(playbackInfo->mDeleteOnZeroWeight).c_str(), - AZStd::to_string(playbackInfo->mInPlace).c_str()); + playbackInfo->m_blendInTime, + playbackInfo->m_blendOutTime, + playbackInfo->m_playSpeed, + playbackInfo->m_targetWeight, + playbackInfo->m_eventWeightThreshold, + playbackInfo->m_maxPlayTime, + playbackInfo->m_numLoops, + playbackInfo->m_priorityLevel, + static_cast(playbackInfo->m_blendMode), + static_cast(playbackInfo->m_playMode), + AZStd::to_string(playbackInfo->m_mirrorMotion).c_str(), + AZStd::to_string(playbackInfo->m_mix).c_str(), + AZStd::to_string(playbackInfo->m_playNow).c_str(), + AZStd::to_string(playbackInfo->m_motionExtractionEnabled).c_str(), + AZStd::to_string(playbackInfo->m_retarget).c_str(), + AZStd::to_string(playbackInfo->m_freezeAtLastFrame).c_str(), + AZStd::to_string(playbackInfo->m_enableMotionEvents).c_str(), + AZStd::to_string(playbackInfo->m_blendOutBeforeEnded).c_str(), + AZStd::to_string(playbackInfo->m_canOverwrite).c_str(), + AZStd::to_string(playbackInfo->m_deleteOnZeroWeight).c_str(), + AZStd::to_string(playbackInfo->m_inPlace).c_str()); } @@ -108,87 +108,87 @@ namespace CommandSystem { if (parameters.CheckIfHasParameter("blendInTime") == true) { - outPlaybackInfo->mBlendInTime = parameters.GetValueAsFloat("blendInTime", command); + outPlaybackInfo->m_blendInTime = parameters.GetValueAsFloat("blendInTime", command); } if (parameters.CheckIfHasParameter("blendOutTime")) { - outPlaybackInfo->mBlendOutTime = parameters.GetValueAsFloat("blendOutTime", command); + outPlaybackInfo->m_blendOutTime = parameters.GetValueAsFloat("blendOutTime", command); } if (parameters.CheckIfHasParameter("playSpeed")) { - outPlaybackInfo->mPlaySpeed = parameters.GetValueAsFloat("playSpeed", command); + outPlaybackInfo->m_playSpeed = parameters.GetValueAsFloat("playSpeed", command); } if (parameters.CheckIfHasParameter("targetWeight")) { - outPlaybackInfo->mTargetWeight = parameters.GetValueAsFloat("targetWeight", command); + outPlaybackInfo->m_targetWeight = parameters.GetValueAsFloat("targetWeight", command); } if (parameters.CheckIfHasParameter("eventWeightThreshold")) { - outPlaybackInfo->mEventWeightThreshold = parameters.GetValueAsFloat("eventWeightThreshold", command); + outPlaybackInfo->m_eventWeightThreshold = parameters.GetValueAsFloat("eventWeightThreshold", command); } if (parameters.CheckIfHasParameter("maxPlayTime")) { - outPlaybackInfo->mMaxPlayTime = parameters.GetValueAsFloat("maxPlayTime", command); + outPlaybackInfo->m_maxPlayTime = parameters.GetValueAsFloat("maxPlayTime", command); } if (parameters.CheckIfHasParameter("numLoops")) { - outPlaybackInfo->mNumLoops = parameters.GetValueAsInt("numLoops", command); + outPlaybackInfo->m_numLoops = parameters.GetValueAsInt("numLoops", command); } if (parameters.CheckIfHasParameter("priorityLevel")) { - outPlaybackInfo->mPriorityLevel = parameters.GetValueAsInt("priorityLevel", command); + outPlaybackInfo->m_priorityLevel = parameters.GetValueAsInt("priorityLevel", command); } if (parameters.CheckIfHasParameter("blendMode")) { - outPlaybackInfo->mBlendMode = (EMotionFX::EMotionBlendMode)parameters.GetValueAsInt("blendMode", command); + outPlaybackInfo->m_blendMode = (EMotionFX::EMotionBlendMode)parameters.GetValueAsInt("blendMode", command); } if (parameters.CheckIfHasParameter("playMode")) { - outPlaybackInfo->mPlayMode = (EMotionFX::EPlayMode)parameters.GetValueAsInt("playMode", command); + outPlaybackInfo->m_playMode = (EMotionFX::EPlayMode)parameters.GetValueAsInt("playMode", command); } if (parameters.CheckIfHasParameter("mirrorMotion")) { - outPlaybackInfo->mMirrorMotion = parameters.GetValueAsBool("mirrorMotion", command); + outPlaybackInfo->m_mirrorMotion = parameters.GetValueAsBool("mirrorMotion", command); } if (parameters.CheckIfHasParameter("mix")) { - outPlaybackInfo->mMix = parameters.GetValueAsBool("mix", command); + outPlaybackInfo->m_mix = parameters.GetValueAsBool("mix", command); } if (parameters.CheckIfHasParameter("playNow")) { - outPlaybackInfo->mPlayNow = parameters.GetValueAsBool("playNow", command); + outPlaybackInfo->m_playNow = parameters.GetValueAsBool("playNow", command); } if (parameters.CheckIfHasParameter("motionExtraction")) { - outPlaybackInfo->mMotionExtractionEnabled = parameters.GetValueAsBool("motionExtraction", command); + outPlaybackInfo->m_motionExtractionEnabled = parameters.GetValueAsBool("motionExtraction", command); } if (parameters.CheckIfHasParameter("retarget")) { - outPlaybackInfo->mRetarget = parameters.GetValueAsBool("retarget", command); + outPlaybackInfo->m_retarget = parameters.GetValueAsBool("retarget", command); } if (parameters.CheckIfHasParameter("freezeAtLastFrame")) { - outPlaybackInfo->mFreezeAtLastFrame = parameters.GetValueAsBool("freezeAtLastFrame", command); + outPlaybackInfo->m_freezeAtLastFrame = parameters.GetValueAsBool("freezeAtLastFrame", command); } if (parameters.CheckIfHasParameter("enableMotionEvents")) { - outPlaybackInfo->mEnableMotionEvents = parameters.GetValueAsBool("enableMotionEvents", command); + outPlaybackInfo->m_enableMotionEvents = parameters.GetValueAsBool("enableMotionEvents", command); } if (parameters.CheckIfHasParameter("blendOutBeforeEnded")) { - outPlaybackInfo->mBlendOutBeforeEnded = parameters.GetValueAsBool("blendOutBeforeEnded", command); + outPlaybackInfo->m_blendOutBeforeEnded = parameters.GetValueAsBool("blendOutBeforeEnded", command); } if (parameters.CheckIfHasParameter("canOverwrite")) { - outPlaybackInfo->mCanOverwrite = parameters.GetValueAsBool("canOverwrite", command); + outPlaybackInfo->m_canOverwrite = parameters.GetValueAsBool("canOverwrite", command); } if (parameters.CheckIfHasParameter("deleteOnZeroWeight")) { - outPlaybackInfo->mDeleteOnZeroWeight = parameters.GetValueAsBool("deleteOnZeroWeight", command); + outPlaybackInfo->m_deleteOnZeroWeight = parameters.GetValueAsBool("deleteOnZeroWeight", command); } if (parameters.CheckIfHasParameter("inPlace")) { - outPlaybackInfo->mInPlace = parameters.GetValueAsBool("inPlace", command); + outPlaybackInfo->m_inPlace = parameters.GetValueAsBool("inPlace", command); } } @@ -327,7 +327,7 @@ namespace CommandSystem #define SYNTAX_MOTIONCOMMANDS \ GetSyntax().ReserveParameters(30); \ GetSyntax().AddRequiredParameter("filename", "The filename of the motion file to play.", MCore::CommandSyntax::PARAMTYPE_STRING); \ - /*GetSyntax().AddParameter( "mirrorPlaneNormal", "The motion mirror plane normal, which is (1,0,0) on default. This setting is only used when mMirrorMotion is set to true.", MCore::CommandSyntax::PARAMTYPE_VECTOR3, "(1, 0, 0)" );*/ \ + /*GetSyntax().AddParameter( "mirrorPlaneNormal", "The motion mirror plane normal, which is (1,0,0) on default. This setting is only used when mirrorMotion is set to true.", MCore::CommandSyntax::PARAMTYPE_VECTOR3, "(1, 0, 0)" );*/ \ GetSyntax().AddParameter("blendInTime", "The time, in seconds, which it will take to fully have blended to the target weight.", MCore::CommandSyntax::PARAMTYPE_FLOAT, "0.3"); \ GetSyntax().AddParameter("blendOutTime", "The time, in seconds, which it takes to smoothly fadeout the motion, after it has been stopped playing.", MCore::CommandSyntax::PARAMTYPE_FLOAT, "0.3"); \ GetSyntax().AddParameter("playSpeed", "The playback speed factor. A value of 1 stands for the original speed, while for example 2 means twice the original speed.", MCore::CommandSyntax::PARAMTYPE_FLOAT, "1.0"); \ @@ -340,7 +340,7 @@ namespace CommandSystem GetSyntax().AddParameter("retargetRootIndex", "The retargeting root node index.", MCore::CommandSyntax::PARAMTYPE_INT, "0"); \ GetSyntax().AddParameter("blendMode", "The motion blend mode. Please read the MotionInstance::SetBlendMode(...) method for more information.", MCore::CommandSyntax::PARAMTYPE_INT, "0"); /* 4294967296 == MCORE_INVALIDINDEX32 */ \ GetSyntax().AddParameter("playMode", "The motion playback mode. This means forward or backward playback.", MCore::CommandSyntax::PARAMTYPE_INT, "0"); \ - GetSyntax().AddParameter("mirrorMotion", "Is motion mirroring enabled or not? When set to true, the mMirrorPlaneNormal is used as mirroring axis.", MCore::CommandSyntax::PARAMTYPE_BOOLEAN, "false"); \ + GetSyntax().AddParameter("mirrorMotion", "Is motion mirroring enabled or not? When set to true, the mirrorPlaneNormal is used as mirroring axis.", MCore::CommandSyntax::PARAMTYPE_BOOLEAN, "false"); \ GetSyntax().AddParameter("mix", "Set to true if you want this motion to mix or not.", MCore::CommandSyntax::PARAMTYPE_BOOLEAN, "false"); \ GetSyntax().AddParameter("playNow", "Set to true if you want to start playing the motion right away. If set to false it will be scheduled for later by inserting it into the motion queue.", MCore::CommandSyntax::PARAMTYPE_BOOLEAN, "true"); \ GetSyntax().AddParameter("motionExtraction", "Set to true when you want to use motion extraction.", MCore::CommandSyntax::PARAMTYPE_BOOLEAN, "true"); \ @@ -546,13 +546,13 @@ namespace CommandSystem EMotionFX::PlayBackInfo* defaultPlayBackInfo = motion->GetDefaultPlayBackInfo(); // copy the current playback info to the undo data - mOldPlaybackInfo = *defaultPlayBackInfo; + m_oldPlaybackInfo = *defaultPlayBackInfo; // adjust the playback info based on the parameters CommandPlayMotion::CommandParametersToPlaybackInfo(this, parameters, defaultPlayBackInfo); // save the current dirty flag and tell the motion that something got changed - mOldDirtyFlag = motion->GetDirtyFlag(); + m_oldDirtyFlag = motion->GetDirtyFlag(); return true; } @@ -585,10 +585,10 @@ namespace CommandSystem } // copy the saved playback info to the actual one - *defaultPlayBackInfo = mOldPlaybackInfo; + *defaultPlayBackInfo = m_oldPlaybackInfo; // set the dirty flag back to the old value - motion->SetDirtyFlag(mOldDirtyFlag); + motion->SetDirtyFlag(m_oldDirtyFlag); return true; } @@ -614,9 +614,6 @@ namespace CommandSystem // execute bool CommandStopMotionInstances::Execute(const MCore::CommandLine& parameters, AZStd::string& outResult) { - // clear our old data so that we start fresh in case of a redo - //mOldData.Clear(); - // get the number of selected actor instances const size_t numSelectedActorInstances = GetCommandManager()->GetCurrentSelection().GetNumSelectedActorInstances(); @@ -716,9 +713,6 @@ namespace CommandSystem MCORE_UNUSED(parameters); MCORE_UNUSED(outResult); - // clear our old data so that we start fresh in case of a redo - //mOldData.Clear(); - // iterate through all actor instances and stop all selected motion instances const size_t numActorInstances = EMotionFX::GetActorManager().GetNumActorInstances(); for (size_t i = 0; i < numActorInstances; ++i) @@ -823,26 +817,26 @@ namespace CommandSystem // adjust the dirty flag if (m_dirtyFlag) { - mOldDirtyFlag = motion->GetDirtyFlag(); + m_oldDirtyFlag = motion->GetDirtyFlag(); motion->SetDirtyFlag(m_dirtyFlag.value()); } // adjust the name if (m_name) { - mOldName = motion->GetName(); + m_oldName = motion->GetName(); motion->SetName(m_name.value().c_str()); - mOldDirtyFlag = motion->GetDirtyFlag(); + m_oldDirtyFlag = motion->GetDirtyFlag(); motion->SetDirtyFlag(true); } // Adjust the motion extraction flags. if (m_extractionFlags) { - mOldExtractionFlags = motion->GetMotionExtractionFlags(); + m_oldExtractionFlags = motion->GetMotionExtractionFlags(); motion->SetMotionExtractionFlags(m_extractionFlags.value()); - mOldDirtyFlag = motion->GetDirtyFlag(); + m_oldDirtyFlag = motion->GetDirtyFlag(); motion->SetDirtyFlag(true); } @@ -866,20 +860,20 @@ namespace CommandSystem // adjust the dirty flag if (m_dirtyFlag) { - motion->SetDirtyFlag(mOldDirtyFlag); + motion->SetDirtyFlag(m_oldDirtyFlag); } // adjust the name if (m_name) { - motion->SetName(mOldName.c_str()); - motion->SetDirtyFlag(mOldDirtyFlag); + motion->SetName(m_oldName.c_str()); + motion->SetDirtyFlag(m_oldDirtyFlag); } if (m_extractionFlags) { - motion->SetMotionExtractionFlags(mOldExtractionFlags); - motion->SetDirtyFlag(mOldDirtyFlag); + motion->SetMotionExtractionFlags(m_oldExtractionFlags); + motion->SetDirtyFlag(m_oldDirtyFlag); } return true; @@ -933,7 +927,7 @@ namespace CommandSystem CommandRemoveMotion::CommandRemoveMotion(MCore::Command* orgCommand) : MCore::Command("RemoveMotion", orgCommand) { - mOldMotionID = MCORE_INVALIDINDEX32; + m_oldMotionId = MCORE_INVALIDINDEX32; } @@ -992,12 +986,12 @@ namespace CommandSystem GetCommandManager()->ExecuteCommandInsideCommand(commandString, outResult); // store the previously used id and remove the motion - mOldIndex = EMotionFX::GetMotionManager().FindMotionIndex(motion); - mOldMotionID = motion->GetID(); - mOldFileName = motion->GetFileName(); + m_oldIndex = EMotionFX::GetMotionManager().FindMotionIndex(motion); + m_oldMotionId = motion->GetID(); + m_oldFileName = motion->GetFileName(); // mark the workspace as dirty - mOldWorkspaceDirtyFlag = GetCommandManager()->GetWorkspaceDirtyFlag(); + m_oldWorkspaceDirtyFlag = GetCommandManager()->GetWorkspaceDirtyFlag(); GetCommandManager()->SetWorkspaceDirtyFlag(true); EMotionFX::GetMotionManager().RemoveMotionByID(motion->GetID()); @@ -1012,11 +1006,11 @@ namespace CommandSystem // execute the group command AZStd::string commandString; - commandString = AZStd::string::format("ImportMotion -filename \"%s\" -motionID %i", mOldFileName.c_str(), mOldMotionID); + commandString = AZStd::string::format("ImportMotion -filename \"%s\" -motionID %i", m_oldFileName.c_str(), m_oldMotionId); bool result = GetCommandManager()->ExecuteCommandInsideCommand(commandString.c_str(), outResult); // restore the workspace dirty flag - GetCommandManager()->SetWorkspaceDirtyFlag(mOldWorkspaceDirtyFlag); + GetCommandManager()->SetWorkspaceDirtyFlag(m_oldWorkspaceDirtyFlag); return result; } @@ -1045,9 +1039,9 @@ namespace CommandSystem CommandScaleMotionData::CommandScaleMotionData(MCore::Command* orgCommand) : MCore::Command("ScaleMotionData", orgCommand) { - mMotionID = MCORE_INVALIDINDEX32; - mScaleFactor = 1.0f; - mOldDirtyFlag = false; + m_motionId = MCORE_INVALIDINDEX32; + m_scaleFactor = 1.0f; + m_oldDirtyFlag = false; } @@ -1092,29 +1086,29 @@ namespace CommandSystem return false; } - mMotionID = motion->GetID(); - mScaleFactor = parameters.GetValueAsFloat("scaleFactor", 1.0f); + m_motionId = motion->GetID(); + m_scaleFactor = parameters.GetValueAsFloat("scaleFactor", 1.0f); AZStd::string targetUnitTypeString; parameters.GetValue("unitType", this, &targetUnitTypeString); - mUseUnitType = parameters.CheckIfHasParameter("unitType"); + m_useUnitType = parameters.CheckIfHasParameter("unitType"); MCore::Distance::EUnitType targetUnitType; bool stringConvertSuccess = MCore::Distance::StringToUnitType(targetUnitTypeString, &targetUnitType); - if (mUseUnitType && stringConvertSuccess == false) + if (m_useUnitType && stringConvertSuccess == false) { outResult = AZStd::string::format("The passed unitType '%s' is not a valid unit type.", targetUnitTypeString.c_str()); return false; } - mOldUnitType = MCore::Distance::UnitTypeToString(motion->GetUnitType()); + m_oldUnitType = MCore::Distance::UnitTypeToString(motion->GetUnitType()); - mOldDirtyFlag = motion->GetDirtyFlag(); + m_oldDirtyFlag = motion->GetDirtyFlag(); motion->SetDirtyFlag(true); // perform the scaling - if (mUseUnitType == false) + if (m_useUnitType == false) { - motion->Scale(mScaleFactor); + motion->Scale(m_scaleFactor); } else { @@ -1130,23 +1124,23 @@ namespace CommandSystem { MCORE_UNUSED(parameters); - if (mUseUnitType == false) + if (m_useUnitType == false) { AZStd::string commandString; - commandString = AZStd::string::format("ScaleMotionData -id %d -scaleFactor %.8f", mMotionID, 1.0f / mScaleFactor); + commandString = AZStd::string::format("ScaleMotionData -id %d -scaleFactor %.8f", m_motionId, 1.0f / m_scaleFactor); GetCommandManager()->ExecuteCommandInsideCommand(commandString.c_str(), outResult); } else { AZStd::string commandString; - commandString = AZStd::string::format("ScaleMotionData -id %d -unitType \"%s\"", mMotionID, mOldUnitType.c_str()); + commandString = AZStd::string::format("ScaleMotionData -id %d -unitType \"%s\"", m_motionId, m_oldUnitType.c_str()); GetCommandManager()->ExecuteCommandInsideCommand(commandString.c_str(), outResult); } - EMotionFX::Motion* motion = EMotionFX::GetMotionManager().FindMotionByID(mMotionID); + EMotionFX::Motion* motion = EMotionFX::GetMotionManager().FindMotionByID(m_motionId); if (motion) { - motion->SetDirtyFlag(mOldDirtyFlag); + motion->SetDirtyFlag(m_oldDirtyFlag); } return true; diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MotionCommands.h b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MotionCommands.h index 2e68d7b2cc..2a87b11627 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MotionCommands.h +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MotionCommands.h @@ -69,33 +69,33 @@ namespace CommandSystem private: AZStd::optional m_dirtyFlag; - bool mOldDirtyFlag; + bool m_oldDirtyFlag; AZStd::optional m_extractionFlags; - EMotionFX::EMotionExtractionFlags mOldExtractionFlags; + EMotionFX::EMotionExtractionFlags m_oldExtractionFlags; AZStd::optional m_name; - AZStd::string mOldName; - AZStd::string mOldMotionExtractionNodeName; + AZStd::string m_oldName; + AZStd::string m_oldMotionExtractionNodeName; }; // Remove motion command. MCORE_DEFINECOMMAND_START(CommandRemoveMotion, "Remove motion", true) public: - uint32 mOldMotionID; - AZStd::string mOldFileName; - size_t mOldIndex; - bool mOldWorkspaceDirtyFlag; + uint32 m_oldMotionId; + AZStd::string m_oldFileName; + size_t m_oldIndex; + bool m_oldWorkspaceDirtyFlag; MCORE_DEFINECOMMAND_END // Scale motion data. MCORE_DEFINECOMMAND_START(CommandScaleMotionData, "Scale motion data", true) public: - AZStd::string mOldUnitType; - uint32 mMotionID; - float mScaleFactor; - bool mOldDirtyFlag; - bool mUseUnitType; + AZStd::string m_oldUnitType; + uint32 m_motionId; + float m_scaleFactor; + bool m_oldDirtyFlag; + bool m_useUnitType; MCORE_DEFINECOMMAND_END @@ -129,8 +129,8 @@ namespace CommandSystem // Adjust default playback info command. MCORE_DEFINECOMMAND_START(CommandAdjustDefaultPlayBackInfo, "Adjust default playback info", true) - EMotionFX::PlayBackInfo mOldPlaybackInfo; - bool mOldDirtyFlag; + EMotionFX::PlayBackInfo m_oldPlaybackInfo; + bool m_oldDirtyFlag; MCORE_DEFINECOMMAND_END diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MotionEventCommands.cpp b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MotionEventCommands.cpp index b1d896ccd4..7c02972b78 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MotionEventCommands.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MotionEventCommands.cpp @@ -293,7 +293,7 @@ namespace CommandSystem CommandRemoveMotionEventTrack::CommandRemoveMotionEventTrack(MCore::Command* orgCommand) : MCore::Command("RemoveMotionEventTrack", orgCommand) { - mOldTrackIndex = InvalidIndex; + m_oldTrackIndex = InvalidIndex; } @@ -332,8 +332,8 @@ namespace CommandSystem } // store information for undo - mOldTrackIndex = eventTrackIndex.GetValue(); - mOldEnabled = eventTable->GetTrack(eventTrackIndex.GetValue())->GetIsEnabled(); + m_oldTrackIndex = eventTrackIndex.GetValue(); + m_oldEnabled = eventTable->GetTrack(eventTrackIndex.GetValue())->GetIsEnabled(); // remove the motion event track eventTable->RemoveTrack(eventTrackIndex.GetValue()); @@ -353,7 +353,7 @@ namespace CommandSystem const int32 motionID = parameters.GetValueAsInt("motionID", this); AZStd::string command; - command = AZStd::string::format("CreateMotionEventTrack -motionID %i -eventTrackName \"%s\" -index %zu -enabled %s", motionID, eventTrackName.c_str(), mOldTrackIndex, mOldEnabled ? "true" : "false"); + command = AZStd::string::format("CreateMotionEventTrack -motionID %i -eventTrackName \"%s\" -index %zu -enabled %s", motionID, eventTrackName.c_str(), m_oldTrackIndex, m_oldEnabled ? "true" : "false"); return GetCommandManager()->ExecuteCommandInsideCommand(command.c_str(), outResult); } @@ -586,9 +586,9 @@ namespace CommandSystem } // add the motion event and check if everything worked fine - mMotionEventNr = eventTrack->AddEvent(m_startTime, m_endTime, m_eventDatas.value_or(EMotionFX::EventDataSet())); + m_motionEventNr = eventTrack->AddEvent(m_startTime, m_endTime, m_eventDatas.value_or(EMotionFX::EventDataSet())); - if (mMotionEventNr == InvalidIndex) + if (m_motionEventNr == InvalidIndex) { outResult = AZStd::string::format("Cannot create motion event. The returned motion event index is not valid."); return false; @@ -604,7 +604,7 @@ namespace CommandSystem { AZ_UNUSED(parameters); - const AZStd::string command = AZStd::string::format("RemoveMotionEvent -motionID %i -eventTrackName \"%s\" -eventNr %zu", m_motionID, m_eventTrackName.c_str(), mMotionEventNr); + const AZStd::string command = AZStd::string::format("RemoveMotionEvent -motionID %i -eventTrackName \"%s\" -eventNr %zu", m_motionID, m_eventTrackName.c_str(), m_motionEventNr); return GetCommandManager()->ExecuteCommandInsideCommand(command.c_str(), outResult); } @@ -700,8 +700,8 @@ namespace CommandSystem // get the motion event and store the old values of the motion event for undo const EMotionFX::MotionEvent& motionEvent = eventTrack->GetEvent(eventNr); - mOldStartTime = motionEvent.GetStartTime(); - mOldEndTime = motionEvent.GetEndTime(); + m_oldStartTime = motionEvent.GetStartTime(); + m_oldEndTime = motionEvent.GetEndTime(); m_oldEventDatas = motionEvent.GetEventDatas(); // remove the motion event @@ -728,7 +728,7 @@ namespace CommandSystem } MCore::CommandGroup commandGroup; - CommandHelperAddMotionEvent(motion, eventTrackName.c_str(), mOldStartTime, mOldEndTime, m_oldEventDatas, &commandGroup); + CommandHelperAddMotionEvent(motion, eventTrackName.c_str(), m_oldStartTime, m_oldEndTime, m_oldEventDatas, &commandGroup); return GetCommandManager()->ExecuteCommandGroupInsideCommand(commandGroup, outResult); } diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MotionEventCommands.h b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MotionEventCommands.h index 629e1e72c5..54dce0fca6 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MotionEventCommands.h +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MotionEventCommands.h @@ -60,8 +60,8 @@ namespace CommandSystem }; MCORE_DEFINECOMMAND_START(CommandRemoveMotionEventTrack, "Remove motion event track", true) - size_t mOldTrackIndex; - bool mOldEnabled; + size_t m_oldTrackIndex; + bool m_oldEnabled; MCORE_DEFINECOMMAND_END class DEFINECOMMAND_API CommandAdjustMotionEventTrack @@ -151,12 +151,12 @@ namespace CommandSystem AZStd::optional m_eventDatas; float m_startTime = 0.0f; float m_endTime = 0.0f; - size_t mMotionEventNr; + size_t m_motionEventNr; }; MCORE_DEFINECOMMAND_START(CommandRemoveMotionEvent, "Remove motion event", true) - float mOldStartTime; - float mOldEndTime; + float m_oldStartTime; + float m_oldEndTime; EMotionFX::EventDataSet m_oldEventDatas; MCORE_DEFINECOMMAND_END diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MotionSetCommands.cpp b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MotionSetCommands.cpp index 051a0e0797..c3d9a88471 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MotionSetCommands.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MotionSetCommands.cpp @@ -68,7 +68,7 @@ namespace CommandSystem CommandCreateMotionSet::CommandCreateMotionSet(MCore::Command* orgCommand) : MCore::Command("CreateMotionSet", orgCommand) { - mPreviouslyUsedID = MCORE_INVALIDINDEX32; + m_previouslyUsedId = MCORE_INVALIDINDEX32; } @@ -130,9 +130,9 @@ namespace CommandSystem } // In case of redoing the command set the previously used id. - if (mPreviouslyUsedID != MCORE_INVALIDINDEX32) + if (m_previouslyUsedId != MCORE_INVALIDINDEX32) { - motionSet->SetID(mPreviouslyUsedID); + motionSet->SetID(m_previouslyUsedId); } // Set the filename. @@ -145,14 +145,14 @@ namespace CommandSystem } // Store info for undo. - mPreviouslyUsedID = motionSet->GetID(); - AZStd::to_string(outResult, mPreviouslyUsedID); + m_previouslyUsedId = motionSet->GetID(); + AZStd::to_string(outResult, m_previouslyUsedId); // Set the motion set callback for custom motion loading. motionSet->SetCallback(aznew CommandSystemMotionSetCallback(motionSet), true); // Set the dirty flag. - const AZStd::string commandString = AZStd::string::format("AdjustMotionSet -motionSetID %i -dirtyFlag true", mPreviouslyUsedID); + const AZStd::string commandString = AZStd::string::format("AdjustMotionSet -motionSetID %i -dirtyFlag true", m_previouslyUsedId); GetCommandManager()->ExecuteCommandInsideCommand(commandString, outResult); // Seturn the id of the newly created motion set. @@ -176,7 +176,7 @@ namespace CommandSystem EMotionFX::GetAnimGraphManager().InvalidateInstanceUniqueDataUsingMotionSet(motionSet); // Mark the workspace as dirty - mOldWorkspaceDirtyFlag = GetCommandManager()->GetWorkspaceDirtyFlag(); + m_oldWorkspaceDirtyFlag = GetCommandManager()->GetWorkspaceDirtyFlag(); GetCommandManager()->SetWorkspaceDirtyFlag(true); return true; } @@ -186,11 +186,11 @@ namespace CommandSystem { MCORE_UNUSED(parameters); - const AZStd::string commandString = AZStd::string::format("RemoveMotionSet -motionSetID %i", mPreviouslyUsedID); + const AZStd::string commandString = AZStd::string::format("RemoveMotionSet -motionSetID %i", m_previouslyUsedId); bool result = GetCommandManager()->ExecuteCommandInsideCommand(commandString, outResult); // Restore the workspace dirty flag. - GetCommandManager()->SetWorkspaceDirtyFlag(mOldWorkspaceDirtyFlag); + GetCommandManager()->SetWorkspaceDirtyFlag(m_oldWorkspaceDirtyFlag); return result; } @@ -218,7 +218,7 @@ namespace CommandSystem CommandRemoveMotionSet::CommandRemoveMotionSet(MCore::Command* orgCommand) : MCore::Command("RemoveMotionSet", orgCommand) { - mPreviouslyUsedID = MCORE_INVALIDINDEX32; + m_previouslyUsedId = MCORE_INVALIDINDEX32; } @@ -240,20 +240,20 @@ namespace CommandSystem } // Store information used by undo. - mPreviouslyUsedID = motionSet->GetID(); - mOldName = motionSet->GetName(); - mOldFileName = motionSet->GetFilename(); + m_previouslyUsedId = motionSet->GetID(); + m_oldName = motionSet->GetName(); + m_oldFileName = motionSet->GetFilename(); if (!motionSet->GetParentSet()) { - mOldParentSetID = MCORE_INVALIDINDEX32; + m_oldParentSetId = MCORE_INVALIDINDEX32; } else { - mOldParentSetID = motionSet->GetParentSet()->GetID(); + m_oldParentSetId = motionSet->GetParentSet()->GetID(); // Set the dirty flag on the parent. - const AZStd::string commandString = AZStd::string::format("AdjustMotionSet -motionSetID %i -dirtyFlag true", mOldParentSetID); + const AZStd::string commandString = AZStd::string::format("AdjustMotionSet -motionSetID %i -dirtyFlag true", m_oldParentSetId); GetCommandManager()->ExecuteCommandInsideCommand(commandString, outResult); } @@ -280,7 +280,7 @@ namespace CommandSystem } // Mark the workspace as dirty. - mOldWorkspaceDirtyFlag = GetCommandManager()->GetWorkspaceDirtyFlag(); + m_oldWorkspaceDirtyFlag = GetCommandManager()->GetWorkspaceDirtyFlag(); GetCommandManager()->SetWorkspaceDirtyFlag(true); return true; @@ -291,22 +291,22 @@ namespace CommandSystem { MCORE_UNUSED(parameters); - AZStd::string commandString = AZStd::string::format("CreateMotionSet -name \"%s\" -motionSetID %i", mOldName.c_str(), mPreviouslyUsedID); + AZStd::string commandString = AZStd::string::format("CreateMotionSet -name \"%s\" -motionSetID %i", m_oldName.c_str(), m_previouslyUsedId); - if (!mOldFileName.empty()) + if (!m_oldFileName.empty()) { - commandString += AZStd::string::format(" -fileName \"%s\"", mOldFileName.c_str()); + commandString += AZStd::string::format(" -fileName \"%s\"", m_oldFileName.c_str()); } - if (mOldParentSetID != MCORE_INVALIDINDEX32) + if (m_oldParentSetId != MCORE_INVALIDINDEX32) { - commandString += AZStd::string::format(" -parentSetID %i", mOldParentSetID); + commandString += AZStd::string::format(" -parentSetID %i", m_oldParentSetId); } const bool result = GetCommandManager()->ExecuteCommandInsideCommand(commandString, outResult); // Restore the workspace dirty flag. - GetCommandManager()->SetWorkspaceDirtyFlag(mOldWorkspaceDirtyFlag); + GetCommandManager()->SetWorkspaceDirtyFlag(m_oldWorkspaceDirtyFlag); return result; } @@ -353,7 +353,7 @@ namespace CommandSystem // Adjust the dirty flag. if (parameters.CheckIfHasParameter("dirtyFlag")) { - mOldDirtyFlag = motionSet->GetDirtyFlag(); + m_oldDirtyFlag = motionSet->GetDirtyFlag(); const bool dirtyFlag = parameters.GetValueAsBool("dirtyFlag", this); motionSet->SetDirtyFlag(dirtyFlag); } @@ -361,12 +361,12 @@ namespace CommandSystem // Set the new name in case the name parameter is specified. if (parameters.CheckIfHasParameter("newName")) { - mOldSetName = motionSet->GetName(); + m_oldSetName = motionSet->GetName(); AZStd::string name; parameters.GetValue("newName", this, name); motionSet->SetName(name.c_str()); - mOldDirtyFlag = motionSet->GetDirtyFlag(); + m_oldDirtyFlag = motionSet->GetDirtyFlag(); motionSet->SetDirtyFlag(true); } @@ -389,13 +389,13 @@ namespace CommandSystem // Adjust the dirty flag if (parameters.CheckIfHasParameter("dirtyFlag")) { - motionSet->SetDirtyFlag(mOldDirtyFlag); + motionSet->SetDirtyFlag(m_oldDirtyFlag); } // Adjust the name. if (parameters.CheckIfHasParameter("newName")) { - motionSet->SetName(mOldSetName.c_str()); + motionSet->SetName(m_oldSetName.c_str()); } return true; @@ -719,8 +719,8 @@ namespace CommandSystem } // Save the old infos for undo. - mOldIdString = motionEntry->GetId(); - mOldMotionFilename = motionEntry->GetFilename(); + m_oldIdString = motionEntry->GetId(); + m_oldMotionFilename = motionEntry->GetFilename(); if (parameters.CheckIfHasParameter("motionFileName")) { @@ -782,7 +782,7 @@ namespace CommandSystem // Update all motion nodes and link them to the new motion id. if (parameters.GetValueAsBool("updateMotionNodeStringIDs", this)) { - UpdateMotionNodes(mOldIdString.c_str(), newId.c_str()); + UpdateMotionNodes(m_oldIdString.c_str(), newId.c_str()); } } @@ -833,12 +833,12 @@ namespace CommandSystem if (idStringChanged) { - command += AZStd::string::format(" -newIDString \"%s\"", mOldIdString.c_str()); + command += AZStd::string::format(" -newIDString \"%s\"", m_oldIdString.c_str()); } if (parameters.CheckIfHasParameter("motionFileName")) { - command += AZStd::string::format(" -motionFileName \"%s\"", mOldMotionFilename.c_str()); + command += AZStd::string::format(" -motionFileName \"%s\"", m_oldMotionFilename.c_str()); } return GetCommandManager()->ExecuteCommandInsideCommand(command, outResult); @@ -869,7 +869,7 @@ namespace CommandSystem CommandLoadMotionSet::CommandLoadMotionSet(MCore::Command* orgCommand) : MCore::Command("LoadMotionSet", orgCommand) { - mOldMotionSetID = MCORE_INVALIDINDEX32; + m_oldMotionSetId = MCORE_INVALIDINDEX32; } @@ -910,11 +910,11 @@ namespace CommandSystem } // In case we are in a redo call assign the previously used id. - if (mOldMotionSetID != MCORE_INVALIDINDEX32) + if (m_oldMotionSetId != MCORE_INVALIDINDEX32) { - motionSet->SetID(mOldMotionSetID); + motionSet->SetID(m_oldMotionSetId); } - mOldMotionSetID = motionSet->GetID(); + m_oldMotionSetId = motionSet->GetID(); // Set the custom loading callback and preload all motions. motionSet->SetCallback(aznew CommandSystemMotionSetCallback(motionSet), true); @@ -924,7 +924,7 @@ namespace CommandSystem AZStd::to_string(outResult, motionSet->GetID()); // Mark the workspace as dirty. - mOldWorkspaceDirtyFlag = GetCommandManager()->GetWorkspaceDirtyFlag(); + m_oldWorkspaceDirtyFlag = GetCommandManager()->GetWorkspaceDirtyFlag(); GetCommandManager()->SetWorkspaceDirtyFlag(true); // Restore original log levels. @@ -938,10 +938,10 @@ namespace CommandSystem MCORE_UNUSED(parameters); // Get the motion set the command created earlier by id. - EMotionFX::MotionSet* motionSet = EMotionFX::GetMotionManager().FindMotionSetByID(mOldMotionSetID); + EMotionFX::MotionSet* motionSet = EMotionFX::GetMotionManager().FindMotionSetByID(m_oldMotionSetId); if (motionSet == nullptr) { - outResult = AZStd::string::format("Cannot undo load motion set command. Previously used motion set id '%i' is not valid.", mOldMotionSetID); + outResult = AZStd::string::format("Cannot undo load motion set command. Previously used motion set id '%i' is not valid.", m_oldMotionSetId); return false; } @@ -952,7 +952,7 @@ namespace CommandSystem const bool result = GetCommandManager()->ExecuteCommandGroupInsideCommand(commandGroup, outResult); // Restore the workspace dirty flag. - GetCommandManager()->SetWorkspaceDirtyFlag(mOldWorkspaceDirtyFlag); + GetCommandManager()->SetWorkspaceDirtyFlag(m_oldWorkspaceDirtyFlag); return result; } diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MotionSetCommands.h b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MotionSetCommands.h index 70f08b1c67..d630f98a45 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MotionSetCommands.h +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MotionSetCommands.h @@ -40,22 +40,22 @@ namespace CommandSystem ////////////////////////////////////////////////////////////////////////////////////////////////////////// MCORE_DEFINECOMMAND_START(CommandCreateMotionSet, "Create motion set", true) public: - uint32 mPreviouslyUsedID; - bool mOldWorkspaceDirtyFlag; + uint32 m_previouslyUsedId; + bool m_oldWorkspaceDirtyFlag; MCORE_DEFINECOMMAND_END MCORE_DEFINECOMMAND_START(CommandRemoveMotionSet, "Remove motion set", true) public: - AZStd::string mOldName; - AZStd::string mOldFileName; - uint32 mOldParentSetID; - uint32 mPreviouslyUsedID; - bool mOldWorkspaceDirtyFlag; + AZStd::string m_oldName; + AZStd::string m_oldFileName; + uint32 m_oldParentSetId; + uint32 m_previouslyUsedId; + bool m_oldWorkspaceDirtyFlag; MCORE_DEFINECOMMAND_END MCORE_DEFINECOMMAND_START(CommandAdjustMotionSet, "Adjust motion set", true) - AZStd::string mOldSetName; - bool mOldDirtyFlag; + AZStd::string m_oldSetName; + bool m_oldDirtyFlag; MCORE_DEFINECOMMAND_END ////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -73,8 +73,8 @@ namespace CommandSystem MCORE_DEFINECOMMAND_START(CommandMotionSetAdjustMotion, "Adjust motion set", true) public: - AZStd::string mOldIdString; - AZStd::string mOldMotionFilename; + AZStd::string m_oldIdString; + AZStd::string m_oldMotionFilename; void UpdateMotionNodes(const char* oldID, const char* newID); MCORE_DEFINECOMMAND_END @@ -85,8 +85,8 @@ namespace CommandSystem public: using RelocateFilenameFunction = AZStd::function; RelocateFilenameFunction m_relocateFilenameFunction; - uint32 mOldMotionSetID; - bool mOldWorkspaceDirtyFlag; + uint32 m_oldMotionSetId; + bool m_oldWorkspaceDirtyFlag; MCORE_DEFINECOMMAND_END ////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/NodeGroupCommands.cpp b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/NodeGroupCommands.cpp index ea83d90d4b..c65429ab83 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/NodeGroupCommands.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/NodeGroupCommands.cpp @@ -264,7 +264,7 @@ namespace CommandSystem actor->AddNodeGroup(nodeGroup); // save the current dirty flag and tell the actor that something got changed - mOldDirtyFlag = actor->GetDirtyFlag(); + m_oldDirtyFlag = actor->GetDirtyFlag(); actor->SetDirtyFlag(true); return true; } @@ -295,7 +295,7 @@ namespace CommandSystem } // set the dirty flag back to the old value - actor->SetDirtyFlag(mOldDirtyFlag); + actor->SetDirtyFlag(m_oldDirtyFlag); return true; } @@ -322,7 +322,7 @@ namespace CommandSystem // constructor CommandRemoveNodeGroup::CommandRemoveNodeGroup(MCore::Command* orgCommand) : MCore::Command("RemoveNodeGroup", orgCommand) - , mOldNodeGroup(nullptr) + , m_oldNodeGroup(nullptr) { } @@ -330,7 +330,7 @@ namespace CommandSystem // destructor CommandRemoveNodeGroup::~CommandRemoveNodeGroup() { - delete mOldNodeGroup; + delete m_oldNodeGroup; } @@ -360,14 +360,14 @@ namespace CommandSystem } // copy the old node group for undo - delete mOldNodeGroup; - mOldNodeGroup = aznew EMotionFX::NodeGroup(*nodeGroup); + delete m_oldNodeGroup; + m_oldNodeGroup = aznew EMotionFX::NodeGroup(*nodeGroup); // remove the node group actor->RemoveNodeGroup(nodeGroup); // save the current dirty flag and tell the actor that something got changed - mOldDirtyFlag = actor->GetDirtyFlag(); + m_oldDirtyFlag = actor->GetDirtyFlag(); actor->SetDirtyFlag(true); return true; } @@ -377,7 +377,7 @@ namespace CommandSystem bool CommandRemoveNodeGroup::Undo(const MCore::CommandLine& parameters, AZStd::string& outResult) { // check if old node group exists - if (!mOldNodeGroup) + if (!m_oldNodeGroup) { return false; } @@ -397,13 +397,13 @@ namespace CommandSystem } // add the node to the group again - if (name == mOldNodeGroup->GetName()) + if (name == m_oldNodeGroup->GetName()) { - actor->AddNodeGroup(aznew EMotionFX::NodeGroup(*mOldNodeGroup)); + actor->AddNodeGroup(aznew EMotionFX::NodeGroup(*m_oldNodeGroup)); } // set the dirty flag back to the old value - actor->SetDirtyFlag(mOldDirtyFlag); + actor->SetDirtyFlag(m_oldDirtyFlag); return true; } diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/NodeGroupCommands.h b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/NodeGroupCommands.h index d29918822d..6c57877bd5 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/NodeGroupCommands.h +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/NodeGroupCommands.h @@ -79,14 +79,14 @@ namespace CommandSystem // add node group MCORE_DEFINECOMMAND_START(CommandAddNodeGroup, "Add node group", true) - bool mOldDirtyFlag; + bool m_oldDirtyFlag; MCORE_DEFINECOMMAND_END // remove a node group MCORE_DEFINECOMMAND_START(CommandRemoveNodeGroup, "Remove node group", true) - EMotionFX::NodeGroup * mOldNodeGroup; - bool mOldDirtyFlag; + EMotionFX::NodeGroup * m_oldNodeGroup; + bool m_oldDirtyFlag; MCORE_DEFINECOMMAND_END diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/RagdollCommands.cpp b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/RagdollCommands.cpp index 37657699d4..e51c9ece0b 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/RagdollCommands.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/RagdollCommands.cpp @@ -90,8 +90,8 @@ namespace EMotionFX const Transform& parentBindTransform = node->GetParentNode() ? bindPose->GetModelSpaceTransform(node->GetParentIndex()) : Transform::CreateIdentity(); - const AZ::Quaternion& nodeBindRotationWorld = nodeBindTransform.mRotation; - const AZ::Quaternion& parentBindRotationWorld = parentBindTransform.mRotation; + const AZ::Quaternion& nodeBindRotationWorld = nodeBindTransform.m_rotation; + const AZ::Quaternion& parentBindRotationWorld = parentBindTransform.m_rotation; AZ::Vector3 boneDirection = GetBoneDirection(skeleton, node); AZStd::vector exampleRotationsLocal; diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/SelectionCommands.cpp b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/SelectionCommands.cpp index 72c7338512..bcc9769c44 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/SelectionCommands.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/SelectionCommands.cpp @@ -547,7 +547,7 @@ namespace CommandSystem bool CommandSelect::Execute(const MCore::CommandLine& parameters, AZStd::string& outResult) { // store the old selection list for undo - mData = GetCommandManager()->GetCurrentSelection(); + m_data = GetCommandManager()->GetCurrentSelection(); // selection add mode return Select(this, parameters, outResult, false); @@ -561,7 +561,7 @@ namespace CommandSystem MCORE_UNUSED(outResult); // restore the old selection and return success - GetCommandManager()->SetCurrentSelection(mData); + GetCommandManager()->SetCurrentSelection(m_data); return true; } @@ -604,7 +604,7 @@ namespace CommandSystem bool CommandUnselect::Execute(const MCore::CommandLine& parameters, AZStd::string& outResult) { // store the old selection list for undo - mData = GetCommandManager()->GetCurrentSelection(); + m_data = GetCommandManager()->GetCurrentSelection(); // unselect mode return CommandSelect::Select(this, parameters, outResult, true); @@ -618,7 +618,7 @@ namespace CommandSystem MCORE_UNUSED(outResult); // restore the old selection and return success - GetCommandManager()->SetCurrentSelection(mData); + GetCommandManager()->SetCurrentSelection(m_data); return true; } @@ -665,7 +665,7 @@ namespace CommandSystem // get the current selection, store it for the undo function and unselect everything SelectionList& selection = GetCommandManager()->GetCurrentSelection(); - mData = selection; + m_data = selection; // if we are in selection lock mode return directly //if (GetCommandManager()->GetLockSelection()) @@ -686,7 +686,7 @@ namespace CommandSystem MCORE_UNUSED(outResult); // restore the old selection and return success - GetCommandManager()->SetCurrentSelection(mData); + GetCommandManager()->SetCurrentSelection(m_data); return true; } @@ -721,10 +721,10 @@ namespace CommandSystem MCORE_UNUSED(outResult); // store the selection locked flag for the undo function - mData = GetCommandManager()->GetLockSelection(); + m_data = GetCommandManager()->GetLockSelection(); // toggle the flag - GetCommandManager()->SetLockSelection(!mData); + GetCommandManager()->SetLockSelection(!m_data); return true; } @@ -737,7 +737,7 @@ namespace CommandSystem MCORE_UNUSED(outResult); // restore the old selection locked flag and return success - GetCommandManager()->SetLockSelection(mData); + GetCommandManager()->SetLockSelection(m_data); return true; } diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/SelectionCommands.h b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/SelectionCommands.h index 0c1fad6588..13a39e5e8a 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/SelectionCommands.h +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/SelectionCommands.h @@ -19,7 +19,7 @@ namespace CommandSystem { MCORE_DEFINECOMMAND_START(CommandSelect, "Select object", true) - SelectionList mData; + SelectionList m_data; public: static const char* s_SelectCmdName; static bool Select(MCore::Command* command, const MCore::CommandLine& parameters, AZStd::string& outResult, bool unselect); diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/SelectionList.cpp b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/SelectionList.cpp index 5910ae84f7..e115c24221 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/SelectionList.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/SelectionList.cpp @@ -27,39 +27,39 @@ namespace CommandSystem size_t SelectionList::GetNumTotalItems() const { - return mSelectedNodes.size() + - mSelectedActors.size() + - mSelectedActorInstances.size() + - mSelectedMotions.size() + - mSelectedMotionInstances.size() + - mSelectedAnimGraphs.size(); + return m_selectedNodes.size() + + m_selectedActors.size() + + m_selectedActorInstances.size() + + m_selectedMotions.size() + + m_selectedMotionInstances.size() + + m_selectedAnimGraphs.size(); } bool SelectionList::GetIsEmpty() const { - return (mSelectedNodes.empty() && - mSelectedActors.empty() && - mSelectedActorInstances.empty() && - mSelectedMotions.empty() && - mSelectedMotionInstances.empty() && - mSelectedAnimGraphs.empty()); + return (m_selectedNodes.empty() && + m_selectedActors.empty() && + m_selectedActorInstances.empty() && + m_selectedMotions.empty() && + m_selectedMotionInstances.empty() && + m_selectedAnimGraphs.empty()); } void SelectionList::Clear() { - mSelectedNodes.clear(); - mSelectedActors.clear(); - mSelectedActorInstances.clear(); - mSelectedMotions.clear(); - mSelectedMotionInstances.clear(); - mSelectedAnimGraphs.clear(); + m_selectedNodes.clear(); + m_selectedActors.clear(); + m_selectedActorInstances.clear(); + m_selectedMotions.clear(); + m_selectedMotionInstances.clear(); + m_selectedAnimGraphs.clear(); } void SelectionList::AddNode(EMotionFX::Node* node) { if (!CheckIfHasNode(node)) { - mSelectedNodes.emplace_back(node); + m_selectedNodes.emplace_back(node); } } @@ -67,7 +67,7 @@ namespace CommandSystem { if (!CheckIfHasActor(actor)) { - mSelectedActors.emplace_back(actor); + m_selectedActors.emplace_back(actor); } } @@ -76,7 +76,7 @@ namespace CommandSystem { if (!CheckIfHasActorInstance(actorInstance)) { - mSelectedActorInstances.emplace_back(actorInstance); + m_selectedActorInstances.emplace_back(actorInstance); } } @@ -86,7 +86,7 @@ namespace CommandSystem { if (!CheckIfHasMotion(motion)) { - mSelectedMotions.emplace_back(motion); + m_selectedMotions.emplace_back(motion); } } @@ -96,7 +96,7 @@ namespace CommandSystem { if (!CheckIfHasMotionInstance(motionInstance)) { - mSelectedMotionInstances.emplace_back(motionInstance); + m_selectedMotionInstances.emplace_back(motionInstance); } } @@ -106,7 +106,7 @@ namespace CommandSystem { if (!CheckIfHasAnimGraph(animGraph)) { - mSelectedAnimGraphs.emplace_back(animGraph); + m_selectedAnimGraphs.emplace_back(animGraph); } } @@ -209,52 +209,52 @@ namespace CommandSystem void SelectionList::RemoveNode(EMotionFX::Node* node) { - mSelectedNodes.erase(AZStd::remove(mSelectedNodes.begin(), mSelectedNodes.end(), node), mSelectedNodes.end()); + m_selectedNodes.erase(AZStd::remove(m_selectedNodes.begin(), m_selectedNodes.end(), node), m_selectedNodes.end()); } void SelectionList::RemoveActor(EMotionFX::Actor* actor) { - mSelectedActors.erase(AZStd::remove(mSelectedActors.begin(), mSelectedActors.end(), actor), mSelectedActors.end()); + m_selectedActors.erase(AZStd::remove(m_selectedActors.begin(), m_selectedActors.end(), actor), m_selectedActors.end()); } // remove the actor from the selection list void SelectionList::RemoveActorInstance(EMotionFX::ActorInstance* actorInstance) { - mSelectedActorInstances.erase(AZStd::remove(mSelectedActorInstances.begin(), mSelectedActorInstances.end(), actorInstance), mSelectedActorInstances.end()); + m_selectedActorInstances.erase(AZStd::remove(m_selectedActorInstances.begin(), m_selectedActorInstances.end(), actorInstance), m_selectedActorInstances.end()); } // remove the motion from the selection list void SelectionList::RemoveMotion(EMotionFX::Motion* motion) { - mSelectedMotions.erase(AZStd::remove(mSelectedMotions.begin(), mSelectedMotions.end(), motion), mSelectedMotions.end()); + m_selectedMotions.erase(AZStd::remove(m_selectedMotions.begin(), m_selectedMotions.end(), motion), m_selectedMotions.end()); } // remove the motion instance from the selection list void SelectionList::RemoveMotionInstance(EMotionFX::MotionInstance* motionInstance) { - mSelectedMotionInstances.erase(AZStd::remove(mSelectedMotionInstances.begin(), mSelectedMotionInstances.end(), motionInstance), mSelectedMotionInstances.end()); + m_selectedMotionInstances.erase(AZStd::remove(m_selectedMotionInstances.begin(), m_selectedMotionInstances.end(), motionInstance), m_selectedMotionInstances.end()); } // remove the anim graph void SelectionList::RemoveAnimGraph(EMotionFX::AnimGraph* animGraph) { - mSelectedAnimGraphs.erase(AZStd::remove(mSelectedAnimGraphs.begin(), mSelectedAnimGraphs.end(), animGraph), mSelectedAnimGraphs.end()); + m_selectedAnimGraphs.erase(AZStd::remove(m_selectedAnimGraphs.begin(), m_selectedAnimGraphs.end(), animGraph), m_selectedAnimGraphs.end()); } // make the selection valid void SelectionList::MakeValid() { // iterate through all actor instances and remove the invalid ones - for (size_t i = 0; i < mSelectedActorInstances.size();) + for (size_t i = 0; i < m_selectedActorInstances.size();) { - EMotionFX::ActorInstance* actorInstance = mSelectedActorInstances[i]; + EMotionFX::ActorInstance* actorInstance = m_selectedActorInstances[i]; if (EMotionFX::GetActorManager().CheckIfIsActorInstanceRegistered(actorInstance) == false) { - mSelectedActorInstances.erase(mSelectedActorInstances.begin() + i); + m_selectedActorInstances.erase(m_selectedActorInstances.begin() + i); } else { @@ -263,13 +263,13 @@ namespace CommandSystem } // iterate through all anim graphs and remove all valid ones - for (size_t i = 0; i < mSelectedAnimGraphs.size();) + for (size_t i = 0; i < m_selectedAnimGraphs.size();) { - EMotionFX::AnimGraph* animGraph = mSelectedAnimGraphs[i]; + EMotionFX::AnimGraph* animGraph = m_selectedAnimGraphs[i]; if (EMotionFX::GetAnimGraphManager().FindAnimGraphIndex(animGraph) == MCORE_INVALIDINDEX32) { - mSelectedAnimGraphs.erase(mSelectedAnimGraphs.begin() + i); + m_selectedAnimGraphs.erase(m_selectedAnimGraphs.begin() + i); } else { @@ -294,7 +294,7 @@ namespace CommandSystem return nullptr; } - return mSelectedActors[0]; + return m_selectedActors[0]; } @@ -313,7 +313,7 @@ namespace CommandSystem return nullptr; } - EMotionFX::ActorInstance* actorInstance = mSelectedActorInstances[0]; + EMotionFX::ActorInstance* actorInstance = m_selectedActorInstances[0]; if (!actorInstance) { return nullptr; @@ -324,7 +324,7 @@ namespace CommandSystem return nullptr; } - return mSelectedActorInstances[0]; + return m_selectedActorInstances[0]; } @@ -341,7 +341,7 @@ namespace CommandSystem return nullptr; } - EMotionFX::Motion* motion = mSelectedMotions[0]; + EMotionFX::Motion* motion = m_selectedMotions[0]; if (!motion) { return nullptr; diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/SelectionList.h b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/SelectionList.h index 6dd1d2d4e2..ce53a1378f 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/SelectionList.h +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/SelectionList.h @@ -45,36 +45,36 @@ namespace CommandSystem * Get the number of selected nodes. * @return The number of selected nodes. */ - MCORE_INLINE size_t GetNumSelectedNodes() const { return mSelectedNodes.size(); } + MCORE_INLINE size_t GetNumSelectedNodes() const { return m_selectedNodes.size(); } /** * Get the number of selected actors */ - MCORE_INLINE size_t GetNumSelectedActors() const { return mSelectedActors.size(); } + MCORE_INLINE size_t GetNumSelectedActors() const { return m_selectedActors.size(); } /** * Get the number of selected actor instances. * @return The number of selected actor instances. */ - MCORE_INLINE size_t GetNumSelectedActorInstances() const { return mSelectedActorInstances.size(); } + MCORE_INLINE size_t GetNumSelectedActorInstances() const { return m_selectedActorInstances.size(); } /** * Get the number of selected motion instances. * @return The number of selected motion instances. */ - MCORE_INLINE size_t GetNumSelectedMotionInstances() const { return mSelectedMotionInstances.size(); } + MCORE_INLINE size_t GetNumSelectedMotionInstances() const { return m_selectedMotionInstances.size(); } /** * Get the number of selected motions. * @return The number of selected motions. */ - MCORE_INLINE size_t GetNumSelectedMotions() const { return mSelectedMotions.size(); } + MCORE_INLINE size_t GetNumSelectedMotions() const { return m_selectedMotions.size(); } /** * Get the number of selected anim graphs. * @return The number of selected anim graphs. */ - MCORE_INLINE size_t GetNumSelectedAnimGraphs() const { return mSelectedAnimGraphs.size(); } + MCORE_INLINE size_t GetNumSelectedAnimGraphs() const { return m_selectedAnimGraphs.size(); } /** * Get the total number of selected objects. @@ -139,7 +139,7 @@ namespace CommandSystem * @param index The index of the node to get from the selection list. * @return A pointer to the given node from the selection list. */ - MCORE_INLINE EMotionFX::Node* GetNode(size_t index) const { return mSelectedNodes[index]; } + MCORE_INLINE EMotionFX::Node* GetNode(size_t index) const { return m_selectedNodes[index]; } /** * Get the first node from the selection list. @@ -147,11 +147,11 @@ namespace CommandSystem */ MCORE_INLINE EMotionFX::Node* GetFirstNode() const { - if (mSelectedNodes.empty()) + if (m_selectedNodes.empty()) { return nullptr; } - return mSelectedNodes[0]; + return m_selectedNodes[0]; } /** @@ -159,7 +159,7 @@ namespace CommandSystem * @param index The index of the actor to get from the selection list. * @return A pointer to the given actor from the selection list. */ - MCORE_INLINE EMotionFX::Actor* GetActor(size_t index) const { return mSelectedActors[index]; } + MCORE_INLINE EMotionFX::Actor* GetActor(size_t index) const { return m_selectedActors[index]; } /** * Get the first actor from the selection list. @@ -167,11 +167,11 @@ namespace CommandSystem */ MCORE_INLINE EMotionFX::Actor* GetFirstActor() const { - if (mSelectedActors.empty()) + if (m_selectedActors.empty()) { return nullptr; } - return mSelectedActors[0]; + return m_selectedActors[0]; } /** @@ -179,7 +179,7 @@ namespace CommandSystem * @param index The index of the actor instance to get from the selection list. * @return A pointer to the given actor instance from the selection list. */ - MCORE_INLINE EMotionFX::ActorInstance* GetActorInstance(size_t index) const { return mSelectedActorInstances[index]; } + MCORE_INLINE EMotionFX::ActorInstance* GetActorInstance(size_t index) const { return m_selectedActorInstances[index]; } /** * Get the first actor instance from the selection list. @@ -187,11 +187,11 @@ namespace CommandSystem */ MCORE_INLINE EMotionFX::ActorInstance* GetFirstActorInstance() const { - if (mSelectedActorInstances.empty()) + if (m_selectedActorInstances.empty()) { return nullptr; } - return mSelectedActorInstances[0]; + return m_selectedActorInstances[0]; } /** @@ -199,7 +199,7 @@ namespace CommandSystem * @param index The index of the anim graph to get from the selection list. * @return A pointer to the given anim graph from the selection list. */ - MCORE_INLINE EMotionFX::AnimGraph* GetAnimGraph(size_t index) const { return mSelectedAnimGraphs[index]; } + MCORE_INLINE EMotionFX::AnimGraph* GetAnimGraph(size_t index) const { return m_selectedAnimGraphs[index]; } /** * Get the first anim graph from the selection list. @@ -207,11 +207,11 @@ namespace CommandSystem */ MCORE_INLINE EMotionFX::AnimGraph* GetFirstAnimGraph() const { - if (mSelectedAnimGraphs.empty()) + if (m_selectedAnimGraphs.empty()) { return nullptr; } - return mSelectedAnimGraphs[0]; + return m_selectedAnimGraphs[0]; } /** @@ -231,7 +231,7 @@ namespace CommandSystem * @param index The index of the motion to get from the selection list. * @return A pointer to the given motion from the selection list. */ - MCORE_INLINE EMotionFX::Motion* GetMotion(size_t index) const { return mSelectedMotions[index]; } + MCORE_INLINE EMotionFX::Motion* GetMotion(size_t index) const { return m_selectedMotions[index]; } /** * Get the first motion from the selection list. @@ -239,11 +239,11 @@ namespace CommandSystem */ MCORE_INLINE EMotionFX::Motion* GetFirstMotion() const { - if (mSelectedMotions.empty()) + if (m_selectedMotions.empty()) { return nullptr; } - return mSelectedMotions[0]; + return m_selectedMotions[0]; } /** @@ -257,7 +257,7 @@ namespace CommandSystem * @param index The index of the motion instance to get from the selection list. * @return A pointer to the given motion instance from the selection list. */ - MCORE_INLINE EMotionFX::MotionInstance* GetMotionInstance(size_t index) const { return mSelectedMotionInstances[index]; } + MCORE_INLINE EMotionFX::MotionInstance* GetMotionInstance(size_t index) const { return m_selectedMotionInstances[index]; } /** * Get the first motion instance from the selection list. @@ -265,48 +265,48 @@ namespace CommandSystem */ MCORE_INLINE EMotionFX::MotionInstance* GetFirstMotionInstance() const { - if (mSelectedMotionInstances.empty()) + if (m_selectedMotionInstances.empty()) { return nullptr; } - return mSelectedMotionInstances[0]; + return m_selectedMotionInstances[0]; } /** * Remove the given node from the selection list. * @param index The index of the node to be removed from the selection list. */ - MCORE_INLINE void RemoveNode(size_t index) { mSelectedNodes.erase(mSelectedNodes.begin() + index); } + MCORE_INLINE void RemoveNode(size_t index) { m_selectedNodes.erase(m_selectedNodes.begin() + index); } /** * Remove the given actor instance from the selection list. * @param index The index of the actor instance to be removed from the selection list. */ - MCORE_INLINE void RemoveActor(size_t index) { mSelectedActors.erase(mSelectedActors.begin() + index); } + MCORE_INLINE void RemoveActor(size_t index) { m_selectedActors.erase(m_selectedActors.begin() + index); } /** * Remove the given actor instance from the selection list. * @param index The index of the actor instance to be removed from the selection list. */ - MCORE_INLINE void RemoveActorInstance(size_t index) { mSelectedActorInstances.erase(mSelectedActorInstances.begin() + index); } + MCORE_INLINE void RemoveActorInstance(size_t index) { m_selectedActorInstances.erase(m_selectedActorInstances.begin() + index); } /** * Remove the given motion from the selection list. * @param index The index of the motion to be removed from the selection list. */ - MCORE_INLINE void RemoveMotion(size_t index) { mSelectedMotions.erase(mSelectedMotions.begin() + index); } + MCORE_INLINE void RemoveMotion(size_t index) { m_selectedMotions.erase(m_selectedMotions.begin() + index); } /** * Remove the given motion instance from the selection list. * @param index The index of the motion instance to be removed from the selection list. */ - MCORE_INLINE void RemoveMotionInstance(size_t index) { mSelectedMotionInstances.erase(mSelectedMotionInstances.begin() + index); } + MCORE_INLINE void RemoveMotionInstance(size_t index) { m_selectedMotionInstances.erase(m_selectedMotionInstances.begin() + index); } /** * Remove the given anim graph from the selection list. * @param index The index of the anim graph to remove from the selection list. */ - MCORE_INLINE void RemoveAnimGraph(size_t index) { mSelectedAnimGraphs.erase(mSelectedAnimGraphs.begin() + index); } + MCORE_INLINE void RemoveAnimGraph(size_t index) { m_selectedAnimGraphs.erase(m_selectedAnimGraphs.begin() + index); } /** * Remove the given node from the selection list. @@ -349,47 +349,47 @@ namespace CommandSystem * @param node A pointer to the node to be checked. * @return True if the node is inside this selection list, false if not. */ - MCORE_INLINE bool CheckIfHasNode(EMotionFX::Node* node) const { return(AZStd::find(mSelectedNodes.begin(), mSelectedNodes.end(), node) != mSelectedNodes.end()); } + MCORE_INLINE bool CheckIfHasNode(EMotionFX::Node* node) const { return(AZStd::find(m_selectedNodes.begin(), m_selectedNodes.end(), node) != m_selectedNodes.end()); } /** * Has actor */ - MCORE_INLINE bool CheckIfHasActor(EMotionFX::Actor* actor) const { return (AZStd::find(mSelectedActors.begin(), mSelectedActors.end(), actor) != mSelectedActors.end()); } + MCORE_INLINE bool CheckIfHasActor(EMotionFX::Actor* actor) const { return (AZStd::find(m_selectedActors.begin(), m_selectedActors.end(), actor) != m_selectedActors.end()); } /** * Check if a given actor instance is selected / is in this selection list. * @param node A pointer to the actor instance to be checked. * @return True if the actor instance is inside this selection list, false if not. */ - MCORE_INLINE bool CheckIfHasActorInstance(EMotionFX::ActorInstance* actorInstance) const { return (AZStd::find(mSelectedActorInstances.begin(), mSelectedActorInstances.end(), actorInstance) != mSelectedActorInstances.end()); } + MCORE_INLINE bool CheckIfHasActorInstance(EMotionFX::ActorInstance* actorInstance) const { return (AZStd::find(m_selectedActorInstances.begin(), m_selectedActorInstances.end(), actorInstance) != m_selectedActorInstances.end()); } /** * Check if a given motion is selected / is in this selection list. * @param node A pointer to the motion to be checked. * @return True if the motion is inside this selection list, false if not. */ - MCORE_INLINE bool CheckIfHasMotion(EMotionFX::Motion* motion) const { return (AZStd::find(mSelectedMotions.begin(), mSelectedMotions.end(), motion) != mSelectedMotions.end()); } + MCORE_INLINE bool CheckIfHasMotion(EMotionFX::Motion* motion) const { return (AZStd::find(m_selectedMotions.begin(), m_selectedMotions.end(), motion) != m_selectedMotions.end()); } /** * Check if a given anim graph is in this selection list. * @param animGraph The anim graph to check for. * @return True if the anim graph is selected inside the selection list, otherwise false is returned. */ - MCORE_INLINE bool CheckIfHasAnimGraph(EMotionFX::AnimGraph* animGraph) const { return (AZStd::find(mSelectedAnimGraphs.begin(), mSelectedAnimGraphs.end(), animGraph) != mSelectedAnimGraphs.end()); } + MCORE_INLINE bool CheckIfHasAnimGraph(EMotionFX::AnimGraph* animGraph) const { return (AZStd::find(m_selectedAnimGraphs.begin(), m_selectedAnimGraphs.end(), animGraph) != m_selectedAnimGraphs.end()); } /** * Check if a given motion instance is selected / is in this selection list. * @param node A pointer to the motion instance to be checked. * @return True if the motion instance is inside this selection list, false if not. */ - MCORE_INLINE bool CheckIfHasMotionInstance(EMotionFX::MotionInstance* motionInstance) const { return (AZStd::find(mSelectedMotionInstances.begin(), mSelectedMotionInstances.end(), motionInstance) != mSelectedMotionInstances.end()); } + MCORE_INLINE bool CheckIfHasMotionInstance(EMotionFX::MotionInstance* motionInstance) const { return (AZStd::find(m_selectedMotionInstances.begin(), m_selectedMotionInstances.end(), motionInstance) != m_selectedMotionInstances.end()); } - MCORE_INLINE void ClearActorSelection() { mSelectedActors.clear(); } - MCORE_INLINE void ClearActorInstanceSelection() { mSelectedActorInstances.clear(); } - MCORE_INLINE void ClearNodeSelection() { mSelectedNodes.clear(); } - MCORE_INLINE void ClearMotionSelection() { mSelectedMotions.clear(); } - MCORE_INLINE void ClearMotionInstanceSelection() { mSelectedMotionInstances.clear(); } - MCORE_INLINE void ClearAnimGraphSelection() { mSelectedAnimGraphs.clear(); } + MCORE_INLINE void ClearActorSelection() { m_selectedActors.clear(); } + MCORE_INLINE void ClearActorInstanceSelection() { m_selectedActorInstances.clear(); } + MCORE_INLINE void ClearNodeSelection() { m_selectedNodes.clear(); } + MCORE_INLINE void ClearMotionSelection() { m_selectedMotions.clear(); } + MCORE_INLINE void ClearMotionInstanceSelection() { m_selectedMotionInstances.clear(); } + MCORE_INLINE void ClearAnimGraphSelection() { m_selectedAnimGraphs.clear(); } void Log(); void MakeValid(); @@ -401,11 +401,11 @@ namespace CommandSystem // ActorInstanceNotificationBus overrides void OnActorInstanceDestroyed(EMotionFX::ActorInstance* actorInstance) override; - AZStd::vector mSelectedNodes; /**< Array of selected nodes. */ - AZStd::vector mSelectedActors; /**< The selected actors. */ - AZStd::vector mSelectedActorInstances; /**< Array of selected actor instances. */ - AZStd::vector mSelectedMotionInstances; /**< Array of selected motion instances. */ - AZStd::vector mSelectedMotions; /**< Array of selected motions. */ - AZStd::vector mSelectedAnimGraphs; /**< Array of selected anim graphs. */ + AZStd::vector m_selectedNodes; /**< Array of selected nodes. */ + AZStd::vector m_selectedActors; /**< The selected actors. */ + AZStd::vector m_selectedActorInstances; /**< Array of selected actor instances. */ + AZStd::vector m_selectedMotionInstances; /**< Array of selected motion instances. */ + AZStd::vector m_selectedMotions; /**< Array of selected motions. */ + AZStd::vector m_selectedAnimGraphs; /**< Array of selected anim graphs. */ }; } // namespace CommandSystem diff --git a/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/EndianConversion.cpp b/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/EndianConversion.cpp index 153ec6e701..064c786b0a 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/EndianConversion.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/EndianConversion.cpp @@ -14,15 +14,15 @@ namespace ExporterLib { void CopyVector2(EMotionFX::FileFormat::FileVector2& to, const AZ::Vector2& from) { - to.mX = from.GetX(); - to.mY = from.GetY(); + to.m_x = from.GetX(); + to.m_y = from.GetY(); } void CopyVector(EMotionFX::FileFormat::FileVector3& to, const AZ::PackedVector3f& from) { - to.mX = from.GetX(); - to.mY = from.GetY(); - to.mZ = from.GetZ(); + to.m_x = from.GetX(); + to.m_y = from.GetY(); + to.m_z = from.GetZ(); } void CopyQuaternion(EMotionFX::FileFormat::FileQuaternion& to, const AZ::Quaternion& from) @@ -33,10 +33,10 @@ namespace ExporterLib q = -q; } - to.mX = q.GetX(); - to.mY = q.GetY(); - to.mZ = q.GetZ(); - to.mW = q.GetW(); + to.m_x = q.GetX(); + to.m_y = q.GetY(); + to.m_z = q.GetZ(); + to.m_w = q.GetW(); } @@ -49,37 +49,37 @@ namespace ExporterLib } const MCore::Compressed16BitQuaternion compressedQuat(q); - to.mX = compressedQuat.mX; - to.mY = compressedQuat.mY; - to.mZ = compressedQuat.mZ; - to.mW = compressedQuat.mW; + to.m_x = compressedQuat.m_x; + to.m_y = compressedQuat.m_y; + to.m_z = compressedQuat.m_z; + to.m_w = compressedQuat.m_w; } void Copy16BitQuaternion(EMotionFX::FileFormat::File16BitQuaternion& to, const MCore::Compressed16BitQuaternion& from) { MCore::Compressed16BitQuaternion q = from; - if (q.mW < 0) + if (q.m_w < 0) { - q.mX = -q.mX; - q.mY = -q.mY; - q.mZ = -q.mZ; - q.mW = -q.mW; + q.m_x = -q.m_x; + q.m_y = -q.m_y; + q.m_z = -q.m_z; + q.m_w = -q.m_w; } - to.mX = q.mX; - to.mY = q.mY; - to.mZ = q.mZ; - to.mW = q.mW; + to.m_x = q.m_x; + to.m_y = q.m_y; + to.m_z = q.m_z; + to.m_w = q.m_w; } void CopyColor(const MCore::RGBAColor& from, EMotionFX::FileFormat::FileColor& to) { - to.mR = from.r; - to.mG = from.g; - to.mB = from.b; - to.mA = from.a; + to.m_r = from.m_r; + to.m_g = from.m_g; + to.m_b = from.m_b; + to.m_a = from.m_a; } @@ -114,87 +114,87 @@ namespace ExporterLib void ConvertFileChunk(EMotionFX::FileFormat::FileChunk* value, MCore::Endian::EEndianType targetEndianType) { - MCore::Endian::ConvertUnsignedInt32(&value->mChunkID, EXPLIB_PLATFORM_ENDIAN, targetEndianType); - MCore::Endian::ConvertUnsignedInt32(&value->mSizeInBytes, EXPLIB_PLATFORM_ENDIAN, targetEndianType); - MCore::Endian::ConvertUnsignedInt32(&value->mVersion, EXPLIB_PLATFORM_ENDIAN, targetEndianType); + MCore::Endian::ConvertUnsignedInt32(&value->m_chunkId, EXPLIB_PLATFORM_ENDIAN, targetEndianType); + MCore::Endian::ConvertUnsignedInt32(&value->m_sizeInBytes, EXPLIB_PLATFORM_ENDIAN, targetEndianType); + MCore::Endian::ConvertUnsignedInt32(&value->m_version, EXPLIB_PLATFORM_ENDIAN, targetEndianType); } void ConvertFileColor(EMotionFX::FileFormat::FileColor* value, MCore::Endian::EEndianType targetEndianType) { - MCore::Endian::ConvertFloat(&value->mR, EXPLIB_PLATFORM_ENDIAN, targetEndianType); - MCore::Endian::ConvertFloat(&value->mG, EXPLIB_PLATFORM_ENDIAN, targetEndianType); - MCore::Endian::ConvertFloat(&value->mB, EXPLIB_PLATFORM_ENDIAN, targetEndianType); - MCore::Endian::ConvertFloat(&value->mA, EXPLIB_PLATFORM_ENDIAN, targetEndianType); + MCore::Endian::ConvertFloat(&value->m_r, EXPLIB_PLATFORM_ENDIAN, targetEndianType); + MCore::Endian::ConvertFloat(&value->m_g, EXPLIB_PLATFORM_ENDIAN, targetEndianType); + MCore::Endian::ConvertFloat(&value->m_b, EXPLIB_PLATFORM_ENDIAN, targetEndianType); + MCore::Endian::ConvertFloat(&value->m_a, EXPLIB_PLATFORM_ENDIAN, targetEndianType); } void ConvertFileVector2(EMotionFX::FileFormat::FileVector2* value, MCore::Endian::EEndianType targetEndianType) { - MCore::Endian::ConvertFloat(&value->mX, EXPLIB_PLATFORM_ENDIAN, targetEndianType); - MCore::Endian::ConvertFloat(&value->mY, EXPLIB_PLATFORM_ENDIAN, targetEndianType); + MCore::Endian::ConvertFloat(&value->m_x, EXPLIB_PLATFORM_ENDIAN, targetEndianType); + MCore::Endian::ConvertFloat(&value->m_y, EXPLIB_PLATFORM_ENDIAN, targetEndianType); } void ConvertFileVector3(EMotionFX::FileFormat::FileVector3* value, MCore::Endian::EEndianType targetEndianType) { - MCore::Endian::ConvertFloat(&value->mX, EXPLIB_PLATFORM_ENDIAN, targetEndianType); - MCore::Endian::ConvertFloat(&value->mY, EXPLIB_PLATFORM_ENDIAN, targetEndianType); - MCore::Endian::ConvertFloat(&value->mZ, EXPLIB_PLATFORM_ENDIAN, targetEndianType); + MCore::Endian::ConvertFloat(&value->m_x, EXPLIB_PLATFORM_ENDIAN, targetEndianType); + MCore::Endian::ConvertFloat(&value->m_y, EXPLIB_PLATFORM_ENDIAN, targetEndianType); + MCore::Endian::ConvertFloat(&value->m_z, EXPLIB_PLATFORM_ENDIAN, targetEndianType); } void ConvertFile16BitVector3(EMotionFX::FileFormat::File16BitVector3* value, MCore::Endian::EEndianType targetEndianType) { - MCore::Endian::ConvertUnsignedInt16(&value->mX, EXPLIB_PLATFORM_ENDIAN, targetEndianType); - MCore::Endian::ConvertUnsignedInt16(&value->mY, EXPLIB_PLATFORM_ENDIAN, targetEndianType); - MCore::Endian::ConvertUnsignedInt16(&value->mZ, EXPLIB_PLATFORM_ENDIAN, targetEndianType); + MCore::Endian::ConvertUnsignedInt16(&value->m_x, EXPLIB_PLATFORM_ENDIAN, targetEndianType); + MCore::Endian::ConvertUnsignedInt16(&value->m_y, EXPLIB_PLATFORM_ENDIAN, targetEndianType); + MCore::Endian::ConvertUnsignedInt16(&value->m_z, EXPLIB_PLATFORM_ENDIAN, targetEndianType); } void ConvertFileQuaternion(EMotionFX::FileFormat::FileQuaternion* value, MCore::Endian::EEndianType targetEndianType) { - MCore::Endian::ConvertFloat(&value->mX, EXPLIB_PLATFORM_ENDIAN, targetEndianType); - MCore::Endian::ConvertFloat(&value->mY, EXPLIB_PLATFORM_ENDIAN, targetEndianType); - MCore::Endian::ConvertFloat(&value->mZ, EXPLIB_PLATFORM_ENDIAN, targetEndianType); - MCore::Endian::ConvertFloat(&value->mW, EXPLIB_PLATFORM_ENDIAN, targetEndianType); + MCore::Endian::ConvertFloat(&value->m_x, EXPLIB_PLATFORM_ENDIAN, targetEndianType); + MCore::Endian::ConvertFloat(&value->m_y, EXPLIB_PLATFORM_ENDIAN, targetEndianType); + MCore::Endian::ConvertFloat(&value->m_z, EXPLIB_PLATFORM_ENDIAN, targetEndianType); + MCore::Endian::ConvertFloat(&value->m_w, EXPLIB_PLATFORM_ENDIAN, targetEndianType); } void ConvertFile16BitQuaternion(EMotionFX::FileFormat::File16BitQuaternion* value, MCore::Endian::EEndianType targetEndianType) { - MCore::Endian::ConvertSignedInt16(&value->mX, EXPLIB_PLATFORM_ENDIAN, targetEndianType); - MCore::Endian::ConvertSignedInt16(&value->mY, EXPLIB_PLATFORM_ENDIAN, targetEndianType); - MCore::Endian::ConvertSignedInt16(&value->mZ, EXPLIB_PLATFORM_ENDIAN, targetEndianType); - MCore::Endian::ConvertSignedInt16(&value->mW, EXPLIB_PLATFORM_ENDIAN, targetEndianType); + MCore::Endian::ConvertSignedInt16(&value->m_x, EXPLIB_PLATFORM_ENDIAN, targetEndianType); + MCore::Endian::ConvertSignedInt16(&value->m_y, EXPLIB_PLATFORM_ENDIAN, targetEndianType); + MCore::Endian::ConvertSignedInt16(&value->m_z, EXPLIB_PLATFORM_ENDIAN, targetEndianType); + MCore::Endian::ConvertSignedInt16(&value->m_w, EXPLIB_PLATFORM_ENDIAN, targetEndianType); } void ConvertFileMotionEvent(EMotionFX::FileFormat::FileMotionEvent* value, MCore::Endian::EEndianType targetEndianType) { - MCore::Endian::ConvertFloat(&value->mStartTime, EXPLIB_PLATFORM_ENDIAN, targetEndianType); - MCore::Endian::ConvertFloat(&value->mEndTime, EXPLIB_PLATFORM_ENDIAN, targetEndianType); - MCore::Endian::ConvertUnsignedInt32(&value->mEventTypeIndex, EXPLIB_PLATFORM_ENDIAN, targetEndianType); - MCore::Endian::ConvertUnsignedInt32(&value->mMirrorTypeIndex, EXPLIB_PLATFORM_ENDIAN, targetEndianType); - MCore::Endian::ConvertUnsignedInt16(&value->mParamIndex, EXPLIB_PLATFORM_ENDIAN, targetEndianType); + MCore::Endian::ConvertFloat(&value->m_startTime, EXPLIB_PLATFORM_ENDIAN, targetEndianType); + MCore::Endian::ConvertFloat(&value->m_endTime, EXPLIB_PLATFORM_ENDIAN, targetEndianType); + MCore::Endian::ConvertUnsignedInt32(&value->m_eventTypeIndex, EXPLIB_PLATFORM_ENDIAN, targetEndianType); + MCore::Endian::ConvertUnsignedInt32(&value->m_mirrorTypeIndex, EXPLIB_PLATFORM_ENDIAN, targetEndianType); + MCore::Endian::ConvertUnsignedInt16(&value->m_paramIndex, EXPLIB_PLATFORM_ENDIAN, targetEndianType); } void ConvertFileMotionEventTable(EMotionFX::FileFormat::FileMotionEventTrack* value, MCore::Endian::EEndianType targetEndianType) { - MCore::Endian::ConvertUnsignedInt32(&value->mNumEvents, EXPLIB_PLATFORM_ENDIAN, targetEndianType); - MCore::Endian::ConvertUnsignedInt32(&value->mNumTypeStrings, EXPLIB_PLATFORM_ENDIAN, targetEndianType); - MCore::Endian::ConvertUnsignedInt32(&value->mNumParamStrings, EXPLIB_PLATFORM_ENDIAN, targetEndianType); - MCore::Endian::ConvertUnsignedInt32(&value->mNumMirrorTypeStrings, EXPLIB_PLATFORM_ENDIAN, targetEndianType); + MCore::Endian::ConvertUnsignedInt32(&value->m_numEvents, EXPLIB_PLATFORM_ENDIAN, targetEndianType); + MCore::Endian::ConvertUnsignedInt32(&value->m_numTypeStrings, EXPLIB_PLATFORM_ENDIAN, targetEndianType); + MCore::Endian::ConvertUnsignedInt32(&value->m_numParamStrings, EXPLIB_PLATFORM_ENDIAN, targetEndianType); + MCore::Endian::ConvertUnsignedInt32(&value->m_numMirrorTypeStrings, EXPLIB_PLATFORM_ENDIAN, targetEndianType); } void ConvertRGBAColor(MCore::RGBAColor* value, MCore::Endian::EEndianType targetEndianType) { - MCore::Endian::ConvertFloat(&value->r, EXPLIB_PLATFORM_ENDIAN, targetEndianType); - MCore::Endian::ConvertFloat(&value->g, EXPLIB_PLATFORM_ENDIAN, targetEndianType); - MCore::Endian::ConvertFloat(&value->b, EXPLIB_PLATFORM_ENDIAN, targetEndianType); - MCore::Endian::ConvertFloat(&value->a, EXPLIB_PLATFORM_ENDIAN, targetEndianType); + MCore::Endian::ConvertFloat(&value->m_r, EXPLIB_PLATFORM_ENDIAN, targetEndianType); + MCore::Endian::ConvertFloat(&value->m_g, EXPLIB_PLATFORM_ENDIAN, targetEndianType); + MCore::Endian::ConvertFloat(&value->m_b, EXPLIB_PLATFORM_ENDIAN, targetEndianType); + MCore::Endian::ConvertFloat(&value->m_a, EXPLIB_PLATFORM_ENDIAN, targetEndianType); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/ExporterActor.cpp b/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/ExporterActor.cpp index 491326552e..598e5fcc9e 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/ExporterActor.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/ExporterActor.cpp @@ -52,9 +52,9 @@ namespace ExporterLib const AZ::u32 bufferSize = static_cast(buffer.size()); EMotionFX::FileFormat::FileChunk chunkHeader; - chunkHeader.mChunkID = EMotionFX::FileFormat::ACTOR_CHUNK_PHYSICSSETUP; - chunkHeader.mVersion = 1; - chunkHeader.mSizeInBytes = bufferSize + sizeof(AZ::u32); + chunkHeader.m_chunkId = EMotionFX::FileFormat::ACTOR_CHUNK_PHYSICSSETUP; + chunkHeader.m_version = 1; + chunkHeader.m_sizeInBytes = bufferSize + sizeof(AZ::u32); ConvertFileChunk(&chunkHeader, targetEndianType); file->Write(&chunkHeader, sizeof(EMotionFX::FileFormat::FileChunk)); @@ -90,9 +90,9 @@ namespace ExporterLib const AZ::u32 bufferSize = static_cast(buffer.size()); EMotionFX::FileFormat::FileChunk chunkHeader; - chunkHeader.mChunkID = EMotionFX::FileFormat::ACTOR_CHUNK_SIMULATEDOBJECTSETUP; - chunkHeader.mVersion = 1; - chunkHeader.mSizeInBytes = bufferSize + sizeof(AZ::u32); + chunkHeader.m_chunkId = EMotionFX::FileFormat::ACTOR_CHUNK_SIMULATEDOBJECTSETUP; + chunkHeader.m_version = 1; + chunkHeader.m_sizeInBytes = bufferSize + sizeof(AZ::u32); ConvertFileChunk(&chunkHeader, targetEndianType); file->Write(&chunkHeader, sizeof(EMotionFX::FileFormat::FileChunk)); @@ -122,9 +122,9 @@ namespace ExporterLib // Write the chunk header EMotionFX::FileFormat::FileChunk chunkHeader; - chunkHeader.mChunkID = EMotionFX::FileFormat::ACTOR_CHUNK_MESHASSET; - chunkHeader.mSizeInBytes = sizeof(EMotionFX::FileFormat::Actor_MeshAsset) + GetStringChunkSize(meshAssetIdString.c_str()); - chunkHeader.mVersion = 1; + chunkHeader.m_chunkId = EMotionFX::FileFormat::ACTOR_CHUNK_MESHASSET; + chunkHeader.m_sizeInBytes = sizeof(EMotionFX::FileFormat::Actor_MeshAsset) + GetStringChunkSize(meshAssetIdString.c_str()); + chunkHeader.m_version = 1; ConvertFileChunk(&chunkHeader, targetEndianType); file->Write(&chunkHeader, sizeof(EMotionFX::FileFormat::FileChunk)); diff --git a/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/FileHeaderExport.cpp b/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/FileHeaderExport.cpp index bafc899d4e..ffeab884a5 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/FileHeaderExport.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/FileHeaderExport.cpp @@ -23,14 +23,13 @@ namespace ExporterLib // the header information EMotionFX::FileFormat::Actor_Header header; memset(&header, 0, sizeof(EMotionFX::FileFormat::Actor_Header)); - header.mFourcc[0] = 'A'; - header.mFourcc[1] = 'C'; - header.mFourcc[2] = 'T'; - header.mFourcc[3] = 'R'; - header.mHiVersion = static_cast(GetFileHighVersion()); - header.mLoVersion = static_cast(GetFileLowVersion()); - header.mEndianType = static_cast(targetEndianType); - //header.mMulOrder = EMotionFX::FileFormat::MULORDER_ROT_SCALE_TRANS; + header.m_fourcc[0] = 'A'; + header.m_fourcc[1] = 'C'; + header.m_fourcc[2] = 'T'; + header.m_fourcc[3] = 'R'; + header.m_hiVersion = static_cast(GetFileHighVersion()); + header.m_loVersion = static_cast(GetFileLowVersion()); + header.m_endianType = static_cast(targetEndianType); // write the header to the stream file->Write(&header, sizeof(EMotionFX::FileFormat::Actor_Header)); @@ -50,42 +49,42 @@ namespace ExporterLib { // chunk header EMotionFX::FileFormat::FileChunk chunkHeader; - chunkHeader.mChunkID = EMotionFX::FileFormat::ACTOR_CHUNK_INFO; + chunkHeader.m_chunkId = EMotionFX::FileFormat::ACTOR_CHUNK_INFO; - chunkHeader.mSizeInBytes = sizeof(EMotionFX::FileFormat::Actor_Info3); - chunkHeader.mSizeInBytes += GetStringChunkSize(sourceApp); - chunkHeader.mSizeInBytes += GetStringChunkSize(orgFileName); - chunkHeader.mSizeInBytes += GetStringChunkSize(GetCompilationDate()); - chunkHeader.mSizeInBytes += GetStringChunkSize(actorName); + chunkHeader.m_sizeInBytes = sizeof(EMotionFX::FileFormat::Actor_Info3); + chunkHeader.m_sizeInBytes += GetStringChunkSize(sourceApp); + chunkHeader.m_sizeInBytes += GetStringChunkSize(orgFileName); + chunkHeader.m_sizeInBytes += GetStringChunkSize(GetCompilationDate()); + chunkHeader.m_sizeInBytes += GetStringChunkSize(actorName); - chunkHeader.mVersion = 3; + chunkHeader.m_version = 3; EMotionFX::FileFormat::Actor_Info3 infoChunk; memset(&infoChunk, 0, sizeof(EMotionFX::FileFormat::Actor_Info3)); - infoChunk.mNumLODs = aznumeric_caster(numLODLevels); - infoChunk.mMotionExtractionNodeIndex = aznumeric_caster(motionExtractionNodeIndex); - infoChunk.mRetargetRootNodeIndex = aznumeric_caster(retargetRootNodeIndex); - infoChunk.mExporterHighVersion = static_cast(EMotionFX::GetEMotionFX().GetHighVersion()); - infoChunk.mExporterLowVersion = static_cast(EMotionFX::GetEMotionFX().GetLowVersion()); - infoChunk.mUnitType = static_cast(unitType); - infoChunk.mOptimizeSkeleton = optimizeSkeleton ? 1 : 0; + infoChunk.m_numLoDs = aznumeric_caster(numLODLevels); + infoChunk.m_motionExtractionNodeIndex = aznumeric_caster(motionExtractionNodeIndex); + infoChunk.m_retargetRootNodeIndex = aznumeric_caster(retargetRootNodeIndex); + infoChunk.m_exporterHighVersion = static_cast(EMotionFX::GetEMotionFX().GetHighVersion()); + infoChunk.m_exporterLowVersion = static_cast(EMotionFX::GetEMotionFX().GetLowVersion()); + infoChunk.m_unitType = static_cast(unitType); + infoChunk.m_optimizeSkeleton = optimizeSkeleton ? 1 : 0; // print repositioning node information MCore::LogDetailedInfo("- File Info"); MCore::LogDetailedInfo(" + Actor Name: '%s'", actorName); MCore::LogDetailedInfo(" + Source Application: '%s'", sourceApp); MCore::LogDetailedInfo(" + Original File: '%s'", orgFileName); - MCore::LogDetailedInfo(" + Exporter Version: v%d.%d", infoChunk.mExporterHighVersion, infoChunk.mExporterLowVersion); + MCore::LogDetailedInfo(" + Exporter Version: v%d.%d", infoChunk.m_exporterHighVersion, infoChunk.m_exporterLowVersion); MCore::LogDetailedInfo(" + Exporter Compilation Date: '%s'", GetCompilationDate()); - MCore::LogDetailedInfo(" + Num LODs = %d", infoChunk.mNumLODs); - MCore::LogDetailedInfo(" + Motion extraction node index = %d", infoChunk.mMotionExtractionNodeIndex); - MCore::LogDetailedInfo(" + Retarget root node index = %d", infoChunk.mRetargetRootNodeIndex); + MCore::LogDetailedInfo(" + Num LODs = %d", infoChunk.m_numLoDs); + MCore::LogDetailedInfo(" + Motion extraction node index = %d", infoChunk.m_motionExtractionNodeIndex); + MCore::LogDetailedInfo(" + Retarget root node index = %d", infoChunk.m_retargetRootNodeIndex); // endian conversion ConvertFileChunk(&chunkHeader, targetEndianType); - ConvertUnsignedInt(&infoChunk.mMotionExtractionNodeIndex, targetEndianType); - ConvertUnsignedInt(&infoChunk.mRetargetRootNodeIndex, targetEndianType); - ConvertUnsignedInt(&infoChunk.mNumLODs, targetEndianType); + ConvertUnsignedInt(&infoChunk.m_motionExtractionNodeIndex, targetEndianType); + ConvertUnsignedInt(&infoChunk.m_retargetRootNodeIndex, targetEndianType); + ConvertUnsignedInt(&infoChunk.m_numLoDs, targetEndianType); file->Write(&chunkHeader, sizeof(EMotionFX::FileFormat::FileChunk)); file->Write(&infoChunk, sizeof(EMotionFX::FileFormat::Actor_Info3)); @@ -104,14 +103,14 @@ namespace ExporterLib EMotionFX::FileFormat::Motion_Header header; memset(&header, 0, sizeof(EMotionFX::FileFormat::Motion_Header)); - header.mFourcc[0] = 'M'; - header.mFourcc[1] = 'O'; - header.mFourcc[2] = 'T'; - header.mFourcc[3] = ' '; + header.m_fourcc[0] = 'M'; + header.m_fourcc[1] = 'O'; + header.m_fourcc[2] = 'T'; + header.m_fourcc[3] = ' '; - header.mHiVersion = static_cast(GetFileHighVersion()); - header.mLoVersion = static_cast(GetFileLowVersion()); - header.mEndianType = static_cast(targetEndianType); + header.m_hiVersion = static_cast(GetFileHighVersion()); + header.m_loVersion = static_cast(GetFileLowVersion()); + header.m_endianType = static_cast(targetEndianType); // write the header to the stream file->Write(&header, sizeof(EMotionFX::FileFormat::Motion_Header)); @@ -122,26 +121,26 @@ namespace ExporterLib { // chunk header EMotionFX::FileFormat::FileChunk chunkHeader; - chunkHeader.mChunkID = EMotionFX::FileFormat::MOTION_CHUNK_INFO; - chunkHeader.mSizeInBytes = sizeof(EMotionFX::FileFormat::Motion_Info3); - chunkHeader.mVersion = 3; + chunkHeader.m_chunkId = EMotionFX::FileFormat::MOTION_CHUNK_INFO; + chunkHeader.m_sizeInBytes = sizeof(EMotionFX::FileFormat::Motion_Info3); + chunkHeader.m_version = 3; EMotionFX::FileFormat::Motion_Info3 infoChunk; memset(&infoChunk, 0, sizeof(EMotionFX::FileFormat::Motion_Info3)); - infoChunk.mMotionExtractionFlags = motion->GetMotionExtractionFlags(); - infoChunk.mMotionExtractionNodeIndex= MCORE_INVALIDINDEX32; // not used anymore - infoChunk.mUnitType = static_cast(motion->GetUnitType()); - infoChunk.mIsAdditive = motion->GetMotionData()->IsAdditive() ? 1 : 0; + infoChunk.m_motionExtractionFlags = motion->GetMotionExtractionFlags(); + infoChunk.m_motionExtractionNodeIndex= MCORE_INVALIDINDEX32; // not used anymore + infoChunk.m_unitType = static_cast(motion->GetUnitType()); + infoChunk.m_isAdditive = motion->GetMotionData()->IsAdditive() ? 1 : 0; MCore::LogDetailedInfo("- File Info"); MCore::LogDetailedInfo(" + Exporter Compilation Date = '%s'", GetCompilationDate()); - MCore::LogDetailedInfo(" + Motion Extraction Flags = 0x%x [capZ=%d]", infoChunk.mMotionExtractionFlags, (infoChunk.mMotionExtractionFlags & EMotionFX::MOTIONEXTRACT_CAPTURE_Z) ? 1 : 0); + MCore::LogDetailedInfo(" + Motion Extraction Flags = 0x%x [capZ=%d]", infoChunk.m_motionExtractionFlags, (infoChunk.m_motionExtractionFlags & EMotionFX::MOTIONEXTRACT_CAPTURE_Z) ? 1 : 0); // endian conversion ConvertFileChunk(&chunkHeader, targetEndianType); - ConvertUnsignedInt(&infoChunk.mMotionExtractionFlags, targetEndianType); - ConvertUnsignedInt(&infoChunk.mMotionExtractionNodeIndex, targetEndianType); + ConvertUnsignedInt(&infoChunk.m_motionExtractionFlags, targetEndianType); + ConvertUnsignedInt(&infoChunk.m_motionExtractionNodeIndex, targetEndianType); file->Write(&chunkHeader, sizeof(EMotionFX::FileFormat::FileChunk)); file->Write(&infoChunk, sizeof(EMotionFX::FileFormat::Motion_Info2)); diff --git a/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/MaterialExport.cpp b/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/MaterialExport.cpp deleted file mode 100644 index 8bd005af6c..0000000000 --- a/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/MaterialExport.cpp +++ /dev/null @@ -1,298 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -#include "Exporter.h" -#include -#include -#include - -#include -#include - - -namespace ExporterLib -{ - // write the material attribute set - void SaveMaterialAttributeSet(MCore::Stream* file, EMotionFX::Material* material, uint32 lodLevel, uint32 materialNumber, MCore::Endian::EEndianType targetEndianType) - { - AZ_UNUSED(material); - // write the chunk header - EMotionFX::FileFormat::FileChunk chunkHeader; - chunkHeader.mChunkID = EMotionFX::FileFormat::ACTOR_CHUNK_MATERIALATTRIBUTESET; - chunkHeader.mSizeInBytes = sizeof(EMotionFX::FileFormat::Actor_MaterialAttributeSet); - chunkHeader.mVersion = 1; - ConvertFileChunk(&chunkHeader, targetEndianType); - file->Write(&chunkHeader, sizeof(EMotionFX::FileFormat::FileChunk)); - - // write the attribute set info header - EMotionFX::FileFormat::Actor_MaterialAttributeSet setInfo; - setInfo.mMaterialIndex = materialNumber; - setInfo.mLODLevel = lodLevel; - ConvertUnsignedInt(&setInfo.mMaterialIndex, targetEndianType); - ConvertUnsignedInt(&setInfo.mLODLevel, targetEndianType); - file->Write(&setInfo, sizeof(EMotionFX::FileFormat::Actor_MaterialAttributeSet)); - - // Write a former empty attribute set. - uint8 version = 1; - file->Write(&version, sizeof(uint8)); - - uint32 numAttributes = 0; - ConvertUnsignedInt(&numAttributes, targetEndianType); - file->Write(&numAttributes, sizeof(uint32)); - } - - - // save the given material for the given LOD level - void SaveMaterial(MCore::Stream* file, EMotionFX::Material* material, uint32 lodLevel, uint32 materialNumber, MCore::Endian::EEndianType targetEndianType) - { - //---------------------------------------- - // Generic EMotionFX::Material - //---------------------------------------- - if (material->GetType() == EMotionFX::Material::TYPE_ID) - { - // chunk header - EMotionFX::FileFormat::FileChunk chunkHeader; - chunkHeader.mChunkID = EMotionFX::FileFormat::ACTOR_CHUNK_GENERICMATERIAL; - chunkHeader.mSizeInBytes = sizeof(EMotionFX::FileFormat::Actor_GenericMaterial) + GetStringChunkSize(material->GetName()); - chunkHeader.mVersion = 1; - - EMotionFX::FileFormat::Actor_GenericMaterial materialChunk; - materialChunk.mLOD = lodLevel; - - ConvertFileChunk(&chunkHeader, targetEndianType); - ConvertUnsignedInt(&materialChunk.mLOD, targetEndianType); - - // write header and material - file->Write(&chunkHeader, sizeof(EMotionFX::FileFormat::FileChunk)); - file->Write(&materialChunk, sizeof(EMotionFX::FileFormat::Actor_GenericMaterial)); - - // followed by: - SaveString(material->GetName(), file, targetEndianType); - - MCore::LogDetailedInfo("- Generic material:"); - MCore::LogDetailedInfo(" + Name: '%s'", material->GetName()); - MCore::LogDetailedInfo(" + LOD: %d", lodLevel); - } - - //---------------------------------------- - // Standard EMotionFX::Material - //---------------------------------------- - if (material->GetType() == EMotionFX::StandardMaterial::TYPE_ID) - { - // typecast to a standard material - EMotionFX::StandardMaterial* standardMaterial = (EMotionFX::StandardMaterial*)material; - - // chunk header - EMotionFX::FileFormat::FileChunk chunkHeader; - chunkHeader.mChunkID = EMotionFX::FileFormat::ACTOR_CHUNK_STDMATERIAL; - chunkHeader.mSizeInBytes = sizeof(EMotionFX::FileFormat::Actor_StandardMaterial) + GetStringChunkSize(standardMaterial->GetName()); - chunkHeader.mVersion = 1; - - const uint32 numLayers = standardMaterial->GetNumLayers(); - for (uint32 i = 0; i < numLayers; ++i) - { - chunkHeader.mSizeInBytes += sizeof(EMotionFX::FileFormat::Actor_StandardMaterialLayer); - chunkHeader.mSizeInBytes += GetStringChunkSize(standardMaterial->GetLayer(i)->GetFileName()); - } - - EMotionFX::FileFormat::Actor_StandardMaterial materialChunk; - CopyColor(standardMaterial->GetAmbient(), materialChunk.mAmbient); - CopyColor(standardMaterial->GetDiffuse(), materialChunk.mDiffuse); - CopyColor(standardMaterial->GetSpecular(), materialChunk.mSpecular); - CopyColor(standardMaterial->GetEmissive(), materialChunk.mEmissive); - materialChunk.mDoubleSided = standardMaterial->GetDoubleSided(); - materialChunk.mIOR = standardMaterial->GetIOR(); - materialChunk.mOpacity = standardMaterial->GetOpacity(); - materialChunk.mShine = standardMaterial->GetShine(); - materialChunk.mShineStrength = standardMaterial->GetShineStrength(); - materialChunk.mTransparencyType = 'F';//standardMaterial->GetTransparencyType(); - materialChunk.mWireFrame = standardMaterial->GetWireFrame(); - materialChunk.mNumLayers = static_cast(standardMaterial->GetNumLayers()); - materialChunk.mLOD = lodLevel; - - // add it to the log file - MCore::LogDetailedInfo("- Standard material:"); - MCore::LogDetailedInfo(" + Name: '%s'", standardMaterial->GetName()); - MCore::LogDetailedInfo(" + LOD: %d", lodLevel); - MCore::LogDetailedInfo(" + Ambient: r=%f g=%f b=%f", materialChunk.mAmbient.mR, materialChunk.mAmbient.mG, materialChunk.mAmbient.mB); - MCore::LogDetailedInfo(" + Diffuse: r=%f g=%f b=%f", materialChunk.mDiffuse.mR, materialChunk.mDiffuse.mG, materialChunk.mDiffuse.mB); - MCore::LogDetailedInfo(" + Specular: r=%f g=%f b=%f", materialChunk.mSpecular.mR, materialChunk.mSpecular.mG, materialChunk.mSpecular.mB); - MCore::LogDetailedInfo(" + Emissive: r=%f g=%f b=%f", materialChunk.mEmissive.mR, materialChunk.mEmissive.mG, materialChunk.mEmissive.mB); - MCore::LogDetailedInfo(" + Shine: %f", materialChunk.mShine); - MCore::LogDetailedInfo(" + ShineStrength: %f", materialChunk.mShineStrength); - MCore::LogDetailedInfo(" + Opacity: %f", materialChunk.mOpacity); - MCore::LogDetailedInfo(" + IndexOfRefraction: %f", materialChunk.mIOR); - MCore::LogDetailedInfo(" + DoubleSided: %i", (int)materialChunk.mDoubleSided); - MCore::LogDetailedInfo(" + WireFrame: %i", (int)materialChunk.mWireFrame); - MCore::LogDetailedInfo(" + TransparencyType: %c", (char)materialChunk.mTransparencyType); - MCore::LogDetailedInfo(" + NumLayers: %i", materialChunk.mNumLayers); - - // endian conversion - ConvertFileChunk(&chunkHeader, targetEndianType); - ConvertFileColor(&materialChunk.mAmbient, targetEndianType); - ConvertFileColor(&materialChunk.mDiffuse, targetEndianType); - ConvertFileColor(&materialChunk.mSpecular, targetEndianType); - ConvertFileColor(&materialChunk.mEmissive, targetEndianType); - ConvertFloat(&materialChunk.mIOR, targetEndianType); - ConvertFloat(&materialChunk.mOpacity, targetEndianType); - ConvertFloat(&materialChunk.mShine, targetEndianType); - ConvertFloat(&materialChunk.mShineStrength, targetEndianType); - ConvertUnsignedInt(&materialChunk.mLOD, targetEndianType); - - // write header and material - file->Write(&chunkHeader, sizeof(EMotionFX::FileFormat::FileChunk)); - file->Write(&materialChunk, sizeof(EMotionFX::FileFormat::Actor_StandardMaterial)); - - // followed by: - SaveString(standardMaterial->GetName(), file, targetEndianType); - - // save all material layers - for (uint32 i = 0; i < numLayers; ++i) - { - // get the layer - EMotionFX::StandardMaterialLayer* layer = standardMaterial->GetLayer(i); - - EMotionFX::FileFormat::Actor_StandardMaterialLayer materialChunkLayer; - materialChunkLayer.mAmount = layer->GetAmount(); - materialChunkLayer.mMapType = static_cast(layer->GetType()); - materialChunkLayer.mMaterialNumber = (uint16)materialNumber; - materialChunkLayer.mRotationRadians = layer->GetRotationRadians(); - materialChunkLayer.mUOffset = layer->GetUOffset(); - materialChunkLayer.mVOffset = layer->GetVOffset(); - materialChunkLayer.mUTiling = layer->GetUTiling(); - materialChunkLayer.mVTiling = layer->GetVTiling(); - materialChunkLayer.mBlendMode = layer->GetBlendMode(); - - // add to log file - MCore::LogDetailedInfo(" - Material layer #%d:", i); - MCore::LogDetailedInfo(" + Name: '%s' (MatNr=%i)", layer->GetFileName(), materialNumber); - MCore::LogDetailedInfo(" + Amount: %f", materialChunkLayer.mAmount); - MCore::LogDetailedInfo(" + Type: %i", (int)materialChunkLayer.mMapType); - MCore::LogDetailedInfo(" + BlendMode: %i", (int)materialChunkLayer.mBlendMode); - MCore::LogDetailedInfo(" + MaterialNumber: %i", (uint32)materialChunkLayer.mMaterialNumber); - MCore::LogDetailedInfo(" + UOffset: %f", materialChunkLayer.mUOffset); - MCore::LogDetailedInfo(" + VOffset: %f", materialChunkLayer.mVOffset); - MCore::LogDetailedInfo(" + UTiling: %f", materialChunkLayer.mUTiling); - MCore::LogDetailedInfo(" + VTiling: %f", materialChunkLayer.mVTiling); - MCore::LogDetailedInfo(" + RotationRadians: %f", materialChunkLayer.mRotationRadians); - - // endian conversion - ConvertFloat(&materialChunkLayer.mAmount, targetEndianType); - ConvertUnsignedShort(&materialChunkLayer.mMaterialNumber, targetEndianType); - ConvertFloat(&materialChunkLayer.mRotationRadians, targetEndianType); - ConvertFloat(&materialChunkLayer.mUOffset, targetEndianType); - ConvertFloat(&materialChunkLayer.mVOffset, targetEndianType); - ConvertFloat(&materialChunkLayer.mUTiling, targetEndianType); - ConvertFloat(&materialChunkLayer.mVTiling, targetEndianType); - - // write header and material layer - file->Write(&materialChunkLayer, sizeof(EMotionFX::FileFormat::Actor_StandardMaterialLayer)); - SaveString(layer->GetFileName(), file, targetEndianType); - } - } - } - - - // save the given materials - void SaveMaterials(MCore::Stream* file, AZStd::vector& materials, uint32 lodLevel, MCore::Endian::EEndianType targetEndianType) - { - // get the number of materials - const uint32 numMaterials = materials.size(); - - // chunk header - EMotionFX::FileFormat::FileChunk chunkHeader; - chunkHeader.mChunkID = EMotionFX::FileFormat::ACTOR_CHUNK_MATERIALINFO; - chunkHeader.mSizeInBytes = sizeof(EMotionFX::FileFormat::Actor_MaterialInfo); - chunkHeader.mVersion = 1; - - // convert endian and write to file - ConvertFileChunk(&chunkHeader, targetEndianType); - file->Write(&chunkHeader, sizeof(EMotionFX::FileFormat::FileChunk)); - - EMotionFX::FileFormat::Actor_MaterialInfo materialInfoChunk; - materialInfoChunk.mLOD = lodLevel; - materialInfoChunk.mNumTotalMaterials = numMaterials; - materialInfoChunk.mNumStandardMaterials = 0; - materialInfoChunk.mNumFXMaterials = 0; - materialInfoChunk.mNumGenericMaterials = 0; - - for (uint32 i = 0; i < numMaterials; i++) - { - if (materials[i]->GetType() == EMotionFX::Material::TYPE_ID) - { - materialInfoChunk.mNumGenericMaterials++; - } - - if (materials[i]->GetType() == EMotionFX::StandardMaterial::TYPE_ID) - { - materialInfoChunk.mNumStandardMaterials++; - } - } - - MCore::LogDetailedInfo("============================================================"); - MCore::LogInfo("Materials (%d)", numMaterials); - MCore::LogDetailedInfo("============================================================"); - - MCORE_ASSERT(materialInfoChunk.mNumTotalMaterials == materialInfoChunk.mNumStandardMaterials + materialInfoChunk.mNumFXMaterials + materialInfoChunk.mNumGenericMaterials); - - // convert endian and write to disk - ConvertUnsignedInt(&materialInfoChunk.mNumTotalMaterials, targetEndianType); - ConvertUnsignedInt(&materialInfoChunk.mNumStandardMaterials, targetEndianType); - ConvertUnsignedInt(&materialInfoChunk.mNumFXMaterials, targetEndianType); - ConvertUnsignedInt(&materialInfoChunk.mNumGenericMaterials, targetEndianType); - ConvertUnsignedInt(&materialInfoChunk.mLOD, targetEndianType); - file->Write(&materialInfoChunk, sizeof(EMotionFX::FileFormat::Actor_MaterialInfo)); - - // export all materials - for (uint32 i = 0; i < numMaterials; i++) - { - SaveMaterial(file, materials[i], lodLevel, i, targetEndianType); - } - - // save all material attribute sets - for (uint32 i = 0; i < numMaterials; i++) - { - SaveMaterialAttributeSet(file, materials[i], lodLevel, i, targetEndianType); - } - } - - - // save out all materials for a given LOD level - void SaveMaterials(MCore::Stream* file, EMotionFX::Actor* actor, uint32 lodLevel, MCore::Endian::EEndianType targetEndianType) - { - // get the number of materials in the given lod level - const uint32 numMaterials = actor->GetNumMaterials(lodLevel); - - // create our materials array and reserve some elements - AZStd::vector materials; - materials.reserve(numMaterials); - - // iterate through the materials - for (uint32 j = 0; j < numMaterials; j++) - { - // get the base material - EMotionFX::Material* baseMaterial = actor->GetMaterial(lodLevel, j); - materials.emplace_back(baseMaterial); - } - - // save the materials - SaveMaterials(file, materials, lodLevel, targetEndianType); - } - - - // save all materials for all LOD levels - void SaveMaterials(MCore::Stream* file, EMotionFX::Actor* actor, MCore::Endian::EEndianType targetEndianType) - { - // get the number of LOD levels and iterate through them - const uint32 numLODLevels = actor->GetNumLODLevels(); - for (uint32 i = 0; i < numLODLevels; ++i) - { - SaveMaterials(file, actor, i, targetEndianType); - } - } -} // namespace ExporterLib diff --git a/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/MeshExport.cpp b/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/MeshExport.cpp deleted file mode 100644 index 40b13d896f..0000000000 --- a/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/MeshExport.cpp +++ /dev/null @@ -1,270 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -#include "Exporter.h" -#include -#include -#include -#include -#include -#include -#include - - -namespace ExporterLib -{ - // save the given mesh - void SaveMesh(MCore::Stream* file, EMotionFX::Mesh* mesh, uint32 nodeIndex, bool isCollisionMesh, uint32 lodLevel, MCore::Endian::EEndianType targetEndianType) - { - // convert endian for abstract layers - for (uint32 i = 0; i < mesh->GetNumVertexAttributeLayers(); ++i) - { - EMotionFX::VertexAttributeLayer* layer = mesh->GetVertexAttributeLayer(i); - if (!layer->GetIsAbstractDataClass()) - { - continue; - } - - EMotionFX::VertexAttributeLayerAbstractData* abstractLayer = static_cast(layer); - - const uint32 type = abstractLayer->GetType(); - - EMotionFX::Importer::AbstractLayerConverter layerConvertFunction; - layerConvertFunction = EMotionFX::Importer::StandardLayerConvert; - - // convert endian and coordinate systems of all data - if (layerConvertFunction(abstractLayer, targetEndianType) == false) - { - MCore::LogError("Don't know how to endian and/or coordinate system convert layer with type %d (%s)", type, EMotionFX::Importer::ActorVertexAttributeLayerTypeToString(type)); - } - } - - uint32 totalSize = sizeof(EMotionFX::FileFormat::Actor_Mesh); - - // add all layers to the total size - uint32 numMeshVerts = mesh->GetNumVertices(); - for (uint32 i = 0; i < mesh->GetNumVertexAttributeLayers(); ++i) - { - EMotionFX::VertexAttributeLayer* layer = mesh->GetVertexAttributeLayer(i); - if (!layer->GetIsAbstractDataClass()) - { - continue; - } - - EMotionFX::VertexAttributeLayerAbstractData* abstractLayer = static_cast(layer); - - totalSize += sizeof(EMotionFX::FileFormat::Actor_VertexAttributeLayer); - totalSize += numMeshVerts * abstractLayer->GetAttributeSizeInBytes(); - totalSize += GetStringChunkSize(layer->GetNameString()); - } - - // add the submeshes - for (uint32 i = 0; i < mesh->GetNumSubMeshes(); ++i) - { - EMotionFX::SubMesh* subMesh = mesh->GetSubMesh(i); - totalSize += sizeof(EMotionFX::FileFormat::Actor_SubMesh); - totalSize += sizeof(uint32) * subMesh->GetNumIndices(); - totalSize += sizeof(uint8) * subMesh->GetNumPolygons(); - totalSize += sizeof(uint32) * subMesh->GetNumBones(); - } - - // write the chunk header - EMotionFX::FileFormat::FileChunk chunkHeader; - chunkHeader.mChunkID = EMotionFX::FileFormat::ACTOR_CHUNK_MESH; - chunkHeader.mSizeInBytes = totalSize; - chunkHeader.mVersion = 1; - ConvertFileChunk(&chunkHeader, targetEndianType); - file->Write(&chunkHeader, sizeof(EMotionFX::FileFormat::FileChunk)); - - // write the mesh header - EMotionFX::FileFormat::Actor_Mesh meshHeader; - memset(&meshHeader, 0, sizeof(EMotionFX::FileFormat::Actor_Mesh)); - meshHeader.mIsCollisionMesh = isCollisionMesh ? 1 : 0; - meshHeader.mNodeIndex = nodeIndex; - meshHeader.mNumLayers = mesh->GetNumVertexAttributeLayers(); - meshHeader.mNumOrgVerts = mesh->GetNumOrgVertices(); - meshHeader.mNumSubMeshes = mesh->GetNumSubMeshes(); - meshHeader.mNumPolygons = mesh->GetNumPolygons(); - meshHeader.mTotalIndices = mesh->GetNumIndices(); - meshHeader.mLOD = lodLevel; - meshHeader.mTotalVerts = (mesh->GetNumVertexAttributeLayers() > 0) ? mesh->GetNumVertices() : 0; - meshHeader.mIsTriangleMesh = mesh->CheckIfIsTriangleMesh(); - - MCore::LogDetailedInfo("- Mesh for node with node number %d:", meshHeader.mNodeIndex); - MCore::LogDetailedInfo(" + LOD: %d", meshHeader.mLOD); - MCore::LogDetailedInfo(" + Num original vertices: %d", meshHeader.mNumOrgVerts); - MCore::LogDetailedInfo(" + Total vertices: %d", meshHeader.mTotalVerts); - MCore::LogDetailedInfo(" + Total polygons: %d", meshHeader.mNumPolygons); - MCore::LogDetailedInfo(" + Total indices: %d", meshHeader.mTotalIndices); - MCore::LogDetailedInfo(" + Num submeshes: %d", meshHeader.mNumSubMeshes); - MCore::LogDetailedInfo(" + Num attribute layers: %d", meshHeader.mNumLayers); - MCore::LogDetailedInfo(" + Is collision mesh: %s", meshHeader.mIsCollisionMesh ? "Yes" : "No"); - MCore::LogDetailedInfo(" + Is triangle mesh: %s", meshHeader.mIsTriangleMesh ? "Yes" : "No"); - - //for (uint32 i=0; iGetNumPolygons(); ++i) - //MCore::LogInfo("poly %d = %d verts", i, mesh->GetPolygonVertexCounts()[i] ); - - // convert endian - ConvertUnsignedInt(&meshHeader.mNodeIndex, targetEndianType); - ConvertUnsignedInt(&meshHeader.mNumLayers, targetEndianType); - ConvertUnsignedInt(&meshHeader.mNumSubMeshes, targetEndianType); - ConvertUnsignedInt(&meshHeader.mNumPolygons, targetEndianType); - ConvertUnsignedInt(&meshHeader.mTotalIndices, targetEndianType); - ConvertUnsignedInt(&meshHeader.mTotalVerts, targetEndianType); - ConvertUnsignedInt(&meshHeader.mNumOrgVerts, targetEndianType); - ConvertUnsignedInt(&meshHeader.mLOD, targetEndianType); - - // write to file - file->Write(&meshHeader, sizeof(EMotionFX::FileFormat::Actor_Mesh)); - - // now save all layers - const uint32 numLayers = mesh->GetNumVertexAttributeLayers(); - for (uint32 layerNr = 0; layerNr < numLayers; ++layerNr) - { - EMotionFX::VertexAttributeLayer* layer = mesh->GetVertexAttributeLayer(layerNr); - if (!layer->GetIsAbstractDataClass()) - { - continue; - } - - EMotionFX::VertexAttributeLayerAbstractData* abstractLayer = static_cast(layer); - - EMotionFX::FileFormat::Actor_VertexAttributeLayer fileLayer; - memset(&fileLayer, 0, sizeof(EMotionFX::FileFormat::Actor_VertexAttributeLayer)); - fileLayer.mLayerTypeID = layer->GetType(); - fileLayer.mAttribSizeInBytes = abstractLayer->GetAttributeSizeInBytes(); - fileLayer.mEnableDeformations = layer->GetKeepOriginals() ? 1 : 0; - fileLayer.mIsScale = 0;// TODO: not used - - MCore::LogDetailedInfo(" - Layer #%d (%s):", layerNr, EMotionFX::Importer::ActorVertexAttributeLayerTypeToString(fileLayer.mLayerTypeID)); - MCore::LogDetailedInfo(" + Type ID: %d", fileLayer.mLayerTypeID); - MCore::LogDetailedInfo(" + Attrib size: %d bytes", fileLayer.mAttribSizeInBytes); - MCore::LogDetailedInfo(" + Enable deforms: %s", fileLayer.mEnableDeformations ? "Yes" : "No"); - MCore::LogDetailedInfo(" + Name: %s", layer->GetName()); - - // convert endian - ConvertUnsignedInt(&fileLayer.mAttribSizeInBytes, targetEndianType); - ConvertUnsignedInt(&fileLayer.mLayerTypeID, targetEndianType); - - // write the layer header - file->Write(&fileLayer, sizeof(EMotionFX::FileFormat::Actor_VertexAttributeLayer)); - - // write the name - SaveString(layer->GetNameString(), file, targetEndianType); - - // write the layer - file->Write((uint8*)abstractLayer->GetOriginalData(), abstractLayer->CalcTotalDataSizeInBytes(false)); - } - - - // and finally save all submeshes - const uint32 numSubMeshes = mesh->GetNumSubMeshes(); - for (uint32 s = 0; s < numSubMeshes; ++s) - { - EMotionFX::SubMesh* subMesh = mesh->GetSubMesh(s); - - EMotionFX::FileFormat::Actor_SubMesh fileSubMesh; - fileSubMesh.mMaterialIndex = subMesh->GetMaterial(); - fileSubMesh.mNumBones = subMesh->GetNumBones(); - fileSubMesh.mNumIndices = subMesh->GetNumIndices(); - fileSubMesh.mNumVerts = subMesh->GetNumVertices(); - fileSubMesh.mNumPolygons = subMesh->GetNumPolygons(); - - MCore::LogDetailedInfo(" - SubMesh #%d:", s); - MCore::LogDetailedInfo(" + Material: %d", fileSubMesh.mMaterialIndex); - MCore::LogDetailedInfo(" + Num vertices: %d", fileSubMesh.mNumVerts); - MCore::LogDetailedInfo(" + Num indices: %d (%d polygons)", fileSubMesh.mNumIndices, fileSubMesh.mNumPolygons); - MCore::LogDetailedInfo(" + Num bones: %d", fileSubMesh.mNumBones); - - // convert endian - ConvertUnsignedInt(&fileSubMesh.mMaterialIndex, targetEndianType); - ConvertUnsignedInt(&fileSubMesh.mNumBones, targetEndianType); - ConvertUnsignedInt(&fileSubMesh.mNumIndices, targetEndianType); - ConvertUnsignedInt(&fileSubMesh.mNumPolygons, targetEndianType); - ConvertUnsignedInt(&fileSubMesh.mNumVerts, targetEndianType); - - // write the submesh header - file->Write(&fileSubMesh, sizeof(EMotionFX::FileFormat::Actor_SubMesh)); - - // write the index data - const uint32 numIndices = subMesh->GetNumIndices(); - const uint32 numPolygons = subMesh->GetNumPolygons(); - const uint32 startVertex = subMesh->GetStartVertex(); - uint32* indices = subMesh->GetIndices(); - uint8* polyVertCounts = subMesh->GetPolygonVertexCounts(); - - for (uint32 i = 0; i < numIndices; ++i) - { - uint32 index = indices[i] - startVertex; - ConvertUnsignedInt(&index, targetEndianType); - file->Write(&index, sizeof(uint32)); - } - - for (uint32 i = 0; i < numPolygons; ++i) - { - uint8 numPolyVerts = polyVertCounts[i]; - file->Write(&numPolyVerts, sizeof(uint8)); - } - - // write the bone numbers - const uint32 numBones = subMesh->GetNumBones(); - for (uint32 i = 0; i < numBones; ++i) - { - uint32 value = subMesh->GetBone(i); - ConvertUnsignedInt(&value, targetEndianType); - file->Write(&value, sizeof(uint32)); - } - } - } - - - // save meshes for all nodes for a given LOD level - void SaveMeshes(MCore::Stream* file, EMotionFX::Actor* actor, uint32 lodLevel, MCore::Endian::EEndianType targetEndianType) - { - MCORE_ASSERT(file); - MCORE_ASSERT(actor); - - MCore::LogDetailedInfo("============================================================"); - MCore::LogInfo("Meshes (LOD=%i", lodLevel); - MCore::LogDetailedInfo("============================================================"); - - // get the number of nodes - const uint32 numNodes = actor->GetNumNodes(); - - // iterate through all nodes - for (uint32 i = 0; i < numNodes; i++) - { - // get the node from the actor - //EMotionFX::Node* node = actor->GetSkeleton()->GetNode(i); - - // get the mesh and save it - EMotionFX::Mesh* mesh = actor->GetMesh(lodLevel, i); - if (mesh) - { - SaveMesh(file, mesh, i, mesh->GetIsCollisionMesh(), lodLevel, targetEndianType); - } - - // get the collision mesh and save it - /* EMotionFX::Mesh* collisionMesh = actor->GetCollisionMesh(lodLevel, i); - if (collisionMesh) - SaveMesh( file, collisionMesh, i, true, lodLevel, targetEndianType );*/ - } - } - - - // save all meshes for all nodes and all LOD levels - void SaveMeshes(MCore::Stream* file, EMotionFX::Actor* actor, MCore::Endian::EEndianType targetEndianType) - { - // get the number of LOD levels, iterate through them and save all meshes - const uint32 numLODLevels = actor->GetNumLODLevels(); - for (uint32 i = 0; i < numLODLevels; ++i) - { - SaveMeshes(file, actor, i, targetEndianType); - } - } -} // namespace ExporterLib diff --git a/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/MorphTargetExport.cpp b/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/MorphTargetExport.cpp index 723669d3f1..5205dcbc97 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/MorphTargetExport.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/MorphTargetExport.cpp @@ -32,11 +32,11 @@ namespace ExporterLib // copy over the information to the chunk EMotionFX::FileFormat::Actor_MorphTarget morphTargetChunk; - morphTargetChunk.mLOD = aznumeric_caster(lodLevel); - morphTargetChunk.mNumTransformations = aznumeric_caster(numTransformations); - morphTargetChunk.mRangeMin = morphTarget->GetRangeMin(); - morphTargetChunk.mRangeMax = morphTarget->GetRangeMax(); - morphTargetChunk.mPhonemeSets = morphTarget->GetPhonemeSets(); + morphTargetChunk.m_lod = aznumeric_caster(lodLevel); + morphTargetChunk.m_numTransformations = aznumeric_caster(numTransformations); + morphTargetChunk.m_rangeMin = morphTarget->GetRangeMin(); + morphTargetChunk.m_rangeMax = morphTarget->GetRangeMax(); + morphTargetChunk.m_phonemeSets = morphTarget->GetPhonemeSets(); // log it MCore::LogDetailedInfo(" - Morph Target: Name='%s'", morphTarget->GetName()); @@ -47,11 +47,11 @@ namespace ExporterLib MCore::LogDetailedInfo(" + PhonemesSets: %s", EMotionFX::MorphTarget::GetPhonemeSetString((EMotionFX::MorphTarget::EPhonemeSet)morphTarget->GetPhonemeSets()).c_str()); // convert endian - ConvertFloat(&morphTargetChunk.mRangeMin, targetEndianType); - ConvertFloat(&morphTargetChunk.mRangeMax, targetEndianType); - ConvertUnsignedInt(&morphTargetChunk.mLOD, targetEndianType); - ConvertUnsignedInt(&morphTargetChunk.mNumTransformations, targetEndianType); - ConvertUnsignedInt(&morphTargetChunk.mPhonemeSets, targetEndianType); + ConvertFloat(&morphTargetChunk.m_rangeMin, targetEndianType); + ConvertFloat(&morphTargetChunk.m_rangeMax, targetEndianType); + ConvertUnsignedInt(&morphTargetChunk.m_lod, targetEndianType); + ConvertUnsignedInt(&morphTargetChunk.m_numTransformations, targetEndianType); + ConvertUnsignedInt(&morphTargetChunk.m_phonemeSets, targetEndianType); // write the bones expression part file->Write(&morphTargetChunk, sizeof(EMotionFX::FileFormat::Actor_MorphTarget)); @@ -63,34 +63,34 @@ namespace ExporterLib for (size_t i = 0; i < numTransformations; i++) { EMotionFX::MorphTargetStandard::Transformation transform = morphTarget->GetTransformation(i); - EMotionFX::Node* node = actor->GetSkeleton()->GetNode(transform.mNodeIndex); + EMotionFX::Node* node = actor->GetSkeleton()->GetNode(transform.m_nodeIndex); if (node == nullptr) { - MCore::LogError("Can't get node '%i'. File is corrupt!", transform.mNodeIndex); + MCore::LogError("Can't get node '%i'. File is corrupt!", transform.m_nodeIndex); continue; } // create and fill the transformation EMotionFX::FileFormat::Actor_MorphTargetTransform transformChunk; - transformChunk.mNodeIndex = aznumeric_caster(transform.mNodeIndex); - CopyVector(transformChunk.mPosition, AZ::PackedVector3f(transform.mPosition)); - CopyVector(transformChunk.mScale, AZ::PackedVector3f(transform.mScale)); - CopyQuaternion(transformChunk.mRotation, transform.mRotation); - CopyQuaternion(transformChunk.mScaleRotation, transform.mScaleRotation); + transformChunk.m_nodeIndex = aznumeric_caster(transform.m_nodeIndex); + CopyVector(transformChunk.m_position, AZ::PackedVector3f(transform.m_position)); + CopyVector(transformChunk.m_scale, AZ::PackedVector3f(transform.m_scale)); + CopyQuaternion(transformChunk.m_rotation, transform.m_rotation); + CopyQuaternion(transformChunk.m_scaleRotation, transform.m_scaleRotation); MCore::LogDetailedInfo(" - EMotionFX::Transform #%i: Node='%s' NodeNr=#%i", i, node->GetName(), node->GetNodeIndex()); - MCore::LogDetailedInfo(" + Pos: %f, %f, %f", transformChunk.mPosition.mX, transformChunk.mPosition.mY, transformChunk.mPosition.mZ); - MCore::LogDetailedInfo(" + Rotation: %f, %f, %f %f", transformChunk.mRotation.mX, transformChunk.mRotation.mY, transformChunk.mRotation.mZ, transformChunk.mRotation.mW); - MCore::LogDetailedInfo(" + Scale: %f, %f, %f", transformChunk.mScale.mX, transformChunk.mScale.mY, transformChunk.mScale.mZ); - MCore::LogDetailedInfo(" + ScaleRot: %f, %f, %f %f", transformChunk.mScaleRotation.mX, transformChunk.mScaleRotation.mY, transformChunk.mScaleRotation.mZ, transformChunk.mScaleRotation.mW); + MCore::LogDetailedInfo(" + Pos: %f, %f, %f", transformChunk.m_position.m_x, transformChunk.m_position.m_y, transformChunk.m_position.m_z); + MCore::LogDetailedInfo(" + Rotation: %f, %f, %f %f", transformChunk.m_rotation.m_x, transformChunk.m_rotation.m_y, transformChunk.m_rotation.m_z, transformChunk.m_rotation.m_w); + MCore::LogDetailedInfo(" + Scale: %f, %f, %f", transformChunk.m_scale.m_x, transformChunk.m_scale.m_y, transformChunk.m_scale.m_z); + MCore::LogDetailedInfo(" + ScaleRot: %f, %f, %f %f", transformChunk.m_scaleRotation.m_x, transformChunk.m_scaleRotation.m_y, transformChunk.m_scaleRotation.m_z, transformChunk.m_scaleRotation.m_w); // convert endian and coordinate system - ConvertUnsignedInt(&transformChunk.mNodeIndex, targetEndianType); - ConvertFileVector3(&transformChunk.mPosition, targetEndianType); - ConvertFileVector3(&transformChunk.mScale, targetEndianType); - ConvertFileQuaternion(&transformChunk.mRotation, targetEndianType); - ConvertFileQuaternion(&transformChunk.mScaleRotation, targetEndianType); + ConvertUnsignedInt(&transformChunk.m_nodeIndex, targetEndianType); + ConvertFileVector3(&transformChunk.m_position, targetEndianType); + ConvertFileVector3(&transformChunk.m_scale, targetEndianType); + ConvertFileQuaternion(&transformChunk.m_rotation, targetEndianType); + ConvertFileQuaternion(&transformChunk.m_scaleRotation, targetEndianType); // write the transformation file->Write(&transformChunk, sizeof(EMotionFX::FileFormat::Actor_MorphTargetTransform)); @@ -175,9 +175,9 @@ namespace ExporterLib // fill in the chunk header EMotionFX::FileFormat::FileChunk chunkHeader; - chunkHeader.mChunkID = EMotionFX::FileFormat::ACTOR_CHUNK_STDPMORPHTARGETS; - chunkHeader.mSizeInBytes = aznumeric_caster(GetMorphSetupChunkSize(morphSetup)); - chunkHeader.mVersion = 2; + chunkHeader.m_chunkId = EMotionFX::FileFormat::ACTOR_CHUNK_STDPMORPHTARGETS; + chunkHeader.m_sizeInBytes = aznumeric_caster(GetMorphSetupChunkSize(morphSetup)); + chunkHeader.m_version = 2; // endian convert the chunk and write it to the file ConvertFileChunk(&chunkHeader, targetEndianType); @@ -185,16 +185,16 @@ namespace ExporterLib // fill in the chunk header EMotionFX::FileFormat::Actor_MorphTargets morphTargetsChunk; - morphTargetsChunk.mNumMorphTargets = aznumeric_caster(numSavedMorphTargets); - morphTargetsChunk.mLOD = aznumeric_caster(lodLevel); + morphTargetsChunk.m_numMorphTargets = aznumeric_caster(numSavedMorphTargets); + morphTargetsChunk.m_lod = aznumeric_caster(lodLevel); MCore::LogDetailedInfo("============================================================"); - MCore::LogInfo("Morph Targets (%i, LOD=%d)", morphTargetsChunk.mNumMorphTargets, morphTargetsChunk.mLOD); + MCore::LogInfo("Morph Targets (%i, LOD=%d)", morphTargetsChunk.m_numMorphTargets, morphTargetsChunk.m_lod); MCore::LogDetailedInfo("============================================================"); // endian convert the chunk and write it to the file - ConvertUnsignedInt(&morphTargetsChunk.mNumMorphTargets, targetEndianType); - ConvertUnsignedInt(&morphTargetsChunk.mLOD, targetEndianType); + ConvertUnsignedInt(&morphTargetsChunk.m_numMorphTargets, targetEndianType); + ConvertUnsignedInt(&morphTargetsChunk.m_lod, targetEndianType); file->Write(&morphTargetsChunk, sizeof(EMotionFX::FileFormat::Actor_MorphTargets)); // save morph targets diff --git a/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/MotionEventExport.cpp b/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/MotionEventExport.cpp index 1d29ca1056..e1bde1ff79 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/MotionEventExport.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/MotionEventExport.cpp @@ -66,10 +66,10 @@ namespace ExporterLib // the motion event table chunk header EMotionFX::FileFormat::FileChunk chunkHeader; - chunkHeader.mChunkID = EMotionFX::FileFormat::SHARED_CHUNK_MOTIONEVENTTABLE; - chunkHeader.mVersion = 3; + chunkHeader.m_chunkId = EMotionFX::FileFormat::SHARED_CHUNK_MOTIONEVENTTABLE; + chunkHeader.m_version = 3; - chunkHeader.mSizeInBytes = static_cast(serializedTableSizeInBytes + sizeof(EMotionFX::FileFormat::FileMotionEventTableSerialized)); + chunkHeader.m_sizeInBytes = static_cast(serializedTableSizeInBytes + sizeof(EMotionFX::FileFormat::FileMotionEventTableSerialized)); EMotionFX::FileFormat::FileMotionEventTableSerialized tableHeader; tableHeader.m_size = serializedTableSizeInBytes; diff --git a/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/NodeExport.cpp b/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/NodeExport.cpp index e7f0fa011e..91727b2113 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/NodeExport.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/NodeExport.cpp @@ -29,11 +29,11 @@ namespace ExporterLib const size_t parentIndex = node->GetParentIndex(); const size_t numChilds = node->GetNumChildNodes(); const EMotionFX::Transform& transform = actor->GetBindPose()->GetLocalSpaceTransform(nodeIndex); - AZ::PackedVector3f position = AZ::PackedVector3f(transform.mPosition); - AZ::Quaternion rotation = transform.mRotation.GetNormalized(); + AZ::PackedVector3f position = AZ::PackedVector3f(transform.m_position); + AZ::Quaternion rotation = transform.m_rotation.GetNormalized(); #ifndef EMFX_SCALE_DISABLED - AZ::PackedVector3f scale = AZ::PackedVector3f(transform.mScale); + AZ::PackedVector3f scale = AZ::PackedVector3f(transform.m_scale); #else AZ::PackedVector3f scale(1.0f, 1.0f, 1.0f); #endif @@ -42,12 +42,12 @@ namespace ExporterLib EMotionFX::FileFormat::Actor_Node2 nodeChunk; memset(&nodeChunk, 0, sizeof(EMotionFX::FileFormat::Actor_Node2)); - CopyVector(nodeChunk.mLocalPos, position); - CopyQuaternion(nodeChunk.mLocalQuat, rotation); - CopyVector(nodeChunk.mLocalScale, scale); + CopyVector(nodeChunk.m_localPos, position); + CopyQuaternion(nodeChunk.m_localQuat, rotation); + CopyVector(nodeChunk.m_localScale, scale); - nodeChunk.mNumChilds = aznumeric_caster(numChilds); - nodeChunk.mParentIndex = aznumeric_caster(parentIndex); + nodeChunk.m_numChilds = aznumeric_caster(numChilds); + nodeChunk.m_parentIndex = aznumeric_caster(parentIndex); // calculate and copy over the skeletal LODs uint32 skeletalLODs = 0; @@ -58,26 +58,26 @@ namespace ExporterLib skeletalLODs |= (1 << l); } } - nodeChunk.mSkeletalLODs = skeletalLODs; + nodeChunk.m_skeletalLoDs = skeletalLODs; // will this node be involved in the bounding volume calculations? if (node->GetIncludeInBoundsCalc()) { - nodeChunk.mNodeFlags |= EMotionFX::Node::ENodeFlags::FLAG_INCLUDEINBOUNDSCALC;// first bit + nodeChunk.m_nodeFlags |= EMotionFX::Node::ENodeFlags::FLAG_INCLUDEINBOUNDSCALC;// first bit } else { - nodeChunk.mNodeFlags &= ~EMotionFX::Node::ENodeFlags::FLAG_INCLUDEINBOUNDSCALC; + nodeChunk.m_nodeFlags &= ~EMotionFX::Node::ENodeFlags::FLAG_INCLUDEINBOUNDSCALC; } // Add an isCritical option in node flag so it won't be optimized out. if (node->GetIsCritical()) { - nodeChunk.mNodeFlags |= EMotionFX::Node::ENodeFlags::FLAG_CRITICAL; // third bit + nodeChunk.m_nodeFlags |= EMotionFX::Node::ENodeFlags::FLAG_CRITICAL; // third bit } else { - nodeChunk.mNodeFlags &= ~EMotionFX::Node::ENodeFlags::FLAG_CRITICAL; + nodeChunk.m_nodeFlags &= ~EMotionFX::Node::ENodeFlags::FLAG_CRITICAL; } // log the node chunk information @@ -90,15 +90,15 @@ namespace ExporterLib { MCore::LogDetailedInfo(" + Parent: name='%s' index=%i", actor->GetSkeleton()->GetNode(parentIndex)->GetName(), parentIndex); } - MCore::LogDetailedInfo(" + NumChilds: %i", nodeChunk.mNumChilds); - MCore::LogDetailedInfo(" + Position: x=%f y=%f z=%f", nodeChunk.mLocalPos.mX, nodeChunk.mLocalPos.mY, nodeChunk.mLocalPos.mZ); - MCore::LogDetailedInfo(" + Rotation: x=%f y=%f z=%f w=%f", nodeChunk.mLocalQuat.mX, nodeChunk.mLocalQuat.mY, nodeChunk.mLocalQuat.mZ, nodeChunk.mLocalQuat.mW); + MCore::LogDetailedInfo(" + NumChilds: %i", nodeChunk.m_numChilds); + MCore::LogDetailedInfo(" + Position: x=%f y=%f z=%f", nodeChunk.m_localPos.m_x, nodeChunk.m_localPos.m_y, nodeChunk.m_localPos.m_z); + MCore::LogDetailedInfo(" + Rotation: x=%f y=%f z=%f w=%f", nodeChunk.m_localQuat.m_x, nodeChunk.m_localQuat.m_y, nodeChunk.m_localQuat.m_z, nodeChunk.m_localQuat.m_w); const AZ::Vector3 euler = MCore::AzQuaternionToEulerAngles(rotation); MCore::LogDetailedInfo(" + Rotation Euler: x=%f y=%f z=%f", float(euler.GetX()) * 180.0 / MCore::Math::pi, float(euler.GetY()) * 180.0 / MCore::Math::pi, float(euler.GetZ()) * 180.0 / MCore::Math::pi); - MCore::LogDetailedInfo(" + Scale: x=%f y=%f z=%f", nodeChunk.mLocalScale.mX, nodeChunk.mLocalScale.mY, nodeChunk.mLocalScale.mZ); + MCore::LogDetailedInfo(" + Scale: x=%f y=%f z=%f", nodeChunk.m_localScale.m_x, nodeChunk.m_localScale.m_y, nodeChunk.m_localScale.m_z); MCore::LogDetailedInfo(" + IncludeInBoundsCalc: %d", node->GetIncludeInBoundsCalc()); // log skeletal lods @@ -111,12 +111,12 @@ namespace ExporterLib MCore::LogDetailedInfo(lodString.c_str()); // endian conversion - ConvertFileVector3(&nodeChunk.mLocalPos, targetEndianType); - ConvertFileQuaternion(&nodeChunk.mLocalQuat, targetEndianType); - ConvertFileVector3(&nodeChunk.mLocalScale, targetEndianType); - ConvertUnsignedInt(&nodeChunk.mParentIndex, targetEndianType); - ConvertUnsignedInt(&nodeChunk.mNumChilds, targetEndianType); - ConvertUnsignedInt(&nodeChunk.mSkeletalLODs, targetEndianType); + ConvertFileVector3(&nodeChunk.m_localPos, targetEndianType); + ConvertFileQuaternion(&nodeChunk.m_localQuat, targetEndianType); + ConvertFileVector3(&nodeChunk.m_localScale, targetEndianType); + ConvertUnsignedInt(&nodeChunk.m_parentIndex, targetEndianType); + ConvertUnsignedInt(&nodeChunk.m_numChilds, targetEndianType); + ConvertUnsignedInt(&nodeChunk.m_skeletalLoDs, targetEndianType); // write it file->Write(&nodeChunk, sizeof(EMotionFX::FileFormat::Actor_Node2)); @@ -136,14 +136,14 @@ namespace ExporterLib // chunk information EMotionFX::FileFormat::FileChunk chunkHeader; - chunkHeader.mChunkID = EMotionFX::FileFormat::ACTOR_CHUNK_NODES; - chunkHeader.mVersion = 2; + chunkHeader.m_chunkId = EMotionFX::FileFormat::ACTOR_CHUNK_NODES; + chunkHeader.m_version = 2; // get the nodes chunk size - chunkHeader.mSizeInBytes = aznumeric_caster(sizeof(EMotionFX::FileFormat::Actor_Nodes2) + numNodes * sizeof(EMotionFX::FileFormat::Actor_Node2)); + chunkHeader.m_sizeInBytes = aznumeric_caster(sizeof(EMotionFX::FileFormat::Actor_Nodes2) + numNodes * sizeof(EMotionFX::FileFormat::Actor_Node2)); for (size_t i = 0; i < numNodes; i++) { - chunkHeader.mSizeInBytes += GetStringChunkSize(actor->GetSkeleton()->GetNode(i)->GetName()); + chunkHeader.m_sizeInBytes += GetStringChunkSize(actor->GetSkeleton()->GetNode(i)->GetName()); } // endian conversion and write it @@ -152,12 +152,12 @@ namespace ExporterLib // nodes chunk EMotionFX::FileFormat::Actor_Nodes2 nodesChunk; - nodesChunk.mNumNodes = aznumeric_caster(numNodes); - nodesChunk.mNumRootNodes = aznumeric_caster(actor->GetSkeleton()->GetNumRootNodes()); + nodesChunk.m_numNodes = aznumeric_caster(numNodes); + nodesChunk.m_numRootNodes = aznumeric_caster(actor->GetSkeleton()->GetNumRootNodes()); // endian conversion and write it - ConvertUnsignedInt(&nodesChunk.mNumNodes, targetEndianType); - ConvertUnsignedInt(&nodesChunk.mNumRootNodes, targetEndianType); + ConvertUnsignedInt(&nodesChunk.m_numNodes, targetEndianType); + ConvertUnsignedInt(&nodesChunk.m_numRootNodes, targetEndianType); file->Write(&nodesChunk, sizeof(EMotionFX::FileFormat::Actor_Nodes2)); @@ -182,12 +182,12 @@ namespace ExporterLib memset(&groupChunk, 0, sizeof(EMotionFX::FileFormat::Actor_NodeGroup)); // set the data - groupChunk.mNumNodes = static_cast(numNodes); - groupChunk.mDisabledOnDefault = nodeGroup->GetIsEnabledOnDefault() ? false : true; + groupChunk.m_numNodes = static_cast(numNodes); + groupChunk.m_disabledOnDefault = nodeGroup->GetIsEnabledOnDefault() ? false : true; // logging MCore::LogDetailedInfo("- Group: name='%s'", nodeGroup->GetName()); - MCore::LogDetailedInfo(" + DisabledOnDefault: %i", groupChunk.mDisabledOnDefault); + MCore::LogDetailedInfo(" + DisabledOnDefault: %i", groupChunk.m_disabledOnDefault); AZStd::string nodesString; for (size_t i = 0; i < numNodes; ++i) { @@ -197,10 +197,10 @@ namespace ExporterLib nodesString += ", "; } } - MCore::LogDetailedInfo(" + Nodes (%i): %s", groupChunk.mNumNodes, nodesString.c_str()); + MCore::LogDetailedInfo(" + Nodes (%i): %s", groupChunk.m_numNodes, nodesString.c_str()); // endian conversion - ConvertUnsignedShort(&groupChunk.mNumNodes, targetEndianType); + ConvertUnsignedShort(&groupChunk.m_numNodes, targetEndianType); // write it file->Write(&groupChunk, sizeof(EMotionFX::FileFormat::Actor_NodeGroup)); @@ -240,16 +240,16 @@ namespace ExporterLib // chunk information EMotionFX::FileFormat::FileChunk chunkHeader; - chunkHeader.mChunkID = EMotionFX::FileFormat::ACTOR_CHUNK_NODEGROUPS; - chunkHeader.mVersion = 1; + chunkHeader.m_chunkId = EMotionFX::FileFormat::ACTOR_CHUNK_NODEGROUPS; + chunkHeader.m_version = 1; // calculate the chunk size - chunkHeader.mSizeInBytes = sizeof(uint16); + chunkHeader.m_sizeInBytes = sizeof(uint16); for (const EMotionFX::NodeGroup* nodeGroup : nodeGroups) { - chunkHeader.mSizeInBytes += sizeof(EMotionFX::FileFormat::Actor_NodeGroup); - chunkHeader.mSizeInBytes += GetStringChunkSize(nodeGroup->GetNameString()); - chunkHeader.mSizeInBytes += sizeof(uint16) * nodeGroup->GetNumNodes(); + chunkHeader.m_sizeInBytes += sizeof(EMotionFX::FileFormat::Actor_NodeGroup); + chunkHeader.m_sizeInBytes += GetStringChunkSize(nodeGroup->GetNameString()); + chunkHeader.m_sizeInBytes += sizeof(uint16) * nodeGroup->GetNumNodes(); } // endian conversion @@ -309,9 +309,9 @@ namespace ExporterLib // chunk information EMotionFX::FileFormat::FileChunk chunkHeader; - chunkHeader.mChunkID = EMotionFX::FileFormat::ACTOR_CHUNK_NODEMOTIONSOURCES; - chunkHeader.mSizeInBytes = aznumeric_caster(sizeof(EMotionFX::FileFormat::Actor_NodeMotionSources2) + (numNodes * sizeof(uint16)) + (numNodes * sizeof(uint8) * 2)); - chunkHeader.mVersion = 1; + chunkHeader.m_chunkId = EMotionFX::FileFormat::ACTOR_CHUNK_NODEMOTIONSOURCES; + chunkHeader.m_sizeInBytes = aznumeric_caster(sizeof(EMotionFX::FileFormat::Actor_NodeMotionSources2) + (numNodes * sizeof(uint16)) + (numNodes * sizeof(uint8) * 2)); + chunkHeader.m_version = 1; // endian conversion and write it ConvertFileChunk(&chunkHeader, targetEndianType); @@ -320,10 +320,10 @@ namespace ExporterLib // the node motion sources chunk data EMotionFX::FileFormat::Actor_NodeMotionSources2 nodeMotionSourcesChunk; - nodeMotionSourcesChunk.mNumNodes = aznumeric_caster(numNodes); + nodeMotionSourcesChunk.m_numNodes = aznumeric_caster(numNodes); // convert endian and save to the file - ConvertUnsignedInt(&nodeMotionSourcesChunk.mNumNodes, targetEndianType); + ConvertUnsignedInt(&nodeMotionSourcesChunk.m_numNodes, targetEndianType); file->Write(&nodeMotionSourcesChunk, sizeof(EMotionFX::FileFormat::Actor_NodeMotionSources2)); @@ -336,7 +336,7 @@ namespace ExporterLib for (const EMotionFX::Actor::NodeMirrorInfo& nodeMirrorInfo : *nodeMirrorInfos) { // get the motion node source - uint16 nodeMotionSource = nodeMirrorInfo.mSourceNode; + uint16 nodeMotionSource = nodeMirrorInfo.m_sourceNode; // convert endian and save to the file ConvertUnsignedShort(&nodeMotionSource, targetEndianType); @@ -346,14 +346,14 @@ namespace ExporterLib // write all axes for (const EMotionFX::Actor::NodeMirrorInfo& nodeMirrorInfo : *nodeMirrorInfos) { - uint8 axis = static_cast(nodeMirrorInfo.mAxis); + uint8 axis = static_cast(nodeMirrorInfo.m_axis); file->Write(&axis, sizeof(uint8)); } // write all flags for (const EMotionFX::Actor::NodeMirrorInfo& nodeMirrorInfo : *nodeMirrorInfos) { - uint8 flags = static_cast(nodeMirrorInfo.mFlags); + uint8 flags = static_cast(nodeMirrorInfo.m_flags); file->Write(&flags, sizeof(uint8)); } } @@ -398,9 +398,9 @@ namespace ExporterLib // chunk information EMotionFX::FileFormat::FileChunk chunkHeader; - chunkHeader.mChunkID = EMotionFX::FileFormat::ACTOR_CHUNK_ATTACHMENTNODES; - chunkHeader.mSizeInBytes = aznumeric_caster(sizeof(EMotionFX::FileFormat::Actor_AttachmentNodes) + numAttachmentNodes * sizeof(uint16)); - chunkHeader.mVersion = 1; + chunkHeader.m_chunkId = EMotionFX::FileFormat::ACTOR_CHUNK_ATTACHMENTNODES; + chunkHeader.m_sizeInBytes = aznumeric_caster(sizeof(EMotionFX::FileFormat::Actor_AttachmentNodes) + numAttachmentNodes * sizeof(uint16)); + chunkHeader.m_version = 1; // endian conversion and write it ConvertFileChunk(&chunkHeader, targetEndianType); @@ -409,10 +409,10 @@ namespace ExporterLib // the attachment nodes chunk data EMotionFX::FileFormat::Actor_AttachmentNodes attachmentNodesChunk; - attachmentNodesChunk.mNumNodes = aznumeric_caster(numAttachmentNodes); + attachmentNodesChunk.m_numNodes = aznumeric_caster(numAttachmentNodes); // convert endian and save to the file - ConvertUnsignedInt(&attachmentNodesChunk.mNumNodes, targetEndianType); + ConvertUnsignedInt(&attachmentNodesChunk.m_numNodes, targetEndianType); file->Write(&attachmentNodesChunk, sizeof(EMotionFX::FileFormat::Actor_AttachmentNodes)); // log details diff --git a/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/SkeletalMotionExport.cpp b/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/SkeletalMotionExport.cpp index 17c5011275..26c2c2c59e 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/SkeletalMotionExport.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/SkeletalMotionExport.cpp @@ -26,9 +26,9 @@ namespace ExporterLib EMotionFX::MotionData::SaveSettings saveSettings; saveSettings.m_targetEndianType = targetEndianType; EMotionFX::FileFormat::FileChunk chunkHeader; - chunkHeader.mChunkID = EMotionFX::FileFormat::MOTION_CHUNK_MOTIONDATA; - chunkHeader.mVersion = 1; - chunkHeader.mSizeInBytes = static_cast( + chunkHeader.m_chunkId = EMotionFX::FileFormat::MOTION_CHUNK_MOTIONDATA; + chunkHeader.m_version = 1; + chunkHeader.m_sizeInBytes = static_cast( sizeof(EMotionFX::FileFormat::Motion_MotionData) + ExporterLib::GetAzStringChunkSize(uuidString) + ExporterLib::GetAzStringChunkSize(nameString) + diff --git a/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/SkinExport.cpp b/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/SkinExport.cpp deleted file mode 100644 index 3c0c30ff53..0000000000 --- a/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/SkinExport.cpp +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -#include "Exporter.h" -#include -#include -#include -#include -#include -#include - - -namespace ExporterLib -{ - // save the given skin for the given LOD level - void SaveSkin(MCore::Stream* file, EMotionFX::Mesh* mesh, uint32 nodeIndex, bool isCollisionMesh, uint32 lodLevel, MCore::Endian::EEndianType targetEndianType) - { - MCORE_ASSERT(mesh); - - const uint32 numLayers = mesh->GetNumSharedVertexAttributeLayers(); - for (uint32 layerNr = 0; layerNr < numLayers; ++layerNr) - { - EMotionFX::VertexAttributeLayer* vertexAttributeLayer = mesh->GetSharedVertexAttributeLayer(layerNr); - - if (vertexAttributeLayer->GetType() != EMotionFX::SkinningInfoVertexAttributeLayer::TYPE_ID) - { - continue; - } - - EMotionFX::SkinningInfoVertexAttributeLayer* skinLayer = static_cast(vertexAttributeLayer); - - // get the number of original vertices - const uint32 numOrgVerts = skinLayer->GetNumAttributes(); - - // get the number of total influences - uint32 numTotalInfluences = 0; - uint32 v; - for (v = 0; v < numOrgVerts; ++v) - { - numTotalInfluences += aznumeric_cast(skinLayer->GetNumInfluences(v)); - } - - // skip meshes which don't contain any influences - if (numOrgVerts <= 0) - { - continue; - } - - if (numOrgVerts != mesh->GetNumOrgVertices()) - { - MCore::LogWarning("More/Less skinning influences (%i) found than the mesh actually has original vertices (%i).", numOrgVerts, mesh->GetNumOrgVertices()); - } - - // chunk header - EMotionFX::FileFormat::FileChunk chunkHeader; - - // calculate the total size and write the chunk header - uint32 totalSize = sizeof(EMotionFX::FileFormat::Actor_SkinningInfo); - totalSize += numTotalInfluences * sizeof(EMotionFX::FileFormat::Actor_SkinInfluence); - totalSize += numOrgVerts * sizeof(EMotionFX::FileFormat::Actor_SkinningInfoTableEntry); - - chunkHeader.mChunkID = EMotionFX::FileFormat::ACTOR_CHUNK_SKINNINGINFO; - chunkHeader.mSizeInBytes = totalSize; - chunkHeader.mVersion = 1; - - // endian conversion - ConvertFileChunk(&chunkHeader, targetEndianType); - - // write header and influence - file->Write(&chunkHeader, sizeof(EMotionFX::FileFormat::FileChunk)); - - if (nodeIndex == MCORE_INVALIDINDEX32) - { - MCore::LogError("Skin (Nr=%i) is not connected to a valid transform node.", nodeIndex); - } - - MCore::LogDetailedInfo(" - Skinning Info (NodeNr=%i):", nodeIndex); - MCore::LogDetailedInfo(" + Total data size: %d kB", totalSize / 1024); - MCore::LogDetailedInfo(" + Num org vertices: %d", numOrgVerts); - MCore::LogDetailedInfo(" + Num total influences: %d", numTotalInfluences); - - EMotionFX::FileFormat::Actor_SkinningInfo skinningInfoChunk; - memset(&skinningInfoChunk, 0, sizeof(EMotionFX::FileFormat::Actor_SkinningInfo)); - skinningInfoChunk.mIsForCollisionMesh = isCollisionMesh ? 1 : 0; - skinningInfoChunk.mNodeIndex = nodeIndex; - skinningInfoChunk.mLOD = lodLevel; - skinningInfoChunk.mNumTotalInfluences = numTotalInfluences; - - AZStd::set localJointIndices = skinLayer->CalcLocalJointIndices(numOrgVerts); - skinningInfoChunk.mNumLocalBones = static_cast(localJointIndices.size()); - - ConvertUnsignedInt(&skinningInfoChunk.mNodeIndex, targetEndianType); - ConvertUnsignedInt(&skinningInfoChunk.mLOD, targetEndianType); - ConvertUnsignedInt(&skinningInfoChunk.mNumTotalInfluences, targetEndianType); - ConvertUnsignedInt(&skinningInfoChunk.mNumLocalBones, targetEndianType); - - file->Write(&skinningInfoChunk, sizeof(EMotionFX::FileFormat::Actor_SkinningInfo)); - - for (v = 0; v < numOrgVerts; ++v) - { - const uint32 weightCount = aznumeric_cast(skinLayer->GetNumInfluences(v)); - - //LogDebug(" - Vertex#%i: NumWeights='%i'", v, weightCount); - - for (uint32 w = 0; w < weightCount; ++w) - { - EMotionFX::FileFormat::Actor_SkinInfluence skinInfluence; - memset(&skinInfluence, 0, sizeof(EMotionFX::FileFormat::Actor_SkinInfluence)); - skinInfluence.mNodeNr = skinLayer->GetInfluence(v, w)->GetNodeNr(); - skinInfluence.mWeight = skinLayer->GetInfluence(v, w)->GetWeight(); - - //LogDebug(" + SkingInfluence#%i: NodeNr='%i', Weight='%f'", w, skinInfluence.mNodeNr, skinInfluence.mWeight); - - ConvertUnsignedShort(&skinInfluence.mNodeNr, targetEndianType); - ConvertFloat(&skinInfluence.mWeight, targetEndianType); - - file->Write(&skinInfluence, sizeof(EMotionFX::FileFormat::Actor_SkinInfluence)); - } - } - - uint32 currentInfluence = 0; - for (v = 0; v < numOrgVerts; ++v) - { - const uint32 weightCount = aznumeric_cast(skinLayer->GetNumInfluences(v)); - - EMotionFX::FileFormat::Actor_SkinningInfoTableEntry skinningTableEntryChunk; - skinningTableEntryChunk.mNumElements = weightCount; - skinningTableEntryChunk.mStartIndex = currentInfluence; - - ConvertUnsignedInt(&skinningTableEntryChunk.mNumElements, targetEndianType); - ConvertUnsignedInt(&skinningTableEntryChunk.mStartIndex, targetEndianType); - - file->Write(&skinningTableEntryChunk, sizeof(EMotionFX::FileFormat::Actor_SkinningInfoTableEntry)); - - currentInfluence += weightCount; - } - } - } - - - // save skins for all nodes for the given LOD level - void SaveSkins(MCore::Stream* file, EMotionFX::Actor* actor, uint32 lodLevel, MCore::Endian::EEndianType targetEndianType) - { - MCORE_ASSERT(file); - - // get the number of nodes - const uint32 numNodes = actor->GetNumNodes(); - - MCore::LogDetailedInfo("============================================================"); - MCore::LogInfo("Skins (LOD=%d", lodLevel); - MCore::LogDetailedInfo("============================================================"); - - // iterate through all nodes - for (uint32 i = 0; i < numNodes; i++) - { - // get the mesh and save it - EMotionFX::Mesh* mesh = actor->GetMesh(lodLevel, i); - if (mesh) - { - SaveSkin(file, mesh, i, false, lodLevel, targetEndianType); - } - - // get the collision mesh and save it - //EMotionFX::Mesh* collisionMesh = actor->GetCollisionMesh(lodLevel, i); - //if (collisionMesh) - //SaveSkin( file, collisionMesh, i, true, lodLevel, targetEndianType ); - } - } - - - // save all skins for all LOD levels - void SaveSkins(MCore::Stream* file, EMotionFX::Actor* actor, MCore::Endian::EEndianType targetEndianType) - { - // get the number of LOD levels, iterate through them and save all skins - const uint32 numLODLevels = actor->GetNumLODLevels(); - for (uint32 i = 0; i < numLODLevels; ++i) - { - SaveSkins(file, actor, i, targetEndianType); - } - } -} // namespace ExporterLib diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/Camera.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/Camera.cpp index fe33cff6e5..f4447c1b10 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/Camera.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/Camera.cpp @@ -17,10 +17,10 @@ namespace MCommon Camera::Camera() { Reset(); - mPosition = AZ::Vector3::CreateZero(); - mScreenWidth = 0; - mScreenHeight = 0; - mProjectionMode = PROJMODE_PERSPECTIVE; + m_position = AZ::Vector3::CreateZero(); + m_screenWidth = 0; + m_screenHeight = 0; + m_projectionMode = PROJMODE_PERSPECTIVE; } @@ -36,27 +36,27 @@ namespace MCommon MCORE_UNUSED(timeDelta); // setup projection matrix - switch (mProjectionMode) + switch (m_projectionMode) { // initialize for perspective projection case PROJMODE_PERSPECTIVE: { - MCore::PerspectiveRH(mProjectionMatrix, MCore::Math::DegreesToRadians(mFOV), mAspect, mNearClipDistance, mFarClipDistance); + MCore::PerspectiveRH(m_projectionMatrix, MCore::Math::DegreesToRadians(m_fov), m_aspect, m_nearClipDistance, m_farClipDistance); break; } // initialize for orthographic projection case PROJMODE_ORTHOGRAPHIC: { - const float halfX = mOrthoClipDimensions.GetX() * 0.5f; - const float halfY = mOrthoClipDimensions.GetY() * 0.5f; - MCore::OrthoOffCenterRH(mProjectionMatrix, -halfX, halfX, halfY, -halfY, -mFarClipDistance, mFarClipDistance); + const float halfX = m_orthoClipDimensions.GetX() * 0.5f; + const float halfY = m_orthoClipDimensions.GetY() * 0.5f; + MCore::OrthoOffCenterRH(m_projectionMatrix, -halfX, halfX, halfY, -halfY, -m_farClipDistance, m_farClipDistance); break; } } // calculate the viewproj matrix - mViewProjMatrix = mProjectionMatrix * mViewMatrix; + m_viewProjMatrix = m_projectionMatrix * m_viewMatrix; } @@ -65,24 +65,24 @@ namespace MCommon { MCORE_UNUSED(flightTime); - mFOV = 55.0f; - mNearClipDistance = 0.1f; - mFarClipDistance = 200.0f; - mAspect = 16.0f / 9.0f; - mRotationSpeed = 0.5f; - mTranslationSpeed = 1.0f; - mViewMatrix = AZ::Matrix4x4::CreateIdentity(); + m_fov = 55.0f; + m_nearClipDistance = 0.1f; + m_farClipDistance = 200.0f; + m_aspect = 16.0f / 9.0f; + m_rotationSpeed = 0.5f; + m_translationSpeed = 1.0f; + m_viewMatrix = AZ::Matrix4x4::CreateIdentity(); } // unproject screen coordinates to a ray MCore::Ray Camera::Unproject(int32 screenX, int32 screenY) { - const AZ::Matrix4x4 invProj = MCore::InvertProjectionMatrix(mProjectionMatrix); - const AZ::Matrix4x4 invView = MCore::InvertProjectionMatrix(mViewMatrix); + const AZ::Matrix4x4 invProj = MCore::InvertProjectionMatrix(m_projectionMatrix); + const AZ::Matrix4x4 invView = MCore::InvertProjectionMatrix(m_viewMatrix); - const AZ::Vector3 start = MCore::Unproject(static_cast(screenX), static_cast(screenY), static_cast(mScreenWidth), static_cast(mScreenHeight), mNearClipDistance, invProj, invView); - const AZ::Vector3 end = MCore::Unproject(static_cast(screenX), static_cast(screenY), static_cast(mScreenWidth), static_cast(mScreenHeight), mFarClipDistance, invProj, invView); + const AZ::Vector3 start = MCore::Unproject(static_cast(screenX), static_cast(screenY), static_cast(m_screenWidth), static_cast(m_screenHeight), m_nearClipDistance, invProj, invView); + const AZ::Vector3 end = MCore::Unproject(static_cast(screenX), static_cast(screenY), static_cast(m_screenWidth), static_cast(m_screenHeight), m_farClipDistance, invProj, invView); return MCore::Ray(start, end); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/Camera.h b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/Camera.h index 6a95621b0d..46b81a9d25 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/Camera.h +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/Camera.h @@ -148,24 +148,24 @@ namespace MCommon * The projection matrix will be calculated every Update(). * @return The projection matrix. */ - MCORE_INLINE AZ::Matrix4x4& GetProjectionMatrix() { return mProjectionMatrix; } - MCORE_INLINE const AZ::Matrix4x4& GetProjectionMatrix() const { return mProjectionMatrix; } + MCORE_INLINE AZ::Matrix4x4& GetProjectionMatrix() { return m_projectionMatrix; } + MCORE_INLINE const AZ::Matrix4x4& GetProjectionMatrix() const { return m_projectionMatrix; } /** * Get the view matrix of the camera. * The view matrix will be calculated every Update(). * @return The view matrix. */ - MCORE_INLINE AZ::Matrix4x4& GetViewMatrix() { return mViewMatrix; } - MCORE_INLINE const AZ::Matrix4x4& GetViewMatrix() const { return mViewMatrix; } + MCORE_INLINE AZ::Matrix4x4& GetViewMatrix() { return m_viewMatrix; } + MCORE_INLINE const AZ::Matrix4x4& GetViewMatrix() const { return m_viewMatrix; } /** * Get the precalculated viewMatrix * projectionMatrix of the camera. * The viewproj matrix will be calculated every Update(). * @return The precalculated matrix containing the result of viewMatrix * projectionMatrix. */ - MCORE_INLINE AZ::Matrix4x4& GetViewProjMatrix() { return mViewProjMatrix; } - MCORE_INLINE const AZ::Matrix4x4& GetViewProjMatrix() const { return mViewProjMatrix; } + MCORE_INLINE AZ::Matrix4x4& GetViewProjMatrix() { return m_viewProjMatrix; } + MCORE_INLINE const AZ::Matrix4x4& GetViewProjMatrix() const { return m_viewProjMatrix; } /** * Get the translation speed. @@ -261,20 +261,20 @@ namespace MCommon virtual void AutoUpdateLimits() {} protected: - AZ::Matrix4x4 mProjectionMatrix; /**< The projection matrix. */ - AZ::Matrix4x4 mViewMatrix; /**< The view matrix. */ - AZ::Matrix4x4 mViewProjMatrix; /**< ViewMatrix * projectionMatrix. Will be recalculated every update call. */ - AZ::Vector3 mPosition; /**< The camera position. */ - AZ::Vector2 mOrthoClipDimensions; /**< A two component vector which defines the distance to the left (x component) and to the top (y component) from the view origin. */ - float mFOV; /**< The vertical field-of-view in degrees. */ - float mNearClipDistance; /**< Distance to the near clipping plane. */ - float mFarClipDistance; /**< Distance to the far clipping plane. */ - float mAspect; /**< x/y viewport ratio. */ - float mRotationSpeed; /**< The angle in degrees that will be applied to the current rotation when the mouse is moving one pixel. */ - float mTranslationSpeed; /**< The value that will be applied to the current camera position when moving the mouse one pixel. */ - ProjectionMode mProjectionMode; /**< The projection mode. The camera supports either perspective or orthographic projection. */ - uint32 mScreenWidth; /**< The screen width in pixels where the camera is used. */ - uint32 mScreenHeight; /**< The screen height in pixels where the camera is used. */ + AZ::Matrix4x4 m_projectionMatrix; /**< The projection matrix. */ + AZ::Matrix4x4 m_viewMatrix; /**< The view matrix. */ + AZ::Matrix4x4 m_viewProjMatrix; /**< ViewMatrix * projectionMatrix. Will be recalculated every update call. */ + AZ::Vector3 m_position; /**< The camera position. */ + AZ::Vector2 m_orthoClipDimensions; /**< A two component vector which defines the distance to the left (x component) and to the top (y component) from the view origin. */ + float m_fov; /**< The vertical field-of-view in degrees. */ + float m_nearClipDistance; /**< Distance to the near clipping plane. */ + float m_farClipDistance; /**< Distance to the far clipping plane. */ + float m_aspect; /**< x/y viewport ratio. */ + float m_rotationSpeed; /**< The angle in degrees that will be applied to the current rotation when the mouse is moving one pixel. */ + float m_translationSpeed; /**< The value that will be applied to the current camera position when moving the mouse one pixel. */ + ProjectionMode m_projectionMode; /**< The projection mode. The camera supports either perspective or orthographic projection. */ + uint32 m_screenWidth; /**< The screen width in pixels where the camera is used. */ + uint32 m_screenHeight; /**< The screen height in pixels where the camera is used. */ }; // include inline code diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/Camera.inl b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/Camera.inl index c6947576d3..43e2ce6fbd 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/Camera.inl +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/Camera.inl @@ -12,139 +12,139 @@ // set the camera position MCORE_INLINE void Camera::SetPosition(const AZ::Vector3& position) { - mPosition = position; + m_position = position; } // get the camera position MCORE_INLINE const AZ::Vector3& Camera::GetPosition() const { - return mPosition; + return m_position; } // set the projection type MCORE_INLINE void Camera::SetProjectionMode(ProjectionMode projectionMode) { - mProjectionMode = projectionMode; + m_projectionMode = projectionMode; } // get the projection type MCORE_INLINE Camera::ProjectionMode Camera::GetProjectionMode() const { - return mProjectionMode; + return m_projectionMode; } // set the clip dimensions for the orthographic projection mode MCORE_INLINE void Camera::SetOrthoClipDimensions(const AZ::Vector2& clipDimensions) { - mOrthoClipDimensions = clipDimensions; + m_orthoClipDimensions = clipDimensions; } // set the screen dimensions where this camera is used in MCORE_INLINE void Camera::SetScreenDimensions(uint32 width, uint32 height) { - mScreenWidth = width; - mScreenHeight = height; + m_screenWidth = width; + m_screenHeight = height; } // set the field of view in degrees MCORE_INLINE void Camera::SetFOV(float fieldOfView) { - mFOV = fieldOfView; + m_fov = fieldOfView; } // set near clip plane distance MCORE_INLINE void Camera::SetNearClipDistance(float nearClipDistance) { - mNearClipDistance = nearClipDistance; + m_nearClipDistance = nearClipDistance; } // set far clip plane distance MCORE_INLINE void Camera::SetFarClipDistance(float farClipDistance) { - mFarClipDistance = farClipDistance; + m_farClipDistance = farClipDistance; } // set the aspect ratio - the aspect ratio is calculated by width/height MCORE_INLINE void Camera::SetAspectRatio(float aspect) { - mAspect = aspect; + m_aspect = aspect; } // return the field of view in degrees MCORE_INLINE float Camera::GetFOV() const { - return mFOV; + return m_fov; } // return the near clip plane distance MCORE_INLINE float Camera::GetNearClipDistance() const { - return mNearClipDistance; + return m_nearClipDistance; } // return the far clip plane distance MCORE_INLINE float Camera::GetFarClipDistance() const { - return mFarClipDistance; + return m_farClipDistance; } // return the aspect ratio MCORE_INLINE float Camera::GetAspectRatio() const { - return mAspect; + return m_aspect; } // get the translation speed MCORE_INLINE float Camera::GetTranslationSpeed() const { - return mTranslationSpeed; + return m_translationSpeed; } // set the translation speed MCORE_INLINE void Camera::SetTranslationSpeed(float translationSpeed) { - mTranslationSpeed = translationSpeed; + m_translationSpeed = translationSpeed; } // get the rotation speed in degrees MCORE_INLINE float Camera::GetRotationSpeed() const { - return mRotationSpeed; + return m_rotationSpeed; } // set the rotation speed in degrees MCORE_INLINE void Camera::SetRotationSpeed(float rotationSpeed) { - mRotationSpeed = rotationSpeed; + m_rotationSpeed = rotationSpeed; } // Get the screen width. MCORE_INLINE uint32 Camera::GetScreenWidth() { - return mScreenWidth; + return m_screenWidth; } // Get the screen height MCORE_INLINE uint32 Camera::GetScreenHeight() { - return mScreenHeight; + return m_screenHeight; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/FirstPersonCamera.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/FirstPersonCamera.cpp index cebfc350b1..112d3c1dc1 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/FirstPersonCamera.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/FirstPersonCamera.cpp @@ -32,20 +32,20 @@ namespace MCommon MCORE_UNUSED(timeDelta); // lock pitching to [-90.0°, 90.0°] - if (mPitch < -90.0f + 0.1f) + if (m_pitch < -90.0f + 0.1f) { - mPitch = -90.0f + 0.1f; + m_pitch = -90.0f + 0.1f; } - if (mPitch > 90.0f - 0.1f) + if (m_pitch > 90.0f - 0.1f) { - mPitch = 90.0f - 0.1f; + m_pitch = 90.0f - 0.1f; } // calculate the camera direction vector based on the yaw and pitch - AZ::Vector3 direction = (AZ::Matrix4x4::CreateRotationX(MCore::Math::DegreesToRadians(mPitch)) * AZ::Matrix4x4::CreateRotationY(MCore::Math::DegreesToRadians(mYaw))) * (AZ::Vector3(0.0f, 0.0f, 1.0f)).GetNormalized(); + AZ::Vector3 direction = (AZ::Matrix4x4::CreateRotationX(MCore::Math::DegreesToRadians(m_pitch)) * AZ::Matrix4x4::CreateRotationY(MCore::Math::DegreesToRadians(m_yaw))) * (AZ::Vector3(0.0f, 0.0f, 1.0f)).GetNormalized(); // look from the camera position into the newly calculated direction - MCore::LookAt(mViewMatrix, mPosition, mPosition + direction * 10.0f, AZ::Vector3(0.0f, 1.0f, 0.0f)); + MCore::LookAt(m_viewMatrix, m_position, m_position + direction * 10.0f, AZ::Vector3(0.0f, 1.0f, 0.0f)); // update our base camera Camera::Update(); @@ -62,7 +62,7 @@ namespace MCommon EKeyboardButtonState buttonState = (EKeyboardButtonState)keyboardKeyFlags; - AZ::Matrix4x4 transposedViewMatrix(mViewMatrix); + AZ::Matrix4x4 transposedViewMatrix(m_viewMatrix); transposedViewMatrix.Transpose(); // get the movement direction vector based on the keyboard input @@ -95,14 +95,14 @@ namespace MCommon // only move the camera when the delta movement is not the zero vector if (MCore::SafeLength(deltaMovement) > MCore::Math::epsilon) { - mPosition += deltaMovement.GetNormalized() * mTranslationSpeed; + m_position += deltaMovement.GetNormalized() * m_translationSpeed; } // rotate the camera if (buttonState & ENABLE_MOUSELOOK) { - mYaw += mouseMovementX * mRotationSpeed; - mPitch += mouseMovementY * mRotationSpeed; + m_yaw += mouseMovementX * m_rotationSpeed; + m_pitch += mouseMovementY * m_rotationSpeed; } } @@ -115,8 +115,8 @@ namespace MCommon // reset the base class attributes Camera::Reset(); - mPitch = 0.0f; - mYaw = 0.0f; - mRoll = 0.0f; + m_pitch = 0.0f; + m_yaw = 0.0f; + m_roll = 0.0f; } } // namespace MCommon diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/FirstPersonCamera.h b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/FirstPersonCamera.h index 54addd0bc4..e0abe7922c 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/FirstPersonCamera.h +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/FirstPersonCamera.h @@ -60,37 +60,37 @@ namespace MCommon * Set the pitch angle in degrees. Looking up and down is limited to 90°. (0=Straight Ahead, +Up, -Down) * @param The pitch angle in degrees, range[-90.0°, 90.0°]. */ - MCORE_INLINE void SetPitch(float pitch) { mPitch = pitch; } + MCORE_INLINE void SetPitch(float pitch) { m_pitch = pitch; } /** * Set the yaw angle in degrees. Vertical rotation. (0=East, +North, -South). * @param yaw The yaw angle in degrees. */ - MCORE_INLINE void SetYaw(float yaw) { mYaw = yaw; } + MCORE_INLINE void SetYaw(float yaw) { m_yaw = yaw; } /** * Set the roll angle in degrees. Rotation around the direction axis (0=Straight, +Clockwise, -CCW). * @param roll The roll angle in degrees. */ - MCORE_INLINE void SetRoll(float roll) { mRoll = roll; } + MCORE_INLINE void SetRoll(float roll) { m_roll = roll; } /** * Get the pitch angle in degrees. Looking up and down is limited to 90°. (0=Straight Ahead, +Up, -Down) * @return The pitch angle in degrees, range[-90.0°, 90.0°]. */ - MCORE_INLINE float GetPitch() const { return mPitch; } + MCORE_INLINE float GetPitch() const { return m_pitch; } /** * Get the yaw angle in degrees. Vertical rotation. (0=East, +North, -South). * @return The yaw angle in degrees. */ - MCORE_INLINE float GetYaw() const { return mYaw; } + MCORE_INLINE float GetYaw() const { return m_yaw; } /** * Get the roll angle in degrees. Rotation around the direction axis (0=Straight, +Clockwise, -CCW). * @return The roll angle in degrees. */ - MCORE_INLINE float GetRoll() const { return mRoll; } + MCORE_INLINE float GetRoll() const { return m_roll; } /** * Update the camera transformation. @@ -119,9 +119,9 @@ namespace MCommon void Reset(float flightTime = 0.0f); private: - float mPitch; /**< Up and down. (0=straight ahead, +up, -down) */ - float mYaw; /**< Steering. (0=east, +north, -south) */ - float mRoll; /**< Rotation around axis of screen. (0=straight, +clockwise, -CCW) */ + float m_pitch; /**< Up and down. (0=straight ahead, +up, -down) */ + float m_yaw; /**< Steering. (0=east, +north, -south) */ + float m_roll; /**< Rotation around axis of screen. (0=straight, +clockwise, -CCW) */ }; } // namespace MCommon diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/LookAtCamera.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/LookAtCamera.cpp index 9cb0355ca0..1599433f9e 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/LookAtCamera.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/LookAtCamera.cpp @@ -29,8 +29,8 @@ namespace MCommon // look at target void LookAtCamera::LookAt(const AZ::Vector3& target, const AZ::Vector3& up) { - mTarget = target; - mUp = up; + m_target = target; + m_up = up; } @@ -39,7 +39,7 @@ namespace MCommon { MCORE_UNUSED(timeDelta); - MCore::LookAtRH(mViewMatrix, mPosition, mTarget, mUp); + MCore::LookAtRH(m_viewMatrix, m_position, m_target, m_up); // update our base camera at the very end Camera::Update(); @@ -53,6 +53,6 @@ namespace MCommon // reset the base class attributes Camera::Reset(); - mUp.Set(0.0f, 0.0f, 1.0f); + m_up.Set(0.0f, 0.0f, 1.0f); } } // namespace MCommon diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/LookAtCamera.h b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/LookAtCamera.h index 00b86e3b05..e17fe65985 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/LookAtCamera.h +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/LookAtCamera.h @@ -66,29 +66,29 @@ namespace MCommon * Set the target position. Note that the camera needs an update after setting a new target. * @param[in] target The new camera target. */ - MCORE_INLINE void SetTarget(const AZ::Vector3& target) { mTarget = target; } + MCORE_INLINE void SetTarget(const AZ::Vector3& target) { m_target = target; } /** * Get the target position. * @return The current camera target. */ - MCORE_INLINE AZ::Vector3 GetTarget() const { return mTarget; } + MCORE_INLINE AZ::Vector3 GetTarget() const { return m_target; } /** * Set the up vector for the camera. Note that the camera needs an update after setting a new up vector. * @param[in] up The new camera up vector. */ - MCORE_INLINE void SetUp(const AZ::Vector3& up) { mUp = up; } + MCORE_INLINE void SetUp(const AZ::Vector3& up) { m_up = up; } /** * Get the camera up vector. * @return The current up vector. */ - MCORE_INLINE AZ::Vector3 GetUp() const { return mUp; } + MCORE_INLINE AZ::Vector3 GetUp() const { return m_up; } protected: - AZ::Vector3 mTarget; /**< The camera target. */ - AZ::Vector3 mUp; /**< The up vector of the camera. */ + AZ::Vector3 m_target; /**< The camera target. */ + AZ::Vector3 m_up; /**< The up vector of the camera. */ }; } // namespace MCommon diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/OrbitCamera.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/OrbitCamera.cpp index 471d4439c6..7a2769ea4d 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/OrbitCamera.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/OrbitCamera.cpp @@ -33,32 +33,32 @@ namespace MCommon // reset the parent class attributes LookAtCamera::Reset(); - mMinDistance = mNearClipDistance; - mMaxDistance = mFarClipDistance * 0.5f; - mPosition = AZ::Vector3::CreateZero(); - mPositionDelta = AZ::Vector2(0.0f, 0.0f); + m_minDistance = m_nearClipDistance; + m_maxDistance = m_farClipDistance * 0.5f; + m_position = AZ::Vector3::CreateZero(); + m_positionDelta = AZ::Vector2(0.0f, 0.0f); if (flightTime < MCore::Math::epsilon) { - mFlightActive = false; - mCurrentDistance = (float)MCore::Distance::ConvertValue(5.0f, MCore::Distance::UNITTYPE_METERS, EMotionFX::GetEMotionFX().GetUnitType()); - mAlpha = GetDefaultAlpha(); - mBeta = GetDefaultBeta(); - mTarget = AZ::Vector3::CreateZero(); + m_flightActive = false; + m_currentDistance = (float)MCore::Distance::ConvertValue(5.0f, MCore::Distance::UNITTYPE_METERS, EMotionFX::GetEMotionFX().GetUnitType()); + m_alpha = GetDefaultAlpha(); + m_beta = GetDefaultBeta(); + m_target = AZ::Vector3::CreateZero(); } else { - mFlightActive = true; - mFlightMaxTime = flightTime; - mFlightCurrentTime = 0.0f; - mFlightSourceDistance = mCurrentDistance; - mFlightTargetDistance = (float)MCore::Distance::ConvertValue(5.0f, MCore::Distance::UNITTYPE_METERS, EMotionFX::GetEMotionFX().GetUnitType()); - mFlightSourcePosition = mTarget; - mFlightTargetPosition = AZ::Vector3::CreateZero(); - mFlightSourceAlpha = mAlpha; - mFlightTargetAlpha = GetDefaultAlpha(); - mFlightSourceBeta = mBeta; - mFlightTargetBeta = GetDefaultBeta(); + m_flightActive = true; + m_flightMaxTime = flightTime; + m_flightCurrentTime = 0.0f; + m_flightSourceDistance = m_currentDistance; + m_flightTargetDistance = (float)MCore::Distance::ConvertValue(5.0f, MCore::Distance::UNITTYPE_METERS, EMotionFX::GetEMotionFX().GetUnitType()); + m_flightSourcePosition = m_target; + m_flightTargetPosition = AZ::Vector3::CreateZero(); + m_flightSourceAlpha = m_alpha; + m_flightTargetAlpha = GetDefaultAlpha(); + m_flightSourceBeta = m_beta; + m_flightTargetBeta = GetDefaultBeta(); } } @@ -66,53 +66,53 @@ namespace MCommon // update limits void OrbitCamera::AutoUpdateLimits() { - mMinDistance = mNearClipDistance; - mMaxDistance = mFarClipDistance * 0.5f; + m_minDistance = m_nearClipDistance; + m_maxDistance = m_farClipDistance * 0.5f; } void OrbitCamera::StartFlight(float distance, const AZ::Vector3& position, float alpha, float beta, float flightTime) { - mFlightActive = true; - mFlightMaxTime = flightTime; - mFlightCurrentTime = 0.0f; - mFlightSourceDistance = mCurrentDistance; - mFlightSourcePosition = mTarget; - mFlightTargetDistance = distance; - mFlightTargetPosition = position; - mFlightSourceAlpha = mAlpha; - mFlightTargetAlpha = alpha; - mFlightSourceBeta = mBeta; - mFlightTargetBeta = beta; + m_flightActive = true; + m_flightMaxTime = flightTime; + m_flightCurrentTime = 0.0f; + m_flightSourceDistance = m_currentDistance; + m_flightSourcePosition = m_target; + m_flightTargetDistance = distance; + m_flightTargetPosition = position; + m_flightSourceAlpha = m_alpha; + m_flightTargetAlpha = alpha; + m_flightSourceBeta = m_beta; + m_flightTargetBeta = beta; } // closeup view of the given bounding box void OrbitCamera::ViewCloseup(const MCore::AABB& boundingBox, float flightTime) { - mFlightActive = true; - mFlightMaxTime = flightTime; - mFlightCurrentTime = 0.0f; - mFlightSourceDistance = mCurrentDistance; - mFlightSourcePosition = mTarget; - const float distanceHorizontalFOV = boundingBox.CalcRadius() / MCore::Math::Tan(0.5f * MCore::Math::DegreesToRadians(mFOV)); - const float distanceVerticalFOV = boundingBox.CalcRadius() / MCore::Math::Tan(0.5f * MCore::Math::DegreesToRadians(mFOV * mAspect)); - mFlightTargetDistance = MCore::Max(distanceHorizontalFOV, distanceVerticalFOV) * 0.9f; - mFlightTargetPosition = boundingBox.CalcMiddle(); - mFlightSourceAlpha = mAlpha; - mFlightSourceAlpha = mAlpha; - mFlightTargetAlpha = GetDefaultAlpha(); - mFlightSourceBeta = mBeta; - mFlightTargetBeta = GetDefaultBeta(); + m_flightActive = true; + m_flightMaxTime = flightTime; + m_flightCurrentTime = 0.0f; + m_flightSourceDistance = m_currentDistance; + m_flightSourcePosition = m_target; + const float distanceHorizontalFOV = boundingBox.CalcRadius() / MCore::Math::Tan(0.5f * MCore::Math::DegreesToRadians(m_fov)); + const float distanceVerticalFOV = boundingBox.CalcRadius() / MCore::Math::Tan(0.5f * MCore::Math::DegreesToRadians(m_fov * m_aspect)); + m_flightTargetDistance = MCore::Max(distanceHorizontalFOV, distanceVerticalFOV) * 0.9f; + m_flightTargetPosition = boundingBox.CalcMiddle(); + m_flightSourceAlpha = m_alpha; + m_flightSourceAlpha = m_alpha; + m_flightTargetAlpha = GetDefaultAlpha(); + m_flightSourceBeta = m_beta; + m_flightTargetBeta = GetDefaultBeta(); // make sure the target flight distance is in range - if (mFlightTargetDistance < mMinDistance) + if (m_flightTargetDistance < m_minDistance) { - mFlightTargetDistance = mMinDistance; + m_flightTargetDistance = m_minDistance; } - if (mFlightTargetDistance > mMaxDistance) + if (m_flightTargetDistance > m_maxDistance) { - mFlightTargetDistance = mMaxDistance; + m_flightTargetDistance = m_maxDistance; } } @@ -127,24 +127,24 @@ namespace MCommon if (leftButtonPressed && rightButtonPressed == false && middleButtonPressed == false) { // rotate our camera - mAlpha += mRotationSpeed * (float)-mouseMovementX; - mBeta += mRotationSpeed * (float) mouseMovementY; + m_alpha += m_rotationSpeed * (float)-mouseMovementX; + m_beta += m_rotationSpeed * (float) mouseMovementY; // prevent the camera from looking upside down - if (mBeta >= 90.0f - 0.01f) + if (m_beta >= 90.0f - 0.01f) { - mBeta = 90.0f - 0.01f; + m_beta = 90.0f - 0.01f; } - if (mBeta <= -90.0f + 0.01f) + if (m_beta <= -90.0f + 0.01f) { - mBeta = -90.0f + 0.01f; + m_beta = -90.0f + 0.01f; } // reset the camera to no rotation if we made a whole circle - if (mAlpha >= 360.0f || mAlpha <= -360.0f) + if (m_alpha >= 360.0f || m_alpha <= -360.0f) { - mAlpha = 0.0f; + m_alpha = 0.0f; } } @@ -152,8 +152,8 @@ namespace MCommon // zoom camera in or out if (leftButtonPressed == false && rightButtonPressed && middleButtonPressed == false) { - const float distanceScale = mCurrentDistance * 0.002f; - mCurrentDistance += (float)-mouseMovementY * distanceScale; + const float distanceScale = m_currentDistance * 0.002f; + m_currentDistance += (float)-mouseMovementY * distanceScale; } // is middle (or left+right) mouse button pressed? @@ -161,13 +161,13 @@ namespace MCommon if ((leftButtonPressed == false && rightButtonPressed == false && middleButtonPressed) || (leftButtonPressed && rightButtonPressed && middleButtonPressed == false)) { - const float distanceScale = mCurrentDistance * 0.002f; + const float distanceScale = m_currentDistance * 0.002f; //if (MCore::GetCoordinateSystem().IsRightHanded()) //distanceScale *= -1.0f; - mPositionDelta.SetX((float)mouseMovementX * distanceScale); - mPositionDelta.SetY((float)mouseMovementY * distanceScale); + m_positionDelta.SetX((float)mouseMovementX * distanceScale); + m_positionDelta.SetY((float)mouseMovementY * distanceScale); } } @@ -175,59 +175,59 @@ namespace MCommon // update the camera void OrbitCamera::Update(float timeDelta) { - if (mFlightActive) + if (m_flightActive) { - mFlightCurrentTime += timeDelta; + m_flightCurrentTime += timeDelta; - const float normalizedTime = mFlightCurrentTime / mFlightMaxTime; + const float normalizedTime = m_flightCurrentTime / m_flightMaxTime; const float interpolatedTime = MCore::CosineInterpolate(0.0f, 1.0f, normalizedTime); - mTarget = mFlightSourcePosition + (mFlightTargetPosition - mFlightSourcePosition) * interpolatedTime; - mCurrentDistance = mFlightSourceDistance + (mFlightTargetDistance - mFlightSourceDistance) * interpolatedTime; - mAlpha = mFlightSourceAlpha + (mFlightTargetAlpha - mFlightSourceAlpha) * interpolatedTime; - mBeta = mFlightSourceBeta + (mFlightTargetBeta - mFlightSourceBeta) * interpolatedTime; + m_target = m_flightSourcePosition + (m_flightTargetPosition - m_flightSourcePosition) * interpolatedTime; + m_currentDistance = m_flightSourceDistance + (m_flightTargetDistance - m_flightSourceDistance) * interpolatedTime; + m_alpha = m_flightSourceAlpha + (m_flightTargetAlpha - m_flightSourceAlpha) * interpolatedTime; + m_beta = m_flightSourceBeta + (m_flightTargetBeta - m_flightSourceBeta) * interpolatedTime; - if (mFlightCurrentTime >= mFlightMaxTime) + if (m_flightCurrentTime >= m_flightMaxTime) { - mFlightActive = false; - mTarget = mFlightTargetPosition; - mCurrentDistance = mFlightTargetDistance; - mAlpha = mFlightTargetAlpha; - mBeta = mFlightTargetBeta; + m_flightActive = false; + m_target = m_flightTargetPosition; + m_currentDistance = m_flightTargetDistance; + m_alpha = m_flightTargetAlpha; + m_beta = m_flightTargetBeta; } } // HACK TODO REMOVEME !!! const float scale = 1.0f; - mCurrentDistance *= scale; + m_currentDistance *= scale; - if (mCurrentDistance <= mMinDistance * scale) + if (m_currentDistance <= m_minDistance * scale) { - mCurrentDistance = mMinDistance * scale; + m_currentDistance = m_minDistance * scale; } - if (mCurrentDistance >= mMaxDistance * scale) + if (m_currentDistance >= m_maxDistance * scale) { - mCurrentDistance = mMaxDistance * scale; + m_currentDistance = m_maxDistance * scale; } // calculate unit direction vector based on our two angles AZ::Vector3 unitSphereVector; - unitSphereVector.SetX(MCore::Math::Cos(MCore::Math::DegreesToRadians(mAlpha)) * MCore::Math::Cos(MCore::Math::DegreesToRadians(mBeta))); - unitSphereVector.SetY(MCore::Math::Sin(MCore::Math::DegreesToRadians(mAlpha)) * MCore::Math::Cos(MCore::Math::DegreesToRadians(mBeta))); - unitSphereVector.SetZ(MCore::Math::Sin(MCore::Math::DegreesToRadians(mBeta))); + unitSphereVector.SetX(MCore::Math::Cos(MCore::Math::DegreesToRadians(m_alpha)) * MCore::Math::Cos(MCore::Math::DegreesToRadians(m_beta))); + unitSphereVector.SetY(MCore::Math::Sin(MCore::Math::DegreesToRadians(m_alpha)) * MCore::Math::Cos(MCore::Math::DegreesToRadians(m_beta))); + unitSphereVector.SetZ(MCore::Math::Sin(MCore::Math::DegreesToRadians(m_beta))); // calculate the right and the up vector based on the direction vector AZ::Vector3 rightVec = unitSphereVector.Cross(AZ::Vector3(0.0f, 0.0f, 1.0f)).GetNormalized(); AZ::Vector3 upVec = rightVec.Cross(unitSphereVector).GetNormalized(); // calculate the lookat target and the camera position using our rotation sphere vectors - mTarget += (rightVec * mPositionDelta.GetX()) * mTranslationSpeed + (upVec * mPositionDelta.GetY()) * mTranslationSpeed; - mPosition = mTarget + (unitSphereVector * mCurrentDistance); + m_target += (rightVec * m_positionDelta.GetX()) * m_translationSpeed + (upVec * m_positionDelta.GetY()) * m_translationSpeed; + m_position = m_target + (unitSphereVector * m_currentDistance); // reset the position delta - mPositionDelta = AZ::Vector2(0.0f, 0.0f); + m_positionDelta = AZ::Vector2(0.0f, 0.0f); // update our lookat camera at the very end LookAtCamera::Update(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/OrbitCamera.h b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/OrbitCamera.h index c3c33a3ef4..8aaa465da9 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/OrbitCamera.h +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/OrbitCamera.h @@ -76,27 +76,27 @@ namespace MCommon void ViewCloseup(const MCore::AABB& boundingBox, float flightTime) override; void StartFlight(float distance, const AZ::Vector3& position, float alpha, float beta, float flightTime); - bool GetIsFlightActive() const { return mFlightActive; } - void SetFlightTargetPosition(const AZ::Vector3& targetPos) { mFlightTargetPosition = targetPos; } + bool GetIsFlightActive() const { return m_flightActive; } + void SetFlightTargetPosition(const AZ::Vector3& targetPos) { m_flightTargetPosition = targetPos; } float FlightTimeLeft() const { - if (mFlightActive == false) + if (m_flightActive == false) { return 0.0f; } - return mFlightMaxTime - mFlightCurrentTime; + return m_flightMaxTime - m_flightCurrentTime; } - MCORE_INLINE float GetCurrentDistance() const { return mCurrentDistance; } - void SetCurrentDistance(float distance) { mCurrentDistance = distance; } + MCORE_INLINE float GetCurrentDistance() const { return m_currentDistance; } + void SetCurrentDistance(float distance) { m_currentDistance = distance; } - MCORE_INLINE float GetAlpha() const { return mAlpha; } + MCORE_INLINE float GetAlpha() const { return m_alpha; } static float GetDefaultAlpha() { return 110.0f; } - void SetAlpha(float alpha) { mAlpha = alpha; } + void SetAlpha(float alpha) { m_alpha = alpha; } - MCORE_INLINE float GetBeta() const { return mBeta; } + MCORE_INLINE float GetBeta() const { return m_beta; } static float GetDefaultBeta() { return 20.0f; } - void SetBeta(float beta) { mBeta = beta; } + void SetBeta(float beta) { m_beta = beta; } // automatically updates the camera afterwards void Set(float alpha, float beta, float currentDistance, const AZ::Vector3& target); @@ -105,24 +105,24 @@ namespace MCommon private: - AZ::Vector2 mPositionDelta; /**< The position delta which will be applied to the camera position when calling update. After adjusting the position it will be reset again. */ - float mMinDistance; /**< The minimum distance from the orbit camera to its target in the orbit sphere. */ - float mMaxDistance; /**< The maximum distance from the orbit camera to its target in the orbit sphere. */ - float mCurrentDistance; /**< The current distance from the orbit camera to its target in the orbit sphere. */ - float mAlpha; /**< The horizontal angle in our orbit sphere. */ - float mBeta; /**< The vertical angle in our orbit sphere. */ + AZ::Vector2 m_positionDelta; /**< The position delta which will be applied to the camera position when calling update. After adjusting the position it will be reset again. */ + float m_minDistance; /**< The minimum distance from the orbit camera to its target in the orbit sphere. */ + float m_maxDistance; /**< The maximum distance from the orbit camera to its target in the orbit sphere. */ + float m_currentDistance; /**< The current distance from the orbit camera to its target in the orbit sphere. */ + float m_alpha; /**< The horizontal angle in our orbit sphere. */ + float m_beta; /**< The vertical angle in our orbit sphere. */ - bool mFlightActive; - float mFlightMaxTime; - float mFlightCurrentTime; - float mFlightSourceDistance; - float mFlightTargetDistance; - AZ::Vector3 mFlightSourcePosition; - AZ::Vector3 mFlightTargetPosition; - float mFlightSourceAlpha; - float mFlightTargetAlpha; - float mFlightSourceBeta; - float mFlightTargetBeta; + bool m_flightActive; + float m_flightMaxTime; + float m_flightCurrentTime; + float m_flightSourceDistance; + float m_flightTargetDistance; + AZ::Vector3 m_flightSourcePosition; + AZ::Vector3 m_flightTargetPosition; + float m_flightSourceAlpha; + float m_flightTargetAlpha; + float m_flightSourceBeta; + float m_flightTargetBeta; }; } // namespace MCommon diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/OrthographicCamera.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/OrthographicCamera.cpp index 722f43c113..a64cdcc97f 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/OrthographicCamera.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/OrthographicCamera.cpp @@ -21,7 +21,7 @@ namespace MCommon { Reset(); SetMode(viewMode); - mProjectionMode = PROJMODE_ORTHOGRAPHIC; + m_projectionMode = PROJMODE_ORTHOGRAPHIC; } @@ -34,50 +34,50 @@ namespace MCommon // update the camera position, orientation and it's matrices void OrthographicCamera::Update(float timeDelta) { - if (mFlightActive) + if (m_flightActive) { - mFlightCurrentTime += timeDelta; + m_flightCurrentTime += timeDelta; - const float normalizedTime = mFlightCurrentTime / mFlightMaxTime; + const float normalizedTime = m_flightCurrentTime / m_flightMaxTime; const float interpolatedTime = MCore::CosineInterpolate(0.0f, 1.0f, normalizedTime); - mPosition = mFlightSourcePosition + (mFlightTargetPosition - mFlightSourcePosition) * interpolatedTime; - mCurrentDistance = mFlightSourceDistance + (mFlightTargetDistance - mFlightSourceDistance) * interpolatedTime; + m_position = m_flightSourcePosition + (m_flightTargetPosition - m_flightSourcePosition) * interpolatedTime; + m_currentDistance = m_flightSourceDistance + (m_flightTargetDistance - m_flightSourceDistance) * interpolatedTime; - if (mFlightCurrentTime >= mFlightMaxTime) + if (m_flightCurrentTime >= m_flightMaxTime) { - mFlightActive = false; - mPosition = mFlightTargetPosition; - mCurrentDistance = mFlightTargetDistance; + m_flightActive = false; + m_position = m_flightTargetPosition; + m_currentDistance = m_flightTargetDistance; } } // HACK TODO REMOVEME !!! const float scale = 1.0f; - mCurrentDistance *= scale; + m_currentDistance *= scale; - if (mCurrentDistance <= mMinDistance * scale) + if (m_currentDistance <= m_minDistance * scale) { - mCurrentDistance = mMinDistance * scale; + m_currentDistance = m_minDistance * scale; } - if (mCurrentDistance >= mMaxDistance * scale) + if (m_currentDistance >= m_maxDistance * scale) { - mCurrentDistance = mMaxDistance * scale; + m_currentDistance = m_maxDistance * scale; } // fake zoom the orthographic camera const float orthoScale = scale * 0.001f; - const float deltaX = mCurrentDistance * mScreenWidth * orthoScale; - const float deltaY = mCurrentDistance * mScreenHeight * orthoScale; + const float deltaX = m_currentDistance * m_screenWidth * orthoScale; + const float deltaY = m_currentDistance * m_screenHeight * orthoScale; SetOrthoClipDimensions(AZ::Vector2(deltaX, deltaY)); // adjust the mouse delta movement so that one pixel mouse movement is exactly one pixel on screen - mPositionDelta.SetX(mPositionDelta.GetX() * mCurrentDistance * orthoScale); - mPositionDelta.SetY(mPositionDelta.GetY() * mCurrentDistance * orthoScale); + m_positionDelta.SetX(m_positionDelta.GetX() * m_currentDistance * orthoScale); + m_positionDelta.SetY(m_positionDelta.GetY() * m_currentDistance * orthoScale); AZ::Vector3 xAxis, yAxis, zAxis; - switch (mMode) + switch (m_mode) { case VIEWMODE_FRONT: { @@ -86,11 +86,11 @@ namespace MCommon zAxis = AZ::Vector3(0.0f, 1.0f, 0.0f); // depth axis // translate the camera - mPosition += xAxis * -mPositionDelta.GetX(); - mPosition += yAxis * mPositionDelta.GetY(); + m_position += xAxis * -m_positionDelta.GetX(); + m_position += yAxis * m_positionDelta.GetY(); // setup the view matrix - MCore::LookAtRH(mViewMatrix, mPosition + zAxis * mCurrentDistance, mPosition, yAxis); + MCore::LookAtRH(m_viewMatrix, m_position + zAxis * m_currentDistance, m_position, yAxis); break; } @@ -101,11 +101,11 @@ namespace MCommon zAxis = AZ::Vector3(0.0f, -1.0f, 0.0f); // depth axis // translate the camera - mPosition += xAxis * -mPositionDelta.GetX(); - mPosition += yAxis * mPositionDelta.GetY(); + m_position += xAxis * -m_positionDelta.GetX(); + m_position += yAxis * m_positionDelta.GetY(); // setup the view matrix - MCore::LookAtRH(mViewMatrix, mPosition + zAxis * mCurrentDistance, mPosition, yAxis); + MCore::LookAtRH(m_viewMatrix, m_position + zAxis * m_currentDistance, m_position, yAxis); break; } @@ -117,11 +117,11 @@ namespace MCommon zAxis = AZ::Vector3(-1.0f, 0.0f, 0.0f); // depth axis // translate the camera - mPosition += xAxis * mPositionDelta.GetX(); - mPosition += yAxis * mPositionDelta.GetY(); + m_position += xAxis * m_positionDelta.GetX(); + m_position += yAxis * m_positionDelta.GetY(); // setup the view matrix - MCore::LookAtRH(mViewMatrix, mPosition + zAxis * mCurrentDistance, mPosition, yAxis); + MCore::LookAtRH(m_viewMatrix, m_position + zAxis * m_currentDistance, m_position, yAxis); break; } @@ -132,11 +132,11 @@ namespace MCommon zAxis = AZ::Vector3(1.0f, 0.0f, 0.0f); // depth axis // translate the camera - mPosition += xAxis * mPositionDelta.GetX(); - mPosition += yAxis * mPositionDelta.GetY(); + m_position += xAxis * m_positionDelta.GetX(); + m_position += yAxis * m_positionDelta.GetY(); // setup the view matrix - MCore::LookAtRH(mViewMatrix, mPosition + zAxis * mCurrentDistance, mPosition, yAxis); + MCore::LookAtRH(m_viewMatrix, m_position + zAxis * m_currentDistance, m_position, yAxis); break; } @@ -147,11 +147,11 @@ namespace MCommon zAxis = AZ::Vector3(0.0f, 0.0f, 1.0f); // depth axis // translate the camera - mPosition += -xAxis* mPositionDelta.GetX(); - mPosition += yAxis * mPositionDelta.GetY(); + m_position += -xAxis* m_positionDelta.GetX(); + m_position += yAxis * m_positionDelta.GetY(); // setup the view matrix - MCore::LookAtRH(mViewMatrix, mPosition + zAxis * mCurrentDistance, mPosition, yAxis); + MCore::LookAtRH(m_viewMatrix, m_position + zAxis * m_currentDistance, m_position, yAxis); break; } @@ -162,18 +162,18 @@ namespace MCommon zAxis = AZ::Vector3(0.0f, 0.0f, -1.0f); // depth axis // translate the camera - mPosition += -xAxis* mPositionDelta.GetX(); - mPosition += yAxis * mPositionDelta.GetY(); + m_position += -xAxis* m_positionDelta.GetX(); + m_position += yAxis * m_positionDelta.GetY(); // setup the view matrix - MCore::LookAtRH(mViewMatrix, mPosition + zAxis * mCurrentDistance, mPosition, yAxis); + MCore::LookAtRH(m_viewMatrix, m_position + zAxis * m_currentDistance, m_position, yAxis); break; } } ; // reset the position delta - mPositionDelta = AZ::Vector2(0.0f, 0.0f); + m_positionDelta = AZ::Vector2(0.0f, 0.0f); // update our base camera Camera::Update(); @@ -189,8 +189,8 @@ namespace MCommon // zoom camera in or out if (leftButtonPressed == false && rightButtonPressed && middleButtonPressed == false) { - const float distanceScale = mCurrentDistance * 0.002f; - mCurrentDistance += (float)-mouseMovementY * distanceScale; + const float distanceScale = m_currentDistance * 0.002f; + m_currentDistance += (float)-mouseMovementY * distanceScale; } // is middle (or left+right) mouse button pressed? @@ -198,8 +198,8 @@ namespace MCommon if ((leftButtonPressed == false && rightButtonPressed == false && middleButtonPressed) || (leftButtonPressed && rightButtonPressed && middleButtonPressed == false)) { - mPositionDelta.SetX((float)mouseMovementX); - mPositionDelta.SetY((float)mouseMovementY); + m_positionDelta.SetX((float)mouseMovementX); + m_positionDelta.SetY((float)mouseMovementY); } } @@ -207,41 +207,41 @@ namespace MCommon // reset the camera attributes void OrthographicCamera::Reset(float flightTime) { - mPositionDelta = AZ::Vector2(0.0f, 0.0f); - mMinDistance = MCore::Math::epsilon; - mMaxDistance = mFarClipDistance * 0.5f; + m_positionDelta = AZ::Vector2(0.0f, 0.0f); + m_minDistance = MCore::Math::epsilon; + m_maxDistance = m_farClipDistance * 0.5f; AZ::Vector3 resetPosition(0.0f, 0.0f, 0.0f); - switch (mMode) + switch (m_mode) { case VIEWMODE_FRONT: { - resetPosition.SetY(mCurrentDistance); + resetPosition.SetY(m_currentDistance); break; } case VIEWMODE_BACK: { - resetPosition.SetY(-mCurrentDistance); + resetPosition.SetY(-m_currentDistance); break; } case VIEWMODE_LEFT: { - resetPosition.SetX(-mCurrentDistance); + resetPosition.SetX(-m_currentDistance); break; } case VIEWMODE_RIGHT: { - resetPosition.SetX(mCurrentDistance); + resetPosition.SetX(m_currentDistance); break; } case VIEWMODE_TOP: { - resetPosition.SetZ(mCurrentDistance); + resetPosition.SetZ(m_currentDistance); break; } case VIEWMODE_BOTTOM: { - resetPosition.SetZ(-mCurrentDistance); + resetPosition.SetZ(-m_currentDistance); break; } } @@ -249,19 +249,19 @@ namespace MCommon if (flightTime < MCore::Math::epsilon) { - mFlightActive = false; - mCurrentDistance = (float)MCore::Distance::ConvertValue(5.0f, MCore::Distance::UNITTYPE_METERS, EMotionFX::GetEMotionFX().GetUnitType()); - mPosition = resetPosition; + m_flightActive = false; + m_currentDistance = (float)MCore::Distance::ConvertValue(5.0f, MCore::Distance::UNITTYPE_METERS, EMotionFX::GetEMotionFX().GetUnitType()); + m_position = resetPosition; } else { - mFlightActive = true; - mFlightMaxTime = flightTime; - mFlightCurrentTime = 0.0f; - mFlightSourceDistance = mCurrentDistance; - mFlightTargetDistance = (float)MCore::Distance::ConvertValue(5.0f, MCore::Distance::UNITTYPE_METERS, EMotionFX::GetEMotionFX().GetUnitType()); - mFlightSourcePosition = mPosition; - mFlightTargetPosition = resetPosition; + m_flightActive = true; + m_flightMaxTime = flightTime; + m_flightCurrentTime = 0.0f; + m_flightSourceDistance = m_currentDistance; + m_flightTargetDistance = (float)MCore::Distance::ConvertValue(5.0f, MCore::Distance::UNITTYPE_METERS, EMotionFX::GetEMotionFX().GetUnitType()); + m_flightSourcePosition = m_position; + m_flightTargetPosition = resetPosition; } // reset the base class attributes @@ -271,22 +271,22 @@ namespace MCommon void OrthographicCamera::StartFlight(float distance, const AZ::Vector3& position, float flightTime) { - mFlightMaxTime = flightTime; - mFlightCurrentTime = 0.0f; - mFlightSourceDistance = mCurrentDistance; - mFlightSourcePosition = mPosition; + m_flightMaxTime = flightTime; + m_flightCurrentTime = 0.0f; + m_flightSourceDistance = m_currentDistance; + m_flightSourcePosition = m_position; if (flightTime < MCore::Math::epsilon) { - mFlightActive = false; - mCurrentDistance = distance; - mPosition = position; + m_flightActive = false; + m_currentDistance = distance; + m_position = position; } else { - mFlightActive = true; - mFlightTargetDistance = distance; - mFlightTargetPosition = position; + m_flightActive = true; + m_flightTargetDistance = distance; + m_flightTargetPosition = position; } } @@ -294,14 +294,14 @@ namespace MCommon // closeup view of the given bounding box void OrthographicCamera::ViewCloseup(const MCore::AABB& boundingBox, float flightTime) { - mFlightMaxTime = flightTime; - mFlightCurrentTime = 0.0f; - mFlightSourceDistance = mCurrentDistance; - mFlightSourcePosition = mPosition; + m_flightMaxTime = flightTime; + m_flightCurrentTime = 0.0f; + m_flightSourceDistance = m_currentDistance; + m_flightSourcePosition = m_position; float boxWidth = 0.0f; float boxHeight = 0.0f; - switch (mMode) + switch (m_mode) { case VIEWMODE_FRONT: { @@ -343,32 +343,32 @@ namespace MCommon ; const float orthoScale = 0.001f; - assert(mScreenWidth != 0 && mScreenHeight != 0); - const float distanceX = (boxWidth) / (mScreenWidth * orthoScale); - const float distanceY = (boxHeight) / (mScreenHeight * orthoScale); + assert(m_screenWidth != 0 && m_screenHeight != 0); + const float distanceX = (boxWidth) / (m_screenWidth * orthoScale); + const float distanceY = (boxHeight) / (m_screenHeight * orthoScale); //LOG("box: x=%f y=%f, boxAspect=%f, orthoAspect=%f, distX=%f, distY=%f", boxWidth, boxHeight, boxAspect, orthoAspect, distanceX, distanceY); if (flightTime < MCore::Math::epsilon) { - mFlightActive = false; - mCurrentDistance = MCore::Max(distanceX, distanceY) * 1.1f; - mPosition = boundingBox.CalcMiddle(); + m_flightActive = false; + m_currentDistance = MCore::Max(distanceX, distanceY) * 1.1f; + m_position = boundingBox.CalcMiddle(); } else { - mFlightActive = true; - mFlightTargetDistance = MCore::Max(distanceX, distanceY) * 1.1f; - mFlightTargetPosition = boundingBox.CalcMiddle(); + m_flightActive = true; + m_flightTargetDistance = MCore::Max(distanceX, distanceY) * 1.1f; + m_flightTargetPosition = boundingBox.CalcMiddle(); } // make sure the target flight distance is in range - if (mFlightTargetDistance < mMinDistance) + if (m_flightTargetDistance < m_minDistance) { - mFlightTargetDistance = mMinDistance; + m_flightTargetDistance = m_minDistance; } - if (mFlightTargetDistance > mMaxDistance) + if (m_flightTargetDistance > m_maxDistance) { - mFlightTargetDistance = mMaxDistance; + m_flightTargetDistance = m_maxDistance; } } @@ -376,7 +376,7 @@ namespace MCommon // get the type identification string const char* OrthographicCamera::GetTypeString() const { - switch (mMode) + switch (m_mode) { case VIEWMODE_FRONT: { @@ -419,8 +419,8 @@ namespace MCommon // unproject screen coordinates to a ray MCore::Ray OrthographicCamera::Unproject(int32 screenX, int32 screenY) { - AZ::Vector3 start = MCore::UnprojectOrtho(static_cast(screenX), static_cast(screenY), static_cast(mScreenWidth), static_cast(mScreenHeight), -1.0f, mProjectionMatrix, mViewMatrix); - AZ::Vector3 end = MCore::UnprojectOrtho(static_cast(screenX), static_cast(screenY), static_cast(mScreenWidth), static_cast(mScreenHeight), 1.0f, mProjectionMatrix, mViewMatrix); + AZ::Vector3 start = MCore::UnprojectOrtho(static_cast(screenX), static_cast(screenY), static_cast(m_screenWidth), static_cast(m_screenHeight), -1.0f, m_projectionMatrix, m_viewMatrix); + AZ::Vector3 end = MCore::UnprojectOrtho(static_cast(screenX), static_cast(screenY), static_cast(m_screenWidth), static_cast(m_screenHeight), 1.0f, m_projectionMatrix, m_viewMatrix); return MCore::Ray(start, end); } @@ -429,7 +429,7 @@ namespace MCommon // update limits void OrthographicCamera::AutoUpdateLimits() { - mMinDistance = mNearClipDistance; - mMaxDistance = mFarClipDistance * 0.5f; + m_minDistance = m_nearClipDistance; + m_maxDistance = m_farClipDistance * 0.5f; } } // namespace MCommon diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/OrthographicCamera.h b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/OrthographicCamera.h index 4fc1b47778..e735cc22bb 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/OrthographicCamera.h +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/OrthographicCamera.h @@ -60,8 +60,8 @@ namespace MCommon */ const char* GetTypeString() const override; - MCORE_INLINE void SetMode(ViewMode viewMode) { mMode = viewMode; } - MCORE_INLINE ViewMode GetMode() const { return mMode; } + MCORE_INLINE void SetMode(ViewMode viewMode) { m_mode = viewMode; } + MCORE_INLINE ViewMode GetMode() const { return m_mode; } /** * Update the camera transformation. @@ -99,15 +99,15 @@ namespace MCommon void AutoUpdateLimits() override; void StartFlight(float distance, const AZ::Vector3& position, float flightTime); - bool GetIsFlightActive() const { return mFlightActive; } - void SetFlightTargetPosition(const AZ::Vector3& targetPos) { mFlightTargetPosition = targetPos; } + bool GetIsFlightActive() const { return m_flightActive; } + void SetFlightTargetPosition(const AZ::Vector3& targetPos) { m_flightTargetPosition = targetPos; } float FlightTimeLeft() const { - if (mFlightActive == false) + if (m_flightActive == false) { return 0.0f; } - return mFlightMaxTime - mFlightCurrentTime; + return m_flightMaxTime - m_flightCurrentTime; } /** @@ -118,22 +118,22 @@ namespace MCommon */ MCore::Ray Unproject(int32 screenX, int32 screenY) override; - MCORE_INLINE void SetCurrentDistance(float distance) { mCurrentDistance = distance; } - MCORE_INLINE float GetCurrentDistance() const { return mCurrentDistance; } + MCORE_INLINE void SetCurrentDistance(float distance) { m_currentDistance = distance; } + MCORE_INLINE float GetCurrentDistance() const { return m_currentDistance; } private: - ViewMode mMode; - AZ::Vector2 mPositionDelta; /**< The position delta which will be applied to the camera position when calling update. After adjusting the position it will be reset again. */ - float mMinDistance; /**< The minimum distance from the orbit camera to its target in the orbit sphere. */ - float mMaxDistance; /**< The maximum distance from the orbit camera to its target in the orbit sphere. */ - float mCurrentDistance; /**< The current distance from the orbit camera to its target in the orbit sphere. */ - bool mFlightActive; - float mFlightMaxTime; - float mFlightCurrentTime; - float mFlightSourceDistance; - AZ::Vector3 mFlightSourcePosition; - float mFlightTargetDistance; - AZ::Vector3 mFlightTargetPosition; + ViewMode m_mode; + AZ::Vector2 m_positionDelta; /**< The position delta which will be applied to the camera position when calling update. After adjusting the position it will be reset again. */ + float m_minDistance; /**< The minimum distance from the orbit camera to its target in the orbit sphere. */ + float m_maxDistance; /**< The maximum distance from the orbit camera to its target in the orbit sphere. */ + float m_currentDistance; /**< The current distance from the orbit camera to its target in the orbit sphere. */ + bool m_flightActive; + float m_flightMaxTime; + float m_flightCurrentTime; + float m_flightSourceDistance; + AZ::Vector3 m_flightSourcePosition; + float m_flightTargetDistance; + AZ::Vector3 m_flightTargetPosition; }; } // namespace MCommon diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RenderUtil.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RenderUtil.cpp index 34dba922ca..183d56a07f 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RenderUtil.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RenderUtil.cpp @@ -22,51 +22,51 @@ namespace MCommon { // gizmo colors - MCore::RGBAColor ManipulatorColors::mSelectionColor = MCore::RGBAColor(1.0f, 1.0f, 0.0f); - MCore::RGBAColor ManipulatorColors::mSelectionColorDarker = MCore::RGBAColor(0.5f, 0.5f, 0.0f, 0.5f); - MCore::RGBAColor ManipulatorColors::mRed = MCore::RGBAColor(0.781f, 0.0f, 0.0f); - MCore::RGBAColor ManipulatorColors::mGreen = MCore::RGBAColor(0.0f, 0.609f, 0.0f); - MCore::RGBAColor ManipulatorColors::mBlue = MCore::RGBAColor(0.0f, 0.0f, 0.762f); + MCore::RGBAColor ManipulatorColors::s_selectionColor = MCore::RGBAColor(1.0f, 1.0f, 0.0f); + MCore::RGBAColor ManipulatorColors::s_selectionColorDarker = MCore::RGBAColor(0.5f, 0.5f, 0.0f, 0.5f); + MCore::RGBAColor ManipulatorColors::s_red = MCore::RGBAColor(0.781f, 0.0f, 0.0f); + MCore::RGBAColor ManipulatorColors::s_green = MCore::RGBAColor(0.0f, 0.609f, 0.0f); + MCore::RGBAColor ManipulatorColors::s_blue = MCore::RGBAColor(0.0f, 0.0f, 0.762f); // static variables - uint32 RenderUtil::mNumMaxLineVertices = 8192 * 16;// 8096 * 16 * sizeof(LineVertex) = 3,5 MB - uint32 RenderUtil::mNumMaxMeshVertices = 1024; - uint32 RenderUtil::mNumMaxMeshIndices = 1024 * 3; - uint32 RenderUtil::mNumMax2DLines = 8192; - uint32 RenderUtil::mNumMaxTriangleVertices = 8192 * 16;// 8096 * 16 * sizeof(LineVertex) = 3,5 MB - float RenderUtil::m_wireframeSphereSegmentCount = 16.0f; + uint32 RenderUtil::s_numMaxLineVertices = 8192 * 16;// 8096 * 16 * sizeof(LineVertex) = 3,5 MB + uint32 RenderUtil::s_numMaxMeshVertices = 1024; + uint32 RenderUtil::s_numMaxMeshIndices = 1024 * 3; + uint32 RenderUtil::s_numMax2DLines = 8192; + uint32 RenderUtil::s_numMaxTriangleVertices = 8192 * 16;// 8096 * 16 * sizeof(LineVertex) = 3,5 MB + float RenderUtil::s_wireframeSphereSegmentCount = 16.0f; // constructor RenderUtil::RenderUtil() : m_devicePixelRatio(1.0f) { - mVertexBuffer = new LineVertex[mNumMaxLineVertices]; - m2DLines = new Line2D[mNumMax2DLines]; - mNumVertices = 0; - mNum2DLines = 0; - mUnitSphereMesh = CreateSphere(1.0f); - mCylinderMesh = CreateCylinder(2.0f, 1.0f, 2.0f); - mArrowHeadMesh = CreateArrowHead(1.0f, 0.5f); - mUnitCubeMesh = CreateCube(1.0f); - mFont = new VectorFont(this); + m_vertexBuffer = new LineVertex[s_numMaxLineVertices]; + m_m2DLines = new Line2D[s_numMax2DLines]; + m_numVertices = 0; + m_num2DLines = 0; + m_unitSphereMesh = CreateSphere(1.0f); + m_cylinderMesh = CreateCylinder(2.0f, 1.0f, 2.0f); + m_arrowHeadMesh = CreateArrowHead(1.0f, 0.5f); + m_unitCubeMesh = CreateCube(1.0f); + m_font = new VectorFont(this); } // destructor RenderUtil::~RenderUtil() { - delete[] mVertexBuffer; - delete[] m2DLines; - delete mUnitSphereMesh; - delete mCylinderMesh; - delete mUnitCubeMesh; - delete mArrowHeadMesh; - delete mFont; + delete[] m_vertexBuffer; + delete[] m_m2DLines; + delete m_unitSphereMesh; + delete m_cylinderMesh; + delete m_unitCubeMesh; + delete m_arrowHeadMesh; + delete m_font; // get rid of the world space positions - mWorldSpacePositions.clear(); + m_worldSpacePositions.clear(); } @@ -74,14 +74,14 @@ namespace MCommon void RenderUtil::RenderLines() { // check if we have to render anything and skip directly in case the line vertex buffer is empty - if (mNumVertices == 0) + if (m_numVertices == 0) { return; } // render the lines and reset the number of vertices - RenderLines(mVertexBuffer, mNumVertices); - mNumVertices = 0; + RenderLines(m_vertexBuffer, m_numVertices); + m_numVertices = 0; } @@ -89,14 +89,14 @@ namespace MCommon void RenderUtil::Render2DLines() { // check if we have to render anything and skip directly in case the line buffer is empty - if (mNum2DLines == 0) + if (m_num2DLines == 0) { return; } // render the lines and reset the number of lines - Render2DLines(m2DLines, mNum2DLines); - mNum2DLines = 0; + Render2DLines(m_m2DLines, m_num2DLines); + m_num2DLines = 0; } @@ -104,14 +104,14 @@ namespace MCommon void RenderUtil::RenderTriangles() { // check if we have to render anything and skip directly in case there are no triangles - if (mTriangleVertices.empty()) + if (m_triangleVertices.empty()) { return; } // render the triangles and clear the array - RenderTriangles(mTriangleVertices); - mTriangleVertices.clear(); + RenderTriangles(m_triangleVertices); + m_triangleVertices.clear(); } @@ -302,12 +302,12 @@ namespace MCommon // constructor RenderUtil::AABBRenderSettings::AABBRenderSettings() { - mNodeBasedAABB = true; - mMeshBasedAABB = true; - mStaticBasedAABB = true; - mStaticBasedColor = MCore::RGBAColor(0.0f, 0.7f, 0.7f); - mNodeBasedColor = MCore::RGBAColor(1.0f, 0.0f, 0.0f); - mMeshBasedColor = MCore::RGBAColor(0.0f, 0.0f, 0.7f); + m_nodeBasedAabb = true; + m_meshBasedAabb = true; + m_staticBasedAabb = true; + m_staticBasedColor = MCore::RGBAColor(0.0f, 0.7f, 0.7f); + m_nodeBasedColor = MCore::RGBAColor(1.0f, 0.0f, 0.0f); + m_meshBasedColor = MCore::RGBAColor(0.0f, 0.0f, 0.7f); } @@ -317,7 +317,7 @@ namespace MCommon const size_t lodLevel = actorInstance->GetLODLevel(); // handle the node based AABB - if (renderSettings.mNodeBasedAABB) + if (renderSettings.m_nodeBasedAabb) { // calculate the node based AABB AZ::Aabb box; @@ -326,12 +326,12 @@ namespace MCommon // render the aabb if (box.IsValid()) { - RenderAabb(box, renderSettings.mNodeBasedColor); + RenderAabb(box, renderSettings.m_nodeBasedColor); } } // handle the mesh based AABB - if (renderSettings.mMeshBasedAABB) + if (renderSettings.m_meshBasedAabb) { // calculate the mesh based AABB AZ::Aabb box; @@ -340,11 +340,11 @@ namespace MCommon // render the aabb if (box.IsValid()) { - RenderAabb(box, renderSettings.mMeshBasedColor); + RenderAabb(box, renderSettings.m_meshBasedColor); } } - if (renderSettings.mStaticBasedAABB) + if (renderSettings.m_staticBasedAabb) { // calculate the static based AABB AZ::Aabb box; @@ -353,7 +353,7 @@ namespace MCommon // render the aabb if (box.IsValid()) { - RenderAabb(box, renderSettings.mStaticBasedColor); + RenderAabb(box, renderSettings.m_staticBasedColor); } } @@ -382,14 +382,14 @@ namespace MCommon if (!visibleJointIndices || visibleJointIndices->empty() || (visibleJointIndices->find(jointIndex) != visibleJointIndices->end())) { - const AZ::Vector3 currentJointPos = pose->GetWorldSpaceTransform(jointIndex).mPosition; + const AZ::Vector3 currentJointPos = pose->GetWorldSpaceTransform(jointIndex).m_position; const bool jointSelected = selectedJointIndices->find(jointIndex) != selectedJointIndices->end(); const size_t parentIndex = joint->GetParentIndex(); if (parentIndex != InvalidIndex) { const bool parentSelected = selectedJointIndices->find(parentIndex) != selectedJointIndices->end(); - const AZ::Vector3 parentJointPos = pose->GetWorldSpaceTransform(parentIndex).mPosition; + const AZ::Vector3 parentJointPos = pose->GetWorldSpaceTransform(parentIndex).m_position; RenderLine(currentJointPos, parentJointPos, parentSelected ? selectedColor : color); } @@ -434,9 +434,9 @@ namespace MCommon const uint32 indexB = indices[triangleStartIndex + 1] + startVertex; const uint32 indexC = indices[triangleStartIndex + 2] + startVertex; - const AZ::Vector3 posA = mWorldSpacePositions[indexA] + normals[indexA] * scale; - const AZ::Vector3 posB = mWorldSpacePositions[indexB] + normals[indexB] * scale; - const AZ::Vector3 posC = mWorldSpacePositions[indexC] + normals[indexC] * scale; + const AZ::Vector3 posA = m_worldSpacePositions[indexA] + normals[indexA] * scale; + const AZ::Vector3 posB = m_worldSpacePositions[indexB] + normals[indexB] * scale; + const AZ::Vector3 posC = m_worldSpacePositions[indexC] + normals[indexC] * scale; if (vertexColors) { @@ -496,9 +496,9 @@ namespace MCommon const uint32 indexB = indices[triangleStartIndex + 1] + startVertex; const uint32 indexC = indices[triangleStartIndex + 2] + startVertex; - const AZ::Vector3& posA = mWorldSpacePositions[ indexA ]; - const AZ::Vector3& posB = mWorldSpacePositions[ indexB ]; - const AZ::Vector3& posC = mWorldSpacePositions[ indexC ]; + const AZ::Vector3& posA = m_worldSpacePositions[ indexA ]; + const AZ::Vector3& posB = m_worldSpacePositions[ indexB ]; + const AZ::Vector3& posC = m_worldSpacePositions[ indexC ]; const AZ::Vector3 normalDir = (posB - posA).Cross(posC - posA).GetNormalized(); @@ -524,7 +524,7 @@ namespace MCommon for (uint32 j = 0; j < numVertices; ++j) { const uint32 vertexIndex = j + startVertex; - const AZ::Vector3& position = mWorldSpacePositions[vertexIndex]; + const AZ::Vector3& position = m_worldSpacePositions[vertexIndex]; const AZ::Vector3 normal = worldTM.TransformVector(normals[vertexIndex]).GetNormalizedSafe() * vertexNormalsScale; RenderLine(position, position + normal, colorVertexNormals); } @@ -578,15 +578,15 @@ namespace MCommon } bitangent = (worldTM.TransformVector(bitangent)).GetNormalizedSafe(); - RenderLine(mWorldSpacePositions[i], mWorldSpacePositions[i] + (tangent * scale), colorTangents); + RenderLine(m_worldSpacePositions[i], m_worldSpacePositions[i] + (tangent * scale), colorTangents); if (tangents[i].GetW() < 0.0f) { - RenderLine(mWorldSpacePositions[i], mWorldSpacePositions[i] + (bitangent * scale), mirroredBitangentColor); + RenderLine(m_worldSpacePositions[i], m_worldSpacePositions[i] + (bitangent * scale), mirroredBitangentColor); } else { - RenderLine(mWorldSpacePositions[i], mWorldSpacePositions[i] + (bitangent * scale), colorBitangent); + RenderLine(m_worldSpacePositions[i], m_worldSpacePositions[i] + (bitangent * scale), colorBitangent); } } @@ -601,28 +601,28 @@ namespace MCommon void RenderUtil::PrepareForMesh(EMotionFX::Mesh* mesh, const AZ::Transform& worldTM) { // check if we have already prepared for the given mesh - if (mCurrentMesh == mesh) + if (m_currentMesh == mesh) { return; } // set our new current mesh - mCurrentMesh = mesh; + m_currentMesh = mesh; // get the number of vertices and the data - const uint32 numVertices = mCurrentMesh->GetNumVertices(); - AZ::Vector3* positions = (AZ::Vector3*)mCurrentMesh->FindVertexData(EMotionFX::Mesh::ATTRIB_POSITIONS); + const uint32 numVertices = m_currentMesh->GetNumVertices(); + AZ::Vector3* positions = (AZ::Vector3*)m_currentMesh->FindVertexData(EMotionFX::Mesh::ATTRIB_POSITIONS); // check if the vertices fits in our buffer - if (mWorldSpacePositions.size() < numVertices) + if (m_worldSpacePositions.size() < numVertices) { - mWorldSpacePositions.resize(numVertices); + m_worldSpacePositions.resize(numVertices); } // pre-calculate the world space positions for (uint32 i = 0; i < numVertices; ++i) { - mWorldSpacePositions[i] = worldTM.TransformPoint(positions[i]); + m_worldSpacePositions[i] = worldTM.TransformPoint(positions[i]); } } @@ -636,11 +636,11 @@ namespace MCommon const size_t nodeIndex = node->GetNodeIndex(); const size_t parentIndex = node->GetParentIndex(); - const AZ::Vector3 nodeWorldPos = pose->GetWorldSpaceTransform(nodeIndex).mPosition; + const AZ::Vector3 nodeWorldPos = pose->GetWorldSpaceTransform(nodeIndex).m_position; if (parentIndex != InvalidIndex) { - const AZ::Vector3 parentWorldPos = pose->GetWorldSpaceTransform(parentIndex).mPosition; + const AZ::Vector3 parentWorldPos = pose->GetWorldSpaceTransform(parentIndex).m_position; const AZ::Vector3 bone = parentWorldPos - nodeWorldPos; const float boneLength = MCore::SafeLength(bone); @@ -686,8 +686,8 @@ namespace MCommon if (!visibleJointIndices || visibleJointIndices->empty() || (visibleJointIndices->find(jointIndex) != visibleJointIndices->end())) { - const AZ::Vector3 nodeWorldPos = pose->GetWorldSpaceTransform(jointIndex).mPosition; - const AZ::Vector3 parentWorldPos = pose->GetWorldSpaceTransform(parentIndex).mPosition; + const AZ::Vector3 nodeWorldPos = pose->GetWorldSpaceTransform(jointIndex).m_position; + const AZ::Vector3 parentWorldPos = pose->GetWorldSpaceTransform(parentIndex).m_position; const AZ::Vector3 bone = parentWorldPos - nodeWorldPos; const AZ::Vector3 boneDirection = MCore::SafeNormalize(bone); const float boneLength = MCore::SafeLength(bone); @@ -740,24 +740,24 @@ namespace MCommon if (scaleBonesOnLength && parentIndex != InvalidIndex && AZStd::find(begin(boneList), end(boneList), jointIndex) != end(boneList)) { static const float axisBoneScale = 50.0f; - axisRenderingSettings.mSize = GetBoneScale(actorInstance, joint) * constPreScale * axisBoneScale; + axisRenderingSettings.m_size = GetBoneScale(actorInstance, joint) * constPreScale * axisBoneScale; } else { - axisRenderingSettings.mSize = constPreScale; + axisRenderingSettings.m_size = constPreScale; } // check if the current bone is selected and set the color according to it if (selectedJointIndices && selectedJointIndices->find(jointIndex) != selectedJointIndices->end()) { - axisRenderingSettings.mSelected = true; + axisRenderingSettings.m_selected = true; } else { - axisRenderingSettings.mSelected = false; + axisRenderingSettings.m_selected = false; } - axisRenderingSettings.mWorldTM = pose->GetWorldSpaceTransform(jointIndex).ToAZTransform(); + axisRenderingSettings.m_worldTm = pose->GetWorldSpaceTransform(jointIndex).ToAZTransform(); RenderLineAxis(axisRenderingSettings); } } @@ -783,8 +783,8 @@ namespace MCommon // render node orientation const EMotionFX::Transform worldTransform = pose->GetWorldSpaceTransform(nodeIndex); - axisRenderingSettings.mSize = GetBoneScale(actorInstance, node) * 5.0f; - axisRenderingSettings.mWorldTM = worldTransform.ToAZTransform(); + axisRenderingSettings.m_size = GetBoneScale(actorInstance, node) * 5.0f; + axisRenderingSettings.m_worldTm = worldTransform.ToAZTransform(); RenderLineAxis(axisRenderingSettings);// line based axis rendering // skip root nodes for the line based skeleton rendering, you could also use curNode->IsRootNode() @@ -792,8 +792,8 @@ namespace MCommon size_t parentIndex = node->GetParentIndex(); if (parentIndex != InvalidIndex) { - const AZ::Vector3 endPos = pose->GetWorldSpaceTransform(parentIndex).mPosition; - RenderLine(worldTransform.mPosition, endPos, color); + const AZ::Vector3 endPos = pose->GetWorldSpaceTransform(parentIndex).m_position; + RenderLine(worldTransform.m_position, endPos, color); } } @@ -821,14 +821,14 @@ namespace MCommon void RenderUtil::UtilMesh::CalculateNormals(bool counterClockWise) { // check if the normals actually got allocated - if (mNormals.empty()) + if (m_normals.empty()) { return; } // reset all normals to the zero vector - const size_t numNormals = mNormals.size(); - MCore::MemSet(&mNormals[0], 0, sizeof(AZ::Vector3) * numNormals); + const size_t numNormals = m_normals.size(); + MCore::MemSet(&m_normals[0], 0, sizeof(AZ::Vector3) * numNormals); // iterate through all vertices and sum up the face normals uint32 i; @@ -837,24 +837,24 @@ namespace MCommon for (i = 0; i < numNormals; i += 3) { - indexA = mIndices[i]; - indexB = mIndices[i + (counterClockWise ? 1 : 2)]; - indexC = mIndices[i + (counterClockWise ? 2 : 1)]; + indexA = m_indices[i]; + indexB = m_indices[i + (counterClockWise ? 1 : 2)]; + indexC = m_indices[i + (counterClockWise ? 2 : 1)]; - v1 = mPositions[indexB] - mPositions[indexA]; - v2 = mPositions[indexC] - mPositions[indexA]; + v1 = m_positions[indexB] - m_positions[indexA]; + v2 = m_positions[indexC] - m_positions[indexA]; normal = v1.Cross(v2); - mNormals[indexA] = mNormals[indexA] + normal; - mNormals[indexB] = mNormals[indexB] + normal; - mNormals[indexC] = mNormals[indexC] + normal; + m_normals[indexA] = m_normals[indexA] + normal; + m_normals[indexB] = m_normals[indexB] + normal; + m_normals[indexC] = m_normals[indexC] + normal; } // normalize all the normals for (i = 0; i < numNormals; ++i) { - mNormals[i] = mNormals[i].GetNormalized(); + m_normals[i] = m_normals[i].GetNormalized(); } } @@ -863,14 +863,14 @@ namespace MCommon void RenderUtil::UtilMesh::Allocate(uint32 numVertices, uint32 numIndices, bool hasNormals) { AZ_Assert(numVertices > 0 && numIndices % 3 == 0, "Invalid numVertices or numIndices"); - AZ_Assert(mPositions.empty() && mIndices.empty() && mNormals.empty(), "data already initialized"); + AZ_Assert(m_positions.empty() && m_indices.empty() && m_normals.empty(), "data already initialized"); // allocate the buffers - mPositions.resize(numVertices); - mIndices.resize(numIndices); + m_positions.resize(numVertices); + m_indices.resize(numIndices); if (hasNormals) { - mNormals.resize(numVertices); + m_normals.resize(numVertices); } } @@ -897,13 +897,13 @@ namespace MCommon void RenderUtil::FillCylinder(UtilMesh* mesh, float baseRadius, float topRadius, float length, bool calculateNormals) { // check if the positions and the indices have been allocated already by the CreateCylinder() function - if (mesh->mPositions.empty() || mesh->mIndices.empty()) + if (mesh->m_positions.empty() || mesh->m_indices.empty()) { return; } // number of segments/sides of the cylinder - const uint32 numSegments = static_cast(mesh->mPositions.size()) / 2; + const uint32 numSegments = static_cast(mesh->m_positions.size()) / 2; // fill in the vertices uint32 i; @@ -913,24 +913,24 @@ namespace MCommon const float z = MCore::Math::Sin(p); const float y = MCore::Math::Cos(p); - mesh->mPositions[i] = AZ::Vector3(0.0f, y * baseRadius, z * baseRadius); - mesh->mPositions[i + numSegments] = AZ::Vector3(-length, y * topRadius, z * topRadius); + mesh->m_positions[i] = AZ::Vector3(0.0f, y * baseRadius, z * baseRadius); + mesh->m_positions[i + numSegments] = AZ::Vector3(-length, y * topRadius, z * topRadius); } // fill in the indices uint32 c = 0; for (i = 0; i < numSegments; ++i) { - mesh->mIndices[c++] = i; - mesh->mIndices[c++] = ((i + 1) % numSegments); - mesh->mIndices[c++] = i + numSegments; + mesh->m_indices[c++] = i; + mesh->m_indices[c++] = ((i + 1) % numSegments); + mesh->m_indices[c++] = i + numSegments; } for (i = 0; i < numSegments; ++i) { - mesh->mIndices[c++] = i + numSegments; - mesh->mIndices[c++] = ((i + 1) % numSegments); - mesh->mIndices[c++] = ((i + 1) % numSegments) + numSegments; + mesh->m_indices[c++] = i + numSegments; + mesh->m_indices[c++] = ((i + 1) % numSegments); + mesh->m_indices[c++] = ((i + 1) % numSegments) + numSegments; } // recalculate normals if desired @@ -995,19 +995,19 @@ namespace MCommon const float x = r * MCore::Math::Sin(p); const float y = r * MCore::Math::Cos(p); - sphereMesh->mPositions[(i - 1) * numSegments + j] = AZ::Vector3(x, y, z * radius); + sphereMesh->m_positions[(i - 1) * numSegments + j] = AZ::Vector3(x, y, z * radius); } } // the highest and lowest vertices - sphereMesh->mPositions[(numSegments - 2) * numSegments + 0] = AZ::Vector3(0.0f, 0.0f, radius); - sphereMesh->mPositions[(numSegments - 2) * numSegments + 1] = AZ::Vector3(0.0f, 0.0f, -radius); + sphereMesh->m_positions[(numSegments - 2) * numSegments + 0] = AZ::Vector3(0.0f, 0.0f, radius); + sphereMesh->m_positions[(numSegments - 2) * numSegments + 1] = AZ::Vector3(0.0f, 0.0f, -radius); // calculate normals - const size_t numPositions = sphereMesh->mPositions.size(); + const size_t numPositions = sphereMesh->m_positions.size(); for (i = 0; i < numPositions; ++i) { - sphereMesh->mNormals[i] = -sphereMesh->mPositions[i].GetNormalized(); + sphereMesh->m_normals[i] = -sphereMesh->m_positions[i].GetNormalized(); } // fill the indices @@ -1016,46 +1016,46 @@ namespace MCommon { for (uint32 j = 0; j < numSegments - 1; j++) { - sphereMesh->mIndices[c++] = (i - 1) * numSegments + j; - sphereMesh->mIndices[c++] = (i - 1) * numSegments + j + 1; - sphereMesh->mIndices[c++] = i * numSegments + j; + sphereMesh->m_indices[c++] = (i - 1) * numSegments + j; + sphereMesh->m_indices[c++] = (i - 1) * numSegments + j + 1; + sphereMesh->m_indices[c++] = i * numSegments + j; - sphereMesh->mIndices[c++] = (i - 1) * numSegments + j + 1; - sphereMesh->mIndices[c++] = i * numSegments + j + 1; - sphereMesh->mIndices[c++] = i * numSegments + j; + sphereMesh->m_indices[c++] = (i - 1) * numSegments + j + 1; + sphereMesh->m_indices[c++] = i * numSegments + j + 1; + sphereMesh->m_indices[c++] = i * numSegments + j; } - sphereMesh->mIndices[c++] = (i - 1) * numSegments + numSegments - 1; - sphereMesh->mIndices[c++] = (i - 1) * numSegments; - sphereMesh->mIndices[c++] = i * numSegments + numSegments - 1; + sphereMesh->m_indices[c++] = (i - 1) * numSegments + numSegments - 1; + sphereMesh->m_indices[c++] = (i - 1) * numSegments; + sphereMesh->m_indices[c++] = i * numSegments + numSegments - 1; - sphereMesh->mIndices[c++] = i * numSegments; - sphereMesh->mIndices[c++] = (i - 1) * numSegments; - sphereMesh->mIndices[c++] = i * numSegments + numSegments - 1; + sphereMesh->m_indices[c++] = i * numSegments; + sphereMesh->m_indices[c++] = (i - 1) * numSegments; + sphereMesh->m_indices[c++] = i * numSegments + numSegments - 1; } // highest and deepest indices for (i = 0; i < numSegments - 1; ++i) { - sphereMesh->mIndices[c++] = i; - sphereMesh->mIndices[c++] = i + 1; - sphereMesh->mIndices[c++] = (numSegments - 2) * numSegments; + sphereMesh->m_indices[c++] = i; + sphereMesh->m_indices[c++] = i + 1; + sphereMesh->m_indices[c++] = (numSegments - 2) * numSegments; } - sphereMesh->mIndices[c++] = numSegments - 1; - sphereMesh->mIndices[c++] = 0; - sphereMesh->mIndices[c++] = (numSegments - 2) * numSegments; + sphereMesh->m_indices[c++] = numSegments - 1; + sphereMesh->m_indices[c++] = 0; + sphereMesh->m_indices[c++] = (numSegments - 2) * numSegments; for (i = 0; i < numSegments - 1; ++i) { - sphereMesh->mIndices[c++] = (numSegments - 3) * numSegments + i; - sphereMesh->mIndices[c++] = (numSegments - 3) * numSegments + i + 1; - sphereMesh->mIndices[c++] = (numSegments - 2) * numSegments + 1; + sphereMesh->m_indices[c++] = (numSegments - 3) * numSegments + i; + sphereMesh->m_indices[c++] = (numSegments - 3) * numSegments + i + 1; + sphereMesh->m_indices[c++] = (numSegments - 2) * numSegments + 1; } - sphereMesh->mIndices[c++] = (numSegments - 3) * numSegments + (numSegments - 1); - sphereMesh->mIndices[c++] = (numSegments - 3) * numSegments; - sphereMesh->mIndices[c++] = (numSegments - 2) * numSegments + 1; + sphereMesh->m_indices[c++] = (numSegments - 3) * numSegments + (numSegments - 1); + sphereMesh->m_indices[c++] = (numSegments - 3) * numSegments; + sphereMesh->m_indices[c++] = (numSegments - 2) * numSegments + 1; return sphereMesh; } @@ -1139,63 +1139,63 @@ namespace MCommon mesh->Allocate(numVertices, numTriangles * 3, true); // define the vertices - mesh->mPositions[0] = AZ::Vector3(-0.5f, -0.5f, -0.5f) * size; - mesh->mPositions[1] = AZ::Vector3(0.5f, -0.5f, -0.5f) * size; - mesh->mPositions[2] = AZ::Vector3(0.5f, 0.5f, -0.5f) * size; - mesh->mPositions[3] = AZ::Vector3(-0.5f, 0.5f, -0.5f) * size; - mesh->mPositions[4] = AZ::Vector3(-0.5f, -0.5f, 0.5f) * size; - mesh->mPositions[5] = AZ::Vector3(0.5f, -0.5f, 0.5f) * size; - mesh->mPositions[6] = AZ::Vector3(0.5f, 0.5f, 0.5f) * size; - mesh->mPositions[7] = AZ::Vector3(-0.5f, 0.5f, 0.5f) * size; + mesh->m_positions[0] = AZ::Vector3(-0.5f, -0.5f, -0.5f) * size; + mesh->m_positions[1] = AZ::Vector3(0.5f, -0.5f, -0.5f) * size; + mesh->m_positions[2] = AZ::Vector3(0.5f, 0.5f, -0.5f) * size; + mesh->m_positions[3] = AZ::Vector3(-0.5f, 0.5f, -0.5f) * size; + mesh->m_positions[4] = AZ::Vector3(-0.5f, -0.5f, 0.5f) * size; + mesh->m_positions[5] = AZ::Vector3(0.5f, -0.5f, 0.5f) * size; + mesh->m_positions[6] = AZ::Vector3(0.5f, 0.5f, 0.5f) * size; + mesh->m_positions[7] = AZ::Vector3(-0.5f, 0.5f, 0.5f) * size; // define the indices - mesh->mIndices[0] = 0; - mesh->mIndices[1] = 1; - mesh->mIndices[2] = 2; + mesh->m_indices[0] = 0; + mesh->m_indices[1] = 1; + mesh->m_indices[2] = 2; - mesh->mIndices[3] = 0; - mesh->mIndices[4] = 2; - mesh->mIndices[5] = 3; + mesh->m_indices[3] = 0; + mesh->m_indices[4] = 2; + mesh->m_indices[5] = 3; - mesh->mIndices[6] = 1; - mesh->mIndices[7] = 5; - mesh->mIndices[8] = 6; + mesh->m_indices[6] = 1; + mesh->m_indices[7] = 5; + mesh->m_indices[8] = 6; - mesh->mIndices[9] = 1; - mesh->mIndices[10] = 6; - mesh->mIndices[11] = 2; + mesh->m_indices[9] = 1; + mesh->m_indices[10] = 6; + mesh->m_indices[11] = 2; - mesh->mIndices[12] = 5; - mesh->mIndices[13] = 4; - mesh->mIndices[14] = 7; + mesh->m_indices[12] = 5; + mesh->m_indices[13] = 4; + mesh->m_indices[14] = 7; - mesh->mIndices[15] = 5; - mesh->mIndices[16] = 7; - mesh->mIndices[17] = 6; + mesh->m_indices[15] = 5; + mesh->m_indices[16] = 7; + mesh->m_indices[17] = 6; - mesh->mIndices[18] = 4; - mesh->mIndices[19] = 0; - mesh->mIndices[20] = 3; + mesh->m_indices[18] = 4; + mesh->m_indices[19] = 0; + mesh->m_indices[20] = 3; - mesh->mIndices[21] = 4; - mesh->mIndices[22] = 3; - mesh->mIndices[23] = 7; + mesh->m_indices[21] = 4; + mesh->m_indices[22] = 3; + mesh->m_indices[23] = 7; - mesh->mIndices[24] = 1; - mesh->mIndices[25] = 0; - mesh->mIndices[26] = 4; + mesh->m_indices[24] = 1; + mesh->m_indices[25] = 0; + mesh->m_indices[26] = 4; - mesh->mIndices[27] = 1; - mesh->mIndices[28] = 4; - mesh->mIndices[29] = 5; + mesh->m_indices[27] = 1; + mesh->m_indices[28] = 4; + mesh->m_indices[29] = 5; - mesh->mIndices[30] = 3; - mesh->mIndices[31] = 2; - mesh->mIndices[32] = 6; + mesh->m_indices[30] = 3; + mesh->m_indices[31] = 2; + mesh->m_indices[32] = 6; - mesh->mIndices[33] = 3; - mesh->mIndices[34] = 6; - mesh->mIndices[35] = 7; + mesh->m_indices[33] = 3; + mesh->m_indices[34] = 6; + mesh->m_indices[35] = 7; // calculate the normals mesh->CalculateNormals(); @@ -1219,7 +1219,7 @@ namespace MCommon // fill in the indices for (uint32 i = 0; i < numVertices; ++i) { - mesh->mIndices[i] = i; + mesh->m_indices[i] = i; } // fill in the vertices and recalculate the normals @@ -1234,7 +1234,7 @@ namespace MCommon { static AZ::Vector3 points[12]; size_t pointNr = 0; - const size_t numVertices = mesh->mPositions.size(); + const size_t numVertices = mesh->m_positions.size(); const size_t numTriangles = numVertices / 3; assert(numTriangles * 3 == numVertices); const size_t numSegments = numTriangles / 2; @@ -1273,14 +1273,14 @@ namespace MCommon vertexNr = i * 6; // triangle 1 - mesh->mPositions[vertexNr + 0] = segmentPoint; - mesh->mPositions[vertexNr + 1] = previousPoint; - mesh->mPositions[vertexNr + 2] = center; + mesh->m_positions[vertexNr + 0] = segmentPoint; + mesh->m_positions[vertexNr + 1] = previousPoint; + mesh->m_positions[vertexNr + 2] = center; // triangle 2 - mesh->mPositions[vertexNr + 3] = previousPoint; - mesh->mPositions[vertexNr + 4] = segmentPoint; - mesh->mPositions[vertexNr + 5] = top; + mesh->m_positions[vertexNr + 3] = previousPoint; + mesh->m_positions[vertexNr + 4] = segmentPoint; + mesh->m_positions[vertexNr + 5] = top; // postprocess data previousPoint = segmentPoint; @@ -1350,36 +1350,36 @@ namespace MCommon // constructor RenderUtil::AxisRenderingSettings::AxisRenderingSettings() { - mSize = 1.0f; - mRenderXAxis = true; - mRenderYAxis = true; - mRenderZAxis = true; - mRenderXAxisName = false; - mRenderYAxisName = false; - mRenderZAxisName = false; - mSelected = false; + m_size = 1.0f; + m_renderXAxis = true; + m_renderYAxis = true; + m_renderZAxis = true; + m_renderXAxisName = false; + m_renderYAxisName = false; + m_renderZAxisName = false; + m_selected = false; } // render line based axis void RenderUtil::RenderLineAxis(const AxisRenderingSettings& settings) { - const float size = settings.mSize; - const AZ::Transform& worldTM = settings.mWorldTM; - const AZ::Vector3& cameraRight = settings.mCameraRight; - const AZ::Vector3& cameraUp = settings.mCameraUp; + const float size = settings.m_size; + const AZ::Transform& worldTM = settings.m_worldTm; + const AZ::Vector3& cameraRight = settings.m_cameraRight; + const AZ::Vector3& cameraUp = settings.m_cameraUp; const float arrowHeadRadius = size * 0.1f; const float arrowHeadHeight = size * 0.3f; const float axisHeight = size * 0.7f; const AZ::Vector3 position = worldTM.GetTranslation(); - if (settings.mRenderXAxis) + if (settings.m_renderXAxis) { // set the color MCore::RGBAColor xAxisColor = MCore::RGBAColor(1.0f, 0.0f, 0.0f); MCore::RGBAColor xSelectedColor; - if (settings.mSelected) + if (settings.m_selected) { xSelectedColor = MCore::RGBAColor(1.0f, 0.647f, 0.0f); } @@ -1393,7 +1393,7 @@ namespace MCommon RenderArrowHead(arrowHeadHeight, arrowHeadRadius, xAxisArrowStart, xAxisDir, xSelectedColor); RenderLine(position, xAxisArrowStart, xAxisColor); - if (settings.mRenderXAxisName) + if (settings.m_renderXAxisName) { const AZ::Vector3 xNamePos = position + xAxisDir * (size * 1.15f); RenderLine(xNamePos + cameraUp * (-0.15f * size) + cameraRight * (0.1f * size), xNamePos + cameraUp * (0.15f * size) + cameraRight * (-0.1f * size), xAxisColor); @@ -1401,13 +1401,13 @@ namespace MCommon } } - if (settings.mRenderYAxis) + if (settings.m_renderYAxis) { // set the color MCore::RGBAColor yAxisColor = MCore::RGBAColor(0.0f, 1.0f, 0.0f); MCore::RGBAColor ySelectedColor; - if (settings.mSelected) + if (settings.m_selected) { ySelectedColor = MCore::RGBAColor(1.0f, 0.647f, 0.0f); } @@ -1421,7 +1421,7 @@ namespace MCommon RenderArrowHead(arrowHeadHeight, arrowHeadRadius, yAxisArrowStart, yAxisDir, ySelectedColor); RenderLine(position, yAxisArrowStart, yAxisColor); - if (settings.mRenderYAxisName) + if (settings.m_renderYAxisName) { const AZ::Vector3 yNamePos = position + yAxisDir * (size * 1.15f); RenderLine(yNamePos, yNamePos + cameraRight * (-0.1f * size) + cameraUp * (0.15f * size), yAxisColor); @@ -1430,13 +1430,13 @@ namespace MCommon } } - if (settings.mRenderZAxis) + if (settings.m_renderZAxis) { // set the color MCore::RGBAColor zAxisColor = MCore::RGBAColor(0.0f, 0.0f, 1.0f); MCore::RGBAColor zSelectedColor; - if (settings.mSelected) + if (settings.m_selected) { zSelectedColor = MCore::RGBAColor(1.0f, 0.647f, 0.0f); } @@ -1450,7 +1450,7 @@ namespace MCommon RenderArrowHead(arrowHeadHeight, arrowHeadRadius, zAxisArrowStart, zAxisDir, zSelectedColor); RenderLine(position, zAxisArrowStart, zAxisColor); - if (settings.mRenderZAxisName) + if (settings.m_renderZAxisName) { const AZ::Vector3 zNamePos = position + zAxisDir * (size * 1.15f); RenderLine(zNamePos + cameraRight * (-0.1f * size) + cameraUp * (0.15f * size), zNamePos + cameraRight * (0.1f * size) + cameraUp * (0.15f * size), zAxisColor); @@ -1700,7 +1700,7 @@ namespace MCommon } // get some helper variables and check if there is a motion extraction node set - EMotionFX::ActorInstance* actorInstance = trajectoryPath->mActorInstance; + EMotionFX::ActorInstance* actorInstance = trajectoryPath->m_actorInstance; EMotionFX::Actor* actor = actorInstance->GetActor(); EMotionFX::Node* extractionNode = actor->GetMotionExtractionNode(); if (extractionNode == NULL) @@ -1709,7 +1709,7 @@ namespace MCommon } // fast access to the trajectory trace particles - const AZStd::vector& traceParticles = trajectoryPath->mTraceParticles; + const AZStd::vector& traceParticles = trajectoryPath->m_traceParticles; const size_t numTraceParticles = traceParticles.size(); if (traceParticles.empty()) { @@ -1728,7 +1728,7 @@ namespace MCommon // Render arrow head ////////////////////////////////////////////////////////////////////////////////////////////////////// // get the position and some direction vectors of the trajectory node matrix - EMotionFX::Transform worldTM = traceParticles[numTraceParticles - 1].mWorldTM; + EMotionFX::Transform worldTM = traceParticles[numTraceParticles - 1].m_worldTm; AZ::Vector3 right = MCore::GetRight(trajectoryWorldTM).GetNormalized(); AZ::Vector3 center = trajectoryWorldTM.GetTranslation(); AZ::Vector3 forward = MCore::GetForward(trajectoryWorldTM).GetNormalized(); @@ -1787,17 +1787,17 @@ namespace MCommon float normalizedDistance = (float)i / numTraceParticles; // get the start and end point of the line segment and calculate the delta between them - worldTM = traceParticles[i].mWorldTM; - a = worldTM.mPosition; - b = traceParticles[i - 1].mWorldTM.mPosition; + worldTM = traceParticles[i].m_worldTm; + a = worldTM.m_position; + b = traceParticles[i - 1].m_worldTm.m_position; right = MCore::GetRight(worldTM.ToAZTransform()).GetNormalized(); if (i > 1 && i < numTraceParticles - 3) { - const AZ::Vector3 deltaA = traceParticles[i - 2].mWorldTM.mPosition - traceParticles[i - 1].mWorldTM.mPosition; - const AZ::Vector3 deltaB = traceParticles[i - 1].mWorldTM.mPosition - traceParticles[i ].mWorldTM.mPosition; - const AZ::Vector3 deltaC = traceParticles[i ].mWorldTM.mPosition - traceParticles[i + 1].mWorldTM.mPosition; - const AZ::Vector3 deltaD = traceParticles[i + 1].mWorldTM.mPosition - traceParticles[i + 2].mWorldTM.mPosition; + const AZ::Vector3 deltaA = traceParticles[i - 2].m_worldTm.m_position - traceParticles[i - 1].m_worldTm.m_position; + const AZ::Vector3 deltaB = traceParticles[i - 1].m_worldTm.m_position - traceParticles[i ].m_worldTm.m_position; + const AZ::Vector3 deltaC = traceParticles[i ].m_worldTm.m_position - traceParticles[i + 1].m_worldTm.m_position; + const AZ::Vector3 deltaD = traceParticles[i + 1].m_worldTm.m_position - traceParticles[i + 2].m_worldTm.m_position; AZ::Vector3 delta = deltaA + deltaB + deltaC + deltaD; delta = MCore::SafeNormalize(delta); @@ -1832,7 +1832,7 @@ namespace MCommon } // render the solid arrow - color.a = normalizedDistance; + color.m_a = normalizedDistance; RenderTriangle(vertices[0] + liftFromGround, vertices[2] + liftFromGround, vertices[1] + liftFromGround, color); RenderTriangle(vertices[1] + liftFromGround, vertices[2] + liftFromGround, vertices[3] + liftFromGround, color); @@ -1856,7 +1856,7 @@ namespace MCommon } // remove all particles while keeping the data in memory - trajectoryPath->mTraceParticles.clear(); + trajectoryPath->m_traceParticles.clear(); } @@ -1895,7 +1895,7 @@ namespace MCommon { const EMotionFX::Node* joint = skeleton->GetNode(actorInstance->GetEnabledNode(i)); const size_t jointIndex = joint->GetNodeIndex(); - const AZ::Vector3 worldPos = pose->GetWorldSpaceTransform(jointIndex).mPosition; + const AZ::Vector3 worldPos = pose->GetWorldSpaceTransform(jointIndex).m_position; // check if the current enabled node is along the visible nodes and render it if that is the case if (visibleJointIndices.empty() || @@ -1961,7 +1961,7 @@ namespace MCommon void RenderUtil::RenderWireframeSphere(float radius, const AZ::Transform& worldTM, const MCore::RGBAColor& color, bool directlyRender) { - const float stepSize = AZ::Constants::TwoPi / m_wireframeSphereSegmentCount; + const float stepSize = AZ::Constants::TwoPi / s_wireframeSphereSegmentCount; AZ::Vector3 pos1, pos2; float x1, y1, x2, y2; @@ -1997,7 +1997,7 @@ namespace MCommon // The end points of these half circles connect the bottom cap to the top cap (the cylinder part in the middle). void RenderUtil::RenderWireframeCapsule(float radius, float height, const AZ::Transform& worldTM, const MCore::RGBAColor& color, bool directlyRender) { - float stepSize = AZ::Constants::TwoPi / m_wireframeSphereSegmentCount; + float stepSize = AZ::Constants::TwoPi / s_wireframeSphereSegmentCount; const float cylinderHeight = height - 2.0f * radius; const float halfCylinderHeight = cylinderHeight * 0.5f; @@ -2341,73 +2341,68 @@ namespace MCommon RenderUtil::FontChar::FontChar() { - mIndexCount = 0; - mIndices = 0; - mX1 = mY1 = mX2 = mY2 = 0; + m_indexCount = 0; + m_indices = 0; + m_x1 = m_y1 = m_x2 = m_y2 = 0; } const unsigned char* RenderUtil::FontChar::Init(const unsigned char* data, const float* vertices) { - data = getUShort(data, mIndexCount); - mIndices = (const unsigned short*)data; - data += mIndexCount * sizeof(unsigned short); + data = getUShort(data, m_indexCount); + m_indices = (const unsigned short*)data; + data += m_indexCount * sizeof(unsigned short); - for (uint32 i = 0; i < mIndexCount; ++i) + for (uint32 i = 0; i < m_indexCount; ++i) { - uint32 index = mIndices[i]; + uint32 index = m_indices[i]; const float* vertex = &vertices[index * 2]; //assert( _finite(vertex[0]) ); //assert( _finite(vertex[1]) ); if (i == 0) { - mX1 = mX2 = vertex[0]; - mY1 = mY2 = vertex[1]; + m_x1 = m_x2 = vertex[0]; + m_y1 = m_y2 = vertex[1]; } else { - if (vertex[0] < mX1) + if (vertex[0] < m_x1) { - mX1 = vertex[0]; + m_x1 = vertex[0]; } - if (vertex[1] < mY1) + if (vertex[1] < m_y1) { - mY1 = vertex[1]; + m_y1 = vertex[1]; } - if (vertex[0] > mX2) + if (vertex[0] > m_x2) { - mX2 = vertex[0]; + m_x2 = vertex[0]; } - if (vertex[1] > mY2) + if (vertex[1] > m_y2) { - mY2 = vertex[1]; + m_y2 = vertex[1]; } } } - //assert( _finite(mX1) ); - //assert( _finite(mX2) ); - //assert( _finite(mY1) ); - //assert( _finite(mY2) ); - return data; } void RenderUtil::FontChar::Render(const float* vertices, RenderUtil* renderUtil, float textScale, float& x, float& y, float posX, float posY, const MCore::RGBAColor& color) { - if (mIndices) + if (m_indices) { - const uint32 lineCount = mIndexCount / 2; - const float spacing = (mX2 - mX1) + 0.05f; + const uint32 lineCount = m_indexCount / 2; + const float spacing = (m_x2 - m_x1) + 0.05f; AZ::Vector2 p1; AZ::Vector2 p2; for (uint32 i = 0; i < lineCount; ++i) { - const float* v1 = &vertices[ mIndices[i * 2 + 0] * 2 ]; - const float* v2 = &vertices[ mIndices[i * 2 + 1] * 2 ]; + const float* v1 = &vertices[ m_indices[i * 2 + 0] * 2 ]; + const float* v2 = &vertices[ m_indices[i * 2 + 1] * 2 ]; p1.SetX((v1[0] + x) * textScale + posX); p1.SetY((v1[1] + y) * textScale); p2.SetX((v2[0] + x) * textScale + posX); @@ -2427,11 +2422,11 @@ namespace MCommon RenderUtil::VectorFont::VectorFont(RenderUtil* renderUtil) { - mRenderUtil = renderUtil; - mVersion = 0; - mVcount = 0; - mCount = 0; - mVertices = NULL; + m_renderUtil = renderUtil; + m_version = 0; + m_vcount = 0; + m_count = 0; + m_vertices = NULL; Init(gFontData); } @@ -2445,10 +2440,10 @@ namespace MCommon void RenderUtil::VectorFont::Release() { - mVersion = 0; - mVcount = 0; - mCount = 0; - mVertices = NULL; + m_version = 0; + m_vcount = 0; + m_count = 0; + m_vertices = NULL; } @@ -2458,22 +2453,22 @@ namespace MCommon if (fontData[0] == 'F' && fontData[1] == 'O' && fontData[2] == 'N' && fontData[3] == 'T') { fontData += 4; - fontData = getUint(fontData, mVersion); + fontData = getUint(fontData, m_version); - if (mVersion == FONT_VERSION) + if (m_version == FONT_VERSION) { - fontData = getUint(fontData, mVcount); - fontData = getUint(fontData, mCount); - fontData = getUint(fontData, mIcount); + fontData = getUint(fontData, m_vcount); + fontData = getUint(fontData, m_count); + fontData = getUint(fontData, m_icount); - uint32 vsize = sizeof(float) * mVcount * 2; - mVertices = (float*)fontData; + uint32 vsize = sizeof(float) * m_vcount * 2; + m_vertices = (float*)fontData; fontData += vsize; - for (uint32 i = 0; i < mCount; ++i) + for (uint32 i = 0; i < m_count; ++i) { unsigned char c = *fontData++; - fontData = mCharacters[c].Init(fontData, mVertices); + fontData = m_characters[c].Init(fontData, m_vertices); } } } @@ -2487,10 +2482,7 @@ namespace MCommon while (*text) { char codeUnit = *text++; - //if (codeUnit <= 255) - textWidth += mCharacters[(int)codeUnit].GetWidth(); - //else - // textWidth += mCharacters['?'].GetWidth(); + textWidth += m_characters[(int)codeUnit].GetWidth(); } return textWidth; @@ -2511,10 +2503,7 @@ namespace MCommon while (*text) { const char c = *text++; - // if (c <= 255) - mCharacters[(int)c].Render(mVertices, mRenderUtil, fontScale, x, y, posX, posY, color); - // else - // mCharacters['?'].Render( mVertices, mRenderUtil, fontScale, x, y, posX, posY, color ); + m_characters[(int)c].Render(m_vertices, m_renderUtil, fontScale, x, y, posX, posY, color); } } } // namespace MCommon diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RenderUtil.h b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RenderUtil.h index 6e870c870e..c21c18fd07 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RenderUtil.h +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RenderUtil.h @@ -33,11 +33,11 @@ namespace MCommon public: // colors - static MCore::RGBAColor mSelectionColor; - static MCore::RGBAColor mSelectionColorDarker; - static MCore::RGBAColor mRed; - static MCore::RGBAColor mGreen; - static MCore::RGBAColor mBlue; + static MCore::RGBAColor s_selectionColor; + static MCore::RGBAColor s_selectionColorDarker; + static MCore::RGBAColor s_red; + static MCore::RGBAColor s_green; + static MCore::RGBAColor s_blue; }; @@ -149,12 +149,12 @@ namespace MCommon */ AABBRenderSettings(); - bool mNodeBasedAABB; /**< Enable in case you want to render the node based AABB (default=true). */ - bool mMeshBasedAABB; /**< Enable in case you want to render the mesh based AABB (default=true). */ - bool mStaticBasedAABB; /**< Enable in case you want to render the static based AABB (default=true). */ - MCore::RGBAColor mNodeBasedColor; /**< The color of the node based AABB. */ - MCore::RGBAColor mMeshBasedColor; /**< The color of the mesh based AABB. */ - MCore::RGBAColor mStaticBasedColor; /**< The color of the static based AABB. */ + bool m_nodeBasedAabb; /**< Enable in case you want to render the node based AABB (default=true). */ + bool m_meshBasedAabb; /**< Enable in case you want to render the mesh based AABB (default=true). */ + bool m_staticBasedAabb; /**< Enable in case you want to render the static based AABB (default=true). */ + MCore::RGBAColor m_nodeBasedColor; /**< The color of the node based AABB. */ + MCore::RGBAColor m_meshBasedColor; /**< The color of the mesh based AABB. */ + MCore::RGBAColor m_staticBasedColor; /**< The color of the static based AABB. */ }; /** @@ -239,7 +239,7 @@ namespace MCommon * @param color The desired sphere color. * @param worldTM The world space transformation matrix. */ - MCORE_INLINE void RenderSphere(const MCore::RGBAColor& color, const AZ::Transform& worldTM) { RenderUtilMesh(mUnitSphereMesh, color, worldTM); } + MCORE_INLINE void RenderSphere(const MCore::RGBAColor& color, const AZ::Transform& worldTM) { RenderUtilMesh(m_unitSphereMesh, color, worldTM); } /** * Render a circle, consisting of lines. @@ -255,7 +255,7 @@ namespace MCommon * @param color The desired cube color. * @param worldTM The world space transformation matrix. */ - MCORE_INLINE void RenderCube(const MCore::RGBAColor& color, const AZ::Transform& worldTM) { RenderUtilMesh(mUnitCubeMesh, color, worldTM); } + MCORE_INLINE void RenderCube(const MCore::RGBAColor& color, const AZ::Transform& worldTM) { RenderUtilMesh(m_unitCubeMesh, color, worldTM); } /** * Render a cylinder. @@ -265,7 +265,7 @@ namespace MCommon * @param color The desired cylinder color. * @param worldTM The world space transformation matrix. */ - MCORE_INLINE void RenderCylinder(float baseRadius, float topRadius, float length, const MCore::RGBAColor& color, const AZ::Transform& worldTM) { FillCylinder(mCylinderMesh, baseRadius, topRadius, length); RenderUtilMesh(mCylinderMesh, color, worldTM); } + MCORE_INLINE void RenderCylinder(float baseRadius, float topRadius, float length, const MCore::RGBAColor& color, const AZ::Transform& worldTM) { FillCylinder(m_cylinderMesh, baseRadius, topRadius, length); RenderUtilMesh(m_cylinderMesh, color, worldTM); } /** * Render a cylinder. @@ -302,7 +302,7 @@ namespace MCommon * @param color The desired arrow head color. * @param worldTM The world space transformation matrix. */ - MCORE_INLINE void RenderArrowHead(float height, float radius, const MCore::RGBAColor& color, const AZ::Transform& worldTM) { FillArrowHead(mArrowHeadMesh, height, radius); RenderUtilMesh(mArrowHeadMesh, color, worldTM); } + MCORE_INLINE void RenderArrowHead(float height, float radius, const MCore::RGBAColor& color, const AZ::Transform& worldTM) { FillArrowHead(m_arrowHeadMesh, height, radius); RenderUtilMesh(m_arrowHeadMesh, color, worldTM); } /** * Render an arrow head. @@ -336,17 +336,17 @@ namespace MCommon */ AxisRenderingSettings(); - AZ::Transform mWorldTM; /**< The world space transformation matrix to visualize. */ - AZ::Vector3 mCameraRight; /**< The inverse of the camera's right vector used for billboarding the axis names. */ - AZ::Vector3 mCameraUp; /**< The inverse of the camera's up vector used for billboarding the axis names. */ - float mSize; /**< The size value in units is used to control the scaling of the axis. */ - bool mRenderXAxis; /**< Set to true if you want to render the x axis, false if the x axis should be skipped. */ - bool mRenderYAxis; /**< Set to true if you want to render the y axis, false if the y axis should be skipped. */ - bool mRenderZAxis; /**< Set to true if you want to render the z axis, false if the z axis should be skipped. */ - bool mRenderXAxisName; /**< Set to true if you want to render the name of the x axis. The name will only be rendered if the axis itself will be rendered as well. */ - bool mRenderYAxisName; /**< Set to true if you want to render the name of the y axis. The name will only be rendered if the axis itself will be rendered as well. */ - bool mRenderZAxisName; /**< Set to true if you want to render the name of the z axis. The name will only be rendered if the axis itself will be rendered as well. */ - bool mSelected; /**< Set to true if you want to render the axis using the selection color. */ + AZ::Transform m_worldTm; /**< The world space transformation matrix to visualize. */ + AZ::Vector3 m_cameraRight; /**< The inverse of the camera's right vector used for billboarding the axis names. */ + AZ::Vector3 m_cameraUp; /**< The inverse of the camera's up vector used for billboarding the axis names. */ + float m_size; /**< The size value in units is used to control the scaling of the axis. */ + bool m_renderXAxis; /**< Set to true if you want to render the x axis, false if the x axis should be skipped. */ + bool m_renderYAxis; /**< Set to true if you want to render the y axis, false if the y axis should be skipped. */ + bool m_renderZAxis; /**< Set to true if you want to render the z axis, false if the z axis should be skipped. */ + bool m_renderXAxisName; /**< Set to true if you want to render the name of the x axis. The name will only be rendered if the axis itself will be rendered as well. */ + bool m_renderYAxisName; /**< Set to true if you want to render the name of the y axis. The name will only be rendered if the axis itself will be rendered as well. */ + bool m_renderZAxisName; /**< Set to true if you want to render the name of the z axis. The name will only be rendered if the axis itself will be rendered as well. */ + bool m_selected; /**< Set to true if you want to render the axis using the selection color. */ }; /** @@ -372,8 +372,8 @@ namespace MCommon struct MCOMMON_API LineVertex { MCORE_MEMORYOBJECTCATEGORY(RenderUtil::LineVertex, MCore::MCORE_DEFAULT_ALIGNMENT, MEMCATEGORY_MCOMMON); - AZ::Vector3 mPosition; /**< The position of the vertex. */ - MCore::RGBAColor mColor; /**< The vertex color. */ + AZ::Vector3 m_position; /**< The position of the vertex. */ + MCore::RGBAColor m_color; /**< The vertex color. */ }; /** @@ -384,12 +384,12 @@ namespace MCommon */ MCORE_INLINE void RenderLine(const AZ::Vector3& v1, const AZ::Vector3& v2, const MCore::RGBAColor& color) { - mVertexBuffer[mNumVertices].mPosition = v1; - mVertexBuffer[mNumVertices + 1].mPosition = v2; - mVertexBuffer[mNumVertices].mColor = color; - mVertexBuffer[mNumVertices + 1].mColor = color; - mNumVertices += 2; - if (mNumVertices >= mNumMaxLineVertices) + m_vertexBuffer[m_numVertices].m_position = v1; + m_vertexBuffer[m_numVertices + 1].m_position = v2; + m_vertexBuffer[m_numVertices].m_color = color; + m_vertexBuffer[m_numVertices + 1].m_color = color; + m_numVertices += 2; + if (m_numVertices >= s_numMaxLineVertices) { RenderLines(); } @@ -416,11 +416,11 @@ namespace MCommon struct MCOMMON_API Line2D { MCORE_MEMORYOBJECTCATEGORY(RenderUtil::Line2D, MCore::MCORE_DEFAULT_ALIGNMENT, MEMCATEGORY_MCOMMON); - float mX1; /**< The x position of the first vertex. */ - float mY1; /**< The y position of the first vertex. */ - float mX2; /**< The x position of the second vertex. */ - float mY2; /**< The y position of the second vertex. */ - MCore::RGBAColor mColor; /**< The line color. */ + float m_x1; /**< The x position of the first vertex. */ + float m_y1; /**< The y position of the first vertex. */ + float m_x2; /**< The x position of the second vertex. */ + float m_y2; /**< The y position of the second vertex. */ + MCore::RGBAColor m_color; /**< The line color. */ }; /** @@ -433,13 +433,13 @@ namespace MCommon */ MCORE_INLINE void Render2DLine(float x1, float y1, float x2, float y2, const MCore::RGBAColor& color) { - m2DLines[mNum2DLines].mX1 = x1; - m2DLines[mNum2DLines].mY1 = y1; - m2DLines[mNum2DLines].mX2 = x2; - m2DLines[mNum2DLines].mY2 = y2; - m2DLines[mNum2DLines].mColor = color; - mNum2DLines++; - if (mNum2DLines >= mNumMax2DLines) + m_m2DLines[m_num2DLines].m_x1 = x1; + m_m2DLines[m_num2DLines].m_y1 = y1; + m_m2DLines[m_num2DLines].m_x2 = x2; + m_m2DLines[m_num2DLines].m_y2 = y2; + m_m2DLines[m_num2DLines].m_color = color; + m_num2DLines++; + if (m_num2DLines >= s_numMax2DLines) { Render2DLines(); } @@ -489,9 +489,9 @@ namespace MCommon */ void Allocate(uint32 numVertices, uint32 numIndices, bool hasNormals); - AZStd::vector mPositions; /**< The vertex buffer. */ - AZStd::vector mIndices; /**< The index buffer. */ - AZStd::vector mNormals; /**< The normal buffer. */ + AZStd::vector m_positions; /**< The vertex buffer. */ + AZStd::vector m_indices; /**< The index buffer. */ + AZStd::vector m_normals; /**< The normal buffer. */ }; /** @@ -500,12 +500,12 @@ namespace MCommon struct UtilMeshVertex { MCORE_MEMORYOBJECTCATEGORY(RenderUtil::UtilMeshVertex, MCore::MCORE_DEFAULT_ALIGNMENT, MEMCATEGORY_MCOMMON); - AZ::Vector3 mPosition; /**< The position of the vertex. */ - AZ::Vector3 mNormal; /**< The vertex normal. */ + AZ::Vector3 m_position; /**< The position of the vertex. */ + AZ::Vector3 m_normal; /**< The vertex normal. */ UtilMeshVertex(const AZ::Vector3& pos, const AZ::Vector3& normal) - : mPosition(pos) - , mNormal(normal) {} + : m_position(pos) + , m_normal(normal) {} }; /** @@ -530,51 +530,33 @@ namespace MCommon * To avoid recalculating them several times we do this at a central place. This function needs to be called before switching to a new mesh inside * the render loop as well as before an animation update, so before calling any of the render normals, face normals, tangents and bitangents functions. */ - MCORE_INLINE void ResetCurrentMesh() { mCurrentMesh = NULL; } + MCORE_INLINE void ResetCurrentMesh() { m_currentMesh = NULL; } //--------------------------------------------------------------------------------------------- - /*struct MCOMMON_API Triangle - { - MCORE_MEMORYOBJECTCATEGORY( RenderUtil::Triangle, MCore::MCORE_DEFAULT_ALIGNMENT, MEMCATEGORY_MCOMMON ); - - AZ::Vector3 mPosA; - AZ::Vector3 mPosB; - AZ::Vector3 mPosC; - - AZ::Vector3 mNormalA; - AZ::Vector3 mNormalB; - AZ::Vector3 mNormalC; - - uint32 mColor; - - Triangle() {} - Triangle(const AZ::Vector3& posA, const AZ::Vector3& posB, const AZ::Vector3& posC, const AZ::Vector3& normalA, const AZ::Vector3& normalB, const AZ::Vector3& normalC, uint32 color) : mPosA(posA), mPosB(posB), mPosC(posC), mNormalA(normalA), mNormalB(normalB), mNormalC(normalC), mColor(color) {} - };*/ - /** * The vertex structure to be used for rendering util meshes. */ struct TriangleVertex { MCORE_MEMORYOBJECTCATEGORY(RenderUtil::TriangleVertex, MCore::MCORE_DEFAULT_ALIGNMENT, MEMCATEGORY_MCOMMON); - AZ::Vector3 mPosition; /**< The position of the vertex. */ - AZ::Vector3 mNormal; /**< The vertex normal. */ - uint32 mColor; + AZ::Vector3 m_position; /**< The position of the vertex. */ + AZ::Vector3 m_normal; /**< The vertex normal. */ + uint32 m_color; MCORE_INLINE TriangleVertex(const AZ::Vector3& pos, const AZ::Vector3& normal, uint32 color) - : mPosition(pos) - , mNormal(normal) - , mColor(color) {} + : m_position(pos) + , m_normal(normal) + , m_color(color) {} }; MCORE_INLINE void AddTriangle(const AZ::Vector3& posA, const AZ::Vector3& posB, const AZ::Vector3& posC, const AZ::Vector3& normalA, const AZ::Vector3& normalB, const AZ::Vector3& normalC, uint32 color) { - mTriangleVertices.emplace_back(TriangleVertex(posA, normalA, color)); - mTriangleVertices.emplace_back(TriangleVertex(posB, normalB, color)); - mTriangleVertices.emplace_back(TriangleVertex(posC, normalC, color)); + m_triangleVertices.emplace_back(TriangleVertex(posA, normalA, color)); + m_triangleVertices.emplace_back(TriangleVertex(posB, normalB, color)); + m_triangleVertices.emplace_back(TriangleVertex(posC, normalC, color)); - if (mTriangleVertices.size() + 2 >= mNumMaxTriangleVertices) + if (m_triangleVertices.size() + 2 >= s_numMaxTriangleVertices) { RenderTriangles(); } @@ -604,20 +586,20 @@ namespace MCommon struct TrajectoryPathParticle { - EMotionFX::Transform mWorldTM; + EMotionFX::Transform m_worldTm; }; struct TrajectoryTracePath { - AZStd::vector mTraceParticles; - EMotionFX::ActorInstance* mActorInstance; - float mTimePassed; + AZStd::vector m_traceParticles; + EMotionFX::ActorInstance* m_actorInstance; + float m_timePassed; TrajectoryTracePath() { - mTraceParticles.reserve(250); - mTimePassed = 0.0f; - mActorInstance = NULL; + m_traceParticles.reserve(250); + m_timePassed = 0.0f; + m_actorInstance = NULL; } }; @@ -637,7 +619,7 @@ namespace MCommon /** * Render text to screen. This will only work in case the Render2DLines() function has been implemented. */ - MCORE_INLINE void RenderText(float x, float y, const char* text, const MCore::RGBAColor& color = MCore::RGBAColor(1.0f, 1.0f, 1.0f), float fontSize = 11.0f, bool centered = false) { mFont->Render(x * m_devicePixelRatio, (y * m_devicePixelRatio) + fontSize - 1, fontSize, centered, text, color); } + MCORE_INLINE void RenderText(float x, float y, const char* text, const MCore::RGBAColor& color = MCore::RGBAColor(1.0f, 1.0f, 1.0f), float fontSize = 11.0f, bool centered = false) { m_font->Render(x * m_devicePixelRatio, (y * m_devicePixelRatio) + fontSize - 1, fontSize, centered, text, color); } /** * Render text to screen. This will only work in case the Render2DLines() function has been implemented. @@ -750,19 +732,19 @@ namespace MCommon MCORE_INLINE float GetWidth() const { float ret = 0.1f; - if (mIndexCount > 0) + if (m_indexCount > 0) { - ret = (mX2 - mX1) + 0.05f; + ret = (m_x2 - m_x1) + 0.05f; } return ret; } - float mX1; - float mX2; - float mY1; - float mY2; - unsigned short mIndexCount; - const unsigned short* mIndices; + float m_x1; + float m_x2; + float m_y1; + float m_y2; + unsigned short m_indexCount; + const unsigned short* m_indices; }; class MCOMMON_API VectorFont @@ -780,39 +762,39 @@ namespace MCommon float CalculateTextWidth(const char* text); private: - uint32 mVersion; - uint32 mVcount; - uint32 mCount; - float* mVertices; - uint32 mIcount; - FontChar mCharacters[256]; - RenderUtil* mRenderUtil; + uint32 m_version; + uint32 m_vcount; + uint32 m_count; + float* m_vertices; + uint32 m_icount; + FontChar m_characters[256]; + RenderUtil* m_renderUtil; }; - EMotionFX::Mesh* mCurrentMesh; /**< A pointer to the mesh whose world space positions are in the pre-calculated positions buffer. NULL in case we haven't pre-calculated any positions yet. */ - AZStd::vector mWorldSpacePositions; /**< The buffer used to store world space positions for rendering normals, tangents and the wireframe. */ + EMotionFX::Mesh* m_currentMesh; /**< A pointer to the mesh whose world space positions are in the pre-calculated positions buffer. NULL in case we haven't pre-calculated any positions yet. */ + AZStd::vector m_worldSpacePositions; /**< The buffer used to store world space positions for rendering normals, tangents and the wireframe. */ - LineVertex* mVertexBuffer; /**< Array of line vertices. */ - uint32 mNumVertices; /**< The current number of vertices in the array. */ - static uint32 mNumMaxLineVertices; /**< The maximum capacity of the line vertex buffer. */ + LineVertex* m_vertexBuffer; /**< Array of line vertices. */ + uint32 m_numVertices; /**< The current number of vertices in the array. */ + static uint32 s_numMaxLineVertices; /**< The maximum capacity of the line vertex buffer. */ - Line2D* m2DLines; /**< Array of 2D lines. */ - uint32 mNum2DLines; /**< The current number of 2D lines in the array. */ - static uint32 mNumMax2DLines; /**< The maximum capacity of the 2D line buffer. */ - static float m_wireframeSphereSegmentCount; + Line2D* m_m2DLines; /**< Array of 2D lines. */ + uint32 m_num2DLines; /**< The current number of 2D lines in the array. */ + static uint32 s_numMax2DLines; /**< The maximum capacity of the 2D line buffer. */ + static float s_wireframeSphereSegmentCount; float m_devicePixelRatio; - VectorFont* mFont; /**< The vector font used to render text. */ + VectorFont* m_font; /**< The vector font used to render text. */ - UtilMesh* mUnitSphereMesh; /**< The preallocated and preconstructed sphere mesh used for rendering. */ - UtilMesh* mCylinderMesh; /**< The preallocated and preconstructed cylinder mesh used for rendering. */ - UtilMesh* mUnitCubeMesh; /**< The preallocated and preconstructed cube mesh used for rendering. */ - UtilMesh* mArrowHeadMesh; /**< The preallocated and preconstructed arrow head mesh used for rendering. */ - static uint32 mNumMaxMeshVertices; /**< The maximum capacity of the util mesh vertex buffer. */ - static uint32 mNumMaxMeshIndices; /**< The maximum capacity of the util mesh index buffer */ + UtilMesh* m_unitSphereMesh; /**< The preallocated and preconstructed sphere mesh used for rendering. */ + UtilMesh* m_cylinderMesh; /**< The preallocated and preconstructed cylinder mesh used for rendering. */ + UtilMesh* m_unitCubeMesh; /**< The preallocated and preconstructed cube mesh used for rendering. */ + UtilMesh* m_arrowHeadMesh; /**< The preallocated and preconstructed arrow head mesh used for rendering. */ + static uint32 s_numMaxMeshVertices; /**< The maximum capacity of the util mesh vertex buffer. */ + static uint32 s_numMaxMeshIndices; /**< The maximum capacity of the util mesh index buffer */ // helper variables for rendering triangles - AZStd::vector mTriangleVertices; - static uint32 mNumMaxTriangleVertices; /**< The maximum capacity of the triangle vertex buffer */ + AZStd::vector m_triangleVertices; + static uint32 s_numMaxTriangleVertices; /**< The maximum capacity of the triangle vertex buffer */ }; } // namespace MCommon diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RotateManipulator.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RotateManipulator.cpp index 123ef00333..3a978d448c 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RotateManipulator.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RotateManipulator.cpp @@ -16,10 +16,10 @@ namespace MCommon RotateManipulator::RotateManipulator(float scalingFactor, bool isVisible) : TransformationManipulator(scalingFactor, isVisible) { - mMode = ROTATE_NONE; - mRotation = AZ::Vector3::CreateZero(); - mRotationQuat = AZ::Quaternion::CreateIdentity(); - mClickPosition = AZ::Vector3::CreateZero(); + m_mode = ROTATE_NONE; + m_rotation = AZ::Vector3::CreateZero(); + m_rotationQuat = AZ::Quaternion::CreateIdentity(); + m_clickPosition = AZ::Vector3::CreateZero(); } @@ -34,35 +34,35 @@ namespace MCommon { MCORE_UNUSED(camera); - // adjust the mSize when in ortho mode - mSize = mScalingFactor; - mInnerRadius = 0.15f * mSize; - mOuterRadius = 0.2f * mSize; - mArrowBaseRadius = mInnerRadius / 70.0f; - mAABBWidth = mInnerRadius / 30.0f;// previous 70.0f - mAxisSize = mSize * 0.05f; - mTextDistance = mSize * 0.05f; - mInnerQuadSize = 0.45f * MCore::Math::Sqrt(2) * mInnerRadius; + // adjust the m_size when in ortho mode + m_size = m_scalingFactor; + m_innerRadius = 0.15f * m_size; + m_outerRadius = 0.2f * m_size; + m_arrowBaseRadius = m_innerRadius / 70.0f; + m_aabbWidth = m_innerRadius / 30.0f;// previous 70.0f + m_axisSize = m_size * 0.05f; + m_textDistance = m_size * 0.05f; + m_innerQuadSize = 0.45f * MCore::Math::Sqrt(2) * m_innerRadius; // set the bounding volumes of the axes selection - mXAxisAABB.SetMax(mPosition + AZ::Vector3(mAABBWidth, mInnerRadius, mInnerRadius)); - mXAxisAABB.SetMin(mPosition - AZ::Vector3(mAABBWidth, mInnerRadius, mInnerRadius)); - mYAxisAABB.SetMax(mPosition + AZ::Vector3(mInnerRadius, mAABBWidth, mInnerRadius)); - mYAxisAABB.SetMin(mPosition - AZ::Vector3(mInnerRadius, mAABBWidth, mInnerRadius)); - mZAxisAABB.SetMax(mPosition + AZ::Vector3(mInnerRadius, mInnerRadius, mAABBWidth)); - mZAxisAABB.SetMin(mPosition - AZ::Vector3(mInnerRadius, mInnerRadius, mAABBWidth)); - mXAxisInnerAABB.SetMax(mPosition + AZ::Vector3(mAABBWidth, mInnerQuadSize, mInnerQuadSize)); - mXAxisInnerAABB.SetMin(mPosition - AZ::Vector3(mAABBWidth, mInnerQuadSize, mInnerQuadSize)); - mYAxisInnerAABB.SetMax(mPosition + AZ::Vector3(mInnerQuadSize, mAABBWidth, mInnerQuadSize)); - mYAxisInnerAABB.SetMin(mPosition - AZ::Vector3(mInnerQuadSize, mAABBWidth, mInnerQuadSize)); - mZAxisInnerAABB.SetMax(mPosition + AZ::Vector3(mInnerQuadSize, mInnerQuadSize, mAABBWidth)); - mZAxisInnerAABB.SetMin(mPosition - AZ::Vector3(mInnerQuadSize, mInnerQuadSize, mAABBWidth)); + m_xAxisAabb.SetMax(m_position + AZ::Vector3(m_aabbWidth, m_innerRadius, m_innerRadius)); + m_xAxisAabb.SetMin(m_position - AZ::Vector3(m_aabbWidth, m_innerRadius, m_innerRadius)); + m_yAxisAabb.SetMax(m_position + AZ::Vector3(m_innerRadius, m_aabbWidth, m_innerRadius)); + m_yAxisAabb.SetMin(m_position - AZ::Vector3(m_innerRadius, m_aabbWidth, m_innerRadius)); + m_zAxisAabb.SetMax(m_position + AZ::Vector3(m_innerRadius, m_innerRadius, m_aabbWidth)); + m_zAxisAabb.SetMin(m_position - AZ::Vector3(m_innerRadius, m_innerRadius, m_aabbWidth)); + m_xAxisInnerAabb.SetMax(m_position + AZ::Vector3(m_aabbWidth, m_innerQuadSize, m_innerQuadSize)); + m_xAxisInnerAabb.SetMin(m_position - AZ::Vector3(m_aabbWidth, m_innerQuadSize, m_innerQuadSize)); + m_yAxisInnerAabb.SetMax(m_position + AZ::Vector3(m_innerQuadSize, m_aabbWidth, m_innerQuadSize)); + m_yAxisInnerAabb.SetMin(m_position - AZ::Vector3(m_innerQuadSize, m_aabbWidth, m_innerQuadSize)); + m_zAxisInnerAabb.SetMax(m_position + AZ::Vector3(m_innerQuadSize, m_innerQuadSize, m_aabbWidth)); + m_zAxisInnerAabb.SetMin(m_position - AZ::Vector3(m_innerQuadSize, m_innerQuadSize, m_aabbWidth)); // set the bounding spheres for inner and outer circle modifiers - mInnerBoundingSphere.SetCenter(mPosition); - mInnerBoundingSphere.SetRadius(mInnerRadius); - mOuterBoundingSphere.SetCenter(mPosition); - mOuterBoundingSphere.SetRadius(mOuterRadius); + m_innerBoundingSphere.SetCenter(m_position); + m_innerBoundingSphere.SetRadius(m_innerRadius); + m_outerBoundingSphere.SetCenter(m_position); + m_outerBoundingSphere.SetRadius(m_outerRadius); } @@ -82,7 +82,7 @@ namespace MCommon MCore::Ray mousePosRay = camera->Unproject(mousePosX, mousePosY); // check if mouse ray hits the outer sphere of the manipulator - if (mousePosRay.Intersects(mOuterBoundingSphere)) + if (mousePosRay.Intersects(m_outerBoundingSphere)) { return true; } @@ -109,14 +109,14 @@ namespace MCommon MCore::Ray camRay = camera->Unproject(screenWidth / 2, screenHeight / 2); AZ::Vector3 camDir = camRay.GetDirection(); - mSignX = (MCore::Math::ACos(camDir.Dot(AZ::Vector3(1.0f, 0.0f, 0.0f))) >= MCore::Math::halfPi) ? 1.0f : -1.0f; - mSignY = (MCore::Math::ACos(camDir.Dot(AZ::Vector3(0.0f, 1.0f, 0.0f))) >= MCore::Math::halfPi) ? 1.0f : -1.0f; - mSignZ = (MCore::Math::ACos(camDir.Dot(AZ::Vector3(0.0f, 0.0f, 1.0f))) >= MCore::Math::halfPi) ? 1.0f : -1.0f; + m_signX = (MCore::Math::ACos(camDir.Dot(AZ::Vector3(1.0f, 0.0f, 0.0f))) >= MCore::Math::halfPi) ? 1.0f : -1.0f; + m_signY = (MCore::Math::ACos(camDir.Dot(AZ::Vector3(0.0f, 1.0f, 0.0f))) >= MCore::Math::halfPi) ? 1.0f : -1.0f; + m_signZ = (MCore::Math::ACos(camDir.Dot(AZ::Vector3(0.0f, 0.0f, 1.0f))) >= MCore::Math::halfPi) ? 1.0f : -1.0f; // determine the axis visibility, to disable movement for invisible axes - mXAxisVisible = (MCore::InRange(MCore::Math::Abs(camDir.Dot(AZ::Vector3(1.0f, 0.0f, 0.0f))) - 1.0f, -MCore::Math::epsilon, MCore::Math::epsilon) == false); - mYAxisVisible = (MCore::InRange(MCore::Math::Abs(camDir.Dot(AZ::Vector3(0.0f, 1.0f, 0.0f))) - 1.0f, -MCore::Math::epsilon, MCore::Math::epsilon) == false); - mZAxisVisible = (MCore::InRange(MCore::Math::Abs(camDir.Dot(AZ::Vector3(0.0f, 0.0f, 1.0f))) - 1.0f, -MCore::Math::epsilon, MCore::Math::epsilon) == false); + m_xAxisVisible = (MCore::InRange(MCore::Math::Abs(camDir.Dot(AZ::Vector3(1.0f, 0.0f, 0.0f))) - 1.0f, -MCore::Math::epsilon, MCore::Math::epsilon) == false); + m_yAxisVisible = (MCore::InRange(MCore::Math::Abs(camDir.Dot(AZ::Vector3(0.0f, 1.0f, 0.0f))) - 1.0f, -MCore::Math::epsilon, MCore::Math::epsilon) == false); + m_zAxisVisible = (MCore::InRange(MCore::Math::Abs(camDir.Dot(AZ::Vector3(0.0f, 0.0f, 1.0f))) - 1.0f, -MCore::Math::epsilon, MCore::Math::epsilon) == false); // update the bounding volumes UpdateBoundingVolumes(); @@ -127,12 +127,12 @@ namespace MCommon void RotateManipulator::Render(MCommon::Camera* camera, RenderUtil* renderUtil) { // return if no render util is set - if (renderUtil == nullptr || camera == nullptr || mIsVisible == false) + if (renderUtil == nullptr || camera == nullptr || m_isVisible == false) { return; } - // set mSize variables for the gizmo + // set m_size variables for the gizmo const uint32 screenWidth = camera->GetScreenWidth(); const uint32 screenHeight = camera->GetScreenHeight(); @@ -143,14 +143,13 @@ namespace MCommon MCore::RGBAColor blueTransparent = MCore::RGBAColor(0.0, 0.0, 0.762f, 0.2f); MCore::RGBAColor greyTransparent = MCore::RGBAColor(0.5f, 0.5f, 0.5f, 0.3f); - MCore::RGBAColor xAxisColor = (mMode == ROTATE_X) ? ManipulatorColors::mSelectionColor : ManipulatorColors::mRed; - MCore::RGBAColor yAxisColor = (mMode == ROTATE_Y) ? ManipulatorColors::mSelectionColor : ManipulatorColors::mGreen; - MCore::RGBAColor zAxisColor = (mMode == ROTATE_Z) ? ManipulatorColors::mSelectionColor : ManipulatorColors::mBlue; - MCore::RGBAColor camRollAxisColor = (mMode == ROTATE_CAMROLL) ? ManipulatorColors::mSelectionColor : grey; - //MCore::RGBAColor camPitchYawColor = (mMode == ROTATE_CAMPITCHYAW) ? ManipulatorColors::mSelectionColor : grey; + MCore::RGBAColor xAxisColor = (m_mode == ROTATE_X) ? ManipulatorColors::s_selectionColor : ManipulatorColors::s_red; + MCore::RGBAColor yAxisColor = (m_mode == ROTATE_Y) ? ManipulatorColors::s_selectionColor : ManipulatorColors::s_green; + MCore::RGBAColor zAxisColor = (m_mode == ROTATE_Z) ? ManipulatorColors::s_selectionColor : ManipulatorColors::s_blue; + MCore::RGBAColor camRollAxisColor = (m_mode == ROTATE_CAMROLL) ? ManipulatorColors::s_selectionColor : grey; // render axis in the center of the rotation gizmo - renderUtil->RenderAxis(mAxisSize, mPosition, AZ::Vector3(1.0f, 0.0f, 0.0f), AZ::Vector3(0.0f, 1.0f, 0.0f), AZ::Vector3(0.0f, 0.0f, 1.0f)); + renderUtil->RenderAxis(m_axisSize, m_position, AZ::Vector3(1.0f, 0.0f, 0.0f), AZ::Vector3(0.0f, 1.0f, 0.0f), AZ::Vector3(0.0f, 0.0f, 1.0f)); // shoot rays to the plane, to get upwards pointing vector on the plane // used for the text positioning and the angle visualization for the view rotation axis @@ -159,7 +158,7 @@ namespace MCommon AZ::Vector3 camRollAxis = originRay.GetDirection(); // calculate the plane perpendicular to the view rotation axis - MCore::PlaneEq rotationPlane(originRay.GetDirection(), mPosition); + MCore::PlaneEq rotationPlane(originRay.GetDirection(), m_position); // get the intersection points of the rays and the plane AZ::Vector3 originRayIntersect, upVecRayIntersect; @@ -177,66 +176,43 @@ namespace MCommon camViewMat.InvertFull(); // set the translation part of the matrix - camViewMat.SetTranslation(mPosition); + camViewMat.SetTranslation(m_position); // render the view axis rotation manipulator const AZ::Transform camViewTransform = AZ::Transform::CreateFromMatrix3x3AndTranslation( AZ::Matrix3x3::CreateFromMatrix4x4(camViewMat), camViewMat.GetTranslation()); - renderUtil->RenderCircle(camViewTransform, mOuterRadius, 64, camRollAxisColor); - renderUtil->RenderCircle(camViewTransform, mInnerRadius, 64, grey); + renderUtil->RenderCircle(camViewTransform, m_outerRadius, 64, camRollAxisColor); + renderUtil->RenderCircle(camViewTransform, m_innerRadius, 64, grey); - if (mMode == ROTATE_CAMPITCHYAW) + if (m_mode == ROTATE_CAMPITCHYAW) { - renderUtil->RenderCircle(camViewTransform, mInnerRadius, 64, grey, 0.0f, MCore::Math::twoPi, true, greyTransparent); + renderUtil->RenderCircle(camViewTransform, m_innerRadius, 64, grey, 0.0f, MCore::Math::twoPi, true, greyTransparent); } - // handle the rotation around the camera roll axis - /* - if (mMode == ROTATE_CAMROLL) - { - // calculate angle of the click position to the reference directions - const float angleUp = Math::ACos( mClickPosition.Dot(upVector) ); - const float angleLeft = Math::ACos( mClickPosition.Dot(leftVector) ); - - // rotate the whole circle around pi, if rotation is in the negative direction - if (mRotation.Dot(mRotationAxis) < 0) - camViewMat = camViewMat * camViewMat.RotationMatrixAxisAngle( upVector, Math::pi ); - - // handle different dot product results (necessary because dot product only handles a range of [0, pi]) - if (angleLeft > Math::halfPi) - camViewMat = camViewMat * camViewMat.RotationMatrixAxisAngle( mRotationAxis, -angleUp ); - else - camViewMat = camViewMat * camViewMat.RotationMatrixAxisAngle( mRotationAxis, angleUp ); - - // render the rotated circle segment to represent the current rotation angle around the view axis - renderUtil->RenderCircle( camViewMat, mOuterRadius, 64, ManipulatorColors::mSelectionColor, 0.0f, mRotation.Length(), true, greyTransparent ); - } - */ - // calculate the signs of the rotation and the angle between the axes and the click position - const float signX = (mRotation.GetX() >= 0) ? 1.0f : -1.0f; - const float signY = (mRotation.GetY() >= 0) ? 1.0f : -1.0f; - const float signZ = (mRotation.GetZ() >= 0) ? 1.0f : -1.0f; - const float angleX = MCore::Math::ACos(mClickPosition.Dot(AZ::Vector3(1.0f, 0.0f, 0.0f))); - const float angleY = MCore::Math::ACos(mClickPosition.Dot(AZ::Vector3(0.0f, 1.0f, 0.0f))); - const float angleZ = MCore::Math::ACos(mClickPosition.Dot(AZ::Vector3(0.0f, 0.0f, 1.0f))); + const float signX = (m_rotation.GetX() >= 0) ? 1.0f : -1.0f; + const float signY = (m_rotation.GetY() >= 0) ? 1.0f : -1.0f; + const float signZ = (m_rotation.GetZ() >= 0) ? 1.0f : -1.0f; + const float angleX = MCore::Math::ACos(m_clickPosition.Dot(AZ::Vector3(1.0f, 0.0f, 0.0f))); + const float angleY = MCore::Math::ACos(m_clickPosition.Dot(AZ::Vector3(0.0f, 1.0f, 0.0f))); + const float angleZ = MCore::Math::ACos(m_clickPosition.Dot(AZ::Vector3(0.0f, 0.0f, 1.0f))); // transformation matrix for the circle for rotation around the x axis AZ::Transform rotMatrixX = MCore::GetRotationMatrixAxisAngle(AZ::Vector3(0.0f, 1.0f, 0.0f), signX * MCore::Math::halfPi); // set the translation part of the matrix - rotMatrixX.SetTranslation(mPosition); + rotMatrixX.SetTranslation(m_position); // render the circle for the rotation around the x axis - if (mMode == ROTATE_X) + if (m_mode == ROTATE_X) { - renderUtil->RenderCircle(rotMatrixX, mInnerRadius, 64, grey); + renderUtil->RenderCircle(rotMatrixX, m_innerRadius, 64, grey); } - renderUtil->RenderCircle(rotMatrixX, mInnerRadius, 64, xAxisColor, 0.0f, MCore::Math::twoPi, false, MCore::RGBAColor(), true, camRollAxis); + renderUtil->RenderCircle(rotMatrixX, m_innerRadius, 64, xAxisColor, 0.0f, MCore::Math::twoPi, false, MCore::RGBAColor(), true, camRollAxis); // draw current angle if in x rotation mode - if (mMode == ROTATE_X) + if (m_mode == ROTATE_X) { // handle different dot product results (necessary because dot product only handles a range of [0, pi]) if (angleZ > MCore::Math::halfPi) @@ -249,28 +225,28 @@ namespace MCommon } // set the translation part of the matrix - rotMatrixX.SetTranslation(mPosition); + rotMatrixX.SetTranslation(m_position); // render the rotated circle segment to represent the current rotation angle around the x axis - renderUtil->RenderCircle(rotMatrixX, mInnerRadius, 64, ManipulatorColors::mSelectionColor, 0.0f, MCore::Math::Abs(mRotation.GetX()), true, redTransparent, true, camRollAxis); + renderUtil->RenderCircle(rotMatrixX, m_innerRadius, 64, ManipulatorColors::s_selectionColor, 0.0f, MCore::Math::Abs(m_rotation.GetX()), true, redTransparent, true, camRollAxis); } // rotation matrix for rotation around the y axis AZ::Transform rotMatrixY = MCore::GetRotationMatrixAxisAngle(AZ::Vector3(1.0f, 0.0f, 0.0f), MCore::Math::halfPi); // set the translation part of the matrix - rotMatrixY.SetTranslation(mPosition); + rotMatrixY.SetTranslation(m_position); // render the circle for rotation around the y axis - if (mMode == ROTATE_Y) + if (m_mode == ROTATE_Y) { - renderUtil->RenderCircle(rotMatrixY, mInnerRadius, 64, grey); + renderUtil->RenderCircle(rotMatrixY, m_innerRadius, 64, grey); } - renderUtil->RenderCircle(rotMatrixY, mInnerRadius, 64, yAxisColor, 0.0f, MCore::Math::twoPi, false, MCore::RGBAColor(), true, camRollAxis); + renderUtil->RenderCircle(rotMatrixY, m_innerRadius, 64, yAxisColor, 0.0f, MCore::Math::twoPi, false, MCore::RGBAColor(), true, camRollAxis); // draw current angle if in y rotation mode - if (mMode == ROTATE_Y) + if (m_mode == ROTATE_Y) { // render current rotation angle depending on the dot product results calculated above if (signY > 0) @@ -293,28 +269,28 @@ namespace MCommon } // set the translation part of the matrix - rotMatrixY.SetTranslation(mPosition); + rotMatrixY.SetTranslation(m_position); // render the rotated circle segment to represent the current rotation angle around the y axis - renderUtil->RenderCircle(rotMatrixY, mInnerRadius, 64, ManipulatorColors::mSelectionColor, 0.0f, MCore::Math::Abs(mRotation.GetY()), true, greenTransparent, true, camRollAxis); + renderUtil->RenderCircle(rotMatrixY, m_innerRadius, 64, ManipulatorColors::s_selectionColor, 0.0f, MCore::Math::Abs(m_rotation.GetY()), true, greenTransparent, true, camRollAxis); } // the circle for rotation around the z axis AZ::Transform rotMatrixZ = AZ::Transform::CreateIdentity(); // set the translation part of the matrix - rotMatrixZ.SetTranslation(mPosition); + rotMatrixZ.SetTranslation(m_position); // render the circle for rotation around the z axis - if (mMode == ROTATE_Z) + if (m_mode == ROTATE_Z) { - renderUtil->RenderCircle(rotMatrixZ, mInnerRadius, 64, grey); + renderUtil->RenderCircle(rotMatrixZ, m_innerRadius, 64, grey); } - renderUtil->RenderCircle(rotMatrixZ, mInnerRadius, 64, zAxisColor, 0.0f, MCore::Math::twoPi, false, MCore::RGBAColor(), true, camRollAxis); + renderUtil->RenderCircle(rotMatrixZ, m_innerRadius, 64, zAxisColor, 0.0f, MCore::Math::twoPi, false, MCore::RGBAColor(), true, camRollAxis); // draw current angle if in z rotation mode - if (mMode == ROTATE_Z) + if (m_mode == ROTATE_Z) { // render current rotation angle depending on the dot product results calculated above if (signZ < 0.0f) @@ -337,56 +313,56 @@ namespace MCommon } // set the translation part of the matrix - rotMatrixZ.SetTranslation(mPosition); + rotMatrixZ.SetTranslation(m_position); // render the rotated circle segment to represent the current rotation angle around the z axis - renderUtil->RenderCircle(rotMatrixZ, mInnerRadius, 64, ManipulatorColors::mSelectionColor, 0.0f, MCore::Math::Abs(mRotation.GetZ()), true, blueTransparent, true, camRollAxis); + renderUtil->RenderCircle(rotMatrixZ, m_innerRadius, 64, ManipulatorColors::s_selectionColor, 0.0f, MCore::Math::Abs(m_rotation.GetZ()), true, blueTransparent, true, camRollAxis); } // break if in different projection mode and camera roll rotation mode - if (mCurrentProjectionMode != camera->GetProjectionMode() && mMode == ROTATE_CAMROLL) + if (m_currentProjectionMode != camera->GetProjectionMode() && m_mode == ROTATE_CAMROLL) { return; } // render the absolute rotation if gizmo is hit - if (mMode != ROTATE_NONE) + if (m_mode != ROTATE_NONE) { - const AZ::Vector3 currRot = MCore::AzQuaternionToEulerAngles(mCallback->GetCurrValueQuat()); - mTempString = AZStd::string::format("Abs. Rotation X: %.3f, Y: %.3f, Z: %.3f", MCore::Math::RadiansToDegrees(currRot.GetX() + MCore::Math::epsilon), MCore::Math::RadiansToDegrees(currRot.GetY() + MCore::Math::epsilon), MCore::Math::RadiansToDegrees(currRot.GetZ() + MCore::Math::epsilon)); - renderUtil->RenderText(10, 10, mTempString.c_str(), ManipulatorColors::mSelectionColor, 9.0f); + const AZ::Vector3 currRot = MCore::AzQuaternionToEulerAngles(m_callback->GetCurrValueQuat()); + m_tempString = AZStd::string::format("Abs. Rotation X: %.3f, Y: %.3f, Z: %.3f", MCore::Math::RadiansToDegrees(currRot.GetX() + MCore::Math::epsilon), MCore::Math::RadiansToDegrees(currRot.GetY() + MCore::Math::epsilon), MCore::Math::RadiansToDegrees(currRot.GetZ() + MCore::Math::epsilon)); + renderUtil->RenderText(10, 10, m_tempString.c_str(), ManipulatorColors::s_selectionColor, 9.0f); } // if the rotation has been changed draw the current direction of the rotation - if (mRotation.GetLength() > 0.0f) + if (m_rotation.GetLength() > 0.0f) { // render text with the rotation values of the axes - float radius = (mMode == ROTATE_CAMROLL) ? mOuterRadius : mInnerRadius; - mTempString = AZStd::string::format("[%.2f, %.2f, %.2f]", MCore::Math::RadiansToDegrees(mRotation.GetX()), MCore::Math::RadiansToDegrees(mRotation.GetY()), MCore::Math::RadiansToDegrees(mRotation.GetZ())); + float radius = (m_mode == ROTATE_CAMROLL) ? m_outerRadius : m_innerRadius; + m_tempString = AZStd::string::format("[%.2f, %.2f, %.2f]", MCore::Math::RadiansToDegrees(m_rotation.GetX()), MCore::Math::RadiansToDegrees(m_rotation.GetY()), MCore::Math::RadiansToDegrees(m_rotation.GetZ())); //String rotationValues = String() = AZStd::string::format("[%.2f, %.2f, %.2f]", camera->GetPosition().x, camera->GetPosition().y, camera->GetPosition().z); - AZ::Vector3 textPosition = MCore::Project(mPosition + (upVector * (mOuterRadius + mTextDistance)), camera->GetViewProjMatrix(), screenWidth, screenHeight); - renderUtil->RenderText(textPosition.GetX() - 2.9f * mTempString.size(), textPosition.GetY(), mTempString.c_str(), ManipulatorColors::mSelectionColor); + AZ::Vector3 textPosition = MCore::Project(m_position + (upVector * (m_outerRadius + m_textDistance)), camera->GetViewProjMatrix(), screenWidth, screenHeight); + renderUtil->RenderText(textPosition.GetX() - 2.9f * m_tempString.size(), textPosition.GetY(), m_tempString.c_str(), ManipulatorColors::s_selectionColor); // mark the click position with a small cube - AZ::Vector3 clickPosition = mPosition + mClickPosition * radius; + AZ::Vector3 clickPosition = m_position + m_clickPosition * radius; // calculate the tangent at the click position - MCore::RGBAColor rotDirColorNegative = (mRotation.Dot(mRotationAxis) > 0.0f) ? ManipulatorColors::mSelectionColor : grey; - MCore::RGBAColor rotDirColorPositive = (mRotation.Dot(mRotationAxis) < 0.0f) ? ManipulatorColors::mSelectionColor : grey; + MCore::RGBAColor rotDirColorNegative = (m_rotation.Dot(m_rotationAxis) > 0.0f) ? ManipulatorColors::s_selectionColor : grey; + MCore::RGBAColor rotDirColorPositive = (m_rotation.Dot(m_rotationAxis) < 0.0f) ? ManipulatorColors::s_selectionColor : grey; // render the tangent directions at the click positions - AZ::Vector3 tangent = mRotationAxis.Cross(mClickPosition).GetNormalized(); - renderUtil->RenderLine(clickPosition, clickPosition + 1.5f * mAxisSize * tangent, rotDirColorPositive); - renderUtil->RenderLine(clickPosition, clickPosition - 1.5f * mAxisSize * tangent, rotDirColorNegative); - renderUtil->RenderCylinder(2.0f * mArrowBaseRadius, 0.0f, 0.5f * mAxisSize, clickPosition + 1.5f * mAxisSize * tangent, tangent, rotDirColorPositive); - renderUtil->RenderCylinder(2.0f * mArrowBaseRadius, 0.0f, 0.5f * mAxisSize, clickPosition - 1.5f * mAxisSize * tangent, -tangent, rotDirColorNegative); + AZ::Vector3 tangent = m_rotationAxis.Cross(m_clickPosition).GetNormalized(); + renderUtil->RenderLine(clickPosition, clickPosition + 1.5f * m_axisSize * tangent, rotDirColorPositive); + renderUtil->RenderLine(clickPosition, clickPosition - 1.5f * m_axisSize * tangent, rotDirColorNegative); + renderUtil->RenderCylinder(2.0f * m_arrowBaseRadius, 0.0f, 0.5f * m_axisSize, clickPosition + 1.5f * m_axisSize * tangent, tangent, rotDirColorPositive); + renderUtil->RenderCylinder(2.0f * m_arrowBaseRadius, 0.0f, 0.5f * m_axisSize, clickPosition - 1.5f * m_axisSize * tangent, -tangent, rotDirColorNegative); } else { - if (mName.size() > 0) + if (m_name.size() > 0) { - AZ::Vector3 textPosition = MCore::Project(mPosition + (upVector * (mOuterRadius + mTextDistance)), camera->GetViewProjMatrix(), screenWidth, screenHeight); - renderUtil->RenderText(textPosition.GetX(), textPosition.GetY(), mName.c_str(), ManipulatorColors::mSelectionColor, 11.0f, true); + AZ::Vector3 textPosition = MCore::Project(m_position + (upVector * (m_outerRadius + m_textDistance)), camera->GetViewProjMatrix(), screenWidth, screenHeight); + renderUtil->RenderText(textPosition.GetX(), textPosition.GetY(), m_name.c_str(), ManipulatorColors::s_selectionColor, 11.0f, true); } } } @@ -399,7 +375,7 @@ namespace MCommon MCORE_UNUSED(middleButtonPressed); // check if camera has been set - if (camera == nullptr || mIsVisible == false || (leftButtonPressed && rightButtonPressed)) + if (camera == nullptr || m_isVisible == false || (leftButtonPressed && rightButtonPressed)) { return; } @@ -407,7 +383,7 @@ namespace MCommon // update the axis visibility flags UpdateAxisDirections(camera); - // get screen mSize + // get screen m_size uint32 screenWidth = camera->GetScreenWidth(); uint32 screenHeight = camera->GetScreenHeight(); @@ -416,15 +392,15 @@ namespace MCommon //MCore::Ray mousePrevPosRay = camera->Unproject( mousePosX-mouseMovementX, mousePosY-mouseMovementY ); MCore::Ray camRollRay = camera->Unproject(screenWidth / 2, screenHeight / 2); AZ::Vector3 camRollAxis = camRollRay.GetDirection(); - mRotationQuat = AZ::Quaternion::CreateIdentity(); + m_rotationQuat = AZ::Quaternion::CreateIdentity(); // check for the selected axis/plane - if (mSelectionLocked == false || mMode == ROTATE_NONE) + if (m_selectionLocked == false || m_mode == ROTATE_NONE) { // update old rotation of the callback - if (mCallback) + if (m_callback) { - mCallback->UpdateOldValues(); + m_callback->UpdateOldValues(); } // the intersection variables @@ -432,88 +408,88 @@ namespace MCommon // set rotation mode to rotation around the x axis, if the following intersection conditions are fulfilled // innerAABB not hit, outerAABB hit, innerBoundingSphere hit and angle between cameraRollAxis and clickPosition > pi/2 - if ((mousePosRay.Intersects(mXAxisInnerAABB) == false || - (camera->GetProjectionMode() == MCommon::Camera::PROJMODE_ORTHOGRAPHIC && mXAxisVisible)) && - mousePosRay.Intersects(mXAxisAABB, &intersectA, &intersectB) && - mousePosRay.Intersects(mInnerBoundingSphere) && - MCore::Math::ACos(camRollAxis.Dot((intersectA - mPosition).GetNormalized())) > MCore::Math::halfPi) + if ((mousePosRay.Intersects(m_xAxisInnerAabb) == false || + (camera->GetProjectionMode() == MCommon::Camera::PROJMODE_ORTHOGRAPHIC && m_xAxisVisible)) && + mousePosRay.Intersects(m_xAxisAabb, &intersectA, &intersectB) && + mousePosRay.Intersects(m_innerBoundingSphere) && + MCore::Math::ACos(camRollAxis.Dot((intersectA - m_position).GetNormalized())) > MCore::Math::halfPi) { - mMode = ROTATE_X; - mRotationAxis = AZ::Vector3(1.0f, 0.0f, 0.0f); - mClickPosition = (intersectA - mPosition).GetNormalized(); - mClickPosition.SetX(0.0f); + m_mode = ROTATE_X; + m_rotationAxis = AZ::Vector3(1.0f, 0.0f, 0.0f); + m_clickPosition = (intersectA - m_position).GetNormalized(); + m_clickPosition.SetX(0.0f); } // set rotation mode to rotation around the y axis, if the following intersection conditions are fulfilled // innerAABB not hit, outerAABB hit, innerBoundingSphere hit and angle between cameraRollAxis and clickPosition > pi/2 - else if ((mousePosRay.Intersects(mYAxisInnerAABB) == false || - (camera->GetProjectionMode() == MCommon::Camera::PROJMODE_ORTHOGRAPHIC && mYAxisVisible)) && - mousePosRay.Intersects(mYAxisAABB, &intersectA, &intersectB) && mousePosRay.Intersects(mInnerBoundingSphere) && - MCore::Math::ACos(camRollAxis.Dot((intersectA - mPosition).GetNormalized())) > MCore::Math::halfPi) + else if ((mousePosRay.Intersects(m_yAxisInnerAabb) == false || + (camera->GetProjectionMode() == MCommon::Camera::PROJMODE_ORTHOGRAPHIC && m_yAxisVisible)) && + mousePosRay.Intersects(m_yAxisAabb, &intersectA, &intersectB) && mousePosRay.Intersects(m_innerBoundingSphere) && + MCore::Math::ACos(camRollAxis.Dot((intersectA - m_position).GetNormalized())) > MCore::Math::halfPi) { - mMode = ROTATE_Y; - mRotationAxis = AZ::Vector3(0.0f, 1.0f, 0.0f); - mClickPosition = (intersectA - mPosition).GetNormalized(); - mClickPosition.SetY(0.0f); + m_mode = ROTATE_Y; + m_rotationAxis = AZ::Vector3(0.0f, 1.0f, 0.0f); + m_clickPosition = (intersectA - m_position).GetNormalized(); + m_clickPosition.SetY(0.0f); } // set rotation mode to rotation around the z axis, if the following intersection conditions are fulfilled // innerAABB not hit, outerAABB hit, innerBoundingSphere hit and angle between cameraRollAxis and clickPosition > pi/2 - else if ((mousePosRay.Intersects(mZAxisInnerAABB) == false || - (camera->GetProjectionMode() == MCommon::Camera::PROJMODE_ORTHOGRAPHIC && mZAxisVisible)) && - mousePosRay.Intersects(mZAxisAABB, &intersectA, &intersectB) && mousePosRay.Intersects(mInnerBoundingSphere) && - MCore::Math::ACos(camRollAxis.Dot((intersectA - mPosition).GetNormalized())) > MCore::Math::halfPi) + else if ((mousePosRay.Intersects(m_zAxisInnerAabb) == false || + (camera->GetProjectionMode() == MCommon::Camera::PROJMODE_ORTHOGRAPHIC && m_zAxisVisible)) && + mousePosRay.Intersects(m_zAxisAabb, &intersectA, &intersectB) && mousePosRay.Intersects(m_innerBoundingSphere) && + MCore::Math::ACos(camRollAxis.Dot((intersectA - m_position).GetNormalized())) > MCore::Math::halfPi) { - mMode = ROTATE_Z; - mRotationAxis = AZ::Vector3(0.0f, 0.0f, 1.0f); - mClickPosition = (intersectA - mPosition).GetNormalized(); - mClickPosition.SetZ(0.0f); + m_mode = ROTATE_Z; + m_rotationAxis = AZ::Vector3(0.0f, 0.0f, 1.0f); + m_clickPosition = (intersectA - m_position).GetNormalized(); + m_clickPosition.SetZ(0.0f); } // set rotation mode to rotation around the pitch and yaw axis of the camera, // if the inner sphere is hit and none of the previous conditions was fulfilled - else if (mousePosRay.Intersects(mInnerBoundingSphere, &intersectA, &intersectB)) + else if (mousePosRay.Intersects(m_innerBoundingSphere, &intersectA, &intersectB)) { - mMode = ROTATE_CAMPITCHYAW; + m_mode = ROTATE_CAMPITCHYAW; // set the rotation axis to zero, because no single axis exists in this mode - mRotationAxis = AZ::Vector3::CreateZero(); + m_rotationAxis = AZ::Vector3::CreateZero(); // project the click position onto the plane which is perpendicular to the rotation direction - MCore::PlaneEq rotationPlane(camRollAxis, mPosition); - mClickPosition = (rotationPlane.Project(intersectA - mPosition)).GetNormalized(); + MCore::PlaneEq rotationPlane(camRollAxis, m_position); + m_clickPosition = (rotationPlane.Project(intersectA - m_position)).GetNormalized(); } // set rotation mode to rotation around the roll axis of the camera, // if the outer sphere is hit and none of the previous conditions was fulfilled - else if (mousePosRay.Intersects(mOuterBoundingSphere, &intersectA, &intersectB)) + else if (mousePosRay.Intersects(m_outerBoundingSphere, &intersectA, &intersectB)) { // set rotation mode to rotate around the view axis - mMode = ROTATE_CAMROLL; + m_mode = ROTATE_CAMROLL; // set the rotation axis to the look at ray direction - mRotationAxis = camRollRay.GetDirection(); + m_rotationAxis = camRollRay.GetDirection(); // project the click position onto the plane which is perpendicular to the rotation direction - MCore::PlaneEq rotationPlane(mRotationAxis, AZ::Vector3::CreateZero()); - mClickPosition = (rotationPlane.Project(intersectA - mPosition)).GetNormalized(); + MCore::PlaneEq rotationPlane(m_rotationAxis, AZ::Vector3::CreateZero()); + m_clickPosition = (rotationPlane.Project(intersectA - m_position)).GetNormalized(); } // no bounding volume is currently hit, therefore do not rotate else { - mMode = ROTATE_NONE; + m_mode = ROTATE_NONE; } } // set selection lock and current projection mode - mSelectionLocked = leftButtonPressed; - mCurrentProjectionMode = camera->GetProjectionMode(); + m_selectionLocked = leftButtonPressed; + m_currentProjectionMode = camera->GetProjectionMode(); // reset the gizmo if no rotation mode is selected - if (mSelectionLocked == false || mMode == ROTATE_NONE) + if (m_selectionLocked == false || m_mode == ROTATE_NONE) { - mRotation = AZ::Vector3::CreateZero(); + m_rotation = AZ::Vector3::CreateZero(); return; } @@ -527,13 +503,13 @@ namespace MCommon } // set the rotation depending on the rotation mode - if (mMode == ROTATE_CAMPITCHYAW) + if (m_mode == ROTATE_CAMPITCHYAW) { // the yaw axis of the camera view MCore::Ray camYawRay = camera->Unproject(screenWidth / 2, screenHeight / 2 - 10); // calculate the plane perpendicular to the view rotation axis - MCore::PlaneEq rotationPlane(camRollAxis, mPosition); + MCore::PlaneEq rotationPlane(camRollAxis, m_position); // get the intersection points of the rays and the plane AZ::Vector3 originRayIntersect, upVecRayIntersect; @@ -548,69 +524,46 @@ namespace MCommon // calculate the projected axes, used to determine the angle between click position // and the axes. This allows weighting the angles by the movement direction. - AZ::Vector3 projectedCenter = MCore::Project(mPosition, camera->GetViewProjMatrix(), screenWidth, screenHeight); - AZ::Vector3 projectedClickPosYaw = MCore::Project(mPosition - leftVector, camera->GetViewProjMatrix(), screenWidth, screenHeight); - AZ::Vector3 projectedClickPosPitch = MCore::Project(mPosition - upVector, camera->GetViewProjMatrix(), screenWidth, screenHeight); + AZ::Vector3 projectedCenter = MCore::Project(m_position, camera->GetViewProjMatrix(), screenWidth, screenHeight); + AZ::Vector3 projectedClickPosYaw = MCore::Project(m_position - leftVector, camera->GetViewProjMatrix(), screenWidth, screenHeight); + AZ::Vector3 projectedClickPosPitch = MCore::Project(m_position - upVector, camera->GetViewProjMatrix(), screenWidth, screenHeight); AZ::Vector3 projDirClickPosYaw = (projectedClickPosYaw - projectedCenter).GetNormalized(); AZ::Vector3 projDirClickPosPitch = (projectedClickPosPitch - projectedCenter).GetNormalized(); // calculate the angle between mouse movement and projected rotation axis - float angleYaw = projDirClickPosYaw.Dot(mouseMovementV3) * mScalingFactor * movementLength * 0.00005f; - float anglePitch = projDirClickPosPitch.Dot(mouseMovementV3) * mScalingFactor * movementLength * 0.00005f; + float angleYaw = projDirClickPosYaw.Dot(mouseMovementV3) * m_scalingFactor * movementLength * 0.00005f; + float anglePitch = projDirClickPosPitch.Dot(mouseMovementV3) * m_scalingFactor * movementLength * 0.00005f; // perform rotation arround the cam yaw and pitch axis AZ::Quaternion rotation = MCore::CreateFromAxisAndAngle(upVector, -angleYaw); rotation = rotation * MCore::CreateFromAxisAndAngle(leftVector, anglePitch); // set euler angles of the rotation variable - mRotation += MCore::AzQuaternionToEulerAngles(rotation); - mRotationQuat = rotation; + m_rotation += MCore::AzQuaternionToEulerAngles(rotation); + m_rotationQuat = rotation; } else { - /* - // HINT: uncommented stuff is the exact rotation, used in maya - // generate current translation plane and calculate mouse intersections - MCore::PlaneEq movementPlane( mRotationAxis, mPosition ); - Vector3 mousePosIntersect, mousePrevPosIntersect; - mousePosRay.Intersects( movementPlane, &mousePosIntersect ); - mousePrevPosRay.Intersects( movementPlane, &mousePrevPosIntersect ); - - // normalize the intersection points, as only the angle between them is needed - mousePosIntersect = (mousePosIntersect - mPosition).Normalize(); - mousePrevPosIntersect = (mousePrevPosIntersect - mPosition).Normalize(); - - // distance of the mouse intersections is the actual movement on the plane - float angleSign = MCore::Sgn((mRotationAxis.Cross(mousePosIntersect-mousePrevPosIntersect)).Dot(mousePosIntersect)); - float angle = MCore::Math::ACos( (mousePrevPosIntersect).Dot((mousePosIntersect)) ) * angleSign; - - mRotation += mRotationAxis * angle; - mRotation = Vector3( MCore::Clamp(mRotation.x, -Math::twoPi, Math::twoPi), MCore::Clamp(mRotation.y, -Math::twoPi, Math::twoPi), MCore::Clamp(mRotation.z, -Math::twoPi, Math::twoPi) ); - mRotationQuat = Quaternion( mRotationAxis, MCore::Clamp(-angle, -Math::twoPi, Math::twoPi) ); - */ // calculate the projected center and click position to determine the rotation angle - AZ::Vector3 tangent = (mRotationAxis.Cross(mClickPosition)).GetNormalized(); - AZ::Vector3 projectedCenter = MCore::Project(mPosition, camera->GetViewProjMatrix(), screenWidth, screenHeight); - AZ::Vector3 projectedClickPos = MCore::Project(mPosition - tangent, camera->GetViewProjMatrix(), screenWidth, screenHeight); + AZ::Vector3 tangent = (m_rotationAxis.Cross(m_clickPosition)).GetNormalized(); + AZ::Vector3 projectedCenter = MCore::Project(m_position, camera->GetViewProjMatrix(), screenWidth, screenHeight); + AZ::Vector3 projectedClickPos = MCore::Project(m_position - tangent, camera->GetViewProjMatrix(), screenWidth, screenHeight); AZ::Vector3 projDirClickPos = (projectedClickPos - projectedCenter); - // calculate the angle between mouse movement and projected rotation axis - //float angle = Math::DegreesToRadians(Math::Floor(Math::RadiansToDegrees((projDirClickPos.Dot( mouseMovementV3 ) * mScalingFactor * 0.00002f) * movementLength))); float angle = MCore::Math::DegreesToRadians(MCore::Sgn(projDirClickPos.Dot(mouseMovementV3)) * 0.2f * MCore::Math::Floor(movementLength + 0.5f)); // adjust rotation - mRotation += mRotationAxis * angle; - //mRotation = Vector3( MCore::Clamp(mRotation.x, -Math::twoPi, Math::twoPi), MCore::Clamp(mRotation.y, -Math::twoPi, Math::twoPi), MCore::Clamp(mRotation.z, -Math::twoPi, Math::twoPi) ); - mRotationQuat = AZ::Quaternion::CreateFromAxisAngle(mRotationAxis, MCore::Math::FMod(-angle, MCore::Math::twoPi)); - mRotationQuat.Normalize(); + m_rotation += m_rotationAxis * angle; + m_rotationQuat = AZ::Quaternion::CreateFromAxisAngle(m_rotationAxis, MCore::Math::FMod(-angle, MCore::Math::twoPi)); + m_rotationQuat.Normalize(); } // update the callback - if (mCallback) + if (m_callback) { - const AZ::Quaternion curRot = mCallback->GetCurrValueQuat(); - const AZ::Quaternion newRot = (curRot * mRotationQuat).GetNormalized(); - mCallback->Update(newRot); + const AZ::Quaternion curRot = m_callback->GetCurrValueQuat(); + const AZ::Quaternion newRot = (curRot * m_rotationQuat).GetNormalized(); + m_callback->Update(newRot); } } } // namespace MCommon diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RotateManipulator.h b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RotateManipulator.h index 5443bad219..4a664b1526 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RotateManipulator.h +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RotateManipulator.h @@ -88,40 +88,40 @@ namespace MCommon void ProcessMouseInput(MCommon::Camera* camera, int32 mousePosX, int32 mousePosY, int32 mouseMovementX, int32 mouseMovementY, bool leftButtonPressed, bool middleButtonPressed, bool rightButtonPressed, uint32 keyboardKeyFlags = 0); protected: - AZ::Vector3 mRotation; - AZ::Quaternion mRotationQuat; - AZ::Vector3 mRotationAxis; - AZ::Vector3 mClickPosition; + AZ::Vector3 m_rotation; + AZ::Quaternion m_rotationQuat; + AZ::Vector3 m_rotationAxis; + AZ::Vector3 m_clickPosition; // bounding volumes for the axes - MCore::BoundingSphere mInnerBoundingSphere; - MCore::BoundingSphere mOuterBoundingSphere; - MCore::AABB mXAxisAABB; - MCore::AABB mYAxisAABB; - MCore::AABB mZAxisAABB; - MCore::AABB mXAxisInnerAABB; - MCore::AABB mYAxisInnerAABB; - MCore::AABB mZAxisInnerAABB; + MCore::BoundingSphere m_innerBoundingSphere; + MCore::BoundingSphere m_outerBoundingSphere; + MCore::AABB m_xAxisAabb; + MCore::AABB m_yAxisAabb; + MCore::AABB m_zAxisAabb; + MCore::AABB m_xAxisInnerAabb; + MCore::AABB m_yAxisInnerAabb; + MCore::AABB m_zAxisInnerAabb; // the proportions of the rotation manipulator - float mSize; - float mInnerRadius; - float mOuterRadius; - float mArrowBaseRadius; - float mAABBWidth; - float mAxisSize; - float mTextDistance; - float mInnerQuadSize; + float m_size; + float m_innerRadius; + float m_outerRadius; + float m_arrowBaseRadius; + float m_aabbWidth; + float m_axisSize; + float m_textDistance; + float m_innerQuadSize; // orientation information - float mSignX; - float mSignY; - float mSignZ; - bool mXAxisVisible; - bool mYAxisVisible; - bool mZAxisVisible; + float m_signX; + float m_signY; + float m_signZ; + bool m_xAxisVisible; + bool m_yAxisVisible; + bool m_zAxisVisible; // store the projection mode of the current render widget - MCommon::Camera::ProjectionMode mCurrentProjectionMode; + MCommon::Camera::ProjectionMode m_currentProjectionMode; }; } // namespace MCommon diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/ScaleManipulator.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/ScaleManipulator.cpp index 65915aec65..a1bb69110d 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/ScaleManipulator.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/ScaleManipulator.cpp @@ -16,12 +16,12 @@ namespace MCommon : TransformationManipulator(scalingFactor, isVisible) { // set the initial values - mMode = SCALE_NONE; - mSelectionLocked = false; - mCallback = nullptr; - mPosition = AZ::Vector3::CreateZero(); - mScaleDirection = AZ::Vector3::CreateZero(); - mScale = AZ::Vector3::CreateZero(); + m_mode = SCALE_NONE; + m_selectionLocked = false; + m_callback = nullptr; + m_position = AZ::Vector3::CreateZero(); + m_scaleDirection = AZ::Vector3::CreateZero(); + m_scale = AZ::Vector3::CreateZero(); } @@ -40,35 +40,35 @@ namespace MCommon UpdateAxisDirections(camera); } - mSize = mScalingFactor; - mScaledSize = AZ::Vector3(mSize, mSize, mSize) + AZ::Vector3(MCore::Max(float(mScale.GetX()), -mSize), MCore::Max(float(mScale.GetY()), -mSize), MCore::Max(float(mScale.GetZ()), -mSize)); - mDiagScale = 0.5f; - mArrowLength = mSize / 10.0f; - mBaseRadius = mSize / 15.0f; + m_size = m_scalingFactor; + m_scaledSize = AZ::Vector3(m_size, m_size, m_size) + AZ::Vector3(MCore::Max(float(m_scale.GetX()), -m_size), MCore::Max(float(m_scale.GetY()), -m_size), MCore::Max(float(m_scale.GetZ()), -m_size)); + m_diagScale = 0.5f; + m_arrowLength = m_size / 10.0f; + m_baseRadius = m_size / 15.0f; // positions for the plane selectors - mFirstPlaneSelectorPos = mScaledSize * 0.3f; - mSecPlaneSelectorPos = mScaledSize * 0.6f; + m_firstPlaneSelectorPos = m_scaledSize * 0.3f; + m_secPlaneSelectorPos = m_scaledSize * 0.6f; // set the bounding volumes of the axes selection - mXAxisAABB.SetMax(mPosition + mSignX * AZ::Vector3(mScaledSize.GetX() + mArrowLength, mBaseRadius, mBaseRadius)); - mXAxisAABB.SetMin(mPosition - mSignX * AZ::Vector3(mBaseRadius, mBaseRadius, mBaseRadius)); - mYAxisAABB.SetMax(mPosition + mSignY * AZ::Vector3(mBaseRadius, mScaledSize.GetY() + mArrowLength, mBaseRadius)); - mYAxisAABB.SetMin(mPosition - mSignY * AZ::Vector3(mBaseRadius, mBaseRadius, mBaseRadius)); - mZAxisAABB.SetMax(mPosition + mSignZ * AZ::Vector3(mBaseRadius, mBaseRadius, mScaledSize.GetZ() + mArrowLength)); - mZAxisAABB.SetMin(mPosition - mSignZ * AZ::Vector3(mBaseRadius, mBaseRadius, mBaseRadius)); + m_xAxisAabb.SetMax(m_position + m_signX * AZ::Vector3(m_scaledSize.GetX() + m_arrowLength, m_baseRadius, m_baseRadius)); + m_xAxisAabb.SetMin(m_position - m_signX * AZ::Vector3(m_baseRadius, m_baseRadius, m_baseRadius)); + m_yAxisAabb.SetMax(m_position + m_signY * AZ::Vector3(m_baseRadius, m_scaledSize.GetY() + m_arrowLength, m_baseRadius)); + m_yAxisAabb.SetMin(m_position - m_signY * AZ::Vector3(m_baseRadius, m_baseRadius, m_baseRadius)); + m_zAxisAabb.SetMax(m_position + m_signZ * AZ::Vector3(m_baseRadius, m_baseRadius, m_scaledSize.GetZ() + m_arrowLength)); + m_zAxisAabb.SetMin(m_position - m_signZ * AZ::Vector3(m_baseRadius, m_baseRadius, m_baseRadius)); // set bounding volumes for the plane selectors - mXYPlaneAABB.SetMax(mPosition + AZ::Vector3(mSecPlaneSelectorPos.GetX() * mSignX, mSecPlaneSelectorPos.GetY() * mSignY, mBaseRadius * mSignZ)); - mXYPlaneAABB.SetMin(mPosition + 0.3f * AZ::Vector3(mSecPlaneSelectorPos.GetX() * mSignX, mSecPlaneSelectorPos.GetY() * mSignY, 0) - AZ::Vector3(mBaseRadius * mSignX, mBaseRadius * mSignY, mBaseRadius * mSignZ)); - mXZPlaneAABB.SetMax(mPosition + AZ::Vector3(mSecPlaneSelectorPos.GetX() * mSignX, mBaseRadius * mSignY, mSecPlaneSelectorPos.GetZ() * mSignZ)); - mXZPlaneAABB.SetMin(mPosition + 0.3f * AZ::Vector3(mSecPlaneSelectorPos.GetX() * mSignX, 0, mSecPlaneSelectorPos.GetZ() * mSignZ) - AZ::Vector3(mBaseRadius * mSignX, mBaseRadius * mSignY, mBaseRadius * mSignZ)); - mYZPlaneAABB.SetMax(mPosition + AZ::Vector3(mBaseRadius * mSignX, mSecPlaneSelectorPos.GetY() * mSignY, mSecPlaneSelectorPos.GetZ() * mSignZ)); - mYZPlaneAABB.SetMin(mPosition + 0.3f * AZ::Vector3(0, mSecPlaneSelectorPos.GetY() * mSignY, mSecPlaneSelectorPos.GetZ() * mSignZ) - AZ::Vector3(mBaseRadius * mSignX, mBaseRadius * mSignY, mBaseRadius * mSignZ)); + m_xyPlaneAabb.SetMax(m_position + AZ::Vector3(m_secPlaneSelectorPos.GetX() * m_signX, m_secPlaneSelectorPos.GetY() * m_signY, m_baseRadius * m_signZ)); + m_xyPlaneAabb.SetMin(m_position + 0.3f * AZ::Vector3(m_secPlaneSelectorPos.GetX() * m_signX, m_secPlaneSelectorPos.GetY() * m_signY, 0) - AZ::Vector3(m_baseRadius * m_signX, m_baseRadius * m_signY, m_baseRadius * m_signZ)); + m_xzPlaneAabb.SetMax(m_position + AZ::Vector3(m_secPlaneSelectorPos.GetX() * m_signX, m_baseRadius * m_signY, m_secPlaneSelectorPos.GetZ() * m_signZ)); + m_xzPlaneAabb.SetMin(m_position + 0.3f * AZ::Vector3(m_secPlaneSelectorPos.GetX() * m_signX, 0, m_secPlaneSelectorPos.GetZ() * m_signZ) - AZ::Vector3(m_baseRadius * m_signX, m_baseRadius * m_signY, m_baseRadius * m_signZ)); + m_yzPlaneAabb.SetMax(m_position + AZ::Vector3(m_baseRadius * m_signX, m_secPlaneSelectorPos.GetY() * m_signY, m_secPlaneSelectorPos.GetZ() * m_signZ)); + m_yzPlaneAabb.SetMin(m_position + 0.3f * AZ::Vector3(0, m_secPlaneSelectorPos.GetY() * m_signY, m_secPlaneSelectorPos.GetZ() * m_signZ) - AZ::Vector3(m_baseRadius * m_signX, m_baseRadius * m_signY, m_baseRadius * m_signZ)); // set bounding volume for the box selector - mXYZBoxAABB.SetMin(mPosition - AZ::Vector3(mBaseRadius * mSignX, mBaseRadius * mSignY, mBaseRadius * mSignZ)); - mXYZBoxAABB.SetMax(mPosition + mDiagScale * AZ::Vector3(mFirstPlaneSelectorPos.GetX() * mSignX, mFirstPlaneSelectorPos.GetY() * mSignY, mFirstPlaneSelectorPos.GetZ() * mSignZ)); + m_xyzBoxAabb.SetMin(m_position - AZ::Vector3(m_baseRadius * m_signX, m_baseRadius * m_signY, m_baseRadius * m_signZ)); + m_xyzBoxAabb.SetMax(m_position + m_diagScale * AZ::Vector3(m_firstPlaneSelectorPos.GetX() * m_signX, m_firstPlaneSelectorPos.GetY() * m_signY, m_firstPlaneSelectorPos.GetZ() * m_signZ)); } @@ -89,14 +89,14 @@ namespace MCommon MCore::Ray camRay = camera->Unproject(screenWidth / 2, screenHeight / 2); AZ::Vector3 camDir = camRay.GetDirection(); - mSignX = (MCore::Math::ACos(camDir.Dot(AZ::Vector3(1.0f, 0.0f, 0.0f))) >= MCore::Math::halfPi - MCore::Math::epsilon) ? 1.0f : -1.0f; - mSignY = (MCore::Math::ACos(camDir.Dot(AZ::Vector3(0.0f, 1.0f, 0.0f))) >= MCore::Math::halfPi - MCore::Math::epsilon) ? 1.0f : -1.0f; - mSignZ = (MCore::Math::ACos(camDir.Dot(AZ::Vector3(0.0f, 0.0f, 1.0f))) >= MCore::Math::halfPi - MCore::Math::epsilon) ? 1.0f : -1.0f; + m_signX = (MCore::Math::ACos(camDir.Dot(AZ::Vector3(1.0f, 0.0f, 0.0f))) >= MCore::Math::halfPi - MCore::Math::epsilon) ? 1.0f : -1.0f; + m_signY = (MCore::Math::ACos(camDir.Dot(AZ::Vector3(0.0f, 1.0f, 0.0f))) >= MCore::Math::halfPi - MCore::Math::epsilon) ? 1.0f : -1.0f; + m_signZ = (MCore::Math::ACos(camDir.Dot(AZ::Vector3(0.0f, 0.0f, 1.0f))) >= MCore::Math::halfPi - MCore::Math::epsilon) ? 1.0f : -1.0f; // determine the axis visibility, to disable movement for invisible axes - mXAxisVisible = (MCore::InRange(MCore::Math::Abs(camDir.Dot(AZ::Vector3(1.0f, 0.0f, 0.0f))) - 1.0f, -MCore::Math::epsilon, MCore::Math::epsilon) == false); - mYAxisVisible = (MCore::InRange(MCore::Math::Abs(camDir.Dot(AZ::Vector3(0.0f, 1.0f, 0.0f))) - 1.0f, -MCore::Math::epsilon, MCore::Math::epsilon) == false); - mZAxisVisible = (MCore::InRange(MCore::Math::Abs(camDir.Dot(AZ::Vector3(0.0f, 0.0f, 1.0f))) - 1.0f, -MCore::Math::epsilon, MCore::Math::epsilon) == false); + m_xAxisVisible = (MCore::InRange(MCore::Math::Abs(camDir.Dot(AZ::Vector3(1.0f, 0.0f, 0.0f))) - 1.0f, -MCore::Math::epsilon, MCore::Math::epsilon) == false); + m_yAxisVisible = (MCore::InRange(MCore::Math::Abs(camDir.Dot(AZ::Vector3(0.0f, 1.0f, 0.0f))) - 1.0f, -MCore::Math::epsilon, MCore::Math::epsilon) == false); + m_zAxisVisible = (MCore::InRange(MCore::Math::Abs(camDir.Dot(AZ::Vector3(0.0f, 0.0f, 1.0f))) - 1.0f, -MCore::Math::epsilon, MCore::Math::epsilon) == false); } @@ -116,13 +116,13 @@ namespace MCommon MCore::Ray mouseRay = camera->Unproject(mousePosX, mousePosY); // check if one of the AABBs is hit - if (mouseRay.Intersects(mXAxisAABB) || - mouseRay.Intersects(mYAxisAABB) || - mouseRay.Intersects(mZAxisAABB) || - mouseRay.Intersects(mXYPlaneAABB) || - mouseRay.Intersects(mXZPlaneAABB) || - mouseRay.Intersects(mYZPlaneAABB) || - mouseRay.Intersects(mXYZBoxAABB)) + if (mouseRay.Intersects(m_xAxisAabb) || + mouseRay.Intersects(m_yAxisAabb) || + mouseRay.Intersects(m_zAxisAabb) || + mouseRay.Intersects(m_xyPlaneAabb) || + mouseRay.Intersects(m_xzPlaneAabb) || + mouseRay.Intersects(m_yzPlaneAabb) || + mouseRay.Intersects(m_xyzBoxAabb)) { return true; } @@ -136,12 +136,12 @@ namespace MCommon void ScaleManipulator::Render(MCommon::Camera* camera, RenderUtil* renderUtil) { // return if no render util is set - if (renderUtil == nullptr || camera == nullptr || mIsVisible == false) + if (renderUtil == nullptr || camera == nullptr || m_isVisible == false) { return; } - // set mSize variables for the gizmo + // set m_size variables for the gizmo const uint32 screenWidth = camera->GetScreenWidth(); const uint32 screenHeight = camera->GetScreenHeight(); @@ -149,131 +149,131 @@ namespace MCommon UpdateAxisDirections(camera); // set color for the axes, depending on the selection (TODO: maybe put these into the constructor.) - MCore::RGBAColor xAxisColor = (mMode == SCALE_XYZ || mMode == SCALE_X || mMode == SCALE_XY || mMode == SCALE_XZ) ? ManipulatorColors::mSelectionColor : ManipulatorColors::mRed; - MCore::RGBAColor yAxisColor = (mMode == SCALE_XYZ || mMode == SCALE_Y || mMode == SCALE_XY || mMode == SCALE_YZ) ? ManipulatorColors::mSelectionColor : ManipulatorColors::mGreen; - MCore::RGBAColor zAxisColor = (mMode == SCALE_XYZ || mMode == SCALE_Z || mMode == SCALE_XZ || mMode == SCALE_YZ) ? ManipulatorColors::mSelectionColor : ManipulatorColors::mBlue; - MCore::RGBAColor xyPlaneColorX = (mMode == SCALE_XYZ || mMode == SCALE_XY) ? ManipulatorColors::mSelectionColor : ManipulatorColors::mRed; - MCore::RGBAColor xyPlaneColorY = (mMode == SCALE_XYZ || mMode == SCALE_XY) ? ManipulatorColors::mSelectionColor : ManipulatorColors::mGreen; - MCore::RGBAColor xzPlaneColorX = (mMode == SCALE_XYZ || mMode == SCALE_XZ) ? ManipulatorColors::mSelectionColor : ManipulatorColors::mRed; - MCore::RGBAColor xzPlaneColorZ = (mMode == SCALE_XYZ || mMode == SCALE_XZ) ? ManipulatorColors::mSelectionColor : ManipulatorColors::mBlue; - MCore::RGBAColor yzPlaneColorY = (mMode == SCALE_XYZ || mMode == SCALE_YZ) ? ManipulatorColors::mSelectionColor : ManipulatorColors::mGreen; - MCore::RGBAColor yzPlaneColorZ = (mMode == SCALE_XYZ || mMode == SCALE_YZ) ? ManipulatorColors::mSelectionColor : ManipulatorColors::mBlue; + MCore::RGBAColor xAxisColor = (m_mode == SCALE_XYZ || m_mode == SCALE_X || m_mode == SCALE_XY || m_mode == SCALE_XZ) ? ManipulatorColors::s_selectionColor : ManipulatorColors::s_red; + MCore::RGBAColor yAxisColor = (m_mode == SCALE_XYZ || m_mode == SCALE_Y || m_mode == SCALE_XY || m_mode == SCALE_YZ) ? ManipulatorColors::s_selectionColor : ManipulatorColors::s_green; + MCore::RGBAColor zAxisColor = (m_mode == SCALE_XYZ || m_mode == SCALE_Z || m_mode == SCALE_XZ || m_mode == SCALE_YZ) ? ManipulatorColors::s_selectionColor : ManipulatorColors::s_blue; + MCore::RGBAColor xyPlaneColorX = (m_mode == SCALE_XYZ || m_mode == SCALE_XY) ? ManipulatorColors::s_selectionColor : ManipulatorColors::s_red; + MCore::RGBAColor xyPlaneColorY = (m_mode == SCALE_XYZ || m_mode == SCALE_XY) ? ManipulatorColors::s_selectionColor : ManipulatorColors::s_green; + MCore::RGBAColor xzPlaneColorX = (m_mode == SCALE_XYZ || m_mode == SCALE_XZ) ? ManipulatorColors::s_selectionColor : ManipulatorColors::s_red; + MCore::RGBAColor xzPlaneColorZ = (m_mode == SCALE_XYZ || m_mode == SCALE_XZ) ? ManipulatorColors::s_selectionColor : ManipulatorColors::s_blue; + MCore::RGBAColor yzPlaneColorY = (m_mode == SCALE_XYZ || m_mode == SCALE_YZ) ? ManipulatorColors::s_selectionColor : ManipulatorColors::s_green; + MCore::RGBAColor yzPlaneColorZ = (m_mode == SCALE_XYZ || m_mode == SCALE_YZ) ? ManipulatorColors::s_selectionColor : ManipulatorColors::s_blue; // the x axis with cube at the line end - AZ::Vector3 firstPlanePosX = mPosition + mSignX * AZ::Vector3(mFirstPlaneSelectorPos.GetX(), 0.0f, 0.0f); - AZ::Vector3 secPlanePosX = mPosition + mSignX * AZ::Vector3(mSecPlaneSelectorPos.GetX(), 0.0f, 0.0f); - if (mXAxisVisible) + AZ::Vector3 firstPlanePosX = m_position + m_signX * AZ::Vector3(m_firstPlaneSelectorPos.GetX(), 0.0f, 0.0f); + AZ::Vector3 secPlanePosX = m_position + m_signX * AZ::Vector3(m_secPlaneSelectorPos.GetX(), 0.0f, 0.0f); + if (m_xAxisVisible) { - renderUtil->RenderLine(mPosition, mPosition + mSignX * AZ::Vector3(mScaledSize.GetX() + 0.5f * mBaseRadius, 0.0f, 0.0f), xAxisColor); - AZ::Vector3 quadPos = MCore::Project(mPosition + mSignX * AZ::Vector3(mScaledSize.GetX() + mBaseRadius, 0, 0), camera->GetViewProjMatrix(), screenWidth, screenHeight); - renderUtil->RenderBorderedRect(static_cast(quadPos.GetX() - 2.0f), static_cast(quadPos.GetX() + 3.0f), static_cast(quadPos.GetY() - 2.0f), static_cast(quadPos.GetY() + 3.0f), ManipulatorColors::mRed, ManipulatorColors::mRed); + renderUtil->RenderLine(m_position, m_position + m_signX * AZ::Vector3(m_scaledSize.GetX() + 0.5f * m_baseRadius, 0.0f, 0.0f), xAxisColor); + AZ::Vector3 quadPos = MCore::Project(m_position + m_signX * AZ::Vector3(m_scaledSize.GetX() + m_baseRadius, 0, 0), camera->GetViewProjMatrix(), screenWidth, screenHeight); + renderUtil->RenderBorderedRect(static_cast(quadPos.GetX() - 2.0f), static_cast(quadPos.GetX() + 3.0f), static_cast(quadPos.GetY() - 2.0f), static_cast(quadPos.GetY() + 3.0f), ManipulatorColors::s_red, ManipulatorColors::s_red); // render the plane selector lines - renderUtil->RenderLine(firstPlanePosX, firstPlanePosX + mDiagScale * (AZ::Vector3(0, mFirstPlaneSelectorPos.GetY() * mSignY, 0) - AZ::Vector3(mFirstPlaneSelectorPos.GetX() * mSignX, 0, 0)), xyPlaneColorX); - renderUtil->RenderLine(firstPlanePosX, firstPlanePosX + mDiagScale * (AZ::Vector3(0, 0, mFirstPlaneSelectorPos.GetZ() * mSignZ) - AZ::Vector3(mFirstPlaneSelectorPos.GetX() * mSignX, 0, 0)), xzPlaneColorX); - renderUtil->RenderLine(secPlanePosX, secPlanePosX + mDiagScale * (AZ::Vector3(0, mSecPlaneSelectorPos.GetY() * mSignY, 0) - AZ::Vector3(mSecPlaneSelectorPos.GetX() * mSignX, 0, 0)), xyPlaneColorX); - renderUtil->RenderLine(secPlanePosX, secPlanePosX + mDiagScale * (AZ::Vector3(0, 0, mSecPlaneSelectorPos.GetZ() * mSignZ) - AZ::Vector3(mSecPlaneSelectorPos.GetX() * mSignX, 0, 0)), xzPlaneColorX); + renderUtil->RenderLine(firstPlanePosX, firstPlanePosX + m_diagScale * (AZ::Vector3(0, m_firstPlaneSelectorPos.GetY() * m_signY, 0) - AZ::Vector3(m_firstPlaneSelectorPos.GetX() * m_signX, 0, 0)), xyPlaneColorX); + renderUtil->RenderLine(firstPlanePosX, firstPlanePosX + m_diagScale * (AZ::Vector3(0, 0, m_firstPlaneSelectorPos.GetZ() * m_signZ) - AZ::Vector3(m_firstPlaneSelectorPos.GetX() * m_signX, 0, 0)), xzPlaneColorX); + renderUtil->RenderLine(secPlanePosX, secPlanePosX + m_diagScale * (AZ::Vector3(0, m_secPlaneSelectorPos.GetY() * m_signY, 0) - AZ::Vector3(m_secPlaneSelectorPos.GetX() * m_signX, 0, 0)), xyPlaneColorX); + renderUtil->RenderLine(secPlanePosX, secPlanePosX + m_diagScale * (AZ::Vector3(0, 0, m_secPlaneSelectorPos.GetZ() * m_signZ) - AZ::Vector3(m_secPlaneSelectorPos.GetX() * m_signX, 0, 0)), xzPlaneColorX); } // the y axis with cube at the line end - AZ::Vector3 firstPlanePosY = mPosition + mSignY * AZ::Vector3(0.0f, mFirstPlaneSelectorPos.GetY(), 0.0f); - AZ::Vector3 secPlanePosY = mPosition + mSignY * AZ::Vector3(0.0f, mSecPlaneSelectorPos.GetY(), 0.0f); - if (mYAxisVisible) + AZ::Vector3 firstPlanePosY = m_position + m_signY * AZ::Vector3(0.0f, m_firstPlaneSelectorPos.GetY(), 0.0f); + AZ::Vector3 secPlanePosY = m_position + m_signY * AZ::Vector3(0.0f, m_secPlaneSelectorPos.GetY(), 0.0f); + if (m_yAxisVisible) { - renderUtil->RenderLine(mPosition, mPosition + mSignY * AZ::Vector3(0.0f, mScaledSize.GetY(), 0.0f), yAxisColor); - AZ::Vector3 quadPos = MCore::Project(mPosition + mSignY * AZ::Vector3(0, mScaledSize.GetY() + 0.5f * mBaseRadius, 0), camera->GetViewProjMatrix(), screenWidth, screenHeight); - renderUtil->RenderBorderedRect(static_cast(quadPos.GetX() - 2.0f), static_cast(quadPos.GetX() + 3.0f), static_cast(quadPos.GetY() - 2.0f), static_cast(quadPos.GetY() + 3.0f), ManipulatorColors::mGreen, ManipulatorColors::mGreen); + renderUtil->RenderLine(m_position, m_position + m_signY * AZ::Vector3(0.0f, m_scaledSize.GetY(), 0.0f), yAxisColor); + AZ::Vector3 quadPos = MCore::Project(m_position + m_signY * AZ::Vector3(0, m_scaledSize.GetY() + 0.5f * m_baseRadius, 0), camera->GetViewProjMatrix(), screenWidth, screenHeight); + renderUtil->RenderBorderedRect(static_cast(quadPos.GetX() - 2.0f), static_cast(quadPos.GetX() + 3.0f), static_cast(quadPos.GetY() - 2.0f), static_cast(quadPos.GetY() + 3.0f), ManipulatorColors::s_green, ManipulatorColors::s_green); // render the plane selector lines - renderUtil->RenderLine(firstPlanePosY, firstPlanePosY + mDiagScale * (AZ::Vector3(mFirstPlaneSelectorPos.GetX() * mSignX, 0, 0) - AZ::Vector3(0, mFirstPlaneSelectorPos.GetY() * mSignY, 0)), xyPlaneColorY); - renderUtil->RenderLine(firstPlanePosY, firstPlanePosY + mDiagScale * (AZ::Vector3(0, 0, mFirstPlaneSelectorPos.GetZ() * mSignZ) - AZ::Vector3(0, mFirstPlaneSelectorPos.GetY() * mSignY, 0)), yzPlaneColorY); - renderUtil->RenderLine(secPlanePosY, secPlanePosY + mDiagScale * (AZ::Vector3(mSecPlaneSelectorPos.GetX() * mSignX, 0, 0) - AZ::Vector3(0, mSecPlaneSelectorPos.GetY() * mSignY, 0)), xyPlaneColorY); - renderUtil->RenderLine(secPlanePosY, secPlanePosY + mDiagScale * (AZ::Vector3(0, 0, mSecPlaneSelectorPos.GetZ() * mSignZ) - AZ::Vector3(0, mSecPlaneSelectorPos.GetY() * mSignY, 0)), yzPlaneColorY); + renderUtil->RenderLine(firstPlanePosY, firstPlanePosY + m_diagScale * (AZ::Vector3(m_firstPlaneSelectorPos.GetX() * m_signX, 0, 0) - AZ::Vector3(0, m_firstPlaneSelectorPos.GetY() * m_signY, 0)), xyPlaneColorY); + renderUtil->RenderLine(firstPlanePosY, firstPlanePosY + m_diagScale * (AZ::Vector3(0, 0, m_firstPlaneSelectorPos.GetZ() * m_signZ) - AZ::Vector3(0, m_firstPlaneSelectorPos.GetY() * m_signY, 0)), yzPlaneColorY); + renderUtil->RenderLine(secPlanePosY, secPlanePosY + m_diagScale * (AZ::Vector3(m_secPlaneSelectorPos.GetX() * m_signX, 0, 0) - AZ::Vector3(0, m_secPlaneSelectorPos.GetY() * m_signY, 0)), xyPlaneColorY); + renderUtil->RenderLine(secPlanePosY, secPlanePosY + m_diagScale * (AZ::Vector3(0, 0, m_secPlaneSelectorPos.GetZ() * m_signZ) - AZ::Vector3(0, m_secPlaneSelectorPos.GetY() * m_signY, 0)), yzPlaneColorY); } // the z axis with cube at the line end - AZ::Vector3 firstPlanePosZ = mPosition + mSignZ * AZ::Vector3(0.0f, 0.0f, mFirstPlaneSelectorPos.GetZ()); - AZ::Vector3 secPlanePosZ = mPosition + mSignZ * AZ::Vector3(0.0f, 0.0f, mSecPlaneSelectorPos.GetZ()); - if (mZAxisVisible) + AZ::Vector3 firstPlanePosZ = m_position + m_signZ * AZ::Vector3(0.0f, 0.0f, m_firstPlaneSelectorPos.GetZ()); + AZ::Vector3 secPlanePosZ = m_position + m_signZ * AZ::Vector3(0.0f, 0.0f, m_secPlaneSelectorPos.GetZ()); + if (m_zAxisVisible) { - renderUtil->RenderLine(mPosition, mPosition + mSignZ * AZ::Vector3(0.0f, 0.0f, mScaledSize.GetZ()), zAxisColor); - AZ::Vector3 quadPos = MCore::Project(mPosition + mSignZ * AZ::Vector3(0, 0, mScaledSize.GetZ() + 0.5f * mBaseRadius), camera->GetViewProjMatrix(), screenWidth, screenHeight); - renderUtil->RenderBorderedRect(static_cast(quadPos.GetX() - 2.0f), static_cast(quadPos.GetX() + 3.0f), static_cast(quadPos.GetY() - 2.0f), static_cast(quadPos.GetY() + 3.0f), ManipulatorColors::mBlue, ManipulatorColors::mBlue); + renderUtil->RenderLine(m_position, m_position + m_signZ * AZ::Vector3(0.0f, 0.0f, m_scaledSize.GetZ()), zAxisColor); + AZ::Vector3 quadPos = MCore::Project(m_position + m_signZ * AZ::Vector3(0, 0, m_scaledSize.GetZ() + 0.5f * m_baseRadius), camera->GetViewProjMatrix(), screenWidth, screenHeight); + renderUtil->RenderBorderedRect(static_cast(quadPos.GetX() - 2.0f), static_cast(quadPos.GetX() + 3.0f), static_cast(quadPos.GetY() - 2.0f), static_cast(quadPos.GetY() + 3.0f), ManipulatorColors::s_blue, ManipulatorColors::s_blue); // render the plane selector lines - renderUtil->RenderLine(firstPlanePosZ, firstPlanePosZ + mDiagScale * (AZ::Vector3(mFirstPlaneSelectorPos.GetX() * mSignX, 0, 0) - AZ::Vector3(0, 0, mFirstPlaneSelectorPos.GetZ() * mSignZ)), xzPlaneColorZ); - renderUtil->RenderLine(firstPlanePosZ, firstPlanePosZ + mDiagScale * (AZ::Vector3(0, mFirstPlaneSelectorPos.GetY() * mSignY, 0) - AZ::Vector3(0, 0, mFirstPlaneSelectorPos.GetZ() * mSignZ)), yzPlaneColorZ); - renderUtil->RenderLine(secPlanePosZ, secPlanePosZ + mDiagScale * (AZ::Vector3(mSecPlaneSelectorPos.GetX() * mSignX, 0, 0) - AZ::Vector3(0, 0, mSecPlaneSelectorPos.GetZ() * mSignZ)), xzPlaneColorZ); - renderUtil->RenderLine(secPlanePosZ, secPlanePosZ + mDiagScale * (AZ::Vector3(0, mSecPlaneSelectorPos.GetY() * mSignY, 0) - AZ::Vector3(0, 0, mSecPlaneSelectorPos.GetZ() * mSignZ)), yzPlaneColorZ); + renderUtil->RenderLine(firstPlanePosZ, firstPlanePosZ + m_diagScale * (AZ::Vector3(m_firstPlaneSelectorPos.GetX() * m_signX, 0, 0) - AZ::Vector3(0, 0, m_firstPlaneSelectorPos.GetZ() * m_signZ)), xzPlaneColorZ); + renderUtil->RenderLine(firstPlanePosZ, firstPlanePosZ + m_diagScale * (AZ::Vector3(0, m_firstPlaneSelectorPos.GetY() * m_signY, 0) - AZ::Vector3(0, 0, m_firstPlaneSelectorPos.GetZ() * m_signZ)), yzPlaneColorZ); + renderUtil->RenderLine(secPlanePosZ, secPlanePosZ + m_diagScale * (AZ::Vector3(m_secPlaneSelectorPos.GetX() * m_signX, 0, 0) - AZ::Vector3(0, 0, m_secPlaneSelectorPos.GetZ() * m_signZ)), xzPlaneColorZ); + renderUtil->RenderLine(secPlanePosZ, secPlanePosZ + m_diagScale * (AZ::Vector3(0, m_secPlaneSelectorPos.GetY() * m_signY, 0) - AZ::Vector3(0, 0, m_secPlaneSelectorPos.GetZ() * m_signZ)), yzPlaneColorZ); } // calculate projected positions for the axis labels and render the text - AZ::Vector3 textPosY = MCore::Project(mPosition + mSignY * AZ::Vector3(0.0, mScaledSize.GetY() + mArrowLength + mBaseRadius, -mBaseRadius), camera->GetViewProjMatrix(), screenWidth, screenHeight); - AZ::Vector3 textPosX = MCore::Project(mPosition + mSignX * AZ::Vector3(mScaledSize.GetX() + mArrowLength + mBaseRadius, -mBaseRadius, 0.0), camera->GetViewProjMatrix(), screenWidth, screenHeight); - AZ::Vector3 textPosZ = MCore::Project(mPosition + mSignZ * AZ::Vector3(0.0, mBaseRadius, mScaledSize.GetZ() + mArrowLength + mBaseRadius), camera->GetViewProjMatrix(), screenWidth, screenHeight); + AZ::Vector3 textPosY = MCore::Project(m_position + m_signY * AZ::Vector3(0.0, m_scaledSize.GetY() + m_arrowLength + m_baseRadius, -m_baseRadius), camera->GetViewProjMatrix(), screenWidth, screenHeight); + AZ::Vector3 textPosX = MCore::Project(m_position + m_signX * AZ::Vector3(m_scaledSize.GetX() + m_arrowLength + m_baseRadius, -m_baseRadius, 0.0), camera->GetViewProjMatrix(), screenWidth, screenHeight); + AZ::Vector3 textPosZ = MCore::Project(m_position + m_signZ * AZ::Vector3(0.0, m_baseRadius, m_scaledSize.GetZ() + m_arrowLength + m_baseRadius), camera->GetViewProjMatrix(), screenWidth, screenHeight); renderUtil->RenderText(textPosX.GetX(), textPosX.GetY(), "X", xAxisColor); renderUtil->RenderText(textPosY.GetX(), textPosY.GetY(), "Y", yAxisColor); renderUtil->RenderText(textPosZ.GetX(), textPosZ.GetY(), "Z", zAxisColor); // Render the triangles for plane selection - if (mMode == SCALE_XY && mXAxisVisible && mYAxisVisible) + if (m_mode == SCALE_XY && m_xAxisVisible && m_yAxisVisible) { - renderUtil->RenderTriangle(firstPlanePosX, secPlanePosX, secPlanePosY, ManipulatorColors::mSelectionColorDarker); - renderUtil->RenderTriangle(firstPlanePosX, secPlanePosY, firstPlanePosY, ManipulatorColors::mSelectionColorDarker); + renderUtil->RenderTriangle(firstPlanePosX, secPlanePosX, secPlanePosY, ManipulatorColors::s_selectionColorDarker); + renderUtil->RenderTriangle(firstPlanePosX, secPlanePosY, firstPlanePosY, ManipulatorColors::s_selectionColorDarker); } - else if (mMode == SCALE_XZ && mXAxisVisible && mZAxisVisible) + else if (m_mode == SCALE_XZ && m_xAxisVisible && m_zAxisVisible) { - renderUtil->RenderTriangle(firstPlanePosX, secPlanePosX, secPlanePosZ, ManipulatorColors::mSelectionColorDarker); - renderUtil->RenderTriangle(firstPlanePosX, secPlanePosZ, firstPlanePosZ, ManipulatorColors::mSelectionColorDarker); + renderUtil->RenderTriangle(firstPlanePosX, secPlanePosX, secPlanePosZ, ManipulatorColors::s_selectionColorDarker); + renderUtil->RenderTriangle(firstPlanePosX, secPlanePosZ, firstPlanePosZ, ManipulatorColors::s_selectionColorDarker); } - else if (mMode == SCALE_YZ && mYAxisVisible && mZAxisVisible) + else if (m_mode == SCALE_YZ && m_yAxisVisible && m_zAxisVisible) { - renderUtil->RenderTriangle(firstPlanePosZ, secPlanePosZ, secPlanePosY, ManipulatorColors::mSelectionColorDarker); - renderUtil->RenderTriangle(firstPlanePosZ, secPlanePosY, firstPlanePosY, ManipulatorColors::mSelectionColorDarker); + renderUtil->RenderTriangle(firstPlanePosZ, secPlanePosZ, secPlanePosY, ManipulatorColors::s_selectionColorDarker); + renderUtil->RenderTriangle(firstPlanePosZ, secPlanePosY, firstPlanePosY, ManipulatorColors::s_selectionColorDarker); } - else if (mMode == SCALE_XYZ) + else if (m_mode == SCALE_XYZ) { - renderUtil->RenderTriangle(firstPlanePosX, firstPlanePosY, firstPlanePosZ, ManipulatorColors::mSelectionColorDarker); - renderUtil->RenderTriangle(mPosition, firstPlanePosX, firstPlanePosZ, ManipulatorColors::mSelectionColorDarker); - renderUtil->RenderTriangle(mPosition, firstPlanePosX, firstPlanePosY, ManipulatorColors::mSelectionColorDarker); - renderUtil->RenderTriangle(mPosition, firstPlanePosY, firstPlanePosZ, ManipulatorColors::mSelectionColorDarker); + renderUtil->RenderTriangle(firstPlanePosX, firstPlanePosY, firstPlanePosZ, ManipulatorColors::s_selectionColorDarker); + renderUtil->RenderTriangle(m_position, firstPlanePosX, firstPlanePosZ, ManipulatorColors::s_selectionColorDarker); + renderUtil->RenderTriangle(m_position, firstPlanePosX, firstPlanePosY, ManipulatorColors::s_selectionColorDarker); + renderUtil->RenderTriangle(m_position, firstPlanePosY, firstPlanePosZ, ManipulatorColors::s_selectionColorDarker); } // check if callback exists - if (mCallback == nullptr) + if (m_callback == nullptr) { return; } // render the current scale factor in percent if gizmo is hit - if (mMode != SCALE_NONE) + if (m_mode != SCALE_NONE) { - const AZ::Vector3& currScale = mCallback->GetCurrValueVec(); - mTempString = AZStd::string::format("Abs. Scale X: %.3f, Y: %.3f, Z: %.3f", MCore::Max(float(currScale.GetX()), 0.0f), MCore::Max(float(currScale.GetY()), 0.0f), MCore::Max(float(currScale.GetZ()), 0.0f)); - renderUtil->RenderText(10, 10, mTempString.c_str(), ManipulatorColors::mSelectionColor, 9.0f); + const AZ::Vector3& currScale = m_callback->GetCurrValueVec(); + m_tempString = AZStd::string::format("Abs. Scale X: %.3f, Y: %.3f, Z: %.3f", MCore::Max(float(currScale.GetX()), 0.0f), MCore::Max(float(currScale.GetY()), 0.0f), MCore::Max(float(currScale.GetZ()), 0.0f)); + renderUtil->RenderText(10, 10, m_tempString.c_str(), ManipulatorColors::s_selectionColor, 9.0f); } // calculate the position offset of the relative text float yOffset = (camera->GetProjectionMode() == MCommon::Camera::PROJMODE_PERSPECTIVE) ? 80.0f : 50.0f; // text position relative scaling or name displayed below the gizmo - AZ::Vector3 textPos = MCore::Project(mPosition + (mSize * AZ::Vector3(mSignX, mSignY, mSignZ) / 3.0f), camera->GetViewProjMatrix(), camera->GetScreenWidth(), camera->GetScreenHeight()); + AZ::Vector3 textPos = MCore::Project(m_position + (m_size * AZ::Vector3(m_signX, m_signY, m_signZ) / 3.0f), camera->GetViewProjMatrix(), camera->GetScreenWidth(), camera->GetScreenHeight()); // render the relative scale when moving - if (mSelectionLocked && mMode != SCALE_NONE) + if (m_selectionLocked && m_mode != SCALE_NONE) { // calculate the scale factor - AZ::Vector3 scaleFactor = ((AZ::Vector3(mSize, mSize, mSize) + mScale) / (float)mSize); + AZ::Vector3 scaleFactor = ((AZ::Vector3(m_size, m_size, m_size) + m_scale) / (float)m_size); // render the scaling value below the gizmo - mTempString = AZStd::string::format("X: %.3f, Y: %.3f, Z: %.3f", MCore::Max(float(scaleFactor.GetX()), 0.0f), MCore::Max(float(scaleFactor.GetY()), 0.0f), MCore::Max(float(scaleFactor.GetZ()), 0.0f)); - renderUtil->RenderText(textPos.GetX(), textPos.GetY() + yOffset, mTempString.c_str(), ManipulatorColors::mSelectionColor, 9.0f, true); + m_tempString = AZStd::string::format("X: %.3f, Y: %.3f, Z: %.3f", MCore::Max(float(scaleFactor.GetX()), 0.0f), MCore::Max(float(scaleFactor.GetY()), 0.0f), MCore::Max(float(scaleFactor.GetZ()), 0.0f)); + renderUtil->RenderText(textPos.GetX(), textPos.GetY() + yOffset, m_tempString.c_str(), ManipulatorColors::s_selectionColor, 9.0f, true); } else { - if (mName.size() > 0) + if (m_name.size() > 0) { - renderUtil->RenderText(textPos.GetX(), textPos.GetY() + yOffset, mName.c_str(), ManipulatorColors::mSelectionColor, 9.0f, true); + renderUtil->RenderText(textPos.GetX(), textPos.GetY() + yOffset, m_name.c_str(), ManipulatorColors::s_selectionColor, 9.0f, true); } } } @@ -286,12 +286,12 @@ namespace MCommon MCORE_UNUSED(middleButtonPressed); // check if camera has been set - if (camera == nullptr || mIsVisible == false || (leftButtonPressed && rightButtonPressed)) + if (camera == nullptr || m_isVisible == false || (leftButtonPressed && rightButtonPressed)) { return; } - // get screen mSize + // get screen m_size const uint32 screenWidth = camera->GetScreenWidth(); const uint32 screenHeight = camera->GetScreenHeight(); @@ -303,63 +303,63 @@ namespace MCommon MCore::Ray mousePrevPosRay = camera->Unproject(mousePosX - mouseMovementX, mousePosY - mouseMovementY); // check for the selected axis/plane - if (mSelectionLocked == false || mMode == SCALE_NONE) + if (m_selectionLocked == false || m_mode == SCALE_NONE) { // update old rotation of the callback - if (mCallback) + if (m_callback) { - mCallback->UpdateOldValues(); + m_callback->UpdateOldValues(); } // handle different scale cases depending on the bounding volumes - if (mousePosRay.Intersects(mXYZBoxAABB)) + if (mousePosRay.Intersects(m_xyzBoxAabb)) { - mMode = SCALE_XYZ; - mScaleDirection = AZ::Vector3(mSignX, mSignY, mSignZ); + m_mode = SCALE_XYZ; + m_scaleDirection = AZ::Vector3(m_signX, m_signY, m_signZ); } - else if (mousePosRay.Intersects(mXYPlaneAABB) && mXAxisVisible && mYAxisVisible) + else if (mousePosRay.Intersects(m_xyPlaneAabb) && m_xAxisVisible && m_yAxisVisible) { - mMode = SCALE_XY; - mScaleDirection = AZ::Vector3(mSignX, mSignY, 0.0f); + m_mode = SCALE_XY; + m_scaleDirection = AZ::Vector3(m_signX, m_signY, 0.0f); } - else if (mousePosRay.Intersects(mXZPlaneAABB) && mXAxisVisible && mZAxisVisible) + else if (mousePosRay.Intersects(m_xzPlaneAabb) && m_xAxisVisible && m_zAxisVisible) { - mMode = SCALE_XZ; - mScaleDirection = AZ::Vector3(mSignX, 0.0f, mSignZ); + m_mode = SCALE_XZ; + m_scaleDirection = AZ::Vector3(m_signX, 0.0f, m_signZ); } - else if (mousePosRay.Intersects(mYZPlaneAABB) && mYAxisVisible && mZAxisVisible) + else if (mousePosRay.Intersects(m_yzPlaneAabb) && m_yAxisVisible && m_zAxisVisible) { - mMode = SCALE_YZ; - mScaleDirection = AZ::Vector3(0.0f, mSignY, mSignZ); + m_mode = SCALE_YZ; + m_scaleDirection = AZ::Vector3(0.0f, m_signY, m_signZ); } - else if (mousePosRay.Intersects(mXAxisAABB) && mXAxisVisible) + else if (mousePosRay.Intersects(m_xAxisAabb) && m_xAxisVisible) { - mMode = SCALE_X; - mScaleDirection = AZ::Vector3(mSignX, 0.0f, 0.0f); + m_mode = SCALE_X; + m_scaleDirection = AZ::Vector3(m_signX, 0.0f, 0.0f); } - else if (mousePosRay.Intersects(mYAxisAABB) && mYAxisVisible) + else if (mousePosRay.Intersects(m_yAxisAabb) && m_yAxisVisible) { - mMode = SCALE_Y; - mScaleDirection = AZ::Vector3(0.0f, mSignY, 0.0f); + m_mode = SCALE_Y; + m_scaleDirection = AZ::Vector3(0.0f, m_signY, 0.0f); } - else if (mousePosRay.Intersects(mZAxisAABB) && mZAxisVisible) + else if (mousePosRay.Intersects(m_zAxisAabb) && m_zAxisVisible) { - mMode = SCALE_Z; - mScaleDirection = AZ::Vector3(0.0f, 0.0f, mSignZ); + m_mode = SCALE_Z; + m_scaleDirection = AZ::Vector3(0.0f, 0.0f, m_signZ); } else { - mMode = SCALE_NONE; + m_mode = SCALE_NONE; } } // set selection lock - mSelectionLocked = leftButtonPressed; + m_selectionLocked = leftButtonPressed; // move the gizmo - if (mSelectionLocked == false || mMode == SCALE_NONE) + if (m_selectionLocked == false || m_mode == SCALE_NONE) { - mScale = AZ::Vector3::CreateZero(); + m_scale = AZ::Vector3::CreateZero(); return; } @@ -369,7 +369,7 @@ namespace MCommon // calculate the movement of the mouse on a plane located at the gizmo position // and perpendicular to the camera direction MCore::Ray camRay = camera->Unproject(screenWidth / 2, screenHeight / 2); - MCore::PlaneEq movementPlane(camRay.GetDirection(), mPosition); + MCore::PlaneEq movementPlane(camRay.GetDirection(), m_position); // calculate the intersection points of the mouse positions with the previously calculated plane AZ::Vector3 mousePosIntersect, mousePrevPosIntersect; @@ -377,17 +377,17 @@ namespace MCommon mousePrevPosRay.Intersects(movementPlane, &mousePrevPosIntersect); // project the mouse movement onto the scale axis - scaleChange = (mScaleDirection * mScaleDirection.Dot(mousePosIntersect) - mScaleDirection * mScaleDirection.Dot(mousePrevPosIntersect)); + scaleChange = (m_scaleDirection * m_scaleDirection.Dot(mousePosIntersect) - m_scaleDirection * m_scaleDirection.Dot(mousePrevPosIntersect)); // update the scale of the gizmo - scaleChange = AZ::Vector3(scaleChange.GetX() * mSignX, scaleChange.GetY() * mSignY, scaleChange.GetZ() * mSignZ); - mScale += scaleChange; + scaleChange = AZ::Vector3(scaleChange.GetX() * m_signX, scaleChange.GetY() * m_signY, scaleChange.GetZ() * m_signZ); + m_scale += scaleChange; // update the callback actor instance - if (mCallback) + if (m_callback) { - AZ::Vector3 updateScale = (AZ::Vector3(mSize, mSize, mSize) + mScale) / (float)mSize; - mCallback->Update(updateScale); + AZ::Vector3 updateScale = (AZ::Vector3(m_size, m_size, m_size) + m_scale) / (float)m_size; + m_callback->Update(updateScale); } } } // namespace MCommon diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/ScaleManipulator.h b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/ScaleManipulator.h index 6d2f167893..affee9622c 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/ScaleManipulator.h +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/ScaleManipulator.h @@ -90,31 +90,31 @@ namespace MCommon protected: // scale vectors - AZ::Vector3 mScaleDirection; - AZ::Vector3 mScale; + AZ::Vector3 m_scaleDirection; + AZ::Vector3 m_scale; // bounding volumes for the axes - MCore::AABB mXAxisAABB; - MCore::AABB mYAxisAABB; - MCore::AABB mZAxisAABB; - MCore::AABB mXYPlaneAABB; - MCore::AABB mXZPlaneAABB; - MCore::AABB mYZPlaneAABB; - MCore::AABB mXYZBoxAABB; + MCore::AABB m_xAxisAabb; + MCore::AABB m_yAxisAabb; + MCore::AABB m_zAxisAabb; + MCore::AABB m_xyPlaneAabb; + MCore::AABB m_xzPlaneAabb; + MCore::AABB m_yzPlaneAabb; + MCore::AABB m_xyzBoxAabb; // size properties of the scale manipulator - float mSize; - AZ::Vector3 mScaledSize; - float mDiagScale; - float mArrowLength; - float mBaseRadius; - AZ::Vector3 mFirstPlaneSelectorPos; - AZ::Vector3 mSecPlaneSelectorPos; - float mSignX; - float mSignY; - float mSignZ; - bool mXAxisVisible; - bool mYAxisVisible; - bool mZAxisVisible; + float m_size; + AZ::Vector3 m_scaledSize; + float m_diagScale; + float m_arrowLength; + float m_baseRadius; + AZ::Vector3 m_firstPlaneSelectorPos; + AZ::Vector3 m_secPlaneSelectorPos; + float m_signX; + float m_signY; + float m_signZ; + bool m_xAxisVisible; + bool m_yAxisVisible; + bool m_zAxisVisible; }; } // namespace MCommon diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/TransformationManipulator.h b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/TransformationManipulator.h index 502c68d522..e9f5d8f72e 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/TransformationManipulator.h +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/TransformationManipulator.h @@ -30,11 +30,11 @@ namespace MCommon */ ManipulatorCallback(EMotionFX::ActorInstance* actorInstance, const AZ::Vector3& oldValue) { - mActorInstance = actorInstance; - mOldValueVec = oldValue; - mCurrValueVec = oldValue; - mCurrValueQuat = AZ::Quaternion::CreateIdentity(); - mOldValueQuat = AZ::Quaternion::CreateIdentity(); + m_actorInstance = actorInstance; + m_oldValueVec = oldValue; + m_currValueVec = oldValue; + m_currValueQuat = AZ::Quaternion::CreateIdentity(); + m_oldValueQuat = AZ::Quaternion::CreateIdentity(); } /** @@ -42,11 +42,11 @@ namespace MCommon */ ManipulatorCallback(EMotionFX::ActorInstance* actorInstance, const AZ::Quaternion& oldValue) { - mActorInstance = actorInstance; - mOldValueQuat = oldValue; - mCurrValueQuat = oldValue; - mOldValueVec = AZ::Vector3::CreateZero(); - mCurrValueVec = AZ::Vector3::CreateZero(); + m_actorInstance = actorInstance; + m_oldValueQuat = oldValue; + m_currValueQuat = oldValue; + m_oldValueVec = AZ::Vector3::CreateZero(); + m_currValueVec = AZ::Vector3::CreateZero(); } /** @@ -57,8 +57,8 @@ namespace MCommon /** * Update the actor instance. */ - virtual void Update(const AZ::Vector3& value) { mCurrValueVec = value; } - virtual void Update(const AZ::Quaternion& value) { mCurrValueQuat = value; } + virtual void Update(const AZ::Vector3& value) { m_currValueVec = value; } + virtual void Update(const AZ::Quaternion& value) { m_currValueQuat = value; } /** * Update old transformation values of the callback @@ -69,35 +69,35 @@ namespace MCommon * Functions to get the current value. * @return the position/scale/rotation of the actor instance. */ - virtual AZ::Vector3 GetCurrValueVec() { return mCurrValueVec; } - virtual AZ::Quaternion GetCurrValueQuat() { return mCurrValueQuat; } + virtual AZ::Vector3 GetCurrValueVec() { return m_currValueVec; } + virtual AZ::Quaternion GetCurrValueQuat() { return m_currValueQuat; } /** * Return the old value. * @return the old value. */ - const AZ::Vector3& GetOldValueVec() const { return mOldValueVec; } - const AZ::Quaternion& GetOldValueQuat() const { return mOldValueQuat; } + const AZ::Vector3& GetOldValueVec() const { return m_oldValueVec; } + const AZ::Quaternion& GetOldValueQuat() const { return m_oldValueQuat; } /** * Apply transformation. */ - virtual void ApplyTransformation() { mOldValueVec = mCurrValueVec; mOldValueQuat = mCurrValueQuat; } + virtual void ApplyTransformation() { m_oldValueVec = m_currValueVec; m_oldValueQuat = m_currValueQuat; } /** * returns the actor instance, if there is one assigned to the callback. * @return The actor instance. */ - EMotionFX::ActorInstance* GetActorInstance() { return mActorInstance; } + EMotionFX::ActorInstance* GetActorInstance() { return m_actorInstance; } virtual bool GetResetFollowMode() const { return false; } protected: - AZ::Quaternion mOldValueQuat; - AZ::Quaternion mCurrValueQuat; - AZ::Vector3 mOldValueVec; - AZ::Vector3 mCurrValueVec; - EMotionFX::ActorInstance* mActorInstance; + AZ::Quaternion m_oldValueQuat; + AZ::Quaternion m_currValueQuat; + AZ::Vector3 m_oldValueVec; + AZ::Vector3 m_currValueVec; + EMotionFX::ActorInstance* m_actorInstance; }; /** @@ -121,12 +121,12 @@ namespace MCommon */ TransformationManipulator(float scalingFactor = 1.0f, bool isVisible = true) { - mScalingFactor = scalingFactor; - mIsVisible = isVisible; - mSelectionLocked = false; - mPosition = AZ::Vector3::CreateZero(); - mRenderOffset = AZ::Vector3::CreateZero(); - mCallback = nullptr; + m_scalingFactor = scalingFactor; + m_isVisible = isVisible; + m_selectionLocked = false; + m_position = AZ::Vector3::CreateZero(); + m_renderOffset = AZ::Vector3::CreateZero(); + m_callback = nullptr; } /** @@ -134,48 +134,48 @@ namespace MCommon */ virtual ~TransformationManipulator() { - delete mCallback; + delete m_callback; } /** * Function to init the position of the gizmo. */ - void Init(const AZ::Vector3& position) { mPosition = position + mRenderOffset; UpdateBoundingVolumes(); } + void Init(const AZ::Vector3& position) { m_position = position + m_renderOffset; UpdateBoundingVolumes(); } /** * Function to set the name of the gizmo. * @param name The name of the gizmo. (e.g. used to identify different parameters) */ - void SetName(const AZStd::string& name) { mName = name; } + void SetName(const AZStd::string& name) { m_name = name; } /** * Function to get the gizmo name. * @return The name of the gizmo. */ - const AZStd::string& GetName() const { return mName; } + const AZStd::string& GetName() const { return m_name; } /** * Get the selection lock state. * @return the selection lock state. */ - void SetSelectionLocked(bool selectionLocked) { mSelectionLocked = selectionLocked; } - bool GetSelectionLocked() { return mSelectionLocked; } + void SetSelectionLocked(bool selectionLocked) { m_selectionLocked = selectionLocked; } + bool GetSelectionLocked() { return m_selectionLocked; } /** * Set the visible state of the manipulator. */ - void SetIsVisible(bool isVisible = true) { mIsVisible = isVisible; } + void SetIsVisible(bool isVisible = true) { m_isVisible = isVisible; } /** * Set the scale of the gizmo. * @param scale The new scale value for the gizmo. */ - void SetScale(float scale, MCommon::Camera* camera = nullptr) { mScalingFactor = scale; UpdateBoundingVolumes(camera); } + void SetScale(float scale, MCommon::Camera* camera = nullptr) { m_scalingFactor = scale; UpdateBoundingVolumes(camera); } /** * Set mode of the gizmo. */ - void SetMode(uint32 mode) { mMode = mode; } + void SetMode(uint32 mode) { m_mode = mode; } /** * Set the render offset of the gizmo. @@ -185,7 +185,7 @@ namespace MCommon void SetRenderOffset(const AZ::Vector3& offset) { AZ::Vector3 oldPos = GetPosition(); - mRenderOffset = offset; + m_renderOffset = offset; Init(oldPos); } @@ -193,39 +193,39 @@ namespace MCommon * Get the position of the gizmo. * @return The position of the gizmo. */ - AZ::Vector3 GetPosition() const { return mPosition - mRenderOffset; } + AZ::Vector3 GetPosition() const { return m_position - m_renderOffset; } /** * Get the position offset of the gizmo. * Only affects rendering position of the gizmo, not the actual value it modifies. * @return The offset position of the gizmo. */ - const AZ::Vector3& GetRenderOffset() const { return mRenderOffset; } + const AZ::Vector3& GetRenderOffset() const { return m_renderOffset; } /** * Set the callback. * @param callback Pointer to the callback used to manipulate the actorinstance. */ - void SetCallback(ManipulatorCallback* callback) { delete mCallback; mCallback = callback; } + void SetCallback(ManipulatorCallback* callback) { delete m_callback; m_callback = callback; } /** * Returns the current callback of the manipulator. * Used to apply the transformation upon mouse release for example. * @return The manipulator callback. */ - ManipulatorCallback* GetCallback() { return mCallback; } + ManipulatorCallback* GetCallback() { return m_callback; } /** * Function to get the mode of the transformation manipulator. * @return The mode of the manipulator. */ - uint32 GetMode() { return mMode; } + uint32 GetMode() { return m_mode; } /** * Returns the visible state of the gizmo. - * @return mIsVisible The visible state of the gizmo. + * @return m_isVisible The visible state of the gizmo. */ - bool GetIsVisible() { return mIsVisible; } + bool GetIsVisible() { return m_isVisible; } /** * Function to get the type of a gizmo. Has to be set by the constructor of the inherited classes. @@ -270,14 +270,14 @@ namespace MCommon } protected: - AZ::Vector3 mPosition; - AZ::Vector3 mRenderOffset; - AZStd::string mName; - AZStd::string mTempString; - uint32 mMode; - float mScalingFactor; - ManipulatorCallback* mCallback; - bool mSelectionLocked; - bool mIsVisible; + AZ::Vector3 m_position; + AZ::Vector3 m_renderOffset; + AZStd::string m_name; + AZStd::string m_tempString; + uint32 m_mode; + float m_scalingFactor; + ManipulatorCallback* m_callback; + bool m_selectionLocked; + bool m_isVisible; }; } // namespace MCommon diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/TranslateManipulator.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/TranslateManipulator.cpp index e20ae5a77e..db2cccb334 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/TranslateManipulator.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/TranslateManipulator.cpp @@ -16,8 +16,8 @@ namespace MCommon : TransformationManipulator(scalingFactor, isVisible) { // set the initial values - mMode = TRANSLATE_NONE; - mCallback = nullptr; + m_mode = TRANSLATE_NONE; + m_callback = nullptr; } @@ -33,26 +33,26 @@ namespace MCommon MCORE_UNUSED(camera); // set the new proportions - mSize = mScalingFactor; - mArrowLength = mSize / 5.0f; - mBaseRadius = mSize / 20.0f; - mPlaneSelectorPos = mSize / 2; + m_size = m_scalingFactor; + m_arrowLength = m_size / 5.0f; + m_baseRadius = m_size / 20.0f; + m_planeSelectorPos = m_size / 2; // set the bounding volumes of the axes selection - mXAxisAABB.SetMax(mPosition + AZ::Vector3(mSize + mArrowLength, mBaseRadius, mBaseRadius)); - mXAxisAABB.SetMin(mPosition - AZ::Vector3(mBaseRadius, mBaseRadius, mBaseRadius)); - mYAxisAABB.SetMax(mPosition + AZ::Vector3(mBaseRadius, mSize + mArrowLength, mBaseRadius)); - mYAxisAABB.SetMin(mPosition - AZ::Vector3(mBaseRadius, mBaseRadius, mBaseRadius)); - mZAxisAABB.SetMax(mPosition + AZ::Vector3(mBaseRadius, mBaseRadius, mSize + mArrowLength)); - mZAxisAABB.SetMin(mPosition - AZ::Vector3(mBaseRadius, mBaseRadius, mBaseRadius)); + m_xAxisAabb.SetMax(m_position + AZ::Vector3(m_size + m_arrowLength, m_baseRadius, m_baseRadius)); + m_xAxisAabb.SetMin(m_position - AZ::Vector3(m_baseRadius, m_baseRadius, m_baseRadius)); + m_yAxisAabb.SetMax(m_position + AZ::Vector3(m_baseRadius, m_size + m_arrowLength, m_baseRadius)); + m_yAxisAabb.SetMin(m_position - AZ::Vector3(m_baseRadius, m_baseRadius, m_baseRadius)); + m_zAxisAabb.SetMax(m_position + AZ::Vector3(m_baseRadius, m_baseRadius, m_size + m_arrowLength)); + m_zAxisAabb.SetMin(m_position - AZ::Vector3(m_baseRadius, m_baseRadius, m_baseRadius)); // set bounding volumes for the plane selectors - mXYPlaneAABB.SetMax(mPosition + AZ::Vector3(mPlaneSelectorPos, mPlaneSelectorPos, mBaseRadius)); - mXYPlaneAABB.SetMin(mPosition + 0.3f * AZ::Vector3(mPlaneSelectorPos, mPlaneSelectorPos, 0) - AZ::Vector3(mBaseRadius, mBaseRadius, mBaseRadius)); - mXZPlaneAABB.SetMax(mPosition + AZ::Vector3(mPlaneSelectorPos, mBaseRadius, mPlaneSelectorPos)); - mXZPlaneAABB.SetMin(mPosition + 0.3f * AZ::Vector3(mPlaneSelectorPos, 0, mPlaneSelectorPos) - AZ::Vector3(mBaseRadius, mBaseRadius, mBaseRadius)); - mYZPlaneAABB.SetMax(mPosition + AZ::Vector3(mBaseRadius, mPlaneSelectorPos, mPlaneSelectorPos)); - mYZPlaneAABB.SetMin(mPosition + 0.3f * AZ::Vector3(0, mPlaneSelectorPos, mPlaneSelectorPos) - AZ::Vector3(mBaseRadius, mBaseRadius, mBaseRadius)); + m_xyPlaneAabb.SetMax(m_position + AZ::Vector3(m_planeSelectorPos, m_planeSelectorPos, m_baseRadius)); + m_xyPlaneAabb.SetMin(m_position + 0.3f * AZ::Vector3(m_planeSelectorPos, m_planeSelectorPos, 0) - AZ::Vector3(m_baseRadius, m_baseRadius, m_baseRadius)); + m_xzPlaneAabb.SetMax(m_position + AZ::Vector3(m_planeSelectorPos, m_baseRadius, m_planeSelectorPos)); + m_xzPlaneAabb.SetMin(m_position + 0.3f * AZ::Vector3(m_planeSelectorPos, 0, m_planeSelectorPos) - AZ::Vector3(m_baseRadius, m_baseRadius, m_baseRadius)); + m_yzPlaneAabb.SetMax(m_position + AZ::Vector3(m_baseRadius, m_planeSelectorPos, m_planeSelectorPos)); + m_yzPlaneAabb.SetMin(m_position + 0.3f * AZ::Vector3(0, m_planeSelectorPos, m_planeSelectorPos) - AZ::Vector3(m_baseRadius, m_baseRadius, m_baseRadius)); } @@ -74,9 +74,9 @@ namespace MCommon AZ::Vector3 camDir = camRollRay.GetDirection(); // determine the axis visibility, to disable movement for invisible axes - mXAxisVisible = (MCore::InRange(MCore::Math::Abs(camDir.Dot(AZ::Vector3(1.0f, 0.0f, 0.0f))) - 1.0f, -MCore::Math::epsilon, MCore::Math::epsilon) == false); - mYAxisVisible = (MCore::InRange(MCore::Math::Abs(camDir.Dot(AZ::Vector3(0.0f, 1.0f, 0.0f))) - 1.0f, -MCore::Math::epsilon, MCore::Math::epsilon) == false); - mZAxisVisible = (MCore::InRange(MCore::Math::Abs(camDir.Dot(AZ::Vector3(0.0f, 0.0f, 1.0f))) - 1.0f, -MCore::Math::epsilon, MCore::Math::epsilon) == false); + m_xAxisVisible = (MCore::InRange(MCore::Math::Abs(camDir.Dot(AZ::Vector3(1.0f, 0.0f, 0.0f))) - 1.0f, -MCore::Math::epsilon, MCore::Math::epsilon) == false); + m_yAxisVisible = (MCore::InRange(MCore::Math::Abs(camDir.Dot(AZ::Vector3(0.0f, 1.0f, 0.0f))) - 1.0f, -MCore::Math::epsilon, MCore::Math::epsilon) == false); + m_zAxisVisible = (MCore::InRange(MCore::Math::Abs(camDir.Dot(AZ::Vector3(0.0f, 0.0f, 1.0f))) - 1.0f, -MCore::Math::epsilon, MCore::Math::epsilon) == false); } @@ -96,8 +96,8 @@ namespace MCommon MCore::Ray mouseRay = camera->Unproject(mousePosX, mousePosY); // check if one of the AABBs is hit - if (mouseRay.Intersects(mXAxisAABB) || mouseRay.Intersects(mYAxisAABB) || mouseRay.Intersects(mZAxisAABB) || - mouseRay.Intersects(mXYPlaneAABB) || mouseRay.Intersects(mXZPlaneAABB) || mouseRay.Intersects(mYZPlaneAABB)) + if (mouseRay.Intersects(m_xAxisAabb) || mouseRay.Intersects(m_yAxisAabb) || mouseRay.Intersects(m_zAxisAabb) || + mouseRay.Intersects(m_xyPlaneAabb) || mouseRay.Intersects(m_xzPlaneAabb) || mouseRay.Intersects(m_yzPlaneAabb)) { return true; } @@ -111,7 +111,7 @@ namespace MCommon void TranslateManipulator::Render(MCommon::Camera* camera, RenderUtil* renderUtil) { // return if no render util is set - if (renderUtil == nullptr || camera == nullptr || mIsVisible == false) + if (renderUtil == nullptr || camera == nullptr || m_isVisible == false) { return; } @@ -124,106 +124,100 @@ namespace MCommon UpdateAxisVisibility(camera); // set color for the axes, depending on the selection - MCore::RGBAColor xAxisColor = (mMode == TRANSLATE_X || mMode == TRANSLATE_XY || mMode == TRANSLATE_XZ) ? ManipulatorColors::mSelectionColor : ManipulatorColors::mRed; - MCore::RGBAColor yAxisColor = (mMode == TRANSLATE_Y || mMode == TRANSLATE_XY || mMode == TRANSLATE_YZ) ? ManipulatorColors::mSelectionColor : ManipulatorColors::mGreen; - MCore::RGBAColor zAxisColor = (mMode == TRANSLATE_Z || mMode == TRANSLATE_XZ || mMode == TRANSLATE_YZ) ? ManipulatorColors::mSelectionColor : ManipulatorColors::mBlue; - MCore::RGBAColor xyPlaneColorX = (mMode == TRANSLATE_XY) ? ManipulatorColors::mSelectionColor : ManipulatorColors::mRed; - MCore::RGBAColor xyPlaneColorY = (mMode == TRANSLATE_XY) ? ManipulatorColors::mSelectionColor : ManipulatorColors::mGreen; - MCore::RGBAColor xzPlaneColorX = (mMode == TRANSLATE_XZ) ? ManipulatorColors::mSelectionColor : ManipulatorColors::mRed; - MCore::RGBAColor xzPlaneColorZ = (mMode == TRANSLATE_XZ) ? ManipulatorColors::mSelectionColor : ManipulatorColors::mBlue; - MCore::RGBAColor yzPlaneColorY = (mMode == TRANSLATE_YZ) ? ManipulatorColors::mSelectionColor : ManipulatorColors::mGreen; - MCore::RGBAColor yzPlaneColorZ = (mMode == TRANSLATE_YZ) ? ManipulatorColors::mSelectionColor : ManipulatorColors::mBlue; + MCore::RGBAColor xAxisColor = (m_mode == TRANSLATE_X || m_mode == TRANSLATE_XY || m_mode == TRANSLATE_XZ) ? ManipulatorColors::s_selectionColor : ManipulatorColors::s_red; + MCore::RGBAColor yAxisColor = (m_mode == TRANSLATE_Y || m_mode == TRANSLATE_XY || m_mode == TRANSLATE_YZ) ? ManipulatorColors::s_selectionColor : ManipulatorColors::s_green; + MCore::RGBAColor zAxisColor = (m_mode == TRANSLATE_Z || m_mode == TRANSLATE_XZ || m_mode == TRANSLATE_YZ) ? ManipulatorColors::s_selectionColor : ManipulatorColors::s_blue; + MCore::RGBAColor xyPlaneColorX = (m_mode == TRANSLATE_XY) ? ManipulatorColors::s_selectionColor : ManipulatorColors::s_red; + MCore::RGBAColor xyPlaneColorY = (m_mode == TRANSLATE_XY) ? ManipulatorColors::s_selectionColor : ManipulatorColors::s_green; + MCore::RGBAColor xzPlaneColorX = (m_mode == TRANSLATE_XZ) ? ManipulatorColors::s_selectionColor : ManipulatorColors::s_red; + MCore::RGBAColor xzPlaneColorZ = (m_mode == TRANSLATE_XZ) ? ManipulatorColors::s_selectionColor : ManipulatorColors::s_blue; + MCore::RGBAColor yzPlaneColorY = (m_mode == TRANSLATE_YZ) ? ManipulatorColors::s_selectionColor : ManipulatorColors::s_green; + MCore::RGBAColor yzPlaneColorZ = (m_mode == TRANSLATE_YZ) ? ManipulatorColors::s_selectionColor : ManipulatorColors::s_blue; - if (mXAxisVisible) + if (m_xAxisVisible) { // the x axis consisting of a line, cylinder and plane selectors - renderUtil->RenderLine(mPosition, mPosition + AZ::Vector3(mSize, 0.0, 0.0), xAxisColor); - renderUtil->RenderCylinder(mBaseRadius, 0, mArrowLength, mPosition + AZ::Vector3(mSize, 0, 0), AZ::Vector3(1, 0, 0), ManipulatorColors::mRed); - renderUtil->RenderLine(mPosition + AZ::Vector3(mPlaneSelectorPos, 0.0, 0.0), mPosition + AZ::Vector3(mPlaneSelectorPos, mPlaneSelectorPos, 0.0), xyPlaneColorX); - renderUtil->RenderLine(mPosition + AZ::Vector3(mPlaneSelectorPos, 0.0, 0.0), mPosition + AZ::Vector3(mPlaneSelectorPos, 0.0, mPlaneSelectorPos), xzPlaneColorX); + renderUtil->RenderLine(m_position, m_position + AZ::Vector3(m_size, 0.0, 0.0), xAxisColor); + renderUtil->RenderCylinder(m_baseRadius, 0, m_arrowLength, m_position + AZ::Vector3(m_size, 0, 0), AZ::Vector3(1, 0, 0), ManipulatorColors::s_red); + renderUtil->RenderLine(m_position + AZ::Vector3(m_planeSelectorPos, 0.0, 0.0), m_position + AZ::Vector3(m_planeSelectorPos, m_planeSelectorPos, 0.0), xyPlaneColorX); + renderUtil->RenderLine(m_position + AZ::Vector3(m_planeSelectorPos, 0.0, 0.0), m_position + AZ::Vector3(m_planeSelectorPos, 0.0, m_planeSelectorPos), xzPlaneColorX); // render the axis label for the x axis - AZ::Vector3 textPosX = MCore::Project(mPosition + AZ::Vector3(mSize + mArrowLength + mBaseRadius, -mBaseRadius, 0.0), camera->GetViewProjMatrix(), screenWidth, screenHeight); + AZ::Vector3 textPosX = MCore::Project(m_position + AZ::Vector3(m_size + m_arrowLength + m_baseRadius, -m_baseRadius, 0.0), camera->GetViewProjMatrix(), screenWidth, screenHeight); renderUtil->RenderText(textPosX.GetX(), textPosX.GetY(), "X", xAxisColor); } - if (mYAxisVisible) + if (m_yAxisVisible) { // the y axis consisting of a line, cylinder and plane selectors - renderUtil->RenderLine(mPosition, mPosition + AZ::Vector3(0.0, mSize, 0.0), yAxisColor); - renderUtil->RenderCylinder(mBaseRadius, 0, mArrowLength, mPosition + AZ::Vector3(0, mSize, 0), AZ::Vector3(0, 1, 0), ManipulatorColors::mGreen); - renderUtil->RenderLine(mPosition + AZ::Vector3(0.0, mPlaneSelectorPos, 0.0), mPosition + AZ::Vector3(mPlaneSelectorPos, mPlaneSelectorPos, 0.0), xyPlaneColorY); - renderUtil->RenderLine(mPosition + AZ::Vector3(0.0, mPlaneSelectorPos, 0.0), mPosition + AZ::Vector3(0.0, mPlaneSelectorPos, mPlaneSelectorPos), yzPlaneColorY); + renderUtil->RenderLine(m_position, m_position + AZ::Vector3(0.0, m_size, 0.0), yAxisColor); + renderUtil->RenderCylinder(m_baseRadius, 0, m_arrowLength, m_position + AZ::Vector3(0, m_size, 0), AZ::Vector3(0, 1, 0), ManipulatorColors::s_green); + renderUtil->RenderLine(m_position + AZ::Vector3(0.0, m_planeSelectorPos, 0.0), m_position + AZ::Vector3(m_planeSelectorPos, m_planeSelectorPos, 0.0), xyPlaneColorY); + renderUtil->RenderLine(m_position + AZ::Vector3(0.0, m_planeSelectorPos, 0.0), m_position + AZ::Vector3(0.0, m_planeSelectorPos, m_planeSelectorPos), yzPlaneColorY); // render the axis label for the y axis - AZ::Vector3 textPosY = MCore::Project(mPosition + AZ::Vector3(0.0, mSize + mArrowLength + mBaseRadius, -mBaseRadius), camera->GetViewProjMatrix(), screenWidth, screenHeight); + AZ::Vector3 textPosY = MCore::Project(m_position + AZ::Vector3(0.0, m_size + m_arrowLength + m_baseRadius, -m_baseRadius), camera->GetViewProjMatrix(), screenWidth, screenHeight); renderUtil->RenderText(textPosY.GetX(), textPosY.GetY(), "Y", yAxisColor); } - if (mZAxisVisible) + if (m_zAxisVisible) { // the z axis consisting of a line, cylinder and plane selectors - renderUtil->RenderLine(mPosition, mPosition + AZ::Vector3(0.0, 0.0, mSize), zAxisColor); - renderUtil->RenderCylinder(mBaseRadius, 0, mArrowLength, mPosition + AZ::Vector3(0, 0, mSize), AZ::Vector3(0, 0, 1), ManipulatorColors::mBlue); - renderUtil->RenderLine(mPosition + AZ::Vector3(0.0, 0.0, mPlaneSelectorPos), mPosition + AZ::Vector3(mPlaneSelectorPos, 0.0, mPlaneSelectorPos), xzPlaneColorZ); - renderUtil->RenderLine(mPosition + AZ::Vector3(0.0, 0.0, mPlaneSelectorPos), mPosition + AZ::Vector3(0.0, mPlaneSelectorPos, mPlaneSelectorPos), yzPlaneColorZ); + renderUtil->RenderLine(m_position, m_position + AZ::Vector3(0.0, 0.0, m_size), zAxisColor); + renderUtil->RenderCylinder(m_baseRadius, 0, m_arrowLength, m_position + AZ::Vector3(0, 0, m_size), AZ::Vector3(0, 0, 1), ManipulatorColors::s_blue); + renderUtil->RenderLine(m_position + AZ::Vector3(0.0, 0.0, m_planeSelectorPos), m_position + AZ::Vector3(m_planeSelectorPos, 0.0, m_planeSelectorPos), xzPlaneColorZ); + renderUtil->RenderLine(m_position + AZ::Vector3(0.0, 0.0, m_planeSelectorPos), m_position + AZ::Vector3(0.0, m_planeSelectorPos, m_planeSelectorPos), yzPlaneColorZ); // render the axis label for the z axis - AZ::Vector3 textPosZ = MCore::Project(mPosition + AZ::Vector3(0.0, mBaseRadius, mSize + mArrowLength + mBaseRadius), camera->GetViewProjMatrix(), screenWidth, screenHeight); + AZ::Vector3 textPosZ = MCore::Project(m_position + AZ::Vector3(0.0, m_baseRadius, m_size + m_arrowLength + m_baseRadius), camera->GetViewProjMatrix(), screenWidth, screenHeight); renderUtil->RenderText(textPosZ.GetX(), textPosZ.GetY(), "Z", zAxisColor); } // draw transparent quad for the plane selectors - if (mMode == TRANSLATE_XY) + if (m_mode == TRANSLATE_XY) { - renderUtil->RenderTriangle(mPosition, mPosition + AZ::Vector3(mPlaneSelectorPos, 0.0f, 0.0f), mPosition + AZ::Vector3(mPlaneSelectorPos, mPlaneSelectorPos, 0.0f), ManipulatorColors::mSelectionColorDarker); - renderUtil->RenderTriangle(mPosition, mPosition + AZ::Vector3(mPlaneSelectorPos, mPlaneSelectorPos, 0.0f), mPosition + AZ::Vector3(0.0f, mPlaneSelectorPos, 0.0f), ManipulatorColors::mSelectionColorDarker); + renderUtil->RenderTriangle(m_position, m_position + AZ::Vector3(m_planeSelectorPos, 0.0f, 0.0f), m_position + AZ::Vector3(m_planeSelectorPos, m_planeSelectorPos, 0.0f), ManipulatorColors::s_selectionColorDarker); + renderUtil->RenderTriangle(m_position, m_position + AZ::Vector3(m_planeSelectorPos, m_planeSelectorPos, 0.0f), m_position + AZ::Vector3(0.0f, m_planeSelectorPos, 0.0f), ManipulatorColors::s_selectionColorDarker); } - else if (mMode == TRANSLATE_XZ) + else if (m_mode == TRANSLATE_XZ) { - renderUtil->RenderTriangle(mPosition, mPosition + AZ::Vector3(mPlaneSelectorPos, 0.0f, 0.0f), mPosition + AZ::Vector3(mPlaneSelectorPos, 0.0f, mPlaneSelectorPos), ManipulatorColors::mSelectionColorDarker); - renderUtil->RenderTriangle(mPosition, mPosition + AZ::Vector3(mPlaneSelectorPos, 0.0f, mPlaneSelectorPos), mPosition + AZ::Vector3(0.0f, 0.0f, mPlaneSelectorPos), ManipulatorColors::mSelectionColorDarker); + renderUtil->RenderTriangle(m_position, m_position + AZ::Vector3(m_planeSelectorPos, 0.0f, 0.0f), m_position + AZ::Vector3(m_planeSelectorPos, 0.0f, m_planeSelectorPos), ManipulatorColors::s_selectionColorDarker); + renderUtil->RenderTriangle(m_position, m_position + AZ::Vector3(m_planeSelectorPos, 0.0f, m_planeSelectorPos), m_position + AZ::Vector3(0.0f, 0.0f, m_planeSelectorPos), ManipulatorColors::s_selectionColorDarker); } - else if (mMode == TRANSLATE_YZ) + else if (m_mode == TRANSLATE_YZ) { - renderUtil->RenderTriangle(mPosition + AZ::Vector3(0.0f, 0.0f, mPlaneSelectorPos), mPosition, mPosition + AZ::Vector3(0.0f, mPlaneSelectorPos, 0.0f), ManipulatorColors::mSelectionColorDarker); - renderUtil->RenderTriangle(mPosition + AZ::Vector3(0.0f, mPlaneSelectorPos, 0.0f), mPosition + AZ::Vector3(0.0f, mPlaneSelectorPos, mPlaneSelectorPos), mPosition + AZ::Vector3(0.0f, 0.0f, mPlaneSelectorPos), ManipulatorColors::mSelectionColorDarker); + renderUtil->RenderTriangle(m_position + AZ::Vector3(0.0f, 0.0f, m_planeSelectorPos), m_position, m_position + AZ::Vector3(0.0f, m_planeSelectorPos, 0.0f), ManipulatorColors::s_selectionColorDarker); + renderUtil->RenderTriangle(m_position + AZ::Vector3(0.0f, m_planeSelectorPos, 0.0f), m_position + AZ::Vector3(0.0f, m_planeSelectorPos, m_planeSelectorPos), m_position + AZ::Vector3(0.0f, 0.0f, m_planeSelectorPos), ManipulatorColors::s_selectionColorDarker); } // render the relative position when moving - if (mCallback) + if (m_callback) { // calculate the y-offset of the text position - AZ::Vector3 deltaPos = GetPosition() - mCallback->GetOldValueVec(); + AZ::Vector3 deltaPos = GetPosition() - m_callback->GetOldValueVec(); float yOffset = (camera->GetProjectionMode() == MCommon::Camera::PROJMODE_PERSPECTIVE) ? 60.0f * ((float)screenHeight / 720.0f) : 40.0f; // render the relative movement - AZ::Vector3 textPos = MCore::Project(mPosition + (AZ::Vector3(mSize, mSize, mSize) / 3.0f), camera->GetViewProjMatrix(), camera->GetScreenWidth(), camera->GetScreenHeight()); + AZ::Vector3 textPos = MCore::Project(m_position + (AZ::Vector3(m_size, m_size, m_size) / 3.0f), camera->GetViewProjMatrix(), camera->GetScreenWidth(), camera->GetScreenHeight()); // render delta position of the gizmo of the name if not dragging at the moment - if (mSelectionLocked && mMode != TRANSLATE_NONE) + if (m_selectionLocked && m_mode != TRANSLATE_NONE) { - mTempString = AZStd::string::format("X: %.3f, Y: %.3f, Z: %.3f", static_cast(deltaPos.GetX()), static_cast(deltaPos.GetY()), static_cast(deltaPos.GetZ())); - renderUtil->RenderText(textPos.GetX(), textPos.GetY() + yOffset, mTempString.c_str(), ManipulatorColors::mSelectionColor, 9.0f, true); + m_tempString = AZStd::string::format("X: %.3f, Y: %.3f, Z: %.3f", static_cast(deltaPos.GetX()), static_cast(deltaPos.GetY()), static_cast(deltaPos.GetZ())); + renderUtil->RenderText(textPos.GetX(), textPos.GetY() + yOffset, m_tempString.c_str(), ManipulatorColors::s_selectionColor, 9.0f, true); } else { - renderUtil->RenderText(textPos.GetX(), textPos.GetY() + yOffset, mName.c_str(), ManipulatorColors::mSelectionColor, 9.0f, true); + renderUtil->RenderText(textPos.GetX(), textPos.GetY() + yOffset, m_name.c_str(), ManipulatorColors::s_selectionColor, 9.0f, true); } } - // render aabbs (for debug issues. remove this) - /* renderUtil->RenderAABB( mXAxisAABB, ManipulatorColors::mSelectionColor, true ); - renderUtil->RenderAABB( mYAxisAABB, ManipulatorColors::mSelectionColor, true ); - renderUtil->RenderAABB( mZAxisAABB, ManipulatorColors::mSelectionColor, true ); - */ - // render the absolute position of the gizmo/actor instance - if (mMode != TRANSLATE_NONE) + if (m_mode != TRANSLATE_NONE) { const AZ::Vector3 offsetPos = GetPosition(); - mTempString = AZStd::string::format("Abs Pos X: %.3f, Y: %.3f, Z: %.3f", static_cast(offsetPos.GetX()), static_cast(offsetPos.GetY()), static_cast(offsetPos.GetZ())); - renderUtil->RenderText(10, 10, mTempString.c_str(), ManipulatorColors::mSelectionColor, 9.0f); + m_tempString = AZStd::string::format("Abs Pos X: %.3f, Y: %.3f, Z: %.3f", static_cast(offsetPos.GetX()), static_cast(offsetPos.GetY()), static_cast(offsetPos.GetZ())); + renderUtil->RenderText(10, 10, m_tempString.c_str(), ManipulatorColors::s_selectionColor, 9.0f); } } @@ -235,7 +229,7 @@ namespace MCommon MCORE_UNUSED(middleButtonPressed); // check if camera has been set - if (camera == nullptr || mIsVisible == false || (leftButtonPressed && rightButtonPressed)) + if (camera == nullptr || m_isVisible == false || (leftButtonPressed && rightButtonPressed)) { return; } @@ -252,64 +246,64 @@ namespace MCommon UpdateAxisVisibility(camera); // check for the selected axis/plane - if (mSelectionLocked == false || mMode == TRANSLATE_NONE) + if (m_selectionLocked == false || m_mode == TRANSLATE_NONE) { // update old values of the callback - if (mCallback) + if (m_callback) { - mCallback->UpdateOldValues(); + m_callback->UpdateOldValues(); } // handle different translation modes - if (mousePosRay.Intersects(mXYPlaneAABB) && mXAxisVisible && mYAxisVisible) + if (mousePosRay.Intersects(m_xyPlaneAabb) && m_xAxisVisible && m_yAxisVisible) { - mMovementDirection = AZ::Vector3(1.0f, 1.0f, 0.0f); - mMovementPlaneNormal = AZ::Vector3(0.0f, 0.0f, 1.0f); - mMode = TRANSLATE_XY; + m_movementDirection = AZ::Vector3(1.0f, 1.0f, 0.0f); + m_movementPlaneNormal = AZ::Vector3(0.0f, 0.0f, 1.0f); + m_mode = TRANSLATE_XY; } - else if (mousePosRay.Intersects(mXZPlaneAABB) && mXAxisVisible && mZAxisVisible) + else if (mousePosRay.Intersects(m_xzPlaneAabb) && m_xAxisVisible && m_zAxisVisible) { - mMovementDirection = AZ::Vector3(1.0f, 0.0f, 1.0f); - mMovementPlaneNormal = AZ::Vector3(0.0f, 1.0f, 0.0f); - mMode = TRANSLATE_XZ; + m_movementDirection = AZ::Vector3(1.0f, 0.0f, 1.0f); + m_movementPlaneNormal = AZ::Vector3(0.0f, 1.0f, 0.0f); + m_mode = TRANSLATE_XZ; } - else if (mousePosRay.Intersects(mYZPlaneAABB) && mYAxisVisible && mZAxisVisible) + else if (mousePosRay.Intersects(m_yzPlaneAabb) && m_yAxisVisible && m_zAxisVisible) { - mMovementDirection = AZ::Vector3(0.0f, 1.0f, 1.0f); - mMovementPlaneNormal = AZ::Vector3(1.0f, 0.0f, 0.0f); - mMode = TRANSLATE_YZ; + m_movementDirection = AZ::Vector3(0.0f, 1.0f, 1.0f); + m_movementPlaneNormal = AZ::Vector3(1.0f, 0.0f, 0.0f); + m_mode = TRANSLATE_YZ; } - else if (mousePosRay.Intersects(mXAxisAABB) && mXAxisVisible) + else if (mousePosRay.Intersects(m_xAxisAabb) && m_xAxisVisible) { - mMovementDirection = AZ::Vector3(1.0f, 0.0f, 0.0f); - mMovementPlaneNormal = AZ::Vector3(0.0f, 1.0f, 1.0f).GetNormalized(); - mMode = TRANSLATE_X; + m_movementDirection = AZ::Vector3(1.0f, 0.0f, 0.0f); + m_movementPlaneNormal = AZ::Vector3(0.0f, 1.0f, 1.0f).GetNormalized(); + m_mode = TRANSLATE_X; } - else if (mousePosRay.Intersects(mYAxisAABB) && mYAxisVisible) + else if (mousePosRay.Intersects(m_yAxisAabb) && m_yAxisVisible) { - mMovementDirection = AZ::Vector3(0.0f, 1.0f, 0.0f); - mMovementPlaneNormal = AZ::Vector3(1.0f, 0.0f, 1.0f).GetNormalized(); - mMode = TRANSLATE_Y; + m_movementDirection = AZ::Vector3(0.0f, 1.0f, 0.0f); + m_movementPlaneNormal = AZ::Vector3(1.0f, 0.0f, 1.0f).GetNormalized(); + m_mode = TRANSLATE_Y; } - else if (mousePosRay.Intersects(mZAxisAABB) && mZAxisVisible) + else if (mousePosRay.Intersects(m_zAxisAabb) && m_zAxisVisible) { - mMovementDirection = AZ::Vector3(0.0f, 0.0f, 1.0f); - mMovementPlaneNormal = AZ::Vector3(1.0f, 1.0f, 0.0f).GetNormalized(); - mMode = TRANSLATE_Z; + m_movementDirection = AZ::Vector3(0.0f, 0.0f, 1.0f); + m_movementPlaneNormal = AZ::Vector3(1.0f, 1.0f, 0.0f).GetNormalized(); + m_mode = TRANSLATE_Z; } else { - mMode = TRANSLATE_NONE; + m_mode = TRANSLATE_NONE; } } // set selection lock - mSelectionLocked = leftButtonPressed; + m_selectionLocked = leftButtonPressed; // move the gizmo - if (mSelectionLocked == false || mMode == TRANSLATE_NONE) + if (m_selectionLocked == false || m_mode == TRANSLATE_NONE) { - mMousePosRelative = AZ::Vector3::CreateZero(); + m_mousePosRelative = AZ::Vector3::CreateZero(); return; } @@ -317,22 +311,22 @@ namespace MCommon AZ::Vector3 movement = AZ::Vector3::CreateZero(); // handle plane movement - if (mMode == TRANSLATE_XY || mMode == TRANSLATE_XZ || mMode == TRANSLATE_YZ) + if (m_mode == TRANSLATE_XY || m_mode == TRANSLATE_XZ || m_mode == TRANSLATE_YZ) { // generate current translation plane and calculate mouse intersections - MCore::PlaneEq movementPlane(mMovementPlaneNormal, mPosition); + MCore::PlaneEq movementPlane(m_movementPlaneNormal, m_position); AZ::Vector3 mousePosIntersect, mousePrevPosIntersect; mousePosRay.Intersects(movementPlane, &mousePosIntersect); mousePrevPosRay.Intersects(movementPlane, &mousePrevPosIntersect); // calculate the mouse position relative to the gizmo - if (MCore::Math::IsFloatZero(MCore::SafeLength(mMousePosRelative))) + if (MCore::Math::IsFloatZero(MCore::SafeLength(m_mousePosRelative))) { - mMousePosRelative = mousePosIntersect - mPosition; + m_mousePosRelative = mousePosIntersect - m_position; } // distance of the mouse intersections is the actual movement on the plane - movement = mousePosIntersect - mMousePosRelative; + movement = mousePosIntersect - m_mousePosRelative; } // handle axis movement @@ -342,12 +336,12 @@ namespace MCommon // calculate the movement of the mouse on a plane located at the gizmo position // and perpendicular to the move direction AZ::Vector3 camDir = camera->Unproject(camera->GetScreenWidth() / 2, camera->GetScreenHeight() / 2).GetDirection(); - AZ::Vector3 thirdAxis = mMovementDirection.Cross(camDir).GetNormalized(); - mMovementPlaneNormal = thirdAxis.Cross(mMovementDirection).GetNormalized(); - thirdAxis = mMovementPlaneNormal.Cross(mMovementDirection).GetNormalized(); + AZ::Vector3 thirdAxis = m_movementDirection.Cross(camDir).GetNormalized(); + m_movementPlaneNormal = thirdAxis.Cross(m_movementDirection).GetNormalized(); + thirdAxis = m_movementPlaneNormal.Cross(m_movementDirection).GetNormalized(); - MCore::PlaneEq movementPlane(mMovementPlaneNormal, mPosition); - MCore::PlaneEq movementPlane2(thirdAxis, mPosition); + MCore::PlaneEq movementPlane(m_movementPlaneNormal, m_position); + MCore::PlaneEq movementPlane2(thirdAxis, m_position); // calculate the intersection points of the mouse positions with the previously calculated plane AZ::Vector3 mousePosIntersect, mousePosIntersect2; @@ -356,44 +350,44 @@ namespace MCommon if (mousePosIntersect.GetLength() < camera->GetFarClipDistance()) { - if (MCore::Math::IsFloatZero(MCore::SafeLength(mMousePosRelative))) + if (MCore::Math::IsFloatZero(MCore::SafeLength(m_mousePosRelative))) { - mMousePosRelative = movementPlane2.Project(mousePosIntersect) - mPosition; + m_mousePosRelative = movementPlane2.Project(mousePosIntersect) - m_position; } mousePosIntersect = movementPlane2.Project(mousePosIntersect); } else { - if (MCore::Math::IsFloatZero(MCore::SafeLength(mMousePosRelative))) + if (MCore::Math::IsFloatZero(MCore::SafeLength(m_mousePosRelative))) { - mMousePosRelative = movementPlane.Project(mousePosIntersect2) - mPosition; + m_mousePosRelative = movementPlane.Project(mousePosIntersect2) - m_position; } mousePosIntersect = movementPlane.Project(mousePosIntersect2); } // adjust the movement vector - movement = mousePosIntersect - mMousePosRelative; + movement = mousePosIntersect - m_mousePosRelative; } // update the position of the gizmo - movement = movement - mPosition; - movement = AZ::Vector3(movement.GetX() * mMovementDirection.GetX(), movement.GetY() * mMovementDirection.GetY(), movement.GetZ() * mMovementDirection.GetZ()); - mPosition += movement; + movement = movement - m_position; + movement = AZ::Vector3(movement.GetX() * m_movementDirection.GetX(), movement.GetY() * m_movementDirection.GetY(), movement.GetZ() * m_movementDirection.GetZ()); + m_position += movement; // update the callback - if (mCallback) + if (m_callback) { // reset the callback position, if the position is too far away from the camera float farClip = camera->GetFarClipDistance(); - if (mPosition.GetLength() >= farClip) + if (m_position.GetLength() >= farClip) { - mPosition = mCallback->GetOldValueVec() + mRenderOffset; + m_position = m_callback->GetOldValueVec() + m_renderOffset; } // update the callback - mCallback->Update(GetPosition()); + m_callback->Update(GetPosition()); } } } // namespace MCommon diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/TranslateManipulator.h b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/TranslateManipulator.h index 7bc0bacfe0..4b916f43b7 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/TranslateManipulator.h +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/TranslateManipulator.h @@ -91,24 +91,24 @@ namespace MCommon protected: // bounding volumes for the axes - MCore::AABB mXAxisAABB; - MCore::AABB mYAxisAABB; - MCore::AABB mZAxisAABB; - MCore::AABB mXYPlaneAABB; - MCore::AABB mXZPlaneAABB; - MCore::AABB mYZPlaneAABB; + MCore::AABB m_xAxisAabb; + MCore::AABB m_yAxisAabb; + MCore::AABB m_zAxisAabb; + MCore::AABB m_xyPlaneAabb; + MCore::AABB m_xzPlaneAabb; + MCore::AABB m_yzPlaneAabb; // the scaling factors for the translate manipulator - float mSize; - float mArrowLength; - float mBaseRadius; - float mPlaneSelectorPos; - AZ::Vector3 mMovementPlaneNormal; - AZ::Vector3 mMovementDirection; - AZ::Vector3 mMousePosRelative; - bool mXAxisVisible; - bool mYAxisVisible; - bool mZAxisVisible; + float m_size; + float m_arrowLength; + float m_baseRadius; + float m_planeSelectorPos; + AZ::Vector3 m_movementPlaneNormal; + AZ::Vector3 m_movementDirection; + AZ::Vector3 m_mousePosRelative; + bool m_xAxisVisible; + bool m_yAxisVisible; + bool m_zAxisVisible; }; } // namespace MCommon diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GBuffer.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GBuffer.cpp index 3e2a25fe80..297bf01638 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GBuffer.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GBuffer.cpp @@ -22,20 +22,20 @@ namespace RenderGL // constructor GBuffer::GBuffer() { - mFBO = 0; - mDepthBufferID = 0; - mWidth = 100; - mHeight = 100; + m_fbo = 0; + m_depthBufferId = 0; + m_width = 100; + m_height = 100; - mRenderTargetA = nullptr; - mRenderTargetB = nullptr; - mRenderTargetC = nullptr; - mRenderTargetD = nullptr; - mRenderTargetE = nullptr; + m_renderTargetA = nullptr; + m_renderTargetB = nullptr; + m_renderTargetC = nullptr; + m_renderTargetD = nullptr; + m_renderTargetE = nullptr; for (uint32 i = 0; i < NUM_COMPONENTS; ++i) { - mComponents[i] = 0; + m_components[i] = 0; } } @@ -62,48 +62,48 @@ namespace RenderGL return false; } - mWidth = width; - mHeight = height; + m_width = width; + m_height = height; // create the FBO - glGenFramebuffers(1, &mFBO); + glGenFramebuffers(1, &m_fbo); for (uint32 i = 0; i < NUM_COMPONENTS; ++i) { - glGenTextures(1, &mComponents[i]); + glGenTextures(1, &m_components[i]); } - glGenTextures(1, &mDepthBufferID); + glGenTextures(1, &m_depthBufferId); // bind the fbo - glBindFramebuffer(GL_FRAMEBUFFER, mFBO); + glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); // init normals texture - glBindTexture(GL_TEXTURE_2D, mComponents[COMPONENT_SHADED]); + glBindTexture(GL_TEXTURE_2D, m_components[COMPONENT_SHADED]); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA, GL_FLOAT, nullptr); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mComponents[COMPONENT_SHADED], 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_components[COMPONENT_SHADED], 0); // init glow color texture - glBindTexture(GL_TEXTURE_2D, mComponents[COMPONENT_GLOW]); + glBindTexture(GL_TEXTURE_2D, m_components[COMPONENT_GLOW]); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA, GL_FLOAT, nullptr); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, mComponents[COMPONENT_GLOW], 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, m_components[COMPONENT_GLOW], 0); // init the depth buffer - glBindTexture(GL_TEXTURE_2D, mDepthBufferID); + glBindTexture(GL_TEXTURE_2D, m_depthBufferId); glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, width, height, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, nullptr); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, mDepthBufferID, 0); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, mDepthBufferID, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_depthBufferId, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_depthBufferId, 0); // unbind glBindTexture(GL_TEXTURE_2D, 0); @@ -131,28 +131,28 @@ namespace RenderGL // release void GBuffer::Release() { - if (mFBO) + if (m_fbo) { - glDeleteFramebuffers(1, &mFBO); + glDeleteFramebuffers(1, &m_fbo); for (uint32 i = 0; i < NUM_COMPONENTS; ++i) { - glDeleteTextures(1, &mComponents[i]); + glDeleteTextures(1, &m_components[i]); } - glDeleteTextures(1, &mDepthBufferID); + glDeleteTextures(1, &m_depthBufferId); } - delete mRenderTargetA; - delete mRenderTargetB; - delete mRenderTargetC; - delete mRenderTargetD; - delete mRenderTargetE; + delete m_renderTargetA; + delete m_renderTargetB; + delete m_renderTargetC; + delete m_renderTargetD; + delete m_renderTargetE; - mRenderTargetA = nullptr; - mRenderTargetB = nullptr; - mRenderTargetC = nullptr; - mRenderTargetD = nullptr; - mRenderTargetE = nullptr; + m_renderTargetA = nullptr; + m_renderTargetB = nullptr; + m_renderTargetC = nullptr; + m_renderTargetD = nullptr; + m_renderTargetE = nullptr; } @@ -167,39 +167,39 @@ namespace RenderGL // resize render textures bool GBuffer::ResizeTextures(uint32 screenWidth, uint32 screenHeight) { - delete mRenderTargetA; - delete mRenderTargetB; - delete mRenderTargetC; - delete mRenderTargetD; - delete mRenderTargetE; + delete m_renderTargetA; + delete m_renderTargetB; + delete m_renderTargetC; + delete m_renderTargetD; + delete m_renderTargetE; - mRenderTargetA = new RenderTexture(); - mRenderTargetB = new RenderTexture(); - mRenderTargetC = new RenderTexture(); - mRenderTargetD = new RenderTexture(); - mRenderTargetE = new RenderTexture(); + m_renderTargetA = new RenderTexture(); + m_renderTargetB = new RenderTexture(); + m_renderTargetC = new RenderTexture(); + m_renderTargetD = new RenderTexture(); + m_renderTargetE = new RenderTexture(); - if (mRenderTargetA->Init(GL_RGBA16F, screenWidth, screenHeight) == false) + if (m_renderTargetA->Init(GL_RGBA16F, screenWidth, screenHeight) == false) { return false; } - if (mRenderTargetB->Init(GL_RGBA16F, screenWidth, screenHeight) == false) + if (m_renderTargetB->Init(GL_RGBA16F, screenWidth, screenHeight) == false) { return false; } - if (mRenderTargetC->Init(GL_RGBA16F, screenWidth, screenHeight) == false) + if (m_renderTargetC->Init(GL_RGBA16F, screenWidth, screenHeight) == false) { return false; } - if (mRenderTargetD->Init(GL_RGBA16F, screenWidth / 2, screenHeight / 2) == false) + if (m_renderTargetD->Init(GL_RGBA16F, screenWidth / 2, screenHeight / 2) == false) { return false; } - if (mRenderTargetE->Init(GL_RGBA16F, screenWidth / 2, screenHeight / 2) == false) + if (m_renderTargetE->Init(GL_RGBA16F, screenWidth / 2, screenHeight / 2) == false) { return false; } @@ -213,16 +213,10 @@ namespace RenderGL { glPushAttrib(GL_VIEWPORT_BIT | GL_COLOR_BUFFER_BIT); - // get the width and height of the current used viewport - //float glDimensions[4]; - //glGetFloatv( GL_VIEWPORT, glDimensions ); - //mPrevWidth = (uint32)glDimensions[2]; - //mPrevHeight = (uint32)glDimensions[3]; - // bind the render texture and frame buffer glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, 0); - glBindFramebuffer(GL_FRAMEBUFFER, mFBO); + glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); GLenum bufs[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 }; glDrawBuffers(2, bufs); @@ -234,14 +228,14 @@ namespace RenderGL } // setup the new viewport - glViewport(0, 0, mWidth, mHeight); + glViewport(0, 0, m_width, m_height); } // clear void GBuffer::Clear(const MCore::RGBAColor& color) { - glClearColor(color.r, color.g, color.b, 1.0f); + glClearColor(color.m_r, color.m_g, color.m_b, 1.0f); glClearDepth(1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); } @@ -252,16 +246,9 @@ namespace RenderGL { glPopAttrib(); - //GLenum bufs[] = { GL_COLOR_ATTACHMENT0 }; - //glDrawBuffers( 1, bufs); - // undbind the frame buffer glBindFramebuffer(GL_FRAMEBUFFER, 0); - // reset viewport to original dimensions - //glViewport( 0, 0, mPrevWidth, mPrevHeight ); - //GetGraphicsManager()->SetRenderTexture(nullptr); - glEnable(GL_TEXTURE_2D); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE0, 0); @@ -278,12 +265,12 @@ namespace RenderGL //----------------------------- // render the main image //----------------------------- - glBindTexture(GL_TEXTURE_2D, mComponents[COMPONENT_SHADED]); + glBindTexture(GL_TEXTURE_2D, m_components[COMPONENT_SHADED]); // setup ortho projection glMatrixMode(GL_PROJECTION); glLoadIdentity(); - glOrtho(0, mWidth, mHeight, 0, -1, 1); + glOrtho(0, m_width, m_height, 0, -1, 1); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); @@ -298,15 +285,15 @@ namespace RenderGL glColor3f(1.0f, 1.0f, 1.0f); glTexCoord2f(1.0f, 1.0f); - glVertex2f(static_cast(mWidth), 0.0f); + glVertex2f(static_cast(m_width), 0.0f); glColor3f(1.0f, 1.0f, 1.0f); glTexCoord2f(1.0f, 0.0f); - glVertex2f(static_cast(mWidth), static_cast(mHeight)); + glVertex2f(static_cast(m_width), static_cast(m_height)); glColor3f(1.0f, 1.0f, 1.0f); glTexCoord2f(0.0f, 0.0f); - glVertex2f(0.0f, static_cast(mHeight)); + glVertex2f(0.0f, static_cast(m_height)); glColor3f(1.0f, 1.0f, 1.0f); glEnd(); @@ -320,14 +307,14 @@ namespace RenderGL // render the small images //----------------------------- uint32 xStart = 10; - uint32 yStart = mHeight - 110; + uint32 yStart = m_height - 110; for (uint32 i = 0; i < NUM_COMPONENTS; ++i) { - glBindTexture(GL_TEXTURE_2D, mComponents[i]); + glBindTexture(GL_TEXTURE_2D, m_components[i]); - const float w = static_cast(mWidth); - const float h = static_cast(mHeight); + const float w = static_cast(m_width); + const float h = static_cast(m_height); // Setup ortho projection glMatrixMode(GL_PROJECTION); diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GBuffer.h b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GBuffer.h index 40b40fea45..cce01485e0 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GBuffer.h +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GBuffer.h @@ -50,32 +50,30 @@ namespace RenderGL void Render(); - MCORE_INLINE uint32 GetTextureID(EComponent component) const { return mComponents[component]; } + MCORE_INLINE uint32 GetTextureID(EComponent component) const { return m_components[component]; } bool Resize(uint32 width, uint32 height); bool ResizeTextures(uint32 screenWidth, uint32 screenHeight); - MCORE_INLINE RenderTexture* GetRenderTargetA() { return mRenderTargetA; } - MCORE_INLINE RenderTexture* GetRenderTargetB() { return mRenderTargetB; } - MCORE_INLINE RenderTexture* GetRenderTargetC() { return mRenderTargetC; } - MCORE_INLINE RenderTexture* GetRenderTargetD() { return mRenderTargetD; } - MCORE_INLINE RenderTexture* GetRenderTargetE() { return mRenderTargetE; } + MCORE_INLINE RenderTexture* GetRenderTargetA() { return m_renderTargetA; } + MCORE_INLINE RenderTexture* GetRenderTargetB() { return m_renderTargetB; } + MCORE_INLINE RenderTexture* GetRenderTargetC() { return m_renderTargetC; } + MCORE_INLINE RenderTexture* GetRenderTargetD() { return m_renderTargetD; } + MCORE_INLINE RenderTexture* GetRenderTargetE() { return m_renderTargetE; } private: - uint32 mFBO; - uint32 mComponents[NUM_COMPONENTS]; - uint32 mDepthBufferID; - //uint32 mPrevWidth; - //uint32 mPrevHeight; - uint32 mWidth; - uint32 mHeight; + uint32 m_fbo; + uint32 m_components[NUM_COMPONENTS]; + uint32 m_depthBufferId; + uint32 m_width; + uint32 m_height; - RenderTexture* mRenderTargetA; /**< A temp render target. */ - RenderTexture* mRenderTargetB; /**< A temp render target. */ - RenderTexture* mRenderTargetC; /**< A temp render target. */ - RenderTexture* mRenderTargetD; /**< Render target with width and height divided by four. */ - RenderTexture* mRenderTargetE; /**< Render target with width and height divided by four. */ + RenderTexture* m_renderTargetA; /**< A temp render target. */ + RenderTexture* m_renderTargetB; /**< A temp render target. */ + RenderTexture* m_renderTargetC; /**< A temp render target. */ + RenderTexture* m_renderTargetD; /**< Render target with width and height divided by four. */ + RenderTexture* m_renderTargetE; /**< Render target with width and height divided by four. */ }; } // namespace RenderGL diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLActor.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLActor.cpp index f7f21629a3..15be9676c1 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLActor.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLActor.cpp @@ -23,12 +23,12 @@ namespace RenderGL // constructor GLActor::GLActor() { - mEnableGPUSkinning = true; - mActor = nullptr; - mEnableGPUSkinning = true; + m_enableGpuSkinning = true; + m_actor = nullptr; + m_enableGpuSkinning = true; - mSkyColor = MCore::RGBAColor(0.55f, 0.55f, 0.55f); - mGroundColor = MCore::RGBAColor(0.117f, 0.015f, 0.07f); + m_skyColor = MCore::RGBAColor(0.55f, 0.55f, 0.55f); + m_groundColor = MCore::RGBAColor(0.117f, 0.015f, 0.07f); } @@ -57,14 +57,14 @@ namespace RenderGL void GLActor::Cleanup() { // get rid of all index and vertex buffers - for (AZStd::vector& vertexBuffers : mVertexBuffers) + for (AZStd::vector& vertexBuffers : m_vertexBuffers) { for (VertexBuffer* vertexBuffer : vertexBuffers) { delete vertexBuffer; } } - for (AZStd::vector& indexBuffers : mIndexBuffers) + for (AZStd::vector& indexBuffers : m_indexBuffers) { for (IndexBuffer* indexBuffer : indexBuffers) { @@ -73,11 +73,11 @@ namespace RenderGL } // delete all materials - for (AZStd::vector& materialsPerLod : mMaterials) + for (AZStd::vector& materialsPerLod : m_materials) { for (MaterialPrimitives* materialPrimitives : materialsPerLod) { - delete materialPrimitives->mMaterial; + delete materialPrimitives->m_material; delete materialPrimitives; } } @@ -88,7 +88,7 @@ namespace RenderGL EMotionFX::Mesh::EMeshType GLActor::ClassifyMeshType(EMotionFX::Node* node, EMotionFX::Mesh* mesh, size_t lodLevel) { MCORE_ASSERT(node && mesh); - return mesh->ClassifyMeshType(lodLevel, mActor, node->GetNodeIndex(), !mEnableGPUSkinning, 4, 200); + return mesh->ClassifyMeshType(lodLevel, m_actor, node->GetNodeIndex(), !m_enableGpuSkinning, 4, 200); } @@ -102,35 +102,35 @@ namespace RenderGL AZ::Debug::Timer initTimer; initTimer.Stamp(); - mActor = actor; - mEnableGPUSkinning = gpuSkinning; - mTexturePath = texturePath; + m_actor = actor; + m_enableGpuSkinning = gpuSkinning; + m_texturePath = texturePath; // get the number of nodes and geometry LOD levels const size_t numGeometryLODLevels = actor->GetNumLODLevels(); const size_t numNodes = actor->GetNumNodes(); // set the pre-allocation amount for the number of materials - mMaterials.resize(numGeometryLODLevels); + m_materials.resize(numGeometryLODLevels); // resize the vertex and index buffers - for (AZStd::vector& vertexBuffers : mVertexBuffers) + for (AZStd::vector& vertexBuffers : m_vertexBuffers) { vertexBuffers.resize(numGeometryLODLevels); AZStd::fill(begin(vertexBuffers), end(vertexBuffers), nullptr); } - for (AZStd::vector& indexBuffers : mIndexBuffers) + for (AZStd::vector& indexBuffers : m_indexBuffers) { indexBuffers.resize(numGeometryLODLevels); AZStd::fill(begin(indexBuffers), end(indexBuffers), nullptr); } - for (MCore::Array2D& primitives : mPrimitives) + for (MCore::Array2D& primitives : m_primitives) { primitives.Resize(numGeometryLODLevels); } - mHomoMaterials.resize(numGeometryLODLevels); - mDynamicNodes.Resize (numGeometryLODLevels); + m_homoMaterials.resize(numGeometryLODLevels); + m_dynamicNodes.Resize (numGeometryLODLevels); EMotionFX::Skeleton* skeleton = actor->GetSkeleton(); @@ -174,27 +174,27 @@ namespace RenderGL // create and add the primitive Primitive newPrimitive; - newPrimitive.mNodeIndex = n; - newPrimitive.mNumVertices = subMesh->GetNumVertices(); - newPrimitive.mNumTriangles = subMesh->CalcNumTriangles(); // subMesh->GetNumIndices() / 3; - newPrimitive.mIndexOffset = totalNumIndices[ meshType ]; - newPrimitive.mVertexOffset = totalNumVerts[ meshType ]; - newPrimitive.mMaterialIndex = 0; // Since GL actor only uses the default material, we should only pass in 0. + newPrimitive.m_nodeIndex = n; + newPrimitive.m_numVertices = subMesh->GetNumVertices(); + newPrimitive.m_numTriangles = subMesh->CalcNumTriangles(); // subMesh->GetNumIndices() / 3; + newPrimitive.m_indexOffset = totalNumIndices[ meshType ]; + newPrimitive.m_vertexOffset = totalNumVerts[ meshType ]; + newPrimitive.m_materialIndex = 0; // Since GL actor only uses the default material, we should only pass in 0. // copy over the used bones from the submesh if (subMesh->GetNumBones() > 0) { - newPrimitive.mBoneNodeIndices = subMesh->GetBonesArray(); + newPrimitive.m_boneNodeIndices = subMesh->GetBonesArray(); } // add to primitive list - mPrimitives[meshType].Add(lodLevel, newPrimitive); + m_primitives[meshType].Add(lodLevel, newPrimitive); // add to material list - MaterialPrimitives* materialPrims = mMaterials[lodLevel][newPrimitive.mMaterialIndex]; - materialPrims->mPrimitives[meshType].emplace_back(newPrimitive); + MaterialPrimitives* materialPrims = m_materials[lodLevel][newPrimitive.m_materialIndex]; + materialPrims->m_primitives[meshType].emplace_back(newPrimitive); - totalNumIndices[meshType] += newPrimitive.mNumTriangles * 3; + totalNumIndices[meshType] += newPrimitive.m_numTriangles * 3; totalNumVerts[meshType] += subMesh->GetNumVertices(); } @@ -202,7 +202,7 @@ namespace RenderGL // add dynamic meshes to the dynamic node list if (meshType == EMotionFX::Mesh::MESHTYPE_CPU_DEFORMED) { - mDynamicNodes.Add(lodLevel, node->GetNodeIndex()); + m_dynamicNodes.Add(lodLevel, node->GetNodeIndex()); } } @@ -210,11 +210,11 @@ namespace RenderGL const size_t numDynamicBytes = sizeof(StandardVertex) * totalNumVerts[EMotionFX::Mesh::MESHTYPE_CPU_DEFORMED]; if (numDynamicBytes > 0) { - mVertexBuffers[EMotionFX::Mesh::MESHTYPE_CPU_DEFORMED][lodLevel] = new VertexBuffer(); - mIndexBuffers [EMotionFX::Mesh::MESHTYPE_CPU_DEFORMED][lodLevel] = new IndexBuffer(); + m_vertexBuffers[EMotionFX::Mesh::MESHTYPE_CPU_DEFORMED][lodLevel] = new VertexBuffer(); + m_indexBuffers [EMotionFX::Mesh::MESHTYPE_CPU_DEFORMED][lodLevel] = new IndexBuffer(); - const bool vbSuccess = mVertexBuffers[EMotionFX::Mesh::MESHTYPE_CPU_DEFORMED][lodLevel]->Init(sizeof(StandardVertex), totalNumVerts[EMotionFX::Mesh::MESHTYPE_CPU_DEFORMED], USAGE_DYNAMIC); - const bool ibSuccess = mIndexBuffers [EMotionFX::Mesh::MESHTYPE_CPU_DEFORMED][lodLevel]->Init(IndexBuffer::INDEXSIZE_32BIT, totalNumIndices[EMotionFX::Mesh::MESHTYPE_CPU_DEFORMED], USAGE_STATIC); + const bool vbSuccess = m_vertexBuffers[EMotionFX::Mesh::MESHTYPE_CPU_DEFORMED][lodLevel]->Init(sizeof(StandardVertex), totalNumVerts[EMotionFX::Mesh::MESHTYPE_CPU_DEFORMED], USAGE_DYNAMIC); + const bool ibSuccess = m_indexBuffers [EMotionFX::Mesh::MESHTYPE_CPU_DEFORMED][lodLevel]->Init(IndexBuffer::INDEXSIZE_32BIT, totalNumIndices[EMotionFX::Mesh::MESHTYPE_CPU_DEFORMED], USAGE_STATIC); // check if the vertex and index buffers are valid if (vbSuccess == false || ibSuccess == false) @@ -228,11 +228,11 @@ namespace RenderGL const size_t numStaticBytes = sizeof(StandardVertex) * totalNumVerts[EMotionFX::Mesh::MESHTYPE_STATIC]; if (numStaticBytes > 0) { - mVertexBuffers[EMotionFX::Mesh::MESHTYPE_STATIC][lodLevel] = new VertexBuffer(); - mIndexBuffers [EMotionFX::Mesh::MESHTYPE_STATIC][lodLevel] = new IndexBuffer(); + m_vertexBuffers[EMotionFX::Mesh::MESHTYPE_STATIC][lodLevel] = new VertexBuffer(); + m_indexBuffers [EMotionFX::Mesh::MESHTYPE_STATIC][lodLevel] = new IndexBuffer(); - const bool vbSuccess = mVertexBuffers[EMotionFX::Mesh::MESHTYPE_STATIC][lodLevel]->Init(sizeof(StandardVertex), totalNumVerts[EMotionFX::Mesh::MESHTYPE_STATIC], USAGE_STATIC); - const bool ibSuccess = mIndexBuffers [EMotionFX::Mesh::MESHTYPE_STATIC][lodLevel]->Init(IndexBuffer::INDEXSIZE_32BIT, totalNumIndices[EMotionFX::Mesh::MESHTYPE_STATIC], USAGE_STATIC); + const bool vbSuccess = m_vertexBuffers[EMotionFX::Mesh::MESHTYPE_STATIC][lodLevel]->Init(sizeof(StandardVertex), totalNumVerts[EMotionFX::Mesh::MESHTYPE_STATIC], USAGE_STATIC); + const bool ibSuccess = m_indexBuffers [EMotionFX::Mesh::MESHTYPE_STATIC][lodLevel]->Init(IndexBuffer::INDEXSIZE_32BIT, totalNumIndices[EMotionFX::Mesh::MESHTYPE_STATIC], USAGE_STATIC); // check if the vertex and index buffers are valid if (vbSuccess == false || ibSuccess == false) @@ -246,11 +246,11 @@ namespace RenderGL const size_t numSkinnedBytes = sizeof(SkinnedVertex) * totalNumVerts[EMotionFX::Mesh::MESHTYPE_GPU_DEFORMED]; if (numSkinnedBytes > 0) { - mVertexBuffers[EMotionFX::Mesh::MESHTYPE_GPU_DEFORMED][lodLevel] = new VertexBuffer(); - mIndexBuffers [EMotionFX::Mesh::MESHTYPE_GPU_DEFORMED][lodLevel] = new IndexBuffer(); + m_vertexBuffers[EMotionFX::Mesh::MESHTYPE_GPU_DEFORMED][lodLevel] = new VertexBuffer(); + m_indexBuffers [EMotionFX::Mesh::MESHTYPE_GPU_DEFORMED][lodLevel] = new IndexBuffer(); - const bool vbSuccess = mVertexBuffers[EMotionFX::Mesh::MESHTYPE_GPU_DEFORMED][lodLevel]->Init(sizeof(SkinnedVertex), totalNumVerts[EMotionFX::Mesh::MESHTYPE_GPU_DEFORMED], USAGE_STATIC); - const bool ibSuccess = mIndexBuffers [EMotionFX::Mesh::MESHTYPE_GPU_DEFORMED][lodLevel]->Init(IndexBuffer::INDEXSIZE_32BIT, totalNumIndices[EMotionFX::Mesh::MESHTYPE_GPU_DEFORMED], USAGE_STATIC); + const bool vbSuccess = m_vertexBuffers[EMotionFX::Mesh::MESHTYPE_GPU_DEFORMED][lodLevel]->Init(sizeof(SkinnedVertex), totalNumVerts[EMotionFX::Mesh::MESHTYPE_GPU_DEFORMED], USAGE_STATIC); + const bool ibSuccess = m_indexBuffers [EMotionFX::Mesh::MESHTYPE_GPU_DEFORMED][lodLevel]->Init(IndexBuffer::INDEXSIZE_32BIT, totalNumIndices[EMotionFX::Mesh::MESHTYPE_GPU_DEFORMED], USAGE_STATIC); // check if the vertex and index buffers are valid if (vbSuccess == false || ibSuccess == false) @@ -344,7 +344,7 @@ namespace RenderGL // fallback to standard material MCore::LogWarning("[OpenGL] Cannot initialize OpenGL material for material '%s'. Falling back to default material.", emfxMaterial->GetName()); StandardMaterial* material = new RenderGL::StandardMaterial(this); - material->Init((EMotionFX::StandardMaterial*)mActor->GetMaterial(0, 0)); + material->Init((EMotionFX::StandardMaterial*)m_actor->GetMaterial(0, 0)); return material; } } @@ -354,12 +354,12 @@ namespace RenderGL void GLActor::InitMaterials(size_t lodLevel) { // get the number of materials and iterate through them - const size_t numMaterials = mActor->GetNumMaterials(lodLevel); + const size_t numMaterials = m_actor->GetNumMaterials(lodLevel); for (size_t m = 0; m < numMaterials; ++m) { - EMotionFX::Material* emfxMaterial = mActor->GetMaterial(lodLevel, m); + EMotionFX::Material* emfxMaterial = m_actor->GetMaterial(lodLevel, m); Material* material = InitMaterial(emfxMaterial); - mMaterials[lodLevel].emplace_back( new MaterialPrimitives(material) ); + m_materials[lodLevel].emplace_back( new MaterialPrimitives(material) ); } } @@ -367,13 +367,13 @@ namespace RenderGL // render the given actor instance void GLActor::Render(EMotionFX::ActorInstance* actorInstance, uint32 renderFlags) { - if (!mActor->IsReady()) + if (!m_actor->IsReady()) { return; } // make sure our actor instance is valid and that we initialized the gl actor - assert(mActor && actorInstance); + assert(m_actor && actorInstance); // update the dynamic vertices (copy dynamic vertices from system memory into the vertex buffer) UpdateDynamicVertices(actorInstance); @@ -398,36 +398,36 @@ namespace RenderGL void GLActor::RenderMeshes(EMotionFX::ActorInstance* actorInstance, EMotionFX::Mesh::EMeshType meshType, uint32 renderFlags) { const size_t lodLevel = actorInstance->GetLODLevel(); - const size_t numMaterials = mMaterials[lodLevel].size(); + const size_t numMaterials = m_materials[lodLevel].size(); if (numMaterials == 0) { return; } - if (mVertexBuffers[meshType][lodLevel] == nullptr || mIndexBuffers[meshType][lodLevel] == nullptr) + if (m_vertexBuffers[meshType][lodLevel] == nullptr || m_indexBuffers[meshType][lodLevel] == nullptr) { return; } - if (mVertexBuffers[meshType][lodLevel]->GetBufferID() == MCORE_INVALIDINDEX32) + if (m_vertexBuffers[meshType][lodLevel]->GetBufferID() == MCORE_INVALIDINDEX32) { return; } // activate vertex and index buffers - mVertexBuffers[meshType][lodLevel]->Activate(); - mIndexBuffers[meshType][lodLevel]->Activate(); + m_vertexBuffers[meshType][lodLevel]->Activate(); + m_indexBuffers[meshType][lodLevel]->Activate(); // render all the primitives in each material - for (const MaterialPrimitives* materialPrims : mMaterials[lodLevel]) + for (const MaterialPrimitives* materialPrims : m_materials[lodLevel]) { - if (materialPrims->mPrimitives[meshType].empty()) + if (materialPrims->m_primitives[meshType].empty()) { continue; } - Material* material = materialPrims->mMaterial; + Material* material = materialPrims->m_material; if (material == nullptr) { continue; @@ -443,7 +443,7 @@ namespace RenderGL material->Activate(activationFlags); // render all primitives - for (const Primitive& primitive : materialPrims->mPrimitives[meshType]) + for (const Primitive& primitive : materialPrims->m_primitives[meshType]) { material->Render(actorInstance, &primitive); } @@ -458,19 +458,19 @@ namespace RenderGL { // get the number of dynamic nodes const size_t lodLevel = actorInstance->GetLODLevel(); - const size_t numNodes = mDynamicNodes.GetNumElements(lodLevel); + const size_t numNodes = m_dynamicNodes.GetNumElements(lodLevel); if (numNodes == 0) { return; } - if (mVertexBuffers[EMotionFX::Mesh::MESHTYPE_CPU_DEFORMED][lodLevel] == nullptr) + if (m_vertexBuffers[EMotionFX::Mesh::MESHTYPE_CPU_DEFORMED][lodLevel] == nullptr) { return; } // lock the dynamic vertex buffer - StandardVertex* dynamicVertices = (StandardVertex*)mVertexBuffers[EMotionFX::Mesh::MESHTYPE_CPU_DEFORMED][lodLevel]->Lock(LOCK_WRITEONLY); + StandardVertex* dynamicVertices = (StandardVertex*)m_vertexBuffers[EMotionFX::Mesh::MESHTYPE_CPU_DEFORMED][lodLevel]->Lock(LOCK_WRITEONLY); if (dynamicVertices == nullptr) { return; @@ -483,8 +483,8 @@ namespace RenderGL for (size_t n = 0; n < numNodes; ++n) { // get the node and its mesh - const size_t nodeIndex = mDynamicNodes.GetElement(lodLevel, n); - EMotionFX::Mesh* mesh = mActor->GetMesh(lodLevel, nodeIndex); + const size_t nodeIndex = m_dynamicNodes.GetElement(lodLevel, n); + EMotionFX::Mesh* mesh = m_actor->GetMesh(lodLevel, nodeIndex); // is the mesh valid? if (mesh == nullptr) @@ -503,10 +503,10 @@ namespace RenderGL { for (uint32 v = 0; v < numVertices; ++v) { - dynamicVertices[globalVert].mPosition = positions[v]; - dynamicVertices[globalVert].mNormal = normals[v]; - dynamicVertices[globalVert].mUV = uvsA[v]; - dynamicVertices[globalVert].mTangent = (tangents) ? tangents[v] : AZ::Vector4(0.0f, 0.0f, 1.0f, 1.0f); + dynamicVertices[globalVert].m_position = positions[v]; + dynamicVertices[globalVert].m_normal = normals[v]; + dynamicVertices[globalVert].m_uv = uvsA[v]; + dynamicVertices[globalVert].m_tangent = (tangents) ? tangents[v] : AZ::Vector4(0.0f, 0.0f, 1.0f, 1.0f); globalVert++; } } @@ -514,17 +514,17 @@ namespace RenderGL { for (uint32 v = 0; v < numVertices; ++v) { - dynamicVertices[globalVert].mPosition = positions[v]; - dynamicVertices[globalVert].mNormal = normals[v]; - dynamicVertices[globalVert].mUV = AZ::Vector2(0.0f, 0.0f); - dynamicVertices[globalVert].mTangent = (tangents) ? tangents[v] : AZ::Vector4(0.0f, 0.0f, 1.0f, 1.0f); + dynamicVertices[globalVert].m_position = positions[v]; + dynamicVertices[globalVert].m_normal = normals[v]; + dynamicVertices[globalVert].m_uv = AZ::Vector2(0.0f, 0.0f); + dynamicVertices[globalVert].m_tangent = (tangents) ? tangents[v] : AZ::Vector4(0.0f, 0.0f, 1.0f, 1.0f); globalVert++; } } } // unlock the vertex buffer - mVertexBuffers[EMotionFX::Mesh::MESHTYPE_CPU_DEFORMED][lodLevel]->Unlock(); + m_vertexBuffers[EMotionFX::Mesh::MESHTYPE_CPU_DEFORMED][lodLevel]->Unlock(); } @@ -537,23 +537,23 @@ namespace RenderGL uint32* skinnedIndices = nullptr; // lock the index buffers - if (mIndexBuffers[EMotionFX::Mesh::MESHTYPE_STATIC][lodLevel]) + if (m_indexBuffers[EMotionFX::Mesh::MESHTYPE_STATIC][lodLevel]) { - staticIndices = (uint32*)mIndexBuffers[EMotionFX::Mesh::MESHTYPE_STATIC][lodLevel]->Lock(LOCK_WRITEONLY); + staticIndices = (uint32*)m_indexBuffers[EMotionFX::Mesh::MESHTYPE_STATIC][lodLevel]->Lock(LOCK_WRITEONLY); } - if (mIndexBuffers[EMotionFX::Mesh::MESHTYPE_CPU_DEFORMED][lodLevel]) + if (m_indexBuffers[EMotionFX::Mesh::MESHTYPE_CPU_DEFORMED][lodLevel]) { - dynamicIndices = (uint32*)mIndexBuffers[EMotionFX::Mesh::MESHTYPE_CPU_DEFORMED][lodLevel]->Lock(LOCK_WRITEONLY); + dynamicIndices = (uint32*)m_indexBuffers[EMotionFX::Mesh::MESHTYPE_CPU_DEFORMED][lodLevel]->Lock(LOCK_WRITEONLY); } - if (mIndexBuffers[EMotionFX::Mesh::MESHTYPE_GPU_DEFORMED][lodLevel]) + if (m_indexBuffers[EMotionFX::Mesh::MESHTYPE_GPU_DEFORMED][lodLevel]) { - skinnedIndices = (uint32*)mIndexBuffers[EMotionFX::Mesh::MESHTYPE_GPU_DEFORMED][lodLevel]->Lock(LOCK_WRITEONLY); + skinnedIndices = (uint32*)m_indexBuffers[EMotionFX::Mesh::MESHTYPE_GPU_DEFORMED][lodLevel]->Lock(LOCK_WRITEONLY); } //if (staticIndices == nullptr || dynamicIndices == nullptr || skinnedIndices == nullptr) - if ((mIndexBuffers[EMotionFX::Mesh::MESHTYPE_STATIC][lodLevel] && staticIndices == nullptr) || - (mIndexBuffers[EMotionFX::Mesh::MESHTYPE_CPU_DEFORMED][lodLevel] && dynamicIndices == nullptr) || - (mIndexBuffers[EMotionFX::Mesh::MESHTYPE_GPU_DEFORMED][lodLevel] && skinnedIndices == nullptr)) + if ((m_indexBuffers[EMotionFX::Mesh::MESHTYPE_STATIC][lodLevel] && staticIndices == nullptr) || + (m_indexBuffers[EMotionFX::Mesh::MESHTYPE_CPU_DEFORMED][lodLevel] && dynamicIndices == nullptr) || + (m_indexBuffers[EMotionFX::Mesh::MESHTYPE_GPU_DEFORMED][lodLevel] && skinnedIndices == nullptr)) { MCore::LogWarning("[OpenGL] Cannot lock index buffers in GLActor::FillIndexBuffers."); return; @@ -567,17 +567,17 @@ namespace RenderGL uint32 staticOffset = 0; uint32 gpuSkinnedOffset = 0; - EMotionFX::Skeleton* skeleton = mActor->GetSkeleton(); + EMotionFX::Skeleton* skeleton = m_actor->GetSkeleton(); // get the number of nodes and iterate through them - const size_t numNodes = mActor->GetNumNodes(); + const size_t numNodes = m_actor->GetNumNodes(); for (size_t n = 0; n < numNodes; ++n) { // get the current node EMotionFX::Node* node = skeleton->GetNode(n); // get the mesh for the node, if there is any - EMotionFX::Mesh* mesh = mActor->GetMesh(lodLevel, n); + EMotionFX::Mesh* mesh = m_actor->GetMesh(lodLevel, n); if (mesh == nullptr) { continue; @@ -662,15 +662,15 @@ namespace RenderGL // unlock the buffers if (staticIndices) { - mIndexBuffers[EMotionFX::Mesh::MESHTYPE_STATIC][lodLevel]->Unlock(); + m_indexBuffers[EMotionFX::Mesh::MESHTYPE_STATIC][lodLevel]->Unlock(); } if (dynamicIndices) { - mIndexBuffers[EMotionFX::Mesh::MESHTYPE_CPU_DEFORMED][lodLevel]->Unlock(); + m_indexBuffers[EMotionFX::Mesh::MESHTYPE_CPU_DEFORMED][lodLevel]->Unlock(); } if (skinnedIndices) { - mIndexBuffers[EMotionFX::Mesh::MESHTYPE_GPU_DEFORMED][lodLevel]->Unlock(); + m_indexBuffers[EMotionFX::Mesh::MESHTYPE_GPU_DEFORMED][lodLevel]->Unlock(); } } @@ -678,22 +678,22 @@ namespace RenderGL // fill the static vertex buffer void GLActor::FillStaticVertexBuffers(size_t lodLevel) { - if (mVertexBuffers[EMotionFX::Mesh::MESHTYPE_STATIC][lodLevel] == nullptr) + if (m_vertexBuffers[EMotionFX::Mesh::MESHTYPE_STATIC][lodLevel] == nullptr) { return; } // get the number of nodes - const size_t numNodes = mActor->GetNumNodes(); + const size_t numNodes = m_actor->GetNumNodes(); if (numNodes == 0) { return; } - EMotionFX::Skeleton* skeleton = mActor->GetSkeleton(); + EMotionFX::Skeleton* skeleton = m_actor->GetSkeleton(); // lock the static vertex buffer - StandardVertex* staticVertices = (StandardVertex*)mVertexBuffers[EMotionFX::Mesh::MESHTYPE_STATIC][lodLevel]->Lock(LOCK_WRITEONLY); + StandardVertex* staticVertices = (StandardVertex*)m_vertexBuffers[EMotionFX::Mesh::MESHTYPE_STATIC][lodLevel]->Lock(LOCK_WRITEONLY); if (staticVertices == nullptr) { return; @@ -709,7 +709,7 @@ namespace RenderGL EMotionFX::Node* node = skeleton->GetNode(n); // get the mesh for the node, if there is any - EMotionFX::Mesh* mesh = mActor->GetMesh(lodLevel, n); + EMotionFX::Mesh* mesh = m_actor->GetMesh(lodLevel, n); if (mesh == nullptr) { continue; @@ -739,10 +739,10 @@ namespace RenderGL const uint32 numVerts = mesh->GetNumVertices(); for (uint32 v = 0; v < numVerts; ++v) { - staticVertices[globalVert].mPosition = positions[v]; - staticVertices[globalVert].mNormal = normals[v]; - staticVertices[globalVert].mUV = uvsA[v]; - staticVertices[globalVert].mTangent = (tangents) ? tangents[v] : AZ::Vector4(0.0f, 0.0f, 1.0f, 1.0f); + staticVertices[globalVert].m_position = positions[v]; + staticVertices[globalVert].m_normal = normals[v]; + staticVertices[globalVert].m_uv = uvsA[v]; + staticVertices[globalVert].m_tangent = (tangents) ? tangents[v] : AZ::Vector4(0.0f, 0.0f, 1.0f, 1.0f); globalVert++; } } @@ -751,39 +751,39 @@ namespace RenderGL const uint32 numVerts = mesh->GetNumVertices(); for (uint32 v = 0; v < numVerts; ++v) { - staticVertices[globalVert].mPosition = positions[v]; - staticVertices[globalVert].mNormal = normals[v]; - staticVertices[globalVert].mUV = AZ::Vector2(0.0f, 0.0f); - staticVertices[globalVert].mTangent = (tangents) ? tangents[v] : AZ::Vector4(0.0f, 0.0f, 1.0f, 1.0f); + staticVertices[globalVert].m_position = positions[v]; + staticVertices[globalVert].m_normal = normals[v]; + staticVertices[globalVert].m_uv = AZ::Vector2(0.0f, 0.0f); + staticVertices[globalVert].m_tangent = (tangents) ? tangents[v] : AZ::Vector4(0.0f, 0.0f, 1.0f, 1.0f); globalVert++; } } } // unlock the vertex buffer - mVertexBuffers[EMotionFX::Mesh::MESHTYPE_STATIC][lodLevel]->Unlock(); + m_vertexBuffers[EMotionFX::Mesh::MESHTYPE_STATIC][lodLevel]->Unlock(); } // fill the GPU skinned vertex buffer void GLActor::FillGPUSkinnedVertexBuffers(size_t lodLevel) { - if (mVertexBuffers[EMotionFX::Mesh::MESHTYPE_GPU_DEFORMED][lodLevel] == nullptr) + if (m_vertexBuffers[EMotionFX::Mesh::MESHTYPE_GPU_DEFORMED][lodLevel] == nullptr) { return; } // get the number of dynamic nodes - const size_t numNodes = mActor->GetNumNodes(); + const size_t numNodes = m_actor->GetNumNodes(); if (numNodes == 0) { return; } - EMotionFX::Skeleton* skeleton = mActor->GetSkeleton(); + EMotionFX::Skeleton* skeleton = m_actor->GetSkeleton(); // lock the GPU skinned vertex buffer - SkinnedVertex* skinnedVertices = (SkinnedVertex*)mVertexBuffers[EMotionFX::Mesh::MESHTYPE_GPU_DEFORMED][lodLevel]->Lock(LOCK_WRITEONLY); + SkinnedVertex* skinnedVertices = (SkinnedVertex*)m_vertexBuffers[EMotionFX::Mesh::MESHTYPE_GPU_DEFORMED][lodLevel]->Lock(LOCK_WRITEONLY); if (skinnedVertices == nullptr) { return; @@ -799,7 +799,7 @@ namespace RenderGL EMotionFX::Node* node = skeleton->GetNode(n); // get the mesh for the node, if there is any - EMotionFX::Mesh* mesh = mActor->GetMesh(lodLevel, n); + EMotionFX::Mesh* mesh = m_actor->GetMesh(lodLevel, n); if (mesh == nullptr) { continue; @@ -845,10 +845,10 @@ namespace RenderGL const uint32 orgVertex = orgVerts[meshVertexNr]; // copy position and normal - skinnedVertices[globalVert].mPosition = positions[meshVertexNr]; - skinnedVertices[globalVert].mNormal = normals[meshVertexNr]; - skinnedVertices[globalVert].mTangent = (tangents) ? tangents[meshVertexNr] : AZ::Vector4(0.0f, 0.0f, 1.0f, 1.0f); - skinnedVertices[globalVert].mUV = (uvsA == nullptr) ? AZ::Vector2(0.0f, 0.0f) : uvsA[meshVertexNr]; + skinnedVertices[globalVert].m_position = positions[meshVertexNr]; + skinnedVertices[globalVert].m_normal = normals[meshVertexNr]; + skinnedVertices[globalVert].m_tangent = (tangents) ? tangents[meshVertexNr] : AZ::Vector4(0.0f, 0.0f, 1.0f, 1.0f); + skinnedVertices[globalVert].m_uv = (uvsA == nullptr) ? AZ::Vector2(0.0f, 0.0f) : uvsA[meshVertexNr]; // get the number of influences and iterate through them const size_t numInfluences = skinningInfo->GetNumInfluences(orgVertex); @@ -857,17 +857,17 @@ namespace RenderGL { // get the influence and its weight and set the indices EMotionFX::SkinInfluence* influence = skinningInfo->GetInfluence(orgVertex, i); - skinnedVertices[globalVert].mWeights[i] = influence->GetWeight(); + skinnedVertices[globalVert].m_weights[i] = influence->GetWeight(); const size_t boneIndex = subMesh->FindBoneIndex(influence->GetNodeNr()); - skinnedVertices[globalVert].mBoneIndices[i] = static_cast(boneIndex); + skinnedVertices[globalVert].m_boneIndices[i] = static_cast(boneIndex); MCORE_ASSERT(boneIndex != InvalidIndex); } // reset remaining weights and offsets for (size_t a = i; a < 4; ++a) { - skinnedVertices[globalVert].mWeights[a] = 0.0f; - skinnedVertices[globalVert].mBoneIndices[a] = 0; + skinnedVertices[globalVert].m_weights[a] = 0.0f; + skinnedVertices[globalVert].m_boneIndices[a] = 0; } globalVert++; @@ -876,6 +876,6 @@ namespace RenderGL } // unlock the vertex buffer - mVertexBuffers[EMotionFX::Mesh::MESHTYPE_GPU_DEFORMED][lodLevel]->Unlock(); + m_vertexBuffers[EMotionFX::Mesh::MESHTYPE_GPU_DEFORMED][lodLevel]->Unlock(); } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLExtensions.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLExtensions.cpp index 83ae498682..91ee24876e 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLExtensions.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLExtensions.cpp @@ -17,7 +17,7 @@ namespace RenderGL { bool ok = true; - ok &= bool((glMapBuffer = (_glMapBuffer)context->getProcAddress(QByteArray("glMapBuffer")))); + ok &= bool((m_glMapBuffer = (_glMapBuffer)context->getProcAddress(QByteArray("glMapBuffer")))); return ok; }; diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLExtensions.h b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLExtensions.h index 1eea2209ec..934d73b29e 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLExtensions.h +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLExtensions.h @@ -21,7 +21,7 @@ namespace RenderGL { bool resolve(const QOpenGLContext* context); - _glMapBuffer glMapBuffer; + _glMapBuffer m_glMapBuffer; }; } // namespace RenderGL diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLRenderUtil.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLRenderUtil.cpp index d53a7b0f72..734b57e96b 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLRenderUtil.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLRenderUtil.cpp @@ -26,61 +26,61 @@ namespace RenderGL : RenderUtil() { // set/reset the member variables - mGraphicsManager = graphicsManager; - mLineShader = nullptr; - mMeshShader = nullptr; - mMeshVertexBuffer = nullptr; - mMeshIndexBuffer = nullptr; + m_graphicsManager = graphicsManager; + m_lineShader = nullptr; + m_meshShader = nullptr; + m_meshVertexBuffer = nullptr; + m_meshIndexBuffer = nullptr; - mTriangleVertexBuffer = nullptr; - mTriangleIndexBuffer = nullptr; + m_triangleVertexBuffer = nullptr; + m_triangleIndexBuffer = nullptr; - mCurrentLineVB = 0; + m_currentLineVb = 0; // initialize the vertex buffers and the shader used for line rendering - for (VertexBuffer*& lineVertexBuffer : mLineVertexBuffers) + for (VertexBuffer*& lineVertexBuffer : m_lineVertexBuffers) { lineVertexBuffer = new VertexBuffer(); - if (lineVertexBuffer->Init(sizeof(LineVertex), mNumMaxLineVertices, USAGE_DYNAMIC) == false) + if (lineVertexBuffer->Init(sizeof(LineVertex), s_numMaxLineVertices, USAGE_DYNAMIC) == false) { MCore::LogError("[OpenGL] Failed to create render utility line vertex buffer."); CleanUp(); } } - mLineShader = graphicsManager->LoadShader("Line_VS.glsl", "Line_PS.glsl"); + m_lineShader = graphicsManager->LoadShader("Line_VS.glsl", "Line_PS.glsl"); // initialize the vertex and the index buffers as well as the shader used for rendering util meshes - mMeshVertexBuffer = new VertexBuffer(); - mMeshIndexBuffer = new IndexBuffer(); + m_meshVertexBuffer = new VertexBuffer(); + m_meshIndexBuffer = new IndexBuffer(); - if (mMeshVertexBuffer->Init(sizeof(UtilMeshVertex), mNumMaxMeshVertices, USAGE_DYNAMIC) == false) + if (m_meshVertexBuffer->Init(sizeof(UtilMeshVertex), s_numMaxMeshVertices, USAGE_DYNAMIC) == false) { MCore::LogError("[OpenGL] Failed to create render utility mesh vertex buffer."); CleanUp(); return; } - if (mMeshIndexBuffer->Init(IndexBuffer::INDEXSIZE_32BIT, mNumMaxMeshIndices, USAGE_DYNAMIC) == false) + if (m_meshIndexBuffer->Init(IndexBuffer::INDEXSIZE_32BIT, s_numMaxMeshIndices, USAGE_DYNAMIC) == false) { MCore::LogError("[OpenGL] Failed to create render utility mesh index buffer."); CleanUp(); return; } - mMeshShader = graphicsManager->LoadShader("RenderUtil_VS.glsl", "RenderUtil_PS.glsl"); + m_meshShader = graphicsManager->LoadShader("RenderUtil_VS.glsl", "RenderUtil_PS.glsl"); // initialize the triangle rendering buffers - mTriangleVertexBuffer = new VertexBuffer(); - if (mTriangleVertexBuffer->Init(sizeof(TriangleVertex), mNumMaxTriangleVertices, USAGE_DYNAMIC) == false) + m_triangleVertexBuffer = new VertexBuffer(); + if (m_triangleVertexBuffer->Init(sizeof(TriangleVertex), s_numMaxTriangleVertices, USAGE_DYNAMIC) == false) { MCore::LogError("[OpenGL] Failed to create triangle vertex buffer."); CleanUp(); return; } - mTriangleIndexBuffer = new IndexBuffer(); - if (mTriangleIndexBuffer->Init(IndexBuffer::INDEXSIZE_32BIT, mNumMaxTriangleVertices, USAGE_STATIC) == false) + m_triangleIndexBuffer = new IndexBuffer(); + if (m_triangleIndexBuffer->Init(IndexBuffer::INDEXSIZE_32BIT, s_numMaxTriangleVertices, USAGE_STATIC) == false) { MCore::LogError("[OpenGL] Failed to create triangle index buffer."); CleanUp(); @@ -88,21 +88,21 @@ namespace RenderGL } // lock the index buffer and fill in the static indices - uint32* indices = (uint32*)mTriangleIndexBuffer->Lock(); + uint32* indices = (uint32*)m_triangleIndexBuffer->Lock(); if (indices) { - for (uint32 i = 0; i < mNumMaxTriangleVertices; ++i) + for (uint32 i = 0; i < s_numMaxTriangleVertices; ++i) { indices[i] = i; } - mTriangleIndexBuffer->Unlock(); + m_triangleIndexBuffer->Unlock(); } // texture rendering - mMaxNumTextures = 256; - mNumTextures = 0; - mTextures = new TextureEntry[mMaxNumTextures]; + m_maxNumTextures = 256; + m_numTextures = 0; + m_textures = new TextureEntry[m_maxNumTextures]; // text rendering } @@ -121,59 +121,59 @@ namespace RenderGL void GLRenderUtil::Validate() { - if (mLineShader) + if (m_lineShader) { - mLineShader->Validate(); + m_lineShader->Validate(); } - if (mMeshShader) + if (m_meshShader) { - mMeshShader->Validate(); + m_meshShader->Validate(); } } // destroy the allocated memory void GLRenderUtil::CleanUp() { - for (VertexBuffer*& lineVertexBuffer : mLineVertexBuffers) + for (VertexBuffer*& lineVertexBuffer : m_lineVertexBuffers) { delete lineVertexBuffer; lineVertexBuffer = nullptr; } - delete mMeshVertexBuffer; - delete mMeshIndexBuffer; + delete m_meshVertexBuffer; + delete m_meshIndexBuffer; - delete mTriangleVertexBuffer; - delete mTriangleIndexBuffer; + delete m_triangleVertexBuffer; + delete m_triangleIndexBuffer; - mMeshVertexBuffer = nullptr; - mMeshIndexBuffer = nullptr; + m_meshVertexBuffer = nullptr; + m_meshIndexBuffer = nullptr; - mTriangleVertexBuffer = nullptr; - mTriangleIndexBuffer = nullptr; + m_triangleVertexBuffer = nullptr; + m_triangleIndexBuffer = nullptr; - mCurrentLineVB = 0; + m_currentLineVb = 0; // get rid of the texture entries - delete[] mTextures; + delete[] m_textures; // get rid of texture entries - for (TextEntry* textEntry : mTextEntries) + for (TextEntry* textEntry : m_textEntries) { delete textEntry; } - mTextEntries.clear(); + m_textEntries.clear(); } // render texture void GLRenderUtil::RenderTexture(Texture* texture, const AZ::Vector2& pos) { - mTextures[mNumTextures].pos = pos; - mTextures[mNumTextures].texture = texture; - mNumTextures++; + m_textures[m_numTextures].m_pos = pos; + m_textures[m_numTextures].m_texture = texture; + m_numTextures++; - if (mNumTextures >= mMaxNumTextures) + if (m_numTextures >= m_maxNumTextures) { RenderTextures(); } @@ -183,7 +183,7 @@ namespace RenderGL // render textures void GLRenderUtil::RenderTextures() { - if (mNumTextures == 0) + if (m_numTextures == 0) { return; } @@ -216,41 +216,41 @@ namespace RenderGL glColor3f(1.0f, 1.0f, 1.0f); // iterate through the textures and render them - for (uint32 i = 0; i < mNumTextures; ++i) + for (uint32 i = 0; i < m_numTextures; ++i) { - TextureEntry& e = mTextures[i]; - float w = static_cast(e.texture->GetWidth()); - float h = static_cast(e.texture->GetHeight()); + TextureEntry& e = m_textures[i]; + float w = static_cast(e.m_texture->GetWidth()); + float h = static_cast(e.m_texture->GetHeight()); - glBindTexture(GL_TEXTURE_2D, e.texture->GetID()); + glBindTexture(GL_TEXTURE_2D, e.m_texture->GetID()); glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); - glVertex3f(e.pos.GetX(), e.pos.GetY(), -1.0f); + glVertex3f(e.m_pos.GetX(), e.m_pos.GetY(), -1.0f); glTexCoord2f(1.0f, 0.0f); - glVertex3f(e.pos.GetX() + w, e.pos.GetY(), -1.0f); + glVertex3f(e.m_pos.GetX() + w, e.m_pos.GetY(), -1.0f); glTexCoord2f(1.0f, 1.0f); - glVertex3f(e.pos.GetX() + w, e.pos.GetY() + h, -1.0f); + glVertex3f(e.m_pos.GetX() + w, e.m_pos.GetY() + h, -1.0f); glTexCoord2f(0.0f, 1.0f); - glVertex3f(e.pos.GetX(), e.pos.GetY() + h, -1.0f); + glVertex3f(e.m_pos.GetX(), e.m_pos.GetY() + h, -1.0f); glEnd(); } glPopAttrib(); - mNumTextures = 0; + m_numTextures = 0; } // overloaded render lines function void GLRenderUtil::RenderLines(LineVertex* vertices, uint32 numVertices) { - if (mLineShader == nullptr) + if (m_lineShader == nullptr) { return; } - VertexBuffer* vertexBuffer = mLineVertexBuffers[mCurrentLineVB]; + VertexBuffer* vertexBuffer = m_lineVertexBuffers[m_currentLineVb]; // copy the vertices into the OpenGL vertex buffer LineVertex* lineVertices = (LineVertex*)vertexBuffer->Lock(); @@ -265,23 +265,23 @@ namespace RenderGL glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); // setup the shader and render the lines - mLineShader->Activate(); + m_lineShader->Activate(); - mLineShader->SetAttribute("inPosition", 4, GL_FLOAT, sizeof(LineVertex), 0); - mLineShader->SetAttribute("inColor", 4, GL_FLOAT, sizeof(LineVertex), sizeof(AZ::Vector3)); - mLineShader->SetUniform("matViewProj", mGraphicsManager->GetCamera()->GetViewProjMatrix(), false); + m_lineShader->SetAttribute("inPosition", 4, GL_FLOAT, sizeof(LineVertex), 0); + m_lineShader->SetAttribute("inColor", 4, GL_FLOAT, sizeof(LineVertex), sizeof(AZ::Vector3)); + m_lineShader->SetUniform("matViewProj", m_graphicsManager->GetCamera()->GetViewProjMatrix(), false); glDrawArrays(GL_LINES, 0, numVertices); - mLineShader->Deactivate(); + m_lineShader->Deactivate(); GetGraphicsManager()->SetShader(nullptr); // if only lines are rendered, we need to unbind this shader totally // otherwise it will stay active and another context can't use it vertexBuffer->Deactivate(); - mCurrentLineVB++; - if (mCurrentLineVB >= MAX_LINE_VERTEXBUFFERS) + m_currentLineVb++; + if (m_currentLineVb >= MAX_LINE_VERTEXBUFFERS) { - mCurrentLineVB = 0; + m_currentLineVb = 0; } } @@ -311,14 +311,14 @@ namespace RenderGL glLoadIdentity(); // use the fixed function pipeline - mGraphicsManager->SetShader(nullptr); + m_graphicsManager->SetShader(nullptr); glBegin(GL_LINES); for (uint32 i = 0; i < numLines; ++i) { - glColor3f(lines[i].mColor.r, lines[i].mColor.g, lines[i].mColor.b); - glVertex3f(lines[i].mX1, lines[i].mY1, 0.0); - glVertex3f(lines[i].mX2, lines[i].mY2, 0.0); + glColor3f(lines[i].m_color.m_r, lines[i].m_color.m_g, lines[i].m_color.m_b); + glVertex3f(lines[i].m_x1, lines[i].m_y1, 0.0); + glVertex3f(lines[i].m_x2, lines[i].m_y2, 0.0); } glEnd(); @@ -350,9 +350,9 @@ namespace RenderGL glLoadIdentity(); // use the fixed function pipeline - mGraphicsManager->SetShader(nullptr); + m_graphicsManager->SetShader(nullptr); - glColor3f(fillColor.r, fillColor.g, fillColor.b); + glColor3f(fillColor.m_r, fillColor.m_g, fillColor.m_b); glBegin(GL_QUADS); glVertex3i(left, top, 0); glVertex3i(left, bottom, 0); @@ -372,65 +372,65 @@ namespace RenderGL // overloaded render util mesh function void GLRenderUtil::RenderUtilMesh(UtilMesh* mesh, const MCore::RGBAColor& color, const AZ::Transform& globalTM) { - if (mMeshShader == nullptr) + if (m_meshShader == nullptr) { return; } // lock the vertex and the index buffer - UtilMeshVertex* vertices = (UtilMeshVertex*)mMeshVertexBuffer->Lock(); - uint32* indices = (uint32*)mMeshIndexBuffer->Lock(); + UtilMeshVertex* vertices = (UtilMeshVertex*)m_meshVertexBuffer->Lock(); + uint32* indices = (uint32*)m_meshIndexBuffer->Lock(); // copy the vertices and the indices into the OpenGL buffers - MCORE_ASSERT(mesh->mPositions.size() <= mNumMaxMeshVertices); - MCore::MemCopy(indices, mesh->mIndices.data(), mesh->mIndices.size() * sizeof(uint32)); + MCORE_ASSERT(mesh->m_positions.size() <= s_numMaxMeshVertices); + MCore::MemCopy(indices, mesh->m_indices.data(), mesh->m_indices.size() * sizeof(uint32)); - if (mesh->mNormals.empty()) + if (mesh->m_normals.empty()) { - const size_t numVertices = mesh->mPositions.size(); + const size_t numVertices = mesh->m_positions.size(); for (size_t i = 0; i < numVertices; ++i) { - vertices[i].mPosition = mesh->mPositions[i]; - vertices[i].mNormal = AZ::Vector3(1.0f, 0.0f, 0.0f); + vertices[i].m_position = mesh->m_positions[i]; + vertices[i].m_normal = AZ::Vector3(1.0f, 0.0f, 0.0f); } } else { - const size_t numVertices = mesh->mPositions.size(); + const size_t numVertices = mesh->m_positions.size(); for (size_t i = 0; i < numVertices; ++i) { - vertices[i].mPosition = mesh->mPositions[i]; - vertices[i].mNormal = mesh->mNormals[i]; + vertices[i].m_position = mesh->m_positions[i]; + vertices[i].m_normal = mesh->m_normals[i]; } } // unlock and activate the vertex and the index buffer - mMeshVertexBuffer->Unlock(); - mMeshIndexBuffer->Unlock(); - mMeshVertexBuffer->Activate(); - mMeshIndexBuffer->Activate(); + m_meshVertexBuffer->Unlock(); + m_meshIndexBuffer->Unlock(); + m_meshVertexBuffer->Activate(); + m_meshIndexBuffer->Activate(); // setup shader - mMeshShader->Activate(); + m_meshShader->Activate(); - MCommon::Camera* camera = mGraphicsManager->GetCamera(); + MCommon::Camera* camera = m_graphicsManager->GetCamera(); const AZ::Matrix4x4 globalMatrix = AZ::Matrix4x4::CreateFromTransform(globalTM); - mMeshShader->SetUniform("worldViewProjectionMatrix", camera->GetViewProjMatrix() * globalMatrix); - mMeshShader->SetUniform("cameraPosition", camera->GetPosition()); - mMeshShader->SetUniform("lightDirection", MCore::GetUp(camera->GetViewMatrix().GetTranspose()).GetNormalized()); // This is GetUp() now, as lookat matrices always seem to use the z axis to point forward - mMeshShader->SetUniform("diffuseColor", color); - mMeshShader->SetUniform("specularColor", AZ::Vector3::CreateOne() * 0.3f); - mMeshShader->SetUniform("specularPower", 8.0f); + m_meshShader->SetUniform("worldViewProjectionMatrix", camera->GetViewProjMatrix() * globalMatrix); + m_meshShader->SetUniform("cameraPosition", camera->GetPosition()); + m_meshShader->SetUniform("lightDirection", MCore::GetUp(camera->GetViewMatrix().GetTranspose()).GetNormalized()); // This is GetUp() now, as lookat matrices always seem to use the z axis to point forward + m_meshShader->SetUniform("diffuseColor", color); + m_meshShader->SetUniform("specularColor", AZ::Vector3::CreateOne() * 0.3f); + m_meshShader->SetUniform("specularPower", 8.0f); // setup shader attributes and draw the mesh const uint32 stride = sizeof(UtilMeshVertex); - mMeshShader->SetAttribute("inPosition", 4, GL_FLOAT, stride, 0); - mMeshShader->SetAttribute("inNormal", 4, GL_FLOAT, stride, sizeof(AZ::Vector3)); - mMeshShader->SetUniform("worldMatrix", globalMatrix); + m_meshShader->SetAttribute("inPosition", 4, GL_FLOAT, stride, 0); + m_meshShader->SetAttribute("inNormal", 4, GL_FLOAT, stride, sizeof(AZ::Vector3)); + m_meshShader->SetUniform("worldMatrix", globalMatrix); - glDrawElements(GL_TRIANGLES, (GLsizei)mesh->mIndices.size(), GL_UNSIGNED_INT, (GLvoid*)nullptr); + glDrawElements(GL_TRIANGLES, (GLsizei)mesh->m_indices.size(), GL_UNSIGNED_INT, (GLvoid*)nullptr); - mMeshShader->Deactivate(); + m_meshShader->Deactivate(); } @@ -441,7 +441,7 @@ namespace RenderGL // load the camera view projection matrix glMatrixMode(GL_PROJECTION); - MCommon::Camera* camera = mGraphicsManager->GetCamera(); + MCommon::Camera* camera = m_graphicsManager->GetCamera(); const AZ::Matrix4x4 transposedProjMatrix = camera->GetViewProjMatrix().GetTranspose(); glLoadMatrixf((float*)&transposedProjMatrix); @@ -450,14 +450,14 @@ namespace RenderGL glLoadIdentity(); // disable the shaders - mGraphicsManager->SetShader(nullptr); + m_graphicsManager->SetShader(nullptr); // set up blending properties glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // render the triangle - glColor4f(color.r, color.g, color.b, color.a); + glColor4f(color.m_r, color.m_g, color.m_b, color.m_a); glBegin(GL_TRIANGLES); glVertex3f(v1.GetX(), v1.GetY(), v1.GetZ()); glVertex3f(v2.GetX(), v2.GetY(), v2.GetZ()); @@ -483,66 +483,66 @@ namespace RenderGL // get the number of vertices to render const uint32 numVertices = aznumeric_caster(triangleVertices.size()); - MCORE_ASSERT(numVertices <= mNumMaxTriangleVertices); + MCORE_ASSERT(numVertices <= s_numMaxTriangleVertices); // lock the vertex buffer - TriangleVertex* vertices = (TriangleVertex*)mTriangleVertexBuffer->Lock(); + TriangleVertex* vertices = (TriangleVertex*)m_triangleVertexBuffer->Lock(); if (vertices == nullptr) { return; } // TODO: Not nice yet, get the color from the first vertex and use if for all triangles - MCore::RGBAColor color((uint32)triangleVertices[0].mColor); + MCore::RGBAColor color((uint32)triangleVertices[0].m_color); // fill in the vertex buffer for (uint32 i = 0; i < numVertices; ++i) { - vertices[i].mPosition = triangleVertices[i].mPosition; - vertices[i].mNormal = triangleVertices[i].mNormal; + vertices[i].m_position = triangleVertices[i].m_position; + vertices[i].m_normal = triangleVertices[i].m_normal; } // unlock and activate the vertex buffer and index buffer - mTriangleVertexBuffer->Unlock(); - mTriangleVertexBuffer->Activate(); - mTriangleIndexBuffer->Activate(); + m_triangleVertexBuffer->Unlock(); + m_triangleVertexBuffer->Activate(); + m_triangleIndexBuffer->Activate(); // setup shader - mMeshShader->Activate(); + m_meshShader->Activate(); - MCommon::Camera* camera = mGraphicsManager->GetCamera(); + MCommon::Camera* camera = m_graphicsManager->GetCamera(); - mMeshShader->SetUniform("worldViewProjectionMatrix", camera->GetViewProjMatrix()); - mMeshShader->SetUniform("cameraPosition", camera->GetPosition()); - mMeshShader->SetUniform("lightDirection", MCore::GetUp(camera->GetViewMatrix().GetTranspose()).GetNormalized()); - mMeshShader->SetUniform("diffuseColor", color); - mMeshShader->SetUniform("specularColor", AZ::Vector3::CreateOne()); - mMeshShader->SetUniform("specularPower", 30.0f); + m_meshShader->SetUniform("worldViewProjectionMatrix", camera->GetViewProjMatrix()); + m_meshShader->SetUniform("cameraPosition", camera->GetPosition()); + m_meshShader->SetUniform("lightDirection", MCore::GetUp(camera->GetViewMatrix().GetTranspose()).GetNormalized()); + m_meshShader->SetUniform("diffuseColor", color); + m_meshShader->SetUniform("specularColor", AZ::Vector3::CreateOne()); + m_meshShader->SetUniform("specularPower", 30.0f); // setup shader attributes and draw the mesh const uint32 stride = sizeof(TriangleVertex); - mMeshShader->SetAttribute("inPosition", 4, GL_FLOAT, stride, 0); - mMeshShader->SetAttribute("inNormal", 4, GL_FLOAT, stride, sizeof(AZ::Vector3)); - mMeshShader->SetUniform("worldMatrix", AZ::Matrix4x4::CreateIdentity()); + m_meshShader->SetAttribute("inPosition", 4, GL_FLOAT, stride, 0); + m_meshShader->SetAttribute("inNormal", 4, GL_FLOAT, stride, sizeof(AZ::Vector3)); + m_meshShader->SetUniform("worldMatrix", AZ::Matrix4x4::CreateIdentity()); glDrawElements(GL_TRIANGLES, numVertices, GL_UNSIGNED_INT, (GLvoid*)nullptr); - mMeshShader->Deactivate(); + m_meshShader->Deactivate(); } void GLRenderUtil::RenderTextPeriod(uint32 x, uint32 y, const char* text, float lifeTime, const MCore::RGBAColor& color, float fontSize, bool centered) { TextEntry* textEntry = new TextEntry(); - textEntry->mX = x; - textEntry->mY = y; - textEntry->mText = text; - textEntry->mLifeTime = lifeTime; - textEntry->mColor = color; - textEntry->mFontSize = fontSize; - textEntry->mCentered = centered; + textEntry->m_x = x; + textEntry->m_y = y; + textEntry->m_text = text; + textEntry->m_lifeTime = lifeTime; + textEntry->m_color = color; + textEntry->m_fontSize = fontSize; + textEntry->m_centered = centered; - mTextEntries.emplace_back(textEntry); + m_textEntries.emplace_back(textEntry); } @@ -550,16 +550,16 @@ namespace RenderGL { static AZ::Debug::Timer timer; const float timeDelta = static_cast(timer.StampAndGetDeltaTimeInSeconds()); - for (uint32 i = 0; i < mTextEntries.size(); ) + for (uint32 i = 0; i < m_textEntries.size(); ) { - TextEntry* textEntry = mTextEntries[i]; - RenderText(static_cast(textEntry->mX), static_cast(textEntry->mY), textEntry->mText.c_str(), textEntry->mColor, textEntry->mFontSize, textEntry->mCentered); + TextEntry* textEntry = m_textEntries[i]; + RenderText(static_cast(textEntry->m_x), static_cast(textEntry->m_y), textEntry->m_text.c_str(), textEntry->m_color, textEntry->m_fontSize, textEntry->m_centered); - textEntry->mLifeTime -= timeDelta; - if (textEntry->mLifeTime < 0.0f) + textEntry->m_lifeTime -= timeDelta; + if (textEntry->m_lifeTime < 0.0f) { delete textEntry; - mTextEntries.erase(AZStd::next(begin(mTextEntries), i)); + m_textEntries.erase(AZStd::next(begin(m_textEntries), i)); } else { diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLRenderUtil.h b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLRenderUtil.h index 0f323ab00c..aa64581449 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLRenderUtil.h +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLRenderUtil.h @@ -73,45 +73,45 @@ namespace RenderGL void CleanUp(); #define MAX_LINE_VERTEXBUFFERS 2 - GraphicsManager* mGraphicsManager; - VertexBuffer* mLineVertexBuffers[MAX_LINE_VERTEXBUFFERS]{}; - uint16 mCurrentLineVB; - GLSLShader* mLineShader; - GLSLShader* mMeshShader; - VertexBuffer* mMeshVertexBuffer; - IndexBuffer* mMeshIndexBuffer; + GraphicsManager* m_graphicsManager; + VertexBuffer* m_lineVertexBuffers[MAX_LINE_VERTEXBUFFERS]{}; + uint16 m_currentLineVb; + GLSLShader* m_lineShader; + GLSLShader* m_meshShader; + VertexBuffer* m_meshVertexBuffer; + IndexBuffer* m_meshIndexBuffer; // vertex and index buffers for rendering triangles - VertexBuffer* mTriangleVertexBuffer; - IndexBuffer* mTriangleIndexBuffer; + VertexBuffer* m_triangleVertexBuffer; + IndexBuffer* m_triangleIndexBuffer; // texture rendering struct TextureEntry { MCORE_MEMORYOBJECTCATEGORY(GLRenderUtil::TextureEntry, MCore::MCORE_DEFAULT_ALIGNMENT, MEMCATEGORY_RENDERING); - Texture* texture; - AZ::Vector2 pos; + Texture* m_texture; + AZ::Vector2 m_pos; TextureEntry() - : pos(0.0f, 0.0f) - , texture(nullptr) {} + : m_pos(0.0f, 0.0f) + , m_texture(nullptr) {} }; struct TextEntry { MCORE_MEMORYOBJECTCATEGORY(GLRenderUtil::TextEntry, MCore::MCORE_DEFAULT_ALIGNMENT, MEMCATEGORY_RENDERING); - uint32 mX; - uint32 mY; - AZStd::string mText; - float mLifeTime; - MCore::RGBAColor mColor; - float mFontSize; - bool mCentered; + uint32 m_x; + uint32 m_y; + AZStd::string m_text; + float m_lifeTime; + MCore::RGBAColor m_color; + float m_fontSize; + bool m_centered; }; - AZStd::vector mTextEntries; - TextureEntry* mTextures; - uint32 mNumTextures; - uint32 mMaxNumTextures; + AZStd::vector m_textEntries; + TextureEntry* m_textures; + uint32 m_numTextures; + uint32 m_maxNumTextures; }; } // namespace RenderGL diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLSLShader.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLSLShader.cpp index b1a5c4699d..72a28a5d11 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLSLShader.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLSLShader.cpp @@ -20,39 +20,39 @@ namespace RenderGL // constructor GLSLShader::ShaderParameter::ShaderParameter(const char* name, GLint loc, bool isAttrib) { - mName = name; - mType = 0; - mSize = 0; - mLocation = loc; - mIsAttribute = isAttrib; - mTextureUnit = MCORE_INVALIDINDEX32; + m_name = name; + m_type = 0; + m_size = 0; + m_location = loc; + m_isAttribute = isAttrib; + m_textureUnit = MCORE_INVALIDINDEX32; } // constructor GLSLShader::GLSLShader() { - mProgram = 0; - mVertexShader = 0; - mPixelShader = 0; - mTextureUnit = 0; + m_program = 0; + m_vertexShader = 0; + m_pixelShader = 0; + m_textureUnit = 0; // pre-alloc data for uniforms and attributes - mUniforms.reserve(10); - mAttributes.reserve(10); - mActivatedAttribs.reserve(10); - mActivatedTextures.reserve(10); + m_uniforms.reserve(10); + m_attributes.reserve(10); + m_activatedAttribs.reserve(10); + m_activatedTextures.reserve(10); } // destructor GLSLShader::~GLSLShader() { - glDetachShader(mProgram, mVertexShader); - glDetachShader(mProgram, mPixelShader); - glDeleteShader(mVertexShader); - glDeleteShader(mPixelShader); - glDeleteShader(mProgram); + glDetachShader(m_program, m_vertexShader); + glDetachShader(m_program, m_pixelShader); + glDeleteShader(m_vertexShader); + glDeleteShader(m_pixelShader); + glDeleteShader(m_program); } @@ -66,32 +66,32 @@ namespace RenderGL // Deactivate void GLSLShader::Deactivate() { - for (const size_t index : mActivatedAttribs) + for (const size_t index : m_activatedAttribs) { - glDisableVertexAttribArray(mAttributes[index].mLocation); + glDisableVertexAttribArray(m_attributes[index].m_location); } - for (const size_t index : mActivatedTextures) + for (const size_t index : m_activatedTextures) { - assert(mUniforms[index].mType == GL_SAMPLER_2D); - glActiveTexture(GL_TEXTURE0 + mUniforms[index].mTextureUnit); + assert(m_uniforms[index].m_type == GL_SAMPLER_2D); + glActiveTexture(GL_TEXTURE0 + m_uniforms[index].m_textureUnit); glBindTexture(GL_TEXTURE_2D, 0); } - mActivatedAttribs.clear(); - mActivatedTextures.clear(); + m_activatedAttribs.clear(); + m_activatedTextures.clear(); } bool GLSLShader::Validate() { int success = 0; - glValidateProgram(mProgram); - glGetProgramiv(mProgram, GL_VALIDATE_STATUS, &success); + glValidateProgram(m_program); + glGetProgramiv(m_program, GL_VALIDATE_STATUS, &success); if (success == 0) { - MCore::LogInfo("Failed to validate program '%s'", mFileName.c_str()); - InfoLog(mProgram, &QOpenGLExtraFunctions::glGetProgramInfoLog); + MCore::LogInfo("Failed to validate program '%s'", m_fileName.c_str()); + InfoLog(m_program, &QOpenGLExtraFunctions::glGetProgramInfoLog); return false; } return true; @@ -114,14 +114,14 @@ namespace RenderGL return false; } - mFileName = filename; + m_fileName = filename; AZStd::string text; text.reserve(4096); text = "#version 120\n"; // build define string - for (const AZStd::string& define : mDefines) + for (const AZStd::string& define : m_defines) { text += AZStd::string::format("#define %s\n", define.c_str()); } @@ -171,10 +171,10 @@ namespace RenderGL AZStd::invoke(func, static_cast(this), object, logLen, &logWritten, text.data()); // if there are any defines, print that out too - if (!mDefines.empty()) + if (!m_defines.empty()) { AZStd::string dStr; - for (const AZStd::string& define : mDefines) + for (const AZStd::string& define : m_defines) { if (!dStr.empty()) { @@ -183,11 +183,11 @@ namespace RenderGL dStr.append(define); } - MCore::LogDetailedInfo("[GLSL] Compiling shader '%s', with defines %s", mFileName.c_str(), dStr.c_str()); + MCore::LogDetailedInfo("[GLSL] Compiling shader '%s', with defines %s", m_fileName.c_str(), dStr.c_str()); } else { - MCore::LogDetailedInfo("[GLSL] Compiling shader '%s'", mFileName.c_str()); + MCore::LogDetailedInfo("[GLSL] Compiling shader '%s'", m_fileName.c_str()); } MCore::LogDetailedInfo(text.c_str()); @@ -204,44 +204,44 @@ namespace RenderGL "O3", nullptr };*/ - mDefines = defines; + m_defines = defines; glUseProgram(0); // compile shaders - if (!vertexFileName.empty() && CompileShader(GL_VERTEX_SHADER, &mVertexShader, vertexFileName) == false) + if (!vertexFileName.empty() && CompileShader(GL_VERTEX_SHADER, &m_vertexShader, vertexFileName) == false) { return false; } - if (!pixelFileName.empty() && CompileShader(GL_FRAGMENT_SHADER, &mPixelShader, pixelFileName) == false) + if (!pixelFileName.empty() && CompileShader(GL_FRAGMENT_SHADER, &m_pixelShader, pixelFileName) == false) { return false; } // create program - mProgram = glCreateProgram(); + m_program = glCreateProgram(); if (!vertexFileName.empty()) { - glAttachShader(mProgram, mVertexShader); + glAttachShader(m_program, m_vertexShader); } if (!pixelFileName.empty()) { - glAttachShader(mProgram, mPixelShader); + glAttachShader(m_program, m_pixelShader); } // link - glLinkProgram(mProgram); + glLinkProgram(m_program); // check for linking errors GLint success = 0; - glGetProgramiv(mProgram, GL_LINK_STATUS, &success); + glGetProgramiv(m_program, GL_LINK_STATUS, &success); if (!success) { MCore::LogInfo("[OpenGL] Failed to link shaders '%.*s' and '%.*s' ", AZ_STRING_ARG(vertexFileName.Native()), AZ_STRING_ARG(pixelFileName.Native())); - InfoLog(mProgram, &QOpenGLExtraFunctions::glGetProgramInfoLog); + InfoLog(m_program, &QOpenGLExtraFunctions::glGetProgramInfoLog); return false; } @@ -258,35 +258,35 @@ namespace RenderGL return nullptr; } - return &mAttributes[index]; + return &m_attributes[index]; } // FindAttributeIndex size_t GLSLShader::FindAttributeIndex(const char* name) { - const auto foundAttribute = AZStd::find_if(begin(mAttributes), end(mAttributes), [name](const auto& attribute) + const auto foundAttribute = AZStd::find_if(begin(m_attributes), end(m_attributes), [name](const auto& attribute) { - return AzFramework::StringFunc::Equal(attribute.mName.c_str(), name, false /* no case */) && + return AzFramework::StringFunc::Equal(attribute.m_name.c_str(), name, false /* no case */) && // if we don't have a valid parameter location, an attribute by this name doesn't exist // we just cached the fact that it doesn't exist, instead of failing glGetAttribLocation every time - attribute.mLocation >= 0; + attribute.m_location >= 0; }); - if (foundAttribute != end(mAttributes)) + if (foundAttribute != end(m_attributes)) { - return AZStd::distance(begin(mAttributes), foundAttribute); + return AZStd::distance(begin(m_attributes), foundAttribute); } // the parameter wasn't cached, try to retrieve it - const GLint loc = glGetAttribLocation(mProgram, name); - mAttributes.emplace_back(name, loc, true); + const GLint loc = glGetAttribLocation(m_program, name); + m_attributes.emplace_back(name, loc, true); if (loc < 0) { return InvalidIndex; } - return mAttributes.size() - 1; + return m_attributes.size() - 1; } @@ -299,7 +299,7 @@ namespace RenderGL return InvalidIndex; } - return p->mLocation; + return p->m_location; } @@ -312,33 +312,33 @@ namespace RenderGL return nullptr; } - return &mUniforms[index]; + return &m_uniforms[index]; } // FindUniformIndex size_t GLSLShader::FindUniformIndex(const char* name) { - const auto foundUniform = AZStd::find_if(begin(mUniforms), end(mUniforms), [name](const auto& uniform) + const auto foundUniform = AZStd::find_if(begin(m_uniforms), end(m_uniforms), [name](const auto& uniform) { - return AzFramework::StringFunc::Equal(uniform.mName.c_str(), name, false /* no case */) && - uniform.mLocation >= 0; + return AzFramework::StringFunc::Equal(uniform.m_name.c_str(), name, false /* no case */) && + uniform.m_location >= 0; }); - if (foundUniform != end(mUniforms)) + if (foundUniform != end(m_uniforms)) { - return AZStd::distance(begin(mUniforms), foundUniform); + return AZStd::distance(begin(m_uniforms), foundUniform); } // the parameter wasn't cached, try to retrieve it - const GLint loc = glGetUniformLocation(mProgram, name); - mUniforms.emplace_back(name, loc, false); + const GLint loc = glGetUniformLocation(m_program, name); + m_uniforms.emplace_back(name, loc, false); if (loc < 0) { return InvalidIndex; } - return mUniforms.size() - 1; + return m_uniforms.size() - 1; } @@ -351,12 +351,12 @@ namespace RenderGL return; } - ShaderParameter* param = &mAttributes[index]; + ShaderParameter* param = &m_attributes[index]; - glEnableVertexAttribArray(param->mLocation); - glVertexAttribPointer(param->mLocation, dim, type, GL_FALSE, stride, (GLvoid*)offset); + glEnableVertexAttribArray(param->m_location); + glVertexAttribPointer(param->m_location, dim, type, GL_FALSE, stride, (GLvoid*)offset); - mActivatedAttribs.emplace_back(index); + m_activatedAttribs.emplace_back(index); } @@ -369,7 +369,7 @@ namespace RenderGL return; } - glUniform1f(param->mLocation, value); + glUniform1f(param->m_location, value); } @@ -382,7 +382,7 @@ namespace RenderGL return; } - glUniform1f(param->mLocation, (float)value); + glUniform1f(param->m_location, (float)value); } @@ -395,7 +395,7 @@ namespace RenderGL return; } - glUniform4fv(param->mLocation, 1, (float*)&color); + glUniform4fv(param->m_location, 1, (float*)&color); } @@ -408,7 +408,7 @@ namespace RenderGL return; } - glUniform2fv(param->mLocation, 1, (float*)&vector); + glUniform2fv(param->m_location, 1, (float*)&vector); } @@ -421,7 +421,7 @@ namespace RenderGL return; } - glUniform3fv(param->mLocation, 1, (float*)&vector); + glUniform3fv(param->m_location, 1, (float*)&vector); } @@ -434,7 +434,7 @@ namespace RenderGL return; } - glUniform4fv(param->mLocation, 1, (float*)&vector); + glUniform4fv(param->m_location, 1, (float*)&vector); } @@ -454,7 +454,7 @@ namespace RenderGL return; } - glUniformMatrix4fv(param->mLocation, 1, !transpose, (float*)&matrix); + glUniformMatrix4fv(param->m_location, 1, !transpose, (float*)&matrix); } @@ -467,7 +467,7 @@ namespace RenderGL return; } - glUniformMatrix4fv(param->mLocation, count, GL_FALSE, (float*)matrices); + glUniformMatrix4fv(param->m_location, count, GL_FALSE, (float*)matrices); } @@ -480,7 +480,7 @@ namespace RenderGL } // update the value - glUniform1fv(param->mLocation, numFloats, values); + glUniform1fv(param->m_location, numFloats, values); } @@ -493,13 +493,13 @@ namespace RenderGL return; } - mUniforms[index].mType = GL_SAMPLER_2D; // why is this being set here? + m_uniforms[index].m_type = GL_SAMPLER_2D; // why is this being set here? // if the texture doesn't have a sampler unit assigned, give it one - if (mUniforms[index].mTextureUnit == MCORE_INVALIDINDEX32) + if (m_uniforms[index].m_textureUnit == MCORE_INVALIDINDEX32) { - mUniforms[index].mTextureUnit = mTextureUnit; - mTextureUnit++; + m_uniforms[index].m_textureUnit = m_textureUnit; + m_textureUnit++; } if (texture == nullptr) @@ -507,11 +507,11 @@ namespace RenderGL texture = GetGraphicsManager()->GetTextureCache()->GetWhiteTexture(); } - glActiveTexture(GL_TEXTURE0 + mUniforms[index].mTextureUnit); + glActiveTexture(GL_TEXTURE0 + m_uniforms[index].m_textureUnit); glBindTexture(GL_TEXTURE_2D, texture->GetID()); - glUniform1i(mUniforms[index].mLocation, mUniforms[index].mTextureUnit); + glUniform1i(m_uniforms[index].m_location, m_uniforms[index].m_textureUnit); - mActivatedTextures.emplace_back(index); + m_activatedTextures.emplace_back(index); } @@ -524,13 +524,13 @@ namespace RenderGL return; } - mUniforms[index].mType = GL_SAMPLER_2D; // why is this being set here? + m_uniforms[index].m_type = GL_SAMPLER_2D; // why is this being set here? // if the texture doesn't have a sampler unit assigned, give it one - if (mUniforms[index].mTextureUnit == MCORE_INVALIDINDEX32) + if (m_uniforms[index].m_textureUnit == MCORE_INVALIDINDEX32) { - mUniforms[index].mTextureUnit = mTextureUnit; - mTextureUnit++; + m_uniforms[index].m_textureUnit = m_textureUnit; + m_textureUnit++; } if (textureID == MCORE_INVALIDINDEX32) @@ -538,11 +538,11 @@ namespace RenderGL textureID = GetGraphicsManager()->GetTextureCache()->GetWhiteTexture()->GetID(); } - glActiveTexture(GL_TEXTURE0 + mUniforms[index].mTextureUnit); + glActiveTexture(GL_TEXTURE0 + m_uniforms[index].m_textureUnit); glBindTexture(GL_TEXTURE_2D, textureID); - glUniform1i(mUniforms[index].mLocation, mUniforms[index].mTextureUnit); + glUniform1i(m_uniforms[index].m_location, m_uniforms[index].m_textureUnit); - mActivatedTextures.emplace_back(index); + m_activatedTextures.emplace_back(index); } @@ -550,7 +550,7 @@ namespace RenderGL bool GLSLShader::CheckIfIsDefined(const char* attributeName) const { // get the number of defines and iterate through them - return AZStd::any_of(begin(mDefines), end(mDefines), [attributeName](const AZStd::string& define) + return AZStd::any_of(begin(m_defines), end(m_defines), [attributeName](const AZStd::string& define) { return AzFramework::StringFunc::Equal(define.c_str(), attributeName, false /* no case */); }); diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLSLShader.h b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLSLShader.h index 0db7948e8f..5975470f86 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLSLShader.h +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLSLShader.h @@ -39,7 +39,7 @@ namespace RenderGL size_t FindAttributeLocation(const char* name); uint32 GetType() const override; - MCORE_INLINE unsigned int GetProgram() const { return mProgram; } + MCORE_INLINE unsigned int GetProgram() const { return m_program; } bool CheckIfIsDefined(const char* attributeName) const; bool Init(AZ::IO::PathView vertexFileName, AZ::IO::PathView pixelFileName, AZStd::vector& defines); @@ -65,12 +65,12 @@ namespace RenderGL { ShaderParameter(const char* name, GLint loc, bool isAttrib); - AZStd::string mName; - GLint mLocation; - GLenum mType; - uint32 mSize; - uint32 mTextureUnit; - bool mIsAttribute; + AZStd::string m_name; + GLint m_location; + GLenum m_type; + uint32 m_size; + uint32 m_textureUnit; + bool m_isAttribute; }; size_t FindAttributeIndex(const char* name); @@ -82,19 +82,19 @@ namespace RenderGL template void InfoLog(GLuint object, T func); - AZ::IO::Path mFileName; + AZ::IO::Path m_fileName; - AZStd::vector mActivatedAttribs; - AZStd::vector mActivatedTextures; - AZStd::vector mUniforms; - AZStd::vector mAttributes; - AZStd::vector mDefines; + AZStd::vector m_activatedAttribs; + AZStd::vector m_activatedTextures; + AZStd::vector m_uniforms; + AZStd::vector m_attributes; + AZStd::vector m_defines; - unsigned int mVertexShader; - unsigned int mPixelShader; - unsigned int mProgram; + unsigned int m_vertexShader; + unsigned int m_pixelShader; + unsigned int m_program; - uint32 mTextureUnit; + uint32 m_textureUnit; }; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GraphicsManager.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GraphicsManager.cpp index 4802477e08..1ccb8650aa 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GraphicsManager.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GraphicsManager.cpp @@ -24,7 +24,7 @@ namespace RenderGL { - size_t GraphicsManager::mNumRandomOffsets = 64; + size_t GraphicsManager::s_numRandomOffsets = 64; GraphicsManager* gGraphicsManager = nullptr; @@ -39,60 +39,60 @@ namespace RenderGL GraphicsManager::GraphicsManager() { gGraphicsManager = this; - mPostProcessing = false; + m_postProcessing = false; // render background - mUseGradientBackground = true; - mClearColor = MCore::RGBAColor(0.359f, 0.3984f, 0.4492f); - mGradientSourceColor = MCore::RGBAColor(0.4941f, 0.5686f, 0.6470f); - mGradientTargetColor = MCore::RGBAColor(0.0941f, 0.1019f, 0.1098f); + m_useGradientBackground = true; + m_clearColor = MCore::RGBAColor(0.359f, 0.3984f, 0.4492f); + m_gradientSourceColor = MCore::RGBAColor(0.4941f, 0.5686f, 0.6470f); + m_gradientTargetColor = MCore::RGBAColor(0.0941f, 0.1019f, 0.1098f); - mGBuffer = nullptr; - mHBloom = nullptr; - mVBloom = nullptr; - mHBlur = nullptr; - mVBlur = nullptr; - mDownSample = nullptr; - mDOF = nullptr; - mSSDO = nullptr; - mHSmartBlur = nullptr; - mVSmartBlur = nullptr; - mRenderTexture = nullptr; - mActiveShader = nullptr; - mCamera = nullptr; - mRenderUtil = nullptr; + m_gBuffer = nullptr; + m_hBloom = nullptr; + m_vBloom = nullptr; + m_hBlur = nullptr; + m_vBlur = nullptr; + m_downSample = nullptr; + m_dof = nullptr; + m_ssdo = nullptr; + m_hSmartBlur = nullptr; + m_vSmartBlur = nullptr; + m_renderTexture = nullptr; + m_activeShader = nullptr; + m_camera = nullptr; + m_renderUtil = nullptr; - mMainLightIntensity = 1.00f; - mMainLightAngleA = -30.0f; - mMainLightAngleB = 18.0f; - mSpecularIntensity = 1.0f; + m_mainLightIntensity = 1.00f; + m_mainLightAngleA = -30.0f; + m_mainLightAngleB = 18.0f; + m_specularIntensity = 1.0f; - mBloomEnabled = true; - mBloomRadius = 4.0f; - mBloomIntensity = 0.85f; - mBloomThreshold = 0.80f; + m_bloomEnabled = true; + m_bloomRadius = 4.0f; + m_bloomIntensity = 0.85f; + m_bloomThreshold = 0.80f; - mDOFEnabled = false; - mDOFBlurRadius = 2.0f; - mDOFFocalDistance = 500.0f; - mDOFNear = 0.001f; - mDOFFar = 1000.0f; + m_dofEnabled = false; + m_dofBlurRadius = 2.0f; + m_dofFocalDistance = 500.0f; + m_dofNear = 0.001f; + m_dofFar = 1000.0f; - mRimAngle = 60.0f; - mRimWidth = 0.65f; - mRimIntensity = 1.5f; - mRimColor = MCore::RGBAColor(1.0f, 0.70f, 0.109f); + m_rimAngle = 60.0f; + m_rimWidth = 0.65f; + m_rimIntensity = 1.5f; + m_rimColor = MCore::RGBAColor(1.0f, 0.70f, 0.109f); - mRandomVectorTexture = nullptr; - mCreateMipMaps = true; - mSkipLoadingTextures = false; + m_randomVectorTexture = nullptr; + m_createMipMaps = true; + m_skipLoadingTextures = false; // init random offsets - mRandomOffsets.resize(mNumRandomOffsets); - AZStd::vector samples = MCore::Random::RandomDirVectorsHalton(AZ::Vector3(0.0f, 1.0f, 0.0f), MCore::Math::twoPi, mNumRandomOffsets); - for (size_t i = 0; i < mNumRandomOffsets; ++i) + m_randomOffsets.resize(s_numRandomOffsets); + AZStd::vector samples = MCore::Random::RandomDirVectorsHalton(AZ::Vector3(0.0f, 1.0f, 0.0f), MCore::Math::twoPi, s_numRandomOffsets); + for (size_t i = 0; i < s_numRandomOffsets; ++i) { - mRandomOffsets[i] = samples[i] * MCore::Random::RandF(0.1f, 1.0f); + m_randomOffsets[i] = samples[i] * MCore::Random::RandF(0.1f, 1.0f); } } @@ -101,38 +101,37 @@ namespace RenderGL GraphicsManager::~GraphicsManager() { // shutdown the texture cache - mTextureCache.Release(); + m_textureCache.Release(); // delete all shaders - mShaderCache.Release(); + m_shaderCache.Release(); // get rid of the OpenGL render utility - delete mRenderUtil; + delete m_renderUtil; // release random vector texture memory - delete mRandomVectorTexture; + delete m_randomVectorTexture; // clear the string memory - mShaderPath.clear(); + m_shaderPath.clear(); } // setup sunset color style rim lighting void GraphicsManager::SetupSunsetRim() { - mRimWidth = 0.65f; - mRimIntensity = 1.5f; - mRimColor = MCore::RGBAColor(1.0f, 0.70f, 0.109f); - //mRimColor = MCore::RGBAColor(1.0f, 0.77f, 0.30f); + m_rimWidth = 0.65f; + m_rimIntensity = 1.5f; + m_rimColor = MCore::RGBAColor(1.0f, 0.70f, 0.109f); } // setup blue color style rim lighting void GraphicsManager::SetupBlueRim() { - mRimWidth = 0.65f; - mRimIntensity = 1.5f; - mRimColor = MCore::RGBAColor(81.0f / 255.0f, 160.0f / 255.0f, 1.0f); + m_rimWidth = 0.65f; + m_rimIntensity = 1.5f; + m_rimColor = MCore::RGBAColor(81.0f / 255.0f, 160.0f / 255.0f, 1.0f); } @@ -152,12 +151,12 @@ namespace RenderGL glBegin(GL_QUADS); // bottom - glColor3f(bottomColor.r, bottomColor.g, bottomColor.b); + glColor3f(bottomColor.m_r, bottomColor.m_g, bottomColor.m_b); glVertex2f(-1.0, -1.0); glVertex2f(1.0, -1.0); // top - glColor3f(topColor.r, topColor.g, topColor.b); + glColor3f(topColor.m_r, topColor.m_g, topColor.m_b); glVertex2f(1.0, 1.0); glVertex2f(-1.0, 1.0); @@ -176,13 +175,13 @@ namespace RenderGL //glPushAttrib( GL_ALL_ATTRIB_BITS ); // Activate render targets - glClearColor(mClearColor.r, mClearColor.g, mClearColor.b, 1.0f); + glClearColor(m_clearColor.m_r, m_clearColor.m_g, m_clearColor.m_b, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); // render the gradient background - if (mUseGradientBackground) + if (m_useGradientBackground) { - RenderGradientBackground(mGradientSourceColor, mGradientTargetColor); + RenderGradientBackground(m_gradientSourceColor, m_gradientTargetColor); } return true; @@ -192,9 +191,9 @@ namespace RenderGL // end a frame (perform the swap) void GraphicsManager::EndRender() { - mRenderUtil->RenderTextPeriods(); - mRenderUtil->RenderTextures(); - ((MCommon::RenderUtil*)mRenderUtil)->Render2DLines(); + m_renderUtil->RenderTextPeriods(); + m_renderUtil->RenderTextures(); + ((MCommon::RenderUtil*)m_renderUtil)->Render2DLines(); } @@ -207,7 +206,7 @@ namespace RenderGL SetShaderPath(shaderPath); // texture cache - if (mTextureCache.Init() == false) + if (m_textureCache.Init() == false) { return false; } @@ -218,7 +217,7 @@ namespace RenderGL glDepthFunc(GL_LEQUAL); glEnable(GL_DEPTH_TEST); - glClearColor(mClearColor.r, mClearColor.g, mClearColor.b, 1.0f); + glClearColor(m_clearColor.m_r, m_clearColor.m_g, m_clearColor.m_b, 1.0f); glHint(GL_POINT_SMOOTH_HINT, GL_NICEST); glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); @@ -228,15 +227,15 @@ namespace RenderGL glDisable(GL_BLEND); // initialize utility rendering - mRenderUtil = new GLRenderUtil(this); - mRenderUtil->Init(); + m_renderUtil = new GLRenderUtil(this); + m_renderUtil->Init(); // post processing - if (mPostProcessing) + if (m_postProcessing) { if (InitPostProcessing() == false) { - mPostProcessing = false; + m_postProcessing = false; } } @@ -275,86 +274,52 @@ namespace RenderGL ResizeTextures(screenWidth, screenHeight); // load horizontal bloom - mHBloom = LoadPostProcessShader("HBloom.glsl"); - if (mHBloom == nullptr) + m_hBloom = LoadPostProcessShader("HBloom.glsl"); + if (m_hBloom == nullptr) { MCore::LogWarning("[OpenGL] Failed to load HBloom shader, disabling post processing."); return false; } // load vertical bloom - mVBloom = LoadPostProcessShader("VBloom.glsl"); - if (mVBloom == nullptr) + m_vBloom = LoadPostProcessShader("VBloom.glsl"); + if (m_vBloom == nullptr) { MCore::LogWarning("[OpenGL] Failed to load VBloom shader, disabling post processing."); return false; } // load vertical bloom - mDownSample = LoadPostProcessShader("DownSample.glsl"); - if (mDownSample == nullptr) + m_downSample = LoadPostProcessShader("DownSample.glsl"); + if (m_downSample == nullptr) { MCore::LogWarning("[OpenGL] Failed to load DownSample shader, disabling post processing."); return false; } // load horizontal blur - mHBlur = LoadPostProcessShader("HBlur.glsl"); - if (mHBlur == nullptr) + m_hBlur = LoadPostProcessShader("HBlur.glsl"); + if (m_hBlur == nullptr) { MCore::LogWarning("[OpenGL] Failed to load HBlur shader, disabling post processing."); return false; } // load vertical blur - mVBlur = LoadPostProcessShader("VBlur.glsl"); - if (mVBlur == nullptr) + m_vBlur = LoadPostProcessShader("VBlur.glsl"); + if (m_vBlur == nullptr) { MCore::LogWarning("[OpenGL] Failed to load VBlur shader, disabling post processing."); return false; } // load DOF shader - mDOF = LoadPostProcessShader("DepthOfField.glsl"); - if (mDOF == nullptr) + m_dof = LoadPostProcessShader("DepthOfField.glsl"); + if (m_dof == nullptr) { MCore::LogWarning("[OpenGL] Failed to load DOF shader, disabling post processing."); return false; } - /* - // load screen space directional occlusion shader - mSSDO = LoadPostProcessShader("SSDO.glsl"); - if (mSSDO == nullptr) - { - MCore::LogWarning("[OpenGL] Failed to load SSDO shader, disabling post processing."); - return false; - } - - // horizontal smartblur - mHSmartBlur = LoadPostProcessShader("HSmartBlur.glsl"); - if (mHSmartBlur == nullptr) - { - MCore::LogWarning("[OpenGL] Failed to load HSmartBlur shader, disabling post processing."); - return false; - } - - // vertical smartblur - mVSmartBlur = LoadPostProcessShader("VSmartBlur.glsl"); - if (mVSmartBlur == nullptr) - { - MCore::LogWarning("[OpenGL] Failed to load VSmartBlur shader, disabling post processing."); - return false; - } - */ - /* - // create the post processing shaders - mSSAO = LoadPostProcessShader("SSAO.glsl"); - if (mSSAO == nullptr) - { - MCore::LogWarning("[OpenGL] Failed to load SSAO shader, disabling post processing."); - return false; - } - */ return true; } @@ -371,17 +336,17 @@ namespace RenderGL // try to load a texture Texture* GraphicsManager::LoadTexture(AZ::IO::PathView filename) { - return LoadTexture(filename, mCreateMipMaps); + return LoadTexture(filename, m_createMipMaps); } // LoadPostProcessShader PostProcessShader* GraphicsManager::LoadPostProcessShader(AZ::IO::PathView cFileName) { - AZ::IO::PathView filename = mShaderPath / cFileName; + AZ::IO::PathView filename = m_shaderPath / cFileName; // check if the shader is already in the cache - Shader* s = mShaderCache.FindShader(filename.Native()); + Shader* s = m_shaderCache.FindShader(filename.Native()); if (s) { return (PostProcessShader*)s; @@ -395,7 +360,7 @@ namespace RenderGL return nullptr; } - mShaderCache.AddShader(filename.Native(), shader); + m_shaderCache.AddShader(filename.Native(), shader); return shader; } @@ -411,8 +376,8 @@ namespace RenderGL // LoadShader GLSLShader* GraphicsManager::LoadShader(AZ::IO::PathView vertexFileName, AZ::IO::PathView pixelFileName, AZStd::vector& defines) { - const AZ::IO::Path vertexPath {vertexFileName.empty() ? AZ::IO::Path{} : mShaderPath / vertexFileName}; - const AZ::IO::Path pixelPath {pixelFileName.empty() ? AZ::IO::Path{} : mShaderPath / pixelFileName}; + const AZ::IO::Path vertexPath {vertexFileName.empty() ? AZ::IO::Path{} : m_shaderPath / vertexFileName}; + const AZ::IO::Path pixelPath {pixelFileName.empty() ? AZ::IO::Path{} : m_shaderPath / pixelFileName}; // construct the lookup string for the shader cache AZStd::string cacheLookupStr = vertexPath.Native() + pixelPath.Native(); @@ -422,7 +387,7 @@ namespace RenderGL } // check if the shader is already in the cache - Shader* cShader = mShaderCache.FindShader(cacheLookupStr); + Shader* cShader = m_shaderCache.FindShader(cacheLookupStr); if (cShader) { return (GLSLShader*)cShader; @@ -436,7 +401,7 @@ namespace RenderGL return nullptr; } - mShaderCache.AddShader(cacheLookupStr, shader); + m_shaderCache.AddShader(cacheLookupStr, shader); return shader; } @@ -463,7 +428,7 @@ namespace RenderGL // SetShader void GraphicsManager::SetShader(Shader* shader) { - if (mActiveShader == shader) + if (m_activeShader == shader) { return; } @@ -471,7 +436,7 @@ namespace RenderGL if (shader == nullptr) { glUseProgram(0); - mActiveShader = nullptr; + m_activeShader = nullptr; return; } @@ -481,7 +446,7 @@ namespace RenderGL glUseProgram(g->GetProgram()); } - mActiveShader = shader; + m_activeShader = shader; } @@ -529,7 +494,7 @@ namespace RenderGL } // create Texture object - mRandomVectorTexture = new Texture(textureID, width, height); + m_randomVectorTexture = new Texture(textureID, width, height); glDisable(GL_TEXTURE_2D); return true; diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GraphicsManager.h b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GraphicsManager.h index e13e643938..67ebbd9441 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GraphicsManager.h +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GraphicsManager.h @@ -49,91 +49,91 @@ namespace RenderGL bool BeginRender(); void EndRender(); - MCORE_INLINE MCommon::Camera* GetCamera() const { return mCamera; } - MCORE_INLINE GLRenderUtil* GetRenderUtil() { return mRenderUtil; } + MCORE_INLINE MCommon::Camera* GetCamera() const { return m_camera; } + MCORE_INLINE GLRenderUtil* GetRenderUtil() { return m_renderUtil; } const char* GetDeviceName(); const char* GetDeviceVendor(); - MCORE_INLINE RenderTexture* GetRenderTexture() { return mRenderTexture; } - MCORE_INLINE AZ::IO::PathView GetShaderPath() const { return mShaderPath; } - MCORE_INLINE TextureCache* GetTextureCache() { return &mTextureCache; } + MCORE_INLINE RenderTexture* GetRenderTexture() { return m_renderTexture; } + MCORE_INLINE AZ::IO::PathView GetShaderPath() const { return m_shaderPath; } + MCORE_INLINE TextureCache* GetTextureCache() { return &m_textureCache; } bool Init(AZ::IO::PathView shaderPath = "Shaders"); - bool GetIsPostProcessingEnabled() const { return mPostProcessing; } + bool GetIsPostProcessingEnabled() const { return m_postProcessing; } PostProcessShader* LoadPostProcessShader(AZ::IO::PathView filename); GLSLShader* LoadShader(AZ::IO::PathView vertexFileName, AZ::IO::PathView pixelFileName); GLSLShader* LoadShader(AZ::IO::PathView vertexFileName, AZ::IO::PathView pixelFileName, AZStd::vector& defines); - MCORE_INLINE void SetGBuffer(GBuffer* gBuffer) { mGBuffer = gBuffer; } - MCORE_INLINE GBuffer* GetGBuffer() { return mGBuffer; } + MCORE_INLINE void SetGBuffer(GBuffer* gBuffer) { m_gBuffer = gBuffer; } + MCORE_INLINE GBuffer* GetGBuffer() { return m_gBuffer; } Texture* LoadTexture(AZ::IO::PathView filename, bool createMipMaps); Texture* LoadTexture(AZ::IO::PathView filename); - void SetCreateMipMaps(bool createMipMaps) { mCreateMipMaps = createMipMaps; } - MCORE_INLINE bool GetCreateMipMaps() const { return mCreateMipMaps; } + void SetCreateMipMaps(bool createMipMaps) { m_createMipMaps = createMipMaps; } + MCORE_INLINE bool GetCreateMipMaps() const { return m_createMipMaps; } - void SetSkipLoadingTextures(bool skipTextures) { mSkipLoadingTextures = skipTextures; } - MCORE_INLINE bool GetSkipLoadingTextures() const { return mSkipLoadingTextures; } + void SetSkipLoadingTextures(bool skipTextures) { m_skipLoadingTextures = skipTextures; } + MCORE_INLINE bool GetSkipLoadingTextures() const { return m_skipLoadingTextures; } void Resize(uint32 width, uint32 height); - MCORE_INLINE void SetCamera(MCommon::Camera* camera) { mCamera = camera; } + MCORE_INLINE void SetCamera(MCommon::Camera* camera) { m_camera = camera; } // background rendering and colors - MCORE_INLINE void SetClearColor(const MCore::RGBAColor& color) { mClearColor = color; } - MCORE_INLINE void SetGradientSourceColor(const MCore::RGBAColor& color) { mGradientSourceColor = color; } - MCORE_INLINE void SetGradientTargetColor(const MCore::RGBAColor& color) { mGradientTargetColor = color; } - MCORE_INLINE void SetUseGradientBackground(bool enabled) { mUseGradientBackground = enabled; } - MCORE_INLINE MCore::RGBAColor GetClearColor() const { return mClearColor; } - MCORE_INLINE MCore::RGBAColor GetGradientSourceColor() const { return mGradientSourceColor; } - MCORE_INLINE MCore::RGBAColor GetGradientTargetColor() const { return mGradientTargetColor; } + MCORE_INLINE void SetClearColor(const MCore::RGBAColor& color) { m_clearColor = color; } + MCORE_INLINE void SetGradientSourceColor(const MCore::RGBAColor& color) { m_gradientSourceColor = color; } + MCORE_INLINE void SetGradientTargetColor(const MCore::RGBAColor& color) { m_gradientTargetColor = color; } + MCORE_INLINE void SetUseGradientBackground(bool enabled) { m_useGradientBackground = enabled; } + MCORE_INLINE MCore::RGBAColor GetClearColor() const { return m_clearColor; } + MCORE_INLINE MCore::RGBAColor GetGradientSourceColor() const { return m_gradientSourceColor; } + MCORE_INLINE MCore::RGBAColor GetGradientTargetColor() const { return m_gradientTargetColor; } void RenderGradientBackground(const MCore::RGBAColor& topColor, const MCore::RGBAColor& bottomColor); void SetShader(Shader* shader); - MCORE_INLINE void SetRenderTexture(RenderTexture* texture) { mRenderTexture = texture; } - MCORE_INLINE void SetShaderPath(AZ::IO::PathView shaderPath) { mShaderPath = shaderPath; } + MCORE_INLINE void SetRenderTexture(RenderTexture* texture) { m_renderTexture = texture; } + MCORE_INLINE void SetShaderPath(AZ::IO::PathView shaderPath) { m_shaderPath = shaderPath; } - MCORE_INLINE void SetBloomEnabled(bool enabled) { mBloomEnabled = enabled; } - MCORE_INLINE void SetBloomThreshold(float threshold) { mBloomThreshold = threshold; } - MCORE_INLINE void SetBloomIntensity(float intensity) { mBloomIntensity = intensity; } - MCORE_INLINE void SetBloomRadius(float radius) { mBloomRadius = radius; } - MCORE_INLINE void SetDOFEnabled(bool enabled) { mDOFEnabled = enabled; } - MCORE_INLINE void SetDOFFocalDistance(float dist) { mDOFFocalDistance = dist; } - MCORE_INLINE void SetDOFNear(float dist) { mDOFNear = dist; } - MCORE_INLINE void SetDOFFar(float dist) { mDOFFar = dist; } - MCORE_INLINE void SetDOFBlurRadius(float radius) { mDOFBlurRadius = radius; } + MCORE_INLINE void SetBloomEnabled(bool enabled) { m_bloomEnabled = enabled; } + MCORE_INLINE void SetBloomThreshold(float threshold) { m_bloomThreshold = threshold; } + MCORE_INLINE void SetBloomIntensity(float intensity) { m_bloomIntensity = intensity; } + MCORE_INLINE void SetBloomRadius(float radius) { m_bloomRadius = radius; } + MCORE_INLINE void SetDOFEnabled(bool enabled) { m_dofEnabled = enabled; } + MCORE_INLINE void SetDOFFocalDistance(float dist) { m_dofFocalDistance = dist; } + MCORE_INLINE void SetDOFNear(float dist) { m_dofNear = dist; } + MCORE_INLINE void SetDOFFar(float dist) { m_dofFar = dist; } + MCORE_INLINE void SetDOFBlurRadius(float radius) { m_dofBlurRadius = radius; } - MCORE_INLINE void SetRimColor(const MCore::RGBAColor& color) { mRimColor = color; } - MCORE_INLINE void SetRimIntensity(float intensity) { mRimIntensity = intensity; } - MCORE_INLINE void SetRimWidth(float width) { mRimWidth = width; } - MCORE_INLINE void SetRimAngle(float angleInDegrees) { mRimAngle = angleInDegrees; } + MCORE_INLINE void SetRimColor(const MCore::RGBAColor& color) { m_rimColor = color; } + MCORE_INLINE void SetRimIntensity(float intensity) { m_rimIntensity = intensity; } + MCORE_INLINE void SetRimWidth(float width) { m_rimWidth = width; } + MCORE_INLINE void SetRimAngle(float angleInDegrees) { m_rimAngle = angleInDegrees; } - MCORE_INLINE void SetMainLightIntensity(float intensity) { mMainLightIntensity = intensity; } - MCORE_INLINE void SetMainLightAngleA(float angleInDegrees) { mMainLightAngleA = angleInDegrees; } - MCORE_INLINE void SetMainLightAngleB(float angleInDegrees) { mMainLightAngleB = angleInDegrees; } - MCORE_INLINE void SetSpecularIntensity(float intensity) { mSpecularIntensity = intensity; } + MCORE_INLINE void SetMainLightIntensity(float intensity) { m_mainLightIntensity = intensity; } + MCORE_INLINE void SetMainLightAngleA(float angleInDegrees) { m_mainLightAngleA = angleInDegrees; } + MCORE_INLINE void SetMainLightAngleB(float angleInDegrees) { m_mainLightAngleB = angleInDegrees; } + MCORE_INLINE void SetSpecularIntensity(float intensity) { m_specularIntensity = intensity; } - MCORE_INLINE bool GetBloomEnabled() const { return mBloomEnabled; } - MCORE_INLINE float GetBloomThreshold() const { return mBloomThreshold; } - MCORE_INLINE float GetBloomIntensity() const { return mBloomIntensity; } - MCORE_INLINE float GetBloomRadius() const { return mBloomRadius; } - MCORE_INLINE bool GetDOFEnabled() const { return mDOFEnabled; } - MCORE_INLINE float GetDOFBlurRadius() const { return mDOFBlurRadius; } - MCORE_INLINE float GetDOFFocalDistance() const { return mDOFFocalDistance; } - MCORE_INLINE float GetDOFNear() const { return mDOFNear; } - MCORE_INLINE float GetDOFFar() const { return mDOFFar; } + MCORE_INLINE bool GetBloomEnabled() const { return m_bloomEnabled; } + MCORE_INLINE float GetBloomThreshold() const { return m_bloomThreshold; } + MCORE_INLINE float GetBloomIntensity() const { return m_bloomIntensity; } + MCORE_INLINE float GetBloomRadius() const { return m_bloomRadius; } + MCORE_INLINE bool GetDOFEnabled() const { return m_dofEnabled; } + MCORE_INLINE float GetDOFBlurRadius() const { return m_dofBlurRadius; } + MCORE_INLINE float GetDOFFocalDistance() const { return m_dofFocalDistance; } + MCORE_INLINE float GetDOFNear() const { return m_dofNear; } + MCORE_INLINE float GetDOFFar() const { return m_dofFar; } - MCORE_INLINE const MCore::RGBAColor& GetRimColor() const { return mRimColor; } - MCORE_INLINE float GetRimIntensity() const { return mRimIntensity; } - MCORE_INLINE float GetRimWidth() const { return mRimWidth; } - MCORE_INLINE float GetRimAngle() const { return mRimAngle; } + MCORE_INLINE const MCore::RGBAColor& GetRimColor() const { return m_rimColor; } + MCORE_INLINE float GetRimIntensity() const { return m_rimIntensity; } + MCORE_INLINE float GetRimWidth() const { return m_rimWidth; } + MCORE_INLINE float GetRimAngle() const { return m_rimAngle; } - MCORE_INLINE float GetMainLightIntensity() const { return mMainLightIntensity; } - MCORE_INLINE float GetMainLightAngleA() const { return mMainLightAngleA; } - MCORE_INLINE float GetMainLightAngleB() const { return mMainLightAngleB; } - MCORE_INLINE float GetSpecularIntensity() const { return mSpecularIntensity; } + MCORE_INLINE float GetMainLightIntensity() const { return m_mainLightIntensity; } + MCORE_INLINE float GetMainLightAngleA() const { return m_mainLightAngleA; } + MCORE_INLINE float GetMainLightAngleB() const { return m_mainLightAngleB; } + MCORE_INLINE float GetSpecularIntensity() const { return m_specularIntensity; } void SetupSunsetRim(); void SetupBlueRim(); @@ -143,58 +143,58 @@ namespace RenderGL bool ResizeTextures(uint32 screenWidth, uint32 screenHeight); bool CreateRandomVectorTexture(uint32 width, uint32 height); - bool mPostProcessing; - RenderTexture* mRenderTexture; // Active RT + bool m_postProcessing; + RenderTexture* m_renderTexture; // Active RT - GBuffer* mGBuffer; /**< The g-buffer. */ + GBuffer* m_gBuffer; /**< The g-buffer. */ - MCommon::Camera* mCamera; /**< The camera used for rendering. */ + MCommon::Camera* m_camera; /**< The camera used for rendering. */ - ShaderCache mShaderCache; /**< The shader manager used to load and manage vertex and pixel shaders. */ - AZ::IO::Path mShaderPath; /**< The absolute path to the directory where the shaders are located. This string will be added as prefix to each shader file the user tries to load. */ - MCore::RGBAColor mClearColor; /**< The scene background color. */ - MCore::RGBAColor mGradientSourceColor; /**< The background gradient source color. */ - MCore::RGBAColor mGradientTargetColor; /**< The background gradient target color. */ - bool mUseGradientBackground; - Shader* mActiveShader; /**< The currently used shader. */ + ShaderCache m_shaderCache; /**< The shader manager used to load and manage vertex and pixel shaders. */ + AZ::IO::Path m_shaderPath; /**< The absolute path to the directory where the shaders are located. This string will be added as prefix to each shader file the user tries to load. */ + MCore::RGBAColor m_clearColor; /**< The scene background color. */ + MCore::RGBAColor m_gradientSourceColor; /**< The background gradient source color. */ + MCore::RGBAColor m_gradientTargetColor; /**< The background gradient target color. */ + bool m_useGradientBackground; + Shader* m_activeShader; /**< The currently used shader. */ // post process shaders - PostProcessShader* mHBloom; - PostProcessShader* mVBloom; - PostProcessShader* mDownSample; - PostProcessShader* mHBlur; - PostProcessShader* mVBlur; - PostProcessShader* mDOF; - PostProcessShader* mSSDO; - PostProcessShader* mHSmartBlur; - PostProcessShader* mVSmartBlur; + PostProcessShader* m_hBloom; + PostProcessShader* m_vBloom; + PostProcessShader* m_downSample; + PostProcessShader* m_hBlur; + PostProcessShader* m_vBlur; + PostProcessShader* m_dof; + PostProcessShader* m_ssdo; + PostProcessShader* m_hSmartBlur; + PostProcessShader* m_vSmartBlur; - Texture* mRandomVectorTexture; - AZStd::vector mRandomOffsets; - static size_t mNumRandomOffsets; + Texture* m_randomVectorTexture; + AZStd::vector m_randomOffsets; + static size_t s_numRandomOffsets; - GLRenderUtil* mRenderUtil; /**< The rendering utility. */ - TextureCache mTextureCache; /**< The texture manager used to load and manage textures. */ + GLRenderUtil* m_renderUtil; /**< The rendering utility. */ + TextureCache m_textureCache; /**< The texture manager used to load and manage textures. */ - bool mBloomEnabled; - float mBloomThreshold; - float mBloomIntensity; - float mBloomRadius; - bool mDOFEnabled; - float mDOFFocalDistance; - float mDOFNear; - float mDOFFar; - float mDOFBlurRadius; - float mRimAngle; - float mRimWidth; - float mRimIntensity; - MCore::RGBAColor mRimColor; - float mMainLightIntensity; - float mMainLightAngleA; - float mMainLightAngleB; - float mSpecularIntensity; - bool mCreateMipMaps; - bool mSkipLoadingTextures; + bool m_bloomEnabled; + float m_bloomThreshold; + float m_bloomIntensity; + float m_bloomRadius; + bool m_dofEnabled; + float m_dofFocalDistance; + float m_dofNear; + float m_dofFar; + float m_dofBlurRadius; + float m_rimAngle; + float m_rimWidth; + float m_rimIntensity; + MCore::RGBAColor m_rimColor; + float m_mainLightIntensity; + float m_mainLightAngleA; + float m_mainLightAngleB; + float m_specularIntensity; + bool m_createMipMaps; + bool m_skipLoadingTextures; }; GraphicsManager* GetGraphicsManager(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/IndexBuffer.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/IndexBuffer.cpp index 279858aba7..01d1e7ef20 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/IndexBuffer.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/IndexBuffer.cpp @@ -17,23 +17,23 @@ namespace RenderGL // default constructor IndexBuffer::IndexBuffer() { - mBufferID = MCORE_INVALIDINDEX32; - mNumIndices = 0; + m_bufferId = MCORE_INVALIDINDEX32; + m_numIndices = 0; } // destructor IndexBuffer::~IndexBuffer() { - glDeleteBuffers(1, &mBufferID); + glDeleteBuffers(1, &m_bufferId); } // activate void IndexBuffer::Activate() { - assert(mBufferID != MCORE_INVALIDINDEX32); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mBufferID); + assert(m_bufferId != MCORE_INVALIDINDEX32); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_bufferId); } @@ -64,8 +64,8 @@ namespace RenderGL } // generate the buffer ID and bind it - glGenBuffers(1, &mBufferID); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mBufferID); + glGenBuffers(1, &m_bufferId); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_bufferId); glBufferData(GL_ELEMENT_ARRAY_BUFFER, (uint32)indexSize * numIndices, indexData, usageGL); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); /* @@ -103,7 +103,7 @@ namespace RenderGL } */ // adjust the number of indices - mNumIndices = numIndices; + m_numIndices = numIndices; return true; } @@ -112,7 +112,7 @@ namespace RenderGL // lock the buffer void* IndexBuffer::Lock(ELockMode lockMode) { - if (mNumIndices == 0) + if (m_numIndices == 0) { return nullptr; } @@ -135,8 +135,8 @@ namespace RenderGL } // lock the buffer - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mBufferID); - void* data = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, lockModeGL); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_bufferId); + void* data = m_glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, lockModeGL); // check for failure if (data == nullptr) @@ -165,12 +165,12 @@ namespace RenderGL // unlock the buffer void IndexBuffer::Unlock() { - if (mNumIndices == 0) + if (m_numIndices == 0) { return; } - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mBufferID); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_bufferId); glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/IndexBuffer.h b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/IndexBuffer.h index eef0ff1d7a..b09e5f394d 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/IndexBuffer.h +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/IndexBuffer.h @@ -35,8 +35,8 @@ namespace RenderGL void Activate(); - MCORE_INLINE uint32 GetBufferID() const { return mBufferID; } - MCORE_INLINE uint32 GetNumIndices() const { return mNumIndices; } + MCORE_INLINE uint32 GetBufferID() const { return m_bufferId; } + MCORE_INLINE uint32 GetNumIndices() const { return m_numIndices; } bool Init(EIndexSize indexSize, uint32 numIndices, EUsageMode usage, void* indexData = nullptr); @@ -44,8 +44,8 @@ namespace RenderGL void Unlock(); private: - uint32 mBufferID; // the buffer ID - uint32 mNumIndices; // the number of indices + uint32 m_bufferId; // the buffer ID + uint32 m_numIndices; // the number of indices // helpers bool GetIsSuccess(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/Material.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/Material.cpp index 0cdaa6d327..f79f8c3edd 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/Material.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/Material.cpp @@ -17,7 +17,7 @@ namespace RenderGL // constructor Material::Material(GLActor* actor) { - mActor = actor; + m_actor = actor; } @@ -52,7 +52,7 @@ namespace RenderGL Texture* Material::LoadTexture(const char* fileName, bool genMipMaps) { Texture* result = nullptr; - AZStd::string filename = mActor->GetTexturePath() + fileName; + AZStd::string filename = m_actor->GetTexturePath() + fileName; AZStd::string extension; AzFramework::StringFunc::Path::GetExtension(fileName, extension, false /* include dot */); diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/Material.h b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/Material.h index 9c0522a6da..825fa4c7b0 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/Material.h +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/Material.h @@ -24,45 +24,45 @@ namespace RenderGL { Primitive() { - mVertexOffset = 0; - mIndexOffset = 0; - mNumTriangles = 0; - mNumVertices = 0; + m_vertexOffset = 0; + m_indexOffset = 0; + m_numTriangles = 0; + m_numVertices = 0; - mNodeIndex = InvalidIndex; - mMaterialIndex = MCORE_INVALIDINDEX32; + m_nodeIndex = InvalidIndex; + m_materialIndex = MCORE_INVALIDINDEX32; } - size_t mNodeIndex; /**< The index of the node to which this primitive belongs to. */ - uint32 mVertexOffset; - uint32 mIndexOffset; /**< The starting index. */ - uint32 mNumTriangles; /**< The number of triangles in the primitive. */ - uint32 mNumVertices; /**< The number of vertices in the primitive. */ - uint32 mMaterialIndex; /**< The material index which is mapped to the primitive. */ + size_t m_nodeIndex; /**< The index of the node to which this primitive belongs to. */ + uint32 m_vertexOffset; + uint32 m_indexOffset; /**< The starting index. */ + uint32 m_numTriangles; /**< The number of triangles in the primitive. */ + uint32 m_numVertices; /**< The number of vertices in the primitive. */ + uint32 m_materialIndex; /**< The material index which is mapped to the primitive. */ - AZStd::vector mBoneNodeIndices;/**< Mapping from local bones 0-50 to nodes. */ + AZStd::vector m_boneNodeIndices;/**< Mapping from local bones 0-50 to nodes. */ }; // StandardVertex struct RENDERGL_API StandardVertex { - AZ::Vector3 mPosition; - AZ::Vector3 mNormal; - AZ::Vector4 mTangent; - AZ::Vector2 mUV; + AZ::Vector3 m_position; + AZ::Vector3 m_normal; + AZ::Vector4 m_tangent; + AZ::Vector2 m_uv; }; // SkinnedVertex struct RENDERGL_API SkinnedVertex { - AZ::Vector3 mPosition; - AZ::Vector3 mNormal; - AZ::Vector4 mTangent; - AZ::Vector2 mUV; - float mWeights[4]; - float mBoneIndices[4]; + AZ::Vector3 m_position; + AZ::Vector3 m_normal; + AZ::Vector4 m_tangent; + AZ::Vector2 m_uv; + float m_weights[4]; + float m_boneIndices[4]; }; @@ -103,7 +103,7 @@ namespace RenderGL Texture* LoadTexture(const char* fileName); const char* AttributeToString(const EAttribute attribute); - GLActor* mActor; + GLActor* m_actor; }; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/PostProcessShader.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/PostProcessShader.cpp index 84c369bcbc..a3ca0f33c4 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/PostProcessShader.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/PostProcessShader.cpp @@ -17,7 +17,7 @@ namespace RenderGL // default constructor PostProcessShader::PostProcessShader() { - mRT = nullptr; + m_rt = nullptr; } @@ -30,8 +30,8 @@ namespace RenderGL void PostProcessShader::ActivateRT(RenderTexture* target) { // Activate rt - mRT = target; - mRT->Activate(); + m_rt = target; + m_rt->Activate(); GLSLShader::Activate(); } @@ -73,8 +73,8 @@ namespace RenderGL { GLSLShader::Deactivate(); - mRT->Deactivate(); - mRT = nullptr; + m_rt->Deactivate(); + m_rt = nullptr; } @@ -89,8 +89,8 @@ namespace RenderGL // Render void PostProcessShader::Render() { - const float w = static_cast(mRT->GetWidth()); - const float h = static_cast(mRT->GetHeight()); + const float w = static_cast(m_rt->GetWidth()); + const float h = static_cast(m_rt->GetHeight()); // Setup ortho projection glMatrixMode(GL_PROJECTION); diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/PostProcessShader.h b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/PostProcessShader.h index 9e976d599e..644e47b9b9 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/PostProcessShader.h +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/PostProcessShader.h @@ -36,7 +36,7 @@ namespace RenderGL private: - RenderTexture* mRT; + RenderTexture* m_rt; }; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/RenderTexture.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/RenderTexture.cpp index d0285c457d..ac85fcf7d7 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/RenderTexture.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/RenderTexture.cpp @@ -19,21 +19,21 @@ namespace RenderGL // constructor RenderTexture::RenderTexture() { - mFormat = 0; - mWidth = 0; - mHeight = 0; - mFrameBuffer = 0; - mDepthBuffer = 0; - mTexture = 0; + m_format = 0; + m_width = 0; + m_height = 0; + m_frameBuffer = 0; + m_depthBuffer = 0; + m_texture = 0; } // destructor RenderTexture::~RenderTexture() { - glDeleteTextures(1, &mTexture); - glDeleteRenderbuffers(1, &mDepthBuffer); - glDeleteFramebuffers(1, &mFrameBuffer); + glDeleteTextures(1, &m_texture); + glDeleteRenderbuffers(1, &m_depthBuffer); + glDeleteFramebuffers(1, &m_frameBuffer); } @@ -47,15 +47,15 @@ namespace RenderGL // get the width and height of the current used viewport float glDimensions[4]; glGetFloatv(GL_VIEWPORT, glDimensions); - mPrevWidth = (uint32)glDimensions[2]; - mPrevHeight = (uint32)glDimensions[3]; + m_prevWidth = (uint32)glDimensions[2]; + m_prevHeight = (uint32)glDimensions[3]; // bind the render texture and frame buffer glBindTexture(GL_TEXTURE_2D, 0); - glBindFramebuffer(GL_FRAMEBUFFER, mFrameBuffer); + glBindFramebuffer(GL_FRAMEBUFFER, m_frameBuffer); // setup the new viewport - glViewport(0, 0, mWidth, mHeight); + glViewport(0, 0, m_width, m_height); GetGraphicsManager()->SetRenderTexture(this); } @@ -63,7 +63,7 @@ namespace RenderGL // clear the render texture void RenderTexture::Clear(const MCore::RGBAColor& color) { - glClearColor(color.r, color.g, color.b, color.a); + glClearColor(color.m_r, color.m_g, color.m_b, color.m_a); glClearDepth(1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); } @@ -76,7 +76,7 @@ namespace RenderGL glBindFramebuffer(GL_FRAMEBUFFER, 0); // reset viewport to original dimensions - glViewport(0, 0, mPrevWidth, mPrevHeight); + glViewport(0, 0, m_prevWidth, m_prevHeight); GetGraphicsManager()->SetRenderTexture(nullptr); } @@ -84,10 +84,10 @@ namespace RenderGL // initialize the render texture bool RenderTexture::Init(int32 format, uint32 width, uint32 height, AZ::u32 depthBuffer) { - mFormat = format; - mWidth = width; - mHeight = height; - mDepthBuffer = depthBuffer; + m_format = format; + m_width = width; + m_height = height; + m_depthBuffer = depthBuffer; // check if the graphics hardware is capable of rendering to textures, return false if not if (hasOpenGLFeature(Framebuffers)) @@ -96,51 +96,51 @@ namespace RenderGL } // create surface IDs - glGenFramebuffers(1, &mFrameBuffer); - glGenTextures(1, &mTexture); + glGenFramebuffers(1, &m_frameBuffer); + glGenTextures(1, &m_texture); // if the depth buffer was not specified, generate it - if (mDepthBuffer == 0) + if (m_depthBuffer == 0) { - glGenRenderbuffers(1, &mDepthBuffer); + glGenRenderbuffers(1, &m_depthBuffer); } // check if initalization of the texture, the frame buffer and the depth buffer worked okay - if (mFrameBuffer == 0 || mDepthBuffer == 0 || mTexture == 0) + if (m_frameBuffer == 0 || m_depthBuffer == 0 || m_texture == 0) { - MCore::LogWarning("[OpenGL] RenderTexture failed to init (5d, %d, %d)", mFrameBuffer, mDepthBuffer, mTexture); + MCore::LogWarning("[OpenGL] RenderTexture failed to init (5d, %d, %d)", m_frameBuffer, m_depthBuffer, m_texture); return false; } // create the frame buffer object - glBindFramebuffer(GL_FRAMEBUFFER, mFrameBuffer); + glBindFramebuffer(GL_FRAMEBUFFER, m_frameBuffer); // setup channels GLenum glChannels = GL_RGBA; - if (mFormat == GL_ALPHA16F_ARB || mFormat == GL_ALPHA32F_ARB) + if (m_format == GL_ALPHA16F_ARB || m_format == GL_ALPHA32F_ARB) { glChannels = GL_ALPHA; } // create render target - glBindTexture(GL_TEXTURE_2D, mTexture); - glTexImage2D(GL_TEXTURE_2D, 0, mFormat, mWidth, mHeight, 0, glChannels, GL_FLOAT, nullptr); + glBindTexture(GL_TEXTURE_2D, m_texture); + glTexImage2D(GL_TEXTURE_2D, 0, m_format, m_width, m_height, 0, glChannels, GL_FLOAT, nullptr); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture, 0); // create depth buffer if (depthBuffer == 0) { - glBindRenderbuffer(GL_RENDERBUFFER, mDepthBuffer); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, mWidth, mHeight); + glBindRenderbuffer(GL_RENDERBUFFER, m_depthBuffer); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, m_width, m_height); } - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mDepthBuffer); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthBuffer); if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/RenderTexture.h b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/RenderTexture.h index 51797e5c38..9839ca0a5f 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/RenderTexture.h +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/RenderTexture.h @@ -49,8 +49,8 @@ namespace RenderGL void Render(); - AZ::u32 GetDepthBuffer() const { return mDepthBuffer; } - int32 GetFormat() const { return mFormat; } + AZ::u32 GetDepthBuffer() const { return m_depthBuffer; } + int32 GetFormat() const { return m_format; } /** * Formats: GL_RGBA32F_ARB @@ -60,11 +60,11 @@ namespace RenderGL bool Init(int32 format, uint32 width, uint32 height, AZ::u32 depthBuffer = 0); private: - int32 mFormat; /*< . */ - uint32 mPrevHeight; /*< . */ - uint32 mPrevWidth; /*< . */ - AZ::u32 mFrameBuffer; - AZ::u32 mDepthBuffer; + int32 m_format; /*< . */ + uint32 m_prevHeight; /*< . */ + uint32 m_prevWidth; /*< . */ + AZ::u32 m_frameBuffer; + AZ::u32 m_depthBuffer; }; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/ShaderCache.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/ShaderCache.cpp index b02ab99505..4d25017831 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/ShaderCache.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/ShaderCache.cpp @@ -15,7 +15,7 @@ namespace RenderGL // constructor ShaderCache::ShaderCache() { - mEntries.reserve(128); + m_entries.reserve(128); } @@ -30,41 +30,41 @@ namespace RenderGL void ShaderCache::Release() { // delete all shaders - for (Entry& entry : mEntries) + for (Entry& entry : m_entries) { - entry.mName.clear(); - delete entry.mShader; + entry.m_name.clear(); + delete entry.m_shader; } // clear all entries - mEntries.clear(); + m_entries.clear(); } // add the shader to the cache (assume there are no duplicate names) void ShaderCache::AddShader(AZStd::string_view filename, Shader* shader) { - mEntries.emplace_back(Entry{filename, shader}); + m_entries.emplace_back(Entry{filename, shader}); } // try to locate a shader based on its name Shader* ShaderCache::FindShader(AZStd::string_view filename) const { - const auto foundShader = AZStd::find_if(begin(mEntries), end(mEntries), [filename](const Entry& entry) + const auto foundShader = AZStd::find_if(begin(m_entries), end(m_entries), [filename](const Entry& entry) { - return AzFramework::StringFunc::Equal(entry.mName, filename, false /* no case */); + return AzFramework::StringFunc::Equal(entry.m_name, filename, false /* no case */); }); - return foundShader != end(mEntries) ? foundShader->mShader : nullptr; + return foundShader != end(m_entries) ? foundShader->m_shader : nullptr; } // check if we have a given shader in the cache bool ShaderCache::CheckIfHasShader(Shader* shader) const { - return AZStd::any_of(begin(mEntries), end(mEntries), [shader](const Entry& entry) + return AZStd::any_of(begin(m_entries), end(m_entries), [shader](const Entry& entry) { - return entry.mShader == shader; + return entry.m_shader == shader; }); } } // namespace RenderGL diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/StandardMaterial.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/StandardMaterial.cpp index 18281f286b..c2537e4948 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/StandardMaterial.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/StandardMaterial.cpp @@ -20,13 +20,13 @@ namespace RenderGL StandardMaterial::StandardMaterial(GLActor* actor) : Material(actor) { - mMaterial = nullptr; - mActiveShader = nullptr; - mAttributesUpdated = true; + m_material = nullptr; + m_activeShader = nullptr; + m_attributesUpdated = true; - mDiffuseMap = GetGraphicsManager()->GetTextureCache()->GetWhiteTexture(); - mSpecularMap = GetGraphicsManager()->GetTextureCache()->GetWhiteTexture(); - mNormalMap = GetGraphicsManager()->GetTextureCache()->GetDefaultNormalTexture(); + m_diffuseMap = GetGraphicsManager()->GetTextureCache()->GetWhiteTexture(); + m_specularMap = GetGraphicsManager()->GetTextureCache()->GetWhiteTexture(); + m_normalMap = GetGraphicsManager()->GetTextureCache()->GetDefaultNormalTexture(); SetAttribute(LIGHTING, true); SetAttribute(SKINNING, false); @@ -48,7 +48,7 @@ namespace RenderGL UpdateShader(); // check if the shader is valid and return in case it's not - if (mActiveShader == nullptr) + if (m_activeShader == nullptr) { return; } @@ -58,103 +58,99 @@ namespace RenderGL if (flags & GLOBAL) { - mActiveShader->Activate(); + m_activeShader->Activate(); // vertex attributes - uint32 stride = mAttributes[SKINNING] ? sizeof(SkinnedVertex) : sizeof(StandardVertex); + uint32 stride = m_attributes[SKINNING] ? sizeof(SkinnedVertex) : sizeof(StandardVertex); static char* structStart = reinterpret_cast(reinterpret_cast(static_cast(0))); - static size_t offsetOfNormal = static_cast((reinterpret_cast(&static_cast(0)->mNormal)) - structStart); - static size_t offsetOfTangent = static_cast((reinterpret_cast(&static_cast(0)->mTangent)) - structStart); - static size_t offsetOfUV = static_cast((reinterpret_cast(&static_cast(0)->mUV)) - structStart); - static size_t offsetOfWeights = static_cast((reinterpret_cast(&static_cast(0)->mWeights)) - structStart); - static size_t offsetOfBoneIndices = static_cast((reinterpret_cast(&static_cast(0)->mBoneIndices)) - structStart); + static size_t offsetOfNormal = static_cast((reinterpret_cast(&static_cast(0)->m_normal)) - structStart); + static size_t offsetOfTangent = static_cast((reinterpret_cast(&static_cast(0)->m_tangent)) - structStart); + static size_t offsetOfUV = static_cast((reinterpret_cast(&static_cast(0)->m_uv)) - structStart); + static size_t offsetOfWeights = static_cast((reinterpret_cast(&static_cast(0)->m_weights)) - structStart); + static size_t offsetOfBoneIndices = static_cast((reinterpret_cast(&static_cast(0)->m_boneIndices)) - structStart); - mActiveShader->SetAttribute("inPosition", 4, GL_FLOAT, stride, 0); - mActiveShader->SetAttribute("inNormal", 4, GL_FLOAT, stride, offsetOfNormal); - mActiveShader->SetAttribute("inTangent", 4, GL_FLOAT, stride, offsetOfTangent); - mActiveShader->SetAttribute("inUV", 2, GL_FLOAT, stride, offsetOfUV); + m_activeShader->SetAttribute("inPosition", 4, GL_FLOAT, stride, 0); + m_activeShader->SetAttribute("inNormal", 4, GL_FLOAT, stride, offsetOfNormal); + m_activeShader->SetAttribute("inTangent", 4, GL_FLOAT, stride, offsetOfTangent); + m_activeShader->SetAttribute("inUV", 2, GL_FLOAT, stride, offsetOfUV); // vertex weights & indices - if (mAttributes[SKINNING]) + if (m_attributes[SKINNING]) { - mActiveShader->SetAttribute("inWeights", 4, GL_FLOAT, stride, offsetOfWeights); - mActiveShader->SetAttribute("inIndices", 4, GL_FLOAT, stride, offsetOfBoneIndices); + m_activeShader->SetAttribute("inWeights", 4, GL_FLOAT, stride, offsetOfWeights); + m_activeShader->SetAttribute("inIndices", 4, GL_FLOAT, stride, offsetOfBoneIndices); } // set the view projection matrix MCommon::Camera* camera = GetGraphicsManager()->GetCamera(); - mActiveShader->SetUniform("matViewProj", camera->GetViewProjMatrix()); - mActiveShader->SetUniform("matView", camera->GetViewMatrix()); + m_activeShader->SetUniform("matViewProj", camera->GetViewProjMatrix()); + m_activeShader->SetUniform("matView", camera->GetViewMatrix()); - // lights - // if (mAttributes[LIGHTING]) { AZ::Vector3 mainLightDir(0.0f, -1.0f, 0.0f); mainLightDir = AZ::Matrix3x3::CreateRotationX(MCore::Math::DegreesToRadians(gfx->GetMainLightAngleB())) * AZ::Matrix3x3::CreateRotationZ(MCore::Math::DegreesToRadians(gfx->GetMainLightAngleA())) * mainLightDir; mainLightDir.Normalize(); - mActiveShader->SetUniform("mainLightDir", mainLightDir); - mActiveShader->SetUniform("skyColor", mActor->GetSkyColor() * gfx->GetMainLightIntensity()); - mActiveShader->SetUniform("groundColor", mActor->GetGroundColor()); - mActiveShader->SetUniform("eyePoint", camera->GetPosition()); + m_activeShader->SetUniform("mainLightDir", mainLightDir); + m_activeShader->SetUniform("skyColor", m_actor->GetSkyColor() * gfx->GetMainLightIntensity()); + m_activeShader->SetUniform("groundColor", m_actor->GetGroundColor()); + m_activeShader->SetUniform("eyePoint", camera->GetPosition()); AZ::Vector3 rimLightDir = MCore::GetUp(camera->GetViewMatrix()); rimLightDir = AZ::Matrix3x3::CreateRotationZ(MCore::Math::DegreesToRadians(gfx->GetRimAngle())) * rimLightDir; rimLightDir.Normalize(); - mActiveShader->SetUniform("rimLightDir", rimLightDir); + m_activeShader->SetUniform("rimLightDir", rimLightDir); - mActiveShader->SetUniform("rimLightFactor", gfx->GetRimIntensity()); - mActiveShader->SetUniform("rimWidth", gfx->GetRimWidth()); - mActiveShader->SetUniform("rimLightColor", gfx->GetRimColor()); + m_activeShader->SetUniform("rimLightFactor", gfx->GetRimIntensity()); + m_activeShader->SetUniform("rimWidth", gfx->GetRimWidth()); + m_activeShader->SetUniform("rimLightColor", gfx->GetRimColor()); } } // Local settings if (flags & LOCAL) { - EMotionFX::StandardMaterial* stdMaterial = (mMaterial->GetType() == EMotionFX::StandardMaterial::TYPE_ID) ? static_cast(mMaterial) : nullptr; + EMotionFX::StandardMaterial* stdMaterial = (m_material->GetType() == EMotionFX::StandardMaterial::TYPE_ID) ? static_cast(m_material) : nullptr; - if (mDiffuseMap == nullptr || mDiffuseMap == gfx->GetTextureCache()->GetWhiteTexture() && stdMaterial) + if (m_diffuseMap == nullptr || m_diffuseMap == gfx->GetTextureCache()->GetWhiteTexture() && stdMaterial) { - mActiveShader->SetUniform("diffuseColor", stdMaterial->GetDiffuse()); + m_activeShader->SetUniform("diffuseColor", stdMaterial->GetDiffuse()); } else { - mActiveShader->SetUniform("diffuseColor", MCore::RGBAColor(1.0f, 1.0f, 1.0f, 1.0f)); + m_activeShader->SetUniform("diffuseColor", MCore::RGBAColor(1.0f, 1.0f, 1.0f, 1.0f)); } - //if (mAttributes[LIGHTING]) { if (stdMaterial) { MCore::RGBAColor specularColor = stdMaterial->GetSpecular() * (stdMaterial->GetShineStrength() * gfx->GetMainLightIntensity() * gfx->GetSpecularIntensity()); - mActiveShader->SetUniform("specularPower", stdMaterial->GetShine()); - mActiveShader->SetUniform("lightSpecular", specularColor); + m_activeShader->SetUniform("specularPower", stdMaterial->GetShine()); + m_activeShader->SetUniform("lightSpecular", specularColor); } else { MCore::RGBAColor specularColor = MCore::RGBAColor(1.0f, 1.0f, 1.0f) * (1.0f * gfx->GetMainLightIntensity() * gfx->GetSpecularIntensity()); - mActiveShader->SetUniform("specularPower", 25.0f); - mActiveShader->SetUniform("lightSpecular", specularColor); + m_activeShader->SetUniform("specularPower", 25.0f); + m_activeShader->SetUniform("lightSpecular", specularColor); } - mActiveShader->SetUniform("normalMap", mNormalMap); + m_activeShader->SetUniform("normalMap", m_normalMap); } - //if (mAttributes[TEXTURING]) { - mActiveShader->SetUniform("diffuseMap", mDiffuseMap); - mActiveShader->SetUniform("specularMap", mSpecularMap); + m_activeShader->SetUniform("diffuseMap", m_diffuseMap); + m_activeShader->SetUniform("specularMap", m_specularMap); } } // update the advanced rendering settings - mActiveShader->SetUniform("glowThreshold", gfx->GetBloomThreshold()); - mActiveShader->SetUniform("focalPlaneDepth", gfx->GetDOFFocalDistance()); - mActiveShader->SetUniform("nearPlaneDepth", gfx->GetDOFNear()); - mActiveShader->SetUniform("farPlaneDepth", gfx->GetDOFFar()); - mActiveShader->SetUniform("blurCutoff", 1.0f); + m_activeShader->SetUniform("glowThreshold", gfx->GetBloomThreshold()); + m_activeShader->SetUniform("focalPlaneDepth", gfx->GetDOFFocalDistance()); + m_activeShader->SetUniform("nearPlaneDepth", gfx->GetDOFNear()); + m_activeShader->SetUniform("farPlaneDepth", gfx->GetDOFFar()); + m_activeShader->SetUniform("blurCutoff", 1.0f); } @@ -162,13 +158,13 @@ namespace RenderGL void StandardMaterial::Deactivate() { // check if the shader is valid and return in case it's not - if (mActiveShader == nullptr) + if (m_activeShader == nullptr) { return; } // deactivate the active shader - mActiveShader->Deactivate(); + m_activeShader->Deactivate(); } @@ -176,7 +172,7 @@ namespace RenderGL bool StandardMaterial::Init(EMotionFX::Material* material) { initializeOpenGLFunctions(); - mMaterial = material; + m_material = material; if (material->GetType() == EMotionFX::StandardMaterial::TYPE_ID) { @@ -191,34 +187,34 @@ namespace RenderGL { case EMotionFX::StandardMaterialLayer::LAYERTYPE_DIFFUSE: { - mDiffuseMap = LoadTexture(layer->GetFileName()); - if (mDiffuseMap == nullptr) + m_diffuseMap = LoadTexture(layer->GetFileName()); + if (m_diffuseMap == nullptr) { - mDiffuseMap = GetGraphicsManager()->GetTextureCache()->GetWhiteTexture(); + m_diffuseMap = GetGraphicsManager()->GetTextureCache()->GetWhiteTexture(); } } break; case EMotionFX::StandardMaterialLayer::LAYERTYPE_SHINESTRENGTH: { - mSpecularMap = LoadTexture(layer->GetFileName()); - if (mSpecularMap == nullptr) + m_specularMap = LoadTexture(layer->GetFileName()); + if (m_specularMap == nullptr) { - mSpecularMap = GetGraphicsManager()->GetTextureCache()->GetWhiteTexture(); + m_specularMap = GetGraphicsManager()->GetTextureCache()->GetWhiteTexture(); } } break; case EMotionFX::StandardMaterialLayer::LAYERTYPE_BUMP: { - mNormalMap = LoadTexture(layer->GetFileName()); - if (mNormalMap == nullptr) + m_normalMap = LoadTexture(layer->GetFileName()); + if (m_normalMap == nullptr) { - mNormalMap = GetGraphicsManager()->GetTextureCache()->GetDefaultNormalTexture(); + m_normalMap = GetGraphicsManager()->GetTextureCache()->GetDefaultNormalTexture(); } } break; case EMotionFX::StandardMaterialLayer::LAYERTYPE_NORMALMAP: { - mNormalMap = LoadTexture(layer->GetFileName()); - if (mNormalMap == nullptr) + m_normalMap = LoadTexture(layer->GetFileName()); + if (m_normalMap == nullptr) { - mNormalMap = GetGraphicsManager()->GetTextureCache()->GetDefaultNormalTexture(); + m_normalMap = GetGraphicsManager()->GetTextureCache()->GetDefaultNormalTexture(); } } break; } @@ -232,10 +228,10 @@ namespace RenderGL // void StandardMaterial::SetAttribute(EAttribute attribute, bool enabled) { - if (mAttributes[attribute] != enabled) + if (m_attributes[attribute] != enabled) { - mAttributes[attribute] = enabled; - mAttributesUpdated = true; + m_attributes[attribute] = enabled; + m_attributesUpdated = true; } } @@ -244,7 +240,7 @@ namespace RenderGL void StandardMaterial::Render(EMotionFX::ActorInstance* actorInstance, const Primitive* primitive) { // check if the shader is valid and return in case it's not - if (mActiveShader == nullptr) + if (m_activeShader == nullptr) { return; } @@ -257,20 +253,20 @@ namespace RenderGL const EMotionFX::TransformData* transformData = actorInstance->GetTransformData(); - if (mAttributes[SKINNING]) + if (m_attributes[SKINNING]) { const AZ::Matrix3x4* skinningMatrices = transformData->GetSkinningMatrices(); // multiple each transform by its inverse bind pose - const size_t numBones = primitive->mBoneNodeIndices.size(); + const size_t numBones = primitive->m_boneNodeIndices.size(); for (size_t i = 0; i < numBones; ++i) { - const size_t nodeNr = primitive->mBoneNodeIndices[i]; + const size_t nodeNr = primitive->m_boneNodeIndices[i]; const AZ::Matrix3x4& skinTransform = skinningMatrices[nodeNr]; - mBoneMatrices[i] = AZ::Matrix4x4::CreateFromMatrix3x4(skinTransform); + m_boneMatrices[i] = AZ::Matrix4x4::CreateFromMatrix3x4(skinTransform); } - mActiveShader->SetUniform("matBones", mBoneMatrices, aznumeric_caster(numBones)); + m_activeShader->SetUniform("matBones", m_boneMatrices, aznumeric_caster(numBones)); } const MCommon::Camera* camera = GetGraphicsManager()->GetCamera(); @@ -280,13 +276,13 @@ namespace RenderGL const AZ::Matrix4x4 worldViewProj = camera->GetViewProjMatrix() * world; const AZ::Matrix4x4 worldIT = world.GetInverseFull().GetTranspose(); - mActiveShader->SetUniform("matWorld", world); - mActiveShader->SetUniform("matWorldIT", worldIT); - mActiveShader->SetUniform("matWorldView", worldView); - mActiveShader->SetUniform("matWorldViewProj", worldViewProj); + m_activeShader->SetUniform("matWorld", world); + m_activeShader->SetUniform("matWorldIT", worldIT); + m_activeShader->SetUniform("matWorldView", worldView); + m_activeShader->SetUniform("matWorldViewProj", worldViewProj); // render the primitive - glDrawElementsBaseVertex(GL_TRIANGLES, primitive->mNumTriangles * 3, GL_UNSIGNED_INT, (GLvoid*)(primitive->mIndexOffset * sizeof(uint32)), primitive->mVertexOffset); + glDrawElementsBaseVertex(GL_TRIANGLES, primitive->m_numTriangles * 3, GL_UNSIGNED_INT, (GLvoid*)(primitive->m_indexOffset * sizeof(uint32)), primitive->m_vertexOffset); } @@ -294,16 +290,16 @@ namespace RenderGL void StandardMaterial::UpdateShader() { // check if any attibutes have changed and skip directly if not - if (mAttributesUpdated == false) + if (m_attributesUpdated == false) { return; } // reset the active shader - mActiveShader = nullptr; + m_activeShader = nullptr; // get the number of shaders and iterate through them - for (GLSLShader* shader : mShaders) + for (GLSLShader* shader : m_shaders) { if (shader == nullptr) { @@ -314,7 +310,7 @@ namespace RenderGL bool match = true; for (uint32 n = 0; n < NUM_ATTRIBUTES; ++n) { - if (mAttributes[n]) + if (m_attributes[n]) { if (shader->CheckIfIsDefined(AttributeToString((EAttribute)n)) == false) { @@ -335,13 +331,13 @@ namespace RenderGL // in case we have found a matching shader update the active shader if (match) { - mActiveShader = shader; + m_activeShader = shader; break; } } // if we didn't find a matching shader, compile it new - if (mActiveShader == nullptr) + if (m_activeShader == nullptr) { // if this function gets called at runtime something is wrong, go bug hunting! @@ -349,17 +345,17 @@ namespace RenderGL AZStd::vector defines; for (uint32 n = 0; n < NUM_ATTRIBUTES; ++n) { - if (mAttributes[n]) + if (m_attributes[n]) { defines.emplace_back(AttributeToString((EAttribute)n)); } } // compile shader and add it to the list of shaders - mActiveShader = GetGraphicsManager()->LoadShader("StandardMaterial_VS.glsl", "StandardMaterial_PS.glsl", defines); - mShaders.emplace_back(mActiveShader); + m_activeShader = GetGraphicsManager()->LoadShader("StandardMaterial_VS.glsl", "StandardMaterial_PS.glsl", defines); + m_shaders.emplace_back(m_activeShader); } - mAttributesUpdated = false; + m_attributesUpdated = false; } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/StandardMaterial.h b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/StandardMaterial.h index d9eb23b50a..528269765c 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/StandardMaterial.h +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/StandardMaterial.h @@ -41,17 +41,17 @@ namespace RenderGL protected: void UpdateShader(); - bool mAttributes[NUM_ATTRIBUTES]; - bool mAttributesUpdated; + bool m_attributes[NUM_ATTRIBUTES]; + bool m_attributesUpdated; - GLSLShader* mActiveShader; - AZStd::vector mShaders; - AZ::Matrix4x4 mBoneMatrices[200]; - EMotionFX::Material* mMaterial; + GLSLShader* m_activeShader; + AZStd::vector m_shaders; + AZ::Matrix4x4 m_boneMatrices[200]; + EMotionFX::Material* m_material; - Texture* mDiffuseMap; - Texture* mSpecularMap; - Texture* mNormalMap; + Texture* m_diffuseMap; + Texture* m_specularMap; + Texture* m_normalMap; }; } // namespace RenderGL diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/TextureCache.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/TextureCache.cpp index dfdce36284..b2e0f46b53 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/TextureCache.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/TextureCache.cpp @@ -18,9 +18,9 @@ namespace RenderGL Texture::Texture() { initializeOpenGLFunctions(); - mTexture = 0; - mWidth = 0; - mHeight = 0; + m_texture = 0; + m_width = 0; + m_height = 0; } @@ -28,26 +28,26 @@ namespace RenderGL Texture::Texture(GLuint texID, uint32 width, uint32 height) { initializeOpenGLFunctions(); - mTexture = texID; - mWidth = width; - mHeight = height; + m_texture = texID; + m_width = width; + m_height = height; } // destructor Texture::~Texture() { - glDeleteTextures(1, &mTexture); + glDeleteTextures(1, &m_texture); } // constructor TextureCache::TextureCache() { - mWhiteTexture = nullptr; - mDefaultNormalTexture = nullptr; + m_whiteTexture = nullptr; + m_defaultNormalTexture = nullptr; - mEntries.reserve(128); + m_entries.reserve(128); } @@ -73,27 +73,27 @@ namespace RenderGL void TextureCache::Release() { // delete all textures - for (Entry& entry : mEntries) + for (Entry& entry : m_entries) { - delete entry.mTexture; + delete entry.m_texture; } // clear all entries - mEntries.clear(); + m_entries.clear(); // delete the white texture - delete mWhiteTexture; - mWhiteTexture = nullptr; + delete m_whiteTexture; + m_whiteTexture = nullptr; - delete mDefaultNormalTexture; - mDefaultNormalTexture = nullptr; + delete m_defaultNormalTexture; + m_defaultNormalTexture = nullptr; } // add the texture to the cache (assume there are no duplicate names) void TextureCache::AddTexture(const char* filename, Texture* texture) { - mEntries.emplace_back(Entry{filename, texture}); + m_entries.emplace_back(Entry{filename, texture}); } @@ -101,11 +101,11 @@ namespace RenderGL Texture* TextureCache::FindTexture(const char* filename) const { // get the number of entries and iterate through them - const auto foundEntry = AZStd::find_if(begin(mEntries), end(mEntries), [filename](const Entry& entry) + const auto foundEntry = AZStd::find_if(begin(m_entries), end(m_entries), [filename](const Entry& entry) { - return AzFramework::StringFunc::Equal(entry.mName.c_str(), filename, false /* no case */); + return AzFramework::StringFunc::Equal(entry.m_name.c_str(), filename, false /* no case */); }); - return foundEntry != end(mEntries) ? foundEntry->mTexture : nullptr; + return foundEntry != end(m_entries) ? foundEntry->m_texture : nullptr; } @@ -113,9 +113,9 @@ namespace RenderGL bool TextureCache::CheckIfHasTexture(Texture* texture) const { // get the number of entries and iterate through them - return AZStd::any_of(begin(mEntries), end(mEntries), [texture](const Entry& entry) + return AZStd::any_of(begin(m_entries), end(m_entries), [texture](const Entry& entry) { - return entry.mTexture == texture; + return entry.m_texture == texture; }); } @@ -123,15 +123,15 @@ namespace RenderGL // remove an item from the cache void TextureCache::RemoveTexture(Texture* texture) { - const auto foundEntry = AZStd::find_if(begin(mEntries), end(mEntries), [texture](const Entry& entry) + const auto foundEntry = AZStd::find_if(begin(m_entries), end(m_entries), [texture](const Entry& entry) { - return entry.mTexture == texture; + return entry.m_texture == texture; }); - if (foundEntry != end(mEntries)) + if (foundEntry != end(m_entries)) { - delete foundEntry->mTexture; - mEntries.erase(foundEntry); + delete foundEntry->m_texture; + m_entries.erase(foundEntry); } } @@ -156,7 +156,7 @@ namespace RenderGL glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageBuffer); glBindTexture(GL_TEXTURE_2D, 0); - mWhiteTexture = new Texture(textureID, width, height); + m_whiteTexture = new Texture(textureID, width, height); return true; } @@ -182,7 +182,7 @@ namespace RenderGL glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageBuffer); glBindTexture(GL_TEXTURE_2D, 0); - mDefaultNormalTexture = new Texture(textureID, width, height); + m_defaultNormalTexture = new Texture(textureID, width, height); return true; } } // namespace RenderGL diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/TextureCache.h b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/TextureCache.h index 43d0f1a635..4350cd67c7 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/TextureCache.h +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/TextureCache.h @@ -28,14 +28,14 @@ namespace RenderGL Texture(AZ::u32 texID, uint32 width, uint32 height); ~Texture(); - MCORE_INLINE uint32 GetHeight() const { return mHeight; } - MCORE_INLINE AZ::u32 GetID() const { return mTexture; } - MCORE_INLINE uint32 GetWidth() const { return mWidth; } + MCORE_INLINE uint32 GetHeight() const { return m_height; } + MCORE_INLINE AZ::u32 GetID() const { return m_texture; } + MCORE_INLINE uint32 GetWidth() const { return m_width; } protected: - AZ::u32 mTexture; - uint32 mWidth; - uint32 mHeight; + AZ::u32 m_texture; + uint32 m_width; + uint32 m_height; }; @@ -56,8 +56,8 @@ namespace RenderGL void AddTexture(const char* filename, Texture* texture); Texture* FindTexture(const char* filename) const; - MCORE_INLINE Texture* GetWhiteTexture() { return mWhiteTexture; } - MCORE_INLINE Texture* GetDefaultNormalTexture() { return mDefaultNormalTexture; } + MCORE_INLINE Texture* GetWhiteTexture() { return m_whiteTexture; } + MCORE_INLINE Texture* GetDefaultNormalTexture() { return m_defaultNormalTexture; } bool CheckIfHasTexture(Texture* texture) const; bool Init(); void RemoveTexture(Texture* texture); @@ -68,13 +68,13 @@ namespace RenderGL struct Entry { - AZStd::string mName; // the search key (unique for each texture) - Texture* mTexture; + AZStd::string m_name; // the search key (unique for each texture) + Texture* m_texture; }; - AZStd::vector mEntries; - Texture* mWhiteTexture; - Texture* mDefaultNormalTexture; + AZStd::vector m_entries; + Texture* m_whiteTexture; + Texture* m_defaultNormalTexture; }; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/VertexBuffer.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/VertexBuffer.cpp index ef062bca0b..8c1587a00e 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/VertexBuffer.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/VertexBuffer.cpp @@ -17,15 +17,15 @@ namespace RenderGL // constructor VertexBuffer::VertexBuffer() { - mBufferID = MCORE_INVALIDINDEX32; - mNumVertices = 0; + m_bufferId = MCORE_INVALIDINDEX32; + m_numVertices = 0; } // destructor VertexBuffer::~VertexBuffer() { - glDeleteBuffers(1, &mBufferID); + glDeleteBuffers(1, &m_bufferId); glBindBuffer(GL_ARRAY_BUFFER, 0); } @@ -33,8 +33,8 @@ namespace RenderGL // activate void VertexBuffer::Activate() { - MCORE_ASSERT(mBufferID != MCORE_INVALIDINDEX32); - glBindBuffer(GL_ARRAY_BUFFER, mBufferID); + MCORE_ASSERT(m_bufferId != MCORE_INVALIDINDEX32); + glBindBuffer(GL_ARRAY_BUFFER, m_bufferId); } @@ -71,13 +71,13 @@ namespace RenderGL } // generate the buffer and bind it - glGenBuffers(1, &mBufferID); - glBindBuffer(GL_ARRAY_BUFFER, mBufferID); + glGenBuffers(1, &m_bufferId); + glBindBuffer(GL_ARRAY_BUFFER, m_bufferId); glBufferData(GL_ARRAY_BUFFER, numBytesPerVertex * numVertices, vertexData, usageGL); glBindBuffer(GL_ARRAY_BUFFER, 0); // adjust the number of vertices - mNumVertices = numVertices; + m_numVertices = numVertices; return true; } @@ -85,7 +85,7 @@ namespace RenderGL // lock the buffer void* VertexBuffer::Lock(ELockMode lockMode) { - if (mNumVertices == 0) + if (m_numVertices == 0) { return nullptr; } @@ -107,8 +107,8 @@ namespace RenderGL lockModeGL = GL_WRITE_ONLY; } - glBindBuffer(GL_ARRAY_BUFFER, mBufferID); - void* data = glMapBuffer(GL_ARRAY_BUFFER, lockModeGL); + glBindBuffer(GL_ARRAY_BUFFER, m_bufferId); + void* data = m_glMapBuffer(GL_ARRAY_BUFFER, lockModeGL); // is the data valid? if (data == nullptr) @@ -138,12 +138,12 @@ namespace RenderGL // unlock the buffer void VertexBuffer::Unlock() { - if (mNumVertices == 0) + if (m_numVertices == 0) { return; } - glBindBuffer(GL_ARRAY_BUFFER, mBufferID); + glBindBuffer(GL_ARRAY_BUFFER, m_bufferId); glUnmapBuffer(GL_ARRAY_BUFFER); glBindBuffer(GL_ARRAY_BUFFER, 0); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/VertexBuffer.h b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/VertexBuffer.h index 1579a89226..c76cf5137a 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/VertexBuffer.h +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/VertexBuffer.h @@ -50,8 +50,8 @@ namespace RenderGL void Activate(); void Deactivate(); - MCORE_INLINE uint32 GetBufferID() const { return mBufferID; } - MCORE_INLINE uint32 GetNumVertices() const { return mNumVertices; } + MCORE_INLINE uint32 GetBufferID() const { return m_bufferId; } + MCORE_INLINE uint32 GetNumVertices() const { return m_numVertices; } bool Init(uint32 numBytesPerVertex, uint32 numVertices, EUsageMode usage, void* vertexData = nullptr); @@ -59,8 +59,8 @@ namespace RenderGL void Unlock(); private: - uint32 mBufferID; // the buffer ID - uint32 mNumVertices; // the number of vertices + uint32 m_bufferId; // the buffer ID + uint32 m_numVertices; // the number of vertices bool GetIsSuccess(); bool GetHasError(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/glactor.h b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/glactor.h index 0b87477114..36158306a1 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/glactor.h +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/glactor.h @@ -47,29 +47,29 @@ namespace RenderGL bool Init(EMotionFX::Actor* actor, const char* texturePath, bool gpuSkinning = true, bool removeGPUSkinnedMeshes = true); - MCORE_INLINE EMotionFX::Actor* GetActor() { return mActor; } - MCORE_INLINE const AZStd::string& GetTexturePath() const { return mTexturePath; } + MCORE_INLINE EMotionFX::Actor* GetActor() { return m_actor; } + MCORE_INLINE const AZStd::string& GetTexturePath() const { return m_texturePath; } void Render(EMotionFX::ActorInstance* actorInstance, uint32 renderFlags = RENDER_LIGHTING | RENDER_TEXTURING); - const MCore::RGBAColor& GetSkyColor() const { return mSkyColor; } - const MCore::RGBAColor& GetGroundColor() const { return mGroundColor; } - void SetGroundColor(const MCore::RGBAColor& color) { mGroundColor = color; } - void SetSkyColor(const MCore::RGBAColor& color) { mSkyColor = color; } + const MCore::RGBAColor& GetSkyColor() const { return m_skyColor; } + const MCore::RGBAColor& GetGroundColor() const { return m_groundColor; } + void SetGroundColor(const MCore::RGBAColor& color) { m_groundColor = color; } + void SetSkyColor(const MCore::RGBAColor& color) { m_skyColor = color; } private: struct RENDERGL_API MaterialPrimitives { - Material* mMaterial; - AZStd::vector mPrimitives[3]; + Material* m_material; + AZStd::vector m_primitives[3]; - MaterialPrimitives() { mMaterial = nullptr; mPrimitives[0].reserve(64); mPrimitives[1].reserve(64); mPrimitives[2].reserve(64); } - MaterialPrimitives(Material* mat) { mMaterial = mat; mPrimitives[0].reserve(64); mPrimitives[1].reserve(64); mPrimitives[2].reserve(64); } + MaterialPrimitives() { m_material = nullptr; m_primitives[0].reserve(64); m_primitives[1].reserve(64); m_primitives[2].reserve(64); } + MaterialPrimitives(Material* mat) { m_material = mat; m_primitives[0].reserve(64); m_primitives[1].reserve(64); m_primitives[2].reserve(64); } }; - AZStd::string mTexturePath; - EMotionFX::Actor* mActor; - bool mEnableGPUSkinning; + AZStd::string m_texturePath; + EMotionFX::Actor* m_actor; + bool m_enableGpuSkinning; void Cleanup(); @@ -85,14 +85,14 @@ namespace RenderGL EMotionFX::Mesh::EMeshType ClassifyMeshType(EMotionFX::Node* node, EMotionFX::Mesh* mesh, size_t lodLevel); - AZStd::vector< AZStd::vector > mMaterials; - MCore::Array2D mDynamicNodes; - MCore::Array2D mPrimitives[3]; - AZStd::vector mHomoMaterials; - AZStd::vector mVertexBuffers[3]; - AZStd::vector mIndexBuffers[3]; - MCore::RGBAColor mGroundColor; - MCore::RGBAColor mSkyColor; + AZStd::vector< AZStd::vector > m_materials; + MCore::Array2D m_dynamicNodes; + MCore::Array2D m_primitives[3]; + AZStd::vector m_homoMaterials; + AZStd::vector m_vertexBuffers[3]; + AZStd::vector m_indexBuffers[3]; + MCore::RGBAColor m_groundColor; + MCore::RGBAColor m_skyColor; GLActor(); ~GLActor(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/shadercache.h b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/shadercache.h index 08bf9dfa58..d33cfcfd7d 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/shadercache.h +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/shadercache.h @@ -37,12 +37,12 @@ namespace RenderGL // a cache entry struct Entry { - AZStd::string mName; // the search key (unique for each shader) - Shader* mShader; + AZStd::string m_name; // the search key (unique for each shader) + Shader* m_shader; }; // - AZStd::vector mEntries; // the shader cache entries + AZStd::vector m_entries; // the shader cache entries }; } // namespace RenderGL diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp index 6f1293e1a3..df039b7186 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp @@ -57,14 +57,14 @@ namespace EMotionFX Actor::NodeLODInfo::NodeLODInfo() { - mMesh = nullptr; - mStack = nullptr; + m_mesh = nullptr; + m_stack = nullptr; } Actor::NodeLODInfo::~NodeLODInfo() { - MCore::Destroy(mMesh); - MCore::Destroy(mStack); + MCore::Destroy(m_mesh); + MCore::Destroy(m_stack); } //---------------------------------------------------- @@ -73,33 +73,33 @@ namespace EMotionFX { SetName(name); - mSkeleton = Skeleton::Create(); + m_skeleton = Skeleton::Create(); - mMotionExtractionNode = InvalidIndex; - mRetargetRootNode = InvalidIndex; - mThreadIndex = 0; - mCustomData = nullptr; - mID = aznumeric_caster(MCore::GetIDGenerator().GenerateID()); - mUnitType = GetEMotionFX().GetUnitType(); - mFileUnitType = mUnitType; + m_motionExtractionNode = InvalidIndex; + m_retargetRootNode = InvalidIndex; + m_threadIndex = 0; + m_customData = nullptr; + m_id = aznumeric_caster(MCore::GetIDGenerator().GenerateID()); + m_unitType = GetEMotionFX().GetUnitType(); + m_fileUnitType = m_unitType; m_staticAabb = AZ::Aabb::CreateNull(); - mUsedForVisualization = false; - mDirtyFlag = false; + m_usedForVisualization = false; + m_dirtyFlag = false; m_physicsSetup = AZStd::make_shared(); m_simulatedObjectSetup = AZStd::make_shared(this); m_optimizeSkeleton = false; #if defined(EMFX_DEVELOPMENT_BUILD) - mIsOwnedByRuntime = false; + m_isOwnedByRuntime = false; #endif // EMFX_DEVELOPMENT_BUILD // make sure we have at least allocated the first LOD of materials and facial setups - mMaterials.reserve(4); // reserve space for 4 lods - mMorphSetups.reserve(4); // - mMaterials.emplace_back(); - mMorphSetups.emplace_back(nullptr); + m_materials.reserve(4); // reserve space for 4 lods + m_morphSetups.reserve(4); // + m_materials.emplace_back(); + m_morphSetups.emplace_back(nullptr); GetEventManager().OnCreateActor(this); ActorNotificationBus::Broadcast(&ActorNotificationBus::Events::OnActorCreated, this); @@ -110,15 +110,15 @@ namespace EMotionFX ActorNotificationBus::Broadcast(&ActorNotificationBus::Events::OnActorDestroyed, this); GetEventManager().OnDeleteActor(this); - mNodeMirrorInfos.clear(); + m_nodeMirrorInfos.clear(); RemoveAllMaterials(); RemoveAllMorphSetups(); RemoveAllNodeGroups(); - mInvBindPoseTransforms.clear(); + m_invBindPoseTransforms.clear(); - MCore::Destroy(mSkeleton); + MCore::Destroy(m_skeleton); } // creates a clone of the actor (a copy). @@ -130,41 +130,41 @@ namespace EMotionFX result->SetFileName(GetFileName()); // copy the actor attributes - result->mMotionExtractionNode = mMotionExtractionNode; - result->mUnitType = mUnitType; - result->mFileUnitType = mFileUnitType; + result->m_motionExtractionNode = m_motionExtractionNode; + result->m_unitType = m_unitType; + result->m_fileUnitType = m_fileUnitType; result->m_staticAabb = m_staticAabb; - result->mRetargetRootNode = mRetargetRootNode; - result->mInvBindPoseTransforms = mInvBindPoseTransforms; + result->m_retargetRootNode = m_retargetRootNode; + result->m_invBindPoseTransforms = m_invBindPoseTransforms; result->m_optimizeSkeleton = m_optimizeSkeleton; result->m_skinToSkeletonIndexMap = m_skinToSkeletonIndexMap; result->RecursiveAddDependencies(this); // clone all nodes groups - for (uint32 i = 0; i < mNodeGroups.GetLength(); ++i) + for (uint32 i = 0; i < m_nodeGroups.GetLength(); ++i) { - result->AddNodeGroup(aznew NodeGroup(*mNodeGroups[i])); + result->AddNodeGroup(aznew NodeGroup(*m_nodeGroups[i])); } // clone the materials - result->mMaterials.resize(mMaterials.size()); - for (size_t i = 0; i < mMaterials.size(); ++i) + result->m_materials.resize(m_materials.size()); + for (size_t i = 0; i < m_materials.size(); ++i) { // get the number of materials in the current LOD - result->mMaterials[i].reserve(mMaterials[i].size()); - for (const Material* material : mMaterials[i]) + result->m_materials[i].reserve(m_materials[i].size()); + for (const Material* material : m_materials[i]) { result->AddMaterial(i, material->Clone()); } } // clone the skeleton - MCore::Destroy(result->mSkeleton); - result->mSkeleton = mSkeleton->Clone(); + MCore::Destroy(result->m_skeleton); + result->m_skeleton = m_skeleton->Clone(); // clone lod data - const size_t numNodes = mSkeleton->GetNumNodes(); + const size_t numNodes = m_skeleton->GetNumNodes(); const size_t numLodLevels = m_meshLodData.m_lodLevels.size(); MeshLODData& resultMeshLodData = result->m_meshLodData; @@ -172,26 +172,26 @@ namespace EMotionFX result->SetNumLODLevels(static_cast(numLodLevels)); for (size_t lodLevel = 0; lodLevel < numLodLevels; ++lodLevel) { - const AZStd::vector& nodeInfos = m_meshLodData.m_lodLevels[lodLevel].mNodeInfos; - AZStd::vector& resultNodeInfos = resultMeshLodData.m_lodLevels[lodLevel].mNodeInfos; + const AZStd::vector& nodeInfos = m_meshLodData.m_lodLevels[lodLevel].m_nodeInfos; + AZStd::vector& resultNodeInfos = resultMeshLodData.m_lodLevels[lodLevel].m_nodeInfos; resultNodeInfos.resize(numNodes); for (size_t n = 0; n < numNodes; ++n) { NodeLODInfo& resultNodeInfo = resultNodeInfos[n]; const NodeLODInfo& sourceNodeInfo = nodeInfos[n]; - resultNodeInfo.mMesh = (sourceNodeInfo.mMesh) ? sourceNodeInfo.mMesh->Clone() : nullptr; - resultNodeInfo.mStack = (sourceNodeInfo.mStack) ? sourceNodeInfo.mStack->Clone(resultNodeInfo.mMesh) : nullptr; + resultNodeInfo.m_mesh = (sourceNodeInfo.m_mesh) ? sourceNodeInfo.m_mesh->Clone() : nullptr; + resultNodeInfo.m_stack = (sourceNodeInfo.m_stack) ? sourceNodeInfo.m_stack->Clone(resultNodeInfo.m_mesh) : nullptr; } } // clone the morph setups - result->mMorphSetups.resize(mMorphSetups.size()); - for (size_t i = 0; i < mMorphSetups.size(); ++i) + result->m_morphSetups.resize(m_morphSetups.size()); + for (size_t i = 0; i < m_morphSetups.size(); ++i) { - if (mMorphSetups[i]) + if (m_morphSetups[i]) { - result->SetMorphSetup(i, mMorphSetups[i]->Clone()); + result->SetMorphSetup(i, m_morphSetups[i]->Clone()); } else { @@ -200,12 +200,12 @@ namespace EMotionFX } // make sure the number of root nodes is still the same - MCORE_ASSERT(result->GetSkeleton()->GetNumRootNodes() == mSkeleton->GetNumRootNodes()); + MCORE_ASSERT(result->GetSkeleton()->GetNumRootNodes() == m_skeleton->GetNumRootNodes()); // copy the transform data result->CopyTransformsFrom(this); - result->mNodeMirrorInfos = mNodeMirrorInfos; + result->m_nodeMirrorInfos = m_nodeMirrorInfos; result->m_physicsSetup = m_physicsSetup; result->SetSimulatedObjectSetup(m_simulatedObjectSetup->Clone(result.get())); @@ -222,37 +222,37 @@ namespace EMotionFX // init node mirror info void Actor::AllocateNodeMirrorInfos() { - const size_t numNodes = mSkeleton->GetNumNodes(); - mNodeMirrorInfos.resize(numNodes); + const size_t numNodes = m_skeleton->GetNumNodes(); + m_nodeMirrorInfos.resize(numNodes); // init the data for (size_t i = 0; i < numNodes; ++i) { - mNodeMirrorInfos[i].mSourceNode = static_cast(i); - mNodeMirrorInfos[i].mAxis = MCORE_INVALIDINDEX8; - mNodeMirrorInfos[i].mFlags = 0; + m_nodeMirrorInfos[i].m_sourceNode = static_cast(i); + m_nodeMirrorInfos[i].m_axis = MCORE_INVALIDINDEX8; + m_nodeMirrorInfos[i].m_flags = 0; } } // remove the node mirror info void Actor::RemoveNodeMirrorInfos() { - mNodeMirrorInfos.clear(); - mNodeMirrorInfos.shrink_to_fit(); + m_nodeMirrorInfos.clear(); + m_nodeMirrorInfos.shrink_to_fit(); } // check if we have our axes detected bool Actor::GetHasMirrorAxesDetected() const { - if (mNodeMirrorInfos.empty()) + if (m_nodeMirrorInfos.empty()) { return false; } - return AZStd::all_of(begin(mNodeMirrorInfos), end(mNodeMirrorInfos), [](const NodeMirrorInfo& nodeMirrorInfo) + return AZStd::all_of(begin(m_nodeMirrorInfos), end(m_nodeMirrorInfos), [](const NodeMirrorInfo& nodeMirrorInfo) { - return nodeMirrorInfo.mAxis != MCORE_INVALIDINDEX8; + return nodeMirrorInfo.m_axis != MCORE_INVALIDINDEX8; }); } @@ -261,7 +261,7 @@ namespace EMotionFX void Actor::RemoveAllMaterials() { // for all LODs - for (AZStd::vector& materials : mMaterials) + for (AZStd::vector& materials : m_materials) { // delete all materials for (Material* material : materials) @@ -270,7 +270,7 @@ namespace EMotionFX } } - mMaterials.clear(); + m_materials.clear(); } @@ -281,8 +281,8 @@ namespace EMotionFX lodLevels.emplace_back(); LODLevel& newLOD = lodLevels.back(); - const size_t numNodes = mSkeleton->GetNumNodes(); - newLOD.mNodeInfos.resize(numNodes); + const size_t numNodes = m_skeleton->GetNumNodes(); + newLOD.m_nodeInfos.resize(numNodes); const size_t numLODs = lodLevels.size(); const size_t lodIndex = numLODs - 1; @@ -290,25 +290,25 @@ namespace EMotionFX // get the number of nodes, iterate through them, create a new LOD level and copy over the meshes from the last LOD level for (size_t i = 0; i < numNodes; ++i) { - NodeLODInfo& newLODInfo = lodLevels[lodIndex].mNodeInfos[static_cast(i)]; + NodeLODInfo& newLODInfo = lodLevels[lodIndex].m_nodeInfos[static_cast(i)]; if (copyFromLastLODLevel && lodIndex > 0) { - const NodeLODInfo& prevLODInfo = lodLevels[lodIndex - 1].mNodeInfos[static_cast(i)]; - newLODInfo.mMesh = (prevLODInfo.mMesh) ? prevLODInfo.mMesh->Clone() : nullptr; - newLODInfo.mStack = (prevLODInfo.mStack) ? prevLODInfo.mStack->Clone(newLODInfo.mMesh) : nullptr; + const NodeLODInfo& prevLODInfo = lodLevels[lodIndex - 1].m_nodeInfos[static_cast(i)]; + newLODInfo.m_mesh = (prevLODInfo.m_mesh) ? prevLODInfo.m_mesh->Clone() : nullptr; + newLODInfo.m_stack = (prevLODInfo.m_stack) ? prevLODInfo.m_stack->Clone(newLODInfo.m_mesh) : nullptr; } else { - newLODInfo.mMesh = nullptr; - newLODInfo.mStack = nullptr; + newLODInfo.m_mesh = nullptr; + newLODInfo.m_stack = nullptr; } } // create a new material array for the new LOD level - mMaterials.resize(lodLevels.size()); + m_materials.resize(lodLevels.size()); // create an empty morph setup for the new LOD level - mMorphSetups.emplace_back(nullptr); + m_morphSetups.emplace_back(nullptr); // copy data from the previous LOD level if wanted if (copyFromLastLODLevel && numLODs > 0) @@ -325,22 +325,22 @@ namespace EMotionFX lodLevels.emplace(lodLevels.begin()+insertAt); LODLevel& newLOD = lodLevels[insertAt]; const size_t lodIndex = insertAt; - const size_t numNodes = mSkeleton->GetNumNodes(); - newLOD.mNodeInfos.resize(numNodes); + const size_t numNodes = m_skeleton->GetNumNodes(); + newLOD.m_nodeInfos.resize(numNodes); // get the number of nodes, iterate through them, create a new LOD level and copy over the meshes from the last LOD level for (size_t i = 0; i < numNodes; ++i) { - NodeLODInfo& lodInfo = lodLevels[lodIndex].mNodeInfos[i]; - lodInfo.mMesh = nullptr; - lodInfo.mStack = nullptr; + NodeLODInfo& lodInfo = lodLevels[lodIndex].m_nodeInfos[i]; + lodInfo.m_mesh = nullptr; + lodInfo.m_stack = nullptr; } // create a new material array for the new LOD level - mMaterials.emplace(AZStd::next(begin(mMaterials), insertAt)); + m_materials.emplace(AZStd::next(begin(m_materials), insertAt)); // create an empty morph setup for the new LOD level - mMorphSetups.emplace(AZStd::next(begin(mMorphSetups), insertAt), nullptr); + m_morphSetups.emplace(AZStd::next(begin(m_morphSetups), insertAt), nullptr); } // replace existing LOD level with the current actor @@ -352,10 +352,10 @@ namespace EMotionFX const LODLevel& sourceLOD = copyLodLevels[copyLODLevel]; LODLevel& targetLOD = lodLevels[replaceLODLevel]; - const size_t numNodes = mSkeleton->GetNumNodes(); + const size_t numNodes = m_skeleton->GetNumNodes(); for (size_t i = 0; i < numNodes; ++i) { - Node* node = mSkeleton->GetNode(i); + Node* node = m_skeleton->GetNode(i); Node* copyNode = copyActor->GetSkeleton()->FindNodeByID(node->GetID()); if (copyNode == nullptr) @@ -363,28 +363,28 @@ namespace EMotionFX MCore::LogWarning("Actor::CopyLODLevel() - Failed to find node '%s' in the actor we want to copy from.", node->GetName()); } - const NodeLODInfo& sourceNodeInfo = sourceLOD.mNodeInfos[ copyNode->GetNodeIndex() ]; - NodeLODInfo& targetNodeInfo = targetLOD.mNodeInfos[i]; + const NodeLODInfo& sourceNodeInfo = sourceLOD.m_nodeInfos[ copyNode->GetNodeIndex() ]; + NodeLODInfo& targetNodeInfo = targetLOD.m_nodeInfos[i]; // first get rid of existing data - MCore::Destroy(targetNodeInfo.mMesh); - targetNodeInfo.mMesh = nullptr; - MCore::Destroy(targetNodeInfo.mStack); - targetNodeInfo.mStack = nullptr; + MCore::Destroy(targetNodeInfo.m_mesh); + targetNodeInfo.m_mesh = nullptr; + MCore::Destroy(targetNodeInfo.m_stack); + targetNodeInfo.m_stack = nullptr; // if the node exists in both models if (copyNode) { // copy over the mesh and collision mesh - if (sourceNodeInfo.mMesh) + if (sourceNodeInfo.m_mesh) { - targetNodeInfo.mMesh = sourceNodeInfo.mMesh->Clone(); + targetNodeInfo.m_mesh = sourceNodeInfo.m_mesh->Clone(); } // handle the stacks - if (sourceNodeInfo.mStack) + if (sourceNodeInfo.m_stack) { - targetNodeInfo.mStack = sourceNodeInfo.mStack->Clone(targetNodeInfo.mMesh); + targetNodeInfo.m_stack = sourceNodeInfo.m_stack->Clone(targetNodeInfo.m_mesh); } // copy the skeletal LOD flag @@ -397,30 +397,30 @@ namespace EMotionFX // copy the materials const size_t numMaterials = copyActor->GetNumMaterials(copyLODLevel); - for (Material* i : mMaterials[replaceLODLevel]) + for (Material* i : m_materials[replaceLODLevel]) { i->Destroy(); } - mMaterials[replaceLODLevel].clear(); - mMaterials[replaceLODLevel].reserve(numMaterials); + m_materials[replaceLODLevel].clear(); + m_materials[replaceLODLevel].reserve(numMaterials); for (size_t i = 0; i < numMaterials; ++i) { AddMaterial(replaceLODLevel, copyActor->GetMaterial(copyLODLevel, i)->Clone()); } // copy the morph setup - if (mMorphSetups[replaceLODLevel]) + if (m_morphSetups[replaceLODLevel]) { - mMorphSetups[replaceLODLevel]->Destroy(); + m_morphSetups[replaceLODLevel]->Destroy(); } if (copyActor->GetMorphSetup(copyLODLevel)) { - mMorphSetups[replaceLODLevel] = copyActor->GetMorphSetup(copyLODLevel)->Clone(); + m_morphSetups[replaceLODLevel] = copyActor->GetMorphSetup(copyLODLevel)->Clone(); } else { - mMorphSetups[replaceLODLevel] = nullptr; + m_morphSetups[replaceLODLevel] = nullptr; } } @@ -430,30 +430,30 @@ namespace EMotionFX m_meshLodData.m_lodLevels.resize(numLODs); // reserve space for the materials - mMaterials.resize(numLODs); + m_materials.resize(numLODs); if (adjustMorphSetup) { - mMorphSetups.resize(numLODs); - AZStd::fill(begin(mMorphSetups), AZStd::next(begin(mMorphSetups), numLODs), nullptr); + m_morphSetups.resize(numLODs); + AZStd::fill(begin(m_morphSetups), AZStd::next(begin(m_morphSetups), numLODs), nullptr); } } // removes all node meshes and stacks void Actor::RemoveAllNodeMeshes() { - const size_t numNodes = mSkeleton->GetNumNodes(); + const size_t numNodes = m_skeleton->GetNumNodes(); AZStd::vector& lodLevels = m_meshLodData.m_lodLevels; for (LODLevel& lodLevel : lodLevels) { for (size_t i = 0; i < numNodes; ++i) { - NodeLODInfo& info = lodLevel.mNodeInfos[i]; - MCore::Destroy(info.mMesh); - info.mMesh = nullptr; - MCore::Destroy(info.mStack); - info.mStack = nullptr; + NodeLODInfo& info = lodLevel.m_nodeInfos[i]; + MCore::Destroy(info.m_mesh); + info.m_mesh = nullptr; + MCore::Destroy(info.m_stack); + info.m_stack = nullptr; } } } @@ -465,7 +465,7 @@ namespace EMotionFX uint32 totalVerts = 0; uint32 totalIndices = 0; - const size_t numNodes = mSkeleton->GetNumNodes(); + const size_t numNodes = m_skeleton->GetNumNodes(); for (size_t i = 0; i < numNodes; ++i) { Mesh* mesh = GetMesh(lodLevel, i); @@ -503,7 +503,7 @@ namespace EMotionFX uint32 totalIndices = 0; // for all nodes - const size_t numNodes = mSkeleton->GetNumNodes(); + const size_t numNodes = m_skeleton->GetNumNodes(); for (size_t i = 0; i < numNodes; ++i) { Mesh* mesh = GetMesh(lodLevel, i); @@ -547,7 +547,7 @@ namespace EMotionFX uint32 totalIndices = 0; // for all nodes - const size_t numNodes = mSkeleton->GetNumNodes(); + const size_t numNodes = m_skeleton->GetNumNodes(); for (size_t i = 0; i < numNodes; ++i) { Mesh* mesh = GetMesh(lodLevel, i); @@ -588,7 +588,7 @@ namespace EMotionFX { size_t maxInfluences = 0; - const size_t numNodes = mSkeleton->GetNumNodes(); + const size_t numNodes = m_skeleton->GetNumNodes(); for (size_t i = 0; i < numNodes; ++i) { Mesh* mesh = GetMesh(lodLevel, i); @@ -608,7 +608,7 @@ namespace EMotionFX void Actor::VerifySkinning(AZStd::vector& conflictNodeFlags, size_t skeletalLODLevel, size_t geometryLODLevel) { // get the number of nodes - const size_t numNodes = mSkeleton->GetNumNodes(); + const size_t numNodes = m_skeleton->GetNumNodes(); // check if the conflict node flag array's size is set to the number of nodes inside the actor if (conflictNodeFlags.size() != numNodes) @@ -623,7 +623,7 @@ namespace EMotionFX for (size_t n = 0; n < numNodes; ++n) { // get the current node and the pointer to the mesh for the given lod level - Node* node = mSkeleton->GetNode(n); + Node* node = m_skeleton->GetNode(n); Mesh* mesh = GetMesh(geometryLODLevel, n); // skip nodes without meshes @@ -696,7 +696,7 @@ namespace EMotionFX bool Actor::CheckIfHasMeshes(size_t lodLevel) const { // check if any of the nodes has a mesh - const size_t numNodes = mSkeleton->GetNumNodes(); + const size_t numNodes = m_skeleton->GetNumNodes(); for (size_t i = 0; i < numNodes; ++i) { if (GetMesh(lodLevel, i)) @@ -712,7 +712,7 @@ namespace EMotionFX bool Actor::CheckIfHasSkinnedMeshes(size_t lodLevel) const { - const size_t numNodes = mSkeleton->GetNumNodes(); + const size_t numNodes = m_skeleton->GetNumNodes(); for (size_t i = 0; i < numNodes; ++i) { const Mesh* mesh = GetMesh(lodLevel, i); @@ -749,7 +749,7 @@ namespace EMotionFX const size_t numLODs = GetNumLODLevels(); // for all LODs, get rid of all the morph setups for each geometry LOD - for (MorphSetup* morphSetup : mMorphSetups) + for (MorphSetup* morphSetup : m_morphSetups) { if (morphSetup) { @@ -763,7 +763,7 @@ namespace EMotionFX if (deleteMeshDeformers) { // for all nodes - const size_t numNodes = mSkeleton->GetNumNodes(); + const size_t numNodes = m_skeleton->GetNumNodes(); for (size_t i = 0; i < numNodes; ++i) { // process all LOD levels @@ -818,7 +818,7 @@ namespace EMotionFX bool Actor::CheckIfIsMaterialUsed(size_t lodLevel, size_t index) const { // iterate through all nodes of the actor and check its meshes - const size_t numNodes = mSkeleton->GetNumNodes(); + const size_t numNodes = m_skeleton->GetNumNodes(); for (size_t i = 0; i < numNodes; ++i) { // if the mesh is in LOD range check if it uses the material @@ -836,11 +836,11 @@ namespace EMotionFX // remove the given material and reassign all material numbers of the submeshes void Actor::RemoveMaterial(size_t lodLevel, size_t index) { - MCORE_ASSERT(lodLevel < mMaterials.size()); + MCORE_ASSERT(lodLevel < m_materials.size()); // first of all remove the given material - mMaterials[lodLevel][index]->Destroy(); - mMaterials[lodLevel].erase(AZStd::next(begin(mMaterials[lodLevel]), index)); + m_materials[lodLevel][index]->Destroy(); + m_materials[lodLevel].erase(AZStd::next(begin(m_materials[lodLevel]), index)); } @@ -854,11 +854,11 @@ namespace EMotionFX size_t maxNumChilds = 0; // traverse through all root nodes - const size_t numRootNodes = mSkeleton->GetNumRootNodes(); + const size_t numRootNodes = m_skeleton->GetNumRootNodes(); for (size_t i = 0; i < numRootNodes; ++i) { // get the given root node from the actor - Node* rootNode = mSkeleton->GetNode(mSkeleton->GetRootNodeIndex(i)); + Node* rootNode = m_skeleton->GetNode(m_skeleton->GetRootNodeIndex(i)); // get the number of child nodes recursively const size_t numChildNodes = rootNode->GetNumChildNodesRecursive(); @@ -890,7 +890,7 @@ namespace EMotionFX outBoneList->clear(); // for all nodes - const size_t numNodes = mSkeleton->GetNumNodes(); + const size_t numNodes = m_skeleton->GetNumNodes(); for (size_t n = 0; n < numNodes; ++n) { Mesh* mesh = GetMesh(lodLevel, n); @@ -938,22 +938,22 @@ namespace EMotionFX for (size_t i = 0; i < numDependencies; ++i) { // add it to the actor instance - mDependencies.emplace_back(*actor->GetDependency(i)); + m_dependencies.emplace_back(*actor->GetDependency(i)); // recursive into the actor we are dependent on - RecursiveAddDependencies(actor->GetDependency(i)->mActor); + RecursiveAddDependencies(actor->GetDependency(i)->m_actor); } } // remove all node groups void Actor::RemoveAllNodeGroups() { - const uint32 numGroups = mNodeGroups.GetLength(); + const uint32 numGroups = m_nodeGroups.GetLength(); for (uint32 i = 0; i < numGroups; ++i) { - delete mNodeGroups[i]; + delete m_nodeGroups[i]; } - mNodeGroups.Clear(); + m_nodeGroups.Clear(); } @@ -966,11 +966,11 @@ namespace EMotionFX AZStd::string nameB; // search through all nodes to find the best match - const size_t numNodes = mSkeleton->GetNumNodes(); + const size_t numNodes = m_skeleton->GetNumNodes(); for (size_t n = 0; n < numNodes; ++n) { // get the node name - const char* name = mSkeleton->GetNode(n)->GetName(); + const char* name = m_skeleton->GetNode(n)->GetName(); // check if a substring appears inside this node's name if (strstr(name, subStringB)) @@ -1023,28 +1023,28 @@ namespace EMotionFX bool Actor::MapNodeMotionSource(const char* sourceNodeName, const char* destNodeName) { // find the source node index - const size_t sourceNodeIndex = mSkeleton->FindNodeByNameNoCase(sourceNodeName)->GetNodeIndex(); + const size_t sourceNodeIndex = m_skeleton->FindNodeByNameNoCase(sourceNodeName)->GetNodeIndex(); if (sourceNodeIndex == InvalidIndex) { return false; } // find the dest node index - const size_t destNodeIndex = mSkeleton->FindNodeByNameNoCase(destNodeName)->GetNodeIndex(); + const size_t destNodeIndex = m_skeleton->FindNodeByNameNoCase(destNodeName)->GetNodeIndex(); if (destNodeIndex == InvalidIndex) { return false; } // allocate the data if we haven't already - if (mNodeMirrorInfos.empty()) + if (m_nodeMirrorInfos.empty()) { AllocateNodeMirrorInfos(); } // apply the mapping - mNodeMirrorInfos[ destNodeIndex ].mSourceNode = static_cast(sourceNodeIndex); - mNodeMirrorInfos[ sourceNodeIndex ].mSourceNode = static_cast(destNodeIndex); + m_nodeMirrorInfos[ destNodeIndex ].m_sourceNode = static_cast(sourceNodeIndex); + m_nodeMirrorInfos[ sourceNodeIndex ].m_sourceNode = static_cast(destNodeIndex); // we succeeded, because both source and dest have been found return true; @@ -1055,14 +1055,14 @@ namespace EMotionFX bool Actor::MapNodeMotionSource(uint16 sourceNodeIndex, uint16 targetNodeIndex) { // allocate the data if we haven't already - if (mNodeMirrorInfos.empty()) + if (m_nodeMirrorInfos.empty()) { AllocateNodeMirrorInfos(); } // apply the mapping - mNodeMirrorInfos[ targetNodeIndex ].mSourceNode = static_cast(sourceNodeIndex); - mNodeMirrorInfos[ sourceNodeIndex ].mSourceNode = static_cast(targetNodeIndex); + m_nodeMirrorInfos[ targetNodeIndex ].m_sourceNode = static_cast(sourceNodeIndex); + m_nodeMirrorInfos[ sourceNodeIndex ].m_sourceNode = static_cast(targetNodeIndex); // we succeeded, because both source and dest have been found return true; @@ -1075,10 +1075,10 @@ namespace EMotionFX void Actor::MatchNodeMotionSources(const char* subStringA, const char* subStringB) { // try to map all nodes - const size_t numNodes = mSkeleton->GetNumNodes(); + const size_t numNodes = m_skeleton->GetNumNodes(); for (size_t i = 0; i < numNodes; ++i) { - Node* node = mSkeleton->GetNode(i); + Node* node = m_skeleton->GetNode(i); // find the best match const uint16 bestIndex = FindBestMatchForNode(node->GetName(), subStringA, subStringB); @@ -1086,8 +1086,8 @@ namespace EMotionFX // if a best match has been found if (bestIndex != MCORE_INVALIDINDEX16) { - MCore::LogDetailedInfo("%s <---> %s", node->GetName(), mSkeleton->GetNode(bestIndex)->GetName()); - MapNodeMotionSource(node->GetName(), mSkeleton->GetNode(bestIndex)->GetName()); + MCore::LogDetailedInfo("%s <---> %s", node->GetName(), m_skeleton->GetNode(bestIndex)->GetName()); + MapNodeMotionSource(node->GetName(), m_skeleton->GetNode(bestIndex)->GetName()); } } } @@ -1096,14 +1096,14 @@ namespace EMotionFX // set the name of the actor void Actor::SetName(const char* name) { - mName = name; + m_name = name; } // set the filename of the actor void Actor::SetFileName(const char* filename) { - mFileName = filename; + m_fileName = filename; } @@ -1114,13 +1114,13 @@ namespace EMotionFX do { - curNodeIndex = mSkeleton->GetNode(curNodeIndex)->GetParentIndex(); + curNodeIndex = m_skeleton->GetNode(curNodeIndex)->GetParentIndex(); if (curNodeIndex == InvalidIndex) { return curNodeIndex; } - if (mSkeleton->GetNode(curNodeIndex)->GetSkeletalLODStatus(skeletalLOD)) + if (m_skeleton->GetNode(curNodeIndex)->GetSkeletalLODStatus(skeletalLOD)) { return curNodeIndex; } @@ -1140,10 +1140,10 @@ namespace EMotionFX for (size_t geomLod = 0; geomLod < numGeomLODs; ++geomLod) { // for all nodes - const size_t numNodes = mSkeleton->GetNumNodes(); + const size_t numNodes = m_skeleton->GetNumNodes(); for (size_t n = 0; n < numNodes; ++n) { - Node* node = mSkeleton->GetNode(n); + Node* node = m_skeleton->GetNode(n); // check if this node has a mesh, if not we can skip it Mesh* mesh = GetMesh(static_cast(geomLod), n); @@ -1182,7 +1182,7 @@ namespace EMotionFX { // if the bone is disabled SkinInfluence* influence = layer->GetInfluence(orgVertex, i); - if (mSkeleton->GetNode(influence->GetNodeNr())->GetSkeletalLODStatus(static_cast(geomLod)) == false) + if (m_skeleton->GetNode(influence->GetNodeNr())->GetSkeletalLODStatus(static_cast(geomLod)) == false) { // find the first parent bone that is enabled in this LOD const size_t newNodeIndex = FindFirstActiveParentBone(geomLod, influence->GetNodeNr()); @@ -1227,7 +1227,7 @@ namespace EMotionFX outPath.reserve(32); // start at the end effector - Node* currentNode = mSkeleton->GetNode(endNodeIndex); + Node* currentNode = m_skeleton->GetNode(endNodeIndex); while (currentNode) { // add the current node to the update list @@ -1252,16 +1252,16 @@ namespace EMotionFX void Actor::SetMotionExtractionNodeIndex(size_t nodeIndex) { - mMotionExtractionNode = nodeIndex; + m_motionExtractionNode = nodeIndex; ActorNotificationBus::Broadcast(&ActorNotificationBus::Events::OnMotionExtractionNodeChanged, this, GetMotionExtractionNode()); } Node* Actor::GetMotionExtractionNode() const { - if (mMotionExtractionNode != InvalidIndex && - mMotionExtractionNode < mSkeleton->GetNumNodes()) + if (m_motionExtractionNode != InvalidIndex && + m_motionExtractionNode < m_skeleton->GetNumNodes()) { - return mSkeleton->GetNode(mMotionExtractionNode); + return m_skeleton->GetNode(m_motionExtractionNode); } return nullptr; @@ -1270,10 +1270,10 @@ namespace EMotionFX void Actor::ReinitializeMeshDeformers() { const size_t numLODLevels = GetNumLODLevels(); - const size_t numNodes = mSkeleton->GetNumNodes(); + const size_t numNodes = m_skeleton->GetNumNodes(); for (size_t i = 0; i < numNodes; ++i) { - Node* node = mSkeleton->GetNode(i); + Node* node = m_skeleton->GetNode(i); // iterate through all LOD levels for (size_t lodLevel = 0; lodLevel < numLODLevels; ++lodLevel) @@ -1291,18 +1291,18 @@ namespace EMotionFX // post init void Actor::PostCreateInit(bool makeGeomLodsCompatibleWithSkeletalLODs, bool convertUnitType) { - if (mThreadIndex == MCORE_INVALIDINDEX32) + if (m_threadIndex == MCORE_INVALIDINDEX32) { - mThreadIndex = 0; + m_threadIndex = 0; } // calculate the inverse bind pose matrices const Pose* bindPose = GetBindPose(); - const size_t numNodes = mSkeleton->GetNumNodes(); - mInvBindPoseTransforms.resize(numNodes); + const size_t numNodes = m_skeleton->GetNumNodes(); + m_invBindPoseTransforms.resize(numNodes); for (size_t i = 0; i < numNodes; ++i) { - mInvBindPoseTransforms[i] = bindPose->GetModelSpaceTransform(i).Inversed(); + m_invBindPoseTransforms[i] = bindPose->GetModelSpaceTransform(i).Inversed(); } // make sure the skinning info doesn't use any disabled bones @@ -1315,12 +1315,12 @@ namespace EMotionFX ReinitializeMeshDeformers(); // make sure our world space bind pose is updated too - if (mMorphSetups.size() > 0 && mMorphSetups[0]) + if (m_morphSetups.size() > 0 && m_morphSetups[0]) { - mSkeleton->GetBindPose()->ResizeNumMorphs(mMorphSetups[0]->GetNumMorphTargets()); + m_skeleton->GetBindPose()->ResizeNumMorphs(m_morphSetups[0]->GetNumMorphTargets()); } - mSkeleton->GetBindPose()->ForceUpdateFullModelSpacePose(); - mSkeleton->GetBindPose()->ZeroMorphWeights(); + m_skeleton->GetBindPose()->ForceUpdateFullModelSpacePose(); + m_skeleton->GetBindPose()->ZeroMorphWeights(); if (!GetHasMirrorInfo()) { @@ -1446,10 +1446,10 @@ namespace EMotionFX { // Optional, not all actors have morph targets. const size_t numLODLevels = m_meshAsset->GetLodAssets().size(); - mMorphSetups.resize(numLODLevels); + m_morphSetups.resize(numLODLevels); for (size_t i = 0; i < numLODLevels; ++i) { - mMorphSetups[i] = nullptr; + m_morphSetups[i] = nullptr; } } @@ -1466,7 +1466,7 @@ namespace EMotionFX // update the static AABB (very heavy as it has to create an actor instance, update mesh deformers, calculate the mesh based bounds etc) void Actor::UpdateStaticAabb() { - ActorInstance* actorInstance = ActorInstance::Create(this, nullptr, mThreadIndex); + ActorInstance* actorInstance = ActorInstance::Create(this, nullptr, m_threadIndex); actorInstance->UpdateMeshDeformers(0.0f); actorInstance->UpdateStaticBasedAabbDimensions(); actorInstance->GetStaticBasedAabb(&m_staticAabb); @@ -1480,7 +1480,7 @@ namespace EMotionFX outPoints.clear(); const size_t geomLODLevel = 0; - const size_t numNodes = mSkeleton->GetNumNodes(); + const size_t numNodes = m_skeleton->GetNumNodes(); for (size_t nodeIndex = 0; nodeIndex < numNodes; nodeIndex++) { @@ -1548,17 +1548,17 @@ namespace EMotionFX Pose pose; pose.LinkToActor(this); - const size_t numNodes = mNodeMirrorInfos.size(); + const size_t numNodes = m_nodeMirrorInfos.size(); for (size_t i = 0; i < numNodes; ++i) { - const uint16 motionSource = (GetHasMirrorInfo()) ? GetNodeMirrorInfo(i).mSourceNode : static_cast(i); + const uint16 motionSource = (GetHasMirrorInfo()) ? GetNodeMirrorInfo(i).m_sourceNode : static_cast(i); // displace the local transform a bit, and calculate its mirrored model space position pose.InitFromBindPose(this); Transform localTransform = pose.GetLocalSpaceTransform(motionSource); Transform orgDelta = Transform::CreateIdentity(); - orgDelta.mPosition.Set(1.1f, 2.2f, 3.3f); - orgDelta.mRotation = MCore::AzEulerAnglesToAzQuat(0.1f, 0.2f, 0.3f); + orgDelta.m_position.Set(1.1f, 2.2f, 3.3f); + orgDelta.m_rotation = MCore::AzEulerAnglesToAzQuat(0.1f, 0.2f, 0.3f); Transform delta = orgDelta; delta.Multiply(localTransform); pose.SetLocalSpaceTransform(motionSource, delta); @@ -1584,12 +1584,11 @@ namespace EMotionFX const Transform& modelSpaceResult = pose.GetModelSpaceTransform(i); // check if we have a matching distance in model space - const float dist = MCore::SafeLength(modelSpaceResult.mPosition - endModelSpaceTransform.mPosition); + const float dist = MCore::SafeLength(modelSpaceResult.m_position - endModelSpaceTransform.m_position); if (dist <= MCore::Math::epsilon) { - //MCore::LogInfo("%s = %f (axis=%d)", mNodes[i]->GetName(), dist, a); - mNodeMirrorInfos[i].mAxis = a; - mNodeMirrorInfos[i].mFlags = 0; + m_nodeMirrorInfos[i].m_axis = a; + m_nodeMirrorInfos[i].m_flags = 0; found = true; break; } @@ -1637,12 +1636,11 @@ namespace EMotionFX const Transform& modelSpaceResult = pose.GetModelSpaceTransform(i); // check if we have a matching distance in world space - const float dist = MCore::SafeLength(modelSpaceResult.mPosition - endModelSpaceTransform.mPosition); + const float dist = MCore::SafeLength(modelSpaceResult.m_position - endModelSpaceTransform.m_position); if (dist <= MCore::Math::epsilon) { - //MCore::LogInfo("*** %s = %f (axis=%d) (flip=%d)", mNodes[i]->GetName(), dist, a, f); - mNodeMirrorInfos[i].mAxis = a; - mNodeMirrorInfos[i].mFlags = flags; + m_nodeMirrorInfos[i].m_axis = a; + m_nodeMirrorInfos[i].m_flags = flags; found = true; break; } @@ -1665,9 +1663,8 @@ namespace EMotionFX if (found == false) { - mNodeMirrorInfos[i].mAxis = bestAxis; - mNodeMirrorInfos[i].mFlags = bestFlags; - //MCore::LogInfo("best for %s = %f (axis=%d) (flags=%d)", mNodes[i]->GetName(), minDist, bestAxis, bestFlags); + m_nodeMirrorInfos[i].m_axis = bestAxis; + m_nodeMirrorInfos[i].m_flags = bestFlags; } } } @@ -1676,21 +1673,21 @@ namespace EMotionFX // get the array of node mirror infos const AZStd::vector& Actor::GetNodeMirrorInfos() const { - return mNodeMirrorInfos; + return m_nodeMirrorInfos; } // get the array of node mirror infos AZStd::vector& Actor::GetNodeMirrorInfos() { - return mNodeMirrorInfos; + return m_nodeMirrorInfos; } // set the node mirror infos directly void Actor::SetNodeMirrorInfos(const AZStd::vector& mirrorInfos) { - mNodeMirrorInfos = mirrorInfos; + m_nodeMirrorInfos = mirrorInfos; } @@ -1700,11 +1697,9 @@ namespace EMotionFX Pose pose; pose.InitFromBindPose(this); - const uint16 numNodes = static_cast(mSkeleton->GetNumNodes()); + const uint16 numNodes = static_cast(m_skeleton->GetNumNodes()); for (uint16 i = 0; i < numNodes; ++i) { - //Node* node = mNodes[i]; - // find the best match const uint16 bestIndex = FindBestMirrorMatchForNode(i, pose); @@ -1721,7 +1716,7 @@ namespace EMotionFX // find the best matching node index uint16 Actor::FindBestMirrorMatchForNode(uint16 nodeIndex, Pose& pose) const { - if (mSkeleton->GetNode(nodeIndex)->GetIsRootNode()) + if (m_skeleton->GetNode(nodeIndex)->GetIsRootNode()) { return MCORE_INVALIDINDEX16; } @@ -1734,7 +1729,7 @@ namespace EMotionFX uint16 result = MCORE_INVALIDINDEX16; // find nodes that have the mirrored transform - const size_t numNodes = mSkeleton->GetNumNodes(); + const size_t numNodes = m_skeleton->GetNumNodes(); for (size_t i = 0; i < numNodes; ++i) { const Transform& curNodeTransform = pose.GetModelSpaceTransform(i); @@ -1743,12 +1738,12 @@ namespace EMotionFX // only check the translation for now #ifndef EMFX_SCALE_DISABLED if (MCore::Compare::CheckIfIsClose( - curNodeTransform.mPosition, - mirroredTransform.mPosition, MCore::Math::epsilon) && - MCore::Compare::CheckIfIsClose(MCore::SafeLength(curNodeTransform.mScale), - MCore::SafeLength(mirroredTransform.mScale), MCore::Math::epsilon)) + curNodeTransform.m_position, + mirroredTransform.m_position, MCore::Math::epsilon) && + MCore::Compare::CheckIfIsClose(MCore::SafeLength(curNodeTransform.m_scale), + MCore::SafeLength(mirroredTransform.m_scale), MCore::Math::epsilon)) #else - if (MCore::Compare::CheckIfIsClose(curNodeTransform.mPosition, mirroredTransform.mPosition, MCore::Math::epsilon)) + if (MCore::Compare::CheckIfIsClose(curNodeTransform.m_position, mirroredTransform.m_position, MCore::Math::epsilon)) #endif { numMatches++; @@ -1759,8 +1754,8 @@ namespace EMotionFX if (numMatches == 1) { - const size_t hierarchyDepth = mSkeleton->CalcHierarchyDepthForNode(nodeIndex); - const size_t matchingHierarchyDepth = mSkeleton->CalcHierarchyDepthForNode(result); + const size_t hierarchyDepth = m_skeleton->CalcHierarchyDepthForNode(nodeIndex); + const size_t matchingHierarchyDepth = m_skeleton->CalcHierarchyDepthForNode(result); if (hierarchyDepth != matchingHierarchyDepth) { return MCORE_INVALIDINDEX16; @@ -1776,7 +1771,7 @@ namespace EMotionFX // resize the transform arrays to the current number of nodes void Actor::ResizeTransformData() { - Pose& bindPose = *mSkeleton->GetBindPose(); + Pose& bindPose = *m_skeleton->GetBindPose(); bindPose.LinkToActor(this, Pose::FLAG_LOCALTRANSFORMREADY, false); const size_t numMorphs = bindPose.GetNumMorphWeights(); @@ -1785,55 +1780,55 @@ namespace EMotionFX bindPose.SetMorphWeight(i, 0.0f); } - mInvBindPoseTransforms.resize(mSkeleton->GetNumNodes()); + m_invBindPoseTransforms.resize(m_skeleton->GetNumNodes()); } // release any transform data void Actor::ReleaseTransformData() { - mSkeleton->GetBindPose()->Clear(); - mInvBindPoseTransforms.clear(); + m_skeleton->GetBindPose()->Clear(); + m_invBindPoseTransforms.clear(); } // copy transforms from another actor void Actor::CopyTransformsFrom(const Actor* other) { - MCORE_ASSERT(other->GetNumNodes() == mSkeleton->GetNumNodes()); + MCORE_ASSERT(other->GetNumNodes() == m_skeleton->GetNumNodes()); ResizeTransformData(); - mInvBindPoseTransforms = other->mInvBindPoseTransforms; - *mSkeleton->GetBindPose() = *other->GetSkeleton()->GetBindPose(); + m_invBindPoseTransforms = other->m_invBindPoseTransforms; + *m_skeleton->GetBindPose() = *other->GetSkeleton()->GetBindPose(); } void Actor::SetNumNodes(size_t numNodes) { - mSkeleton->SetNumNodes(numNodes); + m_skeleton->SetNumNodes(numNodes); AZStd::vector& lodLevels = m_meshLodData.m_lodLevels; for (LODLevel& lodLevel : lodLevels) { - lodLevel.mNodeInfos.resize(numNodes); + lodLevel.m_nodeInfos.resize(numNodes); } - Pose* bindPose = mSkeleton->GetBindPose(); + Pose* bindPose = m_skeleton->GetBindPose(); bindPose->LinkToActor(this, Pose::FLAG_LOCALTRANSFORMREADY, false); } void Actor::AddNode(Node* node) { - mSkeleton->AddNode(node); - mSkeleton->GetBindPose()->LinkToActor(this, Pose::FLAG_LOCALTRANSFORMREADY, false); + m_skeleton->AddNode(node); + m_skeleton->GetBindPose()->LinkToActor(this, Pose::FLAG_LOCALTRANSFORMREADY, false); // initialize the LOD data AZStd::vector& lodLevels = m_meshLodData.m_lodLevels; for (LODLevel& lodLevel : lodLevels) { - lodLevel.mNodeInfos.emplace_back(); + lodLevel.m_nodeInfos.emplace_back(); } - mSkeleton->GetBindPose()->LinkToActor(this, Pose::FLAG_LOCALTRANSFORMREADY, false); - mSkeleton->GetBindPose()->SetLocalSpaceTransform(mSkeleton->GetNumNodes() - 1, Transform::CreateIdentity()); + m_skeleton->GetBindPose()->LinkToActor(this, Pose::FLAG_LOCALTRANSFORMREADY, false); + m_skeleton->GetBindPose()->SetLocalSpaceTransform(m_skeleton->GetNumNodes() - 1, Transform::CreateIdentity()); } Node* Actor::AddNode(size_t nodeIndex, const char* name, size_t parentIndex) @@ -1855,37 +1850,37 @@ namespace EMotionFX void Actor::RemoveNode(size_t nr, bool delMem) { - mSkeleton->RemoveNode(nr, delMem); + m_skeleton->RemoveNode(nr, delMem); AZStd::vector& lodLevels = m_meshLodData.m_lodLevels; for (LODLevel& lodLevel : lodLevels) { - lodLevel.mNodeInfos.erase(AZStd::next(begin(lodLevel.mNodeInfos), nr)); + lodLevel.m_nodeInfos.erase(AZStd::next(begin(lodLevel.m_nodeInfos), nr)); } } void Actor::DeleteAllNodes() { - mSkeleton->RemoveAllNodes(); + m_skeleton->RemoveAllNodes(); AZStd::vector& lodLevels = m_meshLodData.m_lodLevels; for (LODLevel& lodLevel : lodLevels) { - lodLevel.mNodeInfos.clear(); + lodLevel.m_nodeInfos.clear(); } } void Actor::ReserveMaterials(size_t lodLevel, size_t numMaterials) { - mMaterials[lodLevel].reserve(numMaterials); + m_materials[lodLevel].reserve(numMaterials); } // get a material Material* Actor::GetMaterial(size_t lodLevel, size_t nr) const { - MCORE_ASSERT(lodLevel < mMaterials.size()); - MCORE_ASSERT(nr < mMaterials[lodLevel].size()); - return mMaterials[lodLevel][nr]; + MCORE_ASSERT(lodLevel < m_materials.size()); + MCORE_ASSERT(nr < m_materials[lodLevel].size()); + return m_materials[lodLevel][nr]; } @@ -1893,27 +1888,27 @@ namespace EMotionFX size_t Actor::FindMaterialIndexByName(size_t lodLevel, const char* name) const { // search through all materials - const auto foundMaterial = AZStd::find_if(mMaterials[lodLevel].begin(), mMaterials[lodLevel].end(), [name](const Material* material) + const auto foundMaterial = AZStd::find_if(m_materials[lodLevel].begin(), m_materials[lodLevel].end(), [name](const Material* material) { return material->GetNameString() == name; }); - return foundMaterial != mMaterials[lodLevel].end() ? AZStd::distance(mMaterials[lodLevel].begin(), foundMaterial) : InvalidIndex; + return foundMaterial != m_materials[lodLevel].end() ? AZStd::distance(m_materials[lodLevel].begin(), foundMaterial) : InvalidIndex; } // set a material void Actor::SetMaterial(size_t lodLevel, size_t nr, Material* mat) { - mMaterials[lodLevel][nr] = mat; + m_materials[lodLevel][nr] = mat; } void Actor::AddMaterial(size_t lodLevel, Material* mat) { - mMaterials[lodLevel].emplace_back(mat); + m_materials[lodLevel].emplace_back(mat); } size_t Actor::GetNumMaterials(size_t lodLevel) const { - return mMaterials[lodLevel].size(); + return m_materials[lodLevel].size(); } size_t Actor::GetNumLODLevels() const @@ -1924,67 +1919,67 @@ namespace EMotionFX void* Actor::GetCustomData() const { - return mCustomData; + return m_customData; } void Actor::SetCustomData(void* dataPointer) { - mCustomData = dataPointer; + m_customData = dataPointer; } const char* Actor::GetName() const { - return mName.c_str(); + return m_name.c_str(); } const AZStd::string& Actor::GetNameString() const { - return mName; + return m_name; } const char* Actor::GetFileName() const { - return mFileName.c_str(); + return m_fileName.c_str(); } const AZStd::string& Actor::GetFileNameString() const { - return mFileName; + return m_fileName; } void Actor::AddDependency(const Dependency& dependency) { - mDependencies.emplace_back(dependency); + m_dependencies.emplace_back(dependency); } void Actor::SetMorphSetup(size_t lodLevel, MorphSetup* setup) { - mMorphSetups[lodLevel] = setup; + m_morphSetups[lodLevel] = setup; } uint32 Actor::GetNumNodeGroups() const { - return mNodeGroups.GetLength(); + return m_nodeGroups.GetLength(); } NodeGroup* Actor::GetNodeGroup(uint32 index) const { - return mNodeGroups[index]; + return m_nodeGroups[index]; } void Actor::AddNodeGroup(NodeGroup* newGroup) { - mNodeGroups.Add(newGroup); + m_nodeGroups.Add(newGroup); } @@ -1992,16 +1987,16 @@ namespace EMotionFX { if (delFromMem) { - delete mNodeGroups[index]; + delete m_nodeGroups[index]; } - mNodeGroups.Remove(index); + m_nodeGroups.Remove(index); } void Actor::RemoveNodeGroup(NodeGroup* group, bool delFromMem) { - mNodeGroups.RemoveByValue(group); + m_nodeGroups.RemoveByValue(group); if (delFromMem) { delete group; @@ -2012,10 +2007,10 @@ namespace EMotionFX // find a group index by its name uint32 Actor::FindNodeGroupIndexByName(const char* groupName) const { - const uint32 numGroups = mNodeGroups.GetLength(); + const uint32 numGroups = m_nodeGroups.GetLength(); for (uint32 i = 0; i < numGroups; ++i) { - if (mNodeGroups[i]->GetNameString() == groupName) + if (m_nodeGroups[i]->GetNameString() == groupName) { return i; } @@ -2028,10 +2023,10 @@ namespace EMotionFX // find a group index by its name, but not case sensitive uint32 Actor::FindNodeGroupIndexByNameNoCase(const char* groupName) const { - const uint32 numGroups = mNodeGroups.GetLength(); + const uint32 numGroups = m_nodeGroups.GetLength(); for (uint32 i = 0; i < numGroups; ++i) { - if (AzFramework::StringFunc::Equal(mNodeGroups[i]->GetNameString().c_str(), groupName, false /* no case */)) + if (AzFramework::StringFunc::Equal(m_nodeGroups[i]->GetNameString().c_str(), groupName, false /* no case */)) { return i; } @@ -2044,12 +2039,12 @@ namespace EMotionFX // find a group by its name NodeGroup* Actor::FindNodeGroupByName(const char* groupName) const { - const uint32 numGroups = mNodeGroups.GetLength(); + const uint32 numGroups = m_nodeGroups.GetLength(); for (uint32 i = 0; i < numGroups; ++i) { - if (mNodeGroups[i]->GetNameString() == groupName) + if (m_nodeGroups[i]->GetNameString() == groupName) { - return mNodeGroups[i]; + return m_nodeGroups[i]; } } return nullptr; @@ -2059,12 +2054,12 @@ namespace EMotionFX // find a group by its name, but without case sensitivity NodeGroup* Actor::FindNodeGroupByNameNoCase(const char* groupName) const { - const uint32 numGroups = mNodeGroups.GetLength(); + const uint32 numGroups = m_nodeGroups.GetLength(); for (uint32 i = 0; i < numGroups; ++i) { - if (AzFramework::StringFunc::Equal(mNodeGroups[i]->GetNameString().c_str(), groupName, false /* no case */)) + if (AzFramework::StringFunc::Equal(m_nodeGroups[i]->GetNameString().c_str(), groupName, false /* no case */)) { - return mNodeGroups[i]; + return m_nodeGroups[i]; } } return nullptr; @@ -2073,31 +2068,31 @@ namespace EMotionFX void Actor::SetDirtyFlag(bool dirty) { - mDirtyFlag = dirty; + m_dirtyFlag = dirty; } bool Actor::GetDirtyFlag() const { - return mDirtyFlag; + return m_dirtyFlag; } void Actor::SetIsUsedForVisualization(bool flag) { - mUsedForVisualization = flag; + m_usedForVisualization = flag; } bool Actor::GetIsUsedForVisualization() const { - return mUsedForVisualization; + return m_usedForVisualization; } void Actor::SetIsOwnedByRuntime(bool isOwnedByRuntime) { #if defined(EMFX_DEVELOPMENT_BUILD) - mIsOwnedByRuntime = isOwnedByRuntime; + m_isOwnedByRuntime = isOwnedByRuntime; #else AZ_UNUSED(isOwnedByRuntime); #endif @@ -2107,7 +2102,7 @@ namespace EMotionFX bool Actor::GetIsOwnedByRuntime() const { #if defined(EMFX_DEVELOPMENT_BUILD) - return mIsOwnedByRuntime; + return m_isOwnedByRuntime; #else return true; #endif @@ -2128,20 +2123,20 @@ namespace EMotionFX Mesh* Actor::GetMesh(size_t lodLevel, size_t nodeIndex) const { const AZStd::vector& lodLevels = m_meshLodData.m_lodLevels; - return lodLevels[lodLevel].mNodeInfos[nodeIndex].mMesh; + return lodLevels[lodLevel].m_nodeInfos[nodeIndex].m_mesh; } MeshDeformerStack* Actor::GetMeshDeformerStack(size_t lodLevel, size_t nodeIndex) const { const AZStd::vector& lodLevels = m_meshLodData.m_lodLevels; - return lodLevels[lodLevel].mNodeInfos[nodeIndex].mStack; + return lodLevels[lodLevel].m_nodeInfos[nodeIndex].m_stack; } // set the mesh for a given node in a given LOD void Actor::SetMesh(size_t lodLevel, size_t nodeIndex, Mesh* mesh) { AZStd::vector& lodLevels = m_meshLodData.m_lodLevels; - lodLevels[lodLevel].mNodeInfos[nodeIndex].mMesh = mesh; + lodLevels[lodLevel].m_nodeInfos[nodeIndex].m_mesh = mesh; } @@ -2149,7 +2144,7 @@ namespace EMotionFX void Actor::SetMeshDeformerStack(size_t lodLevel, size_t nodeIndex, MeshDeformerStack* stack) { AZStd::vector& lodLevels = m_meshLodData.m_lodLevels; - lodLevels[lodLevel].mNodeInfos[nodeIndex].mStack = stack; + lodLevels[lodLevel].m_nodeInfos[nodeIndex].m_stack = stack; } // check if the mesh has a skinning deformer (either linear or dual quat) @@ -2178,43 +2173,43 @@ namespace EMotionFX AZStd::vector& lodLevels = m_meshLodData.m_lodLevels; LODLevel& lod = lodLevels[lodLevel]; - NodeLODInfo& nodeInfo = lod.mNodeInfos[nodeIndex]; + NodeLODInfo& nodeInfo = lod.m_nodeInfos[nodeIndex]; - if (destroyMesh && nodeInfo.mMesh) + if (destroyMesh && nodeInfo.m_mesh) { - MCore::Destroy(nodeInfo.mMesh); + MCore::Destroy(nodeInfo.m_mesh); } - if (destroyMesh && nodeInfo.mStack) + if (destroyMesh && nodeInfo.m_stack) { - MCore::Destroy(nodeInfo.mStack); + MCore::Destroy(nodeInfo.m_stack); } - nodeInfo.mMesh = nullptr; - nodeInfo.mStack = nullptr; + nodeInfo.m_mesh = nullptr; + nodeInfo.m_stack = nullptr; } void Actor::SetUnitType(MCore::Distance::EUnitType unitType) { - mUnitType = unitType; + m_unitType = unitType; } MCore::Distance::EUnitType Actor::GetUnitType() const { - return mUnitType; + return m_unitType; } void Actor::SetFileUnitType(MCore::Distance::EUnitType unitType) { - mFileUnitType = unitType; + m_fileUnitType = unitType; } MCore::Distance::EUnitType Actor::GetFileUnitType() const { - return mFileUnitType; + return m_fileUnitType; } @@ -2233,7 +2228,7 @@ namespace EMotionFX for (size_t i = 0; i < numNodes; ++i) { Transform transform = bindPose->GetLocalSpaceTransform(i); - transform.mPosition *= scaleFactor; + transform.m_position *= scaleFactor; bindPose->SetLocalSpaceTransform(i, transform); } bindPose->ForceUpdateFullModelSpacePose(); @@ -2241,7 +2236,7 @@ namespace EMotionFX // calculate the inverse bind pose matrices for (size_t i = 0; i < numNodes; ++i) { - mInvBindPoseTransforms[i] = bindPose->GetModelSpaceTransform(i).Inversed(); + m_invBindPoseTransforms[i] = bindPose->GetModelSpaceTransform(i).Inversed(); } // update static aabb @@ -2283,32 +2278,32 @@ namespace EMotionFX // scale everything to the given unit type void Actor::ScaleToUnitType(MCore::Distance::EUnitType targetUnitType) { - if (mUnitType == targetUnitType) + if (m_unitType == targetUnitType) { return; } // calculate the scale factor and scale - const float scaleFactor = static_cast(MCore::Distance::GetConversionFactor(mUnitType, targetUnitType)); + const float scaleFactor = static_cast(MCore::Distance::GetConversionFactor(m_unitType, targetUnitType)); Scale(scaleFactor); // update the unit type - mUnitType = targetUnitType; + m_unitType = targetUnitType; } // Try to figure out which axis points "up" for the motion extraction node. Actor::EAxis Actor::FindBestMatchingMotionExtractionAxis() const { - MCORE_ASSERT(mMotionExtractionNode != InvalidIndex); - if (mMotionExtractionNode == InvalidIndex) + MCORE_ASSERT(m_motionExtractionNode != InvalidIndex); + if (m_motionExtractionNode == InvalidIndex) { return AXIS_Y; } // Get the local space rotation matrix of the motion extraction node. - const Transform& localTransform = GetBindPose()->GetLocalSpaceTransform(mMotionExtractionNode); - const AZ::Matrix3x3 rotationMatrix = AZ::Matrix3x3::CreateFromQuaternion(localTransform.mRotation); + const Transform& localTransform = GetBindPose()->GetLocalSpaceTransform(m_motionExtractionNode); + const AZ::Matrix3x3 rotationMatrix = AZ::Matrix3x3::CreateFromQuaternion(localTransform.m_rotation); // Calculate angles between the up axis and each of the rotation's basis vectors. const AZ::Vector3 globalUpAxis(0.0f, 0.0f, 1.0f); @@ -2338,13 +2333,13 @@ namespace EMotionFX void Actor::SetRetargetRootNodeIndex(size_t nodeIndex) { - mRetargetRootNode = nodeIndex; + m_retargetRootNode = nodeIndex; } void Actor::SetRetargetRootNode(Node* node) { - mRetargetRootNode = node ? node->GetNodeIndex() : InvalidIndex; + m_retargetRootNode = node ? node->GetNodeIndex() : InvalidIndex; } void Actor::InsertJointAndParents(size_t jointIndex, AZStd::unordered_set& includedJointIndices) @@ -2356,7 +2351,7 @@ namespace EMotionFX } // Add the parent. - const size_t parentIndex = mSkeleton->GetNode(jointIndex)->GetParentIndex(); + const size_t parentIndex = m_skeleton->GetNode(jointIndex)->GetParentIndex(); if (parentIndex != InvalidIndex) { InsertJointAndParents(parentIndex, includedJointIndices); @@ -2381,7 +2376,7 @@ namespace EMotionFX continue; } - const size_t numJoints = mSkeleton->GetNumNodes(); + const size_t numJoints = m_skeleton->GetNumNodes(); for (size_t jointIndex = 0; jointIndex < numJoints; ++jointIndex) { const Mesh* mesh = GetMesh(lod, jointIndex); @@ -2412,7 +2407,7 @@ namespace EMotionFX for (const AZStd::string& jointName : alwaysIncludeJoints) { size_t jointIndex = InvalidIndex; - if (!mSkeleton->FindNodeAndIndexByName(jointName, jointIndex)) + if (!m_skeleton->FindNodeAndIndexByName(jointName, jointIndex)) { if (!jointName.empty()) { @@ -2427,22 +2422,22 @@ namespace EMotionFX // Disable all joints first. for (size_t jointIndex = 0; jointIndex < numJoints; ++jointIndex) { - mSkeleton->GetNode(jointIndex)->SetSkeletalLODStatus(lod, false); + m_skeleton->GetNode(jointIndex)->SetSkeletalLODStatus(lod, false); } // Enable all our included joints in this skeletal LOD. AZ_TracePrintf("EMotionFX", "[LOD %d] Enabled joints = %zd\n", lod, includedJointIndices.size()); for (size_t jointIndex : includedJointIndices) { - mSkeleton->GetNode(jointIndex)->SetSkeletalLODStatus(lod, true); + m_skeleton->GetNode(jointIndex)->SetSkeletalLODStatus(lod, true); } } else // When we have an empty include list, enable everything. { - AZ_TracePrintf("EMotionFX", "[LOD %d] Enabled joints = %zd\n", lod, mSkeleton->GetNumNodes()); - for (size_t i = 0; i < mSkeleton->GetNumNodes(); ++i) + AZ_TracePrintf("EMotionFX", "[LOD %d] Enabled joints = %zd\n", lod, m_skeleton->GetNumNodes()); + for (size_t i = 0; i < m_skeleton->GetNumNodes(); ++i) { - mSkeleton->GetNode(i)->SetSkeletalLODStatus(lod, true); + m_skeleton->GetNode(i)->SetSkeletalLODStatus(lod, true); } } } // for each LOD @@ -2455,10 +2450,10 @@ namespace EMotionFX for (size_t lod = 0; lod < numLODs; ++lod) { AZ_TracePrintf("EMotionFX", "[LOD %d]:", lod); - const size_t numJoints = mSkeleton->GetNumNodes(); + const size_t numJoints = m_skeleton->GetNumNodes(); for (size_t jointIndex = 0; jointIndex < numJoints; ++jointIndex) { - const Node* joint = mSkeleton->GetNode(jointIndex); + const Node* joint = m_skeleton->GetNode(jointIndex); if (joint->GetSkeletalLODStatus(lod)) { AZ_TracePrintf("EMotionFX", "\t%s (index=%zu)", joint->GetName(), jointIndex); @@ -2485,7 +2480,7 @@ namespace EMotionFX // 3) In actor skeleton, remove every node that hasn't been marked. // 4) Meanwhile, build a map that represent the child-parent relationship. // 5) After the node index changed, we use the map in 4) to restore the child-parent relationship. - size_t numNodes = mSkeleton->GetNumNodes(); + size_t numNodes = m_skeleton->GetNumNodes(); AZStd::vector flags; AZStd::unordered_map childParentMap; flags.resize(numNodes); @@ -2494,7 +2489,7 @@ namespace EMotionFX // Search the hit detection config to find and keep all the hit detection nodes. for (const Physics::CharacterColliderNodeConfiguration& nodeConfig : m_physicsSetup->GetHitDetectionConfig().m_nodes) { - Node* node = mSkeleton->FindNodeByName(nodeConfig.m_name); + Node* node = m_skeleton->FindNodeByName(nodeConfig.m_name); if (node && nodesToKeep.find(node) == nodesToKeep.end()) { nodesToKeep.emplace(node); @@ -2511,7 +2506,7 @@ namespace EMotionFX // Search the actor skeleton to find all the critical nodes. for (size_t i = 0; i < numNodes; ++i) { - Node* node = mSkeleton->GetNode(i); + Node* node = m_skeleton->GetNode(i); if (node->GetIsCritical() && nodesToKeep.find(node) == nodesToKeep.end()) { nodesToKeep.emplace(node); @@ -2543,26 +2538,26 @@ namespace EMotionFX { if (!flags[nodeIndex]) { - mSkeleton->RemoveNode(nodeIndex); + m_skeleton->RemoveNode(nodeIndex); } } // Update the node index. - mSkeleton->UpdateNodeIndexValues(); + m_skeleton->UpdateNodeIndexValues(); // After the node index changed, the parent index become invalid. First, clear all information about children because // it's not valid anymore. - for (size_t nodeIndex = 0; nodeIndex < mSkeleton->GetNumNodes(); ++nodeIndex) + for (size_t nodeIndex = 0; nodeIndex < m_skeleton->GetNumNodes(); ++nodeIndex) { - Node* node = mSkeleton->GetNode(nodeIndex); + Node* node = m_skeleton->GetNode(nodeIndex); node->RemoveAllChildNodes(); } // Then build the child-parent relationship using the prebuild map. for (auto& pair : childParentMap) { - Node* child = mSkeleton->FindNodeByName(pair.first); - Node* parent = mSkeleton->FindNodeByName(pair.second); + Node* child = m_skeleton->FindNodeByName(pair.first); + Node* parent = m_skeleton->FindNodeByName(pair.second); child->SetParentIndex(parent->GetNodeIndex()); parent->AddChild(child->GetNodeIndex()); } @@ -2596,8 +2591,8 @@ namespace EMotionFX } // In case neither of the mesh joints are present in the actor, just use the root node as fallback. - AZ_Assert(mSkeleton->GetNode(0), "Actor needs to have at least a single joint."); - return mSkeleton->GetNode(0); + AZ_Assert(m_skeleton->GetNode(0), "Actor needs to have at least a single joint."); + return m_skeleton->GetNode(0); } void Actor::ConstructMeshes() @@ -2610,18 +2605,18 @@ namespace EMotionFX lodLevels.clear(); SetNumLODLevels(numLODLevels, /*adjustMorphSetup=*/false); - const size_t numNodes = mSkeleton->GetNumNodes(); + const size_t numNodes = m_skeleton->GetNumNodes(); // Remove all the materials and add them back based on the meshAsset. Eventually we will remove all the material from Actor and // GLActor. RemoveAllMaterials(); - mMaterials.resize(numLODLevels); + m_materials.resize(numLODLevels); for (size_t lodLevel = 0; lodLevel < numLODLevels; ++lodLevel) { const AZ::Data::Asset& lodAsset = lodAssets[lodLevel]; - lodLevels[lodLevel].mNodeInfos.resize(numNodes); + lodLevels[lodLevel].m_nodeInfos.resize(numNodes); // Create a single mesh for the actor. Mesh* mesh = Mesh::CreateFromModelLod(lodAsset, m_skinToSkeletonIndexMap); @@ -2635,13 +2630,13 @@ namespace EMotionFX } const size_t jointIndex = meshJoint->GetNodeIndex(); - NodeLODInfo& jointInfo = lodLevels[lodLevel].mNodeInfos[jointIndex]; + NodeLODInfo& jointInfo = lodLevels[lodLevel].m_nodeInfos[jointIndex]; - jointInfo.mMesh = mesh; + jointInfo.m_mesh = mesh; - if (!jointInfo.mStack) + if (!jointInfo.m_stack) { - jointInfo.mStack = MeshDeformerStack::Create(mesh); + jointInfo.m_stack = MeshDeformerStack::Create(mesh); } // Add the skinning deformers @@ -2665,14 +2660,14 @@ namespace EMotionFX if (dualQuatSkinning) { DualQuatSkinDeformer* skinDeformer = DualQuatSkinDeformer::Create(mesh); - jointInfo.mStack->AddDeformer(skinDeformer); + jointInfo.m_stack->AddDeformer(skinDeformer); skinDeformer->ReserveLocalBones(numLocalJoints); skinDeformer->Reinitialize(this, meshJoint, static_cast(lodLevel)); } else { SoftSkinDeformer* skinDeformer = GetSoftSkinManager().CreateDeformer(mesh); - jointInfo.mStack->AddDeformer(skinDeformer); + jointInfo.m_stack->AddDeformer(skinDeformer); skinDeformer->ReserveLocalBones(numLocalJoints); // pre-alloc data to prevent reallocs skinDeformer->Reinitialize(this, meshJoint, static_cast(lodLevel)); } @@ -2685,7 +2680,7 @@ namespace EMotionFX Node* Actor::FindJointByMeshName(const AZStd::string_view meshName) const { - Node* joint = mSkeleton->FindNodeByName(meshName.data()); + Node* joint = m_skeleton->FindNodeByName(meshName.data()); if (!joint) { // When mesh merging in the model builder is enabled, the name of the mesh is the concatenated version @@ -2695,7 +2690,7 @@ namespace EMotionFX AZ::StringFunc::Tokenize(meshName, tokens, '+'); for (const AZStd::string& token : tokens) { - joint = mSkeleton->FindNodeByName(token); + joint = m_skeleton->FindNodeByName(token); if (joint) { break; @@ -2714,7 +2709,7 @@ namespace EMotionFX AZStd::unordered_map result; for (const auto& pair : skinMetaAsset->GetJointNameToIndexMap()) { - const Node* node = mSkeleton->FindNodeByName(pair.first.c_str()); + const Node* node = m_skeleton->FindNodeByName(pair.first.c_str()); if (!node) { AZ_Assert(node, "Cannot find joint named %s in the skeleton while it is used by the skin.", pair.first.c_str()); @@ -2734,14 +2729,14 @@ namespace EMotionFX const AZStd::array_view>& lodAssets = m_meshAsset->GetLodAssets(); const size_t numLODLevels = lodAssets.size(); - AZ_Assert(mMorphSetups.size() == numLODLevels, "There needs to be a morph setup for every single LOD level."); + AZ_Assert(m_morphSetups.size() == numLODLevels, "There needs to be a morph setup for every single LOD level."); for (size_t lodLevel = 0; lodLevel < numLODLevels; ++lodLevel) { const AZ::Data::Asset& lodAsset = lodAssets[lodLevel]; const AZStd::array_view& sourceMeshes = lodAsset->GetMeshes(); - MorphSetup* morphSetup = mMorphSetups[static_cast(lodLevel)]; + MorphSetup* morphSetup = m_morphSetups[static_cast(lodLevel)]; if (!morphSetup) { continue; @@ -2756,21 +2751,21 @@ namespace EMotionFX } const size_t jointIndex = meshJoint->GetNodeIndex(); - NodeLODInfo& jointInfo = lodLevels[lodLevel].mNodeInfos[jointIndex]; - Mesh* mesh = jointInfo.mMesh; + NodeLODInfo& jointInfo = lodLevels[lodLevel].m_nodeInfos[jointIndex]; + Mesh* mesh = jointInfo.m_mesh; - if (!jointInfo.mStack) + if (!jointInfo.m_stack) { - jointInfo.mStack = MeshDeformerStack::Create(mesh); + jointInfo.m_stack = MeshDeformerStack::Create(mesh); } // Add the morph deformer to the mesh deformer stack (in case there is none yet). - MorphMeshDeformer* morphTargetDeformer = (MorphMeshDeformer*)jointInfo.mStack->FindDeformerByType(MorphMeshDeformer::TYPE_ID); + MorphMeshDeformer* morphTargetDeformer = (MorphMeshDeformer*)jointInfo.m_stack->FindDeformerByType(MorphMeshDeformer::TYPE_ID); if (!morphTargetDeformer) { morphTargetDeformer = MorphMeshDeformer::Create(mesh); // Add insert the deformer at the first position to make sure we apply morph targets before skinning. - jointInfo.mStack->InsertDeformer(/*deformerPosition=*/0, morphTargetDeformer); + jointInfo.m_stack->InsertDeformer(/*deformerPosition=*/0, morphTargetDeformer); } // The lod has shared buffers that combine the data from each submesh. In case any of the submeshes has a @@ -2809,8 +2804,8 @@ namespace EMotionFX MorphTargetStandard::DeformData* deformData = aznew MorphTargetStandard::DeformData(jointIndex, numDeformedVertices); // Set the compression/quantization range for the positions. - deformData->mMinValue = metaData.m_minPositionDelta; - deformData->mMaxValue = metaData.m_maxPositionDelta; + deformData->m_minValue = metaData.m_minPositionDelta; + deformData->m_maxValue = metaData.m_maxPositionDelta; for (AZ::u32 deformVtx = 0; deformVtx < numDeformedVertices; ++deformVtx) { @@ -2822,24 +2817,24 @@ namespace EMotionFX AZ::RPI::CompressedMorphTargetDelta unpackedCompressedDelta = AZ::RPI::UnpackMorphTargetDelta(packedCompressedDelta); // Set the EMotionFX deform data from the CmopressedMorphTargetDelta - deformData->mDeltas[deformVtx].mVertexNr = unpackedCompressedDelta.m_morphedVertexIndex; + deformData->m_deltas[deformVtx].m_vertexNr = unpackedCompressedDelta.m_morphedVertexIndex; - deformData->mDeltas[deformVtx].mPosition = MCore::Compressed16BitVector3( + deformData->m_deltas[deformVtx].m_position = MCore::Compressed16BitVector3( unpackedCompressedDelta.m_positionX, unpackedCompressedDelta.m_positionY, unpackedCompressedDelta.m_positionZ); - deformData->mDeltas[deformVtx].mNormal = MCore::Compressed8BitVector3( + deformData->m_deltas[deformVtx].m_normal = MCore::Compressed8BitVector3( unpackedCompressedDelta.m_normalX, unpackedCompressedDelta.m_normalY, unpackedCompressedDelta.m_normalZ); - deformData->mDeltas[deformVtx].mTangent = MCore::Compressed8BitVector3( + deformData->m_deltas[deformVtx].m_tangent = MCore::Compressed8BitVector3( unpackedCompressedDelta.m_tangentX, unpackedCompressedDelta.m_tangentY, unpackedCompressedDelta.m_tangentZ); - deformData->mDeltas[deformVtx].mBitangent = MCore::Compressed8BitVector3( + deformData->m_deltas[deformVtx].m_bitangent = MCore::Compressed8BitVector3( unpackedCompressedDelta.m_bitangentX, unpackedCompressedDelta.m_bitangentY, unpackedCompressedDelta.m_bitangentZ); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Actor.h b/Gems/EMotionFX/Code/EMotionFX/Source/Actor.h index efcfa52413..5c4a15e2d8 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Actor.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Actor.h @@ -68,8 +68,8 @@ namespace EMotionFX */ struct EMFX_API Dependency { - Actor* mActor; /**< The actor where the instance is dependent on. */ - AnimGraph* mAnimGraph; /**< The anim graph we depend on. */ + Actor* m_actor; /**< The actor where the instance is dependent on. */ + AnimGraph* m_animGraph; /**< The anim graph we depend on. */ }; // @@ -90,9 +90,9 @@ namespace EMotionFX // per node mirror info struct EMFX_API NodeMirrorInfo { - uint16 mSourceNode; // from which node to extract the motion - uint8 mAxis; // X=0, Y=1, Z=2 - uint8 mFlags; // bitfield with MIRRORFLAG_ prefix + uint16 m_sourceNode; // from which node to extract the motion + uint8 m_axis; // X=0, Y=1, Z=2 + uint8 m_flags; // bitfield with MIRRORFLAG_ prefix }; enum class LoadRequirement : bool @@ -114,13 +114,13 @@ namespace EMotionFX * Get the unique identification number for the actor. * @return The unique identification number. */ - MCORE_INLINE uint32 GetID() const { return mID; } + MCORE_INLINE uint32 GetID() const { return m_id; } /** * Set the unique identification number for the actor instance. * @param[in] id The unique identification number. */ - MCORE_INLINE void SetID(uint32 id) { mID = id; } + MCORE_INLINE void SetID(uint32 id) { m_id = id; } /** * Add a node to this actor. @@ -218,7 +218,7 @@ namespace EMotionFX * Get the motion extraction node index. * @result The motion extraction node index, or MCORE_INVALIDINDEX32 when it has not been set. */ - MCORE_INLINE size_t GetMotionExtractionNodeIndex() const { return mMotionExtractionNode; } + MCORE_INLINE size_t GetMotionExtractionNodeIndex() const { return m_motionExtractionNode; } //--------------------------------------------------------------------- @@ -522,15 +522,15 @@ namespace EMotionFX * Get the number of dependencies. * @result The number of dependencies that this actor has on other actors. */ - MCORE_INLINE size_t GetNumDependencies() const { return mDependencies.size(); } + MCORE_INLINE size_t GetNumDependencies() const { return m_dependencies.size(); } /** * Get a given dependency. * @param nr The dependency number, which must be in range of [0..GetNumDependencies()-1]. * @result A pointer to the dependency. */ - MCORE_INLINE Dependency* GetDependency(size_t nr) { return &mDependencies[nr]; } - MCORE_INLINE const Dependency* GetDependency(size_t nr) const { return &mDependencies[nr]; } + MCORE_INLINE Dependency* GetDependency(size_t nr) { return &m_dependencies[nr]; } + MCORE_INLINE const Dependency* GetDependency(size_t nr) const { return &m_dependencies[nr]; } /** * Recursively add dependencies that this actor has on other actors. @@ -546,7 +546,7 @@ namespace EMotionFX * @result A smart pointer object to the morph setup. Use the MCore::Pointer::GetPointer() to get the actual pointer. * That GetPointer() method will return nullptr when there is no morph setup for the given LOD level. */ - MCORE_INLINE MorphSetup* GetMorphSetup(size_t geomLODLevel) const { return mMorphSetups[geomLODLevel]; } + MCORE_INLINE MorphSetup* GetMorphSetup(size_t geomLODLevel) const { return m_morphSetups[geomLODLevel]; } /** * Remove all morph setups. Morph setups contain all morph targtets. @@ -649,16 +649,16 @@ namespace EMotionFX * @param nodeIndex The node index to get the info for. * @result A reference to the mirror info. */ - MCORE_INLINE NodeMirrorInfo& GetNodeMirrorInfo(size_t nodeIndex) { return mNodeMirrorInfos[nodeIndex]; } + MCORE_INLINE NodeMirrorInfo& GetNodeMirrorInfo(size_t nodeIndex) { return m_nodeMirrorInfos[nodeIndex]; } /** * Get the mirror info for a given node. * @param nodeIndex The node index to get the info for. * @result A reference to the mirror info. */ - MCORE_INLINE const NodeMirrorInfo& GetNodeMirrorInfo(size_t nodeIndex) const { return mNodeMirrorInfos[nodeIndex]; } + MCORE_INLINE const NodeMirrorInfo& GetNodeMirrorInfo(size_t nodeIndex) const { return m_nodeMirrorInfos[nodeIndex]; } - MCORE_INLINE bool GetHasMirrorInfo() const { return (mNodeMirrorInfos.size() != 0); } + MCORE_INLINE bool GetHasMirrorInfo() const { return (m_nodeMirrorInfos.size() != 0); } //--------------------------------------------------------------- @@ -754,16 +754,16 @@ namespace EMotionFX void SetNodeMirrorInfos(const AZStd::vector& mirrorInfos); bool GetHasMirrorAxesDetected() const; - MCORE_INLINE const AZStd::vector& GetInverseBindPoseTransforms() const { return mInvBindPoseTransforms; } - MCORE_INLINE Pose* GetBindPose() { return mSkeleton->GetBindPose(); } - MCORE_INLINE const Pose* GetBindPose() const { return mSkeleton->GetBindPose(); } + MCORE_INLINE const AZStd::vector& GetInverseBindPoseTransforms() const { return m_invBindPoseTransforms; } + MCORE_INLINE Pose* GetBindPose() { return m_skeleton->GetBindPose(); } + MCORE_INLINE const Pose* GetBindPose() const { return m_skeleton->GetBindPose(); } /** * Get the inverse bind pose (in world space) transform of a given joint. * @param jointIndex The joint number, which must be in range of [0..GetNumNodes()-1]. * @result The inverse of the bind pose transform. */ - MCORE_INLINE const Transform& GetInverseBindPoseTransform(size_t nodeIndex) const { return mInvBindPoseTransforms[nodeIndex]; } + MCORE_INLINE const Transform& GetInverseBindPoseTransform(size_t nodeIndex) const { return m_invBindPoseTransforms[nodeIndex]; } void ReleaseTransformData(); void ResizeTransformData(); @@ -773,8 +773,8 @@ namespace EMotionFX void SetStaticAabb(const AZ::Aabb& aabb); void UpdateStaticAabb(); // VERY heavy operation, you shouldn't call this ever (internally creates an actor instance, updates mesh deformers, calcs a mesh based aabb, destroys the actor instance again) - void SetThreadIndex(uint32 index) { mThreadIndex = index; } - uint32 GetThreadIndex() const { return mThreadIndex; } + void SetThreadIndex(uint32 index) { m_threadIndex = index; } + uint32 GetThreadIndex() const { return m_threadIndex; } Mesh* GetMesh(size_t lodLevel, size_t nodeIndex) const; MeshDeformerStack* GetMeshDeformerStack(size_t lodLevel, size_t nodeIndex) const; @@ -787,8 +787,8 @@ namespace EMotionFX */ void FindMostInfluencedMeshPoints(const Node* node, AZStd::vector& outPoints) const; - MCORE_INLINE Skeleton* GetSkeleton() const { return mSkeleton; } - MCORE_INLINE size_t GetNumNodes() const { return mSkeleton->GetNumNodes(); } + MCORE_INLINE Skeleton* GetSkeleton() const { return m_skeleton; } + MCORE_INLINE size_t GetNumNodes() const { return m_skeleton->GetNumNodes(); } void SetMesh(size_t lodLevel, size_t nodeIndex, Mesh* mesh); void SetMeshDeformerStack(size_t lodLevel, size_t nodeIndex, MeshDeformerStack* stack); @@ -808,8 +808,8 @@ namespace EMotionFX EAxis FindBestMatchingMotionExtractionAxis() const; - MCORE_INLINE size_t GetRetargetRootNodeIndex() const { return mRetargetRootNode; } - MCORE_INLINE Node* GetRetargetRootNode() const { return (mRetargetRootNode != InvalidIndex) ? mSkeleton->GetNode(mRetargetRootNode) : nullptr; } + MCORE_INLINE size_t GetRetargetRootNodeIndex() const { return m_retargetRootNode; } + MCORE_INLINE Node* GetRetargetRootNode() const { return (m_retargetRootNode != InvalidIndex) ? m_skeleton->GetNode(m_retargetRootNode) : nullptr; } void SetRetargetRootNodeIndex(size_t nodeIndex); void SetRetargetRootNode(Node* node); @@ -857,8 +857,8 @@ namespace EMotionFX // data per node, per lod struct EMFX_API NodeLODInfo { - Mesh* mMesh; - MeshDeformerStack* mStack; + Mesh* m_mesh; + MeshDeformerStack* m_stack; NodeLODInfo(); NodeLODInfo(const NodeLODInfo&) = delete; @@ -868,10 +868,10 @@ namespace EMotionFX { return; } - mMesh = rhs.mMesh; - mStack = rhs.mStack; - rhs.mMesh = nullptr; - rhs.mStack = nullptr; + m_mesh = rhs.m_mesh; + m_stack = rhs.m_stack; + rhs.m_mesh = nullptr; + rhs.m_stack = nullptr; } NodeLODInfo& operator=(const NodeLODInfo&) = delete; NodeLODInfo& operator=(NodeLODInfo&& rhs) @@ -880,10 +880,10 @@ namespace EMotionFX { return *this; } - mMesh = rhs.mMesh; - mStack = rhs.mStack; - rhs.mMesh = nullptr; - rhs.mStack = nullptr; + m_mesh = rhs.m_mesh; + m_stack = rhs.m_stack; + rhs.m_mesh = nullptr; + rhs.m_stack = nullptr; return *this; } ~NodeLODInfo(); @@ -892,7 +892,7 @@ namespace EMotionFX // a lod level struct EMFX_API LODLevel { - AZStd::vector mNodeInfos; + AZStd::vector m_nodeInfos; }; struct MeshLODData @@ -918,31 +918,31 @@ namespace EMotionFX Node* FindMeshJoint(const AZ::Data::Asset& lodModelAsset) const; - Skeleton* mSkeleton; /**< The skeleton, containing the nodes and bind pose. */ - AZStd::vector mDependencies; /**< The dependencies on other actors (shared meshes and transforms). */ - AZStd::string mName; /**< The name of the actor. */ - AZStd::string mFileName; /**< The filename of the actor. */ - AZStd::vector mNodeMirrorInfos; /**< The array of node mirror info. */ - AZStd::vector< AZStd::vector< Material* > > mMaterials; /**< A collection of materials (for each lod). */ - AZStd::vector< MorphSetup* > mMorphSetups; /**< A morph setup for each geometry LOD. */ - MCore::SmallArray mNodeGroups; /**< The set of node groups. */ + Skeleton* m_skeleton; /**< The skeleton, containing the nodes and bind pose. */ + AZStd::vector m_dependencies; /**< The dependencies on other actors (shared meshes and transforms). */ + AZStd::string m_name; /**< The name of the actor. */ + AZStd::string m_fileName; /**< The filename of the actor. */ + AZStd::vector m_nodeMirrorInfos; /**< The array of node mirror info. */ + AZStd::vector< AZStd::vector< Material* > > m_materials; /**< A collection of materials (for each lod). */ + AZStd::vector< MorphSetup* > m_morphSetups; /**< A morph setup for each geometry LOD. */ + MCore::SmallArray m_nodeGroups; /**< The set of node groups. */ AZStd::shared_ptr m_physicsSetup; /**< Hit detection, ragdoll and cloth colliders, joint limits and rigid bodies. */ AZStd::shared_ptr m_simulatedObjectSetup; /**< Setup for simulated objects */ - MCore::Distance::EUnitType mUnitType; /**< The unit type used on export. */ - MCore::Distance::EUnitType mFileUnitType; /**< The unit type used on export. */ - AZStd::vector mInvBindPoseTransforms; /**< The inverse world space bind pose transforms. */ - void* mCustomData; /**< Some custom data, for example a pointer to your own game character class which is linked to this actor. */ - size_t mMotionExtractionNode; /**< The motion extraction node. This is the node from which to transfer a filtered part of the motion onto the actor instance. Can also be MCORE_INVALIDINDEX32 when motion extraction is disabled. */ - size_t mRetargetRootNode; /**< The retarget root node, which controls the height displacement of the character. This is most likely the hip or pelvis node. */ - uint32 mID; /**< The unique identification number for the actor. */ - uint32 mThreadIndex; /**< The thread number we are running on, which is a value starting at 0, up to the number of threads in the job system. */ + MCore::Distance::EUnitType m_unitType; /**< The unit type used on export. */ + MCore::Distance::EUnitType m_fileUnitType; /**< The unit type used on export. */ + AZStd::vector m_invBindPoseTransforms; /**< The inverse world space bind pose transforms. */ + void* m_customData; /**< Some custom data, for example a pointer to your own game character class which is linked to this actor. */ + size_t m_motionExtractionNode; /**< The motion extraction node. This is the node from which to transfer a filtered part of the motion onto the actor instance. Can also be MCORE_INVALIDINDEX32 when motion extraction is disabled. */ + size_t m_retargetRootNode; /**< The retarget root node, which controls the height displacement of the character. This is most likely the hip or pelvis node. */ + uint32 m_id; /**< The unique identification number for the actor. */ + uint32 m_threadIndex; /**< The thread number we are running on, which is a value starting at 0, up to the number of threads in the job system. */ AZ::Aabb m_staticAabb; /**< The static AABB. */ - bool mDirtyFlag; /**< The dirty flag which indicates whether the user has made changes to the actor since the last file save operation. */ - bool mUsedForVisualization; /**< Indicates if the actor is used for visualization specific things and is not used as a normal in-game actor. */ + bool m_dirtyFlag; /**< The dirty flag which indicates whether the user has made changes to the actor since the last file save operation. */ + bool m_usedForVisualization; /**< Indicates if the actor is used for visualization specific things and is not used as a normal in-game actor. */ bool m_optimizeSkeleton; /**< Indicates if we should perform/ */ bool m_isReady = false; /**< If actor as well as its dependent files are fully loaded and initialized.*/ #if defined(EMFX_DEVELOPMENT_BUILD) - bool mIsOwnedByRuntime; /**< Set if the actor is used/owned by the engine runtime. */ + bool m_isOwnedByRuntime; /**< Set if the actor is used/owned by the engine runtime. */ #endif // EMFX_DEVELOPMENT_BUILD }; } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.cpp index f394dc4f5f..6097784e2f 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.cpp @@ -45,27 +45,27 @@ namespace EMotionFX { MCORE_ASSERT(actor); - mEnabledNodes.reserve(actor->GetNumNodes()); + m_enabledNodes.reserve(actor->GetNumNodes()); // set the actor and create the motion system - mBoolFlags = 0; - mActor = actor; - mLODLevel = 0; + m_boolFlags = 0; + m_actor = actor; + m_lodLevel = 0; m_requestedLODLevel = 0; - mNumAttachmentRefs = 0; - mThreadIndex = threadIndex; - mAttachedTo = nullptr; - mSelfAttachment = nullptr; - mCustomData = nullptr; - mID = aznumeric_caster(MCore::GetIDGenerator().GenerateID()); - mVisualizeScale = 1.0f; - mMotionSamplingRate = 0.0f; - mMotionSamplingTimer = 0.0f; + m_numAttachmentRefs = 0; + m_threadIndex = threadIndex; + m_attachedTo = nullptr; + m_selfAttachment = nullptr; + m_customData = nullptr; + m_id = aznumeric_caster(MCore::GetIDGenerator().GenerateID()); + m_visualizeScale = 1.0f; + m_motionSamplingRate = 0.0f; + m_motionSamplingTimer = 0.0f; - mTrajectoryDelta.IdentityWithZeroScale(); + m_trajectoryDelta.IdentityWithZeroScale(); m_staticAabb = AZ::Aabb::CreateNull(); - mAnimGraphInstance = nullptr; + m_animGraphInstance = nullptr; // set the boolean defaults SetFlag(BOOL_ISVISIBLE, true); @@ -84,16 +84,16 @@ namespace EMotionFX EnableAllNodes(); // apply actor node group default states (disable groups of nodes that are disabled on default) - const uint32 numGroups = mActor->GetNumNodeGroups(); + const uint32 numGroups = m_actor->GetNumNodeGroups(); for (uint32 i = 0; i < numGroups; ++i) { - if (mActor->GetNodeGroup(i)->GetIsEnabledOnDefault() == false) // if this group is disabled on default + if (m_actor->GetNodeGroup(i)->GetIsEnabledOnDefault() == false) // if this group is disabled on default { - mActor->GetNodeGroup(i)->DisableNodes(this); // disable all nodes inside this group + m_actor->GetNodeGroup(i)->DisableNodes(this); // disable all nodes inside this group } } // disable nodes that are disabled in LOD 0 - Skeleton* skeleton = mActor->GetSkeleton(); + Skeleton* skeleton = m_actor->GetSkeleton(); const size_t numNodes = skeleton->GetNumNodes(); for (size_t n = 0; n < numNodes; ++n) { @@ -104,27 +104,27 @@ namespace EMotionFX } // setup auto bounds update (it is enabled on default) - mBoundsUpdateFrequency = 0.0f; - mBoundsUpdatePassedTime = 0.0f; - mBoundsUpdateType = BOUNDS_STATIC_BASED; - mBoundsUpdateItemFreq = 1; + m_boundsUpdateFrequency = 0.0f; + m_boundsUpdatePassedTime = 0.0f; + m_boundsUpdateType = BOUNDS_STATIC_BASED; + m_boundsUpdateItemFreq = 1; // initialize the actor local and global transform - mParentWorldTransform.Identity(); - mLocalTransform.Identity(); - mWorldTransform.Identity(); - mWorldTransformInv.Identity(); + m_parentWorldTransform.Identity(); + m_localTransform.Identity(); + m_worldTransform.Identity(); + m_worldTransformInv.Identity(); // init the morph setup instance - mMorphSetup = MorphSetupInstance::Create(); - mMorphSetup->Init(actor->GetMorphSetup(0)); + m_morphSetup = MorphSetupInstance::Create(); + m_morphSetup->Init(actor->GetMorphSetup(0)); // initialize the transformation data of this instance - mTransformData = TransformData::Create(); - mTransformData->InitForActorInstance(this); + m_transformData = TransformData::Create(); + m_transformData->InitForActorInstance(this); // create the motion system - mMotionSystem = MotionLayerSystem::Create(this); + m_motionSystem = MotionLayerSystem::Create(this); // update the global and local matrices UpdateTransformations(0.0f); @@ -133,7 +133,7 @@ namespace EMotionFX UpdateDependencies(); // update the static based AABB dimensions - m_staticAabb = mActor->GetStaticAabb(); + m_staticAabb = m_actor->GetStaticAabb(); if (!m_staticAabb.IsValid()) { UpdateMeshDeformers(0.0f, true); // TODO: not really thread safe because of shared meshes, although it probably will output correctly @@ -141,7 +141,7 @@ namespace EMotionFX } // update the bounds - UpdateBounds(/*lodLevel=*/0, mBoundsUpdateType); + UpdateBounds(/*lodLevel=*/0, m_boundsUpdateType); // register it GetActorManager().RegisterActorInstance(this); @@ -156,24 +156,24 @@ namespace EMotionFX ActorInstanceNotificationBus::Broadcast(&ActorInstanceNotificationBus::Events::OnActorInstanceDestroyed, this); // get rid of the motion system - if (mMotionSystem) + if (m_motionSystem) { - mMotionSystem->Destroy(); + m_motionSystem->Destroy(); } - if (mAnimGraphInstance) + if (m_animGraphInstance) { - mAnimGraphInstance->Destroy(); + m_animGraphInstance->Destroy(); } GetDebugDraw().UnregisterActorInstance(this); // delete all attachments // actor instances that are attached will be detached, and not deleted from memory - const size_t numAttachments = mAttachments.size(); + const size_t numAttachments = m_attachments.size(); for (size_t i = 0; i < numAttachments; ++i) { - ActorInstance* attachmentActorInstance = mAttachments[i]->GetAttachmentActorInstance(); + ActorInstance* attachmentActorInstance = m_attachments[i]->GetAttachmentActorInstance(); if (attachmentActorInstance) { attachmentActorInstance->SetAttachedTo(nullptr); @@ -181,24 +181,24 @@ namespace EMotionFX attachmentActorInstance->DecreaseNumAttachmentRefs(); GetActorManager().UpdateActorInstanceStatus(attachmentActorInstance); } - mAttachments[i]->Destroy(); + m_attachments[i]->Destroy(); } - mAttachments.clear(); + m_attachments.clear(); - if (mMorphSetup) + if (m_morphSetup) { - mMorphSetup->Destroy(); + m_morphSetup->Destroy(); } - if (mTransformData) + if (m_transformData) { - mTransformData->Destroy(); + m_transformData->Destroy(); } // remove the attachment from the actor instance where it is attached to if (GetIsAttachment()) { - mAttachedTo->RemoveAttachment(this /*, false*/); + m_attachedTo->RemoveAttachment(this /*, false*/); } // automatically unregister the actor instance @@ -223,23 +223,23 @@ namespace EMotionFX if (recorder.GetIsInPlayMode() && recorder.GetHasRecorded(this)) { // output the anim graph instance, this doesn't overwrite transforms, just some things internally - if (recorder.GetRecordSettings().mRecordAnimGraphStates && mAnimGraphInstance) + if (recorder.GetRecordSettings().m_recordAnimGraphStates && m_animGraphInstance) { - mAnimGraphInstance->Update(0.0f); - mAnimGraphInstance->Output(nullptr); + m_animGraphInstance->Update(0.0f); + m_animGraphInstance->Output(nullptr); } // apply the main transformation recorder.SampleAndApplyMainTransform(recorder.GetCurrentPlayTime(), this); // apply the node transforms - if (recorder.GetRecordSettings().mRecordTransforms) + if (recorder.GetRecordSettings().m_recordTransforms) { recorder.SampleAndApplyTransforms(recorder.GetCurrentPlayTime(), this); } // sample the morph targets - if (recorder.GetRecordSettings().mRecordMorphs) + if (recorder.GetRecordSettings().m_recordMorphs) { recorder.SampleAndApplyMorphs(recorder.GetCurrentPlayTime(), this); } @@ -252,11 +252,11 @@ namespace EMotionFX // update the bounds when needed if (GetBoundsUpdateEnabled()) { - mBoundsUpdatePassedTime += timePassedInSeconds; - if (mBoundsUpdatePassedTime >= mBoundsUpdateFrequency) + m_boundsUpdatePassedTime += timePassedInSeconds; + if (m_boundsUpdatePassedTime >= m_boundsUpdateFrequency) { - UpdateBounds(mLODLevel, mBoundsUpdateType, mBoundsUpdateItemFreq); - mBoundsUpdatePassedTime = 0.0f; + UpdateBounds(m_lodLevel, m_boundsUpdateType, m_boundsUpdateItemFreq); + m_boundsUpdatePassedTime = 0.0f; } } @@ -270,13 +270,13 @@ namespace EMotionFX if (!attachment || !attachment->GetIsInfluencedByMultipleJoints()) { // update the motion system, which performs all blending, and updates all local transforms (excluding the local matrices) - if (mAnimGraphInstance) + if (m_animGraphInstance) { - mAnimGraphInstance->Update(timePassedInSeconds); + m_animGraphInstance->Update(timePassedInSeconds); UpdateWorldTransform(); if (updateJointTransforms && sampleMotions) { - mAnimGraphInstance->Output(mTransformData->GetCurrentPose()); + m_animGraphInstance->Output(m_transformData->GetCurrentPose()); if (m_ragdollInstance) { @@ -284,9 +284,9 @@ namespace EMotionFX } } } - else if (mMotionSystem) + else if (m_motionSystem) { - mMotionSystem->Update(timePassedInSeconds, (updateJointTransforms && sampleMotions)); + m_motionSystem->Update(timePassedInSeconds, (updateJointTransforms && sampleMotions)); } else { @@ -296,15 +296,15 @@ namespace EMotionFX // when the actor instance isn't visible, we don't want to do more things if (!updateJointTransforms) { - if (GetBoundsUpdateEnabled() && mBoundsUpdateType == BOUNDS_STATIC_BASED) + if (GetBoundsUpdateEnabled() && m_boundsUpdateType == BOUNDS_STATIC_BASED) { - UpdateBounds(mLODLevel, mBoundsUpdateType); + UpdateBounds(m_lodLevel, m_boundsUpdateType); } return; } - mTransformData->GetCurrentPose()->ApplyMorphWeightsToActorInstance(); + m_transformData->GetCurrentPose()->ApplyMorphWeightsToActorInstance(); ApplyMorphSetup(); UpdateSkinningMatrices(); @@ -312,20 +312,20 @@ namespace EMotionFX } else // we are a skin attachment { - mLocalTransform.Identity(); - if (mAnimGraphInstance) + m_localTransform.Identity(); + if (m_animGraphInstance) { - mAnimGraphInstance->Update(timePassedInSeconds); + m_animGraphInstance->Update(timePassedInSeconds); UpdateWorldTransform(); if (updateJointTransforms && sampleMotions) { - mAnimGraphInstance->Output(mTransformData->GetCurrentPose()); + m_animGraphInstance->Output(m_transformData->GetCurrentPose()); } } - else if (mMotionSystem) + else if (m_motionSystem) { - mMotionSystem->Update(timePassedInSeconds, (updateJointTransforms && sampleMotions)); + m_motionSystem->Update(timePassedInSeconds, (updateJointTransforms && sampleMotions)); } else { @@ -335,15 +335,15 @@ namespace EMotionFX // when the actor instance isn't visible, we don't want to do more things if (!updateJointTransforms) { - if (GetBoundsUpdateEnabled() && mBoundsUpdateType == BOUNDS_STATIC_BASED) + if (GetBoundsUpdateEnabled() && m_boundsUpdateType == BOUNDS_STATIC_BASED) { - UpdateBounds(mLODLevel, mBoundsUpdateType); + UpdateBounds(m_lodLevel, m_boundsUpdateType); } return; } - mSelfAttachment->UpdateJointTransforms(*mTransformData->GetCurrentPose()); - mTransformData->GetCurrentPose()->ApplyMorphWeightsToActorInstance(); + m_selfAttachment->UpdateJointTransforms(*m_transformData->GetCurrentPose()); + m_transformData->GetCurrentPose()->ApplyMorphWeightsToActorInstance(); ApplyMorphSetup(); UpdateSkinningMatrices(); UpdateAttachments(); @@ -352,11 +352,11 @@ namespace EMotionFX // update the bounds when needed if (GetBoundsUpdateEnabled()) { - mBoundsUpdatePassedTime += timePassedInSeconds; - if (mBoundsUpdatePassedTime >= mBoundsUpdateFrequency) + m_boundsUpdatePassedTime += timePassedInSeconds; + if (m_boundsUpdatePassedTime >= m_boundsUpdateFrequency) { - UpdateBounds(mLODLevel, mBoundsUpdateType, mBoundsUpdateItemFreq); - mBoundsUpdatePassedTime = 0.0f; + UpdateBounds(m_lodLevel, m_boundsUpdateType, m_boundsUpdateItemFreq); + m_boundsUpdatePassedTime = 0.0f; } } } @@ -364,22 +364,22 @@ namespace EMotionFX // update the world transformation void ActorInstance::UpdateWorldTransform() { - mWorldTransform = mLocalTransform; - mWorldTransform.Multiply(mParentWorldTransform); - mWorldTransformInv = mWorldTransform.Inversed(); + m_worldTransform = m_localTransform; + m_worldTransform.Multiply(m_parentWorldTransform); + m_worldTransformInv = m_worldTransform.Inversed(); } // updates the skinning matrices of all nodes void ActorInstance::UpdateSkinningMatrices() { - AZ::Matrix3x4* skinningMatrices = mTransformData->GetSkinningMatrices(); - const Pose* pose = mTransformData->GetCurrentPose(); + AZ::Matrix3x4* skinningMatrices = m_transformData->GetSkinningMatrices(); + const Pose* pose = m_transformData->GetCurrentPose(); const size_t numNodes = GetNumEnabledNodes(); for (size_t i = 0; i < numNodes; ++i) { const size_t nodeNumber = GetEnabledNode(i); - Transform skinningTransform = mActor->GetInverseBindPoseTransform(nodeNumber); + Transform skinningTransform = m_actor->GetInverseBindPoseTransform(nodeNumber); skinningTransform.Multiply(pose->GetModelSpaceTransform(nodeNumber)); skinningMatrices[nodeNumber] = AZ::Matrix3x4::CreateFromTransform(skinningTransform.ToAZTransform()); } @@ -391,11 +391,11 @@ namespace EMotionFX timePassedInSeconds *= GetEMotionFX().GetGlobalSimulationSpeed(); // Update the mesh deformers. - const Skeleton* skeleton = mActor->GetSkeleton(); - for (uint16 nodeNr : mEnabledNodes) + const Skeleton* skeleton = m_actor->GetSkeleton(); + for (uint16 nodeNr : m_enabledNodes) { Node* node = skeleton->GetNode(nodeNr); - MeshDeformerStack* stack = mActor->GetMeshDeformerStack(mLODLevel, nodeNr); + MeshDeformerStack* stack = m_actor->GetMeshDeformerStack(m_lodLevel, nodeNr); if (stack) { stack->Update(this, node, timePassedInSeconds, processDisabledDeformers); @@ -409,11 +409,11 @@ namespace EMotionFX timePassedInSeconds *= GetEMotionFX().GetGlobalSimulationSpeed(); // Update the mesh morph deformers. - const Skeleton* skeleton = mActor->GetSkeleton(); - for (uint16 nodeNr : mEnabledNodes) + const Skeleton* skeleton = m_actor->GetSkeleton(); + for (uint16 nodeNr : m_enabledNodes) { Node* node = skeleton->GetNode(nodeNr); - MeshDeformerStack* stack = mActor->GetMeshDeformerStack(mLODLevel, nodeNr); + MeshDeformerStack* stack = m_actor->GetMeshDeformerStack(m_lodLevel, nodeNr); if (stack) { stack->UpdateByModifierType(this, node, timePassedInSeconds, MorphMeshDeformer::TYPE_ID, true, processDisabledDeformers); @@ -440,7 +440,7 @@ namespace EMotionFX GetActorManager().GetScheduler()->RecursiveRemoveActorInstance(root); // add the attachment - mAttachments.emplace_back(attachment); + m_attachments.emplace_back(attachment); ActorInstance* attachmentActorInstance = attachment->GetAttachmentActorInstance(); if (attachmentActorInstance) { @@ -460,12 +460,12 @@ namespace EMotionFX size_t ActorInstance::FindAttachmentNr(ActorInstance* actorInstance) { // for all attachments - const auto foundAttachment = AZStd::find_if(mAttachments.begin(), mAttachments.end(), [actorInstance](const Attachment* attachment) + const auto foundAttachment = AZStd::find_if(m_attachments.begin(), m_attachments.end(), [actorInstance](const Attachment* attachment) { return attachment->GetAttachmentActorInstance() == actorInstance; }); - return foundAttachment != mAttachments.end() ? AZStd::distance(mAttachments.begin(), foundAttachment) : InvalidIndex; + return foundAttachment != m_attachments.end() ? AZStd::distance(m_attachments.begin(), foundAttachment) : InvalidIndex; } // remove an attachment by actor instance pointer @@ -486,14 +486,14 @@ namespace EMotionFX // remove an attachment void ActorInstance::RemoveAttachment(size_t nr, bool delFromMem) { - MCORE_ASSERT(nr < mAttachments.size()); + MCORE_ASSERT(nr < m_attachments.size()); // first remove the current attachment tree from the scheduler ActorInstance* root = FindAttachmentRoot(); GetActorManager().GetScheduler()->RecursiveRemoveActorInstance(root); // get the attachment - Attachment* attachment = mAttachments[nr]; + Attachment* attachment = m_attachments[nr]; // its not an attachment anymore ActorInstance* attachmentInstance = attachment->GetAttachmentActorInstance(); @@ -516,7 +516,7 @@ namespace EMotionFX } // remove it from the attachment list - mAttachments.erase(AZStd::next(begin(mAttachments), nr)); + m_attachments.erase(AZStd::next(begin(m_attachments), nr)); // and re-add the root to the scheduler GetActorManager().GetScheduler()->RecursiveInsertActorInstance(root, 0); @@ -532,9 +532,9 @@ namespace EMotionFX void ActorInstance::RemoveAllAttachments(bool delFromMem) { // keep removing the last attachment until there are none left - while (mAttachments.size()) + while (m_attachments.size()) { - RemoveAttachment(mAttachments.size() - 1, delFromMem); + RemoveAttachment(m_attachments.size() - 1, delFromMem); } } @@ -542,26 +542,26 @@ namespace EMotionFX void ActorInstance::UpdateDependencies() { // get rid of existing dependencies - mDependencies.clear(); + m_dependencies.clear(); // add the main dependency Actor::Dependency mainDependency; - mainDependency.mActor = mActor; - mainDependency.mAnimGraph = (mAnimGraphInstance) ? mAnimGraphInstance->GetAnimGraph() : nullptr; - mDependencies.emplace_back(mainDependency); + mainDependency.m_actor = m_actor; + mainDependency.m_animGraph = (m_animGraphInstance) ? m_animGraphInstance->GetAnimGraph() : nullptr; + m_dependencies.emplace_back(mainDependency); // add all dependencies stored inside the actor - const size_t numDependencies = mActor->GetNumDependencies(); + const size_t numDependencies = m_actor->GetNumDependencies(); for (size_t i = 0; i < numDependencies; ++i) { - mDependencies.emplace_back(*mActor->GetDependency(i)); + m_dependencies.emplace_back(*m_actor->GetDependency(i)); } } // set the attachment matrices void ActorInstance::UpdateAttachments() { - for (Attachment* attachment : mAttachments) + for (Attachment* attachment : m_attachments) { attachment->Update(); } @@ -572,9 +572,9 @@ namespace EMotionFX // attachment root ActorInstance* ActorInstance::FindAttachmentRoot() const { - if (mAttachedTo) + if (m_attachedTo) { - return mAttachedTo->FindAttachmentRoot(); + return m_attachedTo->FindAttachmentRoot(); } return const_cast(this); @@ -636,8 +636,8 @@ namespace EMotionFX { *outResult = AZ::Aabb::CreateNull(); - const Pose* pose = mTransformData->GetCurrentPose(); - const Skeleton* skeleton = mActor->GetSkeleton(); + const Pose* pose = m_transformData->GetCurrentPose(); + const Skeleton* skeleton = m_actor->GetSkeleton(); // for all nodes, encapsulate the world space positions const size_t numNodes = GetNumEnabledNodes(); @@ -646,7 +646,7 @@ namespace EMotionFX const uint16 nodeNr = GetEnabledNode(i); if (skeleton->GetNode(nodeNr)->GetIncludeInBoundsCalc()) { - outResult->AddPoint(pose->GetWorldSpaceTransform(nodeNr).mPosition); + outResult->AddPoint(pose->GetWorldSpaceTransform(nodeNr).m_position); } } } @@ -656,8 +656,8 @@ namespace EMotionFX { *outResult = AZ::Aabb::CreateNull(); - const Pose* pose = mTransformData->GetCurrentPose(); - const Skeleton* skeleton = mActor->GetSkeleton(); + const Pose* pose = m_transformData->GetCurrentPose(); + const Skeleton* skeleton = m_actor->GetSkeleton(); // for all nodes, encapsulate the world space positions const size_t numNodes = GetNumEnabledNodes(); @@ -667,7 +667,7 @@ namespace EMotionFX Node* node = skeleton->GetNode(nodeNr); // skip nodes without meshes - Mesh* mesh = mActor->GetMesh(geomLODLevel, nodeNr); + Mesh* mesh = m_actor->GetMesh(geomLODLevel, nodeNr); if (mesh == nullptr) { continue; @@ -692,9 +692,9 @@ namespace EMotionFX void ActorInstance::SetupAutoBoundsUpdate(float updateFrequencyInSeconds, EBoundsType boundsType, uint32 itemFrequency) { MCORE_ASSERT(itemFrequency > 0); // zero would cause an infinite loop - mBoundsUpdateFrequency = updateFrequencyInSeconds; - mBoundsUpdateType = boundsType; - mBoundsUpdateItemFreq = itemFrequency; + m_boundsUpdateFrequency = updateFrequencyInSeconds; + m_boundsUpdateType = boundsType; + m_boundsUpdateItemFreq = itemFrequency; SetBoundsUpdateEnabled(true); } @@ -709,7 +709,7 @@ namespace EMotionFX } // if there is no morph setup, we have nothing to do - MorphSetup* morphSetup = mActor->GetMorphSetup(mLODLevel); + MorphSetup* morphSetup = m_actor->GetMorphSetup(m_lodLevel); if (morphSetup == nullptr) { return; @@ -745,8 +745,8 @@ namespace EMotionFX // check intersection with a ray, but don't get the intersection point or closest intersecting node Node* ActorInstance::IntersectsCollisionMesh(size_t lodLevel, const MCore::Ray& ray) const { - const Skeleton* skeleton = mActor->GetSkeleton(); - const Pose* pose = mTransformData->GetCurrentPose(); + const Skeleton* skeleton = m_actor->GetSkeleton(); + const Pose* pose = m_transformData->GetCurrentPose(); // for all nodes const size_t numNodes = GetNumEnabledNodes(); @@ -755,7 +755,7 @@ namespace EMotionFX const uint16 nodeNr = GetEnabledNode(i); // check if there is a mesh for this node - Mesh* mesh = mActor->GetMesh(lodLevel, nodeNr); + Mesh* mesh = m_actor->GetMesh(lodLevel, nodeNr); if (mesh == nullptr) { continue; @@ -789,8 +789,8 @@ namespace EMotionFX uint32 closestIndices[3]; uint32 triIndices[3]; - const Skeleton* skeleton = mActor->GetSkeleton(); - const Pose* pose = mTransformData->GetCurrentPose(); + const Skeleton* skeleton = m_actor->GetSkeleton(); + const Pose* pose = m_transformData->GetCurrentPose(); // check all nodes const size_t numNodes = GetNumEnabledNodes(); @@ -798,7 +798,7 @@ namespace EMotionFX { const uint16 nodeNr = GetEnabledNode(i); Node* curNode = skeleton->GetNode(nodeNr); - Mesh* mesh = mActor->GetMesh(lodLevel, nodeNr); + Mesh* mesh = m_actor->GetMesh(lodLevel, nodeNr); if (mesh == nullptr) { continue; @@ -861,7 +861,7 @@ namespace EMotionFX // calculate the interpolated normal if (outNormal || outUV) { - Mesh* mesh = mActor->GetMesh(lodLevel, closestNode->GetNodeIndex()); + Mesh* mesh = m_actor->GetMesh(lodLevel, closestNode->GetNodeIndex()); // calculate the normal at the intersection point if (outNormal) @@ -894,8 +894,8 @@ namespace EMotionFX // check intersection with a ray, but don't get the intersection point or closest intersecting node Node* ActorInstance::IntersectsMesh(size_t lodLevel, const MCore::Ray& ray) const { - const Pose* pose = mTransformData->GetCurrentPose(); - const Skeleton* skeleton = mActor->GetSkeleton(); + const Pose* pose = m_transformData->GetCurrentPose(); + const Skeleton* skeleton = m_actor->GetSkeleton(); // for all nodes const size_t numNodes = GetNumEnabledNodes(); @@ -905,7 +905,7 @@ namespace EMotionFX Node* node = skeleton->GetNode(nodeNr); // check if there is a mesh for this node - Mesh* mesh = mActor->GetMesh(lodLevel, nodeNr); + Mesh* mesh = m_actor->GetMesh(lodLevel, nodeNr); if (mesh == nullptr) { continue; @@ -953,8 +953,8 @@ namespace EMotionFX uint32 closestIndices[3]; uint32 triIndices[3]; - const Pose* pose = mTransformData->GetCurrentPose(); - const Skeleton* skeleton = mActor->GetSkeleton(); + const Pose* pose = m_transformData->GetCurrentPose(); + const Skeleton* skeleton = m_actor->GetSkeleton(); // check all nodes const size_t numNodes = GetNumEnabledNodes(); @@ -962,7 +962,7 @@ namespace EMotionFX { const uint16 nodeNr = GetEnabledNode(i); Node* curNode = skeleton->GetNode(nodeNr); - Mesh* mesh = mActor->GetMesh(lodLevel, nodeNr); + Mesh* mesh = m_actor->GetMesh(lodLevel, nodeNr); if (mesh == nullptr) { continue; @@ -1020,7 +1020,7 @@ namespace EMotionFX // calculate the interpolated normal if (outNormal || outUV) { - Mesh* mesh = mActor->GetMesh(lodLevel, closestNode->GetNodeIndex()); + Mesh* mesh = m_actor->GetMesh(lodLevel, closestNode->GetNodeIndex()); // calculate the normal at the intersection point if (outNormal) @@ -1058,12 +1058,12 @@ namespace EMotionFX void ActorInstance::EnableNode(uint16 nodeIndex) { // if this node already is at an enabled state, do nothing - if (AZStd::find(begin(mEnabledNodes), end(mEnabledNodes), nodeIndex) != end(mEnabledNodes)) + if (AZStd::find(begin(m_enabledNodes), end(m_enabledNodes), nodeIndex) != end(m_enabledNodes)) { return; } - Skeleton* skeleton = mActor->GetSkeleton(); + Skeleton* skeleton = m_actor->GetSkeleton(); // find the location where to insert (as the flattened hierarchy needs to be preserved in the array) bool found = false; @@ -1074,16 +1074,16 @@ namespace EMotionFX size_t parentIndex = skeleton->GetNode(curNode)->GetParentIndex(); if (parentIndex != InvalidIndex) { - const auto parentArrayIter = AZStd::find(begin(mEnabledNodes), end(mEnabledNodes), static_cast(parentIndex)); - if (parentArrayIter != end(mEnabledNodes)) + const auto parentArrayIter = AZStd::find(begin(m_enabledNodes), end(m_enabledNodes), static_cast(parentIndex)); + if (parentArrayIter != end(m_enabledNodes)) { - if (parentArrayIter + 1 == end(mEnabledNodes)) + if (parentArrayIter + 1 == end(m_enabledNodes)) { - mEnabledNodes.emplace_back(nodeIndex); + m_enabledNodes.emplace_back(nodeIndex); } else { - mEnabledNodes.emplace(parentArrayIter + 1, nodeIndex); + m_enabledNodes.emplace(parentArrayIter + 1, nodeIndex); } found = true; } @@ -1094,7 +1094,7 @@ namespace EMotionFX } else // if we're dealing with a root node, insert it in the front of the array { - mEnabledNodes.emplace(AZStd::next(begin(mEnabledNodes), 0), nodeIndex); + m_enabledNodes.emplace(AZStd::next(begin(m_enabledNodes), 0), nodeIndex); found = true; } } while (found == false); @@ -1104,24 +1104,24 @@ namespace EMotionFX void ActorInstance::DisableNode(uint16 nodeIndex) { // try to remove the node from the array - const auto it = AZStd::find(begin(mEnabledNodes), end(mEnabledNodes), nodeIndex); - if (it != end(mEnabledNodes)) + const auto it = AZStd::find(begin(m_enabledNodes), end(m_enabledNodes), nodeIndex); + if (it != end(m_enabledNodes)) { - mEnabledNodes.erase(it); + m_enabledNodes.erase(it); } } // enable all nodes void ActorInstance::EnableAllNodes() { - mEnabledNodes.resize(mActor->GetNumNodes()); - std::iota(mEnabledNodes.begin(), mEnabledNodes.end(), 0); + m_enabledNodes.resize(m_actor->GetNumNodes()); + std::iota(m_enabledNodes.begin(), m_enabledNodes.end(), 0); } // disable all nodes void ActorInstance::DisableAllNodes() { - mEnabledNodes.clear(); + m_enabledNodes.clear(); } // change the skeletal LOD level @@ -1131,12 +1131,12 @@ namespace EMotionFX const size_t newLevel = MCore::Clamp(level, 0, 63); // if the lod level is the same as it currently is, do nothing - if (newLevel == mLODLevel) + if (newLevel == m_lodLevel) { return; } - Skeleton* skeleton = mActor->GetSkeleton(); + Skeleton* skeleton = m_actor->GetSkeleton(); // change the state of all nodes that need state changes const size_t numNodes = GetNumNodes(); @@ -1145,7 +1145,7 @@ namespace EMotionFX Node* node = skeleton->GetNode(i); // check the curent and the new enabled state - const bool curEnabled = node->GetSkeletalLODStatus(mLODLevel); + const bool curEnabled = node->GetSkeletalLODStatus(m_lodLevel); const bool newEnabled = node->GetSkeletalLODStatus(newLevel); // if the state changed, enable or disable it @@ -1171,13 +1171,13 @@ namespace EMotionFX void ActorInstance::UpdateLODLevel() { // Switch LOD level in case a change was requested. - if (mLODLevel != m_requestedLODLevel) + if (m_lodLevel != m_requestedLODLevel) { - // Enable and disable all nodes accordingly (do not call this after setting the new mLODLevel) + // Enable and disable all nodes accordingly (do not call this after setting the new m_lodLevel) SetSkeletalLODLevelNodeFlags(m_requestedLODLevel); // Make sure the LOD level is valid and update it. - mLODLevel = MCore::Clamp(m_requestedLODLevel, 0, mActor->GetNumLODLevels() - 1); + m_lodLevel = MCore::Clamp(m_requestedLODLevel, 0, m_actor->GetNumLODLevels() - 1); } } @@ -1185,14 +1185,14 @@ namespace EMotionFX void ActorInstance::UpdateSkeletalLODFlags() { // change the state of all nodes that need state changes - Skeleton* skeleton = mActor->GetSkeleton(); + Skeleton* skeleton = m_actor->GetSkeleton(); const size_t numNodes = skeleton->GetNumNodes(); for (size_t i = 0; i < numNodes; ++i) { Node* node = skeleton->GetNode(i); // if the new LOD says that this node should be enabled, enable it - if (node->GetSkeletalLODStatus(mLODLevel)) + if (node->GetSkeletalLODStatus(m_lodLevel)) { EnableNode(static_cast(i)); } @@ -1208,7 +1208,7 @@ namespace EMotionFX { uint32 numDisabledNodes = 0; - const Skeleton* skeleton = mActor->GetSkeleton(); + const Skeleton* skeleton = m_actor->GetSkeleton(); // get the number of nodes and iterate through them const size_t numNodes = GetNumNodes(); @@ -1259,23 +1259,23 @@ namespace EMotionFX // change the current motion system void ActorInstance::SetMotionSystem(MotionSystem* newSystem, bool delCurrentFromMem) { - if (delCurrentFromMem && mMotionSystem) + if (delCurrentFromMem && m_motionSystem) { - mMotionSystem->Destroy(); + m_motionSystem->Destroy(); } - mMotionSystem = newSystem; + m_motionSystem = newSystem; } // check if this actor instance is a skin attachment bool ActorInstance::GetIsSkinAttachment() const { - if (mSelfAttachment == nullptr) + if (m_selfAttachment == nullptr) { return false; } - return mSelfAttachment->GetIsInfluencedByMultipleJoints(); + return m_selfAttachment->GetIsInfluencedByMultipleJoints(); } // draw a skeleton using lines, calling the drawline callbacks in the event handlers @@ -1294,14 +1294,14 @@ namespace EMotionFX Transform trajectoryTransform = inOutMotionExtractionNodeTransform; // Make sure the z axis is really pointing up and project it onto the ground plane. - const AZ::Vector3 forwardAxis = MCore::CalcForwardAxis(trajectoryTransform.mRotation); + const AZ::Vector3 forwardAxis = MCore::CalcForwardAxis(trajectoryTransform.m_rotation); if (forwardAxis.GetZ() > 0.0f) // Pick the closest, so if we point more upwards already, we take 1.0, otherwise take -1.0. Sometimes Y would point up, sometimes down. { - MCore::RotateFromTo(trajectoryTransform.mRotation, forwardAxis, AZ::Vector3(0.0f, 0.0f, 1.0f)); + MCore::RotateFromTo(trajectoryTransform.m_rotation, forwardAxis, AZ::Vector3(0.0f, 0.0f, 1.0f)); } else { - MCore::RotateFromTo(trajectoryTransform.mRotation, forwardAxis, AZ::Vector3(0.0f, 0.0f, -1.0f)); + MCore::RotateFromTo(trajectoryTransform.m_rotation, forwardAxis, AZ::Vector3(0.0f, 0.0f, -1.0f)); } trajectoryTransform.ApplyMotionExtractionFlags(motionExtractionFlags); @@ -1311,15 +1311,15 @@ namespace EMotionFX bindTransformProjected.ApplyMotionExtractionFlags(motionExtractionFlags); // Remove the projected rotation and translation from the transform to prevent the double transform. - inOutMotionExtractionNodeTransform.mRotation = (bindTransformProjected.mRotation.GetConjugate() * trajectoryTransform.mRotation).GetConjugate() * inOutMotionExtractionNodeTransform.mRotation; - inOutMotionExtractionNodeTransform.mPosition = inOutMotionExtractionNodeTransform.mPosition - (trajectoryTransform.mPosition - bindTransformProjected.mPosition); - inOutMotionExtractionNodeTransform.mRotation.Normalize(); + inOutMotionExtractionNodeTransform.m_rotation = (bindTransformProjected.m_rotation.GetConjugate() * trajectoryTransform.m_rotation).GetConjugate() * inOutMotionExtractionNodeTransform.m_rotation; + inOutMotionExtractionNodeTransform.m_position = inOutMotionExtractionNodeTransform.m_position - (trajectoryTransform.m_position - bindTransformProjected.m_position); + inOutMotionExtractionNodeTransform.m_rotation.Normalize(); } void ActorInstance::MotionExtractionCompensate(Transform& inOutMotionExtractionNodeTransform, EMotionExtractionFlags motionExtractionFlags) const { - MCORE_ASSERT(mActor->GetMotionExtractionNodeIndex() != InvalidIndex); - Transform bindPoseTransform = mTransformData->GetBindPose()->GetLocalSpaceTransform(mActor->GetMotionExtractionNodeIndex()); + MCORE_ASSERT(m_actor->GetMotionExtractionNodeIndex() != InvalidIndex); + Transform bindPoseTransform = m_transformData->GetBindPose()->GetLocalSpaceTransform(m_actor->GetMotionExtractionNodeIndex()); MotionExtractionCompensate(inOutMotionExtractionNodeTransform, bindPoseTransform, motionExtractionFlags); } @@ -1327,13 +1327,13 @@ namespace EMotionFX // Remove the trajectory transform from the motion extraction node to prevent double transformation. void ActorInstance::MotionExtractionCompensate(EMotionExtractionFlags motionExtractionFlags) { - const size_t motionExtractIndex = mActor->GetMotionExtractionNodeIndex(); + const size_t motionExtractIndex = m_actor->GetMotionExtractionNodeIndex(); if (motionExtractIndex == InvalidIndex) { return; } - Pose* currentPose = mTransformData->GetCurrentPose(); + Pose* currentPose = m_transformData->GetCurrentPose(); Transform transform = currentPose->GetLocalSpaceTransform(motionExtractIndex); MotionExtractionCompensate(transform, motionExtractionFlags); @@ -1344,13 +1344,13 @@ namespace EMotionFX { Transform curTransform = inOutTransform; #ifndef EMFX_SCALE_DISABLED - curTransform.mPosition += trajectoryDelta.mPosition * curTransform.mScale; + curTransform.m_position += trajectoryDelta.m_position * curTransform.m_scale; #else - curTransform.mPosition += trajectoryDelta.mPosition; + curTransform.m_position += trajectoryDelta.m_position; #endif - curTransform.mRotation *= trajectoryDelta.mRotation; - curTransform.mRotation.Normalize(); + curTransform.m_rotation *= trajectoryDelta.m_rotation; + curTransform.m_rotation.Normalize(); inOutTransform = curTransform; } @@ -1358,18 +1358,18 @@ namespace EMotionFX // Apply the motion extraction delta transform to the actor instance. void ActorInstance::ApplyMotionExtractionDelta(const Transform& trajectoryDelta) { - if (mActor->GetMotionExtractionNodeIndex() == InvalidIndex) + if (m_actor->GetMotionExtractionNodeIndex() == InvalidIndex) { return; } - ApplyMotionExtractionDelta(mLocalTransform, trajectoryDelta); + ApplyMotionExtractionDelta(m_localTransform, trajectoryDelta); } // apply the currently set motion extraction delta transform to the actor instance void ActorInstance::ApplyMotionExtractionDelta() { - ApplyMotionExtractionDelta(mTrajectoryDelta); + ApplyMotionExtractionDelta(m_trajectoryDelta); } void ActorInstance::SetMotionExtractionEnabled(bool enabled) @@ -1379,7 +1379,7 @@ namespace EMotionFX bool ActorInstance::GetMotionExtractionEnabled() const { - return (mBoolFlags & BOOL_MOTIONEXTRACTION) != 0; + return (m_boolFlags & BOOL_MOTIONEXTRACTION) != 0; } // update the static based aabb dimensions @@ -1393,7 +1393,7 @@ namespace EMotionFX UpdateMeshDeformers(0.0f); // calculate the aabb of this - if (mActor->CheckIfHasMeshes(0)) + if (m_actor->CheckIfHasMeshes(0)) { CalcMeshBasedAabb(0, &m_staticAabb); } @@ -1402,7 +1402,7 @@ namespace EMotionFX CalcNodeBasedAabb(&m_staticAabb); } - mLocalTransform = orgTransform; + m_localTransform = orgTransform; } // calculate the moved static based aabb @@ -1410,52 +1410,52 @@ namespace EMotionFX { if (GetIsSkinAttachment()) { - mSelfAttachment->GetAttachToActorInstance()->CalcStaticBasedAabb(outResult); + m_selfAttachment->GetAttachToActorInstance()->CalcStaticBasedAabb(outResult); return; } *outResult = m_staticAabb; EMFX_SCALECODE( - outResult->SetMin(m_staticAabb.GetMin() * mWorldTransform.mScale); - outResult->SetMax(m_staticAabb.GetMax() * mWorldTransform.mScale);) - outResult->Translate(mWorldTransform.mPosition); + outResult->SetMin(m_staticAabb.GetMin() * m_worldTransform.m_scale); + outResult->SetMax(m_staticAabb.GetMax() * m_worldTransform.m_scale);) + outResult->Translate(m_worldTransform.m_position); } // adjust the anim graph instance void ActorInstance::SetAnimGraphInstance(AnimGraphInstance* instance) { - mAnimGraphInstance = instance; + m_animGraphInstance = instance; UpdateDependencies(); } Actor* ActorInstance::GetActor() const { - return mActor; + return m_actor; } void ActorInstance::SetID(uint32 id) { - mID = id; + m_id = id; } MotionSystem* ActorInstance::GetMotionSystem() const { - return mMotionSystem; + return m_motionSystem; } size_t ActorInstance::GetLODLevel() const { - return mLODLevel; + return m_lodLevel; } void ActorInstance::SetCustomData(void* customData) { - mCustomData = customData; + m_customData = customData; } void* ActorInstance::GetCustomData() const { - return mCustomData; + return m_customData; } AZ::Entity* ActorInstance::GetEntity() const @@ -1475,48 +1475,48 @@ namespace EMotionFX bool ActorInstance::GetBoundsUpdateEnabled() const { - return (mBoolFlags & BOOL_BOUNDSUPDATEENABLED); + return (m_boolFlags & BOOL_BOUNDSUPDATEENABLED); } float ActorInstance::GetBoundsUpdateFrequency() const { - return mBoundsUpdateFrequency; + return m_boundsUpdateFrequency; } float ActorInstance::GetBoundsUpdatePassedTime() const { - return mBoundsUpdatePassedTime; + return m_boundsUpdatePassedTime; } ActorInstance::EBoundsType ActorInstance::GetBoundsUpdateType() const { - return mBoundsUpdateType; + return m_boundsUpdateType; } uint32 ActorInstance::GetBoundsUpdateItemFrequency() const { - return mBoundsUpdateItemFreq; + return m_boundsUpdateItemFreq; } void ActorInstance::SetBoundsUpdateFrequency(float seconds) { - mBoundsUpdateFrequency = seconds; + m_boundsUpdateFrequency = seconds; } void ActorInstance::SetBoundsUpdatePassedTime(float seconds) { - mBoundsUpdatePassedTime = seconds; + m_boundsUpdatePassedTime = seconds; } void ActorInstance::SetBoundsUpdateType(EBoundsType bType) { - mBoundsUpdateType = bType; + m_boundsUpdateType = bType; } void ActorInstance::SetBoundsUpdateItemFrequency(uint32 freq) { MCORE_ASSERT(freq >= 1); - mBoundsUpdateItemFreq = freq; + m_boundsUpdateItemFreq = freq; } void ActorInstance::SetBoundsUpdateEnabled(bool enable) @@ -1551,52 +1551,52 @@ namespace EMotionFX size_t ActorInstance::GetNumAttachments() const { - return mAttachments.size(); + return m_attachments.size(); } Attachment* ActorInstance::GetAttachment(size_t nr) const { - return mAttachments[nr]; + return m_attachments[nr]; } bool ActorInstance::GetIsAttachment() const { - return (mAttachedTo != nullptr); + return (m_attachedTo != nullptr); } ActorInstance* ActorInstance::GetAttachedTo() const { - return mAttachedTo; + return m_attachedTo; } Attachment* ActorInstance::GetSelfAttachment() const { - return mSelfAttachment; + return m_selfAttachment; } size_t ActorInstance::GetNumDependencies() const { - return mDependencies.size(); + return m_dependencies.size(); } Actor::Dependency* ActorInstance::GetDependency(size_t nr) { - return &mDependencies[nr]; + return &m_dependencies[nr]; } MorphSetupInstance* ActorInstance::GetMorphSetupInstance() const { - return mMorphSetup; + return m_morphSetup; } void ActorInstance::SetParentWorldSpaceTransform(const Transform& transform) { - mParentWorldTransform = transform; + m_parentWorldTransform = transform; } const Transform& ActorInstance::GetParentWorldSpaceTransform() const { - return mParentWorldTransform; + return m_parentWorldTransform; } void ActorInstance::SetRender(bool enabled) @@ -1606,7 +1606,7 @@ namespace EMotionFX bool ActorInstance::GetRender() const { - return (mBoolFlags & BOOL_RENDER) != 0; + return (m_boolFlags & BOOL_RENDER) != 0; } void ActorInstance::SetIsUsedForVisualization(bool enabled) @@ -1616,7 +1616,7 @@ namespace EMotionFX bool ActorInstance::GetIsUsedForVisualization() const { - return (mBoolFlags & BOOL_USEDFORVISUALIZATION) != 0; + return (m_boolFlags & BOOL_USEDFORVISUALIZATION) != 0; } void ActorInstance::SetIsOwnedByRuntime(bool isOwnedByRuntime) @@ -1631,7 +1631,7 @@ namespace EMotionFX bool ActorInstance::GetIsOwnedByRuntime() const { #if defined(EMFX_DEVELOPMENT_BUILD) - return (mBoolFlags & BOOL_OWNEDBYRUNTIME) != 0; + return (m_boolFlags & BOOL_OWNEDBYRUNTIME) != 0; #else return true; #endif @@ -1639,22 +1639,22 @@ namespace EMotionFX uint32 ActorInstance::GetThreadIndex() const { - return mThreadIndex; + return m_threadIndex; } void ActorInstance::SetThreadIndex(uint32 index) { - mThreadIndex = index; + m_threadIndex = index; } void ActorInstance::SetTrajectoryDeltaTransform(const Transform& transform) { - mTrajectoryDelta = transform; + m_trajectoryDelta = transform; } const Transform& ActorInstance::GetTrajectoryDeltaTransform() const { - return mTrajectoryDelta; + return m_trajectoryDelta; } AnimGraphPose* ActorInstance::RequestPose(uint32 threadIndex) @@ -1669,70 +1669,70 @@ namespace EMotionFX void ActorInstance::SetMotionSamplingTimer(float timeInSeconds) { - mMotionSamplingTimer = timeInSeconds; + m_motionSamplingTimer = timeInSeconds; } void ActorInstance::SetMotionSamplingRate(float updateRateInSeconds) { - mMotionSamplingRate = updateRateInSeconds; + m_motionSamplingRate = updateRateInSeconds; } float ActorInstance::GetMotionSamplingTimer() const { - return mMotionSamplingTimer; + return m_motionSamplingTimer; } float ActorInstance::GetMotionSamplingRate() const { - return mMotionSamplingRate; + return m_motionSamplingRate; } void ActorInstance::IncreaseNumAttachmentRefs(uint8 numToIncreaseWith) { - mNumAttachmentRefs += numToIncreaseWith; - MCORE_ASSERT(mNumAttachmentRefs == 0 || mNumAttachmentRefs == 1); + m_numAttachmentRefs += numToIncreaseWith; + MCORE_ASSERT(m_numAttachmentRefs == 0 || m_numAttachmentRefs == 1); } void ActorInstance::DecreaseNumAttachmentRefs(uint8 numToDecreaseWith) { - mNumAttachmentRefs -= numToDecreaseWith; - MCORE_ASSERT(mNumAttachmentRefs == 0 || mNumAttachmentRefs == 1); + m_numAttachmentRefs -= numToDecreaseWith; + MCORE_ASSERT(m_numAttachmentRefs == 0 || m_numAttachmentRefs == 1); } uint8 ActorInstance::GetNumAttachmentRefs() const { - return mNumAttachmentRefs; + return m_numAttachmentRefs; } void ActorInstance::SetAttachedTo(ActorInstance* actorInstance) { - mAttachedTo = actorInstance; + m_attachedTo = actorInstance; } void ActorInstance::SetSelfAttachment(Attachment* selfAttachment) { - mSelfAttachment = selfAttachment; + m_selfAttachment = selfAttachment; } void ActorInstance::EnableFlag(uint8 flag) { - mBoolFlags |= flag; + m_boolFlags |= flag; } void ActorInstance::DisableFlag(uint8 flag) { - mBoolFlags &= ~flag; + m_boolFlags &= ~flag; } void ActorInstance::SetFlag(uint8 flag, bool enabled) { if (enabled) { - mBoolFlags |= flag; + m_boolFlags |= flag; } else { - mBoolFlags &= ~flag; + m_boolFlags &= ~flag; } } @@ -1741,7 +1741,7 @@ namespace EMotionFX SetIsVisible(isVisible); // recurse to all child attachments - for (Attachment* attachment : mAttachments) + for (Attachment* attachment : m_attachments) { attachment->GetAttachmentActorInstance()->RecursiveSetIsVisible(isVisible); } @@ -1750,9 +1750,9 @@ namespace EMotionFX void ActorInstance::RecursiveSetIsVisibleTowardsRoot(bool isVisible) { SetIsVisible(isVisible); - if (mSelfAttachment) + if (m_selfAttachment) { - mSelfAttachment->GetAttachToActorInstance()->RecursiveSetIsVisibleTowardsRoot(isVisible); + m_selfAttachment->GetAttachToActorInstance()->RecursiveSetIsVisibleTowardsRoot(isVisible); } } @@ -1764,7 +1764,7 @@ namespace EMotionFX // update the normal scale factor based on the bounds void ActorInstance::UpdateVisualizeScale() { - mVisualizeScale = 0.0f; + m_visualizeScale = 0.0f; UpdateMeshDeformers(0.0f); AZ::Aabb box = AZ::Aabb::CreateNull(); @@ -1773,29 +1773,29 @@ namespace EMotionFX if (box.IsValid()) { const float boxRadius = AZ::Vector3(box.GetMax() - box.GetMin()).GetLength() * 0.5f; - mVisualizeScale = MCore::Max(mVisualizeScale, boxRadius); + m_visualizeScale = MCore::Max(m_visualizeScale, boxRadius); } CalcMeshBasedAabb(0, &box); if (box.IsValid()) { const float boxRadius = AZ::Vector3(box.GetMax() - box.GetMin()).GetLength() * 0.5f; - mVisualizeScale = MCore::Max(mVisualizeScale, boxRadius); + m_visualizeScale = MCore::Max(m_visualizeScale, boxRadius); } - mVisualizeScale *= 0.01f; + m_visualizeScale *= 0.01f; } // get the normal scale factor float ActorInstance::GetVisualizeScale() const { - return mVisualizeScale; + return m_visualizeScale; } // manually set the visualize scale factor void ActorInstance::SetVisualizeScale(float factor) { - mVisualizeScale = factor; + m_visualizeScale = factor; } // Recursively check if we have a given attachment in the hierarchy going downwards. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.h b/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.h index 05a8136326..7ca134c0db 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.h @@ -75,7 +75,7 @@ namespace EMotionFX * Get the unique identification number for the actor instance. * @return The unique identification number. */ - MCORE_INLINE uint32 GetID() const { return mID; } + MCORE_INLINE uint32 GetID() const { return m_id; } /** * Set the unique identification number for the actor instance. @@ -104,7 +104,7 @@ namespace EMotionFX * This can return nullptr, in which case the motion system as returned by GetMotionSystem() will be used. * @result The anim graph instance. */ - MCORE_INLINE AnimGraphInstance* GetAnimGraphInstance() const { return mAnimGraphInstance; } + MCORE_INLINE AnimGraphInstance* GetAnimGraphInstance() const { return m_animGraphInstance; } /** * Set the anim graph instance. @@ -119,7 +119,7 @@ namespace EMotionFX * So if you wish to get or set any transformations, you can do it with the object returned by this method. * @result A pointer to the transformation data object. */ - MCORE_INLINE TransformData* GetTransformData() const { return mTransformData; } + MCORE_INLINE TransformData* GetTransformData() const { return m_transformData; } /** * Enable or disable this actor instance. @@ -136,7 +136,7 @@ namespace EMotionFX * Disabled actor instances are not updated and processed. * @result Returns true when enabled, or false when disabled. */ - MCORE_INLINE bool GetIsEnabled() const { return (mBoolFlags & BOOL_ENABLED) != 0; } + MCORE_INLINE bool GetIsEnabled() const { return (m_boolFlags & BOOL_ENABLED) != 0; } /** * Check the visibility flag. @@ -144,7 +144,7 @@ namespace EMotionFX * This is used internally by the schedulers, so that heavy calculations can be skipped on invisible characters. * @result Returns true when the actor instance is marked as visible, otherwise false is returned. */ - MCORE_INLINE bool GetIsVisible() const { return (mBoolFlags & BOOL_ISVISIBLE) != 0; } + MCORE_INLINE bool GetIsVisible() const { return (m_boolFlags & BOOL_ISVISIBLE) != 0; } /** * Change the visibility state. @@ -489,14 +489,14 @@ namespace EMotionFX * This is relative to its parent (if it is attached ot something). Otherwise it is in world space. * @param position The position/translation to use. */ - MCORE_INLINE void SetLocalSpacePosition(const AZ::Vector3& position) { mLocalTransform.mPosition = position; } + MCORE_INLINE void SetLocalSpacePosition(const AZ::Vector3& position) { m_localTransform.m_position = position; } /** * Set the local rotation of this actor instance. * This is relative to its parent (if it is attached ot something). Otherwise it is in world space. * @param rotation The rotation to use. */ - MCORE_INLINE void SetLocalSpaceRotation(const AZ::Quaternion& rotation) { mLocalTransform.mRotation = rotation; } + MCORE_INLINE void SetLocalSpaceRotation(const AZ::Quaternion& rotation) { m_localTransform.m_rotation = rotation; } EMFX_SCALECODE ( @@ -505,14 +505,14 @@ namespace EMotionFX * This is relative to its parent (if it is attached ot something). Otherwise it is in world space. * @param scale The scale to use. */ - MCORE_INLINE void SetLocalSpaceScale(const AZ::Vector3& scale) { mLocalTransform.mScale = scale; } + MCORE_INLINE void SetLocalSpaceScale(const AZ::Vector3& scale) { m_localTransform.m_scale = scale; } /** * Get the local space scale. * This is relative to its parent (if it is attached ot something). Otherwise it is in world space. * @result The local space scale factor for each axis. */ - MCORE_INLINE const AZ::Vector3& GetLocalSpaceScale() const { return mLocalTransform.mScale; } + MCORE_INLINE const AZ::Vector3& GetLocalSpaceScale() const { return m_localTransform.m_scale; } ) /** @@ -520,20 +520,20 @@ namespace EMotionFX * This is relative to its parent (if it is attached ot something). Otherwise it is in world space. * @result The local space position. */ - MCORE_INLINE const AZ::Vector3& GetLocalSpacePosition() const { return mLocalTransform.mPosition; } + MCORE_INLINE const AZ::Vector3& GetLocalSpacePosition() const { return m_localTransform.m_position; } /** * Get the local space rotation of this actor instance. * This is relative to its parent (if it is attached ot something). Otherwise it is in world space. * @result The local space rotation. */ - MCORE_INLINE const AZ::Quaternion& GetLocalSpaceRotation() const { return mLocalTransform.mRotation; } + MCORE_INLINE const AZ::Quaternion& GetLocalSpaceRotation() const { return m_localTransform.m_rotation; } - MCORE_INLINE void SetLocalSpaceTransform(const Transform& transform) { mLocalTransform = transform; } + MCORE_INLINE void SetLocalSpaceTransform(const Transform& transform) { m_localTransform = transform; } - MCORE_INLINE const Transform& GetLocalSpaceTransform() const { return mLocalTransform; } - MCORE_INLINE const Transform& GetWorldSpaceTransform() const { return mWorldTransform; } - MCORE_INLINE const Transform& GetWorldSpaceTransformInversed() const { return mWorldTransformInv; } + MCORE_INLINE const Transform& GetLocalSpaceTransform() const { return m_localTransform; } + MCORE_INLINE const Transform& GetWorldSpaceTransform() const { return m_worldTransform; } + MCORE_INLINE const Transform& GetWorldSpaceTransformInversed() const { return m_worldTransformInv; } //------------------------------------------------------------------------------------------- @@ -788,20 +788,20 @@ namespace EMotionFX * Get direct access to the array of enabled nodes. * @result A read only reference to the array of enabled nodes. The values inside of this array are the node numbers of the enabled nodes. */ - MCORE_INLINE const AZStd::vector& GetEnabledNodes() const { return mEnabledNodes; } + MCORE_INLINE const AZStd::vector& GetEnabledNodes() const { return m_enabledNodes; } /** * Get the number of enabled nodes inside this actor instance. * @result The number of nodes that have been enabled and are being updated. */ - MCORE_INLINE size_t GetNumEnabledNodes() const { return mEnabledNodes.size(); } + MCORE_INLINE size_t GetNumEnabledNodes() const { return m_enabledNodes.size(); } /** * Get the node number of a given enabled node. * @param index An index in the array of enabled nodes. This must be in range of [0..GetNumEnabledNodes()-1]. * @result The node number, which relates to Actor::GetNode( returnValue ). */ - MCORE_INLINE uint16 GetEnabledNode(size_t index) const { return mEnabledNodes[index]; } + MCORE_INLINE uint16 GetEnabledNode(size_t index) const { return m_enabledNodes[index]; } /** * Enable all nodes inside the actor instance. @@ -856,51 +856,51 @@ namespace EMotionFX float GetMotionSamplingTimer() const; float GetMotionSamplingRate() const; - MCORE_INLINE size_t GetNumNodes() const { return mActor->GetSkeleton()->GetNumNodes(); } + MCORE_INLINE size_t GetNumNodes() const { return m_actor->GetSkeleton()->GetNumNodes(); } void UpdateVisualizeScale(); // not automatically called on creation for performance reasons (this method relatively is slow as it updates all meshes) float GetVisualizeScale() const; void SetVisualizeScale(float factor); private: - TransformData* mTransformData; /**< The transformation data for this instance. */ + TransformData* m_transformData; /**< The transformation data for this instance. */ AZ::Aabb m_aabb; /**< The axis aligned bounding box. */ AZ::Aabb m_staticAabb; /**< A static pre-calculated bounding box, which we can move along with the position of the actor instance, and use for visibility checks. */ - Transform mLocalTransform = Transform::CreateIdentity(); - Transform mWorldTransform = Transform::CreateIdentity(); - Transform mWorldTransformInv = Transform::CreateIdentity(); - Transform mParentWorldTransform = Transform::CreateIdentity(); - Transform mTrajectoryDelta = Transform::CreateIdentityWithZeroScale(); + Transform m_localTransform = Transform::CreateIdentity(); + Transform m_worldTransform = Transform::CreateIdentity(); + Transform m_worldTransformInv = Transform::CreateIdentity(); + Transform m_parentWorldTransform = Transform::CreateIdentity(); + Transform m_trajectoryDelta = Transform::CreateIdentityWithZeroScale(); - AZStd::vector mAttachments; /**< The attachments linked to this actor instance. */ - AZStd::vector mDependencies; /**< The actor dependencies, which specify which Actor objects this instance is dependent on. */ - MorphSetupInstance* mMorphSetup; /**< The morph setup instance. */ - AZStd::vector mEnabledNodes; /**< The list of nodes that are enabled. */ + AZStd::vector m_attachments; /**< The attachments linked to this actor instance. */ + AZStd::vector m_dependencies; /**< The actor dependencies, which specify which Actor objects this instance is dependent on. */ + MorphSetupInstance* m_morphSetup; /**< The morph setup instance. */ + AZStd::vector m_enabledNodes; /**< The list of nodes that are enabled. */ - Actor* mActor; /**< A pointer to the parent actor where this is an instance from. */ - ActorInstance* mAttachedTo; /**< Specifies the actor where this actor is attached to, or nullptr when it is no attachment. */ - Attachment* mSelfAttachment; /**< The attachment it is itself inside the mAttachedTo actor instance, or nullptr when this isn't an attachment. */ - MotionSystem* mMotionSystem; /**< The motion system, that handles all motion playback and blending etc. */ - AnimGraphInstance* mAnimGraphInstance; /**< A pointer to the anim graph instance, which can be nullptr when there is no anim graph instance. */ + Actor* m_actor; /**< A pointer to the parent actor where this is an instance from. */ + ActorInstance* m_attachedTo; /**< Specifies the actor where this actor is attached to, or nullptr when it is no attachment. */ + Attachment* m_selfAttachment; /**< The attachment it is itself inside the m_attachedTo actor instance, or nullptr when this isn't an attachment. */ + MotionSystem* m_motionSystem; /**< The motion system, that handles all motion playback and blending etc. */ + AnimGraphInstance* m_animGraphInstance; /**< A pointer to the anim graph instance, which can be nullptr when there is no anim graph instance. */ AZStd::unique_ptr m_ragdollInstance; - MCore::Mutex mLock; /**< The multi-thread lock. */ - void* mCustomData; /**< A pointer to custom data for this actor. This could be a pointer to your engine or game object for example. */ + MCore::Mutex m_lock; /**< The multi-thread lock. */ + void* m_customData; /**< A pointer to custom data for this actor. This could be a pointer to your engine or game object for example. */ AZ::Entity* m_entity; /**< The entity to which the actor instance belongs to. */ - float mBoundsUpdateFrequency; /**< The bounds update frequency. Which is a time value in seconds. */ - float mBoundsUpdatePassedTime;/**< The time passed since the last bounds update. */ - float mMotionSamplingRate; /**< The motion sampling rate in seconds, where 0.1 would mean to update 10 times per second. A value of 0 or lower means to update every frame. */ - float mMotionSamplingTimer; /**< The time passed since the last time we sampled motions/anim graphs. */ - float mVisualizeScale; /**< Some visualization scale factor when rendering for example normals, to be at a nice size, relative to the character. */ - size_t mLODLevel; /**< The current LOD level, where 0 is the highest detail. */ + float m_boundsUpdateFrequency; /**< The bounds update frequency. Which is a time value in seconds. */ + float m_boundsUpdatePassedTime;/**< The time passed since the last bounds update. */ + float m_motionSamplingRate; /**< The motion sampling rate in seconds, where 0.1 would mean to update 10 times per second. A value of 0 or lower means to update every frame. */ + float m_motionSamplingTimer; /**< The time passed since the last time we sampled motions/anim graphs. */ + float m_visualizeScale; /**< Some visualization scale factor when rendering for example normals, to be at a nice size, relative to the character. */ + size_t m_lodLevel; /**< The current LOD level, where 0 is the highest detail. */ size_t m_requestedLODLevel; /**< Requested LOD level. The actual LOD level will be updated as soon as all transforms for the requested LOD level are ready. */ - uint32 mBoundsUpdateItemFreq; /**< The bounds update item counter step size. A value of 1 means every vertex/node, a value of 2 means every second vertex/node, etc. */ - uint32 mID; /**< The unique identification number for the actor instance. */ - uint32 mThreadIndex; /**< The thread index. This specifies the thread number this actor instance is being processed in. */ - EBoundsType mBoundsUpdateType; /**< The bounds update type (node based, mesh based or collision mesh based). */ + uint32 m_boundsUpdateItemFreq; /**< The bounds update item counter step size. A value of 1 means every vertex/node, a value of 2 means every second vertex/node, etc. */ + uint32 m_id; /**< The unique identification number for the actor instance. */ + uint32 m_threadIndex; /**< The thread index. This specifies the thread number this actor instance is being processed in. */ + EBoundsType m_boundsUpdateType; /**< The bounds update type (node based, mesh based or collision mesh based). */ float m_boundsExpandBy = 0.25f; /**< Expand bounding box by normalized percentage. (Default: 25% greater than the calculated bounding box) */ - uint8 mNumAttachmentRefs; /**< Specifies how many actor instances use this actor instance as attachment. */ - uint8 mBoolFlags; /**< Boolean flags. */ + uint8 m_numAttachmentRefs; /**< Specifies how many actor instances use this actor instance as attachment. */ + uint8 m_boolFlags; /**< Boolean flags. */ /** * Boolean masks, as replacement for having several bools as members. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/ActorManager.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/ActorManager.cpp index b96a4b4962..681efb6039 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/ActorManager.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/ActorManager.cpp @@ -25,15 +25,15 @@ namespace EMotionFX ActorManager::ActorManager() : BaseObject() { - mScheduler = nullptr; + m_scheduler = nullptr; // setup the default scheduler SetScheduler(MultiThreadScheduler::Create()); // reserve memory m_actors.reserve(512); - mActorInstances.reserve(1024); - mRootActorInstances.reserve(1024); + m_actorInstances.reserve(1024); + m_rootActorInstances.reserve(1024); } @@ -41,7 +41,7 @@ namespace EMotionFX ActorManager::~ActorManager() { // delete the scheduler - mScheduler->Destroy(); + m_scheduler->Destroy(); } @@ -57,8 +57,8 @@ namespace EMotionFX // destroy all actor instances while (GetNumActorInstances() > 0) { - MCORE_ASSERT(mActorInstances[0]->GetReferenceCount() == 1); - mActorInstances[0]->Destroy(); + MCORE_ASSERT(m_actorInstances[0]->GetReferenceCount() == 1); + m_actorInstances[0]->Destroy(); } UnregisterAllActorInstances(); @@ -75,11 +75,11 @@ namespace EMotionFX void ActorManager::UnregisterAllActorInstances() { LockActorInstances(); - mActorInstances.clear(); - mRootActorInstances.clear(); - if (mScheduler) + m_actorInstances.clear(); + m_rootActorInstances.clear(); + if (m_scheduler) { - mScheduler->Clear(); + m_scheduler->Clear(); } UnlockActorInstances(); } @@ -91,19 +91,19 @@ namespace EMotionFX LockActorInstances(); // delete the existing scheduler, if wanted - if (delExisting && mScheduler) + if (delExisting && m_scheduler) { - mScheduler->Destroy(); + m_scheduler->Destroy(); } // update the scheduler pointer - mScheduler = scheduler; + m_scheduler = scheduler; // adjust all visibility flags to false for all actor instances - const size_t numActorInstances = mActorInstances.size(); + const size_t numActorInstances = m_actorInstances.size(); for (size_t i = 0; i < numActorInstances; ++i) { - mActorInstances[i]->SetIsVisible(false); + m_actorInstances[i]->SetIsVisible(false); } UnlockActorInstances(); @@ -135,7 +135,7 @@ namespace EMotionFX { LockActorInstances(); - mActorInstances.emplace_back(actorInstance); + m_actorInstances.emplace_back(actorInstance); UpdateActorInstanceStatus(actorInstance, false); UnlockActorInstances(); @@ -209,7 +209,7 @@ namespace EMotionFX LockActorInstances(); // get the number of actor instances and iterate through them - const bool foundActor = AZStd::find(begin(mActorInstances), end(mActorInstances), actorInstance) != end(mActorInstances); + const bool foundActor = AZStd::find(begin(m_actorInstances), end(m_actorInstances), actorInstance) != end(m_actorInstances); UnlockActorInstances(); return foundActor; } @@ -218,19 +218,19 @@ namespace EMotionFX // find the given actor instance inside the actor manager and return its index size_t ActorManager::FindActorInstanceIndex(ActorInstance* actorInstance) const { - const auto foundActorInstance = AZStd::find(begin(mActorInstances), end(mActorInstances), actorInstance); - return foundActorInstance != end(mActorInstances) ? AZStd::distance(begin(mActorInstances), foundActorInstance) : InvalidIndex; + const auto foundActorInstance = AZStd::find(begin(m_actorInstances), end(m_actorInstances), actorInstance); + return foundActorInstance != end(m_actorInstances) ? AZStd::distance(begin(m_actorInstances), foundActorInstance) : InvalidIndex; } // find the actor instance by the identification number ActorInstance* ActorManager::FindActorInstanceByID(uint32 id) const { - const auto foundActorInstance = AZStd::find_if(begin(mActorInstances), end(mActorInstances), [id](const ActorInstance* actorInstance) + const auto foundActorInstance = AZStd::find_if(begin(m_actorInstances), end(m_actorInstances), [id](const ActorInstance* actorInstance) { return actorInstance->GetID() == id; }); - return foundActorInstance != end(mActorInstances) ? *foundActorInstance : nullptr; + return foundActorInstance != end(m_actorInstances) ? *foundActorInstance : nullptr; } @@ -259,7 +259,7 @@ namespace EMotionFX // unregister a given actor instance void ActorManager::UnregisterActorInstance(size_t nr) { - UnregisterActorInstance(mActorInstances[nr]); + UnregisterActorInstance(m_actorInstances[nr]); } @@ -284,7 +284,7 @@ namespace EMotionFX // execute the schedule // this makes all the callback OnUpdate calls etc - mScheduler->Execute(timePassedInSeconds); + m_scheduler->Execute(timePassedInSeconds); UnlockActorInstances(); UnlockActors(); @@ -318,19 +318,19 @@ namespace EMotionFX if (actorInstance->GetAttachedTo() == nullptr) { // make sure it's in the root list - if (AZStd::find(begin(mRootActorInstances), end(mRootActorInstances), actorInstance) == end(mRootActorInstances)) + if (AZStd::find(begin(m_rootActorInstances), end(m_rootActorInstances), actorInstance) == end(m_rootActorInstances)) { - mRootActorInstances.emplace_back(actorInstance); + m_rootActorInstances.emplace_back(actorInstance); } } else // no root actor instance { // remove it from the root list - if (const auto it = AZStd::find(begin(mRootActorInstances), end(mRootActorInstances), actorInstance); it != end(mRootActorInstances)) + if (const auto it = AZStd::find(begin(m_rootActorInstances), end(m_rootActorInstances), actorInstance); it != end(m_rootActorInstances)) { - mRootActorInstances.erase(it); + m_rootActorInstances.erase(it); } - mScheduler->RecursiveRemoveActorInstance(actorInstance); + m_scheduler->RecursiveRemoveActorInstance(actorInstance); } if (lock) @@ -346,19 +346,19 @@ namespace EMotionFX LockActorInstances(); // remove the actor instance from the list - if (const auto it = AZStd::find(begin(mActorInstances), end(mActorInstances), instance); it != end(mActorInstances)) + if (const auto it = AZStd::find(begin(m_actorInstances), end(m_actorInstances), instance); it != end(m_actorInstances)) { - mActorInstances.erase(it); + m_actorInstances.erase(it); } // remove it from the list of roots, if it is in there - if (const auto it = AZStd::find(begin(mRootActorInstances), end(mRootActorInstances), instance); it != end(mRootActorInstances)) + if (const auto it = AZStd::find(begin(m_rootActorInstances), end(m_rootActorInstances), instance); it != end(m_rootActorInstances)) { - mRootActorInstances.erase(it); + m_rootActorInstances.erase(it); } // remove it from the schedule - mScheduler->RemoveActorInstance(instance); + m_scheduler->RemoveActorInstance(instance); UnlockActorInstances(); } @@ -366,25 +366,25 @@ namespace EMotionFX void ActorManager::LockActorInstances() { - mActorInstanceLock.Lock(); + m_actorInstanceLock.Lock(); } void ActorManager::UnlockActorInstances() { - mActorInstanceLock.Unlock(); + m_actorInstanceLock.Unlock(); } void ActorManager::LockActors() { - mActorLock.Lock(); + m_actorLock.Lock(); } void ActorManager::UnlockActors() { - mActorLock.Unlock(); + m_actorLock.Unlock(); } @@ -396,12 +396,12 @@ namespace EMotionFX const AZStd::vector& ActorManager::GetActorInstanceArray() const { - return mActorInstances; + return m_actorInstances; } ActorUpdateScheduler* ActorManager::GetScheduler() const { - return mScheduler; + return m_scheduler; } } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/ActorManager.h b/Gems/EMotionFX/Code/EMotionFX/Source/ActorManager.h index a7f12111ce..ff78250141 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/ActorManager.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/ActorManager.h @@ -124,14 +124,14 @@ namespace EMotionFX * Get the number of actor instances that currently are registered. * @result The number of registered actor instances. */ - MCORE_INLINE size_t GetNumActorInstances() const { return mActorInstances.size(); } + MCORE_INLINE size_t GetNumActorInstances() const { return m_actorInstances.size(); } /** * Get a given registered actor instance. * @param nr The actor instance number, which must be in range of [0..GetNumActorInstances()-1]. * @result A pointer to the actor instance. */ - MCORE_INLINE ActorInstance* GetActorInstance(size_t nr) const { return mActorInstances[nr]; } + MCORE_INLINE ActorInstance* GetActorInstance(size_t nr) const { return m_actorInstances[nr]; } /** * Get the array of actor instances. @@ -201,7 +201,7 @@ namespace EMotionFX * horse is the root attachment instance. * @result Returns the number of root actor instances. */ - MCORE_INLINE size_t GetNumRootActorInstances() const { return mRootActorInstances.size(); } + MCORE_INLINE size_t GetNumRootActorInstances() const { return m_rootActorInstances.size(); } /** * Get a given root actor instance. @@ -211,7 +211,7 @@ namespace EMotionFX * @param nr The root actor instance number, which must be in range of [0..GetNumRootActorInstances()-1]. * @result A pointer to the actor instance that is a root. */ - MCORE_INLINE ActorInstance* GetRootActorInstance(size_t nr) const { return mRootActorInstances[nr]; } + MCORE_INLINE ActorInstance* GetRootActorInstance(size_t nr) const { return m_rootActorInstances[nr]; } /** * Get the currently used actor update scheduler. @@ -255,12 +255,12 @@ namespace EMotionFX void UnlockActors(); private: - AZStd::vector mActorInstances; /**< The registered actor instances. */ + AZStd::vector m_actorInstances; /**< The registered actor instances. */ AZStd::vector> m_actors; /**< The registered actors. */ - AZStd::vector mRootActorInstances; /**< Root actor instances (roots of all attachment chains). */ - ActorUpdateScheduler* mScheduler; /**< The update scheduler to use. */ - MCore::MutexRecursive mActorLock; /**< The multithread lock for touching the actors array. */ - MCore::MutexRecursive mActorInstanceLock; /**< The multithread lock for touching the actor instances array. */ + AZStd::vector m_rootActorInstances; /**< Root actor instances (roots of all attachment chains). */ + ActorUpdateScheduler* m_scheduler; /**< The update scheduler to use. */ + MCore::MutexRecursive m_actorLock; /**< The multithread lock for touching the actors array. */ + MCore::MutexRecursive m_actorInstanceLock; /**< The multithread lock for touching the actor instances array. */ /** * The constructor, which initializes using the multi processor scheduler. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/ActorUpdateScheduler.h b/Gems/EMotionFX/Code/EMotionFX/Source/ActorUpdateScheduler.h index 18fd7ff233..9ca73e423f 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/ActorUpdateScheduler.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/ActorUpdateScheduler.h @@ -80,14 +80,14 @@ namespace EMotionFX */ virtual size_t RemoveActorInstance(ActorInstance* actorInstance, size_t startStep = 0) = 0; - size_t GetNumUpdatedActorInstances() const { return mNumUpdated.GetValue(); } - size_t GetNumVisibleActorInstances() const { return mNumVisible.GetValue(); } - size_t GetNumSampledActorInstances() const { return mNumSampled.GetValue(); } + size_t GetNumUpdatedActorInstances() const { return m_numUpdated.GetValue(); } + size_t GetNumVisibleActorInstances() const { return m_numVisible.GetValue(); } + size_t GetNumSampledActorInstances() const { return m_numSampled.GetValue(); } protected: - MCore::AtomicSizeT mNumUpdated; - MCore::AtomicSizeT mNumVisible; - MCore::AtomicSizeT mNumSampled; + MCore::AtomicSizeT m_numUpdated; + MCore::AtomicSizeT m_numVisible; + MCore::AtomicSizeT m_numSampled; /** * The constructor. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraph.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraph.cpp index 38fb6380e9..a9cfbc4379 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraph.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraph.cpp @@ -35,21 +35,21 @@ namespace EMotionFX AZ_CLASS_ALLOCATOR_IMPL(AnimGraph, AnimGraphAllocator, 0) AnimGraph::AnimGraph() - : mGameControllerSettings(aznew AnimGraphGameControllerSettings()) + : m_gameControllerSettings(aznew AnimGraphGameControllerSettings()) { - mID = aznumeric_caster(MCore::GetIDGenerator().GenerateID()); - mDirtyFlag = false; - mAutoUnregister = true; - mRetarget = false; - mRootStateMachine = nullptr; + m_id = aznumeric_caster(MCore::GetIDGenerator().GenerateID()); + m_dirtyFlag = false; + m_autoUnregister = true; + m_retarget = false; + m_rootStateMachine = nullptr; #if defined(EMFX_DEVELOPMENT_BUILD) - mIsOwnedByRuntime = false; + m_isOwnedByRuntime = false; m_isOwnedByAsset = false; #endif // EMFX_DEVELOPMENT_BUILD // reserve some memory - mNodes.reserve(1024); + m_nodes.reserve(1024); // automatically register the anim graph GetAnimGraphManager().AddAnimGraph(this); @@ -65,35 +65,35 @@ namespace EMotionFX RemoveAllNodeGroups(); - if (mRootStateMachine) + if (m_rootStateMachine) { - delete mRootStateMachine; + delete m_rootStateMachine; } // automatically unregister the anim graph - if (mAutoUnregister) + if (m_autoUnregister) { GetAnimGraphManager().RemoveAnimGraph(this, false); } - delete mGameControllerSettings; + delete m_gameControllerSettings; } void AnimGraph::RecursiveReinit() { - if (!mRootStateMachine) + if (!m_rootStateMachine) { return; } - mRootStateMachine->RecursiveReinit(); + m_rootStateMachine->RecursiveReinit(); } bool AnimGraph::InitAfterLoading() { - if (!mRootStateMachine) + if (!m_rootStateMachine) { return false; } @@ -106,7 +106,7 @@ namespace EMotionFX m_valueParameterIndexByName.emplace(m_valueParameters[i]->GetName(), i); } - return mRootStateMachine->InitAfterLoading(this); + return m_rootStateMachine->InitAfterLoading(this); } void AnimGraph::RecursiveInvalidateUniqueDatas() @@ -307,25 +307,25 @@ namespace EMotionFX // recursively find a given node AnimGraphNode* AnimGraph::RecursiveFindNodeByName(const char* nodeName) const { - return mRootStateMachine->RecursiveFindNodeByName(nodeName); + return m_rootStateMachine->RecursiveFindNodeByName(nodeName); } bool AnimGraph::IsNodeNameUnique(const AZStd::string& newNameCandidate, const AnimGraphNode* forNode) const { - return mRootStateMachine->RecursiveIsNodeNameUnique(newNameCandidate, forNode); + return m_rootStateMachine->RecursiveIsNodeNameUnique(newNameCandidate, forNode); } AnimGraphNode* AnimGraph::RecursiveFindNodeById(AnimGraphNodeId nodeId) const { - return mRootStateMachine->RecursiveFindNodeById(nodeId); + return m_rootStateMachine->RecursiveFindNodeById(nodeId); } AnimGraphStateTransition* AnimGraph::RecursiveFindTransitionById(AnimGraphConnectionId transitionId) const { - for (AnimGraphObject* object : mObjects) + for (AnimGraphObject* object : m_objects) { if (azrtti_typeid(object) == azrtti_typeid()) { @@ -365,7 +365,7 @@ namespace EMotionFX size_t AnimGraph::RecursiveCalcNumNodes() const { - return mRootStateMachine->RecursiveCalcNumNodes(); + return m_rootStateMachine->RecursiveCalcNumNodes(); } @@ -382,7 +382,7 @@ namespace EMotionFX void AnimGraph::RecursiveCalcStatistics(Statistics& outStatistics) const { - RecursiveCalcStatistics(outStatistics, mRootStateMachine); + RecursiveCalcStatistics(outStatistics, m_rootStateMachine); } @@ -425,35 +425,35 @@ namespace EMotionFX // recursively calculate the number of node connections size_t AnimGraph::RecursiveCalcNumNodeConnections() const { - return mRootStateMachine->RecursiveCalcNumNodeConnections(); + return m_rootStateMachine->RecursiveCalcNumNodeConnections(); } // adjust the dirty flag void AnimGraph::SetDirtyFlag(bool dirty) { - mDirtyFlag = dirty; + m_dirtyFlag = dirty; } // adjust the auto unregistering from the anim graph manager on delete void AnimGraph::SetAutoUnregister(bool enabled) { - mAutoUnregister = enabled; + m_autoUnregister = enabled; } // do we auto unregister from the anim graph manager on delete? bool AnimGraph::GetAutoUnregister() const { - return mAutoUnregister; + return m_autoUnregister; } void AnimGraph::SetIsOwnedByRuntime(bool isOwnedByRuntime) { #if defined(EMFX_DEVELOPMENT_BUILD) - mIsOwnedByRuntime = isOwnedByRuntime; + m_isOwnedByRuntime = isOwnedByRuntime; #else AZ_UNUSED(isOwnedByRuntime); #endif @@ -463,7 +463,7 @@ namespace EMotionFX bool AnimGraph::GetIsOwnedByRuntime() const { #if defined(EMFX_DEVELOPMENT_BUILD) - return mIsOwnedByRuntime; + return m_isOwnedByRuntime; #else return true; #endif @@ -494,14 +494,14 @@ namespace EMotionFX // get a pointer to the given node group AnimGraphNodeGroup* AnimGraph::GetNodeGroup(size_t index) const { - return mNodeGroups[index]; + return m_nodeGroups[index]; } // find the node group by name AnimGraphNodeGroup* AnimGraph::FindNodeGroupByName(const char* groupName) const { - for (AnimGraphNodeGroup* nodeGroup : mNodeGroups) + for (AnimGraphNodeGroup* nodeGroup : m_nodeGroups) { // Compare the node names and return a pointer in case they are equal. if (nodeGroup->GetNameString() == groupName) @@ -517,18 +517,18 @@ namespace EMotionFX // find the node group index by name size_t AnimGraph::FindNodeGroupIndexByName(const char* groupName) const { - const auto foundNodeGroup = AZStd::find_if(begin(mNodeGroups), end(mNodeGroups), [groupName](const AnimGraphNodeGroup* nodeGroup) + const auto foundNodeGroup = AZStd::find_if(begin(m_nodeGroups), end(m_nodeGroups), [groupName](const AnimGraphNodeGroup* nodeGroup) { return nodeGroup->GetNameString() == groupName; }); - return foundNodeGroup != end(mNodeGroups) ? AZStd::distance(begin(mNodeGroups), foundNodeGroup) : InvalidIndex; + return foundNodeGroup != end(m_nodeGroups) ? AZStd::distance(begin(m_nodeGroups), foundNodeGroup) : InvalidIndex; } // add the given node group to the anim graph void AnimGraph::AddNodeGroup(AnimGraphNodeGroup* nodeGroup) { - mNodeGroups.push_back(nodeGroup); + m_nodeGroups.push_back(nodeGroup); } @@ -538,11 +538,11 @@ namespace EMotionFX // destroy the object if (delFromMem) { - delete mNodeGroups[index]; + delete m_nodeGroups[index]; } // remove the node group from the array - mNodeGroups.erase(mNodeGroups.begin() + index); + m_nodeGroups.erase(m_nodeGroups.begin() + index); } @@ -552,28 +552,28 @@ namespace EMotionFX // destroy the node groups if (delFromMem) { - for (AnimGraphNodeGroup* nodeGroup : mNodeGroups) + for (AnimGraphNodeGroup* nodeGroup : m_nodeGroups) { delete nodeGroup; } } // remove all node groups - mNodeGroups.clear(); + m_nodeGroups.clear(); } // get the number of node groups size_t AnimGraph::GetNumNodeGroups() const { - return mNodeGroups.size(); + return m_nodeGroups.size(); } // find the node group in which the given anim graph node is in and return a pointer to it AnimGraphNodeGroup* AnimGraph::FindNodeGroupForNode(AnimGraphNode* animGraphNode) const { - for (AnimGraphNodeGroup* nodeGroup : mNodeGroups) + for (AnimGraphNodeGroup* nodeGroup : m_nodeGroups) { // check if the given node is part of the currently iterated node group if (nodeGroup->Contains(animGraphNode->GetId())) @@ -618,24 +618,24 @@ namespace EMotionFX void AnimGraph::RecursiveCollectNodesOfType(const AZ::TypeId& nodeType, AZStd::vector* outNodes) const { - mRootStateMachine->RecursiveCollectNodesOfType(nodeType, outNodes); + m_rootStateMachine->RecursiveCollectNodesOfType(nodeType, outNodes); } void AnimGraph::RecursiveCollectTransitionConditionsOfType(const AZ::TypeId& conditionType, AZStd::vector* outConditions) const { - mRootStateMachine->RecursiveCollectTransitionConditionsOfType(conditionType, outConditions); + m_rootStateMachine->RecursiveCollectTransitionConditionsOfType(conditionType, outConditions); } void AnimGraph::RecursiveCollectObjectsOfType(const AZ::TypeId& objectType, AZStd::vector& outObjects) { - mRootStateMachine->RecursiveCollectObjectsOfType(objectType, outObjects); + m_rootStateMachine->RecursiveCollectObjectsOfType(objectType, outObjects); } void AnimGraph::RecursiveCollectObjectsAffectedBy(AnimGraph* animGraph, AZStd::vector& outObjects) { - mRootStateMachine->RecursiveCollectObjectsAffectedBy(animGraph, outObjects); + m_rootStateMachine->RecursiveCollectObjectsAffectedBy(animGraph, outObjects); } GroupParameter* AnimGraph::FindGroupParameterByName(const AZStd::string& groupName) const @@ -684,7 +684,7 @@ namespace EMotionFX // delete all unique datas for a given object void AnimGraph::RemoveAllObjectData(AnimGraphObject* object, bool delFromMem) { - MCore::LockGuard lock(mLock); + MCore::LockGuard lock(m_lock); for (AnimGraphInstance* animGraphInstance : m_animGraphInstances) { @@ -696,11 +696,11 @@ namespace EMotionFX // set the root state machine void AnimGraph::SetRootStateMachine(AnimGraphStateMachine* stateMachine) { - mRootStateMachine = stateMachine; - if (mRootStateMachine) + m_rootStateMachine = stateMachine; + if (m_rootStateMachine) { // make sure the name is always the same for the root state machine - mRootStateMachine->SetName("Root"); + m_rootStateMachine->SetName("Root"); } } @@ -708,18 +708,18 @@ namespace EMotionFX // add an object void AnimGraph::AddObject(AnimGraphObject* object) { - MCore::LockGuard lock(mLock); + MCore::LockGuard lock(m_lock); // assign the index and add it to the objects array - object->SetObjectIndex(mObjects.size()); - mObjects.push_back(object); + object->SetObjectIndex(m_objects.size()); + m_objects.push_back(object); // if it's a node, add it to the nodes array as well if (azrtti_istypeof(object)) { AnimGraphNode* node = static_cast(object); - node->SetNodeIndex(mNodes.size()); - mNodes.emplace_back(node); + node->SetNodeIndex(m_nodes.size()); + m_nodes.emplace_back(node); } // create a unique data for this added object in the animgraph instances as well @@ -733,7 +733,7 @@ namespace EMotionFX // remove an object void AnimGraph::RemoveObject(AnimGraphObject* object) { - MCore::LockGuard lock(mLock); + MCore::LockGuard lock(m_lock); const size_t objectIndex = object->GetObjectIndex(); @@ -741,16 +741,16 @@ namespace EMotionFX object->RemoveInternalAttributesForAllInstances(); // decrease the indices of all objects that have an index after this node - const size_t numObjects = mObjects.size(); + const size_t numObjects = m_objects.size(); for (size_t i = objectIndex + 1; i < numObjects; ++i) { - AnimGraphObject* curObject = mObjects[i]; + AnimGraphObject* curObject = m_objects[i]; MCORE_ASSERT(i == curObject->GetObjectIndex()); curObject->SetObjectIndex(i - 1); } // remove the object from the array - mObjects.erase(mObjects.begin() + objectIndex); + m_objects.erase(m_objects.begin() + objectIndex); // remove it from the nodes array if it is a node if (azrtti_istypeof(object)) @@ -758,16 +758,16 @@ namespace EMotionFX AnimGraphNode* node = static_cast(object); const size_t nodeIndex = node->GetNodeIndex(); - const size_t numNodes = mNodes.size(); + const size_t numNodes = m_nodes.size(); for (size_t i = nodeIndex + 1; i < numNodes; ++i) { - AnimGraphNode* curNode = mNodes[i]; + AnimGraphNode* curNode = m_nodes[i]; MCORE_ASSERT(i == curNode->GetNodeIndex()); curNode->SetNodeIndex(i - 1); } // remove the object from the array - mNodes.erase(AZStd::next(begin(mNodes), nodeIndex)); + m_nodes.erase(AZStd::next(begin(m_nodes), nodeIndex)); } } @@ -775,21 +775,21 @@ namespace EMotionFX // reserve space for a given amount of objects void AnimGraph::ReserveNumObjects(size_t numObjects) { - mObjects.reserve(numObjects); + m_objects.reserve(numObjects); } // reserve space for a given amount of nodes void AnimGraph::ReserveNumNodes(size_t numNodes) { - mNodes.reserve(numNodes); + m_nodes.reserve(numNodes); } // Calculate number of motion nodes in the graph size_t AnimGraph::CalcNumMotionNodes() const { - return AZStd::accumulate(begin(mNodes), end(mNodes), size_t{0}, [](size_t total, const AnimGraphNode* node) + return AZStd::accumulate(begin(m_nodes), end(m_nodes), size_t{0}, [](size_t total, const AnimGraphNode* node) { return total + azrtti_istypeof(node); }); @@ -806,7 +806,7 @@ namespace EMotionFX // register an animgraph instance void AnimGraph::AddAnimGraphInstance(AnimGraphInstance* animGraphInstance) { - MCore::LockGuard lock(mLock); + MCore::LockGuard lock(m_lock); m_animGraphInstances.emplace_back(animGraphInstance); } @@ -814,7 +814,7 @@ namespace EMotionFX // remove an animgraph instance void AnimGraph::RemoveAnimGraphInstance(AnimGraphInstance* animGraphInstance) { - MCore::LockGuard lock(mLock); + MCore::LockGuard lock(m_lock); m_animGraphInstances.erase(AZStd::remove(m_animGraphInstances.begin(), m_animGraphInstances.end(), animGraphInstance)); } @@ -822,7 +822,7 @@ namespace EMotionFX // decrease internal attribute indices by one, for values higher than the given parameter void AnimGraph::DecreaseInternalAttributeIndices(size_t decreaseEverythingHigherThan) { - for (AnimGraphObject* object : mObjects) + for (AnimGraphObject* object : m_objects) { object->DecreaseInternalAttributeIndices(decreaseEverythingHigherThan); } @@ -831,72 +831,72 @@ namespace EMotionFX const char* AnimGraph::GetFileName() const { - return mFileName.c_str(); + return m_fileName.c_str(); } const AZStd::string& AnimGraph::GetFileNameString() const { - return mFileName; + return m_fileName; } void AnimGraph::SetFileName(const char* fileName) { - mFileName = fileName; + m_fileName = fileName; } AnimGraphStateMachine* AnimGraph::GetRootStateMachine() const { - return mRootStateMachine; + return m_rootStateMachine; } uint32 AnimGraph::GetID() const { - return mID; + return m_id; } void AnimGraph::SetID(uint32 id) { - mID = id; + m_id = id; } bool AnimGraph::GetDirtyFlag() const { - return mDirtyFlag; + return m_dirtyFlag; } AnimGraphGameControllerSettings& AnimGraph::GetGameControllerSettings() { - return *mGameControllerSettings; + return *m_gameControllerSettings; } bool AnimGraph::GetRetargetingEnabled() const { - return mRetarget; + return m_retarget; } void AnimGraph::SetRetargetingEnabled(bool enabled) { - mRetarget = enabled; + m_retarget = enabled; } void AnimGraph::Lock() { - mLock.Lock(); + m_lock.Lock(); } void AnimGraph::Unlock() { - mLock.Unlock(); + m_lock.Unlock(); } @@ -904,7 +904,7 @@ namespace EMotionFX { for (AnimGraphInstance* animGraphInstance : m_animGraphInstances) { - animGraphInstance->SetRetargetingEnabled(mRetarget); + animGraphInstance->SetRetargetingEnabled(m_retarget); } } @@ -920,10 +920,10 @@ namespace EMotionFX serializeContext->Class() ->Version(1) ->Field("rootGroupParameter", &AnimGraph::m_rootParameter) - ->Field("rootStateMachine", &AnimGraph::mRootStateMachine) - ->Field("nodeGroups", &AnimGraph::mNodeGroups) - ->Field("gameControllerSettings", &AnimGraph::mGameControllerSettings) - ->Field("retarget", &AnimGraph::mRetarget) + ->Field("rootStateMachine", &AnimGraph::m_rootStateMachine) + ->Field("nodeGroups", &AnimGraph::m_nodeGroups) + ->Field("gameControllerSettings", &AnimGraph::m_gameControllerSettings) + ->Field("retarget", &AnimGraph::m_retarget) ; @@ -937,7 +937,7 @@ namespace EMotionFX ->ClassElement(AZ::Edit::ClassElements::EditorData, "") ->Attribute(AZ::Edit::Attributes::AutoExpand, "") ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly) - ->DataElement(AZ::Edit::UIHandlers::Default, &AnimGraph::mRetarget, "Retarget", "") + ->DataElement(AZ::Edit::UIHandlers::Default, &AnimGraph::m_retarget, "Retarget", "") ->Attribute(AZ::Edit::Attributes::ChangeNotify, &AnimGraph::OnRetargetingEnabledChanged) ; } @@ -1016,7 +1016,7 @@ namespace EMotionFX void AnimGraph::RemoveInvalidConnections(bool logWarnings) { // Iterate over all nodes - for (AnimGraphNode* node : mNodes) + for (AnimGraphNode* node : m_nodes) { for (size_t c = 0; c < node->GetNumConnections();) { diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraph.h b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraph.h index a356b031aa..2a498f9f81 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraph.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraph.h @@ -377,12 +377,12 @@ namespace EMotionFX void AddObject(AnimGraphObject* object); // registers the object in the array and modifies the object's object index value void RemoveObject(AnimGraphObject* object); // doesn't actually remove it from memory, just removes it from the list - size_t GetNumObjects() const { return mObjects.size(); } - AnimGraphObject* GetObject(size_t index) const { return mObjects[index]; } + size_t GetNumObjects() const { return m_objects.size(); } + AnimGraphObject* GetObject(size_t index) const { return m_objects[index]; } void ReserveNumObjects(size_t numObjects); - size_t GetNumNodes() const { return mNodes.size(); } - AnimGraphNode* GetNode(size_t index) const { return mNodes[index]; } + size_t GetNumNodes() const { return m_nodes.size(); } + AnimGraphNode* GetNode(size_t index) const { return m_nodes[index]; } void ReserveNumNodes(size_t numNodes); size_t CalcNumMotionNodes() const; @@ -415,21 +415,21 @@ namespace EMotionFX GroupParameter m_rootParameter; /**< root group parameter. */ ValueParameterVector m_valueParameters; /**< Cached version of all parameters with values. */ AZStd::unordered_map m_valueParameterIndexByName; /**< Cached version of parameter index by name to accelerate lookups. */ - AZStd::vector mNodeGroups; - AZStd::vector mObjects; - AZStd::vector mNodes; + AZStd::vector m_nodeGroups; + AZStd::vector m_objects; + AZStd::vector m_nodes; AZStd::vector m_animGraphInstances; - AZStd::string mFileName; - AnimGraphStateMachine* mRootStateMachine; - AnimGraphGameControllerSettings* mGameControllerSettings; - MCore::Mutex mLock; - uint32 mID; /**< The unique identification number for this anim graph. */ - bool mAutoUnregister; /**< Specifies whether we will automatically unregister this anim graph set from this anim graph manager or not, when deleting this object. */ - bool mRetarget; /**< Is retargeting enabled on default? */ - bool mDirtyFlag; /**< The dirty flag which indicates whether the user has made changes to this anim graph since the last file save operation. */ + AZStd::string m_fileName; + AnimGraphStateMachine* m_rootStateMachine; + AnimGraphGameControllerSettings* m_gameControllerSettings; + MCore::Mutex m_lock; + uint32 m_id; /**< The unique identification number for this anim graph. */ + bool m_autoUnregister; /**< Specifies whether we will automatically unregister this anim graph set from this anim graph manager or not, when deleting this object. */ + bool m_retarget; /**< Is retargeting enabled on default? */ + bool m_dirtyFlag; /**< The dirty flag which indicates whether the user has made changes to this anim graph since the last file save operation. */ #if defined(EMFX_DEVELOPMENT_BUILD) - bool mIsOwnedByRuntime; /**< Set if the anim graph is used/owned by the engine runtime. */ + bool m_isOwnedByRuntime; /**< Set if the anim graph is used/owned by the engine runtime. */ bool m_isOwnedByAsset; /**< Set if the anim graph is used/owned by an asset. */ #endif // EMFX_DEVELOPMENT_BUILD }; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphAttributeTypes.h b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphAttributeTypes.h index e0f6712145..beb3cd7446 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphAttributeTypes.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphAttributeTypes.h @@ -49,12 +49,12 @@ namespace EMotionFX static AttributePose* Create(); static AttributePose* Create(AnimGraphPose* pose); - void SetValue(AnimGraphPose* value) { mValue = value; } - AnimGraphPose* GetValue() const { return mValue; } - AnimGraphPose* GetValue() { return mValue; } + void SetValue(AnimGraphPose* value) { m_value = value; } + AnimGraphPose* GetValue() const { return m_value; } + AnimGraphPose* GetValue() { return m_value; } // overloaded from the attribute base class - MCore::Attribute* Clone() const override { return Create(mValue); } + MCore::Attribute* Clone() const override { return Create(m_value); } const char* GetTypeString() const override { return "Pose"; } bool InitFrom(const MCore::Attribute* other) override { @@ -63,7 +63,7 @@ namespace EMotionFX return false; } const AttributePose* pose = static_cast(other); - mValue = pose->GetValue(); + m_value = pose->GetValue(); return true; } bool InitFromString(const AZStd::string& valueString) override { MCORE_UNUSED(valueString); return false; } // unsupported @@ -72,12 +72,12 @@ namespace EMotionFX AZ::u32 GetDefaultInterfaceType() const override { return MCore::ATTRIBUTE_INTERFACETYPE_DEFAULT; } private: - AnimGraphPose* mValue; + AnimGraphPose* m_value; AttributePose() - : MCore::Attribute(TYPE_ID) { mValue = nullptr; } + : MCore::Attribute(TYPE_ID) { m_value = nullptr; } AttributePose(AnimGraphPose* pose) - : MCore::Attribute(TYPE_ID) { mValue = pose; } + : MCore::Attribute(TYPE_ID) { m_value = pose; } ~AttributePose() {} }; @@ -97,12 +97,12 @@ namespace EMotionFX static AttributeMotionInstance* Create(); static AttributeMotionInstance* Create(MotionInstance* motionInstance); - void SetValue(MotionInstance* value) { mValue = value; } - MotionInstance* GetValue() const { return mValue; } - MotionInstance* GetValue() { return mValue; } + void SetValue(MotionInstance* value) { m_value = value; } + MotionInstance* GetValue() const { return m_value; } + MotionInstance* GetValue() { return m_value; } // overloaded from the attribute base class - MCore::Attribute* Clone() const override { return Create(mValue); } + MCore::Attribute* Clone() const override { return Create(m_value); } const char* GetTypeString() const override { return "MotionInstance"; } bool InitFrom(const MCore::Attribute* other) override { @@ -111,7 +111,7 @@ namespace EMotionFX return false; } const AttributeMotionInstance* pose = static_cast(other); - mValue = pose->GetValue(); + m_value = pose->GetValue(); return true; } bool InitFromString(const AZStd::string& valueString) override { MCORE_UNUSED(valueString); return false; } // unsupported @@ -120,12 +120,12 @@ namespace EMotionFX AZ::u32 GetDefaultInterfaceType() const override { return MCore::ATTRIBUTE_INTERFACETYPE_DEFAULT; } private: - MotionInstance* mValue; + MotionInstance* m_value; AttributeMotionInstance() - : MCore::Attribute(TYPE_ID) { mValue = nullptr; } + : MCore::Attribute(TYPE_ID) { m_value = nullptr; } AttributeMotionInstance(MotionInstance* motionInstance) - : MCore::Attribute(TYPE_ID) { mValue = motionInstance; } + : MCore::Attribute(TYPE_ID) { m_value = motionInstance; } ~AttributeMotionInstance() {} }; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphBindPoseNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphBindPoseNode.cpp index 1845336df9..e84ffac23a 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphBindPoseNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphBindPoseNode.cpp @@ -72,7 +72,7 @@ namespace EMotionFX // visualize it if (GetEMotionFX().GetIsInEditorMode() && GetCanVisualize(animGraphInstance)) { - animGraphInstance->GetActorInstance()->DrawSkeleton(outputPose->GetPose(), mVisualizeColor); + animGraphInstance->GetActorInstance()->DrawSkeleton(outputPose->GetPose(), m_visualizeColor); } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphEntryNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphEntryNode.cpp index 45fc010a16..d581263e55 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphEntryNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphEntryNode.cpp @@ -111,7 +111,7 @@ namespace EMotionFX if (outputPose && GetEMotionFX().GetIsInEditorMode() && GetCanVisualize(animGraphInstance)) { - animGraphInstance->GetActorInstance()->DrawSkeleton(outputPose->GetPose(), mVisualizeColor); + animGraphInstance->GetActorInstance()->DrawSkeleton(outputPose->GetPose(), m_visualizeColor); } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphEventBuffer.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphEventBuffer.cpp index 0403e277b6..7bea215a71 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphEventBuffer.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphEventBuffer.cpp @@ -24,7 +24,7 @@ namespace EMotionFX { for (EventInfo& event : m_events) { - event.mEmitter = emitterNode; + event.m_emitter = emitterNode; } } @@ -32,9 +32,9 @@ namespace EMotionFX { for (EventInfo& curEvent : m_events) { - AnimGraphNodeData* emitterUniqueData = curEvent.mEmitter->FindOrCreateUniqueNodeData(animGraphInstance); - curEvent.mGlobalWeight = emitterUniqueData->GetGlobalWeight(); - curEvent.mLocalWeight = emitterUniqueData->GetLocalWeight(); + AnimGraphNodeData* emitterUniqueData = curEvent.m_emitter->FindOrCreateUniqueNodeData(animGraphInstance); + curEvent.m_globalWeight = emitterUniqueData->GetGlobalWeight(); + curEvent.m_localWeight = emitterUniqueData->GetLocalWeight(); } } @@ -45,7 +45,7 @@ namespace EMotionFX { AZStd::string eventDataString; - for (const EventDataPtr& eventData : event.mEvent->GetEventDatas()) + for (const EventDataPtr& eventData : event.m_event->GetEventDatas()) { if (eventData) { @@ -57,11 +57,11 @@ namespace EMotionFX } MCore::LogInfo("Event: (time=%f) (eventData=%s) (emitter=%s) (locWeight=%.4f globWeight=%.4f)", - event.mTimeValue, + event.m_timeValue, eventDataString.size() ? eventDataString.c_str() : "", - event.mEmitter->GetName(), - event.mLocalWeight, - event.mGlobalWeight); + event.m_emitter->GetName(), + event.m_localWeight, + event.m_globalWeight); } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphExitNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphExitNode.cpp index 14684603c4..f4af1df28f 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphExitNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphExitNode.cpp @@ -30,7 +30,7 @@ namespace EMotionFX void AnimGraphExitNode::UniqueData::Update() { - AnimGraphExitNode* exitNode = azdynamic_cast(mObject); + AnimGraphExitNode* exitNode = azdynamic_cast(m_object); AZ_Assert(exitNode, "Unique data linked to incorrect node type."); if (m_previousNode && exitNode->FindChildNodeIndex(m_previousNode) == InvalidIndex32) @@ -129,7 +129,7 @@ namespace EMotionFX // visualize it if (GetEMotionFX().GetIsInEditorMode() && GetCanVisualize(animGraphInstance)) { - actorInstance->DrawSkeleton(outputPose->GetPose(), mVisualizeColor); + actorInstance->DrawSkeleton(outputPose->GetPose(), m_visualizeColor); } return; @@ -157,7 +157,7 @@ namespace EMotionFX // visualize it if (GetEMotionFX().GetIsInEditorMode() && GetCanVisualize(animGraphInstance)) { - actorInstance->DrawSkeleton(outputPose->GetPose(), mVisualizeColor); + actorInstance->DrawSkeleton(outputPose->GetPose(), m_visualizeColor); } } @@ -207,7 +207,7 @@ namespace EMotionFX void AnimGraphExitNode::RecursiveResetFlags(AnimGraphInstance* animGraphInstance, uint32 flagsToDisable) { UniqueData* uniqueData = static_cast(animGraphInstance->FindOrCreateUniqueObjectData(this)); - animGraphInstance->DisableObjectFlags(mObjectIndex, flagsToDisable); + animGraphInstance->DisableObjectFlags(m_objectIndex, flagsToDisable); // forward it to the node we came from if (uniqueData->m_previousNode && uniqueData->m_previousNode != this) diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphGameControllerSettings.h b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphGameControllerSettings.h index d36a448be4..c4e123c0c5 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphGameControllerSettings.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphGameControllerSettings.h @@ -96,24 +96,24 @@ namespace EMotionFX /** * Check if the parameter with the given name is being controlled by the gamepad. - * This assumes that the mString member from the ButtonInfo contains the parameter name. - * @param[in] stringName The name to compare against the mString member of the button infos. + * This assumes that the m_string member from the ButtonInfo contains the parameter name. + * @param[in] stringName The name to compare against the m_string member of the button infos. * @result True in case a button info with the given string name doesn't have BUTTONMODE_NONE assigned, false in the other case. */ bool CheckIfIsParameterButtonControlled(const char* stringName); /** * Check if any of the button infos that are linked to the given string name is enabled. - * This assumes that the mString member from the ButtonInfo contains the parameter name. - * @param[in] stringName The name to compare against the mString member of the button infos. + * This assumes that the m_string member from the ButtonInfo contains the parameter name. + * @param[in] stringName The name to compare against the m_string member of the button infos. * @result True in case any of the button infos with the given string name is enabled. */ bool CheckIfIsButtonEnabled(const char* stringName); /** * Set all button infos that are linked to the given string name to the enabled flag. - * This assumes that the mString member from the ButtonInfo contains the parameter name. - * @param[in] stringName The name to compare against the mString member of the button infos. + * This assumes that the m_string member from the ButtonInfo contains the parameter name. + * @param[in] stringName The name to compare against the m_string member of the button infos. * @param[in] isEnabled True in case the button infos shall be enabled, false if they shall become disabled. */ void SetButtonEnabled(const char* stringName, bool isEnabled); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphHubNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphHubNode.cpp index 7463b384f3..061593ecdc 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphHubNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphHubNode.cpp @@ -119,7 +119,7 @@ namespace EMotionFX // Visualize the output pose. if (GetEMotionFX().GetIsInEditorMode() && GetCanVisualize(animGraphInstance)) { - animGraphInstance->GetActorInstance()->DrawSkeleton(outputPose->GetPose(), mVisualizeColor); + animGraphInstance->GetActorInstance()->DrawSkeleton(outputPose->GetPose(), m_visualizeColor); } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphInstance.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphInstance.cpp index 9ed0a0e527..d0c77721d1 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphInstance.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphInstance.cpp @@ -37,24 +37,24 @@ namespace EMotionFX animGraph->AddAnimGraphInstance(this); animGraph->Lock(); - mAnimGraph = animGraph; - mActorInstance = actorInstance; + m_animGraph = animGraph; + m_actorInstance = actorInstance; m_parentAnimGraphInstance = nullptr; - mMotionSet = motionSet; - mAutoUnregister = true; - mEnableVisualization = true; - mRetarget = animGraph->GetRetargetingEnabled(); - mVisualizeScale = 1.0f; + m_motionSet = motionSet; + m_autoUnregister = true; + m_enableVisualization = true; + m_retarget = animGraph->GetRetargetingEnabled(); + m_visualizeScale = 1.0f; m_autoReleaseAllPoses = true; m_autoReleaseAllRefDatas= true; #if defined(EMFX_DEVELOPMENT_BUILD) - mIsOwnedByRuntime = false; + m_isOwnedByRuntime = false; #endif // EMFX_DEVELOPMENT_BUILD if (initSettings) { - mInitSettings = *initSettings; + m_initSettings = *initSettings; } m_eventHandlersByEventType.resize(EVENT_TYPE_ANIM_GRAPH_INSTANCE_LAST_EVENT - EVENT_TYPE_ANIM_GRAPH_INSTANCE_FIRST_EVENT + 1); @@ -71,7 +71,7 @@ namespace EMotionFX // create the parameter value objects CreateParameterValues(); - mAnimGraph->Unlock(); + m_animGraph->Unlock(); GetEventManager().OnCreateAnimGraphInstance(this); } @@ -92,7 +92,7 @@ namespace EMotionFX GetEventManager().OnDeleteAnimGraphInstance(this); // automatically unregister the anim graph instance - if (mAutoUnregister) + if (m_autoUnregister) { GetAnimGraphManager().RemoveAnimGraphInstance(this, false); } @@ -127,7 +127,7 @@ namespace EMotionFX m_leaderGraphs.clear(); // unregister from the animgraph - mAnimGraph->RemoveAnimGraphInstance(this); + m_animGraph->RemoveAnimGraphInstance(this); } @@ -143,7 +143,7 @@ namespace EMotionFX { if (delFromMem) { - for (MCore::Attribute* paramValue : mParamValues) + for (MCore::Attribute* paramValue : m_paramValues) { if (paramValue) { @@ -152,14 +152,14 @@ namespace EMotionFX } } - mParamValues.clear(); + m_paramValues.clear(); } // remove all internal attributes void AnimGraphInstance::RemoveAllInternalAttributes() { - MCore::LockGuard lock(mMutex); + MCore::LockGuard lock(m_mutex); for (MCore::Attribute* internalAttribute : m_internalAttributes) { @@ -173,7 +173,7 @@ namespace EMotionFX size_t AnimGraphInstance::AddInternalAttribute(MCore::Attribute* attribute) { - MCore::LockGuard lock(mMutex); + MCore::LockGuard lock(m_mutex); m_internalAttributes.emplace_back(attribute); return m_internalAttributes.size() - 1; @@ -194,14 +194,14 @@ namespace EMotionFX void AnimGraphInstance::ReserveInternalAttributes(size_t totalNumInternalAttributes) { - MCore::LockGuard lock(mMutex); + MCore::LockGuard lock(m_mutex); m_internalAttributes.reserve(totalNumInternalAttributes); } void AnimGraphInstance::RemoveInternalAttribute(size_t index, bool delFromMem) { - MCore::LockGuard lock(mMutex); + MCore::LockGuard lock(m_mutex); if (delFromMem) { MCore::Attribute* internalAttribute = m_internalAttributes[index]; @@ -219,7 +219,7 @@ namespace EMotionFX void AnimGraphInstance::Output(Pose* outputPose) { // reset max used - const uint32 threadIndex = mActorInstance->GetThreadIndex(); + const uint32 threadIndex = m_actorInstance->GetThreadIndex(); AnimGraphPosePool& posePool = GetEMotionFX().GetThreadData(threadIndex)->GetPosePool(); posePool.ResetMaxUsedPoses(); @@ -250,10 +250,10 @@ namespace EMotionFX } // Gather active state. Must be done in output function. - if (mSnapshot && mSnapshot->IsNetworkAuthoritative()) + if (m_snapshot && m_snapshot->IsNetworkAuthoritative()) { - mSnapshot->CollectActiveNodes(*this); - mSnapshot->CollectMotionNodePlaytimes(*this); + m_snapshot->CollectActiveNodes(*this); + m_snapshot->CollectMotionNodePlaytimes(*this); } } @@ -264,14 +264,14 @@ namespace EMotionFX { RemoveAllParameters(true); - const ValueParameterVector& valueParameters = mAnimGraph->RecursivelyGetValueParameters(); - mParamValues.resize(valueParameters.size()); + const ValueParameterVector& valueParameters = m_animGraph->RecursivelyGetValueParameters(); + m_paramValues.resize(valueParameters.size()); // init the values - const size_t numParams = mParamValues.size(); + const size_t numParams = m_paramValues.size(); for (size_t i = 0; i < numParams; ++i) { - mParamValues[i] = valueParameters[i]->ConstructDefaultValueAsAttribute(); + m_paramValues[i] = valueParameters[i]->ConstructDefaultValueAsAttribute(); } } @@ -280,22 +280,22 @@ namespace EMotionFX void AnimGraphInstance::AddMissingParameterValues() { // check how many parameters we need to add - const ValueParameterVector& valueParameters = mAnimGraph->RecursivelyGetValueParameters(); - const ptrdiff_t numToAdd = aznumeric_cast(valueParameters.size()) - mParamValues.size(); + const ValueParameterVector& valueParameters = m_animGraph->RecursivelyGetValueParameters(); + const ptrdiff_t numToAdd = aznumeric_cast(valueParameters.size()) - m_paramValues.size(); if (numToAdd <= 0) { return; } // make sure we have the right space pre-allocated - mParamValues.reserve(valueParameters.size()); + m_paramValues.reserve(valueParameters.size()); // add the remaining parameters - const size_t startIndex = mParamValues.size(); + const size_t startIndex = m_paramValues.size(); for (ptrdiff_t i = 0; i < numToAdd; ++i) { const size_t index = startIndex + i; - mParamValues.emplace_back(valueParameters[index]->ConstructDefaultValueAsAttribute()); + m_paramValues.emplace_back(valueParameters[index]->ConstructDefaultValueAsAttribute()); } } @@ -305,31 +305,31 @@ namespace EMotionFX { if (delFromMem) { - if (mParamValues[index]) + if (m_paramValues[index]) { - delete mParamValues[index]; + delete m_paramValues[index]; } } - mParamValues.erase(AZStd::next(begin(mParamValues), index)); + m_paramValues.erase(AZStd::next(begin(m_paramValues), index)); } // reinitialize the parameter void AnimGraphInstance::ReInitParameterValue(size_t index) { - if (mParamValues[index]) + if (m_paramValues[index]) { - delete mParamValues[index]; + delete m_paramValues[index]; } - mParamValues[index] = mAnimGraph->FindValueParameter(index)->ConstructDefaultValueAsAttribute(); + m_paramValues[index] = m_animGraph->FindValueParameter(index)->ConstructDefaultValueAsAttribute(); } void AnimGraphInstance::ReInitParameterValues() { - const size_t parameterValueCount = mParamValues.size(); + const size_t parameterValueCount = m_paramValues.size(); for (size_t i = 0; i < parameterValueCount; ++i) { ReInitParameterValue(i); @@ -341,7 +341,7 @@ namespace EMotionFX bool AnimGraphInstance::SwitchToState(const char* stateName) { // now try to find the state - AnimGraphNode* state = mAnimGraph->RecursiveFindNodeByName(stateName); + AnimGraphNode* state = m_animGraph->RecursiveFindNodeByName(stateName); if (state == nullptr) { return false; @@ -382,7 +382,7 @@ namespace EMotionFX bool AnimGraphInstance::TransitionToState(const char* stateName) { // now try to find the state - AnimGraphNode* state = mAnimGraph->RecursiveFindNodeByName(stateName); + AnimGraphNode* state = m_animGraph->RecursiveFindNodeByName(stateName); if (state == nullptr) { return false; @@ -486,28 +486,28 @@ namespace EMotionFX // find the parameter value for a parameter with a given name MCore::Attribute* AnimGraphInstance::FindParameter(const AZStd::string& name) const { - const AZ::Outcome paramIndex = mAnimGraph->FindValueParameterIndexByName(name); + const AZ::Outcome paramIndex = m_animGraph->FindValueParameterIndexByName(name); if (!paramIndex.IsSuccess()) { return nullptr; } - return mParamValues[paramIndex.GetValue()]; + return m_paramValues[paramIndex.GetValue()]; } // add the last anim graph parameter to this instance void AnimGraphInstance::AddParameterValue() { - mParamValues.emplace_back(nullptr); - ReInitParameterValue(mParamValues.size() - 1); + m_paramValues.emplace_back(nullptr); + ReInitParameterValue(m_paramValues.size() - 1); } // add the parameter of the animgraph, at a given index void AnimGraphInstance::InsertParameterValue(size_t index) { - mParamValues.emplace(AZStd::next(begin(mParamValues), index), nullptr); + m_paramValues.emplace(AZStd::next(begin(m_paramValues), index), nullptr); ReInitParameterValue(index); } @@ -515,7 +515,7 @@ namespace EMotionFX // move the parameter from old index to new index void AnimGraphInstance::MoveParameterValue(size_t oldIndex, size_t newIndex) { - MCore::Attribute* oldAttribute = mParamValues[oldIndex]; + MCore::Attribute* oldAttribute = m_paramValues[oldIndex]; // if old index is greater than new index, move elements between oldIndex and newIndex to the right of new index // otherwise, move to the left of new index @@ -524,18 +524,18 @@ namespace EMotionFX for (size_t paramIndex = oldIndex; paramIndex > newIndex; paramIndex--) { const size_t prevIndex = paramIndex - 1; - mParamValues[paramIndex] = mParamValues[prevIndex]; + m_paramValues[paramIndex] = m_paramValues[prevIndex]; } - mParamValues[newIndex] = oldAttribute; + m_paramValues[newIndex] = oldAttribute; } else { for (size_t paramIndex = oldIndex; paramIndex < newIndex; paramIndex++) { const size_t nexIndex = paramIndex + 1; - mParamValues[paramIndex] = mParamValues[nexIndex]; + m_paramValues[paramIndex] = m_paramValues[nexIndex]; } - mParamValues[newIndex] = oldAttribute; + m_paramValues[newIndex] = oldAttribute; } } @@ -566,7 +566,7 @@ namespace EMotionFX void AnimGraphInstance::SetMotionSet(MotionSet* motionSet) { // update the local motion set pointer - mMotionSet = motionSet; + m_motionSet = motionSet; // get the number of state machines, iterate through them and recursively call the callback GetRootNode()->RecursiveOnChangeMotionSet(this, motionSet); @@ -576,20 +576,20 @@ namespace EMotionFX // adjust the auto unregistering from the anim graph manager on delete void AnimGraphInstance::SetAutoUnregisterEnabled(bool enabled) { - mAutoUnregister = enabled; + m_autoUnregister = enabled; } // do we auto unregister from the anim graph manager on delete? bool AnimGraphInstance::GetAutoUnregisterEnabled() const { - return mAutoUnregister; + return m_autoUnregister; } void AnimGraphInstance::SetIsOwnedByRuntime(bool isOwnedByRuntime) { #if defined(EMFX_DEVELOPMENT_BUILD) - mIsOwnedByRuntime = isOwnedByRuntime; + m_isOwnedByRuntime = isOwnedByRuntime; #else AZ_UNUSED(isOwnedByRuntime); #endif @@ -599,7 +599,7 @@ namespace EMotionFX bool AnimGraphInstance::GetIsOwnedByRuntime() const { #if defined(EMFX_DEVELOPMENT_BUILD) - return mIsOwnedByRuntime; + return m_isOwnedByRuntime; #else return true; #endif @@ -610,7 +610,7 @@ namespace EMotionFX ActorInstance* AnimGraphInstance::FindActorInstanceFromParentDepth(size_t parentDepth) const { // start with the actor instance this anim graph instance is working on - ActorInstance* curInstance = mActorInstance; + ActorInstance* curInstance = m_actorInstance; if (parentDepth == 0) { return curInstance; @@ -654,7 +654,7 @@ namespace EMotionFX void AnimGraphInstance::AddUniqueObjectData() { m_uniqueDatas.emplace_back(nullptr); - mObjectFlags.emplace_back(0); + m_objectFlags.emplace_back(0); } // remove the given unique data object @@ -672,7 +672,7 @@ namespace EMotionFX } m_uniqueDatas.erase(m_uniqueDatas.begin() + index); - mObjectFlags.erase(AZStd::next(begin(mObjectFlags), index)); + m_objectFlags.erase(AZStd::next(begin(m_objectFlags), index)); } @@ -680,7 +680,7 @@ namespace EMotionFX { AnimGraphObjectData* data = m_uniqueDatas[index]; m_uniqueDatas.erase(m_uniqueDatas.begin() + index); - mObjectFlags.erase(AZStd::next(begin(mObjectFlags), index)); + m_objectFlags.erase(AZStd::next(begin(m_objectFlags), index)); if (delFromMem && data) { data->Destroy(); @@ -703,7 +703,7 @@ namespace EMotionFX } m_uniqueDatas.clear(); - mObjectFlags.clear(); + m_objectFlags.clear(); } @@ -807,13 +807,13 @@ namespace EMotionFX // init the hashmap void AnimGraphInstance::InitUniqueDatas() { - const size_t numObjects = mAnimGraph->GetNumObjects(); + const size_t numObjects = m_animGraph->GetNumObjects(); m_uniqueDatas.resize(numObjects); - mObjectFlags.resize(numObjects); + m_objectFlags.resize(numObjects); for (size_t i = 0; i < numObjects; ++i) { m_uniqueDatas[i] = nullptr; - mObjectFlags[i] = 0; + m_objectFlags[i] = 0; } } @@ -821,7 +821,7 @@ namespace EMotionFX // get the root node AnimGraphNode* AnimGraphInstance::GetRootNode() const { - return mAnimGraph->GetRootStateMachine(); + return m_animGraph->GetRootStateMachine(); } @@ -832,22 +832,22 @@ namespace EMotionFX Transform trajectoryDelta; // get the motion extraction node, and if it hasn't been set, we can already quit - Node* motionExtractNode = mActorInstance->GetActor()->GetMotionExtractionNode(); + Node* motionExtractNode = m_actorInstance->GetActor()->GetMotionExtractionNode(); if (motionExtractNode == nullptr) { trajectoryDelta.IdentityWithZeroScale(); - mActorInstance->SetTrajectoryDeltaTransform(trajectoryDelta); + m_actorInstance->SetTrajectoryDeltaTransform(trajectoryDelta); return; } // get the root node's trajectory delta - AnimGraphRefCountedData* rootData = mAnimGraph->GetRootStateMachine()->FindOrCreateUniqueNodeData(this)->GetRefCountedData(); + AnimGraphRefCountedData* rootData = m_animGraph->GetRootStateMachine()->FindOrCreateUniqueNodeData(this)->GetRefCountedData(); trajectoryDelta = rootData->GetTrajectoryDelta(); - trajectoryDelta.mRotation.Normalize(); + trajectoryDelta.m_rotation.Normalize(); // update the actor instance with the delta movement already - mActorInstance->SetTrajectoryDeltaTransform(trajectoryDelta); - mActorInstance->ApplyMotionExtractionDelta(); + m_actorInstance->SetTrajectoryDeltaTransform(trajectoryDelta); + m_actorInstance->ApplyMotionExtractionDelta(); } @@ -855,9 +855,9 @@ namespace EMotionFX void AnimGraphInstance::Update(float timePassedInSeconds) { // pass 0: (Optional, networking only) When this instance is shared between network, restore the instance using an animgraph snapshot. - if (mSnapshot) + if (m_snapshot) { - mSnapshot->Restore(*this); + m_snapshot->Restore(*this); } // pass 1: update (bottom up), update motion timers etc @@ -876,7 +876,7 @@ namespace EMotionFX } // reset all node pose ref counts - const uint32 threadIndex = mActorInstance->GetThreadIndex(); + const uint32 threadIndex = m_actorInstance->GetThreadIndex(); ResetPoseRefCountsForAllNodes(); ResetRefDataRefCountsForAllNodes(); GetEMotionFX().GetThreadData(threadIndex)->GetRefCountedDataPool().ResetMaxUsedItems(); @@ -901,7 +901,7 @@ namespace EMotionFX ApplyMotionExtraction(); // store a copy of the root's event buffer - mEventBuffer = rootNodeUniqueData->GetRefCountedData()->GetEventBuffer(); + m_eventBuffer = rootNodeUniqueData->GetRefCountedData()->GetEventBuffer(); // trigger the events inside the root node's buffer OutputEvents(); @@ -923,14 +923,14 @@ namespace EMotionFX // recursively reset flags void AnimGraphInstance::RecursiveResetFlags(uint32 flagsToDisable) { - mAnimGraph->GetRootStateMachine()->RecursiveResetFlags(this, flagsToDisable); + m_animGraph->GetRootStateMachine()->RecursiveResetFlags(this, flagsToDisable); } // reset all node flags void AnimGraphInstance::ResetFlagsForAllObjects(uint32 flagsToDisable) { - for (uint32& objectFlag : mObjectFlags) + for (uint32& objectFlag : m_objectFlags) { objectFlag &= ~flagsToDisable; } @@ -940,10 +940,10 @@ namespace EMotionFX // reset all node pose ref counts void AnimGraphInstance::ResetPoseRefCountsForAllNodes() { - const size_t numNodes = mAnimGraph->GetNumNodes(); + const size_t numNodes = m_animGraph->GetNumNodes(); for (size_t i = 0; i < numNodes; ++i) { - mAnimGraph->GetNode(i)->ResetPoseRefCount(this); + m_animGraph->GetNode(i)->ResetPoseRefCount(this); } } @@ -951,10 +951,10 @@ namespace EMotionFX // reset all node pose ref counts void AnimGraphInstance::ResetRefDataRefCountsForAllNodes() { - const size_t numNodes = mAnimGraph->GetNumNodes(); + const size_t numNodes = m_animGraph->GetNumNodes(); for (size_t i = 0; i < numNodes; ++i) { - mAnimGraph->GetNode(i)->ResetRefDataRefCount(this); + m_animGraph->GetNode(i)->ResetRefDataRefCount(this); } } @@ -962,7 +962,7 @@ namespace EMotionFX // reset all node flags void AnimGraphInstance::ResetFlagsForAllObjects() { - MCore::MemSet(mObjectFlags.data(), 0, sizeof(uint32) * mObjectFlags.size()); + MCore::MemSet(m_objectFlags.data(), 0, sizeof(uint32) * m_objectFlags.size()); for (AnimGraphInstance* childInstance : m_childAnimGraphInstances) { @@ -974,11 +974,11 @@ namespace EMotionFX // reset flags for all nodes void AnimGraphInstance::ResetFlagsForAllNodes(uint32 flagsToDisable) { - const size_t numNodes = mAnimGraph->GetNumNodes(); + const size_t numNodes = m_animGraph->GetNumNodes(); for (size_t i = 0; i < numNodes; ++i) { - AnimGraphNode* node = mAnimGraph->GetNode(i); - mObjectFlags[node->GetObjectIndex()] &= ~flagsToDisable; + AnimGraphNode* node = m_animGraph->GetNode(i); + m_objectFlags[node->GetObjectIndex()] &= ~flagsToDisable; if (GetEMotionFX().GetIsInEditorMode()) { @@ -1009,14 +1009,14 @@ namespace EMotionFX void AnimGraphInstance::CollectActiveAnimGraphNodes(AZStd::vector* outNodes, const AZ::TypeId& nodeType) { outNodes->clear(); - mAnimGraph->GetRootStateMachine()->RecursiveCollectActiveNodes(this, outNodes, nodeType); + m_animGraph->GetRootStateMachine()->RecursiveCollectActiveNodes(this, outNodes, nodeType); } void AnimGraphInstance::CollectActiveNetTimeSyncNodes(AZStd::vector* outNodes) { outNodes->clear(); - mAnimGraph->GetRootStateMachine()->RecursiveCollectActiveNetTimeSyncNodes(this, outNodes); + m_animGraph->GetRootStateMachine()->RecursiveCollectActiveNetTimeSyncNodes(this, outNodes); } AnimGraphObjectData* AnimGraphInstance::FindOrCreateUniqueObjectData(const AnimGraphObject* object) @@ -1052,65 +1052,65 @@ namespace EMotionFX // find the parameter index AZ::Outcome AnimGraphInstance::FindParameterIndex(const AZStd::string& name) const { - return mAnimGraph->FindValueParameterIndexByName(name); + return m_animGraph->FindValueParameterIndexByName(name); } // init all internal attributes void AnimGraphInstance::InitInternalAttributes() { - const size_t numNodes = mAnimGraph->GetNumNodes(); + const size_t numNodes = m_animGraph->GetNumNodes(); for (size_t i = 0; i < numNodes; ++i) { - mAnimGraph->GetNode(i)->InitInternalAttributes(this); + m_animGraph->GetNode(i)->InitInternalAttributes(this); } } void AnimGraphInstance::SetVisualizeScale(float scale) { - mVisualizeScale = scale; + m_visualizeScale = scale; } float AnimGraphInstance::GetVisualizeScale() const { - return mVisualizeScale; + return m_visualizeScale; } void AnimGraphInstance::SetVisualizationEnabled(bool enabled) { - mEnableVisualization = enabled; + m_enableVisualization = enabled; } bool AnimGraphInstance::GetVisualizationEnabled() const { - return mEnableVisualization; + return m_enableVisualization; } bool AnimGraphInstance::GetRetargetingEnabled() const { - return mRetarget; + return m_retarget; } void AnimGraphInstance::SetRetargetingEnabled(bool enabled) { - mRetarget = enabled; + m_retarget = enabled; } const AnimGraphInstance::InitSettings& AnimGraphInstance::GetInitSettings() const { - return mInitSettings; + return m_initSettings; } const AnimGraphEventBuffer& AnimGraphInstance::GetEventBuffer() const { - return mEventBuffer; + return m_eventBuffer; } @@ -1172,72 +1172,72 @@ namespace EMotionFX void AnimGraphInstance::CreateSnapshot(bool authoritative) { - if (mSnapshot) + if (m_snapshot) { AZ_Error("EMotionFX", false, "Snapshot already created for this animgraph instance."); return; } - mSnapshot = AZStd::make_shared(*this, authoritative); + m_snapshot = AZStd::make_shared(*this, authoritative); } void AnimGraphInstance::SetSnapshotSerializer(AZStd::shared_ptr serializer) { - if (!mSnapshot) + if (!m_snapshot) { AZ_Error("EMotionFX", false, "Snapshot should be created first."); return; } - mSnapshot->SetSnapshotSerializer(serializer); + m_snapshot->SetSnapshotSerializer(serializer); } void AnimGraphInstance::SetSnapshotChunkSerializer(AZStd::shared_ptr serializer) { - if (!mSnapshot) + if (!m_snapshot) { AZ_Error("EMotionFX", false, "Snapshot should be created first."); return; } - mSnapshot->SetSnapshotChunkSerializer(serializer); + m_snapshot->SetSnapshotChunkSerializer(serializer); } void AnimGraphInstance::OnNetworkConnected() { - if (!mSnapshot) + if (!m_snapshot) { AZ_Error("EMotionFX", false, "Snapshot should be created first."); return; } - mSnapshot->OnNetworkConnected(*this); + m_snapshot->OnNetworkConnected(*this); } void AnimGraphInstance::OnNetworkParamUpdate(const AttributeContainer& parameters) { - if (!mSnapshot) + if (!m_snapshot) { AZ_Error("EMotionFX", false, "Snapshot should be created first."); return; } - mSnapshot->SetParameters(parameters); + m_snapshot->SetParameters(parameters); } void AnimGraphInstance::OnNetworkActiveNodesUpdate(const AZStd::vector& activeNodes) { - if (!mSnapshot) + if (!m_snapshot) { AZ_Error("EMotionFX", false, "Snapshot should be created first."); return; } - mSnapshot->SetActiveNodes(activeNodes); + m_snapshot->SetActiveNodes(activeNodes); } void AnimGraphInstance::OnNetworkMotionNodePlaytimesUpdate(const MotionNodePlaytimeContainer& motionNodePlaytimes) { - if (!mSnapshot) + if (!m_snapshot) { AZ_Error("EMotionFX", false, "Snapshot should be created first."); return; } - mSnapshot->SetMotionNodePlaytimes(motionNodePlaytimes); + m_snapshot->SetMotionNodePlaytimes(motionNodePlaytimes); } void AnimGraphInstance::SetAutoReleaseRefDatas(bool automaticallyFreeRefDatas) @@ -1252,13 +1252,13 @@ namespace EMotionFX void AnimGraphInstance::ReleaseRefDatas() { - const uint32 threadIndex = mActorInstance->GetThreadIndex(); + const uint32 threadIndex = m_actorInstance->GetThreadIndex(); AnimGraphRefCountedDataPool& refDataPool = GetEMotionFX().GetThreadData(threadIndex)->GetRefCountedDataPool(); - const size_t numNodes = mAnimGraph->GetNumNodes(); + const size_t numNodes = m_animGraph->GetNumNodes(); for (size_t i = 0; i < numNodes; ++i) { - const AnimGraphNode* node = mAnimGraph->GetNode(i); + const AnimGraphNode* node = m_animGraph->GetNode(i); AnimGraphNodeData* nodeData = static_cast(m_uniqueDatas[node->GetObjectIndex()]); if (nodeData) { diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphInstance.h b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphInstance.h index 9366fcff86..81bae83515 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphInstance.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphInstance.h @@ -64,11 +64,11 @@ namespace EMotionFX struct EMFX_API InitSettings { - bool mPreInitMotionInstances; + bool m_preInitMotionInstances; InitSettings() { - mPreInitMotionInstances = false; + m_preInitMotionInstances = false; } }; @@ -79,9 +79,9 @@ namespace EMotionFX void Start(); void Stop(); - MCORE_INLINE ActorInstance* GetActorInstance() const { return mActorInstance; } - MCORE_INLINE AnimGraph* GetAnimGraph() const { return mAnimGraph; } - MCORE_INLINE MotionSet* GetMotionSet() const { return mMotionSet; } + MCORE_INLINE ActorInstance* GetActorInstance() const { return m_actorInstance; } + MCORE_INLINE AnimGraph* GetAnimGraph() const { return m_animGraph; } + MCORE_INLINE MotionSet* GetMotionSet() const { return m_motionSet; } void SetParentAnimGraphInstance(AnimGraphInstance* parentAnimGraphInstance); MCORE_INLINE AnimGraphInstance* GetParentAnimGraphInstance() const { return m_parentAnimGraphInstance; } @@ -118,7 +118,7 @@ namespace EMotionFX template MCORE_INLINE T* GetParameterValueChecked(size_t index) const { - MCore::Attribute* baseAttrib = mParamValues[index]; + MCore::Attribute* baseAttrib = m_paramValues[index]; if (baseAttrib->GetType() == T::TYPE_ID) { return static_cast(baseAttrib); @@ -126,7 +126,7 @@ namespace EMotionFX return nullptr; } - MCORE_INLINE MCore::Attribute* GetParameterValue(size_t index) const { return mParamValues[index]; } + MCORE_INLINE MCore::Attribute* GetParameterValue(size_t index) const { return m_paramValues[index]; } MCore::Attribute* FindParameter(const AZStd::string& name) const; AZ::Outcome FindParameterIndex(const AZStd::string& name) const; @@ -237,39 +237,39 @@ namespace EMotionFX void CollectActiveAnimGraphNodes(AZStd::vector* outNodes, const AZ::TypeId& nodeType = AZ::TypeId::CreateNull()); // MCORE_INVALIDINDEX32 means all node types void CollectActiveNetTimeSyncNodes(AZStd::vector* outNodes); - MCORE_INLINE uint32 GetObjectFlags(size_t objectIndex) const { return mObjectFlags[objectIndex]; } - MCORE_INLINE void SetObjectFlags(size_t objectIndex, uint32 flags) { mObjectFlags[objectIndex] = flags; } - MCORE_INLINE void EnableObjectFlags(size_t objectIndex, uint32 flagsToEnable) { mObjectFlags[objectIndex] |= flagsToEnable; } - MCORE_INLINE void DisableObjectFlags(size_t objectIndex, uint32 flagsToDisable) { mObjectFlags[objectIndex] &= ~flagsToDisable; } + MCORE_INLINE uint32 GetObjectFlags(size_t objectIndex) const { return m_objectFlags[objectIndex]; } + MCORE_INLINE void SetObjectFlags(size_t objectIndex, uint32 flags) { m_objectFlags[objectIndex] = flags; } + MCORE_INLINE void EnableObjectFlags(size_t objectIndex, uint32 flagsToEnable) { m_objectFlags[objectIndex] |= flagsToEnable; } + MCORE_INLINE void DisableObjectFlags(size_t objectIndex, uint32 flagsToDisable) { m_objectFlags[objectIndex] &= ~flagsToDisable; } MCORE_INLINE void SetObjectFlags(size_t objectIndex, uint32 flags, bool enabled) { if (enabled) { - mObjectFlags[objectIndex] |= flags; + m_objectFlags[objectIndex] |= flags; } else { - mObjectFlags[objectIndex] &= ~flags; + m_objectFlags[objectIndex] &= ~flags; } } - MCORE_INLINE bool GetIsObjectFlagEnabled(size_t objectIndex, uint32 flag) const { return (mObjectFlags[objectIndex] & flag) != 0; } + MCORE_INLINE bool GetIsObjectFlagEnabled(size_t objectIndex, uint32 flag) const { return (m_objectFlags[objectIndex] & flag) != 0; } - MCORE_INLINE bool GetIsOutputReady(size_t objectIndex) const { return (mObjectFlags[objectIndex] & OBJECTFLAGS_OUTPUT_READY) != 0; } + MCORE_INLINE bool GetIsOutputReady(size_t objectIndex) const { return (m_objectFlags[objectIndex] & OBJECTFLAGS_OUTPUT_READY) != 0; } MCORE_INLINE void SetIsOutputReady(size_t objectIndex, bool isReady) { SetObjectFlags(objectIndex, OBJECTFLAGS_OUTPUT_READY, isReady); } - MCORE_INLINE bool GetIsSynced(size_t objectIndex) const { return (mObjectFlags[objectIndex] & OBJECTFLAGS_SYNCED) != 0; } + MCORE_INLINE bool GetIsSynced(size_t objectIndex) const { return (m_objectFlags[objectIndex] & OBJECTFLAGS_SYNCED) != 0; } MCORE_INLINE void SetIsSynced(size_t objectIndex, bool isSynced) { SetObjectFlags(objectIndex, OBJECTFLAGS_SYNCED, isSynced); } - MCORE_INLINE bool GetIsResynced(size_t objectIndex) const { return (mObjectFlags[objectIndex] & OBJECTFLAGS_RESYNC) != 0; } + MCORE_INLINE bool GetIsResynced(size_t objectIndex) const { return (m_objectFlags[objectIndex] & OBJECTFLAGS_RESYNC) != 0; } MCORE_INLINE void SetIsResynced(size_t objectIndex, bool isResynced) { SetObjectFlags(objectIndex, OBJECTFLAGS_RESYNC, isResynced); } - MCORE_INLINE bool GetIsUpdateReady(size_t objectIndex) const { return (mObjectFlags[objectIndex] & OBJECTFLAGS_UPDATE_READY) != 0; } + MCORE_INLINE bool GetIsUpdateReady(size_t objectIndex) const { return (m_objectFlags[objectIndex] & OBJECTFLAGS_UPDATE_READY) != 0; } MCORE_INLINE void SetIsUpdateReady(size_t objectIndex, bool isReady) { SetObjectFlags(objectIndex, OBJECTFLAGS_UPDATE_READY, isReady); } - MCORE_INLINE bool GetIsTopDownUpdateReady(size_t objectIndex) const { return (mObjectFlags[objectIndex] & OBJECTFLAGS_TOPDOWNUPDATE_READY) != 0; } + MCORE_INLINE bool GetIsTopDownUpdateReady(size_t objectIndex) const { return (m_objectFlags[objectIndex] & OBJECTFLAGS_TOPDOWNUPDATE_READY) != 0; } MCORE_INLINE void SetIsTopDownUpdateReady(size_t objectIndex, bool isReady) { SetObjectFlags(objectIndex, OBJECTFLAGS_TOPDOWNUPDATE_READY, isReady); } - MCORE_INLINE bool GetIsPostUpdateReady(size_t objectIndex) const { return (mObjectFlags[objectIndex] & OBJECTFLAGS_POSTUPDATE_READY) != 0; } + MCORE_INLINE bool GetIsPostUpdateReady(size_t objectIndex) const { return (m_objectFlags[objectIndex] & OBJECTFLAGS_POSTUPDATE_READY) != 0; } MCORE_INLINE void SetIsPostUpdateReady(size_t objectIndex, bool isReady) { SetObjectFlags(objectIndex, OBJECTFLAGS_POSTUPDATE_READY, isReady); } const InitSettings& GetInitSettings() const; @@ -283,9 +283,9 @@ namespace EMotionFX void CreateSnapshot(bool authoritative); void SetSnapshotSerializer(AZStd::shared_ptr serializer); void SetSnapshotChunkSerializer(AZStd::shared_ptr serializer); - const AZStd::shared_ptr GetSnapshot() const { return mSnapshot; } + const AZStd::shared_ptr GetSnapshot() const { return m_snapshot; } bool IsNetworkEnabled() const { return GetSnapshot(); } - MCore::LcgRandom& GetLcgRandom() { return mLcgRandom; } + MCore::LcgRandom& GetLcgRandom() { return m_lcgRandom; } void OnNetworkConnected(); void OnNetworkParamUpdate(const AttributeContainer& parameters); @@ -298,24 +298,24 @@ namespace EMotionFX void ReleasePoses(); private: - AnimGraph* mAnimGraph; - ActorInstance* mActorInstance; + AnimGraph* m_animGraph; + ActorInstance* m_actorInstance; AnimGraphInstance* m_parentAnimGraphInstance; // If this anim graph instance is in a reference node, it will have a parent anim graph instance. AZStd::vector m_childAnimGraphInstances; // If this anim graph instance contains reference nodes, the anim graph instances will be listed here. - AZStd::vector mParamValues; // a value for each AnimGraph parameter (the control parameters) + AZStd::vector m_paramValues; // a value for each AnimGraph parameter (the control parameters) AZStd::vector m_uniqueDatas; // unique object data - AZStd::vector mObjectFlags; // the object flags + AZStd::vector m_objectFlags; // the object flags using EventHandlerVector = AZStd::vector; AZStd::vector m_eventHandlersByEventType; /**< The event handler to use to process events organized by EventTypes. */ AZStd::vector m_internalAttributes; - MotionSet* mMotionSet; // the used motion set - MCore::Mutex mMutex; - InitSettings mInitSettings; - AnimGraphEventBuffer mEventBuffer; /**< The event buffer of the last update. */ - float mVisualizeScale; - bool mAutoUnregister; /**< Specifies whether we will automatically unregister this anim graph instance set from the anim graph manager or not, when deleting this object. */ - bool mEnableVisualization; - bool mRetarget; /**< Is retargeting enabled? */ + MotionSet* m_motionSet; // the used motion set + MCore::Mutex m_mutex; + InitSettings m_initSettings; + AnimGraphEventBuffer m_eventBuffer; /**< The event buffer of the last update. */ + float m_visualizeScale; + bool m_autoUnregister; /**< Specifies whether we will automatically unregister this anim graph instance set from the anim graph manager or not, when deleting this object. */ + bool m_enableVisualization; + bool m_retarget; /**< Is retargeting enabled? */ bool m_autoReleaseAllPoses; bool m_autoReleaseAllRefDatas; @@ -324,11 +324,11 @@ namespace EMotionFX AZStd::vector m_leaderGraphs; // Network related members - AZStd::shared_ptr mSnapshot; - MCore::LcgRandom mLcgRandom; + AZStd::shared_ptr m_snapshot; + MCore::LcgRandom m_lcgRandom; #if defined(EMFX_DEVELOPMENT_BUILD) - bool mIsOwnedByRuntime; + bool m_isOwnedByRuntime; #endif // EMFX_DEVELOPMENT_BUILD AnimGraphInstance(AnimGraph* animGraph, ActorInstance* actorInstance, MotionSet* motionSet, const InitSettings* initSettings = nullptr); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphManager.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphManager.cpp index fc74d747c6..069bb4b57a 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphManager.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphManager.cpp @@ -28,16 +28,16 @@ namespace EMotionFX AnimGraphManager::AnimGraphManager() : BaseObject() - , mBlendSpaceManager(nullptr) + , m_blendSpaceManager(nullptr) { } AnimGraphManager::~AnimGraphManager() { - if (mBlendSpaceManager) + if (m_blendSpaceManager) { - mBlendSpaceManager->Destroy(); + m_blendSpaceManager->Destroy(); } // delete the anim graph instances and anim graphs //RemoveAllAnimGraphInstances(true); @@ -53,10 +53,10 @@ namespace EMotionFX void AnimGraphManager::Init() { - mAnimGraphInstances.reserve(1024); - mAnimGraphs.reserve(128); + m_animGraphInstances.reserve(1024); + m_animGraphs.reserve(128); - mBlendSpaceManager = aznew BlendSpaceManager(); + m_blendSpaceManager = aznew BlendSpaceManager(); // register custom attribute types MCore::GetAttributeFactory().RegisterAttribute(aznew AttributePose()); @@ -66,51 +66,51 @@ namespace EMotionFX void AnimGraphManager::RemoveAllAnimGraphs(bool delFromMemory) { - MCore::LockGuardRecursive lock(mAnimGraphLock); + MCore::LockGuardRecursive lock(m_animGraphLock); - while (!mAnimGraphs.empty()) + while (!m_animGraphs.empty()) { - RemoveAnimGraph(mAnimGraphs.size() - 1, delFromMemory); + RemoveAnimGraph(m_animGraphs.size() - 1, delFromMemory); } } void AnimGraphManager::RemoveAllAnimGraphInstances(bool delFromMemory) { - MCore::LockGuardRecursive lock(mAnimGraphInstanceLock); + MCore::LockGuardRecursive lock(m_animGraphInstanceLock); - while (!mAnimGraphInstances.empty()) + while (!m_animGraphInstances.empty()) { - RemoveAnimGraphInstance(mAnimGraphInstances.size() - 1, delFromMemory); + RemoveAnimGraphInstance(m_animGraphInstances.size() - 1, delFromMemory); } } void AnimGraphManager::AddAnimGraph(AnimGraph* setup) { - MCore::LockGuardRecursive lock(mAnimGraphLock); - mAnimGraphs.push_back(setup); + MCore::LockGuardRecursive lock(m_animGraphLock); + m_animGraphs.push_back(setup); } // Remove a given anim graph by index. void AnimGraphManager::RemoveAnimGraph(size_t index, bool delFromMemory) { - MCore::LockGuardRecursive lock(mAnimGraphLock); + MCore::LockGuardRecursive lock(m_animGraphLock); - AnimGraph* animGraph = mAnimGraphs[index]; - const int animGraphInstanceCount = static_cast(mAnimGraphInstances.size()); + AnimGraph* animGraph = m_animGraphs[index]; + const int animGraphInstanceCount = static_cast(m_animGraphInstances.size()); for (int i = animGraphInstanceCount - 1; i >= 0; --i) { - if (mAnimGraphInstances[i]->GetAnimGraph() == animGraph) + if (m_animGraphInstances[i]->GetAnimGraph() == animGraph) { - RemoveAnimGraphInstance(mAnimGraphInstances[i]); + RemoveAnimGraphInstance(m_animGraphInstances[i]); } } // Need to remove it from the list of anim graphs first since deleting it can cause assets to get unloaded and // this function to be called recursively (making the index to shift) - mAnimGraphs.erase(mAnimGraphs.begin() + index); + m_animGraphs.erase(m_animGraphs.begin() + index); if (delFromMemory) { @@ -125,7 +125,7 @@ namespace EMotionFX // Remove a given anim graph by pointer. bool AnimGraphManager::RemoveAnimGraph(AnimGraph* animGraph, bool delFromMemory) { - MCore::LockGuardRecursive lock(mAnimGraphLock); + MCore::LockGuardRecursive lock(m_animGraphLock); // find the index of the anim graph and return false in case the pointer is not valid const size_t animGraphIndex = FindAnimGraphIndex(animGraph); @@ -141,18 +141,18 @@ namespace EMotionFX void AnimGraphManager::AddAnimGraphInstance(AnimGraphInstance* animGraphInstance) { - MCore::LockGuardRecursive lock(mAnimGraphInstanceLock); - mAnimGraphInstances.push_back(animGraphInstance); + MCore::LockGuardRecursive lock(m_animGraphInstanceLock); + m_animGraphInstances.push_back(animGraphInstance); } void AnimGraphManager::RemoveAnimGraphInstance(size_t index, bool delFromMemory) { - MCore::LockGuardRecursive lock(mAnimGraphInstanceLock); + MCore::LockGuardRecursive lock(m_animGraphInstanceLock); if (delFromMemory) { - AnimGraphInstance* animGraphInstance = mAnimGraphInstances[index]; + AnimGraphInstance* animGraphInstance = m_animGraphInstances[index]; animGraphInstance->RemoveAllObjectData(true); // Remove all links to the anim graph instance that will get removed. @@ -172,14 +172,14 @@ namespace EMotionFX animGraphInstance->Destroy(); } - mAnimGraphInstances.erase(mAnimGraphInstances.begin() + index); + m_animGraphInstances.erase(m_animGraphInstances.begin() + index); } // remove a given anim graph instance by pointer bool AnimGraphManager::RemoveAnimGraphInstance(AnimGraphInstance* animGraphInstance, bool delFromMemory) { - MCore::LockGuardRecursive lock(mAnimGraphInstanceLock); + MCore::LockGuardRecursive lock(m_animGraphInstanceLock); // find the index of the anim graph instance and return false in case the pointer is not valid const size_t instanceIndex = FindAnimGraphInstanceIndex(animGraphInstance); @@ -196,20 +196,20 @@ namespace EMotionFX void AnimGraphManager::RemoveAnimGraphInstances(AnimGraph* animGraph, bool delFromMemory) { - MCore::LockGuardRecursive lock(mAnimGraphInstanceLock); + MCore::LockGuardRecursive lock(m_animGraphInstanceLock); - if (mAnimGraphInstances.empty()) + if (m_animGraphInstances.empty()) { return; } // Remove anim graph instances back to front in case they are linked to the given anim graph. - const size_t numInstances = mAnimGraphInstances.size(); + const size_t numInstances = m_animGraphInstances.size(); for (size_t i = 0; i < numInstances; ++i) { const size_t reverseIndex = numInstances - 1 - i; - AnimGraphInstance* instance = mAnimGraphInstances[reverseIndex]; + AnimGraphInstance* instance = m_animGraphInstances[reverseIndex]; if (instance->GetAnimGraph() == animGraph) { RemoveAnimGraphInstance(reverseIndex, delFromMemory); @@ -220,30 +220,30 @@ namespace EMotionFX size_t AnimGraphManager::FindAnimGraphIndex(AnimGraph* animGraph) const { - MCore::LockGuardRecursive lock(mAnimGraphLock); + MCore::LockGuardRecursive lock(m_animGraphLock); - auto iterator = AZStd::find(mAnimGraphs.begin(), mAnimGraphs.end(), animGraph); - if (iterator == mAnimGraphs.end()) + auto iterator = AZStd::find(m_animGraphs.begin(), m_animGraphs.end(), animGraph); + if (iterator == m_animGraphs.end()) { return InvalidIndex; } - const size_t index = iterator - mAnimGraphs.begin(); + const size_t index = iterator - m_animGraphs.begin(); return index; } size_t AnimGraphManager::FindAnimGraphInstanceIndex(AnimGraphInstance* animGraphInstance) const { - MCore::LockGuardRecursive lock(mAnimGraphInstanceLock); + MCore::LockGuardRecursive lock(m_animGraphInstanceLock); - auto iterator = AZStd::find(mAnimGraphInstances.begin(), mAnimGraphInstances.end(), animGraphInstance); - if (iterator == mAnimGraphInstances.end()) + auto iterator = AZStd::find(m_animGraphInstances.begin(), m_animGraphInstances.end(), animGraphInstance); + if (iterator == m_animGraphInstances.end()) { return InvalidIndex; } - const size_t index = iterator - mAnimGraphInstances.begin(); + const size_t index = iterator - m_animGraphInstances.begin(); return index; } @@ -251,9 +251,9 @@ namespace EMotionFX // find a anim graph with a given filename AnimGraph* AnimGraphManager::FindAnimGraphByFileName(const char* filename, bool isTool) const { - MCore::LockGuardRecursive lock(mAnimGraphLock); + MCore::LockGuardRecursive lock(m_animGraphLock); - for (EMotionFX::AnimGraph* animGraph : mAnimGraphs) + for (EMotionFX::AnimGraph* animGraph : m_animGraphs) { if (animGraph->GetIsOwnedByRuntime() == isTool) { @@ -273,9 +273,9 @@ namespace EMotionFX // Find anim graph with a given id. AnimGraph* AnimGraphManager::FindAnimGraphByID(uint32 animGraphID) const { - MCore::LockGuardRecursive lock(mAnimGraphLock); + MCore::LockGuardRecursive lock(m_animGraphLock); - for (EMotionFX::AnimGraph* animGraph : mAnimGraphs) + for (EMotionFX::AnimGraph* animGraph : m_animGraphs) { if (animGraph->GetID() == animGraphID) { @@ -290,11 +290,11 @@ namespace EMotionFX // Find the first available anim graph AnimGraph* AnimGraphManager::GetFirstAnimGraph() const { - MCore::LockGuardRecursive lock(mAnimGraphLock); + MCore::LockGuardRecursive lock(m_animGraphLock); - if (mAnimGraphs.size() > 0) + if (m_animGraphs.size() > 0) { - return mAnimGraphs[0]; + return m_animGraphs[0]; } return nullptr; } @@ -302,10 +302,10 @@ namespace EMotionFX void AnimGraphManager::SetAnimGraphVisualizationEnabled(bool enabled) { - MCore::LockGuardRecursive lock(mAnimGraphInstanceLock); + MCore::LockGuardRecursive lock(m_animGraphInstanceLock); // Enable or disable anim graph visualization for all anim graph instances.. - for (AnimGraphInstance* animGraphInstance : mAnimGraphInstances) + for (AnimGraphInstance* animGraphInstance : m_animGraphInstances) { animGraphInstance->SetVisualizationEnabled(enabled); } @@ -314,7 +314,7 @@ namespace EMotionFX void AnimGraphManager::RecursiveCollectObjectsAffectedBy(AnimGraph* animGraph, AZStd::vector& affectedObjects) { - for (EMotionFX::AnimGraph* potentiallyAffected : mAnimGraphs) + for (EMotionFX::AnimGraph* potentiallyAffected : m_animGraphs) { if (potentiallyAffected != animGraph) // exclude the passed one since that will always be affected { @@ -326,7 +326,7 @@ namespace EMotionFX void AnimGraphManager::InvalidateInstanceUniqueDataUsingMotionSet(EMotionFX::MotionSet* motionSet) { // Update unique datas for all anim graph instances that use the given motion set. - for (EMotionFX::AnimGraphInstance* animGraphInstance : mAnimGraphInstances) + for (EMotionFX::AnimGraphInstance* animGraphInstance : m_animGraphInstances) { if (animGraphInstance->GetMotionSet() == motionSet) { diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphManager.h b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphManager.h index 55ee6599fd..acff1779bb 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphManager.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphManager.h @@ -40,7 +40,7 @@ namespace EMotionFX void Init(); - MCORE_INLINE BlendSpaceManager* GetBlendSpaceManager() const { return mBlendSpaceManager; } + MCORE_INLINE BlendSpaceManager* GetBlendSpaceManager() const { return m_blendSpaceManager; } // anim graph helper functions void AddAnimGraph(AnimGraph* setup); @@ -48,8 +48,8 @@ namespace EMotionFX bool RemoveAnimGraph(AnimGraph* animGraph, bool delFromMemory = true); void RemoveAllAnimGraphs(bool delFromMemory = true); - MCORE_INLINE size_t GetNumAnimGraphs() const { MCore::LockGuardRecursive lock(mAnimGraphLock); return mAnimGraphs.size(); } - MCORE_INLINE AnimGraph* GetAnimGraph(size_t index) const { MCore::LockGuardRecursive lock(mAnimGraphLock); return mAnimGraphs[index]; } + MCORE_INLINE size_t GetNumAnimGraphs() const { MCore::LockGuardRecursive lock(m_animGraphLock); return m_animGraphs.size(); } + MCORE_INLINE AnimGraph* GetAnimGraph(size_t index) const { MCore::LockGuardRecursive lock(m_animGraphLock); return m_animGraphs[index]; } AnimGraph* GetFirstAnimGraph() const; size_t FindAnimGraphIndex(AnimGraph* animGraph) const; @@ -64,8 +64,8 @@ namespace EMotionFX void RemoveAllAnimGraphInstances(bool delFromMemory = true); void InvalidateInstanceUniqueDataUsingMotionSet(EMotionFX::MotionSet* motionSet); - size_t GetNumAnimGraphInstances() const { MCore::LockGuardRecursive lock(mAnimGraphInstanceLock); return mAnimGraphInstances.size(); } - AnimGraphInstance* GetAnimGraphInstance(size_t index) const { MCore::LockGuardRecursive lock(mAnimGraphInstanceLock); return mAnimGraphInstances[index]; } + size_t GetNumAnimGraphInstances() const { MCore::LockGuardRecursive lock(m_animGraphInstanceLock); return m_animGraphInstances.size(); } + AnimGraphInstance* GetAnimGraphInstance(size_t index) const { MCore::LockGuardRecursive lock(m_animGraphInstanceLock); return m_animGraphInstances[index]; } size_t FindAnimGraphInstanceIndex(AnimGraphInstance* animGraphInstance) const; @@ -74,11 +74,11 @@ namespace EMotionFX void RecursiveCollectObjectsAffectedBy(AnimGraph* animGraph, AZStd::vector& affectedObjects); private: - AZStd::vector mAnimGraphs; - AZStd::vector mAnimGraphInstances; - BlendSpaceManager* mBlendSpaceManager; - mutable MCore::MutexRecursive mAnimGraphLock; - mutable MCore::MutexRecursive mAnimGraphInstanceLock; + AZStd::vector m_animGraphs; + AZStd::vector m_animGraphInstances; + BlendSpaceManager* m_blendSpaceManager; + mutable MCore::MutexRecursive m_animGraphLock; + mutable MCore::MutexRecursive m_animGraphInstanceLock; // constructor and destructor AnimGraphManager(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphMotionCondition.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphMotionCondition.cpp index 9303ea96c5..02865b044c 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphMotionCondition.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphMotionCondition.cpp @@ -67,7 +67,7 @@ namespace EMotionFX return; } - AnimGraphNode* node = mAnimGraph->RecursiveFindNodeById(m_motionNodeId); + AnimGraphNode* node = m_animGraph->RecursiveFindNodeById(m_motionNodeId); m_motionNode = azdynamic_cast(node); } @@ -145,9 +145,9 @@ namespace EMotionFX } // Update the unique data. - if (uniqueData->mMotionInstance != motionInstance) + if (uniqueData->m_motionInstance != motionInstance) { - uniqueData->mMotionInstance = motionInstance; + uniqueData->m_motionInstance = motionInstance; } // Process the condition depending on the function used. @@ -162,7 +162,7 @@ namespace EMotionFX for (size_t i = 0; i < numEvents; ++i) { const EMotionFX::EventInfo& eventInfo = eventBuffer.GetEvent(i); - const EventDataSet& eventDatas = eventInfo.mEvent->GetEventDatas(); + const EventDataSet& eventDatas = eventInfo.m_event->GetEventDatas(); size_t matches = 0; for (const EventDataPtr& checkAgainstData : m_eventDatas) @@ -314,7 +314,7 @@ namespace EMotionFX void AnimGraphMotionCondition::SetMotionNodeId(AnimGraphNodeId motionNodeId) { m_motionNodeId = motionNodeId; - if (mAnimGraph) + if (m_animGraph) { Reinit(); } @@ -403,7 +403,7 @@ namespace EMotionFX AnimGraphMotionCondition::UniqueData::UniqueData(AnimGraphObject* object, AnimGraphInstance* animGraphInstance, MotionInstance* motionInstance) : AnimGraphObjectData(object, animGraphInstance) { - mMotionInstance = motionInstance; + m_motionInstance = motionInstance; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphMotionCondition.h b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphMotionCondition.h index 3a4e1f9bc7..14e5221aec 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphMotionCondition.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphMotionCondition.h @@ -60,7 +60,7 @@ namespace EMotionFX ~UniqueData() = default; public: - MotionInstance* mMotionInstance = nullptr; + MotionInstance* m_motionInstance = nullptr; }; AnimGraphMotionCondition(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphMotionNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphMotionNode.cpp index ea3784b11c..6bcc69360b 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphMotionNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphMotionNode.cpp @@ -99,7 +99,7 @@ namespace EMotionFX bool AnimGraphMotionNode::GetIsInPlace(AnimGraphInstance* animGraphInstance) const { - EMotionFX::BlendTreeConnection* inPlaceConnection = GetInputPort(INPUTPORT_INPLACE).mConnection; + EMotionFX::BlendTreeConnection* inPlaceConnection = GetInputPort(INPUTPORT_INPLACE).m_connection; if (inPlaceConnection) { return GetInputNumberAsBool(animGraphInstance, INPUTPORT_INPLACE); @@ -110,7 +110,7 @@ namespace EMotionFX void AnimGraphMotionNode::PostUpdate(AnimGraphInstance* animGraphInstance, float timePassedInSeconds) { - if (mDisabled) + if (m_disabled) { UniqueData* uniqueData = static_cast(FindOrCreateUniqueNodeData(animGraphInstance)); RequestRefDatas(animGraphInstance); @@ -121,8 +121,8 @@ namespace EMotionFX } // update the input nodes - EMotionFX::BlendTreeConnection* playSpeedConnection = GetInputPort(INPUTPORT_PLAYSPEED).mConnection; - if (playSpeedConnection && mDisabled == false) + EMotionFX::BlendTreeConnection* playSpeedConnection = GetInputPort(INPUTPORT_PLAYSPEED).m_connection; + if (playSpeedConnection && m_disabled == false) { playSpeedConnection->GetSourceNode()->PerformPostUpdate(animGraphInstance, timePassedInSeconds); } @@ -135,8 +135,8 @@ namespace EMotionFX data->ZeroTrajectoryDelta(); // trigger the motion update - MotionInstance* motionInstance = uniqueData->mMotionInstance; - if (motionInstance && !animGraphInstance->GetIsResynced(mObjectIndex)) + MotionInstance* motionInstance = uniqueData->m_motionInstance; + if (motionInstance && !animGraphInstance->GetIsResynced(m_objectIndex)) { // update the time values and extract events into the event buffer motionInstance->SetWeight(uniqueData->GetLocalWeight()); @@ -176,9 +176,9 @@ namespace EMotionFX if (numMotions > 1) { // check if we reached the end of the motion, if so, pick a new one - if (uniqueData->mMotionInstance) + if (uniqueData->m_motionInstance) { - if (uniqueData->mMotionInstance->GetHasLooped() && m_nextMotionAfterLoop) + if (uniqueData->m_motionInstance->GetHasLooped() && m_nextMotionAfterLoop) { PickNewActiveMotion(animGraphInstance, uniqueData); } @@ -188,9 +188,9 @@ namespace EMotionFX // rewind when the weight reaches 0 when we want to if (!m_loop) { - if (uniqueData->mMotionInstance && uniqueData->GetLocalWeight() < MCore::Math::epsilon && m_rewindOnZeroWeight) + if (uniqueData->m_motionInstance && uniqueData->GetLocalWeight() < MCore::Math::epsilon && m_rewindOnZeroWeight) { - uniqueData->mMotionInstance->SetCurrentTime(0.0f); + uniqueData->m_motionInstance->SetCurrentTime(0.0f); uniqueData->SetCurrentPlayTime(0.0f); uniqueData->SetPreSyncTime(0.0f); } @@ -200,7 +200,7 @@ namespace EMotionFX HierarchicalSyncAllInputNodes(animGraphInstance, uniqueData); // top down update all incoming connections - for (BlendTreeConnection* connection : mConnections) + for (BlendTreeConnection* connection : m_connections) { connection->GetSourceNode()->PerformTopDownUpdate(animGraphInstance, timePassedInSeconds); } @@ -211,25 +211,25 @@ namespace EMotionFX void AnimGraphMotionNode::Update(AnimGraphInstance* animGraphInstance, float timePassedInSeconds) { // update the input nodes - EMotionFX::BlendTreeConnection* playSpeedConnection = GetInputPort(INPUTPORT_PLAYSPEED).mConnection; - if (playSpeedConnection && mDisabled == false) + EMotionFX::BlendTreeConnection* playSpeedConnection = GetInputPort(INPUTPORT_PLAYSPEED).m_connection; + if (playSpeedConnection && m_disabled == false) { UpdateIncomingNode(animGraphInstance, playSpeedConnection->GetSourceNode(), timePassedInSeconds); } - if (!mDisabled) + if (!m_disabled) { UpdateIncomingNode(animGraphInstance, GetInputNode(INPUTPORT_INPLACE), timePassedInSeconds); } // update the motion instance (current time etc) UniqueData* uniqueData = static_cast(FindOrCreateUniqueNodeData(animGraphInstance)); - MotionInstance* motionInstance = uniqueData->mMotionInstance; - if (motionInstance == nullptr || mDisabled) + MotionInstance* motionInstance = uniqueData->m_motionInstance; + if (motionInstance == nullptr || m_disabled) { if (GetEMotionFX().GetIsInEditorMode()) { - if (mDisabled == false) + if (m_disabled == false) { if (motionInstance == nullptr) { @@ -256,17 +256,17 @@ namespace EMotionFX uniqueData->SetPreSyncTime(motionInstance->GetCurrentTime()); // Make sure we use the correct play properties. - motionInstance->SetPlayMode(m_playInfo.mPlayMode); - motionInstance->SetRetargetingEnabled(m_playInfo.mRetarget && animGraphInstance->GetRetargetingEnabled()); - motionInstance->SetMotionEventsEnabled(m_playInfo.mEnableMotionEvents); - motionInstance->SetMirrorMotion(m_playInfo.mMirrorMotion); - motionInstance->SetEventWeightThreshold(m_playInfo.mEventWeightThreshold); - motionInstance->SetMaxLoops(m_playInfo.mNumLoops); - motionInstance->SetMotionExtractionEnabled(m_playInfo.mMotionExtractionEnabled); + motionInstance->SetPlayMode(m_playInfo.m_playMode); + motionInstance->SetRetargetingEnabled(m_playInfo.m_retarget && animGraphInstance->GetRetargetingEnabled()); + motionInstance->SetMotionEventsEnabled(m_playInfo.m_enableMotionEvents); + motionInstance->SetMirrorMotion(m_playInfo.m_mirrorMotion); + motionInstance->SetEventWeightThreshold(m_playInfo.m_eventWeightThreshold); + motionInstance->SetMaxLoops(m_playInfo.m_numLoops); + motionInstance->SetMotionExtractionEnabled(m_playInfo.m_motionExtractionEnabled); motionInstance->SetIsInPlace(GetIsInPlace(animGraphInstance)); - motionInstance->SetFreezeAtLastFrame(m_playInfo.mFreezeAtLastFrame); + motionInstance->SetFreezeAtLastFrame(m_playInfo.m_freezeAtLastFrame); - if (!animGraphInstance->GetIsObjectFlagEnabled(mObjectIndex, AnimGraphInstance::OBJECTFLAGS_SYNCED) || animGraphInstance->GetIsObjectFlagEnabled(mObjectIndex, AnimGraphInstance::OBJECTFLAGS_IS_SYNCLEADER)) + if (!animGraphInstance->GetIsObjectFlagEnabled(m_objectIndex, AnimGraphInstance::OBJECTFLAGS_SYNCED) || animGraphInstance->GetIsObjectFlagEnabled(m_objectIndex, AnimGraphInstance::OBJECTFLAGS_IS_SYNCLEADER)) { // See where we would end up when we would forward in time. const MotionInstance::PlayStateOut newPlayState = motionInstance->CalcPlayStateAfterUpdate(timePassedInSeconds); @@ -296,15 +296,15 @@ namespace EMotionFX void AnimGraphMotionNode::UpdatePlayBackInfo(AnimGraphInstance* animGraphInstance) { - m_playInfo.mPlayMode = (m_reverse) ? PLAYMODE_BACKWARD : PLAYMODE_FORWARD; - m_playInfo.mNumLoops = (m_loop) ? EMFX_LOOPFOREVER : 1; - m_playInfo.mFreezeAtLastFrame = true; - m_playInfo.mEnableMotionEvents = m_emitEvents; - m_playInfo.mMirrorMotion = m_mirrorMotion; - m_playInfo.mPlaySpeed = ExtractCustomPlaySpeed(animGraphInstance); - m_playInfo.mMotionExtractionEnabled = m_motionExtraction; - m_playInfo.mRetarget = m_retarget; - m_playInfo.mInPlace = GetIsInPlace(animGraphInstance); + m_playInfo.m_playMode = (m_reverse) ? PLAYMODE_BACKWARD : PLAYMODE_FORWARD; + m_playInfo.m_numLoops = (m_loop) ? EMFX_LOOPFOREVER : 1; + m_playInfo.m_freezeAtLastFrame = true; + m_playInfo.m_enableMotionEvents = m_emitEvents; + m_playInfo.m_mirrorMotion = m_mirrorMotion; + m_playInfo.m_playSpeed = ExtractCustomPlaySpeed(animGraphInstance); + m_playInfo.m_motionExtractionEnabled = m_motionExtraction; + m_playInfo.m_retarget = m_retarget; + m_playInfo.m_inPlace = GetIsInPlace(animGraphInstance); } @@ -326,12 +326,12 @@ namespace EMotionFX uniqueData->Clear(); // remove the motion instance if it already exists - if (uniqueData->mMotionInstance && uniqueData->mReload) + if (uniqueData->m_motionInstance && uniqueData->m_reload) { - GetMotionInstancePool().Free(uniqueData->mMotionInstance); - uniqueData->mMotionInstance = nullptr; - uniqueData->mMotionSetID = MCORE_INVALIDINDEX32; - uniqueData->mReload = false; + GetMotionInstancePool().Free(uniqueData->m_motionInstance); + uniqueData->m_motionInstance = nullptr; + uniqueData->m_motionSetId = MCORE_INVALIDINDEX32; + uniqueData->m_reload = false; } // get the motion set @@ -346,9 +346,9 @@ namespace EMotionFX } // get the motion from the motion set, load it on demand and make sure the motion loaded successfully - if (uniqueData->mActiveMotionIndex != MCORE_INVALIDINDEX32) + if (uniqueData->m_activeMotionIndex != MCORE_INVALIDINDEX32) { - motion = motionSet->RecursiveFindMotionById(GetMotionId(uniqueData->mActiveMotionIndex)); + motion = motionSet->RecursiveFindMotionById(GetMotionId(uniqueData->m_activeMotionIndex)); } if (!motion) @@ -360,12 +360,12 @@ namespace EMotionFX return nullptr; } - uniqueData->mMotionSetID = motionSet->GetID(); + uniqueData->m_motionSetId = motionSet->GetID(); // create the motion instance MotionInstance* motionInstance = GetMotionInstancePool().RequestNew(motion, actorInstance); motionInstance->InitFromPlayBackInfo(playInfo, true); - motionInstance->SetRetargetingEnabled(animGraphInstance->GetRetargetingEnabled() && playInfo.mRetarget); + motionInstance->SetRetargetingEnabled(animGraphInstance->GetRetargetingEnabled() && playInfo.m_retarget); uniqueData->SetSyncTrack(motionInstance->GetMotion()->GetEventTable()->GetSyncTrack()); uniqueData->SetIsMirrorMotion(motionInstance->GetMirrorMotion()); @@ -377,7 +377,7 @@ namespace EMotionFX motionInstance->SetWeight(1.0f, 0.0f); // update play info - uniqueData->mMotionInstance = motionInstance; + uniqueData->m_motionInstance = motionInstance; uniqueData->SetDuration(motionInstance->GetDuration()); const float curPlayTime = motionInstance->GetCurrentTime(); uniqueData->SetCurrentPlayTime(curPlayTime); @@ -395,7 +395,7 @@ namespace EMotionFX void AnimGraphMotionNode::Output(AnimGraphInstance* animGraphInstance) { // if this motion is disabled, output the bind pose - if (mDisabled) + if (m_disabled) { // request poses to use from the pool, so that all output pose ports have a valid pose to output to we reuse them using a pool system to save memory RequestPoses(animGraphInstance); @@ -406,7 +406,7 @@ namespace EMotionFX } // output the playspeed node - EMotionFX::BlendTreeConnection* playSpeedConnection = GetInputPort(INPUTPORT_PLAYSPEED).mConnection; + EMotionFX::BlendTreeConnection* playSpeedConnection = GetInputPort(INPUTPORT_PLAYSPEED).m_connection; if (playSpeedConnection) { OutputIncomingNode(animGraphInstance, playSpeedConnection->GetSourceNode()); @@ -416,14 +416,14 @@ namespace EMotionFX ActorInstance* actorInstance = animGraphInstance->GetActorInstance(); MotionInstance* motionInstance = nullptr; UniqueData* uniqueData = static_cast(FindOrCreateUniqueNodeData(animGraphInstance)); - if (uniqueData->mReload) + if (uniqueData->m_reload) { motionInstance = CreateMotionInstance(actorInstance, uniqueData); - uniqueData->mReload = false; + uniqueData->m_reload = false; } else { - motionInstance = uniqueData->mMotionInstance; + motionInstance = uniqueData->m_motionInstance; } // update the motion instance output port @@ -448,7 +448,7 @@ namespace EMotionFX SetHasError(uniqueData, false); } - EMotionFX::BlendTreeConnection* inPlaceConnection = GetInputPort(INPUTPORT_INPLACE).mConnection; + EMotionFX::BlendTreeConnection* inPlaceConnection = GetInputPort(INPUTPORT_INPLACE).m_connection; if (inPlaceConnection) { OutputIncomingNode(animGraphInstance, inPlaceConnection->GetSourceNode()); @@ -477,7 +477,7 @@ namespace EMotionFX // visualize it if (GetEMotionFX().GetIsInEditorMode() && GetCanVisualize(animGraphInstance)) { - actorInstance->DrawSkeleton(outputPose->GetPose(), mVisualizeColor); + actorInstance->DrawSkeleton(outputPose->GetPose(), m_visualizeColor); } } @@ -486,7 +486,7 @@ namespace EMotionFX MotionInstance* AnimGraphMotionNode::FindMotionInstance(AnimGraphInstance* animGraphInstance) const { UniqueData* uniqueData = static_cast(animGraphInstance->FindOrCreateUniqueObjectData(this)); - return uniqueData->mMotionInstance; + return uniqueData->m_motionInstance; } @@ -495,9 +495,9 @@ namespace EMotionFX { UniqueData* uniqueData = static_cast(animGraphInstance->FindOrCreateUniqueObjectData(this)); uniqueData->SetCurrentPlayTime(timeInSeconds); - if (uniqueData->mMotionInstance) + if (uniqueData->m_motionInstance) { - uniqueData->mMotionInstance->SetCurrentTime(timeInSeconds); + uniqueData->m_motionInstance->SetCurrentTime(timeInSeconds); } } @@ -510,26 +510,26 @@ namespace EMotionFX AnimGraphMotionNode::UniqueData::~UniqueData() { - GetMotionInstancePool().Free(mMotionInstance); + GetMotionInstancePool().Free(m_motionInstance); } void AnimGraphMotionNode::UniqueData::Reset() { // stop and delete the motion instance - if (mMotionInstance) + if (m_motionInstance) { - mMotionInstance->Stop(0.0f); - GetMotionInstancePool().Free(mMotionInstance); + m_motionInstance->Stop(0.0f); + GetMotionInstancePool().Free(m_motionInstance); } // reset the unique data - mMotionSetID = MCORE_INVALIDINDEX32; - mMotionInstance = nullptr; - mReload = true; - mPlaySpeed = 1.0f; - mCurrentTime = 0.0f; - mDuration = 0.0f; - mActiveMotionIndex = MCORE_INVALIDINDEX32; + m_motionSetId = MCORE_INVALIDINDEX32; + m_motionInstance = nullptr; + m_reload = true; + m_playSpeed = 1.0f; + m_currentTime = 0.0f; + m_duration = 0.0f; + m_activeMotionIndex = MCORE_INVALIDINDEX32; SetSyncTrack(nullptr); Invalidate(); @@ -537,13 +537,13 @@ namespace EMotionFX void AnimGraphMotionNode::UniqueData::Update() { - AnimGraphMotionNode* motionNode = azdynamic_cast(mObject); + AnimGraphMotionNode* motionNode = azdynamic_cast(m_object); AZ_Assert(motionNode, "Unique data linked to incorrect node type."); AnimGraphInstance* animGraphInstance = GetAnimGraphInstance(); motionNode->PickNewActiveMotion(animGraphInstance, this); - if (!mMotionInstance) + if (!m_motionInstance) { motionNode->CreateMotionInstance(animGraphInstance->GetActorInstance(), this); } @@ -560,9 +560,9 @@ namespace EMotionFX motionNode->UpdatePlayBackInfo(animGraphInstance); // update play info - if (mMotionInstance) + if (m_motionInstance) { - MotionInstance* motionInstance = mMotionInstance; + MotionInstance* motionInstance = m_motionInstance; const float currentTime = motionInstance->GetCurrentTime(); SetDuration(motionInstance->GetDuration()); SetCurrentPlayTime(currentTime); @@ -575,7 +575,7 @@ namespace EMotionFX // this function will get called to rewind motion nodes as well as states etc. to reset several settings when a state gets exited void AnimGraphMotionNode::Rewind(AnimGraphInstance* animGraphInstance) { - UniqueData* uniqueData = static_cast(animGraphInstance->GetUniqueObjectData(mObjectIndex)); + UniqueData* uniqueData = static_cast(animGraphInstance->GetUniqueObjectData(m_objectIndex)); // rewind is not necessary if unique data is not created yet if (!uniqueData) @@ -584,7 +584,7 @@ namespace EMotionFX } // find the motion instance for the given anim graph and return directly in case it is invalid - MotionInstance* motionInstance = uniqueData->mMotionInstance; + MotionInstance* motionInstance = uniqueData->m_motionInstance; if (motionInstance == nullptr) { return; @@ -605,7 +605,7 @@ namespace EMotionFX // get the speed from the connection if there is one connected, if not use the node's playspeed float AnimGraphMotionNode::ExtractCustomPlaySpeed(AnimGraphInstance* animGraphInstance) const { - EMotionFX::BlendTreeConnection* playSpeedConnection = GetInputPort(INPUTPORT_PLAYSPEED).mConnection; + EMotionFX::BlendTreeConnection* playSpeedConnection = GetInputPort(INPUTPORT_PLAYSPEED).m_connection; // if there is a node connected to the speed input port, read that value and use it as internal speed float customSpeed; @@ -638,23 +638,23 @@ namespace EMotionFX const size_t numMotions = m_motionRandomSelectionCumulativeWeights.size(); if (numMotions == 1) { - uniqueData->mActiveMotionIndex = 0; + uniqueData->m_activeMotionIndex = 0; } else if (numMotions > 1) { - uniqueData->mReload = true; + uniqueData->m_reload = true; switch (m_indexMode) { // pick a random one, but make sure its not the same as the last one we played case INDEXMODE_RANDOMIZE_NOREPEAT: { - if (uniqueData->mActiveMotionIndex == MCORE_INVALIDINDEX32) + if (uniqueData->m_activeMotionIndex == MCORE_INVALIDINDEX32) { SelectAnyRandomMotionIndex(animGraphInstance, uniqueData); return; } - AZ::u32 curIndex = uniqueData->mActiveMotionIndex; + AZ::u32 curIndex = uniqueData->m_activeMotionIndex; // Make sure we're in a valid range. if (curIndex >= numMotions) @@ -677,17 +677,17 @@ namespace EMotionFX } const int index = FindCumulativeProbabilityIndex(remappedRandomValue); AZ_Assert(index >= 0, "Unable to find random value in motion random weights"); - uniqueData->mActiveMotionIndex = index; + uniqueData->m_activeMotionIndex = index; } break; // pick the next motion from the list case INDEXMODE_SEQUENTIAL: { - uniqueData->mActiveMotionIndex++; - if (uniqueData->mActiveMotionIndex >= numMotions) + uniqueData->m_activeMotionIndex++; + if (uniqueData->m_activeMotionIndex >= numMotions) { - uniqueData->mActiveMotionIndex = 0; + uniqueData->m_activeMotionIndex = 0; } } break; @@ -702,7 +702,7 @@ namespace EMotionFX } else { - uniqueData->mActiveMotionIndex = MCORE_INVALIDINDEX32; + uniqueData->m_activeMotionIndex = MCORE_INVALIDINDEX32; } } @@ -712,7 +712,7 @@ namespace EMotionFX const float randomValue = animGraphInstance->GetLcgRandom().GetRandomFloat() * m_motionRandomSelectionCumulativeWeights.back().second; const int index = FindCumulativeProbabilityIndex(randomValue); AZ_Assert(index >= 0, "Error: unable to find random value among motion random weights"); - uniqueData->mActiveMotionIndex = index; + uniqueData->m_activeMotionIndex = index; } int AnimGraphMotionNode::FindCumulativeProbabilityIndex(float randomValue) const @@ -777,19 +777,19 @@ namespace EMotionFX void AnimGraphMotionNode::ReloadAndInvalidateUniqueDatas() { - if (!mAnimGraph) + if (!m_animGraph) { return; } - const size_t numAnimGraphInstances = mAnimGraph->GetNumAnimGraphInstances(); + const size_t numAnimGraphInstances = m_animGraph->GetNumAnimGraphInstances(); for (size_t i = 0; i < numAnimGraphInstances; ++i) { - AnimGraphInstance* animGraphInstance = mAnimGraph->GetAnimGraphInstance(i); - UniqueData* uniqueData = static_cast(animGraphInstance->GetUniqueObjectData(mObjectIndex)); + AnimGraphInstance* animGraphInstance = m_animGraph->GetAnimGraphInstance(i); + UniqueData* uniqueData = static_cast(animGraphInstance->GetUniqueObjectData(m_objectIndex)); if (uniqueData) { - uniqueData->mReload = true; + uniqueData->m_reload = true; uniqueData->Invalidate(); } } @@ -803,10 +803,10 @@ namespace EMotionFX void AnimGraphMotionNode::RecursiveOnChangeMotionSet(AnimGraphInstance* animGraphInstance, MotionSet* newMotionSet) { AnimGraphNode::RecursiveOnChangeMotionSet(animGraphInstance, newMotionSet); - UniqueData* uniqueData = static_cast(animGraphInstance->GetUniqueObjectData(mObjectIndex)); + UniqueData* uniqueData = static_cast(animGraphInstance->GetUniqueObjectData(m_objectIndex)); if (uniqueData) { - uniqueData->mReload = true; + uniqueData->m_reload = true; uniqueData->Invalidate(); } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphMotionNode.h b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphMotionNode.h index ab6e4bef62..a07bbc625c 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphMotionNode.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphMotionNode.h @@ -72,10 +72,10 @@ namespace EMotionFX void Update() override; public: - uint32 mMotionSetID = InvalidIndex32; - uint32 mActiveMotionIndex = InvalidIndex32; - MotionInstance* mMotionInstance = nullptr; - bool mReload = false; + uint32 m_motionSetId = InvalidIndex32; + uint32 m_activeMotionIndex = InvalidIndex32; + MotionInstance* m_motionInstance = nullptr; + bool m_reload = false; }; AnimGraphMotionNode(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNode.cpp index 67c3f276cc..be5499627d 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNode.cpp @@ -50,17 +50,17 @@ namespace EMotionFX AnimGraphNode::AnimGraphNode() : AnimGraphObject(nullptr) , m_id(AnimGraphNodeId::Create()) - , mNodeIndex(InvalidIndex) - , mDisabled(false) - , mParentNode(nullptr) - , mCustomData(nullptr) - , mVisEnabled(false) - , mIsCollapsed(false) - , mPosX(0) - , mPosY(0) + , m_nodeIndex(InvalidIndex) + , m_disabled(false) + , m_parentNode(nullptr) + , m_customData(nullptr) + , m_visEnabled(false) + , m_isCollapsed(false) + , m_posX(0) + , m_posY(0) { const AZ::u32 col = MCore::GenerateColor(); - mVisualizeColor = AZ::Color( + m_visualizeColor = AZ::Color( MCore::ExtractRed(col)/255.0f, MCore::ExtractGreen(col)/255.0f, MCore::ExtractBlue(col)/255.0f, @@ -81,21 +81,21 @@ namespace EMotionFX RemoveAllConnections(); RemoveAllChildNodes(); - if (mAnimGraph) + if (m_animGraph) { - mAnimGraph->RemoveObject(this); + m_animGraph->RemoveObject(this); } } void AnimGraphNode::RecursiveReinit() { - for (BlendTreeConnection* connection : mConnections) + for (BlendTreeConnection* connection : m_connections) { connection->Reinit(); } - for (AnimGraphNode* childNode : mChildNodes) + for (AnimGraphNode* childNode : m_childNodes) { childNode->RecursiveReinit(); } @@ -113,13 +113,13 @@ namespace EMotionFX } // Initialize connections. - for (BlendTreeConnection* connection : mConnections) + for (BlendTreeConnection* connection : m_connections) { connection->InitAfterLoading(animGraph); } // Initialize child nodes. - for (AnimGraphNode* childNode : mChildNodes) + for (AnimGraphNode* childNode : m_childNodes) { // Sync the child node's parent. childNode->SetParentNode(this); @@ -140,7 +140,7 @@ namespace EMotionFX { for (AnimGraphTriggerAction* action : m_actionSetup.GetActions()) { - action->InitAfterLoading(mAnimGraph); + action->InitAfterLoading(m_animGraph); } } @@ -148,35 +148,27 @@ namespace EMotionFX // copy base settings to the other node void AnimGraphNode::CopyBaseNodeTo(AnimGraphNode* node) const { - //CopyBaseObjectTo( node ); - - // now copy the node related things - // the parent - //if (mParentNode) - //node->mParentNode = node->GetAnimGraph()->RecursiveFindNodeByID( mParentNode->GetID() ); - - // copy the easy values node->m_name = m_name; node->m_id = m_id; - node->mNodeInfo = mNodeInfo; - node->mCustomData = mCustomData; - node->mDisabled = mDisabled; - node->mPosX = mPosX; - node->mPosY = mPosY; - node->mVisualizeColor = mVisualizeColor; - node->mVisEnabled = mVisEnabled; - node->mIsCollapsed = mIsCollapsed; + node->m_nodeInfo = m_nodeInfo; + node->m_customData = m_customData; + node->m_disabled = m_disabled; + node->m_posX = m_posX; + node->m_posY = m_posY; + node->m_visualizeColor = m_visualizeColor; + node->m_visEnabled = m_visEnabled; + node->m_isCollapsed = m_isCollapsed; } void AnimGraphNode::RemoveAllConnections() { - for (BlendTreeConnection* connection : mConnections) + for (BlendTreeConnection* connection : m_connections) { delete connection; } - mConnections.clear(); + m_connections.clear(); } @@ -184,12 +176,12 @@ namespace EMotionFX BlendTreeConnection* AnimGraphNode::AddConnection(AnimGraphNode* sourceNode, uint16 sourcePort, uint16 targetPort) { // make sure the source and target ports are in range - if (targetPort < mInputPorts.size() && sourcePort < sourceNode->mOutputPorts.size()) + if (targetPort < m_inputPorts.size() && sourcePort < sourceNode->m_outputPorts.size()) { BlendTreeConnection* connection = aznew BlendTreeConnection(sourceNode, sourcePort, targetPort); - mConnections.push_back(connection); - mInputPorts[targetPort].mConnection = connection; - sourceNode->mOutputPorts[sourcePort].mConnection = connection; + m_connections.push_back(connection); + m_inputPorts[targetPort].m_connection = connection; + sourceNode->m_outputPorts[sourcePort].m_connection = connection; return connection; } return nullptr; @@ -199,7 +191,7 @@ namespace EMotionFX BlendTreeConnection* AnimGraphNode::AddUnitializedConnection(AnimGraphNode* sourceNode, uint16 sourcePort, uint16 targetPort) { BlendTreeConnection* connection = aznew BlendTreeConnection(sourceNode, sourcePort, targetPort); - mConnections.push_back(connection); + m_connections.push_back(connection); return connection; } @@ -207,7 +199,7 @@ namespace EMotionFX // validate the connections bool AnimGraphNode::ValidateConnections() const { - for (const BlendTreeConnection* connection : mConnections) + for (const BlendTreeConnection* connection : m_connections) { if (!connection->GetIsValid()) { @@ -222,7 +214,7 @@ namespace EMotionFX // check if the given input port is connected bool AnimGraphNode::CheckIfIsInputPortConnected(uint16 inputPort) const { - for (const BlendTreeConnection* connection : mConnections) + for (const BlendTreeConnection* connection : m_connections) { if (connection->GetTargetPort() == inputPort) { @@ -240,16 +232,16 @@ namespace EMotionFX { if (delFromMem) { - for (AnimGraphNode* childNode : mChildNodes) + for (AnimGraphNode* childNode : m_childNodes) { delete childNode; } } - mChildNodes.clear(); + m_childNodes.clear(); // trigger that we removed nodes - GetEventManager().OnRemovedChildNode(mAnimGraph, this); + GetEventManager().OnRemovedChildNode(m_animGraph, this); // TODO: remove the nodes from the node groups of the anim graph as well here } @@ -259,23 +251,23 @@ namespace EMotionFX void AnimGraphNode::RemoveChildNode(size_t index, bool delFromMem) { // remove the node from its node group - AnimGraphNodeGroup* nodeGroup = mAnimGraph->FindNodeGroupForNode(mChildNodes[index]); + AnimGraphNodeGroup* nodeGroup = m_animGraph->FindNodeGroupForNode(m_childNodes[index]); if (nodeGroup) { - nodeGroup->RemoveNodeById(mChildNodes[index]->GetId()); + nodeGroup->RemoveNodeById(m_childNodes[index]->GetId()); } // delete the node from memory if (delFromMem) { - delete mChildNodes[index]; + delete m_childNodes[index]; } // delete the node from the child array - mChildNodes.erase(mChildNodes.begin() + index); + m_childNodes.erase(m_childNodes.begin() + index); // trigger callbacks - GetEventManager().OnRemovedChildNode(mAnimGraph, this); + GetEventManager().OnRemovedChildNode(m_animGraph, this); } @@ -283,11 +275,11 @@ namespace EMotionFX void AnimGraphNode::RemoveChildNodeByPointer(AnimGraphNode* node, bool delFromMem) { // find the index of the given node in the child node array and remove it in case the index is valid - const auto iterator = AZStd::find(mChildNodes.begin(), mChildNodes.end(), node); + const auto iterator = AZStd::find(m_childNodes.begin(), m_childNodes.end(), node); - if (iterator != mChildNodes.end()) + if (iterator != m_childNodes.end()) { - const size_t index = AZStd::distance(mChildNodes.begin(), iterator); + const size_t index = AZStd::distance(m_childNodes.begin(), iterator); RemoveChildNode(index, delFromMem); } } @@ -300,7 +292,7 @@ namespace EMotionFX return const_cast(this); } - for (const AnimGraphNode* childNode : mChildNodes) + for (const AnimGraphNode* childNode : m_childNodes) { AnimGraphNode* result = childNode->RecursiveFindNodeByName(nodeName); if (result) @@ -320,7 +312,7 @@ namespace EMotionFX return false; } - for (const AnimGraphNode* childNode : mChildNodes) + for (const AnimGraphNode* childNode : m_childNodes) { if (!childNode->RecursiveIsNodeNameUnique(newNameCandidate, forNode)) { @@ -339,7 +331,7 @@ namespace EMotionFX return const_cast(this); } - for (const AnimGraphNode* childNode : mChildNodes) + for (const AnimGraphNode* childNode : m_childNodes) { AnimGraphNode* result = childNode->RecursiveFindNodeById(nodeId); if (result) @@ -355,7 +347,7 @@ namespace EMotionFX // find a child node by name AnimGraphNode* AnimGraphNode::FindChildNode(const char* name) const { - for (AnimGraphNode* childNode : mChildNodes) + for (AnimGraphNode* childNode : m_childNodes) { // compare the node name with the parameter and return a pointer to the node in case they are equal if (AzFramework::StringFunc::Equal(childNode->GetName(), name, true /* case sensitive */)) @@ -371,7 +363,7 @@ namespace EMotionFX AnimGraphNode* AnimGraphNode::FindChildNodeById(AnimGraphNodeId childId) const { - for (AnimGraphNode* childNode : mChildNodes) + for (AnimGraphNode* childNode : m_childNodes) { if (childNode->GetId() == childId) { @@ -386,35 +378,35 @@ namespace EMotionFX // find a child node index by name size_t AnimGraphNode::FindChildNodeIndex(const char* name) const { - const auto foundChildNode = AZStd::find_if(begin(mChildNodes), end(mChildNodes), [name](const AnimGraphNode* childNode) + const auto foundChildNode = AZStd::find_if(begin(m_childNodes), end(m_childNodes), [name](const AnimGraphNode* childNode) { return childNode->GetNameString() == name; }); - return foundChildNode != end(mChildNodes) ? AZStd::distance(begin(mChildNodes), foundChildNode) : InvalidIndex; + return foundChildNode != end(m_childNodes) ? AZStd::distance(begin(m_childNodes), foundChildNode) : InvalidIndex; } // find a child node index size_t AnimGraphNode::FindChildNodeIndex(AnimGraphNode* node) const { - const auto foundChildNode = AZStd::find(mChildNodes.begin(), mChildNodes.end(), node); - return foundChildNode != end(mChildNodes) ? AZStd::distance(begin(mChildNodes), foundChildNode) : InvalidIndex; + const auto foundChildNode = AZStd::find(m_childNodes.begin(), m_childNodes.end(), node); + return foundChildNode != end(m_childNodes) ? AZStd::distance(begin(m_childNodes), foundChildNode) : InvalidIndex; } AnimGraphNode* AnimGraphNode::FindFirstChildNodeOfType(const AZ::TypeId& nodeType) const { - const auto foundChild = AZStd::find_if(begin(mChildNodes), end(mChildNodes), [nodeType](const AnimGraphNode* childNode) + const auto foundChild = AZStd::find_if(begin(m_childNodes), end(m_childNodes), [nodeType](const AnimGraphNode* childNode) { return azrtti_typeid(childNode) == nodeType; }); - return foundChild != end(mChildNodes) ? *foundChild : nullptr; + return foundChild != end(m_childNodes) ? *foundChild : nullptr; } bool AnimGraphNode::HasChildNodeOfType(const AZ::TypeId& nodeType) const { - return AZStd::any_of(begin(mChildNodes), end(mChildNodes), [nodeType](const AnimGraphNode* childNode) + return AZStd::any_of(begin(m_childNodes), end(m_childNodes), [nodeType](const AnimGraphNode* childNode) { return azrtti_typeid(childNode) == nodeType; }); @@ -424,7 +416,7 @@ namespace EMotionFX // does this node has a specific incoming connection? bool AnimGraphNode::GetHasConnection(AnimGraphNode* sourceNode, uint16 sourcePort, uint16 targetPort) const { - return AZStd::any_of(begin(mConnections), end(mConnections), [sourceNode, sourcePort, targetPort](const BlendTreeConnection* connection) + return AZStd::any_of(begin(m_connections), end(m_connections), [sourceNode, sourcePort, targetPort](const BlendTreeConnection* connection) { return connection->GetSourceNode() == sourceNode && connection->GetSourcePort() == sourcePort && connection->GetTargetPort() == targetPort; }); @@ -433,16 +425,16 @@ namespace EMotionFX // remove a given connection void AnimGraphNode::RemoveConnection(BlendTreeConnection* connection, bool delFromMem) { - mInputPorts[connection->GetTargetPort()].mConnection = nullptr; + m_inputPorts[connection->GetTargetPort()].m_connection = nullptr; AnimGraphNode* sourceNode = connection->GetSourceNode(); if (sourceNode) { - sourceNode->mOutputPorts[connection->GetSourcePort()].mConnection = nullptr; + sourceNode->m_outputPorts[connection->GetSourcePort()].m_connection = nullptr; } // Remove object by value. - mConnections.erase(AZStd::remove(mConnections.begin(), mConnections.end(), connection), mConnections.end()); + m_connections.erase(AZStd::remove(m_connections.begin(), m_connections.end(), connection), m_connections.end()); if (delFromMem) { delete connection; @@ -454,7 +446,7 @@ namespace EMotionFX void AnimGraphNode::RemoveConnection(AnimGraphNode* sourceNode, uint16 sourcePort, uint16 targetPort) { // for all input connections - for (BlendTreeConnection* connection : mConnections) + for (BlendTreeConnection* connection : m_connections) { if (connection->GetSourceNode() == sourceNode && connection->GetSourcePort() == sourcePort && connection->GetTargetPort() == targetPort) { @@ -467,25 +459,25 @@ namespace EMotionFX bool AnimGraphNode::RemoveConnectionById(AnimGraphConnectionId connectionId, bool delFromMem) { - const size_t numConnections = mConnections.size(); + const size_t numConnections = m_connections.size(); for (size_t i = 0; i < numConnections; ++i) { - if (mConnections[i]->GetId() == connectionId) + if (m_connections[i]->GetId() == connectionId) { - mInputPorts[mConnections[i]->GetTargetPort()].mConnection = nullptr; + m_inputPorts[m_connections[i]->GetTargetPort()].m_connection = nullptr; - AnimGraphNode* sourceNode = mConnections[i]->GetSourceNode(); + AnimGraphNode* sourceNode = m_connections[i]->GetSourceNode(); if (sourceNode) { - sourceNode->mOutputPorts[mConnections[i]->GetSourcePort()].mConnection = nullptr; + sourceNode->m_outputPorts[m_connections[i]->GetSourcePort()].m_connection = nullptr; } if (delFromMem) { - delete mConnections[i]; + delete m_connections[i]; } - mConnections.erase(mConnections.begin() + i); + m_connections.erase(m_connections.begin() + i); } } @@ -496,7 +488,7 @@ namespace EMotionFX // find a given connection BlendTreeConnection* AnimGraphNode::FindConnection(const AnimGraphNode* sourceNode, uint16 sourcePort, uint16 targetPort) const { - for (BlendTreeConnection* connection : mConnections) + for (BlendTreeConnection* connection : m_connections) { if (connection->GetSourceNode() == sourceNode && connection->GetSourcePort() == sourcePort && connection->GetTargetPort() == targetPort) { @@ -512,44 +504,44 @@ namespace EMotionFX // initialize the input ports void AnimGraphNode::InitInputPorts(size_t numPorts) { - mInputPorts.resize(numPorts); + m_inputPorts.resize(numPorts); } // initialize the output ports void AnimGraphNode::InitOutputPorts(size_t numPorts) { - mOutputPorts.resize(numPorts); + m_outputPorts.resize(numPorts); } // find a given output port number size_t AnimGraphNode::FindOutputPortIndex(const AZStd::string& name) const { - const auto foundPort = AZStd::find_if(begin(mOutputPorts), end(mOutputPorts), [&name](const Port& port) + const auto foundPort = AZStd::find_if(begin(m_outputPorts), end(m_outputPorts), [&name](const Port& port) { return port.GetNameString() == name; }); - return foundPort != end(mOutputPorts) ? AZStd::distance(begin(mOutputPorts), foundPort) : InvalidIndex; + return foundPort != end(m_outputPorts) ? AZStd::distance(begin(m_outputPorts), foundPort) : InvalidIndex; } // find a given input port number size_t AnimGraphNode::FindInputPortIndex(const AZStd::string& name) const { - const auto foundPort = AZStd::find_if(begin(mInputPorts), end(mInputPorts), [&name](const Port& port) + const auto foundPort = AZStd::find_if(begin(m_inputPorts), end(m_inputPorts), [&name](const Port& port) { return port.GetNameString() == name; }); - return foundPort != end(mInputPorts) ? AZStd::distance(begin(mInputPorts), foundPort) : InvalidIndex; + return foundPort != end(m_inputPorts) ? AZStd::distance(begin(m_inputPorts), foundPort) : InvalidIndex; } // add an output port and return its index size_t AnimGraphNode::AddOutputPort() { - const size_t currentSize = mOutputPorts.size(); - mOutputPorts.emplace_back(); + const size_t currentSize = m_outputPorts.size(); + m_outputPorts.emplace_back(); return currentSize; } @@ -557,8 +549,8 @@ namespace EMotionFX // add an input port, and return its index size_t AnimGraphNode::AddInputPort() { - const size_t currentSize = mInputPorts.size(); - mInputPorts.emplace_back(); + const size_t currentSize = m_inputPorts.size(); + m_inputPorts.emplace_back(); return static_cast(currentSize); } @@ -566,16 +558,16 @@ namespace EMotionFX // setup a port name void AnimGraphNode::SetInputPortName(size_t portIndex, const char* name) { - MCORE_ASSERT(portIndex < mInputPorts.size()); - mInputPorts[portIndex].mNameID = MCore::GetStringIdPool().GenerateIdForString(name); + MCORE_ASSERT(portIndex < m_inputPorts.size()); + m_inputPorts[portIndex].m_nameId = MCore::GetStringIdPool().GenerateIdForString(name); } // setup a port name void AnimGraphNode::SetOutputPortName(size_t portIndex, const char* name) { - MCORE_ASSERT(portIndex < mOutputPorts.size()); - mOutputPorts[portIndex].mNameID = MCore::GetStringIdPool().GenerateIdForString(name); + MCORE_ASSERT(portIndex < m_outputPorts.size()); + m_outputPorts[portIndex].m_nameId = MCore::GetStringIdPool().GenerateIdForString(name); } @@ -583,7 +575,7 @@ namespace EMotionFX size_t AnimGraphNode::RecursiveCalcNumNodes() const { size_t result = 0; - for (const AnimGraphNode* childNode : mChildNodes) + for (const AnimGraphNode* childNode : m_childNodes) { childNode->RecursiveCountChildNodes(result); } @@ -598,7 +590,7 @@ namespace EMotionFX // increase the counter numNodes++; - for (const AnimGraphNode* childNode : mChildNodes) + for (const AnimGraphNode* childNode : m_childNodes) { childNode->RecursiveCountChildNodes(numNodes); } @@ -620,7 +612,7 @@ namespace EMotionFX // add the connections to our counter numConnections += GetNumConnections(); - for (const AnimGraphNode* childNode : mChildNodes) + for (const AnimGraphNode* childNode : m_childNodes) { childNode->RecursiveCountNodeConnections(numConnections); } @@ -634,13 +626,13 @@ namespace EMotionFX const size_t duplicatePort = FindOutputPortByID(portID); if (duplicatePort != InvalidIndex) { - MCore::LogError("EMotionFX::AnimGraphNode::SetOutputPortAsPose() - There is already a port with the same ID (portID=%d existingPort='%s' newPort='%s' node='%s')", portID, mOutputPorts[duplicatePort].GetName(), name, RTTI_GetTypeName()); + MCore::LogError("EMotionFX::AnimGraphNode::SetOutputPortAsPose() - There is already a port with the same ID (portID=%d existingPort='%s' newPort='%s' node='%s')", portID, m_outputPorts[duplicatePort].GetName(), name, RTTI_GetTypeName()); } SetOutputPortName(outputPortNr, name); - mOutputPorts[outputPortNr].Clear(); - mOutputPorts[outputPortNr].mCompatibleTypes[0] = AttributePose::TYPE_ID; // setup the compatible types of this port - mOutputPorts[outputPortNr].mPortID = portID; + m_outputPorts[outputPortNr].Clear(); + m_outputPorts[outputPortNr].m_compatibleTypes[0] = AttributePose::TYPE_ID; // setup the compatible types of this port + m_outputPorts[outputPortNr].m_portId = portID; } @@ -651,13 +643,13 @@ namespace EMotionFX const size_t duplicatePort = FindOutputPortByID(portID); if (duplicatePort != InvalidIndex) { - MCore::LogError("EMotionFX::AnimGraphNode::SetOutputPortAsMotionInstance() - There is already a port with the same ID (portID=%d existingPort='%s' newPort='%s' node='%s')", portID, mOutputPorts[duplicatePort].GetName(), name, RTTI_GetTypeName()); + MCore::LogError("EMotionFX::AnimGraphNode::SetOutputPortAsMotionInstance() - There is already a port with the same ID (portID=%d existingPort='%s' newPort='%s' node='%s')", portID, m_outputPorts[duplicatePort].GetName(), name, RTTI_GetTypeName()); } SetOutputPortName(outputPortNr, name); - mOutputPorts[outputPortNr].Clear(); - mOutputPorts[outputPortNr].mCompatibleTypes[0] = AttributeMotionInstance::TYPE_ID; // setup the compatible types of this port - mOutputPorts[outputPortNr].mPortID = portID; + m_outputPorts[outputPortNr].Clear(); + m_outputPorts[outputPortNr].m_compatibleTypes[0] = AttributeMotionInstance::TYPE_ID; // setup the compatible types of this port + m_outputPorts[outputPortNr].m_portId = portID; } @@ -668,13 +660,13 @@ namespace EMotionFX const size_t duplicatePort = FindOutputPortByID(portID); if (duplicatePort != InvalidIndex) { - MCore::LogError("EMotionFX::AnimGraphNode::SetOutputPort() - There is already a port with the same ID (portID=%d existingPort='%s' newPort='%s' name='%s')", portID, mOutputPorts[duplicatePort].GetName(), name, RTTI_GetTypeName()); + MCore::LogError("EMotionFX::AnimGraphNode::SetOutputPort() - There is already a port with the same ID (portID=%d existingPort='%s' newPort='%s' name='%s')", portID, m_outputPorts[duplicatePort].GetName(), name, RTTI_GetTypeName()); } SetOutputPortName(outputPortNr, name); - mOutputPorts[outputPortNr].Clear(); - mOutputPorts[outputPortNr].mCompatibleTypes[0] = attributeTypeID; - mOutputPorts[outputPortNr].mPortID = portID; + m_outputPorts[outputPortNr].Clear(); + m_outputPorts[outputPortNr].m_compatibleTypes[0] = attributeTypeID; + m_outputPorts[outputPortNr].m_portId = portID; } void AnimGraphNode::SetupInputPortAsVector3(const char* name, size_t inputPortNr, uint32 portID) @@ -698,13 +690,13 @@ namespace EMotionFX const size_t duplicatePort = FindInputPortByID(portID); if (duplicatePort != InvalidIndex) { - MCore::LogError("EMotionFX::AnimGraphNode::SetInputPortAsNumber() - There is already a port with the same ID (portID=%d existingPort='%s' newPort='%s' node='%s')", portID, MCore::GetStringIdPool().GetName(mInputPorts[duplicatePort].mNameID).c_str(), name, RTTI_GetTypeName()); + MCore::LogError("EMotionFX::AnimGraphNode::SetInputPortAsNumber() - There is already a port with the same ID (portID=%d existingPort='%s' newPort='%s' node='%s')", portID, MCore::GetStringIdPool().GetName(m_inputPorts[duplicatePort].m_nameId).c_str(), name, RTTI_GetTypeName()); } SetInputPortName(inputPortNr, name); - mInputPorts[inputPortNr].Clear(); - mInputPorts[inputPortNr].mPortID = portID; - mInputPorts[inputPortNr].SetCompatibleTypes(attributeTypeIDs); + m_inputPorts[inputPortNr].Clear(); + m_inputPorts[inputPortNr].m_portId = portID; + m_inputPorts[inputPortNr].SetCompatibleTypes(attributeTypeIDs); } // setup an input port as a number (float/int/bool) @@ -714,15 +706,13 @@ namespace EMotionFX const size_t duplicatePort = FindInputPortByID(portID); if (duplicatePort != InvalidIndex) { - MCore::LogError("EMotionFX::AnimGraphNode::SetInputPortAsNumber() - There is already a port with the same ID (portID=%d existingPort='%s' newPort='%s' node='%s')", portID, mInputPorts[duplicatePort].GetName(), name, RTTI_GetTypeName()); + MCore::LogError("EMotionFX::AnimGraphNode::SetInputPortAsNumber() - There is already a port with the same ID (portID=%d existingPort='%s' newPort='%s' node='%s')", portID, m_inputPorts[duplicatePort].GetName(), name, RTTI_GetTypeName()); } SetInputPortName(inputPortNr, name); - mInputPorts[inputPortNr].Clear(); - mInputPorts[inputPortNr].mCompatibleTypes[0] = MCore::AttributeFloat::TYPE_ID; - //mInputPorts[inputPortNr].mCompatibleTypes[1] = MCore::AttributeInt32::TYPE_ID; - //mInputPorts[inputPortNr].mCompatibleTypes[2] = MCore::AttributeBool::TYPE_ID;; - mInputPorts[inputPortNr].mPortID = portID; + m_inputPorts[inputPortNr].Clear(); + m_inputPorts[inputPortNr].m_compatibleTypes[0] = MCore::AttributeFloat::TYPE_ID; + m_inputPorts[inputPortNr].m_portId = portID; } void AnimGraphNode::SetupInputPortAsBool(const char* name, size_t inputPortNr, uint32 portID) @@ -731,15 +721,15 @@ namespace EMotionFX const size_t duplicatePort = FindInputPortByID(portID); if (duplicatePort != InvalidIndex) { - MCore::LogError("EMotionFX::AnimGraphNode::SetInputPortAsBool() - There is already a port with the same ID (portID=%d existingPort='%s' newPort='%s' node='%s')", portID, mInputPorts[duplicatePort].GetName(), name, RTTI_GetTypeName()); + MCore::LogError("EMotionFX::AnimGraphNode::SetInputPortAsBool() - There is already a port with the same ID (portID=%d existingPort='%s' newPort='%s' node='%s')", portID, m_inputPorts[duplicatePort].GetName(), name, RTTI_GetTypeName()); } SetInputPortName(inputPortNr, name); - mInputPorts[inputPortNr].Clear(); - mInputPorts[inputPortNr].mCompatibleTypes[0] = MCore::AttributeBool::TYPE_ID; - mInputPorts[inputPortNr].mCompatibleTypes[1] = MCore::AttributeFloat::TYPE_ID;; - mInputPorts[inputPortNr].mCompatibleTypes[2] = MCore::AttributeInt32::TYPE_ID; - mInputPorts[inputPortNr].mPortID = portID; + m_inputPorts[inputPortNr].Clear(); + m_inputPorts[inputPortNr].m_compatibleTypes[0] = MCore::AttributeBool::TYPE_ID; + m_inputPorts[inputPortNr].m_compatibleTypes[1] = MCore::AttributeFloat::TYPE_ID;; + m_inputPorts[inputPortNr].m_compatibleTypes[2] = MCore::AttributeInt32::TYPE_ID; + m_inputPorts[inputPortNr].m_portId = portID; } // setup a given input port in a generic way @@ -749,16 +739,13 @@ namespace EMotionFX const size_t duplicatePort = FindInputPortByID(portID); if (duplicatePort != InvalidIndex) { - MCore::LogError("EMotionFX::AnimGraphNode::SetInputPort() - There is already a port with the same ID (portID=%d existingPort='%s' newPort='%s' node='%s')", portID, mInputPorts[duplicatePort].GetName(), name, RTTI_GetTypeName()); + MCore::LogError("EMotionFX::AnimGraphNode::SetInputPort() - There is already a port with the same ID (portID=%d existingPort='%s' newPort='%s' node='%s')", portID, m_inputPorts[duplicatePort].GetName(), name, RTTI_GetTypeName()); } SetInputPortName(inputPortNr, name); - mInputPorts[inputPortNr].Clear(); - mInputPorts[inputPortNr].mCompatibleTypes[0] = attributeTypeID; - mInputPorts[inputPortNr].mPortID = portID; - - // make sure we were able to create the attribute - //MCORE_ASSERT( mInputPorts[inputPortNr].mValue ); + m_inputPorts[inputPortNr].Clear(); + m_inputPorts[inputPortNr].m_compatibleTypes[0] = attributeTypeID; + m_inputPorts[inputPortNr].m_portId = portID; } @@ -766,7 +753,7 @@ namespace EMotionFX { ResetUniqueData(animGraphInstance); - for (AnimGraphNode* childNode : mChildNodes) + for (AnimGraphNode* childNode : m_childNodes) { childNode->RecursiveResetUniqueDatas(animGraphInstance); } @@ -788,7 +775,7 @@ namespace EMotionFX { InvalidateUniqueData(animGraphInstance); - for (AnimGraphNode* childNode : mChildNodes) + for (AnimGraphNode* childNode : m_childNodes) { childNode->RecursiveInvalidateUniqueDatas(animGraphInstance); } @@ -800,7 +787,7 @@ namespace EMotionFX MCORE_UNUSED(animGraphInstance); // get the connection that is plugged into the port - BlendTreeConnection* connection = mInputPorts[inputPort].mConnection; + BlendTreeConnection* connection = m_inputPorts[inputPort].m_connection; MCORE_ASSERT(connection); // make sure there is a connection plugged in, otherwise we can't read the value // get the value from the output port of the source node @@ -812,17 +799,17 @@ namespace EMotionFX void AnimGraphNode::RecursiveResetFlags(AnimGraphInstance* animGraphInstance, uint32 flagsToReset) { // reset the flag in this node - animGraphInstance->DisableObjectFlags(mObjectIndex, flagsToReset); + animGraphInstance->DisableObjectFlags(m_objectIndex, flagsToReset); if (GetEMotionFX().GetIsInEditorMode()) { // reset all connections - for (BlendTreeConnection* connection : mConnections) + for (BlendTreeConnection* connection : m_connections) { connection->SetIsVisited(false); } } - for (AnimGraphNode* childNode : mChildNodes) + for (AnimGraphNode* childNode : m_childNodes) { childNode->RecursiveResetFlags(animGraphInstance, flagsToReset); } @@ -996,7 +983,7 @@ namespace EMotionFX const size_t numChildNodes = GetNumChildNodes(); for (size_t i = 0; i < numChildNodes; ++i) { - mChildNodes[i]->RecursiveOnChangeMotionSet(animGraphInstance, newMotionSet); + m_childNodes[i]->RecursiveOnChangeMotionSet(animGraphInstance, newMotionSet); } } @@ -1158,19 +1145,19 @@ namespace EMotionFX bool AnimGraphNode::RecursiveIsParentNode(const AnimGraphNode* node) const { // if we're dealing with a root node we can directly return failure - if (!mParentNode) + if (!m_parentNode) { return false; } // check if the parent is the node and return success in that case - if (mParentNode == node) + if (m_parentNode == node) { return true; } // check if the parent's parent is the node we're searching for - return mParentNode->RecursiveIsParentNode(node); + return m_parentNode->RecursiveIsParentNode(node); } @@ -1183,7 +1170,7 @@ namespace EMotionFX return true; } - return AZStd::any_of(begin(mChildNodes), end(mChildNodes), [node](const AnimGraphNode* childNode) + return AZStd::any_of(begin(m_childNodes), end(m_childNodes), [node](const AnimGraphNode* childNode) { return childNode->RecursiveIsChildNode(node); }); @@ -1204,17 +1191,17 @@ namespace EMotionFX SyncVisualObject(); // in case the parent node is valid check the error status of the parent by checking all children recursively and set that value - if (mParentNode) + if (m_parentNode) { - AnimGraphObjectData* parentUniqueData = mParentNode->FindOrCreateUniqueNodeData(uniqueData->GetAnimGraphInstance()); + AnimGraphObjectData* parentUniqueData = m_parentNode->FindOrCreateUniqueNodeData(uniqueData->GetAnimGraphInstance()); if (hasError) { - mParentNode->SetHasError(parentUniqueData, true); + m_parentNode->SetHasError(parentUniqueData, true); } - else if (!mParentNode->HierarchicalHasError(parentUniqueData, true)) + else if (!m_parentNode->HierarchicalHasError(parentUniqueData, true)) { // In case we are clearing this error, we need to check if this node siblings have errors to clear the parent. - mParentNode->SetHasError(parentUniqueData, false); + m_parentNode->SetHasError(parentUniqueData, false); } } } @@ -1226,7 +1213,7 @@ namespace EMotionFX return true; } - for (const AnimGraphNode* childNode : mChildNodes) + for (const AnimGraphNode* childNode : m_childNodes) { AnimGraphObjectData* childUniqueData = childNode->FindOrCreateUniqueNodeData(uniqueData->GetAnimGraphInstance()); if (childUniqueData->GetHasError()) @@ -1243,7 +1230,7 @@ namespace EMotionFX // collect child nodes of the given type void AnimGraphNode::CollectChildNodesOfType(const AZ::TypeId& nodeType, AZStd::vector* outNodes) const { - for (AnimGraphNode* childNode : mChildNodes) + for (AnimGraphNode* childNode : m_childNodes) { // check the current node type and add it to the output array in case they are the same if (azrtti_typeid(childNode) == nodeType) @@ -1255,7 +1242,7 @@ namespace EMotionFX void AnimGraphNode::CollectChildNodesOfType(const AZ::TypeId& nodeType, AZStd::vector& outNodes) const { - for (AnimGraphNode* childNode : mChildNodes) + for (AnimGraphNode* childNode : m_childNodes) { if (azrtti_typeid(childNode) == nodeType) { @@ -1272,7 +1259,7 @@ namespace EMotionFX outNodes->emplace_back(const_cast(this)); } - for (const AnimGraphNode* childNode : mChildNodes) + for (const AnimGraphNode* childNode : m_childNodes) { childNode->RecursiveCollectNodesOfType(nodeType, outNodes); } @@ -1306,7 +1293,7 @@ namespace EMotionFX } } - for (const AnimGraphNode* childNode : mChildNodes) + for (const AnimGraphNode* childNode : m_childNodes) { childNode->RecursiveCollectTransitionConditionsOfType(conditionType, outConditions); } @@ -1320,7 +1307,7 @@ namespace EMotionFX outObjects.emplace_back(const_cast(this)); } - for (const AnimGraphNode* childNode : mChildNodes) + for (const AnimGraphNode* childNode : m_childNodes) { childNode->RecursiveCollectObjectsOfType(objectType, outObjects); } @@ -1328,7 +1315,7 @@ namespace EMotionFX void AnimGraphNode::RecursiveCollectObjectsAffectedBy(AnimGraph* animGraph, AZStd::vector& outObjects) const { - for (const AnimGraphNode* childNode : mChildNodes) + for (const AnimGraphNode* childNode : m_childNodes) { childNode->RecursiveCollectObjectsAffectedBy(animGraph, outObjects); } @@ -1379,44 +1366,44 @@ namespace EMotionFX // find the input port, based on the port name AnimGraphNode::Port* AnimGraphNode::FindInputPortByName(const AZStd::string& portName) { - const auto foundPort = AZStd::find_if(begin(mInputPorts), end(mInputPorts), [&portName](const Port& port) + const auto foundPort = AZStd::find_if(begin(m_inputPorts), end(m_inputPorts), [&portName](const Port& port) { return port.GetNameString() == portName; }); - return foundPort != end(mInputPorts) ? foundPort : nullptr; + return foundPort != end(m_inputPorts) ? foundPort : nullptr; } // find the output port, based on the port name AnimGraphNode::Port* AnimGraphNode::FindOutputPortByName(const AZStd::string& portName) { - const auto foundPort = AZStd::find_if(begin(mOutputPorts), end(mOutputPorts), [&portName](const Port& port) + const auto foundPort = AZStd::find_if(begin(m_outputPorts), end(m_outputPorts), [&portName](const Port& port) { return port.GetNameString() == portName; }); - return foundPort != end(mOutputPorts) ? foundPort : nullptr; + return foundPort != end(m_outputPorts) ? foundPort : nullptr; } // find the input port index, based on the port id size_t AnimGraphNode::FindInputPortByID(uint32 portID) const { - const auto foundPort = AZStd::find_if(begin(mInputPorts), end(mInputPorts), [portID](const Port& port) + const auto foundPort = AZStd::find_if(begin(m_inputPorts), end(m_inputPorts), [portID](const Port& port) { - return port.mPortID == portID; + return port.m_portId == portID; }); - return foundPort != end(mInputPorts) ? AZStd::distance(begin(mInputPorts), foundPort) : InvalidIndex; + return foundPort != end(m_inputPorts) ? AZStd::distance(begin(m_inputPorts), foundPort) : InvalidIndex; } // find the output port index, based on the port id size_t AnimGraphNode::FindOutputPortByID(uint32 portID) const { - const auto foundPort = AZStd::find_if(begin(mOutputPorts), end(mOutputPorts), [portID](const Port& port) + const auto foundPort = AZStd::find_if(begin(m_outputPorts), end(m_outputPorts), [portID](const Port& port) { - return port.mPortID == portID; + return port.m_portId == portID; }); - return foundPort != end(mOutputPorts) ? AZStd::distance(begin(mOutputPorts), foundPort) : InvalidIndex; + return foundPort != end(m_outputPorts) ? AZStd::distance(begin(m_outputPorts), foundPort) : InvalidIndex; } @@ -1434,12 +1421,12 @@ namespace EMotionFX outConnections.clear(); // if we don't have a parent node we cannot proceed - if (!mParentNode) + if (!m_parentNode) { return; } - for (AnimGraphNode* childNode : mParentNode->GetChildNodes()) + for (AnimGraphNode* childNode : m_parentNode->GetChildNodes()) { // Skip this child if the child is this node if (childNode == this) @@ -1463,12 +1450,12 @@ namespace EMotionFX { outConnections.clear(); - if (!mParentNode) + if (!m_parentNode) { return; } - for (AnimGraphNode* childNode : mParentNode->GetChildNodes()) + for (AnimGraphNode* childNode : m_parentNode->GetChildNodes()) { // Skip this child if the child is this node if (childNode == this) @@ -1509,7 +1496,7 @@ namespace EMotionFX BlendTreeConnection* AnimGraphNode::FindConnectionById(AnimGraphConnectionId connectionId) const { - for (BlendTreeConnection* connection : mConnections) + for (BlendTreeConnection* connection : m_connections) { if (connection->GetId() == connectionId) { @@ -1523,15 +1510,15 @@ namespace EMotionFX bool AnimGraphNode::HasConnectionAtInputPort(AZ::u32 inputPortNr) const { - const Port& inputPort = mInputPorts[inputPortNr]; - return inputPort.mConnection != nullptr; + const Port& inputPort = m_inputPorts[inputPortNr]; + return inputPort.m_connection != nullptr; } // callback that gets called before a node gets removed void AnimGraphNode::OnRemoveNode(AnimGraph* animGraph, AnimGraphNode* nodeToRemove) { - for (AnimGraphNode* childNode : mChildNodes) + for (AnimGraphNode* childNode : m_childNodes) { childNode->OnRemoveNode(animGraph, nodeToRemove); } @@ -1543,7 +1530,7 @@ namespace EMotionFX { outObjects.emplace_back(const_cast(this)); - for (const AnimGraphNode* childNode : mChildNodes) + for (const AnimGraphNode* childNode : m_childNodes) { childNode->RecursiveCollectObjects(outObjects); } @@ -1553,15 +1540,12 @@ namespace EMotionFX // topdown update void AnimGraphNode::TopDownUpdate(AnimGraphInstance* animGraphInstance, float timePassedInSeconds) { - //if (mDisabled) - //return; - // get the unique data AnimGraphNodeData* uniqueData = FindOrCreateUniqueNodeData(animGraphInstance); HierarchicalSyncAllInputNodes(animGraphInstance, uniqueData); // top down update all incoming connections - for (BlendTreeConnection* connection : mConnections) + for (BlendTreeConnection* connection : m_connections) { connection->GetSourceNode()->PerformTopDownUpdate(animGraphInstance, timePassedInSeconds); } @@ -1583,10 +1567,10 @@ namespace EMotionFX // iterate over all incoming connections bool syncTrackFound = false; size_t connectionIndex = InvalidIndex; - const size_t numConnections = mConnections.size(); + const size_t numConnections = m_connections.size(); for (size_t i = 0; i < numConnections; ++i) { - const BlendTreeConnection* connection = mConnections[i]; + const BlendTreeConnection* connection = m_connections[i]; AnimGraphNode* sourceNode = connection->GetSourceNode(); // update the node @@ -1602,13 +1586,13 @@ namespace EMotionFX if (connectionIndex != InvalidIndex) { - uniqueData->Init(animGraphInstance, mConnections[connectionIndex]->GetSourceNode()); + uniqueData->Init(animGraphInstance, m_connections[connectionIndex]->GetSourceNode()); } // set the current sync track to the first input connection - if (!syncTrackFound && numConnections > 0 && mConnections[0]->GetSourceNode()->GetHasOutputPose()) // just pick the first connection's sync track + if (!syncTrackFound && numConnections > 0 && m_connections[0]->GetSourceNode()->GetHasOutputPose()) // just pick the first connection's sync track { - uniqueData->Init(animGraphInstance, mConnections[0]->GetSourceNode()); + uniqueData->Init(animGraphInstance, m_connections[0]->GetSourceNode()); } } @@ -1616,7 +1600,7 @@ namespace EMotionFX // output all incoming nodes void AnimGraphNode::OutputAllIncomingNodes(AnimGraphInstance* animGraphInstance) { - for (const BlendTreeConnection* connection : mConnections) + for (const BlendTreeConnection* connection : m_connections) { OutputIncomingNode(animGraphInstance, connection->GetSourceNode()); } @@ -1637,7 +1621,7 @@ namespace EMotionFX // update all incoming nodes void AnimGraphNode::UpdateAllIncomingNodes(AnimGraphInstance* animGraphInstance, float timePassedInSeconds) { - for (const BlendTreeConnection* connection : mConnections) + for (const BlendTreeConnection* connection : m_connections) { AnimGraphNode* sourceNode = connection->GetSourceNode(); sourceNode->PerformUpdate(animGraphInstance, timePassedInSeconds); @@ -1650,7 +1634,7 @@ namespace EMotionFX { if (GetEMotionFX().GetIsInEditorMode()) { - for (BlendTreeConnection* connection : mConnections) + for (BlendTreeConnection* connection : m_connections) { if (connection->GetSourceNode() == sourceNode) { @@ -1675,7 +1659,7 @@ namespace EMotionFX // mark any connection originating from this node as visited if (GetEMotionFX().GetIsInEditorMode()) { - for (BlendTreeConnection* connection : mConnections) + for (BlendTreeConnection* connection : m_connections) { if (connection->GetSourceNode() == nodeToOutput) { @@ -1692,10 +1676,10 @@ namespace EMotionFX bool poseFound = false; size_t connectionIndex = InvalidIndex; AZ::u16 minTargetPortIndex = MCORE_INVALIDINDEX16; - const size_t numConnections = mConnections.size(); + const size_t numConnections = m_connections.size(); for (size_t i = 0; i < numConnections; ++i) { - const BlendTreeConnection* connection = mConnections[i]; + const BlendTreeConnection* connection = m_connections[i]; AnimGraphNode* sourceNode = connection->GetSourceNode(); // update the node @@ -1709,7 +1693,7 @@ namespace EMotionFX // Find the first connection that plugs into a port that can take a pose. const AZ::u16 targetPortIndex = connection->GetTargetPort(); - if (mInputPorts[targetPortIndex].mCompatibleTypes[0] == AttributePose::TYPE_ID) + if (m_inputPorts[targetPortIndex].m_compatibleTypes[0] == AttributePose::TYPE_ID) { poseFound = true; if (targetPortIndex < minTargetPortIndex) @@ -1726,7 +1710,7 @@ namespace EMotionFX AnimGraphNodeData* uniqueData = FindOrCreateUniqueNodeData(animGraphInstance); if (poseFound && connectionIndex != InvalidIndex) { - const BlendTreeConnection* connection = mConnections[connectionIndex]; + const BlendTreeConnection* connection = m_connections[connectionIndex]; AnimGraphNode* sourceNode = connection->GetSourceNode(); AnimGraphRefCountedData* data = uniqueData->GetRefCountedData(); @@ -1740,10 +1724,10 @@ namespace EMotionFX } } else - if (poseFound == false && numConnections > 0 && mConnections[0]->GetSourceNode()->GetHasOutputPose()) + if (poseFound == false && numConnections > 0 && m_connections[0]->GetSourceNode()->GetHasOutputPose()) { AnimGraphRefCountedData* data = uniqueData->GetRefCountedData(); - AnimGraphNode* sourceNode = mConnections[0]->GetSourceNode(); + AnimGraphNode* sourceNode = m_connections[0]->GetSourceNode(); AnimGraphRefCountedData* sourceData = sourceNode->FindOrCreateUniqueNodeData(animGraphInstance)->GetRefCountedData(); data->SetEventBuffer(sourceData->GetEventBuffer()); data->SetTrajectoryDelta(sourceData->GetTrajectoryDelta()); @@ -1764,10 +1748,10 @@ namespace EMotionFX void AnimGraphNode::RecursiveSetUniqueDataFlag(AnimGraphInstance* animGraphInstance, uint32 flag, bool enabled) { // set the flag - animGraphInstance->SetObjectFlags(mObjectIndex, flag, enabled); + animGraphInstance->SetObjectFlags(m_objectIndex, flag, enabled); // recurse downwards - for (BlendTreeConnection* connection : mConnections) + for (BlendTreeConnection* connection : m_connections) { connection->GetSourceNode()->RecursiveSetUniqueDataFlag(animGraphInstance, flag, enabled); } @@ -1918,7 +1902,7 @@ namespace EMotionFX void AnimGraphNode::HierarchicalSyncAllInputNodes(AnimGraphInstance* animGraphInstance, AnimGraphNodeData* uniqueDataOfThisNode) { // for all connections - for (const BlendTreeConnection* connection : mConnections) + for (const BlendTreeConnection* connection : m_connections) { AnimGraphNode* inputNode = connection->GetSourceNode(); HierarchicalSyncInputNode(animGraphInstance, inputNode, uniqueDataOfThisNode); @@ -1931,14 +1915,14 @@ namespace EMotionFX // check and add this node if (azrtti_typeid(this) == nodeType || nodeType.IsNull()) { - if (animGraphInstance->GetIsOutputReady(mObjectIndex)) // if we processed this node + if (animGraphInstance->GetIsOutputReady(m_objectIndex)) // if we processed this node { outNodes->emplace_back(const_cast(this)); } } // process all child nodes (but only active ones) - for (const AnimGraphNode* childNode : mChildNodes) + for (const AnimGraphNode* childNode : m_childNodes) { if (animGraphInstance->GetIsOutputReady(childNode->GetObjectIndex())) { @@ -1953,14 +1937,14 @@ namespace EMotionFX // Check and add this node if (GetNeedsNetTimeSync()) { - if (animGraphInstance->GetIsOutputReady(mObjectIndex)) // if we processed this node + if (animGraphInstance->GetIsOutputReady(m_objectIndex)) // if we processed this node { outNodes->emplace_back(const_cast(this)); } } // Process all child nodes (but only active ones) - for (const AnimGraphNode* childNode : mChildNodes) + for (const AnimGraphNode* childNode : m_childNodes) { if (animGraphInstance->GetIsOutputReady(childNode->GetObjectIndex())) { @@ -1972,7 +1956,7 @@ namespace EMotionFX bool AnimGraphNode::RecursiveDetectCycles(AZStd::unordered_set& nodes) const { - for (const AnimGraphNode* childNode : mChildNodes) + for (const AnimGraphNode* childNode : m_childNodes) { if (nodes.find(childNode) != nodes.end()) { @@ -2008,10 +1992,10 @@ namespace EMotionFX const uint32 threadIndex = animGraphInstance->GetActorInstance()->GetThreadIndex(); AnimGraphPosePool& posePool = GetEMotionFX().GetThreadData(threadIndex)->GetPosePool(); - const size_t numOutputs = mOutputPorts.size(); + const size_t numOutputs = m_outputPorts.size(); for (size_t i = 0; i < numOutputs; ++i) { - if (mOutputPorts[i].mCompatibleTypes[0] == AttributePose::TYPE_ID) + if (m_outputPorts[i].m_compatibleTypes[0] == AttributePose::TYPE_ID) { MCore::Attribute* attribute = GetOutputAttribute(animGraphInstance, i); MCORE_ASSERT(attribute->GetType() == AttributePose::TYPE_ID); @@ -2036,10 +2020,10 @@ namespace EMotionFX AnimGraphPosePool& posePool = GetEMotionFX().GetThreadData(threadIndex)->GetPosePool(); - const size_t numOutputs = mOutputPorts.size(); + const size_t numOutputs = m_outputPorts.size(); for (size_t i = 0; i < numOutputs; ++i) { - if (mOutputPorts[i].mCompatibleTypes[0] == AttributePose::TYPE_ID) + if (m_outputPorts[i].m_compatibleTypes[0] == AttributePose::TYPE_ID) { MCore::Attribute* attribute = GetOutputAttribute(animGraphInstance, i); MCORE_ASSERT(attribute->GetType() == AttributePose::TYPE_ID); @@ -2055,9 +2039,9 @@ namespace EMotionFX // free all poses from all incoming nodes void AnimGraphNode::FreeIncomingPoses(AnimGraphInstance* animGraphInstance) { - for (const Port& inputPort : mInputPorts) + for (const Port& inputPort : m_inputPorts) { - const BlendTreeConnection* connection = inputPort.mConnection; + const BlendTreeConnection* connection = inputPort.m_connection; if (connection) { AnimGraphNode* sourceNode = connection->GetSourceNode(); @@ -2070,9 +2054,9 @@ namespace EMotionFX // free all poses from all incoming nodes void AnimGraphNode::FreeIncomingRefDatas(AnimGraphInstance* animGraphInstance) { - for (const Port& port : mInputPorts) + for (const Port& port : m_inputPorts) { - const BlendTreeConnection* connection = port.mConnection; + const BlendTreeConnection* connection = port.m_connection; if (connection) { AnimGraphNode* sourceNode = connection->GetSourceNode(); @@ -2125,13 +2109,13 @@ namespace EMotionFX void AnimGraphNode::PerformTopDownUpdate(AnimGraphInstance* animGraphInstance, float timePassedInSeconds) { // check if we already did update - if (animGraphInstance->GetIsTopDownUpdateReady(mObjectIndex)) + if (animGraphInstance->GetIsTopDownUpdateReady(m_objectIndex)) { return; } // mark as done - animGraphInstance->EnableObjectFlags(mObjectIndex, AnimGraphInstance::OBJECTFLAGS_TOPDOWNUPDATE_READY); + animGraphInstance->EnableObjectFlags(m_objectIndex, AnimGraphInstance::OBJECTFLAGS_TOPDOWNUPDATE_READY); TopDownUpdate(animGraphInstance, timePassedInSeconds); } @@ -2141,13 +2125,13 @@ namespace EMotionFX void AnimGraphNode::PerformPostUpdate(AnimGraphInstance* animGraphInstance, float timePassedInSeconds) { // check if we already did update - if (animGraphInstance->GetIsPostUpdateReady(mObjectIndex)) + if (animGraphInstance->GetIsPostUpdateReady(m_objectIndex)) { return; } // mark as done - animGraphInstance->EnableObjectFlags(mObjectIndex, AnimGraphInstance::OBJECTFLAGS_POSTUPDATE_READY); + animGraphInstance->EnableObjectFlags(m_objectIndex, AnimGraphInstance::OBJECTFLAGS_POSTUPDATE_READY); // perform the actual post update PostUpdate(animGraphInstance, timePassedInSeconds); @@ -2161,13 +2145,13 @@ namespace EMotionFX void AnimGraphNode::PerformUpdate(AnimGraphInstance* animGraphInstance, float timePassedInSeconds) { // check if we already did update - if (animGraphInstance->GetIsUpdateReady(mObjectIndex)) + if (animGraphInstance->GetIsUpdateReady(m_objectIndex)) { return; } // mark as done - animGraphInstance->EnableObjectFlags(mObjectIndex, AnimGraphInstance::OBJECTFLAGS_UPDATE_READY); + animGraphInstance->EnableObjectFlags(m_objectIndex, AnimGraphInstance::OBJECTFLAGS_UPDATE_READY); // increase ref count for incoming nodes IncreaseInputRefCounts(animGraphInstance); @@ -2182,13 +2166,13 @@ namespace EMotionFX void AnimGraphNode::PerformOutput(AnimGraphInstance* animGraphInstance) { // check if we already did output - if (animGraphInstance->GetIsOutputReady(mObjectIndex)) + if (animGraphInstance->GetIsOutputReady(m_objectIndex)) { return; } // mark as done - animGraphInstance->EnableObjectFlags(mObjectIndex, AnimGraphInstance::OBJECTFLAGS_OUTPUT_READY); + animGraphInstance->EnableObjectFlags(m_objectIndex, AnimGraphInstance::OBJECTFLAGS_OUTPUT_READY); // perform the output Output(animGraphInstance); @@ -2202,9 +2186,9 @@ namespace EMotionFX // increase input ref counts void AnimGraphNode::IncreaseInputRefDataRefCounts(AnimGraphInstance* animGraphInstance) { - for (const Port& port : mInputPorts) + for (const Port& port : m_inputPorts) { - const BlendTreeConnection* connection = port.mConnection; + const BlendTreeConnection* connection = port.m_connection; if (connection) { AnimGraphNode* sourceNode = connection->GetSourceNode(); @@ -2217,9 +2201,9 @@ namespace EMotionFX // increase input ref counts void AnimGraphNode::IncreaseInputRefCounts(AnimGraphInstance* animGraphInstance) { - for (const Port& port : mInputPorts) + for (const Port& port : m_inputPorts) { - const BlendTreeConnection* connection = port.mConnection; + const BlendTreeConnection* connection = port.m_connection; if (connection) { AnimGraphNode* sourceNode = connection->GetSourceNode(); @@ -2232,7 +2216,7 @@ namespace EMotionFX void AnimGraphNode::RelinkPortConnections() { // After deserializing, nodes hold an array of incoming connections. Each node port caches a pointer to its connection object which we need to link. - for (BlendTreeConnection* connection : mConnections) + for (BlendTreeConnection* connection : m_connections) { AnimGraphNode* sourceNode = connection->GetSourceNode(); const AZ::u16 targetPortNr = connection->GetTargetPort(); @@ -2240,9 +2224,9 @@ namespace EMotionFX if (sourceNode) { - if (sourcePortNr < sourceNode->mOutputPorts.size()) + if (sourcePortNr < sourceNode->m_outputPorts.size()) { - sourceNode->GetOutputPort(sourcePortNr).mConnection = connection; + sourceNode->GetOutputPort(sourcePortNr).m_connection = connection; } else { @@ -2250,9 +2234,9 @@ namespace EMotionFX } } - if (targetPortNr < mInputPorts.size()) + if (targetPortNr < m_inputPorts.size()) { - mInputPorts[targetPortNr].mConnection = connection; + m_inputPorts[targetPortNr].m_connection = connection; } else { @@ -2265,7 +2249,7 @@ namespace EMotionFX // do we have a child of a given type? bool AnimGraphNode::CheckIfHasChildOfType(const AZ::TypeId& nodeType) const { - for (const AnimGraphNode* childNode : mChildNodes) + for (const AnimGraphNode* childNode : m_childNodes) { if (azrtti_typeid(childNode) == nodeType) { @@ -2280,7 +2264,7 @@ namespace EMotionFX // check if we can visualize bool AnimGraphNode::GetCanVisualize(AnimGraphInstance* animGraphInstance) const { - return (mVisEnabled && animGraphInstance->GetVisualizationEnabled() && EMotionFX::GetRecorder().GetIsInPlayMode() == false); + return (m_visEnabled && animGraphInstance->GetVisualizationEnabled() && EMotionFX::GetRecorder().GetIsInPlayMode() == false); } @@ -2288,20 +2272,20 @@ namespace EMotionFX void AnimGraphNode::RemoveInternalAttributesForAllInstances() { // for all output ports - for (Port& port : mOutputPorts) + for (Port& port : m_outputPorts) { - const size_t internalAttributeIndex = port.mAttributeIndex; + const size_t internalAttributeIndex = port.m_attributeIndex; if (internalAttributeIndex != InvalidIndex) { - const size_t numInstances = mAnimGraph->GetNumAnimGraphInstances(); + const size_t numInstances = m_animGraph->GetNumAnimGraphInstances(); for (size_t i = 0; i < numInstances; ++i) { - AnimGraphInstance* animGraphInstance = mAnimGraph->GetAnimGraphInstance(i); + AnimGraphInstance* animGraphInstance = m_animGraph->GetAnimGraphInstance(i); animGraphInstance->RemoveInternalAttribute(internalAttributeIndex); } - mAnimGraph->DecreaseInternalAttributeIndices(internalAttributeIndex); - port.mAttributeIndex = InvalidIndex; + m_animGraph->DecreaseInternalAttributeIndices(internalAttributeIndex); + port.m_attributeIndex = InvalidIndex; } } } @@ -2310,11 +2294,11 @@ namespace EMotionFX // decrease values higher than a given param value void AnimGraphNode::DecreaseInternalAttributeIndices(size_t decreaseEverythingHigherThan) { - for (Port& port : mOutputPorts) + for (Port& port : m_outputPorts) { - if (port.mAttributeIndex > decreaseEverythingHigherThan && port.mAttributeIndex != InvalidIndex) + if (port.m_attributeIndex > decreaseEverythingHigherThan && port.m_attributeIndex != InvalidIndex) { - port.mAttributeIndex--; + port.m_attributeIndex--; } } } @@ -2324,31 +2308,31 @@ namespace EMotionFX void AnimGraphNode::InitInternalAttributes(AnimGraphInstance* animGraphInstance) { // for all output ports of this node - for (Port& port : mOutputPorts) + for (Port& port : m_outputPorts) { - MCore::Attribute* newAttribute = MCore::GetAttributeFactory().CreateAttributeByType(port.mCompatibleTypes[0]); // assume compatibility type 0 to be the attribute type ID - port.mAttributeIndex = animGraphInstance->AddInternalAttribute(newAttribute); + MCore::Attribute* newAttribute = MCore::GetAttributeFactory().CreateAttributeByType(port.m_compatibleTypes[0]); // assume compatibility type 0 to be the attribute type ID + port.m_attributeIndex = animGraphInstance->AddInternalAttribute(newAttribute); } } void* AnimGraphNode::GetCustomData() const { - return mCustomData; + return m_customData; } void AnimGraphNode::SetCustomData(void* dataPointer) { - mCustomData = dataPointer; + m_customData = dataPointer; } void AnimGraphNode::SetNodeInfo(const AZStd::string& info) { - if (mNodeInfo != info) + if (m_nodeInfo != info) { - mNodeInfo = info; + m_nodeInfo = info; SyncVisualObject(); } @@ -2357,88 +2341,88 @@ namespace EMotionFX const AZStd::string& AnimGraphNode::GetNodeInfo() const { - return mNodeInfo; + return m_nodeInfo; } bool AnimGraphNode::GetIsEnabled() const { - return (mDisabled == false); + return (m_disabled == false); } void AnimGraphNode::SetIsEnabled(bool enabled) { - mDisabled = !enabled; + m_disabled = !enabled; } bool AnimGraphNode::GetIsCollapsed() const { - return mIsCollapsed; + return m_isCollapsed; } void AnimGraphNode::SetIsCollapsed(bool collapsed) { - mIsCollapsed = collapsed; + m_isCollapsed = collapsed; } void AnimGraphNode::SetVisualizeColor(const AZ::Color& color) { - mVisualizeColor = color; + m_visualizeColor = color; SyncVisualObject(); } const AZ::Color& AnimGraphNode::GetVisualizeColor() const { - return mVisualizeColor; + return m_visualizeColor; } void AnimGraphNode::SetVisualPos(int32 x, int32 y) { - mPosX = x; - mPosY = y; + m_posX = x; + m_posY = y; } int32 AnimGraphNode::GetVisualPosX() const { - return mPosX; + return m_posX; } int32 AnimGraphNode::GetVisualPosY() const { - return mPosY; + return m_posY; } bool AnimGraphNode::GetIsVisualizationEnabled() const { - return mVisEnabled; + return m_visEnabled; } void AnimGraphNode::SetVisualization(bool enabled) { - mVisEnabled = enabled; + m_visEnabled = enabled; } void AnimGraphNode::AddChildNode(AnimGraphNode* node) { - mChildNodes.push_back(node); + m_childNodes.push_back(node); node->SetParentNode(this); } void AnimGraphNode::ReserveChildNodes(size_t numChildNodes) { - mChildNodes.reserve(numChildNodes); + m_childNodes.reserve(numChildNodes); } @@ -2461,7 +2445,7 @@ namespace EMotionFX void AnimGraphNode::ResetPoseRefCount(AnimGraphInstance* animGraphInstance) { - AnimGraphNodeData* uniqueData = reinterpret_cast(animGraphInstance->GetUniqueObjectData(mObjectIndex)); + AnimGraphNodeData* uniqueData = reinterpret_cast(animGraphInstance->GetUniqueObjectData(m_objectIndex)); if (uniqueData) { uniqueData->SetPoseRefCount(0); @@ -2470,7 +2454,7 @@ namespace EMotionFX void AnimGraphNode::ResetRefDataRefCount(AnimGraphInstance* animGraphInstance) { - AnimGraphNodeData* uniqueData = reinterpret_cast(animGraphInstance->GetUniqueObjectData(mObjectIndex)); + AnimGraphNodeData* uniqueData = reinterpret_cast(animGraphInstance->GetUniqueObjectData(m_objectIndex)); if (uniqueData) { uniqueData->SetRefDataRefCount(0); @@ -2527,14 +2511,14 @@ namespace EMotionFX ->PersistentId([](const void* instance) -> AZ::u64 { return static_cast(instance)->GetId(); }) ->Field("id", &AnimGraphNode::m_id) ->Field("name", &AnimGraphNode::m_name) - ->Field("posX", &AnimGraphNode::mPosX) - ->Field("posY", &AnimGraphNode::mPosY) - ->Field("visualizeColor", &AnimGraphNode::mVisualizeColor) - ->Field("isDisabled", &AnimGraphNode::mDisabled) - ->Field("isCollapsed", &AnimGraphNode::mIsCollapsed) - ->Field("isVisEnabled", &AnimGraphNode::mVisEnabled) - ->Field("childNodes", &AnimGraphNode::mChildNodes) - ->Field("connections", &AnimGraphNode::mConnections) + ->Field("posX", &AnimGraphNode::m_posX) + ->Field("posY", &AnimGraphNode::m_posY) + ->Field("visualizeColor", &AnimGraphNode::m_visualizeColor) + ->Field("isDisabled", &AnimGraphNode::m_disabled) + ->Field("isCollapsed", &AnimGraphNode::m_isCollapsed) + ->Field("isVisEnabled", &AnimGraphNode::m_visEnabled) + ->Field("childNodes", &AnimGraphNode::m_childNodes) + ->Field("connections", &AnimGraphNode::m_connections) ->Field("actionSetup", &AnimGraphNode::m_actionSetup); ; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNode.h b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNode.h index 31d85b6f48..b515621c5b 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNode.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNode.h @@ -56,55 +56,55 @@ namespace EMotionFX AZ_RTTI(AnimGraphNode::Port, "{F66CF090-468F-419A-9518-97988304FEB6}") AZ_CLASS_ALLOCATOR_DECL - BlendTreeConnection* mConnection; // the connection plugged in this port - uint32 mCompatibleTypes[4]; // four possible compatible types - uint32 mPortID; // the unique port ID (unique inside the node input or output port lists) - uint32 mNameID; // the name of the port (using the StringIdPool) - size_t mAttributeIndex; // the index into the animgraph instance global attributes array + BlendTreeConnection* m_connection; // the connection plugged in this port + uint32 m_compatibleTypes[4]; // four possible compatible types + uint32 m_portId; // the unique port ID (unique inside the node input or output port lists) + uint32 m_nameId; // the name of the port (using the StringIdPool) + size_t m_attributeIndex; // the index into the animgraph instance global attributes array - MCORE_INLINE const char* GetName() const { return MCore::GetStringIdPool().GetName(mNameID).c_str(); } - MCORE_INLINE const AZStd::string& GetNameString() const { return MCore::GetStringIdPool().GetName(mNameID); } + MCORE_INLINE const char* GetName() const { return MCore::GetStringIdPool().GetName(m_nameId).c_str(); } + MCORE_INLINE const AZStd::string& GetNameString() const { return MCore::GetStringIdPool().GetName(m_nameId); } - // copy settings from another port (always makes the mConnection and mValue nullptr though) + // copy settings from another port (always makes the m_connection and m_value nullptr though) void InitFrom(const Port& other) { for (uint32 i = 0; i < 4; ++i) { - mCompatibleTypes[i] = other.mCompatibleTypes[i]; + m_compatibleTypes[i] = other.m_compatibleTypes[i]; } - mPortID = other.mPortID; - mNameID = other.mNameID; - mConnection = nullptr; - mAttributeIndex = other.mAttributeIndex; + m_portId = other.m_portId; + m_nameId = other.m_nameId; + m_connection = nullptr; + m_attributeIndex = other.m_attributeIndex; } void SetCompatibleTypes(const AZStd::vector& compatibleTypes) { for (uint32 i = 0; i < 4 && i < compatibleTypes.size(); ++i) { - mCompatibleTypes[i] = compatibleTypes[i]; + m_compatibleTypes[i] = compatibleTypes[i]; } } // get the attribute value MCORE_INLINE MCore::Attribute* GetAttribute(AnimGraphInstance* animGraphInstance) const { - return animGraphInstance->GetInternalAttribute(mAttributeIndex); + return animGraphInstance->GetInternalAttribute(m_attributeIndex); } // port connection compatibility check bool CheckIfIsCompatibleWith(const Port& otherPort) const { // check the data types - for (uint32 compatibleType : mCompatibleTypes) + for (uint32 compatibleType : m_compatibleTypes) { // If there aren't any more compatibility types and we haven't found a compatible one so far, return false if (compatibleType == 0) { return false; } - for (uint32 otherCompatibleTypeIndex : otherPort.mCompatibleTypes) + for (uint32 otherCompatibleTypeIndex : otherPort.m_compatibleTypes) { if (otherCompatibleTypeIndex == compatibleType) { @@ -126,10 +126,10 @@ namespace EMotionFX // clear compatibility types void ClearCompatibleTypes() { - mCompatibleTypes[0] = 0; - mCompatibleTypes[1] = 0; - mCompatibleTypes[2] = 0; - mCompatibleTypes[3] = 0; + m_compatibleTypes[0] = 0; + m_compatibleTypes[1] = 0; + m_compatibleTypes[2] = 0; + m_compatibleTypes[3] = 0; } void Clear() @@ -138,10 +138,10 @@ namespace EMotionFX } Port() - : mConnection(nullptr) - , mPortID(MCORE_INVALIDINDEX32) - , mNameID(MCORE_INVALIDINDEX32) - , mAttributeIndex(InvalidIndex) { ClearCompatibleTypes(); } + : m_connection(nullptr) + , m_portId(MCORE_INVALIDINDEX32) + , m_nameId(MCORE_INVALIDINDEX32) + , m_attributeIndex(InvalidIndex) { ClearCompatibleTypes(); } virtual ~Port() { } }; @@ -448,7 +448,7 @@ namespace EMotionFX MCORE_INLINE AnimGraphNode* GetInputNode(size_t portNr) { - const BlendTreeConnection* con = mInputPorts[portNr].mConnection; + const BlendTreeConnection* con = m_inputPorts[portNr].m_connection; if (con == nullptr) { return nullptr; @@ -458,7 +458,7 @@ namespace EMotionFX MCORE_INLINE MCore::Attribute* GetInputAttribute(AnimGraphInstance* animGraphInstance, size_t portNr) const { - const BlendTreeConnection* con = mInputPorts[portNr].mConnection; + const BlendTreeConnection* con = m_inputPorts[portNr].m_connection; if (con == nullptr) { return nullptr; @@ -648,114 +648,114 @@ namespace EMotionFX return static_cast(attrib); } - MCORE_INLINE MCore::Attribute* GetOutputAttribute(AnimGraphInstance* animGraphInstance, size_t outputPortIndex) const { return mOutputPorts[outputPortIndex].GetAttribute(animGraphInstance); } + MCORE_INLINE MCore::Attribute* GetOutputAttribute(AnimGraphInstance* animGraphInstance, size_t outputPortIndex) const { return m_outputPorts[outputPortIndex].GetAttribute(animGraphInstance); } MCORE_INLINE MCore::AttributeFloat* GetOutputNumber(AnimGraphInstance* animGraphInstance, size_t outputPortIndex) const { - if (mOutputPorts[outputPortIndex].GetAttribute(animGraphInstance) == nullptr) + if (m_outputPorts[outputPortIndex].GetAttribute(animGraphInstance) == nullptr) { return nullptr; } - MCORE_ASSERT(mOutputPorts[outputPortIndex].mCompatibleTypes[0] == MCore::AttributeFloat::TYPE_ID); - return static_cast(mOutputPorts[outputPortIndex].GetAttribute(animGraphInstance)); + MCORE_ASSERT(m_outputPorts[outputPortIndex].m_compatibleTypes[0] == MCore::AttributeFloat::TYPE_ID); + return static_cast(m_outputPorts[outputPortIndex].GetAttribute(animGraphInstance)); } MCORE_INLINE MCore::AttributeFloat* GetOutputFloat(AnimGraphInstance* animGraphInstance, size_t outputPortIndex) const { - if (mOutputPorts[outputPortIndex].GetAttribute(animGraphInstance) == nullptr) + if (m_outputPorts[outputPortIndex].GetAttribute(animGraphInstance) == nullptr) { return nullptr; } - MCORE_ASSERT(mOutputPorts[outputPortIndex].mCompatibleTypes[0] == MCore::AttributeFloat::TYPE_ID); - return static_cast(mOutputPorts[outputPortIndex].GetAttribute(animGraphInstance)); + MCORE_ASSERT(m_outputPorts[outputPortIndex].m_compatibleTypes[0] == MCore::AttributeFloat::TYPE_ID); + return static_cast(m_outputPorts[outputPortIndex].GetAttribute(animGraphInstance)); } MCORE_INLINE MCore::AttributeInt32* GetOutputInt32(AnimGraphInstance* animGraphInstance, size_t outputPortIndex) const { - if (mOutputPorts[outputPortIndex].GetAttribute(animGraphInstance) == nullptr) + if (m_outputPorts[outputPortIndex].GetAttribute(animGraphInstance) == nullptr) { return nullptr; } - MCORE_ASSERT(mOutputPorts[outputPortIndex].mCompatibleTypes[0] == MCore::AttributeInt32::TYPE_ID); - return static_cast(mOutputPorts[outputPortIndex].GetAttribute(animGraphInstance)); + MCORE_ASSERT(m_outputPorts[outputPortIndex].m_compatibleTypes[0] == MCore::AttributeInt32::TYPE_ID); + return static_cast(m_outputPorts[outputPortIndex].GetAttribute(animGraphInstance)); } MCORE_INLINE MCore::AttributeString* GetOutputString(AnimGraphInstance* animGraphInstance, size_t outputPortIndex) const { - if (mOutputPorts[outputPortIndex].GetAttribute(animGraphInstance) == nullptr) + if (m_outputPorts[outputPortIndex].GetAttribute(animGraphInstance) == nullptr) { return nullptr; } - MCORE_ASSERT(mOutputPorts[outputPortIndex].mCompatibleTypes[0] == MCore::AttributeString::TYPE_ID); - return static_cast(mOutputPorts[outputPortIndex].GetAttribute(animGraphInstance)); + MCORE_ASSERT(m_outputPorts[outputPortIndex].m_compatibleTypes[0] == MCore::AttributeString::TYPE_ID); + return static_cast(m_outputPorts[outputPortIndex].GetAttribute(animGraphInstance)); } MCORE_INLINE MCore::AttributeBool* GetOutputBool(AnimGraphInstance* animGraphInstance, size_t outputPortIndex) const { - if (mOutputPorts[outputPortIndex].GetAttribute(animGraphInstance) == nullptr) + if (m_outputPorts[outputPortIndex].GetAttribute(animGraphInstance) == nullptr) { return nullptr; } - MCORE_ASSERT(mOutputPorts[outputPortIndex].mCompatibleTypes[0] == MCore::AttributeBool::TYPE_ID); - return static_cast(mOutputPorts[outputPortIndex].GetAttribute(animGraphInstance)); + MCORE_ASSERT(m_outputPorts[outputPortIndex].m_compatibleTypes[0] == MCore::AttributeBool::TYPE_ID); + return static_cast(m_outputPorts[outputPortIndex].GetAttribute(animGraphInstance)); } MCORE_INLINE MCore::AttributeVector2* GetOutputVector2(AnimGraphInstance* animGraphInstance, size_t outputPortIndex) const { - if (mOutputPorts[outputPortIndex].GetAttribute(animGraphInstance) == nullptr) + if (m_outputPorts[outputPortIndex].GetAttribute(animGraphInstance) == nullptr) { return nullptr; } - MCORE_ASSERT(mOutputPorts[outputPortIndex].mCompatibleTypes[0] == MCore::AttributeVector2::TYPE_ID); - return static_cast(mOutputPorts[outputPortIndex].GetAttribute(animGraphInstance)); + MCORE_ASSERT(m_outputPorts[outputPortIndex].m_compatibleTypes[0] == MCore::AttributeVector2::TYPE_ID); + return static_cast(m_outputPorts[outputPortIndex].GetAttribute(animGraphInstance)); } MCORE_INLINE MCore::AttributeVector3* GetOutputVector3(AnimGraphInstance* animGraphInstance, size_t outputPortIndex) const { - if (mOutputPorts[outputPortIndex].GetAttribute(animGraphInstance) == nullptr) + if (m_outputPorts[outputPortIndex].GetAttribute(animGraphInstance) == nullptr) { return nullptr; } - MCORE_ASSERT(mOutputPorts[outputPortIndex].mCompatibleTypes[0] == MCore::AttributeVector3::TYPE_ID); - return static_cast(mOutputPorts[outputPortIndex].GetAttribute(animGraphInstance)); + MCORE_ASSERT(m_outputPorts[outputPortIndex].m_compatibleTypes[0] == MCore::AttributeVector3::TYPE_ID); + return static_cast(m_outputPorts[outputPortIndex].GetAttribute(animGraphInstance)); } MCORE_INLINE MCore::AttributeVector4* GetOutputVector4(AnimGraphInstance* animGraphInstance, size_t outputPortIndex) const { - if (mOutputPorts[outputPortIndex].GetAttribute(animGraphInstance) == nullptr) + if (m_outputPorts[outputPortIndex].GetAttribute(animGraphInstance) == nullptr) { return nullptr; } - MCORE_ASSERT(mOutputPorts[outputPortIndex].mCompatibleTypes[0] == MCore::AttributeVector4::TYPE_ID); - return static_cast(mOutputPorts[outputPortIndex].GetAttribute(animGraphInstance)); + MCORE_ASSERT(m_outputPorts[outputPortIndex].m_compatibleTypes[0] == MCore::AttributeVector4::TYPE_ID); + return static_cast(m_outputPorts[outputPortIndex].GetAttribute(animGraphInstance)); } MCORE_INLINE MCore::AttributeQuaternion* GetOutputQuaternion(AnimGraphInstance* animGraphInstance, size_t outputPortIndex) const { - if (mOutputPorts[outputPortIndex].GetAttribute(animGraphInstance) == nullptr) + if (m_outputPorts[outputPortIndex].GetAttribute(animGraphInstance) == nullptr) { return nullptr; } - MCORE_ASSERT(mOutputPorts[outputPortIndex].mCompatibleTypes[0] == MCore::AttributeQuaternion::TYPE_ID); - return static_cast(mOutputPorts[outputPortIndex].GetAttribute(animGraphInstance)); + MCORE_ASSERT(m_outputPorts[outputPortIndex].m_compatibleTypes[0] == MCore::AttributeQuaternion::TYPE_ID); + return static_cast(m_outputPorts[outputPortIndex].GetAttribute(animGraphInstance)); } MCORE_INLINE MCore::AttributeColor* GetOutputColor(AnimGraphInstance* animGraphInstance, size_t outputPortIndex) const { - if (mOutputPorts[outputPortIndex].GetAttribute(animGraphInstance) == nullptr) + if (m_outputPorts[outputPortIndex].GetAttribute(animGraphInstance) == nullptr) { return nullptr; } - MCORE_ASSERT(mOutputPorts[outputPortIndex].mCompatibleTypes[0] == MCore::AttributeColor::TYPE_ID); - return static_cast(mOutputPorts[outputPortIndex].GetAttribute(animGraphInstance)); + MCORE_ASSERT(m_outputPorts[outputPortIndex].m_compatibleTypes[0] == MCore::AttributeColor::TYPE_ID); + return static_cast(m_outputPorts[outputPortIndex].GetAttribute(animGraphInstance)); } MCORE_INLINE AttributePose* GetOutputPose(AnimGraphInstance* animGraphInstance, size_t outputPortIndex) const { - if (mOutputPorts[outputPortIndex].GetAttribute(animGraphInstance) == nullptr) + if (m_outputPorts[outputPortIndex].GetAttribute(animGraphInstance) == nullptr) { return nullptr; } - MCORE_ASSERT(mOutputPorts[outputPortIndex].mCompatibleTypes[0] == AttributePose::TYPE_ID); - return static_cast(mOutputPorts[outputPortIndex].GetAttribute(animGraphInstance)); + MCORE_ASSERT(m_outputPorts[outputPortIndex].m_compatibleTypes[0] == AttributePose::TYPE_ID); + return static_cast(m_outputPorts[outputPortIndex].GetAttribute(animGraphInstance)); } MCORE_INLINE AttributeMotionInstance* GetOutputMotionInstance(AnimGraphInstance* animGraphInstance, size_t outputPortIndex) const { - if (mOutputPorts[outputPortIndex].GetAttribute(animGraphInstance) == nullptr) + if (m_outputPorts[outputPortIndex].GetAttribute(animGraphInstance) == nullptr) { return nullptr; } - MCORE_ASSERT(mOutputPorts[outputPortIndex].mCompatibleTypes[0] == AttributeMotionInstance::TYPE_ID); - return static_cast(mOutputPorts[outputPortIndex].GetAttribute(animGraphInstance)); + MCORE_ASSERT(m_outputPorts[outputPortIndex].m_compatibleTypes[0] == AttributeMotionInstance::TYPE_ID); + return static_cast(m_outputPorts[outputPortIndex].GetAttribute(animGraphInstance)); } void SetupInputPortAsNumber(const char* name, size_t inputPortNr, uint32 portID); @@ -797,10 +797,10 @@ namespace EMotionFX virtual void RecursiveResetFlags(AnimGraphInstance* animGraphInstance, uint32 flagsToReset = 0xffffffff); - const AZStd::vector& GetInputPorts() const { return mInputPorts; } - const AZStd::vector& GetOutputPorts() const { return mOutputPorts; } - void SetInputPorts(const AZStd::vector& inputPorts) { mInputPorts = inputPorts; } - void SetOutputPorts(const AZStd::vector& outputPorts) { mOutputPorts = outputPorts; } + const AZStd::vector& GetInputPorts() const { return m_inputPorts; } + const AZStd::vector& GetOutputPorts() const { return m_outputPorts; } + void SetInputPorts(const AZStd::vector& inputPorts) { m_inputPorts = inputPorts; } + void SetOutputPorts(const AZStd::vector& outputPorts) { m_outputPorts = outputPorts; } void InitInputPorts(size_t numPorts); void InitOutputPorts(size_t numPorts); void SetInputPortName(size_t portIndex, const char* name); @@ -810,19 +810,19 @@ namespace EMotionFX size_t AddOutputPort(); size_t AddInputPort(); virtual bool GetIsStateTransitionNode() const { return false; } - MCORE_INLINE MCore::Attribute* GetOutputValue(AnimGraphInstance* animGraphInstance, size_t portIndex) const { return animGraphInstance->GetInternalAttribute(mOutputPorts[portIndex].mAttributeIndex); } - MCORE_INLINE Port& GetInputPort(size_t index) { return mInputPorts[index]; } - MCORE_INLINE Port& GetOutputPort(size_t index) { return mOutputPorts[index]; } - MCORE_INLINE const Port& GetInputPort(size_t index) const { return mInputPorts[index]; } - MCORE_INLINE const Port& GetOutputPort(size_t index) const { return mOutputPorts[index]; } + MCORE_INLINE MCore::Attribute* GetOutputValue(AnimGraphInstance* animGraphInstance, size_t portIndex) const { return animGraphInstance->GetInternalAttribute(m_outputPorts[portIndex].m_attributeIndex); } + MCORE_INLINE Port& GetInputPort(size_t index) { return m_inputPorts[index]; } + MCORE_INLINE Port& GetOutputPort(size_t index) { return m_outputPorts[index]; } + MCORE_INLINE const Port& GetInputPort(size_t index) const { return m_inputPorts[index]; } + MCORE_INLINE const Port& GetOutputPort(size_t index) const { return m_outputPorts[index]; } void RelinkPortConnections(); - MCORE_INLINE size_t GetNumConnections() const { return mConnections.size(); } - MCORE_INLINE BlendTreeConnection* GetConnection(size_t index) const { return mConnections[index]; } - const AZStd::vector& GetConnections() const { return mConnections; } + MCORE_INLINE size_t GetNumConnections() const { return m_connections.size(); } + MCORE_INLINE BlendTreeConnection* GetConnection(size_t index) const { return m_connections[index]; } + const AZStd::vector& GetConnections() const { return m_connections; } - AZ_FORCE_INLINE AnimGraphNode* GetParentNode() const { return mParentNode; } - AZ_FORCE_INLINE void SetParentNode(AnimGraphNode* node) { mParentNode = node; } + AZ_FORCE_INLINE AnimGraphNode* GetParentNode() const { return m_parentNode; } + AZ_FORCE_INLINE void SetParentNode(AnimGraphNode* node) { m_parentNode = node; } /** * Check if the given node is the parent or the parent of the parent etc. of the node. @@ -880,9 +880,9 @@ namespace EMotionFX void CopyBaseNodeTo(AnimGraphNode* node) const; - MCORE_INLINE size_t GetNumChildNodes() const { return mChildNodes.size(); } - MCORE_INLINE AnimGraphNode* GetChildNode(size_t index) const { return mChildNodes[index]; } - const AZStd::vector& GetChildNodes() const { return mChildNodes; } + MCORE_INLINE size_t GetNumChildNodes() const { return m_childNodes.size(); } + MCORE_INLINE AnimGraphNode* GetChildNode(size_t index) const { return m_childNodes[index]; } + const AZStd::vector& GetChildNodes() const { return m_childNodes; } void SetNodeInfo(const AZStd::string& info); const AZStd::string& GetNodeInfo() const; @@ -924,8 +924,8 @@ namespace EMotionFX bool GetCanVisualize(AnimGraphInstance* animGraphInstance) const; - MCORE_INLINE size_t GetNodeIndex() const { return mNodeIndex; } - MCORE_INLINE void SetNodeIndex(size_t index) { mNodeIndex = index; } + MCORE_INLINE size_t GetNodeIndex() const { return m_nodeIndex; } + MCORE_INLINE void SetNodeIndex(size_t index) { m_nodeIndex = index; } void ResetPoseRefCount(AnimGraphInstance* animGraphInstance); MCORE_INLINE void IncreasePoseRefCount(AnimGraphInstance* animGraphInstance) { FindOrCreateUniqueNodeData(animGraphInstance)->IncreasePoseRefCount(); } @@ -944,23 +944,23 @@ namespace EMotionFX static void Reflect(AZ::ReflectContext* context); protected: - size_t mNodeIndex; + size_t m_nodeIndex; AZ::u64 m_id; - AZStd::vector mConnections; - AZStd::vector mInputPorts; - AZStd::vector mOutputPorts; - AZStd::vector mChildNodes; + AZStd::vector m_connections; + AZStd::vector m_inputPorts; + AZStd::vector m_outputPorts; + AZStd::vector m_childNodes; TriggerActionSetup m_actionSetup; - AnimGraphNode* mParentNode; - void* mCustomData; - AZ::Color mVisualizeColor; + AnimGraphNode* m_parentNode; + void* m_customData; + AZ::Color m_visualizeColor; AZStd::string m_name; - AZStd::string mNodeInfo; - int32 mPosX; - int32 mPosY; - bool mDisabled; - bool mVisEnabled; - bool mIsCollapsed; + AZStd::string m_nodeInfo; + int32 m_posX; + int32 m_posY; + bool m_disabled; + bool m_visEnabled; + bool m_isCollapsed; virtual void Output(AnimGraphInstance* animGraphInstance); virtual void TopDownUpdate(AnimGraphInstance* animGraphInstance, float timePassedInSeconds); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNodeData.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNodeData.cpp index a787dd25a2..b329928c39 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNodeData.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNodeData.cpp @@ -20,19 +20,19 @@ namespace EMotionFX // constructor AnimGraphNodeData::AnimGraphNodeData(AnimGraphNode* node, AnimGraphInstance* animGraphInstance) : AnimGraphObjectData(reinterpret_cast(node), animGraphInstance) - , mDuration(0.0f) - , mCurrentTime(0.0f) - , mPlaySpeed(1.0f) - , mPreSyncTime(0.0f) - , mGlobalWeight(1.0f) - , mLocalWeight(1.0f) - , mSyncIndex(InvalidIndex) - , mPoseRefCount(0) - , mRefDataRefCount(0) - , mInheritFlags(0) + , m_duration(0.0f) + , m_currentTime(0.0f) + , m_playSpeed(1.0f) + , m_preSyncTime(0.0f) + , m_globalWeight(1.0f) + , m_localWeight(1.0f) + , m_syncIndex(InvalidIndex) + , m_poseRefCount(0) + , m_refDataRefCount(0) + , m_inheritFlags(0) , m_isMirrorMotion(false) - , mRefCountedData(nullptr) - , mSyncTrack(nullptr) + , m_refCountedData(nullptr) + , m_syncTrack(nullptr) { } @@ -47,16 +47,16 @@ namespace EMotionFX // reset the sync related data void AnimGraphNodeData::Clear() { - mDuration = 0.0f; - mCurrentTime = 0.0f; - mPreSyncTime = 0.0f; - mPlaySpeed = 1.0f; - mGlobalWeight = 1.0f; - mLocalWeight = 1.0f; - mInheritFlags = 0; + m_duration = 0.0f; + m_currentTime = 0.0f; + m_preSyncTime = 0.0f; + m_playSpeed = 1.0f; + m_globalWeight = 1.0f; + m_localWeight = 1.0f; + m_inheritFlags = 0; m_isMirrorMotion = false; - mSyncIndex = InvalidIndex; - mSyncTrack = nullptr; + m_syncIndex = InvalidIndex; + m_syncTrack = nullptr; } @@ -70,15 +70,15 @@ namespace EMotionFX // init from existing node data void AnimGraphNodeData::Init(AnimGraphNodeData* nodeData) { - mDuration = nodeData->mDuration; - mCurrentTime = nodeData->mCurrentTime; - mPreSyncTime = nodeData->mPreSyncTime; - mPlaySpeed = nodeData->mPlaySpeed; - mSyncIndex = nodeData->mSyncIndex; - mGlobalWeight = nodeData->mGlobalWeight; - mInheritFlags = nodeData->mInheritFlags; + m_duration = nodeData->m_duration; + m_currentTime = nodeData->m_currentTime; + m_preSyncTime = nodeData->m_preSyncTime; + m_playSpeed = nodeData->m_playSpeed; + m_syncIndex = nodeData->m_syncIndex; + m_globalWeight = nodeData->m_globalWeight; + m_inheritFlags = nodeData->m_inheritFlags; m_isMirrorMotion = nodeData->m_isMirrorMotion; - mSyncTrack = nodeData->mSyncTrack; + m_syncTrack = nodeData->m_syncTrack; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNodeData.h b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNodeData.h index 68d49ca511..1ad82b1d55 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNodeData.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNodeData.h @@ -51,70 +51,70 @@ namespace EMotionFX void Init(AnimGraphInstance* animGraphInstance, AnimGraphNode* node); void Init(AnimGraphNodeData* nodeData); - MCORE_INLINE AnimGraphNode* GetNode() const { return reinterpret_cast(mObject); } - MCORE_INLINE void SetNode(AnimGraphNode* node) { mObject = reinterpret_cast(node); } + MCORE_INLINE AnimGraphNode* GetNode() const { return reinterpret_cast(m_object); } + MCORE_INLINE void SetNode(AnimGraphNode* node) { m_object = reinterpret_cast(node); } - MCORE_INLINE void SetSyncIndex(size_t syncIndex) { mSyncIndex = syncIndex; } - MCORE_INLINE size_t GetSyncIndex() const { return mSyncIndex; } + MCORE_INLINE void SetSyncIndex(size_t syncIndex) { m_syncIndex = syncIndex; } + MCORE_INLINE size_t GetSyncIndex() const { return m_syncIndex; } - MCORE_INLINE void SetCurrentPlayTime(float absoluteTime) { mCurrentTime = absoluteTime; } - MCORE_INLINE float GetCurrentPlayTime() const { return mCurrentTime; } + MCORE_INLINE void SetCurrentPlayTime(float absoluteTime) { m_currentTime = absoluteTime; } + MCORE_INLINE float GetCurrentPlayTime() const { return m_currentTime; } - MCORE_INLINE void SetPlaySpeed(float speed) { mPlaySpeed = speed; } - MCORE_INLINE float GetPlaySpeed() const { return mPlaySpeed; } + MCORE_INLINE void SetPlaySpeed(float speed) { m_playSpeed = speed; } + MCORE_INLINE float GetPlaySpeed() const { return m_playSpeed; } - MCORE_INLINE void SetDuration(float durationInSeconds) { mDuration = durationInSeconds; } - MCORE_INLINE float GetDuration() const { return mDuration; } + MCORE_INLINE void SetDuration(float durationInSeconds) { m_duration = durationInSeconds; } + MCORE_INLINE float GetDuration() const { return m_duration; } - MCORE_INLINE void SetPreSyncTime(float timeInSeconds) { mPreSyncTime = timeInSeconds; } - MCORE_INLINE float GetPreSyncTime() const { return mPreSyncTime; } + MCORE_INLINE void SetPreSyncTime(float timeInSeconds) { m_preSyncTime = timeInSeconds; } + MCORE_INLINE float GetPreSyncTime() const { return m_preSyncTime; } - MCORE_INLINE void SetGlobalWeight(float weight) { mGlobalWeight = weight; } - MCORE_INLINE float GetGlobalWeight() const { return mGlobalWeight; } + MCORE_INLINE void SetGlobalWeight(float weight) { m_globalWeight = weight; } + MCORE_INLINE float GetGlobalWeight() const { return m_globalWeight; } - MCORE_INLINE void SetLocalWeight(float weight) { mLocalWeight = weight; } - MCORE_INLINE float GetLocalWeight() const { return mLocalWeight; } + MCORE_INLINE void SetLocalWeight(float weight) { m_localWeight = weight; } + MCORE_INLINE float GetLocalWeight() const { return m_localWeight; } - MCORE_INLINE uint8 GetInheritFlags() const { return mInheritFlags; } + MCORE_INLINE uint8 GetInheritFlags() const { return m_inheritFlags; } - MCORE_INLINE bool GetIsBackwardPlaying() const { return (mInheritFlags & INHERITFLAGS_BACKWARD) != 0; } - MCORE_INLINE void SetBackwardFlag() { mInheritFlags |= INHERITFLAGS_BACKWARD; } - MCORE_INLINE void ClearInheritFlags() { mInheritFlags = 0; } + MCORE_INLINE bool GetIsBackwardPlaying() const { return (m_inheritFlags & INHERITFLAGS_BACKWARD) != 0; } + MCORE_INLINE void SetBackwardFlag() { m_inheritFlags |= INHERITFLAGS_BACKWARD; } + MCORE_INLINE void ClearInheritFlags() { m_inheritFlags = 0; } - MCORE_INLINE uint8 GetPoseRefCount() const { return mPoseRefCount; } - MCORE_INLINE void IncreasePoseRefCount() { mPoseRefCount++; } - MCORE_INLINE void DecreasePoseRefCount() { mPoseRefCount--; } - MCORE_INLINE void SetPoseRefCount(uint8 refCount) { mPoseRefCount = refCount; } + MCORE_INLINE uint8 GetPoseRefCount() const { return m_poseRefCount; } + MCORE_INLINE void IncreasePoseRefCount() { m_poseRefCount++; } + MCORE_INLINE void DecreasePoseRefCount() { m_poseRefCount--; } + MCORE_INLINE void SetPoseRefCount(uint8 refCount) { m_poseRefCount = refCount; } - MCORE_INLINE uint8 GetRefDataRefCount() const { return mRefDataRefCount; } - MCORE_INLINE void IncreaseRefDataRefCount() { mRefDataRefCount++; } - MCORE_INLINE void DecreaseRefDataRefCount() { mRefDataRefCount--; } - MCORE_INLINE void SetRefDataRefCount(uint8 refCount) { mRefDataRefCount = refCount; } + MCORE_INLINE uint8 GetRefDataRefCount() const { return m_refDataRefCount; } + MCORE_INLINE void IncreaseRefDataRefCount() { m_refDataRefCount++; } + MCORE_INLINE void DecreaseRefDataRefCount() { m_refDataRefCount--; } + MCORE_INLINE void SetRefDataRefCount(uint8 refCount) { m_refDataRefCount = refCount; } - MCORE_INLINE void SetRefCountedData(AnimGraphRefCountedData* data) { mRefCountedData = data; } - MCORE_INLINE AnimGraphRefCountedData* GetRefCountedData() const { return mRefCountedData; } + MCORE_INLINE void SetRefCountedData(AnimGraphRefCountedData* data) { m_refCountedData = data; } + MCORE_INLINE AnimGraphRefCountedData* GetRefCountedData() const { return m_refCountedData; } - MCORE_INLINE const AnimGraphSyncTrack* GetSyncTrack() const { return mSyncTrack; } - MCORE_INLINE AnimGraphSyncTrack* GetSyncTrack() { return mSyncTrack; } - MCORE_INLINE void SetSyncTrack(AnimGraphSyncTrack* syncTrack) { mSyncTrack = syncTrack; } + MCORE_INLINE const AnimGraphSyncTrack* GetSyncTrack() const { return m_syncTrack; } + MCORE_INLINE AnimGraphSyncTrack* GetSyncTrack() { return m_syncTrack; } + MCORE_INLINE void SetSyncTrack(AnimGraphSyncTrack* syncTrack) { m_syncTrack = syncTrack; } bool GetIsMirrorMotion() const { return m_isMirrorMotion; } void SetIsMirrorMotion(bool newValue) { m_isMirrorMotion = newValue; } protected: - float mDuration; - float mCurrentTime; - float mPlaySpeed; - float mPreSyncTime; - float mGlobalWeight; - float mLocalWeight; - size_t mSyncIndex; /**< The last used sync track index. */ - uint8 mPoseRefCount; - uint8 mRefDataRefCount; - uint8 mInheritFlags; + float m_duration; + float m_currentTime; + float m_playSpeed; + float m_preSyncTime; + float m_globalWeight; + float m_localWeight; + size_t m_syncIndex; /**< The last used sync track index. */ + uint8 m_poseRefCount; + uint8 m_refDataRefCount; + uint8 m_inheritFlags; bool m_isMirrorMotion; - AnimGraphRefCountedData* mRefCountedData; - AnimGraphSyncTrack* mSyncTrack; + AnimGraphRefCountedData* m_refCountedData; + AnimGraphSyncTrack* m_syncTrack; void Delete() override; }; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNodeGroup.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNodeGroup.cpp index a14401d3c8..f2958cdde4 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNodeGroup.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNodeGroup.cpp @@ -17,8 +17,8 @@ namespace EMotionFX AZ_CLASS_ALLOCATOR_IMPL(AnimGraphNodeGroup, AnimGraphAllocator, 0) AnimGraphNodeGroup::AnimGraphNodeGroup() - : mColor(AZ::Color::CreateU32(255, 255, 255, 255)) - , mIsVisible(true) + : m_color(AZ::Color::CreateU32(255, 255, 255, 255)) + , m_isVisible(true) { } @@ -26,7 +26,7 @@ namespace EMotionFX AnimGraphNodeGroup::AnimGraphNodeGroup(const char* groupName) { SetName(groupName); - mIsVisible = true; + m_isVisible = true; } @@ -34,7 +34,7 @@ namespace EMotionFX { SetName(groupName); SetNumNodes(numNodes); - mIsVisible = true; + m_isVisible = true; } @@ -46,7 +46,7 @@ namespace EMotionFX void AnimGraphNodeGroup::RemoveAllNodes() { - mNodeIds.clear(); + m_nodeIds.clear(); } @@ -55,11 +55,11 @@ namespace EMotionFX { if (groupName) { - mName = groupName; + m_name = groupName; } else { - mName.clear(); + m_name.clear(); } } @@ -67,63 +67,63 @@ namespace EMotionFX // get the name of the group as character buffer const char* AnimGraphNodeGroup::GetName() const { - return mName.c_str(); + return m_name.c_str(); } // get the name of the string as mcore string object const AZStd::string& AnimGraphNodeGroup::GetNameString() const { - return mName; + return m_name; } // set the color of the group void AnimGraphNodeGroup::SetColor(const AZ::u32& color) { - mColor = color; + m_color = color; } // get the color of the group AZ::u32 AnimGraphNodeGroup::GetColor() const { - return mColor; + return m_color; } // set the visibility flag void AnimGraphNodeGroup::SetIsVisible(bool isVisible) { - mIsVisible = isVisible; + m_isVisible = isVisible; } // set the number of nodes void AnimGraphNodeGroup::SetNumNodes(size_t numNodes) { - mNodeIds.resize(numNodes); + m_nodeIds.resize(numNodes); } // get the number of nodes size_t AnimGraphNodeGroup::GetNumNodes() const { - return mNodeIds.size(); + return m_nodeIds.size(); } // set a given node to a given node number void AnimGraphNodeGroup::SetNode(size_t index, AnimGraphNodeId nodeId) { - mNodeIds[index] = nodeId; + m_nodeIds[index] = nodeId; } // get the node number of a given index AnimGraphNodeId AnimGraphNodeGroup::GetNode(size_t index) const { - return mNodeIds[index]; + return m_nodeIds[index]; } @@ -133,7 +133,7 @@ namespace EMotionFX // add the node in case it is not in yet if (Contains(nodeId) == false) { - mNodeIds.push_back(nodeId); + m_nodeIds.push_back(nodeId); } } @@ -142,14 +142,14 @@ namespace EMotionFX void AnimGraphNodeGroup::RemoveNodeById(AnimGraphNodeId nodeId) { const AZ::u64 convertedId = nodeId; - mNodeIds.erase(AZStd::remove(mNodeIds.begin(), mNodeIds.end(), convertedId), mNodeIds.end()); + m_nodeIds.erase(AZStd::remove(m_nodeIds.begin(), m_nodeIds.end(), convertedId), m_nodeIds.end()); } // remove a given array element from the list of nodes void AnimGraphNodeGroup::RemoveNodeByGroupIndex(size_t index) { - mNodeIds.erase(mNodeIds.begin() + index); + m_nodeIds.erase(m_nodeIds.begin() + index); } @@ -157,23 +157,23 @@ namespace EMotionFX bool AnimGraphNodeGroup::Contains(AnimGraphNodeId nodeId) const { const AZ::u64 convertedId = nodeId; - return AZStd::find(mNodeIds.begin(), mNodeIds.end(), convertedId) != mNodeIds.end(); + return AZStd::find(m_nodeIds.begin(), m_nodeIds.end(), convertedId) != m_nodeIds.end(); } // init from another group void AnimGraphNodeGroup::InitFrom(const AnimGraphNodeGroup& other) { - mNodeIds = other.mNodeIds; - mColor = other.mColor; - mName = other.mName; - mIsVisible = other.mIsVisible; + m_nodeIds = other.m_nodeIds; + m_color = other.m_color; + m_name = other.m_name; + m_isVisible = other.m_isVisible; } bool AnimGraphNodeGroup::GetIsVisible() const { - return mIsVisible; + return m_isVisible; } @@ -187,9 +187,9 @@ namespace EMotionFX serializeContext->Class() ->Version(1) - ->Field("nodes", &AnimGraphNodeGroup::mNodeIds) - ->Field("name", &AnimGraphNodeGroup::mName) - ->Field("color", &AnimGraphNodeGroup::mColor) - ->Field("isVisible", &AnimGraphNodeGroup::mIsVisible); + ->Field("nodes", &AnimGraphNodeGroup::m_nodeIds) + ->Field("name", &AnimGraphNodeGroup::m_name) + ->Field("color", &AnimGraphNodeGroup::m_color) + ->Field("isVisible", &AnimGraphNodeGroup::m_isVisible); } } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNodeGroup.h b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNodeGroup.h index 611cfd6824..7e1fc909e5 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNodeGroup.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphNodeGroup.h @@ -165,9 +165,9 @@ namespace EMotionFX static void Reflect(AZ::ReflectContext* context); protected: - AZStd::vector mNodeIds; /**< The node ids that are inside this group. */ - AZStd::string mName; /**< The unique identification number for the node group name. */ - AZ::u32 mColor; /**< The color the nodes of the group will be filled with. */ - bool mIsVisible; + AZStd::vector m_nodeIds; /**< The node ids that are inside this group. */ + AZStd::string m_name; /**< The unique identification number for the node group name. */ + AZ::u32 m_color; /**< The color the nodes of the group will be filled with. */ + bool m_isVisible; }; } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphObject.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphObject.cpp index 7b4afbd38a..6bee03f0ae 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphObject.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphObject.cpp @@ -27,8 +27,8 @@ namespace EMotionFX AZ_CLASS_ALLOCATOR_IMPL(AnimGraphObject, AnimGraphAllocator, 0) AnimGraphObject::AnimGraphObject() - : mAnimGraph(nullptr) - , mObjectIndex(MCORE_INVALIDINDEX32) + : m_animGraph(nullptr) + , m_objectIndex(MCORE_INVALIDINDEX32) { } @@ -36,7 +36,7 @@ namespace EMotionFX AnimGraphObject::AnimGraphObject(AnimGraph* animGraph) : AnimGraphObject() { - mAnimGraph = animGraph; + m_animGraph = animGraph; } @@ -124,17 +124,17 @@ namespace EMotionFX void AnimGraphObject::InvalidateUniqueDatas() { AnimGraphObject* object = this; - const size_t numAnimGraphInstances = mAnimGraph->GetNumAnimGraphInstances(); + const size_t numAnimGraphInstances = m_animGraph->GetNumAnimGraphInstances(); for (size_t i = 0; i < numAnimGraphInstances; ++i) { - AnimGraphInstance* animGraphInstance = mAnimGraph->GetAnimGraphInstance(i); + AnimGraphInstance* animGraphInstance = m_animGraph->GetAnimGraphInstance(i); object->InvalidateUniqueData(animGraphInstance); } } void AnimGraphObject::InvalidateUniqueData(AnimGraphInstance* animGraphInstance) { - AnimGraphObjectData* uniqueData = animGraphInstance->GetUniqueObjectData(mObjectIndex); + AnimGraphObjectData* uniqueData = animGraphInstance->GetUniqueObjectData(m_objectIndex); if (uniqueData) { uniqueData->Invalidate(); @@ -143,7 +143,7 @@ namespace EMotionFX void AnimGraphObject::ResetUniqueData(AnimGraphInstance* animGraphInstance) { - AnimGraphObjectData* uniqueData = animGraphInstance->GetUniqueObjectData(mObjectIndex); + AnimGraphObjectData* uniqueData = animGraphInstance->GetUniqueObjectData(m_objectIndex); if (uniqueData) { uniqueData->Reset(); @@ -153,10 +153,10 @@ namespace EMotionFX void AnimGraphObject::ResetUniqueDatas() { AnimGraphObject* object = this; - const size_t numAnimGraphInstances = mAnimGraph->GetNumAnimGraphInstances(); + const size_t numAnimGraphInstances = m_animGraph->GetNumAnimGraphInstances(); for (size_t i = 0; i < numAnimGraphInstances; ++i) { - AnimGraphInstance* animGraphInstance = mAnimGraph->GetAnimGraphInstance(i); + AnimGraphInstance* animGraphInstance = m_animGraph->GetAnimGraphInstance(i); object->ResetUniqueData(animGraphInstance); } } @@ -165,7 +165,7 @@ namespace EMotionFX void AnimGraphObject::Update(AnimGraphInstance* animGraphInstance, float timePassedInSeconds) { MCORE_UNUSED(timePassedInSeconds); - animGraphInstance->EnableObjectFlags(mObjectIndex, AnimGraphInstance::OBJECTFLAGS_UPDATE_READY); + animGraphInstance->EnableObjectFlags(m_objectIndex, AnimGraphInstance::OBJECTFLAGS_UPDATE_READY); } void AnimGraphObject::Reinit() @@ -230,15 +230,15 @@ namespace EMotionFX // does the init for all anim graph instances in the parent animgraph void AnimGraphObject::InitInternalAttributesForAllInstances() { - if (mAnimGraph == nullptr) + if (m_animGraph == nullptr) { return; } - const size_t numInstances = mAnimGraph->GetNumAnimGraphInstances(); + const size_t numInstances = m_animGraph->GetNumAnimGraphInstances(); for (size_t i = 0; i < numInstances; ++i) { - InitInternalAttributes(mAnimGraph->GetAnimGraphInstance(i)); + InitInternalAttributes(m_animGraph->GetAnimGraphInstance(i)); } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphObject.h b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphObject.h index 32905d66a7..ebc92964b0 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphObject.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphObject.h @@ -144,11 +144,11 @@ namespace EMotionFX virtual void RecursiveOnChangeMotionSet(AnimGraphInstance* animGraphInstance, MotionSet* newMotionSet) { MCORE_UNUSED(animGraphInstance); MCORE_UNUSED(newMotionSet); } virtual void OnActorMotionExtractionNodeChanged() {} - MCORE_INLINE size_t GetObjectIndex() const { return mObjectIndex; } - MCORE_INLINE void SetObjectIndex(size_t index) { mObjectIndex = index; } + MCORE_INLINE size_t GetObjectIndex() const { return m_objectIndex; } + MCORE_INLINE void SetObjectIndex(size_t index) { m_objectIndex = index; } - MCORE_INLINE AnimGraph* GetAnimGraph() const { return mAnimGraph; } - MCORE_INLINE void SetAnimGraph(AnimGraph* animGraph) { mAnimGraph = animGraph; } + MCORE_INLINE AnimGraph* GetAnimGraph() const { return m_animGraph; } + MCORE_INLINE void SetAnimGraph(AnimGraph* animGraph) { m_animGraph = animGraph; } size_t SaveUniqueData(AnimGraphInstance* animGraphInstance, uint8* outputBuffer) const; // save and return number of bytes written, when outputBuffer is nullptr only return num bytes it would write size_t LoadUniqueData(AnimGraphInstance* animGraphInstance, const uint8* dataBuffer); // load and return number of bytes read, when dataBuffer is nullptr, 0 should be returned @@ -166,8 +166,8 @@ namespace EMotionFX static void Reflect(AZ::ReflectContext* context); protected: - AnimGraph* mAnimGraph; - size_t mObjectIndex; + AnimGraph* m_animGraph; + size_t m_objectIndex; }; } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphObjectData.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphObjectData.cpp index 3434294747..9c3a7022d1 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphObjectData.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphObjectData.cpp @@ -20,9 +20,9 @@ namespace EMotionFX AnimGraphObjectData::AnimGraphObjectData(AnimGraphObject* object, AnimGraphInstance* animGraphInstance) : BaseObject() { - mObject = object; - mAnimGraphInstance = animGraphInstance; - mObjectFlags = 0; + m_object = object; + m_animGraphInstance = animGraphInstance; + m_objectFlags = 0; } AnimGraphObjectData::~AnimGraphObjectData() diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphObjectData.h b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphObjectData.h index e9cb1ea809..25f28282bd 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphObjectData.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphObjectData.h @@ -70,8 +70,8 @@ public: \ AnimGraphObjectData(AnimGraphObject* object, AnimGraphInstance* animGraphInstance); virtual ~AnimGraphObjectData(); - MCORE_INLINE AnimGraphObject* GetObject() const { return mObject; } - void SetObject(AnimGraphObject* object) { mObject = object; } + MCORE_INLINE AnimGraphObject* GetObject() const { return m_object; } + void SetObject(AnimGraphObject* object) { m_object = object; } // save and return number of bytes written, when outputBuffer is nullptr only return num bytes it would write virtual uint32 Save(uint8* outputBuffer) const; @@ -91,33 +91,33 @@ public: \ bool IsInvalidated() const { return m_invalidated; } void Validate() { m_invalidated = false; } - MCORE_INLINE uint8 GetObjectFlags() const { return mObjectFlags; } - MCORE_INLINE void SetObjectFlags(uint8 flags) { mObjectFlags = flags; } - MCORE_INLINE void EnableObjectFlags(uint8 flagsToEnable) { mObjectFlags |= flagsToEnable; } - MCORE_INLINE void DisableObjectFlags(uint8 flagsToDisable) { mObjectFlags &= ~flagsToDisable; } + MCORE_INLINE uint8 GetObjectFlags() const { return m_objectFlags; } + MCORE_INLINE void SetObjectFlags(uint8 flags) { m_objectFlags = flags; } + MCORE_INLINE void EnableObjectFlags(uint8 flagsToEnable) { m_objectFlags |= flagsToEnable; } + MCORE_INLINE void DisableObjectFlags(uint8 flagsToDisable) { m_objectFlags &= ~flagsToDisable; } MCORE_INLINE void SetObjectFlags(uint8 flags, bool enabled) { if (enabled) { - mObjectFlags |= flags; + m_objectFlags |= flags; } else { - mObjectFlags &= ~flags; + m_objectFlags &= ~flags; } } - MCORE_INLINE bool GetIsObjectFlagEnabled(uint8 flag) const { return (mObjectFlags & flag) != 0; } + MCORE_INLINE bool GetIsObjectFlagEnabled(uint8 flag) const { return (m_objectFlags & flag) != 0; } - MCORE_INLINE bool GetHasError() const { return (mObjectFlags & FLAGS_HAS_ERROR); } + MCORE_INLINE bool GetHasError() const { return (m_objectFlags & FLAGS_HAS_ERROR); } MCORE_INLINE void SetHasError(bool hasError) { SetObjectFlags(FLAGS_HAS_ERROR, hasError); } - AnimGraphInstance* GetAnimGraphInstance() { return mAnimGraphInstance; } - const AnimGraphInstance* GetAnimGraphInstance() const { return mAnimGraphInstance; } + AnimGraphInstance* GetAnimGraphInstance() { return m_animGraphInstance; } + const AnimGraphInstance* GetAnimGraphInstance() const { return m_animGraphInstance; } protected: - AnimGraphObject* mObject; /**< Pointer to the object where this data belongs to. */ - AnimGraphInstance* mAnimGraphInstance; /**< The animgraph instance where this unique data belongs to. */ - uint8 mObjectFlags; + AnimGraphObject* m_object; /**< Pointer to the object where this data belongs to. */ + AnimGraphInstance* m_animGraphInstance; /**< The animgraph instance where this unique data belongs to. */ + uint8 m_objectFlags; bool m_invalidated = true; }; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphParameterAction.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphParameterAction.cpp index c1a35b9399..ec3eb91056 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphParameterAction.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphParameterAction.cpp @@ -46,10 +46,10 @@ namespace EMotionFX void AnimGraphParameterAction::Reinit() { // Find the parameter index for the given parameter name, to prevent string based lookups every frame - m_parameterIndex = mAnimGraph->FindValueParameterIndexByName(m_parameterName); + m_parameterIndex = m_animGraph->FindValueParameterIndexByName(m_parameterName); if (m_parameterIndex.IsSuccess()) { - m_valueParameter = mAnimGraph->FindValueParameter(m_parameterIndex.GetValue()); + m_valueParameter = m_animGraph->FindValueParameter(m_parameterIndex.GetValue()); } else { @@ -123,7 +123,7 @@ namespace EMotionFX void AnimGraphParameterAction::SetParameterName(const AZStd::string& parameterName) { m_parameterName = parameterName; - if (mAnimGraph) + if (m_animGraph) { Reinit(); } @@ -142,7 +142,7 @@ namespace EMotionFX if (m_parameterIndex.IsSuccess()) { // get access to the parameter info and return the type of its default value - const ValueParameter* valueParameter = mAnimGraph->FindValueParameter(m_parameterIndex.GetValue()); + const ValueParameter* valueParameter = m_animGraph->FindValueParameter(m_parameterIndex.GetValue()); return azrtti_typeid(valueParameter); } else @@ -186,7 +186,7 @@ namespace EMotionFX { AZ_UNUSED(beforeChange); AZ_UNUSED(afterChange); - m_parameterIndex = mAnimGraph->FindValueParameterIndexByName(m_parameterName); + m_parameterIndex = m_animGraph->FindValueParameterIndexByName(m_parameterName); } void AnimGraphParameterAction::ParameterRemoved(const AZStd::string& oldParameterName) @@ -198,7 +198,7 @@ namespace EMotionFX } else { - m_parameterIndex = mAnimGraph->FindValueParameterIndexByName(m_parameterName); + m_parameterIndex = m_animGraph->FindValueParameterIndexByName(m_parameterName); } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphParameterCondition.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphParameterCondition.cpp index 052175eb92..c79a24690c 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphParameterCondition.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphParameterCondition.cpp @@ -78,7 +78,7 @@ namespace EMotionFX void AnimGraphParameterCondition::Reinit() { // Find the parameter index for the given parameter name, to prevent string based lookups every frame - m_parameterIndex = mAnimGraph->FindValueParameterIndexByName(m_parameterName); + m_parameterIndex = m_animGraph->FindValueParameterIndexByName(m_parameterName); SetFunction(m_function); } @@ -114,7 +114,7 @@ namespace EMotionFX void AnimGraphParameterCondition::SetParameterName(const AZStd::string& parameterName) { m_parameterName = parameterName; - if (mAnimGraph) + if (m_animGraph) { Reinit(); } @@ -131,7 +131,7 @@ namespace EMotionFX if (m_parameterIndex.IsSuccess()) { // get access to the parameter info and return the type of its default value - const ValueParameter* valueParameter = mAnimGraph->FindValueParameter(m_parameterIndex.GetValue()); + const ValueParameter* valueParameter = m_animGraph->FindValueParameter(m_parameterIndex.GetValue()); return azrtti_typeid(valueParameter); } return AZ::TypeId::CreateNull(); @@ -144,7 +144,7 @@ namespace EMotionFX return false; } - const ValueParameter* valueParameter = mAnimGraph->FindValueParameter(m_parameterIndex.GetValue()); + const ValueParameter* valueParameter = m_animGraph->FindValueParameter(m_parameterIndex.GetValue()); if (!valueParameter) { return false; @@ -500,7 +500,7 @@ namespace EMotionFX if (!newParameterMask.empty()) { m_parameterName = *newParameterMask.begin(); - m_parameterIndex = mAnimGraph->FindValueParameterIndexByName(m_parameterName); + m_parameterIndex = m_animGraph->FindValueParameterIndexByName(m_parameterName); } } @@ -514,7 +514,7 @@ namespace EMotionFX { AZ_UNUSED(newParameterName); // Just recompute the index in the case the new parameter was inserted before ours - m_parameterIndex = mAnimGraph->FindValueParameterIndexByName(m_parameterName); + m_parameterIndex = m_animGraph->FindValueParameterIndexByName(m_parameterName); } void AnimGraphParameterCondition::ParameterRenamed(const AZStd::string& oldParameterName, const AZStd::string& newParameterName) @@ -530,7 +530,7 @@ namespace EMotionFX AZ_UNUSED(beforeChange); AZ_UNUSED(afterChange); // Just recompute the index - m_parameterIndex = mAnimGraph->FindValueParameterIndexByName(m_parameterName); + m_parameterIndex = m_animGraph->FindValueParameterIndexByName(m_parameterName); } void AnimGraphParameterCondition::ParameterRemoved(const AZStd::string& oldParameterName) @@ -542,7 +542,7 @@ namespace EMotionFX } else { - m_parameterIndex = mAnimGraph->FindValueParameterIndexByName(m_parameterName); + m_parameterIndex = m_animGraph->FindValueParameterIndexByName(m_parameterName); } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphPlayTimeCondition.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphPlayTimeCondition.cpp index 1a80a5a09b..125491dc21 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphPlayTimeCondition.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphPlayTimeCondition.cpp @@ -56,7 +56,7 @@ namespace EMotionFX return; } - m_node = mAnimGraph->RecursiveFindNodeById(m_nodeId); + m_node = m_animGraph->RecursiveFindNodeById(m_nodeId); } @@ -181,7 +181,7 @@ namespace EMotionFX void AnimGraphPlayTimeCondition::SetNodeId(AnimGraphNodeId nodeId) { m_nodeId = nodeId; - if (mAnimGraph) + if (m_animGraph) { Reinit(); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphPose.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphPose.cpp index 7918d73c3c..595f434c1c 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphPose.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphPose.cpp @@ -18,16 +18,15 @@ namespace EMotionFX // constructor AnimGraphPose::AnimGraphPose() { - mFlags = 0; + m_flags = 0; } // copy constructor AnimGraphPose::AnimGraphPose(const AnimGraphPose& other) { - mFlags = 0; - mPose.InitFromPose(&other.mPose); - //mFlags = other.mFlags; + m_flags = 0; + m_pose.InitFromPose(&other.m_pose); } @@ -40,8 +39,7 @@ namespace EMotionFX // = operator AnimGraphPose& AnimGraphPose::operator=(const AnimGraphPose& other) { - mPose.InitFromPose(&other.mPose); - //mFlags = other.mFlags; + m_pose.InitFromPose(&other.m_pose); return *this; } @@ -50,7 +48,7 @@ namespace EMotionFX void AnimGraphPose::LinkToActorInstance(const ActorInstance* actorInstance) { // resize the transformation buffer, which contains the local space transformations - mPose.LinkToActorInstance(actorInstance); + m_pose.LinkToActorInstance(actorInstance); } @@ -61,7 +59,7 @@ namespace EMotionFX LinkToActorInstance(actorInstance); // fill the local pose with the bind pose - mPose.InitFromBindPose(actorInstance); + m_pose.InitFromBindPose(actorInstance); } } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphPose.h b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphPose.h index a2b21aec6a..b46faddf7f 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphPose.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphPose.h @@ -39,29 +39,29 @@ namespace EMotionFX void LinkToActorInstance(const ActorInstance* actorInstance); void InitFromBindPose(const ActorInstance* actorInstance); - MCORE_INLINE size_t GetNumNodes() const { return mPose.GetNumTransforms(); } - MCORE_INLINE const Pose& GetPose() const { return mPose; } - MCORE_INLINE Pose& GetPose() { return mPose; } - MCORE_INLINE void SetPose(const Pose& pose) { mPose = pose; } - MCORE_INLINE const ActorInstance* GetActorInstance() const { return mPose.GetActorInstance(); } + MCORE_INLINE size_t GetNumNodes() const { return m_pose.GetNumTransforms(); } + MCORE_INLINE const Pose& GetPose() const { return m_pose; } + MCORE_INLINE Pose& GetPose() { return m_pose; } + MCORE_INLINE void SetPose(const Pose& pose) { m_pose = pose; } + MCORE_INLINE const ActorInstance* GetActorInstance() const { return m_pose.GetActorInstance(); } - MCORE_INLINE bool GetIsInUse() const { return (mFlags & FLAG_INUSE); } + MCORE_INLINE bool GetIsInUse() const { return (m_flags & FLAG_INUSE); } MCORE_INLINE void SetIsInUse(bool inUse) { if (inUse) { - mFlags |= FLAG_INUSE; + m_flags |= FLAG_INUSE; } else { - mFlags &= ~FLAG_INUSE; + m_flags &= ~FLAG_INUSE; } } AnimGraphPose& operator=(const AnimGraphPose& other); private: - Pose mPose; /**< The pose, containing the node transformation. */ - uint8 mFlags; /**< The flags. */ + Pose m_pose; /**< The pose, containing the node transformation. */ + uint8 m_flags; /**< The flags. */ }; } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphPosePool.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphPosePool.cpp index f7f3a6c0bf..4d9d2ca999 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphPosePool.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphPosePool.cpp @@ -16,10 +16,10 @@ namespace EMotionFX // constructor AnimGraphPosePool::AnimGraphPosePool() { - mPoses.reserve(12); - mFreePoses.reserve(12); + m_poses.reserve(12); + m_freePoses.reserve(12); Resize(8); - mMaxUsed = 0; + m_maxUsed = 0; } @@ -27,21 +27,21 @@ namespace EMotionFX AnimGraphPosePool::~AnimGraphPosePool() { // delete all poses - for (AnimGraphPose* pose : mPoses) + for (AnimGraphPose* pose : m_poses) { delete pose; } - mPoses.clear(); + m_poses.clear(); // clear the free array - mFreePoses.clear(); + m_freePoses.clear(); } // resize the number of poses in the pool void AnimGraphPosePool::Resize(size_t numPoses) { - const size_t numOldPoses = mPoses.size(); + const size_t numOldPoses = m_poses.size(); // if we will remove poses if (numPoses < numOldPoses) @@ -50,10 +50,10 @@ namespace EMotionFX const size_t numToRemove = numOldPoses - numPoses; for (size_t i = 0; i < numToRemove; ++i) { - AnimGraphPose* pose = mPoses.back(); - MCORE_ASSERT(AZStd::find(begin(mFreePoses), end(mFreePoses), pose) == end(mFreePoses)); // make sure the pose is not already in use + AnimGraphPose* pose = m_poses.back(); + MCORE_ASSERT(AZStd::find(begin(m_freePoses), end(m_freePoses), pose) == end(m_freePoses)); // make sure the pose is not already in use delete pose; - mPoses.erase(mFreePoses.end() - 1); + m_poses.erase(m_freePoses.end() - 1); } } else // we want to add new poses @@ -62,8 +62,8 @@ namespace EMotionFX for (size_t i = 0; i < numToAdd; ++i) { AnimGraphPose* newPose = new AnimGraphPose(); - mPoses.emplace_back(newPose); - mFreePoses.emplace_back(newPose); + m_poses.emplace_back(newPose); + m_freePoses.emplace_back(newPose); } } } @@ -73,22 +73,22 @@ namespace EMotionFX AnimGraphPose* AnimGraphPosePool::RequestPose(const ActorInstance* actorInstance) { // if we have no free poses left, allocate a new one - if (mFreePoses.empty()) + if (m_freePoses.empty()) { AnimGraphPose* newPose = new AnimGraphPose(); newPose->LinkToActorInstance(actorInstance); - mPoses.emplace_back(newPose); - mMaxUsed = AZStd::max(mMaxUsed, GetNumUsedPoses()); + m_poses.emplace_back(newPose); + m_maxUsed = AZStd::max(m_maxUsed, GetNumUsedPoses()); newPose->SetIsInUse(true); return newPose; } // request the last free pose - AnimGraphPose* pose = mFreePoses[mFreePoses.size() - 1]; + AnimGraphPose* pose = m_freePoses[m_freePoses.size() - 1]; //if (pose->GetActorInstance() != actorInstance) pose->LinkToActorInstance(actorInstance); - mFreePoses.pop_back(); // remove it from the list of free poses - mMaxUsed = AZStd::max(mMaxUsed, GetNumUsedPoses()); + m_freePoses.pop_back(); // remove it from the list of free poses + m_maxUsed = AZStd::max(m_maxUsed, GetNumUsedPoses()); pose->SetIsInUse(true); return pose; } @@ -97,8 +97,7 @@ namespace EMotionFX // free the pose again void AnimGraphPosePool::FreePose(AnimGraphPose* pose) { - //MCORE_ASSERT( mPoses.Contains(pose) ); - mFreePoses.emplace_back(pose); + m_freePoses.emplace_back(pose); pose->SetIsInUse(false); } @@ -106,7 +105,7 @@ namespace EMotionFX // free all poses void AnimGraphPosePool::FreeAllPoses() { - for (AnimGraphPose* curPose : mPoses) + for (AnimGraphPose* curPose : m_poses) { if (curPose->GetIsInUse()) { diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphPosePool.h b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphPosePool.h index 8148d88926..a7244e2dc2 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphPosePool.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphPosePool.h @@ -41,15 +41,15 @@ namespace EMotionFX void FreeAllPoses(); - MCORE_INLINE size_t GetNumFreePoses() const { return mFreePoses.size(); } - MCORE_INLINE size_t GetNumPoses() const { return mPoses.size(); } - MCORE_INLINE size_t GetNumUsedPoses() const { return mPoses.size() - mFreePoses.size(); } - MCORE_INLINE size_t GetNumMaxUsedPoses() const { return mMaxUsed; } - MCORE_INLINE void ResetMaxUsedPoses() { mMaxUsed = 0; } + MCORE_INLINE size_t GetNumFreePoses() const { return m_freePoses.size(); } + MCORE_INLINE size_t GetNumPoses() const { return m_poses.size(); } + MCORE_INLINE size_t GetNumUsedPoses() const { return m_poses.size() - m_freePoses.size(); } + MCORE_INLINE size_t GetNumMaxUsedPoses() const { return m_maxUsed; } + MCORE_INLINE void ResetMaxUsedPoses() { m_maxUsed = 0; } private: - AZStd::vector mPoses; - AZStd::vector mFreePoses; - size_t mMaxUsed; + AZStd::vector m_poses; + AZStd::vector m_freePoses; + size_t m_maxUsed; }; } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphRefCountedData.h b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphRefCountedData.h index f3d04eeacb..2d4c1624ba 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphRefCountedData.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphRefCountedData.h @@ -29,24 +29,24 @@ namespace EMotionFX MCORE_INLINE AnimGraphRefCountedData() = default; MCORE_INLINE ~AnimGraphRefCountedData() = default; - MCORE_INLINE AnimGraphEventBuffer& GetEventBuffer() { return mEventBuffer; } - MCORE_INLINE const AnimGraphEventBuffer& GetEventBuffer() const { return mEventBuffer; } - MCORE_INLINE void SetEventBuffer(const AnimGraphEventBuffer& buf) { mEventBuffer = buf; } - MCORE_INLINE void ClearEventBuffer() { mEventBuffer.Clear(); } + MCORE_INLINE AnimGraphEventBuffer& GetEventBuffer() { return m_eventBuffer; } + MCORE_INLINE const AnimGraphEventBuffer& GetEventBuffer() const { return m_eventBuffer; } + MCORE_INLINE void SetEventBuffer(const AnimGraphEventBuffer& buf) { m_eventBuffer = buf; } + MCORE_INLINE void ClearEventBuffer() { m_eventBuffer.Clear(); } - MCORE_INLINE Transform& GetTrajectoryDelta() { return mTrajectoryDelta; } - MCORE_INLINE const Transform& GetTrajectoryDelta() const { return mTrajectoryDelta; } - MCORE_INLINE void SetTrajectoryDelta(const Transform& transform) { mTrajectoryDelta = transform; } + MCORE_INLINE Transform& GetTrajectoryDelta() { return m_trajectoryDelta; } + MCORE_INLINE const Transform& GetTrajectoryDelta() const { return m_trajectoryDelta; } + MCORE_INLINE void SetTrajectoryDelta(const Transform& transform) { m_trajectoryDelta = transform; } - MCORE_INLINE Transform& GetTrajectoryDeltaMirrored() { return mTrajectoryDeltaMirrored; } - MCORE_INLINE const Transform& GetTrajectoryDeltaMirrored() const { return mTrajectoryDeltaMirrored; } - MCORE_INLINE void SetTrajectoryDeltaMirrored(const Transform& tform) { mTrajectoryDeltaMirrored = tform; } + MCORE_INLINE Transform& GetTrajectoryDeltaMirrored() { return m_trajectoryDeltaMirrored; } + MCORE_INLINE const Transform& GetTrajectoryDeltaMirrored() const { return m_trajectoryDeltaMirrored; } + MCORE_INLINE void SetTrajectoryDeltaMirrored(const Transform& tform) { m_trajectoryDeltaMirrored = tform; } - MCORE_INLINE void ZeroTrajectoryDelta() { mTrajectoryDelta.IdentityWithZeroScale(); mTrajectoryDeltaMirrored.IdentityWithZeroScale(); } + MCORE_INLINE void ZeroTrajectoryDelta() { m_trajectoryDelta.IdentityWithZeroScale(); m_trajectoryDeltaMirrored.IdentityWithZeroScale(); } private: - AnimGraphEventBuffer mEventBuffer; - Transform mTrajectoryDelta = Transform::CreateIdentityWithZeroScale(); - Transform mTrajectoryDeltaMirrored = Transform::CreateIdentityWithZeroScale(); + AnimGraphEventBuffer m_eventBuffer; + Transform m_trajectoryDelta = Transform::CreateIdentityWithZeroScale(); + Transform m_trajectoryDeltaMirrored = Transform::CreateIdentityWithZeroScale(); }; } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphRefCountedDataPool.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphRefCountedDataPool.cpp index 1a04f18375..4fdcaea7f6 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphRefCountedDataPool.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphRefCountedDataPool.cpp @@ -17,10 +17,10 @@ namespace EMotionFX // constructor AnimGraphRefCountedDataPool::AnimGraphRefCountedDataPool() { - mItems.reserve(32); - mFreeItems.reserve(32); + m_items.reserve(32); + m_freeItems.reserve(32); Resize(16); - mMaxUsed = 0; + m_maxUsed = 0; } @@ -28,21 +28,21 @@ namespace EMotionFX AnimGraphRefCountedDataPool::~AnimGraphRefCountedDataPool() { // delete all items - for (AnimGraphRefCountedData*& item : mItems) + for (AnimGraphRefCountedData*& item : m_items) { delete item; } - mItems.clear(); + m_items.clear(); // clear the free array - mFreeItems.clear(); + m_freeItems.clear(); } // resize the number of items in the pool void AnimGraphRefCountedDataPool::Resize(size_t numItems) { - const size_t numOldItems = mItems.size(); + const size_t numOldItems = m_items.size(); // if we will remove Items if (numItems < numOldItems) @@ -51,10 +51,10 @@ namespace EMotionFX const size_t numToRemove = numOldItems - numItems; for (size_t i = 0; i < numToRemove; ++i) { - AnimGraphRefCountedData* item = mItems.back(); - MCORE_ASSERT(AZStd::find(begin(mFreeItems), end(mFreeItems), item) != end(mFreeItems)); // make sure the Item is not already in use + AnimGraphRefCountedData* item = m_items.back(); + MCORE_ASSERT(AZStd::find(begin(m_freeItems), end(m_freeItems), item) != end(m_freeItems)); // make sure the Item is not already in use delete item; - mItems.erase(mItems.end() - 1); + m_items.erase(m_items.end() - 1); } } else // we want to add new Items @@ -63,8 +63,8 @@ namespace EMotionFX for (size_t i = 0; i < numToAdd; ++i) { AnimGraphRefCountedData* newItem = new AnimGraphRefCountedData(); - mItems.emplace_back(newItem); - mFreeItems.emplace_back(newItem); + m_items.emplace_back(newItem); + m_freeItems.emplace_back(newItem); } } } @@ -74,18 +74,18 @@ namespace EMotionFX AnimGraphRefCountedData* AnimGraphRefCountedDataPool::RequestNew() { // if we have no free items left, allocate a new one - if (mFreeItems.empty()) + if (m_freeItems.empty()) { AnimGraphRefCountedData* newItem = new AnimGraphRefCountedData(); - mItems.emplace_back(newItem); - mMaxUsed = AZStd::max(mMaxUsed, GetNumUsedItems()); + m_items.emplace_back(newItem); + m_maxUsed = AZStd::max(m_maxUsed, GetNumUsedItems()); return newItem; } // request the last free item - AnimGraphRefCountedData* item = mFreeItems[mFreeItems.size() - 1]; - mFreeItems.pop_back(); // remove it from the list of free Items - mMaxUsed = AZStd::max(mMaxUsed, GetNumUsedItems()); + AnimGraphRefCountedData* item = m_freeItems[m_freeItems.size() - 1]; + m_freeItems.pop_back(); // remove it from the list of free Items + m_maxUsed = AZStd::max(m_maxUsed, GetNumUsedItems()); return item; } @@ -93,7 +93,7 @@ namespace EMotionFX // free the item again void AnimGraphRefCountedDataPool::Free(AnimGraphRefCountedData* item) { - MCORE_ASSERT(AZStd::find(begin(mItems), end(mItems), item) != end(mItems)); - mFreeItems.emplace_back(item); + MCORE_ASSERT(AZStd::find(begin(m_items), end(m_items), item) != end(m_items)); + m_freeItems.emplace_back(item); } } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphRefCountedDataPool.h b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphRefCountedDataPool.h index d05ea5b5a1..3a7c38ed00 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphRefCountedDataPool.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphRefCountedDataPool.h @@ -34,15 +34,15 @@ namespace EMotionFX AnimGraphRefCountedData* RequestNew(); void Free(AnimGraphRefCountedData* item); - MCORE_INLINE size_t GetNumFreeItems() const { return mFreeItems.size(); } - MCORE_INLINE size_t GetNumItems() const { return mItems.size(); } - MCORE_INLINE size_t GetNumUsedItems() const { return mItems.size() - mFreeItems.size(); } - MCORE_INLINE size_t GetNumMaxUsedItems() const { return mMaxUsed; } - MCORE_INLINE void ResetMaxUsedItems() { mMaxUsed = 0; } + MCORE_INLINE size_t GetNumFreeItems() const { return m_freeItems.size(); } + MCORE_INLINE size_t GetNumItems() const { return m_items.size(); } + MCORE_INLINE size_t GetNumUsedItems() const { return m_items.size() - m_freeItems.size(); } + MCORE_INLINE size_t GetNumMaxUsedItems() const { return m_maxUsed; } + MCORE_INLINE void ResetMaxUsedItems() { m_maxUsed = 0; } private: - AZStd::vector mItems; - AZStd::vector mFreeItems; - size_t mMaxUsed; + AZStd::vector m_items; + AZStd::vector m_freeItems; + size_t m_maxUsed; }; } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphReferenceNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphReferenceNode.cpp index a1f9af2935..605810c5cc 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphReferenceNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphReferenceNode.cpp @@ -68,7 +68,7 @@ namespace EMotionFX void AnimGraphReferenceNode::UniqueData::Update() { - AnimGraphReferenceNode* referenceNode = azdynamic_cast(mObject); + AnimGraphReferenceNode* referenceNode = azdynamic_cast(m_object); AZ_Assert(referenceNode, "Unique data linked to incorrect node type."); MotionSet* motionSet = referenceNode->GetMotionSet(); @@ -116,10 +116,10 @@ namespace EMotionFX { // This node listens to changes in AnimGraph and MotionSet assets. We need to remove this node before disconnecting the asset bus to avoid the disconnect // removing the MotionSet which can in turn access this node that is being deleted. - if (mAnimGraph) + if (m_animGraph) { - mAnimGraph->RemoveObject(this); - mAnimGraph = nullptr; + m_animGraph->RemoveObject(this); + m_animGraph = nullptr; } AZ::Data::AssetBus::MultiHandler::BusDisconnect(); } @@ -296,9 +296,9 @@ namespace EMotionFX } // Update the values for attributes that are fed through a connection - AZ_Assert(mInputPorts.size() == m_parameterIndexByPortIndex.size(), "Expected m_parameterIndexByPortIndex and numInputPorts to be in sync"); + AZ_Assert(m_inputPorts.size() == m_parameterIndexByPortIndex.size(), "Expected m_parameterIndexByPortIndex and numInputPorts to be in sync"); - const uint32 numInputPorts = static_cast(mInputPorts.size()); + const uint32 numInputPorts = static_cast(m_inputPorts.size()); for (uint32 i = 0; i < numInputPorts; ++i) { MCore::Attribute* attribute = GetInputAttribute(animGraphInstance, i); // returns the attribute of the upstream side of the connection @@ -437,7 +437,7 @@ namespace EMotionFX AnimGraph* referencedAnimGraph = GetReferencedAnimGraph(); if (referencedAnimGraph) { - UniqueData* uniqueData = static_cast(animGraphInstance->GetUniqueObjectData(mObjectIndex)); + UniqueData* uniqueData = static_cast(animGraphInstance->GetUniqueObjectData(m_objectIndex)); if (uniqueData && uniqueData->m_referencedAnimGraphInstance) { uniqueData->m_referencedAnimGraphInstance->RecursiveInvalidateUniqueDatas(); @@ -531,10 +531,10 @@ namespace EMotionFX // Use an anim graph instance to recursively go through the parents. If we hit a parent that is referenceAnimGraph, // that means that the child we are about to add is a parent, therefore a cycle - const size_t numAnimGraphInstances = mAnimGraph->GetNumAnimGraphInstances(); + const size_t numAnimGraphInstances = m_animGraph->GetNumAnimGraphInstances(); if (numAnimGraphInstances > 0) { - AnimGraphInstance* animGraphInstance = mAnimGraph->GetAnimGraphInstance(0); + AnimGraphInstance* animGraphInstance = m_animGraph->GetAnimGraphInstance(0); do { if (animGraphInstance->GetAnimGraph() == referenceAnimGraph) @@ -627,11 +627,11 @@ namespace EMotionFX { // Inform the unique datas as well as other systems about the changed anim graph asset, destroy and nullptr the reference // anim graph instances so that we don't try to update an anim graph instance or while the asset already got destructed. - const size_t numAnimGraphInstances = mAnimGraph->GetNumAnimGraphInstances(); + const size_t numAnimGraphInstances = m_animGraph->GetNumAnimGraphInstances(); for (size_t i = 0; i < numAnimGraphInstances; ++i) { - AnimGraphInstance* animGraphInstance = mAnimGraph->GetAnimGraphInstance(i); - UniqueData* uniqueData = static_cast(animGraphInstance->GetUniqueObjectData(mObjectIndex)); + AnimGraphInstance* animGraphInstance = m_animGraph->GetAnimGraphInstance(i); + UniqueData* uniqueData = static_cast(animGraphInstance->GetUniqueObjectData(m_objectIndex)); if (uniqueData) { uniqueData->OnReferenceAnimGraphAssetChanged(); @@ -667,11 +667,11 @@ namespace EMotionFX void AnimGraphReferenceNode::OnMaskedParametersChanged() { - const size_t numAnimGraphInstances = mAnimGraph->GetNumAnimGraphInstances(); + const size_t numAnimGraphInstances = m_animGraph->GetNumAnimGraphInstances(); for (size_t i = 0; i < numAnimGraphInstances; ++i) { - AnimGraphInstance* animGraphInstance = mAnimGraph->GetAnimGraphInstance(i); - UniqueData* uniqueData = static_cast(animGraphInstance->GetUniqueObjectData(mObjectIndex)); + AnimGraphInstance* animGraphInstance = m_animGraph->GetAnimGraphInstance(i); + UniqueData* uniqueData = static_cast(animGraphInstance->GetUniqueObjectData(m_objectIndex)); if (uniqueData) { uniqueData->m_parameterMappingCacheDirty = true; @@ -834,10 +834,10 @@ namespace EMotionFX { MotionSet* motionSet = GetMotionSet(); - const size_t numAnimGraphInstances = mAnimGraph->GetNumAnimGraphInstances(); + const size_t numAnimGraphInstances = m_animGraph->GetNumAnimGraphInstances(); for (size_t i = 0; i < numAnimGraphInstances; ++i) { - AnimGraphInstance* animGraphInstance = mAnimGraph->GetAnimGraphInstance(i); + AnimGraphInstance* animGraphInstance = m_animGraph->GetAnimGraphInstance(i); UniqueData* uniqueData = static_cast(FindOrCreateUniqueNodeData(animGraphInstance)); if (uniqueData->m_referencedAnimGraphInstance) @@ -886,7 +886,7 @@ namespace EMotionFX // exclude those parameters for (const AnimGraphNode::Port& port : GetInputPorts()) { - if (port.mConnection) + if (port.m_connection) { parameterNames.emplace_back(port.GetNameString()); } @@ -979,7 +979,7 @@ namespace EMotionFX AZ_Assert(!GetNumConnections(), "Unexpected connections"); - const ValueParameterVector& valueParameters = mAnimGraph->RecursivelyGetValueParameters(); + const ValueParameterVector& valueParameters = m_animGraph->RecursivelyGetValueParameters(); const ValueParameterVector& referencedValueParameters = referencedAnimGraph->RecursivelyGetValueParameters(); // For each parameter in referencedValueParameters, if it is not in valueParameters or is not compatible, add it @@ -1014,10 +1014,10 @@ namespace EMotionFX m_reinitMaskedParameters = false; } - bool portChanged = !mInputPorts.empty(); + bool portChanged = !m_inputPorts.empty(); // Remove all input ports - mInputPorts.clear(); + m_inputPorts.clear(); m_parameterIndexByPortIndex.clear(); // Get the ValueParameters from the AnimGraph @@ -1054,16 +1054,16 @@ namespace EMotionFX }), m_maskedParameterNames.end() ); - mConnections.erase( - AZStd::remove_if(mConnections.begin(), mConnections.end(), [&removedPortIndexes](const BlendTreeConnection* connection) + m_connections.erase( + AZStd::remove_if(m_connections.begin(), m_connections.end(), [&removedPortIndexes](const BlendTreeConnection* connection) { return removedPortIndexes.find(connection->GetTargetPort()) != removedPortIndexes.end(); }), - mConnections.end() + m_connections.end() ); // Shift the port indexes of the remaining connections - for (BlendTreeConnection* connection : mConnections) + for (BlendTreeConnection* connection : m_connections) { AZ::u16 originalTargetPort = connection->GetTargetPort(); AZ::u16 targetPort = originalTargetPort; @@ -1115,17 +1115,17 @@ namespace EMotionFX // Update the input ports. Don't call RelinkPortConnections, // because ReinitInputPorts cannot guarantee that the connected // nodes have been initialized - for (BlendTreeConnection* connection : mConnections) + for (BlendTreeConnection* connection : m_connections) { const AZ::u16 targetPortNr = connection->GetTargetPort(); - if (targetPortNr < mInputPorts.size()) + if (targetPortNr < m_inputPorts.size()) { - mInputPorts[targetPortNr].mConnection = connection; + m_inputPorts[targetPortNr].m_connection = connection; } else { - AZ_Error("EMotionFX", false, "Can't make connection to input port %i of '%s', max port count is %i.", targetPortNr, GetName(), mInputPorts.size()); + AZ_Error("EMotionFX", false, "Can't make connection to input port %i of '%s', max port count is %i.", targetPortNr, GetName(), m_inputPorts.size()); } } AnimGraphNotificationBus::Broadcast(&AnimGraphNotificationBus::Events::OnSyncVisualObject, this); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphSnapshot.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphSnapshot.cpp index 089f5a7df8..b0a7134043 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphSnapshot.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphSnapshot.cpp @@ -159,7 +159,7 @@ namespace EMotionFX if (AZStd::find(activeStates.begin(), activeStates.end(), node) == activeStates.end()) { stateMachine->EndAllActiveTransitions(&instance); - uniqueData->mCurrentState = node; + uniqueData->m_currentState = node; } } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphStateCondition.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphStateCondition.cpp index 341f045918..4a81cf585b 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphStateCondition.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphStateCondition.cpp @@ -63,7 +63,7 @@ namespace EMotionFX return; } - m_state = mAnimGraph->RecursiveFindNodeById(m_stateId); + m_state = m_animGraph->RecursiveFindNodeById(m_stateId); } @@ -100,7 +100,7 @@ namespace EMotionFX { // in case a event got triggered constantly fire true until the condition gets reset const UniqueData* uniqueData = static_cast(animGraphInstance->FindOrCreateUniqueObjectData(this)); - if (uniqueData->mTriggered) + if (uniqueData->m_triggered) { return true; } @@ -149,7 +149,7 @@ namespace EMotionFX // reached the specified play time if (m_state) { - const float currentLocalTime = m_state->GetCurrentPlayTime(uniqueData->mAnimGraphInstance); + const float currentLocalTime = m_state->GetCurrentPlayTime(uniqueData->m_animGraphInstance); // the has reached play time condition is not part of the event handler, so we have to manually handle it here if (AZ::IsClose(currentLocalTime, m_playTime, AZ::Constants::FloatEpsilon) || currentLocalTime >= m_playTime) { @@ -170,7 +170,7 @@ namespace EMotionFX { // find the unique data and reset it UniqueData* uniqueData = static_cast(animGraphInstance->FindOrCreateUniqueObjectData(this)); - uniqueData->mTriggered = false; + uniqueData->m_triggered = false; } // construct and output the information summary string for this object @@ -221,10 +221,10 @@ namespace EMotionFX // constructor AnimGraphStateCondition::UniqueData::UniqueData(AnimGraphObject* object, AnimGraphInstance* animGraphInstance) : AnimGraphObjectData(object, animGraphInstance) - , mAnimGraphInstance(animGraphInstance) + , m_animGraphInstance(animGraphInstance) { - mEventHandler = nullptr; - mTriggered = false; + m_eventHandler = nullptr; + m_triggered = false; CreateEventHandler(); } @@ -240,22 +240,22 @@ namespace EMotionFX { DeleteEventHandler(); - if (mAnimGraphInstance) + if (m_animGraphInstance) { - mEventHandler = aznew AnimGraphStateCondition::EventHandler(static_cast(mObject), this); - mAnimGraphInstance->AddEventHandler(mEventHandler); + m_eventHandler = aznew AnimGraphStateCondition::EventHandler(static_cast(m_object), this); + m_animGraphInstance->AddEventHandler(m_eventHandler); } } void AnimGraphStateCondition::UniqueData::DeleteEventHandler() { - if (mEventHandler) + if (m_eventHandler) { - mAnimGraphInstance->RemoveEventHandler(mEventHandler); + m_animGraphInstance->RemoveEventHandler(m_eventHandler); - delete mEventHandler; - mEventHandler = nullptr; + delete m_eventHandler; + m_eventHandler = nullptr; } } @@ -279,8 +279,8 @@ namespace EMotionFX AnimGraphStateCondition::EventHandler::EventHandler(AnimGraphStateCondition* condition, UniqueData* uniqueData) : EMotionFX::AnimGraphInstanceEventHandler() { - mCondition = condition; - mUniqueData = uniqueData; + m_condition = condition; + m_uniqueData = uniqueData; } @@ -292,7 +292,7 @@ namespace EMotionFX bool AnimGraphStateCondition::EventHandler::IsTargetState(const AnimGraphNode* state) const { - const AnimGraphNode* conditionState = mCondition->GetState(); + const AnimGraphNode* conditionState = m_condition->GetState(); if (conditionState) { const AZStd::string& stateName = conditionState->GetNameString(); @@ -311,10 +311,10 @@ namespace EMotionFX return; } - const TestFunction testFunction = mCondition->GetTestFunction(); + const TestFunction testFunction = m_condition->GetTestFunction(); if (testFunction == targetFunction && IsTargetState(state)) { - mUniqueData->mTriggered = true; + m_uniqueData->m_triggered = true; } } @@ -355,7 +355,7 @@ namespace EMotionFX void AnimGraphStateCondition::SetStateId(AnimGraphNodeId stateId) { m_stateId = stateId; - if (mAnimGraph) + if (m_animGraph) { Reinit(); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphStateCondition.h b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphStateCondition.h index bc4ca4bf75..1c772e8fbe 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphStateCondition.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphStateCondition.h @@ -63,9 +63,9 @@ namespace EMotionFX // The anim graph instance pointer shouldn't change. If it were to // change, we'd need to remove an existing event handler and create // a new one in the new anim graph instance. - AnimGraphInstance* const mAnimGraphInstance; - AnimGraphStateCondition::EventHandler* mEventHandler; - bool mTriggered; + AnimGraphInstance* const m_animGraphInstance; + AnimGraphStateCondition::EventHandler* m_eventHandler; + bool m_triggered; }; AnimGraphStateCondition(); @@ -125,8 +125,8 @@ namespace EMotionFX bool IsTargetState(const AnimGraphNode* state) const; void OnStateChange(AnimGraphInstance* animGraphInstance, AnimGraphNode* state, TestFunction targetFunction); - AnimGraphStateCondition* mCondition; - UniqueData* mUniqueData; + AnimGraphStateCondition* m_condition; + UniqueData* m_uniqueData; }; AZ::Crc32 GetTestFunctionVisibility() const; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphStateMachine.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphStateMachine.cpp index 3ad6ae8b8b..9b4c2d07ac 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphStateMachine.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphStateMachine.cpp @@ -35,8 +35,8 @@ namespace EMotionFX AnimGraphStateMachine::AnimGraphStateMachine() : AnimGraphNode() - , mEntryState(nullptr) - , mEntryStateNodeNr(InvalidIndex) + , m_entryState(nullptr) + , m_entryStateNodeNr(InvalidIndex) , m_entryStateId(AnimGraphNodeId::InvalidId) , m_alwaysStartInEntryState(true) { @@ -55,7 +55,7 @@ namespace EMotionFX // Re-initialize all child nodes and connections AnimGraphNode::RecursiveReinit(); - for (AnimGraphStateTransition* transition : mTransitions) + for (AnimGraphStateTransition* transition : m_transitions) { transition->RecursiveReinit(); } @@ -68,7 +68,7 @@ namespace EMotionFX return false; } - for (AnimGraphStateTransition* transition : mTransitions) + for (AnimGraphStateTransition* transition : m_transitions) { transition->InitAfterLoading(animGraph); } @@ -82,12 +82,12 @@ namespace EMotionFX void AnimGraphStateMachine::RemoveAllTransitions() { - for (AnimGraphStateTransition* transition : mTransitions) + for (AnimGraphStateTransition* transition : m_transitions) { delete transition; } - mTransitions.clear(); + m_transitions.clear(); } void AnimGraphStateMachine::Output(AnimGraphInstance* animGraphInstance) @@ -95,7 +95,7 @@ namespace EMotionFX ActorInstance* actorInstance = animGraphInstance->GetActorInstance(); AnimGraphPose* outputPose = nullptr; - if (mDisabled) + if (m_disabled) { // Output bind pose in case state machine is disabled. RequestPoses(animGraphInstance); @@ -114,13 +114,13 @@ namespace EMotionFX const AZStd::vector& activeStates = uniqueData->GetActiveStates(); // Single active state, no active transition. - if (!isTransitioning && uniqueData->mCurrentState) + if (!isTransitioning && uniqueData->m_currentState) { - uniqueData->mCurrentState->PerformOutput(animGraphInstance); + uniqueData->m_currentState->PerformOutput(animGraphInstance); RequestPoses(animGraphInstance); outputPose = GetOutputPose(animGraphInstance, OUTPUTPORT_POSE)->GetValue(); - *outputPose = *uniqueData->mCurrentState->GetMainOutputPose(animGraphInstance); + *outputPose = *uniqueData->m_currentState->GetMainOutputPose(animGraphInstance); } // One or more transitions active. else if (isTransitioning) @@ -184,7 +184,7 @@ namespace EMotionFX if (outputPose && GetEMotionFX().GetIsInEditorMode() && GetCanVisualize(animGraphInstance)) { - actorInstance->DrawSkeleton(outputPose->GetPose(), mVisualizeColor); + actorInstance->DrawSkeleton(outputPose->GetPose(), m_visualizeColor); } } @@ -205,7 +205,7 @@ namespace EMotionFX const bool isTransitioning = IsTransitioning(animGraphInstance); AnimGraphStateTransition* latestActiveTransition = GetLatestActiveTransition(uniqueData); - for (AnimGraphStateTransition* curTransition : mTransitions) + for (AnimGraphStateTransition* curTransition : m_transitions) { if (curTransition->GetIsDisabled()) { @@ -321,7 +321,7 @@ namespace EMotionFX } const bool isTransitioning = IsTransitioning(animGraphInstance); - for (const AnimGraphStateTransition* transition : mTransitions) + for (const AnimGraphStateTransition* transition : m_transitions) { // get the current transition and skip it directly if in case it is disabled if (transition->GetIsDisabled()) @@ -369,7 +369,7 @@ namespace EMotionFX // Update the source node for the transition instance in case we're dealing with a wildcard transition. if (transition->GetIsWildcardTransition()) { - sourceNode = uniqueData->mCurrentState; + sourceNode = uniqueData->m_currentState; transition->SetSourceNode(animGraphInstance, sourceNode); } @@ -431,7 +431,7 @@ namespace EMotionFX // Reset the conditions of the transition that has just ended. transition->ResetConditions(animGraphInstance); - targetState->OnStateEnter(animGraphInstance, uniqueData->mCurrentState, transition); + targetState->OnStateEnter(animGraphInstance, uniqueData->m_currentState, transition); eventManager.OnStateEnter(animGraphInstance, targetState); // Ending latest active transition. @@ -439,11 +439,11 @@ namespace EMotionFX { // Emit end state events and adjust the previous and the active states in case the latest active transition is ending. // In other cases we're not leaving the current state yet as it is still active as a source state from another active transition. - uniqueData->mCurrentState->OnStateEnd(animGraphInstance, targetState, transition); - eventManager.OnStateEnd(animGraphInstance, uniqueData->mCurrentState); + uniqueData->m_currentState->OnStateEnd(animGraphInstance, targetState, transition); + eventManager.OnStateEnd(animGraphInstance, uniqueData->m_currentState); - uniqueData->mPreviousState = uniqueData->mCurrentState; - uniqueData->mCurrentState = targetState; + uniqueData->m_previousState = uniqueData->m_currentState; + uniqueData->m_currentState = targetState; } // Ending any interrupted transition on the transition stack that ended transitioning. else if (transition->GetIsDone(animGraphInstance)) @@ -479,14 +479,14 @@ namespace EMotionFX UniqueData* uniqueData = static_cast(FindOrCreateUniqueNodeData(animGraphInstance)); // Defer switch to entry state. - if (uniqueData->mSwitchToEntryState) + if (uniqueData->m_switchToEntryState) { AnimGraphNode* entryState = GetEntryState(); if (entryState) { SwitchToState(animGraphInstance, entryState); } - uniqueData->mSwitchToEntryState = false; + uniqueData->m_switchToEntryState = false; } // Update all currently active transitions. @@ -507,8 +507,8 @@ namespace EMotionFX } // Update the conditions and trigger the right transition based on the conditions and priority levels etc. - UpdateConditions(animGraphInstance, uniqueData->mCurrentState, timePassedInSeconds); - CheckConditions(uniqueData->mCurrentState, animGraphInstance, uniqueData, /*calledFromWithinUpdate*/ true); + UpdateConditions(animGraphInstance, uniqueData->m_currentState, timePassedInSeconds); + CheckConditions(uniqueData->m_currentState, animGraphInstance, uniqueData, /*calledFromWithinUpdate*/ true); #ifdef ENABLE_SINGLEFRAME_MULTISTATETRANSITIONING // Check if our latest active transition is already done, end it and check for further transition candidates. @@ -519,8 +519,8 @@ namespace EMotionFX // End all transitions on the stack back to front EndAllActiveTransitions(animGraphInstance, uniqueData); - UpdateConditions(animGraphInstance, uniqueData->mCurrentState, 0.0f); - CheckConditions(uniqueData->mCurrentState, animGraphInstance, uniqueData, /*calledFromWithinUpdate=*/true); + UpdateConditions(animGraphInstance, uniqueData->m_currentState, 0.0f); + CheckConditions(uniqueData->m_currentState, animGraphInstance, uniqueData, /*calledFromWithinUpdate=*/true); if (numPasses >= s_maxNumPasses) { @@ -545,9 +545,9 @@ namespace EMotionFX UpdateExitStateReachedFlag(animGraphInstance, uniqueData); // Perform play speed synchronization when transitioning. - if (uniqueData->mCurrentState) + if (uniqueData->m_currentState) { - uniqueData->Init(animGraphInstance, uniqueData->mCurrentState); + uniqueData->Init(animGraphInstance, uniqueData->m_currentState); if (IsTransitioning(uniqueData)) { @@ -612,12 +612,12 @@ namespace EMotionFX { if (azrtti_typeid(activeState) == azrtti_typeid()) { - uniqueData->mReachedExitState = true; + uniqueData->m_reachedExitState = true; return; } } - uniqueData->mReachedExitState = false; + uniqueData->m_reachedExitState = false; } void AnimGraphStateMachine::PostUpdate(AnimGraphInstance* animGraphInstance, float timePassedInSeconds) @@ -644,7 +644,7 @@ namespace EMotionFX if (!IsTransitioning(uniqueData)) { - AnimGraphNode* activeState = uniqueData->mCurrentState; + AnimGraphNode* activeState = uniqueData->m_currentState; if (activeState) { // Single active state, no active transition. @@ -728,28 +728,28 @@ namespace EMotionFX } // tell the current node to which node we're exiting - if (uniqueData->mCurrentState) + if (uniqueData->m_currentState) { - uniqueData->mCurrentState->OnStateExit(animGraphInstance, targetState, nullptr); - uniqueData->mCurrentState->OnStateEnd(animGraphInstance, targetState, nullptr); + uniqueData->m_currentState->OnStateExit(animGraphInstance, targetState, nullptr); + uniqueData->m_currentState->OnStateEnd(animGraphInstance, targetState, nullptr); } // tell the new current node from which node we're coming if (targetState) { - targetState->OnStateEntering(animGraphInstance, uniqueData->mCurrentState, nullptr); - targetState->OnStateEnter(animGraphInstance, uniqueData->mCurrentState, nullptr); + targetState->OnStateEntering(animGraphInstance, uniqueData->m_currentState, nullptr); + targetState->OnStateEnter(animGraphInstance, uniqueData->m_currentState, nullptr); } // Inform the event manager. EventManager& eventManager = GetEventManager(); - eventManager.OnStateExit(animGraphInstance, uniqueData->mCurrentState); + eventManager.OnStateExit(animGraphInstance, uniqueData->m_currentState); eventManager.OnStateEntering(animGraphInstance, targetState); - eventManager.OnStateEnd(animGraphInstance, uniqueData->mCurrentState); + eventManager.OnStateEnd(animGraphInstance, uniqueData->m_currentState); eventManager.OnStateEnter(animGraphInstance, targetState); - uniqueData->mPreviousState = uniqueData->mCurrentState; - uniqueData->mCurrentState = targetState; + uniqueData->m_previousState = uniqueData->m_currentState; + uniqueData->m_currentState = targetState; uniqueData->m_activeTransitions.clear(); } @@ -814,7 +814,7 @@ namespace EMotionFX void AnimGraphStateMachine::AddTransition(AnimGraphStateTransition* transition) { - mTransitions.push_back(transition); + m_transitions.push_back(transition); } AnimGraphStateTransition* AnimGraphStateMachine::FindTransition(AnimGraphInstance* animGraphInstance, AnimGraphNode* currentState, AnimGraphNode* targetState) const @@ -843,7 +843,7 @@ namespace EMotionFX AnimGraphStateTransition* prioritizedTransition = nullptr; // first check if there is a ready transition that points directly to the target state - for (AnimGraphStateTransition* transition : mTransitions) + for (AnimGraphStateTransition* transition : m_transitions) { // get the current transition and skip it directly if in case it is disabled if (transition->GetIsDisabled()) @@ -875,7 +875,7 @@ namespace EMotionFX /////////////////////////////////////////////////////////////////////// // in case there is no direct and no indirect transition ready, check for wildcard transitions // there is a maximum number of one for wild card transitions, so we don't need to check the priority values here - for (AnimGraphStateTransition* transition : mTransitions) + for (AnimGraphStateTransition* transition : m_transitions) { // get the current transition and skip it directly if in case it is disabled if (transition->GetIsDisabled()) @@ -896,10 +896,10 @@ namespace EMotionFX AZ::Outcome AnimGraphStateMachine::FindTransitionIndexById(AnimGraphConnectionId transitionId) const { - const size_t numTransitions = mTransitions.size(); + const size_t numTransitions = m_transitions.size(); for (size_t i = 0; i < numTransitions; ++i) { - if (mTransitions[i]->GetId() == transitionId) + if (m_transitions[i]->GetId() == transitionId) { return AZ::Success(i); } @@ -910,10 +910,10 @@ namespace EMotionFX AZ::Outcome AnimGraphStateMachine::FindTransitionIndex(const AnimGraphStateTransition* transition) const { - const auto& iterator = AZStd::find(mTransitions.begin(), mTransitions.end(), transition); - if (iterator != mTransitions.end()) + const auto& iterator = AZStd::find(m_transitions.begin(), m_transitions.end(), transition); + if (iterator != m_transitions.end()) { - const size_t index = iterator - mTransitions.begin(); + const size_t index = iterator - m_transitions.begin(); return AZ::Success(index); } @@ -925,7 +925,7 @@ namespace EMotionFX const AZ::Outcome transitionIndex = FindTransitionIndexById(transitionId); if (transitionIndex.IsSuccess()) { - return mTransitions[transitionIndex.GetValue()]; + return m_transitions[transitionIndex.GetValue()]; } return nullptr; @@ -933,7 +933,7 @@ namespace EMotionFX bool AnimGraphStateMachine::CheckIfHasWildcardTransition(AnimGraphNode* state) const { - for (const AnimGraphStateTransition* transition : mTransitions) + for (const AnimGraphStateTransition* transition : m_transitions) { // check if the given transition is a wildcard transition and if the target node is the given one if (transition->GetTargetNode() == state && transition->GetIsWildcardTransition()) @@ -949,10 +949,10 @@ namespace EMotionFX { if (delFromMem) { - delete mTransitions[transitionIndex]; + delete m_transitions[transitionIndex]; } - mTransitions.erase(mTransitions.begin() + transitionIndex); + m_transitions.erase(m_transitions.begin() + transitionIndex); } AnimGraphNode* AnimGraphStateMachine::GetEntryState() @@ -960,38 +960,38 @@ namespace EMotionFX const AnimGraphNodeId entryStateId = GetEntryStateId(); if (entryStateId.IsValid()) { - if (!mEntryState || (mEntryState && mEntryState->GetId() != entryStateId)) + if (!m_entryState || (m_entryState && m_entryState->GetId() != entryStateId)) { // Sync the entry state based on the id. - mEntryState = FindChildNodeById(entryStateId); + m_entryState = FindChildNodeById(entryStateId); } } else { // Legacy file format way. - if (!mEntryState) + if (!m_entryState) { - if (mEntryStateNodeNr != InvalidIndex && mEntryStateNodeNr < GetNumChildNodes()) + if (m_entryStateNodeNr != InvalidIndex && m_entryStateNodeNr < GetNumChildNodes()) { - mEntryState = GetChildNode(mEntryStateNodeNr); + m_entryState = GetChildNode(m_entryStateNodeNr); } } // End: Legacy file format way. // TODO: Enable this line when deprecating the leagacy file format. - //mEntryState = nullptr; + // m_entryState = nullptr; } - return mEntryState; + return m_entryState; } void AnimGraphStateMachine::SetEntryState(AnimGraphNode* entryState) { - mEntryState = entryState; + m_entryState = entryState; - if (mEntryState) + if (m_entryState) { - m_entryStateId = mEntryState->GetId(); + m_entryStateId = m_entryState->GetId(); } else { @@ -999,25 +999,25 @@ namespace EMotionFX } // Used for the legacy file format. Get rid of this along with the old file format. - mEntryStateNodeNr = FindChildNodeIndex(mEntryState); + m_entryStateNodeNr = FindChildNodeIndex(m_entryState); } AnimGraphNode* AnimGraphStateMachine::GetCurrentState(AnimGraphInstance* animGraphInstance) { UniqueData* uniqueData = static_cast(animGraphInstance->FindOrCreateUniqueNodeData(this)); - return uniqueData->mCurrentState; + return uniqueData->m_currentState; } bool AnimGraphStateMachine::GetExitStateReached(AnimGraphInstance* animGraphInstance) const { // get the unique data for this state machine in a given anim graph instance UniqueData* uniqueData = static_cast(animGraphInstance->FindOrCreateUniqueNodeData(this)); - return uniqueData->mReachedExitState; + return uniqueData->m_reachedExitState; } void AnimGraphStateMachine::RecursiveOnChangeMotionSet(AnimGraphInstance* animGraphInstance, MotionSet* newMotionSet) { - for (AnimGraphStateTransition* transition : mTransitions) + for (AnimGraphStateTransition* transition : m_transitions) { transition->OnChangeMotionSet(animGraphInstance, newMotionSet); } @@ -1029,18 +1029,18 @@ namespace EMotionFX void AnimGraphStateMachine::OnRemoveNode(AnimGraph* animGraph, AnimGraphNode* nodeToRemove) { // is the node to remove the entry state? - if (mEntryState == nodeToRemove) + if (m_entryState == nodeToRemove) { SetEntryState(nullptr); } - for (AnimGraphStateTransition* transition : mTransitions) + for (AnimGraphStateTransition* transition : m_transitions) { transition->OnRemoveNode(animGraph, nodeToRemove); } bool childNodeRemoved = false; - for (AnimGraphNode* childNode : mChildNodes) + for (AnimGraphNode* childNode : m_childNodes) { if (childNode == nodeToRemove) { @@ -1060,7 +1060,7 @@ namespace EMotionFX { ResetUniqueData(animGraphInstance); - for (AnimGraphNode* childNode : mChildNodes) + for (AnimGraphNode* childNode : m_childNodes) { childNode->RecursiveResetUniqueDatas(animGraphInstance); } @@ -1070,7 +1070,7 @@ namespace EMotionFX { AnimGraphNode::RecursiveInvalidateUniqueDatas(animGraphInstance); - for (AnimGraphStateTransition* transition : mTransitions) + for (AnimGraphStateTransition* transition : m_transitions) { transition->RecursiveInvalidateUniqueDatas(animGraphInstance); } @@ -1081,25 +1081,25 @@ namespace EMotionFX void AnimGraphStateMachine::UniqueData::Reset() { m_activeTransitions.clear(); - mCurrentState = nullptr; - mPreviousState = nullptr; - mReachedExitState = false; - mSwitchToEntryState = true; + m_currentState = nullptr; + m_previousState = nullptr; + m_reachedExitState = false; + m_switchToEntryState = true; } void AnimGraphStateMachine::UniqueData::Update() { - AnimGraphStateMachine* stateMachine = azdynamic_cast(mObject); + AnimGraphStateMachine* stateMachine = azdynamic_cast(m_object); AZ_Assert(stateMachine, "Unique data linked to incorrect node type."); // check if any of the active states are invalid and reset them if they are - if (mCurrentState && stateMachine->FindChildNodeIndex(mCurrentState) == InvalidIndex) + if (m_currentState && stateMachine->FindChildNodeIndex(m_currentState) == InvalidIndex) { - mCurrentState = nullptr; + m_currentState = nullptr; } - if (mPreviousState && stateMachine->FindChildNodeIndex(mPreviousState) == InvalidIndex) + if (m_previousState && stateMachine->FindChildNodeIndex(m_previousState) == InvalidIndex) { - mPreviousState = nullptr; + m_previousState = nullptr; } // Check if the currently active transitions are valid and remove them from the transition stack if not. @@ -1125,9 +1125,9 @@ namespace EMotionFX { m_activeStates.clear(); - if (mCurrentState) + if (m_currentState) { - m_activeStates.emplace_back(mCurrentState); + m_activeStates.emplace_back(m_currentState); } // Add target state for all active transitions to the active states. @@ -1158,40 +1158,40 @@ namespace EMotionFX // rewind the state machine if (m_alwaysStartInEntryState && entryState) { - if (uniqueData->mCurrentState) + if (uniqueData->m_currentState) { - uniqueData->mCurrentState->OnStateExit(animGraphInstance, entryState, nullptr); - uniqueData->mCurrentState->OnStateEnd(animGraphInstance, entryState, nullptr); + uniqueData->m_currentState->OnStateExit(animGraphInstance, entryState, nullptr); + uniqueData->m_currentState->OnStateEnd(animGraphInstance, entryState, nullptr); - GetEventManager().OnStateExit(animGraphInstance, uniqueData->mCurrentState); - GetEventManager().OnStateEnd(animGraphInstance, uniqueData->mCurrentState); + GetEventManager().OnStateExit(animGraphInstance, uniqueData->m_currentState); + GetEventManager().OnStateEnd(animGraphInstance, uniqueData->m_currentState); } // rewind the entry state and reset conditions of all outgoing transitions entryState->Rewind(animGraphInstance); ResetOutgoingTransitionConditions(animGraphInstance, entryState); - mEntryState->OnStateEntering(animGraphInstance, uniqueData->mCurrentState, nullptr); - mEntryState->OnStateEnter(animGraphInstance, uniqueData->mCurrentState, nullptr); + m_entryState->OnStateEntering(animGraphInstance, uniqueData->m_currentState, nullptr); + m_entryState->OnStateEnter(animGraphInstance, uniqueData->m_currentState, nullptr); GetEventManager().OnStateEntering(animGraphInstance, entryState); GetEventManager().OnStateEnter(animGraphInstance, entryState); // reset the the unique data of the state machine and overwrite the current state as that is not nullptr but the entry state uniqueData->Reset(); - uniqueData->mCurrentState = entryState; + uniqueData->m_currentState = entryState; } } void AnimGraphStateMachine::RecursiveResetFlags(AnimGraphInstance* animGraphInstance, uint32 flagsToDisable) { // clear the output for all child nodes, just to make sure - for (const AnimGraphNode* childNode : mChildNodes) + for (const AnimGraphNode* childNode : m_childNodes) { animGraphInstance->DisableObjectFlags(childNode->GetObjectIndex(), flagsToDisable); } // Reset flags for this state machine. - animGraphInstance->DisableObjectFlags(mObjectIndex, flagsToDisable); + animGraphInstance->DisableObjectFlags(m_objectIndex, flagsToDisable); // Reset flags recursively for all active states within this state machine. const AZStd::vector& activeStates = GetActiveStates(animGraphInstance); @@ -1209,7 +1209,7 @@ namespace EMotionFX void AnimGraphStateMachine::ResetOutgoingTransitionConditions(AnimGraphInstance* animGraphInstance, AnimGraphNode* state) { - for (AnimGraphStateTransition* transition : mTransitions) + for (AnimGraphStateTransition* transition : m_transitions) { // get the transition, check if it is a possible outgoing connection for our given state and reset it in this case if (transition->GetIsWildcardTransition() || @@ -1223,7 +1223,7 @@ namespace EMotionFX uint32 AnimGraphStateMachine::CalcNumIncomingTransitions(AnimGraphNode* state) const { uint32 result = 0; - for (const AnimGraphStateTransition* transition : mTransitions) + for (const AnimGraphStateTransition* transition : m_transitions) { if (transition->GetTargetNode() == state) { @@ -1236,7 +1236,7 @@ namespace EMotionFX uint32 AnimGraphStateMachine::CalcNumWildcardTransitions(AnimGraphNode* state) const { uint32 result = 0; - for (const AnimGraphStateTransition* transition : mTransitions) + for (const AnimGraphStateTransition* transition : m_transitions) { if (transition->GetIsWildcardTransition() && transition->GetTargetNode() == state) { @@ -1265,7 +1265,7 @@ namespace EMotionFX uint32 AnimGraphStateMachine::CalcNumOutgoingTransitions(AnimGraphNode* state) const { uint32 result = 0; - for (const AnimGraphStateTransition* transition : mTransitions) + for (const AnimGraphStateTransition* transition : m_transitions) { if (!transition->GetIsWildcardTransition() && transition->GetSourceNode() == state) { @@ -1277,7 +1277,7 @@ namespace EMotionFX void AnimGraphStateMachine::RecursiveCollectObjects(AZStd::vector& outObjects) const { - for (const AnimGraphStateTransition* transition : mTransitions) + for (const AnimGraphStateTransition* transition : m_transitions) { transition->RecursiveCollectObjects(outObjects); // this will automatically add all transition conditions as well } @@ -1348,7 +1348,7 @@ namespace EMotionFX if (!IsTransitioning(uniqueData)) { - AnimGraphNode* activeState = uniqueData->mCurrentState; + AnimGraphNode* activeState = uniqueData->m_currentState; if (activeState) { // Single active state, no active transition. @@ -1374,7 +1374,7 @@ namespace EMotionFX if (syncMode != SYNCMODE_DISABLED) { - if (animGraphInstance->GetIsObjectFlagEnabled(mObjectIndex, AnimGraphInstance::OBJECTFLAGS_SYNCED) == false) + if (animGraphInstance->GetIsObjectFlagEnabled(m_objectIndex, AnimGraphInstance::OBJECTFLAGS_SYNCED) == false) { sourceNode->RecursiveSetUniqueDataFlag(animGraphInstance, AnimGraphInstance::OBJECTFLAGS_SYNCED, true); animGraphInstance->SetObjectFlags(sourceNode->GetObjectIndex(), AnimGraphInstance::OBJECTFLAGS_IS_SYNCLEADER, true); @@ -1420,9 +1420,9 @@ namespace EMotionFX { Reset(); - AnimGraphStateMachine* stateMachine = azdynamic_cast(mObject); + AnimGraphStateMachine* stateMachine = azdynamic_cast(m_object); AZ_Assert(stateMachine, "Unique data linked to incorrect node type."); - mCurrentState = stateMachine->GetEntryState(); + m_currentState = stateMachine->GetEntryState(); } uint32 AnimGraphStateMachine::UniqueData::Save(uint8* outputBuffer) const @@ -1438,8 +1438,8 @@ namespace EMotionFX resultSize += chunkSize; SaveVectorOfObjects(m_activeTransitions, &destBuffer, resultSize); - SaveChunk((uint8*)&mCurrentState, sizeof(AnimGraphNode*), &destBuffer, resultSize); - SaveChunk((uint8*)&mPreviousState, sizeof(AnimGraphNode*), &destBuffer, resultSize); + SaveChunk((uint8*)&m_currentState, sizeof(AnimGraphNode*), &destBuffer, resultSize); + SaveChunk((uint8*)&m_previousState, sizeof(AnimGraphNode*), &destBuffer, resultSize); return resultSize; } @@ -1454,8 +1454,8 @@ namespace EMotionFX resultSize += chunkSize; LoadVectorOfObjects(m_activeTransitions, &sourceBuffer, resultSize); - LoadChunk((uint8*)&mCurrentState, sizeof(AnimGraphNode*), &sourceBuffer, resultSize); - LoadChunk((uint8*)&mPreviousState, sizeof(AnimGraphNode*), &sourceBuffer, resultSize); + LoadChunk((uint8*)&m_currentState, sizeof(AnimGraphNode*), &sourceBuffer, resultSize); + LoadChunk((uint8*)&m_previousState, sizeof(AnimGraphNode*), &sourceBuffer, resultSize); return resultSize; } @@ -1463,7 +1463,7 @@ namespace EMotionFX void AnimGraphStateMachine::RecursiveSetUniqueDataFlag(AnimGraphInstance* animGraphInstance, uint32 flag, bool enabled) { // Set flag for this state machine. - animGraphInstance->SetObjectFlags(mObjectIndex, flag, enabled); + animGraphInstance->SetObjectFlags(m_objectIndex, flag, enabled); // Set flag recursively for all active states within this state machine. const AZStd::vector& activeStates = GetActiveStates(animGraphInstance); @@ -1478,7 +1478,7 @@ namespace EMotionFX // check and add this node if (azrtti_typeid(this) == nodeType || nodeType.IsNull()) { - if (animGraphInstance->GetIsOutputReady(mObjectIndex)) // if we processed this node + if (animGraphInstance->GetIsOutputReady(m_objectIndex)) // if we processed this node { outNodes->emplace_back(const_cast(this)); } @@ -1503,7 +1503,7 @@ namespace EMotionFX void AnimGraphStateMachine::ReserveTransitions(size_t numTransitions) { - mTransitions.reserve(numTransitions); + m_transitions.reserve(numTransitions); } void AnimGraphStateMachine::SetEntryStateId(AnimGraphNodeId entryStateId) @@ -1555,7 +1555,7 @@ namespace EMotionFX serializeContext->Class() ->Version(1) ->Field("entryStateId", &AnimGraphStateMachine::m_entryStateId) - ->Field("transitions", &AnimGraphStateMachine::mTransitions) + ->Field("transitions", &AnimGraphStateMachine::m_transitions) ->Field("alwaysStartInEntryState", &AnimGraphStateMachine::m_alwaysStartInEntryState); AZ::EditContext* editContext = serializeContext->GetEditContext(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphStateMachine.h b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphStateMachine.h index 1f8d1eb591..1a00a82744 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphStateMachine.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphStateMachine.h @@ -56,11 +56,11 @@ namespace EMotionFX public: AZStd::vector m_activeTransitions; /**< Stack of active transitions. */ - AnimGraphNode* mCurrentState; /**< The current state. */ - AnimGraphNode* mPreviousState; /**< The previously used state, so the one used before the current one, the one from which we transitioned into the current one. */ - bool mReachedExitState; /**< True in case the state machine's current state is an exit state, false it not. */ + AnimGraphNode* m_currentState; /**< The current state. */ + AnimGraphNode* m_previousState; /**< The previously used state, so the one used before the current one, the one from which we transitioned into the current one. */ + bool m_reachedExitState; /**< True in case the state machine's current state is an exit state, false it not. */ AnimGraphRefCountedData m_prevData; - bool mSwitchToEntryState; + bool m_switchToEntryState; private: AZStd::vector m_activeStates; // TODO: See function comment. @@ -112,14 +112,14 @@ namespace EMotionFX * Get the number of transitions inside this state machine. This includes all kinds of transitions, so also wildcard transitions. * @result The number of transitions inside the state machine. */ - size_t GetNumTransitions() const { return mTransitions.size(); } + size_t GetNumTransitions() const { return m_transitions.size(); } /** * Get a pointer to the state machine transition of the given index. * @param[in] index The index of the transition to return. * @result A pointer to the state machine transition at the given index. */ - AnimGraphStateTransition* GetTransition(size_t index) const { return mTransitions[index]; } + AnimGraphStateTransition* GetTransition(size_t index) const { return m_transitions[index]; } /** * Remove the state machine transition at the given index. @@ -265,9 +265,9 @@ namespace EMotionFX void EndAllActiveTransitions(AnimGraphInstance* animGraphInstance); private: - AZStd::vector mTransitions; /**< The higher the index, the older the active transtion, the more time passed since it got started. Index = 0 is the most recent transition and the one with the highest global influence.*/ - AnimGraphNode* mEntryState; /**< A pointer to the initial state, so the state where the machine starts. */ - size_t mEntryStateNodeNr; /**< Used only in the legacy file format. Remove after the legacy file format will be removed. */ + AZStd::vector m_transitions; /**< The higher the index, the older the active transtion, the more time passed since it got started. Index = 0 is the most recent transition and the one with the highest global influence.*/ + AnimGraphNode* m_entryState; /**< A pointer to the initial state, so the state where the machine starts. */ + size_t m_entryStateNodeNr; /**< Used only in the legacy file format. Remove after the legacy file format will be removed. */ AZ::u64 m_entryStateId; /**< The node id of the entry state. */ bool m_alwaysStartInEntryState; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphStateTransition.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphStateTransition.cpp index 747188ead2..e90491b696 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphStateTransition.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphStateTransition.cpp @@ -180,9 +180,9 @@ namespace EMotionFX float duration ) : AnimGraphObject() - , mConditions(AZStd::move(conditions)) - , mSourceNode(source) - , mTargetNode(target) + , m_conditions(AZStd::move(conditions)) + , m_sourceNode(source) + , m_targetNode(target) , m_sourceNodeId(source ? source->GetId() : ObjectId::InvalidId) , m_targetNodeId(target ? target->GetId() : ObjectId::InvalidId) , m_transitionTime(duration) @@ -192,31 +192,31 @@ namespace EMotionFX AnimGraphStateTransition::~AnimGraphStateTransition() { RemoveAllConditions(true); - if (mAnimGraph) + if (m_animGraph) { - mAnimGraph->RemoveObject(this); + m_animGraph->RemoveObject(this); } } void AnimGraphStateTransition::Reinit() { - if (!mAnimGraph) + if (!m_animGraph) { - mSourceNode = nullptr; - mTargetNode = nullptr; + m_sourceNode = nullptr; + m_targetNode = nullptr; return; } // Re-link the source node. if (GetSourceNodeId().IsValid()) { - mSourceNode = mAnimGraph->RecursiveFindNodeById(GetSourceNodeId()); + m_sourceNode = m_animGraph->RecursiveFindNodeById(GetSourceNodeId()); } // Re-link the target node. if (GetTargetNodeId().IsValid()) { - mTargetNode = mAnimGraph->RecursiveFindNodeById(GetTargetNodeId()); + m_targetNode = m_animGraph->RecursiveFindNodeById(GetTargetNodeId()); } AnimGraphObject::Reinit(); @@ -226,7 +226,7 @@ namespace EMotionFX { Reinit(); - for (AnimGraphTransitionCondition* condition : mConditions) + for (AnimGraphTransitionCondition* condition : m_conditions) { condition->Reinit(); } @@ -243,7 +243,7 @@ namespace EMotionFX InitInternalAttributesForAllInstances(); - for (AnimGraphTransitionCondition* condition : mConditions) + for (AnimGraphTransitionCondition* condition : m_conditions) { condition->SetTransition(this); condition->InitAfterLoading(animGraph); @@ -265,7 +265,7 @@ namespace EMotionFX UniqueData* uniqueData = static_cast(animGraphInstance->FindOrCreateUniqueObjectData(this)); // calculate the blend weight, based on the type of smoothing - const float weight = uniqueData->mBlendWeight; + const float weight = uniqueData->m_blendWeight; // blend the two poses *outputPose = from; @@ -282,37 +282,37 @@ namespace EMotionFX { const float blendTime = GetBlendTime(animGraphInstance); - uniqueData->mTotalSeconds += timePassedInSeconds; - if (uniqueData->mTotalSeconds >= blendTime) + uniqueData->m_totalSeconds += timePassedInSeconds; + if (uniqueData->m_totalSeconds >= blendTime) { - uniqueData->mTotalSeconds = blendTime; - uniqueData->mIsDone = true; + uniqueData->m_totalSeconds = blendTime; + uniqueData->m_isDone = true; } else { - uniqueData->mIsDone = false; + uniqueData->m_isDone = false; } // calculate the blend weight if (blendTime > MCore::Math::epsilon) { - uniqueData->mBlendProgress = uniqueData->mTotalSeconds / blendTime; + uniqueData->m_blendProgress = uniqueData->m_totalSeconds / blendTime; } else { - uniqueData->mBlendProgress = 1.0f; + uniqueData->m_blendProgress = 1.0f; } - uniqueData->mBlendWeight = CalculateWeight(uniqueData->mBlendProgress); + uniqueData->m_blendWeight = CalculateWeight(uniqueData->m_blendProgress); } } void AnimGraphStateTransition::ExtractMotion(AnimGraphInstance* animGraphInstance, AnimGraphRefCountedData* sourceData, Transform* outTransform, Transform* outTransformMirrored) const { UniqueData* uniqueData = static_cast(animGraphInstance->FindOrCreateUniqueObjectData(this)); - const float weight = uniqueData->mBlendWeight; + const float weight = uniqueData->m_blendWeight; - AnimGraphRefCountedData* targetData = mTargetNode->FindOrCreateUniqueNodeData(animGraphInstance)->GetRefCountedData(); + AnimGraphRefCountedData* targetData = m_targetNode->FindOrCreateUniqueNodeData(animGraphInstance)->GetRefCountedData(); CalculateMotionExtractionDelta(m_extractionMode, sourceData, targetData, weight, true, *outTransform, *outTransformMirrored); } @@ -321,12 +321,12 @@ namespace EMotionFX // get the unique data UniqueData* uniqueData = static_cast(animGraphInstance->FindOrCreateUniqueObjectData(this)); - uniqueData->mBlendWeight = 0.0f; - uniqueData->mIsDone = false; - uniqueData->mTotalSeconds = 0.0f; - uniqueData->mBlendProgress = 0.0f; + uniqueData->m_blendWeight = 0.0f; + uniqueData->m_isDone = false; + uniqueData->m_totalSeconds = 0.0f; + uniqueData->m_blendProgress = 0.0f; - mTargetNode->SetSyncIndex(animGraphInstance, MCORE_INVALIDINDEX32); + m_targetNode->SetSyncIndex(animGraphInstance, MCORE_INVALIDINDEX32); // Trigger action for (AnimGraphTriggerAction* action : m_actionSetup.GetActions()) @@ -343,23 +343,23 @@ namespace EMotionFX { // get the unique data and return the is done flag UniqueData* uniqueData = static_cast(animGraphInstance->FindOrCreateUniqueObjectData(this)); - return uniqueData->mIsDone; + return uniqueData->m_isDone; } float AnimGraphStateTransition::GetBlendWeight(AnimGraphInstance* animGraphInstance) const { // get the unique data and return the is done flag UniqueData* uniqueData = static_cast(animGraphInstance->FindOrCreateUniqueObjectData(this)); - return uniqueData->mBlendWeight; + return uniqueData->m_blendWeight; } void AnimGraphStateTransition::OnEndTransition(AnimGraphInstance* animGraphInstance) { // get the unique data UniqueData* uniqueData = static_cast(animGraphInstance->FindOrCreateUniqueObjectData(this)); - uniqueData->mBlendWeight = 1.0f; - uniqueData->mBlendProgress = 1.0f; - uniqueData->mIsDone = true; + uniqueData->m_blendWeight = 1.0f; + uniqueData->m_blendProgress = 1.0f; + uniqueData->m_isDone = true; // Trigger action for (AnimGraphTriggerAction* action : m_actionSetup.GetActions()) @@ -374,28 +374,28 @@ namespace EMotionFX void AnimGraphStateTransition::AddCondition(AnimGraphTransitionCondition* condition) { condition->SetTransition(this); - mConditions.push_back(condition); + m_conditions.push_back(condition); } void AnimGraphStateTransition::InsertCondition(AnimGraphTransitionCondition* condition, size_t index) { condition->SetTransition(this); - mConditions.insert(mConditions.begin() + index, condition); + m_conditions.insert(m_conditions.begin() + index, condition); } void AnimGraphStateTransition::ReserveConditions(size_t numConditions) { - mConditions.reserve(numConditions); + m_conditions.reserve(numConditions); } void AnimGraphStateTransition::RemoveCondition(size_t index, bool delFromMem) { if (delFromMem) { - delete mConditions[index]; + delete m_conditions[index]; } - mConditions.erase(mConditions.begin() + index); + m_conditions.erase(m_conditions.begin() + index); } void AnimGraphStateTransition::RemoveAllConditions(bool delFromMem) @@ -403,19 +403,19 @@ namespace EMotionFX // delete them all from memory if (delFromMem) { - for (AnimGraphTransitionCondition* condition : mConditions) + for (AnimGraphTransitionCondition* condition : m_conditions) { delete condition; } } - mConditions.clear(); + m_conditions.clear(); } // check if all conditions are tested positive bool AnimGraphStateTransition::CheckIfIsReady(AnimGraphInstance* animGraphInstance) const { - if (mConditions.empty()) + if (m_conditions.empty()) { return false; } @@ -423,7 +423,7 @@ namespace EMotionFX if (!GetEMotionFX().GetIsInEditorMode()) { // If we are not in editor mode, we can early out for the first failed condition - for (AnimGraphTransitionCondition* condition : mConditions) + for (AnimGraphTransitionCondition* condition : m_conditions) { const bool testResult = condition->TestCondition(animGraphInstance); @@ -440,7 +440,7 @@ namespace EMotionFX // If we are in editor mode, we need to execute all the conditions so the UI can reflect properly which ones // passed and which ones didn't bool isReady = true; - for (AnimGraphTransitionCondition* condition : mConditions) + for (AnimGraphTransitionCondition* condition : m_conditions) { const bool testResult = condition->TestCondition(animGraphInstance); @@ -455,27 +455,27 @@ namespace EMotionFX void AnimGraphStateTransition::SetIsWildcardTransition(bool isWildcardTransition) { - mIsWildcardTransition = isWildcardTransition; + m_isWildcardTransition = isWildcardTransition; } void AnimGraphStateTransition::SetSourceNode(AnimGraphInstance* animGraphInstance, AnimGraphNode* sourceNode) { UniqueData* uniqueData = static_cast(animGraphInstance->FindOrCreateUniqueObjectData(this)); - uniqueData->mSourceNode = sourceNode; + uniqueData->m_sourceNode = sourceNode; } // get the source node of the transition AnimGraphNode* AnimGraphStateTransition::GetSourceNode(AnimGraphInstance* animGraphInstance) const { // return the normal source node in case we are not dealing with a wildcard transition - if (mIsWildcardTransition == false) + if (m_isWildcardTransition == false) { - return mSourceNode; + return m_sourceNode; } // wildcard transition special case handling UniqueData* uniqueData = static_cast(animGraphInstance->FindOrCreateUniqueObjectData(this)); - return uniqueData->mSourceNode; + return uniqueData->m_sourceNode; } void AnimGraphStateTransition::SetBlendTime(float blendTime) @@ -488,8 +488,8 @@ namespace EMotionFX MCORE_UNUSED(animGraphInstance); // Use a blend time of zero in case this transition is connected to aan entry or exit state. - if ((mSourceNode && (azrtti_typeid(mSourceNode) == azrtti_typeid() || azrtti_typeid(mSourceNode) == azrtti_typeid())) || - (mTargetNode && (azrtti_typeid(mTargetNode) == azrtti_typeid() || azrtti_typeid(mTargetNode) == azrtti_typeid()))) + if ((m_sourceNode && (azrtti_typeid(m_sourceNode) == azrtti_typeid() || azrtti_typeid(m_sourceNode) == azrtti_typeid())) || + (m_targetNode && (azrtti_typeid(m_targetNode) == azrtti_typeid() || azrtti_typeid(m_targetNode) == azrtti_typeid()))) { return 0.0f; } @@ -500,7 +500,7 @@ namespace EMotionFX // callback that gets called before a node gets removed void AnimGraphStateTransition::OnRemoveNode(AnimGraph* animGraph, AnimGraphNode* nodeToRemove) { - for (AnimGraphTransitionCondition* condition : mConditions) + for (AnimGraphTransitionCondition* condition : m_conditions) { condition->OnRemoveNode(animGraph, nodeToRemove); } @@ -508,7 +508,7 @@ namespace EMotionFX void AnimGraphStateTransition::ResetConditions(AnimGraphInstance* animGraphInstance) { - for (AnimGraphTransitionCondition* condition : mConditions) + for (AnimGraphTransitionCondition* condition : m_conditions) { condition->Reset(animGraphInstance); } @@ -596,7 +596,7 @@ namespace EMotionFX { if (m_canBeInterruptedByOthers && transition != this && - (GetIsWildcardTransition() || transition->GetIsWildcardTransition() || transition->GetSourceNode() == mSourceNode)) + (GetIsWildcardTransition() || transition->GetIsWildcardTransition() || transition->GetSourceNode() == m_sourceNode)) { // Allow all in case the transition candidate list is empty, otherwise only allow transitions from the possible interruption candidate list. if (m_canBeInterruptedByTransitionIds.empty() || @@ -665,7 +665,7 @@ namespace EMotionFX // add all sub objects void AnimGraphStateTransition::RecursiveCollectObjects(AZStd::vector& outObjects) const { - for (const AnimGraphTransitionCondition* condition : mConditions) + for (const AnimGraphTransitionCondition* condition : m_conditions) { condition->RecursiveCollectObjects(outObjects); } @@ -706,7 +706,7 @@ namespace EMotionFX { AnimGraphObject::InvalidateUniqueData(animGraphInstance); - for (AnimGraphTransitionCondition* condition : mConditions) + for (AnimGraphTransitionCondition* condition : m_conditions) { condition->InvalidateUniqueData(animGraphInstance); } @@ -761,11 +761,11 @@ namespace EMotionFX void AnimGraphStateTransition::SetSourceNode(AnimGraphNode* node) { - mSourceNode = node; + m_sourceNode = node; - if (mSourceNode) + if (m_sourceNode) { - m_sourceNodeId = mSourceNode->GetId(); + m_sourceNodeId = m_sourceNode->GetId(); } else { @@ -775,17 +775,17 @@ namespace EMotionFX AnimGraphNode* AnimGraphStateTransition::GetSourceNode() const { - AZ_Assert(!mSourceNode || (mSourceNode && mSourceNode->GetId() == GetSourceNodeId()), "Source node not in sync with node id."); - return mSourceNode; + AZ_Assert(!m_sourceNode || (m_sourceNode && m_sourceNode->GetId() == GetSourceNodeId()), "Source node not in sync with node id."); + return m_sourceNode; } void AnimGraphStateTransition::SetTargetNode(AnimGraphNode* node) { - mTargetNode = node; + m_targetNode = node; - if (mTargetNode) + if (m_targetNode) { - m_targetNodeId = mTargetNode->GetId(); + m_targetNodeId = m_targetNode->GetId(); } else { @@ -795,36 +795,36 @@ namespace EMotionFX AnimGraphNode* AnimGraphStateTransition::GetTargetNode() const { - AZ_Assert(mTargetNode && mTargetNode->GetId() == GetTargetNodeId(), "Target node not in sync with node id."); - return mTargetNode; + AZ_Assert(m_targetNode && m_targetNode->GetId() == GetTargetNodeId(), "Target node not in sync with node id."); + return m_targetNode; } void AnimGraphStateTransition::SetVisualOffsets(int32 startX, int32 startY, int32 endX, int32 endY) { - mStartOffsetX = startX; - mStartOffsetY = startY; - mEndOffsetX = endX; - mEndOffsetY = endY; + m_startOffsetX = startX; + m_startOffsetY = startY; + m_endOffsetX = endX; + m_endOffsetY = endY; } int32 AnimGraphStateTransition::GetVisualStartOffsetX() const { - return mStartOffsetX; + return m_startOffsetX; } int32 AnimGraphStateTransition::GetVisualStartOffsetY() const { - return mStartOffsetY; + return m_startOffsetY; } int32 AnimGraphStateTransition::GetVisualEndOffsetX() const { - return mEndOffsetX; + return m_endOffsetX; } int32 AnimGraphStateTransition::GetVisualEndOffsetY() const { - return mEndOffsetY; + return m_endOffsetY; } bool AnimGraphStateTransition::CanWildcardTransitionFrom(AnimGraphNode* sourceNode) const @@ -837,7 +837,7 @@ namespace EMotionFX if (sourceNode) { - if (m_allowTransitionsFrom.Contains(mAnimGraph, sourceNode->GetId())) + if (m_allowTransitionsFrom.Contains(m_animGraph, sourceNode->GetId())) { // In case the given source node is part of the filter (either as individual state or part of a node group), return success. return true; @@ -849,23 +849,23 @@ namespace EMotionFX AZ::Outcome AnimGraphStateTransition::FindConditionIndex(AnimGraphTransitionCondition* condition) const { - const auto iterator = AZStd::find(mConditions.begin(), mConditions.end(), condition); - if (iterator == mConditions.end()) + const auto iterator = AZStd::find(m_conditions.begin(), m_conditions.end(), condition); + if (iterator == m_conditions.end()) { return AZ::Failure(); } - return AZ::Success(static_cast(AZStd::distance(mConditions.begin(), iterator))); + return AZ::Success(static_cast(AZStd::distance(m_conditions.begin(), iterator))); } AnimGraphStateMachine* AnimGraphStateTransition::GetStateMachine() const { - if (!mTargetNode) + if (!m_targetNode) { return nullptr; } - return azdynamic_cast(mTargetNode->GetParentNode()); + return azdynamic_cast(m_targetNode->GetParentNode()); } AZ::Crc32 AnimGraphStateTransition::GetEaseInOutSmoothnessVisibility() const @@ -881,8 +881,8 @@ namespace EMotionFX AZ::Crc32 AnimGraphStateTransition::GetVisibilityHideWhenExitOrEntry() const { // Hide when the transition is connected to an entry or an exit state. - if ((mSourceNode && (azrtti_typeid(mSourceNode) == azrtti_typeid() || azrtti_typeid(mSourceNode) == azrtti_typeid())) || - (mTargetNode && (azrtti_typeid(mTargetNode) == azrtti_typeid() || azrtti_typeid(mTargetNode) == azrtti_typeid()))) + if ((m_sourceNode && (azrtti_typeid(m_sourceNode) == azrtti_typeid() || azrtti_typeid(m_sourceNode) == azrtti_typeid())) || + (m_targetNode && (azrtti_typeid(m_targetNode) == azrtti_typeid() || azrtti_typeid(m_targetNode) == azrtti_typeid()))) { return AZ::Edit::PropertyVisibility::Hide; } @@ -1008,7 +1008,7 @@ namespace EMotionFX ->Field("id", &AnimGraphStateTransition::m_id) ->Field("sourceNodeId", &AnimGraphStateTransition::m_sourceNodeId) ->Field("targetNodeId", &AnimGraphStateTransition::m_targetNodeId) - ->Field("isWildcard", &AnimGraphStateTransition::mIsWildcardTransition) + ->Field("isWildcard", &AnimGraphStateTransition::m_isWildcardTransition) ->Field("isDisabled", &AnimGraphStateTransition::m_isDisabled) ->Field("priority", &AnimGraphStateTransition::m_priority) ->Field("canBeInterruptedByOthers", &AnimGraphStateTransition::m_canBeInterruptedByOthers) @@ -1025,11 +1025,11 @@ namespace EMotionFX ->Field("interpolationType", &AnimGraphStateTransition::m_interpolationType) ->Field("easeInSmoothness", &AnimGraphStateTransition::m_easeInSmoothness) ->Field("easeOutSmoothness", &AnimGraphStateTransition::m_easeOutSmoothness) - ->Field("startOffsetX", &AnimGraphStateTransition::mStartOffsetX) - ->Field("startOffsetY", &AnimGraphStateTransition::mStartOffsetY) - ->Field("endOffsetX", &AnimGraphStateTransition::mEndOffsetX) - ->Field("endOffsetY", &AnimGraphStateTransition::mEndOffsetY) - ->Field("conditions", &AnimGraphStateTransition::mConditions) + ->Field("startOffsetX", &AnimGraphStateTransition::m_startOffsetX) + ->Field("startOffsetY", &AnimGraphStateTransition::m_startOffsetY) + ->Field("endOffsetX", &AnimGraphStateTransition::m_endOffsetX) + ->Field("endOffsetY", &AnimGraphStateTransition::m_endOffsetY) + ->Field("conditions", &AnimGraphStateTransition::m_conditions) ->Field("actionSetup", &AnimGraphStateTransition::m_actionSetup) ->Field("extractionMode", &AnimGraphStateTransition::m_extractionMode) ; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphStateTransition.h b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphStateTransition.h index c9347111bb..9da239b13b 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphStateTransition.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphStateTransition.h @@ -63,11 +63,11 @@ namespace EMotionFX ~UniqueData() = default; public: - AnimGraphNode* mSourceNode = nullptr; - float mBlendWeight = 0.0f; - float mBlendProgress = 0.0f; - float mTotalSeconds = 0.0f; - bool mIsDone = false; + AnimGraphNode* m_sourceNode = nullptr; + float m_blendWeight = 0.0f; + float m_blendProgress = 0.0f; + float m_totalSeconds = 0.0f; + bool m_isDone = false; }; class StateFilterLocal final @@ -218,14 +218,14 @@ namespace EMotionFX * to the destination state. It is basically a transition from all nodes to the destination node of the wildcard transition. A wildcard transition does not have a fixed source node. * @result True in case the transition is a wildcard transition, false if not. */ - bool GetIsWildcardTransition() const { return mIsWildcardTransition; } + bool GetIsWildcardTransition() const { return m_isWildcardTransition; } bool CanWildcardTransitionFrom(AnimGraphNode* sourceNode) const; AnimGraphStateMachine* GetStateMachine() const; - MCORE_INLINE size_t GetNumConditions() const { return mConditions.size(); } - MCORE_INLINE AnimGraphTransitionCondition* GetCondition(size_t index) const { return mConditions[index]; } + MCORE_INLINE size_t GetNumConditions() const { return m_conditions.size(); } + MCORE_INLINE AnimGraphTransitionCondition* GetCondition(size_t index) const { return m_conditions[index]; } AZ::Outcome FindConditionIndex(AnimGraphTransitionCondition* condition) const; void AddCondition(AnimGraphTransitionCondition* condition); @@ -262,12 +262,12 @@ namespace EMotionFX AZ::Crc32 GetVisibilityCanBeInterruptedBy() const; AZ::Crc32 GetVisibilityMaxInterruptionBlendWeight() const; - AZStd::vector mConditions{}; + AZStd::vector m_conditions{}; StateFilterLocal m_allowTransitionsFrom; TriggerActionSetup m_actionSetup; - AnimGraphNode* mSourceNode = nullptr; - AnimGraphNode* mTargetNode = nullptr; + AnimGraphNode* m_sourceNode = nullptr; + AnimGraphNode* m_targetNode = nullptr; AZ::u64 m_sourceNodeId = AnimGraphNodeId::InvalidId; AZ::u64 m_targetNodeId = AnimGraphNodeId::InvalidId; AZ::u64 m_id = AnimGraphConnectionId::Create(); /**< The unique identification number. */ @@ -275,16 +275,16 @@ namespace EMotionFX float m_transitionTime = 0.3f; float m_easeInSmoothness = 0.0f; float m_easeOutSmoothness = 1.0f; - AZ::s32 mStartOffsetX = 0; - AZ::s32 mStartOffsetY = 0; - AZ::s32 mEndOffsetX = 0; - AZ::s32 mEndOffsetY = 0; + AZ::s32 m_startOffsetX = 0; + AZ::s32 m_startOffsetY = 0; + AZ::s32 m_endOffsetX = 0; + AZ::s32 m_endOffsetY = 0; AZ::u32 m_priority = 0; AnimGraphObject::ESyncMode m_syncMode = AnimGraphObject::SYNCMODE_DISABLED; AnimGraphObject::EEventMode m_eventMode = AnimGraphObject::EVENTMODE_BOTHNODES; AnimGraphObject::EExtractionMode m_extractionMode = AnimGraphObject::EXTRACTIONMODE_BLEND; EInterpolationType m_interpolationType = INTERPOLATIONFUNCTION_LINEAR; - bool mIsWildcardTransition = false; /**< Flag which indicates if the state transition is a wildcard transition or not. */ + bool m_isWildcardTransition = false; /**< Flag which indicates if the state transition is a wildcard transition or not. */ bool m_isDisabled = false; bool m_canBeInterruptedByOthers = false; AZStd::vector m_canBeInterruptedByTransitionIds{}; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphSyncTrack.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphSyncTrack.cpp index c6ccf038dd..3c77beaa60 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphSyncTrack.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphSyncTrack.cpp @@ -364,7 +364,7 @@ namespace EMotionFX float AnimGraphSyncTrack::GetDuration() const { - return mMotion->GetMotionData()->GetDuration(); + return m_motion->GetMotionData()->GetDuration(); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphTagCondition.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphTagCondition.cpp index 6b2d0084d7..e6f6e9b9bd 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphTagCondition.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphTagCondition.cpp @@ -54,7 +54,7 @@ namespace EMotionFX for (size_t i = 0; i < numTags; ++i) { // Search for the parameter with the name of the tag and save the index. - const AZ::Outcome parameterIndex = mAnimGraph->FindValueParameterIndexByName(m_tags[i]); + const AZ::Outcome parameterIndex = m_animGraph->FindValueParameterIndexByName(m_tags[i]); if (parameterIndex.IsSuccess()) { // Cache the parameter index to avoid string lookups at runtime. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphTimeCondition.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphTimeCondition.cpp index a339d5752b..3da55ced3e 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphTimeCondition.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphTimeCondition.cpp @@ -73,7 +73,7 @@ namespace EMotionFX UniqueData* uniqueData = static_cast(animGraphInstance->FindOrCreateUniqueObjectData(this)); // increase the elapsed time of the condition - uniqueData->mElapsedTime += timePassedInSeconds; + uniqueData->m_elapsedTime += timePassedInSeconds; } @@ -84,7 +84,7 @@ namespace EMotionFX UniqueData* uniqueData = static_cast(animGraphInstance->FindOrCreateUniqueObjectData(this)); // reset the elapsed time - uniqueData->mElapsedTime = 0.0f; + uniqueData->m_elapsedTime = 0.0f; // use randomized count downs? if (m_useRandomization) @@ -93,17 +93,17 @@ namespace EMotionFX if (animGraphInstance->IsNetworkEnabled()) { // using a seeded random in order to generate predictable result in network. - uniqueData->mCountDownTime = MCore::Random::RandF(m_minRandomTime, m_maxRandomTime, animGraphInstance->GetLcgRandom()); + uniqueData->m_countDownTime = MCore::Random::RandF(m_minRandomTime, m_maxRandomTime, animGraphInstance->GetLcgRandom()); } else { - uniqueData->mCountDownTime = MCore::Random::RandF(m_minRandomTime, m_maxRandomTime); + uniqueData->m_countDownTime = MCore::Random::RandF(m_minRandomTime, m_maxRandomTime); } } else { // get the fixed count down value from the attribute - uniqueData->mCountDownTime = m_countDownTime; + uniqueData->m_countDownTime = m_countDownTime; } } @@ -115,7 +115,7 @@ namespace EMotionFX UniqueData* uniqueData = static_cast(animGraphInstance->FindOrCreateUniqueObjectData(this)); // in case the elapsed time is bigger than the count down time, we can trigger the condition - if (uniqueData->mElapsedTime + 0.0001f >= uniqueData->mCountDownTime) // The 0.0001f is to counter floating point inaccuracies. The AZ float epsilon is too small. + if (uniqueData->m_elapsedTime + 0.0001f >= uniqueData->m_countDownTime) // The 0.0001f is to counter floating point inaccuracies. The AZ float epsilon is too small. { return true; } @@ -162,8 +162,8 @@ namespace EMotionFX AnimGraphTimeCondition::UniqueData::UniqueData(AnimGraphObject* object, AnimGraphInstance* animGraphInstance) : AnimGraphObjectData(object, animGraphInstance) { - mElapsedTime = 0.0f; - mCountDownTime = 0.0f; + m_elapsedTime = 0.0f; + m_countDownTime = 0.0f; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphTimeCondition.h b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphTimeCondition.h index 96de4f2d36..47d17a4d10 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphTimeCondition.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphTimeCondition.h @@ -42,8 +42,8 @@ namespace EMotionFX ~UniqueData() override; public: - float mElapsedTime; /**< The elapsed time in seconds for the given anim graph instance. */ - float mCountDownTime; /**< The count down time in seconds for the given anim graph instance. */ + float m_elapsedTime; /**< The elapsed time in seconds for the given anim graph instance. */ + float m_countDownTime; /**< The count down time in seconds for the given anim graph instance. */ }; AnimGraphTimeCondition(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphTransitionCondition.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphTransitionCondition.cpp index dd297177f3..d7b626f4cf 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphTransitionCondition.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphTransitionCondition.cpp @@ -24,9 +24,9 @@ namespace EMotionFX AnimGraphTransitionCondition::~AnimGraphTransitionCondition() { - if (mAnimGraph) + if (m_animGraph) { - mAnimGraph->RemoveObject(this); + m_animGraph->RemoveObject(this); } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphTriggerAction.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphTriggerAction.cpp index 05b4c6c5b5..ffb8898ce0 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphTriggerAction.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphTriggerAction.cpp @@ -30,9 +30,9 @@ namespace EMotionFX AnimGraphTriggerAction::~AnimGraphTriggerAction() { - if (mAnimGraph) + if (m_animGraph) { - mAnimGraph->RemoveObject(this); + m_animGraph->RemoveObject(this); } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphVector2Condition.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphVector2Condition.cpp index ac1e283c19..987f74417e 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphVector2Condition.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphVector2Condition.cpp @@ -57,7 +57,7 @@ namespace EMotionFX SetOperation(m_operation); // Find the parameter index for the given parameter name, to prevent string based lookups every frame - m_parameterIndex = mAnimGraph->FindValueParameterIndexByName(m_parameterName); + m_parameterIndex = m_animGraph->FindValueParameterIndexByName(m_parameterName); } @@ -89,7 +89,7 @@ namespace EMotionFX if (m_parameterIndex.IsSuccess()) { // get access to the parameter info and return the type of its default value - const ValueParameter* valueParameter = mAnimGraph->FindValueParameter(m_parameterIndex.GetValue()); + const ValueParameter* valueParameter = m_animGraph->FindValueParameter(m_parameterIndex.GetValue()); return azrtti_typeid(valueParameter); } else @@ -348,7 +348,7 @@ namespace EMotionFX { AZ_UNUSED(beforeChange); AZ_UNUSED(afterChange); - m_parameterIndex = mAnimGraph->FindValueParameterIndexByName(m_parameterName); + m_parameterIndex = m_animGraph->FindValueParameterIndexByName(m_parameterName); } void AnimGraphVector2Condition::ParameterRemoved(const AZStd::string& oldParameterName) @@ -360,7 +360,7 @@ namespace EMotionFX } else { - m_parameterIndex = mAnimGraph->FindValueParameterIndexByName(m_parameterName); + m_parameterIndex = m_animGraph->FindValueParameterIndexByName(m_parameterName); } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendSpace1DNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendSpace1DNode.cpp index ee4b6d0dab..0e823075a4 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendSpace1DNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendSpace1DNode.cpp @@ -81,7 +81,7 @@ namespace EMotionFX void BlendSpace1DNode::UniqueData::Update() { - BlendSpace1DNode* blendSpaceNode = azdynamic_cast(mObject); + BlendSpace1DNode* blendSpaceNode = azdynamic_cast(m_object); AZ_Assert(blendSpaceNode, "Unique data linked to incorrect node type."); blendSpaceNode->UpdateMotionInfos(this); @@ -172,7 +172,7 @@ namespace EMotionFX } // If the node is disabled, simply output a bind pose. - if (mDisabled) + if (m_disabled) { SetBindPoseAtOutput(animGraphInstance); return; @@ -246,7 +246,7 @@ namespace EMotionFX if (GetEMotionFX().GetIsInEditorMode() && GetCanVisualize(animGraphInstance)) { - animGraphInstance->GetActorInstance()->DrawSkeleton(outputPose->GetPose(), mVisualizeColor); + animGraphInstance->GetActorInstance()->DrawSkeleton(outputPose->GetPose(), m_visualizeColor); } } @@ -262,7 +262,7 @@ namespace EMotionFX DoTopDownUpdate(animGraphInstance, m_syncMode, uniqueData->m_leaderMotionIdx, uniqueData->m_motionInfos, uniqueData->m_allMotionsHaveSyncTracks); - EMotionFX::BlendTreeConnection* paramConnection = GetInputPort(INPUTPORT_VALUE).mConnection; + EMotionFX::BlendTreeConnection* paramConnection = GetInputPort(INPUTPORT_VALUE).m_connection; if (paramConnection) { AnimGraphNode* paramSrcNode = paramConnection->GetSourceNode(); @@ -276,9 +276,9 @@ namespace EMotionFX void BlendSpace1DNode::Update(AnimGraphInstance* animGraphInstance, float timePassedInSeconds) { - if (!mDisabled) + if (!m_disabled) { - EMotionFX::BlendTreeConnection* paramConnection = GetInputPort(INPUTPORT_VALUE).mConnection; + EMotionFX::BlendTreeConnection* paramConnection = GetInputPort(INPUTPORT_VALUE).m_connection; if (paramConnection) { UpdateIncomingNode(animGraphInstance, paramConnection->GetSourceNode(), timePassedInSeconds); @@ -291,7 +291,7 @@ namespace EMotionFX AZ_Assert(uniqueData, "UniqueData not found for BlendSpace1DNode"); uniqueData->Clear(); - if (mDisabled) + if (m_disabled) { return; } @@ -331,7 +331,7 @@ namespace EMotionFX UniqueData* uniqueData = static_cast(FindOrCreateUniqueNodeData(animGraphInstance)); - if (mDisabled) + if (m_disabled) { RequestRefDatas(animGraphInstance); AnimGraphRefCountedData* data = uniqueData->GetRefCountedData(); @@ -340,7 +340,7 @@ namespace EMotionFX return; } - EMotionFX::BlendTreeConnection* paramConnection = GetInputPort(INPUTPORT_VALUE).mConnection; + EMotionFX::BlendTreeConnection* paramConnection = GetInputPort(INPUTPORT_VALUE).m_connection; if (paramConnection) { paramConnection->GetSourceNode()->PerformPostUpdate(animGraphInstance, timePassedInSeconds); @@ -410,7 +410,7 @@ namespace EMotionFX MotionInstance* motionInstance = motionInstancePool.RequestNew(motion, actorInstance); motionInstance->InitFromPlayBackInfo(playInfo, true); - motionInstance->SetRetargetingEnabled(animGraphInstance->GetRetargetingEnabled() && playInfo.mRetarget); + motionInstance->SetRetargetingEnabled(animGraphInstance->GetRetargetingEnabled() && playInfo.m_retarget); motionInstance->UnPause(); motionInstance->SetIsActive(true); motionInstance->SetWeight(1.0f, 0.0f); @@ -434,7 +434,7 @@ namespace EMotionFX bool BlendSpace1DNode::GetIsInPlace(AnimGraphInstance* animGraphInstance) const { - EMotionFX::BlendTreeConnection* inPlaceConnection = GetInputPort(INPUTPORT_INPLACE).mConnection; + EMotionFX::BlendTreeConnection* inPlaceConnection = GetInputPort(INPUTPORT_INPLACE).m_connection; if (inPlaceConnection) { return GetInputNumberAsBool(animGraphInstance, INPUTPORT_INPLACE); @@ -584,7 +584,7 @@ namespace EMotionFX void BlendSpace1DNode::SetMotions(const AZStd::vector& motions) { m_motions = motions; - if (mAnimGraph) + if (m_animGraph) { Reinit(); } @@ -638,7 +638,7 @@ namespace EMotionFX } else { - EMotionFX::BlendTreeConnection* paramConnection = GetInputPort(INPUTPORT_VALUE).mConnection; + EMotionFX::BlendTreeConnection* paramConnection = GetInputPort(INPUTPORT_VALUE).m_connection; if (GetEMotionFX().GetIsInEditorMode()) { @@ -754,7 +754,7 @@ namespace EMotionFX void BlendSpace1DNode::SetCalculationMethod(ECalculationMethod calculationMethod) { m_calculationMethod = calculationMethod; - if (mAnimGraph) + if (m_animGraph) { Reinit(); } @@ -770,7 +770,7 @@ namespace EMotionFX void BlendSpace1DNode::SetSyncLeaderMotionId(const AZStd::string& syncLeaderMotionId) { m_syncLeaderMotionId = syncLeaderMotionId; - if (mAnimGraph) + if (m_animGraph) { Reinit(); } @@ -786,7 +786,7 @@ namespace EMotionFX void BlendSpace1DNode::SetEvaluatorType(const AZ::TypeId& evaluatorType) { m_evaluatorType = evaluatorType; - if (mAnimGraph) + if (m_animGraph) { Reinit(); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendSpace2DNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendSpace2DNode.cpp index c1f1035f00..b34a860b71 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendSpace2DNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendSpace2DNode.cpp @@ -160,7 +160,7 @@ namespace EMotionFX void BlendSpace2DNode::UniqueData::Update() { - BlendSpace2DNode* blendSpaceNode = azdynamic_cast(mObject); + BlendSpace2DNode* blendSpaceNode = azdynamic_cast(m_object); AZ_Assert(blendSpaceNode, "Unique data linked to incorrect node type."); blendSpaceNode->UpdateMotionInfos(this); @@ -273,7 +273,7 @@ namespace EMotionFX bool BlendSpace2DNode::GetIsInPlace(AnimGraphInstance* animGraphInstance) const { - EMotionFX::BlendTreeConnection* inPlaceConnection = GetInputPort(INPUTPORT_INPLACE).mConnection; + EMotionFX::BlendTreeConnection* inPlaceConnection = GetInputPort(INPUTPORT_INPLACE).m_connection; if (inPlaceConnection) { return GetInputNumberAsBool(animGraphInstance, INPUTPORT_INPLACE); @@ -301,7 +301,7 @@ namespace EMotionFX } // If the node is disabled, simply output a bind pose. - if (mDisabled) + if (m_disabled) { SetBindPoseAtOutput(animGraphInstance); return; @@ -378,7 +378,7 @@ namespace EMotionFX if (GetEMotionFX().GetIsInEditorMode() && GetCanVisualize(animGraphInstance)) { - animGraphInstance->GetActorInstance()->DrawSkeleton(outputPose->GetPose(), mVisualizeColor); + animGraphInstance->GetActorInstance()->DrawSkeleton(outputPose->GetPose(), m_visualizeColor); } } @@ -389,7 +389,7 @@ namespace EMotionFX return; } - if (mDisabled) + if (m_disabled) { return; } @@ -401,7 +401,7 @@ namespace EMotionFX for (int i = 0; i < 2; ++i) { const uint32 portIdx = (i == 0) ? INPUTPORT_XVALUE : INPUTPORT_YVALUE; - EMotionFX::BlendTreeConnection* paramConnection = GetInputPort(portIdx).mConnection; + EMotionFX::BlendTreeConnection* paramConnection = GetInputPort(portIdx).m_connection; if (paramConnection) { AnimGraphNode* paramSrcNode = paramConnection->GetSourceNode(); @@ -420,15 +420,15 @@ namespace EMotionFX return; } - if (!mDisabled) + if (!m_disabled) { - EMotionFX::BlendTreeConnection* param1Connection = GetInputPort(INPUTPORT_XVALUE).mConnection; + EMotionFX::BlendTreeConnection* param1Connection = GetInputPort(INPUTPORT_XVALUE).m_connection; if (param1Connection) { UpdateIncomingNode(animGraphInstance, param1Connection->GetSourceNode(), timePassedInSeconds); } - EMotionFX::BlendTreeConnection* param2Connection = GetInputPort(INPUTPORT_YVALUE).mConnection; + EMotionFX::BlendTreeConnection* param2Connection = GetInputPort(INPUTPORT_YVALUE).m_connection; if (param2Connection) { UpdateIncomingNode(animGraphInstance, param2Connection->GetSourceNode(), timePassedInSeconds); @@ -441,7 +441,7 @@ namespace EMotionFX AZ_Assert(uniqueData, "Unique data not found for blend space 2D node '%s'.", GetName()); uniqueData->Clear(); - if (mDisabled) + if (m_disabled) { return; } @@ -481,7 +481,7 @@ namespace EMotionFX UniqueData* uniqueData = static_cast(FindOrCreateUniqueNodeData(animGraphInstance)); - if (mDisabled) + if (m_disabled) { RequestRefDatas(animGraphInstance); AnimGraphRefCountedData* data = uniqueData->GetRefCountedData(); @@ -490,12 +490,12 @@ namespace EMotionFX return; } - EMotionFX::BlendTreeConnection* param1Connection = GetInputPort(INPUTPORT_XVALUE).mConnection; + EMotionFX::BlendTreeConnection* param1Connection = GetInputPort(INPUTPORT_XVALUE).m_connection; if (param1Connection) { param1Connection->GetSourceNode()->PerformPostUpdate(animGraphInstance, timePassedInSeconds); } - EMotionFX::BlendTreeConnection* param2Connection = GetInputPort(INPUTPORT_YVALUE).mConnection; + EMotionFX::BlendTreeConnection* param2Connection = GetInputPort(INPUTPORT_YVALUE).m_connection; if (param2Connection) { param2Connection->GetSourceNode()->PerformPostUpdate(animGraphInstance, timePassedInSeconds); @@ -565,7 +565,7 @@ namespace EMotionFX MotionInstance* motionInstance = motionInstancePool.RequestNew(motion, actorInstance); motionInstance->InitFromPlayBackInfo(playInfo, true); - motionInstance->SetRetargetingEnabled(animGraphInstance->GetRetargetingEnabled() && playInfo.mRetarget); + motionInstance->SetRetargetingEnabled(animGraphInstance->GetRetargetingEnabled() && playInfo.m_retarget); motionInstance->UnPause(); motionInstance->SetIsActive(true); motionInstance->SetWeight(1.0f, 0.0f); @@ -693,7 +693,7 @@ namespace EMotionFX void BlendSpace2DNode::SetMotions(const AZStd::vector& motions) { m_motions = motions; - if (mAnimGraph) + if (m_animGraph) { Reinit(); } @@ -709,7 +709,7 @@ namespace EMotionFX void BlendSpace2DNode::SetSyncLeaderMotionId(const AZStd::string& syncLeaderMotionId) { m_syncLeaderMotionId = syncLeaderMotionId; - if (mAnimGraph) + if (m_animGraph) { Reinit(); } @@ -725,7 +725,7 @@ namespace EMotionFX void BlendSpace2DNode::SetEvaluatorTypeX(const AZ::TypeId& evaluatorType) { m_evaluatorTypeX = evaluatorType; - if (mAnimGraph) + if (m_animGraph) { Reinit(); } @@ -747,7 +747,7 @@ namespace EMotionFX void BlendSpace2DNode::SetCalculationMethodX(ECalculationMethod calculationMethod) { m_calculationMethodX = calculationMethod; - if (mAnimGraph) + if (m_animGraph) { Reinit(); } @@ -763,7 +763,7 @@ namespace EMotionFX void BlendSpace2DNode::SetEvaluatorTypeY(const AZ::TypeId& evaluatorType) { m_evaluatorTypeY = evaluatorType; - if (mAnimGraph) + if (m_animGraph) { Reinit(); } @@ -785,7 +785,7 @@ namespace EMotionFX void BlendSpace2DNode::SetCalculationMethodY(ECalculationMethod calculationMethod) { m_calculationMethodY = calculationMethod; - if (mAnimGraph) + if (m_animGraph) { Reinit(); } @@ -1041,8 +1041,8 @@ namespace EMotionFX { AZ::Vector2 samplePoint; - EMotionFX::BlendTreeConnection* inputConnectionX = GetInputPort(INPUTPORT_XVALUE).mConnection; - EMotionFX::BlendTreeConnection* inputConnectionY = GetInputPort(INPUTPORT_YVALUE).mConnection; + EMotionFX::BlendTreeConnection* inputConnectionX = GetInputPort(INPUTPORT_XVALUE).m_connection; + EMotionFX::BlendTreeConnection* inputConnectionY = GetInputPort(INPUTPORT_YVALUE).m_connection; if (GetEMotionFX().GetIsInEditorMode()) { diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendSpaceNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendSpaceNode.cpp index 953bb530e7..2c3960ca5e 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendSpaceNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendSpaceNode.cpp @@ -233,7 +233,7 @@ namespace EMotionFX MotionInstance* motionInstance = motionInfo.m_motionInstance; motionInstance->SetFreezeAtLastFrame(!motionInstance->GetIsPlayingForever()); motionInstance->SetPlaySpeed(motionInfo.m_playSpeed); - motionInstance->SetRetargetingEnabled(m_retarget && mAnimGraph->GetRetargetingEnabled()); + motionInstance->SetRetargetingEnabled(m_retarget && m_animGraph->GetRetargetingEnabled()); motionInfo.m_preSyncTime = motionInstance->GetCurrentTime(); // If syncing is enabled, we are going to update the current play time (m_currentTime) of all motions later based @@ -361,8 +361,8 @@ namespace EMotionFX trajectoryDeltaAMirrored.Add(instanceDelta, blendInfo.m_weight); motionInstance->SetMirrorMotion(isMirrored); // restore current mirrored flag } - trajectoryDelta.mRotation.Normalize(); - trajectoryDeltaAMirrored.mRotation.Normalize(); + trajectoryDelta.m_rotation.Normalize(); + trajectoryDeltaAMirrored.m_rotation.Normalize(); } data->SetTrajectoryDelta(trajectoryDelta); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendSpaceNode.h b/Gems/EMotionFX/Code/EMotionFX/Source/BlendSpaceNode.h index 893962d65d..b2acd240ee 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendSpaceNode.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendSpaceNode.h @@ -102,8 +102,8 @@ namespace EMotionFX virtual const AZStd::vector& GetMotions() const = 0; //! The node is in interactive mode when the user is interactively changing the current point. - void SetInteractiveMode(bool enable) { mInteractiveMode = enable; } - bool IsInInteractiveMode() const { return mInteractiveMode; } + void SetInteractiveMode(bool enable) { m_interactiveMode = enable; } + bool IsInInteractiveMode() const { return m_interactiveMode; } static void Reflect(AZ::ReflectContext* context); @@ -166,7 +166,7 @@ namespace EMotionFX static const char* s_eventModeNone; protected: - bool mInteractiveMode = false;// true when the user is changing the current point by dragging in GUI + bool m_interactiveMode = false;// true when the user is changing the current point by dragging in GUI bool m_retarget = true; bool m_inPlace = false; }; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendSpaceParamEvaluator.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendSpaceParamEvaluator.cpp index 48f343cfc3..fb3f9e398a 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendSpaceParamEvaluator.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendSpaceParamEvaluator.cpp @@ -100,14 +100,14 @@ namespace EMotionFX Transform transform; motion->CalcNodeTransform(&motionInstance, &transform, actor, node, 0, retargeting); - AZ::Vector3 position(transform.mPosition); + AZ::Vector3 position(transform.m_position); float distance = 0.0f; float time = sampleTimeStep; for (uint32 i = 1; i < numSamples; ++i, time += sampleTimeStep) { motion->CalcNodeTransform(&motionInstance, &transform, actor, node, time, retargeting); - distance += (transform.mPosition - position).GetLength(); - position = transform.mPosition; + distance += (transform.m_position - position).GetLength(); + position = transform.m_position; } return distance / duration; @@ -142,16 +142,16 @@ namespace EMotionFX Transform transform; motion->CalcNodeTransform(&motionInstance, &transform, actor, node, 0, retargeting); - AZ::Quaternion rotation(transform.mRotation); + AZ::Quaternion rotation(transform.m_rotation); float totalAngle = 0.0f; float time = sampleTimeStep; for (uint32 i = 1; i < numSamples; ++i, time += sampleTimeStep) { motion->CalcNodeTransform(&motionInstance, &transform, actor, node, time, retargeting); - AZ::Quaternion deltaRotation = transform.mRotation * rotation.GetConjugate(); + AZ::Quaternion deltaRotation = transform.m_rotation * rotation.GetConjugate(); const float angle = -MCore::GetEulerZ(deltaRotation);// negating because we prefer the convention of clockwise being +ve totalAngle += angle; - rotation = transform.mRotation; + rotation = transform.m_rotation; } return totalAngle / duration; @@ -185,7 +185,7 @@ namespace EMotionFX Transform endTransform; motion->CalcNodeTransform(&motionInstance, &endTransform, actor, node, duration, retargeting); - AZ::Vector3 diffVec(endTransform.mPosition - startTransform.mPosition); + AZ::Vector3 diffVec(endTransform.m_position - startTransform.m_position); return ::atan2f(diffVec.GetX(), diffVec.GetY()); } @@ -218,19 +218,19 @@ namespace EMotionFX Transform transform; motion->CalcNodeTransform(&motionInstance, &transform, actor, node, 0, retargeting); - AZ::Vector3 position(transform.mPosition); + AZ::Vector3 position(transform.m_position); float slopeSum = 0.0f; float time = sampleTimeStep; uint32 count = 0; // number of samples added to slopeSum for (uint32 i = 1; i < numSamples; ++i, time += sampleTimeStep) { motion->CalcNodeTransform(&motionInstance, &transform, actor, node, time, retargeting); - AZ::Vector3 diffVec(transform.mPosition - position); + AZ::Vector3 diffVec(transform.m_position - position); float horizontalDistance = AZ::Vector2(diffVec.GetX(), diffVec.GetY()).GetLength(); if (horizontalDistance > 0) { slopeSum += atan2f(diffVec.GetZ(), horizontalDistance); - position = transform.mPosition; + position = transform.m_position; count++; } } @@ -268,16 +268,16 @@ namespace EMotionFX Transform transform; motion->CalcNodeTransform(&motionInstance, &transform, actor, node, 0, retargeting); - AZ::Quaternion rotation(transform.mRotation); + AZ::Quaternion rotation(transform.m_rotation); float totalTurnAngle = 0.0f; float time = sampleTimeStep; for (uint32 i = 1; i < numSamples; ++i, time += sampleTimeStep) { motion->CalcNodeTransform(&motionInstance, &transform, actor, node, time, retargeting); - AZ::Quaternion deltaRotation = transform.mRotation * rotation.GetConjugate(); + AZ::Quaternion deltaRotation = transform.m_rotation * rotation.GetConjugate(); const float angle = -MCore::GetEulerZ(deltaRotation);// negating because we prefer the convention of clockwise being +ve totalTurnAngle += angle; - rotation = transform.mRotation; + rotation = transform.m_rotation; } return totalTurnAngle; @@ -311,7 +311,7 @@ namespace EMotionFX Transform endTransform; motion->CalcNodeTransform(&motionInstance, &endTransform, actor, node, duration, retargeting); - return (endTransform.mPosition - startTransform.mPosition).GetLength(); + return (endTransform.m_position - startTransform.m_position).GetLength(); } const char* BlendSpaceTravelDistanceParamEvaluator::GetName() const @@ -345,15 +345,15 @@ namespace EMotionFX Transform transform; motion->CalcNodeTransform(&motionInstance, &transform, actor, node, 0, retargeting); - AZ::Vector3 position(transform.mPosition); + AZ::Vector3 position(transform.m_position); float distance = 0.0f; float time = sampleTimeStep; for (uint32 i = 1; i < numSamples; ++i, time += sampleTimeStep) { motion->CalcNodeTransform(&motionInstance, &transform, actor, node, time, retargeting); - AZ::Vector3 moveVec(transform.mPosition - position); + AZ::Vector3 moveVec(transform.m_position - position); distance += moveVec.Dot(xAxis); - position = transform.mPosition; + position = transform.m_position; } return distance / duration; @@ -390,15 +390,15 @@ namespace EMotionFX Transform transform; motion->CalcNodeTransform(&motionInstance, &transform, actor, node, 0, retargeting); - AZ::Vector3 position(transform.mPosition); + AZ::Vector3 position(transform.m_position); float distance = 0.0f; float time = sampleTimeStep; for (uint32 i = 1; i < numSamples; ++i, time += sampleTimeStep) { motion->CalcNodeTransform(&motionInstance, &transform, actor, node, time, retargeting); - AZ::Vector3 moveVec(transform.mPosition - position); + AZ::Vector3 moveVec(transform.m_position - position); distance += moveVec.Dot(yAxis); - position = transform.mPosition; + position = transform.m_position; } return distance / duration; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTree.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTree.cpp index 809a5d1c31..f742696275 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTree.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTree.cpp @@ -30,7 +30,7 @@ namespace EMotionFX : AnimGraphNode() , m_finalNodeId(AnimGraphNodeId::InvalidId) , m_finalNode(nullptr) - , mVirtualFinalNode(nullptr) + , m_virtualFinalNode(nullptr) { // setup output ports InitOutputPorts(1); @@ -88,7 +88,7 @@ namespace EMotionFX // Relink input and output ports for all nodes in the blend tree with their corresponding connections. // This has to be done after all child nodes called InitAfterLoading() and RegisterPorts(). We're depending on the node load order here // and a given node might be connected to one that has not been loaded yet and thus the ports have not been created yet. - for (AnimGraphNode* childNode : mChildNodes) + for (AnimGraphNode* childNode : m_childNodes) { childNode->RelinkPortConnections(); } @@ -102,9 +102,9 @@ namespace EMotionFX AnimGraphNode* BlendTree::GetRealFinalNode() const { // if there is a virtual final node, use that one - if (mVirtualFinalNode) + if (m_virtualFinalNode) { - return mVirtualFinalNode; + return m_virtualFinalNode; } // otherwise get the real final node @@ -126,7 +126,7 @@ namespace EMotionFX AnimGraphPose* outputPose; // if this node is disabled, output the bind pose - if (mDisabled) + if (m_disabled) { RequestPoses(animGraphInstance); outputPose = GetOutputPose(animGraphInstance, OUTPUTPORT_POSE)->GetValue(); @@ -156,7 +156,7 @@ namespace EMotionFX // visualize it if (GetEMotionFX().GetIsInEditorMode() && GetCanVisualize(animGraphInstance)) { - animGraphInstance->GetActorInstance()->DrawSkeleton(outputPose->GetPose(), mVisualizeColor); + animGraphInstance->GetActorInstance()->DrawSkeleton(outputPose->GetPose(), m_visualizeColor); } } @@ -165,7 +165,7 @@ namespace EMotionFX void BlendTree::PostUpdate(AnimGraphInstance* animGraphInstance, float timePassedInSeconds) { // if this node is disabled, exit - if (mDisabled) + if (m_disabled) { RequestRefDatas(animGraphInstance); AnimGraphNodeData* uniqueData = FindOrCreateUniqueNodeData(animGraphInstance); @@ -213,7 +213,7 @@ namespace EMotionFX void BlendTree::Update(AnimGraphInstance* animGraphInstance, float timePassedInSeconds) { // if this node is disabled, output the bind pose - if (mDisabled) + if (m_disabled) { AnimGraphNodeData* uniqueData = FindOrCreateUniqueNodeData(animGraphInstance); uniqueData->Clear(); @@ -243,7 +243,7 @@ namespace EMotionFX // rewind the nodes in the tree void BlendTree::Rewind(AnimGraphInstance* animGraphInstance) { - for (AnimGraphNode* childNode : mChildNodes) + for (AnimGraphNode* childNode : m_childNodes) { childNode->Rewind(animGraphInstance); } @@ -276,7 +276,7 @@ namespace EMotionFX void BlendTree::RecursiveSetUniqueDataFlag(AnimGraphInstance* animGraphInstance, uint32 flag, bool enabled) { // set flag for this node - animGraphInstance->SetObjectFlags(mObjectIndex, flag, enabled); + animGraphInstance->SetObjectFlags(m_objectIndex, flag, enabled); // get the final node AnimGraphNode* finalNode = GetRealFinalNode(); @@ -310,7 +310,7 @@ namespace EMotionFX void BlendTree::SetVirtualFinalNode(AnimGraphNode* node) { - mVirtualFinalNode = node; + m_virtualFinalNode = node; AnimGraphNotificationBus::Broadcast(&AnimGraphNotificationBus::Events::OnVirtualFinalNodeSet, this); } @@ -319,7 +319,7 @@ namespace EMotionFX void BlendTree::SetFinalNodeId(const AnimGraphNodeId finalNodeId) { m_finalNodeId = finalNodeId; - if (mAnimGraph) + if (m_animGraph) { Reinit(); } @@ -342,7 +342,7 @@ namespace EMotionFX AZStd::unordered_set visitedNodes; AZStd::unordered_set > cycleConnections; - for (AnimGraphNode* childNode : mChildNodes) + for (AnimGraphNode* childNode : m_childNodes) { visitedNodes.clear(); visitedNodes.emplace(childNode); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTree.h b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTree.h index cfe844fdb9..4ba4ba1f00 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTree.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTree.h @@ -64,7 +64,7 @@ namespace EMotionFX bool GetHasOutputPose() const override { return true; } void SetVirtualFinalNode(AnimGraphNode* node); - MCORE_INLINE AnimGraphNode* GetVirtualFinalNode() const { return mVirtualFinalNode; } + MCORE_INLINE AnimGraphNode* GetVirtualFinalNode() const { return m_virtualFinalNode; } void SetFinalNodeId(const AnimGraphNodeId finalNodeId); AZ_FORCE_INLINE AnimGraphNodeId GetFinalNodeId() const { return m_finalNodeId; } @@ -100,7 +100,7 @@ namespace EMotionFX private: AZ::u64 m_finalNodeId; /**< Id of the final node that gets serialized. The final node represents the output of the blend tree. */ BlendTreeFinalNode* m_finalNode; /**< The cached final node pointer based on the final node id. */ - AnimGraphNode* mVirtualFinalNode; /**< The virtual final node, which is the node who's output is used as final output. A value of nullptr means it will use the real mFinalNode. */ + AnimGraphNode* m_virtualFinalNode; /**< The virtual final node, which is the node who's output is used as final output. A value of nullptr means it will use the real m_finalNode. */ /** * Helper function that recursively (through incoming connections) detect cycles. The function performs a DFS to find back edges (connections to itself or to one of its ancestors). diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeAccumTransformNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeAccumTransformNode.cpp index ffbf38c48a..c8f53a4b6f 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeAccumTransformNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeAccumTransformNode.cpp @@ -28,28 +28,28 @@ namespace EMotionFX BlendTreeAccumTransformNode::UniqueData::UniqueData(AnimGraphNode* node, AnimGraphInstance* animGraphInstance) : AnimGraphNodeData(node, animGraphInstance) { - mAdditiveTransform.Identity(); - EMFX_SCALECODE(mAdditiveTransform.mScale.CreateZero();) + m_additiveTransform.Identity(); + EMFX_SCALECODE(m_additiveTransform.m_scale.CreateZero();) SetHasError(true); } void BlendTreeAccumTransformNode::UniqueData::Update() { - BlendTreeAccumTransformNode* accumTransformNode = azdynamic_cast(mObject); + BlendTreeAccumTransformNode* accumTransformNode = azdynamic_cast(m_object); AZ_Assert(accumTransformNode, "Unique data linked to incorrect node type."); - const ActorInstance* actorInstance = mAnimGraphInstance->GetActorInstance(); + const ActorInstance* actorInstance = m_animGraphInstance->GetActorInstance(); const Actor* actor = actorInstance->GetActor(); const Skeleton* skeleton = actor->GetSkeleton(); const Node* node = skeleton->FindNodeByName(accumTransformNode->GetTargetNodeName().c_str()); if (node) { - mNodeIndex = node->GetNodeIndex(); + m_nodeIndex = node->GetNodeIndex(); SetHasError(false); } else { - mNodeIndex = InvalidIndex; + m_nodeIndex = InvalidIndex; SetHasError(true); } } @@ -137,7 +137,7 @@ namespace EMotionFX // make sure we have at least an input pose, otherwise output the bind pose - if (GetInputPort(INPUTPORT_POSE).mConnection == nullptr) + if (GetInputPort(INPUTPORT_POSE).m_connection == nullptr) { RequestPoses(animGraphInstance); outputPose = GetOutputPose(animGraphInstance, OUTPUTPORT_RESULT)->GetValue(); @@ -154,12 +154,12 @@ namespace EMotionFX // get the local transform from our node Transform inputTransform; - outputPose->GetPose().GetLocalSpaceTransform(uniqueData->mNodeIndex, &inputTransform); + outputPose->GetPose().GetLocalSpaceTransform(uniqueData->m_nodeIndex, &inputTransform); Transform outputTransform = inputTransform; // process the rotation - if (GetInputPort(INPUTPORT_ROTATE_AMOUNT).mConnection) + if (GetInputPort(INPUTPORT_ROTATE_AMOUNT).m_connection) { OutputIncomingNode(animGraphInstance, GetInputNode(INPUTPORT_ROTATE_AMOUNT)); @@ -188,15 +188,15 @@ namespace EMotionFX } const AZ::Quaternion targetRot = MCore::CreateFromAxisAndAngle(axis, MCore::Math::DegreesToRadians(360.0f * (inputAmount - 0.5f) * invertFactor)); - AZ::Quaternion deltaRot = MCore::LinearInterpolate(AZ::Quaternion::CreateIdentity(), targetRot, uniqueData->mDeltaTime * factor); + AZ::Quaternion deltaRot = MCore::LinearInterpolate(AZ::Quaternion::CreateIdentity(), targetRot, uniqueData->m_deltaTime * factor); deltaRot.Normalize(); - uniqueData->mAdditiveTransform.mRotation = uniqueData->mAdditiveTransform.mRotation * deltaRot; - outputTransform.mRotation = (inputTransform.mRotation * uniqueData->mAdditiveTransform.mRotation); - outputTransform.mRotation.Normalize(); + uniqueData->m_additiveTransform.m_rotation = uniqueData->m_additiveTransform.m_rotation * deltaRot; + outputTransform.m_rotation = (inputTransform.m_rotation * uniqueData->m_additiveTransform.m_rotation); + outputTransform.m_rotation.Normalize(); } // process the translation - if (GetInputPort(INPUTPORT_TRANSLATE_AMOUNT).mConnection) + if (GetInputPort(INPUTPORT_TRANSLATE_AMOUNT).m_connection) { OutputIncomingNode(animGraphInstance, GetInputNode(INPUTPORT_TRANSLATE_AMOUNT)); @@ -225,15 +225,15 @@ namespace EMotionFX } axis *= (inputAmount - 0.5f) * invertFactor; - uniqueData->mAdditiveTransform.mPosition += MCore::LinearInterpolate(AZ::Vector3::CreateZero(), axis, uniqueData->mDeltaTime * factor); - outputTransform.mPosition = inputTransform.mPosition + uniqueData->mAdditiveTransform.mPosition; + uniqueData->m_additiveTransform.m_position += MCore::LinearInterpolate(AZ::Vector3::CreateZero(), axis, uniqueData->m_deltaTime * factor); + outputTransform.m_position = inputTransform.m_position + uniqueData->m_additiveTransform.m_position; } // process the scale EMFX_SCALECODE ( - if (GetInputPort(INPUTPORT_SCALE_AMOUNT).mConnection) + if (GetInputPort(INPUTPORT_SCALE_AMOUNT).m_connection) { OutputIncomingNode(animGraphInstance, GetInputNode(INPUTPORT_SCALE_AMOUNT)); @@ -265,18 +265,18 @@ namespace EMotionFX } axis *= (inputAmount - 0.5f) * invertFactor; - uniqueData->mAdditiveTransform.mScale += MCore::LinearInterpolate(AZ::Vector3::CreateZero(), axis, uniqueData->mDeltaTime * factor); - outputTransform.mScale = inputTransform.mScale + uniqueData->mAdditiveTransform.mScale; + uniqueData->m_additiveTransform.m_scale += MCore::LinearInterpolate(AZ::Vector3::CreateZero(), axis, uniqueData->m_deltaTime * factor); + outputTransform.m_scale = inputTransform.m_scale + uniqueData->m_additiveTransform.m_scale; } ) // update the transformation of the node - outputPose->GetPose().SetLocalSpaceTransform(uniqueData->mNodeIndex, outputTransform); + outputPose->GetPose().SetLocalSpaceTransform(uniqueData->m_nodeIndex, outputTransform); // visualize it if (GetEMotionFX().GetIsInEditorMode() && GetCanVisualize(animGraphInstance)) { - animGraphInstance->GetActorInstance()->DrawSkeleton(outputPose->GetPose(), mVisualizeColor); + animGraphInstance->GetActorInstance()->DrawSkeleton(outputPose->GetPose(), m_visualizeColor); } } @@ -288,21 +288,21 @@ namespace EMotionFX // store the passed time UniqueData* uniqueData = static_cast(FindOrCreateUniqueNodeData(animGraphInstance)); - uniqueData->mDeltaTime = timePassedInSeconds; + uniqueData->m_deltaTime = timePassedInSeconds; } void BlendTreeAccumTransformNode::OnAxisChanged() { - if (!mAnimGraph) + if (!m_animGraph) { return; } - const size_t numInstances = mAnimGraph->GetNumAnimGraphInstances(); + const size_t numInstances = m_animGraph->GetNumAnimGraphInstances(); for (size_t i = 0; i < numInstances; ++i) { - AnimGraphInstance* animGraphInstance = mAnimGraph->GetAnimGraphInstance(i); + AnimGraphInstance* animGraphInstance = m_animGraph->GetAnimGraphInstance(i); UniqueData* uniqueData = static_cast(animGraphInstance->FindOrCreateUniqueNodeData(this)); if (!uniqueData) @@ -310,8 +310,8 @@ namespace EMotionFX continue; } - uniqueData->mAdditiveTransform.Identity(); - EMFX_SCALECODE(uniqueData->mAdditiveTransform.mScale.CreateZero();) + uniqueData->m_additiveTransform.Identity(); + EMFX_SCALECODE(uniqueData->m_additiveTransform.m_scale.CreateZero();) InvalidateUniqueData(animGraphInstance); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeAccumTransformNode.h b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeAccumTransformNode.h index d8ca76aaa8..8f8fc21a6e 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeAccumTransformNode.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeAccumTransformNode.h @@ -83,9 +83,9 @@ namespace EMotionFX void Update() override; public: - Transform mAdditiveTransform = Transform::CreateIdentity(); - size_t mNodeIndex = InvalidIndex; - float mDeltaTime = 0.0f; + Transform m_additiveTransform = Transform::CreateIdentity(); + size_t m_nodeIndex = InvalidIndex; + float m_deltaTime = 0.0f; }; BlendTreeAccumTransformNode(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlend2AdditiveNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlend2AdditiveNode.cpp index f16d2f6943..1f3f41bb15 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlend2AdditiveNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlend2AdditiveNode.cpp @@ -45,7 +45,7 @@ namespace EMotionFX void BlendTreeBlend2AdditiveNode::Update(AnimGraphInstance* animGraphInstance, float timePassedInSeconds) { - if (mDisabled) + if (m_disabled) { AnimGraphNodeData* uniqueData = FindOrCreateUniqueNodeData(animGraphInstance); uniqueData->Clear(); @@ -91,7 +91,7 @@ namespace EMotionFX void BlendTreeBlend2AdditiveNode::Output(AnimGraphInstance* animGraphInstance) { // If we disabled this blend node, simply output a bind pose. - if (mDisabled) + if (m_disabled) { RequestPoses(animGraphInstance); AnimGraphPose* outputPose = GetOutputPose(animGraphInstance, OUTPUTPORT_POSE)->GetValue(); @@ -109,7 +109,7 @@ namespace EMotionFX OutputIncomingNode(animGraphInstance, weightNode); } - const size_t numNodes = uniqueData->mMask.size(); + const size_t numNodes = uniqueData->m_mask.size(); if (numNodes == 0) { OutputNoFeathering(animGraphInstance); @@ -122,7 +122,7 @@ namespace EMotionFX if (GetEMotionFX().GetIsInEditorMode() && GetCanVisualize(animGraphInstance)) { AnimGraphPose* outPose = GetOutputPose(animGraphInstance, OUTPUTPORT_POSE)->GetValue(); - animGraphInstance->GetActorInstance()->DrawSkeleton(outPose->GetPose(), mVisualizeColor); + animGraphInstance->GetActorInstance()->DrawSkeleton(outPose->GetPose(), m_visualizeColor); } } @@ -207,14 +207,14 @@ namespace EMotionFX Pose& outputLocalPose = outputPose->GetPose(); // If we use a mask, overwrite those nodes. - const size_t numNodes = uniqueData->mMask.size(); + const size_t numNodes = uniqueData->m_mask.size(); if (numNodes > 0) { Transform transform; for (size_t n = 0; n < numNodes; ++n) { - const float finalWeight = blendWeight;// * uniqueData->mWeights[n]; - const size_t nodeIndex = uniqueData->mMask[n]; + const float finalWeight = blendWeight;// * uniqueData->m_weights[n]; + const size_t nodeIndex = uniqueData->m_mask[n]; transform = outputLocalPose.GetLocalSpaceTransform(nodeIndex); transform.ApplyAdditive(additivePose.GetLocalSpaceTransform(nodeIndex), finalWeight); outputLocalPose.SetLocalSpaceTransform(nodeIndex, transform); @@ -241,7 +241,7 @@ namespace EMotionFX Transform delta = Transform::CreateIdentityWithZeroScale(); Transform deltaMirrored = Transform::CreateIdentityWithZeroScale(); - const bool hasMotionExtractionNodeInMask = (uniqueData->mMask.size() == 0) || (uniqueData->mMask.size() > 0 && AZStd::find(uniqueData->mMask.begin(), uniqueData->mMask.end(), actor->GetMotionExtractionNodeIndex()) != uniqueData->mMask.end()); + const bool hasMotionExtractionNodeInMask = (uniqueData->m_mask.size() == 0) || (uniqueData->m_mask.size() > 0 && AZStd::find(uniqueData->m_mask.begin(), uniqueData->m_mask.end(), actor->GetMotionExtractionNodeIndex()) != uniqueData->m_mask.end()); if (!hasMotionExtractionNodeInMask || !nodeBData || m_extractionMode == EXTRACTIONMODE_SOURCEONLY) { delta = nodeAData->GetTrajectoryDelta(); @@ -278,13 +278,13 @@ namespace EMotionFX void BlendTreeBlend2AdditiveNode::TopDownUpdate(AnimGraphInstance* animGraphInstance, float timePassedInSeconds) { - if (mDisabled) + if (m_disabled) { return; } UniqueData* uniqueData = static_cast(animGraphInstance->FindOrCreateUniqueObjectData(this)); - const BlendTreeConnection* con = GetInputPort(INPUTPORT_WEIGHT).mConnection; + const BlendTreeConnection* con = GetInputPort(INPUTPORT_WEIGHT).m_connection; if (con) { AnimGraphNodeData* sourceNodeUniqueData = con->GetSourceNode()->FindOrCreateUniqueNodeData(animGraphInstance); @@ -318,7 +318,7 @@ namespace EMotionFX // If we want to sync the motions. if (m_syncMode != SYNCMODE_DISABLED) { - const bool resync = (uniqueData->mSyncTrackNode != nodeA); + const bool resync = (uniqueData->m_syncTrackNode != nodeA); if (resync) { nodeA->RecursiveSetUniqueDataFlag(animGraphInstance, AnimGraphInstance::OBJECTFLAGS_RESYNC, true); @@ -327,7 +327,7 @@ namespace EMotionFX nodeB->RecursiveSetUniqueDataFlag(animGraphInstance, AnimGraphInstance::OBJECTFLAGS_RESYNC, true); } - uniqueData->mSyncTrackNode = nodeA; + uniqueData->m_syncTrackNode = nodeA; } // Sync the leader to this node. @@ -336,13 +336,13 @@ namespace EMotionFX // Sync the motion's to the leader. for (uint32 i = 0; i < 2; ++i) { - BlendTreeConnection* connection = mInputPorts[INPUTPORT_POSE_A + i].mConnection; + BlendTreeConnection* connection = m_inputPorts[INPUTPORT_POSE_A + i].m_connection; if (!connection) { continue; } - if (animGraphInstance->GetIsObjectFlagEnabled(mObjectIndex, AnimGraphInstance::OBJECTFLAGS_SYNCED) == false) + if (animGraphInstance->GetIsObjectFlagEnabled(m_objectIndex, AnimGraphInstance::OBJECTFLAGS_SYNCED) == false) { connection->GetSourceNode()->RecursiveSetUniqueDataFlag(animGraphInstance, AnimGraphInstance::OBJECTFLAGS_SYNCED, true); } @@ -389,7 +389,7 @@ namespace EMotionFX // post sync update void BlendTreeBlend2AdditiveNode::PostUpdate(AnimGraphInstance* animGraphInstance, float timePassedInSeconds) { - if (mDisabled) + if (m_disabled) { RequestRefDatas(animGraphInstance); UniqueData* uniqueData = static_cast(FindOrCreateUniqueNodeData(animGraphInstance)); @@ -399,7 +399,7 @@ namespace EMotionFX return; } - const BlendTreeConnection* con = GetInputPort(INPUTPORT_WEIGHT).mConnection; + const BlendTreeConnection* con = GetInputPort(INPUTPORT_WEIGHT).m_connection; if (con) { con->GetSourceNode()->PerformPostUpdate(animGraphInstance, timePassedInSeconds); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlend2LegacyNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlend2LegacyNode.cpp index 78fbd91dd1..8e52ea6bef 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlend2LegacyNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlend2LegacyNode.cpp @@ -46,7 +46,7 @@ namespace EMotionFX void BlendTreeBlend2LegacyNode::Update(AnimGraphInstance* animGraphInstance, float timePassedInSeconds) { - if (mDisabled) + if (m_disabled) { AnimGraphNodeData* uniqueData = FindOrCreateUniqueNodeData(animGraphInstance); uniqueData->Clear(); @@ -95,7 +95,7 @@ namespace EMotionFX void BlendTreeBlend2LegacyNode::Output(AnimGraphInstance* animGraphInstance) { - if (mDisabled) + if (m_disabled) { RequestPoses(animGraphInstance); AnimGraphPose* outputPose = GetOutputPose(animGraphInstance, OUTPUTPORT_POSE)->GetValue(); @@ -112,7 +112,7 @@ namespace EMotionFX OutputIncomingNode(animGraphInstance, weightNode); } - const size_t numNodes = uniqueData->mMask.size(); + const size_t numNodes = uniqueData->m_mask.size(); if (numNodes == 0) { OutputNoFeathering(animGraphInstance); @@ -125,7 +125,7 @@ namespace EMotionFX if (GetEMotionFX().GetIsInEditorMode() && GetCanVisualize(animGraphInstance)) { AnimGraphPose* outputPose = GetOutputPose(animGraphInstance, OUTPUTPORT_POSE)->GetValue(); - animGraphInstance->GetActorInstance()->DrawSkeleton(outputPose->GetPose(), mVisualizeColor); + animGraphInstance->GetActorInstance()->DrawSkeleton(outputPose->GetPose(), m_visualizeColor); } } @@ -227,7 +227,7 @@ namespace EMotionFX *outputPose = *nodeA->GetMainOutputPose(animGraphInstance); Pose& outputLocalPose = outputPose->GetPose(); - const size_t numNodes = uniqueData->mMask.size(); + const size_t numNodes = uniqueData->m_mask.size(); if (numNodes > 0) { Transform transform = Transform::CreateIdentity(); @@ -236,8 +236,8 @@ namespace EMotionFX { for (size_t n = 0; n < numNodes; ++n) { - const float finalWeight = blendWeight /* * uniqueData->mWeights[n]*/; - const size_t nodeIndex = uniqueData->mMask[n]; + const float finalWeight = blendWeight /* * uniqueData->m_weights[n]*/; + const size_t nodeIndex = uniqueData->m_mask[n]; transform = outputLocalPose.GetLocalSpaceTransform(nodeIndex); transform.Blend(localMaskPose.GetLocalSpaceTransform(nodeIndex), finalWeight); outputLocalPose.SetLocalSpaceTransform(nodeIndex, transform); @@ -249,8 +249,8 @@ namespace EMotionFX const Pose* bindPose = actorInstance->GetTransformData()->GetBindPose(); for (size_t n = 0; n < numNodes; ++n) { - const float finalWeight = blendWeight /* * uniqueData->mWeights[n]*/; - const size_t nodeIndex = uniqueData->mMask[n]; + const float finalWeight = blendWeight /* * uniqueData->m_weights[n]*/; + const size_t nodeIndex = uniqueData->m_mask[n]; transform = outputLocalPose.GetLocalSpaceTransform(nodeIndex); transform.BlendAdditive(localMaskPose.GetLocalSpaceTransform(nodeIndex), bindPose->GetLocalSpaceTransform(nodeIndex), finalWeight); outputLocalPose.SetLocalSpaceTransform(nodeIndex, transform); @@ -272,7 +272,7 @@ namespace EMotionFX Transform delta = Transform::CreateIdentityWithZeroScale(); Transform deltaMirrored = Transform::CreateIdentityWithZeroScale(); - const bool hasMotionExtractionNodeInMask = (uniqueData->mMask.size() == 0) || (uniqueData->mMask.size() > 0 && AZStd::find(uniqueData->mMask.begin(), uniqueData->mMask.end(), actor->GetMotionExtractionNodeIndex()) != uniqueData->mMask.end()); + const bool hasMotionExtractionNodeInMask = (uniqueData->m_mask.size() == 0) || (uniqueData->m_mask.size() > 0 && AZStd::find(uniqueData->m_mask.begin(), uniqueData->m_mask.end(), actor->GetMotionExtractionNodeIndex()) != uniqueData->m_mask.end()); if (!m_additiveBlending) { CalculateMotionExtractionDelta(m_extractionMode, nodeAData, nodeBData, weight, hasMotionExtractionNodeInMask, delta, deltaMirrored); @@ -291,13 +291,13 @@ namespace EMotionFX void BlendTreeBlend2LegacyNode::TopDownUpdate(AnimGraphInstance* animGraphInstance, float timePassedInSeconds) { - if (mDisabled) + if (m_disabled) { return; } UniqueData* uniqueData = static_cast(animGraphInstance->FindOrCreateUniqueObjectData(this)); - const BlendTreeConnection* con = GetInputPort(INPUTPORT_WEIGHT).mConnection; + const BlendTreeConnection* con = GetInputPort(INPUTPORT_WEIGHT).m_connection; if (con) { AnimGraphNodeData* sourceNodeUniqueData = con->GetSourceNode()->FindOrCreateUniqueNodeData(animGraphInstance); @@ -322,7 +322,7 @@ namespace EMotionFX if (m_syncMode != SYNCMODE_DISABLED) { - const bool resync = (uniqueData->mSyncTrackNode != nodeA); + const bool resync = (uniqueData->m_syncTrackNode != nodeA); if (resync) { nodeA->RecursiveSetUniqueDataFlag(animGraphInstance, AnimGraphInstance::OBJECTFLAGS_RESYNC, true); @@ -331,20 +331,20 @@ namespace EMotionFX nodeB->RecursiveSetUniqueDataFlag(animGraphInstance, AnimGraphInstance::OBJECTFLAGS_RESYNC, true); } - uniqueData->mSyncTrackNode = nodeA; + uniqueData->m_syncTrackNode = nodeA; } nodeA->AutoSync(animGraphInstance, this, 0.0f, SYNCMODE_TRACKBASED, false); for (uint32 i = 0; i < 2; ++i) { - BlendTreeConnection* connection = mInputPorts[INPUTPORT_POSE_A + i].mConnection; + BlendTreeConnection* connection = m_inputPorts[INPUTPORT_POSE_A + i].m_connection; if (!connection) { continue; } - if (animGraphInstance->GetIsObjectFlagEnabled(mObjectIndex, AnimGraphInstance::OBJECTFLAGS_SYNCED) == false) + if (animGraphInstance->GetIsObjectFlagEnabled(m_objectIndex, AnimGraphInstance::OBJECTFLAGS_SYNCED) == false) { connection->GetSourceNode()->RecursiveSetUniqueDataFlag(animGraphInstance, AnimGraphInstance::OBJECTFLAGS_SYNCED, true); } @@ -412,7 +412,7 @@ namespace EMotionFX void BlendTreeBlend2LegacyNode::PostUpdate(AnimGraphInstance* animGraphInstance, float timePassedInSeconds) { - if (mDisabled) + if (m_disabled) { RequestRefDatas(animGraphInstance); UniqueData* uniqueData = static_cast(FindOrCreateUniqueNodeData(animGraphInstance)); @@ -422,7 +422,7 @@ namespace EMotionFX return; } - const BlendTreeConnection* con = GetInputPort(INPUTPORT_WEIGHT).mConnection; + const BlendTreeConnection* con = GetInputPort(INPUTPORT_WEIGHT).m_connection; if (con) { con->GetSourceNode()->PerformPostUpdate(animGraphInstance, timePassedInSeconds); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlend2Node.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlend2Node.cpp index dfa7be26f8..06223d4b14 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlend2Node.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlend2Node.cpp @@ -45,7 +45,7 @@ namespace EMotionFX void BlendTreeBlend2Node::Update(AnimGraphInstance* animGraphInstance, float timePassedInSeconds) { - if (mDisabled) + if (m_disabled) { AnimGraphNodeData* uniqueData = FindOrCreateUniqueNodeData(animGraphInstance); uniqueData->Clear(); @@ -91,7 +91,7 @@ namespace EMotionFX void BlendTreeBlend2Node::Output(AnimGraphInstance* animGraphInstance) { - if (mDisabled) + if (m_disabled) { RequestPoses(animGraphInstance); AnimGraphPose* outputPose = GetOutputPose(animGraphInstance, OUTPUTPORT_POSE)->GetValue(); @@ -108,7 +108,7 @@ namespace EMotionFX OutputIncomingNode(animGraphInstance, weightNode); } - const size_t numNodes = uniqueData->mMask.size(); + const size_t numNodes = uniqueData->m_mask.size(); if (numNodes == 0) { OutputNoFeathering(animGraphInstance); @@ -121,7 +121,7 @@ namespace EMotionFX if (GetEMotionFX().GetIsInEditorMode() && GetCanVisualize(animGraphInstance)) { AnimGraphPose* outputPose = GetOutputPose(animGraphInstance, OUTPUTPORT_POSE)->GetValue(); - animGraphInstance->GetActorInstance()->DrawSkeleton(outputPose->GetPose(), mVisualizeColor); + animGraphInstance->GetActorInstance()->DrawSkeleton(outputPose->GetPose(), m_visualizeColor); } } @@ -210,14 +210,14 @@ namespace EMotionFX *outputPose = *nodeA->GetMainOutputPose(animGraphInstance); Pose& outputLocalPose = outputPose->GetPose(); - const size_t numNodes = uniqueData->mMask.size(); + const size_t numNodes = uniqueData->m_mask.size(); if (numNodes > 0) { Transform transform; for (size_t n = 0; n < numNodes; ++n) { - const float finalWeight = blendWeight /* * uniqueData->mWeights[n]*/; - const size_t nodeIndex = uniqueData->mMask[n]; + const float finalWeight = blendWeight /* * uniqueData->m_weights[n]*/; + const size_t nodeIndex = uniqueData->m_mask[n]; transform = outputLocalPose.GetLocalSpaceTransform(nodeIndex); transform.Blend(localMaskPose.GetLocalSpaceTransform(nodeIndex), finalWeight); outputLocalPose.SetLocalSpaceTransform(nodeIndex, transform); @@ -244,7 +244,7 @@ namespace EMotionFX Transform delta = Transform::CreateIdentityWithZeroScale(); Transform deltaMirrored = Transform::CreateIdentityWithZeroScale(); - const bool hasMotionExtractionNodeInMask = (uniqueData->mMask.size() == 0) || (uniqueData->mMask.size() > 0 && AZStd::find(uniqueData->mMask.begin(), uniqueData->mMask.end(), actor->GetMotionExtractionNodeIndex()) != uniqueData->mMask.end()); + const bool hasMotionExtractionNodeInMask = (uniqueData->m_mask.size() == 0) || (uniqueData->m_mask.size() > 0 && AZStd::find(uniqueData->m_mask.begin(), uniqueData->m_mask.end(), actor->GetMotionExtractionNodeIndex()) != uniqueData->m_mask.end()); CalculateMotionExtractionDelta(m_extractionMode, nodeAData, nodeBData, weight, hasMotionExtractionNodeInMask, delta, deltaMirrored); data->SetTrajectoryDelta(delta); @@ -254,13 +254,13 @@ namespace EMotionFX void BlendTreeBlend2Node::TopDownUpdate(AnimGraphInstance* animGraphInstance, float timePassedInSeconds) { - if (mDisabled) + if (m_disabled) { return; } UniqueData* uniqueData = static_cast(animGraphInstance->FindOrCreateUniqueObjectData(this)); - const BlendTreeConnection* con = GetInputPort(INPUTPORT_WEIGHT).mConnection; + const BlendTreeConnection* con = GetInputPort(INPUTPORT_WEIGHT).m_connection; if (con) { AnimGraphNodeData* sourceNodeUniqueData = con->GetSourceNode()->FindOrCreateUniqueNodeData(animGraphInstance); @@ -287,7 +287,7 @@ namespace EMotionFX if (m_syncMode != SYNCMODE_DISABLED) { - const bool resync = (uniqueData->mSyncTrackNode != nodeA); + const bool resync = (uniqueData->m_syncTrackNode != nodeA); if (resync) { nodeA->RecursiveSetUniqueDataFlag(animGraphInstance, AnimGraphInstance::OBJECTFLAGS_RESYNC, true); @@ -296,20 +296,20 @@ namespace EMotionFX nodeB->RecursiveSetUniqueDataFlag(animGraphInstance, AnimGraphInstance::OBJECTFLAGS_RESYNC, true); } - uniqueData->mSyncTrackNode = nodeA; + uniqueData->m_syncTrackNode = nodeA; } nodeA->AutoSync(animGraphInstance, this, 0.0f, SYNCMODE_TRACKBASED, false); for (uint32 i = 0; i < 2; ++i) { - BlendTreeConnection* connection = mInputPorts[INPUTPORT_POSE_A + i].mConnection; + BlendTreeConnection* connection = m_inputPorts[INPUTPORT_POSE_A + i].m_connection; if (!connection) { continue; } - if (animGraphInstance->GetIsObjectFlagEnabled(mObjectIndex, AnimGraphInstance::OBJECTFLAGS_SYNCED) == false) + if (animGraphInstance->GetIsObjectFlagEnabled(m_objectIndex, AnimGraphInstance::OBJECTFLAGS_SYNCED) == false) { connection->GetSourceNode()->RecursiveSetUniqueDataFlag(animGraphInstance, AnimGraphInstance::OBJECTFLAGS_SYNCED, true); } @@ -360,7 +360,7 @@ namespace EMotionFX void BlendTreeBlend2Node::PostUpdate(AnimGraphInstance* animGraphInstance, float timePassedInSeconds) { - if (mDisabled) + if (m_disabled) { RequestRefDatas(animGraphInstance); UniqueData* uniqueData = static_cast(FindOrCreateUniqueNodeData(animGraphInstance)); @@ -370,7 +370,7 @@ namespace EMotionFX return; } - const BlendTreeConnection* con = GetInputPort(INPUTPORT_WEIGHT).mConnection; + const BlendTreeConnection* con = GetInputPort(INPUTPORT_WEIGHT).m_connection; if (con) { con->GetSourceNode()->PerformPostUpdate(animGraphInstance, timePassedInSeconds); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlend2NodeBase.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlend2NodeBase.cpp index 2876605b0a..fd399085a0 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlend2NodeBase.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlend2NodeBase.cpp @@ -21,23 +21,23 @@ namespace EMotionFX BlendTreeBlend2NodeBase::UniqueData::UniqueData(AnimGraphNode* node, AnimGraphInstance* animGraphInstance) : AnimGraphNodeData(node, animGraphInstance) - , mSyncTrackNode(nullptr) + , m_syncTrackNode(nullptr) { } void BlendTreeBlend2NodeBase::UniqueData::Update() { - BlendTreeBlend2NodeBase* blend2Node = azdynamic_cast(mObject); + BlendTreeBlend2NodeBase* blend2Node = azdynamic_cast(m_object); AZ_Assert(blend2Node, "Unique data linked to incorrect node type."); - mMask.clear(); + m_mask.clear(); - Actor* actor = mAnimGraphInstance->GetActorInstance()->GetActor(); + Actor* actor = m_animGraphInstance->GetActorInstance()->GetActor(); const AZStd::vector& weightedNodeMask = blend2Node->GetWeightedNodeMask(); if (!weightedNodeMask.empty()) { const size_t numNodes = weightedNodeMask.size(); - mMask.reserve(numNodes); + m_mask.reserve(numNodes); // Try to find the node indices by name for all masked nodes. const Skeleton* skeleton = actor->GetSkeleton(); @@ -46,7 +46,7 @@ namespace EMotionFX Node* node = skeleton->FindNodeByName(weightedNode.first.c_str()); if (node) { - mMask.emplace_back(node->GetNodeIndex()); + m_mask.emplace_back(node->GetNodeIndex()); } } } @@ -100,8 +100,8 @@ namespace EMotionFX void BlendTreeBlend2NodeBase::FindBlendNodes(AnimGraphInstance* animGraphInstance, AnimGraphNode** outBlendNodeA, AnimGraphNode** outBlendNodeB, float* outWeight, bool isAdditive, bool optimizeByWeight) { - BlendTreeConnection* connectionA = mInputPorts[INPUTPORT_POSE_A].mConnection; - BlendTreeConnection* connectionB = mInputPorts[INPUTPORT_POSE_B].mConnection; + BlendTreeConnection* connectionA = m_inputPorts[INPUTPORT_POSE_A].m_connection; + BlendTreeConnection* connectionB = m_inputPorts[INPUTPORT_POSE_B].m_connection; if (!connectionA && !connectionB) { *outBlendNodeA = nullptr; @@ -112,11 +112,11 @@ namespace EMotionFX if (connectionA && connectionB) { - *outWeight = (mInputPorts[INPUTPORT_WEIGHT].mConnection) ? GetInputNumberAsFloat(animGraphInstance, INPUTPORT_WEIGHT) : 0.0f; + *outWeight = (m_inputPorts[INPUTPORT_WEIGHT].m_connection) ? GetInputNumberAsFloat(animGraphInstance, INPUTPORT_WEIGHT) : 0.0f; *outWeight = MCore::Clamp(*outWeight, 0.0f, 1.0f); UniqueData* uniqueData = static_cast(animGraphInstance->FindOrCreateUniqueObjectData(this)); - if (!uniqueData->mMask.empty()) + if (!uniqueData->m_mask.empty()) { *outBlendNodeA = connectionA->GetSourceNode(); *outBlendNodeB = connectionB->GetSourceNode(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlend2NodeBase.h b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlend2NodeBase.h index 217e2a2e23..9a9b51b5d1 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlend2NodeBase.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlend2NodeBase.h @@ -54,8 +54,8 @@ namespace EMotionFX void Update() override; public: - AZStd::vector mMask; - AnimGraphNode* mSyncTrackNode; + AZStd::vector m_mask; + AnimGraphNode* m_syncTrackNode; }; BlendTreeBlend2NodeBase(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlendNNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlendNNode.cpp index 147e5c0aa9..7720822655 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlendNNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlendNNode.cpp @@ -31,7 +31,7 @@ namespace EMotionFX void BlendTreeBlendNNode::UniqueData::Update() { - BlendTreeBlendNNode* blendNNode = azdynamic_cast(mObject); + BlendTreeBlendNNode* blendNNode = azdynamic_cast(m_object); AZ_Assert(blendNNode, "Unique data linked to incorrect node type."); blendNNode->UpdateParamWeightRanges(); @@ -136,11 +136,11 @@ namespace EMotionFX { float weightRange = 0.0f; const float defaultWeightStep = 1.0f; - for (const AnimGraphNode::Port& port : mInputPorts) + for (const AnimGraphNode::Port& port : m_inputPorts) { - if (port.mConnection && port.mPortID != PORTID_INPUT_WEIGHT) + if (port.m_connection && port.m_portId != PORTID_INPUT_WEIGHT) { - m_paramWeights.emplace_back(port.mPortID, weightRange); + m_paramWeights.emplace_back(port.m_portId, weightRange); weightRange += defaultWeightStep; } } @@ -172,9 +172,9 @@ namespace EMotionFX } float weight = m_paramWeights.front().m_weightRange; - if (!mDisabled) + if (!m_disabled) { - if (mInputPorts[INPUTPORT_WEIGHT].mConnection) + if (m_inputPorts[INPUTPORT_WEIGHT].m_connection) { weight = GetInputNumberAsFloat(animGraphInstance, INPUTPORT_WEIGHT); } @@ -191,8 +191,8 @@ namespace EMotionFX *outWeight = 0.0f; // Calculate the blend weight and get the nodes - *outNodeA = GetInputPort(INPUTPORT_POSE_0 + poseIndexA).mConnection->GetSourceNode(); - *outNodeB = GetInputPort(INPUTPORT_POSE_0 + poseIndexB).mConnection->GetSourceNode(); + *outNodeA = GetInputPort(INPUTPORT_POSE_0 + poseIndexA).m_connection->GetSourceNode(); + *outNodeB = GetInputPort(INPUTPORT_POSE_0 + poseIndexB).m_connection->GetSourceNode(); *outIndexA = poseIndexA; *outIndexB = poseIndexB; @@ -227,8 +227,8 @@ namespace EMotionFX // Search complete: the input weight is between m_paramWeights[i] and m_paramWeights[i - 1] // Calculate the blend weight and get the nodes and then return - *outNodeA = GetInputPort(INPUTPORT_POSE_0 + poseIndexA).mConnection->GetSourceNode(); - *outNodeB = GetInputPort(INPUTPORT_POSE_0 + poseIndexB).mConnection->GetSourceNode(); + *outNodeA = GetInputPort(INPUTPORT_POSE_0 + poseIndexA).m_connection->GetSourceNode(); + *outNodeB = GetInputPort(INPUTPORT_POSE_0 + poseIndexB).m_connection->GetSourceNode(); *outIndexA = poseIndexA; *outIndexB = poseIndexB; @@ -242,8 +242,8 @@ namespace EMotionFX *outWeight = 0.0f; // Calculate the blend weight and get the nodes - *outNodeA = GetInputPort(INPUTPORT_POSE_0 + poseIndexA).mConnection->GetSourceNode(); - *outNodeB = GetInputPort(INPUTPORT_POSE_0 + poseIndexB).mConnection->GetSourceNode(); + *outNodeA = GetInputPort(INPUTPORT_POSE_0 + poseIndexA).m_connection->GetSourceNode(); + *outNodeB = GetInputPort(INPUTPORT_POSE_0 + poseIndexB).m_connection->GetSourceNode(); *outIndexA = poseIndexA; *outIndexB = poseIndexB; } @@ -259,7 +259,7 @@ namespace EMotionFX // check if we need to resync, this indicates the two motions we blend between changed bool resync = false; - if (uniqueData->mIndexA != poseIndexA || uniqueData->mIndexB != poseIndexB) + if (uniqueData->m_indexA != poseIndexA || uniqueData->m_indexB != poseIndexB) { resync = true; nodeA->RecursiveSetUniqueDataFlag(animGraphInstance, AnimGraphInstance::OBJECTFLAGS_RESYNC, true); @@ -272,14 +272,14 @@ namespace EMotionFX for (uint32 i = 0; i < 10; ++i) { // check if this port is used - BlendTreeConnection* connection = mInputPorts[i].mConnection; + BlendTreeConnection* connection = m_inputPorts[i].m_connection; if (connection == nullptr) { continue; } // mark this node recursively as synced - if (animGraphInstance->GetIsObjectFlagEnabled(mObjectIndex, AnimGraphInstance::OBJECTFLAGS_SYNCED) == false) + if (animGraphInstance->GetIsObjectFlagEnabled(m_objectIndex, AnimGraphInstance::OBJECTFLAGS_SYNCED) == false) { connection->GetSourceNode()->RecursiveSetUniqueDataFlag(animGraphInstance, AnimGraphInstance::OBJECTFLAGS_SYNCED, true); } @@ -307,8 +307,8 @@ namespace EMotionFX } } - uniqueData->mIndexA = poseIndexA; - uniqueData->mIndexB = poseIndexB; + uniqueData->m_indexA = poseIndexA; + uniqueData->m_indexB = poseIndexB; } // perform the calculations / actions @@ -320,7 +320,7 @@ namespace EMotionFX AnimGraphPose* outputPose; // if there are no connections, there is nothing to do - if (mDisabled || !HasRequiredInputs()) + if (m_disabled || !HasRequiredInputs()) { RequestPoses(animGraphInstance); outputPose = GetOutputPose(animGraphInstance, OUTPUTPORT_POSE)->GetValue(); @@ -331,13 +331,13 @@ namespace EMotionFX // visualize it if (GetEMotionFX().GetIsInEditorMode() && GetCanVisualize(animGraphInstance)) { - actorInstance->DrawSkeleton(outputPose->GetPose(), mVisualizeColor); + actorInstance->DrawSkeleton(outputPose->GetPose(), m_visualizeColor); } return; } // output the input weight node - BlendTreeConnection* connection = mInputPorts[INPUTPORT_WEIGHT].mConnection; + BlendTreeConnection* connection = m_inputPorts[INPUTPORT_WEIGHT].m_connection; if (connection) { OutputIncomingNode(animGraphInstance, connection->GetSourceNode()); @@ -361,7 +361,7 @@ namespace EMotionFX // visualize it if (GetEMotionFX().GetIsInEditorMode() && GetCanVisualize(animGraphInstance)) { - actorInstance->DrawSkeleton(outputPose->GetPose(), mVisualizeColor); + actorInstance->DrawSkeleton(outputPose->GetPose(), m_visualizeColor); } return; } @@ -377,7 +377,7 @@ namespace EMotionFX *outputPose = *poseA; if (GetEMotionFX().GetIsInEditorMode() && GetCanVisualize(animGraphInstance)) { - actorInstance->DrawSkeleton(outputPose->GetPose(), mVisualizeColor); + actorInstance->DrawSkeleton(outputPose->GetPose(), m_visualizeColor); } return; } @@ -394,7 +394,7 @@ namespace EMotionFX // visualize it if (GetEMotionFX().GetIsInEditorMode() && GetCanVisualize(animGraphInstance)) { - actorInstance->DrawSkeleton(outputPose->GetPose(), mVisualizeColor); + actorInstance->DrawSkeleton(outputPose->GetPose(), m_visualizeColor); } return; } @@ -408,31 +408,31 @@ namespace EMotionFX // visualize it if (GetEMotionFX().GetIsInEditorMode() && GetCanVisualize(animGraphInstance)) { - actorInstance->DrawSkeleton(outputPose->GetPose(), mVisualizeColor); + actorInstance->DrawSkeleton(outputPose->GetPose(), m_visualizeColor); } } bool BlendTreeBlendNNode::HasRequiredInputs() const { - if (mConnections.empty()) + if (m_connections.empty()) { return false; } // If we have only one input connection and it is our weight input, that means we have no input poses. - return !(mConnections.size() == 1 && mInputPorts[INPUTPORT_WEIGHT].mConnection); + return !(m_connections.size() == 1 && m_inputPorts[INPUTPORT_WEIGHT].m_connection); } void BlendTreeBlendNNode::Update(AnimGraphInstance* animGraphInstance, float timePassedInSeconds) { - if (mDisabled || !HasRequiredInputs()) + if (m_disabled || !HasRequiredInputs()) { UniqueData* uniqueData = static_cast(FindOrCreateUniqueNodeData(animGraphInstance)); uniqueData->Clear(); return; } - const BlendTreeConnection* weightConnection = mInputPorts[INPUTPORT_WEIGHT].mConnection; + const BlendTreeConnection* weightConnection = m_inputPorts[INPUTPORT_WEIGHT].m_connection; if (weightConnection) { UpdateIncomingNode(animGraphInstance, weightConnection->GetSourceNode(), timePassedInSeconds); @@ -475,14 +475,14 @@ namespace EMotionFX void BlendTreeBlendNNode::TopDownUpdate(AnimGraphInstance* animGraphInstance, float timePassedInSeconds) { // if the node is disabled - if (mDisabled || !HasRequiredInputs()) + if (m_disabled || !HasRequiredInputs()) { return; } // top down update the weight input UniqueData* uniqueData = static_cast(FindOrCreateUniqueNodeData(animGraphInstance)); - const BlendTreeConnection* con = GetInputPort(INPUTPORT_WEIGHT).mConnection; + const BlendTreeConnection* con = GetInputPort(INPUTPORT_WEIGHT).m_connection; if (con) { con->GetSourceNode()->FindOrCreateUniqueNodeData(animGraphInstance)->SetGlobalWeight(uniqueData->GetGlobalWeight()); @@ -565,7 +565,7 @@ namespace EMotionFX void BlendTreeBlendNNode::PostUpdate(AnimGraphInstance* animGraphInstance, float timePassedInSeconds) { // if we don't have enough inputs or are disabled, we don't need to update anything - if (mDisabled || !HasRequiredInputs()) + if (m_disabled || !HasRequiredInputs()) { // request the reference counted data inside the unique data RequestRefDatas(animGraphInstance); @@ -577,7 +577,7 @@ namespace EMotionFX } // get the input weight - BlendTreeConnection* connection = mInputPorts[INPUTPORT_WEIGHT].mConnection; + BlendTreeConnection* connection = m_inputPorts[INPUTPORT_WEIGHT].m_connection; if (connection) { connection->GetSourceNode()->PerformPostUpdate(animGraphInstance, timePassedInSeconds); @@ -732,21 +732,21 @@ namespace EMotionFX float* lastNonDefaultValue = nullptr; for (const AnimGraphNode::Port& port : inputPorts) { - if (port.mConnection && port.mPortID != PORTID_INPUT_WEIGHT) + if (port.m_connection && port.m_portId != PORTID_INPUT_WEIGHT) { const float defaultRangeValue = m_paramWeights.empty() ? 0.0f : m_paramWeights.back().GetWeightRange(); - auto portToWeightRangeIterator = portToWeightRangeTable.find(port.mPortID); + auto portToWeightRangeIterator = portToWeightRangeTable.find(port.m_portId); if (portToWeightRangeIterator == portToWeightRangeTable.end()) { // New connection just plugged - m_paramWeights.emplace_back(port.mPortID, defaultRangeValue); + m_paramWeights.emplace_back(port.m_portId, defaultRangeValue); defaultElementsCount++; } else { // Existing connection, using existing weight range - m_paramWeights.emplace_back(port.mPortID, portToWeightRangeIterator->second); + m_paramWeights.emplace_back(port.m_portId, portToWeightRangeIterator->second); // We want to fill the previous default values with uniformly distributed // Weight ranges, if possible: diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlendNNode.h b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlendNNode.h index 22b78db313..72d6ad120c 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlendNNode.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlendNNode.h @@ -94,8 +94,8 @@ namespace EMotionFX void Update() override; public: - uint32 mIndexA = InvalidIndex32; - uint32 mIndexB = InvalidIndex32; + uint32 m_indexA = InvalidIndex32; + uint32 m_indexB = InvalidIndex32; }; BlendTreeBlendNNode(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBoolLogicNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBoolLogicNode.cpp index 70cd7092f8..fc85790518 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBoolLogicNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBoolLogicNode.cpp @@ -33,7 +33,7 @@ namespace EMotionFX SetupOutputPort("Float", OUTPUTPORT_VALUE, MCore::AttributeFloat::TYPE_ID, PORTID_OUTPUT_VALUE); SetupOutputPort("Bool", OUTPUTPORT_BOOL, MCore::AttributeFloat::TYPE_ID, PORTID_OUTPUT_BOOL); - if (mAnimGraph) + if (m_animGraph) { Reinit(); } @@ -121,7 +121,7 @@ namespace EMotionFX void BlendTreeBoolLogicNode::Update(AnimGraphInstance* animGraphInstance, float timePassedInSeconds) { // if there are no incoming connections, there is nothing to do - if (mConnections.empty()) + if (m_connections.empty()) { return; } @@ -131,7 +131,7 @@ namespace EMotionFX // if both x and y inputs have connections bool x, y; - if (mConnections.size() == 2) + if (m_connections.size() == 2) { OutputIncomingNode(animGraphInstance, GetInputNode(INPUTPORT_X)); OutputIncomingNode(animGraphInstance, GetInputNode(INPUTPORT_Y)); @@ -142,7 +142,7 @@ namespace EMotionFX else // only x or y is connected { // if only x has something plugged in - if (mConnections[0]->GetTargetPort() == INPUTPORT_X) + if (m_connections[0]->GetTargetPort() == INPUTPORT_X) { OutputIncomingNode(animGraphInstance, GetInputNode(INPUTPORT_X)); x = GetInputNumberAsBool(animGraphInstance, INPUTPORT_X); @@ -150,7 +150,7 @@ namespace EMotionFX } else // only y has an input { - MCORE_ASSERT(mConnections[0]->GetTargetPort() == INPUTPORT_Y); + MCORE_ASSERT(m_connections[0]->GetTargetPort() == INPUTPORT_Y); OutputIncomingNode(animGraphInstance, GetInputNode(INPUTPORT_Y)); x = m_defaultValue; y = GetInputNumberAsBool(animGraphInstance, INPUTPORT_Y); @@ -174,7 +174,7 @@ namespace EMotionFX void BlendTreeBoolLogicNode::SetFunction(EFunction func) { m_functionEnum = func; - if (mAnimGraph) + if (m_animGraph) { Reinit(); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeConnection.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeConnection.cpp index 7bbbd5ade8..084396f201 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeConnection.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeConnection.cpp @@ -20,9 +20,9 @@ namespace EMotionFX : m_animGraph(nullptr) , m_sourceNode(nullptr) , m_id(AnimGraphConnectionId::Create()) - , mSourcePort(MCORE_INVALIDINDEX16) - , mTargetPort(MCORE_INVALIDINDEX16) - , mVisited(false) + , m_sourcePort(MCORE_INVALIDINDEX16) + , m_targetPort(MCORE_INVALIDINDEX16) + , m_visited(false) { } @@ -34,8 +34,8 @@ namespace EMotionFX m_animGraph = sourceNode->GetAnimGraph(); } - mSourcePort = sourcePort; - mTargetPort = targetPort; + m_sourcePort = sourcePort; + m_targetPort = targetPort; SetSourceNode(sourceNode); } @@ -80,7 +80,7 @@ namespace EMotionFX bool BlendTreeConnection::GetIsValid() const { // make sure the node and input numbers are valid - if (!m_sourceNode || mSourcePort == MCORE_INVALIDINDEX16 || mTargetPort == MCORE_INVALIDINDEX16) + if (!m_sourceNode || m_sourcePort == MCORE_INVALIDINDEX16 || m_targetPort == MCORE_INVALIDINDEX16) { return false; } @@ -101,7 +101,7 @@ namespace EMotionFX ->Version(2) ->Field("id", &BlendTreeConnection::m_id) ->Field("sourceNodeId", &BlendTreeConnection::m_sourceNodeId) - ->Field("sourcePortNr", &BlendTreeConnection::mSourcePort) - ->Field("targetPortNr", &BlendTreeConnection::mTargetPort); + ->Field("sourcePortNr", &BlendTreeConnection::m_sourcePort) + ->Field("targetPortNr", &BlendTreeConnection::m_targetPort); } } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeConnection.h b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeConnection.h index 437cf6de51..7750b7b998 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeConnection.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeConnection.h @@ -41,17 +41,17 @@ namespace EMotionFX AZ_FORCE_INLINE AnimGraphNode* GetSourceNode() const { return m_sourceNode; } AZ_FORCE_INLINE AnimGraphNodeId GetSourceNodeId() const { return m_sourceNodeId; } - MCORE_INLINE AZ::u16 GetSourcePort() const { return mSourcePort; } - MCORE_INLINE AZ::u16 GetTargetPort() const { return mTargetPort; } + MCORE_INLINE AZ::u16 GetSourcePort() const { return m_sourcePort; } + MCORE_INLINE AZ::u16 GetTargetPort() const { return m_targetPort; } - MCORE_INLINE void SetSourcePort(AZ::u16 sourcePort) { mSourcePort = sourcePort; } - MCORE_INLINE void SetTargetPort(AZ::u16 targetPort) { mTargetPort = targetPort; } + MCORE_INLINE void SetSourcePort(AZ::u16 sourcePort) { m_sourcePort = sourcePort; } + MCORE_INLINE void SetTargetPort(AZ::u16 targetPort) { m_targetPort = targetPort; } AnimGraphConnectionId GetId() const { return m_id; } void SetId(AnimGraphConnectionId id) { m_id = id; } - MCORE_INLINE void SetIsVisited(bool visited) { mVisited = visited; } - MCORE_INLINE bool GetIsVisited() const { return mVisited; } + MCORE_INLINE void SetIsVisited(bool visited) { m_visited = visited; } + MCORE_INLINE bool GetIsVisited() const { return m_visited; } AnimGraph* GetAnimGraph() const { return m_animGraph; } @@ -62,8 +62,8 @@ namespace EMotionFX AnimGraphNode* m_sourceNode; /**< The source node from which the incoming connection comes. */ AZ::u64 m_sourceNodeId; AZ::u64 m_id; - AZ::u16 mSourcePort; /**< The source port number, so the output port number of the node where the connection comes from. */ - AZ::u16 mTargetPort; /**< The target port number, which is the input port number of the target node. */ - bool mVisited; /**< True when during updates this connection was used. */ + AZ::u16 m_sourcePort; /**< The source port number, so the output port number of the node where the connection comes from. */ + AZ::u16 m_targetPort; /**< The target port number, which is the input port number of the target node. */ + bool m_visited; /**< True when during updates this connection was used. */ }; } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeDirectionToWeightNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeDirectionToWeightNode.cpp index c87cc32e67..8167addf44 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeDirectionToWeightNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeDirectionToWeightNode.cpp @@ -73,8 +73,8 @@ namespace EMotionFX UpdateAllIncomingNodes(animGraphInstance, timePassedInSeconds); // if there are less than two incoming connections, there is nothing to do - const size_t numConnections = mConnections.size(); - if (numConnections < 2 || mDisabled) + const size_t numConnections = m_connections.size(); + if (numConnections < 2 || m_disabled) { GetOutputFloat(animGraphInstance, OUTPUTPORT_WEIGHT)->SetValue(0.0f); return; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeFinalNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeFinalNode.cpp index c69a778f7e..85418a81b8 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeFinalNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeFinalNode.cpp @@ -71,7 +71,7 @@ namespace EMotionFX AnimGraphPose* outputPose; // if there is no input, just output a bind pose - if (mConnections.empty()) + if (m_connections.empty()) { RequestPoses(animGraphInstance); outputPose = GetOutputPose(animGraphInstance, OUTPUTPORT_RESULT)->GetValue(); @@ -80,7 +80,7 @@ namespace EMotionFX } // output the source node - AnimGraphNode* sourceNode = mConnections[0]->GetSourceNode(); + AnimGraphNode* sourceNode = m_connections[0]->GetSourceNode(); OutputIncomingNode(animGraphInstance, sourceNode); RequestPoses(animGraphInstance); @@ -93,7 +93,7 @@ namespace EMotionFX void BlendTreeFinalNode::Update(AnimGraphInstance* animGraphInstance, float timePassedInSeconds) { // if there are no connections, output nothing - if (mConnections.empty()) + if (m_connections.empty()) { AnimGraphNodeData* uniqueData = FindOrCreateUniqueNodeData(animGraphInstance); uniqueData->Clear(); @@ -101,7 +101,7 @@ namespace EMotionFX } // update the source node - AnimGraphNode* sourceNode = mConnections[0]->GetSourceNode(); + AnimGraphNode* sourceNode = m_connections[0]->GetSourceNode(); UpdateIncomingNode(animGraphInstance, sourceNode, timePassedInSeconds); // update the sync track diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeFloatConditionNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeFloatConditionNode.cpp index 41c688f36a..b93659661d 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeFloatConditionNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeFloatConditionNode.cpp @@ -36,7 +36,7 @@ namespace EMotionFX SetupOutputPort("Bool", OUTPUTPORT_BOOL, MCore::AttributeFloat::TYPE_ID, PORTID_OUTPUT_BOOL); // false on default - if (mAnimGraph) + if (m_animGraph) { Reinit(); } @@ -119,7 +119,7 @@ namespace EMotionFX UpdateAllIncomingNodes(animGraphInstance, timePassedInSeconds); // if there are no incoming connections, there is nothing to do - const size_t numConnections = mConnections.size(); + const size_t numConnections = m_connections.size(); if (numConnections == 0) { return; @@ -138,7 +138,7 @@ namespace EMotionFX else // only x or y is connected { // if only x has something plugged in - if (mConnections[0]->GetTargetPort() == INPUTPORT_X) + if (m_connections[0]->GetTargetPort() == INPUTPORT_X) { OutputIncomingNode(animGraphInstance, GetInputNode(INPUTPORT_X)); x = GetInputNumberAsFloat(animGraphInstance, INPUTPORT_X); @@ -146,7 +146,7 @@ namespace EMotionFX } else // only y has an input { - MCORE_ASSERT(mConnections[0]->GetTargetPort() == INPUTPORT_Y); + MCORE_ASSERT(m_connections[0]->GetTargetPort() == INPUTPORT_Y); x = m_defaultValue; OutputIncomingNode(animGraphInstance, GetInputNode(INPUTPORT_Y)); y = GetInputNumberAsFloat(animGraphInstance, INPUTPORT_Y); @@ -198,7 +198,7 @@ namespace EMotionFX void BlendTreeFloatConditionNode::SetFunction(EFunction func) { m_functionEnum = func; - if (mAnimGraph) + if (m_animGraph) { Reinit(); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeFloatMath1Node.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeFloatMath1Node.cpp index 55924d8fd0..c70a1b69a6 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeFloatMath1Node.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeFloatMath1Node.cpp @@ -29,7 +29,7 @@ namespace EMotionFX InitOutputPorts(1); SetupOutputPort("Result", OUTPUTPORT_RESULT, MCore::AttributeFloat::TYPE_ID, PORTID_OUTPUT_RESULT); - if (mAnimGraph) + if (m_animGraph) { Reinit(); } @@ -192,12 +192,12 @@ namespace EMotionFX UpdateAllIncomingNodes(animGraphInstance, timePassedInSeconds); // If there are no incoming connections, there is nothing to do. - if (mConnections.empty()) + if (m_connections.empty()) { return; } // Pass the input value as output in case we are disabled and have connected inputs. - else if (mDisabled) + else if (m_disabled) { OutputIncomingNode(animGraphInstance, GetInputNode(INPUTPORT_X)); GetOutputFloat(animGraphInstance, OUTPUTPORT_RESULT)->SetValue(GetInputNumberAsFloat(animGraphInstance, INPUTPORT_X)); @@ -219,7 +219,7 @@ namespace EMotionFX void BlendTreeFloatMath1Node::SetMathFunction(EMathFunction func) { m_mathFunction = func; - if (mAnimGraph) + if (m_animGraph) { Reinit(); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeFloatMath2Node.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeFloatMath2Node.cpp index 30a056ee34..de63373bd0 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeFloatMath2Node.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeFloatMath2Node.cpp @@ -32,7 +32,7 @@ namespace EMotionFX InitOutputPorts(1); SetupOutputPort("Result", OUTPUTPORT_RESULT, MCore::AttributeFloat::TYPE_ID, PORTID_OUTPUT_RESULT); - if (mAnimGraph) + if (m_animGraph) { Reinit(); } @@ -131,14 +131,14 @@ namespace EMotionFX UpdateAllIncomingNodes(animGraphInstance, timePassedInSeconds); // if there are no incoming connections, there is nothing to do - if (mConnections.empty()) + if (m_connections.empty()) { return; } // if both x and y inputs have connections float x, y; - if (mConnections.size() == 2) + if (m_connections.size() == 2) { OutputIncomingNode(animGraphInstance, GetInputNode(INPUTPORT_X)); OutputIncomingNode(animGraphInstance, GetInputNode(INPUTPORT_Y)); @@ -149,7 +149,7 @@ namespace EMotionFX else // only x or y is connected { // if only x has something plugged in - if (mConnections[0]->GetTargetPort() == INPUTPORT_X) + if (m_connections[0]->GetTargetPort() == INPUTPORT_X) { OutputIncomingNode(animGraphInstance, GetInputNode(INPUTPORT_X)); x = GetInputNumberAsFloat(animGraphInstance, INPUTPORT_X); @@ -157,7 +157,7 @@ namespace EMotionFX } else // only y has an input { - MCORE_ASSERT(mConnections[0]->GetTargetPort() == INPUTPORT_Y); + MCORE_ASSERT(m_connections[0]->GetTargetPort() == INPUTPORT_Y); x = m_defaultValue; OutputIncomingNode(animGraphInstance, GetInputNode(INPUTPORT_Y)); y = GetInputNumberAsFloat(animGraphInstance, INPUTPORT_Y); @@ -178,7 +178,7 @@ namespace EMotionFX void BlendTreeFloatMath2Node::SetMathFunction(EMathFunction func) { m_mathFunction = func; - if (mAnimGraph) + if (m_animGraph) { Reinit(); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeFloatSwitchNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeFloatSwitchNode.cpp index 048cc48478..46fced6883 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeFloatSwitchNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeFloatSwitchNode.cpp @@ -81,7 +81,7 @@ namespace EMotionFX UpdateAllIncomingNodes(animGraphInstance, timePassedInSeconds); // if the decision port has no incomming connection, there is nothing we can do - if (mInputPorts[INPUTPORT_DECISION].mConnection == nullptr) + if (m_inputPorts[INPUTPORT_DECISION].m_connection == nullptr) { return; } @@ -91,7 +91,7 @@ namespace EMotionFX const int32 decisionValue = MCore::Clamp(GetInputNumberAsInt32(animGraphInstance, INPUTPORT_DECISION), 0, 4); // max 5 cases // return the value for that port - if (mInputPorts[INPUTPORT_0 + decisionValue].mConnection) + if (m_inputPorts[INPUTPORT_0 + decisionValue].m_connection) { //OutputIncomingNode( animGraphInstance, GetInputNode(INPUTPORT_0 + decisionValue) ); GetOutputFloat(animGraphInstance, OUTPUTPORT_RESULT)->SetValue(GetInputNumberAsFloat(animGraphInstance, INPUTPORT_0 + decisionValue)); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeFootIKNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeFootIKNode.cpp index 97d7d4baa0..d81b090300 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeFootIKNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeFootIKNode.cpp @@ -31,16 +31,16 @@ namespace EMotionFX void BlendTreeFootIKNode::UniqueData::Update() { - BlendTreeFootIKNode* footIKNode = azdynamic_cast(mObject); + BlendTreeFootIKNode* footIKNode = azdynamic_cast(m_object); AZ_Assert(footIKNode, "Unique data linked to incorrect node type."); - const ActorInstance* actorInstance = mAnimGraphInstance->GetActorInstance(); + const ActorInstance* actorInstance = m_animGraphInstance->GetActorInstance(); const Actor* actor = actorInstance->GetActor(); const Skeleton* skeleton = actor->GetSkeleton(); SetHasError(false); // Initialize the legs. - if (!footIKNode->InitLegs(mAnimGraphInstance, this)) + if (!footIKNode->InitLegs(m_animGraphInstance, this)) { SetHasError(true); } @@ -49,7 +49,7 @@ namespace EMotionFX const AZStd::string& hipJointName = footIKNode->GetHipJointName(); if ((hipJointName.empty() || !skeleton->FindNodeAndIndexByName(hipJointName, m_hipJointIndex)) && !GetEMotionFX().GetEnableServerOptimization()) { - footIKNode = azdynamic_cast(mObject); + footIKNode = azdynamic_cast(m_object); AZ_Error("EMotionFX", false, "Anim graph footplant IK node '%s' cannot find hip joint named '%s'", footIKNode->GetName(), hipJointName.c_str()); SetHasError(true); } @@ -102,7 +102,7 @@ namespace EMotionFX float BlendTreeFootIKNode::GetActorInstanceScale(const ActorInstance* actorInstance) const { #ifndef EMFX_SCALE_DISABLED - return actorInstance->GetWorldSpaceTransform().mScale.GetZ(); + return actorInstance->GetWorldSpaceTransform().m_scale.GetZ(); #else return 1.0f; #endif @@ -185,7 +185,7 @@ namespace EMotionFX AZ_Error("EMotionFX", false, "Anim graph footplant IK node '%s' cannot find foot joint named '%s'.", GetName(), footJointName.c_str()); return false; } - leg.m_footHeight = actorInstance->GetTransformData()->GetBindPose()->GetModelSpaceTransform(leg.m_jointIndices[LegJointId::Foot]).mPosition.GetZ(); + leg.m_footHeight = actorInstance->GetTransformData()->GetBindPose()->GetModelSpaceTransform(leg.m_jointIndices[LegJointId::Foot]).m_position.GetZ(); // Now grab the parent, assuming this is the knee. Node* knee = footJoint->GetParentNode(); @@ -214,7 +214,7 @@ namespace EMotionFX } leg.m_jointIndices[LegJointId::Toe] = toeJoint->GetNodeIndex(); - leg.m_toeHeight = actorInstance->GetTransformData()->GetBindPose()->GetModelSpaceTransform(leg.m_jointIndices[LegJointId::Toe]).mPosition.GetZ(); + leg.m_toeHeight = actorInstance->GetTransformData()->GetBindPose()->GetModelSpaceTransform(leg.m_jointIndices[LegJointId::Toe]).m_position.GetZ(); leg.m_weight = 0.0f; leg.m_targetWeight = 0.0f; leg.DisableFlag(LegFlags::FootDown); @@ -274,12 +274,12 @@ namespace EMotionFX AZ_Assert(jointIndex != InvalidIndex, "Expecting the joint index to be valid."); const float rayLength = GetRaycastLength(animGraphInstance); - const AZ::Vector3 upVector = animGraphInstance->GetActorInstance()->GetWorldSpaceTransform().mRotation + const AZ::Vector3 upVector = animGraphInstance->GetActorInstance()->GetWorldSpaceTransform().m_rotation .TransformVector(AZ::Vector3(0.0f, 0.0f, 1.0f)); - const AZ::Vector3 jointPositionModelSpace = inputPose.GetModelSpaceTransform(jointIndex).mPosition; - const AZ::Vector3 hipPositionModelSpace = inputPose.GetModelSpaceTransform(uniqueData->m_hipJointIndex).mPosition; - const AZ::Vector3 jointPositionWorldSpace = inputPose.GetWorldSpaceTransform(jointIndex).mPosition; - const AZ::Vector3 hipPositionWorldSpace = inputPose.GetWorldSpaceTransform(uniqueData->m_hipJointIndex).mPosition; + const AZ::Vector3 jointPositionModelSpace = inputPose.GetModelSpaceTransform(jointIndex).m_position; + const AZ::Vector3 hipPositionModelSpace = inputPose.GetModelSpaceTransform(uniqueData->m_hipJointIndex).m_position; + const AZ::Vector3 jointPositionWorldSpace = inputPose.GetWorldSpaceTransform(jointIndex).m_position; + const AZ::Vector3 hipPositionWorldSpace = inputPose.GetWorldSpaceTransform(uniqueData->m_hipJointIndex).m_position; const float hipHeightDiff = hipPositionModelSpace.GetZ() - jointPositionModelSpace.GetZ(); outRayStart = jointPositionWorldSpace + upVector * hipHeightDiff; outRayEnd = jointPositionWorldSpace - upVector * rayLength; @@ -327,7 +327,7 @@ namespace EMotionFX if (rayResult.m_intersected) { ActorInstance* actorInstance = animGraphInstance->GetActorInstance(); - raycastResult.m_position = rayResult.m_position + actorInstance->GetWorldSpaceTransform().mRotation + raycastResult.m_position = rayResult.m_position + actorInstance->GetWorldSpaceTransform().m_rotation .TransformVector(AZ::Vector3(0.0f, 0.0f, heightOffset)); raycastResult.m_normal = rayResult.m_normal; raycastResult.m_intersected = true; @@ -406,7 +406,7 @@ namespace EMotionFX { const Leg& leg = solveParams.m_uniqueData->m_legs[legId]; - AZ::Quaternion result = solveParams.m_outputPose->GetWorldSpaceTransform(leg.m_jointIndices[LegJointId::Foot]).mRotation; + AZ::Quaternion result = solveParams.m_outputPose->GetWorldSpaceTransform(leg.m_jointIndices[LegJointId::Foot]).m_rotation; const bool footDown = leg.IsFlagEnabled(LegFlags::FootDown); const bool toeDown = leg.IsFlagEnabled(LegFlags::ToeDown); const float weight = leg.m_weight * solveParams.m_weight; @@ -419,7 +419,7 @@ namespace EMotionFX float distToToeTarget = 0.01f; if (solveParams.m_intersections[legId].m_toeResult.m_intersected) { - distToToeTarget = (solveParams.m_outputPose->GetWorldSpaceTransform(footIndex).mPosition - solveParams.m_intersections[legId].m_toeResult.m_position).GetLength(); + distToToeTarget = (solveParams.m_outputPose->GetWorldSpaceTransform(footIndex).m_position - solveParams.m_intersections[legId].m_toeResult.m_position).GetLength(); } bool bothPlanted = false; @@ -428,8 +428,8 @@ namespace EMotionFX bothPlanted = true; // Get the current vector from the foot to the toe. - const AZ::Vector3 footPos = solveParams.m_outputPose->GetWorldSpaceTransform(footIndex).mPosition; - const AZ::Vector3 oldToePos = solveParams.m_outputPose->GetWorldSpaceTransform(toeIndex).mPosition; + const AZ::Vector3 footPos = solveParams.m_outputPose->GetWorldSpaceTransform(footIndex).m_position; + const AZ::Vector3 oldToePos = solveParams.m_outputPose->GetWorldSpaceTransform(toeIndex).m_position; const AZ::Vector3 oldToToe = (oldToePos - footPos).GetNormalizedSafe(); // Get the new vector from the foot to the toe. @@ -439,20 +439,20 @@ namespace EMotionFX // Apply a delta rotation to the foot. Transform newTransform = solveParams.m_outputPose->GetWorldSpaceTransform(footIndex); const AZ::Quaternion deltaRot = AZ::Quaternion::CreateShortestArc(oldToToe, newToToe); - result = deltaRot * newTransform.mRotation; + result = deltaRot * newTransform.m_rotation; } else if (footDown) { // Get the current vector from the foot to the toe. - const AZ::Vector3 footPos = solveParams.m_outputPose->GetWorldSpaceTransform(footIndex).mPosition; - const AZ::Vector3 oldToePos = solveParams.m_outputPose->GetWorldSpaceTransform(toeIndex).mPosition; + const AZ::Vector3 footPos = solveParams.m_outputPose->GetWorldSpaceTransform(footIndex).m_position; + const AZ::Vector3 oldToePos = solveParams.m_outputPose->GetWorldSpaceTransform(toeIndex).m_position; const AZ::Vector3 oldToToe = (oldToePos - footPos).GetNormalizedSafe(); // Get the new vector from the foot to the toe. const IntersectionResults& intersections = solveParams.m_intersections[legId]; const float footToeHeightDiff = leg.m_footHeight - leg.m_toeHeight; const AZ::Plane plane = AZ::Plane::CreateFromNormalAndPoint(intersections.m_footResult.m_normal, intersections.m_footResult.m_position); - const AZ::Vector3 offset = solveParams.m_actorInstance->GetWorldSpaceTransform().mRotation + const AZ::Vector3 offset = solveParams.m_actorInstance->GetWorldSpaceTransform().m_rotation .TransformVector((footToeHeightDiff * intersections.m_footResult.m_normal)); AZ::Vector3 newToePos = plane.GetProjected(oldToToe); newToePos = intersections.m_footResult.m_position + newToePos.GetNormalizedSafe() * leg.m_footLength; @@ -462,7 +462,7 @@ namespace EMotionFX // Apply a delta rotation to the foot. Transform newTransform = solveParams.m_outputPose->GetWorldSpaceTransform(footIndex); const AZ::Quaternion deltaRot = AZ::Quaternion::CreateShortestArc(oldToToe, newToToe); - result = deltaRot * newTransform.mRotation; + result = deltaRot * newTransform.m_rotation; } // Visualize some debug things in the viewport. @@ -548,8 +548,8 @@ namespace EMotionFX { const float actorInstanceScale = GetActorInstanceScale(solveParams.m_actorInstance); const float surfaceOffset = s_surfaceThreshold * actorInstanceScale; - footDown = solveParams.m_intersections[legId].m_footResult.m_intersected ? IsBelowSurface(inputGlobalTransforms[LegJointId::Foot].mPosition, footTargetPosition, solveParams.m_intersections[legId].m_footResult.m_normal, surfaceOffset) : false; - toeDown = solveParams.m_intersections[legId].m_toeResult.m_intersected ? IsBelowSurface(inputGlobalTransforms[LegJointId::Toe].mPosition, toeTargetPosition, solveParams.m_intersections[legId].m_toeResult.m_normal, surfaceOffset) : false; + footDown = solveParams.m_intersections[legId].m_footResult.m_intersected ? IsBelowSurface(inputGlobalTransforms[LegJointId::Foot].m_position, footTargetPosition, solveParams.m_intersections[legId].m_footResult.m_normal, surfaceOffset) : false; + toeDown = solveParams.m_intersections[legId].m_toeResult.m_intersected ? IsBelowSurface(inputGlobalTransforms[LegJointId::Toe].m_position, toeTargetPosition, solveParams.m_intersections[legId].m_toeResult.m_normal, surfaceOffset) : false; } else { @@ -607,8 +607,8 @@ namespace EMotionFX } // Limit the target position in height. - const AZ::Vector3 vecToTarget = solveParams.m_actorInstance->GetWorldSpaceTransformInversed().mRotation - .TransformVector(footTargetPosition - inputGlobalTransforms[LegJointId::Foot].mPosition); + const AZ::Vector3 vecToTarget = solveParams.m_actorInstance->GetWorldSpaceTransformInversed().m_rotation + .TransformVector(footTargetPosition - inputGlobalTransforms[LegJointId::Foot].m_position); const float feetDifference = vecToTarget.GetZ(); const float maxFootAdjustment = GetMaxFootAdjustment(solveParams.m_animGraphInstance); if (feetDifference > maxFootAdjustment) @@ -617,11 +617,11 @@ namespace EMotionFX } // Calculate the pole vector. - const AZ::Vector3 toFoot = (inputGlobalTransforms[LegJointId::Foot].mPosition - inputGlobalTransforms[LegJointId::UpperLeg].mPosition).GetNormalizedSafe(); - AZ::Vector3 toKnee = (inputGlobalTransforms[LegJointId::Knee].mPosition - inputGlobalTransforms[LegJointId::UpperLeg].mPosition).GetNormalizedSafe(); + const AZ::Vector3 toFoot = (inputGlobalTransforms[LegJointId::Foot].m_position - inputGlobalTransforms[LegJointId::UpperLeg].m_position).GetNormalizedSafe(); + AZ::Vector3 toKnee = (inputGlobalTransforms[LegJointId::Knee].m_position - inputGlobalTransforms[LegJointId::UpperLeg].m_position).GetNormalizedSafe(); if (AZ::IsClose(toFoot.Dot(toKnee), 1.0f, 0.001f)) { - toKnee += solveParams.m_actorInstance->GetWorldSpaceTransform().mRotation.TransformVector(AZ::Vector3(0.0f, 0.01f, 0.0f)); + toKnee += solveParams.m_actorInstance->GetWorldSpaceTransform().m_rotation.TransformVector(AZ::Vector3(0.0f, 0.01f, 0.0f)); toKnee.NormalizeSafe(); } const AZ::Vector3 planeNormal = toFoot.Cross(toKnee); @@ -629,27 +629,27 @@ namespace EMotionFX // Solve the two joint IK problem by calculating the new position of the knee. AZ::Vector3 kneePos; - Solve2LinkIK(inputGlobalTransforms[LegJointId::UpperLeg].mPosition, inputGlobalTransforms[LegJointId::Knee].mPosition, inputGlobalTransforms[LegJointId::Foot].mPosition, footTargetPosition, finalPoleVector, &kneePos); + Solve2LinkIK(inputGlobalTransforms[LegJointId::UpperLeg].m_position, inputGlobalTransforms[LegJointId::Knee].m_position, inputGlobalTransforms[LegJointId::Foot].m_position, footTargetPosition, finalPoleVector, &kneePos); // Update the upper leg. - AZ::Vector3 oldForward = (inputGlobalTransforms[LegJointId::Knee].mPosition - inputGlobalTransforms[LegJointId::UpperLeg].mPosition).GetNormalizedSafe(); - AZ::Vector3 newForward = (kneePos - inputGlobalTransforms[LegJointId::UpperLeg].mPosition).GetNormalizedSafe(); + AZ::Vector3 oldForward = (inputGlobalTransforms[LegJointId::Knee].m_position - inputGlobalTransforms[LegJointId::UpperLeg].m_position).GetNormalizedSafe(); + AZ::Vector3 newForward = (kneePos - inputGlobalTransforms[LegJointId::UpperLeg].m_position).GetNormalizedSafe(); Transform newTransform = inputGlobalTransforms[LegJointId::UpperLeg]; - MCore::RotateFromTo(newTransform.mRotation, oldForward, newForward); + MCore::RotateFromTo(newTransform.m_rotation, oldForward, newForward); solveParams.m_outputPose->SetWorldSpaceTransform(upperLegIndex, newTransform); // Update the knee. - const AZ::Vector3 footPos = solveParams.m_outputPose->GetWorldSpaceTransform(leg.m_jointIndices[LegJointId::Foot]).mPosition; + const AZ::Vector3 footPos = solveParams.m_outputPose->GetWorldSpaceTransform(leg.m_jointIndices[LegJointId::Foot]).m_position; oldForward = (footPos - kneePos).GetNormalized(); newForward = (footTargetPosition - kneePos).GetNormalizedSafe(); newTransform = solveParams.m_outputPose->GetWorldSpaceTransform(leg.m_jointIndices[LegJointId::Knee]); - MCore::RotateFromTo(newTransform.mRotation, oldForward, newForward); - newTransform.mPosition = kneePos; + MCore::RotateFromTo(newTransform.m_rotation, oldForward, newForward); + newTransform.m_position = kneePos; solveParams.m_outputPose->SetWorldSpaceTransform(kneeIndex, newTransform); if (leg.IsFlagEnabled(LegFlags::FirstUpdate)) { - leg.m_currentFootRot = inputGlobalTransforms[LegJointId::Foot].mRotation; + leg.m_currentFootRot = inputGlobalTransforms[LegJointId::Foot].m_rotation; leg.DisableFlag(LegFlags::FirstUpdate); } @@ -679,7 +679,7 @@ namespace EMotionFX blendT = 1.0f; } leg.m_currentFootRot = leg.m_currentFootRot.NLerp(footRotation, blendT); - footTransform.mRotation = leg.m_currentFootRot; + footTransform.m_rotation = leg.m_currentFootRot; solveParams.m_outputPose->SetWorldSpaceTransform(footIndex, footTransform); // Draw debug lines. @@ -689,8 +689,8 @@ namespace EMotionFX drawData->Lock(); if (!solveParams.m_forceIKDisabled && leg.IsFlagEnabled(LegFlags::IkEnabled) && solveParams.m_intersections[legId].m_footResult.m_intersected) { - drawData->DrawLine(inputGlobalTransforms[LegJointId::UpperLeg].mPosition, kneePos, mVisualizeColor); - drawData->DrawLine(kneePos, footTargetPosition, mVisualizeColor); + drawData->DrawLine(inputGlobalTransforms[LegJointId::UpperLeg].m_position, kneePos, m_visualizeColor); + drawData->DrawLine(kneePos, footTargetPosition, m_visualizeColor); } drawData->Unlock(); } @@ -719,11 +719,11 @@ namespace EMotionFX leg.m_legLength = 0.0f; for (size_t legNodeIndex = 1; legNodeIndex < 3; ++legNodeIndex) { - leg.m_legLength += (inputPose.GetModelSpaceTransform(leg.m_jointIndices[legNodeIndex]).mPosition - inputPose.GetModelSpaceTransform(leg.m_jointIndices[legNodeIndex - 1]).mPosition).GetLength(); + leg.m_legLength += (inputPose.GetModelSpaceTransform(leg.m_jointIndices[legNodeIndex]).m_position - inputPose.GetModelSpaceTransform(leg.m_jointIndices[legNodeIndex - 1]).m_position).GetLength(); } // Calculate the foot length. - leg.m_footLength = (inputPose.GetModelSpaceTransform(leg.m_jointIndices[LegJointId::Toe]).mPosition - inputPose.GetModelSpaceTransform(leg.m_jointIndices[LegJointId::Foot]).mPosition).GetLength(); + leg.m_footLength = (inputPose.GetModelSpaceTransform(leg.m_jointIndices[LegJointId::Toe]).m_position - inputPose.GetModelSpaceTransform(leg.m_jointIndices[LegJointId::Foot]).m_position).GetLength(); } // Adjust the hip by moving it downwards when we can't reach a given target. @@ -739,8 +739,8 @@ namespace EMotionFX // If the target foot position is below the ground plane in model space, so if we actually have to lower the hips. ActorInstance* actorInstance = animGraphInstance->GetActorInstance(); - const AZ::Vector3 upVector = actorInstance->GetWorldSpaceTransform().mRotation.TransformVector(AZ::Vector3(0.0f, 0.0f, 1.0f)); - const AZ::Vector3 leftFootBindPoseModelSpace = actorInstance->GetTransformData()->GetBindPose()->GetModelSpaceTransform(leftLeg.m_jointIndices[LegJointId::Foot]).mPosition; + const AZ::Vector3 upVector = actorInstance->GetWorldSpaceTransform().m_rotation.TransformVector(AZ::Vector3(0.0f, 0.0f, 1.0f)); + const AZ::Vector3 leftFootBindPoseModelSpace = actorInstance->GetTransformData()->GetBindPose()->GetModelSpaceTransform(leftLeg.m_jointIndices[LegJointId::Foot]).m_position; const AZ::Vector3 leftFootBindWorldPos = actorInstance->GetWorldSpaceTransform().TransformPoint(leftFootBindPoseModelSpace); const AZ::Plane leftSurfacePlane = AZ::Plane::CreateFromNormalAndPoint(upVector, leftFootBindWorldPos); float leftCorrection = leftSurfacePlane.GetPointDist(intersectionResults[LegId::Left].m_footResult.m_position); @@ -750,7 +750,7 @@ namespace EMotionFX } // Do the same for the right leg. - const AZ::Vector3 rightFootBindPoseModelSpace = actorInstance->GetTransformData()->GetBindPose()->GetModelSpaceTransform(rightLeg.m_jointIndices[LegJointId::Foot]).mPosition; + const AZ::Vector3 rightFootBindPoseModelSpace = actorInstance->GetTransformData()->GetBindPose()->GetModelSpaceTransform(rightLeg.m_jointIndices[LegJointId::Foot]).m_position; const AZ::Vector3 rightFootBindWorldPos = actorInstance->GetWorldSpaceTransform().TransformPoint(rightFootBindPoseModelSpace); const AZ::Plane rightSurfacePlane = AZ::Plane::CreateFromNormalAndPoint(upVector, rightFootBindWorldPos); float rightCorrection = rightSurfacePlane.GetPointDist(intersectionResults[LegId::Right].m_footResult.m_position); @@ -768,7 +768,7 @@ namespace EMotionFX // Debug render some line to show the displacement. if (GetEMotionFX().GetIsInEditorMode() && GetCanVisualize(animGraphInstance)) { - const AZ::Vector3 hipPos = inputPose.GetWorldSpaceTransform(uniqueData->m_hipJointIndex).mPosition; + const AZ::Vector3 hipPos = inputPose.GetWorldSpaceTransform(uniqueData->m_hipJointIndex).m_position; DebugDraw::ActorInstanceData* drawData = GetDebugDraw().GetActorInstanceData(animGraphInstance->GetActorInstance()); drawData->Lock(); drawData->DrawLine(hipPos, hipPos + AZ::Vector3(0.0f, 0.0f, correction), AZ::Color(1.0f, 0.0f, 1.0f, 1.0f)); @@ -786,7 +786,7 @@ namespace EMotionFX } const float interpolatedCorrection = AZ::Lerp(uniqueData->m_curHipCorrection, correction, t); uniqueData->m_curHipCorrection = interpolatedCorrection; - hipTransform.mPosition += animGraphInstance->GetActorInstance()->GetWorldSpaceTransform().mRotation + hipTransform.m_position += animGraphInstance->GetActorInstance()->GetWorldSpaceTransform().m_rotation .TransformVector(AZ::Vector3(0.0f, 0.0f, interpolatedCorrection)); outputPose.SetWorldSpaceTransform(uniqueData->m_hipJointIndex, hipTransform); inputPose = outputPose; // As we adjusted our hip, the input pose to the IK leg solve has been modified, so update it. @@ -829,7 +829,7 @@ namespace EMotionFX AnimGraphPose* outputPose; // If nothing is connected to the input pose, output a bind pose. - if (!GetInputPort(INPUTPORT_POSE).mConnection) + if (!GetInputPort(INPUTPORT_POSE).m_connection) { RequestPoses(animGraphInstance); outputPose = GetOutputPose(animGraphInstance, OUTPUTPORT_POSE)->GetValue(); @@ -840,7 +840,7 @@ namespace EMotionFX // Get the weight from the input port. float weight = 1.0f; - if (GetInputPort(INPUTPORT_WEIGHT).mConnection) + if (GetInputPort(INPUTPORT_WEIGHT).m_connection) { OutputIncomingNode(animGraphInstance, GetInputNode(INPUTPORT_WEIGHT)); weight = GetInputNumberAsFloat(animGraphInstance, INPUTPORT_WEIGHT); @@ -848,7 +848,7 @@ namespace EMotionFX } // If the weight is near zero or if this node is disabled or if the node is enable for server optimization, we can skip all calculations and just output the input pose. - if (weight < MCore::Math::epsilon || mDisabled || GetEMotionFX().GetEnableServerOptimization()) + if (weight < MCore::Math::epsilon || m_disabled || GetEMotionFX().GetEnableServerOptimization()) { OutputIncomingNode(animGraphInstance, GetInputNode(INPUTPORT_POSE)); const AnimGraphPose* inputPose = GetInputPose(animGraphInstance, INPUTPORT_POSE)->GetValue(); @@ -928,7 +928,7 @@ namespace EMotionFX for (size_t i = 0; i < numEvents; ++i) { const EventInfo& eventInfo = eventBuffer.GetEvent(i); - const MotionEvent* motionEvent = eventInfo.mEvent; + const MotionEvent* motionEvent = eventInfo.m_event; const EventDataSet& eventDataSet = motionEvent->GetEventDatas(); for (const EventDataPtr& eventData : eventDataSet) { diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeGetTransformNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeGetTransformNode.cpp index fd04a43251..b836188757 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeGetTransformNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeGetTransformNode.cpp @@ -33,7 +33,7 @@ namespace EMotionFX void BlendTreeGetTransformNode::UniqueData::Update() { - BlendTreeGetTransformNode* transformNode = azdynamic_cast(mObject); + BlendTreeGetTransformNode* transformNode = azdynamic_cast(m_object); AZ_Assert(transformNode, "Unique data linked to incorrect node type."); m_nodeIndex = InvalidIndex; @@ -41,7 +41,7 @@ namespace EMotionFX const int actorInstanceParentDepth = transformNode->GetActorInstanceParentDepth(); // lookup the actor instance to get the node from - const ActorInstance* alignInstance = mAnimGraphInstance->FindActorInstanceFromParentDepth(actorInstanceParentDepth); + const ActorInstance* alignInstance = m_animGraphInstance->FindActorInstanceFromParentDepth(actorInstanceParentDepth); if (alignInstance) { const Node* alignNode = alignInstance->GetActor()->GetSkeleton()->FindNodeByName(nodeName); @@ -110,7 +110,7 @@ namespace EMotionFX } // make sure we have at least an input pose, otherwise output the bind pose - if (GetInputPort(INPUTPORT_POSE).mConnection) + if (GetInputPort(INPUTPORT_POSE).m_connection) { OutputIncomingNode(animGraphInstance, GetInputNode(INPUTPORT_POSE)); inputPose = GetInputPose(animGraphInstance, INPUTPORT_POSE)->GetValue(); @@ -162,11 +162,11 @@ namespace EMotionFX inputTransform.Identity(); } - GetOutputVector3(animGraphInstance, OUTPUTPORT_TRANSLATION)->SetValue(inputTransform.mPosition); - GetOutputQuaternion(animGraphInstance, OUTPUTPORT_ROTATION)->SetValue(inputTransform.mRotation); + GetOutputVector3(animGraphInstance, OUTPUTPORT_TRANSLATION)->SetValue(inputTransform.m_position); + GetOutputQuaternion(animGraphInstance, OUTPUTPORT_ROTATION)->SetValue(inputTransform.m_rotation); #ifndef EMFX_SCALE_DISABLED - GetOutputVector3(animGraphInstance, OUTPUTPORT_SCALE)->SetValue(inputTransform.mScale); + GetOutputVector3(animGraphInstance, OUTPUTPORT_SCALE)->SetValue(inputTransform.m_scale); #else GetOutputVector3(animGraphInstance, OUTPUTPORT_SCALE)->SetValue(AZ::Vector3::CreateOne()); #endif diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeLookAtNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeLookAtNode.cpp index f904f35ba4..84eeca094d 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeLookAtNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeLookAtNode.cpp @@ -34,13 +34,13 @@ namespace EMotionFX void BlendTreeLookAtNode::UniqueData::Update() { - BlendTreeLookAtNode* lookAtNode = azdynamic_cast(mObject); + BlendTreeLookAtNode* lookAtNode = azdynamic_cast(m_object); AZ_Assert(lookAtNode, "Unique data linked to incorrect node type."); - const ActorInstance* actorInstance = mAnimGraphInstance->GetActorInstance(); + const ActorInstance* actorInstance = m_animGraphInstance->GetActorInstance(); const Actor* actor = actorInstance->GetActor(); - mNodeIndex = InvalidIndex; + m_nodeIndex = InvalidIndex; SetHasError(true); const AZStd::string& targetJointName = lookAtNode->GetTargetNodeName(); @@ -49,7 +49,7 @@ namespace EMotionFX const Node* targetNode = actor->GetSkeleton()->FindNodeByName(targetJointName); if (targetNode) { - mNodeIndex = targetNode->GetNodeIndex(); + m_nodeIndex = targetNode->GetNodeIndex(); SetHasError(false); } } @@ -112,7 +112,7 @@ namespace EMotionFX AnimGraphPose* outputPose; // make sure we have at least an input pose, otherwise output the bind pose - if (GetInputPort(INPUTPORT_POSE).mConnection == nullptr) + if (GetInputPort(INPUTPORT_POSE).m_connection == nullptr) { RequestPoses(animGraphInstance); outputPose = GetOutputPose(animGraphInstance, OUTPUTPORT_POSE)->GetValue(); @@ -123,7 +123,7 @@ namespace EMotionFX // get the weight float weight = 1.0f; - if (GetInputPort(INPUTPORT_WEIGHT).mConnection) + if (GetInputPort(INPUTPORT_WEIGHT).m_connection) { OutputIncomingNode(animGraphInstance, GetInputNode(INPUTPORT_WEIGHT)); weight = GetInputNumberAsFloat(animGraphInstance, INPUTPORT_WEIGHT); @@ -131,7 +131,7 @@ namespace EMotionFX } // if the weight is near zero, we can skip all calculations and act like a pass-trough node - if (weight < MCore::Math::epsilon || mDisabled) + if (weight < MCore::Math::epsilon || m_disabled) { OutputIncomingNode(animGraphInstance, GetInputNode(INPUTPORT_POSE)); RequestPoses(animGraphInstance); @@ -139,7 +139,7 @@ namespace EMotionFX const AnimGraphPose* inputPose = GetInputPose(animGraphInstance, INPUTPORT_POSE)->GetValue(); *outputPose = *inputPose; UniqueData* uniqueData = static_cast(FindOrCreateUniqueNodeData(animGraphInstance)); - uniqueData->mFirstUpdate = true; + uniqueData->m_firstUpdate = true; return; } @@ -177,7 +177,7 @@ namespace EMotionFX ActorInstance* actorInstance = animGraphInstance->GetActorInstance(); // get a shortcut to the local transform object - const size_t nodeIndex = uniqueData->mNodeIndex; + const size_t nodeIndex = uniqueData->m_nodeIndex; Pose& outTransformPose = outputPose->GetPose(); Transform globalTransform = outTransformPose.GetWorldSpaceTransform(nodeIndex); @@ -185,7 +185,7 @@ namespace EMotionFX Skeleton* skeleton = actorInstance->GetActor()->GetSkeleton(); // Prevent invalid float values inside the LookAt matrix construction when both position and goal are the same - const AZ::Vector3 diff = globalTransform.mPosition - goal; + const AZ::Vector3 diff = globalTransform.m_position - goal; if (diff.GetLengthSq() < AZ::Constants::FloatEpsilon) { goal += AZ::Vector3(0.0f, 0.000001f, 0.0f); @@ -194,7 +194,7 @@ namespace EMotionFX // calculate the lookat transform // TODO: a quaternion lookat function would be nicer, so that there are no matrix operations involved AZ::Matrix4x4 lookAt; - MCore::LookAt(lookAt, globalTransform.mPosition, goal, AZ::Vector3(0.0f, 0.0f, 1.0f)); + MCore::LookAt(lookAt, globalTransform.m_position, goal, AZ::Vector3(0.0f, 0.0f, 1.0f)); AZ::Quaternion destRotation = AZ::Quaternion::CreateFromMatrix4x4(lookAt.GetTranspose()); // apply the post rotation @@ -208,8 +208,8 @@ namespace EMotionFX AZ::Quaternion bindRotationLocal; if (parentIndex != InvalidIndex) { - parentRotationGlobal = inputPose->GetPose().GetWorldSpaceTransform(parentIndex).mRotation; - bindRotationLocal = actorInstance->GetTransformData()->GetBindPose()->GetLocalSpaceTransform(parentIndex).mRotation; + parentRotationGlobal = inputPose->GetPose().GetWorldSpaceTransform(parentIndex).m_rotation; + bindRotationLocal = actorInstance->GetTransformData()->GetBindPose()->GetLocalSpaceTransform(parentIndex).m_rotation; } else { @@ -228,47 +228,47 @@ namespace EMotionFX constraint.SetMinTwistAngle(0.0f); constraint.SetMaxTwistAngle(0.0f); constraint.SetTwistAxis(m_twistAxis); - constraint.GetTransform().mRotation = (deltaRotLocal * m_constraintRotation.GetConjugate()); + constraint.GetTransform().m_rotation = (deltaRotLocal * m_constraintRotation.GetConjugate()); constraint.Execute(); if (GetEMotionFX().GetIsInEditorMode() && GetCanVisualize(animGraphInstance)) { AZ::Transform offset = AZ::Transform::CreateFromQuaternion(m_postRotation.GetInverseFull() * bindRotationLocal * m_constraintRotation * parentRotationGlobal); - offset.SetTranslation(globalTransform.mPosition); + offset.SetTranslation(globalTransform.m_position); constraint.DebugDraw(actorInstance, offset, GetVisualizeColor(), 0.5f); } // convert back into world space - destRotation = (bindRotationLocal * (constraint.GetTransform().mRotation * m_constraintRotation)) * parentRotationGlobal; + destRotation = (bindRotationLocal * (constraint.GetTransform().m_rotation * m_constraintRotation)) * parentRotationGlobal; } // init the rotation quaternion to the initial rotation - if (uniqueData->mFirstUpdate) + if (uniqueData->m_firstUpdate) { - uniqueData->mRotationQuat = destRotation; - uniqueData->mFirstUpdate = false; + uniqueData->m_rotationQuat = destRotation; + uniqueData->m_firstUpdate = false; } // interpolate between the current rotation and the destination rotation if (m_smoothing) { - const float speed = m_followSpeed * uniqueData->mTimeDelta * 10.0f; + const float speed = m_followSpeed * uniqueData->m_timeDelta * 10.0f; if (speed < 1.0f) { - uniqueData->mRotationQuat = uniqueData->mRotationQuat.Slerp(destRotation, speed); + uniqueData->m_rotationQuat = uniqueData->m_rotationQuat.Slerp(destRotation, speed); } else { - uniqueData->mRotationQuat = destRotation; + uniqueData->m_rotationQuat = destRotation; } } else { - uniqueData->mRotationQuat = destRotation; + uniqueData->m_rotationQuat = destRotation; } - uniqueData->mRotationQuat.Normalize(); - globalTransform.mRotation = uniqueData->mRotationQuat; + uniqueData->m_rotationQuat.Normalize(); + globalTransform.m_rotation = uniqueData->m_rotationQuat; // only blend when needed if (weight < 0.999f) @@ -294,11 +294,11 @@ namespace EMotionFX DebugDraw& debugDraw = GetDebugDraw(); DebugDraw::ActorInstanceData* drawData = debugDraw.GetActorInstanceData(animGraphInstance->GetActorInstance()); drawData->Lock(); - drawData->DrawLine(goal - AZ::Vector3(s, 0, 0), goal + AZ::Vector3(s, 0, 0), mVisualizeColor); - drawData->DrawLine(goal - AZ::Vector3(0, s, 0), goal + AZ::Vector3(0, s, 0), mVisualizeColor); - drawData->DrawLine(goal - AZ::Vector3(0, 0, s), goal + AZ::Vector3(0, 0, s), mVisualizeColor); - drawData->DrawLine(globalTransform.mPosition, goal, mVisualizeColor); - drawData->DrawLine(globalTransform.mPosition, globalTransform.mPosition + MCore::CalcUpAxis(globalTransform.mRotation) * s * 50.0f, AZ::Color(0.0f, 0.0f, 1.0f, 1.0f)); + drawData->DrawLine(goal - AZ::Vector3(s, 0, 0), goal + AZ::Vector3(s, 0, 0), m_visualizeColor); + drawData->DrawLine(goal - AZ::Vector3(0, s, 0), goal + AZ::Vector3(0, s, 0), m_visualizeColor); + drawData->DrawLine(goal - AZ::Vector3(0, 0, s), goal + AZ::Vector3(0, 0, s), m_visualizeColor); + drawData->DrawLine(globalTransform.m_position, goal, m_visualizeColor); + drawData->DrawLine(globalTransform.m_position, globalTransform.m_position + MCore::CalcUpAxis(globalTransform.m_rotation) * s * 50.0f, AZ::Color(0.0f, 0.0f, 1.0f, 1.0f)); drawData->Unlock(); } } @@ -335,7 +335,7 @@ namespace EMotionFX uniqueData->Clear(); } - uniqueData->mTimeDelta = timePassedInSeconds; + uniqueData->m_timeDelta = timePassedInSeconds; } AZ::Crc32 BlendTreeLookAtNode::GetLimitWidgetsVisibility() const diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeLookAtNode.h b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeLookAtNode.h index 4da3855dd1..098ce5ca08 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeLookAtNode.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeLookAtNode.h @@ -63,10 +63,10 @@ namespace EMotionFX void Update() override; public: - AZ::Quaternion mRotationQuat = AZ::Quaternion::CreateIdentity(); - float mTimeDelta = 0.0f; - size_t mNodeIndex = InvalidIndex; - bool mFirstUpdate = true; + AZ::Quaternion m_rotationQuat = AZ::Quaternion::CreateIdentity(); + float m_timeDelta = 0.0f; + size_t m_nodeIndex = InvalidIndex; + bool m_firstUpdate = true; }; BlendTreeLookAtNode(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeMaskLegacyNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeMaskLegacyNode.cpp index 88da8346d0..ca409fe6d7 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeMaskLegacyNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeMaskLegacyNode.cpp @@ -21,7 +21,7 @@ namespace EMotionFX { - size_t BlendTreeMaskLegacyNode::m_numMasks = 4; + size_t BlendTreeMaskLegacyNode::s_numMasks = 4; AZ_CLASS_ALLOCATOR_IMPL(BlendTreeMaskLegacyNode, AnimGraphAllocator, 0) AZ_CLASS_ALLOCATOR_IMPL(BlendTreeMaskLegacyNode::UniqueData, AnimGraphObjectUniqueDataAllocator, 0) @@ -33,17 +33,17 @@ namespace EMotionFX void BlendTreeMaskLegacyNode::UniqueData::Update() { - BlendTreeMaskLegacyNode* maskNode = azdynamic_cast(mObject); + BlendTreeMaskLegacyNode* maskNode = azdynamic_cast(m_object); AZ_Assert(maskNode, "Unique data linked to incorrect node type."); - Actor* actor = mAnimGraphInstance->GetActorInstance()->GetActor(); + Actor* actor = m_animGraphInstance->GetActorInstance()->GetActor(); const size_t numMasks = BlendTreeMaskLegacyNode::GetNumMasks(); - mMasks.resize(numMasks); - AnimGraphPropertyUtils::ReinitJointIndices(actor, maskNode->GetMask0(), mMasks[0]); - AnimGraphPropertyUtils::ReinitJointIndices(actor, maskNode->GetMask1(), mMasks[1]); - AnimGraphPropertyUtils::ReinitJointIndices(actor, maskNode->GetMask2(), mMasks[2]); - AnimGraphPropertyUtils::ReinitJointIndices(actor, maskNode->GetMask3(), mMasks[3]); + m_masks.resize(numMasks); + AnimGraphPropertyUtils::ReinitJointIndices(actor, maskNode->GetMask0(), m_masks[0]); + AnimGraphPropertyUtils::ReinitJointIndices(actor, maskNode->GetMask1(), m_masks[1]); + AnimGraphPropertyUtils::ReinitJointIndices(actor, maskNode->GetMask2(), m_masks[2]); + AnimGraphPropertyUtils::ReinitJointIndices(actor, maskNode->GetMask3(), m_masks[3]); } BlendTreeMaskLegacyNode::BlendTreeMaskLegacyNode() @@ -54,7 +54,7 @@ namespace EMotionFX , m_outputEvents3(true) { // setup the input ports - InitInputPorts(m_numMasks); + InitInputPorts(s_numMasks); SetupInputPort("Pose 0", INPUTPORT_POSE_0, AttributePose::TYPE_ID, PORTID_INPUT_POSE_0); SetupInputPort("Pose 1", INPUTPORT_POSE_1, AttributePose::TYPE_ID, PORTID_INPUT_POSE_1); SetupInputPort("Pose 2", INPUTPORT_POSE_2, AttributePose::TYPE_ID, PORTID_INPUT_POSE_2); @@ -104,10 +104,10 @@ namespace EMotionFX UniqueData* uniqueData = static_cast(FindOrCreateUniqueNodeData(animGraphInstance)); // for all input ports - for (size_t i = 0; i < m_numMasks; ++i) + for (size_t i = 0; i < s_numMasks; ++i) { // if there is no connection plugged in - if (mInputPorts[INPUTPORT_POSE_0 + i].mConnection == nullptr) + if (m_inputPorts[INPUTPORT_POSE_0 + i].m_connection == nullptr) { continue; } @@ -121,10 +121,10 @@ namespace EMotionFX outputPose = GetOutputPose(animGraphInstance, OUTPUTPORT_RESULT)->GetValue(); outputPose->InitFromBindPose(animGraphInstance->GetActorInstance()); - for (size_t i = 0; i < m_numMasks; ++i) + for (size_t i = 0; i < s_numMasks; ++i) { // if there is no connection plugged in - if (mInputPorts[INPUTPORT_POSE_0 + i].mConnection == nullptr) + if (m_inputPorts[INPUTPORT_POSE_0 + i].m_connection == nullptr) { continue; } @@ -135,11 +135,11 @@ namespace EMotionFX const Pose& localPose = pose->GetPose(); // get the number of nodes inside the mask and default them to all nodes in the local pose in case there aren't any selected - const size_t numNodes = uniqueData->mMasks[i].size(); + const size_t numNodes = uniqueData->m_masks[i].size(); if (numNodes > 0) { // for all nodes in the mask, output their transforms - for (size_t nodeIndex : uniqueData->mMasks[i]) + for (size_t nodeIndex : uniqueData->m_masks[i]) { outputLocalPose.SetLocalSpaceTransform(nodeIndex, localPose.GetLocalSpaceTransform(nodeIndex)); } @@ -153,7 +153,7 @@ namespace EMotionFX // visualize it if (GetEMotionFX().GetIsInEditorMode() && GetCanVisualize(animGraphInstance)) { - animGraphInstance->GetActorInstance()->DrawSkeleton(outputPose->GetPose(), mVisualizeColor); + animGraphInstance->GetActorInstance()->DrawSkeleton(outputPose->GetPose(), m_visualizeColor); } } @@ -182,7 +182,7 @@ namespace EMotionFX void BlendTreeMaskLegacyNode::PostUpdate(AnimGraphInstance* animGraphInstance, float timePassedInSeconds) { // post update all incoming nodes - for (size_t i = 0; i < m_numMasks; ++i) + for (size_t i = 0; i < s_numMasks; ++i) { // if the port has no input, skip it AnimGraphNode* inputNode = GetInputNode(INPUTPORT_POSE_0 + i); @@ -202,7 +202,7 @@ namespace EMotionFX data->ClearEventBuffer(); data->ZeroTrajectoryDelta(); - for (size_t i = 0; i < m_numMasks; ++i) + for (size_t i = 0; i < s_numMasks; ++i) { // if the port has no input, skip it AnimGraphNode* inputNode = GetInputNode(INPUTPORT_POSE_0 + i); @@ -212,11 +212,11 @@ namespace EMotionFX } // get the number of nodes inside the mask and default them to all nodes in the local pose in case there aren't any selected - const size_t numNodes = uniqueData->mMasks[i].size(); + const size_t numNodes = uniqueData->m_masks[i].size(); if (numNodes > 0) { // for all nodes in the mask, output their transforms - for (size_t nodeIndex : uniqueData->mMasks[i]) + for (size_t nodeIndex : uniqueData->m_masks[i]) { if (nodeIndex == animGraphInstance->GetActorInstance()->GetActor()->GetMotionExtractionNodeIndex()) { diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeMaskLegacyNode.h b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeMaskLegacyNode.h index 0cddd9610a..2abc5dc5cf 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeMaskLegacyNode.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeMaskLegacyNode.h @@ -53,7 +53,7 @@ namespace EMotionFX void Update() override; public: - AZStd::vector< AZStd::vector > mMasks; + AZStd::vector< AZStd::vector > m_masks; }; BlendTreeMaskLegacyNode(); @@ -77,7 +77,7 @@ namespace EMotionFX void SetMask2(const AZStd::vector& mask2); void SetMask3(const AZStd::vector& mask3); - static size_t GetNumMasks() { return m_numMasks; } + static size_t GetNumMasks() { return s_numMasks; } const AZStd::vector& GetMask0() const { return m_mask0; } const AZStd::vector& GetMask1() const { return m_mask1; } const AZStd::vector& GetMask2() const { return m_mask2; } @@ -109,6 +109,6 @@ namespace EMotionFX bool m_outputEvents2; bool m_outputEvents3; - static size_t m_numMasks; + static size_t s_numMasks; }; } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeMaskNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeMaskNode.cpp index d43ac3b033..039d11d881 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeMaskNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeMaskNode.cpp @@ -30,16 +30,16 @@ namespace EMotionFX void BlendTreeMaskNode::UniqueData::Update() { - BlendTreeMaskNode* maskNode = azdynamic_cast(mObject); + BlendTreeMaskNode* maskNode = azdynamic_cast(m_object); AZ_Assert(maskNode, "Unique data linked to incorrect node type."); - const Actor* actor = mAnimGraphInstance->GetActorInstance()->GetActor(); + const Actor* actor = m_animGraphInstance->GetActorInstance()->GetActor(); const size_t numMaskInstances = maskNode->GetNumUsedMasks(); m_maskInstances.resize(numMaskInstances); size_t maskInstanceIndex = 0; m_motionExtractionInputPortNr.reset(); - const size_t motionExtractionJointIndex = mAnimGraphInstance->GetActorInstance()->GetActor()->GetMotionExtractionNodeIndex(); + const size_t motionExtractionJointIndex = m_animGraphInstance->GetActorInstance()->GetActor()->GetMotionExtractionNodeIndex(); const AZStd::vector& masks = maskNode->GetMasks(); const size_t numMasks = masks.size(); @@ -129,16 +129,16 @@ namespace EMotionFX void BlendTreeMaskNode::OnMotionExtractionNodeChanged(Actor* actor, [[maybe_unused]] Node* newMotionExtractionNode) { - if (!mAnimGraph) + if (!m_animGraph) { return; } bool needsReinit = false; - const size_t numAnimGraphInstances = mAnimGraph->GetNumAnimGraphInstances(); + const size_t numAnimGraphInstances = m_animGraph->GetNumAnimGraphInstances(); for (size_t i = 0; i < numAnimGraphInstances; ++i) { - AnimGraphInstance* animGraphInstance = mAnimGraph->GetAnimGraphInstance(i); + AnimGraphInstance* animGraphInstance = m_animGraph->GetAnimGraphInstance(i); if (actor == animGraphInstance->GetActorInstance()->GetActor()) { needsReinit = true; @@ -192,7 +192,7 @@ namespace EMotionFX if (GetEMotionFX().GetIsInEditorMode() && GetCanVisualize(animGraphInstance)) { - animGraphInstance->GetActorInstance()->DrawSkeleton(outputAnimGraphPose->GetPose(), mVisualizeColor); + animGraphInstance->GetActorInstance()->DrawSkeleton(outputAnimGraphPose->GetPose(), m_visualizeColor); } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeMirrorPoseNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeMirrorPoseNode.cpp index 04199c18ca..f1e738d56d 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeMirrorPoseNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeMirrorPoseNode.cpp @@ -79,7 +79,7 @@ namespace EMotionFX { // check the enabled state bool isEnabled = true; - if (mInputPorts[INPUTPORT_ENABLED].mConnection) + if (m_inputPorts[INPUTPORT_ENABLED].m_connection) { isEnabled = GetInputNumberAsBool(animGraphInstance, INPUTPORT_ENABLED); } @@ -107,7 +107,7 @@ namespace EMotionFX uniqueData->Init(animGraphInstance, sourceNode); // apply mirroring to the sync track - if (GetIsMirroringEnabled(animGraphInstance) && !mDisabled) + if (GetIsMirroringEnabled(animGraphInstance) && !m_disabled) { EMotionFX::AnimGraphNodeData* sourceNodeData = sourceNode->FindOrCreateUniqueNodeData(animGraphInstance); uniqueData->SetSyncTrack(sourceNodeData->GetSyncTrack()); @@ -119,7 +119,7 @@ namespace EMotionFX // perform the calculations / actions void BlendTreeMirrorPoseNode::Output(AnimGraphInstance* animGraphInstance) { - if (mInputPorts[INPUTPORT_POSE].mConnection == nullptr) + if (m_inputPorts[INPUTPORT_POSE].m_connection == nullptr) { // get the output pose RequestPoses(animGraphInstance); @@ -129,7 +129,7 @@ namespace EMotionFX } // if we're disabled just forward the input pose - if (mDisabled) + if (m_disabled) { OutputIncomingNode(animGraphInstance, GetInputNode(INPUTPORT_POSE)); const AnimGraphPose* inputPose = GetInputPose(animGraphInstance, INPUTPORT_POSE)->GetValue(); @@ -173,11 +173,11 @@ namespace EMotionFX // build the mirror plane normal, based on the mirror axis for this node AZ::Vector3 mirrorPlaneNormal(0.0f, 0.0f, 0.0f); - mirrorPlaneNormal.SetElement(mirrorInfo.mAxis, 1.0f); + mirrorPlaneNormal.SetElement(mirrorInfo.m_axis, 1.0f); // apply the mirrored delta to the bind pose of the current node outputTransform = bindPose->GetLocalSpaceTransform(nodeIndex); - outputTransform.ApplyDeltaMirrored(bindPose->GetLocalSpaceTransform(mirrorInfo.mSourceNode), inPose.GetLocalSpaceTransform(mirrorInfo.mSourceNode), mirrorPlaneNormal, mirrorInfo.mFlags); + outputTransform.ApplyDeltaMirrored(bindPose->GetLocalSpaceTransform(mirrorInfo.m_sourceNode), inPose.GetLocalSpaceTransform(mirrorInfo.m_sourceNode), mirrorPlaneNormal, mirrorInfo.m_flags); // update the pose with the new transform outPose.SetLocalSpaceTransform(nodeIndex, outputTransform); @@ -187,7 +187,7 @@ namespace EMotionFX // visualize it if (GetEMotionFX().GetIsInEditorMode() && GetCanVisualize(animGraphInstance)) { - animGraphInstance->GetActorInstance()->DrawSkeleton(outputPose->GetPose(), mVisualizeColor); + animGraphInstance->GetActorInstance()->DrawSkeleton(outputPose->GetPose(), m_visualizeColor); } } @@ -196,7 +196,7 @@ namespace EMotionFX void BlendTreeMirrorPoseNode::PostUpdate(AnimGraphInstance* animGraphInstance, float timePassedInSeconds) { // check if we have three incoming connections, if not, we can't really continue - if (mConnections.size() == 0 || mInputPorts[INPUTPORT_POSE].mConnection == nullptr) + if (m_connections.size() == 0 || m_inputPorts[INPUTPORT_POSE].m_connection == nullptr) { RequestRefDatas(animGraphInstance); AnimGraphNodeData* uniqueData = FindOrCreateUniqueNodeData(animGraphInstance); @@ -216,7 +216,7 @@ namespace EMotionFX AnimGraphRefCountedData* sourceData = inputNode->FindOrCreateUniqueNodeData(animGraphInstance)->GetRefCountedData(); data->SetEventBuffer(sourceData->GetEventBuffer()); - if (GetIsMirroringEnabled(animGraphInstance) && mDisabled == false) + if (GetIsMirroringEnabled(animGraphInstance) && m_disabled == false) { data->SetTrajectoryDelta(sourceData->GetTrajectoryDeltaMirrored()); data->SetTrajectoryDeltaMirrored(sourceData->GetTrajectoryDelta()); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeMorphTargetNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeMorphTargetNode.cpp index ad88909e29..69e93971fd 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeMorphTargetNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeMorphTargetNode.cpp @@ -27,11 +27,11 @@ namespace EMotionFX void BlendTreeMorphTargetNode::UniqueData::Update() { - BlendTreeMorphTargetNode* morphTargetNode = azdynamic_cast(mObject); + BlendTreeMorphTargetNode* morphTargetNode = azdynamic_cast(m_object); AZ_Assert(morphTargetNode, "Unique data linked to incorrect node type."); // Force update the morph target indices. - morphTargetNode->UpdateMorphIndices(mAnimGraphInstance->GetActorInstance(), this, true); + morphTargetNode->UpdateMorphIndices(m_animGraphInstance->GetActorInstance(), this, true); } BlendTreeMorphTargetNode::BlendTreeMorphTargetNode() @@ -146,7 +146,7 @@ namespace EMotionFX // If there is no input pose init the uutput pose to the bind pose. AnimGraphPose* outputPose; - if (!mInputPorts[INPUTPORT_POSE].mConnection) + if (!m_inputPorts[INPUTPORT_POSE].m_connection) { RequestPoses(animGraphInstance); outputPose = GetOutputPose(animGraphInstance, OUTPUTPORT_POSE)->GetValue(); @@ -162,10 +162,10 @@ namespace EMotionFX } // Try to modify the morph target weight with the value we specified as input. - if (!mDisabled && uniqueData->m_morphTargetIndex != InvalidIndex) + if (!m_disabled && uniqueData->m_morphTargetIndex != InvalidIndex) { // If we have an input to the weight port, read that value use that value to overwrite the pose value with. - if (mInputPorts[INPUTPORT_WEIGHT].mConnection) + if (m_inputPorts[INPUTPORT_WEIGHT].m_connection) { OutputIncomingNode(animGraphInstance, GetInputNode(INPUTPORT_WEIGHT)); const float morphWeight = GetInputNumberAsFloat(animGraphInstance, INPUTPORT_WEIGHT); @@ -178,7 +178,7 @@ namespace EMotionFX // Debug visualize the output pose. if (GetEMotionFX().GetIsInEditorMode() && GetCanVisualize(animGraphInstance)) { - actorInstance->DrawSkeleton(outputPose->GetPose(), mVisualizeColor); + actorInstance->DrawSkeleton(outputPose->GetPose(), m_visualizeColor); } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeMotionFrameNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeMotionFrameNode.cpp index 73494c6ab3..3822d5a2e1 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeMotionFrameNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeMotionFrameNode.cpp @@ -82,7 +82,7 @@ namespace EMotionFX AnimGraphPose* outputPose; // get the motion instance object - BlendTreeConnection* motionConnection = mInputPorts[INPUTPORT_MOTION].mConnection; + BlendTreeConnection* motionConnection = m_inputPorts[INPUTPORT_MOTION].m_connection; if (motionConnection == nullptr) { RequestPoses(animGraphInstance); @@ -92,7 +92,7 @@ namespace EMotionFX // visualize it if (GetEMotionFX().GetIsInEditorMode() && GetCanVisualize(animGraphInstance)) { - actorInstance->DrawSkeleton(outputPose->GetPose(), mVisualizeColor); + actorInstance->DrawSkeleton(outputPose->GetPose(), m_visualizeColor); } return; } @@ -109,14 +109,14 @@ namespace EMotionFX // visualize it if (GetEMotionFX().GetIsInEditorMode() && GetCanVisualize(animGraphInstance)) { - actorInstance->DrawSkeleton(outputPose->GetPose(), mVisualizeColor); + actorInstance->DrawSkeleton(outputPose->GetPose(), m_visualizeColor); } return; } // get the time value float timeValue = 0.0f; - BlendTreeConnection* timeConnection = mInputPorts[INPUTPORT_TIME].mConnection; + BlendTreeConnection* timeConnection = m_inputPorts[INPUTPORT_TIME].m_connection; if (!timeConnection) // get it from the parameter value if there is no connection { timeValue = m_normalizedTimeValue; @@ -149,7 +149,7 @@ namespace EMotionFX // visualize it if (GetEMotionFX().GetIsInEditorMode() && GetCanVisualize(animGraphInstance)) { - actorInstance->DrawSkeleton(outputPose->GetPose(), mVisualizeColor); + actorInstance->DrawSkeleton(outputPose->GetPose(), m_visualizeColor); } } @@ -158,7 +158,7 @@ namespace EMotionFX void BlendTreeMotionFrameNode::PostUpdate(AnimGraphInstance* animGraphInstance, float timePassedInSeconds) { // clear the event buffer - if (mDisabled) + if (m_disabled) { RequestRefDatas(animGraphInstance); AnimGraphNodeData* uniqueData = FindOrCreateUniqueNodeData(animGraphInstance); @@ -169,14 +169,14 @@ namespace EMotionFX } // update the time input - BlendTreeConnection* timeConnection = mInputPorts[INPUTPORT_TIME].mConnection; + BlendTreeConnection* timeConnection = m_inputPorts[INPUTPORT_TIME].m_connection; if (timeConnection) { timeConnection->GetSourceNode()->PerformPostUpdate(animGraphInstance, timePassedInSeconds); } // update the input motion - BlendTreeConnection* motionConnection = mInputPorts[INPUTPORT_MOTION].mConnection; + BlendTreeConnection* motionConnection = m_inputPorts[INPUTPORT_MOTION].m_connection; if (motionConnection) { motionConnection->GetSourceNode()->PerformPostUpdate(animGraphInstance, timePassedInSeconds); @@ -195,7 +195,7 @@ namespace EMotionFX MotionInstance* motionInstance = motionNode->FindMotionInstance(animGraphInstance); if (triggerEvents && motionInstance) { - motionInstance->ExtractEventsNonLoop(uniqueData->mOldTime, uniqueData->mNewTime, &uniqueData->GetRefCountedData()->GetEventBuffer()); + motionInstance->ExtractEventsNonLoop(uniqueData->m_oldTime, uniqueData->m_newTime, &uniqueData->GetRefCountedData()->GetEventBuffer()); data->GetEventBuffer().UpdateEmitters(this); } } @@ -214,14 +214,14 @@ namespace EMotionFX void BlendTreeMotionFrameNode::Update(AnimGraphInstance* animGraphInstance, float timePassedInSeconds) { // update the time input - BlendTreeConnection* timeConnection = mInputPorts[INPUTPORT_TIME].mConnection; + BlendTreeConnection* timeConnection = m_inputPorts[INPUTPORT_TIME].m_connection; if (timeConnection) { UpdateIncomingNode(animGraphInstance, timeConnection->GetSourceNode(), timePassedInSeconds); } // update the input motion - BlendTreeConnection* motionConnection = mInputPorts[INPUTPORT_MOTION].mConnection; + BlendTreeConnection* motionConnection = m_inputPorts[INPUTPORT_MOTION].m_connection; if (motionConnection) { UpdateIncomingNode(animGraphInstance, motionConnection->GetSourceNode(), timePassedInSeconds); @@ -246,14 +246,14 @@ namespace EMotionFX { if (m_emitEventsFromStart) { - uniqueData->mNewTime = 0.0f; - uniqueData->mOldTime = 0.0f; + uniqueData->m_newTime = 0.0f; + uniqueData->m_oldTime = 0.0f; } else { const float newTimeValue = uniqueData->GetDuration() * timeValue; - uniqueData->mNewTime = newTimeValue; - uniqueData->mOldTime = newTimeValue; + uniqueData->m_newTime = newTimeValue; + uniqueData->m_oldTime = newTimeValue; } uniqueData->m_rewindRequested = false; } @@ -264,8 +264,8 @@ namespace EMotionFX uniqueData->Init(animGraphInstance, motionNode); uniqueData->SetCurrentPlayTime(uniqueData->GetDuration() * timeValue); - uniqueData->mOldTime = uniqueData->mNewTime; - uniqueData->mNewTime = uniqueData->GetDuration() * timeValue; + uniqueData->m_oldTime = uniqueData->m_newTime; + uniqueData->m_newTime = uniqueData->GetDuration() * timeValue; } else { diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeMotionFrameNode.h b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeMotionFrameNode.h index 6268012828..184a0bbc98 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeMotionFrameNode.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeMotionFrameNode.h @@ -55,14 +55,14 @@ namespace EMotionFX void Reset() override { - mOldTime = 0.0f; - mNewTime = 0.0f; + m_oldTime = 0.0f; + m_newTime = 0.0f; m_rewindRequested = false; } public: - float mOldTime; - float mNewTime; + float m_oldTime; + float m_newTime; bool m_rewindRequested; }; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeParameterNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeParameterNode.cpp index 8197cae9d0..ae24769584 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeParameterNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeParameterNode.cpp @@ -37,14 +37,14 @@ namespace EMotionFX void BlendTreeParameterNode::Reinit() { // Sort the parameter name mask in the way the parameters are stored in the anim graph. - SortParameterNames(mAnimGraph, m_parameterNames); + SortParameterNames(m_animGraph, m_parameterNames); // Iterate through the parameter name mask and find the corresponding cached value parameter indices. // This expects the parameter names to be sorted in the way the parameters are stored in the anim graph. m_parameterIndices.clear(); for (const AZStd::string& parameterName : m_parameterNames) { - const AZ::Outcome parameterIndex = mAnimGraph->FindValueParameterIndexByName(parameterName); + const AZ::Outcome parameterIndex = m_animGraph->FindValueParameterIndexByName(parameterName); // during removal of parameters, we could end up with a parameter that was removed until the node gets the mask updated if (parameterIndex.IsSuccess()) { @@ -57,7 +57,7 @@ namespace EMotionFX if (m_parameterIndices.empty()) { // Parameter mask is empty, add ports for all parameters. - const ValueParameterVector& valueParameters = mAnimGraph->RecursivelyGetValueParameters(); + const ValueParameterVector& valueParameters = m_animGraph->RecursivelyGetValueParameters(); const uint32 valueParameterCount = static_cast(valueParameters.size()); InitOutputPorts(valueParameterCount); @@ -66,12 +66,12 @@ namespace EMotionFX const ValueParameter* parameter = valueParameters[i]; SetOutputPortName(static_cast(i), parameter->GetName().c_str()); - mOutputPorts[i].mPortID = i; - mOutputPorts[i].ClearCompatibleTypes(); - mOutputPorts[i].mCompatibleTypes[0] = parameter->GetType(); + m_outputPorts[i].m_portId = i; + m_outputPorts[i].ClearCompatibleTypes(); + m_outputPorts[i].m_compatibleTypes[0] = parameter->GetType(); if (GetTypeSupportsFloat(parameter->GetType())) { - mOutputPorts[i].mCompatibleTypes[1] = MCore::AttributeFloat::TYPE_ID; + m_outputPorts[i].m_compatibleTypes[1] = MCore::AttributeFloat::TYPE_ID; } } } @@ -83,15 +83,15 @@ namespace EMotionFX for (size_t i = 0; i < parameterCount; ++i) { - const ValueParameter* parameter = mAnimGraph->FindValueParameter(m_parameterIndices[i]); + const ValueParameter* parameter = m_animGraph->FindValueParameter(m_parameterIndices[i]); SetOutputPortName(static_cast(i), parameter->GetName().c_str()); - mOutputPorts[i].mPortID = static_cast(i); - mOutputPorts[i].ClearCompatibleTypes(); - mOutputPorts[i].mCompatibleTypes[0] = parameter->GetType(); + m_outputPorts[i].m_portId = static_cast(i); + m_outputPorts[i].ClearCompatibleTypes(); + m_outputPorts[i].m_compatibleTypes[0] = parameter->GetType(); if (GetTypeSupportsFloat(parameter->GetType())) { - mOutputPorts[i].mCompatibleTypes[1] = MCore::AttributeFloat::TYPE_ID; + m_outputPorts[i].m_compatibleTypes[1] = MCore::AttributeFloat::TYPE_ID; } } } @@ -139,7 +139,7 @@ namespace EMotionFX if (m_parameterIndices.empty()) { // output all anim graph instance parameter values into the output ports - const uint32 numParameters = static_cast(mOutputPorts.size()); + const uint32 numParameters = static_cast(m_outputPorts.size()); for (uint32 i = 0; i < numParameters; ++i) { GetOutputValue(animGraphInstance, i)->InitFrom(animGraphInstance->GetParameterValue(i)); @@ -235,7 +235,7 @@ namespace EMotionFX void BlendTreeParameterNode::SetParameters(const AZStd::vector& parameterNames) { m_parameterNames = parameterNames; - if (mAnimGraph) + if (m_animGraph) { Reinit(); } @@ -299,7 +299,7 @@ namespace EMotionFX void BlendTreeParameterNode::RemoveParameterByName(const AZStd::string& parameterName) { m_parameterNames.erase(AZStd::remove(m_parameterNames.begin(), m_parameterNames.end(), parameterName), m_parameterNames.end()); - if (mAnimGraph) + if (m_animGraph) { Reinit(); } @@ -376,7 +376,7 @@ namespace EMotionFX // Add all connected parameters for (const AnimGraphNode::Port& port : GetOutputPorts()) { - if (port.mConnection) + if (port.m_connection) { parameterNames.emplace_back(port.GetNameString()); } @@ -435,10 +435,10 @@ namespace EMotionFX // Rename the actual output ports in all cases // (also when the parameter mask is empty and showing all parameters). - const size_t numOutputPorts = mOutputPorts.size(); + const size_t numOutputPorts = m_outputPorts.size(); for (size_t i = 0; i < numOutputPorts; ++i) { - AnimGraphNode::Port& outputPort = mOutputPorts[i]; + AnimGraphNode::Port& outputPort = m_outputPorts[i]; if (outputPort.GetNameString() == oldParameterName) { SetOutputPortName(static_cast(i), newParameterName.c_str()); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreePoseSubtractNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreePoseSubtractNode.cpp index c70dee1de0..be40cb6749 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreePoseSubtractNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreePoseSubtractNode.cpp @@ -78,7 +78,7 @@ namespace EMotionFX AnimGraphNode* subtractNode = GetInputNode(INPUTPORT_POSE_B); // If we are disabled and we have an input node, or if we are no disabled but have no subtract input. - if ((mDisabled && inputNode) || (!mDisabled && inputNode && !subtractNode)) + if ((m_disabled && inputNode) || (!m_disabled && inputNode && !subtractNode)) { OutputIncomingNode(animGraphInstance, inputNode); RequestPoses(animGraphInstance); @@ -86,7 +86,7 @@ namespace EMotionFX *outputPose = *inputNode->GetMainOutputPose(animGraphInstance); return; } - else if (mDisabled || !inputNode) // If we are disabled or have no inputs. + else if (m_disabled || !inputNode) // If we are disabled or have no inputs. { RequestPoses(animGraphInstance); AnimGraphPose* outputPose = GetOutputPose(animGraphInstance, OUTPUTPORT_POSE)->GetValue(); @@ -116,7 +116,7 @@ namespace EMotionFX if (GetEMotionFX().GetIsInEditorMode() && GetCanVisualize(animGraphInstance)) { AnimGraphPose* visualOutputPose = GetOutputPose(animGraphInstance, OUTPUTPORT_POSE)->GetValue(); - animGraphInstance->GetActorInstance()->DrawSkeleton(visualOutputPose->GetPose(), mVisualizeColor); + animGraphInstance->GetActorInstance()->DrawSkeleton(visualOutputPose->GetPose(), m_visualizeColor); } } @@ -127,14 +127,14 @@ namespace EMotionFX AnimGraphNode* subtractNode = GetInputNode(INPUTPORT_POSE_B); // If we are disabled and we have an input node, or if we are no disabled but have no subtract input. - if ((mDisabled && inputNode) || (!mDisabled && inputNode && !subtractNode)) + if ((m_disabled && inputNode) || (!m_disabled && inputNode && !subtractNode)) { UpdateIncomingNode(animGraphInstance, inputNode, timePassedInSeconds); AnimGraphNodeData* uniqueData = FindOrCreateUniqueNodeData(animGraphInstance); uniqueData->Init(animGraphInstance, inputNode); return; } - else if (mDisabled || (!inputNode && !subtractNode)) // If we are disabled or have no inputs. + else if (m_disabled || (!inputNode && !subtractNode)) // If we are disabled or have no inputs. { AnimGraphNodeData* uniqueData = FindOrCreateUniqueNodeData(animGraphInstance); uniqueData->Clear(); @@ -166,7 +166,7 @@ namespace EMotionFX data->ZeroTrajectoryDelta(); // We are disabled and have no input pose, so output no delta. - if (mDisabled || !nodeA) + if (m_disabled || !nodeA) { return; } @@ -191,7 +191,7 @@ namespace EMotionFX AnimGraphNode* inputNode = GetInputNode(INPUTPORT_POSE_A); AnimGraphNode* subtractNode = GetInputNode(INPUTPORT_POSE_B); - if (mDisabled) + if (m_disabled) { if (inputNode) { @@ -211,7 +211,7 @@ namespace EMotionFX { // Sync the input node to this node. inputNode->AutoSync(animGraphInstance, this, 0.0f, SYNCMODE_TRACKBASED, false); - if (animGraphInstance->GetIsObjectFlagEnabled(mObjectIndex, AnimGraphInstance::OBJECTFLAGS_SYNCED) == false) + if (animGraphInstance->GetIsObjectFlagEnabled(m_objectIndex, AnimGraphInstance::OBJECTFLAGS_SYNCED) == false) { inputNode->RecursiveSetUniqueDataFlag(animGraphInstance, AnimGraphInstance::OBJECTFLAGS_SYNCED, true); } @@ -255,7 +255,7 @@ namespace EMotionFX // We are disabled but had an input pose, just forward that in this case. // Do the same if we are not disabled but have no second pose. - if ((mDisabled && inputNode) || (!mDisabled && inputNode && !subtractNode)) + if ((m_disabled && inputNode) || (!m_disabled && inputNode && !subtractNode)) { inputNode->PerformPostUpdate(animGraphInstance, timePassedInSeconds); RequestRefDatas(animGraphInstance); @@ -267,7 +267,7 @@ namespace EMotionFX data->SetTrajectoryDeltaMirrored(inputData->GetTrajectoryDelta()); return; } - else if (mDisabled || !inputNode) // If we are disabled or have no inputs. + else if (m_disabled || !inputNode) // If we are disabled or have no inputs. { RequestRefDatas(animGraphInstance); AnimGraphNodeData* uniqueData = FindOrCreateUniqueNodeData(animGraphInstance); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreePoseSwitchNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreePoseSwitchNode.cpp index 0eb1f3d06a..78fe49894d 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreePoseSwitchNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreePoseSwitchNode.cpp @@ -85,7 +85,7 @@ namespace EMotionFX AnimGraphPose* outputPose; // if the decision port has no incomming connection, there is nothing we can do - if (mInputPorts[INPUTPORT_DECISIONVALUE].mConnection == nullptr) + if (m_inputPorts[INPUTPORT_DECISIONVALUE].m_connection == nullptr) { RequestPoses(animGraphInstance); outputPose = GetOutputPose(animGraphInstance, OUTPUTPORT_POSE)->GetValue(); @@ -98,7 +98,7 @@ namespace EMotionFX const int32 decisionValue = MCore::Clamp(GetInputNumberAsInt32(animGraphInstance, INPUTPORT_DECISIONVALUE), 0, 9); // max 10 cases // check if there is an incoming connection from this port - if (mInputPorts[INPUTPORT_POSE_0 + decisionValue].mConnection == nullptr) + if (m_inputPorts[INPUTPORT_POSE_0 + decisionValue].m_connection == nullptr) { RequestPoses(animGraphInstance); outputPose = GetOutputPose(animGraphInstance, OUTPUTPORT_POSE)->GetValue(); @@ -107,7 +107,7 @@ namespace EMotionFX // visualize it if (GetEMotionFX().GetIsInEditorMode() && GetCanVisualize(animGraphInstance)) { - animGraphInstance->GetActorInstance()->DrawSkeleton(outputPose->GetPose(), mVisualizeColor); + animGraphInstance->GetActorInstance()->DrawSkeleton(outputPose->GetPose(), m_visualizeColor); } return; } @@ -124,7 +124,7 @@ namespace EMotionFX // visualize it if (GetEMotionFX().GetIsInEditorMode() && GetCanVisualize(animGraphInstance)) { - animGraphInstance->GetActorInstance()->DrawSkeleton(outputPose->GetPose(), mVisualizeColor); + animGraphInstance->GetActorInstance()->DrawSkeleton(outputPose->GetPose(), m_visualizeColor); } } @@ -133,7 +133,7 @@ namespace EMotionFX void BlendTreePoseSwitchNode::Update(AnimGraphInstance* animGraphInstance, float timePassedInSeconds) { // if the decision port has no incomming connection, there is nothing we can do - if (mInputPorts[INPUTPORT_DECISIONVALUE].mConnection == nullptr) + if (m_inputPorts[INPUTPORT_DECISIONVALUE].m_connection == nullptr) { UniqueData* uniqueData = static_cast(FindOrCreateUniqueNodeData(animGraphInstance)); uniqueData->Clear(); @@ -141,13 +141,13 @@ namespace EMotionFX } // update the node that plugs into the decision value port - UpdateIncomingNode(animGraphInstance, mInputPorts[INPUTPORT_DECISIONVALUE].mConnection->GetSourceNode(), timePassedInSeconds); + UpdateIncomingNode(animGraphInstance, m_inputPorts[INPUTPORT_DECISIONVALUE].m_connection->GetSourceNode(), timePassedInSeconds); // get the index we choose const int32 decisionValue = MCore::Clamp(GetInputNumberAsInt32(animGraphInstance, INPUTPORT_DECISIONVALUE), 0, 9); // max 10 cases // check if there is an incoming connection from this port - if (mInputPorts[INPUTPORT_POSE_0 + decisionValue].mConnection == nullptr) + if (m_inputPorts[INPUTPORT_POSE_0 + decisionValue].m_connection == nullptr) { UniqueData* uniqueData = static_cast(FindOrCreateUniqueNodeData(animGraphInstance)); uniqueData->Clear(); @@ -155,14 +155,14 @@ namespace EMotionFX } // pass through the motion extraction of the selected node - AnimGraphNode* sourceNode = mInputPorts[INPUTPORT_POSE_0 + decisionValue].mConnection->GetSourceNode(); + AnimGraphNode* sourceNode = m_inputPorts[INPUTPORT_POSE_0 + decisionValue].m_connection->GetSourceNode(); // if our decision value changed since last time, specify that we want to resync // this basically means that the motion extraction delta will be zero for one frame UniqueData* uniqueData = static_cast(FindOrCreateUniqueNodeData(animGraphInstance)); - if (uniqueData->mDecisionIndex != decisionValue) + if (uniqueData->m_decisionIndex != decisionValue) { - uniqueData->mDecisionIndex = decisionValue; + uniqueData->m_decisionIndex = decisionValue; //sourceNode->RecursiveSetUniqueDataFlag(animGraphInstance, AnimGraphObjectData::FLAGS_RESYNC, true); } @@ -176,7 +176,7 @@ namespace EMotionFX void BlendTreePoseSwitchNode::PostUpdate(AnimGraphInstance* animGraphInstance, float timePassedInSeconds) { // if the decision port has no incomming connection, there is nothing we can do - if (mInputPorts[INPUTPORT_DECISIONVALUE].mConnection == nullptr) + if (m_inputPorts[INPUTPORT_DECISIONVALUE].m_connection == nullptr) { RequestRefDatas(animGraphInstance); UniqueData* uniqueData = static_cast(FindOrCreateUniqueNodeData(animGraphInstance)); @@ -187,13 +187,13 @@ namespace EMotionFX } // update the node that plugs into the decision value port - mInputPorts[INPUTPORT_DECISIONVALUE].mConnection->GetSourceNode()->PerformPostUpdate(animGraphInstance, timePassedInSeconds); + m_inputPorts[INPUTPORT_DECISIONVALUE].m_connection->GetSourceNode()->PerformPostUpdate(animGraphInstance, timePassedInSeconds); // get the index we choose const int32 decisionValue = MCore::Clamp(GetInputNumberAsInt32(animGraphInstance, INPUTPORT_DECISIONVALUE), 0, 9); // max 10 cases // check if there is an incoming connection from this port - if (mInputPorts[INPUTPORT_POSE_0 + decisionValue].mConnection == nullptr) + if (m_inputPorts[INPUTPORT_POSE_0 + decisionValue].m_connection == nullptr) { RequestRefDatas(animGraphInstance); UniqueData* uniqueData = static_cast(FindOrCreateUniqueNodeData(animGraphInstance)); @@ -204,7 +204,7 @@ namespace EMotionFX } // pass through the motion extraction of the selected node - AnimGraphNode* sourceNode = mInputPorts[INPUTPORT_POSE_0 + decisionValue].mConnection->GetSourceNode(); + AnimGraphNode* sourceNode = m_inputPorts[INPUTPORT_POSE_0 + decisionValue].m_connection->GetSourceNode(); sourceNode->PerformPostUpdate(animGraphInstance, timePassedInSeconds); // output the events of the source node we picked @@ -223,7 +223,7 @@ namespace EMotionFX void BlendTreePoseSwitchNode::TopDownUpdate(AnimGraphInstance* animGraphInstance, float timePassedInSeconds) { // if the decision port has no incomming connection, there is nothing we can do - if (mInputPorts[INPUTPORT_DECISIONVALUE].mConnection == nullptr) + if (m_inputPorts[INPUTPORT_DECISIONVALUE].m_connection == nullptr) { return; } @@ -232,7 +232,7 @@ namespace EMotionFX const int32 decisionValue = MCore::Clamp(GetInputNumberAsInt32(animGraphInstance, INPUTPORT_DECISIONVALUE), 0, 9); // max 10 cases // check if there is an incoming connection from this port - if (mInputPorts[INPUTPORT_POSE_0 + decisionValue].mConnection == nullptr) + if (m_inputPorts[INPUTPORT_POSE_0 + decisionValue].m_connection == nullptr) { return; } @@ -242,7 +242,7 @@ namespace EMotionFX HierarchicalSyncAllInputNodes(animGraphInstance, uniqueData); // top down update all incoming connections - for (BlendTreeConnection* connection : mConnections) + for (BlendTreeConnection* connection : m_connections) { connection->GetSourceNode()->PerformTopDownUpdate(animGraphInstance, timePassedInSeconds); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreePoseSwitchNode.h b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreePoseSwitchNode.h index 1b8c958c27..9e24eff232 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreePoseSwitchNode.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreePoseSwitchNode.h @@ -67,7 +67,7 @@ namespace EMotionFX : AnimGraphNodeData(node, animGraphInstance) {} public: - int32 mDecisionIndex = -1; + int32 m_decisionIndex = -1; }; BlendTreePoseSwitchNode(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeRagdollNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeRagdollNode.cpp index f62d569a16..1d3c623215 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeRagdollNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeRagdollNode.cpp @@ -30,10 +30,10 @@ namespace EMotionFX void BlendTreeRagdollNode::UniqueData::Update() { - BlendTreeRagdollNode* ragdollNode = azdynamic_cast(mObject); + BlendTreeRagdollNode* ragdollNode = azdynamic_cast(m_object); AZ_Assert(ragdollNode, "Unique data linked to incorrect node type."); - const Actor* actor = mAnimGraphInstance->GetActorInstance()->GetActor(); + const Actor* actor = m_animGraphInstance->GetActorInstance()->GetActor(); const Skeleton* skeleton = actor->GetSkeleton(); const size_t jointCount = skeleton->GetNumNodes(); @@ -54,7 +54,7 @@ namespace EMotionFX } // Check if we selected the ragdoll root node to be added to the simulation. - const ActorInstance* actorInstance = mAnimGraphInstance->GetActorInstance(); + const ActorInstance* actorInstance = m_animGraphInstance->GetActorInstance(); const RagdollInstance* ragdollInstance = actorInstance->GetRagdollInstance(); m_isRagdollRootNodeSimulated = false; if (ragdollInstance) @@ -126,7 +126,7 @@ namespace EMotionFX RequestRefDatas(animGraphInstance); AnimGraphRefCountedData* data = uniqueData->GetRefCountedData(); - if (mDisabled) + if (m_disabled) { data->ClearEventBuffer(); data->ZeroTrajectoryDelta(); @@ -170,13 +170,13 @@ namespace EMotionFX if (ragdollInstance && motionExtractionNode) { // Move the trajectory node based on the ragdoll's movement. - trajectoryDelta.mPosition = ragdollInstance->GetTrajectoryDeltaPos(); + trajectoryDelta.m_position = ragdollInstance->GetTrajectoryDeltaPos(); // Do the same for rotation, but extract and apply z rotation only to the trajectory node. - trajectoryDelta.mRotation = ragdollInstance->GetTrajectoryDeltaRot(); - trajectoryDelta.mRotation.SetX(0.0f); - trajectoryDelta.mRotation.SetY(0.0f); - trajectoryDelta.mRotation.Normalize(); + trajectoryDelta.m_rotation = ragdollInstance->GetTrajectoryDeltaRot(); + trajectoryDelta.m_rotation.SetX(0.0f); + trajectoryDelta.m_rotation.SetY(0.0f); + trajectoryDelta.m_rotation.Normalize(); } data->SetTrajectoryDelta(trajectoryDelta); @@ -207,7 +207,7 @@ namespace EMotionFX } // As we already forwarded the target pose at this point, we can just return in case the node is disabled. - if (mDisabled) + if (m_disabled) { return; } @@ -215,7 +215,7 @@ namespace EMotionFX Pose& outputPose = animGraphOutputPose->GetPose(); if (GetCanVisualize(animGraphInstance)) { - actorInstance->DrawSkeleton(outputPose, mVisualizeColor); + actorInstance->DrawSkeleton(outputPose, m_visualizeColor); } if (HasConnectionAtInputPort(INPUTPORT_ACTIVATE)) @@ -264,7 +264,7 @@ namespace EMotionFX Transform newGlobalTransform( currentRagdollRootNodeState.m_position, currentRagdollRootNodeState.m_orientation, - outputPose.GetWorldSpaceTransform(jointIndex).mScale); + outputPose.GetWorldSpaceTransform(jointIndex).m_scale); #else Transform newGlobalTransform( currentRagdollRootNodeState.m_position, @@ -298,7 +298,7 @@ namespace EMotionFX Transform newGlobalTransform = Transform( currentRagdollNodeState.m_position, currentRagdollNodeState.m_orientation, - outputPose.GetWorldSpaceTransform(jointIndex).mScale); + outputPose.GetWorldSpaceTransform(jointIndex).m_scale); #else Transform newGlobalTransform = Transform( currentRagdollNodeState.m_position, @@ -315,12 +315,12 @@ namespace EMotionFX Transform globalTransform = Transform( currentRagdollNodeState.m_position, currentRagdollNodeState.m_orientation, - outputPose.GetWorldSpaceTransform(jointIndex).mScale); + outputPose.GetWorldSpaceTransform(jointIndex).m_scale); Transform parentGlobalTransform = Transform( currentParentRagdollNodeState.m_position, currentParentRagdollNodeState.m_orientation, - outputPose.GetWorldSpaceTransform(ragdollParentJoint->GetNodeIndex()).mScale); + outputPose.GetWorldSpaceTransform(ragdollParentJoint->GetNodeIndex()).m_scale); #else Transform globalTransform = Transform( currentRagdollNodeState.m_position, @@ -343,15 +343,15 @@ namespace EMotionFX // Set the target pose for the selected and thus simulated joints in the anim graph node has a target pose connected to its input port. // Set the local space transform for powered ragdoll nodes. const Transform& localTransform = targetPose->GetLocalSpaceTransform(jointIndex); - targetRagdollNodeState.m_position = localTransform.mPosition; - targetRagdollNodeState.m_orientation = localTransform.mRotation; + targetRagdollNodeState.m_position = localTransform.m_position; + targetRagdollNodeState.m_orientation = localTransform.m_rotation; } else { // We do not have a target pose connected to the input port, just forward what is currently in the output pose (bind pose). const Transform& localTransform = outputPose.GetLocalSpaceTransform(jointIndex); - targetRagdollNodeState.m_position = localTransform.mPosition; - targetRagdollNodeState.m_orientation = localTransform.mRotation; + targetRagdollNodeState.m_position = localTransform.m_position; + targetRagdollNodeState.m_orientation = localTransform.m_rotation; } } else diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeRagdollStrengthModifierNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeRagdollStrengthModifierNode.cpp index dbf6009c9a..ef5767eef8 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeRagdollStrengthModifierNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeRagdollStrengthModifierNode.cpp @@ -27,11 +27,11 @@ namespace EMotionFX void BlendTreeRagdollStrenghModifierNode::UniqueData::Update() { - BlendTreeRagdollStrenghModifierNode* ragdollModifierNode = azdynamic_cast(mObject); + BlendTreeRagdollStrenghModifierNode* ragdollModifierNode = azdynamic_cast(m_object); AZ_Assert(ragdollModifierNode, "Unique data linked to incorrect node type."); const AZStd::vector& modifiedJointNames = ragdollModifierNode->GetModifiedJointNames(); - const Actor* actor = mAnimGraphInstance->GetActorInstance()->GetActor(); + const Actor* actor = m_animGraphInstance->GetActorInstance()->GetActor(); AnimGraphPropertyUtils::ReinitJointIndices(actor, modifiedJointNames, m_modifiedJointIndices); } @@ -87,7 +87,7 @@ namespace EMotionFX } // As we already forwarded the input pose at this point, we can just return in case the node is disabled. - if (mDisabled) + if (m_disabled) { return; } @@ -95,7 +95,7 @@ namespace EMotionFX Pose& outputPose = animGraphOutputPose->GetPose(); if (GetCanVisualize(animGraphInstance)) { - actorInstance->DrawSkeleton(outputPose, mVisualizeColor); + actorInstance->DrawSkeleton(outputPose, m_visualizeColor); } UniqueData* uniqueData = static_cast(FindOrCreateUniqueNodeData(animGraphInstance)); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeRangeRemapperNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeRangeRemapperNode.cpp index 1672bd6177..9215db80a1 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeRangeRemapperNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeRangeRemapperNode.cpp @@ -72,8 +72,8 @@ namespace EMotionFX UpdateAllIncomingNodes(animGraphInstance, timePassedInSeconds); // if there are no incoming connections, there is nothing to do - const size_t numConnections = mConnections.size(); - if (numConnections == 0 || mDisabled) + const size_t numConnections = m_connections.size(); + if (numConnections == 0 || m_disabled) { if (numConnections > 0) // pass the input value as output in case we are disabled { @@ -89,7 +89,7 @@ namespace EMotionFX float x = GetInputNumberAsFloat(animGraphInstance, INPUTPORT_X); // output the original input, so without remapping, if this node is disabled - if (mDisabled) + if (m_disabled) { GetOutputFloat(animGraphInstance, OUTPUTPORT_RESULT)->SetValue(x); return; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeRaycastNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeRaycastNode.cpp index e9563cfb6f..2d11abc4ff 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeRaycastNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeRaycastNode.cpp @@ -30,7 +30,7 @@ namespace EMotionFX SetupOutputPort("Normal", OUTPUTPORT_NORMAL, MCore::AttributeVector3::TYPE_ID, PORTID_OUTPUT_NORMAL); SetupOutputPort("Intersected", OUTPUTPORT_INTERSECTED, MCore::AttributeFloat::TYPE_ID, PORTID_OUTPUT_INTERSECTED); - if (mAnimGraph) + if (m_animGraph) { Reinit(); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeRotationLimitNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeRotationLimitNode.cpp index d4eaf9fcf1..cf8ebd2a46 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeRotationLimitNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeRotationLimitNode.cpp @@ -155,13 +155,13 @@ namespace EMotionFX void BlendTreeRotationLimitNode::ExecuteMathLogic(EMotionFX::AnimGraphInstance * animGraphInstance) { // If there are no incoming connections, there is nothing to do - if (mConnections.empty()) + if (m_connections.empty()) { return; } m_constraintTransformRotationAngles.SetTwistAxis(m_twistAxis); - m_constraintTransformRotationAngles.GetTransform().mRotation = GetInputQuaternion(animGraphInstance, INPUTPORT_ROTATION)->GetValue(); + m_constraintTransformRotationAngles.GetTransform().m_rotation = GetInputQuaternion(animGraphInstance, INPUTPORT_ROTATION)->GetValue(); m_constraintTransformRotationAngles.SetMaxRotationAngles(AZ::Vector2(GetRotationLimitY().m_max, GetRotationLimitX().m_max)); m_constraintTransformRotationAngles.SetMinRotationAngles(AZ::Vector2(GetRotationLimitY().m_min, GetRotationLimitX().m_min)); @@ -169,7 +169,7 @@ namespace EMotionFX m_constraintTransformRotationAngles.SetMaxTwistAngle(GetRotationLimitZ().m_max); m_constraintTransformRotationAngles.Execute(); - GetOutputQuaternion(animGraphInstance, OUTPUTPORT_RESULT_QUATERNION)->SetValue(m_constraintTransformRotationAngles.GetTransform().mRotation); + GetOutputQuaternion(animGraphInstance, OUTPUTPORT_RESULT_QUATERNION)->SetValue(m_constraintTransformRotationAngles.GetTransform().m_rotation); } void BlendTreeRotationLimitNode::Reflect(AZ::ReflectContext* context) diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeRotationMath2Node.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeRotationMath2Node.cpp index 1f15333561..effe6c8477 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeRotationMath2Node.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeRotationMath2Node.cpp @@ -33,7 +33,7 @@ namespace EMotionFX InitOutputPorts(1); SetupOutputPort("Rotation", INPUTPORT_X, MCore::AttributeQuaternion::TYPE_ID, PORTID_OUTPUT_QUATERNION); - if (mAnimGraph) + if (m_animGraph) { Reinit(); } @@ -99,7 +99,7 @@ namespace EMotionFX void BlendTreeRotationMath2Node::ExecuteMathLogic(EMotionFX::AnimGraphInstance * animGraphInstance) { // If there are no incoming connections, there is nothing to do - if (mConnections.empty()) + if (m_connections.empty()) { return; } @@ -107,7 +107,7 @@ namespace EMotionFX // If both x and y inputs have connections AZ::Quaternion x = m_defaultValue; AZ::Quaternion y = x; - if (mConnections.size() == 2) + if (m_connections.size() == 2) { x = GetInputQuaternion(animGraphInstance, INPUTPORT_X)->GetValue(); @@ -116,13 +116,13 @@ namespace EMotionFX else // Only x or y is connected { // If only x has something plugged in - if (mConnections[0]->GetTargetPort() == INPUTPORT_X) + if (m_connections[0]->GetTargetPort() == INPUTPORT_X) { x = GetInputQuaternion(animGraphInstance, INPUTPORT_X)->GetValue(); } else // Only y has an input { - MCORE_ASSERT(mConnections[0]->GetTargetPort() == INPUTPORT_Y); + MCORE_ASSERT(m_connections[0]->GetTargetPort() == INPUTPORT_Y); y = GetInputQuaternion(animGraphInstance, INPUTPORT_Y)->GetValue(); } } @@ -138,7 +138,7 @@ namespace EMotionFX void BlendTreeRotationMath2Node::SetMathFunction(EMathFunction func) { m_mathFunction = func; - if (mAnimGraph) + if (m_animGraph) { Reinit(); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeSetTransformNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeSetTransformNode.cpp index 0817b95614..87bd31d942 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeSetTransformNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeSetTransformNode.cpp @@ -32,10 +32,10 @@ namespace EMotionFX void BlendTreeSetTransformNode::UniqueData::Update() { - BlendTreeSetTransformNode* transformNode = azdynamic_cast(mObject); + BlendTreeSetTransformNode* transformNode = azdynamic_cast(m_object); AZ_Assert(transformNode, "Unique data linked to incorrect node type."); - ActorInstance* actorInstance = mAnimGraphInstance->GetActorInstance(); + ActorInstance* actorInstance = m_animGraphInstance->GetActorInstance(); Actor* actor = actorInstance->GetActor(); m_nodeIndex = InvalidIndex; @@ -112,7 +112,7 @@ namespace EMotionFX OutputAllIncomingNodes(animGraphInstance); // make sure we have at least an input pose, otherwise output the bind pose - if (GetInputPort(INPUTPORT_POSE).mConnection) + if (GetInputPort(INPUTPORT_POSE).m_connection) { const AnimGraphPose* inputPose = GetInputPose(animGraphInstance, INPUTPORT_POSE)->GetValue(); RequestPoses(animGraphInstance); @@ -154,14 +154,14 @@ namespace EMotionFX AZ::Vector3 translation; if (TryGetInputVector3(animGraphInstance, INPUTPORT_TRANSLATION, translation)) { - outputTransform.mPosition = translation; + outputTransform.m_position = translation; } // process the rotation - if (GetInputPort(INPUTPORT_ROTATION).mConnection) + if (GetInputPort(INPUTPORT_ROTATION).m_connection) { const AZ::Quaternion& rotation = GetInputQuaternion(animGraphInstance, INPUTPORT_ROTATION)->GetValue(); - outputTransform.mRotation = rotation; + outputTransform.m_rotation = rotation; } // process the scale @@ -170,7 +170,7 @@ namespace EMotionFX AZ::Vector3 scale; if (TryGetInputVector3(animGraphInstance, INPUTPORT_SCALE, scale)) { - outputTransform.mScale = scale; + outputTransform.m_scale = scale; } ) @@ -197,7 +197,7 @@ namespace EMotionFX // visualize it if (GetEMotionFX().GetIsInEditorMode() && GetCanVisualize(animGraphInstance)) { - animGraphInstance->GetActorInstance()->DrawSkeleton(outputPose->GetPose(), mVisualizeColor); + animGraphInstance->GetActorInstance()->DrawSkeleton(outputPose->GetPose(), m_visualizeColor); } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeSimulatedObjectNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeSimulatedObjectNode.cpp index d54ef4ffd4..4c2f2c8f31 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeSimulatedObjectNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeSimulatedObjectNode.cpp @@ -38,7 +38,7 @@ namespace EMotionFX void BlendTreeSimulatedObjectNode::UniqueData::Update() { - BlendTreeSimulatedObjectNode* simulatedObjectNode = azdynamic_cast(mObject); + BlendTreeSimulatedObjectNode* simulatedObjectNode = azdynamic_cast(m_object); AZ_Assert(simulatedObjectNode, "Unique data linked to incorrect node type."); const bool solverInitResult = simulatedObjectNode->InitSolvers(GetAnimGraphInstance(), this); @@ -68,7 +68,7 @@ namespace EMotionFX void BlendTreeSimulatedObjectNode::Reinit() { - if (!mAnimGraph) + if (!m_animGraph) { return; } @@ -212,7 +212,7 @@ namespace EMotionFX AnimGraphPose* outputPose; // If nothing is connected to the input pose, output a bind pose. - if (!GetInputPort(INPUTPORT_POSE).mConnection) + if (!GetInputPort(INPUTPORT_POSE).m_connection) { RequestPoses(animGraphInstance); outputPose = GetOutputPose(animGraphInstance, OUTPUTPORT_POSE)->GetValue(); @@ -223,14 +223,14 @@ namespace EMotionFX // Check whether we are active or not. bool isActive = true; - if (GetInputPort(INPUTPORT_ACTIVE).mConnection) + if (GetInputPort(INPUTPORT_ACTIVE).m_connection) { OutputIncomingNode(animGraphInstance, GetInputNode(INPUTPORT_ACTIVE)); isActive = GetInputNumberAsBool(animGraphInstance, INPUTPORT_ACTIVE); } // If we're not active or if this node is disabled or it is optimized for server, we can skip all calculations and just output the input pose. - if (!isActive || mDisabled || GetEMotionFX().GetEnableServerOptimization()) + if (!isActive || m_disabled || GetEMotionFX().GetEnableServerOptimization()) { OutputIncomingNode(animGraphInstance, GetInputNode(INPUTPORT_POSE)); const AnimGraphPose* inputPose = GetInputPose(animGraphInstance, INPUTPORT_POSE)->GetValue(); @@ -291,7 +291,7 @@ namespace EMotionFX { for (const Simulation* sim : uniqueData->m_simulations) { - sim->m_solver.DebugRender(outputPose->GetPose(), m_collisionDetection, true, mVisualizeColor); + sim->m_solver.DebugRender(outputPose->GetPose(), m_collisionDetection, true, m_visualizeColor); } } } @@ -308,15 +308,15 @@ namespace EMotionFX void BlendTreeSimulatedObjectNode::AdjustParticles(const SpringSolver::ParticleAdjustFunction& func) { - if (!mAnimGraph) + if (!m_animGraph) { return; } - const size_t numInstances = mAnimGraph->GetNumAnimGraphInstances(); + const size_t numInstances = m_animGraph->GetNumAnimGraphInstances(); for (size_t i = 0; i < numInstances; ++i) { - AnimGraphInstance* animGraphInstance = mAnimGraph->GetAnimGraphInstance(i); + AnimGraphInstance* animGraphInstance = m_animGraph->GetAnimGraphInstance(i); UniqueData* uniqueData = static_cast(animGraphInstance->FindOrCreateUniqueNodeData(this)); if (!uniqueData) { @@ -332,15 +332,15 @@ namespace EMotionFX void BlendTreeSimulatedObjectNode::OnPropertyChanged(const PropertyChangeFunction& func) { - if (!mAnimGraph) + if (!m_animGraph) { return; } - const size_t numInstances = mAnimGraph->GetNumAnimGraphInstances(); + const size_t numInstances = m_animGraph->GetNumAnimGraphInstances(); for (size_t i = 0; i < numInstances; ++i) { - AnimGraphInstance* animGraphInstance = mAnimGraph->GetAnimGraphInstance(i); + AnimGraphInstance* animGraphInstance = m_animGraph->GetAnimGraphInstance(i); UniqueData* uniqueData = static_cast(animGraphInstance->FindOrCreateUniqueNodeData(this)); if (!uniqueData) { diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeSmoothingNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeSmoothingNode.cpp index b835cbc12b..77703ea467 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeSmoothingNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeSmoothingNode.cpp @@ -27,12 +27,12 @@ namespace EMotionFX void BlendTreeSmoothingNode::UniqueData::Update() { - BlendTreeSmoothingNode* smoothingNode = azdynamic_cast(mObject); + BlendTreeSmoothingNode* smoothingNode = azdynamic_cast(m_object); AZ_Assert(smoothingNode, "Unique data linked to incorrect node type."); if (!smoothingNode->GetInputNode(BlendTreeSmoothingNode::INPUTPORT_DEST)) { - mCurrentValue = 0.0f; + m_currentValue = 0.0f; } } @@ -91,7 +91,7 @@ namespace EMotionFX UniqueData* uniqueData = static_cast(FindOrCreateUniqueNodeData(animGraphInstance)); // if there are no incoming connections, there is nothing to do - if (mConnections.size() == 0) + if (m_connections.size() == 0) { GetOutputFloat(animGraphInstance, OUTPUTPORT_RESULT)->SetValue(0.0f); return; @@ -100,29 +100,29 @@ namespace EMotionFX // if we are disabled, output the dest value directly //OutputIncomingNode( animGraphInstance, GetInputNode(INPUTPORT_DEST) ); const float destValue = GetInputNumberAsFloat(animGraphInstance, INPUTPORT_DEST); - if (mDisabled) + if (m_disabled) { GetOutputFloat(animGraphInstance, OUTPUTPORT_RESULT)->SetValue(destValue); return; } // perform interpolation - const float sourceValue = uniqueData->mCurrentValue; - const float interpolationSpeed = m_interpolationSpeed * uniqueData->mFrameDeltaTime * 10.0f; + const float sourceValue = uniqueData->m_currentValue; + const float interpolationSpeed = m_interpolationSpeed * uniqueData->m_frameDeltaTime * 10.0f; const float interpolationResult = (interpolationSpeed < 0.99999f) ? MCore::LinearInterpolate(sourceValue, destValue, interpolationSpeed) : destValue; // If the interpolation result is close to the dest value within the tolerance, snap to the destination value. if (AZ::IsClose((interpolationResult - destValue), 0.0f, m_snapTolerance)) { - uniqueData->mCurrentValue = destValue; + uniqueData->m_currentValue = destValue; } else { // pass the interpolated result to the output port and the current value of the unique data - uniqueData->mCurrentValue = interpolationResult; + uniqueData->m_currentValue = interpolationResult; } GetOutputFloat(animGraphInstance, OUTPUTPORT_RESULT)->SetValue(interpolationResult); - uniqueData->mFrameDeltaTime = timePassedInSeconds; + uniqueData->m_frameDeltaTime = timePassedInSeconds; } @@ -135,13 +135,13 @@ namespace EMotionFX // check if the current value needs to be reset to the input or the start value when rewinding the node if (m_useStartValue) { - uniqueData->mCurrentValue = m_startValue; + uniqueData->m_currentValue = m_startValue; } else { // set the current value to the current input value UpdateAllIncomingNodes(animGraphInstance, 0.0f); - uniqueData->mCurrentValue = GetInputNumberAsFloat(animGraphInstance, INPUTPORT_DEST); + uniqueData->m_currentValue = GetInputNumberAsFloat(animGraphInstance, INPUTPORT_DEST); } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeSmoothingNode.h b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeSmoothingNode.h index ef16fd397f..e0c65f9fe0 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeSmoothingNode.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeSmoothingNode.h @@ -48,8 +48,8 @@ namespace EMotionFX void Update() override; public: - float mFrameDeltaTime = 0.0f; - float mCurrentValue = 0.0f; + float m_frameDeltaTime = 0.0f; + float m_currentValue = 0.0f; }; BlendTreeSmoothingNode(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeTransformNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeTransformNode.cpp index 07f3256a35..4b6a42b785 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeTransformNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeTransformNode.cpp @@ -33,15 +33,15 @@ namespace EMotionFX void BlendTreeTransformNode::UniqueData::Update() { - BlendTreeTransformNode* transformNode = azdynamic_cast(mObject); + BlendTreeTransformNode* transformNode = azdynamic_cast(m_object); AZ_Assert(transformNode, "Unique data linked to incorrect node type."); - const ActorInstance* actorInstance = mAnimGraphInstance->GetActorInstance(); + const ActorInstance* actorInstance = m_animGraphInstance->GetActorInstance(); const Actor* actor = actorInstance->GetActor(); const AZStd::string& targetJointName = transformNode->GetTargetJointName(); - mNodeIndex = InvalidIndex; + m_nodeIndex = InvalidIndex; SetHasError(true); if (!targetJointName.empty()) @@ -49,7 +49,7 @@ namespace EMotionFX const Node* joint = actor->GetSkeleton()->FindNodeByName(targetJointName); if (joint) { - mNodeIndex = joint->GetNodeIndex(); + m_nodeIndex = joint->GetNodeIndex(); SetHasError(false); } } @@ -132,7 +132,7 @@ namespace EMotionFX } // make sure we have at least an input pose, otherwise output the bind pose - if (GetInputPort(INPUTPORT_POSE).mConnection == nullptr) + if (GetInputPort(INPUTPORT_POSE).m_connection == nullptr) { RequestPoses(animGraphInstance); outputPose = GetOutputPose(animGraphInstance, OUTPUTPORT_RESULT)->GetValue(); @@ -148,48 +148,48 @@ namespace EMotionFX } // get the local transform from our node - Transform inputTransform = outputPose->GetPose().GetLocalSpaceTransform(uniqueData->mNodeIndex); + Transform inputTransform = outputPose->GetPose().GetLocalSpaceTransform(uniqueData->m_nodeIndex); Transform outputTransform = inputTransform; // process the rotation - if (GetInputPort(INPUTPORT_ROTATE_AMOUNT).mConnection) + if (GetInputPort(INPUTPORT_ROTATE_AMOUNT).m_connection) { OutputIncomingNode(animGraphInstance, GetInputNode(INPUTPORT_ROTATE_AMOUNT)); const float rotateFactor = MCore::Clamp(GetInputNumberAsFloat(animGraphInstance, INPUTPORT_ROTATE_AMOUNT), 0.0f, 1.0f); const AZ::Vector3 newAngles = MCore::LinearInterpolate(m_minRotation, m_maxRotation, rotateFactor); - outputTransform.mRotation = inputTransform.mRotation * MCore::AzEulerAnglesToAzQuat(MCore::Math::DegreesToRadians(newAngles.GetX()), + outputTransform.m_rotation = inputTransform.m_rotation * MCore::AzEulerAnglesToAzQuat(MCore::Math::DegreesToRadians(newAngles.GetX()), MCore::Math::DegreesToRadians(newAngles.GetY()), MCore::Math::DegreesToRadians(newAngles.GetZ())); } // process the translation - if (GetInputPort(INPUTPORT_TRANSLATE_AMOUNT).mConnection) + if (GetInputPort(INPUTPORT_TRANSLATE_AMOUNT).m_connection) { OutputIncomingNode(animGraphInstance, GetInputNode(INPUTPORT_TRANSLATE_AMOUNT)); const float factor = MCore::Clamp(GetInputNumberAsFloat(animGraphInstance, INPUTPORT_TRANSLATE_AMOUNT), 0.0f, 1.0f); const AZ::Vector3 newValue = MCore::LinearInterpolate(m_minTranslation, m_maxTranslation, factor); - outputTransform.mPosition = inputTransform.mPosition + newValue; + outputTransform.m_position = inputTransform.m_position + newValue; } // process the scale EMFX_SCALECODE ( - if (GetInputPort(INPUTPORT_SCALE_AMOUNT).mConnection) + if (GetInputPort(INPUTPORT_SCALE_AMOUNT).m_connection) { OutputIncomingNode(animGraphInstance, GetInputNode(INPUTPORT_SCALE_AMOUNT)); const float factor = MCore::Clamp(GetInputNumberAsFloat(animGraphInstance, INPUTPORT_SCALE_AMOUNT), 0.0f, 1.0f); const AZ::Vector3 newValue = MCore::LinearInterpolate(m_minScale, m_maxScale, factor); - outputTransform.mScale = inputTransform.mScale + newValue; + outputTransform.m_scale = inputTransform.m_scale + newValue; } ) // update the transformation of the node - outputPose->GetPose().SetLocalSpaceTransform(uniqueData->mNodeIndex, outputTransform); + outputPose->GetPose().SetLocalSpaceTransform(uniqueData->m_nodeIndex, outputTransform); // visualize it if (GetEMotionFX().GetIsInEditorMode() && GetCanVisualize(animGraphInstance)) { - animGraphInstance->GetActorInstance()->DrawSkeleton(outputPose->GetPose(), mVisualizeColor); + animGraphInstance->GetActorInstance()->DrawSkeleton(outputPose->GetPose(), m_visualizeColor); } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeTransformNode.h b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeTransformNode.h index 1d337fa6a1..b632041f77 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeTransformNode.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeTransformNode.h @@ -70,7 +70,7 @@ namespace EMotionFX void Update() override; public: - size_t mNodeIndex = InvalidIndex; + size_t m_nodeIndex = InvalidIndex; }; BlendTreeTransformNode(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeTwoLinkIKNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeTwoLinkIKNode.cpp index 1054cef095..9a91a59390 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeTwoLinkIKNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeTwoLinkIKNode.cpp @@ -31,20 +31,20 @@ namespace EMotionFX void BlendTreeTwoLinkIKNode::UniqueData::Update() { - BlendTreeTwoLinkIKNode* twoLinkIKNode = azdynamic_cast(mObject); + BlendTreeTwoLinkIKNode* twoLinkIKNode = azdynamic_cast(m_object); AZ_Assert(twoLinkIKNode, "Unique data linked to incorrect node type."); - const ActorInstance* actorInstance = mAnimGraphInstance->GetActorInstance(); + const ActorInstance* actorInstance = m_animGraphInstance->GetActorInstance(); const Actor* actor = actorInstance->GetActor(); const Skeleton* skeleton = actor->GetSkeleton(); // don't update the next time again - mNodeIndexA = InvalidIndex; - mNodeIndexB = InvalidIndex; - mNodeIndexC = InvalidIndex; - mAlignNodeIndex = InvalidIndex; - mBendDirNodeIndex = InvalidIndex; - mEndEffectorNodeIndex = InvalidIndex; + m_nodeIndexA = InvalidIndex; + m_nodeIndexB = InvalidIndex; + m_nodeIndexC = InvalidIndex; + m_alignNodeIndex = InvalidIndex; + m_bendDirNodeIndex = InvalidIndex; + m_endEffectorNodeIndex = InvalidIndex; SetHasError(true); // Find the end joint. @@ -58,18 +58,18 @@ namespace EMotionFX { return; } - mNodeIndexC = jointC->GetNodeIndex(); + m_nodeIndexC = jointC->GetNodeIndex(); // Get the second joint. - mNodeIndexB = jointC->GetParentIndex(); - if (mNodeIndexB == InvalidIndex) + m_nodeIndexB = jointC->GetParentIndex(); + if (m_nodeIndexB == InvalidIndex) { return; } // Get the third joint. - mNodeIndexA = skeleton->GetNode(mNodeIndexB)->GetParentIndex(); - if (mNodeIndexA == InvalidIndex) + m_nodeIndexA = skeleton->GetNode(m_nodeIndexB)->GetParentIndex(); + if (m_nodeIndexA == InvalidIndex) { return; } @@ -79,7 +79,7 @@ namespace EMotionFX const Node* endEffectorJoint = skeleton->FindNodeByName(endEffectorJointName); if (endEffectorJoint) { - mEndEffectorNodeIndex = endEffectorJoint->GetNodeIndex(); + m_endEffectorNodeIndex = endEffectorJoint->GetNodeIndex(); } // Find the bend direction joint. @@ -87,12 +87,12 @@ namespace EMotionFX const Node* bendDirJoint = skeleton->FindNodeByName(bendDirJointName); if (bendDirJoint) { - mBendDirNodeIndex = bendDirJoint->GetNodeIndex(); + m_bendDirNodeIndex = bendDirJoint->GetNodeIndex(); } // lookup the actor instance to get the alignment node from const NodeAlignmentData& alignToJointData = twoLinkIKNode->GetAlignToJointData(); - const ActorInstance* alignInstance = mAnimGraphInstance->FindActorInstanceFromParentDepth(alignToJointData.second); + const ActorInstance* alignInstance = m_animGraphInstance->FindActorInstanceFromParentDepth(alignToJointData.second); if (alignInstance) { if (!alignToJointData.first.empty()) @@ -100,7 +100,7 @@ namespace EMotionFX const Node* alignJoint = alignInstance->GetActor()->GetSkeleton()->FindNodeByName(alignToJointData.first.c_str()); if (alignJoint) { - mAlignNodeIndex = alignJoint->GetNodeIndex(); + m_alignNodeIndex = alignJoint->GetNodeIndex(); } } } @@ -210,7 +210,7 @@ namespace EMotionFX AnimGraphPose* outputPose; // make sure we have at least an input pose, otherwise output the bind pose - if (GetInputPort(INPUTPORT_POSE).mConnection == nullptr) + if (GetInputPort(INPUTPORT_POSE).m_connection == nullptr) { RequestPoses(animGraphInstance); outputPose = GetOutputPose(animGraphInstance, OUTPUTPORT_POSE)->GetValue(); @@ -221,7 +221,7 @@ namespace EMotionFX // get the weight float weight = 1.0f; - if (GetInputPort(INPUTPORT_WEIGHT).mConnection) + if (GetInputPort(INPUTPORT_WEIGHT).m_connection) { OutputIncomingNode(animGraphInstance, GetInputNode(INPUTPORT_WEIGHT)); weight = GetInputNumberAsFloat(animGraphInstance, INPUTPORT_WEIGHT); @@ -229,7 +229,7 @@ namespace EMotionFX } // if the IK weight is near zero, we can skip all calculations and act like a pass-trough node - if (weight < MCore::Math::epsilon || mDisabled) + if (weight < MCore::Math::epsilon || m_disabled) { OutputIncomingNode(animGraphInstance, GetInputNode(INPUTPORT_POSE)); const AnimGraphPose* inputPose = GetInputPose(animGraphInstance, INPUTPORT_POSE)->GetValue(); @@ -260,12 +260,12 @@ namespace EMotionFX } // get the node indices - const size_t nodeIndexA = uniqueData->mNodeIndexA; - const size_t nodeIndexB = uniqueData->mNodeIndexB; - const size_t nodeIndexC = uniqueData->mNodeIndexC; - const size_t bendDirIndex = uniqueData->mBendDirNodeIndex; - size_t alignNodeIndex = uniqueData->mAlignNodeIndex; - size_t endEffectorNodeIndex = uniqueData->mEndEffectorNodeIndex; + const size_t nodeIndexA = uniqueData->m_nodeIndexA; + const size_t nodeIndexB = uniqueData->m_nodeIndexB; + const size_t nodeIndexC = uniqueData->m_nodeIndexC; + const size_t bendDirIndex = uniqueData->m_bendDirNodeIndex; + size_t alignNodeIndex = uniqueData->m_alignNodeIndex; + size_t endEffectorNodeIndex = uniqueData->m_endEffectorNodeIndex; // use the end node as end effector node if no goal node has been specified if (endEffectorNodeIndex == InvalidIndex) @@ -303,13 +303,13 @@ namespace EMotionFX { alignNodeTransform = alignInstance->GetTransformData()->GetCurrentPose()->GetWorldSpaceTransform(alignNodeIndex); } - const AZ::Vector3& offset = alignNodeTransform.mPosition; + const AZ::Vector3& offset = alignNodeTransform.m_position; goal += offset; if (GetEMotionFX().GetIsInEditorMode()) { // check if the offset goal pos values comes from a param node - const BlendTreeConnection* posConnection = GetInputPort(INPUTPORT_GOALPOS).mConnection; + const BlendTreeConnection* posConnection = GetInputPort(INPUTPORT_GOALPOS).m_connection; if (posConnection) { if (azrtti_typeid(posConnection->GetSourceNode()) == azrtti_typeid()) @@ -327,7 +327,7 @@ namespace EMotionFX } else if (GetEMotionFX().GetIsInEditorMode()) { - const BlendTreeConnection* posConnection = GetInputPort(INPUTPORT_GOALPOS).mConnection; + const BlendTreeConnection* posConnection = GetInputPort(INPUTPORT_GOALPOS).m_connection; if (posConnection) { if (azrtti_typeid(posConnection->GetSourceNode()) == azrtti_typeid()) @@ -352,11 +352,11 @@ namespace EMotionFX { if (bendDirIndex != InvalidIndex) { - bendDir = outTransformPose.GetWorldSpaceTransform(bendDirIndex).mPosition - globalTransformA.mPosition; + bendDir = outTransformPose.GetWorldSpaceTransform(bendDirIndex).m_position - globalTransformA.m_position; } else { - bendDir = globalTransformB.mPosition - globalTransformA.mPosition; + bendDir = globalTransformB.m_position - globalTransformA.m_position; } } else @@ -371,7 +371,7 @@ namespace EMotionFX // if we want a relative bend dir, rotate it with the actor (only do this if we don't extract the bend dir) if (m_relativeBendDir && !m_extractBendDir) { - bendDir = actorInstance->GetWorldSpaceTransform().mRotation.TransformVector(bendDir); + bendDir = actorInstance->GetWorldSpaceTransform().m_rotation.TransformVector(bendDir); bendDir = MCore::SafeNormalize(bendDir); } else @@ -393,7 +393,7 @@ namespace EMotionFX { newRotation = inputGoalRot->GetValue(); // use our new rotation directly } - globalTransformC.mRotation = newRotation; + globalTransformC.m_rotation = newRotation; outTransformPose.SetWorldSpaceTransform(nodeIndexC, globalTransformC); } else // align to another node @@ -401,11 +401,11 @@ namespace EMotionFX if (inputGoalRot) { OutputIncomingNode(animGraphInstance, GetInputNode(INPUTPORT_GOALROT)); - globalTransformC.mRotation = GetInputQuaternion(animGraphInstance, INPUTPORT_GOALROT)->GetValue() * alignNodeTransform.mRotation; + globalTransformC.m_rotation = GetInputQuaternion(animGraphInstance, INPUTPORT_GOALROT)->GetValue() * alignNodeTransform.m_rotation; } else { - globalTransformC.mRotation = alignNodeTransform.mRotation; + globalTransformC.m_rotation = alignNodeTransform.m_rotation; } outTransformPose.SetWorldSpaceTransform(nodeIndexC, globalTransformC); @@ -413,15 +413,15 @@ namespace EMotionFX } // adjust the goal and get the end effector position - AZ::Vector3 endEffectorNodePos = outTransformPose.GetWorldSpaceTransform(endEffectorNodeIndex).mPosition; - const AZ::Vector3 posCToEndEffector = endEffectorNodePos - globalTransformC.mPosition; + AZ::Vector3 endEffectorNodePos = outTransformPose.GetWorldSpaceTransform(endEffectorNodeIndex).m_position; + const AZ::Vector3 posCToEndEffector = endEffectorNodePos - globalTransformC.m_position; if (m_rotationEnabled) { goal -= posCToEndEffector; } // store the desired rotation - AZ::Quaternion newNodeRotationC = globalTransformC.mRotation; + AZ::Quaternion newNodeRotationC = globalTransformC.m_rotation; // draw debug lines if (GetEMotionFX().GetIsInEditorMode() && GetCanVisualize(animGraphInstance)) @@ -441,15 +441,15 @@ namespace EMotionFX DebugDraw& debugDraw = GetDebugDraw(); DebugDraw::ActorInstanceData* drawData = debugDraw.GetActorInstanceData(animGraphInstance->GetActorInstance()); drawData->Lock(); - drawData->DrawLine(realGoal - AZ::Vector3(s, 0, 0), realGoal + AZ::Vector3(s, 0, 0), mVisualizeColor); - drawData->DrawLine(realGoal - AZ::Vector3(0, s, 0), realGoal + AZ::Vector3(0, s, 0), mVisualizeColor); - drawData->DrawLine(realGoal - AZ::Vector3(0, 0, s), realGoal + AZ::Vector3(0, 0, s), mVisualizeColor); + drawData->DrawLine(realGoal - AZ::Vector3(s, 0, 0), realGoal + AZ::Vector3(s, 0, 0), m_visualizeColor); + drawData->DrawLine(realGoal - AZ::Vector3(0, s, 0), realGoal + AZ::Vector3(0, s, 0), m_visualizeColor); + drawData->DrawLine(realGoal - AZ::Vector3(0, 0, s), realGoal + AZ::Vector3(0, 0, s), m_visualizeColor); const AZ::Color color(0.0f, 1.0f, 1.0f, 1.0f); - drawData->DrawLine(globalTransformA.mPosition, globalTransformA.mPosition + bendDir * s * 2.5f, color); - drawData->DrawLine(globalTransformA.mPosition - AZ::Vector3(s, 0, 0), globalTransformA.mPosition + AZ::Vector3(s, 0, 0), color); - drawData->DrawLine(globalTransformA.mPosition - AZ::Vector3(0, s, 0), globalTransformA.mPosition + AZ::Vector3(0, s, 0), color); - drawData->DrawLine(globalTransformA.mPosition - AZ::Vector3(0, 0, s), globalTransformA.mPosition + AZ::Vector3(0, 0, s), color); + drawData->DrawLine(globalTransformA.m_position, globalTransformA.m_position + bendDir * s * 2.5f, color); + drawData->DrawLine(globalTransformA.m_position - AZ::Vector3(s, 0, 0), globalTransformA.m_position + AZ::Vector3(s, 0, 0), color); + drawData->DrawLine(globalTransformA.m_position - AZ::Vector3(0, s, 0), globalTransformA.m_position + AZ::Vector3(0, s, 0), color); + drawData->DrawLine(globalTransformA.m_position - AZ::Vector3(0, 0, s), globalTransformA.m_position + AZ::Vector3(0, 0, s), color); drawData->Unlock(); } @@ -457,19 +457,19 @@ namespace EMotionFX AZ::Vector3 midPos; if (m_rotationEnabled) { - Solve2LinkIK(globalTransformA.mPosition, globalTransformB.mPosition, globalTransformC.mPosition, goal, bendDir, &midPos); + Solve2LinkIK(globalTransformA.m_position, globalTransformB.m_position, globalTransformC.m_position, goal, bendDir, &midPos); } else { - Solve2LinkIK(globalTransformA.mPosition, globalTransformB.mPosition, endEffectorNodePos, goal, bendDir, &midPos); + Solve2LinkIK(globalTransformA.m_position, globalTransformB.m_position, endEffectorNodePos, goal, bendDir, &midPos); } // -------------------------------------- // calculate the new node transforms // -------------------------------------- // calculate the differences between the current forward vector and the new one after IK - AZ::Vector3 oldForward = globalTransformB.mPosition - globalTransformA.mPosition; - AZ::Vector3 newForward = midPos - globalTransformA.mPosition; + AZ::Vector3 oldForward = globalTransformB.m_position - globalTransformA.m_position; + AZ::Vector3 newForward = midPos - globalTransformA.m_position; oldForward = MCore::SafeNormalize(oldForward); newForward = MCore::SafeNormalize(newForward); @@ -478,7 +478,7 @@ namespace EMotionFX float deltaAngle = MCore::Math::ACos(MCore::Clamp(dotProduct, -1.0f, 1.0f)); AZ::Vector3 axis = oldForward.Cross(newForward); AZ::Quaternion deltaRot = MCore::CreateFromAxisAndAngle(axis, deltaAngle); - globalTransformA.mRotation = deltaRot * globalTransformA.mRotation; + globalTransformA.m_rotation = deltaRot * globalTransformA.m_rotation; outTransformPose.SetWorldSpaceTransform(nodeIndexA, globalTransformA); // globalTransformA = outTransformPose.GetGlobalTransformIncludingActorInstanceTransform(nodeIndexA); @@ -486,21 +486,21 @@ namespace EMotionFX globalTransformC = outTransformPose.GetWorldSpaceTransform(nodeIndexC); // get the new current node positions - midPos = globalTransformB.mPosition; - endEffectorNodePos = outTransformPose.GetWorldSpaceTransform(endEffectorNodeIndex).mPosition; + midPos = globalTransformB.m_position; + endEffectorNodePos = outTransformPose.GetWorldSpaceTransform(endEffectorNodeIndex).m_position; // second node if (m_rotationEnabled) { - oldForward = globalTransformC.mPosition - globalTransformB.mPosition; + oldForward = globalTransformC.m_position - globalTransformB.m_position; } else { - oldForward = endEffectorNodePos - globalTransformB.mPosition; + oldForward = endEffectorNodePos - globalTransformB.m_position; } oldForward = MCore::SafeNormalize(oldForward); - newForward = goal - globalTransformB.mPosition; + newForward = goal - globalTransformB.m_position; newForward = MCore::SafeNormalize(newForward); // calculate the delta rotation @@ -516,15 +516,15 @@ namespace EMotionFX deltaRot = AZ::Quaternion::CreateIdentity(); } - globalTransformB.mRotation = deltaRot * globalTransformB.mRotation; - globalTransformB.mPosition = midPos; + globalTransformB.m_rotation = deltaRot * globalTransformB.m_rotation; + globalTransformB.m_position = midPos; outTransformPose.SetWorldSpaceTransform(nodeIndexB, globalTransformB); // update the rotation of node C if (m_rotationEnabled) { globalTransformC = outTransformPose.GetWorldSpaceTransform(nodeIndexC); - globalTransformC.mRotation = newNodeRotationC; + globalTransformC.m_rotation = newNodeRotationC; outTransformPose.SetWorldSpaceTransform(nodeIndexC, globalTransformC); } @@ -556,8 +556,8 @@ namespace EMotionFX DebugDraw& debugDraw = GetDebugDraw(); DebugDraw::ActorInstanceData* drawData = debugDraw.GetActorInstanceData(animGraphInstance->GetActorInstance()); drawData->Lock(); - drawData->DrawLine(outTransformPose.GetWorldSpaceTransform(nodeIndexA).mPosition, outTransformPose.GetWorldSpaceTransform(nodeIndexB).mPosition, mVisualizeColor); - drawData->DrawLine(outTransformPose.GetWorldSpaceTransform(nodeIndexB).mPosition, outTransformPose.GetWorldSpaceTransform(nodeIndexC).mPosition, mVisualizeColor); + drawData->DrawLine(outTransformPose.GetWorldSpaceTransform(nodeIndexA).m_position, outTransformPose.GetWorldSpaceTransform(nodeIndexB).m_position, m_visualizeColor); + drawData->DrawLine(outTransformPose.GetWorldSpaceTransform(nodeIndexB).m_position, outTransformPose.GetWorldSpaceTransform(nodeIndexC).m_position, m_visualizeColor); drawData->Unlock(); } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeTwoLinkIKNode.h b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeTwoLinkIKNode.h index 807eb4044e..e39cd7258e 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeTwoLinkIKNode.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeTwoLinkIKNode.h @@ -60,12 +60,12 @@ namespace EMotionFX void Update() override; public: - size_t mNodeIndexA = InvalidIndex; - size_t mNodeIndexB = InvalidIndex; - size_t mNodeIndexC = InvalidIndex; - size_t mEndEffectorNodeIndex = InvalidIndex; - size_t mAlignNodeIndex = InvalidIndex; - size_t mBendDirNodeIndex = InvalidIndex; + size_t m_nodeIndexA = InvalidIndex; + size_t m_nodeIndexB = InvalidIndex; + size_t m_nodeIndexC = InvalidIndex; + size_t m_endEffectorNodeIndex = InvalidIndex; + size_t m_alignNodeIndex = InvalidIndex; + size_t m_bendDirNodeIndex = InvalidIndex; }; BlendTreeTwoLinkIKNode(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeVector3Math1Node.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeVector3Math1Node.cpp index 94ab0ecac0..a70e6a3c61 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeVector3Math1Node.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeVector3Math1Node.cpp @@ -30,7 +30,7 @@ namespace EMotionFX SetupOutputPort("Vector3", OUTPUTPORT_RESULT_VECTOR3, MCore::AttributeVector3::TYPE_ID, PORTID_OUTPUT_VECTOR3); SetupOutputPort("Float", OUTPUTPORT_RESULT_FLOAT, MCore::AttributeFloat::TYPE_ID, PORTID_OUTPUT_FLOAT); - if (mAnimGraph) + if (m_animGraph) { Reinit(); } @@ -153,7 +153,7 @@ namespace EMotionFX void BlendTreeVector3Math1Node::SetMathFunction(EMathFunction func) { m_mathFunction = func; - if (mAnimGraph) + if (m_animGraph) { Reinit(); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeVector3Math2Node.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeVector3Math2Node.cpp index cf00b8bc2c..d305ad6dd7 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeVector3Math2Node.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeVector3Math2Node.cpp @@ -33,7 +33,7 @@ namespace EMotionFX SetupOutputPort("Vector3", OUTPUTPORT_RESULT_VECTOR3, MCore::AttributeVector3::TYPE_ID, PORTID_OUTPUT_VECTOR3); SetupOutputPort("Float", OUTPUTPORT_RESULT_FLOAT, MCore::AttributeFloat::TYPE_ID, PORTID_OUTPUT_FLOAT); - if (mAnimGraph) + if (m_animGraph) { Reinit(); } @@ -118,7 +118,7 @@ namespace EMotionFX UpdateAllIncomingNodes(animGraphInstance, timePassedInSeconds); // if there are no incoming connections, there is nothing to do - if (mConnections.empty()) + if (m_connections.empty()) { return; } @@ -147,7 +147,7 @@ namespace EMotionFX void BlendTreeVector3Math2Node::SetMathFunction(EMathFunction func) { m_mathFunction = func; - if (mAnimGraph) + if (m_animGraph) { Reinit(); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeVector4DecomposeNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeVector4DecomposeNode.cpp index 0694cad02d..7cea0bbce1 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeVector4DecomposeNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeVector4DecomposeNode.cpp @@ -72,7 +72,7 @@ namespace EMotionFX void BlendTreeVector4DecomposeNode::UpdateOutputPortValues(AnimGraphInstance* animGraphInstance) { // If there are no incoming connections, there is nothing to do. - if (mConnections.size() == 0) + if (m_connections.size() == 0) { return; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/CompressedKeyFrames.h b/Gems/EMotionFX/Code/EMotionFX/Source/CompressedKeyFrames.h index 1acd492587..6919f22188 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/CompressedKeyFrames.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/CompressedKeyFrames.h @@ -24,22 +24,22 @@ namespace EMotionFX //-------------------------------------------------------------------------------------- // compress a quaternion template<> - MCORE_INLINE void KeyFrame::SetValue(const AZ::Quaternion& value) { mValue.FromQuaternion(value); } + MCORE_INLINE void KeyFrame::SetValue(const AZ::Quaternion& value) { m_value.FromQuaternion(value); } // decompress into a quaternion template<> - MCORE_INLINE AZ::Quaternion KeyFrame::GetValue() const { return mValue.ToQuaternion(); } + MCORE_INLINE AZ::Quaternion KeyFrame::GetValue() const { return m_value.ToQuaternion(); } // decompress into a quaternion (without return value) template<> - MCORE_INLINE void KeyFrame::GetValue(AZ::Quaternion* outValue) { mValue.UnCompress(outValue); } + MCORE_INLINE void KeyFrame::GetValue(AZ::Quaternion* outValue) { m_value.UnCompress(outValue); } // direct access to compressed values template<> - MCORE_INLINE void KeyFrame::SetStorageTypeValue(const MCore::Compressed8BitQuaternion& value) { mValue = value; } + MCORE_INLINE void KeyFrame::SetStorageTypeValue(const MCore::Compressed8BitQuaternion& value) { m_value = value; } template<> - MCORE_INLINE const MCore::Compressed8BitQuaternion& KeyFrame::GetStorageTypeValue() const { return mValue; } + MCORE_INLINE const MCore::Compressed8BitQuaternion& KeyFrame::GetStorageTypeValue() const { return m_value; } //-------------------------------------------------------------------------------------- @@ -49,22 +49,22 @@ namespace EMotionFX //-------------------------------------------------------------------------------------- // compress a quaternion template<> - MCORE_INLINE void KeyFrame::SetValue(const AZ::Quaternion& value) { mValue.FromQuaternion(value); } + MCORE_INLINE void KeyFrame::SetValue(const AZ::Quaternion& value) { m_value.FromQuaternion(value); } // decompress into a quaternion template<> - MCORE_INLINE AZ::Quaternion KeyFrame::GetValue() const { return mValue.ToQuaternion(); } + MCORE_INLINE AZ::Quaternion KeyFrame::GetValue() const { return m_value.ToQuaternion(); } // decompress into a quaternion template<> - MCORE_INLINE void KeyFrame::GetValue(AZ::Quaternion* outValue) { return mValue.UnCompress(outValue); } + MCORE_INLINE void KeyFrame::GetValue(AZ::Quaternion* outValue) { return m_value.UnCompress(outValue); } // direct access to compressed values template<> - MCORE_INLINE void KeyFrame::SetStorageTypeValue(const MCore::Compressed16BitQuaternion& value) { mValue = value; } + MCORE_INLINE void KeyFrame::SetStorageTypeValue(const MCore::Compressed16BitQuaternion& value) { m_value = value; } template<> - MCORE_INLINE const MCore::Compressed16BitQuaternion& KeyFrame::GetStorageTypeValue() const { return mValue; } + MCORE_INLINE const MCore::Compressed16BitQuaternion& KeyFrame::GetStorageTypeValue() const { return m_value; } //-------------------------------------------------------------------------------------- @@ -74,22 +74,22 @@ namespace EMotionFX //-------------------------------------------------------------------------------------- // compress a float template<> - MCORE_INLINE void KeyFrame::SetValue(const float& value) { mValue.FromFloat(value, 0.0f, 1.0f); } + MCORE_INLINE void KeyFrame::SetValue(const float& value) { m_value.FromFloat(value, 0.0f, 1.0f); } // decompress into a float template<> - MCORE_INLINE float KeyFrame::GetValue() const { return mValue.ToFloat(0.0f, 1.0f); } + MCORE_INLINE float KeyFrame::GetValue() const { return m_value.ToFloat(0.0f, 1.0f); } // decompress into a float template<> - MCORE_INLINE void KeyFrame::GetValue(float* outValue) { mValue.UnCompress(outValue, 0.0f, 1.0f); } + MCORE_INLINE void KeyFrame::GetValue(float* outValue) { m_value.UnCompress(outValue, 0.0f, 1.0f); } // direct access to compressed values template<> - MCORE_INLINE void KeyFrame::SetStorageTypeValue(const MCore::Compressed8BitFloat& value) { mValue = value; } + MCORE_INLINE void KeyFrame::SetStorageTypeValue(const MCore::Compressed8BitFloat& value) { m_value = value; } template<> - MCORE_INLINE const MCore::Compressed8BitFloat& KeyFrame::GetStorageTypeValue() const { return mValue; } + MCORE_INLINE const MCore::Compressed8BitFloat& KeyFrame::GetStorageTypeValue() const { return m_value; } //-------------------------------------------------------------------------------------- @@ -99,21 +99,21 @@ namespace EMotionFX //-------------------------------------------------------------------------------------- // compress a float template<> - MCORE_INLINE void KeyFrame::SetValue(const float& value) { mValue.FromFloat(value, 0.0f, 1.0f); } + MCORE_INLINE void KeyFrame::SetValue(const float& value) { m_value.FromFloat(value, 0.0f, 1.0f); } // decompress into a float template<> - MCORE_INLINE float KeyFrame::GetValue() const { return mValue.ToFloat(0.0f, 1.0f); } + MCORE_INLINE float KeyFrame::GetValue() const { return m_value.ToFloat(0.0f, 1.0f); } // decompress into a float template<> - MCORE_INLINE void KeyFrame::GetValue(float* outValue) { return mValue.UnCompress(outValue, 0.0f, 1.0f); } + MCORE_INLINE void KeyFrame::GetValue(float* outValue) { return m_value.UnCompress(outValue, 0.0f, 1.0f); } // direct access to compressed values template<> - MCORE_INLINE void KeyFrame::SetStorageTypeValue(const MCore::Compressed16BitFloat& value) { mValue = value; } + MCORE_INLINE void KeyFrame::SetStorageTypeValue(const MCore::Compressed16BitFloat& value) { m_value = value; } template<> - MCORE_INLINE const MCore::Compressed16BitFloat& KeyFrame::GetStorageTypeValue() const { return mValue; } + MCORE_INLINE const MCore::Compressed16BitFloat& KeyFrame::GetStorageTypeValue() const { return m_value; } } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/ConstraintTransform.h b/Gems/EMotionFX/Code/EMotionFX/Source/ConstraintTransform.h index 46547eec5d..5316ae3319 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/ConstraintTransform.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/ConstraintTransform.h @@ -27,15 +27,15 @@ namespace EMotionFX AZ_RTTI(ConstraintTransform, "{8C821457-C3C2-4DAD-B552-A7318B420A9C}", Constraint) AZ_CLASS_ALLOCATOR(ConstraintTransform, EMotionFX::Integration::EMotionFXAllocator, 0) - ConstraintTransform() : Constraint() { mTransform.Identity(); } + ConstraintTransform() : Constraint() { m_transform.Identity(); } ~ConstraintTransform() override { } - void SetTransform(const Transform& transform) { mTransform = transform; } - MCORE_INLINE const Transform& GetTransform() const { return mTransform; } - MCORE_INLINE Transform& GetTransform() { return mTransform; } + void SetTransform(const Transform& transform) { m_transform = transform; } + MCORE_INLINE const Transform& GetTransform() const { return m_transform; } + MCORE_INLINE Transform& GetTransform() { return m_transform; } protected: - Transform mTransform = Transform::CreateIdentity(); + Transform m_transform = Transform::CreateIdentity(); }; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/ConstraintTransformRotationAngles.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/ConstraintTransformRotationAngles.cpp index bc571e7cd0..6b23e050ca 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/ConstraintTransformRotationAngles.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/ConstraintTransformRotationAngles.cpp @@ -24,11 +24,11 @@ namespace EMotionFX const float angleY = 0.382683f; // 45 degrees const float twistAngle = 0.0f; // 0 degrees - mMinRotationAngles.Set(-angleX, -angleY); - mMaxRotationAngles.Set(angleX, angleY); - mMinTwist = twistAngle; - mMaxTwist = twistAngle; - mTwistAxis = AXIS_Y; + m_minRotationAngles.Set(-angleX, -angleY); + m_maxRotationAngles.Set(angleX, angleY); + m_minTwist = twistAngle; + m_maxTwist = twistAngle; + m_twistAxis = AXIS_Y; } uint32 ConstraintTransformRotationAngles::GetType() const @@ -45,74 +45,74 @@ namespace EMotionFX { const float angleX = MCore::Math::Sin(MCore::Math::DegreesToRadians(minSwingDegrees.GetX()) * 0.5f); const float angleY = MCore::Math::Sin(MCore::Math::DegreesToRadians(minSwingDegrees.GetY()) * 0.5f); - mMinRotationAngles.Set(angleX, angleY); + m_minRotationAngles.Set(angleX, angleY); } void ConstraintTransformRotationAngles::SetMaxRotationAngles(const AZ::Vector2& maxSwingDegrees) { const float angleX = MCore::Math::Sin(MCore::Math::DegreesToRadians(maxSwingDegrees.GetX()) * 0.5f); const float angleY = MCore::Math::Sin(MCore::Math::DegreesToRadians(maxSwingDegrees.GetY()) * 0.5f); - mMaxRotationAngles.Set(angleX, angleY); + m_maxRotationAngles.Set(angleX, angleY); } void ConstraintTransformRotationAngles::SetMinTwistAngle(float minTwistDegrees) { - mMinTwist = MCore::Math::Sin(MCore::Math::DegreesToRadians(minTwistDegrees) * 0.5f); + m_minTwist = MCore::Math::Sin(MCore::Math::DegreesToRadians(minTwistDegrees) * 0.5f); } void ConstraintTransformRotationAngles::SetMaxTwistAngle(float maxTwistDegrees) { - mMaxTwist = MCore::Math::Sin(MCore::Math::DegreesToRadians(maxTwistDegrees) * 0.5f); + m_maxTwist = MCore::Math::Sin(MCore::Math::DegreesToRadians(maxTwistDegrees) * 0.5f); } void ConstraintTransformRotationAngles::SetTwistAxis(ConstraintTransformRotationAngles::EAxis axis) { - mTwistAxis = axis; + m_twistAxis = axis; } AZ::Vector2 ConstraintTransformRotationAngles::GetMinRotationAnglesDegrees() const { - return AZ::Vector2(MCore::Math::RadiansToDegrees(MCore::Math::ASin(mMinRotationAngles.GetX()) * 2.0f), - MCore::Math::RadiansToDegrees(MCore::Math::ASin(mMinRotationAngles.GetY()) * 2.0f)); + return AZ::Vector2(MCore::Math::RadiansToDegrees(MCore::Math::ASin(m_minRotationAngles.GetX()) * 2.0f), + MCore::Math::RadiansToDegrees(MCore::Math::ASin(m_minRotationAngles.GetY()) * 2.0f)); } AZ::Vector2 ConstraintTransformRotationAngles::GetMaxRotationAnglesDegrees() const { - return AZ::Vector2(MCore::Math::RadiansToDegrees(MCore::Math::ASin(mMaxRotationAngles.GetX()) * 2.0f), - MCore::Math::RadiansToDegrees(MCore::Math::ASin(mMaxRotationAngles.GetY()) * 2.0f)); + return AZ::Vector2(MCore::Math::RadiansToDegrees(MCore::Math::ASin(m_maxRotationAngles.GetX()) * 2.0f), + MCore::Math::RadiansToDegrees(MCore::Math::ASin(m_maxRotationAngles.GetY()) * 2.0f)); } AZ::Vector2 ConstraintTransformRotationAngles::GetMinRotationAnglesRadians() const { - return AZ::Vector2(MCore::Math::ASin(mMinRotationAngles.GetX()) * 2.0f, - MCore::Math::ASin(mMinRotationAngles.GetY()) * 2.0f); + return AZ::Vector2(MCore::Math::ASin(m_minRotationAngles.GetX()) * 2.0f, + MCore::Math::ASin(m_minRotationAngles.GetY()) * 2.0f); } AZ::Vector2 ConstraintTransformRotationAngles::GetMaxRotationAnglesRadians() const { - return AZ::Vector2(MCore::Math::ASin(mMaxRotationAngles.GetX()) * 2.0f, - MCore::Math::ASin(mMaxRotationAngles.GetY()) * 2.0f); + return AZ::Vector2(MCore::Math::ASin(m_maxRotationAngles.GetX()) * 2.0f, + MCore::Math::ASin(m_maxRotationAngles.GetY()) * 2.0f); } float ConstraintTransformRotationAngles::GetMinTwistAngle() const { - return MCore::Math::RadiansToDegrees(MCore::Math::ASin(mMinTwist) * 2.0f); + return MCore::Math::RadiansToDegrees(MCore::Math::ASin(m_minTwist) * 2.0f); } float ConstraintTransformRotationAngles::GetMaxTwistAngle() const { - return MCore::Math::RadiansToDegrees(MCore::Math::ASin(mMaxTwist) * 2.0f); + return MCore::Math::RadiansToDegrees(MCore::Math::ASin(m_maxTwist) * 2.0f); } ConstraintTransformRotationAngles::EAxis ConstraintTransformRotationAngles::GetTwistAxis() const { - return mTwistAxis; + return m_twistAxis; } // The main execution function, which performs the actual constraint. void ConstraintTransformRotationAngles::Execute() { - AZ::Quaternion q = mTransform.mRotation; + AZ::Quaternion q = m_transform.m_rotation; // Always keep w positive. if (q.GetW() < 0.0f) @@ -123,7 +123,7 @@ namespace EMotionFX // Get the axes indices for swing uint32 swingX; uint32 swingY; - switch (mTwistAxis) + switch (m_twistAxis) { // Twist is the X-axis. case AXIS_X: @@ -151,15 +151,15 @@ namespace EMotionFX // Calculate the twist quaternion, based on over which axis we assume there is twist. AZ::Quaternion twist; - const float twistAngle = q.GetElement(mTwistAxis); + const float twistAngle = q.GetElement(m_twistAxis); const float s = twistAngle * twistAngle + q.GetW() * q.GetW(); if (!MCore::Math::IsFloatZero(s)) { const float r = MCore::Math::InvSqrt(s); twist.SetElement(swingX, 0.0f); twist.SetElement(swingY, 0.0f); - twist.SetElement(mTwistAxis, MCore::Clamp(twistAngle * r, mMinTwist, mMaxTwist)); - twist.SetW(MCore::Math::Sqrt(MCore::Max(0.0f, 1.0f - twist.GetElement(mTwistAxis) * twist.GetElement(mTwistAxis)))); + twist.SetElement(m_twistAxis, MCore::Clamp(twistAngle * r, m_minTwist, m_maxTwist)); + twist.SetW(MCore::Math::Sqrt(MCore::Max(0.0f, 1.0f - twist.GetElement(m_twistAxis) * twist.GetElement(m_twistAxis)))); } else { @@ -168,13 +168,13 @@ namespace EMotionFX // Remove the twist from the input rotation so that we are left with a swing and then limit the swing. AZ::Quaternion swing = q * twist.GetConjugate(); - swing.SetElement(swingX, MCore::Clamp(static_cast(swing.GetElement(swingX)), mMinRotationAngles.GetX(), mMaxRotationAngles.GetX())); - swing.SetElement(swingY, MCore::Clamp(static_cast(swing.GetElement(swingY)), mMinRotationAngles.GetY(), mMaxRotationAngles.GetY())); - swing.SetElement(mTwistAxis, 0.0f); + swing.SetElement(swingX, MCore::Clamp(static_cast(swing.GetElement(swingX)), m_minRotationAngles.GetX(), m_maxRotationAngles.GetX())); + swing.SetElement(swingY, MCore::Clamp(static_cast(swing.GetElement(swingY)), m_minRotationAngles.GetY(), m_maxRotationAngles.GetY())); + swing.SetElement(m_twistAxis, 0.0f); swing.SetW(MCore::Math::Sqrt(MCore::Max(0.0f, 1.0f - swing.GetElement(swingX) * swing.GetElement(swingX) - swing.GetElement(swingY) * swing.GetElement(swingY)))); // Combine the limited swing and twist again into a final rotation. - mTransform.mRotation = swing * twist; + m_transform.m_rotation = swing * twist; } AZ::Vector3 ConstraintTransformRotationAngles::GetSphericalPos(float x, float y) const diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/ConstraintTransformRotationAngles.h b/Gems/EMotionFX/Code/EMotionFX/Source/ConstraintTransformRotationAngles.h index 3af63c382e..65e141e6e2 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/ConstraintTransformRotationAngles.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/ConstraintTransformRotationAngles.h @@ -74,11 +74,11 @@ namespace EMotionFX static void Reflect(AZ::ReflectContext* context); protected: - AZ::Vector2 mMinRotationAngles; ///< The minimum rotation angles, actually the precalculated sin(halfAngleRadians). - AZ::Vector2 mMaxRotationAngles; ///< The maximum rotation angles, actually the precalculated sin(halfAngleRadians). - float mMinTwist; ///< The minimum twist angle, actually the precalculated sin(halfAngleRadians). - float mMaxTwist; ///< The maximum twist angle, actually the precalculated sin(halfAngleRadians). - EAxis mTwistAxis; ///< The twist axis index, which has to be either 0, 1 or 2 (default=AXIS_X, which equals 0). + AZ::Vector2 m_minRotationAngles; ///< The minimum rotation angles, actually the precalculated sin(halfAngleRadians). + AZ::Vector2 m_maxRotationAngles; ///< The maximum rotation angles, actually the precalculated sin(halfAngleRadians). + float m_minTwist; ///< The minimum twist angle, actually the precalculated sin(halfAngleRadians). + float m_maxTwist; ///< The maximum twist angle, actually the precalculated sin(halfAngleRadians). + EAxis m_twistAxis; ///< The twist axis index, which has to be either 0, 1 or 2 (default=AXIS_X, which equals 0). void DrawSphericalLine(ActorInstance* actorInstance, const AZ::Vector2& start, const AZ::Vector2& end, uint32 numSteps, const AZ::Color& color, float radius, const AZ::Transform& offset) const; AZ::Vector3 GetSphericalPos(float x, float y) const; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/DebugDraw.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/DebugDraw.cpp index 8f1346f543..0fd06000de 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/DebugDraw.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/DebugDraw.cpp @@ -117,8 +117,8 @@ namespace EMotionFX const size_t parentIndex = skeleton->GetNode(nodeIndex)->GetParentIndex(); if (parentIndex != InvalidIndex) { - const AZ::Vector3& startPos = pose.GetWorldSpaceTransform(nodeIndex).mPosition; - const AZ::Vector3& endPos = pose.GetWorldSpaceTransform(parentIndex).mPosition; + const AZ::Vector3& startPos = pose.GetWorldSpaceTransform(nodeIndex).m_position; + const AZ::Vector3& endPos = pose.GetWorldSpaceTransform(parentIndex).m_position; DrawLine(offset + startPos, offset + endPos, color); } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/DualQuatSkinDeformer.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/DualQuatSkinDeformer.cpp index c107ae88f7..2d5d8e2a46 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/DualQuatSkinDeformer.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/DualQuatSkinDeformer.cpp @@ -38,7 +38,7 @@ namespace EMotionFX const size_t numBones = m_bones.size(); for (size_t i = 0; i < numBones; ++i) { - if (m_bones[i].mNodeNr == nodeIndex) + if (m_bones[i].m_nodeNr == nodeIndex) { return AZ::Success(i); } @@ -79,14 +79,14 @@ namespace EMotionFX { const Actor* actor = actorInstance->GetActor(); const Pose* pose = actorInstance->GetTransformData()->GetCurrentPose(); - const uint32 numVertices = mMesh->GetNumVertices(); + const uint32 numVertices = m_mesh->GetNumVertices(); // pre-calculate the skinning matrices for (BoneInfo& boneInfo : m_bones) { - const size_t nodeIndex = boneInfo.mNodeNr; + const size_t nodeIndex = boneInfo.m_nodeNr; const Transform skinTransform = actor->GetInverseBindPoseTransform(nodeIndex) * pose->GetModelSpaceTransform(nodeIndex); - boneInfo.mDualQuat.FromRotationTranslation(skinTransform.mRotation, skinTransform.mPosition); + boneInfo.m_dualQuat.FromRotationTranslation(skinTransform.m_rotation, skinTransform.m_position); } AZ::JobCompletion jobCompletion; @@ -102,7 +102,7 @@ namespace EMotionFX AZ::JobContext* jobContext = nullptr; AZ::Job* job = AZ::CreateJobFunction([this, startVertex, endVertex]() { - SkinRange(mMesh, startVertex, endVertex, m_bones); + SkinRange(m_mesh, startVertex, endVertex, m_bones); }, /*isAutoDelete=*/true, jobContext); job->SetDependent(&jobCompletion); @@ -145,7 +145,7 @@ namespace EMotionFX if (numInfluences > 0) { // get the pivot quat, used for the dot product check - const MCore::DualQuaternion& pivotQuat = boneInfos[ layer->GetInfluence(orgVertex, 0)->GetBoneNr() ].mDualQuat; + const MCore::DualQuaternion& pivotQuat = boneInfos[ layer->GetInfluence(orgVertex, 0)->GetBoneNr() ].m_dualQuat; // our skinning dual quaternion MCore::DualQuaternion skinQuat(AZ::Quaternion(0, 0, 0, 0), AZ::Quaternion(0, 0, 0, 0)); @@ -156,8 +156,8 @@ namespace EMotionFX weight = influence->GetWeight(); // check if we need to invert the dual quat - MCore::DualQuaternion influenceQuat = boneInfos[ influence->GetBoneNr() ].mDualQuat; - if (influenceQuat.mReal.Dot(pivotQuat.mReal) < 0.0f) + MCore::DualQuaternion influenceQuat = boneInfos[ influence->GetBoneNr() ].m_dualQuat; + if (influenceQuat.m_real.Dot(pivotQuat.m_real) < 0.0f) { influenceQuat *= -1.0f; } @@ -202,7 +202,7 @@ namespace EMotionFX if (numInfluences > 0) { // get the pivot quat, used for the dot product check - const MCore::DualQuaternion& pivotQuat = boneInfos[ layer->GetInfluence(orgVertex, 0)->GetBoneNr() ].mDualQuat; + const MCore::DualQuaternion& pivotQuat = boneInfos[ layer->GetInfluence(orgVertex, 0)->GetBoneNr() ].m_dualQuat; // our skinning dual quaternion MCore::DualQuaternion skinQuat(AZ::Quaternion(0, 0, 0, 0), AZ::Quaternion(0, 0, 0, 0)); @@ -213,8 +213,8 @@ namespace EMotionFX weight = influence->GetWeight(); // check if we need to invert the dual quat - MCore::DualQuaternion influenceQuat = boneInfos[ influence->GetBoneNr() ].mDualQuat; - if (influenceQuat.mReal.Dot(pivotQuat.mReal) < 0.0f) + MCore::DualQuaternion influenceQuat = boneInfos[ influence->GetBoneNr() ].m_dualQuat; + if (influenceQuat.m_real.Dot(pivotQuat.m_real) < 0.0f) { influenceQuat *= -1.0f; } @@ -255,7 +255,7 @@ namespace EMotionFX if (numInfluences > 0) { // get the pivot quat, used for the dot product check - const MCore::DualQuaternion& pivotQuat = boneInfos[ layer->GetInfluence(orgVertex, 0)->GetBoneNr() ].mDualQuat; + const MCore::DualQuaternion& pivotQuat = boneInfos[ layer->GetInfluence(orgVertex, 0)->GetBoneNr() ].m_dualQuat; // our skinning dual quaternion MCore::DualQuaternion skinQuat(AZ::Quaternion(0, 0, 0, 0), AZ::Quaternion(0, 0, 0, 0)); @@ -266,8 +266,8 @@ namespace EMotionFX weight = influence->GetWeight(); // check if we need to invert the dual quat - MCore::DualQuaternion influenceQuat = boneInfos[ influence->GetBoneNr() ].mDualQuat; - if (influenceQuat.mReal.Dot(pivotQuat.mReal) < 0.0f) + MCore::DualQuaternion influenceQuat = boneInfos[ influence->GetBoneNr() ].m_dualQuat; + if (influenceQuat.m_real.Dot(pivotQuat.m_real) < 0.0f) { influenceQuat *= -1.0f; } @@ -304,16 +304,16 @@ namespace EMotionFX m_bones.clear(); // if there is no mesh - if (mMesh == nullptr) + if (m_mesh == nullptr) { return; } - SkinningInfoVertexAttributeLayer* skinningLayer = (SkinningInfoVertexAttributeLayer*)mMesh->FindSharedVertexAttributeLayer(SkinningInfoVertexAttributeLayer::TYPE_ID); + SkinningInfoVertexAttributeLayer* skinningLayer = (SkinningInfoVertexAttributeLayer*)m_mesh->FindSharedVertexAttributeLayer(SkinningInfoVertexAttributeLayer::TYPE_ID); MCORE_ASSERT(skinningLayer); // find out what bones this mesh uses - const uint32 numOrgVerts = mMesh->GetNumOrgVertices(); + const uint32 numOrgVerts = m_mesh->GetNumOrgVertices(); for (uint32 i = 0; i < numOrgVerts; i++) { // now we have located the skinning information for this vertex, we can see if our bones array @@ -333,8 +333,8 @@ namespace EMotionFX { // add the bone to the array of bones in this deformer BoneInfo lastBone; - lastBone.mNodeNr = influence->GetNodeNr(); - lastBone.mDualQuat.Identity(); + lastBone.m_nodeNr = influence->GetNodeNr(); + lastBone.m_dualQuat.Identity(); m_bones.emplace_back(lastBone); influence->SetBoneNr(static_cast(m_bones.size() - 1)); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/DualQuatSkinDeformer.h b/Gems/EMotionFX/Code/EMotionFX/Source/DualQuatSkinDeformer.h index 154885ea7d..434f2920ee 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/DualQuatSkinDeformer.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/DualQuatSkinDeformer.h @@ -104,7 +104,7 @@ namespace EMotionFX * @param index The local bone number, which must be in range of [0..GetNumLocalBones()-1]. * @result The node number, which is in range of [0..Actor::GetNumNodes()-1], depending on the actor where this deformer works on. */ - MCORE_INLINE size_t GetLocalBone(size_t index) const { return m_bones[index].mNodeNr; } + MCORE_INLINE size_t GetLocalBone(size_t index) const { return m_bones[index].m_nodeNr; } /** * Pre-allocate space for a given number of local bones. @@ -119,11 +119,11 @@ namespace EMotionFX */ struct EMFX_API BoneInfo { - size_t mNodeNr; /**< The node number. */ - MCore::DualQuaternion mDualQuat; /**< The dual quat of the pre-calculated matrix that contains the "globalMatrix * inverse(bindPoseMatrix)". */ + size_t m_nodeNr; /**< The node number. */ + MCore::DualQuaternion m_dualQuat; /**< The dual quat of the pre-calculated matrix that contains the "globalMatrix * inverse(bindPoseMatrix)". */ MCORE_INLINE BoneInfo() - : mNodeNr(InvalidIndex) {} + : m_nodeNr(InvalidIndex) {} }; AZStd::vector m_bones; /**< The array of bone information used for pre-calculation. */ @@ -153,7 +153,7 @@ namespace EMotionFX /** * Find the entry number that uses a specified node number. * @param nodeIndex The node number to search for. - * @result The index inside the mBones member array, which uses the given node. + * @result The index inside the m_bones member array, which uses the given node. */ AZ::Outcome FindLocalBoneIndex(size_t nodeIndex) const; }; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/EMotionFXManager.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/EMotionFXManager.cpp index d58b4286b9..82b06c8171 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/EMotionFXManager.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/EMotionFXManager.cpp @@ -62,7 +62,7 @@ namespace EMotionFX } // set the unit type - gEMFX.Get()->SetUnitType(finalSettings.mUnitType); + gEMFX.Get()->SetUnitType(finalSettings.m_unitType); // create and set the objects gEMFX.Get()->SetImporter (Importer::Create()); @@ -111,20 +111,20 @@ namespace EMotionFX AZStd::string lowVersionString; BuildLowVersionString(lowVersionString); - mVersionString = AZStd::string::format("EMotion FX v%d.%s RC4", EMFX_HIGHVERSION, lowVersionString.c_str()); - mCompilationDate = MCORE_DATE; - mHighVersion = EMFX_HIGHVERSION; - mLowVersion = EMFX_LOWVERSION; - mImporter = nullptr; - mActorManager = nullptr; - mMotionManager = nullptr; - mEventManager = nullptr; - mSoftSkinManager = nullptr; - mRecorder = nullptr; - mMotionInstancePool = nullptr; - mDebugDraw = nullptr; - mUnitType = MCore::Distance::UNITTYPE_METERS; - mGlobalSimulationSpeed = 1.0f; + m_versionString = AZStd::string::format("EMotion FX v%d.%s RC4", EMFX_HIGHVERSION, lowVersionString.c_str()); + m_compilationDate = MCORE_DATE; + m_highVersion = EMFX_HIGHVERSION; + m_lowVersion = EMFX_LOWVERSION; + m_importer = nullptr; + m_actorManager = nullptr; + m_motionManager = nullptr; + m_eventManager = nullptr; + m_softSkinManager = nullptr; + m_recorder = nullptr; + m_motionInstancePool = nullptr; + m_debugDraw = nullptr; + m_unitType = MCore::Distance::UNITTYPE_METERS; + m_globalSimulationSpeed = 1.0f; m_isInEditorMode = false; m_isInServerMode = false; @@ -143,41 +143,40 @@ namespace EMotionFX { // the motion manager has to get destructed before the anim graph manager as the motion manager kills all motion instances // from the motion nodes when destructing the motions itself - //mRigManager->Destroy(); - mMotionManager->Destroy(); - mMotionManager = nullptr; + m_motionManager->Destroy(); + m_motionManager = nullptr; - mAnimGraphManager->Destroy(); - mAnimGraphManager = nullptr; + m_animGraphManager->Destroy(); + m_animGraphManager = nullptr; - mImporter->Destroy(); - mImporter = nullptr; + m_importer->Destroy(); + m_importer = nullptr; - mActorManager->Destroy(); - mActorManager = nullptr; + m_actorManager->Destroy(); + m_actorManager = nullptr; - mMotionInstancePool->Destroy(); - mMotionInstancePool = nullptr; + m_motionInstancePool->Destroy(); + m_motionInstancePool = nullptr; - mSoftSkinManager->Destroy(); - mSoftSkinManager = nullptr; + m_softSkinManager->Destroy(); + m_softSkinManager = nullptr; - mRecorder->Destroy(); - mRecorder = nullptr; + m_recorder->Destroy(); + m_recorder = nullptr; - delete mDebugDraw; - mDebugDraw = nullptr; + delete m_debugDraw; + m_debugDraw = nullptr; - mEventManager->Destroy(); - mEventManager = nullptr; + m_eventManager->Destroy(); + m_eventManager = nullptr; // delete the thread datas - for (uint32 i = 0; i < mThreadDatas.size(); ++i) + for (uint32 i = 0; i < m_threadDatas.size(); ++i) { - mThreadDatas[i]->Destroy(); + m_threadDatas[i]->Destroy(); } - mThreadDatas.clear(); + m_threadDatas.clear(); } @@ -193,16 +192,16 @@ namespace EMotionFX { AZ_PROFILE_SCOPE(AZ::Debug::ProfileCategory::Animation, "EMotionFXManager::Update"); - mDebugDraw->Clear(); - mRecorder->UpdatePlayMode(timePassedInSeconds); - mActorManager->UpdateActorInstances(timePassedInSeconds); - mEventManager->OnSimulatePhysics(timePassedInSeconds); - mRecorder->Update(timePassedInSeconds); + m_debugDraw->Clear(); + m_recorder->UpdatePlayMode(timePassedInSeconds); + m_actorManager->UpdateActorInstances(timePassedInSeconds); + m_eventManager->OnSimulatePhysics(timePassedInSeconds); + m_recorder->Update(timePassedInSeconds); // sample and apply all anim graphs we recorded - if (mRecorder->GetIsInPlayMode() && mRecorder->GetRecordSettings().mRecordAnimGraphStates) + if (m_recorder->GetIsInPlayMode() && m_recorder->GetRecordSettings().m_recordAnimGraphStates) { - mRecorder->SampleAndApplyAnimGraphs(mRecorder->GetCurrentPlayTime()); + m_recorder->SampleAndApplyAnimGraphs(m_recorder->GetCurrentPlayTime()); } } @@ -217,9 +216,9 @@ namespace EMotionFX MCore::LogInfo("-----------------------------------------------"); MCore::LogInfo("EMotion FX - Information"); MCore::LogInfo("-----------------------------------------------"); - MCore::LogInfo("Version: v%d.%s", mHighVersion, lowVersionString.c_str()); - MCore::LogInfo("Version string: %s", mVersionString.c_str()); - MCore::LogInfo("Compilation date: %s", mCompilationDate.c_str()); + MCore::LogInfo("Version: v%d.%s", m_highVersion, lowVersionString.c_str()); + MCore::LogInfo("Version string: %s", m_versionString.c_str()); + MCore::LogInfo("Compilation date: %s", m_compilationDate.c_str()); #ifdef MCORE_OPENMP_ENABLED MCore::LogInfo("OpenMP enabled: Yes"); @@ -234,88 +233,88 @@ namespace EMotionFX // get the version string const char* EMotionFXManager::GetVersionString() const { - return mVersionString.c_str(); + return m_versionString.c_str(); } // get the compilation date string const char* EMotionFXManager::GetCompilationDate() const { - return mCompilationDate.c_str(); + return m_compilationDate.c_str(); } // get the high version uint32 EMotionFXManager::GetHighVersion() const { - return mHighVersion; + return m_highVersion; } // get the low version uint32 EMotionFXManager::GetLowVersion() const { - return mLowVersion; + return m_lowVersion; } // set the importer void EMotionFXManager::SetImporter(Importer* importer) { - mImporter = importer; + m_importer = importer; } // set the actor manager void EMotionFXManager::SetActorManager(ActorManager* manager) { - mActorManager = manager; + m_actorManager = manager; } // set the motion manager void EMotionFXManager::SetMotionManager(MotionManager* manager) { - mMotionManager = manager; + m_motionManager = manager; } // set the event manager void EMotionFXManager::SetEventManager(EventManager* manager) { - mEventManager = manager; + m_eventManager = manager; } // set the softskin manager void EMotionFXManager::SetSoftSkinManager(SoftSkinManager* manager) { - mSoftSkinManager = manager; + m_softSkinManager = manager; } // set the anim graph manager void EMotionFXManager::SetAnimGraphManager(AnimGraphManager* manager) { - mAnimGraphManager = manager; + m_animGraphManager = manager; } // set the recorder void EMotionFXManager::SetRecorder(Recorder* recorder) { - mRecorder = recorder; + m_recorder = recorder; } void EMotionFXManager::SetDebugDraw(DebugDraw* draw) { - mDebugDraw = draw; + m_debugDraw = draw; } // set the motion instance pool void EMotionFXManager::SetMotionInstancePool(MotionInstancePool* pool) { - mMotionInstancePool = pool; + m_motionInstancePool = pool; pool->Init(); } @@ -323,19 +322,19 @@ namespace EMotionFX // set the path of the media root directory void EMotionFXManager::SetMediaRootFolder(const char* path) { - mMediaRootFolder = path; + m_mediaRootFolder = path; // Make sure the media root folder has an ending slash. - if (mMediaRootFolder.empty() == false) + if (m_mediaRootFolder.empty() == false) { - const char lastChar = AzFramework::StringFunc::LastCharacter(mMediaRootFolder.c_str()); + const char lastChar = AzFramework::StringFunc::LastCharacter(m_mediaRootFolder.c_str()); if (lastChar != AZ_CORRECT_FILESYSTEM_SEPARATOR && lastChar != AZ_WRONG_FILESYSTEM_SEPARATOR) { - AzFramework::StringFunc::Path::AppendSeparator(mMediaRootFolder); + AzFramework::StringFunc::Path::AppendSeparator(m_mediaRootFolder); } } - EBUS_EVENT(AzFramework::ApplicationRequests::Bus, NormalizePathKeepCase, mMediaRootFolder); + EBUS_EVENT(AzFramework::ApplicationRequests::Bus, NormalizePathKeepCase, m_mediaRootFolder); } @@ -345,20 +344,20 @@ namespace EMotionFX const char* assetSourcePath = AZ::IO::FileIOBase::GetInstance()->GetAlias("@devassets@"); if (assetSourcePath) { - mAssetSourceFolder = assetSourcePath; + m_assetSourceFolder = assetSourcePath; // Add an ending slash in case there is none yet. // TODO: Remove this and adopt EMotionFX code to work with folder paths without slash at the end like Open 3D Engine does. - if (mAssetSourceFolder.empty() == false) + if (m_assetSourceFolder.empty() == false) { - const char lastChar = AzFramework::StringFunc::LastCharacter(mAssetSourceFolder.c_str()); + const char lastChar = AzFramework::StringFunc::LastCharacter(m_assetSourceFolder.c_str()); if (lastChar != AZ_CORRECT_FILESYSTEM_SEPARATOR && lastChar != AZ_WRONG_FILESYSTEM_SEPARATOR) { - AzFramework::StringFunc::Path::AppendSeparator(mAssetSourceFolder); + AzFramework::StringFunc::Path::AppendSeparator(m_assetSourceFolder); } } - EBUS_EVENT(AzFramework::ApplicationRequests::Bus, NormalizePathKeepCase, mAssetSourceFolder); + EBUS_EVENT(AzFramework::ApplicationRequests::Bus, NormalizePathKeepCase, m_assetSourceFolder); } else { @@ -370,20 +369,20 @@ namespace EMotionFX const char* assetCachePath = AZ::IO::FileIOBase::GetInstance()->GetAlias("@assets@"); if (assetCachePath) { - mAssetCacheFolder = assetCachePath; + m_assetCacheFolder = assetCachePath; // Add an ending slash in case there is none yet. // TODO: Remove this and adopt EMotionFX code to work with folder paths without slash at the end like Open 3D Engine does. - if (mAssetCacheFolder.empty() == false) + if (m_assetCacheFolder.empty() == false) { - const char lastChar = AzFramework::StringFunc::LastCharacter(mAssetCacheFolder.c_str()); + const char lastChar = AzFramework::StringFunc::LastCharacter(m_assetCacheFolder.c_str()); if (lastChar != AZ_CORRECT_FILESYSTEM_SEPARATOR && lastChar != AZ_WRONG_FILESYSTEM_SEPARATOR) { - AzFramework::StringFunc::Path::AppendSeparator(mAssetCacheFolder); + AzFramework::StringFunc::Path::AppendSeparator(m_assetCacheFolder); } } - EBUS_EVENT(AzFramework::ApplicationRequests::Bus, NormalizePathKeepCase, mAssetCacheFolder); + EBUS_EVENT(AzFramework::ApplicationRequests::Bus, NormalizePathKeepCase, m_assetCacheFolder); } else { @@ -396,7 +395,7 @@ namespace EMotionFX { outAbsoluteFilename = relativeFilename; EBUS_EVENT(AzFramework::ApplicationRequests::Bus, NormalizePathKeepCase, outAbsoluteFilename); - AzFramework::StringFunc::Replace(outAbsoluteFilename, EMFX_MEDIAROOTFOLDER_STRING, mMediaRootFolder.c_str(), true); + AzFramework::StringFunc::Replace(outAbsoluteFilename, EMFX_MEDIAROOTFOLDER_STRING, m_mediaRootFolder.c_str(), true); } @@ -456,14 +455,14 @@ namespace EMotionFX // get the global speed factor float EMotionFXManager::GetGlobalSimulationSpeed() const { - return mGlobalSimulationSpeed; + return m_globalSimulationSpeed; } // set the global speed factor void EMotionFXManager::SetGlobalSimulationSpeed(float speedFactor) { - mGlobalSimulationSpeed = MCore::Max(0.0f, speedFactor); + m_globalSimulationSpeed = MCore::Max(0.0f, speedFactor); } @@ -476,23 +475,23 @@ namespace EMotionFX numThreads = 1; } - if (mThreadDatas.size() == numThreads) + if (m_threadDatas.size() == numThreads) { return; } // get rid of old data - for (uint32 i = 0; i < mThreadDatas.size(); ++i) + for (uint32 i = 0; i < m_threadDatas.size(); ++i) { - mThreadDatas[i]->Destroy(); + m_threadDatas[i]->Destroy(); } - mThreadDatas.clear(); // force calling constructors again to reset everything - mThreadDatas.resize(numThreads); + m_threadDatas.clear(); // force calling constructors again to reset everything + m_threadDatas.resize(numThreads); for (uint32 i = 0; i < numThreads; ++i) { - mThreadDatas[i] = ThreadData::Create(i); + m_threadDatas[i] = ThreadData::Create(i); } } @@ -501,21 +500,21 @@ namespace EMotionFX void EMotionFXManager::ShrinkPools() { Allocators::ShrinkPools(); - mMotionInstancePool->Shrink(); + m_motionInstancePool->Shrink(); } // get the unit type MCore::Distance::EUnitType EMotionFXManager::GetUnitType() const { - return mUnitType; + return m_unitType; } // set the unit type void EMotionFXManager::SetUnitType(MCore::Distance::EUnitType unitType) { - mUnitType = unitType; + m_unitType = unitType; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/EMotionFXManager.h b/Gems/EMotionFX/Code/EMotionFX/Source/EMotionFXManager.h index 45bf59c94c..d5c5247de6 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/EMotionFXManager.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/EMotionFXManager.h @@ -124,28 +124,28 @@ namespace EMotionFX * This can also be accessed with the GetImporter() macro. * @result A pointer to the importer. */ - MCORE_INLINE Importer* GetImporter() const { return mImporter; } + MCORE_INLINE Importer* GetImporter() const { return m_importer; } /** * Get the actor manager. * This can also be accessed with the GetActorManager() macro. * @result A pointer to the actor manager. */ - MCORE_INLINE ActorManager* GetActorManager() const { return mActorManager; } + MCORE_INLINE ActorManager* GetActorManager() const { return m_actorManager; } /** * Get the motion manager. * This can also be accessed with the GetMotionManager() macro. * @result A pointer to the motion manager. */ - MCORE_INLINE MotionManager* GetMotionManager() const { return mMotionManager; } + MCORE_INLINE MotionManager* GetMotionManager() const { return m_motionManager; } /** * Get the event manager. * This can also be accessed with the GetEventManager() macro. * @result A pointer to the event manager. */ - MCORE_INLINE EventManager* GetEventManager() const { return mEventManager; } + MCORE_INLINE EventManager* GetEventManager() const { return m_eventManager; } /** * Get the soft-skin manager. @@ -155,41 +155,34 @@ namespace EMotionFX * This can also be accessed with the GetSoftSkinManager() macro. * @result A pointer to the soft-skinning manager. */ - MCORE_INLINE SoftSkinManager* GetSoftSkinManager() const { return mSoftSkinManager; } + MCORE_INLINE SoftSkinManager* GetSoftSkinManager() const { return m_softSkinManager; } /** * Get the motion instance pool. * This can also be accessed with the GetMotionInstancePool() macro. * @result A pointer to the motion instance pool. */ - MCORE_INLINE MotionInstancePool* GetMotionInstancePool() const { return mMotionInstancePool; } + MCORE_INLINE MotionInstancePool* GetMotionInstancePool() const { return m_motionInstancePool; } /** * Get the animgraph manager; * This can also be accessed with the GetAnimGraphManager() macro. * @result A pointer to the animgraph manager. */ - MCORE_INLINE AnimGraphManager* GetAnimGraphManager() const { return mAnimGraphManager; } - - /** - * Get the rig manager; - * This can also be accessed with the GetRigManager() macro. - * @result A pointer to the animgraph manager. - */ - // MCORE_INLINE RigManager* GetRigManager() const { return mRigManager; } + MCORE_INLINE AnimGraphManager* GetAnimGraphManager() const { return m_animGraphManager; } /** * Get the recorder. * This can also be accessed with the EMFX_RECODRER macro. * @result A pointer to the recorder. */ - MCORE_INLINE Recorder* GetRecorder() const { return mRecorder; } + MCORE_INLINE Recorder* GetRecorder() const { return m_recorder; } /** * Get the debug drawing class. * @result A pointer to the wavelet cache. */ - MCORE_INLINE DebugDraw* GetDebugDraw() const { return mDebugDraw; } + MCORE_INLINE DebugDraw* GetDebugDraw() const { return m_debugDraw; } /** * Set the path of the media root directory. @@ -243,38 +236,38 @@ namespace EMotionFX * Get the path of the media root folder. * @result The path of the media root directory. */ - MCORE_INLINE const char* GetMediaRootFolder() const { return mMediaRootFolder.c_str(); } + MCORE_INLINE const char* GetMediaRootFolder() const { return m_mediaRootFolder.c_str(); } /** * Get the path of the media root folder as a string object. * @result The path of the media root directory. */ - MCORE_INLINE const AZStd::string& GetMediaRootFolderString() const { return mMediaRootFolder; } + MCORE_INLINE const AZStd::string& GetMediaRootFolderString() const { return m_mediaRootFolder; } /** * Get the asset source folder path. * @result The path of the asset source folder. */ - MCORE_INLINE const AZStd::string& GetAssetSourceFolder() const { return mAssetSourceFolder; } + MCORE_INLINE const AZStd::string& GetAssetSourceFolder() const { return m_assetSourceFolder; } /** * Get the asset cache folder path. * @result The path of the asset cache folder. */ - MCORE_INLINE const AZStd::string& GetAssetCacheFolder() const { return mAssetCacheFolder; } + MCORE_INLINE const AZStd::string& GetAssetCacheFolder() const { return m_assetCacheFolder; } /** * Get the unique per thread data for a given thread by index. * @param threadIndex The thread index, which must be between [0..GetNumThreads()-1]. * @return The unique thread data for this thread. */ - MCORE_INLINE ThreadData* GetThreadData(uint32 threadIndex) const { MCORE_ASSERT(threadIndex < mThreadDatas.size()); return mThreadDatas[threadIndex]; } + MCORE_INLINE ThreadData* GetThreadData(uint32 threadIndex) const { MCORE_ASSERT(threadIndex < m_threadDatas.size()); return m_threadDatas[threadIndex]; } /** * Get the number of threads that are internally created. * @return The number of threads that we have internally created. */ - MCORE_INLINE size_t GetNumThreads() const { return mThreadDatas.size(); } + MCORE_INLINE size_t GetNumThreads() const { return m_threadDatas.size(); } /** * Shrink the memory pools, to reduce memory usage. @@ -338,25 +331,25 @@ namespace EMotionFX bool GetEnableServerOptimization() const { return m_isInServerMode && m_enableServerOptimization; } private: - AZStd::string mVersionString; /**< The version string. */ - AZStd::string mCompilationDate; /**< The compilation date string. */ - AZStd::string mMediaRootFolder; /**< The path of the media root directory. */ - AZStd::string mAssetSourceFolder; /**< The absolute path of the asset source folder. */ - AZStd::string mAssetCacheFolder; /**< The absolute path of the asset cache folder. */ - uint32 mHighVersion; /**< The higher version, which would be 3 in case of v3.01. */ - uint32 mLowVersion; /**< The low version, which would be 100 in case of v3.10 or 10 in case of v3.01. */ - Importer* mImporter; /**< The importer that can load actors and motions. */ - ActorManager* mActorManager; /**< The actor manager. */ - MotionManager* mMotionManager; /**< The motion manager. */ - EventManager* mEventManager; /**< The motion event manager. */ - SoftSkinManager* mSoftSkinManager; /**< The softskin manager. */ - AnimGraphManager* mAnimGraphManager; /**< The animgraph manager. */ - Recorder* mRecorder; /**< The recorder. */ - MotionInstancePool* mMotionInstancePool; /**< The motion instance pool. */ - DebugDraw* mDebugDraw; /**< The debug drawing system. */ - AZStd::vector mThreadDatas; /**< The per thread data. */ - MCore::Distance::EUnitType mUnitType; /**< The unit type, on default it is MCore::Distance::UNITTYPE_METERS. */ - float mGlobalSimulationSpeed; /**< The global simulation speed, default is 1.0. */ + AZStd::string m_versionString; /**< The version string. */ + AZStd::string m_compilationDate; /**< The compilation date string. */ + AZStd::string m_mediaRootFolder; /**< The path of the media root directory. */ + AZStd::string m_assetSourceFolder; /**< The absolute path of the asset source folder. */ + AZStd::string m_assetCacheFolder; /**< The absolute path of the asset cache folder. */ + uint32 m_highVersion; /**< The higher version, which would be 3 in case of v3.01. */ + uint32 m_lowVersion; /**< The low version, which would be 100 in case of v3.10 or 10 in case of v3.01. */ + Importer* m_importer; /**< The importer that can load actors and motions. */ + ActorManager* m_actorManager; /**< The actor manager. */ + MotionManager* m_motionManager; /**< The motion manager. */ + EventManager* m_eventManager; /**< The motion event manager. */ + SoftSkinManager* m_softSkinManager; /**< The softskin manager. */ + AnimGraphManager* m_animGraphManager; /**< The animgraph manager. */ + Recorder* m_recorder; /**< The recorder. */ + MotionInstancePool* m_motionInstancePool; /**< The motion instance pool. */ + DebugDraw* m_debugDraw; /**< The debug drawing system. */ + AZStd::vector m_threadDatas; /**< The per thread data. */ + MCore::Distance::EUnitType m_unitType; /**< The unit type, on default it is MCore::Distance::UNITTYPE_METERS. */ + float m_globalSimulationSpeed; /**< The global simulation speed, default is 1.0. */ bool m_isInEditorMode; /**< True when the runtime requires to support an editor. Optimizations can be made if there is no need for editor support. */ bool m_isInServerMode; /**< True when emotionfx is running on server. */ bool m_enableServerOptimization; /**< True when optimization can be made when emotionfx is running in server mode. */ @@ -454,11 +447,11 @@ namespace EMotionFX */ struct EMFX_API InitSettings { - MCore::Distance::EUnitType mUnitType; /**< The unit type to use. This specifies the size of one unit. On default this is a meter. */ + MCore::Distance::EUnitType m_unitType; /**< The unit type to use. This specifies the size of one unit. On default this is a meter. */ InitSettings() { - mUnitType = MCore::Distance::UNITTYPE_METERS; + m_unitType = MCore::Distance::UNITTYPE_METERS; } }; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/EventHandler.h b/Gems/EMotionFX/Code/EMotionFX/Source/EventHandler.h index c0b7696205..9c8b0ecbfb 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/EventHandler.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/EventHandler.h @@ -121,7 +121,7 @@ namespace EMotionFX { MCORE_UNUSED(eventInfo); // find the event index in the array - // const uint32 eventIndex = GetEventManager().FindEventTypeIndex( eventInfo.mEventTypeID ); + // const uint32 eventIndex = GetEventManager().FindEventTypeIndex( eventInfo.m_eventTypeID ); // get the name of the event // const char* eventName = (eventIndex != MCORE_INVALIDINDEX32) ? GetEventManager().GetEventTypeString( eventIndex ) : ""; @@ -273,7 +273,7 @@ namespace EMotionFX /** * This event gets triggered once the given motion instance gets added to the motion queue. - * This happens when you set the PlayBackInfo::mPlayNow member to false. In that case the MotionSystem::PlayMotion() method (OnPlayMotion) + * This happens when you set the PlayBackInfo::m_playNow member to false. In that case the MotionSystem::PlayMotion() method (OnPlayMotion) * will not directly start playing the motion (OnStartMotionInstance), but will add it to the motion queue instead. * The motion queue will then start playing the motion instance once it should. * @param motionInstance The motion instance that gets added to the motion queue. @@ -316,7 +316,7 @@ namespace EMotionFX /** * Perform a ray intersection test and return the intersection info. - * The first event handler registered that sets the IntersectionInfo::mIsValid to true will be outputting to the outIntersectInfo parameter. + * The first event handler registered that sets the IntersectionInfo::m_isValid to true will be outputting to the outIntersectInfo parameter. * @param start The start point, in world space. * @param end The end point, in world space. * @param outIntersectInfo The resulting intersection info. @@ -395,8 +395,8 @@ namespace EMotionFX */ virtual const AZStd::vector GetHandledEventTypes() const = 0; - void SetMotionInstance(MotionInstance* motionInstance) { mMotionInstance = motionInstance; } - MCORE_INLINE MotionInstance* GetMotionInstance() { return mMotionInstance; } + void SetMotionInstance(MotionInstance* motionInstance) { m_motionInstance = motionInstance; } + MCORE_INLINE MotionInstance* GetMotionInstance() { return m_motionInstance; } /** * The method that processes an event. @@ -495,7 +495,7 @@ namespace EMotionFX /** * This event gets triggered once the given motion instance gets added to the motion queue. - * This happens when you set the PlayBackInfo::mPlayNow member to false. In that case the MotionSystem::PlayMotion() method (OnPlayMotion) + * This happens when you set the PlayBackInfo::m_playNow member to false. In that case the MotionSystem::PlayMotion() method (OnPlayMotion) * will not directly start playing the motion (OnStartMotionInstance), but will add it to the motion queue instead. * The motion queue will then start playing the motion instance once it should. * @param info The playback information used to play this motion instance. @@ -503,6 +503,6 @@ namespace EMotionFX virtual void OnQueueMotionInstance(PlayBackInfo* info) { MCORE_UNUSED(info); } protected: - MotionInstance* mMotionInstance = nullptr; + MotionInstance* m_motionInstance = nullptr; }; } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/EventInfo.h b/Gems/EMotionFX/Code/EMotionFX/Source/EventInfo.h index 1633d4fae7..6b97974fd3 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/EventInfo.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/EventInfo.h @@ -37,13 +37,13 @@ namespace EMotionFX END }; - float mTimeValue; /**< The time value of the event, in seconds. */ - ActorInstance* mActorInstance; /**< The actor instance that triggered this event. */ - const MotionInstance* mMotionInstance; /**< The motion instance which triggered this event, can be nullptr. */ - AnimGraphNode* mEmitter; /**< The animgraph node which originally did emit this event. This parameter can be nullptr. */ - const MotionEvent* mEvent; /**< The event itself. */ - float mGlobalWeight; /**< The global weight of the event. */ - float mLocalWeight; /**< The local weight of the event. */ + float m_timeValue; /**< The time value of the event, in seconds. */ + ActorInstance* m_actorInstance; /**< The actor instance that triggered this event. */ + const MotionInstance* m_motionInstance; /**< The motion instance which triggered this event, can be nullptr. */ + AnimGraphNode* m_emitter; /**< The animgraph node which originally did emit this event. This parameter can be nullptr. */ + const MotionEvent* m_event; /**< The event itself. */ + float m_globalWeight; /**< The global weight of the event. */ + float m_localWeight; /**< The local weight of the event. */ EventState m_eventState; /**< Is this the start of a ranged event? Ticked events will always have this set to true. */ bool IsEventStart() const @@ -58,13 +58,13 @@ namespace EMotionFX MotionEvent* event = nullptr, EventState eventState = START ) - : mTimeValue(timeValue) - , mActorInstance(actorInstance) - , mMotionInstance(motionInstance) - , mEmitter(nullptr) - , mEvent(event) - , mGlobalWeight(1.0f) - , mLocalWeight(1.0f) + : m_timeValue(timeValue) + , m_actorInstance(actorInstance) + , m_motionInstance(motionInstance) + , m_emitter(nullptr) + , m_event(event) + , m_globalWeight(1.0f) + , m_localWeight(1.0f) , m_eventState(eventState) { } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/EventManager.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/EventManager.cpp index e3b4c351ef..b39fcbab99 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/EventManager.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/EventManager.cpp @@ -53,21 +53,21 @@ namespace EMotionFX // lock the event manager void EventManager::Lock() { - mLock.Lock(); + m_lock.Lock(); } // unlock the event manager void EventManager::Unlock() { - mLock.Unlock(); + m_lock.Unlock(); } // register event handler to the manager void EventManager::AddEventHandler(EventHandler* eventHandler) { - MCore::LockGuardRecursive lock(mLock); + MCore::LockGuardRecursive lock(m_lock); AZ_Assert(eventHandler, "Expected non-null event handler"); for (const EventTypes eventType : eventHandler->GetHandledEventTypes()) @@ -82,7 +82,7 @@ namespace EMotionFX // unregister event handler from the manager void EventManager::RemoveEventHandler(EventHandler* eventHandler) { - MCore::LockGuardRecursive lock(mLock); + MCore::LockGuardRecursive lock(m_lock); for (const EventTypes eventType : eventHandler->GetHandledEventTypes()) { @@ -101,9 +101,9 @@ namespace EMotionFX } // trigger the event handlers inside the motion instance - if (eventInfo.mMotionInstance) + if (eventInfo.m_motionInstance) { - eventInfo.mMotionInstance->OnEvent(eventInfo); + eventInfo.m_motionInstance->OnEvent(eventInfo); } // Call event handlers @@ -570,7 +570,7 @@ namespace EMotionFX for (EventHandler* eventHandler : eventHandlers) { const bool result = eventHandler->OnRayIntersectionTest(start, end, outIntersectInfo); - if (outIntersectInfo->mIsValid) + if (outIntersectInfo->m_isValid) { return result; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/EventManager.h b/Gems/EMotionFX/Code/EMotionFX/Source/EventManager.h index cf47eff346..356ffe05ae 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/EventManager.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/EventManager.h @@ -40,31 +40,31 @@ namespace EMotionFX */ struct EMFX_API IntersectionInfo { - AZ::Vector3 mPosition; - AZ::Vector3 mNormal; - AZ::Vector2 mUV; - float mBaryCentricU; - float mBaryCentricV; - ActorInstance* mActorInstance; - ActorInstance* mIgnoreActorInstance; - Node* mNode; - Mesh* mMesh; - uint32 mStartIndex; - bool mIsValid; + AZ::Vector3 m_position; + AZ::Vector3 m_normal; + AZ::Vector2 m_uv; + float m_baryCentricU; + float m_baryCentricV; + ActorInstance* m_actorInstance; + ActorInstance* m_ignoreActorInstance; + Node* m_node; + Mesh* m_mesh; + uint32 m_startIndex; + bool m_isValid; IntersectionInfo() { - mPosition = AZ::Vector3::CreateZero(); - mNormal.Set(0.0f, 1.0f, 0.0f); - mUV = AZ::Vector2::CreateZero(); - mBaryCentricU = 0.0f; - mBaryCentricV = 0.0f; - mActorInstance = nullptr; - mStartIndex = 0; - mIgnoreActorInstance = nullptr; - mNode = nullptr; - mMesh = nullptr; - mIsValid = false; + m_position = AZ::Vector3::CreateZero(); + m_normal.Set(0.0f, 1.0f, 0.0f); + m_uv = AZ::Vector2::CreateZero(); + m_baryCentricU = 0.0f; + m_baryCentricV = 0.0f; + m_actorInstance = nullptr; + m_startIndex = 0; + m_ignoreActorInstance = nullptr; + m_node = nullptr; + m_mesh = nullptr; + m_isValid = false; } }; @@ -263,7 +263,7 @@ namespace EMotionFX /** * This event gets triggered once the given motion instance gets added to the motion queue. - * This happens when you set the PlayBackInfo::mPlayNow member to false. In that case the MotionSystem::PlayMotion() method (OnPlayMotion) + * This happens when you set the PlayBackInfo::m_playNow member to false. In that case the MotionSystem::PlayMotion() method (OnPlayMotion) * will not directly start playing the motion (OnStartMotionInstance), but will add it to the motion queue instead. * The motion queue will then start playing the motion instance once it should. * @param motionInstance The motion instance that gets added to the motion queue. @@ -292,7 +292,7 @@ namespace EMotionFX /** * Perform a ray intersection test and return the intersection info. - * The first event handler registered that sets the IntersectionInfo::mIsValid to true will be outputting to the outIntersectInfo parameter. + * The first event handler registered that sets the IntersectionInfo::m_isValid to true will be outputting to the outIntersectInfo parameter. * @param start The start point, in world space. * @param end The end point, in world space. * @param outIntersectInfo The resulting intersection info. @@ -347,14 +347,14 @@ namespace EMotionFX */ struct EMFX_API RegisteredEventType { - AZStd::string mEventType; /**< The string that describes the event, this is what artists type in 3DSMax/Maya. */ - uint32 mEventID; /**< The unique ID for this event. */ + AZStd::string m_eventType; /**< The string that describes the event, this is what artists type in 3DSMax/Maya. */ + uint32 m_eventId; /**< The unique ID for this event. */ }; using EventHandlerVector = AZStd::vector; AZStd::vector m_eventHandlersByEventType; /**< The event handler to use to process events organized by EventTypes. */ - MCore::MutexRecursive mLock; + MCore::MutexRecursive m_lock; AZStd::mutex m_eventDataLock; AZStd::vector > m_allEventData; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ActorFileFormat.h b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ActorFileFormat.h index 402c70c8a1..e4df8d0cc8 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ActorFileFormat.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ActorFileFormat.h @@ -38,23 +38,23 @@ namespace EMotionFX // (aligned) struct Actor_Header { - uint8 mFourcc[4]; // must be "ACTR" - uint8 mHiVersion; // high version (2 in case of v2.34) - uint8 mLoVersion; // low version (34 in case of v2.34) - uint8 mEndianType; // the endian in which the data is saved [0=little, 1=big] + uint8 m_fourcc[4]; // must be "ACTR" + uint8 m_hiVersion; // high version (2 in case of v2.34) + uint8 m_loVersion; // low version (34 in case of v2.34) + uint8 m_endianType; // the endian in which the data is saved [0=little, 1=big] }; // (not aligned) struct Actor_Info { - uint32 mNumLODs; // the number of level of details - uint32 mTrajectoryNodeIndex; // the node number of the trajectory node used for motion extraction (NOTE: unused as there is no more trajectory node) - uint32 mMotionExtractionNodeIndex;// the node number of the trajectory node used for motion extraction - float mRetargetRootOffset; - uint8 mUnitType; // maps to EMotionFX::EUnitType - uint8 mExporterHighVersion; - uint8 mExporterLowVersion; + uint32 m_numLoDs; // the number of level of details + uint32 m_trajectoryNodeIndex; // the node number of the trajectory node used for motion extraction (NOTE: unused as there is no more trajectory node) + uint32 m_motionExtractionNodeIndex;// the node number of the trajectory node used for motion extraction + float m_retargetRootOffset; + uint8 m_unitType; // maps to EMotionFX::EUnitType + uint8 m_exporterHighVersion; + uint8 m_exporterLowVersion; // followed by: // string : source application (e.g. "3ds Max 2011", "Maya 2011") @@ -67,12 +67,12 @@ namespace EMotionFX // (not aligned) struct Actor_Info2 { - uint32 mNumLODs; // the number of level of details - uint32 mMotionExtractionNodeIndex;// the node number of the trajectory node used for motion extraction - uint32 mRetargetRootNodeIndex; // the retargeting root node index, most likely pointing to the hip or pelvis or MCORE_INVALIDINDEX32 when not set - uint8 mUnitType; // maps to EMotionFX::EUnitType - uint8 mExporterHighVersion; - uint8 mExporterLowVersion; + uint32 m_numLoDs; // the number of level of details + uint32 m_motionExtractionNodeIndex;// the node number of the trajectory node used for motion extraction + uint32 m_retargetRootNodeIndex; // the retargeting root node index, most likely pointing to the hip or pelvis or MCORE_INVALIDINDEX32 when not set + uint8 m_unitType; // maps to EMotionFX::EUnitType + uint8 m_exporterHighVersion; + uint8 m_exporterLowVersion; // followed by: // string : source application (e.g. "3ds Max 2011", "Maya 2011") @@ -85,13 +85,13 @@ namespace EMotionFX // (aligned) struct Actor_Info3 { - uint32 mNumLODs; // the number of level of details - uint32 mMotionExtractionNodeIndex;// the node number of the trajectory node used for motion extraction - uint32 mRetargetRootNodeIndex; // the retargeting root node index, most likely pointing to the hip or pelvis or MCORE_INVALIDINDEX32 when not set - uint8 mUnitType; // maps to EMotionFX::EUnitType - uint8 mExporterHighVersion; - uint8 mExporterLowVersion; - uint8 mOptimizeSkeleton; + uint32 m_numLoDs; // the number of level of details + uint32 m_motionExtractionNodeIndex;// the node number of the trajectory node used for motion extraction + uint32 m_retargetRootNodeIndex; // the retargeting root node index, most likely pointing to the hip or pelvis or MCORE_INVALIDINDEX32 when not set + uint8 m_unitType; // maps to EMotionFX::EUnitType + uint8 m_exporterHighVersion; + uint8 m_exporterLowVersion; + uint8 m_optimizeSkeleton; // followed by: // string : source application (e.g. "3ds Max 2011", "Maya 2011") @@ -110,13 +110,13 @@ namespace EMotionFX // (not aligned) struct Actor_Node2 { - FileQuaternion mLocalQuat; // the local rotation (before hierarchy) - FileVector3 mLocalPos; // the local translation (before hierarchy) - FileVector3 mLocalScale;// the local scale (before hierarchy) - uint32 mSkeletalLODs;// each bit representing if the node is active or not, in the give LOD (bit number) - uint32 mParentIndex;// parent node number, or 0xFFFFFFFF in case of a root node - uint32 mNumChilds; // the number of child nodes - uint8 mNodeFlags; // #1 bit boolean specifies whether we have to include this node in the bounds calculation or not + FileQuaternion m_localQuat; // the local rotation (before hierarchy) + FileVector3 m_localPos; // the local translation (before hierarchy) + FileVector3 m_localScale;// the local scale (before hierarchy) + uint32 m_skeletalLoDs;// each bit representing if the node is active or not, in the give LOD (bit number) + uint32 m_parentIndex;// parent node number, or 0xFFFFFFFF in case of a root node + uint32 m_numChilds; // the number of child nodes + uint8 m_nodeFlags; // #1 bit boolean specifies whether we have to include this node in the bounds calculation or not // followed by: // string : node name (the unique name of the node) @@ -126,8 +126,8 @@ namespace EMotionFX // (aligned) struct Actor_UV { - float mU; - float mV; + float m_u; + float m_v; }; //------------------------------------------------------- @@ -136,14 +136,14 @@ namespace EMotionFX // (aligned) struct Actor_Limit { - FileVector3 mTranslationMin;// the minimum translation values - FileVector3 mTranslationMax;// the maximum translation value. - FileVector3 mRotationMin; // the minimum rotation values - FileVector3 mRotationMax; // the maximum rotation values - FileVector3 mScaleMin; // the minimum scale values - FileVector3 mScaleMax; // the maximum scale values - uint8 mLimitFlags[9]; // the limit type activation flags - uint32 mNodeNumber; // the node number where this info belongs to + FileVector3 m_translationMin;// the minimum translation values + FileVector3 m_translationMax;// the maximum translation value. + FileVector3 m_rotationMin; // the minimum rotation values + FileVector3 m_rotationMax; // the maximum rotation values + FileVector3 m_scaleMin; // the minimum scale values + FileVector3 m_scaleMax; // the maximum scale values + uint8 m_limitFlags[9]; // the limit type activation flags + uint32 m_nodeNumber; // the node number where this info belongs to }; @@ -151,15 +151,15 @@ namespace EMotionFX // (aligned) struct Actor_MorphTarget { - float mRangeMin; // the slider min - float mRangeMax; // the slider max - uint32 mLOD; // the level of detail to which this expression part belongs to - uint32 mNumTransformations;// the number of transformations to follow - uint32 mPhonemeSets; // the number of phoneme sets to follow + float m_rangeMin; // the slider min + float m_rangeMax; // the slider max + uint32 m_lod; // the level of detail to which this expression part belongs to + uint32 m_numTransformations;// the number of transformations to follow + uint32 m_phonemeSets; // the number of phoneme sets to follow // followed by: // string : morph target name - // Actor_MorphTargetTransform[ mNumTransformations ] + // Actor_MorphTargetTransform[ m_numTransformations ] }; @@ -167,11 +167,11 @@ namespace EMotionFX // (aligned) struct Actor_MorphTargets { - uint32 mNumMorphTargets; // the number of morph targets to follow - uint32 mLOD; // the LOD level the morph targets are for + uint32 m_numMorphTargets; // the number of morph targets to follow + uint32 m_lod; // the LOD level the morph targets are for // followed by: - // Actor_MorphTarget[ mNumMorphTargets ] + // Actor_MorphTarget[ m_numMorphTargets ] }; @@ -179,11 +179,11 @@ namespace EMotionFX // (aligned) struct Actor_MorphTargetTransform { - uint32 mNodeIndex; // the node name where the transform belongs to - FileQuaternion mRotation; // the node rotation - FileQuaternion mScaleRotation; // the node delta scale rotation - FileVector3 mPosition; // the node delta position - FileVector3 mScale; // the node delta scale + uint32 m_nodeIndex; // the node name where the transform belongs to + FileQuaternion m_rotation; // the node rotation + FileQuaternion m_scaleRotation; // the node delta scale rotation + FileVector3 m_position; // the node delta position + FileVector3 m_scale; // the node delta scale }; @@ -191,30 +191,30 @@ namespace EMotionFX // (not aligned) struct Actor_NodeGroup { - uint16 mNumNodes; - uint8 mDisabledOnDefault; // 0 = no, 1 = yes + uint16 m_numNodes; + uint8 m_disabledOnDefault; // 0 = no, 1 = yes // followed by: // string : name - // uint16 [mNumNodes] + // uint16 [m_numNodes] }; // (aligned) struct Actor_Nodes2 { - uint32 mNumNodes; - uint32 mNumRootNodes; - // followed by Actor_Node4[mNumNodes] or Actor_NODE5[mNumNodes] (for v2) + uint32 m_numNodes; + uint32 m_numRootNodes; + // followed by Actor_Node4[m_numNodes] or Actor_NODE5[m_numNodes] (for v2) }; // node motion sources used for the motion mirroring feature // (aligned) struct Actor_NodeMotionSources2 { - uint32 mNumNodes; - // followed by uint16[mNumNodes] // an index per node, which indicates the index of the node to extract the motion data from in case mirroring for a given motion is enabled. This array can be nullptr in case no mirroring data has been setup. - // followed by uint8[mNumNodes] // axis identifier (0=X, 1=Y, 2=Z) - // followed by uint8[mNumNodes] // flags identifier (see Actor::MirrorFlags) + uint32 m_numNodes; + // followed by uint16[m_numNodes] // an index per node, which indicates the index of the node to extract the motion data from in case mirroring for a given motion is enabled. This array can be nullptr in case no mirroring data has been setup. + // followed by uint8[m_numNodes] // axis identifier (0=X, 1=Y, 2=Z) + // followed by uint8[m_numNodes] // flags identifier (see Actor::MirrorFlags) }; @@ -222,8 +222,8 @@ namespace EMotionFX // (aligned) struct Actor_AttachmentNodes { - uint32 mNumNodes; - // followed by uint16[mNumNodes] // an index per attachment node + uint32 m_numNodes; + // followed by uint16[m_numNodes] // an index per attachment node }; } // namespace FileFormat } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ChunkProcessors.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ChunkProcessors.cpp index 604dfb8bb9..7d800f8928 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ChunkProcessors.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ChunkProcessors.cpp @@ -244,12 +244,12 @@ namespace EMotionFX // constructor SharedHelperData::SharedHelperData() { - mFileHighVersion = 1; - mFileLowVersion = 0; + m_fileHighVersion = 1; + m_fileLowVersion = 0; // allocate the string buffer used for reading in variable sized strings - mStringStorageSize = 256; - mStringStorage = (char*)MCore::Allocate(mStringStorageSize, EMFX_MEMCATEGORY_IMPORTER); + m_stringStorageSize = 256; + m_stringStorage = (char*)MCore::Allocate(m_stringStorageSize, EMFX_MEMCATEGORY_IMPORTER); } @@ -271,13 +271,13 @@ namespace EMotionFX void SharedHelperData::Reset() { // free the string buffer - if (mStringStorage) + if (m_stringStorage) { - MCore::Free(mStringStorage); + MCore::Free(m_stringStorage); } - mStringStorage = nullptr; - mStringStorageSize = 0; + m_stringStorage = nullptr; + m_stringStorageSize = 0; } const char* SharedHelperData::ReadString(MCore::Stream* file, AZStd::vector* sharedData, MCore::Endian::EEndianType endianType) @@ -295,23 +295,17 @@ namespace EMotionFX MCore::Endian::ConvertUnsignedInt32(&numCharacters, endianType); // if we need to enlarge the buffer - if (helperData->mStringStorageSize < numCharacters + 1) + if (helperData->m_stringStorageSize < numCharacters + 1) { - helperData->mStringStorageSize = numCharacters + 1; - helperData->mStringStorage = (char*)MCore::Realloc(helperData->mStringStorage, helperData->mStringStorageSize, EMFX_MEMCATEGORY_IMPORTER); + helperData->m_stringStorageSize = numCharacters + 1; + helperData->m_stringStorage = (char*)MCore::Realloc(helperData->m_stringStorage, helperData->m_stringStorageSize, EMFX_MEMCATEGORY_IMPORTER); } // receive the actual string - file->Read(helperData->mStringStorage, numCharacters * sizeof(uint8)); - helperData->mStringStorage[numCharacters] = '\0'; + file->Read(helperData->m_stringStorage, numCharacters * sizeof(uint8)); + helperData->m_stringStorage[numCharacters] = '\0'; - //if (helperData->mIsUnicodeFile) - //helperData->mConvertString = helperData->mStringStorage; - //else - // helperData->mConvertString = helperData->mStringStorage; - - //result = helperData->mStringStorage; - return helperData->mStringStorage; + return helperData->m_stringStorage; } //----------------------------------------------------------------------------- @@ -320,9 +314,9 @@ namespace EMotionFX ChunkProcessor::ChunkProcessor(uint32 chunkID, uint32 version) : BaseObject() { - mChunkID = chunkID; - mVersion = version; - mLoggingActive = false; + m_chunkId = chunkID; + m_version = version; + m_loggingActive = false; } @@ -334,34 +328,34 @@ namespace EMotionFX uint32 ChunkProcessor::GetChunkID() const { - return mChunkID; + return m_chunkId; } uint32 ChunkProcessor::GetVersion() const { - return mVersion; + return m_version; } void ChunkProcessor::SetLogging(bool loggingActive) { - mLoggingActive = loggingActive; + m_loggingActive = loggingActive; } bool ChunkProcessor::GetLogging() const { - return mLoggingActive; + return m_loggingActive; } //================================================================================================= bool ChunkProcessorActorNodes2::Process(MCore::File* file, Importer::ImportParameters& importParams) { - const MCore::Endian::EEndianType endianType = importParams.mEndianType; - Actor* actor = importParams.mActor; - Importer::ActorSettings* actorSettings = importParams.mActorSettings; + const MCore::Endian::EEndianType endianType = importParams.m_endianType; + Actor* actor = importParams.m_actor; + Importer::ActorSettings* actorSettings = importParams.m_actorSettings; MCORE_ASSERT(actor); Skeleton* skeleton = actor->GetSkeleton(); @@ -370,44 +364,44 @@ namespace EMotionFX file->Read(&nodesHeader, sizeof(FileFormat::Actor_Nodes2)); // convert endian - MCore::Endian::ConvertUnsignedInt32(&nodesHeader.mNumNodes, endianType); - MCore::Endian::ConvertUnsignedInt32(&nodesHeader.mNumRootNodes, endianType); + MCore::Endian::ConvertUnsignedInt32(&nodesHeader.m_numNodes, endianType); + MCore::Endian::ConvertUnsignedInt32(&nodesHeader.m_numRootNodes, endianType); // pre-allocate space for the nodes - actor->SetNumNodes(nodesHeader.mNumNodes); + actor->SetNumNodes(nodesHeader.m_numNodes); // pre-allocate space for the root nodes - skeleton->ReserveRootNodes(nodesHeader.mNumRootNodes); + skeleton->ReserveRootNodes(nodesHeader.m_numRootNodes); if (GetLogging()) { - MCore::LogDetailedInfo("- Nodes: %d (%d root nodes)", nodesHeader.mNumNodes, nodesHeader.mNumRootNodes); + MCore::LogDetailedInfo("- Nodes: %d (%d root nodes)", nodesHeader.m_numNodes, nodesHeader.m_numRootNodes); } // add the transform actor->ResizeTransformData(); // read all nodes - for (uint32 n = 0; n < nodesHeader.mNumNodes; ++n) + for (uint32 n = 0; n < nodesHeader.m_numNodes; ++n) { // read the node header FileFormat::Actor_Node2 nodeChunk; file->Read(&nodeChunk, sizeof(FileFormat::Actor_Node2)); // read the node name - const char* nodeName = SharedHelperData::ReadString(file, importParams.mSharedData, endianType); + const char* nodeName = SharedHelperData::ReadString(file, importParams.m_sharedData, endianType); // convert endian - MCore::Endian::ConvertUnsignedInt32(&nodeChunk.mParentIndex, endianType); - MCore::Endian::ConvertUnsignedInt32(&nodeChunk.mSkeletalLODs, endianType); - MCore::Endian::ConvertUnsignedInt32(&nodeChunk.mNumChilds, endianType); + MCore::Endian::ConvertUnsignedInt32(&nodeChunk.m_parentIndex, endianType); + MCore::Endian::ConvertUnsignedInt32(&nodeChunk.m_skeletalLoDs, endianType); + MCore::Endian::ConvertUnsignedInt32(&nodeChunk.m_numChilds, endianType); // show the name of the node, the parent and the number of children if (GetLogging()) { MCore::LogDetailedInfo(" + Node name = '%s'", nodeName); - MCore::LogDetailedInfo(" - Parent = '%s'", (nodeChunk.mParentIndex != MCORE_INVALIDINDEX32) ? skeleton->GetNode(nodeChunk.mParentIndex)->GetName() : ""); - MCore::LogDetailedInfo(" - NumChild Nodes = %d", nodeChunk.mNumChilds); + MCore::LogDetailedInfo(" - Parent = '%s'", (nodeChunk.m_parentIndex != MCORE_INVALIDINDEX32) ? skeleton->GetNode(nodeChunk.m_parentIndex)->GetName() : ""); + MCore::LogDetailedInfo(" - NumChild Nodes = %d", nodeChunk.m_numChilds); } // create the new node @@ -418,15 +412,15 @@ namespace EMotionFX node->SetNodeIndex(nodeIndex); // pre-allocate space for the number of child nodes - node->PreAllocNumChildNodes(nodeChunk.mNumChilds); + node->PreAllocNumChildNodes(nodeChunk.m_numChilds); // add it to the actor skeleton->SetNode(n, node); // create Core objects from the data - AZ::Vector3 pos(nodeChunk.mLocalPos.mX, nodeChunk.mLocalPos.mY, nodeChunk.mLocalPos.mZ); - AZ::Vector3 scale(nodeChunk.mLocalScale.mX, nodeChunk.mLocalScale.mY, nodeChunk.mLocalScale.mZ); - AZ::Quaternion rot(nodeChunk.mLocalQuat.mX, nodeChunk.mLocalQuat.mY, nodeChunk.mLocalQuat.mZ, nodeChunk.mLocalQuat.mW); + AZ::Vector3 pos(nodeChunk.m_localPos.m_x, nodeChunk.m_localPos.m_y, nodeChunk.m_localPos.m_z); + AZ::Vector3 scale(nodeChunk.m_localScale.m_x, nodeChunk.m_localScale.m_y, nodeChunk.m_localScale.m_z); + AZ::Quaternion rot(nodeChunk.m_localQuat.m_x, nodeChunk.m_localQuat.m_y, nodeChunk.m_localQuat.m_z, nodeChunk.m_localQuat.m_w); // convert endian and coordinate system ConvertVector3(&pos, endianType); @@ -435,41 +429,41 @@ namespace EMotionFX // set the local transform Transform bindTransform; - bindTransform.mPosition = pos; - bindTransform.mRotation = rot.GetNormalized(); + bindTransform.m_position = pos; + bindTransform.m_rotation = rot.GetNormalized(); EMFX_SCALECODE ( - bindTransform.mScale = scale; + bindTransform.m_scale = scale; ) actor->GetBindPose()->SetLocalSpaceTransform(nodeIndex, bindTransform); // set the skeletal LOD levels - if (actorSettings->mLoadSkeletalLODs) + if (actorSettings->m_loadSkeletalLoDs) { - node->SetSkeletalLODLevelBits(nodeChunk.mSkeletalLODs); + node->SetSkeletalLODLevelBits(nodeChunk.m_skeletalLoDs); } // set if this node has to be taken into the bounding volume calculation - const bool includeInBoundsCalc = (nodeChunk.mNodeFlags & Node::ENodeFlags::FLAG_INCLUDEINBOUNDSCALC); // first bit + const bool includeInBoundsCalc = (nodeChunk.m_nodeFlags & Node::ENodeFlags::FLAG_INCLUDEINBOUNDSCALC); // first bit node->SetIncludeInBoundsCalc(includeInBoundsCalc); // Set if this node is critical and cannot be optimized out. - const bool isCritical = (nodeChunk.mNodeFlags & Node::ENodeFlags::FLAG_CRITICAL); // third bit + const bool isCritical = (nodeChunk.m_nodeFlags & Node::ENodeFlags::FLAG_CRITICAL); // third bit node->SetIsCritical(isCritical); // set the parent, and add this node as child inside the parent - if (nodeChunk.mParentIndex != MCORE_INVALIDINDEX32) // if this node has a parent and the parent node is valid + if (nodeChunk.m_parentIndex != MCORE_INVALIDINDEX32) // if this node has a parent and the parent node is valid { - if (nodeChunk.mParentIndex < n) + if (nodeChunk.m_parentIndex < n) { - node->SetParentIndex(nodeChunk.mParentIndex); - Node* parentNode = skeleton->GetNode(nodeChunk.mParentIndex); + node->SetParentIndex(nodeChunk.m_parentIndex); + Node* parentNode = skeleton->GetNode(nodeChunk.m_parentIndex); parentNode->AddChild(nodeIndex); } else { - MCore::LogError("Cannot assign parent node index (%d) for node '%s' as the parent node is not yet loaded. Making '%s' a root node.", nodeChunk.mParentIndex, node->GetName(), node->GetName()); + MCore::LogError("Cannot assign parent node index (%d) for node '%s' as the parent node is not yet loaded. Making '%s' a root node.", nodeChunk.m_parentIndex, node->GetName(), node->GetName()); skeleton->AddRootNode(nodeIndex); } } @@ -505,42 +499,42 @@ namespace EMotionFX // read all submotions in one chunk bool ChunkProcessorMotionSubMotions::Process(MCore::File* file, Importer::ImportParameters& importParams) { - const MCore::Endian::EEndianType endianType = importParams.mEndianType; - Motion* motion = importParams.mMotion; + const MCore::Endian::EEndianType endianType = importParams.m_endianType; + Motion* motion = importParams.m_motion; AZ_Assert(motion, "Expected a valid motion object."); // read the header FileFormat::Motion_SubMotions subMotionsHeader; file->Read(&subMotionsHeader, sizeof(FileFormat::Motion_SubMotions)); - MCore::Endian::ConvertUnsignedInt32(&subMotionsHeader.mNumSubMotions, endianType); + MCore::Endian::ConvertUnsignedInt32(&subMotionsHeader.m_numSubMotions, endianType); // Create a uniform motion data. NonUniformMotionData* motionData = aznew NonUniformMotionData(); motion->SetMotionData(motionData); - motionData->Resize(subMotionsHeader.mNumSubMotions, motionData->GetNumMorphs(), motionData->GetNumFloats()); + motionData->Resize(subMotionsHeader.m_numSubMotions, motionData->GetNumMorphs(), motionData->GetNumFloats()); // for all submotions - for (uint32 s = 0; s < subMotionsHeader.mNumSubMotions; ++s) + for (uint32 s = 0; s < subMotionsHeader.m_numSubMotions; ++s) { FileFormat::Motion_SkeletalSubMotion fileSubMotion; file->Read(&fileSubMotion, sizeof(FileFormat::Motion_SkeletalSubMotion)); // convert endian - MCore::Endian::ConvertUnsignedInt32(&fileSubMotion.mNumPosKeys, endianType); - MCore::Endian::ConvertUnsignedInt32(&fileSubMotion.mNumRotKeys, endianType); - MCore::Endian::ConvertUnsignedInt32(&fileSubMotion.mNumScaleKeys, endianType); + MCore::Endian::ConvertUnsignedInt32(&fileSubMotion.m_numPosKeys, endianType); + MCore::Endian::ConvertUnsignedInt32(&fileSubMotion.m_numRotKeys, endianType); + MCore::Endian::ConvertUnsignedInt32(&fileSubMotion.m_numScaleKeys, endianType); // read the motion part name - const char* motionJointName = SharedHelperData::ReadString(file, importParams.mSharedData, endianType); + const char* motionJointName = SharedHelperData::ReadString(file, importParams.m_sharedData, endianType); // convert into Core objects - AZ::Vector3 posePos(fileSubMotion.mPosePos.mX, fileSubMotion.mPosePos.mY, fileSubMotion.mPosePos.mZ); - AZ::Vector3 poseScale(fileSubMotion.mPoseScale.mX, fileSubMotion.mPoseScale.mY, fileSubMotion.mPoseScale.mZ); - MCore::Compressed16BitQuaternion poseRot(fileSubMotion.mPoseRot.mX, fileSubMotion.mPoseRot.mY, fileSubMotion.mPoseRot.mZ, fileSubMotion.mPoseRot.mW); + AZ::Vector3 posePos(fileSubMotion.m_posePos.m_x, fileSubMotion.m_posePos.m_y, fileSubMotion.m_posePos.m_z); + AZ::Vector3 poseScale(fileSubMotion.m_poseScale.m_x, fileSubMotion.m_poseScale.m_y, fileSubMotion.m_poseScale.m_z); + MCore::Compressed16BitQuaternion poseRot(fileSubMotion.m_poseRot.m_x, fileSubMotion.m_poseRot.m_y, fileSubMotion.m_poseRot.m_z, fileSubMotion.m_poseRot.m_w); - AZ::Vector3 bindPosePos(fileSubMotion.mBindPosePos.mX, fileSubMotion.mBindPosePos.mY, fileSubMotion.mBindPosePos.mZ); - AZ::Vector3 bindPoseScale(fileSubMotion.mBindPoseScale.mX, fileSubMotion.mBindPoseScale.mY, fileSubMotion.mBindPoseScale.mZ); - MCore::Compressed16BitQuaternion bindPoseRot(fileSubMotion.mBindPoseRot.mX, fileSubMotion.mBindPoseRot.mY, fileSubMotion.mBindPoseRot.mZ, fileSubMotion.mBindPoseRot.mW); + AZ::Vector3 bindPosePos(fileSubMotion.m_bindPosePos.m_x, fileSubMotion.m_bindPosePos.m_y, fileSubMotion.m_bindPosePos.m_z); + AZ::Vector3 bindPoseScale(fileSubMotion.m_bindPoseScale.m_x, fileSubMotion.m_bindPoseScale.m_y, fileSubMotion.m_bindPoseScale.m_z); + MCore::Compressed16BitQuaternion bindPoseRot(fileSubMotion.m_bindPoseRot.m_x, fileSubMotion.m_bindPoseRot.m_y, fileSubMotion.m_bindPoseRot.m_z, fileSubMotion.m_bindPoseRot.m_w); // convert endian and coordinate system ConvertVector3(&posePos, endianType); @@ -582,9 +576,9 @@ namespace EMotionFX static_cast(bindPoseScale.GetX()), static_cast(bindPoseScale.GetY()), static_cast(bindPoseScale.GetZ())); - MCore::LogDetailedInfo(" + Num Pos Keys: %d", fileSubMotion.mNumPosKeys); - MCore::LogDetailedInfo(" + Num Rot Keys: %d", fileSubMotion.mNumRotKeys); - MCore::LogDetailedInfo(" + Num Scale Keys: %d", fileSubMotion.mNumScaleKeys); + MCore::LogDetailedInfo(" + Num Pos Keys: %d", fileSubMotion.m_numPosKeys); + MCore::LogDetailedInfo(" + Num Rot Keys: %d", fileSubMotion.m_numRotKeys); + MCore::LogDetailedInfo(" + Num Scale Keys: %d", fileSubMotion.m_numScaleKeys); } motionData->SetJointName(s, motionJointName); @@ -600,62 +594,62 @@ namespace EMotionFX // now read the animation data uint32 i; - if (fileSubMotion.mNumPosKeys > 0) + if (fileSubMotion.m_numPosKeys > 0) { - motionData->AllocateJointPositionSamples(s, fileSubMotion.mNumPosKeys); - for (i = 0; i < fileSubMotion.mNumPosKeys; ++i) + motionData->AllocateJointPositionSamples(s, fileSubMotion.m_numPosKeys); + for (i = 0; i < fileSubMotion.m_numPosKeys; ++i) { FileFormat::Motion_Vector3Key key; file->Read(&key, sizeof(FileFormat::Motion_Vector3Key)); - MCore::Endian::ConvertFloat(&key.mTime, endianType); - AZ::Vector3 pos(key.mValue.mX, key.mValue.mY, key.mValue.mZ); + MCore::Endian::ConvertFloat(&key.m_time, endianType); + AZ::Vector3 pos(key.m_value.m_x, key.m_value.m_y, key.m_value.m_z); ConvertVector3(&pos, endianType); - motionData->SetJointPositionSample(s, i, {key.mTime, pos}); + motionData->SetJointPositionSample(s, i, {key.m_time, pos}); } } // now the rotation keys - if (fileSubMotion.mNumRotKeys > 0) + if (fileSubMotion.m_numRotKeys > 0) { - motionData->AllocateJointRotationSamples(s, fileSubMotion.mNumRotKeys); - for (i = 0; i < fileSubMotion.mNumRotKeys; ++i) + motionData->AllocateJointRotationSamples(s, fileSubMotion.m_numRotKeys); + for (i = 0; i < fileSubMotion.m_numRotKeys; ++i) { FileFormat::Motion_16BitQuaternionKey key; file->Read(&key, sizeof(FileFormat::Motion_16BitQuaternionKey)); - MCore::Endian::ConvertFloat(&key.mTime, endianType); - MCore::Compressed16BitQuaternion rot(key.mValue.mX, key.mValue.mY, key.mValue.mZ, key.mValue.mW); + MCore::Endian::ConvertFloat(&key.m_time, endianType); + MCore::Compressed16BitQuaternion rot(key.m_value.m_x, key.m_value.m_y, key.m_value.m_z, key.m_value.m_w); Convert16BitQuaternion(&rot, endianType); - motionData->SetJointRotationSample(s, i, {key.mTime, rot.ToQuaternion().GetNormalized()}); + motionData->SetJointRotationSample(s, i, {key.m_time, rot.ToQuaternion().GetNormalized()}); } } #ifndef EMFX_SCALE_DISABLED // and the scale keys - if (fileSubMotion.mNumScaleKeys > 0) + if (fileSubMotion.m_numScaleKeys > 0) { - motionData->AllocateJointScaleSamples(s, fileSubMotion.mNumScaleKeys); - for (i = 0; i < fileSubMotion.mNumScaleKeys; ++i) + motionData->AllocateJointScaleSamples(s, fileSubMotion.m_numScaleKeys); + for (i = 0; i < fileSubMotion.m_numScaleKeys; ++i) { FileFormat::Motion_Vector3Key key; file->Read(&key, sizeof(FileFormat::Motion_Vector3Key)); - MCore::Endian::ConvertFloat(&key.mTime, endianType); - AZ::Vector3 scale(key.mValue.mX, key.mValue.mY, key.mValue.mZ); + MCore::Endian::ConvertFloat(&key.m_time, endianType); + AZ::Vector3 scale(key.m_value.m_x, key.m_value.m_y, key.m_value.m_z); ConvertScale(&scale, endianType); - motionData->SetJointScaleSample(s, i, {key.mTime, scale}); + motionData->SetJointScaleSample(s, i, {key.m_time, scale}); } } #else // no scaling // and the scale keys - if (fileSubMotion.mNumScaleKeys > 0) + if (fileSubMotion.m_numScaleKeys > 0) { - for (i = 0; i < fileSubMotion.mNumScaleKeys; ++i) + for (i = 0; i < fileSubMotion.m_numScaleKeys; ++i) { FileFormat::Motion_Vector3Key key; file->Read(&key, sizeof(FileFormat::Motion_Vector3Key)); @@ -673,8 +667,8 @@ namespace EMotionFX bool ChunkProcessorMotionInfo::Process(MCore::File* file, Importer::ImportParameters& importParams) { - const MCore::Endian::EEndianType endianType = importParams.mEndianType; - Motion* motion = importParams.mMotion; + const MCore::Endian::EEndianType endianType = importParams.m_endianType; + Motion* motion = importParams.m_motion; MCORE_ASSERT(motion); @@ -683,8 +677,8 @@ namespace EMotionFX file->Read(&fileInformation, sizeof(FileFormat::Motion_Info)); // convert endian - MCore::Endian::ConvertUnsignedInt32(&fileInformation.mMotionExtractionMask, endianType); - MCore::Endian::ConvertUnsignedInt32(&fileInformation.mMotionExtractionNodeIndex, endianType); + MCore::Endian::ConvertUnsignedInt32(&fileInformation.m_motionExtractionMask, endianType); + MCore::Endian::ConvertUnsignedInt32(&fileInformation.m_motionExtractionNodeIndex, endianType); if (GetLogging()) { @@ -693,15 +687,15 @@ namespace EMotionFX if (GetLogging()) { - MCore::LogDetailedInfo(" + Unit Type = %d", fileInformation.mUnitType); + MCore::LogDetailedInfo(" + Unit Type = %d", fileInformation.m_unitType); } - motion->SetUnitType(static_cast(fileInformation.mUnitType)); + motion->SetUnitType(static_cast(fileInformation.m_unitType)); motion->SetFileUnitType(motion->GetUnitType()); // Try to remain backward compatible by still capturing height when this was enabled in the old mask system. - if (fileInformation.mMotionExtractionMask & (1 << 2)) // The 1<<2 was the mask used for position Z in the old motion extraction mask settings + if (fileInformation.m_motionExtractionMask & (1 << 2)) // The 1<<2 was the mask used for position Z in the old motion extraction mask settings { motion->SetMotionExtractionFlags(MOTIONEXTRACT_CAPTURE_Z); } @@ -713,8 +707,8 @@ namespace EMotionFX bool ChunkProcessorMotionInfo2::Process(MCore::File* file, Importer::ImportParameters& importParams) { - const MCore::Endian::EEndianType endianType = importParams.mEndianType; - Motion* motion = importParams.mMotion; + const MCore::Endian::EEndianType endianType = importParams.m_endianType; + Motion* motion = importParams.m_motion; MCORE_ASSERT(motion); // read the chunk @@ -722,8 +716,8 @@ namespace EMotionFX file->Read(&fileInformation, sizeof(FileFormat::Motion_Info2)); // convert endian - MCore::Endian::ConvertUnsignedInt32(&fileInformation.mMotionExtractionFlags, endianType); - MCore::Endian::ConvertUnsignedInt32(&fileInformation.mMotionExtractionNodeIndex, endianType); + MCore::Endian::ConvertUnsignedInt32(&fileInformation.m_motionExtractionFlags, endianType); + MCore::Endian::ConvertUnsignedInt32(&fileInformation.m_motionExtractionNodeIndex, endianType); if (GetLogging()) { @@ -732,13 +726,13 @@ namespace EMotionFX if (GetLogging()) { - MCore::LogDetailedInfo(" + Unit Type = %d", fileInformation.mUnitType); - MCore::LogDetailedInfo(" + Motion Extraction Flags = 0x%x [capZ=%d]", fileInformation.mMotionExtractionFlags, (fileInformation.mMotionExtractionFlags & EMotionFX::MOTIONEXTRACT_CAPTURE_Z) ? 1 : 0); + MCore::LogDetailedInfo(" + Unit Type = %d", fileInformation.m_unitType); + MCore::LogDetailedInfo(" + Motion Extraction Flags = 0x%x [capZ=%d]", fileInformation.m_motionExtractionFlags, (fileInformation.m_motionExtractionFlags & EMotionFX::MOTIONEXTRACT_CAPTURE_Z) ? 1 : 0); } - motion->SetUnitType(static_cast(fileInformation.mUnitType)); + motion->SetUnitType(static_cast(fileInformation.m_unitType)); motion->SetFileUnitType(motion->GetUnitType()); - motion->SetMotionExtractionFlags(static_cast(fileInformation.mMotionExtractionFlags)); + motion->SetMotionExtractionFlags(static_cast(fileInformation.m_motionExtractionFlags)); return true; } @@ -747,8 +741,8 @@ namespace EMotionFX bool ChunkProcessorMotionInfo3::Process(MCore::File* file, Importer::ImportParameters& importParams) { - const MCore::Endian::EEndianType endianType = importParams.mEndianType; - Motion* motion = importParams.mMotion; + const MCore::Endian::EEndianType endianType = importParams.m_endianType; + Motion* motion = importParams.m_motion; MCORE_ASSERT(motion); // read the chunk @@ -756,8 +750,8 @@ namespace EMotionFX file->Read(&fileInformation, sizeof(FileFormat::Motion_Info3)); // convert endian - MCore::Endian::ConvertUnsignedInt32(&fileInformation.mMotionExtractionFlags, endianType); - MCore::Endian::ConvertUnsignedInt32(&fileInformation.mMotionExtractionNodeIndex, endianType); + MCore::Endian::ConvertUnsignedInt32(&fileInformation.m_motionExtractionFlags, endianType); + MCore::Endian::ConvertUnsignedInt32(&fileInformation.m_motionExtractionNodeIndex, endianType); if (GetLogging()) { @@ -766,15 +760,15 @@ namespace EMotionFX if (GetLogging()) { - MCore::LogDetailedInfo(" + Unit Type = %d", fileInformation.mUnitType); - MCore::LogDetailedInfo(" + Is Additive Motion = %d", fileInformation.mIsAdditive); - MCore::LogDetailedInfo(" + Motion Extraction Flags = 0x%x [capZ=%d]", fileInformation.mMotionExtractionFlags, (fileInformation.mMotionExtractionFlags & EMotionFX::MOTIONEXTRACT_CAPTURE_Z) ? 1 : 0); + MCore::LogDetailedInfo(" + Unit Type = %d", fileInformation.m_unitType); + MCore::LogDetailedInfo(" + Is Additive Motion = %d", fileInformation.m_isAdditive); + MCore::LogDetailedInfo(" + Motion Extraction Flags = 0x%x [capZ=%d]", fileInformation.m_motionExtractionFlags, (fileInformation.m_motionExtractionFlags & EMotionFX::MOTIONEXTRACT_CAPTURE_Z) ? 1 : 0); } - motion->SetUnitType(static_cast(fileInformation.mUnitType)); - importParams.m_additiveMotion = (fileInformation.mIsAdditive == 0 ? false : true); + motion->SetUnitType(static_cast(fileInformation.m_unitType)); + importParams.m_additiveMotion = (fileInformation.m_isAdditive == 0 ? false : true); motion->SetFileUnitType(motion->GetUnitType()); - motion->SetMotionExtractionFlags(static_cast(fileInformation.mMotionExtractionFlags)); + motion->SetMotionExtractionFlags(static_cast(fileInformation.m_motionExtractionFlags)); return true; } @@ -783,8 +777,8 @@ namespace EMotionFX bool ChunkProcessorActorPhysicsSetup::Process(MCore::File* file, Importer::ImportParameters& importParams) { - const MCore::Endian::EEndianType endianType = importParams.mEndianType; - Actor* actor = importParams.mActor; + const MCore::Endian::EEndianType endianType = importParams.m_endianType; + Actor* actor = importParams.m_actor; AZ::u32 bufferSize; file->Read(&bufferSize, sizeof(AZ::u32)); @@ -807,7 +801,7 @@ namespace EMotionFX if (resultPhysicsSetup) { - if (importParams.mActorSettings->mOptimizeForServer) + if (importParams.m_actorSettings->m_optimizeForServer) { resultPhysicsSetup->OptimizeForServer(); } @@ -821,8 +815,8 @@ namespace EMotionFX bool ChunkProcessorActorSimulatedObjectSetup::Process(MCore::File* file, Importer::ImportParameters& importParams) { - const MCore::Endian::EEndianType endianType = importParams.mEndianType; - Actor* actor = importParams.mActor; + const MCore::Endian::EEndianType endianType = importParams.m_endianType; + Actor* actor = importParams.m_actor; AZ::u32 bufferSize; file->Read(&bufferSize, sizeof(AZ::u32)); @@ -854,13 +848,13 @@ namespace EMotionFX bool ChunkProcessorMeshAsset::Process(MCore::File* file, Importer::ImportParameters& importParams) { - const MCore::Endian::EEndianType endianType = importParams.mEndianType; - Actor* actor = importParams.mActor; + const MCore::Endian::EEndianType endianType = importParams.m_endianType; + Actor* actor = importParams.m_actor; AZ_Assert(actor, "Actor needs to be valid."); EMotionFX::FileFormat::Actor_MeshAsset meshAssetChunk; file->Read(&meshAssetChunk, sizeof(FileFormat::Actor_MeshAsset)); - const char* meshAssetIdString = SharedHelperData::ReadString(file, importParams.mSharedData, endianType); + const char* meshAssetIdString = SharedHelperData::ReadString(file, importParams.m_sharedData, endianType); const AZ::Data::AssetId meshAssetId = AZ::Data::AssetId::CreateString(meshAssetIdString); if (meshAssetId.IsValid()) { @@ -880,8 +874,8 @@ namespace EMotionFX bool ChunkProcessorMotionEventTrackTable::Process(MCore::File* file, Importer::ImportParameters& importParams) { - const MCore::Endian::EEndianType endianType = importParams.mEndianType; - Motion* motion = importParams.mMotion; + const MCore::Endian::EEndianType endianType = importParams.m_endianType; + Motion* motion = importParams.m_motion; MCORE_ASSERT(motion); @@ -890,53 +884,53 @@ namespace EMotionFX file->Read(&fileEventTable, sizeof(FileFormat::FileMotionEventTable)); // convert endian - MCore::Endian::ConvertUnsignedInt32(&fileEventTable.mNumTracks, endianType); + MCore::Endian::ConvertUnsignedInt32(&fileEventTable.m_numTracks, endianType); if (GetLogging()) { MCore::LogDetailedInfo("- Motion Event Table:"); - MCore::LogDetailedInfo(" + Num Tracks = %d", fileEventTable.mNumTracks); + MCore::LogDetailedInfo(" + Num Tracks = %d", fileEventTable.m_numTracks); } // get the motion event table the reserve the event tracks MotionEventTable* motionEventTable = motion->GetEventTable(); - motionEventTable->ReserveNumTracks(fileEventTable.mNumTracks); + motionEventTable->ReserveNumTracks(fileEventTable.m_numTracks); // read all tracks AZStd::string trackName; AZStd::vector typeStrings; AZStd::vector paramStrings; AZStd::vector mirrorTypeStrings; - for (uint32 t = 0; t < fileEventTable.mNumTracks; ++t) + for (uint32 t = 0; t < fileEventTable.m_numTracks; ++t) { // read the motion event table header FileFormat::FileMotionEventTrack fileTrack; file->Read(&fileTrack, sizeof(FileFormat::FileMotionEventTrack)); // read the track name - trackName = SharedHelperData::ReadString(file, importParams.mSharedData, endianType); + trackName = SharedHelperData::ReadString(file, importParams.m_sharedData, endianType); // convert endian - MCore::Endian::ConvertUnsignedInt32(&fileTrack.mNumEvents, endianType); - MCore::Endian::ConvertUnsignedInt32(&fileTrack.mNumTypeStrings, endianType); - MCore::Endian::ConvertUnsignedInt32(&fileTrack.mNumParamStrings, endianType); - MCore::Endian::ConvertUnsignedInt32(&fileTrack.mNumMirrorTypeStrings, endianType); + MCore::Endian::ConvertUnsignedInt32(&fileTrack.m_numEvents, endianType); + MCore::Endian::ConvertUnsignedInt32(&fileTrack.m_numTypeStrings, endianType); + MCore::Endian::ConvertUnsignedInt32(&fileTrack.m_numParamStrings, endianType); + MCore::Endian::ConvertUnsignedInt32(&fileTrack.m_numMirrorTypeStrings, endianType); if (GetLogging()) { MCore::LogDetailedInfo("- Motion Event Track:"); MCore::LogDetailedInfo(" + Name = %s", trackName.c_str()); - MCore::LogDetailedInfo(" + Num events = %d", fileTrack.mNumEvents); - MCore::LogDetailedInfo(" + Num types = %d", fileTrack.mNumTypeStrings); - MCore::LogDetailedInfo(" + Num params = %d", fileTrack.mNumParamStrings); - MCore::LogDetailedInfo(" + Num mirror = %d", fileTrack.mNumMirrorTypeStrings); - MCore::LogDetailedInfo(" + Enabled = %d", fileTrack.mIsEnabled); + MCore::LogDetailedInfo(" + Num events = %d", fileTrack.m_numEvents); + MCore::LogDetailedInfo(" + Num types = %d", fileTrack.m_numTypeStrings); + MCore::LogDetailedInfo(" + Num params = %d", fileTrack.m_numParamStrings); + MCore::LogDetailedInfo(" + Num mirror = %d", fileTrack.m_numMirrorTypeStrings); + MCore::LogDetailedInfo(" + Enabled = %d", fileTrack.m_isEnabled); } // the even type and parameter strings - typeStrings.resize(fileTrack.mNumTypeStrings); - paramStrings.resize(fileTrack.mNumParamStrings); - mirrorTypeStrings.resize(fileTrack.mNumMirrorTypeStrings); + typeStrings.resize(fileTrack.m_numTypeStrings); + paramStrings.resize(fileTrack.m_numParamStrings); + mirrorTypeStrings.resize(fileTrack.m_numMirrorTypeStrings); // read all type strings if (GetLogging()) @@ -944,9 +938,9 @@ namespace EMotionFX MCore::LogDetailedInfo(" + Event types:"); } uint32 i; - for (i = 0; i < fileTrack.mNumTypeStrings; ++i) + for (i = 0; i < fileTrack.m_numTypeStrings; ++i) { - typeStrings[i] = SharedHelperData::ReadString(file, importParams.mSharedData, endianType); + typeStrings[i] = SharedHelperData::ReadString(file, importParams.m_sharedData, endianType); if (GetLogging()) { MCore::LogDetailedInfo(" [%d] = '%s'", i, typeStrings[i].c_str()); @@ -958,9 +952,9 @@ namespace EMotionFX { MCore::LogDetailedInfo(" + Parameters:"); } - for (i = 0; i < fileTrack.mNumParamStrings; ++i) + for (i = 0; i < fileTrack.m_numParamStrings; ++i) { - paramStrings[i] = SharedHelperData::ReadString(file, importParams.mSharedData, endianType); + paramStrings[i] = SharedHelperData::ReadString(file, importParams.m_sharedData, endianType); if (GetLogging()) { MCore::LogDetailedInfo(" [%d] = '%s'", i, paramStrings[i].c_str()); @@ -971,9 +965,9 @@ namespace EMotionFX { MCore::LogDetailedInfo(" + Mirror Type Strings:"); } - for (i = 0; i < fileTrack.mNumMirrorTypeStrings; ++i) + for (i = 0; i < fileTrack.m_numMirrorTypeStrings; ++i) { - mirrorTypeStrings[i] = SharedHelperData::ReadString(file, importParams.mSharedData, endianType); + mirrorTypeStrings[i] = SharedHelperData::ReadString(file, importParams.m_sharedData, endianType); if (GetLogging()) { MCore::LogDetailedInfo(" [%d] = '%s'", i, mirrorTypeStrings[i].c_str()); @@ -982,8 +976,8 @@ namespace EMotionFX // create the default event track MotionEventTrack* track = MotionEventTrack::Create(trackName.c_str(), motion); - track->SetIsEnabled(fileTrack.mIsEnabled != 0); - track->ReserveNumEvents(fileTrack.mNumEvents); + track->SetIsEnabled(fileTrack.m_isEnabled != 0); + track->ReserveNumEvents(fileTrack.m_numEvents); motionEventTable->AddTrack(track); // read all motion events @@ -991,35 +985,35 @@ namespace EMotionFX { MCore::LogDetailedInfo(" + Motion Events:"); } - for (i = 0; i < fileTrack.mNumEvents; ++i) + for (i = 0; i < fileTrack.m_numEvents; ++i) { // read the event header FileFormat::FileMotionEvent fileEvent; file->Read(&fileEvent, sizeof(FileFormat::FileMotionEvent)); // convert endian - MCore::Endian::ConvertUnsignedInt32(&fileEvent.mEventTypeIndex, endianType); - MCore::Endian::ConvertUnsignedInt16(&fileEvent.mParamIndex, endianType); - MCore::Endian::ConvertUnsignedInt32(&fileEvent.mMirrorTypeIndex, endianType); - MCore::Endian::ConvertFloat(&fileEvent.mStartTime, endianType); - MCore::Endian::ConvertFloat(&fileEvent.mEndTime, endianType); + MCore::Endian::ConvertUnsignedInt32(&fileEvent.m_eventTypeIndex, endianType); + MCore::Endian::ConvertUnsignedInt16(&fileEvent.m_paramIndex, endianType); + MCore::Endian::ConvertUnsignedInt32(&fileEvent.m_mirrorTypeIndex, endianType); + MCore::Endian::ConvertFloat(&fileEvent.m_startTime, endianType); + MCore::Endian::ConvertFloat(&fileEvent.m_endTime, endianType); // print motion event information if (GetLogging()) { - MCore::LogDetailedInfo(" [%d] StartTime = %f - EndTime = %f - Type = '%s' - Param = '%s' - Mirror = '%s'", i, fileEvent.mStartTime, fileEvent.mEndTime, typeStrings[fileEvent.mEventTypeIndex].c_str(), paramStrings[fileEvent.mParamIndex].c_str(), mirrorTypeStrings[fileEvent.mMirrorTypeIndex].c_str()); + MCore::LogDetailedInfo(" [%d] StartTime = %f - EndTime = %f - Type = '%s' - Param = '%s' - Mirror = '%s'", i, fileEvent.m_startTime, fileEvent.m_endTime, typeStrings[fileEvent.m_eventTypeIndex].c_str(), paramStrings[fileEvent.m_paramIndex].c_str(), mirrorTypeStrings[fileEvent.m_mirrorTypeIndex].c_str()); } - const AZStd::string eventTypeName = fileEvent.mEventTypeIndex != MCORE_INVALIDINDEX32 ? - typeStrings[fileEvent.mEventTypeIndex] : ""; - const AZStd::string mirrorTypeName = fileEvent.mMirrorTypeIndex != MCORE_INVALIDINDEX32 ? - mirrorTypeStrings[fileEvent.mMirrorTypeIndex] : ""; - const AZStd::string params = paramStrings[fileEvent.mParamIndex]; + const AZStd::string eventTypeName = fileEvent.m_eventTypeIndex != MCORE_INVALIDINDEX32 ? + typeStrings[fileEvent.m_eventTypeIndex] : ""; + const AZStd::string mirrorTypeName = fileEvent.m_mirrorTypeIndex != MCORE_INVALIDINDEX32 ? + mirrorTypeStrings[fileEvent.m_mirrorTypeIndex] : ""; + const AZStd::string params = paramStrings[fileEvent.m_paramIndex]; // add the event track->AddEvent( - fileEvent.mStartTime, - fileEvent.mEndTime, + fileEvent.m_startTime, + fileEvent.m_endTime, GetEventManager().FindOrCreateEventData(eventTypeName, params, mirrorTypeName) ); } @@ -1032,7 +1026,7 @@ namespace EMotionFX bool ChunkProcessorMotionEventTrackTable2::Process(MCore::File* file, Importer::ImportParameters& importParams) { - Motion* motion = importParams.mMotion; + Motion* motion = importParams.m_motion; MCORE_ASSERT(motion); @@ -1071,7 +1065,7 @@ namespace EMotionFX bool ChunkProcessorMotionEventTrackTable3::Process(MCore::File* file, Importer::ImportParameters& importParams) { - Motion* motion = importParams.mMotion; + Motion* motion = importParams.m_motion; MCORE_ASSERT(motion); FileFormat::FileMotionEventTableSerialized fileEventTable; @@ -1122,8 +1116,8 @@ namespace EMotionFX bool ChunkProcessorActorInfo::Process(MCore::File* file, Importer::ImportParameters& importParams) { - const MCore::Endian::EEndianType endianType = importParams.mEndianType; - Actor* actor = importParams.mActor; + const MCore::Endian::EEndianType endianType = importParams.m_endianType; + Actor* actor = importParams.m_actor; MCORE_ASSERT(actor); @@ -1132,10 +1126,10 @@ namespace EMotionFX file->Read(&fileInformation, sizeof(FileFormat::Actor_Info)); // convert endian - MCore::Endian::ConvertUnsignedInt32(&fileInformation.mMotionExtractionNodeIndex, endianType); - MCore::Endian::ConvertUnsignedInt32(&fileInformation.mTrajectoryNodeIndex, endianType); - MCore::Endian::ConvertUnsignedInt32(&fileInformation.mNumLODs, endianType); - MCore::Endian::ConvertFloat(&fileInformation.mRetargetRootOffset, endianType); + MCore::Endian::ConvertUnsignedInt32(&fileInformation.m_motionExtractionNodeIndex, endianType); + MCore::Endian::ConvertUnsignedInt32(&fileInformation.m_trajectoryNodeIndex, endianType); + MCore::Endian::ConvertUnsignedInt32(&fileInformation.m_numLoDs, endianType); + MCore::Endian::ConvertFloat(&fileInformation.m_retargetRootOffset, endianType); if (GetLogging()) { @@ -1143,11 +1137,11 @@ namespace EMotionFX } // read the source application, original filename and the compilation date of the exporter string - SharedHelperData::ReadString(file, importParams.mSharedData, endianType); - SharedHelperData::ReadString(file, importParams.mSharedData, endianType); - SharedHelperData::ReadString(file, importParams.mSharedData, endianType); + SharedHelperData::ReadString(file, importParams.m_sharedData, endianType); + SharedHelperData::ReadString(file, importParams.m_sharedData, endianType); + SharedHelperData::ReadString(file, importParams.m_sharedData, endianType); - const char* name = SharedHelperData::ReadString(file, importParams.mSharedData, endianType); + const char* name = SharedHelperData::ReadString(file, importParams.m_sharedData, endianType); actor->SetName(name); if (GetLogging()) { @@ -1157,20 +1151,19 @@ namespace EMotionFX // print motion event information if (GetLogging()) { - MCore::LogDetailedInfo(" + Exporter version = v%d.%d", fileInformation.mExporterHighVersion, fileInformation.mExporterLowVersion); - MCore::LogDetailedInfo(" + Num LODs = %d", fileInformation.mNumLODs); - MCore::LogDetailedInfo(" + Motion Extraction node = %d", fileInformation.mMotionExtractionNodeIndex); - MCore::LogDetailedInfo(" + Retarget root offset = %f", fileInformation.mRetargetRootOffset); - MCore::LogDetailedInfo(" + UnitType = %d", fileInformation.mUnitType); + MCore::LogDetailedInfo(" + Exporter version = v%d.%d", fileInformation.m_exporterHighVersion, fileInformation.m_exporterLowVersion); + MCore::LogDetailedInfo(" + Num LODs = %d", fileInformation.m_numLoDs); + MCore::LogDetailedInfo(" + Motion Extraction node = %d", fileInformation.m_motionExtractionNodeIndex); + MCore::LogDetailedInfo(" + Retarget root offset = %f", fileInformation.m_retargetRootOffset); + MCore::LogDetailedInfo(" + UnitType = %d", fileInformation.m_unitType); } - actor->SetMotionExtractionNodeIndex(fileInformation.mMotionExtractionNodeIndex); - if (fileInformation.mMotionExtractionNodeIndex != MCORE_INVALIDINDEX32) + actor->SetMotionExtractionNodeIndex(fileInformation.m_motionExtractionNodeIndex); + if (fileInformation.m_motionExtractionNodeIndex != MCORE_INVALIDINDEX32) { - actor->SetMotionExtractionNodeIndex(fileInformation.mMotionExtractionNodeIndex); + actor->SetMotionExtractionNodeIndex(fileInformation.m_motionExtractionNodeIndex); } - // actor->SetRetargetOffset( fileInformation.mRetargetRootOffset ); - actor->SetUnitType(static_cast(fileInformation.mUnitType)); + actor->SetUnitType(static_cast(fileInformation.m_unitType)); actor->SetFileUnitType(actor->GetUnitType()); return true; @@ -1180,17 +1173,17 @@ namespace EMotionFX bool ChunkProcessorActorInfo2::Process(MCore::File* file, Importer::ImportParameters& importParams) { - const MCore::Endian::EEndianType endianType = importParams.mEndianType; - Actor* actor = importParams.mActor; + const MCore::Endian::EEndianType endianType = importParams.m_endianType; + Actor* actor = importParams.m_actor; // read the chunk FileFormat::Actor_Info2 fileInformation; file->Read(&fileInformation, sizeof(FileFormat::Actor_Info2)); // convert endian - MCore::Endian::ConvertUnsignedInt32(&fileInformation.mMotionExtractionNodeIndex, endianType); - MCore::Endian::ConvertUnsignedInt32(&fileInformation.mRetargetRootNodeIndex, endianType); - MCore::Endian::ConvertUnsignedInt32(&fileInformation.mNumLODs, endianType); + MCore::Endian::ConvertUnsignedInt32(&fileInformation.m_motionExtractionNodeIndex, endianType); + MCore::Endian::ConvertUnsignedInt32(&fileInformation.m_retargetRootNodeIndex, endianType); + MCore::Endian::ConvertUnsignedInt32(&fileInformation.m_numLoDs, endianType); if (GetLogging()) { @@ -1198,32 +1191,32 @@ namespace EMotionFX } // read the source application, original filename and the compilation date of the exporter string - SharedHelperData::ReadString(file, importParams.mSharedData, endianType); - SharedHelperData::ReadString(file, importParams.mSharedData, endianType); - SharedHelperData::ReadString(file, importParams.mSharedData, endianType); + SharedHelperData::ReadString(file, importParams.m_sharedData, endianType); + SharedHelperData::ReadString(file, importParams.m_sharedData, endianType); + SharedHelperData::ReadString(file, importParams.m_sharedData, endianType); - const char* name = SharedHelperData::ReadString(file, importParams.mSharedData, endianType); + const char* name = SharedHelperData::ReadString(file, importParams.m_sharedData, endianType); actor->SetName(name); if (GetLogging()) { MCore::LogDetailedInfo(" + Actor name = '%s'", name); - MCore::LogDetailedInfo(" + Exporter version = v%d.%d", fileInformation.mExporterHighVersion, fileInformation.mExporterLowVersion); - MCore::LogDetailedInfo(" + Num LODs = %d", fileInformation.mNumLODs); - MCore::LogDetailedInfo(" + Motion Extraction node = %d", fileInformation.mMotionExtractionNodeIndex); - MCore::LogDetailedInfo(" + Retarget root node = %d", fileInformation.mRetargetRootNodeIndex); - MCore::LogDetailedInfo(" + UnitType = %d", fileInformation.mUnitType); + MCore::LogDetailedInfo(" + Exporter version = v%d.%d", fileInformation.m_exporterHighVersion, fileInformation.m_exporterLowVersion); + MCore::LogDetailedInfo(" + Num LODs = %d", fileInformation.m_numLoDs); + MCore::LogDetailedInfo(" + Motion Extraction node = %d", fileInformation.m_motionExtractionNodeIndex); + MCore::LogDetailedInfo(" + Retarget root node = %d", fileInformation.m_retargetRootNodeIndex); + MCore::LogDetailedInfo(" + UnitType = %d", fileInformation.m_unitType); } - if (fileInformation.mMotionExtractionNodeIndex != MCORE_INVALIDINDEX32) + if (fileInformation.m_motionExtractionNodeIndex != MCORE_INVALIDINDEX32) { - actor->SetMotionExtractionNodeIndex(fileInformation.mMotionExtractionNodeIndex); + actor->SetMotionExtractionNodeIndex(fileInformation.m_motionExtractionNodeIndex); } - if (fileInformation.mRetargetRootNodeIndex != MCORE_INVALIDINDEX32) + if (fileInformation.m_retargetRootNodeIndex != MCORE_INVALIDINDEX32) { - actor->SetRetargetRootNodeIndex(fileInformation.mRetargetRootNodeIndex); + actor->SetRetargetRootNodeIndex(fileInformation.m_retargetRootNodeIndex); } - actor->SetUnitType(static_cast(fileInformation.mUnitType)); + actor->SetUnitType(static_cast(fileInformation.m_unitType)); actor->SetFileUnitType(actor->GetUnitType()); return true; @@ -1233,17 +1226,17 @@ namespace EMotionFX bool ChunkProcessorActorInfo3::Process(MCore::File* file, Importer::ImportParameters& importParams) { - const MCore::Endian::EEndianType endianType = importParams.mEndianType; - Actor* actor = importParams.mActor; + const MCore::Endian::EEndianType endianType = importParams.m_endianType; + Actor* actor = importParams.m_actor; // read the chunk FileFormat::Actor_Info3 fileInformation; file->Read(&fileInformation, sizeof(FileFormat::Actor_Info3)); // convert endian - MCore::Endian::ConvertUnsignedInt32(&fileInformation.mMotionExtractionNodeIndex, endianType); - MCore::Endian::ConvertUnsignedInt32(&fileInformation.mRetargetRootNodeIndex, endianType); - MCore::Endian::ConvertUnsignedInt32(&fileInformation.mNumLODs, endianType); + MCore::Endian::ConvertUnsignedInt32(&fileInformation.m_motionExtractionNodeIndex, endianType); + MCore::Endian::ConvertUnsignedInt32(&fileInformation.m_retargetRootNodeIndex, endianType); + MCore::Endian::ConvertUnsignedInt32(&fileInformation.m_numLoDs, endianType); if (GetLogging()) { @@ -1251,34 +1244,34 @@ namespace EMotionFX } // read the source application, original filename and the compilation date of the exporter string - SharedHelperData::ReadString(file, importParams.mSharedData, endianType); - SharedHelperData::ReadString(file, importParams.mSharedData, endianType); - SharedHelperData::ReadString(file, importParams.mSharedData, endianType); + SharedHelperData::ReadString(file, importParams.m_sharedData, endianType); + SharedHelperData::ReadString(file, importParams.m_sharedData, endianType); + SharedHelperData::ReadString(file, importParams.m_sharedData, endianType); - const char* name = SharedHelperData::ReadString(file, importParams.mSharedData, endianType); + const char* name = SharedHelperData::ReadString(file, importParams.m_sharedData, endianType); actor->SetName(name); if (GetLogging()) { MCore::LogDetailedInfo(" + Actor name = '%s'", name); - MCore::LogDetailedInfo(" + Exporter version = v%d.%d", fileInformation.mExporterHighVersion, fileInformation.mExporterLowVersion); - MCore::LogDetailedInfo(" + Num LODs = %d", fileInformation.mNumLODs); - MCore::LogDetailedInfo(" + Motion Extraction node = %d", fileInformation.mMotionExtractionNodeIndex); - MCore::LogDetailedInfo(" + Retarget root node = %d", fileInformation.mRetargetRootNodeIndex); - MCore::LogDetailedInfo(" + UnitType = %d", fileInformation.mUnitType); + MCore::LogDetailedInfo(" + Exporter version = v%d.%d", fileInformation.m_exporterHighVersion, fileInformation.m_exporterLowVersion); + MCore::LogDetailedInfo(" + Num LODs = %d", fileInformation.m_numLoDs); + MCore::LogDetailedInfo(" + Motion Extraction node = %d", fileInformation.m_motionExtractionNodeIndex); + MCore::LogDetailedInfo(" + Retarget root node = %d", fileInformation.m_retargetRootNodeIndex); + MCore::LogDetailedInfo(" + UnitType = %d", fileInformation.m_unitType); } - if (fileInformation.mMotionExtractionNodeIndex != MCORE_INVALIDINDEX32) + if (fileInformation.m_motionExtractionNodeIndex != MCORE_INVALIDINDEX32) { - actor->SetMotionExtractionNodeIndex(fileInformation.mMotionExtractionNodeIndex); + actor->SetMotionExtractionNodeIndex(fileInformation.m_motionExtractionNodeIndex); } - if (fileInformation.mRetargetRootNodeIndex != MCORE_INVALIDINDEX32) + if (fileInformation.m_retargetRootNodeIndex != MCORE_INVALIDINDEX32) { - actor->SetRetargetRootNodeIndex(fileInformation.mRetargetRootNodeIndex); + actor->SetRetargetRootNodeIndex(fileInformation.m_retargetRootNodeIndex); } - actor->SetUnitType(static_cast(fileInformation.mUnitType)); + actor->SetUnitType(static_cast(fileInformation.m_unitType)); actor->SetFileUnitType(actor->GetUnitType()); - actor->SetOptimizeSkeleton(fileInformation.mOptimizeSkeleton == 0? false : true); + actor->SetOptimizeSkeleton(fileInformation.m_optimizeSkeleton == 0? false : true); return true; } @@ -1288,8 +1281,8 @@ namespace EMotionFX // morph targets bool ChunkProcessorActorProgMorphTarget::Process(MCore::File* file, Importer::ImportParameters& importParams) { - const MCore::Endian::EEndianType endianType = importParams.mEndianType; - Actor* actor = importParams.mActor; + const MCore::Endian::EEndianType endianType = importParams.m_endianType; + Actor* actor = importParams.m_actor; MCORE_ASSERT(actor); Skeleton* skeleton = actor->GetSkeleton(); @@ -1299,27 +1292,27 @@ namespace EMotionFX file->Read(&morphTargetChunk, sizeof(FileFormat::Actor_MorphTarget)); // convert endian - MCore::Endian::ConvertFloat(&morphTargetChunk.mRangeMin, endianType); - MCore::Endian::ConvertFloat(&morphTargetChunk.mRangeMax, endianType); - MCore::Endian::ConvertUnsignedInt32(&morphTargetChunk.mLOD, endianType); - MCore::Endian::ConvertUnsignedInt32(&morphTargetChunk.mNumTransformations, endianType); - MCore::Endian::ConvertUnsignedInt32(&morphTargetChunk.mPhonemeSets, endianType); + MCore::Endian::ConvertFloat(&morphTargetChunk.m_rangeMin, endianType); + MCore::Endian::ConvertFloat(&morphTargetChunk.m_rangeMax, endianType); + MCore::Endian::ConvertUnsignedInt32(&morphTargetChunk.m_lod, endianType); + MCore::Endian::ConvertUnsignedInt32(&morphTargetChunk.m_numTransformations, endianType); + MCore::Endian::ConvertUnsignedInt32(&morphTargetChunk.m_phonemeSets, endianType); // get the expression name - const char* morphTargetName = SharedHelperData::ReadString(file, importParams.mSharedData, endianType); + const char* morphTargetName = SharedHelperData::ReadString(file, importParams.m_sharedData, endianType); // get the level of detail of the expression part - const uint32 morphTargetLOD = morphTargetChunk.mLOD; + const uint32 morphTargetLOD = morphTargetChunk.m_lod; if (GetLogging()) { MCore::LogDetailedInfo(" - Morph Target:"); MCore::LogDetailedInfo(" + Name = '%s'", morphTargetName); - MCore::LogDetailedInfo(" + LOD Level = %d", morphTargetChunk.mLOD); - MCore::LogDetailedInfo(" + RangeMin = %f", morphTargetChunk.mRangeMin); - MCore::LogDetailedInfo(" + RangeMax = %f", morphTargetChunk.mRangeMax); - MCore::LogDetailedInfo(" + NumTransformations = %d", morphTargetChunk.mNumTransformations); - MCore::LogDetailedInfo(" + PhonemeSets: %s", MorphTarget::GetPhonemeSetString((MorphTarget::EPhonemeSet)morphTargetChunk.mPhonemeSets).c_str()); + MCore::LogDetailedInfo(" + LOD Level = %d", morphTargetChunk.m_lod); + MCore::LogDetailedInfo(" + RangeMin = %f", morphTargetChunk.m_rangeMin); + MCore::LogDetailedInfo(" + RangeMax = %f", morphTargetChunk.m_rangeMax); + MCore::LogDetailedInfo(" + NumTransformations = %d", morphTargetChunk.m_numTransformations); + MCore::LogDetailedInfo(" + PhonemeSets: %s", MorphTarget::GetPhonemeSetString((MorphTarget::EPhonemeSet)morphTargetChunk.m_phonemeSets).c_str()); } // check if the morph setup has already been created, if not create it @@ -1336,59 +1329,59 @@ namespace EMotionFX MorphTargetStandard* morphTarget = MorphTargetStandard::Create(morphTargetName); // set the slider range - morphTarget->SetRangeMin(morphTargetChunk.mRangeMin); - morphTarget->SetRangeMax(morphTargetChunk.mRangeMax); + morphTarget->SetRangeMin(morphTargetChunk.m_rangeMin); + morphTarget->SetRangeMax(morphTargetChunk.m_rangeMax); // set the phoneme sets - morphTarget->SetPhonemeSets((MorphTarget::EPhonemeSet)morphTargetChunk.mPhonemeSets); + morphTarget->SetPhonemeSets((MorphTarget::EPhonemeSet)morphTargetChunk.m_phonemeSets); // add the morph target actor->GetMorphSetup(morphTargetLOD)->AddMorphTarget(morphTarget); // read the facial transformations - for (uint32 i = 0; i < morphTargetChunk.mNumTransformations; ++i) + for (uint32 i = 0; i < morphTargetChunk.m_numTransformations; ++i) { // read the facial transformation from disk FileFormat::Actor_MorphTargetTransform transformChunk; file->Read(&transformChunk, sizeof(FileFormat::Actor_MorphTargetTransform)); // create Core objects from the data - AZ::Vector3 pos(transformChunk.mPosition.mX, transformChunk.mPosition.mY, transformChunk.mPosition.mZ); - AZ::Vector3 scale(transformChunk.mScale.mX, transformChunk.mScale.mY, transformChunk.mScale.mZ); - AZ::Quaternion rot(transformChunk.mRotation.mX, transformChunk.mRotation.mY, transformChunk.mRotation.mZ, transformChunk.mRotation.mW); - AZ::Quaternion scaleRot(transformChunk.mScaleRotation.mX, transformChunk.mScaleRotation.mY, transformChunk.mScaleRotation.mZ, transformChunk.mScaleRotation.mW); + AZ::Vector3 pos(transformChunk.m_position.m_x, transformChunk.m_position.m_y, transformChunk.m_position.m_z); + AZ::Vector3 scale(transformChunk.m_scale.m_x, transformChunk.m_scale.m_y, transformChunk.m_scale.m_z); + AZ::Quaternion rot(transformChunk.m_rotation.m_x, transformChunk.m_rotation.m_y, transformChunk.m_rotation.m_z, transformChunk.m_rotation.m_w); + AZ::Quaternion scaleRot(transformChunk.m_scaleRotation.m_x, transformChunk.m_scaleRotation.m_y, transformChunk.m_scaleRotation.m_z, transformChunk.m_scaleRotation.m_w); // convert endian and coordinate system ConvertVector3(&pos, endianType); ConvertScale(&scale, endianType); ConvertQuaternion(&rot, endianType); ConvertQuaternion(&scaleRot, endianType); - MCore::Endian::ConvertUnsignedInt32(&transformChunk.mNodeIndex, endianType); + MCore::Endian::ConvertUnsignedInt32(&transformChunk.m_nodeIndex, endianType); // create our transformation MorphTargetStandard::Transformation transform; - transform.mPosition = pos; - transform.mScale = scale; - transform.mRotation = rot; - transform.mScaleRotation = scaleRot; - transform.mNodeIndex = transformChunk.mNodeIndex; + transform.m_position = pos; + transform.m_scale = scale; + transform.m_rotation = rot; + transform.m_scaleRotation = scaleRot; + transform.m_nodeIndex = transformChunk.m_nodeIndex; if (GetLogging()) { - MCore::LogDetailedInfo(" - Transform #%d: Node='%s' (index=%d)", i, skeleton->GetNode(transform.mNodeIndex)->GetName(), transform.mNodeIndex); + MCore::LogDetailedInfo(" - Transform #%d: Node='%s' (index=%d)", i, skeleton->GetNode(transform.m_nodeIndex)->GetName(), transform.m_nodeIndex); MCore::LogDetailedInfo(" + Pos: %f, %f, %f", - static_cast(transform.mPosition.GetX()), - static_cast(transform.mPosition.GetY()), - static_cast(transform.mPosition.GetZ())); + static_cast(transform.m_position.GetX()), + static_cast(transform.m_position.GetY()), + static_cast(transform.m_position.GetZ())); MCore::LogDetailedInfo(" + Rotation: %f, %f, %f %f", - static_cast(transform.mRotation.GetX()), - static_cast(transform.mRotation.GetY()), - static_cast(transform.mRotation.GetZ()), - static_cast(transform.mRotation.GetW())); + static_cast(transform.m_rotation.GetX()), + static_cast(transform.m_rotation.GetY()), + static_cast(transform.m_rotation.GetZ()), + static_cast(transform.m_rotation.GetW())); MCore::LogDetailedInfo(" + Scale: %f, %f, %f", - static_cast(transform.mScale.GetX()), - static_cast(transform.mScale.GetY()), - static_cast(transform.mScale.GetZ())); + static_cast(transform.m_scale.GetX()), + static_cast(transform.m_scale.GetY()), + static_cast(transform.m_scale.GetZ())); MCore::LogDetailedInfo(" + ScaleRot: %f, %f, %f %f", static_cast(scaleRot.GetX()), static_cast(scaleRot.GetY()), @@ -1408,8 +1401,8 @@ namespace EMotionFX // the node groups chunk bool ChunkProcessorActorNodeGroups::Process(MCore::File* file, Importer::ImportParameters& importParams) { - const MCore::Endian::EEndianType endianType = importParams.mEndianType; - Actor* actor = importParams.mActor; + const MCore::Endian::EEndianType endianType = importParams.m_endianType; + Actor* actor = importParams.m_actor; MCORE_ASSERT(actor); @@ -1429,25 +1422,25 @@ namespace EMotionFX // read the group header FileFormat::Actor_NodeGroup fileGroup; file->Read(&fileGroup, sizeof(FileFormat::Actor_NodeGroup)); - MCore::Endian::ConvertUnsignedInt16(&fileGroup.mNumNodes, endianType); + MCore::Endian::ConvertUnsignedInt16(&fileGroup.m_numNodes, endianType); // read the group name - const char* groupName = SharedHelperData::ReadString(file, importParams.mSharedData, endianType); + const char* groupName = SharedHelperData::ReadString(file, importParams.m_sharedData, endianType); // log some info if (GetLogging()) { MCore::LogDetailedInfo(" + Group '%s'", groupName); - MCore::LogDetailedInfo(" - Num nodes: %d", fileGroup.mNumNodes); - MCore::LogDetailedInfo(" - Disabled on default: %s", fileGroup.mDisabledOnDefault ? "Yes" : "No"); + MCore::LogDetailedInfo(" - Num nodes: %d", fileGroup.m_numNodes); + MCore::LogDetailedInfo(" - Disabled on default: %s", fileGroup.m_disabledOnDefault ? "Yes" : "No"); } // create the new group inside the actor - NodeGroup* newGroup = aznew NodeGroup(groupName, fileGroup.mNumNodes, fileGroup.mDisabledOnDefault ? false : true); + NodeGroup* newGroup = aznew NodeGroup(groupName, fileGroup.m_numNodes, fileGroup.m_disabledOnDefault ? false : true); // read the node numbers uint16 nodeIndex; - for (uint16 n = 0; n < fileGroup.mNumNodes; ++n) + for (uint16 n = 0; n < fileGroup.m_numNodes; ++n) { file->Read(&nodeIndex, sizeof(uint16)); MCore::Endian::ConvertUnsignedInt16(&nodeIndex, endianType); @@ -1465,8 +1458,8 @@ namespace EMotionFX // all submotions in one chunk bool ChunkProcessorMotionMorphSubMotions::Process(MCore::File* file, Importer::ImportParameters& importParams) { - const MCore::Endian::EEndianType endianType = importParams.mEndianType; - Motion* motion = importParams.mMotion; + const MCore::Endian::EEndianType endianType = importParams.m_endianType; + Motion* motion = importParams.m_motion; AZ_Assert(motion, "Expecting a valid motion pointer."); // cast to morph motion @@ -1478,54 +1471,54 @@ namespace EMotionFX file->Read(&subMotionsHeader, sizeof(FileFormat::Motion_MorphSubMotions)); // convert endian - MCore::Endian::ConvertUnsignedInt32(&subMotionsHeader.mNumSubMotions, endianType); + MCore::Endian::ConvertUnsignedInt32(&subMotionsHeader.m_numSubMotions, endianType); // pre-allocate the number of submotions motionData->SetAdditive(importParams.m_additiveMotion); - motionData->Resize(motionData->GetNumJoints(), subMotionsHeader.mNumSubMotions, motionData->GetNumFloats()); + motionData->Resize(motionData->GetNumJoints(), subMotionsHeader.m_numSubMotions, motionData->GetNumFloats()); // for all submotions - for (uint32 s = 0; s < subMotionsHeader.mNumSubMotions; ++s) + for (uint32 s = 0; s < subMotionsHeader.m_numSubMotions; ++s) { // get the morph motion part FileFormat::Motion_MorphSubMotion morphSubMotionChunk; file->Read(&morphSubMotionChunk, sizeof(FileFormat::Motion_MorphSubMotion)); // convert endian - MCore::Endian::ConvertUnsignedInt32(&morphSubMotionChunk.mNumKeys, endianType); - MCore::Endian::ConvertUnsignedInt32(&morphSubMotionChunk.mPhonemeSet, endianType); - MCore::Endian::ConvertFloat(&morphSubMotionChunk.mPoseWeight, endianType); - MCore::Endian::ConvertFloat(&morphSubMotionChunk.mMinWeight, endianType); - MCore::Endian::ConvertFloat(&morphSubMotionChunk.mMaxWeight, endianType); + MCore::Endian::ConvertUnsignedInt32(&morphSubMotionChunk.m_numKeys, endianType); + MCore::Endian::ConvertUnsignedInt32(&morphSubMotionChunk.m_phonemeSet, endianType); + MCore::Endian::ConvertFloat(&morphSubMotionChunk.m_poseWeight, endianType); + MCore::Endian::ConvertFloat(&morphSubMotionChunk.m_minWeight, endianType); + MCore::Endian::ConvertFloat(&morphSubMotionChunk.m_maxWeight, endianType); // read the name of the submotion - const char* name = SharedHelperData::ReadString(file, importParams.mSharedData, endianType); + const char* name = SharedHelperData::ReadString(file, importParams.m_sharedData, endianType); motionData->SetMorphName(s, name); - motionData->AllocateMorphSamples(s, morphSubMotionChunk.mNumKeys); - motionData->SetMorphStaticValue(s, morphSubMotionChunk.mPoseWeight); + motionData->AllocateMorphSamples(s, morphSubMotionChunk.m_numKeys); + motionData->SetMorphStaticValue(s, morphSubMotionChunk.m_poseWeight); if (GetLogging()) { MCore::LogDetailedInfo(" - Morph Submotion: %s", name); - MCore::LogDetailedInfo(" + NrKeys = %d", morphSubMotionChunk.mNumKeys); - MCore::LogDetailedInfo(" + Pose Weight = %f", morphSubMotionChunk.mPoseWeight); - MCore::LogDetailedInfo(" + Minimum Weight = %f", morphSubMotionChunk.mMinWeight); - MCore::LogDetailedInfo(" + Maximum Weight = %f", morphSubMotionChunk.mMaxWeight); - MCore::LogDetailedInfo(" + PhonemeSet = %s", MorphTarget::GetPhonemeSetString((MorphTarget::EPhonemeSet)morphSubMotionChunk.mPhonemeSet).c_str()); + MCore::LogDetailedInfo(" + NrKeys = %d", morphSubMotionChunk.m_numKeys); + MCore::LogDetailedInfo(" + Pose Weight = %f", morphSubMotionChunk.m_poseWeight); + MCore::LogDetailedInfo(" + Minimum Weight = %f", morphSubMotionChunk.m_minWeight); + MCore::LogDetailedInfo(" + Maximum Weight = %f", morphSubMotionChunk.m_maxWeight); + MCore::LogDetailedInfo(" + PhonemeSet = %s", MorphTarget::GetPhonemeSetString((MorphTarget::EPhonemeSet)morphSubMotionChunk.m_phonemeSet).c_str()); } // add keyframes - for (uint32 i = 0; i < morphSubMotionChunk.mNumKeys; ++i) + for (uint32 i = 0; i < morphSubMotionChunk.m_numKeys; ++i) { FileFormat::Motion_UnsignedShortKey keyframeChunk; file->Read(&keyframeChunk, sizeof(FileFormat::Motion_UnsignedShortKey)); - MCore::Endian::ConvertFloat(&keyframeChunk.mTime, endianType); - MCore::Endian::ConvertUnsignedInt16(&keyframeChunk.mValue, endianType); + MCore::Endian::ConvertFloat(&keyframeChunk.m_time, endianType); + MCore::Endian::ConvertUnsignedInt16(&keyframeChunk.m_value, endianType); - const float value = keyframeChunk.mValue / static_cast(std::numeric_limits::max()); - motionData->SetMorphSample(s, i, {keyframeChunk.mTime, value}); + const float value = keyframeChunk.m_value / static_cast(std::numeric_limits::max()); + motionData->SetMorphSample(s, i, {keyframeChunk.m_time, value}); } } // for all submotions @@ -1539,8 +1532,8 @@ namespace EMotionFX // morph targets bool ChunkProcessorActorProgMorphTargets::Process(MCore::File* file, Importer::ImportParameters& importParams) { - const MCore::Endian::EEndianType endianType = importParams.mEndianType; - Actor* actor = importParams.mActor; + const MCore::Endian::EEndianType endianType = importParams.m_endianType; + Actor* actor = importParams.m_actor; MCORE_ASSERT(actor); Skeleton* skeleton = actor->GetSkeleton(); @@ -1550,122 +1543,122 @@ namespace EMotionFX file->Read(&morphTargetsHeader, sizeof(FileFormat::Actor_MorphTargets)); // convert endian - MCore::Endian::ConvertUnsignedInt32(&morphTargetsHeader.mNumMorphTargets, endianType); - MCore::Endian::ConvertUnsignedInt32(&morphTargetsHeader.mLOD, endianType); + MCore::Endian::ConvertUnsignedInt32(&morphTargetsHeader.m_numMorphTargets, endianType); + MCore::Endian::ConvertUnsignedInt32(&morphTargetsHeader.m_lod, endianType); if (GetLogging()) { - MCore::LogDetailedInfo("- Morph targets: %d (LOD=%d)", morphTargetsHeader.mNumMorphTargets, morphTargetsHeader.mLOD); + MCore::LogDetailedInfo("- Morph targets: %d (LOD=%d)", morphTargetsHeader.m_numMorphTargets, morphTargetsHeader.m_lod); } // check if the morph setup has already been created, if not create it - if (actor->GetMorphSetup(morphTargetsHeader.mLOD) == nullptr) + if (actor->GetMorphSetup(morphTargetsHeader.m_lod) == nullptr) { // create the morph setup MorphSetup* morphSetup = MorphSetup::Create(); // set the morph setup - actor->SetMorphSetup(morphTargetsHeader.mLOD, morphSetup); + actor->SetMorphSetup(morphTargetsHeader.m_lod, morphSetup); } // pre-allocate the morph targets - MorphSetup* setup = actor->GetMorphSetup(morphTargetsHeader.mLOD); - setup->ReserveMorphTargets(morphTargetsHeader.mNumMorphTargets); + MorphSetup* setup = actor->GetMorphSetup(morphTargetsHeader.m_lod); + setup->ReserveMorphTargets(morphTargetsHeader.m_numMorphTargets); // read in all morph targets - for (uint32 mt = 0; mt < morphTargetsHeader.mNumMorphTargets; ++mt) + for (uint32 mt = 0; mt < morphTargetsHeader.m_numMorphTargets; ++mt) { // read the expression part from disk FileFormat::Actor_MorphTarget morphTargetChunk; file->Read(&morphTargetChunk, sizeof(FileFormat::Actor_MorphTarget)); // convert endian - MCore::Endian::ConvertFloat(&morphTargetChunk.mRangeMin, endianType); - MCore::Endian::ConvertFloat(&morphTargetChunk.mRangeMax, endianType); - MCore::Endian::ConvertUnsignedInt32(&morphTargetChunk.mLOD, endianType); - MCore::Endian::ConvertUnsignedInt32(&morphTargetChunk.mNumTransformations, endianType); - MCore::Endian::ConvertUnsignedInt32(&morphTargetChunk.mPhonemeSets, endianType); + MCore::Endian::ConvertFloat(&morphTargetChunk.m_rangeMin, endianType); + MCore::Endian::ConvertFloat(&morphTargetChunk.m_rangeMax, endianType); + MCore::Endian::ConvertUnsignedInt32(&morphTargetChunk.m_lod, endianType); + MCore::Endian::ConvertUnsignedInt32(&morphTargetChunk.m_numTransformations, endianType); + MCore::Endian::ConvertUnsignedInt32(&morphTargetChunk.m_phonemeSets, endianType); // make sure they match - MCORE_ASSERT(morphTargetChunk.mLOD == morphTargetsHeader.mLOD); + MCORE_ASSERT(morphTargetChunk.m_lod == morphTargetsHeader.m_lod); // get the expression name - const char* morphTargetName = SharedHelperData::ReadString(file, importParams.mSharedData, endianType); + const char* morphTargetName = SharedHelperData::ReadString(file, importParams.m_sharedData, endianType); // get the level of detail of the expression part - const uint32 morphTargetLOD = morphTargetChunk.mLOD; + const uint32 morphTargetLOD = morphTargetChunk.m_lod; if (GetLogging()) { MCore::LogDetailedInfo(" + Morph Target:"); MCore::LogDetailedInfo(" - Name = '%s'", morphTargetName); - MCore::LogDetailedInfo(" - LOD Level = %d", morphTargetChunk.mLOD); - MCore::LogDetailedInfo(" - RangeMin = %f", morphTargetChunk.mRangeMin); - MCore::LogDetailedInfo(" - RangeMax = %f", morphTargetChunk.mRangeMax); - MCore::LogDetailedInfo(" - NumTransformations = %d", morphTargetChunk.mNumTransformations); - MCore::LogDetailedInfo(" - PhonemeSets: %s", MorphTarget::GetPhonemeSetString((MorphTarget::EPhonemeSet)morphTargetChunk.mPhonemeSets).c_str()); + MCore::LogDetailedInfo(" - LOD Level = %d", morphTargetChunk.m_lod); + MCore::LogDetailedInfo(" - RangeMin = %f", morphTargetChunk.m_rangeMin); + MCore::LogDetailedInfo(" - RangeMax = %f", morphTargetChunk.m_rangeMax); + MCore::LogDetailedInfo(" - NumTransformations = %d", morphTargetChunk.m_numTransformations); + MCore::LogDetailedInfo(" - PhonemeSets: %s", MorphTarget::GetPhonemeSetString((MorphTarget::EPhonemeSet)morphTargetChunk.m_phonemeSets).c_str()); } // create the morph target MorphTargetStandard* morphTarget = MorphTargetStandard::Create(morphTargetName); // set the slider range - morphTarget->SetRangeMin(morphTargetChunk.mRangeMin); - morphTarget->SetRangeMax(morphTargetChunk.mRangeMax); + morphTarget->SetRangeMin(morphTargetChunk.m_rangeMin); + morphTarget->SetRangeMax(morphTargetChunk.m_rangeMax); // set the phoneme sets - morphTarget->SetPhonemeSets((MorphTarget::EPhonemeSet)morphTargetChunk.mPhonemeSets); + morphTarget->SetPhonemeSets((MorphTarget::EPhonemeSet)morphTargetChunk.m_phonemeSets); // add the morph target setup->AddMorphTarget(morphTarget); // the same for the transformations - morphTarget->ReserveTransformations(morphTargetChunk.mNumTransformations); + morphTarget->ReserveTransformations(morphTargetChunk.m_numTransformations); // read the facial transformations - for (uint32 i = 0; i < morphTargetChunk.mNumTransformations; ++i) + for (uint32 i = 0; i < morphTargetChunk.m_numTransformations; ++i) { // read the facial transformation from disk FileFormat::Actor_MorphTargetTransform transformChunk; file->Read(&transformChunk, sizeof(FileFormat::Actor_MorphTargetTransform)); // create Core objects from the data - AZ::Vector3 pos(transformChunk.mPosition.mX, transformChunk.mPosition.mY, transformChunk.mPosition.mZ); - AZ::Vector3 scale(transformChunk.mScale.mX, transformChunk.mScale.mY, transformChunk.mScale.mZ); - AZ::Quaternion rot(transformChunk.mRotation.mX, transformChunk.mRotation.mY, transformChunk.mRotation.mZ, transformChunk.mRotation.mW); - AZ::Quaternion scaleRot(transformChunk.mScaleRotation.mX, transformChunk.mScaleRotation.mY, transformChunk.mScaleRotation.mZ, transformChunk.mScaleRotation.mW); + AZ::Vector3 pos(transformChunk.m_position.m_x, transformChunk.m_position.m_y, transformChunk.m_position.m_z); + AZ::Vector3 scale(transformChunk.m_scale.m_x, transformChunk.m_scale.m_y, transformChunk.m_scale.m_z); + AZ::Quaternion rot(transformChunk.m_rotation.m_x, transformChunk.m_rotation.m_y, transformChunk.m_rotation.m_z, transformChunk.m_rotation.m_w); + AZ::Quaternion scaleRot(transformChunk.m_scaleRotation.m_x, transformChunk.m_scaleRotation.m_y, transformChunk.m_scaleRotation.m_z, transformChunk.m_scaleRotation.m_w); // convert endian and coordinate system ConvertVector3(&pos, endianType); ConvertScale(&scale, endianType); ConvertQuaternion(&rot, endianType); ConvertQuaternion(&scaleRot, endianType); - MCore::Endian::ConvertUnsignedInt32(&transformChunk.mNodeIndex, endianType); + MCore::Endian::ConvertUnsignedInt32(&transformChunk.m_nodeIndex, endianType); // create our transformation MorphTargetStandard::Transformation transform; - transform.mPosition = pos; - transform.mScale = scale; - transform.mRotation = rot; - transform.mScaleRotation = scaleRot; - transform.mNodeIndex = transformChunk.mNodeIndex; + transform.m_position = pos; + transform.m_scale = scale; + transform.m_rotation = rot; + transform.m_scaleRotation = scaleRot; + transform.m_nodeIndex = transformChunk.m_nodeIndex; if (GetLogging()) { - MCore::LogDetailedInfo(" + Transform #%d: Node='%s' (index=%d)", i, skeleton->GetNode(transform.mNodeIndex)->GetName(), transform.mNodeIndex); + MCore::LogDetailedInfo(" + Transform #%d: Node='%s' (index=%d)", i, skeleton->GetNode(transform.m_nodeIndex)->GetName(), transform.m_nodeIndex); MCore::LogDetailedInfo(" - Pos: %f, %f, %f", - static_cast(transform.mPosition.GetX()), - static_cast(transform.mPosition.GetY()), - static_cast(transform.mPosition.GetZ())); + static_cast(transform.m_position.GetX()), + static_cast(transform.m_position.GetY()), + static_cast(transform.m_position.GetZ())); MCore::LogDetailedInfo(" - Rotation: %f, %f, %f %f", - static_cast(transform.mRotation.GetX()), - static_cast(transform.mRotation.GetY()), - static_cast(transform.mRotation.GetZ()), - static_cast(transform.mRotation.GetW())); + static_cast(transform.m_rotation.GetX()), + static_cast(transform.m_rotation.GetY()), + static_cast(transform.m_rotation.GetZ()), + static_cast(transform.m_rotation.GetW())); MCore::LogDetailedInfo(" - Scale: %f, %f, %f", - static_cast(transform.mScale.GetX()), - static_cast(transform.mScale.GetY()), - static_cast(transform.mScale.GetZ())); + static_cast(transform.m_scale.GetX()), + static_cast(transform.m_scale.GetY()), + static_cast(transform.m_scale.GetZ())); MCore::LogDetailedInfo(" - ScaleRot: %f, %f, %f %f", static_cast(scaleRot.GetX()), static_cast(scaleRot.GetY()), @@ -1686,8 +1679,8 @@ namespace EMotionFX // morph targets bool ChunkProcessorActorProgMorphTargets2::Process(MCore::File* file, Importer::ImportParameters& importParams) { - const MCore::Endian::EEndianType endianType = importParams.mEndianType; - Actor* actor = importParams.mActor; + const MCore::Endian::EEndianType endianType = importParams.m_endianType; + Actor* actor = importParams.m_actor; MCORE_ASSERT(actor); Skeleton* skeleton = actor->GetSkeleton(); @@ -1697,122 +1690,122 @@ namespace EMotionFX file->Read(&morphTargetsHeader, sizeof(FileFormat::Actor_MorphTargets)); // convert endian - MCore::Endian::ConvertUnsignedInt32(&morphTargetsHeader.mNumMorphTargets, endianType); - MCore::Endian::ConvertUnsignedInt32(&morphTargetsHeader.mLOD, endianType); + MCore::Endian::ConvertUnsignedInt32(&morphTargetsHeader.m_numMorphTargets, endianType); + MCore::Endian::ConvertUnsignedInt32(&morphTargetsHeader.m_lod, endianType); if (GetLogging()) { - MCore::LogDetailedInfo("- Morph targets: %d (LOD=%d)", morphTargetsHeader.mNumMorphTargets, morphTargetsHeader.mLOD); + MCore::LogDetailedInfo("- Morph targets: %d (LOD=%d)", morphTargetsHeader.m_numMorphTargets, morphTargetsHeader.m_lod); } // check if the morph setup has already been created, if not create it - if (actor->GetMorphSetup(morphTargetsHeader.mLOD) == nullptr) + if (actor->GetMorphSetup(morphTargetsHeader.m_lod) == nullptr) { // create the morph setup MorphSetup* morphSetup = MorphSetup::Create(); // set the morph setup - actor->SetMorphSetup(morphTargetsHeader.mLOD, morphSetup); + actor->SetMorphSetup(morphTargetsHeader.m_lod, morphSetup); } // pre-allocate the morph targets - MorphSetup* setup = actor->GetMorphSetup(morphTargetsHeader.mLOD); - setup->ReserveMorphTargets(morphTargetsHeader.mNumMorphTargets); + MorphSetup* setup = actor->GetMorphSetup(morphTargetsHeader.m_lod); + setup->ReserveMorphTargets(morphTargetsHeader.m_numMorphTargets); // read in all morph targets - for (uint32 mt = 0; mt < morphTargetsHeader.mNumMorphTargets; ++mt) + for (uint32 mt = 0; mt < morphTargetsHeader.m_numMorphTargets; ++mt) { // read the expression part from disk FileFormat::Actor_MorphTarget morphTargetChunk; file->Read(&morphTargetChunk, sizeof(FileFormat::Actor_MorphTarget)); // convert endian - MCore::Endian::ConvertFloat(&morphTargetChunk.mRangeMin, endianType); - MCore::Endian::ConvertFloat(&morphTargetChunk.mRangeMax, endianType); - MCore::Endian::ConvertUnsignedInt32(&morphTargetChunk.mLOD, endianType); - MCore::Endian::ConvertUnsignedInt32(&morphTargetChunk.mNumTransformations, endianType); - MCore::Endian::ConvertUnsignedInt32(&morphTargetChunk.mPhonemeSets, endianType); + MCore::Endian::ConvertFloat(&morphTargetChunk.m_rangeMin, endianType); + MCore::Endian::ConvertFloat(&morphTargetChunk.m_rangeMax, endianType); + MCore::Endian::ConvertUnsignedInt32(&morphTargetChunk.m_lod, endianType); + MCore::Endian::ConvertUnsignedInt32(&morphTargetChunk.m_numTransformations, endianType); + MCore::Endian::ConvertUnsignedInt32(&morphTargetChunk.m_phonemeSets, endianType); // make sure they match - MCORE_ASSERT(morphTargetChunk.mLOD == morphTargetsHeader.mLOD); + MCORE_ASSERT(morphTargetChunk.m_lod == morphTargetsHeader.m_lod); // get the expression name - const char* morphTargetName = SharedHelperData::ReadString(file, importParams.mSharedData, endianType); + const char* morphTargetName = SharedHelperData::ReadString(file, importParams.m_sharedData, endianType); // get the level of detail of the expression part - const uint32 morphTargetLOD = morphTargetChunk.mLOD; + const uint32 morphTargetLOD = morphTargetChunk.m_lod; if (GetLogging()) { MCore::LogDetailedInfo(" + Morph Target:"); MCore::LogDetailedInfo(" - Name = '%s'", morphTargetName); - MCore::LogDetailedInfo(" - LOD Level = %d", morphTargetChunk.mLOD); - MCore::LogDetailedInfo(" - RangeMin = %f", morphTargetChunk.mRangeMin); - MCore::LogDetailedInfo(" - RangeMax = %f", morphTargetChunk.mRangeMax); - MCore::LogDetailedInfo(" - NumTransformations = %d", morphTargetChunk.mNumTransformations); - MCore::LogDetailedInfo(" - PhonemeSets: %s", MorphTarget::GetPhonemeSetString((MorphTarget::EPhonemeSet)morphTargetChunk.mPhonemeSets).c_str()); + MCore::LogDetailedInfo(" - LOD Level = %d", morphTargetChunk.m_lod); + MCore::LogDetailedInfo(" - RangeMin = %f", morphTargetChunk.m_rangeMin); + MCore::LogDetailedInfo(" - RangeMax = %f", morphTargetChunk.m_rangeMax); + MCore::LogDetailedInfo(" - NumTransformations = %d", morphTargetChunk.m_numTransformations); + MCore::LogDetailedInfo(" - PhonemeSets: %s", MorphTarget::GetPhonemeSetString((MorphTarget::EPhonemeSet)morphTargetChunk.m_phonemeSets).c_str()); } // create the morph target MorphTargetStandard* morphTarget = MorphTargetStandard::Create(morphTargetName); // set the slider range - morphTarget->SetRangeMin(morphTargetChunk.mRangeMin); - morphTarget->SetRangeMax(morphTargetChunk.mRangeMax); + morphTarget->SetRangeMin(morphTargetChunk.m_rangeMin); + morphTarget->SetRangeMax(morphTargetChunk.m_rangeMax); // set the phoneme sets - morphTarget->SetPhonemeSets((MorphTarget::EPhonemeSet)morphTargetChunk.mPhonemeSets); + morphTarget->SetPhonemeSets((MorphTarget::EPhonemeSet)morphTargetChunk.m_phonemeSets); // add the morph target setup->AddMorphTarget(morphTarget); // the same for the transformations - morphTarget->ReserveTransformations(morphTargetChunk.mNumTransformations); + morphTarget->ReserveTransformations(morphTargetChunk.m_numTransformations); // read the facial transformations - for (uint32 i = 0; i < morphTargetChunk.mNumTransformations; ++i) + for (uint32 i = 0; i < morphTargetChunk.m_numTransformations; ++i) { // read the facial transformation from disk FileFormat::Actor_MorphTargetTransform transformChunk; file->Read(&transformChunk, sizeof(FileFormat::Actor_MorphTargetTransform)); // create Core objects from the data - AZ::Vector3 pos(transformChunk.mPosition.mX, transformChunk.mPosition.mY, transformChunk.mPosition.mZ); - AZ::Vector3 scale(transformChunk.mScale.mX, transformChunk.mScale.mY, transformChunk.mScale.mZ); - AZ::Quaternion rot(transformChunk.mRotation.mX, transformChunk.mRotation.mY, transformChunk.mRotation.mZ, transformChunk.mRotation.mW); - AZ::Quaternion scaleRot(transformChunk.mScaleRotation.mX, transformChunk.mScaleRotation.mY, transformChunk.mScaleRotation.mZ, transformChunk.mScaleRotation.mW); + AZ::Vector3 pos(transformChunk.m_position.m_x, transformChunk.m_position.m_y, transformChunk.m_position.m_z); + AZ::Vector3 scale(transformChunk.m_scale.m_x, transformChunk.m_scale.m_y, transformChunk.m_scale.m_z); + AZ::Quaternion rot(transformChunk.m_rotation.m_x, transformChunk.m_rotation.m_y, transformChunk.m_rotation.m_z, transformChunk.m_rotation.m_w); + AZ::Quaternion scaleRot(transformChunk.m_scaleRotation.m_x, transformChunk.m_scaleRotation.m_y, transformChunk.m_scaleRotation.m_z, transformChunk.m_scaleRotation.m_w); // convert endian and coordinate system ConvertVector3(&pos, endianType); ConvertScale(&scale, endianType); ConvertQuaternion(&rot, endianType); ConvertQuaternion(&scaleRot, endianType); - MCore::Endian::ConvertUnsignedInt32(&transformChunk.mNodeIndex, endianType); + MCore::Endian::ConvertUnsignedInt32(&transformChunk.m_nodeIndex, endianType); // create our transformation MorphTargetStandard::Transformation transform; - transform.mPosition = pos; - transform.mScale = scale; - transform.mRotation = rot; - transform.mScaleRotation = scaleRot; - transform.mNodeIndex = transformChunk.mNodeIndex; + transform.m_position = pos; + transform.m_scale = scale; + transform.m_rotation = rot; + transform.m_scaleRotation = scaleRot; + transform.m_nodeIndex = transformChunk.m_nodeIndex; if (GetLogging()) { - MCore::LogDetailedInfo(" + Transform #%d: Node='%s' (index=%d)", i, skeleton->GetNode(transform.mNodeIndex)->GetName(), transform.mNodeIndex); + MCore::LogDetailedInfo(" + Transform #%d: Node='%s' (index=%d)", i, skeleton->GetNode(transform.m_nodeIndex)->GetName(), transform.m_nodeIndex); MCore::LogDetailedInfo(" - Pos: %f, %f, %f", - static_cast(transform.mPosition.GetX()), - static_cast(transform.mPosition.GetY()), - static_cast(transform.mPosition.GetZ())); + static_cast(transform.m_position.GetX()), + static_cast(transform.m_position.GetY()), + static_cast(transform.m_position.GetZ())); MCore::LogDetailedInfo(" - Rotation: %f, %f, %f %f", - static_cast(transform.mRotation.GetX()), - static_cast(transform.mRotation.GetY()), - static_cast(transform.mRotation.GetZ()), - static_cast(transform.mRotation.GetW())); + static_cast(transform.m_rotation.GetX()), + static_cast(transform.m_rotation.GetY()), + static_cast(transform.m_rotation.GetZ()), + static_cast(transform.m_rotation.GetW())); MCore::LogDetailedInfo(" - Scale: %f, %f, %f", - static_cast(transform.mScale.GetX()), - static_cast(transform.mScale.GetY()), - static_cast(transform.mScale.GetZ())); + static_cast(transform.m_scale.GetX()), + static_cast(transform.m_scale.GetY()), + static_cast(transform.m_scale.GetZ())); MCore::LogDetailedInfo(" - ScaleRot: %f, %f, %f %f", static_cast(scaleRot.GetX()), static_cast(scaleRot.GetY()), @@ -1834,8 +1827,8 @@ namespace EMotionFX // the node motion sources chunk bool ChunkProcessorActorNodeMotionSources::Process(MCore::File* file, Importer::ImportParameters& importParams) { - const MCore::Endian::EEndianType endianType = importParams.mEndianType; - Actor* actor = importParams.mActor; + const MCore::Endian::EEndianType endianType = importParams.m_endianType; + Actor* actor = importParams.m_actor; uint32 i; MCORE_ASSERT(actor); @@ -1846,8 +1839,8 @@ namespace EMotionFX file->Read(&nodeMotionSourcesChunk, sizeof(FileFormat::Actor_NodeMotionSources2)); // convert endian - MCore::Endian::ConvertUnsignedInt32(&nodeMotionSourcesChunk.mNumNodes, endianType); - const uint32 numNodes = nodeMotionSourcesChunk.mNumNodes; + MCore::Endian::ConvertUnsignedInt32(&nodeMotionSourcesChunk.m_numNodes, endianType); + const uint32 numNodes = nodeMotionSourcesChunk.m_numNodes; if (numNodes == 0) { return true; @@ -1864,7 +1857,7 @@ namespace EMotionFX uint16 sourceNode; file->Read(&sourceNode, sizeof(uint16)); MCore::Endian::ConvertUnsignedInt16(&sourceNode, endianType); - actor->GetNodeMirrorInfo(i).mSourceNode = sourceNode; + actor->GetNodeMirrorInfo(i).m_sourceNode = sourceNode; } // read all axes @@ -1872,7 +1865,7 @@ namespace EMotionFX { uint8 axis; file->Read(&axis, sizeof(uint8)); - actor->GetNodeMirrorInfo(i).mAxis = axis; + actor->GetNodeMirrorInfo(i).m_axis = axis; } // read all flags @@ -1880,7 +1873,7 @@ namespace EMotionFX { uint8 flags; file->Read(&flags, sizeof(uint8)); - actor->GetNodeMirrorInfo(i).mFlags = flags; + actor->GetNodeMirrorInfo(i).m_flags = flags; } // log details @@ -1889,9 +1882,9 @@ namespace EMotionFX MCore::LogDetailedInfo("- Node Motion Sources (%i):", numNodes); for (i = 0; i < numNodes; ++i) { - if (actor->GetNodeMirrorInfo(i).mSourceNode != MCORE_INVALIDINDEX16) + if (actor->GetNodeMirrorInfo(i).m_sourceNode != MCORE_INVALIDINDEX16) { - MCore::LogDetailedInfo(" + '%s' (%i) -> '%s' (%i) [axis=%d] [flags=%d]", skeleton->GetNode(i)->GetName(), i, skeleton->GetNode(actor->GetNodeMirrorInfo(i).mSourceNode)->GetName(), actor->GetNodeMirrorInfo(i).mSourceNode, actor->GetNodeMirrorInfo(i).mAxis, actor->GetNodeMirrorInfo(i).mFlags); + MCore::LogDetailedInfo(" + '%s' (%i) -> '%s' (%i) [axis=%d] [flags=%d]", skeleton->GetNode(i)->GetName(), i, skeleton->GetNode(actor->GetNodeMirrorInfo(i).m_sourceNode)->GetName(), actor->GetNodeMirrorInfo(i).m_sourceNode, actor->GetNodeMirrorInfo(i).m_axis, actor->GetNodeMirrorInfo(i).m_flags); } } } @@ -1904,8 +1897,8 @@ namespace EMotionFX bool ChunkProcessorActorAttachmentNodes::Process(MCore::File* file, Importer::ImportParameters& importParams) { - const MCore::Endian::EEndianType endianType = importParams.mEndianType; - Actor* actor = importParams.mActor; + const MCore::Endian::EEndianType endianType = importParams.m_endianType; + Actor* actor = importParams.m_actor; MCORE_ASSERT(actor); Skeleton* skeleton = actor->GetSkeleton(); @@ -1915,8 +1908,8 @@ namespace EMotionFX file->Read(&attachmentNodesChunk, sizeof(FileFormat::Actor_AttachmentNodes)); // convert endian - MCore::Endian::ConvertUnsignedInt32(&attachmentNodesChunk.mNumNodes, endianType); - const uint32 numAttachmentNodes = attachmentNodesChunk.mNumNodes; + MCore::Endian::ConvertUnsignedInt32(&attachmentNodesChunk.m_numNodes, endianType); + const uint32 numAttachmentNodes = attachmentNodesChunk.m_numNodes; // read all node attachment nodes for (uint32 i = 0; i < numAttachmentNodes; ++i) @@ -1963,35 +1956,35 @@ namespace EMotionFX // node map bool ChunkProcessorNodeMap::Process(MCore::File* file, Importer::ImportParameters& importParams) { - const MCore::Endian::EEndianType endianType = importParams.mEndianType; + const MCore::Endian::EEndianType endianType = importParams.m_endianType; // read the header FileFormat::NodeMapChunk nodeMapChunk; file->Read(&nodeMapChunk, sizeof(FileFormat::NodeMapChunk)); // convert endian - MCore::Endian::ConvertUnsignedInt32(&nodeMapChunk.mNumEntries, endianType); + MCore::Endian::ConvertUnsignedInt32(&nodeMapChunk.m_numEntries, endianType); // load the source actor filename string, but discard it - SharedHelperData::ReadString(file, importParams.mSharedData, endianType); + SharedHelperData::ReadString(file, importParams.m_sharedData, endianType); // log some info if (GetLogging()) { MCore::LogDetailedInfo("- Node Map:"); - MCore::LogDetailedInfo(" + Num entries = %d", nodeMapChunk.mNumEntries); + MCore::LogDetailedInfo(" + Num entries = %d", nodeMapChunk.m_numEntries); } // for all entries - const uint32 numEntries = nodeMapChunk.mNumEntries; - importParams.mNodeMap->Reserve(numEntries); + const uint32 numEntries = nodeMapChunk.m_numEntries; + importParams.m_nodeMap->Reserve(numEntries); AZStd::string firstName; AZStd::string secondName; for (uint32 i = 0; i < numEntries; ++i) { // read both names - firstName = SharedHelperData::ReadString(file, importParams.mSharedData, endianType); - secondName = SharedHelperData::ReadString(file, importParams.mSharedData, endianType); + firstName = SharedHelperData::ReadString(file, importParams.m_sharedData, endianType); + secondName = SharedHelperData::ReadString(file, importParams.m_sharedData, endianType); if (GetLogging()) { @@ -1999,9 +1992,9 @@ namespace EMotionFX } // create the entry - if (importParams.mNodeMapSettings->mLoadNodes) + if (importParams.m_nodeMapSettings->m_loadNodes) { - importParams.mNodeMap->AddEntry(firstName.c_str(), secondName.c_str()); + importParams.m_nodeMap->AddEntry(firstName.c_str(), secondName.c_str()); } } @@ -2019,12 +2012,12 @@ namespace EMotionFX { return false; } - MCore::Endian::ConvertUnsignedInt32(&dataHeader.m_sizeInBytes, importParams.mEndianType); - MCore::Endian::ConvertUnsignedInt32(&dataHeader.m_dataVersion, importParams.mEndianType); + MCore::Endian::ConvertUnsignedInt32(&dataHeader.m_sizeInBytes, importParams.m_endianType); + MCore::Endian::ConvertUnsignedInt32(&dataHeader.m_dataVersion, importParams.m_endianType); // Read the strings. - const AZStd::string uuidString = SharedHelperData::ReadString(file, importParams.mSharedData, importParams.mEndianType); - const AZStd::string className = SharedHelperData::ReadString(file, importParams.mSharedData, importParams.mEndianType); + const AZStd::string uuidString = SharedHelperData::ReadString(file, importParams.m_sharedData, importParams.m_endianType); + const AZStd::string className = SharedHelperData::ReadString(file, importParams.m_sharedData, importParams.m_endianType); // Create the motion data of this type. const AZ::Uuid uuid = AZ::Uuid::CreateString(uuidString.c_str(), uuidString.size()); @@ -2035,25 +2028,25 @@ namespace EMotionFX { AZ_Assert(false, "Unsupported motion data type '%s' using uuid '%s'", className.c_str(), uuidString.c_str()); motionData = aznew UniformMotionData(); // Create an empty dummy motion data, so we don't break things. - importParams.mMotion->SetMotionData(motionData); + importParams.m_motion->SetMotionData(motionData); file->Forward(dataHeader.m_sizeInBytes); return false; } // Read the data. MotionData::ReadSettings readSettings; - readSettings.m_sourceEndianType = importParams.mEndianType; + readSettings.m_sourceEndianType = importParams.m_endianType; readSettings.m_logDetails = GetLogging(); readSettings.m_version = dataHeader.m_dataVersion; if (!motionData->Read(file, readSettings)) { AZ_Error("EMotionFX", false, "Failed to load motion data of type '%s'", className.c_str()); motionData = aznew UniformMotionData(); // Create an empty dummy motion data, so we don't break things. - importParams.mMotion->SetMotionData(motionData); + importParams.m_motion->SetMotionData(motionData); return false; } - importParams.mMotion->SetMotionData(motionData); + importParams.m_motion->SetMotionData(motionData); return true; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ChunkProcessors.h b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ChunkProcessors.h index 66a2193b71..4dc6d11acb 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ChunkProcessors.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ChunkProcessors.h @@ -97,11 +97,11 @@ namespace EMotionFX static const char* ReadString(MCore::Stream* file, AZStd::vector* sharedData, MCore::Endian::EEndianType endianType); public: - uint32 mFileHighVersion; /**< The high file version. For example 3 in case of v3.10. */ - uint32 mFileLowVersion; /**< The low file version. For example 10 in case of v3.10. */ - uint32 mStringStorageSize; /**< The size of the string buffer. */ - bool mIsUnicodeFile; /**< True in case strings in the file are saved using unicode character set, false in case they are saved using multi-byte. */ - char* mStringStorage; /**< The shared string buffer. */ + uint32 m_fileHighVersion; /**< The high file version. For example 3 in case of v3.10. */ + uint32 m_fileLowVersion; /**< The low file version. For example 10 in case of v3.10. */ + uint32 m_stringStorageSize; /**< The size of the string buffer. */ + bool m_isUnicodeFile; /**< True in case strings in the file are saved using unicode character set, false in case they are saved using multi-byte. */ + char* m_stringStorage; /**< The shared string buffer. */ protected: /** * The constructor. @@ -213,12 +213,12 @@ namespace EMotionFX // rmalize and make sure their w components are positive for (uint32 i = 0; i < count; ++i) { - if (value[i].mW < 0) + if (value[i].m_w < 0) { - value[i].mX = -value[i].mX; - value[i].mY = -value[i].mY; - value[i].mZ = -value[i].mZ; - value[i].mW = -value[i].mW; + value[i].m_x = -value[i].m_x; + value[i].m_y = -value[i].m_y; + value[i].m_z = -value[i].m_z; + value[i].m_w = -value[i].m_w; } } } @@ -238,9 +238,9 @@ namespace EMotionFX } protected: - uint32 mChunkID; /**< The id of the chunk processor. */ - uint32 mVersion; /**< The version number of the chunk processor, to provide backward compatibility. */ - bool mLoggingActive; /**< When set to true the processor chunk will log events, otherwise no logging will be performed. */ + uint32 m_chunkId; /**< The id of the chunk processor. */ + uint32 m_version; /**< The version number of the chunk processor, to provide backward compatibility. */ + bool m_loggingActive; /**< When set to true the processor chunk will log events, otherwise no logging will be performed. */ /** * The constructor. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/Importer.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/Importer.cpp index e2cc633012..762fd29dcb 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/Importer.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/Importer.cpp @@ -51,8 +51,8 @@ namespace EMotionFX RegisterStandardChunks(); // init some default values - mLoggingActive = true; - mLogDetails = false; + m_loggingActive = true; + m_logDetails = false; } @@ -60,7 +60,7 @@ namespace EMotionFX Importer::~Importer() { // remove all chunk processors - for (ChunkProcessor* chunkProcessor : mChunkProcessors) + for (ChunkProcessor* chunkProcessor : m_chunkProcessors) { chunkProcessor->Destroy(); } @@ -88,13 +88,13 @@ namespace EMotionFX } // check the FOURCC - if (header.mFourcc[0] != 'A' || header.mFourcc[1] != 'C' || header.mFourcc[2] != 'T' || header.mFourcc[3] != 'R') + if (header.m_fourcc[0] != 'A' || header.m_fourcc[1] != 'C' || header.m_fourcc[2] != 'T' || header.m_fourcc[3] != 'R') { return false; } // read the chunks - switch (header.mEndianType) + switch (header.m_endianType) { case 0: *outEndianType = MCore::Endian::ENDIAN_LITTLE; @@ -103,7 +103,7 @@ namespace EMotionFX *outEndianType = MCore::Endian::ENDIAN_BIG; break; default: - MCore::LogError("Unsupported endian type used! (endian type = %d)", header.mEndianType); + MCore::LogError("Unsupported endian type used! (endian type = %d)", header.m_endianType); return false; } @@ -127,13 +127,13 @@ namespace EMotionFX } // check the FOURCC - if ((header.mFourcc[0] != 'M' || header.mFourcc[1] != 'O' || header.mFourcc[2] != 'T' || header.mFourcc[3] != ' ')) + if ((header.m_fourcc[0] != 'M' || header.m_fourcc[1] != 'O' || header.m_fourcc[2] != 'T' || header.m_fourcc[3] != ' ')) { return false; } // read the chunks - switch (header.mEndianType) + switch (header.m_endianType) { case 0: *outEndianType = MCore::Endian::ENDIAN_LITTLE; @@ -142,7 +142,7 @@ namespace EMotionFX *outEndianType = MCore::Endian::ENDIAN_BIG; break; default: - MCore::LogError("Unsupported endian type used! (endian type = %d)", header.mEndianType); + MCore::LogError("Unsupported endian type used! (endian type = %d)", header.m_endianType); return false; } @@ -164,13 +164,13 @@ namespace EMotionFX } // check the FOURCC - if (header.mFourCC[0] != 'N' || header.mFourCC[1] != 'O' || header.mFourCC[2] != 'M' || header.mFourCC[3] != 'P') + if (header.m_fourCc[0] != 'N' || header.m_fourCc[1] != 'O' || header.m_fourCc[2] != 'M' || header.m_fourCc[3] != 'P') { return false; } // read the chunks - switch (header.mEndianType) + switch (header.m_endianType) { case 0: *outEndianType = MCore::Endian::ENDIAN_LITTLE; @@ -179,7 +179,7 @@ namespace EMotionFX *outEndianType = MCore::Endian::ENDIAN_BIG; break; default: - MCore::LogError("Unsupported endian type used! (endian type = %d)", header.mEndianType); + MCore::LogError("Unsupported endian type used! (endian type = %d)", header.m_endianType); return false; } @@ -305,7 +305,7 @@ namespace EMotionFX actorSettings = *settings; } - if (actorSettings.mOptimizeForServer) + if (actorSettings.m_optimizeForServer) { actorSettings.OptimizeForServer(); } @@ -319,17 +319,17 @@ namespace EMotionFX if (actor) { - actor->SetThreadIndex(actorSettings.mThreadIndex); + actor->SetThreadIndex(actorSettings.m_threadIndex); // set the scale mode // actor->SetScaleMode( scaleMode ); // init the import parameters ImportParameters params; - params.mSharedData = &sharedData; - params.mEndianType = endianType; - params.mActorSettings = &actorSettings; - params.mActor = actor.get(); + params.m_sharedData = &sharedData; + params.m_endianType = endianType; + params.m_actorSettings = &actorSettings; + params.m_actor = actor.get(); // process all chunks while (ProcessChunk(f, params)) @@ -339,13 +339,13 @@ namespace EMotionFX actor->SetFileName(filename); // Generate an optimized version of skeleton for server. - if (actorSettings.mOptimizeForServer && actor->GetOptimizeSkeleton()) + if (actorSettings.m_optimizeForServer && actor->GetOptimizeSkeleton()) { actor->GenerateOptimizedSkeleton(); } // post create init - actor->PostCreateInit(actorSettings.mMakeGeomLODsCompatibleWithSkeletalLODs, actorSettings.mUnitTypeConvert); + actor->PostCreateInit(actorSettings.m_makeGeomLoDsCompatibleWithSkeletalLoDs, actorSettings.m_unitTypeConvert); } // close the file and return a pointer to the actor we loaded @@ -367,7 +367,7 @@ namespace EMotionFX EBUS_EVENT(AzFramework::ApplicationRequests::Bus, NormalizePathKeepCase, filename); // check if we want to load the motion even if a motion with the given filename is already inside the motion manager - if (settings == nullptr || (settings && settings->mForceLoading == false)) + if (settings == nullptr || (settings && settings->m_forceLoading == false)) { // search the motion inside the motion manager and return it if it already got loaded Motion* motion = GetMotionManager().FindMotionByFileName(filename.c_str()); @@ -481,10 +481,10 @@ namespace EMotionFX // init the import parameters ImportParameters params; - params.mSharedData = &sharedData; - params.mEndianType = endianType; - params.mMotionSettings = &motionSettings; - params.mMotion = motion; + params.m_sharedData = &sharedData; + params.m_endianType = endianType; + params.m_motionSettings = &motionSettings; + params.m_motion = motion; // read the chunks while (ProcessChunk(f, params)) @@ -495,7 +495,7 @@ namespace EMotionFX motion->GetEventTable()->AutoCreateSyncTrack(motion); // scale to the EMotion FX unit type - if (motionSettings.mUnitTypeConvert) + if (motionSettings.m_unitTypeConvert) { motion->ScaleToUnitType(GetEMotionFX().GetUnitType()); } @@ -671,7 +671,7 @@ namespace EMotionFX // load the file header FileFormat::NodeMap_Header fileHeader; f->Read(&fileHeader, sizeof(FileFormat::NodeMap_Header)); - if (fileHeader.mFourCC[0] != 'N' || fileHeader.mFourCC[1] != 'O' || fileHeader.mFourCC[2] != 'M' || fileHeader.mFourCC[3] != 'P') + if (fileHeader.m_fourCc[0] != 'N' || fileHeader.m_fourCc[1] != 'O' || fileHeader.m_fourCc[2] != 'M' || fileHeader.m_fourCc[3] != 'P') { MCore::LogError("The node map file is not a valid node map file."); f->Close(); @@ -679,17 +679,17 @@ namespace EMotionFX } // get the endian type - MCore::Endian::EEndianType endianType = (MCore::Endian::EEndianType)fileHeader.mEndianType; + MCore::Endian::EEndianType endianType = (MCore::Endian::EEndianType)fileHeader.m_endianType; // create the node map NodeMap* nodeMap = NodeMap::Create(); // init the import parameters ImportParameters params; - params.mSharedData = &sharedData; - params.mEndianType = endianType; - params.mNodeMap = nodeMap; - params.mNodeMapSettings = &nodeMapSettings; + params.m_sharedData = &sharedData; + params.m_endianType = endianType; + params.m_nodeMap = nodeMap; + params.m_nodeMapSettings = &nodeMapSettings; // process all chunks while (ProcessChunk(f, params)) @@ -713,7 +713,7 @@ namespace EMotionFX void Importer::RegisterChunkProcessor(ChunkProcessor* processorToRegister) { MCORE_ASSERT(processorToRegister); - mChunkProcessors.emplace_back(processorToRegister); + m_chunkProcessors.emplace_back(processorToRegister); } @@ -739,31 +739,31 @@ namespace EMotionFX void Importer::SetLoggingEnabled(bool enabled) { - mLoggingActive = enabled; + m_loggingActive = enabled; } bool Importer::GetLogging() const { - return mLoggingActive; + return m_loggingActive; } void Importer::SetLogDetails(bool detailLoggingActive) { - mLogDetails = detailLoggingActive; + m_logDetails = detailLoggingActive; // set the processors logging flag - for (ChunkProcessor* processor : mChunkProcessors) + for (ChunkProcessor* processor : m_chunkProcessors) { - processor->SetLogging(mLoggingActive && detailLoggingActive); // only enable if logging is also enabled + processor->SetLogging(m_loggingActive && detailLoggingActive); // only enable if logging is also enabled } } bool Importer::GetLogDetails() const { - return mLogDetails; + return m_logDetails; } @@ -790,11 +790,11 @@ namespace EMotionFX ChunkProcessor* Importer::FindChunk(uint32 chunkID, uint32 version) const { // for all chunk processors - const auto foundProcessor = AZStd::find_if(begin(mChunkProcessors), end(mChunkProcessors), [chunkID, version](const ChunkProcessor* processor) + const auto foundProcessor = AZStd::find_if(begin(m_chunkProcessors), end(m_chunkProcessors), [chunkID, version](const ChunkProcessor* processor) { return processor->GetChunkID() == chunkID && processor->GetVersion() == version; }); - return foundProcessor != end(mChunkProcessors) ? *foundProcessor : nullptr; + return foundProcessor != end(m_chunkProcessors) ? *foundProcessor : nullptr; } @@ -802,7 +802,7 @@ namespace EMotionFX void Importer::RegisterStandardChunks() { // reserve space for 75 chunk processors - mChunkProcessors.reserve(75); + m_chunkProcessors.reserve(75); // shared processors RegisterChunkProcessor(aznew ChunkProcessorMotionEventTrackTable()); @@ -853,40 +853,40 @@ namespace EMotionFX return false; // failed reading chunk } // convert endian - const MCore::Endian::EEndianType endianType = importParams.mEndianType; - MCore::Endian::ConvertUnsignedInt32(&chunk.mChunkID, endianType); - MCore::Endian::ConvertUnsignedInt32(&chunk.mSizeInBytes, endianType); - MCore::Endian::ConvertUnsignedInt32(&chunk.mVersion, endianType); + const MCore::Endian::EEndianType endianType = importParams.m_endianType; + MCore::Endian::ConvertUnsignedInt32(&chunk.m_chunkId, endianType); + MCore::Endian::ConvertUnsignedInt32(&chunk.m_sizeInBytes, endianType); + MCore::Endian::ConvertUnsignedInt32(&chunk.m_version, endianType); // try to find the chunk processor which can process this chunk - ChunkProcessor* processor = FindChunk(chunk.mChunkID, chunk.mVersion); + ChunkProcessor* processor = FindChunk(chunk.m_chunkId, chunk.m_version); // if we cannot find the chunk, skip the chunk if (processor == nullptr) { if (GetLogging()) { - MCore::LogError("Importer::ProcessChunk() - Unknown chunk (ID=%d Size=%d bytes Version=%d), skipping...", chunk.mChunkID, chunk.mSizeInBytes, chunk.mVersion); + MCore::LogError("Importer::ProcessChunk() - Unknown chunk (ID=%d Size=%d bytes Version=%d), skipping...", chunk.m_chunkId, chunk.m_sizeInBytes, chunk.m_version); } - file->Forward(chunk.mSizeInBytes); + file->Forward(chunk.m_sizeInBytes); return true; } // get some shortcuts - Importer::ActorSettings* actorSettings = importParams.mActorSettings; - Importer::MotionSettings* skelMotionSettings = importParams.mMotionSettings; + Importer::ActorSettings* actorSettings = importParams.m_actorSettings; + Importer::MotionSettings* skelMotionSettings = importParams.m_motionSettings; // check if we still want to skip the chunk or not bool mustSkip = false; // check if we specified to ignore this chunk - if (actorSettings && AZStd::find(begin(actorSettings->mChunkIDsToIgnore), end(actorSettings->mChunkIDsToIgnore), chunk.mChunkID) != end(actorSettings->mChunkIDsToIgnore)) + if (actorSettings && AZStd::find(begin(actorSettings->m_chunkIDsToIgnore), end(actorSettings->m_chunkIDsToIgnore), chunk.m_chunkId) != end(actorSettings->m_chunkIDsToIgnore)) { mustSkip = true; } - if (skelMotionSettings && AZStd::find(begin(skelMotionSettings->mChunkIDsToIgnore), end(skelMotionSettings->mChunkIDsToIgnore), chunk.mChunkID) != end(skelMotionSettings->mChunkIDsToIgnore)) + if (skelMotionSettings && AZStd::find(begin(skelMotionSettings->m_chunkIDsToIgnore), end(skelMotionSettings->m_chunkIDsToIgnore), chunk.m_chunkId) != end(skelMotionSettings->m_chunkIDsToIgnore)) { mustSkip = true; } @@ -897,10 +897,10 @@ namespace EMotionFX // if we're loading an actor if (actorSettings) { - if ((actorSettings->mLoadLimits == false && chunk.mChunkID == FileFormat::ACTOR_CHUNK_LIMIT) || - (actorSettings->mLoadMorphTargets == false && chunk.mChunkID == FileFormat::ACTOR_CHUNK_STDPROGMORPHTARGET) || - (actorSettings->mLoadMorphTargets == false && chunk.mChunkID == FileFormat::ACTOR_CHUNK_STDPMORPHTARGETS) || - (actorSettings->mLoadSimulatedObjects == false && chunk.mChunkID == FileFormat::ACTOR_CHUNK_SIMULATEDOBJECTSETUP)) + if ((actorSettings->m_loadLimits == false && chunk.m_chunkId == FileFormat::ACTOR_CHUNK_LIMIT) || + (actorSettings->m_loadMorphTargets == false && chunk.m_chunkId == FileFormat::ACTOR_CHUNK_STDPROGMORPHTARGET) || + (actorSettings->m_loadMorphTargets == false && chunk.m_chunkId == FileFormat::ACTOR_CHUNK_STDPMORPHTARGETS) || + (actorSettings->m_loadSimulatedObjects == false && chunk.m_chunkId == FileFormat::ACTOR_CHUNK_SIMULATEDOBJECTSETUP)) { mustSkip = true; } @@ -909,7 +909,7 @@ namespace EMotionFX // if we're loading a motion if (skelMotionSettings) { - if (skelMotionSettings->mLoadMotionEvents == false && chunk.mChunkID == FileFormat::MOTION_CHUNK_MOTIONEVENTTABLE) + if (skelMotionSettings->m_loadMotionEvents == false && chunk.m_chunkId == FileFormat::MOTION_CHUNK_MOTIONEVENTTABLE) { mustSkip = true; } @@ -919,7 +919,7 @@ namespace EMotionFX // if we want to skip this chunk if (mustSkip) { - file->Forward(chunk.mSizeInBytes); + file->Forward(chunk.m_sizeInBytes); return true; } @@ -932,28 +932,28 @@ namespace EMotionFX void Importer::ValidateActorSettings(ActorSettings* settings) { // After atom: Make sure we are not loading the tangents and bitangents - if (AZStd::find(begin(settings->mLayerIDsToIgnore), end(settings->mLayerIDsToIgnore), Mesh::ATTRIB_TANGENTS) == end(settings->mLayerIDsToIgnore)) + if (AZStd::find(begin(settings->m_layerIDsToIgnore), end(settings->m_layerIDsToIgnore), Mesh::ATTRIB_TANGENTS) == end(settings->m_layerIDsToIgnore)) { - settings->mLayerIDsToIgnore.emplace_back(Mesh::ATTRIB_TANGENTS); + settings->m_layerIDsToIgnore.emplace_back(Mesh::ATTRIB_TANGENTS); } - if (AZStd::find(begin(settings->mLayerIDsToIgnore), end(settings->mLayerIDsToIgnore), Mesh::ATTRIB_BITANGENTS) == end(settings->mLayerIDsToIgnore)) + if (AZStd::find(begin(settings->m_layerIDsToIgnore), end(settings->m_layerIDsToIgnore), Mesh::ATTRIB_BITANGENTS) == end(settings->m_layerIDsToIgnore)) { - settings->mLayerIDsToIgnore.emplace_back(Mesh::ATTRIB_BITANGENTS); + settings->m_layerIDsToIgnore.emplace_back(Mesh::ATTRIB_BITANGENTS); } // make sure we load at least the position and normals and org vertex numbers - if(const auto it = AZStd::find(begin(settings->mLayerIDsToIgnore), end(settings->mLayerIDsToIgnore), Mesh::ATTRIB_ORGVTXNUMBERS); it != end(settings->mLayerIDsToIgnore)) + if(const auto it = AZStd::find(begin(settings->m_layerIDsToIgnore), end(settings->m_layerIDsToIgnore), Mesh::ATTRIB_ORGVTXNUMBERS); it != end(settings->m_layerIDsToIgnore)) { - settings->mLayerIDsToIgnore.erase(it); + settings->m_layerIDsToIgnore.erase(it); } - if(const auto it = AZStd::find(begin(settings->mLayerIDsToIgnore), end(settings->mLayerIDsToIgnore), Mesh::ATTRIB_NORMALS); it != end(settings->mLayerIDsToIgnore)) + if(const auto it = AZStd::find(begin(settings->m_layerIDsToIgnore), end(settings->m_layerIDsToIgnore), Mesh::ATTRIB_NORMALS); it != end(settings->m_layerIDsToIgnore)) { - settings->mLayerIDsToIgnore.erase(it); + settings->m_layerIDsToIgnore.erase(it); } - if(const auto it = AZStd::find(begin(settings->mLayerIDsToIgnore), end(settings->mLayerIDsToIgnore), Mesh::ATTRIB_POSITIONS); it != end(settings->mLayerIDsToIgnore)) + if(const auto it = AZStd::find(begin(settings->m_layerIDsToIgnore), end(settings->m_layerIDsToIgnore), Mesh::ATTRIB_POSITIONS); it != end(settings->m_layerIDsToIgnore)) { - settings->mLayerIDsToIgnore.erase(it); + settings->m_layerIDsToIgnore.erase(it); } } @@ -1095,7 +1095,7 @@ namespace EMotionFX file.Close(); return false; } - outInfo->mEndianType = endianType; + outInfo->m_endianType = endianType; // as we seeked to the end of the header and we know the second chunk always is the time stamp, we can read this now FileFormat::FileChunk fileChunk; @@ -1104,8 +1104,8 @@ namespace EMotionFX file.Read(&timeChunk, sizeof(FileFormat::FileTime)); // convert endian - MCore::Endian::ConvertUnsignedInt32(&fileChunk.mChunkID, endianType); - MCore::Endian::ConvertUnsignedInt16(&timeChunk.mYear, endianType); + MCore::Endian::ConvertUnsignedInt32(&fileChunk.m_chunkId, endianType); + MCore::Endian::ConvertUnsignedInt16(&timeChunk.m_year, endianType); return true; } @@ -1128,7 +1128,7 @@ namespace EMotionFX file.Close(); return false; } - outInfo->mEndianType = endianType; + outInfo->m_endianType = endianType; // as we seeked to the end of the header and we know the second chunk always is the time stamp, we can read this now FileFormat::FileChunk fileChunk; @@ -1137,8 +1137,8 @@ namespace EMotionFX file.Read(&timeChunk, sizeof(FileFormat::FileTime)); // convert endian - MCore::Endian::ConvertUnsignedInt32(&fileChunk.mChunkID, endianType); - MCore::Endian::ConvertUnsignedInt16(&timeChunk.mYear, endianType); + MCore::Endian::ConvertUnsignedInt32(&fileChunk.m_chunkId, endianType); + MCore::Endian::ConvertUnsignedInt16(&timeChunk.m_year, endianType); return true; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/Importer.h b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/Importer.h index a708e7f017..1a9fdf3654 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/Importer.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/Importer.h @@ -73,26 +73,26 @@ namespace EMotionFX */ struct EMFX_API ActorSettings { - bool mLoadLimits = true; /**< Set to false if you wish to disable loading of joint limits. */ - bool mLoadSkeletalLODs = true; /**< Set to false if you wish to disable loading of skeletal LOD levels. */ - bool mLoadMorphTargets = true; /**< Set to false if you wish to disable loading any morph targets. */ - bool mDualQuatSkinning = false; /**< Set to true if you wish to enable software skinning using dual quaternions. */ - bool mMakeGeomLODsCompatibleWithSkeletalLODs = false; /**< Set to true if you wish to disable the process that makes sure no skinning influences are mapped to disabled bones. Default is false. */ - bool mUnitTypeConvert = true; /**< Set to false to disable automatic unit type conversion (between cm, meters, etc). On default this is enabled. */ - bool mLoadSimulatedObjects = true; /**< Set to false if you wish to disable loading of simulated objects. */ - bool mOptimizeForServer = false; /**< Set to true if you witsh to optimize this actor to be used on server. */ - uint32 mThreadIndex = 0; - AZStd::vector mChunkIDsToIgnore; /**< Add chunk ID's to this array. Chunks with these ID's will not be processed. */ - AZStd::vector mLayerIDsToIgnore; /**< Add vertex attribute layer ID's to ignore. */ + bool m_loadLimits = true; /**< Set to false if you wish to disable loading of joint limits. */ + bool m_loadSkeletalLoDs = true; /**< Set to false if you wish to disable loading of skeletal LOD levels. */ + bool m_loadMorphTargets = true; /**< Set to false if you wish to disable loading any morph targets. */ + bool m_dualQuatSkinning = false; /**< Set to true if you wish to enable software skinning using dual quaternions. */ + bool m_makeGeomLoDsCompatibleWithSkeletalLoDs = false; /**< Set to true if you wish to disable the process that makes sure no skinning influences are mapped to disabled bones. Default is false. */ + bool m_unitTypeConvert = true; /**< Set to false to disable automatic unit type conversion (between cm, meters, etc). On default this is enabled. */ + bool m_loadSimulatedObjects = true; /**< Set to false if you wish to disable loading of simulated objects. */ + bool m_optimizeForServer = false; /**< Set to true if you witsh to optimize this actor to be used on server. */ + uint32 m_threadIndex = 0; + AZStd::vector m_chunkIDsToIgnore; /**< Add chunk ID's to this array. Chunks with these ID's will not be processed. */ + AZStd::vector m_layerIDsToIgnore; /**< Add vertex attribute layer ID's to ignore. */ /** * If the actor need to be optimized for server, will overwrite a few other actor settings. */ void OptimizeForServer() { - mLoadSkeletalLODs = false; - mLoadMorphTargets = false; - mLoadSimulatedObjects = false; + m_loadSkeletalLoDs = false; + m_loadMorphTargets = false; + m_loadSimulatedObjects = false; } }; @@ -102,10 +102,10 @@ namespace EMotionFX */ struct EMFX_API MotionSettings { - bool mForceLoading = false; /**< Set to true in case you want to load the motion even if a motion with the given filename is already inside the motion manager. */ - bool mLoadMotionEvents = true; /**< Set to false if you wish to disable loading of motion events. */ - bool mUnitTypeConvert = true; /**< Set to false to disable automatic unit type conversion (between cm, meters, etc). On default this is enabled. */ - AZStd::vector mChunkIDsToIgnore; /**< Add the ID's of the chunks you wish to ignore. */ + bool m_forceLoading = false; /**< Set to true in case you want to load the motion even if a motion with the given filename is already inside the motion manager. */ + bool m_loadMotionEvents = true; /**< Set to false if you wish to disable loading of motion events. */ + bool m_unitTypeConvert = true; /**< Set to false to disable automatic unit type conversion (between cm, meters, etc). On default this is enabled. */ + AZStd::vector m_chunkIDsToIgnore; /**< Add the ID's of the chunks you wish to ignore. */ }; /** @@ -123,21 +123,21 @@ namespace EMotionFX */ struct EMFX_API NodeMapSettings { - bool mAutoLoadSourceActor = true; /**< Should we automatically try to load the source actor? (default=true) */ - bool mLoadNodes = true; /**< Add nodes to the map? (default=true) */ + bool m_autoLoadSourceActor = true; /**< Should we automatically try to load the source actor? (default=true) */ + bool m_loadNodes = true; /**< Add nodes to the map? (default=true) */ }; struct EMFX_API ImportParameters { - Actor* mActor = nullptr; - Motion* mMotion = nullptr; - Importer::ActorSettings* mActorSettings = nullptr; - Importer::MotionSettings* mMotionSettings = nullptr; - AZStd::vector* mSharedData = nullptr; - MCore::Endian::EEndianType mEndianType = MCore::Endian::ENDIAN_LITTLE; + Actor* m_actor = nullptr; + Motion* m_motion = nullptr; + Importer::ActorSettings* m_actorSettings = nullptr; + Importer::MotionSettings* m_motionSettings = nullptr; + AZStd::vector* m_sharedData = nullptr; + MCore::Endian::EEndianType m_endianType = MCore::Endian::ENDIAN_LITTLE; - NodeMap* mNodeMap = nullptr; - Importer::NodeMapSettings* mNodeMapSettings = nullptr; + NodeMap* m_nodeMap = nullptr; + Importer::NodeMapSettings* m_nodeMapSettings = nullptr; bool m_isOwnedByRuntime = false; bool m_additiveMotion = false; }; @@ -159,7 +159,7 @@ namespace EMotionFX struct FileInfo { - MCore::Endian::EEndianType mEndianType; + MCore::Endian::EEndianType m_endianType; }; //------------------------------------------------------------------------------------------------- @@ -355,9 +355,9 @@ namespace EMotionFX private: - AZStd::vector mChunkProcessors; /**< The registered chunk processors. */ - bool mLoggingActive; /**< Contains if the importer should perform logging or not or not. */ - bool mLogDetails; /**< Contains if the importer should perform detail-logging or not. */ + AZStd::vector m_chunkProcessors; /**< The registered chunk processors. */ + bool m_loggingActive; /**< Contains if the importer should perform logging or not or not. */ + bool m_logDetails; /**< Contains if the importer should perform detail-logging or not. */ /** * The constructor. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/MotionFileFormat.h b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/MotionFileFormat.h index f947b8abf6..40dac39f98 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/MotionFileFormat.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/MotionFileFormat.h @@ -33,10 +33,10 @@ namespace EMotionFX // (not aligned) struct Motion_Header { - uint8 mFourcc[4]; // must be "MOT " or "MOTW" - uint8 mHiVersion; // high version (2 in case of v2.34) - uint8 mLoVersion; // low version (34 in case of v2.34) - uint8 mEndianType; // the endian in which the data is saved [0=little, 1=big] + uint8 m_fourcc[4]; // must be "MOT " or "MOTW" + uint8 m_hiVersion; // high version (2 in case of v2.34) + uint8 m_loVersion; // low version (34 in case of v2.34) + uint8 m_endianType; // the endian in which the data is saved [0=little, 1=big] }; struct Motion_MotionData @@ -53,49 +53,49 @@ namespace EMotionFX // (not aligned) struct Motion_Info { - uint32 mMotionExtractionMask; // motion extraction mask - uint32 mMotionExtractionNodeIndex; // motion extraction node index - uint8 mUnitType; // maps to EMotionFX::EUnitType + uint32 m_motionExtractionMask; // motion extraction mask + uint32 m_motionExtractionNodeIndex; // motion extraction node index + uint8 m_unitType; // maps to EMotionFX::EUnitType }; // information chunk // (not aligned) struct Motion_Info2 { - uint32 mMotionExtractionFlags; // motion extraction flags - uint32 mMotionExtractionNodeIndex; // motion extraction node index - uint8 mUnitType; // maps to EMotionFX::EUnitType + uint32 m_motionExtractionFlags; // motion extraction flags + uint32 m_motionExtractionNodeIndex; // motion extraction node index + uint8 m_unitType; // maps to EMotionFX::EUnitType }; // information chunk // (not aligned) struct Motion_Info3 { - uint32 mMotionExtractionFlags; // motion extraction flags - uint32 mMotionExtractionNodeIndex; // motion extraction node index - uint8 mUnitType; // maps to EMotionFX::EUnitType - uint8 mIsAdditive; // if the motion is an additive motion [0=false, 1=true] + uint32 m_motionExtractionFlags; // motion extraction flags + uint32 m_motionExtractionNodeIndex; // motion extraction node index + uint8 m_unitType; // maps to EMotionFX::EUnitType + uint8 m_isAdditive; // if the motion is an additive motion [0=false, 1=true] }; // skeletal submotion // (aligned) struct Motion_SkeletalSubMotion { - File16BitQuaternion mPoseRot; // initial pose rotation - File16BitQuaternion mBindPoseRot; // bind pose rotation - FileVector3 mPosePos; // initial pose position - FileVector3 mPoseScale; // initial pose scale - FileVector3 mBindPosePos; // bind pose position - FileVector3 mBindPoseScale; // bind pose scale - uint32 mNumPosKeys; // number of position keyframes to follow - uint32 mNumRotKeys; // number of rotation keyframes to follow - uint32 mNumScaleKeys; // number of scale keyframes to follow + File16BitQuaternion m_poseRot; // initial pose rotation + File16BitQuaternion m_bindPoseRot; // bind pose rotation + FileVector3 m_posePos; // initial pose position + FileVector3 m_poseScale; // initial pose scale + FileVector3 m_bindPosePos; // bind pose position + FileVector3 m_bindPoseScale; // bind pose scale + uint32 m_numPosKeys; // number of position keyframes to follow + uint32 m_numRotKeys; // number of rotation keyframes to follow + uint32 m_numScaleKeys; // number of scale keyframes to follow // followed by: // string : motion part name - // Motion_Vector3Key[ mNumPosKeys ] - // Motion_16BitQuaternionKey[ mNumRotKeys ] - // Motion_Vector3Key[ mNumScaleKeys ] + // Motion_Vector3Key[ m_numPosKeys ] + // Motion_16BitQuaternionKey[ m_numRotKeys ] + // Motion_Vector3Key[ m_numScaleKeys ] }; @@ -103,8 +103,8 @@ namespace EMotionFX // (aligned) struct Motion_Vector3Key { - FileVector3 mValue; // the value - float mTime; // the time in seconds + FileVector3 m_value; // the value + float m_time; // the time in seconds }; @@ -112,8 +112,8 @@ namespace EMotionFX // (aligned) struct Motion_QuaternionKey { - FileQuaternion mValue; // the value - float mTime; // the time in seconds + FileQuaternion m_value; // the value + float m_time; // the time in seconds }; @@ -121,8 +121,8 @@ namespace EMotionFX // (aligned) struct Motion_16BitQuaternionKey { - File16BitQuaternion mValue; // the value - float mTime; // the time in seconds + File16BitQuaternion m_value; // the value + float m_time; // the time in seconds }; @@ -130,25 +130,25 @@ namespace EMotionFX // (aligned) struct Motion_SubMotions { - uint32 mNumSubMotions;// the number of skeletal motions + uint32 m_numSubMotions;// the number of skeletal motions // followed by: - // Motion_SkeletalSubMotion[ mNumSubMotions ] + // Motion_SkeletalSubMotion[ m_numSubMotions ] }; // morph sub motion // (aligned) struct Motion_MorphSubMotion { - float mPoseWeight;// pose weight to use in case no animation data is present - float mMinWeight; // minimum allowed weight value (used for unpacking the keyframe weights) - float mMaxWeight; // maximum allowed weight value (used for unpacking the keyframe weights) - uint32 mPhonemeSet;// the phoneme set of the submotion, 0 if this is a normal morph target submotion - uint32 mNumKeys; // number of keyframes to follow + float m_poseWeight;// pose weight to use in case no animation data is present + float m_minWeight; // minimum allowed weight value (used for unpacking the keyframe weights) + float m_maxWeight; // maximum allowed weight value (used for unpacking the keyframe weights) + uint32 m_phonemeSet;// the phoneme set of the submotion, 0 if this is a normal morph target submotion + uint32 m_numKeys; // number of keyframes to follow // followed by: // string : name (the name of this motion part) - // Motion_UnsignedShortKey[mNumKeys] + // Motion_UnsignedShortKey[m_numKeys] }; @@ -156,17 +156,17 @@ namespace EMotionFX // (not aligned) struct Motion_UnsignedShortKey { - float mTime; // the time in seconds - uint16 mValue; // the value + float m_time; // the time in seconds + uint16 m_value; // the value }; // (aligned) struct Motion_MorphSubMotions { - uint32 mNumSubMotions; + uint32 m_numSubMotions; // followed by: - // Motion_MorphSubMotion[ mNumSubMotions ] + // Motion_MorphSubMotion[ m_numSubMotions ] }; @@ -174,11 +174,11 @@ namespace EMotionFX // (not aligned) struct FileMotionEvent { - float mStartTime; - float mEndTime; - uint32 mEventTypeIndex;// index into the event type string table - uint32 mMirrorTypeIndex;// index into the event type string table - uint16 mParamIndex; // index into the parameter string table + float m_startTime; + float m_endTime; + uint32 m_eventTypeIndex;// index into the event type string table + uint32 m_mirrorTypeIndex;// index into the event type string table + uint16 m_paramIndex; // index into the parameter string table }; @@ -186,18 +186,18 @@ namespace EMotionFX // (not aligned) struct FileMotionEventTrack { - uint32 mNumEvents; - uint32 mNumTypeStrings; - uint32 mNumParamStrings; - uint32 mNumMirrorTypeStrings; - uint8 mIsEnabled; + uint32 m_numEvents; + uint32 m_numTypeStrings; + uint32 m_numParamStrings; + uint32 m_numMirrorTypeStrings; + uint8 m_isEnabled; // followed by: // String track name - // [mNumTypeStrings] string objects - // [mNumParamStrings] string objects - // [mNumMirrorTypeStrings] string objects - // FileMotionEvent[mNumEvents] + // [m_numTypeStrings] string objects + // [m_numParamStrings] string objects + // [m_numMirrorTypeStrings] string objects + // FileMotionEvent[m_numEvents] }; @@ -205,10 +205,10 @@ namespace EMotionFX // (aligned) struct FileMotionEventTable { - uint32 mNumTracks; + uint32 m_numTracks; // followed by: - // FileMotionEventTrack[mNumTracks] + // FileMotionEventTrack[m_numTracks] }; struct FileMotionEventTableSerialized diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/NodeMapFileFormat.h b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/NodeMapFileFormat.h index b68b283510..bd563aa0dd 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/NodeMapFileFormat.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/NodeMapFileFormat.h @@ -25,20 +25,20 @@ namespace EMotionFX struct NodeMap_Header { - uint8 mFourCC[4]; // must be "MOS " - uint8 mHiVersion; // high version (2 in case of v2.34) - uint8 mLoVersion; // low version (34 in case of v2.34) - uint8 mEndianType; // the endian in which the data is saved [0=little, 1=big] + uint8 m_fourCc[4]; // must be "MOS " + uint8 m_hiVersion; // high version (2 in case of v2.34) + uint8 m_loVersion; // low version (34 in case of v2.34) + uint8 m_endianType; // the endian in which the data is saved [0=little, 1=big] }; struct NodeMapChunk { - uint32 mNumEntries;// the number of mapping entries + uint32 m_numEntries;// the number of mapping entries // followed by: // String sourceActorFileName - // for all mNumEntries + // for all m_numEntries // String firstNodeName; // String secondNodeName; }; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/SharedFileFormatStructs.h b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/SharedFileFormatStructs.h index 082bcbf0ef..b5828b98c8 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/SharedFileFormatStructs.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/SharedFileFormatStructs.h @@ -23,75 +23,75 @@ namespace EMotionFX struct FileChunk { - uint32 mChunkID; // the chunk ID - uint32 mSizeInBytes; // the size in bytes of this chunk (excluding this chunk struct) - uint32 mVersion; // the version of the chunk + uint32 m_chunkId; // the chunk ID + uint32 m_sizeInBytes; // the size in bytes of this chunk (excluding this chunk struct) + uint32 m_version; // the version of the chunk }; // color [0..1] range struct FileColor { - float mR; // red - float mG; // green - float mB; // blue - float mA; // alpha + float m_r; // red + float m_g; // green + float m_b; // blue + float m_a; // alpha }; struct FileVector2 { - float mX; - float mY; + float m_x; + float m_y; }; struct FileVector3 { - float mX; // x+ = to the right - float mY; // y+ = forward - float mZ; // z+ = up + float m_x; // x+ = to the right + float m_y; // y+ = forward + float m_z; // z+ = up }; // a compressed 3D vector struct File16BitVector3 { - uint16 mX; // x+ = to the right - uint16 mY; // y+ = forward - uint16 mZ; // z+ = up + uint16 m_x; // x+ = to the right + uint16 m_y; // y+ = forward + uint16 m_z; // z+ = up }; // a compressed 3D vector struct File8BitVector3 { - uint8 mX; // x+ = to the right - uint8 mY; // y+ = forward - uint8 mZ; // z+ = up + uint8 m_x; // x+ = to the right + uint8 m_y; // y+ = forward + uint8 m_z; // z+ = up }; struct FileQuaternion { - float mX; - float mY; - float mZ; - float mW; + float m_x; + float m_y; + float m_z; + float m_w; }; // the 16 bit component quaternion struct File16BitQuaternion { - int16 mX; - int16 mY; - int16 mZ; - int16 mW; + int16 m_x; + int16 m_y; + int16 m_z; + int16 m_w; }; // a time stamp chunk struct FileTime { - uint16 mYear; - int8 mMonth; - int8 mDay; - int8 mHours; - int8 mMinutes; - int8 mSeconds; + uint16 m_year; + int8 m_month; + int8 m_day; + int8 m_hours; + int8 m_minutes; + int8 m_seconds; }; } // namespace FileFormat } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/KeyFrame.h b/Gems/EMotionFX/Code/EMotionFX/Source/KeyFrame.h index 35435823d4..7312d94c69 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/KeyFrame.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/KeyFrame.h @@ -103,8 +103,8 @@ namespace EMotionFX MCORE_INLINE void SetStorageTypeValue(const StorageType& value); protected: - StorageType mValue; /**< The key value. */ - float mTime; /**< Time in seconds. */ + StorageType m_value; /**< The key value. */ + float m_time; /**< Time in seconds. */ }; // include inline code diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/KeyFrame.inl b/Gems/EMotionFX/Code/EMotionFX/Source/KeyFrame.inl index 47df42f07f..5aaf871977 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/KeyFrame.inl +++ b/Gems/EMotionFX/Code/EMotionFX/Source/KeyFrame.inl @@ -9,7 +9,7 @@ // default constructor template KeyFrame::KeyFrame() - : mTime(0) + : m_time(0) { } @@ -17,7 +17,7 @@ KeyFrame::KeyFrame() // extended constructor template KeyFrame::KeyFrame(float time, const ReturnType& value) - : mTime(time) + : m_time(time) { SetValue(value); } @@ -41,55 +41,55 @@ void KeyFrame::Reflect(AZ::ReflectContext* context) serializeContext->Class>() ->Version(1) - ->Field("time", &KeyFrame::mTime) - ->Field("value", &KeyFrame::mValue) + ->Field("time", &KeyFrame::m_time) + ->Field("value", &KeyFrame::m_value) ; } template MCORE_INLINE float KeyFrame::GetTime() const { - return mTime; + return m_time; } template MCORE_INLINE ReturnType KeyFrame::GetValue() const { - return mValue; + return m_value; } template MCORE_INLINE void KeyFrame::GetValue(ReturnType* outValue) { - *outValue = mValue; + *outValue = m_value; } template MCORE_INLINE const StorageType& KeyFrame::GetStorageTypeValue() const { - return mValue; + return m_value; } template MCORE_INLINE void KeyFrame::SetTime(float time) { - mTime = time; + m_time = time; } template MCORE_INLINE void KeyFrame::SetValue(const ReturnType& value) { - mValue = value; + m_value = value; } template MCORE_INLINE void KeyFrame::SetStorageTypeValue(const StorageType& value) { - mValue = value; + m_value = value; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/KeyTrackLinearDynamic.h b/Gems/EMotionFX/Code/EMotionFX/Source/KeyTrackLinearDynamic.h index 5f8f7b49d0..c94886a5f3 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/KeyTrackLinearDynamic.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/KeyTrackLinearDynamic.h @@ -257,7 +257,7 @@ namespace EMotionFX MCORE_INLINE void SetStorageTypeKey(size_t keyNr, float time, const StorageType& value); protected: - AZStd::vector> mKeys; /**< The collection of keys which form the track. */ + AZStd::vector> m_keys; /**< The collection of keys which form the track. */ }; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/KeyTrackLinearDynamic.inl b/Gems/EMotionFX/Code/EMotionFX/Source/KeyTrackLinearDynamic.inl index 806a45b69a..34598f0ae1 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/KeyTrackLinearDynamic.inl +++ b/Gems/EMotionFX/Code/EMotionFX/Source/KeyTrackLinearDynamic.inl @@ -25,7 +25,7 @@ void KeyTrackLinearDynamic::Reflect(AZ::ReflectContext* serializeContext->Class>() ->Version(1) - ->Field("keyValues", &KeyTrackLinearDynamic::mKeys) + ->Field("keyValues", &KeyTrackLinearDynamic::m_keys) ; } @@ -33,7 +33,7 @@ void KeyTrackLinearDynamic::Reflect(AZ::ReflectContext* template void KeyTrackLinearDynamic::ClearKeys() { - mKeys.clear(); + m_keys.clear(); } @@ -42,18 +42,18 @@ template void KeyTrackLinearDynamic::Init() { // check all key time values, so we are sure the first key start at time 0 - if (mKeys.empty()) + if (m_keys.empty()) { return; } // get the time value of the first key, which is our minimum time - const float minTime = mKeys[0].GetTime(); + const float minTime = m_keys[0].GetTime(); // if it's not equal to zero, we have to correct it (and all other keys as well) if (minTime > 0.0f) { - for (KeyFrame& key : mKeys) + for (KeyFrame& key : m_keys) { key.SetTime(key.GetTime() - minTime); } @@ -64,22 +64,22 @@ void KeyTrackLinearDynamic::Init() template MCORE_INLINE KeyFrame* KeyTrackLinearDynamic::GetKey(size_t nr) { - MCORE_ASSERT(nr < mKeys.size()); - return &mKeys[nr]; + MCORE_ASSERT(nr < m_keys.size()); + return &m_keys[nr]; } template MCORE_INLINE KeyFrame* KeyTrackLinearDynamic::GetFirstKey() { - return !mKeys.empty() ? &mKeys[0] : nullptr; + return !m_keys.empty() ? &m_keys[0] : nullptr; } template MCORE_INLINE KeyFrame* KeyTrackLinearDynamic::GetLastKey() { - return !mKeys.empty() ? &mKeys.back() : nullptr; + return !m_keys.empty() ? &m_keys.back() : nullptr; } @@ -87,22 +87,22 @@ MCORE_INLINE KeyFrame* KeyTrackLinearDynamic MCORE_INLINE const KeyFrame* KeyTrackLinearDynamic::GetKey(size_t nr) const { - MCORE_ASSERT(nr < mKeys.size()); - return &mKeys[nr]; + MCORE_ASSERT(nr < m_keys.size()); + return &m_keys[nr]; } template MCORE_INLINE const KeyFrame* KeyTrackLinearDynamic::GetFirstKey() const { - return !mKeys.empty() ? &mKeys[0] : nullptr; + return !m_keys.empty() ? &m_keys[0] : nullptr; } template MCORE_INLINE const KeyFrame* KeyTrackLinearDynamic::GetLastKey() const { - return !mKeys.empty() ? &mKeys.back() : nullptr; + return !m_keys.empty() ? &m_keys.back() : nullptr; } @@ -125,7 +125,7 @@ MCORE_INLINE float KeyTrackLinearDynamic::GetLastTime() template MCORE_INLINE size_t KeyTrackLinearDynamic::GetNumKeys() const { - return mKeys.size(); + return m_keys.size(); } @@ -133,21 +133,21 @@ template MCORE_INLINE void KeyTrackLinearDynamic::AddKey(float time, const ReturnType& value, bool smartPreAlloc) { #ifdef MCORE_DEBUG - if (!mKeys.empty()) + if (!m_keys.empty()) { - MCORE_ASSERT(time >= mKeys.back().GetTime()); + MCORE_ASSERT(time >= m_keys.back().GetTime()); } #endif // if we need to prealloc - if (mKeys.capacity() == mKeys.size() && smartPreAlloc == true) + if (m_keys.capacity() == m_keys.size() && smartPreAlloc == true) { - const size_t numToReserve = mKeys.size() / 4; - mKeys.reserve(mKeys.capacity() + numToReserve); + const size_t numToReserve = m_keys.size() / 4; + m_keys.reserve(m_keys.capacity() + numToReserve); } // not the first key, so add on the end - mKeys.emplace_back(KeyFrame(time, value)); + m_keys.emplace_back(KeyFrame(time, value)); } @@ -155,7 +155,7 @@ MCORE_INLINE void KeyTrackLinearDynamic::AddKey(float t template MCORE_INLINE size_t KeyTrackLinearDynamic::FindKeyNumber(float curTime) const { - return KeyFrameFinder::FindKey(curTime, &mKeys.front(), static_cast(mKeys.size())); + return KeyFrameFinder::FindKey(curTime, &m_keys.front(), static_cast(m_keys.size())); } @@ -164,10 +164,10 @@ template MCORE_INLINE KeyFrame* KeyTrackLinearDynamic::FindKey(float curTime) const { // find the key number - const size_t keyNumber = KeyFrameFinder::FindKey(curTime, &mKeys.front(), mKeys.size()); + const size_t keyNumber = KeyFrameFinder::FindKey(curTime, &m_keys.front(), m_keys.size()); // if no key was found - return (keyNumber != InvalidIndex) ? &mKeys[keyNumber] : nullptr; + return (keyNumber != InvalidIndex) ? &m_keys[keyNumber] : nullptr; } @@ -176,7 +176,7 @@ template ReturnType KeyTrackLinearDynamic::GetValueAtTime(float currentTime, size_t* cachedKey, uint8* outWasCacheHit, bool interpolate) const { MCORE_ASSERT(currentTime >= 0.0); - MCORE_ASSERT(!mKeys.empty()); + MCORE_ASSERT(!m_keys.empty()); // make a local copy of the cached key value size_t localCachedKey = (cachedKey) ? *cachedKey : InvalidIndex; @@ -193,7 +193,7 @@ ReturnType KeyTrackLinearDynamic::GetValueAtTime(float *outWasCacheHit = 0; } - keyNumber = KeyFrameFinder::FindKey(currentTime, &mKeys.front(), mKeys.size()); + keyNumber = KeyFrameFinder::FindKey(currentTime, &m_keys.front(), m_keys.size()); if (cachedKey) { @@ -203,11 +203,11 @@ ReturnType KeyTrackLinearDynamic::GetValueAtTime(float else { // make sure we dont go out of bounds when checking - if (localCachedKey >= mKeys.size() - 2) + if (localCachedKey >= m_keys.size() - 2) { - if (mKeys.size() > 2) + if (m_keys.size() > 2) { - localCachedKey = mKeys.size() - 3; + localCachedKey = m_keys.size() - 3; } else { @@ -216,7 +216,7 @@ ReturnType KeyTrackLinearDynamic::GetValueAtTime(float } // check if the cached key is still valid (cache hit) - if ((mKeys[localCachedKey].GetTime() <= currentTime) && (mKeys[localCachedKey + 1].GetTime() >= currentTime)) + if ((m_keys[localCachedKey].GetTime() <= currentTime) && (m_keys[localCachedKey + 1].GetTime() >= currentTime)) { keyNumber = localCachedKey; if (outWasCacheHit) @@ -226,7 +226,7 @@ ReturnType KeyTrackLinearDynamic::GetValueAtTime(float } else { - if (localCachedKey < mKeys.size() - 2 && (mKeys[localCachedKey + 1].GetTime() <= currentTime) && (mKeys[localCachedKey + 2].GetTime() >= currentTime)) + if (localCachedKey < m_keys.size() - 2 && (m_keys[localCachedKey + 1].GetTime() <= currentTime) && (m_keys[localCachedKey + 2].GetTime() >= currentTime)) { if (outWasCacheHit) { @@ -242,7 +242,7 @@ ReturnType KeyTrackLinearDynamic::GetValueAtTime(float *outWasCacheHit = 0; } - keyNumber = KeyFrameFinder::FindKey(currentTime, &mKeys.front(), mKeys.size()); + keyNumber = KeyFrameFinder::FindKey(currentTime, &m_keys.front(), m_keys.size()); if (cachedKey) { @@ -256,20 +256,20 @@ ReturnType KeyTrackLinearDynamic::GetValueAtTime(float if (keyNumber == InvalidIndex) { // if there are no keys at all, simply return an empty object - if (mKeys.size() == 0) + if (m_keys.size() == 0) { // return an empty object return ReturnType(); } // return the last key - return mKeys.back().GetValue(); + return m_keys.back().GetValue(); } // check if we didn't reach the end of the track - if ((keyNumber + 1) > (mKeys.size() - 1)) + if ((keyNumber + 1) > (m_keys.size() - 1)) { - return mKeys.back().GetValue(); + return m_keys.back().GetValue(); } // perform interpolation @@ -279,7 +279,7 @@ ReturnType KeyTrackLinearDynamic::GetValueAtTime(float } else { - return mKeys[keyNumber].GetValue(); + return m_keys[keyNumber].GetValue(); } } @@ -289,8 +289,8 @@ template MCORE_INLINE ReturnType KeyTrackLinearDynamic::Interpolate(size_t startKey, float currentTime) const { // get the keys to interpolate between - const KeyFrame& firstKey = mKeys[startKey]; - const KeyFrame& nextKey = mKeys[startKey + 1]; + const KeyFrame& firstKey = m_keys[startKey]; + const KeyFrame& nextKey = m_keys[startKey + 1]; // calculate the time value in range of [0..1] const float t = (currentTime - firstKey.GetTime()) / (nextKey.GetTime() - firstKey.GetTime()); @@ -305,8 +305,8 @@ template <> MCORE_INLINE AZ::Quaternion KeyTrackLinearDynamic::Interpolate(size_t startKey, float currentTime) const { // get the keys to interpolate between - const KeyFrame& firstKey = mKeys[startKey]; - const KeyFrame& nextKey = mKeys[startKey + 1]; + const KeyFrame& firstKey = m_keys[startKey]; + const KeyFrame& nextKey = m_keys[startKey + 1]; // calculate the time value in range of [0..1] const float t = (currentTime - firstKey.GetTime()) / (nextKey.GetTime() - firstKey.GetTime()); @@ -320,8 +320,8 @@ template <> MCORE_INLINE AZ::Quaternion KeyTrackLinearDynamic::Interpolate(size_t startKey, float currentTime) const { // get the keys to interpolate between - const KeyFrame& firstKey = mKeys[startKey]; - const KeyFrame& nextKey = mKeys[startKey + 1]; + const KeyFrame& firstKey = m_keys[startKey]; + const KeyFrame& nextKey = m_keys[startKey + 1]; // calculate the time value in range of [0..1] const float t = (currentTime - firstKey.GetTime()) / (nextKey.GetTime() - firstKey.GetTime()); @@ -338,17 +338,17 @@ void KeyTrackLinearDynamic::AddKeySorted(float time, co // if we need to prealloc if (smartPreAlloc) { - if (mKeys.capacity() == mKeys.size()) + if (m_keys.capacity() == m_keys.size()) { - const size_t numToReserve = mKeys.size() / 4; - mKeys.reserve(mKeys.capacity() + numToReserve); + const size_t numToReserve = m_keys.size() / 4; + m_keys.reserve(m_keys.capacity() + numToReserve); } } // if there are no keys yet, add it - if (mKeys.empty()) + if (m_keys.empty()) { - mKeys.emplace_back(KeyFrame(time, value)); + m_keys.emplace_back(KeyFrame(time, value)); return; } @@ -356,29 +356,29 @@ void KeyTrackLinearDynamic::AddKeySorted(float time, co const float keyTime = time; // if we must add it at the end - if (keyTime >= mKeys.back().GetTime()) + if (keyTime >= m_keys.back().GetTime()) { - mKeys.emplace_back(KeyFrame(time, value)); + m_keys.emplace_back(KeyFrame(time, value)); return; } // if we have to add it in the front - if (keyTime < mKeys.front().GetTime()) + if (keyTime < m_keys.front().GetTime()) { - mKeys.insert(mKeys.begin(), KeyFrame(time, value)); + m_keys.insert(m_keys.begin(), KeyFrame(time, value)); return; } // quickly find the location to insert, and insert it - const size_t place = KeyFrameFinder::FindKey(keyTime, &mKeys.front(), mKeys.size()); - mKeys.insert(mKeys.begin() + place + 1, KeyFrame(time, value)); + const size_t place = KeyFrameFinder::FindKey(keyTime, &m_keys.front(), m_keys.size()); + m_keys.insert(m_keys.begin() + place + 1, KeyFrame(time, value)); } template MCORE_INLINE void KeyTrackLinearDynamic::RemoveKey(size_t keyNr) { - mKeys.erase(AZStd::next(mKeys.begin(), keyNr)); + m_keys.erase(AZStd::next(m_keys.begin(), keyNr)); } @@ -387,7 +387,7 @@ void KeyTrackLinearDynamic::MakeLoopable(float fadeTime { MCORE_ASSERT(fadeTime > 0); - if (mKeys.empty()) + if (m_keys.empty()) { return; } @@ -407,14 +407,14 @@ size_t KeyTrackLinearDynamic::Optimize(float maxError) { // if there aren't at least two keys, return, because we never remove the first and last key frames // and we'd need at least two keyframes to interpolate between - if (mKeys.size() <= 2) + if (m_keys.size() <= 2) { return 0; } // create a temparory copy of the keytrack data we're going to optimize KeyTrackLinearDynamic keyTrackCopy; - keyTrackCopy.mKeys = mKeys; + keyTrackCopy.m_keys = m_keys; keyTrackCopy.Init(); // while we want to continue optimizing @@ -423,7 +423,7 @@ size_t KeyTrackLinearDynamic::Optimize(float maxError) do { // get the time of the current keyframe (starting from the second towards the last one) - const float time = mKeys[i].GetTime(); + const float time = m_keys[i].GetTime(); // remove the keyframe and reinit the keytrack (and interpolator's tangents etc) keyTrackCopy.RemoveKey(i); @@ -445,13 +445,12 @@ size_t KeyTrackLinearDynamic::Optimize(float maxError) } else // if the "visual" difference is too high and we do not want ot remove the key, copy over the original keys again to restore it { - keyTrackCopy.mKeys = mKeys; // copy the keyframe array + keyTrackCopy.m_keys = m_keys; // copy the keyframe array keyTrackCopy.Init(); // reinit the keytrack i++; // go to the next keyframe, and try ot remove that one } - } while (i < mKeys.size() - 1); // while we haven't reached the last keyframe (minus one) + } while (i < m_keys.size() - 1); // while we haven't reached the last keyframe (minus one) - //mKeys.shrink_to_fit(); return numRemoved; } @@ -461,7 +460,7 @@ template void KeyTrackLinearDynamic::SetNumKeys(size_t numKeys) { // resize the array of keys - mKeys.resize(numKeys); + m_keys.resize(numKeys); } @@ -470,8 +469,8 @@ template MCORE_INLINE void KeyTrackLinearDynamic::SetKey(size_t keyNr, float time, const ReturnType& value) { // adjust the value and time of the key - mKeys[keyNr].SetValue(value); - mKeys[keyNr].SetTime(time); + m_keys[keyNr].SetValue(value); + m_keys[keyNr].SetTime(time); } @@ -480,8 +479,8 @@ template MCORE_INLINE void KeyTrackLinearDynamic::SetStorageTypeKey(size_t keyNr, float time, const StorageType& value) { // adjust the value and time of the key - mKeys[keyNr].SetStorageTypeValue(value); - mKeys[keyNr].SetTime(time); + m_keys[keyNr].SetStorageTypeValue(value); + m_keys[keyNr].SetTime(time); } @@ -489,7 +488,7 @@ MCORE_INLINE void KeyTrackLinearDynamic::SetStorageType template MCORE_INLINE bool KeyTrackLinearDynamic::CheckIfIsAnimated(const ReturnType& initialPose, float maxError) const { - return !mKeys.empty() && AZStd::any_of(begin(mKeys), end(mKeys), [&initialPose, maxError](const auto& key) + return !m_keys.empty() && AZStd::any_of(begin(m_keys), end(m_keys), [&initialPose, maxError](const auto& key) { return !MCore::Compare::CheckIfIsClose(initialPose, key.GetValue(), maxError); }); @@ -501,7 +500,7 @@ MCORE_INLINE bool KeyTrackLinearDynamic::CheckIfIsAnima template MCORE_INLINE void KeyTrackLinearDynamic::Reserve(size_t numKeys) { - mKeys.reserve(numKeys); + m_keys.reserve(numKeys); } @@ -517,5 +516,5 @@ size_t KeyTrackLinearDynamic::CalcMemoryUsage([[maybe_u template void KeyTrackLinearDynamic::Shrink() { - mKeys.shrink_to_fit(); + m_keys.shrink_to_fit(); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/LayerPass.h b/Gems/EMotionFX/Code/EMotionFX/Source/LayerPass.h index f4aef98b7e..ce0cb5607e 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/LayerPass.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/LayerPass.h @@ -41,14 +41,14 @@ namespace EMotionFX protected: - MotionLayerSystem* mMotionSystem; /**< The motion system where this layer pass works on. */ + MotionLayerSystem* m_motionSystem; /**< The motion system where this layer pass works on. */ /** * The constructor. * @param motionLayerSystem The motion layer system where this pass will be added to. */ LayerPass(MotionLayerSystem* motionLayerSystem) - : BaseObject() { mMotionSystem = motionLayerSystem; } + : BaseObject() { m_motionSystem = motionLayerSystem; } /** * The destructor. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Material.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Material.cpp index c7157ba7c3..2602f3f281 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Material.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Material.cpp @@ -40,21 +40,21 @@ namespace EMotionFX void Material::SetName(const char* name) { // calculate the ID - mNameID = MCore::GetStringIdPool().GenerateIdForString(name); + m_nameId = MCore::GetStringIdPool().GenerateIdForString(name); } // return the material name const char* Material::GetName() const { - return MCore::GetStringIdPool().GetName(mNameID).c_str(); + return MCore::GetStringIdPool().GetName(m_nameId).c_str(); } // return the material name as a string const AZStd::string& Material::GetNameString() const { - return MCore::GetStringIdPool().GetName(mNameID); + return MCore::GetStringIdPool().GetName(m_nameId); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Material.h b/Gems/EMotionFX/Code/EMotionFX/Source/Material.h index 98c40e8b50..a462f9e25a 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Material.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Material.h @@ -78,7 +78,7 @@ namespace EMotionFX void SetName(const char* name); protected: - uint32 mNameID; /**< The material id representing the name. */ + uint32 m_nameId; /**< The material id representing the name. */ /** * The constructor. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.cpp index 450a546c27..9845ec1939 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.cpp @@ -29,25 +29,25 @@ namespace EMotionFX Mesh::Mesh() : BaseObject() { - mNumVertices = 0; - mNumIndices = 0; - mNumOrgVerts = 0; - mNumPolygons = 0; - mIndices = nullptr; - mPolyVertexCounts = nullptr; - mIsCollisionMesh = false; + m_numVertices = 0; + m_numIndices = 0; + m_numOrgVerts = 0; + m_numPolygons = 0; + m_indices = nullptr; + m_polyVertexCounts = nullptr; + m_isCollisionMesh = false; } // allocation constructor Mesh::Mesh(uint32 numVerts, uint32 numIndices, uint32 numPolygons, uint32 numOrgVerts, bool isCollisionMesh) { - mNumVertices = 0; - mNumIndices = 0; - mNumPolygons = 0; - mNumOrgVerts = 0; - mIndices = nullptr; - mPolyVertexCounts = nullptr; - mIsCollisionMesh = isCollisionMesh; + m_numVertices = 0; + m_numIndices = 0; + m_numPolygons = 0; + m_numOrgVerts = 0; + m_indices = nullptr; + m_polyVertexCounts = nullptr; + m_isCollisionMesh = isCollisionMesh; // allocate the mesh data Allocate(numVerts, numIndices, numPolygons, numOrgVerts); @@ -73,22 +73,22 @@ namespace EMotionFX // Local 2D and 4D packed vector structs as we don't have packed representations in AzCore and don't plan to add these. struct Vector2 { - float x; - float y; + float m_x; + float m_y; }; struct Vector4 { - float x; - float y; - float z; - float w; + float m_x; + float m_y; + float m_z; + float m_w; }; // Needed for converting the packed vectors from the Atom buffers that normally load directly into GPU into AzCore versions used by EMFX. AZ::Vector2 ConvertVector(const Vector2& input) { - return AZ::Vector2(input.x, input.y); + return AZ::Vector2(input.m_x, input.m_y); } AZ::Vector3 ConvertVector(const AZ::PackedVector3f& input) @@ -98,7 +98,7 @@ namespace EMotionFX AZ::Vector4 ConvertVector(const Vector4& input) { - return AZ::Vector4(input.x, input.y, input.z, input.w); + return AZ::Vector4(input.m_x, input.m_y, input.m_z, input.m_w); } // Convert Atom buffer storing elements of type SourceType to an EMFX vertex attribute layer storing elements of type TargetType. @@ -192,10 +192,10 @@ namespace EMotionFX AZ_ErrorOnce("EMotionFX", indexBufferViewDescriptor.m_elementSize == 4, "Index buffer must stored as 4 bytes."); const size_t indexBufferCountsInBytes = indexBufferViewDescriptor.m_elementCount * indexBufferViewDescriptor.m_elementSize; const size_t indexBufferOffsetInBytes = indexBufferViewDescriptor.m_elementOffset * indexBufferViewDescriptor.m_elementSize; - memcpy(mesh->mIndices, indexBuffer.begin() + indexBufferOffsetInBytes, indexBufferCountsInBytes); + memcpy(mesh->m_indices, indexBuffer.begin() + indexBufferOffsetInBytes, indexBufferCountsInBytes); // Set the polygon buffer - AZStd::fill(mesh->mPolyVertexCounts, mesh->mPolyVertexCounts + mesh->mNumPolygons, 3); + AZStd::fill(mesh->m_polyVertexCounts, mesh->m_polyVertexCounts + mesh->m_numPolygons, 3); // Skinning data from atom are stored in two separate buffer layer. AZ::u8 maxSkinInfluences = 255; // Later we will calculate this value from skinning data. @@ -359,22 +359,22 @@ namespace EMotionFX // allocate the indices if (numIndices > 0 && numPolygons > 0) { - mIndices = (uint32*)MCore::AlignedAllocate(sizeof(uint32) * numIndices, 32, EMFX_MEMCATEGORY_GEOMETRY_MESHES, Mesh::MEMORYBLOCK_ID); - mPolyVertexCounts = (uint8*)MCore::AlignedAllocate(sizeof(uint8) * numPolygons, 16, EMFX_MEMCATEGORY_GEOMETRY_MESHES, Mesh::MEMORYBLOCK_ID); + m_indices = (uint32*)MCore::AlignedAllocate(sizeof(uint32) * numIndices, 32, EMFX_MEMCATEGORY_GEOMETRY_MESHES, Mesh::MEMORYBLOCK_ID); + m_polyVertexCounts = (uint8*)MCore::AlignedAllocate(sizeof(uint8) * numPolygons, 16, EMFX_MEMCATEGORY_GEOMETRY_MESHES, Mesh::MEMORYBLOCK_ID); } // set number values - mNumVertices = numVerts; - mNumPolygons = numPolygons; - mNumIndices = numIndices; - mNumOrgVerts = numOrgVerts; + m_numVertices = numVerts; + m_numPolygons = numPolygons; + m_numIndices = numIndices; + m_numOrgVerts = numOrgVerts; } // copy all original data over the output data void Mesh::ResetToOriginalData() { - for (VertexAttributeLayer* vertexAttribute : mVertexAttributes) + for (VertexAttributeLayer* vertexAttribute : m_vertexAttributes) { vertexAttribute->ResetToOriginalData(); } @@ -391,29 +391,29 @@ namespace EMotionFX RemoveAllVertexAttributeLayers(); // get rid of all sub meshes - for (SubMesh* subMesh : mSubMeshes) + for (SubMesh* subMesh : m_subMeshes) { subMesh->Destroy(); } - mSubMeshes.clear(); + m_subMeshes.clear(); - if (mIndices) + if (m_indices) { - MCore::AlignedFree(mIndices); + MCore::AlignedFree(m_indices); } - if (mPolyVertexCounts) + if (m_polyVertexCounts) { - MCore::AlignedFree(mPolyVertexCounts); + MCore::AlignedFree(m_polyVertexCounts); } // re-init members - mIndices = nullptr; - mPolyVertexCounts = nullptr; - mNumIndices = 0; - mNumVertices = 0; - mNumOrgVerts = 0; - mNumPolygons = 0; + m_indices = nullptr; + m_polyVertexCounts = nullptr; + m_numIndices = 0; + m_numVertices = 0; + m_numOrgVerts = 0; + m_numPolygons = 0; } @@ -503,14 +503,14 @@ namespace EMotionFX for (size_t i = numTangentLayers; i <= uvSet; ++i) { // add a new tangent layer - AddVertexAttributeLayer(VertexAttributeLayerAbstractData::Create(mNumVertices, Mesh::ATTRIB_TANGENTS, sizeof(AZ::Vector4), true)); + AddVertexAttributeLayer(VertexAttributeLayerAbstractData::Create(m_numVertices, Mesh::ATTRIB_TANGENTS, sizeof(AZ::Vector4), true)); tangents = static_cast(FindVertexData(Mesh::ATTRIB_TANGENTS, i)); orgTangents = static_cast(FindOriginalVertexData(Mesh::ATTRIB_TANGENTS, i)); // Add the bitangents layer. if (storeBitangents) { - AddVertexAttributeLayer(VertexAttributeLayerAbstractData::Create(mNumVertices, Mesh::ATTRIB_BITANGENTS, sizeof(AZ::PackedVector3f), true)); + AddVertexAttributeLayer(VertexAttributeLayerAbstractData::Create(m_numVertices, Mesh::ATTRIB_BITANGENTS, sizeof(AZ::PackedVector3f), true)); bitangents = static_cast(FindVertexData(Mesh::ATTRIB_BITANGENTS, i)); orgBitangents = static_cast(FindOriginalVertexData(Mesh::ATTRIB_BITANGENTS, i)); } @@ -518,7 +518,7 @@ namespace EMotionFX // default all tangents for the newly created layer AZ::Vector4 defaultTangent(1.0f, 0.0f, 0.0f, 0.0f); AZ::Vector3 defaultBitangent(0.0f, 0.0f, 1.0f); - for (uint32 vtx = 0; vtx < mNumVertices; ++vtx) + for (uint32 vtx = 0; vtx < m_numVertices; ++vtx) { tangents[vtx] = defaultTangent; orgTangents[vtx] = defaultTangent; @@ -545,7 +545,7 @@ namespace EMotionFX AZ::Vector3 curBitangent; // calculate for every vertex the tangent and bitangent - for (uint32 i = 0; i < mNumVertices; ++i) + for (uint32 i = 0; i < m_numVertices; ++i) { orgTangents[i] = AZ::Vector4::CreateZero(); tangents[i] = AZ::Vector4::CreateZero(); @@ -601,7 +601,7 @@ namespace EMotionFX } // calculate the per vertex tangents now, fixing up orthogonality and handling mirroring of the bitangent - for (uint32 i = 0; i < mNumVertices; ++i) + for (uint32 i = 0; i < m_numVertices; ++i) { // get the normal AZ::Vector3 normal(normals[i]); @@ -800,8 +800,8 @@ namespace EMotionFX // remove a given submesh void Mesh::RemoveSubMesh(size_t nr, bool delFromMem) { - SubMesh* subMesh = mSubMeshes[nr]; - mSubMeshes.erase(AZStd::next(begin(mSubMeshes), nr)); + SubMesh* subMesh = m_subMeshes[nr]; + m_subMeshes.erase(AZStd::next(begin(m_subMeshes), nr)); if (delFromMem) { subMesh->Destroy(); @@ -812,7 +812,7 @@ namespace EMotionFX // insert a given submesh void Mesh::InsertSubMesh(size_t insertIndex, SubMesh* subMesh) { - mSubMeshes.emplace(AZStd::next(begin(mSubMeshes), insertIndex), subMesh); + m_subMeshes.emplace(AZStd::next(begin(m_subMeshes), insertIndex), subMesh); } @@ -822,7 +822,7 @@ namespace EMotionFX size_t numLayers = 0; // check the types of all vertex attribute layers - for (auto* vertexAttribute : mVertexAttributes) + for (auto* vertexAttribute : m_vertexAttributes) { if (vertexAttribute->GetType() == type) { @@ -844,31 +844,31 @@ namespace EMotionFX VertexAttributeLayer* Mesh::GetSharedVertexAttributeLayer(size_t layerNr) { - MCORE_ASSERT(layerNr < mSharedVertexAttributes.size()); - return mSharedVertexAttributes[layerNr]; + MCORE_ASSERT(layerNr < m_sharedVertexAttributes.size()); + return m_sharedVertexAttributes[layerNr]; } void Mesh::AddSharedVertexAttributeLayer(VertexAttributeLayer* layer) { - MCORE_ASSERT(AZStd::find(begin(mSharedVertexAttributes), end(mSharedVertexAttributes), layer) == end(mSharedVertexAttributes)); - mSharedVertexAttributes.emplace_back(layer); + MCORE_ASSERT(AZStd::find(begin(m_sharedVertexAttributes), end(m_sharedVertexAttributes), layer) == end(m_sharedVertexAttributes)); + m_sharedVertexAttributes.emplace_back(layer); } size_t Mesh::GetNumSharedVertexAttributeLayers() const { - return mSharedVertexAttributes.size(); + return m_sharedVertexAttributes.size(); } size_t Mesh::FindSharedVertexAttributeLayerNumber(uint32 layerTypeID, size_t occurrence) const { - const auto foundLayer = AZStd::find_if(begin(mSharedVertexAttributes), end(mSharedVertexAttributes), [layerTypeID, occurrence](const VertexAttributeLayer* layer) mutable + const auto foundLayer = AZStd::find_if(begin(m_sharedVertexAttributes), end(m_sharedVertexAttributes), [layerTypeID, occurrence](const VertexAttributeLayer* layer) mutable { return layer->GetType() == layerTypeID && occurrence-- == 0; }); - return foundLayer != end(mSharedVertexAttributes) ? AZStd::distance(begin(mSharedVertexAttributes), foundLayer) : InvalidIndex; + return foundLayer != end(m_sharedVertexAttributes) ? AZStd::distance(begin(m_sharedVertexAttributes), foundLayer) : InvalidIndex; } @@ -881,7 +881,7 @@ namespace EMotionFX return nullptr; } - return mSharedVertexAttributes[layerNr]; + return m_sharedVertexAttributes[layerNr]; } @@ -889,10 +889,10 @@ namespace EMotionFX // delete all shared attribute layers void Mesh::RemoveAllSharedVertexAttributeLayers() { - while (mSharedVertexAttributes.size()) + while (m_sharedVertexAttributes.size()) { - mSharedVertexAttributes.back()->Destroy(); - mSharedVertexAttributes.pop_back(); + m_sharedVertexAttributes.back()->Destroy(); + m_sharedVertexAttributes.pop_back(); } } @@ -900,51 +900,51 @@ namespace EMotionFX // remove a layer by its index void Mesh::RemoveSharedVertexAttributeLayer(size_t layerNr) { - MCORE_ASSERT(layerNr < mSharedVertexAttributes.size()); - mSharedVertexAttributes[layerNr]->Destroy(); - mSharedVertexAttributes.erase(AZStd::next(begin(mSharedVertexAttributes), layerNr)); + MCORE_ASSERT(layerNr < m_sharedVertexAttributes.size()); + m_sharedVertexAttributes[layerNr]->Destroy(); + m_sharedVertexAttributes.erase(AZStd::next(begin(m_sharedVertexAttributes), layerNr)); } size_t Mesh::GetNumVertexAttributeLayers() const { - return mVertexAttributes.size(); + return m_vertexAttributes.size(); } VertexAttributeLayer* Mesh::GetVertexAttributeLayer(size_t layerNr) { - MCORE_ASSERT(layerNr < mVertexAttributes.size()); - return mVertexAttributes[layerNr]; + MCORE_ASSERT(layerNr < m_vertexAttributes.size()); + return m_vertexAttributes[layerNr]; } void Mesh::AddVertexAttributeLayer(VertexAttributeLayer* layer) { - MCORE_ASSERT(AZStd::find(begin(mVertexAttributes), end(mVertexAttributes), layer) == end(mVertexAttributes)); - mVertexAttributes.emplace_back(layer); + MCORE_ASSERT(AZStd::find(begin(m_vertexAttributes), end(m_vertexAttributes), layer) == end(m_vertexAttributes)); + m_vertexAttributes.emplace_back(layer); } // find the layer number size_t Mesh::FindVertexAttributeLayerNumber(uint32 layerTypeID, size_t occurrence) const { - const auto foundLayer = AZStd::find_if(begin(mVertexAttributes), end(mVertexAttributes), [layerTypeID, occurrence](const VertexAttributeLayer* layer) mutable + const auto foundLayer = AZStd::find_if(begin(m_vertexAttributes), end(m_vertexAttributes), [layerTypeID, occurrence](const VertexAttributeLayer* layer) mutable { return layer->GetType() == layerTypeID && occurrence-- == 0; }); - return foundLayer != end(mVertexAttributes) ? AZStd::distance(begin(mVertexAttributes), foundLayer) : InvalidIndex; + return foundLayer != end(m_vertexAttributes) ? AZStd::distance(begin(m_vertexAttributes), foundLayer) : InvalidIndex; } // find the layer number size_t Mesh::FindVertexAttributeLayerNumberByName(uint32 layerTypeID, const char* name) const { - const auto foundLayer = AZStd::find_if(begin(mVertexAttributes), end(mVertexAttributes), [layerTypeID, name](const VertexAttributeLayer* layer) + const auto foundLayer = AZStd::find_if(begin(m_vertexAttributes), end(m_vertexAttributes), [layerTypeID, name](const VertexAttributeLayer* layer) { return layer->GetType() == layerTypeID && layer->GetNameString() == name; }); - return foundLayer != end(mVertexAttributes) ? AZStd::distance(begin(mVertexAttributes), foundLayer) : InvalidIndex; + return foundLayer != end(m_vertexAttributes) ? AZStd::distance(begin(m_vertexAttributes), foundLayer) : InvalidIndex; } @@ -958,7 +958,7 @@ namespace EMotionFX return nullptr; } - return mVertexAttributes[layerNr]; + return m_vertexAttributes[layerNr]; } @@ -971,25 +971,25 @@ namespace EMotionFX return nullptr; } - return mVertexAttributes[layerNr]; + return m_vertexAttributes[layerNr]; } void Mesh::RemoveAllVertexAttributeLayers() { - while (mVertexAttributes.size()) + while (m_vertexAttributes.size()) { - mVertexAttributes.back()->Destroy(); - mVertexAttributes.pop_back(); + m_vertexAttributes.back()->Destroy(); + m_vertexAttributes.pop_back(); } } void Mesh::RemoveVertexAttributeLayer(size_t layerNr) { - MCORE_ASSERT(layerNr < mVertexAttributes.size()); - mVertexAttributes[layerNr]->Destroy(); - mVertexAttributes.erase(AZStd::next(begin(mVertexAttributes), layerNr)); + MCORE_ASSERT(layerNr < m_vertexAttributes.size()); + m_vertexAttributes[layerNr]->Destroy(); + m_vertexAttributes.erase(AZStd::next(begin(m_vertexAttributes), layerNr)); } @@ -998,34 +998,34 @@ namespace EMotionFX Mesh* Mesh::Clone() { // allocate a mesh of the same dimensions - Mesh* clone = aznew Mesh(mNumVertices, mNumIndices, mNumPolygons, mNumOrgVerts, mIsCollisionMesh); + Mesh* clone = aznew Mesh(m_numVertices, m_numIndices, m_numPolygons, m_numOrgVerts, m_isCollisionMesh); // copy the mesh data - MCore::MemCopy(clone->mIndices, mIndices, sizeof(uint32) * mNumIndices); - MCore::MemCopy(clone->mPolyVertexCounts, mPolyVertexCounts, sizeof(uint8) * mNumPolygons); + MCore::MemCopy(clone->m_indices, m_indices, sizeof(uint32) * m_numIndices); + MCore::MemCopy(clone->m_polyVertexCounts, m_polyVertexCounts, sizeof(uint8) * m_numPolygons); // copy the submesh data - const size_t numSubMeshes = mSubMeshes.size(); - clone->mSubMeshes.resize(numSubMeshes); + const size_t numSubMeshes = m_subMeshes.size(); + clone->m_subMeshes.resize(numSubMeshes); for (size_t i = 0; i < numSubMeshes; ++i) { - clone->mSubMeshes[i] = mSubMeshes[i]->Clone(clone); + clone->m_subMeshes[i] = m_subMeshes[i]->Clone(clone); } // clone the shared vertex attributes - const size_t numSharedAttributes = mSharedVertexAttributes.size(); - clone->mSharedVertexAttributes.resize(numSharedAttributes); + const size_t numSharedAttributes = m_sharedVertexAttributes.size(); + clone->m_sharedVertexAttributes.resize(numSharedAttributes); for (size_t i = 0; i < numSharedAttributes; ++i) { - clone->mSharedVertexAttributes[i] = mSharedVertexAttributes[i]->Clone(); + clone->m_sharedVertexAttributes[i] = m_sharedVertexAttributes[i]->Clone(); } // clone the non-shared vertex attributes - const size_t numAttributes = mVertexAttributes.size(); - clone->mVertexAttributes.resize(numAttributes); + const size_t numAttributes = m_vertexAttributes.size(); + clone->m_vertexAttributes.resize(numAttributes); for (size_t i = 0; i < numAttributes; ++i) { - clone->mVertexAttributes[i] = mVertexAttributes[i]->Clone(); + clone->m_vertexAttributes[i] = m_vertexAttributes[i]->Clone(); } // return the resulting cloned mesh @@ -1036,8 +1036,8 @@ namespace EMotionFX // swap the data for two vertices void Mesh::SwapVertex(uint32 vertexA, uint32 vertexB) { - MCORE_ASSERT(vertexA < mNumVertices); - MCORE_ASSERT(vertexB < mNumVertices); + MCORE_ASSERT(vertexA < m_numVertices); + MCORE_ASSERT(vertexB < m_numVertices); // if we try to swap itself then there is nothing to do if (vertexA == vertexB) @@ -1046,10 +1046,10 @@ namespace EMotionFX } // swap all vertex attribute layers - const size_t numLayers = mVertexAttributes.size(); + const size_t numLayers = m_vertexAttributes.size(); for (size_t i = 0; i < numLayers; ++i) { - mVertexAttributes[i]->SwapAttributes(vertexA, vertexB); + m_vertexAttributes[i]->SwapAttributes(vertexA, vertexB); } } @@ -1057,8 +1057,8 @@ namespace EMotionFX void Mesh::RemoveVertices(uint32 startVertexNr, uint32 endVertexNr, bool changeIndexBuffer, bool removeEmptySubMeshes) { // perform some checks on the input data - MCORE_ASSERT(endVertexNr < mNumVertices); - MCORE_ASSERT(startVertexNr < mNumVertices); + MCORE_ASSERT(endVertexNr < m_numVertices); + MCORE_ASSERT(startVertexNr < m_numVertices); // make sure the start vertex is before the end vertex in release mode, to prevent weirdness if (startVertexNr > endVertexNr) @@ -1074,7 +1074,7 @@ namespace EMotionFX const uint32 numVertsToRemove = (endVertexNr - startVertexNr) + 1; // +1 because we remove the end vertex as well // remove the num verices counter - mNumVertices -= numVertsToRemove; + m_numVertices -= numVertsToRemove; // remove the attributes from the vertex attribute layers const size_t numLayers = GetNumVertexAttributeLayers(); @@ -1091,9 +1091,9 @@ namespace EMotionFX for (uint32 w = 0; w < numVertsToRemove; ++w) { // adjust all submesh start index offsets changed - for (size_t s = 0; s < mSubMeshes.size();) + for (size_t s = 0; s < m_subMeshes.size();) { - SubMesh* subMesh = mSubMeshes[s]; + SubMesh* subMesh = m_subMeshes[s]; // if we remove a vertex from this submesh if (subMesh->GetStartVertex() <= v && subMesh->GetStartVertex() + subMesh->GetNumVertices() > v) @@ -1111,7 +1111,7 @@ namespace EMotionFX // remove the submesh if it's empty if (subMesh->GetNumVertices() == 0 && removeEmptySubMeshes) { - mSubMeshes.erase(AZStd::next(begin(mSubMeshes), s)); + m_subMeshes.erase(AZStd::next(begin(m_subMeshes), s)); } else { @@ -1128,11 +1128,11 @@ namespace EMotionFX //------------------------------------ if (changeIndexBuffer) { - for (uint32 i = 0; i < mNumIndices; ++i) + for (uint32 i = 0; i < m_numIndices; ++i) { - if (mIndices[i] > startVertexNr) + if (m_indices[i] > startVertexNr) { - mIndices[i] -= numVertsToRemove; + m_indices[i] -= numVertsToRemove; } } } @@ -1145,9 +1145,9 @@ namespace EMotionFX size_t numRemoved = 0; // for all the submeshes - for (size_t i = 0; i < mSubMeshes.size();) + for (size_t i = 0; i < m_subMeshes.size();) { - SubMesh* subMesh = mSubMeshes[i]; + SubMesh* subMesh = m_subMeshes[i]; // get some stats about the submesh bool mustRemove; @@ -1167,7 +1167,7 @@ namespace EMotionFX // remove or skip if (mustRemove) { - mSubMeshes.erase(AZStd::next(begin(mSubMeshes), i)); + m_subMeshes.erase(AZStd::next(begin(m_subMeshes), i)); numRemoved++; } else @@ -1542,19 +1542,19 @@ namespace EMotionFX bool result = true; // check if the indices are valid and return false in case they aren't - if (mIndices == nullptr) + if (m_indices == nullptr) { return false; } // use our 32-bit index buffer as new 16-bit index array directly - uint16* indices = (uint16*)mIndices; + uint16* indices = (uint16*)m_indices; // iterate over all indices and convert the values - for (uint32 i = 0; i < mNumIndices; ++i) + for (uint32 i = 0; i < m_numIndices; ++i) { // create a temporary copy of our 32-bit vertex index - const uint32 oldVertexIndex = mIndices[i]; + const uint32 oldVertexIndex = m_indices[i]; // check if our index is in range of an unsigned short if (oldVertexIndex < 65536) @@ -1570,7 +1570,7 @@ namespace EMotionFX } // realloc the memory to the new index buffer size using 16-bit values and return the result - mIndices = (uint32*)MCore::AlignedRealloc(mIndices, sizeof(uint16) * mNumIndices, 32, EMFX_MEMCATEGORY_GEOMETRY_MESHES, Mesh::MEMORYBLOCK_ID); + m_indices = (uint32*)MCore::AlignedRealloc(m_indices, sizeof(uint16) * m_numIndices, 32, EMFX_MEMCATEGORY_GEOMETRY_MESHES, Mesh::MEMORYBLOCK_ID); return result; } @@ -1610,19 +1610,19 @@ namespace EMotionFX void Mesh::ExtractOriginalVertexPositions(AZStd::vector& outPoints) const { // allocate space - outPoints.resize(mNumOrgVerts); + outPoints.resize(m_numOrgVerts); // get the mesh data const AZ::Vector3* positions = (AZ::Vector3*)FindOriginalVertexData(ATTRIB_POSITIONS); const uint32* orgVerts = (uint32*) FindVertexData(ATTRIB_ORGVTXNUMBERS); // init all org vertices - for (uint32 v = 0; v < mNumOrgVerts; ++v) + for (uint32 v = 0; v < m_numOrgVerts; ++v) { outPoints[v] = positions[0]; // init them, as there are some unused original vertices sometimes } // output the points - for (uint32 i = 0; i < mNumVertices; ++i) + for (uint32 i = 0; i < m_numVertices; ++i) { outPoints[ orgVerts[i] ] = positions[i]; } @@ -1640,8 +1640,8 @@ namespace EMotionFX if (useDuplicates == false) { // the smoothed normals array - AZStd::vector smoothNormals(mNumOrgVerts); - for (uint32 i = 0; i < mNumOrgVerts; ++i) + AZStd::vector smoothNormals(m_numOrgVerts); + for (uint32 i = 0; i < m_numOrgVerts; ++i) { smoothNormals[i] = AZ::Vector3::CreateZero(); } @@ -1681,39 +1681,20 @@ namespace EMotionFX polyStartIndex += numPolyVerts; } - /* - for (uint32 f=0; fScale(scaleFactor); } - for (VertexAttributeLayer* layer : mSharedVertexAttributes) + for (VertexAttributeLayer* layer : m_sharedVertexAttributes) { layer->Scale(scaleFactor); } @@ -1847,7 +1808,7 @@ namespace EMotionFX AZ::Vector3* positions = (AZ::Vector3*)FindVertexData(ATTRIB_POSITIONS); AZ::Vector3* orgPositions = (AZ::Vector3*)FindOriginalVertexData(ATTRIB_POSITIONS); - const uint32 numVerts = mNumVertices; + const uint32 numVerts = m_numVertices; for (uint32 i = 0; i < numVerts; ++i) { positions[i] = positions[i] * scaleFactor; @@ -1859,65 +1820,65 @@ namespace EMotionFX // find by name size_t Mesh::FindVertexAttributeLayerIndexByName(const char* name) const { - const auto foundLayer = AZStd::find_if(begin(mVertexAttributes), end(mVertexAttributes), [name](const VertexAttributeLayer* layer) + const auto foundLayer = AZStd::find_if(begin(m_vertexAttributes), end(m_vertexAttributes), [name](const VertexAttributeLayer* layer) { return layer->GetNameString() == name; }); - return foundLayer != end(mVertexAttributes) ? AZStd::distance(begin(mVertexAttributes), foundLayer) : InvalidIndex; + return foundLayer != end(m_vertexAttributes) ? AZStd::distance(begin(m_vertexAttributes), foundLayer) : InvalidIndex; } // find by name as string size_t Mesh::FindVertexAttributeLayerIndexByNameString(const AZStd::string& name) const { - const auto foundLayer = AZStd::find_if(begin(mVertexAttributes), end(mVertexAttributes), [name](const VertexAttributeLayer* layer) + const auto foundLayer = AZStd::find_if(begin(m_vertexAttributes), end(m_vertexAttributes), [name](const VertexAttributeLayer* layer) { return layer->GetNameString() == name; }); - return foundLayer != end(mVertexAttributes) ? AZStd::distance(begin(mVertexAttributes), foundLayer) : InvalidIndex; + return foundLayer != end(m_vertexAttributes) ? AZStd::distance(begin(m_vertexAttributes), foundLayer) : InvalidIndex; } // find by name ID size_t Mesh::FindVertexAttributeLayerIndexByNameID(uint32 nameID) const { - const auto foundLayer = AZStd::find_if(begin(mVertexAttributes), end(mVertexAttributes), [nameID](const VertexAttributeLayer* layer) + const auto foundLayer = AZStd::find_if(begin(m_vertexAttributes), end(m_vertexAttributes), [nameID](const VertexAttributeLayer* layer) { return layer->GetNameID() == nameID; }); - return foundLayer != end(mVertexAttributes) ? AZStd::distance(begin(mVertexAttributes), foundLayer) : InvalidIndex; + return foundLayer != end(m_vertexAttributes) ? AZStd::distance(begin(m_vertexAttributes), foundLayer) : InvalidIndex; } // find by name size_t Mesh::FindSharedVertexAttributeLayerIndexByName(const char* name) const { - const auto foundLayer = AZStd::find_if(begin(mSharedVertexAttributes), end(mSharedVertexAttributes), [name](const VertexAttributeLayer* layer) + const auto foundLayer = AZStd::find_if(begin(m_sharedVertexAttributes), end(m_sharedVertexAttributes), [name](const VertexAttributeLayer* layer) { return layer->GetNameString() == name; }); - return foundLayer != end(mSharedVertexAttributes) ? AZStd::distance(begin(mSharedVertexAttributes), foundLayer) : InvalidIndex; + return foundLayer != end(m_sharedVertexAttributes) ? AZStd::distance(begin(m_sharedVertexAttributes), foundLayer) : InvalidIndex; } // find by name as string size_t Mesh::FindSharedVertexAttributeLayerIndexByNameString(const AZStd::string& name) const { - const auto foundLayer = AZStd::find_if(begin(mSharedVertexAttributes), end(mSharedVertexAttributes), [name](const VertexAttributeLayer* layer) + const auto foundLayer = AZStd::find_if(begin(m_sharedVertexAttributes), end(m_sharedVertexAttributes), [name](const VertexAttributeLayer* layer) { return layer->GetNameString() == name; }); - return foundLayer != end(mSharedVertexAttributes) ? AZStd::distance(begin(mSharedVertexAttributes), foundLayer) : InvalidIndex; + return foundLayer != end(m_sharedVertexAttributes) ? AZStd::distance(begin(m_sharedVertexAttributes), foundLayer) : InvalidIndex; } // find by name ID size_t Mesh::FindSharedVertexAttributeLayerIndexByNameID(uint32 nameID) const { - const auto foundLayer = AZStd::find_if(begin(mSharedVertexAttributes), end(mSharedVertexAttributes), [nameID](const VertexAttributeLayer* layer) + const auto foundLayer = AZStd::find_if(begin(m_sharedVertexAttributes), end(m_sharedVertexAttributes), [nameID](const VertexAttributeLayer* layer) { return layer->GetNameID() == nameID; }); - return foundLayer != end(mSharedVertexAttributes) ? AZStd::distance(begin(mSharedVertexAttributes), foundLayer) : InvalidIndex; + return foundLayer != end(m_sharedVertexAttributes) ? AZStd::distance(begin(m_sharedVertexAttributes), foundLayer) : InvalidIndex; } } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.h b/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.h index b38a1445f6..c2d776bcdb 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.h @@ -249,7 +249,7 @@ namespace EMotionFX * @param nr The submesh number, which must be in range of [0..GetNumSubMeshes()-1]. * @param subMesh The submesh to use. */ - MCORE_INLINE void SetSubMesh(size_t nr, SubMesh* subMesh) { mSubMeshes[nr] = subMesh; } + MCORE_INLINE void SetSubMesh(size_t nr, SubMesh* subMesh) { m_subMeshes[nr] = subMesh; } /** * Set the number of submeshes. @@ -257,7 +257,7 @@ namespace EMotionFX * Do not forget to use SetSubMesh() to initialize all submeshes! * @param numSubMeshes The number of submeshes to use. */ - MCORE_INLINE void SetNumSubMeshes(size_t numSubMeshes) { mSubMeshes.resize(numSubMeshes); } + MCORE_INLINE void SetNumSubMeshes(size_t numSubMeshes) { m_subMeshes.resize(numSubMeshes); } /** * Remove a given submesh from this mesh. @@ -648,31 +648,31 @@ namespace EMotionFX void Scale(float scaleFactor); - MCORE_INLINE bool GetIsCollisionMesh() const { return mIsCollisionMesh; } - void SetIsCollisionMesh(bool isCollisionMesh) { mIsCollisionMesh = isCollisionMesh; } + MCORE_INLINE bool GetIsCollisionMesh() const { return m_isCollisionMesh; } + void SetIsCollisionMesh(bool isCollisionMesh) { m_isCollisionMesh = isCollisionMesh; } protected: - AZStd::vector mSubMeshes; /**< The collection of sub meshes. */ - uint32* mIndices; /**< The array of indices, which define the faces. */ - uint8* mPolyVertexCounts; /**< The number of vertices for each polygon, where the length of this array equals the number of polygons. */ - uint32 mNumPolygons; /**< The number of polygons in this mesh. */ - uint32 mNumOrgVerts; /**< The number of original vertices. */ - uint32 mNumVertices; /**< Number of vertices. */ - uint32 mNumIndices; /**< Number of indices. */ - bool mIsCollisionMesh; /**< Is this mesh a collision mesh? */ + AZStd::vector m_subMeshes; /**< The collection of sub meshes. */ + uint32* m_indices; /**< The array of indices, which define the faces. */ + uint8* m_polyVertexCounts; /**< The number of vertices for each polygon, where the length of this array equals the number of polygons. */ + uint32 m_numPolygons; /**< The number of polygons in this mesh. */ + uint32 m_numOrgVerts; /**< The number of original vertices. */ + uint32 m_numVertices; /**< Number of vertices. */ + uint32 m_numIndices; /**< Number of indices. */ + bool m_isCollisionMesh; /**< Is this mesh a collision mesh? */ /** * The array of shared vertex attribute layers. * The number of attributes in each shared layer will be equal to the value returned by Mesh::GetNumOrgVertices(). */ - AZStd::vector< VertexAttributeLayer* > mSharedVertexAttributes; + AZStd::vector< VertexAttributeLayer* > m_sharedVertexAttributes; /** * The array of non-shared vertex attribute layers. * The number of attributes in each shared layer will be equal to the value returned by Mesh::GetNumVertices(). */ - AZStd::vector< VertexAttributeLayer* > mVertexAttributes; + AZStd::vector< VertexAttributeLayer* > m_vertexAttributes; /** * Default constructor. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.inl b/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.inl index 6a29a3de69..1794303b76 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.inl +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.inl @@ -8,65 +8,54 @@ MCORE_INLINE uint32 Mesh::GetNumVertices() const { - return mNumVertices; + return m_numVertices; } MCORE_INLINE uint32 Mesh::GetNumIndices() const { - return mNumIndices; + return m_numIndices; } MCORE_INLINE uint32 Mesh::GetNumPolygons() const { - return mNumPolygons; + return m_numPolygons; } MCORE_INLINE size_t Mesh::GetNumSubMeshes() const { - return mSubMeshes.size(); + return m_subMeshes.size(); } MCORE_INLINE SubMesh* Mesh::GetSubMesh(size_t nr) const { - MCORE_ASSERT(nr < mSubMeshes.size()); - return mSubMeshes[nr]; + MCORE_ASSERT(nr < m_subMeshes.size()); + return m_subMeshes[nr]; } MCORE_INLINE void Mesh::AddSubMesh(SubMesh* subMesh) { - mSubMeshes.emplace_back(subMesh); + m_subMeshes.emplace_back(subMesh); } MCORE_INLINE uint32* Mesh::GetIndices() const { - return mIndices; + return m_indices; } MCORE_INLINE uint8* Mesh::GetPolygonVertexCounts() const { - return mPolyVertexCounts; + return m_polyVertexCounts; } -/* -MCORE_INLINE void Mesh::SetFace(const uint32 faceNr, const uint32 a, const uint32 b, const uint32 c) -{ - MCORE_ASSERT(faceNr < mNumIndices * 3); - - uint32 startIndex = faceNr * 3; - mIndices[startIndex++] = a; - mIndices[startIndex++] = b; - mIndices[startIndex] = c; -} -*/ MCORE_INLINE uint32 Mesh::GetNumOrgVertices() const { - return mNumOrgVerts; + return m_numOrgVerts; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MeshDeformer.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MeshDeformer.cpp index b269fdecdd..93a716571d 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MeshDeformer.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MeshDeformer.cpp @@ -19,8 +19,8 @@ namespace EMotionFX MeshDeformer::MeshDeformer(Mesh* mesh) : BaseObject() { - mMesh = mesh; - mIsEnabled = true; + m_mesh = mesh; + m_isEnabled = true; } @@ -33,14 +33,14 @@ namespace EMotionFX // check if the deformer is enabled bool MeshDeformer::GetIsEnabled() const { - return mIsEnabled; + return m_isEnabled; } // enable or disable it void MeshDeformer::SetIsEnabled(bool enabled) { - mIsEnabled = enabled; + m_isEnabled = enabled; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MeshDeformer.h b/Gems/EMotionFX/Code/EMotionFX/Source/MeshDeformer.h index e1caeaf5a9..dcb95fcd82 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MeshDeformer.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MeshDeformer.h @@ -86,8 +86,8 @@ namespace EMotionFX void SetIsEnabled(bool enabled); protected: - Mesh* mMesh; /**< Pointer to the mesh to which the deformer belongs to.*/ - bool mIsEnabled; /**< When set to true, this mesh deformer will be processed, otherwise it will be skipped during update. */ + Mesh* m_mesh; /**< Pointer to the mesh to which the deformer belongs to.*/ + bool m_isEnabled; /**< When set to true, this mesh deformer will be processed, otherwise it will be skipped during update. */ /** * Default constructor. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MeshDeformerStack.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MeshDeformerStack.cpp index ee204cf298..bf7fd657ec 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MeshDeformerStack.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MeshDeformerStack.cpp @@ -21,22 +21,22 @@ namespace EMotionFX MeshDeformerStack::MeshDeformerStack(Mesh* mesh) : BaseObject() { - mMesh = mesh; + m_mesh = mesh; } // destructor MeshDeformerStack::~MeshDeformerStack() { - for (MeshDeformer* deformer : mDeformers) + for (MeshDeformer* deformer : m_deformers) { deformer->Destroy(); } - mDeformers.clear(); + m_deformers.clear(); // reset - mMesh = nullptr; + m_mesh = nullptr; } @@ -50,7 +50,7 @@ namespace EMotionFX // returns the mesh Mesh* MeshDeformerStack::GetMesh() const { - return mMesh; + return m_mesh; } @@ -60,7 +60,7 @@ namespace EMotionFX bool firstEnabled = true; // iterate through the deformers and update them - for (MeshDeformer* deformer : mDeformers) + for (MeshDeformer* deformer : m_deformers) { // if the deformer is enabled if (deformer->GetIsEnabled() || forceUpdateDisabledDeformers) @@ -71,7 +71,7 @@ namespace EMotionFX firstEnabled = false; // reset all output vertex data to the original vertex data - mMesh->ResetToOriginalData(); + m_mesh->ResetToOriginalData(); } // update the mesh deformer @@ -84,7 +84,7 @@ namespace EMotionFX void MeshDeformerStack::UpdateByModifierType(ActorInstance* actorInstance, Node* node, float timeDelta, uint32 typeID, bool resetMesh, bool forceUpdateDisabledDeformers) { bool resetDone = false; - for (MeshDeformer* deformer : mDeformers) + for (MeshDeformer* deformer : m_deformers) { // if the deformer of the correct type and is enabled if (deformer->GetType() == typeID && (deformer->GetIsEnabled() || forceUpdateDisabledDeformers)) @@ -93,7 +93,7 @@ namespace EMotionFX if (resetMesh && !resetDone) { // reset all output vertex data to the original vertex data - mMesh->ResetToOriginalData(); + m_mesh->ResetToOriginalData(); resetDone = true; } @@ -108,12 +108,12 @@ namespace EMotionFX void MeshDeformerStack::ReinitializeDeformers(Actor* actor, Node* node, size_t lodLevel) { // if we have deformers in the stack - const size_t numDeformers = mDeformers.size(); + const size_t numDeformers = m_deformers.size(); // iterate through the deformers and reinitialize them for (size_t i = 0; i < numDeformers; ++i) { - mDeformers[i]->Reinitialize(actor, node, lodLevel); + m_deformers[i]->Reinitialize(actor, node, lodLevel); } } @@ -121,23 +121,23 @@ namespace EMotionFX void MeshDeformerStack::AddDeformer(MeshDeformer* meshDeformer) { // add the object into the stack - mDeformers.emplace_back(meshDeformer); + m_deformers.emplace_back(meshDeformer); } void MeshDeformerStack::InsertDeformer(size_t pos, MeshDeformer* meshDeformer) { // add the object into the stack - mDeformers.emplace(AZStd::next(begin(mDeformers), pos), meshDeformer); + m_deformers.emplace(AZStd::next(begin(m_deformers), pos), meshDeformer); } bool MeshDeformerStack::RemoveDeformer(MeshDeformer* meshDeformer) { // delete the object - if (const auto it = AZStd::find(begin(mDeformers), end(mDeformers), meshDeformer); it != end(mDeformers)) + if (const auto it = AZStd::find(begin(m_deformers), end(m_deformers), meshDeformer); it != end(m_deformers)) { - mDeformers.erase(it); + m_deformers.erase(it); return true; } return false; @@ -150,7 +150,7 @@ namespace EMotionFX MeshDeformerStack* newStack = aznew MeshDeformerStack(mesh); // clone all deformers - for (const MeshDeformer* deformer : mDeformers) + for (const MeshDeformer* deformer : m_deformers) { newStack->AddDeformer(deformer->Clone(mesh)); } @@ -162,14 +162,14 @@ namespace EMotionFX size_t MeshDeformerStack::GetNumDeformers() const { - return mDeformers.size(); + return m_deformers.size(); } MeshDeformer* MeshDeformerStack::GetDeformer(size_t nr) const { - MCORE_ASSERT(nr < mDeformers.size()); - return mDeformers[nr]; + MCORE_ASSERT(nr < m_deformers.size()); + return m_deformers[nr]; } @@ -177,9 +177,9 @@ namespace EMotionFX size_t MeshDeformerStack::RemoveAllDeformersByType(uint32 deformerTypeID) { size_t numRemoved = 0; - for (size_t a = 0; a < mDeformers.size(); ) + for (size_t a = 0; a < m_deformers.size(); ) { - MeshDeformer* deformer = mDeformers[a]; + MeshDeformer* deformer = m_deformers[a]; if (deformer->GetType() == deformerTypeID) { RemoveDeformer(deformer); @@ -199,7 +199,7 @@ namespace EMotionFX // remove all the deformers void MeshDeformerStack::RemoveAllDeformers() { - for (MeshDeformer* deformer : mDeformers) + for (MeshDeformer* deformer : m_deformers) { // retrieve the current deformer // remove the deformer @@ -213,7 +213,7 @@ namespace EMotionFX size_t MeshDeformerStack::EnableAllDeformersByType(uint32 deformerTypeID, bool enabled) { size_t numChanged = 0; - for (MeshDeformer* deformer : mDeformers) + for (MeshDeformer* deformer : m_deformers) { if (deformer->GetType() == deformerTypeID) { @@ -229,7 +229,7 @@ namespace EMotionFX // check if the stack contains a deformer of a specified type bool MeshDeformerStack::CheckIfHasDeformerOfType(uint32 deformerTypeID) const { - return AZStd::any_of(begin(mDeformers), end(mDeformers), [deformerTypeID](const MeshDeformer* deformer) + return AZStd::any_of(begin(m_deformers), end(m_deformers), [deformerTypeID](const MeshDeformer* deformer) { return deformer->GetType() == deformerTypeID; }); @@ -239,10 +239,10 @@ namespace EMotionFX // find a deformer by type ID MeshDeformer* MeshDeformerStack::FindDeformerByType(uint32 deformerTypeID, size_t occurrence) const { - const auto foundDeformer = AZStd::find_if(begin(mDeformers), end(mDeformers), [deformerTypeID, iter = occurrence](const MeshDeformer* deformer) mutable + const auto foundDeformer = AZStd::find_if(begin(m_deformers), end(m_deformers), [deformerTypeID, iter = occurrence](const MeshDeformer* deformer) mutable { return deformer->GetType() == deformerTypeID && iter-- == 0; }); - return foundDeformer != end(mDeformers) ? *foundDeformer : nullptr; + return foundDeformer != end(m_deformers) ? *foundDeformer : nullptr; } } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MeshDeformerStack.h b/Gems/EMotionFX/Code/EMotionFX/Source/MeshDeformerStack.h index ae63a1e495..885bc06cab 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MeshDeformerStack.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MeshDeformerStack.h @@ -159,8 +159,8 @@ namespace EMotionFX MeshDeformer* FindDeformerByType(uint32 deformerTypeID, size_t occurrence = 0) const; private: - AZStd::vector mDeformers; /**< The stack of deformers. */ - Mesh* mMesh; /**< Pointer to the mesh to which the modifier stack belongs to.*/ + AZStd::vector m_deformers; /**< The stack of deformers. */ + Mesh* m_mesh; /**< Pointer to the mesh to which the modifier stack belongs to.*/ /** * Constructor. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MorphMeshDeformer.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MorphMeshDeformer.cpp index e3fd1552b0..8dd0c15d84 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MorphMeshDeformer.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MorphMeshDeformer.cpp @@ -63,13 +63,13 @@ namespace EMotionFX MorphMeshDeformer* result = aznew MorphMeshDeformer(mesh); // copy the deform passes - result->mDeformPasses.resize(mDeformPasses.size()); - for (size_t i = 0; i < mDeformPasses.size(); ++i) + result->m_deformPasses.resize(m_deformPasses.size()); + for (size_t i = 0; i < m_deformPasses.size(); ++i) { - DeformPass& pass = result->mDeformPasses[i]; - pass.mDeformDataNr = mDeformPasses[i].mDeformDataNr; - pass.mMorphTarget = mDeformPasses[i].mMorphTarget; - pass.mLastNearZero = false; + DeformPass& pass = result->m_deformPasses[i]; + pass.m_deformDataNr = m_deformPasses[i].m_deformDataNr; + pass.m_morphTarget = m_deformPasses[i].m_morphTarget; + pass.m_lastNearZero = false; } // return the result @@ -88,23 +88,23 @@ namespace EMotionFX const size_t lodLevel = actorInstance->GetLODLevel(); // apply all deform passes - for (DeformPass& deformPass : mDeformPasses) + for (DeformPass& deformPass : m_deformPasses) { // find the morph target - MorphTargetStandard* morphTarget = (MorphTargetStandard*)actor->GetMorphSetup(lodLevel)->FindMorphTargetByID(deformPass.mMorphTarget->GetID()); + MorphTargetStandard* morphTarget = (MorphTargetStandard*)actor->GetMorphSetup(lodLevel)->FindMorphTargetByID(deformPass.m_morphTarget->GetID()); if (morphTarget == nullptr) { continue; } // get the deform data and number of vertices to deform - MorphTargetStandard::DeformData* deformData = morphTarget->GetDeformData(deformPass.mDeformDataNr); - const uint32 numDeformVerts = deformData->mNumVerts; + MorphTargetStandard::DeformData* deformData = morphTarget->GetDeformData(deformPass.m_deformDataNr); + const uint32 numDeformVerts = deformData->m_numVerts; // this mesh deformer can't work on this mesh, because the deformdata number of vertices is bigger than the // number of vertices inside this mesh! // and that would make it crash, which isn't what we want - if (numDeformVerts > mMesh->GetNumVertices()) + if (numDeformVerts > m_mesh->GetNumVertices()) { continue; } @@ -120,7 +120,7 @@ namespace EMotionFX const bool nearZero = (MCore::Math::Abs(weight) < 0.0001f); // we are near zero, and the previous frame as well, so we can return - if (nearZero && deformPass.mLastNearZero) + if (nearZero && deformPass.m_lastNearZero) { continue; } @@ -128,36 +128,36 @@ namespace EMotionFX // update the flag if (nearZero) { - deformPass.mLastNearZero = true; + deformPass.m_lastNearZero = true; } else { - deformPass.mLastNearZero = false; // we moved away from zero influence + deformPass.m_lastNearZero = false; // we moved away from zero influence } // output data - AZ::Vector3* positions = static_cast(mMesh->FindVertexData(Mesh::ATTRIB_POSITIONS)); - AZ::Vector3* normals = static_cast(mMesh->FindVertexData(Mesh::ATTRIB_NORMALS)); - AZ::Vector4* tangents = static_cast(mMesh->FindVertexData(Mesh::ATTRIB_TANGENTS)); - AZ::Vector3* bitangents = static_cast(mMesh->FindVertexData(Mesh::ATTRIB_BITANGENTS)); + AZ::Vector3* positions = static_cast(m_mesh->FindVertexData(Mesh::ATTRIB_POSITIONS)); + AZ::Vector3* normals = static_cast(m_mesh->FindVertexData(Mesh::ATTRIB_NORMALS)); + AZ::Vector4* tangents = static_cast(m_mesh->FindVertexData(Mesh::ATTRIB_TANGENTS)); + AZ::Vector3* bitangents = static_cast(m_mesh->FindVertexData(Mesh::ATTRIB_BITANGENTS)); // input data - const MorphTargetStandard::DeformData::VertexDelta* deltas = deformData->mDeltas; - const float minValue = deformData->mMinValue; - const float maxValue = deformData->mMaxValue; + const MorphTargetStandard::DeformData::VertexDelta* deltas = deformData->m_deltas; + const float minValue = deformData->m_minValue; + const float maxValue = deformData->m_maxValue; if (tangents && bitangents) { // process all vertices that we need to deform for (uint32 v = 0; v < numDeformVerts; ++v) { - uint32 vtxNr = deltas[v].mVertexNr; + uint32 vtxNr = deltas[v].m_vertexNr; - positions [vtxNr] = positions[vtxNr] + deltas[v].mPosition.ToVector3(minValue, maxValue) * weight; - normals [vtxNr] = normals[vtxNr] + deltas[v].mNormal.ToVector3(-2.0f, 2.0f) * weight; - bitangents[vtxNr] = bitangents[vtxNr] + deltas[v].mBitangent.ToVector3(-2.0f, 2.0f) * weight; + positions [vtxNr] = positions[vtxNr] + deltas[v].m_position.ToVector3(minValue, maxValue) * weight; + normals [vtxNr] = normals[vtxNr] + deltas[v].m_normal.ToVector3(-2.0f, 2.0f) * weight; + bitangents[vtxNr] = bitangents[vtxNr] + deltas[v].m_bitangent.ToVector3(-2.0f, 2.0f) * weight; - const AZ::Vector3 tangentDirVector = deltas[v].mTangent.ToVector3(-2.0f, 2.0f); + const AZ::Vector3 tangentDirVector = deltas[v].m_tangent.ToVector3(-2.0f, 2.0f); tangents[vtxNr] += AZ::Vector4(tangentDirVector.GetX()*weight, tangentDirVector.GetY()*weight, tangentDirVector.GetZ()*weight, 0.0f); } } @@ -165,12 +165,12 @@ namespace EMotionFX { for (uint32 v = 0; v < numDeformVerts; ++v) { - uint32 vtxNr = deltas[v].mVertexNr; + uint32 vtxNr = deltas[v].m_vertexNr; - positions[vtxNr] = positions[vtxNr] + deltas[v].mPosition.ToVector3(minValue, maxValue) * weight; - normals [vtxNr] = normals[vtxNr] + deltas[v].mNormal.ToVector3(-2.0f, 2.0f) * weight; + positions[vtxNr] = positions[vtxNr] + deltas[v].m_position.ToVector3(minValue, maxValue) * weight; + normals [vtxNr] = normals[vtxNr] + deltas[v].m_normal.ToVector3(-2.0f, 2.0f) * weight; - const AZ::Vector3 tangentDirVector = deltas[v].mTangent.ToVector3(-2.0f, 2.0f); + const AZ::Vector3 tangentDirVector = deltas[v].m_tangent.ToVector3(-2.0f, 2.0f); tangents[vtxNr] += AZ::Vector4(tangentDirVector.GetX()*weight, tangentDirVector.GetY()*weight, tangentDirVector.GetZ()*weight, 0.0f); } } @@ -179,10 +179,10 @@ namespace EMotionFX // process all vertices that we need to deform for (uint32 v = 0; v < numDeformVerts; ++v) { - uint32 vtxNr = deltas[v].mVertexNr; + uint32 vtxNr = deltas[v].m_vertexNr; - positions[vtxNr] = positions[vtxNr] + deltas[v].mPosition.ToVector3(minValue, maxValue) * weight; - normals[vtxNr] = normals[vtxNr] + deltas[v].mNormal.ToVector3(-2.0f, 2.0f) * weight; + positions[vtxNr] = positions[vtxNr] + deltas[v].m_position.ToVector3(minValue, maxValue) * weight; + normals[vtxNr] = normals[vtxNr] + deltas[v].m_normal.ToVector3(-2.0f, 2.0f) * weight; } } } @@ -193,7 +193,7 @@ namespace EMotionFX void MorphMeshDeformer::Reinitialize(Actor* actor, Node* node, size_t lodLevel) { // clear the deform passes, but don't free the currently allocated/reserved memory - mDeformPasses.clear(); + m_deformPasses.clear(); // get the morph setup MorphSetup* morphSetup = actor->GetMorphSetup(lodLevel); @@ -211,13 +211,13 @@ namespace EMotionFX { // get the deform data and only add it to our deformer in case it belongs to our mesh MorphTargetStandard::DeformData* deformData = morphTarget->GetDeformData(j); - if (deformData->mNodeIndex == node->GetNodeIndex()) + if (deformData->m_nodeIndex == node->GetNodeIndex()) { // add an empty deform pass and fill it afterwards - mDeformPasses.emplace_back(); - const size_t deformPassIndex = mDeformPasses.size() - 1; - mDeformPasses[deformPassIndex].mDeformDataNr = j; - mDeformPasses[deformPassIndex].mMorphTarget = morphTarget; + m_deformPasses.emplace_back(); + const size_t deformPassIndex = m_deformPasses.size() - 1; + m_deformPasses[deformPassIndex].m_deformDataNr = j; + m_deformPasses[deformPassIndex].m_morphTarget = morphTarget; } } } @@ -226,18 +226,18 @@ namespace EMotionFX void MorphMeshDeformer::AddDeformPass(const DeformPass& deformPass) { - mDeformPasses.emplace_back(deformPass); + m_deformPasses.emplace_back(deformPass); } size_t MorphMeshDeformer::GetNumDeformPasses() const { - return mDeformPasses.size(); + return m_deformPasses.size(); } void MorphMeshDeformer::ReserveDeformPasses(size_t numPasses) { - mDeformPasses.reserve(numPasses); + m_deformPasses.reserve(numPasses); } } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MorphMeshDeformer.h b/Gems/EMotionFX/Code/EMotionFX/Source/MorphMeshDeformer.h index 882d4bdfeb..fb4b2efa5c 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MorphMeshDeformer.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MorphMeshDeformer.h @@ -54,18 +54,18 @@ namespace EMotionFX */ struct EMFX_API DeformPass { - MorphTargetStandard* mMorphTarget; /**< The morph target working on the mesh. */ - size_t mDeformDataNr; /**< An index inside the deform datas of the standard morph target. */ - bool mLastNearZero; /**< Was the last frame's weight near zero? */ + MorphTargetStandard* m_morphTarget; /**< The morph target working on the mesh. */ + size_t m_deformDataNr; /**< An index inside the deform datas of the standard morph target. */ + bool m_lastNearZero; /**< Was the last frame's weight near zero? */ /** * Constructor. * Automatically initializes on defaults. */ DeformPass() - : mMorphTarget(nullptr) - , mDeformDataNr(InvalidIndex) - , mLastNearZero(false) {} + : m_morphTarget(nullptr) + , m_deformDataNr(InvalidIndex) + , m_lastNearZero(false) {} }; /** @@ -132,7 +132,7 @@ namespace EMotionFX void ReserveDeformPasses(size_t numPasses); private: - AZStd::vector mDeformPasses; /**< The deform passes. Each pass basically represents a morph target. */ + AZStd::vector m_deformPasses; /**< The deform passes. Each pass basically represents a morph target. */ /** * Default constructor. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MorphSetup.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MorphSetup.cpp index d4a70dd070..9836325ff2 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MorphSetup.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MorphSetup.cpp @@ -35,7 +35,7 @@ namespace EMotionFX // add a morph target void MorphSetup::AddMorphTarget(MorphTarget* morphTarget) { - mMorphTargets.emplace_back(morphTarget); + m_morphTargets.emplace_back(morphTarget); } @@ -44,20 +44,20 @@ namespace EMotionFX { if (delFromMem) { - mMorphTargets[nr]->Destroy(); + m_morphTargets[nr]->Destroy(); } - mMorphTargets.erase(AZStd::next(begin(mMorphTargets), nr)); + m_morphTargets.erase(AZStd::next(begin(m_morphTargets), nr)); } // remove a morph target void MorphSetup::RemoveMorphTarget(MorphTarget* morphTarget, bool delFromMem) { - const auto* foundMorphTarget = AZStd::find(begin(mMorphTargets), end(mMorphTargets), morphTarget); - if (foundMorphTarget != end(mMorphTargets)) + const auto* foundMorphTarget = AZStd::find(begin(m_morphTargets), end(m_morphTargets), morphTarget); + if (foundMorphTarget != end(m_morphTargets)) { - mMorphTargets.erase(foundMorphTarget); + m_morphTargets.erase(foundMorphTarget); } if (delFromMem) @@ -70,76 +70,76 @@ namespace EMotionFX // remove all morph targets void MorphSetup::RemoveAllMorphTargets() { - for (MorphTarget*& morphTarget : mMorphTargets) + for (MorphTarget*& morphTarget : m_morphTargets) { morphTarget->Destroy(); } - mMorphTargets.clear(); + m_morphTargets.clear(); } // get a morph target by ID MorphTarget* MorphSetup::FindMorphTargetByID(uint32 id) const { - const auto foundMorphTarget = AZStd::find_if(begin(mMorphTargets), end(mMorphTargets), [id](const MorphTarget* morphTarget) + const auto foundMorphTarget = AZStd::find_if(begin(m_morphTargets), end(m_morphTargets), [id](const MorphTarget* morphTarget) { return morphTarget->GetID() == id; }); - return foundMorphTarget != end(mMorphTargets) ? *foundMorphTarget : nullptr; + return foundMorphTarget != end(m_morphTargets) ? *foundMorphTarget : nullptr; } // get a morph target number by ID size_t MorphSetup::FindMorphTargetNumberByID(uint32 id) const { - const auto foundMorphTarget = AZStd::find_if(begin(mMorphTargets), end(mMorphTargets), [id](const MorphTarget* morphTarget) + const auto foundMorphTarget = AZStd::find_if(begin(m_morphTargets), end(m_morphTargets), [id](const MorphTarget* morphTarget) { return morphTarget->GetID() == id; }); - return foundMorphTarget != end(mMorphTargets) ? AZStd::distance(begin(mMorphTargets), foundMorphTarget) : InvalidIndex; + return foundMorphTarget != end(m_morphTargets) ? AZStd::distance(begin(m_morphTargets), foundMorphTarget) : InvalidIndex; } size_t MorphSetup::FindMorphTargetIndexByName(const char* name) const { - const auto foundMorphTarget = AZStd::find_if(begin(mMorphTargets), end(mMorphTargets), [name](const MorphTarget* morphTarget) + const auto foundMorphTarget = AZStd::find_if(begin(m_morphTargets), end(m_morphTargets), [name](const MorphTarget* morphTarget) { return morphTarget->GetNameString() == name; }); - return foundMorphTarget != end(mMorphTargets) ? AZStd::distance(begin(mMorphTargets), foundMorphTarget) : InvalidIndex; + return foundMorphTarget != end(m_morphTargets) ? AZStd::distance(begin(m_morphTargets), foundMorphTarget) : InvalidIndex; } size_t MorphSetup::FindMorphTargetIndexByNameNoCase(const char* name) const { - const auto foundMorphTarget = AZStd::find_if(begin(mMorphTargets), end(mMorphTargets), [name](const MorphTarget* morphTarget) + const auto foundMorphTarget = AZStd::find_if(begin(m_morphTargets), end(m_morphTargets), [name](const MorphTarget* morphTarget) { return AzFramework::StringFunc::Equal(morphTarget->GetNameString().c_str(), name, false /* no case */); }); - return foundMorphTarget != end(mMorphTargets) ? AZStd::distance(begin(mMorphTargets), foundMorphTarget) : InvalidIndex; + return foundMorphTarget != end(m_morphTargets) ? AZStd::distance(begin(m_morphTargets), foundMorphTarget) : InvalidIndex; } // find a morph target by name (case sensitive) MorphTarget* MorphSetup::FindMorphTargetByName(const char* name) const { - const auto foundMorphTarget = AZStd::find_if(begin(mMorphTargets), end(mMorphTargets), [name](const MorphTarget* morphTarget) + const auto foundMorphTarget = AZStd::find_if(begin(m_morphTargets), end(m_morphTargets), [name](const MorphTarget* morphTarget) { return morphTarget->GetNameString() == name; }); - return foundMorphTarget != end(mMorphTargets) ? *foundMorphTarget : nullptr; + return foundMorphTarget != end(m_morphTargets) ? *foundMorphTarget : nullptr; } // find a morph target by name (not case sensitive) MorphTarget* MorphSetup::FindMorphTargetByNameNoCase(const char* name) const { - const auto foundMorphTarget = AZStd::find_if(begin(mMorphTargets), end(mMorphTargets), [name](const MorphTarget* morphTarget) + const auto foundMorphTarget = AZStd::find_if(begin(m_morphTargets), end(m_morphTargets), [name](const MorphTarget* morphTarget) { return AzFramework::StringFunc::Equal(morphTarget->GetNameString().c_str(), name, false /* no case */); }); - return foundMorphTarget != end(mMorphTargets) ? *foundMorphTarget : nullptr; + return foundMorphTarget != end(m_morphTargets) ? *foundMorphTarget : nullptr; } @@ -150,7 +150,7 @@ namespace EMotionFX MorphSetup* clone = MorphSetup::Create(); // clone all morph targets - for (const MorphTarget* morphTarget : mMorphTargets) + for (const MorphTarget* morphTarget : m_morphTargets) { clone->AddMorphTarget(morphTarget->Clone()); } @@ -162,7 +162,7 @@ namespace EMotionFX void MorphSetup::ReserveMorphTargets(size_t numMorphTargets) { - mMorphTargets.reserve(numMorphTargets); + m_morphTargets.reserve(numMorphTargets); } @@ -176,7 +176,7 @@ namespace EMotionFX } // scale the morph targets - for (MorphTarget* morphTarget : mMorphTargets) + for (MorphTarget* morphTarget : m_morphTargets) { morphTarget->Scale(scaleFactor); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MorphSetup.h b/Gems/EMotionFX/Code/EMotionFX/Source/MorphSetup.h index 23a5789e03..12014dba8e 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MorphSetup.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MorphSetup.h @@ -40,14 +40,14 @@ namespace EMotionFX * Get the number of morph targets inside this morph setup. * @result The number of morph targets. */ - MCORE_INLINE size_t GetNumMorphTargets() const { return mMorphTargets.size(); } + MCORE_INLINE size_t GetNumMorphTargets() const { return m_morphTargets.size(); } /** * Get a given morph target. * @param nr The morph target number, must be in range of [0..GetNumMorphTargets()-1]. * @result A pointer to the morph target. */ - MCORE_INLINE MorphTarget* GetMorphTarget(size_t nr) const { return mMorphTargets[nr]; } + MCORE_INLINE MorphTarget* GetMorphTarget(size_t nr) const { return m_morphTargets[nr]; } /** * Add a morph target to this morph setup. @@ -137,7 +137,7 @@ namespace EMotionFX protected: - AZStd::vector mMorphTargets; /**< The collection of morph targets. */ + AZStd::vector m_morphTargets; /**< The collection of morph targets. */ /** * The constructor. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MorphSetupInstance.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MorphSetupInstance.cpp index df4aaa0e7c..5b6e85d653 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MorphSetupInstance.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MorphSetupInstance.cpp @@ -62,12 +62,12 @@ namespace EMotionFX // allocate the number of morph targets const size_t numMorphTargets = morphSetup->GetNumMorphTargets(); - mMorphTargets.resize(numMorphTargets); + m_morphTargets.resize(numMorphTargets); // update the ID values for (uint32 i = 0; i < numMorphTargets; ++i) { - mMorphTargets[i].SetID(morphSetup->GetMorphTarget(i)->GetID()); + m_morphTargets[i].SetID(morphSetup->GetMorphTarget(i)->GetID()); } } @@ -76,11 +76,11 @@ namespace EMotionFX size_t MorphSetupInstance::FindMorphTargetIndexByID(uint32 id) const { // try to locate the morph target with the given ID - const auto foundElement = AZStd::find_if(mMorphTargets.begin(), mMorphTargets.end(), [id](const MorphTarget& morphTarget) + const auto foundElement = AZStd::find_if(m_morphTargets.begin(), m_morphTargets.end(), [id](const MorphTarget& morphTarget) { return morphTarget.GetID() == id; }); - return foundElement != mMorphTargets.end() ? AZStd::distance(mMorphTargets.begin(), foundElement) : InvalidIndex; + return foundElement != m_morphTargets.end() ? AZStd::distance(m_morphTargets.begin(), foundElement) : InvalidIndex; } @@ -89,7 +89,7 @@ namespace EMotionFX const size_t index = FindMorphTargetIndexByID(id); if (index != InvalidIndex) { - return &mMorphTargets[index]; + return &m_morphTargets[index]; } else { diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MorphSetupInstance.h b/Gems/EMotionFX/Code/EMotionFX/Source/MorphSetupInstance.h index e93ed7cf6d..d0c71f1f84 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MorphSetupInstance.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MorphSetupInstance.h @@ -41,9 +41,9 @@ namespace EMotionFX * The constructor. */ MorphTarget() - : mID(MCORE_INVALIDINDEX32) - , mWeight(0.0f) - , mIsInManualMode(false) {} + : m_id(MCORE_INVALIDINDEX32) + , m_weight(0.0f) + , m_isInManualMode(false) {} /** * The destructor. @@ -55,13 +55,13 @@ namespace EMotionFX * This ID links the MorphTarget class with this local morph target class. * @result The ID of this morph target. */ - MCORE_INLINE uint32 GetID() const { return mID; } + MCORE_INLINE uint32 GetID() const { return m_id; } /** * Get the weight value of the morph target. * @result The weight value. */ - float GetWeight() const { return mWeight; } + float GetWeight() const { return m_weight; } /** * Check if we are in manual mode or not. @@ -69,20 +69,20 @@ namespace EMotionFX * then the motion system will overwrite the weight values. * @result Returns true when we are in manual mode, otherwise false is returned. */ - bool GetIsInManualMode() const { return mIsInManualMode; } + bool GetIsInManualMode() const { return m_isInManualMode; } /** * Set the ID of this morph target. * This ID links the MorphTarget class with this local morph target class. * @param id The ID to use. */ - void SetID(uint32 id) { mID = id; } + void SetID(uint32 id) { m_id = id; } /** * Set the weight value of the morph target. * @param weight The weight value. */ - void SetWeight(float weight) { mWeight = weight; } + void SetWeight(float weight) { m_weight = weight; } /** * Enable or disable manual mode. @@ -90,12 +90,12 @@ namespace EMotionFX * then the motion system will overwrite the weight values. * @param enabled Set to true if you wish to enable manual mode on this morph target. Otherwise set to false. */ - void SetManualMode(bool enabled) { mIsInManualMode = enabled; } + void SetManualMode(bool enabled) { m_isInManualMode = enabled; } private: - uint32 mID; /**< The ID, which is based on the weight. */ - float mWeight; /**< The weight for this morph target. */ - bool mIsInManualMode; /**< The flag if we are in manual weight update mode or not. */ + uint32 m_id; /**< The ID, which is based on the weight. */ + float m_weight; /**< The weight for this morph target. */ + bool m_isInManualMode; /**< The flag if we are in manual weight update mode or not. */ }; @@ -123,16 +123,16 @@ namespace EMotionFX * This should always be equal to the number of morph targets in the highest detail. * @result The number of morph targets. */ - MCORE_INLINE size_t GetNumMorphTargets() const { return mMorphTargets.size(); } + MCORE_INLINE size_t GetNumMorphTargets() const { return m_morphTargets.size(); } /** * Get a specific morph target. * @param nr The morph target number, which must be in range of [0..GetNumMorphTargets()-1]. * @result A pointer to the morph target inside this class. */ - MCORE_INLINE MorphTarget* GetMorphTarget(size_t nr) { return &mMorphTargets[nr]; } + MCORE_INLINE MorphTarget* GetMorphTarget(size_t nr) { return &m_morphTargets[nr]; } - MCORE_INLINE const MorphTarget* GetMorphTarget(size_t nr) const { return &mMorphTargets[nr]; } + MCORE_INLINE const MorphTarget* GetMorphTarget(size_t nr) const { return &m_morphTargets[nr]; } /** * Find a given morph target number by its ID. @@ -149,7 +149,7 @@ namespace EMotionFX MorphTarget* FindMorphTargetByID(uint32 id); private: - AZStd::vector mMorphTargets; /**< The unique morph target information. */ + AZStd::vector m_morphTargets; /**< The unique morph target information. */ /** * The default constructor. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MorphTarget.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MorphTarget.cpp index 9ccafbb5f3..f2ff9eef5d 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MorphTarget.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MorphTarget.cpp @@ -23,9 +23,9 @@ namespace EMotionFX MorphTarget::MorphTarget(const char* name) : BaseObject() { - mRangeMin = 0.0f; - mRangeMax = 1.0f; - mPhonemeSets = PHONEMESET_NONE; + m_rangeMin = 0.0f; + m_rangeMax = 1.0f; + m_phonemeSets = PHONEMESET_NONE; // set the name SetName(name); @@ -177,10 +177,10 @@ namespace EMotionFX // calculate the weight in range of 0..1 float MorphTarget::CalcNormalizedWeight(float rangedWeight) const { - const float range = mRangeMax - mRangeMin; + const float range = m_rangeMax - m_rangeMin; if (MCore::Math::Abs(range) > 0.0f) { - return (rangedWeight - mRangeMin) / range; + return (rangedWeight - m_rangeMin) / range; } else { @@ -201,11 +201,11 @@ namespace EMotionFX { if (enabled) { - mPhonemeSets = (EPhonemeSet)((uint32)mPhonemeSets | (uint32)set); + m_phonemeSets = (EPhonemeSet)((uint32)m_phonemeSets | (uint32)set); } else { - mPhonemeSets = (EPhonemeSet)((uint32)mPhonemeSets & (uint32) ~set); + m_phonemeSets = (EPhonemeSet)((uint32)m_phonemeSets & (uint32) ~set); } } @@ -213,87 +213,87 @@ namespace EMotionFX // copy the base class members to the target class void MorphTarget::CopyBaseClassMemberValues(MorphTarget* target) const { - target->mNameID = mNameID; - target->mRangeMin = mRangeMin; - target->mRangeMax = mRangeMax; - target->mPhonemeSets = mPhonemeSets; + target->m_nameId = m_nameId; + target->m_rangeMin = m_rangeMin; + target->m_rangeMax = m_rangeMax; + target->m_phonemeSets = m_phonemeSets; } const char* MorphTarget::GetName() const { - return MCore::GetStringIdPool().GetName(mNameID).c_str(); + return MCore::GetStringIdPool().GetName(m_nameId).c_str(); } const AZStd::string& MorphTarget::GetNameString() const { - return MCore::GetStringIdPool().GetName(mNameID); + return MCore::GetStringIdPool().GetName(m_nameId); } void MorphTarget::SetRangeMin(float rangeMin) { - mRangeMin = rangeMin; + m_rangeMin = rangeMin; } void MorphTarget::SetRangeMax(float rangeMax) { - mRangeMax = rangeMax; + m_rangeMax = rangeMax; } float MorphTarget::GetRangeMin() const { - return mRangeMin; + return m_rangeMin; } float MorphTarget::GetRangeMax() const { - return mRangeMax; + return m_rangeMax; } void MorphTarget::SetName(const char* name) { - mNameID = MCore::GetStringIdPool().GenerateIdForString(name); + m_nameId = MCore::GetStringIdPool().GenerateIdForString(name); } void MorphTarget::SetPhonemeSets(EPhonemeSet phonemeSets) { - mPhonemeSets = phonemeSets; + m_phonemeSets = phonemeSets; } MorphTarget::EPhonemeSet MorphTarget::GetPhonemeSets() const { - return mPhonemeSets; + return m_phonemeSets; } bool MorphTarget::GetIsPhonemeSetEnabled(EPhonemeSet set) const { - return (mPhonemeSets & set) != 0; + return (m_phonemeSets & set) != 0; } float MorphTarget::CalcRangedWeight(float weight) const { - return mRangeMin + (weight * (mRangeMax - mRangeMin)); + return m_rangeMin + (weight * (m_rangeMax - m_rangeMin)); } float MorphTarget::CalcZeroInfluenceWeight() const { - return MCore::Math::Abs(mRangeMin) / MCore::Math::Abs(mRangeMax - mRangeMin); + return MCore::Math::Abs(m_rangeMin) / MCore::Math::Abs(m_rangeMax - m_rangeMin); } bool MorphTarget::GetIsPhoneme() const { - return (mPhonemeSets != PHONEMESET_NONE); + return (m_phonemeSets != PHONEMESET_NONE); } } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MorphTarget.h b/Gems/EMotionFX/Code/EMotionFX/Source/MorphTarget.h index 35e2f620ae..0cd85222d0 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MorphTarget.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MorphTarget.h @@ -77,7 +77,7 @@ namespace EMotionFX * name compares to simple integer compares. * @result The unique ID of the morph target. */ - MCORE_INLINE uint32 GetID() const { return mNameID; } + MCORE_INLINE uint32 GetID() const { return m_nameId; } /** * Get the unique name of the morph target. @@ -276,10 +276,10 @@ namespace EMotionFX virtual void Scale(float scaleFactor) = 0; protected: - uint32 mNameID; /**< The unique ID of the morph target, calculated from the name. */ - float mRangeMin; /**< The minimum range of the weight. */ - float mRangeMax; /**< The maximum range of the weight. */ - EPhonemeSet mPhonemeSets; /**< The phoneme sets in case this morph target is used as a phoneme. */ + uint32 m_nameId; /**< The unique ID of the morph target, calculated from the name. */ + float m_rangeMin; /**< The minimum range of the weight. */ + float m_rangeMax; /**< The maximum range of the weight. */ + EPhonemeSet m_phonemeSets; /**< The phoneme sets in case this morph target is used as a phoneme. */ /** * The constructor. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MorphTargetStandard.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MorphTargetStandard.cpp index c86815be80..ccb849a0d3 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MorphTargetStandard.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MorphTargetStandard.cpp @@ -65,22 +65,12 @@ namespace EMotionFX if (captureTransforms) { - // get a bone list, if we also captured meshes, because in that case we want - // to disable capturing transforms for the bones since the deforms already have been captured - // by the mesh capture - //Array boneList; - //if (mCaptureMeshDeforms) - //pose->ExtractBoneList(0, &boneList); - Skeleton* targetSkeleton = targetPose->GetSkeleton(); Skeleton* neutralSkeleton = neutralPose->GetSkeleton(); const Pose& neutralBindPose = *neutralPose->GetBindPose(); const Pose& targetBindPose = *targetPose->GetBindPose(); - // Transform* neutralData = neutralPose->GetBindPoseLocalTransforms(); - // Transform* targetData = targetPose->GetBindPoseLocalTransforms(); - // check for transformation changes const size_t numPoseNodes = targetSkeleton->GetNumNodes(); for (size_t i = 0; i < numPoseNodes; ++i) @@ -99,25 +89,18 @@ namespace EMotionFX const size_t neutralNodeIndex = neutralNode->GetNodeIndex(); const size_t targetNodeIndex = targetSkeleton->GetNode(i)->GetNodeIndex(); - // skip bones in the bone list - //if (mCaptureMeshDeforms) - //if (boneList.Contains( nodeA )) - //continue; - const Transform& neutralTransform = neutralBindPose.GetLocalSpaceTransform(neutralNodeIndex); const Transform& targetTransform = targetBindPose.GetLocalSpaceTransform(targetNodeIndex); - AZ::Vector3 neutralPos = neutralTransform.mPosition; - AZ::Vector3 targetPos = targetTransform.mPosition; - AZ::Quaternion neutralRot = neutralTransform.mRotation; - AZ::Quaternion targetRot = targetTransform.mRotation; + AZ::Vector3 neutralPos = neutralTransform.m_position; + AZ::Vector3 targetPos = targetTransform.m_position; + AZ::Quaternion neutralRot = neutralTransform.m_rotation; + AZ::Quaternion targetRot = targetTransform.m_rotation; EMFX_SCALECODE ( - AZ::Vector3 neutralScale = neutralTransform.mScale; - AZ::Vector3 targetScale = targetTransform.mScale; - //AZ::Quaternion neutralScaleRot = neutralTransform.mScaleRotation; - //AZ::Quaternion targetScaleRot = targetTransform.mScaleRotation; + AZ::Vector3 neutralScale = neutralTransform.m_scale; + AZ::Vector3 targetScale = targetTransform.m_scale; ) // check if the position changed @@ -137,9 +120,6 @@ namespace EMotionFX changed = (MCore::Compare::CheckIfIsClose(neutralScale, targetScale, MCore::Math::epsilon) == false); } - // check if the scale rotation changed - // if (changed == false) - // changed = (MCore::Compare::CheckIfIsClose(neutralScaleRot, targetScaleRot, MCore::Math::epsilon) == false); ) // if this node changed transformation @@ -147,23 +127,20 @@ namespace EMotionFX { // create a transform object form the node in the pose Transformation transform; - transform.mPosition = targetPos - neutralPos; - transform.mRotation = targetRot; + transform.m_position = targetPos - neutralPos; + transform.m_rotation = targetRot; EMFX_SCALECODE ( - //transform.mScaleRotation= targetScaleRot; - transform.mScale = targetScale - neutralScale; + transform.m_scale = targetScale - neutralScale; ) - transform.mNodeIndex = neutralNodeIndex; + transform.m_nodeIndex = neutralNodeIndex; // add the new transform AddTransformation(transform); } } - - //LogInfo("Num transforms = %d", mTransforms.GetLength()); } } @@ -173,24 +150,24 @@ namespace EMotionFX void MorphTargetStandard::ApplyTransformation(ActorInstance* actorInstance, size_t nodeIndex, AZ::Vector3& position, AZ::Quaternion& rotation, AZ::Vector3& scale, float weight) { // calculate the normalized weight (in range of 0..1) - const float newWeight = MCore::Clamp(weight, mRangeMin, mRangeMax); // make sure its within the range + const float newWeight = MCore::Clamp(weight, m_rangeMin, m_rangeMax); // make sure its within the range const float normalizedWeight = CalcNormalizedWeight(newWeight); // convert in range of 0..1 // calculate the new transformations for all nodes of this morph target - for (const Transformation& transform : mTransforms) + for (const Transformation& transform : m_transforms) { // if this is the node that gets modified by this transform - if (transform.mNodeIndex != nodeIndex) + if (transform.m_nodeIndex != nodeIndex) { continue; } - position += transform.mPosition * newWeight; - scale += transform.mScale * newWeight; + position += transform.m_position * newWeight; + scale += transform.m_scale * newWeight; // rotate additively - const AZ::Quaternion& orgRot = actorInstance->GetTransformData()->GetBindPose()->GetLocalSpaceTransform(nodeIndex).mRotation; - const AZ::Quaternion rot = orgRot.NLerp(transform.mRotation, normalizedWeight); + const AZ::Quaternion& orgRot = actorInstance->GetTransformData()->GetBindPose()->GetLocalSpaceTransform(nodeIndex).m_rotation; + const AZ::Quaternion rot = orgRot.NLerp(transform.m_rotation, normalizedWeight); rotation = rotation * (orgRot.GetInverseFull() * rot); rotation.Normalize(); @@ -204,14 +181,14 @@ namespace EMotionFX bool MorphTargetStandard::Influences(size_t nodeIndex) const { return - AZStd::any_of(begin(mDeformDatas), end(mDeformDatas), [nodeIndex](const DeformData* deformData) + AZStd::any_of(begin(m_deformDatas), end(m_deformDatas), [nodeIndex](const DeformData* deformData) { - return deformData->mNodeIndex == nodeIndex; + return deformData->m_nodeIndex == nodeIndex; }) || - AZStd::any_of(begin(mTransforms), end(mTransforms), [nodeIndex](const Transformation& transform) + AZStd::any_of(begin(m_transforms), end(m_transforms), [nodeIndex](const Transformation& transform) { - return transform.mNodeIndex == nodeIndex; + return transform.m_nodeIndex == nodeIndex; }); } @@ -220,45 +197,34 @@ namespace EMotionFX void MorphTargetStandard::Apply(ActorInstance* actorInstance, float weight) { // calculate the normalized weight (in range of 0..1) - const float newWeight = MCore::Clamp(weight, mRangeMin, mRangeMax); // make sure its within the range + const float newWeight = MCore::Clamp(weight, m_rangeMin, m_rangeMax); // make sure its within the range const float normalizedWeight = CalcNormalizedWeight(newWeight); // convert in range of 0..1 TransformData* transformData = actorInstance->GetTransformData(); Transform newTransform; // calculate the new transformations for all nodes of this morph target - for (const Transformation& transform : mTransforms) + for (const Transformation& transform : m_transforms) { // try to find the node - const size_t nodeIndex = transform.mNodeIndex; + const size_t nodeIndex = transform.m_nodeIndex; // init the transform data newTransform = transformData->GetCurrentPose()->GetLocalSpaceTransform(nodeIndex); // calc new position and scale (delta based targetTransform) - newTransform.mPosition += transform.mPosition * newWeight; + newTransform.m_position += transform.m_position * newWeight; EMFX_SCALECODE ( - newTransform.mScale += transform.mScale * newWeight; - // newTransform.mScaleRotation.Identity(); + newTransform.m_scale += transform.m_scale * newWeight; ) // rotate additively - const AZ::Quaternion& orgRot = transformData->GetBindPose()->GetLocalSpaceTransform(nodeIndex).mRotation; - const AZ::Quaternion rot = orgRot.NLerp(transform.mRotation, normalizedWeight); - newTransform.mRotation = newTransform.mRotation * (orgRot.GetInverseFull() * rot); - newTransform.mRotation.Normalize(); - /* - // scale rotate additively - orgRot = actorInstance->GetTransformData()->GetOrgScaleRot( nodeIndex ); - a = orgRot; - b = mTransforms[i].mScaleRotation; - rot = a.Lerp(b, normalizedWeight); - rot.Normalize(); - newTransform.mScaleRotation = newTransform.mScaleRotation * (orgRot.Inversed() * rot); - newTransform.mScaleRotation.Normalize(); - */ + const AZ::Quaternion& orgRot = transformData->GetBindPose()->GetLocalSpaceTransform(nodeIndex).m_rotation; + const AZ::Quaternion rot = orgRot.NLerp(transform.m_rotation, normalizedWeight); + newTransform.m_rotation = newTransform.m_rotation * (orgRot.GetInverseFull() * rot); + newTransform.m_rotation.Normalize(); // set the new transformation transformData->GetCurrentPose()->SetLocalSpaceTransform(nodeIndex, newTransform); } @@ -266,33 +232,33 @@ namespace EMotionFX size_t MorphTargetStandard::GetNumDeformDatas() const { - return mDeformDatas.size(); + return m_deformDatas.size(); } MorphTargetStandard::DeformData* MorphTargetStandard::GetDeformData(size_t nr) const { - return mDeformDatas[nr]; + return m_deformDatas[nr]; } void MorphTargetStandard::AddDeformData(DeformData* data) { - mDeformDatas.emplace_back(data); + m_deformDatas.emplace_back(data); } void MorphTargetStandard::AddTransformation(const Transformation& transform) { - mTransforms.emplace_back(transform); + m_transforms.emplace_back(transform); } // get the number of transformations in this morph target size_t MorphTargetStandard::GetNumTransformations() const { - return mTransforms.size(); + return m_transforms.size(); } MorphTargetStandard::Transformation& MorphTargetStandard::GetTransformation(size_t nr) { - return mTransforms[nr]; + return m_transforms[nr]; } @@ -305,13 +271,13 @@ namespace EMotionFX // now copy over the standard morph target related values // first start with the transforms - clone->mTransforms = mTransforms; + clone->m_transforms = m_transforms; // now clone the deform datas - clone->mDeformDatas.resize(mDeformDatas.size()); - for (uint32 i = 0; i < mDeformDatas.size(); ++i) + clone->m_deformDatas.resize(m_deformDatas.size()); + for (uint32 i = 0; i < m_deformDatas.size(); ++i) { - clone->mDeformDatas[i] = mDeformDatas[i]->Clone(); + clone->m_deformDatas[i] = m_deformDatas[i]->Clone(); } // return the clone @@ -327,18 +293,18 @@ namespace EMotionFX // constructor MorphTargetStandard::DeformData::DeformData(size_t nodeIndex, uint32 numVerts) { - mNodeIndex = nodeIndex; - mNumVerts = numVerts; - mDeltas = (VertexDelta*)MCore::Allocate(numVerts * sizeof(VertexDelta), EMFX_MEMCATEGORY_GEOMETRY_PMORPHTARGETS, MorphTargetStandard::MEMORYBLOCK_ID); - mMinValue = -10.0f; - mMaxValue = +10.0f; + m_nodeIndex = nodeIndex; + m_numVerts = numVerts; + m_deltas = (VertexDelta*)MCore::Allocate(numVerts * sizeof(VertexDelta), EMFX_MEMCATEGORY_GEOMETRY_PMORPHTARGETS, MorphTargetStandard::MEMORYBLOCK_ID); + m_minValue = -10.0f; + m_maxValue = +10.0f; } // destructor MorphTargetStandard::DeformData::~DeformData() { - MCore::Free(mDeltas); + MCore::Free(m_deltas); } @@ -352,62 +318,62 @@ namespace EMotionFX // clone a morph target MorphTargetStandard::DeformData* MorphTargetStandard::DeformData::Clone() { - MorphTargetStandard::DeformData* clone = aznew MorphTargetStandard::DeformData(mNodeIndex, mNumVerts); + MorphTargetStandard::DeformData* clone = aznew MorphTargetStandard::DeformData(m_nodeIndex, m_numVerts); // copy the data - clone->mMinValue = mMinValue; - clone->mMaxValue = mMaxValue; - MCore::MemCopy((uint8*)clone->mDeltas, (uint8*)mDeltas, mNumVerts * sizeof(VertexDelta)); + clone->m_minValue = m_minValue; + clone->m_maxValue = m_maxValue; + MCore::MemCopy((uint8*)clone->m_deltas, (uint8*)m_deltas, m_numVerts * sizeof(VertexDelta)); return clone; } void MorphTargetStandard::RemoveAllDeformDatas() { - for (DeformData* deformData : mDeformDatas) + for (DeformData* deformData : m_deformDatas) { deformData->Destroy(); } - mDeformDatas.clear(); + m_deformDatas.clear(); } void MorphTargetStandard::RemoveAllDeformDatasFor(Node* joint) { - mDeformDatas.erase( - AZStd::remove_if(mDeformDatas.begin(), mDeformDatas.end(), + m_deformDatas.erase( + AZStd::remove_if(m_deformDatas.begin(), m_deformDatas.end(), [=](const DeformData* deformData) { - return deformData->mNodeIndex == joint->GetNodeIndex(); + return deformData->m_nodeIndex == joint->GetNodeIndex(); }), - mDeformDatas.end()); + m_deformDatas.end()); } // pre-alloc memory for the deform datas void MorphTargetStandard::ReserveDeformDatas(size_t numDeformDatas) { - mDeformDatas.reserve(numDeformDatas); + m_deformDatas.reserve(numDeformDatas); } // pre-allocate memory for the transformations void MorphTargetStandard::ReserveTransformations(size_t numTransforms) { - mTransforms.reserve(numTransforms); + m_transforms.reserve(numTransforms); } void MorphTargetStandard::RemoveDeformData(size_t index, bool delFromMem) { if (delFromMem) { - delete mDeformDatas[index]; + delete m_deformDatas[index]; } - mDeformDatas.erase(mDeformDatas.begin() + index); + m_deformDatas.erase(m_deformDatas.begin() + index); } void MorphTargetStandard::RemoveTransformation(size_t index) { - mTransforms.erase(AZStd::next(begin(mTransforms), index)); + m_transforms.erase(AZStd::next(begin(m_transforms), index)); } @@ -421,18 +387,18 @@ namespace EMotionFX } // scale the transformations - for (Transformation& transform : mTransforms) + for (Transformation& transform : m_transforms) { - transform.mPosition *= scaleFactor; + transform.m_position *= scaleFactor; } // scale the deform datas (packed per vertex morph deltas) - for (DeformData* deformData : mDeformDatas) + for (DeformData* deformData : m_deformDatas) { - DeformData::VertexDelta* deltas = deformData->mDeltas; + DeformData::VertexDelta* deltas = deformData->m_deltas; - float newMinValue = deformData->mMinValue * scaleFactor; - float newMaxValue = deformData->mMaxValue * scaleFactor; + float newMinValue = deformData->m_minValue * scaleFactor; + float newMaxValue = deformData->m_maxValue * scaleFactor; // make sure the values won't be too small if (newMaxValue - newMinValue < 1.0f) @@ -450,21 +416,21 @@ namespace EMotionFX // iterate over the deltas (per vertex values) - const uint32 numVerts = deformData->mNumVerts; + const uint32 numVerts = deformData->m_numVerts; for (uint32 v = 0; v < numVerts; ++v) { // decompress - AZ::Vector3 decompressed = deltas[v].mPosition.ToVector3(deformData->mMinValue, deformData->mMaxValue); + AZ::Vector3 decompressed = deltas[v].m_position.ToVector3(deformData->m_minValue, deformData->m_maxValue); // scale decompressed *= scaleFactor; // compress again - deltas[v].mPosition.FromVector3(decompressed, newMinValue, newMaxValue); + deltas[v].m_position.FromVector3(decompressed, newMinValue, newMaxValue); } - deformData->mMinValue = newMinValue; - deformData->mMaxValue = newMaxValue; + deformData->m_minValue = newMinValue; + deformData->m_maxValue = newMaxValue; } } } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MorphTargetStandard.h b/Gems/EMotionFX/Code/EMotionFX/Source/MorphTargetStandard.h index 2ea1c43906..c4187fd638 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MorphTargetStandard.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MorphTargetStandard.h @@ -59,11 +59,11 @@ namespace EMotionFX */ struct EMFX_API VertexDelta { - MCore::Compressed16BitVector3 mPosition; /**< The position delta. */ - MCore::Compressed8BitVector3 mNormal; /**< The normal delta. */ - MCore::Compressed8BitVector3 mTangent; /**< The first tangent layer delta. */ - MCore::Compressed8BitVector3 mBitangent; /**< The first bitangent layer delta. */ - uint32 mVertexNr; /**< The vertex number inside the mesh to apply this to. */ + MCore::Compressed16BitVector3 m_position; /**< The position delta. */ + MCore::Compressed8BitVector3 m_normal; /**< The normal delta. */ + MCore::Compressed8BitVector3 m_tangent; /**< The first tangent layer delta. */ + MCore::Compressed8BitVector3 m_bitangent; /**< The first bitangent layer delta. */ + uint32 m_vertexNr; /**< The vertex number inside the mesh to apply this to. */ }; static DeformData* Create(size_t nodeIndex, uint32 numVerts); @@ -72,11 +72,11 @@ namespace EMotionFX DeformData* Clone(); public: - VertexDelta* mDeltas; /**< The delta values. */ - uint32 mNumVerts; /**< The number of vertices in the mDeltas and mVertexNumbers arrays. */ - size_t mNodeIndex; /**< The node which this data works on. */ - float mMinValue; /**< The compression/decompression minimum value for the delta positions. */ - float mMaxValue; /**< The compression/decompression maximum value for the delta positions. */ + VertexDelta* m_deltas; /**< The delta values. */ + uint32 m_numVerts; /**< The number of vertices in the m_deltas and m_vertexNumbers arrays. */ + size_t m_nodeIndex; /**< The node which this data works on. */ + float m_minValue; /**< The compression/decompression minimum value for the delta positions. */ + float m_maxValue; /**< The compression/decompression maximum value for the delta positions. */ /** * The constructor. @@ -100,11 +100,11 @@ namespace EMotionFX */ struct EMFX_API MCORE_ALIGN_PRE(16) Transformation { - AZ::Quaternion mRotation; /**< The rotation as absolute value. So not a delta value, but a target (absolute) rotation. */ - AZ::Quaternion mScaleRotation; /**< The scale rotation, as absolute value. */ - AZ::Vector3 mPosition; /**< The position as a delta, so the difference between the original and target position. */ - AZ::Vector3 mScale; /**< The scale as a delta, so the difference between the original and target scale. */ - size_t mNodeIndex; /**< The node number to apply this on. */ + AZ::Quaternion m_rotation; /**< The rotation as absolute value. So not a delta value, but a target (absolute) rotation. */ + AZ::Quaternion m_scaleRotation; /**< The scale rotation, as absolute value. */ + AZ::Vector3 m_position; /**< The position as a delta, so the difference between the original and target position. */ + AZ::Vector3 m_scale; /**< The scale as a delta, so the difference between the original and target scale. */ + size_t m_nodeIndex; /**< The node number to apply this on. */ } MCORE_ALIGN_POST(16); @@ -260,8 +260,8 @@ namespace EMotionFX void Scale(float scaleFactor) override; private: - AZStd::vector mTransforms; /**< The relative transformations for the given nodes, in local space. The rotation however is absolute. */ - AZStd::vector mDeformDatas; /**< The deformation data objects. */ + AZStd::vector m_transforms; /**< The relative transformations for the given nodes, in local space. The rotation however is absolute. */ + AZStd::vector m_deformDatas; /**< The deformation data objects. */ /** * The constructor. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Motion.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Motion.cpp index 382a640e65..9ad55b1c40 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Motion.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Motion.cpp @@ -30,11 +30,11 @@ namespace EMotionFX Motion::Motion(const char* name) : BaseObject() { - mID = aznumeric_caster(MCore::GetIDGenerator().GenerateID()); + m_id = aznumeric_caster(MCore::GetIDGenerator().GenerateID()); m_eventTable = AZStd::make_unique(); - mUnitType = GetEMotionFX().GetUnitType(); - mFileUnitType = mUnitType; - mExtractionFlags = static_cast(0); + m_unitType = GetEMotionFX().GetUnitType(); + m_fileUnitType = m_unitType; + m_extractionFlags = static_cast(0); if (name) { @@ -42,7 +42,7 @@ namespace EMotionFX } #if defined(EMFX_DEVELOPMENT_BUILD) - mIsOwnedByRuntime = false; + m_isOwnedByRuntime = false; #endif // EMFX_DEVELOPMENT_BUILD // automatically register the motion @@ -55,7 +55,7 @@ namespace EMotionFX GetEventManager().OnDeleteMotion(this); // automatically unregister the motion - if (mAutoUnregister) + if (m_autoUnregister) { GetMotionManager().RemoveMotion(this, false); } @@ -68,42 +68,42 @@ namespace EMotionFX void Motion::SetName(const char* name) { // calculate the ID - mNameID = MCore::GetStringIdPool().GenerateIdForString(name); + m_nameId = MCore::GetStringIdPool().GenerateIdForString(name); } // set the filename of the motion void Motion::SetFileName(const char* filename) { - mFileName = filename; + m_fileName = filename; } // adjust the dirty flag void Motion::SetDirtyFlag(bool dirty) { - mDirtyFlag = dirty; + m_dirtyFlag = dirty; } // adjust the auto unregistering from the motion manager on delete void Motion::SetAutoUnregister(bool enabled) { - mAutoUnregister = enabled; + m_autoUnregister = enabled; } // do we auto unregister from the motion manager on delete? bool Motion::GetAutoUnregister() const { - return mAutoUnregister; + return m_autoUnregister; } void Motion::SetIsOwnedByRuntime(bool isOwnedByRuntime) { #if defined(EMFX_DEVELOPMENT_BUILD) - mIsOwnedByRuntime = isOwnedByRuntime; + m_isOwnedByRuntime = isOwnedByRuntime; #else AZ_UNUSED(isOwnedByRuntime); #endif @@ -113,7 +113,7 @@ namespace EMotionFX bool Motion::GetIsOwnedByRuntime() const { #if defined(EMFX_DEVELOPMENT_BUILD) - return mIsOwnedByRuntime; + return m_isOwnedByRuntime; #else return true; #endif @@ -122,25 +122,25 @@ namespace EMotionFX const char* Motion::GetName() const { - return MCore::GetStringIdPool().GetName(mNameID).c_str(); + return MCore::GetStringIdPool().GetName(m_nameId).c_str(); } const AZStd::string& Motion::GetNameString() const { - return MCore::GetStringIdPool().GetName(mNameID); + return MCore::GetStringIdPool().GetName(m_nameId); } void Motion::SetMotionFPS(float motionFPS) { - mMotionFPS = motionFPS; + m_motionFps = motionFPS; } float Motion::GetMotionFPS() const { - return mMotionFPS; + return m_motionFps; } @@ -163,31 +163,31 @@ namespace EMotionFX bool Motion::GetDirtyFlag() const { - return mDirtyFlag; + return m_dirtyFlag; } void Motion::SetMotionExtractionFlags(EMotionExtractionFlags flags) { - mExtractionFlags = flags; + m_extractionFlags = flags; } EMotionExtractionFlags Motion::GetMotionExtractionFlags() const { - return mExtractionFlags; + return m_extractionFlags; } void Motion::SetCustomData(void* dataPointer) { - mCustomData = dataPointer; + m_customData = dataPointer; } void* Motion::GetCustomData() const { - return mCustomData; + return m_customData; } @@ -203,48 +203,48 @@ namespace EMotionFX void Motion::SetID(uint32 id) { - mID = id; + m_id = id; } const char* Motion::GetFileName() const { - return mFileName.c_str(); + return m_fileName.c_str(); } const AZStd::string& Motion::GetFileNameString() const { - return mFileName; + return m_fileName; } uint32 Motion::GetID() const { - return mID; + return m_id; } void Motion::SetUnitType(MCore::Distance::EUnitType unitType) { - mUnitType = unitType; + m_unitType = unitType; } MCore::Distance::EUnitType Motion::GetUnitType() const { - return mUnitType; + return m_unitType; } void Motion::SetFileUnitType(MCore::Distance::EUnitType unitType) { - mFileUnitType = unitType; + m_fileUnitType = unitType; } MCore::Distance::EUnitType Motion::GetFileUnitType() const { - return mFileUnitType; + return m_fileUnitType; } void Motion::Scale(float scaleFactor) @@ -257,17 +257,17 @@ namespace EMotionFX // scale everything to the given unit type void Motion::ScaleToUnitType(MCore::Distance::EUnitType targetUnitType) { - if (mUnitType == targetUnitType) + if (m_unitType == targetUnitType) { return; } // calculate the scale factor and scale - const float scaleFactor = static_cast(MCore::Distance::GetConversionFactor(mUnitType, targetUnitType)); + const float scaleFactor = static_cast(MCore::Distance::GetConversionFactor(m_unitType, targetUnitType)); Scale(scaleFactor); // update the unit type - mUnitType = targetUnitType; + m_unitType = targetUnitType; } void Motion::UpdateDuration() diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Motion.h b/Gems/EMotionFX/Code/EMotionFX/Source/Motion.h index eae1037ab3..e6ec99835b 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Motion.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Motion.h @@ -251,21 +251,21 @@ namespace EMotionFX protected: MotionData* m_motionData = nullptr; /**< The motion data, which can in theory be any data representation/compression. */ - AZStd::string mFileName; /**< The filename of the motion. */ + AZStd::string m_fileName; /**< The filename of the motion. */ PlayBackInfo m_defaultPlayBackInfo; /**< The default/fallback motion playback info which will be used when no playback info is passed to the Play() function. */ AZStd::unique_ptr m_eventTable; /**< The event table, which contains all events, and will make sure events get executed. */ - MCore::Distance::EUnitType mUnitType; /**< The type of units used. */ - MCore::Distance::EUnitType mFileUnitType; /**< The type of units used, inside the file that got loaded. */ - void* mCustomData = nullptr; /**< A pointer to custom user data that is linked with this motion object. */ - float mMotionFPS = 30.0f; /**< The number of keyframes per second. */ - uint32 mNameID = MCORE_INVALIDINDEX32; /**< The ID represention the name or description of this motion. */ - uint32 mID = MCORE_INVALIDINDEX32; /**< The unique identification number for the motion. */ - EMotionExtractionFlags mExtractionFlags; /**< The motion extraction flags, which define behavior of the motion extraction system when applied to this motion. */ - bool mDirtyFlag = false; /**< The dirty flag which indicates whether the user has made changes to the motion since the last file save operation. */ - bool mAutoUnregister = true; /**< Automatically unregister the motion from the motion manager when this motion gets deleted? Default is true. */ + MCore::Distance::EUnitType m_unitType; /**< The type of units used. */ + MCore::Distance::EUnitType m_fileUnitType; /**< The type of units used, inside the file that got loaded. */ + void* m_customData = nullptr; /**< A pointer to custom user data that is linked with this motion object. */ + float m_motionFps = 30.0f; /**< The number of keyframes per second. */ + uint32 m_nameId = MCORE_INVALIDINDEX32; /**< The ID represention the name or description of this motion. */ + uint32 m_id = MCORE_INVALIDINDEX32; /**< The unique identification number for the motion. */ + EMotionExtractionFlags m_extractionFlags; /**< The motion extraction flags, which define behavior of the motion extraction system when applied to this motion. */ + bool m_dirtyFlag = false; /**< The dirty flag which indicates whether the user has made changes to the motion since the last file save operation. */ + bool m_autoUnregister = true; /**< Automatically unregister the motion from the motion manager when this motion gets deleted? Default is true. */ #if defined(EMFX_DEVELOPMENT_BUILD) - bool mIsOwnedByRuntime; + bool m_isOwnedByRuntime; #endif // EMFX_DEVELOPMENT_BUILD }; } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MotionData/MotionData.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MotionData/MotionData.cpp index 7421495c60..e3391ed44f 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MotionData/MotionData.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MotionData/MotionData.cpp @@ -218,18 +218,18 @@ namespace EMotionFX AZ::Vector3 MotionData::GetJointStaticPosition(size_t jointDataIndex) const { - return m_staticJointData[jointDataIndex].m_staticTransform.mPosition; + return m_staticJointData[jointDataIndex].m_staticTransform.m_position; } AZ::Quaternion MotionData::GetJointStaticRotation(size_t jointDataIndex) const { - return m_staticJointData[jointDataIndex].m_staticTransform.mRotation; + return m_staticJointData[jointDataIndex].m_staticTransform.m_rotation; } #ifndef EMFX_SCALE_DISABLED AZ::Vector3 MotionData::GetJointStaticScale(size_t jointDataIndex) const { - return m_staticJointData[jointDataIndex].m_staticTransform.mScale; + return m_staticJointData[jointDataIndex].m_staticTransform.m_scale; } #endif @@ -240,18 +240,18 @@ namespace EMotionFX AZ::Vector3 MotionData::GetJointBindPosePosition(size_t jointDataIndex) const { - return m_staticJointData[jointDataIndex].m_bindTransform.mPosition; + return m_staticJointData[jointDataIndex].m_bindTransform.m_position; } AZ::Quaternion MotionData::GetJointBindPoseRotation(size_t jointDataIndex) const { - return m_staticJointData[jointDataIndex].m_bindTransform.mRotation; + return m_staticJointData[jointDataIndex].m_bindTransform.m_rotation; } #ifndef EMFX_SCALE_DISABLED AZ::Vector3 MotionData::GetJointBindPoseScale(size_t jointDataIndex) const { - return m_staticJointData[jointDataIndex].m_bindTransform.mScale; + return m_staticJointData[jointDataIndex].m_bindTransform.m_scale; } #endif @@ -322,18 +322,18 @@ namespace EMotionFX void MotionData::SetJointStaticPosition(size_t jointDataIndex, const AZ::Vector3& position) { - m_staticJointData[jointDataIndex].m_staticTransform.mPosition = position; + m_staticJointData[jointDataIndex].m_staticTransform.m_position = position; } void MotionData::SetJointStaticRotation(size_t jointDataIndex, const AZ::Quaternion& rotation) { - m_staticJointData[jointDataIndex].m_staticTransform.mRotation = rotation; + m_staticJointData[jointDataIndex].m_staticTransform.m_rotation = rotation; } #ifndef EMFX_SCALE_DISABLED void MotionData::SetJointStaticScale(size_t jointDataIndex, const AZ::Vector3& scale) { - m_staticJointData[jointDataIndex].m_staticTransform.mScale = scale; + m_staticJointData[jointDataIndex].m_staticTransform.m_scale = scale; } #endif @@ -344,18 +344,18 @@ namespace EMotionFX void MotionData::SetJointBindPosePosition(size_t jointDataIndex, const AZ::Vector3& position) { - m_staticJointData[jointDataIndex].m_bindTransform.mPosition = position; + m_staticJointData[jointDataIndex].m_bindTransform.m_position = position; } void MotionData::SetJointBindPoseRotation(size_t jointDataIndex, const AZ::Quaternion& rotation) { - m_staticJointData[jointDataIndex].m_bindTransform.mRotation = rotation; + m_staticJointData[jointDataIndex].m_bindTransform.m_rotation = rotation; } #ifndef EMFX_SCALE_DISABLED void MotionData::SetJointBindPoseScale(size_t jointDataIndex, const AZ::Vector3& scale) { - m_staticJointData[jointDataIndex].m_bindTransform.mScale = scale; + m_staticJointData[jointDataIndex].m_bindTransform.m_scale = scale; } #endif @@ -474,11 +474,11 @@ namespace EMotionFX const size_t retargetRootDataIndex = jointLinks[actor->GetRetargetRootNodeIndex()]; if (retargetRootDataIndex != InvalidIndex) { - const float subMotionHeight = m_staticJointData[retargetRootDataIndex].m_bindTransform.mPosition.GetZ(); + const float subMotionHeight = m_staticJointData[retargetRootDataIndex].m_bindTransform.m_position.GetZ(); if (AZ::GetAbs(subMotionHeight) >= AZ::Constants::FloatEpsilon) { - const float heightFactor = bindPose->GetLocalSpaceTransform(retargetRootIndex).mPosition.GetZ() / subMotionHeight; - inOutTransform.mPosition *= heightFactor; + const float heightFactor = bindPose->GetLocalSpaceTransform(retargetRootIndex).m_position.GetZ() / subMotionHeight; + inOutTransform.m_position *= heightFactor; needsDisplacement = false; } } @@ -491,14 +491,14 @@ namespace EMotionFX const Transform& motionBindPose = m_staticJointData[jointDataIndex].m_bindTransform; if (needsDisplacement) { - const AZ::Vector3 displacement = bindPoseTransform.mPosition - motionBindPose.mPosition; - inOutTransform.mPosition += displacement; + const AZ::Vector3 displacement = bindPoseTransform.m_position - motionBindPose.m_position; + inOutTransform.m_position += displacement; } EMFX_SCALECODE ( - const AZ::Vector3 scaleOffset = bindPoseTransform.mScale - motionBindPose.mScale; - inOutTransform.mScale += scaleOffset; + const AZ::Vector3 scaleOffset = bindPoseTransform.m_scale - motionBindPose.m_scale; + inOutTransform.m_scale += scaleOffset; ) } } @@ -566,8 +566,8 @@ namespace EMotionFX // Scale the static data for (StaticJointData& jointData : m_staticJointData) { - jointData.m_staticTransform.mPosition *= scaleFactor; - jointData.m_bindTransform.mPosition *= scaleFactor; + jointData.m_staticTransform.m_position *= scaleFactor; + jointData.m_bindTransform.m_position *= scaleFactor; } // Scale all data stored by the inherited class. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MotionData/NonUniformMotionData.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MotionData/NonUniformMotionData.cpp index 619a962d7e..6ced6152e1 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MotionData/NonUniformMotionData.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MotionData/NonUniformMotionData.cpp @@ -92,10 +92,10 @@ namespace EMotionFX if (jointDataIndex != InvalidIndex && !inPlace) { const JointData& jointData = m_jointData[jointDataIndex]; - result.mPosition = (!jointData.m_positionTrack.m_times.empty()) ? CalculateInterpolatedValue(jointData.m_positionTrack, settings.m_sampleTime) : m_staticJointData[jointDataIndex].m_staticTransform.mPosition; - result.mRotation = (!jointData.m_rotationTrack.m_times.empty()) ? CalculateInterpolatedValue(jointData.m_rotationTrack, settings.m_sampleTime) : m_staticJointData[jointDataIndex].m_staticTransform.mRotation; + result.m_position = (!jointData.m_positionTrack.m_times.empty()) ? CalculateInterpolatedValue(jointData.m_positionTrack, settings.m_sampleTime) : m_staticJointData[jointDataIndex].m_staticTransform.m_position; + result.m_rotation = (!jointData.m_rotationTrack.m_times.empty()) ? CalculateInterpolatedValue(jointData.m_rotationTrack, settings.m_sampleTime) : m_staticJointData[jointDataIndex].m_staticTransform.m_rotation; #ifndef EMFX_SCALE_DISABLED - result.mScale = (!jointData.m_scaleTrack.m_times.empty()) ? CalculateInterpolatedValue(jointData.m_scaleTrack, settings.m_sampleTime) : m_staticJointData[jointDataIndex].m_staticTransform.mScale; + result.m_scale = (!jointData.m_scaleTrack.m_times.empty()) ? CalculateInterpolatedValue(jointData.m_scaleTrack, settings.m_sampleTime) : m_staticJointData[jointDataIndex].m_staticTransform.m_scale; #endif } else @@ -123,9 +123,9 @@ namespace EMotionFX const Actor::NodeMirrorInfo& mirrorInfo = actor->GetNodeMirrorInfo(jointSkeletonIndex); Transform mirrored = bindPose->GetLocalSpaceTransform(jointSkeletonIndex); AZ::Vector3 mirrorAxis = AZ::Vector3::CreateZero(); - mirrorAxis.SetElement(mirrorInfo.mAxis, 1.0f); - const AZ::u16 motionSource = actor->GetNodeMirrorInfo(jointSkeletonIndex).mSourceNode; - mirrored.ApplyDeltaMirrored(bindPose->GetLocalSpaceTransform(motionSource), result, mirrorAxis, mirrorInfo.mFlags); + mirrorAxis.SetElement(mirrorInfo.m_axis, 1.0f); + const AZ::u16 motionSource = actor->GetNodeMirrorInfo(jointSkeletonIndex).m_sourceNode; + mirrored.ApplyDeltaMirrored(bindPose->GetLocalSpaceTransform(motionSource), result, mirrorAxis, mirrorInfo.m_flags); result = mirrored; } @@ -153,10 +153,10 @@ namespace EMotionFX if (jointDataIndex != InvalidIndex && !inPlace) { const JointData& jointData = m_jointData[jointDataIndex]; - result.mPosition = (!jointData.m_positionTrack.m_times.empty()) ? CalculateInterpolatedValue(jointData.m_positionTrack, settings.m_sampleTime) : m_staticJointData[jointDataIndex].m_staticTransform.mPosition; - result.mRotation = (!jointData.m_rotationTrack.m_times.empty()) ? CalculateInterpolatedValue(jointData.m_rotationTrack, settings.m_sampleTime) : m_staticJointData[jointDataIndex].m_staticTransform.mRotation; + result.m_position = (!jointData.m_positionTrack.m_times.empty()) ? CalculateInterpolatedValue(jointData.m_positionTrack, settings.m_sampleTime) : m_staticJointData[jointDataIndex].m_staticTransform.m_position; + result.m_rotation = (!jointData.m_rotationTrack.m_times.empty()) ? CalculateInterpolatedValue(jointData.m_rotationTrack, settings.m_sampleTime) : m_staticJointData[jointDataIndex].m_staticTransform.m_rotation; #ifndef EMFX_SCALE_DISABLED - result.mScale = (!jointData.m_scaleTrack.m_times.empty()) ? CalculateInterpolatedValue(jointData.m_scaleTrack, settings.m_sampleTime) : m_staticJointData[jointDataIndex].m_staticTransform.mScale; + result.m_scale = (!jointData.m_scaleTrack.m_times.empty()) ? CalculateInterpolatedValue(jointData.m_scaleTrack, settings.m_sampleTime) : m_staticJointData[jointDataIndex].m_staticTransform.m_scale; #endif } else @@ -1018,11 +1018,11 @@ namespace EMotionFX maxScaleError = 0.00001f; } - ReduceTrackSamples(jointData.m_positionTrack, m_staticJointData[i].m_staticTransform.mPosition, maxPosError); - ReduceTrackSamples(jointData.m_rotationTrack, m_staticJointData[i].m_staticTransform.mRotation, maxRotError); + ReduceTrackSamples(jointData.m_positionTrack, m_staticJointData[i].m_staticTransform.m_position, maxPosError); + ReduceTrackSamples(jointData.m_rotationTrack, m_staticJointData[i].m_staticTransform.m_rotation, maxRotError); EMFX_SCALECODE ( - ReduceTrackSamples(jointData.m_scaleTrack, m_staticJointData[i].m_staticTransform.mScale, maxScaleError); + ReduceTrackSamples(jointData.m_scaleTrack, m_staticJointData[i].m_staticTransform.m_scale, maxScaleError); ) } @@ -1143,11 +1143,11 @@ namespace EMotionFX { const float keyTime = s * sampleSpacing; const Transform transform = motionData->SampleJointTransform(keyTime, i); - SetJointPositionSample(i, s, {keyTime, transform.mPosition}); - SetJointRotationSample(i, s, {keyTime, transform.mRotation}); + SetJointPositionSample(i, s, {keyTime, transform.m_position}); + SetJointRotationSample(i, s, {keyTime, transform.m_rotation}); EMFX_SCALECODE ( - SetJointScaleSample(i, s, {keyTime, transform.mScale}); + SetJointScaleSample(i, s, {keyTime, transform.m_scale}); ) } } @@ -1191,18 +1191,18 @@ namespace EMotionFX AZ::Vector3 NonUniformMotionData::SampleJointPosition(float sampleTime, size_t jointDataIndex) const { - return !m_jointData[jointDataIndex].m_positionTrack.m_times.empty() ? CalculateInterpolatedValue(m_jointData[jointDataIndex].m_positionTrack, sampleTime) : m_staticJointData[jointDataIndex].m_staticTransform.mPosition; + return !m_jointData[jointDataIndex].m_positionTrack.m_times.empty() ? CalculateInterpolatedValue(m_jointData[jointDataIndex].m_positionTrack, sampleTime) : m_staticJointData[jointDataIndex].m_staticTransform.m_position; } AZ::Quaternion NonUniformMotionData::SampleJointRotation(float sampleTime, size_t jointDataIndex) const { - return !m_jointData[jointDataIndex].m_rotationTrack.m_times.empty() ? CalculateInterpolatedValue(m_jointData[jointDataIndex].m_rotationTrack, sampleTime) : m_staticJointData[jointDataIndex].m_staticTransform.mRotation; + return !m_jointData[jointDataIndex].m_rotationTrack.m_times.empty() ? CalculateInterpolatedValue(m_jointData[jointDataIndex].m_rotationTrack, sampleTime) : m_staticJointData[jointDataIndex].m_staticTransform.m_rotation; } #ifndef EMFX_SCALE_DISABLED AZ::Vector3 NonUniformMotionData::SampleJointScale(float sampleTime, size_t jointDataIndex) const { - return !m_jointData[jointDataIndex].m_scaleTrack.m_times.empty() ? CalculateInterpolatedValue(m_jointData[jointDataIndex].m_scaleTrack, sampleTime) : m_staticJointData[jointDataIndex].m_staticTransform.mScale; + return !m_jointData[jointDataIndex].m_scaleTrack.m_times.empty() ? CalculateInterpolatedValue(m_jointData[jointDataIndex].m_scaleTrack, sampleTime) : m_staticJointData[jointDataIndex].m_staticTransform.m_scale; } #endif @@ -1210,10 +1210,10 @@ namespace EMotionFX { return Transform ( - !m_jointData[jointDataIndex].m_positionTrack.m_times.empty() ? CalculateInterpolatedValue(m_jointData[jointDataIndex].m_positionTrack, sampleTime) : m_staticJointData[jointDataIndex].m_staticTransform.mPosition, - !m_jointData[jointDataIndex].m_rotationTrack.m_times.empty() ? CalculateInterpolatedValue(m_jointData[jointDataIndex].m_rotationTrack, sampleTime) : m_staticJointData[jointDataIndex].m_staticTransform.mRotation + !m_jointData[jointDataIndex].m_positionTrack.m_times.empty() ? CalculateInterpolatedValue(m_jointData[jointDataIndex].m_positionTrack, sampleTime) : m_staticJointData[jointDataIndex].m_staticTransform.m_position, + !m_jointData[jointDataIndex].m_rotationTrack.m_times.empty() ? CalculateInterpolatedValue(m_jointData[jointDataIndex].m_rotationTrack, sampleTime) : m_staticJointData[jointDataIndex].m_staticTransform.m_rotation #ifndef EMFX_SCALE_DISABLED - ,!m_jointData[jointDataIndex].m_scaleTrack.m_times.empty() ? CalculateInterpolatedValue(m_jointData[jointDataIndex].m_scaleTrack, sampleTime) : m_staticJointData[jointDataIndex].m_staticTransform.mScale + ,!m_jointData[jointDataIndex].m_scaleTrack.m_times.empty() ? CalculateInterpolatedValue(m_jointData[jointDataIndex].m_scaleTrack, sampleTime) : m_staticJointData[jointDataIndex].m_staticTransform.m_scale #endif ); } @@ -1225,11 +1225,11 @@ namespace EMotionFX for (size_t i = 0; i < m_jointData.size(); ++i) { JointData& jointData = tempJointData[i]; - ReduceTrackSamples(jointData.m_positionTrack, m_staticJointData[i].m_staticTransform.mPosition, 0.0001f); - ReduceTrackSamples(jointData.m_rotationTrack, m_staticJointData[i].m_staticTransform.mRotation, 0.0001f); + ReduceTrackSamples(jointData.m_positionTrack, m_staticJointData[i].m_staticTransform.m_position, 0.0001f); + ReduceTrackSamples(jointData.m_rotationTrack, m_staticJointData[i].m_staticTransform.m_rotation, 0.0001f); EMFX_SCALECODE ( - ReduceTrackSamples(jointData.m_scaleTrack, m_staticJointData[i].m_staticTransform.mScale, 0.0001f); + ReduceTrackSamples(jointData.m_scaleTrack, m_staticJointData[i].m_staticTransform.m_scale, 0.0001f); if (jointData.m_scaleTrack.m_times.empty()) { ClearJointScaleSamples(i); @@ -1376,15 +1376,15 @@ namespace EMotionFX if (saveSettings.m_logDetails) { - const AZ::Quaternion uncompressedPoseRot = MCore::Compressed16BitQuaternion(jointInfo.m_staticRot.mX, jointInfo.m_staticRot.mY, jointInfo.m_staticRot.mZ, jointInfo.m_staticRot.mW).ToQuaternion().GetNormalized(); - const AZ::Quaternion uncompressedBindPoseRot = MCore::Compressed16BitQuaternion(jointInfo.m_bindPoseRot.mX, jointInfo.m_bindPoseRot.mY, jointInfo.m_bindPoseRot.mZ, jointInfo.m_bindPoseRot.mW).ToQuaternion().GetNormalized(); + const AZ::Quaternion uncompressedPoseRot = MCore::Compressed16BitQuaternion(jointInfo.m_staticRot.m_x, jointInfo.m_staticRot.m_y, jointInfo.m_staticRot.m_z, jointInfo.m_staticRot.m_w).ToQuaternion().GetNormalized(); + const AZ::Quaternion uncompressedBindPoseRot = MCore::Compressed16BitQuaternion(jointInfo.m_bindPoseRot.m_x, jointInfo.m_bindPoseRot.m_y, jointInfo.m_bindPoseRot.m_z, jointInfo.m_bindPoseRot.m_w).ToQuaternion().GetNormalized(); MCore::LogDetailedInfo("- Motion Joint: %s", motionData->GetJointName(jointDataIndex).c_str()); - MCore::LogDetailedInfo(" + Pose Translation: x=%f y=%f z=%f", jointInfo.m_staticPos.mX, jointInfo.m_staticPos.mY, jointInfo.m_staticPos.mZ); + MCore::LogDetailedInfo(" + Pose Translation: x=%f y=%f z=%f", jointInfo.m_staticPos.m_x, jointInfo.m_staticPos.m_y, jointInfo.m_staticPos.m_z); MCore::LogDetailedInfo(" + Pose Rotation: x=%f y=%f z=%f w=%f", static_cast(uncompressedPoseRot.GetX()), static_cast(uncompressedPoseRot.GetY()), static_cast(uncompressedPoseRot.GetZ()), static_cast(uncompressedPoseRot.GetW())); - MCore::LogDetailedInfo(" + Pose Scale: x=%f y=%f z=%f", jointInfo.m_staticScale.mX, jointInfo.m_staticScale.mY, jointInfo.m_staticScale.mZ); - MCore::LogDetailedInfo(" + Bind Pose Translation: x=%f y=%f z=%f", jointInfo.m_bindPosePos.mX, jointInfo.m_bindPosePos.mY, jointInfo.m_bindPosePos.mZ); + MCore::LogDetailedInfo(" + Pose Scale: x=%f y=%f z=%f", jointInfo.m_staticScale.m_x, jointInfo.m_staticScale.m_y, jointInfo.m_staticScale.m_z); + MCore::LogDetailedInfo(" + Bind Pose Translation: x=%f y=%f z=%f", jointInfo.m_bindPosePos.m_x, jointInfo.m_bindPosePos.m_y, jointInfo.m_bindPosePos.m_z); MCore::LogDetailedInfo(" + Bind Pose Rotation: x=%f y=%f z=%f w=%f", static_cast(uncompressedBindPoseRot.GetX()), static_cast(uncompressedBindPoseRot.GetY()), static_cast(uncompressedBindPoseRot.GetZ()), static_cast(uncompressedBindPoseRot.GetW())); - MCore::LogDetailedInfo(" + Bind Pose Scale: x=%f y=%f z=%f", jointInfo.m_bindPoseScale.mX, jointInfo.m_bindPoseScale.mY, jointInfo.m_bindPoseScale.mZ); + MCore::LogDetailedInfo(" + Bind Pose Scale: x=%f y=%f z=%f", jointInfo.m_bindPoseScale.m_x, jointInfo.m_bindPoseScale.m_y, jointInfo.m_bindPoseScale.m_z); MCore::LogDetailedInfo(" + Num Position Keys: %d", jointInfo.m_numPosKeys); MCore::LogDetailedInfo(" + Num Rotation Keys: %d", jointInfo.m_numRotKeys); MCore::LogDetailedInfo(" + Num Scale Keys: %d", jointInfo.m_numScaleKeys); @@ -1697,12 +1697,12 @@ namespace EMotionFX return false; } - AZ::Vector3 staticPos(jointInfo.m_staticPos.mX, jointInfo.m_staticPos.mY, jointInfo.m_staticPos.mZ); - AZ::Vector3 staticScale(jointInfo.m_staticScale.mX, jointInfo.m_staticScale.mY, jointInfo.m_staticScale.mZ); - MCore::Compressed16BitQuaternion staticRot(jointInfo.m_staticRot.mX, jointInfo.m_staticRot.mY, jointInfo.m_staticRot.mZ, jointInfo.m_staticRot.mW); - AZ::Vector3 bindPosePos(jointInfo.m_bindPosePos.mX, jointInfo.m_bindPosePos.mY, jointInfo.m_bindPosePos.mZ); - AZ::Vector3 bindPoseScale(jointInfo.m_bindPoseScale.mX, jointInfo.m_bindPoseScale.mY, jointInfo.m_bindPoseScale.mZ); - MCore::Compressed16BitQuaternion bindPoseRot(jointInfo.m_bindPoseRot.mX, jointInfo.m_bindPoseRot.mY, jointInfo.m_bindPoseRot.mZ, jointInfo.m_bindPoseRot.mW); + AZ::Vector3 staticPos(jointInfo.m_staticPos.m_x, jointInfo.m_staticPos.m_y, jointInfo.m_staticPos.m_z); + AZ::Vector3 staticScale(jointInfo.m_staticScale.m_x, jointInfo.m_staticScale.m_y, jointInfo.m_staticScale.m_z); + MCore::Compressed16BitQuaternion staticRot(jointInfo.m_staticRot.m_x, jointInfo.m_staticRot.m_y, jointInfo.m_staticRot.m_z, jointInfo.m_staticRot.m_w); + AZ::Vector3 bindPosePos(jointInfo.m_bindPosePos.m_x, jointInfo.m_bindPosePos.m_y, jointInfo.m_bindPosePos.m_z); + AZ::Vector3 bindPoseScale(jointInfo.m_bindPoseScale.m_x, jointInfo.m_bindPoseScale.m_y, jointInfo.m_bindPoseScale.m_z); + MCore::Compressed16BitQuaternion bindPoseRot(jointInfo.m_bindPoseRot.m_x, jointInfo.m_bindPoseRot.m_y, jointInfo.m_bindPoseRot.m_z, jointInfo.m_bindPoseRot.m_w); MCore::Endian::ConvertVector3(&staticPos, sourceEndianType); MCore::Endian::Convert16BitQuaternion(&staticRot, sourceEndianType); MCore::Endian::ConvertVector3(&staticScale, sourceEndianType); @@ -1747,8 +1747,8 @@ namespace EMotionFX return false; } MCore::Endian::ConvertFloat(&keyInfo.m_time, sourceEndianType); - MCore::Endian::ConvertFloat(&keyInfo.m_value.mX, sourceEndianType, /*numFloats=*/3); - motionData->SetJointPositionSample(i, s, {keyInfo.m_time, AZ::Vector3(keyInfo.m_value.mX, keyInfo.m_value.mY, keyInfo.m_value.mZ)}); + MCore::Endian::ConvertFloat(&keyInfo.m_value.m_x, sourceEndianType, /*numFloats=*/3); + motionData->SetJointPositionSample(i, s, {keyInfo.m_time, AZ::Vector3(keyInfo.m_value.m_x, keyInfo.m_value.m_y, keyInfo.m_value.m_z)}); } } @@ -1764,7 +1764,7 @@ namespace EMotionFX return false; } MCore::Endian::ConvertFloat(&keyInfo.m_time, sourceEndianType); - MCore::Compressed16BitQuaternion compressedQuat(keyInfo.m_value.mX, keyInfo.m_value.mY, keyInfo.m_value.mZ, keyInfo.m_value.mW); + MCore::Compressed16BitQuaternion compressedQuat(keyInfo.m_value.m_x, keyInfo.m_value.m_y, keyInfo.m_value.m_z, keyInfo.m_value.m_w); MCore::Endian::Convert16BitQuaternion(&compressedQuat, sourceEndianType); motionData->SetJointRotationSample(i, s, {keyInfo.m_time, compressedQuat.ToQuaternion().GetNormalized()}); } @@ -1784,8 +1784,8 @@ namespace EMotionFX return false; } MCore::Endian::ConvertFloat(&keyInfo.m_time, sourceEndianType); - MCore::Endian::ConvertFloat(&keyInfo.m_value.mX, sourceEndianType, /*numFloats=*/3); - motionData->SetJointScaleSample(i, s, {keyInfo.m_time, AZ::Vector3(keyInfo.m_value.mX, keyInfo.m_value.mY, keyInfo.m_value.mZ)}); + MCore::Endian::ConvertFloat(&keyInfo.m_value.m_x, sourceEndianType, /*numFloats=*/3); + motionData->SetJointScaleSample(i, s, {keyInfo.m_time, AZ::Vector3(keyInfo.m_value.m_x, keyInfo.m_value.m_y, keyInfo.m_value.m_z)}); } } ) diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MotionData/UniformMotionData.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MotionData/UniformMotionData.cpp index 44ed629756..c4451ff902 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MotionData/UniformMotionData.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MotionData/UniformMotionData.cpp @@ -88,11 +88,11 @@ namespace EMotionFX { const float keyTime = s * sampleSpacing; const Transform transform = motionData->SampleJointTransform(keyTime, i); - if (posAnimated) m_jointData[i].m_positions[s] = transform.mPosition; - if (rotAnimated) m_jointData[i].m_rotations[s] = transform.mRotation.GetNormalized(); + if (posAnimated) m_jointData[i].m_positions[s] = transform.m_position; + if (rotAnimated) m_jointData[i].m_rotations[s] = transform.m_rotation.GetNormalized(); EMFX_SCALECODE ( - if (scaleAnimated) m_jointData[i].m_scales[s] = transform.mScale; + if (scaleAnimated) m_jointData[i].m_scales[s] = transform.m_scale; ) } } @@ -156,10 +156,10 @@ namespace EMotionFX { const StaticJointData& staticJointData = m_staticJointData[transformDataIndex]; const JointData& jointData = m_jointData[transformDataIndex]; - result.mPosition = !jointData.m_positions.empty() ? jointData.m_positions[indexA].Lerp(jointData.m_positions[indexB], t) : staticJointData.m_staticTransform.mPosition; - result.mRotation = !jointData.m_rotations.empty() ? jointData.m_rotations[indexA].ToQuaternion().NLerp(jointData.m_rotations[indexB].ToQuaternion(), t) : staticJointData.m_staticTransform.mRotation; + result.m_position = !jointData.m_positions.empty() ? jointData.m_positions[indexA].Lerp(jointData.m_positions[indexB], t) : staticJointData.m_staticTransform.m_position; + result.m_rotation = !jointData.m_rotations.empty() ? jointData.m_rotations[indexA].ToQuaternion().NLerp(jointData.m_rotations[indexB].ToQuaternion(), t) : staticJointData.m_staticTransform.m_rotation; #ifndef EMFX_SCALE_DISABLED - result.mScale = !jointData.m_scales.empty() ? jointData.m_scales[indexA].Lerp(jointData.m_scales[indexB], t) : staticJointData.m_staticTransform.mScale; + result.m_scale = !jointData.m_scales.empty() ? jointData.m_scales[indexA].Lerp(jointData.m_scales[indexB], t) : staticJointData.m_staticTransform.m_scale; #endif } else @@ -187,9 +187,9 @@ namespace EMotionFX const Actor::NodeMirrorInfo& mirrorInfo = actor->GetNodeMirrorInfo(jointSkeletonIndex); Transform mirrored = bindPose->GetLocalSpaceTransform(jointSkeletonIndex); AZ::Vector3 mirrorAxis = AZ::Vector3::CreateZero(); - mirrorAxis.SetElement(mirrorInfo.mAxis, 1.0f); - const AZ::u16 motionSource = actor->GetNodeMirrorInfo(jointSkeletonIndex).mSourceNode; - mirrored.ApplyDeltaMirrored(bindPose->GetLocalSpaceTransform(motionSource), result, mirrorAxis, mirrorInfo.mFlags); + mirrorAxis.SetElement(mirrorInfo.m_axis, 1.0f); + const AZ::u16 motionSource = actor->GetNodeMirrorInfo(jointSkeletonIndex).m_sourceNode; + mirrored.ApplyDeltaMirrored(bindPose->GetLocalSpaceTransform(motionSource), result, mirrorAxis, mirrorInfo.m_flags); result = mirrored; } @@ -225,11 +225,11 @@ namespace EMotionFX { const StaticJointData& staticJointData = m_staticJointData[jointDataIndex]; const JointData& jointData = m_jointData[jointDataIndex]; - result.mPosition = !jointData.m_positions.empty() ? jointData.m_positions[indexA].Lerp(jointData.m_positions[indexB], t) : staticJointData.m_staticTransform.mPosition; - result.mRotation = !jointData.m_rotations.empty() ? jointData.m_rotations[indexA].ToQuaternion().NLerp(jointData.m_rotations[indexB].ToQuaternion(), t) : staticJointData.m_staticTransform.mRotation; + result.m_position = !jointData.m_positions.empty() ? jointData.m_positions[indexA].Lerp(jointData.m_positions[indexB], t) : staticJointData.m_staticTransform.m_position; + result.m_rotation = !jointData.m_rotations.empty() ? jointData.m_rotations[indexA].ToQuaternion().NLerp(jointData.m_rotations[indexB].ToQuaternion(), t) : staticJointData.m_staticTransform.m_rotation; #ifndef EMFX_SCALE_DISABLED - result.mScale = !jointData.m_scales.empty() ? jointData.m_scales[indexA].Lerp(jointData.m_scales[indexB], t) : staticJointData.m_staticTransform.mScale; + result.m_scale = !jointData.m_scales.empty() ? jointData.m_scales[indexA].Lerp(jointData.m_scales[indexB], t) : staticJointData.m_staticTransform.m_scale; #endif } else @@ -663,7 +663,7 @@ namespace EMotionFX CalculateInterpolationIndicesUniform(sampleTime, m_sampleSpacing, m_duration, m_numSamples, indexA, indexB, t); const AZStd::vector& values = m_jointData[jointDataIndex].m_positions; - return !values.empty() ? values[indexA].Lerp(values[indexB], t) : m_staticJointData[jointDataIndex].m_staticTransform.mPosition; + return !values.empty() ? values[indexA].Lerp(values[indexB], t) : m_staticJointData[jointDataIndex].m_staticTransform.m_position; } AZ::Quaternion UniformMotionData::SampleJointRotation(float sampleTime, size_t jointDataIndex) const @@ -674,7 +674,7 @@ namespace EMotionFX CalculateInterpolationIndicesUniform(sampleTime, m_sampleSpacing, m_duration, m_numSamples, indexA, indexB, t); const AZStd::vector& values = m_jointData[jointDataIndex].m_rotations; - return !values.empty() ? values[indexA].ToQuaternion().NLerp(values[indexB].ToQuaternion(), t) : m_staticJointData[jointDataIndex].m_staticTransform.mRotation; + return !values.empty() ? values[indexA].ToQuaternion().NLerp(values[indexB].ToQuaternion(), t) : m_staticJointData[jointDataIndex].m_staticTransform.m_rotation; } #ifndef EMFX_SCALE_DISABLED @@ -686,7 +686,7 @@ namespace EMotionFX CalculateInterpolationIndicesUniform(sampleTime, m_sampleSpacing, m_duration, m_numSamples, indexA, indexB, t); const AZStd::vector& values = m_jointData[jointDataIndex].m_scales; - return !values.empty() ? values[indexA].Lerp(values[indexB], t) : m_staticJointData[jointDataIndex].m_staticTransform.mScale; + return !values.empty() ? values[indexA].Lerp(values[indexB], t) : m_staticJointData[jointDataIndex].m_staticTransform.m_scale; } #endif @@ -706,11 +706,11 @@ namespace EMotionFX return Transform ( - !posValues.empty() ? posValues[indexA].Lerp(posValues[indexB], t) : staticData.m_staticTransform.mScale, - !rotValues.empty() ? rotValues[indexA].ToQuaternion().NLerp(rotValues[indexB].ToQuaternion(), t) : staticData.m_staticTransform.mRotation + !posValues.empty() ? posValues[indexA].Lerp(posValues[indexB], t) : staticData.m_staticTransform.m_scale, + !rotValues.empty() ? rotValues[indexA].ToQuaternion().NLerp(rotValues[indexB].ToQuaternion(), t) : staticData.m_staticTransform.m_rotation #ifndef EMFX_SCALE_DISABLED - ,!scaleValues.empty() ? scaleValues[indexA].Lerp(scaleValues[indexB], t) : staticData.m_staticTransform.mScale + ,!scaleValues.empty() ? scaleValues[indexA].Lerp(scaleValues[indexB], t) : staticData.m_staticTransform.m_scale #endif ); } @@ -808,16 +808,16 @@ namespace EMotionFX if (saveSettings.m_logDetails) { // Create an uncompressed version of the quaternions, for logging. - const AZ::Quaternion uncompressedPoseRot = MCore::Compressed16BitQuaternion(jointChunk.m_staticRot.mX, jointChunk.m_staticRot.mY, jointChunk.m_staticRot.mZ, jointChunk.m_staticRot.mW).ToQuaternion().GetNormalized(); - const AZ::Quaternion uncompressedBindPoseRot = MCore::Compressed16BitQuaternion(jointChunk.m_bindPoseRot.mX, jointChunk.m_bindPoseRot.mY, jointChunk.m_bindPoseRot.mZ, jointChunk.m_bindPoseRot.mW).ToQuaternion().GetNormalized(); + const AZ::Quaternion uncompressedPoseRot = MCore::Compressed16BitQuaternion(jointChunk.m_staticRot.m_x, jointChunk.m_staticRot.m_y, jointChunk.m_staticRot.m_z, jointChunk.m_staticRot.m_w).ToQuaternion().GetNormalized(); + const AZ::Quaternion uncompressedBindPoseRot = MCore::Compressed16BitQuaternion(jointChunk.m_bindPoseRot.m_x, jointChunk.m_bindPoseRot.m_y, jointChunk.m_bindPoseRot.m_z, jointChunk.m_bindPoseRot.m_w).ToQuaternion().GetNormalized(); MCore::LogDetailedInfo("- Motion Joint: %s", motionData->GetJointName(jointDataIndex).c_str()); - MCore::LogDetailedInfo(" + Static Translation: x=%f y=%f z=%f", jointChunk.m_staticPos.mX, jointChunk.m_staticPos.mY, jointChunk.m_staticPos.mZ); + MCore::LogDetailedInfo(" + Static Translation: x=%f y=%f z=%f", jointChunk.m_staticPos.m_x, jointChunk.m_staticPos.m_y, jointChunk.m_staticPos.m_z); MCore::LogDetailedInfo(" + Static Rotation: x=%f y=%f z=%f w=%f", static_cast(uncompressedPoseRot.GetX()), static_cast(uncompressedPoseRot.GetY()), static_cast(uncompressedPoseRot.GetZ()), static_cast(uncompressedPoseRot.GetW())); - MCore::LogDetailedInfo(" + Static Scale: x=%f y=%f z=%f", jointChunk.m_staticScale.mX, jointChunk.m_staticScale.mY, jointChunk.m_staticScale.mZ); - MCore::LogDetailedInfo(" + Bind Pose Translation: x=%f y=%f z=%f", jointChunk.m_bindPosePos.mX, jointChunk.m_bindPosePos.mY, jointChunk.m_bindPosePos.mZ); + MCore::LogDetailedInfo(" + Static Scale: x=%f y=%f z=%f", jointChunk.m_staticScale.m_x, jointChunk.m_staticScale.m_y, jointChunk.m_staticScale.m_z); + MCore::LogDetailedInfo(" + Bind Pose Translation: x=%f y=%f z=%f", jointChunk.m_bindPosePos.m_x, jointChunk.m_bindPosePos.m_y, jointChunk.m_bindPosePos.m_z); MCore::LogDetailedInfo(" + Bind Pose Rotation: x=%f y=%f z=%f w=%f", static_cast(uncompressedBindPoseRot.GetX()), static_cast(uncompressedBindPoseRot.GetY()), static_cast(uncompressedBindPoseRot.GetZ()), static_cast(uncompressedBindPoseRot.GetW())); - MCore::LogDetailedInfo(" + Bind Pose Scale: x=%f y=%f z=%f", jointChunk.m_bindPoseScale.mX, jointChunk.m_bindPoseScale.mY, jointChunk.m_bindPoseScale.mZ); + MCore::LogDetailedInfo(" + Bind Pose Scale: x=%f y=%f z=%f", jointChunk.m_bindPoseScale.m_x, jointChunk.m_bindPoseScale.m_y, jointChunk.m_bindPoseScale.m_z); MCore::LogDetailedInfo(" + Position Animated: %s", (flags & File_UniformMotionData_Flags::IsPositionAnimated) ? "Yes" : "No"); MCore::LogDetailedInfo(" + Rotation Animated: %s", (flags & File_UniformMotionData_Flags::IsRotationAnimated) ? "Yes" : "No"); MCore::LogDetailedInfo(" + Scale Animated: %s", (flags & File_UniformMotionData_Flags::IsScaleAnimated) ? "Yes" : "No"); @@ -1122,12 +1122,12 @@ namespace EMotionFX } // Convert endian. - AZ::Vector3 staticPos(jointInfo.m_staticPos.mX, jointInfo.m_staticPos.mY, jointInfo.m_staticPos.mZ); - AZ::Vector3 staticScale(jointInfo.m_staticScale.mX, jointInfo.m_staticScale.mY, jointInfo.m_staticScale.mZ); - MCore::Compressed16BitQuaternion staticRot(jointInfo.m_staticRot.mX, jointInfo.m_staticRot.mY, jointInfo.m_staticRot.mZ, jointInfo.m_staticRot.mW); - AZ::Vector3 bindPosePos(jointInfo.m_bindPosePos.mX, jointInfo.m_bindPosePos.mY, jointInfo.m_bindPosePos.mZ); - AZ::Vector3 bindPoseScale(jointInfo.m_bindPoseScale.mX, jointInfo.m_bindPoseScale.mY, jointInfo.m_bindPoseScale.mZ); - MCore::Compressed16BitQuaternion bindPoseRot(jointInfo.m_bindPoseRot.mX, jointInfo.m_bindPoseRot.mY, jointInfo.m_bindPoseRot.mZ, jointInfo.m_bindPoseRot.mW); + AZ::Vector3 staticPos(jointInfo.m_staticPos.m_x, jointInfo.m_staticPos.m_y, jointInfo.m_staticPos.m_z); + AZ::Vector3 staticScale(jointInfo.m_staticScale.m_x, jointInfo.m_staticScale.m_y, jointInfo.m_staticScale.m_z); + MCore::Compressed16BitQuaternion staticRot(jointInfo.m_staticRot.m_x, jointInfo.m_staticRot.m_y, jointInfo.m_staticRot.m_z, jointInfo.m_staticRot.m_w); + AZ::Vector3 bindPosePos(jointInfo.m_bindPosePos.m_x, jointInfo.m_bindPosePos.m_y, jointInfo.m_bindPosePos.m_z); + AZ::Vector3 bindPoseScale(jointInfo.m_bindPoseScale.m_x, jointInfo.m_bindPoseScale.m_y, jointInfo.m_bindPoseScale.m_z); + MCore::Compressed16BitQuaternion bindPoseRot(jointInfo.m_bindPoseRot.m_x, jointInfo.m_bindPoseRot.m_y, jointInfo.m_bindPoseRot.m_z, jointInfo.m_bindPoseRot.m_w); MCore::Endian::ConvertVector3(&staticPos, sourceEndianType); MCore::Endian::Convert16BitQuaternion(&staticRot, sourceEndianType); MCore::Endian::ConvertVector3(&staticScale, sourceEndianType); @@ -1171,8 +1171,8 @@ namespace EMotionFX { return false; } - MCore::Endian::ConvertFloat(&fileVector.mX, sourceEndianType, /*numFloats=*/3); - motionData->SetJointPositionSample(i, s, AZ::Vector3(fileVector.mX, fileVector.mY, fileVector.mZ)); + MCore::Endian::ConvertFloat(&fileVector.m_x, sourceEndianType, /*numFloats=*/3); + motionData->SetJointPositionSample(i, s, AZ::Vector3(fileVector.m_x, fileVector.m_y, fileVector.m_z)); } } @@ -1188,7 +1188,7 @@ namespace EMotionFX { return false; } - MCore::Compressed16BitQuaternion compressedQuat(fileQuat.mX, fileQuat.mY, fileQuat.mZ, fileQuat.mW); + MCore::Compressed16BitQuaternion compressedQuat(fileQuat.m_x, fileQuat.m_y, fileQuat.m_z, fileQuat.m_w); MCore::Endian::Convert16BitQuaternion(&compressedQuat, sourceEndianType); motionData->SetJointRotationSample(i, s, compressedQuat.ToQuaternion().GetNormalized()); } @@ -1211,8 +1211,8 @@ namespace EMotionFX } EMFX_SCALECODE ( - MCore::Endian::ConvertFloat(&fileVector.mX, sourceEndianType, /*numFloats=*/3); - motionData->SetJointScaleSample(i, s, AZ::Vector3(fileVector.mX, fileVector.mY, fileVector.mZ)); + MCore::Endian::ConvertFloat(&fileVector.m_x, sourceEndianType, /*numFloats=*/3); + motionData->SetJointScaleSample(i, s, AZ::Vector3(fileVector.m_x, fileVector.m_y, fileVector.m_z)); ) } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MotionEventTrack.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MotionEventTrack.cpp index d288fa8b82..02b8c179b4 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MotionEventTrack.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MotionEventTrack.cpp @@ -25,12 +25,12 @@ namespace EMotionFX AZ_CLASS_ALLOCATOR_IMPL(MotionEventTrack, MotionEventAllocator, 0) MotionEventTrack::MotionEventTrack(Motion* motion) - : mMotion(motion) + : m_motion(motion) { } MotionEventTrack::MotionEventTrack(const char* name, Motion* motion) - : mMotion(motion) + : m_motion(motion) , m_name(name) { } @@ -47,7 +47,7 @@ namespace EMotionFX return *this; } m_events = other.m_events; - mMotion = other.mMotion; + m_motion = other.m_motion; m_name = other.m_name; return *this; } @@ -63,8 +63,8 @@ namespace EMotionFX serializeContext->Class() ->Version(2, VersionConverter) ->Field("name", &MotionEventTrack::m_name) - ->Field("enabled", &MotionEventTrack::mEnabled) - ->Field("deletable", &MotionEventTrack::mDeletable) + ->Field("enabled", &MotionEventTrack::m_enabled) + ->Field("deletable", &MotionEventTrack::m_deletable) ->Field("events", &MotionEventTrack::m_events) ; @@ -392,7 +392,7 @@ namespace EMotionFX { targetTrack->m_name = m_name; targetTrack->m_events = m_events; - targetTrack->mEnabled = mEnabled; + targetTrack->m_enabled = m_enabled; } // reserve memory for a given amount of events @@ -403,35 +403,35 @@ namespace EMotionFX void MotionEventTrack::SetIsEnabled(bool enabled) { - mEnabled = enabled; + m_enabled = enabled; } bool MotionEventTrack::GetIsEnabled() const { - return mEnabled; + return m_enabled; } bool MotionEventTrack::GetIsDeletable() const { - return mDeletable; + return m_deletable; } void MotionEventTrack::SetIsDeletable(bool isDeletable) { - mDeletable = isDeletable; + m_deletable = isDeletable; } Motion* MotionEventTrack::GetMotion() const { - return mMotion; + return m_motion; } void MotionEventTrack::SetMotion(Motion* newMotion) { - mMotion = newMotion; + m_motion = newMotion; } } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MotionEventTrack.h b/Gems/EMotionFX/Code/EMotionFX/Source/MotionEventTrack.h index 63f5abd0dd..fdf2e2bed7 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MotionEventTrack.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MotionEventTrack.h @@ -182,11 +182,11 @@ namespace EMotionFX AZStd::string m_name; /// The motion where this track belongs to. - Motion* mMotion; + Motion* m_motion; /// Is this track enabled? - bool mEnabled = true; - bool mDeletable = true; + bool m_enabled = true; + bool m_deletable = true; private: void ProcessEventsImpl(float startTime, float endTime, ActorInstance* actorInstance, const MotionInstance* motionInstance, const AZStd::function& processFunc); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MotionInstance.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MotionInstance.cpp index 3cefe9e513..696430271a 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MotionInstance.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MotionInstance.cpp @@ -74,30 +74,30 @@ namespace EMotionFX void MotionInstance::InitFromPlayBackInfo(const PlayBackInfo& info, bool resetCurrentPlaytime) { - SetFadeTime (info.mBlendOutTime); - SetMixMode (info.mMix); - SetMaxLoops (info.mNumLoops); - SetBlendMode (info.mBlendMode); - SetPlaySpeed (info.mPlaySpeed); - SetWeight (info.mTargetWeight, info.mBlendInTime); - SetPriorityLevel (info.mPriorityLevel); - SetPlayMode (info.mPlayMode); - SetRetargetingEnabled (info.mRetarget); - SetMotionExtractionEnabled(info.mMotionExtractionEnabled); - SetFreezeAtLastFrame (info.mFreezeAtLastFrame); - SetMotionEventsEnabled (info.mEnableMotionEvents); - SetMaxPlayTime (info.mMaxPlayTime); - SetEventWeightThreshold (info.mEventWeightThreshold); - SetBlendOutBeforeEnded (info.mBlendOutBeforeEnded); - SetCanOverwrite (info.mCanOverwrite); - SetDeleteOnZeroWeight (info.mDeleteOnZeroWeight); - SetMirrorMotion (info.mMirrorMotion); - SetFreezeAtTime (info.mFreezeAtTime); - SetIsInPlace (info.mInPlace); + SetFadeTime (info.m_blendOutTime); + SetMixMode (info.m_mix); + SetMaxLoops (info.m_numLoops); + SetBlendMode (info.m_blendMode); + SetPlaySpeed (info.m_playSpeed); + SetWeight (info.m_targetWeight, info.m_blendInTime); + SetPriorityLevel (info.m_priorityLevel); + SetPlayMode (info.m_playMode); + SetRetargetingEnabled (info.m_retarget); + SetMotionExtractionEnabled(info.m_motionExtractionEnabled); + SetFreezeAtLastFrame (info.m_freezeAtLastFrame); + SetMotionEventsEnabled (info.m_enableMotionEvents); + SetMaxPlayTime (info.m_maxPlayTime); + SetEventWeightThreshold (info.m_eventWeightThreshold); + SetBlendOutBeforeEnded (info.m_blendOutBeforeEnded); + SetCanOverwrite (info.m_canOverwrite); + SetDeleteOnZeroWeight (info.m_deleteOnZeroWeight); + SetMirrorMotion (info.m_mirrorMotion); + SetFreezeAtTime (info.m_freezeAtTime); + SetIsInPlace (info.m_inPlace); if (resetCurrentPlaytime) { - m_currentTime = (info.mPlayMode == PLAYMODE_BACKWARD) ? GetDuration() : 0.0f; + m_currentTime = (info.m_playMode == PLAYMODE_BACKWARD) ? GetDuration() : 0.0f; m_lastCurTime = m_currentTime; m_timeDiffToEnd = GetDuration(); } @@ -363,14 +363,14 @@ namespace EMotionFX const float currentTimePreUpdate = m_currentTime; UpdateTime(timePassed); - // If UpdateTime() did not advance mCurrentTime we can skip over ProcessEvents(). + // If UpdateTime() did not advance m_currentTime we can skip over ProcessEvents(). if (!AZ::IsClose(m_lastCurTime, m_currentTime, AZ::Constants::FloatEpsilon)) { // if we are blending towards the destination motion or layer. - // Do this after UpdateTime(timePassed) and use (mCurrentTime - mLastCurTime) + // Do this after UpdateTime(timePassed) and use (m_currentTime - m_lastCurTime) // as the elapsed time. This will function for Updates that use SetCurrentTime(time, false) // like Simple Motion component does with Track View. This will also work for motions that - // have mPlaySpeed that is not 1.0f. + // have m_playSpeed that is not 1.0f. if (GetIsBlending()) { const float duration = GetDuration(); @@ -854,9 +854,9 @@ namespace EMotionFX m_motion->CalcNodeTransform(this, &oldNodeTransform, actor, rootNode, oldTime, GetRetargetingEnabled()); // calculate the relative transforms - outTransform->mPosition = curNodeTransform.mPosition - oldNodeTransform.mPosition; - outTransform->mRotation = curNodeTransform.mRotation * oldNodeTransform.mRotation.GetConjugate(); - outTransform->mRotation.Normalize(); + outTransform->m_position = curNodeTransform.m_position - oldNodeTransform.m_position; + outTransform->m_rotation = curNodeTransform.m_rotation * oldNodeTransform.m_rotation.GetConjugate(); + outTransform->m_rotation.Normalize(); } // extract the motion delta transform @@ -916,8 +916,8 @@ namespace EMotionFX } // add the relative transform to the final values - trajectoryDelta.mPosition += relativeTrajectoryTransform.mPosition; - trajectoryDelta.mRotation = relativeTrajectoryTransform.mRotation * trajectoryDelta.mRotation; + trajectoryDelta.m_position += relativeTrajectoryTransform.m_position; + trajectoryDelta.m_rotation = relativeTrajectoryTransform.m_rotation * trajectoryDelta.m_rotation; } // calculate the relative movement @@ -925,8 +925,8 @@ namespace EMotionFX CalcRelativeTransform(motionExtractNode, curTimeValue, oldTimeValue, &relativeTrajectoryTransform); // add the relative transform to the final values - trajectoryDelta.mPosition += relativeTrajectoryTransform.mPosition; - trajectoryDelta.mRotation = relativeTrajectoryTransform.mRotation * trajectoryDelta.mRotation; + trajectoryDelta.m_position += relativeTrajectoryTransform.m_position; + trajectoryDelta.m_rotation = relativeTrajectoryTransform.m_rotation * trajectoryDelta.m_rotation; } // if not paused @@ -941,8 +941,8 @@ namespace EMotionFX // Calculate the difference between the first frame of the motion and the bind pose transform. TransformData* transformData = m_actorInstance->GetTransformData(); const Pose* bindPose = transformData->GetBindPose(); - AZ::Quaternion permBindPoseRotDiff = firstFrameTransform.mRotation * bindPose->GetLocalSpaceTransform(motionExtractionNodeIndex).mRotation.GetConjugate(); - AZ::Vector3 permBindPosePosDiff = bindPose->GetLocalSpaceTransform(motionExtractionNodeIndex).mPosition - firstFrameTransform.mPosition; + AZ::Quaternion permBindPoseRotDiff = firstFrameTransform.m_rotation * bindPose->GetLocalSpaceTransform(motionExtractionNodeIndex).m_rotation.GetConjugate(); + AZ::Vector3 permBindPosePosDiff = bindPose->GetLocalSpaceTransform(motionExtractionNodeIndex).m_position - firstFrameTransform.m_position; permBindPoseRotDiff.SetX(0.0f); permBindPoseRotDiff.SetY(0.0f); permBindPoseRotDiff.Normalize(); @@ -964,22 +964,22 @@ namespace EMotionFX // Capture rotation around the up axis only. trajectoryDelta.ApplyMotionExtractionFlags(m_motion->GetMotionExtractionFlags()); - AZ::Quaternion removeRot = currentFrameTransform.mRotation * firstFrameTransform.mRotation.GetConjugate(); + AZ::Quaternion removeRot = currentFrameTransform.m_rotation * firstFrameTransform.m_rotation.GetConjugate(); removeRot.SetX(0.0f); removeRot.SetY(0.0f); removeRot.Normalize(); - AZ::Quaternion rotation = removeRot.GetConjugate() * trajectoryDelta.mRotation * permBindPoseRotDiff.GetConjugate(); + AZ::Quaternion rotation = removeRot.GetConjugate() * trajectoryDelta.m_rotation * permBindPoseRotDiff.GetConjugate(); rotation.SetX(0.0f); rotation.SetY(0.0f); rotation.Normalize(); - AZ::Vector3 rotatedPos = rotation.TransformVector(trajectoryDelta.mPosition - bindPosePosDiff); + AZ::Vector3 rotatedPos = rotation.TransformVector(trajectoryDelta.m_position - bindPosePosDiff); // Calculate the real trajectory delta, taking into account the actor instance rotation. - outTrajectoryDelta.mPosition = m_actorInstance->GetLocalSpaceTransform().mRotation.TransformVector(rotatedPos); - outTrajectoryDelta.mRotation = trajectoryDelta.mRotation * bindPoseRotDiff; - outTrajectoryDelta.mRotation.Normalize(); + outTrajectoryDelta.m_position = m_actorInstance->GetLocalSpaceTransform().m_rotation.TransformVector(rotatedPos); + outTrajectoryDelta.m_rotation = trajectoryDelta.m_rotation * bindPoseRotDiff; + outTrajectoryDelta.m_rotation.Normalize(); if (m_boolFlags & MotionInstance::BOOL_ISFIRSTREPOSUPDATE) { diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MotionInstance.h b/Gems/EMotionFX/Code/EMotionFX/Source/MotionInstance.h index 59bd08d248..f41cf29c79 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MotionInstance.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MotionInstance.h @@ -120,7 +120,7 @@ namespace EMotionFX * Get the blend in time. * This is the time passed to the SetWeight(...) method where when the target weight is bigger than the current. * So only blend ins are counted and not blending out towards for example a weight of 0. - * When you never call SetWeight(...) yourself, this means that this will contain the value specificied to PlayBackInfo::mBlendInTime + * When you never call SetWeight(...) yourself, this means that this will contain the value specificied to PlayBackInfo::m_blendInTime * at the time of MotionSystem::PlayMotion(...). * @result The blend-in time, in seconds. */ @@ -803,7 +803,7 @@ namespace EMotionFX /** * This event gets triggered once the given motion instance gets added to the motion queue. - * This happens when you set the PlayBackInfo::mPlayNow member to false. In that case the MotionSystem::PlayMotion() method (OnPlayMotion) + * This happens when you set the PlayBackInfo::m_playNow member to false. In that case the MotionSystem::PlayMotion() method (OnPlayMotion) * will not directly start playing the motion (OnStartMotionInstance), but will add it to the motion queue instead. * The motion queue will then start playing the motion instance once it should. * @param info The playback information used to play this motion instance. @@ -885,17 +885,17 @@ namespace EMotionFX AZStd::vector m_eventHandlersByEventType; /**< The event handler to use to process events organized by EventTypes. */ float m_currentTime = 0.0f; /**< The current playtime. */ float m_timeDiffToEnd = 0.0f; /**< The time it takes until we reach the loop point in the motion. This also takes the playback direction into account (backward or forward play). */ - float m_freezeAtTime = -1.0f; /**< Freeze at a given time offset in seconds. The current play time would continue running though, and a blend out would be triggered, unlike the mFreezeAtLastFrame. Set to negative value to disable. Default=-1.*/ + float m_freezeAtTime = -1.0f; /**< Freeze at a given time offset in seconds. The current play time would continue running though, and a blend out would be triggered, unlike the m_freezeAtLastFrame. Set to negative value to disable. Default=-1.*/ float m_playSpeed = 1.0f; /**< The playspeed (1.0=normal speed). */ float m_lastCurTime = 0.0f; /**< The last current time, so the current time in the previous update. */ float m_totalPlayTime = 0.0f; /**< The current total play time that this motion is already playing. */ - float m_maxPlayTime = 0.0f; /**< The maximum play time of the motion. If the mTotalPlayTime is higher than this, the motion will be stopped, unless the max play time is zero or negative. */ + float m_maxPlayTime = 0.0f; /**< The maximum play time of the motion. If the m_totalPlayTime is higher than this, the motion will be stopped, unless the max play time is zero or negative. */ float m_eventWeightThreshold = 0.0f; /**< If the weight of the motion instance is below this value, the events won't get processed (default = 0.0f). */ float m_weight = 0.0f; /**< The current weight value, in range of [0..1]. */ float m_weightDelta = 0.0f; /**< The precalculated weight delta value, used during blending between weights. */ float m_targetWeight = 1.0f; /**< The target weight of the layer, when activating the motion. */ float m_blendInTime = 0.0f; /**< The blend in time. */ - float m_fadeTime = 0.3f; /**< Fadeout speed, when playing the animation once. So when it is done playing once, it will fade out in 'mFadeTime' seconds. */ + float m_fadeTime = 0.3f; /**< Fadeout speed, when playing the animation once. So when it is done playing once, it will fade out in 'm_fadeTime' seconds. */ AZ::u32 m_curLoops = 0; /**< Number of loops it currently has made (so the number of times the motion played already). */ AZ::u32 m_maxLoops = EMFX_LOOPFOREVER; /**< The maximum number of loops, before it has to stop. */ AZ::u32 m_lastLoops = 0; /**< The current number of loops in the previous update. */ diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MotionInstancePool.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MotionInstancePool.cpp index a10a4722eb..3a9d7b94b9 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MotionInstancePool.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MotionInstancePool.cpp @@ -20,9 +20,9 @@ namespace EMotionFX // constructor MotionInstancePool::SubPool::SubPool() - : mData(nullptr) - , mNumInstances(0) - , mNumInUse(0) + : m_data(nullptr) + , m_numInstances(0) + , m_numInUse(0) { } @@ -30,8 +30,8 @@ namespace EMotionFX // destructor MotionInstancePool::SubPool::~SubPool() { - MCore::Free(mData); - mData = nullptr; + MCore::Free(m_data); + m_data = nullptr; } @@ -42,36 +42,36 @@ namespace EMotionFX // constructor MotionInstancePool::Pool::Pool() { - mPoolType = POOLTYPE_DYNAMIC; - mData = nullptr; - mNumInstances = 0; - mNumUsedInstances = 0; - mSubPoolSize = 0; + m_poolType = POOLTYPE_DYNAMIC; + m_data = nullptr; + m_numInstances = 0; + m_numUsedInstances = 0; + m_subPoolSize = 0; } // destructor MotionInstancePool::Pool::~Pool() { - if (mPoolType == POOLTYPE_STATIC) + if (m_poolType == POOLTYPE_STATIC) { - MCore::Free(mData); - mData = nullptr; - mFreeList.clear(); + MCore::Free(m_data); + m_data = nullptr; + m_freeList.clear(); } else - if (mPoolType == POOLTYPE_DYNAMIC) + if (m_poolType == POOLTYPE_DYNAMIC) { - MCORE_ASSERT(mData == nullptr); + MCORE_ASSERT(m_data == nullptr); // delete all subpools - for (SubPool* subPool : mSubPools) + for (SubPool* subPool : m_subPools) { delete subPool; } - mSubPools.clear(); + m_subPools.clear(); - mFreeList.clear(); + m_freeList.clear(); } else { @@ -89,19 +89,19 @@ namespace EMotionFX MotionInstancePool::MotionInstancePool() : BaseObject() { - mPool = nullptr; + m_pool = nullptr; } // destructor MotionInstancePool::~MotionInstancePool() { - if (mPool->mNumUsedInstances > 0) + if (m_pool->m_numUsedInstances > 0) { - MCore::LogError("EMotionFX::~MotionInstancePool() - There are still %d unfreed motion instances, please use the Free function in the MotionInstancePool to free them, just like you would delete the object.", mPool->mNumUsedInstances); + MCore::LogError("EMotionFX::~MotionInstancePool() - There are still %d unfreed motion instances, please use the Free function in the MotionInstancePool to free them, just like you would delete the object.", m_pool->m_numUsedInstances); } - delete mPool; + delete m_pool; } @@ -115,7 +115,7 @@ namespace EMotionFX // init the motion instance pool void MotionInstancePool::Init(size_t numInitialInstances, EPoolType poolType, size_t subPoolSize) { - if (mPool) + if (m_pool) { MCore::LogError("EMotionFX::MotionInstancePool::Init() - We have already initialized the pool, ignoring new init call."); return; @@ -130,40 +130,40 @@ namespace EMotionFX } // create the subpool - mPool = new Pool(); - mPool->mNumInstances = numInitialInstances; - mPool->mPoolType = poolType; - mPool->mSubPoolSize = subPoolSize; + m_pool = new Pool(); + m_pool->m_numInstances = numInitialInstances; + m_pool->m_poolType = poolType; + m_pool->m_subPoolSize = subPoolSize; // if we have a static pool if (poolType == POOLTYPE_STATIC) { - mPool->mData = (uint8*)MCore::Allocate(numInitialInstances * sizeof(MotionInstance), EMFX_MEMCATEGORY_MOTIONINSTANCEPOOL);// alloc space - mPool->mFreeList.resize_no_construct(numInitialInstances); + m_pool->m_data = (uint8*)MCore::Allocate(numInitialInstances * sizeof(MotionInstance), EMFX_MEMCATEGORY_MOTIONINSTANCEPOOL);// alloc space + m_pool->m_freeList.resize_no_construct(numInitialInstances); for (size_t i = 0; i < numInitialInstances; ++i) { - void* memLocation = (void*)(mPool->mData + i * sizeof(MotionInstance)); - mPool->mFreeList[i].mAddress = memLocation; - mPool->mFreeList[i].mSubPool = nullptr; + void* memLocation = (void*)(m_pool->m_data + i * sizeof(MotionInstance)); + m_pool->m_freeList[i].m_address = memLocation; + m_pool->m_freeList[i].m_subPool = nullptr; } } else // if we have a dynamic pool if (poolType == POOLTYPE_DYNAMIC) { - mPool->mSubPools.reserve(32); + m_pool->m_subPools.reserve(32); SubPool* subPool = new SubPool(); - subPool->mData = (uint8*)MCore::Allocate(numInitialInstances * sizeof(MotionInstance), EMFX_MEMCATEGORY_MOTIONINSTANCEPOOL);// alloc space - subPool->mNumInstances = numInitialInstances; + subPool->m_data = (uint8*)MCore::Allocate(numInitialInstances * sizeof(MotionInstance), EMFX_MEMCATEGORY_MOTIONINSTANCEPOOL);// alloc space + subPool->m_numInstances = numInitialInstances; - mPool->mFreeList.resize_no_construct(numInitialInstances); + m_pool->m_freeList.resize_no_construct(numInitialInstances); for (size_t i = 0; i < numInitialInstances; ++i) { - mPool->mFreeList[i].mAddress = (void*)(subPool->mData + i * sizeof(MotionInstance)); - mPool->mFreeList[i].mSubPool = subPool; + m_pool->m_freeList[i].m_address = (void*)(subPool->m_data + i * sizeof(MotionInstance)); + m_pool->m_freeList[i].m_subPool = subPool; } - mPool->mSubPools.emplace_back(subPool); + m_pool->m_subPools.emplace_back(subPool); } else { @@ -176,69 +176,68 @@ namespace EMotionFX MotionInstance* MotionInstancePool::RequestNewWithoutLock(Motion* motion, ActorInstance* actorInstance) { // check if we already initialized - if (mPool == nullptr) + if (m_pool == nullptr) { MCore::LogWarning("EMotionFX::MotionInstancePool::RequestNew() - We have not yet initialized the pool, initializing it to a dynamic pool"); Init(); } // if there is are free items left - if (mPool->mFreeList.size() > 0) + if (m_pool->m_freeList.size() > 0) { - const MemLocation& location = mPool->mFreeList.back(); - MotionInstance* result = MotionInstance::Create(location.mAddress, motion, actorInstance); + const MemLocation& location = m_pool->m_freeList.back(); + MotionInstance* result = MotionInstance::Create(location.m_address, motion, actorInstance); - if (location.mSubPool) + if (location.m_subPool) { - location.mSubPool->mNumInUse++; + location.m_subPool->m_numInUse++; } - result->SetSubPool(location.mSubPool); + result->SetSubPool(location.m_subPool); - mPool->mFreeList.pop_back(); // remove it from the free list - mPool->mNumUsedInstances++; + m_pool->m_freeList.pop_back(); // remove it from the free list + m_pool->m_numUsedInstances++; return result; } // we have no more free attributes left - if (mPool->mPoolType == POOLTYPE_DYNAMIC) // we're dynamic, so we can just create new ones + if (m_pool->m_poolType == POOLTYPE_DYNAMIC) // we're dynamic, so we can just create new ones { - const size_t numInstances = mPool->mSubPoolSize; - mPool->mNumInstances += numInstances; + const size_t numInstances = m_pool->m_subPoolSize; + m_pool->m_numInstances += numInstances; SubPool* subPool = new SubPool(); - subPool->mData = (uint8*)MCore::Allocate(numInstances * sizeof(MotionInstance), EMFX_MEMCATEGORY_MOTIONINSTANCEPOOL);// alloc space - subPool->mNumInstances = numInstances; + subPool->m_data = (uint8*)MCore::Allocate(numInstances * sizeof(MotionInstance), EMFX_MEMCATEGORY_MOTIONINSTANCEPOOL);// alloc space + subPool->m_numInstances = numInstances; - const size_t startIndex = mPool->mFreeList.size(); - //mPool->mFreeList.Reserve( numInstances * 2 ); - if (mPool->mFreeList.capacity() < mPool->mNumInstances) + const size_t startIndex = m_pool->m_freeList.size(); + if (m_pool->m_freeList.capacity() < m_pool->m_numInstances) { - mPool->mFreeList.reserve(mPool->mNumInstances + mPool->mFreeList.capacity() / 2); + m_pool->m_freeList.reserve(m_pool->m_numInstances + m_pool->m_freeList.capacity() / 2); } - mPool->mFreeList.resize_no_construct(startIndex + numInstances); + m_pool->m_freeList.resize_no_construct(startIndex + numInstances); for (size_t i = 0; i < numInstances; ++i) { - void* memAddress = (void*)(subPool->mData + i * sizeof(MotionInstance)); - mPool->mFreeList[i + startIndex].mAddress = memAddress; - mPool->mFreeList[i + startIndex].mSubPool = subPool; + void* memAddress = (void*)(subPool->m_data + i * sizeof(MotionInstance)); + m_pool->m_freeList[i + startIndex].m_address = memAddress; + m_pool->m_freeList[i + startIndex].m_subPool = subPool; } - mPool->mSubPools.emplace_back(subPool); + m_pool->m_subPools.emplace_back(subPool); - const MemLocation& location = mPool->mFreeList.back(); - MotionInstance* result = MotionInstance::Create(location.mAddress, motion, actorInstance); - if (location.mSubPool) + const MemLocation& location = m_pool->m_freeList.back(); + MotionInstance* result = MotionInstance::Create(location.m_address, motion, actorInstance); + if (location.m_subPool) { - location.mSubPool->mNumInUse++; + location.m_subPool->m_numInUse++; } - result->SetSubPool(location.mSubPool); - mPool->mFreeList.pop_back(); // remove it from the free list - mPool->mNumUsedInstances++; + result->SetSubPool(location.m_subPool); + m_pool->m_freeList.pop_back(); // remove it from the free list + m_pool->m_numUsedInstances++; return result; } else // we are static and ran out of free attributes - if (mPool->mPoolType == POOLTYPE_STATIC) + if (m_pool->m_poolType == POOLTYPE_STATIC) { MCore::LogError("EMotionFX::MotionInstancePool::RequestNew() - There are no free motion instance in the static pool. Please increase the size of the pool or make it dynamic when calling Init."); MCORE_ASSERT(false); // we ran out of free motion instances @@ -260,7 +259,7 @@ namespace EMotionFX return; } - if (mPool == nullptr) + if (m_pool == nullptr) { MCore::LogWarning("EMotionFX::MotionInstancePool::Free() - The pool has not yet been initialized, please call Init first."); MCORE_ASSERT(false); @@ -270,13 +269,13 @@ namespace EMotionFX // add it back to the free list if (motionInstance->GetSubPool()) { - motionInstance->GetSubPool()->mNumInUse--; + motionInstance->GetSubPool()->m_numInUse--; } - mPool->mFreeList.emplace_back(); - mPool->mFreeList.back().mAddress = motionInstance; - mPool->mFreeList.back().mSubPool = motionInstance->GetSubPool(); - mPool->mNumUsedInstances--; + m_pool->m_freeList.emplace_back(); + m_pool->m_freeList.back().m_address = motionInstance; + m_pool->m_freeList.back().m_subPool = motionInstance->GetSubPool(); + m_pool->m_numUsedInstances--; motionInstance->DecreaseReferenceCount(); motionInstance->~MotionInstance(); // call the destructor @@ -289,27 +288,27 @@ namespace EMotionFX Lock(); MCore::LogInfo("EMotionFX::MotionInstancePool::LogMemoryStats() - Logging motion instance pool info"); - const size_t numFree = mPool->mFreeList.size(); - size_t numUsed = mPool->mNumUsedInstances; + const size_t numFree = m_pool->m_freeList.size(); + size_t numUsed = m_pool->m_numUsedInstances; size_t memUsage = 0; size_t usedMemUsage = 0; size_t totalMemUsage = 0; size_t totalUsedInstancesMemUsage = 0; - if (mPool->mPoolType == POOLTYPE_STATIC) + if (m_pool->m_poolType == POOLTYPE_STATIC) { - if (mPool->mNumInstances > 0) + if (m_pool->m_numInstances > 0) { - memUsage = mPool->mNumInstances * sizeof(MotionInstance); + memUsage = m_pool->m_numInstances * sizeof(MotionInstance); usedMemUsage = numUsed * sizeof(MotionInstance); } } else - if (mPool->mPoolType == POOLTYPE_DYNAMIC) + if (m_pool->m_poolType == POOLTYPE_DYNAMIC) { - if (mPool->mNumInstances > 0) + if (m_pool->m_numInstances > 0) { - memUsage = mPool->mNumInstances * sizeof(MotionInstance); + memUsage = m_pool->m_numInstances * sizeof(MotionInstance); usedMemUsage = numUsed * sizeof(MotionInstance); } } @@ -317,17 +316,17 @@ namespace EMotionFX totalUsedInstancesMemUsage += usedMemUsage; totalMemUsage += memUsage; totalMemUsage += sizeof(Pool); - totalMemUsage += mPool->mFreeList.capacity() * sizeof(decltype(mPool->mFreeList)::value_type); + totalMemUsage += m_pool->m_freeList.capacity() * sizeof(decltype(m_pool->m_freeList)::value_type); MCore::LogInfo("Pool:"); - if (mPool->mPoolType == POOLTYPE_DYNAMIC) + if (m_pool->m_poolType == POOLTYPE_DYNAMIC) { - MCore::LogInfo(" - Num SubPools: %d", mPool->mSubPools.size()); + MCore::LogInfo(" - Num SubPools: %d", m_pool->m_subPools.size()); } - MCore::LogInfo(" - Num Instances: %d", mPool->mNumInstances); + MCore::LogInfo(" - Num Instances: %d", m_pool->m_numInstances); MCore::LogInfo(" - Num Free: %d", numFree); MCore::LogInfo(" - Num Used: %d", numUsed); - MCore::LogInfo(" - PoolType: %s", (mPool->mPoolType == POOLTYPE_STATIC) ? "Static" : "Dynamic"); + MCore::LogInfo(" - PoolType: %s", (m_pool->m_poolType == POOLTYPE_STATIC) ? "Static" : "Dynamic"); MCore::LogInfo(" - Total Instances Mem: %d bytes (%d k)", memUsage, memUsage / 1000); MCore::LogInfo(" - Used Instances Mem: %d (%d k)", totalUsedInstancesMemUsage, totalUsedInstancesMemUsage / 1000); MCore::LogInfo(" - Total Mem Usage: %d (%d k)", totalMemUsage, totalMemUsage / 1000); @@ -358,14 +357,14 @@ namespace EMotionFX // wait with execution until we can set the lock void MotionInstancePool::Lock() { - mLock.Lock(); + m_lock.Lock(); } // release the lock again void MotionInstancePool::Unlock() { - mLock.Unlock(); + m_lock.Unlock(); } @@ -374,26 +373,26 @@ namespace EMotionFX { Lock(); - for (size_t i = 0; i < mPool->mSubPools.size(); ) + for (size_t i = 0; i < m_pool->m_subPools.size(); ) { - SubPool* subPool = mPool->mSubPools[i]; - if (subPool->mNumInUse == 0) + SubPool* subPool = m_pool->m_subPools[i]; + if (subPool->m_numInUse == 0) { // remove all free allocations - for (size_t a = 0; a < mPool->mFreeList.size(); ) + for (size_t a = 0; a < m_pool->m_freeList.size(); ) { - if (mPool->mFreeList[a].mSubPool == subPool) + if (m_pool->m_freeList[a].m_subPool == subPool) { - mPool->mFreeList.erase(AZStd::next(begin(mPool->mFreeList), a)); + m_pool->m_freeList.erase(AZStd::next(begin(m_pool->m_freeList), a)); } else { ++a; } } - mPool->mNumInstances -= subPool->mNumInstances; + m_pool->m_numInstances -= subPool->m_numInstances; - mPool->mSubPools.erase(AZStd::next(begin(mPool->mSubPools), i)); + m_pool->m_subPools.erase(AZStd::next(begin(m_pool->m_subPools), i)); delete subPool; } else @@ -402,11 +401,10 @@ namespace EMotionFX } } - mPool->mSubPools.shrink_to_fit(); - //mPool->mFreeList.Shrink(); - if ((mPool->mFreeList.capacity() - mPool->mFreeList.size()) > 4096) + m_pool->m_subPools.shrink_to_fit(); + if ((m_pool->m_freeList.capacity() - m_pool->m_freeList.size()) > 4096) { - mPool->mFreeList.reserve(mPool->mFreeList.size() + 4096); + m_pool->m_freeList.reserve(m_pool->m_freeList.size() + 4096); } Unlock(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MotionInstancePool.h b/Gems/EMotionFX/Code/EMotionFX/Source/MotionInstancePool.h index e257640e33..54837a1113 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MotionInstancePool.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MotionInstancePool.h @@ -68,15 +68,15 @@ namespace EMotionFX SubPool(); ~SubPool(); - uint8* mData; - size_t mNumInstances; - size_t mNumInUse; + uint8* m_data; + size_t m_numInstances; + size_t m_numInUse; }; struct EMFX_API MemLocation { - void* mAddress; - SubPool* mSubPool; + void* m_address; + SubPool* m_subPool; }; class EMFX_API Pool @@ -87,17 +87,17 @@ namespace EMotionFX Pool(); ~Pool(); - uint8* mData; - size_t mNumInstances; - size_t mNumUsedInstances; - size_t mSubPoolSize; - AZStd::vector mFreeList; - AZStd::vector mSubPools; - EPoolType mPoolType; + uint8* m_data; + size_t m_numInstances; + size_t m_numUsedInstances; + size_t m_subPoolSize; + AZStd::vector m_freeList; + AZStd::vector m_subPools; + EPoolType m_poolType; }; - Pool* mPool; - MCore::Mutex mLock; + Pool* m_pool; + MCore::Mutex m_lock; MotionInstancePool(); ~MotionInstancePool(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MotionLayerSystem.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MotionLayerSystem.cpp index b613ecc147..dddfd1eba8 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MotionLayerSystem.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MotionLayerSystem.cpp @@ -24,7 +24,7 @@ namespace EMotionFX : MotionSystem(actorInstance) { // set the motion based actor repositioning layer pass - mRepositioningPass = RepositioningLayerPass::Create(this); + m_repositioningPass = RepositioningLayerPass::Create(this); } @@ -34,7 +34,7 @@ namespace EMotionFX RemoveAllLayerPasses(); // get rid of the repositioning layer pass - mRepositioningPass->Destroy(); + m_repositioningPass->Destroy(); } @@ -49,7 +49,7 @@ namespace EMotionFX void MotionLayerSystem::RemoveAllLayerPasses(bool delFromMem) { // delete all layer passes - for (LayerPass* layerPass : mLayerPasses) + for (LayerPass* layerPass : m_layerPasses) { if (delFromMem) { @@ -57,7 +57,7 @@ namespace EMotionFX } } - mLayerPasses.clear(); + m_layerPasses.clear(); } @@ -65,23 +65,23 @@ namespace EMotionFX void MotionLayerSystem::StartMotion(MotionInstance* motion, PlayBackInfo* info) { // check if we have any motions playing already - const size_t numMotionInstances = mMotionInstances.size(); + const size_t numMotionInstances = m_motionInstances.size(); if (numMotionInstances > 0) { // find the right location in the motion instance array to insert this motion instance size_t insertPos = FindInsertPos(motion->GetPriorityLevel()); if (insertPos != InvalidIndex) { - mMotionInstances.emplace(AZStd::next(begin(mMotionInstances), insertPos), motion); + m_motionInstances.emplace(AZStd::next(begin(m_motionInstances), insertPos), motion); } else { - mMotionInstances.emplace_back(motion); + m_motionInstances.emplace_back(motion); } } else // no motions are playing, so just add it { - mMotionInstances.emplace_back(motion); + m_motionInstances.emplace_back(motion); } // trigger an event @@ -92,18 +92,18 @@ namespace EMotionFX motion->SetIsActive(true); // start the blend - motion->SetWeight(info->mTargetWeight, info->mBlendInTime); + motion->SetWeight(info->m_targetWeight, info->m_blendInTime); } // find the location where to insert a new motion with a given priority size_t MotionLayerSystem::FindInsertPos(size_t priorityLevel) const { - const auto* foundInsertPosition = AZStd::lower_bound(begin(mMotionInstances), end(mMotionInstances), priorityLevel, [](const MotionInstance* motionInstance, size_t level) + const auto* foundInsertPosition = AZStd::lower_bound(begin(m_motionInstances), end(m_motionInstances), priorityLevel, [](const MotionInstance* motionInstance, size_t level) { return motionInstance->GetPriorityLevel() < level; }); - return foundInsertPosition != end(mMotionInstances) ? AZStd::distance(begin(mMotionInstances), foundInsertPosition) : InvalidIndex; + return foundInsertPosition != end(m_motionInstances) ? AZStd::distance(begin(m_motionInstances), foundInsertPosition) : InvalidIndex; } @@ -117,22 +117,22 @@ namespace EMotionFX UpdateMotionTree(); // update the motion queue - mMotionQueue->Update(); + m_motionQueue->Update(); // process all layer passes - for (LayerPass* layerPass : mLayerPasses) + for (LayerPass* layerPass : m_layerPasses) { layerPass->Process(); } // process the repositioning as last - if (mRepositioningPass) + if (m_repositioningPass) { - mRepositioningPass->Process(); + m_repositioningPass->Process(); } // update the global transform now that we have an updated local transform of the actor instance itself (modified by motion extraction for example) - mActorInstance->UpdateWorldTransform(); + m_actorInstance->UpdateWorldTransform(); // if we need to update the node transforms because the character is visible if (updateNodes) @@ -145,9 +145,9 @@ namespace EMotionFX // update the motion tree void MotionLayerSystem::UpdateMotionTree() { - for (size_t i = 0; i < mMotionInstances.size(); ++i) + for (size_t i = 0; i < m_motionInstances.size(); ++i) { - MotionInstance* source = mMotionInstances[i]; + MotionInstance* source = m_motionInstances[i]; // if we aren't stopping this motion yet if (!source->GetIsStopping()) @@ -227,10 +227,10 @@ namespace EMotionFX if (source->GetCanOverwrite()) { // remove all motions that got overwritten by the current one - const size_t numToRemove = mMotionInstances.size() - (i + 1); + const size_t numToRemove = m_motionInstances.size() - (i + 1); for (size_t a = 0; a < numToRemove; ++a) { - RemoveMotionInstance(mMotionInstances[i + 1]); + RemoveMotionInstance(m_motionInstances[i + 1]); } } } @@ -245,7 +245,7 @@ namespace EMotionFX size_t numRemoved = 0; // start from the bottom up - for (auto iter = rbegin(mMotionInstances); iter != rend(mMotionInstances); ++iter) + for (auto iter = rbegin(m_motionInstances); iter != rend(m_motionInstances); ++iter) { MotionInstance* curInstance = *iter; @@ -267,11 +267,11 @@ namespace EMotionFX MotionInstance* MotionLayerSystem::FindFirstNonMixingMotionInstance() const { // if there aren't any motion instances, return nullptr - const auto foundMotionInstance = AZStd::find_if(begin(mMotionInstances), end(mMotionInstances), [](const MotionInstance* motionInstance) + const auto foundMotionInstance = AZStd::find_if(begin(m_motionInstances), end(m_motionInstances), [](const MotionInstance* motionInstance) { return !motionInstance->GetIsMixing(); }); - return foundMotionInstance != end(mMotionInstances) ? *foundMotionInstance : nullptr; + return foundMotionInstance != end(m_motionInstances) ? *foundMotionInstance : nullptr; } @@ -279,25 +279,25 @@ namespace EMotionFX void MotionLayerSystem::UpdateNodes() { // get the two pose buffers we need - const uint32 threadIndex = mActorInstance->GetThreadIndex(); + const uint32 threadIndex = m_actorInstance->GetThreadIndex(); AnimGraphPosePool& posePool = GetEMotionFX().GetThreadData(threadIndex)->GetPosePool(); - AnimGraphPose* tempAnimGraphPose = posePool.RequestPose(mActorInstance); + AnimGraphPose* tempAnimGraphPose = posePool.RequestPose(m_actorInstance); - const bool motionExtractionEnabled = mActorInstance->GetMotionExtractionEnabled(); + const bool motionExtractionEnabled = m_actorInstance->GetMotionExtractionEnabled(); Pose* tempActorPose = &tempAnimGraphPose->GetPose(); - const size_t numMotionInstances = mMotionInstances.size(); + const size_t numMotionInstances = m_motionInstances.size(); if (numMotionInstances > 0) { if (numMotionInstances > 1) { - TransformData* transformData = mActorInstance->GetTransformData(); + TransformData* transformData = m_actorInstance->GetTransformData(); Pose* finalPose = transformData->GetCurrentPose(); - finalPose->InitFromBindPose(mActorInstance); + finalPose->InitFromBindPose(m_actorInstance); // blend the layers - for (auto iter = rbegin(mMotionInstances); iter != rend(mMotionInstances); ++iter) + for (auto iter = rbegin(m_motionInstances); iter != rend(m_motionInstances); ++iter) { // skip inactive motion instances MotionInstance* instance = *iter; // the motion to be blended @@ -322,12 +322,12 @@ namespace EMotionFX else // there is just one motion playing { // skip inactive motion instances - MotionInstance* instance = mMotionInstances[0]; // the motion to be blended + MotionInstance* instance = m_motionInstances[0]; // the motion to be blended if (instance->GetIsActive() && instance->GetWeight() >= 0.9999f) { - TransformData* transformData = mActorInstance->GetTransformData(); + TransformData* transformData = m_actorInstance->GetTransformData(); Pose* finalPose = transformData->GetCurrentPose(); - finalPose->InitFromBindPose(mActorInstance); + finalPose->InitFromBindPose(m_actorInstance); instance->GetMotion()->Update(finalPose, finalPose, instance); // output the results of the single motion @@ -340,15 +340,15 @@ namespace EMotionFX else if (instance->GetIsActive() && instance->GetWeight() < 0.0001f) // almost not active { - TransformData* transformData = mActorInstance->GetTransformData(); - transformData->GetCurrentPose()->InitFromBindPose(mActorInstance); + TransformData* transformData = m_actorInstance->GetTransformData(); + transformData->GetCurrentPose()->InitFromBindPose(m_actorInstance); } else // semi active { - TransformData* transformData = mActorInstance->GetTransformData(); + TransformData* transformData = m_actorInstance->GetTransformData(); Pose* finalPose = transformData->GetCurrentPose(); - finalPose->InitFromBindPose(mActorInstance); + finalPose->InitFromBindPose(m_actorInstance); instance->GetMotion()->Update(finalPose, tempActorPose, instance); // output the results of the single motion // compensate for motion extraction @@ -365,8 +365,8 @@ namespace EMotionFX else // no motion playing { // update all node transforms - TransformData* transformData = mActorInstance->GetTransformData(); - transformData->GetCurrentPose()->InitFromBindPose(mActorInstance); + TransformData* transformData = m_actorInstance->GetTransformData(); + transformData->GetCurrentPose()->InitFromBindPose(m_actorInstance); } // free the poses back to the pool @@ -377,14 +377,14 @@ namespace EMotionFX // add a new pass void MotionLayerSystem::AddLayerPass(LayerPass* newPass) { - mLayerPasses.emplace_back(newPass); + m_layerPasses.emplace_back(newPass); } // get the number of layer passes size_t MotionLayerSystem::GetNumLayerPasses() const { - return mLayerPasses.size(); + return m_layerPasses.size(); } @@ -393,19 +393,19 @@ namespace EMotionFX { if (delFromMem) { - mLayerPasses[nr]->Destroy(); + m_layerPasses[nr]->Destroy(); } - mLayerPasses.erase(AZStd::next(begin(mLayerPasses), nr)); + m_layerPasses.erase(AZStd::next(begin(m_layerPasses), nr)); } // remove a given pass void MotionLayerSystem::RemoveLayerPass(LayerPass* pass, bool delFromMem) { - if (const auto it = AZStd::find(begin(mLayerPasses), end(mLayerPasses), pass); it != end(mLayerPasses)) + if (const auto it = AZStd::find(begin(m_layerPasses), end(m_layerPasses), pass); it != end(m_layerPasses)) { - mLayerPasses.erase(it); + m_layerPasses.erase(it); } if (delFromMem) @@ -418,7 +418,7 @@ namespace EMotionFX // insert a layer pass at a given position void MotionLayerSystem::InsertLayerPass(size_t insertPos, LayerPass* pass) { - mLayerPasses.emplace(AZStd::next(begin(mLayerPasses), insertPos), pass); + m_layerPasses.emplace(AZStd::next(begin(m_layerPasses), insertPos), pass); } @@ -439,17 +439,17 @@ namespace EMotionFX // remove the repositioning pass void MotionLayerSystem::RemoveRepositioningLayerPass() { - if (mRepositioningPass) + if (m_repositioningPass) { - mRepositioningPass->Destroy(); + m_repositioningPass->Destroy(); } - mRepositioningPass = nullptr; + m_repositioningPass = nullptr; } LayerPass* MotionLayerSystem::GetLayerPass(size_t index) const { - return mLayerPasses[index]; + return m_layerPasses[index]; } } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MotionLayerSystem.h b/Gems/EMotionFX/Code/EMotionFX/Source/MotionLayerSystem.h index be14780341..81119977dd 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MotionLayerSystem.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MotionLayerSystem.h @@ -179,8 +179,8 @@ namespace EMotionFX private: - AZStd::vector mLayerPasses; /**< The layer passes. */ - RepositioningLayerPass* mRepositioningPass; /**< The motion based actor repositioning layer pass. */ + AZStd::vector m_layerPasses; /**< The layer passes. */ + RepositioningLayerPass* m_repositioningPass; /**< The motion based actor repositioning layer pass. */ /** * Constructor. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MotionManager.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MotionManager.cpp index 8472e46796..5ed15fe896 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MotionManager.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MotionManager.cpp @@ -43,7 +43,7 @@ namespace EMotionFX : BaseObject() { // reserve space for 400 motions - mMotions.reserve(400); + m_motions.reserve(400); m_motionDataFactory = aznew MotionDataFactory(); } @@ -66,28 +66,28 @@ namespace EMotionFX if (delFromMemory) { // destroy all motion sets, they will internally call RemoveMotionSetWithoutLock(this) in their destructor - while (mMotionSets.size() > 0) + while (m_motionSets.size() > 0) { - delete mMotionSets[0]; + delete m_motionSets[0]; } // destroy all motions, they will internally call RemoveMotionWithoutLock(this) in their destructor - while (mMotions.size() > 0) + while (m_motions.size() > 0) { - mMotions[0]->Destroy(); + m_motions[0]->Destroy(); } } else { // wait with execution until we can set the lock - mSetLock.Lock(); - mMotionSets.clear(); - mSetLock.Unlock(); + m_setLock.Lock(); + m_motionSets.clear(); + m_setLock.Unlock(); // clear the arrays without destroying the memory of the entries - mLock.Lock(); - mMotions.clear(); - mLock.Unlock(); + m_lock.Lock(); + m_motions.clear(); + m_lock.Unlock(); } } @@ -95,81 +95,81 @@ namespace EMotionFX // find the motion and return a pointer, nullptr if the motion is not in Motion* MotionManager::FindMotionByName(const char* motionName, bool isTool) const { - const auto foundMotion = AZStd::find_if(begin(mMotions), end(mMotions), [motionName, isTool](const auto& motion) + const auto foundMotion = AZStd::find_if(begin(m_motions), end(m_motions), [motionName, isTool](const auto& motion) { return motion->GetIsOwnedByRuntime() != isTool && motion->GetNameString() == motionName; }); - return foundMotion != end(mMotions) ? *foundMotion : nullptr; + return foundMotion != end(m_motions) ? *foundMotion : nullptr; } // find the motion and return a pointer, nullptr if the motion is not in Motion* MotionManager::FindMotionByFileName(const char* fileName, bool isTool) const { - const auto foundMotion = AZStd::find_if(begin(mMotions), end(mMotions), [fileName, isTool](const auto& motion) + const auto foundMotion = AZStd::find_if(begin(m_motions), end(m_motions), [fileName, isTool](const auto& motion) { return motion->GetIsOwnedByRuntime() != isTool && AzFramework::StringFunc::Equal(motion->GetFileNameString().c_str(), fileName, false /* no case */); }); - return foundMotion != end(mMotions) ? *foundMotion : nullptr; + return foundMotion != end(m_motions) ? *foundMotion : nullptr; } // find the motion set by filename and return a pointer, nullptr if the motion set is not in yet MotionSet* MotionManager::FindMotionSetByFileName(const char* fileName, bool isTool) const { - const auto foundMotionSet = AZStd::find_if(begin(mMotionSets), end(mMotionSets), [fileName, isTool](const auto& motionSet) + const auto foundMotionSet = AZStd::find_if(begin(m_motionSets), end(m_motionSets), [fileName, isTool](const auto& motionSet) { return motionSet->GetIsOwnedByRuntime() != isTool && AzFramework::StringFunc::Equal(motionSet->GetFilename(), fileName); }); - return foundMotionSet != end(mMotionSets) ? *foundMotionSet : nullptr; + return foundMotionSet != end(m_motionSets) ? *foundMotionSet : nullptr; } // find the motion set and return a pointer, nullptr if the motion set has not been found MotionSet* MotionManager::FindMotionSetByName(const char* name, bool isOwnedByRuntime) const { - const auto foundMotionSet = AZStd::find_if(begin(mMotionSets), end(mMotionSets), [name, isOwnedByRuntime](const auto& motionSet) + const auto foundMotionSet = AZStd::find_if(begin(m_motionSets), end(m_motionSets), [name, isOwnedByRuntime](const auto& motionSet) { return motionSet->GetIsOwnedByRuntime() == isOwnedByRuntime && AzFramework::StringFunc::Equal(motionSet->GetName(), name); }); - return foundMotionSet != end(mMotionSets) ? *foundMotionSet : nullptr; + return foundMotionSet != end(m_motionSets) ? *foundMotionSet : nullptr; } // find the motion index for the given motion size_t MotionManager::FindMotionIndexByName(const char* motionName, bool isTool) const { - const auto foundMotion = AZStd::find_if(begin(mMotions), end(mMotions), [motionName, isTool](const auto& motion) + const auto foundMotion = AZStd::find_if(begin(m_motions), end(m_motions), [motionName, isTool](const auto& motion) { return motion->GetIsOwnedByRuntime() != isTool && motion->GetNameString() == motionName; }); - return foundMotion != end(mMotions) ? AZStd::distance(begin(mMotions), foundMotion) : InvalidIndex; + return foundMotion != end(m_motions) ? AZStd::distance(begin(m_motions), foundMotion) : InvalidIndex; } // find the motion set index for the given motion size_t MotionManager::FindMotionSetIndexByName(const char* name, bool isTool) const { - const auto foundMotionSet = AZStd::find_if(begin(mMotionSets), end(mMotionSets), [name, isTool](const MotionSet* motionSet) + const auto foundMotionSet = AZStd::find_if(begin(m_motionSets), end(m_motionSets), [name, isTool](const MotionSet* motionSet) { return motionSet->GetIsOwnedByRuntime() != isTool && AzFramework::StringFunc::Equal(motionSet->GetName(), name); }); - return foundMotionSet != end(mMotionSets) ? AZStd::distance(begin(mMotionSets), foundMotionSet) : InvalidIndex; + return foundMotionSet != end(m_motionSets) ? AZStd::distance(begin(m_motionSets), foundMotionSet) : InvalidIndex; } // find the motion index for the given motion size_t MotionManager::FindMotionIndexByID(uint32 id) const { - const auto foundMotion = AZStd::find_if(begin(mMotions), end(mMotions), [id](const Motion* motion) + const auto foundMotion = AZStd::find_if(begin(m_motions), end(m_motions), [id](const Motion* motion) { return motion->GetID() == id; }); - return foundMotion != end(mMotions) ? AZStd::distance(begin(mMotions), foundMotion) : InvalidIndex; + return foundMotion != end(m_motions) ? AZStd::distance(begin(m_motions), foundMotion) : InvalidIndex; // get the number of motions and iterate through them } @@ -177,55 +177,55 @@ namespace EMotionFX // find the motion set index size_t MotionManager::FindMotionSetIndexByID(uint32 id) const { - const auto foundMotionSet = AZStd::find_if(begin(mMotionSets), end(mMotionSets), [id](const MotionSet* motionSet) + const auto foundMotionSet = AZStd::find_if(begin(m_motionSets), end(m_motionSets), [id](const MotionSet* motionSet) { return motionSet->GetID() == id; }); - return foundMotionSet != end(mMotionSets) ? AZStd::distance(begin(mMotionSets), foundMotionSet) : InvalidIndex; + return foundMotionSet != end(m_motionSets) ? AZStd::distance(begin(m_motionSets), foundMotionSet) : InvalidIndex; } // find the motion and return a pointer, nullptr if the motion is not in Motion* MotionManager::FindMotionByID(uint32 id) const { - const auto foundMotion = AZStd::find_if(begin(mMotions), end(mMotions), [id](const Motion* motion) + const auto foundMotion = AZStd::find_if(begin(m_motions), end(m_motions), [id](const Motion* motion) { return motion->GetID() == id; }); - return foundMotion != end(mMotions) ? *foundMotion : nullptr; + return foundMotion != end(m_motions) ? *foundMotion : nullptr; } // find the motion set with the given and return it, nullptr if the motion set won't be found MotionSet* MotionManager::FindMotionSetByID(uint32 id) const { - const auto foundMotionSet = AZStd::find_if(begin(mMotionSets), end(mMotionSets), [id](const MotionSet* motionSet) + const auto foundMotionSet = AZStd::find_if(begin(m_motionSets), end(m_motionSets), [id](const MotionSet* motionSet) { return motionSet->GetID() == id; }); - return foundMotionSet != end(mMotionSets) ? *foundMotionSet : nullptr; + return foundMotionSet != end(m_motionSets) ? *foundMotionSet : nullptr; } // find the motion set index and return it size_t MotionManager::FindMotionSetIndex(MotionSet* motionSet) const { - const auto foundMotionSet = AZStd::find_if(begin(mMotionSets), end(mMotionSets), [motionSet](const MotionSet* ms) + const auto foundMotionSet = AZStd::find_if(begin(m_motionSets), end(m_motionSets), [motionSet](const MotionSet* ms) { return ms == motionSet; }); - return foundMotionSet != end(mMotionSets) ? AZStd::distance(begin(mMotionSets), foundMotionSet) : InvalidIndex; + return foundMotionSet != end(m_motionSets) ? AZStd::distance(begin(m_motionSets), foundMotionSet) : InvalidIndex; } // find the motion index for the given motion size_t MotionManager::FindMotionIndex(Motion* motion) const { - const auto foundMotion = AZStd::find_if(begin(mMotions), end(mMotions), [motion](const Motion* m) + const auto foundMotion = AZStd::find_if(begin(m_motions), end(m_motions), [motion](const Motion* m) { return m == motion; }); - return foundMotion != end(mMotions) ? AZStd::distance(begin(mMotions), foundMotion) : InvalidIndex; + return foundMotion != end(m_motions) ? AZStd::distance(begin(m_motions), foundMotion) : InvalidIndex; } @@ -233,16 +233,16 @@ namespace EMotionFX void MotionManager::AddMotion(Motion* motion) { // wait with execution until we can set the lock - mLock.Lock(); - mMotions.emplace_back(motion); - mLock.Unlock(); + m_lock.Lock(); + m_motions.emplace_back(motion); + m_lock.Unlock(); } // find the motion based on the name and remove it bool MotionManager::RemoveMotionByName(const char* motionName, bool delFromMemory, bool isTool) { - MCore::LockGuard lock(mLock); + MCore::LockGuard lock(m_lock); return RemoveMotionWithoutLock(FindMotionIndexByName(motionName, isTool), delFromMemory); } @@ -250,7 +250,7 @@ namespace EMotionFX // find the motion set based on the name and remove it bool MotionManager::RemoveMotionSetByName(const char* motionName, bool delFromMemory, bool isTool) { - MCore::LockGuard lock(mSetLock); + MCore::LockGuard lock(m_setLock); return RemoveMotionSetWithoutLock(FindMotionSetIndexByName(motionName, isTool), delFromMemory); } @@ -258,7 +258,7 @@ namespace EMotionFX // find the motion based on the id and remove it bool MotionManager::RemoveMotionByID(uint32 id, bool delFromMemory) { - MCore::LockGuard lock(mLock); + MCore::LockGuard lock(m_lock); return RemoveMotionWithoutLock(FindMotionIndexByID(id), delFromMemory); } @@ -266,7 +266,7 @@ namespace EMotionFX // find the motion set based on the id and remove it bool MotionManager::RemoveMotionSetByID(uint32 id, bool delFromMemory) { - MCore::LockGuard lock(mSetLock); + MCore::LockGuard lock(m_setLock); return RemoveMotionSetWithoutLock(FindMotionSetIndexByID(id), delFromMemory); } @@ -274,18 +274,18 @@ namespace EMotionFX // find the index by filename size_t MotionManager::FindMotionIndexByFileName(const char* fileName, bool isTool) const { - const auto foundMotion = AZStd::find_if(begin(mMotions), end(mMotions), [fileName, isTool](const Motion* motion) + const auto foundMotion = AZStd::find_if(begin(m_motions), end(m_motions), [fileName, isTool](const Motion* motion) { return motion->GetIsOwnedByRuntime() != isTool && motion->GetFileNameString() == fileName; }); - return foundMotion != end(mMotions) ? AZStd::distance(begin(mMotions), foundMotion) : InvalidIndex; + return foundMotion != end(m_motions) ? AZStd::distance(begin(m_motions), foundMotion) : InvalidIndex; } // remove the motion by a given filename bool MotionManager::RemoveMotionByFileName(const char* fileName, bool delFromMemory, bool isTool) { - MCore::LockGuard lock(mLock); + MCore::LockGuard lock(m_lock); return RemoveMotionWithoutLock(FindMotionIndexByFileName(fileName, isTool), delFromMemory); } @@ -314,7 +314,7 @@ namespace EMotionFX if (azrtti_istypeof(node)) { AnimGraphMotionNode::UniqueData* motionNodeData = static_cast(uniqueData); - const MotionInstance* motionInstance = motionNodeData->mMotionInstance; + const MotionInstance* motionInstance = motionNodeData->m_motionInstance; if (motionInstance && motionInstance->GetMotion() == motion) { motionNodeData->Reset(); @@ -340,7 +340,7 @@ namespace EMotionFX return false; } - Motion* motion = mMotions[index]; + Motion* motion = m_motions[index]; // stop all motion instances of the motion to delete const size_t numActorInstances = GetActorManager().GetNumActorInstances(); @@ -370,7 +370,7 @@ namespace EMotionFX } // Reset all motion entries in the motion sets of the current motion. - for (const MotionSet* motionSet : mMotionSets) + for (const MotionSet* motionSet : m_motionSets) { const EMotionFX::MotionSet::MotionEntries& motionEntries = motionSet->GetMotionEntries(); for (const auto& item : motionEntries) @@ -398,11 +398,11 @@ namespace EMotionFX // which unregisters the motion from the motion manager motion->SetAutoUnregister(false); motion->Destroy(); - mMotions.erase(AZStd::next(begin(mMotions), index)); // only remove the motion from the motion manager without destroying its memory + m_motions.erase(AZStd::next(begin(m_motions), index)); // only remove the motion from the motion manager without destroying its memory } else { - mMotions.erase(AZStd::next(begin(mMotions), index)); // only remove the motion from the motion manager without destroying its memory + m_motions.erase(AZStd::next(begin(m_motions), index)); // only remove the motion from the motion manager without destroying its memory } return true; @@ -412,8 +412,8 @@ namespace EMotionFX // add a new motion set void MotionManager::AddMotionSet(MotionSet* motionSet) { - MCore::LockGuard lock(mLock); - mMotionSets.emplace_back(motionSet); + MCore::LockGuard lock(m_lock); + m_motionSets.emplace_back(motionSet); } @@ -425,7 +425,7 @@ namespace EMotionFX return false; } - MotionSet* motionSet = mMotionSets[index]; + MotionSet* motionSet = m_motionSets[index]; // remove from the parent MotionSet* parentSet = motionSet->GetParentSet(); @@ -451,7 +451,7 @@ namespace EMotionFX delete motionSet; } - mMotionSets.erase(AZStd::next(begin(mMotionSets), index)); + m_motionSets.erase(AZStd::next(begin(m_motionSets), index)); return true; } @@ -460,7 +460,7 @@ namespace EMotionFX // remove the motion from the motion manager bool MotionManager::RemoveMotion(Motion* motion, bool delFromMemory) { - MCore::LockGuard lock(mLock); + MCore::LockGuard lock(m_lock); return RemoveMotionWithoutLock(FindMotionIndex(motion), delFromMemory); } @@ -468,7 +468,7 @@ namespace EMotionFX // remove the motion set from the motion manager bool MotionManager::RemoveMotionSet(MotionSet* motionSet, bool delFromMemory) { - MCore::LockGuard lock(mSetLock); + MCore::LockGuard lock(m_setLock); return RemoveMotionSetWithoutLock(FindMotionSetIndex(motionSet), delFromMemory); } @@ -479,7 +479,7 @@ namespace EMotionFX size_t result = 0; // get the number of motion sets and iterate through them - for (const MotionSet* motionSet : mMotionSets) + for (const MotionSet* motionSet : m_motionSets) { // sum up the root motion sets if (motionSet->GetParentSet() == nullptr) @@ -495,25 +495,25 @@ namespace EMotionFX // find the given root motion set MotionSet* MotionManager::FindRootMotionSet(size_t index) { - auto foundRootMotionSet = AZStd::find_if(begin(mMotionSets), end(mMotionSets), [iter = index](const MotionSet* motionSet) mutable + auto foundRootMotionSet = AZStd::find_if(begin(m_motionSets), end(m_motionSets), [iter = index](const MotionSet* motionSet) mutable { return motionSet->GetParentSet() == nullptr && iter-- == 0; }); - return foundRootMotionSet != end(mMotionSets) ? *foundRootMotionSet : nullptr; + return foundRootMotionSet != end(m_motionSets) ? *foundRootMotionSet : nullptr; } // wait with execution until we can set the lock void MotionManager::Lock() { - mLock.Lock(); + m_lock.Lock(); } // release the lock again void MotionManager::Unlock() { - mLock.Unlock(); + m_lock.Unlock(); } MotionDataFactory& MotionManager::GetMotionDataFactory() diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MotionManager.h b/Gems/EMotionFX/Code/EMotionFX/Source/MotionManager.h index 2aad2f72d9..24c8c784f3 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MotionManager.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MotionManager.h @@ -44,13 +44,13 @@ namespace EMotionFX * @param[in] index The index of the motion. The index must be in range [0, GetNumMotions()-1]. * @return A pointer to the given motion set. */ - MCORE_INLINE Motion* GetMotion(size_t index) const { return mMotions[index]; } + MCORE_INLINE Motion* GetMotion(size_t index) const { return m_motions[index]; } /** * Get the number of motions in the motion manager. * @return The number of registered motions. */ - MCORE_INLINE size_t GetNumMotions() const { return mMotions.size(); } + MCORE_INLINE size_t GetNumMotions() const { return m_motions.size(); } /** * Remove the motion with the given name from the motion manager. @@ -154,13 +154,13 @@ namespace EMotionFX * @param[in] index The index of the motion set. The index must be in range [0, GetNumMotionSets()-1]. * @return A pointer to the given motion set. */ - MCORE_INLINE MotionSet* GetMotionSet(size_t index) const { return mMotionSets[index]; } + MCORE_INLINE MotionSet* GetMotionSet(size_t index) const { return m_motionSets[index]; } /** * Get the number of motion sets in the motion manager. * @return The number of registered motion sets. */ - MCORE_INLINE size_t GetNumMotionSets() const { return mMotionSets.size(); } + MCORE_INLINE size_t GetNumMotionSets() const { return m_motionSets.size(); } /** * Calculate the number of root motion sets. @@ -233,10 +233,10 @@ namespace EMotionFX const MotionDataFactory& GetMotionDataFactory() const; private: - AZStd::vector mMotions; /**< The array of motions. */ - AZStd::vector mMotionSets; /**< The array of motion sets. */ - MCore::Mutex mLock; /**< Motion lock. */ - MCore::Mutex mSetLock; /**< The motion set multithread lock. */ + AZStd::vector m_motions; /**< The array of motions. */ + AZStd::vector m_motionSets; /**< The array of motion sets. */ + MCore::Mutex m_lock; /**< Motion lock. */ + MCore::Mutex m_setLock; /**< The motion set multithread lock. */ MotionDataFactory* m_motionDataFactory = nullptr; /**< The motion data factory. */ //void RecursiveResetMotionNodes(AnimGraphNode* animGraphNode, Motion* motion); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MotionQueue.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MotionQueue.cpp index 10b52b1f8b..e523572689 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MotionQueue.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MotionQueue.cpp @@ -26,8 +26,8 @@ namespace EMotionFX { MCORE_ASSERT(actorInstance && motionSystem); - mActorInstance = actorInstance; - mMotionSystem = motionSystem; + m_actorInstance = actorInstance; + m_motionSystem = motionSystem; } @@ -48,12 +48,12 @@ namespace EMotionFX // remove a given entry from the queue void MotionQueue::RemoveEntry(size_t nr) { - if (mMotionSystem->RemoveMotionInstance(mEntries[nr].mMotion) == false) + if (m_motionSystem->RemoveMotionInstance(m_entries[nr].m_motion) == false) { - GetMotionInstancePool().Free(mEntries[nr].mMotion); + GetMotionInstancePool().Free(m_entries[nr].m_motion); } - mEntries.erase(AZStd::next(begin(mEntries), nr)); + m_entries.erase(AZStd::next(begin(m_entries), nr)); } @@ -70,7 +70,7 @@ namespace EMotionFX } // if there is only one entry in the queue, we can start playing it immediately - if (mMotionSystem->GetIsPlaying() == false) + if (m_motionSystem->GetIsPlaying() == false) { // get the entry from the queue to play next MotionQueue::QueueEntry queueEntry = GetFirstEntry(); @@ -79,7 +79,7 @@ namespace EMotionFX RemoveFirstEntry(); // start the motion on the queue - mMotionSystem->StartMotion(queueEntry.mMotion, &queueEntry.mPlayInfo); + m_motionSystem->StartMotion(queueEntry.m_motion, &queueEntry.m_playInfo); // get out of this method, nothing more to do :) return; @@ -109,7 +109,7 @@ namespace EMotionFX RemoveFirstEntry(); // start the motion - mMotionSystem->StartMotion(queueEntry.mMotion, &queueEntry.mPlayInfo); + m_motionSystem->StartMotion(queueEntry.m_motion, &queueEntry.m_playInfo); } @@ -117,7 +117,7 @@ namespace EMotionFX bool MotionQueue::ShouldPlayNextMotion() { // find the first non mixing motion - MotionInstance* motionInst = mMotionSystem->FindFirstNonMixingMotionInstance(); + MotionInstance* motionInst = m_motionSystem->FindFirstNonMixingMotionInstance(); // if there isn't a non mixing motion if (motionInst == nullptr) @@ -126,7 +126,7 @@ namespace EMotionFX } // the total amount of blending time - const float timeToRemoveFromMaxTime = GetFirstEntry().mPlayInfo.mBlendInTime + motionInst->GetFadeTime(); + const float timeToRemoveFromMaxTime = GetFirstEntry().m_playInfo.m_blendInTime + motionInst->GetFadeTime(); // if the motion has ended or is stopping, then we should start the next motion if (motionInst->GetIsStopping() || motionInst->GetHasEnded()) @@ -167,7 +167,7 @@ namespace EMotionFX void MotionQueue::ClearAllEntries() { - while (mEntries.size()) + while (m_entries.size()) { RemoveEntry(0); } @@ -176,31 +176,31 @@ namespace EMotionFX void MotionQueue::AddEntry(const MotionQueue::QueueEntry& motion) { - mEntries.emplace_back(motion); + m_entries.emplace_back(motion); } size_t MotionQueue::GetNumEntries() const { - return mEntries.size(); + return m_entries.size(); } MotionQueue::QueueEntry& MotionQueue::GetFirstEntry() { - MCORE_ASSERT(mEntries.size() > 0); - return mEntries[0]; + MCORE_ASSERT(m_entries.size() > 0); + return m_entries[0]; } void MotionQueue::RemoveFirstEntry() { - mEntries.erase(mEntries.begin()); + m_entries.erase(m_entries.begin()); } MotionQueue::QueueEntry& MotionQueue::GetEntry(size_t nr) { - return mEntries[nr]; + return m_entries[nr]; } } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MotionQueue.h b/Gems/EMotionFX/Code/EMotionFX/Source/MotionQueue.h index aa30ccab46..8584d43be2 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MotionQueue.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MotionQueue.h @@ -43,17 +43,17 @@ namespace EMotionFX class QueueEntry { public: - MotionInstance* mMotion; /**< The motion instance we want to play. */ - PlayBackInfo mPlayInfo; /**< The motion playback settings. */ + MotionInstance* m_motion; /**< The motion instance we want to play. */ + PlayBackInfo m_playInfo; /**< The motion playback settings. */ /// The default constructor QueueEntry() - : mMotion(nullptr) {} + : m_motion(nullptr) {} /// The extended constructor. QueueEntry(MotionInstance* motion, class PlayBackInfo* info) - : mMotion(motion) - , mPlayInfo(*info) {} + : m_motion(motion) + , m_playInfo(*info) {} }; /** @@ -133,9 +133,9 @@ namespace EMotionFX void PlayNextMotion(); private: - AZStd::vector mEntries; /**< The motion queue entries. */ - MotionSystem* mMotionSystem; /**< Motion system access pointer. */ - ActorInstance* mActorInstance; /**< The actor instance where this queue works on. */ + AZStd::vector m_entries; /**< The motion queue entries. */ + MotionSystem* m_motionSystem; /**< Motion system access pointer. */ + ActorInstance* m_actorInstance; /**< The actor instance where this queue works on. */ /** * Constructor. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MotionSystem.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MotionSystem.cpp index 7619187d23..a6ddb776c2 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MotionSystem.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MotionSystem.cpp @@ -29,11 +29,11 @@ namespace EMotionFX { MCORE_ASSERT(actorInstance); - mActorInstance = actorInstance; - mMotionQueue = nullptr; + m_actorInstance = actorInstance; + m_motionQueue = nullptr; // create the motion queue - mMotionQueue = MotionQueue::Create(actorInstance, this); + m_motionQueue = MotionQueue::Create(actorInstance, this); GetEventManager().OnCreateMotionSystem(this); } @@ -45,17 +45,16 @@ namespace EMotionFX GetEventManager().OnDeleteMotionSystem(this); // delete the motion infos - while (!mMotionInstances.empty()) + while (!m_motionInstances.empty()) { - //delete mMotionInstances.GetLast(); - GetMotionInstancePool().Free(mMotionInstances.back()); - mMotionInstances.pop_back(); + GetMotionInstancePool().Free(m_motionInstances.back()); + m_motionInstances.pop_back(); } // get rid of the motion queue - if (mMotionQueue) + if (m_motionQueue) { - mMotionQueue->Destroy(); + m_motionQueue->Destroy(); } } @@ -75,33 +74,21 @@ namespace EMotionFX info = &tempInfo; } - /* - // if we want to play a motion which will loop forever (so never ends) and we want to put it on the queue - if (info->mNumLoops==FOREVER && info->mPlayNow==false) - { - // if there is already a motion on the queue, this means the queue would end up in some kind of deadlock - // because it has to wait until the current motion is finished with playing, before it would start this motion - // and since that will never happen, the queue won't be processed anymore... - // so we may simply not allow this to happen. - if (mMotionQueue->GetNumEntries() > 0) - throw Exception("Cannot schedule this LOOPING motion to be played later, because there are already motions queued. If we would put this motion on the queue, all motions added later on to the queue will never be processed because this motion is a looping (so never ending) one.", MCORE_HERE); - }*/ - // trigger the OnPlayMotion event GetEventManager().OnPlayMotion(motion, info); // make sure we always mix when using additive blending - if (info->mBlendMode == BLENDMODE_ADDITIVE && info->mMix == false) + if (info->m_blendMode == BLENDMODE_ADDITIVE && info->m_mix == false) { MCORE_ASSERT(false); // this shouldn't happen actually, please make sure you always mix additive motions - info->mMix = true; + info->m_mix = true; } // create the motion instance and add the motion info the this actor MotionInstance* motionInst = CreateMotionInstance(motion, info); // if we want to play it immediately (so if we do NOT want to schedule it for later on) - if (info->mPlayNow) + if (info->m_playNow) { // start the motion for real StartMotion(motionInst, info); @@ -109,7 +96,7 @@ namespace EMotionFX else { // schedule the motion, by adding it to the back of the motion queue - mMotionQueue->AddEntry(MotionQueue::QueueEntry(motionInst, info)); + m_motionQueue->AddEntry(MotionQueue::QueueEntry(motionInst, info)); motionInst->Pause(); motionInst->SetIsActive(false); GetEventManager().OnQueueMotionInstance(motionInst, info); @@ -124,7 +111,7 @@ namespace EMotionFX MotionInstance* MotionSystem::CreateMotionInstance(Motion* motion, PlayBackInfo* info) { // create the motion instance - MotionInstance* motionInst = GetMotionInstancePool().RequestNew(motion, mActorInstance); + MotionInstance* motionInst = GetMotionInstancePool().RequestNew(motion, m_actorInstance); // initialize the motion instance from the playback info settings motionInst->InitFromPlayBackInfo(*info); @@ -138,9 +125,9 @@ namespace EMotionFX { // remove the motion instance from the actor const bool isSuccess = [this, instance] { - if(const auto it = AZStd::find(begin(mMotionInstances), end(mMotionInstances), instance); it != end(mMotionInstances)) + if(const auto it = AZStd::find(begin(m_motionInstances), end(m_motionInstances), instance); it != end(m_motionInstances)) { - mMotionInstances.erase(it); + m_motionInstances.erase(it); return true; } return false; @@ -163,7 +150,7 @@ namespace EMotionFX MCORE_UNUSED(updateNodes); // update the motion queue - mMotionQueue->Update(); + m_motionQueue->Update(); // update the motions UpdateMotionInstances(timePassed); @@ -173,7 +160,7 @@ namespace EMotionFX // stop all the motions that are currently playing void MotionSystem::StopAllMotions() { - for (MotionInstance* motionInstance : mMotionInstances) + for (MotionInstance* motionInstance : m_motionInstances) { motionInstance->Stop(); } @@ -183,7 +170,7 @@ namespace EMotionFX // stop all motion instances of a given motion void MotionSystem::StopAllMotions(Motion* motion) { - for (MotionInstance* motionInstance : mMotionInstances) + for (MotionInstance* motionInstance : m_motionInstances) { if (motionInstance->GetMotion()->GetID() == motion->GetID()) { @@ -196,14 +183,14 @@ namespace EMotionFX // remove the given motion void MotionSystem::RemoveMotion(size_t nr, bool deleteMem) { - MCORE_ASSERT(nr < mMotionInstances.size()); + MCORE_ASSERT(nr < m_motionInstances.size()); if (deleteMem) { - GetEMotionFX().GetMotionInstancePool()->Free(mMotionInstances[nr]); + GetEMotionFX().GetMotionInstancePool()->Free(m_motionInstances[nr]); } - mMotionInstances.erase(AZStd::next(begin(mMotionInstances), nr)); + m_motionInstances.erase(AZStd::next(begin(m_motionInstances), nr)); } @@ -212,15 +199,15 @@ namespace EMotionFX { MCORE_ASSERT(motion); - const auto it = AZStd::find(begin(mMotionInstances), end(mMotionInstances), motion); - MCORE_ASSERT(it != end(mMotionInstances)); + const auto it = AZStd::find(begin(m_motionInstances), end(m_motionInstances), motion); + MCORE_ASSERT(it != end(m_motionInstances)); - if (it == end(mMotionInstances)) + if (it == end(m_motionInstances)) { return; } - RemoveMotion(AZStd::distance(begin(mMotionInstances), it), delMem); + RemoveMotion(AZStd::distance(begin(m_motionInstances), it), delMem); } @@ -228,7 +215,7 @@ namespace EMotionFX void MotionSystem::UpdateMotionInstances(float timePassed) { // update all the motion infos - for (MotionInstance* motionInstance : mMotionInstances) + for (MotionInstance* motionInstance : m_motionInstances) { motionInstance->Update(timePassed); } @@ -238,7 +225,7 @@ namespace EMotionFX // check if the given motion instance still exists within the actor, so if it hasn't been deleted from memory yet bool MotionSystem::CheckIfIsValidMotionInstance(MotionInstance* instance) const { - return instance && AZStd::any_of(begin(mMotionInstances), end(mMotionInstances), [instance](const MotionInstance* motionInstance) + return instance && AZStd::any_of(begin(m_motionInstances), end(m_motionInstances), [instance](const MotionInstance* motionInstance) { return motionInstance->GetID() == instance->GetID(); }); @@ -248,7 +235,7 @@ namespace EMotionFX // check if there is a motion instance playing, which is an instance of a specified motion bool MotionSystem::CheckIfIsPlayingMotion(Motion* motion, bool ignorePausedMotions) const { - return motion && AZStd::any_of(begin(mMotionInstances), end(mMotionInstances), [motion, ignorePausedMotions](const MotionInstance* motionInstance) + return motion && AZStd::any_of(begin(m_motionInstances), end(m_motionInstances), [motion, ignorePausedMotions](const MotionInstance* motionInstance) { return !(ignorePausedMotions && motionInstance->GetIsPaused()) && motionInstance->GetMotion()->GetID() == motion->GetID(); @@ -259,27 +246,27 @@ namespace EMotionFX // return given motion instance MotionInstance* MotionSystem::GetMotionInstance(size_t nr) const { - MCORE_ASSERT(nr < mMotionInstances.size()); - return mMotionInstances[nr]; + MCORE_ASSERT(nr < m_motionInstances.size()); + return m_motionInstances[nr]; } // return number of motion instances size_t MotionSystem::GetNumMotionInstances() const { - return mMotionInstances.size(); + return m_motionInstances.size(); } // set a new motion queue void MotionSystem::SetMotionQueue(MotionQueue* motionQueue) { - if (mMotionQueue) + if (m_motionQueue) { - mMotionQueue->Destroy(); + m_motionQueue->Destroy(); } - mMotionQueue = motionQueue; + m_motionQueue = motionQueue; } @@ -291,7 +278,7 @@ namespace EMotionFX // copy entries from the given queue to the motion system's one for (size_t i = 0; i < motionQueue->GetNumEntries(); ++i) { - mMotionQueue->AddEntry(motionQueue->GetEntry(i)); + m_motionQueue->AddEntry(motionQueue->GetEntry(i)); } // get rid of the given motion queue @@ -302,25 +289,25 @@ namespace EMotionFX // return motion queue pointer MotionQueue* MotionSystem::GetMotionQueue() const { - return mMotionQueue; + return m_motionQueue; } // return the actor to which this motion system belongs to ActorInstance* MotionSystem::GetActorInstance() const { - return mActorInstance; + return m_actorInstance; } void MotionSystem::AddMotionInstance(MotionInstance* instance) { - mMotionInstances.emplace_back(instance); + m_motionInstances.emplace_back(instance); } bool MotionSystem::GetIsPlaying() const { - return !mMotionInstances.empty(); + return !m_motionInstances.empty(); } } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MotionSystem.h b/Gems/EMotionFX/Code/EMotionFX/Source/MotionSystem.h index 109cf5d41f..611ccd731a 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MotionSystem.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MotionSystem.h @@ -215,9 +215,9 @@ namespace EMotionFX protected: - AZStd::vector mMotionInstances; /**< The collection of motion instances. */ - ActorInstance* mActorInstance; /**< The actor instance where this motion system belongs to. */ - MotionQueue* mMotionQueue; /**< The motion queue. */ + AZStd::vector m_motionInstances; /**< The collection of motion instances. */ + ActorInstance* m_actorInstance; /**< The actor instance where this motion system belongs to. */ + MotionQueue* m_motionQueue; /**< The motion queue. */ /** * Constructor. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MultiThreadScheduler.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MultiThreadScheduler.cpp index 3cc4d027a8..6f07936fe7 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MultiThreadScheduler.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MultiThreadScheduler.cpp @@ -30,8 +30,8 @@ namespace EMotionFX MultiThreadScheduler::MultiThreadScheduler() : ActorUpdateScheduler() { - mCleanTimer = 0.0f; // time passed since last schedule cleanup, in seconds - mSteps.reserve(1000); + m_cleanTimer = 0.0f; // time passed since last schedule cleanup, in seconds + m_steps.reserve(1000); } @@ -52,7 +52,7 @@ namespace EMotionFX void MultiThreadScheduler::Clear() { Lock(); - mSteps.clear(); + m_steps.clear(); Unlock(); } @@ -78,10 +78,10 @@ namespace EMotionFX void MultiThreadScheduler::Print() { // for all steps - const size_t numSteps = mSteps.size(); + const size_t numSteps = m_steps.size(); for (size_t i = 0; i < numSteps; ++i) { - AZ_Printf("EMotionFX", "STEP %.3zu - %zu", i, mSteps[i].mActorInstances.size()); + AZ_Printf("EMotionFX", "STEP %.3zu - %zu", i, m_steps[i].m_actorInstances.size()); } AZ_Printf("EMotionFX", "---------"); @@ -91,15 +91,15 @@ namespace EMotionFX void MultiThreadScheduler::RemoveEmptySteps() { // process all steps - for (size_t s = 0; s < mSteps.size(); ) + for (size_t s = 0; s < m_steps.size(); ) { - if (!mSteps[s].mActorInstances.empty()) + if (!m_steps[s].m_actorInstances.empty()) { s++; } else { - mSteps.erase(AZStd::next(begin(mSteps), s)); + m_steps.erase(AZStd::next(begin(m_steps), s)); } } } @@ -108,21 +108,21 @@ namespace EMotionFX // execute the schedule void MultiThreadScheduler::Execute(float timePassedInSeconds) { - MCore::LockGuardRecursive guard(mMutex); + MCore::LockGuardRecursive guard(m_mutex); - size_t numSteps = mSteps.size(); + size_t numSteps = m_steps.size(); if (numSteps == 0) { return; } // check if we need to cleanup the schedule - mCleanTimer += timePassedInSeconds; - if (mCleanTimer >= 1.0f) + m_cleanTimer += timePassedInSeconds; + if (m_cleanTimer >= 1.0f) { - mCleanTimer = 0.0f; + m_cleanTimer = 0.0f; RemoveEmptySteps(); - numSteps = mSteps.size(); + numSteps = m_steps.size(); } //----------------------------------------------------------- @@ -142,20 +142,20 @@ namespace EMotionFX } // reset stats - mNumUpdated.SetValue(0); - mNumVisible.SetValue(0); - mNumSampled.SetValue(0); + m_numUpdated.SetValue(0); + m_numVisible.SetValue(0); + m_numSampled.SetValue(0); - for (const ScheduleStep& currentStep : mSteps) + for (const ScheduleStep& currentStep : m_steps) { - if (currentStep.mActorInstances.empty()) + if (currentStep.m_actorInstances.empty()) { continue; } // process the actor instances in the current step in parallel AZ::JobCompletion jobCompletion; - for (ActorInstance* actorInstance : currentStep.mActorInstances) + for (ActorInstance* actorInstance : currentStep.m_actorInstances) { if (actorInstance->GetIsEnabled() == false) { @@ -173,7 +173,7 @@ namespace EMotionFX const bool isVisible = actorInstance->GetIsVisible(); if (isVisible) { - mNumVisible.Increment(); + m_numVisible.Increment(); } // check if we want to sample motions @@ -186,7 +186,7 @@ namespace EMotionFX if (isVisible) { - mNumSampled.Increment(); + m_numSampled.Increment(); } } @@ -197,7 +197,7 @@ namespace EMotionFX job->SetDependent(&jobCompletion); job->Start(); - mNumUpdated.Increment(); + m_numUpdated.Increment(); } jobCompletion.StartAndWaitForCompletion(); @@ -209,11 +209,11 @@ namespace EMotionFX bool MultiThreadScheduler::FindNextFreeItem(ActorInstance* actorInstance, size_t startStep, size_t* outStepNr) { // try out all steps - const size_t numSteps = mSteps.size(); + const size_t numSteps = m_steps.size(); for (size_t s = startStep; s < numSteps; ++s) { // if there is a conflicting dependency, skip this step - if (CheckIfHasMatchingDependency(actorInstance, &mSteps[s])) + if (CheckIfHasMatchingDependency(actorInstance, &m_steps[s])) { continue; } @@ -229,11 +229,11 @@ namespace EMotionFX bool MultiThreadScheduler::HasActorInstanceInSteps(const ActorInstance* actorInstance) const { - const size_t numSteps = mSteps.size(); + const size_t numSteps = m_steps.size(); for (size_t s = 0; s < numSteps; ++s) { - const ScheduleStep& step = mSteps[s]; - if (AZStd::find(step.mActorInstances.begin(), step.mActorInstances.end(), actorInstance) != step.mActorInstances.end()) + const ScheduleStep& step = m_steps[s]; + if (AZStd::find(step.m_actorInstances.begin(), step.m_actorInstances.end(), actorInstance) != step.m_actorInstances.end()) { return true; } @@ -244,33 +244,33 @@ namespace EMotionFX void MultiThreadScheduler::RecursiveInsertActorInstance(ActorInstance* instance, size_t startStep) { - MCore::LockGuardRecursive guard(mMutex); + MCore::LockGuardRecursive guard(m_mutex); AZ_Assert(!HasActorInstanceInSteps(instance), "Expected the actor instance not being part of another step already."); // find the first free location that doesn't conflict size_t outStep = startStep; if (!FindNextFreeItem(instance, startStep, &outStep)) { - mSteps.reserve(10); - mSteps.emplace_back(); - outStep = mSteps.size() - 1; + m_steps.reserve(10); + m_steps.emplace_back(); + outStep = m_steps.size() - 1; } // pre-allocate step size - if (mSteps[outStep].mActorInstances.size() % 10 == 0) + if (m_steps[outStep].m_actorInstances.size() % 10 == 0) { - mSteps[outStep].mActorInstances.reserve(mSteps[outStep].mActorInstances.size() + 10); + m_steps[outStep].m_actorInstances.reserve(m_steps[outStep].m_actorInstances.size() + 10); } - if (mSteps[outStep].mDependencies.size() % 5 == 0) + if (m_steps[outStep].m_dependencies.size() % 5 == 0) { - mSteps[outStep].mDependencies.reserve(mSteps[outStep].mDependencies.size() + 5); + m_steps[outStep].m_dependencies.reserve(m_steps[outStep].m_dependencies.size() + 5); } // add the actor instance and its dependencies - mSteps[ outStep ].mActorInstances.reserve(GetEMotionFX().GetNumThreads()); - mSteps[ outStep ].mActorInstances.emplace_back(instance); - AddDependenciesToStep(instance, &mSteps[outStep]); + m_steps[ outStep ].m_actorInstances.reserve(GetEMotionFX().GetNumThreads()); + m_steps[ outStep ].m_actorInstances.emplace_back(instance); + AddDependenciesToStep(instance, &m_steps[outStep]); // recursively add all attachments too const size_t numAttachments = instance->GetNumAttachments(); @@ -288,27 +288,27 @@ namespace EMotionFX // remove the actor instance from the schedule (excluding attachments) size_t MultiThreadScheduler::RemoveActorInstance(ActorInstance* actorInstance, size_t startStep) { - MCore::LockGuardRecursive guard(mMutex); + MCore::LockGuardRecursive guard(m_mutex); // for all scheduler steps, starting from the specified start step number - const size_t numSteps = mSteps.size(); + const size_t numSteps = m_steps.size(); for (size_t s = startStep; s < numSteps; ++s) { - ScheduleStep& step = mSteps[s]; + ScheduleStep& step = m_steps[s]; // Remove all occurrences of the actor instance. - const size_t numActorInstancesPreRemove = step.mActorInstances.size(); - step.mActorInstances.erase(AZStd::remove(step.mActorInstances.begin(), step.mActorInstances.end(), actorInstance), step.mActorInstances.end()); + const size_t numActorInstancesPreRemove = step.m_actorInstances.size(); + step.m_actorInstances.erase(AZStd::remove(step.m_actorInstances.begin(), step.m_actorInstances.end(), actorInstance), step.m_actorInstances.end()); // try to see if there is anything to remove in this step // and if so, reconstruct the dependencies of this step - if (step.mActorInstances.size() < numActorInstancesPreRemove) + if (step.m_actorInstances.size() < numActorInstancesPreRemove) { // clear the dependencies (but don't delete the memory) - step.mDependencies.clear(); + step.m_dependencies.clear(); // calculate the new dependencies for this step - for (ActorInstance* stepActorInstance : step.mActorInstances) + for (ActorInstance* stepActorInstance : step.m_actorInstances) { AddDependenciesToStep(stepActorInstance, &step); } @@ -326,7 +326,7 @@ namespace EMotionFX // remove the actor instance (including all of its attachments) void MultiThreadScheduler::RecursiveRemoveActorInstance(ActorInstance* actorInstance, size_t startStep) { - MCore::LockGuardRecursive guard(mMutex); + MCore::LockGuardRecursive guard(m_mutex); // remove the actual actor instance const size_t step = RemoveActorInstance(actorInstance, startStep); @@ -346,12 +346,12 @@ namespace EMotionFX void MultiThreadScheduler::Lock() { - mMutex.Lock(); + m_mutex.Lock(); } void MultiThreadScheduler::Unlock() { - mMutex.Unlock(); + m_mutex.Unlock(); } } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MultiThreadScheduler.h b/Gems/EMotionFX/Code/EMotionFX/Source/MultiThreadScheduler.h index 6d5a7251e5..cf22875d97 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MultiThreadScheduler.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MultiThreadScheduler.h @@ -50,8 +50,8 @@ namespace EMotionFX */ struct EMFX_API ScheduleStep { - AZStd::vector mDependencies; /**< The dependencies of this scheduler step. No actor instances with the same dependencies are allowed to be added to this step. */ - AZStd::vector mActorInstances; /**< The actor instances used inside this step. Each array entry will execute in another thread. */ + AZStd::vector m_dependencies; /**< The dependencies of this scheduler step. No actor instances with the same dependencies are allowed to be added to this step. */ + AZStd::vector m_actorInstances; /**< The actor instances used inside this step. Each array entry will execute in another thread. */ }; /** @@ -119,13 +119,13 @@ namespace EMotionFX void Lock(); void Unlock(); - const ScheduleStep& GetScheduleStep(size_t index) const { return mSteps[index]; } - size_t GetNumScheduleSteps() const { return mSteps.size(); } + const ScheduleStep& GetScheduleStep(size_t index) const { return m_steps[index]; } + size_t GetNumScheduleSteps() const { return m_steps.size(); } protected: - AZStd::vector< ScheduleStep > mSteps; /**< An array of update steps, that together form the schedule. */ - float mCleanTimer; /**< The time passed since the last automatic call to the Optimize method. */ - MCore::MutexRecursive mMutex; + AZStd::vector< ScheduleStep > m_steps; /**< An array of update steps, that together form the schedule. */ + float m_cleanTimer; /**< The time passed since the last automatic call to the Optimize method. */ + MCore::MutexRecursive m_mutex; bool HasActorInstanceInSteps(const ActorInstance* actorInstance) const; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Node.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Node.cpp index 4bb1d850c9..1217c928bc 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Node.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Node.cpp @@ -20,20 +20,20 @@ namespace EMotionFX Node::Node(const char* name, Skeleton* skeleton) : BaseObject() { - mParentIndex = InvalidIndex; - mNodeIndex = InvalidIndex; // hasn't been set yet - mSkeletalLODs = 0xFFFFFFFF; // set all bits of the integer to 1, which enables this node in all LOD levels on default - mSkeleton = skeleton; - mSemanticNameID = InvalidIndex32; - mNodeFlags = FLAG_INCLUDEINBOUNDSCALC; + m_parentIndex = InvalidIndex; + m_nodeIndex = InvalidIndex; // hasn't been set yet + m_skeletalLoDs = 0xFFFFFFFF; // set all bits of the integer to 1, which enables this node in all LOD levels on default + m_skeleton = skeleton; + m_semanticNameId = InvalidIndex32; + m_nodeFlags = FLAG_INCLUDEINBOUNDSCALC; if (name) { - mNameID = MCore::GetStringIdPool().GenerateIdForString(name); + m_nameId = MCore::GetStringIdPool().GenerateIdForString(name); } else { - mNameID = InvalidIndex32; + m_nameId = InvalidIndex32; } } @@ -41,13 +41,13 @@ namespace EMotionFX Node::Node(uint32 nameID, Skeleton* skeleton) : BaseObject() { - mParentIndex = InvalidIndex; - mNodeIndex = InvalidIndex; // hasn't been set yet - mSkeletalLODs = 0xFFFFFFFF;// set all bits of the integer to 1, which enables this node in all LOD levels on default - mSkeleton = skeleton; - mNameID = nameID; - mSemanticNameID = InvalidIndex32; - mNodeFlags = FLAG_INCLUDEINBOUNDSCALC; + m_parentIndex = InvalidIndex; + m_nodeIndex = InvalidIndex; // hasn't been set yet + m_skeletalLoDs = 0xFFFFFFFF;// set all bits of the integer to 1, which enables this node in all LOD levels on default + m_skeleton = skeleton; + m_nameId = nameID; + m_semanticNameId = InvalidIndex32; + m_nodeFlags = FLAG_INCLUDEINBOUNDSCALC; } @@ -78,19 +78,19 @@ namespace EMotionFX // create a clone of this node Node* Node::Clone(Skeleton* skeleton) const { - Node* result = Node::Create(mNameID, skeleton); + Node* result = Node::Create(m_nameId, skeleton); // copy attributes - result->mParentIndex = mParentIndex; - result->mNodeIndex = mNodeIndex; - result->mSkeletalLODs = mSkeletalLODs; - result->mChildIndices = mChildIndices; - result->mNodeFlags = mNodeFlags; - result->mSemanticNameID = mSemanticNameID; + result->m_parentIndex = m_parentIndex; + result->m_nodeIndex = m_nodeIndex; + result->m_skeletalLoDs = m_skeletalLoDs; + result->m_childIndices = m_childIndices; + result->m_nodeFlags = m_nodeFlags; + result->m_semanticNameId = m_semanticNameId; // copy the node attributes - result->mAttributes.reserve(mAttributes.size()); - for (const NodeAttribute* attribute : mAttributes) + result->m_attributes.reserve(m_attributes.size()); + for (const NodeAttribute* attribute : m_attributes) { result->AddAttribute(attribute->Clone()); } @@ -103,10 +103,10 @@ namespace EMotionFX // removes all attributes void Node::RemoveAllAttributes() { - while (!mAttributes.empty()) + while (!m_attributes.empty()) { - mAttributes.back()->Destroy(); - mAttributes.pop_back(); + m_attributes.back()->Destroy(); + m_attributes.pop_back(); } } @@ -118,9 +118,9 @@ namespace EMotionFX size_t result = 0; // retrieve the number of child nodes of the actual node - for (size_t childIndex : mChildIndices) + for (size_t childIndex : m_childIndices) { - mSkeleton->GetNode(childIndex)->RecursiveCountChildNodes(result); + m_skeleton->GetNode(childIndex)->RecursiveCountChildNodes(result); } return result; @@ -134,9 +134,9 @@ namespace EMotionFX numNodes++; // recurse down the hierarchy - for (size_t childIndex : mChildIndices) + for (size_t childIndex : m_childIndices) { - mSkeleton->GetNode(childIndex)->RecursiveCountChildNodes(numNodes); + m_skeleton->GetNode(childIndex)->RecursiveCountChildNodes(numNodes); } } @@ -173,7 +173,7 @@ namespace EMotionFX // remove the given attribute of the given type from the node void Node::RemoveAttributeByType(uint32 attributeTypeID, size_t occurrence) { - const auto foundAttribute = AZStd::find_if(begin(mAttributes), end(mAttributes), [attributeTypeID, occurrence, currentOccurrence = size_t{0}] (const NodeAttribute* attribute) mutable + const auto foundAttribute = AZStd::find_if(begin(m_attributes), end(m_attributes), [attributeTypeID, occurrence, currentOccurrence = size_t{0}] (const NodeAttribute* attribute) mutable { if (attribute->GetType() == attributeTypeID) { @@ -183,14 +183,14 @@ namespace EMotionFX return false; }); - mAttributes.erase(foundAttribute); + m_attributes.erase(foundAttribute); } // remove all attributes of the given type from the node size_t Node::RemoveAllAttributesByType(uint32 attributeTypeID) { - return AZStd::erase_if(mAttributes, [attributeTypeID](const NodeAttribute* attribute) + return AZStd::erase_if(m_attributes, [attributeTypeID](const NodeAttribute* attribute) { return attribute->GetType() == attributeTypeID; }); @@ -201,12 +201,12 @@ namespace EMotionFX // recursively find the root node (expensive call) Node* Node::FindRoot() const { - size_t parentIndex = mParentIndex; + size_t parentIndex = m_parentIndex; const Node* curNode = this; while (parentIndex != InvalidIndex) { - curNode = mSkeleton->GetNode(parentIndex); + curNode = m_skeleton->GetNode(parentIndex); parentIndex = curNode->GetParentIndex(); } @@ -217,9 +217,9 @@ namespace EMotionFX // get the parent node, or nullptr when it doesn't exist Node* Node::GetParentNode() const { - if (mParentIndex != InvalidIndex) + if (m_parentIndex != InvalidIndex) { - return mSkeleton->GetNode(mParentIndex); + return m_skeleton->GetNode(m_parentIndex); } return nullptr; @@ -231,11 +231,11 @@ namespace EMotionFX { if (name) { - mNameID = MCore::GetStringIdPool().GenerateIdForString(name); + m_nameId = MCore::GetStringIdPool().GenerateIdForString(name); } else { - mNameID = InvalidIndex32; + m_nameId = InvalidIndex32; } } @@ -245,53 +245,53 @@ namespace EMotionFX { if (name) { - mSemanticNameID = MCore::GetStringIdPool().GenerateIdForString(name); + m_semanticNameId = MCore::GetStringIdPool().GenerateIdForString(name); } else { - mSemanticNameID = InvalidIndex32; + m_semanticNameId = InvalidIndex32; } } void Node::SetParentIndex(size_t parentNodeIndex) { - mParentIndex = parentNodeIndex; + m_parentIndex = parentNodeIndex; } // get the name const char* Node::GetName() const { - return MCore::GetStringIdPool().GetName(mNameID).c_str(); + return MCore::GetStringIdPool().GetName(m_nameId).c_str(); } // get the name of the node as pointer to chars const AZStd::string& Node::GetNameString() const { - return MCore::GetStringIdPool().GetName(mNameID); + return MCore::GetStringIdPool().GetName(m_nameId); } // get the semantic name const char* Node::GetSemanticName() const { - return MCore::GetStringIdPool().GetName(mSemanticNameID).c_str(); + return MCore::GetStringIdPool().GetName(m_semanticNameId).c_str(); } // get the semantic name of the node as pointer to chars const AZStd::string& Node::GetSemanticNameString() const { - return MCore::GetStringIdPool().GetName(mSemanticNameID); + return MCore::GetStringIdPool().GetName(m_semanticNameId); } // returns true if this is a root node, so if it has no parents bool Node::GetIsRootNode() const { - return (mParentIndex == InvalidIndex); + return (m_parentIndex == InvalidIndex); } @@ -299,110 +299,110 @@ namespace EMotionFX void Node::AddAttribute(NodeAttribute* attribute) { - mAttributes.emplace_back(attribute); + m_attributes.emplace_back(attribute); } size_t Node::GetNumAttributes() const { - return mAttributes.size(); + return m_attributes.size(); } NodeAttribute* Node::GetAttribute(size_t attributeNr) { // make sure we are in range - MCORE_ASSERT(attributeNr < mAttributes.size()); + MCORE_ASSERT(attributeNr < m_attributes.size()); // return the attribute - return mAttributes[attributeNr]; + return m_attributes[attributeNr]; } size_t Node::FindAttributeNumber(uint32 attributeTypeID) const { // check all attributes, and find where the specific attribute is - const auto foundAttribute = AZStd::find_if(begin(mAttributes), end(mAttributes), [attributeTypeID](const NodeAttribute* attribute) + const auto foundAttribute = AZStd::find_if(begin(m_attributes), end(m_attributes), [attributeTypeID](const NodeAttribute* attribute) { return attribute->GetType() == attributeTypeID; }); - return foundAttribute != end(mAttributes) ? AZStd::distance(begin(mAttributes), foundAttribute) : InvalidIndex; + return foundAttribute != end(m_attributes) ? AZStd::distance(begin(m_attributes), foundAttribute) : InvalidIndex; } NodeAttribute* Node::GetAttributeByType(uint32 attributeType) { // check all attributes - const auto foundAttribute = AZStd::find_if(begin(mAttributes), end(mAttributes), [attributeType](const NodeAttribute* attribute) + const auto foundAttribute = AZStd::find_if(begin(m_attributes), end(m_attributes), [attributeType](const NodeAttribute* attribute) { return attribute->GetType() == attributeType; }); - return foundAttribute != end(mAttributes) ? *foundAttribute : nullptr; + return foundAttribute != end(m_attributes) ? *foundAttribute : nullptr; } // remove the given attribute void Node::RemoveAttribute(size_t index) { - mAttributes.erase(AZStd::next(begin(mAttributes), index)); + m_attributes.erase(AZStd::next(begin(m_attributes), index)); } void Node::AddChild(size_t nodeIndex) { - mChildIndices.emplace_back(nodeIndex); + m_childIndices.emplace_back(nodeIndex); } void Node::SetChild(size_t childNr, size_t childNodeIndex) { - mChildIndices[childNr] = childNodeIndex; + m_childIndices[childNr] = childNodeIndex; } void Node::SetNumChildNodes(size_t numChildNodes) { - mChildIndices.resize(numChildNodes); + m_childIndices.resize(numChildNodes); } void Node::PreAllocNumChildNodes(size_t numChildNodes) { - mChildIndices.reserve(numChildNodes); + m_childIndices.reserve(numChildNodes); } void Node::RemoveChild(size_t nodeIndex) { - if (const auto it = AZStd::find(begin(mChildIndices), end(mChildIndices), nodeIndex); it != end(mChildIndices)) + if (const auto it = AZStd::find(begin(m_childIndices), end(m_childIndices), nodeIndex); it != end(m_childIndices)) { - mChildIndices.erase(it); + m_childIndices.erase(it); } } void Node::RemoveAllChildNodes() { - mChildIndices.clear(); + m_childIndices.clear(); } bool Node::GetHasChildNodes() const { - return !mChildIndices.empty(); + return !m_childIndices.empty(); } void Node::SetNodeIndex(size_t index) { - mNodeIndex = index; + m_nodeIndex = index; } void Node::SetSkeletalLODLevelBits(size_t bitValues) { - mSkeletalLODs = bitValues; + m_skeletalLoDs = bitValues; } @@ -411,11 +411,11 @@ namespace EMotionFX MCORE_ASSERT(lodLevel <= 63); if (enabled) { - mSkeletalLODs |= (1ull << lodLevel); + m_skeletalLoDs |= (1ull << lodLevel); } else { - mSkeletalLODs &= ~(1ull << lodLevel); + m_skeletalLoDs &= ~(1ull << lodLevel); } } @@ -424,11 +424,11 @@ namespace EMotionFX { if (includeThisNode) { - mNodeFlags |= FLAG_INCLUDEINBOUNDSCALC; + m_nodeFlags |= FLAG_INCLUDEINBOUNDSCALC; } else { - mNodeFlags &= ~FLAG_INCLUDEINBOUNDSCALC; + m_nodeFlags &= ~FLAG_INCLUDEINBOUNDSCALC; } } @@ -436,18 +436,18 @@ namespace EMotionFX { if (isCritical) { - mNodeFlags |= FLAG_CRITICAL; + m_nodeFlags |= FLAG_CRITICAL; } else { - mNodeFlags &= ~FLAG_CRITICAL; + m_nodeFlags &= ~FLAG_CRITICAL; } } bool Node::GetIsAttachmentNode() const { - return (mNodeFlags & FLAG_ATTACHMENT) != 0; + return (m_nodeFlags & FLAG_ATTACHMENT) != 0; } @@ -455,11 +455,11 @@ namespace EMotionFX { if (isAttachmentNode) { - mNodeFlags |= FLAG_ATTACHMENT; + m_nodeFlags |= FLAG_ATTACHMENT; } else { - mNodeFlags &= ~FLAG_ATTACHMENT; + m_nodeFlags &= ~FLAG_ATTACHMENT; } } } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Node.h b/Gems/EMotionFX/Code/EMotionFX/Source/Node.h index 19d9f53ff8..01dfacc28c 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Node.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Node.h @@ -92,7 +92,7 @@ namespace EMotionFX * This is either a valid index, or MCORE_INVALIDINDEX32 in case there is no parent node. * @result The index of the parent node, or MCORE_INVALIDINDEX32 in case this node has no parent. */ - MCORE_INLINE size_t GetParentIndex() const { return mParentIndex; } + MCORE_INLINE size_t GetParentIndex() const { return m_parentIndex; } /** * Get the parent node as node pointer. @@ -155,20 +155,20 @@ namespace EMotionFX * same ID number. * @result The node ID number, which can be used for fast compares between nodes. */ - MCORE_INLINE uint32 GetID() const { return mNameID; } + MCORE_INLINE uint32 GetID() const { return m_nameId; } /** * Get the semantic name ID. * To get the name you can also use GetSemanticName() and GetSemanticNameString(). * @result The semantic name ID. */ - MCORE_INLINE uint32 GetSemanticID() const { return mSemanticNameID; } + MCORE_INLINE uint32 GetSemanticID() const { return m_semanticNameId; } /** * Get the number of child nodes attached to this node. * @result The number of child nodes. */ - MCORE_INLINE size_t GetNumChildNodes() const { return mChildIndices.size(); } + MCORE_INLINE size_t GetNumChildNodes() const { return m_childIndices.size(); } /** * Get the number of child nodes down the hierarchy of this node. @@ -182,14 +182,14 @@ namespace EMotionFX * @param nr The child number. * @result The index of the child node, which is a node number inside the actor. */ - MCORE_INLINE size_t GetChildIndex(size_t nr) const { return mChildIndices[nr]; } + MCORE_INLINE size_t GetChildIndex(size_t nr) const { return m_childIndices[nr]; } /** * Checks if the given node is a child of this node. * @param nodeIndex The node to check whether it is a child or not. * @result True if the given node is a child, false if not. */ - MCORE_INLINE bool CheckIfIsChildNode(size_t nodeIndex) const { return (AZStd::find(begin(mChildIndices), end(mChildIndices), nodeIndex) != end(mChildIndices)); } + MCORE_INLINE bool CheckIfIsChildNode(size_t nodeIndex) const { return (AZStd::find(begin(m_childIndices), end(m_childIndices), nodeIndex) != end(m_childIndices)); } /** * Add a child to this node. @@ -336,7 +336,7 @@ namespace EMotionFX * So Actor::GetNode( nodeIndex ) will return this node. * @result The index of the node. */ - MCORE_INLINE size_t GetNodeIndex() const { return mNodeIndex; } + MCORE_INLINE size_t GetNodeIndex() const { return m_nodeIndex; } //------------------------------ @@ -364,7 +364,7 @@ namespace EMotionFX * @param lodLevel The skeletal LOD level to check. * @result Returns true when this node is enabled in the specified LOD level. Otherwise false is returned. */ - MCORE_INLINE bool GetSkeletalLODStatus(size_t lodLevel) const { return (mSkeletalLODs & (1ull << lodLevel)) != 0; } + MCORE_INLINE bool GetSkeletalLODStatus(size_t lodLevel) const { return (m_skeletalLoDs & (1ull << lodLevel)) != 0; } //-------------------------------------------- @@ -376,7 +376,7 @@ namespace EMotionFX * On default all nodes are included inside the bounding volume calculations. * @result Returns true when this node will be included in the bounds calculation, or false when it won't. */ - MCORE_INLINE bool GetIncludeInBoundsCalc() const { return mNodeFlags & FLAG_INCLUDEINBOUNDSCALC; } + MCORE_INLINE bool GetIncludeInBoundsCalc() const { return m_nodeFlags & FLAG_INCLUDEINBOUNDSCALC; } /** * Specify whether this node should be included inside the bounding volume calculations or not. @@ -394,7 +394,7 @@ namespace EMotionFX * Sometimes we perform optimization process on the node. This flag make sure that critical node will always be included in the actor heirarchy. * @result Returns true when this node is critical, or false when it won't. */ - MCORE_INLINE bool GetIsCritical() const { return mNodeFlags & FLAG_CRITICAL; } + MCORE_INLINE bool GetIsCritical() const { return m_nodeFlags & FLAG_CRITICAL; } /** * Specify whether this node is critcal and should not be optimized out in any situations. @@ -415,15 +415,15 @@ namespace EMotionFX void SetIsAttachmentNode(bool isAttachmentNode); private: - size_t mNodeIndex; /**< The node index, which is the index into the array of nodes inside the Skeleton class. */ - size_t mParentIndex; /**< The parent node index, or MCORE_INVALIDINDEX32 when there is no parent. */ - size_t mSkeletalLODs; /**< The skeletal LOD status values. Each bit represents if this node is enabled or disabled in the given LOD. */ - uint32 mNameID; /**< The ID, which is generated from the name. You can use this for fast compares between nodes. */ - uint32 mSemanticNameID; /**< The semantic name ID, for example "LeftHand" or "RightFoot" or so, this can be used for retargeting. */ - Skeleton* mSkeleton; /**< The skeleton where this node belongs to. */ - AZStd::vector mChildIndices; /**< The indices that point to the child nodes. */ - AZStd::vector mAttributes; /**< The node attributes. */ - uint8 mNodeFlags; /**< The node flags are used to store boolean attributes of the node as single bits. */ + size_t m_nodeIndex; /**< The node index, which is the index into the array of nodes inside the Skeleton class. */ + size_t m_parentIndex; /**< The parent node index, or MCORE_INVALIDINDEX32 when there is no parent. */ + size_t m_skeletalLoDs; /**< The skeletal LOD status values. Each bit represents if this node is enabled or disabled in the given LOD. */ + uint32 m_nameId; /**< The ID, which is generated from the name. You can use this for fast compares between nodes. */ + uint32 m_semanticNameId; /**< The semantic name ID, for example "LeftHand" or "RightFoot" or so, this can be used for retargeting. */ + Skeleton* m_skeleton; /**< The skeleton where this node belongs to. */ + AZStd::vector m_childIndices; /**< The indices that point to the child nodes. */ + AZStd::vector m_attributes; /**< The node attributes. */ + uint8 m_nodeFlags; /**< The node flags are used to store boolean attributes of the node as single bits. */ /** * Constructor. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/NodeGroup.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/NodeGroup.cpp index cd2139ec9a..293d64775d 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/NodeGroup.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/NodeGroup.cpp @@ -18,9 +18,9 @@ namespace EMotionFX NodeGroup::NodeGroup(const AZStd::string& groupName, uint16 numNodes, bool enabledOnDefault) - : mName(groupName) - , mNodes(numNodes) - , mEnabledOnDefault(enabledOnDefault) + : m_name(groupName) + , m_nodes(numNodes) + , m_enabledOnDefault(enabledOnDefault) { } @@ -28,59 +28,59 @@ namespace EMotionFX // set the name of the group void NodeGroup::SetName(const AZStd::string& groupName) { - mName = groupName; + m_name = groupName; } // get the name of the group as character buffer const char* NodeGroup::GetName() const { - return mName.c_str(); + return m_name.c_str(); } // get the name of the string as mcore string object const AZStd::string& NodeGroup::GetNameString() const { - return mName; + return m_name; } // set the number of nodes void NodeGroup::SetNumNodes(const uint16 numNodes) { - mNodes.Resize(numNodes); + m_nodes.Resize(numNodes); } // get the number of nodes uint16 NodeGroup::GetNumNodes() const { - return static_cast(mNodes.GetLength()); + return static_cast(m_nodes.GetLength()); } // set a given node to a given node number void NodeGroup::SetNode(uint16 index, uint16 nodeIndex) { - mNodes[index] = nodeIndex; + m_nodes[index] = nodeIndex; } // get the node number of a given index uint16 NodeGroup::GetNode(uint16 index) const { - return mNodes[index]; + return m_nodes[index]; } // enable all nodes in the group inside a given actor instance void NodeGroup::EnableNodes(ActorInstance* targetActorInstance) { - const uint16 numNodes = static_cast(mNodes.GetLength()); + const uint16 numNodes = static_cast(m_nodes.GetLength()); for (uint16 i = 0; i < numNodes; ++i) { - targetActorInstance->EnableNode(mNodes[i]); + targetActorInstance->EnableNode(m_nodes[i]); } } @@ -88,10 +88,10 @@ namespace EMotionFX // disable all nodes in the group inside a given actor instance void NodeGroup::DisableNodes(ActorInstance* targetActorInstance) { - const uint16 numNodes = static_cast(mNodes.GetLength()); + const uint16 numNodes = static_cast(m_nodes.GetLength()); for (uint16 i = 0; i < numNodes; ++i) { - targetActorInstance->DisableNode(mNodes[i]); + targetActorInstance->DisableNode(m_nodes[i]); } } @@ -99,42 +99,42 @@ namespace EMotionFX // add a given node to the group (performs a realloc internally) void NodeGroup::AddNode(uint16 nodeIndex) { - mNodes.Add(nodeIndex); + m_nodes.Add(nodeIndex); } // remove a given node by its node number void NodeGroup::RemoveNodeByNodeIndex(uint16 nodeIndex) { - mNodes.RemoveByValue(nodeIndex); + m_nodes.RemoveByValue(nodeIndex); } // remove a given array element from the list of nodes void NodeGroup::RemoveNodeByGroupIndex(uint16 index) { - mNodes.Remove(index); + m_nodes.Remove(index); } // get the node array directly MCore::SmallArray& NodeGroup::GetNodeArray() { - return mNodes; + return m_nodes; } // is this group enabled on default? bool NodeGroup::GetIsEnabledOnDefault() const { - return mEnabledOnDefault; + return m_enabledOnDefault; } // set the default enabled state void NodeGroup::SetIsEnabledOnDefault(bool enabledOnDefault) { - mEnabledOnDefault = enabledOnDefault; + m_enabledOnDefault = enabledOnDefault; } NodeGroup::NodeGroup(const NodeGroup& aOther) @@ -144,9 +144,9 @@ namespace EMotionFX NodeGroup& NodeGroup::operator=(const NodeGroup& aOther) { - mName = aOther.mName; - mNodes = aOther.mNodes; - mEnabledOnDefault = aOther.mEnabledOnDefault; + m_name = aOther.m_name; + m_nodes = aOther.m_nodes; + m_enabledOnDefault = aOther.m_enabledOnDefault; return *this; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/NodeGroup.h b/Gems/EMotionFX/Code/EMotionFX/Source/NodeGroup.h index b3e82e648b..7ee74415c0 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/NodeGroup.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/NodeGroup.h @@ -154,8 +154,8 @@ namespace EMotionFX void SetIsEnabledOnDefault(bool enabledOnDefault); private: - AZStd::string mName; /**< The name of the group. */ - MCore::SmallArray mNodes; /**< The node index numbers that are inside this group. */ - bool mEnabledOnDefault; /**< Specifies whether this group is enabled on default (true) or disabled (false). With on default we mean after directly after the actor instance using this group has been created. */ + AZStd::string m_name; /**< The name of the group. */ + MCore::SmallArray m_nodes; /**< The node index numbers that are inside this group. */ + bool m_enabledOnDefault; /**< Specifies whether this group is enabled on default (true) or disabled (false). With on default we mean after directly after the actor instance using this group has been created. */ }; } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/NodeMap.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/NodeMap.cpp index fb2fbd9ed7..f9774751ba 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/NodeMap.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/NodeMap.cpp @@ -27,7 +27,7 @@ namespace EMotionFX NodeMap::NodeMap() : BaseObject() { - mSourceActor = nullptr; + m_sourceActor = nullptr; } @@ -41,36 +41,36 @@ namespace EMotionFX // preallocate space void NodeMap::Reserve(size_t numEntries) { - mEntries.reserve(numEntries); + m_entries.reserve(numEntries); } // resize the entries array void NodeMap::Resize(size_t numEntries) { - mEntries.resize(numEntries); + m_entries.resize(numEntries); } // modify the first name of a given entry void NodeMap::SetFirstName(size_t entryIndex, const char* name) { - mEntries[entryIndex].mFirstNameID = MCore::GetStringIdPool().GenerateIdForString(name); + m_entries[entryIndex].m_firstNameId = MCore::GetStringIdPool().GenerateIdForString(name); } // modify the second name void NodeMap::SetSecondName(size_t entryIndex, const char* name) { - mEntries[entryIndex].mSecondNameID = MCore::GetStringIdPool().GenerateIdForString(name); + m_entries[entryIndex].m_secondNameId = MCore::GetStringIdPool().GenerateIdForString(name); } // modify a given entry void NodeMap::SetEntry(size_t entryIndex, const char* firstName, const char* secondName) { - mEntries[entryIndex].mFirstNameID = MCore::GetStringIdPool().GenerateIdForString(firstName); - mEntries[entryIndex].mSecondNameID = MCore::GetStringIdPool().GenerateIdForString(secondName); + m_entries[entryIndex].m_firstNameId = MCore::GetStringIdPool().GenerateIdForString(firstName); + m_entries[entryIndex].m_secondNameId = MCore::GetStringIdPool().GenerateIdForString(secondName); } @@ -101,15 +101,15 @@ namespace EMotionFX void NodeMap::AddEntry(const char* firstName, const char* secondName) { MCORE_ASSERT(GetHasEntry(firstName) == false); // prevent duplicates - mEntries.emplace_back(); - SetEntry(mEntries.size() - 1, firstName, secondName); + m_entries.emplace_back(); + SetEntry(m_entries.size() - 1, firstName, secondName); } // remove a given entry by its index void NodeMap::RemoveEntryByIndex(size_t entryIndex) { - mEntries.erase(AZStd::next(begin(mEntries), entryIndex)); + m_entries.erase(AZStd::next(begin(m_entries), entryIndex)); } @@ -122,7 +122,7 @@ namespace EMotionFX return; } - mEntries.erase(AZStd::next(begin(mEntries), entryIndex)); + m_entries.erase(AZStd::next(begin(m_entries), entryIndex)); } @@ -135,28 +135,28 @@ namespace EMotionFX return; } - mEntries.erase(AZStd::next(begin(mEntries), entryIndex)); + m_entries.erase(AZStd::next(begin(m_entries), entryIndex)); } // set the filename void NodeMap::SetFileName(const char* fileName) { - mFileName = fileName; + m_fileName = fileName; } // get the filename const char* NodeMap::GetFileName() const { - return mFileName.c_str(); + return m_fileName.c_str(); } // get the filename const AZStd::string& NodeMap::GetFileNameString() const { - return mFileName; + return m_fileName; } @@ -211,7 +211,7 @@ namespace EMotionFX size_t numBytes = sizeof(FileFormat::NodeMapChunk); // for all entries - const size_t numEntries = mEntries.size(); + const size_t numEntries = m_entries.size(); for (size_t i = 0; i < numEntries; ++i) { numBytes += CalcFileStringSize(GetFirstNameString(i)); @@ -236,13 +236,13 @@ namespace EMotionFX // try to write the file header FileFormat::NodeMap_Header header{}; - header.mFourCC[0] = 'N'; - header.mFourCC[1] = 'O'; - header.mFourCC[2] = 'M'; - header.mFourCC[3] = 'P'; - header.mHiVersion = 1; - header.mLoVersion = 0; - header.mEndianType = (uint8)targetEndianType; + header.m_fourCc[0] = 'N'; + header.m_fourCc[1] = 'O'; + header.m_fourCc[2] = 'M'; + header.m_fourCc[3] = 'P'; + header.m_hiVersion = 1; + header.m_loVersion = 0; + header.m_endianType = (uint8)targetEndianType; if (f.Write(&header, sizeof(FileFormat::NodeMap_Header)) == 0) { MCore::LogError("NodeMap::Save() - Cannot write the header to file '%s', is the file maybe in use by another application?", fileName); @@ -251,12 +251,12 @@ namespace EMotionFX // write the chunk header FileFormat::FileChunk chunkHeader{}; - chunkHeader.mChunkID = FileFormat::CHUNK_NODEMAP; - chunkHeader.mVersion = 1; - chunkHeader.mSizeInBytes = CalcFileChunkSize();// calculate the chunk size - MCore::Endian::ConvertUnsignedInt32To(&chunkHeader.mChunkID, targetEndianType); - MCore::Endian::ConvertUnsignedInt32To(&chunkHeader.mSizeInBytes, targetEndianType); - MCore::Endian::ConvertUnsignedInt32To(&chunkHeader.mVersion, targetEndianType); + chunkHeader.m_chunkId = FileFormat::CHUNK_NODEMAP; + chunkHeader.m_version = 1; + chunkHeader.m_sizeInBytes = CalcFileChunkSize();// calculate the chunk size + MCore::Endian::ConvertUnsignedInt32To(&chunkHeader.m_chunkId, targetEndianType); + MCore::Endian::ConvertUnsignedInt32To(&chunkHeader.m_sizeInBytes, targetEndianType); + MCore::Endian::ConvertUnsignedInt32To(&chunkHeader.m_version, targetEndianType); if (f.Write(&chunkHeader, sizeof(FileFormat::FileChunk)) == 0) { MCore::LogError("NodeMap::Save() - Cannot write the chunk header to file '%s', is the file maybe in use by another application?", fileName); @@ -265,8 +265,8 @@ namespace EMotionFX // the main info FileFormat::NodeMapChunk nodeMapChunk{}; - nodeMapChunk.mNumEntries = aznumeric_caster(mEntries.size()); - MCore::Endian::ConvertUnsignedInt32To(&nodeMapChunk.mNumEntries, targetEndianType); + nodeMapChunk.m_numEntries = aznumeric_caster(m_entries.size()); + MCore::Endian::ConvertUnsignedInt32To(&nodeMapChunk.m_numEntries, targetEndianType); if (f.Write(&nodeMapChunk, sizeof(FileFormat::NodeMapChunk)) == 0) { MCore::LogError("NodeMap::Save() - Cannot write the node map chunk to file '%s', is the file maybe in use by another application?", fileName); @@ -282,7 +282,7 @@ namespace EMotionFX } // for all entries - const uint32 numEntries = aznumeric_caster(mEntries.size()); + const uint32 numEntries = aznumeric_caster(m_entries.size()); for (uint32 i = 0; i < numEntries; ++i) { if (WriteFileString(&f, GetFirstNameString(i), targetEndianType) == false) @@ -308,49 +308,49 @@ namespace EMotionFX // update the source actor pointer void NodeMap::SetSourceActor(Actor* actor) { - mSourceActor = actor; + m_sourceActor = actor; } // get the source actor pointer Actor* NodeMap::GetSourceActor() const { - return mSourceActor; + return m_sourceActor; } // get the number of entries size_t NodeMap::GetNumEntries() const { - return mEntries.size(); + return m_entries.size(); } // get the first name as char pointer const char* NodeMap::GetFirstName(size_t entryIndex) const { - return MCore::GetStringIdPool().GetName(mEntries[entryIndex].mFirstNameID).c_str(); + return MCore::GetStringIdPool().GetName(m_entries[entryIndex].m_firstNameId).c_str(); } // get the second node name as char pointer const char* NodeMap::GetSecondName(size_t entryIndex) const { - return MCore::GetStringIdPool().GetName(mEntries[entryIndex].mSecondNameID).c_str(); + return MCore::GetStringIdPool().GetName(m_entries[entryIndex].m_secondNameId).c_str(); } // get the first node name as string const AZStd::string& NodeMap::GetFirstNameString(size_t entryIndex) const { - return MCore::GetStringIdPool().GetName(mEntries[entryIndex].mFirstNameID); + return MCore::GetStringIdPool().GetName(m_entries[entryIndex].m_firstNameId); } // get the second node name as string const AZStd::string& NodeMap::GetSecondNameString(size_t entryIndex) const { - return MCore::GetStringIdPool().GetName(mEntries[entryIndex].mSecondNameID); + return MCore::GetStringIdPool().GetName(m_entries[entryIndex].m_secondNameId); } @@ -364,22 +364,22 @@ namespace EMotionFX // find an entry index by its name size_t NodeMap::FindEntryIndexByName(const char* firstName) const { - const auto foundEntry = AZStd::find_if(begin(mEntries), end(mEntries), [firstName](const MapEntry& entry) + const auto foundEntry = AZStd::find_if(begin(m_entries), end(m_entries), [firstName](const MapEntry& entry) { - return MCore::GetStringIdPool().GetName(entry.mFirstNameID) == firstName; + return MCore::GetStringIdPool().GetName(entry.m_firstNameId) == firstName; }); - return foundEntry != end(mEntries) ? AZStd::distance(begin(mEntries), foundEntry) : InvalidIndex; + return foundEntry != end(m_entries) ? AZStd::distance(begin(m_entries), foundEntry) : InvalidIndex; } // find an entry index by its name ID size_t NodeMap::FindEntryIndexByNameID(uint32 firstNameID) const { - const auto foundEntry = AZStd::find_if(begin(mEntries), end(mEntries), [firstNameID](const MapEntry& entry) + const auto foundEntry = AZStd::find_if(begin(m_entries), end(m_entries), [firstNameID](const MapEntry& entry) { - return entry.mFirstNameID == firstNameID; + return entry.m_firstNameId == firstNameID; }); - return foundEntry != end(mEntries) ? AZStd::distance(begin(mEntries), foundEntry) : InvalidIndex; + return foundEntry != end(m_entries) ? AZStd::distance(begin(m_entries), foundEntry) : InvalidIndex; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/NodeMap.h b/Gems/EMotionFX/Code/EMotionFX/Source/NodeMap.h index 3fe2c94386..c0744323af 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/NodeMap.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/NodeMap.h @@ -39,8 +39,8 @@ namespace EMotionFX public: struct MapEntry { - uint32 mFirstNameID = InvalidIndex32; /**< The first name ID, which is the primary key in the map. */ - uint32 mSecondNameID = InvalidIndex32; /**< The second name ID. */ + uint32 m_firstNameId = InvalidIndex32; /**< The first name ID, which is the primary key in the map. */ + uint32 m_secondNameId = InvalidIndex32; /**< The second name ID. */ }; static NodeMap* Create(); @@ -84,9 +84,9 @@ namespace EMotionFX bool Save(const char* fileName, MCore::Endian::EEndianType targetEndianType) const; private: - AZStd::vector mEntries; /**< The array of entries. */ - AZStd::string mFileName; /**< The filename. */ - Actor* mSourceActor; /**< The source actor. */ + AZStd::vector m_entries; /**< The array of entries. */ + AZStd::string m_fileName; /**< The filename. */ + Actor* m_sourceActor; /**< The source actor. */ // constructor and destructor NodeMap(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/PhysicsSetup.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/PhysicsSetup.cpp index dbe57cdd34..02b3fd7649 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/PhysicsSetup.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/PhysicsSetup.cpp @@ -510,15 +510,15 @@ namespace EMotionFX const Node* childNode = skeleton->GetNode(childIndex); const float numSubChildren = static_cast(1 + childNode->GetNumChildNodesRecursive()); totalSubChildren += numSubChildren; - meanChildPosition += numSubChildren * (bindPose->GetModelSpaceTransform(childIndex).mPosition); + meanChildPosition += numSubChildren * (bindPose->GetModelSpaceTransform(childIndex).m_position); } - boneDirection = meanChildPosition / totalSubChildren - nodeBindTransform.mPosition; + boneDirection = meanChildPosition / totalSubChildren - nodeBindTransform.m_position; } // otherwise, point the bone direction away from the parent else { - boneDirection = nodeBindTransform.mPosition - parentBindTransform.mPosition; + boneDirection = nodeBindTransform.m_position - parentBindTransform.m_position; } return boneDirection; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/PlayBackInfo.h b/Gems/EMotionFX/Code/EMotionFX/Source/PlayBackInfo.h index 6ae2b0d809..de84a97da8 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/PlayBackInfo.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/PlayBackInfo.h @@ -65,29 +65,29 @@ namespace EMotionFX *
          * Member Name           - Default Value
          * ---------------------------------
-         * mBlendInTime          - 0.3 (seconds)
-         * mBlendOutTime         - 0.3 (seconds)
-         * mPlaySpeed            - 1.0 (original speed)
-         * mTargetWeight         - 1.0 (fully blend in)
-         * mEventWeightThreshold - 0.0 (allow all events even with low motion instance weight values)
-         * mMaxPlayTime          - 0.0 (disabled when zero or negative)
-         * mClipStartTime        - 0.0 (start and loop from the beginning of the motion)
-         * mClipEndTime          - 0.0 (set to negative or zero to play the full range of the motion)
-         * mNumLoops             - EMFX_LOOPFOREVER
-         * mBlendMode            - BLENDMODE_OVERWRITE (overwrites motions)
-         * mPlayMode             - PLAYMODE_FORWARD (regular forward playing motion)
-         * mMirrorMotion         - false (disable motion mirroring)
-         * mPlayNow              - true (start playing immediately)
-         * mMix                  - false (non mixing motion)
-         * mPriorityLevel        - 0 (no priority)
-         * mMotionExtractionEnabled - true
-         * mRetarget             - false (no motion retargeting allowed)
-         * mFreezeAtLastFrame    - true (motion freezes in last frame when not looping forever)
-         * mEnableMotionEvents   - true (all motion events will be processed for this motion instance
-         * mBlendOutBeforeEnded  - true (blend out so that it faded out at the end of the motion).
-         * mCanOverwrite         - true (can overwrite other motion instances when reaching a weight of 1.0)
-         * mDeleteOnZeroWeight   - true (delete this motion instance when it reaches a weight of 0.0)
-         * mFreezeAtTime;        - -1.0 (Freeze at a given time offset in seconds. The current play time would continue running though, and a blend out would be triggered, unlike the mFreezeAtLastFrame. Set to negative value to disable.
+         * m_blendInTime          - 0.3 (seconds)
+         * m_blendOutTime         - 0.3 (seconds)
+         * m_playSpeed            - 1.0 (original speed)
+         * m_targetWeight         - 1.0 (fully blend in)
+         * m_eventWeightThreshold - 0.0 (allow all events even with low motion instance weight values)
+         * m_maxPlayTime          - 0.0 (disabled when zero or negative)
+         * m_clipStartTime        - 0.0 (start and loop from the beginning of the motion)
+         * m_clipEndTime          - 0.0 (set to negative or zero to play the full range of the motion)
+         * m_numLoops             - EMFX_LOOPFOREVER
+         * m_blendMode            - BLENDMODE_OVERWRITE (overwrites motions)
+         * m_playMode             - PLAYMODE_FORWARD (regular forward playing motion)
+         * m_mirrorMotion         - false (disable motion mirroring)
+         * m_playNow              - true (start playing immediately)
+         * m_mix                  - false (non mixing motion)
+         * m_priorityLevel        - 0 (no priority)
+         * m_motionExtractionEnabled - true
+         * m_retarget             - false (no motion retargeting allowed)
+         * m_freezeAtLastFrame    - true (motion freezes in last frame when not looping forever)
+         * m_enableMotionEvents   - true (all motion events will be processed for this motion instance
+         * m_blendOutBeforeEnded  - true (blend out so that it faded out at the end of the motion).
+         * m_canOverwrite         - true (can overwrite other motion instances when reaching a weight of 1.0)
+         * m_deleteOnZeroWeight   - true (delete this motion instance when it reaches a weight of 0.0)
+         * m_freezeAtTime;        - -1.0 (Freeze at a given time offset in seconds. The current play time would continue running though, and a blend out would be triggered, unlike the m_freezeAtLastFrame. Set to negative value to disable.
          *
          * 
* @@ -95,30 +95,30 @@ namespace EMotionFX */ PlayBackInfo() { - mBlendInTime = 0.3f; - mBlendOutTime = 0.3f; - mPlaySpeed = 1.0f; - mTargetWeight = 1.0f; - mEventWeightThreshold = 0.0f; - mMaxPlayTime = 0.0f; - mClipStartTime = 0.0f; - mClipEndTime = 0.0f; - mFreezeAtTime = -1.0f; - mNumLoops = EMFX_LOOPFOREVER; - mBlendMode = BLENDMODE_OVERWRITE; - mPlayMode = PLAYMODE_FORWARD; - mMirrorMotion = false; - mPlayNow = true; - mMix = false; - mMotionExtractionEnabled = true; - mRetarget = false; - mFreezeAtLastFrame = true; - mEnableMotionEvents = true; - mBlendOutBeforeEnded = true; - mCanOverwrite = true; - mDeleteOnZeroWeight = true; - mInPlace = false; - mPriorityLevel = 0; + m_blendInTime = 0.3f; + m_blendOutTime = 0.3f; + m_playSpeed = 1.0f; + m_targetWeight = 1.0f; + m_eventWeightThreshold = 0.0f; + m_maxPlayTime = 0.0f; + m_clipStartTime = 0.0f; + m_clipEndTime = 0.0f; + m_freezeAtTime = -1.0f; + m_numLoops = EMFX_LOOPFOREVER; + m_blendMode = BLENDMODE_OVERWRITE; + m_playMode = PLAYMODE_FORWARD; + m_mirrorMotion = false; + m_playNow = true; + m_mix = false; + m_motionExtractionEnabled = true; + m_retarget = false; + m_freezeAtLastFrame = true; + m_enableMotionEvents = true; + m_blendOutBeforeEnded = true; + m_canOverwrite = true; + m_deleteOnZeroWeight = true; + m_inPlace = false; + m_priorityLevel = 0; } /** @@ -128,29 +128,29 @@ namespace EMotionFX public: - float mBlendInTime; /**< The time, in seconds, which it will take to fully have blended to the target weight. */ - float mBlendOutTime; /**< The time, in seconds, which it takes to smoothly fadeout the motion, after it has been stopped playing. */ - float mPlaySpeed; /**< The playback speed factor. A value of 1 stands for the original speed, while for example 2 means twice the original speed. */ - float mTargetWeight; /**< The target weight, where 1 means fully active, and 0 means not active at all. */ - float mEventWeightThreshold; /**< The motion event weight threshold. If the motion instance weight is lower than this value, no motion events will be executed for this motion instance. */ - float mMaxPlayTime; /**< The maximum play time, in seconds. Set to zero or a negative value to disable it. */ - float mClipStartTime; /**< The start playback time in seconds. Also in case of looping it will jump to this position on a loop. */ - float mClipEndTime; /**< The end playback time in seconds. It will jump back to the clip start time after reaching this playback time. */ - float mFreezeAtTime; /**< Freeze at a given time offset in seconds. The current play time would continue running though, and a blend out would be triggered, unlike the mFreezeAtLastFrame. Set to negative value to disable. Default=-1.*/ - uint32 mNumLoops; /**< The number of times you want to play this motion. A value of EMFX_LOOPFOREVER means it will loop forever. */ - uint32 mPriorityLevel; /**< The priority level, the higher this value, the higher priority it has on overwriting other motions. */ - EMotionBlendMode mBlendMode; /**< The motion blend mode. Please read the MotionInstance::SetBlendMode(...) method for more information. */ - EPlayMode mPlayMode; /**< The motion playback mode. This means forward or backward playback. */ - bool mMirrorMotion; /**< Is motion mirroring enabled or not? When set to true, the mMirrorPlaneNormal is used as mirroring axis. */ - bool mMix; /**< Set to true if you want this motion to mix or not. */ - bool mPlayNow; /**< Set to true if you want to start playing the motion right away. If set to false it will be scheduled for later by inserting it into the motion queue. */ - bool mMotionExtractionEnabled; /**< Set to true if you want this motion to move and rotate the actor instance, otherwise set to false. */ - bool mRetarget; /**< Set to true if you want to enable motion retargeting. Read the manual for more information. */ - bool mFreezeAtLastFrame; /**< Set to true if you like the motion to freeze at the last frame, for example in case of a death motion. */ - bool mEnableMotionEvents; /**< Set to true to enable motion events, or false to disable processing of motion events for this motion instance. */ - bool mBlendOutBeforeEnded; /**< Set to true if you want the motion to be stopped so that it exactly faded out when the motion/loop fully finished. If set to false it will fade out after the loop has completed (and starts repeating). The default is true. */ - bool mCanOverwrite; /**< Set to true if you want this motion to be able to delete other underlaying motion instances when this motion instance reaches a weight of 1.0.*/ - bool mDeleteOnZeroWeight; /**< Set to true if you wish to delete this motion instance once it reaches a weight of 0.0. */ - bool mInPlace; /**< Set to true if you want the motion to play in place. This means the root of the motion will not move. */ + float m_blendInTime; /**< The time, in seconds, which it will take to fully have blended to the target weight. */ + float m_blendOutTime; /**< The time, in seconds, which it takes to smoothly fadeout the motion, after it has been stopped playing. */ + float m_playSpeed; /**< The playback speed factor. A value of 1 stands for the original speed, while for example 2 means twice the original speed. */ + float m_targetWeight; /**< The target weight, where 1 means fully active, and 0 means not active at all. */ + float m_eventWeightThreshold; /**< The motion event weight threshold. If the motion instance weight is lower than this value, no motion events will be executed for this motion instance. */ + float m_maxPlayTime; /**< The maximum play time, in seconds. Set to zero or a negative value to disable it. */ + float m_clipStartTime; /**< The start playback time in seconds. Also in case of looping it will jump to this position on a loop. */ + float m_clipEndTime; /**< The end playback time in seconds. It will jump back to the clip start time after reaching this playback time. */ + float m_freezeAtTime; /**< Freeze at a given time offset in seconds. The current play time would continue running though, and a blend out would be triggered, unlike the m_freezeAtLastFrame. Set to negative value to disable. Default=-1.*/ + uint32 m_numLoops; /**< The number of times you want to play this motion. A value of EMFX_LOOPFOREVER means it will loop forever. */ + uint32 m_priorityLevel; /**< The priority level, the higher this value, the higher priority it has on overwriting other motions. */ + EMotionBlendMode m_blendMode; /**< The motion blend mode. Please read the MotionInstance::SetBlendMode(...) method for more information. */ + EPlayMode m_playMode; /**< The motion playback mode. This means forward or backward playback. */ + bool m_mirrorMotion; /**< Is motion mirroring enabled or not? When set to true, the m_mirrorPlaneNormal is used as mirroring axis. */ + bool m_mix; /**< Set to true if you want this motion to mix or not. */ + bool m_playNow; /**< Set to true if you want to start playing the motion right away. If set to false it will be scheduled for later by inserting it into the motion queue. */ + bool m_motionExtractionEnabled; /**< Set to true if you want this motion to move and rotate the actor instance, otherwise set to false. */ + bool m_retarget; /**< Set to true if you want to enable motion retargeting. Read the manual for more information. */ + bool m_freezeAtLastFrame; /**< Set to true if you like the motion to freeze at the last frame, for example in case of a death motion. */ + bool m_enableMotionEvents; /**< Set to true to enable motion events, or false to disable processing of motion events for this motion instance. */ + bool m_blendOutBeforeEnded; /**< Set to true if you want the motion to be stopped so that it exactly faded out when the motion/loop fully finished. If set to false it will fade out after the loop has completed (and starts repeating). The default is true. */ + bool m_canOverwrite; /**< Set to true if you want this motion to be able to delete other underlaying motion instances when this motion instance reaches a weight of 1.0.*/ + bool m_deleteOnZeroWeight; /**< Set to true if you wish to delete this motion instance once it reaches a weight of 0.0. */ + bool m_inPlace; /**< Set to true if you want the motion to play in place. This means the root of the motion will not move. */ }; } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Pose.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Pose.cpp index b9f223eded..23390bf69b 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Pose.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Pose.cpp @@ -21,19 +21,13 @@ namespace EMotionFX // default constructor Pose::Pose() { - mActorInstance = nullptr; - mActor = nullptr; - mSkeleton = nullptr; - mLocalSpaceTransforms.SetMemoryCategory(EMFX_MEMCATEGORY_ANIMGRAPH_POSE); - mModelSpaceTransforms.SetMemoryCategory(EMFX_MEMCATEGORY_ANIMGRAPH_POSE); - mFlags.SetMemoryCategory(EMFX_MEMCATEGORY_ANIMGRAPH_POSE); - mMorphWeights.SetMemoryCategory(EMFX_MEMCATEGORY_ANIMGRAPH_POSE); - - // reset morph weights - //mMorphWeights.Reserve(32); - //mLocalSpaceTransforms.Reserve(128); - //mModelSpaceTransforms.Reserve(128); - //mFlags.Reserve(128); + m_actorInstance = nullptr; + m_actor = nullptr; + m_skeleton = nullptr; + m_localSpaceTransforms.SetMemoryCategory(EMFX_MEMCATEGORY_ANIMGRAPH_POSE); + m_modelSpaceTransforms.SetMemoryCategory(EMFX_MEMCATEGORY_ANIMGRAPH_POSE); + m_flags.SetMemoryCategory(EMFX_MEMCATEGORY_ANIMGRAPH_POSE); + m_morphWeights.SetMemoryCategory(EMFX_MEMCATEGORY_ANIMGRAPH_POSE); } @@ -55,16 +49,16 @@ namespace EMotionFX void Pose::LinkToActorInstance(const ActorInstance* actorInstance, uint8 initialFlags) { // store the pointer to the actor instance etc - mActorInstance = actorInstance; - mActor = actorInstance->GetActor(); - mSkeleton = mActor->GetSkeleton(); + m_actorInstance = actorInstance; + m_actor = actorInstance->GetActor(); + m_skeleton = m_actor->GetSkeleton(); // resize the buffers - const size_t numTransforms = mActor->GetSkeleton()->GetNumNodes(); - mLocalSpaceTransforms.ResizeFast(numTransforms); - mModelSpaceTransforms.ResizeFast(numTransforms); - mFlags.ResizeFast(numTransforms); - mMorphWeights.ResizeFast(actorInstance->GetMorphSetupInstance()->GetNumMorphTargets()); + const size_t numTransforms = m_actor->GetSkeleton()->GetNumNodes(); + m_localSpaceTransforms.ResizeFast(numTransforms); + m_modelSpaceTransforms.ResizeFast(numTransforms); + m_flags.ResizeFast(numTransforms); + m_morphWeights.ResizeFast(actorInstance->GetMorphSetupInstance()->GetNumMorphTargets()); for (const auto& poseDataItem : m_poseDatas) { @@ -79,27 +73,27 @@ namespace EMotionFX // link the pose to a given actor void Pose::LinkToActor(const Actor* actor, uint8 initialFlags, bool clearAllFlags) { - mActorInstance = nullptr; - mActor = actor; - mSkeleton = actor->GetSkeleton(); + m_actorInstance = nullptr; + m_actor = actor; + m_skeleton = actor->GetSkeleton(); // resize the buffers - const size_t numTransforms = mActor->GetSkeleton()->GetNumNodes(); - mLocalSpaceTransforms.ResizeFast(numTransforms); - mModelSpaceTransforms.ResizeFast(numTransforms); + const size_t numTransforms = m_actor->GetSkeleton()->GetNumNodes(); + m_localSpaceTransforms.ResizeFast(numTransforms); + m_modelSpaceTransforms.ResizeFast(numTransforms); - const size_t oldSize = mFlags.GetLength(); - mFlags.ResizeFast(numTransforms); + const size_t oldSize = m_flags.GetLength(); + m_flags.ResizeFast(numTransforms); if (oldSize < numTransforms && clearAllFlags == false) { for (size_t i = oldSize; i < numTransforms; ++i) { - mFlags[i] = initialFlags; + m_flags[i] = initialFlags; } } - MorphSetup* morphSetup = mActor->GetMorphSetup(0); - mMorphWeights.ResizeFast((morphSetup) ? morphSetup->GetNumMorphTargets() : 0); + MorphSetup* morphSetup = m_actor->GetMorphSetup(0); + m_morphWeights.ResizeFast((morphSetup) ? morphSetup->GetNumMorphTargets() : 0); for (const auto& poseDataItem : m_poseDatas) { @@ -117,15 +111,15 @@ namespace EMotionFX void Pose::SetNumTransforms(size_t numTransforms) { // resize the buffers - mLocalSpaceTransforms.ResizeFast(numTransforms); - mModelSpaceTransforms.ResizeFast(numTransforms); + m_localSpaceTransforms.ResizeFast(numTransforms); + m_modelSpaceTransforms.ResizeFast(numTransforms); - const size_t oldSize = mFlags.GetLength(); - mFlags.ResizeFast(numTransforms); + const size_t oldSize = m_flags.GetLength(); + m_flags.ResizeFast(numTransforms); for (size_t i = oldSize; i < numTransforms; ++i) { - mFlags[i] = 0; + m_flags[i] = 0; SetLocalSpaceTransform(i, Transform::CreateIdentity()); } } @@ -133,10 +127,10 @@ namespace EMotionFX void Pose::Clear(bool clearMem) { - mLocalSpaceTransforms.Clear(clearMem); - mModelSpaceTransforms.Clear(clearMem); - mFlags.Clear(clearMem); - mMorphWeights.Clear(clearMem); + m_localSpaceTransforms.Clear(clearMem); + m_modelSpaceTransforms.Clear(clearMem); + m_flags.Clear(clearMem); + m_morphWeights.Clear(clearMem); ClearPoseDatas(); } @@ -145,25 +139,10 @@ namespace EMotionFX // clear the pose flags void Pose::ClearFlags(uint8 newFlags) { - MCore::MemSet((uint8*)mFlags.GetPtr(), newFlags, sizeof(uint8) * mFlags.GetLength()); + MCore::MemSet((uint8*)m_flags.GetPtr(), newFlags, sizeof(uint8) * m_flags.GetLength()); } - /* - // init from a set of local space transformations - void Pose::InitFromLocalTransforms(ActorInstance* actorInstance, const Transform* localTransforms) - { - // link to an actor instance - LinkToActorInstance( actorInstance, FLAG_LOCALTRANSFORMREADY ); - - // reset all flags - //MCore::MemSet( (uint8*)mFlags.GetPtr(), FLAG_LOCALTRANSFORMREADY, sizeof(uint8)*mFlags.GetLength() ); - - // copy over the local transforms - MCore::MemCopy((uint8*)mLocalTransforms.GetPtr(), (uint8*)localTransforms, sizeof(Transform)*mLocalTransforms.GetLength()); - } - */ - // initialize this pose to the bind pose void Pose::InitFromBindPose(const ActorInstance* actorInstance) { @@ -192,23 +171,23 @@ namespace EMotionFX // update the full local space pose void Pose::ForceUpdateFullLocalSpacePose() { - Skeleton* skeleton = mActor->GetSkeleton(); + Skeleton* skeleton = m_actor->GetSkeleton(); const size_t numNodes = skeleton->GetNumNodes(); for (size_t i = 0; i < numNodes; ++i) { const size_t parentIndex = skeleton->GetNode(i)->GetParentIndex(); if (parentIndex != InvalidIndex) { - GetModelSpaceTransform(parentIndex, &mLocalSpaceTransforms[i]); - mLocalSpaceTransforms[i].Inverse(); - mLocalSpaceTransforms[i].PreMultiply(mModelSpaceTransforms[i]); + GetModelSpaceTransform(parentIndex, &m_localSpaceTransforms[i]); + m_localSpaceTransforms[i].Inverse(); + m_localSpaceTransforms[i].PreMultiply(m_modelSpaceTransforms[i]); } else { - mLocalSpaceTransforms[i] = mModelSpaceTransforms[i]; + m_localSpaceTransforms[i] = m_modelSpaceTransforms[i]; } - mFlags[i] |= FLAG_LOCALTRANSFORMREADY; + m_flags[i] |= FLAG_LOCALTRANSFORMREADY; } } @@ -217,21 +196,21 @@ namespace EMotionFX void Pose::ForceUpdateFullModelSpacePose() { // iterate from root towards child nodes recursively, updating all model space transforms on the way - Skeleton* skeleton = mActor->GetSkeleton(); + Skeleton* skeleton = m_actor->GetSkeleton(); const size_t numNodes = skeleton->GetNumNodes(); for (size_t i = 0; i < numNodes; ++i) { const size_t parentIndex = skeleton->GetNode(i)->GetParentIndex(); if (parentIndex != InvalidIndex) { - mModelSpaceTransforms[parentIndex].PreMultiply(mLocalSpaceTransforms[i], &mModelSpaceTransforms[i]); + m_modelSpaceTransforms[parentIndex].PreMultiply(m_localSpaceTransforms[i], &m_modelSpaceTransforms[i]); } else { - mModelSpaceTransforms[i] = mLocalSpaceTransforms[i]; + m_modelSpaceTransforms[i] = m_localSpaceTransforms[i]; } - mFlags[i] |= FLAG_MODELTRANSFORMREADY; + m_flags[i] |= FLAG_MODELTRANSFORMREADY; } } @@ -239,28 +218,28 @@ namespace EMotionFX // recursively update void Pose::UpdateModelSpaceTransform(size_t nodeIndex) const { - Skeleton* skeleton = mActor->GetSkeleton(); + Skeleton* skeleton = m_actor->GetSkeleton(); const size_t parentIndex = skeleton->GetNode(nodeIndex)->GetParentIndex(); - if (parentIndex != InvalidIndex && !(mFlags[parentIndex] & FLAG_MODELTRANSFORMREADY)) + if (parentIndex != InvalidIndex && !(m_flags[parentIndex] & FLAG_MODELTRANSFORMREADY)) { UpdateModelSpaceTransform(parentIndex); } // update the model space transform if needed - if ((mFlags[nodeIndex] & FLAG_MODELTRANSFORMREADY) == false) + if ((m_flags[nodeIndex] & FLAG_MODELTRANSFORMREADY) == false) { const Transform& localTransform = GetLocalSpaceTransform(nodeIndex); if (parentIndex != InvalidIndex) { - mModelSpaceTransforms[parentIndex].PreMultiply(localTransform, &mModelSpaceTransforms[nodeIndex]); + m_modelSpaceTransforms[parentIndex].PreMultiply(localTransform, &m_modelSpaceTransforms[nodeIndex]); } else { - mModelSpaceTransforms[nodeIndex] = mLocalSpaceTransforms[nodeIndex]; + m_modelSpaceTransforms[nodeIndex] = m_localSpaceTransforms[nodeIndex]; } - mFlags[nodeIndex] |= FLAG_MODELTRANSFORMREADY; + m_flags[nodeIndex] |= FLAG_MODELTRANSFORMREADY; } } @@ -268,7 +247,7 @@ namespace EMotionFX // update the local transform void Pose::UpdateLocalSpaceTransform(size_t nodeIndex) const { - const uint8 flags = mFlags[nodeIndex]; + const uint8 flags = m_flags[nodeIndex]; if (flags & FLAG_LOCALTRANSFORMREADY) { return; @@ -276,20 +255,20 @@ namespace EMotionFX MCORE_ASSERT(flags & FLAG_MODELTRANSFORMREADY); // the model space transform has to be updated already, otherwise we cannot possibly calculate the local space one - Skeleton* skeleton = mActor->GetSkeleton(); + Skeleton* skeleton = m_actor->GetSkeleton(); const size_t parentIndex = skeleton->GetNode(nodeIndex)->GetParentIndex(); if (parentIndex != InvalidIndex) { - GetModelSpaceTransform(parentIndex, &mLocalSpaceTransforms[nodeIndex]); - mLocalSpaceTransforms[nodeIndex].Inverse(); - mLocalSpaceTransforms[nodeIndex].PreMultiply(mModelSpaceTransforms[nodeIndex]); + GetModelSpaceTransform(parentIndex, &m_localSpaceTransforms[nodeIndex]); + m_localSpaceTransforms[nodeIndex].Inverse(); + m_localSpaceTransforms[nodeIndex].PreMultiply(m_modelSpaceTransforms[nodeIndex]); } else { - mLocalSpaceTransforms[nodeIndex] = mModelSpaceTransforms[nodeIndex]; + m_localSpaceTransforms[nodeIndex] = m_modelSpaceTransforms[nodeIndex]; } - mFlags[nodeIndex] |= FLAG_LOCALTRANSFORMREADY; + m_flags[nodeIndex] |= FLAG_LOCALTRANSFORMREADY; } @@ -297,63 +276,63 @@ namespace EMotionFX const Transform& Pose::GetLocalSpaceTransform(size_t nodeIndex) const { UpdateLocalSpaceTransform(nodeIndex); - return mLocalSpaceTransforms[nodeIndex]; + return m_localSpaceTransforms[nodeIndex]; } const Transform& Pose::GetModelSpaceTransform(size_t nodeIndex) const { UpdateModelSpaceTransform(nodeIndex); - return mModelSpaceTransforms[nodeIndex]; + return m_modelSpaceTransforms[nodeIndex]; } Transform Pose::GetWorldSpaceTransform(size_t nodeIndex) const { UpdateModelSpaceTransform(nodeIndex); - return mModelSpaceTransforms[nodeIndex].Multiplied(mActorInstance->GetWorldSpaceTransform()); + return m_modelSpaceTransforms[nodeIndex].Multiplied(m_actorInstance->GetWorldSpaceTransform()); } void Pose::GetWorldSpaceTransform(size_t nodeIndex, Transform* outResult) const { UpdateModelSpaceTransform(nodeIndex); - *outResult = mModelSpaceTransforms[nodeIndex]; - outResult->Multiply(mActorInstance->GetWorldSpaceTransform()); + *outResult = m_modelSpaceTransforms[nodeIndex]; + outResult->Multiply(m_actorInstance->GetWorldSpaceTransform()); } // calculate a local transform void Pose::GetLocalSpaceTransform(size_t nodeIndex, Transform* outResult) const { - if ((mFlags[nodeIndex] & FLAG_LOCALTRANSFORMREADY) == false) + if ((m_flags[nodeIndex] & FLAG_LOCALTRANSFORMREADY) == false) { UpdateLocalSpaceTransform(nodeIndex); } - *outResult = mLocalSpaceTransforms[nodeIndex]; + *outResult = m_localSpaceTransforms[nodeIndex]; } void Pose::GetModelSpaceTransform(size_t nodeIndex, Transform* outResult) const { UpdateModelSpaceTransform(nodeIndex); - *outResult = mModelSpaceTransforms[nodeIndex]; + *outResult = m_modelSpaceTransforms[nodeIndex]; } // set the local transform void Pose::SetLocalSpaceTransform(size_t nodeIndex, const Transform& newTransform, bool invalidateGlobalTransforms) { - mLocalSpaceTransforms[nodeIndex] = newTransform; - mFlags[nodeIndex] |= FLAG_LOCALTRANSFORMREADY; + m_localSpaceTransforms[nodeIndex] = newTransform; + m_flags[nodeIndex] |= FLAG_LOCALTRANSFORMREADY; // mark all child node model space transforms as dirty (recursively) if (invalidateGlobalTransforms) { - if (mFlags[nodeIndex] & FLAG_MODELTRANSFORMREADY) + if (m_flags[nodeIndex] & FLAG_MODELTRANSFORMREADY) { - RecursiveInvalidateModelSpaceTransforms(mActor, nodeIndex); + RecursiveInvalidateModelSpaceTransforms(m_actor, nodeIndex); } } } @@ -363,13 +342,13 @@ namespace EMotionFX void Pose::RecursiveInvalidateModelSpaceTransforms(const Actor* actor, size_t nodeIndex) { // if this model space transform ain't ready yet assume all child nodes are also not - if ((mFlags[nodeIndex] & FLAG_MODELTRANSFORMREADY) == false) + if ((m_flags[nodeIndex] & FLAG_MODELTRANSFORMREADY) == false) { return; } // mark the global transform as invalid - mFlags[nodeIndex] &= ~FLAG_MODELTRANSFORMREADY; + m_flags[nodeIndex] &= ~FLAG_MODELTRANSFORMREADY; // recurse through all child nodes Skeleton* skeleton = actor->GetSkeleton(); @@ -384,34 +363,34 @@ namespace EMotionFX void Pose::SetModelSpaceTransform(size_t nodeIndex, const Transform& newTransform, bool invalidateChildGlobalTransforms) { - mModelSpaceTransforms[nodeIndex] = newTransform; + m_modelSpaceTransforms[nodeIndex] = newTransform; // invalidate the local transform - mFlags[nodeIndex] &= ~FLAG_LOCALTRANSFORMREADY; + m_flags[nodeIndex] &= ~FLAG_LOCALTRANSFORMREADY; // recursively invalidate all model space transforms of all child nodes if (invalidateChildGlobalTransforms) { - RecursiveInvalidateModelSpaceTransforms(mActor, nodeIndex); + RecursiveInvalidateModelSpaceTransforms(m_actor, nodeIndex); } // mark this model space transform as ready - mFlags[nodeIndex] |= FLAG_MODELTRANSFORMREADY; + m_flags[nodeIndex] |= FLAG_MODELTRANSFORMREADY; UpdateLocalSpaceTransform(nodeIndex); } void Pose::SetWorldSpaceTransform(size_t nodeIndex, const Transform& newTransform, bool invalidateChildGlobalTransforms) { - mModelSpaceTransforms[nodeIndex] = newTransform.Multiplied(mActorInstance->GetWorldSpaceTransformInversed()); - mFlags[nodeIndex] &= ~FLAG_LOCALTRANSFORMREADY; + m_modelSpaceTransforms[nodeIndex] = newTransform.Multiplied(m_actorInstance->GetWorldSpaceTransformInversed()); + m_flags[nodeIndex] &= ~FLAG_LOCALTRANSFORMREADY; if (invalidateChildGlobalTransforms) { - RecursiveInvalidateModelSpaceTransforms(mActor, nodeIndex); + RecursiveInvalidateModelSpaceTransforms(m_actor, nodeIndex); } - mFlags[nodeIndex] |= FLAG_MODELTRANSFORMREADY; + m_flags[nodeIndex] |= FLAG_MODELTRANSFORMREADY; UpdateLocalSpaceTransform(nodeIndex); } @@ -419,38 +398,38 @@ namespace EMotionFX // invalidate all local transforms void Pose::InvalidateAllLocalSpaceTransforms() { - const size_t numFlags = mFlags.GetLength(); + const size_t numFlags = m_flags.GetLength(); for (size_t i = 0; i < numFlags; ++i) { - mFlags[i] &= ~FLAG_LOCALTRANSFORMREADY; + m_flags[i] &= ~FLAG_LOCALTRANSFORMREADY; } } void Pose::InvalidateAllModelSpaceTransforms() { - const size_t numFlags = mFlags.GetLength(); + const size_t numFlags = m_flags.GetLength(); for (size_t i = 0; i < numFlags; ++i) { - mFlags[i] &= ~FLAG_MODELTRANSFORMREADY; + m_flags[i] &= ~FLAG_MODELTRANSFORMREADY; } } void Pose::InvalidateAllLocalAndModelSpaceTransforms() { - const size_t numFlags = mFlags.GetLength(); + const size_t numFlags = m_flags.GetLength(); for (size_t i = 0; i < numFlags; ++i) { - mFlags[i] &= ~(FLAG_LOCALTRANSFORMREADY | FLAG_MODELTRANSFORMREADY); + m_flags[i] &= ~(FLAG_LOCALTRANSFORMREADY | FLAG_MODELTRANSFORMREADY); } } Transform Pose::CalcTrajectoryTransform() const { - MCORE_ASSERT(mActor); - const size_t motionExtractionNodeIndex = mActor->GetMotionExtractionNodeIndex(); + MCORE_ASSERT(m_actor); + const size_t motionExtractionNodeIndex = m_actor->GetMotionExtractionNodeIndex(); if (motionExtractionNodeIndex == InvalidIndex) { return Transform::CreateIdentity(); @@ -462,7 +441,7 @@ namespace EMotionFX void Pose::UpdateAllLocalSpaceTranforms() { - Skeleton* skeleton = mActor->GetSkeleton(); + Skeleton* skeleton = m_actor->GetSkeleton(); const size_t numNodes = skeleton->GetNumNodes(); for (size_t i = 0; i < numNodes; ++i) { @@ -473,7 +452,7 @@ namespace EMotionFX void Pose::UpdateAllModelSpaceTranforms() { - Skeleton* skeleton = mActor->GetSkeleton(); + Skeleton* skeleton = m_actor->GetSkeleton(); const size_t numNodes = skeleton->GetNumNodes(); for (size_t i = 0; i < numNodes; ++i) { @@ -490,8 +469,8 @@ namespace EMotionFX // make sure the number of transforms are equal MCORE_ASSERT(destPose); MCORE_ASSERT(outPose); - MCORE_ASSERT(mLocalSpaceTransforms.GetLength() == destPose->mLocalSpaceTransforms.GetLength()); - MCORE_ASSERT(mLocalSpaceTransforms.GetLength() == outPose->mLocalSpaceTransforms.GetLength()); + MCORE_ASSERT(m_localSpaceTransforms.GetLength() == destPose->m_localSpaceTransforms.GetLength()); + MCORE_ASSERT(m_localSpaceTransforms.GetLength() == outPose->m_localSpaceTransforms.GetLength()); MCORE_ASSERT(instance->GetIsMixing() == false); // get some motion instance properties which we use to decide the optimized blending routine @@ -530,12 +509,12 @@ namespace EMotionFX } // blend the morph weights - const size_t numMorphs = mMorphWeights.GetLength(); + const size_t numMorphs = m_morphWeights.GetLength(); MCORE_ASSERT(actorInstance->GetMorphSetupInstance()->GetNumMorphTargets() == numMorphs); MCORE_ASSERT(numMorphs == destPose->GetNumMorphWeights()); for (size_t i = 0; i < numMorphs; ++i) { - mMorphWeights[i] = MCore::LinearInterpolate(mMorphWeights[i], destPose->mMorphWeights[i], weight); + m_morphWeights[i] = MCore::LinearInterpolate(m_morphWeights[i], destPose->m_morphWeights[i], weight); } } else @@ -554,12 +533,12 @@ namespace EMotionFX outPose->InvalidateAllModelSpaceTransforms(); // blend the morph weights - const size_t numMorphs = mMorphWeights.GetLength(); + const size_t numMorphs = m_morphWeights.GetLength(); MCORE_ASSERT(actorInstance->GetMorphSetupInstance()->GetNumMorphTargets() == numMorphs); MCORE_ASSERT(numMorphs == destPose->GetNumMorphWeights()); for (size_t i = 0; i < numMorphs; ++i) { - mMorphWeights[i] += destPose->mMorphWeights[i] * weight; + m_morphWeights[i] += destPose->m_morphWeights[i] * weight; } } } @@ -571,8 +550,8 @@ namespace EMotionFX // make sure the number of transforms are equal MCORE_ASSERT(destPose); MCORE_ASSERT(outPose); - MCORE_ASSERT(mLocalSpaceTransforms.GetLength() == destPose->mLocalSpaceTransforms.GetLength()); - MCORE_ASSERT(mLocalSpaceTransforms.GetLength() == outPose->mLocalSpaceTransforms.GetLength()); + MCORE_ASSERT(m_localSpaceTransforms.GetLength() == destPose->m_localSpaceTransforms.GetLength()); + MCORE_ASSERT(m_localSpaceTransforms.GetLength() == outPose->m_localSpaceTransforms.GetLength()); MCORE_ASSERT(instance->GetIsMixing()); const bool additive = (instance->GetBlendMode() == BLENDMODE_ADDITIVE); @@ -585,7 +564,7 @@ namespace EMotionFX Transform result; const MotionLinkData* motionLinkData = instance->GetMotion()->GetMotionData()->FindMotionLinkData(actorInstance->GetActor()); - AZ_Assert(motionLinkData->GetJointDataLinks().size() == mLocalSpaceTransforms.GetLength(), "Expecting there to be the same amount of motion links as pose transforms."); + AZ_Assert(motionLinkData->GetJointDataLinks().size() == m_localSpaceTransforms.GetLength(), "Expecting there to be the same amount of motion links as pose transforms."); // blend all transforms if (!additive) @@ -610,12 +589,12 @@ namespace EMotionFX outPose->InvalidateAllModelSpaceTransforms(); // blend the morph weights - const size_t numMorphs = mMorphWeights.GetLength(); + const size_t numMorphs = m_morphWeights.GetLength(); MCORE_ASSERT(actorInstance->GetMorphSetupInstance()->GetNumMorphTargets() == numMorphs); MCORE_ASSERT(numMorphs == destPose->GetNumMorphWeights()); for (size_t i = 0; i < numMorphs; ++i) { - mMorphWeights[i] = MCore::LinearInterpolate(mMorphWeights[i], destPose->mMorphWeights[i], weight); + m_morphWeights[i] = MCore::LinearInterpolate(m_morphWeights[i], destPose->m_morphWeights[i], weight); } } else @@ -640,12 +619,12 @@ namespace EMotionFX outPose->InvalidateAllModelSpaceTransforms(); // blend the morph weights - const size_t numMorphs = mMorphWeights.GetLength(); + const size_t numMorphs = m_morphWeights.GetLength(); MCORE_ASSERT(actorInstance->GetMorphSetupInstance()->GetNumMorphTargets() == numMorphs); MCORE_ASSERT(numMorphs == destPose->GetNumMorphWeights()); for (size_t i = 0; i < numMorphs; ++i) { - mMorphWeights[i] += destPose->mMorphWeights[i] * weight; + m_morphWeights[i] += destPose->m_morphWeights[i] * weight; } } } @@ -656,22 +635,22 @@ namespace EMotionFX { if (!sourcePose) { - if (mActorInstance) + if (m_actorInstance) { - InitFromBindPose(mActorInstance); + InitFromBindPose(m_actorInstance); } else { - InitFromBindPose(mActor); + InitFromBindPose(m_actor); } return; } - mModelSpaceTransforms.MemCopyContentsFrom(sourcePose->mModelSpaceTransforms); - mLocalSpaceTransforms.MemCopyContentsFrom(sourcePose->mLocalSpaceTransforms); - mFlags.MemCopyContentsFrom(sourcePose->mFlags); - mMorphWeights.MemCopyContentsFrom(sourcePose->mMorphWeights); + m_modelSpaceTransforms.MemCopyContentsFrom(sourcePose->m_modelSpaceTransforms); + m_localSpaceTransforms.MemCopyContentsFrom(sourcePose->m_localSpaceTransforms); + m_flags.MemCopyContentsFrom(sourcePose->m_flags); + m_morphWeights.MemCopyContentsFrom(sourcePose->m_morphWeights); // Deactivate pose datas from the current pose that are not in the source that we copy from. // This is needed in order to prevent leftover pose datas and to avoid de-/allocations. @@ -739,35 +718,35 @@ namespace EMotionFX // reset all transforms to zero void Pose::Zero() { - if (mActorInstance) + if (m_actorInstance) { - const size_t numNodes = mActorInstance->GetNumEnabledNodes(); + const size_t numNodes = m_actorInstance->GetNumEnabledNodes(); for (size_t i = 0; i < numNodes; ++i) { - const uint16 nodeNr = mActorInstance->GetEnabledNode(i); - mLocalSpaceTransforms[nodeNr].Zero(); + const uint16 nodeNr = m_actorInstance->GetEnabledNode(i); + m_localSpaceTransforms[nodeNr].Zero(); } - const size_t numMorphs = mMorphWeights.GetLength(); - MCORE_ASSERT(mActorInstance->GetMorphSetupInstance()->GetNumMorphTargets() == numMorphs); + const size_t numMorphs = m_morphWeights.GetLength(); + MCORE_ASSERT(m_actorInstance->GetMorphSetupInstance()->GetNumMorphTargets() == numMorphs); for (size_t i = 0; i < numMorphs; ++i) { - mMorphWeights[i] = 0.0f; + m_morphWeights[i] = 0.0f; } } else { - const size_t numNodes = mActor->GetSkeleton()->GetNumNodes(); + const size_t numNodes = m_actor->GetSkeleton()->GetNumNodes(); for (size_t i = 0; i < numNodes; ++i) { - mLocalSpaceTransforms[i].Zero(); + m_localSpaceTransforms[i].Zero(); } - const size_t numMorphs = mMorphWeights.GetLength(); - MCORE_ASSERT(mActor->GetMorphSetup(0)->GetNumMorphTargets() == numMorphs); + const size_t numMorphs = m_morphWeights.GetLength(); + MCORE_ASSERT(m_actor->GetMorphSetup(0)->GetNumMorphTargets() == numMorphs); for (size_t i = 0; i < numMorphs; ++i) { - mMorphWeights[i] = 0.0f; + m_morphWeights[i] = 0.0f; } } @@ -778,23 +757,23 @@ namespace EMotionFX // normalize all quaternions void Pose::NormalizeQuaternions() { - if (mActorInstance) + if (m_actorInstance) { - const size_t numNodes = mActorInstance->GetNumEnabledNodes(); + const size_t numNodes = m_actorInstance->GetNumEnabledNodes(); for (size_t i = 0; i < numNodes; ++i) { - const uint16 nodeNr = mActorInstance->GetEnabledNode(i); + const uint16 nodeNr = m_actorInstance->GetEnabledNode(i); UpdateLocalSpaceTransform(nodeNr); - mLocalSpaceTransforms[nodeNr].mRotation.Normalize(); + m_localSpaceTransforms[nodeNr].m_rotation.Normalize(); } } else { - const size_t numNodes = mActor->GetSkeleton()->GetNumNodes(); + const size_t numNodes = m_actor->GetSkeleton()->GetNumNodes(); for (size_t i = 0; i < numNodes; ++i) { UpdateLocalSpaceTransform(i); - mLocalSpaceTransforms[i].mRotation.Normalize(); + m_localSpaceTransforms[i].m_rotation.Normalize(); } } } @@ -803,12 +782,12 @@ namespace EMotionFX // add the transforms of another pose to this one void Pose::Sum(const Pose* other, float weight) { - if (mActorInstance) + if (m_actorInstance) { - const size_t numNodes = mActorInstance->GetNumEnabledNodes(); + const size_t numNodes = m_actorInstance->GetNumEnabledNodes(); for (size_t i = 0; i < numNodes; ++i) { - const uint16 nodeNr = mActorInstance->GetEnabledNode(i); + const uint16 nodeNr = m_actorInstance->GetEnabledNode(i); Transform& transform = const_cast(GetLocalSpaceTransform(nodeNr)); const Transform& otherTransform = other->GetLocalSpaceTransform(nodeNr); @@ -816,17 +795,17 @@ namespace EMotionFX } // blend the morph weights - const size_t numMorphs = mMorphWeights.GetLength(); - MCORE_ASSERT(mActorInstance->GetMorphSetupInstance()->GetNumMorphTargets() == numMorphs); + const size_t numMorphs = m_morphWeights.GetLength(); + MCORE_ASSERT(m_actorInstance->GetMorphSetupInstance()->GetNumMorphTargets() == numMorphs); MCORE_ASSERT(numMorphs == other->GetNumMorphWeights()); for (size_t i = 0; i < numMorphs; ++i) { - mMorphWeights[i] += other->mMorphWeights[i] * weight; + m_morphWeights[i] += other->m_morphWeights[i] * weight; } } else { - const size_t numNodes = mActor->GetSkeleton()->GetNumNodes(); + const size_t numNodes = m_actor->GetSkeleton()->GetNumNodes(); for (size_t i = 0; i < numNodes; ++i) { Transform& transform = const_cast(GetLocalSpaceTransform(i)); @@ -835,12 +814,12 @@ namespace EMotionFX } // blend the morph weights - const size_t numMorphs = mMorphWeights.GetLength(); - MCORE_ASSERT(mActor->GetMorphSetup(0)->GetNumMorphTargets() == numMorphs); + const size_t numMorphs = m_morphWeights.GetLength(); + MCORE_ASSERT(m_actor->GetMorphSetup(0)->GetNumMorphTargets() == numMorphs); MCORE_ASSERT(numMorphs == other->GetNumMorphWeights()); for (size_t i = 0; i < numMorphs; ++i) { - mMorphWeights[i] += other->mMorphWeights[i] * weight; + m_morphWeights[i] += other->m_morphWeights[i] * weight; } } @@ -851,23 +830,23 @@ namespace EMotionFX // blend, without motion instance void Pose::Blend(const Pose* destPose, float weight) { - if (mActorInstance) + if (m_actorInstance) { - const size_t numNodes = mActorInstance->GetNumEnabledNodes(); + const size_t numNodes = m_actorInstance->GetNumEnabledNodes(); for (size_t i = 0; i < numNodes; ++i) { - const uint16 nodeNr = mActorInstance->GetEnabledNode(i); + const uint16 nodeNr = m_actorInstance->GetEnabledNode(i); Transform& curTransform = const_cast(GetLocalSpaceTransform(nodeNr)); curTransform.Blend(destPose->GetLocalSpaceTransform(nodeNr), weight); } // blend the morph weights - const size_t numMorphs = mMorphWeights.GetLength(); - MCORE_ASSERT(mActorInstance->GetMorphSetupInstance()->GetNumMorphTargets() == numMorphs); + const size_t numMorphs = m_morphWeights.GetLength(); + MCORE_ASSERT(m_actorInstance->GetMorphSetupInstance()->GetNumMorphTargets() == numMorphs); MCORE_ASSERT(numMorphs == destPose->GetNumMorphWeights()); for (size_t i = 0; i < numMorphs; ++i) { - mMorphWeights[i] = MCore::LinearInterpolate(mMorphWeights[i], destPose->mMorphWeights[i], weight); + m_morphWeights[i] = MCore::LinearInterpolate(m_morphWeights[i], destPose->m_morphWeights[i], weight); } for (const auto& poseDataItem : m_poseDatas) @@ -878,7 +857,7 @@ namespace EMotionFX } else { - const size_t numNodes = mActor->GetSkeleton()->GetNumNodes(); + const size_t numNodes = m_actor->GetSkeleton()->GetNumNodes(); for (size_t i = 0; i < numNodes; ++i) { Transform& curTransform = const_cast(GetLocalSpaceTransform(i)); @@ -886,12 +865,12 @@ namespace EMotionFX } // blend the morph weights - const size_t numMorphs = mMorphWeights.GetLength(); - MCORE_ASSERT(mActor->GetMorphSetup(0)->GetNumMorphTargets() == numMorphs); + const size_t numMorphs = m_morphWeights.GetLength(); + MCORE_ASSERT(m_actor->GetMorphSetup(0)->GetNumMorphTargets() == numMorphs); MCORE_ASSERT(numMorphs == destPose->GetNumMorphWeights()); for (size_t i = 0; i < numMorphs; ++i) { - mMorphWeights[i] = MCore::LinearInterpolate(mMorphWeights[i], destPose->mMorphWeights[i], weight); + m_morphWeights[i] = MCore::LinearInterpolate(m_morphWeights[i], destPose->m_morphWeights[i], weight); } for (const auto& poseDataItem : m_poseDatas) @@ -907,20 +886,20 @@ namespace EMotionFX Pose& Pose::MakeRelativeTo(const Pose& other) { - AZ_Assert(mLocalSpaceTransforms.GetLength() == other.mLocalSpaceTransforms.GetLength(), "Poses must be of the same size"); - if (mActorInstance) + AZ_Assert(m_localSpaceTransforms.GetLength() == other.m_localSpaceTransforms.GetLength(), "Poses must be of the same size"); + if (m_actorInstance) { - const size_t numNodes = mActorInstance->GetNumEnabledNodes(); + const size_t numNodes = m_actorInstance->GetNumEnabledNodes(); for (size_t i = 0; i < numNodes; ++i) { - const uint16 nodeNr = mActorInstance->GetEnabledNode(i); + const uint16 nodeNr = m_actorInstance->GetEnabledNode(i); Transform& transform = const_cast(GetLocalSpaceTransform(nodeNr)); transform = transform.CalcRelativeTo(other.GetLocalSpaceTransform(nodeNr)); } } else { - const size_t numNodes = mLocalSpaceTransforms.GetLength(); + const size_t numNodes = m_localSpaceTransforms.GetLength(); for (size_t i = 0; i < numNodes; ++i) { Transform& transform = const_cast(GetLocalSpaceTransform(i)); @@ -928,11 +907,11 @@ namespace EMotionFX } } - const size_t numMorphs = mMorphWeights.GetLength(); + const size_t numMorphs = m_morphWeights.GetLength(); AZ_Assert(numMorphs == other.GetNumMorphWeights(), "Number of morphs in the pose doesn't match the number of morphs inside the provided input pose."); for (size_t i = 0; i < numMorphs; ++i) { - mMorphWeights[i] -= other.mMorphWeights[i]; + m_morphWeights[i] -= other.m_morphWeights[i]; } InvalidateAllModelSpaceTransforms(); @@ -942,8 +921,8 @@ namespace EMotionFX Pose& Pose::ApplyAdditive(const Pose& additivePose, float weight) { - AZ_Assert(mLocalSpaceTransforms.GetLength() == additivePose.mLocalSpaceTransforms.GetLength(), "Poses must be of the same size"); - if (mActorInstance) + AZ_Assert(m_localSpaceTransforms.GetLength() == additivePose.m_localSpaceTransforms.GetLength(), "Poses must be of the same size"); + if (m_actorInstance) { AZ_Assert(weight > -MCore::Math::epsilon && weight < (1 + MCore::Math::epsilon), "Expected weight to be between 0..1"); } @@ -960,46 +939,46 @@ namespace EMotionFX } else { - AZ_Assert(mLocalSpaceTransforms.GetLength() == additivePose.mLocalSpaceTransforms.GetLength(), "Poses must be of the same size"); - if (mActorInstance) + AZ_Assert(m_localSpaceTransforms.GetLength() == additivePose.m_localSpaceTransforms.GetLength(), "Poses must be of the same size"); + if (m_actorInstance) { - const size_t numNodes = mActorInstance->GetNumEnabledNodes(); + const size_t numNodes = m_actorInstance->GetNumEnabledNodes(); for (size_t i = 0; i < numNodes; ++i) { - uint16 nodeNr = mActorInstance->GetEnabledNode(i); + uint16 nodeNr = m_actorInstance->GetEnabledNode(i); Transform& transform = const_cast(GetLocalSpaceTransform(nodeNr)); const Transform& additiveTransform = additivePose.GetLocalSpaceTransform(nodeNr); - transform.mPosition += additiveTransform.mPosition * weight; - transform.mRotation = transform.mRotation.NLerp(additiveTransform.mRotation * transform.mRotation, weight); + transform.m_position += additiveTransform.m_position * weight; + transform.m_rotation = transform.m_rotation.NLerp(additiveTransform.m_rotation * transform.m_rotation, weight); EMFX_SCALECODE ( - transform.mScale *= AZ::Vector3::CreateOne().Lerp(additiveTransform.mScale, weight); + transform.m_scale *= AZ::Vector3::CreateOne().Lerp(additiveTransform.m_scale, weight); ) - transform.mRotation.Normalize(); + transform.m_rotation.Normalize(); } } else { - const size_t numNodes = mLocalSpaceTransforms.GetLength(); + const size_t numNodes = m_localSpaceTransforms.GetLength(); for (size_t i = 0; i < numNodes; ++i) { Transform& transform = const_cast(GetLocalSpaceTransform(i)); const Transform& additiveTransform = additivePose.GetLocalSpaceTransform(i); - transform.mPosition += additiveTransform.mPosition * weight; - transform.mRotation = transform.mRotation.NLerp(additiveTransform.mRotation * transform.mRotation, weight); + transform.m_position += additiveTransform.m_position * weight; + transform.m_rotation = transform.m_rotation.NLerp(additiveTransform.m_rotation * transform.m_rotation, weight); EMFX_SCALECODE ( - transform.mScale *= AZ::Vector3::CreateOne().Lerp(additiveTransform.mScale, weight); + transform.m_scale *= AZ::Vector3::CreateOne().Lerp(additiveTransform.m_scale, weight); ) - transform.mRotation.Normalize(); + transform.m_rotation.Normalize(); } } - const size_t numMorphs = mMorphWeights.GetLength(); + const size_t numMorphs = m_morphWeights.GetLength(); AZ_Assert(numMorphs == additivePose.GetNumMorphWeights(), "Number of morphs in the pose doesn't match the number of morphs inside the provided input pose."); for (size_t i = 0; i < numMorphs; ++i) { - mMorphWeights[i] += additivePose.mMorphWeights[i] * weight; + m_morphWeights[i] += additivePose.m_morphWeights[i] * weight; } InvalidateAllModelSpaceTransforms(); @@ -1010,46 +989,46 @@ namespace EMotionFX Pose& Pose::ApplyAdditive(const Pose& additivePose) { - AZ_Assert(mLocalSpaceTransforms.GetLength() == additivePose.mLocalSpaceTransforms.GetLength(), "Poses must be of the same size"); - if (mActorInstance) + AZ_Assert(m_localSpaceTransforms.GetLength() == additivePose.m_localSpaceTransforms.GetLength(), "Poses must be of the same size"); + if (m_actorInstance) { - const size_t numNodes = mActorInstance->GetNumEnabledNodes(); + const size_t numNodes = m_actorInstance->GetNumEnabledNodes(); for (size_t i = 0; i < numNodes; ++i) { - uint16 nodeNr = mActorInstance->GetEnabledNode(i); + uint16 nodeNr = m_actorInstance->GetEnabledNode(i); Transform& transform = const_cast(GetLocalSpaceTransform(nodeNr)); const Transform& additiveTransform = additivePose.GetLocalSpaceTransform(nodeNr); - transform.mPosition += additiveTransform.mPosition; - transform.mRotation = transform.mRotation * additiveTransform.mRotation; + transform.m_position += additiveTransform.m_position; + transform.m_rotation = transform.m_rotation * additiveTransform.m_rotation; EMFX_SCALECODE ( - transform.mScale *= additiveTransform.mScale; + transform.m_scale *= additiveTransform.m_scale; ) - transform.mRotation.Normalize(); + transform.m_rotation.Normalize(); } } else { - const size_t numNodes = mLocalSpaceTransforms.GetLength(); + const size_t numNodes = m_localSpaceTransforms.GetLength(); for (size_t i = 0; i < numNodes; ++i) { Transform& transform = const_cast(GetLocalSpaceTransform(i)); const Transform& additiveTransform = additivePose.GetLocalSpaceTransform(i); - transform.mPosition += additiveTransform.mPosition; - transform.mRotation = transform.mRotation * additiveTransform.mRotation; + transform.m_position += additiveTransform.m_position; + transform.m_rotation = transform.m_rotation * additiveTransform.m_rotation; EMFX_SCALECODE ( - transform.mScale *= additiveTransform.mScale; + transform.m_scale *= additiveTransform.m_scale; ) - transform.mRotation.Normalize(); + transform.m_rotation.Normalize(); } } - const size_t numMorphs = mMorphWeights.GetLength(); + const size_t numMorphs = m_morphWeights.GetLength(); AZ_Assert(numMorphs == additivePose.GetNumMorphWeights(), "Number of morphs in the pose doesn't match the number of morphs inside the provided input pose."); for (size_t i = 0; i < numMorphs; ++i) { - mMorphWeights[i] += additivePose.mMorphWeights[i]; + m_morphWeights[i] += additivePose.m_morphWeights[i]; } InvalidateAllModelSpaceTransforms(); @@ -1059,44 +1038,44 @@ namespace EMotionFX Pose& Pose::MakeAdditive(const Pose& refPose) { - AZ_Assert(mLocalSpaceTransforms.GetLength() == refPose.mLocalSpaceTransforms.GetLength(), "Poses must be of the same size"); - if (mActorInstance) + AZ_Assert(m_localSpaceTransforms.GetLength() == refPose.m_localSpaceTransforms.GetLength(), "Poses must be of the same size"); + if (m_actorInstance) { - const size_t numNodes = mActorInstance->GetNumEnabledNodes(); + const size_t numNodes = m_actorInstance->GetNumEnabledNodes(); for (size_t i = 0; i < numNodes; ++i) { - uint16 nodeNr = mActorInstance->GetEnabledNode(i); + uint16 nodeNr = m_actorInstance->GetEnabledNode(i); Transform& transform = const_cast(GetLocalSpaceTransform(nodeNr)); const Transform& refTransform = refPose.GetLocalSpaceTransform(nodeNr); - transform.mPosition = transform.mPosition - refTransform.mPosition; - transform.mRotation = refTransform.mRotation.GetConjugate() * transform.mRotation; + transform.m_position = transform.m_position - refTransform.m_position; + transform.m_rotation = refTransform.m_rotation.GetConjugate() * transform.m_rotation; EMFX_SCALECODE ( - transform.mScale *= refTransform.mScale; + transform.m_scale *= refTransform.m_scale; ) } } else { - const size_t numNodes = mLocalSpaceTransforms.GetLength(); + const size_t numNodes = m_localSpaceTransforms.GetLength(); for (size_t i = 0; i < numNodes; ++i) { Transform& transform = const_cast(GetLocalSpaceTransform(i)); const Transform& refTransform = refPose.GetLocalSpaceTransform(i); - transform.mPosition = transform.mPosition - refTransform.mPosition; - transform.mRotation = refTransform.mRotation.GetConjugate() * transform.mRotation; + transform.m_position = transform.m_position - refTransform.m_position; + transform.m_rotation = refTransform.m_rotation.GetConjugate() * transform.m_rotation; EMFX_SCALECODE ( - transform.mScale *= refTransform.mScale; + transform.m_scale *= refTransform.m_scale; ) } } - const size_t numMorphs = mMorphWeights.GetLength(); + const size_t numMorphs = m_morphWeights.GetLength(); AZ_Assert(numMorphs == refPose.GetNumMorphWeights(), "Number of morphs in the pose doesn't match the number of morphs inside the provided input pose."); for (size_t i = 0; i < numMorphs; ++i) { - mMorphWeights[i] -= refPose.mMorphWeights[i]; + m_morphWeights[i] -= refPose.m_morphWeights[i]; } InvalidateAllModelSpaceTransforms(); @@ -1107,36 +1086,36 @@ namespace EMotionFX // additive blend void Pose::BlendAdditiveUsingBindPose(const Pose* destPose, float weight) { - if (mActorInstance) + if (m_actorInstance) { - const TransformData* transformData = mActorInstance->GetTransformData(); + const TransformData* transformData = m_actorInstance->GetTransformData(); Pose* bindPose = transformData->GetBindPose(); Transform result; - const size_t numNodes = mActorInstance->GetNumEnabledNodes(); + const size_t numNodes = m_actorInstance->GetNumEnabledNodes(); for (size_t i = 0; i < numNodes; ++i) { - const uint16 nodeNr = mActorInstance->GetEnabledNode(i); + const uint16 nodeNr = m_actorInstance->GetEnabledNode(i); BlendTransformAdditiveUsingBindPose(bindPose->GetLocalSpaceTransform(nodeNr), GetLocalSpaceTransform(nodeNr), destPose->GetLocalSpaceTransform(nodeNr), weight, &result); SetLocalSpaceTransform(nodeNr, result, false); } // blend the morph weights - const size_t numMorphs = mMorphWeights.GetLength(); - MCORE_ASSERT(mActorInstance->GetMorphSetupInstance()->GetNumMorphTargets() == numMorphs); + const size_t numMorphs = m_morphWeights.GetLength(); + MCORE_ASSERT(m_actorInstance->GetMorphSetupInstance()->GetNumMorphTargets() == numMorphs); MCORE_ASSERT(numMorphs == destPose->GetNumMorphWeights()); for (size_t i = 0; i < numMorphs; ++i) { - mMorphWeights[i] += destPose->mMorphWeights[i] * weight; + m_morphWeights[i] += destPose->m_morphWeights[i] * weight; } } else { - const TransformData* transformData = mActorInstance->GetTransformData(); + const TransformData* transformData = m_actorInstance->GetTransformData(); Pose* bindPose = transformData->GetBindPose(); Transform result; - const size_t numNodes = mActor->GetSkeleton()->GetNumNodes(); + const size_t numNodes = m_actor->GetSkeleton()->GetNumNodes(); for (size_t i = 0; i < numNodes; ++i) { BlendTransformAdditiveUsingBindPose(bindPose->GetLocalSpaceTransform(i), GetLocalSpaceTransform(i), destPose->GetLocalSpaceTransform(i), weight, &result); @@ -1144,12 +1123,12 @@ namespace EMotionFX } // blend the morph weights - const size_t numMorphs = mMorphWeights.GetLength(); - MCORE_ASSERT(mActor->GetMorphSetup(0)->GetNumMorphTargets() == numMorphs); + const size_t numMorphs = m_morphWeights.GetLength(); + MCORE_ASSERT(m_actor->GetMorphSetup(0)->GetNumMorphTargets() == numMorphs); MCORE_ASSERT(numMorphs == destPose->GetNumMorphWeights()); for (size_t i = 0; i < numMorphs; ++i) { - mMorphWeights[i] += destPose->mMorphWeights[i] * weight; + m_morphWeights[i] += destPose->m_morphWeights[i] * weight; } } @@ -1253,11 +1232,11 @@ namespace EMotionFX // compensate for motion extraction, basically making it in-place void Pose::CompensateForMotionExtractionDirect(EMotionExtractionFlags motionExtractionFlags) { - const size_t motionExtractionNodeIndex = mActor->GetMotionExtractionNodeIndex(); + const size_t motionExtractionNodeIndex = m_actor->GetMotionExtractionNodeIndex(); if (motionExtractionNodeIndex != InvalidIndex) { Transform motionExtractionNodeTransform = GetLocalSpaceTransformDirect(motionExtractionNodeIndex); - mActorInstance->MotionExtractionCompensate(motionExtractionNodeTransform, motionExtractionFlags); + m_actorInstance->MotionExtractionCompensate(motionExtractionNodeTransform, motionExtractionFlags); SetLocalSpaceTransformDirect(motionExtractionNodeIndex, motionExtractionNodeTransform); } } @@ -1266,11 +1245,11 @@ namespace EMotionFX // compensate for motion extraction, basically making it in-place void Pose::CompensateForMotionExtraction(EMotionExtractionFlags motionExtractionFlags) { - const size_t motionExtractionNodeIndex = mActor->GetMotionExtractionNodeIndex(); + const size_t motionExtractionNodeIndex = m_actor->GetMotionExtractionNodeIndex(); if (motionExtractionNodeIndex != InvalidIndex) { Transform motionExtractionNodeTransform = GetLocalSpaceTransform(motionExtractionNodeIndex); - mActorInstance->MotionExtractionCompensate(motionExtractionNodeTransform, motionExtractionFlags); + m_actorInstance->MotionExtractionCompensate(motionExtractionNodeTransform, motionExtractionFlags); SetLocalSpaceTransform(motionExtractionNodeIndex, motionExtractionNodeTransform); } } @@ -1279,14 +1258,14 @@ namespace EMotionFX // apply the morph target weights to the morph setup instance of the given actor instance void Pose::ApplyMorphWeightsToActorInstance() { - MorphSetupInstance* morphSetupInstance = mActorInstance->GetMorphSetupInstance(); + MorphSetupInstance* morphSetupInstance = m_actorInstance->GetMorphSetupInstance(); const size_t numMorphs = morphSetupInstance->GetNumMorphTargets(); for (size_t m = 0; m < numMorphs; ++m) { MorphSetupInstance::MorphTarget* morphTarget = morphSetupInstance->GetMorphTarget(m); if (morphTarget->GetIsInManualMode() == false) { - morphTarget->SetWeight(mMorphWeights[m]); + morphTarget->SetWeight(m_morphWeights[m]); } } } @@ -1295,29 +1274,29 @@ namespace EMotionFX // zero all morph weights void Pose::ZeroMorphWeights() { - const size_t numMorphs = mMorphWeights.GetLength(); + const size_t numMorphs = m_morphWeights.GetLength(); for (size_t m = 0; m < numMorphs; ++m) { - mMorphWeights[m] = 0.0f; + m_morphWeights[m] = 0.0f; } } void Pose::ResizeNumMorphs(size_t numMorphTargets) { - mMorphWeights.Resize(numMorphTargets); + m_morphWeights.Resize(numMorphTargets); } Pose& Pose::PreMultiply(const Pose& other) { - AZ_Assert(mLocalSpaceTransforms.GetLength() == other.mLocalSpaceTransforms.GetLength(), "Poses must be of the same size"); - if (mActorInstance) + AZ_Assert(m_localSpaceTransforms.GetLength() == other.m_localSpaceTransforms.GetLength(), "Poses must be of the same size"); + if (m_actorInstance) { - const size_t numNodes = mActorInstance->GetNumEnabledNodes(); + const size_t numNodes = m_actorInstance->GetNumEnabledNodes(); for (size_t i = 0; i < numNodes; ++i) { - const uint16 nodeNr = mActorInstance->GetEnabledNode(i); + const uint16 nodeNr = m_actorInstance->GetEnabledNode(i); Transform& transform = const_cast(GetLocalSpaceTransform(nodeNr)); Transform otherTransform = other.GetLocalSpaceTransform(nodeNr); transform = otherTransform * transform; @@ -1325,7 +1304,7 @@ namespace EMotionFX } else { - const size_t numNodes = mLocalSpaceTransforms.GetLength(); + const size_t numNodes = m_localSpaceTransforms.GetLength(); for (size_t i = 0; i < numNodes; ++i) { Transform& transform = const_cast(GetLocalSpaceTransform(i)); @@ -1341,20 +1320,20 @@ namespace EMotionFX Pose& Pose::Multiply(const Pose& other) { - AZ_Assert(mLocalSpaceTransforms.GetLength() == other.mLocalSpaceTransforms.GetLength(), "Poses must be of the same size"); - if (mActorInstance) + AZ_Assert(m_localSpaceTransforms.GetLength() == other.m_localSpaceTransforms.GetLength(), "Poses must be of the same size"); + if (m_actorInstance) { - const size_t numNodes = mActorInstance->GetNumEnabledNodes(); + const size_t numNodes = m_actorInstance->GetNumEnabledNodes(); for (size_t i = 0; i < numNodes; ++i) { - uint16 nodeNr = mActorInstance->GetEnabledNode(i); + uint16 nodeNr = m_actorInstance->GetEnabledNode(i); Transform& transform = const_cast(GetLocalSpaceTransform(nodeNr)); transform.Multiply(other.GetLocalSpaceTransform(nodeNr)); } } else { - const size_t numNodes = mLocalSpaceTransforms.GetLength(); + const size_t numNodes = m_localSpaceTransforms.GetLength(); for (size_t i = 0; i < numNodes; ++i) { Transform& transform = const_cast(GetLocalSpaceTransform(i)); @@ -1369,13 +1348,13 @@ namespace EMotionFX Pose& Pose::MultiplyInverse(const Pose& other) { - AZ_Assert(mLocalSpaceTransforms.GetLength() == other.mLocalSpaceTransforms.GetLength(), "Poses must be of the same size"); - if (mActorInstance) + AZ_Assert(m_localSpaceTransforms.GetLength() == other.m_localSpaceTransforms.GetLength(), "Poses must be of the same size"); + if (m_actorInstance) { - const size_t numNodes = mActorInstance->GetNumEnabledNodes(); + const size_t numNodes = m_actorInstance->GetNumEnabledNodes(); for (size_t i = 0; i < numNodes; ++i) { - uint16 nodeNr = mActorInstance->GetEnabledNode(i); + uint16 nodeNr = m_actorInstance->GetEnabledNode(i); Transform& transform = const_cast(GetLocalSpaceTransform(nodeNr)); Transform otherTransform = other.GetLocalSpaceTransform(nodeNr); otherTransform.Inverse(); @@ -1384,7 +1363,7 @@ namespace EMotionFX } else { - const size_t numNodes = mLocalSpaceTransforms.GetLength(); + const size_t numNodes = m_localSpaceTransforms.GetLength(); for (size_t i = 0; i < numNodes; ++i) { Transform& transform = const_cast(GetLocalSpaceTransform(i)); @@ -1401,15 +1380,15 @@ namespace EMotionFX Transform Pose::GetMeshNodeWorldSpaceTransform(size_t lodLevel, size_t nodeIndex) const { - if (!mActorInstance) + if (!m_actorInstance) { return Transform::CreateIdentity(); } - Actor* actor = mActorInstance->GetActor(); + Actor* actor = m_actorInstance->GetActor(); if (actor->CheckIfHasSkinningDeformer(lodLevel, nodeIndex)) { - return mActorInstance->GetWorldSpaceTransform(); + return m_actorInstance->GetWorldSpaceTransform(); } return GetWorldSpaceTransform(nodeIndex); @@ -1419,21 +1398,21 @@ namespace EMotionFX void Pose::Mirror(const MotionLinkData* motionLinkData) { AZ_Assert(motionLinkData, "Expecting valid motionLinkData pointer."); - AZ_Assert(mActorInstance, "Mirroring is only possible in combination with an actor instance."); + AZ_Assert(m_actorInstance, "Mirroring is only possible in combination with an actor instance."); - const Actor* actor = mActorInstance->GetActor(); - const TransformData* transformData = mActorInstance->GetTransformData(); + const Actor* actor = m_actorInstance->GetActor(); + const TransformData* transformData = m_actorInstance->GetTransformData(); const Pose* bindPose = transformData->GetBindPose(); const AZStd::vector& jointLinks = motionLinkData->GetJointDataLinks(); - AnimGraphPose* tempPose = GetEMotionFX().GetThreadData(mActorInstance->GetThreadIndex())->GetPosePool().RequestPose(mActorInstance); + AnimGraphPose* tempPose = GetEMotionFX().GetThreadData(m_actorInstance->GetThreadIndex())->GetPosePool().RequestPose(m_actorInstance); Pose& unmirroredPose = tempPose->GetPose(); unmirroredPose = *this; - const size_t numNodes = mActorInstance->GetNumEnabledNodes(); + const size_t numNodes = m_actorInstance->GetNumEnabledNodes(); for (size_t i = 0; i < numNodes; ++i) { - const size_t nodeNumber = mActorInstance->GetEnabledNode(i); + const size_t nodeNumber = m_actorInstance->GetEnabledNode(i); const size_t jointDataIndex = jointLinks[nodeNumber]; if (jointDataIndex == InvalidIndex) { @@ -1444,12 +1423,12 @@ namespace EMotionFX Transform mirrored = bindPose->GetLocalSpaceTransform(nodeNumber); AZ::Vector3 mirrorAxis = AZ::Vector3::CreateZero(); - mirrorAxis.SetElement(mirrorInfo.mAxis, 1.0f); - mirrored.ApplyDeltaMirrored(bindPose->GetLocalSpaceTransform(mirrorInfo.mSourceNode), unmirroredPose.GetLocalSpaceTransform(mirrorInfo.mSourceNode), mirrorAxis, mirrorInfo.mFlags); + mirrorAxis.SetElement(mirrorInfo.m_axis, 1.0f); + mirrored.ApplyDeltaMirrored(bindPose->GetLocalSpaceTransform(mirrorInfo.m_sourceNode), unmirroredPose.GetLocalSpaceTransform(mirrorInfo.m_sourceNode), mirrorAxis, mirrorInfo.m_flags); SetLocalSpaceTransformDirect(nodeNumber, mirrored); } - GetEMotionFX().GetThreadData(mActorInstance->GetThreadIndex())->GetPosePool().FreePose(tempPose); + GetEMotionFX().GetThreadData(m_actorInstance->GetThreadIndex())->GetPosePool().FreePose(tempPose); } } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Pose.h b/Gems/EMotionFX/Code/EMotionFX/Source/Pose.h index 58dcb59ee4..32c7a33bd2 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Pose.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Pose.h @@ -87,7 +87,7 @@ namespace EMotionFX * The difference between using GetWorldSpaceTransform directly from the current pose is that this looks whether the mesh is skinned or not. * Right now we handle skinned meshes differently. This will change in the future. Skinned meshes will always return an identity transform and therefore act like they cannot be animated. * This requires the pose to be linked to an actor instance. If this is not the case, identity transform is returned. - * @param The LOD level, which must be in range of 0..mActor->GetNumLODLevels(). + * @param The LOD level, which must be in range of 0..m_actor->GetNumLODLevels(). * @param nodeIndex The index of the node. If this node happens to have no mesh the regular current world space transform is returned. */ Transform GetMeshNodeWorldSpaceTransform(size_t lodLevel, size_t nodeIndex) const; @@ -98,25 +98,25 @@ namespace EMotionFX Transform CalcTrajectoryTransform() const; - MCORE_INLINE const Transform* GetLocalSpaceTransforms() const { return mLocalSpaceTransforms.GetReadPtr(); } - MCORE_INLINE const Transform* GetModelSpaceTransforms() const { return mModelSpaceTransforms.GetReadPtr(); } - MCORE_INLINE size_t GetNumTransforms() const { return mLocalSpaceTransforms.GetLength(); } - MCORE_INLINE const ActorInstance* GetActorInstance() const { return mActorInstance; } - MCORE_INLINE const Actor* GetActor() const { return mActor; } - MCORE_INLINE const Skeleton* GetSkeleton() const { return mSkeleton; } + MCORE_INLINE const Transform* GetLocalSpaceTransforms() const { return m_localSpaceTransforms.GetReadPtr(); } + MCORE_INLINE const Transform* GetModelSpaceTransforms() const { return m_modelSpaceTransforms.GetReadPtr(); } + MCORE_INLINE size_t GetNumTransforms() const { return m_localSpaceTransforms.GetLength(); } + MCORE_INLINE const ActorInstance* GetActorInstance() const { return m_actorInstance; } + MCORE_INLINE const Actor* GetActor() const { return m_actor; } + MCORE_INLINE const Skeleton* GetSkeleton() const { return m_skeleton; } - MCORE_INLINE Transform& GetLocalSpaceTransformDirect(size_t nodeIndex) { return mLocalSpaceTransforms[nodeIndex]; } - MCORE_INLINE Transform& GetModelSpaceTransformDirect(size_t nodeIndex) { return mModelSpaceTransforms[nodeIndex]; } - MCORE_INLINE const Transform& GetLocalSpaceTransformDirect(size_t nodeIndex) const { return mLocalSpaceTransforms[nodeIndex]; } - MCORE_INLINE const Transform& GetModelSpaceTransformDirect(size_t nodeIndex) const { return mModelSpaceTransforms[nodeIndex]; } - MCORE_INLINE void SetLocalSpaceTransformDirect(size_t nodeIndex, const Transform& transform){ mLocalSpaceTransforms[nodeIndex] = transform; mFlags[nodeIndex] |= FLAG_LOCALTRANSFORMREADY; } - MCORE_INLINE void SetModelSpaceTransformDirect(size_t nodeIndex, const Transform& transform){ mModelSpaceTransforms[nodeIndex] = transform; mFlags[nodeIndex] |= FLAG_MODELTRANSFORMREADY; } - MCORE_INLINE void InvalidateLocalSpaceTransform(size_t nodeIndex) { mFlags[nodeIndex] &= ~FLAG_LOCALTRANSFORMREADY; } - MCORE_INLINE void InvalidateModelSpaceTransform(size_t nodeIndex) { mFlags[nodeIndex] &= ~FLAG_MODELTRANSFORMREADY; } + MCORE_INLINE Transform& GetLocalSpaceTransformDirect(size_t nodeIndex) { return m_localSpaceTransforms[nodeIndex]; } + MCORE_INLINE Transform& GetModelSpaceTransformDirect(size_t nodeIndex) { return m_modelSpaceTransforms[nodeIndex]; } + MCORE_INLINE const Transform& GetLocalSpaceTransformDirect(size_t nodeIndex) const { return m_localSpaceTransforms[nodeIndex]; } + MCORE_INLINE const Transform& GetModelSpaceTransformDirect(size_t nodeIndex) const { return m_modelSpaceTransforms[nodeIndex]; } + MCORE_INLINE void SetLocalSpaceTransformDirect(size_t nodeIndex, const Transform& transform){ m_localSpaceTransforms[nodeIndex] = transform; m_flags[nodeIndex] |= FLAG_LOCALTRANSFORMREADY; } + MCORE_INLINE void SetModelSpaceTransformDirect(size_t nodeIndex, const Transform& transform){ m_modelSpaceTransforms[nodeIndex] = transform; m_flags[nodeIndex] |= FLAG_MODELTRANSFORMREADY; } + MCORE_INLINE void InvalidateLocalSpaceTransform(size_t nodeIndex) { m_flags[nodeIndex] &= ~FLAG_LOCALTRANSFORMREADY; } + MCORE_INLINE void InvalidateModelSpaceTransform(size_t nodeIndex) { m_flags[nodeIndex] &= ~FLAG_MODELTRANSFORMREADY; } - MCORE_INLINE void SetMorphWeight(size_t index, float weight) { mMorphWeights[index] = weight; } - MCORE_INLINE float GetMorphWeight(size_t index) const { return mMorphWeights[index]; } - MCORE_INLINE size_t GetNumMorphWeights() const { return mMorphWeights.GetLength(); } + MCORE_INLINE void SetMorphWeight(size_t index, float weight) { m_morphWeights[index] = weight; } + MCORE_INLINE float GetMorphWeight(size_t index) const { return m_morphWeights[index]; } + MCORE_INLINE size_t GetNumMorphWeights() const { return m_morphWeights.GetLength(); } void ResizeNumMorphs(size_t numMorphTargets); /** @@ -168,8 +168,8 @@ namespace EMotionFX Pose& operator=(const Pose& other); - MCORE_INLINE uint8 GetFlags(size_t nodeIndex) const { return mFlags[nodeIndex]; } - MCORE_INLINE void SetFlags(size_t nodeIndex, uint8 flags) { mFlags[nodeIndex] = flags; } + MCORE_INLINE uint8 GetFlags(size_t nodeIndex) const { return m_flags[nodeIndex]; } + MCORE_INLINE void SetFlags(size_t nodeIndex, uint8 flags) { m_flags[nodeIndex] = flags; } bool HasPoseData(const AZ::TypeId& typeId) const; PoseData* GetPoseDataByType(const AZ::TypeId& typeId) const; @@ -193,14 +193,14 @@ namespace EMotionFX T* GetAndPreparePoseData(ActorInstance* linkToActorInstance) { return azdynamic_cast(GetAndPreparePoseData(azrtti_typeid(), linkToActorInstance)); } private: - mutable MCore::AlignedArray mLocalSpaceTransforms; - mutable MCore::AlignedArray mModelSpaceTransforms; - mutable MCore::AlignedArray mFlags; + mutable MCore::AlignedArray m_localSpaceTransforms; + mutable MCore::AlignedArray m_modelSpaceTransforms; + mutable MCore::AlignedArray m_flags; AZStd::unordered_map > m_poseDatas; - MCore::AlignedArray mMorphWeights; /**< The morph target weights. */ - const ActorInstance* mActorInstance; - const Actor* mActor; - const Skeleton* mSkeleton; + MCore::AlignedArray m_morphWeights; /**< The morph target weights. */ + const ActorInstance* m_actorInstance; + const Actor* m_actor; + const Skeleton* m_skeleton; void RecursiveInvalidateModelSpaceTransforms(const Actor* actor, size_t nodeIndex); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/PoseDataRagdoll.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/PoseDataRagdoll.cpp index e5c3aa7d8c..1d53b4961d 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/PoseDataRagdoll.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/PoseDataRagdoll.cpp @@ -94,8 +94,8 @@ namespace EMotionFX if (nodeState.m_simulationType == Physics::SimulationType::Kinematic && destNodeState.m_simulationType == Physics::SimulationType::Dynamic) { - nodeState.m_position = jointTransform.mPosition.Lerp(destNodeState.m_position, weight); - nodeState.m_orientation = jointTransform.mRotation.NLerp(destNodeState.m_orientation, weight); + nodeState.m_position = jointTransform.m_position.Lerp(destNodeState.m_position, weight); + nodeState.m_orientation = jointTransform.m_rotation.NLerp(destNodeState.m_orientation, weight); // We're blending from a kinematic to a dynamic joint, which means when starting the blend we know that the animation pose matches the ragdoll pose. // The closest a powered ragdoll joint can be to its target pose and thus matching the kinematic one is by using its maximum strength. @@ -114,8 +114,8 @@ namespace EMotionFX else if (nodeState.m_simulationType == Physics::SimulationType::Dynamic && destNodeState.m_simulationType == Physics::SimulationType::Kinematic) { - nodeState.m_position = nodeState.m_position.Lerp(destJointTransform.mPosition, weight); - nodeState.m_orientation = nodeState.m_orientation.NLerp(destJointTransform.mRotation, weight); + nodeState.m_position = nodeState.m_position.Lerp(destJointTransform.m_position, weight); + nodeState.m_orientation = nodeState.m_orientation.NLerp(destJointTransform.m_rotation, weight); // Inverse way here. Blending towards the maximum strength possible to make sure we're as close as possible to the target pose when switching simulation // state to kinematic. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/RagdollInstance.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/RagdollInstance.cpp index 87221c0bd2..c7da3430b1 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/RagdollInstance.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/RagdollInstance.cpp @@ -333,12 +333,12 @@ namespace EMotionFX void RagdollInstance::GetWorldSpaceTransform(const Pose* pose, size_t jointIndex, AZ::Vector3& outPosition, AZ::Quaternion& outRotation) { const Transform& globalTransform = pose->GetModelSpaceTransform(jointIndex); - const AZ::Quaternion actorInstanceRotation = m_actorInstance->GetLocalSpaceTransform().mRotation; - const AZ::Vector3& actorInstanceTranslation = m_actorInstance->GetLocalSpaceTransform().mPosition; + const AZ::Quaternion actorInstanceRotation = m_actorInstance->GetLocalSpaceTransform().m_rotation; + const AZ::Vector3& actorInstanceTranslation = m_actorInstance->GetLocalSpaceTransform().m_position; // Calculate the world space position and rotation (The actor instance position and rotation equal the entity transform). - outPosition = actorInstanceRotation.TransformVector(globalTransform.mPosition) + actorInstanceTranslation; - outRotation = actorInstanceRotation * globalTransform.mRotation; + outPosition = actorInstanceRotation.TransformVector(globalTransform.m_position) + actorInstanceTranslation; + outRotation = actorInstanceRotation * globalTransform.m_rotation; } void RagdollInstance::ReadRagdollStateFromActorInstance(Physics::RagdollState& outRagdollState, AZ::Vector3& outRagdollPos, AZ::Quaternion& outRagdollRot) @@ -349,8 +349,8 @@ namespace EMotionFX const Skeleton* skeleton = actor->GetSkeleton(); const Pose* currentPose = m_actorInstance->GetTransformData()->GetCurrentPose(); - const AZ::Quaternion& actorInstanceRotation = m_actorInstance->GetLocalSpaceTransform().mRotation; - const AZ::Vector3& actorInstanceTranslation = m_actorInstance->GetLocalSpaceTransform().mPosition; + const AZ::Quaternion& actorInstanceRotation = m_actorInstance->GetLocalSpaceTransform().m_rotation; + const AZ::Vector3& actorInstanceTranslation = m_actorInstance->GetLocalSpaceTransform().m_position; const size_t ragdollNodeCount = m_ragdoll->GetNumNodes(); outRagdollState.resize(ragdollNodeCount); @@ -371,14 +371,14 @@ namespace EMotionFX { // Calculate the ragdoll world space position and rotation from the ragdoll root node representative in the animation skeleton (e.g. the Pelvis). const Transform& globalTransform = currentPose->GetModelSpaceTransform(m_ragdollRootJoint->GetNodeIndex()); - outRagdollPos = actorInstanceRotation.TransformVector(globalTransform.mPosition) + actorInstanceTranslation; - outRagdollRot = actorInstanceRotation * globalTransform.mRotation; + outRagdollPos = actorInstanceRotation.TransformVector(globalTransform.m_position) + actorInstanceTranslation; + outRagdollRot = actorInstanceRotation * globalTransform.m_rotation; } else { AZ_Assert(false, "Expected valid ragdoll root node. Either the ragdoll root node does not exist in the animation skeleton or the ragdoll is empty."); - outRagdollPos = m_actorInstance->GetLocalSpaceTransform().mPosition; - outRagdollRot = m_actorInstance->GetLocalSpaceTransform().mRotation; + outRagdollPos = m_actorInstance->GetLocalSpaceTransform().m_position; + outRagdollRot = m_actorInstance->GetLocalSpaceTransform().m_rotation; } } @@ -512,8 +512,8 @@ namespace EMotionFX drawLine(currentParentPos, simulatedColor, currentPos, simulatedColor, defaultLineThickness); // Render target pose - const AZ::Vector3& targetPos = targetPose.GetWorldSpaceTransform(jointIndex).mPosition; - const AZ::Vector3& targetParentPos = targetPose.GetWorldSpaceTransform(ragdollParentJoint->GetNodeIndex()).mPosition; + const AZ::Vector3& targetPos = targetPose.GetWorldSpaceTransform(jointIndex).m_position; + const AZ::Vector3& targetParentPos = targetPose.GetWorldSpaceTransform(ragdollParentJoint->GetNodeIndex()).m_position; drawLine(targetParentPos, simulatedTargetColor, targetPos, simulatedTargetColor, targetLineThickness); } else diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Recorder.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Recorder.cpp index 3eb32f24ce..085d164a94 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Recorder.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Recorder.cpp @@ -48,10 +48,10 @@ namespace EMotionFX serializeContext->Class() ->Version(1) - ->Field("positions", &Recorder::TransformTracks::mPositions) - ->Field("rotations", &Recorder::TransformTracks::mRotations) + ->Field("positions", &Recorder::TransformTracks::m_positions) + ->Field("rotations", &Recorder::TransformTracks::m_rotations) #ifndef EMFX_SCALE_DISABLED - ->Field("scales", &Recorder::TransformTracks::mScales) + ->Field("scales", &Recorder::TransformTracks::m_scales) #endif ; } @@ -80,27 +80,27 @@ namespace EMotionFX serializeContext->Class() ->Version(1) - ->Field("fps", &Recorder::RecordSettings::mFPS) - ->Field("recordTransforms", &Recorder::RecordSettings::mRecordTransforms) - ->Field("recordNodeHistory", &Recorder::RecordSettings::mRecordNodeHistory) - ->Field("historyStatesOnly", &Recorder::RecordSettings::mHistoryStatesOnly) - ->Field("recordAnimGraphStates", &Recorder::RecordSettings::mRecordAnimGraphStates) - ->Field("recordEvents", &Recorder::RecordSettings::mRecordEvents) - ->Field("recordScale", &Recorder::RecordSettings::mRecordScale) - ->Field("recordMorphs", &Recorder::RecordSettings::mRecordMorphs) - ->Field("interpolate", &Recorder::RecordSettings::mInterpolate) + ->Field("fps", &Recorder::RecordSettings::m_fps) + ->Field("recordTransforms", &Recorder::RecordSettings::m_recordTransforms) + ->Field("recordNodeHistory", &Recorder::RecordSettings::m_recordNodeHistory) + ->Field("historyStatesOnly", &Recorder::RecordSettings::m_historyStatesOnly) + ->Field("recordAnimGraphStates", &Recorder::RecordSettings::m_recordAnimGraphStates) + ->Field("recordEvents", &Recorder::RecordSettings::m_recordEvents) + ->Field("recordScale", &Recorder::RecordSettings::m_recordScale) + ->Field("recordMorphs", &Recorder::RecordSettings::m_recordMorphs) + ->Field("interpolate", &Recorder::RecordSettings::m_interpolate) ; } Recorder::Recorder() : BaseObject() { - mIsInPlayMode = false; - mIsRecording = false; - mAutoPlay = false; - mRecordTime = 0.0f; - mLastRecordTime = 0.0f; - mCurrentPlayTime = 0.0f; + m_isInPlayMode = false; + m_isRecording = false; + m_autoPlay = false; + m_recordTime = 0.0f; + m_lastRecordTime = 0.0f; + m_currentPlayTime = 0.0f; EMotionFX::ActorInstanceNotificationBus::Handler::BusConnect(); } @@ -133,30 +133,30 @@ namespace EMotionFX ->Version(1) ->Field("actorInstanceDatas", &Recorder::m_actorInstanceDatas) ->Field("timeDeltas", &Recorder::m_timeDeltas) - ->Field("settings", &Recorder::mRecordSettings) + ->Field("settings", &Recorder::m_recordSettings) ; } // enable or disable auto play mode void Recorder::SetAutoPlay(bool enabled) { - mAutoPlay = enabled; + m_autoPlay = enabled; } // set the current play time void Recorder::SetCurrentPlayTime(float timeInSeconds) { - mCurrentPlayTime = timeInSeconds; + m_currentPlayTime = timeInSeconds; - if (mCurrentPlayTime < 0.0f) + if (m_currentPlayTime < 0.0f) { - mCurrentPlayTime = 0.0f; + m_currentPlayTime = 0.0f; } - if (mCurrentPlayTime > mRecordTime) + if (m_currentPlayTime > m_recordTime) { - mCurrentPlayTime = mRecordTime; + m_currentPlayTime = m_recordTime; } } @@ -165,21 +165,21 @@ namespace EMotionFX void Recorder::StartPlayBack() { StopRecording(); - mIsInPlayMode = true; + m_isInPlayMode = true; } // stop playback mode void Recorder::StopPlayBack() { - mIsInPlayMode = false; + m_isInPlayMode = false; } // rewind the playback void Recorder::Rewind() { - mCurrentPlayTime = 0.0f; + m_currentPlayTime = 0.0f; } bool Recorder::HasRecording() const @@ -192,13 +192,13 @@ namespace EMotionFX { Lock(); - mIsInPlayMode = false; - mIsRecording = false; - mAutoPlay = false; - mRecordTime = 0.0f; - mLastRecordTime = 0.0f; - mCurrentPlayTime = 0.0f; - mRecordSettings.m_actorInstances.clear(); + m_isInPlayMode = false; + m_isRecording = false; + m_autoPlay = false; + m_recordTime = 0.0f; + m_lastRecordTime = 0.0f; + m_currentPlayTime = 0.0f; + m_recordSettings.m_actorInstances.clear(); m_timeDeltas.clear(); // delete all actor instance datas @@ -225,18 +225,18 @@ namespace EMotionFX m_sessionUuid = AZ::Uuid::Create(); // we are recording again - mRecordSettings = settings; - mIsRecording = true; + m_recordSettings = settings; + m_isRecording = true; // Add all actor instances if we did not specify them explicitly. - if (mRecordSettings.m_actorInstances.empty()) + if (m_recordSettings.m_actorInstances.empty()) { const size_t numActorInstances = GetActorManager().GetNumActorInstances(); - mRecordSettings.m_actorInstances.resize(numActorInstances); + m_recordSettings.m_actorInstances.resize(numActorInstances); for (size_t i = 0; i < numActorInstances; ++i) { ActorInstance* actorInstance = GetActorManager().GetActorInstance(i); - mRecordSettings.m_actorInstances[i] = actorInstance; + m_recordSettings.m_actorInstances[i] = actorInstance; } } @@ -255,9 +255,9 @@ namespace EMotionFX void Recorder::UpdatePlayMode(float timeDelta) { // increase the playtime if we are in automatic play mode and playback is enabled - if (mIsInPlayMode && mAutoPlay) + if (m_isInPlayMode && m_autoPlay) { - SetCurrentPlayTime(mCurrentPlayTime + timeDelta); + SetCurrentPlayTime(m_currentPlayTime + timeDelta); } } @@ -268,18 +268,18 @@ namespace EMotionFX Lock(); // if we are not recording there is nothing to do - if (mIsRecording == false) + if (m_isRecording == false) { Unlock(); return; } // increase the time we record - mRecordTime += timeDelta; + m_recordTime += timeDelta; // save a sample when more time passed than the desired sample rate - const float sampleRate = 1.0f / (float)mRecordSettings.mFPS; - if (mRecordTime - mLastRecordTime >= sampleRate) + const float sampleRate = 1.0f / (float)m_recordSettings.m_fps; + if (m_recordTime - m_lastRecordTime >= sampleRate) { RecordCurrentFrame(timeDelta); } @@ -296,7 +296,7 @@ namespace EMotionFX Lock(); } - mIsRecording = false; + m_isRecording = false; FinalizeAllNodeHistoryItems(); if (lock) @@ -309,7 +309,7 @@ namespace EMotionFX // prepare for recording by resizing and preallocating space/arrays void Recorder::PrepareForRecording() { - const size_t numActorInstances = mRecordSettings.m_actorInstances.size(); + const size_t numActorInstances = m_recordSettings.m_actorInstances.size(); m_actorInstanceDatas.resize(numActorInstances); for (size_t i = 0; i < numActorInstances; ++i) { @@ -317,54 +317,54 @@ namespace EMotionFX ActorInstanceData& actorInstanceData = *m_actorInstanceDatas[i]; // link it to the right actor instance - ActorInstance* actorInstance = mRecordSettings.m_actorInstances[i]; - actorInstanceData.mActorInstance = actorInstance; + ActorInstance* actorInstance = m_recordSettings.m_actorInstances[i]; + actorInstanceData.m_actorInstance = actorInstance; // add the transform tracks - if (mRecordSettings.mRecordTransforms) + if (m_recordSettings.m_recordTransforms) { // for all nodes in the actor instance const size_t numNodes = actorInstance->GetNumNodes(); actorInstanceData.m_transformTracks.resize(numNodes); for (size_t n = 0; n < numNodes; ++n) { - actorInstanceData.m_transformTracks[n].mPositions.Reserve(mRecordSettings.mNumPreAllocTransformKeys); - actorInstanceData.m_transformTracks[n].mRotations.Reserve(mRecordSettings.mNumPreAllocTransformKeys); + actorInstanceData.m_transformTracks[n].m_positions.Reserve(m_recordSettings.m_numPreAllocTransformKeys); + actorInstanceData.m_transformTracks[n].m_rotations.Reserve(m_recordSettings.m_numPreAllocTransformKeys); EMFX_SCALECODE ( - if (mRecordSettings.mRecordScale) + if (m_recordSettings.m_recordScale) { - actorInstanceData.m_transformTracks[n].mScales.Reserve(mRecordSettings.mNumPreAllocTransformKeys); + actorInstanceData.m_transformTracks[n].m_scales.Reserve(m_recordSettings.m_numPreAllocTransformKeys); } ) } } // if recording transforms // if recording morph targets, resize the morphs array - if (mRecordSettings.mRecordMorphs) + if (m_recordSettings.m_recordMorphs) { const size_t numMorphs = actorInstance->GetMorphSetupInstance()->GetNumMorphTargets(); - actorInstanceData.mMorphTracks.resize(numMorphs); + actorInstanceData.m_morphTracks.resize(numMorphs); for (size_t m = 0; m < numMorphs; ++m) { - actorInstanceData.mMorphTracks[m].Reserve(256); + actorInstanceData.m_morphTracks[m].Reserve(256); } } // add the animgraph data - if (mRecordSettings.mRecordAnimGraphStates) + if (m_recordSettings.m_recordAnimGraphStates) { if (actorInstance->GetAnimGraphInstance()) { - actorInstanceData.mAnimGraphData = new AnimGraphInstanceData(); - actorInstanceData.mAnimGraphData->mAnimGraphInstance = actorInstance->GetAnimGraphInstance(); - if (mRecordSettings.mInitialAnimGraphAnimBytes > 0) + actorInstanceData.m_animGraphData = new AnimGraphInstanceData(); + actorInstanceData.m_animGraphData->m_animGraphInstance = actorInstance->GetAnimGraphInstance(); + if (m_recordSettings.m_initialAnimGraphAnimBytes > 0) { - actorInstanceData.mAnimGraphData->mDataBuffer = (uint8*)MCore::Allocate(mRecordSettings.mInitialAnimGraphAnimBytes, EMFX_MEMCATEGORY_RECORDER); + actorInstanceData.m_animGraphData->m_dataBuffer = (uint8*)MCore::Allocate(m_recordSettings.m_initialAnimGraphAnimBytes, EMFX_MEMCATEGORY_RECORDER); } - actorInstanceData.mAnimGraphData->mDataBufferSize = mRecordSettings.mInitialAnimGraphAnimBytes; + actorInstanceData.m_animGraphData->m_dataBufferSize = m_recordSettings.m_initialAnimGraphAnimBytes; } } // if recording animgraphs } // for all actor instances @@ -381,7 +381,7 @@ namespace EMotionFX { for (ActorInstanceData* actorInstanceData : m_actorInstanceDatas) { - const ActorInstance* actorInstance = actorInstanceData->mActorInstance; + const ActorInstance* actorInstance = actorInstanceData->m_actorInstance; if (actorInstanceData->m_transformTracks.empty()) { continue; @@ -390,12 +390,12 @@ namespace EMotionFX const size_t numNodes = actorInstance->GetNumNodes(); for (size_t n = 0; n < numNodes; ++n) { - actorInstanceData->m_transformTracks[n].mPositions.Shrink(); - actorInstanceData->m_transformTracks[n].mRotations.Shrink(); + actorInstanceData->m_transformTracks[n].m_positions.Shrink(); + actorInstanceData->m_transformTracks[n].m_rotations.Shrink(); EMFX_SCALECODE ( - actorInstanceData->m_transformTracks[n].mScales.Shrink(); + actorInstanceData->m_transformTracks[n].m_scales.Shrink(); ) } } @@ -424,13 +424,13 @@ namespace EMotionFX m_timeDeltas.emplace_back(timeDelta); // record the current transforms - if (mRecordSettings.mRecordTransforms) + if (m_recordSettings.m_recordTransforms) { RecordCurrentTransforms(); } // record the current anim graph states - if (mRecordSettings.mRecordAnimGraphStates) + if (m_recordSettings.m_recordAnimGraphStates) { if (!RecordCurrentAnimGraphStates()) { @@ -444,25 +444,25 @@ namespace EMotionFX RecordMainLocalTransforms(); // record morphs - if (mRecordSettings.mRecordMorphs) + if (m_recordSettings.m_recordMorphs) { RecordMorphs(); } // update (while recording) the node history items - if (mRecordSettings.mRecordNodeHistory) + if (m_recordSettings.m_recordNodeHistory) { UpdateNodeHistoryItems(); } // recordo the events - if (mRecordSettings.mRecordEvents) + if (m_recordSettings.m_recordEvents) { RecordEvents(); } // update the last record time - mLastRecordTime = mRecordTime; + m_lastRecordTime = m_recordTime; } @@ -474,13 +474,13 @@ namespace EMotionFX for (size_t i = 0; i < numActorInstances; ++i) { ActorInstanceData& actorInstanceData = *m_actorInstanceDatas[i]; - ActorInstance* actorInstance = actorInstanceData.mActorInstance; + ActorInstance* actorInstance = actorInstanceData.m_actorInstance; const size_t numMorphs = actorInstance->GetMorphSetupInstance()->GetNumMorphTargets(); for (size_t m = 0; m < numMorphs; ++m) { - KeyTrackLinearDynamic& morphTrack = actorInstanceData.mMorphTracks[i]; // morph animation data - morphTrack.AddKey(mRecordTime, actorInstance->GetMorphSetupInstance()->GetMorphTarget(i)->GetWeight()); + KeyTrackLinearDynamic& morphTrack = actorInstanceData.m_morphTracks[i]; // morph animation data + morphTrack.AddKey(m_recordTime, actorInstance->GetMorphSetupInstance()->GetMorphTarget(i)->GetWeight()); } } } @@ -492,13 +492,13 @@ namespace EMotionFX // for all actor instances for (ActorInstanceData* actorInstanceData : m_actorInstanceDatas) { - ActorInstance* actorInstance = actorInstanceData->mActorInstance; + ActorInstance* actorInstance = actorInstanceData->m_actorInstance; const Transform& transform = actorInstance->GetLocalSpaceTransform(); #ifndef EMFX_SCALE_DISABLED - AddTransformKey(actorInstanceData->mActorLocalTransform, transform.mPosition, transform.mRotation, transform.mScale); + AddTransformKey(actorInstanceData->m_actorLocalTransform, transform.m_position, transform.m_rotation, transform.m_scale); #else - AddTransformKey(actorInstanceData->mActorLocalTransform, transform.mPosition, transform.mRotation, AZ::Vector3(1.0f, 1.0f, 1.0f)); + AddTransformKey(actorInstanceData->m_actorLocalTransform, transform.m_position, transform.m_rotation, AZ::Vector3(1.0f, 1.0f, 1.0f)); #endif } } @@ -509,7 +509,7 @@ namespace EMotionFX { for (ActorInstanceData* actorInstanceData : m_actorInstanceDatas) { - ActorInstance* actorInstance = actorInstanceData->mActorInstance; + ActorInstance* actorInstance = actorInstanceData->m_actorInstance; const TransformData* transformData = actorInstance->GetTransformData(); { @@ -519,9 +519,9 @@ namespace EMotionFX const Transform& localTransform = transformData->GetCurrentPose()->GetLocalSpaceTransform(n); #ifndef EMFX_SCALE_DISABLED - AddTransformKey(actorInstanceData->m_transformTracks[n], localTransform.mPosition, localTransform.mRotation, localTransform.mScale); + AddTransformKey(actorInstanceData->m_transformTracks[n], localTransform.m_position, localTransform.m_rotation, localTransform.m_scale); #else - AddTransformKey(actorInstanceData->m_transformTracks[n], localTransform.mPosition, localTransform.mRotation, AZ::Vector3(1.0f, 1.0f, 1.0f)); + AddTransformKey(actorInstanceData->m_transformTracks[n], localTransform.m_position, localTransform.m_rotation, AZ::Vector3(1.0f, 1.0f, 1.0f)); #endif } } @@ -535,43 +535,43 @@ namespace EMotionFX // for all actor instances for (const ActorInstanceData* actorInstanceData : m_actorInstanceDatas) { - if (actorInstanceData->mAnimGraphData == nullptr) + if (actorInstanceData->m_animGraphData == nullptr) { continue; } { // get some shortcuts - AnimGraphInstanceData& animGraphInstanceData = *actorInstanceData->mAnimGraphData; - AnimGraphInstance* animGraphInstance = animGraphInstanceData.mAnimGraphInstance; + AnimGraphInstanceData& animGraphInstanceData = *actorInstanceData->m_animGraphData; + AnimGraphInstance* animGraphInstance = animGraphInstanceData.m_animGraphInstance; const AnimGraph* animGraph = animGraphInstance->GetAnimGraph(); // add a new frame - AZStd::vector& frames = animGraphInstanceData.mFrames; + AZStd::vector& frames = animGraphInstanceData.m_frames; if (!frames.empty()) { - const size_t byteOffset = frames.back().mByteOffset + frames.back().mNumBytes; + const size_t byteOffset = frames.back().m_byteOffset + frames.back().m_numBytes; frames.emplace_back(); - frames.back().mByteOffset = byteOffset; - frames.back().mNumBytes = 0; + frames.back().m_byteOffset = byteOffset; + frames.back().m_numBytes = 0; } else { frames.emplace_back(); - frames.back().mByteOffset = 0; - frames.back().mNumBytes = 0; + frames.back().m_byteOffset = 0; + frames.back().m_numBytes = 0; } // get the current frame AnimGraphAnimFrame& currentFrame = frames.back(); - currentFrame.mTimeValue = mRecordTime; + currentFrame.m_timeValue = m_recordTime; // save the parameter values const size_t numParams = animGraphInstance->GetAnimGraph()->GetNumValueParameters(); - currentFrame.mParameterValues.resize(numParams); + currentFrame.m_parameterValues.resize(numParams); for (size_t p = 0; p < numParams; ++p) { - currentFrame.mParameterValues[p] = AZStd::unique_ptr(animGraphInstance->GetParameterValue(p)->Clone()); + currentFrame.m_parameterValues[p] = AZStd::unique_ptr(animGraphInstance->GetParameterValue(p)->Clone()); } // recursively save all unique datas @@ -581,9 +581,7 @@ namespace EMotionFX } // increase the frames counter - animGraphInstanceData.mNumFrames++; - - //MCore::LogInfo("Frame %d = %d bytes (offset=%d), with %d objects - dataBuffer = %d kb", animGraphInstanceData.mNumFrames, frames.GetLast().mNumBytes, frames.GetLast().mByteOffset, frames.GetLast().mObjectInfos.GetLength(), animGraphInstanceData.mDataBufferSize / 1024); + animGraphInstanceData.m_numFrames++; } } // for all actor instances return true; @@ -594,52 +592,52 @@ namespace EMotionFX bool Recorder::SaveUniqueData(AnimGraphInstance* animGraphInstance, AnimGraphObject* object, AnimGraphInstanceData& animGraphInstanceData) { // get the current frame's data pointer - AnimGraphAnimFrame& currentFrame = animGraphInstanceData.mFrames.back(); - const size_t frameOffset = currentFrame.mByteOffset; + AnimGraphAnimFrame& currentFrame = animGraphInstanceData.m_frames.back(); + const size_t frameOffset = currentFrame.m_byteOffset; // prepare the objects array - mObjects.clear(); - mObjects.reserve(1024); + m_objects.clear(); + m_objects.reserve(1024); // collect the objects we are going to save for this frame - object->RecursiveCollectObjects(mObjects); + object->RecursiveCollectObjects(m_objects); // resize the object infos array - const size_t numObjects = mObjects.size(); - currentFrame.mObjectInfos.resize(numObjects); + const size_t numObjects = m_objects.size(); + currentFrame.m_objectInfos.resize(numObjects); // calculate how much memory we need for this frame size_t requiredFrameBytes = 0; - for (const AnimGraphObject* animGraphObject : mObjects) + for (const AnimGraphObject* animGraphObject : m_objects) { requiredFrameBytes += animGraphObject->SaveUniqueData(animGraphInstance, nullptr); } // make sure we have at least the given amount of space in the buffer we are going to write the frame data to - if (!AssureAnimGraphBufferSize(animGraphInstanceData, requiredFrameBytes + currentFrame.mByteOffset)) + if (!AssureAnimGraphBufferSize(animGraphInstanceData, requiredFrameBytes + currentFrame.m_byteOffset)) { return false; } - uint8* dataPointer = &animGraphInstanceData.mDataBuffer[frameOffset]; + uint8* dataPointer = &animGraphInstanceData.m_dataBuffer[frameOffset]; // save all the unique datas for the objects for (size_t i = 0; i < numObjects; ++i) { // store the object info - AnimGraphObject* curObject = mObjects[i]; - currentFrame.mObjectInfos[i].mObject = curObject; - currentFrame.mObjectInfos[i].mFrameByteOffset = currentFrame.mNumBytes; + AnimGraphObject* curObject = m_objects[i]; + currentFrame.m_objectInfos[i].m_object = curObject; + currentFrame.m_objectInfos[i].m_frameByteOffset = currentFrame.m_numBytes; // write the unique data const size_t numBytesWritten = curObject->SaveUniqueData(animGraphInstance, dataPointer); // increase some offsets/pointers - currentFrame.mNumBytes += numBytesWritten; + currentFrame.m_numBytes += numBytesWritten; dataPointer += numBytesWritten; } // make sure we have a match here, otherwise some of the object->SaveUniqueData(dataPointer) returns different values than object->SaveUniqueData(nullptr) - MCORE_ASSERT(requiredFrameBytes == currentFrame.mNumBytes); + MCORE_ASSERT(requiredFrameBytes == currentFrame.m_numBytes); return true; } @@ -649,19 +647,19 @@ namespace EMotionFX bool Recorder::AssureAnimGraphBufferSize(AnimGraphInstanceData& animGraphInstanceData, size_t numBytes) { // if the buffer is big enough, do nothing - if (animGraphInstanceData.mDataBufferSize >= numBytes) + if (animGraphInstanceData.m_dataBufferSize >= numBytes) { return true; } // we need to reallocate to grow the buffer - const size_t newNumBytes = animGraphInstanceData.mDataBufferSize + (numBytes - animGraphInstanceData.mDataBufferSize) * 100; // allocate 100 frames ahead - void* newBuffer = MCore::Realloc(animGraphInstanceData.mDataBuffer, newNumBytes, EMFX_MEMCATEGORY_RECORDER); + const size_t newNumBytes = animGraphInstanceData.m_dataBufferSize + (numBytes - animGraphInstanceData.m_dataBufferSize) * 100; // allocate 100 frames ahead + void* newBuffer = MCore::Realloc(animGraphInstanceData.m_dataBuffer, newNumBytes, EMFX_MEMCATEGORY_RECORDER); MCORE_ASSERT(newBuffer); if (newBuffer) { - animGraphInstanceData.mDataBuffer = static_cast(newBuffer); - animGraphInstanceData.mDataBufferSize = newNumBytes; + animGraphInstanceData.m_dataBuffer = static_cast(newBuffer); + animGraphInstanceData.m_dataBufferSize = newNumBytes; return true; } RecorderNotificationBus::Broadcast(&RecorderNotificationBus::Events::OnRecordingFailed, @@ -681,51 +679,51 @@ namespace EMotionFX #endif // check if we need to add a position key at all - if (track.mPositions.GetNumKeys() > 0) + if (track.m_positions.GetNumKeys() > 0) { - const AZ::Vector3 lastPos = track.mPositions.GetLastKey()->GetValue(); + const AZ::Vector3 lastPos = track.m_positions.GetLastKey()->GetValue(); if (!pos.IsClose(lastPos, 0.0001f)) { - track.mPositions.AddKey(mRecordTime, pos); + track.m_positions.AddKey(m_recordTime, pos); } } else { - track.mPositions.AddKey(mRecordTime, pos); + track.m_positions.AddKey(m_recordTime, pos); } // check if we need to add a rotation key at all - if (track.mRotations.GetNumKeys() > 0) + if (track.m_rotations.GetNumKeys() > 0) { - const AZ::Quaternion lastRot = track.mRotations.GetLastKey()->GetValue(); + const AZ::Quaternion lastRot = track.m_rotations.GetLastKey()->GetValue(); if (!rot.IsClose(lastRot, 0.0001f)) { - track.mRotations.AddKey(mRecordTime, rot); + track.m_rotations.AddKey(m_recordTime, rot); } } else { - track.mRotations.AddKey(mRecordTime, rot); + track.m_rotations.AddKey(m_recordTime, rot); } EMFX_SCALECODE ( - if (mRecordSettings.mRecordScale) + if (m_recordSettings.m_recordScale) { // check if we need to add a scale key - if (track.mScales.GetNumKeys() > 0) + if (track.m_scales.GetNumKeys() > 0) { - const AZ::Vector3 lastScale = track.mScales.GetLastKey()->GetValue(); + const AZ::Vector3 lastScale = track.m_scales.GetLastKey()->GetValue(); if (!scale.IsClose(lastScale, 0.0001f)) { - track.mScales.AddKey(mRecordTime, scale); + track.m_scales.AddKey(m_recordTime, scale); } } else { - track.mScales.AddKey(mRecordTime, scale); + track.m_scales.AddKey(m_recordTime, scale); } } ) @@ -733,7 +731,7 @@ namespace EMotionFX void Recorder::SampleAndApplyTransforms(float timeInSeconds, ActorInstance* actorInstance) const { - const AZStd::vector& recordedActorInstances = mRecordSettings.m_actorInstances; + const AZStd::vector& recordedActorInstances = m_recordSettings.m_actorInstances; const auto iterator = AZStd::find(recordedActorInstances.begin(), recordedActorInstances.end(), actorInstance); if (iterator != recordedActorInstances.end()) { @@ -746,16 +744,16 @@ namespace EMotionFX { for (const ActorInstanceData* actorInstanceData : m_actorInstanceDatas) { - if(actorInstanceData->mAnimGraphData) + if(actorInstanceData->m_animGraphData) { - SampleAndApplyAnimGraphStates(timeInSeconds, *actorInstanceData->mAnimGraphData); + SampleAndApplyAnimGraphStates(timeInSeconds, *actorInstanceData->m_animGraphData); } } } void Recorder::SampleAndApplyMainTransform(float timeInSeconds, ActorInstance* actorInstance) const { - const AZStd::vector& recordedActorInstances = mRecordSettings.m_actorInstances; + const AZStd::vector& recordedActorInstances = m_recordSettings.m_actorInstances; const auto iterator = AZStd::find(recordedActorInstances.begin(), recordedActorInstances.end(), actorInstance); if (iterator != recordedActorInstances.end()) { @@ -766,18 +764,18 @@ namespace EMotionFX void Recorder::SampleAndApplyMorphs(float timeInSeconds, ActorInstance* actorInstance) const { - const AZStd::vector& recordedActorInstances = mRecordSettings.m_actorInstances; + const AZStd::vector& recordedActorInstances = m_recordSettings.m_actorInstances; const auto iterator = AZStd::find(recordedActorInstances.begin(), recordedActorInstances.end(), actorInstance); if (iterator != recordedActorInstances.end()) { const size_t index = AZStd::distance(recordedActorInstances.begin(), iterator); const ActorInstanceData& actorInstanceData = *m_actorInstanceDatas[index]; - const size_t numMorphs = actorInstanceData.mMorphTracks.size(); + const size_t numMorphs = actorInstanceData.m_morphTracks.size(); if (numMorphs == actorInstance->GetMorphSetupInstance()->GetNumMorphTargets()) { for (size_t i = 0; i < numMorphs; ++i) { - actorInstance->GetMorphSetupInstance()->GetMorphTarget(i)->SetWeight(actorInstanceData.mMorphTracks[i].GetValueAtTime(timeInSeconds)); + actorInstance->GetMorphSetupInstance()->GetMorphTarget(i)->SetWeight(actorInstanceData.m_morphTracks[i].GetValueAtTime(timeInSeconds)); } } } @@ -787,17 +785,17 @@ namespace EMotionFX { // get the actor instance const ActorInstanceData& actorInstanceData = *m_actorInstanceDatas[actorInstanceIndex]; - ActorInstance* actorInstance = actorInstanceData.mActorInstance; + ActorInstance* actorInstance = actorInstanceData.m_actorInstance; // sample and apply - const TransformTracks& track = actorInstanceData.mActorLocalTransform; - actorInstance->SetLocalSpacePosition(track.mPositions.GetValueAtTime(timeInSeconds, nullptr, nullptr, mRecordSettings.mInterpolate)); - actorInstance->SetLocalSpaceRotation(track.mRotations.GetValueAtTime(timeInSeconds, nullptr, nullptr, mRecordSettings.mInterpolate)); + const TransformTracks& track = actorInstanceData.m_actorLocalTransform; + actorInstance->SetLocalSpacePosition(track.m_positions.GetValueAtTime(timeInSeconds, nullptr, nullptr, m_recordSettings.m_interpolate)); + actorInstance->SetLocalSpaceRotation(track.m_rotations.GetValueAtTime(timeInSeconds, nullptr, nullptr, m_recordSettings.m_interpolate)); EMFX_SCALECODE ( - if (mRecordSettings.mRecordScale) + if (m_recordSettings.m_recordScale) { - actorInstance->SetLocalSpaceScale(track.mScales.GetValueAtTime(timeInSeconds, nullptr, nullptr, mRecordSettings.mInterpolate)); + actorInstance->SetLocalSpaceScale(track.m_scales.GetValueAtTime(timeInSeconds, nullptr, nullptr, m_recordSettings.m_interpolate)); } ) } @@ -805,7 +803,7 @@ namespace EMotionFX void Recorder::SampleAndApplyTransforms(float timeInSeconds, size_t actorInstanceIndex) const { const ActorInstanceData& actorInstanceData = *m_actorInstanceDatas[actorInstanceIndex]; - ActorInstance* actorInstance = actorInstanceData.mActorInstance; + ActorInstance* actorInstance = actorInstanceData.m_actorInstance; TransformData* transformData = actorInstance->GetTransformData(); // for all nodes in the actor instance @@ -817,14 +815,14 @@ namespace EMotionFX const TransformTracks& track = actorInstanceData.m_transformTracks[n]; // build the output transform by sampling the keytracks - outTransform.mPosition = track.mPositions.GetValueAtTime(timeInSeconds, nullptr, nullptr, mRecordSettings.mInterpolate); - outTransform.mRotation = track.mRotations.GetValueAtTime(timeInSeconds, nullptr, nullptr, mRecordSettings.mInterpolate); + outTransform.m_position = track.m_positions.GetValueAtTime(timeInSeconds, nullptr, nullptr, m_recordSettings.m_interpolate); + outTransform.m_rotation = track.m_rotations.GetValueAtTime(timeInSeconds, nullptr, nullptr, m_recordSettings.m_interpolate); EMFX_SCALECODE ( - if (mRecordSettings.mRecordScale) + if (m_recordSettings.m_recordScale) { - outTransform.mScale = track.mScales.GetValueAtTime(timeInSeconds, nullptr, nullptr, mRecordSettings.mInterpolate); + outTransform.m_scale = track.m_scales.GetValueAtTime(timeInSeconds, nullptr, nullptr, m_recordSettings.m_interpolate); } ) @@ -843,25 +841,25 @@ namespace EMotionFX } // for all animgraph instances that we recorded, restore their internal states - AnimGraphInstance* animGraphInstance = animGraphInstanceData.mAnimGraphInstance; + AnimGraphInstance* animGraphInstance = animGraphInstanceData.m_animGraphInstance; // get the real frame number (clamped) - const size_t realFrameNumber = AZStd::min(frameNumber, animGraphInstanceData.mFrames.size() - 1); - const AnimGraphAnimFrame& currentFrame = animGraphInstanceData.mFrames[realFrameNumber]; + const size_t realFrameNumber = AZStd::min(frameNumber, animGraphInstanceData.m_frames.size() - 1); + const AnimGraphAnimFrame& currentFrame = animGraphInstanceData.m_frames[realFrameNumber]; // get the data and objects buffers - const size_t byteOffset = currentFrame.mByteOffset; - const uint8* frameDataBuffer = &animGraphInstanceData.mDataBuffer[byteOffset]; - const AZStd::vector& frameObjects = currentFrame.mObjectInfos; + const size_t byteOffset = currentFrame.m_byteOffset; + const uint8* frameDataBuffer = &animGraphInstanceData.m_dataBuffer[byteOffset]; + const AZStd::vector& frameObjects = currentFrame.m_objectInfos; // first lets update all parameter values - MCORE_ASSERT(currentFrame.mParameterValues.size() == animGraphInstance->GetAnimGraph()->GetNumParameters()); - const size_t numParameters = currentFrame.mParameterValues.size(); + MCORE_ASSERT(currentFrame.m_parameterValues.size() == animGraphInstance->GetAnimGraph()->GetNumParameters()); + const size_t numParameters = currentFrame.m_parameterValues.size(); for (size_t p = 0; p < numParameters; ++p) { // make sure the parameters are of the same type - MCORE_ASSERT(animGraphInstance->GetParameterValue(p)->GetType() == currentFrame.mParameterValues[p]->GetType()); - animGraphInstance->GetParameterValue(p)->InitFrom(currentFrame.mParameterValues[p].get()); + MCORE_ASSERT(animGraphInstance->GetParameterValue(p)->GetType() == currentFrame.m_parameterValues[p]->GetType()); + animGraphInstance->GetParameterValue(p)->InitFrom(currentFrame.m_parameterValues[p].get()); } // process all objects for this frame @@ -870,25 +868,25 @@ namespace EMotionFX for (size_t a = 0; a < numObjects; ++a) { const AnimGraphAnimObjectInfo& objectInfo = frameObjects[a]; - const size_t numBytesRead = objectInfo.mObject->LoadUniqueData(animGraphInstance, &frameDataBuffer[objectInfo.mFrameByteOffset]); + const size_t numBytesRead = objectInfo.m_object->LoadUniqueData(animGraphInstance, &frameDataBuffer[objectInfo.m_frameByteOffset]); totalBytesRead += numBytesRead; } // make sure this matches, otherwise the data read is not the same as we have written - MCORE_ASSERT(totalBytesRead == currentFrame.mNumBytes); + MCORE_ASSERT(totalBytesRead == currentFrame.m_numBytes); } bool Recorder::GetHasRecorded(ActorInstance* actorInstance) const { - return AZStd::find(mRecordSettings.m_actorInstances.begin(), mRecordSettings.m_actorInstances.end(), actorInstance) - != mRecordSettings.m_actorInstances.end(); + return AZStd::find(m_recordSettings.m_actorInstances.begin(), m_recordSettings.m_actorInstances.end(), actorInstance) + != m_recordSettings.m_actorInstances.end(); } size_t Recorder::FindActorInstanceDataIndex(ActorInstance* actorInstance) const { const auto found = AZStd::find_if(begin(m_actorInstanceDatas), end(m_actorInstanceDatas), [actorInstance](const ActorInstanceData* data) { - return data->mActorInstance == actorInstance; + return data->m_actorInstance == actorInstance; }); return found != end(m_actorInstanceDatas) ? AZStd::distance(begin(m_actorInstanceDatas), found) : InvalidIndex; } @@ -899,46 +897,46 @@ namespace EMotionFX for (ActorInstanceData* actorInstanceData : m_actorInstanceDatas) { // get the animgraph instance - AnimGraphInstance* animGraphInstance = actorInstanceData->mActorInstance->GetAnimGraphInstance(); + AnimGraphInstance* animGraphInstance = actorInstanceData->m_actorInstance->GetAnimGraphInstance(); if (animGraphInstance == nullptr) { continue; } // collect all active motion nodes - animGraphInstance->CollectActiveAnimGraphNodes(&mActiveNodes); + animGraphInstance->CollectActiveAnimGraphNodes(&m_activeNodes); // get the history items as shortcut - AZStd::vector& historyItems = actorInstanceData->mNodeHistoryItems; + AZStd::vector& historyItems = actorInstanceData->m_nodeHistoryItems; // finalize items for (NodeHistoryItem* curItem : historyItems) { - if (curItem->mIsFinalized) + if (curItem->m_isFinalized) { continue; } // check if we have an active node for the given item - const bool haveActiveNode = AZStd::find_if(begin(mActiveNodes), end(mActiveNodes), [curItem](const AnimGraphNode* activeNode) + const bool haveActiveNode = AZStd::find_if(begin(m_activeNodes), end(m_activeNodes), [curItem](const AnimGraphNode* activeNode) { - return activeNode->GetId() == curItem->mNodeId; - }) != end(mActiveNodes); + return activeNode->GetId() == curItem->m_nodeId; + }) != end(m_activeNodes); // the node got deactivated, finalize the item if (haveActiveNode) { - curItem->mGlobalWeights.Optimize(0.0001f); - curItem->mLocalWeights.Optimize(0.0001f); - curItem->mPlayTimes.Optimize(0.0001f); - curItem->mIsFinalized = true; - curItem->mEndTime = mRecordTime; + curItem->m_globalWeights.Optimize(0.0001f); + curItem->m_localWeights.Optimize(0.0001f); + curItem->m_playTimes.Optimize(0.0001f); + curItem->m_isFinalized = true; + curItem->m_endTime = m_recordTime; continue; } } // iterate over all active nodes - for (const AnimGraphNode* activeNode : mActiveNodes) + for (const AnimGraphNode* activeNode : m_activeNodes) { if (activeNode == animGraphInstance->GetRootNode()) // skip the root node { @@ -948,7 +946,7 @@ namespace EMotionFX const AZ::TypeId typeID = azrtti_typeid(activeNode); // if the parent isn't a state machine then it isn't a state - if (mRecordSettings.mHistoryStatesOnly) + if (m_recordSettings.m_historyStatesOnly) { if (azrtti_typeid(activeNode->GetParentNode()) != azrtti_typeid()) { @@ -957,42 +955,42 @@ namespace EMotionFX } // make sure this node is on our capture list - if (!mRecordSettings.mNodeHistoryTypes.empty()) + if (!m_recordSettings.m_nodeHistoryTypes.empty()) { - if (mRecordSettings.mNodeHistoryTypes.find(typeID) == mRecordSettings.mNodeHistoryTypes.end()) + if (m_recordSettings.m_nodeHistoryTypes.find(typeID) == m_recordSettings.m_nodeHistoryTypes.end()) { continue; } } // skip node types we do not want to capture - if (!mRecordSettings.mNodeHistoryTypesToIgnore.empty()) + if (!m_recordSettings.m_nodeHistoryTypesToIgnore.empty()) { - if (mRecordSettings.mNodeHistoryTypesToIgnore.find(typeID) != mRecordSettings.mNodeHistoryTypesToIgnore.end()) + if (m_recordSettings.m_nodeHistoryTypesToIgnore.find(typeID) != m_recordSettings.m_nodeHistoryTypesToIgnore.end()) { continue; } } // try to locate an existing item - NodeHistoryItem* item = FindNodeHistoryItem(*actorInstanceData, activeNode, mRecordTime); + NodeHistoryItem* item = FindNodeHistoryItem(*actorInstanceData, activeNode, m_recordTime); if (item == nullptr) { item = new NodeHistoryItem(); - item->mName = activeNode->GetName(); - item->mAnimGraphID = animGraphInstance->GetAnimGraph()->GetID(); - item->mStartTime = mRecordTime; - item->mIsFinalized = false; - item->mTrackIndex = FindFreeNodeHistoryItemTrack(*actorInstanceData, item); - item->mNodeId = activeNode->GetId(); - item->mColor = activeNode->GetVisualizeColor(); - item->mTypeColor = activeNode->GetVisualColor(); - item->mCategoryID = (uint32)activeNode->GetPaletteCategory(); - item->mNodeType = typeID; - item->mAnimGraphInstance = animGraphInstance; - item->mGlobalWeights.Reserve(1024); - item->mLocalWeights.Reserve(1024); - item->mPlayTimes.Reserve(1024); + item->m_name = activeNode->GetName(); + item->m_animGraphId = animGraphInstance->GetAnimGraph()->GetID(); + item->m_startTime = m_recordTime; + item->m_isFinalized = false; + item->m_trackIndex = FindFreeNodeHistoryItemTrack(*actorInstanceData, item); + item->m_nodeId = activeNode->GetId(); + item->m_color = activeNode->GetVisualizeColor(); + item->m_typeColor = activeNode->GetVisualColor(); + item->m_categoryId = (uint32)activeNode->GetPaletteCategory(); + item->m_nodeType = typeID; + item->m_animGraphInstance = animGraphInstance; + item->m_globalWeights.Reserve(1024); + item->m_localWeights.Reserve(1024); + item->m_playTimes.Reserve(1024); // get the motion instance if (typeID == azrtti_typeid()) @@ -1001,8 +999,8 @@ namespace EMotionFX MotionInstance* motionInstance = motionNode->FindMotionInstance(animGraphInstance); if (motionInstance) { - item->mMotionID = motionInstance->GetMotion()->GetID(); - AzFramework::StringFunc::Path::GetFileName(item->mMotionFileName.c_str(), item->mMotionFileName); + item->m_motionId = motionInstance->GetMotion()->GetID(); + AzFramework::StringFunc::Path::GetFileName(item->m_motionFileName.c_str(), item->m_motionFileName); } } @@ -1011,9 +1009,9 @@ namespace EMotionFX // add the weight key and update infos const AnimGraphNodeData* uniqueData = activeNode->FindOrCreateUniqueNodeData(animGraphInstance); - const float keyTime = mRecordTime - item->mStartTime; - item->mGlobalWeights.AddKey(keyTime, uniqueData->GetGlobalWeight()); - item->mLocalWeights.AddKey(keyTime, uniqueData->GetLocalWeight()); + const float keyTime = m_recordTime - item->m_startTime; + item->m_globalWeights.AddKey(keyTime, uniqueData->GetGlobalWeight()); + item->m_localWeights.AddKey(keyTime, uniqueData->GetLocalWeight()); float normalizedTime = uniqueData->GetCurrentPlayTime(); const float duration = uniqueData->GetDuration(); @@ -1026,8 +1024,8 @@ namespace EMotionFX normalizedTime = 0.0f; } - item->mPlayTimes.AddKey(keyTime, normalizedTime); - item->mEndTime = mRecordTime; + item->m_playTimes.AddKey(keyTime, normalizedTime); + item->m_endTime = m_recordTime; } } // for all actor instances } @@ -1036,15 +1034,15 @@ namespace EMotionFX // try to find a given node history item Recorder::NodeHistoryItem* Recorder::FindNodeHistoryItem(const ActorInstanceData& actorInstanceData, const AnimGraphNode* node, float recordTime) const { - const AZStd::vector& historyItems = actorInstanceData.mNodeHistoryItems; + const AZStd::vector& historyItems = actorInstanceData.m_nodeHistoryItems; for (NodeHistoryItem* curItem : historyItems) { - if (curItem->mNodeId == node->GetId() && curItem->mStartTime <= recordTime && curItem->mIsFinalized == false) + if (curItem->m_nodeId == node->GetId() && curItem->m_startTime <= recordTime && curItem->m_isFinalized == false) { return curItem; } - if (curItem->mNodeId == node->GetId() && curItem->mStartTime <= recordTime && curItem->mEndTime >= recordTime && curItem->mIsFinalized) + if (curItem->m_nodeId == node->GetId() && curItem->m_startTime <= recordTime && curItem->m_endTime >= recordTime && curItem->m_isFinalized) { return curItem; } @@ -1057,7 +1055,7 @@ namespace EMotionFX // find a free track size_t Recorder::FindFreeNodeHistoryItemTrack(const ActorInstanceData& actorInstanceData, NodeHistoryItem* item) const { - const AZStd::vector& historyItems = actorInstanceData.mNodeHistoryItems; + const AZStd::vector& historyItems = actorInstanceData.m_nodeHistoryItems; bool found = false; size_t trackIndex = 0; @@ -1067,23 +1065,23 @@ namespace EMotionFX for (const NodeHistoryItem* curItem : historyItems) { - if (curItem->mTrackIndex != trackIndex) + if (curItem->m_trackIndex != trackIndex) { continue; } // if the current item is not active anymore - if (curItem->mIsFinalized) + if (curItem->m_isFinalized) { // if the start time of the item we try to insert is within the range of this item - if (item->mStartTime > curItem->mStartTime && item->mStartTime < curItem->mEndTime) + if (item->m_startTime > curItem->m_startTime && item->m_startTime < curItem->m_endTime) { hasCollision = true; break; } // if the end time of this item is within the range of this item - if (item->mEndTime > curItem->mStartTime && item->mEndTime < curItem->mEndTime) + if (item->m_endTime > curItem->m_startTime && item->m_endTime < curItem->m_endTime) { hasCollision = true; break; @@ -1091,7 +1089,7 @@ namespace EMotionFX } else // if the current item is still active and has no real end time yet { - if (item->mStartTime >= curItem->mStartTime) + if (item->m_startTime >= curItem->m_startTime) { hasCollision = true; break; @@ -1117,12 +1115,12 @@ namespace EMotionFX size_t Recorder::CalcMaxNodeHistoryTrackIndex(const ActorInstanceData& actorInstanceData) const { size_t result = 0; - const AZStd::vector& historyItems = actorInstanceData.mNodeHistoryItems; + const AZStd::vector& historyItems = actorInstanceData.m_nodeHistoryItems; for (const NodeHistoryItem* curItem : historyItems) { - if (curItem->mTrackIndex > result) + if (curItem->m_trackIndex > result) { - result = curItem->mTrackIndex; + result = curItem->m_trackIndex; } } @@ -1134,12 +1132,12 @@ namespace EMotionFX size_t Recorder::CalcMaxEventHistoryTrackIndex(const ActorInstanceData& actorInstanceData) const { size_t result = 0; - const AZStd::vector& historyItems = actorInstanceData.mEventHistoryItems; + const AZStd::vector& historyItems = actorInstanceData.m_eventHistoryItems; for (const EventHistoryItem* curItem : historyItems) { - if (curItem->mTrackIndex > result) + if (curItem->m_trackIndex > result) { - result = curItem->mTrackIndex; + result = curItem->m_trackIndex; } } @@ -1169,28 +1167,28 @@ namespace EMotionFX for (const ActorInstanceData* actorInstanceData : m_actorInstanceDatas) { // get the animgraph instance - AnimGraphInstance* animGraphInstance = actorInstanceData->mActorInstance->GetAnimGraphInstance(); + AnimGraphInstance* animGraphInstance = actorInstanceData->m_actorInstance->GetAnimGraphInstance(); if (animGraphInstance == nullptr) { continue; } // collect all active motion nodes - animGraphInstance->CollectActiveAnimGraphNodes(&mActiveNodes); + animGraphInstance->CollectActiveAnimGraphNodes(&m_activeNodes); // get the history items as shortcut - const AZStd::vector& historyItems = actorInstanceData->mNodeHistoryItems; + const AZStd::vector& historyItems = actorInstanceData->m_nodeHistoryItems; // finalize all items for (NodeHistoryItem* historyItem : historyItems) { // remove unneeded key frames - if (historyItem->mIsFinalized == false) + if (historyItem->m_isFinalized == false) { - historyItem->mGlobalWeights.Optimize(0.0001f); - historyItem->mLocalWeights.Optimize(0.0001f); - historyItem->mPlayTimes.Optimize(0.0001f); - historyItem->mIsFinalized = true; + historyItem->m_globalWeights.Optimize(0.0001f); + historyItem->m_localWeights.Optimize(0.0001f); + historyItem->m_playTimes.Optimize(0.0001f); + historyItem->m_isFinalized = true; } } } @@ -1204,7 +1202,7 @@ namespace EMotionFX for (ActorInstanceData* actorInstanceData : m_actorInstanceDatas) { // get the animgraph instance - AnimGraphInstance* animGraphInstance = actorInstanceData->mActorInstance->GetAnimGraphInstance(); + AnimGraphInstance* animGraphInstance = actorInstanceData->m_actorInstance->GetAnimGraphInstance(); if (animGraphInstance == nullptr) { continue; @@ -1214,7 +1212,7 @@ namespace EMotionFX const AnimGraphEventBuffer& eventBuffer = animGraphInstance->GetEventBuffer(); // iterate over all events - AZStd::vector& historyItems = actorInstanceData->mEventHistoryItems; + AZStd::vector& historyItems = actorInstanceData->m_eventHistoryItems; const size_t numEvents = eventBuffer.GetNumEvents(); for (size_t i = 0; i < numEvents; ++i) { @@ -1223,26 +1221,26 @@ namespace EMotionFX { continue; } - EventHistoryItem* item = FindEventHistoryItem(*actorInstanceData, eventInfo, mRecordTime); + EventHistoryItem* item = FindEventHistoryItem(*actorInstanceData, eventInfo, m_recordTime); if (item == nullptr) // create a new one { item = new EventHistoryItem(); // TODO - //item->mEventIndex = GetEventManager().FindEventTypeIndex(eventInfo.mTypeID); - item->mEventInfo = eventInfo; - item->mIsTickEvent = eventInfo.mEvent->GetIsTickEvent(); - item->mStartTime = mRecordTime; - item->mAnimGraphID = animGraphInstance->GetAnimGraph()->GetID(); - item->mEmitterNodeId= eventInfo.mEmitter->GetId(); - item->mColor = eventInfo.mEmitter->GetVisualizeColor(); + //item->m_eventIndex = GetEventManager().FindEventTypeIndex(eventInfo.m_typeID); + item->m_eventInfo = eventInfo; + item->m_isTickEvent = eventInfo.m_event->GetIsTickEvent(); + item->m_startTime = m_recordTime; + item->m_animGraphId = animGraphInstance->GetAnimGraph()->GetID(); + item->m_emitterNodeId= eventInfo.m_emitter->GetId(); + item->m_color = eventInfo.m_emitter->GetVisualizeColor(); - item->mTrackIndex = FindFreeEventHistoryItemTrack(*actorInstanceData, item); + item->m_trackIndex = FindFreeEventHistoryItemTrack(*actorInstanceData, item); historyItems.emplace_back(item); } - item->mEndTime = mRecordTime; + item->m_endTime = m_recordTime; } } } @@ -1252,10 +1250,10 @@ namespace EMotionFX Recorder::EventHistoryItem* Recorder::FindEventHistoryItem(const ActorInstanceData& actorInstanceData, const EventInfo& eventInfo, float recordTime) { MCORE_UNUSED(recordTime); - const AZStd::vector& historyItems = actorInstanceData.mEventHistoryItems; + const AZStd::vector& historyItems = actorInstanceData.m_eventHistoryItems; for (const EventHistoryItem* curItem : historyItems) { - if (curItem->mStartTime < eventInfo.mTimeValue) + if (curItem->m_startTime < eventInfo.m_timeValue) { continue; } @@ -1268,7 +1266,7 @@ namespace EMotionFX // find a free event track index size_t Recorder::FindFreeEventHistoryItemTrack(const ActorInstanceData& actorInstanceData, EventHistoryItem* item) const { - const AZStd::vector& historyItems = actorInstanceData.mEventHistoryItems; + const AZStd::vector& historyItems = actorInstanceData.m_eventHistoryItems; bool found = false; size_t trackIndex = 0; while (found == false) @@ -1277,12 +1275,12 @@ namespace EMotionFX for (const EventHistoryItem* curItem : historyItems) { - if (curItem->mTrackIndex != trackIndex) + if (curItem->m_trackIndex != trackIndex) { continue; } - if (MCore::Compare::CheckIfIsClose(curItem->mStartTime, item->mStartTime, 0.01f)) + if (MCore::Compare::CheckIfIsClose(curItem->m_startTime, item->m_startTime, 0.01f)) { hasCollision = true; break; @@ -1314,13 +1312,13 @@ namespace EMotionFX // just search in the first actor instances data const ActorInstanceData& actorInstanceData = *m_actorInstanceDatas[0]; - const AnimGraphInstanceData* animGraphData = actorInstanceData.mAnimGraphData; + const AnimGraphInstanceData* animGraphData = actorInstanceData.m_animGraphData; if (animGraphData == nullptr) { return InvalidIndex; } - const size_t numFrames = animGraphData->mFrames.size(); + const size_t numFrames = animGraphData->m_frames.size(); if (numFrames == 0) { return InvalidIndex; @@ -1335,16 +1333,16 @@ namespace EMotionFX return 0; } - if (timeValue > animGraphData->mFrames.back().mTimeValue) + if (timeValue > animGraphData->m_frames.back().m_timeValue) { - return animGraphData->mFrames.size() - 1; + return animGraphData->m_frames.size() - 1; } for (size_t i = 0; i < numFrames - 1; ++i) { - const AnimGraphAnimFrame& curFrame = animGraphData->mFrames[i]; - const AnimGraphAnimFrame& nextFrame = animGraphData->mFrames[i + 1]; - if (curFrame.mTimeValue <= timeValue && nextFrame.mTimeValue > timeValue) + const AnimGraphAnimFrame& curFrame = animGraphData->m_frames[i]; + const AnimGraphAnimFrame& nextFrame = animGraphData->m_frames[i + 1]; + if (curFrame.m_timeValue <= timeValue && nextFrame.m_timeValue > timeValue) { return i; } @@ -1358,7 +1356,7 @@ namespace EMotionFX Lock(); // Remove the actor instance from the record settings. - AZStd::vector& recordedActorInstances = mRecordSettings.m_actorInstances; + AZStd::vector& recordedActorInstances = m_recordSettings.m_actorInstances; recordedActorInstances.erase(AZStd::remove_if(recordedActorInstances.begin(), recordedActorInstances.end(), [&actorInstance](ActorInstance* recordedActorInstance){ return recordedActorInstance == actorInstance;}), recordedActorInstances.end()); @@ -1366,7 +1364,7 @@ namespace EMotionFX // Remove the actual recorded data. for (size_t i = 0; i < m_actorInstanceDatas.size();) { - if (m_actorInstanceDatas[i]->mActorInstance == actorInstance) + if (m_actorInstanceDatas[i]->m_actorInstance == actorInstance) { delete m_actorInstanceDatas[i]; m_actorInstanceDatas.erase(AZStd::next(m_actorInstanceDatas.begin(), i)); @@ -1386,16 +1384,16 @@ namespace EMotionFX for (ActorInstanceData* actorInstanceData : m_actorInstanceDatas) { - if (actorInstanceData->mAnimGraphData && actorInstanceData->mAnimGraphData->mAnimGraphInstance) + if (actorInstanceData->m_animGraphData && actorInstanceData->m_animGraphData->m_animGraphInstance) { - AnimGraph* curAnimGraph = actorInstanceData->mAnimGraphData->mAnimGraphInstance->GetAnimGraph(); + AnimGraph* curAnimGraph = actorInstanceData->m_animGraphData->m_animGraphInstance->GetAnimGraph(); if (animGraph != curAnimGraph) { continue; } - delete actorInstanceData->mAnimGraphData; - actorInstanceData->mAnimGraphData = nullptr; + delete actorInstanceData->m_animGraphData; + actorInstanceData->m_animGraphData = nullptr; } } @@ -1411,12 +1409,12 @@ namespace EMotionFX void Recorder::Lock() { - mLock.Lock(); + m_lock.Lock(); } void Recorder::Unlock() { - mLock.Unlock(); + m_lock.Unlock(); } @@ -1429,44 +1427,44 @@ namespace EMotionFX for (size_t i = 0; i <= maxIndex; ++i) { ExtractedNodeHistoryItem item; - item.mTrackIndex = i; - item.mValue = 0.0f; - item.mKeyTrackSampleTime = 0.0f; - item.mNodeHistoryItem = nullptr; + item.m_trackIndex = i; + item.m_value = 0.0f; + item.m_keyTrackSampleTime = 0.0f; + item.m_nodeHistoryItem = nullptr; outItems->emplace(AZStd::next(begin(*outItems), i), AZStd::move(item)); } // find all node history items - const AZStd::vector& historyItems = actorInstanceData.mNodeHistoryItems; + const AZStd::vector& historyItems = actorInstanceData.m_nodeHistoryItems; for (NodeHistoryItem* curItem : historyItems) { - if (curItem->mStartTime <= timeValue && curItem->mEndTime > timeValue) + if (curItem->m_startTime <= timeValue && curItem->m_endTime > timeValue) { ExtractedNodeHistoryItem item; - item.mTrackIndex = curItem->mTrackIndex; - item.mKeyTrackSampleTime = timeValue - curItem->mStartTime; - item.mNodeHistoryItem = curItem; + item.m_trackIndex = curItem->m_trackIndex; + item.m_keyTrackSampleTime = timeValue - curItem->m_startTime; + item.m_nodeHistoryItem = curItem; switch (valueType) { case VALUETYPE_GLOBALWEIGHT: - item.mValue = curItem->mGlobalWeights.GetValueAtTime(item.mKeyTrackSampleTime, nullptr, nullptr, mRecordSettings.mInterpolate); + item.m_value = curItem->m_globalWeights.GetValueAtTime(item.m_keyTrackSampleTime, nullptr, nullptr, m_recordSettings.m_interpolate); break; case VALUETYPE_LOCALWEIGHT: - item.mValue = curItem->mLocalWeights.GetValueAtTime(item.mKeyTrackSampleTime, nullptr, nullptr, mRecordSettings.mInterpolate); + item.m_value = curItem->m_localWeights.GetValueAtTime(item.m_keyTrackSampleTime, nullptr, nullptr, m_recordSettings.m_interpolate); break; case VALUETYPE_PLAYTIME: - item.mValue = curItem->mPlayTimes.GetValueAtTime(item.mKeyTrackSampleTime, nullptr, nullptr, mRecordSettings.mInterpolate); + item.m_value = curItem->m_playTimes.GetValueAtTime(item.m_keyTrackSampleTime, nullptr, nullptr, m_recordSettings.m_interpolate); break; default: MCORE_ASSERT(false); // unsupported mode - item.mValue = curItem->mGlobalWeights.GetValueAtTime(item.mKeyTrackSampleTime, nullptr, nullptr, mRecordSettings.mInterpolate); + item.m_value = curItem->m_globalWeights.GetValueAtTime(item.m_keyTrackSampleTime, nullptr, nullptr, m_recordSettings.m_interpolate); } - outItems->emplace(AZStd::next(begin(*outItems), curItem->mTrackIndex), item); + outItems->emplace(AZStd::next(begin(*outItems), curItem->m_trackIndex), item); } } @@ -1484,7 +1482,7 @@ namespace EMotionFX for (size_t i = 0; i <= maxIndex; ++i) { - outMap->emplace(AZStd::next(begin(*outMap), outItems->at(i).mTrackIndex), i); + outMap->emplace(AZStd::next(begin(*outMap), outItems->at(i).m_trackIndex), i); } } } @@ -1499,13 +1497,13 @@ namespace EMotionFX const size_t maxNumTracks = static_cast(CalcMaxNodeHistoryTrackIndex()) + 1; trackFlags.resize(maxNumTracks); - const size_t numNodeHistoryItems = actorInstanceData.mNodeHistoryItems.size(); + const size_t numNodeHistoryItems = actorInstanceData.m_nodeHistoryItems.size(); for (size_t i = 0; i < numNodeHistoryItems; ++i) { - EMotionFX::Recorder::NodeHistoryItem* item = actorInstanceData.mNodeHistoryItems[i]; + EMotionFX::Recorder::NodeHistoryItem* item = actorInstanceData.m_nodeHistoryItems[i]; // Only process motion history items. - if (item->mMotionID == MCORE_INVALIDINDEX32) + if (item->m_motionId == MCORE_INVALIDINDEX32) { continue; } @@ -1518,32 +1516,32 @@ namespace EMotionFX // We at least have a single active motion. size_t intermediateResult = 1; - trackFlags[item->mTrackIndex] = true; + trackFlags[item->m_trackIndex] = true; for (size_t j = 0; j < numNodeHistoryItems; ++j) { - EMotionFX::Recorder::NodeHistoryItem* innerItem = actorInstanceData.mNodeHistoryItems[j]; + EMotionFX::Recorder::NodeHistoryItem* innerItem = actorInstanceData.m_nodeHistoryItems[j]; // Did we count this track in already? If yes, skip. - if (trackFlags[innerItem->mTrackIndex]) + if (trackFlags[innerItem->m_trackIndex]) { continue; } // Skip self comparison and only process motion history items. - if (i == j || innerItem->mMotionID == MCORE_INVALIDINDEX32) + if (i == j || innerItem->m_motionId == MCORE_INVALIDINDEX32) { continue; } // Are the item and innerItem events overlapping? - if ((item->mStartTime >= innerItem->mStartTime && item->mStartTime <= innerItem->mEndTime) || - (item->mEndTime >= innerItem->mStartTime && item->mEndTime <= innerItem->mEndTime) || - (innerItem->mStartTime >= item->mStartTime && innerItem->mStartTime <= item->mEndTime) || - (innerItem->mEndTime >= item->mStartTime && innerItem->mEndTime <= item->mEndTime)) + if ((item->m_startTime >= innerItem->m_startTime && item->m_startTime <= innerItem->m_endTime) || + (item->m_endTime >= innerItem->m_startTime && item->m_endTime <= innerItem->m_endTime) || + (innerItem->m_startTime >= item->m_startTime && innerItem->m_startTime <= item->m_endTime) || + (innerItem->m_endTime >= item->m_startTime && innerItem->m_endTime <= item->m_endTime)) { intermediateResult++; - trackFlags[innerItem->mTrackIndex] = true; + trackFlags[innerItem->m_trackIndex] = true; } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Recorder.h b/Gems/EMotionFX/Code/EMotionFX/Source/Recorder.h index 7d76b09483..fe87d36ea1 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Recorder.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Recorder.h @@ -59,33 +59,33 @@ namespace EMotionFX AZ_TYPE_INFO(EMotionFX::Recorder::RecordSettings, "{A3F9D69E-3543-4B9D-B6F1-C0D5BAB1EDB1}"); AZStd::vector m_actorInstances; /**< The actor instances to record, or specify none to record all (default=record all). */ - AZStd::unordered_set mNodeHistoryTypes; /**< The array of type node type IDs to capture. Empty array means everything. */ - AZStd::unordered_set mNodeHistoryTypesToIgnore; /**< The array of type node type IDs to NOT capture. Empty array means nothing to ignore. */ - uint32 mFPS; /**< The rate at which to sample (default=15). */ - uint32 mNumPreAllocTransformKeys; /**< Pre-allocate space for this amount of transformation keys per node per actor instance (default=32). */ - size_t mInitialAnimGraphAnimBytes; /**< The number of bytes to allocate to store the anim graph recording (default=2*1024*1024, which is 2mb). This is only used when actually recording anim graph internal state animation. */ - bool mRecordTransforms; /**< Record transformations? (default=true). */ - bool mRecordAnimGraphStates; /**< Record the anim graph internal state? (default=false). */ - bool mRecordNodeHistory; /**< Record the node history? (default=false). */ - bool mHistoryStatesOnly; /**< Record only states in the node history? (default=false, and only used when mRecordNodeHistory is true). */ - bool mRecordScale; /**< Record scale changes when recording transforms? */ - bool mRecordEvents; /**< Record events (default=false). */ - bool mRecordMorphs; /**< Record morph target weight animation (default=true). */ - bool mInterpolate; /**< Interpolate playback? (default=false) */ + AZStd::unordered_set m_nodeHistoryTypes; /**< The array of type node type IDs to capture. Empty array means everything. */ + AZStd::unordered_set m_nodeHistoryTypesToIgnore; /**< The array of type node type IDs to NOT capture. Empty array means nothing to ignore. */ + uint32 m_fps; /**< The rate at which to sample (default=15). */ + uint32 m_numPreAllocTransformKeys; /**< Pre-allocate space for this amount of transformation keys per node per actor instance (default=32). */ + size_t m_initialAnimGraphAnimBytes; /**< The number of bytes to allocate to store the anim graph recording (default=2*1024*1024, which is 2mb). This is only used when actually recording anim graph internal state animation. */ + bool m_recordTransforms; /**< Record transformations? (default=true). */ + bool m_recordAnimGraphStates; /**< Record the anim graph internal state? (default=false). */ + bool m_recordNodeHistory; /**< Record the node history? (default=false). */ + bool m_historyStatesOnly; /**< Record only states in the node history? (default=false, and only used when m_recordNodeHistory is true). */ + bool m_recordScale; /**< Record scale changes when recording transforms? */ + bool m_recordEvents; /**< Record events (default=false). */ + bool m_recordMorphs; /**< Record morph target weight animation (default=true). */ + bool m_interpolate; /**< Interpolate playback? (default=false) */ RecordSettings() { - mFPS = 60; - mNumPreAllocTransformKeys = 32; - mInitialAnimGraphAnimBytes = 1 * 1024 * 1024; // 1 megabyte - mRecordTransforms = true; - mRecordNodeHistory = false; - mHistoryStatesOnly = false; - mRecordAnimGraphStates = false; - mRecordEvents = false; - mRecordScale = true; - mRecordMorphs = true; - mInterpolate = false; + m_fps = 60; + m_numPreAllocTransformKeys = 32; + m_initialAnimGraphAnimBytes = 1 * 1024 * 1024; // 1 megabyte + m_recordTransforms = true; + m_recordNodeHistory = false; + m_historyStatesOnly = false; + m_recordAnimGraphStates = false; + m_recordEvents = false; + m_recordScale = true; + m_recordMorphs = true; + m_interpolate = false; } static void Reflect(AZ::ReflectContext* context); @@ -94,25 +94,25 @@ namespace EMotionFX struct EMFX_API EventHistoryItem { - EventInfo mEventInfo; - size_t mEventIndex; /**< The index to use in combination with GetEventManager().GetEvent(index). */ - size_t mTrackIndex; - AnimGraphNodeId mEmitterNodeId; - uint32 mAnimGraphID; - AZ::Color mColor; - float mStartTime; - float mEndTime; - bool mIsTickEvent; + EventInfo m_eventInfo; + size_t m_eventIndex; /**< The index to use in combination with GetEventManager().GetEvent(index). */ + size_t m_trackIndex; + AnimGraphNodeId m_emitterNodeId; + uint32 m_animGraphId; + AZ::Color m_color; + float m_startTime; + float m_endTime; + bool m_isTickEvent; EventHistoryItem() { - mEventIndex = InvalidIndex; - mTrackIndex = InvalidIndex; - mEmitterNodeId = AnimGraphNodeId(); - mAnimGraphID = MCORE_INVALIDINDEX32; + m_eventIndex = InvalidIndex; + m_trackIndex = InvalidIndex; + m_emitterNodeId = AnimGraphNodeId(); + m_animGraphId = MCORE_INVALIDINDEX32; const AZ::u32 col = MCore::GenerateColor(); - mColor = AZ::Color( + m_color = AZ::Color( MCore::ExtractRed(col)/255.0f, MCore::ExtractGreen(col)/255.0f, MCore::ExtractBlue(col)/255.0f, @@ -122,40 +122,40 @@ namespace EMotionFX struct EMFX_API NodeHistoryItem { - AZStd::string mName; - AZStd::string mMotionFileName; - float mStartTime; // time the motion starts being active - float mEndTime; // time the motion stops being active - KeyTrackLinearDynamic mGlobalWeights; // the global weights at given time values - KeyTrackLinearDynamic mLocalWeights; // the local weights at given time values - KeyTrackLinearDynamic mPlayTimes; // normalized time values (current time in the node/motion) - uint32 mMotionID; // the ID of the Motion object used - size_t mTrackIndex; // the track index - size_t mCachedKey; // a cached key - AnimGraphNodeId mNodeId; // animgraph node Id - AnimGraphInstance* mAnimGraphInstance; // the anim graph instance this node was recorded from - AZ::Color mColor; // the node viz color - AZ::Color mTypeColor; // the node type color - uint32 mAnimGraphID; // the animgraph ID - AZ::TypeId mNodeType; // the node type (Uuid) - uint32 mCategoryID; // the category ID - bool mIsFinalized; // is this a finalized item? + AZStd::string m_name; + AZStd::string m_motionFileName; + float m_startTime; // time the motion starts being active + float m_endTime; // time the motion stops being active + KeyTrackLinearDynamic m_globalWeights; // the global weights at given time values + KeyTrackLinearDynamic m_localWeights; // the local weights at given time values + KeyTrackLinearDynamic m_playTimes; // normalized time values (current time in the node/motion) + uint32 m_motionId; // the ID of the Motion object used + size_t m_trackIndex; // the track index + size_t m_cachedKey; // a cached key + AnimGraphNodeId m_nodeId; // animgraph node Id + AnimGraphInstance* m_animGraphInstance; // the anim graph instance this node was recorded from + AZ::Color m_color; // the node viz color + AZ::Color m_typeColor; // the node type color + uint32 m_animGraphId; // the animgraph ID + AZ::TypeId m_nodeType; // the node type (Uuid) + uint32 m_categoryId; // the category ID + bool m_isFinalized; // is this a finalized item? NodeHistoryItem() { - mStartTime = 0.0f; - mEndTime = 0.0f; - mMotionID = MCORE_INVALIDINDEX32; - mTrackIndex = InvalidIndex; - mCachedKey = InvalidIndex; - mNodeId = AnimGraphNodeId(); - mAnimGraphInstance = nullptr; - mAnimGraphID = MCORE_INVALIDINDEX32; - mNodeType = AZ::TypeId::CreateNull(); - mCategoryID = MCORE_INVALIDINDEX32; - mColor.Set(1.0f, 0.0f, 0.0f, 1.0f); - mTypeColor.Set(1.0f, 0.0f, 0.0f, 1.0f); - mIsFinalized = false; + m_startTime = 0.0f; + m_endTime = 0.0f; + m_motionId = MCORE_INVALIDINDEX32; + m_trackIndex = InvalidIndex; + m_cachedKey = InvalidIndex; + m_nodeId = AnimGraphNodeId(); + m_animGraphInstance = nullptr; + m_animGraphId = MCORE_INVALIDINDEX32; + m_nodeType = AZ::TypeId::CreateNull(); + m_categoryId = MCORE_INVALIDINDEX32; + m_color.Set(1.0f, 0.0f, 0.0f, 1.0f); + m_typeColor.Set(1.0f, 0.0f, 0.0f, 1.0f); + m_isFinalized = false; } }; @@ -168,13 +168,13 @@ namespace EMotionFX struct EMFX_API ExtractedNodeHistoryItem { - NodeHistoryItem* mNodeHistoryItem; - size_t mTrackIndex; - float mValue; - float mKeyTrackSampleTime; + NodeHistoryItem* m_nodeHistoryItem; + size_t m_trackIndex; + float m_value; + float m_keyTrackSampleTime; - friend bool operator< (const ExtractedNodeHistoryItem& a, const ExtractedNodeHistoryItem& b) { return (a.mValue > b.mValue); } - friend bool operator==(const ExtractedNodeHistoryItem& a, const ExtractedNodeHistoryItem& b) { return (a.mValue == b.mValue); } + friend bool operator< (const ExtractedNodeHistoryItem& a, const ExtractedNodeHistoryItem& b) { return (a.m_value > b.m_value); } + friend bool operator==(const ExtractedNodeHistoryItem& a, const ExtractedNodeHistoryItem& b) { return (a.m_value == b.m_value); } }; struct EMFX_API TransformTracks final @@ -183,38 +183,38 @@ namespace EMotionFX static void Reflect(AZ::ReflectContext* context); - KeyTrackLinearDynamic mPositions; - KeyTrackLinearDynamic mRotations; + KeyTrackLinearDynamic m_positions; + KeyTrackLinearDynamic m_rotations; #ifndef EMFX_SCALE_DISABLED - KeyTrackLinearDynamic mScales; + KeyTrackLinearDynamic m_scales; #endif }; struct EMFX_API AnimGraphAnimObjectInfo { - size_t mFrameByteOffset; - AnimGraphObject* mObject; + size_t m_frameByteOffset; + AnimGraphObject* m_object; }; struct EMFX_API AnimGraphAnimFrame { - float mTimeValue = 0.0f; - size_t mByteOffset = 0; - size_t mNumBytes = 0; - AZStd::vector mObjectInfos{}; - AZStd::vector> mParameterValues{}; + float m_timeValue = 0.0f; + size_t m_byteOffset = 0; + size_t m_numBytes = 0; + AZStd::vector m_objectInfos{}; + AZStd::vector> m_parameterValues{}; }; struct EMFX_API AnimGraphInstanceData { - AnimGraphInstance* mAnimGraphInstance = nullptr; - size_t mNumFrames = 0; - size_t mDataBufferSize = 0; - uint8* mDataBuffer = nullptr; - AZStd::vector mFrames{}; + AnimGraphInstance* m_animGraphInstance = nullptr; + size_t m_numFrames = 0; + size_t m_dataBufferSize = 0; + uint8* m_dataBuffer = nullptr; + AZStd::vector m_frames{}; AnimGraphInstanceData() = default; AnimGraphInstanceData(const AnimGraphInstanceData&) = delete; @@ -224,16 +224,16 @@ namespace EMotionFX { return; } - mAnimGraphInstance = rhs.mAnimGraphInstance; - mNumFrames = rhs.mNumFrames; - mDataBufferSize = rhs.mDataBufferSize; - mDataBuffer = rhs.mDataBuffer; - mFrames = AZStd::move(rhs.mFrames); - rhs.mAnimGraphInstance = nullptr; - rhs.mNumFrames = 0; - rhs.mDataBufferSize = 0; - rhs.mDataBuffer = nullptr; - rhs.mFrames = {}; + m_animGraphInstance = rhs.m_animGraphInstance; + m_numFrames = rhs.m_numFrames; + m_dataBufferSize = rhs.m_dataBufferSize; + m_dataBuffer = rhs.m_dataBuffer; + m_frames = AZStd::move(rhs.m_frames); + rhs.m_animGraphInstance = nullptr; + rhs.m_numFrames = 0; + rhs.m_dataBufferSize = 0; + rhs.m_dataBuffer = nullptr; + rhs.m_frames = {}; } AnimGraphInstanceData& operator=(const AnimGraphInstanceData&) = delete; @@ -243,22 +243,22 @@ namespace EMotionFX { return *this; } - mAnimGraphInstance = rhs.mAnimGraphInstance; - mNumFrames = rhs.mNumFrames; - mDataBufferSize = rhs.mDataBufferSize; - mDataBuffer = rhs.mDataBuffer; - mFrames = AZStd::move(rhs.mFrames); - rhs.mAnimGraphInstance = nullptr; - rhs.mNumFrames = 0; - rhs.mDataBufferSize = 0; - rhs.mDataBuffer = nullptr; - rhs.mFrames = {}; + m_animGraphInstance = rhs.m_animGraphInstance; + m_numFrames = rhs.m_numFrames; + m_dataBufferSize = rhs.m_dataBufferSize; + m_dataBuffer = rhs.m_dataBuffer; + m_frames = AZStd::move(rhs.m_frames); + rhs.m_animGraphInstance = nullptr; + rhs.m_numFrames = 0; + rhs.m_dataBufferSize = 0; + rhs.m_dataBuffer = nullptr; + rhs.m_frames = {}; return *this; } ~AnimGraphInstanceData() { - MCore::Free(mDataBuffer); + MCore::Free(m_dataBuffer); } }; @@ -267,40 +267,40 @@ namespace EMotionFX AZ_TYPE_INFO(EMotionFX::Recorder::ActorInstanceData, "{955A7EF9-5DC6-4548-BB72-10C974CF3886}"); AZ_CLASS_ALLOCATOR_DECL - ActorInstance* mActorInstance; // the actor instance this data is about - AnimGraphInstanceData* mAnimGraphData; // the anim graph instance data + ActorInstance* m_actorInstance; // the actor instance this data is about + AnimGraphInstanceData* m_animGraphData; // the anim graph instance data AZStd::vector m_transformTracks; // the transformation tracks, one for each node - AZStd::vector mNodeHistoryItems; // node history items - AZStd::vector mEventHistoryItems; // event history item - TransformTracks mActorLocalTransform; // the actor instance's local transformation - AZStd::vector< KeyTrackLinearDynamic > mMorphTracks; // morph animation data + AZStd::vector m_nodeHistoryItems; // node history items + AZStd::vector m_eventHistoryItems; // event history item + TransformTracks m_actorLocalTransform; // the actor instance's local transformation + AZStd::vector< KeyTrackLinearDynamic > m_morphTracks; // morph animation data ActorInstanceData() { - mNodeHistoryItems.reserve(64); - mEventHistoryItems.reserve(1024); - mMorphTracks.reserve(32); - mAnimGraphData = nullptr; - mActorInstance = nullptr; + m_nodeHistoryItems.reserve(64); + m_eventHistoryItems.reserve(1024); + m_morphTracks.reserve(32); + m_animGraphData = nullptr; + m_actorInstance = nullptr; } ~ActorInstanceData() { // clear the node history items - for (NodeHistoryItem* nodeHistoryItem : mNodeHistoryItems) + for (NodeHistoryItem* nodeHistoryItem : m_nodeHistoryItems) { delete nodeHistoryItem; } - mNodeHistoryItems.clear(); + m_nodeHistoryItems.clear(); // clear the event history items - for (auto & eventHistoryItem : mEventHistoryItems) + for (auto & eventHistoryItem : m_eventHistoryItems) { delete eventHistoryItem; } - mEventHistoryItems.clear(); + m_eventHistoryItems.clear(); - delete mAnimGraphData; + delete m_animGraphData; } static void Reflect(AZ::ReflectContext* context); @@ -334,13 +334,13 @@ namespace EMotionFX void SampleAndApplyAnimGraphs(float timeInSeconds) const; void SampleAndApplyMorphs(float timeInSeconds, ActorInstance* actorInstance) const; - MCORE_INLINE float GetRecordTime() const { return mRecordTime; } - MCORE_INLINE float GetCurrentPlayTime() const { return mCurrentPlayTime; } - MCORE_INLINE bool GetIsRecording() const { return mIsRecording; } - MCORE_INLINE bool GetIsInPlayMode() const { return mIsInPlayMode; } - MCORE_INLINE bool GetIsInAutoPlayMode() const { return mAutoPlay; } + MCORE_INLINE float GetRecordTime() const { return m_recordTime; } + MCORE_INLINE float GetCurrentPlayTime() const { return m_currentPlayTime; } + MCORE_INLINE bool GetIsRecording() const { return m_isRecording; } + MCORE_INLINE bool GetIsInPlayMode() const { return m_isInPlayMode; } + MCORE_INLINE bool GetIsInAutoPlayMode() const { return m_autoPlay; } bool GetHasRecorded(ActorInstance* actorInstance) const; - MCORE_INLINE const RecordSettings& GetRecordSettings() const { return mRecordSettings; } + MCORE_INLINE const RecordSettings& GetRecordSettings() const { return m_recordSettings; } const AZ::Uuid& GetSessionUuid() const { return m_sessionUuid; } const AZStd::vector& GetTimeDeltas() { return m_timeDeltas; } @@ -367,19 +367,19 @@ namespace EMotionFX void Unlock(); private: - RecordSettings mRecordSettings; + RecordSettings m_recordSettings; AZStd::vector m_actorInstanceDatas; AZStd::vector m_timeDeltas; // The value of the time deltas whenever a key is made - AZStd::vector mObjects; - AZStd::vector mActiveNodes; /**< A temp array to store active animgraph nodes in. */ - MCore::Mutex mLock; + AZStd::vector m_objects; + AZStd::vector m_activeNodes; /**< A temp array to store active animgraph nodes in. */ + MCore::Mutex m_lock; AZ::TypeId m_sessionUuid; - float mRecordTime; - float mLastRecordTime; - float mCurrentPlayTime; - bool mIsRecording; - bool mIsInPlayMode; - bool mAutoPlay; + float m_recordTime; + float m_lastRecordTime; + float m_currentPlayTime; + bool m_isRecording; + bool m_isInPlayMode; + bool m_autoPlay; void PrepareForRecording(); void RecordMorphs(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/RepositioningLayerPass.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/RepositioningLayerPass.cpp index 6bbf60700b..1e3171d419 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/RepositioningLayerPass.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/RepositioningLayerPass.cpp @@ -26,7 +26,7 @@ namespace EMotionFX RepositioningLayerPass::RepositioningLayerPass(MotionLayerSystem* motionLayerSystem) : LayerPass(motionLayerSystem) { - mLastReposNode = InvalidIndex; + m_lastReposNode = InvalidIndex; } @@ -53,7 +53,7 @@ namespace EMotionFX // The main function that processes the pass. void RepositioningLayerPass::Process() { - ActorInstance* actorInstance = mMotionSystem->GetActorInstance(); + ActorInstance* actorInstance = m_motionSystem->GetActorInstance(); if (!actorInstance->GetMotionExtractionEnabled()) { actorInstance->SetTrajectoryDeltaTransform(Transform::CreateIdentityWithZeroScale()); @@ -63,7 +63,7 @@ namespace EMotionFX // Get the motion extraction node and check if we are actually playing any motions. Actor* actor = actorInstance->GetActor(); Node* motionExtractNode = actor->GetMotionExtractionNode(); - if (!motionExtractNode || mMotionSystem->GetNumMotionInstances() == 0) + if (!motionExtractNode || m_motionSystem->GetNumMotionInstances() == 0) { actorInstance->SetTrajectoryDeltaTransform(Transform::CreateIdentityWithZeroScale()); return; @@ -77,10 +77,10 @@ namespace EMotionFX // Bottom up traversal of the layers. bool firstBlend = true; - const size_t numMotionInstances = mMotionSystem->GetNumMotionInstances(); + const size_t numMotionInstances = m_motionSystem->GetNumMotionInstances(); for (size_t i = numMotionInstances - 1; i != InvalidIndex; --i) { - MotionInstance* motionInstance = mMotionSystem->GetMotionInstance(i); + MotionInstance* motionInstance = m_motionSystem->GetMotionInstance(i); if (!motionInstance->GetMotionExtractionEnabled()) { continue; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/RepositioningLayerPass.h b/Gems/EMotionFX/Code/EMotionFX/Source/RepositioningLayerPass.h index 4df680092a..333749141a 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/RepositioningLayerPass.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/RepositioningLayerPass.h @@ -59,8 +59,8 @@ namespace EMotionFX private: - AZStd::vector mHierarchyPath; /**< The path of node indices to the repositioning node. */ - size_t mLastReposNode; /**< The last repositioning node index that was used. When this changes, the hierarchy path has to be updated. */ + AZStd::vector m_hierarchyPath; /**< The path of node indices to the repositioning node. */ + size_t m_lastReposNode; /**< The last repositioning node index that was used. When this changes, the hierarchy path has to be updated. */ /** * The constructor. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/SingleThreadScheduler.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/SingleThreadScheduler.cpp index 0e871499df..f5ba7856ac 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/SingleThreadScheduler.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/SingleThreadScheduler.cpp @@ -45,9 +45,9 @@ namespace EMotionFX const ActorManager& actorManager = GetActorManager(); // reset stats - mNumUpdated.SetValue(0); - mNumVisible.SetValue(0); - mNumSampled.SetValue(0); + m_numUpdated.SetValue(0); + m_numVisible.SetValue(0); + m_numSampled.SetValue(0); // propagate root actor instance visibility to their attachments const size_t numRootActorInstances = GetActorManager().GetNumRootActorInstances(); @@ -81,7 +81,7 @@ namespace EMotionFX { actorInstance->SetThreadIndex(0); - mNumUpdated.Increment(); + m_numUpdated.Increment(); const bool isVisible = actorInstance->GetIsVisible(); @@ -95,13 +95,13 @@ namespace EMotionFX if (isVisible) { - mNumSampled.Increment(); + m_numSampled.Increment(); } } if (isVisible) { - mNumVisible.Increment(); + m_numVisible.Increment(); } // update the transformations diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/SkinningInfoVertexAttributeLayer.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/SkinningInfoVertexAttributeLayer.cpp index 4483d98e40..5a3c01802e 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/SkinningInfoVertexAttributeLayer.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/SkinningInfoVertexAttributeLayer.cpp @@ -23,8 +23,8 @@ namespace EMotionFX { if (allocData) { - mData.SetNumPreCachedElements(2); // assume 2 weights per vertex - mData.Resize(numAttributes); + m_data.SetNumPreCachedElements(2); // assume 2 weights per vertex + m_data.Resize(numAttributes); } } @@ -65,25 +65,25 @@ namespace EMotionFX // add a given influence (using a bone and a weight) void SkinningInfoVertexAttributeLayer::AddInfluence(size_t attributeNr, size_t nodeNr, float weight, size_t boneNr) { - mData.Add(attributeNr, SkinInfluence(static_cast(nodeNr), weight, static_cast(boneNr))); + m_data.Add(attributeNr, SkinInfluence(static_cast(nodeNr), weight, static_cast(boneNr))); } // remove the given skin influence void SkinningInfoVertexAttributeLayer::RemoveInfluence(size_t attributeNr, size_t influenceNr) { - mData.Remove(attributeNr, influenceNr); + m_data.Remove(attributeNr, influenceNr); } // the uv vertex attribute layer VertexAttributeLayer* SkinningInfoVertexAttributeLayer::Clone() { - SkinningInfoVertexAttributeLayer* clone = aznew SkinningInfoVertexAttributeLayer(mNumAttributes); + SkinningInfoVertexAttributeLayer* clone = aznew SkinningInfoVertexAttributeLayer(m_numAttributes); // copy over the data - clone->mData = mData; - clone->mNameID = mNameID; + clone->m_data = m_data; + clone->m_nameId = m_nameId; // return the clone return clone; @@ -93,14 +93,14 @@ namespace EMotionFX // swap attribute data data void SkinningInfoVertexAttributeLayer::SwapAttributes(uint32 attribA, uint32 attribB) { - mData.Swap(attribA, attribB); + m_data.Swap(attribA, attribB); } // remove attributes void SkinningInfoVertexAttributeLayer::RemoveAttributes(uint32 startAttributeNr, uint32 endAttributeNr) { - mData.RemoveRows(startAttributeNr, endAttributeNr, true); + m_data.RemoveRows(startAttributeNr, endAttributeNr, true); } @@ -108,7 +108,7 @@ namespace EMotionFX void SkinningInfoVertexAttributeLayer::RemapInfluences(size_t oldNodeNr, size_t newNodeNr) { // get the number of vertices/attributes - const size_t numAttributes = mData.GetNumRows(); + const size_t numAttributes = m_data.GetNumRows(); for (size_t a = 0; a < numAttributes; ++a) { // iterate through all influences and compare them with the old node @@ -129,7 +129,7 @@ namespace EMotionFX void SkinningInfoVertexAttributeLayer::RemoveAllInfluencesForNode(size_t nodeNr) { // get the number of vertices/attributes - const size_t numAttributes = mData.GetNumRows(); + const size_t numAttributes = m_data.GetNumRows(); for (size_t a = 0; a < numAttributes; ++a) { // iterate through all influences and compare them with the given node @@ -159,7 +159,7 @@ namespace EMotionFX } // get the number of vertices/attributes - const size_t numAttributes = mData.GetNumRows(); + const size_t numAttributes = m_data.GetNumRows(); for (size_t a = 0; a < numAttributes; ++a) { // get the number of influences for the current vertex @@ -183,7 +183,7 @@ namespace EMotionFX // optimize the memory usage void SkinningInfoVertexAttributeLayer::OptimizeMemoryUsage() { - mData.Shrink(); + m_data.Shrink(); } @@ -191,7 +191,7 @@ namespace EMotionFX void SkinningInfoVertexAttributeLayer::OptimizeInfluences(float tolerance, size_t maxWeights) { // get the number of vertices/attributes - const size_t numAttributes = mData.GetNumRows(); + const size_t numAttributes = m_data.GetNumRows(); for (size_t a = 0; a < numAttributes; ++a) { if (GetNumInfluences(a) == 0) @@ -257,7 +257,7 @@ namespace EMotionFX const float remaining = 1.0f - totalWeight; for (size_t i = 0; i < numInfluences; ++i) { - const float percentage = mData.GetElement(a, i).GetWeight() / totalWeight; + const float percentage = m_data.GetElement(a, i).GetWeight() / totalWeight; GetInfluence(a, i)->SetWeight(GetInfluence(a, i)->GetWeight() + percentage * remaining); } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/SkinningInfoVertexAttributeLayer.h b/Gems/EMotionFX/Code/EMotionFX/Source/SkinningInfoVertexAttributeLayer.h index 48eeabac77..1dfec9926f 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/SkinningInfoVertexAttributeLayer.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/SkinningInfoVertexAttributeLayer.h @@ -28,9 +28,9 @@ namespace EMotionFX * Default constructor. */ SkinInfluence() - : mWeight(0.0f) - , mBoneNr(0) - , mNodeNr(0) {} + : m_weight(0.0f) + , m_boneNr(0) + , m_nodeNr(0) {} /** * Constructor. @@ -39,52 +39,52 @@ namespace EMotionFX * @param boneNr The bone number, used as optimization inside the softskin deformer. */ SkinInfluence(uint16 nodeNr, float weight, uint16 boneNr = 0) - : mWeight(weight) - , mBoneNr(boneNr) - , mNodeNr(nodeNr) {} + : m_weight(weight) + , m_boneNr(boneNr) + , m_nodeNr(nodeNr) {} /** * Get the weight of this influence. * @result The weight, which should be in range of [0..1]. */ - MCORE_INLINE float GetWeight() const { return mWeight; } + MCORE_INLINE float GetWeight() const { return m_weight; } /** * Adjust the weight value. * @param weight The weight value, which must be in range of [0..1]. */ - void SetWeight(float weight) { mWeight = weight; } + void SetWeight(float weight) { m_weight = weight; } /** * Get the node number that points inside an actor. * So this number is an index you can pass to Actor::GetNode(...) to get the actual node that acts as bone. * @result The node number, which points inside the nodes array of the actor. */ - MCORE_INLINE uint16 GetNodeNr() const { return mNodeNr; } + MCORE_INLINE uint16 GetNodeNr() const { return m_nodeNr; } /** * Set the node number that points inside an actor. * So this number is an index you can pass to Actor::GetNode(...) to get the actual node that acts as bone. * @param nodeNr The node number, which points inside the nodes array of the actor. */ - void SetNodeNr(uint16 nodeNr) { mNodeNr = nodeNr; } + void SetNodeNr(uint16 nodeNr) { m_nodeNr = nodeNr; } /** * Set the bone number, used for precalculations. * @param boneNr The bone number. */ - void SetBoneNr(uint16 boneNr) { mBoneNr = boneNr; } + void SetBoneNr(uint16 boneNr) { m_boneNr = boneNr; } /** * Get the bone number, which is used for precalculations. * @result The bone number. */ - MCORE_INLINE uint16 GetBoneNr() const { return mBoneNr; } + MCORE_INLINE uint16 GetBoneNr() const { return m_boneNr; } private: - float mWeight; /**< The weight value, between 0 and 1. */ - uint16 mBoneNr; /**< A bone number, which points in an array of bone info structs used for precalculating the skinning matrices. */ - uint16 mNodeNr; /**< The node number inside the actor which acts as a bone. */ + float m_weight; /**< The weight value, between 0 and 1. */ + uint16 m_boneNr; /**< A bone number, which points in an array of bone info structs used for precalculating the skinning matrices. */ + uint16 m_nodeNr; /**< The node number inside the actor which acts as a bone. */ }; @@ -149,7 +149,7 @@ namespace EMotionFX * @param attributeNr The attribute/vertex number. * @result The number of influences. */ - MCORE_INLINE size_t GetNumInfluences(size_t attributeNr) { return mData.GetNumElements(attributeNr); } + MCORE_INLINE size_t GetNumInfluences(size_t attributeNr) { return m_data.GetNumElements(attributeNr); } /** * Get a given influence. @@ -157,14 +157,14 @@ namespace EMotionFX * @param influenceNr The influence number, which must be in range of [0..GetNumInfluences()] * @result The given influence. */ - MCORE_INLINE SkinInfluence* GetInfluence(size_t attributeNr, size_t influenceNr) { return &mData.GetElement(attributeNr, influenceNr); } + MCORE_INLINE SkinInfluence* GetInfluence(size_t attributeNr, size_t influenceNr) { return &m_data.GetElement(attributeNr, influenceNr); } /** * Get direct access to the jagged 2D array that contains the skinning influence data. * This can be used in the importers for fast loading and not having to add influence per influence. * @result A reference to the 2D array containing all the skinning influences. */ - MCORE_INLINE MCore::Array2D& GetArray2D() { return mData; } + MCORE_INLINE MCore::Array2D& GetArray2D() { return m_data; } /** * Collect all unique joint indices used by the skin. @@ -251,7 +251,7 @@ namespace EMotionFX void CollapseInfluences(size_t attributeNr); private: - MCore::Array2D mData; /**< The stored influence data. The Array2D template allows a different number of skinning influences per vertex. */ + MCore::Array2D m_data; /**< The stored influence data. The Array2D template allows a different number of skinning influences per vertex. */ /** * The constructor. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/SoftSkinDeformer.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/SoftSkinDeformer.cpp index 004e415501..9b9c808eac 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/SoftSkinDeformer.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/SoftSkinDeformer.cpp @@ -34,8 +34,8 @@ namespace EMotionFX // destructor SoftSkinDeformer::~SoftSkinDeformer() { - mNodeNumbers.clear(); - mBoneMatrices.clear(); + m_nodeNumbers.clear(); + m_boneMatrices.clear(); } @@ -67,8 +67,8 @@ namespace EMotionFX SoftSkinDeformer* result = aznew SoftSkinDeformer(mesh); // copy the bone info (for precalc/optimization reasons) - result->mNodeNumbers = mNodeNumbers; - result->mBoneMatrices = mBoneMatrices; + result->m_nodeNumbers = m_nodeNumbers; + result->m_boneMatrices = m_boneMatrices; // return the result return result; @@ -86,24 +86,24 @@ namespace EMotionFX const AZ::Matrix3x4* skinningMatrices = transformData->GetSkinningMatrices(); // precalc the skinning matrices - const size_t numBones = mBoneMatrices.size(); + const size_t numBones = m_boneMatrices.size(); for (size_t i = 0; i < numBones; i++) { - const size_t nodeIndex = mNodeNumbers[i]; - mBoneMatrices[i] = skinningMatrices[nodeIndex]; + const size_t nodeIndex = m_nodeNumbers[i]; + m_boneMatrices[i] = skinningMatrices[nodeIndex]; } // find the skinning layer - SkinningInfoVertexAttributeLayer* layer = (SkinningInfoVertexAttributeLayer*)mMesh->FindSharedVertexAttributeLayer(SkinningInfoVertexAttributeLayer::TYPE_ID); + SkinningInfoVertexAttributeLayer* layer = (SkinningInfoVertexAttributeLayer*)m_mesh->FindSharedVertexAttributeLayer(SkinningInfoVertexAttributeLayer::TYPE_ID); AZ_Assert(layer, "Cannot find skinning info"); // Perform the skinning. - AZ::Vector3* __restrict positions = static_cast(mMesh->FindVertexData(Mesh::ATTRIB_POSITIONS)); - AZ::Vector3* __restrict normals = static_cast(mMesh->FindVertexData(Mesh::ATTRIB_NORMALS)); - AZ::Vector4* __restrict tangents = static_cast(mMesh->FindVertexData(Mesh::ATTRIB_TANGENTS)); - AZ::Vector3* __restrict bitangents = static_cast(mMesh->FindVertexData(Mesh::ATTRIB_BITANGENTS)); - AZ::u32* __restrict orgVerts = static_cast(mMesh->FindVertexData(Mesh::ATTRIB_ORGVTXNUMBERS)); - SkinVertexRange(0, mMesh->GetNumVertices(), positions, normals, tangents, bitangents, orgVerts, layer); + AZ::Vector3* __restrict positions = static_cast(m_mesh->FindVertexData(Mesh::ATTRIB_POSITIONS)); + AZ::Vector3* __restrict normals = static_cast(m_mesh->FindVertexData(Mesh::ATTRIB_NORMALS)); + AZ::Vector4* __restrict tangents = static_cast(m_mesh->FindVertexData(Mesh::ATTRIB_TANGENTS)); + AZ::Vector3* __restrict bitangents = static_cast(m_mesh->FindVertexData(Mesh::ATTRIB_BITANGENTS)); + AZ::u32* __restrict orgVerts = static_cast(m_mesh->FindVertexData(Mesh::ATTRIB_ORGVTXNUMBERS)); + SkinVertexRange(0, m_mesh->GetNumVertices(), positions, normals, tangents, bitangents, orgVerts, layer); } @@ -134,7 +134,7 @@ namespace EMotionFX for (size_t i = 0; i < numInfluences; ++i) { const SkinInfluence* influence = layer->GetInfluence(orgVertex, i); - MCore::Skin(mBoneMatrices[influence->GetBoneNr()], &vtxPos, &normal, &tangent, &bitangent, &newPos, &newNormal, &newTangent, &newBitangent, influence->GetWeight()); + MCore::Skin(m_boneMatrices[influence->GetBoneNr()], &vtxPos, &normal, &tangent, &bitangent, &newPos, &newNormal, &newTangent, &newBitangent, influence->GetWeight()); } newTangent.SetW(tangents[v].GetW()); @@ -163,7 +163,7 @@ namespace EMotionFX for (size_t i = 0; i < numInfluences; ++i) { const SkinInfluence* influence = layer->GetInfluence(orgVertex, i); - MCore::Skin(mBoneMatrices[influence->GetBoneNr()], &vtxPos, &normal, &tangent, &newPos, &newNormal, &newTangent, influence->GetWeight()); + MCore::Skin(m_boneMatrices[influence->GetBoneNr()], &vtxPos, &normal, &tangent, &newPos, &newNormal, &newTangent, influence->GetWeight()); } newTangent.SetW(tangents[v].GetW()); @@ -190,7 +190,7 @@ namespace EMotionFX for (size_t i = 0; i < numInfluences; ++i) { const SkinInfluence* influence = layer->GetInfluence(orgVertex, i); - MCore::Skin(mBoneMatrices[influence->GetBoneNr()], &vtxPos, &normal, &newPos, &newNormal, influence->GetWeight()); + MCore::Skin(m_boneMatrices[influence->GetBoneNr()], &vtxPos, &normal, &newPos, &newNormal, influence->GetWeight()); } // output the skinned values @@ -209,24 +209,21 @@ namespace EMotionFX MCORE_UNUSED(lodLevel); // clear the bone information array - mBoneMatrices.clear(); - mNodeNumbers.clear(); + m_boneMatrices.clear(); + m_nodeNumbers.clear(); // if there is no mesh - if (mMesh == nullptr) + if (m_mesh == nullptr) { return; } // get the attribute number - SkinningInfoVertexAttributeLayer* skinningLayer = (SkinningInfoVertexAttributeLayer*)mMesh->FindSharedVertexAttributeLayer(SkinningInfoVertexAttributeLayer::TYPE_ID); + SkinningInfoVertexAttributeLayer* skinningLayer = (SkinningInfoVertexAttributeLayer*)m_mesh->FindSharedVertexAttributeLayer(SkinningInfoVertexAttributeLayer::TYPE_ID); MCORE_ASSERT(skinningLayer); - // reserve space for the bone array - //mBones.Reserve( actor->GetNumNodes() ); - // find out what bones this mesh uses - const uint32 numOrgVerts = mMesh->GetNumOrgVertices(); + const uint32 numOrgVerts = m_mesh->GetNumOrgVertices(); for (uint32 i = 0; i < numOrgVerts; i++) { // now we have located the skinning information for this vertex, we can see if our bones array @@ -246,17 +243,14 @@ namespace EMotionFX if (boneIndex == InvalidIndex) { // add the bone to the array of bones in this deformer - mNodeNumbers.emplace_back(influence->GetNodeNr()); - mBoneMatrices.emplace_back(mat); - boneIndex = mBoneMatrices.size() - 1; + m_nodeNumbers.emplace_back(influence->GetNodeNr()); + m_boneMatrices.emplace_back(mat); + boneIndex = m_boneMatrices.size() - 1; } // set the bone number in the influence influence->SetBoneNr(static_cast(boneIndex)); - //MCore::LogInfo("influence %d/%d = %s with weight %f [nodeIndex=%d] [boneIndex=%d]", a+1, numInfluences, actor->GetNode(influence->GetNodeNr())->GetName(), influence->GetWeight(), influence->GetNodeNr(), boneIndex); } } - // get rid of all items in the used bones array - // mBones.Shrink(); } } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/SoftSkinDeformer.h b/Gems/EMotionFX/Code/EMotionFX/Source/SoftSkinDeformer.h index 466f1702a7..ce157baf49 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/SoftSkinDeformer.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/SoftSkinDeformer.h @@ -100,26 +100,26 @@ namespace EMotionFX * This is the number of different bones that the skinning information of the mesh where this deformer works on uses. * @result The number of bones. */ - MCORE_INLINE size_t GetNumLocalBones() const { return mNodeNumbers.size(); } + MCORE_INLINE size_t GetNumLocalBones() const { return m_nodeNumbers.size(); } /** * Get the node number of a given local bone. * @param index The local bone number, which must be in range of [0..GetNumLocalBones()-1]. * @result The node number, which is in range of [0..Actor::GetNumNodes()-1], depending on the actor where this deformer works on. */ - MCORE_INLINE size_t GetLocalBone(size_t index) const { return mNodeNumbers[index]; } + MCORE_INLINE size_t GetLocalBone(size_t index) const { return m_nodeNumbers[index]; } /** * Pre-allocate space for a given number of local bones. * This does not alter the value returned by GetNumLocalBones(). * @param numBones The number of bones to pre-allocate space for. */ - MCORE_INLINE void ReserveLocalBones(size_t numBones) { mNodeNumbers.reserve(numBones); mBoneMatrices.reserve(numBones); } + MCORE_INLINE void ReserveLocalBones(size_t numBones) { m_nodeNumbers.reserve(numBones); m_boneMatrices.reserve(numBones); } protected: - AZStd::vector mBoneMatrices; - AZStd::vector mNodeNumbers; + AZStd::vector m_boneMatrices; + AZStd::vector m_nodeNumbers; /** * Default constructor. @@ -135,12 +135,12 @@ namespace EMotionFX /** * Find the entry number that uses a specified node number. * @param nodeIndex The node number to search for. - * @result The index inside the mBones member array, which uses the given node. + * @result The index inside the m_bones member array, which uses the given node. */ MCORE_INLINE size_t FindLocalBoneIndex(size_t nodeIndex) const { - const auto foundBoneIndex = AZStd::find(begin(mNodeNumbers), end(mNodeNumbers), nodeIndex); - return foundBoneIndex != end(mNodeNumbers) ? AZStd::distance(begin(mNodeNumbers), foundBoneIndex) : InvalidIndex; + const auto foundBoneIndex = AZStd::find(begin(m_nodeNumbers), end(m_nodeNumbers), nodeIndex); + return foundBoneIndex != end(m_nodeNumbers) ? AZStd::distance(begin(m_nodeNumbers), foundBoneIndex) : InvalidIndex; } void SkinVertexRange(uint32 startVertex, uint32 endVertex, AZ::Vector3* positions, AZ::Vector3* normals, AZ::Vector4* tangents, AZ::Vector3* bitangents, uint32* orgVerts, SkinningInfoVertexAttributeLayer* layer); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/SoftSkinManager.h b/Gems/EMotionFX/Code/EMotionFX/Source/SoftSkinManager.h index 946fd531d2..3682bc1abb 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/SoftSkinManager.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/SoftSkinManager.h @@ -51,8 +51,6 @@ namespace EMotionFX SoftSkinDeformer* CreateDeformer(Mesh* mesh); private: - //bool mDetectedSSE; /**< Does the cpu support SSE instructions? */ - /** * The constructor. * When constructed, the class checks if SSE is available on the hardware. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/SpringSolver.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/SpringSolver.cpp index 8765a0e991..83cbc41a36 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/SpringSolver.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/SpringSolver.cpp @@ -412,7 +412,7 @@ namespace EMotionFX const size_t jointIndexA = m_particles[spring.m_particleA].m_joint->GetSkeletonJointIndex(); const size_t jointIndexB = m_particles[spring.m_particleB].m_joint->GetSkeletonJointIndex(); const Pose* bindPose = m_actorInstance->GetTransformData()->GetBindPose(); - const float restLength = (bindPose->GetModelSpaceTransform(jointIndexB).mPosition - bindPose->GetModelSpaceTransform(jointIndexA).mPosition).GetLength(); + const float restLength = (bindPose->GetModelSpaceTransform(jointIndexB).m_position - bindPose->GetModelSpaceTransform(jointIndexA).m_position).GetLength(); if (restLength > AZ::Constants::FloatEpsilon) { spring.m_restLength = restLength; @@ -472,7 +472,7 @@ namespace EMotionFX const float radius = particle.m_joint->GetCollisionRadius() * scaleFactor; if (radius > 0.0f) { - const AZ::Quaternion& jointRotation = pose.GetWorldSpaceTransform(particle.m_joint->GetSkeletonJointIndex()).mRotation; + const AZ::Quaternion& jointRotation = pose.GetWorldSpaceTransform(particle.m_joint->GetSkeletonJointIndex()).m_rotation; drawData->DrawWireframeSphere(particle.m_pos, radius, AZ::Color(0.3f, 0.3f, 0.3f, 1.0f), jointRotation, 12, 12); } } @@ -485,7 +485,7 @@ namespace EMotionFX { if (collider.GetType() == CollisionObject::CollisionType::Sphere) { - const AZ::Quaternion& jointRotation = pose.GetWorldSpaceTransform(collider.m_jointIndex).mRotation; + const AZ::Quaternion& jointRotation = pose.GetWorldSpaceTransform(collider.m_jointIndex).m_rotation; drawData->DrawWireframeSphere(collider.m_globalStart, collider.m_scaledRadius, color * 0.65f, jointRotation, 16, 16); } else if (collider.GetType() == CollisionObject::CollisionType::Capsule) @@ -562,7 +562,7 @@ namespace EMotionFX AZ_Assert(joint->GetMass() > AZ::Constants::FloatEpsilon, "Expected mass to be larger than zero."); Particle particle; particle.m_joint = joint; - particle.m_pos = m_actorInstance->GetTransformData()->GetBindPose()->GetModelSpaceTransform(joint->GetSkeletonJointIndex()).mPosition; + particle.m_pos = m_actorInstance->GetTransformData()->GetBindPose()->GetModelSpaceTransform(joint->GetSkeletonJointIndex()).m_position; particle.m_oldPos = particle.m_pos; particle.m_parentParticleIndex = m_parentParticle; m_particles.emplace_back(particle); @@ -586,8 +586,8 @@ namespace EMotionFX if (restLength < 0.0f) { const Pose* pose = m_actorInstance->GetTransformData()->GetCurrentPose(); - const AZ::Vector3 posA = pose->GetWorldSpaceTransform(nodeA).mPosition; - const AZ::Vector3 posB = pose->GetWorldSpaceTransform(nodeB).mPosition; + const AZ::Vector3 posA = pose->GetWorldSpaceTransform(nodeA).m_position; + const AZ::Vector3 posB = pose->GetWorldSpaceTransform(nodeB).m_position; restLength = (posB - posA).GetLength(); } @@ -695,7 +695,7 @@ namespace EMotionFX float SpringSolver::GetScaleFactor() const { #ifndef EMFX_SCALE_DISABLED - float scaleFactor = m_actorInstance->GetWorldSpaceTransform().mScale.GetX(); + float scaleFactor = m_actorInstance->GetWorldSpaceTransform().m_scale.GetX(); if (AZ::IsClose(scaleFactor, 0.0f, AZ::Constants::FloatEpsilon)) { return AZ::Constants::FloatEpsilon; @@ -725,7 +725,7 @@ namespace EMotionFX if (stiffnessFactor > 0.0f) { const Transform jointWorldTransform = pose.GetWorldSpaceTransform(joint->GetSkeletonJointIndex()); - const AZ::Vector3 force = (jointWorldTransform.mPosition - particle.m_pos) + particle.m_externalForce; + const AZ::Vector3 force = (jointWorldTransform.m_position - particle.m_pos) + particle.m_externalForce; particle.m_force += force * stiffnessFactor; } @@ -816,17 +816,17 @@ namespace EMotionFX } else if (pinnedA && pinnedB) { - particleA.m_pos = worldTransformA.mPosition; - particleB.m_pos = worldTransformB.mPosition; + particleA.m_pos = worldTransformA.m_position; + particleB.m_pos = worldTransformB.m_position; } else if (pinnedB) { - particleB.m_pos = worldTransformB.mPosition; + particleB.m_pos = worldTransformB.m_position; particleA.m_pos += delta * diff; } else // Only particleA is pinned. { - particleA.m_pos = worldTransformA.mPosition; + particleA.m_pos = worldTransformA.m_position; particleB.m_pos -= delta * diff; } @@ -839,7 +839,7 @@ namespace EMotionFX } else { - particleB.m_limitDir = worldTransformA.mPosition - worldTransformB.mPosition; + particleB.m_limitDir = worldTransformA.m_position - worldTransformB.m_position; } PerformConeLimit(particleA, particleB, particleB.m_limitDir); } @@ -886,7 +886,7 @@ namespace EMotionFX const SimulatedJoint* joint = particle.m_joint; if (joint->IsPinned()) { - particle.m_pos = pose.GetWorldSpaceTransform(joint->GetSkeletonJointIndex()).mPosition; + particle.m_pos = pose.GetWorldSpaceTransform(joint->GetSkeletonJointIndex()).m_position; particle.m_oldPos = particle.m_pos; particle.m_force = AZ::Vector3::CreateZero(); } @@ -954,15 +954,15 @@ namespace EMotionFX const Particle& particleB = m_particles[spring.m_particleB]; Transform modelTransformB = pose.GetModelSpaceTransform(particleB.m_joint->GetSkeletonJointIndex()); const Transform& modelTransformA = pose.GetModelSpaceTransform(particleA.m_joint->GetSkeletonJointIndex()); - const AZ::Vector3 oldDir = (modelTransformA.mPosition - modelTransformB.mPosition).GetNormalizedSafe(); + const AZ::Vector3 oldDir = (modelTransformA.m_position - modelTransformB.m_position).GetNormalizedSafe(); const AZ::Vector3 newDir = m_actorInstance->GetWorldSpaceTransformInversed().TransformVector(particleA.m_pos - particleB.m_pos).GetNormalizedSafe(); - modelTransformB.mRotation = AZ::Quaternion::CreateShortestArc(oldDir, newDir).GetNormalized() * modelTransformB.mRotation; - modelTransformB.mRotation.Normalize(); + modelTransformB.m_rotation = AZ::Quaternion::CreateShortestArc(oldDir, newDir).GetNormalized() * modelTransformB.m_rotation; + modelTransformB.m_rotation.Normalize(); if (spring.m_allowStretch) { - modelTransformB.mPosition = particleB.m_pos; + modelTransformB.m_position = particleB.m_pos; } pose.SetModelSpaceTransform(particleB.m_joint->GetSkeletonJointIndex(), modelTransformB); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/StandardMaterial.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/StandardMaterial.cpp index 5f5c439f7c..ab89b0f4b2 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/StandardMaterial.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/StandardMaterial.cpp @@ -20,15 +20,15 @@ namespace EMotionFX StandardMaterialLayer::StandardMaterialLayer() : BaseObject() { - mLayerTypeID = LAYERTYPE_UNKNOWN; - mFileNameID = MCORE_INVALIDINDEX32; - mBlendMode = LAYERBLENDMODE_NONE; - mAmount = 1.0f; - mUOffset = 0.0f; - mVOffset = 0.0f; - mUTiling = 1.0f; - mVTiling = 1.0f; - mRotationRadians = 0.0f; + m_layerTypeId = LAYERTYPE_UNKNOWN; + m_fileNameId = MCORE_INVALIDINDEX32; + m_blendMode = LAYERBLENDMODE_NONE; + m_amount = 1.0f; + m_uOffset = 0.0f; + m_vOffset = 0.0f; + m_uTiling = 1.0f; + m_vTiling = 1.0f; + m_rotationRadians = 0.0f; } @@ -36,17 +36,17 @@ namespace EMotionFX StandardMaterialLayer::StandardMaterialLayer(uint32 layerType, const char* fileName, float amount) : BaseObject() { - mLayerTypeID = layerType; - mAmount = amount; - mUOffset = 0.0f; - mVOffset = 0.0f; - mUTiling = 1.0f; - mVTiling = 1.0f; - mRotationRadians = 0.0f; - mBlendMode = LAYERBLENDMODE_NONE; + m_layerTypeId = layerType; + m_amount = amount; + m_uOffset = 0.0f; + m_vOffset = 0.0f; + m_uTiling = 1.0f; + m_vTiling = 1.0f; + m_rotationRadians = 0.0f; + m_blendMode = LAYERBLENDMODE_NONE; // calculate the ID - mFileNameID = MCore::GetStringIdPool().GenerateIdForString(fileName); + m_fileNameId = MCore::GetStringIdPool().GenerateIdForString(fileName); } @@ -73,22 +73,22 @@ namespace EMotionFX // init from another layer void StandardMaterialLayer::InitFrom(StandardMaterialLayer* layer) { - mLayerTypeID = layer->mLayerTypeID; - mFileNameID = layer->mFileNameID; - mBlendMode = layer->mBlendMode; - mAmount = layer->mAmount; - mUOffset = layer->mUOffset; - mVOffset = layer->mVOffset; - mUTiling = layer->mUTiling; - mVTiling = layer->mVTiling; - mRotationRadians = layer->mRotationRadians; + m_layerTypeId = layer->m_layerTypeId; + m_fileNameId = layer->m_fileNameId; + m_blendMode = layer->m_blendMode; + m_amount = layer->m_amount; + m_uOffset = layer->m_uOffset; + m_vOffset = layer->m_vOffset; + m_uTiling = layer->m_uTiling; + m_vTiling = layer->m_vTiling; + m_rotationRadians = layer->m_rotationRadians; } // return the layer type string const char* StandardMaterialLayer::GetTypeString() const { - switch (mLayerTypeID) + switch (m_layerTypeId) { case LAYERTYPE_UNKNOWN: { @@ -163,7 +163,7 @@ namespace EMotionFX // return the blend mode string const char* StandardMaterialLayer::GetBlendModeString() const { - switch (mBlendMode) + switch (m_blendMode) { case LAYERBLENDMODE_NONE: { @@ -225,116 +225,116 @@ namespace EMotionFX float StandardMaterialLayer::GetUOffset() const { - return mUOffset; + return m_uOffset; } float StandardMaterialLayer::GetVOffset() const { - return mVOffset; + return m_vOffset; } float StandardMaterialLayer::GetUTiling() const { - return mUTiling; + return m_uTiling; } float StandardMaterialLayer::GetVTiling() const { - return mVTiling; + return m_vTiling; } float StandardMaterialLayer::GetRotationRadians() const { - return mRotationRadians; + return m_rotationRadians; } void StandardMaterialLayer::SetUOffset(float uOffset) { - mUOffset = uOffset; + m_uOffset = uOffset; } void StandardMaterialLayer::SetVOffset(float vOffset) { - mVOffset = vOffset; + m_vOffset = vOffset; } void StandardMaterialLayer::SetUTiling(float uTiling) { - mUTiling = uTiling; + m_uTiling = uTiling; } void StandardMaterialLayer::SetVTiling(float vTiling) { - mVTiling = vTiling; + m_vTiling = vTiling; } void StandardMaterialLayer::SetRotationRadians(float rotationRadians) { - mRotationRadians = rotationRadians; + m_rotationRadians = rotationRadians; } const char* StandardMaterialLayer::GetFileName() const { - return MCore::GetStringIdPool().GetName(mFileNameID).c_str(); + return MCore::GetStringIdPool().GetName(m_fileNameId).c_str(); } const AZStd::string& StandardMaterialLayer::GetFileNameString() const { - return MCore::GetStringIdPool().GetName(mFileNameID); + return MCore::GetStringIdPool().GetName(m_fileNameId); } void StandardMaterialLayer::SetFileName(const char* fileName) { // calculate the new ID - mFileNameID = MCore::GetStringIdPool().GenerateIdForString(fileName); + m_fileNameId = MCore::GetStringIdPool().GenerateIdForString(fileName); } void StandardMaterialLayer::SetAmount(float amount) { - mAmount = amount; + m_amount = amount; } float StandardMaterialLayer::GetAmount() const { - return mAmount; + return m_amount; } uint32 StandardMaterialLayer::GetType() const { - return mLayerTypeID; + return m_layerTypeId; } void StandardMaterialLayer::SetType(uint32 typeID) { - mLayerTypeID = typeID; + m_layerTypeId = typeID; } void StandardMaterialLayer::SetBlendMode(unsigned char layerBlendMode) { - mBlendMode = layerBlendMode; + m_blendMode = layerBlendMode; } unsigned char StandardMaterialLayer::GetBlendMode() const { - return mBlendMode; + return m_blendMode; } @@ -346,16 +346,16 @@ namespace EMotionFX StandardMaterial::StandardMaterial(const char* name) : Material(name) { - mAmbient = MCore::RGBAColor(0.2f, 0.2f, 0.2f); - mDiffuse = MCore::RGBAColor(1.0f, 0.0f, 0.0f); - mSpecular = MCore::RGBAColor(1.0f, 1.0f, 1.0f); - mEmissive = MCore::RGBAColor(1.0f, 0.0f, 0.0f); - mShine = 100.0f; - mShineStrength = 1.0f; - mOpacity = 1.0f; - mIOR = 1.5f; - mDoubleSided = true; - mWireFrame = false; + m_ambient = MCore::RGBAColor(0.2f, 0.2f, 0.2f); + m_diffuse = MCore::RGBAColor(1.0f, 0.0f, 0.0f); + m_specular = MCore::RGBAColor(1.0f, 1.0f, 1.0f); + m_emissive = MCore::RGBAColor(1.0f, 0.0f, 0.0f); + m_shine = 100.0f; + m_shineStrength = 1.0f; + m_opacity = 1.0f; + m_ior = 1.5f; + m_doubleSided = true; + m_wireFrame = false; } @@ -384,24 +384,24 @@ namespace EMotionFX StandardMaterial* standardMaterial = static_cast(clone); // copy the attributes - standardMaterial->mAmbient = mAmbient; - standardMaterial->mDiffuse = mDiffuse; - standardMaterial->mSpecular = mSpecular; - standardMaterial->mEmissive = mEmissive; - standardMaterial->mShine = mShine; - standardMaterial->mShineStrength = mShineStrength; - standardMaterial->mOpacity = mOpacity; - standardMaterial->mIOR = mIOR; - standardMaterial->mDoubleSided = mDoubleSided; - standardMaterial->mWireFrame = mWireFrame; + standardMaterial->m_ambient = m_ambient; + standardMaterial->m_diffuse = m_diffuse; + standardMaterial->m_specular = m_specular; + standardMaterial->m_emissive = m_emissive; + standardMaterial->m_shine = m_shine; + standardMaterial->m_shineStrength = m_shineStrength; + standardMaterial->m_opacity = m_opacity; + standardMaterial->m_ior = m_ior; + standardMaterial->m_doubleSided = m_doubleSided; + standardMaterial->m_wireFrame = m_wireFrame; // copy the layers - const size_t numLayers = mLayers.size(); - standardMaterial->mLayers.resize(numLayers); + const size_t numLayers = m_layers.size(); + standardMaterial->m_layers.resize(numLayers); for (size_t i = 0; i < numLayers; ++i) { - standardMaterial->mLayers[i] = StandardMaterialLayer::Create(); - standardMaterial->mLayers[i]->InitFrom(mLayers[i]); + standardMaterial->m_layers[i] = StandardMaterialLayer::Create(); + standardMaterial->m_layers[i]->InitFrom(m_layers[i]); } // return the result @@ -418,9 +418,9 @@ namespace EMotionFX { layer->Destroy(); } - if (const auto it = AZStd::find(begin(mLayers), end(mLayers), layer); it != end(mLayers)) + if (const auto it = AZStd::find(begin(m_layers), end(m_layers), layer); it != end(m_layers)) { - mLayers.erase(it); + m_layers.erase(it); } } } @@ -428,180 +428,180 @@ namespace EMotionFX void StandardMaterial::SetAmbient(const MCore::RGBAColor& ambient) { - mAmbient = ambient; + m_ambient = ambient; } void StandardMaterial::SetDiffuse(const MCore::RGBAColor& diffuse) { - mDiffuse = diffuse; + m_diffuse = diffuse; } void StandardMaterial::SetSpecular(const MCore::RGBAColor& specular) { - mSpecular = specular; + m_specular = specular; } void StandardMaterial::SetEmissive(const MCore::RGBAColor& emissive) { - mEmissive = emissive; + m_emissive = emissive; } void StandardMaterial::SetShine(float shine) { - mShine = shine; + m_shine = shine; } void StandardMaterial::SetShineStrength(float shineStrength) { - mShineStrength = shineStrength; + m_shineStrength = shineStrength; } void StandardMaterial::SetOpacity(float opacity) { - mOpacity = opacity; + m_opacity = opacity; } void StandardMaterial::SetIOR(float ior) { - mIOR = ior; + m_ior = ior; } void StandardMaterial::SetDoubleSided(bool doubleSided) { - mDoubleSided = doubleSided; + m_doubleSided = doubleSided; } void StandardMaterial::SetWireFrame(bool wireFrame) { - mWireFrame = wireFrame; + m_wireFrame = wireFrame; } const MCore::RGBAColor& StandardMaterial::GetAmbient() const { - return mAmbient; + return m_ambient; } const MCore::RGBAColor& StandardMaterial::GetDiffuse() const { - return mDiffuse; + return m_diffuse; } const MCore::RGBAColor& StandardMaterial::GetSpecular() const { - return mSpecular; + return m_specular; } const MCore::RGBAColor& StandardMaterial::GetEmissive() const { - return mEmissive; + return m_emissive; } float StandardMaterial::GetShine() const { - return mShine; + return m_shine; } float StandardMaterial::GetShineStrength() const { - return mShineStrength; + return m_shineStrength; } float StandardMaterial::GetOpacity() const { - return mOpacity; + return m_opacity; } float StandardMaterial::GetIOR() const { - return mIOR; + return m_ior; } bool StandardMaterial::GetDoubleSided() const { - return mDoubleSided; + return m_doubleSided; } bool StandardMaterial::GetWireFrame() const { - return mWireFrame; + return m_wireFrame; } StandardMaterialLayer* StandardMaterial::AddLayer(StandardMaterialLayer* layer) { - mLayers.emplace_back(layer); + m_layers.emplace_back(layer); return layer; } size_t StandardMaterial::GetNumLayers() const { - return mLayers.size(); + return m_layers.size(); } StandardMaterialLayer* StandardMaterial::GetLayer(size_t nr) { - MCORE_ASSERT(nr < mLayers.size()); - return mLayers[nr]; + MCORE_ASSERT(nr < m_layers.size()); + return m_layers[nr]; } void StandardMaterial::RemoveLayer(size_t nr, bool delFromMem) { - MCORE_ASSERT(nr < mLayers.size()); + MCORE_ASSERT(nr < m_layers.size()); if (delFromMem) { - mLayers[nr]->Destroy(); + m_layers[nr]->Destroy(); } - mLayers.erase(AZStd::next(begin(mLayers), nr)); + m_layers.erase(AZStd::next(begin(m_layers), nr)); } void StandardMaterial::RemoveAllLayers() { - for (StandardMaterialLayer* layer : mLayers) + for (StandardMaterialLayer* layer : m_layers) { layer->Destroy(); } - mLayers.clear(); + m_layers.clear(); } size_t StandardMaterial::FindLayer(uint32 layerType) const { // search through all layers - const auto foundLayer = AZStd::find_if(begin(mLayers), end(mLayers), [layerType](const StandardMaterialLayer* layer) + const auto foundLayer = AZStd::find_if(begin(m_layers), end(m_layers), [layerType](const StandardMaterialLayer* layer) { return layer->GetType() == layerType; }); - return foundLayer != end(mLayers) ? AZStd::distance(begin(mLayers), foundLayer) : InvalidIndex; + return foundLayer != end(m_layers) ? AZStd::distance(begin(m_layers), foundLayer) : InvalidIndex; } void StandardMaterial::ReserveLayers(size_t numLayers) { - mLayers.reserve(numLayers); + m_layers.reserve(numLayers); } } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/StandardMaterial.h b/Gems/EMotionFX/Code/EMotionFX/Source/StandardMaterial.h index 05f8154a72..6e90d8cf1f 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/StandardMaterial.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/StandardMaterial.h @@ -223,15 +223,15 @@ namespace EMotionFX float GetRotationRadians() const; private: - uint32 mFileNameID; /**< The filename of the texture, without extension or path. */ - uint32 mLayerTypeID; /**< The layer type. See the enum for some possibilities. */ - float mAmount; /**< The amount value, between 0 and 1. This can for example represent how intens the layer is. */ - float mUOffset; /**< U offset (horizontal texture shift). */ - float mVOffset; /**< V offset (vertical texture shift). */ - float mUTiling; /**< Horizontal tiling factor. */ - float mVTiling; /**< Vertical tiling factor. */ - float mRotationRadians; /**< Texture rotation in radians. */ - unsigned char mBlendMode; /**< The blend mode is used to control how successive layers of textures are combined together. */ + uint32 m_fileNameId; /**< The filename of the texture, without extension or path. */ + uint32 m_layerTypeId; /**< The layer type. See the enum for some possibilities. */ + float m_amount; /**< The amount value, between 0 and 1. This can for example represent how intens the layer is. */ + float m_uOffset; /**< U offset (horizontal texture shift). */ + float m_vOffset; /**< V offset (vertical texture shift). */ + float m_uTiling; /**< Horizontal tiling factor. */ + float m_vTiling; /**< Vertical tiling factor. */ + float m_rotationRadians; /**< Texture rotation in radians. */ + unsigned char m_blendMode; /**< The blend mode is used to control how successive layers of textures are combined together. */ /** * Default constructor. @@ -471,17 +471,17 @@ namespace EMotionFX protected: - AZStd::vector< StandardMaterialLayer* > mLayers; /**< StandardMaterial layers. */ - MCore::RGBAColor mAmbient; /**< Ambient color. */ - MCore::RGBAColor mDiffuse; /**< Diffuse color. */ - MCore::RGBAColor mSpecular; /**< Specular color. */ - MCore::RGBAColor mEmissive; /**< Self illumination color. */ - float mShine; /**< The shine value, from the phong component (the power). */ - float mShineStrength; /**< Shine strength. */ - float mOpacity; /**< The opacity amount [1.0=full opac, 0.0=full transparent]. */ - float mIOR; /**< Index of refraction. */ - bool mDoubleSided; /**< Double sided?. */ - bool mWireFrame; /**< Render in wireframe?. */ + AZStd::vector< StandardMaterialLayer* > m_layers; /**< StandardMaterial layers. */ + MCore::RGBAColor m_ambient; /**< Ambient color. */ + MCore::RGBAColor m_diffuse; /**< Diffuse color. */ + MCore::RGBAColor m_specular; /**< Specular color. */ + MCore::RGBAColor m_emissive; /**< Self illumination color. */ + float m_shine; /**< The shine value, from the phong component (the power). */ + float m_shineStrength; /**< Shine strength. */ + float m_opacity; /**< The opacity amount [1.0=full opac, 0.0=full transparent]. */ + float m_ior; /**< Index of refraction. */ + bool m_doubleSided; /**< Double sided?. */ + bool m_wireFrame; /**< Render in wireframe?. */ /** * Constructor. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/SubMesh.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/SubMesh.cpp index d18006527f..548816b82c 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/SubMesh.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/SubMesh.cpp @@ -21,14 +21,14 @@ namespace EMotionFX // constructor SubMesh::SubMesh(Mesh* parentMesh, uint32 startVertex, uint32 startIndex, uint32 startPolygon, uint32 numVerts, uint32 numIndices, uint32 numPolygons, uint32 materialIndex, size_t numBones) { - mParentMesh = parentMesh; - mNumVertices = numVerts; - mNumIndices = numIndices; - mNumPolygons = numPolygons; - mStartIndex = startIndex; - mStartVertex = startVertex; - mStartPolygon = startPolygon; - mMaterial = materialIndex; + m_parentMesh = parentMesh; + m_numVertices = numVerts; + m_numIndices = numIndices; + m_numPolygons = numPolygons; + m_startIndex = startIndex; + m_startVertex = startVertex; + m_startPolygon = startPolygon; + m_material = materialIndex; SetNumBones(numBones); } @@ -50,8 +50,8 @@ namespace EMotionFX // clone the submesh SubMesh* SubMesh::Clone(Mesh* newParentMesh) { - SubMesh* clone = aznew SubMesh(newParentMesh, mStartVertex, mStartIndex, mStartPolygon, mNumVertices, mNumIndices, mNumPolygons, mMaterial, mBones.size()); - clone->mBones = mBones; + SubMesh* clone = aznew SubMesh(newParentMesh, m_startVertex, m_startIndex, m_startPolygon, m_numVertices, m_numIndices, m_numPolygons, m_material, m_bones.size()); + clone->m_bones = m_bones; return clone; } @@ -59,7 +59,7 @@ namespace EMotionFX // remap bone (oldNodeNr) to bone (newNodeNr) void SubMesh::RemapBone(size_t oldNodeNr, size_t newNodeNr) { - AZStd::replace(mBones.begin(), mBones.end(), oldNodeNr, newNodeNr); + AZStd::replace(m_bones.begin(), m_bones.end(), oldNodeNr, newNodeNr); } @@ -67,10 +67,10 @@ namespace EMotionFX void SubMesh::ReinitBonesArray(SkinningInfoVertexAttributeLayer* skinLayer) { // clear the bones array - mBones.clear(); + m_bones.clear(); // get shortcuts to the original vertex numbers - const uint32* orgVertices = (uint32*)mParentMesh->FindOriginalVertexData(Mesh::ATTRIB_ORGVTXNUMBERS); + const uint32* orgVertices = (uint32*)m_parentMesh->FindOriginalVertexData(Mesh::ATTRIB_ORGVTXNUMBERS); // for all vertices in the submesh const uint32 startVertex = GetStartVertex(); @@ -89,9 +89,9 @@ namespace EMotionFX const uint16 nodeNr = influence->GetNodeNr(); // put the node index in the bones array in case it isn't in already - if (AZStd::find(begin(mBones), end(mBones), nodeNr) == end(mBones)) + if (AZStd::find(begin(m_bones), end(m_bones), nodeNr) == end(m_bones)) { - mBones.emplace_back(nodeNr); + m_bones.emplace_back(nodeNr); } } } @@ -116,118 +116,118 @@ namespace EMotionFX uint32 SubMesh::GetStartIndex() const { - return mStartIndex; + return m_startIndex; } uint32 SubMesh::GetStartVertex() const { - return mStartVertex; + return m_startVertex; } uint32 SubMesh::GetStartPolygon() const { - return mStartPolygon; + return m_startPolygon; } uint32* SubMesh::GetIndices() const { - return (uint32*)(((uint8*)mParentMesh->GetIndices()) + mStartIndex * sizeof(uint32)); + return (uint32*)(((uint8*)m_parentMesh->GetIndices()) + m_startIndex * sizeof(uint32)); } uint8* SubMesh::GetPolygonVertexCounts() const { - uint8* polyVertCounts = mParentMesh->GetPolygonVertexCounts(); - return &polyVertCounts[mStartPolygon]; + uint8* polyVertCounts = m_parentMesh->GetPolygonVertexCounts(); + return &polyVertCounts[m_startPolygon]; } uint32 SubMesh::GetNumVertices() const { - return mNumVertices; + return m_numVertices; } uint32 SubMesh::GetNumIndices() const { - return mNumIndices; + return m_numIndices; } uint32 SubMesh::GetNumPolygons() const { - return mNumPolygons; + return m_numPolygons; } Mesh* SubMesh::GetParentMesh() const { - return mParentMesh; + return m_parentMesh; } void SubMesh::SetParentMesh(Mesh* mesh) { - mParentMesh = mesh; + m_parentMesh = mesh; } void SubMesh::SetMaterial(uint32 materialIndex) { - mMaterial = materialIndex; + m_material = materialIndex; } uint32 SubMesh::GetMaterial() const { - return mMaterial; + return m_material; } void SubMesh::SetStartIndex(uint32 indexOffset) { - mStartIndex = indexOffset; + m_startIndex = indexOffset; } void SubMesh::SetStartPolygon(uint32 polygonNumber) { - mStartPolygon = polygonNumber; + m_startPolygon = polygonNumber; } void SubMesh::SetStartVertex(uint32 vertexOffset) { - mStartVertex = vertexOffset; + m_startVertex = vertexOffset; } void SubMesh::SetNumIndices(uint32 numIndices) { - mNumIndices = numIndices; + m_numIndices = numIndices; } void SubMesh::SetNumVertices(uint32 numVertices) { - mNumVertices = numVertices; + m_numVertices = numVertices; } size_t SubMesh::FindBoneIndex(size_t nodeNr) const { - const auto foundBone = AZStd::find(mBones.begin(), mBones.end(), nodeNr); - return foundBone != mBones.end() ? AZStd::distance(mBones.begin(), foundBone) : InvalidIndex; + const auto foundBone = AZStd::find(m_bones.begin(), m_bones.end(), nodeNr); + return foundBone != m_bones.end() ? AZStd::distance(m_bones.begin(), foundBone) : InvalidIndex; } // remove the given bone void SubMesh::RemoveBone(size_t index) { - mBones.erase(AZStd::next(begin(mBones), index)); + m_bones.erase(AZStd::next(begin(m_bones), index)); } @@ -235,17 +235,17 @@ namespace EMotionFX { if (numBones == 0) { - mBones.clear(); + m_bones.clear(); } else { - mBones.resize(numBones); + m_bones.resize(numBones); } } void SubMesh::SetBone(size_t index, size_t nodeIndex) { - mBones[index] = nodeIndex; + m_bones[index] = nodeIndex; } } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/SubMesh.h b/Gems/EMotionFX/Code/EMotionFX/Source/SubMesh.h index d234a9e4c1..57e3f2b486 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/SubMesh.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/SubMesh.h @@ -191,35 +191,35 @@ namespace EMotionFX * Get the number of bones used by this submesh. * @result The number of bones used by this submesh. */ - MCORE_INLINE size_t GetNumBones() const { return mBones.size(); } + MCORE_INLINE size_t GetNumBones() const { return m_bones.size(); } /** * Get the node index for a given bone. * @param index The bone number, which must be in range of [0..GetNumBones()-1]. * @result The node index value for the given bone. */ - MCORE_INLINE size_t GetBone(size_t index) const { return mBones[index]; } + MCORE_INLINE size_t GetBone(size_t index) const { return m_bones[index]; } /** * Get direct access to the bone values, by getting a pointer to the first bone index. * Each integer in the array represents the node number that acts as bone on this submesh. * @result A pointer to the array of bones used by this submesh. */ - MCORE_INLINE size_t* GetBones() { return mBones.data(); } + MCORE_INLINE size_t* GetBones() { return m_bones.data(); } /** * Get direct access to the bones array. * Each integer in the array represents the node number that acts as bone on this submesh. * @result A read only reference to the array of bones used by this submesh. */ - MCORE_INLINE const AZStd::vector& GetBonesArray() const { return mBones; } + MCORE_INLINE const AZStd::vector& GetBonesArray() const { return m_bones; } /** * Get direct access to the bones array. * Each integer in the array represents the node number that acts as bone on this submesh. * @result A reference to the array of bones used by this submesh. */ - MCORE_INLINE AZStd::vector& GetBonesArray() { return mBones; } + MCORE_INLINE AZStd::vector& GetBonesArray() { return m_bones; } /** * Reinitialize the bones. @@ -268,15 +268,15 @@ namespace EMotionFX protected: - AZStd::vector mBones; /**< The collection of bones. These are stored as node numbers that point into the actor. */ - uint32 mStartVertex; /**< The start vertex number in the vertex data arrays of the parent mesh. */ - uint32 mStartIndex; /**< The start index number in the index array of the parent mesh. */ - uint32 mStartPolygon; /**< The start polygon number in the polygon vertex count array of the parent mesh. */ - uint32 mNumVertices; /**< The number of vertices in this submesh. */ - uint32 mNumIndices; /**< The number of indices in this submesh. */ - uint32 mNumPolygons; /**< The number of polygons in this submesh. */ - uint32 mMaterial; /**< The material index, which points into the materials array in the Node class. */ - Mesh* mParentMesh; /**< The parent mesh. */ + AZStd::vector m_bones; /**< The collection of bones. These are stored as node numbers that point into the actor. */ + uint32 m_startVertex; /**< The start vertex number in the vertex data arrays of the parent mesh. */ + uint32 m_startIndex; /**< The start index number in the index array of the parent mesh. */ + uint32 m_startPolygon; /**< The start polygon number in the polygon vertex count array of the parent mesh. */ + uint32 m_numVertices; /**< The number of vertices in this submesh. */ + uint32 m_numIndices; /**< The number of indices in this submesh. */ + uint32 m_numPolygons; /**< The number of polygons in this submesh. */ + uint32 m_material; /**< The material index, which points into the materials array in the Node class. */ + Mesh* m_parentMesh; /**< The parent mesh. */ /** * Constructor. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/ThreadData.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/ThreadData.cpp index e0e3f2ba3c..d36a568245 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/ThreadData.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/ThreadData.cpp @@ -19,14 +19,14 @@ namespace EMotionFX ThreadData::ThreadData() : BaseObject() { - mThreadIndex = MCORE_INVALIDINDEX32; + m_threadIndex = MCORE_INVALIDINDEX32; } // constructor ThreadData::ThreadData(uint32 threadIndex) { - mThreadIndex = threadIndex; + m_threadIndex = threadIndex; } @@ -52,12 +52,12 @@ namespace EMotionFX void ThreadData::SetThreadIndex(uint32 index) { - mThreadIndex = index; + m_threadIndex = index; } uint32 ThreadData::GetThreadIndex() const { - return mThreadIndex; + return m_threadIndex; } } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/ThreadData.h b/Gems/EMotionFX/Code/EMotionFX/Source/ThreadData.h index cf66a1543e..3ad8ae605a 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/ThreadData.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/ThreadData.h @@ -34,16 +34,16 @@ namespace EMotionFX void SetThreadIndex(uint32 index); uint32 GetThreadIndex() const; - MCORE_INLINE const AnimGraphPosePool& GetPosePool() const { return mPosePool; } - MCORE_INLINE AnimGraphPosePool& GetPosePool() { return mPosePool; } + MCORE_INLINE const AnimGraphPosePool& GetPosePool() const { return m_posePool; } + MCORE_INLINE AnimGraphPosePool& GetPosePool() { return m_posePool; } - MCORE_INLINE AnimGraphRefCountedDataPool& GetRefCountedDataPool() { return mRefCountedDataPool; } - MCORE_INLINE const AnimGraphRefCountedDataPool& GetRefCountedDataPool() const { return mRefCountedDataPool; } + MCORE_INLINE AnimGraphRefCountedDataPool& GetRefCountedDataPool() { return m_refCountedDataPool; } + MCORE_INLINE const AnimGraphRefCountedDataPool& GetRefCountedDataPool() const { return m_refCountedDataPool; } private: - uint32 mThreadIndex; - AnimGraphPosePool mPosePool; - AnimGraphRefCountedDataPool mRefCountedDataPool; + uint32 m_threadIndex; + AnimGraphPosePool m_posePool; + AnimGraphRefCountedDataPool m_refCountedDataPool; ThreadData(); ThreadData(uint32 threadIndex); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Transform.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Transform.cpp index 77f3382d6c..d8b9015044 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Transform.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Transform.cpp @@ -52,12 +52,12 @@ namespace EMotionFX // set void Transform::Set(const AZ::Vector3& position, const AZ::Quaternion& rotation) { - mRotation = rotation; - mPosition = position; + m_rotation = rotation; + m_position = position; EMFX_SCALECODE ( - mScale = AZ::Vector3::CreateOne(); + m_scale = AZ::Vector3::CreateOne(); ) } @@ -69,12 +69,12 @@ namespace EMotionFX MCORE_UNUSED(scale); #endif - mRotation = rotation; - mPosition = position; + m_rotation = rotation; + m_position = position; EMFX_SCALECODE ( - mScale = scale; + m_scale = scale; ) } @@ -82,19 +82,19 @@ namespace EMotionFX // check if this transform is equal to another bool Transform::operator == (const Transform& right) const { - if (MCore::Compare::CheckIfIsClose(mPosition, right.mPosition, MCore::Math::epsilon) == false) + if (MCore::Compare::CheckIfIsClose(m_position, right.m_position, MCore::Math::epsilon) == false) { return false; } - if (MCore::Compare::CheckIfIsClose(mRotation, right.mRotation, MCore::Math::epsilon) == false) + if (MCore::Compare::CheckIfIsClose(m_rotation, right.m_rotation, MCore::Math::epsilon) == false) { return false; } EMFX_SCALECODE ( - if (MCore::Compare::CheckIfIsClose(mScale, right.mScale, MCore::Math::epsilon) == false) + if (MCore::Compare::CheckIfIsClose(m_scale, right.m_scale, MCore::Math::epsilon) == false) { return false; } @@ -107,19 +107,19 @@ namespace EMotionFX // check if this transform is not equal to another bool Transform::operator != (const Transform& right) const { - if (MCore::Compare::CheckIfIsClose(mPosition, right.mPosition, MCore::Math::epsilon)) + if (MCore::Compare::CheckIfIsClose(m_position, right.m_position, MCore::Math::epsilon)) { return true; } - if (MCore::Compare::CheckIfIsClose(mRotation, right.mRotation, MCore::Math::epsilon)) + if (MCore::Compare::CheckIfIsClose(m_rotation, right.m_rotation, MCore::Math::epsilon)) { return true; } EMFX_SCALECODE ( - if (MCore::Compare::CheckIfIsClose(mScale, right.mScale, MCore::Math::epsilon)) + if (MCore::Compare::CheckIfIsClose(m_scale, right.m_scale, MCore::Math::epsilon)) { return true; } @@ -178,15 +178,15 @@ namespace EMotionFX void Transform::InitFromAZTransform(const AZ::Transform& transform) { #ifndef EMFX_SCALE_DISABLED - mPosition = transform.GetTranslation(); - mScale = AZ::Vector3(transform.GetUniformScale()); - mRotation = transform.GetRotation(); + m_position = transform.GetTranslation(); + m_scale = AZ::Vector3(transform.GetUniformScale()); + m_rotation = transform.GetRotation(); #else - mPosition = transform.GetTranslation(); - mRotation = transform.GetRotation(); + m_position = transform.GetTranslation(); + m_rotation = transform.GetRotation(); #endif - mRotation.Normalize(); + m_rotation.Normalize(); } @@ -196,10 +196,10 @@ namespace EMotionFX AZ::Transform result; #ifndef EMFX_SCALE_DISABLED - result = MCore::CreateFromQuaternionAndTranslationAndScale(mRotation, mPosition, mScale); + result = MCore::CreateFromQuaternionAndTranslationAndScale(m_rotation, m_position, m_scale); #else - result = AZ::Transform::CreateFromQuaternionAndTranslation(mRotation, mPosition); + result = AZ::Transform::CreateFromQuaternionAndTranslation(m_rotation, m_position); #endif return result; @@ -209,35 +209,35 @@ namespace EMotionFX // identity the transform void Transform::Identity() { - mPosition = AZ::Vector3::CreateZero(); - mRotation = AZ::Quaternion::CreateIdentity(); + m_position = AZ::Vector3::CreateZero(); + m_rotation = AZ::Quaternion::CreateIdentity(); EMFX_SCALECODE ( - mScale = AZ::Vector3::CreateOne(); + m_scale = AZ::Vector3::CreateOne(); ) } // Zero out the position, scale, and rotation. void Transform::Zero() { - mPosition = AZ::Vector3::CreateZero(); - mRotation = AZ::Quaternion::CreateZero(); + m_position = AZ::Vector3::CreateZero(); + m_rotation = AZ::Quaternion::CreateZero(); EMFX_SCALECODE ( - mScale = AZ::Vector3::CreateZero(); + m_scale = AZ::Vector3::CreateZero(); ) } // Zero out the position and scale, but set quaternion to identity. void Transform::IdentityWithZeroScale() { - mPosition = AZ::Vector3::CreateZero(); - mRotation = AZ::Quaternion::CreateIdentity(); + m_position = AZ::Vector3::CreateZero(); + m_rotation = AZ::Quaternion::CreateIdentity(); EMFX_SCALECODE ( - mScale = AZ::Vector3::CreateZero(); + m_scale = AZ::Vector3::CreateZero(); ); } @@ -245,17 +245,17 @@ namespace EMotionFX Transform& Transform::PreMultiply(const Transform& other) { #ifdef EMFX_SCALE_DISABLED - mPosition += mRotation * other.mPosition; + m_position += m_rotation * other.m_position; #else - mPosition += mRotation.TransformVector((other.mPosition * mScale)); + m_position += m_rotation.TransformVector((other.m_position * m_scale)); #endif - mRotation = mRotation * other.mRotation; - mRotation.Normalize(); + m_rotation = m_rotation * other.m_rotation; + m_rotation.Normalize(); EMFX_SCALECODE ( - mScale = mScale * other.mScale; + m_scale = m_scale * other.m_scale; ) return *this; @@ -274,25 +274,25 @@ namespace EMotionFX AZ::Vector3 Transform::TransformPoint(const AZ::Vector3& point) const { #ifdef EMFX_SCALE_DISABLED - return mPosition + mRotation * point; + return m_position + m_rotation * point; #else - return mPosition + mRotation.TransformVector((point * mScale)); + return m_position + m_rotation.TransformVector((point * m_scale)); #endif } AZ::Vector3 Transform::RotateVector(const AZ::Vector3& v) const { - return mRotation.TransformVector(v); + return m_rotation.TransformVector(v); } AZ::Vector3 Transform::TransformVector(const AZ::Vector3& v) const { #ifdef EMFX_SCALE_DISABLED - return mRotation.TransformVector(v); + return m_rotation.TransformVector(v); #else - return mRotation.TransformVector((v * mScale)); + return m_rotation.TransformVector((v * m_scale)); #endif } @@ -301,17 +301,17 @@ namespace EMotionFX Transform& Transform::Multiply(const Transform& other) { #ifdef EMFX_SCALE_DISABLED - mPosition = other.mRotation.TransformVector(mPosition) + other.mPosition; + m_position = other.m_rotation.TransformVector(m_position) + other.m_position; #else - mPosition = other.mRotation.TransformVector((mPosition * other.mScale)) + other.mPosition; + m_position = other.m_rotation.TransformVector((m_position * other.m_scale)) + other.m_position; #endif - mRotation = other.mRotation * mRotation; - mRotation.Normalize(); + m_rotation = other.m_rotation * m_rotation; + m_rotation.Normalize(); EMFX_SCALECODE ( - mScale = other.mScale * mScale; + m_scale = other.m_scale * m_scale; ) return *this; } @@ -329,7 +329,7 @@ namespace EMotionFX // normalize the quaternions Transform& Transform::Normalize() { - mRotation.Normalize(); + m_rotation.Normalize(); return *this; } @@ -348,15 +348,15 @@ namespace EMotionFX { EMFX_SCALECODE ( - mScale = mScale.GetReciprocal(); + m_scale = m_scale.GetReciprocal(); ) - mRotation = mRotation.GetConjugate(); + m_rotation = m_rotation.GetConjugate(); #ifdef EMFX_SCALE_DISABLED - mPosition = mRotation.TransformVector(-mPosition); + m_position = m_rotation.TransformVector(-m_position); #else - mPosition = mRotation.TransformVector(-mPosition) * mScale; + m_position = m_rotation.TransformVector(-m_position) * m_scale; #endif return *this; @@ -376,14 +376,14 @@ namespace EMotionFX Transform& Transform::Mirror(const AZ::Vector3& planeNormal) { // mirror the position over the plane with the specified normal - mPosition = MCore::Mirror(mPosition, planeNormal); + m_position = MCore::Mirror(m_position, planeNormal); // mirror the quaternion axis component - AZ::Vector3 mirrored = MCore::Mirror(AZ::Vector3(mRotation.GetX(), mRotation.GetY(), mRotation.GetZ()), planeNormal); + AZ::Vector3 mirrored = MCore::Mirror(AZ::Vector3(m_rotation.GetX(), m_rotation.GetY(), m_rotation.GetZ()), planeNormal); // update the rotation quaternion with inverted angle - mRotation.Set(mirrored.GetX(), mirrored.GetY(), mirrored.GetZ(), -mRotation.GetW()); - mRotation.Normalize(); + m_rotation.Set(mirrored.GetX(), mirrored.GetY(), mirrored.GetZ(), -m_rotation.GetW()); + m_rotation.Normalize(); return *this; } @@ -396,14 +396,14 @@ namespace EMotionFX ApplyMirrorFlags(this, mirrorFlags); // mirror the position over the plane with the specified normal - mPosition = MCore::Mirror(mPosition, planeNormal); + m_position = MCore::Mirror(m_position, planeNormal); // mirror the quaternion axis component - AZ::Vector3 mirrored = MCore::Mirror(AZ::Vector3(mRotation.GetX(), mRotation.GetY(), mRotation.GetZ()), planeNormal); + AZ::Vector3 mirrored = MCore::Mirror(AZ::Vector3(m_rotation.GetX(), m_rotation.GetY(), m_rotation.GetZ()), planeNormal); // update the rotation quaternion with inverted angle - mRotation.Set(mirrored.GetX(), mirrored.GetY(), mirrored.GetZ(), -mRotation.GetW()); - mRotation.Normalize(); + m_rotation.Set(mirrored.GetX(), mirrored.GetY(), mirrored.GetZ(), -m_rotation.GetW()); + m_rotation.Normalize(); return *this; } @@ -422,17 +422,17 @@ namespace EMotionFX void Transform::PreMultiply(const Transform& other, Transform* outResult) const { #ifdef EMFX_SCALE_DISABLED - outResult->mPosition = mPosition + mRotation.TransformVector(other.mPosition); + outResult->m_position = m_position + m_rotation.TransformVector(other.m_position); #else - outResult->mPosition = mPosition + (mRotation.TransformVector(other.mPosition) * mScale); + outResult->m_position = m_position + (m_rotation.TransformVector(other.m_position) * m_scale); #endif - outResult->mRotation = mRotation * other.mRotation; - outResult->mRotation.Normalize(); + outResult->m_rotation = m_rotation * other.m_rotation; + outResult->m_rotation.Normalize(); EMFX_SCALECODE ( - outResult->mScale = mScale * other.mScale; + outResult->m_scale = m_scale * other.m_scale; ) } @@ -441,17 +441,17 @@ namespace EMotionFX void Transform::Multiply(const Transform& other, Transform* outResult) const { #ifdef EMFX_SCALE_DISABLED - outResult->mPosition = other.mPosition + other.mRotation.TransformVector(mPosition); + outResult->m_position = other.m_position + other.m_rotation.TransformVector(m_position); #else - outResult->mPosition = other.mPosition + (other.mRotation.TransformVector(mPosition) * other.mScale); + outResult->m_position = other.m_position + (other.m_rotation.TransformVector(m_position) * other.m_scale); #endif - outResult->mRotation = other.mRotation * mRotation; - outResult->mRotation.Normalize(); + outResult->m_rotation = other.m_rotation * m_rotation; + outResult->m_rotation.Normalize(); EMFX_SCALECODE ( - outResult->mScale = other.mScale * mScale; + outResult->m_scale = other.m_scale * m_scale; ) } @@ -469,18 +469,18 @@ namespace EMotionFX void Transform::CalcRelativeTo(const Transform& relativeTo, Transform* outTransform) const { #ifndef EMFX_SCALE_DISABLED - const AZ::Vector3 invScale = relativeTo.mScale.GetReciprocal(); - const AZ::Quaternion invRot = relativeTo.mRotation.GetConjugate(); + const AZ::Vector3 invScale = relativeTo.m_scale.GetReciprocal(); + const AZ::Quaternion invRot = relativeTo.m_rotation.GetConjugate(); - outTransform->mPosition = (invRot.TransformVector(mPosition - relativeTo.mPosition)) * invScale; - outTransform->mRotation = invRot * mRotation; - outTransform->mScale = mScale * invScale; + outTransform->m_position = (invRot.TransformVector(m_position - relativeTo.m_position)) * invScale; + outTransform->m_rotation = invRot * m_rotation; + outTransform->m_scale = m_scale * invScale; #else - const AZ::Quaternion invRot = relativeTo.mRotation.GetConjugate(); - outTransform->mPosition = invRot.TransformVector(mPosition - relativeTo.mPosition); - outTransform->mRotation = invRot * mRotation; + const AZ::Quaternion invRot = relativeTo.m_rotation.GetConjugate(); + outTransform->m_position = invRot.TransformVector(m_position - relativeTo.m_position); + outTransform->m_rotation = invRot * m_rotation; #endif - outTransform->mRotation.Normalize(); + outTransform->m_rotation.Normalize(); } @@ -497,16 +497,16 @@ namespace EMotionFX void Transform::Mirror(const AZ::Vector3& planeNormal, Transform* outResult) const { // mirror the position over the normal - outResult->mPosition = MCore::Mirror(mPosition, planeNormal); + outResult->m_position = MCore::Mirror(m_position, planeNormal); // mirror the quaternion axis component - AZ::Vector3 mirrored = MCore::Mirror(AZ::Vector3(mRotation.GetX(), mRotation.GetY(), mRotation.GetZ()), planeNormal); - outResult->mRotation.Set(mirrored.GetX(), mirrored.GetY(), mirrored.GetZ(), -mRotation.GetW()); // store the mirrored quat - outResult->mRotation.Normalize(); + AZ::Vector3 mirrored = MCore::Mirror(AZ::Vector3(m_rotation.GetX(), m_rotation.GetY(), m_rotation.GetZ()), planeNormal); + outResult->m_rotation.Set(mirrored.GetX(), mirrored.GetY(), mirrored.GetZ(), -m_rotation.GetW()); // store the mirrored quat + outResult->m_rotation.Normalize(); EMFX_SCALECODE ( - outResult->mScale = mScale; + outResult->m_scale = m_scale; ) } @@ -518,9 +518,9 @@ namespace EMotionFX return false; #else return ( - !MCore::Compare::CheckIfIsClose(mScale.GetX(), 1.0f, MCore::Math::epsilon) || - !MCore::Compare::CheckIfIsClose(mScale.GetY(), 1.0f, MCore::Math::epsilon) || - !MCore::Compare::CheckIfIsClose(mScale.GetZ(), 1.0f, MCore::Math::epsilon)); + !MCore::Compare::CheckIfIsClose(m_scale.GetX(), 1.0f, MCore::Math::epsilon) || + !MCore::Compare::CheckIfIsClose(m_scale.GetY(), 1.0f, MCore::Math::epsilon) || + !MCore::Compare::CheckIfIsClose(m_scale.GetZ(), 1.0f, MCore::Math::epsilon)); #endif } @@ -528,12 +528,12 @@ namespace EMotionFX // blend into another transform Transform& Transform::Blend(const Transform& dest, float weight) { - mPosition = MCore::LinearInterpolate(mPosition, dest.mPosition, weight); - mRotation = MCore::NLerp(mRotation, dest.mRotation, weight); + m_position = MCore::LinearInterpolate(m_position, dest.m_position, weight); + m_rotation = MCore::NLerp(m_rotation, dest.m_rotation, weight); EMFX_SCALECODE ( - mScale = MCore::LinearInterpolate(mScale, dest.mScale, weight); + m_scale = MCore::LinearInterpolate(m_scale, dest.m_scale, weight); ) return *this; @@ -543,18 +543,18 @@ namespace EMotionFX // additive blend Transform& Transform::BlendAdditive(const Transform& dest, const Transform& orgTransform, float weight) { - const AZ::Vector3 relPos = dest.mPosition - orgTransform.mPosition; - const AZ::Quaternion& orgRot = orgTransform.mRotation; - const AZ::Quaternion rot = MCore::NLerp(orgRot, dest.mRotation, weight); + const AZ::Vector3 relPos = dest.m_position - orgTransform.m_position; + const AZ::Quaternion& orgRot = orgTransform.m_rotation; + const AZ::Quaternion rot = MCore::NLerp(orgRot, dest.m_rotation, weight); // apply the relative changes - mRotation = mRotation * (orgRot.GetConjugate() * rot); - mRotation.Normalize(); - mPosition += (relPos * weight); + m_rotation = m_rotation * (orgRot.GetConjugate() * rot); + m_rotation.Normalize(); + m_position += (relPos * weight); EMFX_SCALECODE ( - mScale += (dest.mScale - orgTransform.mScale) * weight; + m_scale += (dest.m_scale - orgTransform.m_scale) * weight; ) return *this; @@ -563,13 +563,13 @@ namespace EMotionFX Transform& Transform::ApplyAdditive(const Transform& additive) { - mPosition += additive.mPosition; - mRotation = mRotation * additive.mRotation; - mRotation.Normalize(); + m_position += additive.m_position; + m_rotation = m_rotation * additive.m_rotation; + m_rotation.Normalize(); EMFX_SCALECODE ( - mScale *= additive.mScale; + m_scale *= additive.m_scale; ) return *this; } @@ -577,11 +577,11 @@ namespace EMotionFX Transform& Transform::ApplyAdditive(const Transform& additive, float weight) { - mPosition += additive.mPosition * weight; - mRotation = MCore::NLerp(mRotation, mRotation * additive.mRotation, weight); + m_position += additive.m_position * weight; + m_rotation = MCore::NLerp(m_rotation, m_rotation * additive.m_rotation, weight); EMFX_SCALECODE ( - mScale *= AZ::Vector3::CreateOne().Lerp(additive.mScale, weight); + m_scale *= AZ::Vector3::CreateOne().Lerp(additive.m_scale, weight); ) return *this; } @@ -590,21 +590,21 @@ namespace EMotionFX // sum the transforms Transform& Transform::Add(const Transform& other, float weight) { - mPosition += other.mPosition * weight; + m_position += other.m_position * weight; // make sure we use the correct hemisphere - if (mRotation.Dot(other.mRotation) < 0.0f) + if (m_rotation.Dot(other.m_rotation) < 0.0f) { - mRotation += -(other.mRotation) * weight; + m_rotation += -(other.m_rotation) * weight; } else { - mRotation += other.mRotation * weight; + m_rotation += other.m_rotation * weight; } EMFX_SCALECODE ( - mScale += other.mScale * weight; + m_scale += other.m_scale * weight; ) return *this; @@ -614,11 +614,11 @@ namespace EMotionFX // add a transform Transform& Transform::Add(const Transform& other) { - mPosition += other.mPosition; - mRotation += other.mRotation; + m_position += other.m_position; + m_rotation += other.m_rotation; EMFX_SCALECODE ( - mScale += other.mScale; + m_scale += other.m_scale; ) return *this; } @@ -627,11 +627,11 @@ namespace EMotionFX // subtract a transform Transform& Transform::Subtract(const Transform& other) { - mPosition -= other.mPosition; - mRotation -= other.mRotation; + m_position -= other.m_position; + m_rotation -= other.m_rotation; EMFX_SCALECODE ( - mScale -= other.mScale; + m_scale -= other.m_scale; ) return *this; } @@ -645,22 +645,22 @@ namespace EMotionFX MCore::LogInfo("Transform(%s):", name); } - MCore::LogInfo("mPosition = %.6f, %.6f, %.6f", - static_cast(mPosition.GetX()), - static_cast(mPosition.GetY()), - static_cast(mPosition.GetZ())); - MCore::LogInfo("mRotation = %.6f, %.6f, %.6f, %.6f", - static_cast(mRotation.GetX()), - static_cast(mRotation.GetY()), - static_cast(mRotation.GetZ()), - static_cast(mRotation.GetW())); + MCore::LogInfo("m_position = %.6f, %.6f, %.6f", + static_cast(m_position.GetX()), + static_cast(m_position.GetY()), + static_cast(m_position.GetZ())); + MCore::LogInfo("m_rotation = %.6f, %.6f, %.6f, %.6f", + static_cast(m_rotation.GetX()), + static_cast(m_rotation.GetY()), + static_cast(m_rotation.GetZ()), + static_cast(m_rotation.GetW())); EMFX_SCALECODE ( - MCore::LogInfo("mScale = %.6f, %.6f, %.6f", - static_cast(mScale.GetX()), - static_cast(mScale.GetY()), - static_cast(mScale.GetZ())); + MCore::LogInfo("m_scale = %.6f, %.6f, %.6f", + static_cast(m_scale.GetX()), + static_cast(m_scale.GetY()), + static_cast(m_scale.GetZ())); ) } @@ -675,26 +675,26 @@ namespace EMotionFX if (mirrorFlags & Actor::MIRRORFLAG_INVERT_X) { - inOutTransform->mRotation.SetW(inOutTransform->mRotation.GetW() * -1.0f); - inOutTransform->mRotation.SetX(inOutTransform->mRotation.GetX() * -1.0f); - inOutTransform->mPosition.SetY(inOutTransform->mPosition.GetY() * -1.0f); - inOutTransform->mPosition.SetZ(inOutTransform->mPosition.GetZ() * -1.0f); + inOutTransform->m_rotation.SetW(inOutTransform->m_rotation.GetW() * -1.0f); + inOutTransform->m_rotation.SetX(inOutTransform->m_rotation.GetX() * -1.0f); + inOutTransform->m_position.SetY(inOutTransform->m_position.GetY() * -1.0f); + inOutTransform->m_position.SetZ(inOutTransform->m_position.GetZ() * -1.0f); return; } if (mirrorFlags & Actor::MIRRORFLAG_INVERT_Y) { - inOutTransform->mRotation.SetW(inOutTransform->mRotation.GetW() * -1.0f); - inOutTransform->mRotation.SetY(inOutTransform->mPosition.GetY() * -1.0f); - inOutTransform->mPosition.SetX(inOutTransform->mPosition.GetX() * -1.0f); - inOutTransform->mPosition.SetZ(inOutTransform->mPosition.GetZ() * -1.0f); + inOutTransform->m_rotation.SetW(inOutTransform->m_rotation.GetW() * -1.0f); + inOutTransform->m_rotation.SetY(inOutTransform->m_position.GetY() * -1.0f); + inOutTransform->m_position.SetX(inOutTransform->m_position.GetX() * -1.0f); + inOutTransform->m_position.SetZ(inOutTransform->m_position.GetZ() * -1.0f); return; } if (mirrorFlags & Actor::MIRRORFLAG_INVERT_Z) { - inOutTransform->mRotation.SetW(inOutTransform->mRotation.GetW() * -1.0f); - inOutTransform->mRotation.SetZ(inOutTransform->mPosition.GetZ() * -1.0f); - inOutTransform->mPosition.SetX(inOutTransform->mPosition.GetX() * -1.0f); - inOutTransform->mPosition.SetY(inOutTransform->mPosition.GetY() * -1.0f); + inOutTransform->m_rotation.SetW(inOutTransform->m_rotation.GetW() * -1.0f); + inOutTransform->m_rotation.SetZ(inOutTransform->m_position.GetZ() * -1.0f); + inOutTransform->m_position.SetX(inOutTransform->m_position.GetX() * -1.0f); + inOutTransform->m_position.SetY(inOutTransform->m_position.GetY() * -1.0f); return; } } @@ -748,13 +748,13 @@ namespace EMotionFX // Only keep translation over the XY plane and assume a height of 0. if (!(flags & MOTIONEXTRACT_CAPTURE_Z)) { - mPosition.SetZ(0.0f); + m_position.SetZ(0.0f); } // Only keep the rotation on the Z axis. - mRotation.SetX(0.0f); - mRotation.SetY(0.0f); - mRotation.Normalize(); + m_rotation.SetX(0.0f); + m_rotation.SetY(0.0f); + m_rotation.Normalize(); } @@ -764,12 +764,12 @@ namespace EMotionFX Transform result(*this); // Only keep translation over the XY plane and assume a height of 0. - result.mPosition.SetZ(0.0f); + result.m_position.SetZ(0.0f); // Only keep the rotation on the Z axis. - result.mRotation.SetX(0.0f); - result.mRotation.SetY(0.0f); - result.mRotation.Normalize(); + result.m_rotation.SetX(0.0f); + result.m_rotation.SetY(0.0f); + result.m_rotation.Normalize(); return result; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Transform.h b/Gems/EMotionFX/Code/EMotionFX/Source/Transform.h index 950d39fb55..764de9e8f9 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Transform.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Transform.h @@ -137,10 +137,10 @@ namespace EMotionFX bool operator != (const Transform& right) const; public: - AZ::Quaternion mRotation; /**< The rotation. */ - AZ::Vector3 mPosition; /**< The position. */ + AZ::Quaternion m_rotation; /**< The rotation. */ + AZ::Vector3 m_position; /**< The position. */ #ifndef EMFX_SCALE_DISABLED - AZ::Vector3 mScale; /**< The scale. */ + AZ::Vector3 m_scale; /**< The scale. */ #endif } MCORE_ALIGN_POST(16); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/TransformData.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/TransformData.cpp index 5164f97c01..5349c16ec0 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/TransformData.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/TransformData.cpp @@ -25,10 +25,10 @@ namespace EMotionFX TransformData::TransformData() : BaseObject() { - mSkinningMatrices = nullptr; - mBindPose = nullptr; - mNumTransforms = 0; - mHasUniqueBindPose = false; + m_skinningMatrices = nullptr; + m_bindPose = nullptr; + m_numTransforms = 0; + m_hasUniqueBindPose = false; } @@ -49,17 +49,17 @@ namespace EMotionFX // get rid of all allocated data void TransformData::Release() { - MCore::AlignedFree(mSkinningMatrices); + MCore::AlignedFree(m_skinningMatrices); - if (mHasUniqueBindPose) + if (m_hasUniqueBindPose) { - delete mBindPose; + delete m_bindPose; } - mPose.Clear(); - mSkinningMatrices = nullptr; - mBindPose = nullptr; - mNumTransforms = 0; + m_pose.Clear(); + m_skinningMatrices = nullptr; + m_bindPose = nullptr; + m_numTransforms = 0; } @@ -69,7 +69,7 @@ namespace EMotionFX Release(); // link to the given actor instance - mPose.LinkToActorInstance(actorInstance); + m_pose.LinkToActorInstance(actorInstance); // release all memory if we want to resize to zero nodes const size_t numNodes = actorInstance->GetNumNodes(); @@ -79,23 +79,23 @@ namespace EMotionFX return; } - mSkinningMatrices = (AZ::Matrix3x4*)MCore::AlignedAllocate(sizeof(AZ::Matrix3x4) * numNodes, static_cast(AZStd::alignment_of()), EMFX_MEMCATEGORY_TRANSFORMDATA); - mNumTransforms = numNodes; + m_skinningMatrices = (AZ::Matrix3x4*)MCore::AlignedAllocate(sizeof(AZ::Matrix3x4) * numNodes, static_cast(AZStd::alignment_of()), EMFX_MEMCATEGORY_TRANSFORMDATA); + m_numTransforms = numNodes; - if (mHasUniqueBindPose) + if (m_hasUniqueBindPose) { - mBindPose = new Pose(); - mBindPose->LinkToActorInstance(actorInstance); + m_bindPose = new Pose(); + m_bindPose->LinkToActorInstance(actorInstance); } else { - mBindPose = actorInstance->GetActor()->GetBindPose(); + m_bindPose = actorInstance->GetActor()->GetBindPose(); } // now initialize the data with the actor transforms for (size_t i = 0; i < numNodes; ++i) { - mSkinningMatrices[i] = AZ::Matrix3x4::CreateIdentity(); + m_skinningMatrices[i] = AZ::Matrix3x4::CreateIdentity(); } } @@ -103,16 +103,16 @@ namespace EMotionFX // make the bind pose transforms unique void TransformData::MakeBindPoseTransformsUnique() { - if (mHasUniqueBindPose) + if (m_hasUniqueBindPose) { return; } - const ActorInstance* actorInstance = mPose.GetActorInstance(); - mHasUniqueBindPose = true; - mBindPose = new Pose(); - mBindPose->LinkToActorInstance(actorInstance); - *mBindPose = *actorInstance->GetActor()->GetBindPose(); + const ActorInstance* actorInstance = m_pose.GetActorInstance(); + m_hasUniqueBindPose = true; + m_bindPose = new Pose(); + m_bindPose->LinkToActorInstance(actorInstance); + *m_bindPose = *actorInstance->GetActor()->GetBindPose(); } @@ -121,7 +121,7 @@ namespace EMotionFX // set the scaling value for the node and all child nodes void TransformData::SetBindPoseLocalScaleInherit(size_t nodeIndex, const AZ::Vector3& scale) { - const ActorInstance* actorInstance = mPose.GetActorInstance(); + const ActorInstance* actorInstance = m_pose.GetActorInstance(); const Actor* actor = actorInstance->GetActor(); // get the node index and the number of children of the given node @@ -141,15 +141,15 @@ namespace EMotionFX // update the local space scale void TransformData::SetBindPoseLocalScale(size_t nodeIndex, const AZ::Vector3& scale) { - Transform newTransform = mBindPose->GetLocalSpaceTransform(nodeIndex); - newTransform.mScale = scale; - mBindPose->SetLocalSpaceTransform(nodeIndex, newTransform); + Transform newTransform = m_bindPose->GetLocalSpaceTransform(nodeIndex); + newTransform.m_scale = scale; + m_bindPose->SetLocalSpaceTransform(nodeIndex, newTransform); } ) // EMFX_SCALECODE // set the number of morph weights void TransformData::SetNumMorphWeights(size_t numMorphWeights) { - mPose.ResizeNumMorphs(numMorphWeights); + m_pose.ResizeNumMorphs(numMorphWeights); } } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/TransformData.h b/Gems/EMotionFX/Code/EMotionFX/Source/TransformData.h index d4e70134a3..71c2ee6446 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/TransformData.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/TransformData.h @@ -64,33 +64,33 @@ namespace EMotionFX * The size of the returned array is equal to the amount of nodes in the actor or the value returned by GetNumTransforms() * @result The array of skinning matrices. */ - MCORE_INLINE AZ::Matrix3x4* GetSkinningMatrices() { return mSkinningMatrices; } + MCORE_INLINE AZ::Matrix3x4* GetSkinningMatrices() { return m_skinningMatrices; } /** * Get the skinning matrices (offset from the pose), in read-only (const) mode. * The size of the returned array is equal to the amount of nodes in the actor or the value returned by GetNumTransforms() * @result The array of skinning matrices. */ - MCORE_INLINE const AZ::Matrix3x4* GetSkinningMatrices() const { return mSkinningMatrices; } + MCORE_INLINE const AZ::Matrix3x4* GetSkinningMatrices() const { return m_skinningMatrices; } - MCORE_INLINE Pose* GetBindPose() const { return mBindPose; } - MCORE_INLINE const Pose* GetCurrentPose() const { return &mPose; } - MCORE_INLINE Pose* GetCurrentPose() { return &mPose; } + MCORE_INLINE Pose* GetBindPose() const { return m_bindPose; } + MCORE_INLINE const Pose* GetCurrentPose() const { return &m_pose; } + MCORE_INLINE Pose* GetCurrentPose() { return &m_pose; } /** * Reset the local space transform of a given node to its bind pose local space transform. * @param nodeIndex The node number, which must be in range of [0..GetNumTransforms()-1]. */ - void ResetToBindPoseTransformation(size_t nodeIndex) { mPose.SetLocalSpaceTransform(nodeIndex, mBindPose->GetLocalSpaceTransform(nodeIndex)); } + void ResetToBindPoseTransformation(size_t nodeIndex) { m_pose.SetLocalSpaceTransform(nodeIndex, m_bindPose->GetLocalSpaceTransform(nodeIndex)); } /** * Reset all local space transforms to the local space transforms of the bind pose. */ void ResetToBindPoseTransformations() { - for (size_t i = 0; i < mNumTransforms; ++i) + for (size_t i = 0; i < m_numTransforms; ++i) { - mPose.SetLocalSpaceTransform(i, mBindPose->GetLocalSpaceTransform(i)); + m_pose.SetLocalSpaceTransform(i, m_bindPose->GetLocalSpaceTransform(i)); } } @@ -100,8 +100,8 @@ namespace EMotionFX void SetBindPoseLocalScale(size_t nodeIndex, const AZ::Vector3& scale); ) - MCORE_INLINE const ActorInstance* GetActorInstance() const { return mPose.GetActorInstance(); } - MCORE_INLINE size_t GetNumTransforms() const { return mNumTransforms; } + MCORE_INLINE const ActorInstance* GetActorInstance() const { return m_pose.GetActorInstance(); } + MCORE_INLINE size_t GetNumTransforms() const { return m_numTransforms; } void MakeBindPoseTransformsUnique(); @@ -109,11 +109,11 @@ namespace EMotionFX private: - Pose mPose; /**< The current pose. */ - Pose* mBindPose; /**< The bind pose, which can be unique or point to the bind pose in the actor. */ - AZ::Matrix3x4* mSkinningMatrices; /**< The matrices used for skinning. They are the offset to the bind pose. */ - size_t mNumTransforms; /**< The number of transforms, which is equal to the number of nodes in the linked actor instance. */ - bool mHasUniqueBindPose; /**< Do we have a unique bind pose (when set to true) or do we use the one from the Actor object (when set to false)? */ + Pose m_pose; /**< The current pose. */ + Pose* m_bindPose; /**< The bind pose, which can be unique or point to the bind pose in the actor. */ + AZ::Matrix3x4* m_skinningMatrices; /**< The matrices used for skinning. They are the offset to the bind pose. */ + size_t m_numTransforms; /**< The number of transforms, which is equal to the number of nodes in the linked actor instance. */ + bool m_hasUniqueBindPose; /**< Do we have a unique bind pose (when set to true) or do we use the one from the Actor object (when set to false)? */ /** * The constructor. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/VertexAttributeLayer.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/VertexAttributeLayer.cpp index 25614c17a9..722d599b2d 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/VertexAttributeLayer.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/VertexAttributeLayer.cpp @@ -21,9 +21,9 @@ namespace EMotionFX VertexAttributeLayer::VertexAttributeLayer(uint32 numAttributes, bool keepOriginals) : BaseObject() { - mNumAttributes = numAttributes; - mKeepOriginals = keepOriginals; - mNameID = MCore::GetStringIdPool().GenerateIdForString(""); + m_numAttributes = numAttributes; + m_keepOriginals = keepOriginals; + m_nameId = MCore::GetStringIdPool().GenerateIdForString(""); } @@ -44,27 +44,27 @@ namespace EMotionFX // set the name void VertexAttributeLayer::SetName(const char* name) { - mNameID = MCore::GetStringIdPool().GenerateIdForString(name); + m_nameId = MCore::GetStringIdPool().GenerateIdForString(name); } // get the name const char* VertexAttributeLayer::GetName() const { - return MCore::GetStringIdPool().GetName(mNameID).c_str(); + return MCore::GetStringIdPool().GetName(m_nameId).c_str(); } // get the name string const AZStd::string& VertexAttributeLayer::GetNameString() const { - return MCore::GetStringIdPool().GetName(mNameID); + return MCore::GetStringIdPool().GetName(m_nameId); } // get the name ID uint32 VertexAttributeLayer::GetNameID() const { - return mNameID; + return m_nameId; } } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/VertexAttributeLayer.h b/Gems/EMotionFX/Code/EMotionFX/Source/VertexAttributeLayer.h index 1affcb9b79..525061b5a7 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/VertexAttributeLayer.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/VertexAttributeLayer.h @@ -72,7 +72,7 @@ namespace EMotionFX * Get the number of attributes inside this layer. * @result The number of attributes. */ - MCORE_INLINE uint32 GetNumAttributes() const { return mNumAttributes; } + MCORE_INLINE uint32 GetNumAttributes() const { return m_numAttributes; } /** * Check if this class also stores original vertex data or not. @@ -82,7 +82,7 @@ namespace EMotionFX * The initialization to the original data happens inside the ResetToOriginalData method. * @result Returns true when this class also stores the original (undeformed) data, next to the current (deformed) data. */ - MCORE_INLINE bool GetKeepOriginals() const { return mKeepOriginals; } + MCORE_INLINE bool GetKeepOriginals() const { return m_keepOriginals; } /** * Reset the layer data to it's original data. @@ -129,9 +129,9 @@ namespace EMotionFX protected: - uint32 mNumAttributes; /**< The number of attributes inside this layer. */ - uint32 mNameID; /**< The name ID. */ - bool mKeepOriginals; /**< Should we store a copy of the original data as well? */ + uint32 m_numAttributes; /**< The number of attributes inside this layer. */ + uint32 m_nameId; /**< The name ID. */ + bool m_keepOriginals; /**< Should we store a copy of the original data as well? */ /** * The constructor. diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/VertexAttributeLayerAbstractData.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/VertexAttributeLayerAbstractData.cpp index c0bf0c3a54..b1757c09d1 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/VertexAttributeLayerAbstractData.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/VertexAttributeLayerAbstractData.cpp @@ -20,22 +20,22 @@ namespace EMotionFX VertexAttributeLayerAbstractData::VertexAttributeLayerAbstractData(uint32 numAttributes, uint32 typeID, uint32 attribSizeInBytes, bool keepOriginals) : VertexAttributeLayer(numAttributes, keepOriginals) { - mData = nullptr; - mSwapBuffer = nullptr; - mTypeID = typeID; - mAttribSizeInBytes = attribSizeInBytes; + m_data = nullptr; + m_swapBuffer = nullptr; + m_typeId = typeID; + m_attribSizeInBytes = attribSizeInBytes; // allocate the data - const uint32 numBytes = CalcTotalDataSizeInBytes(mKeepOriginals); - mData = (uint8*)MCore::AlignedAllocate(numBytes, 16, EMFX_MEMCATEGORY_GEOMETRY_VERTEXATTRIBUTES); + const uint32 numBytes = CalcTotalDataSizeInBytes(m_keepOriginals); + m_data = (uint8*)MCore::AlignedAllocate(numBytes, 16, EMFX_MEMCATEGORY_GEOMETRY_VERTEXATTRIBUTES); } // the destructor VertexAttributeLayerAbstractData::~VertexAttributeLayerAbstractData() { - MCore::AlignedFree(mData); - MCore::AlignedFree(mSwapBuffer); + MCore::AlignedFree(m_data); + MCore::AlignedFree(m_swapBuffer); } @@ -49,7 +49,7 @@ namespace EMotionFX // get the layer type uint32 VertexAttributeLayerAbstractData::GetType() const { - return mTypeID; + return m_typeId; } @@ -63,13 +63,13 @@ namespace EMotionFX // calculate the total data size uint32 VertexAttributeLayerAbstractData::CalcTotalDataSizeInBytes(bool includeOriginals) const { - if (includeOriginals && mKeepOriginals) + if (includeOriginals && m_keepOriginals) { - return (mAttribSizeInBytes * mNumAttributes) << 1; // multiplied by two, as we store the originals right after it + return (m_attribSizeInBytes * m_numAttributes) << 1; // multiplied by two, as we store the originals right after it } else { - return mAttribSizeInBytes * mNumAttributes; + return m_attribSizeInBytes * m_numAttributes; } } @@ -78,13 +78,13 @@ namespace EMotionFX VertexAttributeLayer* VertexAttributeLayerAbstractData::Clone() { // create the clone - VertexAttributeLayerAbstractData* clone = aznew VertexAttributeLayerAbstractData(mNumAttributes, mTypeID, mAttribSizeInBytes, mKeepOriginals); + VertexAttributeLayerAbstractData* clone = aznew VertexAttributeLayerAbstractData(m_numAttributes, m_typeId, m_attribSizeInBytes, m_keepOriginals); // copy over the data uint8* cloneData = (uint8*)clone->GetData(); - MCore::MemCopy(cloneData, mData, CalcTotalDataSizeInBytes(true)); + MCore::MemCopy(cloneData, m_data, CalcTotalDataSizeInBytes(true)); - clone->mNameID = mNameID; + clone->m_nameId = m_nameId; return clone; } @@ -93,7 +93,7 @@ namespace EMotionFX void VertexAttributeLayerAbstractData::ResetToOriginalData() { // if we dont have any original data, there is nothing to do - if (mKeepOriginals == false) + if (m_keepOriginals == false) { return; } @@ -111,9 +111,9 @@ namespace EMotionFX void VertexAttributeLayerAbstractData::SwapAttributes(uint32 attribA, uint32 attribB) { // create a swap buffer if we haven't got it already - if (mSwapBuffer == nullptr) + if (m_swapBuffer == nullptr) { - mSwapBuffer = (uint8*)MCore::AlignedAllocate(mAttribSizeInBytes, 16, EMFX_MEMCATEGORY_GEOMETRY_VERTEXATTRIBUTES); + m_swapBuffer = (uint8*)MCore::AlignedAllocate(m_attribSizeInBytes, 16, EMFX_MEMCATEGORY_GEOMETRY_VERTEXATTRIBUTES); } // get the locations of where the attributes are stored @@ -121,18 +121,18 @@ namespace EMotionFX uint8* attribPtrB = (uint8*)GetData(attribB); // swap the attribute data - MCore::MemCopy(mSwapBuffer, attribPtrA, mAttribSizeInBytes); // copy attribute A into the temp swap buffer - MCore::MemCopy(attribPtrA, attribPtrB, mAttribSizeInBytes); // copy attribute B into A - MCore::MemCopy(attribPtrB, mSwapBuffer, mAttribSizeInBytes); // copy the temp swap buffer data into attribute B + MCore::MemCopy(m_swapBuffer, attribPtrA, m_attribSizeInBytes); // copy attribute A into the temp swap buffer + MCore::MemCopy(attribPtrA, attribPtrB, m_attribSizeInBytes); // copy attribute B into A + MCore::MemCopy(attribPtrB, m_swapBuffer, m_attribSizeInBytes); // copy the temp swap buffer data into attribute B // swap the originals - if (mKeepOriginals) + if (m_keepOriginals) { attribPtrA = (uint8*)GetOriginalData(attribA); attribPtrB = (uint8*)GetOriginalData(attribB); - MCore::MemCopy(mSwapBuffer, attribPtrA, mAttribSizeInBytes); // copy attribute A into the temp swap buffer - MCore::MemCopy(attribPtrA, attribPtrB, mAttribSizeInBytes); // copy attribute B into A - MCore::MemCopy(attribPtrB, mSwapBuffer, mAttribSizeInBytes); // copy the temp swap buffer data into attribute B + MCore::MemCopy(m_swapBuffer, attribPtrA, m_attribSizeInBytes); // copy attribute A into the temp swap buffer + MCore::MemCopy(attribPtrA, attribPtrB, m_attribSizeInBytes); // copy attribute B into A + MCore::MemCopy(attribPtrB, m_swapBuffer, m_attribSizeInBytes); // copy the temp swap buffer data into attribute B } } @@ -140,8 +140,8 @@ namespace EMotionFX // remove the swap buffer from memory void VertexAttributeLayerAbstractData::RemoveSwapBuffer() { - MCore::AlignedFree(mSwapBuffer); - mSwapBuffer = nullptr; + MCore::AlignedFree(m_swapBuffer); + m_swapBuffer = nullptr; } @@ -149,11 +149,11 @@ namespace EMotionFX void VertexAttributeLayerAbstractData::RemoveAttributes(uint32 startAttributeNr, uint32 endAttributeNr) { // perform some checks on the input data - MCORE_ASSERT(startAttributeNr < mNumAttributes); - MCORE_ASSERT(endAttributeNr < mNumAttributes); + MCORE_ASSERT(startAttributeNr < m_numAttributes); + MCORE_ASSERT(endAttributeNr < m_numAttributes); // Store the original number of bytes for the reallocation - const size_t numOriginalBytes = CalcTotalDataSizeInBytes(mKeepOriginals); + const size_t numOriginalBytes = CalcTotalDataSizeInBytes(m_keepOriginals); // make sure the start attribute number is lower than the end uint32 start = startAttributeNr; @@ -174,33 +174,33 @@ namespace EMotionFX } // remove the attributes from the current data - const uint32 numBytesToMove = (mNumAttributes - end - 1) * mAttribSizeInBytes; + const uint32 numBytesToMove = (m_numAttributes - end - 1) * m_attribSizeInBytes; if (numBytesToMove > 0) { - MCore::MemMove(mData + start * mAttribSizeInBytes, mData + (end + 1) * mAttribSizeInBytes, numBytesToMove); + MCore::MemMove(m_data + start * m_attribSizeInBytes, m_data + (end + 1) * m_attribSizeInBytes, numBytesToMove); } // remove the attributes from the original data - if (mKeepOriginals) + if (m_keepOriginals) { // remove them from the original data uint8* orgData = (uint8*)GetOriginalData(); if (numBytesToMove > 0) { - MCore::MemMove(orgData + start * mAttribSizeInBytes, orgData + (end + 1) * mAttribSizeInBytes, numBytesToMove); + MCore::MemMove(orgData + start * m_attribSizeInBytes, orgData + (end + 1) * m_attribSizeInBytes, numBytesToMove); } // remove the created gap between the current data and original data, as both original and current data remain in the same continuous piece of memory - MCore::MemMove(mData + (mNumAttributes - numAttribsToRemove) * mAttribSizeInBytes, orgData, (mNumAttributes - numAttribsToRemove) * mAttribSizeInBytes); + MCore::MemMove(m_data + (m_numAttributes - numAttribsToRemove) * m_attribSizeInBytes, orgData, (m_numAttributes - numAttribsToRemove) * m_attribSizeInBytes); } // decrease the number of attributes - mNumAttributes -= numAttribsToRemove; + m_numAttributes -= numAttribsToRemove; // reallocate, to make the data array smaller - const uint32 numBytes = CalcTotalDataSizeInBytes(mKeepOriginals); - mData = (uint8*)MCore::AlignedRealloc(mData, numBytes, numOriginalBytes, 16, EMFX_MEMCATEGORY_GEOMETRY_VERTEXATTRIBUTES); + const uint32 numBytes = CalcTotalDataSizeInBytes(m_keepOriginals); + m_data = (uint8*)MCore::AlignedRealloc(m_data, numBytes, numOriginalBytes, 16, EMFX_MEMCATEGORY_GEOMETRY_VERTEXATTRIBUTES); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/VertexAttributeLayerAbstractData.h b/Gems/EMotionFX/Code/EMotionFX/Source/VertexAttributeLayerAbstractData.h index f2520e6b70..fcd625dbb3 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/VertexAttributeLayerAbstractData.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/VertexAttributeLayerAbstractData.h @@ -92,13 +92,13 @@ namespace EMotionFX * Get a pointer to the data for a given attribute. You have to typecast the data yourself. * @result A pointer to the vertex data of the specified attribute number. */ - MCORE_INLINE void* GetData(uint32 attributeNr) { return (mData + mAttribSizeInBytes * attributeNr); } + MCORE_INLINE void* GetData(uint32 attributeNr) { return (m_data + m_attribSizeInBytes * attributeNr); } /** * Get a pointer to the data. You have to typecast the data yourself. * @result A pointer to the vertex data. */ - MCORE_INLINE void* GetData() override { return mData; } + MCORE_INLINE void* GetData() override { return m_data; } /** * Get the size of one attribute in bytes. @@ -106,7 +106,7 @@ namespace EMotionFX * equal to sizeof(Vector3). * @result The size of a single attribute, in bytes. */ - MCORE_INLINE uint32 GetAttributeSizeInBytes() const { return mAttribSizeInBytes; } + MCORE_INLINE uint32 GetAttributeSizeInBytes() const { return m_attribSizeInBytes; } /** * Get a pointer to the original data, as it is stored in the base pose, before any mesh deformers have been applied. @@ -115,13 +115,13 @@ namespace EMotionFX */ MCORE_INLINE void* GetOriginalData() override { - if (mKeepOriginals) + if (m_keepOriginals) { - return (mData + (mAttribSizeInBytes * mNumAttributes)); + return (m_data + (m_attribSizeInBytes * m_numAttributes)); } else { - return mData; + return m_data; } } @@ -132,13 +132,13 @@ namespace EMotionFX */ MCORE_INLINE void* GetOriginalData(uint32 attributeNr) { - if (mKeepOriginals) + if (m_keepOriginals) { - return (mData + (mAttribSizeInBytes * mNumAttributes) + (mAttribSizeInBytes * attributeNr)); + return (m_data + (m_attribSizeInBytes * m_numAttributes) + (m_attribSizeInBytes * attributeNr)); } else { - return (mData + mAttribSizeInBytes * attributeNr); + return (m_data + m_attribSizeInBytes * attributeNr); } } @@ -166,10 +166,10 @@ namespace EMotionFX bool GetIsAbstractDataClass() const override; private: - uint8* mData; /**< The buffer containing the data. */ - uint8* mSwapBuffer; /**< The swap buffer, used for swapping items. This will only be allocated once you call SwapAttribute, like the LOD generation system does. */ - uint32 mAttribSizeInBytes; /**< The size of a single attribute, in bytes. */ - uint32 mTypeID; /**< The type ID that identifies the type of the data, for example if it is position data, normal data, or colors, etc. */ + uint8* m_data; /**< The buffer containing the data. */ + uint8* m_swapBuffer; /**< The swap buffer, used for swapping items. This will only be allocated once you call SwapAttribute, like the LOD generation system does. */ + uint32 m_attribSizeInBytes; /**< The size of a single attribute, in bytes. */ + uint32 m_typeId; /**< The type ID that identifies the type of the data, for example if it is position data, normal data, or colors, etc. */ /** * The constructor. diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/DockWidgetPlugin.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/DockWidgetPlugin.cpp index 26addcf6e8..4c62d48610 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/DockWidgetPlugin.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/DockWidgetPlugin.cpp @@ -19,23 +19,23 @@ namespace EMStudio // constructor DockWidgetPlugin::DockWidgetPlugin() : EMStudioPlugin() - , mDock() + , m_dock() { } // destructor DockWidgetPlugin::~DockWidgetPlugin() { - if (!mDock.isNull()) + if (!m_dock.isNull()) { - // Disconnecting all signals from mDock to this object since we are + // Disconnecting all signals from m_dock to this object since we are // destroying it. Some plugins connect to visibility change that gets // triggered from removeDockWidget. Calling those slots at this point // is not safe since the plugin is being destroyed. - mDock->disconnect(this); + m_dock->disconnect(this); - EMStudio::GetMainWindow()->removeDockWidget(mDock); - delete mDock; + EMStudio::GetMainWindow()->removeDockWidget(m_dock); + delete m_dock; } } @@ -47,13 +47,13 @@ namespace EMStudio // check if we have a window that uses this object name bool DockWidgetPlugin::GetHasWindowWithObjectName(const AZStd::string& objectName) { - if (mDock.isNull()) + if (m_dock.isNull()) { return false; } // check if the object name is equal to the one of the dock widget - return objectName == FromQtString(mDock->objectName()); + return objectName == FromQtString(m_dock->objectName()); } @@ -75,25 +75,25 @@ namespace EMStudio // set the interface title void DockWidgetPlugin::SetInterfaceTitle(const char* name) { - if (!mDock.isNull()) + if (!m_dock.isNull()) { - mDock->setWindowTitle(name); + m_dock->setWindowTitle(name); } } QDockWidget* DockWidgetPlugin::GetDockWidget() { - if (!mDock.isNull()) + if (!m_dock.isNull()) { - return mDock; + return m_dock; } // get the main window QMainWindow* mainWindow = GetMainWindow(); // create a window for the plugin - mDock = new RemovePluginOnCloseDockWidget(mainWindow, GetName(), this); - mDock->setAllowedAreas(Qt::AllDockWidgetAreas); + m_dock = new RemovePluginOnCloseDockWidget(mainWindow, GetName(), this); + m_dock->setAllowedAreas(Qt::AllDockWidgetAreas); QDockWidget::DockWidgetFeatures features = QDockWidget::NoDockWidgetFeatures; if (GetIsClosable()) @@ -113,11 +113,11 @@ namespace EMStudio features |= QDockWidget::DockWidgetFloatable; } - mDock->setFeatures(features); + m_dock->setFeatures(features); - mainWindow->addDockWidget(Qt::RightDockWidgetArea, mDock); + mainWindow->addDockWidget(Qt::RightDockWidgetArea, m_dock); - return mDock; + return m_dock; } QWidget* DockWidgetPlugin::CreateErrorContentWidget(const char* errorMessage) const diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/DockWidgetPlugin.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/DockWidgetPlugin.h index ac58dd9be7..0db8a68ff6 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/DockWidgetPlugin.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/DockWidgetPlugin.h @@ -41,7 +41,7 @@ namespace EMStudio virtual void SetInterfaceTitle(const char* name); void CreateBaseInterface(const char* objectName) override; - QString GetObjectName() const override { AZ_Assert(mDock, "mDock is null"); return mDock->objectName(); } + QString GetObjectName() const override { AZ_Assert(m_dock, "m_dock is null"); return m_dock->objectName(); } void SetObjectName(const QString& name) override { GetDockWidget()->setObjectName(name); } virtual QSize GetInitialWindowSize() const { return QSize(500, 650); } @@ -53,6 +53,6 @@ namespace EMStudio protected: QWidget* CreateErrorContentWidget(const char* errorMessage) const; - QPointer mDock; + QPointer m_dock; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioManager.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioManager.cpp index 2f557ad290..2321d7c71b 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioManager.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioManager.cpp @@ -62,12 +62,12 @@ namespace EMStudio // Flag that we have an editor around EMotionFX::GetEMotionFX().SetIsInEditorMode(true); - mHTMLLinkString.reserve(32768); - mEventProcessingCallback = nullptr; - mAutoLoadLastWorkspace = false; - mAvoidRendering = false; + m_htmlLinkString.reserve(32768); + m_eventProcessingCallback = nullptr; + m_autoLoadLastWorkspace = false; + m_avoidRendering = false; - mApp = app; + m_app = app; AZ::AllocatorInstance::Create(); @@ -86,20 +86,20 @@ namespace EMStudio MCore::GetLogManager().SetLogLevels(MCore::LogCallback::LOGLEVEL_ALL); // Register editor specific commands. - mCommandManager = new CommandSystem::CommandManager(); - mCommandManager->RegisterCommand(new CommandSaveActorAssetInfo()); - mCommandManager->RegisterCommand(new CommandSaveMotionAssetInfo()); - mCommandManager->RegisterCommand(new CommandSaveMotionSet()); - mCommandManager->RegisterCommand(new CommandSaveAnimGraph()); - mCommandManager->RegisterCommand(new CommandSaveWorkspace()); - mCommandManager->RegisterCommand(new CommandEditorLoadAnimGraph()); - mCommandManager->RegisterCommand(new CommandEditorLoadMotionSet()); + m_commandManager = new CommandSystem::CommandManager(); + m_commandManager->RegisterCommand(new CommandSaveActorAssetInfo()); + m_commandManager->RegisterCommand(new CommandSaveMotionAssetInfo()); + m_commandManager->RegisterCommand(new CommandSaveMotionSet()); + m_commandManager->RegisterCommand(new CommandSaveAnimGraph()); + m_commandManager->RegisterCommand(new CommandSaveWorkspace()); + m_commandManager->RegisterCommand(new CommandEditorLoadAnimGraph()); + m_commandManager->RegisterCommand(new CommandEditorLoadMotionSet()); - mEventPresetManager = new MotionEventPresetManager(); - mPluginManager = new PluginManager(); - mLayoutManager = new LayoutManager(); - mNotificationWindowManager = new NotificationWindowManager(); - mCompileDate = AZStd::string::format("%s", MCORE_DATE); + m_eventPresetManager = new MotionEventPresetManager(); + m_pluginManager = new PluginManager(); + m_layoutManager = new LayoutManager(); + m_notificationWindowManager = new NotificationWindowManager(); + m_compileDate = AZStd::string::format("%s", MCORE_DATE); EMotionFX::SkeletonOutlinerNotificationBus::Handler::BusConnect(); @@ -113,33 +113,33 @@ namespace EMStudio { EMotionFX::SkeletonOutlinerNotificationBus::Handler::BusDisconnect(); - if (mEventProcessingCallback) + if (m_eventProcessingCallback) { - EMStudio::GetCommandManager()->RemoveCallback(mEventProcessingCallback, false); - delete mEventProcessingCallback; + EMStudio::GetCommandManager()->RemoveCallback(m_eventProcessingCallback, false); + delete m_eventProcessingCallback; } // delete all animgraph instances etc ClearScene(); - delete mEventPresetManager; - delete mPluginManager; - delete mLayoutManager; - delete mNotificationWindowManager; - delete mMainWindow; - delete mCommandManager; + delete m_eventPresetManager; + delete m_pluginManager; + delete m_layoutManager; + delete m_notificationWindowManager; + delete m_mainWindow; + delete m_commandManager; AZ::AllocatorInstance::Destroy(); } MainWindow* EMStudioManager::GetMainWindow() { - if (mMainWindow.isNull()) + if (m_mainWindow.isNull()) { - mMainWindow = new MainWindow(); - mMainWindow->Init(); + m_mainWindow = new MainWindow(); + m_mainWindow->Init(); } - return mMainWindow; + return m_mainWindow; } @@ -166,18 +166,18 @@ namespace EMStudio int EMStudioManager::ExecuteApp() { - MCORE_ASSERT(mApp); - MCORE_ASSERT(mMainWindow); + MCORE_ASSERT(m_app); + MCORE_ASSERT(m_mainWindow); #if !defined(EMFX_EMSTUDIOLYEMBEDDED) // try to load all plugins AZStd::string pluginDir = MysticQt::GetAppDir() + "Plugins/"; - mPluginManager->LoadPluginsFromDirectory(pluginDir.c_str()); + m_pluginManager->LoadPluginsFromDirectory(pluginDir.c_str()); #endif // EMFX_EMSTUDIOLYEMBEDDED // Give a chance to every plugin to reflect data - const size_t numPlugins = mPluginManager->GetNumPlugins(); + const size_t numPlugins = m_pluginManager->GetNumPlugins(); if (numPlugins) { AZ::SerializeContext* serializeContext = nullptr; @@ -190,31 +190,31 @@ namespace EMStudio { for (size_t i = 0; i < numPlugins; ++i) { - EMStudioPlugin* plugin = mPluginManager->GetPlugin(i); + EMStudioPlugin* plugin = m_pluginManager->GetPlugin(i); plugin->Reflect(serializeContext); } } } // Register the command event processing callback. - mEventProcessingCallback = new EventProcessingCallback(); - EMStudio::GetCommandManager()->RegisterCallback(mEventProcessingCallback); + m_eventProcessingCallback = new EventProcessingCallback(); + EMStudio::GetCommandManager()->RegisterCallback(m_eventProcessingCallback); // Update the main window create window item with, so that it shows all loaded plugins. - mMainWindow->UpdateCreateWindowMenu(); + m_mainWindow->UpdateCreateWindowMenu(); // Set the recover save path. - MCore::FileSystem::mSecureSavePath = GetManager()->GetRecoverFolder().c_str(); + MCore::FileSystem::s_secureSavePath = GetManager()->GetRecoverFolder().c_str(); // Show the main dialog and wait until it closes. MCore::LogInfo("EMotion Studio initialized..."); #if !defined(EMFX_EMSTUDIOLYEMBEDDED) - mMainWindow->show(); + m_mainWindow->show(); #endif // EMFX_EMSTUDIOLYEMBEDDED // Show the recover window in case we have some .recover files in the recovery folder. - const QString secureSavePath = MCore::FileSystem::mSecureSavePath.c_str(); + const QString secureSavePath = MCore::FileSystem::s_secureSavePath.c_str(); const QStringList recoverFileList = QDir(secureSavePath).entryList(QStringList("*.recover"), QDir::Files); if (!recoverFileList.empty()) { @@ -240,16 +240,16 @@ namespace EMStudio // Show the recover files window only in case there is a valid file to recover. if (!recoverStringArray.empty()) { - RecoverFilesWindow* recoverFilesWindow = new RecoverFilesWindow(mMainWindow, recoverStringArray); + RecoverFilesWindow* recoverFilesWindow = new RecoverFilesWindow(m_mainWindow, recoverStringArray); recoverFilesWindow->exec(); } } - mApp->processEvents(); + m_app->processEvents(); #if !defined(EMFX_EMSTUDIOLYEMBEDDED) // execute the application - return mApp->exec(); + return m_app->exec(); #else return 0; #endif // EMFX_EMSTUDIOLYEMBEDDED @@ -263,12 +263,12 @@ namespace EMStudio const char* EMStudioManager::ConstructHTMLLink(const char* text, const MCore::RGBAColor& color) { - int32 r = aznumeric_cast(color.r * 256); - int32 g = aznumeric_cast(color.g * 256); - int32 b = aznumeric_cast(color.b * 256); + int32 r = aznumeric_cast(color.m_r * 256); + int32 g = aznumeric_cast(color.m_g * 256); + int32 b = aznumeric_cast(color.m_b * 256); - mHTMLLinkString = AZStd::string::format("%s", r, g, b, text, text); - return mHTMLLinkString.c_str(); + m_htmlLinkString = AZStd::string::format("%s", r, g, b, text, text); + return m_htmlLinkString.c_str(); } @@ -432,7 +432,7 @@ namespace EMStudio } // add and return the manipulator - mTransformationManipulators.emplace_back(manipulator); + m_transformationManipulators.emplace_back(manipulator); return manipulator; } @@ -440,9 +440,9 @@ namespace EMStudio // remove the given gizmo from the array void EMStudioManager::RemoveTransformationManipulator(MCommon::TransformationManipulator* manipulator) { - if (const auto it = AZStd::find(begin(mTransformationManipulators), end(mTransformationManipulators), manipulator); it != end(mTransformationManipulators)) + if (const auto it = AZStd::find(begin(m_transformationManipulators), end(m_transformationManipulators), manipulator); it != end(m_transformationManipulators)) { - mTransformationManipulators.erase(it); + m_transformationManipulators.erase(it); } } @@ -450,7 +450,7 @@ namespace EMStudio // returns the gizmo array AZStd::vector* EMStudioManager::GetTransformationManipulators() { - return &mTransformationManipulators; + return &m_transformationManipulators; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioManager.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioManager.h index 95dbd3012a..909f0231f3 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioManager.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioManager.h @@ -59,15 +59,15 @@ namespace EMStudio EMStudioManager(QApplication* app, int& argc, char* argv[]); ~EMStudioManager(); - const char* GetCompileDate() const { return mCompileDate.c_str(); } + const char* GetCompileDate() const { return m_compileDate.c_str(); } - MCORE_INLINE QApplication* GetApp() { return mApp; } - MCORE_INLINE bool HasMainWindow() const { return !mMainWindow.isNull(); } + MCORE_INLINE QApplication* GetApp() { return m_app; } + MCORE_INLINE bool HasMainWindow() const { return !m_mainWindow.isNull(); } MainWindow* GetMainWindow(); - MCORE_INLINE PluginManager* GetPluginManager() { return mPluginManager; } - MCORE_INLINE LayoutManager* GetLayoutManager() { return mLayoutManager; } - MCORE_INLINE NotificationWindowManager* GetNotificationWindowManager() { return mNotificationWindowManager; } - MCORE_INLINE CommandSystem::CommandManager* GetCommandManager() { return mCommandManager; } + MCORE_INLINE PluginManager* GetPluginManager() { return m_pluginManager; } + MCORE_INLINE LayoutManager* GetLayoutManager() { return m_layoutManager; } + MCORE_INLINE NotificationWindowManager* GetNotificationWindowManager() { return m_notificationWindowManager; } + MCORE_INLINE CommandSystem::CommandManager* GetCommandManager() { return m_commandManager; } AZStd::string GetAppDataFolder() const; AZStd::string GetRecoverFolder() const; AZStd::string GetAutosavesFolder() const; @@ -76,10 +76,10 @@ namespace EMStudio static void RenderText(QPainter& painter, const QString& text, const QColor& textColor, const QFont& font, const QFontMetrics& fontMetrics, Qt::Alignment textAlignment, const QRect& rect); // motion event presets - MotionEventPresetManager* GetEventPresetManger() const { return mEventPresetManager; } + MotionEventPresetManager* GetEventPresetManger() const { return m_eventPresetManager; } - void SetAutoLoadLastWorkspace(bool autoLoad) { mAutoLoadLastWorkspace = autoLoad; } - bool GetAutoLoadLastWorkspace() const { return mAutoLoadLastWorkspace; } + void SetAutoLoadLastWorkspace(bool autoLoad) { m_autoLoadLastWorkspace = autoLoad; } + bool GetAutoLoadLastWorkspace() const { return m_autoLoadLastWorkspace; } const char* ConstructHTMLLink(const char* text, const MCore::RGBAColor& color = MCore::RGBAColor(0.95315f, 0.609375f, 0.109375f)); void SetWidgetAsInvalidInput(QWidget* widget); @@ -99,7 +99,7 @@ namespace EMStudio void SetSelectedJointIndices(const AZStd::unordered_set& selectedJointIndices); const AZStd::unordered_set& GetSelectedJointIndices() const { return m_selectedJointIndices; } - Workspace* GetWorkspace() { return &mWorkspace; } + Workspace* GetWorkspace() { return &m_workspace; } // functions for adding/removing gizmos MCommon::TransformationManipulator* AddTransformationManipulator(MCommon::TransformationManipulator* manipulator); @@ -108,29 +108,29 @@ namespace EMStudio void ClearScene(); // remove animgraphs, animgraph instances and actors - MCORE_INLINE bool GetAvoidRendering() const { return mAvoidRendering; } - MCORE_INLINE void SetAvoidRendering(bool avoidRendering) { mAvoidRendering = avoidRendering; } - MCORE_INLINE bool GetIgnoreVisibility() const { return mIgnoreVisible; } - MCORE_INLINE void SetIgnoreVisibility(bool ignoreVisible) { mIgnoreVisible = ignoreVisible; } + MCORE_INLINE bool GetAvoidRendering() const { return m_avoidRendering; } + MCORE_INLINE void SetAvoidRendering(bool avoidRendering) { m_avoidRendering = avoidRendering; } + MCORE_INLINE bool GetIgnoreVisibility() const { return m_ignoreVisible; } + MCORE_INLINE void SetIgnoreVisibility(bool ignoreVisible) { m_ignoreVisible = ignoreVisible; } MCORE_INLINE bool GetSkipSourceControlCommands() { return m_skipSourceControlCommands; } MCORE_INLINE void SetSkipSourceControlCommands(bool skip) { m_skipSourceControlCommands = skip; } private: - AZStd::vector mTransformationManipulators; - QPointer mMainWindow; - QApplication* mApp; - PluginManager* mPluginManager; - LayoutManager* mLayoutManager; - NotificationWindowManager* mNotificationWindowManager; - CommandSystem::CommandManager* mCommandManager; - AZStd::string mCompileDate; + AZStd::vector m_transformationManipulators; + QPointer m_mainWindow; + QApplication* m_app; + PluginManager* m_pluginManager; + LayoutManager* m_layoutManager; + NotificationWindowManager* m_notificationWindowManager; + CommandSystem::CommandManager* m_commandManager; + AZStd::string m_compileDate; AZStd::unordered_set m_visibleJointIndices; AZStd::unordered_set m_selectedJointIndices; - Workspace mWorkspace; - bool mAutoLoadLastWorkspace; - AZStd::string mHTMLLinkString; - bool mAvoidRendering; - bool mIgnoreVisible = false; - MotionEventPresetManager* mEventPresetManager; + Workspace m_workspace; + bool m_autoLoadLastWorkspace; + AZStd::string m_htmlLinkString; + bool m_avoidRendering; + bool m_ignoreVisible = false; + MotionEventPresetManager* m_eventPresetManager; bool m_skipSourceControlCommands = false; // SkeletonOutlinerNotificationBus @@ -150,7 +150,7 @@ namespace EMStudio void OnRemoveCommand(size_t historyIndex) override { MCORE_UNUSED(historyIndex); } void OnSetCurrentCommand(size_t index) override { MCORE_UNUSED(index); } }; - EventProcessingCallback* mEventProcessingCallback; + EventProcessingCallback* m_eventProcessingCallback; }; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioPlugin.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioPlugin.h index 49f306c7e0..0de4ab946c 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioPlugin.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioPlugin.h @@ -80,16 +80,16 @@ namespace EMStudio RenderInfo(MCommon::RenderUtil* renderUtil, MCommon::Camera* camera, uint32 screenWidth, uint32 screenHeight) { - mRenderUtil = renderUtil; - mCamera = camera; - mScreenWidth = screenWidth; - mScreenHeight = screenHeight; + m_renderUtil = renderUtil; + m_camera = camera; + m_screenWidth = screenWidth; + m_screenHeight = screenHeight; } - MCommon::RenderUtil* mRenderUtil; - MCommon::Camera* mCamera; - uint32 mScreenWidth; - uint32 mScreenHeight; + MCommon::RenderUtil* m_renderUtil; + MCommon::Camera* m_camera; + uint32 m_screenWidth; + uint32 m_screenHeight; }; virtual void Render(RenderPlugin* renderPlugin, RenderInfo* renderInfo) { MCORE_UNUSED(renderPlugin); MCORE_UNUSED(renderInfo); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/FileManager.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/FileManager.cpp index dcb7c46fe5..5a89729e49 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/FileManager.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/FileManager.cpp @@ -46,11 +46,11 @@ namespace EMStudio FileManager::FileManager(QWidget* parent) : QObject(parent) { - mLastActorFolder = EMotionFX::GetEMotionFX().GetAssetSourceFolder().c_str(); - mLastMotionSetFolder = EMotionFX::GetEMotionFX().GetAssetSourceFolder().c_str(); - mLastAnimGraphFolder = EMotionFX::GetEMotionFX().GetAssetSourceFolder().c_str(); - mLastWorkspaceFolder = EMotionFX::GetEMotionFX().GetAssetSourceFolder().c_str(); - mLastNodeMapFolder = EMotionFX::GetEMotionFX().GetAssetSourceFolder().c_str(); + m_lastActorFolder = EMotionFX::GetEMotionFX().GetAssetSourceFolder().c_str(); + m_lastMotionSetFolder = EMotionFX::GetEMotionFX().GetAssetSourceFolder().c_str(); + m_lastAnimGraphFolder = EMotionFX::GetEMotionFX().GetAssetSourceFolder().c_str(); + m_lastWorkspaceFolder = EMotionFX::GetEMotionFX().GetAssetSourceFolder().c_str(); + m_lastNodeMapFolder = EMotionFX::GetEMotionFX().GetAssetSourceFolder().c_str(); // Connect to the asset catalog bus for product asset changes. AzFramework::AssetCatalogEventBus::Handler::BusConnect(); @@ -416,14 +416,14 @@ namespace EMStudio QString selectedFilter; const AZStd::string filename = QFileDialog::getSaveFileName(parent, // parent "Save", // caption - GetLastUsedFolder(mLastActorFolder), // directory + GetLastUsedFolder(m_lastActorFolder), // directory "EMotion FX Actor Files (*.actor)", &selectedFilter, options).toUtf8().data(); GetManager()->SetAvoidRendering(false); - UpdateLastUsedFolder(filename.c_str(), mLastActorFolder); + UpdateLastUsedFolder(filename.c_str(), m_lastActorFolder); return filename; } @@ -456,12 +456,12 @@ namespace EMStudio QString selectedFilter; AZStd::string filename = QFileDialog::getOpenFileName(parent, // parent "Open", // caption - GetLastUsedFolder(mLastWorkspaceFolder), // directory + GetLastUsedFolder(m_lastWorkspaceFolder), // directory "EMotionFX Editor Workspace Files (*.emfxworkspace);;All Files (*)", &selectedFilter, options).toUtf8().data(); - UpdateLastUsedFolder(filename.c_str(), mLastWorkspaceFolder); + UpdateLastUsedFolder(filename.c_str(), m_lastWorkspaceFolder); GetManager()->SetAvoidRendering(false); return filename; } @@ -475,7 +475,7 @@ namespace EMStudio QString selectedFilter; AZStd::string filename = QFileDialog::getSaveFileName(parent, // parent "Save", // caption - GetLastUsedFolder(mLastWorkspaceFolder), // directory + GetLastUsedFolder(m_lastWorkspaceFolder), // directory "EMotionFX Editor Workspace Files (*.emfxworkspace)", &selectedFilter, options).toUtf8().data(); @@ -488,7 +488,7 @@ namespace EMStudio return AZStd::string(); } - UpdateLastUsedFolder(filename.c_str(), mLastWorkspaceFolder); + UpdateLastUsedFolder(filename.c_str(), m_lastWorkspaceFolder); return filename; } @@ -557,14 +557,14 @@ namespace EMStudio QString selectedFilter; AZStd::string filename = QFileDialog::getSaveFileName(parent, // parent "Save", // caption - GetLastUsedFolder(mLastMotionSetFolder), // directory + GetLastUsedFolder(m_lastMotionSetFolder), // directory "EMotion FX Motion Set Files (*.motionset)", &selectedFilter, options).toUtf8().data(); GetManager()->SetAvoidRendering(false); - UpdateLastUsedFolder(filename.c_str(), mLastMotionSetFolder); + UpdateLastUsedFolder(filename.c_str(), m_lastMotionSetFolder); return filename; } @@ -636,14 +636,14 @@ namespace EMStudio QString selectedFilter; AZStd::string filename = QFileDialog::getSaveFileName(parent, // parent "Save", // caption - GetLastUsedFolder(mLastAnimGraphFolder), // directory + GetLastUsedFolder(m_lastAnimGraphFolder), // directory "EMotion FX Anim Graph Files (*.animgraph);;All Files (*)", &selectedFilter, options).toUtf8().data(); GetManager()->SetAvoidRendering(false); - UpdateLastUsedFolder(filename.c_str(), mLastAnimGraphFolder); + UpdateLastUsedFolder(filename.c_str(), m_lastAnimGraphFolder); return filename; } @@ -658,14 +658,14 @@ namespace EMStudio QString selectedFilter; const AZStd::string filename = QFileDialog::getOpenFileName(parent, // parent "Open", // caption - GetLastUsedFolder(mLastNodeMapFolder), // directory + GetLastUsedFolder(m_lastNodeMapFolder), // directory "Node Map Files (*.nodeMap);;All Files (*)", &selectedFilter, options).toUtf8().data(); GetManager()->SetAvoidRendering(false); - UpdateLastUsedFolder(filename.c_str(), mLastNodeMapFolder); + UpdateLastUsedFolder(filename.c_str(), m_lastNodeMapFolder); return filename; } @@ -679,14 +679,14 @@ namespace EMStudio QString selectedFilter; const AZStd::string filename = QFileDialog::getSaveFileName(parent, // parent "Save", // caption - GetLastUsedFolder(mLastNodeMapFolder), // directory + GetLastUsedFolder(m_lastNodeMapFolder), // directory "Node Map Files (*.nodeMap);;All Files (*)", &selectedFilter, options).toUtf8().data(); GetManager()->SetAvoidRendering(false); - UpdateLastUsedFolder(filename.c_str(), mLastNodeMapFolder); + UpdateLastUsedFolder(filename.c_str(), m_lastNodeMapFolder); return filename; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/FileManager.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/FileManager.h index 50dfce390a..98d7de188d 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/FileManager.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/FileManager.h @@ -106,13 +106,13 @@ namespace EMStudio private: AZStd::vector m_savedSourceAssets; - QString mLastActorFolder; - QString mLastMotionSetFolder; - QString mLastAnimGraphFolder; - QString mLastWorkspaceFolder; - QString mLastNodeMapFolder; + QString m_lastActorFolder; + QString m_lastMotionSetFolder; + QString m_lastAnimGraphFolder; + QString m_lastWorkspaceFolder; + QString m_lastNodeMapFolder; - bool mSkipFileChangedCheck; + bool m_skipFileChangedCheck; void UpdateLastUsedFolder(const char* filename, QString& outLastFolder) const; QString GetLastUsedFolder(const QString& lastUsedFolder) const; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/KeyboardShortcutsWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/KeyboardShortcutsWindow.cpp index 7355b1da0a..bccf4e1be3 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/KeyboardShortcutsWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/KeyboardShortcutsWindow.cpp @@ -34,8 +34,8 @@ namespace EMStudio KeyboardShortcutsWindow::KeyboardShortcutsWindow(QWidget* parent) : QWidget(parent) { - mSelectedGroup = -1; - mShortcutReceiverDialog = nullptr; + m_selectedGroup = -1; + m_shortcutReceiverDialog = nullptr; // fill the table Init(); @@ -52,51 +52,51 @@ namespace EMStudio void KeyboardShortcutsWindow::Init() { // create the node groups table - mTableWidget = new QTableWidget(); + m_tableWidget = new QTableWidget(); // create the table widget - mTableWidget->setSortingEnabled(false); - mTableWidget->setAlternatingRowColors(true); - mTableWidget->setCornerButtonEnabled(false); - mTableWidget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); - mTableWidget->setContextMenuPolicy(Qt::DefaultContextMenu); + m_tableWidget->setSortingEnabled(false); + m_tableWidget->setAlternatingRowColors(true); + m_tableWidget->setCornerButtonEnabled(false); + m_tableWidget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); + m_tableWidget->setContextMenuPolicy(Qt::DefaultContextMenu); // set the table to row single selection - mTableWidget->setSelectionBehavior(QAbstractItemView::SelectRows); - mTableWidget->setSelectionMode(QAbstractItemView::SingleSelection); + m_tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows); + m_tableWidget->setSelectionMode(QAbstractItemView::SingleSelection); - connect(mTableWidget, &QTableWidget::cellDoubleClicked, this, &KeyboardShortcutsWindow::OnShortcutChange); + connect(m_tableWidget, &QTableWidget::cellDoubleClicked, this, &KeyboardShortcutsWindow::OnShortcutChange); // create the list widget - mListWidget = new QListWidget(); - mListWidget->setAlternatingRowColors(true); - connect(mListWidget, &QListWidget::itemSelectionChanged, this, &KeyboardShortcutsWindow::OnGroupSelectionChanged); + m_listWidget = new QListWidget(); + m_listWidget->setAlternatingRowColors(true); + connect(m_listWidget, &QListWidget::itemSelectionChanged, this, &KeyboardShortcutsWindow::OnGroupSelectionChanged); // build the layout - mHLayout = new QHBoxLayout(); - mHLayout->setMargin(0); - mHLayout->setAlignment(Qt::AlignLeft); + m_hLayout = new QHBoxLayout(); + m_hLayout->setMargin(0); + m_hLayout->setAlignment(Qt::AlignLeft); - mHLayout->addWidget(mListWidget); + m_hLayout->addWidget(m_listWidget); QVBoxLayout* vLayout = new QVBoxLayout(); vLayout->setMargin(0); - vLayout->addWidget(mTableWidget); + vLayout->addWidget(m_tableWidget); QLabel* label = new QLabel("Double-click to adjust shortcut"); label->setAlignment(Qt::AlignCenter); vLayout->addWidget(label); - mHLayout->addLayout(vLayout); + m_hLayout->addLayout(vLayout); // set the main layout - setLayout(mHLayout); + setLayout(m_hLayout); ReInit(); // automatically select the first entry - if (mListWidget->count() > 0) + if (m_listWidget->count() > 0) { - mListWidget->setCurrentRow(0); + m_listWidget->setCurrentRow(0); } } @@ -115,14 +115,14 @@ namespace EMStudio // reconstruct the whole interface void KeyboardShortcutsWindow::ReInit() { - mTableWidget->blockSignals(true); + m_tableWidget->blockSignals(true); // clear - mListWidget->clear(); + m_listWidget->clear(); // make the list widget smaller than the table - mListWidget->setMinimumWidth(150); - mListWidget->setMaximumWidth(150); + m_listWidget->setMinimumWidth(150); + m_listWidget->setMaximumWidth(150); // add the groups to the left list widget MysticQt::KeyboardShortcutManager* shortcutManager = GetMainWindow()->GetShortcutManager(); @@ -130,13 +130,13 @@ namespace EMStudio for (uint32 i = 0; i < numGroups; ++i) { MysticQt::KeyboardShortcutManager::Group* group = shortcutManager->GetGroup(i); - mListWidget->addItem(FromStdString(group->GetName())); + m_listWidget->addItem(FromStdString(group->GetName())); } - mTableWidget->blockSignals(false); + m_tableWidget->blockSignals(false); // automatically select the first entry - mListWidget->setCurrentRow(mSelectedGroup); + m_listWidget->setCurrentRow(m_selectedGroup); } @@ -144,37 +144,37 @@ namespace EMStudio void KeyboardShortcutsWindow::OnGroupSelectionChanged() { // get the group index - mSelectedGroup = mListWidget->currentRow(); - if (mSelectedGroup == -1) + m_selectedGroup = m_listWidget->currentRow(); + if (m_selectedGroup == -1) { return; } // clear the table - mTableWidget->clear(); + m_tableWidget->clear(); // set header item for the table - mTableWidget->setColumnCount(2); + m_tableWidget->setColumnCount(2); QTableWidgetItem* headerItem = new QTableWidgetItem("Action"); headerItem->setTextAlignment(Qt::AlignVCenter | Qt::AlignLeft); - mTableWidget->setHorizontalHeaderItem(0, headerItem); + m_tableWidget->setHorizontalHeaderItem(0, headerItem); headerItem = new QTableWidgetItem("Shortcut"); headerItem->setTextAlignment(Qt::AlignVCenter | Qt::AlignLeft); - mTableWidget->setHorizontalHeaderItem(1, headerItem); + m_tableWidget->setHorizontalHeaderItem(1, headerItem); // set the vertical header not visible - QHeaderView* verticalHeader = mTableWidget->verticalHeader(); + QHeaderView* verticalHeader = m_tableWidget->verticalHeader(); verticalHeader->setVisible(false); // get access to the shortcut group and some data MysticQt::KeyboardShortcutManager* shortcutManager = GetMainWindow()->GetShortcutManager(); - MysticQt::KeyboardShortcutManager::Group* group = shortcutManager->GetGroup(mSelectedGroup); + MysticQt::KeyboardShortcutManager::Group* group = shortcutManager->GetGroup(m_selectedGroup); const size_t numActions = group->GetNumActions(); // set the row count - mTableWidget->setRowCount(aznumeric_caster(numActions)); + m_tableWidget->setRowCount(aznumeric_caster(numActions)); // fill the table with the media root folders for (uint32 i = 0; i < numActions; ++i) @@ -185,25 +185,25 @@ namespace EMStudio // add the item to the table and set the row height QTableWidgetItem* item = new QTableWidgetItem(action->m_qaction->text()); item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable); - mTableWidget->setItem(i, 0, item); + m_tableWidget->setItem(i, 0, item); const QString keyText = ConstructStringFromShortcut(action->m_qaction->shortcut()); item = new QTableWidgetItem(keyText); item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable); - mTableWidget->setItem(i, 1, item); + m_tableWidget->setItem(i, 1, item); - mTableWidget->setRowHeight(i, 21); + m_tableWidget->setRowHeight(i, 21); } // resize the first column - mTableWidget->resizeColumnToContents(0); + m_tableWidget->resizeColumnToContents(0); // needed to have the last column stretching correctly - mTableWidget->setColumnWidth(1, 0); + m_tableWidget->setColumnWidth(1, 0); // set the last column to take the whole space - mTableWidget->horizontalHeader()->setStretchLastSection(true); + m_tableWidget->horizontalHeader()->setStretchLastSection(true); } @@ -211,7 +211,7 @@ namespace EMStudio MysticQt::KeyboardShortcutManager::Group* KeyboardShortcutsWindow::GetCurrentGroup() const { // get access to the group - int32 groupIndex = mListWidget->currentRow(); + int32 groupIndex = m_listWidget->currentRow(); if (groupIndex == -1) { return nullptr; @@ -237,17 +237,17 @@ namespace EMStudio MysticQt::KeyboardShortcutManager::Action* action = group->GetAction(row); ShortcutReceiverDialog shortcutWindow(this, action, group); - mShortcutReceiverDialog = &shortcutWindow; + m_shortcutReceiverDialog = &shortcutWindow; if (shortcutWindow.exec() == QDialog::Accepted) { // handle conflicts - if (shortcutWindow.mConflictDetected) + if (shortcutWindow.m_conflictDetected) { - shortcutWindow.mConflictAction->m_qaction->setShortcut({}); + shortcutWindow.m_conflictAction->m_qaction->setShortcut({}); } // adjust the shortcut action - action->m_qaction->setShortcut(shortcutWindow.mKey); + action->m_qaction->setShortcut(shortcutWindow.m_key); // save the new shortcuts QSettings settings(FromStdString(AZStd::string(GetManager()->GetAppDataFolder() + "EMStudioKeyboardShortcuts.cfg")), QSettings::IniFormat, this); @@ -256,7 +256,7 @@ namespace EMStudio // reinit the window ReInit(); } - mShortcutReceiverDialog = nullptr; + m_shortcutReceiverDialog = nullptr; } @@ -275,12 +275,12 @@ namespace EMStudio // reset to default after pressing context menu void KeyboardShortcutsWindow::OnResetToDefault() { - if (mContextMenuAction == nullptr) + if (m_contextMenuAction == nullptr) { return; } - mContextMenuAction->m_qaction->setShortcut(mContextMenuAction->m_defaultKeySequence); + m_contextMenuAction->m_qaction->setShortcut(m_contextMenuAction->m_defaultKeySequence); ReInit(); } @@ -289,13 +289,13 @@ namespace EMStudio // assign a new key after pressing the context menu item void KeyboardShortcutsWindow::OnAssignNewKey() { - if (mContextMenuAction == nullptr) + if (m_contextMenuAction == nullptr) { return; } // assign the new shortcut - OnShortcutChange(mContextMenuActionIndex, 0); + OnShortcutChange(m_contextMenuActionIndex, 0); } @@ -303,7 +303,7 @@ namespace EMStudio void KeyboardShortcutsWindow::contextMenuEvent(QContextMenuEvent* event) { // find the table widget item at the clicked position - QTableWidgetItem* clickedItem = mTableWidget->itemAt(mTableWidget->viewport()->mapFromGlobal(event->globalPos())); + QTableWidgetItem* clickedItem = m_tableWidget->itemAt(m_tableWidget->viewport()->mapFromGlobal(event->globalPos())); if (clickedItem == nullptr) { return; @@ -315,8 +315,8 @@ namespace EMStudio MysticQt::KeyboardShortcutManager::Group* group = GetCurrentGroup(); // get access to the action - mContextMenuAction = group->GetAction(actionIndex); - mContextMenuActionIndex = actionIndex; + m_contextMenuAction = group->GetAction(actionIndex); + m_contextMenuActionIndex = actionIndex; // create the context menu QMenu menu(this); @@ -343,33 +343,33 @@ namespace EMStudio setWindowTitle(" "); layout->addWidget(new QLabel("Press the new shortcut on the keyboard:")); - mOrgAction = action; - mOrgGroup = group; + m_orgAction = action; + m_orgGroup = group; - mConflictAction = nullptr; - mConflictDetected = false; - mKey = action->m_qaction->shortcut(); + m_conflictAction = nullptr; + m_conflictDetected = false; + m_key = action->m_qaction->shortcut(); - QString keyText = KeyboardShortcutsWindow::ConstructStringFromShortcut(mKey); + QString keyText = KeyboardShortcutsWindow::ConstructStringFromShortcut(m_key); - mLabel = new QLabel(keyText); - mLabel->setAlignment(Qt::AlignHCenter); - QFont font = mLabel->font(); + m_label = new QLabel(keyText); + m_label->setAlignment(Qt::AlignHCenter); + QFont font = m_label->font(); font.setPointSize(14); font.setBold(true); - mLabel->setFont(font); - layout->addWidget(mLabel); + m_label->setFont(font); + layout->addWidget(m_label); - mConflictKeyLabel = new QLabel(""); - mConflictKeyLabel->setAlignment(Qt::AlignHCenter); - layout->addWidget(mConflictKeyLabel); + m_conflictKeyLabel = new QLabel(""); + m_conflictKeyLabel->setAlignment(Qt::AlignHCenter); + layout->addWidget(m_conflictKeyLabel); QHBoxLayout* buttonLayout = new QHBoxLayout(); buttonLayout->setMargin(0); - mOKButton = new QPushButton("OK"); - buttonLayout->addWidget(mOKButton); - connect(mOKButton, &QPushButton::clicked, this, &ShortcutReceiverDialog::accept); + m_okButton = new QPushButton("OK"); + buttonLayout->addWidget(m_okButton); + connect(m_okButton, &QPushButton::clicked, this, &ShortcutReceiverDialog::accept); QPushButton* defaultButton = new QPushButton("Default"); buttonLayout->addWidget(defaultButton); @@ -391,7 +391,7 @@ namespace EMStudio // reset the shortcut to its default value void ShortcutReceiverDialog::ResetToDefault() { - mKey = mOrgAction->m_defaultKeySequence; + m_key = m_orgAction->m_defaultKeySequence; UpdateInterface(); } @@ -403,41 +403,41 @@ namespace EMStudio MysticQt::KeyboardShortcutManager* shortcutManager = GetMainWindow()->GetShortcutManager(); // check if the currently assigned shortcut is already taken by another shortcut - mConflictAction = shortcutManager->FindShortcut(mKey, mOrgGroup); - if (mConflictAction == nullptr || mConflictAction == mOrgAction) + m_conflictAction = shortcutManager->FindShortcut(m_key, m_orgGroup); + if (m_conflictAction == nullptr || m_conflictAction == m_orgAction) { - mOKButton->setToolTip(""); - mLabel->setStyleSheet(""); - mConflictKeyLabel->setStyleSheet(""); - mConflictKeyLabel->setText(""); - mConflictDetected = false; + m_okButton->setToolTip(""); + m_label->setStyleSheet(""); + m_conflictKeyLabel->setStyleSheet(""); + m_conflictKeyLabel->setText(""); + m_conflictDetected = false; } else { - mLabel->setStyleSheet("color: rgb(244, 156, 28);"); - mConflictKeyLabel->setStyleSheet("color: rgb(244, 156, 28);"); + m_label->setStyleSheet("color: rgb(244, 156, 28);"); + m_conflictKeyLabel->setStyleSheet("color: rgb(244, 156, 28);"); - mConflictDetected = true; + m_conflictDetected = true; - if (mConflictAction) + if (m_conflictAction) { - mOKButton->setToolTip(QString("Assigning new shortcut will unassign '%1' automatically.").arg(mConflictAction->m_qaction->text())); + m_okButton->setToolTip(QString("Assigning new shortcut will unassign '%1' automatically.").arg(m_conflictAction->m_qaction->text())); - MysticQt::KeyboardShortcutManager::Group* conflictGroup = shortcutManager->FindGroupForShortcut(mConflictAction); + MysticQt::KeyboardShortcutManager::Group* conflictGroup = shortcutManager->FindGroupForShortcut(m_conflictAction); if (conflictGroup) { - mConflictKeyLabel->setText(QString("Conflicts with: %1 -> %2").arg(FromStdString(conflictGroup->GetName())).arg(mConflictAction->m_qaction->text())); + m_conflictKeyLabel->setText(QString("Conflicts with: %1 -> %2").arg(FromStdString(conflictGroup->GetName())).arg(m_conflictAction->m_qaction->text())); } else { - mConflictKeyLabel->setText(QString("Conflicts with: %1").arg(mConflictAction->m_qaction->text())); + m_conflictKeyLabel->setText(QString("Conflicts with: %1").arg(m_conflictAction->m_qaction->text())); } } } // adjust the label text to the new shortcut - const QString keyText = KeyboardShortcutsWindow::ConstructStringFromShortcut(mKey); - mLabel->setText(keyText); + const QString keyText = KeyboardShortcutsWindow::ConstructStringFromShortcut(m_key); + m_label->setText(keyText); } // called when the user pressed a new shortcut @@ -460,7 +460,7 @@ namespace EMStudio } else { - mKey = event->key() | event->modifiers(); + m_key = event->key() | event->modifiers(); } UpdateInterface(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/KeyboardShortcutsWindow.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/KeyboardShortcutsWindow.h index bcc33ae9f8..bf109af0ca 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/KeyboardShortcutsWindow.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/KeyboardShortcutsWindow.h @@ -39,18 +39,18 @@ namespace EMStudio void keyPressEvent(QKeyEvent* event) override; void UpdateInterface(); - QKeySequence mKey; - bool mConflictDetected; - MysticQt::KeyboardShortcutManager::Action* mConflictAction; + QKeySequence m_key; + bool m_conflictDetected; + MysticQt::KeyboardShortcutManager::Action* m_conflictAction; private slots: void ResetToDefault(); private: - QLabel* mLabel; - QLabel* mConflictKeyLabel; - QPushButton* mOKButton; - MysticQt::KeyboardShortcutManager::Action* mOrgAction; - MysticQt::KeyboardShortcutManager::Group* mOrgGroup; + QLabel* m_label; + QLabel* m_conflictKeyLabel; + QPushButton* m_okButton; + MysticQt::KeyboardShortcutManager::Action* m_orgAction; + MysticQt::KeyboardShortcutManager::Group* m_orgGroup; }; @@ -79,13 +79,13 @@ namespace EMStudio void OnAssignNewKey(); private: - QTableWidget* mTableWidget; - QListWidget* mListWidget; - QHBoxLayout* mHLayout; - int mSelectedGroup; - MysticQt::KeyboardShortcutManager::Action* mContextMenuAction; - int mContextMenuActionIndex; - ShortcutReceiverDialog* mShortcutReceiverDialog; + QTableWidget* m_tableWidget; + QListWidget* m_listWidget; + QHBoxLayout* m_hLayout; + int m_selectedGroup; + MysticQt::KeyboardShortcutManager::Action* m_contextMenuAction; + int m_contextMenuActionIndex; + ShortcutReceiverDialog* m_shortcutReceiverDialog; void contextMenuEvent(QContextMenuEvent* event) override; }; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/LayoutManager.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/LayoutManager.cpp index eed352ad7c..e2dbb3df60 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/LayoutManager.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/LayoutManager.cpp @@ -26,7 +26,7 @@ namespace EMStudio { LayoutManager::LayoutManager() { - mIsSwitching = false; + m_isSwitching = false; } LayoutManager::~LayoutManager() @@ -109,25 +109,25 @@ namespace EMStudio } LayoutHeader header; - header.mFileTypeCode[0] = 'E'; - header.mFileTypeCode[1] = 'M'; - header.mFileTypeCode[2] = 'S'; - header.mFileTypeCode[3] = 'L'; - header.mFileTypeCode[4] = 'A'; - header.mFileTypeCode[5] = 'Y'; - header.mFileTypeCode[6] = 'O'; - header.mFileTypeCode[7] = 'U'; - header.mFileTypeCode[8] = 'T'; - header.mEMFXVersionHigh = EMotionFX::GetEMotionFX().GetHighVersion(); - header.mEMFXVersionLow = EMotionFX::GetEMotionFX().GetLowVersion(); + header.m_fileTypeCode[0] = 'E'; + header.m_fileTypeCode[1] = 'M'; + header.m_fileTypeCode[2] = 'S'; + header.m_fileTypeCode[3] = 'L'; + header.m_fileTypeCode[4] = 'A'; + header.m_fileTypeCode[5] = 'Y'; + header.m_fileTypeCode[6] = 'O'; + header.m_fileTypeCode[7] = 'U'; + header.m_fileTypeCode[8] = 'T'; + header.m_emfxVersionHigh = EMotionFX::GetEMotionFX().GetHighVersion(); + header.m_emfxVersionLow = EMotionFX::GetEMotionFX().GetLowVersion(); - azstrcpy(header.mEMFXCompileDate, 64, EMotionFX::GetEMotionFX().GetCompilationDate()); - azstrcpy(header.mCompileDate, 64, MCORE_DATE); - azstrcpy(header.mDescription, 256, ""); + azstrcpy(header.m_emfxCompileDate, 64, EMotionFX::GetEMotionFX().GetCompilationDate()); + azstrcpy(header.m_compileDate, 64, MCORE_DATE); + azstrcpy(header.m_description, 256, ""); - header.mLayoutVersionHigh = 0; - header.mLayoutVersionLow = 1; - header.mNumPlugins = aznumeric_caster(GetPluginManager()->GetNumActivePlugins()); + header.m_layoutVersionHigh = 0; + header.m_layoutVersionLow = 1; + header.m_numPlugins = aznumeric_caster(GetPluginManager()->GetNumActivePlugins()); if (file.write((char*)&header, sizeof(LayoutHeader)) == -1) { MCore::LogWarning("Failed to write layout header to layout file '%s'", filename); @@ -135,7 +135,7 @@ namespace EMStudio } // For each plugin (window) save the object name. - for (uint32 i = 0; i < header.mNumPlugins; ++i) + for (uint32 i = 0; i < header.m_numPlugins; ++i) { EMStudioPlugin* plugin = GetPluginManager()->GetActivePlugin(i); @@ -145,16 +145,14 @@ namespace EMStudio // Save the plugin header. LayoutPluginHeader pluginHeader; - pluginHeader.mDataSize = static_cast(memFile.GetFileSize()); - pluginHeader.mDataVersion = plugin->GetLayoutDataVersion(); + pluginHeader.m_dataSize = static_cast(memFile.GetFileSize()); + pluginHeader.m_dataVersion = plugin->GetLayoutDataVersion(); - azstrcpy(pluginHeader.mObjectName, 128, FromQtString(plugin->GetObjectName()).c_str()); - azstrcpy(pluginHeader.mPluginName, 128, plugin->GetName()); + azstrcpy(pluginHeader.m_objectName, 128, FromQtString(plugin->GetObjectName()).c_str()); + azstrcpy(pluginHeader.m_pluginName, 128, plugin->GetName()); file.write((char*)&pluginHeader, sizeof(LayoutPluginHeader)); - //MCore::LogDetailedInfo("pluginHeader.mDataSize = %d bytes (version=%d) (name=%s)", pluginHeader.mDataSize, pluginHeader.mDataVersion, pluginHeader.mPluginName); - if (memFile.GetMemoryStart()) { if (file.write((char*)memFile.GetMemoryStart(), memFile.GetFileSize()) == -1) @@ -195,17 +193,17 @@ namespace EMStudio bool LayoutManager::LoadLayout(const char* filename) { // If we are already switching, skip directly. - if (mIsSwitching) + if (m_isSwitching) { return true; } - mIsSwitching = true; + m_isSwitching = true; QFile file(filename); if (file.open(QIODevice::ReadOnly) == false) { - mIsSwitching = false; + m_isSwitching = false; return false; } @@ -218,42 +216,31 @@ namespace EMStudio if (file.read((char*)&header, sizeof(LayoutHeader)) == -1) { MCore::LogWarning("Error reading header from layout file '%s'", filename); - mIsSwitching = false; + m_isSwitching = false; return false; } // Check if this is a valid layout file. - if (header.mFileTypeCode[0] != 'E' || header.mFileTypeCode[1] != 'M' || header.mFileTypeCode[2] != 'S' || - header.mFileTypeCode[3] != 'L' || header.mFileTypeCode[4] != 'A' || header.mFileTypeCode[5] != 'Y' || header.mFileTypeCode[6] != 'O' || header.mFileTypeCode[7] != 'U' || header.mFileTypeCode[8] != 'T') + if (header.m_fileTypeCode[0] != 'E' || header.m_fileTypeCode[1] != 'M' || header.m_fileTypeCode[2] != 'S' || + header.m_fileTypeCode[3] != 'L' || header.m_fileTypeCode[4] != 'A' || header.m_fileTypeCode[5] != 'Y' || header.m_fileTypeCode[6] != 'O' || header.m_fileTypeCode[7] != 'U' || header.m_fileTypeCode[8] != 'T') { MCore::LogWarning("Failed to load file '%s' as it is not a valid EMotion Studio layout file.", filename); - mIsSwitching = false; + m_isSwitching = false; return false; } - //MCore::LogDetailedInfo("EMotion FX version = v%d.%d", header.mEMFXVersionHigh, header.mEMFXVersionLow / 100); - //MCore::LogDetailedInfo("EMotion FX compile date = %s", header.mEMFXCompileDate); - //MCore::LogDetailedInfo("EMStudio compile date = %s", header.mCompileDate); - //MCore::LogDetailedInfo("Layout description = %s", header.mDescription); - //MCore::LogDetailedInfo("Layout version = v%d.%d", header.mLayoutVersionHigh, header.mLayoutVersionLow); - //MCore::LogDetailedInfo("Num active plugins = %d", header.mNumPlugins); - // Iterate through the plugins and try to reuse them. - for (uint32 i = 0; i < header.mNumPlugins; ++i) + for (uint32 i = 0; i < header.m_numPlugins; ++i) { // load the plugin header LayoutPluginHeader pluginHeader; if (file.read((char*)&pluginHeader, sizeof(LayoutPluginHeader)) == -1) { MCore::LogWarning("Error reading plugin header from layout file '%s'", filename); - mIsSwitching = false; + m_isSwitching = false; return false; } - //MCore::LogDetailedInfo("Loading plugin settings for plugin '%s'...", pluginHeader.mPluginName); - //MCore::LogDetailedInfo(" + Data size = %d bytes", pluginHeader.mDataSize); - //MCore::LogDetailedInfo(" + Data version = %d", pluginHeader.mDataVersion); - EMStudioPlugin* plugin = nullptr; // Check if we already have a window using a similar plugin. @@ -264,10 +251,10 @@ namespace EMStudio while (itActivePlugin != activePlugins.end()) { // Is the plugin name the same as we need to create? - if (AzFramework::StringFunc::Equal((*itActivePlugin)->GetName(), pluginHeader.mPluginName)) + if (AzFramework::StringFunc::Equal((*itActivePlugin)->GetName(), pluginHeader.m_pluginName)) { plugin = *itActivePlugin; - plugin->SetObjectName(pluginHeader.mObjectName); + plugin->SetObjectName(pluginHeader.m_objectName); if (plugin->GetPluginType() == EMStudioPlugin::PLUGINTYPE_DOCKWIDGET) { DockWidgetPlugin* dockPlugin = static_cast(plugin); @@ -289,23 +276,23 @@ namespace EMStudio // Try to create the plugin of this type. if (!plugin) { - plugin = GetPluginManager()->CreateWindowOfType(pluginHeader.mPluginName, pluginHeader.mObjectName); + plugin = GetPluginManager()->CreateWindowOfType(pluginHeader.m_pluginName, pluginHeader.m_objectName); if (!plugin) { - MCore::LogError("Failed to create plugin window of type '%s', with data size %d bytes", pluginHeader.mPluginName, pluginHeader.mDataSize); + MCore::LogError("Failed to create plugin window of type '%s', with data size %d bytes", pluginHeader.m_pluginName, pluginHeader.m_dataSize); // Skip the data. - file.seek(file.pos() + pluginHeader.mDataSize); + file.seek(file.pos() + pluginHeader.m_dataSize); continue; } } - if (plugin->ReadLayoutSettings(file, pluginHeader.mDataSize, pluginHeader.mDataVersion) == false) + if (plugin->ReadLayoutSettings(file, pluginHeader.m_dataSize, pluginHeader.m_dataVersion) == false) { MCore::LogWarning("Error reading plugin settings from layout file '%s'", filename); - mIsSwitching = false; + m_isSwitching = false; return false; } } @@ -321,7 +308,7 @@ namespace EMStudio if (file.read((char*)&stateLength, sizeof(uint32)) == -1) { MCore::LogWarning("Error reading main window state length from layout file '%s'", filename); - mIsSwitching = false; + m_isSwitching = false; return false; } @@ -330,7 +317,7 @@ namespace EMStudio if (layout.size() == 0) { MCore::LogWarning("Error reading main window state data from layout file '%s'", filename); - mIsSwitching = false; + m_isSwitching = false; return false; } @@ -345,7 +332,7 @@ namespace EMStudio GetPluginManager()->GetActivePlugin(p)->OnAfterLoadLayout(); } - mIsSwitching = false; + m_isSwitching = false; return true; } } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/LayoutManager.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/LayoutManager.h index 5aabbd6024..4059f8f006 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/LayoutManager.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/LayoutManager.h @@ -17,18 +17,18 @@ namespace EMStudio // layout file header struct LayoutHeader { - char mFileTypeCode[9]; // "EMSLAYOUT", otherwise no valid layout file - uint32 mEMFXVersionHigh; // EMotion FX high version as used in EMStudio - uint32 mEMFXVersionLow; // EMotion FX low version as used in EMStudio - char mEMFXCompileDate[64];// EMotion FX compile date - uint32 mLayoutVersionHigh; // layout file type high version - uint32 mLayoutVersionLow; // layout file type low version - char mCompileDate[64]; // EMStudio compile date - char mDescription[256]; // optional description of the layout - uint32 mNumPlugins; // the number of plugins + char m_fileTypeCode[9]; // "EMSLAYOUT", otherwise no valid layout file + uint32 m_emfxVersionHigh; // EMotion FX high version as used in EMStudio + uint32 m_emfxVersionLow; // EMotion FX low version as used in EMStudio + char m_emfxCompileDate[64];// EMotion FX compile date + uint32 m_layoutVersionHigh; // layout file type high version + uint32 m_layoutVersionLow; // layout file type low version + char m_compileDate[64]; // EMStudio compile date + char m_description[256]; // optional description of the layout + uint32 m_numPlugins; // the number of plugins // followed by: - // LayoutPluginHeader[mNumPlugins] + // LayoutPluginHeader[m_numPlugins] // uint32 mainWindowStateSize // int8 mainWindowState[mainWindowStateSize] }; @@ -36,13 +36,13 @@ namespace EMStudio // the plugin data header struct LayoutPluginHeader { - uint32 mDataSize; // data size of the data which the given plugin will store - char mPluginName[128]; // the name of the plugin (its ID to create as passed to PluginManager::CreateWindowOfType) - char mObjectName[128]; - uint32 mDataVersion; // the data version, to for backward compatibility of loading individual plugin settings from layout files + uint32 m_dataSize; // data size of the data which the given plugin will store + char m_pluginName[128]; // the name of the plugin (its ID to create as passed to PluginManager::CreateWindowOfType) + char m_objectName[128]; + uint32 m_dataVersion; // the data version, to for backward compatibility of loading individual plugin settings from layout files // followed by: - // int8 pluginData[mDataSize] + // int8 pluginData[m_dataSize] }; class EMSTUDIO_API LayoutManager @@ -62,7 +62,7 @@ namespace EMStudio InputDialogValidatable* GetSaveLayoutNameDialog(); private: - bool mIsSwitching; + bool m_isSwitching; InputDialogValidatable* m_inputDialog = nullptr; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/LoadActorSettingsWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/LoadActorSettingsWindow.cpp index 090875f20f..179ea26e34 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/LoadActorSettingsWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/LoadActorSettingsWindow.cpp @@ -40,101 +40,101 @@ namespace EMStudio const QSettings loadActorSettings(GetConfigFilename(), QSettings::IniFormat, this); // create the load meshes checkbox - mLoadMeshesCheckbox = new QCheckBox("Load Meshes"); + m_loadMeshesCheckbox = new QCheckBox("Load Meshes"); const bool loadMeshesValue = loadActorSettings.value("LoadMeshes", true).toBool(); - mLoadMeshesCheckbox->setChecked(loadMeshesValue); + m_loadMeshesCheckbox->setChecked(loadMeshesValue); // connect the load meshes checkbox to enable/disable all related to mesh - connect(mLoadMeshesCheckbox, &QCheckBox::clicked, this, &LoadActorSettingsWindow::LoadMeshesClicked); + connect(m_loadMeshesCheckbox, &QCheckBox::clicked, this, &LoadActorSettingsWindow::LoadMeshesClicked); // create the load collision meshes checkbox - mLoadCollisionMeshesCheckbox = new QCheckBox("Load Collision Meshes"); + m_loadCollisionMeshesCheckbox = new QCheckBox("Load Collision Meshes"); const bool loadCollisionMeshesValue = loadActorSettings.value("LoadCollisionMeshes", true).toBool(); - mLoadCollisionMeshesCheckbox->setChecked(loadCollisionMeshesValue); + m_loadCollisionMeshesCheckbox->setChecked(loadCollisionMeshesValue); // create the load standard material layers checkbox - mLoadStandardMaterialLayersCheckbox = new QCheckBox("Load Standard Material Layers"); + m_loadStandardMaterialLayersCheckbox = new QCheckBox("Load Standard Material Layers"); const bool loadStandardMaterialLayersValue = loadActorSettings.value("LoadStandardMaterialLayers", true).toBool(); - mLoadStandardMaterialLayersCheckbox->setChecked(loadStandardMaterialLayersValue); + m_loadStandardMaterialLayersCheckbox->setChecked(loadStandardMaterialLayersValue); // create the load skinning info checkbox - mLoadSkinningInfoCheckbox = new QCheckBox("Load Skinning Info"); + m_loadSkinningInfoCheckbox = new QCheckBox("Load Skinning Info"); const bool loadSkinningInfoValue = loadActorSettings.value("LoadSkinningInfo", true).toBool(); - mLoadSkinningInfoCheckbox->setChecked(loadSkinningInfoValue); + m_loadSkinningInfoCheckbox->setChecked(loadSkinningInfoValue); // connect the load meshes checkbox to enable/disable all related to mesh - connect(mLoadSkinningInfoCheckbox, &QCheckBox::clicked, this, &LoadActorSettingsWindow::LoadSkinningInfoClicked); + connect(m_loadSkinningInfoCheckbox, &QCheckBox::clicked, this, &LoadActorSettingsWindow::LoadSkinningInfoClicked); // create the load limits checkbox - mLoadLimitsCheckbox = new QCheckBox("Load Limits"); + m_loadLimitsCheckbox = new QCheckBox("Load Limits"); const bool loadLimitsValue = loadActorSettings.value("LoadLimits", true).toBool(); - mLoadLimitsCheckbox->setChecked(loadLimitsValue); + m_loadLimitsCheckbox->setChecked(loadLimitsValue); // create the load geometry LODs checkbox - mLoadGeometryLODsCheckbox = new QCheckBox("Load Geometry LODs"); + m_loadGeometryLoDsCheckbox = new QCheckBox("Load Geometry LODs"); const bool loadGeometryLODsValue = loadActorSettings.value("LoadGeometryLODs", true).toBool(); - mLoadGeometryLODsCheckbox->setChecked(loadGeometryLODsValue); + m_loadGeometryLoDsCheckbox->setChecked(loadGeometryLODsValue); // create the load skeletal LODs checkbox - mLoadSkeletalLODsCheckbox = new QCheckBox("Load Skeletal LODs"); + m_loadSkeletalLoDsCheckbox = new QCheckBox("Load Skeletal LODs"); const bool loadSkeletalLODsValue = loadActorSettings.value("LoadSkeletalLODs", true).toBool(); - mLoadSkeletalLODsCheckbox->setChecked(loadSkeletalLODsValue); + m_loadSkeletalLoDsCheckbox->setChecked(loadSkeletalLODsValue); // create the load tangents checkbox - mLoadTangentsCheckbox = new QCheckBox("Load Tangents"); + m_loadTangentsCheckbox = new QCheckBox("Load Tangents"); const bool loadTangentsValue = loadActorSettings.value("LoadTangents", true).toBool(); - mLoadTangentsCheckbox->setChecked(loadTangentsValue); + m_loadTangentsCheckbox->setChecked(loadTangentsValue); // create the auto generate tangents checkbox - mAutoGenerateTangentsCheckbox = new QCheckBox("Auto Generate Tangents"); + m_autoGenerateTangentsCheckbox = new QCheckBox("Auto Generate Tangents"); const bool autoGenerateTangentsValue = loadActorSettings.value("AutoGenerateTangents", true).toBool(); - mAutoGenerateTangentsCheckbox->setChecked(autoGenerateTangentsValue); + m_autoGenerateTangentsCheckbox->setChecked(autoGenerateTangentsValue); // create the load morph targets checkbox - mLoadMorphTargetsCheckbox = new QCheckBox("Load Morph Targets"); + m_loadMorphTargetsCheckbox = new QCheckBox("Load Morph Targets"); const bool loadMorphTargetsValue = loadActorSettings.value("LoadMorphTargets", true).toBool(); - mLoadMorphTargetsCheckbox->setChecked(loadMorphTargetsValue); + m_loadMorphTargetsCheckbox->setChecked(loadMorphTargetsValue); // create the dual quaternion skinning checkbox - mDualQuaternionSkinningCheckbox = new QCheckBox("Dual Quaternion Skinning"); + m_dualQuaternionSkinningCheckbox = new QCheckBox("Dual Quaternion Skinning"); const bool dualQuaternionSkinningValue = loadActorSettings.value("DualQuaternionSkinning", false).toBool(); - mDualQuaternionSkinningCheckbox->setChecked(dualQuaternionSkinningValue); + m_dualQuaternionSkinningCheckbox->setChecked(dualQuaternionSkinningValue); // disable the controls if load meshes is not enabled if (loadMeshesValue == false) { - mLoadStandardMaterialLayersCheckbox->setDisabled(true); - mLoadSkinningInfoCheckbox->setDisabled(true); - mLoadGeometryLODsCheckbox->setDisabled(true); - mLoadTangentsCheckbox->setDisabled(true); - mAutoGenerateTangentsCheckbox->setDisabled(true); - mDualQuaternionSkinningCheckbox->setDisabled(true); + m_loadStandardMaterialLayersCheckbox->setDisabled(true); + m_loadSkinningInfoCheckbox->setDisabled(true); + m_loadGeometryLoDsCheckbox->setDisabled(true); + m_loadTangentsCheckbox->setDisabled(true); + m_autoGenerateTangentsCheckbox->setDisabled(true); + m_dualQuaternionSkinningCheckbox->setDisabled(true); } else { // disable dual quaternion skinning control if the load dual skinning info is not enabled if (loadSkinningInfoValue == false) { - mDualQuaternionSkinningCheckbox->setDisabled(true); + m_dualQuaternionSkinningCheckbox->setDisabled(true); } } // create the left part settings layout QVBoxLayout* leftPartSettingsLayout = new QVBoxLayout(); - leftPartSettingsLayout->addWidget(mLoadMeshesCheckbox); - leftPartSettingsLayout->addWidget(mLoadCollisionMeshesCheckbox); - leftPartSettingsLayout->addWidget(mLoadStandardMaterialLayersCheckbox); - leftPartSettingsLayout->addWidget(mLoadSkinningInfoCheckbox); - leftPartSettingsLayout->addWidget(mLoadLimitsCheckbox); + leftPartSettingsLayout->addWidget(m_loadMeshesCheckbox); + leftPartSettingsLayout->addWidget(m_loadCollisionMeshesCheckbox); + leftPartSettingsLayout->addWidget(m_loadStandardMaterialLayersCheckbox); + leftPartSettingsLayout->addWidget(m_loadSkinningInfoCheckbox); + leftPartSettingsLayout->addWidget(m_loadLimitsCheckbox); // create the right part settings layout QVBoxLayout* rightPartSettingsLayout = new QVBoxLayout(); - rightPartSettingsLayout->addWidget(mLoadGeometryLODsCheckbox); - rightPartSettingsLayout->addWidget(mLoadSkeletalLODsCheckbox); - rightPartSettingsLayout->addWidget(mLoadTangentsCheckbox); - rightPartSettingsLayout->addWidget(mAutoGenerateTangentsCheckbox); - rightPartSettingsLayout->addWidget(mLoadMorphTargetsCheckbox); - rightPartSettingsLayout->addWidget(mDualQuaternionSkinningCheckbox); + rightPartSettingsLayout->addWidget(m_loadGeometryLoDsCheckbox); + rightPartSettingsLayout->addWidget(m_loadSkeletalLoDsCheckbox); + rightPartSettingsLayout->addWidget(m_loadTangentsCheckbox); + rightPartSettingsLayout->addWidget(m_autoGenerateTangentsCheckbox); + rightPartSettingsLayout->addWidget(m_loadMorphTargetsCheckbox); + rightPartSettingsLayout->addWidget(m_dualQuaternionSkinningCheckbox); // create the settings layout QHBoxLayout* settingsLayout = new QHBoxLayout(); @@ -189,17 +189,17 @@ namespace EMStudio LoadActorSettingsWindow::LoadActorSettings LoadActorSettingsWindow::GetLoadActorSettings() const { LoadActorSettings loadActorSettings; - loadActorSettings.mLoadMeshes = mLoadMeshesCheckbox->isChecked(); - loadActorSettings.mLoadCollisionMeshes = mLoadCollisionMeshesCheckbox->isChecked(); - loadActorSettings.mLoadStandardMaterialLayers = mLoadStandardMaterialLayersCheckbox->isChecked(); - loadActorSettings.mLoadSkinningInfo = mLoadSkinningInfoCheckbox->isChecked(); - loadActorSettings.mLoadLimits = mLoadLimitsCheckbox->isChecked(); - loadActorSettings.mLoadGeometryLODs = mLoadGeometryLODsCheckbox->isChecked(); - loadActorSettings.mLoadSkeletalLODs = mLoadSkeletalLODsCheckbox->isChecked(); - loadActorSettings.mLoadTangents = mLoadTangentsCheckbox->isChecked(); - loadActorSettings.mAutoGenerateTangents = mAutoGenerateTangentsCheckbox->isChecked(); - loadActorSettings.mLoadMorphTargets = mLoadMorphTargetsCheckbox->isChecked(); - loadActorSettings.mDualQuaternionSkinning = mDualQuaternionSkinningCheckbox->isChecked(); + loadActorSettings.m_loadMeshes = m_loadMeshesCheckbox->isChecked(); + loadActorSettings.m_loadCollisionMeshes = m_loadCollisionMeshesCheckbox->isChecked(); + loadActorSettings.m_loadStandardMaterialLayers = m_loadStandardMaterialLayersCheckbox->isChecked(); + loadActorSettings.m_loadSkinningInfo = m_loadSkinningInfoCheckbox->isChecked(); + loadActorSettings.m_loadLimits = m_loadLimitsCheckbox->isChecked(); + loadActorSettings.m_loadGeometryLoDs = m_loadGeometryLoDsCheckbox->isChecked(); + loadActorSettings.m_loadSkeletalLoDs = m_loadSkeletalLoDsCheckbox->isChecked(); + loadActorSettings.m_loadTangents = m_loadTangentsCheckbox->isChecked(); + loadActorSettings.m_autoGenerateTangents = m_autoGenerateTangentsCheckbox->isChecked(); + loadActorSettings.m_loadMorphTargets = m_loadMorphTargetsCheckbox->isChecked(); + loadActorSettings.m_dualQuaternionSkinning = m_dualQuaternionSkinningCheckbox->isChecked(); return loadActorSettings; } @@ -210,45 +210,45 @@ namespace EMStudio QSettings loadActorSettings(GetConfigFilename(), QSettings::IniFormat, this); // set all values - loadActorSettings.setValue("LoadMeshes", mLoadMeshesCheckbox->isChecked()); - loadActorSettings.setValue("LoadCollisionMeshes", mLoadCollisionMeshesCheckbox->isChecked()); - loadActorSettings.setValue("LoadStandardMaterialLayers", mLoadStandardMaterialLayersCheckbox->isChecked()); - loadActorSettings.setValue("LoadSkinningInfo", mLoadSkinningInfoCheckbox->isChecked()); - loadActorSettings.setValue("LoadLimits", mLoadLimitsCheckbox->isChecked()); - loadActorSettings.setValue("LoadGeometryLODs", mLoadGeometryLODsCheckbox->isChecked()); - loadActorSettings.setValue("LoadSkeletalLODs", mLoadSkeletalLODsCheckbox->isChecked()); - loadActorSettings.setValue("LoadTangents", mLoadTangentsCheckbox->isChecked()); - loadActorSettings.setValue("AutoGenerateTangents", mAutoGenerateTangentsCheckbox->isChecked()); - loadActorSettings.setValue("LoadMorphTargets", mLoadMorphTargetsCheckbox->isChecked()); - loadActorSettings.setValue("DualQuaternionSkinning", mDualQuaternionSkinningCheckbox->isChecked()); + loadActorSettings.setValue("LoadMeshes", m_loadMeshesCheckbox->isChecked()); + loadActorSettings.setValue("LoadCollisionMeshes", m_loadCollisionMeshesCheckbox->isChecked()); + loadActorSettings.setValue("LoadStandardMaterialLayers", m_loadStandardMaterialLayersCheckbox->isChecked()); + loadActorSettings.setValue("LoadSkinningInfo", m_loadSkinningInfoCheckbox->isChecked()); + loadActorSettings.setValue("LoadLimits", m_loadLimitsCheckbox->isChecked()); + loadActorSettings.setValue("LoadGeometryLODs", m_loadGeometryLoDsCheckbox->isChecked()); + loadActorSettings.setValue("LoadSkeletalLODs", m_loadSkeletalLoDsCheckbox->isChecked()); + loadActorSettings.setValue("LoadTangents", m_loadTangentsCheckbox->isChecked()); + loadActorSettings.setValue("AutoGenerateTangents", m_autoGenerateTangentsCheckbox->isChecked()); + loadActorSettings.setValue("LoadMorphTargets", m_loadMorphTargetsCheckbox->isChecked()); + loadActorSettings.setValue("DualQuaternionSkinning", m_dualQuaternionSkinningCheckbox->isChecked()); } void LoadActorSettingsWindow::LoadMeshesClicked(bool checked) { // enable or disable controls - mLoadStandardMaterialLayersCheckbox->setEnabled(checked); - mLoadSkinningInfoCheckbox->setEnabled(checked); - mLoadGeometryLODsCheckbox->setEnabled(checked); - mLoadTangentsCheckbox->setEnabled(checked); - mAutoGenerateTangentsCheckbox->setEnabled(checked); + m_loadStandardMaterialLayersCheckbox->setEnabled(checked); + m_loadSkinningInfoCheckbox->setEnabled(checked); + m_loadGeometryLoDsCheckbox->setEnabled(checked); + m_loadTangentsCheckbox->setEnabled(checked); + m_autoGenerateTangentsCheckbox->setEnabled(checked); // the dual quaternion skinning control is enabled based on the laod skinning info control // when the the load meshes is not enabled, the control is disabled if (checked) { - mDualQuaternionSkinningCheckbox->setEnabled(mLoadSkinningInfoCheckbox->isChecked()); + m_dualQuaternionSkinningCheckbox->setEnabled(m_loadSkinningInfoCheckbox->isChecked()); } else { - mDualQuaternionSkinningCheckbox->setDisabled(true); + m_dualQuaternionSkinningCheckbox->setDisabled(true); } } void LoadActorSettingsWindow::LoadSkinningInfoClicked(bool checked) { - mDualQuaternionSkinningCheckbox->setEnabled(checked); + m_dualQuaternionSkinningCheckbox->setEnabled(checked); } @@ -261,17 +261,17 @@ namespace EMStudio LoadActorSettingsWindow::LoadActorSettings::LoadActorSettings() : - mLoadMeshes(true), - mLoadCollisionMeshes(true), - mLoadStandardMaterialLayers(true), - mLoadSkinningInfo(true), - mLoadLimits(true), - mLoadGeometryLODs(true), - mLoadSkeletalLODs(true), - mLoadTangents(true), - mAutoGenerateTangents(true), - mLoadMorphTargets(true), - mDualQuaternionSkinning(false) + m_loadMeshes(true), + m_loadCollisionMeshes(true), + m_loadStandardMaterialLayers(true), + m_loadSkinningInfo(true), + m_loadLimits(true), + m_loadGeometryLoDs(true), + m_loadSkeletalLoDs(true), + m_loadTangents(true), + m_autoGenerateTangents(true), + m_loadMorphTargets(true), + m_dualQuaternionSkinning(false) { } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/LoadActorSettingsWindow.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/LoadActorSettingsWindow.h index eb98036750..265469952b 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/LoadActorSettingsWindow.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/LoadActorSettingsWindow.h @@ -26,17 +26,17 @@ namespace EMStudio public: struct LoadActorSettings { - bool mLoadMeshes; - bool mLoadCollisionMeshes; - bool mLoadStandardMaterialLayers; - bool mLoadSkinningInfo; - bool mLoadLimits; - bool mLoadGeometryLODs; - bool mLoadSkeletalLODs; - bool mLoadTangents; - bool mAutoGenerateTangents; - bool mLoadMorphTargets; - bool mDualQuaternionSkinning; + bool m_loadMeshes; + bool m_loadCollisionMeshes; + bool m_loadStandardMaterialLayers; + bool m_loadSkinningInfo; + bool m_loadLimits; + bool m_loadGeometryLoDs; + bool m_loadSkeletalLoDs; + bool m_loadTangents; + bool m_autoGenerateTangents; + bool m_loadMorphTargets; + bool m_dualQuaternionSkinning; LoadActorSettings(); }; @@ -54,16 +54,16 @@ namespace EMStudio private: QString GetConfigFilename() const; - QCheckBox* mLoadMeshesCheckbox; - QCheckBox* mLoadCollisionMeshesCheckbox; - QCheckBox* mLoadStandardMaterialLayersCheckbox; - QCheckBox* mLoadSkinningInfoCheckbox; - QCheckBox* mLoadLimitsCheckbox; - QCheckBox* mLoadGeometryLODsCheckbox; - QCheckBox* mLoadSkeletalLODsCheckbox; - QCheckBox* mLoadTangentsCheckbox; - QCheckBox* mAutoGenerateTangentsCheckbox; - QCheckBox* mLoadMorphTargetsCheckbox; - QCheckBox* mDualQuaternionSkinningCheckbox; + QCheckBox* m_loadMeshesCheckbox; + QCheckBox* m_loadCollisionMeshesCheckbox; + QCheckBox* m_loadStandardMaterialLayersCheckbox; + QCheckBox* m_loadSkinningInfoCheckbox; + QCheckBox* m_loadLimitsCheckbox; + QCheckBox* m_loadGeometryLoDsCheckbox; + QCheckBox* m_loadSkeletalLoDsCheckbox; + QCheckBox* m_loadTangentsCheckbox; + QCheckBox* m_autoGenerateTangentsCheckbox; + QCheckBox* m_loadMorphTargetsCheckbox; + QCheckBox* m_dualQuaternionSkinningCheckbox; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindow.cpp index c5781ebf12..8ca4e1de81 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindow.cpp @@ -99,7 +99,7 @@ namespace EMStudio // add the link to the actual object ObjectPointer objPointer; - objPointer.mWorkspace = workspace; + objPointer.m_workspace = workspace; outObjects->push_back(objPointer); } } @@ -113,12 +113,12 @@ namespace EMStudio { // get the current object pointer and skip directly if the type check fails ObjectPointer objPointer = objects[i]; - if (objPointer.mWorkspace == nullptr) + if (objPointer.m_workspace == nullptr) { continue; } - Workspace* workspace = objPointer.mWorkspace; + Workspace* workspace = objPointer.m_workspace; // has the workspace been saved already or is it a new one? if (workspace->GetFilenameString().empty()) @@ -183,9 +183,9 @@ namespace EMStudio QHBoxLayout* mainLayout = new QHBoxLayout(); mainLayout->setMargin(0); - mTextEdit = new QTextEdit(); - mTextEdit->setTextInteractionFlags(Qt::NoTextInteraction | Qt::TextSelectableByMouse); - mainLayout->addWidget(mTextEdit); + m_textEdit = new QTextEdit(); + m_textEdit->setTextInteractionFlags(Qt::NoTextInteraction | Qt::TextSelectableByMouse); + mainLayout->addWidget(m_textEdit); setMinimumWidth(600); setMinimumHeight(400); @@ -222,7 +222,7 @@ namespace EMStudio text += "

"; } - mTextEdit->setText(text.c_str()); + m_textEdit->setText(text.c_str()); } MainWindow::MainWindow(QWidget* parent, Qt::WindowFlags flags) @@ -232,45 +232,45 @@ namespace EMStudio , m_undoMenuCallback(nullptr) , m_fancyDockingManager(new AzQtComponents::FancyDocking(this, "emotionstudiosdk")) { - mLoadingOptions = false; - mAutosaveTimer = nullptr; - mPreferencesWindow = nullptr; - mApplicationMode = nullptr; - mDirtyFileManager = nullptr; - mFileManager = nullptr; - mShortcutManager = nullptr; - mNativeEventFilter = nullptr; - mImportActorCallback = nullptr; - mRemoveActorCallback = nullptr; - mRemoveActorInstanceCallback = nullptr; - mImportMotionCallback = nullptr; - mRemoveMotionCallback = nullptr; - mCreateMotionSetCallback = nullptr; - mRemoveMotionSetCallback = nullptr; - mLoadMotionSetCallback = nullptr; - mCreateAnimGraphCallback = nullptr; - mRemoveAnimGraphCallback = nullptr; - mLoadAnimGraphCallback = nullptr; - mSelectCallback = nullptr; - mUnselectCallback = nullptr; + m_loadingOptions = false; + m_autosaveTimer = nullptr; + m_preferencesWindow = nullptr; + m_applicationMode = nullptr; + m_dirtyFileManager = nullptr; + m_fileManager = nullptr; + m_shortcutManager = nullptr; + m_nativeEventFilter = nullptr; + m_importActorCallback = nullptr; + m_removeActorCallback = nullptr; + m_removeActorInstanceCallback = nullptr; + m_importMotionCallback = nullptr; + m_removeMotionCallback = nullptr; + m_createMotionSetCallback = nullptr; + m_removeMotionSetCallback = nullptr; + m_loadMotionSetCallback = nullptr; + m_createAnimGraphCallback = nullptr; + m_removeAnimGraphCallback = nullptr; + m_loadAnimGraphCallback = nullptr; + m_selectCallback = nullptr; + m_unselectCallback = nullptr; m_clearSelectionCallback = nullptr; - mSaveWorkspaceCallback = nullptr; + m_saveWorkspaceCallback = nullptr; } // destructor MainWindow::~MainWindow() { - if (mNativeEventFilter) + if (m_nativeEventFilter) { - QAbstractEventDispatcher::instance()->removeNativeEventFilter(mNativeEventFilter); - delete mNativeEventFilter; - mNativeEventFilter = nullptr; + QAbstractEventDispatcher::instance()->removeNativeEventFilter(m_nativeEventFilter); + delete m_nativeEventFilter; + m_nativeEventFilter = nullptr; } - if (mAutosaveTimer) + if (m_autosaveTimer) { - mAutosaveTimer->stop(); + m_autosaveTimer->stop(); } PluginOptionsNotificationsBus::Router::BusRouterDisconnect(); @@ -280,42 +280,42 @@ namespace EMStudio // results in an empty scene Reset(); - delete mShortcutManager; - delete mFileManager; - delete mDirtyFileManager; + delete m_shortcutManager; + delete m_fileManager; + delete m_dirtyFileManager; // unregister the command callbacks and get rid of the memory - GetCommandManager()->RemoveCommandCallback(mImportActorCallback, false); - GetCommandManager()->RemoveCommandCallback(mRemoveActorCallback, false); - GetCommandManager()->RemoveCommandCallback(mRemoveActorInstanceCallback, false); - GetCommandManager()->RemoveCommandCallback(mImportMotionCallback, false); - GetCommandManager()->RemoveCommandCallback(mRemoveMotionCallback, false); - GetCommandManager()->RemoveCommandCallback(mCreateMotionSetCallback, false); - GetCommandManager()->RemoveCommandCallback(mRemoveMotionSetCallback, false); - GetCommandManager()->RemoveCommandCallback(mLoadMotionSetCallback, false); - GetCommandManager()->RemoveCommandCallback(mCreateAnimGraphCallback, false); - GetCommandManager()->RemoveCommandCallback(mRemoveAnimGraphCallback, false); - GetCommandManager()->RemoveCommandCallback(mLoadAnimGraphCallback, false); - GetCommandManager()->RemoveCommandCallback(mSelectCallback, false); - GetCommandManager()->RemoveCommandCallback(mUnselectCallback, false); + GetCommandManager()->RemoveCommandCallback(m_importActorCallback, false); + GetCommandManager()->RemoveCommandCallback(m_removeActorCallback, false); + GetCommandManager()->RemoveCommandCallback(m_removeActorInstanceCallback, false); + GetCommandManager()->RemoveCommandCallback(m_importMotionCallback, false); + GetCommandManager()->RemoveCommandCallback(m_removeMotionCallback, false); + GetCommandManager()->RemoveCommandCallback(m_createMotionSetCallback, false); + GetCommandManager()->RemoveCommandCallback(m_removeMotionSetCallback, false); + GetCommandManager()->RemoveCommandCallback(m_loadMotionSetCallback, false); + GetCommandManager()->RemoveCommandCallback(m_createAnimGraphCallback, false); + GetCommandManager()->RemoveCommandCallback(m_removeAnimGraphCallback, false); + GetCommandManager()->RemoveCommandCallback(m_loadAnimGraphCallback, false); + GetCommandManager()->RemoveCommandCallback(m_selectCallback, false); + GetCommandManager()->RemoveCommandCallback(m_unselectCallback, false); GetCommandManager()->RemoveCommandCallback(m_clearSelectionCallback, false); - GetCommandManager()->RemoveCommandCallback(mSaveWorkspaceCallback, false); + GetCommandManager()->RemoveCommandCallback(m_saveWorkspaceCallback, false); GetCommandManager()->RemoveCallback(&m_mainWindowCommandManagerCallback, false); - delete mImportActorCallback; - delete mRemoveActorCallback; - delete mRemoveActorInstanceCallback; - delete mImportMotionCallback; - delete mRemoveMotionCallback; - delete mCreateMotionSetCallback; - delete mRemoveMotionSetCallback; - delete mLoadMotionSetCallback; - delete mCreateAnimGraphCallback; - delete mRemoveAnimGraphCallback; - delete mLoadAnimGraphCallback; - delete mSelectCallback; - delete mUnselectCallback; + delete m_importActorCallback; + delete m_removeActorCallback; + delete m_removeActorInstanceCallback; + delete m_importMotionCallback; + delete m_removeMotionCallback; + delete m_createMotionSetCallback; + delete m_removeMotionSetCallback; + delete m_loadMotionSetCallback; + delete m_createAnimGraphCallback; + delete m_removeAnimGraphCallback; + delete m_loadAnimGraphCallback; + delete m_selectCallback; + delete m_unselectCallback; delete m_clearSelectionCallback; - delete mSaveWorkspaceCallback; + delete m_saveWorkspaceCallback; EMotionFX::ActorEditorRequestBus::Handler::BusDisconnect(); @@ -363,8 +363,8 @@ namespace EMStudio QMenuBar* menuBar = new QMenuBar(menuWidget); menuLayout->addWidget(menuBar); - mApplicationMode = new QComboBox(); - menuLayout->addWidget(mApplicationMode); + m_applicationMode = new QComboBox(); + menuLayout->addWidget(m_applicationMode); setMenuWidget(menuWidget); @@ -373,26 +373,26 @@ namespace EMStudio menu->setObjectName("EMFX.MainWindow.FileMenu"); // reset action - mResetAction = menu->addAction(tr("&Reset"), this, &MainWindow::OnReset, QKeySequence::New); - mResetAction->setObjectName("EMFX.MainWindow.ResetAction"); + m_resetAction = menu->addAction(tr("&Reset"), this, &MainWindow::OnReset, QKeySequence::New); + m_resetAction->setObjectName("EMFX.MainWindow.ResetAction"); // save all - mSaveAllAction = menu->addAction(tr("Save All..."), this, &MainWindow::OnSaveAll, QKeySequence::Save); - mSaveAllAction->setObjectName("EMFX.MainWindow.SaveAllAction"); + m_saveAllAction = menu->addAction(tr("Save All..."), this, &MainWindow::OnSaveAll, QKeySequence::Save); + m_saveAllAction->setObjectName("EMFX.MainWindow.SaveAllAction"); // disable the reset and save all menus until one thing is loaded - mResetAction->setDisabled(true); - mSaveAllAction->setDisabled(true); + m_resetAction->setDisabled(true); + m_saveAllAction->setDisabled(true); menu->addSeparator(); // actor file actions QAction* openAction = menu->addAction(tr("&Open Actor"), this, &MainWindow::OnFileOpenActor, QKeySequence::Open); openAction->setObjectName("EMFX.MainWindow.OpenActorAction"); - mMergeActorAction = menu->addAction(tr("&Merge Actor"), this, &MainWindow::OnFileMergeActor, Qt::CTRL + Qt::Key_I); - mMergeActorAction->setObjectName("EMFX.MainWindow.MergeActorAction"); - mSaveSelectedActorsAction = menu->addAction(tr("&Save Selected Actors"), this, &MainWindow::OnFileSaveSelectedActors); - mSaveSelectedActorsAction->setObjectName("EMFX.MainWindow.SaveActorAction"); + m_mergeActorAction = menu->addAction(tr("&Merge Actor"), this, &MainWindow::OnFileMergeActor, Qt::CTRL + Qt::Key_I); + m_mergeActorAction->setObjectName("EMFX.MainWindow.MergeActorAction"); + m_saveSelectedActorsAction = menu->addAction(tr("&Save Selected Actors"), this, &MainWindow::OnFileSaveSelectedActors); + m_saveSelectedActorsAction->setObjectName("EMFX.MainWindow.SaveActorAction"); // disable the merge actor menu until one actor is in the scene DisableMergeActorMenu(); @@ -401,8 +401,8 @@ namespace EMStudio DisableSaveSelectedActorsMenu(); // recent actors submenu - mRecentActors.Init(menu, mOptions.GetMaxRecentFiles(), "Recent Actors", "recentActorFiles"); - connect(&mRecentActors, &MysticQt::RecentFiles::OnRecentFile, this, &MainWindow::OnRecentFile); + m_recentActors.Init(menu, m_options.GetMaxRecentFiles(), "Recent Actors", "recentActorFiles"); + connect(&m_recentActors, &MysticQt::RecentFiles::OnRecentFile, this, &MainWindow::OnRecentFile); // workspace file actions menu->addSeparator(); @@ -416,8 +416,8 @@ namespace EMStudio saveWorkspaceAsAction->setObjectName("EMFX.MainWindow.SaveWorkspaceAsAction"); // recent workspace submenu - mRecentWorkspaces.Init(menu, mOptions.GetMaxRecentFiles(), "Recent Workspaces", "recentWorkspaces"); - connect(&mRecentWorkspaces, &MysticQt::RecentFiles::OnRecentFile, this, &MainWindow::OnRecentFile); + m_recentWorkspaces.Init(menu, m_options.GetMaxRecentFiles(), "Recent Workspaces", "recentWorkspaces"); + connect(&m_recentWorkspaces, &MysticQt::RecentFiles::OnRecentFile, this, &MainWindow::OnRecentFile); // edit menu menu = menuBar->addMenu(tr("&Edit")); @@ -443,19 +443,19 @@ namespace EMStudio preferencesAction->setObjectName("EMFX.MainWindow.PrefsAction"); // layouts item - mLayoutsMenu = menuBar->addMenu(tr("&Layouts")); - mLayoutsMenu->setObjectName("LayoutsMenu"); + m_layoutsMenu = menuBar->addMenu(tr("&Layouts")); + m_layoutsMenu->setObjectName("LayoutsMenu"); UpdateLayoutsMenu(); // reset the application mode selection and connect it - mApplicationMode->setCurrentIndex(-1); - connect(mApplicationMode, qOverload(&QComboBox::currentIndexChanged), this, qOverload(&MainWindow::ApplicationModeChanged)); - mLayoutLoaded = false; + m_applicationMode->setCurrentIndex(-1); + connect(m_applicationMode, qOverload(&QComboBox::currentIndexChanged), this, qOverload(&MainWindow::ApplicationModeChanged)); + m_layoutLoaded = false; // view item menu = menuBar->addMenu(tr("&View")); - mCreateWindowMenu = menu; - mCreateWindowMenu->setObjectName("ViewMenu"); + m_createWindowMenu = menu; + m_createWindowMenu->setObjectName("ViewMenu"); // help menu menu = menuBar->addMenu(tr("&Help")); @@ -483,27 +483,27 @@ namespace EMStudio SetWindowTitleFromFileName(""); // create the autosave timer - mAutosaveTimer = new QTimer(this); - connect(mAutosaveTimer, &QTimer::timeout, this, &MainWindow::OnAutosaveTimeOut); + m_autosaveTimer = new QTimer(this); + connect(m_autosaveTimer, &QTimer::timeout, this, &MainWindow::OnAutosaveTimeOut); // load preferences PluginOptionsNotificationsBus::Router::BusRouterConnect(); LoadPreferences(); - mAutosaveTimer->setInterval(mOptions.GetAutoSaveInterval() * 60 * 1000); + m_autosaveTimer->setInterval(m_options.GetAutoSaveInterval() * 60 * 1000); // Create the dirty file manager and register the workspace callback. - mDirtyFileManager = new DirtyFileManager; - mDirtyFileManager->AddCallback(new SaveDirtyWorkspaceCallback); + m_dirtyFileManager = new DirtyFileManager; + m_dirtyFileManager->AddCallback(new SaveDirtyWorkspaceCallback); // init the file manager - mFileManager = new EMStudio::FileManager(this); + m_fileManager = new EMStudio::FileManager(this); //////////////////////////////////////////////////////////////////////// // Keyboard Shortcut Manager //////////////////////////////////////////////////////////////////////// // create the shortcut manager - mShortcutManager = new MysticQt::KeyboardShortcutManager(); + m_shortcutManager = new MysticQt::KeyboardShortcutManager(); // load the old shortcuts LoadKeyboardShortcuts(); @@ -514,24 +514,24 @@ namespace EMStudio "AnimGraph", this); animGraphLayoutAction->setShortcut(Qt::Key_1 | Qt::AltModifier); - mShortcutManager->RegisterKeyboardShortcut(animGraphLayoutAction, layoutGroupName, false); - connect(animGraphLayoutAction, &QAction::triggered, [this]{ mApplicationMode->setCurrentIndex(0); }); + m_shortcutManager->RegisterKeyboardShortcut(animGraphLayoutAction, layoutGroupName, false); + connect(animGraphLayoutAction, &QAction::triggered, [this]{ m_applicationMode->setCurrentIndex(0); }); addAction(animGraphLayoutAction); QAction* animationLayoutAction = new QAction( "Animation", this); animationLayoutAction->setShortcut(Qt::Key_2 | Qt::AltModifier); - mShortcutManager->RegisterKeyboardShortcut(animationLayoutAction, layoutGroupName, false); - connect(animationLayoutAction, &QAction::triggered, [this]{ mApplicationMode->setCurrentIndex(1); }); + m_shortcutManager->RegisterKeyboardShortcut(animationLayoutAction, layoutGroupName, false); + connect(animationLayoutAction, &QAction::triggered, [this]{ m_applicationMode->setCurrentIndex(1); }); addAction(animationLayoutAction); QAction* characterLayoutAction = new QAction( "Character", this); characterLayoutAction->setShortcut(Qt::Key_1 | Qt::AltModifier); - mShortcutManager->RegisterKeyboardShortcut(characterLayoutAction, layoutGroupName, false); - connect(characterLayoutAction, &QAction::triggered, [this]{ mApplicationMode->setCurrentIndex(2); }); + m_shortcutManager->RegisterKeyboardShortcut(characterLayoutAction, layoutGroupName, false); + connect(characterLayoutAction, &QAction::triggered, [this]{ m_applicationMode->setCurrentIndex(2); }); addAction(characterLayoutAction); EMotionFX::ActorEditorRequestBus::Handler::BusConnect(); @@ -541,42 +541,42 @@ namespace EMStudio EMotionFX::ActorEditorRequestBus::Handler::BusConnect(); // create and register the command callbacks - mImportActorCallback = new CommandImportActorCallback(false); - mRemoveActorCallback = new CommandRemoveActorCallback(false); - mRemoveActorInstanceCallback = new CommandRemoveActorInstanceCallback(false); - mImportMotionCallback = new CommandImportMotionCallback(false); - mRemoveMotionCallback = new CommandRemoveMotionCallback(false); - mCreateMotionSetCallback = new CommandCreateMotionSetCallback(false); - mRemoveMotionSetCallback = new CommandRemoveMotionSetCallback(false); - mLoadMotionSetCallback = new CommandLoadMotionSetCallback(false); - mCreateAnimGraphCallback = new CommandCreateAnimGraphCallback(false); - mRemoveAnimGraphCallback = new CommandRemoveAnimGraphCallback(false); - mLoadAnimGraphCallback = new CommandLoadAnimGraphCallback(false); - mSelectCallback = new CommandSelectCallback(false); - mUnselectCallback = new CommandUnselectCallback(false); + m_importActorCallback = new CommandImportActorCallback(false); + m_removeActorCallback = new CommandRemoveActorCallback(false); + m_removeActorInstanceCallback = new CommandRemoveActorInstanceCallback(false); + m_importMotionCallback = new CommandImportMotionCallback(false); + m_removeMotionCallback = new CommandRemoveMotionCallback(false); + m_createMotionSetCallback = new CommandCreateMotionSetCallback(false); + m_removeMotionSetCallback = new CommandRemoveMotionSetCallback(false); + m_loadMotionSetCallback = new CommandLoadMotionSetCallback(false); + m_createAnimGraphCallback = new CommandCreateAnimGraphCallback(false); + m_removeAnimGraphCallback = new CommandRemoveAnimGraphCallback(false); + m_loadAnimGraphCallback = new CommandLoadAnimGraphCallback(false); + m_selectCallback = new CommandSelectCallback(false); + m_unselectCallback = new CommandUnselectCallback(false); m_clearSelectionCallback = new CommandClearSelectionCallback(false); - mSaveWorkspaceCallback = new CommandSaveWorkspaceCallback(false); - GetCommandManager()->RegisterCommandCallback("ImportActor", mImportActorCallback); - GetCommandManager()->RegisterCommandCallback("RemoveActor", mRemoveActorCallback); - GetCommandManager()->RegisterCommandCallback("RemoveActorInstance", mRemoveActorInstanceCallback); - GetCommandManager()->RegisterCommandCallback("ImportMotion", mImportMotionCallback); - GetCommandManager()->RegisterCommandCallback("RemoveMotion", mRemoveMotionCallback); - GetCommandManager()->RegisterCommandCallback("CreateMotionSet", mCreateMotionSetCallback); - GetCommandManager()->RegisterCommandCallback("RemoveMotionSet", mRemoveMotionSetCallback); - GetCommandManager()->RegisterCommandCallback("LoadMotionSet", mLoadMotionSetCallback); - GetCommandManager()->RegisterCommandCallback("CreateAnimGraph", mCreateAnimGraphCallback); - GetCommandManager()->RegisterCommandCallback("RemoveAnimGraph", mRemoveAnimGraphCallback); - GetCommandManager()->RegisterCommandCallback("LoadAnimGraph", mLoadAnimGraphCallback); - GetCommandManager()->RegisterCommandCallback("Select", mSelectCallback); - GetCommandManager()->RegisterCommandCallback("Unselect", mUnselectCallback); + m_saveWorkspaceCallback = new CommandSaveWorkspaceCallback(false); + GetCommandManager()->RegisterCommandCallback("ImportActor", m_importActorCallback); + GetCommandManager()->RegisterCommandCallback("RemoveActor", m_removeActorCallback); + GetCommandManager()->RegisterCommandCallback("RemoveActorInstance", m_removeActorInstanceCallback); + GetCommandManager()->RegisterCommandCallback("ImportMotion", m_importMotionCallback); + GetCommandManager()->RegisterCommandCallback("RemoveMotion", m_removeMotionCallback); + GetCommandManager()->RegisterCommandCallback("CreateMotionSet", m_createMotionSetCallback); + GetCommandManager()->RegisterCommandCallback("RemoveMotionSet", m_removeMotionSetCallback); + GetCommandManager()->RegisterCommandCallback("LoadMotionSet", m_loadMotionSetCallback); + GetCommandManager()->RegisterCommandCallback("CreateAnimGraph", m_createAnimGraphCallback); + GetCommandManager()->RegisterCommandCallback("RemoveAnimGraph", m_removeAnimGraphCallback); + GetCommandManager()->RegisterCommandCallback("LoadAnimGraph", m_loadAnimGraphCallback); + GetCommandManager()->RegisterCommandCallback("Select", m_selectCallback); + GetCommandManager()->RegisterCommandCallback("Unselect", m_unselectCallback); GetCommandManager()->RegisterCommandCallback("ClearSelection", m_clearSelectionCallback); - GetCommandManager()->RegisterCommandCallback("SaveWorkspace", mSaveWorkspaceCallback); + GetCommandManager()->RegisterCommandCallback("SaveWorkspace", m_saveWorkspaceCallback); GetCommandManager()->RegisterCallback(&m_mainWindowCommandManagerCallback); - AZ_Assert(!mNativeEventFilter, "Double initialization?"); - mNativeEventFilter = new NativeEventFilter(this); - QAbstractEventDispatcher::instance()->installNativeEventFilter(mNativeEventFilter); + AZ_Assert(!m_nativeEventFilter, "Double initialization?"); + m_nativeEventFilter = new NativeEventFilter(this); + QAbstractEventDispatcher::instance()->installNativeEventFilter(m_nativeEventFilter); } MainWindow::MainWindowCommandManagerCallback::MainWindowCommandManagerCallback() @@ -965,7 +965,7 @@ namespace EMStudio void MainWindow::OnWorkspaceSaved(const char* filename) { - mRecentWorkspaces.AddRecentFile(filename); + m_recentWorkspaces.AddRecentFile(filename); SetWindowTitleFromFileName(filename); } @@ -975,50 +975,50 @@ namespace EMStudio // enable the menus if at least one actor if (EMotionFX::GetActorManager().GetNumActors() > 0) { - mResetAction->setEnabled(true); - mSaveAllAction->setEnabled(true); + m_resetAction->setEnabled(true); + m_saveAllAction->setEnabled(true); return; } // enable the menus if at least one motion if (EMotionFX::GetMotionManager().GetNumMotions() > 0) { - mResetAction->setEnabled(true); - mSaveAllAction->setEnabled(true); + m_resetAction->setEnabled(true); + m_saveAllAction->setEnabled(true); return; } // enable the menus if at least one motion set if (EMotionFX::GetMotionManager().GetNumMotionSets() > 0) { - mResetAction->setEnabled(true); - mSaveAllAction->setEnabled(true); + m_resetAction->setEnabled(true); + m_saveAllAction->setEnabled(true); return; } // enable the menus if at least one anim graph if (EMotionFX::GetAnimGraphManager().GetNumAnimGraphs() > 0) { - mResetAction->setEnabled(true); - mSaveAllAction->setEnabled(true); + m_resetAction->setEnabled(true); + m_saveAllAction->setEnabled(true); return; } // nothing loaded, disable the menus - mResetAction->setDisabled(true); - mSaveAllAction->setDisabled(true); + m_resetAction->setDisabled(true); + m_saveAllAction->setDisabled(true); } void MainWindow::EnableMergeActorMenu() { - mMergeActorAction->setEnabled(true); + m_mergeActorAction->setEnabled(true); } void MainWindow::DisableMergeActorMenu() { - mMergeActorAction->setDisabled(true); + m_mergeActorAction->setDisabled(true); } @@ -1052,13 +1052,13 @@ namespace EMStudio void MainWindow::EnableSaveSelectedActorsMenu() { - mSaveSelectedActorsAction->setEnabled(true); + m_saveSelectedActorsAction->setEnabled(true); } void MainWindow::DisableSaveSelectedActorsMenu() { - mSaveSelectedActorsAction->setDisabled(true); + m_saveSelectedActorsAction->setDisabled(true); } @@ -1100,7 +1100,7 @@ namespace EMStudio AZStd::sort(begin(sortedPlugins), end(sortedPlugins)); // clear the window menu - mCreateWindowMenu->clear(); + m_createWindowMenu->clear(); // for all registered plugins, create a menu items for (size_t p = 0; p < numPlugins; ++p) @@ -1120,14 +1120,14 @@ namespace EMStudio if (plugin->AllowMultipleInstances()) { // create the menu - mCreateWindowMenu->addMenu(plugin->GetName()); + m_createWindowMenu->addMenu(plugin->GetName()); // TODO: add each instance inside the submenu } else { // create the action - QAction* action = mCreateWindowMenu->addAction(plugin->GetName()); + QAction* action = m_createWindowMenu->addAction(plugin->GetName()); action->setData(plugin->GetName()); // connect the action to activate the plugin when clicked on it @@ -1144,7 +1144,7 @@ namespace EMStudio if (activePlugin) { // must use the active plugin, as it needs to be initialized to create window entries - activePlugin->AddWindowMenuEntries(mCreateWindowMenu); + activePlugin->AddWindowMenuEntries(m_createWindowMenu); } } } @@ -1210,16 +1210,16 @@ namespace EMStudio // show the preferences dialog void MainWindow::OnPreferences() { - if (mPreferencesWindow == nullptr) + if (m_preferencesWindow == nullptr) { - mPreferencesWindow = new PreferencesWindow(this); - mPreferencesWindow->Init(); + m_preferencesWindow = new PreferencesWindow(this); + m_preferencesWindow->Init(); - AzToolsFramework::ReflectedPropertyEditor* generalPropertyWidget = mPreferencesWindow->AddCategory("General"); + AzToolsFramework::ReflectedPropertyEditor* generalPropertyWidget = m_preferencesWindow->AddCategory("General"); generalPropertyWidget->ClearInstances(); generalPropertyWidget->InvalidateAll(); - generalPropertyWidget->AddInstance(&mOptions, azrtti_typeid(mOptions)); + generalPropertyWidget->AddInstance(&m_options, azrtti_typeid(m_options)); PluginManager* pluginManager = GetPluginManager(); const size_t numPlugins = pluginManager->GetNumActivePlugins(); @@ -1247,11 +1247,11 @@ namespace EMStudio generalPropertyWidget->InvalidateAll(); // Keyboard shortcuts - KeyboardShortcutsWindow* shortcutsWindow = new KeyboardShortcutsWindow(mPreferencesWindow); - mPreferencesWindow->AddCategory(shortcutsWindow, "Keyboard shortcuts"); + KeyboardShortcutsWindow* shortcutsWindow = new KeyboardShortcutsWindow(m_preferencesWindow); + m_preferencesWindow->AddCategory(shortcutsWindow, "Keyboard shortcuts"); } - mPreferencesWindow->exec(); + m_preferencesWindow->exec(); SavePreferences(); } @@ -1261,7 +1261,7 @@ namespace EMStudio { // open the config file QSettings settings(this); - mOptions.Save(settings, *this); + m_options.Save(settings, *this); } @@ -1270,24 +1270,24 @@ namespace EMStudio { // When a setting changes, OnOptionChanged will save. To avoid saving while settings are being // loaded, we use this flag - mLoadingOptions = true; + m_loadingOptions = true; // open the config file QSettings settings(this); - mOptions = GUIOptions::Load(settings, *this); + m_options = GUIOptions::Load(settings, *this); - mLoadingOptions = false; + m_loadingOptions = false; } void MainWindow::AddRecentActorFile(const QString& fileName) { - mRecentActors.AddRecentFile(fileName.toUtf8().data()); + m_recentActors.AddRecentFile(fileName.toUtf8().data()); } void MainWindow::LoadKeyboardShortcuts() { QSettings shortcutSettings(AZStd::string(GetManager()->GetAppDataFolder() + "EMStudioKeyboardShortcuts.cfg").c_str(), QSettings::IniFormat, this); - mShortcutManager->Load(&shortcutSettings); + m_shortcutManager->Load(&shortcutSettings); } void MainWindow::LoadActor(const char* fileName, bool replaceCurrentScene) @@ -1321,17 +1321,17 @@ namespace EMStudio // add the load actor settings LoadActorSettingsWindow::LoadActorSettings loadActorSettings; - loadActorCommand += "-loadMeshes " + AZStd::to_string(loadActorSettings.mLoadMeshes); - loadActorCommand += " -loadTangents " + AZStd::to_string(loadActorSettings.mLoadTangents); - loadActorCommand += " -autoGenTangents " + AZStd::to_string(loadActorSettings.mAutoGenerateTangents); - loadActorCommand += " -loadLimits " + AZStd::to_string(loadActorSettings.mLoadLimits); - loadActorCommand += " -loadGeomLods " + AZStd::to_string(loadActorSettings.mLoadGeometryLODs); - loadActorCommand += " -loadMorphTargets " + AZStd::to_string(loadActorSettings.mLoadMorphTargets); - loadActorCommand += " -loadCollisionMeshes " + AZStd::to_string(loadActorSettings.mLoadCollisionMeshes); - loadActorCommand += " -loadMaterialLayers " + AZStd::to_string(loadActorSettings.mLoadStandardMaterialLayers); - loadActorCommand += " -loadSkinningInfo " + AZStd::to_string(loadActorSettings.mLoadSkinningInfo); - loadActorCommand += " -loadSkeletalLODs " + AZStd::to_string(loadActorSettings.mLoadSkeletalLODs); - loadActorCommand += " -dualQuatSkinning " + AZStd::to_string(loadActorSettings.mDualQuaternionSkinning); + loadActorCommand += "-loadMeshes " + AZStd::to_string(loadActorSettings.m_loadMeshes); + loadActorCommand += " -loadTangents " + AZStd::to_string(loadActorSettings.m_loadTangents); + loadActorCommand += " -autoGenTangents " + AZStd::to_string(loadActorSettings.m_autoGenerateTangents); + loadActorCommand += " -loadLimits " + AZStd::to_string(loadActorSettings.m_loadLimits); + loadActorCommand += " -loadGeomLods " + AZStd::to_string(loadActorSettings.m_loadGeometryLoDs); + loadActorCommand += " -loadMorphTargets " + AZStd::to_string(loadActorSettings.m_loadMorphTargets); + loadActorCommand += " -loadCollisionMeshes " + AZStd::to_string(loadActorSettings.m_loadCollisionMeshes); + loadActorCommand += " -loadMaterialLayers " + AZStd::to_string(loadActorSettings.m_loadStandardMaterialLayers); + loadActorCommand += " -loadSkinningInfo " + AZStd::to_string(loadActorSettings.m_loadSkinningInfo); + loadActorCommand += " -loadSkeletalLODs " + AZStd::to_string(loadActorSettings.m_loadSkeletalLoDs); + loadActorCommand += " -dualQuatSkinning " + AZStd::to_string(loadActorSettings.m_dualQuaternionSkinning); // add the load and the create instance commands commandGroup.AddCommandString(loadActorCommand.c_str()); @@ -1346,14 +1346,14 @@ namespace EMStudio // add the actor in the recent actor list // if the same actor is already in the list, the duplicate is removed - mRecentActors.AddRecentFile(fileName); + m_recentActors.AddRecentFile(fileName); } void MainWindow::LoadCharacter(const AZ::Data::AssetId& actorAssetId, const AZ::Data::AssetId& animgraphId, const AZ::Data::AssetId& motionSetId) { - mCharacterFiles.clear(); + m_characterFiles.clear(); AZStd::string cachePath = gEnv->pFileIO->GetAlias("@assets@"); AZStd::string filename; AzFramework::StringFunc::AssetDatabasePath::Normalize(cachePath); @@ -1396,10 +1396,10 @@ namespace EMStudio AZStd::vector objects; AZStd::vector dirtyObjects; - const size_t numDirtyFilesCallbacks = mDirtyFileManager->GetNumCallbacks(); + const size_t numDirtyFilesCallbacks = m_dirtyFileManager->GetNumCallbacks(); for (size_t i = 0; i < numDirtyFilesCallbacks; ++i) { - SaveDirtyFilesCallback* callback = mDirtyFileManager->GetCallback(i); + SaveDirtyFilesCallback* callback = m_dirtyFileManager->GetCallback(i); callback->GetDirtyFileNames(&filenames, &objects); const size_t numFileNames = filenames.size(); for (size_t j = 0; j < numFileNames; ++j) @@ -1429,18 +1429,18 @@ namespace EMStudio // Dont reload dirty files that are already open. if (!foundActor) { - mCharacterFiles.push_back(actorFilename); + m_characterFiles.push_back(actorFilename); } if (!foundAnimgraph) { - mCharacterFiles.push_back(animgraphFilename); + m_characterFiles.push_back(animgraphFilename); } if (!foundMotionSet) { - mCharacterFiles.push_back(motionSetFilename); + m_characterFiles.push_back(motionSetFilename); } - if (isVisible() && mLayoutLoaded) + if (isVisible() && m_layoutLoaded) { LoadCharacterFiles(); } @@ -1449,7 +1449,7 @@ namespace EMStudio void MainWindow::OnFileNewWorkspace() { // save all files that have been changed - if (mDirtyFileManager->SaveDirtyFiles() == DirtyFileManager::CANCELED) + if (m_dirtyFileManager->SaveDirtyFiles() == DirtyFileManager::CANCELED) { return; } @@ -1491,7 +1491,7 @@ namespace EMStudio void MainWindow::OnFileOpenWorkspace() { - const AZStd::string filename = mFileManager->LoadWorkspaceFileDialog(this); + const AZStd::string filename = m_fileManager->LoadWorkspaceFileDialog(this); if (filename.empty()) { return; @@ -1503,14 +1503,14 @@ namespace EMStudio void MainWindow::OnSaveAll() { - mDirtyFileManager->SaveDirtyFiles(MCORE_INVALIDINDEX32, MCORE_INVALIDINDEX32, QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + m_dirtyFileManager->SaveDirtyFiles(MCORE_INVALIDINDEX32, MCORE_INVALIDINDEX32, QDialogButtonBox::Ok | QDialogButtonBox::Cancel); } void MainWindow::OnFileSaveWorkspace() { // save all files that have been changed, filter to not show the workspace files - if (mDirtyFileManager->SaveDirtyFiles(MCORE_INVALIDINDEX32, SaveDirtyWorkspaceCallback::TYPE_ID) == DirtyFileManager::CANCELED) + if (m_dirtyFileManager->SaveDirtyFiles(MCORE_INVALIDINDEX32, SaveDirtyWorkspaceCallback::TYPE_ID) == DirtyFileManager::CANCELED) { return; } @@ -1552,7 +1552,7 @@ namespace EMStudio void MainWindow::OnFileSaveWorkspaceAs() { // save all files that have been changed, filter to not show the workspace files - if (mDirtyFileManager->SaveDirtyFiles(MCORE_INVALIDINDEX32, SaveDirtyWorkspaceCallback::TYPE_ID) == DirtyFileManager::CANCELED) + if (m_dirtyFileManager->SaveDirtyFiles(MCORE_INVALIDINDEX32, SaveDirtyWorkspaceCallback::TYPE_ID) == DirtyFileManager::CANCELED) { return; } @@ -1643,7 +1643,7 @@ namespace EMStudio void MainWindow::OnReset() { - if (mDirtyFileManager->SaveDirtyFiles() == DirtyFileManager::CANCELED) + if (m_dirtyFileManager->SaveDirtyFiles() == DirtyFileManager::CANCELED) { return; } @@ -1673,52 +1673,52 @@ namespace EMStudio if (optionChanged == GUIOptions::s_maxRecentFilesOptionName) { // Set the maximum number of recent files - mRecentActors.SetMaxRecentFiles(mOptions.GetMaxRecentFiles()); - mRecentWorkspaces.SetMaxRecentFiles(mOptions.GetMaxRecentFiles()); + m_recentActors.SetMaxRecentFiles(m_options.GetMaxRecentFiles()); + m_recentWorkspaces.SetMaxRecentFiles(m_options.GetMaxRecentFiles()); } else if (optionChanged == GUIOptions::s_maxHistoryItemsOptionName) { // Set the maximum number of history items in the command manager - GetCommandManager()->SetMaxHistoryItems(mOptions.GetMaxHistoryItems()); + GetCommandManager()->SetMaxHistoryItems(m_options.GetMaxHistoryItems()); } else if (optionChanged == GUIOptions::s_notificationVisibleTimeOptionName) { // Set the notification visible time - GetNotificationWindowManager()->SetVisibleTime(mOptions.GetNotificationInvisibleTime()); + GetNotificationWindowManager()->SetVisibleTime(m_options.GetNotificationInvisibleTime()); } else if (optionChanged == GUIOptions::s_enableAutosaveOptionName) { // Enable or disable the autosave timer - if (mOptions.GetEnableAutoSave()) + if (m_options.GetEnableAutoSave()) { - mAutosaveTimer->setInterval(mOptions.GetAutoSaveInterval() * 60 * 1000); - mAutosaveTimer->start(); + m_autosaveTimer->setInterval(m_options.GetAutoSaveInterval() * 60 * 1000); + m_autosaveTimer->start(); } else { - mAutosaveTimer->stop(); + m_autosaveTimer->stop(); } } else if (optionChanged == GUIOptions::s_autosaveIntervalOptionName) { // Set the autosave interval - mAutosaveTimer->stop(); - mAutosaveTimer->setInterval(mOptions.GetAutoSaveInterval() * 60 * 1000); - mAutosaveTimer->start(); + m_autosaveTimer->stop(); + m_autosaveTimer->setInterval(m_options.GetAutoSaveInterval() * 60 * 1000); + m_autosaveTimer->start(); } else if (optionChanged == GUIOptions::s_importerLogDetailsEnabledOptionName) { // Set if the detail logging of the importer is enabled or not - EMotionFX::GetImporter().SetLogDetails(mOptions.GetImporterLogDetailsEnabled()); + EMotionFX::GetImporter().SetLogDetails(m_options.GetImporterLogDetailsEnabled()); } else if (optionChanged == GUIOptions::s_autoLoadLastWorkspaceOptionName) { // Set if auto loading the last workspace is enabled or not - GetManager()->SetAutoLoadLastWorkspace(mOptions.GetAutoLoadLastWorkspace()); + GetManager()->SetAutoLoadLastWorkspace(m_options.GetAutoLoadLastWorkspace()); } // Save preferences - if (!mLoadingOptions) + if (!m_loadingOptions) { SavePreferences(); } @@ -1727,12 +1727,12 @@ namespace EMStudio // open an actor void MainWindow::OnFileOpenActor() { - if (mDirtyFileManager->SaveDirtyFiles({azrtti_typeid()}) == DirtyFileManager::CANCELED) + if (m_dirtyFileManager->SaveDirtyFiles({azrtti_typeid()}) == DirtyFileManager::CANCELED) { return; } - AZStd::vector filenames = mFileManager->LoadActorsFileDialog(this); + AZStd::vector filenames = m_fileManager->LoadActorsFileDialog(this); activateWindow(); if (filenames.empty()) { @@ -1750,7 +1750,7 @@ namespace EMStudio // merge an actor void MainWindow::OnFileMergeActor() { - AZStd::vector filenames = mFileManager->LoadActorsFileDialog(this); + AZStd::vector filenames = m_fileManager->LoadActorsFileDialog(this); activateWindow(); if (filenames.empty()) { @@ -1829,7 +1829,7 @@ namespace EMStudio void MainWindow::UpdateLayoutsMenu() { // clear the current menu - mLayoutsMenu->clear(); + m_layoutsMenu->clear(); // generate the layouts path QDir layoutsPath = QDir{ QString(MysticQt::GetDataDir().c_str()) }.filePath("Layouts"); @@ -1840,7 +1840,7 @@ namespace EMStudio dir.setSorting(QDir::Name); // add each layout - mLayoutNames.clear(); + m_layoutNames.clear(); AZStd::string filename; const QFileInfoList list = dir.entryInfoList(); const int listSize = list.size(); @@ -1857,36 +1857,36 @@ namespace EMStudio if (extension == "layout") { AzFramework::StringFunc::Path::GetFileName(filename.c_str(), filename); - mLayoutNames.emplace_back(filename); + m_layoutNames.emplace_back(filename); } } // add each menu - for (const AZStd::string& layoutName : mLayoutNames) + for (const AZStd::string& layoutName : m_layoutNames) { - QAction* action = mLayoutsMenu->addAction(layoutName.c_str()); + QAction* action = m_layoutsMenu->addAction(layoutName.c_str()); connect(action, &QAction::triggered, this, &MainWindow::OnLoadLayout); } // add the separator only if at least one layout - if (!mLayoutNames.empty()) + if (!m_layoutNames.empty()) { - mLayoutsMenu->addSeparator(); + m_layoutsMenu->addSeparator(); } // add the save current menu - QAction* saveCurrentAction = mLayoutsMenu->addAction("Save Current"); + QAction* saveCurrentAction = m_layoutsMenu->addAction("Save Current"); connect(saveCurrentAction, &QAction::triggered, this, &MainWindow::OnLayoutSaveAs); // remove menu is needed only if at least one layout - if (!mLayoutNames.empty()) + if (!m_layoutNames.empty()) { // add the remove menu - QMenu* removeMenu = mLayoutsMenu->addMenu("Remove"); + QMenu* removeMenu = m_layoutsMenu->addMenu("Remove"); removeMenu->setObjectName("RemoveMenu"); // add each layout in the remove menu - for (const AZStd::string& layoutName : mLayoutNames) + for (const AZStd::string& layoutName : m_layoutNames) { // User cannot remove the default layout. This layout is referenced in the qrc file, removing it will // cause compiling issue too. @@ -1900,26 +1900,26 @@ namespace EMStudio } // disable signals to avoid to switch of layout - mApplicationMode->blockSignals(true); + m_applicationMode->blockSignals(true); // update the combo box - mApplicationMode->clear(); - for (const AZStd::string& layoutName : mLayoutNames) + m_applicationMode->clear(); + for (const AZStd::string& layoutName : m_layoutNames) { - mApplicationMode->addItem(layoutName.c_str()); + m_applicationMode->addItem(layoutName.c_str()); } // update the current selection of combo box - const int layoutIndex = mApplicationMode->findText(QString(mOptions.GetApplicationMode().c_str())); - mApplicationMode->setCurrentIndex(layoutIndex); + const int layoutIndex = m_applicationMode->findText(QString(m_options.GetApplicationMode().c_str())); + m_applicationMode->setCurrentIndex(layoutIndex); // enable signals - mApplicationMode->blockSignals(false); + m_applicationMode->blockSignals(false); } void MainWindow::ApplicationModeChanged(int index) { - QString text = mApplicationMode->itemText(index); + QString text = m_applicationMode->itemText(index); ApplicationModeChanged(text); } @@ -1935,7 +1935,7 @@ namespace EMStudio } // update the last used layout and save it in the preferences file - mOptions.SetApplicationMode(text.toUtf8().data()); + m_options.SetApplicationMode(text.toUtf8().data()); SavePreferences(); // generate the filename @@ -1972,16 +1972,16 @@ namespace EMStudio } // check if the layout removed is the current used - if (QString(mOptions.GetApplicationMode().c_str()) == m_removeLayoutNameText) + if (QString(m_options.GetApplicationMode().c_str()) == m_removeLayoutNameText) { // find the layout index on the application mode combo box - const int layoutIndex = mApplicationMode->findText(m_removeLayoutNameText); + const int layoutIndex = m_applicationMode->findText(m_removeLayoutNameText); // set the new layout index, take the previous if the last layout is removed, the next is taken otherwise - const int newLayoutIndex = (layoutIndex == (mApplicationMode->count() - 1)) ? layoutIndex - 1 : layoutIndex + 1; + const int newLayoutIndex = (layoutIndex == (m_applicationMode->count() - 1)) ? layoutIndex - 1 : layoutIndex + 1; // select the layout, it also keeps it and saves to config - mApplicationMode->setCurrentIndex(newLayoutIndex); + m_applicationMode->setCurrentIndex(newLayoutIndex); } // update the layouts menu @@ -2021,7 +2021,7 @@ namespace EMStudio QAction* action = qobject_cast(sender()); // update the last used layout and save it in the preferences file - mOptions.SetApplicationMode(action->text().toUtf8().data()); + m_options.SetApplicationMode(action->text().toUtf8().data()); SavePreferences(); // generate the filename @@ -2031,10 +2031,10 @@ namespace EMStudio if (GetLayoutManager()->LoadLayout(filename.c_str())) { // update the combo box - mApplicationMode->blockSignals(true); - const int layoutIndex = mApplicationMode->findText(action->text()); - mApplicationMode->setCurrentIndex(layoutIndex); - mApplicationMode->blockSignals(false); + m_applicationMode->blockSignals(true); + const int layoutIndex = m_applicationMode->findText(action->text()); + m_applicationMode->setCurrentIndex(layoutIndex); + m_applicationMode->blockSignals(false); } else { @@ -2195,8 +2195,8 @@ namespace EMStudio const size_t actorCount = actorFilenames.size(); if (actorCount == 1) { - mDroppedActorFileName = actorFilenames[0].c_str(); - mRecentActors.AddRecentFile(mDroppedActorFileName.c_str()); + m_droppedActorFileName = actorFilenames[0].c_str(); + m_recentActors.AddRecentFile(m_droppedActorFileName.c_str()); if (contextMenuEnabled) { @@ -2252,11 +2252,11 @@ namespace EMStudio if (numWorkspaces > 0) { // make sure we did not cancel load workspace - if (mDirtyFileManager->SaveDirtyFiles() != DirtyFileManager::CANCELED) + if (m_dirtyFileManager->SaveDirtyFiles() != DirtyFileManager::CANCELED) { // add the workspace in the recent workspace list // if the same workspace is already in the list, the duplicate is removed - mRecentWorkspaces.AddRecentFile(workspaceFilenames[0]); + m_recentWorkspaces.AddRecentFile(workspaceFilenames[0]); // create the command group MCore::CommandGroup workspaceCommandGroup("Load workspace", 64); @@ -2344,21 +2344,21 @@ namespace EMStudio void MainWindow::LoadLayoutAfterShow() { - if (!mLayoutLoaded) + if (!m_layoutLoaded) { - mLayoutLoaded = true; + m_layoutLoaded = true; LoadDefaultLayout(); - if (mCharacterFiles.empty() && GetManager()->GetAutoLoadLastWorkspace()) + if (m_characterFiles.empty() && GetManager()->GetAutoLoadLastWorkspace()) { // load last workspace - const AZStd::string lastRecentWorkspace = mRecentWorkspaces.GetLastRecentFileName(); + const AZStd::string lastRecentWorkspace = m_recentWorkspaces.GetLastRecentFileName(); if (!lastRecentWorkspace.empty()) { - mCharacterFiles.push_back(lastRecentWorkspace); + m_characterFiles.push_back(lastRecentWorkspace); } } - if (!mCharacterFiles.empty()) + if (!m_characterFiles.empty()) { // Need to defer loading the character until the layout is ready. We also // need a couple of initializeGL/paintGL to happen before the character @@ -2391,7 +2391,7 @@ namespace EMStudio // Load default layout. void MainWindow::LoadDefaultLayout() { - if (mApplicationMode->count() == 0) + if (m_applicationMode->count() == 0) { // When the combo box is empty, the call to setCurrentIndex will // not cause any slots to be fired, so dispatch the call manually. @@ -2401,23 +2401,23 @@ namespace EMStudio return; } - int layoutIndex = mApplicationMode->findText(mOptions.GetApplicationMode().c_str()); + int layoutIndex = m_applicationMode->findText(m_options.GetApplicationMode().c_str()); // If searching for the last used layout fails load the default or viewer layout if they exist if (layoutIndex == -1) { - layoutIndex = mApplicationMode->findText("AnimGraph"); + layoutIndex = m_applicationMode->findText("AnimGraph"); } if (layoutIndex == -1) { - layoutIndex = mApplicationMode->findText("Character"); + layoutIndex = m_applicationMode->findText("Character"); } if (layoutIndex == -1) { - layoutIndex = mApplicationMode->findText("Animation"); + layoutIndex = m_applicationMode->findText("Animation"); } - mApplicationMode->setCurrentIndex(layoutIndex); + m_applicationMode->setCurrentIndex(layoutIndex); } @@ -2457,10 +2457,10 @@ namespace EMStudio void MainWindow::LoadCharacterFiles() { - if (!mCharacterFiles.empty()) + if (!m_characterFiles.empty()) { - LoadFiles(mCharacterFiles, 0, 0, false, true); - mCharacterFiles.clear(); + LoadFiles(m_characterFiles, 0, 0, false, true); + m_characterFiles.clear(); // for all registered plugins, call the after load actors callback PluginManager* pluginManager = GetPluginManager(); @@ -2494,18 +2494,18 @@ namespace EMStudio // gets called when the user drag&dropped an actor to the application and then chose to open it in the context menu void MainWindow::OnOpenDroppedActor() { - if (mDirtyFileManager->SaveDirtyFiles({azrtti_typeid()}) == DirtyFileManager::CANCELED) + if (m_dirtyFileManager->SaveDirtyFiles({azrtti_typeid()}) == DirtyFileManager::CANCELED) { return; } - LoadActor(mDroppedActorFileName.c_str(), true); + LoadActor(m_droppedActorFileName.c_str(), true); } // gets called when the user drag&dropped an actor to the application and then chose to merge it in the context menu void MainWindow::OnMergeDroppedActor() { - LoadActor(mDroppedActorFileName.c_str(), false); + LoadActor(m_droppedActorFileName.c_str(), false); } @@ -2536,13 +2536,13 @@ namespace EMStudio void MainWindow::closeEvent(QCloseEvent* event) { - if (mDirtyFileManager->SaveDirtyFiles() == DirtyFileManager::CANCELED) + if (m_dirtyFileManager->SaveDirtyFiles() == DirtyFileManager::CANCELED) { event->ignore(); } else { - mAutosaveTimer->stop(); + m_autosaveTimer->stop(); PluginManager* pluginManager = GetPluginManager(); @@ -2570,22 +2570,22 @@ namespace EMStudio // We mark it as false so next time is shown the layout is re-loaded if // necessary - mLayoutLoaded = false; + m_layoutLoaded = false; } void MainWindow::showEvent(QShowEvent* event) { - if (mOptions.GetEnableAutoSave()) + if (m_options.GetEnableAutoSave()) { - mAutosaveTimer->setInterval(mOptions.GetAutoSaveInterval() * 60 * 1000); - mAutosaveTimer->start(); + m_autosaveTimer->setInterval(m_options.GetAutoSaveInterval() * 60 * 1000); + m_autosaveTimer->start(); } // EMotionFX dock widget is created the first time it's opened, so we need to load layout after that // The singleShot is needed because show event is fired before the dock widget resizes (in the same function dock widget is created) // So we want to load layout after that. It's a bit hacky, but most sensible at the moment. - if (!mLayoutLoaded) + if (!m_layoutLoaded) { QTimer::singleShot(0, this, &MainWindow::LoadLayoutAfterShow); } @@ -2603,7 +2603,7 @@ namespace EMStudio const char* MainWindow::GetCurrentLayoutName() const { // get the selected layout - const int currentLayoutIndex = mApplicationMode->currentIndex(); + const int currentLayoutIndex = m_applicationMode->currentIndex(); // if the index is out of range, return empty name if ((currentLayoutIndex < 0) || (currentLayoutIndex >= (int32)GetNumLayouts())) @@ -2628,10 +2628,10 @@ namespace EMStudio AZStd::vector objects; AZStd::vector dirtyObjects; - const size_t numDirtyFilesCallbacks = mDirtyFileManager->GetNumCallbacks(); + const size_t numDirtyFilesCallbacks = m_dirtyFileManager->GetNumCallbacks(); for (size_t i = 0; i < numDirtyFilesCallbacks; ++i) { - SaveDirtyFilesCallback* callback = mDirtyFileManager->GetCallback(i); + SaveDirtyFilesCallback* callback = m_dirtyFileManager->GetCallback(i); callback->GetDirtyFileNames(&filenames, &objects); const size_t numFileNames = filenames.size(); for (size_t j = 0; j < numFileNames; ++j) @@ -2721,11 +2721,11 @@ namespace EMStudio } // check if the length is upper than the max num files - if (autosaveFileList.length() >= mOptions.GetAutoSaveNumberOfFiles()) + if (autosaveFileList.length() >= m_options.GetAutoSaveNumberOfFiles()) { // number of files to delete // one is added because one space needs to be free for the new file - const int numFilesToDelete = mOptions.GetAutoSaveNumberOfFiles() ? (autosaveFileList.size() - mOptions.GetAutoSaveNumberOfFiles() + 1) : autosaveFileList.size(); + const int numFilesToDelete = m_options.GetAutoSaveNumberOfFiles() ? (autosaveFileList.size() - m_options.GetAutoSaveNumberOfFiles() + 1) : autosaveFileList.size(); // delete each file for (int j = 0; j < numFilesToDelete; ++j) @@ -2749,18 +2749,18 @@ namespace EMStudio AZ_Printf("EMotionFX", "Saving to '%s'\n", newFileFilename.c_str()); // Backing up actors and motions doesn't work anymore as we just update the .assetinfos and the asset processor does the rest. - if (dirtyObjects[i].mMotionSet) + if (dirtyObjects[i].m_motionSet) { - command = AZStd::string::format("SaveMotionSet -motionSetID %i -filename \"%s\" -updateFilename false -updateDirtyFlag false -sourceControl false", dirtyObjects[i].mMotionSet->GetID(), newFileFilename.c_str()); + command = AZStd::string::format("SaveMotionSet -motionSetID %i -filename \"%s\" -updateFilename false -updateDirtyFlag false -sourceControl false", dirtyObjects[i].m_motionSet->GetID(), newFileFilename.c_str()); commandGroup.AddCommandString(command); } - else if (dirtyObjects[i].mAnimGraph) + else if (dirtyObjects[i].m_animGraph) { - const size_t animGraphIndex = EMotionFX::GetAnimGraphManager().FindAnimGraphIndex(dirtyObjects[i].mAnimGraph); + const size_t animGraphIndex = EMotionFX::GetAnimGraphManager().FindAnimGraphIndex(dirtyObjects[i].m_animGraph); command = AZStd::string::format("SaveAnimGraph -index %zu -filename \"%s\" -updateFilename false -updateDirtyFlag false -sourceControl false", animGraphIndex, newFileFilename.c_str()); commandGroup.AddCommandString(command); } - else if (dirtyObjects[i].mWorkspace) + else if (dirtyObjects[i].m_workspace) { Workspace* workspace = GetManager()->GetWorkspace(); workspace->Save(newFileFilename.c_str(), false, false); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindow.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindow.h index d49d47452b..734dd7840d 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindow.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindow.h @@ -91,7 +91,7 @@ namespace EMStudio void Init(const AZStd::vector& errors); private: - QTextEdit* mTextEdit = nullptr; + QTextEdit* m_textEdit = nullptr; }; // the main window @@ -114,7 +114,7 @@ namespace EMStudio static void Reflect(AZ::ReflectContext* context); void Init(); - MCORE_INLINE QMenu* GetLayoutsMenu() { return mLayoutsMenu; } + MCORE_INLINE QMenu* GetLayoutsMenu() { return m_layoutsMenu; } void LoadActor(const char* fileName, bool replaceCurrentScene); void LoadCharacter(const AZ::Data::AssetId& actorAssetId, const AZ::Data::AssetId& animgraphId, const AZ::Data::AssetId& motionSetId); @@ -123,9 +123,9 @@ namespace EMStudio void Activate(const AZ::Data::AssetId& actorAssetId, const EMotionFX::AnimGraph* animGraph, const EMotionFX::MotionSet* motionSet); - MysticQt::RecentFiles* GetRecentWorkspaces() { return &mRecentWorkspaces; } + MysticQt::RecentFiles* GetRecentWorkspaces() { return &m_recentWorkspaces; } - GUIOptions& GetOptions() { return mOptions; } + GUIOptions& GetOptions() { return m_options; } void Reset(bool clearActors = true, bool clearMotionSets = true, bool clearMotions = true, bool clearAnimGraphs = true, MCore::CommandGroup* commandGroup = nullptr); @@ -143,17 +143,17 @@ namespace EMStudio void OnWorkspaceSaved(const char* filename); - MCORE_INLINE QComboBox* GetApplicationModeComboBox() { return mApplicationMode; } - DirtyFileManager* GetDirtyFileManager() const { return mDirtyFileManager; } - FileManager* GetFileManager() const { return mFileManager; } - PreferencesWindow* GetPreferencesWindow() const { return mPreferencesWindow; } + MCORE_INLINE QComboBox* GetApplicationModeComboBox() { return m_applicationMode; } + DirtyFileManager* GetDirtyFileManager() const { return m_dirtyFileManager; } + FileManager* GetFileManager() const { return m_fileManager; } + PreferencesWindow* GetPreferencesWindow() const { return m_preferencesWindow; } - size_t GetNumLayouts() const { return mLayoutNames.size(); } - const char* GetLayoutName(uint32 index) const { return mLayoutNames[index].c_str(); } + size_t GetNumLayouts() const { return m_layoutNames.size(); } + const char* GetLayoutName(uint32 index) const { return m_layoutNames[index].c_str(); } const char* GetCurrentLayoutName() const; static const char* GetEMotionFXPaneName(); - MysticQt::KeyboardShortcutManager* GetShortcutManager() const { return mShortcutManager; } + MysticQt::KeyboardShortcutManager* GetShortcutManager() const { return m_shortcutManager; } AzQtComponents::FancyDocking* GetFancyDockingManager() const { return m_fancyDockingManager; } @@ -186,56 +186,56 @@ namespace EMStudio EMotionFX::Actor* m_prevSelectedActor; EMotionFX::ActorInstance* m_prevSelectedActorInstance; - QMenu* mCreateWindowMenu; - QMenu* mLayoutsMenu; + QMenu* m_createWindowMenu; + QMenu* m_layoutsMenu; QAction* m_undoAction; QAction* m_redoAction; // keyboard shortcut manager - MysticQt::KeyboardShortcutManager* mShortcutManager; + MysticQt::KeyboardShortcutManager* m_shortcutManager; // layouts (application modes) - AZStd::vector mLayoutNames; - bool mLayoutLoaded; + AZStd::vector m_layoutNames; + bool m_layoutLoaded; // menu actions - QAction* mResetAction; - QAction* mSaveAllAction; - QAction* mMergeActorAction; - QAction* mSaveSelectedActorsAction; + QAction* m_resetAction; + QAction* m_saveAllAction; + QAction* m_mergeActorAction; + QAction* m_saveSelectedActorsAction; #ifdef EMFX_DEVELOPMENT_BUILD - QAction* mSaveSelectedActorAsAttachmentsAction; + QAction* m_saveSelectedActorAsAttachmentsAction; #endif // application mode - QComboBox* mApplicationMode; + QComboBox* m_applicationMode; - PreferencesWindow* mPreferencesWindow; + PreferencesWindow* m_preferencesWindow; - FileManager* mFileManager; + FileManager* m_fileManager; - MysticQt::RecentFiles mRecentActors; - MysticQt::RecentFiles mRecentWorkspaces; + MysticQt::RecentFiles m_recentActors; + MysticQt::RecentFiles m_recentWorkspaces; // dirty files - DirtyFileManager* mDirtyFileManager; + DirtyFileManager* m_dirtyFileManager; void SetWindowTitleFromFileName(const AZStd::string& fileName); // drag & drop support void dragEnterEvent(QDragEnterEvent* event) override; void dropEvent(QDropEvent* event) override; - AZStd::string mDroppedActorFileName; + AZStd::string m_droppedActorFileName; // General options - GUIOptions mOptions; - bool mLoadingOptions; + GUIOptions m_options; + bool m_loadingOptions; - QTimer* mAutosaveTimer; + QTimer* m_autosaveTimer; - AZStd::vector mCharacterFiles; + AZStd::vector m_characterFiles; - NativeEventFilter* mNativeEventFilter; + NativeEventFilter* m_nativeEventFilter; void closeEvent(QCloseEvent* event) override; void showEvent(QShowEvent* event) override; @@ -266,21 +266,21 @@ namespace EMStudio MCORE_DEFINECOMMANDCALLBACK(CommandUnselectCallback); MCORE_DEFINECOMMANDCALLBACK(CommandClearSelectionCallback); MCORE_DEFINECOMMANDCALLBACK(CommandSaveWorkspaceCallback); - CommandImportActorCallback* mImportActorCallback; - CommandRemoveActorCallback* mRemoveActorCallback; - CommandRemoveActorInstanceCallback* mRemoveActorInstanceCallback; - CommandImportMotionCallback* mImportMotionCallback; - CommandRemoveMotionCallback* mRemoveMotionCallback; - CommandCreateMotionSetCallback* mCreateMotionSetCallback; - CommandRemoveMotionSetCallback* mRemoveMotionSetCallback; - CommandLoadMotionSetCallback* mLoadMotionSetCallback; - CommandCreateAnimGraphCallback* mCreateAnimGraphCallback; - CommandRemoveAnimGraphCallback* mRemoveAnimGraphCallback; - CommandLoadAnimGraphCallback* mLoadAnimGraphCallback; - CommandSelectCallback* mSelectCallback; - CommandUnselectCallback* mUnselectCallback; + CommandImportActorCallback* m_importActorCallback; + CommandRemoveActorCallback* m_removeActorCallback; + CommandRemoveActorInstanceCallback* m_removeActorInstanceCallback; + CommandImportMotionCallback* m_importMotionCallback; + CommandRemoveMotionCallback* m_removeMotionCallback; + CommandCreateMotionSetCallback* m_createMotionSetCallback; + CommandRemoveMotionSetCallback* m_removeMotionSetCallback; + CommandLoadMotionSetCallback* m_loadMotionSetCallback; + CommandCreateAnimGraphCallback* m_createAnimGraphCallback; + CommandRemoveAnimGraphCallback* m_removeAnimGraphCallback; + CommandLoadAnimGraphCallback* m_loadAnimGraphCallback; + CommandSelectCallback* m_selectCallback; + CommandUnselectCallback* m_unselectCallback; CommandClearSelectionCallback* m_clearSelectionCallback; - CommandSaveWorkspaceCallback* mSaveWorkspaceCallback; + CommandSaveWorkspaceCallback* m_saveWorkspaceCallback; class MainWindowCommandManagerCallback : public MCore::CommandManagerCallback { diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindowEventFilter.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindowEventFilter.h index d6afacf602..c7e82b13e9 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindowEventFilter.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindowEventFilter.h @@ -20,13 +20,13 @@ namespace EMStudio public: NativeEventFilter(MainWindow* mainWindow) : QAbstractNativeEventFilter(), - m_MainWindow(mainWindow) + m_mainWindow(mainWindow) { } virtual bool nativeEventFilter(const QByteArray& /*eventType*/, void* message, long* /*result*/) Q_DECL_OVERRIDE; private: - MainWindow* m_MainWindow; + MainWindow* m_mainWindow; }; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MorphTargetSelectionWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MorphTargetSelectionWindow.cpp index e189b98dcf..326b1b9902 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MorphTargetSelectionWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MorphTargetSelectionWindow.cpp @@ -21,30 +21,30 @@ namespace EMStudio QVBoxLayout* layout = new QVBoxLayout(); - mListWidget = new QListWidget(); - mListWidget->setAlternatingRowColors(true); + m_listWidget = new QListWidget(); + m_listWidget->setAlternatingRowColors(true); if (multiSelect) { - mListWidget->setSelectionMode(QListWidget::ExtendedSelection); + m_listWidget->setSelectionMode(QListWidget::ExtendedSelection); } else { - mListWidget->setSelectionMode(QAbstractItemView::SelectionMode::SingleSelection); + m_listWidget->setSelectionMode(QAbstractItemView::SelectionMode::SingleSelection); } QHBoxLayout* buttonLayout = new QHBoxLayout(); - mOKButton = new QPushButton("OK"); - mCancelButton = new QPushButton("Cancel"); - buttonLayout->addWidget(mOKButton); - buttonLayout->addWidget(mCancelButton); + m_okButton = new QPushButton("OK"); + m_cancelButton = new QPushButton("Cancel"); + buttonLayout->addWidget(m_okButton); + buttonLayout->addWidget(m_cancelButton); - layout->addWidget(mListWidget); + layout->addWidget(m_listWidget); layout->addLayout(buttonLayout); setLayout(layout); - connect(mOKButton, &QPushButton::clicked, this, &MorphTargetSelectionWindow::accept); - connect(mCancelButton, &QPushButton::clicked, this, &MorphTargetSelectionWindow::reject); - connect(mListWidget, &QListWidget::itemSelectionChanged, this, &MorphTargetSelectionWindow::OnSelectionChanged); + connect(m_okButton, &QPushButton::clicked, this, &MorphTargetSelectionWindow::accept); + connect(m_cancelButton, &QPushButton::clicked, this, &MorphTargetSelectionWindow::reject); + connect(m_listWidget, &QListWidget::itemSelectionChanged, this, &MorphTargetSelectionWindow::OnSelectionChanged); } @@ -55,25 +55,25 @@ namespace EMStudio const AZStd::vector& MorphTargetSelectionWindow::GetMorphTargetIDs() const { - return mSelection; + return m_selection; } void MorphTargetSelectionWindow::OnSelectionChanged() { - mSelection.clear(); + m_selection.clear(); - const int numItems = mListWidget->count(); - mSelection.reserve(numItems); + const int numItems = m_listWidget->count(); + m_selection.reserve(numItems); for (int i = 0; i < numItems; ++i) { - QListWidgetItem* item = mListWidget->item(i); + QListWidgetItem* item = m_listWidget->item(i); if (!item->isSelected()) { continue; } - mSelection.emplace_back(item->data(Qt::UserRole).toInt()); + m_selection.emplace_back(item->data(Qt::UserRole).toInt()); } } @@ -85,10 +85,10 @@ namespace EMStudio return; } - mListWidget->blockSignals(true); - mListWidget->clear(); + m_listWidget->blockSignals(true); + m_listWidget->clear(); - mSelection = selection; + m_selection = selection; const size_t numMorphTargets = morphSetup->GetNumMorphTargets(); for (size_t i = 0; i < numMorphTargets; ++i) @@ -100,16 +100,16 @@ namespace EMStudio item->setText(morphTarget->GetName()); item->setData(Qt::UserRole, morphTargetID); - mListWidget->addItem(item); + m_listWidget->addItem(item); - if (AZStd::find(mSelection.begin(), mSelection.end(), morphTargetID) != mSelection.end()) + if (AZStd::find(m_selection.begin(), m_selection.end(), morphTargetID) != m_selection.end()) { item->setSelected(true); } } - mListWidget->blockSignals(false); - mSelection = selection; + m_listWidget->blockSignals(false); + m_selection = selection; } } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MorphTargetSelectionWindow.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MorphTargetSelectionWindow.h index aee6f38754..c05fa91a3d 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MorphTargetSelectionWindow.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MorphTargetSelectionWindow.h @@ -38,9 +38,9 @@ namespace EMStudio void OnSelectionChanged(); private: - AZStd::vector mSelection; - QListWidget* mListWidget; - QPushButton* mOKButton; - QPushButton* mCancelButton; + AZStd::vector m_selection; + QListWidget* m_listWidget; + QPushButton* m_okButton; + QPushButton* m_cancelButton; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MotionEventPresetManager.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MotionEventPresetManager.cpp index e6f3fd5ac8..ac5dd80f4f 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MotionEventPresetManager.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MotionEventPresetManager.cpp @@ -70,12 +70,12 @@ namespace EMStudio //----------------------------------- - const AZ::u32 MotionEventPresetManager::m_unknownEventColor = MCore::RGBA(193, 195, 196, 255); + const AZ::u32 MotionEventPresetManager::s_unknownEventColor = MCore::RGBA(193, 195, 196, 255); MotionEventPresetManager::MotionEventPresetManager() - : mDirtyFlag(false) + : m_dirtyFlag(false) { - mFileName = GetManager()->GetAppDataFolder() + "EMStudioDefaultEventPresets.cfg"; + m_fileName = GetManager()->GetAppDataFolder() + "EMStudioDefaultEventPresets.cfg"; } @@ -96,51 +96,51 @@ namespace EMStudio serializeContext->Class() ->Version(1) - ->Field("eventPresets", &MotionEventPresetManager::mEventPresets) + ->Field("eventPresets", &MotionEventPresetManager::m_eventPresets) ; } void MotionEventPresetManager::Clear() { - for (MotionEventPreset* eventPreset : mEventPresets) + for (MotionEventPreset* eventPreset : m_eventPresets) { delete eventPreset; } - mEventPresets.clear(); + m_eventPresets.clear(); } size_t MotionEventPresetManager::GetNumPresets() const { - return mEventPresets.size(); + return m_eventPresets.size(); } bool MotionEventPresetManager::IsEmpty() const { - return mEventPresets.empty(); + return m_eventPresets.empty(); } void MotionEventPresetManager::AddPreset(MotionEventPreset* preset) { - mEventPresets.emplace_back(preset); - mDirtyFlag = true; + m_eventPresets.emplace_back(preset); + m_dirtyFlag = true; } void MotionEventPresetManager::RemovePreset(size_t index) { - delete mEventPresets[index]; - mEventPresets.erase(mEventPresets.begin() + index); - mDirtyFlag = true; + delete m_eventPresets[index]; + m_eventPresets.erase(m_eventPresets.begin() + index); + m_dirtyFlag = true; } MotionEventPreset* MotionEventPresetManager::GetPreset(size_t index) const { - return mEventPresets[index]; + return m_eventPresets[index]; } @@ -152,14 +152,14 @@ namespace EMStudio MotionEventPreset* rightFootPreset = aznew MotionEventPreset("RightFoot", {AZStd::move(rightFootData)}, AZ::Color(AZ::u8(0), 255, 0, 255)); leftFootPreset->SetIsDefault(true); rightFootPreset->SetIsDefault(true); - mEventPresets.emplace(mEventPresets.begin(), leftFootPreset); - mEventPresets.emplace(AZStd::next(mEventPresets.begin(), 1), rightFootPreset); + m_eventPresets.emplace(m_eventPresets.begin(), leftFootPreset); + m_eventPresets.emplace(AZStd::next(m_eventPresets.begin(), 1), rightFootPreset); } void MotionEventPresetManager::Load(const AZStd::string& filename) { - mFileName = filename; + m_fileName = filename; // Clear the old event presets. Clear(); @@ -169,11 +169,11 @@ namespace EMStudio LoadLegacyQSettingsFormat(); } - // LoadLYSerializedFormat() will clear mEventPresets, so default + // LoadLYSerializedFormat() will clear m_eventPresets, so default // presets have to be made afterwards CreateDefaultPresets(); - mDirtyFlag = false; + m_dirtyFlag = false; // Update the default preset settings filename so that next startup the presets get auto-loaded. SaveToSettings(); @@ -182,7 +182,7 @@ namespace EMStudio bool MotionEventPresetManager::LoadLegacyQSettingsFormat() { - QSettings settings(mFileName.c_str(), QSettings::IniFormat, GetManager()->GetMainWindow()); + QSettings settings(m_fileName.c_str(), QSettings::IniFormat, GetManager()->GetMainWindow()); if (settings.status() != QSettings::Status::NoError) { @@ -221,18 +221,18 @@ namespace EMStudio bool MotionEventPresetManager::LoadLYSerializedFormat() { - return AZ::Utils::LoadObjectFromFileInPlace(mFileName, azrtti_typeid(mEventPresets), &mEventPresets); + return AZ::Utils::LoadObjectFromFileInPlace(m_fileName, azrtti_typeid(m_eventPresets), &m_eventPresets); } void MotionEventPresetManager::SaveAs(const AZStd::string& filename, bool showNotification) { - mFileName = filename; + m_fileName = filename; // Skip saving the built-in presets AZStd::vector presets; - presets.reserve(mEventPresets.size()); - for (MotionEventPreset* preset : mEventPresets) + presets.reserve(m_eventPresets.size()); + for (MotionEventPreset* preset : m_eventPresets) { if (preset->GetIsDefault()) { @@ -251,7 +251,7 @@ namespace EMStudio // Check if the settings correctly saved. if (AZ::Utils::SaveObjectToFile(filename, AZ::DataStream::ST_XML, &presets)) { - mDirtyFlag = false; + m_dirtyFlag = false; // Add file in case it did not exist before (when saving it the first time). if (!SourceControlCommand::CheckOutFile(filename.c_str(), fileExisted, checkoutResultString, /*useSourceControl=*/true, /*add=*/true)) @@ -279,11 +279,11 @@ namespace EMStudio void MotionEventPresetManager::SaveToSettings() { - if (!mFileName.empty()) + if (!m_fileName.empty()) { QSettings settings(GetManager()->GetMainWindow()); settings.beginGroup("EMotionFX"); - settings.setValue("lastEventPresetFile", mFileName.c_str()); + settings.setValue("lastEventPresetFile", m_fileName.c_str()); settings.endGroup(); } } @@ -298,7 +298,7 @@ namespace EMStudio if (!filename.empty()) { - mFileName = AZStd::move(filename); + m_fileName = AZStd::move(filename); } } @@ -306,7 +306,7 @@ namespace EMStudio // Check if motion event with this configuration exists and return color. AZ::u32 MotionEventPresetManager::GetEventColor(const EMotionFX::EventDataSet& eventDatas) const { - for (const MotionEventPreset* preset : mEventPresets) + for (const MotionEventPreset* preset : m_eventPresets) { EMotionFX::EventDataSet commonDatas; const EMotionFX::EventDataSet& presetDatas = preset->GetEventDatas(); @@ -325,6 +325,6 @@ namespace EMStudio } // Use the same color for all events that are not from a preset. - return m_unknownEventColor; + return s_unknownEventColor; } } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MotionEventPresetManager.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MotionEventPresetManager.h index 89e997a96f..8e5853291c 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MotionEventPresetManager.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MotionEventPresetManager.h @@ -75,16 +75,16 @@ namespace EMStudio void Clear(); void Load(const AZStd::string& filename); - void Load() { Load(mFileName); } + void Load() { Load(m_fileName); } void LoadFromSettings(); void SaveAs(const AZStd::string& filename, bool showNotification=true); - void Save(bool showNotification=true) { SaveAs(mFileName, showNotification); } + void Save(bool showNotification=true) { SaveAs(m_fileName, showNotification); } - bool GetIsDirty() const { return mDirtyFlag; } - void SetDirtyFlag(bool isDirty) { mDirtyFlag = isDirty; } - const char* GetFileName() const { return mFileName.c_str(); } - const AZStd::string& GetFileNameString() const { return mFileName; } - void SetFileName(const char* filename) { mFileName = filename; } + bool GetIsDirty() const { return m_dirtyFlag; } + void SetDirtyFlag(bool isDirty) { m_dirtyFlag = isDirty; } + const char* GetFileName() const { return m_fileName.c_str(); } + const AZStd::string& GetFileNameString() const { return m_fileName; } + void SetFileName(const char* filename) { m_fileName = filename; } AZ::u32 GetEventColor(const EMotionFX::EventDataSet& eventDatas) const; @@ -92,10 +92,10 @@ namespace EMStudio bool LoadLYSerializedFormat(); bool LoadLegacyQSettingsFormat(); - AZStd::vector mEventPresets; - AZStd::string mFileName; - bool mDirtyFlag; - static const AZ::u32 m_unknownEventColor; + AZStd::vector m_eventPresets; + AZStd::string m_fileName; + bool m_dirtyFlag; + static const AZ::u32 s_unknownEventColor; void SaveToSettings(); void CreateDefaultPresets(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MotionSetHierarchyWidget.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MotionSetHierarchyWidget.cpp index a5e3a64f1f..99180a716c 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MotionSetHierarchyWidget.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MotionSetHierarchyWidget.cpp @@ -32,10 +32,10 @@ namespace EMStudio MotionSetHierarchyWidget::MotionSetHierarchyWidget(QWidget* parent, bool useSingleSelection, CommandSystem::SelectionList* selectionList) : QWidget(parent) { - mCurrentSelectionList = selectionList; + m_currentSelectionList = selectionList; if (selectionList == nullptr) { - mCurrentSelectionList = &(GetCommandManager()->GetCurrentSelection()); + m_currentSelectionList = &(GetCommandManager()->GetCurrentSelection()); } QVBoxLayout* layout = new QVBoxLayout(); @@ -46,34 +46,34 @@ namespace EMStudio connect(m_searchWidget, &AzQtComponents::FilteredSearchWidget::TextFilterChanged, this, &MotionSetHierarchyWidget::OnTextFilterChanged); // create the tree widget - mHierarchy = new QTreeWidget(); + m_hierarchy = new QTreeWidget(); // create header items - mHierarchy->setColumnCount(2); + m_hierarchy->setColumnCount(2); QStringList headerList; headerList.append("ID"); headerList.append("FileName"); - mHierarchy->setHeaderLabels(headerList); + m_hierarchy->setHeaderLabels(headerList); // set optical stuff for the tree - mHierarchy->setColumnWidth(0, 400); - mHierarchy->setSortingEnabled(false); - mHierarchy->setSelectionMode(QAbstractItemView::SingleSelection); - mHierarchy->setMinimumWidth(620); - mHierarchy->setMinimumHeight(500); - mHierarchy->setAlternatingRowColors(true); - mHierarchy->setExpandsOnDoubleClick(true); - mHierarchy->setAnimated(true); + m_hierarchy->setColumnWidth(0, 400); + m_hierarchy->setSortingEnabled(false); + m_hierarchy->setSelectionMode(QAbstractItemView::SingleSelection); + m_hierarchy->setMinimumWidth(620); + m_hierarchy->setMinimumHeight(500); + m_hierarchy->setAlternatingRowColors(true); + m_hierarchy->setExpandsOnDoubleClick(true); + m_hierarchy->setAnimated(true); // disable the move of section to have column order fixed - mHierarchy->header()->setSectionsMovable(false); + m_hierarchy->header()->setSectionsMovable(false); layout->addWidget(m_searchWidget); - layout->addWidget(mHierarchy); + layout->addWidget(m_hierarchy); setLayout(layout); - connect(mHierarchy, &QTreeWidget::itemSelectionChanged, this, &MotionSetHierarchyWidget::UpdateSelection); - connect(mHierarchy, &QTreeWidget::itemDoubleClicked, this, &MotionSetHierarchyWidget::ItemDoubleClicked); + connect(m_hierarchy, &QTreeWidget::itemSelectionChanged, this, &MotionSetHierarchyWidget::UpdateSelection); + connect(m_hierarchy, &QTreeWidget::itemDoubleClicked, this, &MotionSetHierarchyWidget::ItemDoubleClicked); // connect the window activation signal to refresh if reactivated //connect( this, SIGNAL(visibilityChanged(bool)), this, SLOT(OnVisibilityChanged(bool)) ); @@ -91,12 +91,12 @@ namespace EMStudio // update from a motion set and selection list void MotionSetHierarchyWidget::Update(EMotionFX::MotionSet* motionSet, CommandSystem::SelectionList* selectionList) { - mMotionSet = motionSet; - mCurrentSelectionList = selectionList; + m_motionSet = motionSet; + m_currentSelectionList = selectionList; if (selectionList == nullptr) { - mCurrentSelectionList = &(GetCommandManager()->GetCurrentSelection()); + m_currentSelectionList = &(GetCommandManager()->GetCurrentSelection()); } Update(); @@ -106,12 +106,12 @@ namespace EMStudio // update the widget void MotionSetHierarchyWidget::Update() { - mHierarchy->clear(); + m_hierarchy->clear(); - mHierarchy->blockSignals(true); - if (mMotionSet) + m_hierarchy->blockSignals(true); + if (m_motionSet) { - AddMotionSetWithParents(mMotionSet); + AddMotionSetWithParents(m_motionSet); } else { @@ -128,12 +128,12 @@ namespace EMStudio if (motionSet->GetParentSet() == nullptr) { - RecursiveAddMotionSet(nullptr, EMotionFX::GetMotionManager().GetMotionSet(i), mCurrentSelectionList); + RecursiveAddMotionSet(nullptr, EMotionFX::GetMotionManager().GetMotionSet(i), m_currentSelectionList); } } } - mHierarchy->blockSignals(false); + m_hierarchy->blockSignals(false); UpdateSelection(); } @@ -144,8 +144,8 @@ namespace EMStudio QTreeWidgetItem* motionSetItem; if (parent == nullptr) { - motionSetItem = new QTreeWidgetItem(mHierarchy); - mHierarchy->addTopLevelItem(motionSetItem); + motionSetItem = new QTreeWidgetItem(m_hierarchy); + m_hierarchy->addTopLevelItem(motionSetItem); } else { @@ -196,7 +196,7 @@ namespace EMStudio void MotionSetHierarchyWidget::AddMotionSetWithParents(EMotionFX::MotionSet* motionSet) { // create the motion set item - QTreeWidgetItem* motionSetItem = new QTreeWidgetItem(mHierarchy); + QTreeWidgetItem* motionSetItem = new QTreeWidgetItem(m_hierarchy); // set the name motionSetItem->setText(0, motionSet->GetName()); @@ -232,7 +232,7 @@ namespace EMStudio while (parentMotionSet) { // create the motion set item - QTreeWidgetItem* parentMotionSetItem = new QTreeWidgetItem(mHierarchy); + QTreeWidgetItem* parentMotionSetItem = new QTreeWidgetItem(m_hierarchy); // set the name parentMotionSetItem->setText(0, parentMotionSet->GetName()); @@ -264,7 +264,7 @@ namespace EMStudio } // add the last motion set item as child and set this parent as last motion set item - parentMotionSetItem->addChild(mHierarchy->takeTopLevelItem(mHierarchy->indexOfTopLevelItem(motionSetItem))); + parentMotionSetItem->addChild(m_hierarchy->takeTopLevelItem(m_hierarchy->indexOfTopLevelItem(motionSetItem))); motionSetItem = parentMotionSetItem; // set the next parent motion set @@ -272,19 +272,19 @@ namespace EMStudio } // expand all to show all items - mHierarchy->expandAll(); + m_hierarchy->expandAll(); } void MotionSetHierarchyWidget::Select(const AZStd::vector& selectedItems) { - mSelected = selectedItems; + m_selected = selectedItems; for (const MotionSetSelectionItem& selectionItem : selectedItems) { - const AZStd::string& motionId = selectionItem.mMotionId; + const AZStd::string& motionId = selectionItem.m_motionId; - QTreeWidgetItemIterator itemIterator(mHierarchy); + QTreeWidgetItemIterator itemIterator(m_hierarchy); while (*itemIterator) { QTreeWidgetItem* item = *itemIterator; @@ -302,11 +302,11 @@ namespace EMStudio void MotionSetHierarchyWidget::UpdateSelection() { // Get the selected items in the tree widget. - QList selectedItems = mHierarchy->selectedItems(); + QList selectedItems = m_hierarchy->selectedItems(); // Reset the selection. - mSelected.clear(); - mSelected.reserve(selectedItems.size()); + m_selected.clear(); + m_selected.reserve(selectedItems.size()); AZStd::string motionId; for (const QTreeWidgetItem* item : selectedItems) @@ -325,7 +325,7 @@ namespace EMStudio } MotionSetSelectionItem selectionItem(motionId, motionSet); - mSelected.push_back(selectionItem); + m_selected.push_back(selectionItem); } } @@ -334,14 +334,14 @@ namespace EMStudio { if (useSingleSelection) { - mHierarchy->setSelectionMode(QAbstractItemView::SingleSelection); + m_hierarchy->setSelectionMode(QAbstractItemView::SingleSelection); } else { - mHierarchy->setSelectionMode(QAbstractItemView::ExtendedSelection); + m_hierarchy->setSelectionMode(QAbstractItemView::ExtendedSelection); } - mUseSingleSelection = useSingleSelection; + m_useSingleSelection = useSingleSelection; } @@ -364,14 +364,14 @@ namespace EMStudio void MotionSetHierarchyWidget::FireSelectionDoneSignal() { - emit SelectionChanged(mSelected); + emit SelectionChanged(m_selected); } AZStd::vector& MotionSetHierarchyWidget::GetSelectedItems() { UpdateSelection(); - return mSelected; + return m_selected; } @@ -384,9 +384,9 @@ namespace EMStudio for (const MotionSetSelectionItem& selectedItem : selectedItems) { - if (selectedItem.mMotionSet == motionSet) + if (selectedItem.m_motionSet == motionSet) { - result.push_back(selectedItem.mMotionId); + result.push_back(selectedItem.m_motionId); } } @@ -395,9 +395,9 @@ namespace EMStudio void MotionSetHierarchyWidget::SelectItemsWithText(QString text) { - QList items = mHierarchy->findItems(text, Qt::MatchWrap | Qt::MatchWildcard | Qt::MatchRecursive); + QList items = m_hierarchy->findItems(text, Qt::MatchWrap | Qt::MatchWildcard | Qt::MatchRecursive); - mHierarchy->clearSelection(); + m_hierarchy->clearSelection(); for (QTreeWidgetItem* item : items) { diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MotionSetHierarchyWidget.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MotionSetHierarchyWidget.h index 838044c010..50e86cf8ba 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MotionSetHierarchyWidget.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MotionSetHierarchyWidget.h @@ -33,12 +33,12 @@ namespace EMStudio { struct EMSTUDIO_API MotionSetSelectionItem { - AZStd::string mMotionId; - EMotionFX::MotionSet* mMotionSet; + AZStd::string m_motionId; + EMotionFX::MotionSet* m_motionSet; MotionSetSelectionItem(const AZStd::string& motionId, EMotionFX::MotionSet* motionSet) - : mMotionId(motionId) - , mMotionSet(motionSet) + : m_motionId(motionId) + , m_motionSet(motionSet) { } }; @@ -58,7 +58,7 @@ namespace EMStudio void Update(EMotionFX::MotionSet* motionSet, CommandSystem::SelectionList* selectionList = nullptr); void FireSelectionDoneSignal(); - MCORE_INLINE QTreeWidget* GetTreeWidget() { return mHierarchy; } + MCORE_INLINE QTreeWidget* GetTreeWidget() { return m_hierarchy; } MCORE_INLINE AzQtComponents::FilteredSearchWidget* GetSearchWidget() { return m_searchWidget; } void Select(const AZStd::vector& selectedItems); @@ -84,12 +84,12 @@ namespace EMStudio void RecursiveAddMotionSet(QTreeWidgetItem* parent, EMotionFX::MotionSet* motionSet, CommandSystem::SelectionList* selectionList); void AddMotionSetWithParents(EMotionFX::MotionSet* motionSet); - EMotionFX::MotionSet* mMotionSet; - QTreeWidget* mHierarchy; + EMotionFX::MotionSet* m_motionSet; + QTreeWidget* m_hierarchy; AzQtComponents::FilteredSearchWidget* m_searchWidget; AZStd::string m_searchWidgetText; - AZStd::vector mSelected; - CommandSystem::SelectionList* mCurrentSelectionList; - bool mUseSingleSelection; + AZStd::vector m_selected; + CommandSystem::SelectionList* m_currentSelectionList; + bool m_useSingleSelection; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MotionSetSelectionWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MotionSetSelectionWindow.cpp index 79b53da0f9..23c2000754 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MotionSetSelectionWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MotionSetSelectionWindow.cpp @@ -26,29 +26,29 @@ namespace EMStudio QVBoxLayout* layout = new QVBoxLayout(); - mHierarchyWidget = new MotionSetHierarchyWidget(this, useSingleSelection, selectionList); + m_hierarchyWidget = new MotionSetHierarchyWidget(this, useSingleSelection, selectionList); // create the ok and cancel buttons QHBoxLayout* buttonLayout = new QHBoxLayout(); - mOKButton = new QPushButton("OK"); - mOKButton->setObjectName("EMFX.MotionSetSelectionWindow.Ok"); - mCancelButton = new QPushButton("Cancel"); - mCancelButton->setObjectName("EMFX.MotionSetSelectionWindow.Cancel"); - buttonLayout->addWidget(mOKButton); - buttonLayout->addWidget(mCancelButton); + m_okButton = new QPushButton("OK"); + m_okButton->setObjectName("EMFX.MotionSetSelectionWindow.Ok"); + m_cancelButton = new QPushButton("Cancel"); + m_cancelButton->setObjectName("EMFX.MotionSetSelectionWindow.Cancel"); + buttonLayout->addWidget(m_okButton); + buttonLayout->addWidget(m_cancelButton); - layout->addWidget(mHierarchyWidget); + layout->addWidget(m_hierarchyWidget); layout->addLayout(buttonLayout); setLayout(layout); - connect(mOKButton, &QPushButton::clicked, this, &MotionSetSelectionWindow::accept); - connect(mCancelButton, &QPushButton::clicked, this, &MotionSetSelectionWindow::reject); + connect(m_okButton, &QPushButton::clicked, this, &MotionSetSelectionWindow::accept); + connect(m_cancelButton, &QPushButton::clicked, this, &MotionSetSelectionWindow::reject); connect(this, &MotionSetSelectionWindow::accepted, this, &MotionSetSelectionWindow::OnAccept); - connect(mHierarchyWidget, &MotionSetHierarchyWidget::SelectionChanged, this, &MotionSetSelectionWindow::OnSelectionChanged); + connect(m_hierarchyWidget, &MotionSetHierarchyWidget::SelectionChanged, this, &MotionSetSelectionWindow::OnSelectionChanged); // set the selection mode - mHierarchyWidget->SetSelectionMode(useSingleSelection); - mUseSingleSelection = useSingleSelection; + m_hierarchyWidget->SetSelectionMode(useSingleSelection); + m_useSingleSelection = useSingleSelection; } @@ -59,7 +59,7 @@ namespace EMStudio void MotionSetSelectionWindow::Select(const AZStd::vector& selectedItems) { - mHierarchyWidget->Select(selectedItems); + m_hierarchyWidget->Select(selectedItems); } @@ -85,9 +85,9 @@ namespace EMStudio void MotionSetSelectionWindow::OnAccept() { - if (mUseSingleSelection == false) + if (m_useSingleSelection == false) { - mHierarchyWidget->FireSelectionDoneSignal(); + m_hierarchyWidget->FireSelectionDoneSignal(); } } } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MotionSetSelectionWindow.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MotionSetSelectionWindow.h index 552b45d249..c35e46fc54 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MotionSetSelectionWindow.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MotionSetSelectionWindow.h @@ -29,8 +29,8 @@ namespace EMStudio MotionSetSelectionWindow(QWidget* parent, bool useSingleSelection = true, CommandSystem::SelectionList* selectionList = nullptr); virtual ~MotionSetSelectionWindow(); - MCORE_INLINE MotionSetHierarchyWidget* GetHierarchyWidget() { return mHierarchyWidget; } - void Update(EMotionFX::MotionSet* motionSet, CommandSystem::SelectionList* selectionList = nullptr) { mHierarchyWidget->Update(motionSet, selectionList); } + MCORE_INLINE MotionSetHierarchyWidget* GetHierarchyWidget() { return m_hierarchyWidget; } + void Update(EMotionFX::MotionSet* motionSet, CommandSystem::SelectionList* selectionList = nullptr) { m_hierarchyWidget->Update(motionSet, selectionList); } void Select(const AZStd::vector& selectedItems); void Select(const AZStd::vector& selectedMotionIds, EMotionFX::MotionSet* motionSet); @@ -40,9 +40,9 @@ namespace EMStudio void OnSelectionChanged(AZStd::vector selection); private: - MotionSetHierarchyWidget* mHierarchyWidget; - QPushButton* mOKButton; - QPushButton* mCancelButton; - bool mUseSingleSelection; + MotionSetHierarchyWidget* m_hierarchyWidget; + QPushButton* m_okButton; + QPushButton* m_cancelButton; + bool m_useSingleSelection; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NodeHierarchyWidget.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NodeHierarchyWidget.cpp index 1aa8082f08..63934a380c 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NodeHierarchyWidget.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NodeHierarchyWidget.cpp @@ -25,7 +25,7 @@ EMotionFX::Node* SelectionItem::GetNode() const { - EMotionFX::ActorInstance* actorInstance = EMotionFX::GetActorManager().FindActorInstanceByID(mActorInstanceID); + EMotionFX::ActorInstance* actorInstance = EMotionFX::GetActorManager().FindActorInstanceByID(m_actorInstanceId); if (!actorInstance) { return nullptr; @@ -46,10 +46,10 @@ namespace EMStudio const auto boneIconFilename = iconFilename("Bone.svg"); const auto nodeIconFilename = iconFilename("Node.svg"); const auto meshIconFilename = iconFilename("Mesh.svg"); - mBoneIcon = new QIcon(boneIconFilename); - mNodeIcon = new QIcon(nodeIconFilename); - mMeshIcon = new QIcon(meshIconFilename); - mCharacterIcon = new QIcon(iconFilename("Character.svg")); + m_boneIcon = new QIcon(boneIconFilename); + m_nodeIcon = new QIcon(nodeIconFilename); + m_meshIcon = new QIcon(meshIconFilename); + m_characterIcon = new QIcon(iconFilename("Character.svg")); QVBoxLayout* layout = new QVBoxLayout(); layout->setMargin(0); @@ -67,7 +67,7 @@ namespace EMStudio addFilter(tr("Meshes"), meshIconFilename, FilterType::Meshes); addFilter(tr("Nodes"), nodeIconFilename, FilterType::Nodes); addFilter(tr("Bones"), boneIconFilename, FilterType::Bones); - mFilterState = {FilterType::Meshes, FilterType::Nodes, FilterType::Bones}; + m_filterState = {FilterType::Meshes, FilterType::Nodes, FilterType::Bones}; connect(m_searchWidget, &AzQtComponents::FilteredSearchWidget::TextFilterChanged, this, &NodeHierarchyWidget::OnTextFilterChanged); connect(m_searchWidget, &AzQtComponents::FilteredSearchWidget::TypeFilterChanged, this, [this](const auto& filters) { FilterTypes filterState; @@ -75,52 +75,52 @@ namespace EMStudio { filterState.setFlag(static_cast(filter.metadata.toInt())); } - if (filterState == mFilterState) + if (filterState == m_filterState) { return; } - mFilterState = filterState; + m_filterState = filterState; Update(); emit FilterStateChanged(filterState); }); layout->addWidget(m_searchWidget); // create the tree widget - mHierarchy = new QTreeWidget(); + m_hierarchy = new QTreeWidget(); // create header items - mHierarchy->setColumnCount(1); + m_hierarchy->setColumnCount(1); // set optical stuff for the tree - mHierarchy->header()->setVisible(false); - mHierarchy->header()->setStretchLastSection(true); - mHierarchy->setSortingEnabled(false); - mHierarchy->setSelectionMode(QAbstractItemView::SingleSelection); + m_hierarchy->header()->setVisible(false); + m_hierarchy->header()->setStretchLastSection(true); + m_hierarchy->setSortingEnabled(false); + m_hierarchy->setSelectionMode(QAbstractItemView::SingleSelection); if (useDefaultMinWidth) { - mHierarchy->setMinimumWidth(500); + m_hierarchy->setMinimumWidth(500); } - mHierarchy->setMinimumHeight(400); - mHierarchy->setExpandsOnDoubleClick(true); - mHierarchy->setAnimated(true); + m_hierarchy->setMinimumHeight(400); + m_hierarchy->setExpandsOnDoubleClick(true); + m_hierarchy->setAnimated(true); // disable the move of section to have column order fixed - mHierarchy->header()->setSectionsMovable(false); + m_hierarchy->header()->setSectionsMovable(false); if (useSingleSelection == false) { - mHierarchy->setContextMenuPolicy(Qt::CustomContextMenu); - connect(mHierarchy, &QTreeWidget::customContextMenuRequested, this, &NodeHierarchyWidget::TreeContextMenu); + m_hierarchy->setContextMenuPolicy(Qt::CustomContextMenu); + connect(m_hierarchy, &QTreeWidget::customContextMenuRequested, this, &NodeHierarchyWidget::TreeContextMenu); } - layout->addWidget(mHierarchy); + layout->addWidget(m_hierarchy); setLayout(layout); - connect(mHierarchy, &QTreeWidget::itemSelectionChanged, this, &NodeHierarchyWidget::UpdateSelection); - connect(mHierarchy, &QTreeWidget::itemDoubleClicked, this, &NodeHierarchyWidget::ItemDoubleClicked); - connect(mHierarchy, &QTreeWidget::itemSelectionChanged, this, &NodeHierarchyWidget::OnSelectionChanged); + connect(m_hierarchy, &QTreeWidget::itemSelectionChanged, this, &NodeHierarchyWidget::UpdateSelection); + connect(m_hierarchy, &QTreeWidget::itemDoubleClicked, this, &NodeHierarchyWidget::ItemDoubleClicked); + connect(m_hierarchy, &QTreeWidget::itemSelectionChanged, this, &NodeHierarchyWidget::OnSelectionChanged); // connect the window activation signal to refresh if reactivated //connect( this, SIGNAL(visibilityChanged(bool)), this, SLOT(OnVisibilityChanged(bool)) ); @@ -133,16 +133,16 @@ namespace EMStudio // destructor NodeHierarchyWidget::~NodeHierarchyWidget() { - delete mBoneIcon; - delete mMeshIcon; - delete mNodeIcon; - delete mCharacterIcon; + delete m_boneIcon; + delete m_meshIcon; + delete m_nodeIcon; + delete m_characterIcon; } void NodeHierarchyWidget::Update(const AZStd::vector& actorInstanceIDs, CommandSystem::SelectionList* selectionList) { - mActorInstanceIDs = actorInstanceIDs; + m_actorInstanceIDs = actorInstanceIDs; ConvertFromSelectionList(selectionList); Update(); @@ -151,7 +151,7 @@ namespace EMStudio void NodeHierarchyWidget::Update(uint32 actorInstanceID, CommandSystem::SelectionList* selectionList) { - mActorInstanceIDs.clear(); + m_actorInstanceIDs.clear(); if (actorInstanceID == MCORE_INVALIDINDEX32) { @@ -167,27 +167,27 @@ namespace EMStudio continue; } - mActorInstanceIDs.emplace_back(actorInstance->GetID()); + m_actorInstanceIDs.emplace_back(actorInstance->GetID()); } } else { - mActorInstanceIDs.emplace_back(actorInstanceID); + m_actorInstanceIDs.emplace_back(actorInstanceID); } - Update(mActorInstanceIDs, selectionList); + Update(m_actorInstanceIDs, selectionList); } void NodeHierarchyWidget::Update() { - mHierarchy->blockSignals(true); + m_hierarchy->blockSignals(true); // clear the whole thing (don't put this before blockSignals() else we have a bug in the skeletal LOD choosing, before also doesn't make any sense cause the OnNodesChanged() gets called and resets the selection!) - mHierarchy->clear(); + m_hierarchy->clear(); // get the number actor instances and iterate over them - for (const uint32 actorInstanceID : mActorInstanceIDs) + for (const uint32 actorInstanceID : m_actorInstanceIDs) { // get the actor instance by its id EMotionFX::ActorInstance* actorInstance = EMotionFX::GetActorManager().FindActorInstanceByID(actorInstanceID); @@ -197,7 +197,7 @@ namespace EMStudio } } - mHierarchy->blockSignals(false); + m_hierarchy->blockSignals(false); // after we refilled everything, update the selection UpdateSelection(); @@ -212,13 +212,13 @@ namespace EMStudio const size_t numNodes = actor->GetNumNodes(); // extract the bones from the actor - actor->ExtractBoneList(actorInstance->GetLODLevel(), &mBoneList); + actor->ExtractBoneList(actorInstance->GetLODLevel(), &m_boneList); // calculate the number of polygons and indices uint32 numPolygons, numVertices, numIndices; actor->CalcMeshTotals(actorInstance->GetLODLevel(), &numPolygons, &numVertices, &numIndices); - QTreeWidgetItem* rootItem = new QTreeWidgetItem(mHierarchy); + QTreeWidgetItem* rootItem = new QTreeWidgetItem(m_hierarchy); // select the item in case the actor if (CheckIfActorInstanceSelected(actorInstance->GetID())) @@ -232,11 +232,11 @@ namespace EMStudio rootItem->setText(3, AZStd::to_string(numIndices / 3).c_str()); rootItem->setText(4, ""); rootItem->setExpanded(true); - rootItem->setIcon(0, *mCharacterIcon); + rootItem->setIcon(0, *m_characterIcon); QString whatsthis = AZStd::to_string(actorInstance->GetID()).c_str(); rootItem->setWhatsThis(0, whatsthis); - mHierarchy->addTopLevelItem(rootItem); + m_hierarchy->addTopLevelItem(rootItem); // get the number of root nodes and iterate through them const size_t numRootNodes = actor->GetSkeleton()->GetNumRootNodes(); @@ -264,7 +264,7 @@ namespace EMStudio AZStd::to_lower(nodeName.begin(), nodeName.end()); EMotionFX::Mesh* mesh = actorInstance->GetActor()->GetMesh(actorInstance->GetLODLevel(), nodeIndex); const bool isMeshNode = (mesh); - const bool isBone = (AZStd::find(begin(mBoneList), end(mBoneList), nodeIndex) != end(mBoneList)); + const bool isBone = (AZStd::find(begin(m_boneList), end(m_boneList), nodeIndex) != end(m_boneList)); const bool isNode = (isMeshNode == false && isBone == false); return CheckIfNodeVisible(nodeName, isMeshNode, isBone, isNode); @@ -293,7 +293,7 @@ namespace EMStudio const size_t numChildren = node->GetNumChildNodes(); EMotionFX::Mesh* mesh = actor->GetMesh(actorInstance->GetLODLevel(), nodeIndex); const bool isMeshNode = (mesh); - const bool isBone = (AZStd::find(begin(mBoneList), end(mBoneList), nodeIndex) != end(mBoneList)); + const bool isBone = (AZStd::find(begin(m_boneList), end(m_boneList), nodeIndex) != end(m_boneList)); const bool isNode = (isMeshNode == false && isBone == false); if (CheckIfNodeVisible(nodeName, isMeshNode, isBone, isNode)) @@ -314,18 +314,18 @@ namespace EMStudio // set the correct icon and the type if (isMeshNode) { - item->setIcon(0, *mMeshIcon); + item->setIcon(0, *m_meshIcon); item->setText(1, "Mesh"); item->setText(3, QString::number(mesh->GetNumIndices() / 3)); } else if (isBone) { - item->setIcon(0, *mBoneIcon); + item->setIcon(0, *m_boneIcon); item->setText(1, "Bone"); } else if (isNode) { - item->setIcon(0, *mNodeIcon); + item->setIcon(0, *m_nodeIcon); item->setText(1, "Node"); } else @@ -336,13 +336,13 @@ namespace EMStudio // the mirrored node const bool hasMirrorInfo = actor->GetHasMirrorInfo(); - if (hasMirrorInfo == false || actor->GetNodeMirrorInfo(nodeIndex).mSourceNode == MCORE_INVALIDINDEX16 || actor->GetNodeMirrorInfo(nodeIndex).mSourceNode == nodeIndex) + if (hasMirrorInfo == false || actor->GetNodeMirrorInfo(nodeIndex).m_sourceNode == MCORE_INVALIDINDEX16 || actor->GetNodeMirrorInfo(nodeIndex).m_sourceNode == nodeIndex) { item->setText(4, ""); } else { - item->setText(4, actor->GetSkeleton()->GetNode(actor->GetNodeMirrorInfo(nodeIndex).mSourceNode)->GetName()); + item->setText(4, actor->GetSkeleton()->GetNode(actor->GetNodeMirrorInfo(nodeIndex).m_sourceNode)->GetName()); } parent->addChild(item); @@ -384,7 +384,7 @@ namespace EMStudio for (size_t i = 0; i < m_selectedNodes.size(); ) { // check if this is our node, if yes remove it - if (nodeNameID == m_selectedNodes[i].mNodeNameID && actorInstanceID == m_selectedNodes[i].mActorInstanceID) + if (nodeNameID == m_selectedNodes[i].m_nodeNameId && actorInstanceID == m_selectedNodes[i].m_actorInstanceId) { m_selectedNodes.erase(m_selectedNodes.begin() + i); //LOG("Removing: %s", nodeName); @@ -405,7 +405,7 @@ namespace EMStudio for (size_t i = 0; i < m_selectedNodes.size(); ) { // check if this is our node, if yes remove it - if (emptyStringID == m_selectedNodes[i].mNodeNameID && actorInstanceID == m_selectedNodes[i].mActorInstanceID) + if (emptyStringID == m_selectedNodes[i].m_nodeNameId && actorInstanceID == m_selectedNodes[i].m_actorInstanceId) { m_selectedNodes.erase(m_selectedNodes.begin() + i); //LOG("Removing: %s", nodeName); @@ -430,13 +430,13 @@ namespace EMStudio // Make sure this node is not already in our selection list for (const SelectionItem& selectedItem : m_selectedNodes) { - if (item.mNodeNameID == selectedItem.mNodeNameID && item.mActorInstanceID == selectedItem.mActorInstanceID) + if (item.m_nodeNameId == selectedItem.m_nodeNameId && item.m_actorInstanceId == selectedItem.m_actorInstanceId) { return; } } - if (mUseSingleSelection) + if (m_useSingleSelection) { m_selectedNodes.clear(); } @@ -452,9 +452,9 @@ namespace EMStudio if (item->isSelected() == false) { // get the actor instance id to which this item belongs to - mActorInstanceIDString = FromQtString(item->whatsThis(0)); + m_actorInstanceIdString = FromQtString(item->whatsThis(0)); int actorInstanceID; - const bool validConversion = AzFramework::StringFunc::LooksLikeInt(mActorInstanceIDString.c_str(), &actorInstanceID); + const bool validConversion = AzFramework::StringFunc::LooksLikeInt(m_actorInstanceIdString.c_str(), &actorInstanceID); MCORE_ASSERT(validConversion); // remove the node from the selected nodes @@ -480,24 +480,24 @@ namespace EMStudio void NodeHierarchyWidget::UpdateSelection() { // get the selected items and the number of them - QList selectedItems = mHierarchy->selectedItems(); + QList selectedItems = m_hierarchy->selectedItems(); // remove the unselected tree widget items from the selected nodes - const int numTopLevelItems = mHierarchy->topLevelItemCount(); + const int numTopLevelItems = m_hierarchy->topLevelItemCount(); for (int i = 0; i < numTopLevelItems; ++i) { - RecursiveRemoveUnselectedItems(mHierarchy->topLevelItem(i)); + RecursiveRemoveUnselectedItems(m_hierarchy->topLevelItem(i)); } // iterate through all selected items for (const QTreeWidgetItem* item : selectedItems) { // get the item name - FromQtString(item->text(0), &mItemName); - FromQtString(item->whatsThis(0), &mActorInstanceIDString); + FromQtString(item->text(0), &m_itemName); + FromQtString(item->whatsThis(0), &m_actorInstanceIdString); int actorInstanceID; - const bool validConversion = AzFramework::StringFunc::LooksLikeInt(mActorInstanceIDString.c_str(), &actorInstanceID); + const bool validConversion = AzFramework::StringFunc::LooksLikeInt(m_actorInstanceIdString.c_str(), &actorInstanceID); MCORE_ASSERT(validConversion); EMotionFX::ActorInstance* actorInstance = EMotionFX::GetActorManager().FindActorInstanceByID(actorInstanceID); @@ -509,9 +509,9 @@ namespace EMStudio // check if the item name is actually a valid node EMotionFX::Actor* actor = actorInstance->GetActor(); - if (actor->GetSkeleton()->FindNodeByName(mItemName.c_str())) + if (actor->GetSkeleton()->FindNodeByName(m_itemName.c_str())) { - AddNodeToSelectedNodes(mItemName.c_str(), actorInstanceID); + AddNodeToSelectedNodes(m_itemName.c_str(), actorInstanceID); } // check if we are dealing with an actor instance @@ -528,14 +528,14 @@ namespace EMStudio { if (useSingleSelection) { - mHierarchy->setSelectionMode(QAbstractItemView::SingleSelection); + m_hierarchy->setSelectionMode(QAbstractItemView::SingleSelection); } else { - mHierarchy->setSelectionMode(QAbstractItemView::ExtendedSelection); + m_hierarchy->setSelectionMode(QAbstractItemView::ExtendedSelection); } - mUseSingleSelection = useSingleSelection; + m_useSingleSelection = useSingleSelection; } @@ -571,7 +571,7 @@ namespace EMStudio menu.addAction("Add all towards root to selection"); AZStd::vector itemsToAdd; - if (menu.exec(mHierarchy->mapToGlobal(pos))) + if (menu.exec(m_hierarchy->mapToGlobal(pos))) { // Collect the list of items to select. Actual adding to the // selection has to happen in a separate loop so that the iterators @@ -581,7 +581,7 @@ namespace EMStudio // Ensure the actor instance is still valid before looking at // its skeleton const EMotionFX::ActorInstance* actorInstance = - EMotionFX::GetActorManager().FindActorInstanceByID(selectedItem.mActorInstanceID); + EMotionFX::GetActorManager().FindActorInstanceByID(selectedItem.m_actorInstanceId); if (!actorInstance) { continue; @@ -592,7 +592,7 @@ namespace EMStudio actorInstance->GetActor()->GetSkeleton()->FindNodeByName(selectedItem.GetNodeName()); for(; parentNode; parentNode = parentNode->GetParentNode()) { - itemsToAdd.emplace_back(selectedItem.mActorInstanceID, parentNode->GetName()); + itemsToAdd.emplace_back(selectedItem.m_actorInstanceId, parentNode->GetName()); } } @@ -607,7 +607,6 @@ namespace EMStudio void NodeHierarchyWidget::OnTextFilterChanged(const QString& text) { - //mFindString = String(text.toAscii().data()).Lowered(); FromQtString(text, &m_searchWidgetText); AZStd::to_lower(m_searchWidgetText.begin(), m_searchWidgetText.end()); Update(); @@ -632,7 +631,7 @@ namespace EMStudio { return AZStd::any_of(begin(m_selectedNodes), end(m_selectedNodes), [nodeName, actorInstanceID](const SelectionItem& selectedItem) { - return selectedItem.mActorInstanceID == actorInstanceID && selectedItem.GetNodeNameString() == nodeName; + return selectedItem.m_actorInstanceId == actorInstanceID && selectedItem.GetNodeNameString() == nodeName; }); } @@ -642,7 +641,7 @@ namespace EMStudio { return AZStd::any_of(begin(m_selectedNodes), end(m_selectedNodes), [actorInstanceID](const SelectionItem& selectedItem) { - return selectedItem.mActorInstanceID == actorInstanceID && selectedItem.GetNodeNameString().empty(); + return selectedItem.m_actorInstanceId == actorInstanceID && selectedItem.GetNodeNameString().empty(); }); } @@ -659,7 +658,7 @@ namespace EMStudio m_selectedNodes.clear(); // get the number actor instances and iterate over them - for (const uint32 actorInstanceID : mActorInstanceIDs) + for (const uint32 actorInstanceID : m_actorInstanceIDs) { // add the actor to the node hierarchy widget // get the number of selected nodes and iterate through them @@ -670,7 +669,7 @@ namespace EMStudio if (joint) { SelectionItem selectionItem; - selectionItem.mActorInstanceID = actorInstanceID; + selectionItem.m_actorInstanceId = actorInstanceID; selectionItem.SetNodeName(joint->GetName()); m_selectedNodes.emplace_back(selectionItem); } @@ -681,19 +680,19 @@ namespace EMStudio bool NodeHierarchyWidget::GetDisplayMeshes() const { - return mFilterState.testFlag(FilterType::Meshes); + return m_filterState.testFlag(FilterType::Meshes); } bool NodeHierarchyWidget::GetDisplayNodes() const { - return mFilterState.testFlag(FilterType::Nodes); + return m_filterState.testFlag(FilterType::Nodes); } bool NodeHierarchyWidget::GetDisplayBones() const { - return mFilterState.testFlag(FilterType::Bones); + return m_filterState.testFlag(FilterType::Bones); } } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NodeHierarchyWidget.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NodeHierarchyWidget.h index e4dd215819..c566be6005 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NodeHierarchyWidget.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NodeHierarchyWidget.h @@ -30,26 +30,26 @@ namespace AzQtComponents struct EMSTUDIO_API SelectionItem { - uint32 mActorInstanceID; - uint32 mNodeNameID; - uint32 mMorphTargetID; + uint32 m_actorInstanceId; + uint32 m_nodeNameId; + uint32 m_morphTargetId; SelectionItem() { - mActorInstanceID = MCORE_INVALIDINDEX32; - mNodeNameID = MCORE_INVALIDINDEX32; - mMorphTargetID = MCORE_INVALIDINDEX32; + m_actorInstanceId = MCORE_INVALIDINDEX32; + m_nodeNameId = MCORE_INVALIDINDEX32; + m_morphTargetId = MCORE_INVALIDINDEX32; } SelectionItem(const uint32 actorInstanceID, const char* nodeName, const uint32 morphTargetID = MCORE_INVALIDINDEX32) - : mActorInstanceID(actorInstanceID), mMorphTargetID(morphTargetID) + : m_actorInstanceId(actorInstanceID), m_morphTargetId(morphTargetID) { SetNodeName(nodeName); } - void SetNodeName(const char* nodeName) { mNodeNameID = MCore::GetStringIdPool().GenerateIdForString(nodeName); } - const char* GetNodeName() const { return MCore::GetStringIdPool().GetName(mNodeNameID).c_str(); } - const AZStd::string& GetNodeNameString() const { return MCore::GetStringIdPool().GetName(mNodeNameID); } + void SetNodeName(const char* nodeName) { m_nodeNameId = MCore::GetStringIdPool().GenerateIdForString(nodeName); } + const char* GetNodeName() const { return MCore::GetStringIdPool().GetName(m_nodeNameId).c_str(); } + const AZStd::string& GetNodeNameString() const { return MCore::GetStringIdPool().GetName(m_nodeNameId); } EMotionFX::Node* GetNode() const; }; @@ -70,7 +70,7 @@ namespace EMStudio void Update(uint32 actorInstanceID, CommandSystem::SelectionList* selectionList = nullptr); void Update(const AZStd::vector& actorInstanceIDs, CommandSystem::SelectionList* selectionList = nullptr); void FireSelectionDoneSignal(); - MCORE_INLINE QTreeWidget* GetTreeWidget() { return mHierarchy; } + MCORE_INLINE QTreeWidget* GetTreeWidget() { return m_hierarchy; } MCORE_INLINE AzQtComponents::FilteredSearchWidget* GetSearchWidget() { return m_searchWidget; } // is node shown in the hierarchy widget? @@ -126,18 +126,18 @@ namespace EMStudio void RecursiveRemoveUnselectedItems(QTreeWidgetItem* item); AZStd::vector m_selectedNodes; - QTreeWidget* mHierarchy; + QTreeWidget* m_hierarchy; AzQtComponents::FilteredSearchWidget* m_searchWidget; AZStd::string m_searchWidgetText; - QIcon* mBoneIcon; - QIcon* mNodeIcon; - QIcon* mMeshIcon; - QIcon* mCharacterIcon; - AZStd::vector mBoneList; - AZStd::vector mActorInstanceIDs; - AZStd::string mItemName; - AZStd::string mActorInstanceIDString; - bool mUseSingleSelection; - FilterTypes mFilterState; + QIcon* m_boneIcon; + QIcon* m_nodeIcon; + QIcon* m_meshIcon; + QIcon* m_characterIcon; + AZStd::vector m_boneList; + AZStd::vector m_actorInstanceIDs; + AZStd::string m_itemName; + AZStd::string m_actorInstanceIdString; + bool m_useSingleSelection; + FilterTypes m_filterState; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NodeSelectionWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NodeSelectionWindow.cpp index e0d562ee0f..3458a44de1 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NodeSelectionWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NodeSelectionWindow.cpp @@ -28,35 +28,35 @@ namespace EMStudio NodeSelectionWindow::NodeSelectionWindow(QWidget* parent, bool useSingleSelection) : QDialog(parent) { - mAccepted = false; + m_accepted = false; setWindowTitle("Node Selection Window"); QVBoxLayout* layout = new QVBoxLayout(); - mHierarchyWidget = new NodeHierarchyWidget(this, useSingleSelection); + m_hierarchyWidget = new NodeHierarchyWidget(this, useSingleSelection); // create the ok and cancel buttons QHBoxLayout* buttonLayout = new QHBoxLayout(); - mOKButton = new QPushButton("OK"); - mCancelButton = new QPushButton("Cancel"); - buttonLayout->addWidget(mOKButton); - buttonLayout->addWidget(mCancelButton); + m_okButton = new QPushButton("OK"); + m_cancelButton = new QPushButton("Cancel"); + buttonLayout->addWidget(m_okButton); + buttonLayout->addWidget(m_cancelButton); - layout->addWidget(mHierarchyWidget); + layout->addWidget(m_hierarchyWidget); layout->addLayout(buttonLayout); setLayout(layout); - connect(mOKButton, &QPushButton::clicked, this, &NodeSelectionWindow::accept); - connect(mCancelButton, &QPushButton::clicked, this, &NodeSelectionWindow::reject); + connect(m_okButton, &QPushButton::clicked, this, &NodeSelectionWindow::accept); + connect(m_cancelButton, &QPushButton::clicked, this, &NodeSelectionWindow::reject); connect(this, &NodeSelectionWindow::accepted, this, &NodeSelectionWindow::OnAccept); - connect(mHierarchyWidget, static_cast)>(&NodeHierarchyWidget::OnDoubleClicked), this, &NodeSelectionWindow::OnDoubleClicked); + connect(m_hierarchyWidget, static_cast)>(&NodeHierarchyWidget::OnDoubleClicked), this, &NodeSelectionWindow::OnDoubleClicked); // connect the window activation signal to refresh if reactivated //connect( this, SIGNAL(visibilityChanged(bool)), this, SLOT(OnVisibilityChanged(bool)) ); // set the selection mode - mHierarchyWidget->SetSelectionMode(useSingleSelection); - mUseSingleSelection = useSingleSelection; + m_hierarchyWidget->SetSelectionMode(useSingleSelection); + m_useSingleSelection = useSingleSelection; setMinimumSize(QSize(500, 400)); resize(700, 800); @@ -72,7 +72,7 @@ namespace EMStudio void NodeSelectionWindow::OnAccept() { - mHierarchyWidget->FireSelectionDoneSignal(); + m_hierarchyWidget->FireSelectionDoneSignal(); } } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NodeSelectionWindow.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NodeSelectionWindow.h index 46eabf7b58..df6f0195bc 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NodeSelectionWindow.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NodeSelectionWindow.h @@ -28,9 +28,9 @@ namespace EMStudio * 2. Use the itemSelectionChanged() signal of the GetNodeHierarchyWidget()->GetTreeWidget() to detect when the user adjusts the selection in the node hierarchy widget. * 3. Use the OnSelectionDone() in the GetNodeHierarchyWidget() to detect when the user finished selecting and pressed the OK button. * Example: - * connect( mNodeSelectionWindow, SIGNAL(rejected()), this, SLOT(UserWantsToCancel_1()) ); - * connect( mNodeSelectionWindow->GetNodeHierarchyWidget()->GetTreeWidget(), SIGNAL(itemSelectionChanged()), this, SLOT(SelectionChanged_2()) ); - * connect( mNodeSelectionWindow->GetNodeHierarchyWidget(), SIGNAL(OnSelectionDone(AZStd::vector)), this, SLOT(FinishedSelectionAndPressedOK_3(AZStd::vector)) ); + * connect( m_nodeSelectionWindow, SIGNAL(rejected()), this, SLOT(UserWantsToCancel_1()) ); + * connect( m_nodeSelectionWindow->GetNodeHierarchyWidget()->GetTreeWidget(), SIGNAL(itemSelectionChanged()), this, SLOT(SelectionChanged_2()) ); + * connect( m_nodeSelectionWindow->GetNodeHierarchyWidget(), SIGNAL(OnSelectionDone(AZStd::vector)), this, SLOT(FinishedSelectionAndPressedOK_3(AZStd::vector)) ); */ class EMSTUDIO_API NodeSelectionWindow : public QDialog @@ -41,20 +41,20 @@ namespace EMStudio public: NodeSelectionWindow(QWidget* parent, bool useSingleSelection); - MCORE_INLINE NodeHierarchyWidget* GetNodeHierarchyWidget() { return mHierarchyWidget; } - void Update(uint32 actorInstanceID, CommandSystem::SelectionList* selectionList = nullptr) { mHierarchyWidget->Update(actorInstanceID, selectionList); } - void Update(const AZStd::vector& actorInstanceIDs, CommandSystem::SelectionList* selectionList = nullptr) { mHierarchyWidget->Update(actorInstanceIDs, selectionList); } + MCORE_INLINE NodeHierarchyWidget* GetNodeHierarchyWidget() { return m_hierarchyWidget; } + void Update(uint32 actorInstanceID, CommandSystem::SelectionList* selectionList = nullptr) { m_hierarchyWidget->Update(actorInstanceID, selectionList); } + void Update(const AZStd::vector& actorInstanceIDs, CommandSystem::SelectionList* selectionList = nullptr) { m_hierarchyWidget->Update(actorInstanceIDs, selectionList); } public slots: void OnAccept(); void OnDoubleClicked(AZStd::vector selection); private: - NodeHierarchyWidget* mHierarchyWidget; - QPushButton* mOKButton; - QPushButton* mCancelButton; - bool mUseSingleSelection; - bool mAccepted; + NodeHierarchyWidget* m_hierarchyWidget; + QPushButton* m_okButton; + QPushButton* m_cancelButton; + bool m_useSingleSelection; + bool m_accepted; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NotificationWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NotificationWindow.cpp index c1316878c8..0b277c6195 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NotificationWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NotificationWindow.cpp @@ -22,7 +22,7 @@ namespace EMStudio : QWidget(parent) { // set the opacity - mOpacity = 210; + m_opacity = 210; // set the window title setWindowTitle("Notification"); @@ -40,42 +40,42 @@ namespace EMStudio setFixedWidth(300); // create the icon - mIcon = new QToolButton(); - mIcon->setObjectName("NotificationIcon"); - mIcon->setStyleSheet("#NotificationIcon{ background-color: transparent; border: none; }"); - mIcon->setIconSize(QSize(22, 22)); - mIcon->setFocusPolicy(Qt::NoFocus); + m_icon = new QToolButton(); + m_icon->setObjectName("NotificationIcon"); + m_icon->setStyleSheet("#NotificationIcon{ background-color: transparent; border: none; }"); + m_icon->setIconSize(QSize(22, 22)); + m_icon->setFocusPolicy(Qt::NoFocus); if (type == TYPE_ERROR) { - mIcon->setIcon(MysticQt::GetMysticQt()->FindIcon("Images/Icons/ExclamationMark.svg")); + m_icon->setIcon(MysticQt::GetMysticQt()->FindIcon("Images/Icons/ExclamationMark.svg")); } else if (type == TYPE_WARNING) { - mIcon->setIcon(MysticQt::GetMysticQt()->FindIcon("Images/Icons/Warning.svg")); + m_icon->setIcon(MysticQt::GetMysticQt()->FindIcon("Images/Icons/Warning.svg")); } else if (type == TYPE_SUCCESS) { - mIcon->setIcon(MysticQt::GetMysticQt()->FindIcon("Images/Icons/Confirm.svg")); + m_icon->setIcon(MysticQt::GetMysticQt()->FindIcon("Images/Icons/Confirm.svg")); } - connect(mIcon, &QToolButton::pressed, this, &NotificationWindow::IconPressed); + connect(m_icon, &QToolButton::pressed, this, &NotificationWindow::IconPressed); // create the message label - mMessageLabel = new QLabel(Message); - mMessageLabel->setWordWrap(true); + m_messageLabel = new QLabel(Message); + m_messageLabel->setWordWrap(true); // create the layout QHBoxLayout* layout = new QHBoxLayout(); - layout->addWidget(mIcon); - layout->addWidget(mMessageLabel); + layout->addWidget(m_icon); + layout->addWidget(m_messageLabel); // set the layout setLayout(layout); // start the timer - mTimer = new QTimer(this); - mTimer->setSingleShot(true); - connect(mTimer, &QTimer::timeout, this, &NotificationWindow::TimerTimeOut); - mTimer->start(GetNotificationWindowManager()->GetVisibleTime() * 1000); + m_timer = new QTimer(this); + m_timer->setSingleShot(true); + connect(m_timer, &QTimer::timeout, this, &NotificationWindow::TimerTimeOut); + m_timer->start(GetNotificationWindowManager()->GetVisibleTime() * 1000); } NotificationWindow::~NotificationWindow() @@ -91,7 +91,7 @@ namespace EMStudio MCORE_UNUSED(event); QPainter p(this); p.setPen(Qt::transparent); - p.setBrush(QColor(0, 0, 0, mOpacity)); + p.setBrush(QColor(0, 0, 0, m_opacity)); p.setRenderHint(QPainter::Antialiasing); p.drawRoundedRect(rect(), 10, 10); } @@ -109,13 +109,13 @@ namespace EMStudio void NotificationWindow::mousePressEvent(QMouseEvent* event) { // we only want the left button, stop here if the timer is not active too - if ((mTimer->isActive() == false) || (event->button() != Qt::LeftButton)) + if ((m_timer->isActive() == false) || (event->button() != Qt::LeftButton)) { return; } // stop the timer because the event will be called before - mTimer->stop(); + m_timer->stop(); // call the timer time out function TimerTimeOut(); @@ -126,13 +126,13 @@ namespace EMStudio void NotificationWindow::IconPressed() { // stop here if the timer is not active - if (mTimer->isActive() == false) + if (m_timer->isActive() == false) { return; } // stop the timer because the event will be called before - mTimer->stop(); + m_timer->stop(); // call the timer time out function TimerTimeOut(); @@ -144,24 +144,24 @@ namespace EMStudio { // create the opacity effect and set it on the icon QGraphicsOpacityEffect* iconOpacityEffect = new QGraphicsOpacityEffect(this); - mIcon->setGraphicsEffect(iconOpacityEffect); + m_icon->setGraphicsEffect(iconOpacityEffect); // create the property animation to control the property value QPropertyAnimation* iconPropertyAnimation = new QPropertyAnimation(iconOpacityEffect, "opacity"); iconPropertyAnimation->setDuration(500); - iconPropertyAnimation->setStartValue((double)mOpacity / 255.0); + iconPropertyAnimation->setStartValue((double)m_opacity / 255.0); iconPropertyAnimation->setEndValue(0.0); iconPropertyAnimation->setEasingCurve(QEasingCurve::Linear); iconPropertyAnimation->start(QPropertyAnimation::DeleteWhenStopped); // create the opacity effect and set it on the label QGraphicsOpacityEffect* labelOpacityEffect = new QGraphicsOpacityEffect(this); - mMessageLabel->setGraphicsEffect(labelOpacityEffect); + m_messageLabel->setGraphicsEffect(labelOpacityEffect); // create the property animation to control the property value QPropertyAnimation* labelPropertyAnimation = new QPropertyAnimation(labelOpacityEffect, "opacity"); labelPropertyAnimation->setDuration(500); - labelPropertyAnimation->setStartValue((double)mOpacity / 255.0); + labelPropertyAnimation->setStartValue((double)m_opacity / 255.0); labelPropertyAnimation->setEndValue(0.0); labelPropertyAnimation->setEasingCurve(QEasingCurve::Linear); labelPropertyAnimation->start(QPropertyAnimation::DeleteWhenStopped); @@ -176,7 +176,7 @@ namespace EMStudio void NotificationWindow::OpacityChanged(qreal opacity) { // set the new opacity for the paint of the window - mOpacity = aznumeric_cast(opacity * 255); + m_opacity = aznumeric_cast(opacity * 255); // update the window update(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NotificationWindow.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NotificationWindow.h index b4dfb70ef1..72a53cafdf 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NotificationWindow.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NotificationWindow.h @@ -50,9 +50,9 @@ namespace EMStudio void FadeOutFinished(); private: - QLabel* mMessageLabel; - QToolButton* mIcon; - QTimer* mTimer; - int mOpacity; + QLabel* m_messageLabel; + QToolButton* m_icon; + QTimer* m_timer; + int m_opacity; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NotificationWindowManager.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NotificationWindowManager.cpp index e1c22ee60d..8b651314ca 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NotificationWindowManager.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NotificationWindowManager.cpp @@ -33,7 +33,7 @@ namespace EMStudio // compute the height of all notification windows with the spacing int allNotificationWindowsHeight = 0; - for (const NotificationWindow* currentNotificationWindow : mNotificationWindows) + for (const NotificationWindow* currentNotificationWindow : m_notificationWindows) { allNotificationWindowsHeight += currentNotificationWindow->geometry().height() + notificationWindowSpacing; } @@ -44,7 +44,7 @@ namespace EMStudio notificationWindow->move(mainWindowBottomRight.x() - notificationWindowGeometry.width() - notificationWindowMainWindowPadding, mainWindowBottomRight.y() - allNotificationWindowsHeight - notificationWindowGeometry.height() - notificationWindowMainWindowPadding); // add the notification window in the array - mNotificationWindows.emplace_back(notificationWindow); + m_notificationWindows.emplace_back(notificationWindow); } @@ -52,24 +52,24 @@ namespace EMStudio void NotificationWindowManager::RemoveNotificationWindow(NotificationWindow* notificationWindow) { // find the notification window - auto windowIt = AZStd::find(begin(mNotificationWindows), end(mNotificationWindows), notificationWindow); + auto windowIt = AZStd::find(begin(m_notificationWindows), end(m_notificationWindows), notificationWindow); // if not found, stop here - if (windowIt == end(mNotificationWindows)) + if (windowIt == end(m_notificationWindows)) { return; } // move down each notification window after this one, spacing is added on the height const int notificationWindowHeight = notificationWindow->geometry().height() + notificationWindowSpacing; - for (auto it = windowIt + 1; it != end(mNotificationWindows); ++it) + for (auto it = windowIt + 1; it != end(m_notificationWindows); ++it) { const QPoint pos = (*it)->pos(); (*it)->move(pos.x(), pos.y() + notificationWindowHeight); } // remove the notification window - mNotificationWindows.erase(windowIt); + m_notificationWindows.erase(windowIt); } @@ -81,7 +81,7 @@ namespace EMStudio // move each notification window int currentNotificationWindowHeight = notificationWindowMainWindowPadding; - for (NotificationWindow* notificationWindow : mNotificationWindows) + for (NotificationWindow* notificationWindow : m_notificationWindows) { // add the height of the notification window currentNotificationWindowHeight += notificationWindow->geometry().height(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NotificationWindowManager.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NotificationWindowManager.h index 8817f3d451..4724b4ba54 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NotificationWindowManager.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NotificationWindowManager.h @@ -24,7 +24,7 @@ namespace EMStudio public: MCORE_INLINE NotificationWindowManager() { - mVisibleTime = 5; + m_visibleTime = 5; } void CreateNotificationWindow(NotificationWindow::EType type, const QString& message); @@ -32,28 +32,28 @@ namespace EMStudio MCORE_INLINE NotificationWindow* GetNotificationWindow(uint32 index) const { - return mNotificationWindows[index]; + return m_notificationWindows[index]; } MCORE_INLINE size_t GetNumNotificationWindow() const { - return mNotificationWindows.size(); + return m_notificationWindows.size(); } void OnMovedOrResized(); MCORE_INLINE void SetVisibleTime(int32 timeSeconds) { - mVisibleTime = timeSeconds; + m_visibleTime = timeSeconds; } MCORE_INLINE int32 GetVisibleTime() const { - return mVisibleTime; + return m_visibleTime; } private: - AZStd::vector mNotificationWindows; - int32 mVisibleTime; + AZStd::vector m_notificationWindows; + int32 m_visibleTime; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/PluginManager.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/PluginManager.cpp index d0e8730e52..fde4336a49 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/PluginManager.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/PluginManager.cpp @@ -34,8 +34,8 @@ namespace EMStudio // constructor PluginManager::PluginManager() { - mActivePlugins.reserve(50); - mPlugins.reserve(50); + m_activePlugins.reserve(50); + m_plugins.reserve(50); } @@ -50,19 +50,19 @@ namespace EMStudio // remove a given active plugin void PluginManager::RemoveActivePlugin(EMStudioPlugin* plugin) { - PluginVector::const_iterator itPlugin = AZStd::find(mActivePlugins.begin(), mActivePlugins.end(), plugin); - if (itPlugin == mActivePlugins.end()) + PluginVector::const_iterator itPlugin = AZStd::find(m_activePlugins.begin(), m_activePlugins.end(), plugin); + if (itPlugin == m_activePlugins.end()) { MCore::LogWarning("Failed to remove plugin '%s'", plugin->GetName()); return; } - for (EMStudioPlugin* activePlugin : mActivePlugins) + for (EMStudioPlugin* activePlugin : m_activePlugins) { activePlugin->OnBeforeRemovePlugin(plugin->GetClassID()); } - mActivePlugins.erase(itPlugin); + m_activePlugins.erase(itPlugin); delete plugin; } @@ -74,22 +74,22 @@ namespace EMStudio QApplication::processEvents(); // delete all plugins - for (EMStudioPlugin* plugin : mPlugins) + for (EMStudioPlugin* plugin : m_plugins) { delete plugin; } - mPlugins.clear(); + m_plugins.clear(); // delete all active plugins - for (auto plugin = mActivePlugins.rbegin(); plugin != mActivePlugins.rend(); ++plugin) + for (auto plugin = m_activePlugins.rbegin(); plugin != m_activePlugins.rend(); ++plugin) { - for (EMStudioPlugin* pluginToNotify : mActivePlugins) + for (EMStudioPlugin* pluginToNotify : m_activePlugins) { pluginToNotify->OnBeforeRemovePlugin((*plugin)->GetClassID()); } delete *plugin; - mActivePlugins.pop_back(); + m_activePlugins.pop_back(); } } @@ -97,7 +97,7 @@ namespace EMStudio // register the plugin void PluginManager::RegisterPlugin(EMStudioPlugin* plugin) { - mPlugins.push_back(plugin); + m_plugins.push_back(plugin); } @@ -112,7 +112,7 @@ namespace EMStudio } // create the new plugin of this type - EMStudioPlugin* newPlugin = mPlugins[ pluginIndex ]->Clone(); + EMStudioPlugin* newPlugin = m_plugins[ pluginIndex ]->Clone(); // init the plugin newPlugin->CreateBaseInterface(objectName); @@ -120,7 +120,7 @@ namespace EMStudio // register as active plugin. This has to be done at this point since // the initialization could try to access the plugin and assume that // is active. - mActivePlugins.push_back(newPlugin); + m_activePlugins.push_back(newPlugin); newPlugin->Init(); @@ -131,20 +131,20 @@ namespace EMStudio // find a given plugin by its name (type string) size_t PluginManager::FindPluginByTypeString(const char* pluginType) const { - const auto foundPlugin = AZStd::find_if(begin(mPlugins), end(mPlugins), [pluginType](const EMStudioPlugin* plugin) + const auto foundPlugin = AZStd::find_if(begin(m_plugins), end(m_plugins), [pluginType](const EMStudioPlugin* plugin) { return AzFramework::StringFunc::Equal(pluginType, plugin->GetName()); }); - return foundPlugin != end(mPlugins) ? AZStd::distance(begin(mPlugins), foundPlugin) : InvalidIndex; + return foundPlugin != end(m_plugins) ? AZStd::distance(begin(m_plugins), foundPlugin) : InvalidIndex; } EMStudioPlugin* PluginManager::GetActivePluginByTypeString(const char* pluginType) const { - const auto foundPlugin = AZStd::find_if(begin(mActivePlugins), end(mActivePlugins), [pluginType](const EMStudioPlugin* plugin) + const auto foundPlugin = AZStd::find_if(begin(m_activePlugins), end(m_activePlugins), [pluginType](const EMStudioPlugin* plugin) { return AzFramework::StringFunc::Equal(pluginType, plugin->GetName()); }); - return foundPlugin != end(mActivePlugins) ? *foundPlugin : nullptr; + return foundPlugin != end(m_activePlugins) ? *foundPlugin : nullptr; } // generate a unique object name @@ -166,7 +166,7 @@ namespace EMStudio ); // check if we have a conflict with a current plugin - const bool hasConflict = AZStd::any_of(begin(mActivePlugins), end(mActivePlugins), [&randomString](EMStudioPlugin* plugin) + const bool hasConflict = AZStd::any_of(begin(m_activePlugins), end(m_activePlugins), [&randomString](EMStudioPlugin* plugin) { return plugin->GetHasWindowWithObjectName(randomString); }); @@ -181,7 +181,7 @@ namespace EMStudio // find the number of active plugins of a given type size_t PluginManager::GetNumActivePluginsOfType(const char* pluginType) const { - return AZStd::accumulate(mActivePlugins.begin(), mActivePlugins.end(), size_t{0}, [pluginType](size_t total, const EMStudioPlugin* plugin) + return AZStd::accumulate(m_activePlugins.begin(), m_activePlugins.end(), size_t{0}, [pluginType](size_t total, const EMStudioPlugin* plugin) { return total + AzFramework::StringFunc::Equal(pluginType, plugin->GetName()); }); @@ -191,11 +191,11 @@ namespace EMStudio // find the first active plugin of a given type EMStudioPlugin* PluginManager::FindActivePlugin(uint32 classID) const { - const auto foundPlugin = AZStd::find_if(begin(mActivePlugins), end(mActivePlugins), [classID](const EMStudioPlugin* plugin) + const auto foundPlugin = AZStd::find_if(begin(m_activePlugins), end(m_activePlugins), [classID](const EMStudioPlugin* plugin) { return plugin->GetClassID() == classID; }); - return foundPlugin != end(mActivePlugins) ? *foundPlugin : nullptr; + return foundPlugin != end(m_activePlugins) ? *foundPlugin : nullptr; } @@ -203,7 +203,7 @@ namespace EMStudio // find the number of active plugins of a given type size_t PluginManager::GetNumActivePluginsOfType(uint32 classID) const { - return AZStd::accumulate(mActivePlugins.begin(), mActivePlugins.end(), size_t{0}, [classID](size_t total, const EMStudioPlugin* plugin) + return AZStd::accumulate(m_activePlugins.begin(), m_activePlugins.end(), size_t{0}, [classID](size_t total, const EMStudioPlugin* plugin) { return total + (plugin->GetClassID() == classID); }); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/PluginManager.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/PluginManager.h index 2937c3b387..e3a5f9627a 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/PluginManager.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/PluginManager.h @@ -47,12 +47,12 @@ namespace EMStudio } EMStudioPlugin* FindActivePlugin(uint32 classID) const; // find first active plugin, or nullptr when not found - MCORE_INLINE size_t GetNumPlugins() const { return mPlugins.size(); } - MCORE_INLINE EMStudioPlugin* GetPlugin(const size_t index) { return mPlugins[index]; } + MCORE_INLINE size_t GetNumPlugins() const { return m_plugins.size(); } + MCORE_INLINE EMStudioPlugin* GetPlugin(const size_t index) { return m_plugins[index]; } - MCORE_INLINE size_t GetNumActivePlugins() const { return mActivePlugins.size(); } - MCORE_INLINE EMStudioPlugin* GetActivePlugin(const size_t index) { return mActivePlugins[index]; } - MCORE_INLINE const PluginVector& GetActivePlugins() { return mActivePlugins; } + MCORE_INLINE size_t GetNumActivePlugins() const { return m_activePlugins.size(); } + MCORE_INLINE EMStudioPlugin* GetActivePlugin(const size_t index) { return m_activePlugins[index]; } + MCORE_INLINE const PluginVector& GetActivePlugins() { return m_activePlugins; } size_t GetNumActivePluginsOfType(const char* pluginType) const; size_t GetNumActivePluginsOfType(uint32 classID) const; @@ -61,9 +61,9 @@ namespace EMStudio QString GenerateObjectName() const; private: - PluginVector mPlugins; + PluginVector m_plugins; - PluginVector mActivePlugins; + PluginVector m_activePlugins; void UnloadPlugins(); }; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RecoverFilesWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RecoverFilesWindow.cpp index 3c2fe98e06..04104e4acd 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RecoverFilesWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RecoverFilesWindow.cpp @@ -25,7 +25,7 @@ namespace EMStudio RecoverFilesWindow::RecoverFilesWindow(QWidget* parent, const AZStd::vector& files) : QDialog(parent) { - mFiles = files; + m_files = files; // Update title of the dialog. setWindowTitle("Recover Files"); @@ -39,43 +39,43 @@ namespace EMStudio layout->addWidget(new QLabel("Some files have been corrupted but can be restored. The following files can be recovered:")); // Create the table widget. - mTableWidget = new QTableWidget(); - mTableWidget->setAlternatingRowColors(true); - mTableWidget->setSelectionMode(QAbstractItemView::NoSelection); - mTableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers); - mTableWidget->setMinimumHeight(250); - mTableWidget->setMinimumWidth(600); - mTableWidget->horizontalHeader()->setStretchLastSection(true); - mTableWidget->setCornerButtonEnabled(false); - mTableWidget->setSortingEnabled(false); + m_tableWidget = new QTableWidget(); + m_tableWidget->setAlternatingRowColors(true); + m_tableWidget->setSelectionMode(QAbstractItemView::NoSelection); + m_tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers); + m_tableWidget->setMinimumHeight(250); + m_tableWidget->setMinimumWidth(600); + m_tableWidget->horizontalHeader()->setStretchLastSection(true); + m_tableWidget->setCornerButtonEnabled(false); + m_tableWidget->setSortingEnabled(false); - mTableWidget->setColumnCount(3); + m_tableWidget->setColumnCount(3); // Set the header items. QTableWidgetItem* headerItem = new QTableWidgetItem(""); headerItem->setTextAlignment(Qt::AlignVCenter | Qt::AlignLeft); - mTableWidget->setHorizontalHeaderItem(0, headerItem); + m_tableWidget->setHorizontalHeaderItem(0, headerItem); headerItem = new QTableWidgetItem("Filename"); headerItem->setTextAlignment(Qt::AlignVCenter | Qt::AlignLeft); - mTableWidget->setHorizontalHeaderItem(1, headerItem); + m_tableWidget->setHorizontalHeaderItem(1, headerItem); headerItem = new QTableWidgetItem("Type"); headerItem->setTextAlignment(Qt::AlignVCenter | Qt::AlignLeft); - mTableWidget->setHorizontalHeaderItem(2, headerItem); + m_tableWidget->setHorizontalHeaderItem(2, headerItem); // Set the horizontal header params. - QHeaderView* horizontalHeader = mTableWidget->horizontalHeader(); + QHeaderView* horizontalHeader = m_tableWidget->horizontalHeader(); horizontalHeader->setSectionResizeMode(0, QHeaderView::Fixed); horizontalHeader->setStretchLastSection(true); - mTableWidget->verticalHeader()->hide(); + m_tableWidget->verticalHeader()->hide(); // Set the left column smaller to only fits the checkbox. - mTableWidget->horizontalHeader()->resizeSection(0, 19); + m_tableWidget->horizontalHeader()->resizeSection(0, 19); // Set the row count. const size_t numFiles = files.size(); const int rowCount = static_cast(numFiles); - mTableWidget->setRowCount(rowCount); + m_tableWidget->setRowCount(rowCount); // For each file that might be recovered. AZStd::string backupFilename; @@ -170,22 +170,22 @@ namespace EMStudio itemType->setData(Qt::UserRole, row); // Add table items to the current row. - mTableWidget->setCellWidget(row, 0, checkbox); - mTableWidget->setCellWidget(row, 1, filenameLabel); - mTableWidget->setItem(row, 2, itemType); + m_tableWidget->setCellWidget(row, 0, checkbox); + m_tableWidget->setCellWidget(row, 1, filenameLabel); + m_tableWidget->setItem(row, 2, itemType); - mTableWidget->setRowHeight(row, 21); + m_tableWidget->setRowHeight(row, 21); } - mTableWidget->setSortingEnabled(true); + m_tableWidget->setSortingEnabled(true); // Set the size of the filename column to take the whole space. - mTableWidget->setColumnWidth(1, 894); + m_tableWidget->setColumnWidth(1, 894); // Needed to have the last column stretching correctly. - mTableWidget->setColumnWidth(2, 0); + m_tableWidget->setColumnWidth(2, 0); - layout->addWidget(mTableWidget); + layout->addWidget(m_tableWidget); // Create the warning message. QLabel* warningLabel = new QLabel("Warning: Files that will not be recovered will be deleted"); @@ -265,16 +265,16 @@ namespace EMStudio AZStd::string backupFilename; AZStd::string originalFilename; - const int numRows = mTableWidget->rowCount(); + const int numRows = m_tableWidget->rowCount(); for (int i = 0; i < numRows; ++i) { - QWidget* widget = mTableWidget->cellWidget(i, 0); + QWidget* widget = m_tableWidget->cellWidget(i, 0); QCheckBox* checkbox = static_cast(widget); - QTableWidgetItem* item = mTableWidget->item(i, 2); + QTableWidgetItem* item = m_tableWidget->item(i, 2); const int32 filesIndex = item->data(Qt::UserRole).toInt(); // Get the recover and the backup filenames - const AZStd::string& recoverFilename = mFiles[filesIndex]; + const AZStd::string& recoverFilename = m_files[filesIndex]; backupFilename = recoverFilename; AzFramework::StringFunc::Path::StripExtension(backupFilename); @@ -359,17 +359,17 @@ namespace EMStudio using namespace AZ::IO; FileIOBase* fileIo = FileIOBase::GetInstance(); - const size_t numFiles = mFiles.size(); + const size_t numFiles = m_files.size(); AZStd::string backupFilename; for (size_t i = 0; i < numFiles; ++i) { - backupFilename = mFiles[i]; + backupFilename = m_files[i]; AzFramework::StringFunc::Path::StripExtension(backupFilename); // Remove the recover file. - if (fileIo->Remove(mFiles[i].c_str()) == ResultCode::Error) + if (fileIo->Remove(m_files[i].c_str()) == ResultCode::Error) { - const AZStd::string errorMessage = AZStd::string::format("Cannot delete file '%s'.", mFiles[i].c_str()); + const AZStd::string errorMessage = AZStd::string::format("Cannot delete file '%s'.", m_files[i].c_str()); CommandSystem::GetCommandManager()->AddError(errorMessage); AZ_Error("EMotionFX", false, errorMessage.c_str()); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RecoverFilesWindow.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RecoverFilesWindow.h index f6e25e8ca5..5804db1aa1 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RecoverFilesWindow.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RecoverFilesWindow.h @@ -35,7 +35,7 @@ namespace EMStudio private: AZStd::string GetOriginalFilenameFromRecoverFile(const char* recoverFilename); - QTableWidget* mTableWidget; - AZStd::vector mFiles; + QTableWidget* m_tableWidget; + AZStd::vector m_files; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RemovePluginOnCloseDockWidget.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RemovePluginOnCloseDockWidget.cpp index 1f703b8cfb..8d37c933a4 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RemovePluginOnCloseDockWidget.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RemovePluginOnCloseDockWidget.cpp @@ -15,13 +15,13 @@ namespace EMStudio { RemovePluginOnCloseDockWidget::RemovePluginOnCloseDockWidget(QWidget* parent, const QString& name, EMStudio::EMStudioPlugin* plugin) : AzQtComponents::StyledDockWidget(name, parent) - , mPlugin(plugin) + , m_plugin(plugin) {} void RemovePluginOnCloseDockWidget::closeEvent(QCloseEvent* event) { MCORE_UNUSED(event); - GetPluginManager()->RemoveActivePlugin(mPlugin); + GetPluginManager()->RemoveActivePlugin(m_plugin); GetMainWindow()->UpdateCreateWindowMenu(); } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RemovePluginOnCloseDockWidget.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RemovePluginOnCloseDockWidget.h index 21db2524cc..5a08cd7981 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RemovePluginOnCloseDockWidget.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RemovePluginOnCloseDockWidget.h @@ -28,6 +28,6 @@ namespace EMStudio void closeEvent(QCloseEvent* event) override; private: - EMStudio::EMStudioPlugin* mPlugin; + EMStudio::EMStudioPlugin* m_plugin; }; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/ManipulatorCallbacks.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/ManipulatorCallbacks.cpp index 750de85344..7758ba9163 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/ManipulatorCallbacks.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/ManipulatorCallbacks.cpp @@ -21,20 +21,20 @@ namespace EMStudio ManipulatorCallback::Update(value); // update the position, if actorinstance is still valid - size_t actorInstanceID = EMotionFX::GetActorManager().FindActorInstanceIndex(mActorInstance); + size_t actorInstanceID = EMotionFX::GetActorManager().FindActorInstanceIndex(m_actorInstance); if (actorInstanceID != InvalidIndex) { - mActorInstance->SetLocalSpacePosition(value); + m_actorInstance->SetLocalSpacePosition(value); } } void TranslateManipulatorCallback::UpdateOldValues() { // update the rotation, if actorinstance is still valid - size_t actorInstanceID = EMotionFX::GetActorManager().FindActorInstanceIndex(mActorInstance); + size_t actorInstanceID = EMotionFX::GetActorManager().FindActorInstanceIndex(m_actorInstance); if (actorInstanceID != InvalidIndex) { - mOldValueVec = mActorInstance->GetLocalSpaceTransform().mPosition; + m_oldValueVec = m_actorInstance->GetLocalSpaceTransform().m_position; } } @@ -43,10 +43,10 @@ namespace EMStudio EMotionFX::ActorInstance* actorInstance = GetCommandManager()->GetCurrentSelection().GetSingleActorInstance(); if (actorInstance) { - const AZ::Vector3 newPos = actorInstance->GetLocalSpaceTransform().mPosition; - actorInstance->SetLocalSpacePosition(mOldValueVec); + const AZ::Vector3 newPos = actorInstance->GetLocalSpaceTransform().m_position; + actorInstance->SetLocalSpacePosition(m_oldValueVec); - if ((mOldValueVec - newPos).GetLength() >= MCore::Math::epsilon) + if ((m_oldValueVec - newPos).GetLength() >= MCore::Math::epsilon) { AZStd::string outResult; if (GetCommandManager()->ExecuteCommand( @@ -66,24 +66,24 @@ namespace EMStudio void RotateManipulatorCallback::Update(const AZ::Quaternion& value) { // update the rotation, if actorinstance is still valid - size_t actorInstanceID = EMotionFX::GetActorManager().FindActorInstanceIndex(mActorInstance); + size_t actorInstanceID = EMotionFX::GetActorManager().FindActorInstanceIndex(m_actorInstance); if (actorInstanceID != InvalidIndex) { // temporarily update the actor instance - mActorInstance->SetLocalSpaceRotation(value * mActorInstance->GetLocalSpaceTransform().mRotation.GetNormalized()); + m_actorInstance->SetLocalSpaceRotation(value * m_actorInstance->GetLocalSpaceTransform().m_rotation.GetNormalized()); // update the callback parent - ManipulatorCallback::Update(mActorInstance->GetLocalSpaceTransform().mRotation); + ManipulatorCallback::Update(m_actorInstance->GetLocalSpaceTransform().m_rotation); } } void RotateManipulatorCallback::UpdateOldValues() { // update the rotation, if actorinstance is still valid - size_t actorInstanceID = EMotionFX::GetActorManager().FindActorInstanceIndex(mActorInstance); + size_t actorInstanceID = EMotionFX::GetActorManager().FindActorInstanceIndex(m_actorInstance); if (actorInstanceID != InvalidIndex) { - mOldValueQuat = mActorInstance->GetLocalSpaceTransform().mRotation; + m_oldValueQuat = m_actorInstance->GetLocalSpaceTransform().m_rotation; } } @@ -92,10 +92,10 @@ namespace EMStudio EMotionFX::ActorInstance* actorInstance = GetCommandManager()->GetCurrentSelection().GetSingleActorInstance(); if (actorInstance) { - const AZ::Quaternion newRot = actorInstance->GetLocalSpaceTransform().mRotation; - actorInstance->SetLocalSpaceRotation(mOldValueQuat); + const AZ::Quaternion newRot = actorInstance->GetLocalSpaceTransform().m_rotation; + actorInstance->SetLocalSpaceRotation(m_oldValueQuat); - const float dot = newRot.Dot(mOldValueQuat); + const float dot = newRot.Dot(m_oldValueQuat); if (dot < 1.0f - MCore::Math::epsilon && dot > -1.0f + MCore::Math::epsilon) { AZStd::string outResult; @@ -117,11 +117,11 @@ namespace EMStudio AZ::Vector3 ScaleManipulatorCallback::GetCurrValueVec() { - size_t actorInstanceID = EMotionFX::GetActorManager().FindActorInstanceIndex(mActorInstance); + size_t actorInstanceID = EMotionFX::GetActorManager().FindActorInstanceIndex(m_actorInstance); if (actorInstanceID != InvalidIndex) { #ifndef EMFX_SCALE_DISABLED - return mActorInstance->GetLocalSpaceTransform().mScale; + return m_actorInstance->GetLocalSpaceTransform().m_scale; #else return AZ::Vector3::CreateOne(); #endif @@ -137,16 +137,16 @@ namespace EMStudio EMFX_SCALECODE ( // update the position, if actorinstance is still valid - size_t actorInstanceID = EMotionFX::GetActorManager().FindActorInstanceIndex(mActorInstance); + size_t actorInstanceID = EMotionFX::GetActorManager().FindActorInstanceIndex(m_actorInstance); if (actorInstanceID != InvalidIndex) { float minScale = 0.001f; const AZ::Vector3 scale = AZ::Vector3( - MCore::Max(float(mOldValueVec.GetX() * value.GetX()), minScale), - MCore::Max(float(mOldValueVec.GetY() * value.GetY()), minScale), - MCore::Max(float(mOldValueVec.GetZ() * value.GetZ()), minScale)); + MCore::Max(float(m_oldValueVec.GetX() * value.GetX()), minScale), + MCore::Max(float(m_oldValueVec.GetY() * value.GetY()), minScale), + MCore::Max(float(m_oldValueVec.GetZ() * value.GetZ()), minScale)); - mActorInstance->SetLocalSpaceScale(scale); + m_actorInstance->SetLocalSpaceScale(scale); // update the callback ManipulatorCallback::Update(scale); @@ -159,10 +159,10 @@ namespace EMStudio EMFX_SCALECODE ( // update the rotation, if actorinstance is still valid - size_t actorInstanceID = EMotionFX::GetActorManager().FindActorInstanceIndex(mActorInstance); + size_t actorInstanceID = EMotionFX::GetActorManager().FindActorInstanceIndex(m_actorInstance); if (actorInstanceID != InvalidIndex) { - mOldValueVec = mActorInstance->GetLocalSpaceTransform().mScale; + m_oldValueVec = m_actorInstance->GetLocalSpaceTransform().m_scale; } ) } @@ -174,10 +174,10 @@ namespace EMStudio EMotionFX::ActorInstance* actorInstance = GetCommandManager()->GetCurrentSelection().GetSingleActorInstance(); if (actorInstance) { - AZ::Vector3 newScale = actorInstance->GetLocalSpaceTransform().mScale; - actorInstance->SetLocalSpaceScale(mOldValueVec); + AZ::Vector3 newScale = actorInstance->GetLocalSpaceTransform().m_scale; + actorInstance->SetLocalSpaceScale(m_oldValueVec); - if ((mOldValueVec - newScale).GetLength() >= MCore::Math::epsilon) + if ((m_oldValueVec - newScale).GetLength() >= MCore::Math::epsilon) { AZStd::string outResult; if (GetCommandManager()->ExecuteCommand( diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderOptions.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderOptions.cpp index 274edd36ce..af2cb2c8e8 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderOptions.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderOptions.cpp @@ -130,7 +130,7 @@ namespace EMStudio MCommon::OrbitCamera tempCam; m_nearClipPlaneDistance = tempCam.GetNearClipDistance(); m_farClipPlaneDistance = tempCam.GetFarClipDistance(); - m_FOV = tempCam.GetFOV(); + m_fov = tempCam.GetFOV(); } RenderOptions& RenderOptions::operator=(const RenderOptions& other) @@ -229,7 +229,7 @@ namespace EMStudio settings->setValue(s_tangentsScaleOptionName, (double)m_tangentsScale); settings->setValue(s_nearClipPlaneDistanceOptionName, (double)m_nearClipPlaneDistance); settings->setValue(s_farClipPlaneDistanceOptionName, (double)m_farClipPlaneDistance); - settings->setValue(s_FOVOptionName, (double)m_FOV); + settings->setValue(s_FOVOptionName, (double)m_fov); settings->setValue(s_showFPSOptionName, m_showFPS); settings->setValue(s_lastUsedLayoutOptionName, m_lastUsedLayout.c_str()); @@ -300,7 +300,7 @@ namespace EMStudio options.m_nearClipPlaneDistance = (float)settings->value(s_nearClipPlaneDistanceOptionName, (double)options.m_nearClipPlaneDistance).toDouble(); options.m_farClipPlaneDistance = (float)settings->value(s_farClipPlaneDistanceOptionName, (double)options.m_farClipPlaneDistance).toDouble(); - options.m_FOV = (float)settings->value(s_FOVOptionName, (double)options.m_FOV).toDouble(); + options.m_fov = (float)settings->value(s_FOVOptionName, (double)options.m_fov).toDouble(); options.m_mainLightIntensity = (float)settings->value(s_mainLightIntensityOptionName, (double)options.m_mainLightIntensity).toDouble(); options.m_mainLightAngleA = (float)settings->value(s_mainLightAngleAOptionName, (double)options.m_mainLightAngleA).toDouble(); @@ -358,7 +358,7 @@ namespace EMStudio ->Field(s_scaleBonesOnLengthOptionName, &RenderOptions::m_scaleBonesOnLength) ->Field(s_nearClipPlaneDistanceOptionName, &RenderOptions::m_nearClipPlaneDistance) ->Field(s_farClipPlaneDistanceOptionName, &RenderOptions::m_farClipPlaneDistance) - ->Field(s_FOVOptionName, &RenderOptions::m_FOV) + ->Field(s_FOVOptionName, &RenderOptions::m_fov) ->Field(s_mainLightIntensityOptionName, &RenderOptions::m_mainLightIntensity) ->Field(s_mainLightAngleAOptionName, &RenderOptions::m_mainLightAngleA) ->Field(s_mainLightAngleBOptionName, &RenderOptions::m_mainLightAngleB) @@ -449,7 +449,7 @@ namespace EMStudio ->Attribute(AZ::Edit::Attributes::ChangeNotify, &RenderOptions::OnFarClipPlaneDistanceChangedCallback) ->Attribute(AZ::Edit::Attributes::Min, 1.0f) ->Attribute(AZ::Edit::Attributes::Max, 100000.0f) - ->DataElement(AZ::Edit::UIHandlers::Default, &RenderOptions::m_FOV, "Field of view", + ->DataElement(AZ::Edit::UIHandlers::Default, &RenderOptions::m_fov, "Field of view", "Angle in degrees of the field of view.") ->Attribute(AZ::Edit::Attributes::ChangeNotify, &RenderOptions::OnFOVChangedCallback) ->Attribute(AZ::Edit::Attributes::Min, 1.0f) @@ -662,9 +662,9 @@ namespace EMStudio void RenderOptions::SetFOV(float FOV) { - if (!AZ::IsClose(FOV, m_FOV, std::numeric_limits::epsilon())) + if (!AZ::IsClose(FOV, m_fov, std::numeric_limits::epsilon())) { - m_FOV = FOV; + m_fov = FOV; OnFOVChangedCallback(); } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderOptions.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderOptions.h index 60f7aa1291..f146f62215 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderOptions.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderOptions.h @@ -114,7 +114,7 @@ namespace EMStudio float GetFarClipPlaneDistance() const { return m_farClipPlaneDistance; } void SetFarClipPlaneDistance(float farClipPlaneDistance); - float GetFOV() const { return m_FOV; } + float GetFOV() const { return m_fov; } void SetFOV(float FOV); float GetMainLightIntensity() const { return m_mainLightIntensity; } @@ -324,7 +324,7 @@ namespace EMStudio bool m_scaleBonesOnLength; float m_nearClipPlaneDistance; float m_farClipPlaneDistance; - float m_FOV; + float m_fov; float m_mainLightIntensity; float m_mainLightAngleA; float m_mainLightAngleB; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.cpp index d3e9593add..db0c355002 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.cpp @@ -27,34 +27,34 @@ namespace EMStudio RenderPlugin::RenderPlugin() : DockWidgetPlugin() { - mIsVisible = true; - mRenderUtil = nullptr; - mUpdateCallback = nullptr; + m_isVisible = true; + m_renderUtil = nullptr; + m_updateCallback = nullptr; - mUpdateRenderActorsCallback = nullptr; - mReInitRenderActorsCallback = nullptr; - mCreateActorInstanceCallback = nullptr; - mRemoveActorInstanceCallback = nullptr; - mSelectCallback = nullptr; - mUnselectCallback = nullptr; - mClearSelectionCallback = nullptr; - mResetToBindPoseCallback = nullptr; - mAdjustActorInstanceCallback = nullptr; + m_updateRenderActorsCallback = nullptr; + m_reInitRenderActorsCallback = nullptr; + m_createActorInstanceCallback = nullptr; + m_removeActorInstanceCallback = nullptr; + m_selectCallback = nullptr; + m_unselectCallback = nullptr; + m_clearSelectionCallback = nullptr; + m_resetToBindPoseCallback = nullptr; + m_adjustActorInstanceCallback = nullptr; - mZoomInCursor = nullptr; - mZoomOutCursor = nullptr; + m_zoomInCursor = nullptr; + m_zoomOutCursor = nullptr; - mBaseLayout = nullptr; - mRenderLayoutWidget = nullptr; - mActiveViewWidget = nullptr; - mCurrentSelection = nullptr; + m_baseLayout = nullptr; + m_renderLayoutWidget = nullptr; + m_activeViewWidget = nullptr; + m_currentSelection = nullptr; m_currentLayout = nullptr; - mFocusViewWidget = nullptr; - mFirstFrameAfterReInit = false; + m_focusViewWidget = nullptr; + m_firstFrameAfterReInit = false; - mTranslateManipulator = nullptr; - mRotateManipulator = nullptr; - mScaleManipulator = nullptr; + m_translateManipulator = nullptr; + m_rotateManipulator = nullptr; + m_scaleManipulator = nullptr; EMotionFX::ActorNotificationBus::Handler::BusConnect(); } @@ -83,38 +83,38 @@ namespace EMStudio m_layouts.clear(); // delete the gizmos - GetManager()->RemoveTransformationManipulator(mTranslateManipulator); - GetManager()->RemoveTransformationManipulator(mRotateManipulator); - GetManager()->RemoveTransformationManipulator(mScaleManipulator); + GetManager()->RemoveTransformationManipulator(m_translateManipulator); + GetManager()->RemoveTransformationManipulator(m_rotateManipulator); + GetManager()->RemoveTransformationManipulator(m_scaleManipulator); - delete mTranslateManipulator; - delete mRotateManipulator; - delete mScaleManipulator; + delete m_translateManipulator; + delete m_rotateManipulator; + delete m_scaleManipulator; // get rid of the cursors - delete mZoomInCursor; - delete mZoomOutCursor; + delete m_zoomInCursor; + delete m_zoomOutCursor; // unregister the command callbacks and get rid of the memory - GetCommandManager()->RemoveCommandCallback(mUpdateRenderActorsCallback, false); - GetCommandManager()->RemoveCommandCallback(mReInitRenderActorsCallback, false); - GetCommandManager()->RemoveCommandCallback(mCreateActorInstanceCallback, false); - GetCommandManager()->RemoveCommandCallback(mRemoveActorInstanceCallback, false); - GetCommandManager()->RemoveCommandCallback(mSelectCallback, false); - GetCommandManager()->RemoveCommandCallback(mUnselectCallback, false); - GetCommandManager()->RemoveCommandCallback(mClearSelectionCallback, false); - GetCommandManager()->RemoveCommandCallback(mResetToBindPoseCallback, false); - GetCommandManager()->RemoveCommandCallback(mAdjustActorInstanceCallback, false); + GetCommandManager()->RemoveCommandCallback(m_updateRenderActorsCallback, false); + GetCommandManager()->RemoveCommandCallback(m_reInitRenderActorsCallback, false); + GetCommandManager()->RemoveCommandCallback(m_createActorInstanceCallback, false); + GetCommandManager()->RemoveCommandCallback(m_removeActorInstanceCallback, false); + GetCommandManager()->RemoveCommandCallback(m_selectCallback, false); + GetCommandManager()->RemoveCommandCallback(m_unselectCallback, false); + GetCommandManager()->RemoveCommandCallback(m_clearSelectionCallback, false); + GetCommandManager()->RemoveCommandCallback(m_resetToBindPoseCallback, false); + GetCommandManager()->RemoveCommandCallback(m_adjustActorInstanceCallback, false); - delete mUpdateRenderActorsCallback; - delete mReInitRenderActorsCallback; - delete mCreateActorInstanceCallback; - delete mRemoveActorInstanceCallback; - delete mSelectCallback; - delete mUnselectCallback; - delete mClearSelectionCallback; - delete mResetToBindPoseCallback; - delete mAdjustActorInstanceCallback; + delete m_updateRenderActorsCallback; + delete m_reInitRenderActorsCallback; + delete m_createActorInstanceCallback; + delete m_removeActorInstanceCallback; + delete m_selectCallback; + delete m_unselectCallback; + delete m_clearSelectionCallback; + delete m_resetToBindPoseCallback; + delete m_adjustActorInstanceCallback; for (MCommon::RenderUtil::TrajectoryTracePath* trajectoryPath : m_trajectoryTracePaths) { @@ -128,14 +128,14 @@ namespace EMStudio void RenderPlugin::CleanEMStudioActors() { // get rid of the actors - for (EMStudioRenderActor* actor : mActors) + for (EMStudioRenderActor* actor : m_actors) { if (actor) { delete actor; } } - mActors.clear(); + m_actors.clear(); } @@ -156,7 +156,7 @@ namespace EMStudio // get rid of the emstudio actor delete emstudioActor; - mActors.erase(AZStd::next(begin(mActors), index)); + m_actors.erase(AZStd::next(begin(m_actors), index)); return true; } @@ -216,40 +216,40 @@ namespace EMStudio void RenderPlugin::ReInitTransformationManipulators() { EMotionFX::ActorInstance* actorInstance = GetCommandManager()->GetCurrentSelection().GetSingleActorInstance(); - const RenderOptions::ManipulatorMode mode = mRenderOptions.GetManipulatorMode(); + const RenderOptions::ManipulatorMode mode = m_renderOptions.GetManipulatorMode(); - if (mTranslateManipulator) + if (m_translateManipulator) { if (actorInstance) { - mTranslateManipulator->Init(actorInstance->GetLocalSpaceTransform().mPosition); - mTranslateManipulator->SetCallback(new TranslateManipulatorCallback(actorInstance, actorInstance->GetLocalSpaceTransform().mPosition)); + m_translateManipulator->Init(actorInstance->GetLocalSpaceTransform().m_position); + m_translateManipulator->SetCallback(new TranslateManipulatorCallback(actorInstance, actorInstance->GetLocalSpaceTransform().m_position)); } - mTranslateManipulator->SetIsVisible(actorInstance && mode == RenderOptions::ManipulatorMode::TRANSLATE); + m_translateManipulator->SetIsVisible(actorInstance && mode == RenderOptions::ManipulatorMode::TRANSLATE); } - if (mRotateManipulator) + if (m_rotateManipulator) { if (actorInstance) { - mRotateManipulator->Init(actorInstance->GetLocalSpaceTransform().mPosition); - mRotateManipulator->SetCallback(new RotateManipulatorCallback(actorInstance, actorInstance->GetLocalSpaceTransform().mRotation)); + m_rotateManipulator->Init(actorInstance->GetLocalSpaceTransform().m_position); + m_rotateManipulator->SetCallback(new RotateManipulatorCallback(actorInstance, actorInstance->GetLocalSpaceTransform().m_rotation)); } - mRotateManipulator->SetIsVisible(actorInstance && mode == RenderOptions::ManipulatorMode::ROTATE); + m_rotateManipulator->SetIsVisible(actorInstance && mode == RenderOptions::ManipulatorMode::ROTATE); } - if (mScaleManipulator) + if (m_scaleManipulator) { if (actorInstance) { - mScaleManipulator->Init(actorInstance->GetLocalSpaceTransform().mPosition); + m_scaleManipulator->Init(actorInstance->GetLocalSpaceTransform().m_position); #ifndef EMFX_SCALE_DISABLED - mScaleManipulator->SetCallback(new ScaleManipulatorCallback(actorInstance, actorInstance->GetLocalSpaceTransform().mScale)); + m_scaleManipulator->SetCallback(new ScaleManipulatorCallback(actorInstance, actorInstance->GetLocalSpaceTransform().m_scale)); #else - mScaleManipulator->SetCallback(new ScaleManipulatorCallback(actorInstance, AZ::Vector3::CreateOne())); + m_scaleManipulator->SetCallback(new ScaleManipulatorCallback(actorInstance, AZ::Vector3::CreateOne())); #endif } - mScaleManipulator->SetIsVisible(actorInstance && mode == RenderOptions::ManipulatorMode::SCALE); + m_scaleManipulator->SetIsVisible(actorInstance && mode == RenderOptions::ManipulatorMode::SCALE); } } @@ -269,14 +269,14 @@ namespace EMStudio for (const EMotionFX::Node* joint : joints) { - const AZ::Vector3 jointPosition = pose->GetWorldSpaceTransform(joint->GetNodeIndex()).mPosition; + const AZ::Vector3 jointPosition = pose->GetWorldSpaceTransform(joint->GetNodeIndex()).m_position; aabb.AddPoint(jointPosition); const size_t childCount = joint->GetNumChildNodes(); for (size_t i = 0; i < childCount; ++i) { EMotionFX::Node* childJoint = skeleton->GetNode(joint->GetChildIndex(i)); - const AZ::Vector3 childPosition = pose->GetWorldSpaceTransform(childJoint->GetNodeIndex()).mPosition; + const AZ::Vector3 childPosition = pose->GetWorldSpaceTransform(childJoint->GetNodeIndex()).m_position; aabb.AddPoint(childPosition); } } @@ -300,7 +300,7 @@ namespace EMStudio if (isFollowModeActive) { - QMessageBox::warning(mDock, "Please disable character follow mode", "Zoom to joints is only working in case character follow mode is disabled.\nPlease disable character follow mode in the render view menu: Camera -> Follow Mode", QMessageBox::Ok); + QMessageBox::warning(m_dock, "Please disable character follow mode", "Zoom to joints is only working in case character follow mode is disabled.\nPlease disable character follow mode in the render view menu: Camera -> Follow Mode", QMessageBox::Ok); } } } @@ -313,23 +313,23 @@ namespace EMStudio // try to locate the helper actor for a given instance RenderPlugin::EMStudioRenderActor* RenderPlugin::FindEMStudioActor(const EMotionFX::ActorInstance* actorInstance, bool doubleCheckInstance) const { - const auto foundActor = AZStd::find_if(begin(mActors), end(mActors), [actorInstance, doubleCheckInstance](const EMStudioRenderActor* renderActor) + const auto foundActor = AZStd::find_if(begin(m_actors), end(m_actors), [actorInstance, doubleCheckInstance](const EMStudioRenderActor* renderActor) { // is the parent actor of the instance the same as the one in the emstudio actor? - if (renderActor->mActor == actorInstance->GetActor()) + if (renderActor->m_actor == actorInstance->GetActor()) { // double check if the actor instance is in the actor instance array inside the emstudio actor if (doubleCheckInstance) { // now double check if the actor instance really is in the array of instances of this emstudio actor - const auto foundActorInstance = AZStd::find(begin(renderActor->mActorInstances), end(renderActor->mActorInstances), actorInstance); - return foundActorInstance != end(renderActor->mActorInstances); + const auto foundActorInstance = AZStd::find(begin(renderActor->m_actorInstances), end(renderActor->m_actorInstances), actorInstance); + return foundActorInstance != end(renderActor->m_actorInstances); } return true; } return false; }); - return foundActor != end(mActors) ? *foundActor : nullptr; + return foundActor != end(m_actors) ? *foundActor : nullptr; } @@ -341,19 +341,19 @@ namespace EMStudio return nullptr; } - const auto foundActor = AZStd::find_if(begin(mActors), end(mActors), [match = actor](const EMStudioRenderActor* actor) + const auto foundActor = AZStd::find_if(begin(m_actors), end(m_actors), [match = actor](const EMStudioRenderActor* actor) { - return actor->mActor == match; + return actor->m_actor == match; }); - return foundActor != end(mActors) ? *foundActor : nullptr; + return foundActor != end(m_actors) ? *foundActor : nullptr; } // get the index of the given emstudio actor size_t RenderPlugin::FindEMStudioActorIndex(const EMStudioRenderActor* EMStudioRenderActor) const { - const auto foundActor = AZStd::find(begin(mActors), end(mActors), EMStudioRenderActor); - return foundActor != end(mActors) ? AZStd::distance(begin(mActors), foundActor) : InvalidIndex; + const auto foundActor = AZStd::find(begin(m_actors), end(m_actors), EMStudioRenderActor); + return foundActor != end(m_actors) ? AZStd::distance(begin(m_actors), foundActor) : InvalidIndex; } @@ -371,13 +371,13 @@ namespace EMStudio void RenderPlugin::AddEMStudioActor(EMStudioRenderActor* emstudioActor) { // add the actor to the list and return success - mActors.emplace_back(emstudioActor); + m_actors.emplace_back(emstudioActor); } void RenderPlugin::ReInit(bool resetViewCloseup) { - if (!mRenderUtil) + if (!m_renderUtil) { return; } @@ -404,10 +404,10 @@ namespace EMStudio } } - for (size_t i = 0; i < mActors.size(); ++i) + for (size_t i = 0; i < m_actors.size(); ++i) { - EMStudioRenderActor* emstudioActor = mActors[i]; - EMotionFX::Actor* actor = emstudioActor->mActor; + EMStudioRenderActor* emstudioActor = m_actors[i]; + EMotionFX::Actor* actor = emstudioActor->m_actor; bool found = false; for (size_t j = 0; j < numActors; ++j) @@ -442,9 +442,9 @@ namespace EMStudio if (!emstudioActor) { - for (EMStudioRenderActor* currentEMStudioActor : mActors) + for (EMStudioRenderActor* currentEMStudioActor : m_actors) { - if (actor == currentEMStudioActor->mActor) + if (actor == currentEMStudioActor->m_actor) { emstudioActor = currentEMStudioActor; break; @@ -455,22 +455,22 @@ namespace EMStudio if (emstudioActor) { // set the GL actor - actorInstance->SetCustomData(emstudioActor->mRenderActor); + actorInstance->SetCustomData(emstudioActor->m_renderActor); // add the actor instance to the emstudio actor instances in case it is not in yet - if (AZStd::find(begin(emstudioActor->mActorInstances), end(emstudioActor->mActorInstances), actorInstance) == end(emstudioActor->mActorInstances)) + if (AZStd::find(begin(emstudioActor->m_actorInstances), end(emstudioActor->m_actorInstances), actorInstance) == end(emstudioActor->m_actorInstances)) { - emstudioActor->mActorInstances.emplace_back(actorInstance); + emstudioActor->m_actorInstances.emplace_back(actorInstance); } } } // 4. Unlink invalid actor instances from the emstudio actors - for (EMStudioRenderActor* emstudioActor : mActors) + for (EMStudioRenderActor* emstudioActor : m_actors) { - for (size_t j = 0; j < emstudioActor->mActorInstances.size();) + for (size_t j = 0; j < emstudioActor->m_actorInstances.size();) { - EMotionFX::ActorInstance* emstudioActorInstance = emstudioActor->mActorInstances[j]; + EMotionFX::ActorInstance* emstudioActorInstance = emstudioActor->m_actorInstances[j]; bool found = false; for (size_t k = 0; k < numActorInstances; ++k) @@ -484,7 +484,7 @@ namespace EMStudio if (found == false) { - emstudioActor->mActorInstances.erase(AZStd::next(begin(emstudioActor->mActorInstances), j)); + emstudioActor->m_actorInstances.erase(AZStd::next(begin(emstudioActor->m_actorInstances), j)); } else { @@ -493,7 +493,7 @@ namespace EMStudio } } - mFirstFrameAfterReInit = true; + m_firstFrameAfterReInit = true; m_reinitRequested = false; // zoom the camera to the available character only in case we're dealing with a single instance @@ -513,15 +513,15 @@ namespace EMStudio // constructor RenderPlugin::EMStudioRenderActor::EMStudioRenderActor(EMotionFX::Actor* actor, RenderGL::GLActor* renderActor) { - mRenderActor = renderActor; - mActor = actor; - mNormalsScaleMultiplier = 1.0f; - mCharacterHeight = 0.0f; - mOffsetFromTrajectoryNode = 0.0f; - mMustCalcNormalScale = true; + m_renderActor = renderActor; + m_actor = actor; + m_normalsScaleMultiplier = 1.0f; + m_characterHeight = 0.0f; + m_offsetFromTrajectoryNode = 0.0f; + m_mustCalcNormalScale = true; // extract the bones from the actor and add it to the array - actor->ExtractBoneList(0, &mBoneList); + actor->ExtractBoneList(0, &m_boneList); CalculateNormalScaleMultiplier(); } @@ -531,7 +531,7 @@ namespace EMStudio RenderPlugin::EMStudioRenderActor::~EMStudioRenderActor() { // get the number of actor instances and iterate through them - for (EMotionFX::ActorInstance* actorInstance : mActorInstances) + for (EMotionFX::ActorInstance* actorInstance : m_actorInstances) { // only delete the actor instance in case it is still inside the actor manager // in case it is not present there anymore this means an undo command has already deleted it @@ -549,17 +549,17 @@ namespace EMStudio // only delete the actor in case it is still inside the actor manager // in case it is not present there anymore this means an undo command has already deleted it - if (EMotionFX::GetActorManager().FindActorIndex(mActor) == InvalidIndex) + if (EMotionFX::GetActorManager().FindActorIndex(m_actor) == InvalidIndex) { // in case the actor is not valid anymore make sure to unselect it to avoid bad pointers CommandSystem::SelectionList& selection = GetCommandManager()->GetCurrentSelection(); - selection.RemoveActor(mActor); + selection.RemoveActor(m_actor); } // get rid of the OpenGL actor - if (mRenderActor) + if (m_renderActor) { - mRenderActor->Destroy(); + m_renderActor->Destroy(); } } @@ -567,7 +567,7 @@ namespace EMStudio void RenderPlugin::EMStudioRenderActor::CalculateNormalScaleMultiplier() { // calculate the max extent of the character - EMotionFX::ActorInstance* actorInstance = EMotionFX::ActorInstance::Create(mActor); + EMotionFX::ActorInstance* actorInstance = EMotionFX::ActorInstance::Create(m_actor); actorInstance->UpdateMeshDeformers(0.0f, true); AZ::Aabb aabb; @@ -578,14 +578,14 @@ namespace EMStudio actorInstance->CalcNodeBasedAabb(&aabb); } - mCharacterHeight = aabb.GetExtents().GetZ(); - mOffsetFromTrajectoryNode = aabb.GetMin().GetY() + (mCharacterHeight * 0.5f); + m_characterHeight = aabb.GetExtents().GetZ(); + m_offsetFromTrajectoryNode = aabb.GetMin().GetY() + (m_characterHeight * 0.5f); actorInstance->Destroy(); // scale the normals down to 1% of the character size, that looks pretty nice on all models const float radius = AZ::Vector3(aabb.GetMax() - aabb.GetMin()).GetLength() * 0.5f; - mNormalsScaleMultiplier = radius * 0.01f; + m_normalsScaleMultiplier = radius * 0.01f; } @@ -640,55 +640,55 @@ namespace EMStudio { // load the cursors QDir dataDir{ QString(MysticQt::GetDataDir().c_str()) }; - mZoomInCursor = new QCursor(QPixmap(dataDir.filePath("Images/Rendering/ZoomInCursor.png")).scaled(32, 32)); - mZoomOutCursor = new QCursor(QPixmap(dataDir.filePath("Images/Rendering/ZoomOutCursor.png")).scaled(32, 32)); + m_zoomInCursor = new QCursor(QPixmap(dataDir.filePath("Images/Rendering/ZoomInCursor.png")).scaled(32, 32)); + m_zoomOutCursor = new QCursor(QPixmap(dataDir.filePath("Images/Rendering/ZoomOutCursor.png")).scaled(32, 32)); - mCurrentSelection = &GetCommandManager()->GetCurrentSelection(); + m_currentSelection = &GetCommandManager()->GetCurrentSelection(); - connect(mDock, &QDockWidget::visibilityChanged, this, &RenderPlugin::VisibilityChanged); + connect(m_dock, &QDockWidget::visibilityChanged, this, &RenderPlugin::VisibilityChanged); // add the available render template layouts RegisterRenderPluginLayouts(this); // create the inner widget which contains the base layout - mInnerWidget = new QWidget(); - mDock->setWidget(mInnerWidget); + m_innerWidget = new QWidget(); + m_dock->setWidget(m_innerWidget); // the base layout contains the render layout templates on the left and the render views on the right - mBaseLayout = new QHBoxLayout(mInnerWidget); - mBaseLayout->setContentsMargins(0, 2, 2, 2); - mBaseLayout->setSpacing(0); + m_baseLayout = new QHBoxLayout(m_innerWidget); + m_baseLayout->setContentsMargins(0, 2, 2, 2); + m_baseLayout->setSpacing(0); SetSelectionMode(); // create and register the command callbacks only (only execute this code once for all plugins) - mUpdateRenderActorsCallback = new UpdateRenderActorsCallback(false); - mReInitRenderActorsCallback = new ReInitRenderActorsCallback(false); - mCreateActorInstanceCallback = new CreateActorInstanceCallback(false); - mRemoveActorInstanceCallback = new RemoveActorInstanceCallback(false); - mSelectCallback = new SelectCallback(false); - mUnselectCallback = new UnselectCallback(false); - mClearSelectionCallback = new ClearSelectionCallback(false); - mResetToBindPoseCallback = new CommandResetToBindPoseCallback(false); - mAdjustActorInstanceCallback = new AdjustActorInstanceCallback(false); - GetCommandManager()->RegisterCommandCallback("UpdateRenderActors", mUpdateRenderActorsCallback); - GetCommandManager()->RegisterCommandCallback("ReInitRenderActors", mReInitRenderActorsCallback); - GetCommandManager()->RegisterCommandCallback("CreateActorInstance", mCreateActorInstanceCallback); - GetCommandManager()->RegisterCommandCallback("RemoveActorInstance", mRemoveActorInstanceCallback); - GetCommandManager()->RegisterCommandCallback("Select", mSelectCallback); - GetCommandManager()->RegisterCommandCallback("Unselect", mUnselectCallback); - GetCommandManager()->RegisterCommandCallback("ClearSelection", mClearSelectionCallback); - GetCommandManager()->RegisterCommandCallback("ResetToBindPose", mResetToBindPoseCallback); - GetCommandManager()->RegisterCommandCallback("AdjustActorInstance", mAdjustActorInstanceCallback); + m_updateRenderActorsCallback = new UpdateRenderActorsCallback(false); + m_reInitRenderActorsCallback = new ReInitRenderActorsCallback(false); + m_createActorInstanceCallback = new CreateActorInstanceCallback(false); + m_removeActorInstanceCallback = new RemoveActorInstanceCallback(false); + m_selectCallback = new SelectCallback(false); + m_unselectCallback = new UnselectCallback(false); + m_clearSelectionCallback = new ClearSelectionCallback(false); + m_resetToBindPoseCallback = new CommandResetToBindPoseCallback(false); + m_adjustActorInstanceCallback = new AdjustActorInstanceCallback(false); + GetCommandManager()->RegisterCommandCallback("UpdateRenderActors", m_updateRenderActorsCallback); + GetCommandManager()->RegisterCommandCallback("ReInitRenderActors", m_reInitRenderActorsCallback); + GetCommandManager()->RegisterCommandCallback("CreateActorInstance", m_createActorInstanceCallback); + GetCommandManager()->RegisterCommandCallback("RemoveActorInstance", m_removeActorInstanceCallback); + GetCommandManager()->RegisterCommandCallback("Select", m_selectCallback); + GetCommandManager()->RegisterCommandCallback("Unselect", m_unselectCallback); + GetCommandManager()->RegisterCommandCallback("ClearSelection", m_clearSelectionCallback); + GetCommandManager()->RegisterCommandCallback("ResetToBindPose", m_resetToBindPoseCallback); + GetCommandManager()->RegisterCommandCallback("AdjustActorInstance", m_adjustActorInstanceCallback); // initialize the gizmos - mTranslateManipulator = (MCommon::TranslateManipulator*)GetManager()->AddTransformationManipulator(new MCommon::TranslateManipulator(70.0f, false)); - mScaleManipulator = (MCommon::ScaleManipulator*)GetManager()->AddTransformationManipulator(new MCommon::ScaleManipulator(70.0f, false)); - mRotateManipulator = (MCommon::RotateManipulator*)GetManager()->AddTransformationManipulator(new MCommon::RotateManipulator(70.0f, false)); + m_translateManipulator = (MCommon::TranslateManipulator*)GetManager()->AddTransformationManipulator(new MCommon::TranslateManipulator(70.0f, false)); + m_scaleManipulator = (MCommon::ScaleManipulator*)GetManager()->AddTransformationManipulator(new MCommon::ScaleManipulator(70.0f, false)); + m_rotateManipulator = (MCommon::RotateManipulator*)GetManager()->AddTransformationManipulator(new MCommon::RotateManipulator(70.0f, false)); // Load the render options and set the last used layout. LoadRenderOptions(); - LayoutButtonPressed(mRenderOptions.GetLastUsedLayout().c_str()); + LayoutButtonPressed(m_renderOptions.GetLastUsedLayout().c_str()); EMotionFX::SkeletonOutlinerNotificationBus::Handler::BusConnect(); return true; @@ -702,7 +702,7 @@ namespace EMStudio QSettings settings(renderOptionsFilename.c_str(), QSettings::IniFormat, this); // save the general render options - mRenderOptions.Save(&settings); + m_renderOptions.Save(&settings); AZStd::string groupName; if (m_currentLayout) @@ -727,7 +727,7 @@ namespace EMStudio AZStd::string renderOptionsFilename(GetManager()->GetAppDataFolder()); renderOptionsFilename += "EMStudioRenderOptions.cfg"; QSettings settings(renderOptionsFilename.c_str(), QSettings::IniFormat, this); - mRenderOptions = RenderOptions::Load(&settings); + m_renderOptions = RenderOptions::Load(&settings); AZStd::string groupName; if (m_currentLayout) @@ -745,13 +745,12 @@ namespace EMStudio } } - //SetAspiredRenderingFPS(mRenderOptions.mAspiredRenderFPS); - SetManipulatorMode(mRenderOptions.GetManipulatorMode()); + SetManipulatorMode(m_renderOptions.GetManipulatorMode()); } void RenderPlugin::SetManipulatorMode(RenderOptions::ManipulatorMode mode) { - mRenderOptions.SetManipulatorMode(mode); + m_renderOptions.SetManipulatorMode(mode); for (RenderViewWidget* viewWidget : m_viewWidgets) { @@ -763,7 +762,7 @@ namespace EMStudio void RenderPlugin::VisibilityChanged(bool visible) { - mIsVisible = visible; + m_isVisible = visible; } void RenderPlugin::UpdateActorInstances(float timePassedInSeconds) @@ -794,7 +793,7 @@ namespace EMStudio void RenderPlugin::ProcessFrame(float timePassedInSeconds) { // skip rendering in case we want to avoid updating any 3d views - if (GetManager()->GetAvoidRendering() || mIsVisible == false) + if (GetManager()->GetAvoidRendering() || m_isVisible == false) { return; } @@ -811,14 +810,14 @@ namespace EMStudio { RenderWidget* renderWidget = viewWidget->GetRenderWidget(); - if (!mFirstFrameAfterReInit) + if (!m_firstFrameAfterReInit) { renderWidget->GetCamera()->Update(timePassedInSeconds); } - if (mFirstFrameAfterReInit) + if (m_firstFrameAfterReInit) { - mFirstFrameAfterReInit = false; + m_firstFrameAfterReInit = false; } // redraw @@ -833,17 +832,17 @@ namespace EMStudio AZ::Aabb finalAabb = AZ::Aabb::CreateNull(); CommandSystem::SelectionList& selection = GetCommandManager()->GetCurrentSelection(); - if (mUpdateCallback) + if (m_updateCallback) { - mUpdateCallback->SetEnableRendering(false); + m_updateCallback->SetEnableRendering(false); } // update EMotion FX, but don't render EMotionFX::GetEMotionFX().Update(0.0f); - if (mUpdateCallback) + if (m_updateCallback) { - mUpdateCallback->SetEnableRendering(true); + m_updateCallback->SetEnableRendering(true); } // get the number of actor instances and iterate through them @@ -933,26 +932,26 @@ namespace EMStudio } // save the current settings and disable rendering - mRenderOptions.SetLastUsedLayout(layout->GetName()); + m_renderOptions.SetLastUsedLayout(layout->GetName()); ClearViewWidgets(); VisibilityChanged(false); m_currentLayout = layout; - QWidget* oldLayoutWidget = mRenderLayoutWidget; - QWidget* newLayoutWidget = layout->Create(this, mInnerWidget); + QWidget* oldLayoutWidget = m_renderLayoutWidget; + QWidget* newLayoutWidget = layout->Create(this, m_innerWidget); // delete the old render layout after we created the new one, so we can keep the old resources // this only removes it from the layout - mBaseLayout->removeWidget(oldLayoutWidget); + m_baseLayout->removeWidget(oldLayoutWidget); - mRenderLayoutWidget = newLayoutWidget; + m_renderLayoutWidget = newLayoutWidget; // create thw new one and add it to the base layout - mBaseLayout->addWidget(mRenderLayoutWidget); - mRenderLayoutWidget->update(); - mBaseLayout->update(); - mRenderLayoutWidget->show(); + m_baseLayout->addWidget(m_renderLayoutWidget); + m_renderLayoutWidget->update(); + m_baseLayout->update(); + m_renderLayoutWidget->show(); LoadRenderOptions(); ViewCloseup(false, nullptr, 0.0f); @@ -981,7 +980,7 @@ namespace EMStudio { for (MCommon::RenderUtil::TrajectoryTracePath* trajectoryPath : m_trajectoryTracePaths) { - if (trajectoryPath->mActorInstance == actorInstance) + if (trajectoryPath->m_actorInstance == actorInstance) { return trajectoryPath; } @@ -990,8 +989,8 @@ namespace EMStudio // we haven't created a path for the given actor instance yet, do so MCommon::RenderUtil::TrajectoryTracePath* tracePath = new MCommon::RenderUtil::TrajectoryTracePath(); - tracePath->mActorInstance = actorInstance; - tracePath->mTraceParticles.reserve(512); + tracePath->m_actorInstance = actorInstance; + tracePath->m_traceParticles.reserve(512); m_trajectoryTracePaths.emplace_back(tracePath); return tracePath; @@ -1032,20 +1031,20 @@ namespace EMStudio const EMotionFX::Transform& worldTM = actorInstance->GetWorldSpaceTransform(); bool distanceTraveledEnough = false; - if (trajectoryPath->mTraceParticles.empty()) + if (trajectoryPath->m_traceParticles.empty()) { distanceTraveledEnough = true; } else { - const size_t numParticles = trajectoryPath->mTraceParticles.size(); - const EMotionFX::Transform& oldWorldTM = trajectoryPath->mTraceParticles[numParticles - 1].mWorldTM; + const size_t numParticles = trajectoryPath->m_traceParticles.size(); + const EMotionFX::Transform& oldWorldTM = trajectoryPath->m_traceParticles[numParticles - 1].m_worldTm; - const AZ::Vector3& oldPos = oldWorldTM.mPosition; - const AZ::Quaternion oldRot = oldWorldTM.mRotation.GetNormalized(); - const AZ::Quaternion rotation = worldTM.mRotation.GetNormalized(); + const AZ::Vector3& oldPos = oldWorldTM.m_position; + const AZ::Quaternion oldRot = oldWorldTM.m_rotation.GetNormalized(); + const AZ::Quaternion rotation = worldTM.m_rotation.GetNormalized(); - const AZ::Vector3 deltaPos = worldTM.mPosition - oldPos; + const AZ::Vector3 deltaPos = worldTM.m_position - oldPos; const float deltaRot = MCore::Math::Abs(rotation.Dot(oldRot)); if (MCore::SafeLength(deltaPos) > 0.0001f || deltaRot < 0.99f) { @@ -1054,25 +1053,25 @@ namespace EMStudio } // add the time delta to the time passed since the last add - trajectoryPath->mTimePassed += timePassedInSeconds; + trajectoryPath->m_timePassed += timePassedInSeconds; const uint32 particleSampleRate = 30; - if (trajectoryPath->mTimePassed >= (1.0f / particleSampleRate) && distanceTraveledEnough) + if (trajectoryPath->m_timePassed >= (1.0f / particleSampleRate) && distanceTraveledEnough) { // create the particle, fill its data and add it to the trajectory trace path MCommon::RenderUtil::TrajectoryPathParticle trajectoryParticle; - trajectoryParticle.mWorldTM = worldTM; - trajectoryPath->mTraceParticles.emplace_back(trajectoryParticle); + trajectoryParticle.m_worldTm = worldTM; + trajectoryPath->m_traceParticles.emplace_back(trajectoryParticle); // reset the time passed as we just added a new particle - trajectoryPath->mTimePassed = 0.0f; + trajectoryPath->m_timePassed = 0.0f; } } // make sure we don't have too many items in our array - if (trajectoryPath->mTraceParticles.size() > 50) + if (trajectoryPath->m_traceParticles.size() > 50) { - trajectoryPath->mTraceParticles.erase(begin(trajectoryPath->mTraceParticles)); + trajectoryPath->m_traceParticles.erase(begin(trajectoryPath->m_traceParticles)); } } } @@ -1106,9 +1105,9 @@ namespace EMStudio if (widget->GetRenderFlag(RenderViewWidget::RENDER_AABB)) { MCommon::RenderUtil::AABBRenderSettings settings; - settings.mNodeBasedColor = renderOptions->GetNodeAABBColor(); - settings.mStaticBasedColor = renderOptions->GetStaticAABBColor(); - settings.mMeshBasedColor = renderOptions->GetMeshAABBColor(); + settings.m_nodeBasedColor = renderOptions->GetNodeAABBColor(); + settings.m_staticBasedColor = renderOptions->GetStaticAABBColor(); + settings.m_meshBasedColor = renderOptions->GetMeshAABBColor(); renderUtil->RenderAabbs(actorInstance, settings); } @@ -1146,11 +1145,11 @@ namespace EMStudio renderUtil->EnableLighting(false); // disable lighting if (widget->GetRenderFlag(RenderViewWidget::RENDER_SKELETON)) { - renderUtil->RenderSkeleton(actorInstance, emstudioActor->mBoneList, &visibleJointIndices, &selectedJointIndices, renderOptions->GetSkeletonColor(), renderOptions->GetSelectedObjectColor()); + renderUtil->RenderSkeleton(actorInstance, emstudioActor->m_boneList, &visibleJointIndices, &selectedJointIndices, renderOptions->GetSkeletonColor(), renderOptions->GetSelectedObjectColor()); } if (widget->GetRenderFlag(RenderViewWidget::RENDER_NODEORIENTATION)) { - renderUtil->RenderNodeOrientations(actorInstance, emstudioActor->mBoneList, &visibleJointIndices, &selectedJointIndices, emstudioActor->mNormalsScaleMultiplier * renderOptions->GetNodeOrientationScale(), renderOptions->GetScaleBonesOnLength()); + renderUtil->RenderNodeOrientations(actorInstance, emstudioActor->m_boneList, &visibleJointIndices, &selectedJointIndices, emstudioActor->m_normalsScaleMultiplier * renderOptions->GetNodeOrientationScale(), renderOptions->GetScaleBonesOnLength()); } if (widget->GetRenderFlag(RenderViewWidget::RENDER_ACTORBINDPOSE)) { @@ -1161,7 +1160,7 @@ namespace EMStudio if (widget->GetRenderFlag(RenderViewWidget::RENDER_MOTIONEXTRACTION)) { // render an arrow for the trajectory - renderUtil->RenderTrajectoryPath(FindTracePath(actorInstance), renderOptions->GetTrajectoryArrowInnerColor(), emstudioActor->mCharacterHeight * 0.05f); + renderUtil->RenderTrajectoryPath(FindTracePath(actorInstance), renderOptions->GetTrajectoryArrowInnerColor(), emstudioActor->m_characterHeight * 0.05f); } renderUtil->EnableCulling(cullingEnabled); // reset to the old state renderUtil->EnableLighting(lightingEnabled); @@ -1181,9 +1180,9 @@ namespace EMStudio const size_t numEnabled = actorInstance->GetNumEnabledNodes(); for (size_t i = 0; i < numEnabled; ++i) { - EMotionFX::Node* node = emstudioActor->mActor->GetSkeleton()->GetNode(actorInstance->GetEnabledNode(i)); + EMotionFX::Node* node = emstudioActor->m_actor->GetSkeleton()->GetNode(actorInstance->GetEnabledNode(i)); const size_t nodeIndex = node->GetNodeIndex(); - EMotionFX::Mesh* mesh = emstudioActor->mActor->GetMesh(geomLODLevel, nodeIndex); + EMotionFX::Mesh* mesh = emstudioActor->m_actor->GetMesh(geomLODLevel, nodeIndex); renderUtil->ResetCurrentMesh(); @@ -1196,20 +1195,20 @@ namespace EMStudio if (!mesh->GetIsCollisionMesh()) { - renderUtil->RenderNormals(mesh, worldTM, renderVertexNormals, renderFaceNormals, renderOptions->GetVertexNormalsScale() * emstudioActor->mNormalsScaleMultiplier, renderOptions->GetFaceNormalsScale() * emstudioActor->mNormalsScaleMultiplier, renderOptions->GetVertexNormalsColor(), renderOptions->GetFaceNormalsColor()); + renderUtil->RenderNormals(mesh, worldTM, renderVertexNormals, renderFaceNormals, renderOptions->GetVertexNormalsScale() * emstudioActor->m_normalsScaleMultiplier, renderOptions->GetFaceNormalsScale() * emstudioActor->m_normalsScaleMultiplier, renderOptions->GetVertexNormalsColor(), renderOptions->GetFaceNormalsColor()); if (renderTangents) { - renderUtil->RenderTangents(mesh, worldTM, renderOptions->GetTangentsScale() * emstudioActor->mNormalsScaleMultiplier, renderOptions->GetTangentsColor(), renderOptions->GetMirroredBitangentsColor(), renderOptions->GetBitangentsColor()); + renderUtil->RenderTangents(mesh, worldTM, renderOptions->GetTangentsScale() * emstudioActor->m_normalsScaleMultiplier, renderOptions->GetTangentsColor(), renderOptions->GetMirroredBitangentsColor(), renderOptions->GetBitangentsColor()); } if (renderWireframe) { - renderUtil->RenderWireframe(mesh, worldTM, renderOptions->GetWireframeColor(), false, emstudioActor->mNormalsScaleMultiplier); + renderUtil->RenderWireframe(mesh, worldTM, renderOptions->GetWireframeColor(), false, emstudioActor->m_normalsScaleMultiplier); } } else if (renderCollisionMeshes) { - renderUtil->RenderWireframe(mesh, worldTM, renderOptions->GetCollisionMeshColor(), false, emstudioActor->mNormalsScaleMultiplier); + renderUtil->RenderWireframe(mesh, worldTM, renderOptions->GetCollisionMeshColor(), false, emstudioActor->m_normalsScaleMultiplier); } } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.h index a99a64ef68..01678e024d 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.h @@ -52,14 +52,14 @@ namespace EMStudio { MCORE_MEMORYOBJECTCATEGORY(RenderPlugin::EMStudioRenderActor, MCore::MCORE_DEFAULT_ALIGNMENT, MEMCATEGORY_EMSTUDIOSDK_RENDERPLUGINBASE); - EMotionFX::Actor* mActor; - AZStd::vector mBoneList; - RenderGL::GLActor* mRenderActor; - AZStd::vector mActorInstances; - float mNormalsScaleMultiplier; - float mCharacterHeight; - float mOffsetFromTrajectoryNode; - bool mMustCalcNormalScale; + EMotionFX::Actor* m_actor; + AZStd::vector m_boneList; + RenderGL::GLActor* m_renderActor; + AZStd::vector m_actorInstances; + float m_normalsScaleMultiplier; + float m_characterHeight; + float m_offsetFromTrajectoryNode; + bool m_mustCalcNormalScale; EMStudioRenderActor(EMotionFX::Actor* actor, RenderGL::GLActor* renderActor); virtual ~EMStudioRenderActor(); @@ -72,14 +72,14 @@ namespace EMStudio MCORE_MEMORYOBJECTCATEGORY(RenderPlugin::Layout, MCore::MCORE_DEFAULT_ALIGNMENT, MEMCATEGORY_EMSTUDIOSDK_RENDERPLUGINBASE); public: - Layout() { mRenderPlugin = nullptr; } + Layout() { m_renderPlugin = nullptr; } virtual ~Layout() { } virtual QWidget* Create(RenderPlugin* renderPlugin, QWidget* parent) = 0; virtual const char* GetName() = 0; virtual const char* GetImageFileName() = 0; private: - RenderPlugin* mRenderPlugin; + RenderPlugin* m_renderPlugin; }; RenderPlugin(); @@ -103,7 +103,7 @@ namespace EMStudio EMStudioPlugin::EPluginType GetPluginType() const override { return EMStudioPlugin::PLUGINTYPE_RENDERING; } uint32 GetProcessFramePriority() const override { return 100; } - PluginOptions* GetOptions() override { return &mRenderOptions; } + PluginOptions* GetOptions() override { return &m_renderOptions; } // render actors EMStudioRenderActor* FindEMStudioActor(const EMotionFX::ActorInstance* actorInstance, bool doubleCheckInstance = true) const; @@ -123,16 +123,16 @@ namespace EMStudio // manipulators void ReInitTransformationManipulators(); MCommon::TransformationManipulator* GetActiveManipulator(MCommon::Camera* camera, int32 mousePosX, int32 mousePosY); - MCORE_INLINE MCommon::TranslateManipulator* GetTranslateManipulator() { return mTranslateManipulator; } - MCORE_INLINE MCommon::RotateManipulator* GetRotateManipulator() { return mRotateManipulator; } - MCORE_INLINE MCommon::ScaleManipulator* GetScaleManipulator() { return mScaleManipulator; } + MCORE_INLINE MCommon::TranslateManipulator* GetTranslateManipulator() { return m_translateManipulator; } + MCORE_INLINE MCommon::RotateManipulator* GetRotateManipulator() { return m_rotateManipulator; } + MCORE_INLINE MCommon::ScaleManipulator* GetScaleManipulator() { return m_scaleManipulator; } // other helpers - MCORE_INLINE RenderOptions* GetRenderOptions() { return &mRenderOptions; } + MCORE_INLINE RenderOptions* GetRenderOptions() { return &m_renderOptions; } // view widget helpers - MCORE_INLINE RenderViewWidget* GetFocusViewWidget() { return mFocusViewWidget; } - MCORE_INLINE void SetFocusViewWidget(RenderViewWidget* focusViewWidget) { mFocusViewWidget = focusViewWidget; } + MCORE_INLINE RenderViewWidget* GetFocusViewWidget() { return m_focusViewWidget; } + MCORE_INLINE void SetFocusViewWidget(RenderViewWidget* focusViewWidget) { m_focusViewWidget = focusViewWidget; } RenderViewWidget* GetViewWidget(size_t index) { return m_viewWidgets[index]; } size_t GetNumViewWidgets() const { return m_viewWidgets.size(); } @@ -140,19 +140,19 @@ namespace EMStudio void RemoveViewWidget(RenderViewWidget* viewWidget); void ClearViewWidgets(); - MCORE_INLINE RenderViewWidget* GetActiveViewWidget() { return mActiveViewWidget; } - MCORE_INLINE void SetActiveViewWidget(RenderViewWidget* viewWidget) { mActiveViewWidget = viewWidget; } + MCORE_INLINE RenderViewWidget* GetActiveViewWidget() { return m_activeViewWidget; } + MCORE_INLINE void SetActiveViewWidget(RenderViewWidget* viewWidget) { m_activeViewWidget = viewWidget; } void AddLayout(Layout* layout) { m_layouts.emplace_back(layout); } Layout* FindLayoutByName(const AZStd::string& layoutName) const; Layout* GetCurrentLayout() const { return m_currentLayout; } const AZStd::vector& GetLayouts() { return m_layouts; } - MCORE_INLINE QCursor& GetZoomInCursor() { assert(mZoomInCursor); return *mZoomInCursor; } - MCORE_INLINE QCursor& GetZoomOutCursor() { assert(mZoomOutCursor); return *mZoomOutCursor; } + MCORE_INLINE QCursor& GetZoomInCursor() { assert(m_zoomInCursor); return *m_zoomInCursor; } + MCORE_INLINE QCursor& GetZoomOutCursor() { assert(m_zoomOutCursor); return *m_zoomOutCursor; } - MCORE_INLINE CommandSystem::SelectionList* GetCurrentSelection() const { return mCurrentSelection; } - MCORE_INLINE MCommon::RenderUtil* GetRenderUtil() const { return mRenderUtil; } + MCORE_INLINE CommandSystem::SelectionList* GetCurrentSelection() const { return m_currentSelection; } + MCORE_INLINE MCommon::RenderUtil* GetRenderUtil() const { return m_renderUtil; } AZ::Aabb GetSceneAabb(bool selectedInstancesOnly); @@ -195,38 +195,38 @@ namespace EMStudio AZStd::vector m_trajectoryTracePaths; // the transformation manipulators - MCommon::TranslateManipulator* mTranslateManipulator; - MCommon::RotateManipulator* mRotateManipulator; - MCommon::ScaleManipulator* mScaleManipulator; + MCommon::TranslateManipulator* m_translateManipulator; + MCommon::RotateManipulator* m_rotateManipulator; + MCommon::ScaleManipulator* m_scaleManipulator; - MCommon::RenderUtil* mRenderUtil; - RenderUpdateCallback* mUpdateCallback; + MCommon::RenderUtil* m_renderUtil; + RenderUpdateCallback* m_updateCallback; - RenderOptions mRenderOptions; - AZStd::vector mActors; + RenderOptions m_renderOptions; + AZStd::vector m_actors; // view widgets AZStd::vector m_viewWidgets; - RenderViewWidget* mActiveViewWidget; - RenderViewWidget* mFocusViewWidget; + RenderViewWidget* m_activeViewWidget; + RenderViewWidget* m_focusViewWidget; // render view layouts AZStd::vector m_layouts; Layout* m_currentLayout; // cursor image files - QCursor* mZoomInCursor; - QCursor* mZoomOutCursor; + QCursor* m_zoomInCursor; + QCursor* m_zoomOutCursor; // window visibility - bool mIsVisible; + bool m_isVisible; // base layout and interface functionality - QHBoxLayout* mBaseLayout; - QWidget* mRenderLayoutWidget; - QWidget* mInnerWidget; - CommandSystem::SelectionList* mCurrentSelection; - bool mFirstFrameAfterReInit; + QHBoxLayout* m_baseLayout; + QWidget* m_renderLayoutWidget; + QWidget* m_innerWidget; + CommandSystem::SelectionList* m_currentSelection; + bool m_firstFrameAfterReInit; bool m_reinitRequested = false; // command callbacks @@ -239,14 +239,14 @@ namespace EMStudio MCORE_DEFINECOMMANDCALLBACK(ClearSelectionCallback); MCORE_DEFINECOMMANDCALLBACK(CommandResetToBindPoseCallback); MCORE_DEFINECOMMANDCALLBACK(AdjustActorInstanceCallback); - UpdateRenderActorsCallback* mUpdateRenderActorsCallback; - ReInitRenderActorsCallback* mReInitRenderActorsCallback; - CreateActorInstanceCallback* mCreateActorInstanceCallback; - RemoveActorInstanceCallback* mRemoveActorInstanceCallback; - SelectCallback* mSelectCallback; - UnselectCallback* mUnselectCallback; - ClearSelectionCallback* mClearSelectionCallback; - CommandResetToBindPoseCallback* mResetToBindPoseCallback; - AdjustActorInstanceCallback* mAdjustActorInstanceCallback; + UpdateRenderActorsCallback* m_updateRenderActorsCallback; + ReInitRenderActorsCallback* m_reInitRenderActorsCallback; + CreateActorInstanceCallback* m_createActorInstanceCallback; + RemoveActorInstanceCallback* m_removeActorInstanceCallback; + SelectCallback* m_selectCallback; + UnselectCallback* m_unselectCallback; + ClearSelectionCallback* m_clearSelectionCallback; + CommandResetToBindPoseCallback* m_resetToBindPoseCallback; + AdjustActorInstanceCallback* m_adjustActorInstanceCallback; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderUpdateCallback.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderUpdateCallback.cpp index 3c146c528b..5cc88db0b0 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderUpdateCallback.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderUpdateCallback.cpp @@ -21,15 +21,15 @@ namespace EMStudio // constructor RenderUpdateCallback::RenderUpdateCallback(RenderPlugin* plugin) { - mEnableRendering = true; - mPlugin = plugin; + m_enableRendering = true; + m_plugin = plugin; } // enable or disable rendering void RenderUpdateCallback::SetEnableRendering(bool renderingEnabled) { - mEnableRendering = renderingEnabled; + m_enableRendering = renderingEnabled; } @@ -41,7 +41,7 @@ namespace EMStudio // set to visible for the cases the active view widget is nullptr // this happens when call the Process() function from the render plugin before we update our view - RenderViewWidget* widget = mPlugin->GetActiveViewWidget(); + RenderViewWidget* widget = m_plugin->GetActiveViewWidget(); if (widget == nullptr) { actorInstance->SetIsVisible(true); @@ -72,7 +72,7 @@ namespace EMStudio //actorInstance->UpdateTransformations( timePassedInSeconds, true); // find the corresponding trajectory trace path for the given actor instance - MCommon::RenderUtil::TrajectoryTracePath* trajectoryPath = mPlugin->FindTracePath(actorInstance); + MCommon::RenderUtil::TrajectoryTracePath* trajectoryPath = m_plugin->FindTracePath(actorInstance); if (trajectoryPath) { EMotionFX::Actor* actor = actorInstance->GetActor(); @@ -84,20 +84,20 @@ namespace EMStudio const EMotionFX::Transform globalTM = transformData->GetCurrentPose()->GetWorldSpaceTransform(motionExtractionNode->GetNodeIndex()).ProjectedToGroundPlane(); bool distanceTraveledEnough = false; - if (trajectoryPath->mTraceParticles.empty()) + if (trajectoryPath->m_traceParticles.empty()) { distanceTraveledEnough = true; } else { - const size_t numParticles = trajectoryPath->mTraceParticles.size(); - const EMotionFX::Transform& oldGlobalTM = trajectoryPath->mTraceParticles[numParticles - 1].mWorldTM; + const size_t numParticles = trajectoryPath->m_traceParticles.size(); + const EMotionFX::Transform& oldGlobalTM = trajectoryPath->m_traceParticles[numParticles - 1].m_worldTm; - const AZ::Vector3& oldPos = oldGlobalTM.mPosition; - const AZ::Quaternion& oldRot = oldGlobalTM.mRotation; - const AZ::Quaternion rotation = globalTM.mRotation.GetNormalized(); + const AZ::Vector3& oldPos = oldGlobalTM.m_position; + const AZ::Quaternion& oldRot = oldGlobalTM.m_rotation; + const AZ::Quaternion rotation = globalTM.m_rotation.GetNormalized(); - const AZ::Vector3 deltaPos = globalTM.mPosition - oldPos; + const AZ::Vector3 deltaPos = globalTM.m_position - oldPos; float deltaRot = MCore::Math::Abs(rotation.Dot(oldRot)); if (MCore::SafeLength(deltaPos) > 0.0001f || deltaRot < 0.99f) @@ -107,25 +107,25 @@ namespace EMStudio } // add the time delta to the time passed since the last add - trajectoryPath->mTimePassed += timePassedInSeconds; + trajectoryPath->m_timePassed += timePassedInSeconds; const uint32 particleSampleRate = 30; - if (trajectoryPath->mTimePassed >= (1.0f / particleSampleRate) && distanceTraveledEnough) + if (trajectoryPath->m_timePassed >= (1.0f / particleSampleRate) && distanceTraveledEnough) { // create the particle, fill its data and add it to the trajectory trace path MCommon::RenderUtil::TrajectoryPathParticle trajectoryParticle; - trajectoryParticle.mWorldTM = globalTM; - trajectoryPath->mTraceParticles.emplace_back(trajectoryParticle); + trajectoryParticle.m_worldTm = globalTM; + trajectoryPath->m_traceParticles.emplace_back(trajectoryParticle); // reset the time passed as we just added a new particle - trajectoryPath->mTimePassed = 0.0f; + trajectoryPath->m_timePassed = 0.0f; } } // make sure we don't have too many items in our array - if (trajectoryPath->mTraceParticles.size() > 50) + if (trajectoryPath->m_traceParticles.size() > 50) { - trajectoryPath->mTraceParticles.erase(begin(trajectoryPath->mTraceParticles)); + trajectoryPath->m_traceParticles.erase(begin(trajectoryPath->m_traceParticles)); } } } @@ -136,19 +136,19 @@ namespace EMStudio { MCORE_UNUSED(timePassedInSeconds); - if (mEnableRendering == false) + if (m_enableRendering == false) { return; } - RenderPlugin::EMStudioRenderActor* emstudioActor = mPlugin->FindEMStudioActor(actorInstance); + RenderPlugin::EMStudioRenderActor* emstudioActor = m_plugin->FindEMStudioActor(actorInstance); if (emstudioActor == nullptr) { return; } // renderUtil options - MCommon::RenderUtil* renderUtil = mPlugin->GetRenderUtil(); + MCommon::RenderUtil* renderUtil = m_plugin->GetRenderUtil(); if (renderUtil == nullptr) { return; @@ -157,8 +157,8 @@ namespace EMStudio actorInstance->UpdateMeshDeformers(timePassedInSeconds); // get the active widget & it's rendering options - RenderViewWidget* widget = mPlugin->GetActiveViewWidget(); - RenderOptions* renderOptions = mPlugin->GetRenderOptions(); + RenderViewWidget* widget = m_plugin->GetActiveViewWidget(); + RenderOptions* renderOptions = m_plugin->GetRenderOptions(); const AZStd::unordered_set& visibleJointIndices = GetManager()->GetVisibleJointIndices(); const AZStd::unordered_set& selectedJointIndices = GetManager()->GetSelectedJointIndices(); @@ -167,9 +167,9 @@ namespace EMStudio if (widget->GetRenderFlag(RenderViewWidget::RENDER_AABB)) { MCommon::RenderUtil::AABBRenderSettings settings; - settings.mNodeBasedColor = renderOptions->GetNodeAABBColor(); - settings.mStaticBasedColor = renderOptions->GetStaticAABBColor(); - settings.mMeshBasedColor = renderOptions->GetMeshAABBColor(); + settings.m_nodeBasedColor = renderOptions->GetNodeAABBColor(); + settings.m_staticBasedColor = renderOptions->GetStaticAABBColor(); + settings.m_meshBasedColor = renderOptions->GetMeshAABBColor(); renderUtil->RenderAabbs(actorInstance, settings); } @@ -185,11 +185,11 @@ namespace EMStudio renderUtil->EnableLighting(false); // disable lighting if (widget->GetRenderFlag(RenderViewWidget::RENDER_SKELETON)) { - renderUtil->RenderSkeleton(actorInstance, emstudioActor->mBoneList, &visibleJointIndices, &selectedJointIndices, renderOptions->GetSkeletonColor(), renderOptions->GetSelectedObjectColor()); + renderUtil->RenderSkeleton(actorInstance, emstudioActor->m_boneList, &visibleJointIndices, &selectedJointIndices, renderOptions->GetSkeletonColor(), renderOptions->GetSelectedObjectColor()); } if (widget->GetRenderFlag(RenderViewWidget::RENDER_NODEORIENTATION)) { - renderUtil->RenderNodeOrientations(actorInstance, emstudioActor->mBoneList, &visibleJointIndices, &selectedJointIndices, renderOptions->GetNodeOrientationScale(), renderOptions->GetScaleBonesOnLength()); + renderUtil->RenderNodeOrientations(actorInstance, emstudioActor->m_boneList, &visibleJointIndices, &selectedJointIndices, renderOptions->GetNodeOrientationScale(), renderOptions->GetScaleBonesOnLength()); } if (widget->GetRenderFlag(RenderViewWidget::RENDER_ACTORBINDPOSE)) { @@ -200,8 +200,7 @@ namespace EMStudio if (widget->GetRenderFlag(RenderViewWidget::RENDER_MOTIONEXTRACTION)) { // render an arrow for the trajectory node - //renderUtil->RenderTrajectoryNode(actorInstance, renderOptions->mTrajectoryArrowInnerColor, renderOptions->mTrajectoryArrowBorderColor, emstudioActor->mCharacterHeight*0.05f); - renderUtil->RenderTrajectoryPath(mPlugin->FindTracePath(actorInstance), renderOptions->GetTrajectoryArrowInnerColor(), emstudioActor->mCharacterHeight * 0.05f); + renderUtil->RenderTrajectoryPath(m_plugin->FindTracePath(actorInstance), renderOptions->GetTrajectoryArrowInnerColor(), emstudioActor->m_characterHeight * 0.05f); } renderUtil->EnableCulling(cullingEnabled); // reset to the old state renderUtil->EnableLighting(lightingEnabled); @@ -220,9 +219,8 @@ namespace EMStudio const size_t numEnabled = actorInstance->GetNumEnabledNodes(); for (size_t i = 0; i < numEnabled; ++i) { - EMotionFX::Node* node = emstudioActor->mActor->GetSkeleton()->GetNode(actorInstance->GetEnabledNode(i)); - EMotionFX::Mesh* mesh = emstudioActor->mActor->GetMesh(geomLODLevel, node->GetNodeIndex()); - //EMotionFX::Mesh* collisionMesh = emstudioActor->mActor->GetCollisionMesh( geomLODLevel, node->GetNodeIndex() ); + EMotionFX::Node* node = emstudioActor->m_actor->GetSkeleton()->GetNode(actorInstance->GetEnabledNode(i)); + EMotionFX::Mesh* mesh = emstudioActor->m_actor->GetMesh(geomLODLevel, node->GetNodeIndex()); const AZ::Transform globalTM = pose->GetWorldSpaceTransform(node->GetNodeIndex()).ToAZTransform(); renderUtil->ResetCurrentMesh(); @@ -234,10 +232,10 @@ namespace EMStudio if (mesh->GetIsCollisionMesh() == false) { - renderUtil->RenderNormals(mesh, globalTM, renderVertexNormals, renderFaceNormals, renderOptions->GetVertexNormalsScale() * emstudioActor->mNormalsScaleMultiplier, renderOptions->GetFaceNormalsScale() * emstudioActor->mNormalsScaleMultiplier, renderOptions->GetVertexNormalsColor(), renderOptions->GetFaceNormalsColor()); + renderUtil->RenderNormals(mesh, globalTM, renderVertexNormals, renderFaceNormals, renderOptions->GetVertexNormalsScale() * emstudioActor->m_normalsScaleMultiplier, renderOptions->GetFaceNormalsScale() * emstudioActor->m_normalsScaleMultiplier, renderOptions->GetVertexNormalsColor(), renderOptions->GetFaceNormalsColor()); if (renderTangents) { - renderUtil->RenderTangents(mesh, globalTM, renderOptions->GetTangentsScale() * emstudioActor->mNormalsScaleMultiplier, renderOptions->GetTangentsColor(), renderOptions->GetMirroredBitangentsColor(), renderOptions->GetBitangentsColor()); + renderUtil->RenderTangents(mesh, globalTM, renderOptions->GetTangentsScale() * emstudioActor->m_normalsScaleMultiplier, renderOptions->GetTangentsColor(), renderOptions->GetMirroredBitangentsColor(), renderOptions->GetBitangentsColor()); } if (renderWireframe) { @@ -253,7 +251,7 @@ namespace EMStudio } // render the selection - if (renderOptions->GetRenderSelectionBox() && EMotionFX::GetActorManager().GetNumActorInstances() != 1 && mPlugin->GetCurrentSelection()->CheckIfHasActorInstance(actorInstance)) + if (renderOptions->GetRenderSelectionBox() && EMotionFX::GetActorManager().GetNumActorInstances() != 1 && m_plugin->GetCurrentSelection()->CheckIfHasActorInstance(actorInstance)) { AZ::Aabb aabb = actorInstance->GetAabb(); aabb.Expand(aabb.GetExtents() * 0.005f); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderUpdateCallback.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderUpdateCallback.h index fed8d5feec..a9bc26ae22 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderUpdateCallback.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderUpdateCallback.h @@ -34,8 +34,8 @@ namespace EMStudio void SetEnableRendering(bool renderingEnabled); protected: - bool mEnableRendering; - RenderPlugin* mPlugin; + bool m_enableRendering; + RenderPlugin* m_plugin; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderViewWidget.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderViewWidget.cpp index 55699c165f..93a6dd3019 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderViewWidget.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderViewWidget.cpp @@ -26,12 +26,12 @@ namespace EMStudio { for (uint32 i = 0; i < NUM_RENDER_OPTIONS; ++i) { - mToolbarButtons[i] = nullptr; - mActions[i] = nullptr; + m_toolbarButtons[i] = nullptr; + m_actions[i] = nullptr; } - mRenderOptionsWindow = nullptr; - mPlugin = parentPlugin; + m_renderOptionsWindow = nullptr; + m_plugin = parentPlugin; // create the vertical layout with the menu and the gl widget as entries QVBoxLayout* verticalLayout = new QVBoxLayout(this); @@ -40,14 +40,14 @@ namespace EMStudio verticalLayout->setMargin(0); // create toolbar - mToolBar = new QToolBar(this); - mToolBar->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + m_toolBar = new QToolBar(this); + m_toolBar->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); // add the toolbar to the vertical layout - verticalLayout->addWidget(mToolBar); + verticalLayout->addWidget(m_toolBar); QWidget* renderWidget = nullptr; - mPlugin->CreateRenderWidget(this, &mRenderWidget, &renderWidget); + m_plugin->CreateRenderWidget(this, &m_renderWidget, &renderWidget); verticalLayout->addWidget(renderWidget); new QActionGroup(this); @@ -65,14 +65,14 @@ namespace EMStudio group->addAction(action); } - mToolBar->addSeparator(); + m_toolBar->addSeparator(); QAction* layoutsAction = AddToolBarAction("Layouts", "Layout_category.svg"); { QMenu* contextMenu = new QMenu(this); - const AZStd::vector& layouts = mPlugin->GetLayouts(); - const RenderPlugin::Layout* currentLayout = mPlugin->GetCurrentLayout(); + const AZStd::vector& layouts = m_plugin->GetLayouts(); + const RenderPlugin::Layout* currentLayout = m_plugin->GetCurrentLayout(); for (RenderPlugin::Layout* layout : layouts) { QAction* layoutAction = contextMenu->addAction(layout->GetName()); @@ -80,15 +80,15 @@ namespace EMStudio layoutAction->setCheckable(true); layoutAction->setChecked(layout == currentLayout); - connect(layoutAction, &QAction::triggered, mPlugin, [this, layout](){ - mPlugin->LayoutButtonPressed(layout->GetName()); + connect(layoutAction, &QAction::triggered, m_plugin, [this, layout](){ + m_plugin->LayoutButtonPressed(layout->GetName()); }); } connect(layoutsAction, &QAction::toggled, contextMenu, &QMenu::show); layoutsAction->setMenu(contextMenu); - auto widgetForAction = qobject_cast(mToolBar->widgetForAction(layoutsAction)); + auto widgetForAction = qobject_cast(m_toolBar->widgetForAction(layoutsAction)); if (widgetForAction) { connect(layoutsAction, &QAction::triggered, widgetForAction, &QToolButton::showMenu); @@ -131,7 +131,7 @@ namespace EMStudio viewOptionsAction->setMenu(contextMenu); - auto widgetForAction = qobject_cast(mToolBar->widgetForAction(viewOptionsAction)); + auto widgetForAction = qobject_cast(m_toolBar->widgetForAction(viewOptionsAction)); if (widgetForAction) { connect(viewOptionsAction, &QAction::triggered, widgetForAction, &QToolButton::showMenu); @@ -166,26 +166,26 @@ namespace EMStudio cameraMenu->addSeparator(); - mFollowCharacterAction = cameraMenu->addAction(tr("Follow Character")); - mFollowCharacterAction->setCheckable(true); - mFollowCharacterAction->setChecked(true); - connect(mFollowCharacterAction, &QAction::triggered, this, &RenderViewWidget::OnFollowCharacter); + m_followCharacterAction = cameraMenu->addAction(tr("Follow Character")); + m_followCharacterAction->setCheckable(true); + m_followCharacterAction->setChecked(true); + connect(m_followCharacterAction, &QAction::triggered, this, &RenderViewWidget::OnFollowCharacter); cameraOptionsAction->setMenu(cameraMenu); - mCameraMenu = cameraMenu; + m_cameraMenu = cameraMenu; - auto widgetForAction = qobject_cast(mToolBar->widgetForAction(cameraOptionsAction)); + auto widgetForAction = qobject_cast(m_toolBar->widgetForAction(cameraOptionsAction)); if (widgetForAction) { connect(cameraOptionsAction, &QAction::triggered, widgetForAction, &QToolButton::showMenu); } } - connect(m_manipulatorModes[RenderOptions::SELECT], &QAction::triggered, mPlugin, &RenderPlugin::SetSelectionMode); - connect(m_manipulatorModes[RenderOptions::TRANSLATE], &QAction::triggered, mPlugin, &RenderPlugin::SetTranslationMode); - connect(m_manipulatorModes[RenderOptions::ROTATE], &QAction::triggered, mPlugin, &RenderPlugin::SetRotationMode); - connect(m_manipulatorModes[RenderOptions::SCALE], &QAction::triggered, mPlugin, &RenderPlugin::SetScaleMode); + connect(m_manipulatorModes[RenderOptions::SELECT], &QAction::triggered, m_plugin, &RenderPlugin::SetSelectionMode); + connect(m_manipulatorModes[RenderOptions::TRANSLATE], &QAction::triggered, m_plugin, &RenderPlugin::SetTranslationMode); + connect(m_manipulatorModes[RenderOptions::ROTATE], &QAction::triggered, m_plugin, &RenderPlugin::SetRotationMode); + connect(m_manipulatorModes[RenderOptions::SCALE], &QAction::triggered, m_plugin, &RenderPlugin::SetScaleMode); QAction* toggleSelectionBoxRendering = new QAction( "Toggle Selection Box Rendering", @@ -195,7 +195,7 @@ namespace EMStudio GetMainWindow()->GetShortcutManager()->RegisterKeyboardShortcut(toggleSelectionBoxRendering, RenderPlugin::s_renderWindowShortcutGroupName, true); connect(toggleSelectionBoxRendering, &QAction::triggered, this, [this] { - mPlugin->GetRenderOptions()->SetRenderSelectionBox(mPlugin->GetRenderOptions()->GetRenderSelectionBox() ^ true); + m_plugin->GetRenderOptions()->SetRenderSelectionBox(m_plugin->GetRenderOptions()->GetRenderSelectionBox() ^ true); }); addAction(toggleSelectionBoxRendering); @@ -257,13 +257,13 @@ namespace EMStudio { const uint32 optionIndex = (uint32)option; - if (mToolbarButtons[optionIndex]) + if (m_toolbarButtons[optionIndex]) { - mToolbarButtons[optionIndex]->setChecked(isEnabled); + m_toolbarButtons[optionIndex]->setChecked(isEnabled); } - if (mActions[optionIndex]) + if (m_actions[optionIndex]) { - mActions[optionIndex]->setChecked(isEnabled); + m_actions[optionIndex]->setChecked(isEnabled); } } @@ -280,7 +280,7 @@ namespace EMStudio if (actionIndex >= 0) { - mActions[actionIndex] = action; + m_actions[actionIndex] = action; } } @@ -290,7 +290,7 @@ namespace EMStudio iconFileName += iconName; const QIcon& icon = MysticQt::GetMysticQt()->FindIcon(iconFileName.c_str()); - QAction* action = mToolBar->addAction(icon, entryName); + QAction* action = m_toolBar->addAction(icon, entryName); return action; } @@ -299,22 +299,22 @@ namespace EMStudio // destructor RenderViewWidget::~RenderViewWidget() { - mPlugin->RemoveViewWidget(this); + m_plugin->RemoveViewWidget(this); } // show the global rendering options dialog void RenderViewWidget::OnOptions() { - if (mRenderOptionsWindow == nullptr) + if (m_renderOptionsWindow == nullptr) { - mRenderOptionsWindow = new PreferencesWindow(this); - mRenderOptionsWindow->Init(); + m_renderOptionsWindow = new PreferencesWindow(this); + m_renderOptionsWindow->Init(); - AzToolsFramework::ReflectedPropertyEditor* generalPropertyWidget = mRenderOptionsWindow->FindPropertyWidgetByName("General"); + AzToolsFramework::ReflectedPropertyEditor* generalPropertyWidget = m_renderOptionsWindow->FindPropertyWidgetByName("General"); if (!generalPropertyWidget) { - generalPropertyWidget = mRenderOptionsWindow->AddCategory("General"); + generalPropertyWidget = m_renderOptionsWindow->AddCategory("General"); generalPropertyWidget->ClearInstances(); generalPropertyWidget->InvalidateAll(); } @@ -327,7 +327,7 @@ namespace EMStudio return; } - PluginOptions* pluginOptions = mPlugin->GetOptions(); + PluginOptions* pluginOptions = m_plugin->GetOptions(); AZ_Assert(pluginOptions, "Expected options in render plugin"); generalPropertyWidget->AddInstance(pluginOptions, azrtti_typeid(pluginOptions)); @@ -339,25 +339,25 @@ namespace EMStudio generalPropertyWidget->InvalidateAll(); } - mRenderOptionsWindow->show(); + m_renderOptionsWindow->show(); } void RenderViewWidget::OnShowSelected() { - mRenderWidget->ViewCloseup(true, DEFAULT_FLIGHT_TIME); + m_renderWidget->ViewCloseup(true, DEFAULT_FLIGHT_TIME); } void RenderViewWidget::OnShowEntireScene() { - mRenderWidget->ViewCloseup(false, DEFAULT_FLIGHT_TIME); + m_renderWidget->ViewCloseup(false, DEFAULT_FLIGHT_TIME); } void RenderViewWidget::SetCharacterFollowModeActive(bool active) { - mFollowCharacterAction->setChecked(active); + m_followCharacterAction->setChecked(active); } @@ -366,9 +366,9 @@ namespace EMStudio CommandSystem::SelectionList& selectionList = GetCommandManager()->GetCurrentSelection(); EMotionFX::ActorInstance* followInstance = selectionList.GetFirstActorInstance(); - if (followInstance && GetIsCharacterFollowModeActive() && mRenderWidget) + if (followInstance && GetIsCharacterFollowModeActive() && m_renderWidget) { - mRenderWidget->ViewCloseup(true, DEFAULT_FLIGHT_TIME, 1); + m_renderWidget->ViewCloseup(true, DEFAULT_FLIGHT_TIME, 1); } } @@ -379,7 +379,7 @@ namespace EMStudio { QAction* action = actionModePair.first; action->setCheckable(true); - action->setChecked(mRenderWidget->GetCameraMode() == actionModePair.second); + action->setChecked(m_renderWidget->GetCameraMode() == actionModePair.second); } } @@ -389,10 +389,10 @@ namespace EMStudio for (uint32 i = 0; i < numRenderOptions; ++i) { QString name = QString(i); - settings->setValue(name, mActions[i] ? mActions[i]->isChecked() : false); + settings->setValue(name, m_actions[i] ? m_actions[i]->isChecked() : false); } - settings->setValue("CameraMode", (int32)mRenderWidget->GetCameraMode()); + settings->setValue("CameraMode", (int32)m_renderWidget->GetCameraMode()); settings->setValue("CharacterFollowMode", GetIsCharacterFollowModeActive()); } @@ -403,7 +403,7 @@ namespace EMStudio for (uint32 i = 0; i < numRenderOptions; ++i) { QString name = QString(i); - const bool isEnabled = settings->value(name, mActions[i] ? mActions[i]->isChecked() : false).toBool(); + const bool isEnabled = settings->value(name, m_actions[i] ? m_actions[i]->isChecked() : false).toBool(); SetRenderFlag((ERenderFlag)i, isEnabled); } @@ -411,8 +411,8 @@ namespace EMStudio SetRenderFlag(RENDER_COLLISIONMESHES, false); SetRenderFlag(RENDER_TEXTURING, false); - RenderWidget::CameraMode cameraMode = (RenderWidget::CameraMode)settings->value("CameraMode", (int32)mRenderWidget->GetCameraMode()).toInt(); - mRenderWidget->SwitchCamera(cameraMode); + RenderWidget::CameraMode cameraMode = (RenderWidget::CameraMode)settings->value("CameraMode", (int32)m_renderWidget->GetCameraMode()).toInt(); + m_renderWidget->SwitchCamera(cameraMode); const bool followMode = settings->value("CharacterFollowMode", GetIsCharacterFollowModeActive()).toBool(); SetCharacterFollowModeActive(followMode); @@ -426,7 +426,7 @@ namespace EMStudio const uint32 numRenderOptions = NUM_RENDER_OPTIONS; for (uint32 i = 0; i < numRenderOptions; ++i) { - if (mActions[i] == action) + if (m_actions[i] == action) { return i; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderViewWidget.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderViewWidget.h index defdb0d2a7..aed4f0c133 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderViewWidget.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderViewWidget.h @@ -71,16 +71,16 @@ namespace EMStudio NUM_RENDER_OPTIONS = 26 }; - MCORE_INLINE bool GetRenderFlag(ERenderFlag option) { return mActions[(uint32)option] ? mActions[(uint32)option]->isChecked() : false; } + MCORE_INLINE bool GetRenderFlag(ERenderFlag option) { return m_actions[(uint32)option] ? m_actions[(uint32)option]->isChecked() : false; } void SetRenderFlag(ERenderFlag option, bool isEnabled); uint32 FindActionIndex(QAction* action); - RenderWidget* GetRenderWidget() const { return mRenderWidget; } - QMenu* GetCameraMenu() const { return mCameraMenu; } + RenderWidget* GetRenderWidget() const { return m_renderWidget; } + QMenu* GetCameraMenu() const { return m_cameraMenu; } void SaveOptions(QSettings* settings); void LoadOptions(QSettings* settings); - bool GetIsCharacterFollowModeActive() const { return mFollowCharacterAction->isChecked(); } + bool GetIsCharacterFollowModeActive() const { return m_followCharacterAction->isChecked(); } void SetCharacterFollowModeActive(bool active); void OnContextMenuEvent(QWidget* renderWidget, bool ctrlPressed, int32 localMouseX, int32 localMouseY, QPoint globalMousePos, RenderPlugin* plugin, MCommon::Camera* camera); @@ -89,17 +89,17 @@ namespace EMStudio public slots: void OnOptions(); - void OnOrbitCamera() { mRenderWidget->SwitchCamera(RenderWidget::CAMMODE_ORBIT); UpdateInterface(); } - void OnFirstPersonCamera() { mRenderWidget->SwitchCamera(RenderWidget::CAMMODE_FIRSTPERSON); UpdateInterface(); } - void OnOrthoFrontCamera() { mRenderWidget->SwitchCamera(RenderWidget::CAMMODE_FRONT); UpdateInterface(); } - void OnOrthoBackCamera() { mRenderWidget->SwitchCamera(RenderWidget::CAMMODE_BACK); UpdateInterface(); } - void OnOrthoLeftCamera() { mRenderWidget->SwitchCamera(RenderWidget::CAMMODE_LEFT); UpdateInterface(); } - void OnOrthoRightCamera() { mRenderWidget->SwitchCamera(RenderWidget::CAMMODE_RIGHT); UpdateInterface(); } - void OnOrthoTopCamera() { mRenderWidget->SwitchCamera(RenderWidget::CAMMODE_TOP); UpdateInterface(); } - void OnOrthoBottomCamera() { mRenderWidget->SwitchCamera(RenderWidget::CAMMODE_BOTTOM); UpdateInterface(); } + void OnOrbitCamera() { m_renderWidget->SwitchCamera(RenderWidget::CAMMODE_ORBIT); UpdateInterface(); } + void OnFirstPersonCamera() { m_renderWidget->SwitchCamera(RenderWidget::CAMMODE_FIRSTPERSON); UpdateInterface(); } + void OnOrthoFrontCamera() { m_renderWidget->SwitchCamera(RenderWidget::CAMMODE_FRONT); UpdateInterface(); } + void OnOrthoBackCamera() { m_renderWidget->SwitchCamera(RenderWidget::CAMMODE_BACK); UpdateInterface(); } + void OnOrthoLeftCamera() { m_renderWidget->SwitchCamera(RenderWidget::CAMMODE_LEFT); UpdateInterface(); } + void OnOrthoRightCamera() { m_renderWidget->SwitchCamera(RenderWidget::CAMMODE_RIGHT); UpdateInterface(); } + void OnOrthoTopCamera() { m_renderWidget->SwitchCamera(RenderWidget::CAMMODE_TOP); UpdateInterface(); } + void OnOrthoBottomCamera() { m_renderWidget->SwitchCamera(RenderWidget::CAMMODE_BOTTOM); UpdateInterface(); } void OnResetCamera(float flightTime = 1.0f) { - MCommon::Camera* camera = mRenderWidget->GetCamera(); + MCommon::Camera* camera = m_renderWidget->GetCamera(); if (camera) { camera->Reset(flightTime); @@ -117,15 +117,15 @@ namespace EMStudio QAction* AddToolBarAction(const char* entryName, const char* iconName); void Reset(); - QToolBar* mToolBar; - QMenu* mCameraMenu; - RenderWidget* mRenderWidget; - QAction* mActions[NUM_RENDER_OPTIONS]; - QAction* mFollowCharacterAction; + QToolBar* m_toolBar; + QMenu* m_cameraMenu; + RenderWidget* m_renderWidget; + QAction* m_actions[NUM_RENDER_OPTIONS]; + QAction* m_followCharacterAction; AZStd::vector> m_cameraModeActions; - QPushButton* mToolbarButtons[NUM_RENDER_OPTIONS]; + QPushButton* m_toolbarButtons[NUM_RENDER_OPTIONS]; AZStd::array m_manipulatorModes; - RenderPlugin* mPlugin; - PreferencesWindow* mRenderOptionsWindow; + RenderPlugin* m_plugin; + PreferencesWindow* m_renderOptionsWindow; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderWidget.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderWidget.cpp index 56d27222bb..429a0bffae 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderWidget.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderWidget.cpp @@ -30,31 +30,28 @@ namespace EMStudio // constructor RenderWidget::RenderWidget(RenderPlugin* renderPlugin, RenderViewWidget* viewWidget) - : mEventHandler(this) + : m_eventHandler(this) { // create our event handler - EMotionFX::GetEventManager().AddEventHandler(&mEventHandler); - - //mLines.SetMemoryCategory(MEMCATEGORY_EMSTUDIOSDK_RENDERPLUGINBASE); - //mLines.Reserve(2048); + EMotionFX::GetEventManager().AddEventHandler(&m_eventHandler); // camera used to render the little axis on the bottom left - mAxisFakeCamera = new MCommon::OrthographicCamera(MCommon::OrthographicCamera::VIEWMODE_FRONT); + m_axisFakeCamera = new MCommon::OrthographicCamera(MCommon::OrthographicCamera::VIEWMODE_FRONT); - mPlugin = renderPlugin; - mViewWidget = viewWidget; - mWidth = 0; - mHeight = 0; - mViewCloseupWaiting = 0; - mPrevMouseX = 0; - mPrevMouseY = 0; - mPrevLocalMouseX = 0; - mPrevLocalMouseY = 0; - mOldActorInstancePos = AZ::Vector3::CreateZero(); - mCamera = nullptr; - mActiveTransformManip = nullptr; - mSkipFollowCalcs = false; - mNeedDisableFollowMode = true; + m_plugin = renderPlugin; + m_viewWidget = viewWidget; + m_width = 0; + m_height = 0; + m_viewCloseupWaiting = 0; + m_prevMouseX = 0; + m_prevMouseY = 0; + m_prevLocalMouseX = 0; + m_prevLocalMouseY = 0; + m_oldActorInstancePos = AZ::Vector3::CreateZero(); + m_camera = nullptr; + m_activeTransformManip = nullptr; + m_skipFollowCalcs = false; + m_needDisableFollowMode = true; } @@ -62,81 +59,81 @@ namespace EMStudio RenderWidget::~RenderWidget() { // get rid of the event handler - EMotionFX::GetEventManager().RemoveEventHandler(&mEventHandler); + EMotionFX::GetEventManager().RemoveEventHandler(&m_eventHandler); // get rid of the camera objects - delete mCamera; - delete mAxisFakeCamera; + delete m_camera; + delete m_axisFakeCamera; } // start view closeup flight void RenderWidget::ViewCloseup(const AZ::Aabb& aabb, float flightTime, uint32 viewCloseupWaiting) { - mViewCloseupWaiting = viewCloseupWaiting; - mViewCloseupAABB = aabb; - mViewCloseupFlightTime = flightTime; + m_viewCloseupWaiting = viewCloseupWaiting; + m_viewCloseupAabb = aabb; + m_viewCloseupFlightTime = flightTime; } void RenderWidget::ViewCloseup(bool selectedInstancesOnly, float flightTime, uint32 viewCloseupWaiting) { - mViewCloseupWaiting = viewCloseupWaiting; - mViewCloseupAABB = mPlugin->GetSceneAabb(selectedInstancesOnly); - mViewCloseupFlightTime = flightTime; + m_viewCloseupWaiting = viewCloseupWaiting; + m_viewCloseupAabb = m_plugin->GetSceneAabb(selectedInstancesOnly); + m_viewCloseupFlightTime = flightTime; } // switch the active camera void RenderWidget::SwitchCamera(CameraMode mode) { - delete mCamera; - mCameraMode = mode; + delete m_camera; + m_cameraMode = mode; switch (mode) { case CAMMODE_ORBIT: { - mCamera = new MCommon::OrbitCamera(); + m_camera = new MCommon::OrbitCamera(); break; } case CAMMODE_FIRSTPERSON: { - mCamera = new MCommon::FirstPersonCamera(); + m_camera = new MCommon::FirstPersonCamera(); break; } case CAMMODE_FRONT: { - mCamera = new MCommon::OrthographicCamera(MCommon::OrthographicCamera::VIEWMODE_FRONT); + m_camera = new MCommon::OrthographicCamera(MCommon::OrthographicCamera::VIEWMODE_FRONT); break; } case CAMMODE_BACK: { - mCamera = new MCommon::OrthographicCamera(MCommon::OrthographicCamera::VIEWMODE_BACK); + m_camera = new MCommon::OrthographicCamera(MCommon::OrthographicCamera::VIEWMODE_BACK); break; } case CAMMODE_LEFT: { - mCamera = new MCommon::OrthographicCamera(MCommon::OrthographicCamera::VIEWMODE_LEFT); + m_camera = new MCommon::OrthographicCamera(MCommon::OrthographicCamera::VIEWMODE_LEFT); break; } case CAMMODE_RIGHT: { - mCamera = new MCommon::OrthographicCamera(MCommon::OrthographicCamera::VIEWMODE_RIGHT); + m_camera = new MCommon::OrthographicCamera(MCommon::OrthographicCamera::VIEWMODE_RIGHT); break; } case CAMMODE_TOP: { - mCamera = new MCommon::OrthographicCamera(MCommon::OrthographicCamera::VIEWMODE_TOP); + m_camera = new MCommon::OrthographicCamera(MCommon::OrthographicCamera::VIEWMODE_TOP); break; } case CAMMODE_BOTTOM: { - mCamera = new MCommon::OrthographicCamera(MCommon::OrthographicCamera::VIEWMODE_BOTTOM); + m_camera = new MCommon::OrthographicCamera(MCommon::OrthographicCamera::VIEWMODE_BOTTOM); break; } } // show the entire scene - mPlugin->ViewCloseup(false, this, 0.0f); + m_plugin->ViewCloseup(false, this, 0.0f); } @@ -160,7 +157,7 @@ namespace EMStudio float camDist = 0.0f; // calculate cam distance for the orthographic cam mode - if (mCamera->GetProjectionMode() == MCommon::Camera::PROJMODE_ORTHOGRAPHIC) + if (m_camera->GetProjectionMode() == MCommon::Camera::PROJMODE_ORTHOGRAPHIC) { camDist = 0.75f; switch (GetCameraMode()) @@ -168,20 +165,20 @@ namespace EMStudio case CAMMODE_FRONT: case CAMMODE_BOTTOM: // -(scale.x) - camDist *= -2.0f / static_cast(mCamera->GetViewProjMatrix().GetElement(0, 0)); + camDist *= -2.0f / static_cast(m_camera->GetViewProjMatrix().GetElement(0, 0)); break; case CAMMODE_BACK: case CAMMODE_TOP: // scale.x - camDist *= 2.0f / static_cast(mCamera->GetViewProjMatrix().GetElement(0, 0)); + camDist *= 2.0f / static_cast(m_camera->GetViewProjMatrix().GetElement(0, 0)); break; case CAMMODE_LEFT: // -(scale.y) - camDist *= -2.0f / static_cast(mCamera->GetViewProjMatrix().GetElement(0, 1)); + camDist *= -2.0f / static_cast(m_camera->GetViewProjMatrix().GetElement(0, 1)); break; case CAMMODE_RIGHT: // scale.y - camDist *= 2.0f / static_cast(mCamera->GetViewProjMatrix().GetElement(0, 1)); + camDist *= 2.0f / static_cast(m_camera->GetViewProjMatrix().GetElement(0, 1)); break; default: break; @@ -191,14 +188,14 @@ namespace EMStudio else { if (activeManipulator->GetSelectionLocked() && - mViewWidget->GetIsCharacterFollowModeActive() == false && + m_viewWidget->GetIsCharacterFollowModeActive() == false && activeManipulator->GetType() == MCommon::TransformationManipulator::GIZMOTYPE_TRANSLATION) { - camDist = (callback->GetOldValueVec() - mCamera->GetPosition()).GetLength(); + camDist = (callback->GetOldValueVec() - m_camera->GetPosition()).GetLength(); } else { - camDist = (activeManipulator->GetPosition() - mCamera->GetPosition()).GetLength(); + camDist = (activeManipulator->GetPosition() - m_camera->GetPosition()).GetLength(); } } @@ -213,14 +210,14 @@ namespace EMStudio } else if (activeManipulator->GetType() == MCommon::TransformationManipulator::GIZMOTYPE_SCALE) { - activeManipulator->SetScale(aznumeric_cast(camDist * 0.15), mCamera); + activeManipulator->SetScale(aznumeric_cast(camDist * 0.15), m_camera); } // update position of the actor instance (needed for camera follow mode) EMotionFX::ActorInstance* actorInstance = callback->GetActorInstance(); if (actorInstance) { - activeManipulator->Init(actorInstance->GetLocalSpaceTransform().mPosition); + activeManipulator->Init(actorInstance->GetLocalSpaceTransform().m_position); } } @@ -229,14 +226,14 @@ namespace EMStudio void RenderWidget::OnMouseMoveEvent(QWidget* renderWidget, QMouseEvent* event) { // calculate the delta mouse movement - int32 deltaX = event->globalX() - mPrevMouseX; - int32 deltaY = event->globalY() - mPrevMouseY; + int32 deltaX = event->globalX() - m_prevMouseX; + int32 deltaY = event->globalY() - m_prevMouseY; // store the current value as previous value - mPrevMouseX = event->globalX(); - mPrevMouseY = event->globalY(); - mPrevLocalMouseX = event->x(); - mPrevLocalMouseY = event->y(); + m_prevMouseX = event->globalX(); + m_prevMouseY = event->globalY(); + m_prevLocalMouseX = event->x(); + m_prevLocalMouseY = event->y(); // get the button states const bool leftButtonPressed = event->buttons() & Qt::LeftButton; @@ -249,7 +246,7 @@ namespace EMStudio // accumulate the number of pixels moved since the last right click if (leftButtonPressed == false && middleButtonPressed == false && rightButtonPressed && altPressed == false) { - mPixelsMovedSinceRightClick += (int32)MCore::Math::Abs(aznumeric_cast(deltaX)) + (int32)MCore::Math::Abs(aznumeric_cast(deltaY)); + m_pixelsMovedSinceRightClick += (int32)MCore::Math::Abs(aznumeric_cast(deltaX)) + (int32)MCore::Math::Abs(aznumeric_cast(deltaY)); } // update size/bounding volumes volumes of all existing gizmos @@ -268,16 +265,16 @@ namespace EMStudio } // get the translate manipulator - MCommon::TransformationManipulator* mouseOveredManip = mPlugin->GetActiveManipulator(mCamera, event->x(), event->y()); + MCommon::TransformationManipulator* mouseOveredManip = m_plugin->GetActiveManipulator(m_camera, event->x(), event->y()); // check if the current manipulator is hit if (mouseOveredManip) { - gizmoHit = mouseOveredManip->Hit(mCamera, event->x(), event->y()); + gizmoHit = mouseOveredManip->Hit(m_camera, event->x(), event->y()); } else { - mouseOveredManip = mActiveTransformManip; + mouseOveredManip = m_activeTransformManip; } // flag to check if mouse wrapping occured @@ -287,34 +284,34 @@ namespace EMStudio //if (activeManipulator != (MCommon::TransformationManipulator*)translateManipulator || (translateManipulator && translateManipulator->GetMode() == MCommon::TranslateManipulator::TRANSLATE_NONE)) if (mouseOveredManip == nullptr || (mouseOveredManip && mouseOveredManip->GetType() != MCommon::TransformationManipulator::GIZMOTYPE_TRANSLATION)) { - const int32 width = mCamera->GetScreenWidth(); - const int32 height = mCamera->GetScreenHeight(); + const int32 width = m_camera->GetScreenWidth(); + const int32 height = m_camera->GetScreenHeight(); // handle mouse wrapping, to enable smoother panning if (event->x() > (int32)width) { mouseWrapped = true; QCursor::setPos(QPoint(event->globalX() - width, event->globalY())); - mPrevMouseX = event->globalX() - width; + m_prevMouseX = event->globalX() - width; } else if (event->x() < 0) { mouseWrapped = true; QCursor::setPos(QPoint(event->globalX() + width, event->globalY())); - mPrevMouseX = event->globalX() + width; + m_prevMouseX = event->globalX() + width; } if (event->y() > (int32)height) { mouseWrapped = true; QCursor::setPos(QPoint(event->globalX(), event->globalY() - height)); - mPrevMouseY = event->globalY() - height; + m_prevMouseY = event->globalY() - height; } else if (event->y() < 0) { mouseWrapped = true; QCursor::setPos(QPoint(event->globalX(), event->globalY() + height)); - mPrevMouseY = event->globalY() + height; + m_prevMouseY = event->globalY() + height; } // don't apply the delta, if mouse has been wrapped @@ -335,16 +332,16 @@ namespace EMStudio } else if (mouseOveredManip->GetSelectionLocked()) { - if (mNeedDisableFollowMode) + if (m_needDisableFollowMode) { MCommon::ManipulatorCallback* callback = mouseOveredManip->GetCallback(); if (callback) { if (callback->GetResetFollowMode()) { - mIsCharacterFollowModeActive = mViewWidget->GetIsCharacterFollowModeActive(); - mViewWidget->SetCharacterFollowModeActive(false); - mNeedDisableFollowMode = false; + m_isCharacterFollowModeActive = m_viewWidget->GetIsCharacterFollowModeActive(); + m_viewWidget->SetCharacterFollowModeActive(false); + m_needDisableFollowMode = false; } } } @@ -363,7 +360,7 @@ namespace EMStudio */ // send mouse movement to the manipulators - mouseOveredManip->ProcessMouseInput(mCamera, event->x(), event->y(), deltaX, deltaY, leftButtonPressed && !altPressed, middleButtonPressed, rightButtonPressed); + mouseOveredManip->ProcessMouseInput(m_camera, event->x(), event->y(), deltaX, deltaY, leftButtonPressed && !altPressed, middleButtonPressed, rightButtonPressed); } else { @@ -379,9 +376,9 @@ namespace EMStudio else { // adjust the camera based on keyboard and mouse input - if (mCamera) + if (m_camera) { - switch (mCameraMode) + switch (m_cameraMode) { case CAMMODE_ORBIT: { @@ -395,11 +392,11 @@ namespace EMStudio { if (deltaY < 0) { - renderWidget->setCursor(mPlugin->GetZoomOutCursor()); + renderWidget->setCursor(m_plugin->GetZoomOutCursor()); } else { - renderWidget->setCursor(mPlugin->GetZoomInCursor()); + renderWidget->setCursor(m_plugin->GetZoomInCursor()); } } // move camera forward, backward, left or right @@ -424,11 +421,11 @@ namespace EMStudio { if (deltaY < 0) { - renderWidget->setCursor(mPlugin->GetZoomOutCursor()); + renderWidget->setCursor(m_plugin->GetZoomOutCursor()); } else { - renderWidget->setCursor(mPlugin->GetZoomInCursor()); + renderWidget->setCursor(m_plugin->GetZoomInCursor()); } } // move camera forward, backward, left or right @@ -442,8 +439,8 @@ namespace EMStudio } } - mCamera->ProcessMouseInput(deltaX, deltaY, leftButtonPressed, middleButtonPressed, rightButtonPressed); - mCamera->Update(); + m_camera->ProcessMouseInput(deltaX, deltaY, leftButtonPressed, middleButtonPressed, rightButtonPressed); + m_camera->Update(); } } @@ -455,13 +452,11 @@ namespace EMStudio void RenderWidget::OnMousePressEvent(QWidget* renderWidget, QMouseEvent* event) { // reset the number of pixels moved since the last right click - mPixelsMovedSinceRightClick = 0; + m_pixelsMovedSinceRightClick = 0; // calculate the delta mouse movement and set old mouse position - //const int32 deltaX = event->globalX() - mPrevMouseX; - //const int32 deltaY = event->globalY() - mPrevMouseY; - mPrevMouseX = event->globalX(); - mPrevMouseY = event->globalY(); + m_prevMouseX = event->globalX(); + m_prevMouseY = event->globalY(); // get the button states const bool leftButtonPressed = event->buttons() & Qt::LeftButton; @@ -473,8 +468,8 @@ namespace EMStudio // set the click position if right click was done if (rightButtonPressed) { - mRightClickPosX = QCursor::pos().x(); - mRightClickPosY = QCursor::pos().y(); + m_rightClickPosX = QCursor::pos().x(); + m_rightClickPosY = QCursor::pos().y(); } // get the current selection @@ -485,7 +480,7 @@ namespace EMStudio MCommon::TransformationManipulator* activeManipulator = nullptr; if (leftButtonPressed && middleButtonPressed == false && rightButtonPressed == false) { - activeManipulator = mPlugin->GetActiveManipulator(mCamera, event->x(), event->y()); + activeManipulator = m_plugin->GetActiveManipulator(m_camera, event->x(), event->y()); } if (activeManipulator) @@ -497,12 +492,12 @@ namespace EMStudio { if (gizmoHit && callback->GetResetFollowMode()) { - mIsCharacterFollowModeActive = mViewWidget->GetIsCharacterFollowModeActive(); - mViewWidget->SetCharacterFollowModeActive(false); - mNeedDisableFollowMode = false; + m_isCharacterFollowModeActive = m_viewWidget->GetIsCharacterFollowModeActive(); + m_viewWidget->SetCharacterFollowModeActive(false); + m_needDisableFollowMode = false; - mActiveTransformManip = activeManipulator; - mActiveTransformManip->ProcessMouseInput(mCamera, event->x(), event->y(), 0, 0, leftButtonPressed && !altPressed, middleButtonPressed, rightButtonPressed); + m_activeTransformManip = activeManipulator; + m_activeTransformManip->ProcessMouseInput(m_camera, event->x(), event->y(), 0, 0, leftButtonPressed && !altPressed, middleButtonPressed, rightButtonPressed); } } @@ -552,7 +547,7 @@ namespace EMStudio EMotionFX::ActorInstance* selectedActorInstance = nullptr; AZ::Vector3 oldIntersectionPoint; - const MCore::Ray ray = mCamera->Unproject(mousePosX, mousePosY); + const MCore::Ray ray = m_camera->Unproject(mousePosX, mousePosY); // get the number of actor instances and iterate through them const size_t numActorInstances = EMotionFX::GetActorManager().GetNumActorInstances(); @@ -581,8 +576,8 @@ namespace EMStudio else { // find the actor instance closer to the camera - const float distOld = (mCamera->GetPosition() - oldIntersectionPoint).GetLength(); - const float distNew = (mCamera->GetPosition() - intersect).GetLength(); + const float distOld = (m_camera->GetPosition() - oldIntersectionPoint).GetLength(); + const float distNew = (m_camera->GetPosition() - intersect).GetLength(); if (distNew < distOld) { selectedActorInstance = actorInstance; @@ -615,7 +610,7 @@ namespace EMStudio } } - mSelectedActorInstances.clear(); + m_selectedActorInstances.clear(); if (ctrlPressed) { @@ -623,16 +618,16 @@ namespace EMStudio const size_t numSelectedActorInstances = selection.GetNumSelectedActorInstances(); for (size_t i = 0; i < numSelectedActorInstances; ++i) { - mSelectedActorInstances.emplace_back(selection.GetActorInstance(i)); + m_selectedActorInstances.emplace_back(selection.GetActorInstance(i)); } } if (selectedActorInstance) { - mSelectedActorInstances.emplace_back(selectedActorInstance); + m_selectedActorInstances.emplace_back(selectedActorInstance); } - CommandSystem::SelectActorInstancesUsingCommands(mSelectedActorInstances); + CommandSystem::SelectActorInstancesUsingCommands(m_selectedActorInstances); } } } @@ -647,10 +642,10 @@ namespace EMStudio if (altPressed == false) { // check which manipulator is currently mouse-overed and use the active one in case we're not hoving any - MCommon::TransformationManipulator* mouseOveredManip = mPlugin->GetActiveManipulator(mCamera, event->x(), event->y()); + MCommon::TransformationManipulator* mouseOveredManip = m_plugin->GetActiveManipulator(m_camera, event->x(), event->y()); if (mouseOveredManip == nullptr) { - mouseOveredManip = mActiveTransformManip; + mouseOveredManip = m_activeTransformManip; } // only do in case a manipulator got hovered or is active @@ -664,35 +659,28 @@ namespace EMStudio } // the manipulator - mouseOveredManip->ProcessMouseInput(mCamera, 0, 0, 0, 0, false, false, false); + mouseOveredManip->ProcessMouseInput(m_camera, 0, 0, 0, 0, false, false, false); // reset the camera follow mode state - if (callback && callback->GetResetFollowMode() && mIsCharacterFollowModeActive) + if (callback && callback->GetResetFollowMode() && m_isCharacterFollowModeActive) { - mViewWidget->SetCharacterFollowModeActive(mIsCharacterFollowModeActive); - mSkipFollowCalcs = true; - - /* CommandSystem::SelectionList& selectionList = GetCommandManager()->GetCurrentSelection(); - ActorInstance* followInstance = selectionList.GetFirstActorInstance(); - if (followInstance) - mOldActorInstancePos = followInstance->GetLocalPos();*/ - - //mViewWidget->OnFollowCharacter(); + m_viewWidget->SetCharacterFollowModeActive(m_isCharacterFollowModeActive); + m_skipFollowCalcs = true; } } } // reset the active manipulator - mActiveTransformManip = nullptr; + m_activeTransformManip = nullptr; // reset the disable follow flag - mNeedDisableFollowMode = true; + m_needDisableFollowMode = true; // set the arrow cursor renderWidget->setCursor(Qt::ArrowCursor); // context menu handling - if (mPixelsMovedSinceRightClick < 5) + if (m_pixelsMovedSinceRightClick < 5) { OnContextMenuEvent(renderWidget, event->modifiers() & Qt::ControlModifier, event->modifiers() & Qt::AltModifier, event->x(), event->y(), event->globalPos()); } @@ -704,14 +692,14 @@ namespace EMStudio { MCORE_UNUSED(renderWidget); - mCamera->ProcessMouseInput(0, + m_camera->ProcessMouseInput(0, event->angleDelta().y(), false, false, true ); - mCamera->Update(); + m_camera->Update(); } @@ -720,29 +708,29 @@ namespace EMStudio { // stop context menu execution, if mouse position changed or alt is pressed // so block it if zooming, moving etc. is enabled - if (QCursor::pos().x() != mRightClickPosX || QCursor::pos().y() != mRightClickPosY || altPressed) + if (QCursor::pos().x() != m_rightClickPosX || QCursor::pos().y() != m_rightClickPosY || altPressed) { return; } // call the context menu handler - mViewWidget->OnContextMenuEvent(renderWidget, shiftPressed, localMouseX, localMouseY, globalMousePos, mPlugin, mCamera); + m_viewWidget->OnContextMenuEvent(renderWidget, shiftPressed, localMouseX, localMouseY, globalMousePos, m_plugin, m_camera); } void RenderWidget::RenderAxis() { - MCommon::RenderUtil* renderUtil = mPlugin->GetRenderUtil(); + MCommon::RenderUtil* renderUtil = m_plugin->GetRenderUtil(); if (renderUtil == nullptr) { return; } // set the camera used to render the axis - MCommon::Camera* camera = mCamera; - if (mCamera->GetType() == MCommon::OrthographicCamera::TYPE_ID) + MCommon::Camera* camera = m_camera; + if (m_camera->GetType() == MCommon::OrthographicCamera::TYPE_ID) { - camera = mAxisFakeCamera; + camera = m_axisFakeCamera; } // store the old projection mode so that we can set it back later on @@ -756,103 +744,103 @@ namespace EMStudio // fake zoom the camera so that we draw the axis in a nice size and remember the old distance int32 distanceFromBorder = 40; float size = 25; - if (mCamera->GetType() == MCommon::OrthographicCamera::TYPE_ID) + if (m_camera->GetType() == MCommon::OrthographicCamera::TYPE_ID) { - MCommon::OrthographicCamera* orgCamera = (MCommon::OrthographicCamera*)mCamera; + MCommon::OrthographicCamera* orgCamera = (MCommon::OrthographicCamera*)m_camera; MCommon::OrthographicCamera* orthoCamera = (MCommon::OrthographicCamera*)camera; orthoCamera->SetCurrentDistance(1.0f); orthoCamera->SetPosition(orgCamera->GetPosition()); orthoCamera->SetMode(orgCamera->GetMode()); - orthoCamera->SetScreenDimensions(mWidth, mHeight); + orthoCamera->SetScreenDimensions(m_width, m_height); size *= 0.001f; } // update the camera - camera->SetOrthoClipDimensions(AZ::Vector2(aznumeric_cast(mWidth), aznumeric_cast(mHeight))); + camera->SetOrthoClipDimensions(AZ::Vector2(aznumeric_cast(m_width), aznumeric_cast(m_height))); camera->Update(); MCommon::RenderUtil::AxisRenderingSettings axisRenderingSettings; int32 originScreenX = 0; int32 originScreenY = 0; - switch (mCameraMode) + switch (m_cameraMode) { case CAMMODE_ORBIT: { originScreenX = distanceFromBorder; - originScreenY = mHeight - distanceFromBorder; - axisRenderingSettings.mRenderXAxis = true; - axisRenderingSettings.mRenderYAxis = true; - axisRenderingSettings.mRenderZAxis = true; + originScreenY = m_height - distanceFromBorder; + axisRenderingSettings.m_renderXAxis = true; + axisRenderingSettings.m_renderYAxis = true; + axisRenderingSettings.m_renderZAxis = true; break; } case CAMMODE_FIRSTPERSON: { originScreenX = distanceFromBorder; - originScreenY = mHeight - distanceFromBorder; - axisRenderingSettings.mRenderXAxis = true; - axisRenderingSettings.mRenderYAxis = true; - axisRenderingSettings.mRenderZAxis = true; + originScreenY = m_height - distanceFromBorder; + axisRenderingSettings.m_renderXAxis = true; + axisRenderingSettings.m_renderYAxis = true; + axisRenderingSettings.m_renderZAxis = true; break; } case CAMMODE_FRONT: { originScreenX = distanceFromBorder; - originScreenY = mHeight - distanceFromBorder; - axisRenderingSettings.mRenderXAxis = true; - axisRenderingSettings.mRenderYAxis = true; - axisRenderingSettings.mRenderZAxis = false; + originScreenY = m_height - distanceFromBorder; + axisRenderingSettings.m_renderXAxis = true; + axisRenderingSettings.m_renderYAxis = true; + axisRenderingSettings.m_renderZAxis = false; break; } case CAMMODE_BACK: { originScreenX = 2 * distanceFromBorder; - originScreenY = mHeight - distanceFromBorder; - axisRenderingSettings.mRenderXAxis = true; - axisRenderingSettings.mRenderYAxis = true; - axisRenderingSettings.mRenderZAxis = false; + originScreenY = m_height - distanceFromBorder; + axisRenderingSettings.m_renderXAxis = true; + axisRenderingSettings.m_renderYAxis = true; + axisRenderingSettings.m_renderZAxis = false; break; } case CAMMODE_LEFT: { originScreenX = distanceFromBorder; - originScreenY = mHeight - distanceFromBorder; - axisRenderingSettings.mRenderXAxis = false; - axisRenderingSettings.mRenderYAxis = true; - axisRenderingSettings.mRenderZAxis = true; + originScreenY = m_height - distanceFromBorder; + axisRenderingSettings.m_renderXAxis = false; + axisRenderingSettings.m_renderYAxis = true; + axisRenderingSettings.m_renderZAxis = true; break; } case CAMMODE_RIGHT: { originScreenX = 2 * distanceFromBorder; - originScreenY = mHeight - distanceFromBorder; - axisRenderingSettings.mRenderXAxis = false; - axisRenderingSettings.mRenderYAxis = true; - axisRenderingSettings.mRenderZAxis = true; + originScreenY = m_height - distanceFromBorder; + axisRenderingSettings.m_renderXAxis = false; + axisRenderingSettings.m_renderYAxis = true; + axisRenderingSettings.m_renderZAxis = true; break; } case CAMMODE_TOP: { originScreenX = distanceFromBorder; - originScreenY = mHeight - distanceFromBorder; - axisRenderingSettings.mRenderXAxis = true; - axisRenderingSettings.mRenderYAxis = false; - axisRenderingSettings.mRenderZAxis = true; + originScreenY = m_height - distanceFromBorder; + axisRenderingSettings.m_renderXAxis = true; + axisRenderingSettings.m_renderYAxis = false; + axisRenderingSettings.m_renderZAxis = true; break; } case CAMMODE_BOTTOM: { originScreenX = 2 * distanceFromBorder; - originScreenY = mHeight - distanceFromBorder; - axisRenderingSettings.mRenderXAxis = true; - axisRenderingSettings.mRenderYAxis = false; - axisRenderingSettings.mRenderZAxis = true; + originScreenY = m_height - distanceFromBorder; + axisRenderingSettings.m_renderXAxis = true; + axisRenderingSettings.m_renderYAxis = false; + axisRenderingSettings.m_renderZAxis = true; break; } default: MCORE_ASSERT(false); } - const AZ::Vector3 axisPosition = MCore::UnprojectOrtho(aznumeric_cast(originScreenX), aznumeric_cast(originScreenY), aznumeric_cast(mWidth), aznumeric_cast(mHeight), 0.0f, camera->GetProjectionMatrix(), camera->GetViewMatrix()); + const AZ::Vector3 axisPosition = MCore::UnprojectOrtho(aznumeric_cast(originScreenX), aznumeric_cast(originScreenY), aznumeric_cast(m_width), aznumeric_cast(m_height), 0.0f, camera->GetProjectionMatrix(), camera->GetViewMatrix()); AZ::Matrix4x4 inverseCameraMatrix = camera->GetViewMatrix(); inverseCameraMatrix.InvertFull(); @@ -860,13 +848,13 @@ namespace EMStudio AZ::Transform worldTM = AZ::Transform::CreateIdentity(); worldTM.SetTranslation(axisPosition); - axisRenderingSettings.mSize = size; - axisRenderingSettings.mWorldTM = worldTM; - axisRenderingSettings.mCameraRight = MCore::GetRight(inverseCameraMatrix).GetNormalized(); - axisRenderingSettings.mCameraUp = MCore::GetUp(inverseCameraMatrix).GetNormalized(); - axisRenderingSettings.mRenderXAxisName = true; - axisRenderingSettings.mRenderYAxisName = true; - axisRenderingSettings.mRenderZAxisName = true; + axisRenderingSettings.m_size = size; + axisRenderingSettings.m_worldTm = worldTM; + axisRenderingSettings.m_cameraRight = MCore::GetRight(inverseCameraMatrix).GetNormalized(); + axisRenderingSettings.m_cameraUp = MCore::GetUp(inverseCameraMatrix).GetNormalized(); + axisRenderingSettings.m_renderXAxisName = true; + axisRenderingSettings.m_renderYAxisName = true; + axisRenderingSettings.m_renderZAxisName = true; // render directly as we have to disable the depth test, hope the additional render call won't slow down so much renderUtil->RenderLineAxis(axisRenderingSettings); @@ -881,18 +869,18 @@ namespace EMStudio void RenderWidget::RenderNodeFilterString() { - MCommon::RenderUtil* renderUtil = mPlugin->GetRenderUtil(); + MCommon::RenderUtil* renderUtil = m_plugin->GetRenderUtil(); if (renderUtil == nullptr) { return; } // render the camera mode name at the bottom of the gl widget - const char* text = mCamera->GetTypeString(); + const char* text = m_camera->GetTypeString(); const uint32 textSize = 10; const uint32 cameraNameColor = MCore::RGBAColor(1.0f, 1.0f, 1.0f, 1.0f).ToInt(); - const uint32 cameraNameX = aznumeric_cast(mWidth * 0.5f); - const uint32 cameraNameY = mHeight - 20; + const uint32 cameraNameX = aznumeric_cast(m_width * 0.5f); + const uint32 cameraNameY = m_height - 20; renderUtil->RenderText(aznumeric_cast(cameraNameX), aznumeric_cast(cameraNameY), text, cameraNameColor, textSize, true); //glColor4f(1.0f, 1.0f, 1.0f, 1.0f); @@ -905,17 +893,17 @@ namespace EMStudio void RenderWidget::UpdateCharacterFollowModeData() { - if (mViewWidget->GetIsCharacterFollowModeActive()) + if (m_viewWidget->GetIsCharacterFollowModeActive()) { const CommandSystem::SelectionList& selectionList = GetCommandManager()->GetCurrentSelection(); EMotionFX::ActorInstance* followInstance = selectionList.GetFirstActorInstance(); - if (followInstance && mCamera) + if (followInstance && m_camera) { - const AZ::Vector3& localPos = followInstance->GetLocalSpaceTransform().mPosition; - mPlugin->GetTranslateManipulator()->Init(localPos); - mPlugin->GetRotateManipulator()->Init(localPos); - mPlugin->GetScaleManipulator()->Init(localPos); + const AZ::Vector3& localPos = followInstance->GetLocalSpaceTransform().m_position; + m_plugin->GetTranslateManipulator()->Init(localPos); + m_plugin->GetRotateManipulator()->Init(localPos); + m_plugin->GetScaleManipulator()->Init(localPos); AZ::Vector3 actorInstancePos; @@ -923,12 +911,12 @@ namespace EMStudio const size_t motionExtractionNodeIndex = followActor->GetMotionExtractionNodeIndex(); if (motionExtractionNodeIndex != InvalidIndex) { - actorInstancePos = followInstance->GetWorldSpaceTransform().mPosition; - RenderPlugin::EMStudioRenderActor* emstudioActor = mPlugin->FindEMStudioActor(followActor); + actorInstancePos = followInstance->GetWorldSpaceTransform().m_position; + RenderPlugin::EMStudioRenderActor* emstudioActor = m_plugin->FindEMStudioActor(followActor); if (emstudioActor) { #ifndef EMFX_SCALE_DISABLED - const float scaledOffsetFromTrajectoryNode = followInstance->GetWorldSpaceTransform().mScale.GetZ() * emstudioActor->mOffsetFromTrajectoryNode; + const float scaledOffsetFromTrajectoryNode = followInstance->GetWorldSpaceTransform().m_scale.GetZ() * emstudioActor->m_offsetFromTrajectoryNode; #else const float scaledOffsetFromTrajectoryNode = 1.0f; #endif @@ -937,25 +925,25 @@ namespace EMStudio } else { - actorInstancePos = followInstance->GetWorldSpaceTransform().mPosition; + actorInstancePos = followInstance->GetWorldSpaceTransform().m_position; } // Calculate movement since last frame. - AZ::Vector3 deltaPos = actorInstancePos - mOldActorInstancePos; + AZ::Vector3 deltaPos = actorInstancePos - m_oldActorInstancePos; - if (mSkipFollowCalcs) + if (m_skipFollowCalcs) { deltaPos = AZ::Vector3::CreateZero(); - mSkipFollowCalcs = false; + m_skipFollowCalcs = false; } - mOldActorInstancePos = actorInstancePos; + m_oldActorInstancePos = actorInstancePos; - switch (mCamera->GetType()) + switch (m_camera->GetType()) { case MCommon::OrbitCamera::TYPE_ID: { - MCommon::OrbitCamera* orbitCamera = static_cast(mCamera); + MCommon::OrbitCamera* orbitCamera = static_cast(m_camera); if (orbitCamera->GetIsFlightActive()) { @@ -972,7 +960,7 @@ namespace EMStudio case MCommon::OrthographicCamera::TYPE_ID: { - MCommon::OrthographicCamera* orthoCamera = static_cast(mCamera); + MCommon::OrthographicCamera* orthoCamera = static_cast(m_camera); if (orthoCamera->GetIsFlightActive()) { @@ -990,7 +978,7 @@ namespace EMStudio } else { - mOldActorInstancePos.Set(0.0f, 0.0f, 0.0f); + m_oldActorInstancePos.Set(0.0f, 0.0f, 0.0f); } } @@ -998,7 +986,7 @@ namespace EMStudio // render the manipulator gizmos void RenderWidget::RenderManipulators() { - MCommon::RenderUtil* renderUtil = mPlugin->GetRenderUtil(); + MCommon::RenderUtil* renderUtil = m_plugin->GetRenderUtil(); if (renderUtil == nullptr) { return; @@ -1019,7 +1007,7 @@ namespace EMStudio UpdateActiveTransformationManipulator(activeManipulator); // render the current actor - activeManipulator->Render(mCamera, renderUtil); + activeManipulator->Render(m_camera, renderUtil); } // render any remaining lines @@ -1033,16 +1021,16 @@ namespace EMStudio // render all triangles that got added to the render util void RenderWidget::RenderTriangles() { - MCommon::RenderUtil* renderUtil = mPlugin->GetRenderUtil(); + MCommon::RenderUtil* renderUtil = m_plugin->GetRenderUtil(); if (renderUtil == nullptr) { return; } // render custom triangles - for (const Triangle& curTri : mTriangles) + for (const Triangle& curTri : m_triangles) { - renderUtil->AddTriangle(curTri.mPosA, curTri.mPosB, curTri.mPosC, curTri.mNormalA, curTri.mNormalB, curTri.mNormalC, curTri.mColor); // TODO: make renderutil use uint32 colors instead + renderUtil->AddTriangle(curTri.m_posA, curTri.m_posB, curTri.m_posC, curTri.m_normalA, curTri.m_normalB, curTri.m_normalC, curTri.m_color); // TODO: make renderutil use uint32 colors instead } ClearTriangles(); @@ -1053,7 +1041,7 @@ namespace EMStudio // iterate through all plugins and render their helper data void RenderWidget::RenderCustomPluginData() { - MCommon::RenderUtil* renderUtil = mPlugin->GetRenderUtil(); + MCommon::RenderUtil* renderUtil = m_plugin->GetRenderUtil(); if (renderUtil == nullptr) { return; @@ -1064,9 +1052,9 @@ namespace EMStudio for (size_t i = 0; i < numPlugins; ++i) { EMStudioPlugin* plugin = GetPluginManager()->GetActivePlugin(i); - EMStudioPlugin::RenderInfo renderInfo(renderUtil, mCamera, mWidth, mHeight); + EMStudioPlugin::RenderInfo renderInfo(renderUtil, m_camera, m_width, m_height); - plugin->Render(mPlugin, &renderInfo); + plugin->Render(m_plugin, &renderInfo); } RenderDebugDraw(); @@ -1078,7 +1066,7 @@ namespace EMStudio void RenderWidget::RenderDebugDraw() { - MCommon::RenderUtil* renderUtil = mPlugin->GetRenderUtil(); + MCommon::RenderUtil* renderUtil = m_plugin->GetRenderUtil(); if (!renderUtil) { return; @@ -1107,14 +1095,14 @@ namespace EMStudio // render solid characters void RenderWidget::RenderActorInstances() { - MCommon::RenderUtil* renderUtil = mPlugin->GetRenderUtil(); + MCommon::RenderUtil* renderUtil = m_plugin->GetRenderUtil(); if (renderUtil == nullptr) { return; } // backface culling - const bool backfaceCullingEnabled = mViewWidget->GetRenderFlag(RenderViewWidget::RENDER_BACKFACECULLING); + const bool backfaceCullingEnabled = m_viewWidget->GetRenderFlag(RenderViewWidget::RENDER_BACKFACECULLING); renderUtil->EnableCulling(backfaceCullingEnabled); EMotionFX::GetAnimGraphManager().SetAnimGraphVisualizationEnabled(true); @@ -1129,7 +1117,7 @@ namespace EMStudio EMotionFX::ActorInstance* actorInstance = EMotionFX::GetActorManager().GetActorInstance(i); if (actorInstance->GetRender() && actorInstance->GetIsVisible() && actorInstance->GetIsOwnedByRuntime() == false) { - mPlugin->RenderActorInstance(actorInstance, 0.0f); + m_plugin->RenderActorInstance(actorInstance, 0.0f); } } } @@ -1138,34 +1126,34 @@ namespace EMStudio // prepare the camera void RenderWidget::UpdateCamera() { - if (mCamera == nullptr) + if (m_camera == nullptr) { return; } - RenderOptions* renderOptions = mPlugin->GetRenderOptions(); + RenderOptions* renderOptions = m_plugin->GetRenderOptions(); // update the camera - mCamera->SetNearClipDistance(renderOptions->GetNearClipPlaneDistance()); - mCamera->SetFarClipDistance(renderOptions->GetFarClipPlaneDistance()); - mCamera->SetFOV(renderOptions->GetFOV()); - mCamera->SetAspectRatio(mWidth / (float)mHeight); - mCamera->SetScreenDimensions(mWidth, mHeight); - mCamera->AutoUpdateLimits(); + m_camera->SetNearClipDistance(renderOptions->GetNearClipPlaneDistance()); + m_camera->SetFarClipDistance(renderOptions->GetFarClipPlaneDistance()); + m_camera->SetFOV(renderOptions->GetFOV()); + m_camera->SetAspectRatio(m_width / (float)m_height); + m_camera->SetScreenDimensions(m_width, m_height); + m_camera->AutoUpdateLimits(); - if (mViewCloseupWaiting != 0 && mHeight != 0 && mWidth != 0) + if (m_viewCloseupWaiting != 0 && m_height != 0 && m_width != 0) { - mViewCloseupWaiting--; - if (mViewCloseupWaiting == 0) + m_viewCloseupWaiting--; + if (m_viewCloseupWaiting == 0) { - mCamera->ViewCloseup(MCore::AABB(mViewCloseupAABB.GetMin(), mViewCloseupAABB.GetMax()), mViewCloseupFlightTime); + m_camera->ViewCloseup(MCore::AABB(m_viewCloseupAabb.GetMin(), m_viewCloseupAabb.GetMax()), m_viewCloseupFlightTime); } } // update the manipulators, camera, old actor instance position etc. when using the character follow mode UpdateCharacterFollowModeData(); - mCamera->Update(); + m_camera->Update(); } @@ -1173,14 +1161,14 @@ namespace EMStudio void RenderWidget::RenderGrid() { // directly return in case we do not want to render any type of grid - if (mViewWidget->GetRenderFlag(RenderViewWidget::RENDER_GRID) == false) + if (m_viewWidget->GetRenderFlag(RenderViewWidget::RENDER_GRID) == false) { return; } // get access to the render utility and render options - MCommon::RenderUtil* renderUtil = mPlugin->GetRenderUtil(); - RenderOptions* renderOptions = mPlugin->GetRenderOptions(); + MCommon::RenderUtil* renderUtil = m_plugin->GetRenderUtil(); + RenderOptions* renderOptions = m_plugin->GetRenderOptions(); if (renderUtil == nullptr || renderOptions == nullptr) { return; @@ -1189,20 +1177,20 @@ namespace EMStudio const float unitSize = renderOptions->GetGridUnitSize(); AZ::Vector3 gridNormal = AZ::Vector3(0.0f, 0.0f, 1.0f); - if (mCamera->GetType() == MCommon::OrthographicCamera::TYPE_ID) + if (m_camera->GetType() == MCommon::OrthographicCamera::TYPE_ID) { // disable depth writing for ortho views renderUtil->SetDepthMaskWrite(false); - switch (mCameraMode) + switch (m_cameraMode) { case CAMMODE_LEFT: case CAMMODE_RIGHT: - gridNormal = MCore::GetForward(mCamera->GetViewMatrix()); + gridNormal = MCore::GetForward(m_camera->GetViewMatrix()); break; default: - gridNormal = MCore::GetUp(mCamera->GetViewMatrix()); + gridNormal = MCore::GetUp(m_camera->GetViewMatrix()); } gridNormal.Normalize(); } @@ -1210,8 +1198,8 @@ namespace EMStudio // render the grid AZ::Vector2 gridStart, gridEnd; - renderUtil->CalcVisibleGridArea(mCamera, mWidth, mHeight, unitSize, &gridStart, &gridEnd); - if (mViewWidget->GetRenderFlag(RenderViewWidget::RENDER_GRID)) + renderUtil->CalcVisibleGridArea(m_camera, m_width, m_height, unitSize, &gridStart, &gridEnd); + if (m_viewWidget->GetRenderFlag(RenderViewWidget::RENDER_GRID)) { renderUtil->RenderGrid(gridStart, gridEnd, gridNormal, unitSize, renderOptions->GetMainAxisColor(), renderOptions->GetGridColor(), renderOptions->GetSubStepColor(), true); } @@ -1222,9 +1210,9 @@ namespace EMStudio void RenderWidget::closeEvent([[maybe_unused]] QCloseEvent* event) { - if (mPlugin) + if (m_plugin) { - mPlugin->SaveRenderOptions(); + m_plugin->SaveRenderOptions(); } } } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderWidget.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderWidget.h index d2ec5d71ea..d4906355da 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderWidget.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderWidget.h @@ -47,25 +47,25 @@ namespace EMStudio struct Triangle { - AZ::Vector3 mPosA; - AZ::Vector3 mPosB; - AZ::Vector3 mPosC; + AZ::Vector3 m_posA; + AZ::Vector3 m_posB; + AZ::Vector3 m_posC; - AZ::Vector3 mNormalA; - AZ::Vector3 mNormalB; - AZ::Vector3 mNormalC; + AZ::Vector3 m_normalA; + AZ::Vector3 m_normalB; + AZ::Vector3 m_normalC; - uint32 mColor; + uint32 m_color; Triangle() {} Triangle(const AZ::Vector3& posA, const AZ::Vector3& posB, const AZ::Vector3& posC, const AZ::Vector3& normalA, const AZ::Vector3& normalB, const AZ::Vector3& normalC, uint32 color) - : mPosA(posA) - , mPosB(posB) - , mPosC(posC) - , mNormalA(normalA) - , mNormalB(normalB) - , mNormalC(normalC) - , mColor(color) {} + : m_posA(posA) + , m_posB(posB) + , m_posC(posC) + , m_normalA(normalA) + , m_normalB(normalB) + , m_normalC(normalC) + , m_color(color) {} }; @@ -76,16 +76,16 @@ namespace EMStudio AZ_CLASS_ALLOCATOR_DECL EventHandler(RenderWidget* widget) - : EMotionFX::EventHandler() { mWidget = widget; } + : EMotionFX::EventHandler() { m_widget = widget; } ~EventHandler() {} // overloaded const AZStd::vector GetHandledEventTypes() const override { return { EMotionFX::EVENT_TYPE_ON_DRAW_LINE, EMotionFX::EVENT_TYPE_ON_DRAW_TRIANGLE, EMotionFX::EVENT_TYPE_ON_DRAW_TRIANGLES }; } - MCORE_INLINE void OnDrawTriangle(const AZ::Vector3& posA, const AZ::Vector3& posB, const AZ::Vector3& posC, const AZ::Vector3& normalA, const AZ::Vector3& normalB, const AZ::Vector3& normalC, uint32 color) { mWidget->AddTriangle(posA, posB, posC, normalA, normalB, normalC, color); } - MCORE_INLINE void OnDrawTriangles() { mWidget->RenderTriangles(); } + MCORE_INLINE void OnDrawTriangle(const AZ::Vector3& posA, const AZ::Vector3& posB, const AZ::Vector3& posC, const AZ::Vector3& normalA, const AZ::Vector3& normalB, const AZ::Vector3& normalC, uint32 color) { m_widget->AddTriangle(posA, posB, posC, normalA, normalB, normalC, color); } + MCORE_INLINE void OnDrawTriangles() { m_widget->RenderTriangles(); } private: - RenderWidget* mWidget; + RenderWidget* m_widget; }; RenderWidget(RenderPlugin* renderPlugin, RenderViewWidget* viewWidget); @@ -98,8 +98,8 @@ namespace EMStudio virtual void Update() = 0; // line rendering helper functions - MCORE_INLINE void AddTriangle(const AZ::Vector3& posA, const AZ::Vector3& posB, const AZ::Vector3& posC, const AZ::Vector3& normalA, const AZ::Vector3& normalB, const AZ::Vector3& normalC, uint32 color) { mTriangles.emplace_back(Triangle(posA, posB, posC, normalA, normalB, normalC, color)); } - MCORE_INLINE void ClearTriangles() { mTriangles.clear(); } + MCORE_INLINE void AddTriangle(const AZ::Vector3& posA, const AZ::Vector3& posB, const AZ::Vector3& posC, const AZ::Vector3& normalA, const AZ::Vector3& normalB, const AZ::Vector3& normalC, uint32 color) { m_triangles.emplace_back(Triangle(posA, posB, posC, normalA, normalB, normalC, color)); } + MCORE_INLINE void ClearTriangles() { m_triangles.clear(); } void RenderTriangles(); // helper rendering functions @@ -113,16 +113,16 @@ namespace EMStudio void UpdateCamera(); // camera helper functions - MCORE_INLINE MCommon::Camera* GetCamera() const { return mCamera; } - MCORE_INLINE CameraMode GetCameraMode() const { return mCameraMode; } - MCORE_INLINE void SetSkipFollowCalcs(bool skipFollowCalcs) { mSkipFollowCalcs = skipFollowCalcs; } + MCORE_INLINE MCommon::Camera* GetCamera() const { return m_camera; } + MCORE_INLINE CameraMode GetCameraMode() const { return m_cameraMode; } + MCORE_INLINE void SetSkipFollowCalcs(bool skipFollowCalcs) { m_skipFollowCalcs = skipFollowCalcs; } void ViewCloseup(const AZ::Aabb& aabb, float flightTime, uint32 viewCloseupWaiting = 5); void ViewCloseup(bool selectedInstancesOnly, float flightTime, uint32 viewCloseupWaiting = 5); void SwitchCamera(CameraMode mode); // render bugger dimensions - MCORE_INLINE uint32 GetScreenWidth() const { return mWidth; } - MCORE_INLINE uint32 GetScreenHeight() const { return mHeight; } + MCORE_INLINE uint32 GetScreenWidth() const { return m_width; } + MCORE_INLINE uint32 GetScreenHeight() const { return m_height; } // helper functions for easy calling void OnMouseMoveEvent(QWidget* renderWidget, QMouseEvent* event); @@ -137,40 +137,40 @@ namespace EMStudio void closeEvent(QCloseEvent* event); - RenderPlugin* mPlugin; - RenderViewWidget* mViewWidget; - AZStd::vector mTriangles; - EventHandler mEventHandler; + RenderPlugin* m_plugin; + RenderViewWidget* m_viewWidget; + AZStd::vector m_triangles; + EventHandler m_eventHandler; - AZStd::vector mSelectedActorInstances; + AZStd::vector m_selectedActorInstances; - MCommon::TransformationManipulator* mActiveTransformManip; + MCommon::TransformationManipulator* m_activeTransformManip; // camera helper data - CameraMode mCameraMode; - MCommon::Camera* mCamera; - MCommon::Camera* mAxisFakeCamera; - bool mIsCharacterFollowModeActive; - bool mSkipFollowCalcs; - bool mNeedDisableFollowMode; + CameraMode m_cameraMode; + MCommon::Camera* m_camera; + MCommon::Camera* m_axisFakeCamera; + bool m_isCharacterFollowModeActive; + bool m_skipFollowCalcs; + bool m_needDisableFollowMode; // render buffer dimensions - uint32 mWidth; - uint32 mHeight; + uint32 m_width; + uint32 m_height; // used for closeup camera flights - uint32 mViewCloseupWaiting; - AZ::Aabb mViewCloseupAABB; - float mViewCloseupFlightTime; + uint32 m_viewCloseupWaiting; + AZ::Aabb m_viewCloseupAabb; + float m_viewCloseupFlightTime; // manipulator helper data - AZ::Vector3 mOldActorInstancePos; - int32 mPrevMouseX; - int32 mPrevMouseY; - int32 mPrevLocalMouseX; - int32 mPrevLocalMouseY; - int32 mRightClickPosX; - int32 mRightClickPosY; - int32 mPixelsMovedSinceRightClick; + AZ::Vector3 m_oldActorInstancePos; + int32 m_prevMouseX; + int32 m_prevMouseY; + int32 m_prevLocalMouseX; + int32 m_prevLocalMouseY; + int32 m_rightClickPosX; + int32 m_rightClickPosY; + int32 m_pixelsMovedSinceRightClick; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/SaveChangedFilesManager.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/SaveChangedFilesManager.cpp index 5e624fd75e..6919877170 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/SaveChangedFilesManager.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/SaveChangedFilesManager.cpp @@ -30,11 +30,11 @@ namespace EMStudio { SaveDirtyFilesCallback::ObjectPointer::ObjectPointer() : - mActor(nullptr), - mMotion(nullptr), - mMotionSet(nullptr), - mAnimGraph(nullptr), - mWorkspace(nullptr) + m_actor(nullptr), + m_motion(nullptr), + m_motionSet(nullptr), + m_animGraph(nullptr), + m_workspace(nullptr) { } @@ -52,7 +52,7 @@ namespace EMStudio return; } - mSaveDirtyFilesCallbacks.erase(AZStd::remove(mSaveDirtyFilesCallbacks.begin(), mSaveDirtyFilesCallbacks.end(), callback), mSaveDirtyFilesCallbacks.end()); + m_saveDirtyFilesCallbacks.erase(AZStd::remove(m_saveDirtyFilesCallbacks.begin(), m_saveDirtyFilesCallbacks.end(), callback), m_saveDirtyFilesCallbacks.end()); if (delFromMem) { @@ -63,21 +63,18 @@ namespace EMStudio void DirtyFileManager::SaveSettings() { - const size_t numDirtyFilesCallbacks = mSaveDirtyFilesCallbacks.size(); + const size_t numDirtyFilesCallbacks = m_saveDirtyFilesCallbacks.size(); // save the callback settings to the config file QSettings settings; settings.beginGroup("EMotionFX"); settings.beginGroup("DirtyFileManager"); - //settings.setValue("ShowSettingsWindow", mShowDirtyFileSettingsWindow); for (size_t i = 0; i < numDirtyFilesCallbacks; ++i) { - settings.beginGroup(mSaveDirtyFilesCallbacks[i]->GetFileType()); - settings.setValue("FileExtension", mSaveDirtyFilesCallbacks[i]->GetExtension()); - //settings.setValue( "AskIndividually", mSaveDirtyFilesCallbacks[i]->AskIndividually()); - //settings.setValue( "SkipSaving", mSaveDirtyFilesCallbacks[i]->SkipSaving()); + settings.beginGroup(m_saveDirtyFilesCallbacks[i]->GetFileType()); + settings.setValue("FileExtension", m_saveDirtyFilesCallbacks[i]->GetExtension()); settings.endGroup(); } @@ -89,12 +86,12 @@ namespace EMStudio // destructor DirtyFileManager::~DirtyFileManager() { - const size_t numDirtyFilesCallbacks = mSaveDirtyFilesCallbacks.size(); + const size_t numDirtyFilesCallbacks = m_saveDirtyFilesCallbacks.size(); for (size_t i = 0; i < numDirtyFilesCallbacks; ++i) { - delete mSaveDirtyFilesCallbacks[i]; + delete m_saveDirtyFilesCallbacks[i]; } - mSaveDirtyFilesCallbacks.clear(); + m_saveDirtyFilesCallbacks.clear(); } @@ -134,10 +131,10 @@ namespace EMStudio size_t insertIndex = MCORE_INVALIDINDEX32; // get the number of callbacks and iterate through them - const size_t numCallbacks = mSaveDirtyFilesCallbacks.size(); + const size_t numCallbacks = m_saveDirtyFilesCallbacks.size(); for (size_t i = 0; i < numCallbacks; ++i) { - const uint32 currentPriority = mSaveDirtyFilesCallbacks[i]->GetPriority(); + const uint32 currentPriority = m_saveDirtyFilesCallbacks[i]->GetPriority(); if (newPriority > currentPriority) { @@ -149,11 +146,11 @@ namespace EMStudio // add the new callback if (insertIndex == MCORE_INVALIDINDEX32) { - mSaveDirtyFilesCallbacks.push_back(callback); + m_saveDirtyFilesCallbacks.push_back(callback); } else { - mSaveDirtyFilesCallbacks.insert(mSaveDirtyFilesCallbacks.begin()+insertIndex, callback); + m_saveDirtyFilesCallbacks.insert(m_saveDirtyFilesCallbacks.begin()+insertIndex, callback); } } @@ -162,12 +159,12 @@ namespace EMStudio { AZStd::vector neededCallbacks; - const size_t numDirtyFilesCallbacks = mSaveDirtyFilesCallbacks.size(); + const size_t numDirtyFilesCallbacks = m_saveDirtyFilesCallbacks.size(); // check if there are any dirty files for (size_t i = 0; i < numDirtyFilesCallbacks; ++i) { - SaveDirtyFilesCallback* callback = mSaveDirtyFilesCallbacks[i]; + SaveDirtyFilesCallback* callback = m_saveDirtyFilesCallbacks[i]; // make sure we want to handle the given save dirty files callback if ((type != MCORE_INVALIDINDEX32 && callback->GetType() != type) || (filter != MCORE_INVALIDINDEX32 && callback->GetType() == filter)) @@ -184,11 +181,11 @@ namespace EMStudio { AZStd::vector neededCallbacks; - const size_t numDirtyFilesCallbacks = mSaveDirtyFilesCallbacks.size(); + const size_t numDirtyFilesCallbacks = m_saveDirtyFilesCallbacks.size(); for (size_t i = 0; i < numDirtyFilesCallbacks; ++i) { - SaveDirtyFilesCallback* callback = mSaveDirtyFilesCallbacks[i]; + SaveDirtyFilesCallback* callback = m_saveDirtyFilesCallbacks[i]; // make sure we want to handle the given save dirty files callback if (AZStd::find(typeIds.begin(), typeIds.end(), callback->GetFileRttiType()) != typeIds.end()) @@ -333,9 +330,9 @@ namespace EMStudio MCORE_ASSERT(dirtyFileNames.size() == objects.size()); // store values - mFileNames = dirtyFileNames; - mObjects = objects; - mSaveDirtyFiles = true; + m_fileNames = dirtyFileNames; + m_objects = objects; + m_saveDirtyFiles = true; // update title of the dialog setWindowTitle("Save Changes To Files"); @@ -350,54 +347,54 @@ namespace EMStudio vLayout->addWidget(new QLabel("Do you want to save changes? The following files have been changed but have not been saved yet:")); // create the lod information table - mTableWidget = new QTableWidget(); - mTableWidget->setAlternatingRowColors(true); - mTableWidget->setSelectionMode(QAbstractItemView::NoSelection); - mTableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers); - mTableWidget->setMinimumHeight(250); - mTableWidget->setMinimumWidth(600); - mTableWidget->verticalHeader()->hide(); + m_tableWidget = new QTableWidget(); + m_tableWidget->setAlternatingRowColors(true); + m_tableWidget->setSelectionMode(QAbstractItemView::NoSelection); + m_tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers); + m_tableWidget->setMinimumHeight(250); + m_tableWidget->setMinimumWidth(600); + m_tableWidget->verticalHeader()->hide(); // disable the corner button between the row and column selection thingies - mTableWidget->setCornerButtonEnabled(false); + m_tableWidget->setCornerButtonEnabled(false); // enable the custom context menu for the motion table - mTableWidget->setContextMenuPolicy(Qt::DefaultContextMenu); + m_tableWidget->setContextMenuPolicy(Qt::DefaultContextMenu); // disable sorting when adding the items - mTableWidget->setSortingEnabled(false); + m_tableWidget->setSortingEnabled(false); // clear the table widget - mTableWidget->clear(); - mTableWidget->setColumnCount(3); + m_tableWidget->clear(); + m_tableWidget->setColumnCount(3); // set header items for the table QTableWidgetItem* headerItem = new QTableWidgetItem(""); headerItem->setTextAlignment(Qt::AlignVCenter | Qt::AlignLeft); - mTableWidget->setHorizontalHeaderItem(0, headerItem); + m_tableWidget->setHorizontalHeaderItem(0, headerItem); headerItem = new QTableWidgetItem("FileName"); headerItem->setTextAlignment(Qt::AlignVCenter | Qt::AlignLeft); - mTableWidget->setHorizontalHeaderItem(1, headerItem); + m_tableWidget->setHorizontalHeaderItem(1, headerItem); headerItem = new QTableWidgetItem("Type"); headerItem->setTextAlignment(Qt::AlignVCenter | Qt::AlignLeft); - mTableWidget->setHorizontalHeaderItem(2, headerItem); + m_tableWidget->setHorizontalHeaderItem(2, headerItem); // set column resize modes. The main filename is in column 1, and // stretches to fill any remaining space. The other columns are // informational only, and not very wide, so setting them to always // resize to their contents means we don't have to manage their column // widths. - QHeaderView* horizontalHeader = mTableWidget->horizontalHeader(); + QHeaderView* horizontalHeader = m_tableWidget->horizontalHeader(); horizontalHeader->setSectionResizeMode(0, QHeaderView::ResizeToContents); horizontalHeader->setSectionResizeMode(1, QHeaderView::Stretch); horizontalHeader->setSectionResizeMode(2, QHeaderView::ResizeToContents); const size_t numDirtyFiles = dirtyFileNames.size(); - mTableWidget->setRowCount(static_cast(numDirtyFiles)); + m_tableWidget->setRowCount(static_cast(numDirtyFiles)); for (size_t i = 0; i < numDirtyFiles; ++i) { - SaveDirtyFilesCallback::ObjectPointer object = mObjects[i]; + SaveDirtyFilesCallback::ObjectPointer object = m_objects[i]; QString labelText; if (dirtyFileNames[i].empty()) @@ -438,23 +435,23 @@ namespace EMStudio filenameLabel->setText(labelText); QString typeString; - if (object.mMotion) + if (object.m_motion) { typeString = "Motion"; } - else if (object.mActor) + else if (object.m_actor) { typeString = "Actor"; } - else if (object.mMotionSet) + else if (object.m_motionSet) { typeString = "Motion Set"; } - else if (object.mAnimGraph) + else if (object.m_animGraph) { typeString = "Anim Graph"; } - else if (object.mWorkspace) + else if (object.m_workspace) { typeString = "Workspace"; } @@ -464,19 +461,19 @@ namespace EMStudio itemType->setData(Qt::UserRole, row); // add table items to the current row - mTableWidget->setCellWidget(row, 0, checkbox); - mTableWidget->setCellWidget(row, 1, filenameLabel); - mTableWidget->setItem(row, 2, itemType); + m_tableWidget->setCellWidget(row, 0, checkbox); + m_tableWidget->setCellWidget(row, 1, filenameLabel); + m_tableWidget->setItem(row, 2, itemType); // set the row height - mTableWidget->setRowHeight(row, 21); + m_tableWidget->setRowHeight(row, 21); } // enable sorting - mTableWidget->setSortingEnabled(true); + m_tableWidget->setSortingEnabled(true); // add the table in the layout - vLayout->addWidget(mTableWidget); + vLayout->addWidget(m_tableWidget); // the buttons at the bottom of the dialog QDialogButtonBox* buttonBox = new QDialogButtonBox(buttons); @@ -525,26 +522,26 @@ namespace EMStudio outFileNames->clear(); outObjects->clear(); - const uint32 numRows = mTableWidget->rowCount(); + const uint32 numRows = m_tableWidget->rowCount(); // iteration for motions, motion sets, actors and anim graphs for (uint32 i = 0; i < numRows; ++i) { // get the checkbox - QWidget* widget = mTableWidget->cellWidget(i, 0); + QWidget* widget = m_tableWidget->cellWidget(i, 0); QCheckBox* checkbox = static_cast(widget); // get the type item - QTableWidgetItem* item = mTableWidget->item(i, 2); + QTableWidgetItem* item = m_tableWidget->item(i, 2); const int32 filenameIndex = item->data(Qt::UserRole).toInt(); // get the object pointer - SaveDirtyFilesCallback::ObjectPointer objPointer = mObjects[filenameIndex]; + SaveDirtyFilesCallback::ObjectPointer objPointer = m_objects[filenameIndex]; // add the filename to the list of selected filenames in case the checkbox in the same row is checked if (checkbox->isChecked()) { - outFileNames->push_back(mFileNames[filenameIndex]); + outFileNames->push_back(m_fileNames[filenameIndex]); outObjects->push_back(objPointer); } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/SaveChangedFilesManager.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/SaveChangedFilesManager.h index aabfddd687..48c47ef2ec 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/SaveChangedFilesManager.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/SaveChangedFilesManager.h @@ -40,11 +40,11 @@ namespace EMStudio ObjectPointer(); - EMotionFX::Actor * mActor; - EMotionFX::Motion* mMotion; - EMotionFX::MotionSet* mMotionSet; - EMotionFX::AnimGraph* mAnimGraph; - Workspace* mWorkspace; + EMotionFX::Actor * m_actor; + EMotionFX::Motion* m_motion; + EMotionFX::MotionSet* m_motionSet; + EMotionFX::AnimGraph* m_animGraph; + Workspace* m_workspace; }; SaveDirtyFilesCallback(); @@ -80,8 +80,8 @@ namespace EMStudio // dirty files callbacks void AddCallback(SaveDirtyFilesCallback* callback); void RemoveCallback(SaveDirtyFilesCallback* callback, bool delFromMem = true); - SaveDirtyFilesCallback* GetCallback(size_t index) const { return mSaveDirtyFilesCallbacks[index]; } - size_t GetNumCallbacks() const { return mSaveDirtyFilesCallbacks.size(); } + SaveDirtyFilesCallback* GetCallback(size_t index) const { return m_saveDirtyFilesCallbacks[index]; } + size_t GetNumCallbacks() const { return m_saveDirtyFilesCallbacks.size(); } int SaveDirtyFiles(uint32 type = MCORE_INVALIDINDEX32, uint32 filter = MCORE_INVALIDINDEX32, QDialogButtonBox::StandardButtons buttons = QDialogButtonBox::Ok | QDialogButtonBox::Discard | QDialogButtonBox::Cancel @@ -94,7 +94,7 @@ namespace EMStudio void SaveSettings(); private: - AZStd::vector mSaveDirtyFilesCallbacks; + AZStd::vector m_saveDirtyFilesCallbacks; int SaveDirtyFiles(const AZStd::vector& neededSaveDirtyFilesCallbacks, QDialogButtonBox::StandardButtons buttons); }; @@ -115,18 +115,18 @@ namespace EMStudio ); virtual ~SaveDirtySettingsWindow(); - bool GetSaveDirtyFiles() { return mSaveDirtyFiles; } + bool GetSaveDirtyFiles() { return m_saveDirtyFiles; } void GetSelectedFileNames(AZStd::vector* outFileNames, AZStd::vector* outObjects); public slots: - void OnSaveButton() { mSaveDirtyFiles = true; emit accept(); } - void OnSkipSavingButton() { mSaveDirtyFiles = false; emit accept(); } - void OnCancelButton() { mSaveDirtyFiles = false; emit reject(); } + void OnSaveButton() { m_saveDirtyFiles = true; emit accept(); } + void OnSkipSavingButton() { m_saveDirtyFiles = false; emit accept(); } + void OnCancelButton() { m_saveDirtyFiles = false; emit reject(); } private: - QTableWidget* mTableWidget; - bool mSaveDirtyFiles; - AZStd::vector mFileNames; - AZStd::vector mObjects; + QTableWidget* m_tableWidget; + bool m_saveDirtyFiles; + AZStd::vector m_fileNames; + AZStd::vector m_objects; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/ToolBarPlugin.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/ToolBarPlugin.cpp index f0820b3b5c..87511e19ce 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/ToolBarPlugin.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/ToolBarPlugin.cpp @@ -17,7 +17,7 @@ namespace EMStudio // constructor ToolBarPlugin::ToolBarPlugin() : EMStudioPlugin() - , mBar() + , m_bar() { } @@ -25,10 +25,10 @@ namespace EMStudio // destructor ToolBarPlugin::~ToolBarPlugin() { - if (!mBar.isNull()) + if (!m_bar.isNull()) { - EMStudio::GetMainWindow()->removeToolBar(mBar); - delete mBar; + EMStudio::GetMainWindow()->removeToolBar(m_bar); + delete m_bar; } } @@ -40,13 +40,13 @@ namespace EMStudio // check if we have a window that uses this object name bool ToolBarPlugin::GetHasWindowWithObjectName(const AZStd::string& objectName) { - if (mBar.isNull()) + if (m_bar.isNull()) { return false; } // check if the object name is equal to the one of the dock widget - return objectName == FromQtString(mBar->objectName()); + return objectName == FromQtString(m_bar->objectName()); } @@ -68,33 +68,33 @@ namespace EMStudio // set the interface title void ToolBarPlugin::SetInterfaceTitle(const char* name) { - if (!mBar.isNull()) + if (!m_bar.isNull()) { - mBar->setWindowTitle(name); + m_bar->setWindowTitle(name); } } QToolBar* ToolBarPlugin::GetToolBar() { - if (!mBar.isNull()) + if (!m_bar.isNull()) { - return mBar; + return m_bar; } MainWindow* mainWindow = GetMainWindow(); // create the toolbar - mBar = new QToolBar(GetName(), mainWindow); - mBar->setAllowedAreas(GetAllowedAreas()); - mBar->setFloatable(GetIsFloatable()); - mBar->setMovable(GetIsMovable()); - mBar->setOrientation(GetIsVertical() ? Qt::Vertical : Qt::Horizontal); - mBar->setToolButtonStyle(GetToolButtonStyle()); + m_bar = new QToolBar(GetName(), mainWindow); + m_bar->setAllowedAreas(GetAllowedAreas()); + m_bar->setFloatable(GetIsFloatable()); + m_bar->setMovable(GetIsMovable()); + m_bar->setOrientation(GetIsVertical() ? Qt::Vertical : Qt::Horizontal); + m_bar->setToolButtonStyle(GetToolButtonStyle()); // add the toolbar to the main window - mainWindow->addToolBar(GetToolBarCreationArea(), mBar); + mainWindow->addToolBar(GetToolBarCreationArea(), m_bar); - return mBar; + return m_bar; } } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/ToolBarPlugin.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/ToolBarPlugin.h index 72054ab926..dcda6d2c1f 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/ToolBarPlugin.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/ToolBarPlugin.h @@ -46,7 +46,7 @@ namespace EMStudio virtual void SetInterfaceTitle(const char* name); void CreateBaseInterface(const char* objectName) override; - QString GetObjectName() const override { AZ_Assert(!mBar.isNull(), "Unexpected null bar"); return mBar->objectName(); } + QString GetObjectName() const override { AZ_Assert(!m_bar.isNull(), "Unexpected null bar"); return m_bar->objectName(); } void SetObjectName(const QString& name) override { GetToolBar()->setObjectName(name); } bool GetHasWindowWithObjectName(const AZStd::string& objectName) override; @@ -56,7 +56,7 @@ namespace EMStudio QToolBar* GetToolBar(); protected: - QPointer mBar; + QPointer m_bar; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/UnitScaleWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/UnitScaleWindow.cpp index a39d24c3d7..f449adf733 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/UnitScaleWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/UnitScaleWindow.cpp @@ -23,7 +23,7 @@ namespace EMStudio UnitScaleWindow::UnitScaleWindow(QWidget* parent) : QDialog(parent) { - mScaleFactor = 1.0f; + m_scaleFactor = 1.0f; setModal(true); setWindowTitle("Scale Factor Setup"); @@ -47,27 +47,27 @@ namespace EMStudio scaleLayout->addWidget(new QLabel("Scale Factor:")); - mScaleSpinBox = new AzQtComponents::DoubleSpinBox(); - mScaleSpinBox->setRange(0.00001, 100000.0f); - mScaleSpinBox->setSingleStep(0.01); - mScaleSpinBox->setDecimals(7); - mScaleSpinBox->setValue(1.0f); - scaleLayout->addWidget(mScaleSpinBox); + m_scaleSpinBox = new AzQtComponents::DoubleSpinBox(); + m_scaleSpinBox->setRange(0.00001, 100000.0f); + m_scaleSpinBox->setSingleStep(0.01); + m_scaleSpinBox->setDecimals(7); + m_scaleSpinBox->setValue(1.0f); + scaleLayout->addWidget(m_scaleSpinBox); layout->addLayout(scaleLayout); QHBoxLayout* hLayout = new QHBoxLayout(); hLayout->setContentsMargins(9, 0, 9, 9); - mOK = new QPushButton("OK"); - mCancel = new QPushButton("Cancel"); - hLayout->addWidget(mOK); - hLayout->addWidget(mCancel); + m_ok = new QPushButton("OK"); + m_cancel = new QPushButton("Cancel"); + hLayout->addWidget(m_ok); + hLayout->addWidget(m_cancel); layout->addLayout(hLayout); - connect(mOK, &QPushButton::clicked, this, &UnitScaleWindow::OnOKButton); - connect(mCancel, &QPushButton::clicked, this, &UnitScaleWindow::OnCancelButton); + connect(m_ok, &QPushButton::clicked, this, &UnitScaleWindow::OnOKButton); + connect(m_cancel, &QPushButton::clicked, this, &UnitScaleWindow::OnCancelButton); } @@ -80,7 +80,7 @@ namespace EMStudio // accept void UnitScaleWindow::OnOKButton() { - mScaleFactor = static_cast(mScaleSpinBox->value()); + m_scaleFactor = static_cast(m_scaleSpinBox->value()); emit accept(); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/UnitScaleWindow.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/UnitScaleWindow.h index c60c66fad1..3de0ed1787 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/UnitScaleWindow.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/UnitScaleWindow.h @@ -30,16 +30,16 @@ namespace EMStudio UnitScaleWindow(QWidget* parent); ~UnitScaleWindow(); - float GetScaleFactor() const { return mScaleFactor; } + float GetScaleFactor() const { return m_scaleFactor; } private slots: void OnOKButton(); void OnCancelButton(); private: - float mScaleFactor; - QPushButton* mOK; - QPushButton* mCancel; - AzQtComponents::DoubleSpinBox* mScaleSpinBox; + float m_scaleFactor; + QPushButton* m_ok; + QPushButton* m_cancel; + AzQtComponents::DoubleSpinBox* m_scaleSpinBox; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/Workspace.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/Workspace.cpp index a791b17e25..4cdf645b16 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/Workspace.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/Workspace.cpp @@ -38,7 +38,7 @@ namespace EMStudio { Workspace::Workspace() { - mDirtyFlag = false; + m_dirtyFlag = false; } @@ -161,11 +161,11 @@ namespace EMStudio } const EMotionFX::Transform& transform = actorInstance->GetLocalSpaceTransform(); - const AZ::Vector3& pos = transform.mPosition; - const AZ::Quaternion& rot = transform.mRotation; + const AZ::Vector3& pos = transform.m_position; + const AZ::Quaternion& rot = transform.m_rotation; #ifndef EMFX_SCALE_DISABLED - const AZ::Vector3& scale = transform.mScale; + const AZ::Vector3& scale = transform.m_scale; #else const AZ::Vector3 scale = AZ::Vector3::CreateOne(); #endif @@ -371,14 +371,14 @@ namespace EMStudio // update the workspace filename if (updateFileName) { - mFilename = filename; + m_filename = filename; } // update the workspace dirty flag if (updateDirtyFlag) { GetCommandManager()->SetWorkspaceDirtyFlag(false); - mDirtyFlag = false; + m_dirtyFlag = false; } // save succeeded @@ -404,7 +404,7 @@ namespace EMStudio QSettings settings(filename, QSettings::IniFormat, (QWidget*)GetManager()->GetMainWindow()); - mFilename = filename; + m_filename = filename; AZStd::string commandsString = FromQtString(settings.value("startScript", "").toString()); @@ -435,23 +435,23 @@ namespace EMStudio } GetCommandManager()->SetWorkspaceDirtyFlag(false); - mDirtyFlag = false; + m_dirtyFlag = false; return true; } void Workspace::Reset() { - mFilename.clear(); + m_filename.clear(); GetCommandManager()->SetWorkspaceDirtyFlag(false); - mDirtyFlag = false; + m_dirtyFlag = false; } bool Workspace::GetDirtyFlag() const { - if (mDirtyFlag) + if (m_dirtyFlag) { return true; } @@ -467,7 +467,7 @@ namespace EMStudio void Workspace::SetDirtyFlag(bool dirty) { - mDirtyFlag = dirty; + m_dirtyFlag = dirty; GetCommandManager()->SetWorkspaceDirtyFlag(dirty); } } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/Workspace.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/Workspace.h index 6ef029f131..ad048c6d6b 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/Workspace.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/Workspace.h @@ -35,9 +35,9 @@ namespace EMStudio void Reset(); - void SetFilename(const char* filename) { mFilename = filename; mDirtyFlag = true; } - const AZStd::string& GetFilenameString() const { return mFilename; } - const char* GetFilename() const { return mFilename.c_str(); } + void SetFilename(const char* filename) { m_filename = filename; m_dirtyFlag = true; } + const AZStd::string& GetFilenameString() const { return m_filename; } + const char* GetFilename() const { return m_filename.c_str(); } /** * Set the dirty flag which indicates whether the user has made changes to the motion. This indicator should be set to true @@ -57,7 +57,7 @@ namespace EMStudio void AddFile(AZStd::string* inOutCommands, const char* command, const AZStd::string& filename, const char* additionalParameters = nullptr) const; bool SaveToFile(const char* filename) const; - AZStd::string mFilename; - bool mDirtyFlag; + AZStd::string m_filename; + bool m_dirtyFlag; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/OpenGLRender/GLWidget.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/OpenGLRender/GLWidget.cpp index 2d3a8b9eda..622dd6b566 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/OpenGLRender/GLWidget.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/OpenGLRender/GLWidget.cpp @@ -26,11 +26,11 @@ namespace EMStudio : QOpenGLWidget(parentWidget) , RenderWidget(parentPlugin, parentWidget) { - mParentRenderPlugin = parentPlugin; + m_parentRenderPlugin = parentPlugin; // construct the font metrics used for overlay text rendering - mFont.setPointSize(10); - mFontMetrics = new QFontMetrics(mFont); + m_font.setPointSize(10); + m_fontMetrics = new QFontMetrics(m_font); // create our default camera SwitchCamera(CAMMODE_ORBIT); @@ -47,27 +47,27 @@ namespace EMStudio GLWidget::~GLWidget() { // destruct the font metrics used for overlay text rendering - delete mFontMetrics; + delete m_fontMetrics; } // initialize the Qt OpenGL widget (overloaded from the widget base class) void GLWidget::initializeGL() { - // initializeOpenGLFunctions() and mParentRenderPlugin->InitializeGraphicsManager must be called first to ensure + // initializeOpenGLFunctions() and m_parentRenderPlugin->InitializeGraphicsManager must be called first to ensure // all OpenGL functions have been resolved before doing anything that could make GL calls (e.g. resizing) initializeOpenGLFunctions(); - mParentRenderPlugin->InitializeGraphicsManager(); - if (mParentRenderPlugin->GetGraphicsManager()) + m_parentRenderPlugin->InitializeGraphicsManager(); + if (m_parentRenderPlugin->GetGraphicsManager()) { - mParentRenderPlugin->GetGraphicsManager()->SetGBuffer(&mGBuffer); + m_parentRenderPlugin->GetGraphicsManager()->SetGBuffer(&m_gBuffer); } // set minimum render view dimensions setMinimumHeight(100); setMinimumWidth(100); - mPerfTimer.StampAndGetDeltaTimeInSeconds(); + m_perfTimer.StampAndGetDeltaTimeInSeconds(); } @@ -80,14 +80,14 @@ namespace EMStudio return; } - mParentRenderPlugin->GetRenderUtil()->Validate(); + m_parentRenderPlugin->GetRenderUtil()->Validate(); - mWidth = width; - mHeight = height; - mGBuffer.Resize(width, height); + m_width = width; + m_height = height; + m_gBuffer.Resize(width, height); - RenderGL::GraphicsManager* graphicsManager = mParentRenderPlugin->GetGraphicsManager(); - if (graphicsManager == nullptr || mCamera == nullptr) + RenderGL::GraphicsManager* graphicsManager = m_parentRenderPlugin->GetGraphicsManager(); + if (graphicsManager == nullptr || m_camera == nullptr) { return; } @@ -115,23 +115,23 @@ namespace EMStudio return; } - mRenderTimer.Stamp(); + m_renderTimer.Stamp(); // render the scene - RenderGL::GraphicsManager* graphicsManager = mParentRenderPlugin->GetGraphicsManager(); - if (graphicsManager == nullptr || mCamera == nullptr) + RenderGL::GraphicsManager* graphicsManager = m_parentRenderPlugin->GetGraphicsManager(); + if (graphicsManager == nullptr || m_camera == nullptr) { return; } painter.beginNativePainting(); - graphicsManager->SetGBuffer(&mGBuffer); + graphicsManager->SetGBuffer(&m_gBuffer); - RenderOptions* renderOptions = mParentRenderPlugin->GetRenderOptions(); + RenderOptions* renderOptions = m_parentRenderPlugin->GetRenderOptions(); // get a pointer to the render utility - RenderGL::GLRenderUtil* renderUtil = mParentRenderPlugin->GetGraphicsManager()->GetRenderUtil(); + RenderGL::GLRenderUtil* renderUtil = m_parentRenderPlugin->GetGraphicsManager()->GetRenderUtil(); if (renderUtil == nullptr) { return; @@ -139,35 +139,23 @@ namespace EMStudio // set this as the active widget // note that this is done in paint() instead of by the plugin because of delay when glwidget::update is called - MCORE_ASSERT(mParentRenderPlugin->GetActiveViewWidget() == nullptr); - mParentRenderPlugin->SetActiveViewWidget(mViewWidget); + MCORE_ASSERT(m_parentRenderPlugin->GetActiveViewWidget() == nullptr); + m_parentRenderPlugin->SetActiveViewWidget(m_viewWidget); // set the background colors graphicsManager->SetClearColor(renderOptions->GetBackgroundColor()); graphicsManager->SetGradientSourceColor(renderOptions->GetGradientSourceColor()); graphicsManager->SetGradientTargetColor(renderOptions->GetGradientTargetColor()); - graphicsManager->SetUseGradientBackground(mViewWidget->GetRenderFlag(RenderViewWidget::RENDER_USE_GRADIENTBACKGROUND)); + graphicsManager->SetUseGradientBackground(m_viewWidget->GetRenderFlag(RenderViewWidget::RENDER_USE_GRADIENTBACKGROUND)); // needed to make multiple viewports working glEnable(GL_DEPTH_TEST); glEnable(GL_MULTISAMPLE); // tell the system about the current viewport - glViewport(0, 0, aznumeric_cast(mWidth * devicePixelRatioF()), aznumeric_cast(mHeight * devicePixelRatioF())); + glViewport(0, 0, aznumeric_cast(m_width * devicePixelRatioF()), aznumeric_cast(m_height * devicePixelRatioF())); renderUtil->SetDevicePixelRatio(aznumeric_cast(devicePixelRatioF())); - // update advanced render settings - /* graphicsManager->SetAdvancedRendering( renderOptions->mEnableAdvancedRendering ); - graphicsManager->SetBloomEnabled ( renderOptions->mBloomEnabled ); - graphicsManager->SetBloomThreshold ( renderOptions->mBloomThreshold ); - graphicsManager->SetBloomIntensity ( renderOptions->mBloomIntensity ); - graphicsManager->SetBloomRadius ( renderOptions->mBloomRadius ); - graphicsManager->SetDOFEnabled ( renderOptions->mDOFEnabled ); - graphicsManager->SetDOFFocalDistance( renderOptions->mDOFFocalPoint ); - graphicsManager->SetDOFNear ( renderOptions->mDOFNear ); - graphicsManager->SetDOFFar ( renderOptions->mDOFFar ); - graphicsManager->SetDOFBlurRadius ( renderOptions->mDOFBlurRadius ); - */ graphicsManager->SetRimAngle (renderOptions->GetRimAngle()); graphicsManager->SetRimIntensity (renderOptions->GetRimIntensity()); graphicsManager->SetRimWidth (renderOptions->GetRimWidth()); @@ -180,7 +168,7 @@ namespace EMStudio // update the camera UpdateCamera(); - graphicsManager->SetCamera(mCamera); + graphicsManager->SetCamera(m_camera); graphicsManager->BeginRender(); @@ -216,16 +204,16 @@ namespace EMStudio glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); - MCommon::Camera* camera = mCamera; - if (mCamera->GetType() == MCommon::OrthographicCamera::TYPE_ID) + MCommon::Camera* camera = m_camera; + if (m_camera->GetType() == MCommon::OrthographicCamera::TYPE_ID) { - camera = mAxisFakeCamera; + camera = m_axisFakeCamera; } graphicsManager->SetCamera(camera); RenderWidget::RenderAxis(); - graphicsManager->SetCamera(mCamera); + graphicsManager->SetCamera(m_camera); glPopAttrib(); @@ -235,7 +223,7 @@ namespace EMStudio // render the border around the render view if (EMotionFX::GetRecorder().GetIsRecording() == false && EMotionFX::GetRecorder().GetIsInPlayMode() == false) { - if (mParentRenderPlugin->GetFocusViewWidget() == mViewWidget) + if (m_parentRenderPlugin->GetFocusViewWidget() == m_viewWidget) { RenderBorder(MCore::RGBAColor(1.0f, 0.647f, 0.0f)); } @@ -261,16 +249,16 @@ namespace EMStudio // makes no GL context the current context, needed in multithreaded environments //doneCurrent(); // Ben: results in a white screen - mParentRenderPlugin->SetActiveViewWidget(nullptr); + m_parentRenderPlugin->SetActiveViewWidget(nullptr); painter.endNativePainting(); if (renderOptions->GetShowFPS()) { - const float renderTime = mRenderTimer.GetDeltaTimeInSeconds() * 1000.0f; + const float renderTime = m_renderTimer.GetDeltaTimeInSeconds() * 1000.0f; // get the time delta between the current time and the last frame - const float perfTimeDelta = mPerfTimer.StampAndGetDeltaTimeInSeconds(); + const float perfTimeDelta = m_perfTimer.StampAndGetDeltaTimeInSeconds(); static float fpsTimeElapsed = 0.0f; static uint32 fpsNumFrames = 0; @@ -288,11 +276,7 @@ namespace EMStudio perfTempString = AZStd::string::format("%d FPS (%.1f ms)", lastFPS, renderTime); // initialize the painter and get the font metrics - //painter.setBrush( Qt::NoBrush ); - //painter.setPen( QColor(130, 130, 130) ); - //painter.setFont( mFont ); - EMStudioManager::RenderText(painter, perfTempString.c_str(), QColor(150, 150, 150), mFont, *mFontMetrics, Qt::AlignRight, QRect(width() - 55, height() - 20, 50, 20)); - //painter.drawText( QPoint(width() - 133, height() - 14), perfTempString.AsChar() ); + EMStudioManager::RenderText(painter, perfTempString.c_str(), QColor(150, 150, 150), m_font, *m_fontMetrics, Qt::AlignRight, QRect(width() - 55, height() - 20, 50, 20)); } } @@ -301,7 +285,7 @@ namespace EMStudio { glMatrixMode(GL_PROJECTION); glLoadIdentity(); - glOrtho(0.0f, mWidth, mHeight, 0.0f, 0.0f, 1.0f); + glOrtho(0.0f, m_width, m_height, 0.0f, 0.0f, 1.0f); glMatrixMode (GL_MODELVIEW); glLoadIdentity(); //glTranslatef(0.375f, 0.375f, 0.0f); @@ -312,20 +296,20 @@ namespace EMStudio glLineWidth(3.0f); - glColor3f(color.r, color.g, color.b); + glColor3f(color.m_r, color.m_g, color.m_b); glBegin(GL_LINES); // left glVertex2f(0.0f, 0.0f); - glVertex2f(0.0f, aznumeric_cast(mHeight)); + glVertex2f(0.0f, aznumeric_cast(m_height)); // bottom - glVertex2f(0.0f, aznumeric_cast(mHeight)); - glVertex2f(aznumeric_cast(mWidth), aznumeric_cast(mHeight)); + glVertex2f(0.0f, aznumeric_cast(m_height)); + glVertex2f(aznumeric_cast(m_width), aznumeric_cast(m_height)); // top glVertex2f(0.0f, 0.0f); - glVertex2f(aznumeric_cast(mWidth), 0); + glVertex2f(aznumeric_cast(m_width), 0); // right - glVertex2f(aznumeric_cast(mWidth), 0.0f); - glVertex2f(aznumeric_cast(mWidth), aznumeric_cast(mHeight)); + glVertex2f(aznumeric_cast(m_width), 0.0f); + glVertex2f(aznumeric_cast(m_width), aznumeric_cast(m_height)); glEnd(); glLineWidth(1.0f); @@ -335,7 +319,7 @@ namespace EMStudio void GLWidget::focusInEvent(QFocusEvent* event) { MCORE_UNUSED(event); - mParentRenderPlugin->SetFocusViewWidget(mViewWidget); + m_parentRenderPlugin->SetFocusViewWidget(m_viewWidget); grabKeyboard(); } @@ -343,7 +327,7 @@ namespace EMStudio void GLWidget::focusOutEvent(QFocusEvent* event) { MCORE_UNUSED(event); - mParentRenderPlugin->SetFocusViewWidget(nullptr); + m_parentRenderPlugin->SetFocusViewWidget(nullptr); releaseKeyboard(); } } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/OpenGLRender/GLWidget.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/OpenGLRender/GLWidget.h index 2306da0a5f..685ff4ef88 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/OpenGLRender/GLWidget.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/OpenGLRender/GLWidget.h @@ -76,12 +76,12 @@ namespace EMStudio void Update() { update(); } void RenderBorder(const MCore::RGBAColor& color); - RenderGL::GBuffer mGBuffer; - OpenGLRenderPlugin* mParentRenderPlugin; - QFont mFont; - QFontMetrics* mFontMetrics; - AZ::Debug::Timer mRenderTimer; - AZ::Debug::Timer mPerfTimer; + RenderGL::GBuffer m_gBuffer; + OpenGLRenderPlugin* m_parentRenderPlugin; + QFont m_font; + QFontMetrics* m_fontMetrics; + AZ::Debug::Timer m_renderTimer; + AZ::Debug::Timer m_perfTimer; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/OpenGLRender/OpenGLRenderPlugin.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/OpenGLRender/OpenGLRenderPlugin.cpp index 396a7fc906..5626e482eb 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/OpenGLRender/OpenGLRenderPlugin.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/OpenGLRender/OpenGLRenderPlugin.cpp @@ -25,13 +25,13 @@ namespace EMStudio OpenGLRenderPlugin::OpenGLRenderPlugin() : EMStudio::RenderPlugin() { - mGraphicsManager = nullptr; + m_graphicsManager = nullptr; } OpenGLRenderPlugin::~OpenGLRenderPlugin() { // get rid of the OpenGL graphics manager - delete mGraphicsManager; + delete m_graphicsManager; } // init after the parent dock window has been created @@ -48,7 +48,7 @@ namespace EMStudio // initialize the OpenGL engine bool OpenGLRenderPlugin::InitializeGraphicsManager() { - if (mGraphicsManager) + if (m_graphicsManager) { // initialize all already existing actors and actor instances ReInit(); @@ -59,15 +59,15 @@ namespace EMStudio const auto shaderPath = AZ::IO::Path(MysticQt::GetDataDir()) / "Shaders"; // create graphics manager and initialize it - mGraphicsManager = new RenderGL::GraphicsManager(); - if (mGraphicsManager->Init(shaderPath) == false) + m_graphicsManager = new RenderGL::GraphicsManager(); + if (m_graphicsManager->Init(shaderPath) == false) { MCore::LogError("Could not initialize OpenGL graphics manager."); return false; } // set the render util in the base render plugin - mRenderUtil = mGraphicsManager->GetRenderUtil(); + m_renderUtil = m_graphicsManager->GetRenderUtil(); // initialize all already existing actors and actor instances ReInit(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/OpenGLRender/OpenGLRenderPlugin.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/OpenGLRender/OpenGLRenderPlugin.h index b75a4df24b..1203d7e381 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/OpenGLRender/OpenGLRenderPlugin.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/OpenGLRender/OpenGLRenderPlugin.h @@ -51,10 +51,10 @@ namespace EMStudio // OpenGL engine helper functions bool InitializeGraphicsManager(); - MCORE_INLINE RenderGL::GraphicsManager* GetGraphicsManager() { return mGraphicsManager; } + MCORE_INLINE RenderGL::GraphicsManager* GetGraphicsManager() { return m_graphicsManager; } private: - RenderGL::GraphicsManager* mGraphicsManager; // shared OpenGL engine object + RenderGL::GraphicsManager* m_graphicsManager; // shared OpenGL engine object // overloaded emstudio actor create function which creates an OpenGL render actor internally bool CreateEMStudioActor(EMotionFX::Actor* actor); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/ActionHistory/ActionHistoryCallback.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/ActionHistory/ActionHistoryCallback.cpp index ac23dd489b..2715a0a0fe 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/ActionHistory/ActionHistoryCallback.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/ActionHistory/ActionHistoryCallback.cpp @@ -21,13 +21,13 @@ namespace EMStudio ActionHistoryCallback::ActionHistoryCallback(QListWidget* list) : MCore::CommandManagerCallback() { - mList = list; - mIndex = 0; - mIsRemoving = false; - mGroupExecuting = false; - mExecutedGroup = nullptr; - mNumGroupCommands = 0; - mCurrentCommandIndex = 0; + m_list = list; + m_index = 0; + m_isRemoving = false; + m_groupExecuting = false; + m_executedGroup = nullptr; + m_numGroupCommands = 0; + m_currentCommandIndex = 0; m_darkenedBrush.setColor(QColor(110, 110, 110)); m_brush.setColor(QColor(200, 200, 200)); } @@ -41,16 +41,16 @@ namespace EMStudio { if (MCore::GetLogManager().GetLogLevels() & MCore::LogCallback::LOGLEVEL_DEBUG) { - mTempString = command->GetName(); + m_tempString = command->GetName(); const size_t numParameters = commandLine.GetNumParameters(); for (size_t i = 0; i < numParameters; ++i) { - mTempString += " -"; - mTempString += commandLine.GetParameterName(i); - mTempString += " "; - mTempString += commandLine.GetParameterValue(i); + m_tempString += " -"; + m_tempString += commandLine.GetParameterName(i); + m_tempString += " "; + m_tempString += commandLine.GetParameterValue(i); } - MCore::LogDebugMsg(mTempString.c_str()); + MCore::LogDebugMsg(m_tempString.c_str()); } } } @@ -61,66 +61,66 @@ namespace EMStudio MCORE_UNUSED(group); MCORE_UNUSED(commandLine); MCORE_UNUSED(outResult); - if (mGroupExecuting && mExecutedGroup) + if (m_groupExecuting && m_executedGroup) { - mCurrentCommandIndex++; - if (mCurrentCommandIndex % 32 == 0) + m_currentCommandIndex++; + if (m_currentCommandIndex % 32 == 0) { - EMotionFX::GetEventManager().OnProgressValue(((float)mCurrentCommandIndex / (mNumGroupCommands + 1)) * 100.0f); + EMotionFX::GetEventManager().OnProgressValue(((float)m_currentCommandIndex / (m_numGroupCommands + 1)) * 100.0f); } } if (command && MCore::GetLogManager().GetLogLevels() & MCore::LogCallback::LOGLEVEL_DEBUG) { - mTempString = AZStd::string::format("%sExecution of command '%s' %s", wasSuccess ? " " : "*** ", command->GetName(), wasSuccess ? "completed successfully" : " FAILED"); - MCore::LogDebugMsg(mTempString.c_str()); + m_tempString = AZStd::string::format("%sExecution of command '%s' %s", wasSuccess ? " " : "*** ", command->GetName(), wasSuccess ? "completed successfully" : " FAILED"); + MCore::LogDebugMsg(m_tempString.c_str()); } } // Before executing a command group. void ActionHistoryCallback::OnPreExecuteCommandGroup(MCore::CommandGroup* group, bool undo) { - if (!mGroupExecuting && group->GetNumCommands() > 64) + if (!m_groupExecuting && group->GetNumCommands() > 64) { - mGroupExecuting = true; - mExecutedGroup = group; - mCurrentCommandIndex = 0; - mNumGroupCommands = group->GetNumCommands(); + m_groupExecuting = true; + m_executedGroup = group; + m_currentCommandIndex = 0; + m_numGroupCommands = group->GetNumCommands(); GetManager()->SetAvoidRendering(true); EMotionFX::GetEventManager().OnProgressStart(); - mTempString = AZStd::string::format("%s%s", undo ? "Undo: " : "", group->GetGroupName()); - EMotionFX::GetEventManager().OnProgressText(mTempString.c_str()); + m_tempString = AZStd::string::format("%s%s", undo ? "Undo: " : "", group->GetGroupName()); + EMotionFX::GetEventManager().OnProgressText(m_tempString.c_str()); } if (group && MCore::GetLogManager().GetLogLevels() & MCore::LogCallback::LOGLEVEL_DEBUG) { - mTempString = AZStd::string::format("Starting %s of command group '%s'", undo ? "undo" : "execution", group->GetGroupName()); - MCore::LogDebugMsg(mTempString.c_str()); + m_tempString = AZStd::string::format("Starting %s of command group '%s'", undo ? "undo" : "execution", group->GetGroupName()); + MCore::LogDebugMsg(m_tempString.c_str()); } } // After executing a command group. void ActionHistoryCallback::OnPostExecuteCommandGroup(MCore::CommandGroup* group, bool wasSuccess) { - if (mExecutedGroup == group) + if (m_executedGroup == group) { EMotionFX::GetEventManager().OnProgressEnd(); - mGroupExecuting = false; - mExecutedGroup = nullptr; - mNumGroupCommands = 0; - mCurrentCommandIndex = 0; + m_groupExecuting = false; + m_executedGroup = nullptr; + m_numGroupCommands = 0; + m_currentCommandIndex = 0; GetManager()->SetAvoidRendering(false); } if (group && MCore::GetLogManager().GetLogLevels() & MCore::LogCallback::LOGLEVEL_DEBUG) { - mTempString = AZStd::string::format("%sExecution of command group '%s' %s", wasSuccess ? " " : "*** ", group->GetGroupName(), wasSuccess ? "completed successfully" : " FAILED"); - MCore::LogDebugMsg(mTempString.c_str()); + m_tempString = AZStd::string::format("%sExecution of command group '%s' %s", wasSuccess ? " " : "*** ", group->GetGroupName(), wasSuccess ? "completed successfully" : " FAILED"); + MCore::LogDebugMsg(m_tempString.c_str()); } } @@ -128,44 +128,44 @@ namespace EMStudio void ActionHistoryCallback::OnAddCommandToHistory(size_t historyIndex, MCore::CommandGroup* group, MCore::Command* command, const MCore::CommandLine& commandLine) { MCORE_UNUSED(commandLine); - mTempString = MCore::CommandManager::CommandHistoryEntry::ToString(group, command, mIndex++).c_str(); + m_tempString = MCore::CommandManager::CommandHistoryEntry::ToString(group, command, m_index++).c_str(); - mList->insertItem(aznumeric_caster(historyIndex), new QListWidgetItem(mTempString.c_str(), mList)); - mList->setCurrentRow(aznumeric_caster(historyIndex)); + m_list->insertItem(aznumeric_caster(historyIndex), new QListWidgetItem(m_tempString.c_str(), m_list)); + m_list->setCurrentRow(aznumeric_caster(historyIndex)); } // Remove an item from the history. void ActionHistoryCallback::OnRemoveCommand(size_t historyIndex) { // Remove the item. - mIsRemoving = true; - delete mList->takeItem(aznumeric_caster(historyIndex)); - mIsRemoving = false; + m_isRemoving = true; + delete m_list->takeItem(aznumeric_caster(historyIndex)); + m_isRemoving = false; } // Set the current command. void ActionHistoryCallback::OnSetCurrentCommand(size_t index) { - if (mIsRemoving) + if (m_isRemoving) { return; } if (index == InvalidIndex) { - mList->setCurrentRow(-1); + m_list->setCurrentRow(-1); // Darken all history items. - const int numCommands = mList->count(); + const int numCommands = m_list->count(); for (int i = 0; i < numCommands; ++i) { - mList->item(i)->setForeground(m_darkenedBrush); + m_list->item(i)->setForeground(m_darkenedBrush); } return; } // get the list of selected items - mList->setCurrentRow(aznumeric_caster(index)); + m_list->setCurrentRow(aznumeric_caster(index)); // Get the current history index. const size_t historyIndex = GetCommandManager()->GetHistoryIndex(); @@ -225,13 +225,13 @@ namespace EMStudio const int numCommands = static_cast(GetCommandManager()->GetNumHistoryItems()); for (int i = aznumeric_caster(index); i < numCommands; ++i) { - mList->item(i)->setForeground(m_darkenedBrush); + m_list->item(i)->setForeground(m_darkenedBrush); } // Color enabled ones. for (int i = 0; i <= static_cast(index); ++i) { - mList->item(i)->setForeground(m_brush); + m_list->item(i)->setForeground(m_brush); } } } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/ActionHistory/ActionHistoryCallback.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/ActionHistory/ActionHistoryCallback.h index 0433b22d5d..621ed8ecff 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/ActionHistory/ActionHistoryCallback.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/ActionHistory/ActionHistoryCallback.h @@ -44,15 +44,15 @@ namespace EMStudio void OnSetCurrentCommand(size_t index) override; private: - QListWidget* mList; - AZStd::string mTempString; - uint32 mIndex; - bool mIsRemoving; + QListWidget* m_list; + AZStd::string m_tempString; + uint32 m_index; + bool m_isRemoving; - bool mGroupExecuting; - MCore::CommandGroup* mExecutedGroup; - size_t mNumGroupCommands; - uint32 mCurrentCommandIndex; + bool m_groupExecuting; + MCore::CommandGroup* m_executedGroup; + size_t m_numGroupCommands; + uint32 m_currentCommandIndex; QBrush m_brush; QBrush m_darkenedBrush; }; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/ActionHistory/ActionHistoryPlugin.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/ActionHistory/ActionHistoryPlugin.cpp index 6a80fec548..d84bbebbc6 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/ActionHistory/ActionHistoryPlugin.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/ActionHistory/ActionHistoryPlugin.cpp @@ -18,20 +18,20 @@ namespace EMStudio ActionHistoryPlugin::ActionHistoryPlugin() : EMStudio::DockWidgetPlugin() { - mCallback = nullptr; - mList = nullptr; + m_callback = nullptr; + m_list = nullptr; } ActionHistoryPlugin::~ActionHistoryPlugin() { - if (mCallback) + if (m_callback) { - EMStudio::GetCommandManager()->RemoveCallback(mCallback, false); - delete mCallback; + EMStudio::GetCommandManager()->RemoveCallback(m_callback, false); + delete m_callback; } - delete mList; + delete m_list; } @@ -75,22 +75,22 @@ namespace EMStudio // Init after the parent dock window has been created. bool ActionHistoryPlugin::Init() { - mList = new QListWidget(mDock); + m_list = new QListWidget(m_dock); - mList->setFlow(QListView::TopToBottom); - mList->setMovement(QListView::Static); - mList->setViewMode(QListView::ListMode); - mList->setSelectionRectVisible(true); - mList->setSelectionBehavior(QAbstractItemView::SelectRows); - mList->setSelectionMode(QAbstractItemView::SingleSelection); - mDock->setWidget(mList); + m_list->setFlow(QListView::TopToBottom); + m_list->setMovement(QListView::Static); + m_list->setViewMode(QListView::ListMode); + m_list->setSelectionRectVisible(true); + m_list->setSelectionBehavior(QAbstractItemView::SelectRows); + m_list->setSelectionMode(QAbstractItemView::SingleSelection); + m_dock->setWidget(m_list); // Detect item selection changes. - connect(mList, &QListWidget::itemSelectionChanged, this, &ActionHistoryPlugin::OnSelectedItemChanged); + connect(m_list, &QListWidget::itemSelectionChanged, this, &ActionHistoryPlugin::OnSelectedItemChanged); // Register the callback. - mCallback = new ActionHistoryCallback(mList); - EMStudio::GetCommandManager()->RegisterCallback(mCallback); + m_callback = new ActionHistoryCallback(m_list); + EMStudio::GetCommandManager()->RegisterCallback(m_callback); // Sync the interface with the actual command history. ReInit(); @@ -109,12 +109,12 @@ namespace EMStudio { const MCore::CommandManager::CommandHistoryEntry& historyItem = commandManager->GetHistoryItem(i); - historyItemString = MCore::CommandManager::CommandHistoryEntry::ToString(historyItem.mCommandGroup, historyItem.mExecutedCommand, historyItem.m_historyItemNr); - mList->addItem(new QListWidgetItem(historyItemString.c_str(), mList)); + historyItemString = MCore::CommandManager::CommandHistoryEntry::ToString(historyItem.m_commandGroup, historyItem.m_executedCommand, historyItem.m_historyItemNr); + m_list->addItem(new QListWidgetItem(historyItemString.c_str(), m_list)); } // Set the current history index in case the user called undo. - mList->setCurrentRow(commandManager->GetHistoryIndex()); + m_list->setCurrentRow(commandManager->GetHistoryIndex()); } @@ -122,17 +122,17 @@ namespace EMStudio void ActionHistoryPlugin::OnSelectedItemChanged() { // Get the list of selected items and make sure exactly one is selected. - QList selected = mList->selectedItems(); + QList selected = m_list->selectedItems(); if (selected.count() != 1) { return; } // Get the selected item and its index (row number in the list). - const uint32 index = mList->row(selected.at(0)); + const uint32 index = m_list->row(selected.at(0)); // Change the command index. - mCallback->OnSetCurrentCommand(index); + m_callback->OnSetCurrentCommand(index); } } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/ActionHistory/ActionHistoryPlugin.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/ActionHistory/ActionHistoryPlugin.h index a9bff7780b..550e6628e3 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/ActionHistory/ActionHistoryPlugin.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/ActionHistory/ActionHistoryPlugin.h @@ -51,7 +51,7 @@ namespace EMStudio void OnSelectedItemChanged(); private: - QListWidget* mList; - ActionHistoryCallback* mCallback; + QListWidget* m_list; + ActionHistoryCallback* m_callback; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphActionManager.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphActionManager.cpp index 9a4170d1b0..5e33659056 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphActionManager.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphActionManager.cpp @@ -206,8 +206,8 @@ namespace EMStudio // If found motion entry, add select and play motion command strings to command group. EMotionFX::Motion* motion = motionEntry->GetMotion(); EMotionFX::PlayBackInfo* defaultPlayBackInfo = motion->GetDefaultPlayBackInfo(); - defaultPlayBackInfo->mBlendInTime = 0.0f; - defaultPlayBackInfo->mBlendOutTime = 0.0f; + defaultPlayBackInfo->m_blendInTime = 0.0f; + defaultPlayBackInfo->m_blendOutTime = 0.0f; commandParameters = CommandSystem::CommandPlayMotion::PlayBackInfoToCommandParameters(defaultPlayBackInfo); const size_t motionIndex = EMotionFX::GetMotionManager().FindMotionIndexByName(motion->GetName()); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphEditor.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphEditor.cpp index f6e308f07b..96bc39e29c 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphEditor.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphEditor.cpp @@ -26,8 +26,8 @@ namespace EMotionFX { - const int AnimGraphEditor::m_propertyLabelWidth = 120; - QString AnimGraphEditor::m_lastMotionSetText = ""; + const int AnimGraphEditor::s_propertyLabelWidth = 120; + QString AnimGraphEditor::s_lastMotionSetText = ""; AnimGraphEditor::AnimGraphEditor(EMotionFX::AnimGraph* animGraph, AZ::SerializeContext* serializeContext, QWidget* parent) : QWidget(parent) @@ -64,7 +64,7 @@ namespace EMotionFX m_propertyEditor = aznew AzToolsFramework::ReflectedPropertyEditor(this); m_propertyEditor->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum); m_propertyEditor->setObjectName("PropertyEditor"); - m_propertyEditor->Setup(serializeContext, nullptr, false/*enableScrollbars*/, m_propertyLabelWidth); + m_propertyEditor->Setup(serializeContext, nullptr, false/*enableScrollbars*/, s_propertyLabelWidth); m_propertyEditor->SetSizeHintOffset(QSize(0, 0)); m_propertyEditor->SetAutoResizeLabels(false); m_propertyEditor->SetLeafIndentation(0); @@ -86,9 +86,9 @@ namespace EMotionFX m_motionSetComboBox = new QComboBox(); m_motionSetComboBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); //initializes to last selection if it is there - if (!m_lastMotionSetText.isEmpty()) + if (!s_lastMotionSetText.isEmpty()) { - m_motionSetComboBox->addItem(m_lastMotionSetText); + m_motionSetComboBox->addItem(s_lastMotionSetText); m_motionSetComboBox->setCurrentIndex(0); } connect(m_motionSetComboBox, static_cast(&QComboBox::currentIndexChanged), this, &AnimGraphEditor::OnMotionSetChanged); @@ -303,7 +303,7 @@ namespace EMotionFX const CommandSystem::SelectionList& selectionList = CommandSystem::GetCommandManager()->GetCurrentSelection(); const size_t numActorInstances = selectionList.GetNumSelectedActorInstances(); - AnimGraphEditor::m_lastMotionSetText = m_motionSetComboBox->itemText(index); + AnimGraphEditor::s_lastMotionSetText = m_motionSetComboBox->itemText(index); // if no one actor instance is selected, the combo box has no effect if (numActorInstances == 0) { diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphEditor.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphEditor.h index 1d17c46815..836bc8f8ad 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphEditor.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphEditor.h @@ -58,9 +58,9 @@ namespace EMotionFX AnimGraph* m_animGraph; QLabel* m_filenameLabel; AzToolsFramework::ReflectedPropertyEditor* m_propertyEditor; - static const int m_propertyLabelWidth; + static const int s_propertyLabelWidth; QComboBox* m_motionSetComboBox; - static QString m_lastMotionSetText; + static QString s_lastMotionSetText; AZStd::vector m_commandCallbacks; }; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphHierarchyWidget.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphHierarchyWidget.h index c10320a794..586f419292 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphHierarchyWidget.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphHierarchyWidget.h @@ -34,12 +34,12 @@ namespace CommandSystem struct AnimGraphSelectionItem { AnimGraphSelectionItem(uint32 animGraphID, const AZStd::string& nodeName) - : mAnimGraphID(animGraphID) - , mNodeName(nodeName) + : m_animGraphId(animGraphID) + , m_nodeName(nodeName) {} - uint32 mAnimGraphID; - AZStd::string mNodeName; + uint32 m_animGraphId; + AZStd::string m_nodeName; }; namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphModelCallbacks.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphModelCallbacks.cpp index 5de2b58905..c7dc9304d9 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphModelCallbacks.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphModelCallbacks.cpp @@ -29,7 +29,7 @@ namespace EMStudio { CommandSystem::CommandLoadAnimGraph* commandLoadAnimGraph = static_cast(command); - EMotionFX::AnimGraph* animGraph = EMotionFX::GetAnimGraphManager().FindAnimGraphByID(commandLoadAnimGraph->mOldAnimGraphID); + EMotionFX::AnimGraph* animGraph = EMotionFX::GetAnimGraphManager().FindAnimGraphByID(commandLoadAnimGraph->m_oldAnimGraphId); if (animGraph) { m_animGraphModel.Add(animGraph); @@ -55,7 +55,7 @@ namespace EMStudio { CommandSystem::CommandCreateAnimGraph* commandCreateAnimGraph = static_cast(command); - EMotionFX::AnimGraph* animGraph = EMotionFX::GetAnimGraphManager().FindAnimGraphByID(commandCreateAnimGraph->mPreviouslyUsedID); + EMotionFX::AnimGraph* animGraph = EMotionFX::GetAnimGraphManager().FindAnimGraphByID(commandCreateAnimGraph->m_previouslyUsedId); m_animGraphModel.Add(animGraph); EMotionFX::AnimGraphStateMachine* rootStateMachine = animGraph->GetRootStateMachine(); @@ -164,7 +164,7 @@ namespace EMStudio bool AnimGraphModel::CommandDidActivateAnimGraphPostUndoCallback::Undo(MCore::Command* command, [[maybe_unused]] const MCore::CommandLine& commandLine) { CommandSystem::CommandActivateAnimGraph* commandActivateAnimGraph = static_cast(command); - EMotionFX::ActorInstance* actorInstance = EMotionFX::GetActorManager().FindActorInstanceByID(commandActivateAnimGraph->mActorInstanceID); + EMotionFX::ActorInstance* actorInstance = EMotionFX::GetActorManager().FindActorInstanceByID(commandActivateAnimGraph->m_actorInstanceId); if (actorInstance) { @@ -181,14 +181,14 @@ namespace EMStudio bool AnimGraphModel::CommandDidActivateAnimGraphCallback::Execute(MCore::Command* command, [[maybe_unused]] const MCore::CommandLine& commandLine) { CommandSystem::CommandActivateAnimGraph* commandActivateAnimGraph = static_cast(command); - EMotionFX::ActorInstance* actorInstance = EMotionFX::GetActorManager().FindActorInstanceByID(commandActivateAnimGraph->mActorInstanceID); + EMotionFX::ActorInstance* actorInstance = EMotionFX::GetActorManager().FindActorInstanceByID(commandActivateAnimGraph->m_actorInstanceId); if (actorInstance) { EMotionFX::AnimGraphInstance* currentAnimGraphInstance = actorInstance->GetAnimGraphInstance(); EMotionFX::AnimGraph* currentAnimGraph = currentAnimGraphInstance->GetAnimGraph(); EMotionFX::AnimGraph* oldAnimGraph = nullptr; - oldAnimGraph = EMotionFX::GetAnimGraphManager().FindAnimGraphByID(commandActivateAnimGraph->mOldAnimGraphUsed); + oldAnimGraph = EMotionFX::GetAnimGraphManager().FindAnimGraphByID(commandActivateAnimGraph->m_oldAnimGraphUsed); if (currentAnimGraphInstance) { @@ -209,7 +209,7 @@ namespace EMStudio bool AnimGraphModel::CommandDidActivateAnimGraphCallback::Undo(MCore::Command* command, const MCore::CommandLine& commandLine) { CommandSystem::CommandActivateAnimGraph* commandActivateAnimGraph = static_cast(command); - EMotionFX::ActorInstance* actorInstance = EMotionFX::GetActorManager().FindActorInstanceByID(commandActivateAnimGraph->mActorInstanceID); + EMotionFX::ActorInstance* actorInstance = EMotionFX::GetActorManager().FindActorInstanceByID(commandActivateAnimGraph->m_actorInstanceId); // TODO: do this better, we need to find the animgraphinstance that we are undoing after the undo finishes if (actorInstance) @@ -254,7 +254,7 @@ namespace EMStudio } CommandSystem::CommandAnimGraphCreateNode* commandCreateNode = static_cast(command); - EMotionFX::AnimGraphNode* node = animGraph->RecursiveFindNodeById(commandCreateNode->mNodeId); + EMotionFX::AnimGraphNode* node = animGraph->RecursiveFindNodeById(commandCreateNode->m_nodeId); return m_animGraphModel.NodeAdded(node); } @@ -656,10 +656,10 @@ namespace EMStudio { CommandSystem::CommandAnimGraphSetEntryState* commandSetEntryState = static_cast(command); - EMotionFX::AnimGraph* animGraph = EMotionFX::GetAnimGraphManager().FindAnimGraphByID(commandSetEntryState->mAnimGraphID); + EMotionFX::AnimGraph* animGraph = EMotionFX::GetAnimGraphManager().FindAnimGraphByID(commandSetEntryState->m_animGraphId); if (animGraph) { - EMotionFX::AnimGraphNode* entryNode = animGraph->RecursiveFindNodeById(commandSetEntryState->mOldEntryStateNodeId); + EMotionFX::AnimGraphNode* entryNode = animGraph->RecursiveFindNodeById(commandSetEntryState->m_oldEntryStateNodeId); if (entryNode) { static const QVector entryStateRole = { AnimGraphModel::ROLE_NODE_ENTRY_STATE }; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphPlugin.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphPlugin.cpp index 1a713f52fe..4baec366f0 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphPlugin.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphPlugin.cpp @@ -130,7 +130,7 @@ namespace EMStudio // add the link to the actual object ObjectPointer objPointer; - objPointer.mAnimGraph = animGraph; + objPointer.m_animGraph = animGraph; outObjects->push_back(objPointer); } } @@ -150,12 +150,12 @@ namespace EMStudio for (const SaveDirtyFilesCallback::ObjectPointer& objPointer : objects) { // get the current object pointer and skip directly if the type check fails - if (objPointer.mAnimGraph == nullptr) + if (objPointer.m_animGraph == nullptr) { continue; } - EMotionFX::AnimGraph* animGraph = objPointer.mAnimGraph; + EMotionFX::AnimGraph* animGraph = objPointer.m_animGraph; if (animGraphPlugin->SaveDirtyAnimGraph(animGraph, commandGroup, false) == DirtyFileManager::CANCELED) { return DirtyFileManager::CANCELED; @@ -177,33 +177,32 @@ namespace EMStudio // constructor AnimGraphPlugin::AnimGraphPlugin() : EMStudio::DockWidgetPlugin() - , mEventHandler(this) + , m_eventHandler(this) { - mGraphWidget = nullptr; - mNavigateWidget = nullptr; - mAttributeDock = nullptr; - mNodeGroupDock = nullptr; - mPaletteWidget = nullptr; - mNodePaletteDock = nullptr; - mParameterDock = nullptr; - mParameterWindow = nullptr; - mNodeGroupWindow = nullptr; - mAttributesWindow = nullptr; - mActiveAnimGraph = nullptr; + m_graphWidget = nullptr; + m_navigateWidget = nullptr; + m_attributeDock = nullptr; + m_nodeGroupDock = nullptr; + m_paletteWidget = nullptr; + m_nodePaletteDock = nullptr; + m_parameterDock = nullptr; + m_parameterWindow = nullptr; + m_nodeGroupWindow = nullptr; + m_attributesWindow = nullptr; + m_activeAnimGraph = nullptr; m_animGraphObjectFactory = nullptr; - mGraphNodeFactory = nullptr; - mViewWidget = nullptr; - mDirtyFilesCallback = nullptr; + m_graphNodeFactory = nullptr; + m_viewWidget = nullptr; + m_dirtyFilesCallback = nullptr; m_navigationHistory = nullptr; - mDisplayFlags = 0; - // mShowProcessed = false; - mDisableRendering = false; - mLastPlayTime = -1; - mTotalTime = FLT_MAX; + m_displayFlags = 0; + m_disableRendering = false; + m_lastPlayTime = -1; + m_totalTime = FLT_MAX; #if AZ_TRAIT_EMOTIONFX_HAS_GAME_CONTROLLER - mGameControllerWindow = nullptr; - mGameControllerDock = nullptr; + m_gameControllerWindow = nullptr; + m_gameControllerDock = nullptr; #endif m_animGraphModel = nullptr; m_actionManager = nullptr; @@ -214,7 +213,7 @@ namespace EMStudio AnimGraphPlugin::~AnimGraphPlugin() { // destroy the event handler - EMotionFX::GetEventManager().RemoveEventHandler(&mEventHandler); + EMotionFX::GetEventManager().RemoveEventHandler(&m_eventHandler); // unregister the command callbacks and get rid of the memory for (MCore::Command::Callback* callback : m_commandCallbacks) @@ -223,48 +222,48 @@ namespace EMStudio } // remove the dirty file manager callback - GetMainWindow()->GetDirtyFileManager()->RemoveCallback(mDirtyFilesCallback, false); - delete mDirtyFilesCallback; + GetMainWindow()->GetDirtyFileManager()->RemoveCallback(m_dirtyFilesCallback, false); + delete m_dirtyFilesCallback; delete m_animGraphObjectFactory; // delete the graph node factory - delete mGraphNodeFactory; + delete m_graphNodeFactory; // remove the attribute dock widget - if (mParameterDock) + if (m_parameterDock) { - EMStudio::GetMainWindow()->removeDockWidget(mParameterDock); - delete mParameterDock; + EMStudio::GetMainWindow()->removeDockWidget(m_parameterDock); + delete m_parameterDock; } // remove the attribute dock widget - if (mAttributeDock) + if (m_attributeDock) { - EMStudio::GetMainWindow()->removeDockWidget(mAttributeDock); - delete mAttributeDock; + EMStudio::GetMainWindow()->removeDockWidget(m_attributeDock); + delete m_attributeDock; } // remove the node group dock widget - if (mNodeGroupDock) + if (m_nodeGroupDock) { - EMStudio::GetMainWindow()->removeDockWidget(mNodeGroupDock); - delete mNodeGroupDock; + EMStudio::GetMainWindow()->removeDockWidget(m_nodeGroupDock); + delete m_nodeGroupDock; } // remove the blend node palette - if (mNodePaletteDock) + if (m_nodePaletteDock) { - EMStudio::GetMainWindow()->removeDockWidget(mNodePaletteDock); - delete mNodePaletteDock; + EMStudio::GetMainWindow()->removeDockWidget(m_nodePaletteDock); + delete m_nodePaletteDock; } // remove the game controller dock #if AZ_TRAIT_EMOTIONFX_HAS_GAME_CONTROLLER - if (mGameControllerDock) + if (m_gameControllerDock) { - EMStudio::GetMainWindow()->removeDockWidget(mGameControllerDock); - delete mGameControllerDock; + EMStudio::GetMainWindow()->removeDockWidget(m_gameControllerDock); + delete m_gameControllerDock; } #endif if (m_navigationHistory) @@ -322,32 +321,32 @@ namespace EMStudio // During startup, plugins can be constructed more than once, so don't add connections for those items if (GetAttributeDock() != nullptr) { - mDockWindowActions[WINDOWS_PARAMETERWINDOW] = parent->addAction("Parameter Window"); - mDockWindowActions[WINDOWS_PARAMETERWINDOW]->setCheckable(true); - mDockWindowActions[WINDOWS_ATTRIBUTEWINDOW] = parent->addAction("Attribute Window"); - mDockWindowActions[WINDOWS_ATTRIBUTEWINDOW]->setCheckable(true); - mDockWindowActions[WINDOWS_NODEGROUPWINDOW] = parent->addAction("Node Group Window"); - mDockWindowActions[WINDOWS_NODEGROUPWINDOW]->setCheckable(true); - mDockWindowActions[WINDOWS_PALETTEWINDOW] = parent->addAction("Palette Window"); - mDockWindowActions[WINDOWS_PALETTEWINDOW]->setCheckable(true); + m_dockWindowActions[WINDOWS_PARAMETERWINDOW] = parent->addAction("Parameter Window"); + m_dockWindowActions[WINDOWS_PARAMETERWINDOW]->setCheckable(true); + m_dockWindowActions[WINDOWS_ATTRIBUTEWINDOW] = parent->addAction("Attribute Window"); + m_dockWindowActions[WINDOWS_ATTRIBUTEWINDOW]->setCheckable(true); + m_dockWindowActions[WINDOWS_NODEGROUPWINDOW] = parent->addAction("Node Group Window"); + m_dockWindowActions[WINDOWS_NODEGROUPWINDOW]->setCheckable(true); + m_dockWindowActions[WINDOWS_PALETTEWINDOW] = parent->addAction("Palette Window"); + m_dockWindowActions[WINDOWS_PALETTEWINDOW]->setCheckable(true); #if AZ_TRAIT_EMOTIONFX_HAS_GAME_CONTROLLER - mDockWindowActions[WINDOWS_GAMECONTROLLERWINDOW] = parent->addAction("Game Controller Window"); - mDockWindowActions[WINDOWS_GAMECONTROLLERWINDOW]->setCheckable(true); + m_dockWindowActions[WINDOWS_GAMECONTROLLERWINDOW] = parent->addAction("Game Controller Window"); + m_dockWindowActions[WINDOWS_GAMECONTROLLERWINDOW]->setCheckable(true); #endif - connect(mDockWindowActions[WINDOWS_PARAMETERWINDOW], &QAction::triggered, this, [this](bool checked) { + connect(m_dockWindowActions[WINDOWS_PARAMETERWINDOW], &QAction::triggered, this, [this](bool checked) { UpdateWindowVisibility(WINDOWS_PARAMETERWINDOW, checked); }); - connect(mDockWindowActions[WINDOWS_ATTRIBUTEWINDOW], &QAction::triggered, this, [this](bool checked) { + connect(m_dockWindowActions[WINDOWS_ATTRIBUTEWINDOW], &QAction::triggered, this, [this](bool checked) { UpdateWindowVisibility(WINDOWS_ATTRIBUTEWINDOW, checked); }); - connect(mDockWindowActions[WINDOWS_NODEGROUPWINDOW], &QAction::triggered, this, [this](bool checked) { + connect(m_dockWindowActions[WINDOWS_NODEGROUPWINDOW], &QAction::triggered, this, [this](bool checked) { UpdateWindowVisibility(WINDOWS_NODEGROUPWINDOW, checked); }); - connect(mDockWindowActions[WINDOWS_PALETTEWINDOW], &QAction::triggered, this, [this](bool checked) { + connect(m_dockWindowActions[WINDOWS_PALETTEWINDOW], &QAction::triggered, this, [this](bool checked) { UpdateWindowVisibility(WINDOWS_PALETTEWINDOW, checked); }); #if AZ_TRAIT_EMOTIONFX_HAS_GAME_CONTROLLER - connect(mDockWindowActions[WINDOWS_GAMECONTROLLERWINDOW], &QAction::triggered, this, [this](bool checked) { + connect(m_dockWindowActions[WINDOWS_GAMECONTROLLERWINDOW], &QAction::triggered, this, [this](bool checked) { UpdateWindowVisibility(WINDOWS_GAMECONTROLLERWINDOW, checked); }); #endif @@ -427,17 +426,17 @@ namespace EMStudio void AnimGraphPlugin::SetOptionFlag(EDockWindowOptionFlag option, bool isEnabled) { - if (mDockWindowActions[option]) + if (m_dockWindowActions[option]) { - mDockWindowActions[option]->setChecked(isEnabled); + m_dockWindowActions[option]->setChecked(isEnabled); } } void AnimGraphPlugin::SetOptionEnabled(EDockWindowOptionFlag option, bool isEnabled) { - if (mDockWindowActions[option]) + if (m_dockWindowActions[option]) { - mDockWindowActions[option]->setEnabled(isEnabled); + m_dockWindowActions[option]->setEnabled(isEnabled); } } @@ -474,18 +473,18 @@ namespace EMStudio void AnimGraphPlugin::RegisterPerFrameCallback(AnimGraphPerFrameCallback* callback) { - if (AZStd::find(mPerFrameCallbacks.begin(), mPerFrameCallbacks.end(), callback) == mPerFrameCallbacks.end()) + if (AZStd::find(m_perFrameCallbacks.begin(), m_perFrameCallbacks.end(), callback) == m_perFrameCallbacks.end()) { - mPerFrameCallbacks.push_back(callback); + m_perFrameCallbacks.push_back(callback); } } void AnimGraphPlugin::UnregisterPerFrameCallback(AnimGraphPerFrameCallback* callback) { - auto it = AZStd::find(mPerFrameCallbacks.begin(), mPerFrameCallbacks.end(), callback); - if (it != mPerFrameCallbacks.end()) + auto it = AZStd::find(m_perFrameCallbacks.begin(), m_perFrameCallbacks.end(), callback); + if (it != m_perFrameCallbacks.end()) { - mPerFrameCallbacks.erase(it); + m_perFrameCallbacks.erase(it); } } @@ -537,106 +536,102 @@ namespace EMStudio m_animGraphObjectFactory = aznew EMotionFX::AnimGraphObjectFactory(); // create the graph node factory - mGraphNodeFactory = new GraphNodeFactory(); + m_graphNodeFactory = new GraphNodeFactory(); // create the corresponding widget that holds the menu and the toolbar - mViewWidget = new BlendGraphViewWidget(this, mDock); - mDock->setWidget(mViewWidget); - //mDock->setWidget( mGraphWidget ); // old: without menu and toolbar + m_viewWidget = new BlendGraphViewWidget(this, m_dock); + m_dock->setWidget(m_viewWidget); // create the graph widget - mGraphWidget = new BlendGraphWidget(this, mViewWidget); - //mGraphWidget->resize(1000, 700); - //mGraphWidget->move(0,50); - //mGraphWidget->show(); + m_graphWidget = new BlendGraphWidget(this, m_viewWidget); // get the main window QMainWindow* mainWindow = GetMainWindow(); // create the attribute dock window - mAttributeDock = new AzQtComponents::StyledDockWidget("Attributes", mainWindow); - mainWindow->addDockWidget(Qt::RightDockWidgetArea, mAttributeDock); + m_attributeDock = new AzQtComponents::StyledDockWidget("Attributes", mainWindow); + mainWindow->addDockWidget(Qt::RightDockWidgetArea, m_attributeDock); QDockWidget::DockWidgetFeatures features = QDockWidget::NoDockWidgetFeatures; //features |= QDockWidget::DockWidgetClosable; features |= QDockWidget::DockWidgetFloatable; features |= QDockWidget::DockWidgetMovable; - mAttributeDock->setFeatures(features); - mAttributeDock->setObjectName("AnimGraphPlugin::mAttributeDock"); - mAttributesWindow = new AttributesWindow(this); - mAttributeDock->setWidget(mAttributesWindow); + m_attributeDock->setFeatures(features); + m_attributeDock->setObjectName("AnimGraphPlugin::m_attributeDock"); + m_attributesWindow = new AttributesWindow(this); + m_attributeDock->setWidget(m_attributesWindow); // create the node group dock window - mNodeGroupDock = new AzQtComponents::StyledDockWidget("Node Groups", mainWindow); - mainWindow->addDockWidget(Qt::RightDockWidgetArea, mNodeGroupDock); + m_nodeGroupDock = new AzQtComponents::StyledDockWidget("Node Groups", mainWindow); + mainWindow->addDockWidget(Qt::RightDockWidgetArea, m_nodeGroupDock); features = QDockWidget::NoDockWidgetFeatures; //features |= QDockWidget::DockWidgetClosable; features |= QDockWidget::DockWidgetFloatable; features |= QDockWidget::DockWidgetMovable; - mNodeGroupDock->setFeatures(features); - mNodeGroupDock->setObjectName("AnimGraphPlugin::mNodeGroupDock"); - mNodeGroupWindow = new NodeGroupWindow(this); - mNodeGroupDock->setWidget(mNodeGroupWindow); + m_nodeGroupDock->setFeatures(features); + m_nodeGroupDock->setObjectName("AnimGraphPlugin::m_nodeGroupDock"); + m_nodeGroupWindow = new NodeGroupWindow(this); + m_nodeGroupDock->setWidget(m_nodeGroupWindow); // create the node palette dock - mNodePaletteDock = new AzQtComponents::StyledDockWidget("Anim Graph Palette", mainWindow); - mainWindow->addDockWidget(Qt::RightDockWidgetArea, mNodePaletteDock); + m_nodePaletteDock = new AzQtComponents::StyledDockWidget("Anim Graph Palette", mainWindow); + mainWindow->addDockWidget(Qt::RightDockWidgetArea, m_nodePaletteDock); features = QDockWidget::NoDockWidgetFeatures; //features |= QDockWidget::DockWidgetClosable; features |= QDockWidget::DockWidgetFloatable; features |= QDockWidget::DockWidgetMovable; - mNodePaletteDock->setFeatures(features); - mNodePaletteDock->setObjectName("AnimGraphPlugin::mPaletteDock"); - mPaletteWidget = new NodePaletteWidget(this); - mNodePaletteDock->setWidget(mPaletteWidget); + m_nodePaletteDock->setFeatures(features); + m_nodePaletteDock->setObjectName("AnimGraphPlugin::m_paletteDock"); + m_paletteWidget = new NodePaletteWidget(this); + m_nodePaletteDock->setWidget(m_paletteWidget); // create the parameter dock QScrollArea* scrollArea = new QScrollArea(); - mParameterDock = new AzQtComponents::StyledDockWidget("Parameters", mainWindow); - mainWindow->addDockWidget(Qt::RightDockWidgetArea, mParameterDock); + m_parameterDock = new AzQtComponents::StyledDockWidget("Parameters", mainWindow); + mainWindow->addDockWidget(Qt::RightDockWidgetArea, m_parameterDock); features = QDockWidget::NoDockWidgetFeatures; //features |= QDockWidget::DockWidgetClosable; features |= QDockWidget::DockWidgetFloatable; features |= QDockWidget::DockWidgetMovable; - mParameterDock->setFeatures(features); - mParameterDock->setObjectName("AnimGraphPlugin::mParameterDock"); - mParameterWindow = new ParameterWindow(this); - mParameterDock->setWidget(scrollArea); - scrollArea->setWidget(mParameterWindow); + m_parameterDock->setFeatures(features); + m_parameterDock->setObjectName("AnimGraphPlugin::m_parameterDock"); + m_parameterWindow = new ParameterWindow(this); + m_parameterDock->setWidget(scrollArea); + scrollArea->setWidget(m_parameterWindow); scrollArea->setWidgetResizable(true); // Create Navigation Widget (embedded into BlendGraphViewWidget) - mNavigateWidget = new NavigateWidget(this); + m_navigateWidget = new NavigateWidget(this); // init the display flags - mDisplayFlags = 0; + m_displayFlags = 0; // init the view widget // it must be init after navigate widget is created because actions are linked to it - mViewWidget->Init(mGraphWidget); + m_viewWidget->Init(m_graphWidget); #if AZ_TRAIT_EMOTIONFX_HAS_GAME_CONTROLLER // create the game controller dock - mGameControllerDock = new AzQtComponents::StyledDockWidget("Game Controller", mainWindow); - mainWindow->addDockWidget(Qt::RightDockWidgetArea, mGameControllerDock); + m_gameControllerDock = new AzQtComponents::StyledDockWidget("Game Controller", mainWindow); + mainWindow->addDockWidget(Qt::RightDockWidgetArea, m_gameControllerDock); features = QDockWidget::NoDockWidgetFeatures; //features |= QDockWidget::DockWidgetClosable; features |= QDockWidget::DockWidgetFloatable; features |= QDockWidget::DockWidgetMovable; - mGameControllerDock->setFeatures(features); - mGameControllerDock->setObjectName("AnimGraphPlugin::mGameControllerDock"); - mGameControllerWindow = new GameControllerWindow(this); - mGameControllerDock->setWidget(mGameControllerWindow); + m_gameControllerDock->setFeatures(features); + m_gameControllerDock->setObjectName("AnimGraphPlugin::m_gameControllerDock"); + m_gameControllerWindow = new GameControllerWindow(this); + m_gameControllerDock->setWidget(m_gameControllerWindow); #endif // load options LoadOptions(); // initialize the dirty files callback - mDirtyFilesCallback = new SaveDirtyAnimGraphFilesCallback(); - GetMainWindow()->GetDirtyFileManager()->AddCallback(mDirtyFilesCallback); + m_dirtyFilesCallback = new SaveDirtyAnimGraphFilesCallback(); + GetMainWindow()->GetDirtyFileManager()->AddCallback(m_dirtyFilesCallback); // construct the event handler - EMotionFX::GetEventManager().AddEventHandler(&mEventHandler); + EMotionFX::GetEventManager().AddEventHandler(&m_eventHandler); // connect to the timeline recorder data TimeViewPlugin* timeViewPlugin = FindTimeViewPlugin(); @@ -645,7 +640,7 @@ namespace EMStudio connect(timeViewPlugin, &TimeViewPlugin::DoubleClickedRecorderNodeHistoryItem, this, &AnimGraphPlugin::OnDoubleClickedRecorderNodeHistoryItem); connect(timeViewPlugin, &TimeViewPlugin::ClickedRecorderNodeHistoryItem, this, &AnimGraphPlugin::OnClickedRecorderNodeHistoryItem); // detect changes in the recorder - connect(timeViewPlugin, &TimeViewPlugin::RecorderStateChanged, mParameterWindow, &ParameterWindow::OnRecorderStateChanged); + connect(timeViewPlugin, &TimeViewPlugin::RecorderStateChanged, m_parameterWindow, &ParameterWindow::OnRecorderStateChanged); } EMotionFX::AnimGraph* firstSelectedAnimGraph = CommandSystem::GetCommandManager()->GetCurrentSelection().GetFirstAnimGraph(); @@ -658,14 +653,14 @@ namespace EMStudio void AnimGraphPlugin::LoadOptions() { QSettings settings(AZStd::string(GetManager()->GetAppDataFolder() + "EMStudioRenderOptions.cfg").c_str(), QSettings::IniFormat, this); - mOptions = AnimGraphOptions::Load(&settings); + m_options = AnimGraphOptions::Load(&settings); } // save the options void AnimGraphPlugin::SaveOptions() { QSettings settings(AZStd::string(GetManager()->GetAppDataFolder() + "EMStudioRenderOptions.cfg").c_str(), QSettings::IniFormat, this); - mOptions.Save(&settings); + m_options.Save(&settings); } @@ -673,9 +668,9 @@ namespace EMStudio void AnimGraphPlugin::OnAfterLoadLayout() { // fit graph on screen - if (mGraphWidget->GetActiveGraph()) + if (m_graphWidget->GetActiveGraph()) { - mGraphWidget->GetActiveGraph()->FitGraphOnScreen(mGraphWidget->geometry().width(), mGraphWidget->geometry().height(), mGraphWidget->GetMousePos(), false); + m_graphWidget->GetActiveGraph()->FitGraphOnScreen(m_graphWidget->geometry().width(), m_graphWidget->geometry().height(), m_graphWidget->GetMousePos(), false); } // connect to the timeline recorder data @@ -700,13 +695,13 @@ namespace EMStudio void AnimGraphPlugin::InitForAnimGraph(EMotionFX::AnimGraph* setup) { AZ_UNUSED(setup); - mAttributesWindow->Unlock(); - mAttributesWindow->Init(QModelIndex(), true); // Force update - mParameterWindow->Reinit(); - mNodeGroupWindow->Init(); - mViewWidget->UpdateAnimGraphOptions(); + m_attributesWindow->Unlock(); + m_attributesWindow->Init(QModelIndex(), true); // Force update + m_parameterWindow->Reinit(); + m_nodeGroupWindow->Init(); + m_viewWidget->UpdateAnimGraphOptions(); #if AZ_TRAIT_EMOTIONFX_HAS_GAME_CONTROLLER - mGameControllerWindow->ReInit(); + m_gameControllerWindow->ReInit(); #endif } @@ -715,13 +710,13 @@ namespace EMStudio AnimGraphEventHandler::AnimGraphEventHandler(AnimGraphPlugin* plugin) : EMotionFX::EventHandler() { - mPlugin = plugin; + m_plugin = plugin; } bool AnimGraphEventHandler::OnRayIntersectionTest(const AZ::Vector3& start, const AZ::Vector3& end, EMotionFX::IntersectionInfo* outIntersectInfo) { - outIntersectInfo->mIsValid = true; + outIntersectInfo->m_isValid = true; AZ::Vector3 pos; AZ::Vector3 normal; @@ -745,7 +740,7 @@ namespace EMStudio continue; } - if (actorInstance == outIntersectInfo->mIgnoreActorInstance) + if (actorInstance == outIntersectInfo->m_ignoreActorInstance) { continue; } @@ -757,11 +752,11 @@ namespace EMStudio if (first) { - outIntersectInfo->mPosition = pos; - outIntersectInfo->mNormal = normal; - outIntersectInfo->mUV = uv; - outIntersectInfo->mBaryCentricU = baryU; - outIntersectInfo->mBaryCentricV = baryU; + outIntersectInfo->m_position = pos; + outIntersectInfo->m_normal = normal; + outIntersectInfo->m_uv = uv; + outIntersectInfo->m_baryCentricU = baryU; + outIntersectInfo->m_baryCentricV = baryU; closestDist = MCore::SafeLength(start - pos); } else @@ -769,11 +764,11 @@ namespace EMStudio float dist = MCore::SafeLength(start - pos); if (dist < closestDist) { - outIntersectInfo->mPosition = pos; - outIntersectInfo->mNormal = normal; - outIntersectInfo->mUV = uv; - outIntersectInfo->mBaryCentricU = baryU; - outIntersectInfo->mBaryCentricV = baryU; + outIntersectInfo->m_position = pos; + outIntersectInfo->m_normal = normal; + outIntersectInfo->m_uv = uv; + outIntersectInfo->m_baryCentricU = baryU; + outIntersectInfo->m_baryCentricV = baryU; closestDist = MCore::SafeLength(start - pos); closestDist = dist; } @@ -1008,24 +1003,24 @@ namespace EMStudio void AnimGraphEventHandler::OnDeleteAnimGraph(EMotionFX::AnimGraph* animGraph) { - if (mPlugin->GetActiveAnimGraph() == animGraph) + if (m_plugin->GetActiveAnimGraph() == animGraph) { - mPlugin->SetActiveAnimGraph(nullptr); + m_plugin->SetActiveAnimGraph(nullptr); } } void AnimGraphEventHandler::OnDeleteAnimGraphInstance(EMotionFX::AnimGraphInstance* animGraphInstance) { - mPlugin->GetAnimGraphModel().SetAnimGraphInstance(animGraphInstance->GetAnimGraph(), animGraphInstance, nullptr); + m_plugin->GetAnimGraphModel().SetAnimGraphInstance(animGraphInstance->GetAnimGraph(), animGraphInstance, nullptr); } // activate a given anim graph void AnimGraphPlugin::SetActiveAnimGraph(EMotionFX::AnimGraph* animGraph) { - if (mActiveAnimGraph != animGraph) + if (m_activeAnimGraph != animGraph) { - mActiveAnimGraph = animGraph; + m_activeAnimGraph = animGraph; InitForAnimGraph(animGraph); // Focus on the newly actived anim graph if it has already been added to the anim graph model. @@ -1108,7 +1103,7 @@ namespace EMStudio void AnimGraphPlugin::SaveAnimGraphAs(EMotionFX::AnimGraph* animGraph, MCore::CommandGroup* commandGroup) { - const AZStd::string filename = GetMainWindow()->GetFileManager()->SaveAnimGraphFileDialog(mViewWidget); + const AZStd::string filename = GetMainWindow()->GetFileManager()->SaveAnimGraphFileDialog(m_viewWidget); if (filename.empty()) { return; @@ -1127,7 +1122,7 @@ namespace EMStudio (sourceAnimGraph || cacheAnimGraph) && (sourceAnimGraph != focusedAnimGraph && cacheAnimGraph != focusedAnimGraph)) { - QMessageBox::warning(mDock, "Cannot overwrite anim graph", "Anim graph is already opened and cannot be overwritten.", QMessageBox::Ok); + QMessageBox::warning(m_dock, "Cannot overwrite anim graph", "Anim graph is already opened and cannot be overwritten.", QMessageBox::Ok); return; } @@ -1144,7 +1139,7 @@ namespace EMStudio void AnimGraphPlugin::OnFileOpen() { - AZStd::string filename = GetMainWindow()->GetFileManager()->LoadAnimGraphFileDialog(mViewWidget); + AZStd::string filename = GetMainWindow()->GetFileManager()->LoadAnimGraphFileDialog(m_viewWidget); GetMainWindow()->activateWindow(); if (filename.empty()) { @@ -1269,39 +1264,39 @@ namespace EMStudio // timer event void AnimGraphPlugin::ProcessFrame(float timePassedInSeconds) { - if (GetManager()->GetAvoidRendering() || !mGraphWidget || mGraphWidget->visibleRegion().isEmpty()) + if (GetManager()->GetAvoidRendering() || !m_graphWidget || m_graphWidget->visibleRegion().isEmpty()) { return; } - mTotalTime += timePassedInSeconds; + m_totalTime += timePassedInSeconds; - for (AnimGraphPerFrameCallback* callback : mPerFrameCallbacks) + for (AnimGraphPerFrameCallback* callback : m_perFrameCallbacks) { callback->ProcessFrame(timePassedInSeconds); } bool redraw = false; #ifdef MCORE_DEBUG - if (mTotalTime > 1.0f / 30.0f) + if (m_totalTime > 1.0f / 30.0f) #else - if (mTotalTime > 1.0f / 60.0f) + if (m_totalTime > 1.0f / 60.0f) #endif { redraw = true; - mTotalTime = 0.0f; + m_totalTime = 0.0f; } if (EMotionFX::GetRecorder().GetIsInPlayMode()) { - if (MCore::Compare::CheckIfIsClose(EMotionFX::GetRecorder().GetCurrentPlayTime(), mLastPlayTime, 0.001f) == false) + if (MCore::Compare::CheckIfIsClose(EMotionFX::GetRecorder().GetCurrentPlayTime(), m_lastPlayTime, 0.001f) == false) { - mParameterWindow->UpdateParameterValues(); - mLastPlayTime = EMotionFX::GetRecorder().GetCurrentPlayTime(); + m_parameterWindow->UpdateParameterValues(); + m_lastPlayTime = EMotionFX::GetRecorder().GetCurrentPlayTime(); } } - mGraphWidget->ProcessFrame(redraw); + m_graphWidget->ProcessFrame(redraw); } @@ -1392,17 +1387,17 @@ namespace EMStudio MCORE_UNUSED(actorInstanceData); // try to locate the node based on its unique ID - EMotionFX::AnimGraph* animGraph = EMotionFX::GetAnimGraphManager().FindAnimGraphByID(historyItem->mAnimGraphID); + EMotionFX::AnimGraph* animGraph = EMotionFX::GetAnimGraphManager().FindAnimGraphByID(historyItem->m_animGraphId); if (animGraph == nullptr) { - QMessageBox::warning(mDock, "Cannot Find Anim Graph", "The anim graph used by this node cannot be located anymore, did you delete it?", QMessageBox::Ok); + QMessageBox::warning(m_dock, "Cannot Find Anim Graph", "The anim graph used by this node cannot be located anymore, did you delete it?", QMessageBox::Ok); return; } - EMotionFX::AnimGraphNode* foundNode = animGraph->RecursiveFindNodeById(historyItem->mNodeId); + EMotionFX::AnimGraphNode* foundNode = animGraph->RecursiveFindNodeById(historyItem->m_nodeId); if (foundNode == nullptr) { - QMessageBox::warning(mDock, "Cannot Find Node", "The anim graph node cannot be found. Did you perhaps delete the node or change animgraph?", QMessageBox::Ok); + QMessageBox::warning(m_dock, "Cannot Find Node", "The anim graph node cannot be found. Did you perhaps delete the node or change animgraph?", QMessageBox::Ok); return; } @@ -1422,24 +1417,24 @@ namespace EMStudio MCORE_UNUSED(actorInstanceData); // try to locate the node based on its unique ID - EMotionFX::AnimGraph* animGraph = EMotionFX::GetAnimGraphManager().FindAnimGraphByID(historyItem->mAnimGraphID); + EMotionFX::AnimGraph* animGraph = EMotionFX::GetAnimGraphManager().FindAnimGraphByID(historyItem->m_animGraphId); if (animGraph == nullptr) { - QMessageBox::warning(mDock, "Cannot Find Anim Graph", "The anim graph used by this node cannot be located anymore, did you delete it?", QMessageBox::Ok); + QMessageBox::warning(m_dock, "Cannot Find Anim Graph", "The anim graph used by this node cannot be located anymore, did you delete it?", QMessageBox::Ok); return; } - EMotionFX::AnimGraphNode* foundNode = animGraph->RecursiveFindNodeById(historyItem->mNodeId); + EMotionFX::AnimGraphNode* foundNode = animGraph->RecursiveFindNodeById(historyItem->m_nodeId); if (foundNode == nullptr) { - QMessageBox::warning(mDock, "Cannot Find Node", "The anim graph node cannot be found. Did you perhaps delete the node or change animgraph?", QMessageBox::Ok); + QMessageBox::warning(m_dock, "Cannot Find Node", "The anim graph node cannot be found. Did you perhaps delete the node or change animgraph?", QMessageBox::Ok); return; } EMotionFX::AnimGraphNode* nodeToShow = foundNode->GetParentNode(); if (nodeToShow) { - const QModelIndex foundNodeIndex = m_animGraphModel->FindModelIndex(nodeToShow, historyItem->mAnimGraphInstance); + const QModelIndex foundNodeIndex = m_animGraphModel->FindModelIndex(nodeToShow, historyItem->m_animGraphInstance); if (foundNodeIndex.isValid()) { m_animGraphModel->Focus(foundNodeIndex); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphPlugin.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphPlugin.h index af6fcde3d6..3510920d2c 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphPlugin.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphPlugin.h @@ -84,7 +84,7 @@ namespace EMStudio void OnDeleteAnimGraphInstance(EMotionFX::AnimGraphInstance* animGraphInstance) override; private: - AnimGraphPlugin* mPlugin; + AnimGraphPlugin* m_plugin; }; class AnimGraphPerFrameCallback @@ -133,7 +133,7 @@ namespace EMStudio void AddWindowMenuEntries(QMenu* parent) override; void SetActiveAnimGraph(EMotionFX::AnimGraph* animGraph); - EMotionFX::AnimGraph* GetActiveAnimGraph() { return mActiveAnimGraph; } + EMotionFX::AnimGraph* GetActiveAnimGraph() { return m_activeAnimGraph; } void SaveAnimGraph(const char* filename, size_t animGraphIndex, MCore::CommandGroup* commandGroup = nullptr); void SaveAnimGraph(EMotionFX::AnimGraph* animGraph, MCore::CommandGroup* commandGroup = nullptr); @@ -141,7 +141,7 @@ namespace EMStudio int SaveDirtyAnimGraph(EMotionFX::AnimGraph* animGraph, MCore::CommandGroup* commandGroup, bool askBeforeSaving, bool showCancelButton = true); int OnSaveDirtyAnimGraphs(); - PluginOptions* GetOptions() override { return &mOptions; } + PluginOptions* GetOptions() override { return &m_options; } void LoadOptions(); void SaveOptions(); @@ -193,41 +193,41 @@ namespace EMStudio void OnClickedRecorderNodeHistoryItem(EMotionFX::Recorder::ActorInstanceData* actorInstanceData, EMotionFX::Recorder::NodeHistoryItem* historyItem); public: - BlendGraphWidget* GetGraphWidget() { return mGraphWidget; } - NavigateWidget* GetNavigateWidget() { return mNavigateWidget; } - NodePaletteWidget* GetPaletteWidget() { return mPaletteWidget; } - AttributesWindow* GetAttributesWindow() { return mAttributesWindow; } - ParameterWindow* GetParameterWindow() { return mParameterWindow; } - NodeGroupWindow* GetNodeGroupWidget() { return mNodeGroupWindow; } - BlendGraphViewWidget* GetViewWidget() { return mViewWidget; } + BlendGraphWidget* GetGraphWidget() { return m_graphWidget; } + NavigateWidget* GetNavigateWidget() { return m_navigateWidget; } + NodePaletteWidget* GetPaletteWidget() { return m_paletteWidget; } + AttributesWindow* GetAttributesWindow() { return m_attributesWindow; } + ParameterWindow* GetParameterWindow() { return m_parameterWindow; } + NodeGroupWindow* GetNodeGroupWidget() { return m_nodeGroupWindow; } + BlendGraphViewWidget* GetViewWidget() { return m_viewWidget; } NavigationHistory* GetNavigationHistory() const { return m_navigationHistory; } - QDockWidget* GetAttributeDock() { return mAttributeDock; } - QDockWidget* GetNodePaletteDock() { return mNodePaletteDock; } - QDockWidget* GetParameterDock() { return mParameterDock; } - QDockWidget* GetNodeGroupDock() { return mNodeGroupDock; } + QDockWidget* GetAttributeDock() { return m_attributeDock; } + QDockWidget* GetNodePaletteDock() { return m_nodePaletteDock; } + QDockWidget* GetParameterDock() { return m_parameterDock; } + QDockWidget* GetNodeGroupDock() { return m_nodeGroupDock; } #if AZ_TRAIT_EMOTIONFX_HAS_GAME_CONTROLLER - GameControllerWindow* GetGameControllerWindow() { return mGameControllerWindow; } - QDockWidget* GetGameControllerDock() { return mGameControllerDock; } + GameControllerWindow* GetGameControllerWindow() { return m_gameControllerWindow; } + QDockWidget* GetGameControllerDock() { return m_gameControllerDock; } #endif void SetDisplayFlagEnabled(uint32 flags, bool enabled) { if (enabled) { - mDisplayFlags |= flags; + m_displayFlags |= flags; } else { - mDisplayFlags &= ~flags; + m_displayFlags &= ~flags; } } - bool GetIsDisplayFlagEnabled(uint32 flags) const { return (mDisplayFlags & flags); } - uint32 GetDisplayFlags() const { return mDisplayFlags; } + bool GetIsDisplayFlagEnabled(uint32 flags) const { return (m_displayFlags & flags); } + uint32 GetDisplayFlags() const { return m_displayFlags; } const EMotionFX::AnimGraphObjectFactory* GetAnimGraphObjectFactory() const { return m_animGraphObjectFactory; } - GraphNodeFactory* GetGraphNodeFactory() { return mGraphNodeFactory; } + GraphNodeFactory* GetGraphNodeFactory() { return m_graphNodeFactory; } // overloaded main init function void Reflect(AZ::ReflectContext* serializeContext) override; @@ -235,10 +235,10 @@ namespace EMStudio void OnAfterLoadLayout() override; EMStudioPlugin* Clone() override; - const AnimGraphOptions& GetAnimGraphOptions() const { return mOptions; } + const AnimGraphOptions& GetAnimGraphOptions() const { return m_options; } - void SetDisableRendering(bool flag) { mDisableRendering = flag; } - bool GetDisableRendering() const { return mDisableRendering; } + void SetDisableRendering(bool flag) { m_disableRendering = flag; } + bool GetDisableRendering() const { return m_disableRendering; } void SetActionFilter(const AnimGraphActionFilter& actionFilter); const AnimGraphActionFilter& GetActionFilter() const; @@ -264,44 +264,44 @@ namespace EMStudio MCORE_DEFINECOMMANDCALLBACK(CommandPlayMotionCallback); AZStd::vector m_commandCallbacks; - AZStd::vector mPerFrameCallbacks; + AZStd::vector m_perFrameCallbacks; - bool mDisableRendering; + bool m_disableRendering; - AnimGraphEventHandler mEventHandler; + AnimGraphEventHandler m_eventHandler; - BlendGraphWidget* mGraphWidget; - NavigateWidget* mNavigateWidget; - NodePaletteWidget* mPaletteWidget; - AttributesWindow* mAttributesWindow; - ParameterWindow* mParameterWindow; - NodeGroupWindow* mNodeGroupWindow; - BlendGraphViewWidget* mViewWidget; + BlendGraphWidget* m_graphWidget; + NavigateWidget* m_navigateWidget; + NodePaletteWidget* m_paletteWidget; + AttributesWindow* m_attributesWindow; + ParameterWindow* m_parameterWindow; + NodeGroupWindow* m_nodeGroupWindow; + BlendGraphViewWidget* m_viewWidget; NavigationHistory* m_navigationHistory; - SaveDirtyAnimGraphFilesCallback* mDirtyFilesCallback; + SaveDirtyAnimGraphFilesCallback* m_dirtyFilesCallback; - QDockWidget* mAttributeDock; - QDockWidget* mNodePaletteDock; - QDockWidget* mParameterDock; - QDockWidget* mNodeGroupDock; - QAction* mDockWindowActions[NUM_DOCKWINDOW_OPTIONS]; - EMotionFX::AnimGraph* mActiveAnimGraph; + QDockWidget* m_attributeDock; + QDockWidget* m_nodePaletteDock; + QDockWidget* m_parameterDock; + QDockWidget* m_nodeGroupDock; + QAction* m_dockWindowActions[NUM_DOCKWINDOW_OPTIONS]; + EMotionFX::AnimGraph* m_activeAnimGraph; #if AZ_TRAIT_EMOTIONFX_HAS_GAME_CONTROLLER - GameControllerWindow* mGameControllerWindow; - QPointer mGameControllerDock; + GameControllerWindow* m_gameControllerWindow; + QPointer m_gameControllerDock; #endif - float mLastPlayTime; - float mTotalTime; + float m_lastPlayTime; + float m_totalTime; - uint32 mDisplayFlags; + uint32 m_displayFlags; - AnimGraphOptions mOptions; + AnimGraphOptions m_options; EMotionFX::AnimGraphObjectFactory* m_animGraphObjectFactory; - GraphNodeFactory* mGraphNodeFactory; + GraphNodeFactory* m_graphNodeFactory; // Model used for the MVC pattern AnimGraphModel* m_animGraphModel; @@ -311,7 +311,7 @@ namespace EMStudio AnimGraphActionFilter m_actionFilter; void InitForAnimGraph(EMotionFX::AnimGraph* setup); - bool GetOptionFlag(EDockWindowOptionFlag option) { return mDockWindowActions[(uint32)option]->isChecked(); } + bool GetOptionFlag(EDockWindowOptionFlag option) { return m_dockWindowActions[(uint32)option]->isChecked(); } void SetOptionFlag(EDockWindowOptionFlag option, bool isEnabled); void SetOptionEnabled(EDockWindowOptionFlag option, bool isEnabled); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphVisualNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphVisualNode.cpp index 91f5e00dd0..8af57e6dee 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphVisualNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphVisualNode.cpp @@ -23,10 +23,10 @@ namespace EMStudio AnimGraphVisualNode::AnimGraphVisualNode(const QModelIndex& modelIndex, AnimGraphPlugin* plugin, EMotionFX::AnimGraphNode* node) : GraphNode(modelIndex, node->GetName(), 0, 0) { - mEMFXNode = node; - mCanHaveChildren = node->GetCanHaveChildren(); - mHasVisualGraph = node->GetHasVisualGraph(); - mPlugin = plugin; + m_emfxNode = node; + m_canHaveChildren = node->GetCanHaveChildren(); + m_hasVisualGraph = node->GetHasVisualGraph(); + m_plugin = plugin; SetSubTitle(node->GetPaletteName(), false); } @@ -45,24 +45,24 @@ namespace EMStudio void AnimGraphVisualNode::Sync() { - SetName(mEMFXNode->GetName()); - SetNodeInfo(mEMFXNode->GetNodeInfo()); + SetName(m_emfxNode->GetName()); + SetNodeInfo(m_emfxNode->GetNodeInfo()); - SetDeletable(mEMFXNode->GetIsDeletable()); - SetBaseColor(AzColorToQColor(mEMFXNode->GetVisualColor())); - SetHasChildIndicatorColor(AzColorToQColor(mEMFXNode->GetHasChildIndicatorColor())); - SetIsCollapsed(mEMFXNode->GetIsCollapsed()); + SetDeletable(m_emfxNode->GetIsDeletable()); + SetBaseColor(AzColorToQColor(m_emfxNode->GetVisualColor())); + SetHasChildIndicatorColor(AzColorToQColor(m_emfxNode->GetHasChildIndicatorColor())); + SetIsCollapsed(m_emfxNode->GetIsCollapsed()); // Update position UpdateRects(); - MoveAbsolute(QPoint(mEMFXNode->GetVisualPosX(), mEMFXNode->GetVisualPosY())); + MoveAbsolute(QPoint(m_emfxNode->GetVisualPosX(), m_emfxNode->GetVisualPosY())); - SetIsVisualized(mEMFXNode->GetIsVisualizationEnabled()); - SetCanVisualize(mEMFXNode->GetSupportsVisualization()); - SetIsEnabled(mEMFXNode->GetIsEnabled()); - SetVisualizeColor(AzColorToQColor(mEMFXNode->GetVisualizeColor())); - SetHasVisualOutputPorts(mEMFXNode->GetHasVisualOutputPorts()); - mHasVisualGraph = mEMFXNode->GetHasVisualGraph(); + SetIsVisualized(m_emfxNode->GetIsVisualizationEnabled()); + SetCanVisualize(m_emfxNode->GetSupportsVisualization()); + SetIsEnabled(m_emfxNode->GetIsEnabled()); + SetVisualizeColor(AzColorToQColor(m_emfxNode->GetVisualizeColor())); + SetHasVisualOutputPorts(m_emfxNode->GetHasVisualOutputPorts()); + m_hasVisualGraph = m_emfxNode->GetHasVisualGraph(); UpdateTextPixmap(); } @@ -72,30 +72,6 @@ namespace EMStudio void AnimGraphVisualNode::RenderDebugInfo(QPainter& painter) { MCORE_UNUSED(painter); - /* // get the selected actor instance - EMotionFX::ActorInstance* actorInstance = EMotionFX::GetCommandManager()->GetCurrentSelection().GetSingleActorInstance(); - if (actorInstance == nullptr) - return; - - // get the anim graph instance - EMotionFX::AnimGraphInstance* animGraphInstance = actorInstance->GetAnimGraphInstance(); - if (animGraphInstance == nullptr) - return; - - QRect rect( mRect.left(), mRect.bottom(), mRect.width(), 10 ); - - // draw header text - QTextOption textOptions; - textOptions.setAlignment( Qt::AlignCenter|Qt::AlignTop ); - painter.setPen( QColor(0,255,0) ); - - QString s; - //s.sprintf("%.3f %.3f", mEMFXNode->FindUniqueData(animGraphInstance)->GetInternalPlaySpeed(), mEMFXNode->FindUniqueData(animGraphInstance)->GetPlaySpeed()); - //painter.drawText( rect, s, textOptions ); - - //rect.translate(0, 12); - s.sprintf("%.3f %.3f", mEMFXNode->FindUniqueData(animGraphInstance)->GetGlobalWeight(), mEMFXNode->FindUniqueData(animGraphInstance)->GetLocalWeight()); - painter.drawText( rect, s, textOptions );*/ } @@ -103,7 +79,7 @@ namespace EMStudio void AnimGraphVisualNode::RenderTracks(QPainter& painter, const QColor bgColor, const QColor bgColor2, int32 heightOffset) { // get the sync track - QRect rect(mRect.left() + 5, mRect.bottom() - 13 + heightOffset, mRect.width() - 10, 8); + QRect rect(m_rect.left() + 5, m_rect.bottom() - 13 + heightOffset, m_rect.width() - 10, 8); painter.setPen(bgColor.darker(185)); painter.setBrush(bgColor2); @@ -116,7 +92,7 @@ namespace EMStudio return; } - const float duration = mEMFXNode->GetDuration(animGraphInstance); + const float duration = m_emfxNode->GetDuration(animGraphInstance); if (duration < MCore::Math::epsilon) { return; @@ -124,7 +100,7 @@ namespace EMStudio // draw the background rect QRect playRect = rect; - int32 x = aznumeric_cast(rect.left() + 1 + (rect.width() - 2) * (mEMFXNode->GetCurrentPlayTime(animGraphInstance) / duration)); + int32 x = aznumeric_cast(rect.left() + 1 + (rect.width() - 2) * (m_emfxNode->GetCurrentPlayTime(animGraphInstance) / duration)); playRect.setRight(x); playRect.setLeft(rect.left() + 1); playRect.setTop(rect.top() + 1); @@ -134,7 +110,7 @@ namespace EMStudio painter.drawRect(playRect); // draw the sync keys - const EMotionFX::AnimGraphNodeData* uniqueData = mEMFXNode->FindOrCreateUniqueNodeData(animGraphInstance); + const EMotionFX::AnimGraphNodeData* uniqueData = m_emfxNode->FindOrCreateUniqueNodeData(animGraphInstance); const EMotionFX::AnimGraphSyncTrack* syncTrack = uniqueData->GetSyncTrack(); const size_t numSyncPoints = syncTrack ? syncTrack->GetNumEvents() : 0; @@ -169,7 +145,7 @@ namespace EMStudio // draw the current play time painter.setPen(Qt::yellow); - x = aznumeric_cast(rect.left() + 1 + (rect.width() - 2) * (mEMFXNode->GetCurrentPlayTime(animGraphInstance) / duration)); + x = aznumeric_cast(rect.left() + 1 + (rect.width() - 2) * (m_emfxNode->GetCurrentPlayTime(animGraphInstance) / duration)); painter.drawLine(x, rect.top() + 1, x, rect.bottom()); } @@ -187,7 +163,7 @@ namespace EMStudio // extract anim graph instance EMotionFX::AnimGraphInstance* animGraphInstance = ExtractAnimGraphInstance(); - return (animGraphInstance == nullptr) || (animGraphInstance->GetIsOutputReady(mEMFXNode->GetParentNode()->GetObjectIndex()) == false); + return (animGraphInstance == nullptr) || (animGraphInstance->GetIsOutputReady(m_emfxNode->GetParentNode()->GetObjectIndex()) == false); } @@ -202,7 +178,7 @@ namespace EMStudio } // return the error state of the emfx node - EMotionFX::AnimGraphObjectData* uniqueData = mEMFXNode->FindOrCreateUniqueNodeData(animGraphInstance); - return mEMFXNode->HierarchicalHasError(uniqueData); + EMotionFX::AnimGraphObjectData* uniqueData = m_emfxNode->FindOrCreateUniqueNodeData(animGraphInstance); + return m_emfxNode->HierarchicalHasError(uniqueData); } } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphVisualNode.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphVisualNode.h index 7243d182bc..c25027ef91 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphVisualNode.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphVisualNode.h @@ -34,9 +34,9 @@ namespace EMStudio void Sync() override; - MCORE_INLINE void SetEMFXNode(EMotionFX::AnimGraphNode* emfxNode) { mEMFXNode = emfxNode; } - MCORE_INLINE EMotionFX::AnimGraphNode* GetEMFXNode() { return mEMFXNode; } - MCORE_INLINE AnimGraphPlugin* GetAnimGraphPlugin() const { return mPlugin; } + MCORE_INLINE void SetEMFXNode(EMotionFX::AnimGraphNode* emfxNode) { m_emfxNode = emfxNode; } + MCORE_INLINE EMotionFX::AnimGraphNode* GetEMFXNode() { return m_emfxNode; } + MCORE_INLINE AnimGraphPlugin* GetAnimGraphPlugin() const { return m_plugin; } EMotionFX::AnimGraphInstance* ExtractAnimGraphInstance() const; void RenderTracks(QPainter& painter, const QColor bgColor, const QColor bgColor2, int32 heightOffset = 0); @@ -48,8 +48,8 @@ namespace EMStudio protected: QColor AzColorToQColor(const AZ::Color& col) const; - EMotionFX::AnimGraphNode* mEMFXNode; - EMotionFX::AnimGraphPose mPose; - AnimGraphPlugin* mPlugin; + EMotionFX::AnimGraphNode* m_emfxNode; + EMotionFX::AnimGraphPose m_pose; + AnimGraphPlugin* m_plugin; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AttributesWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AttributesWindow.cpp index 3eb9447eb9..f3d629f300 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AttributesWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AttributesWindow.cpp @@ -41,17 +41,17 @@ namespace EMStudio AttributesWindow::AttributesWindow(AnimGraphPlugin* plugin, QWidget* parent) : QWidget(parent) { - mPlugin = plugin; - mPasteConditionsWindow = nullptr; - mScrollArea = new QScrollArea(); + m_plugin = plugin; + m_pasteConditionsWindow = nullptr; + m_scrollArea = new QScrollArea(); QVBoxLayout* mainLayout = new QVBoxLayout(); mainLayout->setMargin(0); mainLayout->setSpacing(1); setLayout(mainLayout); - mainLayout->addWidget(mScrollArea); - mScrollArea->setWidgetResizable(true); + mainLayout->addWidget(m_scrollArea); + m_scrollArea->setWidgetResizable(true); // The main reflected widget will contain the non-custom attribute version of the // attribute widget. The intention is to reuse the Reflected Property Editor and @@ -111,7 +111,7 @@ namespace EMStudio m_conditionsLayout->setSizeConstraint(QLayout::SetMinAndMaxSize); conditionsVerticalLayout->addLayout(m_conditionsLayout); - m_addConditionButton = new AddConditionButton(mPlugin, m_conditionsWidget); + m_addConditionButton = new AddConditionButton(m_plugin, m_conditionsWidget); m_addConditionButton->setObjectName("EMFX.AttributesWindowWidget.NodeTransition.AddConditionsWidget"); connect(m_addConditionButton, &AddConditionButton::ObjectTypeChosen, this, [=](AZ::TypeId conditionType) { @@ -137,7 +137,7 @@ namespace EMStudio m_actionsLayout->setSizeConstraint(QLayout::SetMinAndMaxSize); actionVerticalLayout->addLayout(m_actionsLayout); - AddActionButton* addActionButton = new AddActionButton(mPlugin, m_actionsWidget); + AddActionButton* addActionButton = new AddActionButton(m_plugin, m_actionsWidget); connect(addActionButton, &AddActionButton::ObjectTypeChosen, this, [=](AZ::TypeId actionType) { const AnimGraphModel::ModelItemType itemType = m_displayingModelIndex.data(AnimGraphModel::ROLE_MODEL_ITEM_TYPE).value(); @@ -171,9 +171,9 @@ namespace EMStudio if (m_mainReflectedWidget) { - if (mScrollArea->widget() == m_mainReflectedWidget) + if (m_scrollArea->widget() == m_mainReflectedWidget) { - mScrollArea->takeWidget(); + m_scrollArea->takeWidget(); } delete m_mainReflectedWidget; } @@ -216,15 +216,15 @@ namespace EMStudio EMotionFX::AnimGraphObject* object = modelIndex.data(AnimGraphModel::ROLE_ANIM_GRAPH_OBJECT_PTR).value(); - QWidget* attributeWidget = mPlugin->GetGraphNodeFactory()->CreateAttributeWidget(azrtti_typeid(object)); + QWidget* attributeWidget = m_plugin->GetGraphNodeFactory()->CreateAttributeWidget(azrtti_typeid(object)); if (attributeWidget) { // In the case we have a custom attribute widget, we cannot reuse the widget, so we just replace it - if (mScrollArea->widget() == m_mainReflectedWidget) + if (m_scrollArea->widget() == m_mainReflectedWidget) { - mScrollArea->takeWidget(); + m_scrollArea->takeWidget(); } - mScrollArea->setWidget(attributeWidget); + m_scrollArea->setWidget(attributeWidget); } else { @@ -235,7 +235,7 @@ namespace EMStudio } else { - animGraph = mPlugin->GetActiveAnimGraph(); + animGraph = m_plugin->GetActiveAnimGraph(); } m_animGraphEditor->SetAnimGraph(animGraph); @@ -270,9 +270,9 @@ namespace EMStudio m_objectCard->setVisible(object); - if (mScrollArea->widget() != m_mainReflectedWidget) + if (m_scrollArea->widget() != m_mainReflectedWidget) { - mScrollArea->setWidget(m_mainReflectedWidget); + m_scrollArea->setWidget(m_mainReflectedWidget); } } @@ -472,7 +472,7 @@ namespace EMStudio void AttributesWindow::AddTransitionCopyPasteMenuEntries(QMenu* menu) { - const NodeGraph* activeGraph = mPlugin->GetGraphWidget()->GetActiveGraph(); + const NodeGraph* activeGraph = m_plugin->GetGraphWidget()->GetActiveGraph(); if (!activeGraph) { return; @@ -533,7 +533,7 @@ namespace EMStudio AZ_UNUSED(selected); AZ_UNUSED(deselected); - const QModelIndexList modelIndexes = mPlugin->GetAnimGraphModel().GetSelectionModel().selectedRows(); + const QModelIndexList modelIndexes = m_plugin->GetAnimGraphModel().GetSelectionModel().selectedRows(); if (!modelIndexes.empty()) { Init(modelIndexes.front()); @@ -729,9 +729,9 @@ namespace EMStudio if (contents.IsSuccess()) { CopyPasteConditionObject copyPasteObject; - copyPasteObject.mContents = contents.GetValue(); - copyPasteObject.mConditionType = azrtti_typeid(condition); - condition->GetSummary(©PasteObject.mSummary); + copyPasteObject.m_contents = contents.GetValue(); + copyPasteObject.m_conditionType = azrtti_typeid(condition); + condition->GetSummary(©PasteObject.m_summary); m_copyPasteClipboard.m_conditions.push_back(copyPasteObject); } } @@ -776,9 +776,9 @@ namespace EMStudio CommandSystem::CommandAddTransitionCondition* addConditionCommand = aznew CommandSystem::CommandAddTransitionCondition( transition->GetAnimGraph()->GetID(), transition->GetId(), - copyPasteObject.mConditionType, + copyPasteObject.m_conditionType, /*insertAt=*/AZStd::nullopt, - copyPasteObject.mContents); + copyPasteObject.m_contents); commandGroup.AddCommand(addConditionCommand); } } @@ -804,14 +804,14 @@ namespace EMStudio return; } - delete mPasteConditionsWindow; - mPasteConditionsWindow = nullptr; + delete m_pasteConditionsWindow; + m_pasteConditionsWindow = nullptr; EMotionFX::AnimGraphStateTransition* transition = m_displayingModelIndex.data(AnimGraphModel::ROLE_TRANSITION_POINTER).value(); // Open the select conditions window and return if the user canceled it. - mPasteConditionsWindow = new PasteConditionsWindow(this); - if (mPasteConditionsWindow->exec() == QDialog::Rejected) + m_pasteConditionsWindow = new PasteConditionsWindow(this); + if (m_pasteConditionsWindow->exec() == QDialog::Rejected) { return; } @@ -824,7 +824,7 @@ namespace EMStudio for (size_t i = 0; i < numConditions; ++i) { // check if the condition was selected in the window, if not skip it - if (!mPasteConditionsWindow->GetIsConditionSelected(i)) + if (!m_pasteConditionsWindow->GetIsConditionSelected(i)) { continue; } @@ -832,9 +832,9 @@ namespace EMStudio CommandSystem::CommandAddTransitionCondition* addConditionCommand = aznew CommandSystem::CommandAddTransitionCondition( transition->GetAnimGraph()->GetID(), transition->GetId(), - m_copyPasteClipboard.m_conditions[i].mConditionType, + m_copyPasteClipboard.m_conditions[i].m_conditionType, /*insertAt=*/AZStd::nullopt, - m_copyPasteClipboard.m_conditions[i].mContents); + m_copyPasteClipboard.m_conditions[i].m_contents); commandGroup.AddCommand(addConditionCommand); numPastedConditions++; @@ -911,28 +911,28 @@ namespace EMStudio layout->addWidget(new QLabel("Please select the conditions you want to paste:")); - mCheckboxes.clear(); + m_checkboxes.clear(); const AttributesWindow::CopyPasteClipboard& copyPasteClipboard = attributeWindow->GetCopyPasteConditionClipboard(); for (const AttributesWindow::CopyPasteConditionObject& copyPasteObject : copyPasteClipboard.m_conditions) { - QCheckBox* checkbox = new QCheckBox(copyPasteObject.mSummary.c_str()); - mCheckboxes.push_back(checkbox); + QCheckBox* checkbox = new QCheckBox(copyPasteObject.m_summary.c_str()); + m_checkboxes.push_back(checkbox); checkbox->setCheckState(Qt::Checked); layout->addWidget(checkbox); } // create the ok and cancel buttons QHBoxLayout* buttonLayout = new QHBoxLayout(); - mOKButton = new QPushButton("OK"); - mCancelButton = new QPushButton("Cancel"); - buttonLayout->addWidget(mOKButton); - buttonLayout->addWidget(mCancelButton); + m_okButton = new QPushButton("OK"); + m_cancelButton = new QPushButton("Cancel"); + buttonLayout->addWidget(m_okButton); + buttonLayout->addWidget(m_cancelButton); layout->addLayout(buttonLayout); setLayout(layout); - connect(mOKButton, &QPushButton::clicked, this, &PasteConditionsWindow::accept); - connect(mCancelButton, &QPushButton::clicked, this, &PasteConditionsWindow::reject); + connect(m_okButton, &QPushButton::clicked, this, &PasteConditionsWindow::accept); + connect(m_cancelButton, &QPushButton::clicked, this, &PasteConditionsWindow::reject); } @@ -945,7 +945,7 @@ namespace EMStudio // check if the condition is selected bool PasteConditionsWindow::GetIsConditionSelected(size_t index) const { - return mCheckboxes[index]->checkState() == Qt::Checked; + return m_checkboxes[index]->checkState() == Qt::Checked; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AttributesWindow.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AttributesWindow.h index 5e278760a6..38bceb4426 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AttributesWindow.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AttributesWindow.h @@ -82,9 +82,9 @@ namespace EMStudio virtual ~PasteConditionsWindow(); bool GetIsConditionSelected(size_t index) const; private: - QPushButton* mOKButton; - QPushButton* mCancelButton; - AZStd::vector mCheckboxes; + QPushButton* m_okButton; + QPushButton* m_cancelButton; + AZStd::vector m_checkboxes; }; @@ -102,9 +102,9 @@ namespace EMStudio // copy & paste struct CopyPasteConditionObject { - AZStd::string mContents; - AZStd::string mSummary; - AZ::TypeId mConditionType; + AZStd::string m_contents; + AZStd::string m_summary; + AZ::TypeId m_conditionType; }; struct CopyPasteClipboard @@ -156,8 +156,8 @@ namespace EMStudio void PasteTransition(bool pasteTransitionProperties, bool pasteConditions); - AnimGraphPlugin* mPlugin; - QScrollArea* mScrollArea; + AnimGraphPlugin* m_plugin; + QScrollArea* m_scrollArea; QPersistentModelIndex m_displayingModelIndex; QWidget* m_mainReflectedWidget; @@ -187,7 +187,7 @@ namespace EMStudio QLayout* m_actionsLayout; AZStd::vector m_actionsCachedWidgets; - PasteConditionsWindow* mPasteConditionsWindow; + PasteConditionsWindow* m_pasteConditionsWindow; CopyPasteClipboard m_copyPasteClipboard; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendGraphViewWidget.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendGraphViewWidget.cpp index 037d75a9b9..59a7e33f04 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendGraphViewWidget.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendGraphViewWidget.cpp @@ -369,9 +369,9 @@ namespace EMStudio toolBar->addAction(m_actions[NAVIGATION_FORWARD]); - mNavigationLink = new NavigationLinkWidget(m_parentPlugin, this); - mNavigationLink->setMinimumHeight(28); - toolBar->addWidget(mNavigationLink); + m_navigationLink = new NavigationLinkWidget(m_parentPlugin, this); + m_navigationLink->setMinimumHeight(28); + toolBar->addWidget(m_navigationLink); toolBar->addAction(m_actions[NAVIGATION_NAVPANETOGGLE]); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendGraphViewWidget.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendGraphViewWidget.h index d1ebfb67d4..f795bef347 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendGraphViewWidget.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendGraphViewWidget.h @@ -133,7 +133,7 @@ namespace EMStudio QHBoxLayout* m_toolbarLayout = nullptr; AZStd::array m_actions{}; AnimGraphPlugin* m_parentPlugin = nullptr; - NavigationLinkWidget* mNavigationLink = nullptr; + NavigationLinkWidget* m_navigationLink = nullptr; QStackedWidget m_viewportStack; QSplitter* m_viewportSplitter = nullptr; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendGraphWidget.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendGraphWidget.cpp index 5d57763ea6..293dc51864 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendGraphWidget.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendGraphWidget.cpp @@ -51,10 +51,10 @@ namespace EMStudio // constructor BlendGraphWidget::BlendGraphWidget(AnimGraphPlugin* plugin, QWidget* parent) : NodeGraphWidget(plugin, nullptr, parent) - , mContextMenuEventMousePos(0, 0) - , mDoubleClickHappened(false) + , m_contextMenuEventMousePos(0, 0) + , m_doubleClickHappened(false) { - mMoveGroup.SetGroupName("Move anim graph nodes"); + m_moveGroup.SetGroupName("Move anim graph nodes"); setAutoFillBackground(false); setAttribute(Qt::WA_OpaquePaintEvent); @@ -78,9 +78,9 @@ namespace EMStudio return; } - if (!mActiveGraph || - !mPlugin->GetActionFilter().m_createNodes || - mActiveGraph->IsInReferencedGraph()) + if (!m_activeGraph || + !m_plugin->GetActionFilter().m_createNodes || + m_activeGraph->IsInReferencedGraph()) { event->ignore(); return; @@ -440,7 +440,7 @@ namespace EMStudio QAction* action = qobject_cast(sender()); // calculate the position - const QPoint offset = SnapLocalToGrid(LocalToGlobal(mContextMenuEventMousePos)); + const QPoint offset = SnapLocalToGrid(LocalToGlobal(m_contextMenuEventMousePos)); // build the name prefix and create the node const AZStd::string typeString = FromQtString(action->whatsThis()); @@ -523,7 +523,7 @@ namespace EMStudio void BlendGraphWidget::OnContextMenuEvent(QPoint mousePos, QPoint globalMousePos, const AnimGraphActionFilter& actionFilter) { - if (!mAllowContextMenu) + if (!m_allowContextMenu) { return; } @@ -542,7 +542,7 @@ namespace EMStudio return; } - mContextMenuEventMousePos = mousePos; + m_contextMenuEventMousePos = mousePos; const AZStd::vector selectedAnimGraphNodes = nodeGraph->GetSelectedAnimGraphNodes(); const AZStd::vector selectedConnections = nodeGraph->GetSelectedNodeConnections(); @@ -597,7 +597,7 @@ namespace EMStudio EMotionFX::AnimGraphStateTransition* transition = FindTransitionForConnection(selectedConnections[0]); if (transition) { - mPlugin->GetAttributesWindow()->AddTransitionCopyPasteMenuEntries(&menu); + m_plugin->GetAttributesWindow()->AddTransitionCopyPasteMenuEntries(&menu); } } } @@ -608,7 +608,7 @@ namespace EMStudio } if (actionFilter.m_delete && - !mActiveGraph->IsInReferencedGraph()) + !m_activeGraph->IsInReferencedGraph()) { QAction* removeConnectionAction = menu.addAction(removeConnectionActionName); connect(removeConnectionAction, &QAction::triggered, this, static_cast(&BlendGraphWidget::DeleteSelectedItems)); @@ -618,22 +618,22 @@ namespace EMStudio } else { - OnContextMenuEvent(this, mousePos, globalMousePos, mPlugin, selectedAnimGraphNodes, true, false, actionFilter); + OnContextMenuEvent(this, mousePos, globalMousePos, m_plugin, selectedAnimGraphNodes, true, false, actionFilter); } } void BlendGraphWidget::mouseDoubleClickEvent(QMouseEvent* event) { - if (mActiveGraph == nullptr) + if (m_activeGraph == nullptr) { return; } - mDoubleClickHappened = true; + m_doubleClickHappened = true; NodeGraphWidget::mouseDoubleClickEvent(event); - GraphNode* node = mActiveGraph->FindNode(event->pos()); + GraphNode* node = m_activeGraph->FindNode(event->pos()); if (node) { const QModelIndex nodeModelIndex = node->GetModelIndex(); @@ -642,9 +642,9 @@ namespace EMStudio { if (animGraphNode->GetHasVisualGraph()) { - if (!node->GetIsInsideArrowRect(mMousePos)) + if (!node->GetIsInsideArrowRect(m_mousePos)) { - mPlugin->GetAnimGraphModel().Focus(nodeModelIndex); + m_plugin->GetAnimGraphModel().Focus(nodeModelIndex); } } } @@ -656,7 +656,7 @@ namespace EMStudio void BlendGraphWidget::mousePressEvent(QMouseEvent* event) { - mDoubleClickHappened = false; + m_doubleClickHappened = false; NodeGraphWidget::mousePressEvent(event); } @@ -666,25 +666,25 @@ namespace EMStudio { //MCore::LogError("mouse release"); - if (mDoubleClickHappened == false) + if (m_doubleClickHappened == false) { if (event->button() == Qt::RightButton) { - OnContextMenuEvent(event->pos(), event->globalPos(), mPlugin->GetActionFilter()); + OnContextMenuEvent(event->pos(), event->globalPos(), m_plugin->GetActionFilter()); //setCursor( Qt::ArrowCursor ); } } NodeGraphWidget::mouseReleaseEvent(event); //setCursor( Qt::ArrowCursor ); - mDoubleClickHappened = false; + m_doubleClickHappened = false; } // start moving void BlendGraphWidget::OnMoveStart() { - mMoveGroup.RemoveAllCommands(); + m_moveGroup.RemoveAllCommands(); } @@ -701,7 +701,7 @@ namespace EMStudio y); // add it to the group - mMoveGroup.AddCommandString(moveString); + m_moveGroup.AddCommandString(moveString); } @@ -711,7 +711,7 @@ namespace EMStudio AZStd::string resultString; // execute the command - if (GetCommandManager()->ExecuteCommandGroup(mMoveGroup, resultString) == false) + if (GetCommandManager()->ExecuteCommandGroup(m_moveGroup, resultString) == false) { if (resultString.size() > 0) { @@ -813,9 +813,9 @@ namespace EMStudio bool BlendGraphWidget::CheckIfIsCreateConnectionValid(AZ::u16 portNr, GraphNode* portNode, NodePort* port, bool isInputPort) { MCORE_UNUSED(port); - MCORE_ASSERT(mActiveGraph); + MCORE_ASSERT(m_activeGraph); - GraphNode* sourceNode = mActiveGraph->GetCreateConnectionNode(); + GraphNode* sourceNode = m_activeGraph->GetCreateConnectionNode(); GraphNode* targetNode = portNode; // don't allow connection to itself @@ -828,7 +828,7 @@ namespace EMStudio if (sourceNode->GetType() != StateGraphNode::TYPE_ID || targetNode->GetType() != StateGraphNode::TYPE_ID) { // dont allow to connect an input port to another input port or output port to another output port - if (isInputPort == mActiveGraph->GetCreateConnectionIsInputPort()) + if (isInputPort == m_activeGraph->GetCreateConnectionIsInputPort()) { return false; } @@ -853,7 +853,7 @@ namespace EMStudio { sourceBlendNode = static_cast(sourceNode); targetBlendNode = static_cast(targetNode); - sourcePortNr = mActiveGraph->GetCreateConnectionPortNr(); + sourcePortNr = m_activeGraph->GetCreateConnectionPortNr(); targetPortNr = portNr; } else @@ -861,7 +861,7 @@ namespace EMStudio sourceBlendNode = static_cast(targetNode); targetBlendNode = static_cast(sourceNode); sourcePortNr = portNr; - targetPortNr = mActiveGraph->GetCreateConnectionPortNr(); + targetPortNr = m_activeGraph->GetCreateConnectionPortNr(); } EMotionFX::AnimGraphNode::Port& sourcePort = sourceBlendNode->GetEMFXNode()->GetOutputPort(sourcePortNr); @@ -936,7 +936,7 @@ namespace EMStudio void BlendGraphWidget::OnCreateConnection(AZ::u16 sourcePortNr, GraphNode* sourceNode, bool sourceIsInputPort, AZ::u16 targetPortNr, GraphNode* targetNode, bool targetIsInputPort, const QPoint& startOffset, const QPoint& endOffset) { MCORE_UNUSED(targetIsInputPort); - MCORE_ASSERT(mActiveGraph); + MCORE_ASSERT(m_activeGraph); GraphNode* realSourceNode; GraphNode* realTargetNode; @@ -964,7 +964,7 @@ namespace EMStudio AZStd::string command; // Check if there already is a connection plugged into the port where we want to put our new connection in. - NodeConnection* existingConnection = mActiveGraph->FindInputConnection(realTargetNode, realInputPortNr); + NodeConnection* existingConnection = m_activeGraph->FindInputConnection(realTargetNode, realInputPortNr); // Special case for state nodes. AZ::TypeId transitionType = AZ::TypeId::CreateNull(); @@ -1039,12 +1039,12 @@ namespace EMStudio // curved connection when creating a new one? bool BlendGraphWidget::CreateConnectionMustBeCurved() { - if (mActiveGraph == nullptr) + if (m_activeGraph == nullptr) { return true; } - if (mActiveGraph->GetCreateConnectionNode()->GetType() == StateGraphNode::TYPE_ID) + if (m_activeGraph->GetCreateConnectionNode()->GetType() == StateGraphNode::TYPE_ID) { return false; } @@ -1056,12 +1056,12 @@ namespace EMStudio // show helper connection suggestion lines when creating a new connection? bool BlendGraphWidget::CreateConnectionShowsHelpers() { - if (mActiveGraph == nullptr) + if (m_activeGraph == nullptr) { return true; } - if (mActiveGraph->GetCreateConnectionNode()->GetType() == StateGraphNode::TYPE_ID) + if (m_activeGraph->GetCreateConnectionNode()->GetType() == StateGraphNode::TYPE_ID) { return false; } @@ -1181,7 +1181,7 @@ namespace EMStudio QAction* action = qobject_cast(sender()); // find the selected node - const QItemSelection selection = mPlugin->GetAnimGraphModel().GetSelectionModel().selection(); + const QItemSelection selection = m_plugin->GetAnimGraphModel().GetSelectionModel().selection(); const QModelIndexList selectionList = selection.indexes(); if (selectionList.empty()) { @@ -1266,19 +1266,19 @@ namespace EMStudio bool BlendGraphWidget::PreparePainting() { // skip rendering in case rendering is disabled - if (mPlugin->GetDisableRendering()) + if (m_plugin->GetDisableRendering()) { return false; } - if (mActiveGraph) + if (m_activeGraph) { // enable or disable graph animation - mActiveGraph->SetUseAnimation(mPlugin->GetAnimGraphOptions().GetGraphAnimation()); + m_activeGraph->SetUseAnimation(m_plugin->GetAnimGraphOptions().GetGraphAnimation()); } // pass down the show fps options flag - NodeGraphWidget::SetShowFPS(mPlugin->GetAnimGraphOptions().GetShowFPS()); + NodeGraphWidget::SetShowFPS(m_plugin->GetAnimGraphOptions().GetShowFPS()); return true; } @@ -1310,7 +1310,7 @@ namespace EMStudio void BlendGraphWidget::OnSetupVisualizeOptions(GraphNode* node) { BlendTreeVisualNode* blendNode = static_cast(node); - mPlugin->GetActionManager().ShowNodeColorPicker(blendNode->GetEMFXNode()); + m_plugin->GetActionManager().ShowNodeColorPicker(blendNode->GetEMFXNode()); } @@ -1326,7 +1326,7 @@ namespace EMStudio boldFont.setBold(true); QFontMetrics boldFontMetrics(boldFont); - if (mActiveGraph) + if (m_activeGraph) { AZStd::string toolTipString; @@ -1335,7 +1335,7 @@ namespace EMStudio QPoint tooltipPos = helpEvent->globalPos(); // find the connection at the mouse position - NodeConnection* connection = mActiveGraph->FindConnection(globalPos); + NodeConnection* connection = m_activeGraph->FindConnection(globalPos); if (connection) { bool conditionFound = false; @@ -1455,7 +1455,7 @@ namespace EMStudio } } - GraphNode* node = mActiveGraph->FindNode(localPos); + GraphNode* node = m_activeGraph->FindNode(localPos); EMotionFX::AnimGraphNode* animGraphNode = nullptr; if (node) @@ -1542,15 +1542,15 @@ namespace EMStudio const AZ::s32 newEndOffsetX = transition->GetVisualEndOffsetX(); const AZ::s32 newEndOffsetY = transition->GetVisualEndOffsetY(); - mActiveGraph->StopReplaceTransitionHead(); - mActiveGraph->StopReplaceTransitionTail(); + m_activeGraph->StopReplaceTransitionHead(); + m_activeGraph->StopReplaceTransitionTail(); // Reset the visual transition before calling the actual command so that undo captures the right previous values. stateConnection->SetSourceNode(oldSourceNode); stateConnection->SetTargetNode(oldTargetNode); transition->SetVisualOffsets(oldStartOffset.x(), oldStartOffset.y(), oldEndOffset.x(), oldEndOffset.y()); - if (mActiveGraph->GetReplaceTransitionValid()) + if (m_activeGraph->GetReplaceTransitionValid()) { CommandSystem::AdjustTransition(transition, /*isDisabled=*/AZStd::nullopt, @@ -1706,8 +1706,8 @@ namespace EMStudio if (newFocusIndex != newFocusParent) { // We are focusing on a node inside a blendtree/statemachine/referencenode - GraphNode* graphNode = mActiveGraph->FindGraphNode(newFocusIndex); - mActiveGraph->ZoomOnRect(graphNode->GetRect(), geometry().width(), geometry().height(), true); + GraphNode* graphNode = m_activeGraph->FindGraphNode(newFocusIndex); + m_activeGraph->ZoomOnRect(graphNode->GetRect(), geometry().width(), geometry().height(), true); } } else diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendGraphWidget.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendGraphWidget.h index fa0801cdc1..f213b0f2e6 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendGraphWidget.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendGraphWidget.h @@ -126,8 +126,8 @@ namespace EMStudio using NodeGraphByModelIndex = AZStd::unordered_map, QPersistentModelIndexHash>; NodeGraphByModelIndex m_nodeGraphByModelIndex; - QPoint mContextMenuEventMousePos; - bool mDoubleClickHappened; - MCore::CommandGroup mMoveGroup; + QPoint m_contextMenuEventMousePos; + bool m_doubleClickHappened; + MCore::CommandGroup m_moveGroup; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendNodeSelectionWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendNodeSelectionWindow.cpp index 81812145e7..3b130f5bd7 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendNodeSelectionWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendNodeSelectionWindow.cpp @@ -22,27 +22,27 @@ namespace EMStudio QVBoxLayout* layout = new QVBoxLayout(); - mHierarchyWidget = new AnimGraphHierarchyWidget(this); + m_hierarchyWidget = new AnimGraphHierarchyWidget(this); // create the ok and cancel buttons QHBoxLayout* buttonLayout = new QHBoxLayout(); - mOKButton = new QPushButton("OK"); - mCancelButton = new QPushButton("Cancel"); - buttonLayout->addWidget(mOKButton); - buttonLayout->addWidget(mCancelButton); + m_okButton = new QPushButton("OK"); + m_cancelButton = new QPushButton("Cancel"); + buttonLayout->addWidget(m_okButton); + buttonLayout->addWidget(m_cancelButton); - layout->addWidget(mHierarchyWidget); + layout->addWidget(m_hierarchyWidget); layout->addLayout(buttonLayout); setLayout(layout); setMinimumSize(QSize(400, 400)); - mOKButton->setEnabled(false); + m_okButton->setEnabled(false); - connect(mOKButton, &QPushButton::clicked, this, &BlendNodeSelectionWindow::accept); - connect(mCancelButton, &QPushButton::clicked, this, &BlendNodeSelectionWindow::reject); - connect(mHierarchyWidget, &AnimGraphHierarchyWidget::OnSelectionDone, this, &BlendNodeSelectionWindow::OnNodeSelected); - connect(mHierarchyWidget, &AnimGraphHierarchyWidget::OnSelectionChanged, this, &BlendNodeSelectionWindow::OnSelectionChanged); + connect(m_okButton, &QPushButton::clicked, this, &BlendNodeSelectionWindow::accept); + connect(m_cancelButton, &QPushButton::clicked, this, &BlendNodeSelectionWindow::reject); + connect(m_hierarchyWidget, &AnimGraphHierarchyWidget::OnSelectionDone, this, &BlendNodeSelectionWindow::OnNodeSelected); + connect(m_hierarchyWidget, &AnimGraphHierarchyWidget::OnSelectionChanged, this, &BlendNodeSelectionWindow::OnSelectionChanged); } @@ -54,7 +54,7 @@ namespace EMStudio void BlendNodeSelectionWindow::OnNodeSelected() { - if (mUseSingleSelection) + if (m_useSingleSelection) { accept(); } @@ -66,7 +66,7 @@ namespace EMStudio AZ_UNUSED(selected); AZ_UNUSED(deselected); - mOKButton->setEnabled(mHierarchyWidget->HasSelectedItems()); + m_okButton->setEnabled(m_hierarchyWidget->HasSelectedItems()); } } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendNodeSelectionWindow.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendNodeSelectionWindow.h index 4ec48bbffb..9d49008d40 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendNodeSelectionWindow.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendNodeSelectionWindow.h @@ -27,9 +27,9 @@ namespace EMStudio * 2. Use the itemSelectionChanged() signal of the GetNodeHierarchyWidget()->GetTreeWidget() to detect when the user adjusts the selection in the node hierarchy widget. * 3. Use the OnSelectionDone() in the GetNodeHierarchyWidget() to detect when the user finished selecting and pressed the OK button. * Example: - * connect( mNodeSelectionWindow, SIGNAL(rejected()), this, SLOT(UserWantsToCancel_1()) ); - * connect( mNodeSelectionWindow->GetNodeHierarchyWidget()->GetTreeWidget(), SIGNAL(itemSelectionChanged()), this, SLOT(SelectionChanged_2()) ); - * connect( mNodeSelectionWindow->GetNodeHierarchyWidget(), SIGNAL(OnSelectionDone(AZStd::vector)), this, SLOT(FinishedSelectionAndPressedOK_3(AZStd::vector)) ); + * connect( m_nodeSelectionWindow, SIGNAL(rejected()), this, SLOT(UserWantsToCancel_1()) ); + * connect( m_nodeSelectionWindow->GetNodeHierarchyWidget()->GetTreeWidget(), SIGNAL(itemSelectionChanged()), this, SLOT(SelectionChanged_2()) ); + * connect( m_nodeSelectionWindow->GetNodeHierarchyWidget(), SIGNAL(OnSelectionDone(AZStd::vector)), this, SLOT(FinishedSelectionAndPressedOK_3(AZStd::vector)) ); */ class BlendNodeSelectionWindow : public QDialog @@ -41,16 +41,16 @@ namespace EMStudio BlendNodeSelectionWindow(QWidget* parent = nullptr); virtual ~BlendNodeSelectionWindow(); - AnimGraphHierarchyWidget& GetAnimGraphHierarchyWidget() { return *mHierarchyWidget; } + AnimGraphHierarchyWidget& GetAnimGraphHierarchyWidget() { return *m_hierarchyWidget; } public slots: void OnNodeSelected(); void OnSelectionChanged(const QItemSelection& selected, const QItemSelection& deselected); private: - AnimGraphHierarchyWidget* mHierarchyWidget; - QPushButton* mOKButton; - QPushButton* mCancelButton; - bool mUseSingleSelection; + AnimGraphHierarchyWidget* m_hierarchyWidget; + QPushButton* m_okButton; + QPushButton* m_cancelButton; + bool m_useSingleSelection; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendTreeVisualNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendTreeVisualNode.cpp index 0cf44af794..823d9a4a88 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendTreeVisualNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendTreeVisualNode.cpp @@ -38,26 +38,26 @@ namespace EMStudio RemoveAllConnections(); // add all input ports - const AZStd::vector& inPorts = mEMFXNode->GetInputPorts(); + const AZStd::vector& inPorts = m_emfxNode->GetInputPorts(); const AZ::u16 numInputs = aznumeric_caster(inPorts.size()); - mInputPorts.reserve(numInputs); + m_inputPorts.reserve(numInputs); for (AZ::u16 i = 0; i < numInputs; ++i) { NodePort* port = AddInputPort(false); - port->SetNameID(inPorts[i].mNameID); + port->SetNameID(inPorts[i].m_nameId); port->SetColor(GetPortColor(inPorts[i])); } if (GetHasVisualOutputPorts()) { // add all output ports - const AZStd::vector& outPorts = mEMFXNode->GetOutputPorts(); + const AZStd::vector& outPorts = m_emfxNode->GetOutputPorts(); const AZ::u16 numOutputs = aznumeric_caster(outPorts.size()); - mOutputPorts.reserve(numOutputs); + m_outputPorts.reserve(numOutputs); for (AZ::u16 i = 0; i < numOutputs; ++i) { NodePort* port = AddOutputPort(false); - port->SetNameID(outPorts[i].mNameID); + port->SetNameID(outPorts[i].m_nameId); port->SetColor(GetPortColor(outPorts[i])); } } @@ -71,12 +71,12 @@ namespace EMStudio { EMotionFX::BlendTreeConnection* connection = childIndex.data(AnimGraphModel::ROLE_CONNECTION_POINTER).value(); - GraphNode* source = mParentGraph->FindGraphNode(connection->GetSourceNode()); + GraphNode* source = m_parentGraph->FindGraphNode(connection->GetSourceNode()); GraphNode* target = this; const AZ::u16 sourcePort = connection->GetSourcePort(); const AZ::u16 targetPort = connection->GetTargetPort(); - NodeConnection* visualConnection = new NodeConnection(mParentGraph, childIndex, target, targetPort, source, sourcePort); + NodeConnection* visualConnection = new NodeConnection(m_parentGraph, childIndex, target, targetPort, source, sourcePort); target->AddConnection(visualConnection); } } @@ -90,7 +90,7 @@ namespace EMStudio // get the port color for a given EMotion FX port QColor BlendTreeVisualNode::GetPortColor(const EMotionFX::AnimGraphNode::Port& port) const { - switch (port.mCompatibleTypes[0]) + switch (port.m_compatibleTypes[0]) { case EMotionFX::AttributePose::TYPE_ID: return QColor(150, 150, 255); @@ -119,7 +119,7 @@ namespace EMStudio void BlendTreeVisualNode::Render(QPainter& painter, QPen* pen, bool renderShadow) { // only render if the given node is visible - if (mIsVisible == false) + if (m_isVisible == false) { return; } @@ -130,8 +130,8 @@ namespace EMStudio RenderShadow(painter); } - float opacityFactor = mOpacity; - if (mIsEnabled == false) + float opacityFactor = m_opacity; + if (m_isEnabled == false) { opacityFactor *= 0.35f; } @@ -155,7 +155,7 @@ namespace EMStudio { borderColor.setRgb(255, 128, 0); - if (mParentGraph->GetScale() > 0.75f) + if (m_parentGraph->GetScale() > 0.75f) { pen->setWidth(2); } @@ -166,12 +166,9 @@ namespace EMStudio { borderColor.setRgb(255, 0, 0); } - //else - //if (mIsProcessed) - //borderColor.setRgb(255,225,0); else { - borderColor = mBorderColor; + borderColor = m_borderColor; } } @@ -183,11 +180,11 @@ namespace EMStudio } else // not selected { - if (mIsEnabled) + if (m_isEnabled) { - if (mIsProcessed || colorAllNodes) + if (m_isProcessed || colorAllNodes) { - bgColor = mBaseColor; + bgColor = m_baseColor; } else { @@ -204,9 +201,9 @@ namespace EMStudio // blinking error if (hasError && !isSelected) { - if (mParentGraph->GetUseAnimation()) + if (m_parentGraph->GetUseAnimation()) { - borderColor = mParentGraph->GetErrorBlinkColor(); + borderColor = m_parentGraph->GetErrorBlinkColor(); } else { @@ -220,16 +217,13 @@ namespace EMStudio QColor headerBgColor; bgColor2 = bgColor.lighter(30);// make darker actually, 30% of the old color, same as bgColor * 0.3f; - //if (mIsProcessed == false/* && mIsUpdated*/ && hasError == false && mIsSelected == false) - //headerBgColor = mBaseColor.lighter(30); - //else headerBgColor = bgColor.lighter(20); // text color QColor textColor; if (!isSelected) { - if (mIsEnabled) + if (m_isEnabled) { textColor = Qt::white; } @@ -243,10 +237,10 @@ namespace EMStudio textColor = QColor(bgColor); } - if (mIsCollapsed == false) + if (m_isCollapsed == false) { // is highlighted/hovered (on-mouse-over effect) - if (mIsHighlighted) + if (m_isHighlighted) { bgColor = bgColor.lighter(120); bgColor2 = bgColor2.lighter(120); @@ -255,9 +249,9 @@ namespace EMStudio // draw the main rect painter.setPen(borderColor); - if (!mIsProcessed && mIsEnabled && !isSelected && !colorAllNodes) + if (!m_isProcessed && m_isEnabled && !isSelected && !colorAllNodes) { - if (mIsHighlighted == false) + if (m_isHighlighted == false) { painter.setBrush(QColor(40, 40, 40)); } @@ -268,21 +262,21 @@ namespace EMStudio } else { - QLinearGradient bgGradient(0, mRect.top(), 0, mRect.bottom()); + QLinearGradient bgGradient(0, m_rect.top(), 0, m_rect.bottom()); bgGradient.setColorAt(0.0f, bgColor); bgGradient.setColorAt(1.0f, bgColor2); painter.setBrush(bgGradient); } - painter.drawRoundedRect(mRect, BORDER_RADIUS, BORDER_RADIUS); + painter.drawRoundedRect(m_rect, BORDER_RADIUS, BORDER_RADIUS); // if the scale is so small that we can't see those small things anymore - QRect fullHeaderRect(mRect.left(), mRect.top(), mRect.width(), 30); - QRect headerRect(mRect.left(), mRect.top(), mRect.width(), 15); - QRect subHeaderRect(mRect.left(), mRect.top() + 13, mRect.width(), 15); + QRect fullHeaderRect(m_rect.left(), m_rect.top(), m_rect.width(), 30); + QRect headerRect(m_rect.left(), m_rect.top(), m_rect.width(), 15); + QRect subHeaderRect(m_rect.left(), m_rect.top() + 13, m_rect.width(), 15); // if the scale is so small that we can't see those small things anymore - if (mParentGraph->GetScale() < 0.3f) + if (m_parentGraph->GetScale() < 0.3f) { painter.setOpacity(1.0f); painter.setClipping(false); @@ -294,19 +288,19 @@ namespace EMStudio painter.setPen(borderColor); painter.setClipRect(fullHeaderRect, Qt::ReplaceClip); painter.setBrush(headerBgColor); - painter.drawRoundedRect(mRect, BORDER_RADIUS, BORDER_RADIUS); + painter.drawRoundedRect(m_rect, BORDER_RADIUS, BORDER_RADIUS); painter.setClipping(false); // if the scale is so small that we can't see those small things anymore - if (mParentGraph->GetScale() > 0.5f) + if (m_parentGraph->GetScale() > 0.5f) { // draw the input ports QColor portBrushColor, portPenColor; - const AZ::u16 numInputs = aznumeric_caster(mInputPorts.size()); + const AZ::u16 numInputs = aznumeric_caster(m_inputPorts.size()); for (AZ::u16 i = 0; i < numInputs; ++i) { // get the input port and the corresponding rect - NodePort* inputPort = &mInputPorts[i]; + NodePort* inputPort = &m_inputPorts[i]; const QRect& portRect = inputPort->GetRect(); // get and set the pen and brush colors @@ -321,11 +315,11 @@ namespace EMStudio if (GetHasVisualOutputPorts()) { // draw the output ports - const AZ::u16 numOutputs = aznumeric_caster(mOutputPorts.size()); + const AZ::u16 numOutputs = aznumeric_caster(m_outputPorts.size()); for (AZ::u16 i = 0; i < numOutputs; ++i) { // get the output port and the corresponding rect - NodePort* outputPort = &mOutputPorts[i]; + NodePort* outputPort = &m_outputPorts[i]; const QRect& portRect = outputPort->GetRect(); // get and set the pen and brush colors @@ -342,16 +336,16 @@ namespace EMStudio else // it is collapsed { // is highlighted/hovered (on-mouse-over effect) - if (mIsHighlighted) + if (m_isHighlighted) { bgColor = bgColor.lighter(160); headerBgColor = headerBgColor.lighter(160); } // if the scale is so small that we can't see those small things anymore - QRect fullHeaderRect(mRect.left(), mRect.top(), mRect.width(), 30); - QRect headerRect(mRect.left(), mRect.top(), mRect.width(), 15); - QRect subHeaderRect(mRect.left(), mRect.top() + 13, mRect.width(), 15); + QRect fullHeaderRect(m_rect.left(), m_rect.top(), m_rect.width(), 30); + QRect headerRect(m_rect.left(), m_rect.top(), m_rect.width(), 15); + QRect subHeaderRect(m_rect.left(), m_rect.top() + 13, m_rect.width(), 15); // draw the header painter.setPen(borderColor); @@ -359,7 +353,7 @@ namespace EMStudio painter.drawRoundedRect(fullHeaderRect, 7.0, 7.0); // if the scale is so small that we can't see those small things anymore - if (mParentGraph->GetScale() < 0.3f) + if (m_parentGraph->GetScale() < 0.3f) { painter.setOpacity(1.0f); return; @@ -370,7 +364,7 @@ namespace EMStudio painter.setClipping(false); } - if (mParentGraph->GetScale() > 0.3f) + if (m_parentGraph->GetScale() > 0.3f) { // draw the collapse triangle if (isSelected) @@ -384,37 +378,37 @@ namespace EMStudio painter.setBrush(QColor(175, 175, 175)); } - if (mIsCollapsed == false) + if (m_isCollapsed == false) { QPoint triangle[3]; - triangle[0].setX(mArrowRect.left()); - triangle[0].setY(mArrowRect.top()); - triangle[1].setX(mArrowRect.right()); - triangle[1].setY(mArrowRect.top()); - triangle[2].setX(mArrowRect.center().x()); - triangle[2].setY(mArrowRect.bottom()); + triangle[0].setX(m_arrowRect.left()); + triangle[0].setY(m_arrowRect.top()); + triangle[1].setX(m_arrowRect.right()); + triangle[1].setY(m_arrowRect.top()); + triangle[2].setX(m_arrowRect.center().x()); + triangle[2].setY(m_arrowRect.bottom()); painter.drawPolygon(triangle, 3, Qt::WindingFill); } else { QPoint triangle[3]; - triangle[0].setX(mArrowRect.left()); - triangle[0].setY(mArrowRect.top()); - triangle[1].setX(mArrowRect.right()); - triangle[1].setY(mArrowRect.center().y()); - triangle[2].setX(mArrowRect.left()); - triangle[2].setY(mArrowRect.bottom()); + triangle[0].setX(m_arrowRect.left()); + triangle[0].setY(m_arrowRect.top()); + triangle[1].setX(m_arrowRect.right()); + triangle[1].setY(m_arrowRect.center().y()); + triangle[2].setX(m_arrowRect.left()); + triangle[2].setY(m_arrowRect.bottom()); painter.drawPolygon(triangle, 3, Qt::WindingFill); } // draw the visualize area - if (mCanVisualize) + if (m_canVisualize) { RenderVisualizeRect(painter, bgColor, bgColor2); } // render the tracks etc - if (mIsCollapsed == false && mEMFXNode->GetHasOutputPose() && mIsProcessed) + if (m_isCollapsed == false && m_emfxNode->GetHasOutputPose() && m_isProcessed) { RenderTracks(painter, bgColor, bgColor2); } @@ -424,60 +418,57 @@ namespace EMStudio } // render the text overlay with the pre-baked node name and port names etc. - float textOpacity = MCore::Clamp(mParentGraph->GetScale() * mParentGraph->GetScale() * 1.5f, 0.0f, 1.0f); - //if (mIsProcessed == false && mIsEnabled) - //textOpacity *= 0.65f; + float textOpacity = MCore::Clamp(m_parentGraph->GetScale() * m_parentGraph->GetScale() * 1.5f, 0.0f, 1.0f); painter.setOpacity(textOpacity); // draw the title - //painter.drawPixmap( mRect, mTextPixmap ); painter.setBrush(Qt::NoBrush); painter.setPen(textColor); - painter.setFont(mHeaderFont); - painter.drawStaticText(mRect.left(), mRect.top(), mTitleText); + painter.setFont(m_headerFont); + painter.drawStaticText(m_rect.left(), m_rect.top(), m_titleText); // draw the subtitle - painter.setFont(mSubTitleFont); - painter.drawStaticText(mRect.left(), aznumeric_cast(mRect.top() + mTitleText.size().height() - 3), mSubTitleText); + painter.setFont(m_subTitleFont); + painter.drawStaticText(m_rect.left(), aznumeric_cast(m_rect.top() + m_titleText.size().height() - 3), m_subTitleText); // draw the info text - if (mIsCollapsed == false) + if (m_isCollapsed == false) { // draw info text QRect textRect; CalcInfoTextRect(textRect, false); - painter.setFont(mInfoTextFont); + painter.setFont(m_infoTextFont); painter.setPen(QColor(255, 128, 0)); - painter.drawStaticText(mRect.left(), textRect.top() + 4, mInfoText); + painter.drawStaticText(m_rect.left(), textRect.top() + 4, m_infoText); painter.setPen(textColor); - painter.setFont(mPortNameFont); + painter.setFont(m_portNameFont); // draw input port text - const AZ::u16 numInputs = aznumeric_caster(mInputPorts.size()); + const AZ::u16 numInputs = aznumeric_caster(m_inputPorts.size()); for (AZ::u16 i = 0; i < numInputs; ++i) { - NodePort* inputPort = &mInputPorts[i]; + NodePort* inputPort = &m_inputPorts[i]; const QRect& portRect = inputPort->GetRect(); if (inputPort->GetNameID() == MCORE_INVALIDINDEX32) { continue; } - painter.drawStaticText(mRect.left() + 8, portRect.top() - 3, mInputPortText[i]); + painter.drawStaticText(m_rect.left() + 8, portRect.top() - 3, m_inputPortText[i]); } // draw output port text - const AZ::u16 numOutputs = aznumeric_caster(mOutputPorts.size()); + const AZ::u16 numOutputs = aznumeric_caster(m_outputPorts.size()); for (AZ::u16 i = 0; i < numOutputs; ++i) { - NodePort* outputPort = &mOutputPorts[i]; + NodePort* outputPort = &m_outputPorts[i]; const QRect& portRect = outputPort->GetRect(); if (outputPort->GetNameID() == MCORE_INVALIDINDEX32) { continue; } - painter.drawStaticText(aznumeric_cast(mRect.right() - 10 - mOutputPortText[i].size().width()), portRect.top() - 3, mOutputPortText[i]); + painter.drawStaticText(aznumeric_cast(m_rect.right() - 10 - m_outputPortText[i].size().width()), portRect.top() - 3, m_outputPortText[i]); } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ContextMenu.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ContextMenu.cpp index da092f93f6..01a7cb1bd1 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ContextMenu.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ContextMenu.cpp @@ -36,7 +36,7 @@ namespace EMStudio const AZStd::vector& objectPrototypes = plugin->GetAnimGraphObjectFactory()->GetUiObjectPrototypes(); for (EMotionFX::AnimGraphObject* objectPrototype : objectPrototypes) { - if (mPlugin->CheckIfCanCreateObject(focusedGraphObject, objectPrototype, category)) + if (m_plugin->CheckIfCanCreateObject(focusedGraphObject, objectPrototype, category)) { isEmpty = false; break; @@ -54,7 +54,7 @@ namespace EMStudio for (const EMotionFX::AnimGraphObject* objectPrototype : objectPrototypes) { - if (mPlugin->CheckIfCanCreateObject(focusedGraphObject, objectPrototype, category)) + if (m_plugin->CheckIfCanCreateObject(focusedGraphObject, objectPrototype, category)) { const EMotionFX::AnimGraphNode* nodePrototype = static_cast(objectPrototype); QAction* action = menu->addAction(nodePrototype->GetPaletteName()); @@ -287,7 +287,7 @@ namespace EMStudio { menu->addSeparator(); QAction* action = menu->addAction("Adjust Visualization Color"); - connect(action, &QAction::triggered, [this, animGraphNode](bool) { mPlugin->GetActionManager().ShowNodeColorPicker(animGraphNode); }); + connect(action, &QAction::triggered, [this, animGraphNode](bool) { m_plugin->GetActionManager().ShowNodeColorPicker(animGraphNode); }); } } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GameController.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GameController.cpp index c1d0d25c9e..4c32cdb0cc 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GameController.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GameController.cpp @@ -20,17 +20,17 @@ BOOL CALLBACK GameController::EnumJoysticksCallback(const DIDEVICEINSTANCE* pdid GameController* manager = static_cast(pContext); // store the name - manager->mDeviceInfo.mName = pdidInstance->tszProductName; + manager->m_deviceInfo.m_name = pdidInstance->tszProductName; // Skip anything other than the perferred Joystick device as defined by the control panel. // Instead you could store all the enumerated Joysticks and let the user pick. - if (manager->mEnumContext.mPrefJoystickConfigValid && IsEqualGUID(pdidInstance->guidInstance, manager->mEnumContext.mPrefJoystickConfig->guidInstance) == false) + if (manager->m_enumContext.m_prefJoystickConfigValid && IsEqualGUID(pdidInstance->guidInstance, manager->m_enumContext.m_prefJoystickConfig->guidInstance) == false) { return DIENUM_CONTINUE; } // Obtain an interface to the enumerated Joystick. - HRESULT result = manager->mDirectInput->CreateDevice(pdidInstance->guidInstance, &manager->mJoystick, nullptr); + HRESULT result = manager->m_directInput->CreateDevice(pdidInstance->guidInstance, &manager->m_joystick, nullptr); // If it failed, then we can't use this Joystick. (Maybe the user unplugged // it while we were in the middle of enumerating it.) @@ -63,7 +63,7 @@ BOOL CALLBACK GameController::EnumObjectsCallback(const DIDEVICEOBJECTINSTANCE* diprg.lMax = +1000; // Set the range for the axis - if (FAILED(manager->mJoystick->SetProperty(DIPROP_RANGE, &diprg.diph))) + if (FAILED(manager->m_joystick->SetProperty(DIPROP_RANGE, &diprg.diph))) { return DIENUM_STOP; } @@ -71,103 +71,94 @@ BOOL CALLBACK GameController::EnumObjectsCallback(const DIDEVICEOBJECTINSTANCE* if (pdidoi->guidType == GUID_XAxis) { - manager->mDeviceElements[ ELEM_POS_X ].mName = pdidoi->tszName; - manager->mDeviceElements[ ELEM_POS_X ].mPresent = true; - manager->mDeviceElements[ ELEM_POS_X ].mValue = 0.0f; - //manager->mDeviceElements[ ELEM_POS_X ].mCalibrationValue = 0.0f; - manager->mDeviceElements[ ELEM_POS_X ].mType = ELEMTYPE_AXIS; - manager->mDeviceInfo.mNumAxes++; + manager->m_deviceElements[ ELEM_POS_X ].m_name = pdidoi->tszName; + manager->m_deviceElements[ ELEM_POS_X ].m_present = true; + manager->m_deviceElements[ ELEM_POS_X ].m_value = 0.0f; + manager->m_deviceElements[ ELEM_POS_X ].m_type = ELEMTYPE_AXIS; + manager->m_deviceInfo.m_numAxes++; } if (pdidoi->guidType == GUID_YAxis) { - manager->mDeviceElements[ ELEM_POS_Y ].mName = pdidoi->tszName; - manager->mDeviceElements[ ELEM_POS_Y ].mPresent = true; - manager->mDeviceElements[ ELEM_POS_Y ].mValue = 0.0f; - //manager->mDeviceElements[ ELEM_POS_Y ].mCalibrationValue = 0.0f; - manager->mDeviceElements[ ELEM_POS_Y ].mType = ELEMTYPE_AXIS; - manager->mDeviceInfo.mNumAxes++; + manager->m_deviceElements[ ELEM_POS_Y ].m_name = pdidoi->tszName; + manager->m_deviceElements[ ELEM_POS_Y ].m_present = true; + manager->m_deviceElements[ ELEM_POS_Y ].m_value = 0.0f; + manager->m_deviceElements[ ELEM_POS_Y ].m_type = ELEMTYPE_AXIS; + manager->m_deviceInfo.m_numAxes++; } if (pdidoi->guidType == GUID_ZAxis) { - manager->mDeviceElements[ ELEM_POS_Z ].mName = pdidoi->tszName; - manager->mDeviceElements[ ELEM_POS_Z ].mPresent = true; - manager->mDeviceElements[ ELEM_POS_Z ].mValue = 0.0f; - //manager->mDeviceElements[ ELEM_POS_Z ].mCalibrationValue = 0.0f; - manager->mDeviceElements[ ELEM_POS_Z ].mType = ELEMTYPE_AXIS; - manager->mDeviceInfo.mNumAxes++; + manager->m_deviceElements[ ELEM_POS_Z ].m_name = pdidoi->tszName; + manager->m_deviceElements[ ELEM_POS_Z ].m_present = true; + manager->m_deviceElements[ ELEM_POS_Z ].m_value = 0.0f; + manager->m_deviceElements[ ELEM_POS_Z ].m_type = ELEMTYPE_AXIS; + manager->m_deviceInfo.m_numAxes++; } if (pdidoi->guidType == GUID_RxAxis) { - manager->mDeviceElements[ ELEM_ROT_X ].mName = pdidoi->tszName; - manager->mDeviceElements[ ELEM_ROT_X ].mPresent = true; - manager->mDeviceElements[ ELEM_ROT_X ].mValue = 0.0f; - //manager->mDeviceElements[ ELEM_ROT_X ].mCalibrationValue = 0.0f; - manager->mDeviceElements[ ELEM_ROT_X ].mType = ELEMTYPE_AXIS; - manager->mDeviceInfo.mNumAxes++; + manager->m_deviceElements[ ELEM_ROT_X ].m_name = pdidoi->tszName; + manager->m_deviceElements[ ELEM_ROT_X ].m_present = true; + manager->m_deviceElements[ ELEM_ROT_X ].m_value = 0.0f; + manager->m_deviceElements[ ELEM_ROT_X ].m_type = ELEMTYPE_AXIS; + manager->m_deviceInfo.m_numAxes++; } if (pdidoi->guidType == GUID_RyAxis) { - manager->mDeviceElements[ ELEM_ROT_Y ].mName = pdidoi->tszName; - manager->mDeviceElements[ ELEM_ROT_Y ].mPresent = true; - manager->mDeviceElements[ ELEM_ROT_Y ].mValue = 0.0f; - //manager->mDeviceElements[ ELEM_ROT_Y ].mCalibrationValue = 0.0f; - manager->mDeviceElements[ ELEM_ROT_Y ].mType = ELEMTYPE_AXIS; - manager->mDeviceInfo.mNumAxes++; + manager->m_deviceElements[ ELEM_ROT_Y ].m_name = pdidoi->tszName; + manager->m_deviceElements[ ELEM_ROT_Y ].m_present = true; + manager->m_deviceElements[ ELEM_ROT_Y ].m_value = 0.0f; + manager->m_deviceElements[ ELEM_ROT_Y ].m_type = ELEMTYPE_AXIS; + manager->m_deviceInfo.m_numAxes++; } if (pdidoi->guidType == GUID_RzAxis) { - manager->mDeviceElements[ ELEM_ROT_Z ].mName = pdidoi->tszName; - manager->mDeviceElements[ ELEM_ROT_Z ].mPresent = true; - manager->mDeviceElements[ ELEM_ROT_Z ].mValue = 0.0f; - //manager->mDeviceElements[ ELEM_ROT_Z ].mCalibrationValue = 0.0f; - manager->mDeviceElements[ ELEM_ROT_Z ].mType = ELEMTYPE_AXIS; - manager->mDeviceInfo.mNumAxes++; + manager->m_deviceElements[ ELEM_ROT_Z ].m_name = pdidoi->tszName; + manager->m_deviceElements[ ELEM_ROT_Z ].m_present = true; + manager->m_deviceElements[ ELEM_ROT_Z ].m_value = 0.0f; + manager->m_deviceElements[ ELEM_ROT_Z ].m_type = ELEMTYPE_AXIS; + manager->m_deviceInfo.m_numAxes++; } // a slider if (pdidoi->guidType == GUID_Slider) { - if (manager->mDeviceInfo.mNumSliders == 0) + if (manager->m_deviceInfo.m_numSliders == 0) { - manager->mDeviceElements[ ELEM_SLIDER_1 ].mName = pdidoi->tszName; - manager->mDeviceElements[ ELEM_SLIDER_1 ].mPresent = true; - manager->mDeviceElements[ ELEM_SLIDER_1 ].mValue = 0.0f; - //manager->mDeviceElements[ ELEM_SLIDER_1 ].mCalibrationValue = 0.0f; - manager->mDeviceElements[ ELEM_SLIDER_1 ].mType = ELEMTYPE_SLIDER; + manager->m_deviceElements[ ELEM_SLIDER_1 ].m_name = pdidoi->tszName; + manager->m_deviceElements[ ELEM_SLIDER_1 ].m_present = true; + manager->m_deviceElements[ ELEM_SLIDER_1 ].m_value = 0.0f; + manager->m_deviceElements[ ELEM_SLIDER_1 ].m_type = ELEMTYPE_SLIDER; } else { - manager->mDeviceElements[ ELEM_SLIDER_2 ].mName = pdidoi->tszName; - manager->mDeviceElements[ ELEM_SLIDER_2 ].mPresent = true; - manager->mDeviceElements[ ELEM_SLIDER_2 ].mValue = 0.0f; - //manager->mDeviceElements[ ELEM_SLIDER_2 ].mCalibrationValue = 0.0f; - manager->mDeviceElements[ ELEM_SLIDER_2 ].mType = ELEMTYPE_SLIDER; + manager->m_deviceElements[ ELEM_SLIDER_2 ].m_name = pdidoi->tszName; + manager->m_deviceElements[ ELEM_SLIDER_2 ].m_present = true; + manager->m_deviceElements[ ELEM_SLIDER_2 ].m_value = 0.0f; + manager->m_deviceElements[ ELEM_SLIDER_2 ].m_type = ELEMTYPE_SLIDER; } - manager->mDeviceInfo.mNumSliders++; + manager->m_deviceInfo.m_numSliders++; } // a POV if (pdidoi->guidType == GUID_POV) { - const uint32 povIndex = manager->mDeviceInfo.mNumPOVs; - manager->mDeviceElements[ ELEM_POV_1 + povIndex ].mName = pdidoi->tszName; - manager->mDeviceElements[ ELEM_POV_1 + povIndex ].mPresent = true; - manager->mDeviceElements[ ELEM_POV_1 + povIndex ].mValue = 0.0f; - //manager->mDeviceElements[ ELEM_POV_1 + povIndex ].mCalibrationValue = 0.0f; - manager->mDeviceElements[ ELEM_POV_1 + povIndex ].mType = ELEMTYPE_POV; - manager->mDeviceInfo.mNumPOVs++; + const uint32 povIndex = manager->m_deviceInfo.m_numPoVs; + manager->m_deviceElements[ ELEM_POV_1 + povIndex ].m_name = pdidoi->tszName; + manager->m_deviceElements[ ELEM_POV_1 + povIndex ].m_present = true; + manager->m_deviceElements[ ELEM_POV_1 + povIndex ].m_value = 0.0f; + manager->m_deviceElements[ ELEM_POV_1 + povIndex ].m_type = ELEMTYPE_POV; + manager->m_deviceInfo.m_numPoVs++; } // a button if (pdidoi->guidType == GUID_Button) { - manager->mDeviceInfo.mNumButtons++; + manager->m_deviceInfo.m_numButtons++; } return DIENUM_CONTINUE; @@ -183,7 +174,7 @@ bool GameController::Init(HWND hWnd) // reinit if (FAILED(InitDirectInput(hWnd))) { - mValid = false; + m_valid = false; return false; } @@ -199,24 +190,24 @@ HRESULT GameController::InitDirectInput(HWND hWnd) HRESULT result; // reset the device info - mDeviceInfo.mName = ""; - mDeviceInfo.mNumAxes = 0; - mDeviceInfo.mNumButtons = 0; - mDeviceInfo.mNumPOVs = 0; - mDeviceInfo.mNumSliders = 0; + m_deviceInfo.m_name = ""; + m_deviceInfo.m_numAxes = 0; + m_deviceInfo.m_numButtons = 0; + m_deviceInfo.m_numPoVs = 0; + m_deviceInfo.m_numSliders = 0; uint32 i; for (i = 0; i < NUM_ELEMENTS; ++i) { - mDeviceElements[i].mPresent = false; - mDeviceElements[i].mValue = 0.0f; + m_deviceElements[i].m_present = false; + m_deviceElements[i].m_value = 0.0f; } // register with the DirectInput subsystem and get a pointer to a IDirectInput interface we can use - result = DirectInput8Create(GetModuleHandle(nullptr), DIRECTINPUT_VERSION, IID_IDirectInput8, ( VOID** )&mDirectInput, nullptr); + result = DirectInput8Create(GetModuleHandle(nullptr), DIRECTINPUT_VERSION, IID_IDirectInput8, ( VOID** )&m_directInput, nullptr); if (FAILED(result)) { - mValid = false; + m_valid = false; return result; } @@ -224,21 +215,21 @@ HRESULT GameController::InitDirectInput(HWND hWnd) memset(&prefJoystickConfig, 0, sizeof(DIJOYCONFIG)); prefJoystickConfig.dwSize = sizeof(DIJOYCONFIG); - mEnumContext.mPrefJoystickConfig = &prefJoystickConfig; - mEnumContext.mPrefJoystickConfigValid = false; + m_enumContext.m_prefJoystickConfig = &prefJoystickConfig; + m_enumContext.m_prefJoystickConfigValid = false; IDirectInputJoyConfig8* joystickConfig = nullptr; - result = mDirectInput->QueryInterface(IID_IDirectInputJoyConfig8, (void**)&joystickConfig); + result = m_directInput->QueryInterface(IID_IDirectInputJoyConfig8, (void**)&joystickConfig); if (FAILED(result)) { - mValid = false; + m_valid = false; return result; } result = joystickConfig->GetConfig(0, &prefJoystickConfig, DIJC_GUIDINSTANCE); if (SUCCEEDED(result)) // this function is expected to fail if no joystick is attached { - mEnumContext.mPrefJoystickConfigValid = true; + m_enumContext.m_prefJoystickConfigValid = true; } if (joystickConfig) @@ -248,18 +239,18 @@ HRESULT GameController::InitDirectInput(HWND hWnd) } // look for a simple Joystick we can use for this sample program. - result = mDirectInput->EnumDevices(DI8DEVCLASS_GAMECTRL, EnumJoysticksCallback, this, DIEDFL_ATTACHEDONLY); + result = m_directInput->EnumDevices(DI8DEVCLASS_GAMECTRL, EnumJoysticksCallback, this, DIEDFL_ATTACHEDONLY); if (FAILED(result)) { - mValid = false; + m_valid = false; return result; } // make sure we got a Joystick - if (mJoystick == nullptr) + if (m_joystick == nullptr) { // No joystick found. - mValid = false; + m_valid = false; return S_OK; } @@ -268,10 +259,10 @@ HRESULT GameController::InitDirectInput(HWND hWnd) // A data format specifies which controls on a device we are interested in, // and how they should be reported. This tells DInput that we will be // passing a DIJOYSTATE2 structure to IDirectInputDevice::GetDeviceState(). - result = mJoystick->SetDataFormat(&c_dfDIJoystick2); + result = m_joystick->SetDataFormat(&c_dfDIJoystick2); if (FAILED(result)) { - mValid = false; + m_valid = false; return result; } @@ -279,10 +270,10 @@ HRESULT GameController::InitDirectInput(HWND hWnd) // interact with the system and with other DInput applications. if (hWnd) { - result = mJoystick->SetCooperativeLevel(hWnd, DISCL_EXCLUSIVE | DISCL_BACKGROUND); + result = m_joystick->SetCooperativeLevel(hWnd, DISCL_EXCLUSIVE | DISCL_BACKGROUND); if (FAILED(result)) { - mValid = false; + m_valid = false; return result; } } @@ -290,37 +281,37 @@ HRESULT GameController::InitDirectInput(HWND hWnd) // Enumerate the Joystick objects. The callback function enabled user // interface elements for objects that are found, and sets the min/max // values property for discovered axes. - result = mJoystick->EnumObjects(EnumObjectsCallback, (VOID*)this, DIDFT_ALL); + result = m_joystick->EnumObjects(EnumObjectsCallback, (VOID*)this, DIDFT_ALL); if (FAILED(result)) { - mValid = false; + m_valid = false; return result; } // acquire the joystick - mJoystick->Acquire(); + m_joystick->Acquire(); // display the device info - MCore::LogDetailedInfo("- Controller = %s", mDeviceInfo.mName.c_str()); - MCore::LogDetailedInfo(" + Num buttons = %d", mDeviceInfo.mNumButtons); - MCore::LogDetailedInfo(" + Num axes = %d", mDeviceInfo.mNumAxes); - MCore::LogDetailedInfo(" + Num sliders = %d", mDeviceInfo.mNumSliders); - MCore::LogDetailedInfo(" + Num POVs = %d", mDeviceInfo.mNumPOVs); + MCore::LogDetailedInfo("- Controller = %s", m_deviceInfo.m_name.c_str()); + MCore::LogDetailedInfo(" + Num buttons = %d", m_deviceInfo.m_numButtons); + MCore::LogDetailedInfo(" + Num axes = %d", m_deviceInfo.m_numAxes); + MCore::LogDetailedInfo(" + Num sliders = %d", m_deviceInfo.m_numSliders); + MCore::LogDetailedInfo(" + Num POVs = %d", m_deviceInfo.m_numPoVs); // display all elements uint32 numPresentElements = 0; for (i = 0; i < NUM_ELEMENTS; ++i) { - if (mDeviceElements[i].mPresent == false) + if (m_deviceElements[i].m_present == false) { continue; } numPresentElements++; - MCore::LogDetailedInfo(" + Element #%d = %s", numPresentElements, mDeviceElements[i].mName.c_str()); + MCore::LogDetailedInfo(" + Element #%d = %s", numPresentElements, m_deviceElements[i].m_name.c_str()); } - mValid = true; + m_valid = true; return S_OK; } @@ -329,18 +320,18 @@ HRESULT GameController::InitDirectInput(HWND hWnd) void GameController::Shutdown() { // unacquire the device one last time just in case - if (mJoystick) + if (m_joystick) { - mJoystick->Unacquire(); - mJoystick->Release(); - mJoystick = nullptr; + m_joystick->Unacquire(); + m_joystick->Release(); + m_joystick = nullptr; } // release any DirectInput objects - if (mDirectInput) + if (m_directInput) { - mDirectInput->Release(); - mDirectInput = nullptr; + m_directInput->Release(); + m_directInput = nullptr; } } @@ -348,42 +339,38 @@ void GameController::Shutdown() // calibrate void GameController::Calibrate() { - mDeviceElements[ELEM_POS_X].mCalibrationValue = -(mJoystickState.lX / 1000.0f); - mDeviceElements[ELEM_POS_Y].mCalibrationValue = -(mJoystickState.lY / 1000.0f); - mDeviceElements[ELEM_POS_Z].mCalibrationValue = -(mJoystickState.lZ / 1000.0f); - mDeviceElements[ELEM_ROT_X].mCalibrationValue = -(mJoystickState.lRx / 1000.0f); - mDeviceElements[ELEM_ROT_Y].mCalibrationValue = -(mJoystickState.lRy / 1000.0f); - mDeviceElements[ELEM_ROT_Z].mCalibrationValue = -(mJoystickState.lRz / 1000.0f); - //mDeviceElements[ELEM_POV_1].mCalibrationValue = -(mJoystickState.rgdwPOV[0] / 1000.0f); - //mDeviceElements[ELEM_POV_2].mCalibrationValue = -(mJoystickState.rgdwPOV[1] / 1000.0f); - //mDeviceElements[ELEM_POV_3].mCalibrationValue = -(mJoystickState.rgdwPOV[2] / 1000.0f); - //mDeviceElements[ELEM_POV_4].mCalibrationValue = -(mJoystickState.rgdwPOV[3] / 1000.0f); - mDeviceElements[ELEM_SLIDER_1].mCalibrationValue = -(mJoystickState.rglSlider[0] / 1000.0f); - mDeviceElements[ELEM_SLIDER_2].mCalibrationValue = -(mJoystickState.rglSlider[1] / 1000.0f); + m_deviceElements[ELEM_POS_X].m_calibrationValue = -(m_joystickState.lX / 1000.0f); + m_deviceElements[ELEM_POS_Y].m_calibrationValue = -(m_joystickState.lY / 1000.0f); + m_deviceElements[ELEM_POS_Z].m_calibrationValue = -(m_joystickState.lZ / 1000.0f); + m_deviceElements[ELEM_ROT_X].m_calibrationValue = -(m_joystickState.lRx / 1000.0f); + m_deviceElements[ELEM_ROT_Y].m_calibrationValue = -(m_joystickState.lRy / 1000.0f); + m_deviceElements[ELEM_ROT_Z].m_calibrationValue = -(m_joystickState.lRz / 1000.0f); + m_deviceElements[ELEM_SLIDER_1].m_calibrationValue = -(m_joystickState.rglSlider[0] / 1000.0f); + m_deviceElements[ELEM_SLIDER_2].m_calibrationValue = -(m_joystickState.rglSlider[1] / 1000.0f); } // update the controller bool GameController::Update() { - if (mJoystick == nullptr) + if (m_joystick == nullptr) { - mValid = false; + m_valid = false; return false; } // poll the device to read the current state - HRESULT result = mJoystick->Poll(); + HRESULT result = m_joystick->Poll(); if (FAILED(result)) { // DInput is telling us that the input stream has been // interrupted. We aren't tracking any state between polls, so // we don't have any special reset that needs to be done. We // just re-acquire and try again. - result = mJoystick->Acquire(); + result = m_joystick->Acquire(); while (result == DIERR_INPUTLOST) { - result = mJoystick->Acquire(); + result = m_joystick->Acquire(); } // reset all buttons @@ -398,70 +385,70 @@ bool GameController::Update() // switching, so just try again later if (result == DIERR_OTHERAPPHASPRIO) { - mValid = true; + m_valid = true; return true; } if (FAILED(result)) { - mValid = false; + m_valid = false; return false; } } // Get the input's device state - result = mJoystick->GetDeviceState(sizeof(DIJOYSTATE2), &mJoystickState); + result = m_joystick->GetDeviceState(sizeof(DIJOYSTATE2), &m_joystickState); if (FAILED(result)) { - mValid = false; + m_valid = false; return false; // The device should have been acquired during the Poll() } // update the values of the elements - mDeviceElements[ELEM_POS_X].mValue = mJoystickState.lX / 1000.0f; - mDeviceElements[ELEM_POS_Y].mValue = mJoystickState.lY / 1000.0f; - mDeviceElements[ELEM_POS_Z].mValue = mJoystickState.lZ / 1000.0f; - mDeviceElements[ELEM_ROT_X].mValue = mJoystickState.lRx / 1000.0f; - mDeviceElements[ELEM_ROT_Y].mValue = mJoystickState.lRy / 1000.0f; - mDeviceElements[ELEM_ROT_Z].mValue = mJoystickState.lRz / 1000.0f; - mDeviceElements[ELEM_SLIDER_1].mValue = mJoystickState.rglSlider[0] / 1000.0f; - mDeviceElements[ELEM_SLIDER_2].mValue = mJoystickState.rglSlider[1] / 1000.0f; + m_deviceElements[ELEM_POS_X].m_value = m_joystickState.lX / 1000.0f; + m_deviceElements[ELEM_POS_Y].m_value = m_joystickState.lY / 1000.0f; + m_deviceElements[ELEM_POS_Z].m_value = m_joystickState.lZ / 1000.0f; + m_deviceElements[ELEM_ROT_X].m_value = m_joystickState.lRx / 1000.0f; + m_deviceElements[ELEM_ROT_Y].m_value = m_joystickState.lRy / 1000.0f; + m_deviceElements[ELEM_ROT_Z].m_value = m_joystickState.lRz / 1000.0f; + m_deviceElements[ELEM_SLIDER_1].m_value = m_joystickState.rglSlider[0] / 1000.0f; + m_deviceElements[ELEM_SLIDER_2].m_value = m_joystickState.rglSlider[1] / 1000.0f; - if (mJoystickState.rgdwPOV[0] == MCORE_INVALIDINDEX32) + if (m_joystickState.rgdwPOV[0] == MCORE_INVALIDINDEX32) { - mDeviceElements[ELEM_POV_1].mValue = 0.0f; + m_deviceElements[ELEM_POV_1].m_value = 0.0f; } else { - mDeviceElements[ELEM_POV_1].mValue = (mJoystickState.rgdwPOV[0] / 100.0f) / 360.0f; + m_deviceElements[ELEM_POV_1].m_value = (m_joystickState.rgdwPOV[0] / 100.0f) / 360.0f; } - if (mJoystickState.rgdwPOV[1] == MCORE_INVALIDINDEX32) + if (m_joystickState.rgdwPOV[1] == MCORE_INVALIDINDEX32) { - mDeviceElements[ELEM_POV_2].mValue = 0.0f; + m_deviceElements[ELEM_POV_2].m_value = 0.0f; } else { - mDeviceElements[ELEM_POV_2].mValue = (mJoystickState.rgdwPOV[1] / 100.0f) / 360.0f; + m_deviceElements[ELEM_POV_2].m_value = (m_joystickState.rgdwPOV[1] / 100.0f) / 360.0f; } - if (mJoystickState.rgdwPOV[2] == MCORE_INVALIDINDEX32) + if (m_joystickState.rgdwPOV[2] == MCORE_INVALIDINDEX32) { - mDeviceElements[ELEM_POV_3].mValue = 0.0f; + m_deviceElements[ELEM_POV_3].m_value = 0.0f; } else { - mDeviceElements[ELEM_POV_3].mValue = (mJoystickState.rgdwPOV[2] / 100.0f) / 360.0f; + m_deviceElements[ELEM_POV_3].m_value = (m_joystickState.rgdwPOV[2] / 100.0f) / 360.0f; } - if (mJoystickState.rgdwPOV[3] == MCORE_INVALIDINDEX32) + if (m_joystickState.rgdwPOV[3] == MCORE_INVALIDINDEX32) { - mDeviceElements[ELEM_POV_4].mValue = 0.0f; + m_deviceElements[ELEM_POV_4].m_value = 0.0f; } else { - mDeviceElements[ELEM_POV_4].mValue = (mJoystickState.rgdwPOV[3] / 100.0f) / 360.0f; + m_deviceElements[ELEM_POV_4].m_value = (m_joystickState.rgdwPOV[3] / 100.0f) / 360.0f; } // apply the dead zone - const float minValue = mDeadZone; + const float minValue = m_deadZone; const float maxValue = 1.0f; const float range = maxValue - minValue; @@ -469,12 +456,12 @@ bool GameController::Update() for (uint32 i = 0; i < 8; ++i) { // get the current normalized value - float value = mDeviceElements[i].mValue; + float value = m_deviceElements[i].m_value; // ignore all values that are smaller than the dead zone - if (value > -mDeadZone && value < mDeadZone) + if (value > -m_deadZone && value < m_deadZone) { - mDeviceElements[i].mValue = 0.0f; + m_deviceElements[i].m_value = 0.0f; } else { @@ -487,14 +474,14 @@ bool GameController::Update() } // calculate the value in the new range excluding the dead zone range - const float newValue = (value - mDeadZone) / range; + const float newValue = (value - m_deadZone) / range; // set it back in normal or negated version - mDeviceElements[i].mValue = negativeValue == false ? newValue : -newValue; + m_deviceElements[i].m_value = negativeValue == false ? newValue : -newValue; } } - mValid = true; + m_valid = true; return true; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GameController.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GameController.h index f1ee2e0e9d..47cfb9ddfc 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GameController.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GameController.h @@ -59,7 +59,7 @@ public: ELEMTYPE_POV = 2 }; - GameController() { mDirectInput = nullptr; mJoystick = nullptr; mHWnd = nullptr; mDeadZone = 0.15f; mValid = false; } + GameController() { m_directInput = nullptr; m_joystick = nullptr; m_hWnd = nullptr; m_deadZone = 0.15f; m_valid = false; } ~GameController() { Shutdown(); } bool Init(HWND hWnd); @@ -67,61 +67,61 @@ public: void Calibrate(); void Shutdown(); - MCORE_INLINE IDirectInputDevice8* GetJoystick() const { return mJoystick; } // returns nullptr when no joystick found during init + MCORE_INLINE IDirectInputDevice8* GetJoystick() const { return m_joystick; } // returns nullptr when no joystick found during init - MCORE_INLINE const char* GetDeviceName() const { return mDeviceInfo.mName.c_str(); } - MCORE_INLINE const AZStd::string& GetDeviceNameString() const { return mDeviceInfo.mName; } - MCORE_INLINE uint32 GetNumButtons() const { return mDeviceInfo.mNumButtons; } - MCORE_INLINE uint32 GetNumSliders() const { return mDeviceInfo.mNumSliders; } - MCORE_INLINE uint32 GetNumPOVs() const { return mDeviceInfo.mNumPOVs; } - MCORE_INLINE uint32 GetNumAxes() const { return mDeviceInfo.mNumAxes; } - void SetDeadZone(float deadZone) { mDeadZone = deadZone; } - MCORE_INLINE float GetDeadZone() const { return mDeadZone; } + MCORE_INLINE const char* GetDeviceName() const { return m_deviceInfo.m_name.c_str(); } + MCORE_INLINE const AZStd::string& GetDeviceNameString() const { return m_deviceInfo.m_name; } + MCORE_INLINE uint32 GetNumButtons() const { return m_deviceInfo.m_numButtons; } + MCORE_INLINE uint32 GetNumSliders() const { return m_deviceInfo.m_numSliders; } + MCORE_INLINE uint32 GetNumPOVs() const { return m_deviceInfo.m_numPoVs; } + MCORE_INLINE uint32 GetNumAxes() const { return m_deviceInfo.m_numAxes; } + void SetDeadZone(float deadZone) { m_deadZone = deadZone; } + MCORE_INLINE float GetDeadZone() const { return m_deadZone; } const char* GetElementEnumName(uint32 index); uint32 FindElementIDByName(const AZStd::string& elementEnumName); - MCORE_INLINE bool GetIsPresent(uint32 elementID) const { return mDeviceElements[elementID].mPresent; } + MCORE_INLINE bool GetIsPresent(uint32 elementID) const { return m_deviceElements[elementID].m_present; } MCORE_INLINE bool GetIsButtonPressed(uint8 buttonIndex) const { if (buttonIndex < 128) { - return (mJoystickState.rgbButtons[buttonIndex] & 0x80) != 0; + return (m_joystickState.rgbButtons[buttonIndex] & 0x80) != 0; } return false; } - MCORE_INLINE float GetValue(uint32 elementID) const { return mDeviceElements[elementID].mValue; } - MCORE_INLINE const char* GetElementName(uint32 elementID) const { return mDeviceElements[elementID].mName.c_str(); } - MCORE_INLINE bool GetIsValid() const { return mValid; } + MCORE_INLINE float GetValue(uint32 elementID) const { return m_deviceElements[elementID].m_value; } + MCORE_INLINE const char* GetElementName(uint32 elementID) const { return m_deviceElements[elementID].m_name.c_str(); } + MCORE_INLINE bool GetIsValid() const { return m_valid; } private: struct DeviceInfo { MCORE_MEMORYOBJECTCATEGORY(GameController::DeviceInfo, EMFX_DEFAULT_ALIGNMENT, MEMCATEGORY_STANDARDPLUGINS_ANIMGRAPH); - AZStd::string mName; - uint32 mNumButtons; - uint32 mNumAxes; - uint32 mNumPOVs; - uint32 mNumSliders; + AZStd::string m_name; + uint32 m_numButtons; + uint32 m_numAxes; + uint32 m_numPoVs; + uint32 m_numSliders; }; struct DeviceElement { MCORE_MEMORYOBJECTCATEGORY(GameController::DeviceElement, EMFX_DEFAULT_ALIGNMENT, MEMCATEGORY_STANDARDPLUGINS_ANIMGRAPH); - AZStd::string mName; - float mValue; - float mCalibrationValue; - ElementType mType; - bool mPresent; + AZStd::string m_name; + float m_value; + float m_calibrationValue; + ElementType m_type; + bool m_present; }; struct EnumContext { MCORE_MEMORYOBJECTCATEGORY(GameController::EnumContext, EMFX_DEFAULT_ALIGNMENT, MEMCATEGORY_STANDARDPLUGINS_ANIMGRAPH); - DIJOYCONFIG* mPrefJoystickConfig; - bool mPrefJoystickConfigValid; + DIJOYCONFIG* m_prefJoystickConfig; + bool m_prefJoystickConfigValid; }; MCORE_INLINE void SetButtonPressed(uint8 buttonIndex, bool isPressed) @@ -132,23 +132,23 @@ private: } if (isPressed) { - mJoystickState.rgbButtons[buttonIndex] |= 0x80; + m_joystickState.rgbButtons[buttonIndex] |= 0x80; } else { - mJoystickState.rgbButtons[buttonIndex] &= ~0x80; + m_joystickState.rgbButtons[buttonIndex] &= ~0x80; } } - IDirectInput8* mDirectInput; - IDirectInputDevice8* mJoystick; - DIJOYSTATE2 mJoystickState; // DInput Joystick state - EnumContext mEnumContext; - HWND mHWnd; - DeviceInfo mDeviceInfo; - DeviceElement mDeviceElements[NUM_ELEMENTS]; - float mDeadZone; - bool mValid; + IDirectInput8* m_directInput; + IDirectInputDevice8* m_joystick; + DIJOYSTATE2 m_joystickState; // DInput Joystick state + EnumContext m_enumContext; + HWND m_hWnd; + DeviceInfo m_deviceInfo; + DeviceElement m_deviceElements[NUM_ELEMENTS]; + float m_deadZone; + bool m_valid; static BOOL CALLBACK EnumJoysticksCallback(const DIDEVICEINSTANCE* pdidInstance, void* pContext); static BOOL CALLBACK EnumObjectsCallback(const DIDEVICEOBJECTINSTANCE* pdidoi, void* pContext); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GameControllerWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GameControllerWindow.cpp index eeb765ce54..c17ff12947 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GameControllerWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GameControllerWindow.cpp @@ -54,20 +54,20 @@ namespace EMStudio GameControllerWindow::GameControllerWindow(AnimGraphPlugin* plugin, QWidget* parent) : QWidget(parent) { - mPlugin = plugin; - mAnimGraph = nullptr; - mDynamicWidget = nullptr; - mPresetNameLineEdit = nullptr; - mParameterGridLayout = nullptr; - mDeadZoneValueLabel = nullptr; - mButtonGridLayout = nullptr; - mDeadZoneSlider = nullptr; - mPresetComboBox = nullptr; - mInterfaceTimerID = MCORE_INVALIDINDEX32; - mGameControllerTimerID = MCORE_INVALIDINDEX32; - mString.reserve(4096); + m_plugin = plugin; + m_animGraph = nullptr; + m_dynamicWidget = nullptr; + m_presetNameLineEdit = nullptr; + m_parameterGridLayout = nullptr; + m_deadZoneValueLabel = nullptr; + m_buttonGridLayout = nullptr; + m_deadZoneSlider = nullptr; + m_presetComboBox = nullptr; + m_interfaceTimerId = MCORE_INVALIDINDEX32; + m_gameControllerTimerId = MCORE_INVALIDINDEX32; + m_string.reserve(4096); #if AZ_TRAIT_EMOTIONFX_HAS_GAME_CONTROLLER - mGameController = nullptr; + m_gameController = nullptr; #endif Init(); @@ -78,29 +78,29 @@ namespace EMStudio GameControllerWindow::~GameControllerWindow() { // stop the timers - mInterfaceTimer.stop(); - mGameControllerTimer.stop(); + m_interfaceTimer.stop(); + m_gameControllerTimer.stop(); // unregister the command callbacks and get rid of the memory - GetCommandManager()->RemoveCommandCallback(mCreateCallback, false); - GetCommandManager()->RemoveCommandCallback(mRemoveCallback, false); - GetCommandManager()->RemoveCommandCallback(mAdjustCallback, false); - GetCommandManager()->RemoveCommandCallback(mSelectCallback, false); - GetCommandManager()->RemoveCommandCallback(mUnselectCallback, false); - GetCommandManager()->RemoveCommandCallback(mClearSelectionCallback, false); - delete mCreateCallback; - delete mRemoveCallback; - delete mAdjustCallback; - delete mClearSelectionCallback; - delete mSelectCallback; - delete mUnselectCallback; + GetCommandManager()->RemoveCommandCallback(m_createCallback, false); + GetCommandManager()->RemoveCommandCallback(m_removeCallback, false); + GetCommandManager()->RemoveCommandCallback(m_adjustCallback, false); + GetCommandManager()->RemoveCommandCallback(m_selectCallback, false); + GetCommandManager()->RemoveCommandCallback(m_unselectCallback, false); + GetCommandManager()->RemoveCommandCallback(m_clearSelectionCallback, false); + delete m_createCallback; + delete m_removeCallback; + delete m_adjustCallback; + delete m_clearSelectionCallback; + delete m_selectCallback; + delete m_unselectCallback; // get rid of the game controller #if AZ_TRAIT_EMOTIONFX_HAS_GAME_CONTROLLER - if (mGameController) + if (m_gameController) { - mGameController->Shutdown(); - delete mGameController; + m_gameController->Shutdown(); + delete m_gameController; } #endif } @@ -110,20 +110,20 @@ namespace EMStudio void GameControllerWindow::Init() { // create the callbacks - mCreateCallback = new CommandCreateBlendParameterCallback(false); - mRemoveCallback = new CommandRemoveBlendParameterCallback(false); - mAdjustCallback = new CommandAdjustBlendParameterCallback(false); - mSelectCallback = new CommandSelectCallback(false); - mUnselectCallback = new CommandUnselectCallback(false); - mClearSelectionCallback = new CommandClearSelectionCallback(false); + m_createCallback = new CommandCreateBlendParameterCallback(false); + m_removeCallback = new CommandRemoveBlendParameterCallback(false); + m_adjustCallback = new CommandAdjustBlendParameterCallback(false); + m_selectCallback = new CommandSelectCallback(false); + m_unselectCallback = new CommandUnselectCallback(false); + m_clearSelectionCallback = new CommandClearSelectionCallback(false); // hook the callbacks to the commands - GetCommandManager()->RegisterCommandCallback("AnimGraphCreateParameter", mCreateCallback); - GetCommandManager()->RegisterCommandCallback("AnimGraphRemoveParameter", mRemoveCallback); - GetCommandManager()->RegisterCommandCallback("AnimGraphAdjustParameter", mAdjustCallback); - GetCommandManager()->RegisterCommandCallback("Select", mSelectCallback); - GetCommandManager()->RegisterCommandCallback("Unselect", mUnselectCallback); - GetCommandManager()->RegisterCommandCallback("ClearSelection", mClearSelectionCallback); + GetCommandManager()->RegisterCommandCallback("AnimGraphCreateParameter", m_createCallback); + GetCommandManager()->RegisterCommandCallback("AnimGraphRemoveParameter", m_removeCallback); + GetCommandManager()->RegisterCommandCallback("AnimGraphAdjustParameter", m_adjustCallback); + GetCommandManager()->RegisterCommandCallback("Select", m_selectCallback); + GetCommandManager()->RegisterCommandCallback("Unselect", m_unselectCallback); + GetCommandManager()->RegisterCommandCallback("ClearSelection", m_clearSelectionCallback); InitGameController(); @@ -132,11 +132,11 @@ namespace EMStudio setLayout(layout); // create the dialog stack - mDialogStack = new MysticQt::DialogStack(); - layout->addWidget(mDialogStack); + m_dialogStack = new MysticQt::DialogStack(); + layout->addWidget(m_dialogStack); // add the game controller - mGameControllerComboBox = new QComboBox(); + m_gameControllerComboBox = new QComboBox(); UpdateGameControllerComboBox(); QHBoxLayout* gameControllerLayout = new QHBoxLayout(); @@ -144,44 +144,44 @@ namespace EMStudio QLabel* activeControllerLabel = new QLabel("Active Controller:"); activeControllerLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); gameControllerLayout->addWidget(activeControllerLabel); - gameControllerLayout->addWidget(mGameControllerComboBox); + gameControllerLayout->addWidget(m_gameControllerComboBox); gameControllerLayout->addWidget(EMStudioManager::MakeSeperatorLabel(1, 20)); // create the presets interface QHBoxLayout* horizontalLayout = new QHBoxLayout(); horizontalLayout->setMargin(0); - mPresetComboBox = new QComboBox(); - mAddPresetButton = new QPushButton(); - mRemovePresetButton = new QPushButton(); - mPresetNameLineEdit = new QLineEdit(); + m_presetComboBox = new QComboBox(); + m_addPresetButton = new QPushButton(); + m_removePresetButton = new QPushButton(); + m_presetNameLineEdit = new QLineEdit(); - connect(mPresetComboBox, static_cast(&QComboBox::currentIndexChanged), this, &GameControllerWindow::OnPresetComboBox); - connect(mAddPresetButton, &QPushButton::clicked, this, &GameControllerWindow::OnAddPresetButton); - connect(mRemovePresetButton, &QPushButton::clicked, this, &GameControllerWindow::OnRemovePresetButton); - connect(mPresetNameLineEdit, &QLineEdit::textEdited, this, &GameControllerWindow::OnPresetNameEdited); - connect(mPresetNameLineEdit, &QLineEdit::returnPressed, this, &GameControllerWindow::OnPresetNameChanged); + connect(m_presetComboBox, static_cast(&QComboBox::currentIndexChanged), this, &GameControllerWindow::OnPresetComboBox); + connect(m_addPresetButton, &QPushButton::clicked, this, &GameControllerWindow::OnAddPresetButton); + connect(m_removePresetButton, &QPushButton::clicked, this, &GameControllerWindow::OnRemovePresetButton); + connect(m_presetNameLineEdit, &QLineEdit::textEdited, this, &GameControllerWindow::OnPresetNameEdited); + connect(m_presetNameLineEdit, &QLineEdit::returnPressed, this, &GameControllerWindow::OnPresetNameChanged); - EMStudioManager::MakeTransparentButton(mAddPresetButton, "Images/Icons/Plus.svg", "Add a game controller preset"); - EMStudioManager::MakeTransparentButton(mRemovePresetButton, "Images/Icons/Remove.svg", "Remove a game controller preset"); + EMStudioManager::MakeTransparentButton(m_addPresetButton, "Images/Icons/Plus.svg", "Add a game controller preset"); + EMStudioManager::MakeTransparentButton(m_removePresetButton, "Images/Icons/Remove.svg", "Remove a game controller preset"); QHBoxLayout* buttonsLayout = new QHBoxLayout(); - buttonsLayout->addWidget(mAddPresetButton); - buttonsLayout->addWidget(mRemovePresetButton); + buttonsLayout->addWidget(m_addPresetButton); + buttonsLayout->addWidget(m_removePresetButton); buttonsLayout->setSpacing(0); buttonsLayout->setMargin(0); horizontalLayout->addWidget(new QLabel("Preset:")); - horizontalLayout->addWidget(mPresetComboBox); + horizontalLayout->addWidget(m_presetComboBox); horizontalLayout->addLayout(buttonsLayout); - horizontalLayout->addWidget(mPresetNameLineEdit); + horizontalLayout->addWidget(m_presetNameLineEdit); gameControllerLayout->addLayout(horizontalLayout); QWidget* dummyWidget = new QWidget(); dummyWidget->setObjectName("StyledWidgetDark"); dummyWidget->setLayout(gameControllerLayout); - mDialogStack->Add(dummyWidget, "Game Controller And Preset Selection"); - connect(mGameControllerComboBox, static_cast(&QComboBox::currentIndexChanged), this, &GameControllerWindow::OnGameControllerComboBox); + m_dialogStack->Add(dummyWidget, "Game Controller And Preset Selection"); + connect(m_gameControllerComboBox, static_cast(&QComboBox::currentIndexChanged), this, &GameControllerWindow::OnGameControllerComboBox); DisablePresetInterface(); AutoSelectGameController(); @@ -195,13 +195,13 @@ namespace EMStudio { #if AZ_TRAIT_EMOTIONFX_HAS_GAME_CONTROLLER // this will call ReInit(); - if (mGameController->GetDeviceNameString().empty() == false && mGameControllerComboBox->count() > 1) + if (m_gameController->GetDeviceNameString().empty() == false && m_gameControllerComboBox->count() > 1) { - mGameControllerComboBox->setCurrentIndex(1); + m_gameControllerComboBox->setCurrentIndex(1); } else { - mGameControllerComboBox->setCurrentIndex(0); + m_gameControllerComboBox->setCurrentIndex(0); } #endif } @@ -211,15 +211,15 @@ namespace EMStudio void GameControllerWindow::InitGameController() { #if AZ_TRAIT_EMOTIONFX_HAS_GAME_CONTROLLER - if (mGameController) + if (m_gameController) { - mGameController->Shutdown(); - delete mGameController; - mGameController = nullptr; + m_gameController->Shutdown(); + delete m_gameController; + m_gameController = nullptr; } // create the game controller object - mGameController = new GameController(); + m_gameController = new GameController(); // Call mainWindow->window() to make sure you get the top level window which the mainWindow might not in fact be. //IEditor* editor = nullptr; @@ -227,7 +227,7 @@ namespace EMStudio //QMainWindow* mainWindow = editor->GetEditorMainWindow(); //HWND hWnd = reinterpret_cast( mainWindow->window()->winId() ); HWND hWnd = nullptr; - if (mGameController->Init(hWnd) == false) + if (m_gameController->Init(hWnd) == false) { MCore::LogError("Cannot initialize game controller."); } @@ -238,19 +238,19 @@ namespace EMStudio void GameControllerWindow::UpdateGameControllerComboBox() { // clear it and add the none option - mGameControllerComboBox->clear(); - mGameControllerComboBox->addItem(NO_GAMECONTROLLER_NAME); + m_gameControllerComboBox->clear(); + m_gameControllerComboBox->addItem(NO_GAMECONTROLLER_NAME); // add the gamepad in case it is valid and the device name is not empty #if AZ_TRAIT_EMOTIONFX_HAS_GAME_CONTROLLER - if (mGameController->GetIsValid() && mGameController->GetDeviceNameString().empty() == false) + if (m_gameController->GetIsValid() && m_gameController->GetDeviceNameString().empty() == false) { - mGameControllerComboBox->addItem(mGameController->GetDeviceName()); + m_gameControllerComboBox->addItem(m_gameController->GetDeviceName()); } #endif // always adjust the size of the combobox to the currently selected text - mGameControllerComboBox->setSizeAdjustPolicy(QComboBox::AdjustToContents); + m_gameControllerComboBox->setSizeAdjustPolicy(QComboBox::AdjustToContents); } @@ -264,24 +264,24 @@ namespace EMStudio ReInit(); // update the parameter window - mPlugin->GetParameterWindow()->Reinit(/*forceReinit*/true); + m_plugin->GetParameterWindow()->Reinit(/*forceReinit*/true); } void GameControllerWindow::DisablePresetInterface() { - mPresetComboBox->blockSignals(true); - mPresetComboBox->clear(); - mPresetComboBox->blockSignals(false); + m_presetComboBox->blockSignals(true); + m_presetComboBox->clear(); + m_presetComboBox->blockSignals(false); - mPresetNameLineEdit->blockSignals(true); - mPresetNameLineEdit->setText(""); - mPresetNameLineEdit->blockSignals(false); + m_presetNameLineEdit->blockSignals(true); + m_presetNameLineEdit->setText(""); + m_presetNameLineEdit->blockSignals(false); - mPresetComboBox->setEnabled(false); - mPresetNameLineEdit->setEnabled(false); - mAddPresetButton->setEnabled(false); - mRemovePresetButton->setEnabled(false); + m_presetComboBox->setEnabled(false); + m_presetNameLineEdit->setEnabled(false); + m_addPresetButton->setEnabled(false); + m_removePresetButton->setEnabled(false); } @@ -289,21 +289,21 @@ namespace EMStudio void GameControllerWindow::ReInit() { // get the anim graph - EMotionFX::AnimGraph* animGraph = mPlugin->GetActiveAnimGraph(); - mAnimGraph = animGraph; + EMotionFX::AnimGraph* animGraph = m_plugin->GetActiveAnimGraph(); + m_animGraph = animGraph; // remove all existing items - if (mDynamicWidget) + if (m_dynamicWidget) { - mDialogStack->Remove(mDynamicWidget); + m_dialogStack->Remove(m_dynamicWidget); } - mDynamicWidget = nullptr; - mInterfaceTimer.stop(); - mGameControllerTimer.stop(); + m_dynamicWidget = nullptr; + m_interfaceTimer.stop(); + m_gameControllerTimer.stop(); // check if we need to recreate the dynamic widget #if AZ_TRAIT_EMOTIONFX_HAS_GAME_CONTROLLER - if (mGameController->GetIsValid() == false || mGameControllerComboBox->currentText() != mGameController->GetDeviceName()) + if (m_gameController->GetIsValid() == false || m_gameControllerComboBox->currentText() != m_gameController->GetDeviceName()) { DisablePresetInterface(); return; @@ -320,8 +320,8 @@ namespace EMStudio } // create the dynamic widget - mDynamicWidget = new QWidget(); - mDynamicWidget->setObjectName("StyledWidgetDark"); + m_dynamicWidget = new QWidget(); + m_dynamicWidget->setObjectName("StyledWidgetDark"); // get the game controller settings from the anim graph EMotionFX::AnimGraphGameControllerSettings& gameControllerSettings = animGraph->GetGameControllerSettings(); @@ -340,16 +340,16 @@ namespace EMStudio EMotionFX::AnimGraphGameControllerSettings::Preset* activePreset = gameControllerSettings.GetActivePreset(); // create the parameter grid layout - mParameterGridLayout = new QGridLayout(); - mParameterGridLayout->setAlignment(Qt::AlignTop); - mParameterGridLayout->setMargin(0); + m_parameterGridLayout = new QGridLayout(); + m_parameterGridLayout->setAlignment(Qt::AlignTop); + m_parameterGridLayout->setMargin(0); // add all parameters - mParameterInfos.clear(); + m_parameterInfos.clear(); const EMotionFX::ValueParameterVector& parameters = animGraph->RecursivelyGetValueParameters(); const int numParameters = aznumeric_caster(parameters.size()); - mParameterInfos.reserve(numParameters); + m_parameterInfos.reserve(numParameters); for (int parameterIndex = 0; parameterIndex < numParameters; ++parameterIndex) { @@ -373,7 +373,7 @@ namespace EMStudio QLabel* label = new QLabel(labelString.c_str()); label->setToolTip(parameter->GetDescription().c_str()); label->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - mParameterGridLayout->addWidget(label, static_cast(parameterIndex), 0); + m_parameterGridLayout->addWidget(label, static_cast(parameterIndex), 0); // add the axis combo box to the layout QComboBox* axesComboBox = new QComboBox(); @@ -389,10 +389,10 @@ namespace EMStudio for (uint32 j = 0; j < GameController::NUM_ELEMENTS; ++j) { // check if the element is present and add it to the combo box if yes - if (mGameController->GetIsPresent(j)) + if (m_gameController->GetIsPresent(j)) { // add the name of the element to the combo box - axesComboBox->addItem(mGameController->GetElementEnumName(j)); + axesComboBox->addItem(m_gameController->GetElementEnumName(j)); // in case the current element is the one the parameter is assigned to, remember the correct index if (j == settingsInfo->m_axis) @@ -408,7 +408,7 @@ namespace EMStudio else if (parameter->GetType() == MCore::AttributeVector2::TYPE_ID) { uint32 numPresentElements = 0; - if (mGameController->GetIsPresent(GameController::ELEM_POS_X) && mGameController->GetIsPresent(GameController::ELEM_POS_Y)) + if (m_gameController->GetIsPresent(GameController::ELEM_POS_X) && m_gameController->GetIsPresent(GameController::ELEM_POS_Y)) { axesComboBox->addItem("Pos XY"); if (settingsInfo->m_axis == 0) @@ -418,7 +418,7 @@ namespace EMStudio numPresentElements++; } - if (mGameController->GetIsPresent(GameController::ELEM_ROT_X) && mGameController->GetIsPresent(GameController::ELEM_ROT_Y)) + if (m_gameController->GetIsPresent(GameController::ELEM_ROT_X) && m_gameController->GetIsPresent(GameController::ELEM_ROT_Y)) { axesComboBox->addItem("Rot XY"); if (settingsInfo->m_axis == 1) @@ -433,7 +433,7 @@ namespace EMStudio // select the given axis in the combo box or select none if there is no assignment yet or the assigned axis wasn't found on the current game controller axesComboBox->setCurrentIndex(selectedComboItem); - mParameterGridLayout->addWidget(axesComboBox, static_cast(parameterIndex), 1); + m_parameterGridLayout->addWidget(axesComboBox, static_cast(parameterIndex), 1); // add the mode combo box to the layout QComboBox* modeComboBox = new QComboBox(); @@ -446,7 +446,7 @@ namespace EMStudio modeComboBox->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); connect(modeComboBox, static_cast(&QComboBox::currentIndexChanged), this, &GameControllerWindow::OnParameterModeComboBox); modeComboBox->setCurrentIndex(settingsInfo->m_mode); - mParameterGridLayout->addWidget(modeComboBox, static_cast(parameterIndex), 2); + m_parameterGridLayout->addWidget(modeComboBox, static_cast(parameterIndex), 2); // add the invert checkbox to the layout QHBoxLayout* invertCheckBoxLayout = new QHBoxLayout(); @@ -459,7 +459,7 @@ namespace EMStudio connect(invertCheckbox, &QCheckBox::stateChanged, this, &GameControllerWindow::OnInvertCheckBoxChanged); invertCheckbox->setCheckState(settingsInfo->m_invert ? Qt::Checked : Qt::Unchecked); invertCheckBoxLayout->addWidget(invertCheckbox); - mParameterGridLayout->addLayout(invertCheckBoxLayout, static_cast(parameterIndex), 3); + m_parameterGridLayout->addLayout(invertCheckBoxLayout, static_cast(parameterIndex), 3); // add the current value edit field to the layout QLineEdit* valueEdit = new QLineEdit(); @@ -468,42 +468,42 @@ namespace EMStudio valueEdit->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); valueEdit->setMinimumWidth(70); valueEdit->setMaximumWidth(70); - mParameterGridLayout->addWidget(valueEdit, static_cast(parameterIndex), 4); + m_parameterGridLayout->addWidget(valueEdit, static_cast(parameterIndex), 4); // create the parameter info and add it to the array ParameterInfo paramInfo; - paramInfo.mParameter = parameter; - paramInfo.mAxis = axesComboBox; - paramInfo.mMode = modeComboBox; - paramInfo.mInvert = invertCheckbox; - paramInfo.mValue = valueEdit; - mParameterInfos.emplace_back(paramInfo); + paramInfo.m_parameter = parameter; + paramInfo.m_axis = axesComboBox; + paramInfo.m_mode = modeComboBox; + paramInfo.m_invert = invertCheckbox; + paramInfo.m_value = valueEdit; + m_parameterInfos.emplace_back(paramInfo); // update the interface UpdateParameterInterface(¶mInfo); } // create the button layout - mButtonGridLayout = new QGridLayout(); - mButtonGridLayout->setAlignment(Qt::AlignTop); - mButtonGridLayout->setMargin(0); + m_buttonGridLayout = new QGridLayout(); + m_buttonGridLayout->setAlignment(Qt::AlignTop); + m_buttonGridLayout->setMargin(0); // clear the button infos - mButtonInfos.clear(); + m_buttonInfos.clear(); // get the number of buttons and iterate through them #if AZ_TRAIT_EMOTIONFX_HAS_GAME_CONTROLLER - const uint32 numButtons = mGameController->GetNumButtons(); + const uint32 numButtons = m_gameController->GetNumButtons(); for (uint32 i = 0; i < numButtons; ++i) { EMotionFX::AnimGraphGameControllerSettings::ButtonInfo* settingsInfo = activePreset->FindButtonInfo(i); MCORE_ASSERT(settingsInfo); // add the button name to the layout - mString = AZStd::string::format("Button %s%d", (i < 10) ? "0" : "", i); - QLabel* nameLabel = new QLabel(mString.c_str()); + m_string = AZStd::string::format("Button %s%d", (i < 10) ? "0" : "", i); + QLabel* nameLabel = new QLabel(m_string.c_str()); nameLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - mButtonGridLayout->addWidget(nameLabel, i, 0); + m_buttonGridLayout->addWidget(nameLabel, i, 0); // add the mode combo box to the layout QComboBox* modeComboBox = new QComboBox(); @@ -517,17 +517,17 @@ namespace EMStudio modeComboBox->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); connect(modeComboBox, static_cast(&QComboBox::currentIndexChanged), this, &GameControllerWindow::OnButtonModeComboBox); modeComboBox->setCurrentIndex(settingsInfo->m_mode); - mButtonGridLayout->addWidget(modeComboBox, i, 1); + m_buttonGridLayout->addWidget(modeComboBox, i, 1); - mButtonInfos.emplace_back(ButtonInfo(i, modeComboBox)); + m_buttonInfos.emplace_back(ButtonInfo(i, modeComboBox)); // reinit the dynamic part of the button layout ReInitButtonInterface(i); } // real time preview of the controller - mPreviewLabels.clear(); - mPreviewLabels.resize(GameController::NUM_ELEMENTS + 1); + m_previewLabels.clear(); + m_previewLabels.resize(GameController::NUM_ELEMENTS + 1); QVBoxLayout* realtimePreviewLayout = new QVBoxLayout(); QGridLayout* previewGridLayout = new QGridLayout(); previewGridLayout->setAlignment(Qt::AlignTop); @@ -535,30 +535,30 @@ namespace EMStudio uint32 realTimePreviewLabelCounter = 0; for (uint32 i = 0; i < GameController::NUM_ELEMENTS; ++i) { - if (mGameController->GetIsPresent(i)) + if (m_gameController->GetIsPresent(i)) { - QLabel* elementNameLabel = new QLabel(mGameController->GetElementEnumName(i)); + QLabel* elementNameLabel = new QLabel(m_gameController->GetElementEnumName(i)); elementNameLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); previewGridLayout->addWidget(elementNameLabel, realTimePreviewLabelCounter, 0); - mPreviewLabels[i] = new QLabel(); - previewGridLayout->addWidget(mPreviewLabels[i], realTimePreviewLabelCounter, 1, Qt::AlignLeft); + m_previewLabels[i] = new QLabel(); + previewGridLayout->addWidget(m_previewLabels[i], realTimePreviewLabelCounter, 1, Qt::AlignLeft); realTimePreviewLabelCounter++; } else { - mPreviewLabels[i] = nullptr; + m_previewLabels[i] = nullptr; } } realtimePreviewLayout->addLayout(previewGridLayout); // add the special case label for the pressed buttons - mPreviewLabels[GameController::NUM_ELEMENTS] = new QLabel(); + m_previewLabels[GameController::NUM_ELEMENTS] = new QLabel(); QLabel* realtimeButtonNameLabel = new QLabel("Buttons"); realtimeButtonNameLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); previewGridLayout->addWidget(realtimeButtonNameLabel, realTimePreviewLabelCounter, 0); - previewGridLayout->addWidget(mPreviewLabels[GameController::NUM_ELEMENTS], realTimePreviewLabelCounter, 1, Qt::AlignLeft); + previewGridLayout->addWidget(m_previewLabels[GameController::NUM_ELEMENTS], realTimePreviewLabelCounter, 1, Qt::AlignLeft); // add the dead zone elements QHBoxLayout* deadZoneLayout = new QHBoxLayout(); @@ -568,26 +568,26 @@ namespace EMStudio deadZoneLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); previewGridLayout->addWidget(deadZoneLabel, realTimePreviewLabelCounter + 1, 0); - mDeadZoneSlider = new AzQtComponents::SliderInt(Qt::Horizontal); - mDeadZoneSlider->setRange(1, 90); - mDeadZoneSlider->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); - deadZoneLayout->addWidget(mDeadZoneSlider); + m_deadZoneSlider = new AzQtComponents::SliderInt(Qt::Horizontal); + m_deadZoneSlider->setRange(1, 90); + m_deadZoneSlider->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + deadZoneLayout->addWidget(m_deadZoneSlider); - mDeadZoneValueLabel = new QLabel(); - deadZoneLayout->addWidget(mDeadZoneValueLabel); + m_deadZoneValueLabel = new QLabel(); + deadZoneLayout->addWidget(m_deadZoneValueLabel); previewGridLayout->addLayout(deadZoneLayout, realTimePreviewLabelCounter + 1, 1); - mDeadZoneSlider->setValue(aznumeric_cast(mGameController->GetDeadZone() * 100)); - mString = AZStd::string::format("%.2f", mGameController->GetDeadZone()); - mDeadZoneValueLabel->setText(mString.c_str()); - connect(mDeadZoneSlider, &AzQtComponents::SliderInt::valueChanged, this, &GameControllerWindow::OnDeadZoneSliderChanged); + m_deadZoneSlider->setValue(aznumeric_cast(m_gameController->GetDeadZone() * 100)); + m_string = AZStd::string::format("%.2f", m_gameController->GetDeadZone()); + m_deadZoneValueLabel->setText(m_string.c_str()); + connect(m_deadZoneSlider, &AzQtComponents::SliderInt::valueChanged, this, &GameControllerWindow::OnDeadZoneSliderChanged); #endif // start the timers - mInterfaceTimer.start(1000 / 20, this); - mInterfaceTimerID = mInterfaceTimer.timerId(); - mGameControllerTimer.start(1000 / 100, this); - mGameControllerTimerID = mGameControllerTimer.timerId(); + m_interfaceTimer.start(1000 / 20, this); + m_interfaceTimerId = m_interfaceTimer.timerId(); + m_gameControllerTimer.start(1000 / 100, this); + m_gameControllerTimerId = m_gameControllerTimer.timerId(); // create the vertical layout for the parameter and the button setup QVBoxLayout* verticalLayout = new QVBoxLayout(); @@ -595,34 +595,34 @@ namespace EMStudio //////////////////////////// - mPresetComboBox->blockSignals(true); - mPresetComboBox->clear(); + m_presetComboBox->blockSignals(true); + m_presetComboBox->clear(); // add the presets to the combo box for (size_t i = 0; i < numPresets; ++i) { - mPresetComboBox->addItem(gameControllerSettings.GetPreset(i)->GetName()); + m_presetComboBox->addItem(gameControllerSettings.GetPreset(i)->GetName()); } // select the active preset const size_t activePresetIndex = gameControllerSettings.GetActivePresetIndex(); if (activePresetIndex != InvalidIndex) { - mPresetComboBox->setCurrentIndex(aznumeric_caster(activePresetIndex)); + m_presetComboBox->setCurrentIndex(aznumeric_caster(activePresetIndex)); } - mPresetComboBox->blockSignals(false); + m_presetComboBox->blockSignals(false); // set the name of the active preset if (gameControllerSettings.GetActivePreset()) { - mPresetNameLineEdit->blockSignals(true); - mPresetNameLineEdit->setText(gameControllerSettings.GetActivePreset()->GetName()); - mPresetNameLineEdit->blockSignals(false); + m_presetNameLineEdit->blockSignals(true); + m_presetNameLineEdit->setText(gameControllerSettings.GetActivePreset()->GetName()); + m_presetNameLineEdit->blockSignals(false); } - mPresetComboBox->setEnabled(true); - mPresetNameLineEdit->setEnabled(true); - mAddPresetButton->setEnabled(true); - mRemovePresetButton->setEnabled(true); + m_presetComboBox->setEnabled(true); + m_presetNameLineEdit->setEnabled(true); + m_addPresetButton->setEnabled(true); + m_removePresetButton->setEnabled(true); //////////////////////////// @@ -658,9 +658,9 @@ namespace EMStudio buttonNameLayout->addWidget(spacerItem); verticalLayout->addLayout(parameterNameLayout); - verticalLayout->addLayout(mParameterGridLayout); + verticalLayout->addLayout(m_parameterGridLayout); verticalLayout->addLayout(buttonNameLayout); - verticalLayout->addLayout(mButtonGridLayout); + verticalLayout->addLayout(m_buttonGridLayout); // main dynamic widget layout QHBoxLayout* dynamicWidgetLayout = new QHBoxLayout(); @@ -679,18 +679,18 @@ namespace EMStudio dynamicWidgetLayout->addWidget(realTimePreviewWidget); dynamicWidgetLayout->setAlignment(realTimePreviewWidget, Qt::AlignTop); #endif - mDynamicWidget->setLayout(dynamicWidgetLayout); + m_dynamicWidget->setLayout(dynamicWidgetLayout); - mDialogStack->Add(mDynamicWidget, "Game Controller Mapping", false, true); + m_dialogStack->Add(m_dynamicWidget, "Game Controller Mapping", false, true); } void GameControllerWindow::OnDeadZoneSliderChanged(int value) { #if AZ_TRAIT_EMOTIONFX_HAS_GAME_CONTROLLER - mGameController->SetDeadZone(value * 0.01f); - mString = AZStd::string::format("%.2f", value * 0.01f); - mDeadZoneValueLabel->setText(mString.c_str()); + m_gameController->SetDeadZone(value * 0.01f); + m_string = AZStd::string::format("%.2f", value * 0.01f); + m_deadZoneValueLabel->setText(m_string.c_str()); #else MCORE_UNUSED(value); #endif @@ -700,22 +700,22 @@ namespace EMStudio GameControllerWindow::ButtonInfo* GameControllerWindow::FindButtonInfo(QWidget* widget) { // get the number of button infos and iterate through them - const auto foundButtonInfo = AZStd::find_if(begin(mButtonInfos), end(mButtonInfos), [widget](const ButtonInfo& buttonInfo) + const auto foundButtonInfo = AZStd::find_if(begin(m_buttonInfos), end(m_buttonInfos), [widget](const ButtonInfo& buttonInfo) { - return buttonInfo.mWidget == widget; + return buttonInfo.m_widget == widget; }); - return foundButtonInfo != end(mButtonInfos) ? &(*foundButtonInfo) : nullptr; + return foundButtonInfo != end(m_buttonInfos) ? &(*foundButtonInfo) : nullptr; } GameControllerWindow::ParameterInfo* GameControllerWindow::FindParamInfoByModeComboBox(QComboBox* comboBox) { // get the number of parameter infos and iterate through them - const auto foundParameterInfo = AZStd::find_if(begin(mParameterInfos), end(mParameterInfos), [comboBox](const ParameterInfo& parameterInfo) + const auto foundParameterInfo = AZStd::find_if(begin(m_parameterInfos), end(m_parameterInfos), [comboBox](const ParameterInfo& parameterInfo) { - return parameterInfo.mMode == comboBox; + return parameterInfo.m_mode == comboBox; }); - return foundParameterInfo != end(mParameterInfos) ? &(*foundParameterInfo) : nullptr; + return foundParameterInfo != end(m_parameterInfos) ? &(*foundParameterInfo) : nullptr; } @@ -723,30 +723,30 @@ namespace EMStudio GameControllerWindow::ParameterInfo* GameControllerWindow::FindButtonInfoByAttributeInfo(const EMotionFX::Parameter* parameter) { // get the number of parameter infos and iterate through them - const auto foundParameterInfo = AZStd::find_if(begin(mParameterInfos), end(mParameterInfos), [parameter](const ParameterInfo& parameterInfo) + const auto foundParameterInfo = AZStd::find_if(begin(m_parameterInfos), end(m_parameterInfos), [parameter](const ParameterInfo& parameterInfo) { - return parameterInfo.mParameter == parameter; + return parameterInfo.m_parameter == parameter; }); - return foundParameterInfo != end(mParameterInfos) ? &(*foundParameterInfo) : nullptr; + return foundParameterInfo != end(m_parameterInfos) ? &(*foundParameterInfo) : nullptr; } // enable/disable controls for a given parameter void GameControllerWindow::UpdateParameterInterface(ParameterInfo* parameterInfo) { - int comboAxisIndex = parameterInfo->mAxis->currentIndex(); + int comboAxisIndex = parameterInfo->m_axis->currentIndex(); if (comboAxisIndex == 0) // None { - parameterInfo->mMode->setEnabled(false); - parameterInfo->mInvert->setEnabled(false); - parameterInfo->mValue->setEnabled(false); - parameterInfo->mValue->setText(""); + parameterInfo->m_mode->setEnabled(false); + parameterInfo->m_invert->setEnabled(false); + parameterInfo->m_value->setEnabled(false); + parameterInfo->m_value->setText(""); } else // some mode set { - parameterInfo->mMode->setEnabled(true); - parameterInfo->mInvert->setEnabled(true); - parameterInfo->mValue->setEnabled(true); + parameterInfo->m_mode->setEnabled(true); + parameterInfo->m_invert->setEnabled(true); + parameterInfo->m_value->setEnabled(true); } } @@ -756,7 +756,7 @@ namespace EMStudio MCORE_UNUSED(value); // get the game controller settings from the current anim graph - EMotionFX::AnimGraphGameControllerSettings& gameControllerSettings = mAnimGraph->GetGameControllerSettings(); + EMotionFX::AnimGraphGameControllerSettings& gameControllerSettings = m_animGraph->GetGameControllerSettings(); // get the active preset EMotionFX::AnimGraphGameControllerSettings::Preset* activePreset = gameControllerSettings.GetActivePreset(); @@ -772,7 +772,7 @@ namespace EMStudio return; } - EMotionFX::AnimGraphGameControllerSettings::ParameterInfo* settingsInfo = activePreset->FindParameterInfo(paramInfo->mParameter->GetName().c_str()); + EMotionFX::AnimGraphGameControllerSettings::ParameterInfo* settingsInfo = activePreset->FindParameterInfo(paramInfo->m_parameter->GetName().c_str()); MCORE_ASSERT(settingsInfo); settingsInfo->m_mode = (EMotionFX::AnimGraphGameControllerSettings::ParameterMode)combo->currentIndex(); } @@ -781,7 +781,7 @@ namespace EMStudio void GameControllerWindow::ReInitButtonInterface(uint32 buttonIndex) { // get the game controller settings from the current anim graph - EMotionFX::AnimGraphGameControllerSettings& gameControllerSettings = mAnimGraph->GetGameControllerSettings(); + EMotionFX::AnimGraphGameControllerSettings& gameControllerSettings = m_animGraph->GetGameControllerSettings(); // get the active preset EMotionFX::AnimGraphGameControllerSettings::Preset* activePreset = gameControllerSettings.GetActivePreset(); @@ -794,7 +794,7 @@ namespace EMStudio MCORE_ASSERT(settingsInfo); // remove the old widget - QLayoutItem* oldLayoutItem = mButtonGridLayout->itemAtPosition(buttonIndex, 2); + QLayoutItem* oldLayoutItem = m_buttonGridLayout->itemAtPosition(buttonIndex, 2); if (oldLayoutItem) { QWidget* oldWidget = oldLayoutItem->widget(); @@ -850,7 +850,7 @@ namespace EMStudio layout->setMargin(0); QComboBox* comboBox = new QComboBox(); - const EMotionFX::ValueParameterVector& valueParameters = mAnimGraph->RecursivelyGetValueParameters(); + const EMotionFX::ValueParameterVector& valueParameters = m_animGraph->RecursivelyGetValueParameters(); for (const EMotionFX::ValueParameter* valueParameter : valueParameters) { if (azrtti_typeid(valueParameter) == azrtti_typeid() || @@ -888,7 +888,7 @@ namespace EMStudio if (widget) { - mButtonGridLayout->addWidget(widget, buttonIndex, 2); + m_buttonGridLayout->addWidget(widget, buttonIndex, 2); } } @@ -905,7 +905,7 @@ namespace EMStudio } // get the game controller settings from the current anim graph - EMotionFX::AnimGraphGameControllerSettings& gameControllerSettings = mAnimGraph->GetGameControllerSettings(); + EMotionFX::AnimGraphGameControllerSettings& gameControllerSettings = m_animGraph->GetGameControllerSettings(); // get the active preset EMotionFX::AnimGraphGameControllerSettings::Preset* activePreset = gameControllerSettings.GetActivePreset(); @@ -936,8 +936,8 @@ namespace EMStudio return; } - settingsInfo->m_string = selectedStates[0].mNodeName.c_str(); - browseEdit->setPlaceholderText(selectedStates[0].mNodeName.c_str()); + settingsInfo->m_string = selectedStates[0].m_nodeName.c_str(); + browseEdit->setPlaceholderText(selectedStates[0].m_nodeName.c_str()); } @@ -947,7 +947,7 @@ namespace EMStudio MCORE_UNUSED(value); // get the game controller settings from the current anim graph - EMotionFX::AnimGraphGameControllerSettings& gameControllerSettings = mAnimGraph->GetGameControllerSettings(); + EMotionFX::AnimGraphGameControllerSettings& gameControllerSettings = m_animGraph->GetGameControllerSettings(); // get the active preset EMotionFX::AnimGraphGameControllerSettings::Preset* activePreset = gameControllerSettings.GetActivePreset(); @@ -963,7 +963,7 @@ namespace EMStudio MCORE_ASSERT(settingsInfo); const AZStd::string parameterName = combo->currentText().toUtf8().data(); - const EMotionFX::Parameter* parameter = mAnimGraph->FindParameterByName(parameterName); + const EMotionFX::Parameter* parameter = m_animGraph->FindParameterByName(parameterName); if (parameter) { settingsInfo->m_string = parameter->GetName(); @@ -974,7 +974,7 @@ namespace EMStudio } // update the parameter window - mPlugin->GetParameterWindow()->Reinit(/*forceReinit*/true); + m_plugin->GetParameterWindow()->Reinit(/*forceReinit*/true); } @@ -984,7 +984,7 @@ namespace EMStudio MCORE_UNUSED(value); // get the game controller settings from the current anim graph - EMotionFX::AnimGraphGameControllerSettings& gameControllerSettings = mAnimGraph->GetGameControllerSettings(); + EMotionFX::AnimGraphGameControllerSettings& gameControllerSettings = m_animGraph->GetGameControllerSettings(); // get the active preset EMotionFX::AnimGraphGameControllerSettings::Preset* activePreset = gameControllerSettings.GetActivePreset(); @@ -1000,7 +1000,7 @@ namespace EMStudio return; } - EMotionFX::AnimGraphGameControllerSettings::ButtonInfo* settingsInfo = activePreset->FindButtonInfo(buttonInfo->mButtonIndex); + EMotionFX::AnimGraphGameControllerSettings::ButtonInfo* settingsInfo = activePreset->FindButtonInfo(buttonInfo->m_buttonIndex); MCORE_ASSERT(settingsInfo); settingsInfo->m_mode = (EMotionFX::AnimGraphGameControllerSettings::ButtonMode)combo->currentIndex(); @@ -1010,7 +1010,7 @@ namespace EMStudio { // The parameter name is empty in case the button info has not been assigned with one yet. // Default it to the first compatible parameter. - const EMotionFX::ValueParameterVector& valueParameters = mAnimGraph->RecursivelyGetValueParameters(); + const EMotionFX::ValueParameterVector& valueParameters = m_animGraph->RecursivelyGetValueParameters(); for (const EMotionFX::ValueParameter* valueParameter : valueParameters) { if (azrtti_typeid(valueParameter) == azrtti_typeid() || @@ -1022,27 +1022,27 @@ namespace EMStudio } } - ReInitButtonInterface(buttonInfo->mButtonIndex); + ReInitButtonInterface(buttonInfo->m_buttonIndex); // update the parameter window - mPlugin->GetParameterWindow()->Reinit(/*forceReinit*/true); + m_plugin->GetParameterWindow()->Reinit(/*forceReinit*/true); } void GameControllerWindow::OnAddPresetButton() { // get the game controller settings from the current anim graph - EMotionFX::AnimGraphGameControllerSettings& gameControllerSettings = mAnimGraph->GetGameControllerSettings(); + EMotionFX::AnimGraphGameControllerSettings& gameControllerSettings = m_animGraph->GetGameControllerSettings(); size_t presetNumber = gameControllerSettings.GetNumPresets(); - mString = AZStd::string::format("Preset %zu", presetNumber); - while (gameControllerSettings.FindPresetIndexByName(mString.c_str()) != InvalidIndex) + m_string = AZStd::string::format("Preset %zu", presetNumber); + while (gameControllerSettings.FindPresetIndexByName(m_string.c_str()) != InvalidIndex) { presetNumber++; - mString = AZStd::string::format("Preset %zu", presetNumber); + m_string = AZStd::string::format("Preset %zu", presetNumber); } - EMotionFX::AnimGraphGameControllerSettings::Preset* preset = aznew EMotionFX::AnimGraphGameControllerSettings::Preset(mString.c_str()); + EMotionFX::AnimGraphGameControllerSettings::Preset* preset = aznew EMotionFX::AnimGraphGameControllerSettings::Preset(m_string.c_str()); gameControllerSettings.AddPreset(preset); ReInit(); @@ -1054,7 +1054,7 @@ namespace EMStudio MCORE_UNUSED(value); // get the game controller settings from the current anim graph - EMotionFX::AnimGraphGameControllerSettings& gameControllerSettings = mAnimGraph->GetGameControllerSettings(); + EMotionFX::AnimGraphGameControllerSettings& gameControllerSettings = m_animGraph->GetGameControllerSettings(); QComboBox* combo = qobject_cast(sender()); EMotionFX::AnimGraphGameControllerSettings::Preset* preset = gameControllerSettings.GetPreset(combo->currentIndex()); @@ -1067,9 +1067,9 @@ namespace EMStudio void GameControllerWindow::OnRemovePresetButton() { // get the game controller settings from the current anim graph - EMotionFX::AnimGraphGameControllerSettings& gameControllerSettings = mAnimGraph->GetGameControllerSettings(); + EMotionFX::AnimGraphGameControllerSettings& gameControllerSettings = m_animGraph->GetGameControllerSettings(); - uint32 presetIndex = mPresetComboBox->currentIndex(); + uint32 presetIndex = m_presetComboBox->currentIndex(); gameControllerSettings.RemovePreset(presetIndex); EMotionFX::AnimGraphGameControllerSettings::Preset* preset = nullptr; @@ -1094,7 +1094,7 @@ namespace EMStudio void GameControllerWindow::OnPresetNameChanged() { // get the game controller settings from the current anim graph - EMotionFX::AnimGraphGameControllerSettings& gameControllerSettings = mAnimGraph->GetGameControllerSettings(); + EMotionFX::AnimGraphGameControllerSettings& gameControllerSettings = m_animGraph->GetGameControllerSettings(); assert(sender()->inherits("QLineEdit")); QLineEdit* widget = qobject_cast(sender()); @@ -1102,7 +1102,7 @@ namespace EMStudio FromQtString(widget->text(), &newValue); // get the currently selected preset - uint32 presetIndex = mPresetComboBox->currentIndex(); + uint32 presetIndex = m_presetComboBox->currentIndex(); size_t newValueIndex = gameControllerSettings.FindPresetIndexByName(newValue.c_str()); if (newValueIndex == InvalidIndex) @@ -1117,28 +1117,28 @@ namespace EMStudio void GameControllerWindow::OnPresetNameEdited(const QString& text) { // get the game controller settings from the current anim graph - EMotionFX::AnimGraphGameControllerSettings& gameControllerSettings = mAnimGraph->GetGameControllerSettings(); + EMotionFX::AnimGraphGameControllerSettings& gameControllerSettings = m_animGraph->GetGameControllerSettings(); // check if there already is a preset with the currently entered name size_t presetIndex = gameControllerSettings.FindPresetIndexByName(FromQtString(text).c_str()); if (presetIndex != InvalidIndex && presetIndex != gameControllerSettings.GetActivePresetIndex()) { - GetManager()->SetWidgetAsInvalidInput(mPresetNameLineEdit); + GetManager()->SetWidgetAsInvalidInput(m_presetNameLineEdit); } else { - mPresetNameLineEdit->setStyleSheet(""); + m_presetNameLineEdit->setStyleSheet(""); } } GameControllerWindow::ParameterInfo* GameControllerWindow::FindParamInfoByAxisComboBox(QComboBox* comboBox) { - const auto foundParameterInfo = AZStd::find_if(begin(mParameterInfos), end(mParameterInfos), [comboBox](const ParameterInfo& parameterInfo) + const auto foundParameterInfo = AZStd::find_if(begin(m_parameterInfos), end(m_parameterInfos), [comboBox](const ParameterInfo& parameterInfo) { - return parameterInfo.mAxis == comboBox; + return parameterInfo.m_axis == comboBox; }); - return foundParameterInfo != end(mParameterInfos) ? &(*foundParameterInfo) : nullptr; + return foundParameterInfo != end(m_parameterInfos) ? &(*foundParameterInfo) : nullptr; } @@ -1147,7 +1147,7 @@ namespace EMStudio MCORE_UNUSED(value); // get the game controller settings from the current anim graph - EMotionFX::AnimGraphGameControllerSettings& gameControllerSettings = mAnimGraph->GetGameControllerSettings(); + EMotionFX::AnimGraphGameControllerSettings& gameControllerSettings = m_animGraph->GetGameControllerSettings(); // get the active preset EMotionFX::AnimGraphGameControllerSettings::Preset* activePreset = gameControllerSettings.GetActivePreset(); @@ -1163,13 +1163,13 @@ namespace EMStudio return; } - EMotionFX::AnimGraphGameControllerSettings::ParameterInfo* settingsInfo = activePreset->FindParameterInfo(paramInfo->mParameter->GetName().c_str()); + EMotionFX::AnimGraphGameControllerSettings::ParameterInfo* settingsInfo = activePreset->FindParameterInfo(paramInfo->m_parameter->GetName().c_str()); MCORE_ASSERT(settingsInfo); #if AZ_TRAIT_EMOTIONFX_HAS_GAME_CONTROLLER - if (azrtti_istypeof(paramInfo->mParameter)) + if (azrtti_istypeof(paramInfo->m_parameter)) { - const uint32 elementID = mGameController->FindElementIDByName(FromQtString(combo->currentText()).c_str()); + const uint32 elementID = m_gameController->FindElementIDByName(FromQtString(combo->currentText()).c_str()); if (elementID >= MCORE_INVALIDINDEX8) { settingsInfo->m_axis = MCORE_INVALIDINDEX8; @@ -1180,7 +1180,7 @@ namespace EMStudio } } else - if (azrtti_typeid(paramInfo->mParameter) == azrtti_typeid()) + if (azrtti_typeid(paramInfo->m_parameter) == azrtti_typeid()) { if (value == 0) { @@ -1199,17 +1199,17 @@ namespace EMStudio UpdateParameterInterface(paramInfo); // update the parameter window - mPlugin->GetParameterWindow()->Reinit(/*forceReinit*/true); + m_plugin->GetParameterWindow()->Reinit(/*forceReinit*/true); } GameControllerWindow::ParameterInfo* GameControllerWindow::FindParamInfoByCheckBox(QCheckBox* checkBox) { - const auto foundParameterInfo = AZStd::find_if(begin(mParameterInfos), end(mParameterInfos), [checkBox](const ParameterInfo& parameterInfo) + const auto foundParameterInfo = AZStd::find_if(begin(m_parameterInfos), end(m_parameterInfos), [checkBox](const ParameterInfo& parameterInfo) { - return parameterInfo.mInvert == checkBox; + return parameterInfo.m_invert == checkBox; }); - return foundParameterInfo != end(mParameterInfos) ? &(*foundParameterInfo) : nullptr; + return foundParameterInfo != end(m_parameterInfos) ? &(*foundParameterInfo) : nullptr; } @@ -1218,7 +1218,7 @@ namespace EMStudio MCORE_UNUSED(state); // get the game controller settings from the current anim graph - EMotionFX::AnimGraphGameControllerSettings& gameControllerSettings = mAnimGraph->GetGameControllerSettings(); + EMotionFX::AnimGraphGameControllerSettings& gameControllerSettings = m_animGraph->GetGameControllerSettings(); // get the active preset EMotionFX::AnimGraphGameControllerSettings::Preset* activePreset = gameControllerSettings.GetActivePreset(); @@ -1234,7 +1234,7 @@ namespace EMStudio return; } - EMotionFX::AnimGraphGameControllerSettings::ParameterInfo* settingsInfo = activePreset->FindParameterInfo(paramInfo->mParameter->GetName().c_str()); + EMotionFX::AnimGraphGameControllerSettings::ParameterInfo* settingsInfo = activePreset->FindParameterInfo(paramInfo->m_parameter->GetName().c_str()); MCORE_ASSERT(settingsInfo); settingsInfo->m_invert = checkBox->checkState() == Qt::Checked ? true : false; } @@ -1248,7 +1248,7 @@ namespace EMStudio UpdateGameControllerComboBox(); AutoSelectGameController(); ReInit(); - mPlugin->GetParameterWindow()->Reinit(/*forceReinit*/true); + m_plugin->GetParameterWindow()->Reinit(/*forceReinit*/true); } @@ -1266,10 +1266,10 @@ namespace EMStudio // update the game controller #if AZ_TRAIT_EMOTIONFX_HAS_GAME_CONTROLLER - mGameController->Update(); + m_gameController->Update(); // check if the game controller is usable and if we have actually checked it in the combobox, if not return directly - if (mGameController->GetIsValid() == false || mGameControllerComboBox->currentIndex() == 0) + if (m_gameController->GetIsValid() == false || m_gameControllerComboBox->currentIndex() == 0) { return; } @@ -1290,7 +1290,7 @@ namespace EMStudio animGraphInstance = actorInstance->GetAnimGraphInstance(); if (animGraphInstance) { - if (animGraphInstance->GetAnimGraph() != mAnimGraph) // if the selected anim graph instance isn't equal to the one of the actor instance + if (animGraphInstance->GetAnimGraph() != m_animGraph) // if the selected anim graph instance isn't equal to the one of the actor instance { return; } @@ -1301,7 +1301,7 @@ namespace EMStudio } // get the game controller settings from the anim graph - EMotionFX::AnimGraphGameControllerSettings& gameControllerSettings = mAnimGraph->GetGameControllerSettings(); + EMotionFX::AnimGraphGameControllerSettings& gameControllerSettings = m_animGraph->GetGameControllerSettings(); // get the active preset EMotionFX::AnimGraphGameControllerSettings::Preset* activePreset = gameControllerSettings.GetActivePreset(); @@ -1310,10 +1310,10 @@ namespace EMStudio return; } - const float timeDelta = mDeltaTimer.StampAndGetDeltaTimeInSeconds(); + const float timeDelta = m_deltaTimer.StampAndGetDeltaTimeInSeconds(); // get the number of parameters and iterate through them - const EMotionFX::ValueParameterVector& valueParameters = mAnimGraph->RecursivelyGetValueParameters(); + const EMotionFX::ValueParameterVector& valueParameters = m_animGraph->RecursivelyGetValueParameters(); const size_t valueParametersCount = valueParameters.size(); for (size_t parameterIndex = 0; parameterIndex < valueParametersCount; ++parameterIndex) { @@ -1334,7 +1334,7 @@ namespace EMStudio if (attribute->GetType() == MCore::AttributeFloat::TYPE_ID) { // get the current value from the game controller - float value = mGameController->GetValue(settingsInfo->m_axis); + float value = m_gameController->GetValue(settingsInfo->m_axis); const EMotionFX::FloatParameter* floatParameter = static_cast(valueParameter); const float minValue = floatParameter->GetMinValue(); const float maxValue = floatParameter->GetMaxValue(); @@ -1421,7 +1421,7 @@ namespace EMStudio // only process in case the parameter info is enabled if (settingsInfo->m_enabled) { - AZ::Quaternion localRot = actorInstance->GetLocalSpaceTransform().mRotation; + AZ::Quaternion localRot = actorInstance->GetLocalSpaceTransform().m_rotation; localRot = localRot * MCore::CreateFromAxisAndAngle(AZ::Vector3(0.0f, 0.0f, 1.0f), value * timeDelta * 3.0f); actorInstance->SetLocalSpaceRotation(localRot); } @@ -1438,20 +1438,20 @@ namespace EMStudio } // check if we also need to update the attribute widget in the parameter window - if (event->timerId() == mInterfaceTimerID) + if (event->timerId() == m_interfaceTimerId) { // find the corresponding attribute widget and set the value in case the parameter info is enabled if (settingsInfo->m_enabled) { - mPlugin->GetParameterWindow()->UpdateParameterValue(valueParameter); + m_plugin->GetParameterWindow()->UpdateParameterValue(valueParameter); } // also update the preview value in the game controller window ParameterInfo* interfaceParamInfo = FindButtonInfoByAttributeInfo(valueParameter); if (interfaceParamInfo) { - mString = AZStd::string::format("%.2f", value); - interfaceParamInfo->mValue->setText(mString.c_str()); + m_string = AZStd::string::format("%.2f", value); + interfaceParamInfo->m_value->setText(m_string.c_str()); } } } // if it's a float attribute @@ -1461,13 +1461,13 @@ namespace EMStudio AZ::Vector2 value(0.0f, 0.0f); if (settingsInfo->m_axis == 0) { - value.SetX(mGameController->GetValue(GameController::ELEM_POS_X)); - value.SetY(mGameController->GetValue(GameController::ELEM_POS_Y)); + value.SetX(m_gameController->GetValue(GameController::ELEM_POS_X)); + value.SetY(m_gameController->GetValue(GameController::ELEM_POS_Y)); } else { - value.SetX(mGameController->GetValue(GameController::ELEM_ROT_X)); - value.SetY(mGameController->GetValue(GameController::ELEM_ROT_Y)); + value.SetX(m_gameController->GetValue(GameController::ELEM_ROT_X)); + value.SetY(m_gameController->GetValue(GameController::ELEM_ROT_Y)); } const EMotionFX::Vector2Parameter* vector2Parameter = static_cast(valueParameter); @@ -1577,7 +1577,7 @@ namespace EMStudio // only process in case the parameter info is enabled if (settingsInfo->m_enabled) { - AZ::Quaternion localRot = actorInstance->GetLocalSpaceTransform().mRotation; + AZ::Quaternion localRot = actorInstance->GetLocalSpaceTransform().m_rotation; localRot = localRot * MCore::CreateFromAxisAndAngle(AZ::Vector3(0.0f, 0.0f, 1.0f), value.GetX() * timeDelta * 3.0f); actorInstance->SetLocalSpaceRotation(localRot); } @@ -1596,30 +1596,30 @@ namespace EMStudio } // check if we also need to update the attribute widget in the parameter window - if (event->timerId() == mInterfaceTimerID) + if (event->timerId() == m_interfaceTimerId) { // find the corresponding attribute widget and set the value in case the parameter info is enabled if (settingsInfo->m_enabled) { - mPlugin->GetParameterWindow()->UpdateParameterValue(valueParameter); + m_plugin->GetParameterWindow()->UpdateParameterValue(valueParameter); } // also update the preview value in the game controller window ParameterInfo* interfaceParamInfo = FindButtonInfoByAttributeInfo(valueParameter); if (interfaceParamInfo) { - mString = AZStd::string::format("%.2f, %.2f", value.GetX(), value.GetY()); - interfaceParamInfo->mValue->setText(mString.c_str()); + m_string = AZStd::string::format("%.2f, %.2f", value.GetX(), value.GetY()); + interfaceParamInfo->m_value->setText(m_string.c_str()); } } } // if it's a vector2 attribute } // for all parameters // update the buttons - const uint32 numButtons = mGameController->GetNumButtons(); + const uint32 numButtons = m_gameController->GetNumButtons(); for (uint32 i = 0; i < numButtons; ++i) { - const bool isPressed = mGameController->GetIsButtonPressed(i); + const bool isPressed = m_gameController->GetIsButtonPressed(i); // get the game controller settings info for the given button EMotionFX::AnimGraphGameControllerSettings::ButtonInfo* settingsInfo = activePreset->FindButtonInfo(i); @@ -1637,7 +1637,7 @@ namespace EMStudio } // Find the corresponding value parameter. - const AZ::Outcome parameterIndex = mAnimGraph->FindValueParameterIndexByName(settingsInfo->m_string); + const AZ::Outcome parameterIndex = m_animGraph->FindValueParameterIndexByName(settingsInfo->m_string); MCore::AttributeBool* boolAttribute = nullptr; if (parameterIndex.IsSuccess()) @@ -1680,10 +1680,10 @@ namespace EMStudio } // check if we also need to update the attribute widget in the parameter window - if (event->timerId() == mInterfaceTimerID) + if (event->timerId() == m_interfaceTimerId) { - const EMotionFX::ValueParameter* valueParameter = mAnimGraph->FindValueParameter(parameterIndex.GetValue()); - mPlugin->GetParameterWindow()->UpdateParameterValue(valueParameter); + const EMotionFX::ValueParameter* valueParameter = m_animGraph->FindValueParameter(parameterIndex.GetValue()); + m_plugin->GetParameterWindow()->UpdateParameterValue(valueParameter); } } @@ -1697,10 +1697,10 @@ namespace EMStudio boolAttribute->SetValue(isPressed ? true : false); // check if we also need to update the attribute widget in the parameter window - if (event->timerId() == mInterfaceTimerID) + if (event->timerId() == m_interfaceTimerId) { - const EMotionFX::ValueParameter* valueParameter = mAnimGraph->FindValueParameter(parameterIndex.GetValue()); - mPlugin->GetParameterWindow()->UpdateParameterValue(valueParameter); + const EMotionFX::ValueParameter* valueParameter = m_animGraph->FindValueParameter(parameterIndex.GetValue()); + m_plugin->GetParameterWindow()->UpdateParameterValue(valueParameter); } } @@ -1714,10 +1714,10 @@ namespace EMStudio boolAttribute->SetValue((!isPressed) ? true : false); // check if we also need to update the attribute widget in the parameter window - if (event->timerId() == mInterfaceTimerID) + if (event->timerId() == m_interfaceTimerId) { - const EMotionFX::ValueParameter* valueParameter = mAnimGraph->FindValueParameter(parameterIndex.GetValue()); - mPlugin->GetParameterWindow()->UpdateParameterValue(valueParameter); + const EMotionFX::ValueParameter* valueParameter = m_animGraph->FindValueParameter(parameterIndex.GetValue()); + m_plugin->GetParameterWindow()->UpdateParameterValue(valueParameter); } } @@ -1751,10 +1751,10 @@ namespace EMStudio } // check if we also need to update the attribute widget in the parameter window - if (event->timerId() == mInterfaceTimerID) + if (event->timerId() == m_interfaceTimerId) { - const EMotionFX::ValueParameter* valueParameter = mAnimGraph->FindValueParameter(parameterIndex.GetValue()); - mPlugin->GetParameterWindow()->UpdateParameterValue(valueParameter); + const EMotionFX::ValueParameter* valueParameter = m_animGraph->FindValueParameter(parameterIndex.GetValue()); + m_plugin->GetParameterWindow()->UpdateParameterValue(valueParameter); } } @@ -1767,43 +1767,43 @@ namespace EMStudio } // check if the interface timer is ticking - if (event->timerId() == mInterfaceTimerID) + if (event->timerId() == m_interfaceTimerId) { // update the interface elements for (uint32 i = 0; i < GameController::NUM_ELEMENTS; ++i) { - if (mGameController->GetIsPresent(i)) + if (m_gameController->GetIsPresent(i)) { - const float value = mGameController->GetValue(i); + const float value = m_gameController->GetValue(i); if (value > 1000.0f) { - mString.clear(); + m_string.clear(); } else { - mString = AZStd::string::format("%.2f", value); + m_string = AZStd::string::format("%.2f", value); } - mPreviewLabels[i]->setText(mString.c_str()); + m_previewLabels[i]->setText(m_string.c_str()); } } // update the active button string - mString.clear(); + m_string.clear(); for (uint32 i = 0; i < numButtons; ++i) { - if (mGameController->GetIsButtonPressed(i)) + if (m_gameController->GetIsButtonPressed(i)) { - mString += AZStd::string::format("%s%d ", (i < 10) ? "0" : "", i); + m_string += AZStd::string::format("%s%d ", (i < 10) ? "0" : "", i); } } - if (mString.size() == 0) + if (m_string.size() == 0) { - mPreviewLabels[GameController::NUM_ELEMENTS]->setText(" "); + m_previewLabels[GameController::NUM_ELEMENTS]->setText(" "); } else { - mPreviewLabels[GameController::NUM_ELEMENTS]->setText(mString.c_str()); + m_previewLabels[GameController::NUM_ELEMENTS]->setText(m_string.c_str()); } } #endif diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GameControllerWindow.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GameControllerWindow.h index c9ea776337..059108625a 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GameControllerWindow.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GameControllerWindow.h @@ -71,15 +71,15 @@ namespace EMStudio MCORE_INLINE bool GetIsGameControllerValid() const { #if AZ_TRAIT_EMOTIONFX_HAS_GAME_CONTROLLER - if (mGameController == nullptr) + if (m_gameController == nullptr) { return false; } - if (mGameControllerComboBox->currentIndex() == 0) + if (m_gameControllerComboBox->currentIndex() == 0) { return false; } - return mGameController->GetIsValid(); + return m_gameController->GetIsValid(); #else return false; #endif @@ -112,22 +112,22 @@ namespace EMStudio MCORE_DEFINECOMMANDCALLBACK(CommandUnselectCallback); MCORE_DEFINECOMMANDCALLBACK(CommandClearSelectionCallback); - CommandCreateBlendParameterCallback* mCreateCallback; - CommandRemoveBlendParameterCallback* mRemoveCallback; - CommandAdjustBlendParameterCallback* mAdjustCallback; - CommandSelectCallback* mSelectCallback; - CommandUnselectCallback* mUnselectCallback; - CommandClearSelectionCallback* mClearSelectionCallback; + CommandCreateBlendParameterCallback* m_createCallback; + CommandRemoveBlendParameterCallback* m_removeCallback; + CommandAdjustBlendParameterCallback* m_adjustCallback; + CommandSelectCallback* m_selectCallback; + CommandUnselectCallback* m_unselectCallback; + CommandClearSelectionCallback* m_clearSelectionCallback; struct ParameterInfo { MCORE_MEMORYOBJECTCATEGORY(GameControllerWindow::ParameterInfo, EMFX_DEFAULT_ALIGNMENT, MEMCATEGORY_STANDARDPLUGINS_ANIMGRAPH); - const EMotionFX::Parameter* mParameter; - QComboBox* mAxis; - QComboBox* mMode; - QCheckBox* mInvert; - QLineEdit* mValue; + const EMotionFX::Parameter* m_parameter; + QComboBox* m_axis; + QComboBox* m_mode; + QCheckBox* m_invert; + QLineEdit* m_value; }; struct ButtonInfo @@ -135,12 +135,12 @@ namespace EMStudio MCORE_MEMORYOBJECTCATEGORY(GameControllerWindow::ButtonInfo, EMFX_DEFAULT_ALIGNMENT, MEMCATEGORY_STANDARDPLUGINS_ANIMGRAPH); ButtonInfo(uint32 index, QWidget* widget) { - mButtonIndex = index; - mWidget = widget; + m_buttonIndex = index; + m_widget = widget; } - uint32 mButtonIndex; - QWidget* mWidget; + uint32 m_buttonIndex; + QWidget* m_widget; }; ParameterInfo* FindParamInfoByModeComboBox(QComboBox* comboBox); @@ -153,37 +153,37 @@ namespace EMStudio void UpdateParameterInterface(ParameterInfo* parameterInfo); void UpdateGameControllerComboBox(); - AnimGraphPlugin* mPlugin; - AZStd::vector mPreviewLabels; - AZStd::vector mParameterInfos; - AZStd::vector mButtonInfos; - QBasicTimer mInterfaceTimer; - QBasicTimer mGameControllerTimer; - AZ::Debug::Timer mDeltaTimer; - int mInterfaceTimerID; - int mGameControllerTimerID; + AnimGraphPlugin* m_plugin; + AZStd::vector m_previewLabels; + AZStd::vector m_parameterInfos; + AZStd::vector m_buttonInfos; + QBasicTimer m_interfaceTimer; + QBasicTimer m_gameControllerTimer; + AZ::Debug::Timer m_deltaTimer; + int m_interfaceTimerId; + int m_gameControllerTimerId; #if AZ_TRAIT_EMOTIONFX_HAS_GAME_CONTROLLER - GameController* mGameController; + GameController* m_gameController; #endif - EMotionFX::AnimGraph* mAnimGraph; + EMotionFX::AnimGraph* m_animGraph; - MysticQt::DialogStack* mDialogStack; + MysticQt::DialogStack* m_dialogStack; - QWidget* mDynamicWidget; - AzQtComponents::SliderInt* mDeadZoneSlider; - QLabel* mDeadZoneValueLabel; - QGridLayout* mParameterGridLayout; - QGridLayout* mButtonGridLayout; - QComboBox* mGameControllerComboBox; + QWidget* m_dynamicWidget; + AzQtComponents::SliderInt* m_deadZoneSlider; + QLabel* m_deadZoneValueLabel; + QGridLayout* m_parameterGridLayout; + QGridLayout* m_buttonGridLayout; + QComboBox* m_gameControllerComboBox; // preset interface elements - QComboBox* mPresetComboBox; - QLineEdit* mPresetNameLineEdit; - QPushButton* mAddPresetButton; - QPushButton* mRemovePresetButton; + QComboBox* m_presetComboBox; + QLineEdit* m_presetNameLineEdit; + QPushButton* m_addPresetButton; + QPushButton* m_removePresetButton; - AZStd::string mString; + AZStd::string m_string; void timerEvent(QTimerEvent* event); void InitGameController(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GraphNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GraphNode.cpp index 4f29a15669..75cca66e3d 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GraphNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GraphNode.cpp @@ -17,59 +17,59 @@ namespace EMStudio { // statics - QColor GraphNode::mPortHighlightColor = QColor(255, 128, 0); - QColor GraphNode::mPortHighlightBGColor = QColor(128, 64, 0); + QColor GraphNode::s_portHighlightColo = QColor(255, 128, 0); + QColor GraphNode::s_portHighlightBGColor = QColor(128, 64, 0); // constructor GraphNode::GraphNode(const QModelIndex& modelIndex, const char* name, AZ::u16 numInputs, AZ::u16 numOutputs) : m_modelIndex(modelIndex) { - mRect = QRect(0, 0, 200, 128); - mBaseColor = QColor(74, 63, 238); - mVisualizeColor = QColor(0, 255, 0); - mOpacity = 1.0f; - mFinalRect = mRect; - mIsDeletable = true; - mIsHighlighted = false; - mConFromOutputOnly = false; - mIsCollapsed = false; - mIsProcessed = false; - mIsUpdated = false; - mIsEnabled = true; - mVisualize = false; - mCanVisualize = false; - mVisualizeHighlighted = false; - mNameAndPortsUpdated = false; - mCanHaveChildren = false; - mHasVisualGraph = false; - mHasVisualOutputPorts = true; - mMaxInputWidth = 0; - mMaxOutputWidth = 0; + m_rect = QRect(0, 0, 200, 128); + m_baseColor = QColor(74, 63, 238); + m_visualizeColor = QColor(0, 255, 0); + m_opacity = 1.0f; + m_finalRect = m_rect; + m_isDeletable = true; + m_isHighlighted = false; + m_conFromOutputOnly = false; + m_isCollapsed = false; + m_isProcessed = false; + m_isUpdated = false; + m_isEnabled = true; + m_visualize = false; + m_canVisualize = false; + m_visualizeHighlighted = false; + m_nameAndPortsUpdated = false; + m_canHaveChildren = false; + m_hasVisualGraph = false; + m_hasVisualOutputPorts = true; + m_maxInputWidth = 0; + m_maxOutputWidth = 0; - mHeaderFont.setPixelSize(12); - mHeaderFont.setBold(true); - mPortNameFont.setPixelSize(9); - mInfoTextFont.setPixelSize(10); - mInfoTextFont.setBold(true); - mSubTitleFont.setPixelSize(10); + m_headerFont.setPixelSize(12); + m_headerFont.setBold(true); + m_portNameFont.setPixelSize(9); + m_infoTextFont.setPixelSize(10); + m_infoTextFont.setBold(true); + m_subTitleFont.setPixelSize(10); // has child node indicator - mSubstPoly.resize(4); + m_substPoly.resize(4); - mTextOptionsCenter.setAlignment(Qt::AlignCenter); - mTextOptionsCenterHV.setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); - mTextOptionsAlignRight.setAlignment(Qt::AlignRight | Qt::AlignVCenter); - mTextOptionsAlignLeft.setAlignment(Qt::AlignLeft | Qt::AlignVCenter); + m_textOptionsCenter.setAlignment(Qt::AlignCenter); + m_textOptionsCenterHv.setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); + m_textOptionsAlignRight.setAlignment(Qt::AlignRight | Qt::AlignVCenter); + m_textOptionsAlignLeft.setAlignment(Qt::AlignLeft | Qt::AlignVCenter); - mInputPorts.resize(numInputs); - mOutputPorts.resize(numOutputs); + m_inputPorts.resize(numInputs); + m_outputPorts.resize(numOutputs); // initialize the port metrics - mPortFontMetrics = new QFontMetrics(mPortNameFont); - mHeaderFontMetrics = new QFontMetrics(mHeaderFont); - mInfoFontMetrics = new QFontMetrics(mInfoTextFont); - mSubTitleFontMetrics = new QFontMetrics(mSubTitleFont); + m_portFontMetrics = new QFontMetrics(m_portNameFont); + m_headerFontMetrics = new QFontMetrics(m_headerFont); + m_infoFontMetrics = new QFontMetrics(m_infoTextFont); + m_subTitleFontMetrics = new QFontMetrics(m_subTitleFont); SetName(name, false); ResetBorderColor(); @@ -80,10 +80,10 @@ namespace EMStudio GraphNode::~GraphNode() { // delete the font metrics - delete mPortFontMetrics; - delete mHeaderFontMetrics; - delete mInfoFontMetrics; - delete mSubTitleFontMetrics; + delete m_portFontMetrics; + delete m_headerFontMetrics; + delete m_infoFontMetrics; + delete m_subTitleFontMetrics; RemoveAllConnections(); } @@ -93,55 +93,53 @@ namespace EMStudio void GraphNode::UpdateTextPixmap() { // init the title text - mTitleText.setTextOption(mTextOptionsCenter); - mTitleText.setTextFormat(Qt::PlainText); - mTitleText.setPerformanceHint(QStaticText::AggressiveCaching); - mTitleText.setTextWidth(mRect.width()); - mTitleText.setText(mElidedName); - mTitleText.prepare(QTransform(), mHeaderFont); + m_titleText.setTextOption(m_textOptionsCenter); + m_titleText.setTextFormat(Qt::PlainText); + m_titleText.setPerformanceHint(QStaticText::AggressiveCaching); + m_titleText.setTextWidth(m_rect.width()); + m_titleText.setText(m_elidedName); + m_titleText.prepare(QTransform(), m_headerFont); // init the title text - mSubTitleText.setTextOption(mTextOptionsCenter); - mSubTitleText.setTextFormat(Qt::PlainText); - mSubTitleText.setPerformanceHint(QStaticText::AggressiveCaching); - mSubTitleText.setTextWidth(mRect.width()); - mSubTitleText.setText(mElidedSubTitle); - mSubTitleText.prepare(QTransform(), mSubTitleFont); + m_subTitleText.setTextOption(m_textOptionsCenter); + m_subTitleText.setTextFormat(Qt::PlainText); + m_subTitleText.setPerformanceHint(QStaticText::AggressiveCaching); + m_subTitleText.setTextWidth(m_rect.width()); + m_subTitleText.setText(m_elidedSubTitle); + m_subTitleText.prepare(QTransform(), m_subTitleFont); // draw the info text QRect textRect; CalcInfoTextRect(textRect, true); - mInfoText.setTextOption(mTextOptionsCenterHV); - mInfoText.setTextFormat(Qt::PlainText); - mInfoText.setPerformanceHint(QStaticText::AggressiveCaching); - mInfoText.setTextWidth(mRect.width()); - mInfoText.setText(mElidedNodeInfo); - mInfoText.prepare(QTransform(), mSubTitleFont); + m_infoText.setTextOption(m_textOptionsCenterHv); + m_infoText.setTextFormat(Qt::PlainText); + m_infoText.setPerformanceHint(QStaticText::AggressiveCaching); + m_infoText.setTextWidth(m_rect.width()); + m_infoText.setText(m_elidedNodeInfo); + m_infoText.prepare(QTransform(), m_subTitleFont); // input ports - const size_t numInputs = mInputPorts.size(); - mInputPortText.resize(numInputs); + const size_t numInputs = m_inputPorts.size(); + m_inputPortText.resize(numInputs); for (size_t i = 0; i < numInputs; ++i) { - QStaticText& staticText = mInputPortText[i]; + QStaticText& staticText = m_inputPortText[i]; staticText.setTextFormat(Qt::PlainText); staticText.setPerformanceHint(QStaticText::AggressiveCaching); - // staticText.setTextWidth( mRect.width() ); - staticText.setText(mInputPorts[i].GetName()); - staticText.prepare(QTransform(), mPortNameFont); + staticText.setText(m_inputPorts[i].GetName()); + staticText.prepare(QTransform(), m_portNameFont); } // output ports - const size_t numOutputs = mOutputPorts.size(); - mOutputPortText.resize(numOutputs); + const size_t numOutputs = m_outputPorts.size(); + m_outputPortText.resize(numOutputs); for (size_t i = 0; i < numOutputs; ++i) { - QStaticText& staticText = mOutputPortText[i]; + QStaticText& staticText = m_outputPortText[i]; staticText.setTextFormat(Qt::PlainText); staticText.setPerformanceHint(QStaticText::AggressiveCaching); - // staticText.setTextWidth( mRect.width() ); - staticText.setText(mOutputPorts[i].GetName()); - staticText.prepare(QTransform(), mPortNameFont); + staticText.setText(m_outputPorts[i].GetName()); + staticText.prepare(QTransform(), m_portNameFont); } } @@ -149,20 +147,20 @@ namespace EMStudio // remove all node connections void GraphNode::RemoveAllConnections() { - for (NodeConnection* connection : mConnections) + for (NodeConnection* connection : m_connections) { delete connection; } - mConnections.clear(); + m_connections.clear(); } // set the name of the node void GraphNode::SetName(const char* name, bool updatePixmap) { - mName = name; - mElidedName = mHeaderFontMetrics->elidedText(name, Qt::ElideMiddle, MAX_NODEWIDTH); + m_name = name; + m_elidedName = m_headerFontMetrics->elidedText(name, Qt::ElideMiddle, MAX_NODEWIDTH); if (updatePixmap) { @@ -175,8 +173,8 @@ namespace EMStudio void GraphNode::SetSubTitle(const char* subTitle, bool updatePixmap) { - mSubTitle = subTitle; - mElidedSubTitle = mSubTitleFontMetrics->elidedText(subTitle, Qt::ElideMiddle, MAX_NODEWIDTH); + m_subTitle = subTitle; + m_elidedSubTitle = m_subTitleFontMetrics->elidedText(subTitle, Qt::ElideMiddle, MAX_NODEWIDTH); if (updatePixmap) { @@ -189,8 +187,8 @@ namespace EMStudio void GraphNode::SetNodeInfo(const AZStd::string& info) { - mNodeInfo = info; - mElidedNodeInfo = mInfoFontMetrics->elidedText(mNodeInfo.c_str(), Qt::ElideMiddle, MAX_NODEWIDTH - mMaxInputWidth - mMaxOutputWidth); + m_nodeInfo = info; + m_elidedNodeInfo = m_infoFontMetrics->elidedText(m_nodeInfo.c_str(), Qt::ElideMiddle, MAX_NODEWIDTH - m_maxInputWidth - m_maxOutputWidth); UpdateNameAndPorts(); UpdateRects(); @@ -201,18 +199,18 @@ namespace EMStudio void GraphNode::UpdateRects() { // calc window rect - mRect.setWidth(CalcRequiredWidth()); - mRect.setHeight(CalcRequiredHeight()); + m_rect.setWidth(CalcRequiredWidth()); + m_rect.setHeight(CalcRequiredHeight()); // calc the rect in screen space (after scrolling and zooming) - mFinalRect = mParentGraph->GetTransform().mapRect(mRect); + m_finalRect = m_parentGraph->GetTransform().mapRect(m_rect); } // adjust the collapsed state void GraphNode::SetIsCollapsed(bool collapsed) { - mIsCollapsed = collapsed; + m_isCollapsed = collapsed; UpdateRects(); UpdateTextPixmap(); } @@ -224,48 +222,46 @@ namespace EMStudio UpdateRects(); // check if this rect is visible - mIsVisible = mFinalRect.intersects(visibleRect); + m_isVisible = m_finalRect.intersects(visibleRect); // check if the node is visible and skip some calculations in case its not - mIsHighlighted = false; - mVisualizeHighlighted = false; - //if (mIsVisible) - //{ + m_isHighlighted = false; + m_visualizeHighlighted = false; // check if the mouse is over the node, if yes highlight the node - if (mIsVisible && mRect.contains(mousePos)) + if (m_isVisible && m_rect.contains(mousePos)) { - mIsHighlighted = true; + m_isHighlighted = true; } // set the arrow rect - mArrowRect.setCoords(mRect.left() + 5, mRect.top() + 9, mRect.left() + 17, mRect.top() + 20); + m_arrowRect.setCoords(m_rect.left() + 5, m_rect.top() + 9, m_rect.left() + 17, m_rect.top() + 20); // set the visualize rect - mVisualizeRect.setCoords(mRect.right() - 13, mRect.top() + 6, mRect.right() - 5, mRect.top() + 14); + m_visualizeRect.setCoords(m_rect.right() - 13, m_rect.top() + 6, m_rect.right() - 5, m_rect.top() + 14); // update the input ports and reset the port highlight flags - const AZ::u16 numInputPorts = aznumeric_caster(mInputPorts.size()); + const AZ::u16 numInputPorts = aznumeric_caster(m_inputPorts.size()); for (AZ::u16 i = 0; i < numInputPorts; ++i) { - mInputPorts[i].SetRect(CalcInputPortRect(i)); - mInputPorts[i].SetIsHighlighted(false); + m_inputPorts[i].SetRect(CalcInputPortRect(i)); + m_inputPorts[i].SetIsHighlighted(false); } // update the output ports and reset the port highlight flags - const AZ::u16 numOutputPorts = aznumeric_caster(mOutputPorts.size()); + const AZ::u16 numOutputPorts = aznumeric_caster(m_outputPorts.size()); for (AZ::u16 i = 0; i < numOutputPorts; ++i) { - mOutputPorts[i].SetRect(CalcOutputPortRect(i)); - mOutputPorts[i].SetIsHighlighted(false); + m_outputPorts[i].SetRect(CalcOutputPortRect(i)); + m_outputPorts[i].SetIsHighlighted(false); } // update the visualize highlight flag, only do this in case: // the mouse position is inside the node and we haven't zoomed too much out - if (mIsHighlighted && mParentGraph->GetScale() > 0.3f) + if (m_isHighlighted && m_parentGraph->GetScale() > 0.3f) { - if (mCanVisualize && GetIsInsideVisualizeRect(mousePos)) + if (m_canVisualize && GetIsInsideVisualizeRect(mousePos)) { - mVisualizeHighlighted = true; + m_visualizeHighlighted = true; } } @@ -273,11 +269,11 @@ namespace EMStudio // 1. the node is NOT collapsed // 2. we haven't zoomed too much out so that the ports aren't visible anymore // 3. the mouse position is inside the adjusted node rect, adjusted because the ports stand bit out of the node - if (mIsCollapsed == false && mParentGraph->GetScale() > 0.5f && mRect.adjusted(-6, 0, 6, 0).contains(mousePos)) + if (m_isCollapsed == false && m_parentGraph->GetScale() > 0.5f && m_rect.adjusted(-6, 0, 6, 0).contains(mousePos)) { // set the set highlight flags for the input ports bool highlightedPortFound = false; - for (NodePort& inputPort : mInputPorts) + for (NodePort& inputPort : m_inputPorts) { // get the input port and the corresponding rect const QRect& portRect = inputPort.GetRect(); @@ -295,7 +291,7 @@ namespace EMStudio if (highlightedPortFound == false) { // set the set highlight flags for the output ports - for (NodePort& outputPort : mOutputPorts) + for (NodePort& outputPort : m_outputPorts) { // get the output port and the corresponding rect const QRect& portRect = outputPort.GetRect(); @@ -322,7 +318,7 @@ namespace EMStudio void GraphNode::Render(QPainter& painter, QPen* pen, bool renderShadow) { // only render if the given node is visible - if (mIsVisible == false) + if (m_isVisible == false) { return; } @@ -336,8 +332,8 @@ namespace EMStudio RenderShadow(painter); } - float opacityFactor = mOpacity; - if (mIsEnabled == false) + float opacityFactor = m_opacity; + if (m_isEnabled == false) { opacityFactor *= 0.35f; } @@ -358,20 +354,11 @@ namespace EMStudio { borderColor.setRgb(255, 128, 0); - if (mParentGraph->GetScale() > 0.75f) + if (m_parentGraph->GetScale() > 0.75f) { pen->setWidth(2); } } - else - { - /* if (mHasError) - borderColor.setRgb(255,0,0); - else if (mIsProcessed) - borderColor.setRgb(255,0,255); - else - borderColor = mBorderColor;*/ - } // background and header colors QColor bgColor; @@ -381,9 +368,9 @@ namespace EMStudio } else // not selected { - if (mIsEnabled) + if (m_isEnabled) { - bgColor = mBaseColor; + bgColor = m_baseColor; } else { @@ -400,7 +387,7 @@ namespace EMStudio QColor textColor; if (!isSelected) { - if (mIsEnabled) + if (m_isEnabled) { textColor = Qt::white; } @@ -415,30 +402,30 @@ namespace EMStudio } - if (mIsCollapsed == false) + if (m_isCollapsed == false) { // is highlighted/hovered (on-mouse-over effect) - if (mIsHighlighted) + if (m_isHighlighted) { bgColor = bgColor.lighter(120); bgColor2 = bgColor2.lighter(120); } // draw the main rect - QLinearGradient bgGradient(0, mRect.top(), 0, mRect.bottom()); + QLinearGradient bgGradient(0, m_rect.top(), 0, m_rect.bottom()); bgGradient.setColorAt(0.0f, bgColor); bgGradient.setColorAt(1.0f, bgColor2); painter.setBrush(bgGradient); painter.setPen(borderColor); - painter.drawRoundedRect(mRect, BORDER_RADIUS, BORDER_RADIUS); + painter.drawRoundedRect(m_rect, BORDER_RADIUS, BORDER_RADIUS); // if the scale is so small that we can't see those small things anymore - QRect fullHeaderRect(mRect.left(), mRect.top(), mRect.width(), 25); - QRect headerRect(mRect.left(), mRect.top(), mRect.width(), 15); - QRect subHeaderRect(mRect.left(), mRect.top() + 13, mRect.width(), 10); + QRect fullHeaderRect(m_rect.left(), m_rect.top(), m_rect.width(), 25); + QRect headerRect(m_rect.left(), m_rect.top(), m_rect.width(), 15); + QRect subHeaderRect(m_rect.left(), m_rect.top() + 13, m_rect.width(), 10); // if the scale is so small that we can't see those small things anymore - if (mParentGraph->GetScale() < 0.3f) + if (m_parentGraph->GetScale() < 0.3f) { painter.setOpacity(1.0f); painter.setClipping(false); @@ -450,39 +437,28 @@ namespace EMStudio painter.setPen(borderColor); painter.setClipRect(fullHeaderRect, Qt::ReplaceClip); painter.setBrush(headerBgColor); - painter.drawRoundedRect(mRect, BORDER_RADIUS, BORDER_RADIUS); + painter.drawRoundedRect(m_rect, BORDER_RADIUS, BORDER_RADIUS); - // draw header text - // REPLACED BY PIXMAP - /*painter.setBrush( Qt::NoBrush ); - painter.setPen( textColor ); - painter.setFont( mHeaderFont ); - painter.drawText( headerRect, mElidedName, mTextOptionsCenter ); - - painter.setFont( mSubTitleFont ); - painter.setBrush( Qt::NoBrush ); - painter.setPen( textColor ); - painter.drawText( subHeaderRect, mElidedSubTitle, mTextOptionsCenter );*/ painter.setClipping(false); // if the scale is so small that we can't see those small things anymore - if (mParentGraph->GetScale() > 0.5f) + if (m_parentGraph->GetScale() > 0.5f) { QRect textRect; // draw the info text CalcInfoTextRect(textRect); painter.setPen(QColor(255, 128, 0)); - painter.setFont(mInfoTextFont); - painter.drawText(textRect, mElidedNodeInfo, mTextOptionsCenterHV); + painter.setFont(m_infoTextFont); + painter.drawText(textRect, m_elidedNodeInfo, m_textOptionsCenterHv); // draw the input ports QColor portBrushColor, portPenColor; - const AZ::u16 numInputs = aznumeric_caster(mInputPorts.size()); + const AZ::u16 numInputs = aznumeric_caster(m_inputPorts.size()); for (AZ::u16 i = 0; i < numInputs; ++i) { // get the input port and the corresponding rect - NodePort* inputPort = &mInputPorts[i]; + NodePort* inputPort = &m_inputPorts[i]; const QRect& portRect = inputPort->GetRect(); // get and set the pen and brush colors @@ -496,18 +472,18 @@ namespace EMStudio // draw the text CalcInputPortTextRect(i, textRect); painter.setPen(textColor); - painter.setFont(mPortNameFont); - painter.drawText(textRect, inputPort->GetName(), mTextOptionsAlignLeft); + painter.setFont(m_portNameFont); + painter.drawText(textRect, inputPort->GetName(), m_textOptionsAlignLeft); } if (GetHasVisualOutputPorts()) { // draw the output ports - const AZ::u16 numOutputs = aznumeric_caster(mOutputPorts.size()); + const AZ::u16 numOutputs = aznumeric_caster(m_outputPorts.size()); for (AZ::u16 i = 0; i < numOutputs; ++i) { // get the output port and the corresponding rect - NodePort* outputPort = &mOutputPorts[i]; + NodePort* outputPort = &m_outputPorts[i]; const QRect& portRect = outputPort->GetRect(); // get and set the pen and brush colors @@ -521,8 +497,8 @@ namespace EMStudio // draw the text CalcOutputPortTextRect(i, textRect); painter.setPen(textColor); - painter.setFont(mPortNameFont); - painter.drawText(textRect, outputPort->GetName(), mTextOptionsAlignRight); + painter.setFont(m_portNameFont); + painter.drawText(textRect, outputPort->GetName(), m_textOptionsAlignRight); } } } @@ -530,16 +506,16 @@ namespace EMStudio else { // is highlighted/hovered (on-mouse-over effect) - if (mIsHighlighted) + if (m_isHighlighted) { bgColor = bgColor.lighter(160); headerBgColor = headerBgColor.lighter(160); } // if the scale is so small that we can't see those small things anymore - QRect fullHeaderRect(mRect.left(), mRect.top(), mRect.width(), 25); - QRect headerRect(mRect.left(), mRect.top(), mRect.width(), 15); - QRect subHeaderRect(mRect.left(), mRect.top() + 13, mRect.width(), 10); + QRect fullHeaderRect(m_rect.left(), m_rect.top(), m_rect.width(), 25); + QRect headerRect(m_rect.left(), m_rect.top(), m_rect.width(), 15); + QRect subHeaderRect(m_rect.left(), m_rect.top() + 13, m_rect.width(), 10); // draw the header painter.setPen(borderColor); @@ -547,7 +523,7 @@ namespace EMStudio painter.drawRoundedRect(fullHeaderRect, 7.0, 7.0); // if the scale is so small that we can't see those small things anymore - if (mParentGraph->GetScale() < 0.3f) + if (m_parentGraph->GetScale() < 0.3f) { painter.setOpacity(1.0f); return; @@ -560,15 +536,15 @@ namespace EMStudio QTextOption textOptions; textOptions.setAlignment(Qt::AlignCenter); painter.setPen(textColor); - painter.setFont(mHeaderFont); - painter.drawText(headerRect, mElidedName, textOptions); + painter.setFont(m_headerFont); + painter.drawText(headerRect, m_elidedName, textOptions); - painter.setFont(mSubTitleFont); - painter.drawText(subHeaderRect, mElidedSubTitle, textOptions); + painter.setFont(m_subTitleFont); + painter.drawText(subHeaderRect, m_elidedSubTitle, textOptions); painter.setClipping(false); } - if (mParentGraph->GetScale() > 0.3f) + if (m_parentGraph->GetScale() > 0.3f) { // draw the collapse triangle if (isSelected) @@ -582,31 +558,31 @@ namespace EMStudio painter.setBrush(QColor(175, 175, 175)); } - if (mIsCollapsed == false) + if (m_isCollapsed == false) { QPoint triangle[3]; - triangle[0].setX(mArrowRect.left()); - triangle[0].setY(mArrowRect.top()); - triangle[1].setX(mArrowRect.right()); - triangle[1].setY(mArrowRect.top()); - triangle[2].setX(mArrowRect.center().x()); - triangle[2].setY(mArrowRect.bottom()); + triangle[0].setX(m_arrowRect.left()); + triangle[0].setY(m_arrowRect.top()); + triangle[1].setX(m_arrowRect.right()); + triangle[1].setY(m_arrowRect.top()); + triangle[2].setX(m_arrowRect.center().x()); + triangle[2].setY(m_arrowRect.bottom()); painter.drawPolygon(triangle, 3, Qt::WindingFill); } else { QPoint triangle[3]; - triangle[0].setX(mArrowRect.left()); - triangle[0].setY(mArrowRect.top()); - triangle[1].setX(mArrowRect.right()); - triangle[1].setY(mArrowRect.center().y()); - triangle[2].setX(mArrowRect.left()); - triangle[2].setY(mArrowRect.bottom()); + triangle[0].setX(m_arrowRect.left()); + triangle[0].setY(m_arrowRect.top()); + triangle[1].setX(m_arrowRect.right()); + triangle[1].setY(m_arrowRect.center().y()); + triangle[2].setX(m_arrowRect.left()); + triangle[2].setY(m_arrowRect.bottom()); painter.drawPolygon(triangle, 3, Qt::WindingFill); } // draw the visualize area - if (mCanVisualize) + if (m_canVisualize) { RenderVisualizeRect(painter, bgColor, bgColor2); } @@ -614,12 +590,6 @@ namespace EMStudio // render the marker which indicates that you can go inside this node RenderHasChildsIndicator(painter, pen, borderColor, bgColor2); } - - /* // render the text overlay with the pre-baked node name and port names etc. - const float textOpacity = mParentGraph->GetScale(); - painter.setOpacity( textOpacity ); - painter.drawPixmap( mRect, mTextPixmap ); - painter.setOpacity( 1.0f );*/ } @@ -629,10 +599,10 @@ namespace EMStudio MCORE_UNUSED(pen); // render the marker which indicates that you can go inside this node - if (mCanHaveChildren || mHasVisualGraph) + if (m_canHaveChildren || m_hasVisualGraph) { const int indicatorSize = 13; - QRect childIndicatorRect(aznumeric_cast(mRect.right() - indicatorSize - 2 * BORDER_RADIUS), mRect.top(), aznumeric_cast(indicatorSize + 2 * BORDER_RADIUS + 1), aznumeric_cast(indicatorSize + 2 * BORDER_RADIUS)); + QRect childIndicatorRect(aznumeric_cast(m_rect.right() - indicatorSize - 2 * BORDER_RADIUS), m_rect.top(), aznumeric_cast(indicatorSize + 2 * BORDER_RADIUS + 1), aznumeric_cast(indicatorSize + 2 * BORDER_RADIUS)); // set the border color to the same one as the node border painter.setPen(borderColor); @@ -648,10 +618,10 @@ namespace EMStudio } // construct the clipping polygon - mSubstPoly[0] = QPointF(childIndicatorRect.right() - indicatorSize, childIndicatorRect.top()); // top right - mSubstPoly[1] = QPointF(childIndicatorRect.right() - 5 * indicatorSize, childIndicatorRect.top()); // top left - mSubstPoly[2] = QPointF(childIndicatorRect.right() + 1, childIndicatorRect.top() + 5 * indicatorSize);// bottom down - mSubstPoly[3] = QPointF(childIndicatorRect.right() + 1, childIndicatorRect.top() + indicatorSize);// bottom up + m_substPoly[0] = QPointF(childIndicatorRect.right() - indicatorSize, childIndicatorRect.top()); // top right + m_substPoly[1] = QPointF(childIndicatorRect.right() - 5 * indicatorSize, childIndicatorRect.top()); // top left + m_substPoly[2] = QPointF(childIndicatorRect.right() + 1, childIndicatorRect.top() + 5 * indicatorSize);// bottom down + m_substPoly[3] = QPointF(childIndicatorRect.right() + 1, childIndicatorRect.top() + indicatorSize);// bottom up // matched mini rounded rect on top of the node rect QPainterPath path; @@ -659,7 +629,7 @@ namespace EMStudio // substract the clipping polygon from the mini rounded rect QPainterPath substPath; - substPath.addPolygon(mSubstPoly); + substPath.addPolygon(m_substPoly); QPainterPath finalPath = path.subtracted(substPath); // draw the indicator @@ -685,8 +655,8 @@ namespace EMStudio } else { - *outPenColor = mPortHighlightColor; - *outBrushColor = mPortHighlightBGColor; + *outPenColor = s_portHighlightColo; + *outBrushColor = s_portHighlightBGColor; } } } @@ -695,8 +665,8 @@ namespace EMStudio // render the shadow for this node void GraphNode::RenderShadow(QPainter& painter) { - float opacityFactor = mOpacity; - if (mIsEnabled == false) + float opacityFactor = m_opacity; + if (m_isEnabled == false) { opacityFactor = 0.10f; } @@ -706,9 +676,9 @@ namespace EMStudio painter.setBrush(QColor(0, 0, 0, 70)); // normal - if (mIsCollapsed == false) + if (m_isCollapsed == false) { - QRect shadowRect = mRect; + QRect shadowRect = m_rect; shadowRect.translate(3, 4); // draw the shadow rect @@ -716,7 +686,7 @@ namespace EMStudio } else // collapsed { - QRect shadowRect(mRect.left(), mRect.top(), mRect.width(), 25); + QRect shadowRect(m_rect.left(), m_rect.top(), m_rect.width(), 25); shadowRect.translate(3, 4); // draw the shadow rect @@ -731,12 +701,12 @@ namespace EMStudio const bool alwaysColor = GetAlwaysColor(); // for all connections - for (NodeConnection* nodeConnection : mConnections) + for (NodeConnection* nodeConnection : m_connections) { if (nodeConnection->GetIsVisible()) { float opacity = 1.0f; - if (!mIsEnabled) + if (!m_isEnabled) { opacity = 0.25f; } @@ -765,7 +735,7 @@ namespace EMStudio { QColor vizBorder; QColor vizBackGround = bgColor2.lighter(110); - if (mVisualize) + if (m_visualize) { vizBorder = Qt::black; } @@ -774,57 +744,56 @@ namespace EMStudio vizBorder = bgColor.darker(180); } - painter.setPen(mVisualizeHighlighted ? QColor(255, 128, 0) : vizBorder); + painter.setPen(m_visualizeHighlighted ? QColor(255, 128, 0) : vizBorder); if (!GetIsSelected()) { - painter.setBrush(mVisualize ? mVisualizeColor : vizBackGround); + painter.setBrush(m_visualize ? m_visualizeColor : vizBackGround); } else { - painter.setBrush(mVisualize ? QColor(255, 128, 0) : bgColor); + painter.setBrush(m_visualize ? QColor(255, 128, 0) : bgColor); } - painter.drawRect(mVisualizeRect); + painter.drawRect(m_visualizeRect); } // test if a point is inside the node bool GraphNode::GetIsInside(const QPoint& globalPoint) const { - return mFinalRect.contains(globalPoint); + return m_finalRect.contains(globalPoint); } // check if we are selected bool GraphNode::GetIsSelected() const { - return mParentGraph->GetAnimGraphModel().GetSelectionModel().isSelected(m_modelIndex); + return m_parentGraph->GetAnimGraphModel().GetSelectionModel().isSelected(m_modelIndex); } // move the node relatively void GraphNode::MoveRelative(const QPoint& deltaMove) { - mRect.translate(deltaMove); + m_rect.translate(deltaMove); } // move absolute void GraphNode::MoveAbsolute(const QPoint& newUpperLeft) { - const int32 width = mRect.width(); - const int32 height = mRect.height(); - mRect = QRect(newUpperLeft.x(), newUpperLeft.y(), width, height); - //MCore::LOG("MoveAbsolute: (%i, %i, %i, %i)", mRect.top(), mRect.left(), mRect.bottom(), mRect.right()); + const int32 width = m_rect.width(); + const int32 height = m_rect.height(); + m_rect = QRect(newUpperLeft.x(), newUpperLeft.y(), width, height); } // calculate the height (including title and bottom) int32 GraphNode::CalcRequiredHeight() const { - if (mIsCollapsed == false) + if (m_isCollapsed == false) { - int32 numPorts = aznumeric_caster(AZStd::max(mInputPorts.size(), mOutputPorts.size())); + int32 numPorts = aznumeric_caster(AZStd::max(m_inputPorts.size(), m_outputPorts.size())); int32 result = (numPorts * 15) + 34; return MCore::Math::Align(result, 10); } @@ -840,9 +809,9 @@ namespace EMStudio { // calc the maximum input port width int maxInputWidth = 0; - for (const NodePort& nodePort : mInputPorts) + for (const NodePort& nodePort : m_inputPorts) { - maxInputWidth = AZStd::max(maxInputWidth, mPortFontMetrics->horizontalAdvance(nodePort.GetName())); + maxInputWidth = AZStd::max(maxInputWidth, m_portFontMetrics->horizontalAdvance(nodePort.GetName())); } return maxInputWidth; @@ -853,9 +822,9 @@ namespace EMStudio { // calc the maximum output port width int maxOutputWidth = 0; - for (const NodePort& nodePort : mOutputPorts) + for (const NodePort& nodePort : m_outputPorts) { - maxOutputWidth = AZStd::max(maxOutputWidth, mPortFontMetrics->horizontalAdvance(nodePort.GetName())); + maxOutputWidth = AZStd::max(maxOutputWidth, m_portFontMetrics->horizontalAdvance(nodePort.GetName())); } return maxOutputWidth; @@ -864,40 +833,40 @@ namespace EMStudio // calculate the width int32 GraphNode::CalcRequiredWidth() { - if (mNameAndPortsUpdated) + if (m_nameAndPortsUpdated) { - return mRequiredWidth; + return m_requiredWidth; } // calc the maximum input port width - mMaxInputWidth = CalcMaxInputPortWidth(); - mMaxOutputWidth = CalcMaxOutputPortWidth(); + m_maxInputWidth = CalcMaxInputPortWidth(); + m_maxOutputWidth = CalcMaxOutputPortWidth(); - const int infoWidth = mInfoFontMetrics->horizontalAdvance(mElidedNodeInfo); - const int totalPortWidth = mMaxInputWidth + mMaxOutputWidth + 40 + infoWidth; + const int infoWidth = m_infoFontMetrics->horizontalAdvance(m_elidedNodeInfo); + const int totalPortWidth = m_maxInputWidth + m_maxOutputWidth + 40 + infoWidth; // make sure the node is at least 100 units in width - const int headerWidth = AZStd::max(mHeaderFontMetrics->horizontalAdvance(mElidedName) + 40, 100); + const int headerWidth = AZStd::max(m_headerFontMetrics->horizontalAdvance(m_elidedName) + 40, 100); - mRequiredWidth = AZStd::max(headerWidth, totalPortWidth); - mRequiredWidth = MCore::Math::Align(mRequiredWidth, 10); + m_requiredWidth = AZStd::max(headerWidth, totalPortWidth); + m_requiredWidth = MCore::Math::Align(m_requiredWidth, 10); - mNameAndPortsUpdated = true; + m_nameAndPortsUpdated = true; - return mRequiredWidth; + return m_requiredWidth; } // get the rect for a given input port QRect GraphNode::CalcInputPortRect(AZ::u16 portNr) { - return QRect(mRect.left() - 5, mRect.top() + 35 + portNr * 15, 8, 8); + return QRect(m_rect.left() - 5, m_rect.top() + 35 + portNr * 15, 8, 8); } // get the rect for a given output port QRect GraphNode::CalcOutputPortRect(AZ::u16 portNr) { - return QRect(mRect.right() - 5, mRect.top() + 35 + portNr * 15, 8, 8); + return QRect(m_rect.right() - 5, m_rect.top() + 35 + portNr * 15, 8, 8); } @@ -906,11 +875,11 @@ namespace EMStudio { if (local == false) { - outRect = QRect(mRect.left() + 15 + mMaxInputWidth, mRect.top() + 24, mRect.width() - 20 - mMaxInputWidth - mMaxOutputWidth, 20); + outRect = QRect(m_rect.left() + 15 + m_maxInputWidth, m_rect.top() + 24, m_rect.width() - 20 - m_maxInputWidth - m_maxOutputWidth, 20); } else { - outRect = QRect(15 + mMaxInputWidth, 24, mRect.width() - 20 - mMaxInputWidth - mMaxOutputWidth, 20); + outRect = QRect(15 + m_maxInputWidth, 24, m_rect.width() - 20 - m_maxInputWidth - m_maxOutputWidth, 20); } } @@ -920,11 +889,11 @@ namespace EMStudio { if (local == false) { - outRect = QRect(mRect.left() + 10, mRect.top() + 24 + portNr * 15, mRect.width() - 20, 20); + outRect = QRect(m_rect.left() + 10, m_rect.top() + 24 + portNr * 15, m_rect.width() - 20, 20); } else { - outRect = QRect(10, 24 + portNr * 15, mRect.width() - 20, 20); + outRect = QRect(10, 24 + portNr * 15, m_rect.width() - 20, 20); } } @@ -934,11 +903,11 @@ namespace EMStudio { if (local == false) { - outRect = QRect(mRect.left() + 10, mRect.top() + 24 + portNr * 15, mRect.width() - 20, 20); + outRect = QRect(m_rect.left() + 10, m_rect.top() + 24 + portNr * 15, m_rect.width() - 20, 20); } else { - outRect = QRect(10, 24 + portNr * 15, mRect.width() - 20, 20); + outRect = QRect(10, 24 + portNr * 15, m_rect.width() - 20, 20); } } @@ -946,40 +915,40 @@ namespace EMStudio // remove all input ports void GraphNode::RemoveAllInputPorts() { - mInputPorts.clear(); + m_inputPorts.clear(); } // remove all output ports void GraphNode::RemoveAllOutputPorts() { - mOutputPorts.clear(); + m_outputPorts.clear(); } // add a new input port NodePort* GraphNode::AddInputPort(bool updateTextPixMap) { - mInputPorts.emplace_back(); - mInputPorts.back().SetNode(this); + m_inputPorts.emplace_back(); + m_inputPorts.back().SetNode(this); if (updateTextPixMap) { UpdateTextPixmap(); } - return &mInputPorts.back(); + return &m_inputPorts.back(); } // add a new output port NodePort* GraphNode::AddOutputPort(bool updateTextPixMap) { - mOutputPorts.emplace_back(); - mOutputPorts.back().SetNode(this); + m_outputPorts.emplace_back(); + m_outputPorts.back().SetNode(this); if (updateTextPixMap) { UpdateTextPixmap(); } - return &mOutputPorts.back(); + return &m_outputPorts.back(); } @@ -987,13 +956,13 @@ namespace EMStudio NodePort* GraphNode::FindPort(int32 x, int32 y, AZ::u16* outPortNr, bool* outIsInputPort, bool includeInputPorts) { // if the node is not visible at all skip directly - if (mIsVisible == false) + if (m_isVisible == false) { return nullptr; } // if the node is collapsed we can skip directly, too - if (mIsCollapsed) + if (m_isCollapsed) { return nullptr; } @@ -1001,7 +970,7 @@ namespace EMStudio // check the input ports if (includeInputPorts) { - const AZ::u16 numInputPorts = aznumeric_caster(mInputPorts.size()); + const AZ::u16 numInputPorts = aznumeric_caster(m_inputPorts.size()); for (AZ::u16 i = 0; i < numInputPorts; ++i) { QRect rect = CalcInputPortRect(i); @@ -1009,13 +978,13 @@ namespace EMStudio { *outPortNr = i; *outIsInputPort = true; - return &mInputPorts[i]; + return &m_inputPorts[i]; } } } // check the output ports - const AZ::u16 numOutputPorts = aznumeric_caster(mOutputPorts.size()); + const AZ::u16 numOutputPorts = aznumeric_caster(m_outputPorts.size()); for (AZ::u16 i = 0; i < numOutputPorts; ++i) { QRect rect = CalcOutputPortRect(i); @@ -1023,7 +992,7 @@ namespace EMStudio { *outPortNr = i; *outIsInputPort = false; - return &mOutputPorts[i]; + return &m_outputPorts[i]; } } @@ -1033,12 +1002,12 @@ namespace EMStudio // remove a given connection bool GraphNode::RemoveConnection(const void* connection, bool removeFromMemory) { - const auto foundConnection = AZStd::find_if(begin(mConnections), end(mConnections), [match = connection](const NodeConnection* connection) + const auto foundConnection = AZStd::find_if(begin(m_connections), end(m_connections), [match = connection](const NodeConnection* connection) { return connection->GetModelIndex().data(AnimGraphModel::ROLE_POINTER).value() == match; }); - if (foundConnection == end(mConnections)) + if (foundConnection == end(m_connections)) { return false; } @@ -1047,7 +1016,7 @@ namespace EMStudio { delete *foundConnection; } - mConnections.erase(foundConnection); + m_connections.erase(foundConnection); return true; } @@ -1055,12 +1024,12 @@ namespace EMStudio // Remove a given connection by model index bool GraphNode::RemoveConnection(const QModelIndex& modelIndex, bool removeFromMemory) { - const auto foundConnection = AZStd::find_if(begin(mConnections), end(mConnections), [match = modelIndex](const NodeConnection* connection) + const auto foundConnection = AZStd::find_if(begin(m_connections), end(m_connections), [match = modelIndex](const NodeConnection* connection) { return connection->GetModelIndex() == match; }); - if (foundConnection == end(mConnections)) + if (foundConnection == end(m_connections)) { return false; } @@ -1069,7 +1038,7 @@ namespace EMStudio { delete *foundConnection; } - mConnections.erase(foundConnection); + m_connections.erase(foundConnection); return true; } @@ -1077,14 +1046,14 @@ namespace EMStudio // called when the name of a port got changed void NodePort::OnNameChanged() { - if (mNode == nullptr) + if (m_node == nullptr) { return; } - mNode->UpdateNameAndPorts(); - mNode->UpdateRects(); - mNode->UpdateTextPixmap(); + m_node->UpdateNameAndPorts(); + m_node->UpdateRects(); + m_node->UpdateTextPixmap(); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GraphNode.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GraphNode.h index 125317408d..297e6c2cd1 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GraphNode.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GraphNode.h @@ -43,28 +43,28 @@ namespace EMStudio public: NodePort() - : mIsHighlighted(false) { mNode = nullptr; mNameID = MCORE_INVALIDINDEX32; mColor.setRgb(50, 150, 250); } + : m_isHighlighted(false) { m_node = nullptr; m_nameId = MCORE_INVALIDINDEX32; m_color.setRgb(50, 150, 250); } - MCORE_INLINE void SetName(const char* name) { mNameID = MCore::GetStringIdPool().GenerateIdForString(name); OnNameChanged(); } - MCORE_INLINE const char* GetName() const { return MCore::GetStringIdPool().GetName(mNameID).c_str(); } - MCORE_INLINE void SetNameID(uint32 id) { mNameID = id; } - MCORE_INLINE uint32 GetNameID() const { return mNameID; } - MCORE_INLINE void SetRect(const QRect& rect) { mRect = rect; } - MCORE_INLINE const QRect& GetRect() const { return mRect; } - MCORE_INLINE void SetColor(const QColor& color) { mColor = color; } - MCORE_INLINE const QColor& GetColor() const { return mColor; } - MCORE_INLINE void SetNode(GraphNode* node) { mNode = node; } - MCORE_INLINE bool GetIsHighlighted() const { return mIsHighlighted; } - MCORE_INLINE void SetIsHighlighted(bool enabled) { mIsHighlighted = enabled; } + MCORE_INLINE void SetName(const char* name) { m_nameId = MCore::GetStringIdPool().GenerateIdForString(name); OnNameChanged(); } + MCORE_INLINE const char* GetName() const { return MCore::GetStringIdPool().GetName(m_nameId).c_str(); } + MCORE_INLINE void SetNameID(uint32 id) { m_nameId = id; } + MCORE_INLINE uint32 GetNameID() const { return m_nameId; } + MCORE_INLINE void SetRect(const QRect& rect) { m_rect = rect; } + MCORE_INLINE const QRect& GetRect() const { return m_rect; } + MCORE_INLINE void SetColor(const QColor& color) { m_color = color; } + MCORE_INLINE const QColor& GetColor() const { return m_color; } + MCORE_INLINE void SetNode(GraphNode* node) { m_node = node; } + MCORE_INLINE bool GetIsHighlighted() const { return m_isHighlighted; } + MCORE_INLINE void SetIsHighlighted(bool enabled) { m_isHighlighted = enabled; } void OnNameChanged(); private: - QRect mRect; - QColor mColor; - GraphNode* mNode; - uint32 mNameID; - bool mIsHighlighted; + QRect m_rect; + QColor m_color; + GraphNode* m_node; + uint32 m_nameId; + bool m_isHighlighted; }; @@ -83,59 +83,58 @@ namespace EMStudio const QModelIndex& GetModelIndex() const { return m_modelIndex; } - MCORE_INLINE void UpdateNameAndPorts() { mNameAndPortsUpdated = false; } - MCORE_INLINE AZStd::vector& GetConnections() { return mConnections; } - MCORE_INLINE size_t GetNumConnections() { return mConnections.size(); } - MCORE_INLINE NodeConnection* GetConnection(size_t index) { return mConnections[index]; } - MCORE_INLINE NodeConnection* AddConnection(NodeConnection* con) { mConnections.emplace_back(con); return con; } - MCORE_INLINE void SetParentGraph(NodeGraph* graph) { mParentGraph = graph; } - MCORE_INLINE NodeGraph* GetParentGraph() { return mParentGraph; } - MCORE_INLINE NodePort* GetInputPort(AZ::u16 index) { return &mInputPorts[index]; } - MCORE_INLINE NodePort* GetOutputPort(AZ::u16 index) { return &mOutputPorts[index]; } - MCORE_INLINE const QRect& GetRect() const { return mRect; } - MCORE_INLINE const QRect& GetFinalRect() const { return mFinalRect; } - MCORE_INLINE const QRect& GetVizRect() const { return mVisualizeRect; } - MCORE_INLINE void SetBaseColor(const QColor& color) { mBaseColor = color; } - MCORE_INLINE QColor GetBaseColor() const { return mBaseColor; } - MCORE_INLINE bool GetIsVisible() const { return mIsVisible; } - MCORE_INLINE const char* GetName() const { return mName.c_str(); } - MCORE_INLINE const AZStd::string& GetNameString() const { return mName; } + MCORE_INLINE void UpdateNameAndPorts() { m_nameAndPortsUpdated = false; } + MCORE_INLINE AZStd::vector& GetConnections() { return m_connections; } + MCORE_INLINE size_t GetNumConnections() { return m_connections.size(); } + MCORE_INLINE NodeConnection* GetConnection(size_t index) { return m_connections[index]; } + MCORE_INLINE NodeConnection* AddConnection(NodeConnection* con) { m_connections.emplace_back(con); return con; } + MCORE_INLINE void SetParentGraph(NodeGraph* graph) { m_parentGraph = graph; } + MCORE_INLINE NodeGraph* GetParentGraph() { return m_parentGraph; } + MCORE_INLINE NodePort* GetInputPort(AZ::u16 index) { return &m_inputPorts[index]; } + MCORE_INLINE NodePort* GetOutputPort(AZ::u16 index) { return &m_outputPorts[index]; } + MCORE_INLINE const QRect& GetRect() const { return m_rect; } + MCORE_INLINE const QRect& GetFinalRect() const { return m_finalRect; } + MCORE_INLINE const QRect& GetVizRect() const { return m_visualizeRect; } + MCORE_INLINE void SetBaseColor(const QColor& color) { m_baseColor = color; } + MCORE_INLINE QColor GetBaseColor() const { return m_baseColor; } + MCORE_INLINE bool GetIsVisible() const { return m_isVisible; } + MCORE_INLINE const char* GetName() const { return m_name.c_str(); } + MCORE_INLINE const AZStd::string& GetNameString() const { return m_name; } - MCORE_INLINE bool GetCreateConFromOutputOnly() const { return mConFromOutputOnly; } - MCORE_INLINE void SetCreateConFromOutputOnly(bool enable) { mConFromOutputOnly = enable; } - MCORE_INLINE bool GetIsDeletable() const { return mIsDeletable; } - MCORE_INLINE bool GetIsCollapsed() const { return mIsCollapsed; } + MCORE_INLINE bool GetCreateConFromOutputOnly() const { return m_conFromOutputOnly; } + MCORE_INLINE void SetCreateConFromOutputOnly(bool enable) { m_conFromOutputOnly = enable; } + MCORE_INLINE bool GetIsDeletable() const { return m_isDeletable; } + MCORE_INLINE bool GetIsCollapsed() const { return m_isCollapsed; } void SetIsCollapsed(bool collapsed); - MCORE_INLINE void SetDeletable(bool deletable) { mIsDeletable = deletable; } + MCORE_INLINE void SetDeletable(bool deletable) { m_isDeletable = deletable; } void SetSubTitle(const char* subTitle, bool updatePixmap = true); - MCORE_INLINE const char* GetSubTitle() const { return mSubTitle.c_str(); } - //MCORE_INLINE const AZStd::string& GetSubTitleString() const { return mSubTitle; } - MCORE_INLINE bool GetIsInsideArrowRect(const QPoint& point) const { return mArrowRect.contains(point, true); } + MCORE_INLINE const char* GetSubTitle() const { return m_subTitle.c_str(); } + MCORE_INLINE bool GetIsInsideArrowRect(const QPoint& point) const { return m_arrowRect.contains(point, true); } - MCORE_INLINE void SetVisualizeColor(const QColor& color) { mVisualizeColor = color; } - MCORE_INLINE const QColor& GetVisualizeColor() const { return mVisualizeColor; } + MCORE_INLINE void SetVisualizeColor(const QColor& color) { m_visualizeColor = color; } + MCORE_INLINE const QColor& GetVisualizeColor() const { return m_visualizeColor; } - MCORE_INLINE void SetHasChildIndicatorColor(const QColor& color) { mHasChildIndicatorColor = color; } - MCORE_INLINE const QColor& GetHasChildIndicatorColor() const { return mHasChildIndicatorColor; } + MCORE_INLINE void SetHasChildIndicatorColor(const QColor& color) { m_hasChildIndicatorColor = color; } + MCORE_INLINE const QColor& GetHasChildIndicatorColor() const { return m_hasChildIndicatorColor; } - MCORE_INLINE bool GetIsHighlighted() const { return mIsHighlighted; } - MCORE_INLINE bool GetIsVisualizedHighlighted() const { return mVisualizeHighlighted; } - MCORE_INLINE bool GetIsInsideVisualizeRect(const QPoint& point) const { return mVisualizeRect.contains(point, true); } + MCORE_INLINE bool GetIsHighlighted() const { return m_isHighlighted; } + MCORE_INLINE bool GetIsVisualizedHighlighted() const { return m_visualizeHighlighted; } + MCORE_INLINE bool GetIsInsideVisualizeRect(const QPoint& point) const { return m_visualizeRect.contains(point, true); } - MCORE_INLINE void SetIsVisualized(bool enabled) { mVisualize = enabled; } - MCORE_INLINE bool GetIsVisualized() const { return mVisualize; } + MCORE_INLINE void SetIsVisualized(bool enabled) { m_visualize = enabled; } + MCORE_INLINE bool GetIsVisualized() const { return m_visualize; } - MCORE_INLINE void SetIsEnabled(bool enabled) { mIsEnabled = enabled; } - MCORE_INLINE bool GetIsEnabled() const { return mIsEnabled; } + MCORE_INLINE void SetIsEnabled(bool enabled) { m_isEnabled = enabled; } + MCORE_INLINE bool GetIsEnabled() const { return m_isEnabled; } - MCORE_INLINE void SetCanVisualize(bool canViz) { mCanVisualize = canViz; } - MCORE_INLINE bool GetCanVisualize() const { return mCanVisualize; } + MCORE_INLINE void SetCanVisualize(bool canViz) { m_canVisualize = canViz; } + MCORE_INLINE bool GetCanVisualize() const { return m_canVisualize; } - MCORE_INLINE float GetOpacity() const { return mOpacity; } - MCORE_INLINE void SetOpacity(float opacity) { mOpacity = opacity; } + MCORE_INLINE float GetOpacity() const { return m_opacity; } + MCORE_INLINE void SetOpacity(float opacity) { m_opacity = opacity; } - AZ::u16 GetNumInputPorts() const { return aznumeric_caster(mInputPorts.size()); } - AZ::u16 GetNumOutputPorts() const { return aznumeric_caster(mOutputPorts.size()); } + AZ::u16 GetNumInputPorts() const { return aznumeric_caster(m_inputPorts.size()); } + AZ::u16 GetNumOutputPorts() const { return aznumeric_caster(m_outputPorts.size()); } NodePort* AddInputPort(bool updateTextPixMap); NodePort* AddOutputPort(bool updateTextPixMap); @@ -180,11 +179,11 @@ namespace EMStudio virtual bool GetAlwaysColor() const { return true; } virtual bool GetHasError() const { return true; } - MCORE_INLINE bool GetIsProcessed() const { return mIsProcessed; } - MCORE_INLINE void SetIsProcessed(bool processed) { mIsProcessed = processed; } + MCORE_INLINE bool GetIsProcessed() const { return m_isProcessed; } + MCORE_INLINE void SetIsProcessed(bool processed) { m_isProcessed = processed; } - MCORE_INLINE bool GetIsUpdated() const { return mIsUpdated; } - MCORE_INLINE void SetIsUpdated(bool updated) { mIsUpdated = updated; } + MCORE_INLINE bool GetIsUpdated() const { return m_isUpdated; } + MCORE_INLINE void SetIsUpdated(bool updated) { m_isUpdated = updated; } virtual void Sync() {} @@ -192,12 +191,12 @@ namespace EMStudio void CalcInputPortTextRect(AZ::u16 portNr, QRect& outRect, bool local = false); void CalcInfoTextRect(QRect& outRect, bool local = false); - MCORE_INLINE void SetHasVisualOutputPorts(bool hasVisualOutputPorts) { mHasVisualOutputPorts = hasVisualOutputPorts; } - MCORE_INLINE bool GetHasVisualOutputPorts() const { return mHasVisualOutputPorts; } + MCORE_INLINE void SetHasVisualOutputPorts(bool hasVisualOutputPorts) { m_hasVisualOutputPorts = hasVisualOutputPorts; } + MCORE_INLINE bool GetHasVisualOutputPorts() const { return m_hasVisualOutputPorts; } - const QColor& GetBorderColor() const { return mBorderColor; } - void SetBorderColor(const QColor& color) { mBorderColor = color; } - void ResetBorderColor() { mBorderColor = QColor(0, 0, 0); } + const QColor& GetBorderColor() const { return m_borderColor; } + void SetBorderColor(const QColor& color) { m_borderColor = color; } + void ResetBorderColor() { m_borderColor = QColor(0, 0, 0); } virtual void UpdateTextPixmap(); static void RenderText(QPainter& painter, const QString& text, const QColor& textColor, const QFont& font, const QFontMetrics& fontMetrics, Qt::Alignment textAlignment, const QRect& rect); @@ -208,75 +207,74 @@ namespace EMStudio void GetNodePortColors(NodePort* nodePort, const QColor& borderColor, const QColor& headerBgColor, QColor* outBrushColor, QColor* outPenColor); QPersistentModelIndex m_modelIndex; - AZStd::string mName; - QString mElidedName; + AZStd::string m_name; + QString m_elidedName; - QPainter mTextPainter; - //QPixmap mTextPixmap; - AZStd::string mSubTitle; - QString mElidedSubTitle; - AZStd::string mNodeInfo; - QString mElidedNodeInfo; - QBrush mBrush; - QColor mBaseColor; - QRect mRect; - QRect mFinalRect; - QRect mArrowRect; - QRect mVisualizeRect; - QColor mBorderColor; - QColor mVisualizeColor; - QColor mHasChildIndicatorColor; - AZStd::vector mConnections; - float mOpacity; - bool mIsVisible; - static QColor mPortHighlightColor; - static QColor mPortHighlightBGColor; + QPainter m_textPainter; + AZStd::string m_subTitle; + QString m_elidedSubTitle; + AZStd::string m_nodeInfo; + QString m_elidedNodeInfo; + QBrush m_brush; + QColor m_baseColor; + QRect m_rect; + QRect m_finalRect; + QRect m_arrowRect; + QRect m_visualizeRect; + QColor m_borderColor; + QColor m_visualizeColor; + QColor m_hasChildIndicatorColor; + AZStd::vector m_connections; + float m_opacity; + bool m_isVisible; + static QColor s_portHighlightColo; + static QColor s_portHighlightBGColor; // font stuff - QFont mHeaderFont; - QFont mPortNameFont; - QFont mSubTitleFont; - QFont mInfoTextFont; - QFontMetrics* mPortFontMetrics; - QFontMetrics* mHeaderFontMetrics; - QFontMetrics* mInfoFontMetrics; - QFontMetrics* mSubTitleFontMetrics; - QTextOption mTextOptionsCenter; - QTextOption mTextOptionsAlignLeft; - QTextOption mTextOptionsAlignRight; - QTextOption mTextOptionsCenterHV; + QFont m_headerFont; + QFont m_portNameFont; + QFont m_subTitleFont; + QFont m_infoTextFont; + QFontMetrics* m_portFontMetrics; + QFontMetrics* m_headerFontMetrics; + QFontMetrics* m_infoFontMetrics; + QFontMetrics* m_subTitleFontMetrics; + QTextOption m_textOptionsCenter; + QTextOption m_textOptionsAlignLeft; + QTextOption m_textOptionsAlignRight; + QTextOption m_textOptionsCenterHv; - QStaticText mTitleText; - QStaticText mSubTitleText; - QStaticText mInfoText; + QStaticText m_titleText; + QStaticText m_subTitleText; + QStaticText m_infoText; - AZStd::vector mInputPortText; - AZStd::vector mOutputPortText; + AZStd::vector m_inputPortText; + AZStd::vector m_outputPortText; - int32 mRequiredWidth; - bool mNameAndPortsUpdated; + int32 m_requiredWidth; + bool m_nameAndPortsUpdated; - NodeGraph* mParentGraph; - AZStd::vector mInputPorts; - AZStd::vector mOutputPorts; - bool mConFromOutputOnly; - bool mIsDeletable; - bool mIsCollapsed; - bool mIsProcessed; - bool mIsUpdated; - bool mVisualize; - bool mCanVisualize; - bool mVisualizeHighlighted; - bool mIsEnabled; - bool mIsHighlighted; - bool mCanHaveChildren; - bool mHasVisualGraph; - bool mHasVisualOutputPorts; + NodeGraph* m_parentGraph; + AZStd::vector m_inputPorts; + AZStd::vector m_outputPorts; + bool m_conFromOutputOnly; + bool m_isDeletable; + bool m_isCollapsed; + bool m_isProcessed; + bool m_isUpdated; + bool m_visualize; + bool m_canVisualize; + bool m_visualizeHighlighted; + bool m_isEnabled; + bool m_isHighlighted; + bool m_canHaveChildren; + bool m_hasVisualGraph; + bool m_hasVisualOutputPorts; - int mMaxInputWidth; // will be calculated automatically in CalcRequiredWidth() - int mMaxOutputWidth; // will be calculated automatically in CalcRequiredWidth() + int m_maxInputWidth; // will be calculated automatically in CalcRequiredWidth() + int m_maxOutputWidth; // will be calculated automatically in CalcRequiredWidth() // has child node indicator - QPolygonF mSubstPoly; + QPolygonF m_substPoly; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GraphWidgetCallback.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GraphWidgetCallback.h index f57828c646..ff14484dc5 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GraphWidgetCallback.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GraphWidgetCallback.h @@ -27,13 +27,13 @@ namespace EMStudio public: // constructor and destructor - GraphWidgetCallback(NodeGraphWidget* graphWidget) { mGraphWidget = graphWidget; } + GraphWidgetCallback(NodeGraphWidget* graphWidget) { m_graphWidget = graphWidget; } virtual ~GraphWidgetCallback() {} virtual void DrawOverlay(QPainter& painter) = 0; protected: - NodeGraphWidget* mGraphWidget; + NodeGraphWidget* m_graphWidget; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeConnection.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeConnection.cpp index cefbb0d0af..c8a36b9f8e 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeConnection.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeConnection.cpp @@ -21,18 +21,18 @@ namespace EMStudio : m_modelIndex(modelIndex) , m_parentGraph(parentGraph) { - mSourceNode = sourceNode; - mSourcePortNr = sourceOutputPortNr; - mTargetNode = targetNode; - mPortNr = portNr; - mIsVisible = false; - mIsProcessed = false; - mIsDashed = false; - mIsDisabled = false; - mIsHeadHighlighted = false; - mIsTailHighlighted = false; - mIsSynced = false; - mColor = QColor(128, 255, 128); + m_sourceNode = sourceNode; + m_sourcePortNr = sourceOutputPortNr; + m_targetNode = targetNode; + m_portNr = portNr; + m_isVisible = false; + m_isProcessed = false; + m_isDashed = false; + m_isDisabled = false; + m_isHeadHighlighted = false; + m_isTailHighlighted = false; + m_isSynced = false; + m_color = QColor(128, 255, 128); } @@ -48,15 +48,15 @@ namespace EMStudio MCORE_UNUSED(mousePos); // calculate the rects - mRect = CalcRect(); - mFinalRect = CalcFinalRect(); + m_rect = CalcRect(); + m_finalRect = CalcFinalRect(); // check for visibility - mIsVisible = mFinalRect.intersects(visibleRect); + m_isVisible = m_finalRect.intersects(visibleRect); // reset the is highlighted flags - mIsHighlighted = false; - mIsConnectedHighlighted = false; + m_isHighlighted = false; + m_isConnectedHighlighted = false; } @@ -73,12 +73,12 @@ namespace EMStudio int32 endY = targetRect.center().y() + 1; // draw the connection - mPainterPath = QPainterPath(); + m_painterPath = QPainterPath(); const float width = aznumeric_cast(abs((endX - 3) - (startX + 3))); - mPainterPath.moveTo(startX, startY); - mPainterPath.lineTo(startX + 3, startY); - mPainterPath.cubicTo(startX + (width / 2), startY, endX - (width / 2), endY, endX - 3, endY); - mPainterPath.lineTo(endX, endY); + m_painterPath.moveTo(startX, startY); + m_painterPath.lineTo(startX + 3, startY); + m_painterPath.cubicTo(startX + (width / 2), startY, endX - (width / 2), endY, endX - 3, endY); + m_painterPath.lineTo(endX, endY); } @@ -90,14 +90,14 @@ namespace EMStudio AZ_UNUSED(visibleRect); // used when relinking - if (mIsDashed) + if (m_isDashed) { return; } painter.setOpacity(opacity); - const float scale = mSourceNode->GetParentGraph()->GetScale(); + const float scale = m_sourceNode->GetParentGraph()->GetScale(); QColor penColor; // draw some small horizontal lines that go outside of the connection port @@ -117,11 +117,10 @@ namespace EMStudio else // unselected { // don't make it bold when not selected - if (mIsProcessed == false && alwaysColor == false) + if (m_isProcessed == false && alwaysColor == false) { - if (mSourceNode) + if (m_sourceNode) { - //penColor = mSourceNode->GetOutputPort(mSourcePortNr)->GetColor(); penColor.setRgb(75, 75, 75); } else @@ -133,14 +132,14 @@ namespace EMStudio } else { - if (mSourceNode) + if (m_sourceNode) { if (alwaysColor == false) { pen->setWidthF(1.5f); } - penColor = mSourceNode->GetOutputPort(mSourcePortNr)->GetColor(); + penColor = m_sourceNode->GetOutputPort(m_sourcePortNr)->GetColor(); } else { @@ -152,13 +151,13 @@ namespace EMStudio } // lighten the color in case the transition is highlighted - if (mIsHighlighted) + if (m_isHighlighted) { penColor = penColor.lighter(160); } // lighten the color in case the transition is connected to the currently selected node - if (mIsConnectedHighlighted) + if (m_isConnectedHighlighted) { const float minInput = 0.1f; const float maxInput = 1.0f; @@ -184,9 +183,9 @@ namespace EMStudio } // blinking red error color - if (mSourceNode && mSourceNode->GetHasError() && !GetIsSelected()) + if (m_sourceNode && m_sourceNode->GetHasError() && !GetIsSelected()) { - NodeGraph* parentGraph = mTargetNode->GetParentGraph(); + NodeGraph* parentGraph = m_targetNode->GetParentGraph(); if (parentGraph->GetUseAnimation()) { penColor = parentGraph->GetErrorBlinkColor(); @@ -199,9 +198,9 @@ namespace EMStudio // set the pen pen->setColor(penColor); - if (mIsProcessed) + if (m_isProcessed) { - NodeGraph* parentGraph = mTargetNode->GetParentGraph(); + NodeGraph* parentGraph = m_targetNode->GetParentGraph(); if (parentGraph->GetScale() > 0.5f && parentGraph->GetUseAnimation()) { pen->setStyle(Qt::PenStyle::DashLine); @@ -229,7 +228,7 @@ namespace EMStudio // draw the curve UpdatePainterPath(); - painter.drawPath(mPainterPath); + painter.drawPath(m_painterPath); // restore opacity and width painter.setOpacity(1.0f); @@ -240,11 +239,11 @@ namespace EMStudio // get the source rect QRect NodeConnection::GetSourceRect() const { - if (mSourceNode) + if (m_sourceNode) { - if (mSourceNode->GetIsCollapsed() == false) + if (m_sourceNode->GetIsCollapsed() == false) { - return mSourceNode->GetOutputPort(mSourcePortNr)->GetRect(); + return m_sourceNode->GetOutputPort(m_sourcePortNr)->GetRect(); } else { @@ -262,9 +261,9 @@ namespace EMStudio // get the target rect QRect NodeConnection::GetTargetRect() const { - if (mTargetNode->GetIsCollapsed() == false) + if (m_targetNode->GetIsCollapsed() == false) { - return mTargetNode->GetInputPort(mPortNr)->GetRect(); + return m_targetNode->GetInputPort(m_portNr)->GetRect(); } else { @@ -276,7 +275,7 @@ namespace EMStudio // intersects this connection? bool NodeConnection::Intersects(const QRect& rect) { - if (mRect.intersects(rect) == false) + if (m_rect.intersects(rect) == false) { return false; } @@ -291,7 +290,7 @@ namespace EMStudio //testPath.addRect( rect ); UpdatePainterPath(); - return mPainterPath.intersects(rect); + return m_painterPath.intersects(rect); } @@ -299,12 +298,12 @@ namespace EMStudio bool NodeConnection::CheckIfIsCloseTo(const QPoint& point) { // if we're not visible don't check - if (mIsVisible == false) + if (m_isVisible == false) { return false; } - if (mRect.contains(point) == false) + if (m_rect.contains(point) == false) { return false; } @@ -325,7 +324,7 @@ namespace EMStudio // get the collapsed source rect QRect NodeConnection::CalcCollapsedSourceRect() const { - QRect tempRect = mSourceNode->GetRect(); + QRect tempRect = m_sourceNode->GetRect(); // QPoint a = QPoint(tempRect.right(), tempRect.top() + tempRect.height() / 2); QPoint a = QPoint(tempRect.right(), tempRect.top() + 13); return QRect(a - QPoint(1, 1), a); @@ -335,7 +334,7 @@ namespace EMStudio // get the collapsed target rect QRect NodeConnection::CalcCollapsedTargetRect() const { - QRect tempRect = mTargetNode->GetRect(); + QRect tempRect = m_targetNode->GetRect(); // QPoint a = QPoint(tempRect.left(), tempRect.top() + tempRect.height() / 2); QPoint a = QPoint(tempRect.left(), tempRect.top() + 13); return QRect(a, a + QPoint(1, 1)); @@ -354,14 +353,14 @@ namespace EMStudio // calc the final rect QRect NodeConnection::CalcFinalRect() const { - if (mSourceNode) + if (m_sourceNode) { - return mSourceNode->GetParentGraph()->GetTransform().mapRect(CalcRect()); + return m_sourceNode->GetParentGraph()->GetTransform().mapRect(CalcRect()); } - if (mTargetNode) + if (m_targetNode) { - return mTargetNode->GetParentGraph()->GetTransform().mapRect(CalcRect()); + return m_targetNode->GetParentGraph()->GetTransform().mapRect(CalcRect()); } MCORE_ASSERT(false); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeConnection.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeConnection.h index 2e305dbd0c..4fd7d41c97 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeConnection.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeConnection.h @@ -60,71 +60,71 @@ namespace EMStudio bool GetIsSelected() const; - MCORE_INLINE bool GetIsVisible() { return mIsVisible; } + MCORE_INLINE bool GetIsVisible() { return m_isVisible; } - MCORE_INLINE AZ::u16 GetInputPortNr() const { return mPortNr; } - MCORE_INLINE AZ::u16 GetOutputPortNr() const { return mSourcePortNr; } - MCORE_INLINE GraphNode* GetSourceNode() { return mSourceNode; } - MCORE_INLINE GraphNode* GetTargetNode() { return mTargetNode; } + MCORE_INLINE AZ::u16 GetInputPortNr() const { return m_portNr; } + MCORE_INLINE AZ::u16 GetOutputPortNr() const { return m_sourcePortNr; } + MCORE_INLINE GraphNode* GetSourceNode() { return m_sourceNode; } + MCORE_INLINE GraphNode* GetTargetNode() { return m_targetNode; } - MCORE_INLINE bool GetIsSynced() const { return mIsSynced; } - MCORE_INLINE void SetIsSynced(bool synced) { mIsSynced = synced; } + MCORE_INLINE bool GetIsSynced() const { return m_isSynced; } + MCORE_INLINE void SetIsSynced(bool synced) { m_isSynced = synced; } - MCORE_INLINE bool GetIsProcessed() const { return mIsProcessed; } - MCORE_INLINE void SetIsProcessed(bool processed) { mIsProcessed = processed; } + MCORE_INLINE bool GetIsProcessed() const { return m_isProcessed; } + MCORE_INLINE void SetIsProcessed(bool processed) { m_isProcessed = processed; } - MCORE_INLINE bool GetIsDashed() const { return mIsDashed; } - MCORE_INLINE void SetIsDashed(bool flag) { mIsDashed = flag; } + MCORE_INLINE bool GetIsDashed() const { return m_isDashed; } + MCORE_INLINE void SetIsDashed(bool flag) { m_isDashed = flag; } - MCORE_INLINE bool GetIsDisabled() const { return mIsDisabled; } - MCORE_INLINE void SetIsDisabled(bool flag) { mIsDisabled = flag; } + MCORE_INLINE bool GetIsDisabled() const { return m_isDisabled; } + MCORE_INLINE void SetIsDisabled(bool flag) { m_isDisabled = flag; } - MCORE_INLINE bool GetIsHighlighted() const { return mIsHighlighted; } - MCORE_INLINE void SetIsHighlighted(bool flag) { mIsHighlighted = flag; } + MCORE_INLINE bool GetIsHighlighted() const { return m_isHighlighted; } + MCORE_INLINE void SetIsHighlighted(bool flag) { m_isHighlighted = flag; } // when a node is selected, we highlight all incoming/outgoing connections from/to that, this is the flag to indicate that - MCORE_INLINE bool GetIsConnectedHighlighted() const { return mIsConnectedHighlighted; } - MCORE_INLINE void SetIsConnectedHighlighted(bool flag) { mIsConnectedHighlighted = flag; } + MCORE_INLINE bool GetIsConnectedHighlighted() const { return m_isConnectedHighlighted; } + MCORE_INLINE void SetIsConnectedHighlighted(bool flag) { m_isConnectedHighlighted = flag; } - MCORE_INLINE void SetIsTailHighlighted(bool flag) { mIsTailHighlighted = flag; } - MCORE_INLINE void SetIsHeadHighlighted(bool flag) { mIsHeadHighlighted = flag; } - MCORE_INLINE bool GetIsTailHighlighted() const { return mIsTailHighlighted; } - MCORE_INLINE bool GetIsHeadHighlighted() const { return mIsHeadHighlighted; } + MCORE_INLINE void SetIsTailHighlighted(bool flag) { m_isTailHighlighted = flag; } + MCORE_INLINE void SetIsHeadHighlighted(bool flag) { m_isHeadHighlighted = flag; } + MCORE_INLINE bool GetIsTailHighlighted() const { return m_isTailHighlighted; } + MCORE_INLINE bool GetIsHeadHighlighted() const { return m_isHeadHighlighted; } virtual bool CheckIfIsCloseToHead(const QPoint& point) const { MCORE_UNUSED(point); return false; } virtual bool CheckIfIsCloseToTail(const QPoint& point) const { MCORE_UNUSED(point); return false; } virtual void CalcStartAndEndPoints(QPoint& start, QPoint& end) const { MCORE_UNUSED(start); MCORE_UNUSED(end); } virtual bool GetIsWildcardTransition() const { return false; } - MCORE_INLINE void SetColor(const QColor& color) { mColor = color; } - MCORE_INLINE const QColor& GetColor() const { return mColor; } + MCORE_INLINE void SetColor(const QColor& color) { m_color = color; } + MCORE_INLINE const QColor& GetColor() const { return m_color; } - void SetSourceNode(GraphNode* node) { mSourceNode = node; } - void SetTargetNode(GraphNode* node) { mTargetNode = node; } + void SetSourceNode(GraphNode* node) { m_sourceNode = node; } + void SetTargetNode(GraphNode* node) { m_targetNode = node; } - void SetTargetPort(AZ::u16 portIndex) { mPortNr = portIndex; } + void SetTargetPort(AZ::u16 portIndex) { m_portNr = portIndex; } protected: NodeGraph* m_parentGraph = nullptr; QPersistentModelIndex m_modelIndex; - QRect mRect; - QRect mFinalRect; - QColor mColor; - GraphNode* mSourceNode; // source node from which the connection comes - GraphNode* mTargetNode; // the target node - QPainterPath mPainterPath; - AZ::u16 mPortNr; // input port where this is connected to - AZ::u16 mSourcePortNr; // source output port number - bool mIsVisible; // is this connection visible? - bool mIsProcessed; // is this connection processed? - bool mIsDisabled; - bool mIsDashed; - bool mIsHighlighted; - bool mIsHeadHighlighted; - bool mIsTailHighlighted; - bool mIsConnectedHighlighted; - bool mIsSynced; + QRect m_rect; + QRect m_finalRect; + QColor m_color; + GraphNode* m_sourceNode; // source node from which the connection comes + GraphNode* m_targetNode; // the target node + QPainterPath m_painterPath; + AZ::u16 m_portNr; // input port where this is connected to + AZ::u16 m_sourcePortNr; // source output port number + bool m_isVisible; // is this connection visible? + bool m_isProcessed; // is this connection processed? + bool m_isDisabled; + bool m_isDashed; + bool m_isHighlighted; + bool m_isHeadHighlighted; + bool m_isTailHighlighted; + bool m_isConnectedHighlighted; + bool m_isSynced; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGraph.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGraph.cpp index 37ec2cfd8b..596f3d7e30 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGraph.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGraph.cpp @@ -42,55 +42,55 @@ namespace EMStudio parent = parent.parent(); } - mErrorBlinkOffset = 0.0f; - mUseAnimation = true; - mDashOffset = 0.0f; - mScale = 1.0f; - mScrollOffset = QPoint(0, 0); - mScalePivot = QPoint(0, 0); - mMinStepSize = 1; - mMaxStepSize = 75; - mEntryNode = nullptr; + m_errorBlinkOffset = 0.0f; + m_useAnimation = true; + m_dashOffset = 0.0f; + m_scale = 1.0f; + m_scrollOffset = QPoint(0, 0); + m_scalePivot = QPoint(0, 0); + m_minStepSize = 1; + m_maxStepSize = 75; + m_entryNode = nullptr; // init connection creation - mConStartOffset = QPoint(0, 0); - mConEndOffset = QPoint(0, 0); - mConPortNr = InvalidIndex16; - mConIsInputPort = true; - mConNode = nullptr; // nullptr when no connection is being created - mConPort = nullptr; - mConIsValid = false; - mTargetPort = nullptr; - mRelinkConnection = nullptr; - mReplaceTransitionHead = nullptr; - mReplaceTransitionTail = nullptr; - mReplaceTransitionSourceNode = nullptr; - mReplaceTransitionTargetNode = nullptr; - mReplaceTransitionStartOffset = QPoint(0, 0); - mReplaceTransitionEndOffset = QPoint(0, 0); + m_conStartOffset = QPoint(0, 0); + m_conEndOffset = QPoint(0, 0); + m_conPortNr = InvalidIndex16; + m_conIsInputPort = true; + m_conNode = nullptr; // nullptr when no connection is being created + m_conPort = nullptr; + m_conIsValid = false; + m_targetPort = nullptr; + m_relinkConnection = nullptr; + m_replaceTransitionHead = nullptr; + m_replaceTransitionTail = nullptr; + m_replaceTransitionSourceNode = nullptr; + m_replaceTransitionTargetNode = nullptr; + m_replaceTransitionStartOffset = QPoint(0, 0); + m_replaceTransitionEndOffset = QPoint(0, 0); // setup scroll interpolator - mStartScrollOffset = QPointF(0.0f, 0.0f); - mTargetScrollOffset = QPointF(0.0f, 0.0f); - mScrollTimer.setSingleShot(false); - connect(&mScrollTimer, &QTimer::timeout, this, &NodeGraph::UpdateAnimatedScrollOffset); + m_startScrollOffset = QPointF(0.0f, 0.0f); + m_targetScrollOffset = QPointF(0.0f, 0.0f); + m_scrollTimer.setSingleShot(false); + connect(&m_scrollTimer, &QTimer::timeout, this, &NodeGraph::UpdateAnimatedScrollOffset); // setup scale interpolator - mStartScale = 1.0f; - mTargetScale = 1.0f; - mScaleTimer.setSingleShot(false); - connect(&mScaleTimer, &QTimer::timeout, this, &NodeGraph::UpdateAnimatedScale); + m_startScale = 1.0f; + m_targetScale = 1.0f; + m_scaleTimer.setSingleShot(false); + connect(&m_scaleTimer, &QTimer::timeout, this, &NodeGraph::UpdateAnimatedScale); - mReplaceTransitionValid = false; + m_replaceTransitionValid = false; // Overlay - mFont.setPixelSize(12); - mTextOptions.setAlignment(Qt::AlignCenter); - mFontMetrics = new QFontMetrics(mFont); + m_font.setPixelSize(12); + m_textOptions.setAlignment(Qt::AlignCenter); + m_fontMetrics = new QFontMetrics(m_font); // Group nodes m_groupFont.setPixelSize(18); - m_groupFontMetrics = new QFontMetrics(mFont); + m_groupFontMetrics = new QFontMetrics(m_font); } @@ -99,7 +99,7 @@ namespace EMStudio { m_graphNodeByModelIndex.clear(); - delete mFontMetrics; + delete m_fontMetrics; } AZStd::vector NodeGraph::GetSelectedGraphNodes() const @@ -213,7 +213,7 @@ namespace EMStudio const QColor textColor = graphNode->GetIsHighlighted() ? QColor(0, 255, 0) : QColor(255, 255, 0); painter.setPen(textColor); - painter.setFont(mFont); + painter.setFont(m_font); QPoint textPosition = textRect.topLeft(); textPosition.setX(textPosition.x() + 3); @@ -222,32 +222,32 @@ namespace EMStudio // add the playspeed if (plugin->GetIsDisplayFlagEnabled(AnimGraphPlugin::DISPLAYFLAG_PLAYSPEED)) { - mQtTempString.asprintf("Play Speed = %.2f", emfxNode->GetPlaySpeed(animGraphInstance)); - painter.drawText(textPosition, mQtTempString); + m_qtTempString.asprintf("Play Speed = %.2f", emfxNode->GetPlaySpeed(animGraphInstance)); + painter.drawText(textPosition, m_qtTempString); textPosition.setY(textPosition.y() + heightSpacing); } // add the global weight if (plugin->GetIsDisplayFlagEnabled(AnimGraphPlugin::DISPLAYFLAG_GLOBALWEIGHT)) { - mQtTempString.asprintf("Global Weight = %.2f", uniqueData->GetGlobalWeight()); - painter.drawText(textPosition, mQtTempString); + m_qtTempString.asprintf("Global Weight = %.2f", uniqueData->GetGlobalWeight()); + painter.drawText(textPosition, m_qtTempString); textPosition.setY(textPosition.y() + heightSpacing); } // add the sync if (plugin->GetIsDisplayFlagEnabled(AnimGraphPlugin::DISPLAYFLAG_SYNCSTATUS)) { - mQtTempString.asprintf("Synced = %s", animGraphInstance->GetIsSynced(emfxNode->GetObjectIndex()) ? "Yes" : "No"); - painter.drawText(textPosition, mQtTempString); + m_qtTempString.asprintf("Synced = %s", animGraphInstance->GetIsSynced(emfxNode->GetObjectIndex()) ? "Yes" : "No"); + painter.drawText(textPosition, m_qtTempString); textPosition.setY(textPosition.y() + heightSpacing); } // add the play position if (plugin->GetIsDisplayFlagEnabled(AnimGraphPlugin::DISPLAYFLAG_PLAYPOSITION)) { - mQtTempString.asprintf("Play Time = %.3f / %.3f", uniqueData->GetCurrentPlayTime(), uniqueData->GetDuration()); - painter.drawText(textPosition, mQtTempString); + m_qtTempString.asprintf("Play Time = %.3f / %.3f", uniqueData->GetCurrentPlayTime(), uniqueData->GetDuration()); + painter.drawText(textPosition, m_qtTempString); textPosition.setY(textPosition.y() + heightSpacing); } } @@ -411,7 +411,7 @@ namespace EMStudio QPoint connectionAttachPoint = visualConnection->CalcFinalRect().center(); const int halfTextHeight = 6; - const int textWidth = mFontMetrics->horizontalAdvance(m_tempStringA.c_str()); + const int textWidth = m_fontMetrics->horizontalAdvance(m_tempStringA.c_str()); const int halfTextWidth = textWidth / 2; const QRect textRect(connectionAttachPoint.x() - halfTextWidth - 1, connectionAttachPoint.y() - halfTextHeight, textWidth + 4, halfTextHeight * 2); @@ -429,11 +429,8 @@ namespace EMStudio // draw the text const QColor& color = visualConnection->GetTargetNode()->GetInputPort(visualConnection->GetInputPortNr())->GetColor(); painter.setPen(color); - painter.setFont(mFont); - // OLD: - //painter.drawText( textPosition, mTempString.c_str() ); - // NEW: - GraphNode::RenderText(painter, m_tempStringA.c_str(), color, mFont, *mFontMetrics, Qt::AlignCenter, textRect); + painter.setFont(m_font); + GraphNode::RenderText(painter, m_tempStringA.c_str(), color, m_font, *m_fontMetrics, Qt::AlignCenter, textRect); } } } @@ -656,12 +653,12 @@ namespace EMStudio connection->SetIsTailHighlighted(false); } - if (mReplaceTransitionHead == connection) + if (m_replaceTransitionHead == connection) { connection->SetIsHeadHighlighted(true); } - if (mReplaceTransitionTail == connection) + if (m_replaceTransitionTail == connection) { connection->SetIsTailHighlighted(true); } @@ -693,8 +690,8 @@ namespace EMStudio void NodeGraph::Render(const QItemSelectionModel& selectionModel, QPainter& painter, int32 width, int32 height, const QPoint& mousePos, float timePassedInSeconds) { // control the scroll speed of the dashed blend tree connections etc - mDashOffset -= 7.5f * timePassedInSeconds; - mErrorBlinkOffset += 5.0f * timePassedInSeconds; + m_dashOffset -= 7.5f * timePassedInSeconds; + m_errorBlinkOffset += 5.0f * timePassedInSeconds; #ifdef GRAPH_PERFORMANCE_FRAMEDURATION MCore::Timer timer; @@ -706,11 +703,11 @@ namespace EMStudio //visibleRect.adjust(50, 50, -50, -50); // setup the transform - mTransform.reset(); - mTransform.translate(mScalePivot.x(), mScalePivot.y()); - mTransform.scale(mScale, mScale); - mTransform.translate(-mScalePivot.x() + mScrollOffset.x(), -mScalePivot.y() + mScrollOffset.y()); - painter.setTransform(mTransform); + m_transform.reset(); + m_transform.translate(m_scalePivot.x(), m_scalePivot.y()); + m_transform.scale(m_scale, m_scale); + m_transform.translate(-m_scalePivot.x() + m_scrollOffset.x(), -m_scalePivot.y() + m_scrollOffset.y()); + painter.setTransform(m_transform); // render the background #ifdef GRAPH_PERFORMANCE_INFO @@ -744,10 +741,10 @@ namespace EMStudio // calculate the connection stepsize // the higher the value, the less lines it renders (so faster) - int32 stepSize = aznumeric_cast(((1.0f / (mScale * (mScale * 1.75f))) * 10) - 7); - stepSize = MCore::Clamp(stepSize, mMinStepSize, mMaxStepSize); + int32 stepSize = aznumeric_cast(((1.0f / (m_scale * (m_scale * 1.75f))) * 10) - 7); + stepSize = MCore::Clamp(stepSize, m_minStepSize, m_maxStepSize); - QRect scaledVisibleRect = mTransform.inverted().mapRect(visibleRect); + QRect scaledVisibleRect = m_transform.inverted().mapRect(visibleRect); bool renderShadow = false; if (GetScale() >= 0.3f) @@ -791,7 +788,7 @@ namespace EMStudio StateConnection::RenderInterruptedTransitions(painter, GetAnimGraphModel(), *this); // render the entry state arrow - RenderEntryPoint(painter, mEntryNode); + RenderEntryPoint(painter, m_entryNode); #ifdef GRAPH_PERFORMANCE_FRAMEDURATION MCore::LogInfo("GraphRenderingTime: %.2f ms.", timer.GetTime() * 1000); @@ -815,7 +812,7 @@ namespace EMStudio painter.setOpacity(1.0f); painter.setPen(QColor(233, 233, 233)); - painter.setFont(mFont); + painter.setFont(m_font); painter.drawText(titleRect, text, QTextOption(Qt::AlignCenter)); painter.restore(); @@ -969,8 +966,8 @@ namespace EMStudio painter.setPen(QColor(40, 40, 40)); // calculate the coordinates in 'zoomed out and scrolled' coordinates, of the window rect - QPoint upperLeft = mTransform.inverted().map(QPoint(0, 0)); - QPoint lowerRight = mTransform.inverted().map(QPoint(width, height)); + QPoint upperLeft = m_transform.inverted().map(QPoint(0, 0)); + QPoint lowerRight = m_transform.inverted().map(QPoint(width, height)); // calculate the start and end ranges in 'scrolled and zoomed out' coordinates // we need to render sub-grids covering that area @@ -986,7 +983,7 @@ namespace EMStudio */ // calculate the alpha - float scale = mScale * mScale * 1.5f; + float scale = m_scale * m_scale * 1.5f; scale = MCore::Clamp(scale, 0.0f, 1.0f); const int32 alpha = aznumeric_cast(MCore::CalcCosineInterpolationWeight(scale) * 255); @@ -995,16 +992,14 @@ namespace EMStudio return; } - // mGridPen.setColor( QColor(58, 58, 58, alpha) ); - // mGridPen.setColor( QColor(46, 46, 46, alpha) ); - mGridPen.setColor(QColor(61, 61, 61, alpha)); - mSubgridPen.setColor(QColor(55, 55, 55, alpha)); + m_gridPen.setColor(QColor(61, 61, 61, alpha)); + m_subgridPen.setColor(QColor(55, 55, 55, alpha)); // setup spacing and size of the grid const int32 spacing = 10; // grid cell size of 20 // draw subgridlines first - painter.setPen(mSubgridPen); + painter.setPen(m_subgridPen); // draw vertical lines for (int32 x = startX; x < endX; x += spacing) @@ -1025,7 +1020,7 @@ namespace EMStudio } // draw render grid lines - painter.setPen(mGridPen); + painter.setPen(m_gridPen); // draw vertical lines for (int32 x = startX; x < endX; x += spacing) @@ -1292,8 +1287,8 @@ namespace EMStudio } else { - mScrollOffset = offset; - mScale = 1.0f; + m_scrollOffset = offset; + m_scale = 1.0f; } } else @@ -1309,7 +1304,7 @@ namespace EMStudio } else { - mScrollOffset = offset; + m_scrollOffset = offset; } // set the zoom factor so it exactly fits @@ -1333,7 +1328,7 @@ namespace EMStudio if (animate == false) { - mScale = MCore::Min(widthZoom, heightZoom); + m_scale = MCore::Min(widthZoom, heightZoom); } else { @@ -1346,10 +1341,10 @@ namespace EMStudio // start an animated scroll to the given scroll offset void NodeGraph::ScrollTo(const QPointF& point) { - mStartScrollOffset = mScrollOffset; - mTargetScrollOffset = point; - mScrollTimer.start(1000 / 60); - mScrollPreciseTimer.Stamp(); + m_startScrollOffset = m_scrollOffset; + m_targetScrollOffset = point; + m_scrollTimer.start(1000 / 60); + m_scrollPreciseTimer.Stamp(); } @@ -1358,16 +1353,15 @@ namespace EMStudio { const float duration = 0.75f; // duration in seconds - float timePassed = mScrollPreciseTimer.GetDeltaTimeInSeconds(); + float timePassed = m_scrollPreciseTimer.GetDeltaTimeInSeconds(); if (timePassed > duration) { timePassed = duration; - mScrollTimer.stop(); + m_scrollTimer.stop(); } const float t = timePassed / duration; - mScrollOffset = MCore::CosineInterpolate(mStartScrollOffset, mTargetScrollOffset, t).toPoint(); - //mGraphWidget->update(); + m_scrollOffset = MCore::CosineInterpolate(m_startScrollOffset, m_targetScrollOffset, t).toPoint(); } @@ -1376,16 +1370,15 @@ namespace EMStudio { const float duration = 0.75f; // duration in seconds - float timePassed = mScalePreciseTimer.GetDeltaTimeInSeconds(); + float timePassed = m_scalePreciseTimer.GetDeltaTimeInSeconds(); if (timePassed > duration) { timePassed = duration; - mScaleTimer.stop(); + m_scaleTimer.stop(); } const float t = timePassed / duration; - mScale = MCore::CosineInterpolate(mStartScale, mTargetScale, t); - //mGraphWidget->update(); + m_scale = MCore::CosineInterpolate(m_startScale, m_targetScale, t); } //static float scaleExp = 1.0f; @@ -1400,7 +1393,7 @@ namespace EMStudio //float t = -6 + (6 * scaleExp); //float newScale = 1/(1+exp(-t)) * 2; - float newScale = mScale + 0.35f; + float newScale = m_scale + 0.35f; newScale = MCore::Clamp(newScale, sLowestScale, 1.0f); ZoomTo(newScale); } @@ -1410,7 +1403,7 @@ namespace EMStudio // zoom out void NodeGraph::ZoomOut() { - float newScale = mScale - 0.35f; + float newScale = m_scale - 0.35f; //scaleExp -= 0.2f; //if (scaleExp < 0.01f) //scaleExp = 0.01f; @@ -1426,10 +1419,10 @@ namespace EMStudio // zoom to a given amount void NodeGraph::ZoomTo(float scale) { - mStartScale = mScale; - mTargetScale = scale; - mScaleTimer.start(1000 / 60); - mScalePreciseTimer.Stamp(); + m_startScale = m_scale; + m_targetScale = scale; + m_scaleTimer.start(1000 / 60); + m_scalePreciseTimer.Stamp(); if (scale < sLowestScale) { sLowestScale = scale; @@ -1440,14 +1433,14 @@ namespace EMStudio // stop an animated zoom void NodeGraph::StopAnimatedZoom() { - mScaleTimer.stop(); + m_scaleTimer.stop(); } // stop an animated scroll void NodeGraph::StopAnimatedScroll() { - mScrollTimer.stop(); + m_scrollTimer.stop(); } @@ -1462,7 +1455,7 @@ namespace EMStudio if (sceneRect.isEmpty() == false) { - const int border = aznumeric_cast(10.0f * (1.0f / mScale)); + const int border = aznumeric_cast(10.0f * (1.0f / m_scale)); sceneRect.adjust(-border, -border, border, border); ZoomOnRect(sceneRect, width, height, animate); } @@ -1500,20 +1493,20 @@ namespace EMStudio // start creating a connection void NodeGraph::StartCreateConnection(AZ::u16 portNr, bool isInputPort, GraphNode* portNode, NodePort* port, const QPoint& startOffset) { - mConPortNr = portNr; - mConIsInputPort = isInputPort; - mConNode = portNode; - mConPort = port; - mConStartOffset = startOffset; + m_conPortNr = portNr; + m_conIsInputPort = isInputPort; + m_conNode = portNode; + m_conPort = port; + m_conStartOffset = startOffset; } // start relinking a connection void NodeGraph::StartRelinkConnection(NodeConnection* connection, AZ::u16 portNr, GraphNode* node) { - mConPortNr = portNr; - mConNode = node; - mRelinkConnection = connection; + m_conPortNr = portNr; + m_conNode = node; + m_relinkConnection = connection; //MCore::LogInfo( "StartRelinkConnection: Connection=(%s->%s) portNr=%i, graphNode=%s", connection->GetSourceNode()->GetName(), connection->GetTargetNode()->GetName(), portNr, node->GetName() ); } @@ -1521,53 +1514,53 @@ namespace EMStudio void NodeGraph::StartReplaceTransitionHead(NodeConnection* connection, QPoint startOffset, QPoint endOffset, GraphNode* sourceNode, GraphNode* targetNode) { - mReplaceTransitionHead = connection; + m_replaceTransitionHead = connection; - mReplaceTransitionStartOffset = startOffset; - mReplaceTransitionEndOffset = endOffset; - mReplaceTransitionSourceNode = sourceNode; - mReplaceTransitionTargetNode = targetNode; + m_replaceTransitionStartOffset = startOffset; + m_replaceTransitionEndOffset = endOffset; + m_replaceTransitionSourceNode = sourceNode; + m_replaceTransitionTargetNode = targetNode; } void NodeGraph::StartReplaceTransitionTail(NodeConnection* connection, QPoint startOffset, QPoint endOffset, GraphNode* sourceNode, GraphNode* targetNode) { - mReplaceTransitionTail = connection; + m_replaceTransitionTail = connection; - mReplaceTransitionStartOffset = startOffset; - mReplaceTransitionEndOffset = endOffset; - mReplaceTransitionSourceNode = sourceNode; - mReplaceTransitionTargetNode = targetNode; + m_replaceTransitionStartOffset = startOffset; + m_replaceTransitionEndOffset = endOffset; + m_replaceTransitionSourceNode = sourceNode; + m_replaceTransitionTargetNode = targetNode; } void NodeGraph::GetReplaceTransitionInfo(NodeConnection** outOldConnection, QPoint* outOldStartOffset, QPoint* outOldEndOffset, GraphNode** outOldSourceNode, GraphNode** outOldTargetNode) { - if (mReplaceTransitionHead) + if (m_replaceTransitionHead) { - *outOldConnection = mReplaceTransitionHead; + *outOldConnection = m_replaceTransitionHead; } - if (mReplaceTransitionTail) + if (m_replaceTransitionTail) { - *outOldConnection = mReplaceTransitionTail; + *outOldConnection = m_replaceTransitionTail; } - *outOldStartOffset = mReplaceTransitionStartOffset; - *outOldEndOffset = mReplaceTransitionEndOffset; - *outOldSourceNode = mReplaceTransitionSourceNode; - *outOldTargetNode = mReplaceTransitionTargetNode; + *outOldStartOffset = m_replaceTransitionStartOffset; + *outOldEndOffset = m_replaceTransitionEndOffset; + *outOldSourceNode = m_replaceTransitionSourceNode; + *outOldTargetNode = m_replaceTransitionTargetNode; } void NodeGraph::StopReplaceTransitionHead() { - mReplaceTransitionHead = nullptr; + m_replaceTransitionHead = nullptr; } void NodeGraph::StopReplaceTransitionTail() { - mReplaceTransitionTail = nullptr; + m_replaceTransitionTail = nullptr; } @@ -1575,11 +1568,11 @@ namespace EMStudio // reset members void NodeGraph::StopRelinkConnection() { - mConPortNr = InvalidIndex16; - mConNode = nullptr; - mRelinkConnection = nullptr; - mConIsValid = false; - mTargetPort = nullptr; + m_conPortNr = InvalidIndex16; + m_conNode = nullptr; + m_relinkConnection = nullptr; + m_conIsValid = false; + m_targetPort = nullptr; } @@ -1587,12 +1580,12 @@ namespace EMStudio // reset members void NodeGraph::StopCreateConnection() { - mConPortNr = InvalidIndex16; - mConIsInputPort = true; - mConNode = nullptr; // nullptr when no connection is being created - mConPort = nullptr; - mTargetPort = nullptr; - mConIsValid = false; + m_conPortNr = InvalidIndex16; + m_conIsInputPort = true; + m_conNode = nullptr; // nullptr when no connection is being created + m_conPort = nullptr; + m_targetPort = nullptr; + m_conIsValid = false; } @@ -1672,7 +1665,7 @@ namespace EMStudio const AZ::u16 numInputPorts = node->GetNumInputPorts(); for (AZ::u16 i = 0; i < numInputPorts; ++i) { - if (CheckIfIsRelinkConnectionValid(mRelinkConnection, node, i, true)) + if (CheckIfIsRelinkConnectionValid(m_relinkConnection, node, i, true)) { QPoint tempStart = end; QPoint tempEnd = node->GetInputPort(i)->GetRect().center(); @@ -1686,9 +1679,9 @@ namespace EMStudio } // figure out the color of the connection line - if (mTargetPort) + if (m_targetPort) { - if (mConIsValid) + if (m_conIsValid) { painter.setPen(QColor(0, 255, 0)); } @@ -1780,14 +1773,13 @@ namespace EMStudio //------------------------------ // update the end point - //start = mConPort->GetRect().center(); start = GetCreateConnectionNode()->GetRect().topLeft() + GetCreateConnectionStartOffset(); end = m_graphWidget->GetMousePos(); // figure out the color of the connection line - if (mTargetPort) + if (m_targetPort) { - if (mConIsValid) + if (m_conIsValid) { painter.setPen(QColor(0, 255, 0)); } @@ -1967,9 +1959,9 @@ namespace EMStudio GraphNodeByModelIndex::const_iterator it = m_graphNodeByModelIndex.find(modelIndex); if (it != m_graphNodeByModelIndex.end()) { - if (it->second.get() == mEntryNode) + if (it->second.get() == m_entryNode) { - mEntryNode = nullptr; + m_entryNode = nullptr; } m_graphNodeByModelIndex.erase(it); } @@ -2489,11 +2481,7 @@ namespace EMStudio // draw the name on top color.setAlpha(255); - //painter.setPen( color ); - //mTempString = nodeGroup->GetName(); - //painter.setFont( m_groupFont ); GraphNode::RenderText(painter, nodeGroup->GetName(), color, m_groupFont, *m_groupFontMetrics, Qt::AlignLeft, textRect); - //painter.drawText( left - 7, top - 7, mTempString ); } } // for all node groups } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGraph.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGraph.h index 11490d8b49..47b316ff81 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGraph.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGraph.h @@ -49,43 +49,43 @@ namespace EMStudio bool IsInReferencedGraph() const { return m_parentReferenceNode.isValid(); } - const QTransform& GetTransform() const { return mTransform; } - float GetScale() const { return mScale; } - void SetScale(float scale) { mScale = scale; } - const QPoint& GetScrollOffset() const { return mScrollOffset; } - void SetScrollOffset(const QPoint& offset) { mScrollOffset = offset; } - void SetScalePivot(const QPoint& pivot) { mScalePivot = pivot; } + const QTransform& GetTransform() const { return m_transform; } + float GetScale() const { return m_scale; } + void SetScale(float scale) { m_scale = scale; } + const QPoint& GetScrollOffset() const { return m_scrollOffset; } + void SetScrollOffset(const QPoint& offset) { m_scrollOffset = offset; } + void SetScalePivot(const QPoint& pivot) { m_scalePivot = pivot; } float GetLowestScale() const { return sLowestScale; } - bool GetIsCreatingConnection() const { return (mConNode && mRelinkConnection == nullptr); } - bool GetIsRelinkingConnection() const { return (mConNode && mRelinkConnection); } - void SetCreateConnectionIsValid(bool isValid) { mConIsValid = isValid; } - bool GetIsCreateConnectionValid() const { return mConIsValid; } - void SetTargetPort(NodePort* port) { mTargetPort = port; } - NodePort* GetTargetPort() { return mTargetPort; } - float GetDashOffset() const { return mDashOffset; } - QColor GetErrorBlinkColor() const { int32 red = aznumeric_cast(160 + ((0.5f + 0.5f * MCore::Math::Cos(mErrorBlinkOffset)) * 96)); red = MCore::Clamp(red, 0, 255); return QColor(red, 0, 0); } + bool GetIsCreatingConnection() const { return (m_conNode && m_relinkConnection == nullptr); } + bool GetIsRelinkingConnection() const { return (m_conNode && m_relinkConnection); } + void SetCreateConnectionIsValid(bool isValid) { m_conIsValid = isValid; } + bool GetIsCreateConnectionValid() const { return m_conIsValid; } + void SetTargetPort(NodePort* port) { m_targetPort = port; } + NodePort* GetTargetPort() { return m_targetPort; } + float GetDashOffset() const { return m_dashOffset; } + QColor GetErrorBlinkColor() const { int32 red = aznumeric_cast(160 + ((0.5f + 0.5f * MCore::Math::Cos(m_errorBlinkOffset)) * 96)); red = MCore::Clamp(red, 0, 255); return QColor(red, 0, 0); } - bool GetIsRepositioningTransitionHead() const { return (mReplaceTransitionHead); } - bool GetIsRepositioningTransitionTail() const { return (mReplaceTransitionTail); } - NodeConnection* GetRepositionedTransitionHead() const { return mReplaceTransitionHead; } - NodeConnection* GetRepositionedTransitionTail() const { return mReplaceTransitionTail; } + bool GetIsRepositioningTransitionHead() const { return (m_replaceTransitionHead); } + bool GetIsRepositioningTransitionTail() const { return (m_replaceTransitionTail); } + NodeConnection* GetRepositionedTransitionHead() const { return m_replaceTransitionHead; } + NodeConnection* GetRepositionedTransitionTail() const { return m_replaceTransitionTail; } void StartReplaceTransitionHead(NodeConnection* connection, QPoint startOffset, QPoint endOffset, GraphNode* sourceNode, GraphNode* targetNode); void StartReplaceTransitionTail(NodeConnection* connection, QPoint startOffset, QPoint endOffset, GraphNode* sourceNode, GraphNode* targetNode); void GetReplaceTransitionInfo(NodeConnection** outConnection, QPoint* outOldStartOffset, QPoint* outOldEndOffset, GraphNode** outOldSourceNode, GraphNode** outOldTargetNode); void StopReplaceTransitionHead(); void StopReplaceTransitionTail(); - void SetReplaceTransitionValid(bool isValid) { mReplaceTransitionValid = isValid; } - bool GetReplaceTransitionValid() const { return mReplaceTransitionValid; } + void SetReplaceTransitionValid(bool isValid) { m_replaceTransitionValid = isValid; } + bool GetReplaceTransitionValid() const { return m_replaceTransitionValid; } void RenderReplaceTransition(QPainter& painter); - GraphNode* GetCreateConnectionNode() { return mConNode; } - NodeConnection* GetRelinkConnection() { return mRelinkConnection; } - AZ::u16 GetCreateConnectionPortNr() const { return mConPortNr; } - bool GetCreateConnectionIsInputPort() const { return mConIsInputPort; } - const QPoint& GetCreateConnectionStartOffset() const { return mConStartOffset; } - const QPoint& GetCreateConnectionEndOffset() const { return mConEndOffset; } - void SetCreateConnectionEndOffset(const QPoint& offset){ mConEndOffset = offset; } + GraphNode* GetCreateConnectionNode() { return m_conNode; } + NodeConnection* GetRelinkConnection() { return m_relinkConnection; } + AZ::u16 GetCreateConnectionPortNr() const { return m_conPortNr; } + bool GetCreateConnectionIsInputPort() const { return m_conIsInputPort; } + const QPoint& GetCreateConnectionStartOffset() const { return m_conStartOffset; } + const QPoint& GetCreateConnectionEndOffset() const { return m_conEndOffset; } + void SetCreateConnectionEndOffset(const QPoint& offset){ m_conEndOffset = offset; } bool CheckIfHasConnection(GraphNode* sourceNode, AZ::u16 outputPortNr, GraphNode* targetNode, AZ::u16 inputPortNr) const; NodeConnection* FindInputConnection(GraphNode* targetNode, AZ::u16 targetPortNr) const; @@ -121,7 +121,7 @@ namespace EMStudio NodePort* FindPort(int32 x, int32 y, GraphNode** outNode, AZ::u16* outPortNr, bool* outIsInputPort, bool includeInputPorts = true); // entry state helper functions - void SetEntryNode(GraphNode* entryNode) { mEntryNode = entryNode; } + void SetEntryNode(GraphNode* entryNode) { m_entryNode = entryNode; } static void RenderEntryPoint(QPainter& painter, GraphNode* node); void FitGraphOnScreen(int32 width, int32 height, const QPoint& mousePos, bool animate = true); @@ -140,8 +140,8 @@ namespace EMStudio static bool LineIntersectsRect(const QRect& b, float x1, float y1, float x2, float y2, double* outX = nullptr, double* outY = nullptr); void DrawOverlay(QPainter& painter); - bool GetUseAnimation() const { return mUseAnimation; } - void SetUseAnimation(bool useAnim) { mUseAnimation = useAnim; } + bool GetUseAnimation() const { return m_useAnimation; } + void SetUseAnimation(bool useAnim) { m_useAnimation = useAnim; } // These methods are not slots, they are being called from BlendGraphWidget void OnRowsAboutToBeRemoved(const QModelIndexList& modelIndexes); @@ -175,55 +175,55 @@ namespace EMStudio using GraphNodeByModelIndex = AZStd::unordered_map, QPersistentModelIndexHash>; GraphNodeByModelIndex m_graphNodeByModelIndex; - GraphNode* mEntryNode; - QTransform mTransform; - float mScale; + GraphNode* m_entryNode; + QTransform m_transform; + float m_scale; static float sLowestScale; - int32 mMinStepSize; - int32 mMaxStepSize; - QPoint mScrollOffset; - QPoint mScalePivot; + int32 m_minStepSize; + int32 m_maxStepSize; + QPoint m_scrollOffset; + QPoint m_scalePivot; - QPointF mTargetScrollOffset; - QPointF mStartScrollOffset; - QTimer mScrollTimer; - AZ::Debug::Timer mScrollPreciseTimer; + QPointF m_targetScrollOffset; + QPointF m_startScrollOffset; + QTimer m_scrollTimer; + AZ::Debug::Timer m_scrollPreciseTimer; - float mTargetScale; - float mStartScale; - QTimer mScaleTimer; - AZ::Debug::Timer mScalePreciseTimer; + float m_targetScale; + float m_startScale; + QTimer m_scaleTimer; + AZ::Debug::Timer m_scalePreciseTimer; // connection info - QPoint mConStartOffset; - QPoint mConEndOffset; - AZ::u16 mConPortNr; - bool mConIsInputPort; - GraphNode* mConNode; // nullptr when no connection is being created - NodeConnection* mRelinkConnection; // nullptr when not relinking a connection - NodePort* mConPort; - NodePort* mTargetPort; - bool mConIsValid; - float mDashOffset; - float mErrorBlinkOffset; - bool mUseAnimation; + QPoint m_conStartOffset; + QPoint m_conEndOffset; + AZ::u16 m_conPortNr; + bool m_conIsInputPort; + GraphNode* m_conNode; // nullptr when no connection is being created + NodeConnection* m_relinkConnection; // nullptr when not relinking a connection + NodePort* m_conPort; + NodePort* m_targetPort; + bool m_conIsValid; + float m_dashOffset; + float m_errorBlinkOffset; + bool m_useAnimation; - NodeConnection* mReplaceTransitionHead; // nullptr when not replacing a transition head - NodeConnection* mReplaceTransitionTail; // nullptr when not replacing a transition tail - QPoint mReplaceTransitionStartOffset; - QPoint mReplaceTransitionEndOffset; - GraphNode* mReplaceTransitionSourceNode; - GraphNode* mReplaceTransitionTargetNode; - bool mReplaceTransitionValid; + NodeConnection* m_replaceTransitionHead; // nullptr when not replacing a transition head + NodeConnection* m_replaceTransitionTail; // nullptr when not replacing a transition tail + QPoint m_replaceTransitionStartOffset; + QPoint m_replaceTransitionEndOffset; + GraphNode* m_replaceTransitionSourceNode; + GraphNode* m_replaceTransitionTargetNode; + bool m_replaceTransitionValid; - QPen mSubgridPen; - QPen mGridPen; + QPen m_subgridPen; + QPen m_gridPen; // Overlay drawing - QFont mFont; - QString mQtTempString; - QTextOption mTextOptions; - QFontMetrics* mFontMetrics; + QFont m_font; + QString m_qtTempString; + QTextOption m_textOptions; + QFontMetrics* m_fontMetrics; AZStd::string m_tempStringA; AZStd::string m_tempStringB; AZStd::string m_tempStringC; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGraphWidget.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGraphWidget.cpp index d7afe634a1..c8085a876a 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGraphWidget.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGraphWidget.cpp @@ -37,8 +37,8 @@ namespace EMStudio { setObjectName("NodeGraphWidget"); - mPlugin = plugin; - mFontMetrics = new QFontMetrics(mFont); + m_plugin = plugin; + m_fontMetrics = new QFontMetrics(m_font); // update the active graph SetActiveGraph(activeGraph); @@ -47,19 +47,19 @@ namespace EMStudio setMouseTracking(true); // init members - mShowFPS = false; - mLeftMousePressed = false; - mPanning = false; - mMiddleMousePressed = false; - mRightMousePressed = false; - mRectSelecting = false; - mShiftPressed = false; - mControlPressed = false; - mAltPressed = false; - mMoveNode = nullptr; - mMouseLastPos = QPoint(0, 0); - mMouseLastPressPos = QPoint(0, 0); - mMousePos = QPoint(0, 0); + m_showFps = false; + m_leftMousePressed = false; + m_panning = false; + m_middleMousePressed = false; + m_rightMousePressed = false; + m_rectSelecting = false; + m_shiftPressed = false; + m_controlPressed = false; + m_altPressed = false; + m_moveNode = nullptr; + m_mouseLastPos = QPoint(0, 0); + m_mouseLastPressPos = QPoint(0, 0); + m_mousePos = QPoint(0, 0); // setup to get focus when we click or use the mouse wheel setFocusPolicy((Qt::FocusPolicy)(Qt::ClickFocus | Qt::WheelFocus)); @@ -70,10 +70,10 @@ namespace EMStudio setAutoFillBackground(false); setAttribute(Qt::WA_OpaquePaintEvent); - mCurWidth = geometry().width(); - mCurHeight = geometry().height(); - mPrevWidth = mCurWidth; - mPrevHeight = mCurHeight; + m_curWidth = geometry().width(); + m_curHeight = geometry().height(); + m_prevWidth = m_curWidth; + m_prevHeight = m_curHeight; } @@ -81,7 +81,7 @@ namespace EMStudio NodeGraphWidget::~NodeGraphWidget() { // delete the overlay font metrics - delete mFontMetrics; + delete m_fontMetrics; } @@ -98,20 +98,20 @@ namespace EMStudio { static QPoint sizeDiff(0, 0); - mCurWidth = w; - mCurHeight = h; + m_curWidth = w; + m_curHeight = h; // specify the center of the window, so that that is the origin - if (mActiveGraph) + if (m_activeGraph) { - mActiveGraph->SetScalePivot(QPoint(w / 2, h / 2)); + m_activeGraph->SetScalePivot(QPoint(w / 2, h / 2)); - QPoint scrollOffset = mActiveGraph->GetScrollOffset(); + QPoint scrollOffset = m_activeGraph->GetScrollOffset(); int32 scrollOffsetX = scrollOffset.x(); int32 scrollOffsetY = scrollOffset.y(); // calculate the size delta - QPoint oldSize = QPoint(mPrevWidth, mPrevHeight); + QPoint oldSize = QPoint(m_prevWidth, m_prevHeight); QPoint size = QPoint(w, h); QPoint diff = oldSize - size; sizeDiff += diff; @@ -136,35 +136,35 @@ namespace EMStudio sizeDiff.setY(modRes); } - mActiveGraph->SetScrollOffset(QPoint(scrollOffsetX, scrollOffsetY)); + m_activeGraph->SetScrollOffset(QPoint(scrollOffsetX, scrollOffsetY)); //MCore::LOG("%d, %d", scrollOffsetX, scrollOffsetY); } QOpenGLWidget::resizeGL(w, h); - mPrevWidth = w; - mPrevHeight = h; + m_prevWidth = w; + m_prevHeight = h; } // set the active graph void NodeGraphWidget::SetActiveGraph(NodeGraph* graph) { - if (mActiveGraph == graph) + if (m_activeGraph == graph) { return; } - if (mActiveGraph) + if (m_activeGraph) { - mActiveGraph->StopCreateConnection(); - mActiveGraph->StopRelinkConnection(); - mActiveGraph->StopReplaceTransitionHead(); - mActiveGraph->StopReplaceTransitionTail(); + m_activeGraph->StopCreateConnection(); + m_activeGraph->StopRelinkConnection(); + m_activeGraph->StopReplaceTransitionHead(); + m_activeGraph->StopReplaceTransitionTail(); } - mActiveGraph = graph; - mMoveNode = nullptr; + m_activeGraph = graph; + m_moveNode = nullptr; emit ActiveGraphChanged(); } @@ -173,7 +173,7 @@ namespace EMStudio // get the active graph NodeGraph* NodeGraphWidget::GetActiveGraph() const { - return mActiveGraph; + return m_activeGraph; } @@ -193,7 +193,7 @@ namespace EMStudio glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // calculate the time passed since the last render - const float timePassedInSeconds = mRenderTimer.StampAndGetDeltaTimeInSeconds(); + const float timePassedInSeconds = m_renderTimer.StampAndGetDeltaTimeInSeconds(); // start painting QPainter painter(this); @@ -202,8 +202,8 @@ namespace EMStudio painter.setRenderHint(QPainter::TextAntialiasing); // get the width and height - const uint32 width = mCurWidth; - const uint32 height = mCurHeight; + const uint32 width = m_curWidth; + const uint32 height = m_curHeight; // fill the background //painter.fillRect( event->rect(), QColor(30, 30, 30) ); @@ -212,19 +212,19 @@ namespace EMStudio painter.drawRect(QRect(0, 0, width, height)); // render the active graph - if (mActiveGraph) + if (m_activeGraph) { - mActiveGraph->Render(mPlugin->GetAnimGraphModel().GetSelectionModel(), painter, width, height, mMousePos, timePassedInSeconds); + m_activeGraph->Render(m_plugin->GetAnimGraphModel().GetSelectionModel(), painter, width, height, m_mousePos, timePassedInSeconds); } // render selection rect - if (mRectSelecting) + if (m_rectSelecting) { painter.resetTransform(); QRect selectRect; CalcSelectRect(selectRect); - if (mAltPressed) + if (m_altPressed) { painter.setBrush(QColor(0, 100, 200, 75)); painter.setPen(QColor(0, 100, 255)); @@ -242,10 +242,10 @@ namespace EMStudio OnDrawOverlay(painter); // render the callback overlay - if (mActiveGraph) + if (m_activeGraph) { painter.resetTransform(); - mActiveGraph->DrawOverlay(painter); + m_activeGraph->DrawOverlay(painter); } // draw the border @@ -277,7 +277,7 @@ namespace EMStudio //painter.setBackgroundMode(Qt::TransparentMode); // render FPS counter - if (mShowFPS) + if (m_showFps) { // get the time delta between the current time and the last frame static AZ::Debug::Timer perfTimer; @@ -288,7 +288,7 @@ namespace EMStudio static uint32 fpsNumFrames = 0; static uint32 lastFPS = 0; fpsTimeElapsed += perfTimeDelta; - const float renderTime = mRenderTimer.StampAndGetDeltaTimeInSeconds() * 1000.0f; + const float renderTime = m_renderTimer.StampAndGetDeltaTimeInSeconds() * 1000.0f; fpsNumFrames++; if (fpsTimeElapsed > 1.0f) { @@ -300,7 +300,7 @@ namespace EMStudio static AZStd::string perfTempString; perfTempString = AZStd::string::format("%i FPS (%.1f ms)", lastFPS, renderTime); - GraphNode::RenderText(painter, perfTempString.c_str(), QColor(150, 150, 150), mFont, *mFontMetrics, Qt::AlignRight, QRect(width - 55, height - 20, 50, 20)); + GraphNode::RenderText(painter, perfTempString.c_str(), QColor(150, 150, 150), m_font, *m_fontMetrics, Qt::AlignRight, QRect(width - 55, height - 20, 50, 20)); } // show the info to which actor the currently rendered graph belongs to @@ -312,13 +312,13 @@ namespace EMStudio EMotionFX::ActorInstance* firstActorInstance = selectionList.GetFirstActorInstance(); // update the stored short filename without path - if (mFullActorName != firstActorInstance->GetActor()->GetFileName()) + if (m_fullActorName != firstActorInstance->GetActor()->GetFileName()) { - AzFramework::StringFunc::Path::GetFileName(firstActorInstance->GetActor()->GetFileNameString().c_str(), mActorName); + AzFramework::StringFunc::Path::GetFileName(firstActorInstance->GetActor()->GetFileNameString().c_str(), m_actorName); } - mTempString = AZStd::string::format("Showing graph for ActorInstance with ID %d and Actor file \"%s\"", firstActorInstance->GetID(), mActorName.c_str()); - GraphNode::RenderText(painter, mTempString.c_str(), QColor(150, 150, 150), mFont, *mFontMetrics, Qt::AlignLeft, QRect(8, 0, 50, 20)); + m_tempString = AZStd::string::format("Showing graph for ActorInstance with ID %d and Actor file \"%s\"", firstActorInstance->GetID(), m_actorName.c_str()); + GraphNode::RenderText(painter, m_tempString.c_str(), QColor(150, 150, 150), m_font, *m_fontMetrics, Qt::AlignLeft, QRect(8, 0, 50, 20)); } } @@ -326,9 +326,9 @@ namespace EMStudio // convert to a global position QPoint NodeGraphWidget::LocalToGlobal(const QPoint& inPoint) const { - if (mActiveGraph) + if (m_activeGraph) { - return mActiveGraph->GetTransform().inverted().map(inPoint); + return m_activeGraph->GetTransform().inverted().map(inPoint); } return inPoint; @@ -338,9 +338,9 @@ namespace EMStudio // convert to a local position QPoint NodeGraphWidget::GlobalToLocal(const QPoint& inPoint) const { - if (mActiveGraph) + if (m_activeGraph) { - return mActiveGraph->GetTransform().map(inPoint); + return m_activeGraph->GetTransform().map(inPoint); } return inPoint; @@ -351,19 +351,16 @@ namespace EMStudio { MCORE_UNUSED(cellSize); - //QPoint scaledMouseDelta = (mousePos - mMouseLastPos) * (1.0f / mActiveGraph->GetScale()); - //QPoint unSnappedTopRight = oldTopRight + scaledMouseDelta; QPoint snapped; snapped.setX(inPoint.x() - aznumeric_cast(MCore::Math::FMod(aznumeric_cast(inPoint.x()), 10.0f))); snapped.setY(inPoint.y() - aznumeric_cast(MCore::Math::FMod(aznumeric_cast(inPoint.y()), 10.0f))); - //snapDelta = snappedTopRight - unSnappedTopRight; return snapped; } // mouse is moving over the widget void NodeGraphWidget::mouseMoveEvent(QMouseEvent* event) { - if (mActiveGraph == nullptr) + if (m_activeGraph == nullptr) { return; } @@ -372,51 +369,51 @@ namespace EMStudio QPoint mousePos = event->pos(); QPoint snapDelta(0, 0); - if (mMoveNode && mLeftMousePressed && mPanning == false && mRectSelecting == false) + if (m_moveNode && m_leftMousePressed && m_panning == false && m_rectSelecting == false) { - QPoint oldTopRight = mMoveNode->GetRect().topRight(); - QPoint scaledMouseDelta = (mousePos - mMouseLastPos) * (1.0f / mActiveGraph->GetScale()); + QPoint oldTopRight = m_moveNode->GetRect().topRight(); + QPoint scaledMouseDelta = (mousePos - m_mouseLastPos) * (1.0f / m_activeGraph->GetScale()); QPoint unSnappedTopRight = oldTopRight + scaledMouseDelta; QPoint snappedTopRight = SnapLocalToGrid(unSnappedTopRight, 10); snapDelta = snappedTopRight - unSnappedTopRight; } - mousePos += snapDelta * mActiveGraph->GetScale(); - QPoint delta = (mousePos - mMouseLastPos) * (1.0f / mActiveGraph->GetScale()); - mMouseLastPos = mousePos; + mousePos += snapDelta * m_activeGraph->GetScale(); + QPoint delta = (mousePos - m_mouseLastPos) * (1.0f / m_activeGraph->GetScale()); + m_mouseLastPos = mousePos; QPoint globalPos = LocalToGlobal(mousePos); SetMousePos(globalPos); //if (delta.x() > 0 || delta.x() < -0 || delta.y() > 0 || delta.y() < -0) if (delta.x() != 0 || delta.y() != 0) { - mAllowContextMenu = false; + m_allowContextMenu = false; } // update modifiers - mAltPressed = event->modifiers() & Qt::AltModifier; - mShiftPressed = event->modifiers() & Qt::ShiftModifier; - mControlPressed = event->modifiers() & Qt::ControlModifier; + m_altPressed = event->modifiers() & Qt::AltModifier; + m_shiftPressed = event->modifiers() & Qt::ShiftModifier; + m_controlPressed = event->modifiers() & Qt::ControlModifier; /*GraphNode* node = */ UpdateMouseCursor(mousePos, globalPos); - if (mRectSelecting == false && mMoveNode == nullptr && - mPlugin->GetActionFilter().m_editConnections && - !mActiveGraph->IsInReferencedGraph()) + if (m_rectSelecting == false && m_moveNode == nullptr && + m_plugin->GetActionFilter().m_editConnections && + !m_activeGraph->IsInReferencedGraph()) { // check if we are clicking on a port GraphNode* portNode = nullptr; NodePort* port = nullptr; AZ::u16 portNr = InvalidIndex16; bool isInputPort = true; - port = mActiveGraph->FindPort(globalPos.x(), globalPos.y(), &portNode, &portNr, &isInputPort); + port = m_activeGraph->FindPort(globalPos.x(), globalPos.y(), &portNode, &portNr, &isInputPort); // check if we are adjusting a transition head or tail - if (mActiveGraph->GetIsRepositioningTransitionHead() || mActiveGraph->GetIsRepositioningTransitionTail()) + if (m_activeGraph->GetIsRepositioningTransitionHead() || m_activeGraph->GetIsRepositioningTransitionTail()) { - NodeConnection* connection = mActiveGraph->GetRepositionedTransitionHead(); + NodeConnection* connection = m_activeGraph->GetRepositionedTransitionHead(); if (connection == nullptr) { - connection = mActiveGraph->GetRepositionedTransitionTail(); + connection = m_activeGraph->GetRepositionedTransitionTail(); } MCORE_ASSERT(connection->GetType() == StateConnection::TYPE_ID); @@ -426,13 +423,13 @@ namespace EMStudio if (transition) { // check if our mouse is-over a node - GraphNode* hoveredNode = mActiveGraph->FindNode(mousePos); + GraphNode* hoveredNode = m_activeGraph->FindNode(mousePos); if (hoveredNode == nullptr && portNode) { hoveredNode = portNode; } - if (mActiveGraph->GetIsRepositioningTransitionHead()) + if (m_activeGraph->GetIsRepositioningTransitionHead()) { // when adjusting the arrow head and we are over the source node with the mouse if (hoveredNode @@ -440,11 +437,11 @@ namespace EMStudio && CheckIfIsValidTransition(stateConnection->GetSourceNode(), hoveredNode)) { stateConnection->SetTargetNode(hoveredNode); - mActiveGraph->SetReplaceTransitionValid(true); + m_activeGraph->SetReplaceTransitionValid(true); } else { - mActiveGraph->SetReplaceTransitionValid(false); + m_activeGraph->SetReplaceTransitionValid(false); } GraphNode* targetNode = stateConnection->GetTargetNode(); @@ -455,7 +452,7 @@ namespace EMStudio newEndOffset.x(), newEndOffset.y()); } } - else if (mActiveGraph->GetIsRepositioningTransitionTail()) + else if (m_activeGraph->GetIsRepositioningTransitionTail()) { // when adjusting the arrow tail and we are over the target node with the mouse if (hoveredNode @@ -463,11 +460,11 @@ namespace EMStudio && CheckIfIsValidTransition(hoveredNode, stateConnection->GetTargetNode())) { stateConnection->SetSourceNode(hoveredNode); - mActiveGraph->SetReplaceTransitionValid(true); + m_activeGraph->SetReplaceTransitionValid(true); } else { - mActiveGraph->SetReplaceTransitionValid(false); + m_activeGraph->SetReplaceTransitionValid(false); } GraphNode* sourceNode = stateConnection->GetSourceNode(); @@ -484,19 +481,19 @@ namespace EMStudio // connection relinking or creation if (port) { - if (mActiveGraph->GetIsCreatingConnection()) + if (m_activeGraph->GetIsCreatingConnection()) { const bool isValid = CheckIfIsCreateConnectionValid(portNr, portNode, port, isInputPort); - mActiveGraph->SetCreateConnectionIsValid(isValid); - mActiveGraph->SetTargetPort(port); + m_activeGraph->SetCreateConnectionIsValid(isValid); + m_activeGraph->SetTargetPort(port); //update(); return; } - else if (mActiveGraph->GetIsRelinkingConnection()) + else if (m_activeGraph->GetIsRelinkingConnection()) { - bool isValid = NodeGraph::CheckIfIsRelinkConnectionValid(mActiveGraph->GetRelinkConnection(), portNode, portNr, isInputPort); - mActiveGraph->SetCreateConnectionIsValid(isValid); - mActiveGraph->SetTargetPort(port); + bool isValid = NodeGraph::CheckIfIsRelinkConnectionValid(m_activeGraph->GetRelinkConnection(), portNode, portNr, isInputPort); + m_activeGraph->SetCreateConnectionIsValid(isValid); + m_activeGraph->SetTargetPort(port); //update(); return; } @@ -512,12 +509,12 @@ namespace EMStudio } else { - mActiveGraph->SetTargetPort(nullptr); + m_activeGraph->SetTargetPort(nullptr); } } // if we are panning - if (mPanning) + if (m_panning) { // handle mouse wrapping, to enable smoother panning bool mouseWrapped = false; @@ -525,26 +522,26 @@ namespace EMStudio { mouseWrapped = true; QCursor::setPos(QPoint(event->globalX() - width(), event->globalY())); - mMouseLastPos = QPoint(event->x() - width(), event->y()); + m_mouseLastPos = QPoint(event->x() - width(), event->y()); } else if (event->x() < 0) { mouseWrapped = true; QCursor::setPos(QPoint(event->globalX() + width(), event->globalY())); - mMouseLastPos = QPoint(event->x() + width(), event->y()); + m_mouseLastPos = QPoint(event->x() + width(), event->y()); } if (event->y() > (int32)height()) { mouseWrapped = true; QCursor::setPos(QPoint(event->globalX(), event->globalY() - height())); - mMouseLastPos = QPoint(event->x(), event->y() - height()); + m_mouseLastPos = QPoint(event->x(), event->y() - height()); } else if (event->y() < 0) { mouseWrapped = true; QCursor::setPos(QPoint(event->globalX(), event->globalY() + height())); - mMouseLastPos = QPoint(event->x(), event->y() + height()); + m_mouseLastPos = QPoint(event->x(), event->y() + height()); } // don't apply the delta, if mouse has been wrapped @@ -553,15 +550,15 @@ namespace EMStudio delta = QPoint(0, 0); } - if (mActiveGraph) + if (m_activeGraph) { // scrolling - if (mAltPressed == false) + if (m_altPressed == false) { - QPoint newOffset = mActiveGraph->GetScrollOffset(); + QPoint newOffset = m_activeGraph->GetScrollOffset(); newOffset += delta; - mActiveGraph->SetScrollOffset(newOffset); - mActiveGraph->StopAnimatedScroll(); + m_activeGraph->SetScrollOffset(newOffset); + m_activeGraph->StopAnimatedScroll(); UpdateMouseCursor(mousePos, globalPos); //update(); return; @@ -570,12 +567,12 @@ namespace EMStudio else { // stop the automated zoom - mActiveGraph->StopAnimatedZoom(); + m_activeGraph->StopAnimatedZoom(); // calculate the new scale value const float scaleDelta = (delta.y() / 120.0f) * 0.2f; - float newScale = MCore::Clamp(mActiveGraph->GetScale() + scaleDelta, mActiveGraph->GetLowestScale(), 1.0f); - mActiveGraph->SetScale(newScale); + float newScale = MCore::Clamp(m_activeGraph->GetScale() + scaleDelta, m_activeGraph->GetLowestScale(), 1.0f); + m_activeGraph->SetScale(newScale); // redraw the viewport //update(); @@ -584,15 +581,15 @@ namespace EMStudio } // if the left mouse button is pressed - if (mLeftMousePressed) + if (m_leftMousePressed) { - if (mMoveNode) + if (m_moveNode) { - if (mActiveGraph && - mPlugin->GetActionFilter().m_editNodes && - !mActiveGraph->IsInReferencedGraph()) + if (m_activeGraph && + m_plugin->GetActionFilter().m_editNodes && + !m_activeGraph->IsInReferencedGraph()) { - const AZStd::vector selectedGraphNodes = mActiveGraph->GetSelectedGraphNodes(); + const AZStd::vector selectedGraphNodes = m_activeGraph->GetSelectedGraphNodes(); if (!selectedGraphNodes.empty()) { // move all selected nodes @@ -601,9 +598,9 @@ namespace EMStudio graphNode->MoveRelative(delta); } } - else if (mMoveNode) + else if (m_moveNode) { - mMoveNode->MoveRelative(delta); + m_moveNode->MoveRelative(delta); } return; } @@ -612,9 +609,9 @@ namespace EMStudio { //setCursor( Qt::ArrowCursor ); - if (mRectSelecting) + if (m_rectSelecting) { - mSelectEnd = mousePos; + m_selectEnd = mousePos; } } @@ -632,27 +629,27 @@ namespace EMStudio // mouse button has been pressed void NodeGraphWidget::mousePressEvent(QMouseEvent* event) { - if (!mActiveGraph) + if (!m_activeGraph) { return; } GetMainWindow()->DisableUndoRedo(); - mAllowContextMenu = true; + m_allowContextMenu = true; // get the mouse position, calculate the global mouse position and update the relevant data QPoint mousePos = event->pos(); - mMouseLastPos = mousePos; - mMouseLastPressPos = mousePos; + m_mouseLastPos = mousePos; + m_mouseLastPressPos = mousePos; QPoint globalPos = LocalToGlobal(mousePos); SetMousePos(globalPos); // update modifiers - mAltPressed = event->modifiers() & Qt::AltModifier; - mShiftPressed = event->modifiers() & Qt::ShiftModifier; - mControlPressed = event->modifiers() & Qt::ControlModifier; - const AnimGraphActionFilter& actionFilter = mPlugin->GetActionFilter(); + m_altPressed = event->modifiers() & Qt::AltModifier; + m_shiftPressed = event->modifiers() & Qt::ShiftModifier; + m_controlPressed = event->modifiers() & Qt::ControlModifier; + const AnimGraphActionFilter& actionFilter = m_plugin->GetActionFilter(); // check if we can start panning if ((event->buttons() & Qt::RightButton && event->buttons() & Qt::LeftButton) || event->button() == Qt::RightButton || event->button() == Qt::MidButton) @@ -660,21 +657,21 @@ namespace EMStudio // update button booleans if (event->buttons() & Qt::RightButton && event->buttons() & Qt::LeftButton) { - mLeftMousePressed = true; - mRightMousePressed = true; + m_leftMousePressed = true; + m_rightMousePressed = true; } if (event->button() == Qt::RightButton) { - mRightMousePressed = true; + m_rightMousePressed = true; GraphNode* node = UpdateMouseCursor(mousePos, globalPos); if (node && node->GetCanVisualize() && node->GetIsInsideVisualizeRect(globalPos)) { OnSetupVisualizeOptions(node); - mRectSelecting = false; - mPanning = false; - mMoveNode = nullptr; + m_rectSelecting = false; + m_panning = false; + m_moveNode = nullptr; //update(); return; } @@ -682,7 +679,7 @@ namespace EMStudio // Right click on the node will trigger a single selection, if the node is not already selected. if (node && !node->GetIsSelected() && !node->GetIsInsideArrowRect(globalPos)) { - mPlugin->GetAnimGraphModel().GetSelectionModel().select(QItemSelection(node->GetModelIndex(), node->GetModelIndex()), + m_plugin->GetAnimGraphModel().GetSelectionModel().select(QItemSelection(node->GetModelIndex(), node->GetModelIndex()), QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); return; } @@ -690,37 +687,33 @@ namespace EMStudio if (event->button() == Qt::MidButton) { - mMiddleMousePressed = true; + m_middleMousePressed = true; } - mPanning = true; - mRectSelecting = false; + m_panning = true; + m_rectSelecting = false; setCursor(Qt::ClosedHandCursor); - //mMoveNode = nullptr; - - // update viewport and return - //update(); return; } // if we press the left mouse button if (event->button() == Qt::LeftButton) { - mLeftMousePressed = true; + m_leftMousePressed = true; // get the node we click on GraphNode* node = UpdateMouseCursor(mousePos, globalPos); // if we pressed the visualize icon - GraphNode* orgNode = mActiveGraph->FindNode(mousePos); + GraphNode* orgNode = m_activeGraph->FindNode(mousePos); if (orgNode && orgNode->GetCanVisualize() && orgNode->GetIsInsideVisualizeRect(globalPos)) { const bool viz = !orgNode->GetIsVisualized(); orgNode->SetIsVisualized(viz); OnVisualizeToggle(orgNode, viz); - mRectSelecting = false; - mPanning = false; - mMoveNode = nullptr; + m_rectSelecting = false; + m_panning = false; + m_moveNode = nullptr; //update(); return; } @@ -805,29 +798,29 @@ namespace EMStudio timeViewPlugin->SetMode(TimeViewMode::AnimGraph); } - if (!mActiveGraph->IsInReferencedGraph()) + if (!m_activeGraph->IsInReferencedGraph()) { // check if we are clicking on an input port GraphNode* portNode = nullptr; NodePort* port = nullptr; AZ::u16 portNr = InvalidIndex16; bool isInputPort = true; - port = mActiveGraph->FindPort(globalPos.x(), globalPos.y(), &portNode, &portNr, &isInputPort); + port = m_activeGraph->FindPort(globalPos.x(), globalPos.y(), &portNode, &portNr, &isInputPort); if (port) { - mMoveNode = nullptr; - mPanning = false; - mRectSelecting = false; + m_moveNode = nullptr; + m_panning = false; + m_rectSelecting = false; // relink existing connection - NodeConnection* connection = mActiveGraph->FindInputConnection(portNode, portNr); + NodeConnection* connection = m_activeGraph->FindInputConnection(portNode, portNr); if (actionFilter.m_editConnections && isInputPort && connection && portNode->GetType() != StateGraphNode::TYPE_ID) { connection->SetIsDashed(true); UpdateMouseCursor(mousePos, globalPos); - mActiveGraph->StartRelinkConnection(connection, portNr, portNode); + m_activeGraph->StartRelinkConnection(connection, portNr, portNode); return; } @@ -839,7 +832,7 @@ namespace EMStudio { QPoint offset = globalPos - portNode->GetRect().topLeft(); UpdateMouseCursor(mousePos, globalPos); - mActiveGraph->StartCreateConnection(portNr, isInputPort, portNode, port, offset); + m_activeGraph->StartCreateConnection(portNr, isInputPort, portNode, port, offset); //update(); return; } @@ -847,7 +840,7 @@ namespace EMStudio } // check if we click on an transition arrow head or tail - NodeConnection* connection = mActiveGraph->FindConnection(globalPos); + NodeConnection* connection = m_activeGraph->FindConnection(globalPos); if (actionFilter.m_editConnections && connection && connection->GetType() == StateConnection::TYPE_ID) { @@ -860,21 +853,21 @@ namespace EMStudio if (!stateConnection->GetIsWildcardTransition() && stateConnection->CheckIfIsCloseToHead(globalPos)) { - mMoveNode = nullptr; - mPanning = false; - mRectSelecting = false; + m_moveNode = nullptr; + m_panning = false; + m_rectSelecting = false; - mActiveGraph->StartReplaceTransitionHead(stateConnection, startOffset, endOffset, stateConnection->GetSourceNode(), stateConnection->GetTargetNode()); + m_activeGraph->StartReplaceTransitionHead(stateConnection, startOffset, endOffset, stateConnection->GetSourceNode(), stateConnection->GetTargetNode()); return; } if (!stateConnection->GetIsWildcardTransition() && stateConnection->CheckIfIsCloseToTail(globalPos)) { - mMoveNode = nullptr; - mPanning = false; - mRectSelecting = false; + m_moveNode = nullptr; + m_panning = false; + m_rectSelecting = false; - mActiveGraph->StartReplaceTransitionTail(stateConnection, startOffset, endOffset, stateConnection->GetSourceNode(), stateConnection->GetTargetNode()); + m_activeGraph->StartReplaceTransitionTail(stateConnection, startOffset, endOffset, stateConnection->GetSourceNode(), stateConnection->GetTargetNode()); return; } } @@ -883,32 +876,32 @@ namespace EMStudio // get the node we click on node = UpdateMouseCursor(mousePos, globalPos); - if (node && mShiftPressed) + if (node && m_shiftPressed) { OnShiftClickedNode(node); } else { - if (node && mShiftPressed == false && mControlPressed == false && mAltPressed == false && + if (node && m_shiftPressed == false && m_controlPressed == false && m_altPressed == false && actionFilter.m_editNodes && - !mActiveGraph->IsInReferencedGraph()) + !m_activeGraph->IsInReferencedGraph()) { - mMoveNode = node; - mPanning = false; + m_moveNode = node; + m_panning = false; setCursor(Qt::ClosedHandCursor); } else { - mMoveNode = nullptr; - mPanning = false; - mRectSelecting = true; - mSelectStart = mousePos; - mSelectEnd = mSelectStart; + m_moveNode = nullptr; + m_panning = false; + m_rectSelecting = true; + m_selectStart = mousePos; + m_selectEnd = m_selectStart; setCursor(Qt::ArrowCursor); } } - if (mActiveGraph) + if (m_activeGraph) { // shift is used to activate a state, disable all selection behavior in case we press shift! // check if we clicked a node and additionally not clicked its arrow rect @@ -917,42 +910,42 @@ namespace EMStudio { nodeClicked = true; } - if (!mShiftPressed) + if (!m_shiftPressed) { // check the node we're clicking on - if (!mControlPressed) + if (!m_controlPressed) { // only reset the selection in case we clicked in empty space or in case the node we clicked on is not part of if (!node || (node && !node->GetIsSelected())) { - mPlugin->GetAnimGraphModel().GetSelectionModel().clear(); + m_plugin->GetAnimGraphModel().GetSelectionModel().clear(); } } // node clicked with shift only - if (nodeClicked && mControlPressed) + if (nodeClicked && m_controlPressed) { - mPlugin->GetAnimGraphModel().GetSelectionModel().select(QItemSelection(node->GetModelIndex(), node->GetModelIndex()), + m_plugin->GetAnimGraphModel().GetSelectionModel().select(QItemSelection(node->GetModelIndex(), node->GetModelIndex()), QItemSelectionModel::Toggle | QItemSelectionModel::Rows); } // node clicked with ctrl only - else if (nodeClicked && !mControlPressed) + else if (nodeClicked && !m_controlPressed) { - mPlugin->GetAnimGraphModel().GetSelectionModel().select(QItemSelection(node->GetModelIndex(), node->GetModelIndex()), + m_plugin->GetAnimGraphModel().GetSelectionModel().select(QItemSelection(node->GetModelIndex(), node->GetModelIndex()), QItemSelectionModel::Select | QItemSelectionModel::Rows); } // in case we didn't click on a node, check if we click on a connection else if (!nodeClicked) { - mActiveGraph->SelectConnectionCloseTo(LocalToGlobal(event->pos()), mControlPressed == false, true); + m_activeGraph->SelectConnectionCloseTo(LocalToGlobal(event->pos()), m_controlPressed == false, true); } } else { // in case shift and control are both pressed, special case! - if (mControlPressed && node) + if (m_controlPressed && node) { - mPlugin->GetAnimGraphModel().GetSelectionModel().select(QItemSelection(node->GetModelIndex(), node->GetModelIndex()), + m_plugin->GetAnimGraphModel().GetSelectionModel().select(QItemSelection(node->GetModelIndex(), node->GetModelIndex()), QItemSelectionModel::Current | QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); } } @@ -969,7 +962,7 @@ namespace EMStudio const QPoint globalPos = LocalToGlobal(mousePos); SetMousePos(globalPos); - if (mActiveGraph == nullptr) + if (m_activeGraph == nullptr) { return; } @@ -977,24 +970,24 @@ namespace EMStudio GetMainWindow()->UpdateUndoRedo(); // update modifiers - mAltPressed = event->modifiers() & Qt::AltModifier; - mShiftPressed = event->modifiers() & Qt::ShiftModifier; - mControlPressed = event->modifiers() & Qt::ControlModifier; + m_altPressed = event->modifiers() & Qt::AltModifier; + m_shiftPressed = event->modifiers() & Qt::ShiftModifier; + m_controlPressed = event->modifiers() & Qt::ControlModifier; - const AnimGraphActionFilter& actionFilter = mPlugin->GetActionFilter(); + const AnimGraphActionFilter& actionFilter = m_plugin->GetActionFilter(); // both left and right released at the same time if (event->buttons() & Qt::RightButton && event->buttons() & Qt::LeftButton) { - mRightMousePressed = false; - mLeftMousePressed = false; + m_rightMousePressed = false; + m_leftMousePressed = false; } // right mouse button if (event->button() == Qt::RightButton) { - mRightMousePressed = false; - mPanning = false; + m_rightMousePressed = false; + m_panning = false; UpdateMouseCursor(mousePos, globalPos); //update(); return; @@ -1003,23 +996,23 @@ namespace EMStudio // middle mouse button if (event->button() == Qt::MidButton) { - mMiddleMousePressed = false; - mPanning = false; + m_middleMousePressed = false; + m_panning = false; } // if we release the left mouse button if (event->button() == Qt::LeftButton) { - const bool mouseMoved = (event->pos() != mMouseLastPressPos); + const bool mouseMoved = (event->pos() != m_mouseLastPressPos); // if we pressed the visualize icon GraphNode* node = UpdateMouseCursor(mousePos, globalPos); if (node && node->GetCanVisualize() && node->GetIsInsideVisualizeRect(globalPos)) { - mRectSelecting = false; - mPanning = false; - mMoveNode = nullptr; - mLeftMousePressed = false; + m_rectSelecting = false; + m_panning = false; + m_moveNode = nullptr; + m_leftMousePressed = false; UpdateMouseCursor(mousePos, globalPos); //update(); return; @@ -1027,80 +1020,80 @@ namespace EMStudio if (node && node->GetIsInsideArrowRect(globalPos)) { - mRectSelecting = false; - mPanning = false; - mMoveNode = nullptr; - mLeftMousePressed = false; + m_rectSelecting = false; + m_panning = false; + m_moveNode = nullptr; + m_leftMousePressed = false; UpdateMouseCursor(mousePos, globalPos); //update(); return; } // if we were creating a connection - if (mActiveGraph->GetIsCreatingConnection()) + if (m_activeGraph->GetIsCreatingConnection()) { - AZ_Assert(!mActiveGraph->IsInReferencedGraph(), "Expected to not be in a referenced graph"); + AZ_Assert(!m_activeGraph->IsInReferencedGraph(), "Expected to not be in a referenced graph"); // create the connection if needed - if (mActiveGraph->GetTargetPort()) + if (m_activeGraph->GetTargetPort()) { - if (mActiveGraph->GetIsCreateConnectionValid()) + if (m_activeGraph->GetIsCreateConnectionValid()) { AZ::u16 targetPortNr; bool targetIsInputPort; GraphNode* targetNode; - NodePort* targetPort = mActiveGraph->FindPort(globalPos.x(), globalPos.y(), &targetNode, &targetPortNr, &targetIsInputPort); - if (targetPort && mActiveGraph->GetTargetPort() == targetPort - && targetNode != mActiveGraph->GetCreateConnectionNode()) + NodePort* targetPort = m_activeGraph->FindPort(globalPos.x(), globalPos.y(), &targetNode, &targetPortNr, &targetIsInputPort); + if (targetPort && m_activeGraph->GetTargetPort() == targetPort + && targetNode != m_activeGraph->GetCreateConnectionNode()) { #ifndef MCORE_DEBUG MCORE_UNUSED(targetPort); #endif QPoint endOffset = globalPos - targetNode->GetRect().topLeft(); - mActiveGraph->SetCreateConnectionEndOffset(endOffset); + m_activeGraph->SetCreateConnectionEndOffset(endOffset); // trigger the callback - OnCreateConnection(mActiveGraph->GetCreateConnectionPortNr(), - mActiveGraph->GetCreateConnectionNode(), - mActiveGraph->GetCreateConnectionIsInputPort(), + OnCreateConnection(m_activeGraph->GetCreateConnectionPortNr(), + m_activeGraph->GetCreateConnectionNode(), + m_activeGraph->GetCreateConnectionIsInputPort(), targetPortNr, targetNode, targetIsInputPort, - mActiveGraph->GetCreateConnectionStartOffset(), - mActiveGraph->GetCreateConnectionEndOffset()); + m_activeGraph->GetCreateConnectionStartOffset(), + m_activeGraph->GetCreateConnectionEndOffset()); } } } - mActiveGraph->StopCreateConnection(); - mLeftMousePressed = false; + m_activeGraph->StopCreateConnection(); + m_leftMousePressed = false; UpdateMouseCursor(mousePos, globalPos); //update(); return; } // if we were relinking a connection - if (mActiveGraph->GetIsRelinkingConnection()) + if (m_activeGraph->GetIsRelinkingConnection()) { AZ_Assert(actionFilter.m_editConnections, "Expected edit connections being enabled."); - AZ_Assert(!mActiveGraph->IsInReferencedGraph(), "Expected to not be in a referenced graph"); + AZ_Assert(!m_activeGraph->IsInReferencedGraph(), "Expected to not be in a referenced graph"); // get the information from the current mouse position AZ::u16 newTargetPortNr; bool newTargetIsInputPort; GraphNode* newTargetNode; - NodePort* newTargetPort = mActiveGraph->FindPort(globalPos.x(), globalPos.y(), &newTargetNode, &newTargetPortNr, &newTargetIsInputPort); + NodePort* newTargetPort = m_activeGraph->FindPort(globalPos.x(), globalPos.y(), &newTargetNode, &newTargetPortNr, &newTargetIsInputPort); // relink existing connection NodeConnection* connection = nullptr; if (newTargetPort) { - connection = mActiveGraph->FindInputConnection(newTargetNode, newTargetPortNr); + connection = m_activeGraph->FindInputConnection(newTargetNode, newTargetPortNr); } - NodeConnection* relinkedConnection = mActiveGraph->GetRelinkConnection(); + NodeConnection* relinkedConnection = m_activeGraph->GetRelinkConnection(); if (relinkedConnection) { relinkedConnection->SetIsDashed(false); @@ -1146,7 +1139,7 @@ namespace EMStudio CommandSystem::RelinkConnectionTarget(&commandGroup, animGraph->GetID(), sourceNodeName.c_str(), sourcePortNr, oldTargetNodeName.c_str(), oldTargetPortNr, newTargetNodeName.c_str(), newTargetPortNr); // call this before calling the commands as the commands will trigger a graph update - mActiveGraph->StopRelinkConnection(); + m_activeGraph->StopRelinkConnection(); // execute the command group AZStd::string commandResult; @@ -1160,113 +1153,111 @@ namespace EMStudio } } - //mActiveGraph->StopCreateConnection(); - mActiveGraph->StopRelinkConnection(); - mLeftMousePressed = false; + m_activeGraph->StopRelinkConnection(); + m_leftMousePressed = false; UpdateMouseCursor(mousePos, globalPos); - //update(); return; } // in case we adjusted a transition start or end point - if (mActiveGraph->GetIsRepositioningTransitionHead() || mActiveGraph->GetIsRepositioningTransitionTail()) + if (m_activeGraph->GetIsRepositioningTransitionHead() || m_activeGraph->GetIsRepositioningTransitionTail()) { AZ_Assert(actionFilter.m_editConnections, "Expected edit connections being enabled."); - AZ_Assert(!mActiveGraph->IsInReferencedGraph(), "Expected to not be in a referenced graph"); + AZ_Assert(!m_activeGraph->IsInReferencedGraph(), "Expected to not be in a referenced graph"); NodeConnection* connection; QPoint oldStartOffset, oldEndOffset; GraphNode* oldSourceNode; GraphNode* oldTargetNode; - mActiveGraph->GetReplaceTransitionInfo(&connection, &oldStartOffset, &oldEndOffset, &oldSourceNode, &oldTargetNode); - GraphNode* newDropNode = mActiveGraph->FindNode(event->pos()); + m_activeGraph->GetReplaceTransitionInfo(&connection, &oldStartOffset, &oldEndOffset, &oldSourceNode, &oldTargetNode); + GraphNode* newDropNode = m_activeGraph->FindNode(event->pos()); if (newDropNode && newDropNode != oldSourceNode) { - if (mActiveGraph->GetIsRepositioningTransitionHead()) + if (m_activeGraph->GetIsRepositioningTransitionHead()) { ReplaceTransition(connection, oldStartOffset, oldEndOffset, oldSourceNode, oldTargetNode, oldSourceNode, newDropNode); - mActiveGraph->StopReplaceTransitionHead(); + m_activeGraph->StopReplaceTransitionHead(); } - else if (mActiveGraph->GetIsRepositioningTransitionTail() && newDropNode != oldTargetNode) + else if (m_activeGraph->GetIsRepositioningTransitionTail() && newDropNode != oldTargetNode) { ReplaceTransition(connection, oldStartOffset, oldEndOffset, oldSourceNode, oldTargetNode, newDropNode, oldTargetNode); - mActiveGraph->StopReplaceTransitionTail(); + m_activeGraph->StopReplaceTransitionTail(); } } else { ReplaceTransition(connection, oldStartOffset, oldEndOffset, oldSourceNode, oldTargetNode, oldSourceNode, oldTargetNode); - if (mActiveGraph->GetIsRepositioningTransitionHead()) + if (m_activeGraph->GetIsRepositioningTransitionHead()) { - mActiveGraph->StopReplaceTransitionHead(); + m_activeGraph->StopReplaceTransitionHead(); } - else if (mActiveGraph->GetIsRepositioningTransitionTail()) + else if (m_activeGraph->GetIsRepositioningTransitionTail()) { - mActiveGraph->StopReplaceTransitionTail(); + m_activeGraph->StopReplaceTransitionTail(); } } return; } // if we are finished moving, trigger the OnMoveNode callbacks - if (mMoveNode && mouseMoved && + if (m_moveNode && mouseMoved && actionFilter.m_editNodes && - !mActiveGraph->IsInReferencedGraph()) + !m_activeGraph->IsInReferencedGraph()) { OnMoveStart(); bool moveNodeSelected = false; // prevent moving the same node twice - const AZStd::vector selectedNodes = mActiveGraph->GetSelectedGraphNodes(); + const AZStd::vector selectedNodes = m_activeGraph->GetSelectedGraphNodes(); for (GraphNode* currentNode : selectedNodes) { OnMoveNode(currentNode, currentNode->GetRect().topLeft().x(), currentNode->GetRect().topLeft().y()); - if (currentNode == mMoveNode) + if (currentNode == m_moveNode) { moveNodeSelected = true; } } - if (!moveNodeSelected && !mMoveNode) + if (!moveNodeSelected && !m_moveNode) { - OnMoveNode(mMoveNode, mMoveNode->GetRect().topLeft().x(), mMoveNode->GetRect().topLeft().y()); + OnMoveNode(m_moveNode, m_moveNode->GetRect().topLeft().x(), m_moveNode->GetRect().topLeft().y()); } OnMoveEnd(); } - mPanning = false; - mMoveNode = nullptr; + m_panning = false; + m_moveNode = nullptr; UpdateMouseCursor(mousePos, globalPos); // get the node we click on node = UpdateMouseCursor(mousePos, globalPos); - if (mRectSelecting && mouseMoved) + if (m_rectSelecting && mouseMoved) { // calc the selection rect QRect selectRect; CalcSelectRect(selectRect); // select things inside it - if (selectRect.isEmpty() == false && mActiveGraph) + if (selectRect.isEmpty() == false && m_activeGraph) { - selectRect = mActiveGraph->GetTransform().inverted().mapRect(selectRect); + selectRect = m_activeGraph->GetTransform().inverted().mapRect(selectRect); // select nodes when alt is not pressed - if (mAltPressed == false) + if (m_altPressed == false) { - const bool overwriteSelection = (mControlPressed == false); - mActiveGraph->SelectNodesInRect(selectRect, overwriteSelection, mControlPressed); + const bool overwriteSelection = (m_controlPressed == false); + m_activeGraph->SelectNodesInRect(selectRect, overwriteSelection, m_controlPressed); } else // zoom into the selected rect { - mActiveGraph->ZoomOnRect(selectRect, geometry().width(), geometry().height(), true); + m_activeGraph->ZoomOnRect(selectRect, geometry().width(), geometry().height(), true); } } } - mLeftMousePressed = false; - mRectSelecting = false; + m_leftMousePressed = false; + m_rectSelecting = false; } } @@ -1275,7 +1266,7 @@ namespace EMStudio void NodeGraphWidget::mouseDoubleClickEvent(QMouseEvent* event) { // only do things when a graph is active - if (mActiveGraph == nullptr) + if (m_activeGraph == nullptr) { return; } @@ -1291,12 +1282,12 @@ namespace EMStudio if (event->button() == Qt::LeftButton) { // check if double clicked on a node - GraphNode* node = mActiveGraph->FindNode(mousePos); + GraphNode* node = m_activeGraph->FindNode(mousePos); if (node == nullptr) { // if we didn't double click on a node zoom in to the clicked area - mActiveGraph->ScrollTo(-LocalToGlobal(mousePos) + geometry().center()); - mActiveGraph->ZoomIn(); + m_activeGraph->ScrollTo(-LocalToGlobal(mousePos) + geometry().center()); + m_activeGraph->ZoomIn(); } } @@ -1304,18 +1295,18 @@ namespace EMStudio if (event->button() == Qt::RightButton) { // check if double clicked on a node - GraphNode* node = mActiveGraph->FindNode(mousePos); + GraphNode* node = m_activeGraph->FindNode(mousePos); if (node == nullptr) { - mActiveGraph->ScrollTo(-LocalToGlobal(mousePos) + geometry().center()); - mActiveGraph->ZoomOut(); + m_activeGraph->ScrollTo(-LocalToGlobal(mousePos) + geometry().center()); + m_activeGraph->ZoomOut(); } } setCursor(Qt::ArrowCursor); // reset flags - mRectSelecting = false; + m_rectSelecting = false; // redraw the viewport //update(); @@ -1326,7 +1317,7 @@ namespace EMStudio void NodeGraphWidget::wheelEvent(QWheelEvent* event) { // only do things when a graph is active - if (mActiveGraph == nullptr) + if (m_activeGraph == nullptr) { return; } @@ -1344,12 +1335,12 @@ namespace EMStudio SetMousePos(globalPos); // stop the automated zoom - mActiveGraph->StopAnimatedZoom(); + m_activeGraph->StopAnimatedZoom(); // calculate the new scale value const float scaleDelta = (event->angleDelta().y() / 120.0f) * 0.05f; - float newScale = MCore::Clamp(mActiveGraph->GetScale() + scaleDelta, mActiveGraph->GetLowestScale(), 1.0f); - mActiveGraph->SetScale(newScale); + float newScale = MCore::Clamp(m_activeGraph->GetScale() + scaleDelta, m_activeGraph->GetLowestScale(), 1.0f); + m_activeGraph->SetScale(newScale); // redraw the viewport //update(); @@ -1360,20 +1351,20 @@ namespace EMStudio GraphNode* NodeGraphWidget::UpdateMouseCursor(const QPoint& localMousePos, const QPoint& globalMousePos) { // if there is no active graph - if (mActiveGraph == nullptr) + if (m_activeGraph == nullptr) { setCursor(Qt::ArrowCursor); return nullptr; } - if (mPanning || mMoveNode) + if (m_panning || m_moveNode) { setCursor(Qt::ClosedHandCursor); return nullptr; } // check if we hover above a node - GraphNode* node = mActiveGraph->FindNode(localMousePos); + GraphNode* node = m_activeGraph->FindNode(localMousePos); // check if the node is valid // we test firstly the node to have the visualize cursor correct @@ -1407,7 +1398,7 @@ namespace EMStudio AZ::u16 portNr; GraphNode* portNode; bool isInputPort; - NodePort* nodePort = mActiveGraph->FindPort(globalMousePos.x(), globalMousePos.y(), &portNode, &portNr, &isInputPort); + NodePort* nodePort = m_activeGraph->FindPort(globalMousePos.x(), globalMousePos.y(), &portNode, &portNr, &isInputPort); if (nodePort) { if ((isInputPort && portNode->GetCreateConFromOutputOnly() == false) || isInputPort == false) @@ -1427,7 +1418,7 @@ namespace EMStudio AZ::u16 portNr; GraphNode* portNode; bool isInputPort; - NodePort* nodePort = mActiveGraph->FindPort(globalMousePos.x(), globalMousePos.y(), &portNode, &portNr, &isInputPort); + NodePort* nodePort = m_activeGraph->FindPort(globalMousePos.x(), globalMousePos.y(), &portNode, &portNr, &isInputPort); if (nodePort) { if ((isInputPort && portNode->GetCreateConFromOutputOnly() == false) || isInputPort == false) @@ -1454,10 +1445,10 @@ namespace EMStudio // calculate the selection rect void NodeGraphWidget::CalcSelectRect(QRect& outRect) { - const int32 startX = MCore::Min(mSelectStart.x(), mSelectEnd.x()); - const int32 startY = MCore::Min(mSelectStart.y(), mSelectEnd.y()); - const int32 width = abs(mSelectEnd.x() - mSelectStart.x()); - const int32 height = abs(mSelectEnd.y() - mSelectStart.y()); + const int32 startX = MCore::Min(m_selectStart.x(), m_selectEnd.x()); + const int32 startY = MCore::Min(m_selectStart.y(), m_selectEnd.y()); + const int32 width = abs(m_selectEnd.x() - m_selectStart.x()); + const int32 height = abs(m_selectEnd.y() - m_selectStart.y()); outRect = QRect(startX, startY, width, height); } @@ -1470,17 +1461,17 @@ namespace EMStudio { case Qt::Key_Shift: { - mShiftPressed = true; + m_shiftPressed = true; break; } case Qt::Key_Control: { - mControlPressed = true; + m_controlPressed = true; break; } case Qt::Key_Alt: { - mAltPressed = true; + m_altPressed = true; break; } } @@ -1495,17 +1486,17 @@ namespace EMStudio { case Qt::Key_Shift: { - mShiftPressed = false; + m_shiftPressed = false; break; } case Qt::Key_Control: { - mControlPressed = false; + m_controlPressed = false; break; } case Qt::Key_Alt: { - mAltPressed = false; + m_altPressed = false; break; } } @@ -1529,15 +1520,15 @@ namespace EMStudio void NodeGraphWidget::focusOutEvent(QFocusEvent* event) { MCORE_UNUSED(event); - mShiftPressed = false; - mControlPressed = false; - mAltPressed = false; + m_shiftPressed = false; + m_controlPressed = false; + m_altPressed = false; releaseKeyboard(); - if (mActiveGraph && mActiveGraph->GetIsCreatingConnection()) + if (m_activeGraph && m_activeGraph->GetIsCreatingConnection()) { - mActiveGraph->StopCreateConnection(); - mLeftMousePressed = false; + m_activeGraph->StopCreateConnection(); + m_leftMousePressed = false; } } @@ -1545,9 +1536,9 @@ namespace EMStudio // return the number of selected nodes size_t NodeGraphWidget::CalcNumSelectedNodes() const { - if (mActiveGraph) + if (m_activeGraph) { - return mActiveGraph->CalcNumSelectedNodes(); + return m_activeGraph->CalcNumSelectedNodes(); } return 0; } @@ -1559,12 +1550,12 @@ namespace EMStudio MCORE_UNUSED(portNr); MCORE_UNUSED(port); - if (mActiveGraph == nullptr) + if (m_activeGraph == nullptr) { return false; } - GraphNode* sourceNode = mActiveGraph->GetCreateConnectionNode(); + GraphNode* sourceNode = m_activeGraph->GetCreateConnectionNode(); GraphNode* targetNode = portNode; // don't allow connection to itself @@ -1574,7 +1565,7 @@ namespace EMStudio } // dont allow to connect an input port to another input port or output port to another output port - if (isInputPort == mActiveGraph->GetCreateConnectionIsInputPort()) + if (isInputPort == m_activeGraph->GetCreateConnectionIsInputPort()) { return false; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGraphWidget.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGraphWidget.h index d8b73ee5be..f3bea6d5f9 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGraphWidget.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGraphWidget.h @@ -48,16 +48,16 @@ namespace EMStudio NodeGraphWidget(AnimGraphPlugin* plugin, NodeGraph* activeGraph = nullptr, QWidget* parent = nullptr); virtual ~NodeGraphWidget(); - AnimGraphPlugin* GetPlugin() { return mPlugin; } + AnimGraphPlugin* GetPlugin() { return m_plugin; } void SetActiveGraph(NodeGraph* graph); NodeGraph* GetActiveGraph() const; void SetCallback(GraphWidgetCallback* callback); - MCORE_INLINE GraphWidgetCallback* GetCallback() { return mCallback; } - MCORE_INLINE const QPoint& GetMousePos() const { return mMousePos; } - MCORE_INLINE void SetMousePos(const QPoint& pos) { mMousePos = pos; } - MCORE_INLINE void SetShowFPS(bool showFPS) { mShowFPS = showFPS; } + MCORE_INLINE GraphWidgetCallback* GetCallback() { return m_callback; } + MCORE_INLINE const QPoint& GetMousePos() const { return m_mousePos; } + MCORE_INLINE void SetMousePos(const QPoint& pos) { m_mousePos = pos; } + MCORE_INLINE void SetShowFPS(bool showFPS) { m_showFps = showFPS; } size_t CalcNumSelectedNodes() const; @@ -125,35 +125,35 @@ namespace EMStudio GraphNode* UpdateMouseCursor(const QPoint& localMousePos, const QPoint& globalMousePos); protected: - AnimGraphPlugin* mPlugin; - bool mShowFPS; - QPoint mMousePos; - QPoint mMouseLastPos; - QPoint mMouseLastPressPos; - QPoint mSelectStart; - QPoint mSelectEnd; - int mPrevWidth; - int mPrevHeight; - int mCurWidth; - int mCurHeight; - GraphNode* mMoveNode; // the node we're moving - NodeGraph* mActiveGraph = nullptr; - GraphWidgetCallback* mCallback; - QFont mFont; - QFontMetrics* mFontMetrics; - AZ::Debug::Timer mRenderTimer; - AZStd::string mTempString; - AZStd::string mFullActorName; - AZStd::string mActorName; - bool mAllowContextMenu; - bool mLeftMousePressed; - bool mMiddleMousePressed; - bool mRightMousePressed; - bool mPanning; - bool mRectSelecting; - bool mShiftPressed; - bool mControlPressed; - bool mAltPressed; + AnimGraphPlugin* m_plugin; + bool m_showFps; + QPoint m_mousePos; + QPoint m_mouseLastPos; + QPoint m_mouseLastPressPos; + QPoint m_selectStart; + QPoint m_selectEnd; + int m_prevWidth; + int m_prevHeight; + int m_curWidth; + int m_curHeight; + GraphNode* m_moveNode; // the node we're moving + NodeGraph* m_activeGraph = nullptr; + GraphWidgetCallback* m_callback; + QFont m_font; + QFontMetrics* m_fontMetrics; + AZ::Debug::Timer m_renderTimer; + AZStd::string m_tempString; + AZStd::string m_fullActorName; + AZStd::string m_actorName; + bool m_allowContextMenu; + bool m_leftMousePressed; + bool m_middleMousePressed; + bool m_rightMousePressed; + bool m_panning; + bool m_rectSelecting; + bool m_shiftPressed; + bool m_controlPressed; + bool m_altPressed; bool m_borderOverwrite = false; QColor m_borderOverwriteColor; float m_borderOverwriteWidth; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGroupWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGroupWindow.cpp index 3183bc8a0f..71eba1205e 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGroupWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGroupWindow.cpp @@ -52,8 +52,8 @@ namespace EMStudio : QDialog(parent) { // Store the values - mAnimGraph = animGraph; - mNodeGroup = nodeGroup; + m_animGraph = animGraph; + m_nodeGroup = nodeGroup; // set the window title setWindowTitle("Rename Node Group"); @@ -68,24 +68,23 @@ namespace EMStudio layout->addWidget(new QLabel("Please enter the new node group name:")); // add the line edit - mLineEdit = new QLineEdit(); - connect(mLineEdit, &QLineEdit::textEdited, this, &NodeGroupRenameWindow::TextEdited); - layout->addWidget(mLineEdit); + m_lineEdit = new QLineEdit(); + connect(m_lineEdit, &QLineEdit::textEdited, this, &NodeGroupRenameWindow::TextEdited); + layout->addWidget(m_lineEdit); // set the current name and select all - mLineEdit->setText(nodeGroup.c_str()); - mLineEdit->selectAll(); + m_lineEdit->setText(nodeGroup.c_str()); + m_lineEdit->selectAll(); // create the button layout QHBoxLayout* buttonLayout = new QHBoxLayout(); - mOKButton = new QPushButton("OK"); + m_okButton = new QPushButton("OK"); QPushButton* cancelButton = new QPushButton("Cancel"); - //buttonLayout->addWidget(mErrorMsg); - buttonLayout->addWidget(mOKButton); + buttonLayout->addWidget(m_okButton); buttonLayout->addWidget(cancelButton); // connect the buttons - connect(mOKButton, &QPushButton::clicked, this, &NodeGroupRenameWindow::Accepted); + connect(m_okButton, &QPushButton::clicked, this, &NodeGroupRenameWindow::Accepted); connect(cancelButton, &QPushButton::clicked, this, &NodeGroupRenameWindow::reject); // set the new layout @@ -99,36 +98,32 @@ namespace EMStudio const AZStd::string convertedNewName = FromQtString(text); if (text.isEmpty()) { - //mErrorMsg->setVisible(false); - mOKButton->setEnabled(false); - GetManager()->SetWidgetAsInvalidInput(mLineEdit); + m_okButton->setEnabled(false); + GetManager()->SetWidgetAsInvalidInput(m_lineEdit); } - else if (mNodeGroup == convertedNewName) + else if (m_nodeGroup == convertedNewName) { - //mErrorMsg->setVisible(false); - mOKButton->setEnabled(true); - mLineEdit->setStyleSheet(""); + m_okButton->setEnabled(true); + m_lineEdit->setStyleSheet(""); } else { // find duplicate name in the anim graph other than this node group - const size_t numNodeGroups = mAnimGraph->GetNumNodeGroups(); + const size_t numNodeGroups = m_animGraph->GetNumNodeGroups(); for (size_t i = 0; i < numNodeGroups; ++i) { - EMotionFX::AnimGraphNodeGroup* nodeGroup = mAnimGraph->GetNodeGroup(i); + EMotionFX::AnimGraphNodeGroup* nodeGroup = m_animGraph->GetNodeGroup(i); if (nodeGroup->GetNameString() == convertedNewName) { - //mErrorMsg->setVisible(true); - mOKButton->setEnabled(false); - GetManager()->SetWidgetAsInvalidInput(mLineEdit); + m_okButton->setEnabled(false); + GetManager()->SetWidgetAsInvalidInput(m_lineEdit); return; } } // no duplicate name found - //mErrorMsg->setVisible(false); - mOKButton->setEnabled(true); - mLineEdit->setStyleSheet(""); + m_okButton->setEnabled(true); + m_lineEdit->setStyleSheet(""); } } @@ -137,11 +132,11 @@ namespace EMStudio { // Execute the command AZStd::string outResult; - const AZStd::string convertedNewName = FromQtString(mLineEdit->text()); + const AZStd::string convertedNewName = FromQtString(m_lineEdit->text()); auto* command = aznew CommandSystem::CommandAnimGraphAdjustNodeGroup( GetCommandManager()->FindCommand(CommandSystem::CommandAnimGraphAdjustNodeGroup::s_commandName), - mAnimGraph->GetID(), - /*name = */ mNodeGroup, + m_animGraph->GetID(), + /*name = */ m_nodeGroup, /*visible = */ AZStd::nullopt, /*newName = */ convertedNewName ); @@ -158,25 +153,25 @@ namespace EMStudio NodeGroupWindow::NodeGroupWindow(AnimGraphPlugin* plugin) : QWidget() { - mPlugin = plugin; - mTableWidget = nullptr; - mAddAction = nullptr; + m_plugin = plugin; + m_tableWidget = nullptr; + m_addAction = nullptr; // create and register the command callbacks - mCreateCallback = new CommandAnimGraphAddNodeGroupCallback(false); - mRemoveCallback = new CommandAnimGraphRemoveNodeGroupCallback(false); - mAdjustCallback = new CommandAnimGraphAdjustNodeGroupCallback(false); - GetCommandManager()->RegisterCommandCallback("AnimGraphAddNodeGroup", mCreateCallback); - GetCommandManager()->RegisterCommandCallback("AnimGraphRemoveNodeGroup", mRemoveCallback); - GetCommandManager()->RegisterCommandCallback(CommandSystem::CommandAnimGraphAdjustNodeGroup::s_commandName.data(), mAdjustCallback); + m_createCallback = new CommandAnimGraphAddNodeGroupCallback(false); + m_removeCallback = new CommandAnimGraphRemoveNodeGroupCallback(false); + m_adjustCallback = new CommandAnimGraphAdjustNodeGroupCallback(false); + GetCommandManager()->RegisterCommandCallback("AnimGraphAddNodeGroup", m_createCallback); + GetCommandManager()->RegisterCommandCallback("AnimGraphRemoveNodeGroup", m_removeCallback); + GetCommandManager()->RegisterCommandCallback(CommandSystem::CommandAnimGraphAdjustNodeGroup::s_commandName.data(), m_adjustCallback); // add the add button - mAddAction = new QAction(MysticQt::GetMysticQt()->FindIcon("Images/Icons/Plus.svg"), tr("Add new node group"), this); - connect(mAddAction, &QAction::triggered, this, &NodeGroupWindow::OnAddNodeGroup); + m_addAction = new QAction(MysticQt::GetMysticQt()->FindIcon("Images/Icons/Plus.svg"), tr("Add new node group"), this); + connect(m_addAction, &QAction::triggered, this, &NodeGroupWindow::OnAddNodeGroup); // add the buttons to add, remove and clear the motions QToolBar* toolBar = new QToolBar(); - toolBar->addAction(mAddAction); + toolBar->addAction(m_addAction); toolBar->addSeparator(); @@ -186,59 +181,57 @@ namespace EMStudio toolBar->addWidget(m_searchWidget); // create the table widget - mTableWidget = new QTableWidget(); - mTableWidget->setAlternatingRowColors(true); - mTableWidget->setCornerButtonEnabled(false); - mTableWidget->setSelectionBehavior(QAbstractItemView::SelectRows); - mTableWidget->setSelectionMode(QAbstractItemView::ExtendedSelection); - mTableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers); - mTableWidget->setContextMenuPolicy(Qt::DefaultContextMenu); - connect(mTableWidget, &QTableWidget::itemSelectionChanged, this, &NodeGroupWindow::UpdateInterface); - //connect( mTableWidget, SIGNAL(cellChanged(int, int)), this, SLOT(OnCellChanged(int, int)) ); - //connect( mTableWidget, SIGNAL(itemChanged(QTableWidgetItem*)), this, SLOT(OnNameEdited(QTableWidgetItem*)) ); + m_tableWidget = new QTableWidget(); + m_tableWidget->setAlternatingRowColors(true); + m_tableWidget->setCornerButtonEnabled(false); + m_tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows); + m_tableWidget->setSelectionMode(QAbstractItemView::ExtendedSelection); + m_tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers); + m_tableWidget->setContextMenuPolicy(Qt::DefaultContextMenu); + connect(m_tableWidget, &QTableWidget::itemSelectionChanged, this, &NodeGroupWindow::UpdateInterface); // set the column count - mTableWidget->setColumnCount(3); + m_tableWidget->setColumnCount(3); // set header items for the table QTableWidgetItem* headerItem = new QTableWidgetItem("Vis"); headerItem->setTextAlignment(Qt::AlignVCenter | Qt::AlignLeft); - mTableWidget->setHorizontalHeaderItem(0, headerItem); + m_tableWidget->setHorizontalHeaderItem(0, headerItem); headerItem = new QTableWidgetItem("Color"); headerItem->setTextAlignment(Qt::AlignVCenter | Qt::AlignLeft); - mTableWidget->setHorizontalHeaderItem(1, headerItem); + m_tableWidget->setHorizontalHeaderItem(1, headerItem); headerItem = new QTableWidgetItem("Name"); headerItem->setTextAlignment(Qt::AlignVCenter | Qt::AlignLeft); - mTableWidget->setHorizontalHeaderItem(2, headerItem); + m_tableWidget->setHorizontalHeaderItem(2, headerItem); // set the column params - mTableWidget->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Fixed); - mTableWidget->horizontalHeader()->setSectionResizeMode(1, QHeaderView::Fixed); - mTableWidget->setColumnWidth(0, 25); - mTableWidget->setColumnWidth(1, 41); - mTableWidget->horizontalHeader()->setVisible(false); + m_tableWidget->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Fixed); + m_tableWidget->horizontalHeader()->setSectionResizeMode(1, QHeaderView::Fixed); + m_tableWidget->setColumnWidth(0, 25); + m_tableWidget->setColumnWidth(1, 41); + m_tableWidget->horizontalHeader()->setVisible(false); - mTableWidget->setShowGrid(false); + m_tableWidget->setShowGrid(false); - AzQtComponents::CheckBox::setVisibilityMode(mTableWidget, true); - connect(mTableWidget, &QTableWidget::itemChanged, this, &NodeGroupWindow::OnItemChanged); + AzQtComponents::CheckBox::setVisibilityMode(m_tableWidget, true); + connect(m_tableWidget, &QTableWidget::itemChanged, this, &NodeGroupWindow::OnItemChanged); // ser the horizontal header params - QHeaderView* horizontalHeader = mTableWidget->horizontalHeader(); + QHeaderView* horizontalHeader = m_tableWidget->horizontalHeader(); horizontalHeader->setSortIndicator(2, Qt::AscendingOrder); horizontalHeader->setStretchLastSection(true); // hide the vertical header - QHeaderView* verticalHeader = mTableWidget->verticalHeader(); + QHeaderView* verticalHeader = m_tableWidget->verticalHeader(); verticalHeader->setVisible(false); // create the vertical layout - mVerticalLayout = new QVBoxLayout(); - mVerticalLayout->setSpacing(2); - mVerticalLayout->setMargin(3); - mVerticalLayout->setAlignment(Qt::AlignTop); - mVerticalLayout->addWidget(toolBar); - mVerticalLayout->addWidget(mTableWidget); + m_verticalLayout = new QVBoxLayout(); + m_verticalLayout->setSpacing(2); + m_verticalLayout->setMargin(3); + m_verticalLayout->setAlignment(Qt::AlignTop); + m_verticalLayout->addWidget(toolBar); + m_verticalLayout->addWidget(m_tableWidget); // set the object name setObjectName("StyledWidget"); @@ -246,7 +239,7 @@ namespace EMStudio // create the fake widget and layout QWidget* fakeWidget = new QWidget(); fakeWidget->setObjectName("StyledWidget"); - fakeWidget->setLayout(mVerticalLayout); + fakeWidget->setLayout(m_verticalLayout); QVBoxLayout* fakeLayout = new QVBoxLayout(); fakeLayout->setMargin(0); @@ -267,12 +260,12 @@ namespace EMStudio NodeGroupWindow::~NodeGroupWindow() { // unregister the command callbacks and get rid of the memory - GetCommandManager()->RemoveCommandCallback(mCreateCallback, false); - GetCommandManager()->RemoveCommandCallback(mRemoveCallback, false); - GetCommandManager()->RemoveCommandCallback(mAdjustCallback, false); - delete mCreateCallback; - delete mRemoveCallback; - delete mAdjustCallback; + GetCommandManager()->RemoveCommandCallback(m_createCallback, false); + GetCommandManager()->RemoveCommandCallback(m_removeCallback, false); + GetCommandManager()->RemoveCommandCallback(m_adjustCallback, false); + delete m_createCallback; + delete m_removeCallback; + delete m_adjustCallback; } @@ -283,7 +276,7 @@ namespace EMStudio AZStd::vector selectedNodeGroups; // get the current selection - const QList selectedItems = mTableWidget->selectedItems(); + const QList selectedItems = m_tableWidget->selectedItems(); // get the number of selected items const int numSelectedItems = selectedItems.count(); @@ -293,7 +286,7 @@ namespace EMStudio for (int i = 0; i < numSelectedItems; ++i) { const int rowIndex = selectedItems[i]->row(); - const AZStd::string nodeGroupName = FromQtString(mTableWidget->item(rowIndex, 2)->text()); + const AZStd::string nodeGroupName = FromQtString(m_tableWidget->item(rowIndex, 2)->text()); if (AZStd::find(begin(selectedNodeGroups), end(selectedNodeGroups), nodeGroupName) == end(selectedNodeGroups)) { selectedNodeGroups.emplace_back(nodeGroupName); @@ -301,28 +294,28 @@ namespace EMStudio } // clear the lookup array - mWidgetTable.clear(); + m_widgetTable.clear(); // get the anim graph - EMotionFX::AnimGraph* animGraph = mPlugin->GetActiveAnimGraph(); + EMotionFX::AnimGraph* animGraph = m_plugin->GetActiveAnimGraph(); if (animGraph == nullptr) { - mTableWidget->setRowCount(0); + m_tableWidget->setRowCount(0); UpdateInterface(); return; } // disable signals - mTableWidget->blockSignals(true); + m_tableWidget->blockSignals(true); // get the number of node groups const int numNodeGroups = aznumeric_caster(animGraph->GetNumNodeGroups()); // set table size and add header items - mTableWidget->setRowCount(numNodeGroups); + m_tableWidget->setRowCount(numNodeGroups); // disable the sorting - mTableWidget->setSortingEnabled(false); + m_tableWidget->setSortingEnabled(false); // add each node group for (int i = 0; i < numNodeGroups; ++i) @@ -343,13 +336,13 @@ namespace EMStudio visibilityCheckboxItem->setData(Qt::CheckStateRole, nodeGroup->GetIsVisible() ? Qt::Checked : Qt::Unchecked); // add the item, it's needed to have the background color + the widget - mTableWidget->setItem(i, 0, visibilityCheckboxItem); + m_tableWidget->setItem(i, 0, visibilityCheckboxItem); // create the color item QTableWidgetItem* colorItem = new QTableWidgetItem(); // add the item, it's needed to have the background color + the widget - mTableWidget->setItem(i, 1, colorItem); + m_tableWidget->setItem(i, 1, colorItem); // create the color widget AzQtComponents::ColorLabel* colorWidget = new AzQtComponents::ColorLabel(color); @@ -365,15 +358,15 @@ namespace EMStudio colorLayout->addWidget(colorWidget); colorLayoutWidget->setLayout(colorLayout); - mWidgetTable.emplace_back(WidgetLookup{colorWidget, i}); + m_widgetTable.emplace_back(WidgetLookup{colorWidget, i}); connect(colorWidget, &AzQtComponents::ColorLabel::colorChanged, this, &NodeGroupWindow::OnColorChanged); // add the color label in the table - mTableWidget->setCellWidget(i, 1, colorLayoutWidget); + m_tableWidget->setCellWidget(i, 1, colorLayoutWidget); // create the node group name label QTableWidgetItem* nameItem = new QTableWidgetItem(nodeGroup->GetName()); - mTableWidget->setItem(i, 2, nameItem); + m_tableWidget->setItem(i, 2, nameItem); // set the item selected visibilityCheckboxItem->setSelected(itemSelected); @@ -381,24 +374,24 @@ namespace EMStudio nameItem->setSelected(itemSelected); // set the row height - mTableWidget->setRowHeight(i, 21); + m_tableWidget->setRowHeight(i, 21); // check if the current item contains the find text if (QString(nodeGroup->GetName()).contains(m_searchWidgetText.c_str(), Qt::CaseInsensitive)) { - mTableWidget->showRow(i); + m_tableWidget->showRow(i); } else { - mTableWidget->hideRow(i); + m_tableWidget->hideRow(i); } } // enable the sorting - mTableWidget->setSortingEnabled(true); + m_tableWidget->setSortingEnabled(true); // enable signals - mTableWidget->blockSignals(false); + m_tableWidget->blockSignals(false); // update the interface UpdateInterface(); @@ -416,7 +409,7 @@ namespace EMStudio void NodeGroupWindow::OnAddNodeGroup() { // add the parameter - EMotionFX::AnimGraph* animGraph = mPlugin->GetActiveAnimGraph(); + EMotionFX::AnimGraph* animGraph = m_plugin->GetActiveAnimGraph(); if (animGraph == nullptr) { MCore::LogWarning("NodeGroupWindow::OnAddNodeGroup() - No AnimGraph active!"); @@ -439,12 +432,12 @@ namespace EMStudio { // select the new node group EMotionFX::AnimGraphNodeGroup* lastNodeGroup = animGraph->GetNodeGroup(animGraph->GetNumNodeGroups() - 1); - const int numRows = mTableWidget->rowCount(); + const int numRows = m_tableWidget->rowCount(); for (int i = 0; i < numRows; ++i) { - if (mTableWidget->item(i, 2)->text() == QString(lastNodeGroup->GetName())) + if (m_tableWidget->item(i, 2)->text() == QString(lastNodeGroup->GetName())) { - mTableWidget->selectRow(i); + m_tableWidget->selectRow(i); break; } } @@ -455,18 +448,18 @@ namespace EMStudio // find the index for the given widget int NodeGroupWindow::FindGroupIndexByWidget(QObject* widget) const { - const auto foundGroup = AZStd::find_if(begin(mWidgetTable), end(mWidgetTable), [widget](const auto& tableEntry) + const auto foundGroup = AZStd::find_if(begin(m_widgetTable), end(m_widgetTable), [widget](const auto& tableEntry) { - return tableEntry.mWidget == widget; + return tableEntry.m_widget == widget; }); - return foundGroup != end(mWidgetTable) ? foundGroup->mGroupIndex : MCore::InvalidIndexT; + return foundGroup != end(m_widgetTable) ? foundGroup->m_groupIndex : MCore::InvalidIndexT; } void NodeGroupWindow::OnIsVisible(int state, int row) { // get the anim graph - EMotionFX::AnimGraph* animGraph = mPlugin->GetActiveAnimGraph(); + EMotionFX::AnimGraph* animGraph = m_plugin->GetActiveAnimGraph(); if (animGraph == nullptr) { return; @@ -504,7 +497,7 @@ namespace EMStudio void NodeGroupWindow::OnColorChanged(const AZ::Color& color) { // get the anim graph - EMotionFX::AnimGraph* animGraph = mPlugin->GetActiveAnimGraph(); + EMotionFX::AnimGraph* animGraph = m_plugin->GetActiveAnimGraph(); if (animGraph == nullptr) { return; @@ -544,14 +537,14 @@ namespace EMStudio void NodeGroupWindow::UpdateInterface() { // get the anim graph - EMotionFX::AnimGraph* animGraph = mPlugin->GetActiveAnimGraph(); + EMotionFX::AnimGraph* animGraph = m_plugin->GetActiveAnimGraph(); if (animGraph == nullptr) { - mAddAction->setEnabled(false); + m_addAction->setEnabled(false); return; } - mAddAction->setEnabled(true); + m_addAction->setEnabled(true); } @@ -559,14 +552,14 @@ namespace EMStudio void NodeGroupWindow::OnRemoveSelectedGroups() { // get the anim graph - EMotionFX::AnimGraph* animGraph = mPlugin->GetActiveAnimGraph(); + EMotionFX::AnimGraph* animGraph = m_plugin->GetActiveAnimGraph(); if (animGraph == nullptr) { return; } // get the current selection - const QList selectedItems = mTableWidget->selectedItems(); + const QList selectedItems = m_tableWidget->selectedItems(); // get the number of selected items const int numSelectedItems = selectedItems.count(); @@ -612,7 +605,7 @@ namespace EMStudio AZStd::string tempString; for (size_t i = 0; i < numRowIndices; ++i) { - const AZStd::string nodeGroupName = FromQtString(mTableWidget->item(rowIndices[i], 2)->text()); + const AZStd::string nodeGroupName = FromQtString(m_tableWidget->item(rowIndices[i], 2)->text()); if (i == 0 || i == numRowIndices - 1) { tempString = AZStd::string::format("AnimGraphRemoveNodeGroup -animGraphID %i -name \"%s\"", animGraph->GetID(), nodeGroupName.c_str()); @@ -631,13 +624,13 @@ namespace EMStudio } // selected the next row - if (rowIndices[0] > (mTableWidget->rowCount() - 1)) + if (rowIndices[0] > (m_tableWidget->rowCount() - 1)) { - mTableWidget->selectRow(rowIndices[0] - 1); + m_tableWidget->selectRow(rowIndices[0] - 1); } else { - mTableWidget->selectRow(rowIndices[0]); + m_tableWidget->selectRow(rowIndices[0]); } } @@ -646,11 +639,11 @@ namespace EMStudio void NodeGroupWindow::OnRenameSelectedNodeGroup() { // take the item of the name column - const QList selectedItems = mTableWidget->selectedItems(); - QTableWidgetItem* item = mTableWidget->item(selectedItems[0]->row(), 2); + const QList selectedItems = m_tableWidget->selectedItems(); + QTableWidgetItem* item = m_tableWidget->item(selectedItems[0]->row(), 2); // show the rename window - NodeGroupRenameWindow nodeGroupRenameWindow(this, mPlugin->GetActiveAnimGraph(), FromQtString(item->text())); + NodeGroupRenameWindow nodeGroupRenameWindow(this, m_plugin->GetActiveAnimGraph(), FromQtString(item->text())); nodeGroupRenameWindow.exec(); } @@ -658,7 +651,7 @@ namespace EMStudio void NodeGroupWindow::OnClearNodeGroups() { // get the anim graph - EMotionFX::AnimGraph* animGraph = mPlugin->GetActiveAnimGraph(); + EMotionFX::AnimGraph* animGraph = m_plugin->GetActiveAnimGraph(); if (animGraph == nullptr) { return; @@ -715,7 +708,7 @@ namespace EMStudio void NodeGroupWindow::contextMenuEvent(QContextMenuEvent* event) { // get the current selection - const QList selectedItems = mTableWidget->selectedItems(); + const QList selectedItems = m_tableWidget->selectedItems(); // get the number of selected items const int numSelectedItems = selectedItems.count(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGroupWindow.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGroupWindow.h index e19b831790..69255ce9b4 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGroupWindow.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGroupWindow.h @@ -54,10 +54,10 @@ namespace EMStudio void Accepted(); private: - EMotionFX::AnimGraph* mAnimGraph; - AZStd::string mNodeGroup; - QLineEdit* mLineEdit; - QPushButton* mOKButton; + EMotionFX::AnimGraph* m_animGraph; + AZStd::string m_nodeGroup; + QLineEdit* m_lineEdit; + QPushButton* m_okButton; }; class NodeGroupWindow @@ -98,22 +98,22 @@ namespace EMStudio MCORE_DEFINECOMMANDCALLBACK(CommandAnimGraphAdjustNodeGroupCallback); MCORE_DEFINECOMMANDCALLBACK(CommandAnimGraphRemoveNodeGroupCallback); - CommandAnimGraphAddNodeGroupCallback* mCreateCallback; - CommandAnimGraphAdjustNodeGroupCallback* mAdjustCallback; - CommandAnimGraphRemoveNodeGroupCallback* mRemoveCallback; + CommandAnimGraphAddNodeGroupCallback* m_createCallback; + CommandAnimGraphAdjustNodeGroupCallback* m_adjustCallback; + CommandAnimGraphRemoveNodeGroupCallback* m_removeCallback; struct WidgetLookup { - QObject* mWidget; - int mGroupIndex; + QObject* m_widget; + int m_groupIndex; }; - AnimGraphPlugin* mPlugin; - QTableWidget* mTableWidget; - QVBoxLayout* mVerticalLayout; - QAction* mAddAction; + AnimGraphPlugin* m_plugin; + QTableWidget* m_tableWidget; + QVBoxLayout* m_verticalLayout; + QAction* m_addAction; AzQtComponents::FilteredSearchWidget* m_searchWidget; AZStd::string m_searchWidgetText; - AZStd::vector mWidgetTable; + AZStd::vector m_widgetTable; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodePaletteWidget.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodePaletteWidget.cpp index a0ee45be0b..bd55ce2905 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodePaletteWidget.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodePaletteWidget.cpp @@ -287,23 +287,23 @@ namespace EMStudio } NodePaletteWidget::EventHandler::EventHandler(NodePaletteWidget* widget) - : mWidget(widget) + : m_widget(widget) {} void NodePaletteWidget::EventHandler::OnCreatedNode(EMotionFX::AnimGraph* animGraph, EMotionFX::AnimGraphNode* node) { - if (mWidget->mNode && node->GetParentNode() == mWidget->mNode) + if (m_widget->m_node && node->GetParentNode() == m_widget->m_node) { - mWidget->Init(animGraph, mWidget->mNode); + m_widget->Init(animGraph, m_widget->m_node); } } void NodePaletteWidget::EventHandler::OnRemovedChildNode(EMotionFX::AnimGraph* animGraph, EMotionFX::AnimGraphNode* parentNode) { - if (mWidget->mNode && parentNode && parentNode == mWidget->mNode) + if (m_widget->m_node && parentNode && parentNode == m_widget->m_node) { - mWidget->Init(animGraph, mWidget->mNode); + m_widget->Init(animGraph, m_widget->m_node); } } @@ -311,52 +311,52 @@ namespace EMStudio // constructor NodePaletteWidget::NodePaletteWidget(AnimGraphPlugin* plugin) : QWidget() - , mPlugin(plugin) - , mModel(new NodePaletteModel(plugin, this)) + , m_plugin(plugin) + , m_model(new NodePaletteModel(plugin, this)) { - mNode = nullptr; + m_node = nullptr; // create the default layout - mLayout = new QVBoxLayout(); - mLayout->setMargin(0); - mLayout->setSpacing(0); + m_layout = new QVBoxLayout(); + m_layout->setMargin(0); + m_layout->setSpacing(0); // create the initial text - mInitialText = new QLabel("Create and activate a Anim Graph first.
Then drag and drop items from the
palette into the Anim Graph window.
"); - mInitialText->setAlignment(Qt::AlignCenter); - mInitialText->setTextFormat(Qt::RichText); - mInitialText->setMaximumSize(10000, 10000); - mInitialText->setMargin(0); - mInitialText->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum); + m_initialText = new QLabel("Create and activate a Anim Graph first.
Then drag and drop items from the
palette into the Anim Graph window.
"); + m_initialText->setAlignment(Qt::AlignCenter); + m_initialText->setTextFormat(Qt::RichText); + m_initialText->setMaximumSize(10000, 10000); + m_initialText->setMargin(0); + m_initialText->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum); // add the initial text in the layout - mLayout->addWidget(mInitialText); + m_layout->addWidget(m_initialText); // create the tree view - mTreeView = new QTreeView(this); - mTreeView->setHeaderHidden(true); - mTreeView->setModel(mModel); - mTreeView->setDragDropMode(QAbstractItemView::DragOnly); + m_treeView = new QTreeView(this); + m_treeView->setHeaderHidden(true); + m_treeView->setModel(m_model); + m_treeView->setDragDropMode(QAbstractItemView::DragOnly); // add the tree view in the layout - mLayout->addWidget(mTreeView); + m_layout->addWidget(m_treeView); // set the default layout - setLayout(mLayout); + setLayout(m_layout); // register the event handler - mEventHandler = aznew NodePaletteWidget::EventHandler(this); - EMotionFX::GetEventManager().AddEventHandler(mEventHandler); + m_eventHandler = aznew NodePaletteWidget::EventHandler(this); + EMotionFX::GetEventManager().AddEventHandler(m_eventHandler); - connect(&mPlugin->GetAnimGraphModel(), &AnimGraphModel::FocusChanged, this, &NodePaletteWidget::OnFocusChanged); + connect(&m_plugin->GetAnimGraphModel(), &AnimGraphModel::FocusChanged, this, &NodePaletteWidget::OnFocusChanged); } // destructor NodePaletteWidget::~NodePaletteWidget() { - EMotionFX::GetEventManager().RemoveEventHandler(mEventHandler); - delete mEventHandler; + EMotionFX::GetEventManager().RemoveEventHandler(m_eventHandler); + delete m_eventHandler; } @@ -364,33 +364,33 @@ namespace EMStudio void NodePaletteWidget::Init(EMotionFX::AnimGraph* animGraph, EMotionFX::AnimGraphNode* node) { // set the node - mNode = node; + m_node = node; // check if the anim graph is not valid // on this case we show a message to say no one anim graph is activated if (animGraph == nullptr) { // set the layout params - mLayout->setMargin(0); - mLayout->setSpacing(0); + m_layout->setMargin(0); + m_layout->setSpacing(0); // set the widget visible or not - mInitialText->setVisible(true); - mTreeView->setVisible(false); + m_initialText->setVisible(true); + m_treeView->setVisible(false); } else { // set the layout params - mLayout->setMargin(2); - mLayout->setSpacing(2); + m_layout->setMargin(2); + m_layout->setSpacing(2); // set the widget visible or not - mInitialText->setVisible(false); - mTreeView->setVisible(true); + m_initialText->setVisible(false); + m_treeView->setVisible(true); } SaveExpandStates(); - mModel->setNode(mNode); + m_model->setNode(m_node); RestoreExpandStates(); } @@ -398,16 +398,16 @@ namespace EMStudio void NodePaletteWidget::SaveExpandStates() { m_expandedCatagory.clear(); - const auto& catagoryNames = mModel->GetCategoryNames(); + const auto& catagoryNames = m_model->GetCategoryNames(); // Save the expand state. for (const auto& categoryName : catagoryNames) { const QString& str = categoryName.second; - const QModelIndexList items = mModel->match(mModel->index(0, 0), Qt::DisplayRole, QVariant::fromValue(str)); + const QModelIndexList items = m_model->match(m_model->index(0, 0), Qt::DisplayRole, QVariant::fromValue(str)); if (!items.isEmpty()) { - if (mTreeView->isExpanded(items.first())) + if (m_treeView->isExpanded(items.first())) { m_expandedCatagory.emplace(categoryName.first); } @@ -418,7 +418,7 @@ namespace EMStudio void NodePaletteWidget::RestoreExpandStates() { - const auto& catagoryNames = mModel->GetCategoryNames(); + const auto& catagoryNames = m_model->GetCategoryNames(); // Restore the expand state. for (const auto& categoryName : catagoryNames) @@ -430,10 +430,10 @@ namespace EMStudio } const QString& str = categoryName.second; - const QModelIndexList items = mModel->match(mModel->index(0, 0), Qt::DisplayRole, QVariant::fromValue(str)); + const QModelIndexList items = m_model->match(m_model->index(0, 0), Qt::DisplayRole, QVariant::fromValue(str)); if (!items.isEmpty()) { - mTreeView->setExpanded(items.first(), true); + m_treeView->setExpanded(items.first(), true); } } m_expandedCatagory.clear(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodePaletteWidget.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodePaletteWidget.h index be6d17bc12..2ca1a85f74 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodePaletteWidget.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodePaletteWidget.h @@ -48,7 +48,7 @@ namespace EMStudio void OnRemovedChildNode(EMotionFX::AnimGraph* animGraph, EMotionFX::AnimGraphNode* parentNode) override; private: - NodePaletteWidget* mWidget; + NodePaletteWidget* m_widget; }; NodePaletteWidget(AnimGraphPlugin* plugin); @@ -65,13 +65,13 @@ namespace EMStudio void SaveExpandStates(); void RestoreExpandStates(); - AnimGraphPlugin* mPlugin; - NodePaletteModel* mModel; - QTreeView* mTreeView; - EMotionFX::AnimGraphNode* mNode; - EventHandler* mEventHandler; - QVBoxLayout* mLayout; - QLabel* mInitialText; + AnimGraphPlugin* m_plugin; + NodePaletteModel* m_model; + QTreeView* m_treeView; + EMotionFX::AnimGraphNode* m_node; + EventHandler* m_eventHandler; + QVBoxLayout* m_layout; + QLabel* m_initialText; // Cache the expanded states. AZStd::unordered_set m_expandedCatagory; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ParameterCreateEditDialog.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ParameterCreateEditDialog.cpp index f93e72821c..eb4696ef23 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ParameterCreateEditDialog.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ParameterCreateEditDialog.cpp @@ -25,7 +25,7 @@ namespace EMStudio { - int ParameterCreateEditDialog::m_parameterEditorMinWidth = 300; + int ParameterCreateEditDialog::s_parameterEditorMinWidth = 300; ParameterCreateEditDialog::ParameterCreateEditDialog(AnimGraphPlugin* plugin, QWidget* parent, const EMotionFX::Parameter* editParameter) : QDialog(parent) @@ -74,7 +74,7 @@ namespace EMStudio m_parameterEditorWidget->setSizePolicy(QSizePolicy::Policy::MinimumExpanding, QSizePolicy::Policy::MinimumExpanding); m_parameterEditorWidget->SetSizeHintOffset(QSize(0, 0)); m_parameterEditorWidget->SetLeafIndentation(0); - m_parameterEditorWidget->setMinimumWidth(m_parameterEditorMinWidth); + m_parameterEditorWidget->setMinimumWidth(s_parameterEditorMinWidth); mainLayout->addWidget(m_parameterEditorWidget); // Add the preview information diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ParameterCreateEditDialog.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ParameterCreateEditDialog.h index 75b0777269..941ee53727 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ParameterCreateEditDialog.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ParameterCreateEditDialog.h @@ -78,6 +78,6 @@ namespace EMStudio AZStd::unique_ptr m_parameter; AZStd::string m_originalName; - static int m_parameterEditorMinWidth; + static int s_parameterEditorMinWidth; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ParameterEditor/ColorParameterEditor.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ParameterEditor/ColorParameterEditor.cpp index 0302bb66ee..047de95f15 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ParameterEditor/ColorParameterEditor.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ParameterEditor/ColorParameterEditor.cpp @@ -63,7 +63,7 @@ namespace EMStudio if (!m_attributes.empty()) { MCore::AttributeColor* attribute = static_cast(m_attributes[0]); - m_currentValue = AZ::Color(attribute->GetValue().r, attribute->GetValue().g, attribute->GetValue().b, attribute->GetValue().a); + m_currentValue = AZ::Color(attribute->GetValue().m_r, attribute->GetValue().m_g, attribute->GetValue().m_b, attribute->GetValue().m_a); } else { diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ParameterSelectionWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ParameterSelectionWindow.cpp index 6b17148fe4..51a47a47bf 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ParameterSelectionWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ParameterSelectionWindow.cpp @@ -24,32 +24,32 @@ namespace EMStudio ParameterSelectionWindow::ParameterSelectionWindow(QWidget* parent, bool useSingleSelection) : QDialog(parent) { - mAccepted = false; + m_accepted = false; setWindowTitle("Parameter Selection Window"); QVBoxLayout* layout = new QVBoxLayout(); - mParameterWidget = new ParameterWidget(this, useSingleSelection); + m_parameterWidget = new ParameterWidget(this, useSingleSelection); // create the ok and cancel buttons QHBoxLayout* buttonLayout = new QHBoxLayout(); - mOKButton = new QPushButton("OK"); - mCancelButton = new QPushButton("Cancel"); - buttonLayout->addWidget(mOKButton); - buttonLayout->addWidget(mCancelButton); + m_okButton = new QPushButton("OK"); + m_cancelButton = new QPushButton("Cancel"); + buttonLayout->addWidget(m_okButton); + buttonLayout->addWidget(m_cancelButton); - layout->addWidget(mParameterWidget); + layout->addWidget(m_parameterWidget); layout->addLayout(buttonLayout); setLayout(layout); - connect(mOKButton, &QPushButton::clicked, this, &ParameterSelectionWindow::accept); - connect(mCancelButton, &QPushButton::clicked, this, &ParameterSelectionWindow::reject); + connect(m_okButton, &QPushButton::clicked, this, &ParameterSelectionWindow::accept); + connect(m_cancelButton, &QPushButton::clicked, this, &ParameterSelectionWindow::reject); connect(this, &ParameterSelectionWindow::accepted, this, &ParameterSelectionWindow::OnAccept); - connect(mParameterWidget, &ParameterWidget::OnDoubleClicked, this, &ParameterSelectionWindow::OnDoubleClicked); + connect(m_parameterWidget, &ParameterWidget::OnDoubleClicked, this, &ParameterSelectionWindow::OnDoubleClicked); // set the selection mode - mParameterWidget->SetSelectionMode(useSingleSelection); - mUseSingleSelection = useSingleSelection; + m_parameterWidget->SetSelectionMode(useSingleSelection); + m_useSingleSelection = useSingleSelection; } @@ -67,7 +67,7 @@ namespace EMStudio void ParameterSelectionWindow::OnAccept() { - mParameterWidget->FireSelectionDoneSignal(); + m_parameterWidget->FireSelectionDoneSignal(); } } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ParameterSelectionWindow.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ParameterSelectionWindow.h index 25e717f473..cb8e28c476 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ParameterSelectionWindow.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ParameterSelectionWindow.h @@ -26,9 +26,9 @@ namespace EMStudio * 2. Use the itemSelectionChanged() signal of the GetNodeHierarchyWidget()->GetTreeWidget() to detect when the user adjusts the selection in the node hierarchy widget. * 3. Use the OnSelectionDone() in the GetNodeHierarchyWidget() to detect when the user finished selecting and pressed the OK button. * Example: - * connect( mParameterSelectionWindow, SIGNAL(rejected()), this, SLOT(UserWantsToCancel_1()) ); - * connect( mParameterSelectionWindow->GetNodeHierarchyWidget()->GetTreeWidget(), SIGNAL(itemSelectionChanged()), this, SLOT(SelectionChanged_2()) ); - * connect( mParameterSelectionWindow->GetNodeHierarchyWidget(), SIGNAL(OnSelectionDone(AZStd::vector)), this, SLOT(FinishedSelectionAndPressedOK_3(AZStd::vector)) ); + * connect( m_parameterSelectionWindow, SIGNAL(rejected()), this, SLOT(UserWantsToCancel_1()) ); + * connect( m_parameterSelectionWindow->GetNodeHierarchyWidget()->GetTreeWidget(), SIGNAL(itemSelectionChanged()), this, SLOT(SelectionChanged_2()) ); + * connect( m_parameterSelectionWindow->GetNodeHierarchyWidget(), SIGNAL(OnSelectionDone(AZStd::vector)), this, SLOT(FinishedSelectionAndPressedOK_3(AZStd::vector)) ); */ class ParameterSelectionWindow : public QDialog @@ -40,18 +40,18 @@ namespace EMStudio ParameterSelectionWindow(QWidget* parent, bool useSingleSelection); virtual ~ParameterSelectionWindow(); - MCORE_INLINE ParameterWidget* GetParameterWidget() { return mParameterWidget; } - void Update(EMotionFX::AnimGraph* animGraph, const AZStd::vector& selectedParameters) { mParameterWidget->Update(animGraph, selectedParameters); } + MCORE_INLINE ParameterWidget* GetParameterWidget() { return m_parameterWidget; } + void Update(EMotionFX::AnimGraph* animGraph, const AZStd::vector& selectedParameters) { m_parameterWidget->Update(animGraph, selectedParameters); } public slots: void OnAccept(); void OnDoubleClicked(const AZStd::string& item); private: - ParameterWidget* mParameterWidget; - QPushButton* mOKButton; - QPushButton* mCancelButton; - bool mUseSingleSelection; - bool mAccepted; + ParameterWidget* m_parameterWidget; + QPushButton* m_okButton; + QPushButton* m_cancelButton; + bool m_useSingleSelection; + bool m_accepted; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ParameterWidget.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ParameterWidget.cpp index 87f9782c95..3c96367d1f 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ParameterWidget.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ParameterWidget.cpp @@ -36,32 +36,32 @@ namespace EMStudio layout->setMargin(0); // create the tree widget - mTreeWidget = new QTreeWidget(); + m_treeWidget = new QTreeWidget(); // create header items - mTreeWidget->setColumnCount(1); + m_treeWidget->setColumnCount(1); QStringList headerList; headerList.append("Name"); - mTreeWidget->setHeaderLabels(headerList); + m_treeWidget->setHeaderLabels(headerList); // set optical stuff for the tree - mTreeWidget->setSortingEnabled(false); - mTreeWidget->setSelectionMode(QAbstractItemView::SingleSelection); - mTreeWidget->setMinimumWidth(620); - mTreeWidget->setMinimumHeight(500); - mTreeWidget->setAlternatingRowColors(true); - mTreeWidget->setExpandsOnDoubleClick(true); - mTreeWidget->setAnimated(true); + m_treeWidget->setSortingEnabled(false); + m_treeWidget->setSelectionMode(QAbstractItemView::SingleSelection); + m_treeWidget->setMinimumWidth(620); + m_treeWidget->setMinimumHeight(500); + m_treeWidget->setAlternatingRowColors(true); + m_treeWidget->setExpandsOnDoubleClick(true); + m_treeWidget->setAnimated(true); // disable the move of section to have column order fixed - mTreeWidget->header()->setSectionsMovable(false); + m_treeWidget->header()->setSectionsMovable(false); layout->addWidget(m_searchWidget); - layout->addWidget(mTreeWidget); + layout->addWidget(m_treeWidget); setLayout(layout); - connect(mTreeWidget, &QTreeWidget::itemSelectionChanged, this, &ParameterWidget::UpdateSelection); - connect(mTreeWidget, &QTreeWidget::itemDoubleClicked, this, &ParameterWidget::ItemDoubleClicked); + connect(m_treeWidget, &QTreeWidget::itemSelectionChanged, this, &ParameterWidget::UpdateSelection); + connect(m_treeWidget, &QTreeWidget::itemDoubleClicked, this, &ParameterWidget::ItemDoubleClicked); // set the selection mode SetSelectionMode(useSingleSelection); @@ -75,9 +75,9 @@ namespace EMStudio void ParameterWidget::Update(EMotionFX::AnimGraph* animGraph, const AZStd::vector& selectedParameters) { - mAnimGraph = animGraph; - mSelectedParameters = selectedParameters; - mOldSelectedParameters = selectedParameters; + m_animGraph = animGraph; + m_selectedParameters = selectedParameters; + m_oldSelectedParameters = selectedParameters; Update(); } @@ -102,15 +102,15 @@ namespace EMStudio } else { - item = new QTreeWidgetItem(mTreeWidget); - mTreeWidget->addTopLevelItem(item); + item = new QTreeWidgetItem(m_treeWidget); + m_treeWidget->addTopLevelItem(item); } item->setText(0, parameter->GetName().c_str()); item->setExpanded(true); // check if the given parameter is selected - if (AZStd::find(mOldSelectedParameters.begin(), mOldSelectedParameters.end(), parameter->GetName()) != mOldSelectedParameters.end()) + if (AZStd::find(m_oldSelectedParameters.begin(), m_oldSelectedParameters.end(), parameter->GetName()) != m_oldSelectedParameters.end()) { item->setSelected(true); } @@ -120,39 +120,39 @@ namespace EMStudio void ParameterWidget::Update() { - mTreeWidget->clear(); - mTreeWidget->blockSignals(true); + m_treeWidget->clear(); + m_treeWidget->blockSignals(true); // add all parameters that belong to no group parameter - const EMotionFX::ValueParameterVector childValueParameters = mAnimGraph->GetChildValueParameters(); + const EMotionFX::ValueParameterVector childValueParameters = m_animGraph->GetChildValueParameters(); for (const EMotionFX::ValueParameter* parameter : childValueParameters) { - AddParameterToInterface(mAnimGraph, parameter, nullptr); + AddParameterToInterface(m_animGraph, parameter, nullptr); } // get all group parameters and iterate through them AZStd::string tempString; - const EMotionFX::GroupParameterVector groupParameters = mAnimGraph->RecursivelyGetGroupParameters(); + const EMotionFX::GroupParameterVector groupParameters = m_animGraph->RecursivelyGetGroupParameters(); for (const EMotionFX::GroupParameter* groupParameter : groupParameters) { // add the group item to the tree widget - QTreeWidgetItem* groupItem = new QTreeWidgetItem(mTreeWidget); + QTreeWidgetItem* groupItem = new QTreeWidgetItem(m_treeWidget); groupItem->setText(0, groupParameter->GetName().c_str()); groupItem->setExpanded(true); const EMotionFX::ValueParameterVector childValueParameters2 = groupParameter->GetChildValueParameters(); tempString = AZStd::string::format("%zu Parameters", childValueParameters2.size()); groupItem->setToolTip(1, tempString.c_str()); - mTreeWidget->addTopLevelItem(groupItem); + m_treeWidget->addTopLevelItem(groupItem); // add all parameters that belong to the given group bool groupSelected = !childValueParameters2.empty(); for (const EMotionFX::ValueParameter* valueParameter : childValueParameters2) { - AddParameterToInterface(mAnimGraph, valueParameter, groupItem); + AddParameterToInterface(m_animGraph, valueParameter, groupItem); // check if the given parameter is selected - if (groupSelected && AZStd::find(mOldSelectedParameters.begin(), mOldSelectedParameters.end(), valueParameter->GetName()) == mOldSelectedParameters.end()) + if (groupSelected && AZStd::find(m_oldSelectedParameters.begin(), m_oldSelectedParameters.end(), valueParameter->GetName()) == m_oldSelectedParameters.end()) { groupSelected = false; } @@ -161,18 +161,18 @@ namespace EMStudio groupItem->setSelected(groupSelected); } - mTreeWidget->blockSignals(false); + m_treeWidget->blockSignals(false); UpdateSelection(); } void ParameterWidget::UpdateSelection() { - QList selectedItems = mTreeWidget->selectedItems(); + QList selectedItems = m_treeWidget->selectedItems(); - mSelectedParameters.clear(); + m_selectedParameters.clear(); const uint32 numSelectedItems = selectedItems.count(); - mSelectedParameters.reserve(numSelectedItems); + m_selectedParameters.reserve(numSelectedItems); // Iterate through the selected items in the tree widget. AZStd::string itemName; @@ -183,7 +183,7 @@ namespace EMStudio // Get the parameter by name. // Skip elements that we can't find as they also shouldn't be selectable. - const EMotionFX::Parameter* parameter = mAnimGraph->FindParameterByName(itemName); + const EMotionFX::Parameter* parameter = m_animGraph->FindParameterByName(itemName); if (!parameter) { continue; @@ -192,9 +192,9 @@ namespace EMStudio // check if the selected item is a parameter if (azrtti_typeid(parameter) != azrtti_typeid()) { - if (AZStd::find(mSelectedParameters.begin(), mSelectedParameters.end(), itemName) == mSelectedParameters.end()) + if (AZStd::find(m_selectedParameters.begin(), m_selectedParameters.end(), itemName) == m_selectedParameters.end()) { - mSelectedParameters.emplace_back(itemName); + m_selectedParameters.emplace_back(itemName); } } // selected item is a group @@ -205,9 +205,9 @@ namespace EMStudio const EMotionFX::ValueParameterVector valueParameters = groupParameter->RecursivelyGetChildValueParameters(); for (const EMotionFX::ValueParameter* valueParameter : valueParameters) { - if (AZStd::find(mSelectedParameters.begin(), mSelectedParameters.end(), valueParameter->GetName()) == mSelectedParameters.end()) + if (AZStd::find(m_selectedParameters.begin(), m_selectedParameters.end(), valueParameter->GetName()) == m_selectedParameters.end()) { - mSelectedParameters.emplace_back(valueParameter->GetName()); + m_selectedParameters.emplace_back(valueParameter->GetName()); } } } @@ -219,14 +219,14 @@ namespace EMStudio { if (useSingleSelection) { - mTreeWidget->setSelectionMode(QAbstractItemView::SingleSelection); + m_treeWidget->setSelectionMode(QAbstractItemView::SingleSelection); } else { - mTreeWidget->setSelectionMode(QAbstractItemView::ExtendedSelection); + m_treeWidget->setSelectionMode(QAbstractItemView::ExtendedSelection); } - mUseSingleSelection = useSingleSelection; + m_useSingleSelection = useSingleSelection; } void ParameterWidget::SetFilterTypes(const AZStd::vector& filterTypes) @@ -240,9 +240,9 @@ namespace EMStudio MCORE_UNUSED(column); UpdateSelection(); - if (!mSelectedParameters.empty()) + if (!m_selectedParameters.empty()) { - emit OnDoubleClicked(mSelectedParameters[0]); + emit OnDoubleClicked(m_selectedParameters[0]); } } @@ -257,7 +257,7 @@ namespace EMStudio void ParameterWidget::FireSelectionDoneSignal() { - emit OnSelectionDone(mSelectedParameters); + emit OnSelectionDone(m_selectedParameters); } } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ParameterWidget.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ParameterWidget.h index ed2bd1c4e9..9f0601243b 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ParameterWidget.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ParameterWidget.h @@ -45,11 +45,11 @@ namespace EMStudio void SetFilterTypes(const AZStd::vector& filterTypes); void Update(EMotionFX::AnimGraph* animGraph, const AZStd::vector& selectedParameters); void FireSelectionDoneSignal(); - MCORE_INLINE QTreeWidget* GetTreeWidget() { return mTreeWidget; } + MCORE_INLINE QTreeWidget* GetTreeWidget() { return m_treeWidget; } MCORE_INLINE AzQtComponents::FilteredSearchWidget* GetSearchWidget() { return m_searchWidget; } // this calls UpdateSelection() and then returns the member array containing the selected items - AZStd::vector& GetSelectedParameters() { UpdateSelection(); return mSelectedParameters; } + AZStd::vector& GetSelectedParameters() { UpdateSelection(); return m_selectedParameters; } signals: void OnSelectionDone(const AZStd::vector& selectedItems); @@ -65,13 +65,13 @@ namespace EMStudio private: void AddParameterToInterface(EMotionFX::AnimGraph* animGraph, const EMotionFX::Parameter* parameter, QTreeWidgetItem* groupParameterItem); - EMotionFX::AnimGraph* mAnimGraph; - QTreeWidget* mTreeWidget; + EMotionFX::AnimGraph* m_animGraph; + QTreeWidget* m_treeWidget; AzQtComponents::FilteredSearchWidget* m_searchWidget; AZStd::string m_searchWidgetText; AZStd::vector m_filterTypes; - AZStd::vector mSelectedParameters; - AZStd::vector mOldSelectedParameters; - bool mUseSingleSelection; + AZStd::vector m_selectedParameters; + AZStd::vector m_oldSelectedParameters; + bool m_useSingleSelection; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ParameterWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ParameterWindow.cpp index 9664011083..c93d358c07 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ParameterWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ParameterWindow.cpp @@ -47,7 +47,7 @@ namespace EMStudio { - int ParameterWindow::m_contextMenuWidth = 100; + int ParameterWindow::s_contextMenuWidth = 100; // constructor ParameterCreateRenameWindow::ParameterCreateRenameWindow(const char* windowTitle, const char* topText, const char* defaultName, const char* oldName, const AZStd::vector& invalidNames, QWidget* parent) @@ -56,8 +56,8 @@ namespace EMStudio setObjectName("EMFX.ParameterCreateRenameDialog"); // store values - mOldName = oldName; - mInvalidNames = invalidNames; + m_oldName = oldName; + m_invalidNames = invalidNames; // update title of the about dialog setWindowTitle(windowTitle); @@ -75,27 +75,27 @@ namespace EMStudio } // add the line edit - mLineEdit = new QLineEdit(defaultName); - connect(mLineEdit, &QLineEdit::textChanged, this, &ParameterCreateRenameWindow::NameEditChanged); - mLineEdit->selectAll(); + m_lineEdit = new QLineEdit(defaultName); + connect(m_lineEdit, &QLineEdit::textChanged, this, &ParameterCreateRenameWindow::NameEditChanged); + m_lineEdit->selectAll(); // create the button layout QHBoxLayout* buttonLayout = new QHBoxLayout(); - mOKButton = new QPushButton("OK"); - mCancelButton = new QPushButton("Cancel"); - buttonLayout->addWidget(mOKButton); - buttonLayout->addWidget(mCancelButton); + m_okButton = new QPushButton("OK"); + m_cancelButton = new QPushButton("Cancel"); + buttonLayout->addWidget(m_okButton); + buttonLayout->addWidget(m_cancelButton); // set the layout - layout->addWidget(mLineEdit); + layout->addWidget(m_lineEdit); layout->addLayout(buttonLayout); setLayout(layout); // connect the buttons - connect(mOKButton, &QPushButton::clicked, this, &ParameterCreateRenameWindow::accept); - connect(mCancelButton, &QPushButton::clicked, this, &ParameterCreateRenameWindow::reject); + connect(m_okButton, &QPushButton::clicked, this, &ParameterCreateRenameWindow::accept); + connect(m_cancelButton, &QPushButton::clicked, this, &ParameterCreateRenameWindow::reject); - mOKButton->setDefault(true); + m_okButton->setDefault(true); } // check for duplicate names upon editing @@ -104,44 +104,44 @@ namespace EMStudio const AZStd::string convertedNewName = text.toUtf8().data(); if (text.isEmpty()) { - mOKButton->setEnabled(false); - GetManager()->SetWidgetAsInvalidInput(mLineEdit); + m_okButton->setEnabled(false); + GetManager()->SetWidgetAsInvalidInput(m_lineEdit); } - else if (mOldName == convertedNewName) + else if (m_oldName == convertedNewName) { - mOKButton->setEnabled(true); - mLineEdit->setStyleSheet(""); + m_okButton->setEnabled(true); + m_lineEdit->setStyleSheet(""); } else { // Check if the name has invalid characters. if (!EMotionFX::Parameter::IsNameValid(convertedNewName, nullptr)) { - mOKButton->setEnabled(false); - GetManager()->SetWidgetAsInvalidInput(mLineEdit); + m_okButton->setEnabled(false); + GetManager()->SetWidgetAsInvalidInput(m_lineEdit); return; } // Is there a parameter with the given name already? - if (AZStd::find(mInvalidNames.begin(), mInvalidNames.end(), convertedNewName) != mInvalidNames.end()) + if (AZStd::find(m_invalidNames.begin(), m_invalidNames.end(), convertedNewName) != m_invalidNames.end()) { - mOKButton->setEnabled(false); - GetManager()->SetWidgetAsInvalidInput(mLineEdit); + m_okButton->setEnabled(false); + GetManager()->SetWidgetAsInvalidInput(m_lineEdit); return; } // no duplicate name found - mOKButton->setEnabled(true); - mLineEdit->setStyleSheet(""); + m_okButton->setEnabled(true); + m_lineEdit->setStyleSheet(""); } } ParameterWindow::ParameterWindow(AnimGraphPlugin* plugin) : QWidget() { - mPlugin = plugin; - mEnsureVisibility = false; - mLockSelection = false; + m_plugin = plugin; + m_ensureVisibility = false; + m_lockSelection = false; // add the add button QToolBar* toolBar = new QToolBar(this); @@ -182,55 +182,55 @@ namespace EMStudio toolBar->addWidget(m_searchWidget); // create the parameter tree widget - mTreeWidget = new ParameterWindowTreeWidget(); - mTreeWidget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); - mTreeWidget->setObjectName("AnimGraphParamWindow"); - mTreeWidget->header()->setVisible(false); + m_treeWidget = new ParameterWindowTreeWidget(); + m_treeWidget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); + m_treeWidget->setObjectName("AnimGraphParamWindow"); + m_treeWidget->header()->setVisible(false); // adjust selection mode and enable some other helpful things - mTreeWidget->setSelectionBehavior(QAbstractItemView::SelectRows); - mTreeWidget->setSelectionMode(QAbstractItemView::ExtendedSelection); - mTreeWidget->setExpandsOnDoubleClick(true); - mTreeWidget->setColumnCount(3); - mTreeWidget->setUniformRowHeights(true); - mTreeWidget->setIndentation(10); - mTreeWidget->header()->setSectionResizeMode(0, QHeaderView::ResizeToContents); - mTreeWidget->header()->setSectionResizeMode(1, QHeaderView::ResizeToContents); - mTreeWidget->header()->setSectionResizeMode(2, QHeaderView::Stretch); + m_treeWidget->setSelectionBehavior(QAbstractItemView::SelectRows); + m_treeWidget->setSelectionMode(QAbstractItemView::ExtendedSelection); + m_treeWidget->setExpandsOnDoubleClick(true); + m_treeWidget->setColumnCount(3); + m_treeWidget->setUniformRowHeights(true); + m_treeWidget->setIndentation(10); + m_treeWidget->header()->setSectionResizeMode(0, QHeaderView::ResizeToContents); + m_treeWidget->header()->setSectionResizeMode(1, QHeaderView::ResizeToContents); + m_treeWidget->header()->setSectionResizeMode(2, QHeaderView::Stretch); // enable drag and drop - mTreeWidget->setDragEnabled(true); - mTreeWidget->setDragDropMode(QAbstractItemView::InternalMove); + m_treeWidget->setDragEnabled(true); + m_treeWidget->setDragDropMode(QAbstractItemView::InternalMove); // connect the tree widget - connect(mTreeWidget, &QTreeWidget::itemSelectionChanged, this, &ParameterWindow::OnSelectionChanged); - connect(mTreeWidget, &QTreeWidget::itemCollapsed, this, &ParameterWindow::OnGroupCollapsed); - connect(mTreeWidget, &QTreeWidget::itemExpanded, this, &ParameterWindow::OnGroupExpanded); - connect(mTreeWidget, &ParameterWindowTreeWidget::ParameterMoved, this, &ParameterWindow::OnMoveParameterTo); - connect(mTreeWidget, &ParameterWindowTreeWidget::DragEnded, this, [this]() + connect(m_treeWidget, &QTreeWidget::itemSelectionChanged, this, &ParameterWindow::OnSelectionChanged); + connect(m_treeWidget, &QTreeWidget::itemCollapsed, this, &ParameterWindow::OnGroupCollapsed); + connect(m_treeWidget, &QTreeWidget::itemExpanded, this, &ParameterWindow::OnGroupExpanded); + connect(m_treeWidget, &ParameterWindowTreeWidget::ParameterMoved, this, &ParameterWindow::OnMoveParameterTo); + connect(m_treeWidget, &ParameterWindowTreeWidget::DragEnded, this, [this]() { Reinit(/*forceReinit*/true); }); // create and fill the vertical layout - mVerticalLayout = new QVBoxLayout(); - mVerticalLayout->setObjectName("StyledWidget"); - mVerticalLayout->setSpacing(2); - mVerticalLayout->setMargin(0); - mVerticalLayout->setAlignment(Qt::AlignTop); - mVerticalLayout->addWidget(toolBar); - mVerticalLayout->addWidget(mTreeWidget); + m_verticalLayout = new QVBoxLayout(); + m_verticalLayout->setObjectName("StyledWidget"); + m_verticalLayout->setSpacing(2); + m_verticalLayout->setMargin(0); + m_verticalLayout->setAlignment(Qt::AlignTop); + m_verticalLayout->addWidget(toolBar); + m_verticalLayout->addWidget(m_treeWidget); // set the object name setObjectName("StyledWidget"); - setLayout(mVerticalLayout); + setLayout(m_verticalLayout); // set the focus policy setFocusPolicy(Qt::ClickFocus); // Force reinitialize in case e.g. a parameter got added or removed. - connect(&mPlugin->GetAnimGraphModel(), &AnimGraphModel::ParametersChanged, [this](EMotionFX::AnimGraph* animGraph) + connect(&m_plugin->GetAnimGraphModel(), &AnimGraphModel::ParametersChanged, [this](EMotionFX::AnimGraph* animGraph) { if (animGraph == m_animGraph) { @@ -238,7 +238,7 @@ namespace EMStudio } }); - connect(&mPlugin->GetAnimGraphModel(), &AnimGraphModel::FocusChanged, this, &ParameterWindow::OnFocusChanged); + connect(&m_plugin->GetAnimGraphModel(), &AnimGraphModel::FocusChanged, this, &ParameterWindow::OnFocusChanged); // Trigger actions are processed from EMotionFX worker threads, which // are not allowed to update the UI. Use a QueuedConnection to force @@ -267,7 +267,7 @@ namespace EMStudio // get access to the game controller and check if it is valid bool isGameControllerValid = false; #if AZ_TRAIT_EMOTIONFX_HAS_GAME_CONTROLLER - GameControllerWindow* gameControllerWindow = mPlugin->GetGameControllerWindow(); + GameControllerWindow* gameControllerWindow = m_plugin->GetGameControllerWindow(); if (gameControllerWindow) { isGameControllerValid = gameControllerWindow->GetIsGameControllerValid(); @@ -318,7 +318,7 @@ namespace EMStudio bool isGameControllerValid = false; #if AZ_TRAIT_EMOTIONFX_HAS_GAME_CONTROLLER - GameControllerWindow* gameControllerWindow = mPlugin->GetGameControllerWindow(); + GameControllerWindow* gameControllerWindow = m_plugin->GetGameControllerWindow(); if (gameControllerWindow) { isGameControllerValid = gameControllerWindow->GetIsGameControllerValid(); @@ -343,9 +343,9 @@ namespace EMStudio void ParameterWindow::AddParameterToInterface(EMotionFX::AnimGraph* animGraph, const EMotionFX::Parameter* parameter, QTreeWidgetItem* parentWidgetItem) { // Only filter value parameters - if (!mFilterString.empty() + if (!m_filterString.empty() && azrtti_typeid(parameter) != azrtti_typeid() - && AzFramework::StringFunc::Find(parameter->GetName().c_str(), mFilterString.c_str()) == AZStd::string::npos) + && AzFramework::StringFunc::Find(parameter->GetName().c_str(), m_filterString.c_str()) == AZStd::string::npos) { return; } @@ -360,10 +360,10 @@ namespace EMStudio if (GetIsParameterSelected(parameter->GetName())) { widgetItem->setSelected(true); - if (mEnsureVisibility) + if (m_ensureVisibility) { - mTreeWidget->scrollToItem(widgetItem); - mEnsureVisibility = false; + m_treeWidget->scrollToItem(widgetItem); + m_ensureVisibility = false; } } @@ -405,7 +405,7 @@ namespace EMStudio AZ_Error("EMotionFX", false, "Can't get serialize context from component application."); return; } - parameterWidget.m_propertyEditor = aznew AzToolsFramework::ReflectedPropertyEditor(mTreeWidget); + parameterWidget.m_propertyEditor = aznew AzToolsFramework::ReflectedPropertyEditor(m_treeWidget); parameterWidget.m_propertyEditor->SetSizeHintOffset(QSize(0, 0)); parameterWidget.m_propertyEditor->SetAutoResizeLabels(false); parameterWidget.m_propertyEditor->SetLeafIndentation(0); @@ -419,7 +419,7 @@ namespace EMStudio parameterWidget.m_propertyEditor->ExpandAll(); parameterWidget.m_propertyEditor->InvalidateAll(); - mTreeWidget->setItemWidget(widgetItem, 2, parameterWidget.m_propertyEditor); + m_treeWidget->setItemWidget(widgetItem, 2, parameterWidget.m_propertyEditor); // create the gizmo widget in case the parameter is currently not being controlled by the gamepad QWidget* gizmoWidget = nullptr; @@ -445,8 +445,8 @@ namespace EMStudio } if (gizmoWidget) { - mTreeWidget->setItemWidget(widgetItem, 1, gizmoWidget); - mTreeWidget->setColumnWidth(1, 20); + m_treeWidget->setItemWidget(widgetItem, 1, gizmoWidget); + m_treeWidget->setColumnWidth(1, 20); } auto insertIt = m_parameterWidgets.emplace(parameter, AZStd::move(parameterWidget)); @@ -520,7 +520,7 @@ namespace EMStudio QAction* editAction = menu->addAction("Edit"); connect(editAction, &QAction::triggered, this, &ParameterWindow::OnEditButton); } - if (!mSelectedParameterNames.empty()) + if (!m_selectedParameterNames.empty()) { menu->addSeparator(); @@ -561,7 +561,7 @@ namespace EMStudio && AZStd::find(groupParametersInCurrentParameter.begin(), groupParametersInCurrentParameter.end(), groupParameter) == groupParametersInCurrentParameter.end() - && AZStd::find(mSelectedParameterNames.begin(), mSelectedParameterNames.end(), groupParameter->GetName()) == mSelectedParameterNames.end()) + && AZStd::find(m_selectedParameterNames.begin(), m_selectedParameterNames.end(), groupParameter->GetName()) == m_selectedParameterNames.end()) { QAction* groupAction = groupMenu->addAction(groupParameter->GetName().c_str()); groupAction->setCheckable(true); @@ -586,7 +586,7 @@ namespace EMStudio menu->addSeparator(); // remove action - if (!mSelectedParameterNames.empty()) + if (!m_selectedParameterNames.empty()) { QAction* removeAction = menu->addAction("Remove"); connect(removeAction, &QAction::triggered, this, &ParameterWindow::OnRemoveSelected); @@ -676,29 +676,29 @@ namespace EMStudio void ParameterWindow::Reinit(bool forceReinit) { - mLockSelection = true; + m_lockSelection = true; // Early out in case we're already showing the parameters from the focused anim graph. - if (!forceReinit && m_animGraph == mPlugin->GetAnimGraphModel().GetFocusedAnimGraph()) + if (!forceReinit && m_animGraph == m_plugin->GetAnimGraphModel().GetFocusedAnimGraph()) { UpdateAttributesForParameterWidgets(); UpdateInterface(); - mLockSelection = false; + m_lockSelection = false; return; } - m_animGraph = mPlugin->GetAnimGraphModel().GetFocusedAnimGraph(); - qobject_cast(mTreeWidget)->SetAnimGraph(m_animGraph); + m_animGraph = m_plugin->GetAnimGraphModel().GetFocusedAnimGraph(); + qobject_cast(m_treeWidget)->SetAnimGraph(m_animGraph); // First clear the parameter widgets array and then the actual tree widget. // Don't change the order here as the tree widget clear call calls an on selection changed which uses the parameter widget array. m_parameterWidgets.clear(); - mTreeWidget->clear(); + m_treeWidget->clear(); if (!m_animGraph) { UpdateInterface(); - mLockSelection = false; + m_lockSelection = false; return; } @@ -706,10 +706,10 @@ namespace EMStudio const EMotionFX::ParameterVector& childParameters = m_animGraph->GetChildParameters(); for (const EMotionFX::Parameter* parameter : childParameters) { - AddParameterToInterface(m_animGraph, parameter, mTreeWidget->invisibleRootItem()); + AddParameterToInterface(m_animGraph, parameter, m_treeWidget->invisibleRootItem()); } - mLockSelection = false; + m_lockSelection = false; UpdateAttributesForParameterWidgets(); UpdateInterface(); @@ -718,11 +718,11 @@ namespace EMStudio void ParameterWindow::SingleSelectGroupParameter(const char* groupName, bool ensureVisibility, bool updateInterface) { - mSelectedParameterNames.clear(); + m_selectedParameterNames.clear(); - mSelectedParameterNames.push_back(groupName); + m_selectedParameterNames.push_back(groupName); - mEnsureVisibility = ensureVisibility; + m_ensureVisibility = ensureVisibility; if (updateInterface) { @@ -732,10 +732,10 @@ namespace EMStudio void ParameterWindow::SelectParameters(const AZStd::vector& parameterNames, bool updateInterface) { - mTreeWidget->clearSelection(); + m_treeWidget->clearSelection(); for (const AZStd::string& parameterName : parameterNames) { - const QList foundItems = mTreeWidget->findItems(parameterName.c_str(), Qt::MatchFixedString); + const QList foundItems = m_treeWidget->findItems(parameterName.c_str(), Qt::MatchFixedString); for (QTreeWidgetItem* foundItem : foundItems) { foundItem->setSelected(true); @@ -753,7 +753,7 @@ namespace EMStudio void ParameterWindow::OnTextFilterChanged(const QString& text) { - mFilterString = text.toUtf8().data(); + m_filterString = text.toUtf8().data(); Reinit(/*forceReinit=*/true); } @@ -829,7 +829,7 @@ namespace EMStudio // disable the remove and edit buttton if we dont have any parameter selected m_editAction->setEnabled(true); - if (mSelectedParameterNames.empty()) + if (m_selectedParameterNames.empty()) { m_editAction->setEnabled(false); } @@ -838,7 +838,7 @@ namespace EMStudio bool moveUpPossible, moveDownPossible; CanMove(&moveUpPossible, &moveDownPossible); - bool isAnimGraphActive = mPlugin->IsAnimGraphActive(m_animGraph); + bool isAnimGraphActive = m_plugin->IsAnimGraphActive(m_animGraph); // Make the parameter widgets read-only in case they are either controlled by the gamepad or the anim graph is not running on an actor instance. for (const auto& iterator : m_parameterWidgets) @@ -912,7 +912,7 @@ namespace EMStudio return; } - ParameterCreateEditDialog* createEditParameterDialog = new ParameterCreateEditDialog(mPlugin, this); + ParameterCreateEditDialog* createEditParameterDialog = new ParameterCreateEditDialog(m_plugin, this); createEditParameterDialog->Init(); EMStudio::ParameterCreateEditDialog::connect(createEditParameterDialog, &QDialog::finished, [=](int resultCode) @@ -988,7 +988,7 @@ namespace EMStudio const AZStd::string oldName = parameter->GetName(); // create and init the dialog - ParameterCreateEditDialog* dialog = new ParameterCreateEditDialog(mPlugin, this, parameter); + ParameterCreateEditDialog* dialog = new ParameterCreateEditDialog(m_plugin, this, parameter); dialog->Init(); // We cannot use exec here as we need to access it from the tests EMStudio::ParameterCreateEditDialog::connect(dialog, &QDialog::finished, [=](int resultCode) @@ -1023,7 +1023,7 @@ namespace EMStudio EMotionFX::AnimGraphNode::Port newPort; if (const EMotionFX::ValueParameter* valueParameter = azrtti_cast(editedParameter.get())) { - newPort.mCompatibleTypes[0] = valueParameter->GetType(); + newPort.m_compatibleTypes[0] = valueParameter->GetType(); } // Get the list of all parameter nodes @@ -1107,13 +1107,13 @@ namespace EMStudio void ParameterWindow::UpdateSelectionArrays() { // only update the selection in case it is not locked - if (mLockSelection) + if (m_lockSelection) { return; } // clear the selection - mSelectedParameterNames.clear(); + m_selectedParameterNames.clear(); if (!m_animGraph) { @@ -1121,14 +1121,14 @@ namespace EMStudio } // make sure we only have exactly one selected item - QList selectedItems = mTreeWidget->selectedItems(); + QList selectedItems = m_treeWidget->selectedItems(); int32 numSelectedItems = selectedItems.count(); for (int32 i = 0; i < numSelectedItems; ++i) { // get the selected item QTreeWidgetItem* selectedItem = selectedItems[i]; - mSelectedParameterNames.emplace_back(selectedItem->data(0, Qt::UserRole).toString().toUtf8().data()); + m_selectedParameterNames.emplace_back(selectedItem->data(0, Qt::UserRole).toString().toUtf8().data()); } } @@ -1136,7 +1136,7 @@ namespace EMStudio // get the index of the selected parameter const EMotionFX::Parameter* ParameterWindow::GetSingleSelectedParameter() const { - if (mSelectedParameterNames.size() != 1) + if (m_selectedParameterNames.size() != 1) { return nullptr; } @@ -1147,7 +1147,7 @@ namespace EMStudio } // find and return the index of the parameter in the anim graph - return m_animGraph->FindParameterByName(mSelectedParameterNames[0]); + return m_animGraph->FindParameterByName(m_selectedParameterNames[0]); } @@ -1192,7 +1192,7 @@ namespace EMStudio AZStd::vector selectedValueParameters; // get the number of selected parameters and iterate through them - for (const AZStd::string& selectedParameter : mSelectedParameterNames) + for (const AZStd::string& selectedParameter : m_selectedParameterNames) { const EMotionFX::Parameter* parameter = m_animGraph->FindParameterByName(selectedParameter); if (!parameter) @@ -1211,7 +1211,7 @@ namespace EMStudio for (const EMotionFX::Parameter* parameter2 : parametersInGroup) { const AZStd::string& parameterName = parameter2->GetName(); - if (AZStd::find(mSelectedParameterNames.begin(), mSelectedParameterNames.end(), parameterName) == mSelectedParameterNames.end()) + if (AZStd::find(m_selectedParameterNames.begin(), m_selectedParameterNames.end(), parameterName) == m_selectedParameterNames.end()) { paramsOfSelectedGroup.push_back(parameterName); } @@ -1294,7 +1294,7 @@ namespace EMStudio int ParameterWindow::GetTopLevelItemCount() const { - return mTreeWidget->topLevelItemCount(); + return m_treeWidget->topLevelItemCount(); } // move parameter under a specific parent, at a determined index @@ -1345,7 +1345,7 @@ namespace EMStudio } // get the number of selected parameters and return directly in case there aren't any selected - const size_t numSelectedParameters = mSelectedParameterNames.size(); + const size_t numSelectedParameters = m_selectedParameterNames.size(); if (numSelectedParameters == 0) { return; @@ -1364,7 +1364,7 @@ namespace EMStudio const EMotionFX::GroupParameter* groupParameter = m_animGraph->FindGroupParameterByName(groupParameterName); AZStd::string parameterNames; - AZ::StringFunc::Join(parameterNames, begin(mSelectedParameterNames), end(mSelectedParameterNames), ";"); + AZ::StringFunc::Join(parameterNames, begin(m_selectedParameterNames), end(m_selectedParameterNames), ";"); if (groupParameter) { commandString = AZStd::string::format(R"(AnimGraphAdjustGroupParameter -animGraphID %d -name "%s" -parameterNames "%s" -action "add")", diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ParameterWindow.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ParameterWindow.h index 3d53469c16..66cb62f0a5 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ParameterWindow.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ParameterWindow.h @@ -63,18 +63,18 @@ namespace EMStudio AZStd::string GetName() const { - return mLineEdit->text().toUtf8().data(); + return m_lineEdit->text().toUtf8().data(); } private slots: void NameEditChanged(const QString& text); private: - AZStd::string mOldName; - AZStd::vector mInvalidNames; - QPushButton* mOKButton; - QPushButton* mCancelButton; - QLineEdit* mLineEdit; + AZStd::string m_oldName; + AZStd::vector m_invalidNames; + QPushButton* m_okButton; + QPushButton* m_cancelButton; + QLineEdit* m_lineEdit; }; class ParameterWindow @@ -96,7 +96,7 @@ namespace EMStudio bool GetIsParameterSelected(const AZStd::string& parameterName) { - if (AZStd::find(mSelectedParameterNames.begin(), mSelectedParameterNames.end(), parameterName) == mSelectedParameterNames.end()) + if (AZStd::find(m_selectedParameterNames.begin(), m_selectedParameterNames.end(), parameterName) == m_selectedParameterNames.end()) { return false; } @@ -192,21 +192,21 @@ namespace EMStudio // toolbar buttons QAction* m_addAction; - static int m_contextMenuWidth; + static int s_contextMenuWidth; QAction* m_editAction; - AZStd::vector mSelectedParameterNames; - bool mEnsureVisibility; - bool mLockSelection; + AZStd::vector m_selectedParameterNames; + bool m_ensureVisibility; + bool m_lockSelection; - AZStd::string mFilterString; - AnimGraphPlugin* mPlugin; - ParameterWindowTreeWidget* mTreeWidget; + AZStd::string m_filterString; + AnimGraphPlugin* m_plugin; + ParameterWindowTreeWidget* m_treeWidget; AzQtComponents::FilteredSearchWidget* m_searchWidget; - QVBoxLayout* mVerticalLayout; - QScrollArea* mScrollArea; - AZStd::string mNameString; + QVBoxLayout* m_verticalLayout; + QScrollArea* m_scrollArea; + AZStd::string m_nameString; struct ParameterWidget { AZStd::unique_ptr m_valueParameterEditor; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/StateFilterSelectionWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/StateFilterSelectionWindow.cpp index b7abf10da0..846dd45c07 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/StateFilterSelectionWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/StateFilterSelectionWindow.cpp @@ -33,16 +33,16 @@ namespace EMStudio setLayout(mainLayout); mainLayout->setAlignment(Qt::AlignTop); - mTableWidget = new QTableWidget(); - mTableWidget->setAlternatingRowColors(true); - mTableWidget->setSelectionBehavior(QAbstractItemView::SelectRows); - mTableWidget->setSelectionMode(QAbstractItemView::ExtendedSelection); - mTableWidget->horizontalHeader()->setStretchLastSection(true); - mTableWidget->setCornerButtonEnabled(false); - mTableWidget->setContextMenuPolicy(Qt::DefaultContextMenu); - connect(mTableWidget, &QTableWidget::itemSelectionChanged, this, &StateFilterSelectionWindow::OnSelectionChanged); + m_tableWidget = new QTableWidget(); + m_tableWidget->setAlternatingRowColors(true); + m_tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows); + m_tableWidget->setSelectionMode(QAbstractItemView::ExtendedSelection); + m_tableWidget->horizontalHeader()->setStretchLastSection(true); + m_tableWidget->setCornerButtonEnabled(false); + m_tableWidget->setContextMenuPolicy(Qt::DefaultContextMenu); + connect(m_tableWidget, &QTableWidget::itemSelectionChanged, this, &StateFilterSelectionWindow::OnSelectionChanged); - mainLayout->addWidget(mTableWidget); + mainLayout->addWidget(m_tableWidget); QHBoxLayout* buttonLayout = new QHBoxLayout(); mainLayout->addLayout(buttonLayout); @@ -69,25 +69,25 @@ namespace EMStudio void StateFilterSelectionWindow::ReInit(EMotionFX::AnimGraphStateMachine* stateMachine, const AZStd::vector& oldNodeSelection, const AZStd::vector& oldGroupSelection) { m_stateMachine = stateMachine; - mSelectedGroupNames = oldGroupSelection; + m_selectedGroupNames = oldGroupSelection; m_selectedNodeIds = oldNodeSelection; // clear the table widget - mWidgetTable.clear(); - mTableWidget->clear(); - mTableWidget->setColumnCount(2); + m_widgetTable.clear(); + m_tableWidget->clear(); + m_tableWidget->setColumnCount(2); // set header items for the table QTableWidgetItem* headerItem = new QTableWidgetItem("Name"); headerItem->setTextAlignment(Qt::AlignVCenter | Qt::AlignLeft); - mTableWidget->setHorizontalHeaderItem(0, headerItem); + m_tableWidget->setHorizontalHeaderItem(0, headerItem); headerItem = new QTableWidgetItem("Type"); headerItem->setTextAlignment(Qt::AlignVCenter | Qt::AlignLeft); - mTableWidget->setHorizontalHeaderItem(1, headerItem); + m_tableWidget->setHorizontalHeaderItem(1, headerItem); - mTableWidget->resizeColumnsToContents(); - QHeaderView* horizontalHeader = mTableWidget->horizontalHeader(); + m_tableWidget->resizeColumnsToContents(); + QHeaderView* horizontalHeader = m_tableWidget->horizontalHeader(); horizontalHeader->setStretchLastSection(true); if (!m_stateMachine) @@ -101,12 +101,12 @@ namespace EMStudio const size_t numNodeGroups = animGraph->GetNumNodeGroups(); const size_t numNodes = m_stateMachine->GetNumChildNodes(); const int numRows = aznumeric_caster(numNodeGroups + numNodes); - mTableWidget->setRowCount(numRows); + m_tableWidget->setRowCount(numRows); // Block signals for the table widget to not reach OnSelectionChanged() when adding rows as that // clears m_selectedNodeIds and thus breaks the 'is node selected' check in the following loop. { - QSignalBlocker signalBlocker(mTableWidget); + QSignalBlocker signalBlocker(m_tableWidget); // iterate the nodes and add them all uint32 currentRowIndex = 0; @@ -161,9 +161,9 @@ namespace EMStudio } // resize to contents and adjust header - QHeaderView* verticalHeader = mTableWidget->verticalHeader(); + QHeaderView* verticalHeader = m_tableWidget->verticalHeader(); verticalHeader->setVisible(false); - mTableWidget->resizeColumnsToContents(); + m_tableWidget->resizeColumnsToContents(); horizontalHeader->setStretchLastSection(true); } @@ -185,10 +185,10 @@ namespace EMStudio nameItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); // add the name item in the table - mTableWidget->setItem(rowIndex, 0, nameItem); + m_tableWidget->setItem(rowIndex, 0, nameItem); // add a lookup - mWidgetTable.emplace_back(WidgetLookup(nameItem, name, isGroup)); + m_widgetTable.emplace_back(WidgetLookup(nameItem, name, isGroup)); // create the type item QTableWidgetItem* typeItem = nullptr; @@ -205,10 +205,10 @@ namespace EMStudio typeItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); // add the type item in the table - mTableWidget->setItem(rowIndex, 1, typeItem); + m_tableWidget->setItem(rowIndex, 1, typeItem); // add a lookup - mWidgetTable.emplace_back(WidgetLookup(typeItem, name, isGroup)); + m_widgetTable.emplace_back(WidgetLookup(typeItem, name, isGroup)); // set backgroundcolor of the row if (isGroup) @@ -227,7 +227,7 @@ namespace EMStudio } // set the row height - mTableWidget->setRowHeight(rowIndex, 21); + m_tableWidget->setRowHeight(rowIndex, 21); } @@ -242,12 +242,12 @@ namespace EMStudio const EMotionFX::AnimGraph* animGraph = m_stateMachine->GetAnimGraph(); // for all table entries - const size_t numWidgets = mWidgetTable.size(); + const size_t numWidgets = m_widgetTable.size(); for (size_t i = 0; i < numWidgets; ++i) { - if (mWidgetTable[i].mIsGroup && mWidgetTable[i].mWidget == widget) + if (m_widgetTable[i].m_isGroup && m_widgetTable[i].m_widget == widget) { - return animGraph->FindNodeGroupByName(mWidgetTable[i].mName.c_str()); + return animGraph->FindNodeGroupByName(m_widgetTable[i].m_name.c_str()); } } @@ -267,12 +267,12 @@ namespace EMStudio const EMotionFX::AnimGraph* animGraph = m_stateMachine->GetAnimGraph(); // for all table entries - const size_t numWidgets = mWidgetTable.size(); + const size_t numWidgets = m_widgetTable.size(); for (size_t i = 0; i < numWidgets; ++i) { - if (mWidgetTable[i].mIsGroup == false && mWidgetTable[i].mWidget == widget) + if (m_widgetTable[i].m_isGroup == false && m_widgetTable[i].m_widget == widget) { - return animGraph->RecursiveFindNodeByName(mWidgetTable[i].mName.c_str()); + return animGraph->RecursiveFindNodeByName(m_widgetTable[i].m_name.c_str()); } } @@ -285,11 +285,11 @@ namespace EMStudio void StateFilterSelectionWindow::OnSelectionChanged() { // reset the selection arrays - mSelectedGroupNames.clear(); + m_selectedGroupNames.clear(); m_selectedNodeIds.clear(); // get the selected items and the number of them - QList selectedItems = mTableWidget->selectedItems(); + QList selectedItems = m_tableWidget->selectedItems(); const int numSelectedItems = selectedItems.count(); // iterate through the selected items @@ -311,9 +311,9 @@ namespace EMStudio if (nodeGroup) { // add the node group name in case it is not in yet - if (AZStd::find(mSelectedGroupNames.begin(), mSelectedGroupNames.end(), nodeGroup->GetName()) == mSelectedGroupNames.end()) + if (AZStd::find(m_selectedGroupNames.begin(), m_selectedGroupNames.end(), nodeGroup->GetName()) == m_selectedGroupNames.end()) { - mSelectedGroupNames.emplace_back(nodeGroup->GetName()); + m_selectedGroupNames.emplace_back(nodeGroup->GetName()); } } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/StateFilterSelectionWindow.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/StateFilterSelectionWindow.h index 0ebf063703..1789ff77cb 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/StateFilterSelectionWindow.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/StateFilterSelectionWindow.h @@ -38,7 +38,7 @@ namespace EMStudio void ReInit(EMotionFX::AnimGraphStateMachine* stateMachine, const AZStd::vector& oldNodeSelection, const AZStd::vector& oldGroupSelection); const AZStd::vector GetSelectedNodeIds() const { return m_selectedNodeIds; } - const AZStd::vector& GetSelectedGroupNames() const { return mSelectedGroupNames; } + const AZStd::vector& GetSelectedGroupNames() const { return m_selectedGroupNames; } protected slots: void OnSelectionChanged(); @@ -47,15 +47,15 @@ namespace EMStudio struct WidgetLookup { MCORE_MEMORYOBJECTCATEGORY(StateFilterSelectionWindow::WidgetLookup, EMFX_DEFAULT_ALIGNMENT, MEMCATEGORY_STANDARDPLUGINS_ANIMGRAPH); - QTableWidgetItem* mWidget; - AZStd::string mName; - bool mIsGroup; + QTableWidgetItem* m_widget; + AZStd::string m_name; + bool m_isGroup; WidgetLookup(QTableWidgetItem* widget, const char* name, bool isGroup) { - mWidget = widget; - mName = name; - mIsGroup = isGroup; + m_widget = widget; + m_name = name; + m_isGroup = isGroup; } }; @@ -63,10 +63,10 @@ namespace EMStudio EMotionFX::AnimGraphNode* FindNodeByWidget(QTableWidgetItem* widget) const; void AddRow(uint32 rowIndex, const char* name, bool isGroup, bool isSelected, const QColor& color = QColor(255, 255, 255)); - AZStd::vector mWidgetTable; - AZStd::vector mSelectedGroupNames; + AZStd::vector m_widgetTable; + AZStd::vector m_selectedGroupNames; AZStd::vector m_selectedNodeIds; - QTableWidget* mTableWidget; + QTableWidget* m_tableWidget; EMotionFX::AnimGraphStateMachine* m_stateMachine; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/StateGraphNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/StateGraphNode.cpp index 0ce567c366..319f2c5b4f 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/StateGraphNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/StateGraphNode.cpp @@ -28,8 +28,8 @@ namespace EMStudio StateConnection::StateConnection(NodeGraph* parentGraph, const QModelIndex& modelIndex, GraphNode* sourceNode, GraphNode* targetNode, bool isWildcardConnection) : NodeConnection(parentGraph, modelIndex, targetNode, 0, sourceNode, 0) { - mColor = StateMachineColors::s_transitionColor; - mIsWildcardConnection = isWildcardConnection; + m_color = StateMachineColors::s_transitionColor; + m_isWildcardConnection = isWildcardConnection; } @@ -49,7 +49,7 @@ namespace EMStudio CalcStartAndEndPoints(start, end); // Adjust the start and end points in case this is a wildcard transition. - if (mIsWildcardConnection) + if (m_isWildcardConnection) { start = end - QPoint(WILDCARDTRANSITION_SIZE, WILDCARDTRANSITION_SIZE); end += QPoint(3, 3); @@ -130,7 +130,7 @@ namespace EMStudio } } - QColor color = mColor; + QColor color = m_color; if (GetIsSelected()) { @@ -140,26 +140,26 @@ namespace EMStudio { color = StateMachineColors::s_interruptionCandidateColor; } - else if (mIsSynced) + else if (m_isSynced) { color.setRgb(115, 125, 200); } // darken the color in case the transition is disabled - if (mIsDisabled) + if (m_isDisabled) { color = color.darker(165); } // lighten the color in case the transition is highlighted - if (mIsHighlighted) + if (m_isHighlighted) { color = color.lighter(150); painter.setOpacity(1.0); } // lighten the color in case the transition is connected to the currently selected node - if (mIsConnectedHighlighted) + if (m_isConnectedHighlighted) { pen->setWidth(2); color = color.lighter(150); @@ -186,12 +186,12 @@ namespace EMStudio RenderTransition(painter, *brush, *pen, start, end, color, activeColor, - isSelected, /*isDashed=*/mIsDisabled, + isSelected, /*isDashed=*/m_isDisabled, showBlendState, blendWeight, - /*highlightHead=*/mIsHeadHighlighted && mIsWildcardConnection == false, + /*highlightHead=*/m_isHeadHighlighted && m_isWildcardConnection == false, /*gradientActiveIndicator=*/!gotInterrupted); - if (mIsHeadHighlighted) + if (m_isHeadHighlighted) { brush->setColor(color); painter.setBrush(*brush); @@ -251,7 +251,7 @@ namespace EMStudio } // darken the color in case the transition is disabled - if (mIsDisabled) + if (m_isDisabled) { conditionColor = conditionColor.darker(185); } @@ -268,7 +268,7 @@ namespace EMStudio QColor actionColor = Qt::yellow; // darken the color in case the transition is disabled - if (mIsDisabled) + if (m_isDisabled) { actionColor = actionColor.darker(185); } @@ -299,7 +299,7 @@ namespace EMStudio CalcStartAndEndPoints(start, end); // check if we are dealing with a wildcard transition - if (mIsWildcardConnection) + if (m_isWildcardConnection) { start = end - QPoint(WILDCARDTRANSITION_SIZE, WILDCARDTRANSITION_SIZE); end += QPoint(3, 3); @@ -394,10 +394,10 @@ namespace EMStudio const QPoint endOffset = QPoint(transition->GetVisualEndOffsetX(), transition->GetVisualEndOffsetY()); QPoint start = startOffset; - QPoint end = mTargetNode->GetRect().topLeft() + endOffset; - if (mSourceNode) + QPoint end = m_targetNode->GetRect().topLeft() + endOffset; + if (m_sourceNode) { - start += mSourceNode->GetRect().topLeft(); + start += m_sourceNode->GetRect().topLeft(); } else { @@ -405,12 +405,12 @@ namespace EMStudio } QRect sourceRect; - if (mSourceNode) + if (m_sourceNode) { - sourceRect = mSourceNode->GetRect(); + sourceRect = m_sourceNode->GetRect(); } - QRect targetRect = mTargetNode->GetRect(); + QRect targetRect = m_targetNode->GetRect(); targetRect.adjust(-2, -2, 2, 2); // calc the real start point @@ -647,10 +647,8 @@ namespace EMStudio ResetBorderColor(); SetCreateConFromOutputOnly(true); - // mTextOptions.setAlignment( Qt::AlignCenter ); - - mInputPorts.resize(1); - mOutputPorts.resize(4); + m_inputPorts.resize(1); + m_outputPorts.resize(4); } StateGraphNode::~StateGraphNode() @@ -661,16 +659,16 @@ namespace EMStudio { AnimGraphVisualNode::Sync(); - EMotionFX::AnimGraphStateMachine* parentStateMachine = static_cast(mEMFXNode->GetParentNode()); - if (parentStateMachine->GetEntryState() == mEMFXNode) + EMotionFX::AnimGraphStateMachine* parentStateMachine = static_cast(m_emfxNode->GetParentNode()); + if (parentStateMachine->GetEntryState() == m_emfxNode) { - mParentGraph->SetEntryNode(this); + m_parentGraph->SetEntryNode(this); } } void StateGraphNode::Render(QPainter& painter, QPen* pen, bool renderShadow) { - if (!mIsVisible) + if (!m_isVisible) { return; } @@ -684,13 +682,13 @@ namespace EMStudio bool isActive = false; bool gotInterrupted = false; - if (animGraphInstance && mEMFXNode && animGraphInstance->GetAnimGraph() == mEMFXNode->GetAnimGraph()) + if (animGraphInstance && m_emfxNode && animGraphInstance->GetAnimGraph() == m_emfxNode->GetAnimGraph()) { - AZ_Assert(azrtti_typeid(mEMFXNode->GetParentNode()) == azrtti_typeid(), "Expected a valid state machine."); - const EMotionFX::AnimGraphStateMachine* stateMachine = static_cast(mEMFXNode->GetParentNode()); + AZ_Assert(azrtti_typeid(m_emfxNode->GetParentNode()) == azrtti_typeid(), "Expected a valid state machine."); + const EMotionFX::AnimGraphStateMachine* stateMachine = static_cast(m_emfxNode->GetParentNode()); const AZStd::vector& activeStates = stateMachine->GetActiveStates(animGraphInstance); - if (AZStd::find(activeStates.begin(), activeStates.end(), mEMFXNode) != activeStates.end()) + if (AZStd::find(activeStates.begin(), activeStates.end(), m_emfxNode) != activeStates.end()) { isActive = true; @@ -698,7 +696,7 @@ namespace EMStudio const EMotionFX::AnimGraphStateTransition* latestActiveTransition = stateMachine->GetLatestActiveTransition(animGraphInstance); for (const EMotionFX::AnimGraphStateTransition* activeTransition : activeTransitions) { - if (activeTransition != latestActiveTransition && activeTransition->GetTargetNode() == mEMFXNode) + if (activeTransition != latestActiveTransition && activeTransition->GetTargetNode() == m_emfxNode) { gotInterrupted = true; break; @@ -707,14 +705,14 @@ namespace EMStudio } } - mBorderColor.setRgb(0, 0, 0); + m_borderColor.setRgb(0, 0, 0); if (isActive) { - mBorderColor = StateMachineColors::s_activeColor; + m_borderColor = StateMachineColors::s_activeColor; } if (gotInterrupted) { - mBorderColor = StateMachineColors::s_interruptedColor; + m_borderColor = StateMachineColors::s_interruptedColor; } QColor borderColor; @@ -727,7 +725,7 @@ namespace EMStudio } else { - borderColor = mBorderColor; + borderColor = m_borderColor; } // background color @@ -738,16 +736,16 @@ namespace EMStudio } else { - bgColor = mBaseColor; + bgColor = m_baseColor; } // blinking red error color const bool hasError = GetHasError(); if (hasError && !isSelected) { - if (mParentGraph->GetUseAnimation()) + if (m_parentGraph->GetUseAnimation()) { - borderColor = mParentGraph->GetErrorBlinkColor(); + borderColor = m_parentGraph->GetErrorBlinkColor(); } else { @@ -761,18 +759,15 @@ namespace EMStudio QColor textColor = isSelected ? Qt::black : Qt::white; // is highlighted/hovered (on-mouse-over effect) - if (mIsHighlighted) + if (m_isHighlighted) { bgColor = bgColor.lighter(120); bgColor2 = bgColor2.lighter(120); } // draw the main rect - // check if we need to color all nodes or not - //const bool colorAllNodes = GetAlwaysColor(); - //if (mIsProcessed || colorAllNodes || mIsSelected==true) { - QLinearGradient bgGradient(0, mRect.top(), 0, mRect.bottom()); + QLinearGradient bgGradient(0, m_rect.top(), 0, m_rect.bottom()); bgGradient.setColorAt(0.0f, bgColor); bgGradient.setColorAt(1.0f, bgColor2); painter.setBrush(bgGradient); @@ -780,19 +775,19 @@ namespace EMStudio } // add 4px to have empty space for the visualize button - painter.drawRoundedRect(mRect, BORDER_RADIUS, BORDER_RADIUS); + painter.drawRoundedRect(m_rect, BORDER_RADIUS, BORDER_RADIUS); // if the scale is so small that we can still see the small things - if (mParentGraph->GetScale() > 0.3f) + if (m_parentGraph->GetScale() > 0.3f) { // draw the visualize area - if (mCanVisualize) + if (m_canVisualize) { RenderVisualizeRect(painter, bgColor, bgColor2); } // render the tracks etc - if (mEMFXNode->GetHasOutputPose() && mIsProcessed) + if (m_emfxNode->GetHasOutputPose() && m_isProcessed) { RenderTracks(painter, bgColor, bgColor2, 3); } @@ -804,14 +799,12 @@ namespace EMStudio painter.setClipping(false); // render the text overlay with the pre-baked node name and port names etc. - const float textOpacity = MCore::Clamp(mParentGraph->GetScale() * mParentGraph->GetScale() * 1.5f, 0.0f, 1.0f); + const float textOpacity = MCore::Clamp(m_parentGraph->GetScale() * m_parentGraph->GetScale() * 1.5f, 0.0f, 1.0f); painter.setOpacity(textOpacity); - painter.setFont(mHeaderFont); + painter.setFont(m_headerFont); painter.setBrush(Qt::NoBrush); painter.setPen(textColor); - //painter.drawStaticText(mRect.left(), mRect.center().y()-6, mTitleText); - painter.drawStaticText(mRect.left(), aznumeric_cast(mRect.center().y() - mTitleText.size().height() / 2), mTitleText); - // painter.drawPixmap( mRect, mTextPixmap ); + painter.drawStaticText(m_rect.left(), aznumeric_cast(m_rect.center().y() - m_titleText.size().height() / 2), m_titleText); painter.setOpacity(1.0f); RenderDebugInfo(painter); @@ -824,7 +817,7 @@ namespace EMStudio int32 StateGraphNode::CalcRequiredWidth() { - const uint32 headerWidth = mHeaderFontMetrics->horizontalAdvance(mElidedName) + 40; + const uint32 headerWidth = m_headerFontMetrics->horizontalAdvance(m_elidedName) + 40; // make sure the node is at least 100 units in width return MCore::Max(headerWidth, 100); @@ -833,7 +826,7 @@ namespace EMStudio QRect StateGraphNode::CalcInputPortRect(AZ::u16 portNr) { MCORE_UNUSED(portNr); - return mRect.adjusted(10, 10, -10, -10); + return m_rect.adjusted(10, 10, -10, -10); } QRect StateGraphNode::CalcOutputPortRect(AZ::u16 portNr) @@ -841,16 +834,16 @@ namespace EMStudio switch (portNr) { case 0: - return QRect(mRect.left(), mRect.top(), mRect.width(), 8); + return QRect(m_rect.left(), m_rect.top(), m_rect.width(), 8); break; // top case 1: - return QRect(mRect.left(), mRect.bottom() - 8, mRect.width(), 9); + return QRect(m_rect.left(), m_rect.bottom() - 8, m_rect.width(), 9); break; // bottom case 2: - return QRect(mRect.left(), mRect.top(), 8, mRect.height()); + return QRect(m_rect.left(), m_rect.top(), 8, m_rect.height()); break; // left case 3: - return QRect(mRect.right() - 8, mRect.top(), 9, mRect.height()); + return QRect(m_rect.right() - 8, m_rect.top(), 9, m_rect.height()); break; // right default: MCORE_ASSERT(false); @@ -864,7 +857,7 @@ namespace EMStudio MCORE_UNUSED(bgColor2); QColor vizBorder; - if (mVisualize) + if (m_visualize) { vizBorder = Qt::black; } @@ -873,26 +866,26 @@ namespace EMStudio vizBorder = bgColor.darker(225); } - painter.setPen(mVisualizeHighlighted ? StateMachineColors::s_selectedColor : vizBorder); + painter.setPen(m_visualizeHighlighted ? StateMachineColors::s_selectedColor : vizBorder); if (!GetIsSelected()) { - painter.setBrush(mVisualize ? mVisualizeColor : bgColor); + painter.setBrush(m_visualize ? m_visualizeColor : bgColor); } else { - painter.setBrush(mVisualize ? StateMachineColors::s_selectedColor : bgColor); + painter.setBrush(m_visualize ? StateMachineColors::s_selectedColor : bgColor); } - painter.drawRect(mVisualizeRect); + painter.drawRect(m_visualizeRect); } void StateGraphNode::UpdateTextPixmap() { - mTitleText.setTextOption(mTextOptionsCenter); - mTitleText.setTextFormat(Qt::PlainText); - mTitleText.setPerformanceHint(QStaticText::AggressiveCaching); - mTitleText.setTextWidth(mRect.width()); - mTitleText.setText(mElidedName); - mTitleText.prepare(QTransform(), mHeaderFont); + m_titleText.setTextOption(m_textOptionsCenter); + m_titleText.setTextFormat(Qt::PlainText); + m_titleText.setPerformanceHint(QStaticText::AggressiveCaching); + m_titleText.setTextWidth(m_rect.width()); + m_titleText.setText(m_elidedName); + m_titleText.prepare(QTransform(), m_headerFont); } } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/StateGraphNode.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/StateGraphNode.h index cee57b4a4f..6a7549e876 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/StateGraphNode.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/StateGraphNode.h @@ -58,7 +58,7 @@ namespace EMStudio EMotionFX::AnimGraphTransitionCondition* FindCondition(const QPoint& mousePos); - bool GetIsWildcardTransition() const override { return mIsWildcardConnection; } + bool GetIsWildcardTransition() const override { return m_isWildcardConnection; } static void RenderTransition(QPainter& painter, QBrush& brush, QPen& pen, QPoint start, QPoint end, @@ -70,7 +70,7 @@ namespace EMStudio private: void RenderConditionsAndActions(EMotionFX::AnimGraphInstance* animGraphInstance, QPainter* painter, QPen* pen, QBrush* brush, QPoint& start, QPoint& end); - bool mIsWildcardConnection; + bool m_isWildcardConnection; }; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentNodesWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentNodesWindow.cpp index 78eab3d362..be1feb93fc 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentNodesWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentNodesWindow.cpp @@ -32,9 +32,9 @@ namespace EMStudio AttachmentNodesWindow::AttachmentNodesWindow(QWidget* parent) : QWidget(parent) { - mNodeTable = nullptr; - mSelectNodesButton = nullptr; - mNodeAction = ""; + m_nodeTable = nullptr; + m_selectNodesButton = nullptr; + m_nodeAction = ""; // init the widget Init(); @@ -51,49 +51,49 @@ namespace EMStudio void AttachmentNodesWindow::Init() { // create the node groups table - mNodeTable = new QTableWidget(0, 1, 0); + m_nodeTable = new QTableWidget(0, 1, 0); // create the table widget - mNodeTable->setMinimumHeight(125); - mNodeTable->setAlternatingRowColors(true); - mNodeTable->setCornerButtonEnabled(false); - mNodeTable->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); - mNodeTable->setContextMenuPolicy(Qt::DefaultContextMenu); + m_nodeTable->setMinimumHeight(125); + m_nodeTable->setAlternatingRowColors(true); + m_nodeTable->setCornerButtonEnabled(false); + m_nodeTable->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); + m_nodeTable->setContextMenuPolicy(Qt::DefaultContextMenu); // set the table to row selection - mNodeTable->setSelectionBehavior(QAbstractItemView::SelectRows); + m_nodeTable->setSelectionBehavior(QAbstractItemView::SelectRows); // make the table items read only - mNodeTable->setEditTriggers(QAbstractItemView::NoEditTriggers); + m_nodeTable->setEditTriggers(QAbstractItemView::NoEditTriggers); // set header items for the table QTableWidgetItem* nameHeaderItem = new QTableWidgetItem("Nodes"); nameHeaderItem->setTextAlignment(Qt::AlignVCenter | Qt::AlignLeft); - mNodeTable->setHorizontalHeaderItem(0, nameHeaderItem); + m_nodeTable->setHorizontalHeaderItem(0, nameHeaderItem); - QHeaderView* horizontalHeader = mNodeTable->horizontalHeader(); + QHeaderView* horizontalHeader = m_nodeTable->horizontalHeader(); horizontalHeader->setStretchLastSection(true); // create the node selection window - mNodeSelectionWindow = new NodeSelectionWindow(this, false); + m_nodeSelectionWindow = new NodeSelectionWindow(this, false); // create the selection buttons - mSelectNodesButton = new QToolButton(); - mAddNodesButton = new QToolButton(); - mRemoveNodesButton = new QToolButton(); + m_selectNodesButton = new QToolButton(); + m_addNodesButton = new QToolButton(); + m_removeNodesButton = new QToolButton(); - EMStudioManager::MakeTransparentButton(mSelectNodesButton, "Images/Icons/Plus.svg", "Select nodes and replace the current selection"); - EMStudioManager::MakeTransparentButton(mAddNodesButton, "Images/Icons/Plus.svg", "Select nodes and add them to the current selection"); - EMStudioManager::MakeTransparentButton(mRemoveNodesButton, "Images/Icons/Minus.svg", "Remove selected nodes from the list"); + EMStudioManager::MakeTransparentButton(m_selectNodesButton, "Images/Icons/Plus.svg", "Select nodes and replace the current selection"); + EMStudioManager::MakeTransparentButton(m_addNodesButton, "Images/Icons/Plus.svg", "Select nodes and add them to the current selection"); + EMStudioManager::MakeTransparentButton(m_removeNodesButton, "Images/Icons/Minus.svg", "Remove selected nodes from the list"); // create the buttons layout QHBoxLayout* buttonLayout = new QHBoxLayout(); buttonLayout->setSpacing(0); buttonLayout->setAlignment(Qt::AlignLeft); - buttonLayout->addWidget(mSelectNodesButton); - buttonLayout->addWidget(mAddNodesButton); - buttonLayout->addWidget(mRemoveNodesButton); + buttonLayout->addWidget(m_selectNodesButton); + buttonLayout->addWidget(m_addNodesButton); + buttonLayout->addWidget(m_removeNodesButton); // create the layouts QVBoxLayout* layout = new QVBoxLayout(); @@ -101,18 +101,18 @@ namespace EMStudio layout->setSpacing(2); layout->addLayout(buttonLayout); - layout->addWidget(mNodeTable); + layout->addWidget(m_nodeTable); // set the main layout setLayout(layout); // connect controls to the slots - connect(mSelectNodesButton, &QToolButton::clicked, this, &AttachmentNodesWindow::SelectNodesButtonPressed); - connect(mAddNodesButton, &QToolButton::clicked, this, &AttachmentNodesWindow::SelectNodesButtonPressed); - connect(mRemoveNodesButton, &QToolButton::clicked, this, &AttachmentNodesWindow::RemoveNodesButtonPressed); - connect(mNodeTable, &QTableWidget::itemSelectionChanged, this, &AttachmentNodesWindow::OnItemSelectionChanged); - connect(mNodeSelectionWindow->GetNodeHierarchyWidget(), &NodeHierarchyWidget::OnSelectionDone, this, &AttachmentNodesWindow::NodeSelectionFinished); - connect(mNodeSelectionWindow->GetNodeHierarchyWidget(), &NodeHierarchyWidget::OnDoubleClicked, this, &AttachmentNodesWindow::NodeSelectionFinished); + connect(m_selectNodesButton, &QToolButton::clicked, this, &AttachmentNodesWindow::SelectNodesButtonPressed); + connect(m_addNodesButton, &QToolButton::clicked, this, &AttachmentNodesWindow::SelectNodesButtonPressed); + connect(m_removeNodesButton, &QToolButton::clicked, this, &AttachmentNodesWindow::RemoveNodesButtonPressed); + connect(m_nodeTable, &QTableWidget::itemSelectionChanged, this, &AttachmentNodesWindow::OnItemSelectionChanged); + connect(m_nodeSelectionWindow->GetNodeHierarchyWidget(), &NodeHierarchyWidget::OnSelectionDone, this, &AttachmentNodesWindow::NodeSelectionFinished); + connect(m_nodeSelectionWindow->GetNodeHierarchyWidget(), &NodeHierarchyWidget::OnDoubleClicked, this, &AttachmentNodesWindow::NodeSelectionFinished); } @@ -120,13 +120,13 @@ namespace EMStudio void AttachmentNodesWindow::UpdateInterface() { // clear the table widget - mNodeTable->clear(); + m_nodeTable->clear(); // check if the current actor exists - if (mActor == nullptr) + if (m_actor == nullptr) { // set the column count - mNodeTable->setColumnCount(0); + m_nodeTable->setColumnCount(0); // disable the widgets SetWidgetDisabled(true); @@ -136,23 +136,23 @@ namespace EMStudio } // set the column count - mNodeTable->setColumnCount(1); + m_nodeTable->setColumnCount(1); // enable the widget SetWidgetDisabled(false); // set the remove nodes button enabled or not based on selection - mRemoveNodesButton->setEnabled((mNodeTable->rowCount() != 0) && (mNodeTable->selectedItems().size() != 0)); + m_removeNodesButton->setEnabled((m_nodeTable->rowCount() != 0) && (m_nodeTable->selectedItems().size() != 0)); // counter for attachment nodes int numAttachmentNodes = 0; // set the row count - const int numNodes = aznumeric_caster(mActor->GetNumNodes()); + const int numNodes = aznumeric_caster(m_actor->GetNumNodes()); for (int i = 0; i < numNodes; ++i) { // get the nodegroup - EMotionFX::Node* node = mActor->GetSkeleton()->GetNode(i); + EMotionFX::Node* node = m_actor->GetSkeleton()->GetNode(i); if (node->GetIsAttachmentNode()) { numAttachmentNodes++; @@ -160,19 +160,19 @@ namespace EMStudio } // set the row count - mNodeTable->setRowCount(numAttachmentNodes); + m_nodeTable->setRowCount(numAttachmentNodes); // set header items for the table - QTableWidgetItem* nameHeaderItem = new QTableWidgetItem(AZStd::string::format("Attachment Nodes (%d / %zu)", numAttachmentNodes, mActor->GetNumNodes()).c_str()); + QTableWidgetItem* nameHeaderItem = new QTableWidgetItem(AZStd::string::format("Attachment Nodes (%d / %zu)", numAttachmentNodes, m_actor->GetNumNodes()).c_str()); nameHeaderItem->setTextAlignment(Qt::AlignVCenter | Qt::AlignCenter); - mNodeTable->setHorizontalHeaderItem(0, nameHeaderItem); + m_nodeTable->setHorizontalHeaderItem(0, nameHeaderItem); // fill the table with content uint16 currentRow = 0; for (uint16 i = 0; i < numNodes; ++i) { // get the nodegroup - EMotionFX::Node* node = mActor->GetSkeleton()->GetNode(i); + EMotionFX::Node* node = m_actor->GetSkeleton()->GetNode(i); // continue if node does not exist if (node == nullptr || node->GetIsAttachmentNode() == false) @@ -182,24 +182,24 @@ namespace EMStudio // create table items QTableWidgetItem* tableItemNodeName = new QTableWidgetItem(node->GetName()); - mNodeTable->setItem(currentRow, 0, tableItemNodeName); + m_nodeTable->setItem(currentRow, 0, tableItemNodeName); // set the row height and increase row counter - mNodeTable->setRowHeight(currentRow, 21); + m_nodeTable->setRowHeight(currentRow, 21); ++currentRow; } // resize to contents and adjust header - QHeaderView* verticalHeader = mNodeTable->verticalHeader(); + QHeaderView* verticalHeader = m_nodeTable->verticalHeader(); verticalHeader->setVisible(false); - mNodeTable->resizeColumnsToContents(); - mNodeTable->horizontalHeader()->setStretchLastSection(true); + m_nodeTable->resizeColumnsToContents(); + m_nodeTable->horizontalHeader()->setStretchLastSection(true); // set table size - mNodeTable->setColumnWidth(0, 37); - mNodeTable->setColumnWidth(3, 0); - mNodeTable->setColumnHidden(3, true); - mNodeTable->sortItems(3); + m_nodeTable->setColumnWidth(0, 37); + m_nodeTable->setColumnWidth(3, 0); + m_nodeTable->setColumnHidden(3, true); + m_nodeTable->sortItems(3); // toggle enabled state of the remove button OnItemSelectionChanged(); @@ -210,7 +210,7 @@ namespace EMStudio void AttachmentNodesWindow::SetActor(EMotionFX::Actor* actor) { // set the new actor - mActor = actor; + m_actor = actor; // update the interface UpdateInterface(); @@ -221,20 +221,20 @@ namespace EMStudio void AttachmentNodesWindow::SelectNodesButtonPressed() { // check if actor is set - if (mActor == nullptr) + if (m_actor == nullptr) { return; } // set the action for the selected nodes QWidget* senderWidget = (QWidget*)sender(); - if (senderWidget == mAddNodesButton) + if (senderWidget == m_addNodesButton) { - mNodeAction = "add"; + m_nodeAction = "add"; } else { - mNodeAction = "select"; + m_nodeAction = "select"; } // get the selected actorinstance @@ -248,23 +248,23 @@ namespace EMStudio } // create selection list for the current nodes within the group - mNodeSelectionList.Clear(); - if (senderWidget == mSelectNodesButton) + m_nodeSelectionList.Clear(); + if (senderWidget == m_selectNodesButton) { - const size_t numNodes = mActor->GetNumNodes(); + const size_t numNodes = m_actor->GetNumNodes(); for (size_t i = 0; i < numNodes; ++i) { - EMotionFX::Node* node = mActor->GetSkeleton()->GetNode(i); + EMotionFX::Node* node = m_actor->GetSkeleton()->GetNode(i); if (node->GetIsAttachmentNode()) { - mNodeSelectionList.AddNode(node); + m_nodeSelectionList.AddNode(node); } } } // show the node selection window - mNodeSelectionWindow->Update(actorInstance->GetID(), &mNodeSelectionList); - mNodeSelectionWindow->show(); + m_nodeSelectionWindow->Update(actorInstance->GetID(), &m_nodeSelectionList); + m_nodeSelectionWindow->show(); } @@ -274,11 +274,11 @@ namespace EMStudio // generate node list string AZStd::string nodeList; int lowestSelectedRow = AZStd::numeric_limits::max(); - const int numTableRows = mNodeTable->rowCount(); + const int numTableRows = m_nodeTable->rowCount(); for (int i = 0; i < numTableRows; ++i) { // get the current table item - QTableWidgetItem* item = mNodeTable->item(i, 0); + QTableWidgetItem* item = m_nodeTable->item(i, 0); if (item == nullptr) { continue; @@ -304,20 +304,20 @@ namespace EMStudio // call command for adjusting disable on default flag AZStd::string outResult; AZStd::string command; - command = AZStd::string::format("AdjustActor -actorID %i -nodeAction \"remove\" -attachmentNodes \"%s\"", mActor->GetID(), nodeList.c_str()); + command = AZStd::string::format("AdjustActor -actorID %i -nodeAction \"remove\" -attachmentNodes \"%s\"", m_actor->GetID(), nodeList.c_str()); if (EMStudio::GetCommandManager()->ExecuteCommand(command.c_str(), outResult) == false) { MCore::LogError(outResult.c_str()); } // selected the next row - if (lowestSelectedRow > mNodeTable->rowCount() - 1) + if (lowestSelectedRow > m_nodeTable->rowCount() - 1) { - mNodeTable->selectRow(lowestSelectedRow - 1); + m_nodeTable->selectRow(lowestSelectedRow - 1); } else { - mNodeTable->selectRow(lowestSelectedRow); + m_nodeTable->selectRow(lowestSelectedRow); } } @@ -342,7 +342,7 @@ namespace EMStudio // call command for adjusting disable on default flag AZStd::string outResult; AZStd::string command; - command = AZStd::string::format("AdjustActor -actorID %i -nodeAction \"%s\" -attachmentNodes \"%s\"", mActor->GetID(), mNodeAction.c_str(), nodeList.c_str()); + command = AZStd::string::format("AdjustActor -actorID %i -nodeAction \"%s\" -attachmentNodes \"%s\"", m_actor->GetID(), m_nodeAction.c_str(), nodeList.c_str()); if (EMStudio::GetCommandManager()->ExecuteCommand(command.c_str(), outResult) == false) { MCore::LogError(outResult.c_str()); @@ -353,17 +353,17 @@ namespace EMStudio // enable/disable the dialog void AttachmentNodesWindow::SetWidgetDisabled(bool disabled) { - mNodeTable->setDisabled(disabled); - mSelectNodesButton->setDisabled(disabled); - mAddNodesButton->setDisabled(disabled); - mRemoveNodesButton->setDisabled(disabled); + m_nodeTable->setDisabled(disabled); + m_selectNodesButton->setDisabled(disabled); + m_addNodesButton->setDisabled(disabled); + m_removeNodesButton->setDisabled(disabled); } // handle item selection changes of the node table void AttachmentNodesWindow::OnItemSelectionChanged() { - mRemoveNodesButton->setEnabled((mNodeTable->rowCount() != 0) && (!mNodeTable->selectedItems().empty())); + m_removeNodesButton->setEnabled((m_nodeTable->rowCount() != 0) && (!m_nodeTable->selectedItems().empty())); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentNodesWindow.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentNodesWindow.h index 3a3c3f096e..1743db3ab9 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentNodesWindow.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentNodesWindow.h @@ -66,18 +66,18 @@ namespace EMStudio private: // the current actor - EMotionFX::Actor* mActor; + EMotionFX::Actor* m_actor; // the node selection window and node group - NodeSelectionWindow* mNodeSelectionWindow; - CommandSystem::SelectionList mNodeSelectionList; - AZStd::string mNodeAction; + NodeSelectionWindow* m_nodeSelectionWindow; + CommandSystem::SelectionList m_nodeSelectionList; + AZStd::string m_nodeAction; // widgets - QTableWidget* mNodeTable; - QToolButton* mSelectNodesButton; - QToolButton* mAddNodesButton; - QToolButton* mRemoveNodesButton; + QTableWidget* m_nodeTable; + QToolButton* m_selectNodesButton; + QToolButton* m_addNodesButton; + QToolButton* m_removeNodesButton; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentsHierarchyWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentsHierarchyWindow.cpp index 536ff16f57..5bdb61dea5 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentsHierarchyWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentsHierarchyWindow.cpp @@ -24,7 +24,7 @@ namespace EMStudio AttachmentsHierarchyWindow::AttachmentsHierarchyWindow(QWidget* parent) : QWidget(parent) { - mHierarchy = nullptr; + m_hierarchy = nullptr; } @@ -40,27 +40,27 @@ namespace EMStudio verticalLayout->setMargin(0); setLayout(verticalLayout); - mHierarchy = new QTreeWidget(); - verticalLayout->addWidget(mHierarchy); - mHierarchy->setColumnCount(1); - mHierarchy->setHeaderHidden(true); + m_hierarchy = new QTreeWidget(); + verticalLayout->addWidget(m_hierarchy); + m_hierarchy->setColumnCount(1); + m_hierarchy->setHeaderHidden(true); // set optical stuff for the tree - mHierarchy->setColumnWidth(0, 200); - mHierarchy->setColumnWidth(1, 20); - mHierarchy->setColumnWidth(1, 100); - mHierarchy->setSortingEnabled(false); - mHierarchy->setSelectionMode(QAbstractItemView::NoSelection); - mHierarchy->setMinimumWidth(150); - mHierarchy->setMinimumHeight(125); - mHierarchy->setAlternatingRowColors(true); - mHierarchy->setExpandsOnDoubleClick(true); - mHierarchy->setAnimated(true); + m_hierarchy->setColumnWidth(0, 200); + m_hierarchy->setColumnWidth(1, 20); + m_hierarchy->setColumnWidth(1, 100); + m_hierarchy->setSortingEnabled(false); + m_hierarchy->setSelectionMode(QAbstractItemView::NoSelection); + m_hierarchy->setMinimumWidth(150); + m_hierarchy->setMinimumHeight(125); + m_hierarchy->setAlternatingRowColors(true); + m_hierarchy->setExpandsOnDoubleClick(true); + m_hierarchy->setAnimated(true); // disable the move of section to have column order fixed - mHierarchy->header()->setSectionsMovable(false); + m_hierarchy->header()->setSectionsMovable(false); - verticalLayout->addWidget(mHierarchy); + verticalLayout->addWidget(m_hierarchy); ReInit(); } @@ -69,7 +69,7 @@ namespace EMStudio void AttachmentsHierarchyWindow::ReInit() { // clear the tree - mHierarchy->clear(); + m_hierarchy->clear(); // get the number of actor instances and iterate through them const size_t numActorInstances = EMotionFX::GetActorManager().GetNumActorInstances(); @@ -88,12 +88,12 @@ namespace EMStudio // check if we are dealing with a root actor instance if (attachedTo == nullptr) { - QTreeWidgetItem* item = new QTreeWidgetItem(mHierarchy); + QTreeWidgetItem* item = new QTreeWidgetItem(m_hierarchy); AZStd::string actorFilename; AzFramework::StringFunc::Path::GetFileName(actor->GetFileNameString().c_str(), actorFilename); item->setText(0, QString("%1 (ID:%2)").arg(actorFilename.c_str()).arg(actorInstance->GetID())); item->setExpanded(true); - mHierarchy->addTopLevelItem(item); + m_hierarchy->addTopLevelItem(item); // get the number of attachments and iterate through them const size_t numAttachments = actorInstance->GetNumAttachments(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentsHierarchyWindow.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentsHierarchyWindow.h index 5621cb9bdd..92a55668e8 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentsHierarchyWindow.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentsHierarchyWindow.h @@ -39,7 +39,7 @@ namespace EMStudio private: void RecursivelyAddAttachments(QTreeWidgetItem* parent, EMotionFX::ActorInstance* actorInstance); - QTreeWidget* mHierarchy; + QTreeWidget* m_hierarchy; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentsPlugin.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentsPlugin.cpp index 738879e96e..401945647e 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentsPlugin.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentsPlugin.cpp @@ -20,16 +20,16 @@ namespace EMStudio AttachmentsPlugin::AttachmentsPlugin() : EMStudio::DockWidgetPlugin() { - mDialogStack = nullptr; - mSelectCallback = nullptr; - mUnselectCallback = nullptr; - mClearSelectionCallback = nullptr; - mAddAttachmentCallback = nullptr; - mAddDeformableAttachmentCallback = nullptr; - mRemoveAttachmentCallback = nullptr; - mClearAttachmentsCallback = nullptr; - mAdjustActorCallback = nullptr; - mAttachmentNodesWindow = nullptr; + m_dialogStack = nullptr; + m_selectCallback = nullptr; + m_unselectCallback = nullptr; + m_clearSelectionCallback = nullptr; + m_addAttachmentCallback = nullptr; + m_addDeformableAttachmentCallback = nullptr; + m_removeAttachmentCallback = nullptr; + m_clearAttachmentsCallback = nullptr; + m_adjustActorCallback = nullptr; + m_attachmentNodesWindow = nullptr; } @@ -37,23 +37,23 @@ namespace EMStudio AttachmentsPlugin::~AttachmentsPlugin() { // unregister the command callbacks and get rid of the memory - GetCommandManager()->RemoveCommandCallback(mSelectCallback, false); - GetCommandManager()->RemoveCommandCallback(mUnselectCallback, false); - GetCommandManager()->RemoveCommandCallback(mClearSelectionCallback, false); - GetCommandManager()->RemoveCommandCallback(mAddAttachmentCallback, false); - GetCommandManager()->RemoveCommandCallback(mAddDeformableAttachmentCallback, false); - GetCommandManager()->RemoveCommandCallback(mRemoveAttachmentCallback, false); - GetCommandManager()->RemoveCommandCallback(mClearAttachmentsCallback, false); - GetCommandManager()->RemoveCommandCallback(mAdjustActorCallback, false); + GetCommandManager()->RemoveCommandCallback(m_selectCallback, false); + GetCommandManager()->RemoveCommandCallback(m_unselectCallback, false); + GetCommandManager()->RemoveCommandCallback(m_clearSelectionCallback, false); + GetCommandManager()->RemoveCommandCallback(m_addAttachmentCallback, false); + GetCommandManager()->RemoveCommandCallback(m_addDeformableAttachmentCallback, false); + GetCommandManager()->RemoveCommandCallback(m_removeAttachmentCallback, false); + GetCommandManager()->RemoveCommandCallback(m_clearAttachmentsCallback, false); + GetCommandManager()->RemoveCommandCallback(m_adjustActorCallback, false); - delete mSelectCallback; - delete mUnselectCallback; - delete mClearSelectionCallback; - delete mAddAttachmentCallback; - delete mAddDeformableAttachmentCallback; - delete mRemoveAttachmentCallback; - delete mClearAttachmentsCallback; - delete mAdjustActorCallback; + delete m_selectCallback; + delete m_unselectCallback; + delete m_clearSelectionCallback; + delete m_addAttachmentCallback; + delete m_addDeformableAttachmentCallback; + delete m_removeAttachmentCallback; + delete m_clearAttachmentsCallback; + delete m_adjustActorCallback; } @@ -70,52 +70,52 @@ namespace EMStudio //LogInfo("Initializing attachments window."); // create the dialog stack - assert(mDialogStack == nullptr); - mDialogStack = new MysticQt::DialogStack(mDock); - mDock->setWidget(mDialogStack); + assert(m_dialogStack == nullptr); + m_dialogStack = new MysticQt::DialogStack(m_dock); + m_dock->setWidget(m_dialogStack); // create the attachments window - mAttachmentsWindow = new AttachmentsWindow(mDialogStack); - mAttachmentsWindow->Init(); - mDialogStack->Add(mAttachmentsWindow, "Selected Actor Instance", false, true, true, false); + m_attachmentsWindow = new AttachmentsWindow(m_dialogStack); + m_attachmentsWindow->Init(); + m_dialogStack->Add(m_attachmentsWindow, "Selected Actor Instance", false, true, true, false); // create the attachment hierarchy window - mAttachmentsHierarchyWindow = new AttachmentsHierarchyWindow(mDialogStack); - mAttachmentsHierarchyWindow->Init(); - mDialogStack->Add(mAttachmentsHierarchyWindow, "Hierarchy", false, true, true, false); + m_attachmentsHierarchyWindow = new AttachmentsHierarchyWindow(m_dialogStack); + m_attachmentsHierarchyWindow->Init(); + m_dialogStack->Add(m_attachmentsHierarchyWindow, "Hierarchy", false, true, true, false); // create the attachment nodes window - mAttachmentNodesWindow = new AttachmentNodesWindow(mDialogStack); - mDialogStack->Add(mAttachmentNodesWindow, "Attachment Nodes", false, true); + m_attachmentNodesWindow = new AttachmentNodesWindow(m_dialogStack); + m_dialogStack->Add(m_attachmentNodesWindow, "Attachment Nodes", false, true); // create and register the command callbacks only (only execute this code once for all plugins) - mSelectCallback = new CommandSelectCallback(false); - mUnselectCallback = new CommandUnselectCallback(false); - mClearSelectionCallback = new CommandClearSelectionCallback(false); + m_selectCallback = new CommandSelectCallback(false); + m_unselectCallback = new CommandUnselectCallback(false); + m_clearSelectionCallback = new CommandClearSelectionCallback(false); - mAddAttachmentCallback = new CommandAddAttachmentCallback(false); - mAddDeformableAttachmentCallback = new CommandAddDeformableAttachmentCallback(false); - mRemoveAttachmentCallback = new CommandRemoveAttachmentCallback(false); - mClearAttachmentsCallback = new CommandClearAttachmentsCallback(false); - mAdjustActorCallback = new CommandAdjustActorCallback(false); - mRemoveActorInstanceCallback = new CommandRemoveActorInstanceCallback(false); + m_addAttachmentCallback = new CommandAddAttachmentCallback(false); + m_addDeformableAttachmentCallback = new CommandAddDeformableAttachmentCallback(false); + m_removeAttachmentCallback = new CommandRemoveAttachmentCallback(false); + m_clearAttachmentsCallback = new CommandClearAttachmentsCallback(false); + m_adjustActorCallback = new CommandAdjustActorCallback(false); + m_removeActorInstanceCallback = new CommandRemoveActorInstanceCallback(false); - GetCommandManager()->RegisterCommandCallback("Select", mSelectCallback); - GetCommandManager()->RegisterCommandCallback("Unselect", mUnselectCallback); - GetCommandManager()->RegisterCommandCallback("ClearSelection", mClearSelectionCallback); + GetCommandManager()->RegisterCommandCallback("Select", m_selectCallback); + GetCommandManager()->RegisterCommandCallback("Unselect", m_unselectCallback); + GetCommandManager()->RegisterCommandCallback("ClearSelection", m_clearSelectionCallback); - GetCommandManager()->RegisterCommandCallback("AddAttachment", mAddAttachmentCallback); - GetCommandManager()->RegisterCommandCallback("AddDeformableAttachment", mAddDeformableAttachmentCallback); - GetCommandManager()->RegisterCommandCallback("RemoveAttachment", mRemoveAttachmentCallback); - GetCommandManager()->RegisterCommandCallback("ClearAttachments", mClearAttachmentsCallback); - GetCommandManager()->RegisterCommandCallback("AdjustActor", mAdjustActorCallback); - GetCommandManager()->RegisterCommandCallback("RemoveActorInstance", mRemoveActorInstanceCallback); + GetCommandManager()->RegisterCommandCallback("AddAttachment", m_addAttachmentCallback); + GetCommandManager()->RegisterCommandCallback("AddDeformableAttachment", m_addDeformableAttachmentCallback); + GetCommandManager()->RegisterCommandCallback("RemoveAttachment", m_removeAttachmentCallback); + GetCommandManager()->RegisterCommandCallback("ClearAttachments", m_clearAttachmentsCallback); + GetCommandManager()->RegisterCommandCallback("AdjustActor", m_adjustActorCallback); + GetCommandManager()->RegisterCommandCallback("RemoveActorInstance", m_removeActorInstanceCallback); // reinit the dialog ReInit(); // connect the window activation signal to refresh if reactivated - connect(mDock, &QDockWidget::visibilityChanged, this, &AttachmentsPlugin::WindowReInit); + connect(m_dock, &QDockWidget::visibilityChanged, this, &AttachmentsPlugin::WindowReInit); return true; } @@ -124,8 +124,8 @@ namespace EMStudio // function to reinit the window void AttachmentsPlugin::ReInit() { - mAttachmentsWindow->ReInit(); - mAttachmentsHierarchyWindow->ReInit(); + m_attachmentsWindow->ReInit(); + m_attachmentsHierarchyWindow->ReInit(); // get the current actor const CommandSystem::SelectionList& selection = GetCommandManager()->GetCurrentSelection(); @@ -139,7 +139,7 @@ namespace EMStudio } // set the actor of the attachment nodes window - mAttachmentNodesWindow->SetActor(actor); + m_attachmentNodesWindow->SetActor(actor); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentsPlugin.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentsPlugin.h index 63ce91e187..d59d0d1b93 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentsPlugin.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentsPlugin.h @@ -58,7 +58,7 @@ namespace EMStudio bool Init() override; EMStudioPlugin* Clone() override; void ReInit(); - AttachmentsWindow* GetAttachmentsWindow() const { return mAttachmentsWindow; } + AttachmentsWindow* GetAttachmentsWindow() const { return m_attachmentsWindow; } public slots: void WindowReInit(bool visible); @@ -75,21 +75,21 @@ namespace EMStudio MCORE_DEFINECOMMANDCALLBACK(CommandAdjustActorCallback); MCORE_DEFINECOMMANDCALLBACK(CommandRemoveActorInstanceCallback); - CommandSelectCallback* mSelectCallback; - CommandUnselectCallback* mUnselectCallback; - CommandClearSelectionCallback* mClearSelectionCallback; - CommandAddAttachmentCallback* mAddAttachmentCallback; - CommandAddDeformableAttachmentCallback* mAddDeformableAttachmentCallback; - CommandRemoveAttachmentCallback* mRemoveAttachmentCallback; - CommandClearAttachmentsCallback* mClearAttachmentsCallback; - CommandAdjustActorCallback* mAdjustActorCallback; - CommandRemoveActorInstanceCallback* mRemoveActorInstanceCallback; + CommandSelectCallback* m_selectCallback; + CommandUnselectCallback* m_unselectCallback; + CommandClearSelectionCallback* m_clearSelectionCallback; + CommandAddAttachmentCallback* m_addAttachmentCallback; + CommandAddDeformableAttachmentCallback* m_addDeformableAttachmentCallback; + CommandRemoveAttachmentCallback* m_removeAttachmentCallback; + CommandClearAttachmentsCallback* m_clearAttachmentsCallback; + CommandAdjustActorCallback* m_adjustActorCallback; + CommandRemoveActorInstanceCallback* m_removeActorInstanceCallback; - QWidget* mNoSelectionWidget; - MysticQt::DialogStack* mDialogStack; - AttachmentsWindow* mAttachmentsWindow; - AttachmentsHierarchyWindow* mAttachmentsHierarchyWindow; - AttachmentNodesWindow* mAttachmentNodesWindow; + QWidget* m_noSelectionWidget; + MysticQt::DialogStack* m_dialogStack; + AttachmentsWindow* m_attachmentsWindow; + AttachmentsHierarchyWindow* m_attachmentsHierarchyWindow; + AttachmentNodesWindow* m_attachmentNodesWindow; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentsWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentsWindow.cpp index 4b971f9c32..9d25eeb41b 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentsWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentsWindow.cpp @@ -40,12 +40,12 @@ namespace EMStudio AttachmentsWindow::AttachmentsWindow(QWidget* parent, bool deformable) : QWidget(parent) { - mTableWidget = nullptr; - mActorInstance = nullptr; - mNodeSelectionWindow = nullptr; - mWaitingForAttachment = false; - mIsDeformableAttachment = deformable; - mEscapeShortcut = new QShortcut(QKeySequence(Qt::Key_Escape), this); + m_tableWidget = nullptr; + m_actorInstance = nullptr; + m_nodeSelectionWindow = nullptr; + m_waitingForAttachment = false; + m_isDeformableAttachment = deformable; + m_escapeShortcut = new QShortcut(QKeySequence(Qt::Key_Escape), this); } @@ -58,54 +58,54 @@ namespace EMStudio // init the geometry lod window void AttachmentsWindow::Init() { - mTempString.reserve(16384); + m_tempString.reserve(16384); setObjectName("StackFrameOnlyBG"); setAcceptDrops(true); // create the lod information table - mTableWidget = new QTableWidget(); + m_tableWidget = new QTableWidget(); // set the alternating row colors - mTableWidget->setAlternatingRowColors(true); + m_tableWidget->setAlternatingRowColors(true); // set the table to row single selection - mTableWidget->setSelectionBehavior(QAbstractItemView::SelectRows); - mTableWidget->setSelectionMode(QAbstractItemView::ExtendedSelection); + m_tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows); + m_tableWidget->setSelectionMode(QAbstractItemView::ExtendedSelection); // make the table items read only - mTableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers); + m_tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers); // set the minimum size and the resizing policy - mTableWidget->setMinimumHeight(125); - mTableWidget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); + m_tableWidget->setMinimumHeight(125); + m_tableWidget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); // automatically adjust the size of the last entry to make it always fitting the table widget size - QHeaderView* horizontalHeader = mTableWidget->horizontalHeader(); + QHeaderView* horizontalHeader = m_tableWidget->horizontalHeader(); horizontalHeader->setStretchLastSection(true); // disable the corner button between the row and column selection thingies - mTableWidget->setCornerButtonEnabled(false); + m_tableWidget->setCornerButtonEnabled(false); // enable the custom context menu for the motion table - mTableWidget->setContextMenuPolicy(Qt::DefaultContextMenu); + m_tableWidget->setContextMenuPolicy(Qt::DefaultContextMenu); // set the column count - mTableWidget->setColumnCount(6); + m_tableWidget->setColumnCount(6); // set header items for the table - mTableWidget->setHorizontalHeaderItem(0, new QTableWidgetItem("Vis")); - mTableWidget->setHorizontalHeaderItem(1, new QTableWidgetItem("ID")); - mTableWidget->setHorizontalHeaderItem(2, new QTableWidgetItem("Name")); - mTableWidget->setHorizontalHeaderItem(3, new QTableWidgetItem("IsSkin")); - mTableWidget->setHorizontalHeaderItem(4, new QTableWidgetItem("Node")); - mTableWidget->setHorizontalHeaderItem(5, new QTableWidgetItem("Nodes")); + m_tableWidget->setHorizontalHeaderItem(0, new QTableWidgetItem("Vis")); + m_tableWidget->setHorizontalHeaderItem(1, new QTableWidgetItem("ID")); + m_tableWidget->setHorizontalHeaderItem(2, new QTableWidgetItem("Name")); + m_tableWidget->setHorizontalHeaderItem(3, new QTableWidgetItem("IsSkin")); + m_tableWidget->setHorizontalHeaderItem(4, new QTableWidgetItem("Node")); + m_tableWidget->setHorizontalHeaderItem(5, new QTableWidgetItem("Nodes")); // set the horizontal header alignement horizontalHeader->setDefaultAlignment(Qt::AlignVCenter | Qt::AlignLeft); // set the vertical header not visible - QHeaderView* verticalHeader = mTableWidget->verticalHeader(); + QHeaderView* verticalHeader = m_tableWidget->verticalHeader(); verticalHeader->setVisible(false); // set the vis fast updates and IsSkin columns fixed @@ -114,103 +114,103 @@ namespace EMStudio horizontalHeader->setSectionResizeMode(5, QHeaderView::Fixed); // set the width of the other columns - mTableWidget->setColumnWidth(0, 25); - mTableWidget->setColumnWidth(1, 25); - mTableWidget->setColumnWidth(2, 100); - mTableWidget->setColumnWidth(3, 44); - mTableWidget->setColumnWidth(4, 100); - mTableWidget->setColumnWidth(5, 32); + m_tableWidget->setColumnWidth(0, 25); + m_tableWidget->setColumnWidth(1, 25); + m_tableWidget->setColumnWidth(2, 100); + m_tableWidget->setColumnWidth(3, 44); + m_tableWidget->setColumnWidth(4, 100); + m_tableWidget->setColumnWidth(5, 32); // create buttons for the attachments dialog - mOpenAttachmentButton = new QToolButton(); - mOpenDeformableAttachmentButton = new QToolButton(); - mRemoveButton = new QToolButton(); - mClearButton = new QToolButton(); - mCancelSelectionButton = new QToolButton(); + m_openAttachmentButton = new QToolButton(); + m_openDeformableAttachmentButton = new QToolButton(); + m_removeButton = new QToolButton(); + m_clearButton = new QToolButton(); + m_cancelSelectionButton = new QToolButton(); - EMStudioManager::MakeTransparentButton(mOpenAttachmentButton, "Images/Icons/Open.svg", "Open actor from file and add it as regular attachment"); - EMStudioManager::MakeTransparentButton(mOpenDeformableAttachmentButton, "Images/Icons/Open.svg", "Open actor from file and add it as skin attachment"); - EMStudioManager::MakeTransparentButton(mRemoveButton, "Images/Icons/Minus.svg", "Remove selected attachments"); - EMStudioManager::MakeTransparentButton(mClearButton, "Images/Icons/Clear.svg", "Remove all attachments"); - EMStudioManager::MakeTransparentButton(mCancelSelectionButton, "Images/Icons/Remove.svg", "Cancel attachment selection"); + EMStudioManager::MakeTransparentButton(m_openAttachmentButton, "Images/Icons/Open.svg", "Open actor from file and add it as regular attachment"); + EMStudioManager::MakeTransparentButton(m_openDeformableAttachmentButton, "Images/Icons/Open.svg", "Open actor from file and add it as skin attachment"); + EMStudioManager::MakeTransparentButton(m_removeButton, "Images/Icons/Minus.svg", "Remove selected attachments"); + EMStudioManager::MakeTransparentButton(m_clearButton, "Images/Icons/Clear.svg", "Remove all attachments"); + EMStudioManager::MakeTransparentButton(m_cancelSelectionButton, "Images/Icons/Remove.svg", "Cancel attachment selection"); // create the buttons layout QHBoxLayout* buttonLayout = new QHBoxLayout(); buttonLayout->setSpacing(0); buttonLayout->setAlignment(Qt::AlignLeft); - buttonLayout->addWidget(mOpenAttachmentButton); - buttonLayout->addWidget(mOpenDeformableAttachmentButton); - buttonLayout->addWidget(mRemoveButton); - buttonLayout->addWidget(mClearButton); + buttonLayout->addWidget(m_openAttachmentButton); + buttonLayout->addWidget(m_openDeformableAttachmentButton); + buttonLayout->addWidget(m_removeButton); + buttonLayout->addWidget(m_clearButton); // create the buttons layout for selection mode QHBoxLayout* buttonLayoutSelectionMode = new QHBoxLayout(); buttonLayoutSelectionMode->setSpacing(0); buttonLayoutSelectionMode->setAlignment(Qt::AlignLeft); - buttonLayoutSelectionMode->addWidget(mCancelSelectionButton); + buttonLayoutSelectionMode->addWidget(m_cancelSelectionButton); // create info widgets - mWaitingForAttachmentWidget = new QWidget(); - mNoSelectionWidget = new QWidget(); - mWaitingForAttachmentLayout = new QVBoxLayout(); - mNoSelectionLayout = new QVBoxLayout(); + m_waitingForAttachmentWidget = new QWidget(); + m_noSelectionWidget = new QWidget(); + m_waitingForAttachmentLayout = new QVBoxLayout(); + m_noSelectionLayout = new QVBoxLayout(); QLabel* waitingForAttachmentLabel = new QLabel("Please select an actor instance."); QLabel* noSelectionLabel = new QLabel("No attachments to show."); - mWaitingForAttachmentLayout->addLayout(buttonLayoutSelectionMode); - mWaitingForAttachmentLayout->addWidget(waitingForAttachmentLabel); - mWaitingForAttachmentLayout->setAlignment(waitingForAttachmentLabel, Qt::AlignCenter); - mWaitingForAttachmentWidget->setLayout(mWaitingForAttachmentLayout); - mWaitingForAttachmentWidget->setHidden(true); + m_waitingForAttachmentLayout->addLayout(buttonLayoutSelectionMode); + m_waitingForAttachmentLayout->addWidget(waitingForAttachmentLabel); + m_waitingForAttachmentLayout->setAlignment(waitingForAttachmentLabel, Qt::AlignCenter); + m_waitingForAttachmentWidget->setLayout(m_waitingForAttachmentLayout); + m_waitingForAttachmentWidget->setHidden(true); - mNoSelectionLayout->addWidget(noSelectionLabel); - mNoSelectionLayout->setAlignment(noSelectionLabel, Qt::AlignCenter); - mNoSelectionWidget->setLayout(mNoSelectionLayout); - mNoSelectionWidget->setHidden(true); + m_noSelectionLayout->addWidget(noSelectionLabel); + m_noSelectionLayout->setAlignment(noSelectionLabel, Qt::AlignCenter); + m_noSelectionWidget->setLayout(m_noSelectionLayout); + m_noSelectionWidget->setHidden(true); // create the layouts - mAttachmentsWidget = new QWidget(); - mAttachmentsLayout = new QVBoxLayout(); - mMainLayout = new QVBoxLayout(); - mMainLayout->setMargin(0); - mMainLayout->setSpacing(2); - mAttachmentsLayout->setMargin(0); - mAttachmentsLayout->setSpacing(2); + m_attachmentsWidget = new QWidget(); + m_attachmentsLayout = new QVBoxLayout(); + m_mainLayout = new QVBoxLayout(); + m_mainLayout->setMargin(0); + m_mainLayout->setSpacing(2); + m_attachmentsLayout->setMargin(0); + m_attachmentsLayout->setSpacing(2); // fill the attachments layout - mAttachmentsLayout->addLayout(buttonLayout); - mAttachmentsLayout->addWidget(mTableWidget); - mAttachmentsWidget->setLayout(mAttachmentsLayout); - mAttachmentsWidget->setObjectName("StackFrameOnlyBG"); + m_attachmentsLayout->addLayout(buttonLayout); + m_attachmentsLayout->addWidget(m_tableWidget); + m_attachmentsWidget->setLayout(m_attachmentsLayout); + m_attachmentsWidget->setObjectName("StackFrameOnlyBG"); // settings for the selection mode widgets - mWaitingForAttachmentWidget->setObjectName("StackFrameOnlyBG"); - mWaitingForAttachmentWidget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); - mWaitingForAttachmentLayout->setSpacing(0); - mWaitingForAttachmentLayout->setMargin(0); - mNoSelectionWidget->setObjectName("StackFrameOnlyBG"); - mNoSelectionWidget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); + m_waitingForAttachmentWidget->setObjectName("StackFrameOnlyBG"); + m_waitingForAttachmentWidget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); + m_waitingForAttachmentLayout->setSpacing(0); + m_waitingForAttachmentLayout->setMargin(0); + m_noSelectionWidget->setObjectName("StackFrameOnlyBG"); + m_noSelectionWidget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); // fill the main layout - mMainLayout->addWidget(mAttachmentsWidget); - mMainLayout->addWidget(mWaitingForAttachmentWidget); - mMainLayout->addWidget(mNoSelectionWidget); - setLayout(mMainLayout); + m_mainLayout->addWidget(m_attachmentsWidget); + m_mainLayout->addWidget(m_waitingForAttachmentWidget); + m_mainLayout->addWidget(m_noSelectionWidget); + setLayout(m_mainLayout); // create the node selection window - mNodeSelectionWindow = new NodeSelectionWindow(this, true); + m_nodeSelectionWindow = new NodeSelectionWindow(this, true); // connect the controls to the slots - connect(mTableWidget, &QTableWidget::itemSelectionChanged, this, &AttachmentsWindow::OnSelectionChanged); - connect(mOpenAttachmentButton, &QToolButton::clicked, this, &AttachmentsWindow::OnOpenAttachmentButtonClicked); - connect(mOpenDeformableAttachmentButton, &QToolButton::clicked, this, &AttachmentsWindow::OnOpenDeformableAttachmentButtonClicked); - connect(mRemoveButton, &QToolButton::clicked, this, &AttachmentsWindow::OnRemoveButtonClicked); - connect(mClearButton, &QToolButton::clicked, this, &AttachmentsWindow::OnClearButtonClicked); - connect(mNodeSelectionWindow->GetNodeHierarchyWidget(), &NodeHierarchyWidget::OnSelectionDone, this, &AttachmentsWindow::OnAttachmentNodesSelected); - connect(mNodeSelectionWindow, &NodeSelectionWindow::rejected, this, &AttachmentsWindow::OnCancelAttachmentNodeSelection); - connect(mNodeSelectionWindow->GetNodeHierarchyWidget()->GetTreeWidget(), &QTreeWidget::itemSelectionChanged, this, &AttachmentsWindow::OnNodeChanged); - connect(mEscapeShortcut, &QShortcut::activated, this, &AttachmentsWindow::OnEscapeButtonPressed); - connect(mCancelSelectionButton, &QToolButton::clicked, this, &AttachmentsWindow::OnEscapeButtonPressed); + connect(m_tableWidget, &QTableWidget::itemSelectionChanged, this, &AttachmentsWindow::OnSelectionChanged); + connect(m_openAttachmentButton, &QToolButton::clicked, this, &AttachmentsWindow::OnOpenAttachmentButtonClicked); + connect(m_openDeformableAttachmentButton, &QToolButton::clicked, this, &AttachmentsWindow::OnOpenDeformableAttachmentButtonClicked); + connect(m_removeButton, &QToolButton::clicked, this, &AttachmentsWindow::OnRemoveButtonClicked); + connect(m_clearButton, &QToolButton::clicked, this, &AttachmentsWindow::OnClearButtonClicked); + connect(m_nodeSelectionWindow->GetNodeHierarchyWidget(), &NodeHierarchyWidget::OnSelectionDone, this, &AttachmentsWindow::OnAttachmentNodesSelected); + connect(m_nodeSelectionWindow, &NodeSelectionWindow::rejected, this, &AttachmentsWindow::OnCancelAttachmentNodeSelection); + connect(m_nodeSelectionWindow->GetNodeHierarchyWidget()->GetTreeWidget(), &QTreeWidget::itemSelectionChanged, this, &AttachmentsWindow::OnNodeChanged); + connect(m_escapeShortcut, &QShortcut::activated, this, &AttachmentsWindow::OnEscapeButtonPressed); + connect(m_cancelSelectionButton, &QToolButton::clicked, this, &AttachmentsWindow::OnEscapeButtonPressed); // reinit the window ReInit(); @@ -222,13 +222,13 @@ namespace EMStudio { // get the selected actor instance const CommandSystem::SelectionList& selection = GetCommandManager()->GetCurrentSelection(); - mActorInstance = selection.GetSingleActorInstance(); + m_actorInstance = selection.GetSingleActorInstance(); // disable controls if no actor instance is selected - if (mActorInstance == nullptr) + if (m_actorInstance == nullptr) { // set the row count - mTableWidget->setRowCount(0); + m_tableWidget->setRowCount(0); // update the interface UpdateInterface(); @@ -238,15 +238,15 @@ namespace EMStudio } // the number of existing attachments - const int numAttachments = aznumeric_caster(mActorInstance->GetNumAttachments()); + const int numAttachments = aznumeric_caster(m_actorInstance->GetNumAttachments()); // set table size and add header items - mTableWidget->setRowCount(numAttachments); + m_tableWidget->setRowCount(numAttachments); // loop trough all attachments and add them to the table for (int i = 0; i < numAttachments; ++i) { - EMotionFX::Attachment* attachment = mActorInstance->GetAttachment(i); + EMotionFX::Attachment* attachment = m_actorInstance->GetAttachment(i); if (attachment == nullptr) { continue; @@ -254,7 +254,7 @@ namespace EMStudio EMotionFX::ActorInstance* attachmentInstance = attachment->GetAttachmentActorInstance(); EMotionFX::Actor* attachmentActor = attachmentInstance->GetActor(); - EMotionFX::Actor* attachedToActor = mActorInstance->GetActor(); + EMotionFX::Actor* attachedToActor = m_actorInstance->GetActor(); EMotionFX::Node* attachedToNode = !attachment->GetIsInfluencedByMultipleJoints() ? attachedToNode = attachedToActor->GetSkeleton()->GetNode( @@ -262,14 +262,14 @@ namespace EMStudio : nullptr; // create table items - mTempString = AZStd::string::format("%i", attachmentInstance->GetID()); - QTableWidgetItem* tableItemID = new QTableWidgetItem(mTempString.c_str()); - AzFramework::StringFunc::Path::GetFileName(attachmentActor->GetFileNameString().c_str(), mTempString); - QTableWidgetItem* tableItemName = new QTableWidgetItem(mTempString.c_str()); - mTempString = attachment->GetIsInfluencedByMultipleJoints() ? "Yes" : "No"; - QTableWidgetItem* tableItemDeformable = new QTableWidgetItem(mTempString.c_str()); - mTempString = AZStd::string::format("%zu", attachmentInstance->GetNumNodes()); - QTableWidgetItem* tableItemNumNodes = new QTableWidgetItem(mTempString.c_str()); + m_tempString = AZStd::string::format("%i", attachmentInstance->GetID()); + QTableWidgetItem* tableItemID = new QTableWidgetItem(m_tempString.c_str()); + AzFramework::StringFunc::Path::GetFileName(attachmentActor->GetFileNameString().c_str(), m_tempString); + QTableWidgetItem* tableItemName = new QTableWidgetItem(m_tempString.c_str()); + m_tempString = attachment->GetIsInfluencedByMultipleJoints() ? "Yes" : "No"; + QTableWidgetItem* tableItemDeformable = new QTableWidgetItem(m_tempString.c_str()); + m_tempString = AZStd::string::format("%zu", attachmentInstance->GetNumNodes()); + QTableWidgetItem* tableItemNumNodes = new QTableWidgetItem(m_tempString.c_str()); QTableWidgetItem* tableItemNodeName = new QTableWidgetItem(""); // set node name if exists if (attachedToNode) @@ -279,7 +279,7 @@ namespace EMStudio auto nodeSelectionButton = new AzQtComponents::BrowseEdit(); nodeSelectionButton->setPlaceholderText(attachedToNode->GetName()); nodeSelectionButton->setStyleSheet("text-align: left;"); - mTableWidget->setCellWidget(i, 4, nodeSelectionButton); + m_tableWidget->setCellWidget(i, 4, nodeSelectionButton); connect(nodeSelectionButton, &AzQtComponents::BrowseEdit::attachedButtonTriggered, this, &AttachmentsWindow::OnSelectNodeButtonClicked); } @@ -290,18 +290,18 @@ namespace EMStudio isVisibleCheckBox->setChecked(true); // add table items to the current row - mTableWidget->setCellWidget(i, 0, isVisibleCheckBox); - mTableWidget->setItem(i, 1, tableItemID); - mTableWidget->setItem(i, 2, tableItemName); - mTableWidget->setItem(i, 3, tableItemDeformable); - mTableWidget->setItem(i, 4, tableItemNodeName); - mTableWidget->setItem(i, 5, tableItemNumNodes); + m_tableWidget->setCellWidget(i, 0, isVisibleCheckBox); + m_tableWidget->setItem(i, 1, tableItemID); + m_tableWidget->setItem(i, 2, tableItemName); + m_tableWidget->setItem(i, 3, tableItemDeformable); + m_tableWidget->setItem(i, 4, tableItemNodeName); + m_tableWidget->setItem(i, 5, tableItemNumNodes); // connect the controls to the functions connect(isVisibleCheckBox, &QCheckBox::stateChanged, this, &AttachmentsWindow::OnVisibilityChanged); // set the row height - mTableWidget->setRowHeight(i, 21); + m_tableWidget->setRowHeight(i, 21); } // update the interface @@ -312,8 +312,8 @@ namespace EMStudio // update the enabled state of the remove/clear button depending on the table entries void AttachmentsWindow::OnUpdateButtonsEnabled() { - mRemoveButton->setEnabled(mTableWidget->selectedItems().size() != 0); - mClearButton->setEnabled(mTableWidget->rowCount() != 0); + m_removeButton->setEnabled(m_tableWidget->selectedItems().size() != 0); + m_clearButton->setEnabled(m_tableWidget->rowCount() != 0); } @@ -321,8 +321,8 @@ namespace EMStudio void AttachmentsWindow::UpdateInterface() { // enable/disable widgets, based on the selection state - mAttachmentsWidget->setHidden(mWaitingForAttachment); - mWaitingForAttachmentWidget->setHidden((mWaitingForAttachment == false)); + m_attachmentsWidget->setHidden(m_waitingForAttachment); + m_waitingForAttachmentWidget->setHidden((m_waitingForAttachment == false)); // update remove/clear buttons OnUpdateButtonsEnabled(); @@ -340,8 +340,8 @@ namespace EMStudio const QList urls = mimeData->urls(); // clear the drop filenames - mDropFileNames.clear(); - mDropFileNames.reserve(urls.count()); + m_dropFileNames.clear(); + m_dropFileNames.reserve(urls.count()); // get the number of urls and iterate over them AZStd::string filename; @@ -355,12 +355,12 @@ namespace EMStudio if (extension == "actor") { - mDropFileNames.push_back(filename); + m_dropFileNames.push_back(filename); } } // get the number of dropped sound files - if (mDropFileNames.empty()) + if (m_dropFileNames.empty()) { MCore::LogWarning("Drag and drop failed. No valid actor file dropped."); } @@ -411,13 +411,13 @@ namespace EMStudio MCore::CommandGroup commandGroup("Add attachments"); // skip adding if no actor instance is selected - if (mActorInstance == nullptr) + if (m_actorInstance == nullptr) { return; } // get name of the first node - EMotionFX::Actor* actor = mActorInstance->GetActor(); + EMotionFX::Actor* actor = m_actorInstance->GetActor(); if (actor == nullptr) { return; @@ -447,19 +447,19 @@ namespace EMStudio } // add the attachment - if (mIsDeformableAttachment == false) + if (m_isDeformableAttachment == false) { - commandGroup.AddCommandString(AZStd::string::format("AddAttachment -attachmentID %%LASTRESULT%% -attachToID %i -attachToNode \"%s\"", mActorInstance->GetID(), nodeName).c_str()); + commandGroup.AddCommandString(AZStd::string::format("AddAttachment -attachmentID %%LASTRESULT%% -attachToID %i -attachToNode \"%s\"", m_actorInstance->GetID(), nodeName).c_str()); } else { - commandGroup.AddCommandString(AZStd::string::format("AddDeformableAttachment -attachmentID %%LASTRESULT%% -attachToID %i", mActorInstance->GetID()).c_str()); + commandGroup.AddCommandString(AZStd::string::format("AddDeformableAttachment -attachmentID %%LASTRESULT%% -attachToID %i", m_actorInstance->GetID()).c_str()); } } // select the old actorinstance commandGroup.AddCommandString("Unselect -actorInstanceID SELECT_ALL -actorID SELECT_ALL"); - commandGroup.AddCommandString(AZStd::string::format("Select -actorinstanceID %i", mActorInstance->GetID()).c_str()); + commandGroup.AddCommandString(AZStd::string::format("Select -actorinstanceID %i", m_actorInstance->GetID()).c_str()); // execute the command group GetCommandManager()->ExecuteCommandGroup(commandGroup, outString); @@ -485,7 +485,7 @@ namespace EMStudio const int id = GetIDFromTableRow(item->row()); const AZStd::string nodeName = GetNodeNameFromTableRow(item->row()); - group.AddCommandString(AZStd::string::format("RemoveAttachment -attachmentID %d -attachToID %i -attachToNode \"%s\"", id, mActorInstance->GetID(), nodeName.c_str()).c_str()); + group.AddCommandString(AZStd::string::format("RemoveAttachment -attachmentID %d -attachToID %i -attachToNode \"%s\"", id, m_actorInstance->GetID(), nodeName.c_str()).c_str()); } // execute the group command @@ -499,33 +499,33 @@ namespace EMStudio // called if an actor has been dropped for normal attachments void AttachmentsWindow::OnDroppedAttachmentsActors() { - mIsDeformableAttachment = false; + m_isDeformableAttachment = false; // add attachments to the selected actorinstance - AddAttachments(mDropFileNames); + AddAttachments(m_dropFileNames); // clear the attachments array - mDropFileNames.clear(); + m_dropFileNames.clear(); } // called if an actor has been dropped for deformable attachments void AttachmentsWindow::OnDroppedDeformableActors() { - mIsDeformableAttachment = true; + m_isDeformableAttachment = true; // add attachments to the selected actorinstance - AddAttachments(mDropFileNames); + AddAttachments(m_dropFileNames); // clear the attachments array - mDropFileNames.clear(); + m_dropFileNames.clear(); } // connects two selected actor instances void AttachmentsWindow::OnAttachmentSelected() { - if (mWaitingForAttachment == false) + if (m_waitingForAttachment == false) { return; } @@ -534,13 +534,13 @@ namespace EMStudio const CommandSystem::SelectionList& selection = GetCommandManager()->GetCurrentSelection(); EMotionFX::ActorInstance* attachmentInstance = selection.GetSingleActorInstance(); - if (mActorInstance == nullptr || attachmentInstance == nullptr) + if (m_actorInstance == nullptr || attachmentInstance == nullptr) { return; } // get name of the first node - EMotionFX::Actor* actor = mActorInstance->GetActor(); + EMotionFX::Actor* actor = m_actorInstance->GetActor(); if (actor == nullptr) { return; @@ -550,28 +550,28 @@ namespace EMStudio const char* nodeName = actor->GetSkeleton()->GetNode(0)->GetName(); // remove the attachment in case it is already attached - mActorInstance->RemoveAttachment(attachmentInstance); + m_actorInstance->RemoveAttachment(attachmentInstance); // execute command for the attachment AZStd::string outResult; MCore::CommandGroup commandGroup("Add Attachment"); // add the attachment - if (mIsDeformableAttachment == false) + if (m_isDeformableAttachment == false) { - commandGroup.AddCommandString(AZStd::string::format("AddAttachment -attachToID %i -attachmentID %i -attachToNode \"%s\"", mActorInstance->GetID(), attachmentInstance->GetID(), nodeName).c_str()); + commandGroup.AddCommandString(AZStd::string::format("AddAttachment -attachToID %i -attachmentID %i -attachToNode \"%s\"", m_actorInstance->GetID(), attachmentInstance->GetID(), nodeName).c_str()); } else { - commandGroup.AddCommandString(AZStd::string::format("AddDeformableAttachment -attachToID %i -attachmentID %i", mActorInstance->GetID(), attachmentInstance->GetID()).c_str()); + commandGroup.AddCommandString(AZStd::string::format("AddDeformableAttachment -attachToID %i -attachmentID %i", m_actorInstance->GetID(), attachmentInstance->GetID()).c_str()); } // clear selection and select the actor instance the attachment is attached to commandGroup.AddCommandString(AZStd::string::format("ClearSelection")); - commandGroup.AddCommandString(AZStd::string::format("Select -actorInstanceID %i", mActorInstance->GetID())); + commandGroup.AddCommandString(AZStd::string::format("Select -actorInstanceID %i", m_actorInstance->GetID())); // reset the state for selection - mWaitingForAttachment = false; + m_waitingForAttachment = false; // execute the command group EMStudio::GetCommandManager()->ExecuteCommandGroup(commandGroup, outResult); @@ -583,14 +583,14 @@ namespace EMStudio void AttachmentsWindow::OnNodeChanged() { - NodeHierarchyWidget* hierarchyWidget = mNodeSelectionWindow->GetNodeHierarchyWidget(); + NodeHierarchyWidget* hierarchyWidget = m_nodeSelectionWindow->GetNodeHierarchyWidget(); AZStd::vector& selectedItems = hierarchyWidget->GetSelectedItems(); if (selectedItems.size() != 1) { return; } - const uint32 actorInstanceID = selectedItems[0].mActorInstanceID; + const uint32 actorInstanceID = selectedItems[0].m_actorInstanceId; const char* nodeName = selectedItems[0].GetNodeName(); EMotionFX::ActorInstance* actorInstance = EMotionFX::GetActorManager().FindActorInstanceByID(actorInstanceID); if (actorInstance == nullptr) @@ -598,7 +598,7 @@ namespace EMStudio return; } - assert(actorInstance == mActorInstance); + assert(actorInstance == m_actorInstance); EMotionFX::Actor* actor = actorInstance->GetActor(); EMotionFX::Node* node = actor->GetSkeleton()->FindNodeByName(nodeName); @@ -615,18 +615,18 @@ namespace EMStudio } // reapply the attachment - mActorInstance->RemoveAttachment(attachment); + m_actorInstance->RemoveAttachment(attachment); // create and add the new attachment - EMotionFX::AttachmentNode* newAttachment = EMotionFX::AttachmentNode::Create(mActorInstance, node->GetNodeIndex(), attachment); - mActorInstance->AddAttachment(newAttachment); + EMotionFX::AttachmentNode* newAttachment = EMotionFX::AttachmentNode::Create(m_actorInstance, node->GetNodeIndex(), attachment); + m_actorInstance->AddAttachment(newAttachment); } EMotionFX::ActorInstance* AttachmentsWindow::GetSelectedAttachment() { // get the attachment id - const QList selectedTableItems = mTableWidget->selectedItems(); + const QList selectedTableItems = m_tableWidget->selectedItems(); if (selectedTableItems.length() < 1) { return nullptr; @@ -653,16 +653,15 @@ namespace EMStudio return; } - mActorInstance->RemoveAttachment(attachment); + m_actorInstance->RemoveAttachment(attachment); - EMotionFX::Actor* actor = mActorInstance->GetActor(); - EMotionFX::Node* node = actor->GetSkeleton()->FindNodeByName(mNodeBeforeSelectionWindow.c_str()); + EMotionFX::Actor* actor = m_actorInstance->GetActor(); + EMotionFX::Node* node = actor->GetSkeleton()->FindNodeByName(m_nodeBeforeSelectionWindow.c_str()); if (node) { - EMotionFX::AttachmentNode* newAttachment = EMotionFX::AttachmentNode::Create(mActorInstance, node->GetNodeIndex(), attachment); - mActorInstance->AddAttachment(newAttachment); - //mActorInstance->AddAttachment(node->GetNodeIndex(), attachment); + EMotionFX::AttachmentNode* newAttachment = EMotionFX::AttachmentNode::Create(m_actorInstance, node->GetNodeIndex(), attachment); + m_actorInstance->AddAttachment(newAttachment); } } @@ -670,7 +669,7 @@ namespace EMStudio void AttachmentsWindow::OnOpenAttachmentButtonClicked() { // set to normal attachment - mIsDeformableAttachment = false; + m_isDeformableAttachment = false; AZStd::vector filenames = GetMainWindow()->GetFileManager()->LoadActorsFileDialog(this); if (filenames.empty()) @@ -686,7 +685,7 @@ namespace EMStudio void AttachmentsWindow::OnOpenDeformableAttachmentButtonClicked() { // set to skin attachment - mIsDeformableAttachment = true; + m_isDeformableAttachment = true; AZStd::vector filenames = GetMainWindow()->GetFileManager()->LoadActorsFileDialog(this); if (filenames.empty()) @@ -702,7 +701,7 @@ namespace EMStudio void AttachmentsWindow::OnRemoveButtonClicked() { int lowestSelectedRow = AZStd::numeric_limits::max(); - const QList selectedItems = mTableWidget->selectedItems(); + const QList selectedItems = m_tableWidget->selectedItems(); for (const QTableWidgetItem* selectedItem : selectedItems) { if (selectedItem->row() < lowestSelectedRow) @@ -713,13 +712,13 @@ namespace EMStudio RemoveTableItems(selectedItems); - if (lowestSelectedRow > (mTableWidget->rowCount() - 1)) + if (lowestSelectedRow > (m_tableWidget->rowCount() - 1)) { - mTableWidget->selectRow(lowestSelectedRow - 1); + m_tableWidget->selectRow(lowestSelectedRow - 1); } else { - mTableWidget->selectRow(lowestSelectedRow); + m_tableWidget->selectRow(lowestSelectedRow); } } @@ -727,8 +726,8 @@ namespace EMStudio // remove all attachments void AttachmentsWindow::OnClearButtonClicked() { - mTableWidget->selectAll(); - RemoveTableItems(mTableWidget->selectedItems()); + m_tableWidget->selectAll(); + RemoveTableItems(m_tableWidget->selectedItems()); } @@ -746,14 +745,14 @@ namespace EMStudio const int row = GetRowContainingWidget(widget); if (row != -1) { - mTableWidget->selectRow(row); + m_tableWidget->selectRow(row); } - mNodeBeforeSelectionWindow = GetSelectedNodeName(); + m_nodeBeforeSelectionWindow = GetSelectedNodeName(); // show the node selection window - mNodeSelectionWindow->Update(mActorInstance->GetID()); - mNodeSelectionWindow->show(); + m_nodeSelectionWindow->Update(m_actorInstance->GetID()); + m_nodeSelectionWindow->show(); } @@ -767,7 +766,7 @@ namespace EMStudio return; } - const uint32 actorInstanceID = selection[0].mActorInstanceID; + const uint32 actorInstanceID = selection[0].m_actorInstanceId; const char* nodeName = selection[0].GetNodeName(); if (EMotionFX::GetActorManager().FindActorInstanceByID(actorInstanceID) == nullptr) { @@ -788,8 +787,8 @@ namespace EMStudio AZStd::string oldNodeName = GetSelectedNodeName(); // remove and readd the attachment - commandGroup.AddCommandString(AZStd::string::format("RemoveAttachment -attachmentID %i -attachToID %i -attachToNode \"%s\"", attachment->GetID(), mActorInstance->GetID(), oldNodeName.c_str()).c_str()); - commandGroup.AddCommandString(AZStd::string::format("AddAttachment -attachToID %i -attachmentID %i -attachToNode \"%s\"", mActorInstance->GetID(), attachment->GetID(), nodeName).c_str()); + commandGroup.AddCommandString(AZStd::string::format("RemoveAttachment -attachmentID %i -attachToID %i -attachToNode \"%s\"", attachment->GetID(), m_actorInstance->GetID(), oldNodeName.c_str()).c_str()); + commandGroup.AddCommandString(AZStd::string::format("AddAttachment -attachToID %i -attachmentID %i -attachToNode \"%s\"", m_actorInstance->GetID(), attachment->GetID(), nodeName).c_str()); // execute the command group GetCommandManager()->ExecuteCommandGroup(commandGroup, outResult); @@ -799,7 +798,7 @@ namespace EMStudio // get the selected node name AZStd::string AttachmentsWindow::GetSelectedNodeName() { - const QList items = mTableWidget->selectedItems(); + const QList items = m_tableWidget->selectedItems(); const size_t numItems = items.length(); if (numItems < 1) { @@ -834,7 +833,7 @@ namespace EMStudio // extracts the actor instance id from a given row int AttachmentsWindow::GetIDFromTableRow(int row) { - QTableWidgetItem* item = mTableWidget->item(row, 1); + QTableWidgetItem* item = m_tableWidget->item(row, 1); if (item == nullptr) { return MCore::InvalidIndexT; @@ -850,7 +849,7 @@ namespace EMStudio // extracts the node name from a given row AZStd::string AttachmentsWindow::GetNodeNameFromTableRow(int row) { - QTableWidgetItem* item = mTableWidget->item(row, 4); + QTableWidgetItem* item = m_tableWidget->item(row, 4); if (item == nullptr) { return {}; @@ -864,13 +863,13 @@ namespace EMStudio int AttachmentsWindow::GetRowContainingWidget(const QWidget* widget) { // loop trough the table items and search for widget - const int numRows = mTableWidget->rowCount(); - const int numCols = mTableWidget->columnCount(); + const int numRows = m_tableWidget->rowCount(); + const int numCols = m_tableWidget->columnCount(); for (int i = 0; i < numRows; ++i) { for (int j = 0; j < numCols; ++j) { - if (mTableWidget->cellWidget(i, j) == widget) + if (m_tableWidget->cellWidget(i, j) == widget) { return i; } @@ -891,7 +890,7 @@ namespace EMStudio // cancel selection of escape button is pressed void AttachmentsWindow::OnEscapeButtonPressed() { - mWaitingForAttachment = false; + m_waitingForAttachment = false; UpdateInterface(); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentsWindow.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentsWindow.h index b3bd45fb22..9d3cb2d0f6 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentsWindow.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/Attachments/AttachmentsWindow.h @@ -56,7 +56,7 @@ namespace EMStudio void AddAttachments(const AZStd::vector& filenames); void OnAttachmentSelected(); - bool GetIsWaitingForAttachment() const { return mWaitingForAttachment; } + bool GetIsWaitingForAttachment() const { return m_waitingForAttachment; } EMotionFX::ActorInstance* GetSelectedAttachment(); AZStd::string GetSelectedNodeName(); @@ -89,35 +89,35 @@ namespace EMStudio AZStd::string GetNodeNameFromTableRow(int row); int GetRowContainingWidget(const QWidget* widget); - bool mWaitingForAttachment; - bool mIsDeformableAttachment; + bool m_waitingForAttachment; + bool m_isDeformableAttachment; - QVBoxLayout* mWaitingForAttachmentLayout; - QVBoxLayout* mNoSelectionLayout; - QVBoxLayout* mMainLayout; - QVBoxLayout* mAttachmentsLayout; + QVBoxLayout* m_waitingForAttachmentLayout; + QVBoxLayout* m_noSelectionLayout; + QVBoxLayout* m_mainLayout; + QVBoxLayout* m_attachmentsLayout; - QWidget* mAttachmentsWidget; - QWidget* mWaitingForAttachmentWidget; - QWidget* mNoSelectionWidget; + QWidget* m_attachmentsWidget; + QWidget* m_waitingForAttachmentWidget; + QWidget* m_noSelectionWidget; - QShortcut* mEscapeShortcut; + QShortcut* m_escapeShortcut; - QTableWidget* mTableWidget; - EMotionFX::ActorInstance* mActorInstance; - AZStd::vector mAttachments; - AZStd::string mNodeBeforeSelectionWindow; + QTableWidget* m_tableWidget; + EMotionFX::ActorInstance* m_actorInstance; + AZStd::vector m_attachments; + AZStd::string m_nodeBeforeSelectionWindow; - QToolButton* mOpenAttachmentButton; - QToolButton* mOpenDeformableAttachmentButton; - QToolButton* mRemoveButton; - QToolButton* mClearButton; - QToolButton* mCancelSelectionButton; + QToolButton* m_openAttachmentButton; + QToolButton* m_openDeformableAttachmentButton; + QToolButton* m_removeButton; + QToolButton* m_clearButton; + QToolButton* m_cancelSelectionButton; - NodeSelectionWindow* mNodeSelectionWindow; + NodeSelectionWindow* m_nodeSelectionWindow; - AZStd::vector mDropFileNames; - AZStd::string mTempString; + AZStd::vector m_dropFileNames; + AZStd::string m_tempString; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/CommandBar/CommandBarPlugin.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/CommandBar/CommandBarPlugin.cpp index f06dedfc67..80577de3b4 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/CommandBar/CommandBarPlugin.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/CommandBar/CommandBarPlugin.cpp @@ -91,11 +91,11 @@ namespace EMStudio m_commandEdit = new QLineEdit(); m_commandEdit->setPlaceholderText("Enter command"); connect(m_commandEdit, &QLineEdit::returnPressed, this, &CommandBarPlugin::OnEnter); - m_commandEditAction = mBar->addWidget(m_commandEdit); + m_commandEditAction = m_bar->addWidget(m_commandEdit); m_resultEdit = new QLineEdit(); m_resultEdit->setReadOnly(true); - m_commandResultAction = mBar->addWidget(m_resultEdit); + m_commandResultAction = m_bar->addWidget(m_resultEdit); m_globalSimSpeedSlider = new AzQtComponents::SliderDouble(Qt::Horizontal); m_globalSimSpeedSlider->setMaximumWidth(80); @@ -104,9 +104,9 @@ namespace EMStudio m_globalSimSpeedSlider->setValue(1.0); m_globalSimSpeedSlider->setToolTip("The global simulation speed factor.\nA value of 1.0 means the normal speed, which is when the slider handle is in the center.\nPress the button on the right of this slider to reset to the normal speed."); connect(m_globalSimSpeedSlider, &AzQtComponents::SliderDouble::valueChanged, this, &CommandBarPlugin::OnGlobalSimSpeedChanged); - m_globalSimSpeedSliderAction = mBar->addWidget(m_globalSimSpeedSlider); + m_globalSimSpeedSliderAction = m_bar->addWidget(m_globalSimSpeedSlider); - m_globalSimSpeedResetAction = mBar->addAction(MysticQt::GetMysticQt()->FindIcon("Images/Icons/Reset.svg"), + m_globalSimSpeedResetAction = m_bar->addAction(MysticQt::GetMysticQt()->FindIcon("Images/Icons/Reset.svg"), tr("Reset the global simulation speed factor to its normal speed"), this, &CommandBarPlugin::ResetGlobalSimSpeed); @@ -114,7 +114,7 @@ namespace EMStudio m_progressText->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); m_progressText->setAlignment(Qt::AlignRight); m_progressText->setStyleSheet("padding-right: 1px; color: rgb(140, 140, 140);"); - m_progressTextAction = mBar->addWidget(m_progressText); + m_progressTextAction = m_bar->addWidget(m_progressText); m_progressTextAction->setVisible(false); m_progressBar = new QProgressBar(); @@ -122,10 +122,10 @@ namespace EMStudio m_progressBar->setValue(0); m_progressBar->setMaximumWidth(300); m_progressBar->setStyleSheet("padding-right: 2px;"); - m_progressBarAction = mBar->addWidget(m_progressBar); + m_progressBarAction = m_bar->addWidget(m_progressBar); m_progressBarAction->setVisible(false); - m_lockSelectionAction = mBar->addAction(MysticQt::GetMysticQt()->FindIcon("Images/Icons/Reset.svg"), + m_lockSelectionAction = m_bar->addAction(MysticQt::GetMysticQt()->FindIcon("Images/Icons/Reset.svg"), tr("Lock or unlock the selection of actor instances"), this, &CommandBarPlugin::OnLockSelectionButton); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/CommandBrowser/CommandBrowserPlugin.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/CommandBrowser/CommandBrowserPlugin.cpp deleted file mode 100644 index 2a8a8f99bc..0000000000 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/CommandBrowser/CommandBrowserPlugin.cpp +++ /dev/null @@ -1,280 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -/* - -// include required headers -#include "CommandBrowserPlugin.h" -#include "../../../../EMStudioSDK/Source/EMStudioManager.h" -#include - - -namespace EMStudio -{ - -// constructor -CommandBrowserPlugin::CommandBrowserPlugin() : EMStudio::DockWidgetPlugin() -{ - mWebView = nullptr; -} - - -// destructor -CommandBrowserPlugin::~CommandBrowserPlugin() -{ -} - - -// clone the log window -EMStudioPlugin* CommandBrowserPlugin::Clone() -{ - CommandBrowserPlugin* newPlugin = new CommandBrowserPlugin(); - return newPlugin; -} - - -// init after the parent dock window has been created -bool CommandBrowserPlugin::Init() -{ - //LogInfo("Initializing command browser window."); - //QWebSettings::globalSettings()->setAttribute(QWebSettings::JavascriptEnabled, true); - mWebView = new QWebView( mDock ); - mWebView->setObjectName( "QWebView" ); - mWebView->settings()->setAttribute(QWebSettings::JavascriptEnabled, true); - mWebView->settings()->setAttribute(QWebSettings::JavascriptCanOpenWindows, true ); - mDock->SetContents( mWebView ); - GenerateCommandList(); - return true; -} - - -void CommandBrowserPlugin::GenerateCommandList() -{ - CommandSystem::CommandManager* manager = GetCommandManager(); - - uint32 i; - const uint32 numCommands = manager->GetNumRegisteredCommands(); - - // generate the html header - QString html; - html = ""; - html += ""; - html += "\n"; - - html += "\n"; - html += "\n"; - html += "\n"; - - // init all commands as closed - html += "\n"; - - // write the alphabet - html += "\n"; - MCore::Command* prevCommand = nullptr; - for (i=0; iGetCommand(i); - - // find out if we need to show the leading character - bool newFirstCharacter = false; - if (prevCommand == nullptr) - newFirstCharacter = true; - else - if (prevCommand->GetName()[0] != command->GetName()[0]) - newFirstCharacter = true; - - // display the first character as link - if (newFirstCharacter) - { - const char character = command->GetName()[0]; - QString newString; - newString.sprintf("%c ", character, character); - html += newString; - } - - prevCommand = command; - } - html += ""; - html += "
"; - html += "
"; - html += "
\n"; - - - // show all commands as links - prevCommand = nullptr; - for (i=0; iGetCommand(i); - - // find out if we need to show the leading character - bool newFirstCharacter = false; - if (prevCommand == nullptr) - newFirstCharacter = true; - else - if (prevCommand->GetName()[0] != command->GetName()[0]) - newFirstCharacter = true; - - if (newFirstCharacter) - { - // if this isn't the first command - if (i != 0) - { - html += "
"; - //html += "
"; - html += "
"; - } - - QString newString; - newString.sprintf("", command->GetName()[0]); - html += newString; - - html += "\n"; - html += (char)command->GetName()[0]; - html += ""; - - html += "
"; - html += "
"; - //html += "
"; - //html += "
"; - } - - QString newString; - newString.sprintf("
%s
\n", command->GetName(), command->GetName()); - html += newString; - newString.sprintf("
\n", command->GetName()); - html += newString; - - prevCommand = command; - } - html += "\n"; - - - // set the html code - mWebView->setHtml( html ); -} - -} // namespace EMStudio -*/ diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/CommandBrowser/CommandBrowserPlugin.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/CommandBrowser/CommandBrowserPlugin.h deleted file mode 100644 index b4aa695ce5..0000000000 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/CommandBrowser/CommandBrowserPlugin.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -#ifndef __EMSTUDIO_COMMANDBROWSERPLUGIN_H -#define __EMSTUDIO_COMMANDBROWSERPLUGIN_H -/* -// include MCore -//#include (); // init the max second column width - mMaxSecondColumnWidth = 0; + m_maxSecondColumnWidth = 0; // init the table setColumnCount(2); @@ -47,9 +47,9 @@ namespace EMStudio // set the filter #ifdef AZ_DEBUG_BUILD - mFilter = LOGLEVEL_FATAL | LOGLEVEL_ERROR | LOGLEVEL_WARNING | LOGLEVEL_INFO | LOGLEVEL_DETAILEDINFO | LOGLEVEL_DEBUG; + m_filter = LOGLEVEL_FATAL | LOGLEVEL_ERROR | LOGLEVEL_WARNING | LOGLEVEL_INFO | LOGLEVEL_DETAILEDINFO | LOGLEVEL_DEBUG; #else - mFilter = LOGLEVEL_FATAL | LOGLEVEL_ERROR | LOGLEVEL_WARNING | LOGLEVEL_INFO; + m_filter = LOGLEVEL_FATAL | LOGLEVEL_ERROR | LOGLEVEL_WARNING | LOGLEVEL_INFO; #endif connect(this, &LogWindowCallback::DoLog, this, &LogWindowCallback::LogImpl, Qt::QueuedConnection); @@ -113,17 +113,17 @@ namespace EMStudio setItem(newRowIndex, 1, messageItem); // check the filter, if the filter is not enabled, it's not needed to test the find value - if ((mFilter & (int)logLevel) != 0) + if ((m_filter & (int)logLevel) != 0) { // check the find value, set the row not visible if the text is not found - if (messageItem->text().contains(mFind, Qt::CaseInsensitive)) + if (messageItem->text().contains(m_find, Qt::CaseInsensitive)) { // set the row not hidden setRowHidden(newRowIndex, false); // custom resize of the column to be efficient const int itemWidth = itemDelegate()->sizeHint(viewOptions(), indexFromItem(messageItem)).width(); - mMaxSecondColumnWidth = qMax(mMaxSecondColumnWidth, itemWidth); + m_maxSecondColumnWidth = qMax(m_maxSecondColumnWidth, itemWidth); SetColumnWidthToTakeWholeSpace(); } else @@ -145,10 +145,10 @@ namespace EMStudio void LogWindowCallback::SetFind(const QString& find) { // store the new find - mFind = find; + m_find = find; // init the max second column width - mMaxSecondColumnWidth = 0; + m_maxSecondColumnWidth = 0; // test each row with the new find const int numRows = rowCount(); @@ -159,17 +159,17 @@ namespace EMStudio const int logLevel = messageItem->data(Qt::UserRole).toInt(); // check the filter, if the filter is not enabled, it's not needed to test the find value - if ((mFilter & logLevel) != 0) + if ((m_filter & logLevel) != 0) { // check the find value, set the row not visible if the text is not found - if (messageItem->text().contains(mFind, Qt::CaseInsensitive)) + if (messageItem->text().contains(m_find, Qt::CaseInsensitive)) { // set the row not hidden setRowHidden(i, false); // update the new column width to keep the maximum const int itemWidth = itemDelegate()->sizeHint(viewOptions(), indexFromItem(messageItem)).width(); - mMaxSecondColumnWidth = qMax(mMaxSecondColumnWidth, itemWidth); + m_maxSecondColumnWidth = qMax(m_maxSecondColumnWidth, itemWidth); } else { @@ -191,10 +191,10 @@ namespace EMStudio void LogWindowCallback::SetFilter(uint32 filter) { // store the new filter - mFilter = filter; + m_filter = filter; // init the max second column width - mMaxSecondColumnWidth = 0; + m_maxSecondColumnWidth = 0; // test each row with the new find const int numRows = rowCount(); @@ -205,17 +205,17 @@ namespace EMStudio const int logLevel = messageItem->data(Qt::UserRole).toInt(); // check the filter, if the filter is not enabled, it's not needed to test the find value - if ((mFilter & logLevel) != 0) + if ((m_filter & logLevel) != 0) { // check the find value, set the row not visible if the text is not found - if (messageItem->text().contains(mFind, Qt::CaseInsensitive)) + if (messageItem->text().contains(m_find, Qt::CaseInsensitive)) { // set the row not hidden setRowHidden(i, false); // update the new column width to keep the maximum const int itemWidth = itemDelegate()->sizeHint(viewOptions(), indexFromItem(messageItem)).width(); - mMaxSecondColumnWidth = qMax(mMaxSecondColumnWidth, itemWidth); + m_maxSecondColumnWidth = qMax(m_maxSecondColumnWidth, itemWidth); } else { @@ -263,13 +263,13 @@ namespace EMStudio { const int firstColumnWidth = columnWidth(0); const int widthWihoutFirstColumnWidth = qMax(0, viewport()->width() - firstColumnWidth); - if (mMaxSecondColumnWidth < widthWihoutFirstColumnWidth) + if (m_maxSecondColumnWidth < widthWihoutFirstColumnWidth) { setColumnWidth(1, widthWihoutFirstColumnWidth); } else { - setColumnWidth(1, mMaxSecondColumnWidth); + setColumnWidth(1, m_maxSecondColumnWidth); } } @@ -345,7 +345,7 @@ namespace EMStudio { setRowCount(0); setColumnWidth(1, 0); - mMaxSecondColumnWidth = 0; + m_maxSecondColumnWidth = 0; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/LogWindow/LogWindowCallback.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/LogWindow/LogWindowCallback.h index 3a1598e120..2e319e1dfa 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/LogWindow/LogWindowCallback.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/LogWindow/LogWindowCallback.h @@ -40,13 +40,13 @@ namespace EMStudio void SetFind(const QString& find); QString GetFind() const { - return mFind; + return m_find; } void SetFilter(uint32 filter); uint32 GetFilter() const { - return mFilter; + return m_filter; } protected: @@ -70,9 +70,9 @@ namespace EMStudio void SetColumnWidthToTakeWholeSpace(); private: - QString mFind; - uint32 mFilter; - int mMaxSecondColumnWidth; + QString m_find; + uint32 m_filter; + int m_maxSecondColumnWidth; bool m_scrollToBottom; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/LogWindow/LogWindowPlugin.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/LogWindow/LogWindowPlugin.cpp index a9a7c6a174..8fd80bb584 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/LogWindow/LogWindowPlugin.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/LogWindow/LogWindowPlugin.cpp @@ -20,7 +20,7 @@ namespace EMStudio LogWindowPlugin::LogWindowPlugin() : EMStudio::DockWidgetPlugin() { - mLogCallback = nullptr; + m_logCallback = nullptr; } @@ -28,7 +28,7 @@ namespace EMStudio LogWindowPlugin::~LogWindowPlugin() { // remove the callback from the log manager (automatically deletes from memory as well) - const size_t index = MCore::GetLogManager().FindLogCallback(mLogCallback); + const size_t index = MCore::GetLogManager().FindLogCallback(m_logCallback); if (index != InvalidIndex) { MCore::GetLogManager().RemoveLogCallback(index); @@ -83,7 +83,7 @@ namespace EMStudio bool LogWindowPlugin::Init() { // create the widget - QWidget* windowWidget = new QWidget(mDock); + QWidget* windowWidget = new QWidget(m_dock); // create the layout QVBoxLayout* windowWidgetLayout = new QVBoxLayout(); @@ -91,7 +91,7 @@ namespace EMStudio windowWidgetLayout->setMargin(3); // create the find widget - mSearchWidget = new AzQtComponents::FilteredSearchWidget(windowWidget); + m_searchWidget = new AzQtComponents::FilteredSearchWidget(windowWidget); AddFilter(tr("Fatal"), MCore::LogCallback::LOGLEVEL_FATAL, true); AddFilter(tr("Error"), MCore::LogCallback::LOGLEVEL_ERROR, true); AddFilter(tr("Warning"), MCore::LogCallback::LOGLEVEL_WARNING, true); @@ -103,13 +103,13 @@ namespace EMStudio AddFilter(tr("Detailed Info"), MCore::LogCallback::LOGLEVEL_DETAILEDINFO, false); AddFilter(tr("Debug"), MCore::LogCallback::LOGLEVEL_DEBUG, false); #endif - connect(mSearchWidget, &AzQtComponents::FilteredSearchWidget::TextFilterChanged, this, &LogWindowPlugin::OnTextFilterChanged); - connect(mSearchWidget, &AzQtComponents::FilteredSearchWidget::TypeFilterChanged, this, &LogWindowPlugin::OnTypeFilterChanged); + connect(m_searchWidget, &AzQtComponents::FilteredSearchWidget::TextFilterChanged, this, &LogWindowPlugin::OnTextFilterChanged); + connect(m_searchWidget, &AzQtComponents::FilteredSearchWidget::TypeFilterChanged, this, &LogWindowPlugin::OnTypeFilterChanged); // create the filter layout QHBoxLayout* topLayout = new QHBoxLayout(); topLayout->addWidget(new QLabel("Filter:")); - topLayout->addWidget(mSearchWidget); + topLayout->addWidget(m_searchWidget); topLayout->addStretch(); topLayout->setSpacing(6); @@ -117,18 +117,18 @@ namespace EMStudio windowWidgetLayout->addLayout(topLayout); // create and add the table and callback - mLogCallback = new LogWindowCallback(nullptr); - windowWidgetLayout->addWidget(mLogCallback); + m_logCallback = new LogWindowCallback(nullptr); + windowWidgetLayout->addWidget(m_logCallback); // set the layout windowWidget->setLayout(windowWidgetLayout); // set the table as content - mDock->setWidget(windowWidget); + m_dock->setWidget(windowWidget); // create the callback - mLogCallback->SetLogLevels(MCore::LogCallback::LOGLEVEL_ALL); - MCore::GetLogManager().AddLogCallback(mLogCallback); + m_logCallback->SetLogLevels(MCore::LogCallback::LOGLEVEL_ALL); + MCore::GetLogManager().AddLogCallback(m_logCallback); // return true because the plugin is correctly initialized return true; @@ -138,7 +138,7 @@ namespace EMStudio // find changed void LogWindowPlugin::OnTextFilterChanged(const QString& text) { - mLogCallback->SetFind(text); + m_logCallback->SetFind(text); } @@ -150,7 +150,7 @@ namespace EMStudio { newFilter |= filter.metadata.toInt(); } - mLogCallback->SetFilter(newFilter); + m_logCallback->SetFilter(newFilter); } @@ -159,7 +159,7 @@ namespace EMStudio AzQtComponents::SearchTypeFilter filter(tr("Level"), name); filter.metadata = static_cast(level); filter.enabled = enabled; - mSearchWidget->AddTypeFilter(filter); + m_searchWidget->AddTypeFilter(filter); } } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/LogWindow/LogWindowPlugin.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/LogWindow/LogWindowPlugin.h index 1b40b3fa2a..61b6ab4b8c 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/LogWindow/LogWindowPlugin.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/LogWindow/LogWindowPlugin.h @@ -61,8 +61,8 @@ namespace EMStudio private: void AddFilter(const QString& name, MCore::LogCallback::ELogLevel level, bool enabled); - LogWindowCallback* mLogCallback; - AzQtComponents::FilteredSearchWidget* mSearchWidget; + LogWindowCallback* m_logCallback; + AzQtComponents::FilteredSearchWidget* m_searchWidget; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/MorphTargetEditWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/MorphTargetEditWindow.cpp index a53ed94909..7a38b0813d 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/MorphTargetEditWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/MorphTargetEditWindow.cpp @@ -21,11 +21,11 @@ namespace EMStudio : QDialog(parent) { // keep values - mActorInstance = actorInstance; - mMorphTarget = morphTarget; + m_actorInstance = actorInstance; + m_morphTarget = morphTarget; // init the phoneme selection window - mPhonemeSelectionWindow = nullptr; + m_phonemeSelectionWindow = nullptr; // set the window name setWindowTitle(QString("Edit Morph Target: %1").arg(morphTarget->GetName())); @@ -35,35 +35,35 @@ namespace EMStudio layout->setAlignment(Qt::AlignVCenter); // get the morph target range min/max - const float morphTargetRangeMin = mMorphTarget->GetRangeMin(); - const float morphTargetRangeMax = mMorphTarget->GetRangeMax(); + const float morphTargetRangeMin = m_morphTarget->GetRangeMin(); + const float morphTargetRangeMax = m_morphTarget->GetRangeMax(); // create the range min label QLabel* rangeMinLabel = new QLabel("Range Min"); // create the range min double spinbox - mRangeMin = new AzQtComponents::DoubleSpinBox(); - mRangeMin->setSingleStep(0.1); - mRangeMin->setRange(std::numeric_limits::lowest(), morphTargetRangeMax); - mRangeMin->setValue(morphTargetRangeMin); - connect(mRangeMin, qOverload(&QDoubleSpinBox::valueChanged), this, &MorphTargetEditWindow::MorphTargetRangeMinValueChanged); + m_rangeMin = new AzQtComponents::DoubleSpinBox(); + m_rangeMin->setSingleStep(0.1); + m_rangeMin->setRange(std::numeric_limits::lowest(), morphTargetRangeMax); + m_rangeMin->setValue(morphTargetRangeMin); + connect(m_rangeMin, qOverload(&QDoubleSpinBox::valueChanged), this, &MorphTargetEditWindow::MorphTargetRangeMinValueChanged); // create the range max label QLabel* rangeMaxLabel = new QLabel("Range Max"); // create the range max double spinbox - mRangeMax = new AzQtComponents::DoubleSpinBox(); - mRangeMax->setSingleStep(0.1); - mRangeMax->setRange(morphTargetRangeMin, std::numeric_limits::max()); - mRangeMax->setValue(morphTargetRangeMax); - connect(mRangeMax, qOverload(&QDoubleSpinBox::valueChanged), this, &MorphTargetEditWindow::MorphTargetRangeMaxValueChanged); + m_rangeMax = new AzQtComponents::DoubleSpinBox(); + m_rangeMax->setSingleStep(0.1); + m_rangeMax->setRange(morphTargetRangeMin, std::numeric_limits::max()); + m_rangeMax->setValue(morphTargetRangeMax); + connect(m_rangeMax, qOverload(&QDoubleSpinBox::valueChanged), this, &MorphTargetEditWindow::MorphTargetRangeMaxValueChanged); // create the grid layout QGridLayout* gridLayout = new QGridLayout(); gridLayout->addWidget(rangeMinLabel, 0, 0); - gridLayout->addWidget(mRangeMin, 0, 1); + gridLayout->addWidget(m_rangeMin, 0, 1); gridLayout->addWidget(rangeMaxLabel, 1, 0); - gridLayout->addWidget(mRangeMax, 1, 1); + gridLayout->addWidget(m_rangeMax, 1, 1); // create the buttons layout QHBoxLayout* buttonsLayout = new QHBoxLayout(); @@ -95,36 +95,36 @@ namespace EMStudio MorphTargetEditWindow::~MorphTargetEditWindow() { - delete mPhonemeSelectionWindow; + delete m_phonemeSelectionWindow; } void MorphTargetEditWindow::UpdateInterface() { // get the morph target range min/max - const float morphTargetRangeMin = mMorphTarget->GetRangeMin(); - const float morphTargetRangeMax = mMorphTarget->GetRangeMax(); + const float morphTargetRangeMin = m_morphTarget->GetRangeMin(); + const float morphTargetRangeMax = m_morphTarget->GetRangeMax(); // disable signals - mRangeMin->blockSignals(true); - mRangeMax->blockSignals(true); + m_rangeMin->blockSignals(true); + m_rangeMax->blockSignals(true); // update the range min - mRangeMin->setRange(std::numeric_limits::lowest(), morphTargetRangeMax); - mRangeMin->setValue(morphTargetRangeMin); + m_rangeMin->setRange(std::numeric_limits::lowest(), morphTargetRangeMax); + m_rangeMin->setValue(morphTargetRangeMin); // update the range max - mRangeMax->setRange(morphTargetRangeMin, std::numeric_limits::max()); - mRangeMax->setValue(morphTargetRangeMax); + m_rangeMax->setRange(morphTargetRangeMin, std::numeric_limits::max()); + m_rangeMax->setValue(morphTargetRangeMax); // enable signals - mRangeMin->blockSignals(false); - mRangeMax->blockSignals(false); + m_rangeMin->blockSignals(false); + m_rangeMax->blockSignals(false); // update the phoneme selection window - if (mPhonemeSelectionWindow) + if (m_phonemeSelectionWindow) { - mPhonemeSelectionWindow->UpdateInterface(); + m_phonemeSelectionWindow->UpdateInterface(); } } @@ -132,24 +132,24 @@ namespace EMStudio void MorphTargetEditWindow::MorphTargetRangeMinValueChanged(double value) { const float rangeMin = (float)value; - mRangeMax->setRange(rangeMin, std::numeric_limits::max()); + m_rangeMax->setRange(rangeMin, std::numeric_limits::max()); } void MorphTargetEditWindow::MorphTargetRangeMaxValueChanged(double value) { const float rangeMax = (float)value; - mRangeMin->setRange(std::numeric_limits::lowest(), rangeMax); + m_rangeMin->setRange(std::numeric_limits::lowest(), rangeMax); } void MorphTargetEditWindow::Accepted() { - const float rangeMin = (float)mRangeMin->value(); - const float rangeMax = (float)mRangeMax->value(); + const float rangeMin = (float)m_rangeMin->value(); + const float rangeMax = (float)m_rangeMax->value(); AZStd::string result; - AZStd::string command = AZStd::string::format("AdjustMorphTarget -actorInstanceID %i -lodLevel %zu -name \"%s\" -rangeMin %f -rangeMax %f", mActorInstance->GetID(), mActorInstance->GetLODLevel(), mMorphTarget->GetNameString().c_str(), rangeMin, rangeMax); + AZStd::string command = AZStd::string::format("AdjustMorphTarget -actorInstanceID %i -lodLevel %zu -name \"%s\" -rangeMin %f -rangeMax %f", m_actorInstance->GetID(), m_actorInstance->GetLODLevel(), m_morphTarget->GetNameString().c_str(), rangeMin, rangeMax); if (EMStudio::GetCommandManager()->ExecuteCommand(command, result) == false) { AZ_Error("EMotionFX", false, result.c_str()); @@ -161,9 +161,9 @@ namespace EMStudio void MorphTargetEditWindow::EditPhonemeButtonClicked() { - delete mPhonemeSelectionWindow; - mPhonemeSelectionWindow = new PhonemeSelectionWindow(mActorInstance->GetActor(), mActorInstance->GetLODLevel(), mMorphTarget, this); - mPhonemeSelectionWindow->exec(); + delete m_phonemeSelectionWindow; + m_phonemeSelectionWindow = new PhonemeSelectionWindow(m_actorInstance->GetActor(), m_actorInstance->GetLODLevel(), m_morphTarget, this); + m_phonemeSelectionWindow->exec(); } } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/MorphTargetEditWindow.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/MorphTargetEditWindow.h index e5f6d59055..9439c9d84c 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/MorphTargetEditWindow.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/MorphTargetEditWindow.h @@ -31,7 +31,7 @@ namespace EMStudio ~MorphTargetEditWindow(); void UpdateInterface(); - EMotionFX::MorphTarget* GetMorphTarget() { return mMorphTarget; } + EMotionFX::MorphTarget* GetMorphTarget() { return m_morphTarget; } public slots: void Accepted(); @@ -40,10 +40,10 @@ namespace EMStudio void EditPhonemeButtonClicked(); private: - EMotionFX::ActorInstance* mActorInstance; - EMotionFX::MorphTarget* mMorphTarget; - AzQtComponents::DoubleSpinBox* mRangeMin; - AzQtComponents::DoubleSpinBox* mRangeMax; - PhonemeSelectionWindow* mPhonemeSelectionWindow; + EMotionFX::ActorInstance* m_actorInstance; + EMotionFX::MorphTarget* m_morphTarget; + AzQtComponents::DoubleSpinBox* m_rangeMin; + AzQtComponents::DoubleSpinBox* m_rangeMax; + PhonemeSelectionWindow* m_phonemeSelectionWindow; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/MorphTargetGroupWidget.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/MorphTargetGroupWidget.cpp index aee88f9394..2fec1f424f 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/MorphTargetGroupWidget.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/MorphTargetGroupWidget.cpp @@ -23,11 +23,11 @@ namespace EMStudio : QWidget(parent) { // keep values - mName = name; - mActorInstance = actorInstance; + m_name = name; + m_actorInstance = actorInstance; // init the edit window to nullptr - mEditWindow = nullptr; + m_editWindow = nullptr; // create the layout QVBoxLayout* layout = new QVBoxLayout(); @@ -35,9 +35,9 @@ namespace EMStudio layout->setMargin(0); // checkbox to enable/disable manual mode for all morph targets - mSelectAll = new QCheckBox("Select All"); - mSelectAll->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed); - connect(mSelectAll, &QCheckBox::stateChanged, this, &MorphTargetGroupWidget::SetManualModeForAll); + m_selectAll = new QCheckBox("Select All"); + m_selectAll->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed); + connect(m_selectAll, &QCheckBox::stateChanged, this, &MorphTargetGroupWidget::SetManualModeForAll); // button for resetting all morph targets QPushButton* resetAll = new QPushButton("Reset All"); @@ -46,7 +46,7 @@ namespace EMStudio // add controls to the top layout QHBoxLayout* topControlLayout = new QHBoxLayout(); - topControlLayout->addWidget(mSelectAll); + topControlLayout->addWidget(m_selectAll); topControlLayout->addWidget(resetAll); topControlLayout->setSpacing(5); topControlLayout->setMargin(0); @@ -60,13 +60,13 @@ namespace EMStudio gridLayout->setVerticalSpacing(2); const size_t numMorphTargets = morphTargets.size(); - mMorphTargets.resize(numMorphTargets); + m_morphTargets.resize(numMorphTargets); for (size_t i=0; iaddWidget(numberLabel, intIndex, 0); // add the manual mode checkbox - mMorphTargets[i].mManualMode = new QCheckBox(); - mMorphTargets[i].mManualMode->setMaximumWidth(15); - mMorphTargets[i].mManualMode->setProperty("MorphTargetIndex", intIndex); - mMorphTargets[i].mManualMode->setStyleSheet("QCheckBox{ spacing: 0px; }"); - gridLayout->addWidget(mMorphTargets[i].mManualMode, intIndex, 1); - connect(mMorphTargets[i].mManualMode, &QCheckBox::clicked, this, &MorphTargetGroupWidget::ManualModeClicked); + m_morphTargets[i].m_manualMode = new QCheckBox(); + m_morphTargets[i].m_manualMode->setMaximumWidth(15); + m_morphTargets[i].m_manualMode->setProperty("MorphTargetIndex", intIndex); + m_morphTargets[i].m_manualMode->setStyleSheet("QCheckBox{ spacing: 0px; }"); + gridLayout->addWidget(m_morphTargets[i].m_manualMode, intIndex, 1); + connect(m_morphTargets[i].m_manualMode, &QCheckBox::clicked, this, &MorphTargetGroupWidget::ManualModeClicked); // create slider to adjust the morph target - mMorphTargets[i].mSliderWeight = new AzQtComponents::SliderDoubleCombo(); - mMorphTargets[i].mSliderWeight->setMinimumWidth(50); - mMorphTargets[i].mSliderWeight->setProperty("MorphTargetIndex", intIndex); - mMorphTargets[i].mSliderWeight->spinbox()->setMinimumWidth(40); - mMorphTargets[i].mSliderWeight->spinbox()->setMaximumWidth(40); - gridLayout->addWidget(mMorphTargets[i].mSliderWeight, intIndex, 2); - connect(mMorphTargets[i].mSliderWeight, &AzQtComponents::SliderDoubleCombo::valueChanged, this, &MorphTargetGroupWidget::SliderWeightMoved); - connect(mMorphTargets[i].mSliderWeight, &AzQtComponents::SliderDoubleCombo::editingFinished, this, &MorphTargetGroupWidget::SliderWeightReleased); + m_morphTargets[i].m_sliderWeight = new AzQtComponents::SliderDoubleCombo(); + m_morphTargets[i].m_sliderWeight->setMinimumWidth(50); + m_morphTargets[i].m_sliderWeight->setProperty("MorphTargetIndex", intIndex); + m_morphTargets[i].m_sliderWeight->spinbox()->setMinimumWidth(40); + m_morphTargets[i].m_sliderWeight->spinbox()->setMaximumWidth(40); + gridLayout->addWidget(m_morphTargets[i].m_sliderWeight, intIndex, 2); + connect(m_morphTargets[i].m_sliderWeight, &AzQtComponents::SliderDoubleCombo::valueChanged, this, &MorphTargetGroupWidget::SliderWeightMoved); + connect(m_morphTargets[i].m_sliderWeight, &AzQtComponents::SliderDoubleCombo::editingFinished, this, &MorphTargetGroupWidget::SliderWeightReleased); // create the name label QLabel* nameLabel = new QLabel(morphTargets[i]->GetName()); @@ -116,7 +116,7 @@ namespace EMStudio // the destructor MorphTargetGroupWidget::~MorphTargetGroupWidget() { - delete mEditWindow; + delete m_editWindow; } @@ -128,12 +128,12 @@ namespace EMStudio AZStd::string command; // loop trough all morph targets and enable/disable manual mode - const size_t numMorphTargets = mMorphTargets.size(); + const size_t numMorphTargets = m_morphTargets.size(); for (size_t i = 0; i < numMorphTargets; ++i) { - EMotionFX::MorphTarget* morphTarget = mMorphTargets[i].mMorphTarget; + EMotionFX::MorphTarget* morphTarget = m_morphTargets[i].m_morphTarget; - command = AZStd::string::format("AdjustMorphTarget -actorInstanceID %i -lodLevel %zu -name \"%s\" -manualMode ", mActorInstance->GetID(), mActorInstance->GetLODLevel(), morphTarget->GetName()); + command = AZStd::string::format("AdjustMorphTarget -actorInstanceID %i -lodLevel %zu -name \"%s\" -manualMode ", m_actorInstance->GetID(), m_actorInstance->GetLODLevel(), morphTarget->GetName()); command += AZStd::to_string(value == Qt::Checked); commandGroup.AddCommandString(command); } @@ -154,12 +154,12 @@ namespace EMStudio AZStd::string command; // loop trough all morph targets and enable/disable manual mode - const size_t numMorphTargets = mMorphTargets.size(); + const size_t numMorphTargets = m_morphTargets.size(); for (size_t i = 0; i < numMorphTargets; ++i) { - EMotionFX::MorphTarget* morphTarget = mMorphTargets[i].mMorphTarget; + EMotionFX::MorphTarget* morphTarget = m_morphTargets[i].m_morphTarget; - command = AZStd::string::format("AdjustMorphTarget -actorInstanceID %i -lodLevel %zu -name \"%s\" -weight %f", mActorInstance->GetID(), mActorInstance->GetLODLevel(), morphTarget->GetName(), morphTarget->CalcZeroInfluenceWeight()); + command = AZStd::string::format("AdjustMorphTarget -actorInstanceID %i -lodLevel %zu -name \"%s\" -weight %f", m_actorInstance->GetID(), m_actorInstance->GetLODLevel(), morphTarget->GetName(), morphTarget->CalcZeroInfluenceWeight()); commandGroup.AddCommandString(command); } @@ -176,12 +176,12 @@ namespace EMStudio { QCheckBox* checkBox = static_cast(sender()); const int morphTargetIndex = checkBox->property("MorphTargetIndex").toInt(); - EMotionFX::MorphTarget* morphTarget = mMorphTargets[morphTargetIndex].mMorphTarget; + EMotionFX::MorphTarget* morphTarget = m_morphTargets[morphTargetIndex].m_morphTarget; AZStd::string result; const AZStd::string command = AZStd::string::format("AdjustMorphTarget -actorInstanceID %i -lodLevel %zu -name \"%s\" -weight %f -manualMode %s", - mActorInstance->GetID(), - mActorInstance->GetLODLevel(), + m_actorInstance->GetID(), + m_actorInstance->GetLODLevel(), morphTarget->GetName(), 0.0f, AZStd::to_string(checkBox->isChecked()).c_str()); @@ -198,7 +198,7 @@ namespace EMStudio // get the morph target AzQtComponents::SliderDoubleCombo* floatSlider = static_cast(sender()); const int morphTargetIndex = floatSlider->property("MorphTargetIndex").toInt(); - EMotionFX::MorphSetupInstance::MorphTarget* morphTargetInstance = mMorphTargets[morphTargetIndex].mMorphTargetInstance; + EMotionFX::MorphSetupInstance::MorphTarget* morphTargetInstance = m_morphTargets[morphTargetIndex].m_morphTargetInstance; // update the weight morphTargetInstance->SetWeight(aznumeric_cast(floatSlider->value())); @@ -211,22 +211,22 @@ namespace EMStudio // get the morph target and the morph target instance AzQtComponents::SliderDoubleCombo* floatSlider = static_cast(sender()); const int morphTargetIndex = floatSlider->property("MorphTargetIndex").toInt(); - EMotionFX::MorphTarget* morphTarget = mMorphTargets[morphTargetIndex].mMorphTarget; - EMotionFX::MorphSetupInstance::MorphTarget* morphTargetInstance = mMorphTargets[morphTargetIndex].mMorphTargetInstance; + EMotionFX::MorphTarget* morphTarget = m_morphTargets[morphTargetIndex].m_morphTarget; + EMotionFX::MorphSetupInstance::MorphTarget* morphTargetInstance = m_morphTargets[morphTargetIndex].m_morphTargetInstance; // set the old weight to have the undo correct - morphTargetInstance->SetWeight(mMorphTargets[morphTargetIndex].mOldWeight); + morphTargetInstance->SetWeight(m_morphTargets[morphTargetIndex].m_oldWeight); // execute command AZStd::string result; - const AZStd::string command = AZStd::string::format("AdjustMorphTarget -actorInstanceID %i -lodLevel %zu -name \"%s\" -weight %f", mActorInstance->GetID(), mActorInstance->GetLODLevel(), morphTarget->GetName(), floatSlider->value()); + const AZStd::string command = AZStd::string::format("AdjustMorphTarget -actorInstanceID %i -lodLevel %zu -name \"%s\" -weight %f", m_actorInstance->GetID(), m_actorInstance->GetLODLevel(), morphTarget->GetName(), floatSlider->value()); if (EMStudio::GetCommandManager()->ExecuteCommand(command, result) == false) { AZ_Error("EMotionFX", false, result.c_str()); } // set the new old weight value - mMorphTargets[morphTargetIndex].mOldWeight = aznumeric_cast(floatSlider->value()); + m_morphTargets[morphTargetIndex].m_oldWeight = aznumeric_cast(floatSlider->value()); } @@ -236,12 +236,12 @@ namespace EMStudio // get the morph target QPushButton* button = static_cast(sender()); const int morphTargetIndex = button->property("MorphTargetIndex").toInt(); - EMotionFX::MorphTarget* morphTarget = mMorphTargets[morphTargetIndex].mMorphTarget; + EMotionFX::MorphTarget* morphTarget = m_morphTargets[morphTargetIndex].m_morphTarget; // show the edit window - delete mEditWindow; - mEditWindow = new MorphTargetEditWindow(mActorInstance, morphTarget, this); - mEditWindow->exec(); + delete m_editWindow; + m_editWindow = new MorphTargetEditWindow(m_actorInstance, morphTarget, this); + m_editWindow->exec(); } @@ -250,13 +250,13 @@ namespace EMStudio { bool selectAllChecked = true; - const size_t numMorphTargets = mMorphTargets.size(); + const size_t numMorphTargets = m_morphTargets.size(); for (size_t i = 0; i < numMorphTargets; ++i) { - const float rangeMin = mMorphTargets[i].mMorphTarget->GetRangeMin(); - const float rangeMax = mMorphTargets[i].mMorphTarget->GetRangeMax(); - const float weight = mMorphTargets[i].mMorphTargetInstance->GetWeight(); - const bool manualMode = mMorphTargets[i].mMorphTargetInstance->GetIsInManualMode(); + const float rangeMin = m_morphTargets[i].m_morphTarget->GetRangeMin(); + const float rangeMax = m_morphTargets[i].m_morphTarget->GetRangeMax(); + const float weight = m_morphTargets[i].m_morphTargetInstance->GetWeight(); + const bool manualMode = m_morphTargets[i].m_morphTargetInstance->GetIsInManualMode(); // check if the select all should not be checked if (manualMode == false) @@ -265,82 +265,82 @@ namespace EMStudio } // disable signals - QSignalBlocker sb(mMorphTargets[i].mSliderWeight); - mMorphTargets[i].mManualMode->blockSignals(true); + QSignalBlocker sb(m_morphTargets[i].m_sliderWeight); + m_morphTargets[i].m_manualMode->blockSignals(true); // update the manual mode - mMorphTargets[i].mManualMode->setChecked(manualMode); + m_morphTargets[i].m_manualMode->setChecked(manualMode); // update the slider weight - mMorphTargets[i].mSliderWeight->setDisabled(!manualMode); - mMorphTargets[i].mSliderWeight->setRange(rangeMin, rangeMax); + m_morphTargets[i].m_sliderWeight->setDisabled(!manualMode); + m_morphTargets[i].m_sliderWeight->setRange(rangeMin, rangeMax); // enforce single step of 0.1 - mMorphTargets[i].mSliderWeight->slider()->setNumSteps(aznumeric_cast((rangeMax - rangeMin) / 0.1)); - mMorphTargets[i].mSliderWeight->setValue(weight); + m_morphTargets[i].m_sliderWeight->slider()->setNumSteps(aznumeric_cast((rangeMax - rangeMin) / 0.1)); + m_morphTargets[i].m_sliderWeight->setValue(weight); // enable signals - mMorphTargets[i].mManualMode->blockSignals(false); + m_morphTargets[i].m_manualMode->blockSignals(false); // store the current weight // the weight is updated in realtime but before to execute the adjust command it has to be reset to have the undo correct - mMorphTargets[i].mOldWeight = weight; + m_morphTargets[i].m_oldWeight = weight; } // update the select all - mSelectAll->blockSignals(true); - mSelectAll->setChecked(selectAllChecked); - mSelectAll->blockSignals(false); + m_selectAll->blockSignals(true); + m_selectAll->setChecked(selectAllChecked); + m_selectAll->blockSignals(false); // update the edit window - if (mEditWindow) + if (m_editWindow) { - mEditWindow->UpdateInterface(); + m_editWindow->UpdateInterface(); } } void MorphTargetGroupWidget::UpdateMorphTarget(const char* name) { // update the row - const size_t numMorphTargets = mMorphTargets.size(); + const size_t numMorphTargets = m_morphTargets.size(); for (size_t i = 0; i < numMorphTargets; ++i) { // continue of the name is not the same - if (mMorphTargets[i].mMorphTarget->GetNameString() != name) + if (m_morphTargets[i].m_morphTarget->GetNameString() != name) { continue; } // get values - const float rangeMin = mMorphTargets[i].mMorphTarget->GetRangeMin(); - const float rangeMax = mMorphTargets[i].mMorphTarget->GetRangeMax(); - const float weight = mMorphTargets[i].mMorphTargetInstance->GetWeight(); - const bool manualMode = mMorphTargets[i].mMorphTargetInstance->GetIsInManualMode(); + const float rangeMin = m_morphTargets[i].m_morphTarget->GetRangeMin(); + const float rangeMax = m_morphTargets[i].m_morphTarget->GetRangeMax(); + const float weight = m_morphTargets[i].m_morphTargetInstance->GetWeight(); + const bool manualMode = m_morphTargets[i].m_morphTargetInstance->GetIsInManualMode(); // disable signals - QSignalBlocker sb(mMorphTargets[i].mSliderWeight); - mMorphTargets[i].mManualMode->blockSignals(true); + QSignalBlocker sb(m_morphTargets[i].m_sliderWeight); + m_morphTargets[i].m_manualMode->blockSignals(true); // update the manual mode - mMorphTargets[i].mManualMode->setChecked(manualMode); + m_morphTargets[i].m_manualMode->setChecked(manualMode); // update the slider weight - mMorphTargets[i].mSliderWeight->setDisabled(!manualMode); - mMorphTargets[i].mSliderWeight->setRange(rangeMin, rangeMax); + m_morphTargets[i].m_sliderWeight->setDisabled(!manualMode); + m_morphTargets[i].m_sliderWeight->setRange(rangeMin, rangeMax); // enforce single step of 0.1 - mMorphTargets[i].mSliderWeight->slider()->setNumSteps(aznumeric_cast((rangeMax - rangeMin) / 0.1)); - mMorphTargets[i].mSliderWeight->setValue(weight); + m_morphTargets[i].m_sliderWeight->slider()->setNumSteps(aznumeric_cast((rangeMax - rangeMin) / 0.1)); + m_morphTargets[i].m_sliderWeight->setValue(weight); // enable signals - mMorphTargets[i].mManualMode->blockSignals(false); + m_morphTargets[i].m_manualMode->blockSignals(false); // store the current weight // the weight is updated in realtime but before to execute the adjust command it has to be reset to have the undo correct - mMorphTargets[i].mOldWeight = weight; + m_morphTargets[i].m_oldWeight = weight; // update edit window in case it's the edit of this morph target - if (mEditWindow && mEditWindow->GetMorphTarget() == mMorphTargets[i].mMorphTarget) + if (m_editWindow && m_editWindow->GetMorphTarget() == m_morphTargets[i].m_morphTarget) { - mEditWindow->UpdateInterface(); + m_editWindow->UpdateInterface(); } // stop here because we found it @@ -351,15 +351,15 @@ namespace EMStudio bool selectAllChecked = true; for (uint32 i = 0; i < numMorphTargets; ++i) { - if (mMorphTargets[i].mMorphTargetInstance->GetIsInManualMode() == false) + if (m_morphTargets[i].m_morphTargetInstance->GetIsInManualMode() == false) { selectAllChecked = false; break; } } - mSelectAll->blockSignals(true); - mSelectAll->setChecked(selectAllChecked); - mSelectAll->blockSignals(false); + m_selectAll->blockSignals(true); + m_selectAll->setChecked(selectAllChecked); + m_selectAll->blockSignals(false); } } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/MorphTargetGroupWidget.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/MorphTargetGroupWidget.h index 7a4bdb40b6..5e8519afcc 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/MorphTargetGroupWidget.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/MorphTargetGroupWidget.h @@ -39,16 +39,16 @@ namespace EMStudio struct MorphTarget { - EMotionFX::MorphTarget* mMorphTarget; - EMotionFX::MorphSetupInstance::MorphTarget* mMorphTargetInstance; - QCheckBox* mManualMode; - AzQtComponents::SliderDoubleCombo* mSliderWeight = nullptr; - float mOldWeight; + EMotionFX::MorphTarget* m_morphTarget; + EMotionFX::MorphSetupInstance::MorphTarget* m_morphTargetInstance; + QCheckBox* m_manualMode; + AzQtComponents::SliderDoubleCombo* m_sliderWeight = nullptr; + float m_oldWeight; }; void UpdateInterface(); void UpdateMorphTarget(const char* name); - const MorphTarget* GetMorphTarget(size_t index){ return &mMorphTargets[index]; } + const MorphTarget* GetMorphTarget(size_t index){ return &m_morphTargets[index]; } public slots: void SetManualModeForAll(int value); @@ -59,10 +59,10 @@ namespace EMStudio void ResetAll(); private: - AZStd::string mName; - EMotionFX::ActorInstance* mActorInstance; - QCheckBox* mSelectAll; - AZStd::vector mMorphTargets; - MorphTargetEditWindow* mEditWindow; + AZStd::string m_name; + EMotionFX::ActorInstance* m_actorInstance; + QCheckBox* m_selectAll; + AZStd::vector m_morphTargets; + MorphTargetEditWindow* m_editWindow; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/MorphTargetsWindowPlugin.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/MorphTargetsWindowPlugin.cpp index ce8de9483a..1ceeb155fa 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/MorphTargetsWindowPlugin.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/MorphTargetsWindowPlugin.cpp @@ -22,9 +22,9 @@ namespace EMStudio MorphTargetsWindowPlugin::MorphTargetsWindowPlugin() : EMStudio::DockWidgetPlugin() { - mDialogStack = nullptr; - mCurrentActorInstance = nullptr; - mStaticTextWidget = nullptr; + m_dialogStack = nullptr; + m_currentActorInstance = nullptr; + m_staticTextWidget = nullptr; EMotionFX::ActorInstanceNotificationBus::Handler::BusConnect(); } @@ -43,7 +43,7 @@ namespace EMStudio Clear(); // delete the dialog stack - delete mDialogStack; + delete m_dialogStack; } @@ -59,19 +59,19 @@ namespace EMStudio bool MorphTargetsWindowPlugin::Init() { // create the static text layout - mStaticTextWidget = new QWidget(); - mStaticTextLayout = new QVBoxLayout(); - mStaticTextWidget->setLayout(mStaticTextLayout); + m_staticTextWidget = new QWidget(); + m_staticTextLayout = new QVBoxLayout(); + m_staticTextWidget->setLayout(m_staticTextLayout); QLabel* label = new QLabel("No morph targets to show."); - mStaticTextLayout->addWidget(label); - mStaticTextLayout->setAlignment(label, Qt::AlignCenter); + m_staticTextLayout->addWidget(label); + m_staticTextLayout->setAlignment(label, Qt::AlignCenter); // create the dialog stack - assert(mDialogStack == nullptr); - mDialogStack = new MysticQt::DialogStack(); - mDock->setMinimumWidth(300); - mDock->setMinimumHeight(100); - mDock->setWidget(mStaticTextWidget); + assert(m_dialogStack == nullptr); + m_dialogStack = new MysticQt::DialogStack(); + m_dock->setMinimumWidth(300); + m_dock->setMinimumHeight(100); + m_dock->setWidget(m_staticTextWidget); GetCommandManager()->RegisterCommandCallback("Select", m_callbacks, false); GetCommandManager()->RegisterCommandCallback("Unselect", m_callbacks, false); @@ -83,7 +83,7 @@ namespace EMStudio ReInit(); // connect the window activation signal to refresh if reactivated - connect(mDock, &QDockWidget::visibilityChanged, this, &MorphTargetsWindowPlugin::WindowReInit); + connect(m_dock, &QDockWidget::visibilityChanged, this, &MorphTargetsWindowPlugin::WindowReInit); // done return true; @@ -93,18 +93,18 @@ namespace EMStudio // clear the morph target window void MorphTargetsWindowPlugin::Clear() { - if (mDock) + if (m_dock) { - mDock->setWidget(mStaticTextWidget); + m_dock->setWidget(m_staticTextWidget); } // clear the dialog stack - if (mDialogStack) + if (m_dialogStack) { - mDialogStack->Clear(); + m_dialogStack->Clear(); } - mMorphTargetGroups.clear(); + m_morphTargetGroups.clear(); } // reinit the morph target dialog, e.g. if selection changes @@ -121,13 +121,13 @@ namespace EMStudio if (actorInstance == nullptr) { // set the dock contents - mDock->setWidget(mStaticTextWidget); + m_dock->setWidget(m_staticTextWidget); // clear dialog and reset the current actor instance as we cleared the window - if (mCurrentActorInstance) + if (m_currentActorInstance) { Clear(); - mCurrentActorInstance = nullptr; + m_currentActorInstance = nullptr; } // done @@ -135,10 +135,10 @@ namespace EMStudio } // only reinit the morph targets if actor instance changed - if (mCurrentActorInstance != actorInstance || forceReInit) + if (m_currentActorInstance != actorInstance || forceReInit) { // set the current actor instance in any case - mCurrentActorInstance = actorInstance; + m_currentActorInstance = actorInstance; // arrays for the default morph targets and the phonemes AZStd::vector phonemes; @@ -150,7 +150,7 @@ namespace EMStudio EMotionFX::MorphSetup* morphSetup = actor->GetMorphSetup(actorInstance->GetLODLevel()); if (morphSetup == nullptr) { - mDock->setWidget(mStaticTextWidget); + m_dock->setWidget(m_staticTextWidget); return; } @@ -158,7 +158,7 @@ namespace EMStudio EMotionFX::MorphSetupInstance* morphSetupInstance = actorInstance->GetMorphSetupInstance(); if (morphSetupInstance == nullptr) { - mDock->setWidget(mStaticTextWidget); + m_dock->setWidget(m_staticTextWidget); return; } @@ -217,11 +217,11 @@ namespace EMStudio // create static text if no morph targets are available if (defaultMorphTargets.empty() && phonemes.empty()) { - mDock->setWidget(mStaticTextWidget); + m_dock->setWidget(m_staticTextWidget); } else { - mDock->setWidget(mDialogStack); + m_dock->setWidget(m_dialogStack); } // adjust the slider values to the correct weights of the selected actor instance @@ -237,11 +237,11 @@ namespace EMStudio return; } - MorphTargetGroupWidget* morphTargetGroup = new MorphTargetGroupWidget(name, mCurrentActorInstance, morphTargets, morphTargetInstances, mDialogStack); + MorphTargetGroupWidget* morphTargetGroup = new MorphTargetGroupWidget(name, m_currentActorInstance, morphTargets, morphTargetInstances, m_dialogStack); morphTargetGroup->setObjectName("EMFX.MorphTargetsWindowPlugin.MorphTargetGroupWidget"); - mMorphTargetGroups.push_back(morphTargetGroup); + m_morphTargetGroups.push_back(morphTargetGroup); - mDialogStack->Add(morphTargetGroup, name); + m_dialogStack->Add(morphTargetGroup, name); } @@ -258,7 +258,7 @@ namespace EMStudio // update the interface void MorphTargetsWindowPlugin::UpdateInterface() { - for (MorphTargetGroupWidget* group : mMorphTargetGroups) + for (MorphTargetGroupWidget* group : m_morphTargetGroups) { group->UpdateInterface(); } @@ -268,7 +268,7 @@ namespace EMStudio // update the morph target void MorphTargetsWindowPlugin::UpdateMorphTarget(const char* name) { - for (MorphTargetGroupWidget* group : mMorphTargetGroups) + for (MorphTargetGroupWidget* group : m_morphTargetGroups) { group->UpdateMorphTarget(name); } @@ -276,7 +276,7 @@ namespace EMStudio void MorphTargetsWindowPlugin::OnActorInstanceDestroyed(EMotionFX::ActorInstance* actorInstance) { - if (mCurrentActorInstance == actorInstance) + if (m_currentActorInstance == actorInstance) { ReInit(/*actorInstance=*/nullptr); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/MorphTargetsWindowPlugin.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/MorphTargetsWindowPlugin.h index 4e81a24b39..d2295fcd9c 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/MorphTargetsWindowPlugin.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/MorphTargetsWindowPlugin.h @@ -60,7 +60,7 @@ namespace EMStudio // creates a new group with several morph targets void CreateGroup(const char* name, const AZStd::vector& morphTargets, const AZStd::vector& morphTargetInstances); - EMotionFX::ActorInstance* GetActorInstance() const { return mCurrentActorInstance; } + EMotionFX::ActorInstance* GetActorInstance() const { return m_currentActorInstance; } void UpdateInterface(); void UpdateMorphTarget(const char* name); @@ -82,15 +82,15 @@ namespace EMStudio AZStd::vector m_callbacks; // holds the generated groups for the morph targets - AZStd::vector mMorphTargetGroups; + AZStd::vector m_morphTargetGroups; // holds the currently selected actor instance - EMotionFX::ActorInstance* mCurrentActorInstance; + EMotionFX::ActorInstance* m_currentActorInstance; // some qt stuff - QVBoxLayout* mStaticTextLayout; - QWidget* mStaticTextWidget; - MysticQt::DialogStack* mDialogStack; - QLabel* mInfoText; + QVBoxLayout* m_staticTextLayout; + QWidget* m_staticTextWidget; + MysticQt::DialogStack* m_dialogStack; + QLabel* m_infoText; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/PhonemeSelectionWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/PhonemeSelectionWindow.cpp index 5619398c67..4f1aa5b42b 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/PhonemeSelectionWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/PhonemeSelectionWindow.cpp @@ -34,25 +34,25 @@ namespace EMStudio VisimeWidget::VisimeWidget(const AZStd::string& filename) { // set the file name and size hints - mFileName = filename; - mSelected = false; - mMouseWithinWidget = false; + m_fileName = filename; + m_selected = false; + m_mouseWithinWidget = false; setMinimumHeight(60); setMaximumHeight(60); setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); // extract the pure filename - AzFramework::StringFunc::Path::GetFileName(filename.c_str(), mFileNameWithoutExt); + AzFramework::StringFunc::Path::GetFileName(filename.c_str(), m_fileNameWithoutExt); // load the pixmap - mPixmap = new QPixmap(filename.c_str()); + m_pixmap = new QPixmap(filename.c_str()); } // destructor VisimeWidget::~VisimeWidget() { - delete mPixmap; + delete m_pixmap; } @@ -82,11 +82,11 @@ namespace EMStudio painter.setPen(QColor(66, 66, 66)); // draw selection border - if (mSelected) + if (m_selected) { painter.setBrush(QBrush(QColor(244, 156, 28))); } - else if (mMouseWithinWidget) + else if (m_mouseWithinWidget) { painter.setBrush(QBrush(QColor(153, 160, 178))); } @@ -98,11 +98,11 @@ namespace EMStudio painter.drawRoundedRect(0, 2, width(), height() - 4, 5.0, 5.0); // draw background - if (mSelected) + if (m_selected) { painter.setBrush(QBrush(QColor(56, 65, 72))); } - else if (mMouseWithinWidget) + else if (m_mouseWithinWidget) { painter.setBrush(QBrush(QColor(134, 142, 150))); } @@ -115,10 +115,10 @@ namespace EMStudio painter.drawRoundedRect(2, 4, width() - 4, height() - 8, 5.0, 5.0); // draw visime image - painter.drawPixmap(5, 5, height() - 10, height() - 10, *mPixmap); + painter.drawPixmap(5, 5, height() - 10, height() - 10, *m_pixmap); // draw visime name - if (mSelected) + if (m_selected) { painter.setPen(QColor(244, 156, 28)); } @@ -128,7 +128,7 @@ namespace EMStudio } //painter.setFont( QFont("MS Shell Dlg 2", 8) ); - painter.drawText(70, (height() / 2) + 4, mFileNameWithoutExt.c_str()); + painter.drawText(70, (height() / 2) + 4, m_fileNameWithoutExt.c_str()); } @@ -140,11 +140,11 @@ namespace EMStudio setMinimumWidth(800); setMinimumHeight(450); - mActor = actor; - mMorphTarget = morphTarget; - mLODLevel = lodLevel; - mMorphSetup = actor->GetMorphSetup(lodLevel); - mDirtyFlag = false; + m_actor = actor; + m_morphTarget = morphTarget; + m_lodLevel = lodLevel; + m_morphSetup = actor->GetMorphSetup(lodLevel); + m_dirtyFlag = false; // init the dialog Init(); @@ -165,49 +165,49 @@ namespace EMStudio setSizeGripEnabled(false); // buttons to add / remove / clear phonemes - mAddPhonemesButton = new QPushButton(""); - mAddPhonemesButtonArrow = new QPushButton(""); - mRemovePhonemesButton = new QPushButton(""); - mRemovePhonemesButtonArrow = new QPushButton(""); - mClearPhonemesButton = new QPushButton(""); + m_addPhonemesButton = new QPushButton(""); + m_addPhonemesButtonArrow = new QPushButton(""); + m_removePhonemesButton = new QPushButton(""); + m_removePhonemesButtonArrow = new QPushButton(""); + m_clearPhonemesButton = new QPushButton(""); - EMStudioManager::MakeTransparentButton(mAddPhonemesButtonArrow, "Images/Icons/PlayForward.svg", "Assign the selected phonemes to the morph target."); - EMStudioManager::MakeTransparentButton(mRemovePhonemesButtonArrow, "Images/Icons/PlayBackward.svg", "Unassign the selected phonemes from the morph target."); - EMStudioManager::MakeTransparentButton(mAddPhonemesButton, "Images/Icons/Plus.svg", "Assign the selected phonemes to the morph target."); - EMStudioManager::MakeTransparentButton(mRemovePhonemesButton, "Images/Icons/Minus.svg", "Unassign the selected phonemes from the morph target."); - EMStudioManager::MakeTransparentButton(mClearPhonemesButton, "Images/Icons/Clear.svg", "Unassign all phonemes from the morph target."); + EMStudioManager::MakeTransparentButton(m_addPhonemesButtonArrow, "Images/Icons/PlayForward.svg", "Assign the selected phonemes to the morph target."); + EMStudioManager::MakeTransparentButton(m_removePhonemesButtonArrow, "Images/Icons/PlayBackward.svg", "Unassign the selected phonemes from the morph target."); + EMStudioManager::MakeTransparentButton(m_addPhonemesButton, "Images/Icons/Plus.svg", "Assign the selected phonemes to the morph target."); + EMStudioManager::MakeTransparentButton(m_removePhonemesButton, "Images/Icons/Minus.svg", "Unassign the selected phonemes from the morph target."); + EMStudioManager::MakeTransparentButton(m_clearPhonemesButton, "Images/Icons/Clear.svg", "Unassign all phonemes from the morph target."); // init the visime tables - mPossiblePhonemeSetsTable = new DragTableWidget(0, 1); - mSelectedPhonemeSetsTable = new DragTableWidget(0, 1); - mPossiblePhonemeSetsTable->setCornerButtonEnabled(false); - mPossiblePhonemeSetsTable->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); - mPossiblePhonemeSetsTable->setContextMenuPolicy(Qt::DefaultContextMenu); - mSelectedPhonemeSetsTable->setCornerButtonEnabled(false); - mSelectedPhonemeSetsTable->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); - mSelectedPhonemeSetsTable->setContextMenuPolicy(Qt::DefaultContextMenu); + m_possiblePhonemeSetsTable = new DragTableWidget(0, 1); + m_selectedPhonemeSetsTable = new DragTableWidget(0, 1); + m_possiblePhonemeSetsTable->setCornerButtonEnabled(false); + m_possiblePhonemeSetsTable->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); + m_possiblePhonemeSetsTable->setContextMenuPolicy(Qt::DefaultContextMenu); + m_selectedPhonemeSetsTable->setCornerButtonEnabled(false); + m_selectedPhonemeSetsTable->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); + m_selectedPhonemeSetsTable->setContextMenuPolicy(Qt::DefaultContextMenu); // set the table to row single selection - mPossiblePhonemeSetsTable->setSelectionBehavior(QAbstractItemView::SelectRows); - mSelectedPhonemeSetsTable->setSelectionBehavior(QAbstractItemView::SelectRows); + m_possiblePhonemeSetsTable->setSelectionBehavior(QAbstractItemView::SelectRows); + m_selectedPhonemeSetsTable->setSelectionBehavior(QAbstractItemView::SelectRows); // make the table items read only - mPossiblePhonemeSetsTable->setEditTriggers(QAbstractItemView::NoEditTriggers); - mSelectedPhonemeSetsTable->setEditTriggers(QAbstractItemView::NoEditTriggers); + m_possiblePhonemeSetsTable->setEditTriggers(QAbstractItemView::NoEditTriggers); + m_selectedPhonemeSetsTable->setEditTriggers(QAbstractItemView::NoEditTriggers); // resize to contents and adjust header - QHeaderView* verticalHeaderPossible = mPossiblePhonemeSetsTable->verticalHeader(); - QHeaderView* verticalHeaderSelected = mSelectedPhonemeSetsTable->verticalHeader(); - QHeaderView* horizontalHeaderPossible = mPossiblePhonemeSetsTable->horizontalHeader(); - QHeaderView* horizontalHeaderSelected = mSelectedPhonemeSetsTable->horizontalHeader(); + QHeaderView* verticalHeaderPossible = m_possiblePhonemeSetsTable->verticalHeader(); + QHeaderView* verticalHeaderSelected = m_selectedPhonemeSetsTable->verticalHeader(); + QHeaderView* horizontalHeaderPossible = m_possiblePhonemeSetsTable->horizontalHeader(); + QHeaderView* horizontalHeaderSelected = m_selectedPhonemeSetsTable->horizontalHeader(); verticalHeaderPossible->setVisible(false); verticalHeaderSelected->setVisible(false); horizontalHeaderPossible->setVisible(false); horizontalHeaderSelected->setVisible(false); // create the dialog stacks - mPossiblePhonemeSets = new MysticQt::DialogStack(this); - mSelectedPhonemeSets = new MysticQt::DialogStack(this); + m_possiblePhonemeSets = new MysticQt::DialogStack(this); + m_selectedPhonemeSets = new MysticQt::DialogStack(this); // create and fill the main layout QHBoxLayout* layout = new QHBoxLayout(); @@ -232,10 +232,10 @@ namespace EMStudio QHBoxLayout* buttonLayout = new QHBoxLayout(); buttonLayout->setSpacing(0); buttonLayout->setAlignment(Qt::AlignLeft); - buttonLayout->addWidget(mAddPhonemesButton); + buttonLayout->addWidget(m_addPhonemesButton); leftLayout->addLayout(buttonLayout); - leftLayout->addWidget(mPossiblePhonemeSetsTable); + leftLayout->addWidget(m_possiblePhonemeSetsTable); leftLayout->addWidget(labelHelperWidgetAdd); // the center layout @@ -244,8 +244,8 @@ namespace EMStudio // fill the center layout centerLayout->addWidget(seperatorLineTop); - centerLayout->addWidget(mAddPhonemesButtonArrow); - centerLayout->addWidget(mRemovePhonemesButtonArrow); + centerLayout->addWidget(m_addPhonemesButtonArrow); + centerLayout->addWidget(m_removePhonemesButtonArrow); centerLayout->addWidget(seperatorLineBottom); // the right layout and info label @@ -262,12 +262,12 @@ namespace EMStudio buttonLayout = new QHBoxLayout(); buttonLayout->setSpacing(0); buttonLayout->setAlignment(Qt::AlignLeft); - buttonLayout->addWidget(mRemovePhonemesButton); - buttonLayout->addWidget(mClearPhonemesButton); + buttonLayout->addWidget(m_removePhonemesButton); + buttonLayout->addWidget(m_clearPhonemesButton); // fill the right layozt rightLayout->addLayout(buttonLayout); - rightLayout->addWidget(mSelectedPhonemeSetsTable); + rightLayout->addWidget(m_selectedPhonemeSetsTable); rightLayout->addWidget(labelHelperWidgetRemove); @@ -285,13 +285,13 @@ namespace EMStudio helperWidgetRight->setLayout(rightLayout); // add helper widgets to the dialog stacks - mPossiblePhonemeSets->Add(helperWidgetLeft, "Possible Phoneme Sets", false, true, false); - mSelectedPhonemeSets->Add(helperWidgetRight, "Selected Phoneme Sets", false, true, false); + m_possiblePhonemeSets->Add(helperWidgetLeft, "Possible Phoneme Sets", false, true, false); + m_selectedPhonemeSets->Add(helperWidgetRight, "Selected Phoneme Sets", false, true, false); // add sublayouts to the main layout - layout->addWidget(mPossiblePhonemeSets); + layout->addWidget(m_possiblePhonemeSets); layout->addLayout(centerLayout); - layout->addWidget(mSelectedPhonemeSets); + layout->addWidget(m_selectedPhonemeSets); // set the main layout setLayout(layout); @@ -300,35 +300,35 @@ namespace EMStudio UpdateInterface(); // connect signals to the slots - connect(mPossiblePhonemeSetsTable, &DragTableWidget::itemSelectionChanged, this, &PhonemeSelectionWindow::PhonemeSelectionChanged); - connect(mSelectedPhonemeSetsTable, &DragTableWidget::itemSelectionChanged, this, &PhonemeSelectionWindow::PhonemeSelectionChanged); - connect(mPossiblePhonemeSetsTable, &DragTableWidget::dataDropped, this, &PhonemeSelectionWindow::RemoveSelectedPhonemeSets); - connect(mRemovePhonemesButton, &QPushButton::clicked, this, &PhonemeSelectionWindow::RemoveSelectedPhonemeSets); - connect(mRemovePhonemesButtonArrow, &QPushButton::clicked, this, &PhonemeSelectionWindow::RemoveSelectedPhonemeSets); - connect(mAddPhonemesButton, &QPushButton::clicked, this, &PhonemeSelectionWindow::AddSelectedPhonemeSets); - connect(mAddPhonemesButtonArrow, &QPushButton::clicked, this, &PhonemeSelectionWindow::AddSelectedPhonemeSets); - connect(mSelectedPhonemeSetsTable, &DragTableWidget::dataDropped, this, &PhonemeSelectionWindow::AddSelectedPhonemeSets); - connect(mClearPhonemesButton, &QPushButton::clicked, this, &PhonemeSelectionWindow::ClearSelectedPhonemeSets); - connect(mPossiblePhonemeSetsTable, &DragTableWidget::itemDoubleClicked, this, &PhonemeSelectionWindow::AddSelectedPhonemeSets); - connect(mSelectedPhonemeSetsTable, &DragTableWidget::itemDoubleClicked, this, &PhonemeSelectionWindow::RemoveSelectedPhonemeSets); + connect(m_possiblePhonemeSetsTable, &DragTableWidget::itemSelectionChanged, this, &PhonemeSelectionWindow::PhonemeSelectionChanged); + connect(m_selectedPhonemeSetsTable, &DragTableWidget::itemSelectionChanged, this, &PhonemeSelectionWindow::PhonemeSelectionChanged); + connect(m_possiblePhonemeSetsTable, &DragTableWidget::dataDropped, this, &PhonemeSelectionWindow::RemoveSelectedPhonemeSets); + connect(m_removePhonemesButton, &QPushButton::clicked, this, &PhonemeSelectionWindow::RemoveSelectedPhonemeSets); + connect(m_removePhonemesButtonArrow, &QPushButton::clicked, this, &PhonemeSelectionWindow::RemoveSelectedPhonemeSets); + connect(m_addPhonemesButton, &QPushButton::clicked, this, &PhonemeSelectionWindow::AddSelectedPhonemeSets); + connect(m_addPhonemesButtonArrow, &QPushButton::clicked, this, &PhonemeSelectionWindow::AddSelectedPhonemeSets); + connect(m_selectedPhonemeSetsTable, &DragTableWidget::dataDropped, this, &PhonemeSelectionWindow::AddSelectedPhonemeSets); + connect(m_clearPhonemesButton, &QPushButton::clicked, this, &PhonemeSelectionWindow::ClearSelectedPhonemeSets); + connect(m_possiblePhonemeSetsTable, &DragTableWidget::itemDoubleClicked, this, &PhonemeSelectionWindow::AddSelectedPhonemeSets); + connect(m_selectedPhonemeSetsTable, &DragTableWidget::itemDoubleClicked, this, &PhonemeSelectionWindow::RemoveSelectedPhonemeSets); } void PhonemeSelectionWindow::UpdateInterface() { // return if morph setup is not valid - if (mMorphSetup == nullptr) + if (m_morphSetup == nullptr) { return; } // clear the tables - mPossiblePhonemeSetsTable->clear(); - mSelectedPhonemeSetsTable->clear(); + m_possiblePhonemeSetsTable->clear(); + m_selectedPhonemeSetsTable->clear(); // get number of morph targets - const size_t numMorphTargets = mMorphSetup->GetNumMorphTargets(); - const uint32 numPhonemeSets = mMorphTarget->GetNumAvailablePhonemeSets(); + const size_t numMorphTargets = m_morphSetup->GetNumMorphTargets(); + const uint32 numPhonemeSets = m_morphTarget->GetNumAvailablePhonemeSets(); int insertPosition = 0; for (int i = 1; i < numPhonemeSets; ++i) { @@ -336,7 +336,7 @@ namespace EMStudio bool phonemeSetFound = false; for (size_t j = 0; j < numMorphTargets; ++j) { - EMotionFX::MorphTarget* morphTarget = mMorphSetup->GetMorphTarget(j); + EMotionFX::MorphTarget* morphTarget = m_morphSetup->GetMorphTarget(j); if (morphTarget->GetIsPhonemeSetEnabled((EMotionFX::MorphTarget::EPhonemeSet)(1 << i))) { phonemeSetFound = true; @@ -352,69 +352,69 @@ namespace EMStudio // get the phoneme set name EMotionFX::MorphTarget::EPhonemeSet phonemeSet = (EMotionFX::MorphTarget::EPhonemeSet)(1 << i); - const AZStd::string phonemeSetName = mMorphTarget->GetPhonemeSetString(phonemeSet).c_str(); + const AZStd::string phonemeSetName = m_morphTarget->GetPhonemeSetString(phonemeSet).c_str(); // set the row count for the possible phoneme sets table - mPossiblePhonemeSetsTable->setRowCount(insertPosition + 1); + m_possiblePhonemeSetsTable->setRowCount(insertPosition + 1); // create dummy table widget item. QTableWidgetItem* item = new QTableWidgetItem(phonemeSetName.c_str()); item->setToolTip(GetPhonemeSetExample(phonemeSet)); - mPossiblePhonemeSetsTable->setItem(insertPosition, 0, item); + m_possiblePhonemeSetsTable->setItem(insertPosition, 0, item); // create the visime widget and add it to the table const AZStd::string filename = AZStd::string::format("%s/Images/Visimes/%s.png", MysticQt::GetDataDir().c_str(), phonemeSetName.c_str()); VisimeWidget* visimeWidget = new VisimeWidget(filename); - mPossiblePhonemeSetsTable->setCellWidget(insertPosition, 0, visimeWidget); + m_possiblePhonemeSetsTable->setCellWidget(insertPosition, 0, visimeWidget); // set row and column properties - mPossiblePhonemeSetsTable->setRowHeight(insertPosition, visimeWidget->height() + 2); + m_possiblePhonemeSetsTable->setRowHeight(insertPosition, visimeWidget->height() + 2); // increase insert position ++insertPosition; } // fill the table with the selected phoneme sets - const AZStd::string selectedPhonemeSets = mMorphTarget->GetPhonemeSetString(mMorphTarget->GetPhonemeSets()); + const AZStd::string selectedPhonemeSets = m_morphTarget->GetPhonemeSetString(m_morphTarget->GetPhonemeSets()); AZStd::vector splittedPhonemeSets; AzFramework::StringFunc::Tokenize(selectedPhonemeSets.c_str(), splittedPhonemeSets, MCore::CharacterConstants::comma, true /* keep empty strings */, true /* keep space strings */); const int numSelectedPhonemeSets = aznumeric_caster(splittedPhonemeSets.size()); - mSelectedPhonemeSetsTable->setRowCount(numSelectedPhonemeSets); + m_selectedPhonemeSetsTable->setRowCount(numSelectedPhonemeSets); for (int i = 0; i < numSelectedPhonemeSets; ++i) { // create dummy table widget item. - const EMotionFX::MorphTarget::EPhonemeSet phonemeSet = mMorphTarget->FindPhonemeSet(splittedPhonemeSets[i].c_str()); + const EMotionFX::MorphTarget::EPhonemeSet phonemeSet = m_morphTarget->FindPhonemeSet(splittedPhonemeSets[i].c_str()); QTableWidgetItem* item = new QTableWidgetItem(splittedPhonemeSets[i].c_str()); item->setToolTip(GetPhonemeSetExample(phonemeSet)); - mSelectedPhonemeSetsTable->setItem(i, 0, item); + m_selectedPhonemeSetsTable->setItem(i, 0, item); // create the visime widget and add it to the table const AZStd::string filename = AZStd::string::format("%s/Images/Visimes/%s.png", MysticQt::GetDataDir().c_str(), splittedPhonemeSets[i].c_str()); VisimeWidget* visimeWidget = new VisimeWidget(filename); - mSelectedPhonemeSetsTable->setCellWidget(i, 0, visimeWidget); + m_selectedPhonemeSetsTable->setCellWidget(i, 0, visimeWidget); // set row and column properties - mSelectedPhonemeSetsTable->setRowHeight(i, visimeWidget->height() + 2); + m_selectedPhonemeSetsTable->setRowHeight(i, visimeWidget->height() + 2); } // stretch last section of the tables and disable horizontal header - QHeaderView* horizontalHeaderSelected = mSelectedPhonemeSetsTable->horizontalHeader(); + QHeaderView* horizontalHeaderSelected = m_selectedPhonemeSetsTable->horizontalHeader(); horizontalHeaderSelected->setVisible(false); horizontalHeaderSelected->setStretchLastSection(true); - QHeaderView* horizontalHeaderPossible = mPossiblePhonemeSetsTable->horizontalHeader(); + QHeaderView* horizontalHeaderPossible = m_possiblePhonemeSetsTable->horizontalHeader(); horizontalHeaderPossible->setVisible(false); horizontalHeaderPossible->setStretchLastSection(true); // disable/enable buttons upon reinit of the tables - mAddPhonemesButton->setDisabled(true); - mAddPhonemesButtonArrow->setDisabled(true); - mRemovePhonemesButton->setDisabled(true); - mRemovePhonemesButtonArrow->setDisabled(true); - mClearPhonemesButton->setDisabled(mSelectedPhonemeSetsTable->rowCount() == 0); + m_addPhonemesButton->setDisabled(true); + m_addPhonemesButtonArrow->setDisabled(true); + m_removePhonemesButton->setDisabled(true); + m_removePhonemesButtonArrow->setDisabled(true); + m_clearPhonemesButton->setDisabled(m_selectedPhonemeSetsTable->rowCount() == 0); } @@ -426,15 +426,15 @@ namespace EMStudio // disable/enable buttons bool selected = !table->selectedItems().empty(); - if (table == mPossiblePhonemeSetsTable) + if (table == m_possiblePhonemeSetsTable) { - mAddPhonemesButton->setDisabled(!selected); - mAddPhonemesButtonArrow->setDisabled(!selected); + m_addPhonemesButton->setDisabled(!selected); + m_addPhonemesButtonArrow->setDisabled(!selected); } else { - mRemovePhonemesButton->setDisabled(!selected); - mRemovePhonemesButtonArrow->setDisabled(!selected); + m_removePhonemesButton->setDisabled(!selected); + m_removePhonemesButtonArrow->setDisabled(!selected); } // adjust selection state of the cell widgetsmActor @@ -461,7 +461,7 @@ namespace EMStudio // removes the selected phoneme sets void PhonemeSelectionWindow::RemoveSelectedPhonemeSets() { - QList selectedItems = mSelectedPhonemeSetsTable->selectedItems(); + QList selectedItems = m_selectedPhonemeSetsTable->selectedItems(); if (selectedItems.empty()) { return; @@ -475,7 +475,7 @@ namespace EMStudio } // call command to remove selected the phoneme sets - const AZStd::string command = AZStd::string::format("AdjustMorphTarget -actorID %i -lodLevel %zu -name \"%s\" -phonemeAction \"remove\" -phonemeSets \"%s\"", mActor->GetID(), mLODLevel, mMorphTarget->GetName(), phonemeSets.c_str()); + const AZStd::string command = AZStd::string::format("AdjustMorphTarget -actorID %i -lodLevel %zu -name \"%s\" -phonemeAction \"remove\" -phonemeSets \"%s\"", m_actor->GetID(), m_lodLevel, m_morphTarget->GetName(), phonemeSets.c_str()); AZStd::string result; if (!EMStudio::GetCommandManager()->ExecuteCommand(command, result)) @@ -484,7 +484,7 @@ namespace EMStudio } else { - mDirtyFlag = true; + m_dirtyFlag = true; } } @@ -492,7 +492,7 @@ namespace EMStudio // adds the selected phoneme sets void PhonemeSelectionWindow::AddSelectedPhonemeSets() { - QList selectedItems = mSelectedPhonemeSetsTable->selectedItems(); + QList selectedItems = m_selectedPhonemeSetsTable->selectedItems(); if (selectedItems.empty()) { return; @@ -506,7 +506,7 @@ namespace EMStudio } // call command to add the selected phoneme sets - const AZStd::string command = AZStd::string::format("AdjustMorphTarget -actorID %i -lodLevel %zu -name \"%s\" -phonemeAction \"add\" -phonemeSets \"%s\"", mActor->GetID(), mLODLevel, mMorphTarget->GetName(), phonemeSets.c_str()); + const AZStd::string command = AZStd::string::format("AdjustMorphTarget -actorID %i -lodLevel %zu -name \"%s\" -phonemeAction \"add\" -phonemeSets \"%s\"", m_actor->GetID(), m_lodLevel, m_morphTarget->GetName(), phonemeSets.c_str()); AZStd::string result; if (!EMStudio::GetCommandManager()->ExecuteCommand(command, result)) @@ -515,7 +515,7 @@ namespace EMStudio } else { - mDirtyFlag = true; + m_dirtyFlag = true; } } @@ -523,7 +523,7 @@ namespace EMStudio // clear the selected phoneme sets void PhonemeSelectionWindow::ClearSelectedPhonemeSets() { - const AZStd::string command = AZStd::string::format("AdjustMorphTarget -actorID %i -lodLevel %zu -name \"%s\" -phonemeAction \"clear\"", mActor->GetID(), mLODLevel, mMorphTarget->GetName()); + const AZStd::string command = AZStd::string::format("AdjustMorphTarget -actorID %i -lodLevel %zu -name \"%s\" -phonemeAction \"clear\"", m_actor->GetID(), m_lodLevel, m_morphTarget->GetName()); AZStd::string result; if (!EMStudio::GetCommandManager()->ExecuteCommand(command, result)) @@ -532,7 +532,7 @@ namespace EMStudio } else { - mDirtyFlag = true; + m_dirtyFlag = true; } } @@ -590,7 +590,7 @@ namespace EMStudio MCORE_UNUSED(event); // check if something changed - if (mDirtyFlag == false) + if (m_dirtyFlag == false) { return; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/PhonemeSelectionWindow.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/PhonemeSelectionWindow.h index a6bffffb75..80f0d9b19e 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/PhonemeSelectionWindow.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/PhonemeSelectionWindow.h @@ -91,19 +91,19 @@ namespace EMStudio VisimeWidget(const AZStd::string& filename); virtual ~VisimeWidget(); - void SetSelected(bool selected = true) { mSelected = selected; } + void SetSelected(bool selected = true) { m_selected = selected; } void UpdateInterface(); void paintEvent(QPaintEvent* event) override; - void enterEvent(QEvent* event) override { MCORE_UNUSED(event); mMouseWithinWidget = true; repaint(); } - void leaveEvent(QEvent* event) override { MCORE_UNUSED(event); mMouseWithinWidget = false; repaint(); } + void enterEvent(QEvent* event) override { MCORE_UNUSED(event); m_mouseWithinWidget = true; repaint(); } + void leaveEvent(QEvent* event) override { MCORE_UNUSED(event); m_mouseWithinWidget = false; repaint(); } private: - AZStd::string mFileName; - AZStd::string mFileNameWithoutExt; - QPixmap* mPixmap; - bool mSelected; - bool mMouseWithinWidget; + AZStd::string m_fileName; + AZStd::string m_fileNameWithoutExt; + QPixmap* m_pixmap; + bool m_selected; + bool m_mouseWithinWidget; }; @@ -138,23 +138,23 @@ namespace EMStudio private: // the morph target - EMotionFX::Actor* mActor; - EMotionFX::MorphTarget* mMorphTarget; - size_t mLODLevel; - EMotionFX::MorphSetup* mMorphSetup; + EMotionFX::Actor* m_actor; + EMotionFX::MorphTarget* m_morphTarget; + size_t m_lodLevel; + EMotionFX::MorphSetup* m_morphSetup; // the dialogstacks - MysticQt::DialogStack* mPossiblePhonemeSets; - MysticQt::DialogStack* mSelectedPhonemeSets; - DragTableWidget* mPossiblePhonemeSetsTable; - DragTableWidget* mSelectedPhonemeSetsTable; + MysticQt::DialogStack* m_possiblePhonemeSets; + MysticQt::DialogStack* m_selectedPhonemeSets; + DragTableWidget* m_possiblePhonemeSetsTable; + DragTableWidget* m_selectedPhonemeSetsTable; - QPushButton* mAddPhonemesButton; - QPushButton* mRemovePhonemesButton; - QPushButton* mClearPhonemesButton; - QPushButton* mAddPhonemesButtonArrow; - QPushButton* mRemovePhonemesButtonArrow; + QPushButton* m_addPhonemesButton; + QPushButton* m_removePhonemesButton; + QPushButton* m_clearPhonemesButton; + QPushButton* m_addPhonemesButtonArrow; + QPushButton* m_removePhonemesButtonArrow; - bool mDirtyFlag; + bool m_dirtyFlag; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionEvents/MotionEventPresetsWidget.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionEvents/MotionEventPresetsWidget.cpp index 9432ad1d78..e0e9455770 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionEvents/MotionEventPresetsWidget.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionEvents/MotionEventPresetsWidget.cpp @@ -33,7 +33,7 @@ namespace EMStudio { MotionEventPresetsWidget::MotionEventPresetsWidget(QWidget* parent, MotionEventsPlugin* plugin) : QWidget(parent) - , mPlugin(plugin) + , m_plugin(plugin) { Init(); } @@ -48,17 +48,17 @@ namespace EMStudio layout->setSpacing(2); // create the table widget - mTableWidget = new DragTableWidget(0, 2, nullptr); - mTableWidget->setCornerButtonEnabled(false); - mTableWidget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); - mTableWidget->setContextMenuPolicy(Qt::DefaultContextMenu); - mTableWidget->setShowGrid(false); + m_tableWidget = new DragTableWidget(0, 2, nullptr); + m_tableWidget->setCornerButtonEnabled(false); + m_tableWidget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); + m_tableWidget->setContextMenuPolicy(Qt::DefaultContextMenu); + m_tableWidget->setShowGrid(false); // set the table to row single selection - mTableWidget->setSelectionBehavior(QAbstractItemView::SelectRows); - mTableWidget->setSelectionMode(QAbstractItemView::ExtendedSelection); + m_tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows); + m_tableWidget->setSelectionMode(QAbstractItemView::ExtendedSelection); - QHeaderView* horizontalHeader = mTableWidget->horizontalHeader(); + QHeaderView* horizontalHeader = m_tableWidget->horizontalHeader(); horizontalHeader->setStretchLastSection(true); horizontalHeader->setVisible(false); @@ -89,15 +89,15 @@ namespace EMStudio } layout->addWidget(toolBar); - layout->addWidget(mTableWidget); + layout->addWidget(m_tableWidget); layout->addLayout(ioButtonsLayout); // set the main layout setLayout(layout); // connect the signals and the slots - connect(mTableWidget, &MotionEventPresetsWidget::DragTableWidget::itemSelectionChanged, this, &MotionEventPresetsWidget::SelectionChanged); - connect(mTableWidget, &QTableWidget::cellDoubleClicked, this, [this](int row, int column) + connect(m_tableWidget, &MotionEventPresetsWidget::DragTableWidget::itemSelectionChanged, this, &MotionEventPresetsWidget::SelectionChanged); + connect(m_tableWidget, &QTableWidget::cellDoubleClicked, this, [this](int row, int column) { AZ_UNUSED(column); MotionEventPreset* preset = GetEventPresetManager()->GetPreset(row); @@ -108,7 +108,7 @@ namespace EMStudio GetEventPresetManager()->SetDirtyFlag(true); ReInit(); - mPlugin->FireColorChangedSignal(); + m_plugin->FireColorChangedSignal(); } }); @@ -116,14 +116,14 @@ namespace EMStudio // initialize everything ReInit(); UpdateInterface(); - mPlugin->ReInit(); + m_plugin->ReInit(); } void MotionEventPresetsWidget::ReInit() { // Remember selected items - QList selectedItems = mTableWidget->selectedItems(); + QList selectedItems = m_tableWidget->selectedItems(); AZStd::vector selectedRows; selectedRows.reserve(selectedItems.size()); for (const QTableWidgetItem* selectedItem : selectedItems) @@ -133,11 +133,11 @@ namespace EMStudio } // clear the table widget - mTableWidget->clear(); - mTableWidget->setColumnCount(2); + m_tableWidget->clear(); + m_tableWidget->setColumnCount(2); const size_t numEventPresets = GetEventPresetManager()->GetNumPresets(); - mTableWidget->setRowCount(static_cast(numEventPresets)); + m_tableWidget->setRowCount(static_cast(numEventPresets)); // set header items for the table QTableWidgetItem* colorHeaderItem = new QTableWidgetItem("Color"); @@ -145,11 +145,11 @@ namespace EMStudio colorHeaderItem->setTextAlignment(Qt::AlignVCenter | Qt::AlignLeft); presetNameHeaderItem->setTextAlignment(Qt::AlignVCenter | Qt::AlignLeft); - mTableWidget->setHorizontalHeaderItem(0, colorHeaderItem); - mTableWidget->setHorizontalHeaderItem(1, presetNameHeaderItem); + m_tableWidget->setHorizontalHeaderItem(0, colorHeaderItem); + m_tableWidget->setHorizontalHeaderItem(1, presetNameHeaderItem); - mTableWidget->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Fixed); - mTableWidget->setColumnWidth(0, 39); + m_tableWidget->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Fixed); + m_tableWidget->setColumnWidth(0, 39); for (AZ::u32 i = 0; i < numEventPresets; ++i) { @@ -173,8 +173,8 @@ namespace EMStudio tableItemColor->setWhatsThis(whatsThisString.c_str()); tableItemPresetName->setWhatsThis(whatsThisString.c_str()); - mTableWidget->setItem(i, 0, tableItemColor); - mTableWidget->setItem(i, 1, tableItemPresetName); + m_tableWidget->setItem(i, 0, tableItemColor); + m_tableWidget->setItem(i, 1, tableItemPresetName); // Editing will be handled in the double click signal handler tableItemPresetName->setFlags(tableItemPresetName->flags() ^ Qt::ItemIsEditable); @@ -188,23 +188,23 @@ namespace EMStudio } // set the vertical header not visible - QHeaderView* verticalHeader = mTableWidget->verticalHeader(); + QHeaderView* verticalHeader = m_tableWidget->verticalHeader(); verticalHeader->setVisible(false); - mTableWidget->resizeColumnToContents(1); - mTableWidget->resizeColumnToContents(2); + m_tableWidget->resizeColumnToContents(1); + m_tableWidget->resizeColumnToContents(2); - if (mTableWidget->columnWidth(1) < 36) + if (m_tableWidget->columnWidth(1) < 36) { - mTableWidget->setColumnWidth(1, 36); + m_tableWidget->setColumnWidth(1, 36); } - if (mTableWidget->columnWidth(2) < 70) + if (m_tableWidget->columnWidth(2) < 70) { - mTableWidget->setColumnWidth(2, 70); + m_tableWidget->setColumnWidth(2, 70); } - mTableWidget->horizontalHeader()->setStretchLastSection(true); + m_tableWidget->horizontalHeader()->setStretchLastSection(true); // update the interface UpdateInterface(); @@ -243,7 +243,7 @@ namespace EMStudio void MotionEventPresetsWidget::RemoveSelectedMotionEventPresets() { - QList selectedItems = mTableWidget->selectedItems(); + QList selectedItems = m_tableWidget->selectedItems(); if (selectedItems.isEmpty()) { ClearMotionEventPresetsButton(); @@ -272,13 +272,13 @@ namespace EMStudio ReInit(); // selected the next row - if (firstSelectedRow > (mTableWidget->rowCount() - 1)) + if (firstSelectedRow > (m_tableWidget->rowCount() - 1)) { - mTableWidget->selectRow(firstSelectedRow - 1); + m_tableWidget->selectRow(firstSelectedRow - 1); } else { - mTableWidget->selectRow(firstSelectedRow); + m_tableWidget->selectRow(firstSelectedRow); } } @@ -303,7 +303,7 @@ namespace EMStudio void MotionEventPresetsWidget::ClearMotionEventPresets() { - mTableWidget->selectAll(); + m_tableWidget->selectAll(); RemoveSelectedMotionEventPresets(); UpdateInterface(); } @@ -329,7 +329,7 @@ namespace EMStudio ReInit(); UpdateInterface(); - mPlugin->ReInit(); + m_plugin->ReInit(); } @@ -366,7 +366,7 @@ namespace EMStudio void MotionEventPresetsWidget::contextMenuEvent(QContextMenuEvent* event) { - QList selectedItems = mTableWidget->selectedItems(); + QList selectedItems = m_tableWidget->selectedItems(); if (selectedItems.isEmpty()) { return; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionEvents/MotionEventPresetsWidget.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionEvents/MotionEventPresetsWidget.h index 331780fe19..8d36f57c25 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionEvents/MotionEventPresetsWidget.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionEvents/MotionEventPresetsWidget.h @@ -46,7 +46,7 @@ namespace EMStudio void Init(); void UpdateInterface(); - QTableWidget* GetMotionEventPresetsTable() { return mTableWidget; } + QTableWidget* GetMotionEventPresetsTable() { return m_tableWidget; } public slots: void ReInit(); @@ -93,12 +93,12 @@ namespace EMStudio } }; - DragTableWidget* mTableWidget = nullptr; + DragTableWidget* m_tableWidget = nullptr; QAction* m_addAction = nullptr; QAction* m_saveMenuAction = nullptr; QAction* m_saveAction = nullptr; QAction* m_saveAsAction = nullptr; QAction* m_loadAction = nullptr; - MotionEventsPlugin* mPlugin = nullptr; + MotionEventsPlugin* m_plugin = nullptr; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionEvents/MotionEventsPlugin.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionEvents/MotionEventsPlugin.cpp index 193fbec9e3..316b2017cc 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionEvents/MotionEventsPlugin.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionEvents/MotionEventsPlugin.cpp @@ -25,34 +25,34 @@ namespace EMStudio { MotionEventsPlugin::MotionEventsPlugin() : EMStudio::DockWidgetPlugin() - , mAdjustMotionCallback(nullptr) - , mSelectCallback(nullptr) - , mUnselectCallback(nullptr) - , mClearSelectionCallback(nullptr) - , mDialogStack(nullptr) - , mMotionEventPresetsWidget(nullptr) - , mMotionEventWidget(nullptr) - , mMotionTable(nullptr) - , mTimeViewPlugin(nullptr) - , mTrackHeaderWidget(nullptr) - , mTrackDataWidget(nullptr) - , mMotionWindowPlugin(nullptr) - , mMotionListWindow(nullptr) - , mMotion(nullptr) + , m_adjustMotionCallback(nullptr) + , m_selectCallback(nullptr) + , m_unselectCallback(nullptr) + , m_clearSelectionCallback(nullptr) + , m_dialogStack(nullptr) + , m_motionEventPresetsWidget(nullptr) + , m_motionEventWidget(nullptr) + , m_motionTable(nullptr) + , m_timeViewPlugin(nullptr) + , m_trackHeaderWidget(nullptr) + , m_trackDataWidget(nullptr) + , m_motionWindowPlugin(nullptr) + , m_motionListWindow(nullptr) + , m_motion(nullptr) { } MotionEventsPlugin::~MotionEventsPlugin() { - GetCommandManager()->RemoveCommandCallback(mAdjustMotionCallback, false); - GetCommandManager()->RemoveCommandCallback(mSelectCallback, false); - GetCommandManager()->RemoveCommandCallback(mUnselectCallback, false); - GetCommandManager()->RemoveCommandCallback(mClearSelectionCallback, false); - delete mAdjustMotionCallback; - delete mSelectCallback; - delete mUnselectCallback; - delete mClearSelectionCallback; + GetCommandManager()->RemoveCommandCallback(m_adjustMotionCallback, false); + GetCommandManager()->RemoveCommandCallback(m_selectCallback, false); + GetCommandManager()->RemoveCommandCallback(m_unselectCallback, false); + GetCommandManager()->RemoveCommandCallback(m_clearSelectionCallback, false); + delete m_adjustMotionCallback; + delete m_selectCallback; + delete m_unselectCallback; + delete m_clearSelectionCallback; } @@ -74,12 +74,12 @@ namespace EMStudio { if (classID == TimeViewPlugin::CLASS_ID) { - mTimeViewPlugin = nullptr; + m_timeViewPlugin = nullptr; } if (classID == MotionWindowPlugin::CLASS_ID) { - mMotionWindowPlugin = nullptr; + m_motionWindowPlugin = nullptr; } } @@ -91,28 +91,28 @@ namespace EMStudio GetEventPresetManager()->Load(); // create callbacks - mAdjustMotionCallback = new CommandAdjustMotionCallback(false); - mSelectCallback = new CommandSelectCallback(false); - mUnselectCallback = new CommandUnselectCallback(false); - mClearSelectionCallback = new CommandClearSelectionCallback(false); - GetCommandManager()->RegisterCommandCallback("AdjustMotion", mAdjustMotionCallback); - GetCommandManager()->RegisterCommandCallback("Select", mSelectCallback); - GetCommandManager()->RegisterCommandCallback("Unselect", mUnselectCallback); - GetCommandManager()->RegisterCommandCallback("ClearSelection", mClearSelectionCallback); + m_adjustMotionCallback = new CommandAdjustMotionCallback(false); + m_selectCallback = new CommandSelectCallback(false); + m_unselectCallback = new CommandUnselectCallback(false); + m_clearSelectionCallback = new CommandClearSelectionCallback(false); + GetCommandManager()->RegisterCommandCallback("AdjustMotion", m_adjustMotionCallback); + GetCommandManager()->RegisterCommandCallback("Select", m_selectCallback); + GetCommandManager()->RegisterCommandCallback("Unselect", m_unselectCallback); + GetCommandManager()->RegisterCommandCallback("ClearSelection", m_clearSelectionCallback); // create the dialog stack - assert(mDialogStack == nullptr); - mDialogStack = new MysticQt::DialogStack(mDock); - mDock->setWidget(mDialogStack); + assert(m_dialogStack == nullptr); + m_dialogStack = new MysticQt::DialogStack(m_dock); + m_dock->setWidget(m_dialogStack); // create the motion event presets widget - mMotionEventPresetsWidget = new MotionEventPresetsWidget(mDialogStack, this); - mDialogStack->Add(mMotionEventPresetsWidget, "Motion Event Presets", false, true); - connect(mDock, &QDockWidget::visibilityChanged, this, &MotionEventsPlugin::WindowReInit); + m_motionEventPresetsWidget = new MotionEventPresetsWidget(m_dialogStack, this); + m_dialogStack->Add(m_motionEventPresetsWidget, "Motion Event Presets", false, true); + connect(m_dock, &QDockWidget::visibilityChanged, this, &MotionEventsPlugin::WindowReInit); // create the motion event properties widget - mMotionEventWidget = new MotionEventWidget(mDialogStack); - mDialogStack->Add(mMotionEventWidget, "Motion Event Properties", false, true); + m_motionEventWidget = new MotionEventWidget(m_dialogStack); + m_dialogStack->Add(m_motionEventWidget, "Motion Event Properties", false, true); ValidatePluginLinks(); UpdateMotionEventWidget(); @@ -123,30 +123,30 @@ namespace EMStudio void MotionEventsPlugin::ValidatePluginLinks() { - if (!mTimeViewPlugin) + if (!m_timeViewPlugin) { EMStudioPlugin* timeViewBasePlugin = EMStudio::GetPluginManager()->FindActivePlugin(TimeViewPlugin::CLASS_ID); if (timeViewBasePlugin) { - mTimeViewPlugin = (TimeViewPlugin*)timeViewBasePlugin; - mTrackDataWidget = mTimeViewPlugin->GetTrackDataWidget(); - mTrackHeaderWidget = mTimeViewPlugin->GetTrackHeaderWidget(); + m_timeViewPlugin = (TimeViewPlugin*)timeViewBasePlugin; + m_trackDataWidget = m_timeViewPlugin->GetTrackDataWidget(); + m_trackHeaderWidget = m_timeViewPlugin->GetTrackHeaderWidget(); - connect(mTrackDataWidget, &TrackDataWidget::MotionEventPresetsDropped, this, &MotionEventsPlugin::OnEventPresetDropped); - connect(mTimeViewPlugin, &TimeViewPlugin::SelectionChanged, this, &MotionEventsPlugin::UpdateMotionEventWidget); - connect(this, &MotionEventsPlugin::OnColorChanged, mTimeViewPlugin, &TimeViewPlugin::ReInit); + connect(m_trackDataWidget, &TrackDataWidget::MotionEventPresetsDropped, this, &MotionEventsPlugin::OnEventPresetDropped); + connect(m_timeViewPlugin, &TimeViewPlugin::SelectionChanged, this, &MotionEventsPlugin::UpdateMotionEventWidget); + connect(this, &MotionEventsPlugin::OnColorChanged, m_timeViewPlugin, &TimeViewPlugin::ReInit); } } - if (!mMotionWindowPlugin) + if (!m_motionWindowPlugin) { EMStudioPlugin* motionBasePlugin = EMStudio::GetPluginManager()->FindActivePlugin(MotionWindowPlugin::CLASS_ID); if (motionBasePlugin) { - mMotionWindowPlugin = (MotionWindowPlugin*)motionBasePlugin; - mMotionListWindow = mMotionWindowPlugin->GetMotionListWindow(); + m_motionWindowPlugin = (MotionWindowPlugin*)motionBasePlugin; + m_motionListWindow = m_motionWindowPlugin->GetMotionListWindow(); - connect(mMotionListWindow, &MotionListWindow::MotionSelectionChanged, this, &MotionEventsPlugin::MotionSelectionChanged); + connect(m_motionListWindow, &MotionListWindow::MotionSelectionChanged, this, &MotionEventsPlugin::MotionSelectionChanged); } } } @@ -155,9 +155,9 @@ namespace EMStudio void MotionEventsPlugin::MotionSelectionChanged() { EMotionFX::Motion* motion = GetCommandManager()->GetCurrentSelection().GetSingleMotion(); - if (mMotion != motion) + if (m_motion != motion) { - mMotion = motion; + m_motion = motion; ReInit(); } } @@ -185,7 +185,7 @@ namespace EMStudio bool MotionEventsPlugin::CheckIfIsPresetReadyToDrop() { // get the motion event presets table - QTableWidget* eventPresetsTable = mMotionEventPresetsWidget->GetMotionEventPresetsTable(); + QTableWidget* eventPresetsTable = m_motionEventPresetsWidget->GetMotionEventPresetsTable(); if (eventPresetsTable == nullptr) { return false; @@ -210,18 +210,17 @@ namespace EMStudio void MotionEventsPlugin::OnEventPresetDropped(QPoint position) { // calculate the start time for the motion event - double dropTimeInSeconds = mTimeViewPlugin->PixelToTime(position.x()); - //mTimeViewPlugin->CalcTime( position.x(), &dropTimeInSeconds, nullptr, nullptr, nullptr, nullptr ); + double dropTimeInSeconds = m_timeViewPlugin->PixelToTime(position.x()); // get the time track on which we dropped the preset - TimeTrack* timeTrack = mTimeViewPlugin->GetTrackAt(position.y()); - if (!timeTrack || !mMotion) + TimeTrack* timeTrack = m_timeViewPlugin->GetTrackAt(position.y()); + if (!timeTrack || !m_motion) { return; } // get the corresponding motion event track - EMotionFX::MotionEventTable* eventTable = mMotion->GetEventTable(); + EMotionFX::MotionEventTable* eventTable = m_motion->GetEventTable(); EMotionFX::MotionEventTrack* eventTrack = eventTable->FindTrackByName(timeTrack->GetName()); if (eventTrack == nullptr) { @@ -229,7 +228,7 @@ namespace EMStudio } // get the motion event presets table - QTableWidget* eventPresetsTable = mMotionEventPresetsWidget->GetMotionEventPresetsTable(); + QTableWidget* eventPresetsTable = m_motionEventPresetsWidget->GetMotionEventPresetsTable(); if (eventPresetsTable == nullptr) { return; @@ -246,7 +245,7 @@ namespace EMStudio if (itemName->isSelected()) { CommandSystem::CommandCreateMotionEvent* createMotionEventCommand = aznew CommandSystem::CommandCreateMotionEvent(); - createMotionEventCommand->SetMotionID(mMotion->GetID()); + createMotionEventCommand->SetMotionID(m_motion->GetID()); createMotionEventCommand->SetEventTrackName(eventTrack->GetName()); createMotionEventCommand->SetStartTime(aznumeric_cast(dropTimeInSeconds)); createMotionEventCommand->SetEndTime(aznumeric_cast(dropTimeInSeconds)); @@ -263,20 +262,20 @@ namespace EMStudio void MotionEventsPlugin::UpdateMotionEventWidget() { - if (!mMotionEventWidget || !mTimeViewPlugin) + if (!m_motionEventWidget || !m_timeViewPlugin) { return; } - mTimeViewPlugin->UpdateSelection(); - if (mTimeViewPlugin->GetNumSelectedEvents() != 1) + m_timeViewPlugin->UpdateSelection(); + if (m_timeViewPlugin->GetNumSelectedEvents() != 1) { - mMotionEventWidget->ReInit(); + m_motionEventWidget->ReInit(); } else { - EventSelectionItem selectionItem = mTimeViewPlugin->GetSelectedEvent(0); - mMotionEventWidget->ReInit(selectionItem.mMotion, selectionItem.GetMotionEvent()); + EventSelectionItem selectionItem = m_timeViewPlugin->GetSelectedEvent(0); + m_motionEventWidget->ReInit(selectionItem.m_motion, selectionItem.GetMotionEvent()); } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionEvents/MotionEventsPlugin.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionEvents/MotionEventsPlugin.h index 7f3e821f8d..7cd34e4bca 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionEvents/MotionEventsPlugin.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionEvents/MotionEventsPlugin.h @@ -56,7 +56,7 @@ namespace EMStudio void OnBeforeRemovePlugin(uint32 classID) override; - MotionEventPresetsWidget* GetPresetsWidget() const { return mMotionEventPresetsWidget; } + MotionEventPresetsWidget* GetPresetsWidget() const { return m_motionEventPresetsWidget; } void ValidatePluginLinks(); @@ -78,21 +78,21 @@ namespace EMStudio MCORE_DEFINECOMMANDCALLBACK(CommandSelectCallback); MCORE_DEFINECOMMANDCALLBACK(CommandUnselectCallback); MCORE_DEFINECOMMANDCALLBACK(CommandClearSelectionCallback); - CommandAdjustMotionCallback* mAdjustMotionCallback; - CommandSelectCallback* mSelectCallback; - CommandUnselectCallback* mUnselectCallback; - CommandClearSelectionCallback* mClearSelectionCallback; + CommandAdjustMotionCallback* m_adjustMotionCallback; + CommandSelectCallback* m_selectCallback; + CommandUnselectCallback* m_unselectCallback; + CommandClearSelectionCallback* m_clearSelectionCallback; - MysticQt::DialogStack* mDialogStack; - MotionEventPresetsWidget* mMotionEventPresetsWidget; - MotionEventWidget* mMotionEventWidget; + MysticQt::DialogStack* m_dialogStack; + MotionEventPresetsWidget* m_motionEventPresetsWidget; + MotionEventWidget* m_motionEventWidget; - QTableWidget* mMotionTable; - TimeViewPlugin* mTimeViewPlugin; - TrackHeaderWidget* mTrackHeaderWidget; - TrackDataWidget* mTrackDataWidget; - MotionWindowPlugin* mMotionWindowPlugin; - MotionListWindow* mMotionListWindow; - EMotionFX::Motion* mMotion; + QTableWidget* m_motionTable; + TimeViewPlugin* m_timeViewPlugin; + TrackHeaderWidget* m_trackHeaderWidget; + TrackDataWidget* m_trackDataWidget; + MotionWindowPlugin* m_motionWindowPlugin; + MotionListWindow* m_motionListWindow; + EMotionFX::Motion* m_motion; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetManagementWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetManagementWindow.cpp index 5943263e3d..ca62d6d927 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetManagementWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetManagementWindow.cpp @@ -120,7 +120,7 @@ namespace EMStudio : QDialog(parent) { // store the motion set - mMotionSet = motionSet; + m_motionSet = motionSet; // set the window title setWindowTitle("Enter new motion set name"); @@ -132,33 +132,27 @@ namespace EMStudio QVBoxLayout* layout = new QVBoxLayout(); // add the line edit - mLineEdit = new QLineEdit(); - connect(mLineEdit, &QLineEdit::textEdited, this, &MotionSetManagementRenameWindow::TextEdited); - layout->addWidget(mLineEdit); + m_lineEdit = new QLineEdit(); + connect(m_lineEdit, &QLineEdit::textEdited, this, &MotionSetManagementRenameWindow::TextEdited); + layout->addWidget(m_lineEdit); // set the current name and select all - mLineEdit->setText(motionSet->GetName()); - mLineEdit->selectAll(); - - // create add the error message - /*mErrorMsg = new QLabel("Error: Duplicate name found"); - mErrorMsg->setAlignment(Qt::AlignVCenter | Qt::AlignLeft); - mErrorMsg->setVisible(false);*/ + m_lineEdit->setText(motionSet->GetName()); + m_lineEdit->selectAll(); // create the button layout QHBoxLayout* buttonLayout = new QHBoxLayout(); - mOKButton = new QPushButton("OK"); + m_okButton = new QPushButton("OK"); QPushButton* cancelButton = new QPushButton("Cancel"); - //buttonLayout->addWidget(mErrorMsg); - buttonLayout->addWidget(mOKButton); + buttonLayout->addWidget(m_okButton); buttonLayout->addWidget(cancelButton); // Allow pressing the enter key as alternative to pressing the ok button for faster workflow. - mOKButton->setAutoDefault(true); - mOKButton->setDefault(true); + m_okButton->setAutoDefault(true); + m_okButton->setDefault(true); // connect the buttons - connect(mOKButton, &QPushButton::clicked, this, &MotionSetManagementRenameWindow::Accepted); + connect(m_okButton, &QPushButton::clicked, this, &MotionSetManagementRenameWindow::Accepted); connect(cancelButton, &QPushButton::clicked, this, &MotionSetManagementRenameWindow::reject); // set the new layout @@ -171,15 +165,13 @@ namespace EMStudio { if (text.isEmpty()) { - //mErrorMsg->setVisible(false); - mOKButton->setEnabled(false); - GetManager()->SetWidgetAsInvalidInput(mLineEdit); + m_okButton->setEnabled(false); + GetManager()->SetWidgetAsInvalidInput(m_lineEdit); } - else if (text == mMotionSet->GetName()) + else if (text == m_motionSet->GetName()) { - //mErrorMsg->setVisible(false); - mOKButton->setEnabled(true); - mLineEdit->setStyleSheet(""); + m_okButton->setEnabled(true); + m_lineEdit->setStyleSheet(""); } else { @@ -196,24 +188,22 @@ namespace EMStudio if (text == motionSet->GetName()) { - //mErrorMsg->setVisible(true); - mOKButton->setEnabled(false); - GetManager()->SetWidgetAsInvalidInput(mLineEdit); + m_okButton->setEnabled(false); + GetManager()->SetWidgetAsInvalidInput(m_lineEdit); return; } } // no duplicate name found - //mErrorMsg->setVisible(false); - mOKButton->setEnabled(true); - mLineEdit->setStyleSheet(""); + m_okButton->setEnabled(true); + m_lineEdit->setStyleSheet(""); } } void MotionSetManagementRenameWindow::Accepted() { - const AZStd::string commandString = AZStd::string::format("AdjustMotionSet -motionSetID %i -newName \"%s\"", mMotionSet->GetID(), mLineEdit->text().toUtf8().data()); + const AZStd::string commandString = AZStd::string::format("AdjustMotionSet -motionSetID %i -newName \"%s\"", m_motionSet->GetID(), m_lineEdit->text().toUtf8().data()); AZStd::string result; if (!EMStudio::GetCommandManager()->ExecuteCommand(commandString, result)) @@ -229,7 +219,7 @@ namespace EMStudio MotionSetManagementWindow::MotionSetManagementWindow(MotionSetsWindowPlugin* parentPlugin, QWidget* parent) : QWidget(parent) { - mPlugin = parentPlugin; + m_plugin = parentPlugin; } @@ -248,31 +238,31 @@ namespace EMStudio layout->setMargin(0); layout->setSpacing(2); - mMotionSetsTree = new QTreeWidget(); + m_motionSetsTree = new QTreeWidget(); // set the table to row single selection - mMotionSetsTree->setSelectionBehavior(QAbstractItemView::SelectRows); - mMotionSetsTree->setSelectionMode(QAbstractItemView::ExtendedSelection); + m_motionSetsTree->setSelectionBehavior(QAbstractItemView::SelectRows); + m_motionSetsTree->setSelectionMode(QAbstractItemView::ExtendedSelection); // set the minimum size and the resizing policy - mMotionSetsTree->setMinimumHeight(150); - mMotionSetsTree->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - mMotionSetsTree->setColumnCount(1); + m_motionSetsTree->setMinimumHeight(150); + m_motionSetsTree->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + m_motionSetsTree->setColumnCount(1); - mMotionSetsTree->setAlternatingRowColors(true); - mMotionSetsTree->setExpandsOnDoubleClick(true); - mMotionSetsTree->setAnimated(true); - mMotionSetsTree->setObjectName("EMFX.MotionSetManagementWindow.MotionSetsTree"); + m_motionSetsTree->setAlternatingRowColors(true); + m_motionSetsTree->setExpandsOnDoubleClick(true); + m_motionSetsTree->setAnimated(true); + m_motionSetsTree->setObjectName("EMFX.MotionSetManagementWindow.MotionSetsTree"); - connect(mMotionSetsTree, &QTreeWidget::itemSelectionChanged, this, &MotionSetManagementWindow::OnSelectionChanged); + connect(m_motionSetsTree, &QTreeWidget::itemSelectionChanged, this, &MotionSetManagementWindow::OnSelectionChanged); QStringList headerList; headerList.append("Name"); - mMotionSetsTree->setHeaderLabels(headerList); - mMotionSetsTree->header()->setSortIndicator(0, Qt::AscendingOrder); + m_motionSetsTree->setHeaderLabels(headerList); + m_motionSetsTree->header()->setSortIndicator(0, Qt::AscendingOrder); // disable the move of section to have column order fixed - mMotionSetsTree->header()->setSectionsMovable(false); + m_motionSetsTree->header()->setSectionsMovable(false); QToolBar* toolBar = new QToolBar(this); toolBar->setObjectName("MotionSetManagementWindow.ToolBar"); @@ -311,7 +301,7 @@ namespace EMStudio toolBar->addWidget(m_searchWidget); layout->addWidget(toolBar); - layout->addWidget(mMotionSetsTree); + layout->addWidget(m_motionSetsTree); ReInit(); UpdateInterface(); @@ -373,7 +363,7 @@ namespace EMStudio void MotionSetManagementWindow::ReInit() { // Get the selected items in the motion set tree widget.. - const QList selectedItems = mMotionSetsTree->selectedItems(); + const QList selectedItems = m_motionSetsTree->selectedItems(); const int numSelectedItems = selectedItems.size(); // Create and fill an array containing ids of all selected motion sets. @@ -385,11 +375,11 @@ namespace EMStudio }); // Set the sorting disabled to avoid index issues. - mMotionSetsTree->setSortingEnabled(false); + m_motionSetsTree->setSortingEnabled(false); // Clear all old items. - mMotionSetsTree->blockSignals(true); - mMotionSetsTree->clear(); + m_motionSetsTree->blockSignals(true); + m_motionSetsTree->clear(); // Iterate through root motion sets and fill in the table recursively. AZStd::string tempString; @@ -409,7 +399,7 @@ namespace EMStudio } // add the top level item - QTreeWidgetItem* item = new QTreeWidgetItem(mMotionSetsTree); + QTreeWidgetItem* item = new QTreeWidgetItem(m_motionSetsTree); item->setText(0, motionSet->GetName()); item->setData(0, Qt::UserRole, motionSet->GetID()); item->setIcon(0, QIcon(QStringLiteral(":/EMotionFX/MotionSet.svg"))); @@ -418,7 +408,7 @@ namespace EMStudio AZStd::to_string(tempString, motionSet->GetID()); item->setWhatsThis(0, tempString.c_str()); - mMotionSetsTree->addTopLevelItem(item); + m_motionSetsTree->addTopLevelItem(item); // Should the motion set be selected? if (AZStd::find(selectedMotionSetIDs.begin(), selectedMotionSetIDs.end(), motionSet->GetID()) != selectedMotionSetIDs.end()) @@ -459,20 +449,20 @@ namespace EMStudio } // enable the tree signals - mMotionSetsTree->blockSignals(false); + m_motionSetsTree->blockSignals(false); // enable the sorting - mMotionSetsTree->setSortingEnabled(true); + m_motionSetsTree->setSortingEnabled(true); } void MotionSetManagementWindow::OnSelectionChanged() { - const QList selectedItems = mMotionSetsTree->selectedItems(); + const QList selectedItems = m_motionSetsTree->selectedItems(); const size_t numSelected = selectedItems.count(); if (numSelected != 1) { - mPlugin->SetSelectedSet(nullptr); + m_plugin->SetSelectedSet(nullptr); } else { @@ -481,7 +471,7 @@ namespace EMStudio if (selectedSet) { - mPlugin->SetSelectedSet(selectedSet); + m_plugin->SetSelectedSet(selectedSet); } } } @@ -498,7 +488,7 @@ namespace EMStudio connect(addAction, &QAction::triggered, this, &MotionSetManagementWindow::OnCreateMotionSet); // get the selected items - const QList selectedItems = mMotionSetsTree->selectedItems(); + const QList selectedItems = m_motionSetsTree->selectedItems(); const int numSelectedItems = selectedItems.count(); // add remove if at least one item selected @@ -537,7 +527,7 @@ namespace EMStudio void MotionSetManagementWindow::OnCreateMotionSet() { - const QList selectedItems = mMotionSetsTree->selectedItems(); + const QList selectedItems = m_motionSetsTree->selectedItems(); const int numSelectedItems = selectedItems.count(); // only add the motion set as child if at least one item selected @@ -562,7 +552,7 @@ namespace EMStudio } // Select the new motion set - mMotionSetsTree->clearSelection(); + m_motionSetsTree->clearSelection(); const EMotionFX::MotionSet* motionSet = EMotionFX::GetMotionManager().FindMotionSetByName(uniqueMotionSetName.c_str()); if (motionSet) { @@ -611,7 +601,7 @@ namespace EMStudio } // Select the new motion sets. - mMotionSetsTree->clearSelection(); + m_motionSetsTree->clearSelection(); for (const AZStd::pair& nameAndParentMotionSet : parentMotionSetByName) { EMotionFX::MotionSet* motionSet = nameAndParentMotionSet.second->RecursiveFindMotionSetByName(nameAndParentMotionSet.first); @@ -624,8 +614,8 @@ namespace EMStudio void MotionSetManagementWindow::SelectItemsById(uint32 motionSetId) { bool selectionChanged = false; - disconnect(mMotionSetsTree, &QTreeWidget::itemSelectionChanged, this, &MotionSetManagementWindow::OnSelectionChanged); - QTreeWidgetItemIterator it(mMotionSetsTree); + disconnect(m_motionSetsTree, &QTreeWidget::itemSelectionChanged, this, &MotionSetManagementWindow::OnSelectionChanged); + QTreeWidgetItemIterator it(m_motionSetsTree); while (*it) { if ((*it)->data(0, Qt::UserRole).toUInt() == motionSetId) @@ -639,7 +629,7 @@ namespace EMStudio } ++it; } - connect(mMotionSetsTree, &QTreeWidget::itemSelectionChanged, this, &MotionSetManagementWindow::OnSelectionChanged); + connect(m_motionSetsTree, &QTreeWidget::itemSelectionChanged, this, &MotionSetManagementWindow::OnSelectionChanged); if (selectionChanged) { OnSelectionChanged(); @@ -649,7 +639,7 @@ namespace EMStudio void MotionSetManagementWindow::GetSelectedMotionSets(AZStd::vector& outSelectedMotionSets) const { // Get the selected items from the motion set tree widget. - const QList selectedItems = mMotionSetsTree->selectedItems(); + const QList selectedItems = m_motionSetsTree->selectedItems(); outSelectedMotionSets.resize(selectedItems.size()); @@ -721,7 +711,7 @@ namespace EMStudio void MotionSetManagementWindow::OnRemoveSelectedMotionSets() { - const QList selectedItems = mMotionSetsTree->selectedItems(); + const QList selectedItems = m_motionSetsTree->selectedItems(); if (selectedItems.empty()) { return; @@ -752,7 +742,7 @@ namespace EMStudio EMotionFX::MotionSet* motionSet = EMotionFX::GetMotionManager().FindMotionSetByID(motionSetID); // in case we modified the motion set ask if the user wants to save changes it before removing it - mPlugin->SaveDirtyMotionSet(motionSet, nullptr, true, false); + m_plugin->SaveDirtyMotionSet(motionSet, nullptr, true, false); // recursively increase motions reference count RecursiveIncreaseMotionsReferenceCount(motionSet); @@ -785,14 +775,14 @@ namespace EMStudio void MotionSetManagementWindow::OnRenameSelectedMotionSet() { - MotionSetManagementRenameWindow motionSetManagementRenameWindow(this, mPlugin->GetSelectedSet()); + MotionSetManagementRenameWindow motionSetManagementRenameWindow(this, m_plugin->GetSelectedSet()); motionSetManagementRenameWindow.exec(); } void MotionSetManagementWindow::OnClearMotionSets() { // show the save dirty files window before - if (mPlugin->OnSaveDirtyMotionSets() == DirtyFileManager::CANCELED) + if (m_plugin->OnSaveDirtyMotionSets() == DirtyFileManager::CANCELED) { return; } @@ -880,7 +870,7 @@ namespace EMStudio void MotionSetManagementWindow::UpdateInterface() { - const QList selectedItems = mMotionSetsTree->selectedItems(); + const QList selectedItems = m_motionSetsTree->selectedItems(); const int numSelectedItems = selectedItems.count(); // remove and save buttons are valid if at least one item is selected @@ -915,14 +905,14 @@ namespace EMStudio { AZStd::string filename = GetMainWindow()->GetFileManager()->LoadMotionSetFileDialog(this); GetMainWindow()->activateWindow(); - mPlugin->LoadMotionSet(filename); + m_plugin->LoadMotionSet(filename); } void MotionSetManagementWindow::OnSave() { // get the selected items and the number of selected items - const QList selectedItems = mMotionSetsTree->selectedItems(); + const QList selectedItems = m_motionSetsTree->selectedItems(); const int numSelectedItems = selectedItems.count(); // at leat one item must be selected @@ -996,7 +986,7 @@ namespace EMStudio void MotionSetManagementWindow::OnSaveAs() { // get the selected items and the number of selected items - const QList selectedItems = mMotionSetsTree->selectedItems(); + const QList selectedItems = m_motionSetsTree->selectedItems(); const int numSelectedItems = selectedItems.count(); // filter to only keep the root motion sets from the selected items diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetManagementWindow.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetManagementWindow.h index 368f5bd9c7..ffe5f0f698 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetManagementWindow.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetManagementWindow.h @@ -61,10 +61,9 @@ namespace EMStudio void Accepted(); private: - EMotionFX::MotionSet* mMotionSet; - QLineEdit* mLineEdit; - QPushButton* mOKButton; - //QLabel* mErrorMsg; + EMotionFX::MotionSet* m_motionSet; + QLineEdit* m_lineEdit; + QPushButton* m_okButton; }; @@ -113,8 +112,8 @@ namespace EMStudio void contextMenuEvent(QContextMenuEvent* event) override; private: - QVBoxLayout* mVLayout = nullptr; - QTreeWidget* mMotionSetsTree = nullptr; + QVBoxLayout* m_vLayout = nullptr; + QTreeWidget* m_motionSetsTree = nullptr; QAction* m_addAction = nullptr; QAction* m_openAction = nullptr; QAction* m_saveMenuAction = nullptr; @@ -122,6 +121,6 @@ namespace EMStudio QAction* m_saveAsAction = nullptr; AzQtComponents::FilteredSearchWidget* m_searchWidget = nullptr; AZStd::string m_searchWidgetText; - MotionSetsWindowPlugin* mPlugin = nullptr; + MotionSetsWindowPlugin* m_plugin = nullptr; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetWindow.cpp index 3fd928c60c..6d16ea19b1 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetWindow.cpp @@ -124,11 +124,11 @@ namespace EMStudio RenameMotionEntryWindow::RenameMotionEntryWindow(QWidget* parent, EMotionFX::MotionSet* motionSet, const AZStd::string& motionId) : QDialog(parent) { - mMotionSet = motionSet; + m_motionSet = motionSet; m_motionId = motionId; // Build a list of unique string id values from all motion set entries. - mMotionSet->BuildIdStringList(m_existingIds); + m_motionSet->BuildIdStringList(m_existingIds); // Set the window title and minimum width. setWindowTitle("Enter new motion ID"); @@ -136,25 +136,25 @@ namespace EMStudio QVBoxLayout* layout = new QVBoxLayout(); - mLineEdit = new QLineEdit(); - connect(mLineEdit, &QLineEdit::textEdited, this, &RenameMotionEntryWindow::TextEdited); - layout->addWidget(mLineEdit); + m_lineEdit = new QLineEdit(); + connect(m_lineEdit, &QLineEdit::textEdited, this, &RenameMotionEntryWindow::TextEdited); + layout->addWidget(m_lineEdit); // Set the old motion id as text and select all so that the user can directly start typing. - mLineEdit->setText(m_motionId.c_str()); - mLineEdit->selectAll(); + m_lineEdit->setText(m_motionId.c_str()); + m_lineEdit->selectAll(); QHBoxLayout* buttonLayout = new QHBoxLayout(); - mOKButton = new QPushButton("OK"); + m_okButton = new QPushButton("OK"); QPushButton* cancelButton = new QPushButton("Cancel"); - buttonLayout->addWidget(mOKButton); + buttonLayout->addWidget(m_okButton); buttonLayout->addWidget(cancelButton); // Allow pressing the enter key as alternative to pressing the ok button for faster workflow. - mOKButton->setAutoDefault(true); - mOKButton->setDefault(true); + m_okButton->setAutoDefault(true); + m_okButton->setDefault(true); - connect(mOKButton, &QPushButton::clicked, this, &RenameMotionEntryWindow::Accepted); + connect(m_okButton, &QPushButton::clicked, this, &RenameMotionEntryWindow::Accepted); connect(cancelButton, &QPushButton::clicked, this, &RenameMotionEntryWindow::reject); layout->addLayout(buttonLayout); @@ -169,24 +169,22 @@ namespace EMStudio // Disable the ok button and put the text edit in error state in case the new motion id is either empty or does already exist in the motion set. if (newId.empty() || AZStd::find(m_existingIds.begin(), m_existingIds.end(), newId) != m_existingIds.end()) { - //mErrorMsg->setVisible(false); - mOKButton->setEnabled(false); - GetManager()->SetWidgetAsInvalidInput(mLineEdit); + m_okButton->setEnabled(false); + GetManager()->SetWidgetAsInvalidInput(m_lineEdit); return; } - //mErrorMsg->setVisible(false); - mOKButton->setEnabled(true); - mLineEdit->setStyleSheet(""); + m_okButton->setEnabled(true); + m_lineEdit->setStyleSheet(""); } void RenameMotionEntryWindow::Accepted() { AZStd::string commandString = AZStd::string::format("MotionSetAdjustMotion -motionSetID %i -idString \"%s\" -newIDString \"%s\" -updateMotionNodeStringIDs true", - mMotionSet->GetID(), + m_motionSet->GetID(), m_motionId.c_str(), - mLineEdit->text().toUtf8().data()); + m_lineEdit->text().toUtf8().data()); AZStd::string result; if (!EMStudio::GetCommandManager()->ExecuteCommand(commandString, result)) @@ -202,7 +200,7 @@ namespace EMStudio MotionSetWindow::MotionSetWindow(MotionSetsWindowPlugin* parentPlugin, QWidget* parent) : QWidget(parent) { - mPlugin = parentPlugin; + m_plugin = parentPlugin; } @@ -253,7 +251,7 @@ namespace EMStudio // left side - m_tableWidget = new MotionSetTableWidget(mPlugin, this); + m_tableWidget = new MotionSetTableWidget(m_plugin, this); m_tableWidget->setObjectName("EMFX.MotionSetWindow.TableWidget"); tableLayout->addWidget(m_tableWidget); m_tableWidget->setAlternatingRowColors(true); @@ -328,11 +326,11 @@ namespace EMStudio void MotionSetWindow::ReInit() { - EMotionFX::MotionSet* selectedSet = mPlugin->GetSelectedSet(); + EMotionFX::MotionSet* selectedSet = m_plugin->GetSelectedSet(); const size_t selectedSetIndex = EMotionFX::GetMotionManager().FindMotionSetIndex(selectedSet); if (selectedSetIndex != InvalidIndex) { - UpdateMotionSetTable(m_tableWidget, mPlugin->GetSelectedSet()); + UpdateMotionSetTable(m_tableWidget, m_plugin->GetSelectedSet()); } else { @@ -344,15 +342,11 @@ namespace EMStudio bool MotionSetWindow::AddMotion(EMotionFX::MotionSet* motionSet, EMotionFX::MotionSet::MotionEntry* motionEntry) { // check if the motion set is the one we currently see in the interface, if not there is nothing to do - if (mPlugin->GetSelectedSet() == motionSet) + if (m_plugin->GetSelectedSet() == motionSet) { InsertRow(motionSet, motionEntry, m_tableWidget, false); } - // check if the motion set is the one we currently see in the interface in the right table, if not there is nothing to do - //if (mRightSelectedSet == motionSet) - // InsertRow(motionSet, motionEntry, mMotionSetTableRight, true); - UpdateInterface(); return true; } @@ -373,7 +367,7 @@ namespace EMStudio } // Check if the motion set is the one we currently see in the interface, if not there is nothing to do. - if (mPlugin->GetSelectedSet() == motionSet) + if (m_plugin->GetSelectedSet() == motionSet) { FillRow(motionSet, motionEntry, rowIndex, m_tableWidget, false); } @@ -386,7 +380,7 @@ namespace EMStudio bool MotionSetWindow::RemoveMotion(EMotionFX::MotionSet* motionSet, EMotionFX::MotionSet::MotionEntry* motionEntry) { // Check if the motion set is the one we currently see in the interface, if not there is nothing to do. - if (mPlugin->GetSelectedSet() == motionSet) + if (m_plugin->GetSelectedSet() == motionSet) { RemoveRow(motionSet, motionEntry, m_tableWidget); } @@ -416,9 +410,9 @@ namespace EMStudio if (defaultPlayBackInfo) { // Don't blend in and out of the for previewing animations. We might only see a short bit of it for animations smaller than the blend in/out time. - defaultPlayBackInfo->mBlendInTime = 0.0f; - defaultPlayBackInfo->mBlendOutTime = 0.0f; - defaultPlayBackInfo->mFreezeAtLastFrame = (defaultPlayBackInfo->mNumLoops != EMFX_LOOPFOREVER); + defaultPlayBackInfo->m_blendInTime = 0.0f; + defaultPlayBackInfo->m_blendOutTime = 0.0f; + defaultPlayBackInfo->m_freezeAtLastFrame = (defaultPlayBackInfo->m_numLoops != EMFX_LOOPFOREVER); commandParameters = CommandSystem::CommandPlayMotion::PlayBackInfoToCommandParameters(defaultPlayBackInfo); } @@ -811,7 +805,7 @@ namespace EMStudio void MotionSetWindow::UpdateInterface() { - EMotionFX::MotionSet* motionSet = mPlugin->GetSelectedSet(); + EMotionFX::MotionSet* motionSet = m_plugin->GetSelectedSet(); const bool isEnabled = (motionSet != nullptr); m_addAction->setEnabled(isEnabled); @@ -866,7 +860,7 @@ namespace EMStudio void MotionSetWindow::OnAddNewEntry() { - EMotionFX::MotionSet* selectedSet = mPlugin->GetSelectedSet(); + EMotionFX::MotionSet* selectedSet = m_plugin->GetSelectedSet(); if (!selectedSet) { return; @@ -903,7 +897,7 @@ namespace EMStudio void MotionSetWindow::AddMotions(const AZStd::vector& filenames) { - EMotionFX::MotionSet* selectedSet = mPlugin->GetSelectedSet(); + EMotionFX::MotionSet* selectedSet = m_plugin->GetSelectedSet(); if (!selectedSet) { return; @@ -1068,7 +1062,7 @@ namespace EMStudio void MotionSetWindow::OnRemoveMotions() { - EMotionFX::MotionSet* motionSet = mPlugin->GetSelectedSet(); + EMotionFX::MotionSet* motionSet = m_plugin->GetSelectedSet(); if (!motionSet) { return; @@ -1254,7 +1248,7 @@ namespace EMStudio EMotionFX::MotionSet::MotionEntry* motionEntry = FindMotionEntry(item); // Show the entry renaming window. - RenameMotionEntryWindow window(this, mPlugin->GetSelectedSet(), motionEntry->GetId().c_str()); + RenameMotionEntryWindow window(this, m_plugin->GetSelectedSet(), motionEntry->GetId().c_str()); window.exec(); } @@ -1274,7 +1268,7 @@ namespace EMStudio void MotionSetWindow::OnUnassignMotions() { - EMotionFX::MotionSet* motionSet = mPlugin->GetSelectedSet(); + EMotionFX::MotionSet* motionSet = m_plugin->GetSelectedSet(); if (!motionSet) { return; @@ -1322,7 +1316,7 @@ namespace EMStudio void MotionSetWindow::OnClearMotions() { - EMotionFX::MotionSet* motionSet = mPlugin->GetSelectedSet(); + EMotionFX::MotionSet* motionSet = m_plugin->GetSelectedSet(); if (!motionSet) { return; @@ -1412,7 +1406,7 @@ namespace EMStudio GetRowIndices(selectedItems, rowIndices); // get the selected motion set - EMotionFX::MotionSet* motionSet = mPlugin->GetSelectedSet(); + EMotionFX::MotionSet* motionSet = m_plugin->GetSelectedSet(); // generate the motions IDs array AZStd::vector motionIDs; @@ -1442,7 +1436,7 @@ namespace EMStudio void MotionSetWindow::OnEntryDoubleClicked(QTableWidgetItem* item) { - const EMotionFX::MotionSet* motionSet = mPlugin->GetSelectedSet(); + const EMotionFX::MotionSet* motionSet = m_plugin->GetSelectedSet(); if (!motionSet) { return; @@ -1603,7 +1597,7 @@ namespace EMStudio : QTableWidget(parent) { // keep the parent plugin - mPlugin = parentPlugin; + m_plugin = parentPlugin; // enable drop only setAcceptDrops(true); @@ -1620,7 +1614,7 @@ namespace EMStudio void MotionSetTableWidget::dropEvent(QDropEvent* event) { - mPlugin->GetMotionSetWindow()->dropEvent(event); + m_plugin->GetMotionSetWindow()->dropEvent(event); } @@ -1639,7 +1633,7 @@ namespace EMStudio // return the mime data QMimeData* MotionSetTableWidget::mimeData(const QList items) const { - EMotionFX::MotionSet* motionSet = mPlugin->GetSelectedSet(); + EMotionFX::MotionSet* motionSet = m_plugin->GetSelectedSet(); if (motionSet == nullptr) { return nullptr; @@ -1682,13 +1676,13 @@ namespace EMStudio : QDialog(parent) { // save the motion set and the motion IDs - mMotionSet = motionSet; - mMotionIDs = motionIDs; + m_motionSet = motionSet; + m_motionIDs = motionIDs; // Reserve space. - mValids.reserve(mMotionIDs.size()); - mMotionToModifiedMap.reserve(mMotionIDs.size()); - mModifiedMotionIDs.reserve(motionSet->GetNumMotionEntries()); + m_valids.reserve(m_motionIDs.size()); + m_motionToModifiedMap.reserve(m_motionIDs.size()); + m_modifiedMotionIDs.reserve(motionSet->GetNumMotionEntries()); // set the window title setWindowTitle("Batch Edit Motion IDs"); @@ -1701,113 +1695,113 @@ namespace EMStudio spacerWidget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); // create the combobox - mComboBox = new QComboBox(); - mComboBox->addItem("Replace All"); - mComboBox->addItem("Replace First"); - mComboBox->addItem("Replace Last"); + m_comboBox = new QComboBox(); + m_comboBox->addItem("Replace All"); + m_comboBox->addItem("Replace First"); + m_comboBox->addItem("Replace Last"); // connect the combobox - connect(mComboBox, static_cast(&QComboBox::currentIndexChanged), this, &MotionEditStringIDWindow::CurrentIndexChanged); + connect(m_comboBox, static_cast(&QComboBox::currentIndexChanged), this, &MotionEditStringIDWindow::CurrentIndexChanged); // create the string line edits - mStringALineEdit = new QLineEdit(); - mStringBLineEdit = new QLineEdit(); + m_stringALineEdit = new QLineEdit(); + m_stringBLineEdit = new QLineEdit(); // connect the line edit - connect(mStringALineEdit, &QLineEdit::textChanged, this, &MotionEditStringIDWindow::StringABChanged); - connect(mStringBLineEdit, &QLineEdit::textChanged, this, &MotionEditStringIDWindow::StringABChanged); + connect(m_stringALineEdit, &QLineEdit::textChanged, this, &MotionEditStringIDWindow::StringABChanged); + connect(m_stringBLineEdit, &QLineEdit::textChanged, this, &MotionEditStringIDWindow::StringABChanged); // add the operation layout QHBoxLayout* operationLayout = new QHBoxLayout(); operationLayout->addWidget(new QLabel("Operation:")); - operationLayout->addWidget(mComboBox); + operationLayout->addWidget(m_comboBox); operationLayout->addWidget(spacerWidget); operationLayout->addWidget(new QLabel("StringA:")); - operationLayout->addWidget(mStringALineEdit); + operationLayout->addWidget(m_stringALineEdit); operationLayout->addWidget(new QLabel("StringB:")); - operationLayout->addWidget(mStringBLineEdit); + operationLayout->addWidget(m_stringBLineEdit); layout->addLayout(operationLayout); // create the table widget - mTableWidget = new QTableWidget(); - mTableWidget->setAlternatingRowColors(true); - mTableWidget->setGridStyle(Qt::SolidLine); - mTableWidget->setSelectionBehavior(QAbstractItemView::SelectRows); - mTableWidget->setSelectionMode(QAbstractItemView::SingleSelection); - mTableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers); + m_tableWidget = new QTableWidget(); + m_tableWidget->setAlternatingRowColors(true); + m_tableWidget->setGridStyle(Qt::SolidLine); + m_tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows); + m_tableWidget->setSelectionMode(QAbstractItemView::SingleSelection); + m_tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers); // set the table widget columns - mTableWidget->setColumnCount(2); + m_tableWidget->setColumnCount(2); QStringList headerLabels; headerLabels.append("Before"); headerLabels.append("After"); - mTableWidget->setHorizontalHeaderLabels(headerLabels); - mTableWidget->horizontalHeader()->setStretchLastSection(true); - mTableWidget->horizontalHeader()->setDefaultAlignment(Qt::AlignLeft); - mTableWidget->horizontalHeader()->setSortIndicator(0, Qt::AscendingOrder); + m_tableWidget->setHorizontalHeaderLabels(headerLabels); + m_tableWidget->horizontalHeader()->setStretchLastSection(true); + m_tableWidget->horizontalHeader()->setDefaultAlignment(Qt::AlignLeft); + m_tableWidget->horizontalHeader()->setSortIndicator(0, Qt::AscendingOrder); // Set the row count - const size_t numMotionIDs = mMotionIDs.size(); - mTableWidget->setRowCount(static_cast(numMotionIDs)); + const size_t numMotionIDs = m_motionIDs.size(); + m_tableWidget->setRowCount(static_cast(numMotionIDs)); // disable the sorting - mTableWidget->setSortingEnabled(false); + m_tableWidget->setSortingEnabled(false); // initialize the table for (size_t i = 0; i < numMotionIDs; ++i) { // create the before and after table widget items - QTableWidgetItem* beforeTableWidgetItem = new QTableWidgetItem(mMotionIDs[i].c_str()); - QTableWidgetItem* afterTableWidgetItem = new QTableWidgetItem(mMotionIDs[i].c_str()); + QTableWidgetItem* beforeTableWidgetItem = new QTableWidgetItem(m_motionIDs[i].c_str()); + QTableWidgetItem* afterTableWidgetItem = new QTableWidgetItem(m_motionIDs[i].c_str()); // set the text of the row const int row = static_cast(i); - mTableWidget->setItem(row, 0, beforeTableWidgetItem); - mTableWidget->setItem(row, 1, afterTableWidgetItem); + m_tableWidget->setItem(row, 0, beforeTableWidgetItem); + m_tableWidget->setItem(row, 1, afterTableWidgetItem); } - mTableWidget->setSortingEnabled(true); - mTableWidget->resizeColumnToContents(0); - mTableWidget->setCornerButtonEnabled(false); + m_tableWidget->setSortingEnabled(true); + m_tableWidget->resizeColumnToContents(0); + m_tableWidget->setCornerButtonEnabled(false); - layout->addWidget(mTableWidget); + layout->addWidget(m_tableWidget); // create the num motion IDs label // this label never change, it's the total of motion ID in the table - mNumMotionIDsLabel = new QLabel(); - mNumMotionIDsLabel->setAlignment(Qt::AlignLeft); - mNumMotionIDsLabel->setText(QString("Number of motion IDs: %1").arg(numMotionIDs)); + m_numMotionIDsLabel = new QLabel(); + m_numMotionIDsLabel->setAlignment(Qt::AlignLeft); + m_numMotionIDsLabel->setText(QString("Number of motion IDs: %1").arg(numMotionIDs)); // create the num modified IDs label - mNumModifiedIDsLabel = new QLabel(); - mNumModifiedIDsLabel->setAlignment(Qt::AlignCenter); - mNumModifiedIDsLabel->setText("Number of modified IDs: 0"); + m_numModifiedIDsLabel = new QLabel(); + m_numModifiedIDsLabel->setAlignment(Qt::AlignCenter); + m_numModifiedIDsLabel->setText("Number of modified IDs: 0"); // create the num duplicate IDs label - mNumDuplicateIDsLabel = new QLabel(); - mNumDuplicateIDsLabel->setAlignment(Qt::AlignRight); - mNumDuplicateIDsLabel->setText("Number of duplicate IDs: 0"); + m_numDuplicateIDsLabel = new QLabel(); + m_numDuplicateIDsLabel->setAlignment(Qt::AlignRight); + m_numDuplicateIDsLabel->setText("Number of duplicate IDs: 0"); // add the stats layout QHBoxLayout* statsLayout = new QHBoxLayout(); - statsLayout->addWidget(mNumMotionIDsLabel); - statsLayout->addWidget(mNumModifiedIDsLabel); - statsLayout->addWidget(mNumDuplicateIDsLabel); + statsLayout->addWidget(m_numMotionIDsLabel); + statsLayout->addWidget(m_numModifiedIDsLabel); + statsLayout->addWidget(m_numDuplicateIDsLabel); layout->addLayout(statsLayout); // add the bottom buttons QHBoxLayout* buttonLayout = new QHBoxLayout(); - mApplyButton = new QPushButton("Apply"); + m_applyButton = new QPushButton("Apply"); QPushButton* closeButton = new QPushButton("Close"); - buttonLayout->addWidget(mApplyButton); + buttonLayout->addWidget(m_applyButton); buttonLayout->addWidget(closeButton); layout->addLayout(buttonLayout); // apply button is disabled because nothing is changed - mApplyButton->setEnabled(false); + m_applyButton->setEnabled(false); // connect the buttons - connect(mApplyButton, &QPushButton::clicked, this, &MotionEditStringIDWindow::Accepted); + connect(m_applyButton, &QPushButton::clicked, this, &MotionEditStringIDWindow::Accepted); connect(closeButton, &QPushButton::clicked, this, &MotionEditStringIDWindow::reject); setLayout(layout); @@ -1823,13 +1817,13 @@ namespace EMStudio // add each command AZStd::string commandString; - for (size_t validID : mValids) + for (size_t validID : m_valids) { // get the motion ID and the modified ID - AZStd::string& motionID = mMotionIDs[validID]; - const AZStd::string& modifiedID = mModifiedMotionIDs[mMotionToModifiedMap[validID]]; + AZStd::string& motionID = m_motionIDs[validID]; + const AZStd::string& modifiedID = m_modifiedMotionIDs[m_motionToModifiedMap[validID]]; - commandString = AZStd::string::format("MotionSetAdjustMotion -motionSetID %i -idString \"%s\" -newIDString \"%s\" -updateMotionNodeStringIDs true", mMotionSet->GetID(), motionID.c_str(), modifiedID.c_str()); + commandString = AZStd::string::format("MotionSetAdjustMotion -motionSetID %i -idString \"%s\" -newIDString \"%s\" -updateMotionNodeStringIDs true", m_motionSet->GetID(), motionID.c_str(), modifiedID.c_str()); motionID = modifiedID; // add the command in the group @@ -1844,46 +1838,46 @@ namespace EMStudio } // block signals for the reset - mStringALineEdit->blockSignals(true); - mStringBLineEdit->blockSignals(true); + m_stringALineEdit->blockSignals(true); + m_stringBLineEdit->blockSignals(true); // reset the string line edits - mStringALineEdit->setText(""); - mStringBLineEdit->setText(""); + m_stringALineEdit->setText(""); + m_stringBLineEdit->setText(""); // enable signals after the reset - mStringALineEdit->blockSignals(false); - mStringBLineEdit->blockSignals(false); + m_stringALineEdit->blockSignals(false); + m_stringBLineEdit->blockSignals(false); // disable the sorting - mTableWidget->setSortingEnabled(false); + m_tableWidget->setSortingEnabled(false); // set the new table using modified motion IDs - const size_t numMotionIDs = mMotionIDs.size(); + const size_t numMotionIDs = m_motionIDs.size(); for (size_t i = 0; i < numMotionIDs; ++i) { // create the before and after table widget items - QTableWidgetItem* beforeTableWidgetItem = new QTableWidgetItem(mMotionIDs[i].c_str()); - QTableWidgetItem* afterTableWidgetItem = new QTableWidgetItem(mMotionIDs[i].c_str()); + QTableWidgetItem* beforeTableWidgetItem = new QTableWidgetItem(m_motionIDs[i].c_str()); + QTableWidgetItem* afterTableWidgetItem = new QTableWidgetItem(m_motionIDs[i].c_str()); // set the text of the row const int row = static_cast(i); - mTableWidget->setItem(row, 0, beforeTableWidgetItem); - mTableWidget->setItem(row, 1, afterTableWidgetItem); + m_tableWidget->setItem(row, 0, beforeTableWidgetItem); + m_tableWidget->setItem(row, 1, afterTableWidgetItem); } // enable the sorting - mTableWidget->setSortingEnabled(true); + m_tableWidget->setSortingEnabled(true); // resize before column - mTableWidget->resizeColumnToContents(0); + m_tableWidget->resizeColumnToContents(0); // reset the stats - mNumModifiedIDsLabel->setText("Number of modified IDs: 0"); - mNumDuplicateIDsLabel->setText("Number of duplicate IDs: 0"); + m_numModifiedIDsLabel->setText("Number of modified IDs: 0"); + m_numDuplicateIDsLabel->setText("Number of duplicate IDs: 0"); // apply button is disabled because nothing is changed - mApplyButton->setEnabled(false); + m_applyButton->setEnabled(false); } @@ -1904,10 +1898,10 @@ namespace EMStudio void MotionEditStringIDWindow::UpdateTableAndButton() { // get the number of motion IDs - const size_t numMotionIDs = mMotionIDs.size(); + const size_t numMotionIDs = m_motionIDs.size(); // Remember the selected motion IDs so we can restore selection after swapping the table items. - const QList selectedItems = mTableWidget->selectedItems(); + const QList selectedItems = m_tableWidget->selectedItems(); const int numSelectedItems = selectedItems.size(); QVector selectedMotionIds(numSelectedItems); for (int i = 0; i < numSelectedItems; ++i) @@ -1916,59 +1910,59 @@ namespace EMStudio } // special case where the string A and B are empty, nothing is replaced - if ((mStringALineEdit->text().isEmpty()) && (mStringBLineEdit->text().isEmpty())) + if ((m_stringALineEdit->text().isEmpty()) && (m_stringBLineEdit->text().isEmpty())) { // disable the sorting - mTableWidget->setSortingEnabled(false); + m_tableWidget->setSortingEnabled(false); // reset the table for (size_t i = 0; i < numMotionIDs; ++i) { // create the before and after table widget items - QTableWidgetItem* beforeTableWidgetItem = new QTableWidgetItem(mMotionIDs[i].c_str()); - QTableWidgetItem* afterTableWidgetItem = new QTableWidgetItem(mMotionIDs[i].c_str()); + QTableWidgetItem* beforeTableWidgetItem = new QTableWidgetItem(m_motionIDs[i].c_str()); + QTableWidgetItem* afterTableWidgetItem = new QTableWidgetItem(m_motionIDs[i].c_str()); // set the text of the row const int row = static_cast(i); - mTableWidget->setItem(row, 0, beforeTableWidgetItem); - mTableWidget->setItem(row, 1, afterTableWidgetItem); + m_tableWidget->setItem(row, 0, beforeTableWidgetItem); + m_tableWidget->setItem(row, 1, afterTableWidgetItem); } // enable the sorting - mTableWidget->setSortingEnabled(true); + m_tableWidget->setSortingEnabled(true); // reset the stats - mNumModifiedIDsLabel->setText("Number of modified IDs: 0"); - mNumDuplicateIDsLabel->setText("Number of duplicate IDs: 0"); + m_numModifiedIDsLabel->setText("Number of modified IDs: 0"); + m_numDuplicateIDsLabel->setText("Number of duplicate IDs: 0"); // apply button is disabled because nothing is changed - mApplyButton->setEnabled(false); + m_applyButton->setEnabled(false); // stop here return; } // Clear the arrays but keep the memory to avoid alloc. - mValids.clear(); - mModifiedMotionIDs.clear(); - mMotionToModifiedMap.clear(); + m_valids.clear(); + m_modifiedMotionIDs.clear(); + m_motionToModifiedMap.clear(); // Copy all motion IDs from the motion set in the modified array. - const EMotionFX::MotionSet::MotionEntries& motionEntries = mMotionSet->GetMotionEntries(); + const EMotionFX::MotionSet::MotionEntries& motionEntries = m_motionSet->GetMotionEntries(); for (const auto& item : motionEntries) { const EMotionFX::MotionSet::MotionEntry* motionEntry = item.second; - mModifiedMotionIDs.push_back(motionEntry->GetId().c_str()); + m_modifiedMotionIDs.push_back(motionEntry->GetId().c_str()); } // Modify each ID using the operation in the modified array. AZStd::string newMotionID; AZStd::string tempString; - for (const AZStd::string& motionID : mMotionIDs) + for (const AZStd::string& motionID : m_motionIDs) { // 0=Replace All, 1=Replace First, 2=Replace Last - const int operationMode = mComboBox->currentIndex(); + const int operationMode = m_comboBox->currentIndex(); // compute the new text switch (operationMode) @@ -1976,7 +1970,7 @@ namespace EMStudio case 0: { tempString = motionID.c_str(); - AzFramework::StringFunc::Replace(tempString, mStringALineEdit->text().toUtf8().data(), mStringBLineEdit->text().toUtf8().data(), true /* case sensitive */); + AzFramework::StringFunc::Replace(tempString, m_stringALineEdit->text().toUtf8().data(), m_stringBLineEdit->text().toUtf8().data(), true /* case sensitive */); newMotionID = tempString.c_str(); break; } @@ -1984,7 +1978,7 @@ namespace EMStudio case 1: { tempString = motionID.c_str(); - AzFramework::StringFunc::Replace(tempString, mStringALineEdit->text().toUtf8().data(), mStringBLineEdit->text().toUtf8().data(), true /* case sensitive */, true /* replace first */, false /* replace last */); + AzFramework::StringFunc::Replace(tempString, m_stringALineEdit->text().toUtf8().data(), m_stringBLineEdit->text().toUtf8().data(), true /* case sensitive */, true /* replace first */, false /* replace last */); newMotionID = tempString.c_str(); break; } @@ -1992,21 +1986,21 @@ namespace EMStudio case 2: { tempString = motionID.c_str(); - AzFramework::StringFunc::Replace(tempString, mStringALineEdit->text().toUtf8().data(), mStringBLineEdit->text().toUtf8().data(), true /* case sensitive */, false /* replace first */, true /* replace last */); + AzFramework::StringFunc::Replace(tempString, m_stringALineEdit->text().toUtf8().data(), m_stringBLineEdit->text().toUtf8().data(), true /* case sensitive */, false /* replace first */, true /* replace last */); newMotionID = tempString.c_str(); break; } } // change the value in the array and add the mapping motion to modified - auto iterator = AZStd::find(mModifiedMotionIDs.begin(), mModifiedMotionIDs.end(), motionID); - const size_t modifiedIndex = iterator - mModifiedMotionIDs.begin(); - mModifiedMotionIDs[modifiedIndex] = newMotionID; - mMotionToModifiedMap.push_back(modifiedIndex); + auto iterator = AZStd::find(m_modifiedMotionIDs.begin(), m_modifiedMotionIDs.end(), motionID); + const size_t modifiedIndex = iterator - m_modifiedMotionIDs.begin(); + m_modifiedMotionIDs[modifiedIndex] = newMotionID; + m_motionToModifiedMap.push_back(modifiedIndex); } // disable the sorting - mTableWidget->setSortingEnabled(false); + m_tableWidget->setSortingEnabled(false); // found flags size_t numDuplicateFound = 0; @@ -2015,18 +2009,18 @@ namespace EMStudio for (size_t i = 0; i < numMotionIDs; ++i) { // find the index in the motion set - const AZStd::string& modifiedID = mModifiedMotionIDs[mMotionToModifiedMap[i]]; + const AZStd::string& modifiedID = m_modifiedMotionIDs[m_motionToModifiedMap[i]]; // create the before and after table widget items - QTableWidgetItem* beforeTableWidgetItem = new QTableWidgetItem(mMotionIDs[i].c_str()); + QTableWidgetItem* beforeTableWidgetItem = new QTableWidgetItem(m_motionIDs[i].c_str()); QTableWidgetItem* afterTableWidgetItem = new QTableWidgetItem(modifiedID.c_str()); // find duplicate size_t itemFoundCounter = 0; - const size_t numMotionEntries = mMotionSet->GetNumMotionEntries(); + const size_t numMotionEntries = m_motionSet->GetNumMotionEntries(); for (size_t k = 0; k < numMotionEntries; ++k) { - if (mModifiedMotionIDs[k] == modifiedID) + if (m_modifiedMotionIDs[k] == modifiedID) { ++itemFoundCounter; if (itemFoundCounter > 1) @@ -2045,51 +2039,51 @@ namespace EMStudio } else { - if (modifiedID != mMotionIDs[i]) + if (modifiedID != m_motionIDs[i]) { // set the row green beforeTableWidgetItem->setForeground(Qt::green); afterTableWidgetItem->setForeground(Qt::green); // add a valid - mValids.push_back(i); + m_valids.push_back(i); } } // set the text of the row - mTableWidget->setItem(aznumeric_caster(i), 0, beforeTableWidgetItem); - mTableWidget->setItem(aznumeric_caster(i), 1, afterTableWidgetItem); + m_tableWidget->setItem(aznumeric_caster(i), 0, beforeTableWidgetItem); + m_tableWidget->setItem(aznumeric_caster(i), 1, afterTableWidgetItem); } // enable the sorting - mTableWidget->setSortingEnabled(true); + m_tableWidget->setSortingEnabled(true); // update the num modified label - mNumModifiedIDsLabel->setText(QString("Number of modified IDs: %1").arg(mValids.size())); + m_numModifiedIDsLabel->setText(QString("Number of modified IDs: %1").arg(m_valids.size())); // update the num duplicate label // the number is in red if at least one found if (numDuplicateFound > 0) { - mNumDuplicateIDsLabel->setText(QString("Number of duplicate IDs: %1").arg(numDuplicateFound)); + m_numDuplicateIDsLabel->setText(QString("Number of duplicate IDs: %1").arg(numDuplicateFound)); } else { - mNumDuplicateIDsLabel->setText("Number of duplicate IDs: 0"); + m_numDuplicateIDsLabel->setText("Number of duplicate IDs: 0"); } // enable or disable the apply button - mApplyButton->setEnabled((!mValids.empty()) && (numDuplicateFound == 0)); + m_applyButton->setEnabled((!m_valids.empty()) && (numDuplicateFound == 0)); // Reselect the remembered motions. - mTableWidget->clearSelection(); - const int rowCount = mTableWidget->rowCount(); + m_tableWidget->clearSelection(); + const int rowCount = m_tableWidget->rowCount(); for (int i = 0; i < rowCount; ++i) { - const QTableWidgetItem* item = mTableWidget->item(i, 0); + const QTableWidgetItem* item = m_tableWidget->item(i, 0); if (AZStd::find(selectedMotionIds.begin(), selectedMotionIds.end(), item->text()) != selectedMotionIds.end()) { - mTableWidget->selectRow(i); + m_tableWidget->selectRow(i); } } } @@ -2102,7 +2096,7 @@ namespace EMStudio return nullptr; } - const EMotionFX::MotionSet* motionSet = mPlugin->GetSelectedSet(); + const EMotionFX::MotionSet* motionSet = m_plugin->GetSelectedSet(); if (!motionSet) { return nullptr; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetWindow.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetWindow.h index 33b3828e5a..8c1fe04662 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetWindow.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetWindow.h @@ -62,11 +62,11 @@ namespace EMStudio void Accepted(); private: - EMotionFX::MotionSet* mMotionSet; + EMotionFX::MotionSet* m_motionSet; AZStd::vector m_existingIds; AZStd::string m_motionId; - QLineEdit* mLineEdit; - QPushButton* mOKButton; + QLineEdit* m_lineEdit; + QPushButton* m_okButton; }; @@ -88,19 +88,19 @@ namespace EMStudio void UpdateTableAndButton(); private: - EMotionFX::MotionSet* mMotionSet; - AZStd::vector mMotionIDs; - AZStd::vector mModifiedMotionIDs; - AZStd::vector mMotionToModifiedMap; - AZStd::vector mValids; - QTableWidget* mTableWidget; - QLineEdit* mStringALineEdit; - QLineEdit* mStringBLineEdit; - QPushButton* mApplyButton; - QLabel* mNumMotionIDsLabel; - QLabel* mNumModifiedIDsLabel; - QLabel* mNumDuplicateIDsLabel; - QComboBox* mComboBox; + EMotionFX::MotionSet* m_motionSet; + AZStd::vector m_motionIDs; + AZStd::vector m_modifiedMotionIDs; + AZStd::vector m_motionToModifiedMap; + AZStd::vector m_valids; + QTableWidget* m_tableWidget; + QLineEdit* m_stringALineEdit; + QLineEdit* m_stringBLineEdit; + QPushButton* m_applyButton; + QLabel* m_numMotionIDsLabel; + QLabel* m_numModifiedIDsLabel; + QLabel* m_numDuplicateIDsLabel; + QComboBox* m_comboBox; }; @@ -124,7 +124,7 @@ namespace EMStudio void dragEnterEvent(QDragEnterEvent* event) override; void dragMoveEvent(QDragMoveEvent* event) override; - MotionSetsWindowPlugin* mPlugin; + MotionSetsWindowPlugin* m_plugin; }; @@ -187,7 +187,7 @@ namespace EMStudio size_t CalcNumMotionEntriesUsingMotionExcluding(const AZStd::string& motionFilename, EMotionFX::MotionSet* excludedMotionSet); private: - QVBoxLayout* mVLayout = nullptr; + QVBoxLayout* m_vLayout = nullptr; MotionSetTableWidget* m_tableWidget = nullptr; QAction* m_addAction = nullptr; @@ -196,6 +196,6 @@ namespace EMStudio AzQtComponents::FilteredSearchWidget* m_searchWidget = nullptr; AZStd::string m_searchWidgetText; - MotionSetsWindowPlugin* mPlugin = nullptr; + MotionSetsWindowPlugin* m_plugin = nullptr; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetsWindowPlugin.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetsWindowPlugin.cpp index 3860edd009..bb84dee35d 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetsWindowPlugin.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetsWindowPlugin.cpp @@ -42,7 +42,7 @@ namespace EMStudio public: SaveDirtyMotionSetFilesCallback(MotionSetsWindowPlugin* plugin) - : SaveDirtyFilesCallback() { mPlugin = plugin; } + : SaveDirtyFilesCallback() { m_plugin = plugin; } ~SaveDirtyMotionSetFilesCallback() {} enum @@ -79,7 +79,7 @@ namespace EMStudio // add the link to the actual object ObjectPointer objPointer; - objPointer.mMotionSet = motionSet; + objPointer.m_motionSet = motionSet; outObjects->push_back(objPointer); } } @@ -94,13 +94,13 @@ namespace EMStudio { // get the current object pointer and skip directly if the type check fails ObjectPointer objPointer = objects[i]; - if (objPointer.mMotionSet == nullptr) + if (objPointer.m_motionSet == nullptr) { continue; } - EMotionFX::MotionSet* motionSet = objPointer.mMotionSet; - if (mPlugin->SaveDirtyMotionSet(motionSet, commandGroup, false) == DirtyFileManager::CANCELED) + EMotionFX::MotionSet* motionSet = objPointer.m_motionSet; + if (m_plugin->SaveDirtyMotionSet(motionSet, commandGroup, false) == DirtyFileManager::CANCELED) { return DirtyFileManager::CANCELED; } @@ -117,7 +117,7 @@ namespace EMStudio } private: - MotionSetsWindowPlugin* mPlugin; + MotionSetsWindowPlugin* m_plugin; }; @@ -125,43 +125,42 @@ namespace EMStudio MotionSetsWindowPlugin::MotionSetsWindowPlugin() : EMStudio::DockWidgetPlugin() { - mDialogStack = nullptr; - mSelectedSet = nullptr; - mCreateMotionSetCallback = nullptr; + m_dialogStack = nullptr; + m_selectedSet = nullptr; + m_createMotionSetCallback = nullptr; m_reinitCallback = nullptr; - mAdjustMotionSetCallback = nullptr; - mMotionSetAddMotionCallback = nullptr; - mMotionSetRemoveMotionCallback = nullptr; - mMotionSetAdjustMotionCallback = nullptr; - mLoadMotionSetCallback = nullptr; - //mStringIDWindow = nullptr; - mMotionSetManagementWindow = nullptr; - mMotionSetWindow = nullptr; - mDirtyFilesCallback = nullptr; + m_adjustMotionSetCallback = nullptr; + m_motionSetAddMotionCallback = nullptr; + m_motionSetRemoveMotionCallback = nullptr; + m_motionSetAdjustMotionCallback = nullptr; + m_loadMotionSetCallback = nullptr; + m_motionSetManagementWindow = nullptr; + m_motionSetWindow = nullptr; + m_dirtyFilesCallback = nullptr; } // destructor MotionSetsWindowPlugin::~MotionSetsWindowPlugin() { - GetCommandManager()->RemoveCommandCallback(mCreateMotionSetCallback, false); + GetCommandManager()->RemoveCommandCallback(m_createMotionSetCallback, false); GetCommandManager()->RemoveCommandCallback(m_reinitCallback, false); - GetCommandManager()->RemoveCommandCallback(mAdjustMotionSetCallback, false); - GetCommandManager()->RemoveCommandCallback(mMotionSetAddMotionCallback, false); - GetCommandManager()->RemoveCommandCallback(mMotionSetRemoveMotionCallback, false); - GetCommandManager()->RemoveCommandCallback(mMotionSetAdjustMotionCallback, false); - GetCommandManager()->RemoveCommandCallback(mLoadMotionSetCallback, false); + GetCommandManager()->RemoveCommandCallback(m_adjustMotionSetCallback, false); + GetCommandManager()->RemoveCommandCallback(m_motionSetAddMotionCallback, false); + GetCommandManager()->RemoveCommandCallback(m_motionSetRemoveMotionCallback, false); + GetCommandManager()->RemoveCommandCallback(m_motionSetAdjustMotionCallback, false); + GetCommandManager()->RemoveCommandCallback(m_loadMotionSetCallback, false); - delete mCreateMotionSetCallback; + delete m_createMotionSetCallback; delete m_reinitCallback; - delete mAdjustMotionSetCallback; - delete mMotionSetAddMotionCallback; - delete mMotionSetRemoveMotionCallback; - delete mMotionSetAdjustMotionCallback; - delete mLoadMotionSetCallback; + delete m_adjustMotionSetCallback; + delete m_motionSetAddMotionCallback; + delete m_motionSetRemoveMotionCallback; + delete m_motionSetAdjustMotionCallback; + delete m_loadMotionSetCallback; - GetMainWindow()->GetDirtyFileManager()->RemoveCallback(mDirtyFilesCallback, false); - delete mDirtyFilesCallback; + GetMainWindow()->GetDirtyFileManager()->RemoveCallback(m_dirtyFilesCallback, false); + delete m_dirtyFilesCallback; } @@ -176,49 +175,49 @@ namespace EMStudio // init after the parent dock window has been created bool MotionSetsWindowPlugin::Init() { - mCreateMotionSetCallback = new CommandCreateMotionSetCallback(false); + m_createMotionSetCallback = new CommandCreateMotionSetCallback(false); m_reinitCallback = new CommandReinitCallback(false); - mAdjustMotionSetCallback = new CommandAdjustMotionSetCallback(false); - mMotionSetAddMotionCallback = new CommandMotionSetAddMotionCallback(false); - mMotionSetRemoveMotionCallback = new CommandMotionSetRemoveMotionCallback(false); - mMotionSetAdjustMotionCallback = new CommandMotionSetAdjustMotionCallback(false); - mLoadMotionSetCallback = new CommandLoadMotionSetCallback(false); + m_adjustMotionSetCallback = new CommandAdjustMotionSetCallback(false); + m_motionSetAddMotionCallback = new CommandMotionSetAddMotionCallback(false); + m_motionSetRemoveMotionCallback = new CommandMotionSetRemoveMotionCallback(false); + m_motionSetAdjustMotionCallback = new CommandMotionSetAdjustMotionCallback(false); + m_loadMotionSetCallback = new CommandLoadMotionSetCallback(false); - GetCommandManager()->RegisterCommandCallback("CreateMotionSet", mCreateMotionSetCallback); + GetCommandManager()->RegisterCommandCallback("CreateMotionSet", m_createMotionSetCallback); GetCommandManager()->RegisterCommandCallback("RemoveMotionSet", m_reinitCallback); - GetCommandManager()->RegisterCommandCallback("AdjustMotionSet", mAdjustMotionSetCallback); + GetCommandManager()->RegisterCommandCallback("AdjustMotionSet", m_adjustMotionSetCallback); - GetCommandManager()->RegisterCommandCallback("MotionSetAddMotion", mMotionSetAddMotionCallback); - GetCommandManager()->RegisterCommandCallback("MotionSetRemoveMotion", mMotionSetRemoveMotionCallback); - GetCommandManager()->RegisterCommandCallback("MotionSetAdjustMotion", mMotionSetAdjustMotionCallback); - GetCommandManager()->RegisterCommandCallback("LoadMotionSet", mLoadMotionSetCallback); + GetCommandManager()->RegisterCommandCallback("MotionSetAddMotion", m_motionSetAddMotionCallback); + GetCommandManager()->RegisterCommandCallback("MotionSetRemoveMotion", m_motionSetRemoveMotionCallback); + GetCommandManager()->RegisterCommandCallback("MotionSetAdjustMotion", m_motionSetAdjustMotionCallback); + GetCommandManager()->RegisterCommandCallback("LoadMotionSet", m_loadMotionSetCallback); GetCommandManager()->RegisterCommandCallback("RemoveMotion", m_reinitCallback); // create the dialog stack - assert(mDialogStack == nullptr); - mDialogStack = new MysticQt::DialogStack(mDock); - mDock->setWidget(mDialogStack); + assert(m_dialogStack == nullptr); + m_dialogStack = new MysticQt::DialogStack(m_dock); + m_dock->setWidget(m_dialogStack); // connect the window activation signal to refresh if reactivated - connect(mDock, &QDockWidget::visibilityChanged, this, &MotionSetsWindowPlugin::WindowReInit); + connect(m_dock, &QDockWidget::visibilityChanged, this, &MotionSetsWindowPlugin::WindowReInit); // create the set management window - mMotionSetManagementWindow = new MotionSetManagementWindow(this, mDialogStack); - mMotionSetManagementWindow->Init(); - mDialogStack->Add(mMotionSetManagementWindow, "Motion Set Management", false, true, true, false); + m_motionSetManagementWindow = new MotionSetManagementWindow(this, m_dialogStack); + m_motionSetManagementWindow->Init(); + m_dialogStack->Add(m_motionSetManagementWindow, "Motion Set Management", false, true, true, false); // create the motion set properties window - mMotionSetWindow = new MotionSetWindow(this, mDialogStack); - mMotionSetWindow->Init(); - mDialogStack->Add(mMotionSetWindow, "Motion Set", false, true); + m_motionSetWindow = new MotionSetWindow(this, m_dialogStack); + m_motionSetWindow->Init(); + m_dialogStack->Add(m_motionSetWindow, "Motion Set", false, true); ReInit(); SetSelectedSet(nullptr); // initialize the dirty files callback - mDirtyFilesCallback = new SaveDirtyMotionSetFilesCallback(this); - GetMainWindow()->GetDirtyFileManager()->AddCallback(mDirtyFilesCallback); + m_dirtyFilesCallback = new SaveDirtyMotionSetFilesCallback(this); + GetMainWindow()->GetDirtyFileManager()->AddCallback(m_dirtyFilesCallback); return true; } @@ -226,26 +225,26 @@ namespace EMStudio EMotionFX::MotionSet* MotionSetsWindowPlugin::GetSelectedSet() const { - if (EMotionFX::GetMotionManager().FindMotionSetIndex(mSelectedSet) == InvalidIndex) + if (EMotionFX::GetMotionManager().FindMotionSetIndex(m_selectedSet) == InvalidIndex) { return nullptr; } - return mSelectedSet; + return m_selectedSet; } void MotionSetsWindowPlugin::ReInit() { // Validate existence of selected motion set and reset selection in case selection is invalid. - if (EMotionFX::GetMotionManager().FindMotionSetIndex(mSelectedSet) == InvalidIndex) + if (EMotionFX::GetMotionManager().FindMotionSetIndex(m_selectedSet) == InvalidIndex) { - mSelectedSet = nullptr; + m_selectedSet = nullptr; } - SetSelectedSet(mSelectedSet); - mMotionSetManagementWindow->ReInit(); - mMotionSetWindow->ReInit(); + SetSelectedSet(m_selectedSet); + m_motionSetManagementWindow->ReInit(); + m_motionSetWindow->ReInit(); } @@ -334,16 +333,16 @@ namespace EMStudio void MotionSetsWindowPlugin::SetSelectedSet(EMotionFX::MotionSet* motionSet) { - mSelectedSet = motionSet; + m_selectedSet = motionSet; if (motionSet) { - mMotionSetManagementWindow->SelectItemsById(motionSet->GetID()); + m_motionSetManagementWindow->SelectItemsById(motionSet->GetID()); } - mMotionSetManagementWindow->ReInit(); - mMotionSetManagementWindow->UpdateInterface(); - mMotionSetWindow->ReInit(); - mMotionSetWindow->UpdateInterface(); + m_motionSetManagementWindow->ReInit(); + m_motionSetManagementWindow->UpdateInterface(); + m_motionSetWindow->ReInit(); + m_motionSetWindow->UpdateInterface(); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetsWindowPlugin.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetsWindowPlugin.h index 4b7b16f5f5..459118c831 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetsWindowPlugin.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetsWindowPlugin.h @@ -72,8 +72,8 @@ namespace EMStudio void SetSelectedSet(EMotionFX::MotionSet* motionSet); int SaveDirtyMotionSet(EMotionFX::MotionSet* motionSet, MCore::CommandGroup* commandGroup, bool askBeforeSaving, bool showCancelButton = true); - MotionSetManagementWindow* GetManagementWindow() { return mMotionSetManagementWindow; } - MotionSetWindow* GetMotionSetWindow() { return mMotionSetWindow; } + MotionSetManagementWindow* GetManagementWindow() { return m_motionSetManagementWindow; } + MotionSetWindow* GetMotionSetWindow() { return m_motionSetWindow; } int OnSaveDirtyMotionSets(); void LoadMotionSet(AZStd::string filename); @@ -94,22 +94,21 @@ namespace EMStudio MCORE_DEFINECOMMANDCALLBACK(CommandMotionSetAdjustMotionCallback); MCORE_DEFINECOMMANDCALLBACK(CommandLoadMotionSetCallback); - CommandCreateMotionSetCallback* mCreateMotionSetCallback; + CommandCreateMotionSetCallback* m_createMotionSetCallback; CommandReinitCallback* m_reinitCallback; - CommandAdjustMotionSetCallback* mAdjustMotionSetCallback; - CommandMotionSetAddMotionCallback* mMotionSetAddMotionCallback; - CommandMotionSetRemoveMotionCallback* mMotionSetRemoveMotionCallback; - CommandMotionSetAdjustMotionCallback* mMotionSetAdjustMotionCallback; - CommandLoadMotionSetCallback* mLoadMotionSetCallback; + CommandAdjustMotionSetCallback* m_adjustMotionSetCallback; + CommandMotionSetAddMotionCallback* m_motionSetAddMotionCallback; + CommandMotionSetRemoveMotionCallback* m_motionSetRemoveMotionCallback; + CommandMotionSetAdjustMotionCallback* m_motionSetAdjustMotionCallback; + CommandLoadMotionSetCallback* m_loadMotionSetCallback; - MotionSetManagementWindow* mMotionSetManagementWindow; - MotionSetWindow* mMotionSetWindow; + MotionSetManagementWindow* m_motionSetManagementWindow; + MotionSetWindow* m_motionSetWindow; - MysticQt::DialogStack* mDialogStack; - //MotionSetStringIDWindow* mStringIDWindow; + MysticQt::DialogStack* m_dialogStack; - EMotionFX::MotionSet* mSelectedSet; + EMotionFX::MotionSet* m_selectedSet; - SaveDirtyMotionSetFilesCallback* mDirtyFilesCallback; + SaveDirtyMotionSetFilesCallback* m_dirtyFilesCallback; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionWindow/MotionExtractionWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionWindow/MotionExtractionWindow.cpp index 419535da81..de5eb31d92 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionWindow/MotionExtractionWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionWindow/MotionExtractionWindow.cpp @@ -31,32 +31,32 @@ namespace EMStudio MotionExtractionWindow::MotionExtractionWindow(QWidget* parent, MotionWindowPlugin* motionWindowPlugin) : QWidget(parent) { - mMotionWindowPlugin = motionWindowPlugin; - mSelectCallback = nullptr; - mUnselectCallback = nullptr; - mClearSelectionCallback = nullptr; - mWarningWidget = nullptr; - mMainVerticalLayout = nullptr; - mChildVerticalLayout = nullptr; - mMotionExtractionNodeSelectionWindow= nullptr; - mWarningSelectNodeLink = nullptr; - mAdjustActorCallback = nullptr; - mCaptureHeight = nullptr; - mWarningShowed = false; + m_motionWindowPlugin = motionWindowPlugin; + m_selectCallback = nullptr; + m_unselectCallback = nullptr; + m_clearSelectionCallback = nullptr; + m_warningWidget = nullptr; + m_mainVerticalLayout = nullptr; + m_childVerticalLayout = nullptr; + m_motionExtractionNodeSelectionWindow= nullptr; + m_warningSelectNodeLink = nullptr; + m_adjustActorCallback = nullptr; + m_captureHeight = nullptr; + m_warningShowed = false; } // destructor MotionExtractionWindow::~MotionExtractionWindow() { - GetCommandManager()->RemoveCommandCallback(mSelectCallback, false); - GetCommandManager()->RemoveCommandCallback(mUnselectCallback, false); - GetCommandManager()->RemoveCommandCallback(mClearSelectionCallback, false); - GetCommandManager()->RemoveCommandCallback(mAdjustActorCallback, false); - delete mAdjustActorCallback; - delete mSelectCallback; - delete mUnselectCallback; - delete mClearSelectionCallback; + GetCommandManager()->RemoveCommandCallback(m_selectCallback, false); + GetCommandManager()->RemoveCommandCallback(m_unselectCallback, false); + GetCommandManager()->RemoveCommandCallback(m_clearSelectionCallback, false); + GetCommandManager()->RemoveCommandCallback(m_adjustActorCallback, false); + delete m_adjustActorCallback; + delete m_selectCallback; + delete m_unselectCallback; + delete m_clearSelectionCallback; } @@ -65,21 +65,21 @@ namespace EMStudio // Create the flags widget. void MotionExtractionWindow::CreateFlagsWidget() { - mFlagsWidget = new QWidget(); + m_flagsWidget = new QWidget(); - mCaptureHeight = new QCheckBox(); - AzQtComponents::CheckBox::applyToggleSwitchStyle(mCaptureHeight); - connect(mCaptureHeight, &QCheckBox::clicked, this, &MotionExtractionWindow::OnMotionExtractionFlagsUpdated); + m_captureHeight = new QCheckBox(); + AzQtComponents::CheckBox::applyToggleSwitchStyle(m_captureHeight); + connect(m_captureHeight, &QCheckBox::clicked, this, &MotionExtractionWindow::OnMotionExtractionFlagsUpdated); QGridLayout* layout = new QGridLayout(); layout->setAlignment(Qt::AlignTop); layout->setSpacing(3); layout->addWidget(new QLabel(tr("Capture Height Changes")), 0, 0); - layout->addWidget(mCaptureHeight, 0, 1); + layout->addWidget(m_captureHeight, 0, 1); layout->setContentsMargins(0, 0, 0, 0); - mFlagsWidget->setLayout(layout); + m_flagsWidget->setLayout(layout); - mChildVerticalLayout->addWidget(mFlagsWidget); + m_childVerticalLayout->addWidget(m_flagsWidget); } @@ -87,17 +87,17 @@ namespace EMStudio void MotionExtractionWindow::CreateWarningWidget() { // create the warning widget - mWarningWidget = new QWidget(); - mWarningWidget->setMinimumHeight(MOTIONEXTRACTIONWINDOW_HEIGHT); - mWarningWidget->setMaximumHeight(MOTIONEXTRACTIONWINDOW_HEIGHT); + m_warningWidget = new QWidget(); + m_warningWidget->setMinimumHeight(MOTIONEXTRACTIONWINDOW_HEIGHT); + m_warningWidget->setMaximumHeight(MOTIONEXTRACTIONWINDOW_HEIGHT); QLabel* warningLabel = new QLabel("No node has been selected yet to enable Motion Extraction."); warningLabel->setWordWrap(true); warningLabel->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); - mWarningSelectNodeLink = new AzQtComponents::BrowseEdit(mWarningWidget); - mWarningSelectNodeLink->setPlaceholderText("Click here to setup the Motion Extraction node"); - connect(mWarningSelectNodeLink, &AzQtComponents::BrowseEdit::attachedButtonTriggered, this, &MotionExtractionWindow::OnSelectMotionExtractionNode); + m_warningSelectNodeLink = new AzQtComponents::BrowseEdit(m_warningWidget); + m_warningSelectNodeLink->setPlaceholderText("Click here to setup the Motion Extraction node"); + connect(m_warningSelectNodeLink, &AzQtComponents::BrowseEdit::attachedButtonTriggered, this, &MotionExtractionWindow::OnSelectMotionExtractionNode); // create and fill the layout QVBoxLayout* layout = new QVBoxLayout(); @@ -106,12 +106,12 @@ namespace EMStudio layout->setContentsMargins(0, 0, 0, 0); layout->addWidget(warningLabel); - layout->addWidget(mWarningSelectNodeLink); + layout->addWidget(m_warningSelectNodeLink); - mWarningWidget->setLayout(layout); + m_warningWidget->setLayout(layout); // add it to our main layout - mChildVerticalLayout->addWidget(mWarningWidget); + m_childVerticalLayout->addWidget(m_warningWidget); } @@ -119,23 +119,23 @@ namespace EMStudio void MotionExtractionWindow::Init() { // create and register the command callbacks - mSelectCallback = new CommandSelectCallback(false); - mUnselectCallback = new CommandUnselectCallback(false); - mClearSelectionCallback = new CommandClearSelectionCallback(false); - mAdjustActorCallback = new CommandAdjustActorCallback(false); - GetCommandManager()->RegisterCommandCallback("AdjustActor", mAdjustActorCallback); - GetCommandManager()->RegisterCommandCallback("Select", mSelectCallback); - GetCommandManager()->RegisterCommandCallback("Unselect", mUnselectCallback); - GetCommandManager()->RegisterCommandCallback("ClearSelection", mClearSelectionCallback); + m_selectCallback = new CommandSelectCallback(false); + m_unselectCallback = new CommandUnselectCallback(false); + m_clearSelectionCallback = new CommandClearSelectionCallback(false); + m_adjustActorCallback = new CommandAdjustActorCallback(false); + GetCommandManager()->RegisterCommandCallback("AdjustActor", m_adjustActorCallback); + GetCommandManager()->RegisterCommandCallback("Select", m_selectCallback); + GetCommandManager()->RegisterCommandCallback("Unselect", m_unselectCallback); + GetCommandManager()->RegisterCommandCallback("ClearSelection", m_clearSelectionCallback); // create the node selection windows - mMotionExtractionNodeSelectionWindow = new NodeSelectionWindow(this, true); - connect(mMotionExtractionNodeSelectionWindow->GetNodeHierarchyWidget(), &NodeHierarchyWidget::OnSelectionDone, this, &MotionExtractionWindow::OnMotionExtractionNodeSelected); + m_motionExtractionNodeSelectionWindow = new NodeSelectionWindow(this, true); + connect(m_motionExtractionNodeSelectionWindow->GetNodeHierarchyWidget(), &NodeHierarchyWidget::OnSelectionDone, this, &MotionExtractionWindow::OnMotionExtractionNodeSelected); // set some layout for our window - mMainVerticalLayout = new QVBoxLayout(); - mMainVerticalLayout->setSpacing(0); - setLayout(mMainVerticalLayout); + m_mainVerticalLayout = new QVBoxLayout(); + m_mainVerticalLayout->setSpacing(0); + setLayout(m_mainVerticalLayout); QCheckBox* checkBox = new QCheckBox(tr("Motion extraction")); checkBox->setChecked(true); @@ -160,17 +160,17 @@ namespace EMStudio {\ image: url(:/Cards/img/UI20/Cards/caret-right.svg);\ }"); - mMainVerticalLayout->addWidget(checkBox); + m_mainVerticalLayout->addWidget(checkBox); QWidget* childWidget = new QWidget(this); - mMainVerticalLayout->addWidget(childWidget); + m_mainVerticalLayout->addWidget(childWidget); - mChildVerticalLayout = new QVBoxLayout(childWidget); - mChildVerticalLayout->setContentsMargins(28,0,0,0); + m_childVerticalLayout = new QVBoxLayout(childWidget); + m_childVerticalLayout->setContentsMargins(28,0,0,0); connect(checkBox, &QCheckBox::toggled, childWidget, &QWidget::setVisible); // default create the warning widget (this is needed else we're getting a crash when switching layouts as the widget and the flag might be out of sync) CreateWarningWidget(); - mWarningShowed = true; + m_warningShowed = true; // update interface UpdateInterface(); @@ -191,9 +191,9 @@ namespace EMStudio EMotionFX::Actor* actor = nullptr; EMotionFX::Node* extractionNode = nullptr; - if (mCaptureHeight) + if (m_captureHeight) { - mCaptureHeight->setEnabled( isEnabled ); + m_captureHeight->setEnabled( isEnabled ); } if (actorInstance) @@ -205,51 +205,51 @@ namespace EMStudio if (extractionNode == nullptr) { // Check if we already show the warning widget, if yes, do nothing. - if (mWarningShowed == false) + if (m_warningShowed == false) { CreateWarningWidget(); - if (mFlagsWidget) + if (m_flagsWidget) { - mFlagsWidget->hide(); - mFlagsWidget->deleteLater(); - mFlagsWidget = nullptr; - mCaptureHeight = nullptr; + m_flagsWidget->hide(); + m_flagsWidget->deleteLater(); + m_flagsWidget = nullptr; + m_captureHeight = nullptr; } } // Disable the link in case no actor is selected. if (actorInstance == nullptr) { - mWarningSelectNodeLink->setEnabled(false); + m_warningSelectNodeLink->setEnabled(false); } else { - mWarningSelectNodeLink->setEnabled(true); + m_warningSelectNodeLink->setEnabled(true); } // Return directly in case we show the warning widget. - mWarningShowed = true; + m_warningShowed = true; return; } else { // Check if we already show the motion extraction flags widget, if yes, do nothing. - if (mWarningShowed) + if (m_warningShowed) { - if (mWarningWidget) + if (m_warningWidget) { - mWarningWidget->hide(); - mWarningWidget->deleteLater(); - mWarningWidget = nullptr; + m_warningWidget->hide(); + m_warningWidget->deleteLater(); + m_warningWidget = nullptr; } CreateFlagsWidget(); } - if (mCaptureHeight) + if (m_captureHeight) { - mCaptureHeight->setEnabled( isEnabled ); + m_captureHeight->setEnabled( isEnabled ); } // Figure out if all selected motions use the same settings. @@ -280,31 +280,31 @@ namespace EMStudio // Adjust the height capture checkbox, based on the selected motions. const bool triState = (numMotions > 1) && !allCaptureHeightEqual; - mCaptureHeight->setTristate( triState ); + m_captureHeight->setTristate( triState ); if (numMotions > 1) { if (!allCaptureHeightEqual) { - mCaptureHeight->setCheckState( Qt::CheckState::PartiallyChecked ); + m_captureHeight->setCheckState( Qt::CheckState::PartiallyChecked ); } else { - mCaptureHeight->setChecked( curCaptureHeight ); + m_captureHeight->setChecked( curCaptureHeight ); } } else { if (numCaptureHeight > 0) { - mCaptureHeight->setCheckState( Qt::CheckState::Checked ); + m_captureHeight->setCheckState( Qt::CheckState::Checked ); } else { - mCaptureHeight->setCheckState( Qt::CheckState::Unchecked ); + m_captureHeight->setCheckState( Qt::CheckState::Unchecked ); } } - mWarningShowed = false; + m_warningShowed = false; } } @@ -314,7 +314,7 @@ namespace EMStudio { int flags = 0; - if (mCaptureHeight->checkState() == Qt::CheckState::Checked) + if (m_captureHeight->checkState() == Qt::CheckState::Checked) flags |= EMotionFX::MOTIONEXTRACT_CAPTURE_Z; return static_cast(flags); @@ -388,8 +388,8 @@ namespace EMStudio return; } - mMotionExtractionNodeSelectionWindow->Update(actorInstance->GetID()); - mMotionExtractionNodeSelectionWindow->show(); + m_motionExtractionNodeSelectionWindow->Update(actorInstance->GetID()); + m_motionExtractionNodeSelectionWindow->show(); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionWindow/MotionExtractionWindow.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionWindow/MotionExtractionWindow.h index cb7371a74d..5e314df323 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionWindow/MotionExtractionWindow.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionWindow/MotionExtractionWindow.h @@ -61,28 +61,28 @@ namespace EMStudio MCORE_DEFINECOMMANDCALLBACK(CommandUnselectCallback); MCORE_DEFINECOMMANDCALLBACK(CommandClearSelectionCallback); MCORE_DEFINECOMMANDCALLBACK(CommandAdjustActorCallback); - CommandSelectCallback* mSelectCallback; - CommandUnselectCallback* mUnselectCallback; - CommandClearSelectionCallback* mClearSelectionCallback; - CommandAdjustActorCallback* mAdjustActorCallback; + CommandSelectCallback* m_selectCallback; + CommandUnselectCallback* m_unselectCallback; + CommandClearSelectionCallback* m_clearSelectionCallback; + CommandAdjustActorCallback* m_adjustActorCallback; // general - MotionWindowPlugin* mMotionWindowPlugin; - QCheckBox* mAutoMode; + MotionWindowPlugin* m_motionWindowPlugin; + QCheckBox* m_autoMode; // flags widget - QWidget* mFlagsWidget; - QCheckBox* mCaptureHeight; + QWidget* m_flagsWidget; + QCheckBox* m_captureHeight; // - QVBoxLayout* mMainVerticalLayout; - QVBoxLayout* mChildVerticalLayout; - QWidget* mWarningWidget; - bool mWarningShowed; + QVBoxLayout* m_mainVerticalLayout; + QVBoxLayout* m_childVerticalLayout; + QWidget* m_warningWidget; + bool m_warningShowed; // motion extraction node selection - NodeSelectionWindow* mMotionExtractionNodeSelectionWindow; - AzQtComponents::BrowseEdit* mWarningSelectNodeLink; + NodeSelectionWindow* m_motionExtractionNodeSelectionWindow; + AzQtComponents::BrowseEdit* m_warningSelectNodeLink; // helper functions void CreateFlagsWidget(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionWindow/MotionListWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionWindow/MotionListWindow.cpp index c909098dae..0940a620e6 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionWindow/MotionListWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionWindow/MotionListWindow.cpp @@ -124,8 +124,8 @@ namespace EMStudio : QWidget(parent) { setObjectName("MotionListWindow"); - mMotionTable = nullptr; - mMotionWindowPlugin = motionWindowPlugin; + m_motionTable = nullptr; + m_motionWindowPlugin = motionWindowPlugin; } @@ -137,77 +137,77 @@ namespace EMStudio void MotionListWindow::Init() { - mVLayout = new QVBoxLayout(); - mVLayout->setMargin(3); - mVLayout->setSpacing(2); - mMotionTable = new MotionTableWidget(mMotionWindowPlugin, this); - mMotionTable->setObjectName("EMFX.MotionListWindow.MotionTable"); - mMotionTable->setAlternatingRowColors(true); - connect(mMotionTable, &MotionTableWidget::cellDoubleClicked, this, &MotionListWindow::cellDoubleClicked); - connect(mMotionTable, &MotionTableWidget::itemSelectionChanged, this, &MotionListWindow::itemSelectionChanged); + m_vLayout = new QVBoxLayout(); + m_vLayout->setMargin(3); + m_vLayout->setSpacing(2); + m_motionTable = new MotionTableWidget(m_motionWindowPlugin, this); + m_motionTable->setObjectName("EMFX.MotionListWindow.MotionTable"); + m_motionTable->setAlternatingRowColors(true); + connect(m_motionTable, &MotionTableWidget::cellDoubleClicked, this, &MotionListWindow::cellDoubleClicked); + connect(m_motionTable, &MotionTableWidget::itemSelectionChanged, this, &MotionListWindow::itemSelectionChanged); // set the table to row single selection - mMotionTable->setSelectionBehavior(QAbstractItemView::SelectRows); - mMotionTable->setSelectionMode(QAbstractItemView::ExtendedSelection); + m_motionTable->setSelectionBehavior(QAbstractItemView::SelectRows); + m_motionTable->setSelectionMode(QAbstractItemView::ExtendedSelection); // make the table items read only - mMotionTable->setEditTriggers(QAbstractItemView::NoEditTriggers); + m_motionTable->setEditTriggers(QAbstractItemView::NoEditTriggers); // disable the corner button between the row and column selection thingies - mMotionTable->setCornerButtonEnabled(false); + m_motionTable->setCornerButtonEnabled(false); // enable the custom context menu for the motion table - mMotionTable->setContextMenuPolicy(Qt::DefaultContextMenu); + m_motionTable->setContextMenuPolicy(Qt::DefaultContextMenu); // set the column count - mMotionTable->setColumnCount(5); + m_motionTable->setColumnCount(5); // add the name column QTableWidgetItem* nameHeaderItem = new QTableWidgetItem("Name"); nameHeaderItem->setTextAlignment(Qt::AlignVCenter | Qt::AlignLeft); - mMotionTable->setHorizontalHeaderItem(0, nameHeaderItem); + m_motionTable->setHorizontalHeaderItem(0, nameHeaderItem); // add the length column QTableWidgetItem* lengthHeaderItem = new QTableWidgetItem("Duration"); lengthHeaderItem->setTextAlignment(Qt::AlignVCenter | Qt::AlignLeft); - mMotionTable->setHorizontalHeaderItem(1, lengthHeaderItem); + m_motionTable->setHorizontalHeaderItem(1, lengthHeaderItem); // add the sub column QTableWidgetItem* subHeaderItem = new QTableWidgetItem("Joints"); subHeaderItem->setToolTip("Number of joints inside the motion"); subHeaderItem->setTextAlignment(Qt::AlignVCenter | Qt::AlignLeft); - mMotionTable->setHorizontalHeaderItem(2, subHeaderItem); + m_motionTable->setHorizontalHeaderItem(2, subHeaderItem); // add the msub column QTableWidgetItem* msubHeaderItem = new QTableWidgetItem("Morphs"); msubHeaderItem->setToolTip("Number of morph targets inside the motion"); msubHeaderItem->setTextAlignment(Qt::AlignVCenter | Qt::AlignLeft); - mMotionTable->setHorizontalHeaderItem(3, msubHeaderItem); + m_motionTable->setHorizontalHeaderItem(3, msubHeaderItem); // add the type column QTableWidgetItem* typeHeaderItem = new QTableWidgetItem("Type"); typeHeaderItem->setTextAlignment(Qt::AlignVCenter | Qt::AlignLeft); - mMotionTable->setHorizontalHeaderItem(4, typeHeaderItem); + m_motionTable->setHorizontalHeaderItem(4, typeHeaderItem); // set the sorting order on the first column - mMotionTable->horizontalHeader()->setSortIndicator(0, Qt::AscendingOrder); + m_motionTable->horizontalHeader()->setSortIndicator(0, Qt::AscendingOrder); // hide the vertical columns - QHeaderView* verticalHeader = mMotionTable->verticalHeader(); + QHeaderView* verticalHeader = m_motionTable->verticalHeader(); verticalHeader->setVisible(false); // set the last column to take the whole available space - mMotionTable->horizontalHeader()->setStretchLastSection(true); + m_motionTable->horizontalHeader()->setStretchLastSection(true); // set the column width - mMotionTable->setColumnWidth(0, 300); - mMotionTable->setColumnWidth(1, 55); - mMotionTable->setColumnWidth(2, 50); - mMotionTable->setColumnWidth(3, 55); - mMotionTable->setColumnWidth(4, 105); + m_motionTable->setColumnWidth(0, 300); + m_motionTable->setColumnWidth(1, 55); + m_motionTable->setColumnWidth(2, 50); + m_motionTable->setColumnWidth(3, 55); + m_motionTable->setColumnWidth(4, 105); - mVLayout->addWidget(mMotionTable); - setLayout(mVLayout); + m_vLayout->addWidget(m_motionTable); + setLayout(m_vLayout); ReInit(); } @@ -224,7 +224,7 @@ namespace EMStudio bool MotionListWindow::AddMotionByID(uint32 motionID) { // find the motion entry based on the id - MotionWindowPlugin::MotionTableEntry* motionEntry = mMotionWindowPlugin->FindMotionEntryByID(motionID); + MotionWindowPlugin::MotionTableEntry* motionEntry = m_motionWindowPlugin->FindMotionEntryByID(motionID); if (motionEntry == nullptr) { return false; @@ -237,15 +237,15 @@ namespace EMStudio } // get the motion - EMotionFX::Motion* motion = motionEntry->mMotion; + EMotionFX::Motion* motion = motionEntry->m_motion; // disable the sorting - mMotionTable->setSortingEnabled(false); + m_motionTable->setSortingEnabled(false); // insert the new row const int rowIndex = 0; - mMotionTable->insertRow(rowIndex); - mMotionTable->setRowHeight(rowIndex, 21); + m_motionTable->insertRow(rowIndex); + m_motionTable->setRowHeight(rowIndex, 21); // create the name item QTableWidgetItem* nameTableItem = new QTableWidgetItem(motion->GetName()); @@ -257,7 +257,7 @@ namespace EMStudio nameTableItem->setToolTip(motion->GetFileName()); // set the item in the motion table - mMotionTable->setItem(rowIndex, 0, nameTableItem); + m_motionTable->setItem(rowIndex, 0, nameTableItem); // create the length item AZStd::string length; @@ -265,7 +265,7 @@ namespace EMStudio QTableWidgetItem* lengthTableItem = new QTableWidgetItem(length.c_str()); // set the item in the motion table - mMotionTable->setItem(rowIndex, 1, lengthTableItem); + m_motionTable->setItem(rowIndex, 1, lengthTableItem); // set the sub and msub text AZStd::string sub, msub; @@ -278,12 +278,12 @@ namespace EMStudio QTableWidgetItem* msubTableItem = new QTableWidgetItem(msub.c_str()); // set the items in the motion table - mMotionTable->setItem(rowIndex, 2, subTableItem); - mMotionTable->setItem(rowIndex, 3, msubTableItem); + m_motionTable->setItem(rowIndex, 2, subTableItem); + m_motionTable->setItem(rowIndex, 3, msubTableItem); // create and set the type item QTableWidgetItem* typeTableItem = new QTableWidgetItem(motionData->RTTI_GetTypeName()); - mMotionTable->setItem(rowIndex, 4, typeTableItem); + m_motionTable->setItem(rowIndex, 4, typeTableItem); // set the items italic if the motion is dirty if (motion->GetDirtyFlag()) @@ -301,7 +301,7 @@ namespace EMStudio } // enable the sorting - mMotionTable->setSortingEnabled(true); + m_motionTable->setSortingEnabled(true); // update the interface UpdateInterface(); @@ -314,7 +314,7 @@ namespace EMStudio uint32 MotionListWindow::FindRowByMotionID(uint32 motionID) { // iterate through the rows and compare the motion IDs - const int rowCount = mMotionTable->rowCount(); + const int rowCount = m_motionTable->rowCount(); for (int i = 0; i < rowCount; ++i) { if (GetMotionID(i) == motionID) @@ -338,7 +338,7 @@ namespace EMStudio } // remove the row - mMotionTable->removeRow(rowIndex); + m_motionTable->removeRow(rowIndex); // update the interface UpdateInterface(); @@ -350,12 +350,12 @@ namespace EMStudio bool MotionListWindow::CheckIfIsMotionVisible(MotionWindowPlugin::MotionTableEntry* entry) { - if (entry->mMotion->GetIsOwnedByRuntime()) + if (entry->m_motion->GetIsOwnedByRuntime()) { return false; } - AZStd::string motionNameLowered = entry->mMotion->GetNameString(); + AZStd::string motionNameLowered = entry->m_motion->GetNameString(); AZStd::to_lower(motionNameLowered.begin(), motionNameLowered.end()); if (m_searchWidgetText.empty() || motionNameLowered.find(m_searchWidgetText) != AZStd::string::npos) { @@ -369,33 +369,33 @@ namespace EMStudio { const CommandSystem::SelectionList selection = GetCommandManager()->GetCurrentSelection(); - size_t numMotions = mMotionWindowPlugin->GetNumMotionEntries(); - mShownMotionEntries.clear(); - mShownMotionEntries.reserve(numMotions); + size_t numMotions = m_motionWindowPlugin->GetNumMotionEntries(); + m_shownMotionEntries.clear(); + m_shownMotionEntries.reserve(numMotions); for (size_t i = 0; i < numMotions; ++i) { - MotionWindowPlugin::MotionTableEntry* entry = mMotionWindowPlugin->GetMotionEntry(i); + MotionWindowPlugin::MotionTableEntry* entry = m_motionWindowPlugin->GetMotionEntry(i); if (CheckIfIsMotionVisible(entry)) { - mShownMotionEntries.push_back(entry); + m_shownMotionEntries.push_back(entry); } } - numMotions = mShownMotionEntries.size(); + numMotions = m_shownMotionEntries.size(); // set the number of rows - mMotionTable->setRowCount(static_cast(numMotions)); + m_motionTable->setRowCount(static_cast(numMotions)); // set the sorting disabled - mMotionTable->setSortingEnabled(false); + m_motionTable->setSortingEnabled(false); // iterate through the motions and fill in the table for (int i = 0; i < numMotions; ++i) { - EMotionFX::Motion* motion = mShownMotionEntries[static_cast(i)]->mMotion; + EMotionFX::Motion* motion = m_shownMotionEntries[static_cast(i)]->m_motion; // set the row height - mMotionTable->setRowHeight(i, 21); + m_motionTable->setRowHeight(i, 21); // create the name item QTableWidgetItem* nameTableItem = new QTableWidgetItem(motion->GetName()); @@ -407,7 +407,7 @@ namespace EMStudio nameTableItem->setToolTip(motion->GetFileName()); // set the item in the motion table - mMotionTable->setItem(i, 0, nameTableItem); + m_motionTable->setItem(i, 0, nameTableItem); // create the length item AZStd::string length; @@ -415,7 +415,7 @@ namespace EMStudio QTableWidgetItem* lengthTableItem = new QTableWidgetItem(length.c_str()); // set the item in the motion table - mMotionTable->setItem(i, 1, lengthTableItem); + m_motionTable->setItem(i, 1, lengthTableItem); // set the sub and msub text AZStd::string sub, msub; @@ -428,12 +428,12 @@ namespace EMStudio QTableWidgetItem* msubTableItem = new QTableWidgetItem(msub.c_str()); // set the items in the motion table - mMotionTable->setItem(i, 2, subTableItem); - mMotionTable->setItem(i, 3, msubTableItem); + m_motionTable->setItem(i, 2, subTableItem); + m_motionTable->setItem(i, 3, msubTableItem); // create and set the type item QTableWidgetItem* typeTableItem = new QTableWidgetItem(motionData->RTTI_GetTypeName()); - mMotionTable->setItem(i, 4, typeTableItem); + m_motionTable->setItem(i, 4, typeTableItem); // set the items italic if the motion is dirty if (motion->GetDirtyFlag()) @@ -452,7 +452,7 @@ namespace EMStudio } // set the sorting enabled - mMotionTable->setSortingEnabled(true); + m_motionTable->setSortingEnabled(true); // set the old selection as before the reinit UpdateSelection(selection); @@ -463,10 +463,10 @@ namespace EMStudio void MotionListWindow::UpdateSelection(const CommandSystem::SelectionList& selectionList) { // block signals to not have the motion table events when selection changed - mMotionTable->blockSignals(true); + m_motionTable->blockSignals(true); // clear the selection - mMotionTable->clearSelection(); + m_motionTable->clearSelection(); // iterate through the selected motions and select the corresponding rows in the table widget const size_t numSelectedMotions = selectionList.GetNumSelectedMotions(); @@ -478,17 +478,17 @@ namespace EMStudio if (row != MCORE_INVALIDINDEX32) { // select the entire row - const int columnCount = mMotionTable->columnCount(); + const int columnCount = m_motionTable->columnCount(); for (int c = 0; c < columnCount; ++c) { - QTableWidgetItem* tableWidgetItem = mMotionTable->item(row, c); + QTableWidgetItem* tableWidgetItem = m_motionTable->item(row, c); tableWidgetItem->setSelected(true); } } } // enable the signals now all rows are selected - mMotionTable->blockSignals(false); + m_motionTable->blockSignals(false); // call the selection changed itemSelectionChanged(); @@ -502,7 +502,7 @@ namespace EMStudio uint32 MotionListWindow::GetMotionID(uint32 rowIndex) { - QTableWidgetItem* tableItem = mMotionTable->item(rowIndex, 0); + QTableWidgetItem* tableItem = m_motionTable->item(rowIndex, 0); if (tableItem) { return tableItem->data(Qt::UserRole).toInt(); @@ -520,7 +520,7 @@ namespace EMStudio if (motion) { - mMotionWindowPlugin->PlayMotion(motion); + m_motionWindowPlugin->PlayMotion(motion); } } @@ -528,7 +528,7 @@ namespace EMStudio void MotionListWindow::itemSelectionChanged() { // get the current selection - const QList selectedItems = mMotionTable->selectedItems(); + const QList selectedItems = m_motionTable->selectedItems(); // get the number of selected items const int numSelectedItems = selectedItems.count(); @@ -546,20 +546,20 @@ namespace EMStudio } // clear the selected motion IDs - mSelectedMotionIDs.clear(); + m_selectedMotionIDs.clear(); // get the number of selected items and iterate through them - mSelectedMotionIDs.reserve(rowIndices.size()); + m_selectedMotionIDs.reserve(rowIndices.size()); for (const int rowIndex : rowIndices) { - mSelectedMotionIDs.push_back(GetMotionID(rowIndex)); + m_selectedMotionIDs.push_back(GetMotionID(rowIndex)); } // unselect all motions GetCommandManager()->GetCurrentSelection().ClearMotionSelection(); // get the number of selected motions and iterate through them - for (uint32 selectedMotionID : mSelectedMotionIDs) + for (uint32 selectedMotionID : m_selectedMotionIDs) { // find the motion by name in the motion library and select it EMotionFX::Motion* motion = EMotionFX::GetMotionManager().FindMotionByID(selectedMotionID); @@ -570,7 +570,7 @@ namespace EMStudio } // update the interface - mMotionWindowPlugin->UpdateInterface(); + m_motionWindowPlugin->UpdateInterface(); // emit signal that tells other windows that the motion selection changed emit MotionSelectionChanged(); @@ -748,7 +748,7 @@ namespace EMStudio MotionTableWidget::MotionTableWidget(MotionWindowPlugin* parentPlugin, QWidget* parent) : QTableWidget(parent) { - mPlugin = parentPlugin; + m_plugin = parentPlugin; // enable dragging setDragEnabled(true); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionWindow/MotionListWindow.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionWindow/MotionListWindow.h index 89f2dc8f8a..7308ce12e1 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionWindow/MotionListWindow.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionWindow/MotionListWindow.h @@ -62,7 +62,7 @@ namespace EMStudio QStringList mimeTypes() const override; Qt::DropActions supportedDropActions() const override; - MotionWindowPlugin* mPlugin; + MotionWindowPlugin* m_plugin; }; @@ -80,7 +80,7 @@ namespace EMStudio void ReInit(); void UpdateInterface(); - QTableWidget* GetMotionTable() { return mMotionTable; } + QTableWidget* GetMotionTable() { return m_motionTable; } bool AddMotionByID(uint32 motionID); bool RemoveMotionByID(uint32 motionID); @@ -108,11 +108,11 @@ namespace EMStudio void UpdateSelection(const CommandSystem::SelectionList& selectionList); private: - AZStd::vector mSelectedMotionIDs; - AZStd::vector mShownMotionEntries; - QVBoxLayout* mVLayout; - MotionTableWidget* mMotionTable; - MotionWindowPlugin* mMotionWindowPlugin; + AZStd::vector m_selectedMotionIDs; + AZStd::vector m_shownMotionEntries; + QVBoxLayout* m_vLayout; + MotionTableWidget* m_motionTable; + MotionWindowPlugin* m_motionWindowPlugin; AZStd::string m_searchWidgetText; }; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionWindow/MotionRetargetingWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionWindow/MotionRetargetingWindow.cpp index 6596a7c868..d6dbe2c4cc 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionWindow/MotionRetargetingWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionWindow/MotionRetargetingWindow.cpp @@ -26,9 +26,8 @@ namespace EMStudio MotionRetargetingWindow::MotionRetargetingWindow(QWidget* parent, MotionWindowPlugin* motionWindowPlugin) : QWidget(parent) { - mMotionWindowPlugin = motionWindowPlugin; - mMotionRetargetingButton = nullptr; - //mRenderMotionBindPose = nullptr; + m_motionWindowPlugin = motionWindowPlugin; + m_motionRetargetingButton = nullptr; } @@ -44,18 +43,11 @@ namespace EMStudio QGridLayout* layout = new QGridLayout(); setLayout(layout); - mMotionRetargetingButton = new QCheckBox(); - AzQtComponents::CheckBox::applyToggleSwitchStyle(mMotionRetargetingButton); + m_motionRetargetingButton = new QCheckBox(); + AzQtComponents::CheckBox::applyToggleSwitchStyle(m_motionRetargetingButton); layout->addWidget(new QLabel(tr("Use Motion Retargeting")), 0, 0); - layout->addWidget(mMotionRetargetingButton, 0, 1); - connect(mMotionRetargetingButton, &QCheckBox::clicked, this, &MotionRetargetingWindow::UpdateMotions); - - //mRenderMotionBindPose = new QCheckBox(); - //AzQtComponents::CheckBox::applyToggleSwitchStyle(mRenderMotionBindPose); - //mRenderMotionBindPose->setToolTip("Render motion bind pose of the currently selected motion for the selected actor instances"); - //mRenderMotionBindPose->setChecked(false); - //layout->addWidget(new QLabel(tr("Render Motion Bind Pose")), 1, 0); - //layout->addWidget(mRenderMotionBindPose, 1, 1); + layout->addWidget(m_motionRetargetingButton, 0, 1); + connect(m_motionRetargetingButton, &QCheckBox::clicked, this, &MotionRetargetingWindow::UpdateMotions); } @@ -70,21 +62,21 @@ namespace EMStudio const size_t numMotions = selection.GetNumSelectedMotions(); for (size_t i = 0; i < numMotions; ++i) { - MotionWindowPlugin::MotionTableEntry* entry = mMotionWindowPlugin->FindMotionEntryByID(selection.GetMotion(i)->GetID()); + MotionWindowPlugin::MotionTableEntry* entry = m_motionWindowPlugin->FindMotionEntryByID(selection.GetMotion(i)->GetID()); if (entry == nullptr) { MCore::LogError("Cannot find motion table entry for the given motion."); continue; } - EMotionFX::Motion* motion = entry->mMotion; + EMotionFX::Motion* motion = entry->m_motion; EMotionFX::PlayBackInfo* playbackInfo = motion->GetDefaultPlayBackInfo(); AZStd::string commandParameters; - if (playbackInfo->mRetarget != mMotionRetargetingButton->isChecked()) + if (playbackInfo->m_retarget != m_motionRetargetingButton->isChecked()) { - commandParameters += AZStd::string::format("-retarget %s ", AZStd::to_string(mMotionRetargetingButton->isChecked()).c_str()); + commandParameters += AZStd::string::format("-retarget %s ", AZStd::to_string(m_motionRetargetingButton->isChecked()).c_str()); } // in case the command parameters are empty it means nothing changed, so we can skip this command @@ -111,8 +103,7 @@ namespace EMStudio const size_t numSelectedMotions = selection.GetNumSelectedMotions(); const bool isEnabled = (numSelectedMotions != 0); - mMotionRetargetingButton->setEnabled(isEnabled); - //mRenderMotionBindPose->setEnabled(isEnabled); + m_motionRetargetingButton->setEnabled(isEnabled); if (isEnabled == false) { @@ -122,17 +113,17 @@ namespace EMStudio // iterate through the selected motions for (size_t i = 0; i < numSelectedMotions; ++i) { - MotionWindowPlugin::MotionTableEntry* entry = mMotionWindowPlugin->FindMotionEntryByID(selection.GetMotion(i)->GetID()); + MotionWindowPlugin::MotionTableEntry* entry = m_motionWindowPlugin->FindMotionEntryByID(selection.GetMotion(i)->GetID()); if (entry == nullptr) { MCore::LogWarning("Cannot find motion table entry for the given motion."); continue; } - EMotionFX::Motion* motion = entry->mMotion; + EMotionFX::Motion* motion = entry->m_motion; EMotionFX::PlayBackInfo* defaultPlayBackInfo = motion->GetDefaultPlayBackInfo(); - mMotionRetargetingButton->setChecked(defaultPlayBackInfo->mRetarget); + m_motionRetargetingButton->setChecked(defaultPlayBackInfo->m_retarget); } } } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionWindow/MotionRetargetingWindow.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionWindow/MotionRetargetingWindow.h index 3c5d50bc36..a846982eca 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionWindow/MotionRetargetingWindow.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionWindow/MotionRetargetingWindow.h @@ -47,12 +47,11 @@ namespace EMStudio void UpdateMotions(); private: - MotionWindowPlugin* mMotionWindowPlugin; - QCheckBox* mMotionRetargetingButton; - //QCheckBox* mRenderMotionBindPose; - EMotionFX::ActorInstance* mSelectedActorInstance; - EMotionFX::Actor* mActor; - CommandSystem::SelectionList mSelectionList; + MotionWindowPlugin* m_motionWindowPlugin; + QCheckBox* m_motionRetargetingButton; + EMotionFX::ActorInstance* m_selectedActorInstance; + EMotionFX::Actor* m_actor; + CommandSystem::SelectionList m_selectionList; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionWindow/MotionWindowPlugin.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionWindow/MotionWindowPlugin.cpp index 1452d0ac93..87c6a601aa 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionWindow/MotionWindowPlugin.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionWindow/MotionWindowPlugin.cpp @@ -40,7 +40,7 @@ namespace EMStudio public: SaveDirtyMotionFilesCallback(MotionWindowPlugin* plugin) - : SaveDirtyFilesCallback() { mPlugin = plugin; } + : SaveDirtyFilesCallback() { m_plugin = plugin; } ~SaveDirtyMotionFilesCallback() {} enum @@ -72,7 +72,7 @@ namespace EMStudio // add the link to the actual object ObjectPointer objPointer; - objPointer.mMotion = motion; + objPointer.m_motion = motion; outObjects->push_back(objPointer); } } @@ -87,13 +87,13 @@ namespace EMStudio { // get the current object pointer and skip directly if the type check fails ObjectPointer objPointer = objects[i]; - if (objPointer.mMotion == nullptr) + if (objPointer.m_motion == nullptr) { continue; } - EMotionFX::Motion* motion = objPointer.mMotion; - if (mPlugin->SaveDirtyMotion(motion, commandGroup, false) == DirtyFileManager::CANCELED) + EMotionFX::Motion* motion = objPointer.m_motion; + if (m_plugin->SaveDirtyMotion(motion, commandGroup, false) == DirtyFileManager::CANCELED) { return DirtyFileManager::CANCELED; } @@ -110,31 +110,31 @@ namespace EMStudio } private: - MotionWindowPlugin* mPlugin; + MotionWindowPlugin* m_plugin; }; - AZStd::vector MotionWindowPlugin::mInternalMotionInstanceSelection; + AZStd::vector MotionWindowPlugin::s_internalMotionInstanceSelection; MotionWindowPlugin::MotionWindowPlugin() : EMStudio::DockWidgetPlugin() { - mDialogStack = nullptr; - mMotionListWindow = nullptr; - mMotionPropertiesWindow = nullptr; - mMotionExtractionWindow = nullptr; - mMotionRetargetingWindow = nullptr; - mDirtyFilesCallback = nullptr; - mAddMotionsAction = nullptr; - mSaveAction = nullptr; - mMotionNameLabel = nullptr; + m_dialogStack = nullptr; + m_motionListWindow = nullptr; + m_motionPropertiesWindow = nullptr; + m_motionExtractionWindow = nullptr; + m_motionRetargetingWindow = nullptr; + m_dirtyFilesCallback = nullptr; + m_addMotionsAction = nullptr; + m_saveAction = nullptr; + m_motionNameLabel = nullptr; } MotionWindowPlugin::~MotionWindowPlugin() { - delete mDialogStack; + delete m_dialogStack; ClearMotionEntries(); // unregister the command callbacks and get rid of the memory @@ -144,19 +144,19 @@ namespace EMStudio } m_callbacks.clear(); - GetMainWindow()->GetDirtyFileManager()->RemoveCallback(mDirtyFilesCallback, false); - delete mDirtyFilesCallback; + GetMainWindow()->GetDirtyFileManager()->RemoveCallback(m_dirtyFilesCallback, false); + delete m_dirtyFilesCallback; } void MotionWindowPlugin::ClearMotionEntries() { - const size_t numEntries = mMotionEntries.size(); + const size_t numEntries = m_motionEntries.size(); for (size_t i = 0; i < numEntries; ++i) { - delete mMotionEntries[i]; + delete m_motionEntries[i]; } - mMotionEntries.clear(); + m_motionEntries.clear(); } @@ -180,9 +180,9 @@ namespace EMStudio GetCommandManager()->RegisterCommandCallback("ScaleMotionData", m_callbacks, false); GetCommandManager()->RegisterCommandCallback("Select", m_callbacks, false); - QWidget* container = new QWidget(mDock); + QWidget* container = new QWidget(m_dock); container->setLayout(new QVBoxLayout); - mDock->setWidget(container); + m_dock->setWidget(container); QToolBar* toolBar = new QToolBar(container); container->layout()->addWidget(toolBar); @@ -194,73 +194,73 @@ namespace EMStudio container->layout()->addWidget(splitterWidget); // create the motion list stack window - mMotionListWindow = new MotionListWindow(splitterWidget, this); - mMotionListWindow->Init(); - connect(mMotionListWindow, &MotionListWindow::SaveRequested, this, &MotionWindowPlugin::OnSave); - connect(mMotionListWindow, &MotionListWindow::RemoveMotionsRequested, this, &MotionWindowPlugin::OnRemoveMotions); - splitterWidget->addWidget(mMotionListWindow); + m_motionListWindow = new MotionListWindow(splitterWidget, this); + m_motionListWindow->Init(); + connect(m_motionListWindow, &MotionListWindow::SaveRequested, this, &MotionWindowPlugin::OnSave); + connect(m_motionListWindow, &MotionListWindow::RemoveMotionsRequested, this, &MotionWindowPlugin::OnRemoveMotions); + splitterWidget->addWidget(m_motionListWindow); // reinitialize the motion table entries ReInit(); - mAddMotionsAction = toolBar->addAction(MysticQt::GetMysticQt()->FindIcon("Images/Icons/Plus.svg"), tr("Load motions"), this, &MotionWindowPlugin::OnAddMotions); - mSaveAction = toolBar->addAction(MysticQt::GetMysticQt()->FindIcon("Images/Menu/FileSave.svg"), tr("Save selected motions"), this, &MotionWindowPlugin::OnSave); + m_addMotionsAction = toolBar->addAction(MysticQt::GetMysticQt()->FindIcon("Images/Icons/Plus.svg"), tr("Load motions"), this, &MotionWindowPlugin::OnAddMotions); + m_saveAction = toolBar->addAction(MysticQt::GetMysticQt()->FindIcon("Images/Menu/FileSave.svg"), tr("Save selected motions"), this, &MotionWindowPlugin::OnSave); toolBar->addSeparator(); AzQtComponents::FilteredSearchWidget* searchWidget = new AzQtComponents::FilteredSearchWidget(toolBar); - connect(searchWidget, &AzQtComponents::FilteredSearchWidget::TextFilterChanged, mMotionListWindow, &MotionListWindow::OnTextFilterChanged); + connect(searchWidget, &AzQtComponents::FilteredSearchWidget::TextFilterChanged, m_motionListWindow, &MotionListWindow::OnTextFilterChanged); toolBar->addWidget(searchWidget); // create the dialog stack - assert(mDialogStack == nullptr); - mDialogStack = new MysticQt::DialogStack(splitterWidget); - mDialogStack->setMinimumWidth(279); - splitterWidget->addWidget(mDialogStack); + assert(m_dialogStack == nullptr); + m_dialogStack = new MysticQt::DialogStack(splitterWidget); + m_dialogStack->setMinimumWidth(279); + splitterWidget->addWidget(m_dialogStack); // add the motion properties stack window - mMotionPropertiesWindow = new MotionPropertiesWindow(mDialogStack, this); - mMotionPropertiesWindow->Init(); - mDialogStack->Add(mMotionPropertiesWindow, "Motion Properties", false, true); + m_motionPropertiesWindow = new MotionPropertiesWindow(m_dialogStack, this); + m_motionPropertiesWindow->Init(); + m_dialogStack->Add(m_motionPropertiesWindow, "Motion Properties", false, true); // add the motion name label QWidget* motionName = new QWidget(); QBoxLayout* motionNameLayout = new QHBoxLayout(motionName); - mMotionNameLabel = new QLabel(); + m_motionNameLabel = new QLabel(); QLabel* label = new QLabel(tr("Motion name")); motionNameLayout->addWidget(label); - motionNameLayout->addWidget(mMotionNameLabel); + motionNameLayout->addWidget(m_motionNameLabel); motionNameLayout->setStretchFactor(label, 3); - motionNameLayout->setStretchFactor(mMotionNameLabel, 2); - mMotionPropertiesWindow->layout()->addWidget(motionName); + motionNameLayout->setStretchFactor(m_motionNameLabel, 2); + m_motionPropertiesWindow->layout()->addWidget(motionName); // add the motion extraction stack window - mMotionExtractionWindow = new MotionExtractionWindow(mDialogStack, this); - mMotionExtractionWindow->Init(); - mMotionPropertiesWindow->AddSubProperties(mMotionExtractionWindow); + m_motionExtractionWindow = new MotionExtractionWindow(m_dialogStack, this); + m_motionExtractionWindow->Init(); + m_motionPropertiesWindow->AddSubProperties(m_motionExtractionWindow); // add the motion retargeting stack window - mMotionRetargetingWindow = new MotionRetargetingWindow(mDialogStack, this); - mMotionRetargetingWindow->Init(); - mMotionPropertiesWindow->AddSubProperties(mMotionRetargetingWindow); + m_motionRetargetingWindow = new MotionRetargetingWindow(m_dialogStack, this); + m_motionRetargetingWindow->Init(); + m_motionPropertiesWindow->AddSubProperties(m_motionRetargetingWindow); - mMotionPropertiesWindow->FinalizeSubProperties(); + m_motionPropertiesWindow->FinalizeSubProperties(); // connect the window activation signal to refresh if reactivated - connect(mDock, &QDockWidget::visibilityChanged, this, &MotionWindowPlugin::VisibilityChanged); + connect(m_dock, &QDockWidget::visibilityChanged, this, &MotionWindowPlugin::VisibilityChanged); // update the new interface and return success UpdateInterface(); // initialize the dirty files callback - mDirtyFilesCallback = new SaveDirtyMotionFilesCallback(this); - GetMainWindow()->GetDirtyFileManager()->AddCallback(mDirtyFilesCallback); + m_dirtyFilesCallback = new SaveDirtyMotionFilesCallback(this); + GetMainWindow()->GetDirtyFileManager()->AddCallback(m_dirtyFilesCallback); return true; } void MotionWindowPlugin::OnAddMotions() { - const AZStd::vector filenames = GetMainWindow()->GetFileManager()->LoadMotionsFileDialog(mMotionListWindow); + const AZStd::vector filenames = GetMainWindow()->GetFileManager()->LoadMotionsFileDialog(m_motionListWindow); CommandSystem::LoadMotionsCommand(filenames); } @@ -294,7 +294,7 @@ namespace EMStudio // show the window if at least one failed remove motion if (!failedRemoveMotions.empty()) { - MotionListRemoveMotionsFailedWindow removeMotionsFailedWindow(mMotionListWindow, failedRemoveMotions); + MotionListRemoveMotionsFailedWindow removeMotionsFailedWindow(m_motionListWindow, failedRemoveMotions); removeMotionsFailedWindow.exec(); } } @@ -355,7 +355,7 @@ namespace EMStudio // find the lowest row selected int lowestRowSelected = AZStd::numeric_limits::max(); - const QList selectedItems = mMotionListWindow->GetMotionTable()->selectedItems(); + const QList selectedItems = m_motionListWindow->GetMotionTable()->selectedItems(); for (const QTableWidgetItem* selectedItem : selectedItems) { lowestRowSelected = AZStd::min(lowestRowSelected, selectedItem->row()); @@ -366,19 +366,19 @@ namespace EMStudio CommandSystem::RemoveMotions(motionsToRemove, &failedRemoveMotions); // selected the next row - if (lowestRowSelected > (mMotionListWindow->GetMotionTable()->rowCount() - 1)) + if (lowestRowSelected > (m_motionListWindow->GetMotionTable()->rowCount() - 1)) { - mMotionListWindow->GetMotionTable()->selectRow(lowestRowSelected - 1); + m_motionListWindow->GetMotionTable()->selectRow(lowestRowSelected - 1); } else { - mMotionListWindow->GetMotionTable()->selectRow(lowestRowSelected); + m_motionListWindow->GetMotionTable()->selectRow(lowestRowSelected); } // show the window if at least one failed remove motion if (!failedRemoveMotions.empty()) { - MotionListRemoveMotionsFailedWindow removeMotionsFailedWindow(mMotionListWindow, failedRemoveMotions); + MotionListRemoveMotionsFailedWindow removeMotionsFailedWindow(m_motionListWindow, failedRemoveMotions); removeMotionsFailedWindow.exec(); } } @@ -422,8 +422,8 @@ namespace EMStudio { if (!motion->GetIsOwnedByRuntime()) { - mMotionEntries.push_back(new MotionTableEntry(motion)); - return mMotionListWindow->AddMotionByID(motionID); + m_motionEntries.push_back(new MotionTableEntry(motion)); + return m_motionListWindow->AddMotionByID(motionID); } } } @@ -434,21 +434,21 @@ namespace EMStudio bool MotionWindowPlugin::RemoveMotionByIndex(size_t index) { - const uint32 motionID = mMotionEntries[index]->mMotionID; + const uint32 motionID = m_motionEntries[index]->m_motionId; - delete mMotionEntries[index]; - mMotionEntries.erase(mMotionEntries.begin() + index); + delete m_motionEntries[index]; + m_motionEntries.erase(m_motionEntries.begin() + index); - return mMotionListWindow->RemoveMotionByID(motionID); + return m_motionListWindow->RemoveMotionByID(motionID); } bool MotionWindowPlugin::RemoveMotionById(uint32 motionID) { - const size_t numMotionEntries = mMotionEntries.size(); + const size_t numMotionEntries = m_motionEntries.size(); for (size_t i = 0; i < numMotionEntries; ++i) { - if (mMotionEntries[i]->mMotionID == motionID) + if (m_motionEntries[i]->m_motionId == motionID) { return RemoveMotionByIndex(i); } @@ -471,15 +471,15 @@ namespace EMStudio } if (FindMotionEntryByID(motion->GetID()) == nullptr) { - mMotionEntries.push_back(new MotionTableEntry(motion)); + m_motionEntries.push_back(new MotionTableEntry(motion)); } } // iterate through all motions inside the motion window plugin - AZStd::erase_if(mMotionEntries, [](MotionTableEntry* entry) + AZStd::erase_if(m_motionEntries, [](MotionTableEntry* entry) { // check if the motion still is in the motion library, if not also remove it from the motion window plugin - if (EMotionFX::GetMotionManager().FindMotionIndexByID(entry->mMotionID) == InvalidIndex) + if (EMotionFX::GetMotionManager().FindMotionIndexByID(entry->m_motionId) == InvalidIndex) { delete entry; return true; @@ -488,13 +488,13 @@ namespace EMStudio }); // update the motion list window - mMotionListWindow->ReInit(); + m_motionListWindow->ReInit(); } void MotionWindowPlugin::UpdateMotions() { - mMotionRetargetingWindow->UpdateMotions(); + m_motionRetargetingWindow->UpdateMotions(); } @@ -518,30 +518,30 @@ namespace EMStudio const CommandSystem::SelectionList& selection = GetCommandManager()->GetCurrentSelection(); const bool hasSelectedMotions = selection.GetNumSelectedMotions() > 0; - if (mMotionNameLabel) + if (m_motionNameLabel) { MotionTableEntry* entry = hasSelectedMotions ? FindMotionEntryByID(selection.GetMotion(0)->GetID()) : nullptr; - EMotionFX::Motion* motion = entry ? entry->mMotion : nullptr; - mMotionNameLabel->setText(motion ? motion->GetName() : nullptr); + EMotionFX::Motion* motion = entry ? entry->m_motion : nullptr; + m_motionNameLabel->setText(motion ? motion->GetName() : nullptr); } - if (mSaveAction) + if (m_saveAction) { // related to the selected motions - mSaveAction->setEnabled(hasSelectedMotions); + m_saveAction->setEnabled(hasSelectedMotions); } - if (mMotionListWindow) + if (m_motionListWindow) { - mMotionListWindow->UpdateInterface(); + m_motionListWindow->UpdateInterface(); } - if (mMotionExtractionWindow) + if (m_motionExtractionWindow) { - mMotionExtractionWindow->UpdateInterface(); + m_motionExtractionWindow->UpdateInterface(); } - if (mMotionRetargetingWindow) + if (m_motionRetargetingWindow) { - mMotionRetargetingWindow->UpdateInterface(); + m_motionRetargetingWindow->UpdateInterface(); } } @@ -558,7 +558,7 @@ namespace EMStudio const size_t numSelectedActorInstances = selectionList.GetNumSelectedActorInstances(); const size_t numSelectedMotions = selectionList.GetNumSelectedMotions(); - mInternalMotionInstanceSelection.clear(); + s_internalMotionInstanceSelection.clear(); for (size_t i = 0; i < numSelectedActorInstances; ++i) { @@ -575,23 +575,23 @@ namespace EMStudio EMotionFX::MotionInstance* motionInstance = motionSystem->GetMotionInstance(k); if (motionInstance->GetMotion() == motion) { - mInternalMotionInstanceSelection.push_back(motionInstance); + s_internalMotionInstanceSelection.push_back(motionInstance); } } } } - return mInternalMotionInstanceSelection; + return s_internalMotionInstanceSelection; } MotionWindowPlugin::MotionTableEntry* MotionWindowPlugin::FindMotionEntryByID(uint32 motionID) { - const auto foundEntry = AZStd::find_if(begin(mMotionEntries), end(mMotionEntries), [motionID](const MotionTableEntry* entry) + const auto foundEntry = AZStd::find_if(begin(m_motionEntries), end(m_motionEntries), [motionID](const MotionTableEntry* entry) { - return entry->mMotionID == motionID; + return entry->m_motionId == motionID; }); - return foundEntry != end(mMotionEntries) ? *foundEntry : nullptr; + return foundEntry != end(m_motionEntries) ? *foundEntry : nullptr; } @@ -613,9 +613,9 @@ namespace EMStudio EMotionFX::PlayBackInfo* defaultPlayBackInfo = motion->GetDefaultPlayBackInfo(); // Don't blend in and out of the for previewing animations. We might only see a short bit of it for animations smaller than the blend in/out time. - defaultPlayBackInfo->mBlendInTime = 0.0f; - defaultPlayBackInfo->mBlendOutTime = 0.0f; - defaultPlayBackInfo->mFreezeAtLastFrame = (defaultPlayBackInfo->mNumLoops != EMFX_LOOPFOREVER); + defaultPlayBackInfo->m_blendInTime = 0.0f; + defaultPlayBackInfo->m_blendOutTime = 0.0f; + defaultPlayBackInfo->m_freezeAtLastFrame = (defaultPlayBackInfo->m_numLoops != EMFX_LOOPFOREVER); commandParameters = CommandSystem::CommandPlayMotion::PlayBackInfoToCommandParameters(defaultPlayBackInfo); @@ -655,7 +655,7 @@ namespace EMStudio continue; } - command = AZStd::string::format("StopMotionInstances -filename \"%s\"", entry->mMotion->GetFileName()); + command = AZStd::string::format("StopMotionInstances -filename \"%s\"", entry->m_motion->GetFileName()); commandGroup.AddCommandString(command); } @@ -669,7 +669,7 @@ namespace EMStudio void MotionWindowPlugin::Render(RenderPlugin* renderPlugin, EMStudioPlugin::RenderInfo* renderInfo) { - MCommon::RenderUtil* renderUtil = renderInfo->mRenderUtil; + MCommon::RenderUtil* renderUtil = renderInfo->m_renderUtil; // make sure the render objects are valid if (renderPlugin == nullptr || renderUtil == nullptr) @@ -682,8 +682,8 @@ namespace EMStudio // constructor MotionWindowPlugin::MotionTableEntry::MotionTableEntry(EMotionFX::Motion* motion) { - mMotionID = motion->GetID(); - mMotion = motion; + m_motionId = motion->GetID(); + m_motion = motion; } @@ -829,7 +829,7 @@ namespace EMStudio { MCORE_UNUSED(commandLine); CommandSystem::CommandImportMotion* importMotionCommand = static_cast(command); - return CallbackAddMotionByID(importMotionCommand->mOldMotionID); + return CallbackAddMotionByID(importMotionCommand->m_oldMotionId); } @@ -847,7 +847,7 @@ namespace EMStudio { MCORE_UNUSED(commandLine); CommandSystem::CommandRemoveMotion* removeMotionCommand = static_cast(command); - return CallbackRemoveMotion(removeMotionCommand->mOldMotionID); + return CallbackRemoveMotion(removeMotionCommand->m_oldMotionId); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionWindow/MotionWindowPlugin.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionWindow/MotionWindowPlugin.h index 0bd181e63b..7f4ebc3e78 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionWindow/MotionWindowPlugin.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MotionWindow/MotionWindowPlugin.h @@ -71,22 +71,22 @@ namespace EMStudio MotionTableEntry(EMotionFX::Motion* motion); - EMotionFX::Motion* mMotion; - uint32 mMotionID; + EMotionFX::Motion* m_motion; + uint32 m_motionId; }; MotionTableEntry* FindMotionEntryByID(uint32 motionID); - MCORE_INLINE size_t GetNumMotionEntries() { return mMotionEntries.size(); } - MCORE_INLINE MotionTableEntry* GetMotionEntry(size_t index) { return mMotionEntries[index]; } + MCORE_INLINE size_t GetNumMotionEntries() { return m_motionEntries.size(); } + MCORE_INLINE MotionTableEntry* GetMotionEntry(size_t index) { return m_motionEntries[index]; } bool AddMotion(uint32 motionID); bool RemoveMotionByIndex(size_t index); bool RemoveMotionById(uint32 motionID); static AZStd::vector& GetSelectedMotionInstances(); - MCORE_INLINE MotionRetargetingWindow* GetMotionRetargetingWindow() { return mMotionRetargetingWindow; } - MCORE_INLINE MotionExtractionWindow* GetMotionExtractionWindow() { return mMotionExtractionWindow; } - MCORE_INLINE MotionListWindow* GetMotionListWindow() { return mMotionListWindow; } + MCORE_INLINE MotionRetargetingWindow* GetMotionRetargetingWindow() { return m_motionRetargetingWindow; } + MCORE_INLINE MotionExtractionWindow* GetMotionExtractionWindow() { return m_motionExtractionWindow; } + MCORE_INLINE MotionListWindow* GetMotionListWindow() { return m_motionListWindow; } MCORE_INLINE const char* GetDefaultNodeSelectionLabelText() { return "Click to select node"; } int OnSaveDirtyMotions(); @@ -121,21 +121,21 @@ namespace EMStudio AZStd::vector m_callbacks; - AZStd::vector mMotionEntries; + AZStd::vector m_motionEntries; - MysticQt::DialogStack* mDialogStack; - MotionListWindow* mMotionListWindow; - MotionPropertiesWindow* mMotionPropertiesWindow; - MotionExtractionWindow* mMotionExtractionWindow; - MotionRetargetingWindow* mMotionRetargetingWindow; + MysticQt::DialogStack* m_dialogStack; + MotionListWindow* m_motionListWindow; + MotionPropertiesWindow* m_motionPropertiesWindow; + MotionExtractionWindow* m_motionExtractionWindow; + MotionRetargetingWindow* m_motionRetargetingWindow; - SaveDirtyMotionFilesCallback* mDirtyFilesCallback; + SaveDirtyMotionFilesCallback* m_dirtyFilesCallback; - QAction* mAddMotionsAction; - QAction* mSaveAction; + QAction* m_addMotionsAction; + QAction* m_saveAction; - QLabel* mMotionNameLabel; + QLabel* m_motionNameLabel; - static AZStd::vector mInternalMotionInstanceSelection; + static AZStd::vector s_internalMotionInstanceSelection; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeGroups/NodeGroupManagementWidget.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeGroups/NodeGroupManagementWidget.cpp index 84c281a18f..67aee6a5af 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeGroups/NodeGroupManagementWidget.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeGroups/NodeGroupManagementWidget.cpp @@ -32,8 +32,8 @@ namespace EMStudio : QDialog(parent) { // store the values - mActor = actor; - mNodeGroupName = nodeGroupName; + m_actor = actor; + m_nodeGroupName = nodeGroupName; // set the window title setWindowTitle("Rename Node Group"); @@ -48,23 +48,23 @@ namespace EMStudio layout->addWidget(new QLabel("Please enter the new node group name:")); // add the line edit - mLineEdit = new QLineEdit(); - connect(mLineEdit, &QLineEdit::textEdited, this, &NodeGroupManagementRenameWindow::TextEdited); - layout->addWidget(mLineEdit); + m_lineEdit = new QLineEdit(); + connect(m_lineEdit, &QLineEdit::textEdited, this, &NodeGroupManagementRenameWindow::TextEdited); + layout->addWidget(m_lineEdit); // set the current name and select all - mLineEdit->setText(nodeGroupName.c_str()); - mLineEdit->selectAll(); + m_lineEdit->setText(nodeGroupName.c_str()); + m_lineEdit->selectAll(); // create the button layout QHBoxLayout* buttonLayout = new QHBoxLayout(); - mOKButton = new QPushButton("OK"); + m_okButton = new QPushButton("OK"); QPushButton* cancelButton = new QPushButton("Cancel"); - buttonLayout->addWidget(mOKButton); + buttonLayout->addWidget(m_okButton); buttonLayout->addWidget(cancelButton); // connect the buttons - connect(mOKButton, &QPushButton::clicked, this, &NodeGroupManagementRenameWindow::Accepted); + connect(m_okButton, &QPushButton::clicked, this, &NodeGroupManagementRenameWindow::Accepted); connect(cancelButton, &QPushButton::clicked, this, &NodeGroupManagementRenameWindow::reject); // set the new layout @@ -78,44 +78,42 @@ namespace EMStudio const AZStd::string convertedNewName = text.toUtf8().data(); if (text.isEmpty()) { - //mErrorMsg->setVisible(false); - mOKButton->setEnabled(false); - GetManager()->SetWidgetAsInvalidInput(mLineEdit); + m_okButton->setEnabled(false); + GetManager()->SetWidgetAsInvalidInput(m_lineEdit); } - else if (mNodeGroupName == convertedNewName) + else if (m_nodeGroupName == convertedNewName) { - //mErrorMsg->setVisible(false); - mOKButton->setEnabled(true); - mLineEdit->setStyleSheet(""); + m_okButton->setEnabled(true); + m_lineEdit->setStyleSheet(""); } else { // find duplicate name, it can't be the same name because we already handle this case before - EMotionFX::NodeGroup* nodeGroup = mActor->FindNodeGroupByName(convertedNewName.c_str()); + EMotionFX::NodeGroup* nodeGroup = m_actor->FindNodeGroupByName(convertedNewName.c_str()); if (nodeGroup) { - mOKButton->setEnabled(false); - GetManager()->SetWidgetAsInvalidInput(mLineEdit); + m_okButton->setEnabled(false); + GetManager()->SetWidgetAsInvalidInput(m_lineEdit); return; } // no duplicate name found - mOKButton->setEnabled(true); - mLineEdit->setStyleSheet(""); + m_okButton->setEnabled(true); + m_lineEdit->setStyleSheet(""); } } void NodeGroupManagementRenameWindow::Accepted() { - const AZStd::string convertedNewName = mLineEdit->text().toUtf8().data(); + const AZStd::string convertedNewName = m_lineEdit->text().toUtf8().data(); // execute the command AZStd::string outResult; auto* command = aznew CommandSystem::CommandAdjustNodeGroup( GetCommandManager()->FindCommand(CommandSystem::CommandAdjustNodeGroup::s_commandName), - /*actorId=*/ mActor->GetID(), - /*name=*/ mNodeGroupName, + /*actorId=*/ m_actor->GetID(), + /*name=*/ m_nodeGroupName, /*newName=*/ convertedNewName ); if (GetCommandManager()->ExecuteCommand(command, outResult) == false) @@ -133,11 +131,11 @@ namespace EMStudio : QWidget(parent) { // init the button variables to nullptr - mAddButton = nullptr; - mRemoveButton = nullptr; - mClearButton = nullptr; - mNodeGroupsTable = nullptr; - mSelectedRow = MCORE_INVALIDINDEX32; + m_addButton = nullptr; + m_removeButton = nullptr; + m_clearButton = nullptr; + m_nodeGroupsTable = nullptr; + m_selectedRow = MCORE_INVALIDINDEX32; // set the node group widget SetNodeGroupWidget(nodeGroupWidget); @@ -157,20 +155,20 @@ namespace EMStudio void NodeGroupManagementWidget::Init() { // create the node groups table - mNodeGroupsTable = new QTableWidget(); + m_nodeGroupsTable = new QTableWidget(); // create the table widget - mNodeGroupsTable->setAlternatingRowColors(true); - mNodeGroupsTable->setCornerButtonEnabled(false); - mNodeGroupsTable->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); - mNodeGroupsTable->setContextMenuPolicy(Qt::DefaultContextMenu); + m_nodeGroupsTable->setAlternatingRowColors(true); + m_nodeGroupsTable->setCornerButtonEnabled(false); + m_nodeGroupsTable->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); + m_nodeGroupsTable->setContextMenuPolicy(Qt::DefaultContextMenu); // set the table to row single selection - mNodeGroupsTable->setSelectionBehavior(QAbstractItemView::SelectRows); - mNodeGroupsTable->setSelectionMode(QAbstractItemView::SingleSelection); + m_nodeGroupsTable->setSelectionBehavior(QAbstractItemView::SelectRows); + m_nodeGroupsTable->setSelectionMode(QAbstractItemView::SingleSelection); // set the column count - mNodeGroupsTable->setColumnCount(3); + m_nodeGroupsTable->setColumnCount(3); // set header items for the table QTableWidgetItem* enabledHeaderItem = new QTableWidgetItem(""); @@ -178,44 +176,44 @@ namespace EMStudio QTableWidgetItem* numNodesHeaderItem = new QTableWidgetItem("Num Nodes"); nameHeaderItem->setTextAlignment(Qt::AlignVCenter | Qt::AlignLeft); numNodesHeaderItem->setTextAlignment(Qt::AlignVCenter | Qt::AlignLeft); - mNodeGroupsTable->setHorizontalHeaderItem(0, enabledHeaderItem); - mNodeGroupsTable->setHorizontalHeaderItem(1, nameHeaderItem); - mNodeGroupsTable->setHorizontalHeaderItem(2, numNodesHeaderItem); + m_nodeGroupsTable->setHorizontalHeaderItem(0, enabledHeaderItem); + m_nodeGroupsTable->setHorizontalHeaderItem(1, nameHeaderItem); + m_nodeGroupsTable->setHorizontalHeaderItem(2, numNodesHeaderItem); // set the first column fixed - QHeaderView* horizontalHeader = mNodeGroupsTable->horizontalHeader(); - mNodeGroupsTable->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Fixed); - mNodeGroupsTable->setColumnWidth(0, 19); + QHeaderView* horizontalHeader = m_nodeGroupsTable->horizontalHeader(); + m_nodeGroupsTable->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Fixed); + m_nodeGroupsTable->setColumnWidth(0, 19); // set the name column width - mNodeGroupsTable->setColumnWidth(1, 150); + m_nodeGroupsTable->setColumnWidth(1, 150); // set the vertical columns not visible - QHeaderView* verticalHeader = mNodeGroupsTable->verticalHeader(); + QHeaderView* verticalHeader = m_nodeGroupsTable->verticalHeader(); verticalHeader->setVisible(false); // set the last column to take the whole space horizontalHeader->setStretchLastSection(true); // disable editing - mNodeGroupsTable->setEditTriggers(QAbstractItemView::NoEditTriggers); + m_nodeGroupsTable->setEditTriggers(QAbstractItemView::NoEditTriggers); // create buttons - mAddButton = new QPushButton(); - mRemoveButton = new QPushButton(); - mClearButton = new QPushButton(); + m_addButton = new QPushButton(); + m_removeButton = new QPushButton(); + m_clearButton = new QPushButton(); - EMStudioManager::MakeTransparentButton(mAddButton, "Images/Icons/Plus.svg", "Add a new node group"); - EMStudioManager::MakeTransparentButton(mRemoveButton, "Images/Icons/Minus.svg", "Remove selected node groups"); - EMStudioManager::MakeTransparentButton(mClearButton, "Images/Icons/Clear.svg", "Remove all node groups"); + EMStudioManager::MakeTransparentButton(m_addButton, "Images/Icons/Plus.svg", "Add a new node group"); + EMStudioManager::MakeTransparentButton(m_removeButton, "Images/Icons/Minus.svg", "Remove selected node groups"); + EMStudioManager::MakeTransparentButton(m_clearButton, "Images/Icons/Clear.svg", "Remove all node groups"); // add the buttons to the button layout QHBoxLayout* buttonLayout = new QHBoxLayout(); buttonLayout->setSpacing(0); buttonLayout->setAlignment(Qt::AlignLeft); - buttonLayout->addWidget(mAddButton); - buttonLayout->addWidget(mRemoveButton); - buttonLayout->addWidget(mClearButton); + buttonLayout->addWidget(m_addButton); + buttonLayout->addWidget(m_removeButton); + buttonLayout->addWidget(m_clearButton); // create the layouts QVBoxLayout* layout = new QVBoxLayout(); @@ -226,18 +224,16 @@ namespace EMStudio // add widgets to the main layout layout->addLayout(buttonLayout); - layout->addWidget(mNodeGroupsTable); + layout->addWidget(m_nodeGroupsTable); // set the main layout setLayout(layout); // connect controls to the slots - connect(mAddButton, &QPushButton::clicked, this, &NodeGroupManagementWidget::AddNodeGroup); - connect(mRemoveButton, &QPushButton::clicked, this, &NodeGroupManagementWidget::RemoveSelectedNodeGroup); - connect(mClearButton, &QPushButton::clicked, this, &NodeGroupManagementWidget::ClearNodeGroups); - connect(mNodeGroupsTable, &QTableWidget::itemSelectionChanged, this, &NodeGroupManagementWidget::UpdateNodeGroupWidget); - //connect( mNodeGroupsTable, SIGNAL(currentItemChanged(QTableWidgetItem*, QTableWidgetItem*)), this, SLOT(UpdateNodeGroupWidget(QTableWidgetItem*, QTableWidgetItem*)) ); - //connect( mNodeGroupsTable, SIGNAL(itemDoubleClicked(QTableWidgetItem*)), this, SLOT(NodeGroupeNameDoubleClicked(QTableWidgetItem*)) ); + connect(m_addButton, &QPushButton::clicked, this, &NodeGroupManagementWidget::AddNodeGroup); + connect(m_removeButton, &QPushButton::clicked, this, &NodeGroupManagementWidget::RemoveSelectedNodeGroup); + connect(m_clearButton, &QPushButton::clicked, this, &NodeGroupManagementWidget::ClearNodeGroups); + connect(m_nodeGroupsTable, &QTableWidget::itemSelectionChanged, this, &NodeGroupManagementWidget::UpdateNodeGroupWidget); } @@ -245,35 +241,35 @@ namespace EMStudio void NodeGroupManagementWidget::UpdateInterface() { // check if the current actor exists - if (mActor == nullptr) + if (m_actor == nullptr) { // remove all rows - mNodeGroupsTable->setRowCount(0); + m_nodeGroupsTable->setRowCount(0); // disable the controls - mAddButton->setDisabled(true); - mRemoveButton->setDisabled(true); - mClearButton->setDisabled(true); + m_addButton->setDisabled(true); + m_removeButton->setDisabled(true); + m_clearButton->setDisabled(true); // stop here return; } // enable/disable the controls - mAddButton->setDisabled(false); - const bool disableButtons = mActor->GetNumNodeGroups() == 0; - mRemoveButton->setDisabled(disableButtons); - mClearButton->setDisabled(disableButtons); + m_addButton->setDisabled(false); + const bool disableButtons = m_actor->GetNumNodeGroups() == 0; + m_removeButton->setDisabled(disableButtons); + m_clearButton->setDisabled(disableButtons); // set the row count - mNodeGroupsTable->setRowCount(mActor->GetNumNodeGroups()); + m_nodeGroupsTable->setRowCount(m_actor->GetNumNodeGroups()); // fill the table with the existing node groups - const uint32 numNodeGroups = mActor->GetNumNodeGroups(); + const uint32 numNodeGroups = m_actor->GetNumNodeGroups(); for (uint32 i = 0; i < numNodeGroups; ++i) { // get the nodegroup - EMotionFX::NodeGroup* nodeGroup = mActor->GetNodeGroup(i); + EMotionFX::NodeGroup* nodeGroup = m_actor->GetNodeGroup(i); // continue if node group does not exist if (nodeGroup == nullptr) @@ -295,18 +291,18 @@ namespace EMStudio QTableWidgetItem* tableItemNumNodes = new QTableWidgetItem(numGroupString.c_str()); // add items to the table - mNodeGroupsTable->setCellWidget(i, 0, checkbox); - mNodeGroupsTable->setItem(i, 1, tableItemGroupName); - mNodeGroupsTable->setItem(i, 2, tableItemNumNodes); + m_nodeGroupsTable->setCellWidget(i, 0, checkbox); + m_nodeGroupsTable->setItem(i, 1, tableItemGroupName); + m_nodeGroupsTable->setItem(i, 2, tableItemNumNodes); // set the row height - mNodeGroupsTable->setRowHeight(i, 21); + m_nodeGroupsTable->setRowHeight(i, 21); } // set the old selected row if any one - if (mSelectedRow != MCORE_INVALIDINDEX32) + if (m_selectedRow != MCORE_INVALIDINDEX32) { - mNodeGroupsTable->setCurrentCell(mSelectedRow, 0); + m_nodeGroupsTable->setCurrentCell(m_selectedRow, 0); } } @@ -315,7 +311,7 @@ namespace EMStudio void NodeGroupManagementWidget::SetActor(EMotionFX::Actor* actor) { // set the new actor - mActor = actor; + m_actor = actor; // update the interface UpdateInterface(); @@ -326,7 +322,7 @@ namespace EMStudio void NodeGroupManagementWidget::SetNodeGroupWidget(NodeGroupWidget* nodeGroupWidget) { // set the node group widget - mNodeGroupWidget = nodeGroupWidget; + m_nodeGroupWidget = nodeGroupWidget; } @@ -334,37 +330,37 @@ namespace EMStudio void NodeGroupManagementWidget::UpdateNodeGroupWidget() { // return if no node group widget is set - if (mNodeGroupWidget == nullptr) + if (m_nodeGroupWidget == nullptr) { return; } // set the node group widget to the actual selection - mNodeGroupWidget->SetActor(mActor); + m_nodeGroupWidget->SetActor(m_actor); // return if the actor is not valid - if (mActor == nullptr) + if (m_actor == nullptr) { return; } // get the current row - const int currentRow = mNodeGroupsTable->currentRow(); + const int currentRow = m_nodeGroupsTable->currentRow(); // check if the row is valid if (currentRow != -1) { // set the current row - mSelectedRow = currentRow; + m_selectedRow = currentRow; // set the node group - EMotionFX::NodeGroup* nodeGroup = mActor->FindNodeGroupByName(FromQtString(mNodeGroupsTable->item(mSelectedRow, 1)->text()).c_str()); - mNodeGroupWidget->SetNodeGroup(nodeGroup); + EMotionFX::NodeGroup* nodeGroup = m_actor->FindNodeGroupByName(FromQtString(m_nodeGroupsTable->item(m_selectedRow, 1)->text()).c_str()); + m_nodeGroupWidget->SetNodeGroup(nodeGroup); } else { - mNodeGroupWidget->SetNodeGroup(nullptr); - mSelectedRow = MCORE_INVALIDINDEX32; + m_nodeGroupWidget->SetNodeGroup(nullptr); + m_selectedRow = MCORE_INVALIDINDEX32; } } @@ -375,7 +371,7 @@ namespace EMStudio // find the node group index to add uint32 groupNumber = 0; AZStd::string groupName = AZStd::string::format("UnnamedNodeGroup%i", groupNumber); - while (SearchTableForString(mNodeGroupsTable, groupName.c_str(), true) >= 0) + while (SearchTableForString(m_nodeGroupsTable, groupName.c_str(), true) >= 0) { ++groupNumber; groupName = AZStd::string::format("UnnamedNodeGroup%i", groupNumber); @@ -383,20 +379,15 @@ namespace EMStudio // call command for adding a new node group AZStd::string outResult; - const AZStd::string command = AZStd::string::format("AddNodeGroup -actorID %i -name \"%s\"", mActor->GetID(), groupName.c_str()); + const AZStd::string command = AZStd::string::format("AddNodeGroup -actorID %i -name \"%s\"", m_actor->GetID(), groupName.c_str()); if (EMStudio::GetCommandManager()->ExecuteCommand(command.c_str(), outResult) == false) { AZ_Error("EMotionFX", false, outResult.c_str()); } // select the new added row - const int insertPosition = SearchTableForString(mNodeGroupsTable, groupName.c_str()); - mNodeGroupsTable->selectRow(insertPosition); - - // find insert position - /*int insertPosition = SearchTableForString( mNodeGroupsTable, groupName.c_str() ); - if (insertPosition >= 0) - NodeGroupeNameDoubleClicked( mNodeGroupsTable->item(insertPosition, 0) );*/ + const int insertPosition = SearchTableForString(m_nodeGroupsTable, groupName.c_str()); + m_nodeGroupsTable->selectRow(insertPosition); } @@ -404,38 +395,38 @@ namespace EMStudio void NodeGroupManagementWidget::RemoveSelectedNodeGroup() { // set the node group of the node group widget to nullptr - if (mNodeGroupWidget) + if (m_nodeGroupWidget) { - mNodeGroupWidget->SetNodeGroup(nullptr); + m_nodeGroupWidget->SetNodeGroup(nullptr); } // return if there is no entry to delete - const int currentRow = mNodeGroupsTable->currentRow(); + const int currentRow = m_nodeGroupsTable->currentRow(); if (currentRow < 0) { return; } // get the nodegroup - QTableWidgetItem* item = mNodeGroupsTable->item(currentRow, 1); - EMotionFX::NodeGroup* nodeGroup = mActor->FindNodeGroupByName(FromQtString(item->text()).c_str()); + QTableWidgetItem* item = m_nodeGroupsTable->item(currentRow, 1); + EMotionFX::NodeGroup* nodeGroup = m_actor->FindNodeGroupByName(FromQtString(item->text()).c_str()); // call command for removing a nodegroup AZStd::string outResult; - const AZStd::string command = AZStd::string::format("RemoveNodeGroup -actorID %i -name \"%s\"", mActor->GetID(), nodeGroup->GetName()); + const AZStd::string command = AZStd::string::format("RemoveNodeGroup -actorID %i -name \"%s\"", m_actor->GetID(), nodeGroup->GetName()); if (EMStudio::GetCommandManager()->ExecuteCommand(command.c_str(), outResult) == false) { AZ_Error("EMotionFX", false, outResult.c_str()); } // selected the next row - if (currentRow > (mNodeGroupsTable->rowCount() - 1)) + if (currentRow > (m_nodeGroupsTable->rowCount() - 1)) { - mNodeGroupsTable->selectRow(currentRow - 1); + m_nodeGroupsTable->selectRow(currentRow - 1); } else { - mNodeGroupsTable->selectRow(currentRow); + m_nodeGroupsTable->selectRow(currentRow); } } @@ -444,11 +435,11 @@ namespace EMStudio void NodeGroupManagementWidget::RenameSelectedNodeGroup() { // get the nodegroup - QTableWidgetItem* item = mNodeGroupsTable->item(mNodeGroupsTable->currentRow(), 1); - EMotionFX::NodeGroup* nodeGroup = mActor->FindNodeGroupByName(FromQtString(item->text()).c_str()); + QTableWidgetItem* item = m_nodeGroupsTable->item(m_nodeGroupsTable->currentRow(), 1); + EMotionFX::NodeGroup* nodeGroup = m_actor->FindNodeGroupByName(FromQtString(item->text()).c_str()); // show the rename window - NodeGroupManagementRenameWindow nodeGroupManagementRenameWindow(this, mActor, nodeGroup->GetName()); + NodeGroupManagementRenameWindow nodeGroupManagementRenameWindow(this, m_actor, nodeGroup->GetName()); nodeGroupManagementRenameWindow.exec(); } @@ -456,7 +447,7 @@ namespace EMStudio // function to clear the nodegroups void NodeGroupManagementWidget::ClearNodeGroups() { - CommandSystem::ClearNodeGroupsCommand(mActor); + CommandSystem::ClearNodeGroupsCommand(m_actor); } @@ -468,13 +459,13 @@ namespace EMStudio // find the checkbox row AZStd::string nodeGroupName; - const int rowCount = mNodeGroupsTable->rowCount(); + const int rowCount = m_nodeGroupsTable->rowCount(); for (int i = 0; i < rowCount; ++i) { - QCheckBox* rowChechbox = (QCheckBox*)mNodeGroupsTable->cellWidget(i, 0); + QCheckBox* rowChechbox = (QCheckBox*)m_nodeGroupsTable->cellWidget(i, 0); if (rowChechbox == senderCheckbox) { - nodeGroupName = mNodeGroupsTable->item(i, 1)->text().toUtf8().data(); + nodeGroupName = m_nodeGroupsTable->item(i, 1)->text().toUtf8().data(); break; } } @@ -483,7 +474,7 @@ namespace EMStudio AZStd::string outResult; auto* command = aznew CommandSystem::CommandAdjustNodeGroup( GetCommandManager()->FindCommand(CommandSystem::CommandAdjustNodeGroup::s_commandName), - /*actorId=*/ mActor->GetID(), + /*actorId=*/ m_actor->GetID(), /*name=*/ nodeGroupName, /*newName=*/ AZStd::nullopt, /*enabledOnDefault=*/ checked @@ -560,13 +551,13 @@ namespace EMStudio void NodeGroupManagementWidget::contextMenuEvent(QContextMenuEvent* event) { // if the actor is not valid, the node group management is disabled - if (mActor == nullptr) + if (m_actor == nullptr) { return; } // get the current selection - const QList selectedItems = mNodeGroupsTable->selectedItems(); + const QList selectedItems = m_nodeGroupsTable->selectedItems(); // get the number of selected items const uint32 numSelectedItems = selectedItems.count(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeGroups/NodeGroupManagementWidget.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeGroups/NodeGroupManagementWidget.h index a7a8616edc..37f92346e4 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeGroups/NodeGroupManagementWidget.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeGroups/NodeGroupManagementWidget.h @@ -39,10 +39,10 @@ namespace EMStudio void Accepted(); private: - EMotionFX::Actor* mActor; - AZStd::string mNodeGroupName; - QLineEdit* mLineEdit; - QPushButton* mOKButton; + EMotionFX::Actor* m_actor; + AZStd::string m_nodeGroupName; + QLineEdit* m_lineEdit; + QPushButton* m_okButton; }; @@ -91,21 +91,21 @@ namespace EMStudio private: // pointer to the nodegroup widget - NodeGroupWidget* mNodeGroupWidget; + NodeGroupWidget* m_nodeGroupWidget; // searches for the given text in the table int SearchTableForString(QTableWidget* tableWidget, const QString& text, bool ignoreCurrentSelection = false); // the actor - EMotionFX::Actor* mActor; + EMotionFX::Actor* m_actor; // the listbox - QTableWidget* mNodeGroupsTable; - uint32 mSelectedRow; + QTableWidget* m_nodeGroupsTable; + uint32 m_selectedRow; // the buttons - QPushButton* mAddButton; - QPushButton* mRemoveButton; - QPushButton* mClearButton; + QPushButton* m_addButton; + QPushButton* m_removeButton; + QPushButton* m_clearButton; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeGroups/NodeGroupWidget.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeGroups/NodeGroupWidget.cpp index 1a95899c32..7ce09a55d7 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeGroups/NodeGroupWidget.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeGroups/NodeGroupWidget.cpp @@ -33,10 +33,9 @@ namespace EMStudio NodeGroupWidget::NodeGroupWidget(QWidget* parent) : QWidget(parent) { - //mEnabledOnDefaultCheckbox = nullptr; - mNodeTable = nullptr; - mSelectNodesButton = nullptr; - mNodeGroup = nullptr; + m_nodeTable = nullptr; + m_selectNodesButton = nullptr; + m_nodeGroup = nullptr; // init the widget Init(); @@ -52,60 +51,48 @@ namespace EMStudio // the init function void NodeGroupWidget::Init() { - // create the disable checkbox - //mEnabledOnDefaultCheckbox = new QCheckBox( "Enabled On Default" ); - - // edit field for the group name - //mNodeGroupNameEdit = new QLineEdit(); - // create the node groups table - mNodeTable = new QTableWidget(0, 1, 0); + m_nodeTable = new QTableWidget(0, 1, 0); // create the table widget - mNodeTable->setCornerButtonEnabled(false); - mNodeTable->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); - mNodeTable->setContextMenuPolicy(Qt::DefaultContextMenu); + m_nodeTable->setCornerButtonEnabled(false); + m_nodeTable->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); + m_nodeTable->setContextMenuPolicy(Qt::DefaultContextMenu); // set the table to row selection - mNodeTable->setSelectionBehavior(QAbstractItemView::SelectRows); + m_nodeTable->setSelectionBehavior(QAbstractItemView::SelectRows); // make the table items read only - mNodeTable->setEditTriggers(QAbstractItemView::NoEditTriggers); + m_nodeTable->setEditTriggers(QAbstractItemView::NoEditTriggers); // set header items for the table QTableWidgetItem* nameHeaderItem = new QTableWidgetItem("Nodes"); nameHeaderItem->setTextAlignment(Qt::AlignVCenter | Qt::AlignLeft); - mNodeTable->setHorizontalHeaderItem(0, nameHeaderItem); + m_nodeTable->setHorizontalHeaderItem(0, nameHeaderItem); - QHeaderView* horizontalHeader = mNodeTable->horizontalHeader(); + QHeaderView* horizontalHeader = m_nodeTable->horizontalHeader(); horizontalHeader->setStretchLastSection(true); // create the node selection window - mNodeSelectionWindow = new NodeSelectionWindow(this, false); + m_nodeSelectionWindow = new NodeSelectionWindow(this, false); // create the selection buttons - mSelectNodesButton = new QPushButton(); - mAddNodesButton = new QPushButton(); - mRemoveNodesButton = new QPushButton(); + m_selectNodesButton = new QPushButton(); + m_addNodesButton = new QPushButton(); + m_removeNodesButton = new QPushButton(); - EMStudioManager::MakeTransparentButton(mSelectNodesButton, "Images/Icons/Plus.svg", "Select nodes and replace the current selection"); - EMStudioManager::MakeTransparentButton(mAddNodesButton, "Images/Icons/Plus.svg", "Select nodes and add them to the current selection"); - EMStudioManager::MakeTransparentButton(mRemoveNodesButton, "Images/Icons/Minus.svg", "Remove selected nodes from the list"); + EMStudioManager::MakeTransparentButton(m_selectNodesButton, "Images/Icons/Plus.svg", "Select nodes and replace the current selection"); + EMStudioManager::MakeTransparentButton(m_addNodesButton, "Images/Icons/Plus.svg", "Select nodes and add them to the current selection"); + EMStudioManager::MakeTransparentButton(m_removeNodesButton, "Images/Icons/Minus.svg", "Remove selected nodes from the list"); // create the buttons layout QHBoxLayout* buttonLayout = new QHBoxLayout(); buttonLayout->setSpacing(0); buttonLayout->setAlignment(Qt::AlignLeft); - buttonLayout->addWidget(mSelectNodesButton); - buttonLayout->addWidget(mAddNodesButton); - buttonLayout->addWidget(mRemoveNodesButton); - - // create layout for the edit field - /*QHBoxLayout* editLayout = new QHBoxLayout(); - editLayout->addWidget( new QLabel("Name:") ); - editLayout->addWidget( mNodeGroupNameEdit ); - editLayout->addWidget( mEnabledOnDefaultCheckbox );*/ + buttonLayout->addWidget(m_selectNodesButton); + buttonLayout->addWidget(m_addNodesButton); + buttonLayout->addWidget(m_removeNodesButton); // create the layouts QVBoxLayout* layout = new QVBoxLayout(); @@ -116,7 +103,7 @@ namespace EMStudio tableLayout->setMargin(0); tableLayout->addLayout(buttonLayout); - tableLayout->addWidget(mNodeTable); + tableLayout->addWidget(m_nodeTable); layout->addLayout(tableLayout); //layout->addLayout( editLayout ); @@ -125,12 +112,12 @@ namespace EMStudio setLayout(layout); // connect controls to the slots - connect(mSelectNodesButton, &QPushButton::clicked, this, &NodeGroupWidget::SelectNodesButtonPressed); - connect(mAddNodesButton, &QPushButton::clicked, this, &NodeGroupWidget::SelectNodesButtonPressed); - connect(mRemoveNodesButton, &QPushButton::clicked, this, &NodeGroupWidget::RemoveNodesButtonPressed); - connect(mNodeTable, &QTableWidget::itemSelectionChanged, this, &NodeGroupWidget::OnItemSelectionChanged); - connect(mNodeSelectionWindow->GetNodeHierarchyWidget(), &NodeHierarchyWidget::OnSelectionDone, this, &NodeGroupWidget::NodeSelectionFinished); - connect(mNodeSelectionWindow->GetNodeHierarchyWidget(), &NodeHierarchyWidget::OnDoubleClicked, this, &NodeGroupWidget::NodeSelectionFinished); + connect(m_selectNodesButton, &QPushButton::clicked, this, &NodeGroupWidget::SelectNodesButtonPressed); + connect(m_addNodesButton, &QPushButton::clicked, this, &NodeGroupWidget::SelectNodesButtonPressed); + connect(m_removeNodesButton, &QPushButton::clicked, this, &NodeGroupWidget::RemoveNodesButtonPressed); + connect(m_nodeTable, &QTableWidget::itemSelectionChanged, this, &NodeGroupWidget::OnItemSelectionChanged); + connect(m_nodeSelectionWindow->GetNodeHierarchyWidget(), &NodeHierarchyWidget::OnSelectionDone, this, &NodeGroupWidget::NodeSelectionFinished); + connect(m_nodeSelectionWindow->GetNodeHierarchyWidget(), &NodeHierarchyWidget::OnDoubleClicked, this, &NodeGroupWidget::NodeSelectionFinished); } @@ -138,48 +125,45 @@ namespace EMStudio void NodeGroupWidget::UpdateInterface() { // clear the table widget - mNodeTable->clear(); + m_nodeTable->clear(); // check if the node group is not valid - if (mNodeGroup == nullptr) + if (m_nodeGroup == nullptr) { // set the column count - mNodeTable->setColumnCount(0); + m_nodeTable->setColumnCount(0); // disable the widgets SetWidgetEnabled(false); - // clear the edit field - //mNodeGroupNameEdit->setText( "" ); - // stop here return; } // set the column count - mNodeTable->setColumnCount(1); + m_nodeTable->setColumnCount(1); // enable the widget SetWidgetEnabled(true); // set the remove nodes button enabled or not based on selection - mRemoveNodesButton->setEnabled((mNodeTable->rowCount() != 0) && (mNodeTable->selectedItems().size() != 0)); + m_removeNodesButton->setEnabled((m_nodeTable->rowCount() != 0) && (m_nodeTable->selectedItems().size() != 0)); // clear the table widget - mNodeTable->setRowCount(mNodeGroup->GetNumNodes()); + m_nodeTable->setRowCount(m_nodeGroup->GetNumNodes()); // set header items for the table - AZStd::string headerText = AZStd::string::format("%s Nodes (%i / %zu)", ((mNodeGroup->GetIsEnabledOnDefault()) ? "Enabled" : "Disabled"), mNodeGroup->GetNumNodes(), mActor->GetNumNodes()); + AZStd::string headerText = AZStd::string::format("%s Nodes (%i / %zu)", ((m_nodeGroup->GetIsEnabledOnDefault()) ? "Enabled" : "Disabled"), m_nodeGroup->GetNumNodes(), m_actor->GetNumNodes()); QTableWidgetItem* nameHeaderItem = new QTableWidgetItem(headerText.c_str()); nameHeaderItem->setTextAlignment(Qt::AlignVCenter | Qt::AlignCenter); - mNodeTable->setHorizontalHeaderItem(0, nameHeaderItem); + m_nodeTable->setHorizontalHeaderItem(0, nameHeaderItem); // fill the table with content - const uint16 numNodes = mNodeGroup->GetNumNodes(); + const uint16 numNodes = m_nodeGroup->GetNumNodes(); for (uint16 i = 0; i < numNodes; ++i) { // get the nodegroup - EMotionFX::Node* node = mActor->GetSkeleton()->GetNode(mNodeGroup->GetNode(i)); + EMotionFX::Node* node = m_actor->GetSkeleton()->GetNode(m_nodeGroup->GetNode(i)); // continue if node does not exist if (node == nullptr) @@ -189,23 +173,23 @@ namespace EMStudio // create table items QTableWidgetItem* tableItemNodeName = new QTableWidgetItem(node->GetName()); - mNodeTable->setItem(i, 0, tableItemNodeName); + m_nodeTable->setItem(i, 0, tableItemNodeName); // set the row height - mNodeTable->setRowHeight(i, 21); + m_nodeTable->setRowHeight(i, 21); } // resize to contents and adjust header - QHeaderView* verticalHeader = mNodeTable->verticalHeader(); + QHeaderView* verticalHeader = m_nodeTable->verticalHeader(); verticalHeader->setVisible(false); - mNodeTable->resizeColumnsToContents(); - mNodeTable->horizontalHeader()->setStretchLastSection(true); + m_nodeTable->resizeColumnsToContents(); + m_nodeTable->horizontalHeader()->setStretchLastSection(true); // set table size - mNodeTable->setColumnWidth(0, 37); - mNodeTable->setColumnWidth(3, 0); - mNodeTable->setColumnHidden(3, true); - mNodeTable->sortItems(3); + m_nodeTable->setColumnWidth(0, 37); + m_nodeTable->setColumnWidth(3, 0); + m_nodeTable->setColumnHidden(3, true); + m_nodeTable->sortItems(3); } @@ -213,14 +197,14 @@ namespace EMStudio void NodeGroupWidget::SetNodeGroup(EMotionFX::NodeGroup* nodeGroup) { // check if the actor was set - if (mActor == nullptr) + if (m_actor == nullptr) { - mNodeGroup = nullptr; + m_nodeGroup = nullptr; return; } // set the node group - mNodeGroup = nodeGroup; + m_nodeGroup = nodeGroup; // update the interface UpdateInterface(); @@ -231,8 +215,8 @@ namespace EMStudio void NodeGroupWidget::SetActor(EMotionFX::Actor* actor) { // set the new actor - mActor = actor; - mNodeGroup = nullptr; + m_actor = actor; + m_nodeGroup = nullptr; // update the interface UpdateInterface(); @@ -243,20 +227,20 @@ namespace EMStudio void NodeGroupWidget::SelectNodesButtonPressed() { // check if node group is set - if (mNodeGroup == nullptr) + if (m_nodeGroup == nullptr) { return; } // set the action for the selected nodes QWidget* senderWidget = (QWidget*)sender(); - if (senderWidget == mAddNodesButton) + if (senderWidget == m_addNodesButton) { - mNodeAction = CommandSystem::CommandAdjustNodeGroup::NodeAction::Add; + m_nodeAction = CommandSystem::CommandAdjustNodeGroup::NodeAction::Add; } else { - mNodeAction = CommandSystem::CommandAdjustNodeGroup::NodeAction::Replace; + m_nodeAction = CommandSystem::CommandAdjustNodeGroup::NodeAction::Replace; } // get the selected actorinstance @@ -270,28 +254,28 @@ namespace EMStudio } // create selection list for the current nodes within the group - mNodeSelectionList.Clear(); - if (senderWidget == mSelectNodesButton) + m_nodeSelectionList.Clear(); + if (senderWidget == m_selectNodesButton) { - MCore::SmallArray& nodes = mNodeGroup->GetNodeArray(); + MCore::SmallArray& nodes = m_nodeGroup->GetNodeArray(); const uint16 numNodes = nodes.GetLength(); for (uint16 i = 0; i < numNodes; ++i) { - EMotionFX::Node* node = mActor->GetSkeleton()->GetNode(nodes[i]); - mNodeSelectionList.AddNode(node); + EMotionFX::Node* node = m_actor->GetSkeleton()->GetNode(nodes[i]); + m_nodeSelectionList.AddNode(node); } } // show the node selection window - mNodeSelectionWindow->Update(actorInstance->GetID(), &mNodeSelectionList); - mNodeSelectionWindow->show(); + m_nodeSelectionWindow->Update(actorInstance->GetID(), &m_nodeSelectionList); + m_nodeSelectionWindow->show(); } // remove nodes void NodeGroupWidget::RemoveNodesButtonPressed() { - if (mNodeTable->selectedItems().empty()) + if (m_nodeTable->selectedItems().empty()) { return; } @@ -299,7 +283,7 @@ namespace EMStudio // generate node list string AZStd::vector nodeList; int lowestSelectedRow = AZStd::numeric_limits::max(); - for (const QTableWidgetItem* item : mNodeTable->selectedItems()) + for (const QTableWidgetItem* item : m_nodeTable->selectedItems()) { nodeList.emplace_back(FromQtString(item->text())); lowestSelectedRow = AZStd::min(lowestSelectedRow, item->row()); @@ -308,8 +292,8 @@ namespace EMStudio AZStd::string outResult; auto* command = aznew CommandSystem::CommandAdjustNodeGroup( GetCommandManager()->FindCommand(CommandSystem::CommandAdjustNodeGroup::s_commandName), - /*actorId=*/ mActor->GetID(), - /*name=*/ mNodeGroup->GetName(), + /*actorId=*/ m_actor->GetID(), + /*name=*/ m_nodeGroup->GetName(), /*newName=*/ AZStd::nullopt, /*enabledOnDefault=*/ AZStd::nullopt, /*nodeNames=*/ AZStd::move(nodeList), @@ -321,13 +305,13 @@ namespace EMStudio } // selected the next row - if (lowestSelectedRow > (mNodeTable->rowCount() - 1)) + if (lowestSelectedRow > (m_nodeTable->rowCount() - 1)) { - mNodeTable->selectRow(lowestSelectedRow - 1); + m_nodeTable->selectRow(lowestSelectedRow - 1); } else { - mNodeTable->selectRow(lowestSelectedRow); + m_nodeTable->selectRow(lowestSelectedRow); } } @@ -352,12 +336,12 @@ namespace EMStudio AZStd::string outResult; auto* command = aznew CommandSystem::CommandAdjustNodeGroup( GetCommandManager()->FindCommand(CommandSystem::CommandAdjustNodeGroup::s_commandName), - /*actorId=*/ mActor->GetID(), - /*name=*/ mNodeGroup->GetName(), + /*actorId=*/ m_actor->GetID(), + /*name=*/ m_nodeGroup->GetName(), /*newName=*/ AZStd::nullopt, /*enabledOnDefault=*/ AZStd::nullopt, /*nodeNames=*/ AZStd::move(nodeList), - /*nodeAction=*/ mNodeAction + /*nodeAction=*/ m_nodeAction ); if (EMStudio::GetCommandManager()->ExecuteCommand(command, outResult) == false) { @@ -369,19 +353,17 @@ namespace EMStudio // handle item selection changes of the node table void NodeGroupWidget::OnItemSelectionChanged() { - mRemoveNodesButton->setEnabled((mNodeTable->rowCount() != 0) && (mNodeTable->selectedItems().size() != 0)); + m_removeNodesButton->setEnabled((m_nodeTable->rowCount() != 0) && (m_nodeTable->selectedItems().size() != 0)); } // enable/disable the dialog void NodeGroupWidget::SetWidgetEnabled(bool enabled) { - //mNodeGroupNameEdit->setDisabled( !enabled ); - //mEnabledOnDefaultCheckbox->setDisabled( !enabled ); - mNodeTable->setDisabled(!enabled); - mSelectNodesButton->setDisabled(!enabled); - mAddNodesButton->setDisabled(!enabled); - mRemoveNodesButton->setDisabled(!enabled); + m_nodeTable->setDisabled(!enabled); + m_selectNodesButton->setDisabled(!enabled); + m_addNodesButton->setDisabled(!enabled); + m_removeNodesButton->setDisabled(!enabled); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeGroups/NodeGroupWidget.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeGroups/NodeGroupWidget.h index 6861e77756..c96b972085 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeGroups/NodeGroupWidget.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeGroups/NodeGroupWidget.h @@ -53,18 +53,18 @@ namespace EMStudio void keyReleaseEvent(QKeyEvent* event) override; private: - EMotionFX::Actor* mActor; + EMotionFX::Actor* m_actor; - NodeSelectionWindow* mNodeSelectionWindow; - CommandSystem::SelectionList mNodeSelectionList; - EMotionFX::NodeGroup* mNodeGroup; - uint16 mNodeGroupIndex; - CommandSystem::CommandAdjustNodeGroup::NodeAction mNodeAction; + NodeSelectionWindow* m_nodeSelectionWindow; + CommandSystem::SelectionList m_nodeSelectionList; + EMotionFX::NodeGroup* m_nodeGroup; + uint16 m_nodeGroupIndex; + CommandSystem::CommandAdjustNodeGroup::NodeAction m_nodeAction; // widgets - QTableWidget* mNodeTable; - QPushButton* mSelectNodesButton; - QPushButton* mAddNodesButton; - QPushButton* mRemoveNodesButton; + QTableWidget* m_nodeTable; + QPushButton* m_selectNodesButton; + QPushButton* m_addNodesButton; + QPushButton* m_removeNodesButton; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeGroups/NodeGroupsPlugin.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeGroups/NodeGroupsPlugin.cpp index 218035dc30..3fe5c589a7 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeGroups/NodeGroupsPlugin.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeGroups/NodeGroupsPlugin.cpp @@ -26,16 +26,16 @@ namespace EMStudio NodeGroupsPlugin::NodeGroupsPlugin() : EMStudio::DockWidgetPlugin() { - mDialogStack = nullptr; - mNodeGroupWidget = nullptr; - mNodeGroupManagementWidget = nullptr; - mSelectCallback = nullptr; - mUnselectCallback = nullptr; - mClearSelectionCallback = nullptr; - mAdjustNodeGroupCallback = nullptr; - mAddNodeGroupCallback = nullptr; - mRemoveNodeGroupCallback = nullptr; - mCurrentActor = nullptr; + m_dialogStack = nullptr; + m_nodeGroupWidget = nullptr; + m_nodeGroupManagementWidget = nullptr; + m_selectCallback = nullptr; + m_unselectCallback = nullptr; + m_clearSelectionCallback = nullptr; + m_adjustNodeGroupCallback = nullptr; + m_addNodeGroupCallback = nullptr; + m_removeNodeGroupCallback = nullptr; + m_currentActor = nullptr; } @@ -43,23 +43,23 @@ namespace EMStudio NodeGroupsPlugin::~NodeGroupsPlugin() { // unregister the command callbacks and get rid of the memory - GetCommandManager()->RemoveCommandCallback(mSelectCallback, false); - GetCommandManager()->RemoveCommandCallback(mUnselectCallback, false); - GetCommandManager()->RemoveCommandCallback(mClearSelectionCallback, false); - GetCommandManager()->RemoveCommandCallback(mAdjustNodeGroupCallback, false); - GetCommandManager()->RemoveCommandCallback(mAddNodeGroupCallback, false); - GetCommandManager()->RemoveCommandCallback(mRemoveNodeGroupCallback, false); + GetCommandManager()->RemoveCommandCallback(m_selectCallback, false); + GetCommandManager()->RemoveCommandCallback(m_unselectCallback, false); + GetCommandManager()->RemoveCommandCallback(m_clearSelectionCallback, false); + GetCommandManager()->RemoveCommandCallback(m_adjustNodeGroupCallback, false); + GetCommandManager()->RemoveCommandCallback(m_addNodeGroupCallback, false); + GetCommandManager()->RemoveCommandCallback(m_removeNodeGroupCallback, false); // remove the callback - delete mSelectCallback; - delete mUnselectCallback; - delete mClearSelectionCallback; - delete mAdjustNodeGroupCallback; - delete mAddNodeGroupCallback; - delete mRemoveNodeGroupCallback; + delete m_selectCallback; + delete m_unselectCallback; + delete m_clearSelectionCallback; + delete m_adjustNodeGroupCallback; + delete m_addNodeGroupCallback; + delete m_removeNodeGroupCallback; // clear dialogstack and delete afterwards - delete mDialogStack; + delete m_dialogStack; } @@ -75,40 +75,40 @@ namespace EMStudio bool NodeGroupsPlugin::Init() { // create the dialog stack - assert(mDialogStack == nullptr); - mDialogStack = new MysticQt::DialogStack(); - mDock->setMinimumWidth(300); - mDock->setMinimumHeight(100); - mDock->setWidget(mDialogStack); + assert(m_dialogStack == nullptr); + m_dialogStack = new MysticQt::DialogStack(); + m_dock->setMinimumWidth(300); + m_dock->setMinimumHeight(100); + m_dock->setWidget(m_dialogStack); // create the management and node group widgets - mNodeGroupWidget = new NodeGroupWidget(); - mNodeGroupManagementWidget = new NodeGroupManagementWidget(mNodeGroupWidget); + m_nodeGroupWidget = new NodeGroupWidget(); + m_nodeGroupManagementWidget = new NodeGroupManagementWidget(m_nodeGroupWidget); // add the widgets to the dialog stack - mDialogStack->Add(mNodeGroupManagementWidget, "Node Group Management", false, true, true, false); - mDialogStack->Add(mNodeGroupWidget, "Node Group", false, true, true); + m_dialogStack->Add(m_nodeGroupManagementWidget, "Node Group Management", false, true, true, false); + m_dialogStack->Add(m_nodeGroupWidget, "Node Group", false, true, true); // create and register the command callbacks only (only execute this code once for all plugins) - mSelectCallback = new CommandSelectCallback(false); - mUnselectCallback = new CommandUnselectCallback(false); - mClearSelectionCallback = new CommandClearSelectionCallback(false); - mAdjustNodeGroupCallback = new CommandAdjustNodeGroupCallback(false); - mAddNodeGroupCallback = new CommandAddNodeGroupCallback(false); - mRemoveNodeGroupCallback = new CommandRemoveNodeGroupCallback(false); + m_selectCallback = new CommandSelectCallback(false); + m_unselectCallback = new CommandUnselectCallback(false); + m_clearSelectionCallback = new CommandClearSelectionCallback(false); + m_adjustNodeGroupCallback = new CommandAdjustNodeGroupCallback(false); + m_addNodeGroupCallback = new CommandAddNodeGroupCallback(false); + m_removeNodeGroupCallback = new CommandRemoveNodeGroupCallback(false); - GetCommandManager()->RegisterCommandCallback("Select", mSelectCallback); - GetCommandManager()->RegisterCommandCallback("Unselect", mUnselectCallback); - GetCommandManager()->RegisterCommandCallback("ClearSelection", mClearSelectionCallback); - GetCommandManager()->RegisterCommandCallback(CommandSystem::CommandAdjustNodeGroup::s_commandName.data(), mAdjustNodeGroupCallback); - GetCommandManager()->RegisterCommandCallback("AddNodeGroup", mAddNodeGroupCallback); - GetCommandManager()->RegisterCommandCallback("RemoveNodeGroup", mRemoveNodeGroupCallback); + GetCommandManager()->RegisterCommandCallback("Select", m_selectCallback); + GetCommandManager()->RegisterCommandCallback("Unselect", m_unselectCallback); + GetCommandManager()->RegisterCommandCallback("ClearSelection", m_clearSelectionCallback); + GetCommandManager()->RegisterCommandCallback(CommandSystem::CommandAdjustNodeGroup::s_commandName.data(), m_adjustNodeGroupCallback); + GetCommandManager()->RegisterCommandCallback("AddNodeGroup", m_addNodeGroupCallback); + GetCommandManager()->RegisterCommandCallback("RemoveNodeGroup", m_removeNodeGroupCallback); // reinit the dialog ReInit(); // connect the window activation signal to refresh if reactivated - connect(mDock, &QDockWidget::visibilityChanged, this, &NodeGroupsPlugin::WindowReInit); + connect(m_dock, &QDockWidget::visibilityChanged, this, &NodeGroupsPlugin::WindowReInit); return true; } @@ -124,10 +124,10 @@ namespace EMStudio // show hint if no/multiple actor instances is/are selected if (actorInstance == nullptr) { - mCurrentActor = nullptr; - mNodeGroupWidget->SetActor(nullptr); - mNodeGroupWidget->SetNodeGroup(nullptr); - mNodeGroupManagementWidget->SetActor(nullptr); + m_currentActor = nullptr; + m_nodeGroupWidget->SetActor(nullptr); + m_nodeGroupWidget->SetNodeGroup(nullptr); + m_nodeGroupManagementWidget->SetActor(nullptr); return; } @@ -135,18 +135,18 @@ namespace EMStudio EMotionFX::Actor* actor = actorInstance->GetActor(); // only reinit the node groups window if actorinstance changed - if (mCurrentActor != actor) + if (m_currentActor != actor) { // set the new actor - mCurrentActor = actor; + m_currentActor = actor; // set the new actor on each widget - mNodeGroupWidget->SetActor(mCurrentActor); - mNodeGroupManagementWidget->SetActor(mCurrentActor); + m_nodeGroupWidget->SetActor(m_currentActor); + m_nodeGroupManagementWidget->SetActor(m_currentActor); } // set the dialog stack as main widget - mDock->setWidget(mDialogStack); + m_dock->setWidget(m_dialogStack); // update the interface UpdateInterface(); @@ -166,8 +166,8 @@ namespace EMStudio // update the interface void NodeGroupsPlugin::UpdateInterface() { - mNodeGroupManagementWidget->UpdateInterface(); - mNodeGroupWidget->UpdateInterface(); + m_nodeGroupManagementWidget->UpdateInterface(); + m_nodeGroupWidget->UpdateInterface(); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeGroups/NodeGroupsPlugin.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeGroups/NodeGroupsPlugin.h index 7704708571..613d2e3494 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeGroups/NodeGroupsPlugin.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeGroups/NodeGroupsPlugin.h @@ -74,22 +74,22 @@ namespace EMStudio MCORE_DEFINECOMMANDCALLBACK(CommandAddNodeGroupCallback); MCORE_DEFINECOMMANDCALLBACK(CommandRemoveNodeGroupCallback); - CommandSelectCallback* mSelectCallback; - CommandUnselectCallback* mUnselectCallback; - CommandClearSelectionCallback* mClearSelectionCallback; - CommandAdjustNodeGroupCallback* mAdjustNodeGroupCallback; - CommandAddNodeGroupCallback* mAddNodeGroupCallback; - CommandRemoveNodeGroupCallback* mRemoveNodeGroupCallback; + CommandSelectCallback* m_selectCallback; + CommandUnselectCallback* m_unselectCallback; + CommandClearSelectionCallback* m_clearSelectionCallback; + CommandAdjustNodeGroupCallback* m_adjustNodeGroupCallback; + CommandAddNodeGroupCallback* m_addNodeGroupCallback; + CommandRemoveNodeGroupCallback* m_removeNodeGroupCallback; // current selected actor - EMotionFX::Actor* mCurrentActor; + EMotionFX::Actor* m_currentActor; // the dialog stack widgets - NodeGroupWidget* mNodeGroupWidget; - NodeGroupManagementWidget* mNodeGroupManagementWidget; + NodeGroupWidget* m_nodeGroupWidget; + NodeGroupManagementWidget* m_nodeGroupManagementWidget; // some qt stuff - MysticQt::DialogStack* mDialogStack; - QLabel* mInfoText; + MysticQt::DialogStack* m_dialogStack; + QLabel* m_infoText; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/NodeInfo.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/NodeInfo.cpp index a402dc869e..3bbf9a0731 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/NodeInfo.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/NodeInfo.cpp @@ -31,11 +31,11 @@ namespace EMStudio m_name = node->GetNameString(); // transform info - m_position = transformData->GetCurrentPose()->GetLocalSpaceTransform(nodeIndex).mPosition; - m_rotation = transformData->GetCurrentPose()->GetLocalSpaceTransform(nodeIndex).mRotation; + m_position = transformData->GetCurrentPose()->GetLocalSpaceTransform(nodeIndex).m_position; + m_rotation = transformData->GetCurrentPose()->GetLocalSpaceTransform(nodeIndex).m_rotation; #ifndef EMFX_SCALE_DISABLED - m_scale = transformData->GetCurrentPose()->GetLocalSpaceTransform(nodeIndex).mScale; + m_scale = transformData->GetCurrentPose()->GetLocalSpaceTransform(nodeIndex).m_scale; #else m_scale = AZ::Vector3::CreateOne(); #endif @@ -53,9 +53,9 @@ namespace EMStudio if (actor->GetHasMirrorInfo()) { const EMotionFX::Actor::NodeMirrorInfo& nodeMirrorInfo = actor->GetNodeMirrorInfo(nodeIndex); - if (nodeMirrorInfo.mSourceNode != MCORE_INVALIDINDEX16 && nodeMirrorInfo.mSourceNode != nodeIndex) + if (nodeMirrorInfo.m_sourceNode != MCORE_INVALIDINDEX16 && nodeMirrorInfo.m_sourceNode != nodeIndex) { - m_mirrorNodeName = actor->GetSkeleton()->GetNode(nodeMirrorInfo.mSourceNode)->GetNameString(); + m_mirrorNodeName = actor->GetSkeleton()->GetNode(nodeMirrorInfo.m_sourceNode)->GetNameString(); } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/NodeWindowPlugin.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/NodeWindowPlugin.cpp index 7b47b8cb43..6b7beb20de 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/NodeWindowPlugin.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/NodeWindowPlugin.cpp @@ -28,8 +28,8 @@ namespace EMStudio { NodeWindowPlugin::NodeWindowPlugin() : EMStudio::DockWidgetPlugin() - , mDialogStack(nullptr) - , mHierarchyWidget(nullptr) + , m_dialogStack(nullptr) + , m_hierarchyWidget(nullptr) , m_propertyWidget(nullptr) { } @@ -79,35 +79,35 @@ namespace EMStudio GetCommandManager()->RegisterCommandCallback("ClearSelection", m_callbacks.back()); // create the dialog stack - AZ_Assert(!mDialogStack, "Expected an unitialized mDialogStack, was this function called more than once?"); - mDialogStack = new MysticQt::DialogStack(); + AZ_Assert(!m_dialogStack, "Expected an unitialized m_dialogStack, was this function called more than once?"); + m_dialogStack = new MysticQt::DialogStack(); // add the node hierarchy - mHierarchyWidget = new NodeHierarchyWidget(mDock, false); - mHierarchyWidget->setObjectName("EMFX.NodeWindowPlugin.NodeHierarchyWidget.HierarchyWidget"); - mHierarchyWidget->GetTreeWidget()->setMinimumWidth(100); - mDialogStack->Add(mHierarchyWidget, "Hierarchy", false, true); + m_hierarchyWidget = new NodeHierarchyWidget(m_dock, false); + m_hierarchyWidget->setObjectName("EMFX.NodeWindowPlugin.NodeHierarchyWidget.HierarchyWidget"); + m_hierarchyWidget->GetTreeWidget()->setMinimumWidth(100); + m_dialogStack->Add(m_hierarchyWidget, "Hierarchy", false, true); // add the node attributes widget - m_propertyWidget = aznew AzToolsFramework::ReflectedPropertyEditor(mDialogStack); + m_propertyWidget = aznew AzToolsFramework::ReflectedPropertyEditor(m_dialogStack); m_propertyWidget->setObjectName("EMFX.NodeWindowPlugin.ReflectedPropertyEditor.PropertyWidget"); m_propertyWidget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); m_propertyWidget->SetAutoResizeLabels(true); - mDialogStack->Add(m_propertyWidget, "Node Attributes", false, true, true, false); + m_dialogStack->Add(m_propertyWidget, "Node Attributes", false, true, true, false); // prepare the dock window - mDock->setWidget(mDialogStack); - mDock->setMinimumWidth(100); - mDock->setMinimumHeight(100); + m_dock->setWidget(m_dialogStack); + m_dock->setMinimumWidth(100); + m_dock->setMinimumHeight(100); // add functionality to the controls - connect(mDock, &QDockWidget::visibilityChanged, this, &NodeWindowPlugin::VisibilityChanged); - connect(mHierarchyWidget->GetTreeWidget(), &QTreeWidget::itemSelectionChanged, this, &NodeWindowPlugin::OnNodeChanged); + connect(m_dock, &QDockWidget::visibilityChanged, this, &NodeWindowPlugin::VisibilityChanged); + connect(m_hierarchyWidget->GetTreeWidget(), &QTreeWidget::itemSelectionChanged, this, &NodeWindowPlugin::OnNodeChanged); - const AzQtComponents::FilteredSearchWidget* searchWidget = mHierarchyWidget->GetSearchWidget(); + const AzQtComponents::FilteredSearchWidget* searchWidget = m_hierarchyWidget->GetSearchWidget(); connect(searchWidget, &AzQtComponents::FilteredSearchWidget::TextFilterChanged, this, &NodeWindowPlugin::OnTextFilterChanged); - connect(mHierarchyWidget, &NodeHierarchyWidget::FilterStateChanged, this, &NodeWindowPlugin::UpdateVisibleNodeIndices); + connect(m_hierarchyWidget, &NodeHierarchyWidget::FilterStateChanged, this, &NodeWindowPlugin::UpdateVisibleNodeIndices); // reinit the dialog ReInit(); @@ -123,15 +123,15 @@ namespace EMStudio EMotionFX::ActorInstance* actorInstance = selection.GetSingleActorInstance(); // reset the node name filter - mHierarchyWidget->GetSearchWidget()->ClearTextFilter(); - mHierarchyWidget->GetTreeWidget()->clear(); + m_hierarchyWidget->GetSearchWidget()->ClearTextFilter(); + m_hierarchyWidget->GetTreeWidget()->clear(); m_propertyWidget->ClearInstances(); m_propertyWidget->InvalidateAll(); if (actorInstance) { - mHierarchyWidget->Update(actorInstance->GetID()); + m_hierarchyWidget->Update(actorInstance->GetID()); m_actorInfo.reset(aznew ActorInfo(actorInstance)); m_propertyWidget->AddInstance(m_actorInfo.get(), azrtti_typeid(m_actorInfo.get())); } @@ -158,14 +158,14 @@ namespace EMStudio selection.ClearNodeSelection(); m_selectedNodeIndices.clear(); - AZStd::vector& selectedItems = mHierarchyWidget->GetSelectedItems(); + AZStd::vector& selectedItems = m_hierarchyWidget->GetSelectedItems(); EMotionFX::ActorInstance* selectedInstance = nullptr; EMotionFX::Node* selectedNode = nullptr; for (const SelectionItem& selectedItem : selectedItems) { - const uint32 actorInstanceID = selectedItem.mActorInstanceID; + const uint32 actorInstanceID = selectedItem.m_actorInstanceId; const char* nodeName = selectedItem.GetNodeName(); EMotionFX::ActorInstance* actorInstance = EMotionFX::GetActorManager().FindActorInstanceByID(actorInstanceID); @@ -177,7 +177,7 @@ namespace EMStudio EMotionFX::Actor* actor = actorInstance->GetActor(); EMotionFX::Node* node = actor->GetSkeleton()->FindNodeByName(nodeName); - if (node && mHierarchyWidget->CheckIfNodeVisible(actorInstance, node)) + if (node && m_hierarchyWidget->CheckIfNodeVisible(actorInstance, node)) { if (selectedInstance == nullptr) { @@ -278,11 +278,11 @@ namespace EMStudio return; } - AZStd::string filterString = mHierarchyWidget->GetSearchWidgetText(); + AZStd::string filterString = m_hierarchyWidget->GetSearchWidgetText(); AZStd::to_lower(filterString.begin(), filterString.end()); - const bool showNodes = mHierarchyWidget->GetDisplayNodes(); - const bool showBones = mHierarchyWidget->GetDisplayBones(); - const bool showMeshes = mHierarchyWidget->GetDisplayMeshes(); + const bool showNodes = m_hierarchyWidget->GetDisplayNodes(); + const bool showBones = m_hierarchyWidget->GetDisplayBones(); + const bool showMeshes = m_hierarchyWidget->GetDisplayMeshes(); // get access to the actor and the number of nodes EMotionFX::Actor* actor = actorInstance->GetActor(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/NodeWindowPlugin.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/NodeWindowPlugin.h index 582e9e9eac..157486df10 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/NodeWindowPlugin.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/NodeWindowPlugin.h @@ -76,12 +76,12 @@ namespace EMStudio AZStd::vector m_callbacks; - MysticQt::DialogStack* mDialogStack; - NodeHierarchyWidget* mHierarchyWidget; + MysticQt::DialogStack* m_dialogStack; + NodeHierarchyWidget* m_hierarchyWidget; AzToolsFramework::ReflectedPropertyEditor* m_propertyWidget; - AZStd::string mString; - AZStd::string mTempGroupName; + AZStd::string m_string; + AZStd::string m_tempGroupName; AZStd::unordered_set m_visibleNodeIndices; AZStd::unordered_set m_selectedNodeIndices; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/ActorPropertiesWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/ActorPropertiesWindow.cpp index 4e8e51b601..c449f492b1 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/ActorPropertiesWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/ActorPropertiesWindow.cpp @@ -24,7 +24,7 @@ namespace EMStudio ActorPropertiesWindow::ActorPropertiesWindow(QWidget* parent, SceneManagerPlugin* plugin) : QWidget(parent) { - mPlugin = plugin; + m_plugin = plugin; } // init after the parent dock window has been created @@ -44,9 +44,9 @@ namespace EMStudio // actor name rowNr = 0; layout->addWidget(new QLabel("Actor name"), rowNr, 0); - mNameEdit = new QLineEdit(); - connect(mNameEdit, &QLineEdit::editingFinished, this, &ActorPropertiesWindow::NameEditChanged); - layout->addWidget(mNameEdit, rowNr, 1); + m_nameEdit = new QLineEdit(); + connect(m_nameEdit, &QLineEdit::editingFinished, this, &ActorPropertiesWindow::NameEditChanged); + layout->addWidget(m_nameEdit, rowNr, 1); // Motion extraction joint. rowNr++; @@ -94,14 +94,14 @@ namespace EMStudio // mirror setup rowNr++; - mMirrorSetupWindow = new MirrorSetupWindow(mPlugin->GetDockWidget(), mPlugin); - mMirrorSetupLink = new AzQtComponents::BrowseEdit(); - mMirrorSetupLink->setClearButtonEnabled(true); - mMirrorSetupLink->setLineEditReadOnly(true); - mMirrorSetupLink->setPlaceholderText("Click folder to setup"); + m_mirrorSetupWindow = new MirrorSetupWindow(m_plugin->GetDockWidget(), m_plugin); + m_mirrorSetupLink = new AzQtComponents::BrowseEdit(); + m_mirrorSetupLink->setClearButtonEnabled(true); + m_mirrorSetupLink->setLineEditReadOnly(true); + m_mirrorSetupLink->setPlaceholderText("Click folder to setup"); layout->addWidget(new QLabel("Mirror setup"), rowNr, 0); - layout->addWidget(mMirrorSetupLink, rowNr, 1); - connect(mMirrorSetupLink, &AzQtComponents::BrowseEdit::attachedButtonTriggered, this, &ActorPropertiesWindow::OnMirrorSetup); + layout->addWidget(m_mirrorSetupLink, rowNr, 1); + connect(m_mirrorSetupLink, &AzQtComponents::BrowseEdit::attachedButtonTriggered, this, &ActorPropertiesWindow::OnMirrorSetup); UpdateInterface(); } @@ -109,8 +109,8 @@ namespace EMStudio void ActorPropertiesWindow::UpdateInterface() { - mActor = nullptr; - mActorInstance = nullptr; + m_actor = nullptr; + m_actorInstance = nullptr; EMotionFX::ActorInstance* actorInstance = GetCommandManager()->GetCurrentSelection().GetSingleActorInstance(); EMotionFX::Actor* actor = GetCommandManager()->GetCurrentSelection().GetSingleActor(); @@ -118,13 +118,13 @@ namespace EMStudio // in case we have selected a single actor instance if (actorInstance) { - mActorInstance = actorInstance; - mActor = actorInstance->GetActor(); + m_actorInstance = actorInstance; + m_actor = actorInstance->GetActor(); } // in case we have selected a single actor else if (actor) { - mActor = actor; + m_actor = actor; const size_t numActorInstances = EMotionFX::GetActorManager().GetNumActorInstances(); for (size_t i = 0; i < numActorInstances; ++i) @@ -132,15 +132,15 @@ namespace EMStudio EMotionFX::ActorInstance* currentInstance = EMotionFX::GetActorManager().GetActorInstance(i); if (currentInstance->GetActor() == actor) { - mActorInstance = currentInstance; + m_actorInstance = currentInstance; break; } } } - mMirrorSetupWindow->Reinit(); + m_mirrorSetupWindow->Reinit(); - if (mActorInstance == nullptr || mActor == nullptr) + if (m_actorInstance == nullptr || m_actor == nullptr) { // reset data and disable interface elements m_motionExtractionJointBrowseEdit->setEnabled(false); @@ -155,37 +155,37 @@ namespace EMStudio m_excludeFromBoundsBrowseEdit->SetSelectedJoints({}); // actor name - mNameEdit->setEnabled(false); - mNameEdit->setText(""); + m_nameEdit->setEnabled(false); + m_nameEdit->setText(""); - mMirrorSetupLink->setEnabled(false); + m_mirrorSetupLink->setEnabled(false); return; } - mMirrorSetupLink->setEnabled(true); + m_mirrorSetupLink->setEnabled(true); // Motion extraction node - EMotionFX::Node* extractionNode = mActor->GetMotionExtractionNode(); + EMotionFX::Node* extractionNode = m_actor->GetMotionExtractionNode(); m_motionExtractionJointBrowseEdit->setEnabled(true); if (extractionNode) { - m_motionExtractionJointBrowseEdit->SetSelectedJoints({SelectionItem(mActorInstance->GetID(), extractionNode->GetName())}); + m_motionExtractionJointBrowseEdit->SetSelectedJoints({SelectionItem(m_actorInstance->GetID(), extractionNode->GetName())}); } else { m_motionExtractionJointBrowseEdit->SetSelectedJoints({}); } - EMotionFX::Node* bestMatchingNode = mActor->FindBestMotionExtractionNode(); - m_findBestMatchButton->setVisible(bestMatchingNode && mActor->GetMotionExtractionNode() != bestMatchingNode); + EMotionFX::Node* bestMatchingNode = m_actor->FindBestMotionExtractionNode(); + m_findBestMatchButton->setVisible(bestMatchingNode && m_actor->GetMotionExtractionNode() != bestMatchingNode); // Retarget root node - EMotionFX::Node* retargetRootNode = mActor->GetRetargetRootNode(); + EMotionFX::Node* retargetRootNode = m_actor->GetRetargetRootNode(); m_retargetRootJointBrowseEdit->setEnabled(true); if (retargetRootNode) { - m_retargetRootJointBrowseEdit->SetSelectedJoints({SelectionItem(mActorInstance->GetID(), retargetRootNode->GetName())}); + m_retargetRootJointBrowseEdit->SetSelectedJoints({SelectionItem(m_actorInstance->GetID(), retargetRootNode->GetName())}); } else { @@ -196,23 +196,23 @@ namespace EMStudio m_excludeFromBoundsBrowseEdit->setEnabled(true); AZStd::vector jointsExcludedFromBounds; - if (mActorInstance) + if (m_actorInstance) { - const size_t numNodes = mActor->GetNumNodes(); + const size_t numNodes = m_actor->GetNumNodes(); for (size_t i = 0; i < numNodes; ++i) { - EMotionFX::Node* node = mActor->GetSkeleton()->GetNode(i); + EMotionFX::Node* node = m_actor->GetSkeleton()->GetNode(i); if (!node->GetIncludeInBoundsCalc()) { - jointsExcludedFromBounds.emplace_back(mActorInstance->GetID(), node->GetName()); + jointsExcludedFromBounds.emplace_back(m_actorInstance->GetID(), node->GetName()); } } } m_excludeFromBoundsBrowseEdit->SetSelectedJoints(jointsExcludedFromBounds); // actor name - mNameEdit->setEnabled(true); - mNameEdit->setText(mActor->GetName()); + m_nameEdit->setEnabled(true); + m_nameEdit->setText(m_actor->GetName()); } void ActorPropertiesWindow::GetNodeName(const AZStd::vector& joints, AZStd::string* outNodeName, uint32* outActorID) @@ -226,7 +226,7 @@ namespace EMStudio return; } - const uint32 actorInstanceID = joints[0].mActorInstanceID; + const uint32 actorInstanceID = joints[0].m_actorInstanceId; const char* nodeName = joints[0].GetNodeName(); EMotionFX::ActorInstance* actorInstance = EMotionFX::GetActorManager().FindActorInstanceByID(actorInstanceID); if (!actorInstance) @@ -299,13 +299,13 @@ namespace EMStudio void ActorPropertiesWindow::OnFindBestMatchingNode() { // check if the actor is invalid - if (mActor == nullptr) + if (m_actor == nullptr) { return; } // find the best motion extraction node - EMotionFX::Node* bestMatchingNode = mActor->FindBestMotionExtractionNode(); + EMotionFX::Node* bestMatchingNode = m_actor->FindBestMotionExtractionNode(); if (bestMatchingNode == nullptr) { return; @@ -315,7 +315,7 @@ namespace EMStudio MCore::CommandGroup commandGroup("Adjust motion extraction node"); // adjust the actor - const AZStd::string command = AZStd::string::format("AdjustActor -actorID %i -motionExtractionNodeName \"%s\"", mActor->GetID(), bestMatchingNode->GetName()); + const AZStd::string command = AZStd::string::format("AdjustActor -actorID %i -motionExtractionNodeName \"%s\"", m_actor->GetID(), bestMatchingNode->GetName()); commandGroup.AddCommandString(command); // execute the command group @@ -329,13 +329,13 @@ namespace EMStudio // actor name changed void ActorPropertiesWindow::NameEditChanged() { - if (mActor == nullptr) + if (m_actor == nullptr) { return; } // execute the command - const AZStd::string command = AZStd::string::format("AdjustActor -actorID %i -name \"%s\"", mActor->GetID(), mNameEdit->text().toUtf8().data()); + const AZStd::string command = AZStd::string::format("AdjustActor -actorID %i -name \"%s\"", m_actor->GetID(), m_nameEdit->text().toUtf8().data()); AZStd::string result; if (!EMStudio::GetCommandManager()->ExecuteCommand(command, result)) @@ -353,13 +353,13 @@ namespace EMStudio return; } - AZStd::string command = AZStd::string::format("AdjustActor -actorID %i -nodesExcludedFromBounds \"", mActor->GetID()); + AZStd::string command = AZStd::string::format("AdjustActor -actorID %i -nodesExcludedFromBounds \"", m_actor->GetID()); // prepare the nodes excluded from bounds string size_t addedItems = 0; for (const SelectionItem& selectedJoint : selectedJoints) { - EMotionFX::Node* node = mActor->GetSkeleton()->FindNodeByName(selectedJoint.GetNodeName()); + EMotionFX::Node* node = m_actor->GetSkeleton()->FindNodeByName(selectedJoint.GetNodeName()); if (node) { if (addedItems > 0) @@ -395,7 +395,7 @@ namespace EMStudio EMotionFX::Actor* actor = actorInstance->GetActor(); EMotionFX::Skeleton* skeleton = actor->GetSkeleton(); - const size_t numJoints = mActor->GetNumNodes(); + const size_t numJoints = m_actor->GetNumNodes(); // Include all joints first. for (size_t i = 0; i < numJoints; ++i) @@ -417,9 +417,9 @@ namespace EMStudio // open the mirror setup void ActorPropertiesWindow::OnMirrorSetup() { - if (mMirrorSetupWindow) + if (m_mirrorSetupWindow) { - mMirrorSetupWindow->exec(); + m_mirrorSetupWindow->exec(); } } } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/ActorPropertiesWindow.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/ActorPropertiesWindow.h index 67568d80b0..70af16ca17 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/ActorPropertiesWindow.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/ActorPropertiesWindow.h @@ -69,14 +69,14 @@ namespace EMStudio ActorJointBrowseEdit* m_retargetRootJointBrowseEdit = nullptr; ActorJointBrowseEdit* m_excludeFromBoundsBrowseEdit = nullptr; - AzQtComponents::BrowseEdit* mMirrorSetupLink = nullptr; - MirrorSetupWindow* mMirrorSetupWindow = nullptr; + AzQtComponents::BrowseEdit* m_mirrorSetupLink = nullptr; + MirrorSetupWindow* m_mirrorSetupWindow = nullptr; // actor name - QLineEdit* mNameEdit = nullptr; + QLineEdit* m_nameEdit = nullptr; - SceneManagerPlugin* mPlugin = nullptr; - EMotionFX::Actor* mActor = nullptr; - EMotionFX::ActorInstance* mActorInstance = nullptr; + SceneManagerPlugin* m_plugin = nullptr; + EMotionFX::Actor* m_actor = nullptr; + EMotionFX::ActorInstance* m_actorInstance = nullptr; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/MirrorSetupWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/MirrorSetupWindow.cpp index fc01f68efe..d1fd241a2f 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/MirrorSetupWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/MirrorSetupWindow.cpp @@ -42,7 +42,7 @@ namespace EMStudio MirrorSetupWindow::MirrorSetupWindow(QWidget* parent, SceneManagerPlugin* plugin) : QDialog(parent) { - mPlugin = plugin; + m_plugin = plugin; // set the window title setWindowTitle("Mirror Setup"); @@ -53,10 +53,10 @@ namespace EMStudio // load some icons const QDir dataDir{ QString(MysticQt::GetDataDir().c_str()) }; - mBoneIcon = new QIcon(dataDir.filePath("Images/Icons/Bone.svg")); - mNodeIcon = new QIcon(dataDir.filePath("Images/Icons/Node.svg")); - mMeshIcon = new QIcon(dataDir.filePath("Images/Icons/Mesh.svg")); - mMappedIcon = new QIcon(dataDir.filePath("Images/Icons/Confirm.svg")); + m_boneIcon = new QIcon(dataDir.filePath("Images/Icons/Bone.svg")); + m_nodeIcon = new QIcon(dataDir.filePath("Images/Icons/Node.svg")); + m_meshIcon = new QIcon(dataDir.filePath("Images/Icons/Mesh.svg")); + m_mappedIcon = new QIcon(dataDir.filePath("Images/Icons/Confirm.svg")); // create the main layout QVBoxLayout* mainLayout = new QVBoxLayout(); @@ -72,36 +72,36 @@ namespace EMStudio toolBarLayout->setMargin(0); toolBarLayout->setSpacing(0); mainLayout->addLayout(toolBarLayout); - mButtonOpen = new QPushButton(); - EMStudioManager::MakeTransparentButton(mButtonOpen, "Images/Icons/Open.svg", "Load and apply a mapping template."); - connect(mButtonOpen, &QPushButton::clicked, this, &MirrorSetupWindow::OnLoadMapping); - mButtonSave = new QPushButton(); - EMStudioManager::MakeTransparentButton(mButtonSave, "Images/Menu/FileSave.svg", "Save the currently setup mapping as template."); - connect(mButtonSave, &QPushButton::clicked, this, &MirrorSetupWindow::OnSaveMapping); - mButtonClear = new QPushButton(); - EMStudioManager::MakeTransparentButton(mButtonClear, "Images/Icons/Clear.svg", "Clear the currently setup mapping entirely."); - connect(mButtonClear, &QPushButton::clicked, this, &MirrorSetupWindow::OnClearMapping); + m_buttonOpen = new QPushButton(); + EMStudioManager::MakeTransparentButton(m_buttonOpen, "Images/Icons/Open.svg", "Load and apply a mapping template."); + connect(m_buttonOpen, &QPushButton::clicked, this, &MirrorSetupWindow::OnLoadMapping); + m_buttonSave = new QPushButton(); + EMStudioManager::MakeTransparentButton(m_buttonSave, "Images/Menu/FileSave.svg", "Save the currently setup mapping as template."); + connect(m_buttonSave, &QPushButton::clicked, this, &MirrorSetupWindow::OnSaveMapping); + m_buttonClear = new QPushButton(); + EMStudioManager::MakeTransparentButton(m_buttonClear, "Images/Icons/Clear.svg", "Clear the currently setup mapping entirely."); + connect(m_buttonClear, &QPushButton::clicked, this, &MirrorSetupWindow::OnClearMapping); - mButtonGuess = new QPushButton(); - EMStudioManager::MakeTransparentButton(mButtonGuess, "Images/Icons/Character.svg", "Perform name based mapping."); - connect(mButtonGuess, &QPushButton::clicked, this, &MirrorSetupWindow::OnBestGuess); + m_buttonGuess = new QPushButton(); + EMStudioManager::MakeTransparentButton(m_buttonGuess, "Images/Icons/Character.svg", "Perform name based mapping."); + connect(m_buttonGuess, &QPushButton::clicked, this, &MirrorSetupWindow::OnBestGuess); - toolBarLayout->addWidget(mButtonOpen, 0, Qt::AlignLeft); - toolBarLayout->addWidget(mButtonSave, 0, Qt::AlignLeft); - toolBarLayout->addWidget(mButtonClear, 0, Qt::AlignLeft); + toolBarLayout->addWidget(m_buttonOpen, 0, Qt::AlignLeft); + toolBarLayout->addWidget(m_buttonSave, 0, Qt::AlignLeft); + toolBarLayout->addWidget(m_buttonClear, 0, Qt::AlignLeft); toolBarLayout->addSpacerItem(new QSpacerItem(100, 1, QSizePolicy::Expanding, QSizePolicy::Minimum)); QHBoxLayout* leftRightLayout = new QHBoxLayout(); leftRightLayout->addWidget(new QLabel("Left:"), 0, Qt::AlignRight); - mLeftEdit = new QLineEdit("Bip01 L"); - mLeftEdit->setMaximumWidth(75); - leftRightLayout->addWidget(mLeftEdit, 0, Qt::AlignRight); - mRightEdit = new QLineEdit("Bip01 R"); - mRightEdit->setMaximumWidth(75); + m_leftEdit = new QLineEdit("Bip01 L"); + m_leftEdit->setMaximumWidth(75); + leftRightLayout->addWidget(m_leftEdit, 0, Qt::AlignRight); + m_rightEdit = new QLineEdit("Bip01 R"); + m_rightEdit->setMaximumWidth(75); leftRightLayout->addWidget(new QLabel("Right:"), 0, Qt::AlignRight); - leftRightLayout->addWidget(mRightEdit, 0, Qt::AlignRight); - leftRightLayout->addWidget(mButtonGuess, 0, Qt::AlignRight); + leftRightLayout->addWidget(m_rightEdit, 0, Qt::AlignRight); + leftRightLayout->addWidget(m_buttonGuess, 0, Qt::AlignRight); leftRightLayout->setSpacing(6); leftRightLayout->setMargin(0); @@ -140,36 +140,35 @@ namespace EMStudio curSearchLayout->setSpacing(6); curSearchLayout->setMargin(0); - mCurrentList = new QTableWidget(); - mCurrentList->setAlternatingRowColors(true); - mCurrentList->setGridStyle(Qt::SolidLine); - mCurrentList->setSelectionBehavior(QAbstractItemView::SelectRows); - mCurrentList->setSelectionMode(QAbstractItemView::SingleSelection); - //mCurrentList->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); - mCurrentList->setCornerButtonEnabled(false); - mCurrentList->setEditTriggers(QAbstractItemView::NoEditTriggers); - mCurrentList->setContextMenuPolicy(Qt::DefaultContextMenu); - mCurrentList->setColumnCount(3); - mCurrentList->setColumnWidth(0, 20); - mCurrentList->setColumnWidth(1, 20); - mCurrentList->setSortingEnabled(true); - QHeaderView* verticalHeader = mCurrentList->verticalHeader(); + m_currentList = new QTableWidget(); + m_currentList->setAlternatingRowColors(true); + m_currentList->setGridStyle(Qt::SolidLine); + m_currentList->setSelectionBehavior(QAbstractItemView::SelectRows); + m_currentList->setSelectionMode(QAbstractItemView::SingleSelection); + m_currentList->setCornerButtonEnabled(false); + m_currentList->setEditTriggers(QAbstractItemView::NoEditTriggers); + m_currentList->setContextMenuPolicy(Qt::DefaultContextMenu); + m_currentList->setColumnCount(3); + m_currentList->setColumnWidth(0, 20); + m_currentList->setColumnWidth(1, 20); + m_currentList->setSortingEnabled(true); + QHeaderView* verticalHeader = m_currentList->verticalHeader(); verticalHeader->setVisible(false); QTableWidgetItem* headerItem = new QTableWidgetItem(""); headerItem->setTextAlignment(Qt::AlignVCenter | Qt::AlignLeft); - mCurrentList->setHorizontalHeaderItem(0, headerItem); + m_currentList->setHorizontalHeaderItem(0, headerItem); headerItem = new QTableWidgetItem(""); headerItem->setTextAlignment(Qt::AlignVCenter | Qt::AlignLeft); - mCurrentList->setHorizontalHeaderItem(1, headerItem); + m_currentList->setHorizontalHeaderItem(1, headerItem); headerItem = new QTableWidgetItem("Name"); headerItem->setTextAlignment(Qt::AlignVCenter | Qt::AlignLeft); - mCurrentList->setHorizontalHeaderItem(2, headerItem); - mCurrentList->horizontalHeader()->setStretchLastSection(true); - mCurrentList->horizontalHeader()->setSortIndicatorShown(false); - mCurrentList->horizontalHeader()->setSectionsClickable(false); - connect(mCurrentList, &QTableWidget::itemSelectionChanged, this, &MirrorSetupWindow::OnCurrentListSelectionChanged); - connect(mCurrentList, &QTableWidget::itemDoubleClicked, this, &MirrorSetupWindow::OnCurrentListDoubleClicked); - leftListLayout->addWidget(mCurrentList); + m_currentList->setHorizontalHeaderItem(2, headerItem); + m_currentList->horizontalHeader()->setStretchLastSection(true); + m_currentList->horizontalHeader()->setSortIndicatorShown(false); + m_currentList->horizontalHeader()->setSectionsClickable(false); + connect(m_currentList, &QTableWidget::itemSelectionChanged, this, &MirrorSetupWindow::OnCurrentListSelectionChanged); + connect(m_currentList, &QTableWidget::itemDoubleClicked, this, &MirrorSetupWindow::OnCurrentListDoubleClicked); + leftListLayout->addWidget(m_currentList); // add link button middle part QVBoxLayout* middleLayout = new QVBoxLayout(); @@ -204,35 +203,34 @@ namespace EMStudio sourceSearchLayout->setSpacing(6); sourceSearchLayout->setMargin(0); - mSourceList = new QTableWidget(); - mSourceList->setAlternatingRowColors(true); - mSourceList->setGridStyle(Qt::SolidLine); - mSourceList->setSelectionBehavior(QAbstractItemView::SelectRows); - mSourceList->setSelectionMode(QAbstractItemView::SingleSelection); - //mSourceList->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); - mSourceList->setCornerButtonEnabled(false); - mSourceList->setEditTriggers(QAbstractItemView::NoEditTriggers); - mSourceList->setContextMenuPolicy(Qt::DefaultContextMenu); - mSourceList->setColumnCount(3); - mSourceList->setColumnWidth(0, 20); - mSourceList->setColumnWidth(1, 20); - mSourceList->setSortingEnabled(true); - verticalHeader = mSourceList->verticalHeader(); + m_sourceList = new QTableWidget(); + m_sourceList->setAlternatingRowColors(true); + m_sourceList->setGridStyle(Qt::SolidLine); + m_sourceList->setSelectionBehavior(QAbstractItemView::SelectRows); + m_sourceList->setSelectionMode(QAbstractItemView::SingleSelection); + m_sourceList->setCornerButtonEnabled(false); + m_sourceList->setEditTriggers(QAbstractItemView::NoEditTriggers); + m_sourceList->setContextMenuPolicy(Qt::DefaultContextMenu); + m_sourceList->setColumnCount(3); + m_sourceList->setColumnWidth(0, 20); + m_sourceList->setColumnWidth(1, 20); + m_sourceList->setSortingEnabled(true); + verticalHeader = m_sourceList->verticalHeader(); verticalHeader->setVisible(false); headerItem = new QTableWidgetItem(""); headerItem->setTextAlignment(Qt::AlignVCenter | Qt::AlignLeft); - mSourceList->setHorizontalHeaderItem(0, headerItem); + m_sourceList->setHorizontalHeaderItem(0, headerItem); headerItem = new QTableWidgetItem(""); headerItem->setTextAlignment(Qt::AlignVCenter | Qt::AlignLeft); - mSourceList->setHorizontalHeaderItem(1, headerItem); + m_sourceList->setHorizontalHeaderItem(1, headerItem); headerItem = new QTableWidgetItem("Name"); headerItem->setTextAlignment(Qt::AlignVCenter | Qt::AlignLeft); - mSourceList->setHorizontalHeaderItem(2, headerItem); - mSourceList->horizontalHeader()->setStretchLastSection(true); - mSourceList->horizontalHeader()->setSortIndicatorShown(false); - mSourceList->horizontalHeader()->setSectionsClickable(false); - connect(mSourceList, &QTableWidget::itemSelectionChanged, this, &MirrorSetupWindow::OnSourceListSelectionChanged); - rightListLayout->addWidget(mSourceList); + m_sourceList->setHorizontalHeaderItem(2, headerItem); + m_sourceList->horizontalHeader()->setStretchLastSection(true); + m_sourceList->horizontalHeader()->setSortIndicatorShown(false); + m_sourceList->horizontalHeader()->setSectionsClickable(false); + connect(m_sourceList, &QTableWidget::itemSelectionChanged, this, &MirrorSetupWindow::OnSourceListSelectionChanged); + rightListLayout->addWidget(m_sourceList); // create the mapping table QVBoxLayout* lowerLayout = new QVBoxLayout(); @@ -244,53 +242,48 @@ namespace EMStudio mappingLayout->setMargin(0); lowerLayout->addLayout(mappingLayout); mappingLayout->addWidget(new QLabel("Mapping:"), 0, Qt::AlignLeft | Qt::AlignVCenter); - //mButtonGuess = new QPushButton(); - //EMStudioManager::MakeTransparentButton( mButtonGuess, "Images/Icons/Character.svg", "Best guess mapping" ); - //connect( mButtonGuess, SIGNAL(clicked()), this, SLOT(OnBestGuessGeometrical()) ); - //mappingLayout->addWidget( mButtonGuess, 0, Qt::AlignLeft ); spacerWidget = new QWidget(); spacerWidget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum); mappingLayout->addWidget(spacerWidget); - mMappingTable = new QTableWidget(); - lowerLayout->addWidget(mMappingTable); - mMappingTable->setAlternatingRowColors(true); - mMappingTable->setGridStyle(Qt::SolidLine); - mMappingTable->setSelectionBehavior(QAbstractItemView::SelectRows); - mMappingTable->setSelectionMode(QAbstractItemView::SingleSelection); - //mMappingTable->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); - mMappingTable->setCornerButtonEnabled(false); - mMappingTable->setEditTriggers(QAbstractItemView::NoEditTriggers); - mMappingTable->setContextMenuPolicy(Qt::DefaultContextMenu); - mMappingTable->setContentsMargins(3, 1, 3, 1); - mMappingTable->setColumnCount(2); - mMappingTable->setColumnWidth(0, mMappingTable->width() / 2); - mMappingTable->setColumnWidth(1, mMappingTable->width() / 2); - verticalHeader = mMappingTable->verticalHeader(); + m_mappingTable = new QTableWidget(); + lowerLayout->addWidget(m_mappingTable); + m_mappingTable->setAlternatingRowColors(true); + m_mappingTable->setGridStyle(Qt::SolidLine); + m_mappingTable->setSelectionBehavior(QAbstractItemView::SelectRows); + m_mappingTable->setSelectionMode(QAbstractItemView::SingleSelection); + m_mappingTable->setCornerButtonEnabled(false); + m_mappingTable->setEditTriggers(QAbstractItemView::NoEditTriggers); + m_mappingTable->setContextMenuPolicy(Qt::DefaultContextMenu); + m_mappingTable->setContentsMargins(3, 1, 3, 1); + m_mappingTable->setColumnCount(2); + m_mappingTable->setColumnWidth(0, m_mappingTable->width() / 2); + m_mappingTable->setColumnWidth(1, m_mappingTable->width() / 2); + verticalHeader = m_mappingTable->verticalHeader(); verticalHeader->setVisible(false); // add the table headers headerItem = new QTableWidgetItem("Node"); headerItem->setTextAlignment(Qt::AlignVCenter | Qt::AlignLeft); - mMappingTable->setHorizontalHeaderItem(0, headerItem); + m_mappingTable->setHorizontalHeaderItem(0, headerItem); headerItem = new QTableWidgetItem("Mapped to"); headerItem->setTextAlignment(Qt::AlignVCenter | Qt::AlignLeft); - mMappingTable->setHorizontalHeaderItem(1, headerItem); - mMappingTable->horizontalHeader()->setStretchLastSection(true); - mMappingTable->horizontalHeader()->setSortIndicatorShown(false); - mMappingTable->horizontalHeader()->setSectionsClickable(false); - connect(mMappingTable, &QTableWidget::itemDoubleClicked, this, &MirrorSetupWindow::OnMappingTableDoubleClicked); - connect(mMappingTable, &QTableWidget::itemSelectionChanged, this, &MirrorSetupWindow::OnMappingTableSelectionChanged); + m_mappingTable->setHorizontalHeaderItem(1, headerItem); + m_mappingTable->horizontalHeader()->setStretchLastSection(true); + m_mappingTable->horizontalHeader()->setSortIndicatorShown(false); + m_mappingTable->horizontalHeader()->setSectionsClickable(false); + connect(m_mappingTable, &QTableWidget::itemDoubleClicked, this, &MirrorSetupWindow::OnMappingTableDoubleClicked); + connect(m_mappingTable, &QTableWidget::itemSelectionChanged, this, &MirrorSetupWindow::OnMappingTableSelectionChanged); } // destructor MirrorSetupWindow::~MirrorSetupWindow() { - delete mBoneIcon; - delete mNodeIcon; - delete mMeshIcon; - delete mMappedIcon; + delete m_boneIcon; + delete m_nodeIcon; + delete m_meshIcon; + delete m_mappedIcon; } @@ -298,7 +291,7 @@ namespace EMStudio void MirrorSetupWindow::OnMappingTableDoubleClicked(QTableWidgetItem* item) { MCORE_UNUSED(item); - // TODO: open a node hierarchy widget, where we can select a node from the mSourceActor + // TODO: open a node hierarchy widget, where we can select a node from the m_sourceActor // the problem is that the node hierarchy widget works with actor instances, which we don't have and do not really want to create either // I think the node hierarchy widget shouldn't use actor instances only, but should support actors as well } @@ -322,7 +315,7 @@ namespace EMStudio // get the node name const uint32 rowIndex = item->row(); - const AZStd::string nodeName = mCurrentList->item(rowIndex, 2)->text().toUtf8().data(); + const AZStd::string nodeName = m_currentList->item(rowIndex, 2)->text().toUtf8().data(); // find its index in the current actor, and remove its mapping EMotionFX::Node* node = currentActor->GetSkeleton()->FindNodeByName(nodeName.c_str()); @@ -336,12 +329,12 @@ namespace EMStudio // current list selection changed void MirrorSetupWindow::OnCurrentListSelectionChanged() { - QList items = mCurrentList->selectedItems(); + QList items = m_currentList->selectedItems(); if (items.count() > 0) { //const uint32 currentListRow = items[0]->row(); - QTableWidgetItem* nameItem = mCurrentList->item(items[0]->row(), 2); - QList mappingTableItems = mMappingTable->findItems(nameItem->text(), Qt::MatchExactly); + QTableWidgetItem* nameItem = m_currentList->item(items[0]->row(), 2); + QList mappingTableItems = m_mappingTable->findItems(nameItem->text(), Qt::MatchExactly); for (int32 i = 0; i < mappingTableItems.count(); ++i) { @@ -352,8 +345,8 @@ namespace EMStudio const uint32 rowIndex = mappingTableItems[i]->row(); - mMappingTable->selectRow(rowIndex); - mMappingTable->setCurrentItem(mappingTableItems[i]); + m_mappingTable->selectRow(rowIndex); + m_mappingTable->setCurrentItem(mappingTableItems[i]); } } } @@ -362,12 +355,12 @@ namespace EMStudio // source list selection changed void MirrorSetupWindow::OnSourceListSelectionChanged() { - QList items = mSourceList->selectedItems(); + QList items = m_sourceList->selectedItems(); if (items.count() > 0) { //const uint32 currentListRow = items[0]->row(); - QTableWidgetItem* nameItem = mSourceList->item(items[0]->row(), 2); - QList mappingTableItems = mMappingTable->findItems(nameItem->text(), Qt::MatchExactly); + QTableWidgetItem* nameItem = m_sourceList->item(items[0]->row(), 2); + QList mappingTableItems = m_mappingTable->findItems(nameItem->text(), Qt::MatchExactly); for (int32 i = 0; i < mappingTableItems.count(); ++i) { @@ -378,8 +371,8 @@ namespace EMStudio const uint32 rowIndex = mappingTableItems[i]->row(); - mMappingTable->selectRow(rowIndex); - mMappingTable->setCurrentItem(mappingTableItems[i]); + m_mappingTable->selectRow(rowIndex); + m_mappingTable->setCurrentItem(mappingTableItems[i]); } } } @@ -389,30 +382,30 @@ namespace EMStudio void MirrorSetupWindow::OnMappingTableSelectionChanged() { // select both items in the list widgets as well - QList items = mMappingTable->selectedItems(); + QList items = m_mappingTable->selectedItems(); if (items.count() > 0) { const uint32 rowIndex = items[0]->row(); - QTableWidgetItem* item = mMappingTable->item(rowIndex, 0); + QTableWidgetItem* item = m_mappingTable->item(rowIndex, 0); if (item) { - QList listItems = mCurrentList->findItems(item->text(), Qt::MatchExactly); + QList listItems = m_currentList->findItems(item->text(), Qt::MatchExactly); if (listItems.count() > 0) { - mCurrentList->selectRow(listItems[0]->row()); - mCurrentList->setCurrentItem(listItems[0]); + m_currentList->selectRow(listItems[0]->row()); + m_currentList->setCurrentItem(listItems[0]); } } - item = mMappingTable->item(rowIndex, 1); + item = m_mappingTable->item(rowIndex, 1); if (item) { - QList listItems = mSourceList->findItems(item->text(), Qt::MatchExactly); + QList listItems = m_sourceList->findItems(item->text(), Qt::MatchExactly); if (listItems.count() > 0) { - mSourceList->selectRow(listItems[0]->row()); - mSourceList->setCurrentItem(listItems[0]); + m_sourceList->selectRow(listItems[0]->row()); + m_sourceList->setCurrentItem(listItems[0]); } } } @@ -432,18 +425,18 @@ namespace EMStudio // extract the list of bones if (currentActor) { - currentActor->ExtractBoneList(0, &mCurrentBoneList); + currentActor->ExtractBoneList(0, &m_currentBoneList); } // clear the node map if (reInitMap) { - mMap.clear(); + m_map.clear(); if (currentActor) { const size_t numNodes = aznumeric_caster(currentActor->GetNumNodes()); - mMap.resize(numNodes); - AZStd::fill(mMap.begin(), mMap.end(), InvalidIndex); + m_map.resize(numNodes); + AZStd::fill(m_map.begin(), m_map.end(), InvalidIndex); } } @@ -481,7 +474,7 @@ namespace EMStudio { if (!actor) { - mCurrentList->setRowCount(0); + m_currentList->setRowCount(0); return; } @@ -499,7 +492,7 @@ namespace EMStudio numRows++; } } - mCurrentList->setRowCount(numRows); + m_currentList->setRowCount(numRows); // fill the rows int rowIndex = 0; @@ -510,34 +503,34 @@ namespace EMStudio if (currentName.contains(filterString, Qt::CaseInsensitive) || filterString.isEmpty()) { // mark if there is a mapping or not - const bool mapped = (mMap[node->GetNodeIndex()] != InvalidIndex); + const bool mapped = (m_map[node->GetNodeIndex()] != InvalidIndex); QTableWidgetItem* mappedItem = new QTableWidgetItem(); - mappedItem->setIcon(mapped ? *mMappedIcon : QIcon()); - mCurrentList->setItem(rowIndex, 0, mappedItem); + mappedItem->setIcon(mapped ? *m_mappedIcon : QIcon()); + m_currentList->setItem(rowIndex, 0, mappedItem); // pick the right icon for the type column QTableWidgetItem* typeItem = new QTableWidgetItem(); if (actor->GetMesh(0, node->GetNodeIndex())) { - typeItem->setIcon(*mMeshIcon); + typeItem->setIcon(*m_meshIcon); } - else if (AZStd::find(begin(mCurrentBoneList), end(mCurrentBoneList), node->GetNodeIndex()) != end(mCurrentBoneList)) + else if (AZStd::find(begin(m_currentBoneList), end(m_currentBoneList), node->GetNodeIndex()) != end(m_currentBoneList)) { - typeItem->setIcon(*mBoneIcon); + typeItem->setIcon(*m_boneIcon); } else { - typeItem->setIcon(*mNodeIcon); + typeItem->setIcon(*m_nodeIcon); } - mCurrentList->setItem(rowIndex, 1, typeItem); + m_currentList->setItem(rowIndex, 1, typeItem); // set the name QTableWidgetItem* currentTableItem = new QTableWidgetItem(currentName); - mCurrentList->setItem(rowIndex, 2, currentTableItem); + m_currentList->setItem(rowIndex, 2, currentTableItem); // set the row height and add one index - mCurrentList->setRowHeight(rowIndex, 21); + m_currentList->setRowHeight(rowIndex, 21); ++rowIndex; } } @@ -549,7 +542,7 @@ namespace EMStudio { if (!actor) { - mSourceList->setRowCount(0); + m_sourceList->setRowCount(0); return; } @@ -567,7 +560,7 @@ namespace EMStudio numRows++; } } - mSourceList->setRowCount(numRows); + m_sourceList->setRowCount(numRows); // fill the rows int rowIndex = 0; @@ -578,34 +571,34 @@ namespace EMStudio if (name.contains(filterString, Qt::CaseInsensitive) || filterString.isEmpty()) { // mark if there is a mapping or not - const bool mapped = AZStd::find(mMap.begin(), mMap.end(), i) != mMap.end(); + const bool mapped = AZStd::find(m_map.begin(), m_map.end(), i) != m_map.end(); QTableWidgetItem* mappedItem = new QTableWidgetItem(); - mappedItem->setIcon(mapped ? *mMappedIcon : QIcon()); - mSourceList->setItem(rowIndex, 0, mappedItem); + mappedItem->setIcon(mapped ? *m_mappedIcon : QIcon()); + m_sourceList->setItem(rowIndex, 0, mappedItem); // pick the right icon for the type column QTableWidgetItem* typeItem = new QTableWidgetItem(); if (actor->GetMesh(0, node->GetNodeIndex())) { - typeItem->setIcon(*mMeshIcon); + typeItem->setIcon(*m_meshIcon); } - else if (AZStd::find(mSourceBoneList.begin(), mSourceBoneList.end(), node->GetNodeIndex()) != mSourceBoneList.end()) + else if (AZStd::find(m_sourceBoneList.begin(), m_sourceBoneList.end(), node->GetNodeIndex()) != m_sourceBoneList.end()) { - typeItem->setIcon(*mBoneIcon); + typeItem->setIcon(*m_boneIcon); } else { - typeItem->setIcon(*mNodeIcon); + typeItem->setIcon(*m_nodeIcon); } - mSourceList->setItem(rowIndex, 1, typeItem); + m_sourceList->setItem(rowIndex, 1, typeItem); // set the name QTableWidgetItem* currentTableItem = new QTableWidgetItem(name); - mSourceList->setItem(rowIndex, 2, currentTableItem); + m_sourceList->setItem(rowIndex, 2, currentTableItem); // set the row height and add one index - mSourceList->setRowHeight(rowIndex, 21); + m_sourceList->setRowHeight(rowIndex, 21); ++rowIndex; } } @@ -617,7 +610,7 @@ namespace EMStudio { if (!currentActor) { - mMappingTable->setRowCount(0); + m_mappingTable->setRowCount(0); return; } @@ -625,24 +618,24 @@ namespace EMStudio QString currentName; QString sourceName; const int numNodes = aznumeric_caster(currentActor->GetNumNodes()); - mMappingTable->setRowCount(numNodes); + m_mappingTable->setRowCount(numNodes); for (int i = 0; i < numNodes; ++i) { currentName = currentActor->GetSkeleton()->GetNode(i)->GetName(); QTableWidgetItem* currentTableItem = new QTableWidgetItem(currentName); - mMappingTable->setItem(i, 0, currentTableItem); - mMappingTable->setRowHeight(i, 21); + m_mappingTable->setItem(i, 0, currentTableItem); + m_mappingTable->setRowHeight(i, 21); - if (mMap[i] != InvalidIndex) + if (m_map[i] != InvalidIndex) { - sourceName = sourceActor->GetSkeleton()->GetNode(mMap[i])->GetName(); + sourceName = sourceActor->GetSkeleton()->GetNode(m_map[i])->GetName(); currentTableItem = new QTableWidgetItem(sourceName); - mMappingTable->setItem(i, 1, currentTableItem); + m_mappingTable->setItem(i, 1, currentTableItem); } else { - mMappingTable->setItem(i, 1, new QTableWidgetItem()); + m_mappingTable->setItem(i, 1, new QTableWidgetItem()); } } } @@ -651,24 +644,24 @@ namespace EMStudio // pressing the link button void MirrorSetupWindow::OnLinkPressed() { - if (mCurrentList->currentRow() == -1 || mSourceList->currentRow() == -1) + if (m_currentList->currentRow() == -1 || m_sourceList->currentRow() == -1) { return; } // get the names - QTableWidgetItem* curItem = mCurrentList->currentItem(); - QTableWidgetItem* sourceItem = mSourceList->currentItem(); + QTableWidgetItem* curItem = m_currentList->currentItem(); + QTableWidgetItem* sourceItem = m_sourceList->currentItem(); if (!curItem || !sourceItem) { return; } - curItem = mCurrentList->item(curItem->row(), 2); - sourceItem = mSourceList->item(sourceItem->row(), 2); + curItem = m_currentList->item(curItem->row(), 2); + sourceItem = m_sourceList->item(sourceItem->row(), 2); const AZStd::string currentNodeName = curItem->text().toUtf8().data(); - const AZStd::string sourceNodeName = mSourceList->currentItem()->text().toUtf8().data(); + const AZStd::string sourceNodeName = m_sourceList->currentItem()->text().toUtf8().data(); if (sourceNodeName.empty() || currentNodeName.empty()) { return; @@ -692,21 +685,21 @@ namespace EMStudio EMotionFX::Actor* currentActor = GetSelectedActor(); // update the map - const size_t oldSourceIndex = mMap[currentNodeIndex]; - mMap[currentNodeIndex] = sourceNodeIndex; + const size_t oldSourceIndex = m_map[currentNodeIndex]; + m_map[currentNodeIndex] = sourceNodeIndex; // update the current table const QString curName = currentActor->GetSkeleton()->GetNode(currentNodeIndex)->GetName(); - const QList currentListItems = mCurrentList->findItems(curName, Qt::MatchExactly); + const QList currentListItems = m_currentList->findItems(curName, Qt::MatchExactly); for (int32 i = 0; i < currentListItems.count(); ++i) { const int rowIndex = currentListItems[i]->row(); - QTableWidgetItem* mappedItem = mCurrentList->item(rowIndex, 0); + QTableWidgetItem* mappedItem = m_currentList->item(rowIndex, 0); if (!mappedItem) { mappedItem = new QTableWidgetItem(); - mCurrentList->setItem(rowIndex, 0, mappedItem); + m_currentList->setItem(rowIndex, 0, mappedItem); } if (sourceNodeIndex == InvalidIndex) @@ -715,25 +708,25 @@ namespace EMStudio } else { - mappedItem->setIcon(*mMappedIcon); + mappedItem->setIcon(*m_mappedIcon); } } // update source table if (sourceNodeIndex != InvalidIndex) { - const bool stillUsed = AZStd::find(mMap.begin(), mMap.end(), sourceNodeIndex) != mMap.end(); + const bool stillUsed = AZStd::find(m_map.begin(), m_map.end(), sourceNodeIndex) != m_map.end(); const QString sourceName = currentActor->GetSkeleton()->GetNode(sourceNodeIndex)->GetName(); - const QList sourceListItems = mSourceList->findItems(sourceName, Qt::MatchExactly); + const QList sourceListItems = m_sourceList->findItems(sourceName, Qt::MatchExactly); for (int32 i = 0; i < sourceListItems.count(); ++i) { const int rowIndex = sourceListItems[i]->row(); - QTableWidgetItem* mappedItem = mSourceList->item(rowIndex, 0); + QTableWidgetItem* mappedItem = m_sourceList->item(rowIndex, 0); if (!mappedItem) { mappedItem = new QTableWidgetItem(); - mSourceList->setItem(rowIndex, 0, mappedItem); + m_sourceList->setItem(rowIndex, 0, mappedItem); } if (stillUsed == false) @@ -742,7 +735,7 @@ namespace EMStudio } else { - mappedItem->setIcon(*mMappedIcon); + mappedItem->setIcon(*m_mappedIcon); } } } @@ -750,18 +743,18 @@ namespace EMStudio { if (oldSourceIndex != InvalidIndex) { - const bool stillUsed = AZStd::find(mMap.begin(), mMap.end(), sourceNodeIndex) != mMap.end(); + const bool stillUsed = AZStd::find(m_map.begin(), m_map.end(), sourceNodeIndex) != m_map.end(); const QString sourceName = currentActor->GetSkeleton()->GetNode(oldSourceIndex)->GetName(); - const QList sourceListItems = mSourceList->findItems(sourceName, Qt::MatchExactly); + const QList sourceListItems = m_sourceList->findItems(sourceName, Qt::MatchExactly); for (int32 i = 0; i < sourceListItems.count(); ++i) { const int rowIndex = sourceListItems[i]->row(); - QTableWidgetItem* mappedItem = mSourceList->item(rowIndex, 0); + QTableWidgetItem* mappedItem = m_sourceList->item(rowIndex, 0); if (!mappedItem) { mappedItem = new QTableWidgetItem(); - mSourceList->setItem(rowIndex, 0, mappedItem); + m_sourceList->setItem(rowIndex, 0, mappedItem); } if (stillUsed == false) @@ -770,18 +763,18 @@ namespace EMStudio } else { - mappedItem->setIcon(*mMappedIcon); + mappedItem->setIcon(*m_mappedIcon); } } } } // update the mapping table - QTableWidgetItem* item = mMappingTable->item(aznumeric_caster(currentNodeIndex), 1); + QTableWidgetItem* item = m_mappingTable->item(aznumeric_caster(currentNodeIndex), 1); if (!item && sourceNodeIndex != InvalidIndex) { item = new QTableWidgetItem(); - mMappingTable->setItem(aznumeric_caster(currentNodeIndex), 1, item); + m_mappingTable->setItem(aznumeric_caster(currentNodeIndex), 1, item); } if (sourceNodeIndex == InvalidIndex) @@ -827,10 +820,10 @@ namespace EMStudio // remove the currently selected mapping void MirrorSetupWindow::RemoveCurrentSelectedMapping() { - QList items = mCurrentList->selectedItems(); + QList items = m_currentList->selectedItems(); if (items.count() > 0) { - QTableWidgetItem* item = mCurrentList->item(items[0]->row(), 0); + QTableWidgetItem* item = m_currentList->item(items[0]->row(), 0); if (item) { OnCurrentListDoubleClicked(item); @@ -881,7 +874,7 @@ namespace EMStudio // now update our mapping data const size_t numNodes = currentActor->GetNumNodes(); - AZStd::fill(mMap.begin(), AZStd::next(mMap.begin(), numNodes), InvalidIndex); + AZStd::fill(m_map.begin(), AZStd::next(m_map.begin(), numNodes), InvalidIndex); // now apply the map we loaded to the data we have here const size_t numEntries = nodeMap->GetNumEntries(); @@ -902,7 +895,7 @@ namespace EMStudio } // create the mapping - mMap[currentNode->GetNodeIndex()] = sourceNode->GetNodeIndex(); + m_map[currentNode->GetNodeIndex()] = sourceNode->GetNodeIndex(); } // apply the current map as command @@ -952,7 +945,7 @@ namespace EMStudio for (size_t i = 0; i < numNodes; ++i) { // skip unmapped entries - if (mMap[i] == InvalidIndex) + if (m_map[i] == InvalidIndex) { continue; } @@ -960,7 +953,7 @@ namespace EMStudio // add the entry to the map if it doesn't yet exist if (map->GetHasEntry(currentActor->GetSkeleton()->GetNode(i)->GetName()) == false) { - map->AddEntry(currentActor->GetSkeleton()->GetNode(i)->GetName(), currentActor->GetSkeleton()->GetNode(mMap[i])->GetName()); + map->AddEntry(currentActor->GetSkeleton()->GetNode(i)->GetName(), currentActor->GetSkeleton()->GetNode(m_map[i])->GetName()); } } @@ -1018,7 +1011,7 @@ namespace EMStudio } const size_t numNodes = currentActor->GetNumNodes(); - return AZStd::all_of(mMap.begin(), AZStd::next(mMap.begin(), numNodes), [](const size_t nodeIndex) + return AZStd::all_of(m_map.begin(), AZStd::next(m_map.begin(), numNodes), [](const size_t nodeIndex) { return nodeIndex != InvalidIndex; }); @@ -1037,10 +1030,10 @@ namespace EMStudio const bool canGuess = (currentActor); // enable or disable them - mButtonOpen->setEnabled(canOpen); - mButtonSave->setEnabled(canSave); - mButtonClear->setEnabled(canClear); - mButtonGuess->setEnabled(canGuess); + m_buttonOpen->setEnabled(canOpen); + m_buttonSave->setEnabled(canSave); + m_buttonClear->setEnabled(canClear); + m_buttonGuess->setEnabled(canGuess); } @@ -1054,7 +1047,7 @@ namespace EMStudio return; } - if (mLeftEdit->text().size() == 0 || mRightEdit->text().size() == 0) + if (m_leftEdit->text().size() == 0 || m_rightEdit->text().size() == 0) { QMessageBox::information(this, "Empty Left And Right Strings", "Please enter both a left and right sub-string.\nThis can be something like 'Left' and 'Right'.\nThis would map nodes like 'Left Arm' to 'Right Arm' nodes.", QMessageBox::Ok); return; @@ -1066,15 +1059,15 @@ namespace EMStudio for (size_t i = 0; i < numNodes; ++i) { // skip already setup mappings - if (mMap[i] != InvalidIndex) + if (m_map[i] != InvalidIndex) { continue; } - const uint16 matchIndex = currentActor->FindBestMatchForNode(currentActor->GetSkeleton()->GetNode(i)->GetName(), FromQtString(mLeftEdit->text()).c_str(), FromQtString(mRightEdit->text()).c_str()); + const uint16 matchIndex = currentActor->FindBestMatchForNode(currentActor->GetSkeleton()->GetNode(i)->GetName(), FromQtString(m_leftEdit->text()).c_str(), FromQtString(m_rightEdit->text()).c_str()); if (matchIndex != MCORE_INVALIDINDEX16) { - mMap[i] = matchIndex; + m_map[i] = matchIndex; numGuessed++; } } @@ -1117,19 +1110,19 @@ namespace EMStudio { if (actor->GetHasMirrorInfo()) { - uint16 motionSource = actor->GetNodeMirrorInfo(i).mSourceNode; + uint16 motionSource = actor->GetNodeMirrorInfo(i).m_sourceNode; if (motionSource != i) { - mMap[i] = motionSource; + m_map[i] = motionSource; } else { - mMap[i] = InvalidIndex; + m_map[i] = InvalidIndex; } } else { - mMap[i] = InvalidIndex; + m_map[i] = InvalidIndex; } } } @@ -1149,7 +1142,7 @@ namespace EMStudio AZStd::string commandString = AZStd::string::format("AdjustActor -actorID %d -mirrorSetup \"", currentActor->GetID()); for (size_t i = 0; i < currentActor->GetNumNodes(); ++i) { - size_t sourceNode = mMap[i]; + size_t sourceNode = m_map[i]; if (sourceNode != InvalidIndex && sourceNode != i) { commandString += currentActor->GetSkeleton()->GetNode(i)->GetName(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/MirrorSetupWindow.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/MirrorSetupWindow.h index 660359ba4a..6fc435025b 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/MirrorSetupWindow.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/MirrorSetupWindow.h @@ -63,25 +63,25 @@ namespace EMStudio private: - SceneManagerPlugin* mPlugin; - QTableWidget* mSourceList; - QTableWidget* mCurrentList; - QTableWidget* mMappingTable; - QPushButton* mButtonOpen; - QPushButton* mButtonSave; - QPushButton* mButtonClear; - QPushButton* mButtonGuess; - QLineEdit* mLeftEdit; - QLineEdit* mRightEdit; + SceneManagerPlugin* m_plugin; + QTableWidget* m_sourceList; + QTableWidget* m_currentList; + QTableWidget* m_mappingTable; + QPushButton* m_buttonOpen; + QPushButton* m_buttonSave; + QPushButton* m_buttonClear; + QPushButton* m_buttonGuess; + QLineEdit* m_leftEdit; + QLineEdit* m_rightEdit; AzQtComponents::FilteredSearchWidget* m_searchWidgetCurrent; AzQtComponents::FilteredSearchWidget* m_searchWidgetSource; - QIcon* mBoneIcon; - QIcon* mNodeIcon; - QIcon* mMeshIcon; - QIcon* mMappedIcon; - AZStd::vector mCurrentBoneList; - AZStd::vector mSourceBoneList; - AZStd::vector mMap; + QIcon* m_boneIcon; + QIcon* m_nodeIcon; + QIcon* m_meshIcon; + QIcon* m_mappedIcon; + AZStd::vector m_currentBoneList; + AZStd::vector m_sourceBoneList; + AZStd::vector m_map; void FillCurrentListWidget(EMotionFX::Actor* actor, const QString& filterString); void FillSourceListWidget(EMotionFX::Actor* actor, const QString& filterString); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/SceneManagerPlugin.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/SceneManagerPlugin.cpp index 61b6c44dbb..3e498f6383 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/SceneManagerPlugin.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/SceneManagerPlugin.cpp @@ -38,7 +38,7 @@ namespace EMStudio // add the link to the actual object ObjectPointer objPointer; - objPointer.mActor = actor; + objPointer.m_actor = actor; outObjects->push_back(objPointer); } } @@ -52,13 +52,13 @@ namespace EMStudio for (const ObjectPointer& objPointer : objects) { // get the current object pointer and skip directly if the type check fails - if (objPointer.mActor == nullptr) + if (objPointer.m_actor == nullptr) { continue; } - EMotionFX::Actor* actor = objPointer.mActor; - if (mPlugin->SaveDirtyActor(actor, commandGroup, false) == DirtyFileManager::CANCELED) + EMotionFX::Actor* actor = objPointer.m_actor; + if (m_plugin->SaveDirtyActor(actor, commandGroup, false) == DirtyFileManager::CANCELED) { return DirtyFileManager::CANCELED; } @@ -72,20 +72,20 @@ namespace EMStudio SceneManagerPlugin::SceneManagerPlugin() : EMStudio::DockWidgetPlugin() { - mImportActorCallback = nullptr; - mCreateActorInstanceCallback = nullptr; - mSelectCallback = nullptr; - mUnselectCallback = nullptr; - mClearSelectionCallback = nullptr; - mRemoveActorCallback = nullptr; - mRemoveActorInstanceCallback = nullptr; - mSaveActorAssetInfoCallback = nullptr; - mScaleActorDataCallback = nullptr; - mActorPropsWindow = nullptr; - mAdjustActorCallback = nullptr; - mActorSetCollisionMeshesCallback = nullptr; - mAdjustActorInstanceCallback = nullptr; - mDirtyFilesCallback = nullptr; + m_importActorCallback = nullptr; + m_createActorInstanceCallback = nullptr; + m_selectCallback = nullptr; + m_unselectCallback = nullptr; + m_clearSelectionCallback = nullptr; + m_removeActorCallback = nullptr; + m_removeActorInstanceCallback = nullptr; + m_saveActorAssetInfoCallback = nullptr; + m_scaleActorDataCallback = nullptr; + m_actorPropsWindow = nullptr; + m_adjustActorCallback = nullptr; + m_actorSetCollisionMeshesCallback = nullptr; + m_adjustActorInstanceCallback = nullptr; + m_dirtyFilesCallback = nullptr; } @@ -177,33 +177,33 @@ namespace EMStudio SceneManagerPlugin::~SceneManagerPlugin() { // unregister the command callbacks and get rid of the memory - GetCommandManager()->RemoveCommandCallback(mImportActorCallback, false); - GetCommandManager()->RemoveCommandCallback(mCreateActorInstanceCallback, false); - GetCommandManager()->RemoveCommandCallback(mSelectCallback, false); - GetCommandManager()->RemoveCommandCallback(mUnselectCallback, false); - GetCommandManager()->RemoveCommandCallback(mClearSelectionCallback, false); - GetCommandManager()->RemoveCommandCallback(mRemoveActorCallback, false); - GetCommandManager()->RemoveCommandCallback(mRemoveActorInstanceCallback, false); - GetCommandManager()->RemoveCommandCallback(mSaveActorAssetInfoCallback, false); - GetCommandManager()->RemoveCommandCallback(mAdjustActorCallback, false); - GetCommandManager()->RemoveCommandCallback(mActorSetCollisionMeshesCallback, false); - GetCommandManager()->RemoveCommandCallback(mAdjustActorInstanceCallback, false); - GetCommandManager()->RemoveCommandCallback(mScaleActorDataCallback, false); - delete mImportActorCallback; - delete mCreateActorInstanceCallback; - delete mSelectCallback; - delete mUnselectCallback; - delete mClearSelectionCallback; - delete mRemoveActorCallback; - delete mRemoveActorInstanceCallback; - delete mSaveActorAssetInfoCallback; - delete mAdjustActorCallback; - delete mActorSetCollisionMeshesCallback; - delete mAdjustActorInstanceCallback; - delete mScaleActorDataCallback; + GetCommandManager()->RemoveCommandCallback(m_importActorCallback, false); + GetCommandManager()->RemoveCommandCallback(m_createActorInstanceCallback, false); + GetCommandManager()->RemoveCommandCallback(m_selectCallback, false); + GetCommandManager()->RemoveCommandCallback(m_unselectCallback, false); + GetCommandManager()->RemoveCommandCallback(m_clearSelectionCallback, false); + GetCommandManager()->RemoveCommandCallback(m_removeActorCallback, false); + GetCommandManager()->RemoveCommandCallback(m_removeActorInstanceCallback, false); + GetCommandManager()->RemoveCommandCallback(m_saveActorAssetInfoCallback, false); + GetCommandManager()->RemoveCommandCallback(m_adjustActorCallback, false); + GetCommandManager()->RemoveCommandCallback(m_actorSetCollisionMeshesCallback, false); + GetCommandManager()->RemoveCommandCallback(m_adjustActorInstanceCallback, false); + GetCommandManager()->RemoveCommandCallback(m_scaleActorDataCallback, false); + delete m_importActorCallback; + delete m_createActorInstanceCallback; + delete m_selectCallback; + delete m_unselectCallback; + delete m_clearSelectionCallback; + delete m_removeActorCallback; + delete m_removeActorInstanceCallback; + delete m_saveActorAssetInfoCallback; + delete m_adjustActorCallback; + delete m_actorSetCollisionMeshesCallback; + delete m_adjustActorInstanceCallback; + delete m_scaleActorDataCallback; - GetMainWindow()->GetDirtyFileManager()->RemoveCallback(mDirtyFilesCallback, false); - delete mDirtyFilesCallback; + GetMainWindow()->GetDirtyFileManager()->RemoveCallback(m_dirtyFilesCallback, false); + delete m_dirtyFilesCallback; } @@ -221,57 +221,57 @@ namespace EMStudio MysticQt::DialogStack* dialogStack = new MysticQt::DialogStack(); // create and register the command callbacks only (only execute this code once for all plugins) - mImportActorCallback = new ImportActorCallback(false); - mCreateActorInstanceCallback = new CreateActorInstanceCallback(false); - mSelectCallback = new CommandSelectCallback(false); - mUnselectCallback = new CommandUnselectCallback(false); - mClearSelectionCallback = new CommandClearSelectionCallback(false); - mRemoveActorCallback = new RemoveActorCallback(false); - mRemoveActorInstanceCallback = new RemoveActorInstanceCallback(false); - mSaveActorAssetInfoCallback = new SaveActorAssetInfoCallback(false); - mAdjustActorCallback = new CommandAdjustActorCallback(false); - mActorSetCollisionMeshesCallback = new CommandActorSetCollisionMeshesCallback(false); - mAdjustActorInstanceCallback = new CommandAdjustActorInstanceCallback(false); - mScaleActorDataCallback = new CommandScaleActorDataCallback(false); + m_importActorCallback = new ImportActorCallback(false); + m_createActorInstanceCallback = new CreateActorInstanceCallback(false); + m_selectCallback = new CommandSelectCallback(false); + m_unselectCallback = new CommandUnselectCallback(false); + m_clearSelectionCallback = new CommandClearSelectionCallback(false); + m_removeActorCallback = new RemoveActorCallback(false); + m_removeActorInstanceCallback = new RemoveActorInstanceCallback(false); + m_saveActorAssetInfoCallback = new SaveActorAssetInfoCallback(false); + m_adjustActorCallback = new CommandAdjustActorCallback(false); + m_actorSetCollisionMeshesCallback = new CommandActorSetCollisionMeshesCallback(false); + m_adjustActorInstanceCallback = new CommandAdjustActorInstanceCallback(false); + m_scaleActorDataCallback = new CommandScaleActorDataCallback(false); - GetCommandManager()->RegisterCommandCallback("ImportActor", mImportActorCallback); - GetCommandManager()->RegisterCommandCallback("CreateActorInstance", mCreateActorInstanceCallback); - GetCommandManager()->RegisterCommandCallback("Select", mSelectCallback); - GetCommandManager()->RegisterCommandCallback("Unselect", mUnselectCallback); - GetCommandManager()->RegisterCommandCallback("ClearSelection", mClearSelectionCallback); - GetCommandManager()->RegisterCommandCallback("RemoveActor", mRemoveActorCallback); - GetCommandManager()->RegisterCommandCallback("RemoveActorInstance", mRemoveActorInstanceCallback); - GetCommandManager()->RegisterCommandCallback("SaveActorAssetInfo", mSaveActorAssetInfoCallback); - GetCommandManager()->RegisterCommandCallback("AdjustActor", mAdjustActorCallback); - GetCommandManager()->RegisterCommandCallback("ActorSetCollisionMeshes", mActorSetCollisionMeshesCallback); - GetCommandManager()->RegisterCommandCallback("AdjustActorInstance", mAdjustActorInstanceCallback); - GetCommandManager()->RegisterCommandCallback("ScaleActorData", mScaleActorDataCallback); + GetCommandManager()->RegisterCommandCallback("ImportActor", m_importActorCallback); + GetCommandManager()->RegisterCommandCallback("CreateActorInstance", m_createActorInstanceCallback); + GetCommandManager()->RegisterCommandCallback("Select", m_selectCallback); + GetCommandManager()->RegisterCommandCallback("Unselect", m_unselectCallback); + GetCommandManager()->RegisterCommandCallback("ClearSelection", m_clearSelectionCallback); + GetCommandManager()->RegisterCommandCallback("RemoveActor", m_removeActorCallback); + GetCommandManager()->RegisterCommandCallback("RemoveActorInstance", m_removeActorInstanceCallback); + GetCommandManager()->RegisterCommandCallback("SaveActorAssetInfo", m_saveActorAssetInfoCallback); + GetCommandManager()->RegisterCommandCallback("AdjustActor", m_adjustActorCallback); + GetCommandManager()->RegisterCommandCallback("ActorSetCollisionMeshes", m_actorSetCollisionMeshesCallback); + GetCommandManager()->RegisterCommandCallback("AdjustActorInstance", m_adjustActorInstanceCallback); + GetCommandManager()->RegisterCommandCallback("ScaleActorData", m_scaleActorDataCallback); // create the actors window - mActorsWindow = new ActorsWindow(this); + m_actorsWindow = new ActorsWindow(this); // add in the dialog stack - dialogStack->Add(mActorsWindow, "Actors", false, true, true); + dialogStack->Add(m_actorsWindow, "Actors", false, true, true); // create the actor properties window - mActorPropsWindow = new ActorPropertiesWindow(mDock, this); - mActorPropsWindow->Init(); + m_actorPropsWindow = new ActorPropertiesWindow(m_dock, this); + m_actorPropsWindow->Init(); // add the actor properties window to the stack window - dialogStack->Add(mActorPropsWindow, "Actor Properties", false, false, true); + dialogStack->Add(m_actorPropsWindow, "Actor Properties", false, false, true); // set dialog stack as main widget of the dock - mDock->setWidget(dialogStack); + m_dock->setWidget(dialogStack); // connect - connect(mDock, &QDockWidget::visibilityChanged, this, &SceneManagerPlugin::WindowReInit); + connect(m_dock, &QDockWidget::visibilityChanged, this, &SceneManagerPlugin::WindowReInit); // reinit the dialog ReInit(); // initialize the dirty files callback - mDirtyFilesCallback = new SaveDirtyActorFilesCallback(this); - GetMainWindow()->GetDirtyFileManager()->AddCallback(mDirtyFilesCallback); + m_dirtyFilesCallback = new SaveDirtyActorFilesCallback(this); + GetMainWindow()->GetDirtyFileManager()->AddCallback(m_dirtyFilesCallback); return true; } @@ -281,7 +281,7 @@ namespace EMStudio void SceneManagerPlugin::ReInit() { // reinit the actors window - mActorsWindow->ReInit(); + m_actorsWindow->ReInit(); // update the interface UpdateInterface(); @@ -292,10 +292,10 @@ namespace EMStudio void SceneManagerPlugin::UpdateInterface() { // update interface of the actors window - mActorsWindow->UpdateInterface(); + m_actorsWindow->UpdateInterface(); // update interface of the actor properties window - mActorPropsWindow->UpdateInterface(); + m_actorPropsWindow->UpdateInterface(); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/SceneManagerPlugin.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/SceneManagerPlugin.h index 5d0bbb50b1..b6d2a55306 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/SceneManagerPlugin.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/SceneManagerPlugin.h @@ -37,7 +37,7 @@ namespace EMStudio public: SaveDirtyActorFilesCallback(SceneManagerPlugin* plugin) - : SaveDirtyFilesCallback() { mPlugin = plugin; } + : SaveDirtyFilesCallback() { m_plugin = plugin; } ~SaveDirtyActorFilesCallback() {} uint32 GetType() const override { return TYPE_ID; } @@ -54,7 +54,7 @@ namespace EMStudio int SaveDirtyFiles(const AZStd::vector& filenamesToSave, const AZStd::vector& objects, MCore::CommandGroup* commandGroup) override; private: - SceneManagerPlugin* mPlugin; + SceneManagerPlugin* m_plugin; }; class SceneManagerPlugin @@ -107,22 +107,22 @@ namespace EMStudio MCORE_DEFINECOMMANDCALLBACK(CommandAdjustActorInstanceCallback); MCORE_DEFINECOMMANDCALLBACK(CommandScaleActorDataCallback); - ImportActorCallback* mImportActorCallback; - CreateActorInstanceCallback* mCreateActorInstanceCallback; - CommandSelectCallback* mSelectCallback; - CommandUnselectCallback* mUnselectCallback; - CommandClearSelectionCallback* mClearSelectionCallback; - RemoveActorCallback* mRemoveActorCallback; - RemoveActorInstanceCallback* mRemoveActorInstanceCallback; - SaveActorAssetInfoCallback* mSaveActorAssetInfoCallback; - CommandAdjustActorCallback* mAdjustActorCallback; - CommandActorSetCollisionMeshesCallback* mActorSetCollisionMeshesCallback; - CommandAdjustActorInstanceCallback* mAdjustActorInstanceCallback; - CommandScaleActorDataCallback* mScaleActorDataCallback; + ImportActorCallback* m_importActorCallback; + CreateActorInstanceCallback* m_createActorInstanceCallback; + CommandSelectCallback* m_selectCallback; + CommandUnselectCallback* m_unselectCallback; + CommandClearSelectionCallback* m_clearSelectionCallback; + RemoveActorCallback* m_removeActorCallback; + RemoveActorInstanceCallback* m_removeActorInstanceCallback; + SaveActorAssetInfoCallback* m_saveActorAssetInfoCallback; + CommandAdjustActorCallback* m_adjustActorCallback; + CommandActorSetCollisionMeshesCallback* m_actorSetCollisionMeshesCallback; + CommandAdjustActorInstanceCallback* m_adjustActorInstanceCallback; + CommandScaleActorDataCallback* m_scaleActorDataCallback; - SaveDirtyActorFilesCallback* mDirtyFilesCallback; + SaveDirtyActorFilesCallback* m_dirtyFilesCallback; - ActorsWindow* mActorsWindow; - ActorPropertiesWindow* mActorPropsWindow; + ActorsWindow* m_actorsWindow; + ActorPropertiesWindow* m_actorPropsWindow; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/PlaybackOptionsGroup.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/PlaybackOptionsGroup.cpp index 14e2c79b88..4a5cc3f3d5 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/PlaybackOptionsGroup.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/PlaybackOptionsGroup.cpp @@ -108,18 +108,18 @@ namespace EMStudio continue; } - EMotionFX::Motion* motion = entry->mMotion; + EMotionFX::Motion* motion = entry->m_motion; const EMotionFX::PlayBackInfo* defaultPlayBackInfo = motion->GetDefaultPlayBackInfo(); - m_loopForeverAction->setChecked(defaultPlayBackInfo->mNumLoops == EMFX_LOOPFOREVER); - m_mirrorAction->setChecked(defaultPlayBackInfo->mMirrorMotion); - m_inPlaceAction->setChecked(defaultPlayBackInfo->mInPlace); - m_retargetAction->setChecked(defaultPlayBackInfo->mRetarget); + m_loopForeverAction->setChecked(defaultPlayBackInfo->m_numLoops == EMFX_LOOPFOREVER); + m_mirrorAction->setChecked(defaultPlayBackInfo->m_mirrorMotion); + m_inPlaceAction->setChecked(defaultPlayBackInfo->m_inPlace); + m_retargetAction->setChecked(defaultPlayBackInfo->m_retarget); - const bool playBackward = (defaultPlayBackInfo->mPlayMode == EMotionFX::PLAYMODE_BACKWARD); + const bool playBackward = (defaultPlayBackInfo->m_playMode == EMotionFX::PLAYMODE_BACKWARD); m_backwardAction->setChecked(playBackward); - SetPlaySpeed(defaultPlayBackInfo->mPlaySpeed); + SetPlaySpeed(defaultPlayBackInfo->m_playSpeed); } } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeInfoWidget.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeInfoWidget.cpp index 3878f36885..defa8e4701 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeInfoWidget.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeInfoWidget.cpp @@ -23,20 +23,19 @@ namespace EMStudio { setObjectName("TimeInfoWidget"); - mPlugin = plugin; + m_plugin = plugin; // init font - mFont.setPixelSize(mShowOverwriteStartTime ? 22 : 18); - mOverwriteFont.setPixelSize(12); - //mFont.setBold( true ); + m_font.setPixelSize(m_showOverwriteStartTime ? 22 : 18); + m_overwriteFont.setPixelSize(12); - mOverwriteStartTime = 0; - mOverwriteEndTime = 0; - mOverwriteMode = false; + m_overwriteStartTime = 0; + m_overwriteEndTime = 0; + m_overwriteMode = false; // init brushes and pens - mPenText = QPen(QColor(200, 200, 200)); - mPenTextFocus = QPen(QColor(244, 156, 28)); + m_penText = QPen(QColor(200, 200, 200)); + m_penTextFocus = QPen(QColor(244, 156, 28)); setFocusPolicy(Qt::StrongFocus); } @@ -58,8 +57,8 @@ namespace EMStudio // set the overwrite time which will be displayed when the overwrite mode is active void TimeInfoWidget::SetOverwriteTime(double startTime, double endTime) { - mOverwriteStartTime = startTime; - mOverwriteEndTime = endTime; + m_overwriteStartTime = startTime; + m_overwriteEndTime = endTime; } @@ -75,91 +74,84 @@ namespace EMStudio QTextOption options; options.setAlignment(Qt::AlignCenter); - if (mPlugin->GetTrackDataWidget()->hasFocus()) + if (m_plugin->GetTrackDataWidget()->hasFocus()) { - painter.setPen(mPenTextFocus); + painter.setPen(m_penTextFocus); } else { - painter.setPen(mPenText); + painter.setPen(m_penText); } - painter.setFont(mFont); - - // use the time of the plugin in case we are not in overwrite mode, if we are use the overwrite time - //uint32 usedTime = mPlugin->mCurTimeX; - //if (mOverwriteMode) - // usedTime = mOverwriteTime; + painter.setFont(m_font); // calculate the time values for this pixel uint32 minutes; uint32 seconds; uint32 milSecs; uint32 frameNumber; - // mPlugin->CalcTime(mPlugin->mCurTimeX/mPlugin->mTimeScale, nullptr, &minutes, &seconds, &milSecs, &frameNumber, false); - mPlugin->DecomposeTime(mPlugin->mCurTime, &minutes, &seconds, &milSecs, &frameNumber); - mCurTimeString = AZStd::string::format("%.2d:%.2d:%.2d", minutes, seconds, milSecs); + m_plugin->DecomposeTime(m_plugin->m_curTime, &minutes, &seconds, &milSecs, &frameNumber); + m_curTimeString = AZStd::string::format("%.2d:%.2d:%.2d", minutes, seconds, milSecs); QRect upperTextRect = event->rect(); - if (mShowOverwriteStartTime) + if (m_showOverwriteStartTime) { upperTextRect.setTop(upperTextRect.top() + 1); upperTextRect.setHeight(upperTextRect.height() - 17); } else { - mPlugin->DecomposeTime(mOverwriteEndTime, &minutes, &seconds, &milSecs, &frameNumber); - mCurTimeString += AZStd::string::format(" / %.2d:%.2d:%.2d", minutes, seconds, milSecs); + m_plugin->DecomposeTime(m_overwriteEndTime, &minutes, &seconds, &milSecs, &frameNumber); + m_curTimeString += AZStd::string::format(" / %.2d:%.2d:%.2d", minutes, seconds, milSecs); } - painter.drawText(upperTextRect, mCurTimeString.c_str(), options); + painter.drawText(upperTextRect, m_curTimeString.c_str(), options); - if (!mShowOverwriteStartTime) + if (!m_showOverwriteStartTime) { return; } - if (mOverwriteStartTime < 0) + if (m_overwriteStartTime < 0) { - mOverwriteStartTime = 0; + m_overwriteStartTime = 0; } - if (mOverwriteEndTime < 0) + if (m_overwriteEndTime < 0) { - mOverwriteEndTime = 0; + m_overwriteEndTime = 0; } // calculate the time values for the overwrite time uint32 minutesStart, minutesEnd; uint32 secondsStart, secondsEnd; uint32 milSecsStart, milSecsEnd; - mPlugin->DecomposeTime(mOverwriteStartTime, &minutesStart, &secondsStart, &milSecsStart, &frameNumber); - mPlugin->DecomposeTime(mOverwriteEndTime, &minutesEnd, &secondsEnd, &milSecsEnd, &frameNumber); + m_plugin->DecomposeTime(m_overwriteStartTime, &minutesStart, &secondsStart, &milSecsStart, &frameNumber); + m_plugin->DecomposeTime(m_overwriteEndTime, &minutesEnd, &secondsEnd, &milSecsEnd, &frameNumber); // use the duration of the motion or recording if (minutesStart == minutesEnd && secondsStart == secondsEnd && milSecsStart == milSecsEnd) { - //mOverwriteTimeString = AZStd::string::format("%.2d:%.2d:%.2d", minutesStart, secondsStart, milSecsStart); uint32 dummyFrame; double duration; - mPlugin->GetDataTimes(&duration, nullptr, nullptr); - mPlugin->DecomposeTime(duration, &minutesEnd, &secondsEnd, &milSecsEnd, &dummyFrame); + m_plugin->GetDataTimes(&duration, nullptr, nullptr); + m_plugin->DecomposeTime(duration, &minutesEnd, &secondsEnd, &milSecsEnd, &dummyFrame); } - mOverwriteTimeString = AZStd::string::format("%.2d:%.2d:%.2d / %.2d:%.2d:%.2d", minutesStart, secondsStart, milSecsStart, minutesEnd, secondsEnd, milSecsEnd); + m_overwriteTimeString = AZStd::string::format("%.2d:%.2d:%.2d / %.2d:%.2d:%.2d", minutesStart, secondsStart, milSecsStart, minutesEnd, secondsEnd, milSecsEnd); QRect lowerTextRect = event->rect(); lowerTextRect.setTop(upperTextRect.height()); - painter.setFont(mOverwriteFont); - painter.drawText(lowerTextRect, mOverwriteTimeString.c_str(), options); + painter.setFont(m_overwriteFont); + painter.drawText(lowerTextRect, m_overwriteTimeString.c_str(), options); } // propagate key events to the plugin and let it handle by a shared function void TimeInfoWidget::keyPressEvent(QKeyEvent* event) { - if (mPlugin) + if (m_plugin) { - mPlugin->OnKeyPressEvent(event); + m_plugin->OnKeyPressEvent(event); } } @@ -167,9 +159,9 @@ namespace EMStudio // propagate key events to the plugin and let it handle by a shared function void TimeInfoWidget::keyReleaseEvent(QKeyEvent* event) { - if (mPlugin) + if (m_plugin) { - mPlugin->OnKeyReleaseEvent(event); + m_plugin->OnKeyReleaseEvent(event); } } } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeInfoWidget.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeInfoWidget.h index 3c1146ed5b..bc9ac258eb 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeInfoWidget.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeInfoWidget.h @@ -36,8 +36,8 @@ namespace EMStudio TimeInfoWidget(TimeViewPlugin* plugin, QWidget* parent = nullptr); ~TimeInfoWidget(); - bool GetIsOverwriteMode() { return mOverwriteMode; } - void SetIsOverwriteMode(bool active) { mOverwriteMode = active; } + bool GetIsOverwriteMode() { return m_overwriteMode; } + void SetIsOverwriteMode(bool active) { m_overwriteMode = active; } void SetOverwriteTime(double startTime, double endTime); protected: @@ -45,18 +45,18 @@ namespace EMStudio QSize sizeHint() const; private: - QFont mFont; - QFont mOverwriteFont; - QBrush mBrushBackground; - QPen mPenText; - QPen mPenTextFocus; - AZStd::string mCurTimeString; - AZStd::string mOverwriteTimeString; - TimeViewPlugin* mPlugin; - double mOverwriteStartTime; - double mOverwriteEndTime; - bool mOverwriteMode; - bool mShowOverwriteStartTime = false; + QFont m_font; + QFont m_overwriteFont; + QBrush m_brushBackground; + QPen m_penText; + QPen m_penTextFocus; + AZStd::string m_curTimeString; + AZStd::string m_overwriteTimeString; + TimeViewPlugin* m_plugin; + double m_overwriteStartTime; + double m_overwriteEndTime; + bool m_overwriteMode; + bool m_showOverwriteStartTime = false; void keyPressEvent(QKeyEvent* event); void keyReleaseEvent(QKeyEvent* event); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeTrack.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeTrack.cpp index c1c440d0d8..550e95eeef 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeTrack.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeTrack.cpp @@ -19,24 +19,22 @@ namespace EMStudio // the constructor TimeTrack::TimeTrack(TimeViewPlugin* plugin) { - mPlugin = plugin; - mHeight = 20; - mStartY = 0; - mEnabled = false; - mIsHighlighted = false; - mVisible = false; - mDeletable = true; + m_plugin = plugin; + m_height = 20; + m_startY = 0; + m_enabled = false; + m_isHighlighted = false; + m_visible = false; + m_deletable = true; // init font - mFont.setPixelSize(14); - //mFont.setBold( true ); + m_font.setPixelSize(14); // init brushes and pens - mBrushDataBG = QColor(60, 65, 70); - //mBrushDataBG = QColor(50, 50, 50); - mBrushDataDisabledBG = QColor(50, 50, 50);// use the same color //QBrush( QColor(33, 33, 33) ); - mBrushHeaderBG = QBrush(QColor(30, 30, 30)); - mPenText = QPen(QColor(255, 255, 255)); + m_brushDataBg = QColor(60, 65, 70); + m_brushDataDisabledBg = QColor(50, 50, 50);// use the same color //QBrush( QColor(33, 33, 33) ); + m_brushHeaderBg = QBrush(QColor(30, 30, 30)); + m_penText = QPen(QColor(255, 255, 255)); } @@ -52,14 +50,14 @@ namespace EMStudio { MCORE_UNUSED(width); - if (mVisible == false) + if (m_visible == false) { return; } - int32 animEndPixel = aznumeric_cast(mPlugin->TimeToPixel(animationLength)); - int32 clipStartPixel = aznumeric_cast(mPlugin->TimeToPixel(clipStartTime)); - int32 clipEndPixel = aznumeric_cast(mPlugin->TimeToPixel(clipEndTime)); + int32 animEndPixel = aznumeric_cast(m_plugin->TimeToPixel(animationLength)); + int32 clipStartPixel = aznumeric_cast(m_plugin->TimeToPixel(clipStartTime)); + int32 clipEndPixel = aznumeric_cast(m_plugin->TimeToPixel(clipEndTime)); // fill the background uint32 height = GetHeight(); @@ -68,17 +66,17 @@ namespace EMStudio QRect clipStartRect(0, startY, clipStartPixel, height); QRect clipEndRect(clipEndPixel, startY, animEndPixel - clipEndPixel, height); - QColor disabledBGColor = mBrushDataDisabledBG; - QColor bgColor = mBrushDataBG; + QColor disabledBGColor = m_brushDataDisabledBg; + QColor bgColor = m_brushDataBg; // make the colors a bit lighter so that we see some highlighting effect - if (mIsHighlighted) + if (m_isHighlighted) { disabledBGColor = disabledBGColor.lighter(120); bgColor = bgColor.lighter(120); } - if (mEnabled) + if (m_enabled) { painter.setPen(Qt::NoPen); painter.setBrush(disabledBGColor); @@ -105,10 +103,10 @@ namespace EMStudio // render all elements //uint32 numRenderedElements = 0; - const size_t numElems = mElements.size(); + const size_t numElems = m_elements.size(); for (size_t i = 0; i < numElems; ++i) { - TimeTrackElement* element = mElements[i]; + TimeTrackElement* element = m_elements[i]; // skip rendering the element in case it is not inside the visible area in the widget if (element->GetEndTime() < startTime || @@ -117,7 +115,7 @@ namespace EMStudio continue; } - bool enabled = mEnabled; + bool enabled = m_enabled; // make sure we render the motion event as disabled as soon as it is in the clipped area if (element->GetEndTime() < clipStartTime || @@ -137,7 +135,7 @@ namespace EMStudio // render the track header void TimeTrack::RenderHeader(QPainter& painter, uint32 width, int32 startY) { - if (mVisible == false) + if (m_visible == false) { return; } @@ -147,14 +145,14 @@ namespace EMStudio QRect rect(0, startY, width, height); painter.setPen(Qt::NoPen); - painter.setBrush(mBrushHeaderBG); + painter.setBrush(m_brushHeaderBg); painter.drawRect(rect); // render the name QTextOption options; options.setAlignment(Qt::AlignCenter); - painter.setPen(mPenText); - painter.drawText(rect, mName.c_str(), options); + painter.setPen(m_penText); + painter.drawText(rect, m_name.c_str(), options); } @@ -163,26 +161,26 @@ namespace EMStudio { if (delFromMem) { - for (TimeTrackElement* element : mElements) + for (TimeTrackElement* element : m_elements) { delete element; } } - mElements.clear(); + m_elements.clear(); } // get the track element at a given pixel TimeTrackElement* TimeTrack::GetElementAt(int32 x, int32 y) const { - if (mVisible == false) + if (m_visible == false) { return nullptr; } // for all elements - for (TimeTrackElement* element : mElements) + for (TimeTrackElement* element : m_elements) { // check if its inside if (element->GetIsVisible() == false) @@ -203,12 +201,12 @@ namespace EMStudio // calculate the number of selected elements size_t TimeTrack::CalcNumSelectedElements() const { - if (mVisible == false) + if (m_visible == false) { return 0; } - return AZStd::accumulate(begin(mElements), end(mElements), size_t{0}, [](size_t total, const TimeTrackElement* element) + return AZStd::accumulate(begin(m_elements), end(m_elements), size_t{0}, [](size_t total, const TimeTrackElement* element) { return total + element->GetIsSelected(); }); @@ -218,16 +216,16 @@ namespace EMStudio // find and return the first of the selected elements TimeTrackElement* TimeTrack::GetFirstSelectedElement() const { - if (mVisible == false) + if (m_visible == false) { return nullptr; } - const auto foundElement = AZStd::find_if(begin(mElements), end(mElements), [](const TimeTrackElement* element) + const auto foundElement = AZStd::find_if(begin(m_elements), end(m_elements), [](const TimeTrackElement* element) { return element->GetIsSelected(); }); - return foundElement != end(mElements) ? *foundElement : nullptr; + return foundElement != end(m_elements) ? *foundElement : nullptr; } @@ -239,11 +237,11 @@ namespace EMStudio const size_t endNr = AZStd::max(elementStartNr, elementEndNr); // get the number of elements and iterate through them - const size_t numElems = mElements.size(); + const size_t numElems = m_elements.size(); for (size_t i = 0; i < numElems; ++i) { const size_t elementNr = i; - TimeTrackElement* element = mElements[i]; + TimeTrackElement* element = m_elements[i]; // check if the current element is in range if (elementNr >= startNr && elementNr <= endNr) @@ -262,7 +260,7 @@ namespace EMStudio void TimeTrack::SelectElementsInRect(const QRect& rect, bool overwriteCurSelection, bool select, bool toggleMode) { // get the number of elements and iterate through them - for (TimeTrackElement* element : mElements) + for (TimeTrackElement* element : m_elements) { // get the current element and the corresponding rect QRect elementRect = element->CalcRect(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeTrack.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeTrack.h index 55dcae73c3..2d6023844c 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeTrack.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeTrack.h @@ -37,20 +37,20 @@ namespace EMStudio TimeTrack(TimeViewPlugin* plugin); ~TimeTrack(); - void SetHeight(uint32 height) { mHeight = height; } - MCORE_INLINE uint32 GetHeight() const { return mHeight; } + void SetHeight(uint32 height) { m_height = height; } + MCORE_INLINE uint32 GetHeight() const { return m_height; } void RenderHeader(QPainter& painter, uint32 width, int32 startY); // @param startTime The time in seconds of the left border of the visible area in the widget. void RenderData(QPainter& painter, uint32 width, int32 startY, double startTime, double endTime, double animationLength, double clipStartTime, double clipEndTime); - MCORE_INLINE size_t GetNumElements() const { return mElements.size(); } - MCORE_INLINE TimeTrackElement* GetElement(size_t index) const { return mElements[index]; } - void AddElement(TimeTrackElement* elem) { elem->SetTrack(this); mElements.push_back(elem); } + MCORE_INLINE size_t GetNumElements() const { return m_elements.size(); } + MCORE_INLINE TimeTrackElement* GetElement(size_t index) const { return m_elements[index]; } + void AddElement(TimeTrackElement* elem) { elem->SetTrack(this); m_elements.push_back(elem); } void RemoveElement(TimeTrackElement* elem, bool delFromMem = true) { - mElements.erase(AZStd::remove(mElements.begin(), mElements.end(), elem), mElements.end()); + m_elements.erase(AZStd::remove(m_elements.begin(), m_elements.end(), elem), m_elements.end()); if (delFromMem) { delete elem; @@ -60,14 +60,14 @@ namespace EMStudio { if (delFromMem) { - delete mElements[index]; + delete m_elements[index]; } - mElements.erase(mElements.begin() + index); + m_elements.erase(m_elements.begin() + index); } void RemoveAllElements(bool delFromMem = true); void SetElementCount(size_t count) { - mElements.resize(count); + m_elements.resize(count); } size_t CalcNumSelectedElements() const; @@ -75,42 +75,42 @@ namespace EMStudio void RangeSelectElements(size_t elementStartNr, size_t elementEndNr); void SelectElementsInRect(const QRect& rect, bool overwriteCurSelection, bool select, bool toggleMode); - MCORE_INLINE TimeViewPlugin* GetPlugin() { return mPlugin; } - MCORE_INLINE void SetStartY(uint32 y) { mStartY = y; } - MCORE_INLINE uint32 GetStartY() const { return mStartY; } - bool GetIsInside(uint32 y) const { return (y >= mStartY) && (y <= (mStartY + mHeight)); } + MCORE_INLINE TimeViewPlugin* GetPlugin() { return m_plugin; } + MCORE_INLINE void SetStartY(uint32 y) { m_startY = y; } + MCORE_INLINE uint32 GetStartY() const { return m_startY; } + bool GetIsInside(uint32 y) const { return (y >= m_startY) && (y <= (m_startY + m_height)); } - void SetName(const char* name) { mName = name; } - const char* GetName() const { return mName.c_str(); } + void SetName(const char* name) { m_name = name; } + const char* GetName() const { return m_name.c_str(); } - bool GetIsEnabled() const { return mEnabled; } - void SetIsEnabled(bool enabled) { mEnabled = enabled; } + bool GetIsEnabled() const { return m_enabled; } + void SetIsEnabled(bool enabled) { m_enabled = enabled; } - bool GetIsDeletable() const { return mDeletable; } - void SetIsDeletable(bool isDeletable) { mDeletable = isDeletable; } + bool GetIsDeletable() const { return m_deletable; } + void SetIsDeletable(bool isDeletable) { m_deletable = isDeletable; } - bool GetIsVisible() const { return mVisible; } - void SetIsVisible(bool visible) { mVisible = visible; } + bool GetIsVisible() const { return m_visible; } + void SetIsVisible(bool visible) { m_visible = visible; } - MCORE_INLINE bool GetIsHighlighted() const { return mIsHighlighted; } - MCORE_INLINE void SetIsHighlighted(bool enabled) { mIsHighlighted = enabled; } + MCORE_INLINE bool GetIsHighlighted() const { return m_isHighlighted; } + MCORE_INLINE void SetIsHighlighted(bool enabled) { m_isHighlighted = enabled; } TimeTrackElement* GetElementAt(int32 x, int32 y) const; protected: - AZStd::string mName; - uint32 mHeight; - uint32 mStartY; - QFont mFont; - QBrush mBrushHeaderBG; - QColor mBrushDataBG; - QColor mBrushDataDisabledBG; - QPen mPenText; - TimeViewPlugin* mPlugin; - AZStd::vector mElements; - bool mEnabled; - bool mVisible; - bool mDeletable; - bool mIsHighlighted; + AZStd::string m_name; + uint32 m_height; + uint32 m_startY; + QFont m_font; + QBrush m_brushHeaderBg; + QColor m_brushDataBg; + QColor m_brushDataDisabledBg; + QPen m_penText; + TimeViewPlugin* m_plugin; + AZStd::vector m_elements; + bool m_enabled; + bool m_visible; + bool m_deletable; + bool m_isHighlighted; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeTrackElement.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeTrackElement.cpp index 78e911eb0a..5bb6d842fc 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeTrackElement.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeTrackElement.cpp @@ -21,27 +21,27 @@ namespace EMStudio { // statics - QColor TimeTrackElement::mTextColor = QColor(30, 30, 30); - QColor TimeTrackElement::mHighlightedTextColor = QColor(0, 0, 0); - QColor TimeTrackElement::mHighlightedColor = QColor(255, 128, 0); - int32 TimeTrackElement::mTickHalfWidth = 7; + QColor TimeTrackElement::s_textColor = QColor(30, 30, 30); + QColor TimeTrackElement::s_highlightedTextColor = QColor(0, 0, 0); + QColor TimeTrackElement::s_highlightedColor = QColor(255, 128, 0); + int32 TimeTrackElement::s_tickHalfWidth = 7; // constructor TimeTrackElement::TimeTrackElement(const char* name, TimeTrack* timeTrack, size_t elementNumber, QColor color) { - mTrack = timeTrack; - mName = name; - mIsSelected = false; - mShowTimeHandles = false; - mIsHighlighted = false; - mStartTime = 0.0; - mEndTime = 0.0; - mColor = color; - mElementNumber = elementNumber; - mIsCut = false; + m_track = timeTrack; + m_name = name; + m_isSelected = false; + m_showTimeHandles = false; + m_isHighlighted = false; + m_startTime = 0.0; + m_endTime = 0.0; + m_color = color; + m_elementNumber = elementNumber; + m_isCut = false; // init font - mFont.setPixelSize(10); + m_font.setPixelSize(10); } @@ -54,13 +54,13 @@ namespace EMStudio // calculate the dimensions in pixels void TimeTrackElement::CalcDimensions(int32* outStartX, int32* outStartY, int32* outWidth, int32* outHeight) const { - TimeViewPlugin* plugin = mTrack->GetPlugin(); + TimeViewPlugin* plugin = m_track->GetPlugin(); - *outStartX = aznumeric_cast(plugin->TimeToPixel(mStartTime)); - int32 endX = aznumeric_cast(plugin->TimeToPixel(mEndTime)); - *outStartY = mTrack->GetStartY() + 1; + *outStartX = aznumeric_cast(plugin->TimeToPixel(m_startTime)); + int32 endX = aznumeric_cast(plugin->TimeToPixel(m_endTime)); + *outStartY = m_track->GetStartY() + 1; *outWidth = (endX - *outStartX); - *outHeight = mTrack->GetHeight() - 1; + *outHeight = m_track->GetHeight() - 1; } @@ -92,14 +92,14 @@ namespace EMStudio // create the rect QRect rect(startX, startY, width + 1, height); - QColor color = mColor; + QColor color = m_color; QColor borderColor(30, 30, 30); - QColor textColor = mTextColor; - if (mIsSelected) + QColor textColor = s_textColor; + if (m_isSelected) { - color = mHighlightedColor; - borderColor = mHighlightedColor; - textColor = mHighlightedTextColor; + color = s_highlightedColor; + borderColor = s_highlightedColor; + textColor = s_highlightedTextColor; } // in case the track is disabled @@ -111,14 +111,14 @@ namespace EMStudio } // make the colors a bit lighter so that we see some highlighting effect - if (mIsHighlighted) + if (m_isHighlighted) { borderColor = borderColor.lighter(130); color = color.lighter(130); } // in case the track is cutted - if (mIsCut) + if (m_isCut) { borderColor.setAlpha(90); color.setAlpha(90); @@ -149,32 +149,32 @@ namespace EMStudio options.setAlignment(Qt::AlignCenter); painter.setPen(textColor); - painter.setFont(mFont); + painter.setFont(m_font); painter.setRenderHint(QPainter::Antialiasing); - painter.drawText(rect, mName, options); + painter.drawText(rect, m_name, options); painter.setRenderHint(QPainter::Antialiasing, false); } else { height--; - mTickPoints[0] = QPoint(startX, startY); - mTickPoints[1] = QPoint(startX + mTickHalfWidth, startY + height / 2); - mTickPoints[2] = QPoint(startX + mTickHalfWidth, startY + height); - mTickPoints[3] = QPoint(startX - mTickHalfWidth, startY + height); - mTickPoints[4] = QPoint(startX - mTickHalfWidth, startY + height / 2); - mTickPoints[5] = QPoint(startX, startY); + m_tickPoints[0] = QPoint(startX, startY); + m_tickPoints[1] = QPoint(startX + s_tickHalfWidth, startY + height / 2); + m_tickPoints[2] = QPoint(startX + s_tickHalfWidth, startY + height); + m_tickPoints[3] = QPoint(startX - s_tickHalfWidth, startY + height); + m_tickPoints[4] = QPoint(startX - s_tickHalfWidth, startY + height / 2); + m_tickPoints[5] = QPoint(startX, startY); painter.setPen(Qt::NoPen); painter.setBrush(gradient); //painter.setBrush( color ); painter.setRenderHint(QPainter::Antialiasing); - painter.drawPolygon(mTickPoints, 5, Qt::WindingFill); + painter.drawPolygon(m_tickPoints, 5, Qt::WindingFill); painter.setRenderHint(QPainter::Antialiasing, false); painter.setBrush(Qt::NoBrush); painter.setPen(borderColor); painter.setRenderHint(QPainter::Antialiasing); - painter.drawPolyline(mTickPoints, 6); + painter.drawPolyline(m_tickPoints, 6); painter.setRenderHint(QPainter::Antialiasing, false); } } @@ -195,12 +195,12 @@ namespace EMStudio bool isTickElement = width < 1 ? true : false; if (isTickElement) { - startX -= mTickHalfWidth; - width += 2 * mTickHalfWidth; + startX -= s_tickHalfWidth; + width += 2 * s_tickHalfWidth; } // take scrolling into account - startX = aznumeric_cast(startX + mTrack->GetPlugin()->GetScrollX()); + startX = aznumeric_cast(startX + m_track->GetPlugin()->GetScrollX()); // check if we're inside the area of the element if (MCore::InRange(x, startX, startX + width) && MCore::InRange(y, startY, startY + height)) @@ -252,15 +252,15 @@ namespace EMStudio void TimeTrackElement::MoveRelative(double timeDelta) { // don't allow it to start before zero - if (mStartTime + timeDelta < 0.0) + if (m_startTime + timeDelta < 0.0) { - mStartTime -= mStartTime; - mEndTime -= mStartTime; + m_startTime -= m_startTime; + m_endTime -= m_startTime; } else { - mStartTime += timeDelta; - mEndTime += timeDelta; + m_startTime += timeDelta; + m_endTime += timeDelta; } } @@ -280,8 +280,8 @@ namespace EMStudio bool isTickElement = width < 1 ? true : false; if (isTickElement) { - startX -= mTickHalfWidth; - width += 2 * mTickHalfWidth; + startX -= s_tickHalfWidth; + width += 2 * s_tickHalfWidth; } int32 endX = startX + width; @@ -310,14 +310,14 @@ namespace EMStudio // resize the start point case RESIZEPOINT_START: { - double newStartTime = mStartTime + timeDelta; - mTrack->GetPlugin()->SnapTime(&newStartTime, this, snapThreshold); - mStartTime = newStartTime; + double newStartTime = m_startTime + timeDelta; + m_track->GetPlugin()->SnapTime(&newStartTime, this, snapThreshold); + m_startTime = newStartTime; - if (newStartTime > mEndTime) + if (newStartTime > m_endTime) { - mStartTime = mEndTime; - mEndTime = newStartTime; + m_startTime = m_endTime; + m_endTime = newStartTime; return RESIZEPOINT_END; } @@ -328,14 +328,14 @@ namespace EMStudio // resize the end point case RESIZEPOINT_END: { - double newEndTime = mEndTime + timeDelta; - mTrack->GetPlugin()->SnapTime(&newEndTime, this, snapThreshold); - mEndTime = newEndTime; + double newEndTime = m_endTime + timeDelta; + m_track->GetPlugin()->SnapTime(&newEndTime, this, snapThreshold); + m_endTime = newEndTime; - if (newEndTime < mStartTime) + if (newEndTime < m_startTime) { - mEndTime = mStartTime; - mStartTime = newEndTime; + m_endTime = m_startTime; + m_startTime = newEndTime; return RESIZEPOINT_START; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeTrackElement.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeTrackElement.h index 1e0d38486b..2bc4c5187b 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeTrackElement.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeTrackElement.h @@ -38,25 +38,25 @@ namespace EMStudio TimeTrackElement(const char* name, TimeTrack* timeTrack, size_t elementNumber = InvalidIndex, QColor color = QColor(0, 0, 0)); virtual ~TimeTrackElement(); - MCORE_INLINE double GetStartTime() const { return mStartTime; } - MCORE_INLINE double GetEndTime() const { return mEndTime; } - MCORE_INLINE bool GetIsSelected() const { return mIsSelected; } - MCORE_INLINE TimeTrack* GetTrack() { return mTrack; } - MCORE_INLINE size_t GetElementNumber() const { return mElementNumber; } - QColor GetColor() const { return mColor; } + MCORE_INLINE double GetStartTime() const { return m_startTime; } + MCORE_INLINE double GetEndTime() const { return m_endTime; } + MCORE_INLINE bool GetIsSelected() const { return m_isSelected; } + MCORE_INLINE TimeTrack* GetTrack() { return m_track; } + MCORE_INLINE size_t GetElementNumber() const { return m_elementNumber; } + QColor GetColor() const { return m_color; } - void SetIsSelected(bool selected) { mIsSelected = selected; } - void SetStartTime(double startTime) { mStartTime = startTime; } - void SetEndTime(double endTime) { mEndTime = endTime; } - void SetName(const char* name) { mName = name; } - void SetToolTip(const char* toolTip) { mToolTip = toolTip; } - void SetTrack(TimeTrack* track) { mTrack = track; } - void SetElementNumber(size_t elementNumber) { mElementNumber = elementNumber; } - void SetColor(QColor color) { mColor = color; } + void SetIsSelected(bool selected) { m_isSelected = selected; } + void SetStartTime(double startTime) { m_startTime = startTime; } + void SetEndTime(double endTime) { m_endTime = endTime; } + void SetName(const char* name) { m_name = name; } + void SetToolTip(const char* toolTip) { m_toolTip = toolTip; } + void SetTrack(TimeTrack* track) { m_track = track; } + void SetElementNumber(size_t elementNumber) { m_elementNumber = elementNumber; } + void SetColor(QColor color) { m_color = color; } - const QString& GetName() const { return mName; } - const QString& GetToolTip() const { return mToolTip; } - const QFont& GetFont() const { return mFont; } + const QString& GetName() const { return m_name; } + const QString& GetToolTip() const { return m_toolTip; } + const QFont& GetFont() const { return m_font; } virtual void Render(QPainter& painter, bool isTrackEnabled); virtual bool SnapTime(double* inOutTime, double snapTreshold) const; @@ -68,42 +68,42 @@ namespace EMStudio void CalcDimensions(int32* outStartX, int32* outStartY, int32* outWidth, int32* outHeight) const; QRect CalcRect(); - bool GetShowTimeHandles() const { return mShowTimeHandles; } - void SetShowTimeHandles(bool show) { mShowTimeHandles = show; } - void SetShowToolTip(bool show) { mShowToolTip = show; } - bool GetShowToolTip() const { return mShowToolTip; } + bool GetShowTimeHandles() const { return m_showTimeHandles; } + void SetShowTimeHandles(bool show) { m_showTimeHandles = show; } + void SetShowToolTip(bool show) { m_showToolTip = show; } + bool GetShowToolTip() const { return m_showToolTip; } - bool GetIsVisible() const { return mVisible; } - void SetIsVisible(bool visible) { mVisible = visible; } + bool GetIsVisible() const { return m_visible; } + void SetIsVisible(bool visible) { m_visible = visible; } - bool GetIsCut() const { return mIsCut; } - void SetIsCut(bool cut) { mIsCut = cut; } + bool GetIsCut() const { return m_isCut; } + void SetIsCut(bool cut) { m_isCut = cut; } - MCORE_INLINE bool GetIsHighlighted() const { return mIsHighlighted; } - MCORE_INLINE void SetIsHighlighted(bool enabled) { mIsHighlighted = enabled; } + MCORE_INLINE bool GetIsHighlighted() const { return m_isHighlighted; } + MCORE_INLINE void SetIsHighlighted(bool enabled) { m_isHighlighted = enabled; } protected: - QFont mFont; - QBrush mBrush; - TimeTrack* mTrack; - double mStartTime; - double mEndTime; - QString mName; - QString mToolTip; - QColor mColor; - size_t mElementNumber; - QPoint mTickPoints[6]; + QFont m_font; + QBrush m_brush; + TimeTrack* m_track; + double m_startTime; + double m_endTime; + QString m_name; + QString m_toolTip; + QColor m_color; + size_t m_elementNumber; + QPoint m_tickPoints[6]; - bool mVisible; - bool mIsCut; - bool mIsSelected; - bool mShowTimeHandles; - bool mShowToolTip; - bool mIsHighlighted; + bool m_visible; + bool m_isCut; + bool m_isSelected; + bool m_showTimeHandles; + bool m_showToolTip; + bool m_isHighlighted; - static QColor mHighlightedColor; - static QColor mTextColor; - static QColor mHighlightedTextColor; - static int32 mTickHalfWidth; + static QColor s_highlightedColor; + static QColor s_textColor; + static QColor s_highlightedTextColor; + static int32 s_tickHalfWidth; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeViewPlugin.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeViewPlugin.cpp index 6f8ab95891..a87b7066b5 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeViewPlugin.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeViewPlugin.cpp @@ -47,46 +47,46 @@ namespace EMStudio TimeViewPlugin::TimeViewPlugin() : EMStudio::DockWidgetPlugin() { - mPixelsPerSecond = 60; - mCurTime = 0; - mFPS = 32; - mTimeScale = 1.0; - mTargetTimeScale = 1.0; - mScrollX = 0.0; - mTargetScrollX = 0.0; - mMaxTime = 0.0; - mMaxHeight = 0.0; - mMinScale = 0.25; - mMaxScale = 100.0; - mCurMouseX = 0; - mCurMouseY = 0; - mTotalTime = FLT_MAX; - mZoomInCursor = nullptr; - mZoomOutCursor = nullptr; - mIsAnimating = false; - mDirty = true; + m_pixelsPerSecond = 60; + m_curTime = 0; + m_fps = 32; + m_timeScale = 1.0; + m_targetTimeScale = 1.0; + m_scrollX = 0.0; + m_targetScrollX = 0.0; + m_maxTime = 0.0; + m_maxHeight = 0.0; + m_minScale = 0.25; + m_maxScale = 100.0; + m_curMouseX = 0; + m_curMouseY = 0; + m_totalTime = FLT_MAX; + m_zoomInCursor = nullptr; + m_zoomOutCursor = nullptr; + m_isAnimating = false; + m_dirty = true; - mTrackDataHeaderWidget = nullptr; - mTrackDataWidget = nullptr; - mTrackHeaderWidget = nullptr; - mTimeInfoWidget = nullptr; + m_trackDataHeaderWidget = nullptr; + m_trackDataWidget = nullptr; + m_trackHeaderWidget = nullptr; + m_timeInfoWidget = nullptr; - mNodeHistoryItem = nullptr; - mEventHistoryItem = nullptr; - mActorInstanceData = nullptr; - mEventEmitterNode = nullptr; + m_nodeHistoryItem = nullptr; + m_eventHistoryItem = nullptr; + m_actorInstanceData = nullptr; + m_eventEmitterNode = nullptr; - mMainWidget = nullptr; - mMotionWindowPlugin = nullptr; - mMotionEventsPlugin = nullptr; - mMotionListWindow = nullptr; + m_mainWidget = nullptr; + m_motionWindowPlugin = nullptr; + m_motionEventsPlugin = nullptr; + m_motionListWindow = nullptr; m_motionSetPlugin = nullptr; - mMotion = nullptr; + m_motion = nullptr; - mBrushCurTimeHandle = QBrush(QColor(255, 180, 0)); - mPenCurTimeHandle = QPen(QColor(255, 180, 0)); - mPenTimeHandles = QPen(QColor(150, 150, 150), 1, Qt::DotLine); - mPenCurTimeHelper = QPen(QColor(100, 100, 100), 1, Qt::DotLine); + m_brushCurTimeHandle = QBrush(QColor(255, 180, 0)); + m_penCurTimeHandle = QPen(QColor(255, 180, 0)); + m_penTimeHandles = QPen(QColor(150, 150, 150), 1, Qt::DotLine); + m_penCurTimeHelper = QPen(QColor(100, 100, 100), 1, Qt::DotLine); } TimeViewPlugin::~TimeViewPlugin() @@ -103,11 +103,11 @@ namespace EMStudio RemoveAllTracks(); // get rid of the cursors - delete mZoomInCursor; - delete mZoomOutCursor; + delete m_zoomInCursor; + delete m_zoomOutCursor; // get rid of the motion infos - for (MotionInfo* motionInfo : mMotionInfos) + for (MotionInfo* motionInfo : m_motionInfos) { delete motionInfo; } @@ -162,12 +162,12 @@ namespace EMStudio { if (classID == MotionWindowPlugin::CLASS_ID) { - mMotionWindowPlugin = nullptr; + m_motionWindowPlugin = nullptr; } if (classID == MotionEventsPlugin::CLASS_ID) { - mMotionEventsPlugin = nullptr; + m_motionEventsPlugin = nullptr; } } @@ -196,37 +196,37 @@ namespace EMStudio GetCommandManager()->RegisterCommandCallback("PlayMotion", m_commandCallbacks.back()); // load the cursors - mZoomInCursor = new QCursor(QPixmap(QDir{ QString(MysticQt::GetDataDir().c_str()) }.filePath("Images/Rendering/ZoomInCursor.png")).scaled(32, 32)); - mZoomOutCursor = new QCursor(QPixmap(QDir{ QString(MysticQt::GetDataDir().c_str()) }.filePath("Images/Rendering/ZoomOutCursor.png")).scaled(32, 32)); + m_zoomInCursor = new QCursor(QPixmap(QDir{ QString(MysticQt::GetDataDir().c_str()) }.filePath("Images/Rendering/ZoomInCursor.png")).scaled(32, 32)); + m_zoomOutCursor = new QCursor(QPixmap(QDir{ QString(MysticQt::GetDataDir().c_str()) }.filePath("Images/Rendering/ZoomOutCursor.png")).scaled(32, 32)); // create main widget - mMainWidget = new QWidget(mDock); - mDock->setWidget(mMainWidget); + m_mainWidget = new QWidget(m_dock); + m_dock->setWidget(m_mainWidget); QGridLayout* mainLayout = new QGridLayout(); mainLayout->setMargin(0); mainLayout->setSpacing(0); - mMainWidget->setLayout(mainLayout); + m_mainWidget->setLayout(mainLayout); // create widgets in the header QHBoxLayout* topLayout = new QHBoxLayout(); // Top - mTimeViewToolBar = new TimeViewToolBar(this); + m_timeViewToolBar = new TimeViewToolBar(this); // Top-left - mTimeInfoWidget = new TimeInfoWidget(this); - mTimeInfoWidget->setFixedWidth(175); - topLayout->addWidget(mTimeInfoWidget); - topLayout->addWidget(mTimeViewToolBar); + m_timeInfoWidget = new TimeInfoWidget(this); + m_timeInfoWidget->setFixedWidth(175); + topLayout->addWidget(m_timeInfoWidget); + topLayout->addWidget(m_timeViewToolBar); mainLayout->addLayout(topLayout, 0, 0, 1, 2); // Top-right - mTrackDataHeaderWidget = new TrackDataHeaderWidget(this, mDock); - mTrackDataHeaderWidget->setFixedHeight(40); + m_trackDataHeaderWidget = new TrackDataHeaderWidget(this, m_dock); + m_trackDataHeaderWidget->setFixedHeight(40); // create widgets in the body. For the body we are going to put a scroll area // so we can get a vertical scroll bar when we have more tracks than what the // view can show - QScrollArea* bodyWidget = new QScrollArea(mMainWidget); + QScrollArea* bodyWidget = new QScrollArea(m_mainWidget); bodyWidget->setFrameShape(QFrame::NoFrame); bodyWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); bodyWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); @@ -242,39 +242,39 @@ namespace EMStudio mainLayout->addWidget(bodyWidget, 2, 0, 1, 2); // Bottom-left - mTrackHeaderWidget = new TrackHeaderWidget(this, mDock); - mTrackHeaderWidget->setFixedWidth(175); - bodyLayout->addWidget(mTrackHeaderWidget); + m_trackHeaderWidget = new TrackHeaderWidget(this, m_dock); + m_trackHeaderWidget->setFixedWidth(175); + bodyLayout->addWidget(m_trackHeaderWidget); // Left QHBoxLayout* addTrackAndTrackDataLayout = new QHBoxLayout; - addTrackAndTrackDataLayout->addWidget(mTrackHeaderWidget->GetAddTrackWidget()); - mTrackHeaderWidget->GetAddTrackWidget()->setFixedWidth(175); - addTrackAndTrackDataLayout->addWidget(mTrackDataHeaderWidget); + addTrackAndTrackDataLayout->addWidget(m_trackHeaderWidget->GetAddTrackWidget()); + m_trackHeaderWidget->GetAddTrackWidget()->setFixedWidth(175); + addTrackAndTrackDataLayout->addWidget(m_trackDataHeaderWidget); mainLayout->addLayout(addTrackAndTrackDataLayout, 1, 0, 1, 2); // bottom-right - mTrackDataWidget = new TrackDataWidget(this, mDock); - bodyLayout->addWidget(mTrackDataWidget); + m_trackDataWidget = new TrackDataWidget(this, m_dock); + bodyLayout->addWidget(m_trackDataWidget); - connect(mTrackDataWidget, &TrackDataWidget::SelectionChanged, this, &TimeViewPlugin::OnSelectionChanged); + connect(m_trackDataWidget, &TrackDataWidget::SelectionChanged, this, &TimeViewPlugin::OnSelectionChanged); - connect(mTrackDataWidget, &TrackDataWidget::ElementTrackChanged, this, &TimeViewPlugin::MotionEventTrackChanged); - connect(mTrackDataWidget, &TrackDataWidget::MotionEventChanged, this, &TimeViewPlugin::MotionEventChanged); + connect(m_trackDataWidget, &TrackDataWidget::ElementTrackChanged, this, &TimeViewPlugin::MotionEventTrackChanged); + connect(m_trackDataWidget, &TrackDataWidget::MotionEventChanged, this, &TimeViewPlugin::MotionEventChanged); connect(this, &TimeViewPlugin::DeleteKeyPressed, this, &TimeViewPlugin::RemoveSelectedMotionEvents); - connect(mDock, &QDockWidget::visibilityChanged, this, &TimeViewPlugin::VisibilityChanged); + connect(m_dock, &QDockWidget::visibilityChanged, this, &TimeViewPlugin::VisibilityChanged); connect(this, &TimeViewPlugin::ManualTimeChange, this, &TimeViewPlugin::OnManualTimeChange); - connect(mTimeViewToolBar, &TimeViewToolBar::RecorderStateChanged, this, &TimeViewPlugin::RecorderStateChanged); + connect(m_timeViewToolBar, &TimeViewToolBar::RecorderStateChanged, this, &TimeViewPlugin::RecorderStateChanged); SetCurrentTime(0.0f); SetScale(1.0f); SetRedrawFlag(); - mTimeViewToolBar->UpdateInterface(); + m_timeViewToolBar->UpdateInterface(); EMotionFX::AnimGraphEditorNotificationBus::Handler::BusConnect(); return true; @@ -284,7 +284,7 @@ namespace EMStudio // add a new track void TimeViewPlugin::AddTrack(TimeTrack* track) { - mTracks.emplace_back(track); + m_tracks.emplace_back(track); SetRedrawFlag(); } @@ -293,18 +293,18 @@ namespace EMStudio void TimeViewPlugin::RemoveAllTracks() { // get the number of time tracks and iterate through them - for (TimeTrack* track : mTracks) + for (TimeTrack* track : m_tracks) { delete track; } - mTracks.clear(); + m_tracks.clear(); SetRedrawFlag(); } TimeTrack* TimeViewPlugin::FindTrackByElement(TimeTrackElement* element) const { - const auto foundTrack = AZStd::find_if(begin(mTracks), end(mTracks), [element](const TimeTrack* timeTrack) + const auto foundTrack = AZStd::find_if(begin(m_tracks), end(m_tracks), [element](const TimeTrack* timeTrack) { // get the number of time track elements and iterate through them const size_t numElements = timeTrack->GetNumElements(); @@ -317,15 +317,15 @@ namespace EMStudio } return false; }); - return foundTrack != end(mTracks) ? *foundTrack : nullptr; + return foundTrack != end(m_tracks) ? *foundTrack : nullptr; } AZ::Outcome TimeViewPlugin::FindTrackIndex(const TimeTrack* track) const { - const auto foundTrack = AZStd::find(begin(mTracks), end(mTracks), track); - if (foundTrack != end(mTracks)) + const auto foundTrack = AZStd::find(begin(m_tracks), end(m_tracks), track); + if (foundTrack != end(m_tracks)) { - return AZ::Success(static_cast(AZStd::distance(begin(mTracks), foundTrack))); + return AZ::Success(static_cast(AZStd::distance(begin(m_tracks), foundTrack))); } return AZ::Failure(); } @@ -378,7 +378,7 @@ namespace EMStudio } if (outFrameNr) { - *outFrameNr = aznumeric_cast(timeValue / (double)mFPS); + *outFrameNr = aznumeric_cast(timeValue / (double)m_fps); } } @@ -388,10 +388,10 @@ namespace EMStudio { if (scaleXPixel) { - xPixel *= mTimeScale; + xPixel *= m_timeScale; } - const double pixelTime = ((xPixel + mScrollX) / mPixelsPerSecond); + const double pixelTime = ((xPixel + m_scrollX) / m_pixelsPerSecond); if (outPixelTime) { @@ -411,7 +411,7 @@ namespace EMStudio } if (outFrameNr) { - *outFrameNr = aznumeric_cast(pixelTime / (double)mFPS); + *outFrameNr = aznumeric_cast(pixelTime / (double)m_fps); } } @@ -423,11 +423,11 @@ namespace EMStudio return; } - if (mMotion) + if (m_motion) { - MotionInfo* motionInfo = FindMotionInfo(mMotion->GetID()); - motionInfo->mScale = mTargetTimeScale; - motionInfo->mScrollX = mTargetScrollX; + MotionInfo* motionInfo = FindMotionInfo(m_motion->GetID()); + motionInfo->m_scale = m_targetTimeScale; + motionInfo->m_scrollX = m_targetScrollX; } } @@ -436,20 +436,19 @@ namespace EMStudio void TimeViewPlugin::UpdateVisualData() { ValidatePluginLinks(); - mTrackDataHeaderWidget->update(); - mTrackDataWidget->update(); - mTimeInfoWidget->update(); - mDirty = false; + m_trackDataHeaderWidget->update(); + m_trackDataWidget->update(); + m_timeInfoWidget->update(); + m_dirty = false; } // calc the time value to a pixel value (excluding scroll) double TimeViewPlugin::TimeToPixel(double timeInSeconds, bool scale) const { - // return ((timeInSeconds * mPixelsPerSecond)/* / mTimeScale*/) - mScrollX; - double result = ((timeInSeconds * mPixelsPerSecond)) - mScrollX; + double result = ((timeInSeconds * m_pixelsPerSecond)) - m_scrollX; if (scale) { - return (result * mTimeScale); + return (result * m_timeScale); } else { @@ -462,10 +461,10 @@ namespace EMStudio TimeTrackElement* TimeViewPlugin::GetElementAt(int32 x, int32 y) { // for all tracks - for (const TimeTrack* track : mTracks) + for (const TimeTrack* track : m_tracks) { // check if the absolute pixel is inside - TimeTrackElement* result = track->GetElementAt(aznumeric_cast(x + mScrollX), y); + TimeTrackElement* result = track->GetElementAt(aznumeric_cast(x + m_scrollX), y); if (result) { return result; @@ -480,11 +479,11 @@ namespace EMStudio TimeTrack* TimeViewPlugin::GetTrackAt(int32 y) { // for all tracks - const auto foundTrack = AZStd::find_if(begin(mTracks), end(mTracks), [y](const TimeTrack* track) + const auto foundTrack = AZStd::find_if(begin(m_tracks), end(m_tracks), [y](const TimeTrack* track) { return track->GetIsInside(y); }); - return foundTrack != end(mTracks) ? *foundTrack : nullptr; + return foundTrack != end(m_tracks) ? *foundTrack : nullptr; } @@ -492,7 +491,7 @@ namespace EMStudio void TimeViewPlugin::UnselectAllElements() { // for all tracks - for (TimeTrack* track : mTracks) + for (TimeTrack* track : m_tracks) { // for all elements, deselect it const size_t numElems = track->GetNumElements(); @@ -510,7 +509,7 @@ namespace EMStudio // return the time of the current time marker, in seconds double TimeViewPlugin::GetCurrentTime() const { - return mCurTime; + return m_curTime; } @@ -518,39 +517,39 @@ namespace EMStudio { if (isScaledPixel) { - xPixel /= mTimeScale; + xPixel /= m_timeScale; } - return ((xPixel + mScrollX) / mPixelsPerSecond); + return ((xPixel + m_scrollX) / m_pixelsPerSecond); } void TimeViewPlugin::DeltaScrollX(double deltaX, bool animate) { - double newTime = (mTargetScrollX + (deltaX / mTimeScale)) / mPixelsPerSecond; - if (newTime < mMaxTime - (1 / mTimeScale)) + double newTime = (m_targetScrollX + (deltaX / m_timeScale)) / m_pixelsPerSecond; + if (newTime < m_maxTime - (1 / m_timeScale)) { - SetScrollX(mTargetScrollX + (deltaX / mTimeScale), animate); + SetScrollX(m_targetScrollX + (deltaX / m_timeScale), animate); } else { - SetScrollX((mMaxTime - ((1 / mTimeScale))) * mPixelsPerSecond, animate); + SetScrollX((m_maxTime - ((1 / m_timeScale))) * m_pixelsPerSecond, animate); } SetRedrawFlag(); } void TimeViewPlugin::SetScrollX(double scrollX, bool animate) { - mTargetScrollX = scrollX; + m_targetScrollX = scrollX; - if (mTargetScrollX < 0) + if (m_targetScrollX < 0) { - mTargetScrollX = 0; + m_targetScrollX = 0; } if (animate == false) { - mScrollX = mTargetScrollX; + m_scrollX = m_targetScrollX; } // inform the motion info about the changes @@ -563,11 +562,11 @@ namespace EMStudio void TimeViewPlugin::SetCurrentTime(double timeInSeconds) { const double oneMs = 1.0 / 1000.0; - if (!AZ::IsClose(mCurTime, timeInSeconds, oneMs)) + if (!AZ::IsClose(m_curTime, timeInSeconds, oneMs)) { - mDirty = true; + m_dirty = true; } - mCurTime = timeInSeconds; + m_curTime = timeInSeconds; } @@ -583,7 +582,7 @@ namespace EMStudio } // for all tracks - for (TimeTrack* track : mTracks) + for (TimeTrack* track : m_tracks) { if (track->GetIsVisible() == false || track->GetIsEnabled() == false) { @@ -624,7 +623,7 @@ namespace EMStudio void TimeViewPlugin::RenderElementTimeHandles(QPainter& painter, uint32 dataWindowHeight, const QPen& pen) { // for all tracks - for (const TimeTrack* track : mTracks) + for (const TimeTrack* track : m_tracks) { if (track->GetIsVisible() == false) { @@ -658,7 +657,7 @@ namespace EMStudio void TimeViewPlugin::DisableAllToolTips() { // for all tracks - for (const TimeTrack* track : mTracks) + for (const TimeTrack* track : m_tracks) { // for all elements const size_t numElems = track->GetNumElements(); @@ -676,7 +675,7 @@ namespace EMStudio bool TimeViewPlugin::FindResizePoint(int32 x, int32 y, TimeTrackElement** outElement, uint32* outID) { // for all tracks - for (const TimeTrack* track : mTracks) + for (const TimeTrack* track : m_tracks) { if (track->GetIsVisible() == false) { @@ -720,95 +719,95 @@ namespace EMStudio // render the frame void TimeViewPlugin::ProcessFrame(float timePassedInSeconds) { - if (GetManager()->GetAvoidRendering() || mMainWidget->visibleRegion().isEmpty()) + if (GetManager()->GetAvoidRendering() || m_mainWidget->visibleRegion().isEmpty()) { return; } - mTotalTime += timePassedInSeconds; + m_totalTime += timePassedInSeconds; ValidatePluginLinks(); // animate the zoom - mScrollX += (mTargetScrollX - mScrollX) * 0.2; + m_scrollX += (m_targetScrollX - m_scrollX) * 0.2; - mIsAnimating = false; - if (mTargetTimeScale > mTimeScale) + m_isAnimating = false; + if (m_targetTimeScale > m_timeScale) { - if (MCore::Math::Abs(aznumeric_cast(mTargetScrollX - mScrollX)) <= 1) + if (MCore::Math::Abs(aznumeric_cast(m_targetScrollX - m_scrollX)) <= 1) { - mTimeScale += (mTargetTimeScale - mTimeScale) * 0.1; + m_timeScale += (m_targetTimeScale - m_timeScale) * 0.1; } } else { - mTimeScale += (mTargetTimeScale - mTimeScale) * 0.1; + m_timeScale += (m_targetTimeScale - m_timeScale) * 0.1; } - if (MCore::Math::Abs(aznumeric_cast(mTargetScrollX - mScrollX)) <= 1) + if (MCore::Math::Abs(aznumeric_cast(m_targetScrollX - m_scrollX)) <= 1) { - mScrollX = mTargetScrollX; + m_scrollX = m_targetScrollX; } else { - mIsAnimating = true; + m_isAnimating = true; } - if (MCore::Math::Abs(aznumeric_cast(mTargetTimeScale - mTimeScale)) <= 0.001) + if (MCore::Math::Abs(aznumeric_cast(m_targetTimeScale - m_timeScale)) <= 0.001) { - mTimeScale = mTargetTimeScale; + m_timeScale = m_targetTimeScale; } else { - mIsAnimating = true; + m_isAnimating = true; } // get the maximum time - GetDataTimes(&mMaxTime, nullptr, nullptr); + GetDataTimes(&m_maxTime, nullptr, nullptr); UpdateMaxHeight(); - mTrackDataWidget->UpdateRects(); + m_trackDataWidget->UpdateRects(); - if (MCore::Math::Abs(aznumeric_cast(mMaxHeight - mLastMaxHeight)) > 0.0001) + if (MCore::Math::Abs(aznumeric_cast(m_maxHeight - m_lastMaxHeight)) > 0.0001) { - mLastMaxHeight = mMaxHeight; + m_lastMaxHeight = m_maxHeight; } - if (mTrackDataWidget->mDragging == false && mTrackDataWidget->mResizing == false) + if (m_trackDataWidget->m_dragging == false && m_trackDataWidget->m_resizing == false) { - mTimeInfoWidget->SetOverwriteTime(PixelToTime(mCurMouseX), mMaxTime); + m_timeInfoWidget->SetOverwriteTime(PixelToTime(m_curMouseX), m_maxTime); } // update the hovering items - mEventEmitterNode = nullptr; - mActorInstanceData = mTrackDataWidget->FindActorInstanceData(); + m_eventEmitterNode = nullptr; + m_actorInstanceData = m_trackDataWidget->FindActorInstanceData(); if (EMotionFX::GetRecorder().GetRecordTime() > MCore::Math::epsilon) { - mEventHistoryItem = mTrackDataWidget->FindEventHistoryItem(mActorInstanceData, aznumeric_cast(mCurMouseX), aznumeric_cast(mCurMouseY)); - mNodeHistoryItem = mTrackDataWidget->FindNodeHistoryItem(mActorInstanceData, aznumeric_cast(mCurMouseX), aznumeric_cast(mCurMouseY)); + m_eventHistoryItem = m_trackDataWidget->FindEventHistoryItem(m_actorInstanceData, aznumeric_cast(m_curMouseX), aznumeric_cast(m_curMouseY)); + m_nodeHistoryItem = m_trackDataWidget->FindNodeHistoryItem(m_actorInstanceData, aznumeric_cast(m_curMouseX), aznumeric_cast(m_curMouseY)); - if (mEventHistoryItem) + if (m_eventHistoryItem) { - EMotionFX::AnimGraph* animGraph = EMotionFX::GetAnimGraphManager().FindAnimGraphByID(mEventHistoryItem->mAnimGraphID); + EMotionFX::AnimGraph* animGraph = EMotionFX::GetAnimGraphManager().FindAnimGraphByID(m_eventHistoryItem->m_animGraphId); if (animGraph) { - mEventEmitterNode = animGraph->RecursiveFindNodeById(mEventHistoryItem->mEmitterNodeId); + m_eventEmitterNode = animGraph->RecursiveFindNodeById(m_eventHistoryItem->m_emitterNodeId); } } } else { - mActorInstanceData = nullptr; - mNodeHistoryItem = nullptr; - mEventHistoryItem = nullptr; + m_actorInstanceData = nullptr; + m_nodeHistoryItem = nullptr; + m_eventHistoryItem = nullptr; } switch (m_mode) { case TimeViewMode::Motion: { - double newCurrentTime = mCurTime; + double newCurrentTime = m_curTime; - if (!mMotion) + if (!m_motion) { // Use the start time when either no motion is selected. newCurrentTime = 0.0f; @@ -817,17 +816,17 @@ namespace EMStudio { const AZStd::vector& motionInstances = MotionWindowPlugin::GetSelectedMotionInstances(); if (motionInstances.size() == 1 && - motionInstances[0]->GetMotion() == mMotion) + motionInstances[0]->GetMotion() == m_motion) { EMotionFX::MotionInstance* motionInstance = motionInstances[0]; - if (!AZ::IsClose(aznumeric_cast(mCurTime), motionInstance->GetCurrentTime(), MCore::Math::epsilon)) + if (!AZ::IsClose(aznumeric_cast(m_curTime), motionInstance->GetCurrentTime(), MCore::Math::epsilon)) { newCurrentTime = motionInstance->GetCurrentTime(); } } } - if (!mTrackDataWidget->mDragging && !mTrackDataWidget->mResizing) + if (!m_trackDataWidget->m_dragging && !m_trackDataWidget->m_resizing) { SetCurrentTime(newCurrentTime); } @@ -843,12 +842,12 @@ namespace EMStudio if (recorder.GetIsInPlayMode() && recorder.GetIsInAutoPlayMode()) { SetCurrentTime(recorder.GetCurrentPlayTime()); - MakeTimeVisible(mCurTime, 0.5, false); + MakeTimeVisible(m_curTime, 0.5, false); } if (recorder.GetIsRecording()) { - SetCurrentTime(mMaxTime); + SetCurrentTime(m_maxTime); MakeTimeVisible(recorder.GetRecordTime(), 0.95, false); } } @@ -867,15 +866,15 @@ namespace EMStudio } } - if (mIsAnimating) + if (m_isAnimating) { - mDirty = true; + m_dirty = true; } bool redraw = false; float fps = 15.0f; #ifndef MCORE_DEBUG - if (mIsAnimating) + if (m_isAnimating) { fps = 60.0f; } @@ -885,13 +884,13 @@ namespace EMStudio } #endif - if (mTotalTime >= 1.0f / fps) + if (m_totalTime >= 1.0f / fps) { redraw = true; - mTotalTime = 0.0f; + m_totalTime = 0.0f; } - if (redraw && mDirty) + if (redraw && m_dirty) { UpdateVisualData(); } @@ -900,34 +899,26 @@ namespace EMStudio void TimeViewPlugin::SetRedrawFlag() { - mDirty = true; + m_dirty = true; } void TimeViewPlugin::UpdateViewSettings() { - SetScale(mTimeScale); + SetScale(m_timeScale); } void TimeViewPlugin::SetScale(double scale, bool animate) { - // if (mMaxTime < centerTime) - /* double rangeStart = PixelToTime( 0.0 ); - double rangeEnd = PixelToTime( mTrackDataWidget->geometry().width() ); - if (rangeEnd > mMaxTime) - rangeEnd = mMaxTime; - - double centerTime = (rangeStart + rangeEnd) / 2.0; - */ double curTime = GetCurrentTime(); - mTargetTimeScale = scale; - mTargetTimeScale = MCore::Clamp(scale, mMinScale, mMaxScale); + m_targetTimeScale = scale; + m_targetTimeScale = MCore::Clamp(scale, m_minScale, m_maxScale); if (animate == false) { - mTimeScale = mTargetTimeScale; + m_timeScale = m_targetTimeScale; } UpdateCurrentMotionInfo(); @@ -937,44 +928,6 @@ namespace EMStudio // MakeTimeVisible( centerTime, 0.5 ); } - // set the maximum time value - /*void TimeViewPlugin::SetMaxTime(double maxTime) - { - mMaxTime = maxTime; - mMaxTimeInPixels = (maxTime * TIMEVIEW_PIXELSPERSECOND) / mTimeScale; - - double oldSliderMax = mHorizontalScroll->maximum(); - double oldNormalizedValue = (double)mHorizontalScroll->value() / oldSliderMax; - - mHorizontalScroll->setRange( 0, mMaxTimeInPixels ); - mHorizontalScroll->setValue( oldNormalizedValue * mMaxTimeInPixels ); - } - - - // set the time view scale and keep it in a reasonable range - void TimeViewPlugin::SetTimeScale(float scale) - { - mTimeScale = scale; - - const float minScale = 0.01f; - //const float maxScale = 100.0f; - - if (mTimeScale < minScale) - mTimeScale = minScale; - - if (mTimeScale > mMaxScale) - mTimeScale = mMaxScale; - - // adjust the maximum time - SetMaxTime(mMaxTime); - - // adjust the current play time - SetCurrentTime( GetCurrentTime() ); - - // inform the motion info about the changes - UpdateCurrentMotionInfo(); - }*/ - void TimeViewPlugin::OnKeyPressEvent(QKeyEvent* event) { @@ -988,30 +941,30 @@ namespace EMStudio if (event->key() == Qt::Key_Down) { - mTrackDataWidget->scroll(0, 20); + m_trackDataWidget->scroll(0, 20); event->accept(); return; } if (event->key() == Qt::Key_Up) { - mTrackDataWidget->scroll(0, -20); + m_trackDataWidget->scroll(0, -20); event->accept(); return; } if (event->key() == Qt::Key_Plus) { - double zoomDelta = 0.1 * 3 * MCore::Clamp(mTargetTimeScale / 2.0, 1.0, 22.0); - SetScale(mTargetTimeScale + zoomDelta); + double zoomDelta = 0.1 * 3 * MCore::Clamp(m_targetTimeScale / 2.0, 1.0, 22.0); + SetScale(m_targetTimeScale + zoomDelta); event->accept(); return; } if (event->key() == Qt::Key_Minus) { - double zoomDelta = 0.1 * 3 * MCore::Clamp(mTargetTimeScale / 2.0, 1.0, 22.0); - SetScale(mTargetTimeScale - zoomDelta); + double zoomDelta = 0.1 * 3 * MCore::Clamp(m_targetTimeScale / 2.0, 1.0, 22.0); + SetScale(m_targetTimeScale - zoomDelta); event->accept(); return; } @@ -1020,10 +973,10 @@ namespace EMStudio { if (event->key() == Qt::Key_Left) { - mTargetScrollX -= (mPixelsPerSecond * 3) / mTimeScale; - if (mTargetScrollX < 0) + m_targetScrollX -= (m_pixelsPerSecond * 3) / m_timeScale; + if (m_targetScrollX < 0) { - mTargetScrollX = 0; + m_targetScrollX = 0; } event->accept(); return; @@ -1031,10 +984,10 @@ namespace EMStudio if (event->key() == Qt::Key_Right) { - const double newTime = (mScrollX + ((mPixelsPerSecond * 3) / mTimeScale)) / mPixelsPerSecond; - if (newTime < mMaxTime) + const double newTime = (m_scrollX + ((m_pixelsPerSecond * 3) / m_timeScale)) / m_pixelsPerSecond; + if (newTime < m_maxTime) { - mTargetScrollX += ((mPixelsPerSecond * 3) / mTimeScale); + m_targetScrollX += ((m_pixelsPerSecond * 3) / m_timeScale); } event->accept(); @@ -1065,10 +1018,10 @@ namespace EMStudio if (event->key() == Qt::Key_PageUp) { - mTargetScrollX -= mTrackDataWidget->geometry().width() / mTimeScale; - if (mTargetScrollX < 0) + m_targetScrollX -= m_trackDataWidget->geometry().width() / m_timeScale; + if (m_targetScrollX < 0) { - mTargetScrollX = 0; + m_targetScrollX = 0; } event->accept(); return; @@ -1076,10 +1029,10 @@ namespace EMStudio if (event->key() == Qt::Key_PageDown) { - const double newTime = (mScrollX + (mTrackDataWidget->geometry().width() / mTimeScale)) / mPixelsPerSecond; - if (newTime < mMaxTime) + const double newTime = (m_scrollX + (m_trackDataWidget->geometry().width() / m_timeScale)) / m_pixelsPerSecond; + if (newTime < m_maxTime) { - mTargetScrollX += mTrackDataWidget->geometry().width() / mTimeScale; + m_targetScrollX += m_trackDataWidget->geometry().width() / m_timeScale; } event->accept(); @@ -1106,9 +1059,9 @@ namespace EMStudio void TimeViewPlugin::ValidatePluginLinks() { - mMotionWindowPlugin = nullptr; - mMotionListWindow = nullptr; - mMotionEventsPlugin = nullptr; + m_motionWindowPlugin = nullptr; + m_motionListWindow = nullptr; + m_motionEventsPlugin = nullptr; m_motionSetPlugin = nullptr; EMStudio::PluginManager* pluginManager = EMStudio::GetPluginManager(); @@ -1116,9 +1069,9 @@ namespace EMStudio EMStudioPlugin* motionBasePlugin = pluginManager->FindActivePlugin(MotionWindowPlugin::CLASS_ID); if (motionBasePlugin) { - mMotionWindowPlugin = static_cast(motionBasePlugin); - mMotionListWindow = mMotionWindowPlugin->GetMotionListWindow(); - connect(mMotionListWindow, &MotionListWindow::MotionSelectionChanged, this, &TimeViewPlugin::MotionSelectionChanged, Qt::UniqueConnection); // UniqueConnection as we could connect multiple times. + m_motionWindowPlugin = static_cast(motionBasePlugin); + m_motionListWindow = m_motionWindowPlugin->GetMotionListWindow(); + connect(m_motionListWindow, &MotionListWindow::MotionSelectionChanged, this, &TimeViewPlugin::MotionSelectionChanged, Qt::UniqueConnection); // UniqueConnection as we could connect multiple times. } EMStudioPlugin* motionSetBasePlugin = pluginManager->FindActivePlugin(MotionSetsWindowPlugin::CLASS_ID); @@ -1131,8 +1084,8 @@ namespace EMStudio EMStudioPlugin* motionEventsBasePlugin = pluginManager->FindActivePlugin(MotionEventsPlugin::CLASS_ID); if (motionEventsBasePlugin) { - mMotionEventsPlugin = static_cast(motionEventsBasePlugin); - mMotionEventsPlugin->ValidatePluginLinks(); + m_motionEventsPlugin = static_cast(motionEventsBasePlugin); + m_motionEventsPlugin->ValidatePluginLinks(); } } @@ -1140,7 +1093,7 @@ namespace EMStudio void TimeViewPlugin::MotionSelectionChanged() { ValidatePluginLinks(); - if ((mMotionListWindow && mMotionListWindow->isVisible()) || + if ((m_motionListWindow && m_motionListWindow->isVisible()) || (m_motionSetPlugin && m_motionSetPlugin->GetMotionSetWindow() && m_motionSetPlugin->GetMotionSetWindow()->isVisible())) { SetMode(TimeViewMode::Motion); @@ -1150,14 +1103,14 @@ namespace EMStudio void TimeViewPlugin::UpdateSelection() { - mSelectedEvents.clear(); - if (!mMotion) + m_selectedEvents.clear(); + if (!m_motion) { return; } // get the motion event table - const EMotionFX::MotionEventTable* eventTable = mMotion->GetEventTable(); + const EMotionFX::MotionEventTable* eventTable = m_motion->GetEventTable(); // get the number of tracks in the time view and iterate through them const size_t numTracks = GetNumTracks(); @@ -1189,10 +1142,10 @@ namespace EMStudio if (element->GetIsSelected()) { EventSelectionItem selectionItem; - selectionItem.mMotion = mMotion; - selectionItem.mTrackNr = trackNr.GetValue(); - selectionItem.mEventNr = element->GetElementNumber(); - mSelectedEvents.emplace_back(selectionItem); + selectionItem.m_motion = m_motion; + selectionItem.m_trackNr = trackNr.GetValue(); + selectionItem.m_eventNr = element->GetElementNumber(); + m_selectedEvents.emplace_back(selectionItem); } } } @@ -1201,10 +1154,10 @@ namespace EMStudio void TimeViewPlugin::ReInit() { - if (EMotionFX::GetMotionManager().FindMotionIndex(mMotion) == InvalidIndex) + if (EMotionFX::GetMotionManager().FindMotionIndex(m_motion) == InvalidIndex) { // set the motion first back to nullptr - mMotion = nullptr; + m_motion = nullptr; } // update the selection and save it @@ -1217,16 +1170,16 @@ namespace EMStudio (EMotionFX::GetRecorder().GetIsRecording() || EMotionFX::GetRecorder().GetRecordTime() > MCore::Math::epsilon || EMotionFX::GetRecorder().GetIsInPlayMode())) { SetScrollX(0); - mTrackHeaderWidget->ReInit(); + m_trackHeaderWidget->ReInit(); return; } - if (mMotion) + if (m_motion) { size_t trackIndex; AZStd::string text; - const EMotionFX::MotionEventTable* eventTable = mMotion->GetEventTable(); + const EMotionFX::MotionEventTable* eventTable = m_motion->GetEventTable(); RemoveAllTracks(); @@ -1268,14 +1221,14 @@ namespace EMStudio timeTrack->AddElement(element); } - // Select the element if in mSelectedEvents. - for (const EventSelectionItem& selectionItem : mSelectedEvents) + // Select the element if in m_selectedEvents. + for (const EventSelectionItem& selectionItem : m_selectedEvents) { - if (mMotion != selectionItem.mMotion) + if (m_motion != selectionItem.m_motion) { continue; } - if (selectionItem.mTrackNr == trackIndex && selectionItem.mEventNr == eventIndex) + if (selectionItem.m_trackNr == trackIndex && selectionItem.m_eventNr == eventIndex) { element->SetIsSelected(true); break; @@ -1367,7 +1320,7 @@ namespace EMStudio timeTrack->SetElementCount(numMotionEvents); } } - else // mMotion == nullptr + else // m_motion == nullptr { const size_t numEventTracks = GetNumTracks(); for (size_t trackIndex = 0; trackIndex < numEventTracks; ++trackIndex) @@ -1385,27 +1338,26 @@ namespace EMStudio } // update the time view plugin - mTrackHeaderWidget->ReInit(); + m_trackHeaderWidget->ReInit(); - if (mMotion) + if (m_motion) { - //animationLength = mMotion->GetMaxTime(); - MotionInfo* motionInfo = FindMotionInfo(mMotion->GetID()); + MotionInfo* motionInfo = FindMotionInfo(m_motion->GetID()); // if we already selected before, set the remembered settings - if (motionInfo->mInitialized) + if (motionInfo->m_initialized) { - const int32 tempScroll = aznumeric_cast(motionInfo->mScrollX); - SetScale(motionInfo->mScale); + const int32 tempScroll = aznumeric_cast(motionInfo->m_scrollX); + SetScale(motionInfo->m_scale); SetScrollX(tempScroll); } else { // selected the animation the first time - motionInfo->mInitialized = true; - mTargetTimeScale = CalcFitScale(mMinScale, mMaxScale) * 0.8; - motionInfo->mScale = mTargetTimeScale; - motionInfo->mScrollX = 0.0; + motionInfo->m_initialized = true; + m_targetTimeScale = CalcFitScale(m_minScale, m_maxScale) * 0.8; + motionInfo->m_scale = m_targetTimeScale; + motionInfo->m_scrollX = 0.0; } } @@ -1416,27 +1368,27 @@ namespace EMStudio // find the motion info for the given motion id TimeViewPlugin::MotionInfo* TimeViewPlugin::FindMotionInfo(uint32 motionID) { - const auto foundMotionInfo = AZStd::find_if(begin(mMotionInfos), end(mMotionInfos), [motionID](const MotionInfo* motionInfo) + const auto foundMotionInfo = AZStd::find_if(begin(m_motionInfos), end(m_motionInfos), [motionID](const MotionInfo* motionInfo) { - return motionInfo->mMotionID == motionID; + return motionInfo->m_motionId == motionID; }); - if (foundMotionInfo != end(mMotionInfos)) + if (foundMotionInfo != end(m_motionInfos)) { return *foundMotionInfo; } // we haven't found a motion info for the given id yet, so create a new one MotionInfo* motionInfo = new MotionInfo(); - motionInfo->mMotionID = motionID; - motionInfo->mInitialized = false; - mMotionInfos.emplace_back(motionInfo); + motionInfo->m_motionId = motionID; + motionInfo->m_initialized = false; + m_motionInfos.emplace_back(motionInfo); return motionInfo; } void TimeViewPlugin::Select(const AZStd::vector& selection) { - mSelectedEvents = selection; + m_selectedEvents = selection; // get the number of tracks in the time view and iterate through them const size_t numTracks = GetNumTracks(); @@ -1455,8 +1407,8 @@ namespace EMStudio for (const EventSelectionItem& selectionItem : selection) { - TimeTrack* track = GetTrack(selectionItem.mTrackNr); - TimeTrackElement* element = track->GetElement(selectionItem.mEventNr); + TimeTrack* track = GetTrack(selectionItem.m_trackNr); + TimeTrackElement* element = track->GetElement(selectionItem.m_eventNr); element->SetIsSelected(true); } @@ -1472,23 +1424,23 @@ namespace EMStudio return nullptr; } - if (mEventNr >= eventTrack->GetNumEvents()) + if (m_eventNr >= eventTrack->GetNumEvents()) { return nullptr; } - return &(eventTrack->GetEvent(mEventNr)); + return &(eventTrack->GetEvent(m_eventNr)); } EMotionFX::MotionEventTrack* EventSelectionItem::GetEventTrack() { - if (mTrackNr >= mMotion->GetEventTable()->GetNumTracks()) + if (m_trackNr >= m_motion->GetEventTable()->GetNumTracks()) { return nullptr; } - EMotionFX::MotionEventTrack* eventTrack = mMotion->GetEventTable()->GetTrack(mTrackNr); + EMotionFX::MotionEventTrack* eventTrack = m_motion->GetEventTable()->GetTrack(m_trackNr); return eventTrack; } @@ -1496,7 +1448,7 @@ namespace EMStudio void TimeViewPlugin::AddMotionEvent(int32 x, int32 y) { - if (mMotion == nullptr) + if (m_motion == nullptr) { return; } @@ -1560,7 +1512,7 @@ namespace EMStudio } // get the corresponding motion event track - EMotionFX::MotionEventTable* eventTable = mMotion->GetEventTable(); + EMotionFX::MotionEventTable* eventTable = m_motion->GetEventTable(); EMotionFX::MotionEventTrack* eventTrack = eventTable->FindTrackByName(timeTrack->GetName()); if (eventTrack == nullptr) { @@ -1575,7 +1527,7 @@ namespace EMStudio // adjust the motion event AZStd::string outResult, command; - command = AZStd::string::format("AdjustMotionEvent -motionID %i -eventTrackName \"%s\" -eventNr %zu -startTime %f -endTime %f", mMotion->GetID(), eventTrack->GetName(), motionEventNr, startTime, endTime); + command = AZStd::string::format("AdjustMotionEvent -motionID %i -eventTrackName \"%s\" -eventNr %zu -startTime %f -endTime %f", m_motion->GetID(), eventTrack->GetName(), motionEventNr, startTime, endTime); if (EMStudio::GetCommandManager()->ExecuteCommand(command.c_str(), outResult) == false) { MCore::LogError(outResult.c_str()); @@ -1589,23 +1541,23 @@ namespace EMStudio AZStd::string result; MCore::CommandGroup commandGroup("Remove motion events"); - if (mTrackDataWidget) + if (m_trackDataWidget) { - mTrackDataWidget->ClearState(); + m_trackDataWidget->ClearState(); } - if (mMotion == nullptr) + if (m_motion == nullptr) { return; } - if (EMotionFX::GetMotionManager().FindMotionIndex(mMotion) == InvalidIndex) + if (EMotionFX::GetMotionManager().FindMotionIndex(m_motion) == InvalidIndex) { return; } // get the motion event table - // MotionEventTable& eventTable = mMotion->GetEventTable(); + // MotionEventTable& eventTable = m_motion->GetEventTable(); AZStd::vector eventNumbers; // get the number of tracks in the time view and iterate through them @@ -1653,18 +1605,17 @@ namespace EMStudio AZStd::string result; MCore::CommandGroup commandGroup("Remove motion events"); - if (mMotion == nullptr) + if (m_motion == nullptr) { return; } - if (EMotionFX::GetMotionManager().FindMotionIndex(mMotion) == InvalidIndex) + if (EMotionFX::GetMotionManager().FindMotionIndex(m_motion) == InvalidIndex) { return; } // get the motion event table - // MotionEventTable& eventTable = mMotion->GetEventTable(); AZStd::vector eventNumbers; // get the number of tracks in the time view and iterate through them @@ -1732,11 +1683,11 @@ namespace EMStudio if (outClipStart) { - *outClipStart = playbackInfo->mClipStartTime; + *outClipStart = playbackInfo->m_clipStartTime; } if (outClipEnd) { - *outClipEnd = playbackInfo->mClipEndTime; + *outClipEnd = playbackInfo->m_clipEndTime; } if (outMaxTime) { @@ -1770,8 +1721,8 @@ namespace EMStudio // zoom to fit void TimeViewPlugin::ZoomToFit() { - mTargetScrollX = 0.0; - mTargetTimeScale = CalcFitScale(mMinScale, mMaxScale); + m_targetScrollX = 0.0; + m_targetTimeScale = CalcFitScale(m_minScale, m_maxScale); } @@ -1786,8 +1737,8 @@ namespace EMStudio double scale = 1.0; if (maxTime > 0.0) { - double width = mTrackDataWidget->geometry().width(); - scale = (width / mPixelsPerSecond) / maxTime; + double width = m_trackDataWidget->geometry().width(); + scale = (width / m_pixelsPerSecond) / maxTime; } if (scale < minScale) @@ -1808,7 +1759,7 @@ namespace EMStudio bool TimeViewPlugin::GetIsTimeVisible(double timeValue) const { const double pixel = TimeToPixel(timeValue); - return (pixel >= 0.0 && pixel < mTrackDataWidget->geometry().width()); + return (pixel >= 0.0 && pixel < m_trackDataWidget->geometry().width()); } @@ -1820,17 +1771,17 @@ namespace EMStudio const double pixel = TimeToPixel(timeValue, false); // if we need to scroll to the right - double width = mTrackDataWidget->geometry().width() / mTimeScale; - mTargetScrollX += (pixel - width) + width * (1.0 - offsetFactor); + double width = m_trackDataWidget->geometry().width() / m_timeScale; + m_targetScrollX += (pixel - width) + width * (1.0 - offsetFactor); - if (mTargetScrollX < 0) + if (m_targetScrollX < 0) { - mTargetScrollX = 0; + m_targetScrollX = 0; } if (animate == false) { - mScrollX = mTargetScrollX; + m_scrollX = m_targetScrollX; } } @@ -1838,7 +1789,7 @@ namespace EMStudio // update the maximum height void TimeViewPlugin::UpdateMaxHeight() { - mMaxHeight = 0.0; + m_maxHeight = 0.0; // find the selected actor instance EMotionFX::Recorder& recorder = EMotionFX::GetRecorder(); @@ -1851,7 +1802,7 @@ namespace EMStudio const size_t actorInstanceDataIndex = recorder.FindActorInstanceDataIndex(actorInstance); if (actorInstanceDataIndex != InvalidIndex) { - RecorderGroup* recorderGroup = mTimeViewToolBar->GetRecorderGroup(); + RecorderGroup* recorderGroup = m_timeViewToolBar->GetRecorderGroup(); const bool displayNodeActivity = recorderGroup->GetDisplayNodeActivity(); const bool displayEvents = recorderGroup->GetDisplayMotionEvents(); const bool displayRelativeGraph = recorderGroup->GetDisplayRelativeGraph(); @@ -1860,7 +1811,7 @@ namespace EMStudio const EMotionFX::Recorder::ActorInstanceData& actorInstanceData = recorder.GetActorInstanceData(actorInstanceDataIndex); if (displayNodeActivity) { - mMaxHeight += ((recorder.CalcMaxNodeHistoryTrackIndex(actorInstanceData) + 1) * (mTrackDataWidget->mNodeHistoryItemHeight + 3)); + m_maxHeight += ((recorder.CalcMaxNodeHistoryTrackIndex(actorInstanceData) + 1) * (m_trackDataWidget->m_nodeHistoryItemHeight + 3)); isTop = false; } @@ -1868,18 +1819,18 @@ namespace EMStudio { if (isTop == false) { - mMaxHeight += 10 + 10; + m_maxHeight += 10 + 10; } isTop = false; - mMaxHeight += mTrackDataWidget->mEventHistoryTotalHeight; + m_maxHeight += m_trackDataWidget->m_eventHistoryTotalHeight; } if (displayRelativeGraph) { if (isTop == false) { - mMaxHeight += 10; + m_maxHeight += 10; } isTop = false; @@ -1889,17 +1840,17 @@ namespace EMStudio } else { - if (mMotion) + if (m_motion) { - for (const TimeTrack* track : mTracks) + for (const TimeTrack* track : m_tracks) { if (track->GetIsVisible() == false) { continue; } - mMaxHeight += track->GetHeight(); - mMaxHeight += 1; + m_maxHeight += track->GetHeight(); + m_maxHeight += 1; } } } @@ -1910,39 +1861,37 @@ namespace EMStudio void TimeViewPlugin::OnZoomAll() { ZoomToFit(); - //if (mTargetTimeScale < 1.0) - //mTargetTimeScale = 1.0; } // goto time zero void TimeViewPlugin::OnGotoTimeZero() { - mTargetScrollX = 0; + m_targetScrollX = 0; } // reset timeline void TimeViewPlugin::OnResetTimeline() { - mTargetScrollX = 0; - mTargetTimeScale = 1.0; + m_targetScrollX = 0; + m_targetTimeScale = 1.0; } // center on current time void TimeViewPlugin::OnCenterOnCurTime() { - MakeTimeVisible(mCurTime, 0.5); + MakeTimeVisible(m_curTime, 0.5); } // center on current time void TimeViewPlugin::OnShowNodeHistoryNodeInGraph() { - if (mNodeHistoryItem && mActorInstanceData) + if (m_nodeHistoryItem && m_actorInstanceData) { - emit DoubleClickedRecorderNodeHistoryItem(mActorInstanceData, mNodeHistoryItem); + emit DoubleClickedRecorderNodeHistoryItem(m_actorInstanceData, m_nodeHistoryItem); } } @@ -1950,9 +1899,9 @@ namespace EMStudio // center on current time void TimeViewPlugin::OnClickNodeHistoryNode() { - if (mNodeHistoryItem && mActorInstanceData) + if (m_nodeHistoryItem && m_actorInstanceData) { - emit ClickedRecorderNodeHistoryItem(mActorInstanceData, mNodeHistoryItem); + emit ClickedRecorderNodeHistoryItem(m_actorInstanceData, m_nodeHistoryItem); } } @@ -1960,17 +1909,17 @@ namespace EMStudio // zooming on rect void TimeViewPlugin::ZoomRect(const QRect& rect) { - mTargetScrollX = mScrollX + (rect.left() / mTimeScale); - mTargetTimeScale = mTrackDataWidget->geometry().width() / (double)(rect.width() / mTimeScale); + m_targetScrollX = m_scrollX + (rect.left() / m_timeScale); + m_targetTimeScale = m_trackDataWidget->geometry().width() / (double)(rect.width() / m_timeScale); - if (mTargetTimeScale < 1.0) + if (m_targetTimeScale < 1.0) { - mTargetTimeScale = 1.0; + m_targetTimeScale = 1.0; } - if (mTargetTimeScale > mMaxScale) + if (m_targetTimeScale > m_maxScale) { - mTargetTimeScale = mMaxScale; + m_targetTimeScale = m_maxScale; } } @@ -2070,7 +2019,7 @@ namespace EMStudio // calculate the content heights uint32 TimeViewPlugin::CalcContentHeight() const { - RecorderGroup* recorderGroup = mTimeViewToolBar->GetRecorderGroup(); + RecorderGroup* recorderGroup = m_timeViewToolBar->GetRecorderGroup(); const bool displayNodeActivity = recorderGroup->GetDisplayNodeActivity(); const bool displayEvents = recorderGroup->GetDisplayMotionEvents(); const bool displayRelativeGraph = recorderGroup->GetDisplayRelativeGraph(); @@ -2078,12 +2027,12 @@ namespace EMStudio uint32 result = 0; if (displayNodeActivity) { - result += mTrackDataWidget->mNodeHistoryRect.bottom(); + result += m_trackDataWidget->m_nodeHistoryRect.bottom(); } if (displayEvents) { - result += mTrackDataWidget->mEventHistoryTotalHeight; + result += m_trackDataWidget->m_eventHistoryTotalHeight; } if (displayRelativeGraph) @@ -2120,15 +2069,15 @@ namespace EMStudio case TimeViewMode::Motion: { EMotionFX::Motion* motion = GetCommandManager()->GetCurrentSelection().GetSingleMotion(); - if ((mMotion != motion) || modeChanged) + if ((m_motion != motion) || modeChanged) { - mMotion = motion; + m_motion = motion; ReInit(); } - if (mTrackHeaderWidget) + if (m_trackHeaderWidget) { - mTrackHeaderWidget->GetAddTrackWidget()->setEnabled(motion != nullptr); + m_trackHeaderWidget->GetAddTrackWidget()->setEnabled(motion != nullptr); } break; @@ -2136,13 +2085,13 @@ namespace EMStudio default: { - mMotion = nullptr; + m_motion = nullptr; ReInit(); OnZoomAll(); SetCurrentTime(0.0f); } } - mTimeViewToolBar->UpdateInterface(); + m_timeViewToolBar->UpdateInterface(); } } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeViewPlugin.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeViewPlugin.h index e6af4e1ae1..1eed525c41 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeViewPlugin.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeViewPlugin.h @@ -39,9 +39,9 @@ namespace EMStudio EMotionFX::MotionEvent* GetMotionEvent(); EMotionFX::MotionEventTrack* GetEventTrack(); - size_t mEventNr;// the motion event index in its track - size_t mTrackNr;// the corresponding track in which the event is in - EMotionFX::Motion* mMotion;// the parent motion of the event track + size_t m_eventNr;// the motion event index in its track + size_t m_trackNr;// the corresponding track in which the event is in + EMotionFX::Motion* m_motion;// the parent motion of the event track }; class TimeViewPlugin @@ -88,7 +88,7 @@ namespace EMStudio void SetMode(TimeViewMode mode); TimeViewMode GetMode() const { return m_mode; } - double GetScrollX() const { return mScrollX; } + double GetScrollX() const { return m_scrollX; } void DeltaScrollX(double deltaX, bool animate = true); @@ -108,15 +108,15 @@ namespace EMStudio double CalcFitScale(double minScale = 1.0, double maxScale = 100.0) const; void MakeTimeVisible(double timeValue, double offsetFactor = 0.95, bool animate = true); bool GetIsTimeVisible(double timeValue) const; - float GetTimeScale() const { return aznumeric_cast(mTimeScale); } + float GetTimeScale() const { return aznumeric_cast(m_timeScale); } void RenderElementTimeHandles(QPainter& painter, uint32 dataWindowHeight, const QPen& pen); void DisableAllToolTips(); void AddTrack(TimeTrack* track); void RemoveAllTracks(); - TimeTrack* GetTrack(size_t index) { return mTracks[index]; } - size_t GetNumTracks() const { return mTracks.size(); } + TimeTrack* GetTrack(size_t index) { return m_tracks[index]; } + size_t GetNumTracks() const { return m_tracks.size(); } AZ::Outcome FindTrackIndex(const TimeTrack* track) const; TimeTrack* FindTrackByElement(TimeTrackElement* element) const; @@ -132,15 +132,15 @@ namespace EMStudio bool FindResizePoint(int32 x, int32 y, TimeTrackElement** outElement, uint32* outID); - QCursor* GetZoomInCursor() const { return mZoomInCursor; } - QCursor* GetZoomOutCursor() const { return mZoomOutCursor; } + QCursor* GetZoomInCursor() const { return m_zoomInCursor; } + QCursor* GetZoomOutCursor() const { return m_zoomOutCursor; } // some getters - TrackDataHeaderWidget* GetTrackDataHeaderWidget() { return mTrackDataHeaderWidget; } - TrackDataWidget* GetTrackDataWidget() { return mTrackDataWidget; } - TrackHeaderWidget* GetTrackHeaderWidget() { return mTrackHeaderWidget; } - TimeInfoWidget* GetTimeInfoWidget() { return mTimeInfoWidget; } - TimeViewToolBar* GetTimeViewToolBar() { return mTimeViewToolBar; } + TrackDataHeaderWidget* GetTrackDataHeaderWidget() { return m_trackDataHeaderWidget; } + TrackDataWidget* GetTrackDataWidget() { return m_trackDataWidget; } + TrackHeaderWidget* GetTrackHeaderWidget() { return m_trackHeaderWidget; } + TimeInfoWidget* GetTimeInfoWidget() { return m_timeInfoWidget; } + TimeViewToolBar* GetTimeViewToolBar() { return m_timeViewToolBar; } void OnKeyPressEvent(QKeyEvent* event); void OnKeyReleaseEvent(QKeyEvent* event); @@ -151,12 +151,12 @@ namespace EMStudio void ZoomRect(const QRect& rect); - size_t GetNumSelectedEvents() { return mSelectedEvents.size(); } - EventSelectionItem GetSelectedEvent(size_t index) const { return mSelectedEvents[index]; } + size_t GetNumSelectedEvents() { return m_selectedEvents.size(); } + EventSelectionItem GetSelectedEvent(size_t index) const { return m_selectedEvents[index]; } void Select(const AZStd::vector& selection); - MCORE_INLINE EMotionFX::Motion* GetMotion() const { return mMotion; } + MCORE_INLINE EMotionFX::Motion* GetMotion() const { return m_motion; } void SetRedrawFlag(); uint32 CalcContentHeight() const; @@ -205,66 +205,66 @@ namespace EMStudio MCORE_DEFINECOMMANDCALLBACK(UpdateInterfaceCallback); AZStd::vector m_commandCallbacks; - TrackDataHeaderWidget* mTrackDataHeaderWidget; - TrackDataWidget* mTrackDataWidget; - TrackHeaderWidget* mTrackHeaderWidget; - TimeInfoWidget* mTimeInfoWidget; - TimeViewToolBar* mTimeViewToolBar; - QWidget* mMainWidget; + TrackDataHeaderWidget* m_trackDataHeaderWidget; + TrackDataWidget* m_trackDataWidget; + TrackHeaderWidget* m_trackHeaderWidget; + TimeInfoWidget* m_timeInfoWidget; + TimeViewToolBar* m_timeViewToolBar; + QWidget* m_mainWidget; TimeViewMode m_mode = TimeViewMode::None; - EMotionFX::Motion* mMotion; - MotionWindowPlugin* mMotionWindowPlugin; - MotionEventsPlugin* mMotionEventsPlugin; - MotionListWindow* mMotionListWindow; + EMotionFX::Motion* m_motion; + MotionWindowPlugin* m_motionWindowPlugin; + MotionEventsPlugin* m_motionEventsPlugin; + MotionListWindow* m_motionListWindow; MotionSetsWindowPlugin* m_motionSetPlugin; - AZStd::vector mSelectedEvents; + AZStd::vector m_selectedEvents; - EMotionFX::Recorder::ActorInstanceData* mActorInstanceData; - EMotionFX::Recorder::NodeHistoryItem* mNodeHistoryItem; - EMotionFX::Recorder::EventHistoryItem* mEventHistoryItem; - EMotionFX::AnimGraphNode* mEventEmitterNode; + EMotionFX::Recorder::ActorInstanceData* m_actorInstanceData; + EMotionFX::Recorder::NodeHistoryItem* m_nodeHistoryItem; + EMotionFX::Recorder::EventHistoryItem* m_eventHistoryItem; + EMotionFX::AnimGraphNode* m_eventEmitterNode; struct MotionInfo { - uint32 mMotionID; - bool mInitialized; - double mScale; - double mScrollX; + uint32 m_motionId; + bool m_initialized; + double m_scale; + double m_scrollX; }; MotionInfo* FindMotionInfo(uint32 motionID); void UpdateCurrentMotionInfo(); - AZStd::vector mMotionInfos; - AZStd::vector mTracks; + AZStd::vector m_motionInfos; + AZStd::vector m_tracks; - double mPixelsPerSecond; // pixels per second - double mScrollX; // horizontal scroll offset - double mCurTime; // current time - double mFPS; // the frame rate, used to snap time values to and to calculate frame numbers - double mCurMouseX; - double mCurMouseY; - double mMaxTime; // the end time of the full time bar - double mMaxHeight; - double mLastMaxHeight; - double mTimeScale; // the time zoom scale factor - double mMaxScale; - double mMinScale; - float mTotalTime; + double m_pixelsPerSecond; // pixels per second + double m_scrollX; // horizontal scroll offset + double m_curTime; // current time + double m_fps; // the frame rate, used to snap time values to and to calculate frame numbers + double m_curMouseX; + double m_curMouseY; + double m_maxTime; // the end time of the full time bar + double m_maxHeight; + double m_lastMaxHeight; + double m_timeScale; // the time zoom scale factor + double m_maxScale; + double m_minScale; + float m_totalTime; - double mTargetTimeScale; - double mTargetScrollX; + double m_targetTimeScale; + double m_targetScrollX; - bool mIsAnimating; - bool mDirty; + bool m_isAnimating; + bool m_dirty; - QCursor* mZoomInCursor; - QCursor* mZoomOutCursor; + QCursor* m_zoomInCursor; + QCursor* m_zoomOutCursor; - QPen mPenCurTimeHandle; - QPen mPenTimeHandles; - QPen mPenCurTimeHelper; - QBrush mBrushCurTimeHandle; + QPen m_penCurTimeHandle; + QPen m_penTimeHandles; + QPen m_penCurTimeHelper; + QBrush m_brushCurTimeHandle; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeViewToolBar.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeViewToolBar.cpp index 618d5f2bf5..d95b606b3f 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeViewToolBar.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeViewToolBar.cpp @@ -32,7 +32,7 @@ namespace EMStudio { setObjectName("TimeViewToolBar"); - mPlugin = plugin; + m_plugin = plugin; m_recorderGroup = new RecorderGroup(plugin, this); m_playbackControls = new PlaybackControlsGroup(this); @@ -75,7 +75,7 @@ namespace EMStudio void TimeViewToolBar::OnPlayForwardButton() { - switch (mPlugin->GetMode()) + switch (m_plugin->GetMode()) { case TimeViewMode::Motion: { @@ -179,11 +179,11 @@ namespace EMStudio const float newTime = MCore::Min(EMotionFX::GetRecorder().GetCurrentPlayTime() + (1.0f / 60.0f), EMotionFX::GetRecorder().GetRecordTime()); EMotionFX::GetRecorder().SetCurrentPlayTime(newTime); - if (mPlugin) + if (m_plugin) { - mPlugin->SetCurrentTime(newTime); - mPlugin->GetTimeInfoWidget()->update(); - mPlugin->SetRedrawFlag(); + m_plugin->SetCurrentTime(newTime); + m_plugin->GetTimeInfoWidget()->update(); + m_plugin->SetRedrawFlag(); } } @@ -195,11 +195,11 @@ namespace EMStudio const float newTime = MCore::Max(EMotionFX::GetRecorder().GetCurrentPlayTime() - (1.0f / 60.0f), 0.0f); EMotionFX::GetRecorder().SetCurrentPlayTime(newTime); - if (mPlugin) + if (m_plugin) { - mPlugin->SetCurrentTime(newTime); - mPlugin->GetTimeInfoWidget()->update(); - mPlugin->SetRedrawFlag(); + m_plugin->SetCurrentTime(newTime); + m_plugin->GetTimeInfoWidget()->update(); + m_plugin->SetRedrawFlag(); } emit RecorderStateChanged(); @@ -221,10 +221,10 @@ namespace EMStudio case RecorderGroup::PlaybackRecording: { EMotionFX::GetRecorder().SetCurrentPlayTime(EMotionFX::GetRecorder().GetRecordTime()); - if (mPlugin) + if (m_plugin) { - mPlugin->SetCurrentTime(EMotionFX::GetRecorder().GetCurrentPlayTime()); - mPlugin->SetRedrawFlag(); + m_plugin->SetCurrentTime(EMotionFX::GetRecorder().GetCurrentPlayTime()); + m_plugin->SetRedrawFlag(); } break; } @@ -251,10 +251,10 @@ namespace EMStudio case RecorderGroup::PlaybackRecording: { EMotionFX::GetRecorder().SetCurrentPlayTime(0.0f); - if (mPlugin) + if (m_plugin) { - mPlugin->SetCurrentTime(EMotionFX::GetRecorder().GetCurrentPlayTime()); - mPlugin->SetRedrawFlag(); + m_plugin->SetCurrentTime(EMotionFX::GetRecorder().GetCurrentPlayTime()); + m_plugin->SetRedrawFlag(); } break; } @@ -294,28 +294,28 @@ namespace EMStudio } EMotionFX::Recorder::RecordSettings settings; - settings.mFPS = 1000000; - settings.mRecordTransforms = true; - settings.mRecordAnimGraphStates = true; - settings.mRecordNodeHistory = true; - settings.mRecordScale = true; - settings.mInitialAnimGraphAnimBytes = 4 * 1024 * 1024; // 4 mb - settings.mHistoryStatesOnly = m_recorderGroup->GetRecordStatesOnly(); - settings.mRecordEvents = m_recorderGroup->GetRecordEvents(); + settings.m_fps = 1000000; + settings.m_recordTransforms = true; + settings.m_recordAnimGraphStates = true; + settings.m_recordNodeHistory = true; + settings.m_recordScale = true; + settings.m_initialAnimGraphAnimBytes = 4 * 1024 * 1024; // 4 mb + settings.m_historyStatesOnly = m_recorderGroup->GetRecordStatesOnly(); + settings.m_recordEvents = m_recorderGroup->GetRecordEvents(); if (m_recorderGroup->GetRecordMotionsOnly()) { - settings.mNodeHistoryTypes.insert(azrtti_typeid()); + settings.m_nodeHistoryTypes.insert(azrtti_typeid()); } EMotionFX::GetRecorder().StartRecording(settings); // reinit the time view plugin - if (mPlugin) + if (m_plugin) { - mPlugin->ReInit(); - mPlugin->SetScale(1.0); - mPlugin->SetScrollX(0); + m_plugin->ReInit(); + m_plugin->SetScale(1.0); + m_plugin->SetScrollX(0); } } else @@ -326,13 +326,13 @@ namespace EMStudio EMotionFX::GetRecorder().SetCurrentPlayTime(0.0f); // reinit the time view plugin - if (mPlugin) + if (m_plugin) { - mPlugin->ReInit(); - mPlugin->OnZoomAll(); - mPlugin->SetCurrentTime(0.0f); - mPlugin->GetTrackDataWidget()->setFocus(); - mPlugin->GetTrackDataHeaderWidget()->setFocus(); + m_plugin->ReInit(); + m_plugin->OnZoomAll(); + m_plugin->SetCurrentTime(0.0f); + m_plugin->GetTrackDataWidget()->setFocus(); + m_plugin->GetTrackDataHeaderWidget()->setFocus(); } } @@ -347,12 +347,12 @@ namespace EMStudio UpdateInterface(); // reinit the time view plugin - if (mPlugin) + if (m_plugin) { - mPlugin->ReInit(); - mPlugin->SetScale(1.0); - mPlugin->SetScrollX(0); - mPlugin->SetCurrentTime(0.0f); + m_plugin->ReInit(); + m_plugin->SetScale(1.0); + m_plugin->SetScrollX(0); + m_plugin->SetCurrentTime(0.0f); } emit RecorderStateChanged(); @@ -377,11 +377,11 @@ namespace EMStudio continue; } - EMotionFX::Motion* motion = entry->mMotion; + EMotionFX::Motion* motion = entry->m_motion; EMotionFX::PlayBackInfo* playbackInfo = motion->GetDefaultPlayBackInfo(); AZStd::string commandParameters; - if (MCore::Compare::CheckIfIsClose(playbackInfo->mPlaySpeed, m_playbackOptions->GetPlaySpeed(), 0.001f) == false) + if (MCore::Compare::CheckIfIsClose(playbackInfo->m_playSpeed, m_playbackOptions->GetPlaySpeed(), 0.001f) == false) { commandParameters += AZStd::string::format("-playSpeed %f ", m_playbackOptions->GetPlaySpeed()); } @@ -397,25 +397,25 @@ namespace EMStudio } const bool mirrorMotion = m_playbackOptions->GetMirrorMotion(); - if (playbackInfo->mMirrorMotion != mirrorMotion) + if (playbackInfo->m_mirrorMotion != mirrorMotion) { commandParameters += AZStd::string::format("-mirrorMotion %s ", AZStd::to_string(mirrorMotion).c_str()); } const EMotionFX::EPlayMode playMode = m_playbackOptions->GetPlayMode(); - if (playbackInfo->mPlayMode != playMode) + if (playbackInfo->m_playMode != playMode) { commandParameters += AZStd::string::format("-playMode %i ", static_cast(playMode)); } const bool inPlace = m_playbackOptions->GetInPlace(); - if (playbackInfo->mInPlace != inPlace) + if (playbackInfo->m_inPlace != inPlace) { commandParameters += AZStd::string::format("-inPlace %s ", AZStd::to_string(inPlace).c_str()); } const bool retarget = m_playbackOptions->GetRetarget(); - if (playbackInfo->mRetarget != retarget) + if (playbackInfo->m_retarget != retarget) { commandParameters += AZStd::string::format("-retarget %s ", AZStd::to_string(retarget).c_str()); } @@ -437,7 +437,7 @@ namespace EMStudio void TimeViewToolBar::UpdateInterface() { - const TimeViewMode mode = mPlugin->GetMode(); + const TimeViewMode mode = m_plugin->GetMode(); const bool playbackOptionsVisible = m_playbackOptions->UpdateInterface(mode, /*showRightSeparator=*/false); const bool playbackControlsVisible = m_playbackControls->UpdateInterface(mode, /*showRightSeparator=*/playbackOptionsVisible); @@ -446,15 +446,15 @@ namespace EMStudio void TimeViewToolBar::OnDetailedNodes() { - mPlugin->SetRedrawFlag(); + m_plugin->SetRedrawFlag(); if (!m_recorderGroup->GetDetailedNodes()) { - mPlugin->mTrackDataWidget->mNodeHistoryItemHeight = 20; + m_plugin->m_trackDataWidget->m_nodeHistoryItemHeight = 20; } else { - mPlugin->mTrackDataWidget->mNodeHistoryItemHeight = 35; + m_plugin->m_trackDataWidget->m_nodeHistoryItemHeight = 35; } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeViewToolBar.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeViewToolBar.h index 0e2abbc594..eda6337832 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeViewToolBar.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TimeViewToolBar.h @@ -63,7 +63,7 @@ namespace EMStudio RecorderGroup::RecordingMode GetCurrentRecordingMode() const; private: - TimeViewPlugin* mPlugin = nullptr; + TimeViewPlugin* m_plugin = nullptr; RecorderGroup* m_recorderGroup; PlaybackControlsGroup* m_playbackControls; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackDataHeaderWidget.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackDataHeaderWidget.cpp index a70a12dbeb..0d1f55c172 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackDataHeaderWidget.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackDataHeaderWidget.cpp @@ -49,46 +49,46 @@ namespace EMStudio TrackDataHeaderWidget::TrackDataHeaderWidget(TimeViewPlugin* plugin, QWidget* parent) : QOpenGLWidget(parent) , QOpenGLFunctions() - , mPlugin(plugin) - , mLastMouseX(0) - , mLastMouseY(0) - , mMouseLeftClicked(false) - , mMouseRightClicked(false) - , mMouseMidClicked(false) - , mIsScrolling(false) - , mAllowContextMenu(true) + , m_plugin(plugin) + , m_lastMouseX(0) + , m_lastMouseY(0) + , m_mouseLeftClicked(false) + , m_mouseRightClicked(false) + , m_mouseMidClicked(false) + , m_isScrolling(false) + , m_allowContextMenu(true) { setObjectName("TrackDataHeaderWidget"); // init brushes and pens - mBrushBackgroundOutOfRange = QBrush(QColor(35, 35, 35), Qt::SolidPattern); + m_brushBackgroundOutOfRange = QBrush(QColor(35, 35, 35), Qt::SolidPattern); - mHeaderGradientActive = QLinearGradient(0, 0, 0, 35); - mHeaderGradientActive.setColorAt(1.0f, QColor(100, 105, 110)); - mHeaderGradientActive.setColorAt(0.5f, QColor(30, 35, 40)); - mHeaderGradientActive.setColorAt(0.0f, QColor(20, 20, 20)); + m_headerGradientActive = QLinearGradient(0, 0, 0, 35); + m_headerGradientActive.setColorAt(1.0f, QColor(100, 105, 110)); + m_headerGradientActive.setColorAt(0.5f, QColor(30, 35, 40)); + m_headerGradientActive.setColorAt(0.0f, QColor(20, 20, 20)); - mHeaderGradientActiveFocus = QLinearGradient(0, 0, 0, 35); - mHeaderGradientActiveFocus.setColorAt(1.0f, QColor(100, 105, 130)); - mHeaderGradientActiveFocus.setColorAt(0.5f, QColor(30, 35, 40)); - mHeaderGradientActiveFocus.setColorAt(0.0f, QColor(20, 20, 20)); + m_headerGradientActiveFocus = QLinearGradient(0, 0, 0, 35); + m_headerGradientActiveFocus.setColorAt(1.0f, QColor(100, 105, 130)); + m_headerGradientActiveFocus.setColorAt(0.5f, QColor(30, 35, 40)); + m_headerGradientActiveFocus.setColorAt(0.0f, QColor(20, 20, 20)); - mHeaderGradientInactive = QLinearGradient(0, 0, 0, 35); - mHeaderGradientInactive.setColorAt(1.0f, QColor(30, 30, 30)); - mHeaderGradientInactive.setColorAt(0.0f, QColor(20, 20, 20)); + m_headerGradientInactive = QLinearGradient(0, 0, 0, 35); + m_headerGradientInactive.setColorAt(1.0f, QColor(30, 30, 30)); + m_headerGradientInactive.setColorAt(0.0f, QColor(20, 20, 20)); - mHeaderGradientInactiveFocus = QLinearGradient(0, 0, 0, 35); - mHeaderGradientInactiveFocus.setColorAt(1.0f, QColor(30, 30, 30)); - mHeaderGradientInactiveFocus.setColorAt(0.0f, QColor(20, 20, 20)); + m_headerGradientInactiveFocus = QLinearGradient(0, 0, 0, 35); + m_headerGradientInactiveFocus.setColorAt(1.0f, QColor(30, 30, 30)); + m_headerGradientInactiveFocus.setColorAt(0.0f, QColor(20, 20, 20)); - mPenMainTimeStepLinesActive = QPen(QColor(110, 110, 110)); + m_penMainTimeStepLinesActive = QPen(QColor(110, 110, 110)); - mTimeLineFont.setPixelSize(12); - mDataFont.setPixelSize(13); + m_timeLineFont.setPixelSize(12); + m_dataFont.setPixelSize(13); // load the time handle top image QDir imageName{ QString(MysticQt::GetMysticQt()->GetDataDir().c_str()) }; - mTimeHandleTop = QPixmap(imageName.filePath("Images/Icons/TimeHandleTop.png")); + m_timeHandleTop = QPixmap(imageName.filePath("Images/Icons/TimeHandleTop.png")); setMouseTracking(true); setAcceptDrops(true); @@ -117,9 +117,9 @@ namespace EMStudio { MCORE_UNUSED(w); MCORE_UNUSED(h); - if (mPlugin) + if (m_plugin) { - mPlugin->SetRedrawFlag(); + m_plugin->SetRedrawFlag(); } } @@ -135,16 +135,16 @@ namespace EMStudio // draw a background rect painter.setPen(Qt::NoPen); - painter.setBrush(mBrushBackgroundOutOfRange); + painter.setBrush(m_brushBackgroundOutOfRange); painter.drawRect(rect); - painter.setFont(mDataFont); + painter.setFont(m_dataFont); // draw the timeline painter.setRenderHint(QPainter::Antialiasing, false); DrawTimeLine(painter, rect); const uint32 height = geometry().height(); - mPlugin->RenderElementTimeHandles(painter, height, mPlugin->mPenTimeHandles); + m_plugin->RenderElementTimeHandles(painter, height, m_plugin->m_penTimeHandles); DrawTimeMarker(painter, rect); } @@ -154,10 +154,10 @@ namespace EMStudio { // draw the current time marker float startHeight = 0.0f; - const float curTimeX = aznumeric_cast(mPlugin->TimeToPixel(mPlugin->mCurTime)); - painter.drawPixmap(aznumeric_cast(curTimeX - (mTimeHandleTop.width() / 2) - 1), 0, mTimeHandleTop); + const float curTimeX = aznumeric_cast(m_plugin->TimeToPixel(m_plugin->m_curTime)); + painter.drawPixmap(aznumeric_cast(curTimeX - (m_timeHandleTop.width() / 2) - 1), 0, m_timeHandleTop); - painter.setPen(mPlugin->mPenCurTimeHandle); + painter.setPen(m_plugin->m_penCurTimeHandle); painter.drawLine(QPointF(curTimeX, startHeight), QPointF(curTimeX, rect.bottom())); } @@ -169,52 +169,52 @@ namespace EMStudio } // if double clicked in the timeline - mPlugin->MakeTimeVisible(mPlugin->PixelToTime(event->x()), 0.5); + m_plugin->MakeTimeVisible(m_plugin->PixelToTime(event->x()), 0.5); } // when the mouse is moving, while a button is pressed void TrackDataHeaderWidget::mouseMoveEvent(QMouseEvent* event) { - mPlugin->SetRedrawFlag(); + m_plugin->SetRedrawFlag(); - const int32 deltaRelX = event->x() - mLastMouseX; - mLastMouseX = event->x(); - mPlugin->mCurMouseX = event->x(); - mPlugin->mCurMouseY = event->y(); + const int32 deltaRelX = event->x() - m_lastMouseX; + m_lastMouseX = event->x(); + m_plugin->m_curMouseX = event->x(); + m_plugin->m_curMouseY = event->y(); - const int32 deltaRelY = event->y() - mLastMouseY; - mLastMouseY = event->y(); + const int32 deltaRelY = event->y() - m_lastMouseY; + m_lastMouseY = event->y(); const bool altPressed = event->modifiers() & Qt::AltModifier; - const bool isZooming = mMouseLeftClicked == false && mMouseRightClicked && altPressed; - const bool isPanning = mMouseLeftClicked == false && isZooming == false && (mMouseMidClicked || mMouseRightClicked); + const bool isZooming = m_mouseLeftClicked == false && m_mouseRightClicked && altPressed; + const bool isPanning = m_mouseLeftClicked == false && isZooming == false && (m_mouseMidClicked || m_mouseRightClicked); if (deltaRelY != 0) { - mAllowContextMenu = false; + m_allowContextMenu = false; } - if (mMouseRightClicked) + if (m_mouseRightClicked) { - mIsScrolling = true; + m_isScrolling = true; } // if the mouse left button is pressed - if (mMouseLeftClicked) + if (m_mouseLeftClicked) { // update the current time marker int newX = event->x(); newX = AZ::GetClamp(newX, 0, geometry().width() - 1); - mPlugin->mCurTime = mPlugin->PixelToTime(newX); + m_plugin->m_curTime = m_plugin->PixelToTime(newX); EMotionFX::Recorder& recorder = EMotionFX::GetRecorder(); if (recorder.GetRecordTime() > AZ::Constants::FloatEpsilon) { if (recorder.GetIsInPlayMode()) { - recorder.SetCurrentPlayTime(aznumeric_cast(mPlugin->GetCurrentTime())); + recorder.SetCurrentPlayTime(aznumeric_cast(m_plugin->GetCurrentTime())); recorder.SetAutoPlay(false); - emit mPlugin->ManualTimeChange(aznumeric_cast(mPlugin->GetCurrentTime())); + emit m_plugin->ManualTimeChange(aznumeric_cast(m_plugin->GetCurrentTime())); } } else @@ -223,33 +223,33 @@ namespace EMStudio if (motionInstances.size() == 1) { EMotionFX::MotionInstance* motionInstance = motionInstances[0]; - motionInstance->SetCurrentTime(aznumeric_cast(mPlugin->GetCurrentTime()), false); + motionInstance->SetCurrentTime(aznumeric_cast(m_plugin->GetCurrentTime()), false); motionInstance->SetPause(true); - emit mPlugin->ManualTimeChange(aznumeric_cast(mPlugin->GetCurrentTime())); + emit m_plugin->ManualTimeChange(aznumeric_cast(m_plugin->GetCurrentTime())); } } - mIsScrolling = true; + m_isScrolling = true; } else if (isPanning) { if (EMotionFX::GetRecorder().GetIsRecording() == false) { - mPlugin->DeltaScrollX(-deltaRelX, false); + m_plugin->DeltaScrollX(-deltaRelX, false); } } else if (isZooming) { if (deltaRelY < 0) { - setCursor(*(mPlugin->GetZoomOutCursor())); + setCursor(*(m_plugin->GetZoomOutCursor())); } else { - setCursor(*(mPlugin->GetZoomInCursor())); + setCursor(*(m_plugin->GetZoomInCursor())); } - DoMouseYMoveZoom(deltaRelY, mPlugin); + DoMouseYMoveZoom(deltaRelY, m_plugin); } else // no left mouse button is pressed { @@ -275,43 +275,43 @@ namespace EMStudio void TrackDataHeaderWidget::UpdateMouseOverCursor() { // disable all tooltips - mPlugin->DisableAllToolTips(); + m_plugin->DisableAllToolTips(); } // when the mouse is pressed void TrackDataHeaderWidget::mousePressEvent(QMouseEvent* event) { - mPlugin->SetRedrawFlag(); + m_plugin->SetRedrawFlag(); const bool ctrlPressed = event->modifiers() & Qt::ControlModifier; const bool shiftPressed = event->modifiers() & Qt::ShiftModifier; const bool altPressed = event->modifiers() & Qt::AltModifier; // store the last clicked position - mAllowContextMenu = true; + m_allowContextMenu = true; if (event->button() == Qt::RightButton) { - mMouseRightClicked = true; + m_mouseRightClicked = true; } if (event->button() == Qt::MidButton) { - mMouseMidClicked = true; + m_mouseMidClicked = true; } if (event->button() == Qt::LeftButton) { - mMouseLeftClicked = true; + m_mouseLeftClicked = true; EMotionFX::Recorder& recorder = EMotionFX::GetRecorder(); - if (!mPlugin->mNodeHistoryItem && !altPressed) + if (!m_plugin->m_nodeHistoryItem && !altPressed) { // update the current time marker int newX = event->x(); newX = AZ::GetClamp(newX, 0, geometry().width() - 1); - mPlugin->mCurTime = mPlugin->PixelToTime(newX); + m_plugin->m_curTime = m_plugin->PixelToTime(newX); if (recorder.GetRecordTime() > AZ::Constants::FloatEpsilon) { @@ -320,10 +320,10 @@ namespace EMStudio recorder.StartPlayBack(); } - recorder.SetCurrentPlayTime(aznumeric_cast(mPlugin->GetCurrentTime())); + recorder.SetCurrentPlayTime(aznumeric_cast(m_plugin->GetCurrentTime())); recorder.SetAutoPlay(false); - emit mPlugin->ManualTimeChangeStart(aznumeric_cast(mPlugin->GetCurrentTime())); - emit mPlugin->ManualTimeChange(aznumeric_cast(mPlugin->GetCurrentTime())); + emit m_plugin->ManualTimeChangeStart(aznumeric_cast(m_plugin->GetCurrentTime())); + emit m_plugin->ManualTimeChange(aznumeric_cast(m_plugin->GetCurrentTime())); } else { @@ -331,19 +331,19 @@ namespace EMStudio if (motionInstances.size() == 1) { EMotionFX::MotionInstance* motionInstance = motionInstances[0]; - motionInstance->SetCurrentTime(aznumeric_cast(mPlugin->GetCurrentTime()), false); + motionInstance->SetCurrentTime(aznumeric_cast(m_plugin->GetCurrentTime()), false); motionInstance->SetPause(true); - mPlugin->GetTimeViewToolBar()->UpdateInterface(); - emit mPlugin->ManualTimeChangeStart(aznumeric_cast(mPlugin->GetCurrentTime())); - emit mPlugin->ManualTimeChange(aznumeric_cast(mPlugin->GetCurrentTime())); + m_plugin->GetTimeViewToolBar()->UpdateInterface(); + emit m_plugin->ManualTimeChangeStart(aznumeric_cast(m_plugin->GetCurrentTime())); + emit m_plugin->ManualTimeChange(aznumeric_cast(m_plugin->GetCurrentTime())); } } } } //const bool altPressed = event->modifiers() & Qt::AltModifier; - const bool isZooming = mMouseLeftClicked == false && mMouseRightClicked && altPressed; - const bool isPanning = mMouseLeftClicked == false && isZooming == false && (mMouseMidClicked || mMouseRightClicked); + const bool isZooming = m_mouseLeftClicked == false && m_mouseRightClicked && altPressed; + const bool isPanning = m_mouseLeftClicked == false && isZooming == false && (m_mouseMidClicked || m_mouseRightClicked); if (isPanning) { @@ -352,7 +352,7 @@ namespace EMStudio if (isZooming) { - setCursor(*(mPlugin->GetZoomInCursor())); + setCursor(*(m_plugin->GetZoomInCursor())); } } @@ -360,33 +360,33 @@ namespace EMStudio // when releasing the mouse button void TrackDataHeaderWidget::mouseReleaseEvent(QMouseEvent* event) { - mPlugin->SetRedrawFlag(); + m_plugin->SetRedrawFlag(); setCursor(Qt::ArrowCursor); // disable overwrite mode in any case when the mouse gets released so that we display the current time from the plugin again - if (mPlugin->GetTimeInfoWidget()) + if (m_plugin->GetTimeInfoWidget()) { - mPlugin->GetTimeInfoWidget()->SetIsOverwriteMode(false); + m_plugin->GetTimeInfoWidget()->SetIsOverwriteMode(false); } const bool ctrlPressed = event->modifiers() & Qt::ControlModifier; if (event->button() == Qt::RightButton) { - mMouseRightClicked = false; - mIsScrolling = false; + m_mouseRightClicked = false; + m_isScrolling = false; } if (event->button() == Qt::MidButton) { - mMouseMidClicked = false; + m_mouseMidClicked = false; } if (event->button() == Qt::LeftButton) { - mMouseLeftClicked = false; - mIsScrolling = false; + m_mouseLeftClicked = false; + m_isScrolling = false; return; } @@ -397,7 +397,7 @@ namespace EMStudio // drag & drop support void TrackDataHeaderWidget::dragEnterEvent(QDragEnterEvent* event) { - mPlugin->SetRedrawFlag(); + m_plugin->SetRedrawFlag(); // this is needed to actually reach the drop event function event->acceptProposedAction(); @@ -444,16 +444,16 @@ namespace EMStudio // handle mouse wheel event void TrackDataHeaderWidget::wheelEvent(QWheelEvent* event) { - DoWheelEvent(event, mPlugin); + DoWheelEvent(event, m_plugin); } void TrackDataHeaderWidget::dragMoveEvent(QDragMoveEvent* event) { - mPlugin->SetRedrawFlag(); + m_plugin->SetRedrawFlag(); QPoint mousePos = event->pos(); - double dropTime = mPlugin->PixelToTime(mousePos.x()); - mPlugin->SetCurrentTime(dropTime); + double dropTime = m_plugin->PixelToTime(mousePos.x()); + m_plugin->SetCurrentTime(dropTime); const AZStd::vector& motionInstances = MotionWindowPlugin::GetSelectedMotionInstances(); if (motionInstances.size() == 1) @@ -470,9 +470,9 @@ namespace EMStudio // propagate key events to the plugin and let it handle by a shared function void TrackDataHeaderWidget::keyPressEvent(QKeyEvent* event) { - if (mPlugin) + if (m_plugin) { - mPlugin->OnKeyPressEvent(event); + m_plugin->OnKeyPressEvent(event); } } @@ -480,9 +480,9 @@ namespace EMStudio // propagate key events to the plugin and let it handle by a shared function void TrackDataHeaderWidget::keyReleaseEvent(QKeyEvent* event) { - if (mPlugin) + if (m_plugin) { - mPlugin->OnKeyReleaseEvent(event); + m_plugin->OnKeyReleaseEvent(event); } } @@ -493,12 +493,11 @@ namespace EMStudio double animationLength = 0.0; double clipStart = 0.0; double clipEnd = 0.0; - mPlugin->GetDataTimes(&animationLength, &clipStart, &clipEnd); + m_plugin->GetDataTimes(&animationLength, &clipStart, &clipEnd); // calculate the pixel offsets - double animEndPixel = mPlugin->TimeToPixel(animationLength); - double clipStartPixel = mPlugin->TimeToPixel(clipStart); - //double clipEndPixel = mPlugin->TimeToPixel(clipEnd); + double animEndPixel = m_plugin->TimeToPixel(animationLength); + double clipStartPixel = m_plugin->TimeToPixel(clipStart); // fill with the background color QRect motionRect = rect; @@ -511,16 +510,16 @@ namespace EMStudio painter.setPen(Qt::NoPen); if (hasFocus() == false) { - painter.setBrush(mHeaderGradientActive); + painter.setBrush(m_headerGradientActive); painter.drawRect(motionRect); - painter.setBrush(mHeaderGradientInactive); + painter.setBrush(m_headerGradientInactive); painter.drawRect(outOfRangeRect); } else { - painter.setBrush(mHeaderGradientActiveFocus); + painter.setBrush(m_headerGradientActiveFocus); painter.drawRect(motionRect); - painter.setBrush(mHeaderGradientInactiveFocus); + painter.setBrush(m_headerGradientInactiveFocus); painter.drawRect(outOfRangeRect); } @@ -529,7 +528,7 @@ namespace EMStudio if (recorder.GetRecordTime() > MCore::Math::epsilon) { QRectF recorderRect = rect; - recorderRect.setRight(mPlugin->TimeToPixel(recorder.GetRecordTime())); + recorderRect.setRight(m_plugin->TimeToPixel(recorder.GetRecordTime())); recorderRect.setTop(height() - 3); recorderRect.setBottom(height()); @@ -542,7 +541,7 @@ namespace EMStudio if (animationLength > MCore::Math::epsilon) { QRectF rangeRect = rect; - rangeRect.setRight(mPlugin->TimeToPixel(animationLength)); + rangeRect.setRight(m_plugin->TimeToPixel(animationLength)); rangeRect.setTop(height() - 3); rangeRect.setBottom(height()); @@ -554,21 +553,16 @@ namespace EMStudio QTextOption options; options.setAlignment(Qt::AlignCenter); - painter.setFont(mTimeLineFont); + painter.setFont(m_timeLineFont); const uint32 width = rect.width(); //const uint32 height = rect.height(); float yOffset = 19.0f; - //const double pixelsPerSecond = mPlugin->mPixelsPerSecond; - - double timeOffset = mPlugin->PixelToTime(0.0) * 1000.0; + double timeOffset = m_plugin->PixelToTime(0.0) * 1000.0; timeOffset = (timeOffset - ((int32)timeOffset % 5000)) / 1000.0; - //if (rand() % 10 == 0) - //MCore::LogInfo("%f", mPlugin->mTimeScale); - uint32 minutes, seconds, milSecs, frameNumber; double pixelTime; @@ -578,35 +572,34 @@ namespace EMStudio //uint32 index = 0; while (curX <= width) { - curX = mPlugin->TimeToPixel(curTime, false); - mPlugin->CalcTime(curX, &pixelTime, &minutes, &seconds, &milSecs, &frameNumber, false); + curX = m_plugin->TimeToPixel(curTime, false); + m_plugin->CalcTime(curX, &pixelTime, &minutes, &seconds, &milSecs, &frameNumber, false); seconds += minutes * 60; - curX *= mPlugin->mTimeScale; + curX *= m_plugin->m_timeScale; curTime += 5.0; - painter.setPen(mPenMainTimeStepLinesActive); + painter.setPen(m_penMainTimeStepLinesActive); painter.drawLine(QPointF(curX, yOffset - 3.0f), QPointF(curX, yOffset + 10.0f)); - mTimeString = AZStd::string::format("%.2d:%.2d", seconds, milSecs); // will only do an allocation once, reuses the memory + m_timeString = AZStd::string::format("%.2d:%.2d", seconds, milSecs); // will only do an allocation once, reuses the memory - //painter.setPen( mPenText ); painter.setPen(QColor(175, 175, 175)); - painter.drawText(QRect(aznumeric_cast(curX - 25), aznumeric_cast(yOffset - 23), 52, 20), mTimeString.c_str(), options); + painter.drawText(QRect(aznumeric_cast(curX - 25), aznumeric_cast(yOffset - 23), 52, 20), m_timeString.c_str(), options); } // draw the seconds curTime = timeOffset; - if (mPlugin->mTimeScale >= 0.25) + if (m_plugin->m_timeScale >= 0.25) { uint32 index = 0; curX = 0.0; while (curX <= width) { - curX = mPlugin->TimeToPixel(curTime, false); - mPlugin->CalcTime(curX, &pixelTime, &minutes, &seconds, &milSecs, &frameNumber, false); + curX = m_plugin->TimeToPixel(curTime, false); + m_plugin->CalcTime(curX, &pixelTime, &minutes, &seconds, &milSecs, &frameNumber, false); seconds += minutes * 60; - curX *= mPlugin->mTimeScale; + curX *= m_plugin->m_timeScale; curTime += 1.0; if (index % 5 == 0) @@ -618,8 +611,8 @@ namespace EMStudio if (curX > -100 && curX < width + 100) { - painter.setPen(mPenMainTimeStepLinesActive); - if (mPlugin->mTimeScale < 0.9) + painter.setPen(m_penMainTimeStepLinesActive); + if (m_plugin->m_timeScale < 0.9) { painter.drawLine(QPointF(curX, yOffset - 1.0f), QPointF(curX, yOffset + 5.0f)); } @@ -628,11 +621,11 @@ namespace EMStudio painter.drawLine(QPointF(curX, yOffset - 3.0f), QPointF(curX, yOffset + 10.0f)); } - if (mPlugin->mTimeScale >= 0.48) + if (m_plugin->m_timeScale >= 0.48) { - mTimeString = AZStd::string::format("%.2d:%.2d", seconds, milSecs); // will only do an allocation once, reuses the memory + m_timeString = AZStd::string::format("%.2d:%.2d", seconds, milSecs); // will only do an allocation once, reuses the memory - float alpha = aznumeric_cast((mPlugin->mTimeScale - 0.48f) / 1.0f); + float alpha = aznumeric_cast((m_plugin->m_timeScale - 0.48f) / 1.0f); alpha *= 2; if (alpha > 1.0f) { @@ -640,7 +633,7 @@ namespace EMStudio } painter.setPen(QColor(200, 200, 200, aznumeric_cast(alpha * 255))); - painter.drawText(QRect(aznumeric_cast(curX - 25), aznumeric_cast(yOffset - 23), 52, 20), mTimeString.c_str(), options); + painter.drawText(QRect(aznumeric_cast(curX - 25), aznumeric_cast(yOffset - 23), 52, 20), m_timeString.c_str(), options); } } } @@ -648,16 +641,16 @@ namespace EMStudio // 500 ms curTime = timeOffset; - if (mPlugin->mTimeScale >= 0.1) + if (m_plugin->m_timeScale >= 0.1) { uint32 index = 0; curX = 0; while (curX <= width) { - curX = mPlugin->TimeToPixel(curTime, false); - mPlugin->CalcTime(curX, &pixelTime, &minutes, &seconds, &milSecs, &frameNumber, false); + curX = m_plugin->TimeToPixel(curTime, false); + m_plugin->CalcTime(curX, &pixelTime, &minutes, &seconds, &milSecs, &frameNumber, false); seconds += minutes * 60; - curX *= mPlugin->mTimeScale; + curX *= m_plugin->m_timeScale; curTime += 0.5; if (index % 2 == 0) @@ -669,10 +662,10 @@ namespace EMStudio if (curX > -100 && curX < width + 100) { - painter.setPen(mPenMainTimeStepLinesActive); - if (mPlugin->mTimeScale < 1.5) + painter.setPen(m_penMainTimeStepLinesActive); + if (m_plugin->m_timeScale < 1.5) { - if (mPlugin->mTimeScale < 1.0) + if (m_plugin->m_timeScale < 1.0) { painter.drawLine(QPointF(curX, yOffset - 1.0f), QPointF(curX, yOffset + 1.0f)); } @@ -686,19 +679,18 @@ namespace EMStudio painter.drawLine(QPointF(curX, yOffset - 3.0f), QPointF(curX, yOffset + 10.0f)); } - if (mPlugin->mTimeScale >= 2.0f) + if (m_plugin->m_timeScale >= 2.0f) { - mTimeString = AZStd::string::format("%.2d:%.2d", seconds, milSecs); // will only do an allocation once, reuses the memory + m_timeString = AZStd::string::format("%.2d:%.2d", seconds, milSecs); // will only do an allocation once, reuses the memory - float alpha = aznumeric_cast((mPlugin->mTimeScale - 2.0f) / 2.0f); + float alpha = aznumeric_cast((m_plugin->m_timeScale - 2.0f) / 2.0f); if (alpha > 1.0f) { alpha = 1.0; } - //painter.setPen( mPenText ); painter.setPen(QColor(175, 175, 175, aznumeric_cast(alpha * 255))); - painter.drawText(QRect(aznumeric_cast(curX - 25), aznumeric_cast(yOffset - 23), 52, 20), mTimeString.c_str(), options); + painter.drawText(QRect(aznumeric_cast(curX - 25), aznumeric_cast(yOffset - 23), 52, 20), m_timeString.c_str(), options); } } } @@ -706,7 +698,7 @@ namespace EMStudio // 100 ms curTime = timeOffset; - if (mPlugin->mTimeScale >= 0.95f) + if (m_plugin->m_timeScale >= 0.95f) { uint32 index = 0; curX = 0; @@ -717,10 +709,10 @@ namespace EMStudio index = 1; } - curX = mPlugin->TimeToPixel(curTime, false); - mPlugin->CalcTime(curX, &pixelTime, &minutes, &seconds, &milSecs, &frameNumber, false); + curX = m_plugin->TimeToPixel(curTime, false); + m_plugin->CalcTime(curX, &pixelTime, &minutes, &seconds, &milSecs, &frameNumber, false); seconds += minutes * 60; - curX *= mPlugin->mTimeScale; + curX *= m_plugin->m_timeScale; curTime += 0.1; if (index == 0 || index == 5 || index == 10) @@ -733,40 +725,40 @@ namespace EMStudio if (curX > -100 && curX < width + 100) { - painter.setPen(mPenMainTimeStepLinesActive); + painter.setPen(m_penMainTimeStepLinesActive); painter.drawLine(QPointF(curX, yOffset), QPointF(curX, yOffset + 3.0f)); - if (mPlugin->mTimeScale >= 11.0f) + if (m_plugin->m_timeScale >= 11.0f) { - float alpha = aznumeric_cast((mPlugin->mTimeScale - 11.0f) / 4.0f); + float alpha = aznumeric_cast((m_plugin->m_timeScale - 11.0f) / 4.0f); if (alpha > 1.0f) { alpha = 1.0; } - mTimeString = AZStd::string::format("%.2d:%.2d", seconds, milSecs); // will only do an allocation once, reuses the memory + m_timeString = AZStd::string::format("%.2d:%.2d", seconds, milSecs); // will only do an allocation once, reuses the memory painter.setPen(QColor(110, 110, 110, aznumeric_cast(alpha * 255))); - painter.drawText(QRect(aznumeric_cast(curX - 25), aznumeric_cast(yOffset - 23), 52, 20), mTimeString.c_str(), options); + painter.drawText(QRect(aznumeric_cast(curX - 25), aznumeric_cast(yOffset - 23), 52, 20), m_timeString.c_str(), options); } } } } - timeOffset = mPlugin->PixelToTime(0.0) * 1000.0; + timeOffset = m_plugin->PixelToTime(0.0) * 1000.0; timeOffset = (timeOffset - ((int32)timeOffset % 1000)) / 1000.0; // 50 ms curTime = timeOffset; - if (mPlugin->mTimeScale >= 1.9) + if (m_plugin->m_timeScale >= 1.9) { uint32 index = 0; curX = 0; while (curX <= width) { - curX = mPlugin->TimeToPixel(curTime, false); - mPlugin->CalcTime(curX, &pixelTime, &minutes, &seconds, &milSecs, &frameNumber, false); + curX = m_plugin->TimeToPixel(curTime, false); + m_plugin->CalcTime(curX, &pixelTime, &minutes, &seconds, &milSecs, &frameNumber, false); seconds += minutes * 60; - curX *= mPlugin->mTimeScale; + curX *= m_plugin->m_timeScale; curTime += 0.05; if (index % 2 == 0) @@ -779,21 +771,20 @@ namespace EMStudio if (curX > -100 && curX < width + 100) { - painter.setPen(mPenMainTimeStepLinesActive); + painter.setPen(m_penMainTimeStepLinesActive); painter.drawLine(QPointF(curX, yOffset), QPointF(curX, yOffset + 1.0f)); - if (mPlugin->mTimeScale >= 25.0f) + if (m_plugin->m_timeScale >= 25.0f) { - float alpha = aznumeric_cast((mPlugin->mTimeScale - 25.0f) / 6.0f); + float alpha = aznumeric_cast((m_plugin->m_timeScale - 25.0f) / 6.0f); if (alpha > 1.0f) { alpha = 1.0; } - mTimeString = AZStd::string::format("%.2d:%.2d", seconds, milSecs); // will only do an allocation once, reuses the memory - //painter.setPen( mPenText ); + m_timeString = AZStd::string::format("%.2d:%.2d", seconds, milSecs); // will only do an allocation once, reuses the memory painter.setPen(QColor(80, 80, 80, aznumeric_cast(alpha * 255))); - painter.drawText(QRect(aznumeric_cast(curX - 25), aznumeric_cast(yOffset - 23), 52, 20), mTimeString.c_str(), options); + painter.drawText(QRect(aznumeric_cast(curX - 25), aznumeric_cast(yOffset - 23), 52, 20), m_timeString.c_str(), options); } } } @@ -802,15 +793,15 @@ namespace EMStudio // 10 ms curTime = timeOffset; - if (mPlugin->mTimeScale >= 7.9) + if (m_plugin->m_timeScale >= 7.9) { uint32 index = 0; curX = 0; while (curX <= width) { - curX = mPlugin->TimeToPixel(curTime, false); - mPlugin->CalcTime(curX, &pixelTime, &minutes, &seconds, &milSecs, &frameNumber, false); - curX *= mPlugin->mTimeScale; + curX = m_plugin->TimeToPixel(curTime, false); + m_plugin->CalcTime(curX, &pixelTime, &minutes, &seconds, &milSecs, &frameNumber, false); + curX *= m_plugin->m_timeScale; curTime += 0.01; if (index % 5 == 0) @@ -824,21 +815,20 @@ namespace EMStudio if (curX > -100 && curX < width + 100) { //MCore::LogInfo("%f", curX); - painter.setPen(mPenMainTimeStepLinesActive); + painter.setPen(m_penMainTimeStepLinesActive); painter.drawLine(QPointF(curX, yOffset), QPointF(curX, yOffset + 1.0f)); - if (mPlugin->mTimeScale >= 65.0) + if (m_plugin->m_timeScale >= 65.0) { - float alpha = aznumeric_cast((mPlugin->mTimeScale - 65.0f) / 5.0f); + float alpha = aznumeric_cast((m_plugin->m_timeScale - 65.0f) / 5.0f); if (alpha > 1.0f) { alpha = 1.0; } - mTimeString = AZStd::string::format("%.2d:%.2d", seconds, milSecs); // will only do an allocation once, reuses the memory - //painter.setPen( mPenText ); + m_timeString = AZStd::string::format("%.2d:%.2d", seconds, milSecs); // will only do an allocation once, reuses the memory painter.setPen(QColor(60, 60, 60, aznumeric_cast(alpha * 255))); - painter.drawText(QRect(aznumeric_cast(curX - 25), aznumeric_cast(yOffset - 23), 52, 20), mTimeString.c_str(), options); + painter.drawText(QRect(aznumeric_cast(curX - 25), aznumeric_cast(yOffset - 23), 52, 20), m_timeString.c_str(), options); } } } @@ -855,10 +845,10 @@ namespace EMStudio // Timeline actions //--------------------- QAction* action = menu.addAction("Zoom To Fit All"); - connect(action, &QAction::triggered, mPlugin, &TimeViewPlugin::OnZoomAll); + connect(action, &QAction::triggered, m_plugin, &TimeViewPlugin::OnZoomAll); action = menu.addAction("Reset Timeline"); - connect(action, &QAction::triggered, mPlugin, &TimeViewPlugin::OnResetTimeline); + connect(action, &QAction::triggered, m_plugin, &TimeViewPlugin::OnResetTimeline); // show the menu at the given position menu.exec(event->globalPos()); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackDataHeaderWidget.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackDataHeaderWidget.h index 30fa3a741e..16d6171e4b 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackDataHeaderWidget.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackDataHeaderWidget.h @@ -57,26 +57,26 @@ namespace EMStudio void keyReleaseEvent(QKeyEvent* event) override; private: - QBrush mBrushBackgroundOutOfRange; - TimeViewPlugin* mPlugin; - bool mMouseLeftClicked; - bool mMouseMidClicked; - bool mMouseRightClicked; - bool mIsScrolling; - int32 mLastMouseX; - int32 mLastMouseY; - bool mAllowContextMenu; + QBrush m_brushBackgroundOutOfRange; + TimeViewPlugin* m_plugin; + bool m_mouseLeftClicked; + bool m_mouseMidClicked; + bool m_mouseRightClicked; + bool m_isScrolling; + int32 m_lastMouseX; + int32 m_lastMouseY; + bool m_allowContextMenu; - QPixmap mTimeHandleTop; + QPixmap m_timeHandleTop; - QFont mTimeLineFont; - QFont mDataFont; - AZStd::string mTimeString; - QLinearGradient mHeaderGradientActive; - QLinearGradient mHeaderGradientInactive; - QLinearGradient mHeaderGradientActiveFocus; - QLinearGradient mHeaderGradientInactiveFocus; - QPen mPenMainTimeStepLinesActive; + QFont m_timeLineFont; + QFont m_dataFont; + AZStd::string m_timeString; + QLinearGradient m_headerGradientActive; + QLinearGradient m_headerGradientInactive; + QLinearGradient m_headerGradientActiveFocus; + QLinearGradient m_headerGradientInactiveFocus; + QPen m_penMainTimeStepLinesActive; void UpdateMouseOverCursor(); void DrawTimeLine(QPainter& painter, const QRect& rect); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackDataWidget.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackDataWidget.cpp index 06569b3bf3..6c2ab60010 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackDataWidget.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackDataWidget.cpp @@ -55,37 +55,37 @@ namespace EMStudio TrackDataWidget::TrackDataWidget(TimeViewPlugin* plugin, QWidget* parent) : QOpenGLWidget(parent) , QOpenGLFunctions() - , mBrushBackground(QColor(40, 45, 50), Qt::SolidPattern) - , mBrushBackgroundClipped(QColor(40, 40, 40), Qt::SolidPattern) - , mBrushBackgroundOutOfRange(QColor(35, 35, 35), Qt::SolidPattern) - , mPlugin(plugin) - , mMouseLeftClicked(false) - , mMouseMidClicked(false) - , mMouseRightClicked(false) - , mDragging(false) - , mResizing(false) - , mRectZooming(false) - , mIsScrolling(false) - , mLastLeftClickedX(0) - , mLastMouseMoveX(0) - , mLastMouseX(0) - , mLastMouseY(0) - , mNodeHistoryItemHeight(20) - , mEventHistoryTotalHeight(0) - , mAllowContextMenu(true) - , mDraggingElement(nullptr) - , mDragElementTrack(nullptr) - , mResizeElement(nullptr) - , mGraphStartHeight(0) - , mEventsStartHeight(0) - , mNodeRectsStartHeight(0) - , mSelectStart(0, 0) - , mSelectEnd(0, 0) - , mRectSelecting(false) + , m_brushBackground(QColor(40, 45, 50), Qt::SolidPattern) + , m_brushBackgroundClipped(QColor(40, 40, 40), Qt::SolidPattern) + , m_brushBackgroundOutOfRange(QColor(35, 35, 35), Qt::SolidPattern) + , m_plugin(plugin) + , m_mouseLeftClicked(false) + , m_mouseMidClicked(false) + , m_mouseRightClicked(false) + , m_dragging(false) + , m_resizing(false) + , m_rectZooming(false) + , m_isScrolling(false) + , m_lastLeftClickedX(0) + , m_lastMouseMoveX(0) + , m_lastMouseX(0) + , m_lastMouseY(0) + , m_nodeHistoryItemHeight(20) + , m_eventHistoryTotalHeight(0) + , m_allowContextMenu(true) + , m_draggingElement(nullptr) + , m_dragElementTrack(nullptr) + , m_resizeElement(nullptr) + , m_graphStartHeight(0) + , m_eventsStartHeight(0) + , m_nodeRectsStartHeight(0) + , m_selectStart(0, 0) + , m_selectEnd(0, 0) + , m_rectSelecting(false) { setObjectName("TrackDataWidget"); - mDataFont.setPixelSize(13); + m_dataFont.setPixelSize(13); setMouseTracking(true); setAcceptDrops(true); @@ -114,9 +114,9 @@ namespace EMStudio { MCORE_UNUSED(w); MCORE_UNUSED(h); - if (mPlugin) + if (m_plugin) { - mPlugin->SetRedrawFlag(); + m_plugin->SetRedrawFlag(); } } @@ -124,10 +124,10 @@ namespace EMStudio // calculate the selection rect void TrackDataWidget::CalcSelectRect(QRect& outRect) { - const int32 startX = MCore::Min(mSelectStart.x(), mSelectEnd.x()); - const int32 startY = MCore::Min(mSelectStart.y(), mSelectEnd.y()); - const int32 width = abs(mSelectEnd.x() - mSelectStart.x()); - const int32 height = abs(mSelectEnd.y() - mSelectStart.y()); + const int32 startX = MCore::Min(m_selectStart.x(), m_selectEnd.x()); + const int32 startY = MCore::Min(m_selectStart.y(), m_selectEnd.y()); + const int32 width = abs(m_selectEnd.x() - m_selectStart.x()); + const int32 height = abs(m_selectEnd.y() - m_selectStart.y()); outRect = QRect(startX, startY, width, height); } @@ -145,12 +145,12 @@ namespace EMStudio // draw a background rect painter.setPen(Qt::NoPen); - painter.setBrush(mBrushBackgroundOutOfRange); + painter.setBrush(m_brushBackgroundOutOfRange); painter.drawRect(rect); - painter.setFont(mDataFont); + painter.setFont(m_dataFont); // if there is a recording show that, otherwise show motion tracks - switch (mPlugin->GetMode()) + switch (m_plugin->GetMode()) { case TimeViewMode::AnimGraph: { @@ -170,18 +170,18 @@ namespace EMStudio painter.setRenderHint(QPainter::Antialiasing, false); - mPlugin->RenderElementTimeHandles(painter, geometry().height(), mPlugin->mPenTimeHandles); + m_plugin->RenderElementTimeHandles(painter, geometry().height(), m_plugin->m_penTimeHandles); DrawTimeMarker(painter, rect); // render selection rect - if (mRectSelecting) + if (m_rectSelecting) { painter.resetTransform(); QRect selectRect; CalcSelectRect(selectRect); - if (mRectZooming) + if (m_rectZooming) { painter.setBrush(QColor(0, 100, 200, 75)); painter.setPen(QColor(0, 100, 255)); @@ -189,7 +189,7 @@ namespace EMStudio } else { - if (EMotionFX::GetRecorder().GetRecordTime() < MCore::Math::epsilon && mPlugin->mMotion) + if (EMotionFX::GetRecorder().GetRecordTime() < MCore::Math::epsilon && m_plugin->m_motion) { painter.setBrush(QColor(200, 120, 0, 75)); painter.setPen(QColor(255, 128, 0)); @@ -201,9 +201,9 @@ namespace EMStudio void TrackDataWidget::RemoveTrack(size_t trackIndex) { - mPlugin->SetRedrawFlag(); + m_plugin->SetRedrawFlag(); CommandSystem::CommandRemoveEventTrack(trackIndex); - mPlugin->UnselectAllElements(); + m_plugin->UnselectAllElements(); ClearState(); } @@ -212,8 +212,8 @@ namespace EMStudio { // draw the current time marker float startHeight = 0.0f; - const float curTimeX = aznumeric_cast(mPlugin->TimeToPixel(mPlugin->mCurTime)); - painter.setPen(mPlugin->mPenCurTimeHandle); + const float curTimeX = aznumeric_cast(m_plugin->TimeToPixel(m_plugin->m_curTime)); + painter.setPen(m_plugin->m_penCurTimeHandle); painter.drawLine(QPointF(curTimeX, startHeight), QPointF(curTimeX, rect.bottom())); } @@ -229,7 +229,7 @@ namespace EMStudio QRect motionRect = rect; const float animationLength = recorder.GetRecordTime(); - const double animEndPixel = mPlugin->TimeToPixel(animationLength); + const double animEndPixel = m_plugin->TimeToPixel(animationLength); backgroundRect.setLeft(aznumeric_cast(animEndPixel)); motionRect.setRight(aznumeric_cast(animEndPixel)); motionRect.setTop(0); @@ -237,9 +237,9 @@ namespace EMStudio // render the rects painter.setPen(Qt::NoPen); - painter.setBrush(mBrushBackground); + painter.setBrush(m_brushBackground); painter.drawRect(motionRect); - painter.setBrush(mBrushBackgroundOutOfRange); + painter.setBrush(m_brushBackgroundOutOfRange); painter.drawRect(backgroundRect); // find the selected actor instance @@ -259,7 +259,7 @@ namespace EMStudio // get the actor instance data for the first selected actor instance, and render the node history for that const EMotionFX::Recorder::ActorInstanceData* actorInstanceData = &recorder.GetActorInstanceData(actorInstanceDataIndex); - RecorderGroup* recorderGroup = mPlugin->GetTimeViewToolBar()->GetRecorderGroup(); + RecorderGroup* recorderGroup = m_plugin->GetTimeViewToolBar()->GetRecorderGroup(); const bool displayNodeActivity = recorderGroup->GetDisplayNodeActivity(); const bool displayEvents = recorderGroup->GetDisplayMotionEvents(); const bool displayRelativeGraph = recorderGroup->GetDisplayRelativeGraph(); @@ -270,31 +270,31 @@ namespace EMStudio if (displayNodeActivity) { - mNodeRectsStartHeight = startOffset; + m_nodeRectsStartHeight = startOffset; PaintRecorderNodeHistory(painter, rect, actorInstanceData); isTop = false; - startOffset = mNodeHistoryRect.bottom(); - requiredHeight = mNodeHistoryRect.bottom(); + startOffset = m_nodeHistoryRect.bottom(); + requiredHeight = m_nodeHistoryRect.bottom(); } if (displayEvents) { if (isTop == false) { - mEventsStartHeight = startOffset; - mEventsStartHeight += PaintSeparator(painter, mEventsStartHeight, animationLength); - mEventsStartHeight += 10; - startOffset = mEventsStartHeight; + m_eventsStartHeight = startOffset; + m_eventsStartHeight += PaintSeparator(painter, m_eventsStartHeight, animationLength); + m_eventsStartHeight += 10; + startOffset = m_eventsStartHeight; requiredHeight += 11; } else { startOffset += 3; - mEventsStartHeight = startOffset; + m_eventsStartHeight = startOffset; requiredHeight += 3; } - startOffset += mEventHistoryTotalHeight; + startOffset += m_eventHistoryTotalHeight; isTop = false; PaintRecorderEventHistory(painter, rect, actorInstanceData); @@ -304,15 +304,15 @@ namespace EMStudio { if (isTop == false) { - mGraphStartHeight = startOffset + 10; - mGraphStartHeight += PaintSeparator(painter, mGraphStartHeight, animationLength); - startOffset = mGraphStartHeight; + m_graphStartHeight = startOffset + 10; + m_graphStartHeight += PaintSeparator(painter, m_graphStartHeight, animationLength); + startOffset = m_graphStartHeight; requiredHeight += 11; } else { startOffset += 3; - mGraphStartHeight = startOffset; + m_graphStartHeight = startOffset; requiredHeight += 3; } @@ -341,17 +341,17 @@ namespace EMStudio painter.setRenderHint(QPainter::Antialiasing, true); // get the history items shortcut - const AZStd::vector& historyItems = actorInstanceData->mNodeHistoryItems; + const AZStd::vector& historyItems = actorInstanceData->m_nodeHistoryItems; int32 windowWidth = geometry().width(); - RecorderGroup* recorderGroup = mPlugin->GetTimeViewToolBar()->GetRecorderGroup(); + RecorderGroup* recorderGroup = m_plugin->GetTimeViewToolBar()->GetRecorderGroup(); const bool useNodeColors = recorderGroup->GetUseNodeTypeColors(); const bool limitGraphHeight = recorderGroup->GetLimitGraphHeight(); - const bool showNodeNames = mPlugin->mTrackHeaderWidget->mNodeNamesCheckBox->isChecked(); - const bool showMotionFiles = mPlugin->mTrackHeaderWidget->mMotionFilesCheckBox->isChecked(); - const bool interpolate = recorder.GetRecordSettings().mInterpolate; + const bool showNodeNames = m_plugin->m_trackHeaderWidget->m_nodeNamesCheckBox->isChecked(); + const bool showMotionFiles = m_plugin->m_trackHeaderWidget->m_motionFilesCheckBox->isChecked(); + const bool interpolate = recorder.GetRecordSettings().m_interpolate; - float graphHeight = aznumeric_cast(geometry().height() - mGraphStartHeight); + float graphHeight = aznumeric_cast(geometry().height() - m_graphStartHeight); float graphBottom; if (limitGraphHeight == false) { @@ -364,27 +364,27 @@ namespace EMStudio graphHeight = 200; } - graphBottom = mGraphStartHeight + graphHeight; + graphBottom = m_graphStartHeight + graphHeight; } - const uint32 graphContentsCode = mPlugin->mTrackHeaderWidget->mGraphContentsComboBox->currentIndex(); + const uint32 graphContentsCode = m_plugin->m_trackHeaderWidget->m_graphContentsComboBox->currentIndex(); for (EMotionFX::Recorder::NodeHistoryItem* curItem : historyItems) { - double startTimePixel = mPlugin->TimeToPixel(curItem->mStartTime); - double endTimePixel = mPlugin->TimeToPixel(curItem->mEndTime); + double startTimePixel = m_plugin->TimeToPixel(curItem->m_startTime); + double endTimePixel = m_plugin->TimeToPixel(curItem->m_endTime); - const QRect itemRect(QPoint(aznumeric_cast(startTimePixel), mGraphStartHeight), QPoint(aznumeric_cast(endTimePixel), geometry().height())); + const QRect itemRect(QPoint(aznumeric_cast(startTimePixel), m_graphStartHeight), QPoint(aznumeric_cast(endTimePixel), geometry().height())); if (rect.intersects(itemRect) == false) { continue; } - const AZ::Color colorCode = (useNodeColors) ? curItem->mTypeColor : curItem->mColor; + const AZ::Color colorCode = (useNodeColors) ? curItem->m_typeColor : curItem->m_color; QColor color; color.setRgbF(colorCode.GetR(), colorCode.GetG(), colorCode.GetB(), colorCode.GetA()); - if (mPlugin->mNodeHistoryItem != curItem || mIsScrolling || mPlugin->mIsAnimating) + if (m_plugin->m_nodeHistoryItem != curItem || m_isScrolling || m_plugin->m_isAnimating) { painter.setPen(color); color.setAlpha(64); @@ -402,20 +402,20 @@ namespace EMStudio int32 widthInPixels = aznumeric_cast(endTimePixel - startTimePixel); if (widthInPixels > 0) { - EMotionFX::KeyTrackLinearDynamic* keyTrack = &curItem->mGlobalWeights; // init on global weights + EMotionFX::KeyTrackLinearDynamic* keyTrack = &curItem->m_globalWeights; // init on global weights if (graphContentsCode == 1) { - keyTrack = &curItem->mLocalWeights; + keyTrack = &curItem->m_localWeights; } else if (graphContentsCode == 2) { - keyTrack = &curItem->mPlayTimes; + keyTrack = &curItem->m_playTimes; } - float lastWeight = keyTrack->GetValueAtTime(0.0f, &curItem->mCachedKey, nullptr, interpolate); - const float keyTimeStep = (curItem->mEndTime - curItem->mStartTime) / (float)widthInPixels; + float lastWeight = keyTrack->GetValueAtTime(0.0f, &curItem->m_cachedKey, nullptr, interpolate); + const float keyTimeStep = (curItem->m_endTime - curItem->m_startTime) / (float)widthInPixels; const int32 pixelStepSize = 1;//(widthInPixels / 300.0f) + 1; @@ -435,12 +435,12 @@ namespace EMStudio firstPixel = false; } - const float weight = keyTrack->GetValueAtTime(w * keyTimeStep, &curItem->mCachedKey, nullptr, interpolate); + const float weight = keyTrack->GetValueAtTime(w * keyTimeStep, &curItem->m_cachedKey, nullptr, interpolate); const float height = graphBottom - weight * graphHeight; path.lineTo(QPointF(startTimePixel + w + 1, height)); } - const float weight = keyTrack->GetValueAtTime(curItem->mEndTime, &curItem->mCachedKey, nullptr, interpolate); + const float weight = keyTrack->GetValueAtTime(curItem->m_endTime, &curItem->m_cachedKey, nullptr, interpolate); const float height = graphBottom - weight * graphHeight; path.lineTo(QPointF(startTimePixel + widthInPixels - 1, height)); path.lineTo(QPointF(startTimePixel + widthInPixels, graphBottom + 1)); @@ -449,13 +449,13 @@ namespace EMStudio } // calculate the remapped track list, based on sorted global weight, with the most influencing track on top - recorder.ExtractNodeHistoryItems(*actorInstanceData, aznumeric_cast(mPlugin->mCurTime), true, (EMotionFX::Recorder::EValueType)graphContentsCode, &mActiveItems, &mTrackRemap); + recorder.ExtractNodeHistoryItems(*actorInstanceData, aznumeric_cast(m_plugin->m_curTime), true, (EMotionFX::Recorder::EValueType)graphContentsCode, &m_activeItems, &m_trackRemap); // display the values and names int offset = 0; - for (const EMotionFX::Recorder::ExtractedNodeHistoryItem& activeItem : mActiveItems) + for (const EMotionFX::Recorder::ExtractedNodeHistoryItem& activeItem : m_activeItems) { - EMotionFX::Recorder::NodeHistoryItem* curItem = activeItem.mNodeHistoryItem; + EMotionFX::Recorder::NodeHistoryItem* curItem = activeItem.m_nodeHistoryItem; if (curItem == nullptr) { continue; @@ -463,39 +463,39 @@ namespace EMStudio offset += 15; - mTempString.clear(); + m_tempString.clear(); if (showNodeNames) { - mTempString += curItem->mName.c_str(); + m_tempString += curItem->m_name.c_str(); } - if (showMotionFiles && !curItem->mMotionFileName.empty()) + if (showMotionFiles && !curItem->m_motionFileName.empty()) { - if (!mTempString.empty()) + if (!m_tempString.empty()) { - mTempString += " - "; + m_tempString += " - "; } - mTempString += curItem->mMotionFileName.c_str(); + m_tempString += curItem->m_motionFileName.c_str(); } - if (!mTempString.empty()) + if (!m_tempString.empty()) { - mTempString += AZStd::string::format(" = %.4f", activeItem.mValue); + m_tempString += AZStd::string::format(" = %.4f", activeItem.m_value); } else { - mTempString = AZStd::string::format("%.4f", activeItem.mValue); + m_tempString = AZStd::string::format("%.4f", activeItem.m_value); } - const AZ::Color colorCode = (useNodeColors) ? activeItem.mNodeHistoryItem->mTypeColor : activeItem.mNodeHistoryItem->mColor; + const AZ::Color colorCode = (useNodeColors) ? activeItem.m_nodeHistoryItem->m_typeColor : activeItem.m_nodeHistoryItem->m_color; QColor color; color.setRgbF(colorCode.GetR(), colorCode.GetG(), colorCode.GetB(), colorCode.GetA()); painter.setPen(color); painter.setBrush(Qt::NoBrush); - painter.setFont(mDataFont); - painter.drawText(3, offset + mGraphStartHeight, mTempString.c_str()); + painter.setFont(m_dataFont); + painter.drawText(3, offset + m_graphStartHeight, m_tempString.c_str()); } } @@ -512,10 +512,10 @@ namespace EMStudio } // get the history items shortcut - const AZStd::vector& historyItems = actorInstanceData->mEventHistoryItems; + const AZStd::vector& historyItems = actorInstanceData->m_eventHistoryItems; QRect clipRect = rect; - clipRect.setRight(aznumeric_cast(mPlugin->TimeToPixel(animationLength))); + clipRect.setRight(aznumeric_cast(m_plugin->TimeToPixel(animationLength))); painter.setClipRect(clipRect); painter.setClipping(true); @@ -526,8 +526,8 @@ namespace EMStudio QPointF tickPoints[6]; for (const EMotionFX::Recorder::EventHistoryItem* curItem : historyItems) { - float height = aznumeric_cast((curItem->mTrackIndex * 20) + mEventsStartHeight); - double startTimePixel = mPlugin->TimeToPixel(curItem->mStartTime); + float height = aznumeric_cast((curItem->m_trackIndex * 20) + m_eventsStartHeight); + double startTimePixel = m_plugin->TimeToPixel(curItem->m_startTime); const QRect itemRect(QPoint(aznumeric_cast(startTimePixel - tickHalfWidth), aznumeric_cast(height)), QSize(aznumeric_cast(tickHalfWidth * 2), aznumeric_cast(tickHeight))); if (rect.intersects(itemRect) == false) @@ -537,17 +537,17 @@ namespace EMStudio // try to locate the node based on its unique ID QColor borderColor(30, 30, 30); - const AZ::Color& colorCode = curItem->mColor; + const AZ::Color& colorCode = curItem->m_color; QColor color; color.setRgbF(colorCode.GetR(), colorCode.GetG(), colorCode.GetB(), colorCode.GetA()); - if (mIsScrolling == false && mPlugin->mIsAnimating == false) + if (m_isScrolling == false && m_plugin->m_isAnimating == false) { - if (mPlugin->mNodeHistoryItem && mPlugin->mNodeHistoryItem->mNodeId == curItem->mEmitterNodeId) + if (m_plugin->m_nodeHistoryItem && m_plugin->m_nodeHistoryItem->m_nodeId == curItem->m_emitterNodeId) { - if (curItem->mStartTime >= mPlugin->mNodeHistoryItem->mStartTime && curItem->mStartTime <= mPlugin->mNodeHistoryItem->mEndTime) + if (curItem->m_startTime >= m_plugin->m_nodeHistoryItem->m_startTime && curItem->m_startTime <= m_plugin->m_nodeHistoryItem->m_endTime) { - RecorderGroup* recorderGroup = mPlugin->GetTimeViewToolBar()->GetRecorderGroup(); + RecorderGroup* recorderGroup = m_plugin->GetTimeViewToolBar()->GetRecorderGroup(); if (recorderGroup->GetDisplayNodeActivity()) { borderColor = QColor(255, 128, 0); @@ -556,7 +556,7 @@ namespace EMStudio } } - if (mPlugin->mEventHistoryItem == curItem) + if (m_plugin->m_eventHistoryItem == curItem) { borderColor = QColor(255, 128, 0); color = borderColor; @@ -607,64 +607,64 @@ namespace EMStudio } // skip the complete rendering of the node history data when its bounds are not inside view - if (!rect.intersects(mNodeHistoryRect)) + if (!rect.intersects(m_nodeHistoryRect)) { return; } // get the history items shortcut - const AZStd::vector& historyItems = actorInstanceData->mNodeHistoryItems; + const AZStd::vector& historyItems = actorInstanceData->m_nodeHistoryItems; int32 windowWidth = geometry().width(); // calculate the remapped track list, based on sorted global weight, with the most influencing track on top - RecorderGroup* recorderGroup = mPlugin->GetTimeViewToolBar()->GetRecorderGroup(); + RecorderGroup* recorderGroup = m_plugin->GetTimeViewToolBar()->GetRecorderGroup(); const bool sorted = recorderGroup->GetSortNodeActivity(); const bool useNodeColors = recorderGroup->GetUseNodeTypeColors(); - const int graphContentsCode = mPlugin->mTrackHeaderWidget->mNodeContentsComboBox->currentIndex(); - recorder.ExtractNodeHistoryItems(*actorInstanceData, aznumeric_cast(mPlugin->mCurTime), sorted, (EMotionFX::Recorder::EValueType)graphContentsCode, &mActiveItems, &mTrackRemap); + const int graphContentsCode = m_plugin->m_trackHeaderWidget->m_nodeContentsComboBox->currentIndex(); + recorder.ExtractNodeHistoryItems(*actorInstanceData, aznumeric_cast(m_plugin->m_curTime), sorted, (EMotionFX::Recorder::EValueType)graphContentsCode, &m_activeItems, &m_trackRemap); - const bool showNodeNames = mPlugin->mTrackHeaderWidget->mNodeNamesCheckBox->isChecked(); - const bool showMotionFiles = mPlugin->mTrackHeaderWidget->mMotionFilesCheckBox->isChecked(); - const bool interpolate = recorder.GetRecordSettings().mInterpolate; + const bool showNodeNames = m_plugin->m_trackHeaderWidget->m_nodeNamesCheckBox->isChecked(); + const bool showMotionFiles = m_plugin->m_trackHeaderWidget->m_motionFilesCheckBox->isChecked(); + const bool interpolate = recorder.GetRecordSettings().m_interpolate; - const int nodeContentsCode = mPlugin->mTrackHeaderWidget->mNodeContentsComboBox->currentIndex(); + const int nodeContentsCode = m_plugin->m_trackHeaderWidget->m_nodeContentsComboBox->currentIndex(); // for all history items QRectF itemRect; for (EMotionFX::Recorder::NodeHistoryItem* curItem : historyItems) { // draw the background rect - double startTimePixel = mPlugin->TimeToPixel(curItem->mStartTime); - double endTimePixel = mPlugin->TimeToPixel(curItem->mEndTime); + double startTimePixel = m_plugin->TimeToPixel(curItem->m_startTime); + double endTimePixel = m_plugin->TimeToPixel(curItem->m_endTime); - const size_t trackIndex = mTrackRemap[ curItem->mTrackIndex ]; + const size_t trackIndex = m_trackRemap[ curItem->m_trackIndex ]; itemRect.setLeft(startTimePixel); itemRect.setRight(endTimePixel - 1); - itemRect.setTop((mNodeRectsStartHeight + (aznumeric_cast(trackIndex) * (mNodeHistoryItemHeight + 3)) + 3)); - itemRect.setBottom(itemRect.top() + mNodeHistoryItemHeight); + itemRect.setTop((m_nodeRectsStartHeight + (aznumeric_cast(trackIndex) * (m_nodeHistoryItemHeight + 3)) + 3)); + itemRect.setBottom(itemRect.top() + m_nodeHistoryItemHeight); if (!rect.intersects(itemRect.toRect())) { continue; } - const AZ::Color colorCode = (useNodeColors) ? curItem->mTypeColor : curItem->mColor; + const AZ::Color colorCode = (useNodeColors) ? curItem->m_typeColor : curItem->m_color; QColor color; color.setRgbF(colorCode.GetR(), colorCode.GetG(), colorCode.GetB(), colorCode.GetA()); bool matchesEvent = false; - if (mIsScrolling == false && mPlugin->mIsAnimating == false) + if (m_isScrolling == false && m_plugin->m_isAnimating == false) { - if (mPlugin->mNodeHistoryItem == curItem) + if (m_plugin->m_nodeHistoryItem == curItem) { color = QColor(255, 128, 0); } - if (mPlugin->mEventEmitterNode && mPlugin->mEventEmitterNode->GetId() == curItem->mNodeId && mPlugin->mEventHistoryItem) + if (m_plugin->m_eventEmitterNode && m_plugin->m_eventEmitterNode->GetId() == curItem->m_nodeId && m_plugin->m_eventHistoryItem) { - if (mPlugin->mEventHistoryItem->mStartTime >= curItem->mStartTime && mPlugin->mEventHistoryItem->mStartTime <= curItem->mEndTime) + if (m_plugin->m_eventHistoryItem->m_startTime >= curItem->m_startTime && m_plugin->m_eventHistoryItem->m_startTime <= curItem->m_endTime) { color = QColor(255, 128, 0); matchesEvent = true; @@ -688,24 +688,24 @@ namespace EMStudio int32 widthInPixels = aznumeric_cast(endTimePixel - startTimePixel); if (widthInPixels > 0) { - const EMotionFX::KeyTrackLinearDynamic* keyTrack = &curItem->mGlobalWeights; // init on global weights + const EMotionFX::KeyTrackLinearDynamic* keyTrack = &curItem->m_globalWeights; // init on global weights if (nodeContentsCode == 1) { - keyTrack = &curItem->mLocalWeights; + keyTrack = &curItem->m_localWeights; } else if (nodeContentsCode == 2) { - keyTrack = &curItem->mPlayTimes; + keyTrack = &curItem->m_playTimes; } - float lastWeight = keyTrack->GetValueAtTime(0.0f, &curItem->mCachedKey, nullptr, interpolate); - const float keyTimeStep = (curItem->mEndTime - curItem->mStartTime) / (float)widthInPixels; + float lastWeight = keyTrack->GetValueAtTime(0.0f, &curItem->m_cachedKey, nullptr, interpolate); + const float keyTimeStep = (curItem->m_endTime - curItem->m_startTime) / (float)widthInPixels; const int32 pixelStepSize = 1;//(widthInPixels / 300.0f) + 1; path.moveTo(QPointF(startTimePixel - 1, itemRect.bottom() + 1)); - path.lineTo(QPointF(startTimePixel + 1, itemRect.bottom() - 1 - lastWeight * mNodeHistoryItemHeight)); + path.lineTo(QPointF(startTimePixel + 1, itemRect.bottom() - 1 - lastWeight * m_nodeHistoryItemHeight)); bool firstPixel = true; for (int32 w = 1; w < widthInPixels - 1; w += pixelStepSize) { @@ -720,13 +720,13 @@ namespace EMStudio firstPixel = false; } - const float weight = keyTrack->GetValueAtTime(w * keyTimeStep, &curItem->mCachedKey, nullptr, interpolate); - const float height = aznumeric_cast(itemRect.bottom() - weight * mNodeHistoryItemHeight); + const float weight = keyTrack->GetValueAtTime(w * keyTimeStep, &curItem->m_cachedKey, nullptr, interpolate); + const float height = aznumeric_cast(itemRect.bottom() - weight * m_nodeHistoryItemHeight); path.lineTo(QPointF(startTimePixel + w + 1, height)); } - const float weight = keyTrack->GetValueAtTime(curItem->mEndTime, &curItem->mCachedKey, nullptr, interpolate); - const float height = aznumeric_cast(itemRect.bottom() - weight * mNodeHistoryItemHeight); + const float weight = keyTrack->GetValueAtTime(curItem->m_endTime, &curItem->m_cachedKey, nullptr, interpolate); + const float height = aznumeric_cast(itemRect.bottom() - weight * m_nodeHistoryItemHeight); path.lineTo(QPointF(startTimePixel + widthInPixels - 1, height)); path.lineTo(QPointF(startTimePixel + widthInPixels, itemRect.bottom() + 1)); painter.drawPath(path); @@ -737,9 +737,9 @@ namespace EMStudio // draw the text if (matchesEvent != true) { - if (mIsScrolling == false && mPlugin->mIsAnimating == false) + if (m_isScrolling == false && m_plugin->m_isAnimating == false) { - if (mPlugin->mNodeHistoryItem != curItem) + if (m_plugin->m_nodeHistoryItem != curItem) { painter.setPen(QColor(255, 255, 255, 175)); } @@ -758,25 +758,25 @@ namespace EMStudio painter.setPen(Qt::black); } - mTempString.clear(); + m_tempString.clear(); if (showNodeNames) { - mTempString += curItem->mName.c_str(); + m_tempString += curItem->m_name.c_str(); } - if (showMotionFiles && !curItem->mMotionFileName.empty()) + if (showMotionFiles && !curItem->m_motionFileName.empty()) { - if (!mTempString.empty()) + if (!m_tempString.empty()) { - mTempString += " - "; + m_tempString += " - "; } - mTempString += curItem->mMotionFileName.c_str(); + m_tempString += curItem->m_motionFileName.c_str(); } - if (!mTempString.empty()) + if (!m_tempString.empty()) { - painter.drawText(aznumeric_cast(itemRect.left() + 3), aznumeric_cast(itemRect.bottom() - 2), mTempString.c_str()); + painter.drawText(aznumeric_cast(itemRect.left() + 3), aznumeric_cast(itemRect.bottom() - 2), m_tempString.c_str()); } painter.setClipping(false); @@ -793,17 +793,17 @@ namespace EMStudio // get the track over which the cursor is positioned QPoint localCursorPos = mapFromGlobal(QCursor::pos()); - TimeTrack* mouseCursorTrack = mPlugin->GetTrackAt(localCursorPos.y()); + TimeTrack* mouseCursorTrack = m_plugin->GetTrackAt(localCursorPos.y()); if (localCursorPos.x() < 0 || localCursorPos.x() > width()) { mouseCursorTrack = nullptr; } // handle highlighting - const size_t numTracks = mPlugin->GetNumTracks(); + const size_t numTracks = m_plugin->GetNumTracks(); for (size_t i = 0; i < numTracks; ++i) { - TimeTrack* track = mPlugin->GetTrack(i); + TimeTrack* track = m_plugin->GetTrack(i); // set the highlighting flag for the track if (track == mouseCursorTrack) @@ -812,7 +812,7 @@ namespace EMStudio track->SetIsHighlighted(true); // get the element over which the cursor is positioned - TimeTrackElement* mouseCursorElement = mPlugin->GetElementAt(localCursorPos.x(), localCursorPos.y()); + TimeTrackElement* mouseCursorElement = m_plugin->GetElementAt(localCursorPos.x(), localCursorPos.y()); // get the number of elements, iterate through them and disable the highlight flag const size_t numElements = track->GetNumElements(); @@ -844,7 +844,7 @@ namespace EMStudio } } - EMotionFX::Motion* motion = mPlugin->GetMotion(); + EMotionFX::Motion* motion = m_plugin->GetMotion(); if (motion) { // get the motion length @@ -852,8 +852,8 @@ namespace EMStudio // get the playback info and read out the clip start/end times EMotionFX::PlayBackInfo* playbackInfo = motion->GetDefaultPlayBackInfo(); - clipStart = playbackInfo->mClipStartTime; - clipEnd = playbackInfo->mClipEndTime; + clipStart = playbackInfo->m_clipStartTime; + clipEnd = playbackInfo->m_clipEndTime; // HACK: fix this later clipStart = 0.0; @@ -861,9 +861,9 @@ namespace EMStudio } // calculate the pixel index of where the animation ends and where it gets clipped - const double animEndPixel = mPlugin->TimeToPixel(animationLength); - const double clipStartPixel = mPlugin->TimeToPixel(clipStart); - const double clipEndPixel = mPlugin->TimeToPixel(clipEnd); + const double animEndPixel = m_plugin->TimeToPixel(animationLength); + const double clipStartPixel = m_plugin->TimeToPixel(clipStart); + const double clipEndPixel = m_plugin->TimeToPixel(clipEnd); // enable anti aliassing //painter.setRenderHint(QPainter::Antialiasing); @@ -888,13 +888,13 @@ namespace EMStudio // render the rects painter.setPen(Qt::NoPen); - painter.setBrush(mBrushBackgroundClipped); + painter.setBrush(m_brushBackgroundClipped); painter.drawRect(clipStartRect); - painter.setBrush(mBrushBackground); + painter.setBrush(m_brushBackground); painter.drawRect(motionRect); - painter.setBrush(mBrushBackgroundClipped); + painter.setBrush(m_brushBackgroundClipped); painter.drawRect(clipEndRect); - painter.setBrush(mBrushBackgroundOutOfRange); + painter.setBrush(m_brushBackgroundOutOfRange); painter.drawRect(outOfRangeRect); // render the tracks @@ -909,16 +909,16 @@ namespace EMStudio // calculate the start and end time range of the visible area double visibleStartTime, visibleEndTime; - visibleStartTime = mPlugin->PixelToTime(0); //mPlugin->CalcTime( 0, &visibleStartTime, nullptr, nullptr, nullptr, nullptr ); - visibleEndTime = mPlugin->PixelToTime(width); //mPlugin->CalcTime( width, &visibleEndTime, nullptr, nullptr, nullptr, nullptr ); + visibleStartTime = m_plugin->PixelToTime(0); + visibleEndTime = m_plugin->PixelToTime(width); // for all tracks - for (TimeTrack* track : mPlugin->mTracks) + for (TimeTrack* track : m_plugin->m_tracks) { track->SetStartY(yOffset); // path for making the cut elements a bit transparent - if (mCutMode) + if (m_cutMode) { // disable cut mode for all elements on default const size_t numElements = track->GetNumElements(); @@ -928,7 +928,7 @@ namespace EMStudio } // get the number of copy elements and check if ours is in - for (const CopyElement& copyElement : mCopyElements) + for (const CopyElement& copyElement : m_copyElements) { // get the copy element and make sure we're in the right track if (copyElement.m_trackName != track->GetName()) @@ -958,27 +958,27 @@ namespace EMStudio } // render the element time handles - mPlugin->RenderElementTimeHandles(painter, height, mPlugin->mPenTimeHandles); + m_plugin->RenderElementTimeHandles(painter, height, m_plugin->m_penTimeHandles); } // show the time of the currently dragging element in the time info view void TrackDataWidget::ShowElementTimeInfo(TimeTrackElement* element) { - if (mPlugin->GetTimeInfoWidget() == nullptr) + if (m_plugin->GetTimeInfoWidget() == nullptr) { return; } // enable overwrite mode so that the time info widget will show the custom time rather than the current time of the plugin - mPlugin->GetTimeInfoWidget()->SetIsOverwriteMode(true); + m_plugin->GetTimeInfoWidget()->SetIsOverwriteMode(true); // calculate the dimensions int32 startX, startY, width, height; element->CalcDimensions(&startX, &startY, &width, &height); // show the times of the element - mPlugin->GetTimeInfoWidget()->SetOverwriteTime(mPlugin->PixelToTime(startX), mPlugin->PixelToTime(startX + width)); + m_plugin->GetTimeInfoWidget()->SetOverwriteTime(m_plugin->PixelToTime(startX), m_plugin->PixelToTime(startX + width)); } @@ -990,21 +990,21 @@ namespace EMStudio } // if we clicked inside the node history area - RecorderGroup* recorderGroup = mPlugin->GetTimeViewToolBar()->GetRecorderGroup(); + RecorderGroup* recorderGroup = m_plugin->GetTimeViewToolBar()->GetRecorderGroup(); if (GetIsInsideNodeHistory(event->y()) && recorderGroup->GetDisplayNodeActivity()) { EMotionFX::Recorder::ActorInstanceData* actorInstanceData = FindActorInstanceData(); EMotionFX::Recorder::NodeHistoryItem* historyItem = FindNodeHistoryItem(actorInstanceData, event->x(), event->y()); if (historyItem) { - emit mPlugin->DoubleClickedRecorderNodeHistoryItem(actorInstanceData, historyItem); + emit m_plugin->DoubleClickedRecorderNodeHistoryItem(actorInstanceData, historyItem); } } } void TrackDataWidget::SetPausedTime(float timeValue, bool emitTimeChangeStart) { - mPlugin->mCurTime = timeValue; + m_plugin->m_curTime = timeValue; const AZStd::vector& motionInstances = MotionWindowPlugin::GetSelectedMotionInstances(); if (motionInstances.size() == 1) { @@ -1014,137 +1014,137 @@ namespace EMStudio } if (emitTimeChangeStart) { - emit mPlugin->ManualTimeChangeStart(timeValue); + emit m_plugin->ManualTimeChangeStart(timeValue); } - emit mPlugin->ManualTimeChange(timeValue); + emit m_plugin->ManualTimeChange(timeValue); } // when the mouse is moving, while a button is pressed void TrackDataWidget::mouseMoveEvent(QMouseEvent* event) { - mPlugin->SetRedrawFlag(); + m_plugin->SetRedrawFlag(); QPoint mousePos = event->pos(); - const int32 deltaRelX = event->x() - mLastMouseX; - mLastMouseX = event->x(); - mPlugin->mCurMouseX = event->x(); - mPlugin->mCurMouseY = event->y(); + const int32 deltaRelX = event->x() - m_lastMouseX; + m_lastMouseX = event->x(); + m_plugin->m_curMouseX = event->x(); + m_plugin->m_curMouseY = event->y(); - const int32 deltaRelY = event->y() - mLastMouseY; - mLastMouseY = event->y(); + const int32 deltaRelY = event->y() - m_lastMouseY; + m_lastMouseY = event->y(); const bool altPressed = event->modifiers() & Qt::AltModifier; - const bool isZooming = mMouseLeftClicked == false && mMouseRightClicked && altPressed; - const bool isPanning = mMouseLeftClicked == false && isZooming == false && (mMouseMidClicked || mMouseRightClicked); + const bool isZooming = m_mouseLeftClicked == false && m_mouseRightClicked && altPressed; + const bool isPanning = m_mouseLeftClicked == false && isZooming == false && (m_mouseMidClicked || m_mouseRightClicked); if (deltaRelY != 0) { - mAllowContextMenu = false; + m_allowContextMenu = false; } // get the track over which the cursor is positioned - TimeTrack* mouseCursorTrack = mPlugin->GetTrackAt(event->y()); + TimeTrack* mouseCursorTrack = m_plugin->GetTrackAt(event->y()); - if (mMouseRightClicked) + if (m_mouseRightClicked) { - mIsScrolling = true; + m_isScrolling = true; } // if the mouse left button is pressed - if (mMouseLeftClicked) + if (m_mouseLeftClicked) { if (altPressed) { - mRectZooming = true; + m_rectZooming = true; } else { - mRectZooming = false; + m_rectZooming = false; } // rect selection: update mouse position - if (mRectSelecting) + if (m_rectSelecting) { - mSelectEnd = mousePos; + m_selectEnd = mousePos; } - if (mDraggingElement == nullptr && mResizeElement == nullptr && mRectSelecting == false) + if (m_draggingElement == nullptr && m_resizeElement == nullptr && m_rectSelecting == false) { // update the current time marker int newX = event->x(); newX = MCore::Clamp(newX, 0, geometry().width() - 1); - mPlugin->mCurTime = mPlugin->PixelToTime(newX); + m_plugin->m_curTime = m_plugin->PixelToTime(newX); EMotionFX::Recorder& recorder = EMotionFX::GetRecorder(); if (recorder.GetRecordTime() > MCore::Math::epsilon) { if (recorder.GetIsInPlayMode()) { - recorder.SetCurrentPlayTime(aznumeric_cast(mPlugin->GetCurrentTime())); + recorder.SetCurrentPlayTime(aznumeric_cast(m_plugin->GetCurrentTime())); recorder.SetAutoPlay(false); - emit mPlugin->ManualTimeChange(aznumeric_cast(mPlugin->GetCurrentTime())); + emit m_plugin->ManualTimeChange(aznumeric_cast(m_plugin->GetCurrentTime())); } } else { - SetPausedTime(aznumeric_cast(mPlugin->mCurTime)); + SetPausedTime(aznumeric_cast(m_plugin->m_curTime)); } - mIsScrolling = true; + m_isScrolling = true; } TimeTrack* dragElementTrack = nullptr; - if (mDraggingElement) + if (m_draggingElement) { - dragElementTrack = mDraggingElement->GetTrack(); + dragElementTrack = m_draggingElement->GetTrack(); } // calculate the delta movement - const int32 deltaX = event->x() - mLastLeftClickedX; + const int32 deltaX = event->x() - m_lastLeftClickedX; const int32 movement = abs(deltaX); const bool elementTrackChanged = (mouseCursorTrack && dragElementTrack && mouseCursorTrack != dragElementTrack); - if ((movement > 1 && !mDragging) || elementTrackChanged) + if ((movement > 1 && !m_dragging) || elementTrackChanged) { - mDragging = true; + m_dragging = true; } // handle resizing - if (mResizing) + if (m_resizing) { - if (mPlugin->FindTrackByElement(mResizeElement) == nullptr) + if (m_plugin->FindTrackByElement(m_resizeElement) == nullptr) { - mResizeElement = nullptr; + m_resizeElement = nullptr; } - if (mResizeElement) + if (m_resizeElement) { - TimeTrack* resizeElementTrack = mResizeElement->GetTrack(); + TimeTrack* resizeElementTrack = m_resizeElement->GetTrack(); // only allow resizing on enabled time tracks if (resizeElementTrack->GetIsEnabled()) { - mResizeElement->SetShowTimeHandles(true); - mResizeElement->SetShowToolTip(false); + m_resizeElement->SetShowTimeHandles(true); + m_resizeElement->SetShowToolTip(false); - double resizeTime = (deltaRelX / mPlugin->mTimeScale) / mPlugin->mPixelsPerSecond; - mResizeID = mResizeElement->HandleResize(mResizeID, resizeTime, 0.02 / mPlugin->mTimeScale); + double resizeTime = (deltaRelX / m_plugin->m_timeScale) / m_plugin->m_pixelsPerSecond; + m_resizeId = m_resizeElement->HandleResize(m_resizeId, resizeTime, 0.02 / m_plugin->m_timeScale); // show the time of the currently resizing element in the time info view - ShowElementTimeInfo(mResizeElement); + ShowElementTimeInfo(m_resizeElement); // Move the current time marker along with the event resizing position. float timeValue = 0.0f; - switch (mResizeID) + switch (m_resizeId) { case TimeTrackElement::RESIZEPOINT_START: { - timeValue = aznumeric_cast(mResizeElement->GetStartTime()); + timeValue = aznumeric_cast(m_resizeElement->GetStartTime()); break; } case TimeTrackElement::RESIZEPOINT_END: { - timeValue = aznumeric_cast(mResizeElement->GetEndTime()); + timeValue = aznumeric_cast(m_resizeElement->GetEndTime()); break; } default: @@ -1162,7 +1162,7 @@ namespace EMStudio } // if we are not dragging or no element is being dragged, there is nothing to do - if (mDragging == false || mDraggingElement == nullptr) + if (m_dragging == false || m_draggingElement == nullptr) { return; } @@ -1171,79 +1171,79 @@ namespace EMStudio if (elementTrackChanged) { // if yes we need to remove the dragging element from the old time track - dragElementTrack->RemoveElement(mDraggingElement, false); + dragElementTrack->RemoveElement(m_draggingElement, false); // and add it to the new time track where the cursor now is over - mouseCursorTrack->AddElement(mDraggingElement); - mDraggingElement->SetTrack(mouseCursorTrack); + mouseCursorTrack->AddElement(m_draggingElement); + m_draggingElement->SetTrack(mouseCursorTrack); } // show the time of the currently dragging element in the time info view - ShowElementTimeInfo(mDraggingElement); + ShowElementTimeInfo(m_draggingElement); // adjust the cursor setCursor(Qt::ClosedHandCursor); - mDraggingElement->SetShowToolTip(false); + m_draggingElement->SetShowToolTip(false); // show the time handles - mDraggingElement->SetShowTimeHandles(true); + m_draggingElement->SetShowTimeHandles(true); - const double snapThreshold = 0.02 / mPlugin->mTimeScale; + const double snapThreshold = 0.02 / m_plugin->m_timeScale; // calculate how many pixels we moved with the mouse - const int32 deltaMovement = event->x() - mLastMouseMoveX; - mLastMouseMoveX = event->x(); + const int32 deltaMovement = event->x() - m_lastMouseMoveX; + m_lastMouseMoveX = event->x(); // snap the moved amount to a given time value - double snappedTime = mDraggingElement->GetStartTime() + ((deltaMovement / mPlugin->mPixelsPerSecond) / mPlugin->mTimeScale); + double snappedTime = m_draggingElement->GetStartTime() + ((deltaMovement / m_plugin->m_pixelsPerSecond) / m_plugin->m_timeScale); bool startSnapped = false; if (abs(deltaMovement) < 2 && abs(deltaMovement) > 0) // only snap when moving the mouse very slowly { - startSnapped = mPlugin->SnapTime(&snappedTime, mDraggingElement, snapThreshold); + startSnapped = m_plugin->SnapTime(&snappedTime, m_draggingElement, snapThreshold); } // in case the start time didn't snap to anything if (startSnapped == false) { // try to snap the end time - double snappedEndTime = mDraggingElement->GetEndTime() + ((deltaMovement / mPlugin->mPixelsPerSecond) / mPlugin->mTimeScale); - /*bool endSnapped = */ mPlugin->SnapTime(&snappedEndTime, mDraggingElement, snapThreshold); + double snappedEndTime = m_draggingElement->GetEndTime() + ((deltaMovement / m_plugin->m_pixelsPerSecond) / m_plugin->m_timeScale); + /*bool endSnapped = */ m_plugin->SnapTime(&snappedEndTime, m_draggingElement, snapThreshold); // apply the delta movement - const double deltaTime = snappedEndTime - mDraggingElement->GetEndTime(); - mDraggingElement->MoveRelative(deltaTime); + const double deltaTime = snappedEndTime - m_draggingElement->GetEndTime(); + m_draggingElement->MoveRelative(deltaTime); } else { // apply the snapped delta movement - const double deltaTime = snappedTime - mDraggingElement->GetStartTime(); - mDraggingElement->MoveRelative(deltaTime); + const double deltaTime = snappedTime - m_draggingElement->GetStartTime(); + m_draggingElement->MoveRelative(deltaTime); } - dragElementTrack = mDraggingElement->GetTrack(); - const float timeValue = aznumeric_cast(mDraggingElement->GetStartTime()); + dragElementTrack = m_draggingElement->GetTrack(); + const float timeValue = aznumeric_cast(m_draggingElement->GetStartTime()); SetPausedTime(timeValue); } else if (isPanning) { if (EMotionFX::GetRecorder().GetIsRecording() == false) { - mPlugin->DeltaScrollX(-deltaRelX, false); + m_plugin->DeltaScrollX(-deltaRelX, false); } } else if (isZooming) { if (deltaRelY < 0) { - setCursor(*(mPlugin->GetZoomOutCursor())); + setCursor(*(m_plugin->GetZoomOutCursor())); } else { - setCursor(*(mPlugin->GetZoomInCursor())); + setCursor(*(m_plugin->GetZoomInCursor())); } - DoMouseYMoveZoom(deltaRelY, mPlugin); + DoMouseYMoveZoom(deltaRelY, m_plugin); } else // no left mouse button is pressed { @@ -1271,10 +1271,10 @@ namespace EMStudio void TrackDataWidget::UpdateMouseOverCursor(int32 x, int32 y) { // disable all tooltips - mPlugin->DisableAllToolTips(); + m_plugin->DisableAllToolTips(); // get the time track and return directly if we are not over a valid track with the cursor - TimeTrack* timeTrack = mPlugin->GetTrackAt(y); + TimeTrack* timeTrack = m_plugin->GetTrackAt(y); if (timeTrack == nullptr) { setCursor(Qt::ArrowCursor); @@ -1282,7 +1282,7 @@ namespace EMStudio } // get the element over which the cursor is positioned - TimeTrackElement* element = mPlugin->GetElementAt(x, y); + TimeTrackElement* element = m_plugin->GetElementAt(x, y); // in case the cursor is over an element, show tool tips if (element) @@ -1291,7 +1291,7 @@ namespace EMStudio } else { - mPlugin->DisableAllToolTips(); + m_plugin->DisableAllToolTips(); } // do not allow any editing in case the track is not enabled @@ -1302,10 +1302,10 @@ namespace EMStudio } // check if we are hovering over a resize point - if (mPlugin->FindResizePoint(x, y, &mResizeElement, &mResizeID)) + if (m_plugin->FindResizePoint(x, y, &m_resizeElement, &m_resizeId)) { setCursor(Qt::SizeHorCursor); - mResizeElement->SetShowToolTip(true); + m_resizeElement->SetShowToolTip(true); } else // if we're not above a resize point { @@ -1324,7 +1324,7 @@ namespace EMStudio // when the mouse is pressed void TrackDataWidget::mousePressEvent(QMouseEvent* event) { - mPlugin->SetRedrawFlag(); + m_plugin->SetRedrawFlag(); QPoint mousePos = event->pos(); @@ -1333,35 +1333,35 @@ namespace EMStudio const bool altPressed = event->modifiers() & Qt::AltModifier; // store the last clicked position - mLastMouseMoveX = event->x(); - mAllowContextMenu = true; - mRectSelecting = false; + m_lastMouseMoveX = event->x(); + m_allowContextMenu = true; + m_rectSelecting = false; if (event->button() == Qt::RightButton) { - mMouseRightClicked = true; + m_mouseRightClicked = true; } if (event->button() == Qt::MidButton) { - mMouseMidClicked = true; + m_mouseMidClicked = true; } if (event->button() == Qt::LeftButton) { - mMouseLeftClicked = true; + m_mouseLeftClicked = true; EMotionFX::Recorder& recorder = EMotionFX::GetRecorder(); - if ((mPlugin->mNodeHistoryItem == nullptr) && altPressed == false && (recorder.GetRecordTime() >= MCore::Math::epsilon)) + if ((m_plugin->m_nodeHistoryItem == nullptr) && altPressed == false && (recorder.GetRecordTime() >= MCore::Math::epsilon)) { // update the current time marker int newX = event->x(); newX = MCore::Clamp(newX, 0, geometry().width() - 1); - mPlugin->mCurTime = mPlugin->PixelToTime(newX); + m_plugin->m_curTime = m_plugin->PixelToTime(newX); if (recorder.GetRecordTime() < MCore::Math::epsilon) { - SetPausedTime(aznumeric_cast(mPlugin->GetCurrentTime()), /*emitTimeChangeStart=*/true); + SetPausedTime(aznumeric_cast(m_plugin->GetCurrentTime()), /*emitTimeChangeStart=*/true); } else { @@ -1370,34 +1370,34 @@ namespace EMStudio recorder.StartPlayBack(); } - recorder.SetCurrentPlayTime(aznumeric_cast(mPlugin->GetCurrentTime())); + recorder.SetCurrentPlayTime(aznumeric_cast(m_plugin->GetCurrentTime())); recorder.SetAutoPlay(false); - emit mPlugin->ManualTimeChangeStart(aznumeric_cast(mPlugin->GetCurrentTime())); - emit mPlugin->ManualTimeChange(aznumeric_cast(mPlugin->GetCurrentTime())); + emit m_plugin->ManualTimeChangeStart(aznumeric_cast(m_plugin->GetCurrentTime())); + emit m_plugin->ManualTimeChange(aznumeric_cast(m_plugin->GetCurrentTime())); } } else // not inside timeline { // if we clicked inside the node history area - RecorderGroup* recorderGroup = mPlugin->GetTimeViewToolBar()->GetRecorderGroup(); + RecorderGroup* recorderGroup = m_plugin->GetTimeViewToolBar()->GetRecorderGroup(); if (GetIsInsideNodeHistory(event->y()) && recorderGroup->GetDisplayNodeActivity()) { EMotionFX::Recorder::ActorInstanceData* actorInstanceData = FindActorInstanceData(); EMotionFX::Recorder::NodeHistoryItem* historyItem = FindNodeHistoryItem(actorInstanceData, event->x(), event->y()); if (historyItem && altPressed == false) { - emit mPlugin->ClickedRecorderNodeHistoryItem(actorInstanceData, historyItem); + emit m_plugin->ClickedRecorderNodeHistoryItem(actorInstanceData, historyItem); } } { // unselect all elements if (ctrlPressed == false && shiftPressed == false) { - mPlugin->UnselectAllElements(); + m_plugin->UnselectAllElements(); } // find the element we're clicking in - TimeTrackElement* element = mPlugin->GetElementAt(event->x(), event->y()); + TimeTrackElement* element = m_plugin->GetElementAt(event->x(), event->y()); if (element) { // show the time of the currently dragging element in the time info view @@ -1407,15 +1407,15 @@ namespace EMStudio if (timeTrack->GetIsEnabled()) { - mDraggingElement = element; - mDragElementTrack = timeTrack; - mDraggingElement->SetShowTimeHandles(true); + m_draggingElement = element; + m_dragElementTrack = timeTrack; + m_draggingElement->SetShowTimeHandles(true); setCursor(Qt::ClosedHandCursor); } else { - mDraggingElement = nullptr; - mDragElementTrack = nullptr; + m_draggingElement = nullptr; + m_dragElementTrack = nullptr; } // shift select @@ -1443,28 +1443,28 @@ namespace EMStudio } else // no element clicked { - mDraggingElement = nullptr; - mDragElementTrack = nullptr; + m_draggingElement = nullptr; + m_dragElementTrack = nullptr; // rect selection - mRectSelecting = true; - mSelectStart = mousePos; - mSelectEnd = mSelectStart; + m_rectSelecting = true; + m_selectStart = mousePos; + m_selectEnd = m_selectStart; setCursor(Qt::ArrowCursor); } // if we're going to resize - mResizing = mResizeElement && mResizeID != InvalidIndex32; + m_resizing = m_resizeElement && m_resizeId != InvalidIndex32; // store the last clicked position - mMouseLeftClicked = true; - mLastLeftClickedX = event->x(); + m_mouseLeftClicked = true; + m_lastLeftClickedX = event->x(); } } } - const bool isZooming = mMouseLeftClicked == false && mMouseRightClicked && altPressed; - const bool isPanning = mMouseLeftClicked == false && isZooming == false && (mMouseMidClicked || mMouseRightClicked); + const bool isZooming = m_mouseLeftClicked == false && m_mouseRightClicked && altPressed; + const bool isPanning = m_mouseLeftClicked == false && isZooming == false && (m_mouseMidClicked || m_mouseRightClicked); if (isPanning) { @@ -1473,7 +1473,7 @@ namespace EMStudio if (isZooming) { - setCursor(*(mPlugin->GetZoomInCursor())); + setCursor(*(m_plugin->GetZoomInCursor())); } } @@ -1481,58 +1481,58 @@ namespace EMStudio // when releasing the mouse button void TrackDataWidget::mouseReleaseEvent(QMouseEvent* event) { - mPlugin->SetRedrawFlag(); + m_plugin->SetRedrawFlag(); setCursor(Qt::ArrowCursor); // disable overwrite mode in any case when the mouse gets released so that we display the current time from the plugin again - if (mPlugin->GetTimeInfoWidget()) + if (m_plugin->GetTimeInfoWidget()) { - mPlugin->GetTimeInfoWidget()->SetIsOverwriteMode(false); + m_plugin->GetTimeInfoWidget()->SetIsOverwriteMode(false); } - mLastMouseMoveX = event->x(); + m_lastMouseMoveX = event->x(); const bool ctrlPressed = event->modifiers() & Qt::ControlModifier; //const bool shiftPressed = event->modifiers() & Qt::ShiftModifier; if (event->button() == Qt::RightButton) { - mMouseRightClicked = false; - mIsScrolling = false; + m_mouseRightClicked = false; + m_isScrolling = false; } if (event->button() == Qt::MidButton) { - mMouseMidClicked = false; + m_mouseMidClicked = false; } if (event->button() == Qt::LeftButton) { - TimeTrack* mouseCursorTrack = mPlugin->GetTrackAt(event->y()); - const bool elementTrackChanged = (mouseCursorTrack && mDragElementTrack && mouseCursorTrack != mDragElementTrack); + TimeTrack* mouseCursorTrack = m_plugin->GetTrackAt(event->y()); + const bool elementTrackChanged = (mouseCursorTrack && m_dragElementTrack && mouseCursorTrack != m_dragElementTrack); - if (mDragging && mMouseLeftClicked && mDraggingElement && !mIsScrolling && !mResizing) + if (m_dragging && m_mouseLeftClicked && m_draggingElement && !m_isScrolling && !m_resizing) { - SetPausedTime(aznumeric_cast(mDraggingElement->GetStartTime())); + SetPausedTime(aznumeric_cast(m_draggingElement->GetStartTime())); } - if ((mResizing || mDragging) && elementTrackChanged == false && mDraggingElement) + if ((m_resizing || m_dragging) && elementTrackChanged == false && m_draggingElement) { - emit MotionEventChanged(mDraggingElement, mDraggingElement->GetStartTime(), mDraggingElement->GetEndTime()); + emit MotionEventChanged(m_draggingElement, m_draggingElement->GetStartTime(), m_draggingElement->GetEndTime()); } - mMouseLeftClicked = false; - mDragging = false; - mResizing = false; - mIsScrolling = false; + m_mouseLeftClicked = false; + m_dragging = false; + m_resizing = false; + m_isScrolling = false; // rect selection - if (mRectSelecting) + if (m_rectSelecting) { - if (mRectZooming) + if (m_rectZooming) { - mRectZooming = false; + m_rectZooming = false; // calc the selection rect QRect selectRect; @@ -1541,7 +1541,7 @@ namespace EMStudio // zoom in on the rect if (selectRect.isEmpty() == false) { - mPlugin->ZoomRect(selectRect); + m_plugin->ZoomRect(selectRect); } } else @@ -1553,8 +1553,6 @@ namespace EMStudio // select things inside it if (selectRect.isEmpty() == false) { - //selectRect = mActiveGraph->GetTransform().inverted().mapRect( selectRect ); - // rect select the elements const bool overwriteSelection = (ctrlPressed == false); SelectElementsInRect(selectRect, overwriteSelection, true, ctrlPressed); @@ -1563,37 +1561,37 @@ namespace EMStudio } // check if we moved an element to another track - if (elementTrackChanged && mDraggingElement) + if (elementTrackChanged && m_draggingElement) { // lastly fire a signal so that the data can change along with - emit ElementTrackChanged(mDraggingElement->GetElementNumber(), aznumeric_cast(mDraggingElement->GetStartTime()), aznumeric_cast(mDraggingElement->GetEndTime()), mDragElementTrack->GetName(), mouseCursorTrack->GetName()); + emit ElementTrackChanged(m_draggingElement->GetElementNumber(), aznumeric_cast(m_draggingElement->GetStartTime()), aznumeric_cast(m_draggingElement->GetEndTime()), m_dragElementTrack->GetName(), mouseCursorTrack->GetName()); } - mDragElementTrack = nullptr; + m_dragElementTrack = nullptr; - if (mDraggingElement) + if (m_draggingElement) { - mDraggingElement->SetShowTimeHandles(false); - mDraggingElement = nullptr; + m_draggingElement->SetShowTimeHandles(false); + m_draggingElement = nullptr; } // disable rect selection mode again - mRectSelecting = false; + m_rectSelecting = false; return; } // disable rect selection mode again - mRectSelecting = false; + m_rectSelecting = false; UpdateMouseOverCursor(event->x(), event->y()); } void TrackDataWidget::ClearState() { - mDragElementTrack = nullptr; - mDraggingElement = nullptr; - mDragging = false; - mResizing = false; - mResizeElement = nullptr; + m_dragElementTrack = nullptr; + m_draggingElement = nullptr; + m_dragging = false; + m_resizing = false; + m_resizeElement = nullptr; } // the mouse wheel is adjusted @@ -1637,15 +1635,15 @@ namespace EMStudio // handle mouse wheel event void TrackDataWidget::wheelEvent(QWheelEvent* event) { - DoWheelEvent(event, mPlugin); + DoWheelEvent(event, m_plugin); } // drag & drop support void TrackDataWidget::dragEnterEvent(QDragEnterEvent* event) { - mPlugin->SetRedrawFlag(); - mOldCurrentTime = mPlugin->GetCurrentTime(); + m_plugin->SetRedrawFlag(); + m_oldCurrentTime = m_plugin->GetCurrentTime(); // this is needed to actually reach the drop event function event->acceptProposedAction(); @@ -1654,11 +1652,11 @@ namespace EMStudio void TrackDataWidget::dragMoveEvent(QDragMoveEvent* event) { - mPlugin->SetRedrawFlag(); + m_plugin->SetRedrawFlag(); QPoint mousePos = event->pos(); - double dropTime = mPlugin->PixelToTime(mousePos.x()); - mPlugin->SetCurrentTime(dropTime); + double dropTime = m_plugin->PixelToTime(mousePos.x()); + m_plugin->SetCurrentTime(dropTime); SetPausedTime(aznumeric_cast(dropTime)); } @@ -1666,26 +1664,26 @@ namespace EMStudio void TrackDataWidget::dropEvent(QDropEvent* event) { - mPlugin->SetRedrawFlag(); + m_plugin->SetRedrawFlag(); // accept the drop event->acceptProposedAction(); // emit drop event emit MotionEventPresetsDropped(event->pos()); - mPlugin->SetCurrentTime(mOldCurrentTime); + m_plugin->SetCurrentTime(m_oldCurrentTime); } // the context menu event void TrackDataWidget::contextMenuEvent(QContextMenuEvent* event) { - if (mIsScrolling || mDragging || mResizing || !mAllowContextMenu) + if (m_isScrolling || m_dragging || m_resizing || !m_allowContextMenu) { return; } - mPlugin->SetRedrawFlag(); + m_plugin->SetRedrawFlag(); if (EMotionFX::GetRecorder().GetRecordTime() > MCore::Math::epsilon) { @@ -1693,26 +1691,26 @@ namespace EMStudio return; } - if (mPlugin->mMotion == nullptr) + if (m_plugin->m_motion == nullptr) { return; } QPoint point = event->pos(); - mContextMenuX = point.x(); - mContextMenuY = point.y(); + m_contextMenuX = point.x(); + m_contextMenuY = point.y(); - TimeTrack* timeTrack = mPlugin->GetTrackAt(mContextMenuY); + TimeTrack* timeTrack = m_plugin->GetTrackAt(m_contextMenuY); size_t numElements = 0; size_t numSelectedElements = 0; // calculate the number of selected and total events - const size_t numTracks = mPlugin->GetNumTracks(); + const size_t numTracks = m_plugin->GetNumTracks(); for (size_t i = 0; i < numTracks; ++i) { // get the current time view track - TimeTrack* track = mPlugin->GetTrack(i); + TimeTrack* track = m_plugin->GetTrack(i); if (track->GetIsVisible() == false) { continue; @@ -1751,7 +1749,7 @@ namespace EMStudio if (timeTrack) { - TimeTrackElement* element = mPlugin->GetElementAt(mContextMenuX, mContextMenuY); + TimeTrackElement* element = m_plugin->GetElementAt(m_contextMenuX, m_contextMenuY); if (element == nullptr) { QAction* action = menu.addAction("Add motion event"); @@ -1840,9 +1838,9 @@ namespace EMStudio // propagate key events to the plugin and let it handle by a shared function void TrackDataWidget::keyPressEvent(QKeyEvent* event) { - if (mPlugin) + if (m_plugin) { - mPlugin->OnKeyPressEvent(event); + m_plugin->OnKeyPressEvent(event); } } @@ -1850,31 +1848,31 @@ namespace EMStudio // propagate key events to the plugin and let it handle by a shared function void TrackDataWidget::keyReleaseEvent(QKeyEvent* event) { - if (mPlugin) + if (m_plugin) { - mPlugin->OnKeyReleaseEvent(event); + m_plugin->OnKeyReleaseEvent(event); } } void TrackDataWidget::AddMotionEvent(int32 x, int32 y) { - mPlugin->AddMotionEvent(x, y); + m_plugin->AddMotionEvent(x, y); } void TrackDataWidget::RemoveMotionEvent(int32 x, int32 y) { - mPlugin->SetRedrawFlag(); + m_plugin->SetRedrawFlag(); // get the time track on which we dropped the preset - TimeTrack* timeTrack = mPlugin->GetTrackAt(y); + TimeTrack* timeTrack = m_plugin->GetTrackAt(y); if (timeTrack == nullptr) { return; } // get the time track on which we dropped the preset - TimeTrackElement* element = mPlugin->GetElementAt(x, y); + TimeTrackElement* element = m_plugin->GetElementAt(x, y); if (element == nullptr) { return; @@ -1887,9 +1885,9 @@ namespace EMStudio // remove selected motion events in track void TrackDataWidget::RemoveSelectedMotionEventsInTrack() { - mPlugin->SetRedrawFlag(); + m_plugin->SetRedrawFlag(); // get the track where we are at the moment - TimeTrack* timeTrack = mPlugin->GetTrackAt(mLastMouseY); + TimeTrack* timeTrack = m_plugin->GetTrackAt(m_lastMouseY); if (timeTrack == nullptr) { return; @@ -1913,7 +1911,7 @@ namespace EMStudio // remove the motion events CommandSystem::CommandHelperRemoveMotionEvents(timeTrack->GetName(), eventNumbers); - mPlugin->UnselectAllElements(); + m_plugin->UnselectAllElements(); ClearState(); } @@ -1921,9 +1919,9 @@ namespace EMStudio // remove all motion events in track void TrackDataWidget::RemoveAllMotionEventsInTrack() { - mPlugin->SetRedrawFlag(); + m_plugin->SetRedrawFlag(); - TimeTrack* timeTrack = mPlugin->GetTrackAt(mLastMouseY); + TimeTrack* timeTrack = m_plugin->GetTrackAt(m_lastMouseY); if (timeTrack == nullptr) { return; @@ -1941,19 +1939,19 @@ namespace EMStudio // remove the motion events CommandSystem::CommandHelperRemoveMotionEvents(timeTrack->GetName(), eventNumbers); - mPlugin->UnselectAllElements(); + m_plugin->UnselectAllElements(); ClearState(); } void TrackDataWidget::OnRemoveEventTrack() { - const TimeTrack* timeTrack = mPlugin->GetTrackAt(mLastMouseY); + const TimeTrack* timeTrack = m_plugin->GetTrackAt(m_lastMouseY); if (!timeTrack) { return; } - const AZ::Outcome trackIndexOutcome = mPlugin->FindTrackIndex(timeTrack); + const AZ::Outcome trackIndexOutcome = m_plugin->FindTrackIndex(timeTrack); if (trackIndexOutcome.IsSuccess()) { RemoveTrack(trackIndexOutcome.GetValue()); @@ -1963,10 +1961,10 @@ namespace EMStudio void TrackDataWidget::FillCopyElements(bool selectedItemsOnly) { // clear the array before feeding it - mCopyElements.clear(); + m_copyElements.clear(); // get the time track name - const TimeTrack* timeTrack = mPlugin->GetTrackAt(mContextMenuY); + const TimeTrack* timeTrack = m_plugin->GetTrackAt(m_contextMenuY); if (timeTrack == nullptr) { return; @@ -1974,7 +1972,7 @@ namespace EMStudio const AZStd::string trackName = timeTrack->GetName(); // check if the motion is valid and return failure in case it is not - const EMotionFX::Motion* motion = mPlugin->GetMotion(); + const EMotionFX::Motion* motion = m_plugin->GetMotion(); if (motion == nullptr) { return; @@ -2004,7 +2002,7 @@ namespace EMStudio const EMotionFX::MotionEvent& motionEvent = eventTrack->GetEvent(i); // create the copy paste element and add it to the array - mCopyElements.emplace_back( + m_copyElements.emplace_back( motion->GetID(), eventTrack->GetNameString(), motionEvent.GetEventDatas(), @@ -2018,44 +2016,44 @@ namespace EMStudio // cut all events from a track void TrackDataWidget::OnCutTrack() { - mPlugin->SetRedrawFlag(); + m_plugin->SetRedrawFlag(); FillCopyElements(false); - mCutMode = true; + m_cutMode = true; } // copy all events from a track void TrackDataWidget::OnCopyTrack() { - mPlugin->SetRedrawFlag(); + m_plugin->SetRedrawFlag(); FillCopyElements(false); - mCutMode = false; + m_cutMode = false; } // cut motion event void TrackDataWidget::OnCutElement() { - mPlugin->SetRedrawFlag(); + m_plugin->SetRedrawFlag(); FillCopyElements(true); - mCutMode = true; + m_cutMode = true; } // copy motion event void TrackDataWidget::OnCopyElement() { - mPlugin->SetRedrawFlag(); + m_plugin->SetRedrawFlag(); FillCopyElements(true); - mCutMode = false; + m_cutMode = false; } @@ -2080,10 +2078,10 @@ namespace EMStudio // paste motion events void TrackDataWidget::DoPaste(bool useLocation) { - mPlugin->SetRedrawFlag(); + m_plugin->SetRedrawFlag(); // get the time track name where we are pasting - TimeTrack* timeTrack = mPlugin->GetTrackAt(mContextMenuY); + TimeTrack* timeTrack = m_plugin->GetTrackAt(m_contextMenuY); if (timeTrack == nullptr) { return; @@ -2091,23 +2089,23 @@ namespace EMStudio AZStd::string trackName = timeTrack->GetName(); // get the number of elements to copy - const size_t numElements = mCopyElements.size(); + const size_t numElements = m_copyElements.size(); // create the command group MCore::CommandGroup commandGroup("Paste motion events"); // find the min and maximum time values of the events to paste - auto [minEvent, maxEvent] = AZStd::minmax_element(begin(mCopyElements), end(mCopyElements), [](const CopyElement& left, const CopyElement& right) + auto [minEvent, maxEvent] = AZStd::minmax_element(begin(m_copyElements), end(m_copyElements), [](const CopyElement& left, const CopyElement& right) { return left.m_startTime < right.m_startTime; }); - if (mCutMode) + if (m_cutMode) { // iterate through the copy elements from back to front and delete the selected ones for (int32 i = static_cast(numElements) - 1; i >= 0; i--) { - const CopyElement& copyElement = mCopyElements[i]; + const CopyElement& copyElement = m_copyElements[i]; // get the motion to which the original element belongs to EMotionFX::Motion* motion = EMotionFX::GetMotionManager().FindMotionByID(copyElement.m_motionID); @@ -2146,10 +2144,10 @@ namespace EMStudio } } - const float offset = useLocation ? aznumeric_cast(mPlugin->PixelToTime(mContextMenuX, true)) - minEvent->m_startTime : 0.0f; + const float offset = useLocation ? aznumeric_cast(m_plugin->PixelToTime(m_contextMenuX, true)) - minEvent->m_startTime : 0.0f; // iterate through the elements to copy and add the new motion events - for (const CopyElement& copyElement : mCopyElements) + for (const CopyElement& copyElement : m_copyElements) { float startTime = copyElement.m_startTime + offset; float endTime = copyElement.m_endTime + offset; @@ -2171,16 +2169,16 @@ namespace EMStudio MCore::LogError(outResult.c_str()); } - if (mCutMode) + if (m_cutMode) { - mCopyElements.clear(); + m_copyElements.clear(); } } void TrackDataWidget::OnCreatePresetEvent() { - mPlugin->SetRedrawFlag(); + m_plugin->SetRedrawFlag(); EMStudioPlugin* plugin = EMStudio::GetPluginManager()->FindActivePlugin(MotionEventsPlugin::CLASS_ID); if (plugin == nullptr) { @@ -2189,13 +2187,13 @@ namespace EMStudio MotionEventsPlugin* eventsPlugin = static_cast(plugin); - QPoint mousePos(mContextMenuX, mContextMenuY); + QPoint mousePos(m_contextMenuX, m_contextMenuY); eventsPlugin->OnEventPresetDropped(mousePos); } void TrackDataWidget::OnAddTrack() { - mPlugin->SetRedrawFlag(); + m_plugin->SetRedrawFlag(); CommandSystem::CommandAddEventTrack(); } @@ -2203,11 +2201,11 @@ namespace EMStudio void TrackDataWidget::SelectElementsInRect(const QRect& rect, bool overwriteCurSelection, bool select, bool toggleMode) { // get the number of tracks and iterate through them - const size_t numTracks = mPlugin->GetNumTracks(); + const size_t numTracks = m_plugin->GetNumTracks(); for (size_t i = 0; i < numTracks; ++i) { // get the current time track - TimeTrack* track = mPlugin->GetTrack(i); + TimeTrack* track = m_plugin->GetTrack(i); if (track->GetIsVisible() == false) { continue; @@ -2262,7 +2260,7 @@ namespace EMStudio else { // get the hovered element and track - TimeTrackElement* element = mPlugin->GetElementAt(localPos.x(), localPos.y()); + TimeTrackElement* element = m_plugin->GetElementAt(localPos.x(), localPos.y()); if (element == nullptr) { return QOpenGLWidget::event(event); @@ -2291,20 +2289,20 @@ namespace EMStudio const EMotionFX::Recorder::ActorInstanceData* actorInstanceData = FindActorInstanceData(); // if we recorded node history - mNodeHistoryRect = QRect(); - if (actorInstanceData && !actorInstanceData->mNodeHistoryItems.empty()) + m_nodeHistoryRect = QRect(); + if (actorInstanceData && !actorInstanceData->m_nodeHistoryItems.empty()) { - const int height = aznumeric_caster((recorder.CalcMaxNodeHistoryTrackIndex(*actorInstanceData) + 1) * (mNodeHistoryItemHeight + 3) + mNodeRectsStartHeight); - mNodeHistoryRect.setTop(mNodeRectsStartHeight); - mNodeHistoryRect.setBottom(height); - mNodeHistoryRect.setLeft(0); - mNodeHistoryRect.setRight(geometry().width()); + const int height = aznumeric_caster((recorder.CalcMaxNodeHistoryTrackIndex(*actorInstanceData) + 1) * (m_nodeHistoryItemHeight + 3) + m_nodeRectsStartHeight); + m_nodeHistoryRect.setTop(m_nodeRectsStartHeight); + m_nodeHistoryRect.setBottom(height); + m_nodeHistoryRect.setLeft(0); + m_nodeHistoryRect.setRight(geometry().width()); } - mEventHistoryTotalHeight = 0; - if (actorInstanceData && !actorInstanceData->mEventHistoryItems.empty()) + m_eventHistoryTotalHeight = 0; + if (actorInstanceData && !actorInstanceData->m_eventHistoryItems.empty()) { - mEventHistoryTotalHeight = aznumeric_caster((recorder.CalcMaxEventHistoryTrackIndex(*actorInstanceData) + 1) * 20); + m_eventHistoryTotalHeight = aznumeric_caster((recorder.CalcMaxEventHistoryTrackIndex(*actorInstanceData) + 1) * 20); } } @@ -2322,22 +2320,22 @@ namespace EMStudio return nullptr; } - // make sure the mTrackRemap array is up to date - RecorderGroup* recorderGroup = mPlugin->GetTimeViewToolBar()->GetRecorderGroup(); + // make sure the m_trackRemap array is up to date + RecorderGroup* recorderGroup = m_plugin->GetTimeViewToolBar()->GetRecorderGroup(); const bool sorted = recorderGroup->GetSortNodeActivity(); - const int graphContentsCode = mPlugin->mTrackHeaderWidget->mNodeContentsComboBox->currentIndex(); - EMotionFX::GetRecorder().ExtractNodeHistoryItems(*actorInstanceData, aznumeric_cast(mPlugin->mCurTime), sorted, (EMotionFX::Recorder::EValueType)graphContentsCode, &mActiveItems, &mTrackRemap); + const int graphContentsCode = m_plugin->m_trackHeaderWidget->m_nodeContentsComboBox->currentIndex(); + EMotionFX::GetRecorder().ExtractNodeHistoryItems(*actorInstanceData, aznumeric_cast(m_plugin->m_curTime), sorted, (EMotionFX::Recorder::EValueType)graphContentsCode, &m_activeItems, &m_trackRemap); // get the history items shortcut - const AZStd::vector& historyItems = actorInstanceData->mNodeHistoryItems; + const AZStd::vector& historyItems = actorInstanceData->m_nodeHistoryItems; QRect rect; for (EMotionFX::Recorder::NodeHistoryItem* curItem : historyItems) { // draw the background rect - double startTimePixel = mPlugin->TimeToPixel(curItem->mStartTime); - double endTimePixel = mPlugin->TimeToPixel(curItem->mEndTime); + double startTimePixel = m_plugin->TimeToPixel(curItem->m_startTime); + double endTimePixel = m_plugin->TimeToPixel(curItem->m_endTime); if (startTimePixel > x || endTimePixel < x) { @@ -2346,8 +2344,8 @@ namespace EMStudio rect.setLeft(aznumeric_cast(startTimePixel)); rect.setRight(aznumeric_cast(endTimePixel)); - rect.setTop((mNodeRectsStartHeight + (aznumeric_cast(mTrackRemap[curItem->mTrackIndex]) * (mNodeHistoryItemHeight + 3)) + 3)); - rect.setBottom(rect.top() + mNodeHistoryItemHeight); + rect.setTop((m_nodeRectsStartHeight + (aznumeric_cast(m_trackRemap[curItem->m_trackIndex]) * (m_nodeHistoryItemHeight + 3)) + 3)); + rect.setBottom(rect.top() + m_nodeHistoryItemHeight); if (rect.contains(x, y)) { @@ -2387,8 +2385,8 @@ namespace EMStudio void TrackDataWidget::DoRecorderContextMenuEvent(QContextMenuEvent* event) { QPoint point = event->pos(); - mContextMenuX = point.x(); - mContextMenuY = point.y(); + m_contextMenuX = point.x(); + m_contextMenuY = point.y(); // create the context menu QMenu menu(this); @@ -2397,10 +2395,10 @@ namespace EMStudio // Timeline actions //--------------------- QAction* action = menu.addAction("Zoom To Fit All"); - connect(action, &QAction::triggered, mPlugin, &TimeViewPlugin::OnZoomAll); + connect(action, &QAction::triggered, m_plugin, &TimeViewPlugin::OnZoomAll); action = menu.addAction("Reset Timeline"); - connect(action, &QAction::triggered, mPlugin, &TimeViewPlugin::OnResetTimeline); + connect(action, &QAction::triggered, m_plugin, &TimeViewPlugin::OnResetTimeline); //--------------------- // Right-clicked on a motion item @@ -2411,7 +2409,7 @@ namespace EMStudio menu.addSeparator(); action = menu.addAction("Show Node In Graph"); - connect(action, &QAction::triggered, mPlugin, &TimeViewPlugin::OnShowNodeHistoryNodeInGraph); + connect(action, &QAction::triggered, m_plugin, &TimeViewPlugin::OnShowNodeHistoryNodeInGraph); } // show the menu at the given position @@ -2425,15 +2423,15 @@ namespace EMStudio // node name outString += AZStd::string::format("

Node Name: 

"); - outString += AZStd::string::format("

%s

", item->mName.c_str()); + outString += AZStd::string::format("

%s

", item->m_name.c_str()); // build the node path string - EMotionFX::ActorInstance* actorInstance = FindActorInstanceData()->mActorInstance; + EMotionFX::ActorInstance* actorInstance = FindActorInstanceData()->m_actorInstance; EMotionFX::AnimGraphInstance* animGraphInstance = actorInstance->GetAnimGraphInstance(); if (animGraphInstance) { EMotionFX::AnimGraph* animGraph = animGraphInstance->GetAnimGraph(); - EMotionFX::AnimGraphNode* node = animGraph->RecursiveFindNodeById(item->mNodeId); + EMotionFX::AnimGraphNode* node = animGraph->RecursiveFindNodeById(item->m_nodeId); if (node) { AZStd::vector nodePath; @@ -2476,13 +2474,13 @@ namespace EMStudio } // motion name - if (item->mMotionID != InvalidIndex32 && !item->mMotionFileName.empty()) + if (item->m_motionId != InvalidIndex32 && !item->m_motionFileName.empty()) { outString += AZStd::string::format("

Motion FileName: 

"); - outString += AZStd::string::format("

%s

", item->mMotionFileName.c_str()); + outString += AZStd::string::format("

%s

", item->m_motionFileName.c_str()); // show motion info - EMotionFX::Motion* motion = EMotionFX::GetMotionManager().FindMotionByID(item->mMotionID); + EMotionFX::Motion* motion = EMotionFX::GetMotionManager().FindMotionByID(item->m_motionId); if (motion) { AZStd::string path; @@ -2525,14 +2523,14 @@ namespace EMStudio return nullptr; } - const AZStd::vector& historyItems = actorInstanceData->mEventHistoryItems; + const AZStd::vector& historyItems = actorInstanceData->m_eventHistoryItems; const float tickHalfWidth = 7; const float tickHeight = 16; for (EMotionFX::Recorder::EventHistoryItem* curItem : historyItems) { - float height = aznumeric_caster((curItem->mTrackIndex * 20) + mEventsStartHeight); - double startTimePixel = mPlugin->TimeToPixel(curItem->mStartTime); + float height = aznumeric_caster((curItem->m_trackIndex * 20) + m_eventsStartHeight); + double startTimePixel = m_plugin->TimeToPixel(curItem->m_startTime); const QRect rect(QPoint(aznumeric_cast(startTimePixel - tickHalfWidth), aznumeric_cast(height)), QSize(aznumeric_cast(tickHalfWidth * 2), aznumeric_cast(tickHeight))); if (rect.contains(QPoint(x, y))) @@ -2550,7 +2548,7 @@ namespace EMStudio { outString = ""; - const EMotionFX::MotionEvent* motionEvent = item->mEventInfo.mEvent; + const EMotionFX::MotionEvent* motionEvent = item->m_eventInfo.m_event; for (const EMotionFX::EventDataPtr& eventData : motionEvent->GetEventDatas()) { if (eventData) @@ -2574,25 +2572,25 @@ namespace EMStudio outString += AZStd::string::format(""); outString += AZStd::string::format(""); - outString += AZStd::string::format("", item->mEventInfo.mTimeValue); + outString += AZStd::string::format("", item->m_eventInfo.m_timeValue); outString += AZStd::string::format(""); - outString += AZStd::string::format("", item->mStartTime); + outString += AZStd::string::format("", item->m_startTime); outString += AZStd::string::format(""); - outString += AZStd::string::format("", (item->mIsTickEvent == false) ? "Yes" : "No"); + outString += AZStd::string::format("", (item->m_isTickEvent == false) ? "Yes" : "No"); - if (item->mIsTickEvent == false) + if (item->m_isTickEvent == false) { const static AZStd::string eventStartText = "Event Start"; const static AZStd::string eventActiveText = "Event Active"; const static AZStd::string eventEndText = "Event End"; const AZStd::string* outputEventStateText = &eventStartText; - if (item->mEventInfo.m_eventState == EMotionFX::EventInfo::EventState::ACTIVE) + if (item->m_eventInfo.m_eventState == EMotionFX::EventInfo::EventState::ACTIVE) { outputEventStateText = &eventActiveText; } - else if (item->mEventInfo.m_eventState == EMotionFX::EventInfo::EventState::END) + else if (item->m_eventInfo.m_eventState == EMotionFX::EventInfo::EventState::END) { outputEventStateText = &eventEndText; } @@ -2601,18 +2599,18 @@ namespace EMStudio } outString += AZStd::string::format(""); - outString += AZStd::string::format("", item->mEventInfo.mGlobalWeight); + outString += AZStd::string::format("", item->m_eventInfo.m_globalWeight); outString += AZStd::string::format(""); - outString += AZStd::string::format("", item->mEventInfo.mLocalWeight); + outString += AZStd::string::format("", item->m_eventInfo.m_localWeight); // build the node path string - EMotionFX::ActorInstance* actorInstance = FindActorInstanceData()->mActorInstance; + EMotionFX::ActorInstance* actorInstance = FindActorInstanceData()->m_actorInstance; EMotionFX::AnimGraphInstance* animGraphInstance = actorInstance->GetAnimGraphInstance(); if (animGraphInstance) { - EMotionFX::AnimGraph* animGraph = EMotionFX::GetAnimGraphManager().FindAnimGraphByID(item->mAnimGraphID);//animGraphInstance->GetAnimGraph(); - EMotionFX::AnimGraphNode* node = animGraph->RecursiveFindNodeById(item->mEmitterNodeId); + EMotionFX::AnimGraph* animGraph = EMotionFX::GetAnimGraphManager().FindAnimGraphByID(item->m_animGraphId);//animGraphInstance->GetAnimGraph(); + EMotionFX::AnimGraphNode* node = animGraph->RecursiveFindNodeById(item->m_emitterNodeId); if (node) { outString += AZStd::string::format(""); @@ -2696,7 +2694,7 @@ namespace EMStudio { painter.setPen(QColor(60, 70, 80)); painter.setBrush(Qt::NoBrush); - painter.drawLine(QPoint(0, heightOffset), QPoint(aznumeric_cast(mPlugin->TimeToPixel(animationLength)), heightOffset)); + painter.drawLine(QPoint(0, heightOffset), QPoint(aznumeric_cast(m_plugin->TimeToPixel(animationLength)), heightOffset)); return 1; } } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackDataWidget.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackDataWidget.h index 48effb92d0..d0cbf8f032 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackDataWidget.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackDataWidget.h @@ -73,8 +73,8 @@ namespace EMStudio void ElementTrackChanged(size_t eventNr, float startTime, float endTime, const char* oldTrackName, const char* newTrackName); private slots: - void OnRemoveElement() { RemoveMotionEvent(mContextMenuX, mContextMenuY); } - void OnAddElement() { AddMotionEvent(mContextMenuX, mContextMenuY); } + void OnRemoveElement() { RemoveMotionEvent(m_contextMenuX, m_contextMenuY); } + void OnAddElement() { AddMotionEvent(m_contextMenuX, m_contextMenuY); } void OnAddTrack(); void OnCreatePresetEvent(); void RemoveSelectedMotionEventsInTrack(); @@ -106,38 +106,38 @@ namespace EMStudio void PaintRelativeGraph(QPainter& painter, const QRect& rect, const EMotionFX::Recorder::ActorInstanceData* actorInstanceData); uint32 PaintSeparator(QPainter& painter, int32 heightOffset, float animationLength); - QBrush mBrushBackground; - QBrush mBrushBackgroundClipped; - QBrush mBrushBackgroundOutOfRange; - TimeViewPlugin* mPlugin; - bool mMouseLeftClicked; - bool mMouseMidClicked; - bool mMouseRightClicked; - bool mDragging; - bool mResizing; - bool mRectZooming; - bool mIsScrolling; - int32 mLastLeftClickedX; - int32 mLastMouseMoveX; - int32 mLastMouseX; - int32 mLastMouseY; - uint32 mNodeHistoryItemHeight; - uint32 mEventHistoryTotalHeight; - bool mAllowContextMenu; + QBrush m_brushBackground; + QBrush m_brushBackgroundClipped; + QBrush m_brushBackgroundOutOfRange; + TimeViewPlugin* m_plugin; + bool m_mouseLeftClicked; + bool m_mouseMidClicked; + bool m_mouseRightClicked; + bool m_dragging; + bool m_resizing; + bool m_rectZooming; + bool m_isScrolling; + int32 m_lastLeftClickedX; + int32 m_lastMouseMoveX; + int32 m_lastMouseX; + int32 m_lastMouseY; + uint32 m_nodeHistoryItemHeight; + uint32 m_eventHistoryTotalHeight; + bool m_allowContextMenu; - TimeTrackElement* mDraggingElement; - TimeTrack* mDragElementTrack; - TimeTrackElement* mResizeElement; - uint32 mResizeID; - int32 mContextMenuX; - int32 mContextMenuY; - uint32 mGraphStartHeight; - uint32 mEventsStartHeight; - uint32 mNodeRectsStartHeight; - double mOldCurrentTime; + TimeTrackElement* m_draggingElement; + TimeTrack* m_dragElementTrack; + TimeTrackElement* m_resizeElement; + uint32 m_resizeId; + int32 m_contextMenuX; + int32 m_contextMenuY; + uint32 m_graphStartHeight; + uint32 m_eventsStartHeight; + uint32 m_nodeRectsStartHeight; + double m_oldCurrentTime; - AZStd::vector mActiveItems; - AZStd::vector mTrackRemap; + AZStd::vector m_activeItems; + AZStd::vector m_trackRemap; // copy and paste struct CopyElement @@ -158,21 +158,21 @@ namespace EMStudio } }; - bool GetIsReadyForPaste() const { return mCopyElements.empty() == false; } + bool GetIsReadyForPaste() const { return m_copyElements.empty() == false; } void FillCopyElements(bool selectedItemsOnly); - AZStd::vector mCopyElements; - bool mCutMode; + AZStd::vector m_copyElements; + bool m_cutMode; - QFont mDataFont; - AZStd::string mTempString; + QFont m_dataFont; + AZStd::string m_tempString; // rect selection - QPoint mSelectStart; - QPoint mSelectEnd; - bool mRectSelecting; + QPoint m_selectStart; + QPoint m_selectEnd; + bool m_rectSelecting; - QRect mNodeHistoryRect; + QRect m_nodeHistoryRect; void CalcSelectRect(QRect& outRect); void SelectElementsInRect(const QRect& rect, bool overwriteCurSelection, bool select, bool toggleMode); @@ -181,7 +181,7 @@ namespace EMStudio void UpdateMouseOverCursor(int32 x, int32 y); void DrawTimeMarker(QPainter& painter, const QRect& rect); - bool GetIsInsideNodeHistory(int32 y) const { return mNodeHistoryRect.contains(1, y); } + bool GetIsInsideNodeHistory(int32 y) const { return m_nodeHistoryRect.contains(1, y); } void DoRecorderContextMenuEvent(QContextMenuEvent* event); void UpdateRects(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackHeaderWidget.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackHeaderWidget.cpp index 5b21d8c7b5..bbdaf6e4a7 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackHeaderWidget.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackHeaderWidget.cpp @@ -33,18 +33,18 @@ namespace EMStudio TrackHeaderWidget::TrackHeaderWidget(TimeViewPlugin* plugin, QWidget* parent) : QWidget(parent) { - mPlugin = plugin; - mTrackLayout = nullptr; - mTrackWidget = nullptr; - mStackWidget = nullptr; - mNodeNamesCheckBox = nullptr; - mMotionFilesCheckBox = nullptr; + m_plugin = plugin; + m_trackLayout = nullptr; + m_trackWidget = nullptr; + m_stackWidget = nullptr; + m_nodeNamesCheckBox = nullptr; + m_motionFilesCheckBox = nullptr; // create the main layout - mMainLayout = new QVBoxLayout(); - mMainLayout->setMargin(2); - mMainLayout->setSpacing(0); - mMainLayout->setAlignment(Qt::AlignTop); + m_mainLayout = new QVBoxLayout(); + m_mainLayout->setMargin(2); + m_mainLayout->setSpacing(0); + m_mainLayout->setAlignment(Qt::AlignTop); //////////////////////////////// // Create the add event button @@ -65,12 +65,12 @@ namespace EMStudio mainAddWidget->setFixedSize(175, 40); mainAddWidget->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - mMainLayout->addWidget(mainAddWidget); - mAddTrackWidget = mainAddWidget; + m_mainLayout->addWidget(mainAddWidget); + m_addTrackWidget = mainAddWidget; //////////////////////////////// // recorder settings - mStackWidget = new MysticQt::DialogStack(); + m_stackWidget = new MysticQt::DialogStack(); //----------- @@ -80,51 +80,51 @@ namespace EMStudio contentsLayout->setMargin(0); contentsWidget->setLayout(contentsLayout); - mNodeNamesCheckBox = new QCheckBox("Show Node Names"); - mNodeNamesCheckBox->setChecked(true); - mNodeNamesCheckBox->setCheckable(true); - AzQtComponents::CheckBox::applyToggleSwitchStyle(mNodeNamesCheckBox); - connect(mNodeNamesCheckBox, &QCheckBox::stateChanged, this, &TrackHeaderWidget::OnCheckBox); - contentsLayout->addWidget(mNodeNamesCheckBox); + m_nodeNamesCheckBox = new QCheckBox("Show Node Names"); + m_nodeNamesCheckBox->setChecked(true); + m_nodeNamesCheckBox->setCheckable(true); + AzQtComponents::CheckBox::applyToggleSwitchStyle(m_nodeNamesCheckBox); + connect(m_nodeNamesCheckBox, &QCheckBox::stateChanged, this, &TrackHeaderWidget::OnCheckBox); + contentsLayout->addWidget(m_nodeNamesCheckBox); - mMotionFilesCheckBox = new QCheckBox("Show Motion Files"); - mMotionFilesCheckBox->setChecked(false); - mMotionFilesCheckBox->setCheckable(true); - AzQtComponents::CheckBox::applyToggleSwitchStyle(mMotionFilesCheckBox); - connect(mMotionFilesCheckBox, &QCheckBox::stateChanged, this, &TrackHeaderWidget::OnCheckBox); - contentsLayout->addWidget(mMotionFilesCheckBox); + m_motionFilesCheckBox = new QCheckBox("Show Motion Files"); + m_motionFilesCheckBox->setChecked(false); + m_motionFilesCheckBox->setCheckable(true); + AzQtComponents::CheckBox::applyToggleSwitchStyle(m_motionFilesCheckBox); + connect(m_motionFilesCheckBox, &QCheckBox::stateChanged, this, &TrackHeaderWidget::OnCheckBox); + contentsLayout->addWidget(m_motionFilesCheckBox); QHBoxLayout* comboLayout = new QHBoxLayout(); comboLayout->addWidget(new QLabel("Nodes:")); - mNodeContentsComboBox = new QComboBox(); - mNodeContentsComboBox->setEditable(false); - mNodeContentsComboBox->addItem("Global Weights"); - mNodeContentsComboBox->addItem("Local Weights"); - mNodeContentsComboBox->addItem("Local Time"); - mNodeContentsComboBox->setCurrentIndex(0); - connect(mNodeContentsComboBox, static_cast(&QComboBox::currentIndexChanged), this, &TrackHeaderWidget::OnComboBoxIndexChanged); - comboLayout->addWidget(mNodeContentsComboBox); + m_nodeContentsComboBox = new QComboBox(); + m_nodeContentsComboBox->setEditable(false); + m_nodeContentsComboBox->addItem("Global Weights"); + m_nodeContentsComboBox->addItem("Local Weights"); + m_nodeContentsComboBox->addItem("Local Time"); + m_nodeContentsComboBox->setCurrentIndex(0); + connect(m_nodeContentsComboBox, static_cast(&QComboBox::currentIndexChanged), this, &TrackHeaderWidget::OnComboBoxIndexChanged); + comboLayout->addWidget(m_nodeContentsComboBox); contentsLayout->addLayout(comboLayout); comboLayout = new QHBoxLayout(); comboLayout->addWidget(new QLabel("Graph:")); - mGraphContentsComboBox = new QComboBox(); - mGraphContentsComboBox->setEditable(false); - mGraphContentsComboBox->addItem("Global Weights"); - mGraphContentsComboBox->addItem("Local Weights"); - mGraphContentsComboBox->addItem("Local Time"); - mGraphContentsComboBox->setCurrentIndex(0); - connect(mGraphContentsComboBox, static_cast(&QComboBox::currentIndexChanged), this, &TrackHeaderWidget::OnComboBoxIndexChanged); - comboLayout->addWidget(mGraphContentsComboBox); + m_graphContentsComboBox = new QComboBox(); + m_graphContentsComboBox->setEditable(false); + m_graphContentsComboBox->addItem("Global Weights"); + m_graphContentsComboBox->addItem("Local Weights"); + m_graphContentsComboBox->addItem("Local Time"); + m_graphContentsComboBox->setCurrentIndex(0); + connect(m_graphContentsComboBox, static_cast(&QComboBox::currentIndexChanged), this, &TrackHeaderWidget::OnComboBoxIndexChanged); + comboLayout->addWidget(m_graphContentsComboBox); contentsLayout->addLayout(comboLayout); - mStackWidget->Add(contentsWidget, "Contents", false, false, true); + m_stackWidget->Add(contentsWidget, "Contents", false, false, true); //----------- - mMainLayout->addWidget(mStackWidget); + m_mainLayout->addWidget(m_stackWidget); setFocusPolicy(Qt::StrongFocus); - setLayout(mMainLayout); + setLayout(m_mainLayout); ReInit(); } @@ -138,119 +138,119 @@ namespace EMStudio void TrackHeaderWidget::ReInit() { - mPlugin->SetRedrawFlag(); + m_plugin->SetRedrawFlag(); - if (mTrackWidget) + if (m_trackWidget) { - mTrackWidget->hide(); - mMainLayout->removeWidget(mTrackWidget); - mTrackWidget->deleteLater(); // TODO: this causes flickering, but normal deletion will make it crash + m_trackWidget->hide(); + m_mainLayout->removeWidget(m_trackWidget); + m_trackWidget->deleteLater(); // TODO: this causes flickering, but normal deletion will make it crash } - mTrackWidget = nullptr; + m_trackWidget = nullptr; // If we are in anim graph mode and have a recording, don't init for the motions. - if ((mPlugin->GetMode() != TimeViewMode::Motion) && - (EMotionFX::GetRecorder().GetIsRecording() || EMotionFX::GetRecorder().GetRecordTime() > MCore::Math::epsilon || EMotionFX::GetRecorder().GetIsInPlayMode() || !mPlugin->mMotion)) + if ((m_plugin->GetMode() != TimeViewMode::Motion) && + (EMotionFX::GetRecorder().GetIsRecording() || EMotionFX::GetRecorder().GetRecordTime() > MCore::Math::epsilon || EMotionFX::GetRecorder().GetIsInPlayMode() || !m_plugin->m_motion)) { - mAddTrackWidget->setVisible(false); + m_addTrackWidget->setVisible(false); setVisible(false); - if ((mPlugin->GetMode() != TimeViewMode::Motion) && + if ((m_plugin->GetMode() != TimeViewMode::Motion) && (EMotionFX::GetRecorder().GetIsRecording() || EMotionFX::GetRecorder().GetRecordTime() > MCore::Math::epsilon)) { - mStackWidget->setVisible(true); + m_stackWidget->setVisible(true); } else { - mStackWidget->setVisible(false); + m_stackWidget->setVisible(false); } return; } - mAddTrackWidget->setVisible(true); + m_addTrackWidget->setVisible(true); setVisible(true); - mStackWidget->setVisible(false); + m_stackWidget->setVisible(false); - if (mPlugin->mTracks.empty()) + if (m_plugin->m_tracks.empty()) { return; } - mTrackWidget = new QWidget(); - mTrackLayout = new QVBoxLayout(); - mTrackLayout->setMargin(0); - mTrackLayout->setSpacing(1); + m_trackWidget = new QWidget(); + m_trackLayout = new QVBoxLayout(); + m_trackLayout->setMargin(0); + m_trackLayout->setSpacing(1); - const size_t numTracks = mPlugin->mTracks.size(); + const size_t numTracks = m_plugin->m_tracks.size(); for (size_t i = 0; i < numTracks; ++i) { - TimeTrack* track = mPlugin->mTracks[i]; + TimeTrack* track = m_plugin->m_tracks[i]; if (track->GetIsVisible() == false) { continue; } - HeaderTrackWidget* widget = new HeaderTrackWidget(mTrackWidget, mPlugin, this, track, i); + HeaderTrackWidget* widget = new HeaderTrackWidget(m_trackWidget, m_plugin, this, track, i); connect(widget, &HeaderTrackWidget::TrackNameChanged, this, &TrackHeaderWidget::OnTrackNameChanged); connect(widget, &HeaderTrackWidget::EnabledStateChanged, this, &TrackHeaderWidget::OnTrackEnabledStateChanged); - mTrackLayout->addWidget(widget); + m_trackLayout->addWidget(widget); } - mTrackWidget->setLayout(mTrackLayout); - mMainLayout->addWidget(mTrackWidget); + m_trackWidget->setLayout(m_trackLayout); + m_mainLayout->addWidget(m_trackWidget); } HeaderTrackWidget::HeaderTrackWidget(QWidget* parent, TimeViewPlugin* parentPlugin, TrackHeaderWidget* trackHeaderWidget, TimeTrack* timeTrack, size_t trackIndex) : QWidget(parent) { - mPlugin = parentPlugin; + m_plugin = parentPlugin; QHBoxLayout* mainLayout = new QHBoxLayout(); mainLayout->setMargin(0); mainLayout->setSpacing(0); - mHeaderTrackWidget = trackHeaderWidget; - mEnabledCheckbox = new QCheckBox(); - mNameLabel = new QLabel(timeTrack->GetName()); - mNameEdit = new QLineEdit(timeTrack->GetName()); - mTrack = timeTrack; - mTrackIndex = trackIndex; + m_headerTrackWidget = trackHeaderWidget; + m_enabledCheckbox = new QCheckBox(); + m_nameLabel = new QLabel(timeTrack->GetName()); + m_nameEdit = new QLineEdit(timeTrack->GetName()); + m_track = timeTrack; + m_trackIndex = trackIndex; - mNameEdit->setVisible(false); - mNameEdit->setFrame(false); + m_nameEdit->setVisible(false); + m_nameEdit->setFrame(false); - mEnabledCheckbox->setFixedWidth(36); - AzQtComponents::CheckBox::applyToggleSwitchStyle(mEnabledCheckbox); + m_enabledCheckbox->setFixedWidth(36); + AzQtComponents::CheckBox::applyToggleSwitchStyle(m_enabledCheckbox); if (timeTrack->GetIsEnabled()) { - mEnabledCheckbox->setCheckState(Qt::Checked); + m_enabledCheckbox->setCheckState(Qt::Checked); } else { - mNameEdit->setStyleSheet("background-color: rgb(70, 70, 70);"); - mEnabledCheckbox->setCheckState(Qt::Unchecked); + m_nameEdit->setStyleSheet("background-color: rgb(70, 70, 70);"); + m_enabledCheckbox->setCheckState(Qt::Unchecked); } if (timeTrack->GetIsDeletable() == false) { - mNameEdit->setReadOnly(true); - mEnabledCheckbox->setEnabled(false); + m_nameEdit->setReadOnly(true); + m_enabledCheckbox->setEnabled(false); } else { - mNameLabel->installEventFilter(this); + m_nameLabel->installEventFilter(this); } - connect(mNameEdit, &QLineEdit::editingFinished, this, &HeaderTrackWidget::NameChanged); - connect(mNameEdit, &QLineEdit::textEdited, this, &HeaderTrackWidget::NameEdited); - connect(mEnabledCheckbox, &QCheckBox::stateChanged, this, &HeaderTrackWidget::EnabledCheckBoxChanged); + connect(m_nameEdit, &QLineEdit::editingFinished, this, &HeaderTrackWidget::NameChanged); + connect(m_nameEdit, &QLineEdit::textEdited, this, &HeaderTrackWidget::NameEdited); + connect(m_enabledCheckbox, &QCheckBox::stateChanged, this, &HeaderTrackWidget::EnabledCheckBoxChanged); setContextMenuPolicy(Qt::CustomContextMenu); connect(this, &QWidget::customContextMenuRequested, this, [this](const QPoint& pos) @@ -258,20 +258,18 @@ namespace EMStudio QMenu m; auto action = m.addAction(tr("Remove track"), this, [=] { - mPlugin->GetTrackDataWidget()->RemoveTrack(mTrackIndex); + m_plugin->GetTrackDataWidget()->RemoveTrack(m_trackIndex); }); - action->setEnabled(mTrack->GetIsDeletable()); + action->setEnabled(m_track->GetIsDeletable()); m.exec(mapToGlobal(pos)); }); mainLayout->insertSpacing(0, 4); - mainLayout->addWidget(mNameLabel); - mainLayout->addWidget(mNameEdit); - mainLayout->addWidget(mEnabledCheckbox); + mainLayout->addWidget(m_nameLabel); + mainLayout->addWidget(m_nameEdit); + mainLayout->addWidget(m_enabledCheckbox); mainLayout->insertSpacing(5, 2); - //mainLayout->setAlignment(mEnabledCheckbox, Qt::AlignLeft); - setLayout(mainLayout); setMinimumHeight(20); @@ -280,12 +278,12 @@ namespace EMStudio bool HeaderTrackWidget::eventFilter(QObject* object, QEvent* event) { - if (object == mNameLabel && event->type() == QEvent::MouseButtonDblClick) + if (object == m_nameLabel && event->type() == QEvent::MouseButtonDblClick) { - mNameLabel->setVisible(false); - mNameEdit->setVisible(true); - mNameEdit->selectAll(); - mNameEdit->setFocus(); + m_nameLabel->setVisible(false); + m_nameEdit->setVisible(true); + m_nameEdit->selectAll(); + m_nameEdit->setFocus(); } return QWidget::eventFilter(object, event); } @@ -293,28 +291,28 @@ namespace EMStudio void HeaderTrackWidget::NameChanged() { MCORE_ASSERT(sender()->inherits("QLineEdit")); - mPlugin->SetRedrawFlag(); + m_plugin->SetRedrawFlag(); QLineEdit* widget = qobject_cast(sender()); - mNameLabel->setVisible(true); - mNameEdit->setVisible(false); + m_nameLabel->setVisible(true); + m_nameEdit->setVisible(false); if (ValidateName()) { - mNameLabel->setText(widget->text()); - emit TrackNameChanged(widget->text(), mTrackIndex); + m_nameLabel->setText(widget->text()); + emit TrackNameChanged(widget->text(), m_trackIndex); } } bool HeaderTrackWidget::ValidateName() { - AZStd::string name = mNameEdit->text().toUtf8().data(); + AZStd::string name = m_nameEdit->text().toUtf8().data(); bool nameUnique = true; - const size_t numTracks = mPlugin->GetNumTracks(); + const size_t numTracks = m_plugin->GetNumTracks(); for (size_t i = 0; i < numTracks; ++i) { - TimeTrack* track = mPlugin->GetTrack(i); + TimeTrack* track = m_plugin->GetTrack(i); - if (mTrack != track) + if (m_track != track) { if (name == track->GetName()) { @@ -331,21 +329,21 @@ namespace EMStudio void HeaderTrackWidget::NameEdited(const QString& text) { MCORE_UNUSED(text); - mPlugin->SetRedrawFlag(); + m_plugin->SetRedrawFlag(); if (ValidateName() == false) { - GetManager()->SetWidgetAsInvalidInput(mNameEdit); + GetManager()->SetWidgetAsInvalidInput(m_nameEdit); } else { - mNameEdit->setStyleSheet(""); + m_nameEdit->setStyleSheet(""); } } void HeaderTrackWidget::EnabledCheckBoxChanged(int state) { - mPlugin->SetRedrawFlag(); + m_plugin->SetRedrawFlag(); bool enabled = false; if (state == Qt::Checked) @@ -353,16 +351,16 @@ namespace EMStudio enabled = true; } - emit EnabledStateChanged(enabled, mTrackIndex); + emit EnabledStateChanged(enabled, m_trackIndex); } // propagate key events to the plugin and let it handle by a shared function void HeaderTrackWidget::keyPressEvent(QKeyEvent* event) { - if (mPlugin) + if (m_plugin) { - mPlugin->OnKeyPressEvent(event); + m_plugin->OnKeyPressEvent(event); } } @@ -370,9 +368,9 @@ namespace EMStudio // propagate key events to the plugin and let it handle by a shared function void HeaderTrackWidget::keyReleaseEvent(QKeyEvent* event) { - if (mPlugin) + if (m_plugin) { - mPlugin->OnKeyReleaseEvent(event); + m_plugin->OnKeyReleaseEvent(event); } } @@ -380,9 +378,9 @@ namespace EMStudio // propagate key events to the plugin and let it handle by a shared function void TrackHeaderWidget::keyPressEvent(QKeyEvent* event) { - if (mPlugin) + if (m_plugin) { - mPlugin->OnKeyPressEvent(event); + m_plugin->OnKeyPressEvent(event); } } @@ -390,9 +388,9 @@ namespace EMStudio // propagate key events to the plugin and let it handle by a shared function void TrackHeaderWidget::keyReleaseEvent(QKeyEvent* event) { - if (mPlugin) + if (m_plugin) { - mPlugin->OnKeyReleaseEvent(event); + m_plugin->OnKeyReleaseEvent(event); } } @@ -401,16 +399,16 @@ namespace EMStudio void TrackHeaderWidget::OnDetailedNodesCheckBox(int state) { MCORE_UNUSED(state); - mPlugin->SetRedrawFlag(); + m_plugin->SetRedrawFlag(); - RecorderGroup* recorderGroup = mPlugin->GetTimeViewToolBar()->GetRecorderGroup(); + RecorderGroup* recorderGroup = m_plugin->GetTimeViewToolBar()->GetRecorderGroup(); if (!recorderGroup->GetDetailedNodes()) { - mPlugin->mTrackDataWidget->mNodeHistoryItemHeight = 20; + m_plugin->m_trackDataWidget->m_nodeHistoryItemHeight = 20; } else { - mPlugin->mTrackDataWidget->mNodeHistoryItemHeight = 35; + m_plugin->m_trackDataWidget->m_nodeHistoryItemHeight = 35; } } @@ -419,7 +417,7 @@ namespace EMStudio void TrackHeaderWidget::OnCheckBox(int state) { MCORE_UNUSED(state); - mPlugin->SetRedrawFlag(); + m_plugin->SetRedrawFlag(); } @@ -427,6 +425,6 @@ namespace EMStudio void TrackHeaderWidget::OnComboBoxIndexChanged(int state) { MCORE_UNUSED(state); - mPlugin->SetRedrawFlag(); + m_plugin->SetRedrawFlag(); } } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackHeaderWidget.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackHeaderWidget.h index dae551d2bb..b794f248f6 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackHeaderWidget.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackHeaderWidget.h @@ -48,14 +48,14 @@ namespace EMStudio public: HeaderTrackWidget(QWidget* parent, TimeViewPlugin* parentPlugin, TrackHeaderWidget* trackHeaderWidget, TimeTrack* timeTrack, size_t trackIndex); - QCheckBox* mEnabledCheckbox; - QLabel* mNameLabel; - QLineEdit* mNameEdit; - QPushButton* mRemoveButton; - TimeTrack* mTrack; - size_t mTrackIndex; - TrackHeaderWidget* mHeaderTrackWidget; - TimeViewPlugin* mPlugin; + QCheckBox* m_enabledCheckbox; + QLabel* m_nameLabel; + QLineEdit* m_nameEdit; + QPushButton* m_removeButton; + TimeTrack* m_track; + size_t m_trackIndex; + TrackHeaderWidget* m_headerTrackWidget; + TimeViewPlugin* m_plugin; bool ValidateName(); @@ -93,7 +93,7 @@ namespace EMStudio void ReInit(); void UpdateDataContents(); - QWidget* GetAddTrackWidget() { return mAddTrackWidget; } + QWidget* GetAddTrackWidget() { return m_addTrackWidget; } public slots: void OnAddTrackButtonClicked() { CommandSystem::CommandAddEventTrack(); } @@ -104,17 +104,17 @@ namespace EMStudio void OnComboBoxIndexChanged(int state); private: - TimeViewPlugin* mPlugin; - QVBoxLayout* mMainLayout; - QWidget* mTrackWidget; - QVBoxLayout* mTrackLayout; - QWidget* mAddTrackWidget; - QPushButton* mAddTrackButton; - MysticQt::DialogStack* mStackWidget; - QComboBox* mGraphContentsComboBox; - QComboBox* mNodeContentsComboBox; - QCheckBox* mNodeNamesCheckBox; - QCheckBox* mMotionFilesCheckBox; + TimeViewPlugin* m_plugin; + QVBoxLayout* m_mainLayout; + QWidget* m_trackWidget; + QVBoxLayout* m_trackLayout; + QWidget* m_addTrackWidget; + QPushButton* m_addTrackButton; + MysticQt::DialogStack* m_stackWidget; + QComboBox* m_graphContentsComboBox; + QComboBox* m_nodeContentsComboBox; + QCheckBox* m_nodeNamesCheckBox; + QCheckBox* m_motionFilesCheckBox; void keyPressEvent(QKeyEvent* event); void keyReleaseEvent(QKeyEvent* event); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/standardplugins_files.cmake b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/standardplugins_files.cmake index ae5a633c7f..65af4d50ee 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/standardplugins_files.cmake +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/standardplugins_files.cmake @@ -133,8 +133,6 @@ set(FILES Source/AnimGraph/ParameterEditor/Vector4ParameterEditor.h Source/CommandBar/CommandBarPlugin.cpp Source/CommandBar/CommandBarPlugin.h - Source/CommandBrowser/CommandBrowserPlugin.cpp - Source/CommandBrowser/CommandBrowserPlugin.h Source/LogWindow/LogWindowCallback.cpp Source/LogWindow/LogWindowCallback.h Source/LogWindow/LogWindowPlugin.cpp diff --git a/Gems/EMotionFX/Code/Editor/Platform/Windows/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindowEventFilter_Windows.cpp b/Gems/EMotionFX/Code/Editor/Platform/Windows/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindowEventFilter_Windows.cpp index 05bb9a5773..01ad023bd1 100644 --- a/Gems/EMotionFX/Code/Editor/Platform/Windows/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindowEventFilter_Windows.cpp +++ b/Gems/EMotionFX/Code/Editor/Platform/Windows/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindowEventFilter_Windows.cpp @@ -22,7 +22,7 @@ namespace EMStudio { // The reason why there are multiple of such messages is because it emits messages for all related hardware nodes. // But we do not know the name of the hardware to look for here either, so we can't filter that. - emit m_MainWindow->HardwareChangeDetected(); + emit m_mainWindow->HardwareChangeDetected(); } } diff --git a/Gems/EMotionFX/Code/MCore/Source/AABB.h b/Gems/EMotionFX/Code/MCore/Source/AABB.h index 04df59f453..3e6af3bc96 100644 --- a/Gems/EMotionFX/Code/MCore/Source/AABB.h +++ b/Gems/EMotionFX/Code/MCore/Source/AABB.h @@ -38,8 +38,8 @@ namespace MCore * @param maxPnt The maximum point. */ MCORE_INLINE AABB(const AZ::Vector3& minPnt, const AZ::Vector3& maxPnt) - : mMin(minPnt) - , mMax(maxPnt) {} + : m_min(minPnt) + , m_max(maxPnt) {} /** * Initialize the box minimum and maximum points. @@ -47,7 +47,7 @@ namespace MCore * Note, that the default constructor already calls this method. So you should only call it when you want to 'reset' the minimum and * maximum points of the box. */ - MCORE_INLINE void Init() { mMin.Set(FLT_MAX, FLT_MAX, FLT_MAX); mMax.Set(-FLT_MAX, -FLT_MAX, -FLT_MAX); } + MCORE_INLINE void Init() { m_min.Set(FLT_MAX, FLT_MAX, FLT_MAX); m_max.Set(-FLT_MAX, -FLT_MAX, -FLT_MAX); } /** * Check if this is a valid AABB or not. @@ -56,15 +56,15 @@ namespace MCore */ MCORE_INLINE bool CheckIfIsValid() const { - if (mMin.GetX() > mMax.GetX()) + if (m_min.GetX() > m_max.GetX()) { return false; } - if (mMin.GetY() > mMax.GetY()) + if (m_min.GetY() > m_max.GetY()) { return false; } - if (mMin.GetZ() > mMax.GetZ()) + if (m_min.GetZ() > m_max.GetZ()) { return false; } @@ -83,7 +83,7 @@ namespace MCore * This method automatically adjusts the minimum and maximum point of the box after 'adding' the given AABB to this box. * @param box The AABB to 'add' to this box. */ - MCORE_INLINE void Encapsulate(const AABB& box) { Encapsulate(box.mMin); Encapsulate(box.mMax); } + MCORE_INLINE void Encapsulate(const AABB& box) { Encapsulate(box.m_min); Encapsulate(box.m_max); } /** * Widen the box in all dimensions with a given number of units. @@ -91,12 +91,12 @@ namespace MCore */ MCORE_INLINE void Widen(float delta) { - mMin.SetX(mMin.GetX() - delta); - mMin.SetY(mMin.GetY() - delta); - mMin.SetZ(mMin.GetZ() - delta); - mMax.SetX(mMax.GetX() + delta); - mMax.SetY(mMax.GetY() + delta); - mMax.SetZ(mMax.GetZ() + delta); + m_min.SetX(m_min.GetX() - delta); + m_min.SetY(m_min.GetY() - delta); + m_min.SetZ(m_min.GetZ() - delta); + m_max.SetX(m_max.GetX() + delta); + m_max.SetY(m_max.GetY() + delta); + m_max.SetZ(m_max.GetZ() + delta); } /** @@ -104,7 +104,7 @@ namespace MCore * This means the middle of the box will be moved by the given vector. * @param offset The offset vector to translate (move) the box with. */ - MCORE_INLINE void Translate(const AZ::Vector3& offset) { mMin += offset; mMax += offset; } + MCORE_INLINE void Translate(const AZ::Vector3& offset) { m_min += offset; m_max += offset; } /** * Checks if a given point is inside this box or not. @@ -112,7 +112,7 @@ namespace MCore * @param v The vector (3D point) to perform the test with. * @result Returns true when the given point is inside the box, otherwise false is returned. */ - MCORE_INLINE bool Contains(const AZ::Vector3& v) const { return (InRange(v.GetX(), mMin.GetX(), mMax.GetX()) && InRange(v.GetZ(), mMin.GetZ(), mMax.GetZ()) && InRange(v.GetY(), mMin.GetY(), mMax.GetY())); } + MCORE_INLINE bool Contains(const AZ::Vector3& v) const { return (InRange(v.GetX(), m_min.GetX(), m_max.GetX()) && InRange(v.GetZ(), m_min.GetZ(), m_max.GetZ()) && InRange(v.GetY(), m_min.GetY(), m_max.GetY())); } /** * Checks if a given AABB is COMPLETELY inside this box or not. @@ -120,7 +120,7 @@ namespace MCore * @param box The AABB to perform the test with. * @result Returns true when the AABB 'b' is COMPLETELY inside this box. If it's completely or partially outside, false will be returned. */ - MCORE_INLINE bool Contains(const AABB& box) const { return (Contains(box.mMin) && Contains(box.mMax)); } + MCORE_INLINE bool Contains(const AABB& box) const { return (Contains(box.m_min) && Contains(box.m_max)); } /** * Checks if a given AABB partially or completely contains, so intersects, this box or not. @@ -128,35 +128,35 @@ namespace MCore * @param box The AABB to perform the test with. * @result Returns true when the given AABB 'b' is completely or partially inside this box. Only false will be returned when the given AABB 'b' is COMPLETELY outside this box. */ - MCORE_INLINE bool Intersects(const AABB& box) const { return !(mMin.GetX() > box.mMax.GetX() || mMax.GetX() < box.mMin.GetX() || mMin.GetY() > box.mMax.GetY() || mMax.GetY() < box.mMin.GetY() || mMin.GetZ() > box.mMax.GetZ() || mMax.GetZ() < box.mMin.GetZ()); } + MCORE_INLINE bool Intersects(const AABB& box) const { return !(m_min.GetX() > box.m_max.GetX() || m_max.GetX() < box.m_min.GetX() || m_min.GetY() > box.m_max.GetY() || m_max.GetY() < box.m_min.GetY() || m_min.GetZ() > box.m_max.GetZ() || m_max.GetZ() < box.m_min.GetZ()); } /** * Calculates and returns the width of the box. * The width is the distance between the minimum and maximum point, along the X-axis. * @result The width of the box. */ - MCORE_INLINE float CalcWidth() const { return mMax.GetX() - mMin.GetX(); } + MCORE_INLINE float CalcWidth() const { return m_max.GetX() - m_min.GetX(); } /** * Calculates and returns the height of the box. * The height is the distance between the minimum and maximum point, along the Z-axis. * @result The height of the box. */ - MCORE_INLINE float CalcHeight() const { return mMax.GetZ() - mMin.GetZ(); } + MCORE_INLINE float CalcHeight() const { return m_max.GetZ() - m_min.GetZ(); } /** * Calculates and returns the depth of the box. * The depth is the distance between the minimum and maximum point, along the Y-axis. * @result The depth of the box. */ - MCORE_INLINE float CalcDepth() const { return mMax.GetY() - mMin.GetY(); } + MCORE_INLINE float CalcDepth() const { return m_max.GetY() - m_min.GetY(); } /** * Calculate the volume of the box. * This equals width x height x depth. * @result The volume of the box. */ - MCORE_INLINE float CalcVolume() const { return (mMax.GetX() - mMin.GetX()) * (mMax.GetY() - mMin.GetY()) * (mMax.GetZ() - mMin.GetZ()); } + MCORE_INLINE float CalcVolume() const { return (m_max.GetX() - m_min.GetX()) * (m_max.GetY() - m_min.GetY()) * (m_max.GetZ() - m_min.GetZ()); } /** * Calculate the surface area of the box. @@ -164,9 +164,9 @@ namespace MCore */ MCORE_INLINE float CalcSurfaceArea() const { - const float width = mMax.GetX() - mMin.GetX(); - const float height = mMax.GetY() - mMin.GetY(); - const float depth = mMax.GetZ() - mMin.GetZ(); + const float width = m_max.GetX() - m_min.GetX(); + const float height = m_max.GetY() - m_min.GetY(); + const float depth = m_max.GetZ() - m_min.GetZ(); return (2.0f * height * width) + (2.0f * height * depth) + (2.0f * width * depth); } @@ -175,14 +175,14 @@ namespace MCore * This is simply done by taking the average of the minimum and maximum point along each axis. * @result The center (or middle) point of this box. */ - MCORE_INLINE AZ::Vector3 CalcMiddle() const { return (mMin + mMax) * 0.5f; } + MCORE_INLINE AZ::Vector3 CalcMiddle() const { return (m_min + m_max) * 0.5f; } /** * Calculates the extents of the box. * This is the vector from the center to a corner of the box. * @result The vector containing the extents. */ - MCORE_INLINE AZ::Vector3 CalcExtents() const { return (mMax - mMin) * 0.5f; } + MCORE_INLINE AZ::Vector3 CalcExtents() const { return (m_max - m_min) * 0.5f; } /** * Calculates the radius of this box. @@ -191,60 +191,60 @@ namespace MCore * get the minimum sphere which exactly contains this box. * @result The length of the center of the box to one of the extreme points. So the minimum radius of the bounding sphere containing this box. */ - MCORE_INLINE float CalcRadius() const { return SafeLength(mMax - mMin) * 0.5f; } + MCORE_INLINE float CalcRadius() const { return SafeLength(m_max - m_min) * 0.5f; } /** * Get the minimum point of the box. * @result The minimum point of the box. */ - MCORE_INLINE const AZ::Vector3& GetMin() const { return mMin; } + MCORE_INLINE const AZ::Vector3& GetMin() const { return m_min; } /** * Get the maximum point of the box. * @result The maximum point of the box. */ - MCORE_INLINE const AZ::Vector3& GetMax() const { return mMax; } + MCORE_INLINE const AZ::Vector3& GetMax() const { return m_max; } /** * Set the minimum point of the box. * @param minVec The vector representing the minimum point of the box. */ - MCORE_INLINE void SetMin(const AZ::Vector3& minVec) { mMin = minVec; } + MCORE_INLINE void SetMin(const AZ::Vector3& minVec) { m_min = minVec; } /** * Set the maximum point of the box. * @param maxVec The vector representing the maximum point of the box. */ - MCORE_INLINE void SetMax(const AZ::Vector3& maxVec) { mMax = maxVec; } + MCORE_INLINE void SetMax(const AZ::Vector3& maxVec) { m_max = maxVec; } void CalcCornerPoints(AZ::Vector3* outPoints) const { - outPoints[0].Set(mMin.GetX(), mMin.GetY(), mMax.GetZ()); // 4-------------5 - outPoints[1].Set(mMax.GetX(), mMin.GetY(), mMax.GetZ()); // /| / | - outPoints[2].Set(mMax.GetX(), mMin.GetY(), mMin.GetZ()); // 0------------1 | - outPoints[3].Set(mMin.GetX(), mMin.GetY(), mMin.GetZ()); // | | | | - outPoints[4].Set(mMin.GetX(), mMax.GetY(), mMax.GetZ()); // | 7----------|--6 - outPoints[5].Set(mMax.GetX(), mMax.GetY(), mMax.GetZ()); // | / | / - outPoints[6].Set(mMax.GetX(), mMax.GetY(), mMin.GetZ()); // |/ |/ - outPoints[7].Set(mMin.GetX(), mMax.GetY(), mMin.GetZ()); // 3------------2 + outPoints[0].Set(m_min.GetX(), m_min.GetY(), m_max.GetZ()); // 4-------------5 + outPoints[1].Set(m_max.GetX(), m_min.GetY(), m_max.GetZ()); // /| / | + outPoints[2].Set(m_max.GetX(), m_min.GetY(), m_min.GetZ()); // 0------------1 | + outPoints[3].Set(m_min.GetX(), m_min.GetY(), m_min.GetZ()); // | | | | + outPoints[4].Set(m_min.GetX(), m_max.GetY(), m_max.GetZ()); // | 7----------|--6 + outPoints[5].Set(m_max.GetX(), m_max.GetY(), m_max.GetZ()); // | / | / + outPoints[6].Set(m_max.GetX(), m_max.GetY(), m_min.GetZ()); // |/ |/ + outPoints[7].Set(m_min.GetX(), m_max.GetY(), m_min.GetZ()); // 3------------2 } private: - AZ::Vector3 mMin; /**< The minimum point. */ - AZ::Vector3 mMax; /**< The maximum point. */ + AZ::Vector3 m_min; /**< The minimum point. */ + AZ::Vector3 m_max; /**< The maximum point. */ }; // encapsulate a point in the box MCORE_INLINE void AABB::Encapsulate(const AZ::Vector3& v) { - mMin.SetX(Min(mMin.GetX(), v.GetX())); - mMin.SetY(Min(mMin.GetY(), v.GetY())); - mMin.SetZ(Min(mMin.GetZ(), v.GetZ())); + m_min.SetX(Min(m_min.GetX(), v.GetX())); + m_min.SetY(Min(m_min.GetY(), v.GetY())); + m_min.SetZ(Min(m_min.GetZ(), v.GetZ())); - mMax.SetX(Max(mMax.GetX(), v.GetX())); - mMax.SetY(Max(mMax.GetY(), v.GetY())); - mMax.SetZ(Max(mMax.GetZ(), v.GetZ())); + m_max.SetX(Max(m_max.GetX(), v.GetX())); + m_max.SetY(Max(m_max.GetY(), v.GetY())); + m_max.SetZ(Max(m_max.GetZ(), v.GetZ())); } } // namespace MCore diff --git a/Gems/EMotionFX/Code/MCore/Source/AlignedArray.h b/Gems/EMotionFX/Code/MCore/Source/AlignedArray.h index ef1d157e03..5ffaac2e40 100644 --- a/Gems/EMotionFX/Code/MCore/Source/AlignedArray.h +++ b/Gems/EMotionFX/Code/MCore/Source/AlignedArray.h @@ -40,10 +40,10 @@ namespace MCore * Initializes the array so it's empty and has no memory allocated. */ MCORE_INLINE AlignedArray() - : mData(nullptr) - , mLength(0) - , mMaxLength(0) - , mMemCategory(MCORE_MEMCATEGORY_ARRAY) {} + : m_data(nullptr) + , m_length(0) + , m_maxLength(0) + , m_memCategory(MCORE_MEMCATEGORY_ARRAY) {} /** * Constructor which creates a given number of elements. @@ -52,12 +52,12 @@ namespace MCore * @param memCategory The memory category the array is in. */ MCORE_INLINE explicit AlignedArray(T* elems, size_t num, uint16 memCategory = MCORE_MEMCATEGORY_ARRAY) - : mLength(num) - , mMaxLength(AllocSize(num)) - , mMemCategory(memCategory) + : m_length(num) + , m_maxLength(AllocSize(num)) + , m_memCategory(memCategory) { - mData = (T*)AlignedAllocate(mMaxLength * sizeof(T), alignment, mMemCategory, MEMORYBLOCK_ID, MCORE_FILE, MCORE_LINE); - for (size_t i = 0; i < mLength; ++i) + m_data = (T*)AlignedAllocate(m_maxLength * sizeof(T), alignment, m_memCategory, MEMORYBLOCK_ID, MCORE_FILE, MCORE_LINE); + for (size_t i = 0; i < m_length; ++i) { Construct(i, elems[i]); } @@ -69,15 +69,15 @@ namespace MCore * @param memCategory The memory category the array is in. */ MCORE_INLINE explicit AlignedArray(size_t initSize, uint16 memCategory = MCORE_MEMCATEGORY_ARRAY) - : mData(nullptr) - , mLength(initSize) - , mMaxLength(initSize) - , mMemCategory(memCategory) + : m_data(nullptr) + , m_length(initSize) + , m_maxLength(initSize) + , m_memCategory(memCategory) { - if (mMaxLength > 0) + if (m_maxLength > 0) { - mData = (T*)AlignedAllocate(mMaxLength * sizeof(T), alignment, mMemCategory, MEMORYBLOCK_ID, MCORE_FILE, MCORE_LINE); - for (size_t i = 0; i < mLength; ++i) + m_data = (T*)AlignedAllocate(m_maxLength * sizeof(T), alignment, m_memCategory, MEMORYBLOCK_ID, MCORE_FILE, MCORE_LINE); + for (size_t i = 0; i < m_length; ++i) { Construct(i); } @@ -89,16 +89,16 @@ namespace MCore * @param other The other array to copy the data from. */ AlignedArray(const AlignedArray& other) - : mData(nullptr) - , mLength(0) - , mMaxLength(0) - , mMemCategory(MCORE_MEMCATEGORY_ARRAY) { *this = other; } + : m_data(nullptr) + , m_length(0) + , m_maxLength(0) + , m_memCategory(MCORE_MEMCATEGORY_ARRAY) { *this = other; } /** * Move constructor. * @param other The array to move the data from. */ - AlignedArray(AlignedArray&& other) { mData = other.mData; mLength = other.mLength; mMaxLength = other.mMaxLength; mMemCategory = other.mMemCategory; other.mData = nullptr; other.mLength = 0; other.mMaxLength = 0; } + AlignedArray(AlignedArray&& other) { m_data = other.m_data; m_length = other.m_length; m_maxLength = other.m_maxLength; m_memCategory = other.m_memCategory; other.m_data = nullptr; other.m_length = 0; other.m_maxLength = 0; } /** * Destructor. Deletes all entry data. @@ -119,13 +119,13 @@ namespace MCore */ ~AlignedArray() { - for (size_t i = 0; i < mLength; ++i) + for (size_t i = 0; i < m_length; ++i) { Destruct(i); } - if (mData) + if (m_data) { - AlignedFree(mData); + AlignedFree(m_data); } } @@ -134,89 +134,89 @@ namespace MCore * On default the memory category is 0, which means unknown. * @result The memory category ID. */ - MCORE_INLINE uint16 GetMemoryCategory() const { return mMemCategory; } + MCORE_INLINE uint16 GetMemoryCategory() const { return m_memCategory; } /** * Set the memory category ID, where allocations made by this array will belong to. * On default, after construction of the array, the category ID is 0, which means it is unknown. * @param categoryID The memory category ID where this arrays allocations belong to. */ - MCORE_INLINE void SetMemoryCategory(uint16 categoryID) { mMemCategory = categoryID; } + MCORE_INLINE void SetMemoryCategory(uint16 categoryID) { m_memCategory = categoryID; } /** * Get a pointer to the first element. * @result A pointer to the first element. */ - MCORE_INLINE T* GetPtr() { return mData; } + MCORE_INLINE T* GetPtr() { return m_data; } /** * Get a pointer to the first element. * @result A pointer to the first element. */ - MCORE_INLINE T* GetPtr() const { return mData; } + MCORE_INLINE T* GetPtr() const { return m_data; } /** * Get a given item/element. * @param pos The item/element number. * @result A reference to the element. */ - MCORE_INLINE T& GetItem(size_t pos) { return mData[pos]; } + MCORE_INLINE T& GetItem(size_t pos) { return m_data[pos]; } /** * Get the first element. * @result A reference to the first element. */ - MCORE_INLINE T& GetFirst() { return mData[0]; } + MCORE_INLINE T& GetFirst() { return m_data[0]; } /** * Get the last element. * @result A reference to the last element. */ - MCORE_INLINE T& GetLast() { return mData[mLength - 1]; } + MCORE_INLINE T& GetLast() { return m_data[m_length - 1]; } /** * Get a read-only pointer to the first element. * @result A read-only pointer to the first element. */ - MCORE_INLINE const T* GetReadPtr() const { return mData; } + MCORE_INLINE const T* GetReadPtr() const { return m_data; } /** * Get a read-only reference to a given element number. * @param pos The element number. * @result A read-only reference to the given element. */ - MCORE_INLINE const T& GetItem(size_t pos) const { return mData[pos]; } + MCORE_INLINE const T& GetItem(size_t pos) const { return m_data[pos]; } /** * Get a read-only reference to the first element. * @result A read-only reference to the first element. */ - MCORE_INLINE const T& GetFirst() const { return mData[0]; } + MCORE_INLINE const T& GetFirst() const { return m_data[0]; } /** * Get a read-only reference to the last element. * @result A read-only reference to the last element. */ - MCORE_INLINE const T& GetLast() const { return mData[mLength - 1]; } + MCORE_INLINE const T& GetLast() const { return m_data[m_length - 1]; } /** * Check if the array is empty or not. * @result Returns true when there are no elements in the array, otherwise false is returned. */ - MCORE_INLINE bool GetIsEmpty() const { return (mLength == 0); } + MCORE_INLINE bool GetIsEmpty() const { return (m_length == 0); } /** * Checks if the passed index is in the array's range. * @param index The index to check. * @return True if the passed index is valid, false if not. */ - MCORE_INLINE bool GetIsValidIndex(size_t index) const { return (index < mLength); } + MCORE_INLINE bool GetIsValidIndex(size_t index) const { return (index < m_length); } /** * Get the number of elements in the array. * @result The number of elements in the array. */ - MCORE_INLINE size_t GetLength() const { return mLength; } + MCORE_INLINE size_t GetLength() const { return m_length; } /** * Get the maximum number of elements. This is the number of elements there currently is space for to store. @@ -224,7 +224,7 @@ namespace MCore * This purely has to do with pre-allocating, to reduce the number of reallocs. * @result The maximum array length. */ - MCORE_INLINE size_t GetMaxLength() const { return mMaxLength; } + MCORE_INLINE size_t GetMaxLength() const { return m_maxLength; } /** * Calculates the memory usage used by this array. @@ -233,7 +233,7 @@ namespace MCore */ MCORE_INLINE size_t CalcMemoryUsage(bool includeMembers = true) const { - size_t result = mMaxLength * sizeof(T); + size_t result = m_maxLength * sizeof(T); if (includeMembers) { result += sizeof(AlignedArray); @@ -246,19 +246,19 @@ namespace MCore * @param pos The element number. * @param value The value to store at that element number. */ - MCORE_INLINE void SetElem(size_t pos, const T& value) { mData[pos] = value; } + MCORE_INLINE void SetElem(size_t pos, const T& value) { m_data[pos] = value; } /** * Add a given element to the back of the array. * @param x The element to add. */ - MCORE_INLINE void Add(const T& x) { Grow(++mLength); Construct(mLength - 1, x); } + MCORE_INLINE void Add(const T& x) { Grow(++m_length); Construct(m_length - 1, x); } /** * Add a given element to the back of the array, but without pre-allocation caching. * @param x The element to add. */ - MCORE_INLINE void AddExact(const T& x) { GrowExact(++mLength); Construct(mLength - 1, x); } + MCORE_INLINE void AddExact(const T& x) { GrowExact(++m_length); Construct(m_length - 1, x); } /** * Add a given array to the back of this array. @@ -266,8 +266,8 @@ namespace MCore */ MCORE_INLINE void Add(const AlignedArray& a) { - size_t l = mLength; - Grow(mLength + a.mLength); + size_t l = m_length; + Grow(m_length + a.m_length); for (size_t i = 0; i < a.GetLength(); ++i) { Construct(l + i, a[i]); @@ -277,19 +277,19 @@ namespace MCore /** * Add an empty (default constructed) element to the back of the array. */ - MCORE_INLINE void AddEmpty() { Grow(++mLength); Construct(mLength - 1); } + MCORE_INLINE void AddEmpty() { Grow(++m_length); Construct(m_length - 1); } /** * Add an empty (default constructed) element to the back of the array, but without pre-allocation caching. */ - MCORE_INLINE void AddEmptyExact() { GrowExact(++mLength); Construct(mLength - 1); } + MCORE_INLINE void AddEmptyExact() { GrowExact(++m_length); Construct(m_length - 1); } /** * Remove the first array element. */ MCORE_INLINE void RemoveFirst() { - if (mLength > 0) + if (m_length > 0) { Remove(0); } @@ -300,9 +300,9 @@ namespace MCore */ MCORE_INLINE void RemoveLast() { - if (mLength > 0) + if (m_length > 0) { - Destruct(--mLength); + Destruct(--m_length); } } @@ -310,14 +310,14 @@ namespace MCore * Insert an empty element (default constructed) at a given position in the array. * @param pos The position to create the empty element. */ - MCORE_INLINE void Insert(size_t pos) { Grow(mLength + 1); MoveElements(pos + 1, pos, mLength - pos - 1); Construct(pos); } + MCORE_INLINE void Insert(size_t pos) { Grow(m_length + 1); MoveElements(pos + 1, pos, m_length - pos - 1); Construct(pos); } /** * Insert a given element at a given position in the array. * @param pos The position to insert the empty element. * @param x The element to store at this position. */ - MCORE_INLINE void Insert(size_t pos, const T& x) { Grow(mLength + 1); MoveElements(pos + 1, pos, mLength - pos - 1); Construct(pos, x); } + MCORE_INLINE void Insert(size_t pos, const T& x) { Grow(m_length + 1); MoveElements(pos + 1, pos, m_length - pos - 1); Construct(pos, x); } /** * Remove an element at a given position. @@ -326,11 +326,11 @@ namespace MCore MCORE_INLINE void Remove(size_t pos) { Destruct(pos); - if (mLength > 1) + if (m_length > 1) { - MoveElements(pos, pos + 1, mLength - pos - 1); + MoveElements(pos, pos + 1, m_length - pos - 1); } - mLength--; + m_length--; } /** @@ -344,8 +344,8 @@ namespace MCore { Destruct(i); } - MoveElements(pos, pos + num, mLength - pos - num); - mLength -= num; + MoveElements(pos, pos + num, m_length - pos - num); + m_length -= num; } /** @@ -375,12 +375,12 @@ namespace MCore MCORE_INLINE void SwapRemove(size_t pos) { Destruct(pos); - if (pos != mLength - 1) + if (pos != m_length - 1) { - Construct(pos, mData[mLength - 1]); - Destruct(mLength - 1); + Construct(pos, m_data[m_length - 1]); + Destruct(m_length - 1); } - mLength--; + m_length--; } // remove element at and place the last element of the array in that position /** @@ -403,11 +403,11 @@ namespace MCore */ MCORE_INLINE void Clear(bool clearMem = true) { - for (size_t i = 0; i < mLength; ++i) + for (size_t i = 0; i < m_length; ++i) { Destruct(i); } - mLength = 0; + m_length = 0; if (clearMem) { this->Free(); @@ -420,11 +420,11 @@ namespace MCore */ MCORE_INLINE void AssureSize(size_t newLength) { - if (mLength >= newLength) + if (m_length >= newLength) { return; } - size_t oldLen = mLength; + size_t oldLen = m_length; Grow(newLength); for (size_t i = oldLen; i < newLength; ++i) { @@ -438,7 +438,7 @@ namespace MCore */ MCORE_INLINE void Reserve(size_t minLength) { - if (mMaxLength < minLength) + if (m_maxLength < minLength) { Realloc(minLength); } @@ -449,12 +449,12 @@ namespace MCore */ MCORE_INLINE void Shrink() { - if (mLength == mMaxLength) + if (m_length == m_maxLength) { return; } - MCORE_ASSERT(mMaxLength >= mLength); - Realloc(mLength); + MCORE_ASSERT(m_maxLength >= m_length); + Realloc(m_length); } /** @@ -471,9 +471,9 @@ namespace MCore */ MCORE_INLINE size_t Find(const T& x) const { - for (size_t i = 0; i < mLength; ++i) + for (size_t i = 0; i < m_length; ++i) { - if (mData[i] == x) + if (m_data[i] == x) { return i; } @@ -487,7 +487,7 @@ namespace MCore * This resizes this array to be the exact length of the array we will copy the data from. * @param other The array to copy the data from. */ - MCORE_INLINE void MemCopyContentsFrom(const AlignedArray& other) { Resize(other.GetLength()); MemCopy((uint8*)mData, (uint8*)other.mData, sizeof(T) * other.mLength); } + MCORE_INLINE void MemCopyContentsFrom(const AlignedArray& other) { Resize(other.GetLength()); MemCopy((uint8*)m_data, (uint8*)other.m_data, sizeof(T) * other.m_length); } // sort function and standard sort function typedef int32 (MCORE_CDECL * CmpFunc)(const T& itemA, const T& itemB); @@ -526,7 +526,7 @@ namespace MCore * Sort the complete array using a given sort function. * @param cmp The sort function to use. */ - MCORE_INLINE void Sort(CmpFunc cmp) { InnerSort(0, mLength - 1, cmp); } + MCORE_INLINE void Sort(CmpFunc cmp) { InnerSort(0, m_length - 1, cmp); } /** * Sort a given part of the array using a given sort function. @@ -540,7 +540,7 @@ namespace MCore { if (last == InvalidIndex) { - last = mLength - 1; + last = m_length - 1; } InnerSort(first, last, cmp); } @@ -565,17 +565,17 @@ namespace MCore // resize in a fast way that doesn't call constructors or destructors void ResizeFast(size_t newLength) { - if (mLength == newLength) + if (m_length == newLength) { return; } - if (newLength > mLength) + if (newLength > m_length) { GrowExact(newLength); } - mLength = newLength; + m_length = newLength; } /** @@ -585,16 +585,16 @@ namespace MCore */ void Resize(size_t newLength) { - if (mLength == newLength) + if (m_length == newLength) { return; } // check for growing or shrinking array - if (newLength > mLength) + if (newLength > m_length) { // growing array, construct empty elements at end of array - const size_t oldLen = mLength; + const size_t oldLen = m_length; GrowExact(newLength); for (size_t i = oldLen; i < newLength; ++i) { @@ -604,12 +604,12 @@ namespace MCore else { // shrinking array, destruct elements at end of array - for (size_t i = newLength; i < mLength; ++i) + for (size_t i = newLength; i < m_length; ++i) { Destruct(i); } - mLength = newLength; + m_length = newLength; } } @@ -624,20 +624,20 @@ namespace MCore { if (numElements > 0) { - MemMove(mData + destIndex, mData + sourceIndex, numElements * sizeof(T)); + MemMove(m_data + destIndex, m_data + sourceIndex, numElements * sizeof(T)); } } // operators bool operator==(const AlignedArray& other) const { - if (mLength != other.mLength) + if (m_length != other.m_length) { return false; } - for (size_t i = 0; i < mLength; ++i) + for (size_t i = 0; i < m_length; ++i) { - if (mData[i] != other.mData[i]) + if (m_data[i] != other.m_data[i]) { return false; } @@ -649,11 +649,11 @@ namespace MCore if (&other != this) { Clear(false); - mMemCategory = other.mMemCategory; - Grow(other.mLength); - for (size_t i = 0; i < mLength; ++i) + m_memCategory = other.m_memCategory; + Grow(other.m_length); + for (size_t i = 0; i < m_length; ++i) { - Construct(i, other.mData[i]); + Construct(i, other.m_data[i]); } } return *this; @@ -661,35 +661,35 @@ namespace MCore AlignedArray& operator= (AlignedArray&& other) { MCORE_ASSERT(&other != this); - if (mData) + if (m_data) { - AlignedFree(mData); + AlignedFree(m_data); } - mData = other.mData; - mMemCategory = other.mMemCategory; - mLength = other.mLength; - mMaxLength = other.mMaxLength; - other.mData = nullptr; - other.mLength = 0; - other.mMaxLength = 0; + m_data = other.m_data; + m_memCategory = other.m_memCategory; + m_length = other.m_length; + m_maxLength = other.m_maxLength; + other.m_data = nullptr; + other.m_length = 0; + other.m_maxLength = 0; return *this; } AlignedArray& operator+=(const T& other) { Add(other); return *this; } AlignedArray& operator+=(const AlignedArray& other) { Add(other); return *this; } - MCORE_INLINE T& operator[](size_t index) { MCORE_ASSERT(index < mLength); return mData[index]; } - MCORE_INLINE const T& operator[](size_t index) const { MCORE_ASSERT(index < mLength); return mData[index]; } + MCORE_INLINE T& operator[](size_t index) { MCORE_ASSERT(index < m_length); return m_data[index]; } + MCORE_INLINE const T& operator[](size_t index) const { MCORE_ASSERT(index < m_length); return m_data[index]; } private: - T* mData; /**< The element data. */ - size_t mLength; /**< The number of used elements in the array. */ - size_t mMaxLength; /**< The number of elements that we have allocated memory for. */ - uint16 mMemCategory; /**< The memory category ID. */ + T* m_data; /**< The element data. */ + size_t m_length; /**< The number of used elements in the array. */ + size_t m_maxLength; /**< The number of elements that we have allocated memory for. */ + uint16 m_memCategory; /**< The memory category ID. */ // private functions MCORE_INLINE void Grow(size_t newLength) { - mLength = newLength; - if (mMaxLength >= newLength) + m_length = newLength; + if (m_maxLength >= newLength) { return; } @@ -697,14 +697,14 @@ namespace MCore } MCORE_INLINE void GrowExact(size_t newLength) { - mLength = newLength; - if (mMaxLength < newLength) + m_length = newLength; + if (m_maxLength < newLength) { Realloc(newLength); } } MCORE_INLINE size_t AllocSize(size_t num) { return 1 + num /*+num/8*/; } - MCORE_INLINE void Alloc(size_t num) { mData = (T*)AlignedAllocate(num * sizeof(T), alignment, mMemCategory, MEMORYBLOCK_ID, MCORE_FILE, MCORE_LINE); } + MCORE_INLINE void Alloc(size_t num) { m_data = (T*)AlignedAllocate(num * sizeof(T), alignment, m_memCategory, MEMORYBLOCK_ID, MCORE_FILE, MCORE_LINE); } MCORE_INLINE void Realloc(size_t newSize) { if (newSize == 0) @@ -712,43 +712,43 @@ namespace MCore this->Free(); return; } - if (mData) + if (m_data) { - mData = (T*)AlignedRealloc(mData, newSize * sizeof(T), mMaxLength * sizeof(T), alignment, mMemCategory, MEMORYBLOCK_ID, MCORE_FILE, MCORE_LINE); + m_data = (T*)AlignedRealloc(m_data, newSize * sizeof(T), m_maxLength * sizeof(T), alignment, m_memCategory, MEMORYBLOCK_ID, MCORE_FILE, MCORE_LINE); } else { - mData = (T*)AlignedAllocate(newSize * sizeof(T), alignment, mMemCategory, MEMORYBLOCK_ID, MCORE_FILE, MCORE_LINE); + m_data = (T*)AlignedAllocate(newSize * sizeof(T), alignment, m_memCategory, MEMORYBLOCK_ID, MCORE_FILE, MCORE_LINE); } - mMaxLength = newSize; + m_maxLength = newSize; } void Free() { - mLength = 0; - mMaxLength = 0; - if (mData) + m_length = 0; + m_maxLength = 0; + if (m_data) { - AlignedFree(mData); - mData = nullptr; + AlignedFree(m_data); + m_data = nullptr; } } - MCORE_INLINE void Construct(size_t index, const T& original) { ::new(mData + index)T(original); } // copy-construct an element at which is a copy of - MCORE_INLINE void Construct(size_t index) { ::new(mData + index)T; } // construct an element at place + MCORE_INLINE void Construct(size_t index, const T& original) { ::new(m_data + index)T(original); } // copy-construct an element at which is a copy of + MCORE_INLINE void Construct(size_t index) { ::new(m_data + index)T; } // construct an element at place MCORE_INLINE void Destruct(size_t index) { #if (MCORE_COMPILER == MCORE_COMPILER_MSVC) MCORE_UNUSED(index); // work around an MSVC compiler bug, where it triggers a warning that parameter 'index' is unused #endif - (mData + index)->~T(); + (m_data + index)->~T(); } // partition part of array (for sorting) int32 Partition(int32 left, int32 right, CmpFunc cmp) { - ::MCore::Swap(mData[left], mData[ (left + right) >> 1 ]); + ::MCore::Swap(m_data[left], m_data[ (left + right) >> 1 ]); - T& target = mData[right]; + T& target = m_data[right]; int32 i = left - 1; int32 j = right; @@ -757,14 +757,14 @@ namespace MCore { while (i < j) { - if (cmp(mData[++i], target) >= 0) + if (cmp(m_data[++i], target) >= 0) { break; } } while (j > i) { - if (cmp(mData[--j], target) <= 0) + if (cmp(m_data[--j], target) <= 0) { break; } @@ -773,10 +773,10 @@ namespace MCore { break; } - ::MCore::Swap(mData[i], mData[j]); + ::MCore::Swap(m_data[i], m_data[j]); } - ::MCore::Swap(mData[i], mData[right]); + ::MCore::Swap(m_data[i], m_data[right]); return i; } }; diff --git a/Gems/EMotionFX/Code/MCore/Source/Array2D.h b/Gems/EMotionFX/Code/MCore/Source/Array2D.h index a2bad5a5c2..f6c9234067 100644 --- a/Gems/EMotionFX/Code/MCore/Source/Array2D.h +++ b/Gems/EMotionFX/Code/MCore/Source/Array2D.h @@ -45,8 +45,8 @@ namespace MCore */ struct TableEntry { - size_t mStartIndex; /**< The index offset where the data for this row starts. */ - size_t mNumElements; /**< The number of elements to follow. */ + size_t m_startIndex; /**< The index offset where the data for this row starts. */ + size_t m_numElements; /**< The number of elements to follow. */ }; /** @@ -67,7 +67,7 @@ namespace MCore * */ Array2D(size_t numRows, size_t numPreAllocatedElemsPerRow = 2) - : mNumPreCachedElements(numPreAllocatedElemsPerRow) { Resize(numRows); } + : m_numPreCachedElements(numPreAllocatedElemsPerRow) { Resize(numRows); } /** * Resize the array in one dimension (the number of rows). @@ -126,7 +126,7 @@ namespace MCore * speedup adding of new elements and prevent memory reallocs. The default value is set to 2 when creating an array, unless specified differently. * @param numElemsPerRow The number of elements per row that should be pre-allocated. */ - void SetNumPreCachedElements(size_t numElemsPerRow) { mNumPreCachedElements = numElemsPerRow; } + void SetNumPreCachedElements(size_t numElemsPerRow) { m_numPreCachedElements = numElemsPerRow; } /** * Get the number of pre-cached/allocated elements per row, when creating new rows. @@ -134,14 +134,14 @@ namespace MCore * @result The number of elements per row that will be pre-allocated/cached when adding a new row. * @see SetNumPreCachedElements. */ - size_t GetNumPreCachedElements() const { return mNumPreCachedElements; } + size_t GetNumPreCachedElements() const { return m_numPreCachedElements; } /** * Get the number of stored elements inside a given row. * @param rowIndex The row number. * @result The number of elements stored inside this row. */ - size_t GetNumElements(size_t rowIndex) const { return mIndexTable[rowIndex].mNumElements; } + size_t GetNumElements(size_t rowIndex) const { return m_indexTable[rowIndex].m_numElements; } /** * Get a pointer to the element data stored in a given row. @@ -152,7 +152,7 @@ namespace MCore * @param rowIndex the row number. * @result A pointer to the element data for the given row. */ - T* GetElements(size_t rowIndex) { return &mData[ mIndexTable[rowIndex].mStartIndex ]; } + T* GetElements(size_t rowIndex) { return &m_data[ m_indexTable[rowIndex].m_startIndex ]; } /** * Get the data of a given element. @@ -160,7 +160,7 @@ namespace MCore * @param elementNr The element number inside this row to retrieve. * @result A reference to the element data. */ - T& GetElement(size_t rowIndex, size_t elementNr) { return mData[ mIndexTable[rowIndex].mStartIndex + elementNr ]; } + T& GetElement(size_t rowIndex, size_t elementNr) { return m_data[ m_indexTable[rowIndex].m_startIndex + elementNr ]; } /** * Get the data of a given element. @@ -168,7 +168,7 @@ namespace MCore * @param elementNr The element number inside this row to retrieve. * @result A const reference to the element data. */ - const T& GetElement(size_t rowIndex, size_t elementNr) const { return mData[ mIndexTable[rowIndex].mStartIndex + elementNr ]; } + const T& GetElement(size_t rowIndex, size_t elementNr) const { return m_data[ m_indexTable[rowIndex].m_startIndex + elementNr ]; } /** * Set the value for a given element in the array. @@ -176,13 +176,13 @@ namespace MCore * @param elementNr The element number to set the value for. * @param value The value to set the element to. */ - void SetElement(size_t rowIndex, size_t elementNr, const T& value) { MCORE_ASSERT(rowIndex < mIndexTable.GetLength()); MCORE_ASSERT(elementNr < mIndexTable[rowIndex].mNumElements); mData[ mIndexTable[rowIndex].mStartIndex + elementNr ] = value; } + void SetElement(size_t rowIndex, size_t elementNr, const T& value) { MCORE_ASSERT(rowIndex < m_indexTable.GetLength()); MCORE_ASSERT(elementNr < m_indexTable[rowIndex].m_numElements); m_data[ m_indexTable[rowIndex].m_startIndex + elementNr ] = value; } /** * Get the number of rows in the 2D array. * @result The number of rows. */ - size_t GetNumRows() const { return mIndexTable.size(); } + size_t GetNumRows() const { return m_indexTable.size(); } /** * Calculate the percentage of memory that is filled with element data. @@ -192,7 +192,7 @@ namespace MCore * would be most optimal. * @result The percentage (in range of 0..100) of used element memory. */ - float CalcUsedElementMemoryPercentage() const { return (mData.GetLength() ? (CalcTotalNumElements() / (float)mData.GetLength()) * 100.0f : 0); } + float CalcUsedElementMemoryPercentage() const { return (m_data.GetLength() ? (CalcTotalNumElements() / (float)m_data.GetLength()) * 100.0f : 0); } /** * Swap the element data of two rows. @@ -220,12 +220,12 @@ namespace MCore */ void Clear(bool freeMem = true) { - mIndexTable.clear(); - mData.clear(); + m_indexTable.clear(); + m_data.clear(); if (freeMem) { - mIndexTable.shrink_to_fit(); - mData.shrink_to_fit(); + m_indexTable.shrink_to_fit(); + m_data.shrink_to_fit(); } } @@ -242,7 +242,7 @@ namespace MCore * The length of the array equals the value returned by GetNumRows(). * @result The array of index table entries, which specify the start indices and number of entries per row. */ - AZStd::vector& GetIndexTable() { return mIndexTable; } + AZStd::vector& GetIndexTable() { return m_indexTable; } /** * Get the data array. @@ -250,12 +250,12 @@ namespace MCore * Normally you shouldn't be using this method. However it is useful in some specific cases. * @result The data array that contains all elements. */ - AZStd::vector& GetData() { return mData; } + AZStd::vector& GetData() { return m_data; } private: - AZStd::vector mData; /**< The element data. */ - AZStd::vector mIndexTable; /**< The index table that let's us know where what data is inside the element data array. */ - size_t mNumPreCachedElements = 2; /**< The number of elements per row to pre-allocate when resizing this array. This prevents some re-allocs. */ + AZStd::vector m_data; /**< The element data. */ + AZStd::vector m_indexTable; /**< The index table that let's us know where what data is inside the element data array. */ + size_t m_numPreCachedElements = 2; /**< The number of elements per row to pre-allocate when resizing this array. This prevents some re-allocs. */ }; diff --git a/Gems/EMotionFX/Code/MCore/Source/Array2D.inl b/Gems/EMotionFX/Code/MCore/Source/Array2D.inl index 47a3fd7015..5682ab54b0 100644 --- a/Gems/EMotionFX/Code/MCore/Source/Array2D.inl +++ b/Gems/EMotionFX/Code/MCore/Source/Array2D.inl @@ -11,7 +11,7 @@ template void Array2D::Resize(size_t numRows, bool autoShrink) { // get the current (old) number of rows - const size_t oldNumRows = mIndexTable.size(); + const size_t oldNumRows = m_indexTable.size(); // don't do anything when we don't need to if (numRows == oldNumRows) @@ -20,7 +20,7 @@ void Array2D::Resize(size_t numRows, bool autoShrink) } // resize the index table - mIndexTable.resize(numRows); + m_indexTable.resize(numRows); // check if we decreased the number of rows or not if (numRows < oldNumRows) @@ -36,13 +36,13 @@ void Array2D::Resize(size_t numRows, bool autoShrink) // init the new table entries for (size_t i = oldNumRows; i < numRows; ++i) { - mIndexTable[i].mStartIndex = mData.size() + (i * mNumPreCachedElements); - mIndexTable[i].mNumElements = 0; + m_indexTable[i].m_startIndex = m_data.size() + (i * m_numPreCachedElements); + m_indexTable[i].m_numElements = 0; } // grow the data array const size_t numNewRows = numRows - oldNumRows; - mData.resize(mData.size() + numNewRows * mNumPreCachedElements); + m_data.resize(m_data.size() + numNewRows * m_numPreCachedElements); } } @@ -51,20 +51,20 @@ void Array2D::Resize(size_t numRows, bool autoShrink) template void Array2D::Add(size_t rowIndex, const T& element) { - AZ_Assert(rowIndex < mIndexTable.size(), "Array index out of bounds"); + AZ_Assert(rowIndex < m_indexTable.size(), "Array index out of bounds"); // find the insert location inside the data array - size_t insertPos = mIndexTable[rowIndex].mStartIndex + mIndexTable[rowIndex].mNumElements; - if (insertPos >= mData.size()) + size_t insertPos = m_indexTable[rowIndex].m_startIndex + m_indexTable[rowIndex].m_numElements; + if (insertPos >= m_data.size()) { - mData.resize(insertPos + 1); + m_data.resize(insertPos + 1); } // check if we need to insert for real bool needRealInsert = true; - if (rowIndex < mIndexTable.size() - 1) // if there are still entries coming after the one we have to add to + if (rowIndex < m_indexTable.size() - 1) // if there are still entries coming after the one we have to add to { - if (insertPos < mIndexTable[rowIndex + 1].mStartIndex) // if basically there are empty unused element we can use + if (insertPos < m_indexTable[rowIndex + 1].m_startIndex) // if basically there are empty unused element we can use { needRealInsert = false; // then we don't need to do any reallocs } @@ -72,9 +72,9 @@ void Array2D::Add(size_t rowIndex, const T& element) else { // if we're dealing with the last row - if (rowIndex == mIndexTable.size() - 1) + if (rowIndex == m_indexTable.size() - 1) { - if (insertPos < mData.size()) // if basically there are empty unused element we can use + if (insertPos < m_data.size()) // if basically there are empty unused element we can use { needRealInsert = false; } @@ -85,22 +85,22 @@ void Array2D::Add(size_t rowIndex, const T& element) if (needRealInsert) { // insert the element inside the data array - mData.insert(AZStd::next(begin(mData), insertPos), element); + m_data.insert(AZStd::next(begin(m_data), insertPos), element); // adjust the index table entries - const size_t numRows = mIndexTable.size(); + const size_t numRows = m_indexTable.size(); for (size_t i = rowIndex + 1; i < numRows; ++i) { - mIndexTable[i].mStartIndex++; + m_indexTable[i].m_startIndex++; } } else { - mData[insertPos] = element; + m_data[insertPos] = element; } // increase the number of elements in the index table - mIndexTable[rowIndex].mNumElements++; + m_indexTable[rowIndex].m_numElements++; } @@ -108,21 +108,21 @@ void Array2D::Add(size_t rowIndex, const T& element) template void Array2D::Remove(size_t rowIndex, size_t elementIndex) { - AZ_Assert(rowIndex < mIndexTable.size(), "Array2D<>::Remove: array index out of bounds"); - AZ_Assert(elementIndex < mIndexTable[rowIndex].mNumElements, "Array2D<>::Remove: element index out of bounds"); - AZ_Assert(mIndexTable[rowIndex].mNumElements > 0, "Array2D<>::Remove: array index out of bounds"); + AZ_Assert(rowIndex < m_indexTable.size(), "Array2D<>::Remove: array index out of bounds"); + AZ_Assert(elementIndex < m_indexTable[rowIndex].m_numElements, "Array2D<>::Remove: element index out of bounds"); + AZ_Assert(m_indexTable[rowIndex].m_numElements > 0, "Array2D<>::Remove: array index out of bounds"); - const size_t startIndex = mIndexTable[rowIndex].mStartIndex; - const size_t maxElementIndex = mIndexTable[rowIndex].mNumElements - 1; + const size_t startIndex = m_indexTable[rowIndex].m_startIndex; + const size_t maxElementIndex = m_indexTable[rowIndex].m_numElements - 1; // swap the last element with the one to be removed if (elementIndex != maxElementIndex) { - mData[startIndex + elementIndex] = mData[startIndex + maxElementIndex]; + m_data[startIndex + elementIndex] = m_data[startIndex + maxElementIndex]; } // decrease the number of elements - mIndexTable[rowIndex].mNumElements--; + m_indexTable[rowIndex].m_numElements--; } @@ -130,8 +130,8 @@ void Array2D::Remove(size_t rowIndex, size_t elementIndex) template void Array2D::RemoveRow(size_t rowIndex, bool autoShrink) { - AZ_Assert(rowIndex < mIndexTable.GetLength(), "Array2D<>::RemoveRow: rowIndex out of bounds"); - mIndexTable.Remove(rowIndex); + AZ_Assert(rowIndex < m_indexTable.GetLength(), "Array2D<>::RemoveRow: rowIndex out of bounds"); + m_indexTable.Remove(rowIndex); // optimize memory usage when desired if (autoShrink) @@ -145,19 +145,19 @@ void Array2D::RemoveRow(size_t rowIndex, bool autoShrink) template void Array2D::RemoveRows(size_t startRow, size_t endRow, bool autoShrink) { - AZ_Assert(startRow < mIndexTable.size(), "Array2D<>::RemoveRows: startRow out of bounds"); - AZ_Assert(endRow < mIndexTable.size(), "Array2D<>::RemoveRows: endRow out of bounds"); + AZ_Assert(startRow < m_indexTable.size(), "Array2D<>::RemoveRows: startRow out of bounds"); + AZ_Assert(endRow < m_indexTable.size(), "Array2D<>::RemoveRows: endRow out of bounds"); // check if the start row is smaller than the end row if (startRow < endRow) { const size_t numToRemove = (endRow - startRow) + 1; - mIndexTable.erase(AZStd::next(begin(mIndexTable), startRow), AZStd::next(AZStd::next(begin(mIndexTable), startRow), numToRemove)); + m_indexTable.erase(AZStd::next(begin(m_indexTable), startRow), AZStd::next(AZStd::next(begin(m_indexTable), startRow), numToRemove)); } else // if the end row is smaller than the start row { const size_t numToRemove = (startRow - endRow) + 1; - mIndexTable.erase(AZStd::next(begin(mIndexTable), endRow), AZStd::next(AZStd::next(begin(mIndexTable), endRow), numToRemove)); + m_indexTable.erase(AZStd::next(begin(m_indexTable), endRow), AZStd::next(AZStd::next(begin(m_indexTable), endRow), numToRemove)); } // optimize memory usage when desired @@ -173,7 +173,7 @@ template void Array2D::Shrink() { // for all attributes, except for the last one - const size_t numRows = mIndexTable.size(); + const size_t numRows = m_indexTable.size(); if (numRows == 0) { return; @@ -183,20 +183,20 @@ void Array2D::Shrink() const size_t numRowsMinusOne = numRows - 1; for (size_t a = 0; a < numRowsMinusOne; ++a) { - const size_t firstUnusedIndex = mIndexTable[a ].mStartIndex + mIndexTable[a].mNumElements; - const size_t numUnusedElements = mIndexTable[a + 1].mStartIndex - firstUnusedIndex; + const size_t firstUnusedIndex = m_indexTable[a ].m_startIndex + m_indexTable[a].m_numElements; + const size_t numUnusedElements = m_indexTable[a + 1].m_startIndex - firstUnusedIndex; // if we have pre-cached/unused elements, remove those by moving memory to remove the "holes" if (numUnusedElements > 0) { // remove the unused elements from the array - mData.erase(AZStd::next(begin(mData), firstUnusedIndex), AZStd::next(AZStd::next(begin(mData), firstUnusedIndex), numUnusedElements)); + m_data.erase(AZStd::next(begin(m_data), firstUnusedIndex), AZStd::next(AZStd::next(begin(m_data), firstUnusedIndex), numUnusedElements)); // change the start indices for all the rows coming after the current one - const size_t numTotalRows = mIndexTable.size(); + const size_t numTotalRows = m_indexTable.size(); for (size_t i = a + 1; i < numTotalRows; ++i) { - mIndexTable[i].mStartIndex -= numUnusedElements; + m_indexTable[i].m_startIndex -= numUnusedElements; } } } @@ -207,25 +207,25 @@ void Array2D::Shrink() for (size_t row = 0; row < numRows; ++row) { // if the data starts after the place where it could start, move it to the place where it could start - if (mIndexTable[row].mStartIndex > dataPos) + if (m_indexTable[row].m_startIndex > dataPos) { - AZStd::move(AZStd::next(begin(mData), this->mIndexTable[row].mStartIndex), AZStd::next(AZStd::next(begin(mData), this->mIndexTable[row].mStartIndex), this->mIndexTable[row].mNumElements), AZStd::next(begin(mData), dataPos)); - mIndexTable[row].mStartIndex = dataPos; + AZStd::move(AZStd::next(begin(m_data), this->m_indexTable[row].m_startIndex), AZStd::next(AZStd::next(begin(m_data), this->m_indexTable[row].m_startIndex), this->m_indexTable[row].m_numElements), AZStd::next(begin(m_data), dataPos)); + m_indexTable[row].m_startIndex = dataPos; } // increase the data pos - dataPos += mIndexTable[row].mNumElements; + dataPos += m_indexTable[row].m_numElements; } // remove all unused data items - if (dataPos < mData.size()) + if (dataPos < m_data.size()) { - mData.erase(AZStd::next(begin(mData), dataPos), end(mData)); + m_data.erase(AZStd::next(begin(m_data), dataPos), end(m_data)); } // shrink the arrays - mData.shrink_to_fit(); - mIndexTable.shrink_to_fit(); + m_data.shrink_to_fit(); + m_indexTable.shrink_to_fit(); } @@ -236,10 +236,10 @@ size_t Array2D::CalcTotalNumElements() const size_t totalElements = 0; // add all number of row elements together - const size_t numRows = mIndexTable.size(); + const size_t numRows = m_indexTable.size(); for (size_t i = 0; i < numRows; ++i) { - totalElements += mIndexTable[i].mNumElements; + totalElements += m_indexTable[i].m_numElements; } return totalElements; @@ -251,14 +251,14 @@ template void Array2D::Swap(size_t rowA, size_t rowB) { // get the original number of elements from both rows - const size_t numElementsA = mIndexTable[rowA].mNumElements; - const size_t numElementsB = mIndexTable[rowB].mNumElements; + const size_t numElementsA = m_indexTable[rowA].m_numElements; + const size_t numElementsB = m_indexTable[rowB].m_numElements; // move the element data of rowA into a temp buffer AZStd::vector tempData(numElementsA); AZStd::move( - AZStd::next(mData.begin(), mIndexTable[rowA].mStartIndex), - AZStd::next(mData.begin(), mIndexTable[rowA].mStartIndex + numElementsA), + AZStd::next(m_data.begin(), m_indexTable[rowA].m_startIndex), + AZStd::next(m_data.begin(), m_indexTable[rowA].m_startIndex + numElementsA), tempData.begin() ); diff --git a/Gems/EMotionFX/Code/MCore/Source/Attribute.cpp b/Gems/EMotionFX/Code/MCore/Source/Attribute.cpp index 416d493453..ac6772e44e 100644 --- a/Gems/EMotionFX/Code/MCore/Source/Attribute.cpp +++ b/Gems/EMotionFX/Code/MCore/Source/Attribute.cpp @@ -13,7 +13,7 @@ namespace MCore { Attribute::Attribute(AZ::u32 typeID) { - mTypeID = typeID; + m_typeId = typeID; } Attribute::~Attribute() diff --git a/Gems/EMotionFX/Code/MCore/Source/Attribute.h b/Gems/EMotionFX/Code/MCore/Source/Attribute.h index 3b9b4459aa..e1ea970044 100644 --- a/Gems/EMotionFX/Code/MCore/Source/Attribute.h +++ b/Gems/EMotionFX/Code/MCore/Source/Attribute.h @@ -55,7 +55,7 @@ namespace MCore virtual Attribute* Clone() const = 0; virtual const char* GetTypeString() const = 0; - MCORE_INLINE AZ::u32 GetType() const { return mTypeID; } + MCORE_INLINE AZ::u32 GetType() const { return m_typeId; } virtual bool InitFromString(const AZStd::string& valueString) = 0; virtual bool ConvertToString(AZStd::string& outString) const = 0; virtual bool InitFrom(const Attribute* other) = 0; @@ -67,7 +67,7 @@ namespace MCore virtual void NetworkSerialize(EMotionFX::Network::AnimGraphSnapshotChunkSerializer&) {}; protected: - AZ::u32 mTypeID; /**< The unique type ID of the attribute class. */ + AZ::u32 m_typeId; /**< The unique type ID of the attribute class. */ Attribute(AZ::u32 typeID); }; diff --git a/Gems/EMotionFX/Code/MCore/Source/AttributeBool.cpp b/Gems/EMotionFX/Code/MCore/Source/AttributeBool.cpp index d91e188aae..cc9a7f88b7 100644 --- a/Gems/EMotionFX/Code/MCore/Source/AttributeBool.cpp +++ b/Gems/EMotionFX/Code/MCore/Source/AttributeBool.cpp @@ -20,13 +20,13 @@ namespace MCore switch (other->GetType()) { case TYPE_ID: - mValue = static_cast(other)->GetValue(); + m_value = static_cast(other)->GetValue(); return true; case MCore::AttributeFloat::TYPE_ID: - mValue = !MCore::Math::IsFloatZero(static_cast(other)->GetValue()); + m_value = !MCore::Math::IsFloatZero(static_cast(other)->GetValue()); return true; case MCore::AttributeInt32::TYPE_ID: - mValue = static_cast(other)->GetValue() != 0; + m_value = static_cast(other)->GetValue() != 0; return true; default: return false; diff --git a/Gems/EMotionFX/Code/MCore/Source/AttributeBool.h b/Gems/EMotionFX/Code/MCore/Source/AttributeBool.h index 3be04c3ce1..bf5d13d8fe 100644 --- a/Gems/EMotionFX/Code/MCore/Source/AttributeBool.h +++ b/Gems/EMotionFX/Code/MCore/Source/AttributeBool.h @@ -35,33 +35,33 @@ namespace MCore static AttributeBool* Create(bool value = false); // adjust values - MCORE_INLINE bool GetValue() const { return mValue; } - MCORE_INLINE void SetValue(bool value) { mValue = value; } + MCORE_INLINE bool GetValue() const { return m_value; } + MCORE_INLINE void SetValue(bool value) { m_value = value; } - MCORE_INLINE uint8* GetRawDataPointer() { return reinterpret_cast(&mValue); } + MCORE_INLINE uint8* GetRawDataPointer() { return reinterpret_cast(&m_value); } MCORE_INLINE size_t GetRawDataSize() const { return sizeof(bool); } // overloaded from the attribute base class - Attribute* Clone() const override { return AttributeBool::Create(mValue); } + Attribute* Clone() const override { return AttributeBool::Create(m_value); } const char* GetTypeString() const override { return "AttributeBool"; } bool InitFrom(const Attribute* other); bool InitFromString(const AZStd::string& valueString) override { - return AzFramework::StringFunc::LooksLikeBool(valueString.c_str(), &mValue); + return AzFramework::StringFunc::LooksLikeBool(valueString.c_str(), &m_value); } - bool ConvertToString(AZStd::string& outString) const override { outString = AZStd::string::format("%d", (mValue) ? 1 : 0); return true; } + bool ConvertToString(AZStd::string& outString) const override { outString = AZStd::string::format("%d", (m_value) ? 1 : 0); return true; } size_t GetClassSize() const override { return sizeof(AttributeBool); } AZ::u32 GetDefaultInterfaceType() const override { return ATTRIBUTE_INTERFACETYPE_CHECKBOX; } private: - bool mValue; /**< The boolean value, false on default. */ + bool m_value; /**< The boolean value, false on default. */ AttributeBool() : Attribute(TYPE_ID) - , mValue(false) {} + , m_value(false) {} AttributeBool(bool value) : Attribute(TYPE_ID) - , mValue(value) {} + , m_value(value) {} ~AttributeBool() {} }; } // namespace MCore diff --git a/Gems/EMotionFX/Code/MCore/Source/AttributeColor.h b/Gems/EMotionFX/Code/MCore/Source/AttributeColor.h index 4ad488af47..31205a088e 100644 --- a/Gems/EMotionFX/Code/MCore/Source/AttributeColor.h +++ b/Gems/EMotionFX/Code/MCore/Source/AttributeColor.h @@ -38,14 +38,14 @@ namespace MCore static AttributeColor* Create(const RGBAColor& value); // adjust values - MCORE_INLINE const RGBAColor& GetValue() const { return mValue; } - MCORE_INLINE void SetValue(const RGBAColor& value) { mValue = value; } + MCORE_INLINE const RGBAColor& GetValue() const { return m_value; } + MCORE_INLINE void SetValue(const RGBAColor& value) { m_value = value; } - MCORE_INLINE uint8* GetRawDataPointer() { return reinterpret_cast(&mValue); } + MCORE_INLINE uint8* GetRawDataPointer() { return reinterpret_cast(&m_value); } MCORE_INLINE size_t GetRawDataSize() const { return sizeof(RGBAColor); } // overloaded from the attribute base class - Attribute* Clone() const override { return AttributeColor::Create(mValue); } + Attribute* Clone() const override { return AttributeColor::Create(m_value); } const char* GetTypeString() const override { return "AttributeColor"; } bool InitFrom(const Attribute* other) override { @@ -53,7 +53,7 @@ namespace MCore { return false; } - mValue = static_cast(other)->GetValue(); + m_value = static_cast(other)->GetValue(); return true; } bool InitFromString(const AZStd::string& valueString) override @@ -63,21 +63,21 @@ namespace MCore { return false; } - mValue.Set(vec4.GetX(), vec4.GetY(), vec4.GetZ(), vec4.GetW()); + m_value.Set(vec4.GetX(), vec4.GetY(), vec4.GetZ(), vec4.GetW()); return true; } - bool ConvertToString(AZStd::string& outString) const override { AZStd::to_string(outString, AZ::Vector4(mValue.r, mValue.g, mValue.b, mValue.a)); return true; } + bool ConvertToString(AZStd::string& outString) const override { AZStd::to_string(outString, AZ::Vector4(m_value.m_r, m_value.m_g, m_value.m_b, m_value.m_a)); return true; } size_t GetClassSize() const override { return sizeof(AttributeColor); } AZ::u32 GetDefaultInterfaceType() const override { return ATTRIBUTE_INTERFACETYPE_COLOR; } private: - RGBAColor mValue; /**< The color value. */ + RGBAColor m_value; /**< The color value. */ AttributeColor() - : Attribute(TYPE_ID) { mValue.Set(0.0f, 0.0f, 0.0f, 1.0f); } + : Attribute(TYPE_ID) { m_value.Set(0.0f, 0.0f, 0.0f, 1.0f); } AttributeColor(const RGBAColor& value) : Attribute(TYPE_ID) - , mValue(value) { } + , m_value(value) { } ~AttributeColor() {} }; } // namespace MCore diff --git a/Gems/EMotionFX/Code/MCore/Source/AttributeFactory.cpp b/Gems/EMotionFX/Code/MCore/Source/AttributeFactory.cpp index 53b91dbb98..860d067671 100644 --- a/Gems/EMotionFX/Code/MCore/Source/AttributeFactory.cpp +++ b/Gems/EMotionFX/Code/MCore/Source/AttributeFactory.cpp @@ -41,13 +41,13 @@ namespace MCore { if (delFromMem) { - for (Attribute* attribute : mRegistered) + for (Attribute* attribute : m_registered) { delete attribute; } } - mRegistered.clear(); + m_registered.clear(); } @@ -57,11 +57,11 @@ namespace MCore const size_t attribIndex = FindAttributeIndexByType(attribute->GetType()); if (attribIndex != InvalidIndex) { - MCore::LogWarning("MCore::AttributeFactory::RegisterAttribute() - There is already an attribute of the same type registered (typeID %d vs %d - typeString '%s' vs '%s')", attribute->GetType(), mRegistered[attribIndex]->GetType(), attribute->GetTypeString(), mRegistered[attribIndex]->GetTypeString()); + MCore::LogWarning("MCore::AttributeFactory::RegisterAttribute() - There is already an attribute of the same type registered (typeID %d vs %d - typeString '%s' vs '%s')", attribute->GetType(), m_registered[attribIndex]->GetType(), attribute->GetTypeString(), m_registered[attribIndex]->GetTypeString()); return; } - mRegistered.emplace_back(attribute); + m_registered.emplace_back(attribute); } @@ -77,21 +77,21 @@ namespace MCore if (delFromMem) { - delete mRegistered[attribIndex]; + delete m_registered[attribIndex]; } - mRegistered.erase(mRegistered.begin() + attribIndex); + m_registered.erase(m_registered.begin() + attribIndex); } size_t AttributeFactory::FindAttributeIndexByType(size_t typeID) const { - const auto foundAttribute = AZStd::find_if(begin(mRegistered), end(mRegistered), [typeID](const Attribute* registeredAttribute) + const auto foundAttribute = AZStd::find_if(begin(m_registered), end(m_registered), [typeID](const Attribute* registeredAttribute) { return registeredAttribute->GetType() == typeID; }); - return foundAttribute != end(mRegistered) ? AZStd::distance(begin(mRegistered), foundAttribute) : InvalidIndex; + return foundAttribute != end(m_registered) ? AZStd::distance(begin(m_registered), foundAttribute) : InvalidIndex; } @@ -103,13 +103,13 @@ namespace MCore return nullptr; } - return mRegistered[attribIndex]->Clone(); + return m_registered[attribIndex]->Clone(); } void AttributeFactory::RegisterStandardTypes() { - mRegistered.reserve(10); + m_registered.reserve(10); RegisterAttribute(aznew AttributeFloat()); RegisterAttribute(aznew AttributeInt32()); RegisterAttribute(aznew AttributeString()); diff --git a/Gems/EMotionFX/Code/MCore/Source/AttributeFactory.h b/Gems/EMotionFX/Code/MCore/Source/AttributeFactory.h index 02bd5b0e1b..cb4c234267 100644 --- a/Gems/EMotionFX/Code/MCore/Source/AttributeFactory.h +++ b/Gems/EMotionFX/Code/MCore/Source/AttributeFactory.h @@ -30,13 +30,13 @@ namespace MCore void UnregisterAttribute(Attribute* attribute, bool delFromMem = true); void RegisterStandardTypes(); - size_t GetNumRegisteredAttributes() const { return mRegistered.size(); } - Attribute* GetRegisteredAttribute(size_t index) const { return mRegistered[index]; } + size_t GetNumRegisteredAttributes() const { return m_registered.size(); } + Attribute* GetRegisteredAttribute(size_t index) const { return m_registered[index]; } size_t FindAttributeIndexByType(size_t typeID) const; Attribute* CreateAttributeByType(size_t typeID) const; private: - AZStd::vector mRegistered; + AZStd::vector m_registered; }; } // namespace MCore diff --git a/Gems/EMotionFX/Code/MCore/Source/AttributeFloat.cpp b/Gems/EMotionFX/Code/MCore/Source/AttributeFloat.cpp index d8310d0744..fdfdc8a03b 100644 --- a/Gems/EMotionFX/Code/MCore/Source/AttributeFloat.cpp +++ b/Gems/EMotionFX/Code/MCore/Source/AttributeFloat.cpp @@ -21,13 +21,13 @@ namespace MCore switch (other->GetType()) { case TYPE_ID: - mValue = static_cast(other)->GetValue(); + m_value = static_cast(other)->GetValue(); return true; case MCore::AttributeBool::TYPE_ID: - mValue = static_cast(other)->GetValue(); + m_value = static_cast(other)->GetValue(); return true; case MCore::AttributeInt32::TYPE_ID: - mValue = static_cast(static_cast(other)->GetValue()); + m_value = static_cast(static_cast(other)->GetValue()); return true; default: return false; diff --git a/Gems/EMotionFX/Code/MCore/Source/AttributeFloat.h b/Gems/EMotionFX/Code/MCore/Source/AttributeFloat.h index fee4494ba5..97a68a9673 100644 --- a/Gems/EMotionFX/Code/MCore/Source/AttributeFloat.h +++ b/Gems/EMotionFX/Code/MCore/Source/AttributeFloat.h @@ -36,33 +36,33 @@ namespace MCore static AttributeFloat* Create(float value = 0.0f); // adjust values - MCORE_INLINE float GetValue() const { return mValue; } - MCORE_INLINE void SetValue(float value) { mValue = value; } + MCORE_INLINE float GetValue() const { return m_value; } + MCORE_INLINE void SetValue(float value) { m_value = value; } - MCORE_INLINE uint8* GetRawDataPointer() { return reinterpret_cast(&mValue); } + MCORE_INLINE uint8* GetRawDataPointer() { return reinterpret_cast(&m_value); } MCORE_INLINE size_t GetRawDataSize() const { return sizeof(float); } // overloaded from the attribute base class - Attribute* Clone() const override { return AttributeFloat::Create(mValue); } + Attribute* Clone() const override { return AttributeFloat::Create(m_value); } const char* GetTypeString() const override { return "AttributeFloat"; } bool InitFrom(const Attribute* other) override; bool InitFromString(const AZStd::string& valueString) override { - return AzFramework::StringFunc::LooksLikeFloat(valueString.c_str(), &mValue); + return AzFramework::StringFunc::LooksLikeFloat(valueString.c_str(), &m_value); } - bool ConvertToString(AZStd::string& outString) const override { outString = AZStd::string::format("%.8f", mValue); return true; } + bool ConvertToString(AZStd::string& outString) const override { outString = AZStd::string::format("%.8f", m_value); return true; } size_t GetClassSize() const override { return sizeof(AttributeFloat); } AZ::u32 GetDefaultInterfaceType() const override { return ATTRIBUTE_INTERFACETYPE_FLOATSPINNER; } private: - float mValue; /**< The float value. */ + float m_value; /**< The float value. */ AttributeFloat() : Attribute(TYPE_ID) - , mValue(0.0f) {} + , m_value(0.0f) {} AttributeFloat(float value) : Attribute(TYPE_ID) - , mValue(value) {} + , m_value(value) {} ~AttributeFloat() {} }; } // namespace MCore diff --git a/Gems/EMotionFX/Code/MCore/Source/AttributeInt32.cpp b/Gems/EMotionFX/Code/MCore/Source/AttributeInt32.cpp index d932c98a43..2297aca522 100644 --- a/Gems/EMotionFX/Code/MCore/Source/AttributeInt32.cpp +++ b/Gems/EMotionFX/Code/MCore/Source/AttributeInt32.cpp @@ -21,13 +21,13 @@ namespace MCore switch (other->GetType()) { case TYPE_ID: - mValue = static_cast(other)->GetValue(); + m_value = static_cast(other)->GetValue(); return true; case MCore::AttributeBool::TYPE_ID: - mValue = static_cast(other)->GetValue(); + m_value = static_cast(other)->GetValue(); return true; case MCore::AttributeFloat::TYPE_ID: - mValue = static_cast(static_cast(other)->GetValue()); + m_value = static_cast(static_cast(other)->GetValue()); return true; default: return false; diff --git a/Gems/EMotionFX/Code/MCore/Source/AttributeInt32.h b/Gems/EMotionFX/Code/MCore/Source/AttributeInt32.h index b1fd1da686..e195d584a5 100644 --- a/Gems/EMotionFX/Code/MCore/Source/AttributeInt32.h +++ b/Gems/EMotionFX/Code/MCore/Source/AttributeInt32.h @@ -36,33 +36,33 @@ namespace MCore static AttributeInt32* Create(int32 value = 0); // adjust values - MCORE_INLINE int32 GetValue() const { return mValue; } - MCORE_INLINE void SetValue(int32 value) { mValue = value; } + MCORE_INLINE int32 GetValue() const { return m_value; } + MCORE_INLINE void SetValue(int32 value) { m_value = value; } - MCORE_INLINE uint8* GetRawDataPointer() { return reinterpret_cast(&mValue); } + MCORE_INLINE uint8* GetRawDataPointer() { return reinterpret_cast(&m_value); } MCORE_INLINE size_t GetRawDataSize() const { return sizeof(int32); } // overloaded from the attribute base class - Attribute* Clone() const override { return AttributeInt32::Create(mValue); } + Attribute* Clone() const override { return AttributeInt32::Create(m_value); } const char* GetTypeString() const override { return "AttributeInt32"; } bool InitFrom(const Attribute* other); bool InitFromString(const AZStd::string& valueString) override { - return AzFramework::StringFunc::LooksLikeInt(valueString.c_str(), &mValue); + return AzFramework::StringFunc::LooksLikeInt(valueString.c_str(), &m_value); } - bool ConvertToString(AZStd::string& outString) const override { outString = AZStd::string::format("%d", mValue); return true; } + bool ConvertToString(AZStd::string& outString) const override { outString = AZStd::string::format("%d", m_value); return true; } size_t GetClassSize() const override { return sizeof(AttributeInt32); } AZ::u32 GetDefaultInterfaceType() const override { return ATTRIBUTE_INTERFACETYPE_INTSPINNER; } private: - int32 mValue; /**< The signed integer value. */ + int32 m_value; /**< The signed integer value. */ AttributeInt32() : Attribute(TYPE_ID) - , mValue(0) {} + , m_value(0) {} AttributeInt32(int32 value) : Attribute(TYPE_ID) - , mValue(value) {} + , m_value(value) {} ~AttributeInt32() {} }; } // namespace MCore diff --git a/Gems/EMotionFX/Code/MCore/Source/AttributePointer.h b/Gems/EMotionFX/Code/MCore/Source/AttributePointer.h index 98eb5f602b..d0cf2d5194 100644 --- a/Gems/EMotionFX/Code/MCore/Source/AttributePointer.h +++ b/Gems/EMotionFX/Code/MCore/Source/AttributePointer.h @@ -36,11 +36,11 @@ namespace MCore static AttributePointer* Create(void* value = nullptr); // adjust values - MCORE_INLINE void* GetValue() const { return mValue; } - MCORE_INLINE void SetValue(void* value) { mValue = value; } + MCORE_INLINE void* GetValue() const { return m_value; } + MCORE_INLINE void SetValue(void* value) { m_value = value; } // overloaded from the attribute base class - Attribute* Clone() const override { return AttributePointer::Create(mValue); } + Attribute* Clone() const override { return AttributePointer::Create(m_value); } const char* GetTypeString() const override { return "AttributePointer"; } bool InitFrom(const Attribute* other) override { @@ -48,7 +48,7 @@ namespace MCore { return false; } - mValue = static_cast(other)->GetValue(); + m_value = static_cast(other)->GetValue(); return true; } bool InitFromString(const AZStd::string& valueString) override { MCORE_UNUSED(valueString); MCORE_ASSERT(false); return false; } // currently unsupported @@ -57,14 +57,14 @@ namespace MCore AZ::u32 GetDefaultInterfaceType() const override { return ATTRIBUTE_INTERFACETYPE_DEFAULT; } private: - void* mValue; /**< The pointer value. */ + void* m_value; /**< The pointer value. */ AttributePointer() : Attribute(TYPE_ID) - , mValue(nullptr) { } + , m_value(nullptr) { } AttributePointer(void* pointer) : Attribute(TYPE_ID) - , mValue(pointer) { } + , m_value(pointer) { } ~AttributePointer() {} }; } // namespace MCore diff --git a/Gems/EMotionFX/Code/MCore/Source/AttributeQuaternion.h b/Gems/EMotionFX/Code/MCore/Source/AttributeQuaternion.h index 39d9243197..1efbe7f690 100644 --- a/Gems/EMotionFX/Code/MCore/Source/AttributeQuaternion.h +++ b/Gems/EMotionFX/Code/MCore/Source/AttributeQuaternion.h @@ -38,15 +38,15 @@ namespace MCore static AttributeQuaternion* Create(float x, float y, float z, float w); static AttributeQuaternion* Create(const AZ::Quaternion& value); - MCORE_INLINE uint8* GetRawDataPointer() { return reinterpret_cast(&mValue); } + MCORE_INLINE uint8* GetRawDataPointer() { return reinterpret_cast(&m_value); } MCORE_INLINE size_t GetRawDataSize() const { return sizeof(AZ::Quaternion); } // adjust values - MCORE_INLINE const AZ::Quaternion& GetValue() const { return mValue; } - MCORE_INLINE void SetValue(const AZ::Quaternion& value) { mValue = value; } + MCORE_INLINE const AZ::Quaternion& GetValue() const { return m_value; } + MCORE_INLINE void SetValue(const AZ::Quaternion& value) { m_value = value; } // overloaded from the attribute base class - Attribute* Clone() const override { return AttributeQuaternion::Create(mValue); } + Attribute* Clone() const override { return AttributeQuaternion::Create(m_value); } const char* GetTypeString() const override { return "AttributeQuaternion"; } bool InitFrom(const Attribute* other) override { @@ -54,7 +54,7 @@ namespace MCore { return false; } - mValue = static_cast(other)->GetValue(); + m_value = static_cast(other)->GetValue(); return true; } bool InitFromString(const AZStd::string& valueString) override @@ -64,23 +64,23 @@ namespace MCore { return false; } - mValue.Set(vec4.GetX(), vec4.GetY(), vec4.GetZ(), vec4.GetW()); + m_value.Set(vec4.GetX(), vec4.GetY(), vec4.GetZ(), vec4.GetW()); return true; } - bool ConvertToString(AZStd::string& outString) const override { AZStd::to_string(outString, mValue); return true; } + bool ConvertToString(AZStd::string& outString) const override { AZStd::to_string(outString, m_value); return true; } size_t GetClassSize() const override { return sizeof(AttributeQuaternion); } AZ::u32 GetDefaultInterfaceType() const override { return ATTRIBUTE_INTERFACETYPE_DEFAULT; } private: - AZ::Quaternion mValue; /**< The Quaternion value. */ + AZ::Quaternion m_value; /**< The Quaternion value. */ AttributeQuaternion() : Attribute(TYPE_ID) - , mValue(AZ::Quaternion::CreateIdentity()) + , m_value(AZ::Quaternion::CreateIdentity()) {} AttributeQuaternion(const AZ::Quaternion& value) : Attribute(TYPE_ID) - , mValue(value) {} + , m_value(value) {} ~AttributeQuaternion() { } }; } // namespace MCore diff --git a/Gems/EMotionFX/Code/MCore/Source/AttributeString.h b/Gems/EMotionFX/Code/MCore/Source/AttributeString.h index a05c057023..916b9ad2fd 100644 --- a/Gems/EMotionFX/Code/MCore/Source/AttributeString.h +++ b/Gems/EMotionFX/Code/MCore/Source/AttributeString.h @@ -35,16 +35,16 @@ namespace MCore static AttributeString* Create(const AZStd::string& value); static AttributeString* Create(const char* value = ""); - MCORE_INLINE uint8* GetRawDataPointer() { return reinterpret_cast(mValue.data()); } - MCORE_INLINE size_t GetRawDataSize() const { return mValue.size(); } + MCORE_INLINE uint8* GetRawDataPointer() { return reinterpret_cast(m_value.data()); } + MCORE_INLINE size_t GetRawDataSize() const { return m_value.size(); } // adjust values - MCORE_INLINE const char* AsChar() const { return mValue.c_str(); } - MCORE_INLINE const AZStd::string& GetValue() const { return mValue; } - MCORE_INLINE void SetValue(const AZStd::string& value) { mValue = value; } + MCORE_INLINE const char* AsChar() const { return m_value.c_str(); } + MCORE_INLINE const AZStd::string& GetValue() const { return m_value; } + MCORE_INLINE void SetValue(const AZStd::string& value) { m_value = value; } // overloaded from the attribute base class - Attribute* Clone() const override { return AttributeString::Create(mValue); } + Attribute* Clone() const override { return AttributeString::Create(m_value); } const char* GetTypeString() const override { return "AttributeString"; } bool InitFrom(const Attribute* other) override { @@ -52,25 +52,25 @@ namespace MCore { return false; } - mValue = static_cast(other)->GetValue(); + m_value = static_cast(other)->GetValue(); return true; } - bool InitFromString(const AZStd::string& valueString) override { mValue = valueString; return true; } - bool ConvertToString(AZStd::string& outString) const override { outString = mValue; return true; } + bool InitFromString(const AZStd::string& valueString) override { m_value = valueString; return true; } + bool ConvertToString(AZStd::string& outString) const override { outString = m_value; return true; } size_t GetClassSize() const override { return sizeof(AttributeString); } uint32 GetDefaultInterfaceType() const override { return ATTRIBUTE_INTERFACETYPE_STRING; } private: - AZStd::string mValue; /**< The string value. */ + AZStd::string m_value; /**< The string value. */ AttributeString() : Attribute(TYPE_ID) { } AttributeString(const AZStd::string& value) : Attribute(TYPE_ID) - , mValue(value) { } + , m_value(value) { } AttributeString(const char* value) : Attribute(TYPE_ID) - , mValue(value) { } - ~AttributeString() { mValue.clear(); } + , m_value(value) { } + ~AttributeString() { m_value.clear(); } }; } // namespace MCore diff --git a/Gems/EMotionFX/Code/MCore/Source/AttributeVector2.h b/Gems/EMotionFX/Code/MCore/Source/AttributeVector2.h index 826899186a..2d12e7a268 100644 --- a/Gems/EMotionFX/Code/MCore/Source/AttributeVector2.h +++ b/Gems/EMotionFX/Code/MCore/Source/AttributeVector2.h @@ -42,15 +42,15 @@ namespace MCore static AttributeVector2* Create(const AZ::Vector2& value); static AttributeVector2* Create(float x, float y); - MCORE_INLINE uint8* GetRawDataPointer() { return reinterpret_cast(&mValue); } + MCORE_INLINE uint8* GetRawDataPointer() { return reinterpret_cast(&m_value); } MCORE_INLINE size_t GetRawDataSize() const { return sizeofVector2; } // adjust values - MCORE_INLINE const AZ::Vector2& GetValue() const { return mValue; } - MCORE_INLINE void SetValue(const AZ::Vector2& value) { mValue = value; } + MCORE_INLINE const AZ::Vector2& GetValue() const { return m_value; } + MCORE_INLINE void SetValue(const AZ::Vector2& value) { m_value = value; } // overloaded from the attribute base class - Attribute* Clone() const override { return AttributeVector2::Create(mValue); } + Attribute* Clone() const override { return AttributeVector2::Create(m_value); } const char* GetTypeString() const override { return "AttributeVector2"; } bool InitFrom(const Attribute* other) override { @@ -58,25 +58,25 @@ namespace MCore { return false; } - mValue = static_cast(other)->GetValue(); + m_value = static_cast(other)->GetValue(); return true; } bool InitFromString(const AZStd::string& valueString) override { - return AzFramework::StringFunc::LooksLikeVector2(valueString.c_str(), &mValue); + return AzFramework::StringFunc::LooksLikeVector2(valueString.c_str(), &m_value); } - bool ConvertToString(AZStd::string& outString) const override { AZStd::to_string(outString, mValue); return true; } + bool ConvertToString(AZStd::string& outString) const override { AZStd::to_string(outString, m_value); return true; } size_t GetClassSize() const override { return sizeof(AttributeVector2); } AZ::u32 GetDefaultInterfaceType() const override { return ATTRIBUTE_INTERFACETYPE_VECTOR2; } private: - AZ::Vector2 mValue; /**< The Vector2 value. */ + AZ::Vector2 m_value; /**< The Vector2 value. */ AttributeVector2() - : Attribute(TYPE_ID) { mValue.Set(0.0f, 0.0f); } + : Attribute(TYPE_ID) { m_value.Set(0.0f, 0.0f); } AttributeVector2(const AZ::Vector2& value) : Attribute(TYPE_ID) - , mValue(value) { } + , m_value(value) { } ~AttributeVector2() { } }; } // namespace MCore diff --git a/Gems/EMotionFX/Code/MCore/Source/AttributeVector3.h b/Gems/EMotionFX/Code/MCore/Source/AttributeVector3.h index 066962fb8f..481a4e4665 100644 --- a/Gems/EMotionFX/Code/MCore/Source/AttributeVector3.h +++ b/Gems/EMotionFX/Code/MCore/Source/AttributeVector3.h @@ -37,15 +37,15 @@ namespace MCore static AttributeVector3* Create(const AZ::Vector3& value); static AttributeVector3* Create(float x, float y, float z); - MCORE_INLINE uint8* GetRawDataPointer() { return reinterpret_cast(&mValue); } + MCORE_INLINE uint8* GetRawDataPointer() { return reinterpret_cast(&m_value); } MCORE_INLINE size_t GetRawDataSize() const { return sizeof(AZ::Vector3); } // adjust values - MCORE_INLINE const AZ::Vector3& GetValue() const { return mValue; } - MCORE_INLINE void SetValue(const AZ::Vector3& value) { mValue = value; } + MCORE_INLINE const AZ::Vector3& GetValue() const { return m_value; } + MCORE_INLINE void SetValue(const AZ::Vector3& value) { m_value = value; } // overloaded from the attribute base class - Attribute* Clone() const override { return AttributeVector3::Create(mValue); } + Attribute* Clone() const override { return AttributeVector3::Create(m_value); } const char* GetTypeString() const override { return "AttributeVector3"; } bool InitFrom(const Attribute* other) override { @@ -53,7 +53,7 @@ namespace MCore { return false; } - mValue = static_cast(other)->GetValue(); + m_value = static_cast(other)->GetValue(); return true; } bool InitFromString(const AZStd::string& valueString) override @@ -63,21 +63,21 @@ namespace MCore { return false; } - mValue.Set(vec3.GetX(), vec3.GetY(), vec3.GetZ()); + m_value.Set(vec3.GetX(), vec3.GetY(), vec3.GetZ()); return true; } - bool ConvertToString(AZStd::string& outString) const override { AZStd::to_string(outString, mValue); return true; } + bool ConvertToString(AZStd::string& outString) const override { AZStd::to_string(outString, m_value); return true; } size_t GetClassSize() const override { return sizeof(AttributeVector3); } AZ::u32 GetDefaultInterfaceType() const override { return ATTRIBUTE_INTERFACETYPE_VECTOR3; } private: - AZ::Vector3 mValue; /**< The Vector3 value. */ + AZ::Vector3 m_value; /**< The Vector3 value. */ AttributeVector3() - : Attribute(TYPE_ID) { mValue.Set(0.0f, 0.0f, 0.0f); } + : Attribute(TYPE_ID) { m_value.Set(0.0f, 0.0f, 0.0f); } AttributeVector3(const AZ::Vector3& value) : Attribute(TYPE_ID) - , mValue(value) { } + , m_value(value) { } ~AttributeVector3() { } }; } // namespace MCore diff --git a/Gems/EMotionFX/Code/MCore/Source/AttributeVector4.h b/Gems/EMotionFX/Code/MCore/Source/AttributeVector4.h index 7b20e92a6b..cc38fb92ab 100644 --- a/Gems/EMotionFX/Code/MCore/Source/AttributeVector4.h +++ b/Gems/EMotionFX/Code/MCore/Source/AttributeVector4.h @@ -38,15 +38,15 @@ namespace MCore static AttributeVector4* Create(const AZ::Vector4& value); static AttributeVector4* Create(float x, float y, float z, float w); - MCORE_INLINE uint8* GetRawDataPointer() { return reinterpret_cast(&mValue); } + MCORE_INLINE uint8* GetRawDataPointer() { return reinterpret_cast(&m_value); } MCORE_INLINE size_t GetRawDataSize() const { return sizeof(AZ::Vector4); } // adjust values - MCORE_INLINE const AZ::Vector4& GetValue() const { return mValue; } - MCORE_INLINE void SetValue(const AZ::Vector4& value) { mValue = value; } + MCORE_INLINE const AZ::Vector4& GetValue() const { return m_value; } + MCORE_INLINE void SetValue(const AZ::Vector4& value) { m_value = value; } // overloaded from the attribute base class - Attribute* Clone() const override { return AttributeVector4::Create(mValue); } + Attribute* Clone() const override { return AttributeVector4::Create(m_value); } const char* GetTypeString() const override { return "AttributeVector4"; } bool InitFrom(const Attribute* other) override { @@ -54,26 +54,25 @@ namespace MCore { return false; } - mValue = static_cast(other)->GetValue(); + m_value = static_cast(other)->GetValue(); return true; } bool InitFromString(const AZStd::string& valueString) override { - return AzFramework::StringFunc::LooksLikeVector4(valueString.c_str(), &mValue); + return AzFramework::StringFunc::LooksLikeVector4(valueString.c_str(), &m_value); } - bool ConvertToString(AZStd::string& outString) const override { AZStd::to_string(outString, mValue); return true; } - // void ConvertCoordinateSystem() { GetCoordinateSystem().ConvertVector4(&mValue); } + bool ConvertToString(AZStd::string& outString) const override { AZStd::to_string(outString, m_value); return true; } size_t GetClassSize() const override { return sizeof(AttributeVector4); } AZ::u32 GetDefaultInterfaceType() const override { return ATTRIBUTE_INTERFACETYPE_VECTOR4; } private: - AZ::Vector4 mValue; /**< The Vector4 value. */ + AZ::Vector4 m_value; /**< The Vector4 value. */ AttributeVector4() - : Attribute(TYPE_ID) { mValue.Set(0.0f, 0.0f, 0.0f, 0.0f); } + : Attribute(TYPE_ID) { m_value.Set(0.0f, 0.0f, 0.0f, 0.0f); } AttributeVector4(const AZ::Vector4& value) : Attribute(TYPE_ID) - , mValue(value) { } + , m_value(value) { } ~AttributeVector4() { } }; } // namespace MCore diff --git a/Gems/EMotionFX/Code/MCore/Source/AzCoreConversions.h b/Gems/EMotionFX/Code/MCore/Source/AzCoreConversions.h index d185a804b8..bbc874dfdd 100644 --- a/Gems/EMotionFX/Code/MCore/Source/AzCoreConversions.h +++ b/Gems/EMotionFX/Code/MCore/Source/AzCoreConversions.h @@ -29,7 +29,7 @@ namespace MCore { AZ_FORCE_INLINE AZ::Color EmfxColorToAzColor(const RGBAColor& emfxColor) { - return AZ::Color(emfxColor.r, emfxColor.g, emfxColor.b, emfxColor.a); + return AZ::Color(emfxColor.m_r, emfxColor.m_g, emfxColor.m_b, emfxColor.m_a); } AZ_FORCE_INLINE RGBAColor AzColorToEmfxColor(const AZ::Color& azColor) @@ -39,10 +39,10 @@ namespace MCore AZ_FORCE_INLINE AZ::Transform EmfxTransformToAzTransform(const EMotionFX::Transform& emfxTransform) { - AZ::Transform transform = AZ::Transform::CreateFromQuaternionAndTranslation(emfxTransform.mRotation, emfxTransform.mPosition); + AZ::Transform transform = AZ::Transform::CreateFromQuaternionAndTranslation(emfxTransform.m_rotation, emfxTransform.m_position); EMFX_SCALECODE ( - transform.MultiplyByUniformScale(emfxTransform.mScale.GetMaxElement()); + transform.MultiplyByUniformScale(emfxTransform.m_scale.GetMaxElement()); ) return transform; } diff --git a/Gems/EMotionFX/Code/MCore/Source/BoundingSphere.cpp b/Gems/EMotionFX/Code/MCore/Source/BoundingSphere.cpp index 959cebe16d..376052563f 100644 --- a/Gems/EMotionFX/Code/MCore/Source/BoundingSphere.cpp +++ b/Gems/EMotionFX/Code/MCore/Source/BoundingSphere.cpp @@ -17,26 +17,26 @@ namespace MCore void BoundingSphere::Encapsulate(const AZ::Vector3& v) { // calculate the squared distance from the center to the point - const AZ::Vector3 diff = v - mCenter; + const AZ::Vector3 diff = v - m_center; const float dist = diff.Dot(diff); // if the current sphere doesn't contain the point, grow the sphere so that it contains the point - if (dist > mRadiusSq) + if (dist > m_radiusSq) { - const AZ::Vector3 diff2 = diff.GetNormalized() * mRadius; + const AZ::Vector3 diff2 = diff.GetNormalized() * m_radius; const AZ::Vector3 delta = 0.5f * (diff - diff2); - mCenter += delta; + m_center += delta; // TODO: KB- Was a 'safe' function, is there an AZ equivalent? float length = delta.GetLengthSq(); if (length >= FLT_EPSILON) { - mRadius += sqrtf(length); + m_radius += sqrtf(length); } else { - mRadius = 0.0f; + m_radius = 0.0f; } - mRadiusSq = mRadius * mRadius; + m_radiusSq = m_radius * m_radius; } } @@ -49,10 +49,10 @@ namespace MCore for (int32_t t = 0; t < 3; ++t) { const AZ::Vector3& minVec = b.GetMin(); - if (mCenter.GetElement(t) < minVec.GetElement(t)) + if (m_center.GetElement(t) < minVec.GetElement(t)) { - distance += (mCenter.GetElement(t) - minVec.GetElement(t)) * (mCenter.GetElement(t) - minVec.GetElement(t)); - if (distance > mRadiusSq) + distance += (m_center.GetElement(t) - minVec.GetElement(t)) * (m_center.GetElement(t) - minVec.GetElement(t)); + if (distance > m_radiusSq) { return false; } @@ -60,10 +60,10 @@ namespace MCore else { const AZ::Vector3& maxVec = b.GetMax(); - if (mCenter.GetElement(t) > maxVec.GetElement(t)) + if (m_center.GetElement(t) > maxVec.GetElement(t)) { - distance += (mCenter.GetElement(t) - maxVec.GetElement(t)) * (mCenter.GetElement(t) - maxVec.GetElement(t)); - if (distance > mRadiusSq) + distance += (m_center.GetElement(t) - maxVec.GetElement(t)) * (m_center.GetElement(t) - maxVec.GetElement(t)); + if (distance > m_radiusSq) { return false; } @@ -82,20 +82,20 @@ namespace MCore for (int32_t t = 0; t < 3; ++t) { const AZ::Vector3& maxVec = b.GetMax(); - if (mCenter.GetElement(t) < maxVec.GetElement(t)) + if (m_center.GetElement(t) < maxVec.GetElement(t)) { - distance += (mCenter.GetElement(t) - maxVec.GetElement(t)) * (mCenter.GetElement(t) - maxVec.GetElement(t)); + distance += (m_center.GetElement(t) - maxVec.GetElement(t)) * (m_center.GetElement(t) - maxVec.GetElement(t)); } else { const AZ::Vector3& minVec = b.GetMin(); - if (mCenter.GetElement(t) > minVec.GetElement(t)) + if (m_center.GetElement(t) > minVec.GetElement(t)) { - distance += (mCenter.GetElement(t) - minVec.GetElement(t)) * (mCenter.GetElement(t) - minVec.GetElement(t)); + distance += (m_center.GetElement(t) - minVec.GetElement(t)) * (m_center.GetElement(t) - minVec.GetElement(t)); } } - if (distance > mRadiusSq) + if (distance > m_radiusSq) { return false; } diff --git a/Gems/EMotionFX/Code/MCore/Source/BoundingSphere.h b/Gems/EMotionFX/Code/MCore/Source/BoundingSphere.h index db8aee70cc..1687f72799 100644 --- a/Gems/EMotionFX/Code/MCore/Source/BoundingSphere.h +++ b/Gems/EMotionFX/Code/MCore/Source/BoundingSphere.h @@ -32,9 +32,9 @@ namespace MCore * Sets the sphere center to (0,0,0) and makes the radius 0. */ MCORE_INLINE BoundingSphere() - : mCenter(AZ::Vector3::CreateZero()) - , mRadius(0.0f) - , mRadiusSq(0.0f) {} + : m_center(AZ::Vector3::CreateZero()) + , m_radius(0.0f) + , m_radiusSq(0.0f) {} /** * Constructor which sets the center of the sphere and it's radius. @@ -43,9 +43,9 @@ namespace MCore * @param rad The radius of the sphere. */ MCORE_INLINE BoundingSphere(const AZ::Vector3& pos, float rad) - : mCenter(pos) - , mRadius(rad) - , mRadiusSq(rad * rad) {} + : m_center(pos) + , m_radius(rad) + , m_radiusSq(rad * rad) {} /** * Constructor which sets the center, radius and squared radius. @@ -55,16 +55,16 @@ namespace MCore * @param radSq The squared radius of the sphere (rad*rad). */ MCORE_INLINE BoundingSphere(const AZ::Vector3& pos, float rad, float radSq) - : mCenter(pos) - , mRadius(rad) - , mRadiusSq(radSq) {} + : m_center(pos) + , m_radius(rad) + , m_radiusSq(radSq) {} /** * Initialize the spheres center, radius and square radius. * This will set the center position to (0,0,0) and both the radius and squared radius to 0. * Call this method when you want to reset the sphere. Note that this is already done by the default constructor. */ - MCORE_INLINE void Init() { mCenter = AZ::Vector3::CreateZero(); mRadius = mRadiusSq = 0.0f; } + MCORE_INLINE void Init() { m_center = AZ::Vector3::CreateZero(); m_radius = m_radiusSq = 0.0f; } /** * Encapsulate a 3D point to the sphere. @@ -75,12 +75,12 @@ namespace MCore */ MCORE_INLINE void EncapsulateFast(const AZ::Vector3& v) { - AZ::Vector3 diff = (mCenter - v); + AZ::Vector3 diff = (m_center - v); const float dist = diff.Dot(diff); - if (dist > mRadiusSq) + if (dist > m_radiusSq) { - mRadiusSq = dist; - mRadius = Math::Sqrt(dist); + m_radiusSq = dist; + m_radius = Math::Sqrt(dist); } } @@ -90,7 +90,7 @@ namespace MCore * @param v The vector representing the 3D point to perform the test with. * @result Returns true when 'v' is inside the spheres volume, otherwise false is returned. */ - MCORE_INLINE bool Contains(const AZ::Vector3& v) { return ((mCenter - v).GetLengthSq() <= mRadiusSq); } + MCORE_INLINE bool Contains(const AZ::Vector3& v) { return ((m_center - v).GetLengthSq() <= m_radiusSq); } /** * Check if the sphere COMPLETELY contains a given other sphere. @@ -98,7 +98,7 @@ namespace MCore * @param s The sphere to perform the test with. * @result Returns true when 's' is completely inside this sphere. False is returned in any other case. */ - MCORE_INLINE bool Contains(const BoundingSphere& s) const { return ((mCenter - s.mCenter).GetLengthSq() <= (mRadiusSq - s.mRadiusSq)); } + MCORE_INLINE bool Contains(const BoundingSphere& s) const { return ((m_center - s.m_center).GetLengthSq() <= (m_radiusSq - s.m_radiusSq)); } /** * Check if a given sphere intersects with this sphere. @@ -106,7 +106,7 @@ namespace MCore * @param s The sphere to perform the intersection test with. * @result Returns true when 's' intersects this sphere. So if it's partially or completely inside this sphere or if the borders overlap. */ - MCORE_INLINE bool Intersects(const BoundingSphere& s) const { return ((mCenter - s.mCenter).GetLengthSq() <= (mRadiusSq + s.mRadiusSq)); } + MCORE_INLINE bool Intersects(const BoundingSphere& s) const { return ((m_center - s.m_center).GetLengthSq() <= (m_radiusSq + s.m_radiusSq)); } /** * Encapsulate a given 3D point with this sphere. @@ -138,36 +138,36 @@ namespace MCore * Get the radius of the sphere. * @result Returns the radius of the sphere. */ - MCORE_INLINE float GetRadius() const { return mRadius; } + MCORE_INLINE float GetRadius() const { return m_radius; } /** * Get the squared radius of the sphere. * @result Returns the squared radius of the sphere (no calculations done for this), since it's already known. */ - MCORE_INLINE float GetRadiusSquared() const { return mRadiusSq; } + MCORE_INLINE float GetRadiusSquared() const { return m_radiusSq; } /** * Get the center of the sphere. So the position of the sphere. * @result Returns the center position of the sphere. */ - MCORE_INLINE const AZ::Vector3& GetCenter() const { return mCenter; } + MCORE_INLINE const AZ::Vector3& GetCenter() const { return m_center; } /** * Set the center of the sphere. * @param center The center position of the sphere. */ - MCORE_INLINE void SetCenter(const AZ::Vector3& center) { mCenter = center; } + MCORE_INLINE void SetCenter(const AZ::Vector3& center) { m_center = center; } /** * Set the radius of the sphere. * The squared radius will automatically be updated inside this method. * @param radius The radius of the sphere. */ - MCORE_INLINE void SetRadius(float radius) { mRadius = radius; mRadiusSq = radius * radius; } + MCORE_INLINE void SetRadius(float radius) { m_radius = radius; m_radiusSq = radius * radius; } private: - AZ::Vector3 mCenter; /**< The center of the sphere. */ - float mRadius; /**< The radius of the sphere. */ - float mRadiusSq; /**< The squared radius of the sphere (mRadius*mRadius).*/ + AZ::Vector3 m_center; /**< The center of the sphere. */ + float m_radius; /**< The radius of the sphere. */ + float m_radiusSq; /**< The squared radius of the sphere (m_radius*m_radius).*/ }; } // namespace MCore diff --git a/Gems/EMotionFX/Code/MCore/Source/Color.cpp b/Gems/EMotionFX/Code/MCore/Source/Color.cpp index 77249bddfb..504142528c 100644 --- a/Gems/EMotionFX/Code/MCore/Source/Color.cpp +++ b/Gems/EMotionFX/Code/MCore/Source/Color.cpp @@ -13,7 +13,7 @@ namespace MCore { // the color table - uint32 RGBAColor::mColorTable[128] = + uint32 RGBAColor::s_colorTable[128] = { 0xFF000080, 0xFF00008B, diff --git a/Gems/EMotionFX/Code/MCore/Source/Color.h b/Gems/EMotionFX/Code/MCore/Source/Color.h index 8845d1f41b..ee8b88cc47 100644 --- a/Gems/EMotionFX/Code/MCore/Source/Color.h +++ b/Gems/EMotionFX/Code/MCore/Source/Color.h @@ -48,20 +48,20 @@ namespace MCore * Default constructor. Color will be set to black (0,0,0,0). */ MCORE_INLINE RGBAColor() - : r(0.0f) - , g(0.0f) - , b(0.0f) - , a(1.0f) {} + : m_r(0.0f) + , m_g(0.0f) + , m_b(0.0f) + , m_a(1.0f) {} /** * Constructor which sets all components to the same given value. * @param value The value to put in all components (r,g,b,a). */ MCORE_INLINE RGBAColor(float value) - : r(value) - , g(value) - , b(value) - , a(value) {} + : m_r(value) + , m_g(value) + , m_b(value) + , m_a(value) {} /** * Constructor which sets each color component. @@ -71,40 +71,40 @@ namespace MCore * @param cA The value for alpha [default=1.0] */ MCORE_INLINE RGBAColor(float cR, float cG, float cB, float cA = 1.0f) - : r(cR) - , g(cG) - , b(cB) - , a(cA) {} + : m_r(cR) + , m_g(cG) + , m_b(cB) + , m_a(cA) {} /** * Copy constructor. * @param col The color to copy the component values from. */ MCORE_INLINE RGBAColor(const RGBAColor& col) - : r(col.r) - , g(col.g) - , b(col.b) - , a(col.a) {} + : m_r(col.m_r) + , m_g(col.m_g) + , m_b(col.m_b) + , m_a(col.m_a) {} /** * Constructor to convert a 32-bits DWORD to a high precision color. * @param col The 32-bits DWORD, for example constructed using the MCore::RGBA(...) function. */ RGBAColor(uint32 col) - : r(ExtractRed(col) / 255.0f) - , g(ExtractGreen(col) / 255.0f) - , b(ExtractBlue(col) / 255.0f) - , a(ExtractAlpha(col) / 255.0f) {} + : m_r(ExtractRed(col) / 255.0f) + , m_g(ExtractGreen(col) / 255.0f) + , m_b(ExtractBlue(col) / 255.0f) + , m_a(ExtractAlpha(col) / 255.0f) {} /** * Constructor to convert from AZ::Color. This constructor is convenient until we replace the usage of this class with AZ::Color * @param color The AZ::Color to construct from */ RGBAColor(const AZ::Color& color) - : r(color.GetR()) - , g(color.GetG()) - , b(color.GetB()) - , a(color.GetA()) + : m_r(color.GetR()) + , m_g(color.GetG()) + , m_b(color.GetB()) + , m_a(color.GetA()) {} /** @@ -112,7 +112,7 @@ namespace MCore */ operator AZ::Color() const { - return AZ::Color(r, g, b, a); + return AZ::Color(m_r, m_g, m_b, m_a); } /** @@ -122,18 +122,18 @@ namespace MCore * @param cB The value for blue. * @param cA The value for alpha. */ - MCORE_INLINE void Set(float cR, float cG, float cB, float cA) { r = cR; g = cG; b = cB; a = cA; } + MCORE_INLINE void Set(float cR, float cG, float cB, float cA) { m_r = cR; m_g = cG; m_b = cB; m_a = cA; } /** * Set the color component values. * @param color The color to set. */ - MCORE_INLINE void Set(const RGBAColor& color) { r = color.r; g = color.g; b = color.b; a = color.a; } + MCORE_INLINE void Set(const RGBAColor& color) { m_r = color.m_r; m_g = color.m_g; m_b = color.m_b; m_a = color.m_a; } /** * Clear the color component values. Set them all to zero, so the color turns into black. */ - MCORE_INLINE void Zero() { r = g = b = a = 0.0f; } + MCORE_INLINE void Zero() { m_r = m_g = m_b = m_a = 0.0f; } /** * Clamp all color component values in a range of 0..1 @@ -141,20 +141,20 @@ namespace MCore * the Exposure method for exposure control or the Normalize method. * @result The clamped color. */ - MCORE_INLINE RGBAColor& Clamp() { r = MCore::Clamp(r, 0.0f, 1.0f); g = MCore::Clamp(g, 0.0f, 1.0f); b = MCore::Clamp(b, 0.0f, 1.0f); a = MCore::Clamp(a, 0.0f, 1.0f); return *this; } + MCORE_INLINE RGBAColor& Clamp() { m_r = MCore::Clamp(m_r, 0.0f, 1.0f); m_g = MCore::Clamp(m_g, 0.0f, 1.0f); m_b = MCore::Clamp(m_b, 0.0f, 1.0f); m_a = MCore::Clamp(m_a, 0.0f, 1.0f); return *this; } /** * Returns the length of the color components (r, g, b), just like you calculate the length of a vector. * The higher the length value, the more bright the color will be. * @result The length of the vector constructed by the r, g and b components. */ - MCORE_INLINE float CalcLength() const { return Math::Sqrt(r * r + g * g + b * b); } + MCORE_INLINE float CalcLength() const { return Math::Sqrt(m_r * m_r + m_g * m_g + m_b * m_b); } /** * Calculates and returns the intensity of the color. This gives an idea of how bright the color would be on the screen. * @result The intensity. */ - MCORE_INLINE float CalcIntensity() const { return r * 0.212671f + g * 0.715160f + b * 0.072169f; } + MCORE_INLINE float CalcIntensity() const { return m_r * 0.212671f + m_g * 0.715160f + m_b * 0.072169f; } /** * Checks if this color is close to another given color. @@ -164,25 +164,25 @@ namespace MCore */ MCORE_INLINE bool CheckIfIsClose(const RGBAColor& col, float distSq = 0.0001f) const { - float cR = (r - col.r); + float cR = (m_r - col.m_r); cR *= cR; if (cR > distSq) { return false; } - float cG = (g - col.g); + float cG = (m_g - col.m_g); cR += cG * cG; if (cR > distSq) { return false; } - float cB = (b - col.b); + float cB = (m_b - col.m_b); cR += cB * cB; if (cR > distSq) { return false; } - float cA = (a - col.a); + float cA = (m_a - col.m_a); cR += cA * cA; return (cR < distSq); } @@ -192,7 +192,7 @@ namespace MCore * In order to work correctly, the color component values must be in range of 0..1. So they have to be clamped, normalized or exposure controlled before calling this method. * @result The 32-bit integer value where each byte is a color component. */ - MCORE_INLINE uint32 ToInt() const { return MCore::RGBA((uint8)(r * 255), (uint8)(g * 255), (uint8)(b * 255), (uint8)(a * 255)); } + MCORE_INLINE uint32 ToInt() const { return MCore::RGBA((uint8)(m_r * 255), (uint8)(m_g * 255), (uint8)(m_b * 255), (uint8)(m_a * 255)); } /** * Perform exposure control on the color components. @@ -202,9 +202,9 @@ namespace MCore */ MCORE_INLINE RGBAColor& Exposure(float exposure = 1.5f) { - r = 1.0f - Math::Exp(-r * exposure); - g = 1.0f - Math::Exp(-g * exposure); - b = 1.0f - Math::Exp(-b * exposure); + m_r = 1.0f - Math::Exp(-m_r * exposure); + m_g = 1.0f - Math::Exp(-m_g * exposure); + m_b = 1.0f - Math::Exp(-m_b * exposure); return *this; } @@ -220,67 +220,67 @@ namespace MCore { float maxVal = 1.0f; - if (r > maxVal) + if (m_r > maxVal) { - maxVal = r; + maxVal = m_r; } - if (g > maxVal) + if (m_g > maxVal) { - maxVal = g; + maxVal = m_g; } - if (b > maxVal) + if (m_b > maxVal) { - maxVal = b; + maxVal = m_b; } float mul = 1.0f / maxVal; - r *= mul; - g *= mul; - b *= mul; + m_r *= mul; + m_g *= mul; + m_b *= mul; return *this; } // operators - MCORE_INLINE bool operator==(const RGBAColor& col) const { return ((r == col.r) && (g == col.g) && (b == col.b) && (a == col.a)); } - MCORE_INLINE const RGBAColor& operator*=(const RGBAColor& col) { r *= col.r; g *= col.g; b *= col.b; a *= col.a; return *this; } - MCORE_INLINE const RGBAColor& operator+=(const RGBAColor& col) { r += col.r; g += col.g; b += col.b; a += col.a; return *this; } - MCORE_INLINE const RGBAColor& operator-=(const RGBAColor& col) { r -= col.r; g -= col.g; b -= col.b; a -= col.a; return *this; } - MCORE_INLINE const RGBAColor& operator*=(float m) { r *= m; g *= m; b *= m; a *= m; return *this; } + MCORE_INLINE bool operator==(const RGBAColor& col) const { return ((m_r == col.m_r) && (m_g == col.m_g) && (m_b == col.m_b) && (m_a == col.m_a)); } + MCORE_INLINE const RGBAColor& operator*=(const RGBAColor& col) { m_r *= col.m_r; m_g *= col.m_g; m_b *= col.m_b; m_a *= col.m_a; return *this; } + MCORE_INLINE const RGBAColor& operator+=(const RGBAColor& col) { m_r += col.m_r; m_g += col.m_g; m_b += col.m_b; m_a += col.m_a; return *this; } + MCORE_INLINE const RGBAColor& operator-=(const RGBAColor& col) { m_r -= col.m_r; m_g -= col.m_g; m_b -= col.m_b; m_a -= col.m_a; return *this; } + MCORE_INLINE const RGBAColor& operator*=(float m) { m_r *= m; m_g *= m; m_b *= m; m_a *= m; return *this; } //MCORE_INLINE const RGBAColor& operator*=(double m) { r*=m; g*=m; b*=m; a*=m; return *this; } - MCORE_INLINE const RGBAColor& operator/=(float d) { float ooD = 1.0f / d; r *= ooD; g *= ooD; b *= ooD; a *= ooD; return *this; } + MCORE_INLINE const RGBAColor& operator/=(float d) { float ooD = 1.0f / d; m_r *= ooD; m_g *= ooD; m_b *= ooD; m_a *= ooD; return *this; } //MCORE_INLINE const RGBAColor& operator/=(double d) { float ooD=1.0f/d; r*=ooD; g*=ooD; b*=ooD; a*=ooD; return *this; } - MCORE_INLINE const RGBAColor& operator= (const RGBAColor& col) { r = col.r; g = col.g; b = col.b; a = col.a; return *this; } - MCORE_INLINE const RGBAColor& operator= (float colorValue) { r = colorValue; g = colorValue; b = colorValue; a = colorValue; return *this; } + MCORE_INLINE const RGBAColor& operator= (const RGBAColor& col) { m_r = col.m_r; m_g = col.m_g; m_b = col.m_b; m_a = col.m_a; return *this; } + MCORE_INLINE const RGBAColor& operator= (float colorValue) { m_r = colorValue; m_g = colorValue; m_b = colorValue; m_a = colorValue; return *this; } - MCORE_INLINE float& operator[](int32 row) { return ((float*)&r)[row]; } - MCORE_INLINE operator float*() { return (float*)&r; } - MCORE_INLINE operator const float*() const { return (const float*)&r; } + MCORE_INLINE float& operator[](int32 row) { return ((float*)&m_r)[row]; } + MCORE_INLINE operator float*() { return (float*)&m_r; } + MCORE_INLINE operator const float*() const { return (const float*)&m_r; } - static uint32 mColorTable[128]; + static uint32 s_colorTable[128]; // attributes - float r; /**< Red component. */ - float g; /**< Green component. */ - float b; /**< Blue component. */ - float a; /**< Alpha component. */ + float m_r; /**< Red component. */ + float m_g; /**< Green component. */ + float m_b; /**< Blue component. */ + float m_a; /**< Alpha component. */ }; /** * Picks a random color from a table of 128 different colors. * @result The generated color. */ - MCORE_INLINE uint32 GenerateColor() { return RGBAColor::mColorTable[rand() % 128]; } + MCORE_INLINE uint32 GenerateColor() { return RGBAColor::s_colorTable[rand() % 128]; } // operators - MCORE_INLINE RGBAColor operator*(const RGBAColor& colA, const RGBAColor& colB) { return RGBAColor(colA.r * colB.r, colA.g * colB.g, colA.b * colB.b, colA.a * colB.a); } - MCORE_INLINE RGBAColor operator+(const RGBAColor& colA, const RGBAColor& colB) { return RGBAColor(colA.r + colB.r, colA.g + colB.g, colA.b + colB.b, colA.a + colB.a); } - MCORE_INLINE RGBAColor operator-(const RGBAColor& colA, const RGBAColor& colB) { return RGBAColor(colA.r - colB.r, colA.g - colB.g, colA.b - colB.b, colA.b - colB.b); } - MCORE_INLINE RGBAColor operator*(const RGBAColor& colA, float m) { return RGBAColor(colA.r * m, colA.g * m, colA.b * m, colA.a * m); } + MCORE_INLINE RGBAColor operator*(const RGBAColor& colA, const RGBAColor& colB) { return RGBAColor(colA.m_r * colB.m_r, colA.m_g * colB.m_g, colA.m_b * colB.m_b, colA.m_a * colB.m_a); } + MCORE_INLINE RGBAColor operator+(const RGBAColor& colA, const RGBAColor& colB) { return RGBAColor(colA.m_r + colB.m_r, colA.m_g + colB.m_g, colA.m_b + colB.m_b, colA.m_a + colB.m_a); } + MCORE_INLINE RGBAColor operator-(const RGBAColor& colA, const RGBAColor& colB) { return RGBAColor(colA.m_r - colB.m_r, colA.m_g - colB.m_g, colA.m_b - colB.m_b, colA.m_b - colB.m_b); } + MCORE_INLINE RGBAColor operator*(const RGBAColor& colA, float m) { return RGBAColor(colA.m_r * m, colA.m_g * m, colA.m_b * m, colA.m_a * m); } //MCORE_INLINE RGBAColor operator*(const RGBAColor& colA, double m) { return RGBAColor(colA.r*m, colA.g*m, colA.b*m, colA.a*m); } - MCORE_INLINE RGBAColor operator*(float m, const RGBAColor& colB) { return RGBAColor(m * colB.r, m * colB.g, m * colB.b, m * colB.a); } + MCORE_INLINE RGBAColor operator*(float m, const RGBAColor& colB) { return RGBAColor(m * colB.m_r, m * colB.m_g, m * colB.m_b, m * colB.m_a); } //MCORE_INLINE RGBAColor operator*(double m, const RGBAColor& colB) { return RGBAColor(m*colB.r, m*colB.g, m*colB.b, m*colB.a); } - MCORE_INLINE RGBAColor operator/(const RGBAColor& colA, float d) { float ooD = 1.0f / d; return RGBAColor(colA.r * ooD, colA.g * ooD, colA.b * ooD, colA.a * ooD); } + MCORE_INLINE RGBAColor operator/(const RGBAColor& colA, float d) { float ooD = 1.0f / d; return RGBAColor(colA.m_r * ooD, colA.m_g * ooD, colA.m_b * ooD, colA.m_a * ooD); } //MCORE_INLINE RGBAColor operator/(const RGBAColor& colA, double d) { float ooD=1.0f/d; return RGBAColor(colA.r*ooD, colA.g*ooD, colA.b*ooD, colA.a*ooD); } } // namespace MCore diff --git a/Gems/EMotionFX/Code/MCore/Source/Command.cpp b/Gems/EMotionFX/Code/MCore/Source/Command.cpp index 8845e7c278..d53477b1e1 100644 --- a/Gems/EMotionFX/Code/MCore/Source/Command.cpp +++ b/Gems/EMotionFX/Code/MCore/Source/Command.cpp @@ -17,8 +17,8 @@ namespace MCore // constructor Command::Callback::Callback(bool executePreUndo, bool executePreCommand) { - mPreUndoExecute = executePreUndo; - mPreCommandExecute = executePreCommand; + m_preUndoExecute = executePreUndo; + m_preCommandExecute = executePreCommand; } @@ -30,8 +30,8 @@ namespace MCore // constructor Command::Command(AZStd::string commandName, Command* originalCommand) - : mOrgCommand(originalCommand) - , mCommandName(AZStd::move(commandName)) + : m_orgCommand(originalCommand) + , m_commandName(AZStd::move(commandName)) { } @@ -59,13 +59,13 @@ namespace MCore const char* Command::GetName() const { - return mCommandName.c_str(); + return m_commandName.c_str(); } const AZStd::string& Command::GetNameString() const { - return mCommandName; + return m_commandName; } @@ -84,25 +84,25 @@ namespace MCore size_t Command::GetNumCallbacks() const { - return mCallbacks.size(); + return m_callbacks.size(); } void Command::AddCallback(Command::Callback* callback) { - mCallbacks.push_back(callback); + m_callbacks.push_back(callback); } bool Command::CheckIfHasCallback(Command::Callback* callback) const { - return (AZStd::find(mCallbacks.begin(), mCallbacks.end(), callback) != mCallbacks.end()); + return (AZStd::find(m_callbacks.begin(), m_callbacks.end(), callback) != m_callbacks.end()); } void Command::RemoveCallback(Command::Callback* callback, bool delFromMem) { - mCallbacks.erase(AZStd::remove(mCallbacks.begin(), mCallbacks.end(), callback), mCallbacks.end()); + m_callbacks.erase(AZStd::remove(m_callbacks.begin(), m_callbacks.end(), callback), m_callbacks.end()); if (delFromMem) { delete callback; @@ -112,21 +112,21 @@ namespace MCore void Command::RemoveAllCallbacks() { - const size_t numCallbacks = mCallbacks.size(); + const size_t numCallbacks = m_callbacks.size(); for (size_t i = 0; i < numCallbacks; ++i) { // If it crashes here, you probably created your callback in another dll and didn't remove it from memory there as well. - delete mCallbacks[i]; + delete m_callbacks[i]; } - mCallbacks.clear(); + m_callbacks.clear(); } // calculate the number of registered pre-execute callbacks size_t Command::CalcNumPreCommandCallbacks() const { - return AZStd::accumulate(begin(mCallbacks), end(mCallbacks), size_t{0}, [](size_t total, const Callback* callback) + return AZStd::accumulate(begin(m_callbacks), end(m_callbacks), size_t{0}, [](size_t total, const Callback* callback) { return callback->GetExecutePreCommand() ? total + 1 : total; }); @@ -136,6 +136,6 @@ namespace MCore // calculate the number of registered post-execute callbacks size_t Command::CalcNumPostCommandCallbacks() const { - return mCallbacks.size() - CalcNumPreCommandCallbacks(); + return m_callbacks.size() - CalcNumPreCommandCallbacks(); } } // namespace MCore diff --git a/Gems/EMotionFX/Code/MCore/Source/Command.h b/Gems/EMotionFX/Code/MCore/Source/Command.h index d6bfb3a0d7..615156223d 100644 --- a/Gems/EMotionFX/Code/MCore/Source/Command.h +++ b/Gems/EMotionFX/Code/MCore/Source/Command.h @@ -68,9 +68,9 @@ namespace MCore const char* GetHistoryName() const { return HISTORYNAME; } \ const char* GetDescription() const; \ MCore::Command* Create() { return new CLASSNAME(this); } \ - OLDVALUETYPE& GetData() { return mData; } \ + OLDVALUETYPE& GetData() { return m_data; } \ protected: \ - OLDVALUETYPE mData; \ + OLDVALUETYPE m_data; \ #define MCORE_DEFINECOMMAND_1_END }; @@ -167,17 +167,17 @@ namespace MCore * Get the flag which controls if the callback gets executed before the command or after it. * @return True in case the callback gets called before the command, false when it gets called afterwards. */ - MCORE_INLINE bool GetExecutePreCommand() const { return mPreCommandExecute; } + MCORE_INLINE bool GetExecutePreCommand() const { return m_preCommandExecute; } /** * Get the flag which controls if the callback gets executed before undo or after it. * @return True in case the callback gets called before undo, false when it gets called afterwards. */ - MCORE_INLINE bool GetExecutePreUndo() const { return mPreUndoExecute; } + MCORE_INLINE bool GetExecutePreUndo() const { return m_preUndoExecute; } private: - bool mPreCommandExecute; /**< Flag which controls if the callback gets executed before the command (true) or after it (false). */ - bool mPreUndoExecute; /**< Flag which controls if the callback gets executed before the undo (true) or after it (false). */ + bool m_preCommandExecute; /**< Flag which controls if the callback gets executed before the command (true) or after it (false). */ + bool m_preUndoExecute; /**< Flag which controls if the callback gets executed before the undo (true) or after it (false). */ }; /** @@ -273,7 +273,7 @@ namespace MCore * Also it can verify and show info about these parameters. * @result The syntax object. */ - MCORE_INLINE CommandSyntax& GetSyntax() { return mSyntax; } + MCORE_INLINE CommandSyntax& GetSyntax() { return m_syntax; } /** * Get the number of registered/added command callbacks. @@ -298,7 +298,7 @@ namespace MCore * @param index The callback number, which must be in range of [0..GetNumCallbacks()-1]. * @result A pointer to the command callback object. */ - MCORE_INLINE Command::Callback* GetCallback(size_t index) { return mCallbacks[index]; } + MCORE_INLINE Command::Callback* GetCallback(size_t index) { return m_callbacks[index]; } /** * Add (register) a command callback. @@ -325,7 +325,7 @@ namespace MCore */ void RemoveAllCallbacks(); - void SetOriginalCommand(Command* orgCommand) { mOrgCommand = orgCommand; } + void SetOriginalCommand(Command* orgCommand) { m_orgCommand = orgCommand; } /** * Get the original command where this command has been cloned from. @@ -335,9 +335,9 @@ namespace MCore */ MCORE_INLINE Command* GetOriginalCommand() { - if (mOrgCommand) + if (m_orgCommand) { - return mOrgCommand; + return m_orgCommand; } else { @@ -359,9 +359,9 @@ namespace MCore } private: - Command* mOrgCommand; /**< The original command, or nullptr when this is the original. */ - AZStd::string mCommandName; /**< The unique command name used to identify the command. */ - CommandSyntax mSyntax; /**< The command syntax, which contains info about the possible parameters etc. */ - AZStd::vector mCallbacks; /**< The command callbacks. */ + Command* m_orgCommand; /**< The original command, or nullptr when this is the original. */ + AZStd::string m_commandName; /**< The unique command name used to identify the command. */ + CommandSyntax m_syntax; /**< The command syntax, which contains info about the possible parameters etc. */ + AZStd::vector m_callbacks; /**< The command callbacks. */ }; } // namespace MCore diff --git a/Gems/EMotionFX/Code/MCore/Source/CommandGroup.cpp b/Gems/EMotionFX/Code/MCore/Source/CommandGroup.cpp index e69b91278d..e12b2b5ed8 100644 --- a/Gems/EMotionFX/Code/MCore/Source/CommandGroup.cpp +++ b/Gems/EMotionFX/Code/MCore/Source/CommandGroup.cpp @@ -35,144 +35,144 @@ namespace MCore { if (numToReserve > 0) { - mCommands.reserve(numToReserve); + m_commands.reserve(numToReserve); } } void CommandGroup::AddCommandString(const char* commandString) { - mCommands.emplace_back(CommandEntry()); - mCommands.back().mCommandString = commandString; + m_commands.emplace_back(CommandEntry()); + m_commands.back().m_commandString = commandString; } void CommandGroup::AddCommandString(const AZStd::string& commandString) { - mCommands.emplace_back(CommandEntry()); - mCommands.back().mCommandString = commandString; + m_commands.emplace_back(CommandEntry()); + m_commands.back().m_commandString = commandString; } void CommandGroup::AddCommand(MCore::Command* command) { - mCommands.emplace_back(CommandEntry()); - mCommands.back().mCommand = command; + m_commands.emplace_back(CommandEntry()); + m_commands.back().m_command = command; } const char* CommandGroup::GetCommandString(size_t index) const { - return mCommands[index].mCommandString.c_str(); + return m_commands[index].m_commandString.c_str(); } const AZStd::string& CommandGroup::GetCommandStringAsString(size_t index) const { - return mCommands[index].mCommandString; + return m_commands[index].m_commandString; } Command* CommandGroup::GetCommand(size_t index) { - return mCommands[index].mCommand; + return m_commands[index].m_command; } const CommandLine& CommandGroup::GetParameters(size_t index) const { - return mCommands[index].mCommandLine; + return m_commands[index].m_commandLine; } const char* CommandGroup::GetGroupName() const { - return mGroupName.c_str(); + return m_groupName.c_str(); } const AZStd::string& CommandGroup::GetGroupNameString() const { - return mGroupName; + return m_groupName; } void CommandGroup::SetGroupName(const char* groupName) { - mGroupName = groupName; + m_groupName = groupName; } void CommandGroup::SetGroupName(const AZStd::string& groupName) { - mGroupName = groupName; + m_groupName = groupName; } void CommandGroup::SetCommandString(size_t index, const char* commandString) { - mCommands[index].mCommandString = commandString; + m_commands[index].m_commandString = commandString; } void CommandGroup::SetParameters(size_t index, const CommandLine& params) { - mCommands[index].mCommandLine = params; + m_commands[index].m_commandLine = params; } void CommandGroup::SetCommand(size_t index, Command* command) { - mCommands[index].mCommand = command; + m_commands[index].m_command = command; } size_t CommandGroup::GetNumCommands() const { - return mCommands.size(); + return m_commands.size(); } void CommandGroup::RemoveAllCommands(bool delFromMem) { if (delFromMem) { - for (CommandEntry& commandEntry : mCommands) + for (CommandEntry& commandEntry : m_commands) { - delete commandEntry.mCommand; + delete commandEntry.m_command; } } - mCommands.clear(); + m_commands.clear(); } CommandGroup* CommandGroup::Clone() const { - CommandGroup* newGroup = new CommandGroup(mGroupName, 0); - newGroup->mCommands = mCommands; - newGroup->mHistoryAfterError = mHistoryAfterError; - newGroup->mContinueAfterError = mContinueAfterError; - newGroup->mReturnFalseAfterError = mReturnFalseAfterError; + CommandGroup* newGroup = new CommandGroup(m_groupName, 0); + newGroup->m_commands = m_commands; + newGroup->m_historyAfterError = m_historyAfterError; + newGroup->m_continueAfterError = m_continueAfterError; + newGroup->m_returnFalseAfterError = m_returnFalseAfterError; return newGroup; } // continue execution of the remaining commands after one fails to execute? void CommandGroup::SetContinueAfterError(bool continueAfter) { - mContinueAfterError = continueAfter; + m_continueAfterError = continueAfter; } // add group to the history even when one internal command failed to execute? void CommandGroup::SetAddToHistoryAfterError(bool addAfterError) { - mHistoryAfterError = addAfterError; + m_historyAfterError = addAfterError; } // check to see if we continue executing internal commands even if one failed bool CommandGroup::GetContinueAfterError() const { - return mContinueAfterError; + return m_continueAfterError; } // check if we add this group to the history, even if one internal command failed bool CommandGroup::GetAddToHistoryAfterError() const { - return mHistoryAfterError; + return m_historyAfterError; } // set if the command group shall return false after an error occurred or not void CommandGroup::SetReturnFalseAfterError(bool returnAfterError) { - mReturnFalseAfterError = returnAfterError; + m_returnFalseAfterError = returnAfterError; } // returns true in case the group returns false when executing it bool CommandGroup::GetReturnFalseAfterError() const { - return mReturnFalseAfterError; + return m_returnFalseAfterError; } } // namespace MCore diff --git a/Gems/EMotionFX/Code/MCore/Source/CommandGroup.h b/Gems/EMotionFX/Code/MCore/Source/CommandGroup.h index 5a4ef0a201..0d7b8683b1 100644 --- a/Gems/EMotionFX/Code/MCore/Source/CommandGroup.h +++ b/Gems/EMotionFX/Code/MCore/Source/CommandGroup.h @@ -219,15 +219,15 @@ namespace MCore */ struct MCORE_API CommandEntry { - MCore::Command* mCommand = nullptr; /**< The command object, which gets set when you execute the group inside the command manager. */ - MCore::CommandLine mCommandLine{}; /**< The command line that was used when executing this command. */ - AZStd::string mCommandString{}; /**< The command string that we will execute. */ + MCore::Command* m_command = nullptr; /**< The command object, which gets set when you execute the group inside the command manager. */ + MCore::CommandLine m_commandLine{}; /**< The command line that was used when executing this command. */ + AZStd::string m_commandString{}; /**< The command string that we will execute. */ }; - AZStd::vector mCommands; /**< The set of commands inside the group. */ - AZStd::string mGroupName; /**< The name of the group as it will appear inside the command history. */ - bool mContinueAfterError; /**< */ - bool mHistoryAfterError; /**< */ - bool mReturnFalseAfterError; + AZStd::vector m_commands; /**< The set of commands inside the group. */ + AZStd::string m_groupName; /**< The name of the group as it will appear inside the command history. */ + bool m_continueAfterError; /**< */ + bool m_historyAfterError; /**< */ + bool m_returnFalseAfterError; }; } // namespace MCore diff --git a/Gems/EMotionFX/Code/MCore/Source/CommandLine.cpp b/Gems/EMotionFX/Code/MCore/Source/CommandLine.cpp index ae536101e6..a55d066cdc 100644 --- a/Gems/EMotionFX/Code/MCore/Source/CommandLine.cpp +++ b/Gems/EMotionFX/Code/MCore/Source/CommandLine.cpp @@ -34,14 +34,14 @@ namespace MCore } // return the default value if the parameter value is empty - if (m_parameters[paramIndex].mValue.empty()) + if (m_parameters[paramIndex].m_value.empty()) { *outResult = defaultValue; return; } // return the parameter value - *outResult = m_parameters[paramIndex].mValue; + *outResult = m_parameters[paramIndex].m_value; } @@ -57,14 +57,14 @@ namespace MCore } // Return the default value if the parameter value is empty. - if (m_parameters[paramIndex].mValue.empty()) + if (m_parameters[paramIndex].m_value.empty()) { outResult = defaultValue; return; } // Return the actual parameter value. - outResult = m_parameters[paramIndex].mValue.c_str(); + outResult = m_parameters[paramIndex].m_value.c_str(); } @@ -79,13 +79,13 @@ namespace MCore } // return the default value if the parameter value is empty - if (m_parameters[paramIndex].mValue.empty()) + if (m_parameters[paramIndex].m_value.empty()) { return defaultValue; } // return the parameter value - return AzFramework::StringFunc::ToInt(m_parameters[paramIndex].mValue.c_str()); + return AzFramework::StringFunc::ToInt(m_parameters[paramIndex].m_value.c_str()); } @@ -100,13 +100,13 @@ namespace MCore } // return the default value if the parameter value is empty - if (m_parameters[paramIndex].mValue.empty()) + if (m_parameters[paramIndex].m_value.empty()) { return defaultValue; } // return the parameter value - return AzFramework::StringFunc::ToFloat(m_parameters[paramIndex].mValue.c_str()); + return AzFramework::StringFunc::ToFloat(m_parameters[paramIndex].m_value.c_str()); } @@ -121,13 +121,13 @@ namespace MCore } // return the default value if the parameter value is empty - if (m_parameters[paramIndex].mValue.empty()) + if (m_parameters[paramIndex].m_value.empty()) { return true; } // return the parameter value - return AzFramework::StringFunc::ToBool(m_parameters[paramIndex].mValue.c_str()); + return AzFramework::StringFunc::ToBool(m_parameters[paramIndex].m_value.c_str()); } @@ -142,14 +142,14 @@ namespace MCore } // return the default value if the parameter value is empty - if (m_parameters[paramIndex].mValue.empty()) + if (m_parameters[paramIndex].m_value.empty()) { return defaultValue; } // return the parameter value - return AzFramework::StringFunc::ToVector3(m_parameters[paramIndex].mValue.c_str()); + return AzFramework::StringFunc::ToVector3(m_parameters[paramIndex].m_value.c_str()); } @@ -164,13 +164,13 @@ namespace MCore } // return the default value if the parameter value is empty - if (m_parameters[paramIndex].mValue.empty()) + if (m_parameters[paramIndex].m_value.empty()) { return defaultValue; } // return the parameter value - return AzFramework::StringFunc::ToVector4(m_parameters[paramIndex].mValue.c_str()); + return AzFramework::StringFunc::ToVector4(m_parameters[paramIndex].m_value.c_str()); } @@ -186,7 +186,7 @@ namespace MCore } // return the parameter value - *outResult = m_parameters[paramIndex].mValue; + *outResult = m_parameters[paramIndex].m_value; } @@ -201,7 +201,7 @@ namespace MCore const size_t paramIndex = FindParameterIndex(paramName); if (paramIndex != InvalidIndex) { - return AZ::Success(m_parameters[paramIndex].mValue); + return AZ::Success(m_parameters[paramIndex].m_value); } return AZ::Failure(); @@ -218,7 +218,7 @@ namespace MCore } // return the parameter value - return m_parameters[paramIndex].mValue; + return m_parameters[paramIndex].m_value; } @@ -241,7 +241,7 @@ namespace MCore } // return the parameter value - return AzFramework::StringFunc::ToInt(m_parameters[paramIndex].mValue.c_str()); + return AzFramework::StringFunc::ToInt(m_parameters[paramIndex].m_value.c_str()); } // get the value as float @@ -263,7 +263,7 @@ namespace MCore } // return the parameter value - return AzFramework::StringFunc::ToFloat(m_parameters[paramIndex].mValue.c_str()); + return AzFramework::StringFunc::ToFloat(m_parameters[paramIndex].m_value.c_str()); } @@ -286,7 +286,7 @@ namespace MCore } // return the parameter value - return AzFramework::StringFunc::ToBool(m_parameters[paramIndex].mValue.c_str()); + return AzFramework::StringFunc::ToBool(m_parameters[paramIndex].m_value.c_str()); } @@ -309,7 +309,7 @@ namespace MCore } // return the parameter value - return AzFramework::StringFunc::ToVector3(m_parameters[paramIndex].mValue.c_str()); + return AzFramework::StringFunc::ToVector3(m_parameters[paramIndex].m_value.c_str()); } @@ -332,7 +332,7 @@ namespace MCore } // return the parameter value - return AzFramework::StringFunc::ToVector4(m_parameters[paramIndex].mValue.c_str()); + return AzFramework::StringFunc::ToVector4(m_parameters[paramIndex].m_value.c_str()); } @@ -346,14 +346,14 @@ namespace MCore // get the parameter name for a given parameter const AZStd::string& CommandLine::GetParameterName(size_t nr) const { - return m_parameters[nr].mName; + return m_parameters[nr].m_name; } // get the parameter value for a given parameter number const AZStd::string& CommandLine::GetParameterValue(size_t nr) const { - return m_parameters[nr].mValue; + return m_parameters[nr].m_value; } @@ -368,7 +368,7 @@ namespace MCore } // return true the parameter has a value that is not empty - return (m_parameters[paramIndex].mValue.empty() == false); + return (m_parameters[paramIndex].m_value.empty() == false); } @@ -378,7 +378,7 @@ namespace MCore // compare all parameter names on a non-case sensitive way const auto foundParameter = AZStd::find_if(begin(m_parameters), end(m_parameters), [paramName](const Parameter& parameter) { - return AzFramework::StringFunc::Equal(parameter.mName, paramName, false /* no case */); + return AzFramework::StringFunc::Equal(parameter.m_name, paramName, false /* no case */); }); return foundParameter != end(m_parameters) ? AZStd::distance(begin(m_parameters), foundParameter) : InvalidIndex; @@ -542,7 +542,7 @@ namespace MCore LogInfo("Command line '%s' has %d parameters", debugName, numParameters); for (size_t i = 0; i < numParameters; ++i) { - LogInfo("Param %d (name='%s' value='%s'", i, m_parameters[i].mName.c_str(), m_parameters[i].mValue.c_str()); + LogInfo("Param %d (name='%s' value='%s'", i, m_parameters[i].m_name.c_str(), m_parameters[i].m_value.c_str()); } } } // namespace MCore diff --git a/Gems/EMotionFX/Code/MCore/Source/CommandLine.h b/Gems/EMotionFX/Code/MCore/Source/CommandLine.h index 8a4e5172e8..07b22ce9e5 100644 --- a/Gems/EMotionFX/Code/MCore/Source/CommandLine.h +++ b/Gems/EMotionFX/Code/MCore/Source/CommandLine.h @@ -271,8 +271,8 @@ namespace MCore */ struct MCORE_API Parameter { - AZStd::string mName; /**< The parameter name, for example "XRES". */ - AZStd::string mValue; /**< The parameter value, for example "1024". */ + AZStd::string m_name; /**< The parameter name, for example "XRES". */ + AZStd::string m_value; /**< The parameter value, for example "1024". */ }; AZStd::vector m_parameters; /**< The parameters that have been detected in the command line string. */ diff --git a/Gems/EMotionFX/Code/MCore/Source/CommandSyntax.cpp b/Gems/EMotionFX/Code/MCore/Source/CommandSyntax.cpp index fb10da4eb4..0bc228898c 100644 --- a/Gems/EMotionFX/Code/MCore/Source/CommandSyntax.cpp +++ b/Gems/EMotionFX/Code/MCore/Source/CommandSyntax.cpp @@ -68,21 +68,21 @@ namespace MCore // check if this param is a required one or not bool CommandSyntax::GetParamRequired(size_t index) const { - return m_parameters[index].mRequired; + return m_parameters[index].m_required; } // get the parameter name const char* CommandSyntax::GetParamName(size_t index) const { - return m_parameters[index].mName.c_str(); + return m_parameters[index].m_name.c_str(); } // get the parameter description const char* CommandSyntax::GetParamDescription(size_t index) const { - return m_parameters[index].mDescription.c_str(); + return m_parameters[index].m_description.c_str(); } @@ -95,7 +95,7 @@ namespace MCore const char* CommandSyntax::GetParamTypeString(const Parameter& parameter) const { // check the type - switch (parameter.mParamType) + switch (parameter.m_paramType) { case PARAMTYPE_STRING: return "String"; @@ -129,7 +129,7 @@ namespace MCore // get the parameter type CommandSyntax::EParamType CommandSyntax::GetParamType(size_t index) const { - return m_parameters[index].mParamType; + return m_parameters[index].m_paramType; } @@ -145,7 +145,7 @@ namespace MCore { const auto foundParameter = AZStd::find_if(begin(m_parameters), end(m_parameters), [parameter](const Parameter& p) { - return AzFramework::StringFunc::Equal(p.mName, parameter, false /* no case */); + return AzFramework::StringFunc::Equal(p.m_name, parameter, false /* no case */); }); return foundParameter != end(m_parameters) ? AZStd::distance(begin(m_parameters), foundParameter) : InvalidIndex; } @@ -154,7 +154,7 @@ namespace MCore // get the default value for a given parameter const AZStd::string& CommandSyntax::GetDefaultValue(size_t index) const { - return m_parameters[index].mDefaultValue; + return m_parameters[index].m_defaultValue; } @@ -163,7 +163,7 @@ namespace MCore const size_t index = FindParameterIndex(paramName); if (index != InvalidIndex) { - return m_parameters[index].mDefaultValue; + return m_parameters[index].m_defaultValue; } static const AZStd::string empty; @@ -180,7 +180,7 @@ namespace MCore return false; } - outDefaultValue = m_parameters[index].mDefaultValue; + outDefaultValue = m_parameters[index].m_defaultValue; return true; } @@ -203,28 +203,28 @@ namespace MCore for (const Parameter& parameter : m_parameters) { // if the required parameter hasn't been specified - if (parameter.mRequired && commandLine.CheckIfHasParameter(parameter.mName) == false) + if (parameter.m_required && commandLine.CheckIfHasParameter(parameter.m_name) == false) { - outResult += AZStd::string::format("Required parameter '%s' has not been specified.\n", parameter.mName.c_str()); + outResult += AZStd::string::format("Required parameter '%s' has not been specified.\n", parameter.m_name.c_str()); } else { // find the parameter index - const size_t paramIndex = commandLine.FindParameterIndex(parameter.mName.c_str()); + const size_t paramIndex = commandLine.FindParameterIndex(parameter.m_name.c_str()); if (paramIndex != InvalidIndex) { const AZStd::string& value = commandLine.GetParameterValue(paramIndex); - const AZStd::string& paramName = parameter.mName; + const AZStd::string& paramName = parameter.m_name; // if the parameter value has not been specified and it is not a boolean parameter - if ((value.empty()) && parameter.mParamType != PARAMTYPE_BOOLEAN && parameter.mParamType != PARAMTYPE_STRING) + if ((value.empty()) && parameter.m_paramType != PARAMTYPE_BOOLEAN && parameter.m_paramType != PARAMTYPE_STRING) { outResult += AZStd::string::format("Parameter '%s' has no value specified.\n", paramName.c_str()); } else { // check if we specified a valid int - if (parameter.mParamType == PARAMTYPE_INT) + if (parameter.m_paramType == PARAMTYPE_INT) { if (!AzFramework::StringFunc::LooksLikeInt(value.c_str())) { @@ -233,7 +233,7 @@ namespace MCore } // check if the specified float is valid - if (parameter.mParamType == PARAMTYPE_FLOAT) + if (parameter.m_paramType == PARAMTYPE_FLOAT) { if (!AzFramework::StringFunc::LooksLikeFloat(value.c_str())) { @@ -242,7 +242,7 @@ namespace MCore } // check if this is a valid boolean - if (parameter.mParamType == PARAMTYPE_BOOLEAN) + if (parameter.m_paramType == PARAMTYPE_BOOLEAN) { if (!value.empty() && !AzFramework::StringFunc::LooksLikeBool(value.c_str())) { @@ -251,7 +251,7 @@ namespace MCore } // check if this is a valid boolean - if (parameter.mParamType == PARAMTYPE_CHAR) + if (parameter.m_paramType == PARAMTYPE_CHAR) { if (value.size() > 1) { @@ -260,7 +260,7 @@ namespace MCore } // check if the specified vector3 is valid - if (parameter.mParamType == PARAMTYPE_VECTOR3) + if (parameter.m_paramType == PARAMTYPE_VECTOR3) { if (!AzFramework::StringFunc::LooksLikeVector3(value.c_str())) { @@ -269,7 +269,7 @@ namespace MCore } // check if the specified vector3 is valid - if (parameter.mParamType == PARAMTYPE_VECTOR4) + if (parameter.m_paramType == PARAMTYPE_VECTOR4) { if (!AzFramework::StringFunc::LooksLikeVector4(value.c_str())) { @@ -302,8 +302,8 @@ namespace MCore // find the longest command name size_t offset = AZStd::minmax_element(begin(m_parameters), end(m_parameters), [](const Parameter& left, const Parameter& right) { - return left.mName.size() < right.mName.size(); - }).second->mName.size(); + return left.m_name.size() < right.m_name.size(); + }).second->m_name.size(); size_t offset2 = offset; size_t offset3 = offset; @@ -330,19 +330,19 @@ namespace MCore for (const Parameter& parameter : m_parameters) { offset2 = offset3; - final = parameter.mName; + final = parameter.m_name; offset2 += 5; final.append(offset2 - final.size(), MCore::CharacterConstants::space); final += GetParamTypeString(parameter); offset2 += 15; final.append(offset2 - final.size(), MCore::CharacterConstants::space); - final += parameter.mRequired ? "Yes" : "No"; + final += parameter.m_required ? "Yes" : "No"; offset2 += 10; final.append(offset2 - final.size(), MCore::CharacterConstants::space); - final += parameter.mDefaultValue; + final += parameter.m_defaultValue; offset2 += 20; final.append(offset2 - final.size(), MCore::CharacterConstants::space); - final += parameter.mDescription; + final += parameter.m_description; MCore::LogInfo(final.c_str()); } diff --git a/Gems/EMotionFX/Code/MCore/Source/CommandSyntax.h b/Gems/EMotionFX/Code/MCore/Source/CommandSyntax.h index 730dd9047a..ded4c1ee02 100644 --- a/Gems/EMotionFX/Code/MCore/Source/CommandSyntax.h +++ b/Gems/EMotionFX/Code/MCore/Source/CommandSyntax.h @@ -47,15 +47,15 @@ namespace MCore struct MCORE_API Parameter { Parameter(AZStd::string name, AZStd::string description, AZStd::string defaultValue, EParamType paramType, bool required) - : mName(AZStd::move(name)), mDescription(AZStd::move(description)), mDefaultValue(AZStd::move(defaultValue)), mParamType(paramType), mRequired(required) + : m_name(AZStd::move(name)), m_description(AZStd::move(description)), m_defaultValue(AZStd::move(defaultValue)), m_paramType(paramType), m_required(required) { } - AZStd::string mName; /**< The name of the parameter. */ - AZStd::string mDescription; /**< The description of the parameter. */ - AZStd::string mDefaultValue; /**< The default value. */ - EParamType mParamType; /**< The parameter type. */ - bool mRequired; /**< Is this parameter required or optional? */ + AZStd::string m_name; /**< The name of the parameter. */ + AZStd::string m_description; /**< The description of the parameter. */ + AZStd::string m_defaultValue; /**< The default value. */ + EParamType m_paramType; /**< The parameter type. */ + bool m_required; /**< Is this parameter required or optional? */ }; public: diff --git a/Gems/EMotionFX/Code/MCore/Source/CompressedFloat.h b/Gems/EMotionFX/Code/MCore/Source/CompressedFloat.h index 0ad5d2c5fd..99ef631e39 100644 --- a/Gems/EMotionFX/Code/MCore/Source/CompressedFloat.h +++ b/Gems/EMotionFX/Code/MCore/Source/CompressedFloat.h @@ -82,7 +82,7 @@ namespace MCore MCORE_INLINE float ToFloat(float minValue, float maxValue) const; public: - StorageType mValue; /**< The compressed/packed value. */ + StorageType m_value; /**< The compressed/packed value. */ // the number of steps within the specified range enum diff --git a/Gems/EMotionFX/Code/MCore/Source/CompressedFloat.inl b/Gems/EMotionFX/Code/MCore/Source/CompressedFloat.inl index 54bb5ec3ea..61b971b2aa 100644 --- a/Gems/EMotionFX/Code/MCore/Source/CompressedFloat.inl +++ b/Gems/EMotionFX/Code/MCore/Source/CompressedFloat.inl @@ -19,7 +19,7 @@ MCORE_INLINE TCompressedFloat::TCompressedFloat(float value, float { // TODO: make sure due to rounding/floating point errors the result is not negative? const StorageType f = (1.0f / (maxValue - minValue)) * CONVERT_VALUE; - mValue = (value - minValue) * f; + m_value = (value - minValue) * f; } @@ -27,7 +27,7 @@ MCORE_INLINE TCompressedFloat::TCompressedFloat(float value, float template MCORE_INLINE TCompressedFloat::TCompressedFloat(StorageType value) { - mValue = value; + m_value = value; } @@ -37,7 +37,7 @@ MCORE_INLINE void TCompressedFloat::FromFloat(float value, float mi { // TODO: make sure due to rounding/floating point errors the result is not negative? const StorageType f = (StorageType)(1.0f / (maxValue - minValue)) * CONVERT_VALUE; - mValue = (StorageType)((value - minValue) * f); + m_value = (StorageType)((value - minValue) * f); } @@ -47,7 +47,7 @@ MCORE_INLINE void TCompressedFloat::UnCompress(float* output, float { // unpack and normalize const float f = (1.0f / (float)CONVERT_VALUE) * (maxValue - minValue); - *output = ((float)mValue * f) + minValue; + *output = ((float)m_value * f) + minValue; } @@ -56,5 +56,5 @@ template MCORE_INLINE float TCompressedFloat::ToFloat(float minValue, float maxValue) const { const float f = (1.0f / (float)CONVERT_VALUE) * (maxValue - minValue); - return ((mValue * f) + minValue); + return ((m_value * f) + minValue); } diff --git a/Gems/EMotionFX/Code/MCore/Source/CompressedQuaternion.h b/Gems/EMotionFX/Code/MCore/Source/CompressedQuaternion.h index ce3304dd8f..0b25283410 100644 --- a/Gems/EMotionFX/Code/MCore/Source/CompressedQuaternion.h +++ b/Gems/EMotionFX/Code/MCore/Source/CompressedQuaternion.h @@ -73,7 +73,7 @@ namespace MCore AZ_INLINE operator AZ::Quaternion() const { return ToQuaternion(); } public: - StorageType mX, mY, mZ, mW; /**< The compressed/packed quaternion components values. */ + StorageType m_x, m_y, m_z, m_w; /**< The compressed/packed quaternion components values. */ // the number of steps within the specified range enum diff --git a/Gems/EMotionFX/Code/MCore/Source/CompressedQuaternion.inl b/Gems/EMotionFX/Code/MCore/Source/CompressedQuaternion.inl index 4dc1c2d867..2f8499b6ba 100644 --- a/Gems/EMotionFX/Code/MCore/Source/CompressedQuaternion.inl +++ b/Gems/EMotionFX/Code/MCore/Source/CompressedQuaternion.inl @@ -9,10 +9,10 @@ // constructor template MCORE_INLINE TCompressedQuaternion::TCompressedQuaternion() - : mX(0) - , mY(0) - , mZ(0) - , mW(CONVERT_VALUE) + : m_x(0) + , m_y(0) + , m_z(0) + , m_w(CONVERT_VALUE) { } @@ -20,10 +20,10 @@ MCORE_INLINE TCompressedQuaternion::TCompressedQuaternion() // constructor template MCORE_INLINE TCompressedQuaternion::TCompressedQuaternion(float xVal, float yVal, float zVal, float wVal) - : mX((StorageType)xVal) - , mY((StorageType)yVal) - , mZ((StorageType)zVal) - , mW((StorageType)wVal) + : m_x((StorageType)xVal) + , m_y((StorageType)yVal) + , m_z((StorageType)zVal) + , m_w((StorageType)wVal) { } @@ -31,10 +31,10 @@ MCORE_INLINE TCompressedQuaternion::TCompressedQuaternion(float xVa // constructor template MCORE_INLINE TCompressedQuaternion::TCompressedQuaternion(const AZ::Quaternion& quat) - : mX((StorageType)(static_cast(quat.GetX()) * CONVERT_VALUE)) - , mY((StorageType)(static_cast(quat.GetY()) * CONVERT_VALUE)) - , mZ((StorageType)(static_cast(quat.GetZ()) * CONVERT_VALUE)) - , mW((StorageType)(static_cast(quat.GetW()) * CONVERT_VALUE)) + : m_x((StorageType)(static_cast(quat.GetX()) * CONVERT_VALUE)) + , m_y((StorageType)(static_cast(quat.GetY()) * CONVERT_VALUE)) + , m_z((StorageType)(static_cast(quat.GetZ()) * CONVERT_VALUE)) + , m_w((StorageType)(static_cast(quat.GetW()) * CONVERT_VALUE)) { } @@ -44,10 +44,10 @@ template MCORE_INLINE void TCompressedQuaternion::FromQuaternion(const AZ::Quaternion& quat) { // pack it - mX = (StorageType)(static_cast(quat.GetX()) * CONVERT_VALUE); - mY = (StorageType)(static_cast(quat.GetY()) * CONVERT_VALUE); - mZ = (StorageType)(static_cast(quat.GetZ()) * CONVERT_VALUE); - mW = (StorageType)(static_cast(quat.GetW()) * CONVERT_VALUE); + m_x = (StorageType)(static_cast(quat.GetX()) * CONVERT_VALUE); + m_y = (StorageType)(static_cast(quat.GetY()) * CONVERT_VALUE); + m_z = (StorageType)(static_cast(quat.GetZ()) * CONVERT_VALUE); + m_w = (StorageType)(static_cast(quat.GetW()) * CONVERT_VALUE); } // uncompress into a quaternion @@ -55,7 +55,7 @@ template MCORE_INLINE void TCompressedQuaternion::UnCompress(AZ::Quaternion* output) const { const float f = 1.0f / (float)CONVERT_VALUE; - output->Set(mX * f, mY * f, mZ * f, mW * f); + output->Set(m_x * f, m_y * f, m_z * f, m_w * f); } @@ -63,7 +63,7 @@ MCORE_INLINE void TCompressedQuaternion::UnCompress(AZ::Quaternion* template <> MCORE_INLINE void TCompressedQuaternion::UnCompress(AZ::Quaternion* output) const { - output->Set(mX * 0.000030518509448f, mY * 0.000030518509448f, mZ * 0.000030518509448f, mW * 0.000030518509448f); + output->Set(m_x * 0.000030518509448f, m_y * 0.000030518509448f, m_z * 0.000030518509448f, m_w * 0.000030518509448f); } @@ -72,7 +72,7 @@ template MCORE_INLINE AZ::Quaternion TCompressedQuaternion::ToQuaternion() const { const float f = 1.0f / (float)CONVERT_VALUE; - return AZ::Quaternion(mX * f, mY * f, mZ * f, mW * f); + return AZ::Quaternion(m_x * f, m_y * f, m_z * f, m_w * f); } @@ -80,5 +80,5 @@ MCORE_INLINE AZ::Quaternion TCompressedQuaternion::ToQuaternion() c template <> MCORE_INLINE AZ::Quaternion TCompressedQuaternion::ToQuaternion() const { - return AZ::Quaternion(mX * 0.000030518509448f, mY * 0.000030518509448f, mZ * 0.000030518509448f, mW * 0.000030518509448f); + return AZ::Quaternion(m_x * 0.000030518509448f, m_y * 0.000030518509448f, m_z * 0.000030518509448f, m_w * 0.000030518509448f); } diff --git a/Gems/EMotionFX/Code/MCore/Source/CompressedVector.h b/Gems/EMotionFX/Code/MCore/Source/CompressedVector.h index 32fc2d71f7..d38a0a1862 100644 --- a/Gems/EMotionFX/Code/MCore/Source/CompressedVector.h +++ b/Gems/EMotionFX/Code/MCore/Source/CompressedVector.h @@ -46,9 +46,9 @@ namespace MCore * @param z The compressed z component. */ MCORE_INLINE TCompressedVector3(StorageType x, StorageType y, StorageType z) - : mX(x) - , mY(y) - , mZ(z) {} + : m_x(x) + , m_y(y) + , m_z(z) {} /** * Create a compressed vector from an uncompressed one. @@ -78,7 +78,7 @@ namespace MCore public: - StorageType mX, mY, mZ; /**< The compressed/packed vector components. */ + StorageType m_x, m_y, m_z; /**< The compressed/packed vector components. */ // the number of steps within the specified range enum diff --git a/Gems/EMotionFX/Code/MCore/Source/CompressedVector.inl b/Gems/EMotionFX/Code/MCore/Source/CompressedVector.inl index 693e2ac832..ce9adc60c9 100644 --- a/Gems/EMotionFX/Code/MCore/Source/CompressedVector.inl +++ b/Gems/EMotionFX/Code/MCore/Source/CompressedVector.inl @@ -19,9 +19,9 @@ MCORE_INLINE TCompressedVector3::TCompressedVector3(const AZ::Vecto { // TODO: make sure due to rounding/floating point errors the result is not negative? const float f = static_cast(CONVERT_VALUE) / (maxValue - minValue); - mX = static_cast((vec.GetX() - minValue) * f); - mY = static_cast((vec.GetY() - minValue) * f); - mZ = static_cast((vec.GetZ() - minValue) * f); + m_x = static_cast((vec.GetX() - minValue) * f); + m_y = static_cast((vec.GetY() - minValue) * f); + m_z = static_cast((vec.GetZ() - minValue) * f); } @@ -31,9 +31,9 @@ MCORE_INLINE void TCompressedVector3::FromVector3(const AZ::Vector3 { // TODO: make sure due to rounding/floating point errors the result is not negative? const float f = static_cast(CONVERT_VALUE) / (maxValue - minValue); - mX = static_cast((vec.GetX() - minValue) * f); - mY = static_cast((vec.GetY() - minValue) * f); - mZ = static_cast((vec.GetZ() - minValue) * f); + m_x = static_cast((vec.GetX() - minValue) * f); + m_y = static_cast((vec.GetY() - minValue) * f); + m_z = static_cast((vec.GetZ() - minValue) * f); } @@ -42,6 +42,6 @@ template MCORE_INLINE AZ::Vector3 TCompressedVector3::ToVector3(float minValue, float maxValue) const { const float f = (maxValue - minValue) / static_cast(CONVERT_VALUE); - return AZ::Vector3(static_cast(mX) * f + minValue, static_cast(mY) * f + minValue, static_cast(mZ) * f + minValue); + return AZ::Vector3(static_cast(m_x) * f + minValue, static_cast(m_y) * f + minValue, static_cast(m_z) * f + minValue); } diff --git a/Gems/EMotionFX/Code/MCore/Source/DiskFile.cpp b/Gems/EMotionFX/Code/MCore/Source/DiskFile.cpp index 27e94489e6..6fd0c59085 100644 --- a/Gems/EMotionFX/Code/MCore/Source/DiskFile.cpp +++ b/Gems/EMotionFX/Code/MCore/Source/DiskFile.cpp @@ -15,7 +15,7 @@ namespace MCore // constructor DiskFile::DiskFile() : File() - , mFile(nullptr) + , m_file(nullptr) { } @@ -38,7 +38,7 @@ namespace MCore bool DiskFile::Open(const char* fileName, EMode mode) { // if the file already is open, close it first - if (mFile) + if (m_file) { Close(); } @@ -65,27 +65,27 @@ namespace MCore }(); // set the file mode we used - mFileMode = mode; + m_fileMode = mode; // set the filename - mFileName = fileName; + m_fileName = fileName; // try to open the file - mFile = nullptr; - azfopen(&mFile, fileName, fileMode); + m_file = nullptr; + azfopen(&m_file, fileName, fileMode); // check on success - return (mFile != nullptr); + return (m_file != nullptr); } // close the file void DiskFile::Close() { - if (mFile) + if (m_file) { - fclose(mFile); - mFile = nullptr; + fclose(m_file); + m_file = nullptr; } } @@ -93,41 +93,41 @@ namespace MCore // flush the file void DiskFile::Flush() { - MCORE_ASSERT(mFile); - fflush(mFile); + MCORE_ASSERT(m_file); + fflush(m_file); } bool DiskFile::GetIsOpen() const { - return (mFile != nullptr); + return (m_file != nullptr); } // return true when we have reached the end of the file bool DiskFile::GetIsEOF() const { - MCORE_ASSERT(mFile); - return (feof(mFile) != 0); + MCORE_ASSERT(m_file); + return (feof(m_file) != 0); } // returns the next byte in the file uint8 DiskFile::GetNextByte() { - MCORE_ASSERT(mFile); - MCORE_ASSERT((mFileMode == READ) || (mFileMode == READWRITE) || (mFileMode == READWRITEAPPEND) || (mFileMode == APPEND) || (mFileMode == READWRITECREATE)); // make sure we opened the file in read mode - return static_cast(fgetc(mFile)); + MCORE_ASSERT(m_file); + MCORE_ASSERT((m_fileMode == READ) || (m_fileMode == READWRITE) || (m_fileMode == READWRITEAPPEND) || (m_fileMode == APPEND) || (m_fileMode == READWRITECREATE)); // make sure we opened the file in read mode + return static_cast(fgetc(m_file)); } // write a given byte to the file bool DiskFile::WriteByte(uint8 value) { - MCORE_ASSERT(mFile); - MCORE_ASSERT((mFileMode == WRITE) || (mFileMode == READWRITE) || (mFileMode == READWRITEAPPEND) || (mFileMode == READWRITECREATE)); // make sure we opened the file in write mode + MCORE_ASSERT(m_file); + MCORE_ASSERT((m_fileMode == WRITE) || (m_fileMode == READWRITE) || (m_fileMode == READWRITEAPPEND) || (m_fileMode == READWRITECREATE)); // make sure we opened the file in write mode - if (fputc(value, mFile) == EOF) + if (fputc(value, m_file) == EOF) { return false; } @@ -139,10 +139,10 @@ namespace MCore // write data to the file size_t DiskFile::Write(const void* data, size_t length) { - MCORE_ASSERT(mFile); - MCORE_ASSERT((mFileMode == WRITE) || (mFileMode == READWRITE) || (mFileMode == READWRITEAPPEND) || (mFileMode == READWRITECREATE)); // make sure we opened the file in write mode + MCORE_ASSERT(m_file); + MCORE_ASSERT((m_fileMode == WRITE) || (m_fileMode == READWRITE) || (m_fileMode == READWRITEAPPEND) || (m_fileMode == READWRITECREATE)); // make sure we opened the file in write mode - if (fwrite(data, length, 1, mFile) == 0) + if (fwrite(data, length, 1, m_file) == 0) { return 0; } @@ -154,10 +154,10 @@ namespace MCore // read data from the file size_t DiskFile::Read(void* data, size_t length) { - MCORE_ASSERT(mFile); - MCORE_ASSERT((mFileMode == READ) || (mFileMode == READWRITE) || (mFileMode == READWRITEAPPEND) || (mFileMode == APPEND) || (mFileMode == READWRITECREATE)); // make sure we opened the file in read mode + MCORE_ASSERT(m_file); + MCORE_ASSERT((m_fileMode == READ) || (m_fileMode == READWRITE) || (m_fileMode == READWRITEAPPEND) || (m_fileMode == APPEND) || (m_fileMode == READWRITECREATE)); // make sure we opened the file in read mode - if (fread(data, length, 1, mFile) == 0) + if (fread(data, length, 1, m_file) == 0) { return 0; } @@ -169,13 +169,13 @@ namespace MCore // get the file mode DiskFile::EMode DiskFile::GetFileMode() const { - return mFileMode; + return m_fileMode; } // get the file name const AZStd::string& DiskFile::GetFileName() const { - return mFileName; + return m_fileName; } } // namespace MCore diff --git a/Gems/EMotionFX/Code/MCore/Source/DiskFile.h b/Gems/EMotionFX/Code/MCore/Source/DiskFile.h index d17ff7f1f8..4f09a73f3b 100644 --- a/Gems/EMotionFX/Code/MCore/Source/DiskFile.h +++ b/Gems/EMotionFX/Code/MCore/Source/DiskFile.h @@ -162,8 +162,8 @@ namespace MCore const AZStd::string& GetFileName() const; protected: - AZStd::string mFileName; /**< The filename */ - FILE* mFile; /**< The file handle. */ - EMode mFileMode; /**< The mode we opened the file with. */ + AZStd::string m_fileName; /**< The filename */ + FILE* m_file; /**< The file handle. */ + EMode m_fileMode; /**< The mode we opened the file with. */ }; } // namespace MCore diff --git a/Gems/EMotionFX/Code/MCore/Source/Distance.cpp b/Gems/EMotionFX/Code/MCore/Source/Distance.cpp index e2a966b370..d73a4db601 100644 --- a/Gems/EMotionFX/Code/MCore/Source/Distance.cpp +++ b/Gems/EMotionFX/Code/MCore/Source/Distance.cpp @@ -16,8 +16,8 @@ namespace MCore // convert it into another unit type const MCore::Distance& Distance::ConvertTo(EUnitType targetUnitType) { - mDistance = mDistanceMeters * GetConversionFactorFromMeters(targetUnitType); - mUnitType = targetUnitType; + m_distance = m_distanceMeters * GetConversionFactorFromMeters(targetUnitType); + m_unitType = targetUnitType; return *this; } @@ -166,7 +166,7 @@ namespace MCore // update the distance in meters void Distance::UpdateDistanceMeters() { - mDistanceMeters = mDistance * GetConversionFactorToMeters(mUnitType); + m_distanceMeters = m_distance * GetConversionFactorToMeters(m_unitType); } diff --git a/Gems/EMotionFX/Code/MCore/Source/Distance.h b/Gems/EMotionFX/Code/MCore/Source/Distance.h index 3f26295201..6548fc251d 100644 --- a/Gems/EMotionFX/Code/MCore/Source/Distance.h +++ b/Gems/EMotionFX/Code/MCore/Source/Distance.h @@ -38,21 +38,21 @@ namespace MCore }; MCORE_INLINE Distance() - : mDistance(0.0) - , mDistanceMeters(0.0) - , mUnitType(UNITTYPE_METERS) { } + : m_distance(0.0) + , m_distanceMeters(0.0) + , m_unitType(UNITTYPE_METERS) { } MCORE_INLINE Distance(double units, EUnitType unitType) - : mDistance(units) - , mDistanceMeters(0.0) - , mUnitType(unitType) { UpdateDistanceMeters(); } + : m_distance(units) + , m_distanceMeters(0.0) + , m_unitType(unitType) { UpdateDistanceMeters(); } MCORE_INLINE Distance(float units, EUnitType unitType) - : mDistance(units) - , mDistanceMeters(0.0) - , mUnitType(unitType) { UpdateDistanceMeters(); } + : m_distance(units) + , m_distanceMeters(0.0) + , m_unitType(unitType) { UpdateDistanceMeters(); } MCORE_INLINE Distance(const Distance& other) - : mDistance(other.mDistance) - , mDistanceMeters(other.mDistanceMeters) - , mUnitType(other.mUnitType) {} + : m_distance(other.m_distance) + , m_distanceMeters(other.m_distanceMeters) + , m_unitType(other.m_unitType) {} const Distance& ConvertTo(EUnitType targetUnitType); MCORE_INLINE Distance ConvertedTo(EUnitType targetUnitType) const { Distance result(*this); result.ConvertTo(targetUnitType); return result; } @@ -65,46 +65,46 @@ namespace MCore static const char* UnitTypeToString(EUnitType unitType); static bool StringToUnitType(const AZStd::string& str, EUnitType* outUnitType); - MCORE_INLINE double GetDistance() const { return mDistance; } - MCORE_INLINE EUnitType GetUnitType() const { return mUnitType; } + MCORE_INLINE double GetDistance() const { return m_distance; } + MCORE_INLINE EUnitType GetUnitType() const { return m_unitType; } - MCORE_INLINE void Set(double dist, EUnitType unitType) { mDistance = dist; mUnitType = unitType; UpdateDistanceMeters(); } - MCORE_INLINE void SetDistance(double dist) { mDistance = dist; UpdateDistanceMeters(); } - MCORE_INLINE void SetUnitType(EUnitType unitType) { mUnitType = unitType; UpdateDistanceMeters(); } + MCORE_INLINE void Set(double dist, EUnitType unitType) { m_distance = dist; m_unitType = unitType; UpdateDistanceMeters(); } + MCORE_INLINE void SetDistance(double dist) { m_distance = dist; UpdateDistanceMeters(); } + MCORE_INLINE void SetUnitType(EUnitType unitType) { m_unitType = unitType; UpdateDistanceMeters(); } - MCORE_INLINE double CalcDistanceInUnitType(EUnitType targetUnitType) const { return mDistanceMeters * GetConversionFactorFromMeters(targetUnitType); } - MCORE_INLINE double CalcNumMillimeters() const { return mDistanceMeters * 1000.0; } - MCORE_INLINE double CalcNumCentimeters() const { return mDistanceMeters * 100.0; } - MCORE_INLINE double CalcNumDecimeters() const { return mDistanceMeters * 10.0; } - MCORE_INLINE double CalcNumMeters() const { return mDistanceMeters; } - MCORE_INLINE double CalcNumKilometers() const { return mDistanceMeters * 0.001; } - MCORE_INLINE double CalcNumInches() const { return mDistanceMeters * 39.370078740157; } - MCORE_INLINE double CalcNumFeet() const { return mDistanceMeters * 3.2808398950131; } - MCORE_INLINE double CalcNumYards() const { return mDistanceMeters * 1.0936132983377; } - MCORE_INLINE double CalcNumMiles() const { return mDistanceMeters * 0.00062137119223733; } + MCORE_INLINE double CalcDistanceInUnitType(EUnitType targetUnitType) const { return m_distanceMeters * GetConversionFactorFromMeters(targetUnitType); } + MCORE_INLINE double CalcNumMillimeters() const { return m_distanceMeters * 1000.0; } + MCORE_INLINE double CalcNumCentimeters() const { return m_distanceMeters * 100.0; } + MCORE_INLINE double CalcNumDecimeters() const { return m_distanceMeters * 10.0; } + MCORE_INLINE double CalcNumMeters() const { return m_distanceMeters; } + MCORE_INLINE double CalcNumKilometers() const { return m_distanceMeters * 0.001; } + MCORE_INLINE double CalcNumInches() const { return m_distanceMeters * 39.370078740157; } + MCORE_INLINE double CalcNumFeet() const { return m_distanceMeters * 3.2808398950131; } + MCORE_INLINE double CalcNumYards() const { return m_distanceMeters * 1.0936132983377; } + MCORE_INLINE double CalcNumMiles() const { return m_distanceMeters * 0.00062137119223733; } - MCORE_INLINE Distance operator - () const { return Distance(-mDistance, mUnitType); } - MCORE_INLINE const Distance& operator = (const Distance& other) { mDistance = other.mDistance; mDistanceMeters = other.mDistanceMeters; mUnitType = other.mUnitType; return *this; } + MCORE_INLINE Distance operator - () const { return Distance(-m_distance, m_unitType); } + MCORE_INLINE const Distance& operator = (const Distance& other) { m_distance = other.m_distance; m_distanceMeters = other.m_distanceMeters; m_unitType = other.m_unitType; return *this; } - MCORE_INLINE const Distance& operator *= (double f) { mDistance *= f; UpdateDistanceMeters(); return *this; } - MCORE_INLINE const Distance& operator /= (double f) { mDistance /= f; UpdateDistanceMeters(); return *this; } - MCORE_INLINE const Distance& operator += (double f) { mDistance += f; UpdateDistanceMeters(); return *this; } - MCORE_INLINE const Distance& operator -= (double f) { mDistance -= f; UpdateDistanceMeters(); return *this; } + MCORE_INLINE const Distance& operator *= (double f) { m_distance *= f; UpdateDistanceMeters(); return *this; } + MCORE_INLINE const Distance& operator /= (double f) { m_distance /= f; UpdateDistanceMeters(); return *this; } + MCORE_INLINE const Distance& operator += (double f) { m_distance += f; UpdateDistanceMeters(); return *this; } + MCORE_INLINE const Distance& operator -= (double f) { m_distance -= f; UpdateDistanceMeters(); return *this; } - MCORE_INLINE const Distance& operator *= (float f) { mDistance *= f; UpdateDistanceMeters(); return *this; } - MCORE_INLINE const Distance& operator /= (float f) { mDistance /= f; UpdateDistanceMeters(); return *this; } - MCORE_INLINE const Distance& operator += (float f) { mDistance += f; UpdateDistanceMeters(); return *this; } - MCORE_INLINE const Distance& operator -= (float f) { mDistance -= f; UpdateDistanceMeters(); return *this; } + MCORE_INLINE const Distance& operator *= (float f) { m_distance *= f; UpdateDistanceMeters(); return *this; } + MCORE_INLINE const Distance& operator /= (float f) { m_distance /= f; UpdateDistanceMeters(); return *this; } + MCORE_INLINE const Distance& operator += (float f) { m_distance += f; UpdateDistanceMeters(); return *this; } + MCORE_INLINE const Distance& operator -= (float f) { m_distance -= f; UpdateDistanceMeters(); return *this; } - MCORE_INLINE const Distance& operator *= (const Distance& other) { mDistance *= other.ConvertedTo(mUnitType).GetDistance(); UpdateDistanceMeters(); return *this; } - MCORE_INLINE const Distance& operator /= (const Distance& other) { mDistance /= other.ConvertedTo(mUnitType).GetDistance(); UpdateDistanceMeters(); return *this; } - MCORE_INLINE const Distance& operator += (const Distance& other) { mDistance += other.ConvertedTo(mUnitType).GetDistance(); UpdateDistanceMeters(); return *this; } - MCORE_INLINE const Distance& operator -= (const Distance& other) { mDistance -= other.ConvertedTo(mUnitType).GetDistance(); UpdateDistanceMeters(); return *this; } + MCORE_INLINE const Distance& operator *= (const Distance& other) { m_distance *= other.ConvertedTo(m_unitType).GetDistance(); UpdateDistanceMeters(); return *this; } + MCORE_INLINE const Distance& operator /= (const Distance& other) { m_distance /= other.ConvertedTo(m_unitType).GetDistance(); UpdateDistanceMeters(); return *this; } + MCORE_INLINE const Distance& operator += (const Distance& other) { m_distance += other.ConvertedTo(m_unitType).GetDistance(); UpdateDistanceMeters(); return *this; } + MCORE_INLINE const Distance& operator -= (const Distance& other) { m_distance -= other.ConvertedTo(m_unitType).GetDistance(); UpdateDistanceMeters(); return *this; } private: - double mDistance; /**< The actual distance in the current unit type. */ - double mDistanceMeters; /**< The distance in meters. */ - EUnitType mUnitType; /**< The actual unit type. */ + double m_distance; /**< The actual distance in the current unit type. */ + double m_distanceMeters; /**< The distance in meters. */ + EUnitType m_unitType; /**< The actual unit type. */ void UpdateDistanceMeters(); }; diff --git a/Gems/EMotionFX/Code/MCore/Source/DualQuaternion.cpp b/Gems/EMotionFX/Code/MCore/Source/DualQuaternion.cpp index bf4d249472..43c33b1a08 100644 --- a/Gems/EMotionFX/Code/MCore/Source/DualQuaternion.cpp +++ b/Gems/EMotionFX/Code/MCore/Source/DualQuaternion.cpp @@ -16,12 +16,12 @@ namespace MCore // calculate the inverse DualQuaternion& DualQuaternion::Inverse() { - const float realLength = mReal.GetLength(); - const float dotProduct = mReal.Dot(mDual); + const float realLength = m_real.GetLength(); + const float dotProduct = m_real.Dot(m_dual); const float dualFactor = realLength - 2.0f * dotProduct; - mReal.Set(-mReal.GetX() * realLength, -mReal.GetY() * realLength, -mReal.GetZ() * realLength, mReal.GetW() * realLength); - mDual.Set(-mDual.GetX() * dualFactor, -mDual.GetY() * dualFactor, -mDual.GetZ() * dualFactor, mDual.GetW() * dualFactor); + m_real.Set(-m_real.GetX() * realLength, -m_real.GetY() * realLength, -m_real.GetZ() * realLength, m_real.GetW() * realLength); + m_dual.Set(-m_dual.GetX() * dualFactor, -m_dual.GetY() * dualFactor, -m_dual.GetZ() * dualFactor, m_dual.GetW() * dualFactor); return *this; } @@ -30,26 +30,26 @@ namespace MCore // calculate the inversed version DualQuaternion DualQuaternion::Inversed() const { - const float realLength = mReal.GetLength(); - const float dotProduct = mReal.Dot(mDual); + const float realLength = m_real.GetLength(); + const float dotProduct = m_real.Dot(m_dual); const float dualFactor = realLength - 2.0f * dotProduct; - return DualQuaternion(AZ::Quaternion(-mReal.GetX() * realLength, -mReal.GetY() * realLength, -mReal.GetZ() * realLength, mReal.GetW() * realLength), - AZ::Quaternion(-mDual.GetX() * dualFactor, -mDual.GetY() * dualFactor, -mDual.GetZ() * dualFactor, mDual.GetW() * dualFactor)); + return DualQuaternion(AZ::Quaternion(-m_real.GetX() * realLength, -m_real.GetY() * realLength, -m_real.GetZ() * realLength, m_real.GetW() * realLength), + AZ::Quaternion(-m_dual.GetX() * dualFactor, -m_dual.GetY() * dualFactor, -m_dual.GetZ() * dualFactor, m_dual.GetW() * dualFactor)); } // convert the dual quaternion to a matrix AZ::Transform DualQuaternion::ToTransform() const { - const float sqLen = mReal.Dot(mReal); - const float x = mReal.GetX(); - const float y = mReal.GetY(); - const float z = mReal.GetZ(); - const float w = mReal.GetW(); - const float t0 = mDual.GetW(); - const float t1 = mDual.GetX(); - const float t2 = mDual.GetY(); - const float t3 = mDual.GetZ(); + const float sqLen = m_real.Dot(m_real); + const float x = m_real.GetX(); + const float y = m_real.GetY(); + const float z = m_real.GetZ(); + const float w = m_real.GetW(); + const float t0 = m_dual.GetW(); + const float t1 = m_dual.GetX(); + const float t2 = m_dual.GetY(); + const float t3 = m_dual.GetZ(); AZ::Matrix3x3 matrix3x3; matrix3x3.SetElement(0, 0, w * w + x * x - y * y - z * z); @@ -85,12 +85,12 @@ namespace MCore // normalizes the dual quaternion DualQuaternion& DualQuaternion::Normalize() { - const float length = mReal.GetLength(); + const float length = m_real.GetLength(); const float invLength = 1.0f / length; - mReal.Set(mReal.GetX() * invLength, mReal.GetY() * invLength, mReal.GetZ() * invLength, mReal.GetW() * invLength); - mDual.Set(mDual.GetX() * invLength, mDual.GetY() * invLength, mDual.GetZ() * invLength, mDual.GetW() * invLength); - mDual += mReal * (mReal.Dot(mDual) * -1.0f); + m_real.Set(m_real.GetX() * invLength, m_real.GetY() * invLength, m_real.GetZ() * invLength, m_real.GetW() * invLength); + m_dual.Set(m_dual.GetX() * invLength, m_dual.GetY() * invLength, m_dual.GetZ() * invLength, m_dual.GetW() * invLength); + m_dual += m_real * (m_real.Dot(m_dual) * -1.0f); return *this; } @@ -98,11 +98,11 @@ namespace MCore // convert back into rotation and translation void DualQuaternion::ToRotationTranslation(AZ::Quaternion* outRot, AZ::Vector3* outPos) const { - const float invLength = 1.0f / mReal.GetLength(); - *outRot = mReal * invLength; - outPos->Set(2.0f * (-mDual.GetW() * mReal.GetX() + mDual.GetX() * mReal.GetW() - mDual.GetY() * mReal.GetZ() + mDual.GetZ() * mReal.GetY()) * invLength, - 2.0f * (-mDual.GetW() * mReal.GetY() + mDual.GetX() * mReal.GetZ() + mDual.GetY() * mReal.GetW() - mDual.GetZ() * mReal.GetX()) * invLength, - 2.0f * (-mDual.GetW() * mReal.GetZ() - mDual.GetX() * mReal.GetY() + mDual.GetY() * mReal.GetX() + mDual.GetZ() * mReal.GetW()) * invLength); + const float invLength = 1.0f / m_real.GetLength(); + *outRot = m_real * invLength; + outPos->Set(2.0f * (-m_dual.GetW() * m_real.GetX() + m_dual.GetX() * m_real.GetW() - m_dual.GetY() * m_real.GetZ() + m_dual.GetZ() * m_real.GetY()) * invLength, + 2.0f * (-m_dual.GetW() * m_real.GetY() + m_dual.GetX() * m_real.GetZ() + m_dual.GetY() * m_real.GetW() - m_dual.GetZ() * m_real.GetX()) * invLength, + 2.0f * (-m_dual.GetW() * m_real.GetZ() - m_dual.GetX() * m_real.GetY() + m_dual.GetY() * m_real.GetX() + m_dual.GetZ() * m_real.GetW()) * invLength); } @@ -110,10 +110,10 @@ namespace MCore // only works with normalized dual quaternions void DualQuaternion::NormalizedToRotationTranslation(AZ::Quaternion* outRot, AZ::Vector3* outPos) const { - *outRot = mReal; - outPos->Set(2.0f * (-mDual.GetW() * mReal.GetX() + mDual.GetX() * mReal.GetW() - mDual.GetY() * mReal.GetZ() + mDual.GetZ() * mReal.GetY()), - 2.0f * (-mDual.GetW() * mReal.GetY() + mDual.GetX() * mReal.GetZ() + mDual.GetY() * mReal.GetW() - mDual.GetZ() * mReal.GetX()), - 2.0f * (-mDual.GetW() * mReal.GetZ() - mDual.GetX() * mReal.GetY() + mDual.GetY() * mReal.GetX() + mDual.GetZ() * mReal.GetW())); + *outRot = m_real; + outPos->Set(2.0f * (-m_dual.GetW() * m_real.GetX() + m_dual.GetX() * m_real.GetW() - m_dual.GetY() * m_real.GetZ() + m_dual.GetZ() * m_real.GetY()), + 2.0f * (-m_dual.GetW() * m_real.GetY() + m_dual.GetX() * m_real.GetZ() + m_dual.GetY() * m_real.GetW() - m_dual.GetZ() * m_real.GetX()), + 2.0f * (-m_dual.GetW() * m_real.GetZ() - m_dual.GetX() * m_real.GetY() + m_dual.GetY() * m_real.GetX() + m_dual.GetZ() * m_real.GetW())); } diff --git a/Gems/EMotionFX/Code/MCore/Source/DualQuaternion.h b/Gems/EMotionFX/Code/MCore/Source/DualQuaternion.h index af16713363..74caa715e5 100644 --- a/Gems/EMotionFX/Code/MCore/Source/DualQuaternion.h +++ b/Gems/EMotionFX/Code/MCore/Source/DualQuaternion.h @@ -37,16 +37,16 @@ namespace MCore * This automatically initializes the dual quaternion to identity. */ MCORE_INLINE DualQuaternion() - : mReal(0.0f, 0.0f, 0.0f, 1.0f) - , mDual(0.0f, 0.0f, 0.0f, 0.0f) {} + : m_real(0.0f, 0.0f, 0.0f, 1.0f) + , m_dual(0.0f, 0.0f, 0.0f, 0.0f) {} /** * Copy constructor. * @param other The dual quaternion to copy the data from. */ MCORE_INLINE DualQuaternion(const DualQuaternion& other) - : mReal(other.mReal) - , mDual(other.mDual) {} + : m_real(other.m_real) + , m_dual(other.m_dual) {} /** * Extended constructor. @@ -56,8 +56,8 @@ namespace MCore * or use the FromRotationTranslation method. */ MCORE_INLINE DualQuaternion(const AZ::Quaternion& real, const AZ::Quaternion& dual) - : mReal(real) - , mDual(dual) {} + : m_real(real) + , m_dual(dual) {} /** * Constructor which takes a matrix as input parameter. @@ -81,7 +81,7 @@ namespace MCore * @note Please keep in mind that you should not set the translation directly into the dual part. If you want to initialize the dual quaternion from * a rotation and translation, please use the special constructor for this, or the FromRotationTranslation method. */ - MCORE_INLINE void Set(const AZ::Quaternion& real, const AZ::Quaternion& dual) { mReal = real; mDual = dual; } + MCORE_INLINE void Set(const AZ::Quaternion& real, const AZ::Quaternion& dual) { m_real = real; m_dual = dual; } /** * Normalize the dual quaternion. @@ -102,7 +102,7 @@ namespace MCore * The default constructor already puts the dual quaternion in its identity transform. * @result A reference to this quaternion, but now having an identity transform. */ - MCORE_INLINE DualQuaternion& Identity() { mReal = AZ::Quaternion::CreateIdentity(); mDual.Set(0.0f, 0.0f, 0.0f, 0.0f); return *this; } + MCORE_INLINE DualQuaternion& Identity() { m_real = AZ::Quaternion::CreateIdentity(); m_dual.Set(0.0f, 0.0f, 0.0f, 0.0f); return *this; } /** * Get the dot product between the two dual quaternions. @@ -112,7 +112,7 @@ namespace MCore * @result A 2D vector containing the result of the dot products. The x component contains the result of the dot between the real part and the y component * contains the result of the dot product between the dual parts. */ - MCORE_INLINE AZ::Vector2 Dot(const DualQuaternion& other) const { return AZ::Vector2(mReal.Dot(other.mReal), mDual.Dot(other.mDual)); } + MCORE_INLINE AZ::Vector2 Dot(const DualQuaternion& other) const { return AZ::Vector2(m_real.Dot(other.m_real), m_dual.Dot(other.m_dual)); } /** * Calculate the length of the dual quaternion. @@ -120,7 +120,7 @@ namespace MCore * The result of the real part will be stored in the x component of the 2D vector, and the result of the dual part will be stored in the y component. * @result The 2D vector containing the length of the real and dual part. */ - MCORE_INLINE AZ::Vector2 Length() const { const float realLen = mReal.GetLength(); return AZ::Vector2(realLen, mReal.Dot(mDual) / realLen); } + MCORE_INLINE AZ::Vector2 Length() const { const float realLen = m_real.GetLength(); return AZ::Vector2(realLen, m_real.Dot(m_dual) / realLen); } /** * Inverse this dual quaternion. @@ -139,14 +139,14 @@ namespace MCore * @result A reference to this dual quaternion, but now conjugaged. * @note If you want to inverse a unit quaternion, you can use the conjugate instead, as that gives the same result, but is much faster to calculate. */ - MCORE_INLINE DualQuaternion& Conjugate() { mReal = mReal.GetConjugate(); mDual = mDual.GetConjugate(); return *this; } + MCORE_INLINE DualQuaternion& Conjugate() { m_real = m_real.GetConjugate(); m_dual = m_dual.GetConjugate(); return *this; } /** * Calculate a conjugated version of this dual quaternion. * @result A copy of this dual quaternion, but conjugated. * @note If you want to inverse a unit quaternion, you can use the conjugate instead, as that gives the same result, but is much faster to calculate. */ - MCORE_INLINE DualQuaternion Conjugated() const { return DualQuaternion(mReal.GetConjugate(), mDual.GetConjugate()); } + MCORE_INLINE DualQuaternion Conjugated() const { return DualQuaternion(m_real.GetConjugate(), m_dual.GetConjugate()); } /** * Initialize the current quaternion from a specified matrix. @@ -228,28 +228,27 @@ namespace MCore // operators MCORE_INLINE const DualQuaternion& operator=(const AZ::Transform& transform) { FromTransform(transform); return *this; } - MCORE_INLINE const DualQuaternion& operator=(const DualQuaternion& other) { mReal = other.mReal; mDual = other.mDual; return *this; } - MCORE_INLINE DualQuaternion operator-() const { return DualQuaternion(-mReal, -mDual); } - MCORE_INLINE const DualQuaternion& operator+=(const DualQuaternion& q) { mReal += q.mReal; mDual += q.mDual; return *this; } - MCORE_INLINE const DualQuaternion& operator-=(const DualQuaternion& q) { mReal -= q.mReal; mDual -= q.mDual; return *this; } - MCORE_INLINE const DualQuaternion& operator*=(const DualQuaternion& q) { const AZ::Quaternion orgReal(mReal); mReal *= q.mReal; mDual = orgReal * q.mDual + q.mReal * mDual; return *this; } - MCORE_INLINE const DualQuaternion& operator*=(float f) { mReal *= f; mDual *= f; return *this; } - //MCORE_INLINE const DualQuaternion& operator*=(double f) { mReal*=f; mDual*=f; return *this; } + MCORE_INLINE const DualQuaternion& operator=(const DualQuaternion& other) { m_real = other.m_real; m_dual = other.m_dual; return *this; } + MCORE_INLINE DualQuaternion operator-() const { return DualQuaternion(-m_real, -m_dual); } + MCORE_INLINE const DualQuaternion& operator+=(const DualQuaternion& q) { m_real += q.m_real; m_dual += q.m_dual; return *this; } + MCORE_INLINE const DualQuaternion& operator-=(const DualQuaternion& q) { m_real -= q.m_real; m_dual -= q.m_dual; return *this; } + MCORE_INLINE const DualQuaternion& operator*=(const DualQuaternion& q) { const AZ::Quaternion orgReal(m_real); m_real *= q.m_real; m_dual = orgReal * q.m_dual + q.m_real * m_dual; return *this; } + MCORE_INLINE const DualQuaternion& operator*=(float f) { m_real *= f; m_dual *= f; return *this; } // attributes - AZ::Quaternion mReal; /**< The real value, which you can see as the regular rotation quaternion. */ - AZ::Quaternion mDual; /**< The dual part, which you can see as the translation part. */ + AZ::Quaternion m_real; /**< The real value, which you can see as the regular rotation quaternion. */ + AZ::Quaternion m_dual; /**< The dual part, which you can see as the translation part. */ }; // operators - MCORE_INLINE DualQuaternion operator*(const DualQuaternion& a, float f) { return DualQuaternion(a.mReal * f, a.mDual * f); } - MCORE_INLINE DualQuaternion operator*(float f, const DualQuaternion& b) { return DualQuaternion(b.mReal * f, b.mDual * f); } - MCORE_INLINE DualQuaternion operator+(const DualQuaternion& a, const DualQuaternion& b) { return DualQuaternion(a.mReal + b.mReal, a.mDual + b.mDual); } - MCORE_INLINE DualQuaternion operator-(const DualQuaternion& a, const DualQuaternion& b) { return DualQuaternion(a.mReal - b.mReal, a.mDual - b.mDual); } + MCORE_INLINE DualQuaternion operator*(const DualQuaternion& a, float f) { return DualQuaternion(a.m_real * f, a.m_dual * f); } + MCORE_INLINE DualQuaternion operator*(float f, const DualQuaternion& b) { return DualQuaternion(b.m_real * f, b.m_dual * f); } + MCORE_INLINE DualQuaternion operator+(const DualQuaternion& a, const DualQuaternion& b) { return DualQuaternion(a.m_real + b.m_real, a.m_dual + b.m_dual); } + MCORE_INLINE DualQuaternion operator-(const DualQuaternion& a, const DualQuaternion& b) { return DualQuaternion(a.m_real - b.m_real, a.m_dual - b.m_dual); } MCORE_INLINE DualQuaternion operator*(const DualQuaternion& a, const DualQuaternion& b) { - return DualQuaternion(a.mReal * b.mReal, a.mReal * b.mDual + b.mReal * a.mDual); + return DualQuaternion(a.m_real * b.m_real, a.m_real * b.m_dual + b.m_real * a.m_dual); } // include the inline code diff --git a/Gems/EMotionFX/Code/MCore/Source/DualQuaternion.inl b/Gems/EMotionFX/Code/MCore/Source/DualQuaternion.inl index d928bae6d9..1c0c378852 100644 --- a/Gems/EMotionFX/Code/MCore/Source/DualQuaternion.inl +++ b/Gems/EMotionFX/Code/MCore/Source/DualQuaternion.inl @@ -8,9 +8,9 @@ // extended constructor MCORE_INLINE DualQuaternion::DualQuaternion(const AZ::Quaternion& rotation, const AZ::Vector3& translation) - : mReal(rotation) + : m_real(rotation) { - mDual = 0.5f * (AZ::Quaternion(translation.GetX(), translation.GetY(), translation.GetZ(), 0.0f) * rotation); + m_dual = 0.5f * (AZ::Quaternion(translation.GetX(), translation.GetY(), translation.GetZ(), 0.0f) * rotation); } @@ -18,10 +18,10 @@ MCORE_INLINE DualQuaternion::DualQuaternion(const AZ::Quaternion& rotation, cons // transform a 3D point with the dual quaternion MCORE_INLINE AZ::Vector3 DualQuaternion::TransformPoint(const AZ::Vector3& point) const { - const AZ::Vector3 realVector(mReal.GetX(), mReal.GetY(), mReal.GetZ()); - const AZ::Vector3 dualVector(mDual.GetX(), mDual.GetY(), mDual.GetZ()); - const AZ::Vector3 position = point + 2.0f * (realVector.Cross(realVector.Cross(point) + (mReal.GetW() * point))); - const AZ::Vector3 displacement = 2.0f * (mReal.GetW() * dualVector - mDual.GetW() * realVector + realVector.Cross(dualVector)); + const AZ::Vector3 realVector(m_real.GetX(), m_real.GetY(), m_real.GetZ()); + const AZ::Vector3 dualVector(m_dual.GetX(), m_dual.GetY(), m_dual.GetZ()); + const AZ::Vector3 position = point + 2.0f * (realVector.Cross(realVector.Cross(point) + (m_real.GetW() * point))); + const AZ::Vector3 displacement = 2.0f * (m_real.GetW() * dualVector - m_dual.GetW() * realVector + realVector.Cross(dualVector)); return position + displacement; } @@ -29,8 +29,8 @@ MCORE_INLINE AZ::Vector3 DualQuaternion::TransformPoint(const AZ::Vector3& point // transform a vector with this dual quaternion MCORE_INLINE AZ::Vector3 DualQuaternion::TransformVector(const AZ::Vector3& v) const { - const AZ::Vector3 realVector(mReal.GetX(), mReal.GetY(), mReal.GetZ()); - const AZ::Vector3 dualVector(mDual.GetX(), mDual.GetY(), mDual.GetZ()); - return v + 2.0f * (realVector.Cross(realVector.Cross(v) + mReal.GetW() * v)); + const AZ::Vector3 realVector(m_real.GetX(), m_real.GetY(), m_real.GetZ()); + const AZ::Vector3 dualVector(m_dual.GetX(), m_dual.GetY(), m_dual.GetZ()); + return v + 2.0f * (realVector.Cross(realVector.Cross(v) + m_real.GetW() * v)); } diff --git a/Gems/EMotionFX/Code/MCore/Source/FileSystem.cpp b/Gems/EMotionFX/Code/MCore/Source/FileSystem.cpp index 71b426e532..d97cd7c9a9 100644 --- a/Gems/EMotionFX/Code/MCore/Source/FileSystem.cpp +++ b/Gems/EMotionFX/Code/MCore/Source/FileSystem.cpp @@ -18,13 +18,13 @@ namespace MCore { // The folder path used to keep a backup in SaveToFileSecured. - StaticString FileSystem::mSecureSavePath; + StaticString FileSystem::s_secureSavePath; // Save to file secured by a backup file. bool FileSystem::SaveToFileSecured(const char* filename, const AZStd::function& saveFunction, CommandManager* commandManager) { // If the secure save path is not set, simply call the save function. - if (mSecureSavePath.empty()) + if (s_secureSavePath.empty()) { return saveFunction(); } @@ -45,12 +45,12 @@ namespace MCore // Find a unique backup filename. AZ::u32 backupFileIndex = 0; AZStd::string backupFileIndexString; - AZStd::string backupFilename = mSecureSavePath.c_str() + baseFilename + '.' + extension; + AZStd::string backupFilename = s_secureSavePath.c_str() + baseFilename + '.' + extension; while (fileIo->Exists(backupFilename.c_str())) { AZStd::to_string(backupFileIndexString, ++backupFileIndex); - backupFilename = mSecureSavePath.c_str() + baseFilename + backupFileIndexString + '.' + extension; + backupFilename = s_secureSavePath.c_str() + baseFilename + backupFileIndexString + '.' + extension; } // Copy the file to the backup filename. diff --git a/Gems/EMotionFX/Code/MCore/Source/FileSystem.h b/Gems/EMotionFX/Code/MCore/Source/FileSystem.h index 2fdf74ff46..3bf86577e5 100644 --- a/Gems/EMotionFX/Code/MCore/Source/FileSystem.h +++ b/Gems/EMotionFX/Code/MCore/Source/FileSystem.h @@ -34,6 +34,6 @@ namespace MCore */ static bool SaveToFileSecured(const char* filename, const AZStd::function& saveFunction, CommandManager* commandManager = nullptr); - static StaticString mSecureSavePath; /**< The folder path used to keep a backup in SaveToFileSecured. */ + static StaticString s_secureSavePath; /**< The folder path used to keep a backup in SaveToFileSecured. */ }; } // namespace MCore diff --git a/Gems/EMotionFX/Code/MCore/Source/IDGenerator.cpp b/Gems/EMotionFX/Code/MCore/Source/IDGenerator.cpp index 7e4ff9b16e..dc25288c19 100644 --- a/Gems/EMotionFX/Code/MCore/Source/IDGenerator.cpp +++ b/Gems/EMotionFX/Code/MCore/Source/IDGenerator.cpp @@ -15,7 +15,7 @@ namespace MCore { // constructor IDGenerator::IDGenerator() - : mNextID{0} + : m_nextId{0} { } @@ -29,7 +29,7 @@ namespace MCore // get a unique id size_t IDGenerator::GenerateID() { - const size_t result = mNextID++; + const size_t result = m_nextId++; MCORE_ASSERT(result != InvalidIndex); // reached the limit return result; } diff --git a/Gems/EMotionFX/Code/MCore/Source/IDGenerator.h b/Gems/EMotionFX/Code/MCore/Source/IDGenerator.h index 1418b7d3d1..5c392e45b1 100644 --- a/Gems/EMotionFX/Code/MCore/Source/IDGenerator.h +++ b/Gems/EMotionFX/Code/MCore/Source/IDGenerator.h @@ -31,7 +31,7 @@ namespace MCore size_t GenerateID(); private: - AZStd::atomic mNextID; /**< The id used for the next GenerateID() call. */ + AZStd::atomic m_nextId; /**< The id used for the next GenerateID() call. */ /** * Default constructor. diff --git a/Gems/EMotionFX/Code/MCore/Source/LogManager.cpp b/Gems/EMotionFX/Code/MCore/Source/LogManager.cpp index ecf4eb9168..0621926fb2 100644 --- a/Gems/EMotionFX/Code/MCore/Source/LogManager.cpp +++ b/Gems/EMotionFX/Code/MCore/Source/LogManager.cpp @@ -13,21 +13,21 @@ namespace MCore { // static mutex - Mutex LogManager::mGlobalMutex; + Mutex LogManager::s_globalMutex; //-------------------------------------------------------------------------------------------- // constructor LogCallback::LogCallback() { - mLogLevels = LOGLEVEL_DEFAULT; + m_logLevels = LOGLEVEL_DEFAULT; } // set the log levels this callback will accept and pass through void LogCallback::SetLogLevels(ELogLevel logLevels) { - mLogLevels = logLevels; + m_logLevels = logLevels; GetLogManager().InitLogLevels(); } @@ -75,10 +75,10 @@ namespace MCore void LogManager::AddLogCallback(LogCallback* callback) { MCORE_ASSERT(callback); - LockGuard lock(mMutex); + LockGuard lock(m_mutex); // add the callback to the stack - mLogCallbacks.emplace_back(callback); + m_logCallbacks.emplace_back(callback); // collect the enabled log levels InitLogLevels(); @@ -88,14 +88,14 @@ namespace MCore // remove a specific log callback from the stack void LogManager::RemoveLogCallback(size_t index) { - MCORE_ASSERT(index < mLogCallbacks.size()); - LockGuard lock(mMutex); + MCORE_ASSERT(index < m_logCallbacks.size()); + LockGuard lock(m_mutex); // delete it from memory - delete mLogCallbacks[index]; + delete m_logCallbacks[index]; // remove the callback from the stack - mLogCallbacks.erase(AZStd::next(begin(mLogCallbacks), index)); + m_logCallbacks.erase(AZStd::next(begin(m_logCallbacks), index)); // collect the enabled log levels InitLogLevels(); @@ -104,10 +104,10 @@ namespace MCore // remove all given log callbacks by type void LogManager::RemoveAllByType(uint32 type) { - LockGuard lock(mMutex); + LockGuard lock(m_mutex); // Put all the callbacks of the type to be removed at the end of the vector - mLogCallbacks.erase(AZStd::remove_if(begin(mLogCallbacks), end(mLogCallbacks), [type](const LogCallback* callback) + m_logCallbacks.erase(AZStd::remove_if(begin(m_logCallbacks), end(m_logCallbacks), [type](const LogCallback* callback) { if (callback->GetType() == type) { @@ -125,15 +125,15 @@ namespace MCore // remove all log callbacks from the stack void LogManager::ClearLogCallbacks() { - LockGuard lock(mMutex); + LockGuard lock(m_mutex); // get rid of the callbacks - for (auto* logCallback : mLogCallbacks) + for (auto* logCallback : m_logCallbacks) { delete logCallback; } - mLogCallbacks.clear(); + m_logCallbacks.clear(); // collect the enabled log levels InitLogLevels(); @@ -143,13 +143,13 @@ namespace MCore // retrieve a pointer to the given log callback LogCallback* LogManager::GetLogCallback(size_t index) { - return mLogCallbacks[index]; + return m_logCallbacks[index]; } // return number of log callbacks in the stack size_t LogManager::GetNumLogCallbacks() const { - return mLogCallbacks.size(); + return m_logCallbacks.size(); } // collect all enabled log levels @@ -159,12 +159,12 @@ namespace MCore int32 logLevels = LogCallback::LOGLEVEL_NONE; // enable all log levels that are enabled by any of the callbacks - for (auto* logCallback : mLogCallbacks) + for (auto* logCallback : m_logCallbacks) { logLevels |= (int32)logCallback->GetLogLevels(); } - mLogLevels = (LogCallback::ELogLevel)logLevels; + m_logLevels = (LogCallback::ELogLevel)logLevels; } @@ -172,23 +172,23 @@ namespace MCore void LogManager::SetLogLevels(LogCallback::ELogLevel logLevels) { // iterate through all log callbacks and set it to the given log levels - for (auto* logCallback : mLogCallbacks) + for (auto* logCallback : m_logCallbacks) { logCallback->SetLogLevels(logLevels); } // force set the log manager's log levels to the given one as well - mLogLevels = logLevels; + m_logLevels = logLevels; } // the main logging method void LogManager::LogMessage(const char* message, LogCallback::ELogLevel logLevel) { - LockGuard lock(mMutex); + LockGuard lock(m_mutex); // iterate through all callbacks - for (auto* logCallback : mLogCallbacks) + for (auto* logCallback : m_logCallbacks) { if (logCallback->GetLogLevels() & logLevel) { @@ -202,9 +202,9 @@ namespace MCore size_t LogManager::FindLogCallback(LogCallback* callback) const { // iterate through all callbacks - for (size_t i = 0; i < mLogCallbacks.size(); ++i) + for (size_t i = 0; i < m_logCallbacks.size(); ++i) { - if (mLogCallbacks[i] == callback) + if (m_logCallbacks[i] == callback) { return i; } @@ -216,7 +216,7 @@ namespace MCore void LogFatalError(const char* what, ...) { - LockGuard lock(LogManager::mGlobalMutex); + LockGuard lock(LogManager::s_globalMutex); // skip the va list construction in case that the message won't be logged by any of the callbacks if (GetLogManager().GetLogLevels() & LogCallback::LOGLEVEL_FATAL) @@ -236,7 +236,7 @@ namespace MCore void LogError(const char* what, ...) { - LockGuard lock(LogManager::mGlobalMutex); + LockGuard lock(LogManager::s_globalMutex); // skip the va list construction in case that the message won't be logged by any of the callbacks if (GetLogManager().GetLogLevels() & LogCallback::LOGLEVEL_ERROR) @@ -256,7 +256,7 @@ namespace MCore void LogWarning(const char* what, ...) { - LockGuard lock(LogManager::mGlobalMutex); + LockGuard lock(LogManager::s_globalMutex); // skip the va list construction in case that the message won't be logged by any of the callbacks if (GetLogManager().GetLogLevels() & LogCallback::LOGLEVEL_WARNING) @@ -276,7 +276,7 @@ namespace MCore void LogInfo(const char* what, ...) { - LockGuard lock(LogManager::mGlobalMutex); + LockGuard lock(LogManager::s_globalMutex); // skip the va list construction in case that the message won't be logged by any of the callbacks if (GetLogManager().GetLogLevels() & LogCallback::LOGLEVEL_INFO) @@ -296,7 +296,7 @@ namespace MCore void LogDetailedInfo(const char* what, ...) { - LockGuard lock(LogManager::mGlobalMutex); + LockGuard lock(LogManager::s_globalMutex); // skip the va list construction in case that the message won't be logged by any of the callbacks if (GetLogManager().GetLogLevels() & LogCallback::LOGLEVEL_DETAILEDINFO) @@ -316,7 +316,7 @@ namespace MCore void LogDebug(const char* what, ...) { - LockGuard lock(LogManager::mGlobalMutex); + LockGuard lock(LogManager::s_globalMutex); // skip the va list construction in case that the message won't be logged by any of the callbacks if (GetLogManager().GetLogLevels() & LogCallback::LOGLEVEL_DEBUG) @@ -335,7 +335,7 @@ namespace MCore void LogDebugMsg(const char* msg) { - LockGuard lock(LogManager::mGlobalMutex); + LockGuard lock(LogManager::s_globalMutex); // skip the va list construction in case that the message won't be logged by any of the callbacks if (GetLogManager().GetLogLevels() & LogCallback::LOGLEVEL_DEBUG) diff --git a/Gems/EMotionFX/Code/MCore/Source/LogManager.h b/Gems/EMotionFX/Code/MCore/Source/LogManager.h index d5e2316436..864aa50219 100644 --- a/Gems/EMotionFX/Code/MCore/Source/LogManager.h +++ b/Gems/EMotionFX/Code/MCore/Source/LogManager.h @@ -75,7 +75,7 @@ namespace MCore * To check if a log level is enabled use logical bitwise and comparison, example: if (GetLogLevels() & LOGLEVEL_EXAMPLE). * @result The log levels packed as bit flags which are enabled on the callback. */ - MCORE_INLINE ELogLevel GetLogLevels() const { return mLogLevels; } + MCORE_INLINE ELogLevel GetLogLevels() const { return m_logLevels; } /** * Set the log levels this callback will accept and pass through. @@ -86,7 +86,7 @@ namespace MCore void SetLogLevels(ELogLevel logLevels); protected: - ELogLevel mLogLevels; /**< The log levels that will pass the callback. All messages from log flags which are disabled won't be logged. The default value of the log level will be LOGLEVEL_DEFAULT. */ + ELogLevel m_logLevels; /**< The log levels that will pass the callback. All messages from log flags which are disabled won't be logged. The default value of the log level will be LOGLEVEL_DEFAULT. */ }; //---------------------------------------------------------------------------- @@ -232,7 +232,7 @@ namespace MCore * To check if a log level is enabled by one of the callbacks use logical bitwise and comparison, example: if (GetLogLevels() & LOGLEVEL_EXAMPLE). * @result The log levels packed as bit flags which are enabled on the callback. */ - MCORE_INLINE LogCallback::ELogLevel GetLogLevels() const { return mLogLevels; } + MCORE_INLINE LogCallback::ELogLevel GetLogLevels() const { return m_logLevels; } /** * Iterate over all callbacks and collect the enabled log levels. @@ -249,11 +249,11 @@ namespace MCore void LogMessage(const char* message, LogCallback::ELogLevel logLevel = LogCallback::LOGLEVEL_INFO); public: - static Mutex mGlobalMutex; /**< The multithread mutex, used by some global Log functions. */ + static Mutex s_globalMutex; /**< The multithread mutex, used by some global Log functions. */ private: - AZStd::vector mLogCallbacks; /**< A collection of log callback instances. */ - LogCallback::ELogLevel mLogLevels; /**< The log levels that will pass one of the callbacks. All messages from log flags which are disabled won't be logged. */ - Mutex mMutex; /**< The mutex for logging locally. */ + AZStd::vector m_logCallbacks; /**< A collection of log callback instances. */ + LogCallback::ELogLevel m_logLevels; /**< The log levels that will pass one of the callbacks. All messages from log flags which are disabled won't be logged. */ + Mutex m_mutex; /**< The mutex for logging locally. */ }; } // namespace MCore diff --git a/Gems/EMotionFX/Code/MCore/Source/MCoreCommandManager.cpp b/Gems/EMotionFX/Code/MCore/Source/MCoreCommandManager.cpp index 657c5e0303..5cdd9c2600 100644 --- a/Gems/EMotionFX/Code/MCore/Source/MCoreCommandManager.cpp +++ b/Gems/EMotionFX/Code/MCore/Source/MCoreCommandManager.cpp @@ -17,15 +17,14 @@ namespace MCore { CommandManager::CommandHistoryEntry::CommandHistoryEntry(CommandGroup* group, Command* command, const CommandLine& parameters, size_t historyItemNr) { - mCommandGroup = group; - mExecutedCommand = command; - mParameters = parameters; + m_commandGroup = group; + m_executedCommand = command; + m_parameters = parameters; m_historyItemNr = historyItemNr; } CommandManager::CommandHistoryEntry::~CommandHistoryEntry() { - // remark: the mCommand and mCommandGroup are automatically deleted after popping from the history } AZStd::string CommandManager::CommandHistoryEntry::ToString(CommandGroup* group, Command* command, size_t historyItemNr) @@ -44,38 +43,38 @@ namespace MCore AZStd::string CommandManager::CommandHistoryEntry::ToString() const { - return ToString(mCommandGroup, mExecutedCommand, m_historyItemNr); + return ToString(m_commandGroup, m_executedCommand, m_historyItemNr); } CommandManager::CommandManager() { - mCommands.reserve(128); + m_commands.reserve(128); // set default values - mMaxHistoryEntries = 100; - mHistoryIndex = -1; + m_maxHistoryEntries = 100; + m_historyIndex = -1; m_totalNumHistoryItems = 0; // preallocate history entries - mCommandHistory.reserve(mMaxHistoryEntries); + m_commandHistory.reserve(m_maxHistoryEntries); m_commandsInExecution = 0; } CommandManager::~CommandManager() { - for (auto element : mRegisteredCommands) + for (auto element : m_registeredCommands) { Command* command = element.second; delete command; } - mRegisteredCommands.clear(); + m_registeredCommands.clear(); // remove all callbacks RemoveCallbacks(); // destroy the command history - while (!mCommandHistory.empty()) + while (!m_commandHistory.empty()) { PopCommandHistory(); } @@ -85,93 +84,93 @@ namespace MCore void CommandManager::PushCommandHistory(CommandGroup* commandGroup) { // if we reached the maximum number of history entries remove the oldest one - if (mCommandHistory.size() >= mMaxHistoryEntries) + if (m_commandHistory.size() >= m_maxHistoryEntries) { PopCommandHistory(); - mHistoryIndex = static_cast(mCommandHistory.size()) - 1; + m_historyIndex = static_cast(m_commandHistory.size()) - 1; } - if (!mCommandHistory.empty()) + if (!m_commandHistory.empty()) { // remove unneeded commandsnumToRemove - const size_t numToRemove = mCommandHistory.size() - mHistoryIndex - 1; - for (CommandManagerCallback* managerCallback : mCallbacks) + const size_t numToRemove = m_commandHistory.size() - m_historyIndex - 1; + for (CommandManagerCallback* managerCallback : m_callbacks) { for (size_t a = 0; a < numToRemove; ++a) { - managerCallback->OnRemoveCommand(mHistoryIndex + 1); + managerCallback->OnRemoveCommand(m_historyIndex + 1); } } for (size_t a = 0; a < numToRemove; ++a) { - delete mCommandHistory[mHistoryIndex + 1].mExecutedCommand; - delete mCommandHistory[mHistoryIndex + 1].mCommandGroup; - mCommandHistory.erase(mCommandHistory.begin() + mHistoryIndex + 1); + delete m_commandHistory[m_historyIndex + 1].m_executedCommand; + delete m_commandHistory[m_historyIndex + 1].m_commandGroup; + m_commandHistory.erase(m_commandHistory.begin() + m_historyIndex + 1); } } // resize the command history - mCommandHistory.resize(mHistoryIndex + 1); + m_commandHistory.resize(m_historyIndex + 1); // add a command history entry m_totalNumHistoryItems++; - mCommandHistory.push_back(CommandHistoryEntry(commandGroup, nullptr, CommandLine(), m_totalNumHistoryItems)); + m_commandHistory.push_back(CommandHistoryEntry(commandGroup, nullptr, CommandLine(), m_totalNumHistoryItems)); // increase the history index - mHistoryIndex++; + m_historyIndex++; // perform callbacks - for (CommandManagerCallback* managerCallback : mCallbacks) + for (CommandManagerCallback* managerCallback : m_callbacks) { - managerCallback->OnAddCommandToHistory(mHistoryIndex, commandGroup, nullptr, CommandLine()); + managerCallback->OnAddCommandToHistory(m_historyIndex, commandGroup, nullptr, CommandLine()); } } // save command in the history void CommandManager::PushCommandHistory(Command* command, const CommandLine& parameters) { - if (!mCommandHistory.empty()) + if (!m_commandHistory.empty()) { // if we reached the maximum number of history entries remove the oldest one - if (mCommandHistory.size() >= mMaxHistoryEntries) + if (m_commandHistory.size() >= m_maxHistoryEntries) { PopCommandHistory(); - mHistoryIndex = static_cast(mCommandHistory.size()) - 1; + m_historyIndex = static_cast(m_commandHistory.size()) - 1; } // remove unneeded commands - const size_t numToRemove = mCommandHistory.size() - mHistoryIndex - 1; - for (CommandManagerCallback* managerCallback : mCallbacks) + const size_t numToRemove = m_commandHistory.size() - m_historyIndex - 1; + for (CommandManagerCallback* managerCallback : m_callbacks) { for (size_t a = 0; a < numToRemove; ++a) { - managerCallback->OnRemoveCommand(mHistoryIndex + 1); + managerCallback->OnRemoveCommand(m_historyIndex + 1); } } for (size_t a = 0; a < numToRemove; ++a) { - delete mCommandHistory[mHistoryIndex + 1].mExecutedCommand; - delete mCommandHistory[mHistoryIndex + 1].mCommandGroup; - mCommandHistory.erase(mCommandHistory.begin() + mHistoryIndex + 1); + delete m_commandHistory[m_historyIndex + 1].m_executedCommand; + delete m_commandHistory[m_historyIndex + 1].m_commandGroup; + m_commandHistory.erase(m_commandHistory.begin() + m_historyIndex + 1); } } // resize the command history - mCommandHistory.resize(mHistoryIndex + 1); + m_commandHistory.resize(m_historyIndex + 1); // add a command history entry m_totalNumHistoryItems++; - mCommandHistory.push_back(CommandHistoryEntry(nullptr, command, parameters, m_totalNumHistoryItems)); + m_commandHistory.push_back(CommandHistoryEntry(nullptr, command, parameters, m_totalNumHistoryItems)); // increase the history index - mHistoryIndex++; + m_historyIndex++; // perform callbacks - for (CommandManagerCallback* managerCallback : mCallbacks) + for (CommandManagerCallback* managerCallback : m_callbacks) { - managerCallback->OnAddCommandToHistory(mHistoryIndex, nullptr, command, parameters); + managerCallback->OnAddCommandToHistory(m_historyIndex, nullptr, command, parameters); } } @@ -179,23 +178,23 @@ namespace MCore void CommandManager::PopCommandHistory() { // perform callbacks - for (CommandManagerCallback* managerCallback : mCallbacks) + for (CommandManagerCallback* managerCallback : m_callbacks) { managerCallback->OnRemoveCommand(0); } // destroy the command and remove it from the command history - Command* command = mCommandHistory.front().mExecutedCommand; + Command* command = m_commandHistory.front().m_executedCommand; if (command) { delete command; } else { - delete mCommandHistory.front().mCommandGroup; + delete m_commandHistory.front().m_commandGroup; } - mCommandHistory.erase(mCommandHistory.begin()); + m_commandHistory.erase(m_commandHistory.begin()); } bool CommandManager::ExecuteCommand(const AZStd::string& command, AZStd::string& outCommandResult, bool addToHistory, Command** outExecutedCommand, CommandLine* outExecutedParameters, bool callFromCommandGroup, bool clearErrors, bool handleErrors) @@ -456,7 +455,7 @@ namespace MCore ++m_commandsInExecution; // execute command manager callbacks - for (CommandManagerCallback* managerCallback : mCallbacks) + for (CommandManagerCallback* managerCallback : m_callbacks) { managerCallback->OnPreExecuteCommandGroup(&commandGroup, false); } @@ -581,25 +580,25 @@ namespace MCore delete newGroup; // execute command manager callbacks - for (CommandManagerCallback* managerCallback : mCallbacks) + for (CommandManagerCallback* managerCallback : m_callbacks) { managerCallback->OnPostExecuteCommandGroup(&commandGroup, false); } // Let the callbacks handle error reporting (e.g. show an error report window). - if (handleErrors && !mErrors.empty()) + if (handleErrors && !m_errors.empty()) { // Execute error report callbacks. - for (CommandManagerCallback* managerCallback : mCallbacks) + for (CommandManagerCallback* managerCallback : m_callbacks) { - managerCallback->OnShowErrorReport(mErrors); + managerCallback->OnShowErrorReport(m_errors); } } // Clear errors after reporting if specified. if (clearErrors) { - mErrors.clear(); + m_errors.clear(); } --m_commandsInExecution; @@ -642,19 +641,19 @@ namespace MCore } // execute command manager callbacks - for (CommandManagerCallback* managerCallback : mCallbacks) + for (CommandManagerCallback* managerCallback : m_callbacks) { managerCallback->OnPostExecuteCommandGroup(&commandGroup, true); } // Let the callbacks handle error reporting (e.g. show an error report window). - const bool errorsOccured = !mErrors.empty(); + const bool errorsOccured = !m_errors.empty(); if (handleErrors && errorsOccured) { // Execute error report callbacks. - for (CommandManagerCallback* managerCallback : mCallbacks) + for (CommandManagerCallback* managerCallback : m_callbacks) { - managerCallback->OnShowErrorReport(mErrors); + managerCallback->OnShowErrorReport(m_errors); } } @@ -665,7 +664,7 @@ namespace MCore // Clear errors after reporting if specified. if (clearErrors) { - mErrors.clear(); + m_errors.clear(); } --m_commandsInExecution; @@ -700,7 +699,7 @@ namespace MCore if (preUndo) { - for (CommandManagerCallback* managerCallback : mCallbacks) + for (CommandManagerCallback* managerCallback : m_callbacks) { managerCallback->OnPreUndoCommand(command, parameters); } @@ -717,7 +716,7 @@ namespace MCore if (!preUndo) { - for (CommandManagerCallback* managerCallback : mCallbacks) + for (CommandManagerCallback* managerCallback : m_callbacks) { managerCallback->OnPostUndoCommand(command, parameters); } @@ -762,15 +761,15 @@ namespace MCore bool CommandManager::Undo(AZStd::string& outCommandResult) { // check if we can undo - if (mCommandHistory.empty() && mHistoryIndex >= 0) + if (m_commandHistory.empty() && m_historyIndex >= 0) { outCommandResult = "Cannot undo command. The command history is empty"; return false; } // get the last called command from the command history - const CommandHistoryEntry& lastEntry = mCommandHistory[mHistoryIndex]; - Command* command = lastEntry.mExecutedCommand; + const CommandHistoryEntry& lastEntry = m_commandHistory[m_historyIndex]; + Command* command = lastEntry.m_executedCommand; ++m_commandsInExecution; @@ -779,22 +778,22 @@ namespace MCore if (command) { // execute pre-undo callbacks - ExecuteUndoCallbacks(command, lastEntry.mParameters, true); + ExecuteUndoCallbacks(command, lastEntry.m_parameters, true); // undo the command, get the result and reset it - result = command->Undo(lastEntry.mParameters, outCommandResult); + result = command->Undo(lastEntry.m_parameters, outCommandResult); // execute post-undo callbacks - ExecuteUndoCallbacks(command, lastEntry.mParameters, false); + ExecuteUndoCallbacks(command, lastEntry.m_parameters, false); } // we are dealing with a command group else { - CommandGroup* group = lastEntry.mCommandGroup; + CommandGroup* group = lastEntry.m_commandGroup; MCORE_ASSERT(group); // perform callbacks - for (CommandManagerCallback* managerCallback : mCallbacks) + for (CommandManagerCallback* managerCallback : m_callbacks) { managerCallback->OnPreExecuteCommandGroup(group, true); } @@ -827,29 +826,29 @@ namespace MCore } // perform callbacks - for (CommandManagerCallback* managerCallback : mCallbacks) + for (CommandManagerCallback* managerCallback : m_callbacks) { managerCallback->OnPostExecuteCommandGroup(group, result); } } // go one step back in the command history - mHistoryIndex--; + m_historyIndex--; // perform callbacks - for (CommandManagerCallback* managerCallback : mCallbacks) + for (CommandManagerCallback* managerCallback : m_callbacks) { - managerCallback->OnSetCurrentCommand(mHistoryIndex); + managerCallback->OnSetCurrentCommand(m_historyIndex); } // Let the callbacks handle error reporting (e.g. show an error report window). - if (!mErrors.empty()) + if (!m_errors.empty()) { - for (CommandManagerCallback* managerCallback : mCallbacks) + for (CommandManagerCallback* managerCallback : m_callbacks) { - managerCallback->OnShowErrorReport(mErrors); + managerCallback->OnShowErrorReport(m_errors); } - mErrors.clear(); + m_errors.clear(); } --m_commandsInExecution; @@ -860,23 +859,16 @@ namespace MCore // redo the last undoed command bool CommandManager::Redo(AZStd::string& outCommandResult) { - /* // check if there are still commands to undo in the history - if (mHistoryIndex >= mCommandHistory.GetLength()) - { - outCommandResult = "Cannot redo command. Either the history is empty or the history index is out of range."; - return false; - }*/ - // get the last called command from the command history - const CommandHistoryEntry& lastEntry = mCommandHistory[mHistoryIndex + 1]; + const CommandHistoryEntry& lastEntry = m_commandHistory[m_historyIndex + 1]; // if we just redo one single command bool result = true; - if (lastEntry.mExecutedCommand) + if (lastEntry.m_executedCommand) { // redo the command, get the result and reset it - result = ExecuteCommand(lastEntry.mExecutedCommand, - lastEntry.mParameters, + result = ExecuteCommand(lastEntry.m_executedCommand, + lastEntry.m_parameters, outCommandResult, /*addToHistory=*/false, /*callFromCommandGroup=*/false, @@ -888,10 +880,10 @@ namespace MCore else { ++m_commandsInExecution; - CommandGroup* group = lastEntry.mCommandGroup; + CommandGroup* group = lastEntry.m_commandGroup; AZ_Assert(group, "Cannot redo. Command group is not valid."); - for (CommandManagerCallback* managerCallback : mCallbacks) + for (CommandManagerCallback* managerCallback : m_callbacks) { managerCallback->OnPreExecuteCommandGroup(group, false); } @@ -917,29 +909,29 @@ namespace MCore } --m_commandsInExecution; - for (CommandManagerCallback* managerCallback : mCallbacks) + for (CommandManagerCallback* managerCallback : m_callbacks) { managerCallback->OnPostExecuteCommandGroup(group, result); } } // go one step forward in the command history - mHistoryIndex++; + m_historyIndex++; // perform callbacks - for (CommandManagerCallback* managerCallback : mCallbacks) + for (CommandManagerCallback* managerCallback : m_callbacks) { - managerCallback->OnSetCurrentCommand(mHistoryIndex); + managerCallback->OnSetCurrentCommand(m_historyIndex); } // Let the callbacks handle error reporting (e.g. show an error report window). - if (!mErrors.empty()) + if (!m_errors.empty()) { - for (CommandManagerCallback* managerCallback : mCallbacks) + for (CommandManagerCallback* managerCallback : m_callbacks) { - managerCallback->OnShowErrorReport(mErrors); + managerCallback->OnShowErrorReport(m_errors); } - mErrors.clear(); + m_errors.clear(); } return result; @@ -970,17 +962,17 @@ namespace MCore } // add the command to the hash table - mRegisteredCommands.insert(AZStd::make_pair(command->GetNameString(), command)); + m_registeredCommands.insert(AZStd::make_pair(command->GetNameString(), command)); // we're going to insert the command in a sorted way now bool found = false; - const size_t numCommands = mCommands.size(); + const size_t numCommands = m_commands.size(); for (size_t i = 0; i < numCommands; ++i) { - if (azstricmp(mCommands[i]->GetName(), command->GetName()) > 0) + if (azstricmp(m_commands[i]->GetName(), command->GetName()) > 0) { found = true; - mCommands.insert(mCommands.begin() + i, command); + m_commands.insert(m_commands.begin() + i, command); break; } } @@ -988,7 +980,7 @@ namespace MCore // if no insert location has been found, add it to the back of the array if (!found) { - mCommands.push_back(command); + m_commands.push_back(command); } // initialize the command syntax @@ -1000,8 +992,8 @@ namespace MCore Command* CommandManager::FindCommand(const AZStd::string& commandName) { - auto iterator = mRegisteredCommands.find(commandName); - if (iterator == mRegisteredCommands.end()) + auto iterator = m_registeredCommands.find(commandName); + if (iterator == m_registeredCommands.end()) { return nullptr; } @@ -1046,7 +1038,7 @@ namespace MCore } // execute command manager callbacks - for (CommandManagerCallback* managerCallback : mCallbacks) + for (CommandManagerCallback* managerCallback : m_callbacks) { managerCallback->OnPreExecuteCommand(nullptr, command, commandLine); } @@ -1081,25 +1073,25 @@ namespace MCore } // execute all post execute callbacks - for (CommandManagerCallback* managerCallback : mCallbacks) + for (CommandManagerCallback* managerCallback : m_callbacks) { managerCallback->OnPostExecuteCommand(nullptr, command, commandLine, result, outCommandResult); } // Let the callbacks handle error reporting (e.g. show an error report window). - if (handleErrors && !mErrors.empty()) + if (handleErrors && !m_errors.empty()) { // Execute error report callbacks. - for (CommandManagerCallback* managerCallback : mCallbacks) + for (CommandManagerCallback* managerCallback : m_callbacks) { - managerCallback->OnShowErrorReport(mErrors); + managerCallback->OnShowErrorReport(m_errors); } } // Clear errors after reporting if specified. if (clearErrors) { - mErrors.clear(); + m_errors.clear(); } #ifdef MCORE_COMMANDMANAGER_PERFORMANCE @@ -1124,14 +1116,14 @@ namespace MCore LogDetailedInfo("----------------------------------"); // get the number of entries in the command history - const size_t numHistoryEntries = mCommandHistory.size(); + const size_t numHistoryEntries = m_commandHistory.size(); LogDetailedInfo("Command History (%d entries) - oldest (top entry) to newest (bottom entry):", numHistoryEntries); // print the command history entries for (size_t i = 0; i < numHistoryEntries; ++i) { - AZStd::string text = AZStd::string::format("%.3zu: name='%s', num parameters=%zu", i, mCommandHistory[i].mExecutedCommand->GetName(), mCommandHistory[i].mParameters.GetNumParameters()); - if (i == mHistoryIndex) + AZStd::string text = AZStd::string::format("%.3zu: name='%s', num parameters=%zu", i, m_commandHistory[i].m_executedCommand->GetName(), m_commandHistory[i].m_parameters.GetNumParameters()); + if (i == m_historyIndex) { LogDetailedInfo("-> %s", text.c_str()); } @@ -1146,22 +1138,22 @@ namespace MCore void CommandManager::RemoveCallbacks() { - for (CommandManagerCallback* managerCallback : mCallbacks) + for (CommandManagerCallback* managerCallback : m_callbacks) { delete managerCallback; } - mCallbacks.clear(); + m_callbacks.clear(); } void CommandManager::RegisterCallback(CommandManagerCallback* callback) { - mCallbacks.push_back(callback); + m_callbacks.push_back(callback); } void CommandManager::RemoveCallback(CommandManagerCallback* callback, bool delFromMem) { - mCallbacks.erase(AZStd::remove(mCallbacks.begin(), mCallbacks.end(), callback), mCallbacks.end()); + m_callbacks.erase(AZStd::remove(m_callbacks.begin(), m_callbacks.end(), callback), m_callbacks.end()); if (delFromMem) { @@ -1171,83 +1163,83 @@ namespace MCore size_t CommandManager::GetNumCallbacks() const { - return mCallbacks.size(); + return m_callbacks.size(); } CommandManagerCallback* CommandManager::GetCallback(size_t index) { - return mCallbacks[index]; + return m_callbacks[index]; } // set the max num history items void CommandManager::SetMaxHistoryItems(size_t maxItems) { maxItems = AZStd::max(size_t{1}, maxItems); - mMaxHistoryEntries = maxItems; + m_maxHistoryEntries = maxItems; - while (mCommandHistory.size() > mMaxHistoryEntries) + while (m_commandHistory.size() > m_maxHistoryEntries) { PopCommandHistory(); - mHistoryIndex = static_cast(mCommandHistory.size()) - 1; + m_historyIndex = static_cast(m_commandHistory.size()) - 1; } } size_t CommandManager::GetMaxHistoryItems() const { - return mMaxHistoryEntries; + return m_maxHistoryEntries; } ptrdiff_t CommandManager::GetHistoryIndex() const { - return mHistoryIndex; + return m_historyIndex; } size_t CommandManager::GetNumHistoryItems() const { - return mCommandHistory.size(); + return m_commandHistory.size(); } const CommandManager::CommandHistoryEntry& CommandManager::GetHistoryItem(size_t index) const { - return mCommandHistory[index]; + return m_commandHistory[index]; } Command* CommandManager::GetHistoryCommand(size_t historyIndex) { - return mCommandHistory[historyIndex].mExecutedCommand; + return m_commandHistory[historyIndex].m_executedCommand; } void CommandManager::ClearHistory() { // clear the command history - while (!mCommandHistory.empty()) + while (!m_commandHistory.empty()) { PopCommandHistory(); } // reset the history index - mHistoryIndex = -1; + m_historyIndex = -1; } const CommandLine& CommandManager::GetHistoryCommandLine(size_t historyIndex) const { - return mCommandHistory[historyIndex].mParameters; + return m_commandHistory[historyIndex].m_parameters; } size_t CommandManager::GetNumRegisteredCommands() const { - return mCommands.size(); + return m_commands.size(); } Command* CommandManager::GetCommand(size_t index) { - return mCommands[index]; + return m_commands[index]; } // delete the given callback from all commands void CommandManager::RemoveCommandCallback(Command::Callback* callback, bool delFromMem) { - for (Command* command : mCommands) + for (Command* command : m_commands) { command->RemoveCallback(callback, false); // false = don't delete from memory } @@ -1297,18 +1289,18 @@ namespace MCore bool CommandManager::ShowErrorReport() { // Let the callbacks handle error reporting (e.g. show an error report window). - const bool errorsOccured = !mErrors.empty(); + const bool errorsOccured = !m_errors.empty(); if (errorsOccured) { // Execute error report callbacks. - for (CommandManagerCallback* managerCallback : mCallbacks) + for (CommandManagerCallback* managerCallback : m_callbacks) { - managerCallback->OnShowErrorReport(mErrors); + managerCallback->OnShowErrorReport(m_errors); } } // clear errors after reporting - mErrors.clear(); + m_errors.clear(); return errorsOccured; } diff --git a/Gems/EMotionFX/Code/MCore/Source/MCoreCommandManager.h b/Gems/EMotionFX/Code/MCore/Source/MCoreCommandManager.h index 566c3d17fd..d59639dee5 100644 --- a/Gems/EMotionFX/Code/MCore/Source/MCoreCommandManager.h +++ b/Gems/EMotionFX/Code/MCore/Source/MCoreCommandManager.h @@ -38,9 +38,9 @@ namespace MCore struct MCORE_API CommandHistoryEntry { CommandHistoryEntry() - : mCommandGroup(nullptr) - , mExecutedCommand(nullptr) - , mParameters(nullptr) {} + : m_commandGroup(nullptr) + , m_executedCommand(nullptr) + , m_parameters(nullptr) {} /** * Extended Constructor. @@ -55,9 +55,9 @@ namespace MCore static AZStd::string ToString(CommandGroup* group, Command* command, size_t historyItemNr); AZStd::string ToString() const; - CommandGroup* mCommandGroup; /**< A pointer to the command group, or nullptr when no group is used (in that case it uses a single command). */ - Command* mExecutedCommand; /**< A pointer to the command object, or nullptr when no command is used (in that case it uses a group). */ - CommandLine mParameters; /**< The used command arguments, unused in case no command is used (in that case it uses a group). */ + CommandGroup* m_commandGroup; /**< A pointer to the command group, or nullptr when no group is used (in that case it uses a single command). */ + Command* m_executedCommand; /**< A pointer to the command object, or nullptr when no command is used (in that case it uses a group). */ + CommandLine m_parameters; /**< The used command arguments, unused in case no command is used (in that case it uses a group). */ size_t m_historyItemNr; /**< The global history item number. This number will neither change depending on the size of the history queue nor with undo/redo. */ }; @@ -280,8 +280,8 @@ namespace MCore * Add error message to the internal callback based error handling system. * @param[in] errorLine The error line to add to the internal error handler. */ - MCORE_INLINE void AddError(const char* errorLine) { mErrors.push_back(errorLine); } - MCORE_INLINE void AddError(const AZStd::string& errorLine) { mErrors.push_back(errorLine); } + MCORE_INLINE void AddError(const char* errorLine) { m_errors.push_back(errorLine); } + MCORE_INLINE void AddError(const AZStd::string& errorLine) { m_errors.push_back(errorLine); } /** * Checks if an error occurred and calls the error handling callbacks. @@ -296,13 +296,13 @@ namespace MCore bool IsExecuting() const { return m_commandsInExecution > 0; } protected: - AZStd::unordered_map mRegisteredCommands; /**< A hash table storing the command objects for fast command object access. */ - AZStd::vector mCommandHistory; /**< The command history stack for undo/redo functionality. */ - AZStd::vector mCallbacks; /**< The command manager callbacks. */ - AZStd::vector mErrors; /**< List of errors that happened during command execution. */ - AZStd::vector mCommands; /**< A flat array of registered commands, for easy traversal. */ - size_t mMaxHistoryEntries; /**< The maximum remembered commands in the command history. */ - ptrdiff_t mHistoryIndex; /**< The command history iterator. The current position in the undo/redo history. */ + AZStd::unordered_map m_registeredCommands; /**< A hash table storing the command objects for fast command object access. */ + AZStd::vector m_commandHistory; /**< The command history stack for undo/redo functionality. */ + AZStd::vector m_callbacks; /**< The command manager callbacks. */ + AZStd::vector m_errors; /**< List of errors that happened during command execution. */ + AZStd::vector m_commands; /**< A flat array of registered commands, for easy traversal. */ + size_t m_maxHistoryEntries; /**< The maximum remembered commands in the command history. */ + ptrdiff_t m_historyIndex; /**< The command history iterator. The current position in the undo/redo history. */ size_t m_totalNumHistoryItems; /**< The number of history items since the application start. This number will neither change depending on the size of the history queue nor with undo/redo. */ int m_commandsInExecution; /**< The number of commands currently in execution. */ diff --git a/Gems/EMotionFX/Code/MCore/Source/MCoreSystem.cpp b/Gems/EMotionFX/Code/MCore/Source/MCoreSystem.cpp index f981a825c4..e84c7a9ff7 100644 --- a/Gems/EMotionFX/Code/MCore/Source/MCoreSystem.cpp +++ b/Gems/EMotionFX/Code/MCore/Source/MCoreSystem.cpp @@ -27,10 +27,10 @@ namespace MCore Initializer::InitSettings::InitSettings() { - mMemAllocFunction = StandardAllocate; - mMemReallocFunction = StandardRealloc; - mMemFreeFunction = StandardFree; - mTrackMemoryUsage = false; // do not track memory usage on default, for maximum performance and pretty much zero tracking overhead + m_memAllocFunction = StandardAllocate; + m_memReallocFunction = StandardRealloc; + m_memFreeFunction = StandardFree; + m_trackMemoryUsage = false; // do not track memory usage on default, for maximum performance and pretty much zero tracking overhead } // static main init method @@ -47,7 +47,7 @@ namespace MCore { // create the main core object using placement new gMCore = AZ::Environment::CreateVariable(kMCoreInstanceVarName); - gMCore.Set(new(realSettings->mMemAllocFunction(sizeof(MCoreSystem), MCORE_MEMCATEGORY_MCORESYSTEM, 0, MCORE_FILE, MCORE_LINE))MCoreSystem()); + gMCore.Set(new(realSettings->m_memAllocFunction(sizeof(MCoreSystem), MCORE_MEMCATEGORY_MCORESYSTEM, 0, MCORE_FILE, MCORE_LINE))MCoreSystem()); } else { @@ -81,19 +81,19 @@ namespace MCore // constructor MCoreSystem::MCoreSystem() - : mAllocateFunction(StandardAllocate) - , mReallocFunction(StandardRealloc) - , mFreeFunction(StandardFree) + : m_allocateFunction(StandardAllocate) + , m_reallocFunction(StandardRealloc) + , m_freeFunction(StandardFree) { - mLogManager = nullptr; - mIDGenerator = nullptr; - mStringIdPool = nullptr; - mAttributeFactory = nullptr; - mMemoryTracker = nullptr; - mMemTempBuffer = nullptr; - mMemTempBufferSize = 0; - mTrackMemory = true; - mMemoryMutex = new Mutex(); + m_logManager = nullptr; + m_idGenerator = nullptr; + m_stringIdPool = nullptr; + m_attributeFactory = nullptr; + m_memoryTracker = nullptr; + m_memTempBuffer = nullptr; + m_memTempBufferSize = 0; + m_trackMemory = true; + m_memoryMutex = new Mutex(); } @@ -107,45 +107,45 @@ namespace MCore // init the mcore system bool MCoreSystem::Init(const MCore::Initializer::InitSettings& settings) { - if (settings.mMemAllocFunction) + if (settings.m_memAllocFunction) { - mAllocateFunction = settings.mMemAllocFunction; + m_allocateFunction = settings.m_memAllocFunction; } else { - mAllocateFunction = StandardAllocate; + m_allocateFunction = StandardAllocate; } - if (settings.mMemReallocFunction) + if (settings.m_memReallocFunction) { - mReallocFunction = settings.mMemReallocFunction; + m_reallocFunction = settings.m_memReallocFunction; } else { - mReallocFunction = StandardRealloc; + m_reallocFunction = StandardRealloc; } - if (settings.mMemFreeFunction) + if (settings.m_memFreeFunction) { - mFreeFunction = settings.mMemFreeFunction; + m_freeFunction = settings.m_memFreeFunction; } else { - mFreeFunction = StandardFree; + m_freeFunction = StandardFree; } // allocate new objects - mMemoryTracker = new MemoryTracker(); - mTrackMemory = settings.mTrackMemoryUsage; - mLogManager = new LogManager(); - mIDGenerator = new IDGenerator(); - mStringIdPool = new StringIdPool(); - mAttributeFactory = new AttributeFactory(); - mMemTempBufferSize = 256 * 1024; - mMemTempBuffer = Allocate(mMemTempBufferSize, MCORE_MEMCATEGORY_SYSTEM);// 256 kb - MCORE_ASSERT(mMemTempBuffer); + m_memoryTracker = new MemoryTracker(); + m_trackMemory = settings.m_trackMemoryUsage; + m_logManager = new LogManager(); + m_idGenerator = new IDGenerator(); + m_stringIdPool = new StringIdPool(); + m_attributeFactory = new AttributeFactory(); + m_memTempBufferSize = 256 * 1024; + m_memTempBuffer = Allocate(m_memTempBufferSize, MCORE_MEMCATEGORY_SYSTEM);// 256 kb + MCORE_ASSERT(m_memTempBuffer); - if (mTrackMemory) + if (m_trackMemory) { - RegisterMemoryCategories(*mMemoryTracker); + RegisterMemoryCategories(*m_memoryTracker); } return true; @@ -156,41 +156,41 @@ namespace MCore void MCoreSystem::Shutdown() { // free any mem temp buffer - MCore::Free(mMemTempBuffer); - mMemTempBuffer = nullptr; - mMemTempBufferSize = 0; + MCore::Free(m_memTempBuffer); + m_memTempBuffer = nullptr; + m_memTempBufferSize = 0; // shutdown the log manager - delete mLogManager; - mLogManager = nullptr; + delete m_logManager; + m_logManager = nullptr; // delete the ID generator - delete mIDGenerator; - mIDGenerator = nullptr; + delete m_idGenerator; + m_idGenerator = nullptr; // Delete the string based ID generator. - delete mStringIdPool; - mStringIdPool = nullptr; + delete m_stringIdPool; + m_stringIdPool = nullptr; // delete the attribute factory - delete mAttributeFactory; - mAttributeFactory = nullptr; + delete m_attributeFactory; + m_attributeFactory = nullptr; // Clear the memory of the file system secure save path. - FileSystem::mSecureSavePath.clear(); + FileSystem::s_secureSavePath.clear(); // log memory leaks - if (mTrackMemory) + if (m_trackMemory) { - mMemoryTracker->LogLeaks(); + m_memoryTracker->LogLeaks(); } // delete the memory tracker - delete mMemoryTracker; - mMemoryTracker = nullptr; + delete m_memoryTracker; + m_memoryTracker = nullptr; - delete mMemoryMutex; - mMemoryMutex = nullptr; + delete m_memoryMutex; + m_memoryMutex = nullptr; } @@ -198,25 +198,25 @@ namespace MCore void MCoreSystem::MemTempBufferAssureSize(size_t numBytes) { // if the buffer is already big enough, we can just return - if (mMemTempBufferSize >= numBytes) + if (m_memTempBufferSize >= numBytes) { return; } // resize the buffer (make it bigger) - mMemTempBuffer = Realloc(mMemTempBuffer, numBytes, MCORE_MEMCATEGORY_SYSTEM); - MCORE_ASSERT(mMemTempBuffer); + m_memTempBuffer = Realloc(m_memTempBuffer, numBytes, MCORE_MEMCATEGORY_SYSTEM); + MCORE_ASSERT(m_memTempBuffer); - mMemTempBufferSize = numBytes; + m_memTempBufferSize = numBytes; } // free the temp buffer void MCoreSystem::MemTempBufferFree() { - MCore::Free(mMemTempBuffer); - mMemTempBuffer = nullptr; - mMemTempBufferSize = 0; + MCore::Free(m_memTempBuffer); + m_memTempBuffer = nullptr; + m_memTempBufferSize = 0; } diff --git a/Gems/EMotionFX/Code/MCore/Source/MCoreSystem.h b/Gems/EMotionFX/Code/MCore/Source/MCoreSystem.h index 11fdc79988..496198c430 100644 --- a/Gems/EMotionFX/Code/MCore/Source/MCoreSystem.h +++ b/Gems/EMotionFX/Code/MCore/Source/MCoreSystem.h @@ -38,10 +38,10 @@ namespace MCore public: struct MCORE_API InitSettings { - AllocateCallback mMemAllocFunction; /**< The memory allocation function, defaults to nullptr, which means the standard malloc function will be used. */ - ReallocCallback mMemReallocFunction; /**< The memory reallocation function, defaults to nullptr, which means the standard realloc function will be used. */ - FreeCallback mMemFreeFunction; /**< The memory free function, defaults to nullptr, which means the standard free function will be used. */ - bool mTrackMemoryUsage; /**< Enable this to track memory usage statistics. This has a bit of an impact on memory allocation and release speed and memory usage though. You should really only use this in debug mode. On default it is disabled. */ + AllocateCallback m_memAllocFunction; /**< The memory allocation function, defaults to nullptr, which means the standard malloc function will be used. */ + ReallocCallback m_memReallocFunction; /**< The memory reallocation function, defaults to nullptr, which means the standard realloc function will be used. */ + FreeCallback m_memFreeFunction; /**< The memory free function, defaults to nullptr, which means the standard free function will be used. */ + bool m_trackMemoryUsage; /**< Enable this to track memory usage statistics. This has a bit of an impact on memory allocation and release speed and memory usage though. You should really only use this in debug mode. On default it is disabled. */ InitSettings(); }; @@ -80,59 +80,59 @@ namespace MCore * Get the log manager. * @result A reference to the log manager. */ - MCORE_INLINE LogManager& GetLogManager() { return *mLogManager; } + MCORE_INLINE LogManager& GetLogManager() { return *m_logManager; } /** * Get the ID generator. * @result A reference to the ID generator. */ - MCORE_INLINE IDGenerator& GetIDGenerator() { return *mIDGenerator; } + MCORE_INLINE IDGenerator& GetIDGenerator() { return *m_idGenerator; } /** * Get the string based ID generator. * @result A reference to the string based ID generator. */ - MCORE_INLINE StringIdPool& GetStringIdPool() { return *mStringIdPool; } + MCORE_INLINE StringIdPool& GetStringIdPool() { return *m_stringIdPool; } /** * Get the attribute factory. * @result A reference to the attribute factory, which is used to create attributes of a certain type. */ - MCORE_INLINE AttributeFactory& GetAttributeFactory() { return *mAttributeFactory; } + MCORE_INLINE AttributeFactory& GetAttributeFactory() { return *m_attributeFactory; } /** * Get the memory tracker. * @result A reference to the memory tracker, which can be used to track memory allocations and usage. */ - MCORE_INLINE MemoryTracker& GetMemoryTracker() { return *mMemoryTracker; } - MCORE_INLINE bool GetIsTrackingMemory() const { return mTrackMemory; } + MCORE_INLINE MemoryTracker& GetMemoryTracker() { return *m_memoryTracker; } + MCORE_INLINE bool GetIsTrackingMemory() const { return m_trackMemory; } - MCORE_INLINE void* GetMemTempBuffer() { return mMemTempBuffer; } - MCORE_INLINE size_t GetMemTempBufferSize() const { return mMemTempBufferSize; } + MCORE_INLINE void* GetMemTempBuffer() { return m_memTempBuffer; } + MCORE_INLINE size_t GetMemTempBufferSize() const { return m_memTempBufferSize; } void MemTempBufferAssureSize(size_t numBytes); void MemTempBufferFree(); void RegisterMemoryCategories(MemoryTracker& memTracker); - MCORE_INLINE Mutex& GetMemoryMutex() { return *mMemoryMutex; } + MCORE_INLINE Mutex& GetMemoryMutex() { return *m_memoryMutex; } - MCORE_INLINE AllocateCallback GetAllocateFunction() { return mAllocateFunction; } - MCORE_INLINE ReallocCallback GetReallocFunction() { return mReallocFunction; } - MCORE_INLINE FreeCallback GetFreeFunction() { return mFreeFunction; } + MCORE_INLINE AllocateCallback GetAllocateFunction() { return m_allocateFunction; } + MCORE_INLINE ReallocCallback GetReallocFunction() { return m_reallocFunction; } + MCORE_INLINE FreeCallback GetFreeFunction() { return m_freeFunction; } private: - LogManager* mLogManager; /**< The log manager. */ - IDGenerator* mIDGenerator; /**< The ID generator. */ - StringIdPool* mStringIdPool; /**< The string based ID generator. */ - AttributeFactory* mAttributeFactory; /**< The attribute factory. */ - MemoryTracker* mMemoryTracker; /**< The memory tracker. */ - Mutex* mMemoryMutex; - AllocateCallback mAllocateFunction; - ReallocCallback mReallocFunction; - FreeCallback mFreeFunction; - void* mMemTempBuffer; /**< A buffer with temp memory, used by the MCore::AlignedRealloc, to assure data integrity after reallocating memory. */ - size_t mMemTempBufferSize; /**< The size in bytes, of the MemTempBuffer. */ - bool mTrackMemory; /**< Check if we want to track memory or not. */ + LogManager* m_logManager; /**< The log manager. */ + IDGenerator* m_idGenerator; /**< The ID generator. */ + StringIdPool* m_stringIdPool; /**< The string based ID generator. */ + AttributeFactory* m_attributeFactory; /**< The attribute factory. */ + MemoryTracker* m_memoryTracker; /**< The memory tracker. */ + Mutex* m_memoryMutex; + AllocateCallback m_allocateFunction; + ReallocCallback m_reallocFunction; + FreeCallback m_freeFunction; + void* m_memTempBuffer; /**< A buffer with temp memory, used by the MCore::AlignedRealloc, to assure data integrity after reallocating memory. */ + size_t m_memTempBufferSize; /**< The size in bytes, of the MemTempBuffer. */ + bool m_trackMemory; /**< Check if we want to track memory or not. */ /** * The constructor. diff --git a/Gems/EMotionFX/Code/MCore/Source/Matrix4.cpp b/Gems/EMotionFX/Code/MCore/Source/Matrix4.cpp index 229f67ec0c..f454df04ab 100644 --- a/Gems/EMotionFX/Code/MCore/Source/Matrix4.cpp +++ b/Gems/EMotionFX/Code/MCore/Source/Matrix4.cpp @@ -86,9 +86,9 @@ namespace MCore Matrix r; #if (AZ_TRAIT_USE_PLATFORM_SIMD_SSE && defined(MCORE_MATRIX_ROWMAJOR)) - const float* m = right.m16; - const float* n = m16; - float* t = r.m16; + const float* m = right.m_m16; + const float* n = m_m16; + float* t = r.m_m16; __m128 x0; __m128 x1; @@ -211,9 +211,9 @@ namespace MCore Matrix& Matrix::operator *= (const Matrix& right) { #if (AZ_TRAIT_USE_PLATFORM_SIMD_SSE && defined(MCORE_MATRIX_ROWMAJOR)) - const float* m = right.m16; - const float* n = m16; - float* t = this->m16; + const float* m = right.m_m16; + const float* n = m_m16; + float* t = this->m_m16; __m128 x0; __m128 x1; @@ -687,9 +687,9 @@ namespace MCore void Matrix::MultMatrix(const Matrix& right) { #if (AZ_TRAIT_USE_PLATFORM_SIMD_SSE && defined(MCORE_MATRIX_ROWMAJOR)) - const float* m = right.m16; - const float* n = m16; - float* t = this->m16; + const float* m = right.m_m16; + const float* n = m_m16; + float* t = this->m_m16; __m128 x0; __m128 x1; @@ -1246,9 +1246,9 @@ namespace MCore void Matrix::MultMatrix4x3(const Matrix& right) { #if (AZ_TRAIT_USE_PLATFORM_SIMD_SSE && defined(MCORE_MATRIX_ROWMAJOR)) - const float* m = right.m16; - const float* n = m16; - float* t = this->m16; + const float* m = right.m_m16; + const float* n = m_m16; + float* t = this->m_m16; __m128 x0; __m128 x1; @@ -1336,9 +1336,9 @@ namespace MCore void Matrix::MultMatrix(const Matrix& left, const Matrix& right) { #if (AZ_TRAIT_USE_PLATFORM_SIMD_SSE && defined(MCORE_MATRIX_ROWMAJOR)) - const float* m = right.m16; - const float* n = left.m16; - float* t = this->m16; + const float* m = right.m_m16; + const float* n = left.m_m16; + float* t = this->m_m16; __m128 x0; __m128 x1; @@ -1423,9 +1423,9 @@ namespace MCore void Matrix::MultMatrix4x3(const Matrix& left, const Matrix& right) { #if (AZ_TRAIT_USE_PLATFORM_SIMD_SSE && defined(MCORE_MATRIX_ROWMAJOR)) - const float* m = right.m16; - const float* n = left.m16; - float* t = this->m16; + const float* m = right.m_m16; + const float* n = left.m_m16; + float* t = this->m_m16; __m128 x0; __m128 x1; @@ -2052,10 +2052,10 @@ namespace MCore void Matrix::Log() const { MCore::LogDetailedInfo(""); - MCore::LogDetailedInfo("(%.8f, %.8f, %.8f, %.8f)", m16[0], m16[1], m16[2], m16[3]); - MCore::LogDetailedInfo("(%.8f, %.8f, %.8f, %.8f)", m16[4], m16[5], m16[6], m16[7]); - MCore::LogDetailedInfo("(%.8f, %.8f, %.8f, %.8f)", m16[8], m16[9], m16[10], m16[11]); - MCore::LogDetailedInfo("(%.8f, %.8f, %.8f, %.8f)", m16[12], m16[13], m16[14], m16[15]); + MCore::LogDetailedInfo("(%.8f, %.8f, %.8f, %.8f)", m_m16[0], m_m16[1], m_m16[2], m_m16[3]); + MCore::LogDetailedInfo("(%.8f, %.8f, %.8f, %.8f)", m_m16[4], m_m16[5], m_m16[6], m_m16[7]); + MCore::LogDetailedInfo("(%.8f, %.8f, %.8f, %.8f)", m_m16[8], m_m16[9], m_m16[10], m_m16[11]); + MCore::LogDetailedInfo("(%.8f, %.8f, %.8f, %.8f)", m_m16[12], m_m16[13], m_m16[14], m_m16[15]); MCore::LogDetailedInfo(""); } diff --git a/Gems/EMotionFX/Code/MCore/Source/Matrix4.h b/Gems/EMotionFX/Code/MCore/Source/Matrix4.h index 4be819bcc1..c136aa824e 100644 --- a/Gems/EMotionFX/Code/MCore/Source/Matrix4.h +++ b/Gems/EMotionFX/Code/MCore/Source/Matrix4.h @@ -84,7 +84,7 @@ namespace MCore * The number of elements stored at the float pointer location that is used as parameter must be at least 16 floats in size. * @param elementData A pointer to the matrix float data, which must be 16 floats in size, or more, although only the first 16 floats are used. */ - MCORE_INLINE explicit Matrix(const float* elementData) { MCore::MemCopy(m16, elementData, sizeof(float) * 16); } + MCORE_INLINE explicit Matrix(const float* elementData) { MCore::MemCopy(m_m16, elementData, sizeof(float) * 16); } /** * Copy constructor. @@ -779,7 +779,7 @@ namespace MCore AZ::Matrix4x4 ToAzMatrix() const { #ifdef MCORE_MATRIX_ROWMAJOR - return AZ::Matrix4x4::CreateFromRowMajorFloat16(m16); + return AZ::Matrix4x4::CreateFromRowMajorFloat16(m_m16); #else return AZ::Matrix4x4::CreateFromColumnMajorFloat16(m16); #endif @@ -907,7 +907,7 @@ namespace MCore // attributes union { - float m16[16]; // 16 floats as 1D array + float m_m16[16]; // 16 floats as 1D array float m44[4][4]; // as 2D array }; } MCORE_ALIGN_POST(16); diff --git a/Gems/EMotionFX/Code/MCore/Source/Matrix4.inl b/Gems/EMotionFX/Code/MCore/Source/Matrix4.inl index 67f550c2d5..99900abcee 100644 --- a/Gems/EMotionFX/Code/MCore/Source/Matrix4.inl +++ b/Gems/EMotionFX/Code/MCore/Source/Matrix4.inl @@ -8,13 +8,13 @@ MCORE_INLINE Matrix::Matrix(const Matrix& m) { - MCore::MemCopy(m16, m.m16, sizeof(Matrix)); + MCore::MemCopy(m_m16, m.m_m16, sizeof(Matrix)); } MCORE_INLINE void Matrix::operator = (const Matrix& right) { - MCore::MemCopy(m16, right.m16, sizeof(Matrix)); + MCore::MemCopy(m_m16, right.m_m16, sizeof(Matrix)); } @@ -301,7 +301,7 @@ MCORE_INLINE Matrix& Matrix::operator *= (float value) { for (uint32 i = 0; i < 16; ++i) { - m16[i] *= value; + m_m16[i] *= value; } return *this; diff --git a/Gems/EMotionFX/Code/MCore/Source/MemoryFile.cpp b/Gems/EMotionFX/Code/MCore/Source/MemoryFile.cpp index 09021a105a..f90336ea5d 100644 --- a/Gems/EMotionFX/Code/MCore/Source/MemoryFile.cpp +++ b/Gems/EMotionFX/Code/MCore/Source/MemoryFile.cpp @@ -24,25 +24,25 @@ namespace MCore // try to open the memory location bool MemoryFile::Open(uint8* memoryStart, size_t length) { - mMemoryStart = memoryStart; - mCurrentPos = memoryStart; - mLength = length; - mUsedLength = length; - mPreAllocSize = 1024; // pre-allocate 1 extra KB + m_memoryStart = memoryStart; + m_currentPos = memoryStart; + m_length = length; + m_usedLength = length; + m_preAllocSize = 1024; // pre-allocate 1 extra KB // if we need to create a new memory block if (memoryStart == nullptr) { - mAllocate = true; + m_allocate = true; if (length > 0) { - mMemoryStart = (uint8*)MCore::Allocate(length, MCORE_MEMCATEGORY_MEMORYFILE); - mCurrentPos = mMemoryStart; + m_memoryStart = (uint8*)MCore::Allocate(length, MCORE_MEMCATEGORY_MEMORYFILE); + m_currentPos = m_memoryStart; } } else { - mAllocate = false; + m_allocate = false; } return true; @@ -53,15 +53,15 @@ namespace MCore void MemoryFile::Close() { // get rid of the allocated memory - if (mAllocate) + if (m_allocate) { - MCore::Free(mMemoryStart); + MCore::Free(m_memoryStart); } - mMemoryStart = nullptr; - mCurrentPos = nullptr; - mLength = 0; - mUsedLength = 0; + m_memoryStart = nullptr; + m_currentPos = nullptr; + m_length = 0; + m_usedLength = 0; } @@ -73,7 +73,7 @@ namespace MCore bool MemoryFile::GetIsOpen() const { - return (mMemoryStart != nullptr); + return (m_memoryStart != nullptr); } @@ -87,8 +87,8 @@ namespace MCore // returns the next byte in the file uint8 MemoryFile::GetNextByte() { - uint8 value = *mCurrentPos; - mCurrentPos++; + uint8 value = *m_currentPos; + m_currentPos++; return value; } @@ -96,7 +96,7 @@ namespace MCore // returns the position (offset) in the file in bytes size_t MemoryFile::GetPos() const { - return (size_t)(mCurrentPos - mMemoryStart); + return (size_t)(m_currentPos - m_memoryStart); } @@ -111,13 +111,13 @@ namespace MCore // seek a given number of bytes ahead from it's current position bool MemoryFile::Forward(size_t numBytes) { - uint8* newPos = mCurrentPos + numBytes; - if (newPos > (mMemoryStart + mLength)) + uint8* newPos = m_currentPos + numBytes; + if (newPos > (m_memoryStart + m_length)) { return false; } - mCurrentPos = newPos; + m_currentPos = newPos; return true; } @@ -125,12 +125,12 @@ namespace MCore // seek to an absolute position in the file (offset in bytes) bool MemoryFile::Seek(size_t offset) { - if (offset > mLength) + if (offset > m_length) { return false; } - mCurrentPos = mMemoryStart + offset; + m_currentPos = m_memoryStart + offset; return true; } @@ -139,25 +139,25 @@ namespace MCore size_t MemoryFile::Write(const void* data, size_t length) { // if it won't fit in our allocated buffer, we have to enlarge it - if ((mCurrentPos + length > mMemoryStart + mLength) && mAllocate) + if ((m_currentPos + length > m_memoryStart + m_length) && m_allocate) { - size_t offset = mCurrentPos - mMemoryStart; - size_t numBytesExtra = mCurrentPos + length - mMemoryStart; - numBytesExtra += mPreAllocSize; - mMemoryStart = (uint8*)MCore::Realloc((uint8*)mMemoryStart, mLength + numBytesExtra, MCORE_MEMCATEGORY_MEMORYFILE); - mLength += numBytesExtra; - mCurrentPos = mMemoryStart + offset; + size_t offset = m_currentPos - m_memoryStart; + size_t numBytesExtra = m_currentPos + length - m_memoryStart; + numBytesExtra += m_preAllocSize; + m_memoryStart = (uint8*)MCore::Realloc((uint8*)m_memoryStart, m_length + numBytesExtra, MCORE_MEMCATEGORY_MEMORYFILE); + m_length += numBytesExtra; + m_currentPos = m_memoryStart + offset; } // memcopy over the data - MCORE_ASSERT((mCurrentPos + length) <= (mMemoryStart + mLength)); // make sure we don't write past the end of our buffer - MCore::MemCopy(mCurrentPos, data, length); + MCORE_ASSERT((m_currentPos + length) <= (m_memoryStart + m_length)); // make sure we don't write past the end of our buffer + MCore::MemCopy(m_currentPos, data, length); Forward(length); // only overwrite the used length in case we reached the boundary (don't do it in case we modify some data in the middle etc.) - if (mUsedLength < GetPos()) + if (m_usedLength < GetPos()) { - mUsedLength = GetPos(); + m_usedLength = GetPos(); } return length; @@ -167,17 +167,16 @@ namespace MCore // read data from the file size_t MemoryFile::Read(void* data, size_t length) { - // MCORE_ASSERT(mCurrentPos + length <= (uint8*)mMemoryStart + mLength); // make sure we don't read past the end of the memory block - if (mCurrentPos + length > (uint8*)mMemoryStart + mLength) + if (m_currentPos + length > (uint8*)m_memoryStart + m_length) { - const size_t numRead = length - ((mCurrentPos + length) - ((uint8*)mMemoryStart + mLength)); - MCore::MemCopy(data, mCurrentPos, numRead); + const size_t numRead = length - ((m_currentPos + length) - ((uint8*)m_memoryStart + m_length)); + MCore::MemCopy(data, m_currentPos, numRead); Forward(numRead); MCore::LogWarning("MCore::MemoryFile::Read() - We can only read %d bytes of the %d bytes requested, as we are reading past the end of the memory file!", numRead, length); return numRead; } - MCore::MemCopy(data, mCurrentPos, length); + MCore::MemCopy(data, m_currentPos, length); Forward(length); return length; } @@ -186,28 +185,28 @@ namespace MCore // returns the filesize in bytes size_t MemoryFile::GetFileSize() const { - return mUsedLength; + return m_usedLength; } // get the memory start address uint8* MemoryFile::GetMemoryStart() const { - return mMemoryStart; + return m_memoryStart; } // get the pre-alloc size size_t MemoryFile::GetPreAllocSize() const { - return mPreAllocSize; + return m_preAllocSize; } // set the pre-alloc size void MemoryFile::SetPreAllocSize(size_t newSizeInBytes) { - mPreAllocSize = newSizeInBytes; + m_preAllocSize = newSizeInBytes; } diff --git a/Gems/EMotionFX/Code/MCore/Source/MemoryFile.h b/Gems/EMotionFX/Code/MCore/Source/MemoryFile.h index eba9580043..ea2855fd08 100644 --- a/Gems/EMotionFX/Code/MCore/Source/MemoryFile.h +++ b/Gems/EMotionFX/Code/MCore/Source/MemoryFile.h @@ -39,12 +39,12 @@ namespace MCore */ MemoryFile() : File() - , mMemoryStart(nullptr) - , mCurrentPos(nullptr) - , mLength(0) - , mUsedLength(0) - , mPreAllocSize(1024) - , mAllocate(false) {} + , m_memoryStart(nullptr) + , m_currentPos(nullptr) + , m_length(0) + , m_usedLength(0) + , m_preAllocSize(1024) + , m_allocate(false) {} /** * Destructor. Automatically closes the file. @@ -187,11 +187,11 @@ namespace MCore bool SaveToDiskFile(const char* fileName); private: - uint8* mMemoryStart; /**< The location of the file */ - uint8* mCurrentPos; /**< The current location */ - size_t mLength; /**< The total length of the file. */ - size_t mUsedLength; /**< The actual used length of the memory file. */ - size_t mPreAllocSize; /**< The pre-allocation size (in bytes) when we have to reallocate memory. This prevents many allocations. The default=1024, which is 1kb.*/ - bool mAllocate; /**< Can we reallocate or not? */ + uint8* m_memoryStart; /**< The location of the file */ + uint8* m_currentPos; /**< The current location */ + size_t m_length; /**< The total length of the file. */ + size_t m_usedLength; /**< The actual used length of the memory file. */ + size_t m_preAllocSize; /**< The pre-allocation size (in bytes) when we have to reallocate memory. This prevents many allocations. The default=1024, which is 1kb.*/ + bool m_allocate; /**< Can we reallocate or not? */ }; } // namespace MCore diff --git a/Gems/EMotionFX/Code/MCore/Source/MemoryObject.cpp b/Gems/EMotionFX/Code/MCore/Source/MemoryObject.cpp index 017ef3f2e1..9afad03a39 100644 --- a/Gems/EMotionFX/Code/MCore/Source/MemoryObject.cpp +++ b/Gems/EMotionFX/Code/MCore/Source/MemoryObject.cpp @@ -25,37 +25,37 @@ namespace MCore // constructor MemoryObject::MemoryObject() { - mReferenceCount.SetValue(1); + m_referenceCount.SetValue(1); } // destructor MemoryObject::~MemoryObject() { - MCORE_ASSERT(mReferenceCount.GetValue() == 0); + MCORE_ASSERT(m_referenceCount.GetValue() == 0); } // increase the reference count void MemoryObject::IncreaseReferenceCount() { - mReferenceCount.Increment(); + m_referenceCount.Increment(); } // decrease the reference count void MemoryObject::DecreaseReferenceCount() { - MCORE_ASSERT(mReferenceCount.GetValue() > 0); - mReferenceCount.Decrement(); + MCORE_ASSERT(m_referenceCount.GetValue() > 0); + m_referenceCount.Decrement(); } // destroy the object void MemoryObject::Destroy() { - MCORE_ASSERT(mReferenceCount.GetValue() > 0); - if (mReferenceCount.Decrement() == 1) + MCORE_ASSERT(m_referenceCount.GetValue() > 0); + if (m_referenceCount.Decrement() == 1) { Delete(); } @@ -65,7 +65,7 @@ namespace MCore // get the reference count uint32 MemoryObject::GetReferenceCount() const { - return mReferenceCount.GetValue(); + return m_referenceCount.GetValue(); } diff --git a/Gems/EMotionFX/Code/MCore/Source/MemoryObject.h b/Gems/EMotionFX/Code/MCore/Source/MemoryObject.h index 9dfa48284f..cf872da865 100644 --- a/Gems/EMotionFX/Code/MCore/Source/MemoryObject.h +++ b/Gems/EMotionFX/Code/MCore/Source/MemoryObject.h @@ -61,7 +61,7 @@ namespace MCore virtual void Delete(); private: - AtomicUInt32 mReferenceCount; + AtomicUInt32 m_referenceCount; }; diff --git a/Gems/EMotionFX/Code/MCore/Source/MemoryTracker.cpp b/Gems/EMotionFX/Code/MCore/Source/MemoryTracker.cpp index 2cecb43a69..d2f5b9efd8 100644 --- a/Gems/EMotionFX/Code/MCore/Source/MemoryTracker.cpp +++ b/Gems/EMotionFX/Code/MCore/Source/MemoryTracker.cpp @@ -16,33 +16,33 @@ namespace MCore // global stats constructor MemoryTracker::GlobalStats::GlobalStats() { - mCurrentNumBytes = 0; - mCurrentNumAllocs = 0; - mTotalNumAllocs = 0; - mTotalNumReallocs = 0; - mTotalNumFrees = 0; + m_currentNumBytes = 0; + m_currentNumAllocs = 0; + m_totalNumAllocs = 0; + m_totalNumReallocs = 0; + m_totalNumFrees = 0; } // category stats constructor MemoryTracker::CategoryStats::CategoryStats() { - mCurrentNumBytes = 0; - mCurrentNumAllocs = 0; - mTotalNumAllocs = 0; - mTotalNumReallocs = 0; - mTotalNumFrees = 0; + m_currentNumBytes = 0; + m_currentNumAllocs = 0; + m_totalNumAllocs = 0; + m_totalNumReallocs = 0; + m_totalNumFrees = 0; } // group statistics MemoryTracker::GroupStats::GroupStats() { - mCurrentNumBytes = 0; - mCurrentNumAllocs = 0; - mTotalNumAllocs = 0; - mTotalNumReallocs = 0; - mTotalNumFrees = 0; + m_currentNumBytes = 0; + m_currentNumAllocs = 0; + m_totalNumAllocs = 0; + m_totalNumReallocs = 0; + m_totalNumFrees = 0; } @@ -63,7 +63,7 @@ namespace MCore void MemoryTracker::RegisterAlloc(void* memAddress, size_t numBytes, uint32 categoryID) { - LockGuard lock(mMutex); + LockGuard lock(m_mutex); RegisterAllocNoLock(memAddress, numBytes, categoryID); } @@ -73,40 +73,40 @@ namespace MCore { // insert the new allocation Allocation newAlloc; - newAlloc.mMemAddress = memAddress; - newAlloc.mNumBytes = numBytes; - newAlloc.mCategoryID = categoryID; - mAllocs.insert(std::make_pair(memAddress, newAlloc)); + newAlloc.m_memAddress = memAddress; + newAlloc.m_numBytes = numBytes; + newAlloc.m_categoryId = categoryID; + m_allocs.insert(std::make_pair(memAddress, newAlloc)); // update global stats - mGlobalStats.mTotalNumAllocs++; - mGlobalStats.mCurrentNumAllocs++; - mGlobalStats.mCurrentNumBytes += numBytes; + m_globalStats.m_totalNumAllocs++; + m_globalStats.m_currentNumAllocs++; + m_globalStats.m_currentNumBytes += numBytes; // update the category stats - auto categoryItem = mCategories.find(categoryID); - if (categoryItem != mCategories.end()) + auto categoryItem = m_categories.find(categoryID); + if (categoryItem != m_categories.end()) { CategoryStats& catStats = categoryItem->second; - catStats.mTotalNumAllocs++; - catStats.mCurrentNumAllocs++; - catStats.mCurrentNumBytes += numBytes; + catStats.m_totalNumAllocs++; + catStats.m_currentNumAllocs++; + catStats.m_currentNumBytes += numBytes; } else { // auto register the new category CategoryStats catStats; - catStats.mTotalNumAllocs++; - catStats.mCurrentNumAllocs++; - catStats.mCurrentNumBytes += numBytes; - mCategories.insert(std::make_pair(categoryID, catStats)); + catStats.m_totalNumAllocs++; + catStats.m_currentNumAllocs++; + catStats.m_currentNumBytes += numBytes; + m_categories.insert(std::make_pair(categoryID, catStats)); } } void MemoryTracker::RegisterRealloc(void* oldAddress, void* newAddress, size_t numBytes, uint32 categoryID) { - LockGuard lock(mMutex); + LockGuard lock(m_mutex); RegisterReallocNoLock(oldAddress, newAddress, numBytes, categoryID); } @@ -122,52 +122,52 @@ namespace MCore } // try to locate the allocation - auto item = mAllocs.find(oldAddress); + auto item = m_allocs.find(oldAddress); // if we found the item - if (item != mAllocs.end()) + if (item != m_allocs.end()) { const Allocation& allocation = item->second; - const size_t oldNumBytes = allocation.mNumBytes; + const size_t oldNumBytes = allocation.m_numBytes; // update the global stats - mGlobalStats.mCurrentNumBytes += (numBytes - oldNumBytes); - mGlobalStats.mTotalNumReallocs++; + m_globalStats.m_currentNumBytes += (numBytes - oldNumBytes); + m_globalStats.m_totalNumReallocs++; // the category got updated, unregister it from the old category - const bool categoryChanged = (categoryID != allocation.mCategoryID); + const bool categoryChanged = (categoryID != allocation.m_categoryId); if (categoryChanged) { - auto oldCategoryItem = mCategories.find(allocation.mCategoryID); - MCORE_ASSERT(oldCategoryItem != mCategories.end()); - oldCategoryItem->second.mCurrentNumBytes -= oldNumBytes; - oldCategoryItem->second.mCurrentNumAllocs--; + auto oldCategoryItem = m_categories.find(allocation.m_categoryId); + MCORE_ASSERT(oldCategoryItem != m_categories.end()); + oldCategoryItem->second.m_currentNumBytes -= oldNumBytes; + oldCategoryItem->second.m_currentNumAllocs--; } // remove the allocation - mAllocs.erase(item); + m_allocs.erase(item); // re-insert it using the new address (new key) Allocation newAlloc; - newAlloc.mCategoryID = categoryID; - newAlloc.mMemAddress = newAddress; - newAlloc.mNumBytes = numBytes; - mAllocs.insert(std::make_pair(newAddress, newAlloc)); + newAlloc.m_categoryId = categoryID; + newAlloc.m_memAddress = newAddress; + newAlloc.m_numBytes = numBytes; + m_allocs.insert(std::make_pair(newAddress, newAlloc)); // update the category stats - auto categoryItem = mCategories.find(categoryID); - MCORE_ASSERT(categoryItem != mCategories.end()); + auto categoryItem = m_categories.find(categoryID); + MCORE_ASSERT(categoryItem != m_categories.end()); CategoryStats& catStats = categoryItem->second; - catStats.mTotalNumReallocs++; + catStats.m_totalNumReallocs++; if (categoryChanged == false) { - catStats.mCurrentNumBytes += (numBytes - oldNumBytes); + catStats.m_currentNumBytes += (numBytes - oldNumBytes); } else { - catStats.mCurrentNumBytes += numBytes; - catStats.mCurrentNumAllocs++; + catStats.m_currentNumBytes += numBytes; + catStats.m_currentNumAllocs++; } } else // not found, we must just register this as a regular allocation @@ -179,7 +179,7 @@ namespace MCore void MemoryTracker::RegisterFree(void* memAddress) { - LockGuard lock(mMutex); + LockGuard lock(m_mutex); RegisterFreeNoLock(memAddress); } @@ -193,27 +193,27 @@ namespace MCore } // find the allocation using this address - auto item = mAllocs.find(memAddress); - if (item != mAllocs.end()) + auto item = m_allocs.find(memAddress); + if (item != m_allocs.end()) { Allocation& allocation = item->second; // update global stats - mGlobalStats.mCurrentNumBytes -= allocation.mNumBytes; - mGlobalStats.mTotalNumFrees++; - mGlobalStats.mCurrentNumAllocs--; + m_globalStats.m_currentNumBytes -= allocation.m_numBytes; + m_globalStats.m_totalNumFrees++; + m_globalStats.m_currentNumAllocs--; // update the category stats - auto categoryItem = mCategories.find(allocation.mCategoryID); - MCORE_ASSERT(categoryItem != mCategories.end()); // this should be impossible + auto categoryItem = m_categories.find(allocation.m_categoryId); + MCORE_ASSERT(categoryItem != m_categories.end()); // this should be impossible CategoryStats& catStats = categoryItem->second; - catStats.mCurrentNumAllocs--; - catStats.mTotalNumFrees++; - catStats.mCurrentNumBytes -= allocation.mNumBytes; + catStats.m_currentNumAllocs--; + catStats.m_totalNumFrees++; + catStats.m_currentNumBytes -= allocation.m_numBytes; // remove the allocation - mAllocs.erase(item); + m_allocs.erase(item); } else { @@ -227,25 +227,25 @@ namespace MCore // clear all stored allocations void MemoryTracker::Clear() { - LockGuard lock(mMutex); - mAllocs.clear(); - mCategories.clear(); - mGroups.clear(); - mGlobalStats = GlobalStats(); + LockGuard lock(m_mutex); + m_allocs.clear(); + m_categories.clear(); + m_groups.clear(); + m_globalStats = GlobalStats(); } // get the global stats const MemoryTracker::GlobalStats& MemoryTracker::GetGlobalStats() const { - return mGlobalStats; + return m_globalStats; } // get category statistics bool MemoryTracker::GetCategoryStatistics(uint32 categoryID, CategoryStats* outStats) { - LockGuard lock(mMutex); + LockGuard lock(m_mutex); return GetCategoryStatisticsNoLock(categoryID, outStats); } @@ -253,8 +253,8 @@ namespace MCore // get category statistics, without lock bool MemoryTracker::GetCategoryStatisticsNoLock(uint32 categoryID, CategoryStats* outStats) { - auto item = mCategories.find(categoryID); - if (item != mCategories.end()) + auto item = m_categories.find(categoryID); + if (item != m_categories.end()) { *outStats = item->second; return true; @@ -267,20 +267,20 @@ namespace MCore // register the name to a given category void MemoryTracker::RegisterCategory(uint32 categoryID, const char* name) { - LockGuard lock(mMutex); + LockGuard lock(m_mutex); // try to see if the category exists already - auto item = mCategories.find(categoryID); - if (item == mCategories.end()) + auto item = m_categories.find(categoryID); + if (item == m_categories.end()) { // register the new category CategoryStats catStats; - catStats.mName = name; - mCategories.insert(std::make_pair(categoryID, catStats)); + catStats.m_name = name; + m_categories.insert(std::make_pair(categoryID, catStats)); } else { - item->second.mName = name; + item->second.m_name = name; } } @@ -288,30 +288,30 @@ namespace MCore // register a given group void MemoryTracker::RegisterGroup(uint32 groupID, const char* name, const std::vector& categories) { - LockGuard lock(mMutex); + LockGuard lock(m_mutex); - auto item = mGroups.find(groupID); - if (item == mGroups.end()) + auto item = m_groups.find(groupID); + if (item == m_groups.end()) { // create a new group Group newGroup; - newGroup.mName = name; + newGroup.m_name = name; for (auto& cat : categories) { - newGroup.mCategories.insert(cat); + newGroup.m_categories.insert(cat); } - mGroups.insert(std::make_pair(groupID, newGroup)); + m_groups.insert(std::make_pair(groupID, newGroup)); } else { // update the existing group by inserting categories that don't exist yet inside the group Group& group = item->second; - group.mName = name; + group.m_name = name; for (auto& cat : categories) { - if (group.mCategories.find(cat) == group.mCategories.end()) + if (group.m_categories.find(cat) == group.m_categories.end()) { - group.mCategories.insert(cat); + group.m_categories.insert(cat); } } } @@ -321,7 +321,7 @@ namespace MCore // update the statistics for all groups void MemoryTracker::UpdateGroupStatistics() { - LockGuard lock(mMutex); + LockGuard lock(m_mutex); UpdateGroupStatisticsNoLock(); } @@ -330,24 +330,24 @@ namespace MCore void MemoryTracker::UpdateGroupStatisticsNoLock() { // for all registered groups - for (auto& item : mGroups) + for (auto& item : m_groups) { Group& group = item.second; // reset the totals - group.mStats = GroupStats(); + group.m_stats = GroupStats(); // for all categories - for (auto categoryID : group.mCategories) + for (auto categoryID : group.m_categories) { CategoryStats categoryStats; GetCategoryStatisticsNoLock(categoryID, &categoryStats); - group.mStats.mCurrentNumAllocs += categoryStats.mCurrentNumAllocs; - group.mStats.mCurrentNumBytes += categoryStats.mCurrentNumBytes; - group.mStats.mTotalNumAllocs += categoryStats.mTotalNumAllocs; - group.mStats.mTotalNumFrees += categoryStats.mTotalNumFrees; - group.mStats.mTotalNumReallocs += categoryStats.mTotalNumReallocs; + group.m_stats.m_currentNumAllocs += categoryStats.m_currentNumAllocs; + group.m_stats.m_currentNumBytes += categoryStats.m_currentNumBytes; + group.m_stats.m_totalNumAllocs += categoryStats.m_totalNumAllocs; + group.m_stats.m_totalNumFrees += categoryStats.m_totalNumFrees; + group.m_stats.m_totalNumReallocs += categoryStats.m_totalNumReallocs; } } } @@ -355,15 +355,15 @@ namespace MCore // get group statistics bool MemoryTracker::GetGroupStatistics(uint32 groupID, GroupStats* outGroupStats) { - LockGuard lock(mMutex); + LockGuard lock(m_mutex); - auto item = mGroups.find(groupID); - if (item == mGroups.end()) + auto item = m_groups.find(groupID); + if (item == m_groups.end()) { return false; } - const GroupStats& groupStats = item->second.mStats; + const GroupStats& groupStats = item->second.m_stats; *outGroupStats = groupStats; return true; @@ -373,67 +373,67 @@ namespace MCore // get the allocations const std::unordered_map& MemoryTracker::GetAllocations() const { - return mAllocs; + return m_allocs; } // get the groups const std::unordered_map& MemoryTracker::GetGroups() const { - return mGroups; + return m_groups; } // get the categories const std::map& MemoryTracker::GetCategories() const { - return mCategories; + return m_categories; } // multithread lock void MemoryTracker::Lock() { - mMutex.Lock(); + m_mutex.Lock(); } // multithread unlock void MemoryTracker::Unlock() { - mMutex.Unlock(); + m_mutex.Unlock(); } // log the stats void MemoryTracker::LogStatistics(bool currentlyAllocatedOnly) { - LockGuard lock(mMutex); + LockGuard lock(m_mutex); // update the group statistics (thread safe also) UpdateGroupStatisticsNoLock(); Print("--[ Memory Global Statistics ]-----------------------------------------------------------------------"); - Print(FormatStdString("Current Num Bytes Used = %d bytes (%d k or %.2f mb)", mGlobalStats.mCurrentNumBytes, mGlobalStats.mCurrentNumBytes / 1000, mGlobalStats.mCurrentNumBytes / 1000000.0f).c_str()); - Print(FormatStdString("Current Num Allocs = %d", mGlobalStats.mCurrentNumAllocs).c_str()); - Print(FormatStdString("Total Num Allocs = %d", mGlobalStats.mTotalNumAllocs).c_str()); - Print(FormatStdString("Total Num Reallocs = %d", mGlobalStats.mTotalNumReallocs).c_str()); - Print(FormatStdString("Total Num Frees = %d", mGlobalStats.mTotalNumFrees).c_str()); + Print(FormatStdString("Current Num Bytes Used = %d bytes (%d k or %.2f mb)", m_globalStats.m_currentNumBytes, m_globalStats.m_currentNumBytes / 1000, m_globalStats.m_currentNumBytes / 1000000.0f).c_str()); + Print(FormatStdString("Current Num Allocs = %d", m_globalStats.m_currentNumAllocs).c_str()); + Print(FormatStdString("Total Num Allocs = %d", m_globalStats.m_totalNumAllocs).c_str()); + Print(FormatStdString("Total Num Reallocs = %d", m_globalStats.m_totalNumReallocs).c_str()); + Print(FormatStdString("Total Num Frees = %d", m_globalStats.m_totalNumFrees).c_str()); - if (mCategories.empty() == false) + if (m_categories.empty() == false) { Print(""); Print("--[ Memory Category Statistics ]---------------------------------------------------------------------"); - for (auto& item : mCategories) + for (auto& item : m_categories) { const uint32 categoryID = item.first; const CategoryStats& stats = item.second; - if (stats.mTotalNumAllocs > 0) + if (stats.m_totalNumAllocs > 0) { bool display = true; if (currentlyAllocatedOnly) { - if (stats.mCurrentNumAllocs == 0) + if (stats.m_currentNumAllocs == 0) { display = false; } @@ -441,26 +441,26 @@ namespace MCore if (display) { - Print(FormatStdString("[Cat %4d] - %8d bytes (%6d k) in %5d allocs [%6d / %6d / %6d] --> %s", categoryID, stats.mCurrentNumBytes, stats.mCurrentNumBytes / 1000, stats.mCurrentNumAllocs, stats.mTotalNumAllocs, stats.mTotalNumReallocs, stats.mTotalNumFrees, stats.mName.c_str()).c_str()); + Print(FormatStdString("[Cat %4d] - %8d bytes (%6d k) in %5d allocs [%6d / %6d / %6d] --> %s", categoryID, stats.m_currentNumBytes, stats.m_currentNumBytes / 1000, stats.m_currentNumAllocs, stats.m_totalNumAllocs, stats.m_totalNumReallocs, stats.m_totalNumFrees, stats.m_name.c_str()).c_str()); } } } } - if (mGroups.empty() == false) + if (m_groups.empty() == false) { Print(""); Print("--[ Group Statistics ]-------------------------------------------------------------------------------"); - for (auto& item : mGroups) + for (auto& item : m_groups) { const uint32 groupID = item.first; const Group& group = item.second; - if (group.mStats.mTotalNumAllocs > 0) + if (group.m_stats.m_totalNumAllocs > 0) { bool display = true; if (currentlyAllocatedOnly) { - if (group.mStats.mCurrentNumAllocs == 0) + if (group.m_stats.m_currentNumAllocs == 0) { display = false; } @@ -468,7 +468,7 @@ namespace MCore if (display) { - Print(FormatStdString("[Group %4d] - %8d bytes (%6d k) in %5d allocs [%6d / %6d / %6d] --> %s", groupID, group.mStats.mCurrentNumBytes, group.mStats.mCurrentNumBytes / 1000, group.mStats.mCurrentNumAllocs, group.mStats.mTotalNumAllocs, group.mStats.mTotalNumReallocs, group.mStats.mTotalNumFrees, group.mName.c_str()).c_str()); + Print(FormatStdString("[Group %4d] - %8d bytes (%6d k) in %5d allocs [%6d / %6d / %6d] --> %s", groupID, group.m_stats.m_currentNumBytes, group.m_stats.m_currentNumBytes / 1000, group.m_stats.m_currentNumAllocs, group.m_stats.m_totalNumAllocs, group.m_stats.m_totalNumReallocs, group.m_stats.m_totalNumFrees, group.m_name.c_str()).c_str()); } } } @@ -479,12 +479,12 @@ namespace MCore // log the stats void MemoryTracker::LogLeaks() { - LockGuard lock(mMutex); + LockGuard lock(m_mutex); // update the group statistics (thread safe also) UpdateGroupStatisticsNoLock(); - if (mAllocs.size() == 0) + if (m_allocs.size() == 0) { Print("MCore::MemoryTracker::LogLeaks() - No memory leaks have been detected."); return; @@ -492,34 +492,34 @@ namespace MCore // log globals Print("--[ Memory Leak Global Statistics ]-----------------------------------------------------------------------"); - Print(FormatStdString("Leaking Num Bytes = %d bytes (%d k or %.2f mb)", mGlobalStats.mCurrentNumBytes, mGlobalStats.mCurrentNumBytes / 1000, mGlobalStats.mCurrentNumBytes / 1000000.0f).c_str()); - Print(FormatStdString("Leaking Num Allocs = %d", mGlobalStats.mCurrentNumAllocs).c_str()); + Print(FormatStdString("Leaking Num Bytes = %d bytes (%d k or %.2f mb)", m_globalStats.m_currentNumBytes, m_globalStats.m_currentNumBytes / 1000, m_globalStats.m_currentNumBytes / 1000000.0f).c_str()); + Print(FormatStdString("Leaking Num Allocs = %d", m_globalStats.m_currentNumAllocs).c_str()); Print(""); // log category totals Print("--[ Memory Category Leak Statistics ]---------------------------------------------------------------------"); - for (auto& item : mCategories) + for (auto& item : m_categories) { const uint32 categoryID = item.first; const CategoryStats& stats = item.second; - if (stats.mCurrentNumAllocs > 0) + if (stats.m_currentNumAllocs > 0) { - Print(FormatStdString("[Cat %4d] - %8d bytes (%6d k) in %5d allocs [%6d / %6d / %6d] --> %s", categoryID, stats.mCurrentNumBytes, stats.mCurrentNumBytes / 1000, stats.mCurrentNumAllocs, stats.mTotalNumAllocs, stats.mTotalNumReallocs, stats.mTotalNumFrees, stats.mName.c_str()).c_str()); + Print(FormatStdString("[Cat %4d] - %8d bytes (%6d k) in %5d allocs [%6d / %6d / %6d] --> %s", categoryID, stats.m_currentNumBytes, stats.m_currentNumBytes / 1000, stats.m_currentNumAllocs, stats.m_totalNumAllocs, stats.m_totalNumReallocs, stats.m_totalNumFrees, stats.m_name.c_str()).c_str()); } } Print(""); - if (mGroups.empty() == false) + if (m_groups.empty() == false) { Print(""); Print("--[ Group Statistics ]-------------------------------------------------------------------------------"); - for (auto& item : mGroups) + for (auto& item : m_groups) { const uint32 groupID = item.first; const Group& group = item.second; - if (group.mStats.mCurrentNumAllocs > 0) + if (group.m_stats.m_currentNumAllocs > 0) { - Print(FormatStdString("[Group %4d] - %8d bytes (%6d k) in %5d allocs [%6d / %6d / %6d] --> %s", groupID, group.mStats.mCurrentNumBytes, group.mStats.mCurrentNumBytes / 1000, group.mStats.mCurrentNumAllocs, group.mStats.mTotalNumAllocs, group.mStats.mTotalNumReallocs, group.mStats.mTotalNumFrees, group.mName.c_str()).c_str()); + Print(FormatStdString("[Group %4d] - %8d bytes (%6d k) in %5d allocs [%6d / %6d / %6d] --> %s", groupID, group.m_stats.m_currentNumBytes, group.m_stats.m_currentNumBytes / 1000, group.m_stats.m_currentNumAllocs, group.m_stats.m_totalNumAllocs, group.m_stats.m_totalNumReallocs, group.m_stats.m_totalNumFrees, group.m_name.c_str()).c_str()); } } Print(""); @@ -528,7 +528,7 @@ namespace MCore // log individual leaks Print("--[ Memory Allocations ]----------------------------------------------------------------------------------"); uint32 allocNumber = 0; - for (auto& item : mAllocs) + for (auto& item : m_allocs) { const char* data = static_cast(item.first); const Allocation& allocation = item.second; @@ -536,7 +536,7 @@ namespace MCore char buffer[64]; memset(buffer, 0, 64); - const size_t numBytes = (allocation.mNumBytes >= 64) ? 63 : allocation.mNumBytes; + const size_t numBytes = (allocation.m_numBytes >= 64) ? 63 : allocation.m_numBytes; for (uint32 i = 0; i < numBytes; ++i) { char c = data[i]; @@ -547,9 +547,9 @@ namespace MCore buffer[i] = c; } - auto catItem = mCategories.find(allocation.mCategoryID); - MCORE_ASSERT(catItem != mCategories.end()); - Print(FormatStdString("#%-4d - %6d bytes (cat=%4d) - [%-66s] --> %s", allocNumber, allocation.mNumBytes, allocation.mCategoryID, buffer, catItem->second.mName.c_str()).c_str()); + auto catItem = m_categories.find(allocation.m_categoryId); + MCORE_ASSERT(catItem != m_categories.end()); + Print(FormatStdString("#%-4d - %6d bytes (cat=%4d) - [%-66s] --> %s", allocNumber, allocation.m_numBytes, allocation.m_categoryId, buffer, catItem->second.m_name.c_str()).c_str()); allocNumber++; } diff --git a/Gems/EMotionFX/Code/MCore/Source/MemoryTracker.h b/Gems/EMotionFX/Code/MCore/Source/MemoryTracker.h index 6a387ed508..e944306c14 100644 --- a/Gems/EMotionFX/Code/MCore/Source/MemoryTracker.h +++ b/Gems/EMotionFX/Code/MCore/Source/MemoryTracker.h @@ -41,9 +41,9 @@ namespace MCore */ struct MCORE_API Allocation { - void* mMemAddress; /**< The memory address of the allocation. */ - size_t mNumBytes; /**< The number of bytes allocated at this address. */ - uint32 mCategoryID; /**< The memory category of this allocation. */ + void* m_memAddress; /**< The memory address of the allocation. */ + size_t m_numBytes; /**< The number of bytes allocated at this address. */ + uint32 m_categoryId; /**< The memory category of this allocation. */ }; /** @@ -51,11 +51,11 @@ namespace MCore */ struct MCORE_API GlobalStats { - size_t mCurrentNumBytes; /**< Current number of bytes allocated. */ - uint32 mCurrentNumAllocs; /**< The current number of allocations. */ - uint32 mTotalNumAllocs; /**< Total number of allocations ever made. */ - uint32 mTotalNumReallocs; /**< Total number of reallocations ever made. */ - uint32 mTotalNumFrees; /**< Total number of frees ever made. */ + size_t m_currentNumBytes; /**< Current number of bytes allocated. */ + uint32 m_currentNumAllocs; /**< The current number of allocations. */ + uint32 m_totalNumAllocs; /**< Total number of allocations ever made. */ + uint32 m_totalNumReallocs; /**< Total number of reallocations ever made. */ + uint32 m_totalNumFrees; /**< Total number of frees ever made. */ GlobalStats(); }; @@ -65,12 +65,12 @@ namespace MCore */ struct MCORE_API CategoryStats { - size_t mCurrentNumBytes; /**< Current number of bytes allocated. */ - uint32 mCurrentNumAllocs; /**< Current number of allocations active. */ - uint32 mTotalNumAllocs; /**< Total number of allocations ever made in this category. */ - uint32 mTotalNumReallocs; /**< Total number of reallocations ever made in this category. */ - uint32 mTotalNumFrees; /**< Total number of frees ever made in this category. */ - std::string mName; /**< The name of the category, can be empty if not registered with RegisterCategory. */ + size_t m_currentNumBytes; /**< Current number of bytes allocated. */ + uint32 m_currentNumAllocs; /**< Current number of allocations active. */ + uint32 m_totalNumAllocs; /**< Total number of allocations ever made in this category. */ + uint32 m_totalNumReallocs; /**< Total number of reallocations ever made in this category. */ + uint32 m_totalNumFrees; /**< Total number of frees ever made in this category. */ + std::string m_name; /**< The name of the category, can be empty if not registered with RegisterCategory. */ CategoryStats(); }; @@ -80,11 +80,11 @@ namespace MCore */ struct MCORE_API GroupStats { - size_t mCurrentNumBytes; - uint32 mCurrentNumAllocs; - uint32 mTotalNumAllocs; /**< Total number of allocations ever made in this category. */ - uint32 mTotalNumReallocs; /**< Total number of reallocations ever made in this category. */ - uint32 mTotalNumFrees; /**< Total number of frees ever made in this category. */ + size_t m_currentNumBytes; + uint32 m_currentNumAllocs; + uint32 m_totalNumAllocs; /**< Total number of allocations ever made in this category. */ + uint32 m_totalNumReallocs; /**< Total number of reallocations ever made in this category. */ + uint32 m_totalNumFrees; /**< Total number of frees ever made in this category. */ GroupStats(); }; @@ -94,9 +94,9 @@ namespace MCore */ struct MCORE_API Group { - std::set mCategories; /**< The ID values of the categories that are part of this group. */ - std::string mName; /**< The name of the category. */ - GroupStats mStats; /**< The statistics. */ + std::set m_categories; /**< The ID values of the categories that are part of this group. */ + std::string m_name; /**< The name of the category. */ + GroupStats m_stats; /**< The statistics. */ }; //-------------------------------- @@ -254,11 +254,11 @@ namespace MCore void Unlock(); private: - std::unordered_map mAllocs; /**< The unordered map of allocations, with the memory address as key. */ - std::unordered_map mGroups; /**< The groups, with the group ID as key.*/ - std::map mCategories; /**< The ordered map of categories, with the category ID as key. */ - GlobalStats mGlobalStats; /**< The global memory statistics. */ - mutable Mutex mMutex; /**< The multithread mutex used to lock and unlock. */ + std::unordered_map m_allocs; /**< The unordered map of allocations, with the memory address as key. */ + std::unordered_map m_groups; /**< The groups, with the group ID as key.*/ + std::map m_categories; /**< The ordered map of categories, with the category ID as key. */ + GlobalStats m_globalStats; /**< The global memory statistics. */ + mutable Mutex m_mutex; /**< The multithread mutex used to lock and unlock. */ /** * Register a given memory allocation. diff --git a/Gems/EMotionFX/Code/MCore/Source/MultiThreadManager.h b/Gems/EMotionFX/Code/MCore/Source/MultiThreadManager.h index a4fe6eaa10..eccfa9f5f3 100644 --- a/Gems/EMotionFX/Code/MCore/Source/MultiThreadManager.h +++ b/Gems/EMotionFX/Code/MCore/Source/MultiThreadManager.h @@ -29,12 +29,12 @@ namespace MCore MCORE_INLINE Mutex() {} MCORE_INLINE ~Mutex() {} - MCORE_INLINE void Lock() { mMutex.lock(); } - MCORE_INLINE void Unlock() { mMutex.unlock(); } - MCORE_INLINE bool TryLock() { return mMutex.try_lock(); } + MCORE_INLINE void Lock() { m_mutex.lock(); } + MCORE_INLINE void Unlock() { m_mutex.unlock(); } + MCORE_INLINE bool TryLock() { return m_mutex.try_lock(); } private: - AZStd::mutex mMutex; + AZStd::mutex m_mutex; }; @@ -44,12 +44,12 @@ namespace MCore MCORE_INLINE MutexRecursive() {} MCORE_INLINE ~MutexRecursive() {} - MCORE_INLINE void Lock() { mMutex.lock(); } - MCORE_INLINE void Unlock() { mMutex.unlock(); } - MCORE_INLINE bool TryLock() { return mMutex.try_lock(); } + MCORE_INLINE void Lock() { m_mutex.lock(); } + MCORE_INLINE void Unlock() { m_mutex.unlock(); } + MCORE_INLINE bool TryLock() { return m_mutex.try_lock(); } private: - AZStd::recursive_mutex mMutex; + AZStd::recursive_mutex m_mutex; }; @@ -59,13 +59,13 @@ namespace MCore MCORE_INLINE ConditionVariable() {} MCORE_INLINE ~ConditionVariable() {} - MCORE_INLINE void Wait(Mutex& mtx, const AZStd::function& predicate) { AZStd::unique_lock lock(mtx.mMutex); mVariable.wait(lock, predicate); } - MCORE_INLINE void WaitWithTimeout(Mutex& mtx, uint32 microseconds, const AZStd::function& predicate) { AZStd::unique_lock lock(mtx.mMutex); mVariable.wait_for(lock, AZStd::chrono::microseconds(microseconds), predicate); } - MCORE_INLINE void NotifyOne() { mVariable.notify_one(); } - MCORE_INLINE void NotifyAll() { mVariable.notify_all(); } + MCORE_INLINE void Wait(Mutex& mtx, const AZStd::function& predicate) { AZStd::unique_lock lock(mtx.m_mutex); m_variable.wait(lock, predicate); } + MCORE_INLINE void WaitWithTimeout(Mutex& mtx, uint32 microseconds, const AZStd::function& predicate) { AZStd::unique_lock lock(mtx.m_mutex); m_variable.wait_for(lock, AZStd::chrono::microseconds(microseconds), predicate); } + MCORE_INLINE void NotifyOne() { m_variable.notify_one(); } + MCORE_INLINE void NotifyAll() { m_variable.notify_all(); } private: - AZStd::condition_variable mVariable; + AZStd::condition_variable m_variable; }; @@ -75,14 +75,14 @@ namespace MCore MCORE_INLINE AtomicInt32() { SetValue(0); } MCORE_INLINE ~AtomicInt32() {} - MCORE_INLINE void SetValue(int32 value) { mAtomic.store(value); } - MCORE_INLINE int32 GetValue() const { int32 value = mAtomic.load(); return value; } + MCORE_INLINE void SetValue(int32 value) { m_atomic.store(value); } + MCORE_INLINE int32 GetValue() const { int32 value = m_atomic.load(); return value; } - MCORE_INLINE int32 Increment() { return mAtomic++; } - MCORE_INLINE int32 Decrement() { return mAtomic--; } + MCORE_INLINE int32 Increment() { return m_atomic++; } + MCORE_INLINE int32 Decrement() { return m_atomic--; } private: - AZStd::atomic mAtomic; + AZStd::atomic m_atomic; }; @@ -93,14 +93,14 @@ namespace MCore MCORE_INLINE AtomicUInt32() { SetValue(0); } MCORE_INLINE ~AtomicUInt32() {} - MCORE_INLINE void SetValue(uint32 value) { mAtomic.store(value); } - MCORE_INLINE uint32 GetValue() const { uint32 value = mAtomic.load(); return value; } + MCORE_INLINE void SetValue(uint32 value) { m_atomic.store(value); } + MCORE_INLINE uint32 GetValue() const { uint32 value = m_atomic.load(); return value; } - MCORE_INLINE uint32 Increment() { return mAtomic++; } - MCORE_INLINE uint32 Decrement() { return mAtomic--; } + MCORE_INLINE uint32 Increment() { return m_atomic++; } + MCORE_INLINE uint32 Decrement() { return m_atomic--; } private: - AZStd::atomic mAtomic; + AZStd::atomic m_atomic; }; @@ -109,14 +109,14 @@ namespace MCore public: MCORE_INLINE AtomicSizeT() { SetValue(0); } - MCORE_INLINE void SetValue(size_t value) { mAtomic.store(value); } - MCORE_INLINE size_t GetValue() const { size_t value = mAtomic.load(); return value; } + MCORE_INLINE void SetValue(size_t value) { m_atomic.store(value); } + MCORE_INLINE size_t GetValue() const { size_t value = m_atomic.load(); return value; } - MCORE_INLINE size_t Increment() { return mAtomic++; } - MCORE_INLINE size_t Decrement() { return mAtomic--; } + MCORE_INLINE size_t Increment() { return m_atomic++; } + MCORE_INLINE size_t Decrement() { return m_atomic--; } private: - AZStd::atomic mAtomic; + AZStd::atomic m_atomic; }; @@ -127,58 +127,58 @@ namespace MCore Thread(const AZStd::function& threadFunction) { Init(threadFunction); } ~Thread() {} - void Init(const AZStd::function& threadFunction) { mThread = AZStd::thread(threadFunction); } - void Join() { mThread.join(); } + void Init(const AZStd::function& threadFunction) { m_thread = AZStd::thread(threadFunction); } + void Join() { m_thread.join(); } private: - AZStd::thread mThread; + AZStd::thread m_thread; }; class MCORE_API LockGuard { public: - MCORE_INLINE LockGuard(Mutex& mutex) { mMutex = &mutex; mutex.Lock(); } - MCORE_INLINE ~LockGuard() { mMutex->Unlock(); } + MCORE_INLINE LockGuard(Mutex& mutex) { m_mutex = &mutex; mutex.Lock(); } + MCORE_INLINE ~LockGuard() { m_mutex->Unlock(); } private: - Mutex* mMutex; + Mutex* m_mutex; }; class MCORE_API LockGuardRecursive { public: - MCORE_INLINE LockGuardRecursive(MutexRecursive& mutex) { mMutex = &mutex; mutex.Lock(); } - MCORE_INLINE ~LockGuardRecursive() { mMutex->Unlock(); } + MCORE_INLINE LockGuardRecursive(MutexRecursive& mutex) { m_mutex = &mutex; mutex.Lock(); } + MCORE_INLINE ~LockGuardRecursive() { m_mutex->Unlock(); } private: - MutexRecursive* mMutex; + MutexRecursive* m_mutex; }; class MCORE_API ConditionEvent { public: - ConditionEvent() { mConditionValue = false; } + ConditionEvent() { m_conditionValue = false; } ~ConditionEvent() { } - void Reset() { mConditionValue = false; } + void Reset() { m_conditionValue = false; } void Wait() { - mCV.Wait(mMutex, [this] { return mConditionValue; }); + m_cv.Wait(m_mutex, [this] { return m_conditionValue; }); } void WaitWithTimeout(uint32 microseconds) { - mCV.WaitWithTimeout(mMutex, microseconds, [this] { return mConditionValue; }); + m_cv.WaitWithTimeout(m_mutex, microseconds, [this] { return m_conditionValue; }); } - void NotifyAll() { { LockGuard lockMutex(mMutex); mConditionValue = true; } mCV.NotifyAll(); } - void NotifyOne() { { LockGuard lockMutex(mMutex); mConditionValue = true; } mCV.NotifyOne(); } + void NotifyAll() { { LockGuard lockMutex(m_mutex); m_conditionValue = true; } m_cv.NotifyAll(); } + void NotifyOne() { { LockGuard lockMutex(m_mutex); m_conditionValue = true; } m_cv.NotifyOne(); } private: - Mutex mMutex; - ConditionVariable mCV; - bool mConditionValue; + Mutex m_mutex; + ConditionVariable m_cv; + bool m_conditionValue; }; } // namespace MCore diff --git a/Gems/EMotionFX/Code/MCore/Source/PlaneEq.h b/Gems/EMotionFX/Code/MCore/Source/PlaneEq.h index 402de4a12c..df8738a1ee 100644 --- a/Gems/EMotionFX/Code/MCore/Source/PlaneEq.h +++ b/Gems/EMotionFX/Code/MCore/Source/PlaneEq.h @@ -54,8 +54,8 @@ namespace MCore * @param pnt A point on the plane. */ MCORE_INLINE PlaneEq(const AZ::Vector3& norm, const AZ::Vector3& pnt) - : mNormal(norm) - , mDist(-((norm.GetX() * pnt.GetX()) + (norm.GetY() * pnt.GetY()) + (norm.GetZ() * pnt.GetZ()))) {} + : m_normal(norm) + , m_dist(-((norm.GetX() * pnt.GetX()) + (norm.GetY() * pnt.GetY()) + (norm.GetZ() * pnt.GetZ()))) {} /** * Constructor when you know the normal and the value of d out of the plane equation (Ax + By + Cz + d = 0) @@ -63,8 +63,8 @@ namespace MCore * @param d The value of 'd' out of the plane equation. */ MCORE_INLINE PlaneEq(const AZ::Vector3& norm, float d) - : mNormal(norm) - , mDist(d) {} + : m_normal(norm) + , m_dist(d) {} /** * Constructor when you know 3 points on the plane (the winding matters here (clockwise vs counter-clockwise) @@ -74,8 +74,8 @@ namespace MCore * @param v3 The third point on the plane. */ MCORE_INLINE PlaneEq(const AZ::Vector3& v1, const AZ::Vector3& v2, const AZ::Vector3& v3) - : mNormal((v2 - v1).Cross(v3 - v1).GetNormalized()) - , mDist(-(mNormal.Dot(v1))) {} + : m_normal((v2 - v1).Cross(v3 - v1).GetNormalized()) + , m_dist(-(m_normal.Dot(v1))) {} /** * Calculates and returns the dominant plane. @@ -86,9 +86,9 @@ namespace MCore */ MCORE_INLINE EPlane CalcDominantPlane() const { - return (Math::Abs(mNormal.GetY()) > Math::Abs(mNormal.GetX()) - ? (Math::Abs(mNormal.GetZ()) > Math::Abs(mNormal.GetY()) - ? PLANE_XY : PLANE_XZ) : (Math::Abs(mNormal.GetZ()) > Math::Abs(mNormal.GetX()) + return (Math::Abs(m_normal.GetY()) > Math::Abs(m_normal.GetX()) + ? (Math::Abs(m_normal.GetZ()) > Math::Abs(m_normal.GetY()) + ? PLANE_XY : PLANE_XZ) : (Math::Abs(m_normal.GetZ()) > Math::Abs(m_normal.GetX()) ? PLANE_XY : PLANE_YZ)); } @@ -98,7 +98,7 @@ namespace MCore * @param v The vector representing the 3D point to use for the calculation. * @result The distance from 'v' to this plane, along the normal of this plane. */ - MCORE_INLINE float CalcDistanceTo(const AZ::Vector3& v) const { return mNormal.Dot(v) + mDist; } + MCORE_INLINE float CalcDistanceTo(const AZ::Vector3& v) const { return m_normal.Dot(v) + m_dist; } /** * Construct the plane when the normal of the plane and a point on the plane are known. @@ -107,8 +107,8 @@ namespace MCore */ MCORE_INLINE void Construct(const AZ::Vector3& normal, const AZ::Vector3& pointOnPlane) { - mNormal = normal; - mDist = -((normal.GetX() * pointOnPlane.GetX()) + (normal.GetY() * pointOnPlane.GetY()) + (normal.GetZ() * pointOnPlane.GetZ())); + m_normal = normal; + m_dist = -((normal.GetX() * pointOnPlane.GetX()) + (normal.GetY() * pointOnPlane.GetY()) + (normal.GetZ() * pointOnPlane.GetZ())); } /** @@ -118,8 +118,8 @@ namespace MCore */ MCORE_INLINE void Construct(const AZ::Vector3& normal, float d) { - mNormal = normal; - mDist = d; + m_normal = normal; + m_dist = d; } /** @@ -131,21 +131,21 @@ namespace MCore */ MCORE_INLINE void Construct(const AZ::Vector3& v1, const AZ::Vector3& v2, const AZ::Vector3& v3) { - mNormal = (v2 - v1).Cross(v3 - v1).GetNormalized(); - mDist = -(mNormal.Dot(v1)); + m_normal = (v2 - v1).Cross(v3 - v1).GetNormalized(); + m_dist = -(m_normal.Dot(v1)); } /** * Get the normal of the plane. * @result Returns the normal of the plane. */ - MCORE_INLINE const AZ::Vector3& GetNormal() const { return mNormal; } + MCORE_INLINE const AZ::Vector3& GetNormal() const { return m_normal; } /** * Get the 'd' out of the plane equation (Ax + By + Cz + d = 0). * @result Returns the 'd' from the plane equation. */ - MCORE_INLINE float GetDist() const { return mDist; } + MCORE_INLINE float GetDist() const { return m_dist; } /** * Checks if a given axis aligned bounding box (AABB) is partially above (aka in front) this plane or not. @@ -189,12 +189,12 @@ namespace MCore * @param vectorToProject The vector you wish to project onto the plane. * @result The projected vector. */ - MCORE_INLINE AZ::Vector3 Project(const AZ::Vector3& vectorToProject) { return vectorToProject - vectorToProject.Dot(mNormal) * mNormal; } + MCORE_INLINE AZ::Vector3 Project(const AZ::Vector3& vectorToProject) { return vectorToProject - vectorToProject.Dot(m_normal) * m_normal; } private: - AZ::Vector3 mNormal; /**< The normal of the plane. */ - float mDist; /**< The D in the plane equation (Ax + By + Cz + D = 0). */ + AZ::Vector3 m_normal; /**< The normal of the plane. */ + float m_dist; /**< The D in the plane equation (Ax + By + Cz + D = 0). */ }; // include the inline code diff --git a/Gems/EMotionFX/Code/MCore/Source/PlaneEq.inl b/Gems/EMotionFX/Code/MCore/Source/PlaneEq.inl index f59fcbc2ca..62ccb19551 100644 --- a/Gems/EMotionFX/Code/MCore/Source/PlaneEq.inl +++ b/Gems/EMotionFX/Code/MCore/Source/PlaneEq.inl @@ -12,11 +12,11 @@ MCORE_INLINE bool PlaneEq::PartiallyAbove(const AABB& box) const { const AZ::Vector3 minVec = box.GetMin(); const AZ::Vector3 maxVec = box.GetMax(); - const AZ::Vector3 testPoint(IsNegative(float(mNormal.GetX())) ? minVec.GetX() : maxVec.GetX(), - IsNegative(static_cast(mNormal.GetY())) ? minVec.GetY() : maxVec.GetY(), - IsNegative(static_cast(mNormal.GetZ())) ? minVec.GetZ() : maxVec.GetZ()); + const AZ::Vector3 testPoint(IsNegative(float(m_normal.GetX())) ? minVec.GetX() : maxVec.GetX(), + IsNegative(static_cast(m_normal.GetY())) ? minVec.GetY() : maxVec.GetY(), + IsNegative(static_cast(m_normal.GetZ())) ? minVec.GetZ() : maxVec.GetZ()); - return IsPositive(mNormal.Dot(testPoint) + mDist); + return IsPositive(m_normal.Dot(testPoint) + m_dist); } @@ -25,9 +25,9 @@ MCORE_INLINE bool PlaneEq::CompletelyAbove(const AABB& box) const { const AZ::Vector3 minVec = box.GetMin(); const AZ::Vector3 maxVec = box.GetMax(); - const AZ::Vector3 testPoint(IsPositive(mNormal.GetX()) ? minVec.GetX() : maxVec.GetX(), - IsPositive(mNormal.GetY()) ? minVec.GetY() : maxVec.GetY(), - IsPositive(mNormal.GetZ()) ? minVec.GetZ() : maxVec.GetZ()); + const AZ::Vector3 testPoint(IsPositive(m_normal.GetX()) ? minVec.GetX() : maxVec.GetX(), + IsPositive(m_normal.GetY()) ? minVec.GetY() : maxVec.GetY(), + IsPositive(m_normal.GetZ()) ? minVec.GetZ() : maxVec.GetZ()); - return IsPositive(mNormal.Dot(testPoint) + mDist); + return IsPositive(m_normal.Dot(testPoint) + m_dist); } diff --git a/Gems/EMotionFX/Code/MCore/Source/Random.cpp b/Gems/EMotionFX/Code/MCore/Source/Random.cpp index 393a8f36ed..2a21abc6ae 100644 --- a/Gems/EMotionFX/Code/MCore/Source/Random.cpp +++ b/Gems/EMotionFX/Code/MCore/Source/Random.cpp @@ -24,11 +24,11 @@ namespace MCore r |= 0x3f800000; //result is in [1,2), uniformly distributed union { - float f; - unsigned int i; + float m_f; + unsigned int m_i; } u; - u.i = r; - return u.f - 1.0f; + u.m_i = r; + return u.m_f - 1.0f; } // returns a random direction vector @@ -690,15 +690,15 @@ namespace MCore HaltonSequence::HaltonSequence() { // init members - mDimensions = 0; - mNextDim = 0; - mMemory = 0; - mN = 0; - mN0 = 0; - mX = nullptr; - mRadical = nullptr; - mBase = nullptr; - mOwnBase = false; + m_dimensions = 0; + m_nextDim = 0; + m_memory = 0; + m_n = 0; + m_n0 = 0; + m_x = nullptr; + m_radical = nullptr; + m_base = nullptr; + m_ownBase = false; } @@ -706,15 +706,15 @@ namespace MCore HaltonSequence::HaltonSequence(uint32 dimensions, uint32 offset, uint32* primes) { // init members - mDimensions = 0; - mNextDim = 0; - mMemory = 0; - mN = 0; - mN0 = 0; - mX = nullptr; - mRadical = nullptr; - mBase = nullptr; - mOwnBase = false; + m_dimensions = 0; + m_nextDim = 0; + m_memory = 0; + m_n = 0; + m_n0 = 0; + m_x = nullptr; + m_radical = nullptr; + m_base = nullptr; + m_ownBase = false; // initialize Init(dimensions, offset, primes); @@ -726,33 +726,33 @@ namespace MCore { MCORE_ASSERT(dimensions > 0); - mNextDim = 0; - mDimensions = dimensions; - mX = (double*)MCore::Allocate(dimensions * sizeof(double), MCORE_MEMCATEGORY_HALTONSEQ); - mMemory = sizeof(HaltonSequence) + dimensions * sizeof(double); + m_nextDim = 0; + m_dimensions = dimensions; + m_x = (double*)MCore::Allocate(dimensions * sizeof(double), MCORE_MEMCATEGORY_HALTONSEQ); + m_memory = sizeof(HaltonSequence) + dimensions * sizeof(double); - mN = offset; - mN0 = offset; - mRadical = (double*)MCore::Allocate(dimensions * sizeof(double), MCORE_MEMCATEGORY_HALTONSEQ); + m_n = offset; + m_n0 = offset; + m_radical = (double*)MCore::Allocate(dimensions * sizeof(double), MCORE_MEMCATEGORY_HALTONSEQ); - mOwnBase = (!primes); + m_ownBase = (!primes); - if (mOwnBase) + if (m_ownBase) { - mBase = FirstPrimes((uint32)dimensions); + m_base = FirstPrimes((uint32)dimensions); } else { - mBase = primes; + m_base = primes; } for (uint32 j = 0; j < dimensions; ++j) { - mRadical[j] = 1.0 / (double)mBase[j]; - mX[j] = 0.0; + m_radical[j] = 1.0 / (double)m_base[j]; + m_x[j] = 0.0; } - SetInstance(mN0); + SetInstance(m_n0); } @@ -765,23 +765,23 @@ namespace MCore void HaltonSequence::Release() { - if (mOwnBase && mBase) + if (m_ownBase && m_base) { - MCore::Free(mBase); + MCore::Free(m_base); } - mBase = nullptr; + m_base = nullptr; - if (mRadical) + if (m_radical) { - MCore::Free(mRadical); + MCore::Free(m_radical); } - mRadical = nullptr; + m_radical = nullptr; - if (mX) + if (m_x) { - MCore::Free(mX); + MCore::Free(m_x); } - mX = nullptr; + m_x = nullptr; } @@ -791,49 +791,49 @@ namespace MCore const double one = 1.0 - 1e-10; double h, hh, remainder; - mN++; + m_n++; - if (mN & 8191) + if (m_n & 8191) { - for (uint32 j = 0; j < mDimensions; ++j) + for (uint32 j = 0; j < m_dimensions; ++j) { - remainder = one - mX[j]; + remainder = one - m_x[j]; if (remainder < 0.0) { - mX[j] = 0.0; + m_x[j] = 0.0; } else { - if (mRadical[j] < remainder) + if (m_radical[j] < remainder) { - mX[j] += mRadical[j]; + m_x[j] += m_radical[j]; } else { - h = mRadical[j]; + h = m_radical[j]; do { hh = h; - h *= mRadical[j]; + h *= m_radical[j]; } while (h >= remainder); - mX[j] += hh + h - 1.0; + m_x[j] += hh + h - 1.0; } } } } else { - if (mN >= 1073741824) // 2^30 + if (m_n >= 1073741824) // 2^30 { SetInstance(0); } else { - SetInstance(mN); + SetInstance(m_n); } } } @@ -847,16 +847,16 @@ namespace MCore uint32 b; double fac; - mN = instance; - for (uint32 j = 0; j < mDimensions; ++j) + m_n = instance; + for (uint32 j = 0; j < m_dimensions; ++j) { - mX[j] = 0.0; - fac = mRadical[j]; - b = mBase[j]; + m_x[j] = 0.0; + fac = m_radical[j]; + b = m_base[j]; - for (im = mN; im > 0; im /= b, fac *= mRadical[j]) + for (im = m_n; im > 0; im /= b, fac *= m_radical[j]) { - mX[j] += fac * (double)(im % b); + m_x[j] += fac * (double)(im % b); } } } diff --git a/Gems/EMotionFX/Code/MCore/Source/Random.h b/Gems/EMotionFX/Code/MCore/Source/Random.h index 6e1a51fbb2..55576bb958 100644 --- a/Gems/EMotionFX/Code/MCore/Source/Random.h +++ b/Gems/EMotionFX/Code/MCore/Source/Random.h @@ -299,35 +299,35 @@ namespace MCore * Returns the number of dimensions in the sequence. * @result The number of dimensions. */ - uint32 GetNumDimensions() const { return mDimensions; } + uint32 GetNumDimensions() const { return m_dimensions; } /** * Get the memory usage in bytes by this sequence. * @result The memory usage in bytes by this sequence. */ - uint32 GetMemoryUsage() const { return mMemory; } + uint32 GetMemoryUsage() const { return m_memory; } /** * Get the current vector number. * @result The vector number. */ - uint32 GetVectorNumber() const { return (mN - mN0); } + uint32 GetVectorNumber() const { return (m_n - m_n0); } /** * Get the value of current dimension, and go to the next dimension. * @result The value of the current dimension, and step to the next dimension. */ - double GetNextDimension() { MCORE_ASSERT(mNextDim != mDimensions); return mX[mNextDim++]; } + double GetNextDimension() { MCORE_ASSERT(m_nextDim != m_dimensions); return m_x[m_nextDim++]; } /** * Reset the dimension stepping (by GetNextDimension()) and go to the first dimension again. */ - void ResetNextDimension() { mNextDim = 0; } + void ResetNextDimension() { m_nextDim = 0; } /** * Restart the sequence. */ - void Restart() { SetInstance(mN0); } + void Restart() { SetInstance(m_n0); } /** * Get the next values in the sequence. So update the dimension values. @@ -348,19 +348,19 @@ namespace MCore /** * Get a value for a given dimension. (*sequence[0]) would be the value of the first dimension and (*sequence[1]) would be the value of the second dimension, etc. */ - double operator[](uint32 j) const { MCORE_ASSERT(j < mDimensions); return mX[j]; } + double operator[](uint32 j) const { MCORE_ASSERT(j < m_dimensions); return m_x[j]; } private: - uint32 mDimensions; /**< The number of dimensions to generate random numbers for. */ - uint32 mNextDim; /**< The next dimension. */ - uint32 mMemory; /**< */ - uint32 mN; /**< */ - uint32 mN0; /**< */ - double* mX; /**< */ - double* mRadical; /**< */ - uint32* mBase; /**< Prime numbers. */ - bool mOwnBase; /**< Specifies whether we use our own primes or user specified. */ + uint32 m_dimensions; /**< The number of dimensions to generate random numbers for. */ + uint32 m_nextDim; /**< The next dimension. */ + uint32 m_memory; /**< */ + uint32 m_n; /**< */ + uint32 m_n0; /**< */ + double* m_x; /**< */ + double* m_radical; /**< */ + uint32* m_base; /**< Prime numbers. */ + bool m_ownBase; /**< Specifies whether we use our own primes or user specified. */ /** * Generates the first n number of primes. diff --git a/Gems/EMotionFX/Code/MCore/Source/Ray.cpp b/Gems/EMotionFX/Code/MCore/Source/Ray.cpp index 9498635c3f..7df1188e77 100644 --- a/Gems/EMotionFX/Code/MCore/Source/Ray.cpp +++ b/Gems/EMotionFX/Code/MCore/Source/Ray.cpp @@ -20,23 +20,23 @@ namespace MCore // ray-boundingsphere bool Ray::Intersects(const BoundingSphere& s, AZ::Vector3* intersectA, AZ::Vector3* intersectB) const { - const AZ::Vector3 rayOrg = mOrigin - s.GetCenter(); // ray in space of the sphere + const AZ::Vector3 rayOrg = m_origin - s.GetCenter(); // ray in space of the sphere // The Intersection can be solved by finding the solutions of the quadratic equation: - // (mOrigin + t * mDirection)^2 - s.GetRadiusSquared() = 0 - // Where t is a value that makes (mOrigin + t * mDirection) intersect the sphere + // (m_origin + t * m_direction)^2 - s.GetRadiusSquared() = 0 + // Where t is a value that makes (m_origin + t * m_direction) intersect the sphere // Expanding the above equation we have to find t1 and t2: - // t1 = (-2 * mOrigin * mDirection + sqrt(delta)) / (2 * mDirection^2) - // t2 = (-2 * mOrigin * mDirection - sqrt(delta)) / (2 * mDirection^2) - // where delta = (2 * mOrigin * mDirection) ^ 2 - 4 * mDirection^2 * (mOrigin^2 - s.GetRadiusSquared()) + // t1 = (-2 * m_origin * m_direction + sqrt(delta)) / (2 * m_direction^2) + // t2 = (-2 * m_origin * m_direction - sqrt(delta)) / (2 * m_direction^2) + // where delta = (2 * m_origin * m_direction) ^ 2 - 4 * m_direction^2 * (m_origin^2 - s.GetRadiusSquared()) // The two intersection points will be: - // mOrigin + mDirection * t1 - // mOrigin + mDirection * t2 + // m_origin + m_direction * t1 + // m_origin + m_direction * t2 // If delta < 0, then there is no intersection // If delta == 0, it intersects int he same point // - const float a = mDirection.GetLengthSq(); - const float b = 2.0f * mDirection.Dot(rayOrg); + const float a = m_direction.GetLengthSq(); + const float b = 2.0f * m_direction.Dot(rayOrg); const float c = rayOrg.GetLengthSq() - s.GetRadiusSquared(); const float delta = ((b * b) - 4.0f * a * c); @@ -63,22 +63,22 @@ namespace MCore { if (intersectA) { - (*intersectA) = mOrigin + mDirection * t1; + (*intersectA) = m_origin + m_direction * t1; } if (intersectB) { - (*intersectB) = mOrigin + mDirection * t2; + (*intersectB) = m_origin + m_direction * t2; } } else { if (intersectA) { - (*intersectA) = mOrigin + mDirection * t2; + (*intersectA) = m_origin + m_direction * t2; } if (intersectB) { - (*intersectB) = mOrigin + mDirection * t1; + (*intersectB) = m_origin + m_direction * t1; } } } @@ -88,11 +88,11 @@ namespace MCore const float t = -0.5f * b / a; if (intersectA) { - (*intersectA) = mOrigin + mDirection * t; + (*intersectA) = m_origin + m_direction * t; } if (intersectB) { - (*intersectB) = mOrigin + mDirection * t; + (*intersectB) = m_origin + m_direction * t; } } @@ -104,11 +104,11 @@ namespace MCore bool Ray::Intersects(const PlaneEq& p, AZ::Vector3* intersect) const { // check if ray is parallel to plane (no intersection) or ray pointing away from plane (no intersection) - float dot1 = p.GetNormal().Dot(mDirection); + float dot1 = p.GetNormal().Dot(m_direction); //if (dot1 >= 0) return false; // backface cull // calc second dot product - float dot2 = -(p.GetNormal().Dot(mOrigin) + p.GetDist()); + float dot2 = -(p.GetNormal().Dot(m_origin) + p.GetDist()); // calc t value float t = dot2 / dot1; @@ -127,9 +127,9 @@ namespace MCore // calc intersection point if (intersect) { - intersect->SetX(mOrigin.GetX() + (mDirection.GetX() * t)); - intersect->SetY(mOrigin.GetY() + (mDirection.GetY() * t)); - intersect->SetZ(mOrigin.GetZ() + (mDirection.GetZ() * t)); + intersect->SetX(m_origin.GetX() + (m_direction.GetX() * t)); + intersect->SetY(m_origin.GetY() + (m_direction.GetY() * t)); + intersect->SetZ(m_origin.GetZ() + (m_direction.GetZ() * t)); } return true; @@ -144,7 +144,7 @@ namespace MCore const AZ::Vector3 edge2 = p3 - p1; // begin calculating determinant - also used to calculate U parameter - const AZ::Vector3 dir = mDest - mOrigin; + const AZ::Vector3 dir = m_dest - m_origin; const AZ::Vector3 pvec = dir.Cross(edge2); // if determinant is near zero, ray lies in plane of triangle @@ -155,7 +155,7 @@ namespace MCore } // calculate distance from vert0 to ray origin - const AZ::Vector3 tvec = mOrigin - p1; + const AZ::Vector3 tvec = m_origin - p1; // calculate U parameter and test bounds const float inv_det = 1.0f / det; @@ -193,7 +193,7 @@ namespace MCore } if (intersect) { - *intersect = mOrigin + t * dir; + *intersect = m_origin + t * dir; } // yes, there was an intersection @@ -212,10 +212,10 @@ namespace MCore // For all three axes, check the near and far intersection point on the two slabs for (int32 i = 0; i < 3; i++) { - if (Math::Abs(mDirection.GetElement(i)) < Math::epsilon) + if (Math::Abs(m_direction.GetElement(i)) < Math::epsilon) { // direction is parallel to this plane, check if we're somewhere between min and max - if ((mOrigin.GetElement(i) < minVec.GetElement(i)) || (mOrigin.GetElement(i) > maxVec.GetElement(i))) + if ((m_origin.GetElement(i) < minVec.GetElement(i)) || (m_origin.GetElement(i) > maxVec.GetElement(i))) { return false; } @@ -223,8 +223,8 @@ namespace MCore else { // calculate t's at the near and far slab, see if these are min or max t's - float t1 = (minVec.GetElement(i) - mOrigin.GetElement(i)) / mDirection.GetElement(i); - float t2 = (maxVec.GetElement(i) - mOrigin.GetElement(i)) / mDirection.GetElement(i); + float t1 = (minVec.GetElement(i) - m_origin.GetElement(i)) / m_direction.GetElement(i); + float t2 = (maxVec.GetElement(i) - m_origin.GetElement(i)) / m_direction.GetElement(i); if (t1 > t2) { float temp = t1; @@ -248,12 +248,12 @@ namespace MCore if (intersectA) { - *intersectA = mOrigin + mDirection * tNear; + *intersectA = m_origin + m_direction * tNear; } if (intersectB) { - *intersectB = mOrigin + mDirection * tFar; + *intersectB = m_origin + m_direction * tFar; } return true; diff --git a/Gems/EMotionFX/Code/MCore/Source/Ray.h b/Gems/EMotionFX/Code/MCore/Source/Ray.h index f5fa779bd2..1d5bec0f43 100644 --- a/Gems/EMotionFX/Code/MCore/Source/Ray.h +++ b/Gems/EMotionFX/Code/MCore/Source/Ray.h @@ -46,9 +46,9 @@ namespace MCore * @param endPoint The end (destination) point of the ray. */ MCORE_INLINE Ray(const AZ::Vector3& org, const AZ::Vector3& endPoint) - : mOrigin(org) - , mDest(endPoint) - , mDirection((endPoint - org).GetNormalized()) {} + : m_origin(org) + , m_dest(endPoint) + , m_direction((endPoint - org).GetNormalized()) {} /** * Constructor which sets the origin, destination point and direction. @@ -57,9 +57,9 @@ namespace MCore * @param dir The normalized direction vector of the ray, which should be (endPoint - startPoint).Normalize() */ MCORE_INLINE Ray(const AZ::Vector3& org, const AZ::Vector3& endPoint, const AZ::Vector3& dir) - : mOrigin(org) - , mDest(endPoint) - , mDirection(dir) {} + : m_origin(org) + , m_dest(endPoint) + , m_direction(dir) {} /** * Set the origin and destination point (end point) of the ray. @@ -67,37 +67,37 @@ namespace MCore * @param org The origin of the ray, so the start point. * @param endPoint The destination of the ray, so the end point. */ - MCORE_INLINE void Set(const AZ::Vector3& org, const AZ::Vector3& endPoint) { mOrigin = org; mDest = endPoint; mDirection = (mDest - mOrigin).GetNormalized(); } + MCORE_INLINE void Set(const AZ::Vector3& org, const AZ::Vector3& endPoint) { m_origin = org; m_dest = endPoint; m_direction = (m_dest - m_origin).GetNormalized(); } /** * Set the origin of the ray, so the start point. The direction will automatically be updated as well. * @param org The origin. */ - MCORE_INLINE void SetOrigin(const AZ::Vector3& org) { mOrigin = org; mDirection = (mDest - mOrigin).GetNormalized(); } + MCORE_INLINE void SetOrigin(const AZ::Vector3& org) { m_origin = org; m_direction = (m_dest - m_origin).GetNormalized(); } /** * Set the destination point of the ray. * @param dest The destination of the ray. */ - MCORE_INLINE void SetDest(const AZ::Vector3& dest) { mDest = dest; mDirection = (mDest - mOrigin).GetNormalized(); } + MCORE_INLINE void SetDest(const AZ::Vector3& dest) { m_dest = dest; m_direction = (m_dest - m_origin).GetNormalized(); } /** * Get the origin of the ray. * @result The origin of the ray, so where it starts. */ - MCORE_INLINE const AZ::Vector3& GetOrigin() const { return mOrigin; } + MCORE_INLINE const AZ::Vector3& GetOrigin() const { return m_origin; } /** * Get the destination of the ray. * @result The destination point of the ray, so where it ends. */ - MCORE_INLINE const AZ::Vector3& GetDest() const { return mDest; } + MCORE_INLINE const AZ::Vector3& GetDest() const { return m_dest; } /** * Get the direction of the ray. * @result The normalized direction vector of the ray, so the direction its heading to. */ - MCORE_INLINE const AZ::Vector3& GetDirection() const { return mDirection; } + MCORE_INLINE const AZ::Vector3& GetDirection() const { return m_direction; } /** * Perform a ray/sphere intersection test. @@ -161,11 +161,11 @@ namespace MCore * Calculates the length of the ray. * @result The length of the ray. */ - MCORE_INLINE float Length() const { return SafeLength(mDest - mOrigin); } + MCORE_INLINE float Length() const { return SafeLength(m_dest - m_origin); } private: - AZ::Vector3 mOrigin; /**< The origin of the ray. */ - AZ::Vector3 mDest; /**< The destination of the ray. */ - AZ::Vector3 mDirection; /**< The normalized direction vector of the ray. */ + AZ::Vector3 m_origin; /**< The origin of the ray. */ + AZ::Vector3 m_dest; /**< The destination of the ray. */ + AZ::Vector3 m_direction; /**< The normalized direction vector of the ray. */ }; } // namespace MCore diff --git a/Gems/EMotionFX/Code/MCore/Source/SmallArray.h b/Gems/EMotionFX/Code/MCore/Source/SmallArray.h index 69e3219b7f..ab94cabbfe 100644 --- a/Gems/EMotionFX/Code/MCore/Source/SmallArray.h +++ b/Gems/EMotionFX/Code/MCore/Source/SmallArray.h @@ -36,32 +36,32 @@ class SmallArray * Default constructor. * Initializes the array so it's empty and has no memory allocated. */ - MCORE_INLINE SmallArray() : mData(nullptr), mLength(0) {} + MCORE_INLINE SmallArray() : m_data(nullptr), m_length(0) {} /** * Constructor which creates a given number of elements. * @param elems The element data. * @param num The number of elements in 'elems'. */ - MCORE_INLINE explicit SmallArray(T* elems, uint32 num) : mLength(num) { mData = (T*)MCore::Allocate(mLength * sizeof(T), MCORE_MEMCATEGORY_SMALLARRAY, MEMORYBLOCK_ID, MCORE_FILE, MCORE_LINE); for (uint32 i=0; i 0) { mData = (T*)MCore::Allocate(mLength * sizeof(T), MCORE_MEMCATEGORY_SMALLARRAY, MEMORYBLOCK_ID, MCORE_FILE, MCORE_LINE); for (uint32 i=0; i 0) { m_data = (T*)MCore::Allocate(m_length * sizeof(T), MCORE_MEMCATEGORY_SMALLARRAY, MEMORYBLOCK_ID, MCORE_FILE, MCORE_LINE); for (uint32 i=0; i& other) : mData(nullptr), mLength(0) { *this = other; } + SmallArray(const SmallArray& other) : m_data(nullptr), m_length(0) { *this = other; } /** * Move constructor. * @param other The array to move the data from. */ - SmallArray(SmallArray&& other) { mData=other.mData; mLength=other.mLength; other.mData=nullptr; other.mLength=0; } + SmallArray(SmallArray&& other) { m_data=other.m_data; m_length=other.m_length; other.m_data=nullptr; other.m_length=0; } /** * Destructor. Deletes all entry data. @@ -80,143 +80,143 @@ class SmallArray * data.Clear(); * */ - ~SmallArray() { for (uint32 i=0; i); return result; } + MCORE_INLINE uint32 CalcMemoryUsage(bool includeMembers=true) const { uint32 result = m_length*sizeof(T); if (includeMembers) result+=sizeof(MCore::SmallArray); return result; } /** * Set a given element to a given value. * @param pos The element number. * @param value The value to store at that element number. */ - MCORE_INLINE void SetElem(uint32 pos, const T& value) { mData[pos] = value; } + MCORE_INLINE void SetElem(uint32 pos, const T& value) { m_data[pos] = value; } /** * Add a given element to the back of the array. * @param x The element to add. */ - MCORE_INLINE void Add(const T& x) { Grow(++mLength); Construct(mLength-1, x); } + MCORE_INLINE void Add(const T& x) { Grow(++m_length); Construct(m_length-1, x); } /** * Add a given array to the back of this array. * @param a The array to add. */ - MCORE_INLINE void Add(const SmallArray& a) { uint32 l=mLength; Grow(mLength+a.mLength); for (uint32 i=0; i& a) { uint32 l=m_length; Grow(m_length+a.m_length); for (uint32 i=0; i 0) Remove((uint32)0); } + MCORE_INLINE void RemoveFirst() { if (m_length > 0) Remove((uint32)0); } /** * Remove the last array element. */ - MCORE_INLINE void RemoveLast() { if (mLength > 0) Destruct(--mLength); } + MCORE_INLINE void RemoveLast() { if (m_length > 0) Destruct(--m_length); } /** * Insert an empty element (default constructed) at a given position in the array. * @param pos The position to create the empty element. */ - MCORE_INLINE void Insert(uint32 pos) { Grow(mLength+1); MoveElements(pos+1, pos, mLength-pos-1); Construct(pos); } + MCORE_INLINE void Insert(uint32 pos) { Grow(m_length+1); MoveElements(pos+1, pos, m_length-pos-1); Construct(pos); } /** * Insert a given element at a given position in the array. * @param pos The position to insert the empty element. * @param x The element to store at this position. */ - MCORE_INLINE void Insert(uint32 pos, const T& x) { Grow(mLength+1); MoveElements(pos+1, pos, mLength-pos-1); Construct(pos, x); } + MCORE_INLINE void Insert(uint32 pos, const T& x) { Grow(m_length+1); MoveElements(pos+1, pos, m_length-pos-1); Construct(pos, x); } /** * Remove an element at a given position. * @param pos The element number to remove. */ - MCORE_INLINE void Remove(uint32 pos) { Destruct(pos); MoveElements(pos, pos+1, mLength-pos-1); mLength--; } + MCORE_INLINE void Remove(uint32 pos) { Destruct(pos); MoveElements(pos, pos+1, m_length-pos-1); m_length--; } /** * Remove a given number of elements starting at a given position in the array. * @param pos The start element, so to start removing from. * @param num The number of elements to remove from this position. */ - MCORE_INLINE void Remove(uint32 pos, uint32 num) { for (uint32 i=pos; i * ABGDEF [this is the result. G has been moved to the empty position]. */ - MCORE_INLINE void SwapRemove(uint32 pos) { Destruct(pos); if (pos != mLength-1) { Construct(pos, mData[mLength-1]); Destruct(mLength-1); } mLength--; } // remove element at and place the last element of the array in that position + MCORE_INLINE void SwapRemove(uint32 pos) { Destruct(pos); if (pos != m_length-1) { Construct(pos, m_data[m_length-1]); Destruct(m_length-1); } m_length--; } // remove element at and place the last element of the array in that position /** * Swap two elements. @@ -247,19 +247,19 @@ class SmallArray * @param clearMem If set to true (default) the allocated memory will also be released. If set to false, GetMaxLength() will still return the number of elements * which the array contained before calling the Clear() method. */ - MCORE_INLINE void Clear(bool clearMem=true) { for (uint32 i=0; i= newLength) return; uint32 oldLen=mLength; Grow(newLength); for (uint32 i=oldLen; i= newLength) return; uint32 oldLen=m_length; Grow(newLength); for (uint32 i=oldLen; i mLength) + if (newLength > m_length) { // growing array, construct empty elements at end of array - uint32 oldLen = mLength; + uint32 oldLen = m_length; GrowExact(newLength); - if (mData == nullptr) + if (m_data == nullptr) { return false; } @@ -329,10 +329,10 @@ class SmallArray else { // shrinking array, destruct elements at end of array - for (uint32 i=newLength; i 0) - MCore::MemMove(mData+destIndex, mData+sourceIndex, numElements * sizeof(T)); + MCore::MemMove(m_data+destIndex, m_data+sourceIndex, numElements * sizeof(T)); } // operators - bool operator==(const SmallArray& other) const { if (mLength != other.mLength) return false; for (uint32 i=0; i& operator= (const SmallArray& other) { if (&other != this) { Clear(); Grow(other.mLength); for (uint32 i=0; i& operator= (SmallArray&& other) { MCORE_ASSERT(&other != this); if (mData!=nullptr) MCore::Free(mData); mData=other.mData; mLength=other.mLength; other.mData=nullptr; other.mLength=0; return *this; } - //SmallArray& operator+ (const SmallArray& other) const { SmallArray newArray; newArray.Grow(mLength+other.mLength); uint32 i; for (i=0; i& other) const { if (m_length != other.m_length) return false; for (uint32 i=0; i& operator= (const SmallArray& other) { if (&other != this) { Clear(); Grow(other.m_length); for (uint32 i=0; i& operator= (SmallArray&& other) { MCORE_ASSERT(&other != this); if (m_data!=nullptr) MCore::Free(m_data); m_data=other.m_data; m_length=other.m_length; other.m_data=nullptr; other.m_length=0; return *this; } SmallArray& operator+=(const T& other) { Add(other); return *this; } SmallArray& operator+=(const SmallArray& other) { Add(other); return *this; } - MCORE_INLINE T& operator[](const uint32 index) { MCORE_ASSERT(indexFree(); return; } - if (mData) - mData = (T*)MCore::Realloc(mData, newSize * sizeof(T), MCORE_MEMCATEGORY_SMALLARRAY, MEMORYBLOCK_ID, MCORE_FILE, MCORE_LINE); + if (m_data) + m_data = (T*)MCore::Realloc(m_data, newSize * sizeof(T), MCORE_MEMCATEGORY_SMALLARRAY, MEMORYBLOCK_ID, MCORE_FILE, MCORE_LINE); else - mData = (T*)MCore::Allocate(newSize * sizeof(T), MCORE_MEMCATEGORY_SMALLARRAY, MEMORYBLOCK_ID, MCORE_FILE, MCORE_LINE); + m_data = (T*)MCore::Allocate(newSize * sizeof(T), MCORE_MEMCATEGORY_SMALLARRAY, MEMORYBLOCK_ID, MCORE_FILE, MCORE_LINE); } - MCORE_INLINE void Free() { mLength=0; if (mData) MCore::Free(mData); mData=nullptr; } - MCORE_INLINE void Construct(uint32 index, const T& original) { ::new(mData+index) T(original); } // copy-construct an element at which is a copy of - MCORE_INLINE void Construct(uint32 index) { ::new(mData+index) T; } // construct an element at place + MCORE_INLINE void Free() { m_length=0; if (m_data) MCore::Free(m_data); m_data=nullptr; } + MCORE_INLINE void Construct(uint32 index, const T& original) { ::new(m_data+index) T(original); } // copy-construct an element at which is a copy of + MCORE_INLINE void Construct(uint32 index) { ::new(m_data+index) T; } // construct an element at place MCORE_INLINE void Destruct(uint32 index) { #if (MCORE_COMPILER == MCORE_COMPILER_MSVC) // work around a compiler bug, marking this index parameter as unused MCORE_UNUSED(index); #endif - (mData+index)->~T(); + (m_data+index)->~T(); } // destruct an element at // partition part of array (for sorting) int32 Partition(int32 left, int32 right, CmpFunc cmp) { - ::MCore::Swap(mData[left], mData[ (left+right)>>1 ]); + ::MCore::Swap(m_data[left], m_data[ (left+right)>>1 ]); - T& target = mData[right]; + T& target = m_data[right]; int32 i = left-1; int32 j = right; bool neverQuit = true; // workaround to disable a "warning C4127: conditional expression is constant" while (neverQuit) { - while (i < j) { if (cmp(mData[++i], target) >= 0) break; } - while (j > i) { if (cmp(mData[--j], target) <= 0) break; } + while (i < j) { if (cmp(m_data[++i], target) >= 0) break; } + while (j > i) { if (cmp(m_data[--j], target) <= 0) break; } if (i >= j) break; - ::MCore::Swap(mData[i], mData[j]); + ::MCore::Swap(m_data[i], m_data[j]); } - ::MCore::Swap(mData[i], mData[right]); + ::MCore::Swap(m_data[i], m_data[right]); return i; } }; diff --git a/Gems/EMotionFX/Code/MCore/Source/StringIdPool.cpp b/Gems/EMotionFX/Code/MCore/Source/StringIdPool.cpp index dc08f628fe..643258373b 100644 --- a/Gems/EMotionFX/Code/MCore/Source/StringIdPool.cpp +++ b/Gems/EMotionFX/Code/MCore/Source/StringIdPool.cpp @@ -29,13 +29,13 @@ namespace MCore { Lock(); - for (AZStd::basic_string*& string : mStrings) + for (AZStd::basic_string*& string : m_strings) { delete string; } - mStrings.clear(); + m_strings.clear(); - mStringToIndex.clear(); + m_stringToIndex.clear(); Unlock(); } @@ -43,7 +43,7 @@ namespace MCore AZ::u32 StringIdPool::GenerateIdForStringWithoutLock(const AZStd::string& objectName) { // Try to insert it, if we hit a collision, we have the element. - auto iterator = mStringToIndex.emplace(objectName, aznumeric_caster(mStrings.size())); + auto iterator = m_stringToIndex.emplace(objectName, aznumeric_caster(m_strings.size())); if (!iterator.second) { // could not insert, we have the element @@ -52,7 +52,7 @@ namespace MCore // Create the new string object and push it to the string list. AZStd::string* newString = new AZStd::string(objectName); - mStrings.push_back(newString); + m_strings.push_back(newString); // The string was already added to the hashmap return iterator.first->second; @@ -72,7 +72,7 @@ namespace MCore { Lock(); MCORE_ASSERT(id != InvalidIndex32); - const AZStd::string* stringAddress = mStrings[id]; + const AZStd::string* stringAddress = m_strings[id]; Unlock(); return *stringAddress; } @@ -81,7 +81,7 @@ namespace MCore void StringIdPool::Reserve(size_t numStrings) { Lock(); - mStrings.reserve(numStrings); + m_strings.reserve(numStrings); Unlock(); } @@ -89,27 +89,27 @@ namespace MCore // Wait with execution until we can set the lock. void StringIdPool::Lock() { - mMutex.Lock(); + m_mutex.Lock(); } // Release the lock again. void StringIdPool::Unlock() { - mMutex.Unlock(); + m_mutex.Unlock(); } void StringIdPool::Log(bool includeEntries) { - AZ_Printf("EMotionFX", "StringIdPool: NumEntries=%d\n", mStrings.size()); + AZ_Printf("EMotionFX", "StringIdPool: NumEntries=%d\n", m_strings.size()); if (includeEntries) { - const size_t numStrings = mStrings.size(); + const size_t numStrings = m_strings.size(); for (size_t i = 0; i < numStrings; ++i) { - AZ_Printf("EMotionFX", " #%d: String='%s', Id=%d\n", i, mStrings[i]->c_str(), GenerateIdForString(mStrings[i]->c_str())); + AZ_Printf("EMotionFX", " #%d: String='%s', Id=%d\n", i, m_strings[i]->c_str(), GenerateIdForString(m_strings[i]->c_str())); } } } diff --git a/Gems/EMotionFX/Code/MCore/Source/StringIdPool.h b/Gems/EMotionFX/Code/MCore/Source/StringIdPool.h index 9f58adf028..75bbc1b010 100644 --- a/Gems/EMotionFX/Code/MCore/Source/StringIdPool.h +++ b/Gems/EMotionFX/Code/MCore/Source/StringIdPool.h @@ -66,9 +66,9 @@ namespace MCore private: - AZStd::vector mStrings; - AZStd::unordered_map mStringToIndex; /**< The string to index table, where the index maps into mNames array and is directly the ID. */ - Mutex mMutex; /**< The multithread lock. */ + AZStd::vector m_strings; + AZStd::unordered_map m_stringToIndex; /**< The string to index table, where the index maps into m_names array and is directly the ID. */ + Mutex m_mutex; /**< The multithread lock. */ StringIdPool(); ~StringIdPool(); diff --git a/Gems/EMotionFX/Code/MysticQt/Source/DialogStack.cpp b/Gems/EMotionFX/Code/MysticQt/Source/DialogStack.cpp index 6a6d540519..27f83b07a3 100644 --- a/Gems/EMotionFX/Code/MysticQt/Source/DialogStack.cpp +++ b/Gems/EMotionFX/Code/MysticQt/Source/DialogStack.cpp @@ -60,15 +60,15 @@ namespace MysticQt setObjectName("DialogStack"); // create the root splitter - mRootSplitter = new DialogStackSplitter(); - mRootSplitter->setOrientation(Qt::Vertical); - mRootSplitter->setChildrenCollapsible(false); + m_rootSplitter = new DialogStackSplitter(); + m_rootSplitter->setOrientation(Qt::Vertical); + m_rootSplitter->setChildrenCollapsible(false); // set the widget resizable to have the scrollarea resizing it setWidgetResizable(true); // set the scrollarea widget - setWidget(mRootSplitter); + setWidget(m_rootSplitter); } @@ -82,7 +82,7 @@ namespace MysticQt void DialogStack::Clear() { // destroy the dialogs - mDialogs.clear(); + m_dialogs.clear(); // update the scroll bars UpdateScrollBars(); @@ -103,10 +103,10 @@ namespace MysticQt // add the dialog widget // the splitter is hierarchical : {a, {b, c}} DialogStackSplitter* dialogSplitter; - if (mDialogs.empty()) + if (m_dialogs.empty()) { // add the dialog widget - dialogSplitter = mRootSplitter; + dialogSplitter = m_rootSplitter; dialogSplitter->addWidget(dialogWidget); // stretch if needed @@ -118,10 +118,10 @@ namespace MysticQt else { // check if one space is free on the last splitter - if (mDialogs.back().mSplitter->count() == 1) + if (m_dialogs.back().m_splitter->count() == 1) { // add the dialog widget - dialogSplitter = mDialogs.back().mSplitter; + dialogSplitter = m_dialogs.back().m_splitter; dialogSplitter->addWidget(dialogWidget); // stretch if needed @@ -131,16 +131,16 @@ namespace MysticQt } // less space used by the splitter when the last dialog is closed - if (mDialogs.back().mFrame->isHidden()) + if (m_dialogs.back().m_frame->isHidden()) { - mDialogs.back().mSplitter->handle(1)->setFixedHeight(1); - mDialogs.back().mSplitter->setStyleSheet("QSplitter::handle{ height: 1px; background: transparent; }"); + m_dialogs.back().m_splitter->handle(1)->setFixedHeight(1); + m_dialogs.back().m_splitter->setStyleSheet("QSplitter::handle{ height: 1px; background: transparent; }"); } // disable the splitter - if (mDialogs.back().mFrame->isHidden()) + if (m_dialogs.back().m_frame->isHidden()) { - mDialogs.back().mSplitter->handle(1)->setDisabled(true); + m_dialogs.back().m_splitter->handle(1)->setDisabled(true); } } else // already two dialogs in the splitter @@ -151,24 +151,24 @@ namespace MysticQt dialogSplitter->setChildrenCollapsible(false); // add the current last dialog and the new dialog after - dialogSplitter->addWidget(mDialogs.back().mDialogWidget); + dialogSplitter->addWidget(m_dialogs.back().m_dialogWidget); dialogSplitter->addWidget(dialogWidget); // stretch if needed - if (mDialogs.back().mMaximizeSize && mDialogs.back().mStretchWhenMaximize) + if (m_dialogs.back().m_maximizeSize && m_dialogs.back().m_stretchWhenMaximize) { dialogSplitter->setStretchFactor(0, 1); } // less space used by the splitter when the last dialog is closed - if (mDialogs.back().mFrame->isHidden()) + if (m_dialogs.back().m_frame->isHidden()) { dialogSplitter->handle(1)->setFixedHeight(1); dialogSplitter->setStyleSheet("QSplitter::handle{ height: 1px; background: transparent; }"); } // disable the splitter - if (mDialogs.back().mFrame->isHidden()) + if (m_dialogs.back().m_frame->isHidden()) { dialogSplitter->handle(1)->setDisabled(true); } @@ -180,27 +180,27 @@ namespace MysticQt } // replace the last dialog by the new splitter - mDialogs.back().mSplitter->addWidget(dialogSplitter); + m_dialogs.back().m_splitter->addWidget(dialogSplitter); // disable the splitter - if (mDialogs.size() > 1) + if (m_dialogs.size() > 1) { - const auto previousDialogIt = mDialogs.end() - 2; - if (previousDialogIt->mFrame->isHidden()) + const auto previousDialogIt = m_dialogs.end() - 2; + if (previousDialogIt->m_frame->isHidden()) { - mDialogs.back().mSplitter->handle(1)->setDisabled(true); + m_dialogs.back().m_splitter->handle(1)->setDisabled(true); } // stretch the splitter if needed // the correct behavior is found after experimentations - if ((mDialogs.back().mMaximizeSize && mDialogs.back().mStretchWhenMaximize) || (previousDialogIt->mMaximizeSize && previousDialogIt->mStretchWhenMaximize == false)) + if ((m_dialogs.back().m_maximizeSize && m_dialogs.back().m_stretchWhenMaximize) || (previousDialogIt->m_maximizeSize && previousDialogIt->m_stretchWhenMaximize == false)) { - mDialogs.back().mSplitter->setStretchFactor(1, 1); + m_dialogs.back().m_splitter->setStretchFactor(1, 1); } } // set the new splitter of the last dialog - mDialogs.back().mSplitter = dialogSplitter; + m_dialogs.back().m_splitter = dialogSplitter; } } @@ -263,19 +263,19 @@ namespace MysticQt dialogWidget->adjustSize(); // register it, so that we know which frame is linked to which header button - mDialogs.emplace_back(Dialog{ - /*.mButton =*/ headerButton, - /*.mFrame =*/ frame, - /*.mWidget =*/ widget, - /*.mDialogWidget =*/ dialogWidget, - /*.mSplitter =*/ dialogSplitter, - /*.mClosable =*/ closable, - /*.mMaximizeSize =*/ maximizeSize, - /*.mStretchWhenMaximize =*/ stretchWhenMaximize, - /*.mMinimumHeightBeforeClose =*/ 0, - /*.mMaximumHeightBeforeClose =*/ 0, - /*.mLayout =*/ layout, - /*.mDialogLayout =*/ dialogLayout, + m_dialogs.emplace_back(Dialog{ + /*.m_button =*/ headerButton, + /*.m_frame =*/ frame, + /*.m_widget =*/ widget, + /*.m_dialogWidget =*/ dialogWidget, + /*.m_splitter =*/ dialogSplitter, + /*.m_closable =*/ closable, + /*.m_maximizeSize =*/ maximizeSize, + /*.m_stretchWhenMaximize =*/ stretchWhenMaximize, + /*.m_minimumHeightBeforeClose =*/ 0, + /*.m_maximumHeightBeforeClose =*/ 0, + /*.m_layout =*/ layout, + /*.m_dialogLayout =*/ dialogLayout, }); // check if the dialog is closed @@ -305,12 +305,12 @@ namespace MysticQt bool DialogStack::Remove(QWidget* widget) { - const auto foundDialog = AZStd::find_if(begin(mDialogs), end(mDialogs), [widget](const Dialog& dialog) + const auto foundDialog = AZStd::find_if(begin(m_dialogs), end(m_dialogs), [widget](const Dialog& dialog) { - return dialog.mFrame->layout()->indexOf(widget) != -1; + return dialog.m_frame->layout()->indexOf(widget) != -1; }); - if (foundDialog == end(mDialogs)) + if (foundDialog == end(m_dialogs)) { return false; } @@ -318,9 +318,9 @@ namespace MysticQt // if the widget is located in the current layout, remove it // all next dialogs has to be moved to the previous splitter and delete if the last splitter is empty // TODO : shift all dialogs needed as explained on the previous comment - foundDialog->mDialogWidget->hide(); - foundDialog->mDialogWidget->deleteLater(); - mDialogs.erase(foundDialog); + foundDialog->m_dialogWidget->hide(); + foundDialog->m_dialogWidget->deleteLater(); + m_dialogs.erase(foundDialog); // update the scroll bars UpdateScrollBars(); @@ -334,7 +334,7 @@ namespace MysticQt { QPushButton* button = (QPushButton*)sender(); const size_t dialogIndex = FindDialog(button); - if (mDialogs[dialogIndex].mFrame->isHidden()) + if (m_dialogs[dialogIndex].m_frame->isHidden()) { Open(button); } @@ -348,83 +348,83 @@ namespace MysticQt // find the dialog that goes with the given button size_t DialogStack::FindDialog(QPushButton* pushButton) { - const auto foundDialog = AZStd::find_if(begin(mDialogs), end(mDialogs), [pushButton](const Dialog& dialog) + const auto foundDialog = AZStd::find_if(begin(m_dialogs), end(m_dialogs), [pushButton](const Dialog& dialog) { - return dialog.mButton == pushButton; + return dialog.m_button == pushButton; }); - return foundDialog != end(mDialogs) ? AZStd::distance(begin(mDialogs), foundDialog) : MCore::InvalidIndex; + return foundDialog != end(m_dialogs) ? AZStd::distance(begin(m_dialogs), foundDialog) : MCore::InvalidIndex; } // open the dialog void DialogStack::Open(QPushButton* button) { - const auto dialog = AZStd::find_if(begin(mDialogs), end(mDialogs), [button](const Dialog& dialog) + const auto dialog = AZStd::find_if(begin(m_dialogs), end(m_dialogs), [button](const Dialog& dialog) { - return dialog.mButton == button; + return dialog.m_button == button; }); - if (dialog == end(mDialogs)) + if (dialog == end(m_dialogs)) { return; } // show the widget inside the dialog - dialog->mFrame->show(); + dialog->m_frame->show(); // set the previous minimum and maximum height before closed - dialog->mDialogWidget->setMinimumHeight(dialog->mMinimumHeightBeforeClose); - dialog->mDialogWidget->setMaximumHeight(dialog->mMaximumHeightBeforeClose); + dialog->m_dialogWidget->setMinimumHeight(dialog->m_minimumHeightBeforeClose); + dialog->m_dialogWidget->setMaximumHeight(dialog->m_maximumHeightBeforeClose); // change the stylesheet and the icon button->setStyleSheet(""); button->setIcon(GetMysticQt()->FindIcon("Images/Icons/ArrowDownGray.png")); // more space used by the splitter when the dialog is open - if (dialog != mDialogs.end() - 1) + if (dialog != m_dialogs.end() - 1) { - dialog->mSplitter->handle(1)->setFixedHeight(4); - dialog->mSplitter->setStyleSheet("QSplitter::handle{ height: 4px; background: transparent; }"); + dialog->m_splitter->handle(1)->setFixedHeight(4); + dialog->m_splitter->setStyleSheet("QSplitter::handle{ height: 4px; background: transparent; }"); } // enable the splitter - if (dialog != mDialogs.end() - 1) + if (dialog != m_dialogs.end() - 1) { - dialog->mSplitter->handle(1)->setEnabled(true); + dialog->m_splitter->handle(1)->setEnabled(true); } // maximize the size if it's needed - if (mDialogs.size() > 1) + if (m_dialogs.size() > 1) { - if (dialog->mMaximizeSize) + if (dialog->m_maximizeSize) { // special case if it's the first dialog - if (dialog == mDialogs.begin()) + if (dialog == m_dialogs.begin()) { // if it's the first dialog and stretching is enabled, it expand to the max, all others expand to the min - if (dialog->mStretchWhenMaximize == false && (dialog + 1)->mMaximizeSize && (dialog + 1)->mFrame->isHidden() == false) + if (dialog->m_stretchWhenMaximize == false && (dialog + 1)->m_maximizeSize && (dialog + 1)->m_frame->isHidden() == false) { - static_cast(dialog->mSplitter)->MoveFirstSplitterToMin(); + static_cast(dialog->m_splitter)->MoveFirstSplitterToMin(); } else { - static_cast(dialog->mSplitter)->MoveFirstSplitterToMax(); + static_cast(dialog->m_splitter)->MoveFirstSplitterToMax(); } } else // not the first dialog { // set the previous dialog to the min to have this dialog expanded to the top - if ((dialog - 1)->mFrame->isHidden() || (dialog - 1)->mMaximizeSize == false || ((dialog - 1)->mMaximizeSize && (dialog - 1)->mStretchWhenMaximize == false)) + if ((dialog - 1)->m_frame->isHidden() || (dialog - 1)->m_maximizeSize == false || ((dialog - 1)->m_maximizeSize && (dialog - 1)->m_stretchWhenMaximize == false)) { - static_cast((dialog - 1)->mSplitter)->MoveFirstSplitterToMin(); + static_cast((dialog - 1)->m_splitter)->MoveFirstSplitterToMin(); } // special case if it's not the last dialog - if (dialog != mDialogs.end() - 1) + if (dialog != m_dialogs.end() - 1) { // if the next dialog is closed, it's needed to expand to the max too - if ((dialog + 1)->mFrame->isHidden()) + if ((dialog + 1)->m_frame->isHidden()) { - static_cast(dialog->mSplitter)->MoveFirstSplitterToMax(); + static_cast(dialog->m_splitter)->MoveFirstSplitterToMax(); } } } @@ -439,58 +439,58 @@ namespace MysticQt // close the dialog void DialogStack::Close(QPushButton* button) { - const auto dialog = AZStd::find_if(begin(mDialogs), end(mDialogs), [button](const Dialog& dialog) + const auto dialog = AZStd::find_if(begin(m_dialogs), end(m_dialogs), [button](const Dialog& dialog) { - return dialog.mButton == button; + return dialog.m_button == button; }); - if (dialog == end(mDialogs)) + if (dialog == end(m_dialogs)) { return; } // only closable dialog can be closed - if (dialog->mClosable == false) + if (dialog->m_closable == false) { return; } // keep the min and max height before close - dialog->mMinimumHeightBeforeClose = dialog->mDialogWidget->minimumHeight(); - dialog->mMaximumHeightBeforeClose = dialog->mDialogWidget->maximumHeight(); + dialog->m_minimumHeightBeforeClose = dialog->m_dialogWidget->minimumHeight(); + dialog->m_maximumHeightBeforeClose = dialog->m_dialogWidget->maximumHeight(); // hide the widget inside the dialog - dialog->mFrame->hide(); + dialog->m_frame->hide(); // set the widget to fixed size to not have it possible to resize - dialog->mDialogWidget->setMinimumHeight(dialog->mButton->height()); - dialog->mDialogWidget->setMaximumHeight(dialog->mButton->height()); + dialog->m_dialogWidget->setMinimumHeight(dialog->m_button->height()); + dialog->m_dialogWidget->setMaximumHeight(dialog->m_button->height()); // change the stylesheet and the icon button->setStyleSheet("border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border: 1px solid rgb(40,40,40);"); // TODO: link to the real style sheets button->setIcon(GetMysticQt()->FindIcon("Images/Icons/ArrowRightGray.png")); // less space used by the splitter when the dialog is closed - if (dialog < mDialogs.end() - 1) + if (dialog < m_dialogs.end() - 1) { - dialog->mSplitter->handle(1)->setFixedHeight(1); - dialog->mSplitter->setStyleSheet("QSplitter::handle{ height: 1px; background: transparent; }"); - dialog->mSplitter->handle(1)->setDisabled(true); - static_cast(dialog->mSplitter)->MoveFirstSplitterToMin(); + dialog->m_splitter->handle(1)->setFixedHeight(1); + dialog->m_splitter->setStyleSheet("QSplitter::handle{ height: 1px; background: transparent; }"); + dialog->m_splitter->handle(1)->setDisabled(true); + static_cast(dialog->m_splitter)->MoveFirstSplitterToMin(); } // maximize the first needed to avoid empty space bool findPreviousMaximizedDialogNeeded = true; - for (auto curDialog = dialog + 1; curDialog != mDialogs.end(); ++curDialog) + for (auto curDialog = dialog + 1; curDialog != m_dialogs.end(); ++curDialog) { - if (curDialog->mMaximizeSize && curDialog->mFrame->isHidden() == false) + if (curDialog->m_maximizeSize && curDialog->m_frame->isHidden() == false) { - if (curDialog != (mDialogs.end() - 1) && (curDialog + 1)->mFrame->isHidden()) + if (curDialog != (m_dialogs.end() - 1) && (curDialog + 1)->m_frame->isHidden()) { - static_cast(curDialog->mSplitter)->MoveFirstSplitterToMax(); + static_cast(curDialog->m_splitter)->MoveFirstSplitterToMax(); } else { - static_cast((curDialog - 1)->mSplitter)->MoveFirstSplitterToMin(); + static_cast((curDialog - 1)->m_splitter)->MoveFirstSplitterToMin(); } findPreviousMaximizedDialogNeeded = false; break; @@ -498,11 +498,11 @@ namespace MysticQt } if (findPreviousMaximizedDialogNeeded) { - for (auto curDialog = AZStd::make_reverse_iterator(dialog) + 1; curDialog != mDialogs.rend(); ++curDialog) + for (auto curDialog = AZStd::make_reverse_iterator(dialog) + 1; curDialog != m_dialogs.rend(); ++curDialog) { - if (curDialog->mMaximizeSize && curDialog->mFrame->isHidden() == false) + if (curDialog->m_maximizeSize && curDialog->m_frame->isHidden() == false) { - static_cast(curDialog->mSplitter)->MoveFirstSplitterToMax(); + static_cast(curDialog->m_splitter)->MoveFirstSplitterToMax(); break; } } @@ -519,8 +519,8 @@ namespace MysticQt if (event->buttons() & Qt::LeftButton) { // keep the mouse pos - mPrevMouseX = event->globalX(); - mPrevMouseY = event->globalY(); + m_prevMouseX = event->globalX(); + m_prevMouseY = event->globalY(); // set the cursor if the scrollbar is visible if ((horizontalScrollBar()->maximum() > 0) || (verticalScrollBar()->maximum() > 0)) @@ -566,8 +566,8 @@ namespace MysticQt } // calculate the delta mouse movement - const int32 deltaX = event->globalX() - mPrevMouseX; - const int32 deltaY = event->globalY() - mPrevMouseY; + const int32 deltaX = event->globalX() - m_prevMouseX; + const int32 deltaY = event->globalY() - m_prevMouseY; // now apply this delta movement to the scroller int32 newX = horizontalScrollBar()->value() - deltaX; @@ -576,8 +576,8 @@ namespace MysticQt verticalScrollBar()->setSliderPosition(newY); // store the current value as previous value - mPrevMouseX = event->globalX(); - mPrevMouseY = event->globalY(); + m_prevMouseX = event->globalX(); + m_prevMouseY = event->globalY(); } @@ -606,15 +606,15 @@ namespace MysticQt QScrollArea::resizeEvent(event); // maximize the first dialog needed - if (mDialogs.empty() || mDialogs.size() == 1) + if (m_dialogs.empty() || m_dialogs.size() == 1) { return; } - for (auto dialog = mDialogs.rbegin() + 1; dialog != mDialogs.rend(); ++dialog) + for (auto dialog = m_dialogs.rbegin() + 1; dialog != m_dialogs.rend(); ++dialog) { - if (dialog->mMaximizeSize && dialog->mFrame->isHidden() == false) + if (dialog->m_maximizeSize && dialog->m_frame->isHidden() == false) { - static_cast(dialog->mSplitter)->MoveFirstSplitterToMax(); + static_cast(dialog->m_splitter)->MoveFirstSplitterToMax(); break; } } @@ -624,54 +624,54 @@ namespace MysticQt // replace an internal widget void DialogStack::ReplaceWidget(QWidget* oldWidget, QWidget* newWidget) { - for (auto dialog = mDialogs.begin(); dialog != mDialogs.end(); ++dialog) + for (auto dialog = m_dialogs.begin(); dialog != m_dialogs.end(); ++dialog) { // go next if the widget is not the same - if (dialog->mWidget != oldWidget) + if (dialog->m_widget != oldWidget) { continue; } // replace the widget - dialog->mFrame->layout()->replaceWidget(oldWidget, newWidget); - dialog->mWidget = newWidget; + dialog->m_frame->layout()->replaceWidget(oldWidget, newWidget); + dialog->m_widget = newWidget; // adjust size of the new widget newWidget->adjustSize(); // set the constraints - if (dialog->mMaximizeSize == false) + if (dialog->m_maximizeSize == false) { // get margins - const QMargins frameMargins = dialog->mLayout->contentsMargins(); - const QMargins dialogMargins = dialog->mDialogLayout->contentsMargins(); + const QMargins frameMargins = dialog->m_layout->contentsMargins(); + const QMargins dialogMargins = dialog->m_dialogLayout->contentsMargins(); const int frameMarginTopBottom = frameMargins.top() + frameMargins.bottom(); const int dialogMarginTopBottom = dialogMargins.top() + dialogMargins.bottom(); const int allMarginsTopBottom = frameMarginTopBottom + dialogMarginTopBottom; // set the frame height - dialog->mFrame->setFixedHeight(newWidget->height() + frameMarginTopBottom); + dialog->m_frame->setFixedHeight(newWidget->height() + frameMarginTopBottom); // compute the dialog height - const int dialogHeight = newWidget->height() + allMarginsTopBottom + dialog->mButton->height(); + const int dialogHeight = newWidget->height() + allMarginsTopBottom + dialog->m_button->height(); // set the maximum height in case the dialog is not closed, if it's closed update the stored height - if (dialog->mFrame->isHidden() == false) + if (dialog->m_frame->isHidden() == false) { // set the dialog height - dialog->mDialogWidget->setFixedHeight(dialogHeight); + dialog->m_dialogWidget->setFixedHeight(dialogHeight); // set the first splitter to the min if needed - if (dialog != mDialogs.end() - 1) + if (dialog != m_dialogs.end() - 1) { - static_cast(dialog->mSplitter)->MoveFirstSplitterToMin(); + static_cast(dialog->m_splitter)->MoveFirstSplitterToMin(); } } else // dialog closed { // update the minimum and maximum stored height - dialog->mMinimumHeightBeforeClose = dialogHeight; - dialog->mMaximumHeightBeforeClose = dialogHeight; + dialog->m_minimumHeightBeforeClose = dialogHeight; + dialog->m_maximumHeightBeforeClose = dialogHeight; } } diff --git a/Gems/EMotionFX/Code/MysticQt/Source/DialogStack.h b/Gems/EMotionFX/Code/MysticQt/Source/DialogStack.h index 6bf810b281..bf93b5d23f 100644 --- a/Gems/EMotionFX/Code/MysticQt/Source/DialogStack.h +++ b/Gems/EMotionFX/Code/MysticQt/Source/DialogStack.h @@ -62,18 +62,18 @@ namespace MysticQt private: struct Dialog { - QPushButton* mButton = nullptr; - QWidget* mFrame = nullptr; - QWidget* mWidget = nullptr; - QWidget* mDialogWidget = nullptr; - DialogStackSplitter* mSplitter = nullptr; - bool mClosable = true; - bool mMaximizeSize = false; - bool mStretchWhenMaximize = false; - int mMinimumHeightBeforeClose = 0; - int mMaximumHeightBeforeClose = 0; - QLayout* mLayout = nullptr; - QLayout* mDialogLayout = nullptr; + QPushButton* m_button = nullptr; + QWidget* m_frame = nullptr; + QWidget* m_widget = nullptr; + QWidget* m_dialogWidget = nullptr; + DialogStackSplitter* m_splitter = nullptr; + bool m_closable = true; + bool m_maximizeSize = false; + bool m_stretchWhenMaximize = false; + int m_minimumHeightBeforeClose = 0; + int m_maximumHeightBeforeClose = 0; + QLayout* m_layout = nullptr; + QLayout* m_dialogLayout = nullptr; }; private: @@ -83,10 +83,10 @@ namespace MysticQt void UpdateScrollBars(); private: - DialogStackSplitter* mRootSplitter; - AZStd::vector mDialogs; - int32 mPrevMouseX; - int32 mPrevMouseY; + DialogStackSplitter* m_rootSplitter; + AZStd::vector m_dialogs; + int32 m_prevMouseX; + int32 m_prevMouseY; }; } // namespace MysticQt diff --git a/Gems/EMotionFX/Code/MysticQt/Source/MysticQtManager.cpp b/Gems/EMotionFX/Code/MysticQt/Source/MysticQtManager.cpp index 3386e1a0d2..537ad6bedd 100644 --- a/Gems/EMotionFX/Code/MysticQt/Source/MysticQtManager.cpp +++ b/Gems/EMotionFX/Code/MysticQt/Source/MysticQtManager.cpp @@ -22,7 +22,7 @@ namespace MysticQt // constructor MysticQtManager::MysticQtManager() { - mMainWindow = nullptr; + m_mainWindow = nullptr; } @@ -30,11 +30,11 @@ namespace MysticQt MysticQtManager::~MysticQtManager() { // get the number of icons and destroy them - for (IconData* icon : mIcons) + for (IconData* icon : m_icons) { delete icon; } - mIcons.clear(); + m_icons.clear(); } @@ -42,33 +42,33 @@ namespace MysticQt // constructor MysticQtManager::IconData::IconData(const char* filename) { - mFileName = filename; - mIcon = new QIcon(QDir{ QString(GetMysticQt()->GetDataDir().c_str()) }.filePath(filename)); + m_fileName = filename; + m_icon = new QIcon(QDir{ QString(GetMysticQt()->GetDataDir().c_str()) }.filePath(filename)); } // destructor MysticQtManager::IconData::~IconData() { - delete mIcon; + delete m_icon; } const QIcon& MysticQtManager::FindIcon(const char* filename) { // get the number of icons and iterate through them - for (IconData* icon : mIcons) + for (IconData* icon : m_icons) { - if (AzFramework::StringFunc::Equal(icon->mFileName.c_str(), filename, false /* no case */)) + if (AzFramework::StringFunc::Equal(icon->m_fileName.c_str(), filename, false /* no case */)) { - return *(icon->mIcon); + return *(icon->m_icon); } } // we haven't found it IconData* iconData = new IconData(filename); - mIcons.emplace_back(iconData); - return *(iconData->mIcon); + m_icons.emplace_back(iconData); + return *(iconData->m_icon); } diff --git a/Gems/EMotionFX/Code/MysticQt/Source/MysticQtManager.h b/Gems/EMotionFX/Code/MysticQt/Source/MysticQtManager.h index e0be07796e..9c8a73b92f 100644 --- a/Gems/EMotionFX/Code/MysticQt/Source/MysticQtManager.h +++ b/Gems/EMotionFX/Code/MysticQt/Source/MysticQtManager.h @@ -36,28 +36,28 @@ namespace MysticQt MCORE_MEMORYOBJECTCATEGORY(MysticQtManager, MCore::MCORE_DEFAULT_ALIGNMENT, MEMCATEGORY_MYSTICQT); public: - MCORE_INLINE QWidget* GetMainWindow() const { return mMainWindow; } - MCORE_INLINE void SetMainWindow(QWidget* mainWindow) { mMainWindow = mainWindow; } + MCORE_INLINE QWidget* GetMainWindow() const { return m_mainWindow; } + MCORE_INLINE void SetMainWindow(QWidget* mainWindow) { m_mainWindow = mainWindow; } MCORE_INLINE void SetAppDir(const char* appDir) { - mAppDir = appDir; - if (mDataDir.size() == 0) + m_appDir = appDir; + if (m_dataDir.size() == 0) { - mDataDir = appDir; + m_dataDir = appDir; } } - MCORE_INLINE const AZStd::string& GetAppDir() const { return mAppDir; } + MCORE_INLINE const AZStd::string& GetAppDir() const { return m_appDir; } MCORE_INLINE void SetDataDir(const char* dataDir) { - mDataDir = dataDir; - if (mAppDir.size() == 0) + m_dataDir = dataDir; + if (m_appDir.size() == 0) { - mAppDir = dataDir; + m_appDir = dataDir; } } - MCORE_INLINE const AZStd::string& GetDataDir() const { return mDataDir; } + MCORE_INLINE const AZStd::string& GetDataDir() const { return m_dataDir; } const QIcon& FindIcon(const char* filename); @@ -69,14 +69,14 @@ namespace MysticQt IconData(const char* filename); ~IconData(); - QIcon* mIcon; - AZStd::string mFileName; + QIcon* m_icon; + AZStd::string m_fileName; }; - QWidget* mMainWindow; - AZStd::vector mIcons; - AZStd::string mAppDir; - AZStd::string mDataDir; + QWidget* m_mainWindow; + AZStd::vector m_icons; + AZStd::string m_appDir; + AZStd::string m_dataDir; MysticQtManager(); ~MysticQtManager(); diff --git a/Gems/EMotionFX/Code/MysticQt/Source/RecentFiles.cpp b/Gems/EMotionFX/Code/MysticQt/Source/RecentFiles.cpp index 78490a3b13..b5dfd2ead1 100644 --- a/Gems/EMotionFX/Code/MysticQt/Source/RecentFiles.cpp +++ b/Gems/EMotionFX/Code/MysticQt/Source/RecentFiles.cpp @@ -27,7 +27,7 @@ namespace MysticQt ToolTipMenu(const QString title, QWidget* parent) : QMenu(title, parent) { - mParent = parent; + m_parent = parent; } bool event(QEvent* e) override @@ -40,7 +40,7 @@ namespace MysticQt QAction* action = activeAction(); if (action) { - QToolTip::showText(helpEvent->globalPos(), action->toolTip(), mParent); + QToolTip::showText(helpEvent->globalPos(), action->toolTip(), m_parent); } } else @@ -52,7 +52,7 @@ namespace MysticQt } private: - QWidget* mParent; + QWidget* m_parent; }; diff --git a/Gems/EMotionFX/Code/Platform/Common/FileOffsetType/MCore/Source/DiskFile_FileOffsetType.cpp b/Gems/EMotionFX/Code/Platform/Common/FileOffsetType/MCore/Source/DiskFile_FileOffsetType.cpp index e041afb417..1603f6326e 100644 --- a/Gems/EMotionFX/Code/Platform/Common/FileOffsetType/MCore/Source/DiskFile_FileOffsetType.cpp +++ b/Gems/EMotionFX/Code/Platform/Common/FileOffsetType/MCore/Source/DiskFile_FileOffsetType.cpp @@ -14,18 +14,18 @@ namespace MCore // returns the position (offset) in the file in bytes size_t DiskFile::GetPos() const { - MCORE_ASSERT(mFile); + MCORE_ASSERT(m_file); - return ftello(mFile); + return ftello(m_file); } // seek a given number of bytes ahead from it's current position bool DiskFile::Forward(size_t numBytes) { - MCORE_ASSERT(mFile); + MCORE_ASSERT(m_file); - if (fseeko(mFile, numBytes, SEEK_CUR) != 0) + if (fseeko(m_file, numBytes, SEEK_CUR) != 0) { return false; } @@ -36,9 +36,9 @@ namespace MCore // seek to an absolute position in the file (offset in bytes) bool DiskFile::Seek(size_t offset) { - MCORE_ASSERT(mFile); + MCORE_ASSERT(m_file); - if (fseeko(mFile, offset, SEEK_SET) != 0) + if (fseeko(m_file, offset, SEEK_SET) != 0) { return false; } @@ -49,8 +49,8 @@ namespace MCore // returns the filesize in bytes size_t DiskFile::GetFileSize() const { - MCORE_ASSERT(mFile); - if (mFile == nullptr) + MCORE_ASSERT(m_file); + if (m_file == nullptr) { return 0; } @@ -59,13 +59,13 @@ namespace MCore size_t curPos = GetPos(); // seek to the end of the file - fseeko(mFile, 0, SEEK_END); + fseeko(m_file, 0, SEEK_END); // get the position, whis is the size of the file size_t fileSize = GetPos(); // seek back to the original position - fseeko(mFile, curPos, SEEK_SET); + fseeko(m_file, curPos, SEEK_SET); // return the size of the file return fileSize; diff --git a/Gems/EMotionFX/Code/Platform/Common/WinAPI/MCore/Source/DiskFile_WinAPI.cpp b/Gems/EMotionFX/Code/Platform/Common/WinAPI/MCore/Source/DiskFile_WinAPI.cpp index 14a73bf3f5..6cafebeff5 100644 --- a/Gems/EMotionFX/Code/Platform/Common/WinAPI/MCore/Source/DiskFile_WinAPI.cpp +++ b/Gems/EMotionFX/Code/Platform/Common/WinAPI/MCore/Source/DiskFile_WinAPI.cpp @@ -14,18 +14,18 @@ namespace MCore // returns the position (offset) in the file in bytes size_t DiskFile::GetPos() const { - MCORE_ASSERT(mFile); + MCORE_ASSERT(m_file); - return _ftelli64(mFile); + return _ftelli64(m_file); } // seek a given number of bytes ahead from it's current position bool DiskFile::Forward(size_t numBytes) { - MCORE_ASSERT(mFile); + MCORE_ASSERT(m_file); - if (_fseeki64(mFile, numBytes, SEEK_CUR) != 0) + if (_fseeki64(m_file, numBytes, SEEK_CUR) != 0) { return false; } @@ -36,9 +36,9 @@ namespace MCore // seek to an absolute position in the file (offset in bytes) bool DiskFile::Seek(size_t offset) { - MCORE_ASSERT(mFile); + MCORE_ASSERT(m_file); - if (_fseeki64(mFile, offset, SEEK_SET) != 0) + if (_fseeki64(m_file, offset, SEEK_SET) != 0) { return false; } @@ -49,8 +49,8 @@ namespace MCore // returns the filesize in bytes size_t DiskFile::GetFileSize() const { - MCORE_ASSERT(mFile); - if (mFile == nullptr) + MCORE_ASSERT(m_file); + if (m_file == nullptr) { return 0; } @@ -59,13 +59,13 @@ namespace MCore size_t curPos = GetPos(); // seek to the end of the file - _fseeki64(mFile, 0, SEEK_END); + _fseeki64(m_file, 0, SEEK_END); // get the position, whis is the size of the file size_t fileSize = GetPos(); // seek back to the original position - _fseeki64(mFile, curPos, SEEK_SET); + _fseeki64(m_file, curPos, SEEK_SET); // return the size of the file return fileSize; diff --git a/Gems/EMotionFX/Code/Source/Editor/ColliderContainerWidget.cpp b/Gems/EMotionFX/Code/Source/Editor/ColliderContainerWidget.cpp index ef76629780..fea4f23c6a 100644 --- a/Gems/EMotionFX/Code/Source/Editor/ColliderContainerWidget.cpp +++ b/Gems/EMotionFX/Code/Source/Editor/ColliderContainerWidget.cpp @@ -617,12 +617,12 @@ namespace EMotionFX const MCore::RGBAColor& colliderColor) { const size_t nodeIndex = node->GetNodeIndex(); - MCommon::RenderUtil* renderUtil = renderInfo->mRenderUtil; + MCommon::RenderUtil* renderUtil = renderInfo->m_renderUtil; for (const auto& collider : colliders) { #ifndef EMFX_SCALE_DISABLED - const AZ::Vector3& worldScale = actorInstance->GetTransformData()->GetCurrentPose()->GetModelSpaceTransform(nodeIndex).mScale; + const AZ::Vector3& worldScale = actorInstance->GetTransformData()->GetCurrentPose()->GetModelSpaceTransform(nodeIndex).m_scale; #else const AZ::Vector3 worldScale = AZ::Vector3::CreateOne(); #endif @@ -677,7 +677,7 @@ namespace EMotionFX return; } - MCommon::RenderUtil* renderUtil = renderInfo->mRenderUtil; + MCommon::RenderUtil* renderUtil = renderInfo->m_renderUtil; const bool oldLightingEnabled = renderUtil->GetLightingEnabled(); renderUtil->EnableLighting(false); diff --git a/Gems/EMotionFX/Code/Source/Editor/ObjectEditor.cpp b/Gems/EMotionFX/Code/Source/Editor/ObjectEditor.cpp index b8cf69f2cb..b5db607c50 100644 --- a/Gems/EMotionFX/Code/Source/Editor/ObjectEditor.cpp +++ b/Gems/EMotionFX/Code/Source/Editor/ObjectEditor.cpp @@ -13,7 +13,7 @@ namespace EMotionFX { - const int ObjectEditor::m_propertyLabelWidth = 160; + const int ObjectEditor::s_propertyLabelWidth = 160; ObjectEditor::ObjectEditor(AZ::SerializeContext* serializeContext, QWidget* parent) : ObjectEditor(serializeContext, nullptr, parent) @@ -30,7 +30,7 @@ namespace EMotionFX m_propertyEditor = aznew AzToolsFramework::ReflectedPropertyEditor(this); m_propertyEditor->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum); m_propertyEditor->setObjectName("PropertyEditor"); - m_propertyEditor->Setup(serializeContext, notify, false/*enableScrollbars*/, m_propertyLabelWidth); + m_propertyEditor->Setup(serializeContext, notify, false/*enableScrollbars*/, s_propertyLabelWidth); QVBoxLayout* mainLayout = new QVBoxLayout(this); mainLayout->setSizeConstraint(QLayout::SetMinimumSize); diff --git a/Gems/EMotionFX/Code/Source/Editor/ObjectEditor.h b/Gems/EMotionFX/Code/Source/Editor/ObjectEditor.h index a726170b98..c76dc3b88f 100644 --- a/Gems/EMotionFX/Code/Source/Editor/ObjectEditor.h +++ b/Gems/EMotionFX/Code/Source/Editor/ObjectEditor.h @@ -47,6 +47,6 @@ namespace EMotionFX private: void* m_object; AzToolsFramework::ReflectedPropertyEditor* m_propertyEditor; - static const int m_propertyLabelWidth; + static const int s_propertyLabelWidth; }; } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/Source/Editor/Plugins/Cloth/ClothJointInspectorPlugin.cpp b/Gems/EMotionFX/Code/Source/Editor/Plugins/Cloth/ClothJointInspectorPlugin.cpp index 0b806ebc00..861100b073 100644 --- a/Gems/EMotionFX/Code/Source/Editor/Plugins/Cloth/ClothJointInspectorPlugin.cpp +++ b/Gems/EMotionFX/Code/Source/Editor/Plugins/Cloth/ClothJointInspectorPlugin.cpp @@ -65,13 +65,13 @@ namespace EMotionFX scrollArea->setWidget(m_jointWidget); scrollArea->setWidgetResizable(true); - mDock->setWidget(scrollArea); + m_dock->setWidget(scrollArea); EMotionFX::SkeletonOutlinerNotificationBus::Handler::BusConnect(); } else { - mDock->setWidget(CreateErrorContentWidget("Cloth collider editor depends on the NVIDIA Cloth gem. Please enable it in the project configurator.")); + m_dock->setWidget(CreateErrorContentWidget("Cloth collider editor depends on the NVIDIA Cloth gem. Please enable it in the project configurator.")); } return true; diff --git a/Gems/EMotionFX/Code/Source/Editor/Plugins/HitDetection/HitDetectionJointInspectorPlugin.cpp b/Gems/EMotionFX/Code/Source/Editor/Plugins/HitDetection/HitDetectionJointInspectorPlugin.cpp index d0578306ab..c69fdd9393 100644 --- a/Gems/EMotionFX/Code/Source/Editor/Plugins/HitDetection/HitDetectionJointInspectorPlugin.cpp +++ b/Gems/EMotionFX/Code/Source/Editor/Plugins/HitDetection/HitDetectionJointInspectorPlugin.cpp @@ -51,13 +51,13 @@ namespace EMotionFX scrollArea->setWidget(m_nodeWidget); scrollArea->setWidgetResizable(true); - mDock->setWidget(scrollArea); + m_dock->setWidget(scrollArea); EMotionFX::SkeletonOutlinerNotificationBus::Handler::BusConnect(); } else { - mDock->setWidget(CreateErrorContentWidget("Hit detection collider editor depends on the PhysX gem. Please enable it in the project configurator.")); + m_dock->setWidget(CreateErrorContentWidget("Hit detection collider editor depends on the PhysX gem. Please enable it in the project configurator.")); } return true; diff --git a/Gems/EMotionFX/Code/Source/Editor/Plugins/Ragdoll/RagdollNodeInspectorPlugin.cpp b/Gems/EMotionFX/Code/Source/Editor/Plugins/Ragdoll/RagdollNodeInspectorPlugin.cpp index 93c4e2cb67..5324950c82 100644 --- a/Gems/EMotionFX/Code/Source/Editor/Plugins/Ragdoll/RagdollNodeInspectorPlugin.cpp +++ b/Gems/EMotionFX/Code/Source/Editor/Plugins/Ragdoll/RagdollNodeInspectorPlugin.cpp @@ -80,13 +80,13 @@ namespace EMotionFX scrollArea->setWidget(m_nodeWidget); scrollArea->setWidgetResizable(true); - mDock->setWidget(scrollArea); + m_dock->setWidget(scrollArea); EMotionFX::SkeletonOutlinerNotificationBus::Handler::BusConnect(); } else { - mDock->setWidget(CreateErrorContentWidget("Ragdoll editor depends on the PhysX gem. Please enable it in the project configurator.")); + m_dock->setWidget(CreateErrorContentWidget("Ragdoll editor depends on the PhysX gem. Please enable it in the project configurator.")); } return true; @@ -432,7 +432,7 @@ namespace EMotionFX return; } - MCommon::RenderUtil* renderUtil = renderInfo->mRenderUtil; + MCommon::RenderUtil* renderUtil = renderInfo->m_renderUtil; const bool oldLightingEnabled = renderUtil->GetLightingEnabled(); renderUtil->EnableLighting(false); @@ -539,8 +539,8 @@ namespace EMotionFX const size_t parentNodeIndex = parentNode->GetNodeIndex(); const Transform& actorInstanceWorldTransform = actorInstance->GetWorldSpaceTransform(); const Pose* currentPose = actorInstance->GetTransformData()->GetCurrentPose(); - const AZ::Quaternion& parentOrientation = currentPose->GetModelSpaceTransform(parentNodeIndex).mRotation; - const AZ::Quaternion& childOrientation = currentPose->GetModelSpaceTransform(nodeIndex).mRotation; + const AZ::Quaternion& parentOrientation = currentPose->GetModelSpaceTransform(parentNodeIndex).m_rotation; + const AZ::Quaternion& childOrientation = currentPose->GetModelSpaceTransform(nodeIndex).m_rotation; m_vertexBuffer.clear(); m_indexBuffer.clear(); @@ -554,10 +554,10 @@ namespace EMotionFX } Transform jointModelSpaceTransform = currentPose->GetModelSpaceTransform(parentNodeIndex); - jointModelSpaceTransform.mPosition = currentPose->GetModelSpaceTransform(nodeIndex).mPosition; + jointModelSpaceTransform.m_position = currentPose->GetModelSpaceTransform(nodeIndex).m_position; const Transform jointGlobalTransformNoScale = jointModelSpaceTransform * actorInstanceWorldTransform; - MCommon::RenderUtil* renderUtil = renderInfo->mRenderUtil; + MCommon::RenderUtil* renderUtil = renderInfo->m_renderUtil; const size_t numLineBufferEntries = m_lineBuffer.size(); if (m_lineValidityBuffer.size() * 2 != numLineBufferEntries) { @@ -588,6 +588,6 @@ namespace EMotionFX const Transform childModelSpaceTransform = childJointLocalSpaceTransform * currentPose->GetModelSpaceTransform(node->GetNodeIndex()); const Transform jointChildWorldSpaceTransformNoScale = (childModelSpaceTransform * actorInstanceWorldSpaceTransform); - renderInfo->mRenderUtil->RenderArrow(0.1f, jointChildWorldSpaceTransformNoScale.mPosition, MCore::GetRight(jointChildWorldSpaceTransformNoScale.ToAZTransform()), color); + renderInfo->m_renderUtil->RenderArrow(0.1f, jointChildWorldSpaceTransformNoScale.m_position, MCore::GetRight(jointChildWorldSpaceTransformNoScale.ToAZTransform()), color); } } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/Source/Editor/Plugins/SimulatedObject/SimulatedObjectSelectionWindow.cpp b/Gems/EMotionFX/Code/Source/Editor/Plugins/SimulatedObject/SimulatedObjectSelectionWindow.cpp index 978ee0a298..681008d979 100644 --- a/Gems/EMotionFX/Code/Source/Editor/Plugins/SimulatedObject/SimulatedObjectSelectionWindow.cpp +++ b/Gems/EMotionFX/Code/Source/Editor/Plugins/SimulatedObject/SimulatedObjectSelectionWindow.cpp @@ -26,11 +26,11 @@ namespace EMStudio { setWindowTitle("SimulatedObject Selection Window"); - m_OKButton = new QPushButton("OK"); + m_okButton = new QPushButton("OK"); m_cancelButton = new QPushButton("Cancel"); QHBoxLayout* buttonLayout = new QHBoxLayout(); - buttonLayout->addWidget(m_OKButton); + buttonLayout->addWidget(m_okButton); buttonLayout->addWidget(m_cancelButton); QVBoxLayout* layout = new QVBoxLayout(this); @@ -38,7 +38,7 @@ namespace EMStudio layout->addWidget(m_simulatedObjectSelectionWidget); layout->addLayout(buttonLayout); - connect(m_OKButton, &QPushButton::clicked, this, &SimulatedObjectSelectionWindow::accept); + connect(m_okButton, &QPushButton::clicked, this, &SimulatedObjectSelectionWindow::accept); connect(m_cancelButton, &QPushButton::clicked, this, &SimulatedObjectSelectionWindow::reject); connect(m_simulatedObjectSelectionWidget, &SimulatedObjectSelectionWidget::OnDoubleClicked, this, &SimulatedObjectSelectionWindow::accept); } diff --git a/Gems/EMotionFX/Code/Source/Editor/Plugins/SimulatedObject/SimulatedObjectSelectionWindow.h b/Gems/EMotionFX/Code/Source/Editor/Plugins/SimulatedObject/SimulatedObjectSelectionWindow.h index 6411be5c98..d5bebb7abd 100644 --- a/Gems/EMotionFX/Code/Source/Editor/Plugins/SimulatedObject/SimulatedObjectSelectionWindow.h +++ b/Gems/EMotionFX/Code/Source/Editor/Plugins/SimulatedObject/SimulatedObjectSelectionWindow.h @@ -33,7 +33,7 @@ namespace EMStudio private: SimulatedObjectSelectionWidget* m_simulatedObjectSelectionWidget = nullptr; - QPushButton* m_OKButton = nullptr; + QPushButton* m_okButton = nullptr; QPushButton* m_cancelButton = nullptr; bool m_accepted = false; }; diff --git a/Gems/EMotionFX/Code/Source/Editor/Plugins/SimulatedObject/SimulatedObjectWidget.cpp b/Gems/EMotionFX/Code/Source/Editor/Plugins/SimulatedObject/SimulatedObjectWidget.cpp index bd57e24d08..a2b23e3268 100644 --- a/Gems/EMotionFX/Code/Source/Editor/Plugins/SimulatedObject/SimulatedObjectWidget.cpp +++ b/Gems/EMotionFX/Code/Source/Editor/Plugins/SimulatedObject/SimulatedObjectWidget.cpp @@ -113,7 +113,7 @@ namespace EMotionFX connect(m_addSimulatedObjectButton, &QPushButton::clicked, this, [this]() { - m_actionManager->OnAddNewObjectAndAddJoints(m_actor, /*selectedJoints=*/{}, /*addChildJoints=*/false, mDock); + m_actionManager->OnAddNewObjectAndAddJoints(m_actor, /*selectedJoints=*/{}, /*addChildJoints=*/false, m_dock); }); AZ::SerializeContext* serializeContext; @@ -130,9 +130,9 @@ namespace EMotionFX mainLayout->addWidget(m_selectionWidget, /*stretch=*/1); mainLayout->addStretch(); - mDock->setWidget(m_mainWidget); + m_dock->setWidget(m_mainWidget); - m_simulatedObjectInspectorDock = new AzQtComponents::StyledDockWidget("Simulated Object Inspector", mDock); + m_simulatedObjectInspectorDock = new AzQtComponents::StyledDockWidget("Simulated Object Inspector", m_dock); m_simulatedObjectInspectorDock->setFeatures(QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable); m_simulatedObjectInspectorDock->setObjectName("EMFX.SimulatedObjectWidget.SimulatedObjectInspectorDock"); m_simulatedJointWidget = new SimulatedJointWidget(this); @@ -361,7 +361,7 @@ namespace EMotionFX connect(addToSimulatedObjectMenu->addAction("New simulated object..."), &QAction::triggered, this, [this, selectedRowIndices]() { const bool addChildren = (QMessageBox::question(this->GetDockWidget(), "Add children of joints?", "Add all children of selected joints to the simulated object?") == QMessageBox::Yes); - m_actionManager->OnAddNewObjectAndAddJoints(m_actor, selectedRowIndices, addChildren, mDock); + m_actionManager->OnAddNewObjectAndAddJoints(m_actor, selectedRowIndices, addChildren, m_dock); }); menu->addSeparator(); @@ -536,7 +536,7 @@ namespace EMotionFX void SimulatedObjectWidget::RenderJointRadius(const SimulatedJoint* joint, ActorInstance* actorInstance, const AZ::Color& color) { #ifndef EMFX_SCALE_DISABLED - const float scale = actorInstance->GetWorldSpaceTransform().mScale.GetX(); + const float scale = actorInstance->GetWorldSpaceTransform().m_scale.GetX(); #else const float scale = 1.0f; #endif @@ -553,7 +553,7 @@ namespace EMotionFX DebugDraw& debugDraw = GetDebugDraw(); DebugDraw::ActorInstanceData* drawData = debugDraw.GetActorInstanceData(actorInstance); drawData->Lock(); - drawData->DrawWireframeSphere(jointTransform.mPosition, radius, color, jointTransform.mRotation, 12, 12); + drawData->DrawWireframeSphere(jointTransform.m_position, radius, color, jointTransform.m_rotation, 12, 12); drawData->Unlock(); } } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/Source/Editor/Plugins/SkeletonOutliner/SkeletonOutlinerPlugin.cpp b/Gems/EMotionFX/Code/Source/Editor/Plugins/SkeletonOutliner/SkeletonOutlinerPlugin.cpp index 949325f101..f8ca291d55 100644 --- a/Gems/EMotionFX/Code/Source/Editor/Plugins/SkeletonOutliner/SkeletonOutlinerPlugin.cpp +++ b/Gems/EMotionFX/Code/Source/Editor/Plugins/SkeletonOutliner/SkeletonOutlinerPlugin.cpp @@ -42,7 +42,7 @@ namespace EMotionFX bool SkeletonOutlinerPlugin::Init() { - m_mainWidget = new QWidget(mDock); + m_mainWidget = new QWidget(m_dock); QVBoxLayout* mainLayout = new QVBoxLayout(); m_mainWidget->setLayout(mainLayout); @@ -112,7 +112,7 @@ namespace EMotionFX connect(m_searchWidget, &AzQtComponents::FilteredSearchWidget::TypeFilterChanged, this, &SkeletonOutlinerPlugin::OnTypeFilterChanged); mainLayout->addWidget(m_treeView); - mDock->setWidget(m_mainWidget); + m_dock->setWidget(m_mainWidget); EMotionFX::SkeletonOutlinerRequestBus::Handler::BusConnect(); Reinit(); diff --git a/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/ActorGoalNodeHandler.cpp b/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/ActorGoalNodeHandler.cpp index 8cbee5924b..9883b06e23 100644 --- a/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/ActorGoalNodeHandler.cpp +++ b/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/ActorGoalNodeHandler.cpp @@ -131,7 +131,7 @@ namespace EMotionFX if (newSelection.size() == 1) { AZStd::string selectedNodeName = newSelection[0].GetNodeName(); - AZ::u32 selectedActorInstanceId = newSelection[0].mActorInstanceID; + AZ::u32 selectedActorInstanceId = newSelection[0].m_actorInstanceId; const auto parentDepth = AZStd::find(begin(actorInstanceIDs), end(actorInstanceIDs), selectedActorInstanceId); AZ_Assert(parentDepth != end(actorInstanceIDs), "Cannot get parent depth. The selected actor instance was not shown in the selection window."); diff --git a/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/AnimGraphNodeHandler.cpp b/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/AnimGraphNodeHandler.cpp index 06542e5fef..81c15d2f98 100644 --- a/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/AnimGraphNodeHandler.cpp +++ b/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/AnimGraphNodeHandler.cpp @@ -113,7 +113,7 @@ namespace EMotionFX const AZStd::vector& selectedNodes = dialog.GetAnimGraphHierarchyWidget().GetSelectedItems(); if (!selectedNodes.empty()) { - AnimGraphNode* selectedNode = m_animGraph->RecursiveFindNodeByName(selectedNodes[0].mNodeName.c_str()); + AnimGraphNode* selectedNode = m_animGraph->RecursiveFindNodeByName(selectedNodes[0].m_nodeName.c_str()); if (selectedNode) { m_nodeId = selectedNode->GetId(); diff --git a/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/BlendNParamWeightsHandler.cpp b/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/BlendNParamWeightsHandler.cpp index 62b1af5250..7b615c22ce 100644 --- a/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/BlendNParamWeightsHandler.cpp +++ b/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/BlendNParamWeightsHandler.cpp @@ -238,11 +238,11 @@ namespace EMotionFX const char* sourceNodeName = ""; for (const AnimGraphNode::Port& port : inputPorts) { - if (port.mConnection) + if (port.m_connection) { - if (port.mPortID == paramWeights[i].GetPortId()) + if (port.m_portId == paramWeights[i].GetPortId()) { - sourceNodeName = port.mConnection->GetSourceNode()->GetName(); + sourceNodeName = port.m_connection->GetSourceNode()->GetName(); } } } diff --git a/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/LODSceneGraphWidget.h b/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/LODSceneGraphWidget.h index 1ed9a8f67d..4905f8612d 100644 --- a/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/LODSceneGraphWidget.h +++ b/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/LODSceneGraphWidget.h @@ -40,7 +40,7 @@ namespace EMotionFX private: bool m_hideUncheckableItem; - Data::LodNodeSelectionList m_LODSelectionList; + Data::LodNodeSelectionList m_lodSelectionList; }; } } diff --git a/Gems/EMotionFX/Code/Source/Integration/Assets/ActorAsset.cpp b/Gems/EMotionFX/Code/Source/Integration/Assets/ActorAsset.cpp index bfee6b582c..5082d4b739 100644 --- a/Gems/EMotionFX/Code/Source/Integration/Assets/ActorAsset.cpp +++ b/Gems/EMotionFX/Code/Source/Integration/Assets/ActorAsset.cpp @@ -55,7 +55,7 @@ namespace EMotionFX Importer::ActorSettings actorSettings; if (GetEMotionFX().GetEnableServerOptimization()) { - actorSettings.mOptimizeForServer = true; + actorSettings.m_optimizeForServer = true; } assetData->m_emfxActor = EMotionFX::GetImporter().LoadActor( diff --git a/Gems/EMotionFX/Code/Source/Integration/Components/ActorComponent.cpp b/Gems/EMotionFX/Code/Source/Integration/Components/ActorComponent.cpp index 9f996f46fd..303a7e118b 100644 --- a/Gems/EMotionFX/Code/Source/Integration/Components/ActorComponent.cpp +++ b/Gems/EMotionFX/Code/Source/Integration/Components/ActorComponent.cpp @@ -526,14 +526,14 @@ namespace EMotionFX if (m_actorInstance) { const Transform localTransform = m_actorInstance->GetParentWorldSpaceTransform().Inversed() * Transform(world); - m_actorInstance->SetLocalSpacePosition(localTransform.mPosition); - m_actorInstance->SetLocalSpaceRotation(localTransform.mRotation); + m_actorInstance->SetLocalSpacePosition(localTransform.m_position); + m_actorInstance->SetLocalSpaceRotation(localTransform.m_rotation); // Disable updating the scale to prevent feedback from adding up. // We need to find a better way to handle this or to prevent this feedback loop. EMFX_SCALECODE ( - m_actorInstance->SetLocalSpaceScale(localTransform.mScale); + m_actorInstance->SetLocalSpaceScale(localTransform.m_scale); ) } } @@ -663,8 +663,8 @@ namespace EMotionFX if (emfxNode) { const Transform& nodeTransform = emfxPose->GetModelSpaceTransform(emfxNode->GetNodeIndex()); - physicsPose[nodeIndex].m_position = nodeTransform.mPosition; - physicsPose[nodeIndex].m_orientation = nodeTransform.mRotation; + physicsPose[nodeIndex].m_position = nodeTransform.m_position; + physicsPose[nodeIndex].m_orientation = nodeTransform.m_rotation; } } @@ -780,11 +780,11 @@ namespace EMotionFX case Space::LocalSpace: { const Transform& localTransform = currentPose->GetLocalSpaceTransform(index); - outPosition = localTransform.mPosition; - outRotation = localTransform.mRotation; + outPosition = localTransform.m_position; + outRotation = localTransform.m_rotation; EMFX_SCALECODE ( - outScale = localTransform.mScale; + outScale = localTransform.m_scale; ) return; } @@ -792,11 +792,11 @@ namespace EMotionFX case Space::ModelSpace: { const Transform& modelTransform = currentPose->GetModelSpaceTransform(index); - outPosition = modelTransform.mPosition; - outRotation = modelTransform.mRotation; + outPosition = modelTransform.m_position; + outRotation = modelTransform.m_rotation; EMFX_SCALECODE ( - outScale = modelTransform.mScale; + outScale = modelTransform.m_scale; ) return; } @@ -804,11 +804,11 @@ namespace EMotionFX case Space::WorldSpace: { const Transform worldTransform = currentPose->GetWorldSpaceTransform(index); - outPosition = worldTransform.mPosition; - outRotation = worldTransform.mRotation; + outPosition = worldTransform.m_position; + outRotation = worldTransform.m_rotation; EMFX_SCALECODE ( - outScale = worldTransform.mScale; + outScale = worldTransform.m_scale; ) return; } diff --git a/Gems/EMotionFX/Code/Source/Integration/Components/SimpleMotionComponent.cpp b/Gems/EMotionFX/Code/Source/Integration/Components/SimpleMotionComponent.cpp index fa7ea7f2a7..dd7fdeea50 100644 --- a/Gems/EMotionFX/Code/Source/Integration/Components/SimpleMotionComponent.cpp +++ b/Gems/EMotionFX/Code/Source/Integration/Components/SimpleMotionComponent.cpp @@ -444,18 +444,18 @@ namespace EMotionFX } //init the PlaybackInfo based on our config EMotionFX::PlayBackInfo info; - info.mNumLoops = cfg.m_loop ? EMFX_LOOPFOREVER : 1; - info.mRetarget = cfg.m_retarget; - info.mPlayMode = cfg.m_reverse ? EMotionFX::EPlayMode::PLAYMODE_BACKWARD : EMotionFX::EPlayMode::PLAYMODE_FORWARD; - info.mFreezeAtLastFrame = info.mNumLoops == 1; - info.mMirrorMotion = cfg.m_mirror; - info.mPlaySpeed = cfg.m_playspeed; - info.mPlayNow = true; - info.mDeleteOnZeroWeight = deleteOnZeroWeight; - info.mCanOverwrite = false; - info.mBlendInTime = cfg.m_blendInTime; - info.mBlendOutTime = cfg.m_blendOutTime; - info.mInPlace = cfg.m_inPlace; + info.m_numLoops = cfg.m_loop ? EMFX_LOOPFOREVER : 1; + info.m_retarget = cfg.m_retarget; + info.m_playMode = cfg.m_reverse ? EMotionFX::EPlayMode::PLAYMODE_BACKWARD : EMotionFX::EPlayMode::PLAYMODE_FORWARD; + info.m_freezeAtLastFrame = info.m_numLoops == 1; + info.m_mirrorMotion = cfg.m_mirror; + info.m_playSpeed = cfg.m_playspeed; + info.m_playNow = true; + info.m_deleteOnZeroWeight = deleteOnZeroWeight; + info.m_canOverwrite = false; + info.m_blendInTime = cfg.m_blendInTime; + info.m_blendOutTime = cfg.m_blendOutTime; + info.m_inPlace = cfg.m_inPlace; return actorInstance->GetMotionSystem()->PlayMotion(motionAsset->m_emfxMotion.get(), &info); } diff --git a/Gems/EMotionFX/Code/Source/Integration/System/PipelineComponent.cpp b/Gems/EMotionFX/Code/Source/Integration/System/PipelineComponent.cpp index 6536241465..8946a435b6 100644 --- a/Gems/EMotionFX/Code/Source/Integration/System/PipelineComponent.cpp +++ b/Gems/EMotionFX/Code/Source/Integration/System/PipelineComponent.cpp @@ -21,14 +21,14 @@ namespace EMotionFX AZ::EnvironmentVariable PipelineComponent::s_eMotionFXAllocatorInitializer = nullptr; PipelineComponent::PipelineComponent() - : m_EMotionFXInited(false) + : m_eMotionFxInited(false) { } void PipelineComponent::Activate() { - if (!m_EMotionFXInited) + if (!m_eMotionFxInited) { // Start EMotionFX allocator or increase the reference counting s_eMotionFXAllocatorInitializer = AZ::Environment::CreateVariable(EMotionFXAllocatorInitializer::EMotionFXAllocatorInitializerTag); @@ -42,7 +42,7 @@ namespace EMotionFX // Initialize EMotion FX runtime. EMotionFX::Initializer::InitSettings emfxSettings; - emfxSettings.mUnitType = MCore::Distance::UNITTYPE_METERS; + emfxSettings.m_unitType = MCore::Distance::UNITTYPE_METERS; if (!EMotionFX::Initializer::Init(&emfxSettings)) { @@ -52,15 +52,15 @@ namespace EMotionFX // Initialize the EMotionFX command system. m_commandManager = AZStd::make_unique(); - m_EMotionFXInited = true; + m_eMotionFxInited = true; } } void PipelineComponent::Deactivate() { - if (m_EMotionFXInited) + if (m_eMotionFxInited) { - m_EMotionFXInited = false; + m_eMotionFxInited = false; m_commandManager.reset(); EMotionFX::Initializer::Shutdown(); MCore::Initializer::Shutdown(); diff --git a/Gems/EMotionFX/Code/Source/Integration/System/PipelineComponent.h b/Gems/EMotionFX/Code/Source/Integration/System/PipelineComponent.h index d89d1a33a0..392af36fd5 100644 --- a/Gems/EMotionFX/Code/Source/Integration/System/PipelineComponent.h +++ b/Gems/EMotionFX/Code/Source/Integration/System/PipelineComponent.h @@ -33,7 +33,7 @@ namespace EMotionFX static void Reflect(AZ::ReflectContext* context); private: - bool m_EMotionFXInited; + bool m_eMotionFxInited; AZStd::unique_ptr m_commandManager; // Creates a static shared pointer using the AZ EnvironmentVariable system. diff --git a/Gems/EMotionFX/Code/Source/Integration/System/SystemComponent.cpp b/Gems/EMotionFX/Code/Source/Integration/System/SystemComponent.cpp index 78aa3b4426..b5a252e293 100644 --- a/Gems/EMotionFX/Code/Source/Integration/System/SystemComponent.cpp +++ b/Gems/EMotionFX/Code/Source/Integration/System/SystemComponent.cpp @@ -132,7 +132,7 @@ namespace EMotionFX /// Dispatch motion events to listeners via ActorNotificationBus::OnMotionEvent. void OnEvent(const EMotionFX::EventInfo& emfxInfo) override { - const ActorInstance* actorInstance = emfxInfo.mActorInstance; + const ActorInstance* actorInstance = emfxInfo.m_actorInstance; if (actorInstance) { const AZ::EntityId owningEntityId = actorInstance->GetEntityId(); @@ -140,11 +140,11 @@ namespace EMotionFX // Fill engine-compatible structure to dispatch to game code. MotionEvent motionEvent; motionEvent.m_entityId = owningEntityId; - motionEvent.m_actorInstance = emfxInfo.mActorInstance; - motionEvent.m_motionInstance = emfxInfo.mMotionInstance; - motionEvent.m_time = emfxInfo.mTimeValue; + motionEvent.m_actorInstance = emfxInfo.m_actorInstance; + motionEvent.m_motionInstance = emfxInfo.m_motionInstance; + motionEvent.m_time = emfxInfo.m_timeValue; // TODO - for (const auto& eventData : emfxInfo.mEvent->GetEventDatas()) + for (const auto& eventData : emfxInfo.m_event->GetEventDatas()) { if (const EMotionFX::TwoStringEventData* twoStringEventData = azrtti_cast(eventData.get())) { @@ -153,8 +153,8 @@ namespace EMotionFX break; } } - motionEvent.m_globalWeight = emfxInfo.mGlobalWeight; - motionEvent.m_localWeight = emfxInfo.mLocalWeight; + motionEvent.m_globalWeight = emfxInfo.m_globalWeight; + motionEvent.m_localWeight = emfxInfo.m_localWeight; motionEvent.m_isEventStart = emfxInfo.IsEventStart(); // Queue the event to flush on the main thread. @@ -469,9 +469,9 @@ namespace EMotionFX // Initialize MCore, which is EMotionFX's standard library of containers and systems. MCore::Initializer::InitSettings coreSettings; - coreSettings.mMemAllocFunction = &EMotionFXAlloc; - coreSettings.mMemReallocFunction = &EMotionFXRealloc; - coreSettings.mMemFreeFunction = &EMotionFXFree; + coreSettings.m_memAllocFunction = &EMotionFXAlloc; + coreSettings.m_memReallocFunction = &EMotionFXRealloc; + coreSettings.m_memFreeFunction = &EMotionFXFree; if (!MCore::Initializer::Init(&coreSettings)) { AZ_Error("EMotion FX Animation", false, "Failed to initialize EMotion FX SDK Core"); @@ -480,7 +480,7 @@ namespace EMotionFX // Initialize EMotionFX runtime. EMotionFX::Initializer::InitSettings emfxSettings; - emfxSettings.mUnitType = MCore::Distance::UNITTYPE_METERS; + emfxSettings.m_unitType = MCore::Distance::UNITTYPE_METERS; if (!EMotionFX::Initializer::Init(&emfxSettings)) { @@ -709,7 +709,7 @@ namespace EMotionFX AZ::Transform currentTransform = AZ::Transform::CreateIdentity(); AZ::TransformBus::EventResult(currentTransform, entityId, &AZ::TransformBus::Events::GetWorldTM); - const AZ::Vector3 actorInstancePosition = actorInstance->GetWorldSpaceTransform().mPosition; + const AZ::Vector3 actorInstancePosition = actorInstance->GetWorldSpaceTransform().m_position; const AZ::Vector3 positionDelta = actorInstancePosition - currentTransform.GetTranslation(); if (hasPhysicsController) @@ -724,7 +724,7 @@ namespace EMotionFX } // Update the entity rotation. - const AZ::Quaternion actorInstanceRotation = actorInstance->GetWorldSpaceTransform().mRotation; + const AZ::Quaternion actorInstanceRotation = actorInstance->GetWorldSpaceTransform().m_rotation; const AZ::Quaternion currentRotation = currentTransform.GetRotation(); if (!currentRotation.IsClose(actorInstanceRotation, AZ::Constants::FloatEpsilon)) { diff --git a/Gems/EMotionFX/Code/Tests/AnimGraphDeferredInitTests.cpp b/Gems/EMotionFX/Code/Tests/AnimGraphDeferredInitTests.cpp index e05e5f3245..aa1bde295a 100644 --- a/Gems/EMotionFX/Code/Tests/AnimGraphDeferredInitTests.cpp +++ b/Gems/EMotionFX/Code/Tests/AnimGraphDeferredInitTests.cpp @@ -36,7 +36,7 @@ namespace EMotionFX m_blendTree->AddChildNode(paramNode); paramNode->InitAfterLoading(m_animGraph.get()); paramNode->InvalidateUniqueData(m_animGraphInstance); - m_blend2Node->AddConnection(paramNode, paramNode->FindOutputPortByName("weightParam")->mPortID, BlendTreeBlend2Node::PORTID_INPUT_WEIGHT); + m_blend2Node->AddConnection(paramNode, paramNode->FindOutputPortByName("weightParam")->m_portId, BlendTreeBlend2Node::PORTID_INPUT_WEIGHT); } void ConstructGraph() diff --git a/Gems/EMotionFX/Code/Tests/AnimGraphMotionNodeTests.cpp b/Gems/EMotionFX/Code/Tests/AnimGraphMotionNodeTests.cpp index 2a199f5e8b..121f438d82 100644 --- a/Gems/EMotionFX/Code/Tests/AnimGraphMotionNodeTests.cpp +++ b/Gems/EMotionFX/Code/Tests/AnimGraphMotionNodeTests.cpp @@ -118,16 +118,16 @@ namespace EMotionFX } protected: - size_t m_l_handIndex = InvalidIndex; - size_t m_l_loArmIndex = InvalidIndex; - size_t m_l_loLegIndex = InvalidIndex; - size_t m_l_ankleIndex = InvalidIndex; - size_t m_r_handIndex = InvalidIndex; - size_t m_r_loArmIndex = InvalidIndex; - size_t m_r_loLegIndex = InvalidIndex; - size_t m_r_ankleIndex = InvalidIndex; - size_t m_jack_rootIndex = InvalidIndex; - size_t m_bip01__pelvisIndex = InvalidIndex; + size_t m_lHandIndex = InvalidIndex; + size_t m_lLoArmIndex = InvalidIndex; + size_t m_lLoLegIndex = InvalidIndex; + size_t m_lAnkleIndex = InvalidIndex; + size_t m_rHandIndex = InvalidIndex; + size_t m_rLoArmIndex = InvalidIndex; + size_t m_rLoLegIndex = InvalidIndex; + size_t m_rAnkleIndex = InvalidIndex; + size_t m_jackRootIndex = InvalidIndex; + size_t m_bip01PelvisIndex = InvalidIndex; AnimGraphMotionNode* m_motionNode = nullptr; BlendTree* m_blendTree = nullptr; BlendTreeFloatConstantNode* m_fltConstNode = nullptr; @@ -147,16 +147,16 @@ namespace EMotionFX void SetupIndices() { - Node* rootNode = m_jackSkeleton->FindNodeAndIndexByName("jack_root", m_jack_rootIndex); - Node* pelvisNode = m_jackSkeleton->FindNodeAndIndexByName("Bip01__pelvis", m_bip01__pelvisIndex); - Node* lHandNode = m_jackSkeleton->FindNodeAndIndexByName("l_hand", m_l_handIndex); - Node* lLoArmNode = m_jackSkeleton->FindNodeAndIndexByName("l_loArm", m_l_loArmIndex); - Node* lLoLegNode = m_jackSkeleton->FindNodeAndIndexByName("l_loLeg", m_l_loLegIndex); - Node* lAnkleNode = m_jackSkeleton->FindNodeAndIndexByName("l_ankle", m_l_ankleIndex); - Node* rHandNode = m_jackSkeleton->FindNodeAndIndexByName("r_hand", m_r_handIndex); - Node* rLoArmNode = m_jackSkeleton->FindNodeAndIndexByName("r_loArm", m_r_loArmIndex); - Node* rLoLegNode = m_jackSkeleton->FindNodeAndIndexByName("r_loLeg", m_r_loLegIndex); - Node* rAnkleNode = m_jackSkeleton->FindNodeAndIndexByName("r_ankle", m_r_ankleIndex); + Node* rootNode = m_jackSkeleton->FindNodeAndIndexByName("jack_root", m_jackRootIndex); + Node* pelvisNode = m_jackSkeleton->FindNodeAndIndexByName("Bip01__pelvis", m_bip01PelvisIndex); + Node* lHandNode = m_jackSkeleton->FindNodeAndIndexByName("l_hand", m_lHandIndex); + Node* lLoArmNode = m_jackSkeleton->FindNodeAndIndexByName("l_loArm", m_lLoArmIndex); + Node* lLoLegNode = m_jackSkeleton->FindNodeAndIndexByName("l_loLeg", m_lLoLegIndex); + Node* lAnkleNode = m_jackSkeleton->FindNodeAndIndexByName("l_ankle", m_lAnkleIndex); + Node* rHandNode = m_jackSkeleton->FindNodeAndIndexByName("r_hand", m_rHandIndex); + Node* rLoArmNode = m_jackSkeleton->FindNodeAndIndexByName("r_loArm", m_rLoArmIndex); + Node* rLoLegNode = m_jackSkeleton->FindNodeAndIndexByName("r_loLeg", m_rLoLegIndex); + Node* rAnkleNode = m_jackSkeleton->FindNodeAndIndexByName("r_ankle", m_rAnkleIndex); // Make sure all nodes exist. ASSERT_TRUE(rootNode && pelvisNode && lHandNode && lLoArmNode && lLoLegNode && lAnkleNode && @@ -166,14 +166,14 @@ namespace EMotionFX void SetupMirrorNodes() { m_actor->AllocateNodeMirrorInfos(); - m_actor->GetNodeMirrorInfo(m_l_handIndex).mSourceNode = static_cast(m_r_handIndex); - m_actor->GetNodeMirrorInfo(m_r_handIndex).mSourceNode = static_cast(m_l_handIndex); - m_actor->GetNodeMirrorInfo(m_l_loArmIndex).mSourceNode = static_cast(m_r_loArmIndex); - m_actor->GetNodeMirrorInfo(m_r_loArmIndex).mSourceNode = static_cast(m_l_loArmIndex); - m_actor->GetNodeMirrorInfo(m_l_loLegIndex).mSourceNode = static_cast(m_r_loLegIndex); - m_actor->GetNodeMirrorInfo(m_r_loLegIndex).mSourceNode = static_cast(m_l_loLegIndex); - m_actor->GetNodeMirrorInfo(m_l_ankleIndex).mSourceNode = static_cast(m_r_ankleIndex); - m_actor->GetNodeMirrorInfo(m_r_ankleIndex).mSourceNode = static_cast(m_l_ankleIndex); + m_actor->GetNodeMirrorInfo(m_lHandIndex).m_sourceNode = static_cast(m_rHandIndex); + m_actor->GetNodeMirrorInfo(m_rHandIndex).m_sourceNode = static_cast(m_lHandIndex); + m_actor->GetNodeMirrorInfo(m_lLoArmIndex).m_sourceNode = static_cast(m_rLoArmIndex); + m_actor->GetNodeMirrorInfo(m_rLoArmIndex).m_sourceNode = static_cast(m_lLoArmIndex); + m_actor->GetNodeMirrorInfo(m_lLoLegIndex).m_sourceNode = static_cast(m_rLoLegIndex); + m_actor->GetNodeMirrorInfo(m_rLoLegIndex).m_sourceNode = static_cast(m_lLoLegIndex); + m_actor->GetNodeMirrorInfo(m_lAnkleIndex).m_sourceNode = static_cast(m_rAnkleIndex); + m_actor->GetNodeMirrorInfo(m_rAnkleIndex).m_sourceNode = static_cast(m_lAnkleIndex); m_actor->AutoDetectMirrorAxes(); } }; @@ -186,11 +186,11 @@ namespace EMotionFX // Follow-through during the duration(~1.06666672 seconds) of the motion. for (float i = 0.1f; i < 1.2f; i += 0.1f) { - const AZ::Vector3 rootCurrentPos = m_jackPose->GetModelSpaceTransform(m_jack_rootIndex).mPosition; - const AZ::Vector3 pelvisCurrentPos = m_jackPose->GetModelSpaceTransform(m_bip01__pelvisIndex).mPosition; + const AZ::Vector3 rootCurrentPos = m_jackPose->GetModelSpaceTransform(m_jackRootIndex).m_position; + const AZ::Vector3 pelvisCurrentPos = m_jackPose->GetModelSpaceTransform(m_bip01PelvisIndex).m_position; GetEMotionFX().Update(1.0f / 10.0f); - const AZ::Vector3 rootUpdatedPos = m_jackPose->GetModelSpaceTransform(m_jack_rootIndex).mPosition; - const AZ::Vector3 pelvisUpdatedPos = m_jackPose->GetModelSpaceTransform(m_bip01__pelvisIndex).mPosition; + const AZ::Vector3 rootUpdatedPos = m_jackPose->GetModelSpaceTransform(m_jackRootIndex).m_position; + const AZ::Vector3 pelvisUpdatedPos = m_jackPose->GetModelSpaceTransform(m_bip01PelvisIndex).m_position; const float rootDifference = rootUpdatedPos.GetY() - rootCurrentPos.GetY(); const float pelvisDifference = pelvisUpdatedPos.GetY() - pelvisCurrentPos.GetY(); @@ -203,7 +203,7 @@ namespace EMotionFX TEST_F(AnimGraphMotionNodeFixture, NoInputAndLoopOutputsCorrectMotionAndPose) { AnimGraphMotionNode::UniqueData* uniqueData = static_cast(m_animGraphInstance->FindOrCreateUniqueNodeData(m_motionNode)); - uniqueData->mReload = true; + uniqueData->m_reload = true; m_motionNode->SetLoop(true); m_motionNode->InvalidateUniqueData(m_animGraphInstance); m_actorInstance->SetMotionExtractionEnabled(false); @@ -211,14 +211,14 @@ namespace EMotionFX GetEMotionFX().Update(0.0f); // Needed to trigger a refresh of motion node internals. // Update to half the motion's duration. - AZ::Vector3 rootStartPos = m_jackPose->GetModelSpaceTransform(m_jack_rootIndex).mPosition; - AZ::Vector3 pelvisStartPos = m_jackPose->GetModelSpaceTransform(m_bip01__pelvisIndex).mPosition; + AZ::Vector3 rootStartPos = m_jackPose->GetModelSpaceTransform(m_jackRootIndex).m_position; + AZ::Vector3 pelvisStartPos = m_jackPose->GetModelSpaceTransform(m_bip01PelvisIndex).m_position; const float duration = m_motionNode->GetDuration(m_animGraphInstance); const float offset = duration * 0.5f; GetEMotionFX().Update(offset); EXPECT_FLOAT_EQ(uniqueData->GetCurrentPlayTime(), offset); - AZ::Vector3 rootCurrentPos = m_jackPose->GetModelSpaceTransform(m_jack_rootIndex).mPosition; - AZ::Vector3 pelvisCurrentPos = m_jackPose->GetModelSpaceTransform(m_bip01__pelvisIndex).mPosition; + AZ::Vector3 rootCurrentPos = m_jackPose->GetModelSpaceTransform(m_jackRootIndex).m_position; + AZ::Vector3 pelvisCurrentPos = m_jackPose->GetModelSpaceTransform(m_bip01PelvisIndex).m_position; EXPECT_TRUE(rootCurrentPos.GetY() > rootStartPos.GetY()) << "Y-axis position of root should increase."; EXPECT_TRUE(pelvisCurrentPos.GetY() > pelvisStartPos.GetY()) << "Y-axis position of pelvis should increase."; @@ -227,8 +227,8 @@ namespace EMotionFX pelvisStartPos = pelvisCurrentPos; GetEMotionFX().Update(duration * 0.6f); EXPECT_FLOAT_EQ(uniqueData->GetCurrentPlayTime(), duration * 0.1f); - rootCurrentPos = m_jackPose->GetModelSpaceTransform(m_jack_rootIndex).mPosition; - pelvisCurrentPos = m_jackPose->GetModelSpaceTransform(m_bip01__pelvisIndex).mPosition; + rootCurrentPos = m_jackPose->GetModelSpaceTransform(m_jackRootIndex).m_position; + pelvisCurrentPos = m_jackPose->GetModelSpaceTransform(m_bip01PelvisIndex).m_position; EXPECT_TRUE(rootCurrentPos.GetY() < rootStartPos.GetY()) << "Y-axis position of root should increase."; EXPECT_TRUE(pelvisCurrentPos.GetY() < pelvisStartPos.GetY()) << "Y-axis position of pelvis should increase."; }; @@ -237,7 +237,7 @@ namespace EMotionFX { m_motionNode->SetReverse(true); AnimGraphMotionNode::UniqueData* uniqueData = static_cast(m_animGraphInstance->FindOrCreateUniqueNodeData(m_motionNode)); - uniqueData->mReload = true; + uniqueData->m_reload = true; GetEMotionFX().Update(1.1f); EXPECT_TRUE(m_motionNode->GetIsReversed()) << "Reverse effect should be on."; @@ -246,11 +246,11 @@ namespace EMotionFX // Follow-through during the duration(~1.06666672 seconds) of the motion. for (float i = 0.1f; i < 1.2f; i += 0.1f) { - const AZ::Vector3 rootCurrentPos = m_jackPose->GetModelSpaceTransform(m_jack_rootIndex).mPosition; - const AZ::Vector3 pelvisCurrentPos = m_jackPose->GetModelSpaceTransform(m_bip01__pelvisIndex).mPosition; + const AZ::Vector3 rootCurrentPos = m_jackPose->GetModelSpaceTransform(m_jackRootIndex).m_position; + const AZ::Vector3 pelvisCurrentPos = m_jackPose->GetModelSpaceTransform(m_bip01PelvisIndex).m_position; GetEMotionFX().Update(1.0f / 10.0f); - const AZ::Vector3 rootUpdatedPos = m_jackPose->GetModelSpaceTransform(m_jack_rootIndex).mPosition; - const AZ::Vector3 pelvisUpdatedPos = m_jackPose->GetModelSpaceTransform(m_bip01__pelvisIndex).mPosition; + const AZ::Vector3 rootUpdatedPos = m_jackPose->GetModelSpaceTransform(m_jackRootIndex).m_position; + const AZ::Vector3 pelvisUpdatedPos = m_jackPose->GetModelSpaceTransform(m_bip01PelvisIndex).m_position; const float rootDifference = rootCurrentPos.GetY() - rootUpdatedPos.GetY(); const float pelvisDifference = pelvisCurrentPos.GetY() - pelvisUpdatedPos.GetY(); @@ -263,33 +263,33 @@ namespace EMotionFX TEST_F(AnimGraphMotionNodeFixture, DISABLED_NoInputAndMirrorMotionOutputsCorrectMotionAndPose) { AnimGraphMotionNode::UniqueData* uniqueData = static_cast(m_animGraphInstance->FindOrCreateUniqueNodeData(m_motionNode)); - uniqueData->mReload = true; + uniqueData->m_reload = true; GetEMotionFX().Update(1.0f); // Get positions before mirroring to compare with mirrored positions later. - const AZ::Vector3 l_handCurrentPos = m_jackPose->GetModelSpaceTransform(m_l_handIndex).mPosition; - const AZ::Vector3 l_loArmCurrentPos = m_jackPose->GetModelSpaceTransform(m_l_loArmIndex).mPosition; - const AZ::Vector3 l_loLegCurrentPos = m_jackPose->GetModelSpaceTransform(m_l_loLegIndex).mPosition; - const AZ::Vector3 l_ankleCurrentPos = m_jackPose->GetModelSpaceTransform(m_l_ankleIndex).mPosition; - const AZ::Vector3 r_handCurrentPos = m_jackPose->GetModelSpaceTransform(m_r_handIndex).mPosition; - const AZ::Vector3 r_loArmCurrentPos = m_jackPose->GetModelSpaceTransform(m_r_loArmIndex).mPosition; - const AZ::Vector3 r_loLegCurrentPos = m_jackPose->GetModelSpaceTransform(m_r_loLegIndex).mPosition; - const AZ::Vector3 r_ankleCurrentPos = m_jackPose->GetModelSpaceTransform(m_r_ankleIndex).mPosition; + const AZ::Vector3 l_handCurrentPos = m_jackPose->GetModelSpaceTransform(m_lHandIndex).m_position; + const AZ::Vector3 l_loArmCurrentPos = m_jackPose->GetModelSpaceTransform(m_lLoArmIndex).m_position; + const AZ::Vector3 l_loLegCurrentPos = m_jackPose->GetModelSpaceTransform(m_lLoLegIndex).m_position; + const AZ::Vector3 l_ankleCurrentPos = m_jackPose->GetModelSpaceTransform(m_lAnkleIndex).m_position; + const AZ::Vector3 r_handCurrentPos = m_jackPose->GetModelSpaceTransform(m_rHandIndex).m_position; + const AZ::Vector3 r_loArmCurrentPos = m_jackPose->GetModelSpaceTransform(m_rLoArmIndex).m_position; + const AZ::Vector3 r_loLegCurrentPos = m_jackPose->GetModelSpaceTransform(m_rLoLegIndex).m_position; + const AZ::Vector3 r_ankleCurrentPos = m_jackPose->GetModelSpaceTransform(m_rAnkleIndex).m_position; m_motionNode->SetMirrorMotion(true); - uniqueData->mReload = true; + uniqueData->m_reload = true; GetEMotionFX().Update(0.0001f); EXPECT_TRUE(m_motionNode->GetMirrorMotion()) << "Mirror motion effect should be on."; - const AZ::Vector3 l_handMirroredPos = m_jackPose->GetModelSpaceTransform(m_l_handIndex).mPosition; - const AZ::Vector3 l_loArmMirroredPos = m_jackPose->GetModelSpaceTransform(m_l_loArmIndex).mPosition; - const AZ::Vector3 l_loLegMirroredPos = m_jackPose->GetModelSpaceTransform(m_l_loLegIndex).mPosition; - const AZ::Vector3 l_ankleMirroredPos = m_jackPose->GetModelSpaceTransform(m_l_ankleIndex).mPosition; - const AZ::Vector3 r_handMirroredPos = m_jackPose->GetModelSpaceTransform(m_r_handIndex).mPosition; - const AZ::Vector3 r_loArmMirroredPos = m_jackPose->GetModelSpaceTransform(m_r_loArmIndex).mPosition; - const AZ::Vector3 r_loLegMirroredPos = m_jackPose->GetModelSpaceTransform(m_r_loLegIndex).mPosition; - const AZ::Vector3 r_ankleMirroredPos = m_jackPose->GetModelSpaceTransform(m_r_ankleIndex).mPosition; + const AZ::Vector3 l_handMirroredPos = m_jackPose->GetModelSpaceTransform(m_lHandIndex).m_position; + const AZ::Vector3 l_loArmMirroredPos = m_jackPose->GetModelSpaceTransform(m_lLoArmIndex).m_position; + const AZ::Vector3 l_loLegMirroredPos = m_jackPose->GetModelSpaceTransform(m_lLoLegIndex).m_position; + const AZ::Vector3 l_ankleMirroredPos = m_jackPose->GetModelSpaceTransform(m_lAnkleIndex).m_position; + const AZ::Vector3 r_handMirroredPos = m_jackPose->GetModelSpaceTransform(m_rHandIndex).m_position; + const AZ::Vector3 r_loArmMirroredPos = m_jackPose->GetModelSpaceTransform(m_rLoArmIndex).m_position; + const AZ::Vector3 r_loLegMirroredPos = m_jackPose->GetModelSpaceTransform(m_rLoLegIndex).m_position; + const AZ::Vector3 r_ankleMirroredPos = m_jackPose->GetModelSpaceTransform(m_rAnkleIndex).m_position; EXPECT_TRUE(PositionsAreMirrored(l_handCurrentPos, r_handMirroredPos, 0.001f)) << "Actor's left hand should be mirrored to right hand."; EXPECT_TRUE(PositionsAreMirrored(l_handMirroredPos, r_handCurrentPos, 0.001f)) << "Actor's right hand should be mirrored to left hand."; @@ -303,7 +303,7 @@ namespace EMotionFX TEST_F(AnimGraphMotionNodeFixture, InPlaceInputAndNoEffectOutputsCorrectMotionAndPose) { - m_motionNode->AddConnection(m_paramNode, m_paramNode->FindOutputPortByName("InPlace")->mPortID, AnimGraphMotionNode::INPUTPORT_INPLACE); + m_motionNode->AddConnection(m_paramNode, m_paramNode->FindOutputPortByName("InPlace")->m_portId, AnimGraphMotionNode::INPUTPORT_INPLACE); ParamSetValue("InPlace", true); m_animGraphInstance->FindOrCreateUniqueNodeData(m_motionNode); @@ -315,15 +315,15 @@ namespace EMotionFX // Follow-through during the duration(~1.06666672 seconds) of the motion. for (float i = 0.1f; i < 1.2f; i += 0.1f) { - const AZ::Vector3 rootCurrentPos = m_jackPose->GetModelSpaceTransform(m_jack_rootIndex).mPosition; - const AZ::Vector3 pelvisCurrentPos = m_jackPose->GetModelSpaceTransform(m_bip01__pelvisIndex).mPosition; - const AZ::Vector3 lankleCurrentPos = m_jackPose->GetModelSpaceTransform(m_l_ankleIndex).mPosition; - const AZ::Vector3 rankleCurrentPos = m_jackPose->GetModelSpaceTransform(m_r_ankleIndex).mPosition; + const AZ::Vector3 rootCurrentPos = m_jackPose->GetModelSpaceTransform(m_jackRootIndex).m_position; + const AZ::Vector3 pelvisCurrentPos = m_jackPose->GetModelSpaceTransform(m_bip01PelvisIndex).m_position; + const AZ::Vector3 lankleCurrentPos = m_jackPose->GetModelSpaceTransform(m_lAnkleIndex).m_position; + const AZ::Vector3 rankleCurrentPos = m_jackPose->GetModelSpaceTransform(m_rAnkleIndex).m_position; GetEMotionFX().Update(1.0f / 10.0f); - const AZ::Vector3 rootUpdatedPos = m_jackPose->GetModelSpaceTransform(m_jack_rootIndex).mPosition; - const AZ::Vector3 pelvisUpdatedPos = m_jackPose->GetModelSpaceTransform(m_bip01__pelvisIndex).mPosition; - const AZ::Vector3 lankleUpdatedPos = m_jackPose->GetModelSpaceTransform(m_l_ankleIndex).mPosition; - const AZ::Vector3 rankleUpdatedPos = m_jackPose->GetModelSpaceTransform(m_r_ankleIndex).mPosition; + const AZ::Vector3 rootUpdatedPos = m_jackPose->GetModelSpaceTransform(m_jackRootIndex).m_position; + const AZ::Vector3 pelvisUpdatedPos = m_jackPose->GetModelSpaceTransform(m_bip01PelvisIndex).m_position; + const AZ::Vector3 lankleUpdatedPos = m_jackPose->GetModelSpaceTransform(m_lAnkleIndex).m_position; + const AZ::Vector3 rankleUpdatedPos = m_jackPose->GetModelSpaceTransform(m_rAnkleIndex).m_position; EXPECT_TRUE(m_motionNode->GetIsInPlace(m_animGraphInstance)) << "InPlace flag of the motion node should be true."; EXPECT_TRUE(rootUpdatedPos.IsClose(rootCurrentPos, 0.0f)) << "Position of root should not change."; EXPECT_TRUE(pelvisCurrentPos != pelvisUpdatedPos) << "Position of pelvis should change."; @@ -343,12 +343,12 @@ namespace EMotionFX GetEMotionFX().Update(1.0f / 60.0f); // Root node's initial position under the first speed factor. - AZ::Vector3 rootInitialPosUnderSpeed1 = m_jackPose->GetModelSpaceTransform(m_jack_rootIndex).mPosition; - uniqueData->mReload = true; + AZ::Vector3 rootInitialPosUnderSpeed1 = m_jackPose->GetModelSpaceTransform(m_jackRootIndex).m_position; + uniqueData->m_reload = true; GetEMotionFX().Update(1.1f); // Root node's final position under the first speed factor. - AZ::Vector3 rootFinalPosUnderSpeed1 = m_jackPose->GetModelSpaceTransform(m_jack_rootIndex).mPosition; + AZ::Vector3 rootFinalPosUnderSpeed1 = m_jackPose->GetModelSpaceTransform(m_jackRootIndex).m_position; std::vector speedFactors = { 2.0f, 3.0f, 10.0f, 100.0f }; std::vector playTimes = { 0.6f, 0.4f, 0.11f, 0.011f }; for (size_t i = 0; i < 4; i++) @@ -357,12 +357,12 @@ namespace EMotionFX m_fltConstNode->SetValue(speedFactors[i]); GetEMotionFX().Update(1.0f / 60.0f); - uniqueData->mReload = true; - const AZ::Vector3 rootInitialPosUnderSpeed2 = m_jackPose->GetModelSpaceTransform(m_jack_rootIndex).mPosition; + uniqueData->m_reload = true; + const AZ::Vector3 rootInitialPosUnderSpeed2 = m_jackPose->GetModelSpaceTransform(m_jackRootIndex).m_position; // Faster play speed requires less play time to reach its final pose. GetEMotionFX().Update(playTimes[i]); - const AZ::Vector3 rootFinalPosUnderSpeed2 = m_jackPose->GetModelSpaceTransform(m_jack_rootIndex).mPosition; + const AZ::Vector3 rootFinalPosUnderSpeed2 = m_jackPose->GetModelSpaceTransform(m_jackRootIndex).m_position; EXPECT_TRUE(rootInitialPosUnderSpeed1.IsClose(rootInitialPosUnderSpeed2, 0.0f)) << "Root initial position should be same in different motion speeds."; EXPECT_TRUE(rootFinalPosUnderSpeed1.IsClose(rootFinalPosUnderSpeed2, 0.0f)) << "Root final position should be same in different motion speeds."; @@ -379,10 +379,10 @@ namespace EMotionFX m_motionNode->SetMotionPlaySpeed(1.0f); GetEMotionFX().Update(1.0f / 60.0f); - rootInitialPosUnderSpeed1 = m_jackPose->GetModelSpaceTransform(m_jack_rootIndex).mPosition; - uniqueData->mReload = true; + rootInitialPosUnderSpeed1 = m_jackPose->GetModelSpaceTransform(m_jackRootIndex).m_position; + uniqueData->m_reload = true; GetEMotionFX().Update(1.1f); - rootFinalPosUnderSpeed1 = m_jackPose->GetModelSpaceTransform(m_jack_rootIndex).mPosition; + rootFinalPosUnderSpeed1 = m_jackPose->GetModelSpaceTransform(m_jackRootIndex).m_position; // Similar test to using the InPlace input port. for (size_t i = 0; i < 4; i++) @@ -391,11 +391,11 @@ namespace EMotionFX m_motionNode->SetMotionPlaySpeed(speedFactors[i]); GetEMotionFX().Update(1.0f / 60.0f); - uniqueData->mReload = true; - const AZ::Vector3 rootInitialPosUnderSpeed2 = m_jackPose->GetModelSpaceTransform(m_jack_rootIndex).mPosition; + uniqueData->m_reload = true; + const AZ::Vector3 rootInitialPosUnderSpeed2 = m_jackPose->GetModelSpaceTransform(m_jackRootIndex).m_position; GetEMotionFX().Update(playTimes[i]); - const AZ::Vector3 rootFinalPosUnderSpeed2 = m_jackPose->GetModelSpaceTransform(m_jack_rootIndex).mPosition; + const AZ::Vector3 rootFinalPosUnderSpeed2 = m_jackPose->GetModelSpaceTransform(m_jackRootIndex).m_position; EXPECT_TRUE(rootInitialPosUnderSpeed1.IsClose(rootInitialPosUnderSpeed2, 0.0f)); EXPECT_TRUE(rootFinalPosUnderSpeed1.IsClose(rootFinalPosUnderSpeed2, 0.0f)); @@ -412,7 +412,7 @@ namespace EMotionFX AddMotionData(TestMotionAssets::GetJackDie(), "jack_death_fall_back_zup"); m_motionNode->AddMotionId("jack_death_fall_back_zup"); AnimGraphMotionNode::UniqueData* uniqueData = static_cast(m_animGraphInstance->FindOrCreateUniqueNodeData(m_motionNode)); - uniqueData->mReload = true; + uniqueData->m_reload = true; m_motionNode->Reinit(); m_motionNode->SetIndexMode(AnimGraphMotionNode::INDEXMODE_RANDOMIZE); @@ -429,11 +429,11 @@ namespace EMotionFX for (size_t i = 0; i < 20; i++) { // Run the test loop multiple times to make sure all the motion index is picked. - uniqueData->mReload = true; + uniqueData->m_reload = true; m_motionNode->Reinit(); GetEMotionFX().Update(2.0f); - const uint32 motionIndex = uniqueData->mActiveMotionIndex; + const uint32 motionIndex = uniqueData->m_activeMotionIndex; if (motionIndex == 0) { motion1Displayed = true; @@ -457,18 +457,18 @@ namespace EMotionFX uniqueData->Reset(); m_motionNode->Reinit(); uniqueData->Update(); - uint32 currentMotionIndex = uniqueData->mActiveMotionIndex; + uint32 currentMotionIndex = uniqueData->m_activeMotionIndex; // In randomized no repeat index mode, motions should change in each loop. for (size_t i = 0; i < 10; i++) { - uniqueData->mReload = true; + uniqueData->m_reload = true; m_motionNode->Reinit(); // As we keep and use the cached version of the unique data, we need to manually update it. uniqueData->Update(); - const AZ::u32 updatedMotionIndex = uniqueData->mActiveMotionIndex; + const AZ::u32 updatedMotionIndex = uniqueData->m_activeMotionIndex; EXPECT_TRUE(updatedMotionIndex != currentMotionIndex) << "Updated motion index should be different from its previous motion index."; currentMotionIndex = updatedMotionIndex; } @@ -478,11 +478,11 @@ namespace EMotionFX // In sequential index mode, motions should increase its index each time and wrap around. Basically iterating over the list of motions. for (size_t i = 0; i < 10; i++) { - uniqueData->mReload = true; + uniqueData->m_reload = true; m_motionNode->Reinit(); uniqueData->Update(); - EXPECT_NE(currentMotionIndex, uniqueData->mActiveMotionIndex) << "Updated motion index should match the expected motion index."; - currentMotionIndex = uniqueData->mActiveMotionIndex; + EXPECT_NE(currentMotionIndex, uniqueData->m_activeMotionIndex) << "Updated motion index should match the expected motion index."; + currentMotionIndex = uniqueData->m_activeMotionIndex; } }; } // end namespace EMotionFX diff --git a/Gems/EMotionFX/Code/Tests/AnimGraphNodeEventFilterTests.cpp b/Gems/EMotionFX/Code/Tests/AnimGraphNodeEventFilterTests.cpp index eb1da8f0a3..7509f03ede 100644 --- a/Gems/EMotionFX/Code/Tests/AnimGraphNodeEventFilterTests.cpp +++ b/Gems/EMotionFX/Code/Tests/AnimGraphNodeEventFilterTests.cpp @@ -26,12 +26,12 @@ namespace EMotionFX { struct EventFilteringTestParam { - AnimGraphObject::EEventMode eventMode; - float motionTime; - float testDuration; // Maximum of time this test will be run. - AZStd::pair eventTimeRange; - float blendWeight; - int eventTriggerTimes; + AnimGraphObject::EEventMode m_eventMode; + float m_motionTime; + float m_testDuration; // Maximum of time this test will be run. + AZStd::pair m_eventTimeRange; + float m_blendWeight; + int m_eventTriggerTimes; }; // Use this event handler to test if the on event is called. @@ -111,7 +111,7 @@ namespace EMotionFX const AZStd::string motionId = AZStd::string::format("Motion%zu", i); Motion* motion = aznew Motion(motionId.c_str()); motion->SetMotionData(aznew NonUniformMotionData()); - motion->GetMotionData()->SetDuration(param.motionTime); + motion->GetMotionData()->SetDuration(param.m_motionTime); m_motions.emplace_back(motion); MotionSet::MotionEntry* motionEntry = aznew MotionSet::MotionEntry(motion->GetName(), motion->GetName(), motion); m_motionSet->AddMotionEntry(motionEntry); @@ -124,7 +124,7 @@ namespace EMotionFX motion->GetEventTable()->AutoCreateSyncTrack(motion); AnimGraphSyncTrack* syncTrack = motion->GetEventTable()->GetSyncTrack(); AZStd::shared_ptr data = GetEMotionFX().GetEventManager()->FindOrCreateEventData(motionId.c_str(), "params"); - syncTrack->AddEvent(param.eventTimeRange.first, param.eventTimeRange.second, data); + syncTrack->AddEvent(param.m_eventTimeRange.first, param.m_eventTimeRange.second, data); } m_eventHandler = aznew EventFilteringEventHandler(); @@ -151,20 +151,20 @@ namespace EMotionFX TEST_P(AnimGraphNodeEventFilterTestFixture, EventFilterTests) { const EventFilteringTestParam& param = GetParam(); - m_floatNode->SetValue(param.blendWeight); - m_blend2Node->SetEventMode(param.eventMode); + m_floatNode->SetValue(param.m_blendWeight); + m_blend2Node->SetEventMode(param.m_eventMode); // Calling update first to make sure unique data is created. GetEMotionFX().Update(0.0f); // Expect the event handler will call different number of times based on the filtering mode, motion event range and test duration. EXPECT_CALL(*m_eventHandler, OnEvent(testing::_)) - .Times(param.eventTriggerTimes); + .Times(param.m_eventTriggerTimes); // Update emfx to trigger the event firing. float totalTime = 0.0f; const float deltaTime = 0.1f; - while (totalTime <= param.testDuration) + while (totalTime <= param.m_testDuration) { GetEMotionFX().Update(deltaTime); totalTime += deltaTime; diff --git a/Gems/EMotionFX/Code/Tests/AnimGraphStateMachineInterruptionTests.cpp b/Gems/EMotionFX/Code/Tests/AnimGraphStateMachineInterruptionTests.cpp index 38acdd68ee..1f700129c0 100644 --- a/Gems/EMotionFX/Code/Tests/AnimGraphStateMachineInterruptionTests.cpp +++ b/Gems/EMotionFX/Code/Tests/AnimGraphStateMachineInterruptionTests.cpp @@ -21,34 +21,34 @@ namespace EMotionFX struct AnimGraphStateMachine_InterruptionTestData { // Graph construction data. - float transitionLeftBlendTime; - float transitionLeftCountDownTime; - float transitionMiddleBlendTime; - float transitionMiddleCountDownTime; - float transitionRightBlendTime; - float transitionRightCountDownTime; + float m_transitionLeftBlendTime; + float m_transitionLeftCountDownTime; + float m_transitionMiddleBlendTime; + float m_transitionMiddleCountDownTime; + float m_transitionRightBlendTime; + float m_transitionRightCountDownTime; // Per frame checks. struct ActiveObjectsAtFrame { - AZ::u32 frameNr; + AZ::u32 m_frameNr; - bool stateA; - bool stateB; - bool stateC; - bool transitionLeft; - bool transitionMiddle; - bool transitionRight; + bool m_stateA; + bool m_stateB; + bool m_stateC; + bool m_transitionLeft; + bool m_transitionMiddle; + bool m_transitionRight; - AZ::u32 numStatesEntering; - AZ::u32 numStatesEntered; - AZ::u32 numStatesExited; - AZ::u32 numStatesEnded; - AZ::u32 numTransitionsStarted; - AZ::u32 numTransitionsEnded; + AZ::u32 m_numStatesEntering; + AZ::u32 m_numStatesEntered; + AZ::u32 m_numStatesExited; + AZ::u32 m_numStatesEnded; + AZ::u32 m_numTransitionsStarted; + AZ::u32 m_numTransitionsEnded; }; - std::vector activeObjectsAtFrame; + std::vector m_activeObjectsAtFrame; }; class AnimGraphStateMachine_InterruptionFixture @@ -86,21 +86,21 @@ namespace EMotionFX AnimGraphStateTransition* transitionLeft = AddTransitionWithTimeCondition(stateStart, stateA, - param.transitionLeftBlendTime/*blendTime*/, - param.transitionLeftCountDownTime)/*countDownTime*/; + param.m_transitionLeftBlendTime/*blendTime*/, + param.m_transitionLeftCountDownTime)/*countDownTime*/; transitionLeft->SetCanBeInterrupted(true); AnimGraphStateTransition* transitionMiddle = AddTransitionWithTimeCondition(stateStart, stateB, - param.transitionMiddleBlendTime, - param.transitionMiddleCountDownTime); + param.m_transitionMiddleBlendTime, + param.m_transitionMiddleCountDownTime); transitionMiddle->SetCanBeInterrupted(true); transitionMiddle->SetCanInterruptOtherTransitions(true); AnimGraphStateTransition* transitionRight = AddTransitionWithTimeCondition(stateStart, stateC, - param.transitionRightBlendTime, - param.transitionRightCountDownTime); + param.m_transitionRightBlendTime, + param.m_transitionRightCountDownTime); transitionRight->SetCanInterruptOtherTransitions(true); m_motionNodeAnimGraph->InitAfterLoading(); @@ -142,58 +142,58 @@ namespace EMotionFX /*preUpdateCallback*/[this](AnimGraphInstance*, float, float, int) {}, /*postUpdateCallback*/[this](AnimGraphInstance* animGraphInstance, [[maybe_unused]] float time, [[maybe_unused]] float timeDelta, int frame) { - const std::vector& activeObjectsAtFrame = GetParam().activeObjectsAtFrame; + const std::vector& activeObjectsAtFrame = GetParam().m_activeObjectsAtFrame; const AnimGraphStateMachine* stateMachine = this->m_rootStateMachine; const AZStd::vector& activeStates = stateMachine->GetActiveStates(animGraphInstance); const AZStd::vector& activeTransitions = stateMachine->GetActiveTransitions(animGraphInstance); AnimGraphStateMachine_InterruptionTestData::ActiveObjectsAtFrame compareAgainst; - compareAgainst.stateA = AZStd::find_if(activeStates.begin(), activeStates.end(), + compareAgainst.m_stateA = AZStd::find_if(activeStates.begin(), activeStates.end(), [](AnimGraphNode* element) -> bool { return element->GetNameString() == "A"; }) != activeStates.end(); - compareAgainst.stateB = AZStd::find_if(activeStates.begin(), activeStates.end(), + compareAgainst.m_stateB = AZStd::find_if(activeStates.begin(), activeStates.end(), [](AnimGraphNode* element) -> bool { return element->GetNameString() == "B"; }) != activeStates.end(); - compareAgainst.stateC = AZStd::find_if(activeStates.begin(), activeStates.end(), + compareAgainst.m_stateC = AZStd::find_if(activeStates.begin(), activeStates.end(), [](AnimGraphNode* element) -> bool { return element->GetNameString() == "C"; }) != activeStates.end(); - compareAgainst.transitionLeft = AZStd::find_if(activeTransitions.begin(), activeTransitions.end(), + compareAgainst.m_transitionLeft = AZStd::find_if(activeTransitions.begin(), activeTransitions.end(), [](AnimGraphStateTransition* element) -> bool { return element->GetTargetNode()->GetNameString() == "A"; }) != activeTransitions.end(); - compareAgainst.transitionMiddle = AZStd::find_if(activeTransitions.begin(), activeTransitions.end(), + compareAgainst.m_transitionMiddle = AZStd::find_if(activeTransitions.begin(), activeTransitions.end(), [](AnimGraphStateTransition* element) -> bool { return element->GetTargetNode()->GetNameString() == "B"; }) != activeTransitions.end(); - compareAgainst.transitionRight = AZStd::find_if(activeTransitions.begin(), activeTransitions.end(), + compareAgainst.m_transitionRight = AZStd::find_if(activeTransitions.begin(), activeTransitions.end(), [](AnimGraphStateTransition* element) -> bool { return element->GetTargetNode()->GetNameString() == "C"; }) != activeTransitions.end(); for (const auto& activeObjects : activeObjectsAtFrame) { - if (activeObjects.frameNr == frame) + if (activeObjects.m_frameNr == frame) { // Check which states and transitions are active and compare it to the expected ones. - EXPECT_EQ(activeObjects.stateA, compareAgainst.stateA) - << "State A expected to be " << (activeObjects.stateA ? "active." : "inactive."); - EXPECT_EQ(activeObjects.stateB, compareAgainst.stateB) - << "State B expected to be " << (activeObjects.stateB ? "active." : "inactive."); - EXPECT_EQ(activeObjects.stateC, compareAgainst.stateC) - << "State C expected to be " << (activeObjects.stateB ? "active." : "inactive."); - EXPECT_EQ(activeObjects.transitionLeft, compareAgainst.transitionLeft) - << "Transition Start->A expected to be " << (activeObjects.transitionLeft ? "active." : "inactive."); - EXPECT_EQ(activeObjects.transitionMiddle, compareAgainst.transitionMiddle) - << "Transition Start->B expected to be " << (activeObjects.transitionMiddle ? "active." : "inactive."); - EXPECT_EQ(activeObjects.transitionRight, compareAgainst.transitionRight) - << "Transition Start->C expected to be " << (activeObjects.transitionRight ? "active." : "inactive."); + EXPECT_EQ(activeObjects.m_stateA, compareAgainst.m_stateA) + << "State A expected to be " << (activeObjects.m_stateA ? "active." : "inactive."); + EXPECT_EQ(activeObjects.m_stateB, compareAgainst.m_stateB) + << "State B expected to be " << (activeObjects.m_stateB ? "active." : "inactive."); + EXPECT_EQ(activeObjects.m_stateC, compareAgainst.m_stateC) + << "State C expected to be " << (activeObjects.m_stateB ? "active." : "inactive."); + EXPECT_EQ(activeObjects.m_transitionLeft, compareAgainst.m_transitionLeft) + << "Transition Start->A expected to be " << (activeObjects.m_transitionLeft ? "active." : "inactive."); + EXPECT_EQ(activeObjects.m_transitionMiddle, compareAgainst.m_transitionMiddle) + << "Transition Start->B expected to be " << (activeObjects.m_transitionMiddle ? "active." : "inactive."); + EXPECT_EQ(activeObjects.m_transitionRight, compareAgainst.m_transitionRight) + << "Transition Start->C expected to be " << (activeObjects.m_transitionRight ? "active." : "inactive."); // Check anim graph events. - EXPECT_EQ(this->m_eventHandler->m_numStatesEntering, activeObjects.numStatesEntering) - << this->m_eventHandler->m_numStatesEntering << " states entering while " << activeObjects.numStatesEntering << " are expected."; - EXPECT_EQ(this->m_eventHandler->m_numStatesEntered, activeObjects.numStatesEntered) - << this->m_eventHandler->m_numStatesEntered << " states entered while " << activeObjects.numStatesEntered << " are expected."; - EXPECT_EQ(this->m_eventHandler->m_numStatesExited, activeObjects.numStatesExited) - << this->m_eventHandler->m_numStatesExited << " states exited while " << activeObjects.numStatesExited << " are expected."; - EXPECT_EQ(this->m_eventHandler->m_numStatesEnded, activeObjects.numStatesEnded) - << this->m_eventHandler->m_numStatesEnded << " states ended while " << activeObjects.numStatesEnded << " are expected."; - EXPECT_EQ(this->m_eventHandler->m_numTransitionsStarted, activeObjects.numTransitionsStarted) - << this->m_eventHandler->m_numTransitionsStarted << " transitions started while " << activeObjects.numTransitionsStarted << " are expected."; - EXPECT_EQ(this->m_eventHandler->m_numTransitionsEnded, activeObjects.numTransitionsEnded) - << this->m_eventHandler->m_numTransitionsEnded << " transitions ended while " << activeObjects.numTransitionsEnded << " are expected."; + EXPECT_EQ(this->m_eventHandler->m_numStatesEntering, activeObjects.m_numStatesEntering) + << this->m_eventHandler->m_numStatesEntering << " states entering while " << activeObjects.m_numStatesEntering << " are expected."; + EXPECT_EQ(this->m_eventHandler->m_numStatesEntered, activeObjects.m_numStatesEntered) + << this->m_eventHandler->m_numStatesEntered << " states entered while " << activeObjects.m_numStatesEntered << " are expected."; + EXPECT_EQ(this->m_eventHandler->m_numStatesExited, activeObjects.m_numStatesExited) + << this->m_eventHandler->m_numStatesExited << " states exited while " << activeObjects.m_numStatesExited << " are expected."; + EXPECT_EQ(this->m_eventHandler->m_numStatesEnded, activeObjects.m_numStatesEnded) + << this->m_eventHandler->m_numStatesEnded << " states ended while " << activeObjects.m_numStatesEnded << " are expected."; + EXPECT_EQ(this->m_eventHandler->m_numTransitionsStarted, activeObjects.m_numTransitionsStarted) + << this->m_eventHandler->m_numTransitionsStarted << " transitions started while " << activeObjects.m_numTransitionsStarted << " are expected."; + EXPECT_EQ(this->m_eventHandler->m_numTransitionsEnded, activeObjects.m_numTransitionsEnded) + << this->m_eventHandler->m_numTransitionsEnded << " transitions ended while " << activeObjects.m_numTransitionsEnded << " are expected."; } } } @@ -381,13 +381,13 @@ namespace EMotionFX struct AnimGraphStateMachine_InterruptionPropertiesTestData { - float transitionLeftBlendTime; - float transitionLeftCountDownTime; - float transitionRightBlendTime; - float transitionRightCountDownTime; - AnimGraphStateTransition::EInterruptionMode interruptionMode; - float maxBlendWeight; - AnimGraphStateTransition::EInterruptionBlendBehavior interruptionBlendBehavior; + float m_transitionLeftBlendTime; + float m_transitionLeftCountDownTime; + float m_transitionRightBlendTime; + float m_transitionRightCountDownTime; + AnimGraphStateTransition::EInterruptionMode m_interruptionMode; + float m_maxBlendWeight; + AnimGraphStateTransition::EInterruptionBlendBehavior m_interruptionBlendBehavior; }; class AnimGraphStateMachine_InterruptionPropertiesFixture @@ -422,18 +422,18 @@ namespace EMotionFX // Start->A (can be interrupted) m_transitionLeft = AddTransitionWithTimeCondition(stateStart, stateA, - param.transitionLeftBlendTime, - param.transitionLeftCountDownTime); + param.m_transitionLeftBlendTime, + param.m_transitionLeftCountDownTime); m_transitionLeft->SetCanBeInterrupted(true); - m_transitionLeft->SetInterruptionMode(param.interruptionMode); - m_transitionLeft->SetMaxInterruptionBlendWeight(param.maxBlendWeight); - m_transitionLeft->SetInterruptionBlendBehavior(param.interruptionBlendBehavior); + m_transitionLeft->SetInterruptionMode(param.m_interruptionMode); + m_transitionLeft->SetMaxInterruptionBlendWeight(param.m_maxBlendWeight); + m_transitionLeft->SetInterruptionBlendBehavior(param.m_interruptionBlendBehavior); // Start->B (interrupting transition) m_transitionRight = AddTransitionWithTimeCondition(stateStart, stateB, - param.transitionRightBlendTime, - param.transitionRightCountDownTime); + param.m_transitionRightBlendTime, + param.m_transitionRightCountDownTime); m_transitionRight->SetCanInterruptOtherTransitions(true); m_motionNodeAnimGraph->InitAfterLoading(); diff --git a/Gems/EMotionFX/Code/Tests/AnimGraphStateMachineSyncTests.cpp b/Gems/EMotionFX/Code/Tests/AnimGraphStateMachineSyncTests.cpp index 1d341dd753..37996abbd8 100644 --- a/Gems/EMotionFX/Code/Tests/AnimGraphStateMachineSyncTests.cpp +++ b/Gems/EMotionFX/Code/Tests/AnimGraphStateMachineSyncTests.cpp @@ -20,11 +20,11 @@ namespace EMotionFX { struct AnimGraphStateMachineSyncParam { - float playSpeedA; - float durationA; - float playSpeedB; - float durationB; - bool syncEnabled; + float m_playSpeedA; + float m_durationA; + float m_playSpeedB; + float m_durationB; + bool m_syncEnabled; }; class AnimGraphStateMachineSyncFixture @@ -51,7 +51,7 @@ namespace EMotionFX 1.0f/*blendTime*/, 0.0f/*countDownTime*/); - if (param.syncEnabled) + if (param.m_syncEnabled) { m_transition->SetSyncMode(AnimGraphObject::SYNCMODE_CLIPBASED); } @@ -85,8 +85,8 @@ namespace EMotionFX m_animGraphInstance->Destroy(); m_animGraphInstance = m_motionNodeAnimGraph->GetAnimGraphInstance(m_actorInstance, m_motionSet); - SetUpMotionNode("testMotionA", param.playSpeedA, param.durationA, m_stateA); - SetUpMotionNode("testMotionB", param.playSpeedB, param.durationB, m_stateB); + SetUpMotionNode("testMotionA", param.m_playSpeedA, param.m_durationA, m_stateA); + SetUpMotionNode("testMotionB", param.m_playSpeedB, param.m_durationB, m_stateB); GetEMotionFX().Update(0.0f); } diff --git a/Gems/EMotionFX/Code/Tests/AnimGraphSyncTrackTests.cpp b/Gems/EMotionFX/Code/Tests/AnimGraphSyncTrackTests.cpp index d23638c9ea..bb0c4e47b8 100644 --- a/Gems/EMotionFX/Code/Tests/AnimGraphSyncTrackTests.cpp +++ b/Gems/EMotionFX/Code/Tests/AnimGraphSyncTrackTests.cpp @@ -19,27 +19,27 @@ namespace EMotionFX { struct FindEventIndicesParams { - void (*eventFactory)(MotionEventTrack* track); - float timeValue; - size_t expectedLeft; - size_t expectedRight; + void (*m_eventFactory)(MotionEventTrack* track); + float m_timeValue; + size_t m_expectedLeft; + size_t m_expectedRight; }; void PrintTo(FindEventIndicesParams const object, ::std::ostream* os) { - if (object.eventFactory == &MakeNoEvents) + if (object.m_eventFactory == &MakeNoEvents) { *os << "Events: 0"; } - else if (object.eventFactory == &MakeOneEvent) + else if (object.m_eventFactory == &MakeOneEvent) { *os << "Events: 1"; } - else if (object.eventFactory == &MakeTwoEvents) + else if (object.m_eventFactory == &MakeTwoEvents) { *os << "Events: 2"; } - else if (object.eventFactory == &MakeThreeEvents) + else if (object.m_eventFactory == &MakeThreeEvents) { *os << "Events: 3"; } @@ -47,9 +47,9 @@ namespace EMotionFX { *os << "Events: Unknown"; } - *os << " Time value: " << object.timeValue - << " Expected left: " << object.expectedLeft - << " Expected right: " << object.expectedRight + *os << " Time value: " << object.m_timeValue + << " Expected left: " << object.m_expectedLeft + << " Expected right: " << object.m_expectedRight ; } @@ -67,7 +67,7 @@ namespace EMotionFX m_syncTrack = m_motion->GetEventTable()->GetSyncTrack(); const FindEventIndicesParams& params = GetParam(); - params.eventFactory(m_syncTrack); + params.m_eventFactory(m_syncTrack); } void TearDown() override @@ -85,9 +85,9 @@ namespace EMotionFX { const FindEventIndicesParams& params = GetParam(); size_t indexLeft, indexRight; - m_syncTrack->FindEventIndices(params.timeValue, &indexLeft, &indexRight); - EXPECT_EQ(indexLeft, params.expectedLeft); - EXPECT_EQ(indexRight, params.expectedRight); + m_syncTrack->FindEventIndices(params.m_timeValue, &indexLeft, &indexRight); + EXPECT_EQ(indexLeft, params.m_expectedLeft); + EXPECT_EQ(indexRight, params.m_expectedRight); } INSTANTIATE_TEST_CASE_P(TestFindEventIndices, TestFindEventIndicesFixture, @@ -167,28 +167,28 @@ namespace EMotionFX struct FindMatchingEventsParams { - void (*eventFactory)(MotionEventTrack* track); - size_t startingIndex; - size_t inEventAIndex; - size_t inEventBIndex; - size_t expectedEventA; - size_t expectedEventB; - bool mirrorInput; - bool mirrorOutput; - bool forward; + void (*m_eventFactory)(MotionEventTrack* track); + size_t m_startingIndex; + size_t m_inEventAIndex; + size_t m_inEventBIndex; + size_t m_expectedEventA; + size_t m_expectedEventB; + bool m_mirrorInput; + bool m_mirrorOutput; + bool m_forward; }; void PrintTo(FindMatchingEventsParams const object, ::std::ostream* os) { - if (object.eventFactory == &MakeNoEvents) + if (object.m_eventFactory == &MakeNoEvents) { *os << "Events: 0"; } - else if (object.eventFactory == &MakeOneEvent) + else if (object.m_eventFactory == &MakeOneEvent) { *os << "Events: 1"; } - else if (object.eventFactory == &MakeTwoLeftRightEvents) + else if (object.m_eventFactory == &MakeTwoLeftRightEvents) { *os << "Events: LRLR"; } @@ -196,14 +196,14 @@ namespace EMotionFX { *os << "Events: Unknown"; } - *os << " Start index: " << object.startingIndex - << " In Event A: " << object.inEventAIndex - << " In Event B: " << object.inEventBIndex - << " Expected Event A: " << object.expectedEventA - << " Expected Event B: " << object.expectedEventB - << " Mirror Input: " << object.mirrorInput - << " Mirror Output: " << object.mirrorOutput - << " Play direction: " << (object.forward ? "Forward" : "Backward") + *os << " Start index: " << object.m_startingIndex + << " In Event A: " << object.m_inEventAIndex + << " In Event B: " << object.m_inEventBIndex + << " Expected Event A: " << object.m_expectedEventA + << " Expected Event B: " << object.m_expectedEventB + << " Mirror Input: " << object.m_mirrorInput + << " Mirror Output: " << object.m_mirrorOutput + << " Play direction: " << (object.m_forward ? "Forward" : "Backward") ; } @@ -221,7 +221,7 @@ namespace EMotionFX m_syncTrack = m_motion->GetEventTable()->GetSyncTrack(); const FindMatchingEventsParams& params = GetParam(); - params.eventFactory(m_syncTrack); + params.m_eventFactory(m_syncTrack); } void TearDown() override @@ -241,21 +241,21 @@ namespace EMotionFX // Make sure we have an event to get the id of const size_t eventCount = m_syncTrack->GetNumEvents(); - const size_t eventAID = eventCount ? m_syncTrack->GetEvent(params.inEventAIndex).HashForSyncing(params.mirrorInput) : 0; - const size_t eventBID = eventCount ? m_syncTrack->GetEvent(params.inEventBIndex).HashForSyncing(params.mirrorInput) : 0; + const size_t eventAID = eventCount ? m_syncTrack->GetEvent(params.m_inEventAIndex).HashForSyncing(params.m_mirrorInput) : 0; + const size_t eventBID = eventCount ? m_syncTrack->GetEvent(params.m_inEventBIndex).HashForSyncing(params.m_mirrorInput) : 0; size_t outLeft, outRight; m_syncTrack->FindMatchingEvents( - params.startingIndex, + params.m_startingIndex, eventAID, eventBID, &outLeft, &outRight, - params.forward, - params.mirrorOutput + params.m_forward, + params.m_mirrorOutput ); - EXPECT_EQ(outLeft, params.expectedEventA); - EXPECT_EQ(outRight, params.expectedEventB); + EXPECT_EQ(outLeft, params.m_expectedEventA); + EXPECT_EQ(outRight, params.m_expectedEventB); } INSTANTIATE_TEST_CASE_P(TestFindMatchingEvents, TestFindMatchingEventsFixture, diff --git a/Gems/EMotionFX/Code/Tests/AnimGraphTransitionConditionTests.cpp b/Gems/EMotionFX/Code/Tests/AnimGraphTransitionConditionTests.cpp index 67f7421509..8e72ea1e8a 100644 --- a/Gems/EMotionFX/Code/Tests/AnimGraphTransitionConditionTests.cpp +++ b/Gems/EMotionFX/Code/Tests/AnimGraphTransitionConditionTests.cpp @@ -72,7 +72,7 @@ namespace EMotionFX const ConditionSetUpFunc& func, const ActiveNodesMap& activeNodesMap, const FrameCallback& frameCallback = [] (AnimGraphInstance*, int) {} - ) : m_setUpFunction(func), activeNodes(activeNodesMap), callback(frameCallback) + ) : m_setUpFunction(func), m_activeNodes(activeNodesMap), m_callback(frameCallback) { } @@ -80,9 +80,9 @@ namespace EMotionFX const ConditionSetUpFunc m_setUpFunction; // List of nodes that are active on each frame - const ActiveNodesMap activeNodes; + const ActiveNodesMap m_activeNodes; - const FrameCallback callback; + const FrameCallback m_callback; }; template @@ -90,14 +90,14 @@ namespace EMotionFX public ::testing::WithParamInterface> { public: - const float fps; - const float updateInterval; - const int numUpdates; + const float m_fps; + const float m_updateInterval; + const int m_numUpdates; TransitionConditionFixtureP() - : fps(60.0f) - , updateInterval(1.0f / fps) - , numUpdates(static_cast(3.0f * fps)) + : m_fps(60.0f) + , m_updateInterval(1.0f / m_fps) + , m_numUpdates(static_cast(3.0f * m_fps)) { } @@ -130,14 +130,14 @@ namespace EMotionFX protected: void RunEMotionFXUpdateLoop() { - const ActiveNodesMap& activeNodes = this->GetParam().activeNodes; - const FrameCallback& callback = this->GetParam().callback; + const ActiveNodesMap& activeNodes = this->GetParam().m_activeNodes; + const FrameCallback& callback = this->GetParam().m_callback; // Allow tests to set starting values for parameters callback(m_animGraphInstance, -1); // Run the EMotionFX update loop for 3 seconds at 60 fps - for (int frameNum = 0; frameNum < numUpdates; ++frameNum) + for (int frameNum = 0; frameNum < m_numUpdates; ++frameNum) { // Allow for test-data defined updates to the graph state callback(m_animGraphInstance, frameNum); @@ -154,7 +154,7 @@ namespace EMotionFX } else { - GetEMotionFX().Update(updateInterval); + GetEMotionFX().Update(m_updateInterval); } // Check the state for the current frame @@ -168,7 +168,7 @@ namespace EMotionFX const AZStd::vector& gotActiveNodes = m_stateMachine->GetActiveStates(m_animGraphInstance); - EXPECT_EQ(gotActiveNodes, expectedActiveNodes) << "on frame " << frameNum << ", time " << frameNum * updateInterval; + EXPECT_EQ(gotActiveNodes, expectedActiveNodes) << "on frame " << frameNum << ", time " << frameNum * m_updateInterval; } } { @@ -237,28 +237,28 @@ namespace EMotionFX motionToExitTransition->SetBlendTime(0.0f); motionToExitTransition->AddCondition(motionToExitCondition); - mChildState = aznew AnimGraphStateMachine(); - mChildState->SetName("ChildStateMachine"); - mChildState->AddChildNode(childMotionNode); - mChildState->AddChildNode(childExitNode); - mChildState->SetEntryState(childMotionNode); - mChildState->AddTransition(motionToExitTransition); + m_childState = aznew AnimGraphStateMachine(); + m_childState->SetName("ChildStateMachine"); + m_childState->AddChildNode(childMotionNode); + m_childState->AddChildNode(childExitNode); + m_childState->SetEntryState(childMotionNode); + m_childState->AddTransition(motionToExitTransition); AnimGraphTimeCondition* motion0ToChildStateCondition = aznew AnimGraphTimeCondition(); motion0ToChildStateCondition->SetCountDownTime(0.5f); AnimGraphStateTransition* motion0ToChildStateTransition = aznew AnimGraphStateTransition(); motion0ToChildStateTransition->SetSourceNode(m_motionNodeA); - motion0ToChildStateTransition->SetTargetNode(mChildState); + motion0ToChildStateTransition->SetTargetNode(m_childState); motion0ToChildStateTransition->SetBlendTime(0.5f); motion0ToChildStateTransition->AddCondition(motion0ToChildStateCondition); AnimGraphStateTransition* childStateToMotion1Transition = aznew AnimGraphStateTransition(); - childStateToMotion1Transition->SetSourceNode(mChildState); + childStateToMotion1Transition->SetSourceNode(m_childState); childStateToMotion1Transition->SetTargetNode(m_motionNodeB); childStateToMotion1Transition->SetBlendTime(0.5f); - m_stateMachine->AddChildNode(mChildState); + m_stateMachine->AddChildNode(m_childState); m_stateMachine->AddTransition(motion0ToChildStateTransition); m_stateMachine->AddTransition(childStateToMotion1Transition); @@ -272,7 +272,7 @@ namespace EMotionFX } protected: - AnimGraphStateMachine* mChildState; + AnimGraphStateMachine* m_childState; }; class RangedMotionEventConditionFixture diff --git a/Gems/EMotionFX/Code/Tests/BlendTreeFloatMath1NodeTests.cpp b/Gems/EMotionFX/Code/Tests/BlendTreeFloatMath1NodeTests.cpp index 522cbf194e..3ece046845 100644 --- a/Gems/EMotionFX/Code/Tests/BlendTreeFloatMath1NodeTests.cpp +++ b/Gems/EMotionFX/Code/Tests/BlendTreeFloatMath1NodeTests.cpp @@ -98,7 +98,7 @@ namespace EMotionFX void TestInput(const AZStd::string& paramName, std::vector xInputs) { BlendTreeConnection* connection = m_floatMath1Node->AddConnection(m_paramNode, - m_paramNode->FindOutputPortByName(paramName)->mPortID, BlendTreeFloatMath1Node::PORTID_INPUT_X); + m_paramNode->FindOutputPortByName(paramName)->m_portId, BlendTreeFloatMath1Node::PORTID_INPUT_X); for (inputType i : xInputs) { diff --git a/Gems/EMotionFX/Code/Tests/BlendTreeFootIKNodeTests.cpp b/Gems/EMotionFX/Code/Tests/BlendTreeFootIKNodeTests.cpp index 609d291800..2f62365dd8 100644 --- a/Gems/EMotionFX/Code/Tests/BlendTreeFootIKNodeTests.cpp +++ b/Gems/EMotionFX/Code/Tests/BlendTreeFootIKNodeTests.cpp @@ -142,8 +142,8 @@ namespace EMotionFX ASSERT_NE(footIndex, InvalidIndex); EMotionFX::Transform transform = m_actorInstance->GetTransformData()->GetCurrentPose()->GetWorldSpaceTransform(footIndex); const BlendTreeFootIKNode::UniqueData* uniqueData = static_cast(m_animGraphInstance->FindOrCreateUniqueNodeData(m_ikNode)); - const float correction = (m_actorInstance->GetWorldSpaceTransform().mRotation.TransformVector(AZ::Vector3(0.0f, 0.0f, uniqueData->m_legs[legId].m_footHeight))).GetZ(); - const float pos = transform.mPosition.GetZ() - correction; + const float correction = (m_actorInstance->GetWorldSpaceTransform().m_rotation.TransformVector(AZ::Vector3(0.0f, 0.0f, uniqueData->m_legs[legId].m_footHeight))).GetZ(); + const float pos = transform.m_position.GetZ() - correction; EXPECT_NEAR(pos, height, tolerance); } @@ -325,7 +325,7 @@ namespace EMotionFX // Rotate the actor instance 180 degrees over the X axis as well. EMotionFX::Transform transform; transform.Identity(); - transform.mRotation = AZ::Quaternion::CreateFromAxisAngle(AZ::Vector3(1.0f, 0.0f, 0.0f), MCore::Math::pi); + transform.m_rotation = AZ::Quaternion::CreateFromAxisAngle(AZ::Vector3(1.0f, 0.0f, 0.0f), MCore::Math::pi); m_actorInstance->SetLocalSpaceTransform(transform); // Tests where the leg can reach the target position just fine, make sure the hip adjustment doesn't break it. diff --git a/Gems/EMotionFX/Code/Tests/BlendTreeMaskNodeTests.cpp b/Gems/EMotionFX/Code/Tests/BlendTreeMaskNodeTests.cpp index e63fd2c2c7..b86041c7aa 100644 --- a/Gems/EMotionFX/Code/Tests/BlendTreeMaskNodeTests.cpp +++ b/Gems/EMotionFX/Code/Tests/BlendTreeMaskNodeTests.cpp @@ -72,7 +72,7 @@ namespace EMotionFX for (size_t i = 0; i < numJoints; ++i) { Transform transform = outputPose.GetLocalSpaceTransform(i); - transform.mPosition = AZ::Vector3(m_identificationValue, m_identificationValue, m_identificationValue); + transform.m_position = AZ::Vector3(m_identificationValue, m_identificationValue, m_identificationValue); outputPose.SetLocalSpaceTransform(i, transform); } } @@ -230,7 +230,7 @@ namespace EMotionFX // The components of the position embed the origin. // If the compareValue equals m_basePosePosValue, it originates from the base pose input. // In case the joint is part of any of the masks and got overwriten by them, the compareValue represents the mask index. - const size_t compareValue = static_cast(transform.mPosition.GetX()); + const size_t compareValue = static_cast(transform.m_position.GetX()); AZ::Outcome maskIndex = FindMaskIndexForJoint(jointIndex); if (maskIndex.IsSuccess()) diff --git a/Gems/EMotionFX/Code/Tests/BlendTreeMirrorPoseNodeTests.cpp b/Gems/EMotionFX/Code/Tests/BlendTreeMirrorPoseNodeTests.cpp index 9851409a94..ee61e25370 100644 --- a/Gems/EMotionFX/Code/Tests/BlendTreeMirrorPoseNodeTests.cpp +++ b/Gems/EMotionFX/Code/Tests/BlendTreeMirrorPoseNodeTests.cpp @@ -32,8 +32,8 @@ namespace EMotionFX public: void SetupMirrorNodes(const Node* leftNode, const Node* rightNode) { - m_actor->GetNodeMirrorInfo(leftNode->GetNodeIndex()).mSourceNode = static_cast(rightNode->GetNodeIndex()); - m_actor->GetNodeMirrorInfo(rightNode->GetNodeIndex()).mSourceNode = static_cast(leftNode->GetNodeIndex()); + m_actor->GetNodeMirrorInfo(leftNode->GetNodeIndex()).m_sourceNode = static_cast(rightNode->GetNodeIndex()); + m_actor->GetNodeMirrorInfo(rightNode->GetNodeIndex()).m_sourceNode = static_cast(leftNode->GetNodeIndex()); } void ConstructGraph() override @@ -129,13 +129,13 @@ namespace EMotionFX // Remember the original position for comparison later Pose * jackPose = m_actorInstance->GetTransformData()->GetCurrentPose(); - const AZ::Vector3 l_upArmOriginalPos = jackPose->GetModelSpaceTransform(l_upArmIndex).mPosition; - const AZ::Vector3 r_upArmOriginalPos = jackPose->GetModelSpaceTransform(r_upArmIndex).mPosition; + const AZ::Vector3 l_upArmOriginalPos = jackPose->GetModelSpaceTransform(l_upArmIndex).m_position; + const AZ::Vector3 r_upArmOriginalPos = jackPose->GetModelSpaceTransform(r_upArmIndex).m_position; GetEMotionFX().Update(1.0f / 60.0f); // Remember mirrored position - const AZ::Vector3 l_upArmMirroredPos = jackPose->GetModelSpaceTransform(l_upArmIndex).mPosition; - const AZ::Vector3 r_upArmMirroredPos = jackPose->GetModelSpaceTransform(r_upArmIndex).mPosition; + const AZ::Vector3 l_upArmMirroredPos = jackPose->GetModelSpaceTransform(l_upArmIndex).m_position; + const AZ::Vector3 r_upArmMirroredPos = jackPose->GetModelSpaceTransform(r_upArmIndex).m_position; // Expect poses to be at the same position because mirror pose node is off EXPECT_FALSE(m_mirrorPoseNode->GetIsMirroringEnabled(m_animGraphInstance)); @@ -144,19 +144,19 @@ namespace EMotionFX // Mirror Pose Node enabled m_floatConstantNode->SetValue(1.0f); - const AZ::Vector3 l_upArmPos = jackPose->GetModelSpaceTransform(l_upArmIndex).mPosition; - const AZ::Vector3 r_upArmPos = jackPose->GetModelSpaceTransform(r_upArmIndex).mPosition; - const AZ::Vector3 l_loArmPos = jackPose->GetModelSpaceTransform(l_loArmIndex).mPosition; - const AZ::Vector3 r_loArmPos = jackPose->GetModelSpaceTransform(r_loArmIndex).mPosition; - const AZ::Vector3 l_handPos = jackPose->GetModelSpaceTransform(l_handIndex).mPosition; - const AZ::Vector3 r_handPos = jackPose->GetModelSpaceTransform(r_handIndex).mPosition; + const AZ::Vector3 l_upArmPos = jackPose->GetModelSpaceTransform(l_upArmIndex).m_position; + const AZ::Vector3 r_upArmPos = jackPose->GetModelSpaceTransform(r_upArmIndex).m_position; + const AZ::Vector3 l_loArmPos = jackPose->GetModelSpaceTransform(l_loArmIndex).m_position; + const AZ::Vector3 r_loArmPos = jackPose->GetModelSpaceTransform(r_loArmIndex).m_position; + const AZ::Vector3 l_handPos = jackPose->GetModelSpaceTransform(l_handIndex).m_position; + const AZ::Vector3 r_handPos = jackPose->GetModelSpaceTransform(r_handIndex).m_position; GetEMotionFX().Update(1.0f / 60.0f); - const AZ::Vector3 mirroredl_upArmPos = jackPose->GetModelSpaceTransform(l_upArmIndex).mPosition; - const AZ::Vector3 mirroredr_upArmPos = jackPose->GetModelSpaceTransform(r_upArmIndex).mPosition; - const AZ::Vector3 mirroredl_loArmPos = jackPose->GetModelSpaceTransform(l_loArmIndex).mPosition; - const AZ::Vector3 mirroredr_loArmPos = jackPose->GetModelSpaceTransform(r_loArmIndex).mPosition; - const AZ::Vector3 mirroredl_handPos = jackPose->GetModelSpaceTransform(l_handIndex).mPosition; - const AZ::Vector3 mirroredr_handPos = jackPose->GetModelSpaceTransform(r_handIndex).mPosition; + const AZ::Vector3 mirroredl_upArmPos = jackPose->GetModelSpaceTransform(l_upArmIndex).m_position; + const AZ::Vector3 mirroredr_upArmPos = jackPose->GetModelSpaceTransform(r_upArmIndex).m_position; + const AZ::Vector3 mirroredl_loArmPos = jackPose->GetModelSpaceTransform(l_loArmIndex).m_position; + const AZ::Vector3 mirroredr_loArmPos = jackPose->GetModelSpaceTransform(r_loArmIndex).m_position; + const AZ::Vector3 mirroredl_handPos = jackPose->GetModelSpaceTransform(l_handIndex).m_position; + const AZ::Vector3 mirroredr_handPos = jackPose->GetModelSpaceTransform(r_handIndex).m_position; EXPECT_TRUE(m_mirrorPoseNode->GetIsMirroringEnabled(m_animGraphInstance)); diff --git a/Gems/EMotionFX/Code/Tests/BlendTreeMotionFrameNodeTests.cpp b/Gems/EMotionFX/Code/Tests/BlendTreeMotionFrameNodeTests.cpp index 49938c121e..947b10f16e 100644 --- a/Gems/EMotionFX/Code/Tests/BlendTreeMotionFrameNodeTests.cpp +++ b/Gems/EMotionFX/Code/Tests/BlendTreeMotionFrameNodeTests.cpp @@ -73,7 +73,7 @@ namespace EMotionFX void SetAndTestTimeValue(BlendTreeMotionFrameNode::UniqueData* uniqueData, float newNormalizedTime, bool rewind = false) { - const float prevNewTime = uniqueData->mNewTime; + const float prevNewTime = uniqueData->m_newTime; m_motionFrameNode->SetNormalizedTimeValue(newNormalizedTime); if (rewind) @@ -96,9 +96,9 @@ namespace EMotionFX expectedOldTime = newNormalizedTime * m_motionDuration; } } - EXPECT_EQ(uniqueData->mOldTime, expectedOldTime); + EXPECT_EQ(uniqueData->m_oldTime, expectedOldTime); - EXPECT_EQ(uniqueData->mNewTime, newNormalizedTime * m_motionDuration); + EXPECT_EQ(uniqueData->m_newTime, newNormalizedTime * m_motionDuration); } public: diff --git a/Gems/EMotionFX/Code/Tests/BlendTreeRotationLimitNodeTests.cpp b/Gems/EMotionFX/Code/Tests/BlendTreeRotationLimitNodeTests.cpp index 31e0d696d0..b6d5e0b04d 100644 --- a/Gems/EMotionFX/Code/Tests/BlendTreeRotationLimitNodeTests.cpp +++ b/Gems/EMotionFX/Code/Tests/BlendTreeRotationLimitNodeTests.cpp @@ -101,10 +101,10 @@ namespace EMotionFX Transform expected = Transform::CreateIdentity(); expected.Set(AZ::Vector3::CreateZero(), expectedRotation); - bool success = AZ::IsClose(expected.mRotation.GetW(), outputRoot.mRotation.GetW(), 0.0001f); - success = success && AZ::IsClose(expected.mRotation.GetX(), outputRoot.mRotation.GetX(), 0.0001f); - success = success && AZ::IsClose(expected.mRotation.GetY(), outputRoot.mRotation.GetY(), 0.0001f); - success = success && AZ::IsClose(expected.mRotation.GetZ(), outputRoot.mRotation.GetZ(), 0.0001f); + bool success = AZ::IsClose(expected.m_rotation.GetW(), outputRoot.m_rotation.GetW(), 0.0001f); + success = success && AZ::IsClose(expected.m_rotation.GetX(), outputRoot.m_rotation.GetX(), 0.0001f); + success = success && AZ::IsClose(expected.m_rotation.GetY(), outputRoot.m_rotation.GetY(), 0.0001f); + success = success && AZ::IsClose(expected.m_rotation.GetZ(), outputRoot.m_rotation.GetZ(), 0.0001f); ASSERT_TRUE(success); } diff --git a/Gems/EMotionFX/Code/Tests/BlendTreeRotationMath2NodeTests.cpp b/Gems/EMotionFX/Code/Tests/BlendTreeRotationMath2NodeTests.cpp index a59d91fa8c..ef0a2aa959 100644 --- a/Gems/EMotionFX/Code/Tests/BlendTreeRotationMath2NodeTests.cpp +++ b/Gems/EMotionFX/Code/Tests/BlendTreeRotationMath2NodeTests.cpp @@ -87,10 +87,10 @@ namespace EMotionFX Transform outputRoot = GetOutputTransform(); Transform expected = Transform::CreateIdentity(); expected.Set(AZ::Vector3::CreateZero(), expectedRotation); - bool success = AZ::IsClose(expected.mRotation.GetW(), outputRoot.mRotation.GetW(), 0.0001f); - success = success && AZ::IsClose(expected.mRotation.GetX(), outputRoot.mRotation.GetX(), 0.0001f); - success = success && AZ::IsClose(expected.mRotation.GetY(), outputRoot.mRotation.GetY(), 0.0001f); - success = success && AZ::IsClose(expected.mRotation.GetZ(), outputRoot.mRotation.GetZ(), 0.0001f); + bool success = AZ::IsClose(expected.m_rotation.GetW(), outputRoot.m_rotation.GetW(), 0.0001f); + success = success && AZ::IsClose(expected.m_rotation.GetX(), outputRoot.m_rotation.GetX(), 0.0001f); + success = success && AZ::IsClose(expected.m_rotation.GetY(), outputRoot.m_rotation.GetY(), 0.0001f); + success = success && AZ::IsClose(expected.m_rotation.GetZ(), outputRoot.m_rotation.GetZ(), 0.0001f); m_rotationMathNode->SetMathFunction(EMotionFX::BlendTreeRotationMath2Node::MATHFUNCTION_INVERSE_MULTIPLY); @@ -99,10 +99,10 @@ namespace EMotionFX outputRoot = GetOutputTransform(); expected.Identity(); expected.Set(AZ::Vector3::CreateZero(), expectedRotation); - success = success && AZ::IsClose(expected.mRotation.GetW(), outputRoot.mRotation.GetW(), 0.0001f); - success = success && AZ::IsClose(expected.mRotation.GetX(), outputRoot.mRotation.GetX(), 0.0001f); - success = success && AZ::IsClose(expected.mRotation.GetY(), outputRoot.mRotation.GetY(), 0.0001f); - success = success && AZ::IsClose(expected.mRotation.GetZ(), outputRoot.mRotation.GetZ(), 0.0001f); + success = success && AZ::IsClose(expected.m_rotation.GetW(), outputRoot.m_rotation.GetW(), 0.0001f); + success = success && AZ::IsClose(expected.m_rotation.GetX(), outputRoot.m_rotation.GetX(), 0.0001f); + success = success && AZ::IsClose(expected.m_rotation.GetY(), outputRoot.m_rotation.GetY(), 0.0001f); + success = success && AZ::IsClose(expected.m_rotation.GetZ(), outputRoot.m_rotation.GetZ(), 0.0001f); ASSERT_TRUE(success); diff --git a/Gems/EMotionFX/Code/Tests/BlendTreeSimulatedObjectNodeTests.cpp b/Gems/EMotionFX/Code/Tests/BlendTreeSimulatedObjectNodeTests.cpp index df2f644eb4..a4ec05746a 100644 --- a/Gems/EMotionFX/Code/Tests/BlendTreeSimulatedObjectNodeTests.cpp +++ b/Gems/EMotionFX/Code/Tests/BlendTreeSimulatedObjectNodeTests.cpp @@ -135,10 +135,10 @@ namespace EMotionFX for (size_t joint = 0; joint < 3; ++joint) { - const AZ::Vector3& jointPos = currentPose.GetWorldSpaceTransform(m_jointIndices[joint]).mPosition; - const AZ::Vector3& jointBindPos = bindPose.GetWorldSpaceTransform(m_jointIndices[joint]).mPosition; + const AZ::Vector3& jointPos = currentPose.GetWorldSpaceTransform(m_jointIndices[joint]).m_position; + const AZ::Vector3& jointBindPos = bindPose.GetWorldSpaceTransform(m_jointIndices[joint]).m_position; ASSERT_TRUE((jointPos - jointBindPos).GetLength() <= 0.01f); // Make sure we didn't move too far from the bind pose. - ASSERT_TRUE(AZ::IsClose(currentPose.GetWorldSpaceTransform(m_jointIndices[joint]).mRotation.GetLength(), 1.0f, 0.001f)); // Make sure we have a unit quaternion. + ASSERT_TRUE(AZ::IsClose(currentPose.GetWorldSpaceTransform(m_jointIndices[joint]).m_rotation.GetLength(), 1.0f, 0.001f)); // Make sure we have a unit quaternion. } } } diff --git a/Gems/EMotionFX/Code/Tests/BlendTreeTransformNodeTests.cpp b/Gems/EMotionFX/Code/Tests/BlendTreeTransformNodeTests.cpp index 13baa72d09..80e6c81bb3 100644 --- a/Gems/EMotionFX/Code/Tests/BlendTreeTransformNodeTests.cpp +++ b/Gems/EMotionFX/Code/Tests/BlendTreeTransformNodeTests.cpp @@ -89,13 +89,13 @@ namespace EMotionFX translate_amount->SetValue(0.5f); Evaluate(); - expected.mPosition = AZ::Vector3(5.0f, 0.0f, 0.0f); + expected.m_position = AZ::Vector3(5.0f, 0.0f, 0.0f); outputRoot = GetOutputTransform(); ASSERT_EQ(expected, outputRoot); translate_amount->SetValue(1.0f); Evaluate(); - expected.mPosition = AZ::Vector3(10.0f, 0.0f, 0.0f); + expected.m_position = AZ::Vector3(10.0f, 0.0f, 0.0f); outputRoot = GetOutputTransform(); ASSERT_EQ(expected, outputRoot); } diff --git a/Gems/EMotionFX/Code/Tests/BlendTreeTwoLinkIKNodeTests.cpp b/Gems/EMotionFX/Code/Tests/BlendTreeTwoLinkIKNodeTests.cpp index 820e6d9fa4..d68bf9db83 100644 --- a/Gems/EMotionFX/Code/Tests/BlendTreeTwoLinkIKNodeTests.cpp +++ b/Gems/EMotionFX/Code/Tests/BlendTreeTwoLinkIKNodeTests.cpp @@ -28,13 +28,13 @@ namespace EMotionFX { struct BlendTreeTwoLinkIKNodeTestsData { - AZStd::string testJointName; - std::vector linkedJointNames; - std::vector> reachablePositions; - std::vector> unreachablePositions; - std::vector> rotations; - std::vector bendDirPosition; - std::vector alignToNodeNames; + AZStd::string m_testJointName; + std::vector m_linkedJointNames; + std::vector> m_reachablePositions; + std::vector> m_unreachablePositions; + std::vector> m_rotations; + std::vector m_bendDirPosition; + std::vector m_alignToNodeNames; }; class BlendTreeTwoLinkIKNodeFixture @@ -70,7 +70,7 @@ namespace EMotionFX m_paramNode = aznew BlendTreeParameterNode(); m_twoLinkIKNode = aznew BlendTreeTwoLinkIKNode(); - m_twoLinkIKNode->SetEndNodeName(m_param.testJointName); + m_twoLinkIKNode->SetEndNodeName(m_param.m_testJointName); m_blendTree = aznew BlendTree(); m_blendTree->AddChildNode(bindPoseNode); @@ -137,9 +137,9 @@ namespace EMotionFX TEST_P(BlendTreeTwoLinkIKNodeFixture, ReachablePositionsOutputCorrectPose) { // Set values for vector3 and twoLinkIKNode weight parameter - m_twoLinkIKNode->AddConnection(m_paramNode, m_paramNode->FindOutputPortByName("WeightParam")->mPortID, BlendTreeTwoLinkIKNode::INPUTPORT_WEIGHT); + m_twoLinkIKNode->AddConnection(m_paramNode, m_paramNode->FindOutputPortByName("WeightParam")->m_portId, BlendTreeTwoLinkIKNode::INPUTPORT_WEIGHT); m_twoLinkIKNode->AddConnection(m_paramNode, - m_paramNode->FindOutputPortByName("GoalPosParam")->mPortID, BlendTreeTwoLinkIKNode::INPUTPORT_GOALPOS); + m_paramNode->FindOutputPortByName("GoalPosParam")->m_portId, BlendTreeTwoLinkIKNode::INPUTPORT_GOALPOS); GetEMotionFX().Update(1.0f / 60.0f); const float weight = testing::get<0>(GetParam()); @@ -148,10 +148,10 @@ namespace EMotionFX // Remeber specific joint's original position to compare with its new position later const Pose* jackPose = m_actorInstance->GetTransformData()->GetCurrentPose(); size_t testJointIndex; - m_jackSkeleton->FindNodeAndIndexByName(m_param.testJointName, testJointIndex); - const AZ::Vector3& testJointPos = jackPose->GetModelSpaceTransform(testJointIndex).mPosition; + m_jackSkeleton->FindNodeAndIndexByName(m_param.m_testJointName, testJointIndex); + const AZ::Vector3& testJointPos = jackPose->GetModelSpaceTransform(testJointIndex).m_position; - for (std::vector goalPosXYZ : m_param.reachablePositions) + for (std::vector goalPosXYZ : m_param.m_reachablePositions) { const float goalX = goalPosXYZ[0]; const float goalY = goalPosXYZ[1]; @@ -159,7 +159,7 @@ namespace EMotionFX ParamSetValue("GoalPosParam", AZ::Vector3(goalX, goalY, goalZ)); GetEMotionFX().Update(5.0f / 60.0f); - const AZ::Vector3& testJointNewPos = jackPose->GetModelSpaceTransform(testJointIndex).mPosition; + const AZ::Vector3& testJointNewPos = jackPose->GetModelSpaceTransform(testJointIndex).m_position; // Based on weight, check if position of node changes to reachable goal position if (weight) @@ -179,7 +179,7 @@ namespace EMotionFX TEST_P(BlendTreeTwoLinkIKNodeFixture, ReachableAlignToNodeOutputCorrectPose) { - m_twoLinkIKNode->AddConnection(m_paramNode, m_paramNode->FindOutputPortByName("WeightParam")->mPortID, + m_twoLinkIKNode->AddConnection(m_paramNode, m_paramNode->FindOutputPortByName("WeightParam")->m_portId, BlendTreeTwoLinkIKNode::INPUTPORT_WEIGHT); GetEMotionFX().Update(1.0f / 60.0f); @@ -188,26 +188,26 @@ namespace EMotionFX const Pose* jackPose = m_actorInstance->GetTransformData()->GetCurrentPose(); size_t testJointIndex; - m_jackSkeleton->FindNodeAndIndexByName(m_param.testJointName, testJointIndex); - const AZ::Vector3& testJointPos = jackPose->GetModelSpaceTransform(testJointIndex).mPosition; + m_jackSkeleton->FindNodeAndIndexByName(m_param.m_testJointName, testJointIndex); + const AZ::Vector3& testJointPos = jackPose->GetModelSpaceTransform(testJointIndex).m_position; - for (AZStd::string& nodeName : m_param.alignToNodeNames) + for (AZStd::string& nodeName : m_param.m_alignToNodeNames) { NodeAlignmentData alignToNode; alignToNode.first = nodeName; alignToNode.second = 0; m_twoLinkIKNode->SetAlignToNode(alignToNode); - // Update will set uniqueData->mMustUpdate to false for efficiency purposes - // Unique data only updates once unless reset mMustUpdate to true again + // Update will set uniqueData->m_mustUpdate to false for efficiency purposes + // Unique data only updates once unless reset m_mustUpdate to true again BlendTreeTwoLinkIKNode::UniqueData* uniqueData = static_cast(m_animGraphInstance->FindOrCreateUniqueNodeData(m_twoLinkIKNode)); uniqueData->Invalidate(); size_t alignToNodeIndex; m_jackSkeleton->FindNodeAndIndexByName(nodeName, alignToNodeIndex); GetEMotionFX().Update(1.0f / 60.0f); - const AZ::Vector3& alignToNodePos = jackPose->GetModelSpaceTransform(alignToNodeIndex).mPosition; - const AZ::Vector3& testJointNewPos = jackPose->GetModelSpaceTransform(testJointIndex).mPosition; + const AZ::Vector3& alignToNodePos = jackPose->GetModelSpaceTransform(alignToNodeIndex).m_position; + const AZ::Vector3& testJointNewPos = jackPose->GetModelSpaceTransform(testJointIndex).m_position; // Based on weight, check if position of node changes to alignToNode position if (weight) @@ -224,10 +224,10 @@ namespace EMotionFX TEST_P(BlendTreeTwoLinkIKNodeFixture, UnreachablePositionsOutputCorrectPose) { - m_twoLinkIKNode->AddConnection(m_paramNode, m_paramNode->FindOutputPortByName("WeightParam")->mPortID, + m_twoLinkIKNode->AddConnection(m_paramNode, m_paramNode->FindOutputPortByName("WeightParam")->m_portId, BlendTreeTwoLinkIKNode::INPUTPORT_WEIGHT); m_twoLinkIKNode->AddConnection(m_paramNode, - m_paramNode->FindOutputPortByName("GoalPosParam")->mPortID, BlendTreeTwoLinkIKNode::INPUTPORT_GOALPOS); + m_paramNode->FindOutputPortByName("GoalPosParam")->m_portId, BlendTreeTwoLinkIKNode::INPUTPORT_GOALPOS); GetEMotionFX().Update(1.0f / 60.0f); const float weight = testing::get<0>(GetParam()); @@ -237,12 +237,12 @@ namespace EMotionFX size_t testJointIndex; size_t linkedJoint0Index; size_t linkedJoint1Index; - m_jackSkeleton->FindNodeAndIndexByName(m_param.testJointName, testJointIndex); - m_jackSkeleton->FindNodeAndIndexByName(m_param.linkedJointNames[0], linkedJoint0Index); - m_jackSkeleton->FindNodeAndIndexByName(m_param.linkedJointNames[1], linkedJoint1Index); - const AZ::Vector3& testJointPos = jackPose->GetModelSpaceTransform(testJointIndex).mPosition; + m_jackSkeleton->FindNodeAndIndexByName(m_param.m_testJointName, testJointIndex); + m_jackSkeleton->FindNodeAndIndexByName(m_param.m_linkedJointNames[0], linkedJoint0Index); + m_jackSkeleton->FindNodeAndIndexByName(m_param.m_linkedJointNames[1], linkedJoint1Index); + const AZ::Vector3& testJointPos = jackPose->GetModelSpaceTransform(testJointIndex).m_position; - for (std::vector goalPosXYZ : m_param.unreachablePositions) + for (std::vector goalPosXYZ : m_param.m_unreachablePositions) { const float goalX = goalPosXYZ[0]; const float goalY = goalPosXYZ[1]; @@ -250,9 +250,9 @@ namespace EMotionFX ParamSetValue("GoalPosParam", AZ::Vector3(goalX, goalY, goalZ)); GetEMotionFX().Update(1.0f / 60.0f); - const AZ::Vector3& testJointNewPos = jackPose->GetModelSpaceTransform(testJointIndex).mPosition; - const AZ::Vector3& linkedJoint0Pos = jackPose->GetModelSpaceTransform(linkedJoint0Index).mPosition; - const AZ::Vector3& linkedJoint1Pos = jackPose->GetModelSpaceTransform(linkedJoint1Index).mPosition; + const AZ::Vector3& testJointNewPos = jackPose->GetModelSpaceTransform(testJointIndex).m_position; + const AZ::Vector3& linkedJoint0Pos = jackPose->GetModelSpaceTransform(linkedJoint0Index).m_position; + const AZ::Vector3& linkedJoint1Pos = jackPose->GetModelSpaceTransform(linkedJoint1Index).m_position; // Based on weight, check if position of the test node // And its linked nodes are pointing towards the unreachable position @@ -272,12 +272,12 @@ namespace EMotionFX TEST_P(BlendTreeTwoLinkIKNodeFixture, RotatedPositionsOutputCorrectPose) { - m_twoLinkIKNode->AddConnection(m_paramNode, m_paramNode->FindOutputPortByName("WeightParam")->mPortID, + m_twoLinkIKNode->AddConnection(m_paramNode, m_paramNode->FindOutputPortByName("WeightParam")->m_portId, BlendTreeTwoLinkIKNode::INPUTPORT_WEIGHT); m_twoLinkIKNode->AddConnection(m_paramNode, - m_paramNode->FindOutputPortByName("GoalPosParam")->mPortID, BlendTreeTwoLinkIKNode::INPUTPORT_GOALPOS); + m_paramNode->FindOutputPortByName("GoalPosParam")->m_portId, BlendTreeTwoLinkIKNode::INPUTPORT_GOALPOS); m_twoLinkIKNode->AddConnection(m_paramNode, - m_paramNode->FindOutputPortByName("RotationParam")->mPortID, BlendTreeTwoLinkIKNode::INPUTPORT_GOALROT); + m_paramNode->FindOutputPortByName("RotationParam")->m_portId, BlendTreeTwoLinkIKNode::INPUTPORT_GOALROT); m_twoLinkIKNode->SetRotationEnabled(true); GetEMotionFX().Update(1.0f / 60.0f); @@ -288,10 +288,10 @@ namespace EMotionFX const Pose* jackPose = m_actorInstance->GetTransformData()->GetCurrentPose(); size_t testJointIndex; - m_jackSkeleton->FindNodeAndIndexByName(m_param.testJointName, testJointIndex); - const AZ::Quaternion testJointRotation = jackPose->GetModelSpaceTransform(testJointIndex).mRotation; + m_jackSkeleton->FindNodeAndIndexByName(m_param.m_testJointName, testJointIndex); + const AZ::Quaternion testJointRotation = jackPose->GetModelSpaceTransform(testJointIndex).m_rotation; - for (std::vector rotateXYZ : m_param.rotations) + for (std::vector rotateXYZ : m_param.m_rotations) { const float rotateX = rotateXYZ[0]; const float rotateY = rotateXYZ[1]; @@ -299,7 +299,7 @@ namespace EMotionFX ParamSetValue("RotationParam", AZ::Quaternion(rotateX, rotateY, rotateZ, 1.0f)); GetEMotionFX().Update(1.0f / 60.0f); - const AZ::Quaternion testJointNewRotation = jackPose->GetModelSpaceTransform(testJointIndex).mRotation; + const AZ::Quaternion testJointNewRotation = jackPose->GetModelSpaceTransform(testJointIndex).m_rotation; if (weight) { @@ -315,20 +315,20 @@ namespace EMotionFX TEST_P(BlendTreeTwoLinkIKNodeFixture, BendDirectionOutputCorrectPose) { - m_twoLinkIKNode->AddConnection(m_paramNode, m_paramNode->FindOutputPortByName("WeightParam")->mPortID, + m_twoLinkIKNode->AddConnection(m_paramNode, m_paramNode->FindOutputPortByName("WeightParam")->m_portId, BlendTreeTwoLinkIKNode::INPUTPORT_WEIGHT); m_twoLinkIKNode->AddConnection(m_paramNode, - m_paramNode->FindOutputPortByName("GoalPosParam")->mPortID, BlendTreeTwoLinkIKNode::INPUTPORT_GOALPOS); + m_paramNode->FindOutputPortByName("GoalPosParam")->m_portId, BlendTreeTwoLinkIKNode::INPUTPORT_GOALPOS); m_twoLinkIKNode->AddConnection(m_paramNode, - m_paramNode->FindOutputPortByName("BendDirParam")->mPortID, BlendTreeTwoLinkIKNode::INPUTPORT_BENDDIR); + m_paramNode->FindOutputPortByName("BendDirParam")->m_portId, BlendTreeTwoLinkIKNode::INPUTPORT_BENDDIR); m_twoLinkIKNode->SetRelativeBendDir(true); GetEMotionFX().Update(1.0f / 60.0f); // Set up Jack's arm to specific position for testing const float weight = testing::get<0>(GetParam()); - const float x = m_param.bendDirPosition[0]; - const float y = m_param.bendDirPosition[1]; - const float z = m_param.bendDirPosition[2]; + const float x = m_param.m_bendDirPosition[0]; + const float y = m_param.m_bendDirPosition[1]; + const float z = m_param.m_bendDirPosition[2]; ParamSetValue("WeightParam", weight); ParamSetValue("GoalPosParam", AZ::Vector3(x, y, z)); GetEMotionFX().Update(1.0f / 60.0f); @@ -336,28 +336,28 @@ namespace EMotionFX Pose* jackPose = m_actorInstance->GetTransformData()->GetCurrentPose(); size_t testBendJointIndex; size_t testJointIndex; - AZStd::string& bendLoArm = m_param.linkedJointNames[0]; + AZStd::string& bendLoArm = m_param.m_linkedJointNames[0]; m_jackSkeleton->FindNodeAndIndexByName(bendLoArm, testBendJointIndex); - m_jackSkeleton->FindNodeAndIndexByName(m_param.testJointName, testJointIndex); + m_jackSkeleton->FindNodeAndIndexByName(m_param.m_testJointName, testJointIndex); - const AZ::Vector3 testJointBendPos = jackPose->GetModelSpaceTransform(testBendJointIndex).mPosition; + const AZ::Vector3 testJointBendPos = jackPose->GetModelSpaceTransform(testBendJointIndex).m_position; // Bend the test joint to opposite positions and check positions are opposite ParamSetValue("BendDirParam", AZ::Vector3(1.0f, 0.0f, 0.0f)); GetEMotionFX().Update(1.0f / 60.0f); - const AZ::Vector3 testJointBendRightPos = jackPose->GetModelSpaceTransform(testBendJointIndex).mPosition; + const AZ::Vector3 testJointBendRightPos = jackPose->GetModelSpaceTransform(testBendJointIndex).m_position; ParamSetValue("BendDirParam", AZ::Vector3(-1.0f, 0.0f, 0.0f)); GetEMotionFX().Update(1.0f / 60.0f); - const AZ::Vector3 testJointBendLeftPos = jackPose->GetModelSpaceTransform(testBendJointIndex).mPosition; + const AZ::Vector3 testJointBendLeftPos = jackPose->GetModelSpaceTransform(testBendJointIndex).m_position; ParamSetValue("BendDirParam", AZ::Vector3(0.0f, 1.0f, 0.0f)); GetEMotionFX().Update(1.0f / 60.0f); - const AZ::Vector3 testJointBendDownPos = jackPose->GetModelSpaceTransform(testBendJointIndex).mPosition; + const AZ::Vector3 testJointBendDownPos = jackPose->GetModelSpaceTransform(testBendJointIndex).m_position; ParamSetValue("BendDirParam", AZ::Vector3(0.0f, -1.0f, 0.0f)); GetEMotionFX().Update(1.0f / 60.0f); - const AZ::Vector3 testJointBendUpPos = jackPose->GetModelSpaceTransform(testBendJointIndex).mPosition; + const AZ::Vector3 testJointBendUpPos = jackPose->GetModelSpaceTransform(testBendJointIndex).m_position; if (weight) { @@ -382,14 +382,14 @@ namespace EMotionFX TEST_P(BlendTreeTwoLinkIKNodeFixture, CombinedFunctionsOutputCorrectPose) { // Two Link IK Node should not break when using all of its functions at the same time - m_twoLinkIKNode->AddConnection(m_paramNode, m_paramNode->FindOutputPortByName("WeightParam")->mPortID, + m_twoLinkIKNode->AddConnection(m_paramNode, m_paramNode->FindOutputPortByName("WeightParam")->m_portId, BlendTreeTwoLinkIKNode::INPUTPORT_WEIGHT); m_twoLinkIKNode->AddConnection(m_paramNode, - m_paramNode->FindOutputPortByName("GoalPosParam")->mPortID, BlendTreeTwoLinkIKNode::INPUTPORT_GOALPOS); + m_paramNode->FindOutputPortByName("GoalPosParam")->m_portId, BlendTreeTwoLinkIKNode::INPUTPORT_GOALPOS); m_twoLinkIKNode->AddConnection(m_paramNode, - m_paramNode->FindOutputPortByName("RotationParam")->mPortID, BlendTreeTwoLinkIKNode::INPUTPORT_GOALROT); + m_paramNode->FindOutputPortByName("RotationParam")->m_portId, BlendTreeTwoLinkIKNode::INPUTPORT_GOALROT); m_twoLinkIKNode->AddConnection(m_paramNode, - m_paramNode->FindOutputPortByName("BendDirParam")->mPortID, BlendTreeTwoLinkIKNode::INPUTPORT_BENDDIR); + m_paramNode->FindOutputPortByName("BendDirParam")->m_portId, BlendTreeTwoLinkIKNode::INPUTPORT_BENDDIR); m_twoLinkIKNode->SetRotationEnabled(true); m_twoLinkIKNode->SetRelativeBendDir(true); GetEMotionFX().Update(1.0f / 60.0f); @@ -397,48 +397,48 @@ namespace EMotionFX const Pose* jackPose = m_actorInstance->GetTransformData()->GetCurrentPose(); size_t testJointIndex; size_t testBendJointIndex; - AZStd::string& bendLoArm = m_param.linkedJointNames[0]; - m_jackSkeleton->FindNodeAndIndexByName(m_param.testJointName, testJointIndex); + AZStd::string& bendLoArm = m_param.m_linkedJointNames[0]; + m_jackSkeleton->FindNodeAndIndexByName(m_param.m_testJointName, testJointIndex); m_jackSkeleton->FindNodeAndIndexByName(bendLoArm, testBendJointIndex); // Adding weight and goal position const float weight = testing::get<0>(GetParam()); - const float posX = m_param.bendDirPosition[0]; - const float posY = m_param.bendDirPosition[1]; - const float posZ = m_param.bendDirPosition[2]; + const float posX = m_param.m_bendDirPosition[0]; + const float posY = m_param.m_bendDirPosition[1]; + const float posZ = m_param.m_bendDirPosition[2]; ParamSetValue("WeightParam", weight); ParamSetValue("GoalPosParam", AZ::Vector3(posX, posY, posZ)); GetEMotionFX().Update(1.0f / 60.0f); // Add bend direction - const AZ::Vector3 testJointBendPos = jackPose->GetModelSpaceTransform(testBendJointIndex).mPosition; + const AZ::Vector3 testJointBendPos = jackPose->GetModelSpaceTransform(testBendJointIndex).m_position; ParamSetValue("BendDirParam", AZ::Vector3(1.0f, 0.0f, 0.0f)); GetEMotionFX().Update(1.0f / 60.0f); - const AZ::Vector3 testJointBendRightPos = jackPose->GetModelSpaceTransform(testBendJointIndex).mPosition; + const AZ::Vector3 testJointBendRightPos = jackPose->GetModelSpaceTransform(testBendJointIndex).m_position; ParamSetValue("BendDirParam", AZ::Vector3(-1.0f, 0.0f, 0.0f)); GetEMotionFX().Update(1.0f / 60.0f); - const AZ::Vector3 testJointBendLeftPos = jackPose->GetModelSpaceTransform(testBendJointIndex).mPosition; + const AZ::Vector3 testJointBendLeftPos = jackPose->GetModelSpaceTransform(testBendJointIndex).m_position; ParamSetValue("BendDirParam", AZ::Vector3(0.0f, 1.0f, 0.0f)); GetEMotionFX().Update(1.0f / 60.0f); - const AZ::Vector3 testJointBendDownPos = jackPose->GetModelSpaceTransform(testBendJointIndex).mPosition; + const AZ::Vector3 testJointBendDownPos = jackPose->GetModelSpaceTransform(testBendJointIndex).m_position; ParamSetValue("BendDirParam", AZ::Vector3(0.0f, -1.0f, 0.0f)); GetEMotionFX().Update(1.0f / 60.0f); - const AZ::Vector3 testJointBendUpPos = jackPose->GetModelSpaceTransform(testBendJointIndex).mPosition; + const AZ::Vector3 testJointBendUpPos = jackPose->GetModelSpaceTransform(testBendJointIndex).m_position; // Rotations with bent joint - const AZ::Quaternion testJointOriginalRotation = jackPose->GetModelSpaceTransform(testJointIndex).mRotation; - for (std::vector rotateXYZ : m_param.rotations) + const AZ::Quaternion testJointOriginalRotation = jackPose->GetModelSpaceTransform(testJointIndex).m_rotation; + for (std::vector rotateXYZ : m_param.m_rotations) { const float rotateX = rotateXYZ[0]; const float rotateY = rotateXYZ[1]; const float rotateZ = rotateXYZ[2]; ParamSetValue("RotationParam", AZ::Quaternion(rotateX, rotateY, rotateZ, 1.0f)); GetEMotionFX().Update(1.0f / 60.0f); - const AZ::Quaternion testJointNewRotation = jackPose->GetModelSpaceTransform(testJointIndex).mRotation; + const AZ::Quaternion testJointNewRotation = jackPose->GetModelSpaceTransform(testJointIndex).m_rotation; if (weight) { diff --git a/Gems/EMotionFX/Code/Tests/BoolLogicNodeTests.cpp b/Gems/EMotionFX/Code/Tests/BoolLogicNodeTests.cpp index 9d2e1a11c6..6214005a71 100644 --- a/Gems/EMotionFX/Code/Tests/BoolLogicNodeTests.cpp +++ b/Gems/EMotionFX/Code/Tests/BoolLogicNodeTests.cpp @@ -168,15 +168,15 @@ namespace EMotionFX const AZStd::vector& parameterNodeOutputPorts = parameterNode->GetOutputPorts(); for (const EMotionFX::AnimGraphNode::Port& port : parameterNodeOutputPorts) { - uint32 paramIndex = parameterNode->GetParameterIndex(port.mPortID); + uint32 paramIndex = parameterNode->GetParameterIndex(port.m_portId); if (paramIndex == boolXParamIndexOutcome.GetValue()) { - boolXOutputPortIndex = port.mPortID; + boolXOutputPortIndex = port.m_portId; portIndicesFound++; } else if (paramIndex == boolYParamIndexOutcome.GetValue()) { - boolYOutputPortIndex = port.mPortID; + boolYOutputPortIndex = port.m_portId; portIndicesFound++; } } diff --git a/Gems/EMotionFX/Code/Tests/Bugs/CanUndoParameterDeletionAndRestoreBlendTreeConnections.cpp b/Gems/EMotionFX/Code/Tests/Bugs/CanUndoParameterDeletionAndRestoreBlendTreeConnections.cpp index 9da4f0fdb8..88ca19b277 100644 --- a/Gems/EMotionFX/Code/Tests/Bugs/CanUndoParameterDeletionAndRestoreBlendTreeConnections.cpp +++ b/Gems/EMotionFX/Code/Tests/Bugs/CanUndoParameterDeletionAndRestoreBlendTreeConnections.cpp @@ -142,7 +142,7 @@ namespace EMotionFX for (const AnimGraphNode::Port& outputPort : outputPorts) { - ASSERT_TRUE(outputPort.mConnection) << "Expected a valid connection at the output port."; + ASSERT_TRUE(outputPort.m_connection) << "Expected a valid connection at the output port."; } } @@ -173,7 +173,7 @@ namespace EMotionFX for (const AnimGraphNode::Port& outputPort : outputPorts) { - ASSERT_TRUE(outputPort.mConnection) << "Expected a valid connection at the output port."; + ASSERT_TRUE(outputPort.m_connection) << "Expected a valid connection at the output port."; } } } diff --git a/Gems/EMotionFX/Code/Tests/EmotionFXMathLibTests.cpp b/Gems/EMotionFX/Code/Tests/EmotionFXMathLibTests.cpp index 041cc9e862..e4d532928c 100644 --- a/Gems/EMotionFX/Code/Tests/EmotionFXMathLibTests.cpp +++ b/Gems/EMotionFX/Code/Tests/EmotionFXMathLibTests.cpp @@ -22,9 +22,9 @@ protected: void SetUp() override { - m_azNormalizedVector3_a = AZ::Vector3(s_x1, s_y1, s_z1); - m_azNormalizedVector3_a.Normalize(); - m_azQuaternion_a = AZ::Quaternion::CreateFromAxisAngle(m_azNormalizedVector3_a, s_angle_a); + m_azNormalizedVector3A = AZ::Vector3(s_x1, s_y1, s_z1); + m_azNormalizedVector3A.Normalize(); + m_azQuaternionA = AZ::Quaternion::CreateFromAxisAngle(m_azNormalizedVector3A, s_angle_a); } void TearDown() override @@ -117,8 +117,8 @@ protected: static const float s_y1; static const float s_z1; static const float s_angle_a; - AZ::Vector3 m_azNormalizedVector3_a; - AZ::Quaternion m_azQuaternion_a; + AZ::Vector3 m_azNormalizedVector3A; + AZ::Quaternion m_azQuaternionA; }; const float EmotionFXMathLibTests::s_toleranceHigh = 0.00001f; diff --git a/Gems/EMotionFX/Code/Tests/Integration/PoseComparisonFixture.h b/Gems/EMotionFX/Code/Tests/Integration/PoseComparisonFixture.h index 16d9fb2389..d354153f9b 100644 --- a/Gems/EMotionFX/Code/Tests/Integration/PoseComparisonFixture.h +++ b/Gems/EMotionFX/Code/Tests/Integration/PoseComparisonFixture.h @@ -18,12 +18,12 @@ namespace EMotionFX struct PoseComparisonFixtureParams { - const char* actorFile = nullptr; - const char* animGraphFile = nullptr; - const char* motionSetFile = nullptr; - const char* recordingFile = nullptr; + const char* m_actorFile = nullptr; + const char* m_animGraphFile = nullptr; + const char* m_motionSetFile = nullptr; + const char* m_recordingFile = nullptr; PoseComparisonFixtureParams(const char* actorFile, const char* animGraphFile, const char* motionSetFile, const char* recordingFile) - : actorFile(actorFile), animGraphFile(animGraphFile), motionSetFile(motionSetFile), recordingFile(recordingFile) + : m_actorFile(actorFile), m_animGraphFile(animGraphFile), m_motionSetFile(motionSetFile), m_recordingFile(recordingFile) {} }; diff --git a/Gems/EMotionFX/Code/Tests/Integration/PoseComparisonTests.cpp b/Gems/EMotionFX/Code/Tests/Integration/PoseComparisonTests.cpp index d50b72cb4d..cccf744cfc 100644 --- a/Gems/EMotionFX/Code/Tests/Integration/PoseComparisonTests.cpp +++ b/Gems/EMotionFX/Code/Tests/Integration/PoseComparisonTests.cpp @@ -23,7 +23,7 @@ namespace EMotionFX { void PrintTo(const Recorder::ActorInstanceData& actorInstanceData, ::std::ostream* os) { - *os << actorInstanceData.mActorInstance->GetActor()->GetName(); + *os << actorInstanceData.m_actorInstance->GetActor()->GetName(); } template @@ -42,8 +42,8 @@ namespace EMotionFX void PrintTo(const Recorder::TransformTracks& tracks, ::std::ostream* os) { - PrintTo(tracks.mPositions, os); - PrintTo(tracks.mRotations, os); + PrintTo(tracks.m_positions, os); + PrintTo(tracks.m_rotations, os); } AZ_PUSH_DISABLE_WARNING(4100, "-Wmissing-declarations") // 'result_listener': unreferenced formal parameter @@ -178,15 +178,15 @@ namespace EMotionFX void INTEG_PoseComparisonFixture::LoadAssets() { - const AZStd::string actorPath = ResolvePath(GetParam().actorFile); + const AZStd::string actorPath = ResolvePath(GetParam().m_actorFile); m_actor = EMotionFX::GetImporter().LoadActor(actorPath); ASSERT_TRUE(m_actor) << "Failed to load actor"; - const AZStd::string animGraphPath = ResolvePath(GetParam().animGraphFile); + const AZStd::string animGraphPath = ResolvePath(GetParam().m_animGraphFile); m_animGraph = EMotionFX::GetImporter().LoadAnimGraph(animGraphPath); ASSERT_TRUE(m_animGraph) << "Failed to load anim graph"; - const AZStd::string motionSetPath = ResolvePath(GetParam().motionSetFile); + const AZStd::string motionSetPath = ResolvePath(GetParam().m_motionSetFile); m_motionSet = EMotionFX::GetImporter().LoadMotionSet(motionSetPath); ASSERT_TRUE(m_motionSet) << "Failed to load motion set"; m_motionSet->Preload(); @@ -197,7 +197,7 @@ namespace EMotionFX TEST_P(INTEG_PoseComparisonFixture, Integ_TestPoses) { - const AZStd::string recordingPath = ResolvePath(GetParam().recordingFile); + const AZStd::string recordingPath = ResolvePath(GetParam().m_recordingFile); Recorder* recording = EMotionFX::Recorder::LoadFromFile(recordingPath.c_str()); const EMotionFX::Recorder::ActorInstanceData& expectedActorInstanceData = recording->GetActorInstanceData(0); @@ -222,10 +222,10 @@ namespace EMotionFX { const Recorder::TransformTracks& gotTrack = gotTracks[trackNum]; const Recorder::TransformTracks& expectedTrack = expectedTracks[trackNum]; - const char* nodeName = gotActorInstanceData.mActorInstance->GetActor()->GetSkeleton()->GetNode(trackNum)->GetName(); + const char* nodeName = gotActorInstanceData.m_actorInstance->GetActor()->GetSkeleton()->GetNode(trackNum)->GetName(); - EXPECT_THAT(gotTrack.mPositions, MatchesKeyTrack(expectedTrack.mPositions, nodeName)); - EXPECT_THAT(gotTrack.mRotations, MatchesKeyTrack(expectedTrack.mRotations, nodeName)); + EXPECT_THAT(gotTrack.m_positions, MatchesKeyTrack(expectedTrack.m_positions, nodeName)); + EXPECT_THAT(gotTrack.m_rotations, MatchesKeyTrack(expectedTrack.m_rotations, nodeName)); } recording->Destroy(); @@ -235,14 +235,14 @@ namespace EMotionFX { // Make one recording, 10 seconds at 60 fps Recorder::RecordSettings settings; - settings.mFPS = 1000000; - settings.mRecordTransforms = true; - settings.mRecordAnimGraphStates = false; - settings.mRecordNodeHistory = false; - settings.mRecordScale = false; - settings.mInitialAnimGraphAnimBytes = 4 * 1024 * 1024; // 4 mb - settings.mHistoryStatesOnly = false; - settings.mRecordEvents = false; + settings.m_fps = 1000000; + settings.m_recordTransforms = true; + settings.m_recordAnimGraphStates = false; + settings.m_recordNodeHistory = false; + settings.m_recordScale = false; + settings.m_initialAnimGraphAnimBytes = 4 * 1024 * 1024; // 4 mb + settings.m_historyStatesOnly = false; + settings.m_recordEvents = false; EMotionFX::GetRecorder().StartRecording(settings); @@ -285,10 +285,10 @@ namespace EMotionFX { const Recorder::TransformTracks& gotTrack = gotTracks[trackNum]; const Recorder::TransformTracks& expectedTrack = expectedTracks[trackNum]; - const char* nodeName = gotActorInstanceData.mActorInstance->GetActor()->GetSkeleton()->GetNode(trackNum)->GetName(); + const char* nodeName = gotActorInstanceData.m_actorInstance->GetActor()->GetSkeleton()->GetNode(trackNum)->GetName(); - EXPECT_THAT(gotTrack.mPositions, MatchesKeyTrack(expectedTrack.mPositions, nodeName)); - EXPECT_THAT(gotTrack.mRotations, MatchesKeyTrack(expectedTrack.mRotations, nodeName)); + EXPECT_THAT(gotTrack.m_positions, MatchesKeyTrack(expectedTrack.m_positions, nodeName)); + EXPECT_THAT(gotTrack.m_rotations, MatchesKeyTrack(expectedTrack.m_rotations, nodeName)); } recording->Destroy(); diff --git a/Gems/EMotionFX/Code/Tests/Matchers.h b/Gems/EMotionFX/Code/Tests/Matchers.h index ad3c204f72..9f7b9017ba 100644 --- a/Gems/EMotionFX/Code/Tests/Matchers.h +++ b/Gems/EMotionFX/Code/Tests/Matchers.h @@ -81,12 +81,12 @@ template<> inline bool IsCloseMatcherP::gmock_Impl::MatchAndExplain(const EMotionFX::Transform& arg, ::testing::MatchResultListener* result_listener) const { #ifndef EMFX_SCALE_DISABLED - return ::testing::ExplainMatchResult(IsClose(expected.mPosition), arg.mPosition, result_listener) - && ::testing::ExplainMatchResult(IsClose(expected.mRotation), arg.mRotation, result_listener) - && ::testing::ExplainMatchResult(IsClose(expected.mScale), arg.mScale, result_listener); + return ::testing::ExplainMatchResult(IsClose(expected.m_position), arg.m_position, result_listener) + && ::testing::ExplainMatchResult(IsClose(expected.m_rotation), arg.m_rotation, result_listener) + && ::testing::ExplainMatchResult(IsClose(expected.m_scale), arg.m_scale, result_listener); #else - return ::testing::ExplainMatchResult(IsClose(expected.mPosition), arg.mPosition, result_listener) - && ::testing::ExplainMatchResult(IsClose(expected.mRotation), arg.mRotation, result_listener); + return ::testing::ExplainMatchResult(IsClose(expected.m_position), arg.m_position, result_listener) + && ::testing::ExplainMatchResult(IsClose(expected.m_rotation), arg.m_rotation, result_listener); #endif } @@ -96,20 +96,20 @@ inline bool IsCloseMatcherP::gmock_Impl::Ma { using ::testing::FloatEq; using ::testing::ExplainMatchResult; - return ExplainMatchResult(FloatEq(expected.m16[0]), arg.m16[0], result_listener) - && ExplainMatchResult(FloatEq(expected.m16[1]), arg.m16[1], result_listener) - && ExplainMatchResult(FloatEq(expected.m16[2]), arg.m16[2], result_listener) - && ExplainMatchResult(FloatEq(expected.m16[3]), arg.m16[3], result_listener) - && ExplainMatchResult(FloatEq(expected.m16[4]), arg.m16[4], result_listener) - && ExplainMatchResult(FloatEq(expected.m16[5]), arg.m16[5], result_listener) - && ExplainMatchResult(FloatEq(expected.m16[6]), arg.m16[6], result_listener) - && ExplainMatchResult(FloatEq(expected.m16[7]), arg.m16[7], result_listener) - && ExplainMatchResult(FloatEq(expected.m16[8]), arg.m16[8], result_listener) - && ExplainMatchResult(FloatEq(expected.m16[9]), arg.m16[9], result_listener) - && ExplainMatchResult(FloatEq(expected.m16[10]), arg.m16[10], result_listener) - && ExplainMatchResult(FloatEq(expected.m16[11]), arg.m16[11], result_listener) - && ExplainMatchResult(FloatEq(expected.m16[12]), arg.m16[12], result_listener) - && ExplainMatchResult(FloatEq(expected.m16[13]), arg.m16[13], result_listener) - && ExplainMatchResult(FloatEq(expected.m16[14]), arg.m16[14], result_listener) - && ExplainMatchResult(FloatEq(expected.m16[15]), arg.m16[15], result_listener); + return ExplainMatchResult(FloatEq(expected.m_m16[0]), arg.m_m16[0], result_listener) + && ExplainMatchResult(FloatEq(expected.m_m16[1]), arg.m_m16[1], result_listener) + && ExplainMatchResult(FloatEq(expected.m_m16[2]), arg.m_m16[2], result_listener) + && ExplainMatchResult(FloatEq(expected.m_m16[3]), arg.m_m16[3], result_listener) + && ExplainMatchResult(FloatEq(expected.m_m16[4]), arg.m_m16[4], result_listener) + && ExplainMatchResult(FloatEq(expected.m_m16[5]), arg.m_m16[5], result_listener) + && ExplainMatchResult(FloatEq(expected.m_m16[6]), arg.m_m16[6], result_listener) + && ExplainMatchResult(FloatEq(expected.m_m16[7]), arg.m_m16[7], result_listener) + && ExplainMatchResult(FloatEq(expected.m_m16[8]), arg.m_m16[8], result_listener) + && ExplainMatchResult(FloatEq(expected.m_m16[9]), arg.m_m16[9], result_listener) + && ExplainMatchResult(FloatEq(expected.m_m16[10]), arg.m_m16[10], result_listener) + && ExplainMatchResult(FloatEq(expected.m_m16[11]), arg.m_m16[11], result_listener) + && ExplainMatchResult(FloatEq(expected.m_m16[12]), arg.m_m16[12], result_listener) + && ExplainMatchResult(FloatEq(expected.m_m16[13]), arg.m_m16[13], result_listener) + && ExplainMatchResult(FloatEq(expected.m_m16[14]), arg.m_m16[14], result_listener) + && ExplainMatchResult(FloatEq(expected.m_m16[15]), arg.m_m16[15], result_listener); } diff --git a/Gems/EMotionFX/Code/Tests/MorphTargetRuntimeTests.cpp b/Gems/EMotionFX/Code/Tests/MorphTargetRuntimeTests.cpp index 10f735ca24..02c17702a2 100644 --- a/Gems/EMotionFX/Code/Tests/MorphTargetRuntimeTests.cpp +++ b/Gems/EMotionFX/Code/Tests/MorphTargetRuntimeTests.cpp @@ -82,7 +82,7 @@ namespace EMotionFX m_morphSetup->AddMorphTarget(morphTarget); // Without this call, the bind pose does not know about newly added - // morph target (mMorphWeights.GetLength() == 0) + // morph target (m_morphWeights.size() == 0) m_actor->ResizeTransformData(); m_actor->PostCreateInit(/*makeGeomLodsCompatibleWithSkeletalLODs=*/false, /*convertUnitType=*/false); diff --git a/Gems/EMotionFX/Code/Tests/MotionEventTrackTests.cpp b/Gems/EMotionFX/Code/Tests/MotionEventTrackTests.cpp index a857efb2ca..30ab36e35a 100644 --- a/Gems/EMotionFX/Code/Tests/MotionEventTrackTests.cpp +++ b/Gems/EMotionFX/Code/Tests/MotionEventTrackTests.cpp @@ -27,11 +27,11 @@ namespace EMotionFX { struct ExtractEventsParams { - void (*eventFactory)(MotionEventTrack* track); - float startTime; - float endTime; - EPlayMode playMode; - std::vector expectedEvents; + void (*m_eventFactory)(MotionEventTrack* track); + float m_startTime; + float m_endTime; + EPlayMode m_playMode; + std::vector m_expectedEvents; }; void PrintTo(const EMotionFX::EventInfo::EventState& state, ::std::ostream* os) @@ -52,7 +52,7 @@ namespace EMotionFX void PrintTo(const EMotionFX::EventInfo& event, ::std::ostream* os) { - *os << "Time: " << event.mTimeValue + *os << "Time: " << event.m_timeValue << " State: " ; PrintTo(event.m_eventState, os); @@ -60,23 +60,23 @@ namespace EMotionFX void PrintTo(const ExtractEventsParams& object, ::std::ostream* os) { - if (object.eventFactory == &MakeNoEvents) + if (object.m_eventFactory == &MakeNoEvents) { *os << "Events: 0"; } - else if (object.eventFactory == &MakeOneEvent) + else if (object.m_eventFactory == &MakeOneEvent) { *os << "Events: 1"; } - else if (object.eventFactory == &MakeTwoEvents) + else if (object.m_eventFactory == &MakeTwoEvents) { *os << "Events: 2"; } - else if (object.eventFactory == &MakeThreeEvents) + else if (object.m_eventFactory == &MakeThreeEvents) { *os << "Events: 3"; } - else if (object.eventFactory == &MakeThreeRangedEvents) + else if (object.m_eventFactory == &MakeThreeRangedEvents) { *os << "Events: 3 (ranged)"; } @@ -84,15 +84,15 @@ namespace EMotionFX { *os << "Events: Unknown"; } - *os << " Start time: " << object.startTime - << " End time: " << object.endTime - << " Play mode: " << ((object.playMode == EPlayMode::PLAYMODE_FORWARD) ? "Forward" : "Backward") + *os << " Start time: " << object.m_startTime + << " End time: " << object.m_endTime + << " Play mode: " << ((object.m_playMode == EPlayMode::PLAYMODE_FORWARD) ? "Forward" : "Backward") << " Expected events: [" ; - for (const auto& entry : object.expectedEvents) + for (const auto& entry : object.m_expectedEvents) { PrintTo(entry, os); - if (&entry != &(*(object.expectedEvents.end() - 1))) + if (&entry != &(*(object.m_expectedEvents.end() - 1))) { *os << ", "; } @@ -148,7 +148,7 @@ namespace EMotionFX m_motion->GetEventTable()->AutoCreateSyncTrack(m_motion); m_track = m_motion->GetEventTable()->GetSyncTrack(); - GetParam().eventFactory(m_track); + GetParam().m_eventFactory(m_track); m_actor = ActorFactory::CreateAndInit(5); @@ -178,11 +178,11 @@ namespace EMotionFX const ExtractEventsParams& params = GetParam(); // Call the function being tested - func(params.startTime, params.endTime, params.playMode, m_motionInstance); + func(params.m_startTime, params.m_endTime, params.m_playMode, m_motionInstance); // ProcessEvents filters out the ACTIVE events, remove those from our expected results AZStd::vector expectedEvents; - for (const EventInfo& event : params.expectedEvents) + for (const EventInfo& event : params.m_expectedEvents) { if (event.m_eventState != EventInfo::ACTIVE || m_shouldContainActiveEvents) { @@ -195,7 +195,7 @@ namespace EMotionFX { const EventInfo& gotEvent = m_buffer->GetEvent(i); const EventInfo& expectedEvent = expectedEvents[i]; - EXPECT_EQ(gotEvent.mTimeValue, expectedEvent.mTimeValue); + EXPECT_EQ(gotEvent.m_timeValue, expectedEvent.m_timeValue); EXPECT_EQ(gotEvent.m_eventState, expectedEvent.m_eventState); } } diff --git a/Gems/EMotionFX/Code/Tests/MotionExtractionBusTests.cpp b/Gems/EMotionFX/Code/Tests/MotionExtractionBusTests.cpp index 5c823c153f..d8b8a2a430 100644 --- a/Gems/EMotionFX/Code/Tests/MotionExtractionBusTests.cpp +++ b/Gems/EMotionFX/Code/Tests/MotionExtractionBusTests.cpp @@ -137,7 +137,7 @@ namespace EMotionFX AZ::Transform currentTransform = AZ::Transform::CreateIdentity(); AZ::TransformBus::EventResult(currentTransform, m_entityId, &AZ::TransformBus::Events::GetWorldTM); - const AZ::Vector3 actorInstancePosition = actorInstance->GetWorldSpaceTransform().mPosition; + const AZ::Vector3 actorInstancePosition = actorInstance->GetWorldSpaceTransform().m_position; const AZ::Vector3 positionDelta = actorInstancePosition - currentTransform.GetTranslation(); EXPECT_CALL(testBus, ExtractMotion(testing::_, testing::_)); diff --git a/Gems/EMotionFX/Code/Tests/MotionExtractionTests.cpp b/Gems/EMotionFX/Code/Tests/MotionExtractionTests.cpp index 85c0e4201f..35f1b96cce 100644 --- a/Gems/EMotionFX/Code/Tests/MotionExtractionTests.cpp +++ b/Gems/EMotionFX/Code/Tests/MotionExtractionTests.cpp @@ -36,8 +36,8 @@ namespace EMotionFX { struct MotionExtractionTestsData { - std::vector durationMultipliers; - std::vector numOfLoops; + std::vector m_durationMultipliers; + std::vector m_numOfLoops; }; std::vector motionExtractionTestData @@ -59,8 +59,8 @@ namespace EMotionFX m_actorInstance->SetMotionExtractionEnabled(true); m_actor->AutoSetMotionExtractionNode(); - rootNode = m_jackSkeleton->FindNodeAndIndexByName("jack_root", m_jack_rootIndex); - hipNode = m_jackSkeleton->FindNodeAndIndexByName("Bip01__pelvis", m_jack_hipIndex); + m_rootNode = m_jackSkeleton->FindNodeAndIndexByName("jack_root", m_jackRootIndex); + m_hipNode = m_jackSkeleton->FindNodeAndIndexByName("Bip01__pelvis", m_jackHipIndex); m_jackPose = m_actorInstance->GetTransformData()->GetCurrentPose(); AddMotionEntry(TestMotionAssets::GetJackWalkForward(), "jack_walk_forward_aim_zup"); @@ -119,13 +119,13 @@ namespace EMotionFX } protected: - size_t m_jack_rootIndex = InvalidIndex; - size_t m_jack_hipIndex = InvalidIndex; + size_t m_jackRootIndex = InvalidIndex; + size_t m_jackHipIndex = InvalidIndex; AnimGraphMotionNode* m_motionNode = nullptr; BlendTree* m_blendTree = nullptr; Motion* m_motion = nullptr; - Node* rootNode = nullptr; - Node* hipNode = nullptr; + Node* m_rootNode = nullptr; + Node* m_hipNode = nullptr; Pose* m_jackPose = nullptr; Skeleton* m_jackSkeleton = nullptr; }; @@ -227,7 +227,7 @@ namespace EMotionFX // Make sure we also really end where we expect. // Motion extraction will introduce some small inaccuracies, so we can't use AZ::g_fltEps here, but need a slightly larger value in our AZ::IsClose(). - const float yPos = m_actorInstance->GetWorldSpaceTransform().mPosition.GetY(); + const float yPos = m_actorInstance->GetWorldSpaceTransform().m_position.GetY(); EXPECT_TRUE(AZ::IsClose(yPos, expectedY, 0.01f)); } #endif @@ -243,16 +243,16 @@ namespace EMotionFX // The expected delta used is the distance of the jack walk forward motion will move in 1 complete duration const float expectedDelta = ExtractLastFramePos().GetY(); - for (size_t paramIndex = 0; paramIndex < m_param.durationMultipliers.size(); paramIndex++) + for (size_t paramIndex = 0; paramIndex < m_param.m_durationMultipliers.size(); paramIndex++) { // Test motion extraction under different durations/time deltas - const float motionDuration = 1.066f * m_param.durationMultipliers[paramIndex]; - const float originalPositionY = m_actorInstance->GetWorldSpaceTransform().mPosition.GetY(); - for (AZ::u32 i = 0; i < m_param.numOfLoops[paramIndex]; i++) + const float motionDuration = 1.066f * m_param.m_durationMultipliers[paramIndex]; + const float originalPositionY = m_actorInstance->GetWorldSpaceTransform().m_position.GetY(); + for (AZ::u32 i = 0; i < m_param.m_numOfLoops[paramIndex]; i++) { GetEMotionFX().Update(motionDuration); } - const float updatedPositionY = m_actorInstance->GetWorldSpaceTransform().mPosition.GetY(); + const float updatedPositionY = m_actorInstance->GetWorldSpaceTransform().m_position.GetY(); const float actualDeltaY = AZ::GetAbs(updatedPositionY - originalPositionY); EXPECT_TRUE(AZ::GetAbs(actualDeltaY - expectedDelta) < 0.002f) << "The absolute difference between actual delta and expected delta of Y-axis should be less than 0.002f."; @@ -262,15 +262,15 @@ namespace EMotionFX const AZ::Quaternion actorRotation(0.0f, 0.0f, -1.0f, 1.0f); m_actorInstance->SetLocalSpaceRotation(actorRotation.GetNormalized()); GetEMotionFX().Update(0.0f); - for (size_t paramIndex = 0; paramIndex < m_param.durationMultipliers.size(); paramIndex++) + for (size_t paramIndex = 0; paramIndex < m_param.m_durationMultipliers.size(); paramIndex++) { - const float motionDuration = 1.066f * m_param.durationMultipliers[paramIndex]; - const float originalPositionX = m_actorInstance->GetWorldSpaceTransform().mPosition.GetX(); - for (AZ::u32 i = 0; i < m_param.numOfLoops[paramIndex]; i++) + const float motionDuration = 1.066f * m_param.m_durationMultipliers[paramIndex]; + const float originalPositionX = m_actorInstance->GetWorldSpaceTransform().m_position.GetX(); + for (AZ::u32 i = 0; i < m_param.m_numOfLoops[paramIndex]; i++) { GetEMotionFX().Update(motionDuration); } - const float updatedPositionX = m_actorInstance->GetWorldSpaceTransform().mPosition.GetX(); + const float updatedPositionX = m_actorInstance->GetWorldSpaceTransform().m_position.GetX(); const float actualDeltaX = AZ::GetAbs(updatedPositionX - originalPositionX); EXPECT_TRUE(AZ::GetAbs(actualDeltaX - expectedDelta) < 0.002f) << "The absolute difference between actual delta and expected delta of X-axis should be less than 0.002f."; @@ -290,17 +290,17 @@ namespace EMotionFX const AZ::Quaternion diagonalRotation = m_reverse ? AZ::Quaternion(0.0f, 0.0f, 0.5f, 1.0f) : AZ::Quaternion(0.0f, 0.0f, -0.5f, 1.0f); m_actorInstance->SetLocalSpaceRotation(diagonalRotation.GetNormalized()); GetEMotionFX().Update(0.0f); - for (size_t paramIndex = 0; paramIndex < m_param.durationMultipliers.size(); paramIndex++) + for (size_t paramIndex = 0; paramIndex < m_param.m_durationMultipliers.size(); paramIndex++) { - const float originalPositionX = m_actorInstance->GetWorldSpaceTransform().mPosition.GetX(); - const float originalPositionY = m_actorInstance->GetWorldSpaceTransform().mPosition.GetY(); - const float motionDuration = 1.066f * m_param.durationMultipliers[paramIndex]; - for (AZ::u32 i = 0; i < m_param.numOfLoops[paramIndex]; i++) + const float originalPositionX = m_actorInstance->GetWorldSpaceTransform().m_position.GetX(); + const float originalPositionY = m_actorInstance->GetWorldSpaceTransform().m_position.GetY(); + const float motionDuration = 1.066f * m_param.m_durationMultipliers[paramIndex]; + for (AZ::u32 i = 0; i < m_param.m_numOfLoops[paramIndex]; i++) { GetEMotionFX().Update(motionDuration); } - const float updatedPositionX = m_actorInstance->GetWorldSpaceTransform().mPosition.GetX(); - const float updatedPositionY = m_actorInstance->GetWorldSpaceTransform().mPosition.GetY(); + const float updatedPositionX = m_actorInstance->GetWorldSpaceTransform().m_position.GetX(); + const float updatedPositionY = m_actorInstance->GetWorldSpaceTransform().m_position.GetY(); const float actualDeltaX = AZ::GetAbs(updatedPositionX - originalPositionX); const float actualDeltaY = AZ::GetAbs(updatedPositionY - originalPositionY); EXPECT_NEAR(actualDeltaX, expectedDeltaX, 0.001f) @@ -327,14 +327,14 @@ namespace EMotionFX // This is because the presync time value of the second motion node is from the unsynced playback. // When we improve our syncing system we can handle this differently and we won't expect a zero trajectory delta anymore. GetEMotionFX().Update(0.15f); - EXPECT_FLOAT_EQ(m_actorInstance->GetTrajectoryDeltaTransform().mPosition.GetLength(), 0.0f); + EXPECT_FLOAT_EQ(m_actorInstance->GetTrajectoryDeltaTransform().m_position.GetLength(), 0.0f); EXPECT_FLOAT_EQ(m_motionNode1->GetCurrentPlayTime(m_animGraphInstance), m_motionNode2->GetCurrentPlayTime(m_animGraphInstance)); EXPECT_EQ(m_animGraphInstance->GetEventBuffer().GetNumEvents(), 0); // The second frame should be as normal. GetEMotionFX().Update(0.15f); - EXPECT_GT(m_actorInstance->GetTrajectoryDeltaTransform().mPosition.GetLength(), 0.0f); - EXPECT_LE(m_actorInstance->GetTrajectoryDeltaTransform().mPosition.GetLength(), 0.3f); + EXPECT_GT(m_actorInstance->GetTrajectoryDeltaTransform().m_position.GetLength(), 0.0f); + EXPECT_LE(m_actorInstance->GetTrajectoryDeltaTransform().m_position.GetLength(), 0.3f); EXPECT_FLOAT_EQ(m_motionNode1->GetCurrentPlayTime(m_animGraphInstance), m_motionNode2->GetCurrentPlayTime(m_animGraphInstance)); EXPECT_EQ(m_animGraphInstance->GetEventBuffer().GetNumEvents(), 0); } diff --git a/Gems/EMotionFX/Code/Tests/MotionLayerSystemTests.cpp b/Gems/EMotionFX/Code/Tests/MotionLayerSystemTests.cpp index dd3661a366..de0c37f5b2 100644 --- a/Gems/EMotionFX/Code/Tests/MotionLayerSystemTests.cpp +++ b/Gems/EMotionFX/Code/Tests/MotionLayerSystemTests.cpp @@ -35,11 +35,11 @@ namespace EMotionFX MotionSystem* motionSystem = actorInstance->GetMotionSystem(); PlayBackInfo playBackInfo; - playBackInfo.mBlendInTime = 1.0f; - playBackInfo.mBlendOutTime = 1.0f; - playBackInfo.mNumLoops = 1; - playBackInfo.mPlayNow = false; - playBackInfo.mFreezeAtLastFrame = false; + playBackInfo.m_blendInTime = 1.0f; + playBackInfo.m_blendOutTime = 1.0f; + playBackInfo.m_numLoops = 1; + playBackInfo.m_playNow = false; + playBackInfo.m_freezeAtLastFrame = false; // Add 2 motions to the queue const MotionInstance* motionInstance1 = motionSystem->PlayMotion(motion1, &playBackInfo); @@ -106,10 +106,10 @@ namespace EMotionFX MotionSystem* motionSystem = actorInstance->GetMotionSystem(); PlayBackInfo playBackInfo; - playBackInfo.mBlendInTime = 1.0f; - playBackInfo.mBlendOutTime = 1.0f; - playBackInfo.mNumLoops = EMFX_LOOPFOREVER; - playBackInfo.mPlayNow = true; + playBackInfo.m_blendInTime = 1.0f; + playBackInfo.m_blendOutTime = 1.0f; + playBackInfo.m_numLoops = EMFX_LOOPFOREVER; + playBackInfo.m_playNow = true; const MotionInstance* walkInstance = motionSystem->PlayMotion(walk, &playBackInfo); @@ -163,11 +163,11 @@ namespace EMotionFX MotionSystem* motionSystem = actorInstance->GetMotionSystem(); PlayBackInfo playBackInfo; - playBackInfo.mBlendInTime = 1.0f; - playBackInfo.mBlendOutTime = 1.0f; - playBackInfo.mNumLoops = 1; - playBackInfo.mPlayNow = false; - playBackInfo.mFreezeAtLastFrame = false; + playBackInfo.m_blendInTime = 1.0f; + playBackInfo.m_blendOutTime = 1.0f; + playBackInfo.m_numLoops = 1; + playBackInfo.m_playNow = false; + playBackInfo.m_freezeAtLastFrame = false; // Add 2 motions to the queue const MotionInstance* motionInstance1 = motionSystem->PlayMotion(motion1, &playBackInfo); diff --git a/Gems/EMotionFX/Code/Tests/MultiThreadSchedulerTests.cpp b/Gems/EMotionFX/Code/Tests/MultiThreadSchedulerTests.cpp index f3d6d44e1d..180da46746 100644 --- a/Gems/EMotionFX/Code/Tests/MultiThreadSchedulerTests.cpp +++ b/Gems/EMotionFX/Code/Tests/MultiThreadSchedulerTests.cpp @@ -31,14 +31,14 @@ namespace EMotionFX // Create an actor instance and make sure it is in the scheduler. ActorInstance* actorInstance = ActorInstance::Create(actor.get()); EXPECT_EQ(scheduler->GetNumScheduleSteps(), 1) << "The actor instance should be part of the scheduler."; - EXPECT_EQ(scheduler->GetScheduleStep(0).mActorInstances.size(), 1) << "The step should hold exactly one actor instance."; - EXPECT_EQ(scheduler->GetScheduleStep(0).mActorInstances[0], actorInstance) << "The actor instance should be part of the step."; + EXPECT_EQ(scheduler->GetScheduleStep(0).m_actorInstances.size(), 1) << "The step should hold exactly one actor instance."; + EXPECT_EQ(scheduler->GetScheduleStep(0).m_actorInstances[0], actorInstance) << "The actor instance should be part of the step."; // Insert the actor instance manually again and make sure there is no duplicate. scheduler->RecursiveInsertActorInstance(actorInstance); EXPECT_EQ(scheduler->GetNumScheduleSteps(), 1) << "The actor instance should be part of the scheduler."; - EXPECT_EQ(scheduler->GetScheduleStep(0).mActorInstances.size(), 1) << "The step should hold exactly one actor instance."; - EXPECT_EQ(scheduler->GetScheduleStep(0).mActorInstances[0], actorInstance) << "The actor instance should be part of the step."; + EXPECT_EQ(scheduler->GetScheduleStep(0).m_actorInstances.size(), 1) << "The step should hold exactly one actor instance."; + EXPECT_EQ(scheduler->GetScheduleStep(0).m_actorInstances[0], actorInstance) << "The actor instance should be part of the step."; actorInstance->Destroy(); } diff --git a/Gems/EMotionFX/Code/Tests/NonUniformMotionDataTests.cpp b/Gems/EMotionFX/Code/Tests/NonUniformMotionDataTests.cpp index 02256e1e12..09a4e46b84 100644 --- a/Gems/EMotionFX/Code/Tests/NonUniformMotionDataTests.cpp +++ b/Gems/EMotionFX/Code/Tests/NonUniformMotionDataTests.cpp @@ -745,15 +745,15 @@ namespace EMotionFX EXPECT_FALSE(motionData.IsJointAnimated(3)); EXPECT_STREQ(motionData.GetJointName(3).c_str(), "Joint4"); - EXPECT_THAT(motionData.GetJointPoseTransform(3).mPosition, IsClose(poseTransform.mPosition)); - EXPECT_THAT(motionData.GetJointPoseTransform(3).mRotation, IsClose(poseTransform.mRotation)); + EXPECT_THAT(motionData.GetJointPoseTransform(3).m_position, IsClose(poseTransform.m_position)); + EXPECT_THAT(motionData.GetJointPoseTransform(3).m_rotation, IsClose(poseTransform.m_rotation)); #ifndef EMFX_SCALE_DISABLED - EXPECT_THAT(motionData.GetJointPoseTransform(3).mScale, IsClose(poseTransform.mScale)); + EXPECT_THAT(motionData.GetJointPoseTransform(3).m_scale, IsClose(poseTransform.m_scale)); #endif - EXPECT_THAT(motionData.GetJointBindPoseTransform(3).mPosition, IsClose(bindTransform.mPosition)); - EXPECT_THAT(motionData.GetJointBindPoseTransform(3).mRotation, IsClose(bindTransform.mRotation)); + EXPECT_THAT(motionData.GetJointBindPoseTransform(3).m_position, IsClose(bindTransform.m_position)); + EXPECT_THAT(motionData.GetJointBindPoseTransform(3).m_rotation, IsClose(bindTransform.m_rotation)); #ifndef EMFX_SCALE_DISABLED - EXPECT_THAT(motionData.GetJointBindPoseTransform(3).mScale, IsClose(bindTransform.mScale)); + EXPECT_THAT(motionData.GetJointBindPoseTransform(3).m_scale, IsClose(bindTransform.m_scale)); #endif // Test adding a morph. @@ -888,19 +888,19 @@ namespace EMotionFX sampleSettings.m_actorInstance = m_actorInstance; sampleSettings.m_sampleTime = expectation.first; const Transform sampledResult = motionData.SampleJointTransform(sampleSettings, 0); - EXPECT_THAT(sampledResult.mPosition, IsClose(expectation.second.mPosition)); - EXPECT_THAT(sampledResult.mRotation, IsClose(expectation.second.mRotation)); + EXPECT_THAT(sampledResult.m_position, IsClose(expectation.second.m_position)); + EXPECT_THAT(sampledResult.m_rotation, IsClose(expectation.second.m_rotation)); #ifndef EMFX_SCALE_DISABLED - EXPECT_THAT(sampledResult.mScale, IsClose(expectation.second.mScale)); + EXPECT_THAT(sampledResult.m_scale, IsClose(expectation.second.m_scale)); #endif // Fourth joint has no motion data to apply to our actor, so expect a bind pose. // It has motion data, but there is no joint in the skeleton that matches its name, so it is like motion data for a joint that doesn't exist in our actor. const Transform fourthJointTransform = motionData.SampleJointTransform(sampleSettings, 3); - EXPECT_THAT(fourthJointTransform.mPosition, IsClose(expectedBindTransform.mPosition)); - EXPECT_THAT(fourthJointTransform.mRotation, IsClose(expectedBindTransform.mRotation)); + EXPECT_THAT(fourthJointTransform.m_position, IsClose(expectedBindTransform.m_position)); + EXPECT_THAT(fourthJointTransform.m_rotation, IsClose(expectedBindTransform.m_rotation)); #ifndef EMFX_SCALE_DISABLED - EXPECT_THAT(fourthJointTransform.mScale, IsClose(expectedBindTransform.mScale)); + EXPECT_THAT(fourthJointTransform.m_scale, IsClose(expectedBindTransform.m_scale)); #endif } @@ -917,19 +917,19 @@ namespace EMotionFX // We only verify the first joint, to see if it interpolated fine. const Transform sampledResult = pose.GetLocalSpaceTransform(0); - EXPECT_THAT(sampledResult.mPosition, IsClose(expectation.second.mPosition)); - EXPECT_THAT(sampledResult.mRotation, IsClose(expectation.second.mRotation)); + EXPECT_THAT(sampledResult.m_position, IsClose(expectation.second.m_position)); + EXPECT_THAT(sampledResult.m_rotation, IsClose(expectation.second.m_rotation)); #ifndef EMFX_SCALE_DISABLED - EXPECT_THAT(sampledResult.mScale, IsClose(expectation.second.mScale)); + EXPECT_THAT(sampledResult.m_scale, IsClose(expectation.second.m_scale)); #endif // Fourth joint has no motion data to apply to our actor, so expect a bind pose. // It has motion data, but there is no joint in the skeleton that matches its name, so it is like motion data for a joint that doesn't exist in our actor. const Transform fourthJointTransform = pose.GetLocalSpaceTransform(3); - EXPECT_THAT(fourthJointTransform.mPosition, IsClose(expectedBindTransform.mPosition)); - EXPECT_THAT(fourthJointTransform.mRotation, IsClose(expectedBindTransform.mRotation)); + EXPECT_THAT(fourthJointTransform.m_position, IsClose(expectedBindTransform.m_position)); + EXPECT_THAT(fourthJointTransform.m_rotation, IsClose(expectedBindTransform.m_rotation)); #ifndef EMFX_SCALE_DISABLED - EXPECT_THAT(fourthJointTransform.mScale, IsClose(expectedBindTransform.mScale)); + EXPECT_THAT(fourthJointTransform.m_scale, IsClose(expectedBindTransform.m_scale)); #endif } } diff --git a/Gems/EMotionFX/Code/Tests/PoseTests.cpp b/Gems/EMotionFX/Code/Tests/PoseTests.cpp index 0dd592cda7..ed14da5354 100644 --- a/Gems/EMotionFX/Code/Tests/PoseTests.cpp +++ b/Gems/EMotionFX/Code/Tests/PoseTests.cpp @@ -729,7 +729,7 @@ namespace EMotionFX const Transform transformResult = pose.CalcTrajectoryTransform(); const Transform expectedResult = pose.GetWorldSpaceTransform(motionExtractionJointIndex).ProjectedToGroundPlane(); EXPECT_THAT(transformResult, IsClose(expectedResult)); - EXPECT_EQ(transformResult.mPosition, AZ::Vector3(1.0f, 1.0f, 0.0f)); + EXPECT_EQ(transformResult.m_position, AZ::Vector3(1.0f, 1.0f, 0.0f)); } /////////////////////////////////////////////////////////////////////////// @@ -747,16 +747,16 @@ namespace EMotionFX ASSERT_NE(joint, nullptr) << "Can't find the joint named 'joint4'."; const Transform jointTransform = pose.GetWorldSpaceTransform(jointIndex); - EXPECT_THAT(jointTransform.mScale, IsClose(AZ::Vector3::CreateOne())); + EXPECT_THAT(jointTransform.m_scale, IsClose(AZ::Vector3::CreateOne())); AZ::Vector3 scale(2.0f); m_actorInstance->SetLocalSpaceScale(scale); m_actorInstance->UpdateWorldTransform(); const Transform jointTransform2 = pose.GetWorldSpaceTransform(jointIndex); - EXPECT_THAT(jointTransform2.mScale, IsClose(scale)); + EXPECT_THAT(jointTransform2.m_scale, IsClose(scale)); - const float distToOrigin = jointTransform.mPosition.GetLength(); - const float distToOrigin2= jointTransform2.mPosition.GetLength(); + const float distToOrigin = jointTransform.m_position.GetLength(); + const float distToOrigin2= jointTransform2.m_position.GetLength(); EXPECT_FLOAT_EQ(distToOrigin2 / distToOrigin, 2.0f) << "Expecting the scaled joint to be twice as far from the origin as the unscaled joint."; ) } @@ -786,7 +786,7 @@ namespace EMotionFX AZ::Quaternion::CreateFromAxisAngle(AZ::Vector3(0.0f, 1.0f, 0.0f), floatI)); EMFX_SCALECODE ( - transform.mScale = AZ::Vector3(floatI, floatI, floatI); + transform.m_scale = AZ::Vector3(floatI, floatI, floatI); ) destPose.SetLocalSpaceTransform(i, transform); } @@ -807,7 +807,7 @@ namespace EMotionFX Transform expectedResult = sourceTransform; expectedResult.Blend(destTransform, blendWeight); EXPECT_THAT(transformResult, IsClose(expectedResult)); - CheckIfRotationIsNormalized(destTransform.mRotation); + CheckIfRotationIsNormalized(destTransform.m_rotation); } } @@ -827,7 +827,7 @@ namespace EMotionFX AZ::Quaternion::CreateFromAxisAngle(AZ::Vector3(0.0f, 1.0f, 0.0f), floatI)); EMFX_SCALECODE ( - transform.mScale = AZ::Vector3(floatI, floatI, floatI); + transform.m_scale = AZ::Vector3(floatI, floatI, floatI); ) sourcePose.SetLocalSpaceTransform(i, transform); @@ -844,7 +844,7 @@ namespace EMotionFX AZ::Quaternion::CreateFromAxisAngle(AZ::Vector3(1.0f, 0.0f, 0.0f), floatI)); EMFX_SCALECODE ( - transform.mScale = AZ::Vector3(floatI, floatI, floatI); + transform.m_scale = AZ::Vector3(floatI, floatI, floatI); ) destPose.SetLocalSpaceTransform(i, transform); @@ -866,7 +866,7 @@ namespace EMotionFX Transform expectedResult = sourceTransform; expectedResult.BlendAdditive(destTransform, bindPoseTransform, blendWeight); EXPECT_THAT(transformResult, IsClose(expectedResult)); - CheckIfRotationIsNormalized(destTransform.mRotation); + CheckIfRotationIsNormalized(destTransform.m_rotation); } } @@ -1030,7 +1030,7 @@ namespace EMotionFX { const Transform& transformRel = poseRel.GetLocalSpaceTransform(i); - const AZ::Vector3& result = transformRel.mPosition; + const AZ::Vector3& result = transformRel.m_position; EXPECT_TRUE(result.IsClose(AZ::Vector3::CreateOne())); } } @@ -1142,22 +1142,22 @@ namespace EMotionFX Transform expectedResult = Transform::CreateIdentity(); if (additiveFunction == MakeAdditive) { - expectedResult.mPosition = transformA.mPosition - transformB.mPosition; - expectedResult.mRotation = transformB.mRotation.GetConjugate() * transformA.mRotation; + expectedResult.m_position = transformA.m_position - transformB.m_position; + expectedResult.m_rotation = transformB.m_rotation.GetConjugate() * transformA.m_rotation; EMFX_SCALECODE ( - expectedResult.mScale = transformA.mScale * transformB.mScale; + expectedResult.m_scale = transformA.m_scale * transformB.m_scale; ) } else if (additiveFunction == ApplyAdditive || weight > 1.0f - MCore::Math::epsilon) { - expectedResult.mPosition = transformA.mPosition + transformB.mPosition; - expectedResult.mRotation = transformA.mRotation * transformB.mRotation; - expectedResult.mRotation.Normalize(); + expectedResult.m_position = transformA.m_position + transformB.m_position; + expectedResult.m_rotation = transformA.m_rotation * transformB.m_rotation; + expectedResult.m_rotation.Normalize(); EMFX_SCALECODE ( - expectedResult.mScale = transformA.mScale * transformB.mScale; + expectedResult.m_scale = transformA.m_scale * transformB.m_scale; ) } else if (weight < MCore::Math::epsilon ) @@ -1166,13 +1166,13 @@ namespace EMotionFX } else { - expectedResult.mPosition = transformA.mPosition + transformB.mPosition * weight; - expectedResult.mRotation = transformA.mRotation.NLerp(transformB.mRotation * transformA.mRotation, weight); - expectedResult.mRotation.Normalize(); + expectedResult.m_position = transformA.m_position + transformB.m_position * weight; + expectedResult.m_rotation = transformA.m_rotation.NLerp(transformB.m_rotation * transformA.m_rotation, weight); + expectedResult.m_rotation.Normalize(); EMFX_SCALECODE ( - expectedResult.mScale = transformA.mScale * AZ::Vector3::CreateOne().Lerp(transformB.mScale, weight); + expectedResult.m_scale = transformA.m_scale * AZ::Vector3::CreateOne().Lerp(transformB.m_scale, weight); ) } @@ -1257,7 +1257,7 @@ namespace EMotionFX for (size_t i = 0; i < m_actor->GetSkeleton()->GetNumNodes(); ++i) { - CheckIfRotationIsNormalized(pose.GetLocalSpaceTransform(i).mRotation); + CheckIfRotationIsNormalized(pose.GetLocalSpaceTransform(i).m_rotation); } } diff --git a/Gems/EMotionFX/Code/Tests/Printers.cpp b/Gems/EMotionFX/Code/Tests/Printers.cpp index ebf5167508..eb909a7aca 100644 --- a/Gems/EMotionFX/Code/Tests/Printers.cpp +++ b/Gems/EMotionFX/Code/Tests/Printers.cpp @@ -39,12 +39,12 @@ namespace EMotionFX void PrintTo(const Transform& transform, ::std::ostream* os) { *os << "(pos: "; - PrintTo(transform.mPosition, os); + PrintTo(transform.m_position, os); *os << ", rot: "; - PrintTo(transform.mRotation, os); + PrintTo(transform.m_rotation, os); #if !defined(EMFX_SCALE_DISABLED) *os << ", scale: "; - PrintTo(transform.mScale, os); + PrintTo(transform.m_scale, os); #endif *os << ")"; } diff --git a/Gems/EMotionFX/Code/Tests/RandomMotionSelectionTests.cpp b/Gems/EMotionFX/Code/Tests/RandomMotionSelectionTests.cpp index 3a0b7f4959..556166e240 100644 --- a/Gems/EMotionFX/Code/Tests/RandomMotionSelectionTests.cpp +++ b/Gems/EMotionFX/Code/Tests/RandomMotionSelectionTests.cpp @@ -73,14 +73,14 @@ namespace EMotionFX for (int i = 0; i < iterationCount; ++i) { m_motionNode->PickNewActiveMotion(m_animGraphInstance, nodeUniqueData); - auto mapIterator = m_selectedMotionCount->find(nodeUniqueData->mActiveMotionIndex); + auto mapIterator = m_selectedMotionCount->find(nodeUniqueData->m_activeMotionIndex); if (mapIterator != m_selectedMotionCount->end()) { mapIterator->second++; } else { - m_selectedMotionCount->emplace(nodeUniqueData->mActiveMotionIndex, 1); + m_selectedMotionCount->emplace(nodeUniqueData->m_activeMotionIndex, 1); } } diff --git a/Gems/EMotionFX/Code/Tests/SimulatedObjectSetupTests.cpp b/Gems/EMotionFX/Code/Tests/SimulatedObjectSetupTests.cpp index c8bb4fe6df..f37f571982 100644 --- a/Gems/EMotionFX/Code/Tests/SimulatedObjectSetupTests.cpp +++ b/Gems/EMotionFX/Code/Tests/SimulatedObjectSetupTests.cpp @@ -156,8 +156,8 @@ namespace SimulatedObjectSetupTests struct AddSimulatedJointAndChildrenParams { - AZ::u32 jointIndex; - size_t expectedSimulatedJointCount; + AZ::u32 m_jointIndex; + size_t m_expectedSimulatedJointCount; }; class AddSimulatedJointAndChildrenFixture @@ -177,8 +177,8 @@ namespace SimulatedObjectSetupTests SimulatedObjectSetup setup(&actor); SimulatedObject* object = setup.AddSimulatedObject(); - object->AddSimulatedJointAndChildren(GetParam().jointIndex); - EXPECT_EQ(object->GetSimulatedJoints().size(), GetParam().expectedSimulatedJointCount); + object->AddSimulatedJointAndChildren(GetParam().m_jointIndex); + EXPECT_EQ(object->GetSimulatedJoints().size(), GetParam().m_expectedSimulatedJointCount); } INSTANTIATE_TEST_CASE_P(Test, AddSimulatedJointAndChildrenFixture, diff --git a/Gems/EMotionFX/Code/Tests/SyncingSystemTests.cpp b/Gems/EMotionFX/Code/Tests/SyncingSystemTests.cpp index 985b2eb6c1..a4a89da3ba 100644 --- a/Gems/EMotionFX/Code/Tests/SyncingSystemTests.cpp +++ b/Gems/EMotionFX/Code/Tests/SyncingSystemTests.cpp @@ -24,17 +24,17 @@ namespace EMotionFX { struct SyncParam { - void (*eventFactoryA)(MotionEventTrack* track) = MakeNoEvents; - void (*eventFactoryB)(MotionEventTrack* track) = MakeNoEvents; + void (*m_eventFactoryA)(MotionEventTrack* track) = MakeNoEvents; + void (*m_eventFactoryB)(MotionEventTrack* track) = MakeNoEvents; // 2.0 seconds of simulation, 0.1 increments, 21 playtimes - AZStd::array expectedPlayTimeA {}; - AZStd::array expectedPlayTimeB {}; + AZStd::array m_expectedPlayTimeA {}; + AZStd::array m_expectedPlayTimeB {}; // Expected play times will be calculated based on motion event and duration from AnimGraphNode::SyncUsingSyncTracks(). - AnimGraphObject::ESyncMode syncMode = AnimGraphObject::ESyncMode::SYNCMODE_DISABLED; - float weightParam = 0.0f; - bool reverseMotion = false; + AnimGraphObject::ESyncMode m_syncMode = AnimGraphObject::ESyncMode::SYNCMODE_DISABLED; + float m_weightParam = 0.0f; + bool m_reverseMotion = false; }; class SyncingSystemFixture @@ -45,7 +45,7 @@ namespace EMotionFX void ConstructGraph() override { const SyncParam param = GetParam(); - m_syncMode = param.syncMode; + m_syncMode = param.m_syncMode; AnimGraphFixture::ConstructGraph(); m_blendTreeAnimGraph = AnimGraphFactory::Create(); m_rootStateMachine = m_blendTreeAnimGraph->GetRootStateMachine(); @@ -143,16 +143,16 @@ namespace EMotionFX TEST_P(SyncingSystemFixture, SyncingSystemPlaySpeedTests) { const SyncParam param = GetParam(); - param.eventFactoryA(m_syncTrackA); - param.eventFactoryB(m_syncTrackB); + param.m_eventFactoryA(m_syncTrackA); + param.m_eventFactoryB(m_syncTrackB); GetEMotionFX().Update(0.0f); MCore::AttributeFloat* weightParam = m_animGraphInstance->GetParameterValueChecked(0); - weightParam->SetValue(param.weightParam); + weightParam->SetValue(param.m_weightParam); // Test reverse motion - m_motionNodeA->SetReverse(param.reverseMotion); - m_motionNodeB->SetReverse(param.reverseMotion); + m_motionNodeA->SetReverse(param.m_reverseMotion); + m_motionNodeB->SetReverse(param.m_reverseMotion); uint32 playTimeIndex = 0; const float tolerance = 0.00001f; Simulate(2.0f/*simulationTime*/, 10.0f/*expectedFps*/, 0.0f/*fpsVariance*/, @@ -180,7 +180,7 @@ namespace EMotionFX float factorB; float interpolatedSpeedA; AZStd::tie(interpolatedSpeedA, factorA, factorB) = AnimGraphNode::SyncPlaySpeeds( - motionPlaySpeedA, durationA, motionPlaySpeedB, durationB, param.weightParam); + motionPlaySpeedA, durationA, motionPlaySpeedB, durationB, param.m_weightParam); EXPECT_FLOAT_EQ(statePlaySpeedA, interpolatedSpeedA * factorA) << "Motion playspeeds should match the set playspeed in the motion node throughout blending."; } else if(m_blend2Node->GetSyncMode() == AnimGraphObject::SYNCMODE_TRACKBASED) @@ -188,8 +188,8 @@ namespace EMotionFX const float motionPlayTimeA = m_motionNodeA->GetCurrentPlayTime(animGraphInstance); const float motionPlayTimeB = m_motionNodeB->GetCurrentPlayTime(animGraphInstance); - EXPECT_NEAR(motionPlayTimeA, param.expectedPlayTimeA[playTimeIndex], tolerance) << "Motion node A playtime should match the expected playtime."; - EXPECT_NEAR(motionPlayTimeB, param.expectedPlayTimeB[playTimeIndex], tolerance) << "Motion node B playtime should match the expected playtime."; + EXPECT_NEAR(motionPlayTimeA, param.m_expectedPlayTimeA[playTimeIndex], tolerance) << "Motion node A playtime should match the expected playtime."; + EXPECT_NEAR(motionPlayTimeB, param.m_expectedPlayTimeB[playTimeIndex], tolerance) << "Motion node B playtime should match the expected playtime."; playTimeIndex++; } } diff --git a/Gems/EMotionFX/Code/Tests/TestAssetCode/SimpleActors.cpp b/Gems/EMotionFX/Code/Tests/TestAssetCode/SimpleActors.cpp index 45e9ad8649..3e1dac41c2 100644 --- a/Gems/EMotionFX/Code/Tests/TestAssetCode/SimpleActors.cpp +++ b/Gems/EMotionFX/Code/Tests/TestAssetCode/SimpleActors.cpp @@ -31,7 +31,7 @@ namespace EMotionFX AddNode(i, ("joint" + AZStd::to_string(i)).c_str(), i - 1); Transform transform = Transform::CreateIdentity(); - transform.mPosition = AZ::Vector3(static_cast(i), 0.0f, 0.0f); + transform.m_position = AZ::Vector3(static_cast(i), 0.0f, 0.0f); GetBindPose()->SetLocalSpaceTransform(i, transform); } } @@ -44,7 +44,7 @@ namespace EMotionFX AddNode(i, ("rootJoint" + AZStd::to_string(i)).c_str()); Transform transform = Transform::CreateIdentity(); - transform.mPosition = AZ::Vector3(static_cast(i), 0.0f, 0.0f); + transform.m_position = AZ::Vector3(static_cast(i), 0.0f, 0.0f); GetBindPose()->SetLocalSpaceTransform(i, transform); } } @@ -87,7 +87,7 @@ namespace EMotionFX AddNode(i, ("joint" + AZStd::to_string(i)).c_str(), i - 1); Transform transform = Transform::CreateIdentity(); - transform.mPosition = AZ::Vector3(static_cast(i), 0.0f, 0.0f); + transform.m_position = AZ::Vector3(static_cast(i), 0.0f, 0.0f); GetBindPose()->SetLocalSpaceTransform(i, transform); } } diff --git a/Gems/EMotionFX/Code/Tests/TransformUnitTests.cpp b/Gems/EMotionFX/Code/Tests/TransformUnitTests.cpp index 89cbddfb4d..b5f98bc5e8 100644 --- a/Gems/EMotionFX/Code/Tests/TransformUnitTests.cpp +++ b/Gems/EMotionFX/Code/Tests/TransformUnitTests.cpp @@ -52,33 +52,33 @@ namespace EMotionFX TEST(TransformFixture, CreateIdentity) { const Transform transform = Transform::CreateIdentity(); - EXPECT_TRUE(transform.mPosition.IsZero()); - EXPECT_EQ(transform.mRotation, AZ::Quaternion::CreateIdentity()); + EXPECT_TRUE(transform.m_position.IsZero()); + EXPECT_EQ(transform.m_rotation, AZ::Quaternion::CreateIdentity()); EMFX_SCALECODE ( - EXPECT_EQ(transform.mScale, AZ::Vector3::CreateOne()); + EXPECT_EQ(transform.m_scale, AZ::Vector3::CreateOne()); ) } TEST(TransformFixture, CreateIdentityWithZeroScale) { const Transform transform = Transform::CreateIdentityWithZeroScale(); - EXPECT_TRUE(transform.mPosition.IsZero()); - EXPECT_EQ(transform.mRotation, AZ::Quaternion::CreateIdentity()); + EXPECT_TRUE(transform.m_position.IsZero()); + EXPECT_EQ(transform.m_rotation, AZ::Quaternion::CreateIdentity()); EMFX_SCALECODE ( - EXPECT_EQ(transform.mScale, AZ::Vector3::CreateZero()); + EXPECT_EQ(transform.m_scale, AZ::Vector3::CreateZero()); ) } TEST(TransformFixture, CreateZero) { const Transform transform = Transform::CreateZero(); - EXPECT_TRUE(transform.mPosition.IsZero()); - EXPECT_EQ(transform.mRotation, AZ::Quaternion::CreateZero()); + EXPECT_TRUE(transform.m_position.IsZero()); + EXPECT_EQ(transform.m_rotation, AZ::Quaternion::CreateZero()); EMFX_SCALECODE ( - EXPECT_EQ(transform.mScale, AZ::Vector3::CreateZero()); + EXPECT_EQ(transform.m_scale, AZ::Vector3::CreateZero()); ) } @@ -86,11 +86,11 @@ namespace EMotionFX TEST(TransformFixture, ConstructFromVec3Quat) { const Transform transform(AZ::Vector3(6.0f, 7.0f, 8.0f), AZ::Quaternion::CreateRotationX(AZ::Constants::HalfPi)); - EXPECT_EQ(transform.mPosition, AZ::Vector3(6.0f, 7.0f, 8.0f)); - EXPECT_THAT(transform.mRotation, IsClose(AZ::Quaternion(sqrt2over2, 0.0f, 0.0f, sqrt2over2))); + EXPECT_EQ(transform.m_position, AZ::Vector3(6.0f, 7.0f, 8.0f)); + EXPECT_THAT(transform.m_rotation, IsClose(AZ::Quaternion(sqrt2over2, 0.0f, 0.0f, sqrt2over2))); EMFX_SCALECODE ( - EXPECT_EQ(transform.mScale, AZ::Vector3::CreateOne()); + EXPECT_EQ(transform.m_scale, AZ::Vector3::CreateOne()); ) } @@ -148,11 +148,11 @@ namespace EMotionFX TEST_P(TransformConstructFromVec3QuatVec3Fixture, ConstructFromVec3QuatVec3) { const Transform transform(ExpectedPosition(), ExpectedRotation(), ExpectedScale()); - EXPECT_THAT(transform.mPosition, IsClose(ExpectedPosition())); - EXPECT_THAT(transform.mRotation, IsClose(ExpectedRotation())); + EXPECT_THAT(transform.m_position, IsClose(ExpectedPosition())); + EXPECT_THAT(transform.m_rotation, IsClose(ExpectedRotation())); EMFX_SCALECODE ( - EXPECT_THAT(transform.mScale, IsClose(ExpectedScale())); + EXPECT_THAT(transform.m_scale, IsClose(ExpectedScale())); ) } @@ -160,11 +160,11 @@ namespace EMotionFX { Transform transform(AZ::Vector3(5.0f, 6.0f, 7.0f), AZ::Quaternion(0.1f, 0.2f, 0.3f, 0.4f), AZ::Vector3(8.0f, 9.0f, 10.0f)); transform.Set(ExpectedPosition(), ExpectedRotation(), ExpectedScale()); - EXPECT_THAT(transform.mPosition, IsClose(ExpectedPosition())); - EXPECT_THAT(transform.mRotation, IsClose(ExpectedRotation())); + EXPECT_THAT(transform.m_position, IsClose(ExpectedPosition())); + EXPECT_THAT(transform.m_rotation, IsClose(ExpectedRotation())); EMFX_SCALECODE ( - EXPECT_THAT(transform.mScale, IsClose(ExpectedScale())); + EXPECT_THAT(transform.m_scale, IsClose(ExpectedScale())); ) } @@ -191,11 +191,11 @@ namespace EMotionFX { Transform transform(AZ::Vector3(5.0f, 6.0f, 7.0f), AZ::Quaternion(0.1f, 0.2f, 0.3f, 0.4f), AZ::Vector3(8.0f, 9.0f, 10.0f)); transform.Set(AZ::Vector3(1.0f, 2.0f, 3.0f), AZ::Quaternion::CreateRotationX(AZ::Constants::QuarterPi)); - EXPECT_EQ(transform.mPosition, AZ::Vector3(1.0f, 2.0f, 3.0f)); - EXPECT_THAT(transform.mRotation, IsClose(AZ::Quaternion::CreateRotationX(AZ::Constants::QuarterPi))); + EXPECT_EQ(transform.m_position, AZ::Vector3(1.0f, 2.0f, 3.0f)); + EXPECT_THAT(transform.m_rotation, IsClose(AZ::Quaternion::CreateRotationX(AZ::Constants::QuarterPi))); EMFX_SCALECODE ( - EXPECT_EQ(transform.mScale, AZ::Vector3::CreateOne()); + EXPECT_EQ(transform.m_scale, AZ::Vector3::CreateOne()); ) } @@ -203,11 +203,11 @@ namespace EMotionFX { Transform transform(AZ::Vector3(1.0f, 2.0f, 3.0f), AZ::Quaternion(0.1f, 0.2f, 0.3f, 0.4f), AZ::Vector3(4.0f, 5.0f, 6.0f)); transform.Identity(); - EXPECT_EQ(transform.mPosition, AZ::Vector3::CreateZero()); - EXPECT_EQ(transform.mRotation, AZ::Quaternion::CreateIdentity()); + EXPECT_EQ(transform.m_position, AZ::Vector3::CreateZero()); + EXPECT_EQ(transform.m_rotation, AZ::Quaternion::CreateIdentity()); EMFX_SCALECODE ( - EXPECT_EQ(transform.mScale, AZ::Vector3::CreateOne()); + EXPECT_EQ(transform.m_scale, AZ::Vector3::CreateOne()); ) } @@ -215,11 +215,11 @@ namespace EMotionFX { Transform transform(AZ::Vector3(1.0f, 2.0f, 3.0f), AZ::Quaternion(0.1f, 0.2f, 0.3f, 0.4f), AZ::Vector3(4.0f, 5.0f, 6.0f)); transform.Zero(); - EXPECT_EQ(transform.mPosition, AZ::Vector3::CreateZero()); - EXPECT_EQ(transform.mRotation, AZ::Quaternion::CreateZero()); + EXPECT_EQ(transform.m_position, AZ::Vector3::CreateZero()); + EXPECT_EQ(transform.m_rotation, AZ::Quaternion::CreateZero()); EMFX_SCALECODE ( - EXPECT_EQ(transform.mScale, AZ::Vector3::CreateZero()); + EXPECT_EQ(transform.m_scale, AZ::Vector3::CreateZero()); ) } @@ -227,11 +227,11 @@ namespace EMotionFX { Transform transform(AZ::Vector3(1.0f, 2.0f, 3.0f), AZ::Quaternion(0.1f, 0.2f, 0.3f, 0.4f), AZ::Vector3(4.0f, 5.0f, 6.0f)); transform.IdentityWithZeroScale(); - EXPECT_EQ(transform.mPosition, AZ::Vector3::CreateZero()); - EXPECT_EQ(transform.mRotation, AZ::Quaternion::CreateIdentity()); + EXPECT_EQ(transform.m_position, AZ::Vector3::CreateZero()); + EXPECT_EQ(transform.m_rotation, AZ::Quaternion::CreateIdentity()); EMFX_SCALECODE ( - EXPECT_EQ(transform.mScale, AZ::Vector3::CreateZero()); + EXPECT_EQ(transform.m_scale, AZ::Vector3::CreateZero()); ) } @@ -662,54 +662,54 @@ namespace EMotionFX struct ApplyDeltaParams { - const Transform initial; - const Transform a; - const Transform b; - const Transform expected; - const float weight; + const Transform m_initial; + const Transform m_a; + const Transform m_b; + const Transform m_expected; + const float m_weight; }; using TransformApplyDeltaFixture = ::testing::TestWithParam; TEST_P(TransformApplyDeltaFixture, ApplyDelta) { - if (GetParam().weight != 1.0f) + if (GetParam().m_weight != 1.0f) { return; } - Transform transform = GetParam().initial; - transform.ApplyDelta(GetParam().a, GetParam().b); + Transform transform = GetParam().m_initial; + transform.ApplyDelta(GetParam().m_a, GetParam().m_b); EXPECT_THAT( transform, - IsClose(GetParam().expected) + IsClose(GetParam().m_expected) ); } TEST_P(TransformApplyDeltaFixture, ApplyDeltaMirrored) { - if (GetParam().weight != 1.0f) + if (GetParam().m_weight != 1.0f) { return; } const AZ::Vector3 mirrorAxis = AZ::Vector3::CreateAxisX(); - Transform transform = GetParam().initial; - transform.ApplyDeltaMirrored(GetParam().a, GetParam().b, mirrorAxis); + Transform transform = GetParam().m_initial; + transform.ApplyDeltaMirrored(GetParam().m_a, GetParam().m_b, mirrorAxis); EXPECT_THAT( transform, - IsClose(GetParam().expected.Mirrored(mirrorAxis)) + IsClose(GetParam().m_expected.Mirrored(mirrorAxis)) ); } TEST_P(TransformApplyDeltaFixture, ApplyDeltaWithWeight) { - Transform transform = GetParam().initial; - transform.ApplyDeltaWithWeight(GetParam().a, GetParam().b, GetParam().weight); + Transform transform = GetParam().m_initial; + transform.ApplyDeltaWithWeight(GetParam().m_a, GetParam().m_b, GetParam().m_weight); EXPECT_THAT( transform, - IsClose(GetParam().expected) + IsClose(GetParam().m_expected) ); } @@ -774,7 +774,7 @@ namespace EMotionFX AZ::Quaternion(2.0f, 0.0f, 0.0f, 2.0f), AZ::Vector3::CreateOne() ).Normalize(); - EXPECT_FLOAT_EQ(transform.mRotation.GetLength(), 1.0f); + EXPECT_FLOAT_EQ(transform.m_rotation.GetLength(), 1.0f); } TEST(TransformFixture, Normalized) @@ -784,7 +784,7 @@ namespace EMotionFX AZ::Quaternion(2.0f, 0.0f, 0.0f, 2.0f), AZ::Vector3::CreateOne() ).Normalized(); - EXPECT_FLOAT_EQ(transform.mRotation.GetLength(), 1.0f); + EXPECT_FLOAT_EQ(transform.m_rotation.GetLength(), 1.0f); } TEST(TransformFixture, BlendAdditive) @@ -808,39 +808,39 @@ namespace EMotionFX : public ::testing::Test { protected: - const AZ::Vector3 translationA{5.0f, 6.0f, 7.0f}; - const AZ::Quaternion rotationA = AZ::Quaternion::CreateFromAxisAngle(AZ::Vector3::CreateAxisX(), AZ::Constants::QuarterPi); - const AZ::Vector3 scaleA = AZ::Vector3::CreateOne(); + const AZ::Vector3 m_translationA{5.0f, 6.0f, 7.0f}; + const AZ::Quaternion m_rotationA = AZ::Quaternion::CreateFromAxisAngle(AZ::Vector3::CreateAxisX(), AZ::Constants::QuarterPi); + const AZ::Vector3 m_scaleA = AZ::Vector3::CreateOne(); - const AZ::Vector3 translationB{11.0f, 12.0f, 13.0f}; - const AZ::Quaternion rotationB = AZ::Quaternion::CreateFromAxisAngle(AZ::Vector3::CreateAxisX(), AZ::Constants::HalfPi); - const AZ::Vector3 scaleB{3.0f, 4.0f, 5.0f}; + const AZ::Vector3 m_translationB{11.0f, 12.0f, 13.0f}; + const AZ::Quaternion m_rotationB = AZ::Quaternion::CreateFromAxisAngle(AZ::Vector3::CreateAxisX(), AZ::Constants::HalfPi); + const AZ::Vector3 m_scaleB{3.0f, 4.0f, 5.0f}; }; TEST_F(TwoTransformsFixture, Blend) { - const Transform transformA(translationA, rotationA, scaleA); - const Transform transformB(translationB, rotationB, scaleB); + const Transform transformA(m_translationA, m_rotationA, m_scaleA); + const Transform transformB(m_translationB, m_rotationB, m_scaleB); EXPECT_THAT( - Transform(translationA, rotationA, scaleA).Blend(transformB, 0.0f), + Transform(m_translationA, m_rotationA, m_scaleA).Blend(transformB, 0.0f), IsClose(transformA) ); EXPECT_THAT( - Transform(translationA, rotationA, scaleA).Blend(transformB, 0.25f), + Transform(m_translationA, m_rotationA, m_scaleA).Blend(transformB, 0.25f), IsClose(Transform(AZ::Vector3(6.5f, 7.5f, 8.5f), AZ::Quaternion::CreateFromAxisAngle(AZ::Vector3::CreateAxisX(), AZ::Constants::Pi * 5.0f / 16.0f), AZ::Vector3(1.5f, 1.75f, 2.0f))) ); EXPECT_THAT( - Transform(translationA, rotationA, scaleA).Blend(transformB, 0.5f), + Transform(m_translationA, m_rotationA, m_scaleA).Blend(transformB, 0.5f), IsClose(Transform(AZ::Vector3(8.0f, 9.0f, 10.0f), AZ::Quaternion::CreateFromAxisAngle(AZ::Vector3::CreateAxisX(), AZ::Constants::Pi * 3.0f / 8.0f), AZ::Vector3(2.0f, 2.5f, 3.0f))) ); EXPECT_THAT( - Transform(translationA, rotationA, scaleA).Blend(transformB, 0.75f), + Transform(m_translationA, m_rotationA, m_scaleA).Blend(transformB, 0.75f), IsClose(Transform(AZ::Vector3(9.5f, 10.5f, 11.5f), AZ::Quaternion::CreateFromAxisAngle(AZ::Vector3::CreateAxisX(), AZ::Constants::Pi * 7.0f / 16.0f), AZ::Vector3(2.5f, 3.25f, 4.0f))) ); EXPECT_THAT( - Transform(translationA, rotationA, scaleA).Blend(transformB, 1.0f), + Transform(m_translationA, m_rotationA, m_scaleA).Blend(transformB, 1.0f), IsClose(transformB) ); } @@ -848,8 +848,8 @@ namespace EMotionFX TEST_F(TwoTransformsFixture, ApplyAdditiveTransform) { EXPECT_THAT( - Transform(translationA, rotationA, scaleA).ApplyAdditive(Transform(translationB, rotationB, scaleB)), - IsClose(Transform(translationA + translationB, rotationA * rotationB, scaleA * scaleB)) + Transform(m_translationA, m_rotationA, m_scaleA).ApplyAdditive(Transform(m_translationB, m_rotationB, m_scaleB)), + IsClose(Transform(m_translationA + m_translationB, m_rotationA * m_rotationB, m_scaleA * m_scaleB)) ); } @@ -857,16 +857,16 @@ namespace EMotionFX { const float factor = 0.5f; EXPECT_THAT( - Transform(translationA, rotationA, scaleA).ApplyAdditive(Transform(translationB, rotationB, scaleB), factor), - IsClose(Transform(translationA + translationB * factor, rotationA.NLerp(rotationA * rotationB, factor), scaleA * AZ::Vector3::CreateOne().Lerp(scaleB, factor))) + Transform(m_translationA, m_rotationA, m_scaleA).ApplyAdditive(Transform(m_translationB, m_rotationB, m_scaleB), factor), + IsClose(Transform(m_translationA + m_translationB * factor, m_rotationA.NLerp(m_rotationA * m_rotationB, factor), m_scaleA * AZ::Vector3::CreateOne().Lerp(m_scaleB, factor))) ); } TEST_F(TwoTransformsFixture, AddTransform) { EXPECT_THAT( - Transform(translationA, rotationA, scaleA).Add(Transform(translationB, rotationB, scaleB)), - IsClose(Transform(translationA + translationB, rotationA + rotationB, scaleA + scaleB)) + Transform(m_translationA, m_rotationA, m_scaleA).Add(Transform(m_translationB, m_rotationB, m_scaleB)), + IsClose(Transform(m_translationA + m_translationB, m_rotationA + m_rotationB, m_scaleA + m_scaleB)) ); } @@ -874,16 +874,16 @@ namespace EMotionFX { const float factor = 0.5f; EXPECT_THAT( - Transform(translationA, rotationA, scaleA).Add(Transform(translationB, rotationB, scaleB), factor), - IsClose(Transform(translationA + translationB * factor, rotationA + rotationB * factor, scaleA + scaleB * factor)) + Transform(m_translationA, m_rotationA, m_scaleA).Add(Transform(m_translationB, m_rotationB, m_scaleB), factor), + IsClose(Transform(m_translationA + m_translationB * factor, m_rotationA + m_rotationB * factor, m_scaleA + m_scaleB * factor)) ); } TEST_F(TwoTransformsFixture, Subtract) { EXPECT_THAT( - Transform(translationA, rotationA, scaleA).Subtract(Transform(translationB, rotationB, scaleB)), - IsClose(Transform(translationA - translationB, rotationA - rotationB, scaleA - scaleB)) + Transform(m_translationA, m_rotationA, m_scaleA).Subtract(Transform(m_translationB, m_rotationB, m_scaleB)), + IsClose(Transform(m_translationA - m_translationB, m_rotationA - m_rotationB, m_scaleA - m_scaleB)) ); } diff --git a/Gems/EMotionFX/Code/Tests/UI/CanMorphManyShapes.cpp b/Gems/EMotionFX/Code/Tests/UI/CanMorphManyShapes.cpp index 2ed0407d53..f47ad20d23 100644 --- a/Gems/EMotionFX/Code/Tests/UI/CanMorphManyShapes.cpp +++ b/Gems/EMotionFX/Code/Tests/UI/CanMorphManyShapes.cpp @@ -66,7 +66,7 @@ namespace EMotionFX ); m_morphSetup->AddMorphTarget(morphTarget); - // Without this call, the bind pose does not know about newly added morph target (mMorphWeights.GetLength() == 0) + // Without this call, the bind pose does not know about newly added morph target (m_morphWeights.size() == 0) m_actor->ResizeTransformData(); m_actor->PostCreateInit(/*makeGeomLodsCompatibleWithSkeletalLODs=*/false, /*convertUnitType=*/false); @@ -161,13 +161,13 @@ namespace EMotionFX EXPECT_TRUE(morphTarget) << "Cannot access MorphTarget"; // Switch the morphTarget to manual mode - morphTarget->mManualMode->click(); + morphTarget->m_manualMode->click(); // Set the slider to 0.5f; - morphTarget->mSliderWeight->slider()->setValue(0.5f); + morphTarget->m_sliderWeight->slider()->setValue(0.5f); // Get the instance of the MorphTargetInstance - EMotionFX::MorphSetupInstance::MorphTarget* morphTargetInstance = morphTarget->mMorphTargetInstance; + EMotionFX::MorphSetupInstance::MorphTarget* morphTargetInstance = morphTarget->m_morphTargetInstance; ASSERT_TRUE(morphTargetInstance) << "Cannot get Instance of Morph Target"; EXPECT_EQ(morphTargetInstance->GetWeight(), 0.5f) << "Morph Taget Instance is not set to the correct value"; } diff --git a/Gems/EMotionFX/Code/Tests/UI/ModalPopupHandler.cpp b/Gems/EMotionFX/Code/Tests/UI/ModalPopupHandler.cpp index 4e00a2998c..cecd865515 100644 --- a/Gems/EMotionFX/Code/Tests/UI/ModalPopupHandler.cpp +++ b/Gems/EMotionFX/Code/Tests/UI/ModalPopupHandler.cpp @@ -44,7 +44,7 @@ namespace EMotionFX m_totalTime = 0; m_actionCompletionCallback = completionCallback; - m_MenuActiveCallback = menuCallback; + m_menuActiveCallback = menuCallback; m_timeout = timeout; // Kick a timer off to check whether the menu is open. @@ -84,7 +84,7 @@ namespace EMotionFX } // The menu is now active, inform the calling object. - m_MenuActiveCallback(menu); + m_menuActiveCallback(menu); } void ModalPopupHandler::CheckForPopupWidget() diff --git a/Gems/EMotionFX/Code/Tests/UI/ModalPopupHandler.h b/Gems/EMotionFX/Code/Tests/UI/ModalPopupHandler.h index 2ebe5ed2ce..95b3c2c233 100644 --- a/Gems/EMotionFX/Code/Tests/UI/ModalPopupHandler.h +++ b/Gems/EMotionFX/Code/Tests/UI/ModalPopupHandler.h @@ -162,7 +162,7 @@ namespace EMotionFX void CheckForPopupWidget(); private: - MenuActiveCallback m_MenuActiveCallback = nullptr; + MenuActiveCallback m_menuActiveCallback = nullptr; WidgetActiveCallback m_widgetActiveCallback = nullptr; ActionCompletionCallback m_actionCompletionCallback = nullptr; diff --git a/Gems/EMotionFX/Code/Tests/UniformMotionDataTests.cpp b/Gems/EMotionFX/Code/Tests/UniformMotionDataTests.cpp index 7433a403e1..e82d10097b 100644 --- a/Gems/EMotionFX/Code/Tests/UniformMotionDataTests.cpp +++ b/Gems/EMotionFX/Code/Tests/UniformMotionDataTests.cpp @@ -406,15 +406,15 @@ namespace EMotionFX EXPECT_FALSE(motionData.IsJointAnimated(3)); EXPECT_STREQ(motionData.GetJointName(3).c_str(), "Joint4"); - EXPECT_THAT(motionData.GetJointPoseTransform(3).mPosition, IsClose(poseTransform.mPosition)); - EXPECT_THAT(motionData.GetJointPoseTransform(3).mRotation, IsClose(poseTransform.mRotation)); + EXPECT_THAT(motionData.GetJointPoseTransform(3).m_position, IsClose(poseTransform.m_position)); + EXPECT_THAT(motionData.GetJointPoseTransform(3).m_rotation, IsClose(poseTransform.m_rotation)); #ifndef EMFX_SCALE_DISABLED - EXPECT_THAT(motionData.GetJointPoseTransform(3).mScale, IsClose(poseTransform.mScale)); + EXPECT_THAT(motionData.GetJointPoseTransform(3).m_scale, IsClose(poseTransform.m_scale)); #endif - EXPECT_THAT(motionData.GetJointBindPoseTransform(3).mPosition, IsClose(bindTransform.mPosition)); - EXPECT_THAT(motionData.GetJointBindPoseTransform(3).mRotation, IsClose(bindTransform.mRotation)); + EXPECT_THAT(motionData.GetJointBindPoseTransform(3).m_position, IsClose(bindTransform.m_position)); + EXPECT_THAT(motionData.GetJointBindPoseTransform(3).m_rotation, IsClose(bindTransform.m_rotation)); #ifndef EMFX_SCALE_DISABLED - EXPECT_THAT(motionData.GetJointBindPoseTransform(3).mScale, IsClose(bindTransform.mScale)); + EXPECT_THAT(motionData.GetJointBindPoseTransform(3).m_scale, IsClose(bindTransform.m_scale)); #endif // Test adding a morph. @@ -549,19 +549,19 @@ namespace EMotionFX sampleSettings.m_actorInstance = m_actorInstance; sampleSettings.m_sampleTime = expectation.first; const Transform sampledResult = motionData.SampleJointTransform(sampleSettings, 0); - EXPECT_THAT(sampledResult.mPosition, IsClose(expectation.second.mPosition)); - EXPECT_THAT(sampledResult.mRotation, IsClose(expectation.second.mRotation)); + EXPECT_THAT(sampledResult.m_position, IsClose(expectation.second.m_position)); + EXPECT_THAT(sampledResult.m_rotation, IsClose(expectation.second.m_rotation)); #ifndef EMFX_SCALE_DISABLED - EXPECT_THAT(sampledResult.mScale, IsClose(expectation.second.mScale)); + EXPECT_THAT(sampledResult.m_scale, IsClose(expectation.second.m_scale)); #endif // Fourth joint has no motion data to apply to our actor, so expect a bind pose. // It has motion data, but there is no joint in the skeleton that matches its name, so it is like motion data for a joint that doesn't exist in our actor. const Transform fourthJointTransform = motionData.SampleJointTransform(sampleSettings, 3); - EXPECT_THAT(fourthJointTransform.mPosition, IsClose(expectedBindTransform.mPosition)); - EXPECT_THAT(fourthJointTransform.mRotation, IsClose(expectedBindTransform.mRotation)); + EXPECT_THAT(fourthJointTransform.m_position, IsClose(expectedBindTransform.m_position)); + EXPECT_THAT(fourthJointTransform.m_rotation, IsClose(expectedBindTransform.m_rotation)); #ifndef EMFX_SCALE_DISABLED - EXPECT_THAT(fourthJointTransform.mScale, IsClose(expectedBindTransform.mScale)); + EXPECT_THAT(fourthJointTransform.m_scale, IsClose(expectedBindTransform.m_scale)); #endif } @@ -578,19 +578,19 @@ namespace EMotionFX // We only verify the first joint, to see if it interpolated fine. const Transform sampledResult = pose.GetLocalSpaceTransform(0); - EXPECT_THAT(sampledResult.mPosition, IsClose(expectation.second.mPosition)); - EXPECT_THAT(sampledResult.mRotation, IsClose(expectation.second.mRotation)); + EXPECT_THAT(sampledResult.m_position, IsClose(expectation.second.m_position)); + EXPECT_THAT(sampledResult.m_rotation, IsClose(expectation.second.m_rotation)); #ifndef EMFX_SCALE_DISABLED - EXPECT_THAT(sampledResult.mScale, IsClose(expectation.second.mScale)); + EXPECT_THAT(sampledResult.m_scale, IsClose(expectation.second.m_scale)); #endif // Fourth joint has no motion data to apply to our actor, so expect a bind pose. // It has motion data, but there is no joint in the skeleton that matches its name, so it is like motion data for a joint that doesn't exist in our actor. const Transform fourthJointTransform = pose.GetLocalSpaceTransform(3); - EXPECT_THAT(fourthJointTransform.mPosition, IsClose(expectedBindTransform.mPosition)); - EXPECT_THAT(fourthJointTransform.mRotation, IsClose(expectedBindTransform.mRotation)); + EXPECT_THAT(fourthJointTransform.m_position, IsClose(expectedBindTransform.m_position)); + EXPECT_THAT(fourthJointTransform.m_rotation, IsClose(expectedBindTransform.m_rotation)); #ifndef EMFX_SCALE_DISABLED - EXPECT_THAT(fourthJointTransform.mScale, IsClose(expectedBindTransform.mScale)); + EXPECT_THAT(fourthJointTransform.m_scale, IsClose(expectedBindTransform.m_scale)); #endif } } diff --git a/Gems/NvCloth/Code/Source/Components/ClothComponentMesh/ActorClothSkinning.cpp b/Gems/NvCloth/Code/Source/Components/ClothComponentMesh/ActorClothSkinning.cpp index 5359ed6ad5..8baea091a2 100644 --- a/Gems/NvCloth/Code/Source/Components/ClothComponentMesh/ActorClothSkinning.cpp +++ b/Gems/NvCloth/Code/Source/Components/ClothComponentMesh/ActorClothSkinning.cpp @@ -415,7 +415,7 @@ namespace NvCloth const MCore::DualQuaternion& skinningDualQuaternion = m_skinningDualQuaternions.at(jointIndex); - float flip = AZ::GetSign(vertexSkinningTransform.mReal.Dot(skinningDualQuaternion.mReal)); + float flip = AZ::GetSign(vertexSkinningTransform.m_real.Dot(skinningDualQuaternion.m_real)); vertexSkinningTransform += skinningDualQuaternion * jointWeight * flip; } // Normalizing the dual quaternion as the GPU shaders do. This will remove the scale from the transform. From 18709dad7a1afd2469d0cfbafa0ff10197cfb1b6 Mon Sep 17 00:00:00 2001 From: kberg-amzn Date: Mon, 9 Aug 2021 16:44:31 -0700 Subject: [PATCH 236/803] Removing imgui debug module from server target Signed-off-by: kberg-amzn --- Gems/Multiplayer/Code/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/Multiplayer/Code/CMakeLists.txt b/Gems/Multiplayer/Code/CMakeLists.txt index e8b38c8799..96527fbfc4 100644 --- a/Gems/Multiplayer/Code/CMakeLists.txt +++ b/Gems/Multiplayer/Code/CMakeLists.txt @@ -79,7 +79,7 @@ ly_add_target( # The "Multiplayer" target is used by clients and servers, Debug is used only on clients. ly_create_alias(NAME Multiplayer.Clients NAMESPACE Gem TARGETS Gem::Multiplayer Gem::Multiplayer.Debug) -ly_create_alias(NAME Multiplayer.Servers NAMESPACE Gem TARGETS Gem::Multiplayer Gem::Multiplayer.Debug) +ly_create_alias(NAME Multiplayer.Servers NAMESPACE Gem TARGETS Gem::Multiplayer) if (PAL_TRAIT_BUILD_HOST_TOOLS) ly_add_target( From 3bf4caf7d234ed86524e454b2d6c1e4b8462ac70 Mon Sep 17 00:00:00 2001 From: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> Date: Mon, 9 Aug 2021 20:07:04 -0700 Subject: [PATCH 237/803] [redcode/crythread-2nd-pass] removed Cry*CriticalSection functions Signed-off-by: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> --- Code/Legacy/CryCommon/CryThreadImpl.h | 2 +- .../Legacy/CryCommon/CryThreadImpl_pthreads.h | 56 ------------------- Code/Legacy/CryCommon/MultiThread.h | 8 --- Code/Legacy/CryCommon/crycommon_files.cmake | 1 - Code/Legacy/CryCommon/platform_impl.cpp | 53 ------------------ 5 files changed, 1 insertion(+), 119 deletions(-) delete mode 100644 Code/Legacy/CryCommon/CryThreadImpl_pthreads.h diff --git a/Code/Legacy/CryCommon/CryThreadImpl.h b/Code/Legacy/CryCommon/CryThreadImpl.h index 0226b73716..4ff2cc6438 100644 --- a/Code/Legacy/CryCommon/CryThreadImpl.h +++ b/Code/Legacy/CryCommon/CryThreadImpl.h @@ -14,7 +14,7 @@ // Include architecture specific code. #if defined(LINUX) || defined(APPLE) -#include +// noting to include #define AZ_RESTRICTED_SECTION_IMPLEMENTED #elif defined(WIN32) || defined(WIN64) #include diff --git a/Code/Legacy/CryCommon/CryThreadImpl_pthreads.h b/Code/Legacy/CryCommon/CryThreadImpl_pthreads.h deleted file mode 100644 index 38838991a8..0000000000 --- a/Code/Legacy/CryCommon/CryThreadImpl_pthreads.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - -#ifndef CRYINCLUDE_CRYCOMMON_CRYTHREADIMPL_PTHREADS_H -#define CRYINCLUDE_CRYCOMMON_CRYTHREADIMPL_PTHREADS_H -#pragma once - - -#include "CryThread_pthreads.h" - -/////////////////////////////////////////////////////////////////////////////// -// CryCriticalSection implementation -/////////////////////////////////////////////////////////////////////////////// -typedef CryLockT TCritSecType; - -void CryDeleteCriticalSection(void* cs) -{ - delete ((TCritSecType*)cs); -} - -void CryEnterCriticalSection(void* cs) -{ - ((TCritSecType*)cs)->Lock(); -} - -bool CryTryCriticalSection(void* cs) -{ - return false; -} - -void CryLeaveCriticalSection(void* cs) -{ - ((TCritSecType*)cs)->Unlock(); -} - -void CryCreateCriticalSectionInplace(void* pCS) -{ - new (pCS) TCritSecType; -} - -void CryDeleteCriticalSectionInplace(void*) -{ -} - -void* CryCreateCriticalSection() -{ - return (void*) new TCritSecType; -} - -#endif // CRYINCLUDE_CRYCOMMON_CRYTHREADIMPL_PTHREADS_H diff --git a/Code/Legacy/CryCommon/MultiThread.h b/Code/Legacy/CryCommon/MultiThread.h index 2b224c4743..c3aa892d14 100644 --- a/Code/Legacy/CryCommon/MultiThread.h +++ b/Code/Legacy/CryCommon/MultiThread.h @@ -48,14 +48,6 @@ LONG CryInterlockedCompareExchange(LONG volatile* dst, LONG exchange, LONG c void* CryInterlockedCompareExchangePointer(void* volatile* dst, void* exchange, void* comperand); void* CryInterlockedExchangePointer (void* volatile* dst, void* exchange); -void* CryCreateCriticalSection(); -void CryCreateCriticalSectionInplace(void*); -void CryDeleteCriticalSection(void* cs); -void CryDeleteCriticalSectionInplace(void* cs); -void CryEnterCriticalSection(void* cs); -bool CryTryCriticalSection(void* cs); -void CryLeaveCriticalSection(void* cs); - #if defined(AZ_RESTRICTED_PLATFORM) #define AZ_RESTRICTED_SECTION MULTITHREAD_H_SECTION_DEFINE_CRYINTERLOCKEXCHANGE #include AZ_RESTRICTED_FILE(MultiThread_h) diff --git a/Code/Legacy/CryCommon/crycommon_files.cmake b/Code/Legacy/CryCommon/crycommon_files.cmake index b4dac2ec08..487d08b13c 100644 --- a/Code/Legacy/CryCommon/crycommon_files.cmake +++ b/Code/Legacy/CryCommon/crycommon_files.cmake @@ -162,7 +162,6 @@ set(FILES CryLibrary.h CryThread_pthreads.h CryThread_windows.h - CryThreadImpl_pthreads.h CryThreadImpl_windows.h CryWindows.h Linux32Specific.h diff --git a/Code/Legacy/CryCommon/platform_impl.cpp b/Code/Legacy/CryCommon/platform_impl.cpp index a677ba30b6..09d7493ae7 100644 --- a/Code/Legacy/CryCommon/platform_impl.cpp +++ b/Code/Legacy/CryCommon/platform_impl.cpp @@ -364,59 +364,6 @@ void CryInterlockedAdd(volatile size_t* pVal, ptrdiff_t iAdd) assert((iAdd == 0) || (iAdd < 0 && v < v - (size_t)iAdd) || (iAdd > 0 && v > v - (size_t)iAdd)); } -////////////////////////////////////////////////////////////////////////// -void* CryCreateCriticalSection() -{ - CRITICAL_SECTION* pCS = new CRITICAL_SECTION; - InitializeCriticalSection(pCS); - return pCS; -} - -void CryCreateCriticalSectionInplace(void* pCS) -{ - InitializeCriticalSection((CRITICAL_SECTION*)pCS); -} -////////////////////////////////////////////////////////////////////////// -void CryDeleteCriticalSection(void* cs) -{ - CRITICAL_SECTION* pCS = (CRITICAL_SECTION*)cs; - if (pCS->LockCount >= 0) - { - CryFatalError("Critical Section hanging lock"); - } - DeleteCriticalSection(pCS); - delete pCS; -} - -////////////////////////////////////////////////////////////////////////// -void CryDeleteCriticalSectionInplace(void* cs) -{ - CRITICAL_SECTION* pCS = (CRITICAL_SECTION*)cs; - if (pCS->LockCount >= 0) - { - CryFatalError("Critical Section hanging lock"); - } - DeleteCriticalSection(pCS); -} - -////////////////////////////////////////////////////////////////////////// -void CryEnterCriticalSection(void* cs) -{ - EnterCriticalSection((CRITICAL_SECTION*)cs); -} - -////////////////////////////////////////////////////////////////////////// -bool CryTryCriticalSection(void* cs) -{ - return TryEnterCriticalSection((CRITICAL_SECTION*)cs) != 0; -} - -////////////////////////////////////////////////////////////////////////// -void CryLeaveCriticalSection(void* cs) -{ - LeaveCriticalSection((CRITICAL_SECTION*)cs); -} - ////////////////////////////////////////////////////////////////////////// uint32 CryGetFileAttributes(const char* lpFileName) { From 4b68e6c7666cc034b3b56d9541c1c17e95e49106 Mon Sep 17 00:00:00 2001 From: AMZN-AlexOteiza <82234181+AMZN-AlexOteiza@users.noreply.github.com> Date: Tue, 10 Aug 2021 09:08:16 +0100 Subject: [PATCH 238/803] Added support for pytest marks, including skipping of tests (#2353) Signed-off-by: Garcia Ruiz Co-authored-by: Garcia Ruiz --- .../ly_test_tools/o3de/editor_test.py | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/Tools/LyTestTools/ly_test_tools/o3de/editor_test.py b/Tools/LyTestTools/ly_test_tools/o3de/editor_test.py index 29484617d1..0851c63681 100644 --- a/Tools/LyTestTools/ly_test_tools/o3de/editor_test.py +++ b/Tools/LyTestTools/ly_test_tools/o3de/editor_test.py @@ -6,6 +6,8 @@ SPDX-License-Identifier: Apache-2.0 OR MIT """ import pytest +from _pytest.skipping import pytest_runtest_setup as skipping_pytest_runtest_setup + import inspect from typing import List from abc import ABC @@ -333,6 +335,10 @@ class EditorTestSuite(): next(wrap, None) return single_run setattr(self.obj, name, make_test_func(name, test_spec)) + f = make_test_func(name, test_spec) + if hasattr(test_spec, "pytestmark"): + f.pytestmark = test_spec.pytestmark + setattr(self.obj, name, f) # Add the shared tests, for these we will create a runner class for storing the run information # that will be later used for selecting what tests runners will be run @@ -359,6 +365,8 @@ class EditorTestSuite(): return result result_func = make_func(test_spec) + if hasattr(test_spec, "pytestmark"): + result_func.pytestmark = test_spec.pytestmark setattr(self.obj, test_spec.__name__, result_func) runners.append(runner) @@ -450,8 +458,15 @@ class EditorTestSuite(): def filter_session_shared_tests(session_items, shared_tests): # Retrieve the test sub-set that was collected # this can be less than the original set if were overriden via -k argument or similars - collected_elem_names = [test.originalname for test in session_items] - selected_shared_tests = [test for test in shared_tests if test.__name__ in collected_elem_names] + def will_run(item): + try: + skipping_pytest_runtest_setup(item) + return True + except: + return False + + session_items_by_name = { item.originalname:item for item in session_items } + selected_shared_tests = [test for test in shared_tests if test.__name__ in session_items_by_name.keys() and will_run(session_items_by_name[test.__name__])] return selected_shared_tests @staticmethod From d1240444982b7f6877d4d1101c67dac01bcb21b2 Mon Sep 17 00:00:00 2001 From: aaguilea Date: Tue, 10 Aug 2021 09:19:16 +0100 Subject: [PATCH 239/803] First step removing legacy code from the camera Signed-off-by: aaguilea --- Code/Editor/EditorViewportWidget.cpp | 16 +- .../Editor/LegacyViewportCameraController.cpp | 537 ------------------ Code/Editor/LegacyViewportCameraController.h | 91 --- Code/Editor/editor_lib_files.cmake | 2 - 4 files changed, 4 insertions(+), 642 deletions(-) delete mode 100644 Code/Editor/LegacyViewportCameraController.cpp delete mode 100644 Code/Editor/LegacyViewportCameraController.h diff --git a/Code/Editor/EditorViewportWidget.cpp b/Code/Editor/EditorViewportWidget.cpp index 4c638e1f82..419e51914d 100644 --- a/Code/Editor/EditorViewportWidget.cpp +++ b/Code/Editor/EditorViewportWidget.cpp @@ -72,7 +72,6 @@ #include "IPostEffectGroup.h" #include "EditorPreferencesPageGeneral.h" #include "ViewportManipulatorController.h" -#include "LegacyViewportCameraController.h" #include "ViewPane.h" #include "CustomResolutionDlg.h" @@ -102,14 +101,13 @@ AZ_CVAR( bool, ed_visibility_logTiming, false, nullptr, AZ::ConsoleFunctorFlags::Null, "Output the timing of the new IVisibilitySystem query"); -AZ_CVAR(bool, ed_useNewCameraSystem, true, nullptr, AZ::ConsoleFunctorFlags::Null, "Use the new Editor camera system"); AZ_CVAR(bool, ed_showCursorCameraLook, true, nullptr, AZ::ConsoleFunctorFlags::Null, "Show the cursor when using free look with the new camera system"); namespace SandboxEditor { bool UsingNewCameraSystem() { - return ed_useNewCameraSystem; + return true; } } // namespace SandboxEditor @@ -1476,14 +1474,9 @@ void EditorViewportWidget::SetViewportId(int id) m_renderViewport->GetControllerList()->Add(AZStd::make_shared()); - if (ed_useNewCameraSystem) - { - m_renderViewport->GetControllerList()->Add(CreateModularViewportCameraController(AzFramework::ViewportId(id))); - } - else - { - m_renderViewport->GetControllerList()->Add(AZStd::make_shared()); - } + + m_renderViewport->GetControllerList()->Add(CreateModularViewportCameraController(AzFramework::ViewportId(id))); + m_renderViewport->SetViewportSettings(&g_EditorViewportSettings); @@ -2519,7 +2512,6 @@ void EditorViewportWidget::CenterOnAABB(const AABB& aabb) m_orbitDistance = fabs(m_orbitDistance); SetViewTM(newTM); - SandboxEditor::OrbitCameraControlsBus::Event(GetViewportId(), &SandboxEditor::OrbitCameraControlsBus::Events::SetOrbitDistance, m_orbitDistance); } void EditorViewportWidget::CenterOnSliceInstance() diff --git a/Code/Editor/LegacyViewportCameraController.cpp b/Code/Editor/LegacyViewportCameraController.cpp deleted file mode 100644 index eb7323b423..0000000000 --- a/Code/Editor/LegacyViewportCameraController.cpp +++ /dev/null @@ -1,537 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -#include "LegacyViewportCameraController.h" - -#include -#include -#include -#include -#include -#include - -#include -#include -#include "CryCommon/MathConversion.h" -#include "SandboxAPI.h" -#include "Settings.h" - -namespace SandboxEditor -{ - -LegacyViewportCameraControllerInstance::LegacyViewportCameraControllerInstance(AzFramework::ViewportId viewportId, LegacyViewportCameraController* controller) - : AzFramework::MultiViewportControllerInstanceInterface(viewportId, controller) -{ - OrbitCameraControlsBus::Handler::BusConnect(viewportId); -} - -LegacyViewportCameraControllerInstance::~LegacyViewportCameraControllerInstance() -{ - OrbitCameraControlsBus::Handler::BusDisconnect(); -} - -bool LegacyViewportCameraControllerInstance::JustAltHeld() const -{ - return (m_modifiers ^ Qt::AltModifier) == 0; -} - -bool LegacyViewportCameraControllerInstance::NoModifierHeld() const -{ - return !m_modifiers; -} - -bool LegacyViewportCameraControllerInstance::AllowDolly() const -{ - return JustAltHeld(); -} - -bool LegacyViewportCameraControllerInstance::AllowOrbit() const -{ - return JustAltHeld(); -} - -bool LegacyViewportCameraControllerInstance::AllowPan() const -{ - // begin pan with alt (inverted movement) or no modifiers - return JustAltHeld() || NoModifierHeld(); -} - -bool LegacyViewportCameraControllerInstance::InvertPan() const -{ - return JustAltHeld(); -} - -void LegacyViewportCameraControllerInstance::SetOrbitDistance(float orbitDistance) -{ - m_orbitDistance = orbitDistance; -} - - -AZ::RPI::ViewportContextPtr LegacyViewportCameraControllerInstance::GetViewportContext() -{ - // This could be cached, if needed - auto viewportContextManager = AZ::Interface::Get(); - if (!viewportContextManager) - { - return {}; - } - return viewportContextManager->GetViewportContextById(GetViewportId()); -} - -bool LegacyViewportCameraControllerInstance::HandleMouseMove( - int dx, int dy) -{ - if (dx == 0 && dy == 0) - { - return false; - } - - auto viewportContext = GetViewportContext(); - if (!viewportContext) - { - return false; - } - - float speedScale = gSettings.cameraMoveSpeed; - - if (m_modifiers & Qt::Key_Control) - { - speedScale *= gSettings.cameraFastMoveSpeed; - } - - if (m_inMoveMode || m_inOrbitMode || m_inRotateMode || m_inZoomMode) - { - m_totalMouseMoveDelta += AZStd::abs(dx) + AZStd::abs(dy); - } - - if ((m_inRotateMode && m_inMoveMode) || m_inZoomMode) - { - Matrix34 m = AZTransformToLYTransform(viewportContext->GetCameraTransform()); - - Vec3 ydir = m.GetColumn1().GetNormalized(); - Vec3 pos = m.GetTranslation(); - - const float posDelta = 0.2f * dy * speedScale; - pos = pos - ydir * posDelta; - m_orbitDistance = m_orbitDistance + posDelta; - m_orbitDistance = fabs(m_orbitDistance); - - m.SetTranslation(pos); - viewportContext->SetCameraTransform(LYTransformToAZTransform(m)); - return true; - } - else if (m_inRotateMode) - { - Ang3 angles(dy, 0, dx); - angles = angles * 0.002f * gSettings.cameraRotateSpeed; - if (gSettings.invertYRotation) - { - angles.x = -angles.x; - } - Matrix34 camtm = AZTransformToLYTransform(viewportContext->GetCameraTransform()); - Ang3 ypr = CCamera::CreateAnglesYPR(Matrix33(camtm)); - ypr.x += angles.z; - ypr.y += angles.x; - - ypr.y = AZStd::clamp(ypr.y, -1.5f, 1.5f); // to keep rotation in reasonable range - ypr.z = 0; // to have camera always upward - - camtm = Matrix34(CCamera::CreateOrientationYPR(ypr), camtm.GetTranslation()); - viewportContext->SetCameraTransform(LYTransformToAZTransform(camtm)); - return true; - } - else if (m_inMoveMode) - { - // Slide. - Matrix34 m = AZTransformToLYTransform(viewportContext->GetCameraTransform()); - Vec3 xdir = m.GetColumn0().GetNormalized(); - Vec3 zdir = m.GetColumn2().GetNormalized(); - - if (InvertPan()) - { - xdir = -xdir; - zdir = -zdir; - } - - Vec3 pos = m.GetTranslation(); - pos += 0.1f * xdir * dx * speedScale + 0.1f * zdir * dy * speedScale; - m.SetTranslation(pos); - - AZ::Transform transform = viewportContext->GetCameraTransform(); - transform.SetTranslation(LYVec3ToAZVec3(pos)); - viewportContext->SetCameraTransform(transform); - return true; - } - else if (m_inOrbitMode) - { - Ang3 angles(dy, 0, dx); - angles = angles * 0.002f * gSettings.cameraRotateSpeed; - - if (gSettings.invertPan) - { - angles.z = -angles.z; - } - - Matrix34 m = AZTransformToLYTransform(viewportContext->GetCameraTransform()); - Ang3 ypr = CCamera::CreateAnglesYPR(Matrix33(m)); - ypr.x += angles.z; - ypr.y = AZStd::clamp(ypr.y, -1.5f, 1.5f); // to keep rotation in reasonable range - ypr.y += angles.x; - - Matrix33 rotateTM = CCamera::CreateOrientationYPR(ypr); - - Vec3 src = m.GetTranslation(); - Vec3 trg(m_orbitTarget.GetX(), m_orbitTarget.GetY(), m_orbitTarget.GetZ()); - float fCameraRadius = (trg - src).GetLength(); - - // Calc new source. - src = trg - rotateTM * Vec3(0, 1, 0) * fCameraRadius; - Matrix34 camTM = rotateTM; - camTM.SetTranslation(src); - - viewportContext->SetCameraTransform(LYTransformToAZTransform(camTM)); - return true; - } - return false; -} - -bool LegacyViewportCameraControllerInstance::HandleMouseWheel(float zDelta) -{ - auto viewportContext = GetViewportContext(); - if (!viewportContext) - { - return false; - } - - Matrix34 m = AZTransformToLYTransform(viewportContext->GetCameraTransform()); - const Vec3 ydir = m.GetColumn1().GetNormalized(); - - Vec3 pos = m.GetTranslation(); - - const float posDelta = 0.01f * zDelta * gSettings.wheelZoomSpeed; - pos += ydir * posDelta; - m_orbitDistance = m_orbitDistance - posDelta; - m_orbitDistance = fabs(m_orbitDistance); - - m.SetTranslation(pos); - viewportContext->SetCameraTransform(LYTransformToAZTransform(m)); - return true; -} - -bool LegacyViewportCameraControllerInstance::IsKeyDown(Qt::Key key) const -{ - return m_pressedKeys.contains(key); -} - -Qt::Key LegacyViewportCameraControllerInstance::GetKeyboardKey(const AzFramework::InputChannel& inputChannel) -{ - using Key = AzFramework::InputDeviceKeyboard::Key; - const auto& id = inputChannel.GetInputChannelId(); - if (id == Key::AlphanumericW) - { - return Qt::Key_W; - } - else if (id == Key::AlphanumericA) - { - return Qt::Key_A; - } - else if (id == Key::AlphanumericS) - { - return Qt::Key_S; - } - else if (id == Key::AlphanumericD) - { - return Qt::Key_D; - } - else if (id == Key::AlphanumericQ) - { - return Qt::Key_Q; - } - else if (id == Key::AlphanumericE) - { - return Qt::Key_E; - } - else if (id == Key::NavigationArrowUp) - { - return Qt::Key_Up; - } - else if (id == Key::NavigationArrowUp) - { - return Qt::Key_Down; - } - else if (id == Key::NavigationArrowUp) - { - return Qt::Key_Left; - } - else if (id == Key::NavigationArrowUp) - { - return Qt::Key_Right; - } - return Qt::Key_unknown; -} - -Qt::KeyboardModifier LegacyViewportCameraControllerInstance::GetKeyboardModifier(const AzFramework::InputChannel& inputChannel) -{ - using Key = AzFramework::InputDeviceKeyboard::Key; - const auto& id = inputChannel.GetInputChannelId(); - if (id == Key::ModifierAltL || id == Key::ModifierAltR) - { - return Qt::KeyboardModifier::AltModifier; - } - if (id == Key::ModifierCtrlL || id == Key::ModifierCtrlR) - { - return Qt::KeyboardModifier::ControlModifier; - } - if (id == Key::ModifierShiftL || id == Key::ModifierShiftR) - { - return Qt::KeyboardModifier::ShiftModifier; - } - return Qt::KeyboardModifier::NoModifier; -} - -bool LegacyViewportCameraControllerInstance::HandleInputChannelEvent(const AzFramework::ViewportControllerInputEvent& event) -{ - using AzFramework::InputChannel; - using MouseButton = AzFramework::InputDeviceMouse::Button; - const auto& id = event.m_inputChannel.GetInputChannelId(); - const auto& state = event.m_inputChannel.GetState(); - bool shouldCaptureCursor = m_capturingCursor; - bool shouldConsumeEvent = false; - - if (id == AzFramework::InputDeviceMouse::Movement::X || id == AzFramework::InputDeviceMouse::Movement::Y) - { - int dx = 0; - int dy = 0; - if (id == AzFramework::InputDeviceMouse::Movement::X) - { - dx = -aznumeric_cast(event.m_inputChannel.GetValue()); - } - else - { - dy = -aznumeric_cast(event.m_inputChannel.GetValue()); - } - return HandleMouseMove(dx, dy); - } - else if (id == MouseButton::Left) - { - if (state == InputChannel::State::Began) - { - if (AllowOrbit()) - { - AzFramework::CameraState cameraState; - AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::EventResult( - cameraState, event.m_viewportId, - &AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::Events::GetCameraState); - - m_inOrbitMode = true; - m_orbitTarget = cameraState.m_position + cameraState.m_forward * m_orbitDistance; - - shouldConsumeEvent = true; - shouldCaptureCursor = true; - } - } - else if (state == InputChannel::State::Ended) - { - m_inOrbitMode = false; - shouldCaptureCursor = false; - } - } - else if (id == MouseButton::Right) - { - if (state == InputChannel::State::Began) - { - if (AllowDolly()) - { - m_inZoomMode = true; - } - else - { - m_inRotateMode = true; - } - - shouldCaptureCursor = true; - // Record how much the cursor has been moved to see if we should own the mouse up event. - m_totalMouseMoveDelta = 0; - } - else if (state == InputChannel::State::Ended) - { - m_inZoomMode = false; - m_inRotateMode = false; - // If we've moved the cursor more than a couple pixels, we should eat this mouse up event to prevent the context menu controller from seeing it. - shouldConsumeEvent = m_totalMouseMoveDelta > 2; - shouldCaptureCursor = false; - } - } - else if (id == MouseButton::Middle) - { - if (state == InputChannel::State::Began) - { - if (AllowPan()) - { - m_inMoveMode = true; - shouldConsumeEvent = true; - shouldCaptureCursor = true; - } - } - else if (state == InputChannel::State::Ended) - { - m_inMoveMode = false; - shouldCaptureCursor = false; - } - } - else if (auto modifier = GetKeyboardModifier(event.m_inputChannel); modifier != Qt::KeyboardModifier::NoModifier) - { - if (state == InputChannel::State::Ended) - { - m_modifiers &= ~modifier; - } - else - { - m_modifiers |= modifier; - } - } - else if (id == AzFramework::InputDeviceMouse::Movement::Z) - { - if (state == InputChannel::State::Began || state == InputChannel::State::Updated) - { - shouldConsumeEvent = HandleMouseWheel(event.m_inputChannel.GetValue()); - } - } - else if (auto key = GetKeyboardKey(event.m_inputChannel); key != Qt::Key_unknown) - { - if (!event.m_inputChannel.IsActive()) - { - m_pressedKeys.erase(key); - } - else - { - m_pressedKeys.insert(key); - shouldConsumeEvent = true; - } - } - - UpdateCursorCapture(shouldCaptureCursor); - - return shouldConsumeEvent; -} - -void LegacyViewportCameraControllerInstance::UpdateCursorCapture(bool shouldCaptureCursor) -{ - if (m_capturingCursor != shouldCaptureCursor) - { - if (shouldCaptureCursor) - { - AzToolsFramework::ViewportInteraction::ViewportMouseCursorRequestBus::Event( - GetViewportId(), - &AzToolsFramework::ViewportInteraction::ViewportMouseCursorRequestBus::Events::BeginCursorCapture - ); - } - else - { - AzToolsFramework::ViewportInteraction::ViewportMouseCursorRequestBus::Event( - GetViewportId(), - &AzToolsFramework::ViewportInteraction::ViewportMouseCursorRequestBus::Events::EndCursorCapture - ); - } - - m_capturingCursor = shouldCaptureCursor; - } -} - -void LegacyViewportCameraControllerInstance::ResetInputChannels() -{ - m_modifiers = 0; - m_pressedKeys.clear(); - UpdateCursorCapture(false); - m_inRotateMode = m_inMoveMode = m_inOrbitMode = m_inZoomMode = false; -} - -void LegacyViewportCameraControllerInstance::UpdateViewport(const AzFramework::ViewportControllerUpdateEvent& event) -{ - auto viewportContext = GetViewportContext(); - if (!viewportContext) - { - return; - } - - AZ::Transform transform = viewportContext->GetCameraTransform(); - AZ::Vector3 xdir = transform.GetBasisX(); - AZ::Vector3 ydir = transform.GetBasisY(); - AZ::Vector3 zdir = transform.GetBasisZ(); - - AZ::Vector3 pos = transform.GetTranslation(); - - float speedScale = AZStd::GetMin(30.0f * event.m_deltaTime.count(), 20.0f); - - // Use the global modifier keys instead of our keymap. It's more reliable. - const bool shiftPressed = m_modifiers & Qt::ShiftModifier; - const bool controlPressed = m_modifiers & Qt::ControlModifier; - - speedScale *= gSettings.cameraMoveSpeed; - if (controlPressed) - { - return; - } - - if (shiftPressed) - { - speedScale *= gSettings.cameraFastMoveSpeed; - } - - bool cameraMoved = false; - - if (IsKeyDown(Qt::Key_Up) || IsKeyDown(Qt::Key_W)) - { - // move forward - cameraMoved = true; - pos = pos + (speedScale * m_moveSpeed * ydir); - } - - if (IsKeyDown(Qt::Key_Down) || IsKeyDown(Qt::Key_S)) - { - // move backward - cameraMoved = true; - pos = pos - (speedScale * m_moveSpeed * ydir); - } - - if (IsKeyDown(Qt::Key_Left) || IsKeyDown(Qt::Key_A)) - { - // move left - cameraMoved = true; - pos = pos - (speedScale * m_moveSpeed * xdir); - } - - if (IsKeyDown(Qt::Key_Right) || IsKeyDown(Qt::Key_D)) - { - // move right - cameraMoved = true; - pos = pos + (speedScale * m_moveSpeed * xdir); - } - - if (IsKeyDown(Qt::Key_E)) - { - // move Up - cameraMoved = true; - pos = pos + (speedScale * m_moveSpeed * zdir); - } - - if (IsKeyDown(Qt::Key_Q)) - { - // move down - cameraMoved = true; - pos = pos - (speedScale * m_moveSpeed * zdir); - } - - if (cameraMoved) - { - transform.SetTranslation(pos); - viewportContext->SetCameraTransform(transform); - } -} - -} //namespace SandboxEditor diff --git a/Code/Editor/LegacyViewportCameraController.h b/Code/Editor/LegacyViewportCameraController.h deleted file mode 100644 index 6edd344f23..0000000000 --- a/Code/Editor/LegacyViewportCameraController.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -#pragma once - -#include -#include -#include -#include - -#include - -#include -#include - -namespace AzFramework -{ - struct ScreenPoint; -} - -namespace SandboxEditor -{ - class OrbitCameraControls - : public AZ::EBusTraits - { - public: - ////////////////////////////////////////////////////////////////////////// - // EBusTraits overrides - static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple; - static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById; - using BusIdType = AzFramework::ViewportId; - ////////////////////////////////////////////////////////////////////////// - - virtual void SetOrbitDistance(float orbitDistance [[maybe_unused]]) {;} - }; - using OrbitCameraControlsBus = AZ::EBus; - - class LegacyViewportCameraControllerInstance; - using LegacyViewportCameraController = AzFramework::MultiViewportController; - - class LegacyViewportCameraControllerInstance final - : public AzFramework::MultiViewportControllerInstanceInterface - , public OrbitCameraControlsBus::Handler - { - public: - LegacyViewportCameraControllerInstance(AzFramework::ViewportId viewport, LegacyViewportCameraController* controller); - ~LegacyViewportCameraControllerInstance(); - - bool HandleInputChannelEvent(const AzFramework::ViewportControllerInputEvent& event) override; - void ResetInputChannels() override; - void UpdateViewport(const AzFramework::ViewportControllerUpdateEvent& event) override; - - void SetOrbitDistance(float orbitDistance) override; - - private: - bool JustAltHeld() const; - bool NoModifierHeld() const; - bool AllowDolly() const; - bool AllowOrbit() const; - bool AllowPan() const; - bool InvertPan() const; - - static Qt::KeyboardModifier GetKeyboardModifier(const AzFramework::InputChannel& inputChannel); - static Qt::Key GetKeyboardKey(const AzFramework::InputChannel& inputChannel); - - AZ::RPI::ViewportContextPtr GetViewportContext(); - - bool HandleMouseMove(int dx, int dy); - bool HandleMouseWheel(float zDelta); - bool IsKeyDown(Qt::Key key) const; - void UpdateCursorCapture(bool shouldCaptureCursor); - - bool m_inRotateMode = false; - bool m_inMoveMode = false; - bool m_inOrbitMode = false; - bool m_inZoomMode = false; - int m_totalMouseMoveDelta = 0; - float m_orbitDistance = 10.f; - float m_moveSpeed = 1.f; - AZ::Vector3 m_orbitTarget = {}; - unsigned int m_modifiers = {}; - AZStd::unordered_set m_pressedKeys; - bool m_capturingCursor = false; - }; - -} //namespace SandboxEditor diff --git a/Code/Editor/editor_lib_files.cmake b/Code/Editor/editor_lib_files.cmake index d59edfe6a8..b921d4a559 100644 --- a/Code/Editor/editor_lib_files.cmake +++ b/Code/Editor/editor_lib_files.cmake @@ -803,8 +803,6 @@ set(FILES EditorViewportCamera.h ViewportManipulatorController.cpp ViewportManipulatorController.h - LegacyViewportCameraController.cpp - LegacyViewportCameraController.h RenderViewport.cpp RenderViewport.h TopRendererWnd.cpp From 97d0456e5fe3c7d829b9db9d0af083334b5388bf Mon Sep 17 00:00:00 2001 From: aaguilea Date: Tue, 10 Aug 2021 12:08:01 +0100 Subject: [PATCH 240/803] uber nit Signed-off-by: aaguilea --- Code/Editor/EditorViewportWidget.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/Code/Editor/EditorViewportWidget.cpp b/Code/Editor/EditorViewportWidget.cpp index 419e51914d..75ac349501 100644 --- a/Code/Editor/EditorViewportWidget.cpp +++ b/Code/Editor/EditorViewportWidget.cpp @@ -1474,10 +1474,8 @@ void EditorViewportWidget::SetViewportId(int id) m_renderViewport->GetControllerList()->Add(AZStd::make_shared()); - m_renderViewport->GetControllerList()->Add(CreateModularViewportCameraController(AzFramework::ViewportId(id))); - m_renderViewport->SetViewportSettings(&g_EditorViewportSettings); UpdateScene(); From c2a2d1c5c79b8c41211e2156dac7a98ba1a9a3d5 Mon Sep 17 00:00:00 2001 From: John Date: Tue, 10 Aug 2021 14:20:46 +0100 Subject: [PATCH 241/803] Add changes from TIF/Feature branch. Signed-off-by: John --- .../Source/TestImpactCommandLineOptions.cpp | 56 +- .../Source/TestImpactCommandLineOptions.h | 24 +- .../Code/Source/TestImpactConsoleMain.cpp | 178 +++-- ...tImpactConsoleTestSequenceEventHandler.cpp | 58 +- ...estImpactConsoleTestSequenceEventHandler.h | 9 +- .../TestImpactRuntimeConfigurationFactory.cpp | 21 +- .../TestImpactClientSequenceReport.h | 500 ++++++++++++--- ...TestImpactClientSequenceReportSerializer.h | 28 + .../TestImpactClientTestRun.h | 145 +++-- .../TestImpactConfiguration.h | 2 +- .../TestImpactFramework/TestImpactPolicy.h | 81 +++ .../TestImpactFramework/TestImpactRuntime.h | 30 +- .../TestImpactSequenceReportException.h | 22 + .../TestImpactTestSequence.h | 114 +--- ...estImpactFileUtils.h => TestImpactUtils.h} | 65 +- .../TestImpactTestTargetMetaMapFactory.cpp | 4 +- .../TestImpactDynamicDependencyMap.cpp | 2 - .../TestImpactDynamicDependencyMap.h | 2 +- .../TestImpactTestSelectorAndPrioritizer.h | 2 +- .../Enumeration/TestImpactTestEnumerator.cpp | 2 +- .../Run/TestImpactInstrumentedTestRunner.cpp | 2 +- .../TestEngine/Run/TestImpactTestRunner.cpp | 2 +- .../TestEngine/TestImpactTestEngine.cpp | 2 +- .../Source/TestImpactClientSequenceReport.cpp | 324 +++++----- ...stImpactClientSequenceReportSerializer.cpp | 606 ++++++++++++++++++ .../Code/Source/TestImpactClientTestRun.cpp | 130 ++-- .../Runtime/Code/Source/TestImpactRuntime.cpp | 496 ++++++++------ .../Code/Source/TestImpactRuntimeUtils.cpp | 2 +- .../Code/Source/TestImpactRuntimeUtils.h | 56 +- .../Runtime/Code/Source/TestImpactUtils.cpp | 244 +++++++ .../testimpactframework_runtime_files.cmake | 7 +- .../ConsoleFrontendConfig.in | 6 +- .../LYTestImpactFramework.cmake | 9 +- .../build/Platform/Windows/build_config.json | 2 +- scripts/build/TestImpactAnalysis/git_utils.py | 77 ++- .../build/TestImpactAnalysis/mars_utils.py | 452 +++++++++++++ scripts/build/TestImpactAnalysis/tiaf.py | 428 +++++++------ .../build/TestImpactAnalysis/tiaf_driver.py | 132 +++- .../build/TestImpactAnalysis/tiaf_logger.py | 20 + .../tiaf_persistent_storage.py | 118 ++++ .../tiaf_persistent_storage_local.py | 56 ++ .../tiaf_persistent_storage_s3.py | 87 +++ 42 files changed, 3534 insertions(+), 1069 deletions(-) create mode 100644 Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactClientSequenceReportSerializer.h create mode 100644 Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactPolicy.h create mode 100644 Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactSequenceReportException.h rename Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/{TestImpactFileUtils.h => TestImpactUtils.h} (51%) create mode 100644 Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactClientSequenceReportSerializer.cpp create mode 100644 Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactUtils.cpp create mode 100644 scripts/build/TestImpactAnalysis/mars_utils.py create mode 100644 scripts/build/TestImpactAnalysis/tiaf_logger.py create mode 100644 scripts/build/TestImpactAnalysis/tiaf_persistent_storage.py create mode 100644 scripts/build/TestImpactAnalysis/tiaf_persistent_storage_local.py create mode 100644 scripts/build/TestImpactAnalysis/tiaf_persistent_storage_s3.py diff --git a/Code/Tools/TestImpactFramework/Frontend/Console/Code/Source/TestImpactCommandLineOptions.cpp b/Code/Tools/TestImpactFramework/Frontend/Console/Code/Source/TestImpactCommandLineOptions.cpp index cbe587cf1a..0d1f352f21 100644 --- a/Code/Tools/TestImpactFramework/Frontend/Console/Code/Source/TestImpactCommandLineOptions.cpp +++ b/Code/Tools/TestImpactFramework/Frontend/Console/Code/Source/TestImpactCommandLineOptions.cpp @@ -6,6 +6,8 @@ * */ +#include + #include #include @@ -19,8 +21,9 @@ namespace TestImpact { // Options ConfigKey, + DataFileKey, ChangeListKey, - OutputChangeListKey, + SequenceReportKey, SequenceKey, TestPrioritizationPolicyKey, ExecutionFailurePolicyKey, @@ -55,8 +58,9 @@ namespace TestImpact { // Options "config", + "datafile", "changelist", - "ochangelist", + "report", "sequence", "ppolicy", "epolicy", @@ -92,14 +96,19 @@ namespace TestImpact return ParsePathOption(OptionKeys[ConfigKey], cmd).value_or(LY_TEST_IMPACT_DEFAULT_CONFIG_FILE); } + AZStd::optional ParseDataFile(const AZ::CommandLine& cmd) + { + return ParsePathOption(OptionKeys[DataFileKey], cmd); + } + AZStd::optional ParseChangeListFile(const AZ::CommandLine& cmd) { return ParsePathOption(OptionKeys[ChangeListKey], cmd); } - bool ParseOutputChangeList(const AZ::CommandLine& cmd) + AZStd::optional ParseSequenceReportFile(const AZ::CommandLine& cmd) { - return ParseOnOffOption(OptionKeys[OutputChangeListKey], BinaryStateValue{ false, true }, cmd).value_or(false); + return ParsePathOption(OptionKeys[SequenceReportKey], cmd); } TestSequenceType ParseTestSequenceType(const AZ::CommandLine& cmd) @@ -255,9 +264,9 @@ namespace TestImpact { const AZStd::vector> states = { - {GetSuiteTypeName(SuiteType::Main), SuiteType::Main}, - {GetSuiteTypeName(SuiteType::Periodic), SuiteType::Periodic}, - {GetSuiteTypeName(SuiteType::Sandbox), SuiteType::Sandbox} + { SuiteTypeAsString(SuiteType::Main), SuiteType::Main }, + { SuiteTypeAsString(SuiteType::Periodic), SuiteType::Periodic }, + { SuiteTypeAsString(SuiteType::Sandbox), SuiteType::Sandbox } }; return ParseMultiStateOption(OptionKeys[SuiteFilterKey], states, cmd).value_or(SuiteType::Main); @@ -270,8 +279,9 @@ namespace TestImpact cmd.Parse(argc, argv); m_configurationFile = ParseConfigurationFile(cmd); + m_dataFile = ParseDataFile(cmd); m_changeListFile = ParseChangeListFile(cmd); - m_outputChangeList = ParseOutputChangeList(cmd); + m_sequenceReportFile = ParseSequenceReportFile(cmd); m_testSequenceType = ParseTestSequenceType(cmd); m_testPrioritizationPolicy = ParseTestPrioritizationPolicy(cmd); m_executionFailurePolicy = ParseExecutionFailurePolicy(cmd); @@ -286,28 +296,43 @@ namespace TestImpact m_safeMode = ParseSafeMode(cmd); m_suiteFilter = ParseSuiteFilter(cmd); } + + bool CommandLineOptions::HasDataFilePath() const + { + return m_dataFile.has_value(); + } - bool CommandLineOptions::HasChangeListFile() const + bool CommandLineOptions::HasChangeListFilePath() const { return m_changeListFile.has_value(); } + bool CommandLineOptions::HasSequenceReportFilePath() const + { + return m_sequenceReportFile.has_value(); + } + bool CommandLineOptions::HasSafeMode() const { return m_safeMode; } - const AZStd::optional& CommandLineOptions::GetChangeListFile() const + const AZStd::optional& CommandLineOptions::GetDataFilePath() const + { + return m_dataFile; + } + + const AZStd::optional& CommandLineOptions::GetChangeListFilePath() const { return m_changeListFile; } - bool CommandLineOptions::HasOutputChangeList() const + const AZStd::optional& CommandLineOptions::GetSequenceReportFilePath() const { - return m_outputChangeList; + return m_sequenceReportFile; } - const RepoPath& CommandLineOptions::GetConfigurationFile() const + const RepoPath& CommandLineOptions::GetConfigurationFilePath() const { return m_configurationFile; } @@ -379,8 +404,12 @@ namespace TestImpact " options:\n" " -config= Path to the configuration file for the TIAF runtime (default: \n" " ..json).\n" + " -datafile= Optional path to a test impact data file that will used instead of that\n" + " specified in the config file.\n" " -changelist= Path to the JSON of source file changes to perform test impact \n" " analysis on.\n" + " -report= Path to where the sequence report file will be written (if this option \n" + " is not specified, no report will be written).\n" " -gtimeout= Global timeout value to terminate the entire test sequence should it \n" " be exceeded.\n" " -ttimeout= Timeout value to terminate individual test targets should it be \n" @@ -443,7 +472,6 @@ namespace TestImpact " available, no prioritization will occur).\n" " -maxconcurrency= The maximum number of concurrent test targets/shards to be in flight at \n" " any given moment.\n" - " -ochangelist= Outputs the change list used for test selection.\n" " -suite= The test suite to select from for this test sequence."; return help; diff --git a/Code/Tools/TestImpactFramework/Frontend/Console/Code/Source/TestImpactCommandLineOptions.h b/Code/Tools/TestImpactFramework/Frontend/Console/Code/Source/TestImpactCommandLineOptions.h index ea58305afb..36ca4231b9 100644 --- a/Code/Tools/TestImpactFramework/Frontend/Console/Code/Source/TestImpactCommandLineOptions.h +++ b/Code/Tools/TestImpactFramework/Frontend/Console/Code/Source/TestImpactCommandLineOptions.h @@ -36,20 +36,29 @@ namespace TestImpact CommandLineOptions(int argc, char** argv); static AZStd::string GetCommandLineUsageString(); + //! Returns true if a test impact data file path has been supplied, otherwise false. + bool HasDataFilePath() const; + //! Returns true if a change list file path has been supplied, otherwise false. - bool HasChangeListFile() const; + bool HasChangeListFilePath() const; + + //! Returns true if a sequence report file path has been supplied, otherwise false. + bool HasSequenceReportFilePath() const; //! Returns true if the safe mode option has been enabled, otherwise false. bool HasSafeMode() const; - //! Returns true if the output change list option has been enabled, otherwise false. - bool HasOutputChangeList() const; - //! Returns the path to the runtime configuration file. - const RepoPath& GetConfigurationFile() const; + const RepoPath& GetConfigurationFilePath() const; + + //! Returns the path to the data file (if any). + const AZStd::optional& GetDataFilePath() const; //! Returns the path to the change list file (if any). - const AZStd::optional& GetChangeListFile() const; + const AZStd::optional& GetChangeListFilePath() const; + + //! Returns the path to the sequence report file (if any). + const AZStd::optional& GetSequenceReportFilePath() const; //! Returns the test sequence type to run. TestSequenceType GetTestSequenceType() const; @@ -89,8 +98,9 @@ namespace TestImpact private: RepoPath m_configurationFile; + AZStd::optional m_dataFile; AZStd::optional m_changeListFile; - bool m_outputChangeList = false; + AZStd::optional m_sequenceReportFile; TestSequenceType m_testSequenceType; Policy::TestPrioritization m_testPrioritizationPolicy = Policy::TestPrioritization::None; Policy::ExecutionFailure m_executionFailurePolicy = Policy::ExecutionFailure::Continue; diff --git a/Code/Tools/TestImpactFramework/Frontend/Console/Code/Source/TestImpactConsoleMain.cpp b/Code/Tools/TestImpactFramework/Frontend/Console/Code/Source/TestImpactConsoleMain.cpp index 8027649a44..bbb4765ad4 100644 --- a/Code/Tools/TestImpactFramework/Frontend/Console/Code/Source/TestImpactConsoleMain.cpp +++ b/Code/Tools/TestImpactFramework/Frontend/Console/Code/Source/TestImpactConsoleMain.cpp @@ -9,14 +9,16 @@ #include #include #include +#include #include #include #include #include #include -#include +#include #include #include +#include #include #include @@ -33,31 +35,6 @@ namespace TestImpact { namespace Console { - //! Generates a string to be used for printing to the console for the specified change list. - AZStd::string GenerateChangeListString(const ChangeList& changeList) - { - AZStd::string output; - - const auto& outputFiles = [&output](const AZStd::vector& files) - { - for (const auto& file : files) - { - output += AZStd::string::format("\t%s\n", file.c_str()); - } - }; - - output += AZStd::string::format("Created files (%u):\n", changeList.m_createdFiles.size()); - outputFiles(changeList.m_createdFiles); - - output += AZStd::string::format("Updated files (%u):\n", changeList.m_updatedFiles.size()); - outputFiles(changeList.m_updatedFiles); - - output += AZStd::string::format("Deleted files (%u):\n", changeList.m_deletedFiles.size()); - outputFiles(changeList.m_deletedFiles); - - return output; - } - //! Gets the appropriate console return code for the specified test sequence result. ReturnCode GetReturnCodeForTestSequenceResult(TestSequenceResult result) { @@ -75,6 +52,20 @@ namespace TestImpact } } + //! Wrapper around sequence reports to optionally serialize them and transform the result into a return code. + template + ReturnCode ConsumeSequenceReportAndGetReturnCode(const SequenceReportType& sequenceReport, const CommandLineOptions& options) + { + if (options.HasSequenceReportFilePath()) + { + std::cout << "Exporting sequence report '" << options.GetSequenceReportFilePath().value().c_str() << "'" << std::endl; + const auto sequenceReportJson = SerializeSequenceReport(sequenceReport); + WriteFileContents(sequenceReportJson, options.GetSequenceReportFilePath().value()); + } + + return GetReturnCodeForTestSequenceResult(sequenceReport.GetResult()); + } + //! Wrapper around impact analysis sequences to handle the case where the safe mode option is active. ReturnCode WrappedImpactAnalysisTestSequence( const CommandLineOptions& options, @@ -88,35 +79,34 @@ namespace TestImpact CommandLineOptionsException, "Expected a change list for impact analysis but none was provided"); - TestSequenceResult result = TestSequenceResult::Failure; if (options.HasSafeMode()) { if (options.GetTestSequenceType() == TestSequenceType::ImpactAnalysis) { - auto safeImpactAnalysisSequenceReport = runtime.SafeImpactAnalysisTestSequence( - changeList.value(), - options.GetTestPrioritizationPolicy(), - options.GetTestTargetTimeout(), - options.GetGlobalTimeout(), - SafeImpactAnalysisTestSequenceStartCallback, - SafeImpactAnalysisTestSequenceCompleteCallback, - TestRunCompleteCallback); - - result = safeImpactAnalysisSequenceReport.GetResult(); + return ConsumeSequenceReportAndGetReturnCode( + runtime.SafeImpactAnalysisTestSequence( + changeList.value(), + options.GetTestPrioritizationPolicy(), + options.GetTestTargetTimeout(), + options.GetGlobalTimeout(), + SafeImpactAnalysisTestSequenceStartCallback, + SafeImpactAnalysisTestSequenceCompleteCallback, + TestRunCompleteCallback), + options); } else if (options.GetTestSequenceType() == TestSequenceType::ImpactAnalysisNoWrite) { // A no-write impact analysis sequence with safe mode enabled is functionally identical to a regular sequence type // due to a) the selected tests being run without instrumentation and b) the discarded tests also being run without // instrumentation - auto sequenceReport = runtime.RegularTestSequence( - options.GetTestTargetTimeout(), - options.GetGlobalTimeout(), - TestSequenceStartCallback, - TestSequenceCompleteCallback, - TestRunCompleteCallback); - - result = sequenceReport.GetResult(); + return ConsumeSequenceReportAndGetReturnCode( + runtime.RegularTestSequence( + options.GetTestTargetTimeout(), + options.GetGlobalTimeout(), + TestSequenceStartCallback, + RegularTestSequenceCompleteCallback, + TestRunCompleteCallback), + options); } else { @@ -139,20 +129,18 @@ namespace TestImpact throw(Exception("Unexpected sequence type")); } - auto impactAnalysisSequenceReport = runtime.ImpactAnalysisTestSequence( - changeList.value(), - options.GetTestPrioritizationPolicy(), - dynamicDependencyMapPolicy, - options.GetTestTargetTimeout(), - options.GetGlobalTimeout(), - ImpactAnalysisTestSequenceStartCallback, - ImpactAnalysisTestSequenceCompleteCallback, - TestRunCompleteCallback); - - result = impactAnalysisSequenceReport.GetResult(); + return ConsumeSequenceReportAndGetReturnCode( + runtime.ImpactAnalysisTestSequence( + changeList.value(), + options.GetTestPrioritizationPolicy(), + dynamicDependencyMapPolicy, + options.GetTestTargetTimeout(), + options.GetGlobalTimeout(), + ImpactAnalysisTestSequenceStartCallback, + ImpactAnalysisTestSequenceCompleteCallback, + TestRunCompleteCallback), + options); } - - return GetReturnCodeForTestSequenceResult(result); }; //! Entry point for the test impact analysis framework console front end application. @@ -164,28 +152,22 @@ namespace TestImpact AZStd::optional changeList; // If we have a change list, check to see whether or not the client has requested the printing of said change list - if (options.HasChangeListFile()) + if (options.HasChangeListFilePath()) { - changeList = DeserializeChangeList(ReadFileContents(*options.GetChangeListFile())); - if (options.HasOutputChangeList()) - { - std::cout << "Change List:\n"; - std::cout << GenerateChangeListString(*changeList).c_str(); - - if (options.GetTestSequenceType() == TestSequenceType::None) - { - return ReturnCode::Success; - } - } + changeList = DeserializeChangeList(ReadFileContents(*options.GetChangeListFilePath())); } - // As of now, there are no other non-test operations other than printing a change list so getting this far is considered an error - AZ_TestImpact_Eval(options.GetTestSequenceType() != TestSequenceType::None, CommandLineOptionsException, "No action specified"); + // As of now, there are no non-test operations but leave this door open for the future + if (options.GetTestSequenceType() == TestSequenceType::None) + { + return ReturnCode::Success; + } std::cout << "Constructing in-memory model of source tree and test coverage for test suite "; - std::cout << GetSuiteTypeName(options.GetSuiteFilter()).c_str() << ", this may take a moment...\n"; + std::cout << SuiteTypeAsString(options.GetSuiteFilter()).c_str() << ", this may take a moment...\n"; Runtime runtime( - RuntimeConfigurationFactory(ReadFileContents(options.GetConfigurationFile())), + RuntimeConfigurationFactory(ReadFileContents(options.GetConfigurationFilePath())), + options.GetDataFilePath(), options.GetSuiteFilter(), options.GetExecutionFailurePolicy(), options.GetFailedTestCoveragePolicy(), @@ -208,25 +190,25 @@ namespace TestImpact { case TestSequenceType::Regular: { - const auto sequenceReport = runtime.RegularTestSequence( - options.GetTestTargetTimeout(), - options.GetGlobalTimeout(), - TestSequenceStartCallback, - TestSequenceCompleteCallback, - TestRunCompleteCallback); - - return GetReturnCodeForTestSequenceResult(sequenceReport.GetResult()); + return ConsumeSequenceReportAndGetReturnCode( + runtime.RegularTestSequence( + options.GetTestTargetTimeout(), + options.GetGlobalTimeout(), + TestSequenceStartCallback, + RegularTestSequenceCompleteCallback, + TestRunCompleteCallback), + options); } case TestSequenceType::Seed: { - const auto sequenceReport = runtime.SeededTestSequence( - options.GetTestTargetTimeout(), - options.GetGlobalTimeout(), - TestSequenceStartCallback, - TestSequenceCompleteCallback, - TestRunCompleteCallback); - - return GetReturnCodeForTestSequenceResult(sequenceReport.GetResult()); + return ConsumeSequenceReportAndGetReturnCode( + runtime.SeededTestSequence( + options.GetTestTargetTimeout(), + options.GetGlobalTimeout(), + TestSequenceStartCallback, + SeedTestSequenceCompleteCallback, + TestRunCompleteCallback), + options); } case TestSequenceType::ImpactAnalysisNoWrite: case TestSequenceType::ImpactAnalysis: @@ -241,14 +223,14 @@ namespace TestImpact } else { - const auto sequenceReport = runtime.SeededTestSequence( - options.GetTestTargetTimeout(), - options.GetGlobalTimeout(), - TestSequenceStartCallback, - TestSequenceCompleteCallback, - TestRunCompleteCallback); - - return GetReturnCodeForTestSequenceResult(sequenceReport.GetResult()); + return ConsumeSequenceReportAndGetReturnCode( + runtime.SeededTestSequence( + options.GetTestTargetTimeout(), + options.GetGlobalTimeout(), + TestSequenceStartCallback, + SeedTestSequenceCompleteCallback, + TestRunCompleteCallback), + options); } } default: diff --git a/Code/Tools/TestImpactFramework/Frontend/Console/Code/Source/TestImpactConsoleTestSequenceEventHandler.cpp b/Code/Tools/TestImpactFramework/Frontend/Console/Code/Source/TestImpactConsoleTestSequenceEventHandler.cpp index da7052933c..e7430fe90b 100644 --- a/Code/Tools/TestImpactFramework/Frontend/Console/Code/Source/TestImpactConsoleTestSequenceEventHandler.cpp +++ b/Code/Tools/TestImpactFramework/Frontend/Console/Code/Source/TestImpactConsoleTestSequenceEventHandler.cpp @@ -6,8 +6,9 @@ * */ -#include +#include +#include #include #include @@ -20,7 +21,7 @@ namespace TestImpact { void TestSuiteFilter(SuiteType filter) { - std::cout << "Test suite filter: " << GetSuiteTypeName(filter).c_str() << "\n"; + std::cout << "Test suite filter: " << SuiteTypeAsString(filter).c_str() << "\n"; } void ImpactAnalysisTestSelection(size_t numSelectedTests, size_t numDiscardedTests, size_t numExcludedTests, size_t numDraftedTests) @@ -36,69 +37,66 @@ namespace TestImpact { std::cout << "Sequence completed in " << (testRunReport.GetDuration().count() / 1000.f) << "s with"; - if (!testRunReport.GetExecutionFailureTests().empty() || - !testRunReport.GetFailingTests().empty() || - !testRunReport.GetTimedOutTests().empty() || - !testRunReport.GetUnexecutedTests().empty()) + if (!testRunReport.GetExecutionFailureTestRuns().empty() || + !testRunReport.GetFailingTestRuns().empty() || + !testRunReport.GetTimedOutTestRuns().empty() || + !testRunReport.GetUnexecutedTestRuns().empty()) { std::cout << ":\n"; std::cout << SetColor(Foreground::White, Background::Red).c_str() - << testRunReport.GetFailingTests().size() + << testRunReport.GetFailingTestRuns().size() << ResetColor().c_str() << " test failures\n"; std::cout << SetColor(Foreground::White, Background::Red).c_str() - << testRunReport.GetExecutionFailureTests().size() + << testRunReport.GetExecutionFailureTestRuns().size() << ResetColor().c_str() << " execution failures\n"; std::cout << SetColor(Foreground::White, Background::Red).c_str() - << testRunReport.GetTimedOutTests().size() + << testRunReport.GetTimedOutTestRuns().size() << ResetColor().c_str() << " test timeouts\n"; std::cout << SetColor(Foreground::White, Background::Red).c_str() - << testRunReport.GetUnexecutedTests().size() + << testRunReport.GetUnexecutedTestRuns().size() << ResetColor().c_str() << " unexecuted tests\n"; - if (!testRunReport.GetFailingTests().empty()) + if (!testRunReport.GetFailingTestRuns().empty()) { std::cout << "\nTest failures:\n"; - for (const auto& testRunFailure : testRunReport.GetFailingTests()) + for (const auto& testRunFailure : testRunReport.GetFailingTestRuns()) { - for (const auto& testCaseFailure : testRunFailure.GetTestCaseFailures()) + for (const auto& test : testRunFailure.GetTests()) { - for (const auto& testFailure : testCaseFailure.GetTestFailures()) + if (test.GetResult() == Client::TestResult::Failed) { - std::cout << " " - << testRunFailure.GetTargetName().c_str() - << "." << testCaseFailure.GetName().c_str() - << "." << testFailure.GetName().c_str() << "\n"; + std::cout << " " << test.GetName().c_str() << "\n"; } } } } - if (!testRunReport.GetExecutionFailureTests().empty()) + if (!testRunReport.GetExecutionFailureTestRuns().empty()) { std::cout << "\nExecution failures:\n"; - for (const auto& executionFailure : testRunReport.GetExecutionFailureTests()) + for (const auto& executionFailure : testRunReport.GetExecutionFailureTestRuns()) { std::cout << " " << executionFailure.GetTargetName().c_str() << "\n"; std::cout << executionFailure.GetCommandString().c_str() << "\n"; } } - if (!testRunReport.GetTimedOutTests().empty()) + if (!testRunReport.GetTimedOutTestRuns().empty()) { std::cout << "\nTimed out tests:\n"; - for (const auto& testTimeout : testRunReport.GetTimedOutTests()) + for (const auto& testTimeout : testRunReport.GetTimedOutTestRuns()) { std::cout << " " << testTimeout.GetTargetName().c_str() << "\n"; } } - if (!testRunReport.GetUnexecutedTests().empty()) + if (!testRunReport.GetUnexecutedTestRuns().empty()) { std::cout << "\nUnexecuted tests:\n"; - for (const auto& unexecutedTest : testRunReport.GetUnexecutedTests()) + for (const auto& unexecutedTest : testRunReport.GetUnexecutedTestRuns()) { std::cout << " " << unexecutedTest.GetTargetName().c_str() << "\n"; } @@ -106,7 +104,7 @@ namespace TestImpact } else { - std::cout << SetColor(Foreground::White, Background::Green).c_str() << " \100% passes!\n" << ResetColor().c_str() << "\n"; + std::cout << " " << SetColor(Foreground::White, Background::Green).c_str() << "100% passes!\n" << ResetColor().c_str() << "\n"; } } } @@ -149,13 +147,17 @@ namespace TestImpact draftedTests.size()); } - void TestSequenceCompleteCallback(const Client::SequenceReport& sequenceReport) + void RegularTestSequenceCompleteCallback(const Client::RegularSequenceReport& sequenceReport) { - Output::FailureReport(sequenceReport.GetSelectedTestRunReport()); std::cout << "Updating and serializing the test impact analysis data, this may take a moment...\n"; } + void SeedTestSequenceCompleteCallback(const Client::SeedSequenceReport& sequenceReport) + { + Output::FailureReport(sequenceReport.GetSelectedTestRunReport()); + } + void ImpactAnalysisTestSequenceCompleteCallback(const Client::ImpactAnalysisSequenceReport& sequenceReport) { std::cout << "Selected test run:\n"; @@ -181,7 +183,7 @@ namespace TestImpact std::cout << "Updating and serializing the test impact analysis data, this may take a moment...\n"; } - void TestRunCompleteCallback(const Client::TestRun& testRun, size_t numTestRunsCompleted, size_t totalNumTestRuns) + void TestRunCompleteCallback(const Client::TestRunBase& testRun, size_t numTestRunsCompleted, size_t totalNumTestRuns) { const auto progress = AZStd::string::format("(%03u/%03u)", numTestRunsCompleted, totalNumTestRuns, testRun.GetTargetName().c_str()); diff --git a/Code/Tools/TestImpactFramework/Frontend/Console/Code/Source/TestImpactConsoleTestSequenceEventHandler.h b/Code/Tools/TestImpactFramework/Frontend/Console/Code/Source/TestImpactConsoleTestSequenceEventHandler.h index ff757b2d5a..8f28d60617 100644 --- a/Code/Tools/TestImpactFramework/Frontend/Console/Code/Source/TestImpactConsoleTestSequenceEventHandler.h +++ b/Code/Tools/TestImpactFramework/Frontend/Console/Code/Source/TestImpactConsoleTestSequenceEventHandler.h @@ -38,8 +38,11 @@ namespace TestImpact const Client::TestRunSelection& discardedTests, const AZStd::vector& draftedTests); - //! Handler for TestSequenceCompleteCallback event. - void TestSequenceCompleteCallback(const Client::SequenceReport& sequenceReport); + //! Handler for RegularTestSequenceCompleteCallback event. + void RegularTestSequenceCompleteCallback(const Client::RegularSequenceReport& sequenceReport); + + //! Handler for SeedTestSequenceCompleteCallback event. + void SeedTestSequenceCompleteCallback(const Client::SeedSequenceReport& sequenceReport); //! Handler for ImpactAnalysisTestSequenceCompleteCallback event. void ImpactAnalysisTestSequenceCompleteCallback(const Client::ImpactAnalysisSequenceReport& sequenceReport); @@ -48,6 +51,6 @@ namespace TestImpact void SafeImpactAnalysisTestSequenceCompleteCallback(const Client::SafeImpactAnalysisSequenceReport& sequenceReport); //! Handler for TestRunCompleteCallback event. - void TestRunCompleteCallback(const Client::TestRun& testRun, size_t numTestRunsCompleted, size_t totalNumTestRuns); + void TestRunCompleteCallback(const Client::TestRunBase& testRun, size_t numTestRunsCompleted, size_t totalNumTestRuns); } // namespace Console } // namespace TestImpact diff --git a/Code/Tools/TestImpactFramework/Frontend/Console/Code/Source/TestImpactRuntimeConfigurationFactory.cpp b/Code/Tools/TestImpactFramework/Frontend/Console/Code/Source/TestImpactRuntimeConfigurationFactory.cpp index 0d54cf417d..8ea32d6447 100644 --- a/Code/Tools/TestImpactFramework/Frontend/Console/Code/Source/TestImpactRuntimeConfigurationFactory.cpp +++ b/Code/Tools/TestImpactFramework/Frontend/Console/Code/Source/TestImpactRuntimeConfigurationFactory.cpp @@ -7,6 +7,7 @@ */ #include +#include #include @@ -140,17 +141,17 @@ namespace TestImpact return tempWorkspaceConfig; } - AZStd::array ParseTestImpactAnalysisDataFiles(const RepoPath& root, const rapidjson::Value& sparTIAFile) + AZStd::array ParseTestImpactAnalysisDataFiles(const RepoPath& root, const rapidjson::Value& sparTiaFile) { - AZStd::array sparTIAFiles; - sparTIAFiles[static_cast(SuiteType::Main)] = - GetAbsPathFromRelPath(root, sparTIAFile[GetSuiteTypeName(SuiteType::Main).c_str()].GetString()); - sparTIAFiles[static_cast(SuiteType::Periodic)] = - GetAbsPathFromRelPath(root, sparTIAFile[GetSuiteTypeName(SuiteType::Periodic).c_str()].GetString()); - sparTIAFiles[static_cast(SuiteType::Sandbox)] = - GetAbsPathFromRelPath(root, sparTIAFile[GetSuiteTypeName(SuiteType::Sandbox).c_str()].GetString()); + AZStd::array sparTiaFiles; + sparTiaFiles[static_cast(SuiteType::Main)] = + GetAbsPathFromRelPath(root, sparTiaFile[SuiteTypeAsString(SuiteType::Main).c_str()].GetString()); + sparTiaFiles[static_cast(SuiteType::Periodic)] = + GetAbsPathFromRelPath(root, sparTiaFile[SuiteTypeAsString(SuiteType::Periodic).c_str()].GetString()); + sparTiaFiles[static_cast(SuiteType::Sandbox)] = + GetAbsPathFromRelPath(root, sparTiaFile[SuiteTypeAsString(SuiteType::Sandbox).c_str()].GetString()); - return sparTIAFiles; + return sparTiaFiles; } WorkspaceConfig::Active ParseActiveWorkspaceConfig(const rapidjson::Value& activeWorkspace) @@ -160,7 +161,7 @@ namespace TestImpact activeWorkspaceConfig.m_root = activeWorkspace[Config::Keys[Config::Root]].GetString(); activeWorkspaceConfig.m_enumerationCacheDirectory = GetAbsPathFromRelPath(activeWorkspaceConfig.m_root, relativePaths[Config::Keys[Config::EnumerationCacheDir]].GetString()); - activeWorkspaceConfig.m_sparTIAFiles = + activeWorkspaceConfig.m_sparTiaFiles = ParseTestImpactAnalysisDataFiles(activeWorkspaceConfig.m_root, relativePaths[Config::Keys[Config::TestImpactDataFiles]]); return activeWorkspaceConfig; } diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactClientSequenceReport.h b/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactClientSequenceReport.h index 73f3827fae..e86123ddc7 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactClientSequenceReport.h +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactClientSequenceReport.h @@ -1,6 +1,7 @@ /* - * Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. - * + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * * SPDX-License-Identifier: Apache-2.0 OR MIT * */ @@ -11,10 +12,25 @@ #include #include +#include +#include + namespace TestImpact { namespace Client { + //! The report types generated by each sequence. + enum class SequenceReportType : AZ::u8 + { + RegularSequence, + SeedSequence, + ImpactAnalysisSequence, + SafeImpactAnalysisSequence + }; + + //! Calculates the final sequence result for a composite of multiple sequences. + TestSequenceResult CalculateMultiTestSequenceResult(const AZStd::vector& results); + //! Report detailing the result and duration of a given set of test runs along with the details of each individual test run. class TestRunReport { @@ -23,20 +39,20 @@ namespace TestImpact //! @param result The result of this set of test runs. //! @param startTime The time point his set of test runs started. //! @param duration The duration this set of test runs took to complete. - //! @param passingTests The set of test runs that executed successfully with no failing tests. - //! @param failing tests The set of test runs that executed successfully but had one or more failing tests. - //! @param executionFailureTests The set of test runs that failed to execute. - //! @param timedOutTests The set of test runs that executed successfully but were terminated prematurely due to timing out. - //! @param unexecutedTests The set of test runs that were queued up for execution but did not get the opportunity to execute. + //! @param passingTestRuns The set of test runs that executed successfully with no failing test runs. + //! @param failingTestRuns The set of test runs that executed successfully but had one or more failing tests. + //! @param executionFailureTestRuns The set of test runs that failed to execute. + //! @param timedOutTestRuns The set of test runs that executed successfully but were terminated prematurely due to timing out. + //! @param unexecutedTestRuns The set of test runs that were queued up for execution but did not get the opportunity to execute. TestRunReport( TestSequenceResult result, AZStd::chrono::high_resolution_clock::time_point startTime, AZStd::chrono::milliseconds duration, - AZStd::vector&& passingTests, - AZStd::vector&& failingTests, - AZStd::vector&& executionFailureTests, - AZStd::vector&& timedOutTests, - AZStd::vector&& unexecutedTests); + AZStd::vector&& passingTestRuns, + AZStd::vector&& failingTestRuns, + AZStd::vector&& executionFailureTestRuns, + AZStd::vector&& timedOutTestRuns, + AZStd::vector&& unexecutedTestRuns); //! Returns the result of this sequence of test runs. TestSequenceResult GetResult() const; @@ -50,190 +66,478 @@ namespace TestImpact //! Returns the duration this sequence of test runs took to complete. AZStd::chrono::milliseconds GetDuration() const; + //! Returns the total number of test runs. + size_t GetTotalNumTestRuns() const; + //! Returns the number of passing test runs. - size_t GetNumPassingTests() const; + size_t GetNumPassingTestRuns() const; //! Returns the number of failing test runs. - size_t GetNumFailingTests() const; + size_t GetNumFailingTestRuns() const; + + //! Returns the number of test runs that failed to execute. + size_t GetNumExecutionFailureTestRuns() const; //! Returns the number of timed out test runs. - size_t GetNumTimedOutTests() const; + size_t GetNumTimedOutTestRuns() const; //! Returns the number of unexecuted test runs. - size_t GetNumUnexecutedTests() const; + size_t GetNumUnexecutedTestRuns() const; + + //! Returns the total number of passing tests across all test runs in the report. + size_t GetTotalNumPassingTests() const; + + //! Returns the total number of failing tests across all test runs in the report. + size_t GetTotalNumFailingTests() const; + + //! Returns the total number of disabled tests across all test runs in the report. + size_t GetTotalNumDisabledTests() const; //! Returns the set of test runs that executed successfully with no failing tests. - const AZStd::vector& GetPassingTests() const; + const AZStd::vector& GetPassingTestRuns() const; //! Returns the set of test runs that executed successfully but had one or more failing tests. - const AZStd::vector& GetFailingTests() const; + const AZStd::vector& GetFailingTestRuns() const; //! Returns the set of test runs that failed to execute. - const AZStd::vector& GetExecutionFailureTests() const; + const AZStd::vector& GetExecutionFailureTestRuns() const; //! Returns the set of test runs that executed successfully but were terminated prematurely due to timing out. - const AZStd::vector& GetTimedOutTests() const; + const AZStd::vector& GetTimedOutTestRuns() const; //! Returns the set of test runs that were queued up for execution but did not get the opportunity to execute. - const AZStd::vector& GetUnexecutedTests() const; + const AZStd::vector& GetUnexecutedTestRuns() const; private: - TestSequenceResult m_result; + TestSequenceResult m_result = TestSequenceResult::Success; AZStd::chrono::high_resolution_clock::time_point m_startTime; - AZStd::chrono::milliseconds m_duration; - AZStd::vector m_passingTests; - AZStd::vector m_failingTests; - AZStd::vector m_executionFailureTests; - AZStd::vector m_timedOutTests; - AZStd::vector m_unexecutedTests; + AZStd::chrono::milliseconds m_duration = AZStd::chrono::milliseconds{ 0 }; + AZStd::vector m_passingTestRuns; + AZStd::vector m_failingTestRuns; + AZStd::vector m_executionFailureTestRuns; + AZStd::vector m_timedOutTestRuns; + AZStd::vector m_unexecutedTestRuns; + size_t m_totalNumPassingTests = 0; + size_t m_totalNumFailingTests = 0; + size_t m_totalNumDisabledTests = 0; }; - //! Report detailing a test run sequence of selected tests. - class SequenceReport + //! Base class for all sequence report types. + template + class SequenceReportBase { public: //! Constructs the report for a sequence of selected tests. + //! @param type The type of sequence this report is generated for. + //! @param maxConcurrency The maximum number of concurrent test targets in flight at any given time. + //! @param testTargetTimeout The maximum duration individual test targets may be in flight for (infinite if empty). + //! @param globalTimeout The maximum duration the entire test sequence may run for (infinite if empty). + //! @param policyState The policy state this sequence was executed under. //! @param suiteType The suite from which the tests have been selected from. - //! @param selectedTests The target names of the selected tests. + //! @param selectedTestRuns The target names of the selected test runs. //! @param selectedTestRunReport The report for the set of selected test runs. - SequenceReport(SuiteType suiteType, const TestRunSelection& selectedTests, TestRunReport&& selectedTestRunReport); + SequenceReportBase( + SequenceReportType type, + size_t maxConcurrency, + const AZStd::optional& testTargetTimeout, + const AZStd::optional& globalTimeout, + const PolicyStateType& policyState, + SuiteType suiteType, + const TestRunSelection& selectedTestRuns, + TestRunReport&& selectedTestRunReport) + : m_type(type) + , m_maxConcurrency(maxConcurrency) + , m_testTargetTimeout(testTargetTimeout) + , m_globalTimeout(globalTimeout) + , m_policyState(policyState) + , m_suite(suiteType) + , m_selectedTestRuns(selectedTestRuns) + , m_selectedTestRunReport(AZStd::move(selectedTestRunReport)) + { + } + + virtual ~SequenceReportBase() = default; + + //! Returns the identifying type for this sequence report. + SequenceReportType GetType() const + { + return m_type; + } + + //! Returns the maximum concurrency for this sequence. + size_t GetMaxConcurrency() const + { + return m_maxConcurrency; + } + + //! Returns the global timeout for this sequence. + const AZStd::optional& GetGlobalTimeout() const + { + return m_globalTimeout; + } + + //! Returns the test target timeout for this sequence. + const AZStd::optional& GetTestTargetTimeout() const + { + return m_testTargetTimeout; + } + + //! Returns the policy state for this sequence. + const PolicyStateType& GetPolicyState() const + { + return m_policyState; + } + + //! Returns the suite for this sequence. + SuiteType GetSuite() const + { + return m_suite; + } + + //! Returns the result of the sequence. + virtual TestSequenceResult GetResult() const + { + return m_selectedTestRunReport.GetResult(); + } //! Returns the tests selected for running in the sequence. - TestRunSelection GetSelectedTests() const; + TestRunSelection GetSelectedTestRuns() const + { + return m_selectedTestRuns; + } //! Returns the report for the selected test runs. - TestRunReport GetSelectedTestRunReport() const; + TestRunReport GetSelectedTestRunReport() const + { + return m_selectedTestRunReport; + } //! Returns the start time of the sequence. - AZStd::chrono::high_resolution_clock::time_point GetStartTime() const; + AZStd::chrono::high_resolution_clock::time_point GetStartTime() const + { + return m_selectedTestRunReport.GetStartTime(); + } //! Returns the end time of the sequence. - AZStd::chrono::high_resolution_clock::time_point GetEndTime() const; - - //! Returns the result of the sequence. - virtual TestSequenceResult GetResult() const; + AZStd::chrono::high_resolution_clock::time_point GetEndTime() const + { + return GetStartTime() + GetDuration(); + } //! Returns the entire duration the sequence took from start to finish. - virtual AZStd::chrono::milliseconds GetDuration() const; + virtual AZStd::chrono::milliseconds GetDuration() const + { + return m_selectedTestRunReport.GetDuration(); + } - //! Get the total number of tests in the sequence that passed. - virtual size_t GetTotalNumPassingTests() const; + //! Returns the total number of test runs across all test run reports. + virtual size_t GetTotalNumTestRuns() const + { + return m_selectedTestRunReport.GetTotalNumTestRuns(); + } - //! Get the total number of tests in the sequence that contain one or more test failures. - virtual size_t GetTotalNumFailingTests() const; + //! Returns the total number of passing tests across all test targets in all test run reports. + virtual size_t GetTotalNumPassingTests() const + { + return m_selectedTestRunReport.GetTotalNumPassingTests(); + } - //! Get the total number of tests in the sequence that timed out whilst in flight. - virtual size_t GetTotalNumTimedOutTests() const; + //! Returns the total number of failing tests across all test targets in all test run reports. + virtual size_t GetTotalNumFailingTests() const + { + return m_selectedTestRunReport.GetTotalNumFailingTests(); + } - //! Get the total number of tests in the sequence that were queued for execution but did not get the oppurtunity to execute. - virtual size_t GetTotalNumUnexecutedTests() const; + //! Returns the total number of unexecuted tests across all test targets in all test run reports. + virtual size_t GetTotalNumDisabledTests() const + { + return m_selectedTestRunReport.GetTotalNumDisabledTests(); + } + + //! Get the total number of test runs in the sequence that passed. + virtual size_t GetTotalNumPassingTestRuns() const + { + return m_selectedTestRunReport.GetNumPassingTestRuns(); + } + + //! Get the total number of test runs in the sequence that contain one or more test failures. + virtual size_t GetTotalNumFailingTestRuns() const + { + return m_selectedTestRunReport.GetNumFailingTestRuns(); + } + + //! Returns the total number of test runs that failed to execute. + virtual size_t GetTotalNumExecutionFailureTestRuns() const + { + return m_selectedTestRunReport.GetNumExecutionFailureTestRuns(); + } + + //! Get the total number of test runs in the sequence that timed out whilst in flight. + virtual size_t GetTotalNumTimedOutTestRuns() const + { + return m_selectedTestRunReport.GetNumTimedOutTestRuns(); + } + + //! Get the total number of test runs in the sequence that were queued for execution but did not get the opportunity to execute. + virtual size_t GetTotalNumUnexecutedTestRuns() const + { + return m_selectedTestRunReport.GetNumUnexecutedTestRuns(); + } private: - SuiteType m_suite; - TestRunSelection m_selectedTests; + SequenceReportType m_type; + size_t m_maxConcurrency = 0; + AZStd::optional m_testTargetTimeout; + AZStd::optional m_globalTimeout; + PolicyStateType m_policyState; + SuiteType m_suite = SuiteType::Main; + TestRunSelection m_selectedTestRuns; TestRunReport m_selectedTestRunReport; }; - //! Report detailing a test run sequence of selected and drafted tests. - class DraftingSequenceReport - : public SequenceReport + //! Report type for regular test sequences. + class RegularSequenceReport + : public SequenceReportBase { public: - //! Constructs the report for a sequence of selected and drafted tests. + //! Constructs the report for a regular sequence. + //! @param maxConcurrency The maximum number of concurrent test targets in flight at any given time. + //! @param testTargetTimeout The maximum duration individual test targets may be in flight for (infinite if empty). + //! @param globalTimeout The maximum duration the entire test sequence may run for (infinite if empty). + //! @param policyState The policy state this sequence was executed under. //! @param suiteType The suite from which the tests have been selected from. - //! @param selectedTests The target names of the selected tests. - //! @param draftedTests The target names of the drafted tests. + //! @param selectedTestRuns The target names of the selected test runs. + //! @param selectedTestRunReport The report for the set of selected test runs. + RegularSequenceReport( + size_t maxConcurrency, + const AZStd::optional& testTargetTimeout, + const AZStd::optional& globalTimeout, + const SequencePolicyState& policyState, + SuiteType suiteType, + const TestRunSelection& selectedTestRuns, + TestRunReport&& selectedTestRunReport); + }; + + //! Report type for seed test sequences. + class SeedSequenceReport + : public SequenceReportBase + { + public: + //! Constructs the report for a seed sequence. + //! @param maxConcurrency The maximum number of concurrent test targets in flight at any given time. + //! @param testTargetTimeout The maximum duration individual test targets may be in flight for (infinite if empty). + //! @param globalTimeout The maximum duration the entire test sequence may run for (infinite if empty). + //! @param policyState The policy state this sequence was executed under. + //! @param suiteType The suite from which the tests have been selected from. + //! @param selectedTestRuns The target names of the selected test runs. + //! @param selectedTestRunReport The report for the set of selected test runs. + SeedSequenceReport( + size_t maxConcurrency, + const AZStd::optional& testTargetTimeout, + const AZStd::optional& globalTimeout, + const SequencePolicyState& policyState, + SuiteType suiteType, + const TestRunSelection& selectedTestRuns, + TestRunReport&& selectedTestRunReport); + }; + + //! Report detailing a test run sequence of selected and drafted tests. + template + class DraftingSequenceReportBase + : public SequenceReportBase + { + public: + //! Constructs the report for sequences that draft in previously failed/newly added test targets. + //! @param type The type of sequence this report is generated for. + //! @param maxConcurrency The maximum number of concurrent test targets in flight at any given time. + //! @param testTargetTimeout The maximum duration individual test targets may be in flight for (infinite if empty). + //! @param globalTimeout The maximum duration the entire test sequence may run for (infinite if empty). + //! @param policyState The policy state this sequence was executed under. + //! @param suiteType The suite from which the tests have been selected from. + //! @param selectedTestRuns The target names of the selected test runs. + //! @param draftedTestRuns The target names of the drafted test runs. //! @param selectedTestRunReport The report for the set of selected test runs. //! @param draftedTestRunReport The report for the set of drafted test runs. - DraftingSequenceReport( + DraftingSequenceReportBase( + SequenceReportType type, + size_t maxConcurrency, + const AZStd::optional& testTargetTimeout, + const AZStd::optional& globalTimeout, + const PolicyStateType& policyState, SuiteType suiteType, - const TestRunSelection& selectedTests, - const AZStd::vector& draftedTests, + const TestRunSelection& selectedTestRuns, + const AZStd::vector& draftedTestRuns, TestRunReport&& selectedTestRunReport, - TestRunReport&& draftedTestRunReport); + TestRunReport&& draftedTestRunReport) + : SequenceReportBase( + type, + maxConcurrency, + testTargetTimeout, + globalTimeout, + policyState, + suiteType, + selectedTestRuns, + AZStd::move(selectedTestRunReport)) + , m_draftedTestRuns(draftedTestRuns) + , m_draftedTestRunReport(AZStd::move(draftedTestRunReport)) + { + } - // SequenceReport overrides ... - TestSequenceResult GetResult() const override; - AZStd::chrono::milliseconds GetDuration() const override; - size_t GetTotalNumPassingTests() const override; - size_t GetTotalNumFailingTests() const override; - size_t GetTotalNumTimedOutTests() const override; - size_t GetTotalNumUnexecutedTests() const override; - - //! Returns the tests drafted for running in the sequence. - const AZStd::vector& GetDraftedTests() const; + //! Returns the tests drafted for running in the sequence. + const AZStd::vector& GetDraftedTestRuns() const + { + return m_draftedTestRuns; + } //! Returns the report for the drafted test runs. - TestRunReport GetDraftedTestRunReport() const; + TestRunReport GetDraftedTestRunReport() const + { + return m_draftedTestRunReport; + } + // SequenceReport overrides ... + AZStd::chrono::milliseconds GetDuration() const override + { + return SequenceReportBase::GetDuration() + m_draftedTestRunReport.GetDuration(); + } + + TestSequenceResult GetResult() const override + { + return CalculateMultiTestSequenceResult({ SequenceReportBase::GetResult(), m_draftedTestRunReport.GetResult() }); + } + + size_t GetTotalNumTestRuns() const override + { + return SequenceReportBase::GetTotalNumTestRuns() + m_draftedTestRunReport.GetTotalNumTestRuns(); + } + + size_t GetTotalNumPassingTests() const override + { + return SequenceReportBase::GetTotalNumPassingTests() + m_draftedTestRunReport.GetTotalNumPassingTests(); + } + + size_t GetTotalNumFailingTests() const override + { + return SequenceReportBase::GetTotalNumFailingTests() + m_draftedTestRunReport.GetTotalNumFailingTests(); + } + + size_t GetTotalNumDisabledTests() const override + { + return SequenceReportBase::GetTotalNumDisabledTests() + m_draftedTestRunReport.GetTotalNumDisabledTests(); + } + + size_t GetTotalNumPassingTestRuns() const override + { + return SequenceReportBase::GetTotalNumPassingTestRuns() + m_draftedTestRunReport.GetNumPassingTestRuns(); + } + + size_t GetTotalNumFailingTestRuns() const override + { + return SequenceReportBase::GetTotalNumFailingTestRuns() + m_draftedTestRunReport.GetNumFailingTestRuns(); + } + + size_t GetTotalNumExecutionFailureTestRuns() const override + { + return SequenceReportBase::GetTotalNumExecutionFailureTestRuns() + m_draftedTestRunReport.GetNumExecutionFailureTestRuns(); + } + + size_t GetTotalNumTimedOutTestRuns() const override + { + return SequenceReportBase::GetTotalNumTimedOutTestRuns() + m_draftedTestRunReport.GetNumTimedOutTestRuns(); + } + + size_t GetTotalNumUnexecutedTestRuns() const override + { + return SequenceReportBase::GetTotalNumUnexecutedTestRuns() + m_draftedTestRunReport.GetNumUnexecutedTestRuns(); + } private: - AZStd::vector m_draftedTests; + AZStd::vector m_draftedTestRuns; TestRunReport m_draftedTestRunReport; }; //! Report detailing an impact analysis sequence of selected, discarded and drafted tests. class ImpactAnalysisSequenceReport - : public DraftingSequenceReport + : public DraftingSequenceReportBase { public: - //! Constructs the report for a sequence of selected and drafted tests. + //! Constructs the report for an impact analysis sequence. + //! @param maxConcurrency The maximum number of concurrent test targets in flight at any given time. + //! @param testTargetTimeout The maximum duration individual test targets may be in flight for (infinite if empty). + //! @param globalTimeout The maximum duration the entire test sequence may run for (infinite if empty). + //! @param policyState The policy state this sequence was executed under. //! @param suiteType The suite from which the tests have been selected from. - //! @param selectedTests The target names of the selected tests. - //! @param discardedTests The target names of the discarded tests. - //! @param draftedTests The target names of the drafted tests. + //! @param selectedTestRuns The target names of the selected test runs. + //! @param draftedTestRuns The target names of the drafted test runs. //! @param selectedTestRunReport The report for the set of selected test runs. //! @param draftedTestRunReport The report for the set of drafted test runs. ImpactAnalysisSequenceReport( + size_t maxConcurrency, + const AZStd::optional& testTargetTimeout, + const AZStd::optional& globalTimeout, + const ImpactAnalysisSequencePolicyState& policyState, SuiteType suiteType, - const TestRunSelection& selectedTests, - const AZStd::vector& discardedTests, - const AZStd::vector& draftedTests, + const TestRunSelection& selectedTestRuns, + const AZStd::vector& discardedTestRuns, + const AZStd::vector& draftedTestRuns, TestRunReport&& selectedTestRunReport, TestRunReport&& draftedTestRunReport); - //! Returns the tests discarded from running in the sequence. - const AZStd::vector& GetDiscardedTests() const; + //! Returns the test runs discarded from running in the sequence. + const AZStd::vector& GetDiscardedTestRuns() const; private: - AZStd::vector m_discardedTests; + AZStd::vector m_discardedTestRuns; }; - //! Report detailing an impact analysis sequence of selected, discarded and drafted tests. + //! Report detailing an impact analysis sequence of selected, discarded and drafted test runs. class SafeImpactAnalysisSequenceReport - : public DraftingSequenceReport + : public DraftingSequenceReportBase { public: - //! Constructs the report for a sequence of selected and drafted tests. + //! Constructs the report for a sequence of selected, discarded and drafted test runs. + //! @param maxConcurrency The maximum number of concurrent test targets in flight at any given time. + //! @param testTargetTimeout The maximum duration individual test targets may be in flight for (infinite if empty). + //! @param globalTimeout The maximum duration the entire test sequence may run for (infinite if empty). + //! @param policyState The policy state this sequence was executed under. //! @param suiteType The suite from which the tests have been selected from. - //! @param selectedTests The target names of the selected tests. - //! @param discardedTests The target names of the discarded tests. - //! @param draftedTests The target names of the drafted tests. + //! @param selectedTestRuns The target names of the selected test runs. + //! @param discardedTestRuns The target names of the discarded test runs. + //! @param draftedTestRuns The target names of the drafted test runs. //! @param selectedTestRunReport The report for the set of selected test runs. //! @param discardedTestRunReport The report for the set of discarded test runs. //! @param draftedTestRunReport The report for the set of drafted test runs. SafeImpactAnalysisSequenceReport( + size_t maxConcurrency, + const AZStd::optional& testTargetTimeout, + const AZStd::optional& globalTimeout, + const SafeImpactAnalysisSequencePolicyState& policyState, SuiteType suiteType, - const TestRunSelection& selectedTests, - const TestRunSelection& discardedTests, - const AZStd::vector& draftedTests, + const TestRunSelection& selectedTestRuns, + const TestRunSelection& discardedTestRuns, + const AZStd::vector& draftedTestRuns, TestRunReport&& selectedTestRunReport, TestRunReport&& discardedTestRunReport, TestRunReport&& draftedTestRunReport); - // DraftingSequenceReport overrides ... - TestSequenceResult GetResult() const override; + // SequenceReport overrides ... AZStd::chrono::milliseconds GetDuration() const override; + TestSequenceResult GetResult() const override; + size_t GetTotalNumTestRuns() const override; size_t GetTotalNumPassingTests() const override; size_t GetTotalNumFailingTests() const override; - size_t GetTotalNumTimedOutTests() const override; - size_t GetTotalNumUnexecutedTests() const override; + size_t GetTotalNumDisabledTests() const override; + size_t GetTotalNumPassingTestRuns() const override; + size_t GetTotalNumFailingTestRuns() const override; + size_t GetTotalNumExecutionFailureTestRuns() const override; + size_t GetTotalNumTimedOutTestRuns() const override; + size_t GetTotalNumUnexecutedTestRuns() const override; //! Returns the report for the discarded test runs. - const TestRunSelection GetDiscardedTests() const; + const TestRunSelection GetDiscardedTestRuns() const; //! Returns the report for the discarded test runs. TestRunReport GetDiscardedTestRunReport() const; private: - TestRunSelection m_discardedTests; + TestRunSelection m_discardedTestRuns; TestRunReport m_discardedTestRunReport; }; } // namespace Client diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactClientSequenceReportSerializer.h b/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactClientSequenceReportSerializer.h new file mode 100644 index 0000000000..fc226588e7 --- /dev/null +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactClientSequenceReportSerializer.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#pragma once + +#include + +#include + +namespace TestImpact +{ + //! Serializes a regular sequence report to JSON format. + AZStd::string SerializeSequenceReport(const Client::RegularSequenceReport& sequenceReport); + + //! Serializes a seed sequence report to JSON format. + AZStd::string SerializeSequenceReport(const Client::SeedSequenceReport& sequenceReport); + + //! Serializes an impact analysis sequence report to JSON format. + AZStd::string SerializeSequenceReport(const Client::ImpactAnalysisSequenceReport& sequenceReport); + + //! Serializes a safe impact analysis sequence report to JSON format. + AZStd::string SerializeSequenceReport(const Client::SafeImpactAnalysisSequenceReport& sequenceReport); +} // namespace TestImpact diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactClientTestRun.h b/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactClientTestRun.h index 4b7715bf1d..f22963b5e6 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactClientTestRun.h +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactClientTestRun.h @@ -26,8 +26,8 @@ namespace TestImpact AllTestsPass //!< The test run completed its run and all tests passed. }; - //! Representation of a completed test run. - class TestRun + //! Representation of a test run. + class TestRunBase { public: //! Constructs the client facing representation of a given test target's run. @@ -36,13 +36,15 @@ namespace TestImpact //! @param startTime The start time, relative to the sequence start, that this run started. //! @param duration The duration that this test run took to complete. //! @param result The result of the run. - TestRun( + TestRunBase( const AZStd::string& name, const AZStd::string& commandString, AZStd::chrono::high_resolution_clock::time_point startTime, AZStd::chrono::milliseconds duration, TestRunResult result); + virtual ~TestRunBase() = default; + //! Returns the test target name. const AZStd::string& GetTargetName() const; @@ -69,75 +71,120 @@ namespace TestImpact AZStd::chrono::milliseconds m_duration; }; - //! Represents an individual test of a test target that failed. - class TestFailure + //! Representation of a test run that failed to execute. + class TestRunWithExecutionFailure + : public TestRunBase { public: - TestFailure(const AZStd::string& testName, const AZStd::string& errorMessage); + using TestRunBase::TestRunBase; + TestRunWithExecutionFailure(TestRunBase&& testRun); + }; - //! Returns the name of the test that failed. + //! Representation of a test run that was terminated in-flight due to timing out. + class TimedOutTestRun + : public TestRunBase + { + public: + using TestRunBase::TestRunBase; + TimedOutTestRun(TestRunBase&& testRun); + }; + + //! Representation of a test run that was not executed. + class UnexecutedTestRun + : public TestRunBase + { + public: + using TestRunBase::TestRunBase; + UnexecutedTestRun(TestRunBase&& testRun); + }; + + // Result of a test executed during a test run. + enum class TestResult : AZ::u8 + { + Passed, + Failed, + NotRun + }; + + //! Representation of a single test in a test target. + class Test + { + public: + //! Constructs the test with the specified name and result. + Test(const AZStd::string& testName, TestResult result); + + //! Returns the name of this test. const AZStd::string& GetName() const; - //! Returns the error message of the test that failed. - const AZStd::string& GetErrorMessage() const; + //! Returns the result of executing this test. + TestResult GetResult() const; private: AZStd::string m_name; - AZStd::string m_errorMessage; + TestResult m_result; }; - //! Represents a collection of tests that failed. - //! @note Only the failing tests are included in the collection. - class TestCaseFailure + //! Representation of a test run that completed with or without test failures. + class CompletedTestRun + : public TestRunBase { public: - TestCaseFailure(const AZStd::string& testCaseName, AZStd::vector&& testFailures); - - //! Returns the name of the test case containing the failing tests. - const AZStd::string& GetName() const; - - //! Returns the collection of tests in this test case that failed. - const AZStd::vector& GetTestFailures() const; - - private: - AZStd::string m_name; - AZStd::vector m_testFailures; - }; - - //! Representation of a test run's failing tests. - class TestRunWithTestFailures - : public TestRun - { - public: - //! Constructs the client facing representation of a given test target's run. - //! @param name The name of the test target. - //! @param commandString The command string used to execute this test target. - //! @param startTime The start time, relative to the sequence start, that this run started. + //! Constructs the test run from the specified test target executaion data. + //! @param name The name of the test target for this run. + //! @param commandString The command string used to execute the test target for this run. + //! @param startTime The start time, offset from the sequence start time, that this test run started. //! @param duration The duration that this test run took to complete. - //! @param result The result of the run. - //! @param testFailures The failing tests for this test run. - TestRunWithTestFailures( + //! @param result The result of this test run. + //! @param tests The tests contained in the test target for this test run. + CompletedTestRun( const AZStd::string& name, const AZStd::string& commandString, AZStd::chrono::high_resolution_clock::time_point startTime, AZStd::chrono::milliseconds duration, TestRunResult result, - AZStd::vector&& testFailures); + AZStd::vector&& tests); - //! Constructs the client facing representation of a given test target's run. - //! @param testRun The test run this run is to be derived from. - //! @param testFailures The failing tests for this run. - TestRunWithTestFailures(TestRun&& testRun, AZStd::vector&& testFailures); + //! Constructs the test run from the specified test target executaion data. + CompletedTestRun(TestRunBase&& testRun, AZStd::vector&& tests); - //! Returns the total number of failing tests in this run. - size_t GetNumTestFailures() const; + //! Returns the total number of tests in the run. + size_t GetTotalNumTests() const; - //! Returns the test cases in this run containing failing tests. - const AZStd::vector& GetTestCaseFailures() const; + //! Returns the total number of passing tests in the run. + size_t GetTotalNumPassingTests() const; + + //! Returns the total number of failing tests in the run. + size_t GetTotalNumFailingTests() const; + + //! Returns the total number of disabled tests in the run. + size_t GetTotalNumDisabledTests() const; + + //! Returns the tests in the run. + const AZStd::vector& GetTests() const; private: - AZStd::vector m_testCaseFailures; - size_t m_numTestFailures = 0; + AZStd::vector m_tests; + size_t m_totalNumPassingTests = 0; + size_t m_totalNumFailingTests = 0; + size_t m_totalNumDisabledTests = 0; + }; + + //! Representation of a test run that completed with no test failures. + class PassingTestRun + : public CompletedTestRun + { + public: + using CompletedTestRun::CompletedTestRun; + PassingTestRun(TestRunBase&& testRun, AZStd::vector&& tests); + }; + + //! Representation of a test run that completed with one or more test failures. + class FailingTestRun + : public CompletedTestRun + { + public: + using CompletedTestRun::CompletedTestRun; + FailingTestRun(TestRunBase&& testRun, AZStd::vector&& tests); }; } // namespace Client } // namespace TestImpact diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactConfiguration.h b/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactConfiguration.h index c10c27c643..fcacd90e71 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactConfiguration.h +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactConfiguration.h @@ -44,7 +44,7 @@ namespace TestImpact { RepoPath m_root; //!< Path to the persistent workspace tracked by the repository. RepoPath m_enumerationCacheDirectory; //!< Path to the test enumerations cache. - AZStd::array m_sparTIAFiles; //!< Paths to the test impact analysis data files for each test suite. + AZStd::array m_sparTiaFiles; //!< Paths to the test impact analysis data files for each test suite. }; Temp m_temp; diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactPolicy.h b/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactPolicy.h new file mode 100644 index 0000000000..b400af018a --- /dev/null +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactPolicy.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#pragma once + +#include + +namespace TestImpact +{ + namespace Policy + { + //! Policy for handling of test targets that fail to execute (e.g. due to the binary not being found). + //! @note Test targets that fail to execute will be tagged such that their execution can be attempted at a later date. This is + //! important as otherwise it would be erroneously assumed that they cover no sources due to having no entries in the dynamic + //! dependency map. + enum class ExecutionFailure : AZ::u8 + { + Abort, //!< Abort the test sequence and report a failure. + Continue, //!< Continue the test sequence but treat the execution failures as test failures after the run. + Ignore //!< Continue the test sequence and ignore the execution failures. + }; + + //! Policy for handling the coverage data of failed tests targets (both tests that failed to execute and tests that ran but failed). + enum class FailedTestCoverage : AZ::u8 + { + Discard, //!< Discard the coverage data produced by the failing tests, causing them to be drafted into future test runs. + Keep //!< Keep any existing coverage data and update the coverage data for failed test targets that produce coverage. + }; + + //! Policy for prioritizing selected tests. + enum class TestPrioritization : AZ::u8 + { + None, //!< Do not attempt any test prioritization. + DependencyLocality //!< Prioritize test targets according to the locality of the production targets they cover in the build + //!< dependency graph. + }; + + //! Policy for handling test targets that report failing tests. + enum class TestFailure : AZ::u8 + { + Abort, //!< Abort the test sequence and report the test failure. + Continue //!< Continue the test sequence and report the test failures after the run. + }; + + //! Policy for handling integrity failures of the dynamic dependency map and the source to target mappings. + enum class IntegrityFailure : AZ::u8 + { + Abort, //!< Abort the test sequence and report the test failure. + Continue //!< Continue the test sequence and report the test failures after the run. + }; + + //! Policy for updating the dynamic dependency map with the coverage data of produced by test sequences. + enum class DynamicDependencyMap : AZ::u8 + { + Discard, //!< Discard the coverage data produced by test sequences. + Update //!< Update the dynamic dependency map with the coverage data produced by test sequences. + }; + + //! Policy for sharding test targets that have been marked for test sharding. + enum class TestSharding : AZ::u8 + { + Never, //!< Do not shard any test targets. + Always //!< Shard all test targets that have been marked for test sharding. + }; + + //! Standard output capture of test target runs. + enum class TargetOutputCapture : AZ::u8 + { + None, //!< Do not capture any output. + StdOut, //!< Send captured output to standard output + File, //!< Write captured output to file. + StdOutAndFile //!< Send captured output to standard output and write to file. + }; + + } // namespace Policy +} // namespace TestImpact diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactRuntime.h b/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactRuntime.h index 69feb48749..ec8d88eaad 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactRuntime.h +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactRuntime.h @@ -78,7 +78,7 @@ namespace TestImpact //! @param testRunMeta The test that has completed. //! @param numTestRunsCompleted The number of test runs that have completed. //! @param totalNumTestRuns The total number of test runs in the sequence. - using TestRunCompleteCallback = AZStd::function; + using TestRunCompleteCallback = AZStd::function; //! The API exposed to the client responsible for all test runs and persistent data management. class Runtime @@ -86,6 +86,7 @@ namespace TestImpact public: //! Constructs a runtime with the specified configuration and policies. //! @param config The configuration used for this runtime instance. + //! @param dataFile The optional data file to be used instead of that specified in the config file. //! @param suiteFilter The test suite for which the coverage data and test selection will draw from. //! @param executionFailurePolicy Determines how to handle test targets that fail to execute. //! @param executionFailureDraftingPolicy Determines how test targets that previously failed to execute are drafted into subsequent test sequences. @@ -94,6 +95,7 @@ namespace TestImpact //! @param testShardingPolicy Determines how to handle test targets that have opted in to test sharding. Runtime( RuntimeConfig&& config, + AZStd::optional dataFile, SuiteType suiteFilter, Policy::ExecutionFailure executionFailurePolicy, Policy::FailedTestCoverage failedTestCoveragePolicy, @@ -112,11 +114,11 @@ namespace TestImpact //! @param testSequenceCompleteCallback The client function to be called after the test sequence has completed. //! @param testRunCompleteCallback The client function to be called after an individual test run has completed. //! @returns The test run and sequence report for the selected test sequence. - Client::SequenceReport RegularTestSequence( + Client::RegularSequenceReport RegularTestSequence( AZStd::optional testTargetTimeout, AZStd::optional globalTimeout, AZStd::optional testSequenceStartCallback, - AZStd::optional> testSequenceCompleteCallback, + AZStd::optional> testSequenceCompleteCallback, AZStd::optional testRunCompleteCallback); //! Runs a test sequence where tests are selected according to test impact analysis so long as they are not on the excluded list. @@ -164,11 +166,11 @@ namespace TestImpact //! @param testSequenceCompleteCallback The client function to be called after the test sequence has completed. //! @param testRunCompleteCallback The client function to be called after an individual test run has completed. //! @returns The test run and sequence report for the selected test sequence. - Client::SequenceReport SeededTestSequence( + Client::SeedSequenceReport SeededTestSequence( AZStd::optional testTargetTimeout, AZStd::optional globalTimeout, AZStd::optional testSequenceStartCallback, - AZStd::optional> testSequenceCompleteCallback, + AZStd::optional> testSequenceCompleteCallback, AZStd::optional testRunCompleteCallback); //! Returns true if the runtime has test impact analysis data (either preexisting or generated). @@ -184,7 +186,7 @@ namespace TestImpact //! @param changeList The change list for which the covering tests and enumeration cache updates will be generated for. //! @param testPrioritizationPolicy The test prioritization strategy to use for the selected test targets. //! @returns The pair of selected test targets and discarded test targets. - AZStd::pair, AZStd::vector> SelectCoveringTestTargetsAndUpdateEnumerationCache( + AZStd::pair, AZStd::vector> SelectCoveringTestTargets( const ChangeList& changeList, Policy::TestPrioritization testPrioritizationPolicy); @@ -204,8 +206,22 @@ namespace TestImpact //! Updates the dynamic dependency map and serializes the entire map to disk. void UpdateAndSerializeDynamicDependencyMap(const AZStd::vector& jobs); + //! Generates a base policy state for the current runtime policy runtime configuration. + PolicyStateBase GeneratePolicyStateBase() const; + + //! Generates a regular/seed sequence policy state for the current runtime policy runtime configuration. + SequencePolicyState GenerateSequencePolicyState() const; + + //! Generates a safe impact analysis sequence policy state for the current runtime policy runtime configuration. + SafeImpactAnalysisSequencePolicyState GenerateSafeImpactAnalysisSequencePolicyState( + Policy::TestPrioritization testPrioritizationPolicy) const; + + //! Generates an impact analysis sequence policy state for the current runtime policy runtime configuration. + ImpactAnalysisSequencePolicyState GenerateImpactAnalysisSequencePolicyState( + Policy::TestPrioritization testPrioritizationPolicy, Policy::DynamicDependencyMap dynamicDependencyMapPolicy) const; + RuntimeConfig m_config; - RepoPath m_sparTIAFile; + RepoPath m_sparTiaFile; SuiteType m_suiteFilter; Policy::ExecutionFailure m_executionFailurePolicy; Policy::FailedTestCoverage m_failedTestCoveragePolicy; diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactSequenceReportException.h b/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactSequenceReportException.h new file mode 100644 index 0000000000..72c2d0c530 --- /dev/null +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactSequenceReportException.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#pragma once + +#include + +namespace TestImpact +{ + //! Exception for sequence report operations. + class SequenceReportException + : public Exception + { + public: + using Exception::Exception; + }; +} // namespace TestImpact diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactTestSequence.h b/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactTestSequence.h index 8841c29644..38b716398c 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactTestSequence.h +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactTestSequence.h @@ -9,76 +9,12 @@ #pragma once #include +#include #include namespace TestImpact { - namespace Policy - { - //! Policy for handling of test targets that fail to execute (e.g. due to the binary not being found). - //! @note Test targets that fail to execute will be tagged such that their execution can be attempted at a later date. This is - //! important as otherwise it would be erroneously assumed that they cover no sources due to having no entries in the dynamic - //! dependency map. - enum class ExecutionFailure - { - Abort, //!< Abort the test sequence and report a failure. - Continue, //!< Continue the test sequence but treat the execution failures as test failures after the run. - Ignore //!< Continue the test sequence and ignore the execution failures. - }; - - //! Policy for handling the coverage data of failed tests targets (both test that failed to execute and tests that ran but failed). - enum class FailedTestCoverage - { - Discard, //!< Discard the coverage data produced by the failing tests, causing them to be drafted into future test runs. - Keep //!< Keep any existing coverage data and update the coverage data for failed test targetss that produce coverage. - }; - - //! Policy for prioritizing selected tests. - enum class TestPrioritization - { - None, //!< Do not attempt any test prioritization. - DependencyLocality //!< Prioritize test targets according to the locality of the production targets they cover in the build dependency graph. - }; - - //! Policy for handling test targets that report failing tests. - enum class TestFailure - { - Abort, //!< Abort the test sequence and report the test failure. - Continue //!< Continue the test sequence and report the test failures after the run. - }; - - //! Policy for handling integrity failures of the dynamic dependency map and the source to target mappings. - enum class IntegrityFailure - { - Abort, //!< Abort the test sequence and report the test failure. - Continue //!< Continue the test sequence and report the test failures after the run. - }; - - //! Policy for updating the dynamic dependency map with the coverage data of produced by test sequences. - enum class DynamicDependencyMap - { - Discard, //!< Discard the coverage data produced by test sequences. - Update //!< Update the dynamic dependency map with the coverage data produced by test sequences. - }; - - //! Policy for sharding test targets that have been marked for test sharding. - enum class TestSharding - { - Never, //!< Do not shard any test targets. - Always //!< Shard all test targets that have been marked for test sharding. - }; - - //! Standard output capture of test target runs. - enum class TargetOutputCapture - { - None, //!< Do not capture any output. - StdOut, //!< Send captured output to standard output - File, //!< Write captured output to file. - StdOutAndFile //!< Send captured output to standard output and write to file. - }; - } - //! Configuration for test targets that opt in to test sharding. enum class ShardConfiguration { @@ -97,22 +33,6 @@ namespace TestImpact Sandbox }; - //! User-friendly names for the test suite types. - inline AZStd::string GetSuiteTypeName(SuiteType suiteType) - { - switch (suiteType) - { - case SuiteType::Main: - return "main"; - case SuiteType::Periodic: - return "periodic"; - case SuiteType::Sandbox: - return "sandbox"; - default: - throw(RuntimeException("Unexpected suite type")); - } - } - //! Result of a test sequence that was run. enum class TestSequenceResult { @@ -120,4 +40,36 @@ namespace TestImpact Failure, //!< One or more tests failed and/or timed out and/or failed to launch and/or an integrity failure was encountered. Timeout //!< The global timeout for the sequence was exceeded. }; + + //! Base representation of runtime policies. + struct PolicyStateBase + { + Policy::ExecutionFailure m_executionFailurePolicy = Policy::ExecutionFailure::Continue; + Policy::FailedTestCoverage m_failedTestCoveragePolicy = Policy::FailedTestCoverage::Keep; + Policy::TestFailure m_testFailurePolicy = Policy::TestFailure::Abort; + Policy::IntegrityFailure m_integrityFailurePolicy = Policy::IntegrityFailure::Abort; + Policy::TestSharding m_testShardingPolicy = Policy::TestSharding::Never; + Policy::TargetOutputCapture m_targetOutputCapture = Policy::TargetOutputCapture::None; + }; + + //! Representation of regular and seed sequence policies. + struct SequencePolicyState + { + PolicyStateBase m_basePolicies; + }; + + //! Representation of impact analysis sequence policies. + struct ImpactAnalysisSequencePolicyState + { + PolicyStateBase m_basePolicies; + Policy::TestPrioritization m_testPrioritizationPolicy = Policy::TestPrioritization::None; + Policy::DynamicDependencyMap m_dynamicDependencyMap = Policy::DynamicDependencyMap::Update; + }; + + //! Representation of safe impact analysis sequence policies. + struct SafeImpactAnalysisSequencePolicyState + { + PolicyStateBase m_basePolicies; + Policy::TestPrioritization m_testPrioritizationPolicy = Policy::TestPrioritization::None; + }; } // namespace TestImpact diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactFileUtils.h b/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactUtils.h similarity index 51% rename from Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactFileUtils.h rename to Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactUtils.h index f77008ffa7..c4625e9d2c 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactFileUtils.h +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactUtils.h @@ -6,12 +6,12 @@ * */ -#include -#include +#include +#include +#include #include #include -#include #pragma once @@ -59,23 +59,48 @@ namespace TestImpact //! Delete the files that match the pattern from the specified directory. //! @param path The path to the directory to pattern match the files for deletion. //! @param pattern The pattern to match files for deletion. - inline void DeleteFiles(const RepoPath& path, const AZStd::string& pattern) - { - AZ::IO::SystemFile::FindFiles(AZStd::string::format("%s/%s", path.c_str(), pattern.c_str()).c_str(), - [&path](const char* file, bool isFile) - { - if (isFile) - { - AZ::IO::SystemFile::Delete(AZStd::string::format("%s/%s", path.c_str(), file).c_str()); - } - - return true; - }); - } + //! @return The number of files that were deleted. + size_t DeleteFiles(const RepoPath& path, const AZStd::string& pattern); //! Deletes the specified file. - inline void DeleteFile(const RepoPath& file) - { - DeleteFiles(file.ParentPath(), file.Filename().Native()); - } + void DeleteFile(const RepoPath& file); + + //! User-friendly names for the test suite types. + AZStd::string SuiteTypeAsString(SuiteType suiteType); + + //! User-friendly names for the sequence report types. + AZStd::string SequenceReportTypeAsString(Client::SequenceReportType type); + + //! User-friendly names for the sequence result types. + AZStd::string TestSequenceResultAsString(TestSequenceResult result); + + //! User-friendly names for the test run result types. + AZStd::string TestRunResultAsString(Client::TestRunResult result); + + //! User-friendly names for the execution failure policy types. + AZStd::string ExecutionFailurePolicyAsString(Policy::ExecutionFailure executionFailurePolicy); + + //! User-friendly names for the failed test coverage policy types. + AZStd::string FailedTestCoveragePolicyAsString(Policy::FailedTestCoverage failedTestCoveragePolicy); + + //! User-friendly names for the test prioritization policy types. + AZStd::string TestPrioritizationPolicyAsString(Policy::TestPrioritization testPrioritizationPolicy); + + //! User-friendly names for the test failure policy types. + AZStd::string TestFailurePolicyAsString(Policy::TestFailure testFailurePolicy); + + //! User-friendly names for the integrity failure policy types. + AZStd::string IntegrityFailurePolicyAsString(Policy::IntegrityFailure integrityFailurePolicy); + + //! User-friendly names for the dynamic dependency map policy types. + AZStd::string DynamicDependencyMapPolicyAsString(Policy::DynamicDependencyMap dynamicDependencyMapPolicy); + + //! User-friendly names for the test sharding policy types. + AZStd::string TestShardingPolicyAsString(Policy::TestSharding testShardingPolicy); + + //! User-friendly names for the target output capture policy types. + AZStd::string TargetOutputCapturePolicyAsString(Policy::TargetOutputCapture targetOutputCapturePolicy); + + //! User-friendly names for the client test result types. + AZStd::string ClientTestResultAsString(Client::TestResult result); } // namespace TestImpact diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Source/Artifact/Factory/TestImpactTestTargetMetaMapFactory.cpp b/Code/Tools/TestImpactFramework/Runtime/Code/Source/Artifact/Factory/TestImpactTestTargetMetaMapFactory.cpp index d69177814f..4c8d71bba1 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Source/Artifact/Factory/TestImpactTestTargetMetaMapFactory.cpp +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Source/Artifact/Factory/TestImpactTestTargetMetaMapFactory.cpp @@ -6,6 +6,8 @@ * */ +#include + #include #include @@ -67,7 +69,7 @@ namespace TestImpact { // Check to see if this test target has the suite we're looking for if (const auto suiteName = suite[Keys[SuiteKey]].GetString(); - strcmp(GetSuiteTypeName(suiteType).c_str(), suiteName) == 0) + strcmp(SuiteTypeAsString(suiteType).c_str(), suiteName) == 0) { testMeta.m_suite = suiteName; testMeta.m_customArgs = suite[Keys[CommandKey]].GetString(); diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Source/Dependency/TestImpactDynamicDependencyMap.cpp b/Code/Tools/TestImpactFramework/Runtime/Code/Source/Dependency/TestImpactDynamicDependencyMap.cpp index 1c79494c30..af32171b2b 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Source/Dependency/TestImpactDynamicDependencyMap.cpp +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Source/Dependency/TestImpactDynamicDependencyMap.cpp @@ -156,8 +156,6 @@ namespace TestImpact { coveringTestTargetIt->second.erase(source); } - - } // 2. diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Source/Dependency/TestImpactDynamicDependencyMap.h b/Code/Tools/TestImpactFramework/Runtime/Code/Source/Dependency/TestImpactDynamicDependencyMap.h index 5309a00894..d63938930f 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Source/Dependency/TestImpactDynamicDependencyMap.h +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Source/Dependency/TestImpactDynamicDependencyMap.h @@ -9,7 +9,7 @@ #pragma once #include -#include +#include #include #include diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Source/Dependency/TestImpactTestSelectorAndPrioritizer.h b/Code/Tools/TestImpactFramework/Runtime/Code/Source/Dependency/TestImpactTestSelectorAndPrioritizer.h index 4f266af8d2..bcfd8d24d5 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Source/Dependency/TestImpactTestSelectorAndPrioritizer.h +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Source/Dependency/TestImpactTestSelectorAndPrioritizer.h @@ -8,7 +8,7 @@ #pragma once -#include +#include #include #include diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Enumeration/TestImpactTestEnumerator.cpp b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Enumeration/TestImpactTestEnumerator.cpp index c2ba00835a..e564b93f6c 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Enumeration/TestImpactTestEnumerator.cpp +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Enumeration/TestImpactTestEnumerator.cpp @@ -6,7 +6,7 @@ * */ -#include +#include #include #include diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Run/TestImpactInstrumentedTestRunner.cpp b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Run/TestImpactInstrumentedTestRunner.cpp index cad8df1449..bf7e4d2c34 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Run/TestImpactInstrumentedTestRunner.cpp +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Run/TestImpactInstrumentedTestRunner.cpp @@ -6,7 +6,7 @@ * */ -#include +#include #include #include diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Run/TestImpactTestRunner.cpp b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Run/TestImpactTestRunner.cpp index a138e329b6..a480f4aa4a 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Run/TestImpactTestRunner.cpp +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Run/TestImpactTestRunner.cpp @@ -6,7 +6,7 @@ * */ -#include +#include #include #include diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/TestImpactTestEngine.cpp b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/TestImpactTestEngine.cpp index 226301d444..c84700065f 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/TestImpactTestEngine.cpp +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/TestImpactTestEngine.cpp @@ -6,7 +6,7 @@ * */ -#include +#include #include #include diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactClientSequenceReport.cpp b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactClientSequenceReport.cpp index ba3a479fdf..3f4656758a 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactClientSequenceReport.cpp +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactClientSequenceReport.cpp @@ -1,6 +1,7 @@ /* - * Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. - * + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * * SPDX-License-Identifier: Apache-2.0 OR MIT * */ @@ -11,7 +12,6 @@ namespace TestImpact { namespace Client { - //! Calculates the final sequence result for a composite of multiple sequences. TestSequenceResult CalculateMultiTestSequenceResult(const AZStd::vector& results) { // Order of precedence: @@ -19,14 +19,12 @@ namespace TestImpact // 2. TestSequenceResult::Timeout // 3. TestSequenceResult::Success - if (const auto it = AZStd::find(results.begin(), results.end(), TestSequenceResult::Failure); - it != results.end()) + if (const auto it = AZStd::find(results.begin(), results.end(), TestSequenceResult::Failure); it != results.end()) { return TestSequenceResult::Failure; } - - if (const auto it = AZStd::find(results.begin(), results.end(), TestSequenceResult::Timeout); - it != results.end()) + + if (const auto it = AZStd::find(results.begin(), results.end(), TestSequenceResult::Timeout); it != results.end()) { return TestSequenceResult::Timeout; } @@ -38,20 +36,32 @@ namespace TestImpact TestSequenceResult result, AZStd::chrono::high_resolution_clock::time_point startTime, AZStd::chrono::milliseconds duration, - AZStd::vector&& passingTests, - AZStd::vector&& failingTests, - AZStd::vector&& executionFailureTests, - AZStd::vector&& timedOutTests, - AZStd::vector&& unexecutedTests) + AZStd::vector&& passingTestRuns, + AZStd::vector&& failingTestRuns, + AZStd::vector&& executionFailureTestRuns, + AZStd::vector&& timedOutTestRuns, + AZStd::vector&& unexecutedTestRuns) : m_startTime(startTime) , m_result(result) , m_duration(duration) - , m_passingTests(AZStd::move(passingTests)) - , m_failingTests(AZStd::move(failingTests)) - , m_executionFailureTests(AZStd::move(executionFailureTests)) - , m_timedOutTests(AZStd::move(timedOutTests)) - , m_unexecutedTests(AZStd::move(unexecutedTests)) + , m_passingTestRuns(AZStd::move(passingTestRuns)) + , m_failingTestRuns(AZStd::move(failingTestRuns)) + , m_executionFailureTestRuns(AZStd::move(executionFailureTestRuns)) + , m_timedOutTestRuns(AZStd::move(timedOutTestRuns)) + , m_unexecutedTestRuns(AZStd::move(unexecutedTestRuns)) { + for (const auto& failingTestRun : m_failingTestRuns) + { + m_totalNumPassingTests += failingTestRun.GetTotalNumPassingTests(); + m_totalNumFailingTests += failingTestRun.GetTotalNumFailingTests(); + m_totalNumDisabledTests += failingTestRun.GetTotalNumDisabledTests(); + } + + for (const auto& passingTestRun : m_passingTestRuns) + { + m_totalNumPassingTests += passingTestRun.GetTotalNumPassingTests(); + m_totalNumDisabledTests += passingTestRun.GetTotalNumDisabledTests(); + } } TestSequenceResult TestRunReport::GetResult() const @@ -74,234 +84,238 @@ namespace TestImpact return m_duration; } - size_t TestRunReport::GetNumPassingTests() const + size_t TestRunReport::GetTotalNumTestRuns() const { - return m_passingTests.size(); + return + GetNumPassingTestRuns() + + GetNumFailingTestRuns() + + GetNumExecutionFailureTestRuns() + + GetNumTimedOutTestRuns() + + GetNumUnexecutedTestRuns(); } - size_t TestRunReport::GetNumFailingTests() const + size_t TestRunReport::GetNumPassingTestRuns() const { - return m_failingTests.size(); + return m_passingTestRuns.size(); } - size_t TestRunReport::GetNumTimedOutTests() const + size_t TestRunReport::GetNumFailingTestRuns() const { - return m_timedOutTests.size(); + return m_failingTestRuns.size(); } - size_t TestRunReport::GetNumUnexecutedTests() const + size_t TestRunReport::GetNumExecutionFailureTestRuns() const { - return m_unexecutedTests.size(); + return m_executionFailureTestRuns.size(); } - const AZStd::vector& TestRunReport::GetPassingTests() const + size_t TestRunReport::TestRunReport::GetNumTimedOutTestRuns() const { - return m_passingTests; + return m_timedOutTestRuns.size(); } - const AZStd::vector& TestRunReport::GetFailingTests() const + size_t TestRunReport::GetNumUnexecutedTestRuns() const { - return m_failingTests; + return m_unexecutedTestRuns.size(); } - const AZStd::vector& TestRunReport::GetExecutionFailureTests() const + const AZStd::vector& TestRunReport::GetPassingTestRuns() const { - return m_executionFailureTests; + return m_passingTestRuns; } - const AZStd::vector& TestRunReport::GetTimedOutTests() const + const AZStd::vector& TestRunReport::GetFailingTestRuns() const { - return m_timedOutTests; + return m_failingTestRuns; } - const AZStd::vector& TestRunReport::GetUnexecutedTests() const + const AZStd::vector& TestRunReport::GetExecutionFailureTestRuns() const { - return m_unexecutedTests; + return m_executionFailureTestRuns; } - SequenceReport::SequenceReport(SuiteType suiteType, const TestRunSelection& selectedTests, TestRunReport&& selectedTestRunReport) - : m_suite(suiteType) - , m_selectedTests(selectedTests) - , m_selectedTestRunReport(AZStd::move(selectedTestRunReport)) + const AZStd::vector& TestRunReport::GetTimedOutTestRuns() const { + return m_timedOutTestRuns; } - TestSequenceResult SequenceReport::GetResult() const + const AZStd::vector& TestRunReport::GetUnexecutedTestRuns() const { - return m_selectedTestRunReport.GetResult(); + return m_unexecutedTestRuns; } - AZStd::chrono::high_resolution_clock::time_point SequenceReport::GetStartTime() const + size_t TestRunReport::GetTotalNumPassingTests() const { - return m_selectedTestRunReport.GetStartTime(); + return m_totalNumPassingTests; } - AZStd::chrono::high_resolution_clock::time_point SequenceReport::GetEndTime() const + size_t TestRunReport::GetTotalNumFailingTests() const { - return GetStartTime() + GetDuration(); + return m_totalNumFailingTests; } - AZStd::chrono::milliseconds SequenceReport::GetDuration() const + size_t TestRunReport::GetTotalNumDisabledTests() const { - return m_selectedTestRunReport.GetDuration(); + return m_totalNumDisabledTests; } - TestRunSelection SequenceReport::GetSelectedTests() const - { - return m_selectedTests; - } - - TestRunReport SequenceReport::GetSelectedTestRunReport() const - { - return m_selectedTestRunReport; - } - - size_t SequenceReport::GetTotalNumPassingTests() const - { - return m_selectedTestRunReport.GetNumPassingTests(); - } - - size_t SequenceReport::GetTotalNumFailingTests() const - { - return m_selectedTestRunReport.GetNumFailingTests(); - } - - size_t SequenceReport::GetTotalNumTimedOutTests() const - { - return m_selectedTestRunReport.GetNumTimedOutTests(); - } - - size_t SequenceReport::GetTotalNumUnexecutedTests() const - { - return m_selectedTestRunReport.GetNumUnexecutedTests(); - } - - DraftingSequenceReport::DraftingSequenceReport( + RegularSequenceReport::RegularSequenceReport( + size_t maxConcurrency, + const AZStd::optional& testTargetTimeout, + const AZStd::optional& globalTimeout, + const SequencePolicyState& policyState, SuiteType suiteType, - const TestRunSelection& selectedTests, - const AZStd::vector& draftedTests, - TestRunReport&& selectedTestRunReport, - TestRunReport&& draftedTestRunReport) - : SequenceReport(suiteType, selectedTests, AZStd::move(selectedTestRunReport)) - , m_draftedTests(draftedTests) - , m_draftedTestRunReport(AZStd::move(draftedTestRunReport)) + const TestRunSelection& selectedTestRuns, + TestRunReport&& selectedTestRunReport) + : SequenceReportBase( + SequenceReportType::RegularSequence, + maxConcurrency, + testTargetTimeout, + globalTimeout, + policyState, + suiteType, + selectedTestRuns, + AZStd::move(selectedTestRunReport)) { } - TestSequenceResult DraftingSequenceReport::GetResult() const + SeedSequenceReport::SeedSequenceReport( + size_t maxConcurrency, + const AZStd::optional& testTargetTimeout, + const AZStd::optional& globalTimeout, + const SequencePolicyState& policyState, + SuiteType suiteType, + const TestRunSelection& selectedTestRuns, + TestRunReport&& selectedTestRunReport) + : SequenceReportBase( + SequenceReportType::SeedSequence, + maxConcurrency, + testTargetTimeout, + globalTimeout, + policyState, + suiteType, + selectedTestRuns, + AZStd::move(selectedTestRunReport)) { - return CalculateMultiTestSequenceResult({SequenceReport::GetResult(), m_draftedTestRunReport.GetResult()}); - } - - AZStd::chrono::milliseconds DraftingSequenceReport::GetDuration() const - { - return SequenceReport::GetDuration() + m_draftedTestRunReport.GetDuration(); - } - - size_t DraftingSequenceReport::GetTotalNumPassingTests() const - { - return SequenceReport::GetTotalNumPassingTests() + m_draftedTestRunReport.GetNumPassingTests(); - } - - size_t DraftingSequenceReport::GetTotalNumFailingTests() const - { - return SequenceReport::GetTotalNumFailingTests() + m_draftedTestRunReport.GetNumFailingTests(); - } - - size_t DraftingSequenceReport::GetTotalNumTimedOutTests() const - { - return SequenceReport::GetTotalNumTimedOutTests() + m_draftedTestRunReport.GetNumTimedOutTests(); - } - - size_t DraftingSequenceReport::GetTotalNumUnexecutedTests() const - { - return SequenceReport::GetTotalNumUnexecutedTests() + m_draftedTestRunReport.GetNumUnexecutedTests(); - } - - const AZStd::vector& DraftingSequenceReport::GetDraftedTests() const - { - return m_draftedTests; - } - - TestRunReport DraftingSequenceReport::GetDraftedTestRunReport() const - { - return m_draftedTestRunReport; } ImpactAnalysisSequenceReport::ImpactAnalysisSequenceReport( + size_t maxConcurrency, + const AZStd::optional& testTargetTimeout, + const AZStd::optional& globalTimeout, + const ImpactAnalysisSequencePolicyState& policyState, SuiteType suiteType, - const TestRunSelection& selectedTests, - const AZStd::vector& discardedTests, - const AZStd::vector& draftedTests, + const TestRunSelection& selectedTestRuns, + const AZStd::vector& discardedTestRuns, + const AZStd::vector& draftedTestRuns, TestRunReport&& selectedTestRunReport, TestRunReport&& draftedTestRunReport) - : DraftingSequenceReport( - suiteType, - selectedTests, - draftedTests, - AZStd::move(selectedTestRunReport), - AZStd::move(draftedTestRunReport)) - , m_discardedTests(discardedTests) + : DraftingSequenceReportBase( + SequenceReportType::ImpactAnalysisSequence, + maxConcurrency, + testTargetTimeout, + globalTimeout, + policyState, + suiteType, + selectedTestRuns, + draftedTestRuns, + AZStd::move(selectedTestRunReport), + AZStd::move(draftedTestRunReport)) + , m_discardedTestRuns(discardedTestRuns) { } - const AZStd::vector& ImpactAnalysisSequenceReport::GetDiscardedTests() const + const AZStd::vector& ImpactAnalysisSequenceReport::GetDiscardedTestRuns() const { - return m_discardedTests; + return m_discardedTestRuns; } SafeImpactAnalysisSequenceReport::SafeImpactAnalysisSequenceReport( + size_t maxConcurrency, + const AZStd::optional& testTargetTimeout, + const AZStd::optional& globalTimeout, + const SafeImpactAnalysisSequencePolicyState& policyState, SuiteType suiteType, - const TestRunSelection& selectedTests, - const TestRunSelection& discardedTests, - const AZStd::vector& draftedTests, + const TestRunSelection& selectedTestRuns, + const TestRunSelection& discardedTestRuns, + const AZStd::vector& draftedTestRuns, TestRunReport&& selectedTestRunReport, TestRunReport&& discardedTestRunReport, TestRunReport&& draftedTestRunReport) - : DraftingSequenceReport( - suiteType, - selectedTests, - draftedTests, - AZStd::move(selectedTestRunReport), - AZStd::move(draftedTestRunReport)) - , m_discardedTests(discardedTests) + : DraftingSequenceReportBase( + SequenceReportType::SafeImpactAnalysisSequence, + maxConcurrency, + testTargetTimeout, + globalTimeout, + policyState, + suiteType, + selectedTestRuns, + draftedTestRuns, + AZStd::move(selectedTestRunReport), + AZStd::move(draftedTestRunReport)) + , m_discardedTestRuns(discardedTestRuns) , m_discardedTestRunReport(AZStd::move(discardedTestRunReport)) { } TestSequenceResult SafeImpactAnalysisSequenceReport::GetResult() const { - return CalculateMultiTestSequenceResult({ DraftingSequenceReport::GetResult(), m_discardedTestRunReport.GetResult() }); + return CalculateMultiTestSequenceResult({ DraftingSequenceReportBase::GetResult(), m_discardedTestRunReport.GetResult() }); } AZStd::chrono::milliseconds SafeImpactAnalysisSequenceReport::GetDuration() const { - return DraftingSequenceReport::GetDuration() + m_discardedTestRunReport.GetDuration(); + return DraftingSequenceReportBase::GetDuration() + m_discardedTestRunReport.GetDuration(); + } + + size_t SafeImpactAnalysisSequenceReport::GetTotalNumTestRuns() const + { + return DraftingSequenceReportBase::GetTotalNumTestRuns() + m_discardedTestRunReport.GetTotalNumTestRuns(); } size_t SafeImpactAnalysisSequenceReport::GetTotalNumPassingTests() const { - return DraftingSequenceReport::GetTotalNumPassingTests() + m_discardedTestRunReport.GetNumPassingTests(); + return DraftingSequenceReportBase::GetTotalNumPassingTests() + m_discardedTestRunReport.GetTotalNumPassingTests(); } size_t SafeImpactAnalysisSequenceReport::GetTotalNumFailingTests() const { - return DraftingSequenceReport::GetTotalNumFailingTests() + m_discardedTestRunReport.GetNumFailingTests(); + return DraftingSequenceReportBase::GetTotalNumFailingTests() + m_discardedTestRunReport.GetTotalNumFailingTests(); } - size_t SafeImpactAnalysisSequenceReport::GetTotalNumTimedOutTests() const + size_t SafeImpactAnalysisSequenceReport::GetTotalNumDisabledTests() const { - return DraftingSequenceReport::GetTotalNumTimedOutTests() + m_discardedTestRunReport.GetNumTimedOutTests(); + return DraftingSequenceReportBase::GetTotalNumDisabledTests() + m_discardedTestRunReport.GetTotalNumDisabledTests(); } - size_t SafeImpactAnalysisSequenceReport::GetTotalNumUnexecutedTests() const + size_t SafeImpactAnalysisSequenceReport::GetTotalNumPassingTestRuns() const { - return DraftingSequenceReport::GetTotalNumUnexecutedTests() + m_discardedTestRunReport.GetNumUnexecutedTests(); + return DraftingSequenceReportBase::GetTotalNumPassingTestRuns() + m_discardedTestRunReport.GetNumPassingTestRuns(); + } + + size_t SafeImpactAnalysisSequenceReport::GetTotalNumFailingTestRuns() const + { + return DraftingSequenceReportBase::GetTotalNumFailingTestRuns() + m_discardedTestRunReport.GetNumFailingTestRuns(); + } + + size_t SafeImpactAnalysisSequenceReport::GetTotalNumExecutionFailureTestRuns() const + { + return DraftingSequenceReportBase::GetTotalNumExecutionFailureTestRuns() + m_discardedTestRunReport.GetNumExecutionFailureTestRuns(); + } + + size_t SafeImpactAnalysisSequenceReport::GetTotalNumTimedOutTestRuns() const + { + return DraftingSequenceReportBase::GetTotalNumTimedOutTestRuns() + m_discardedTestRunReport.GetNumTimedOutTestRuns(); + } + + size_t SafeImpactAnalysisSequenceReport::GetTotalNumUnexecutedTestRuns() const + { + return DraftingSequenceReportBase::GetTotalNumUnexecutedTestRuns() + m_discardedTestRunReport.GetNumUnexecutedTestRuns(); } - const TestRunSelection SafeImpactAnalysisSequenceReport::GetDiscardedTests() const + const TestRunSelection SafeImpactAnalysisSequenceReport::GetDiscardedTestRuns() const { - return m_discardedTests; + return m_discardedTestRuns; } TestRunReport SafeImpactAnalysisSequenceReport::GetDiscardedTestRunReport() const diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactClientSequenceReportSerializer.cpp b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactClientSequenceReportSerializer.cpp new file mode 100644 index 0000000000..99a187fe16 --- /dev/null +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactClientSequenceReportSerializer.cpp @@ -0,0 +1,606 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include +#include + +#include +#include +#include +#include + +namespace TestImpact +{ + namespace + { + namespace SequenceReportFields + { + // Keys for pertinent JSON node and attribute names + constexpr const char* Keys[] = + { + "name", + "command_args", + "start_time", + "end_time", + "duration", + "result", + "num_passing_tests", + "num_failing_tests", + "num_disabled_tests", + "tests", + "num_passing_test_runs", + "num_failing_test_runs", + "num_execution_failure_test_runs", + "num_timed_out_test_runs", + "num_unexecuted_test_runs", + "passing_test_runs", + "failing_test_runs", + "execution_failure_test_runs", + "timed_out_test_runs", + "unexecuted_test_runs", + "total_num_passing_tests", + "total_num_failing_tests", + "total_num_disabled_tests", + "total_num_test_runs", + "num_included_test_runs", + "num_excluded_test_runs", + "included_test_runs", + "excluded_test_runs", + "execution_failure", + "coverage_failure", + "test_failure", + "integrity_failure", + "test_sharding", + "target_output_capture", + "test_prioritization", + "dynamic_dependency_map", + "type", + "test_target_timeout", + "global_timeout", + "max_concurrency", + "policy", + "suite", + "selected_test_runs", + "selected_test_run_report", + "total_num_passing_test_runs", + "total_num_failing_test_runs", + "total_num_execution_failure_test_runs", + "total_num_timed_out_test_runs", + "total_num_unexecuted_test_runs", + "drafted_test_runs", + "drafted_test_run_report", + "discarded_test_runs", + "discarded_test_run_report" + }; + + enum + { + Name, + CommandArgs, + StartTime, + EndTime, + Duration, + Result, + NumPassingTests, + NumFailingTests, + NumDisabledTests, + Tests, + NumPassingTestRuns, + NumFailingTestRuns, + NumExecutionFailureTestRuns, + NumTimedOutTestRuns, + NumUnexecutedTestRuns, + PassingTestRuns, + FailingTestRuns, + ExecutionFailureTestRuns, + TimedOutTestRuns, + UnexecutedTestRuns, + TotalNumPassingTests, + TotalNumFailingTests, + TotalNumDisabledTests, + TotalNumTestRuns, + NumIncludedTestRuns, + NumExcludedTestRuns, + IncludedTestRuns, + ExcludedTestRuns, + ExecutionFailure, + CoverageFailure, + TestFailure, + IntegrityFailure, + TestSharding, + TargetOutputCapture, + TestPrioritization, + DynamicDependencyMap, + Type, + TestTargetTimeout, + GlobalTimeout, + MaxConcurrency, + Policy, + Suite, + SelectedTestRuns, + SelectedTestRunReport, + TotalNumPassingTestRuns, + TotalNumFailingTestRuns, + TotalNumExecutionFailureTestRuns, + TotalNumTimedOutTestRuns, + TotalNumUnexecutedTestRuns, + DraftedTestRuns, + DraftedTestRunReport, + DiscardedTestRuns, + DiscardedTestRunReport + }; + } // namespace SequenceReportFields + + AZ::u64 TimePointInMsAsInt64(AZStd::chrono::high_resolution_clock::time_point timePoint) + { + return AZStd::chrono::duration_cast(timePoint.time_since_epoch()).count(); + } + + void SerializeTestRunMembers(const Client::TestRunBase& testRun, rapidjson::PrettyWriter& writer) + { + // Name + writer.Key(SequenceReportFields::Keys[SequenceReportFields::Name]); + writer.String(testRun.GetTargetName().c_str()); + + // Command string + writer.Key(SequenceReportFields::Keys[SequenceReportFields::CommandArgs]); + writer.String(testRun.GetCommandString().c_str()); + + // Start time + writer.Key(SequenceReportFields::Keys[SequenceReportFields::StartTime]); + writer.Int64(TimePointInMsAsInt64(testRun.GetStartTime())); + + // End time + writer.Key(SequenceReportFields::Keys[SequenceReportFields::EndTime]); + writer.Int64(TimePointInMsAsInt64(testRun.GetEndTime())); + + // Duration + writer.Key(SequenceReportFields::Keys[SequenceReportFields::Duration]); + writer.Uint64(testRun.GetDuration().count()); + + // Result + writer.Key(SequenceReportFields::Keys[SequenceReportFields::Result]); + writer.String(TestRunResultAsString(testRun.GetResult()).c_str()); + } + + void SerializeTestRun(const Client::TestRunBase& testRun, rapidjson::PrettyWriter& writer) + { + writer.StartObject(); + { + SerializeTestRunMembers(testRun, writer); + } + writer.EndObject(); + } + + void SerializeCompletedTestRun(const Client::CompletedTestRun& testRun, rapidjson::PrettyWriter& writer) + { + writer.StartObject(); + { + SerializeTestRunMembers(testRun, writer); + + // Number of passing test cases + writer.Key(SequenceReportFields::Keys[SequenceReportFields::NumPassingTests]); + writer.Uint64(testRun.GetTotalNumPassingTests()); + + // Number of failing test cases + writer.Key(SequenceReportFields::Keys[SequenceReportFields::NumFailingTests]); + writer.Uint64(testRun.GetTotalNumFailingTests()); + + // Number of disabled test cases + writer.Key(SequenceReportFields::Keys[SequenceReportFields::NumDisabledTests]); + writer.Uint64(testRun.GetTotalNumDisabledTests()); + + // Tests + writer.Key(SequenceReportFields::Keys[SequenceReportFields::Tests]); + writer.StartArray(); + + for (const auto& test : testRun.GetTests()) + { + // Test + writer.StartObject(); + + // Name + writer.Key(SequenceReportFields::Keys[SequenceReportFields::Name]); + writer.String(test.GetName().c_str()); + + // Result + writer.Key(SequenceReportFields::Keys[SequenceReportFields::Result]); + writer.String(ClientTestResultAsString(test.GetResult()).c_str()); + + writer.EndObject(); // Test + } + + writer.EndArray(); // Tests + } + writer.EndObject(); + } + + void SerializeTestRunReport( + const Client::TestRunReport& testRunReport, rapidjson::PrettyWriter& writer) + { + writer.StartObject(); + { + // Result + writer.Key(SequenceReportFields::Keys[SequenceReportFields::Result]); + writer.String(TestSequenceResultAsString(testRunReport.GetResult()).c_str()); + + // Start time + writer.Key(SequenceReportFields::Keys[SequenceReportFields::StartTime]); + writer.Int64(TimePointInMsAsInt64(testRunReport.GetStartTime())); + + // End time + writer.Key(SequenceReportFields::Keys[SequenceReportFields::EndTime]); + writer.Int64(TimePointInMsAsInt64(testRunReport.GetEndTime())); + + // Duration + writer.Key(SequenceReportFields::Keys[SequenceReportFields::Duration]); + writer.Uint64(testRunReport.GetDuration().count()); + + // Number of passing test runs + writer.Key(SequenceReportFields::Keys[SequenceReportFields::NumPassingTestRuns]); + writer.Uint64(testRunReport.GetNumPassingTestRuns()); + + // Number of failing test runs + writer.Key(SequenceReportFields::Keys[SequenceReportFields::NumFailingTestRuns]); + writer.Uint64(testRunReport.GetNumFailingTestRuns()); + + // Number of test runs that failed to execute + writer.Key(SequenceReportFields::Keys[SequenceReportFields::NumExecutionFailureTestRuns]); + writer.Uint64(testRunReport.GetNumExecutionFailureTestRuns()); + + // Number of timed out test runs + writer.Key(SequenceReportFields::Keys[SequenceReportFields::NumTimedOutTestRuns]); + writer.Uint64(testRunReport.GetNumTimedOutTestRuns()); + + // Number of unexecuted test runs + writer.Key(SequenceReportFields::Keys[SequenceReportFields::NumUnexecutedTestRuns]); + writer.Uint64(testRunReport.GetNumUnexecutedTestRuns()); + + // Passing test runs + writer.Key(SequenceReportFields::Keys[SequenceReportFields::PassingTestRuns]); + writer.StartArray(); + for (const auto& testRun : testRunReport.GetPassingTestRuns()) + { + SerializeCompletedTestRun(testRun, writer); + } + writer.EndArray(); // Passing test runs + + // Failing test runs + writer.Key(SequenceReportFields::Keys[SequenceReportFields::FailingTestRuns]); + writer.StartArray(); + for (const auto& testRun : testRunReport.GetFailingTestRuns()) + { + SerializeCompletedTestRun(testRun, writer); + } + writer.EndArray(); // Failing test runs + + // Execution failures + writer.Key(SequenceReportFields::Keys[SequenceReportFields::ExecutionFailureTestRuns]); + writer.StartArray(); + for (const auto& testRun : testRunReport.GetExecutionFailureTestRuns()) + { + SerializeTestRun(testRun, writer); + } + writer.EndArray(); // Execution failures + + // Timed out test runs + writer.Key(SequenceReportFields::Keys[SequenceReportFields::TimedOutTestRuns]); + writer.StartArray(); + for (const auto& testRun : testRunReport.GetTimedOutTestRuns()) + { + SerializeTestRun(testRun, writer); + } + writer.EndArray(); // Timed out test runs + + // Unexecuted test runs + writer.Key(SequenceReportFields::Keys[SequenceReportFields::UnexecutedTestRuns]); + writer.StartArray(); + for (const auto& testRun : testRunReport.GetUnexecutedTestRuns()) + { + SerializeTestRun(testRun, writer); + } + writer.EndArray(); // Unexecuted test runs + + // Number of passing tests + writer.Key(SequenceReportFields::Keys[SequenceReportFields::TotalNumPassingTests]); + writer.Uint64(testRunReport.GetTotalNumPassingTests()); + + // Number of failing tests + writer.Key(SequenceReportFields::Keys[SequenceReportFields::TotalNumFailingTests]); + writer.Uint64(testRunReport.GetTotalNumFailingTests()); + + // Number of disabled tests + writer.Key(SequenceReportFields::Keys[SequenceReportFields::TotalNumDisabledTests]); + writer.Uint64(testRunReport.GetTotalNumDisabledTests()); + } + writer.EndObject(); + } + + void SerializeTestSelection( + const Client::TestRunSelection& testSelection, rapidjson::PrettyWriter& writer) + { + writer.StartObject(); + { + // Total number of test runs + writer.Key(SequenceReportFields::Keys[SequenceReportFields::TotalNumTestRuns]); + writer.Uint64(testSelection.GetTotalNumTests()); + + // Number of included test runs + writer.Key(SequenceReportFields::Keys[SequenceReportFields::NumIncludedTestRuns]); + writer.Uint64(testSelection.GetNumIncludedTestRuns()); + + // Number of excluded test runs + writer.Key(SequenceReportFields::Keys[SequenceReportFields::NumExcludedTestRuns]); + writer.Uint64(testSelection.GetNumExcludedTestRuns()); + + // Included test runs + writer.Key(SequenceReportFields::Keys[SequenceReportFields::IncludedTestRuns]); + writer.StartArray(); + for (const auto& testRun : testSelection.GetIncludededTestRuns()) + { + writer.String(testRun.c_str()); + } + writer.EndArray(); // Included test runs + + // Excluded test runs + writer.Key(SequenceReportFields::Keys[SequenceReportFields::ExcludedTestRuns]); + writer.StartArray(); + for (const auto& testRun : testSelection.GetExcludedTestRuns()) + { + writer.String(testRun.c_str()); + } + writer.EndArray(); // Excluded test runs + } + writer.EndObject(); + } + + void SerializePolicyStateBaseMembers(const PolicyStateBase& policyState, rapidjson::PrettyWriter& writer) + { + // Execution failure + writer.Key(SequenceReportFields::Keys[SequenceReportFields::ExecutionFailure]); + writer.String(ExecutionFailurePolicyAsString(policyState.m_executionFailurePolicy).c_str()); + + // Failed test coverage + writer.Key(SequenceReportFields::Keys[SequenceReportFields::CoverageFailure]); + writer.String(FailedTestCoveragePolicyAsString(policyState.m_failedTestCoveragePolicy).c_str()); + + // Test failure + writer.Key(SequenceReportFields::Keys[SequenceReportFields::TestFailure]); + writer.String(TestFailurePolicyAsString(policyState.m_testFailurePolicy).c_str()); + + // Integrity failure + writer.Key(SequenceReportFields::Keys[SequenceReportFields::IntegrityFailure]); + writer.String(IntegrityFailurePolicyAsString(policyState.m_integrityFailurePolicy).c_str()); + + // Test sharding + writer.Key(SequenceReportFields::Keys[SequenceReportFields::TestSharding]); + writer.String(TestShardingPolicyAsString(policyState.m_testShardingPolicy).c_str()); + + // Target output capture + writer.Key(SequenceReportFields::Keys[SequenceReportFields::TargetOutputCapture]); + writer.String(TargetOutputCapturePolicyAsString(policyState.m_targetOutputCapture).c_str()); + } + + void SerializePolicyStateMembers( + const SequencePolicyState& policyState, rapidjson::PrettyWriter& writer) + { + SerializePolicyStateBaseMembers(policyState.m_basePolicies, writer); + } + + void SerializePolicyStateMembers( + const SafeImpactAnalysisSequencePolicyState& policyState, rapidjson::PrettyWriter& writer) + { + SerializePolicyStateBaseMembers(policyState.m_basePolicies, writer); + + // Test prioritization + writer.Key(SequenceReportFields::Keys[SequenceReportFields::TestPrioritization]); + writer.String(TestPrioritizationPolicyAsString(policyState.m_testPrioritizationPolicy).c_str()); + } + + void SerializePolicyStateMembers( + const ImpactAnalysisSequencePolicyState& policyState, rapidjson::PrettyWriter& writer) + { + SerializePolicyStateBaseMembers(policyState.m_basePolicies, writer); + + // Test prioritization + writer.Key(SequenceReportFields::Keys[SequenceReportFields::TestPrioritization]); + writer.String(TestPrioritizationPolicyAsString(policyState.m_testPrioritizationPolicy).c_str()); + + // Dynamic dependency map + writer.Key(SequenceReportFields::Keys[SequenceReportFields::DynamicDependencyMap]); + writer.String(DynamicDependencyMapPolicyAsString(policyState.m_dynamicDependencyMap).c_str()); + } + + template + void SerializeSequenceReportBaseMembers( + const Client::SequenceReportBase& sequenceReport, rapidjson::PrettyWriter& writer) + { + // Type + writer.Key(SequenceReportFields::Keys[SequenceReportFields::Type]); + writer.String(SequenceReportTypeAsString(sequenceReport.GetType()).c_str()); + + // Test target timeout + writer.Key(SequenceReportFields::Keys[SequenceReportFields::TestTargetTimeout]); + writer.Uint64(sequenceReport.GetTestTargetTimeout().value_or(AZStd::chrono::milliseconds{0}).count()); + + // Global timeout + writer.Key(SequenceReportFields::Keys[SequenceReportFields::GlobalTimeout]); + writer.Uint64(sequenceReport.GetGlobalTimeout().value_or(AZStd::chrono::milliseconds{ 0 }).count()); + + // Maximum concurrency + writer.Key(SequenceReportFields::Keys[SequenceReportFields::MaxConcurrency]); + writer.Uint64(sequenceReport.GetMaxConcurrency()); + + // Policies + writer.Key(SequenceReportFields::Keys[SequenceReportFields::Policy]); + writer.StartObject(); + { + SerializePolicyStateMembers(sequenceReport.GetPolicyState(), writer); + } + writer.EndObject(); // Policies + + // Suite + writer.Key(SequenceReportFields::Keys[SequenceReportFields::Suite]); + writer.String(SuiteTypeAsString(sequenceReport.GetSuite()).c_str()); + + // Selected test runs + writer.Key(SequenceReportFields::Keys[SequenceReportFields::SelectedTestRuns]); + SerializeTestSelection(sequenceReport.GetSelectedTestRuns(), writer); + + // Selected test run report + writer.Key(SequenceReportFields::Keys[SequenceReportFields::SelectedTestRunReport]); + SerializeTestRunReport(sequenceReport.GetSelectedTestRunReport(), writer); + + // Start time + writer.Key(SequenceReportFields::Keys[SequenceReportFields::StartTime]); + writer.Int64(TimePointInMsAsInt64(sequenceReport.GetStartTime())); + + // End time + writer.Key(SequenceReportFields::Keys[SequenceReportFields::EndTime]); + writer.Int64(TimePointInMsAsInt64(sequenceReport.GetEndTime())); + + // Duration + writer.Key(SequenceReportFields::Keys[SequenceReportFields::Duration]); + writer.Uint64(sequenceReport.GetDuration().count()); + + // Result + writer.Key(SequenceReportFields::Keys[SequenceReportFields::Result]); + writer.String(TestSequenceResultAsString(sequenceReport.GetResult()).c_str()); + + // Total number of test runs + writer.Key(SequenceReportFields::Keys[SequenceReportFields::TotalNumTestRuns]); + writer.Uint64(sequenceReport.GetTotalNumTestRuns()); + + // Total number of passing test runs + writer.Key(SequenceReportFields::Keys[SequenceReportFields::TotalNumPassingTestRuns]); + writer.Uint64(sequenceReport.GetTotalNumPassingTestRuns()); + + // Total number of failing test runs + writer.Key(SequenceReportFields::Keys[SequenceReportFields::TotalNumFailingTestRuns]); + writer.Uint64(sequenceReport.GetTotalNumFailingTestRuns()); + + // Total number of test runs that failed to execute + writer.Key(SequenceReportFields::Keys[SequenceReportFields::TotalNumExecutionFailureTestRuns]); + writer.Uint64(sequenceReport.GetTotalNumExecutionFailureTestRuns()); + + // Total number of timed out test runs + writer.Key(SequenceReportFields::Keys[SequenceReportFields::TotalNumTimedOutTestRuns]); + writer.Uint64(sequenceReport.GetTotalNumTimedOutTestRuns()); + + // Total number of unexecuted test runs + writer.Key(SequenceReportFields::Keys[SequenceReportFields::TotalNumUnexecutedTestRuns]); + writer.Uint64(sequenceReport.GetTotalNumUnexecutedTestRuns()); + + // Total number of passing tests + writer.Key(SequenceReportFields::Keys[SequenceReportFields::TotalNumPassingTests]); + writer.Uint64(sequenceReport.GetTotalNumPassingTests()); + + // Total number of failing tests + writer.Key(SequenceReportFields::Keys[SequenceReportFields::TotalNumFailingTests]); + writer.Uint64(sequenceReport.GetTotalNumFailingTests()); + + // Total number of disabled tests + writer.Key(SequenceReportFields::Keys[SequenceReportFields::TotalNumDisabledTests]); + writer.Uint64(sequenceReport.GetTotalNumDisabledTests()); + } + + template + void SerializeDraftingSequenceReportMembers( + const Client::DraftingSequenceReportBase& sequenceReport, rapidjson::PrettyWriter& writer) + { + SerializeSequenceReportBaseMembers(sequenceReport, writer); + + // Drafted test runs + writer.Key(SequenceReportFields::Keys[SequenceReportFields::DraftedTestRuns]); + writer.StartArray(); + for (const auto& testRun : sequenceReport.GetDraftedTestRuns()) + { + writer.String(testRun.c_str()); + } + writer.EndArray(); // Drafted test runs + + // Drafted test run report + writer.Key(SequenceReportFields::Keys[SequenceReportFields::DraftedTestRunReport]); + SerializeTestRunReport(sequenceReport.GetDraftedTestRunReport(), writer); + } + } // namespace + + AZStd::string SerializeSequenceReport(const Client::RegularSequenceReport& sequenceReport) + { + rapidjson::StringBuffer stringBuffer; + rapidjson::PrettyWriter writer(stringBuffer); + + writer.StartObject(); + { + SerializeSequenceReportBaseMembers(sequenceReport, writer); + } + writer.EndObject(); + + return stringBuffer.GetString(); + } + + AZStd::string SerializeSequenceReport(const Client::SeedSequenceReport& sequenceReport) + { + rapidjson::StringBuffer stringBuffer; + rapidjson::PrettyWriter writer(stringBuffer); + + writer.StartObject(); + { + SerializeSequenceReportBaseMembers(sequenceReport, writer); + } + writer.EndObject(); + + return stringBuffer.GetString(); + } + + AZStd::string SerializeSequenceReport(const Client::ImpactAnalysisSequenceReport& sequenceReport) + { + rapidjson::StringBuffer stringBuffer; + rapidjson::PrettyWriter writer(stringBuffer); + + writer.StartObject(); + { + SerializeDraftingSequenceReportMembers(sequenceReport, writer); + + // Discarded test runs + writer.Key(SequenceReportFields::Keys[SequenceReportFields::DiscardedTestRuns]); + writer.StartArray(); + for (const auto& testRun : sequenceReport.GetDiscardedTestRuns()) + { + writer.String(testRun.c_str()); + } + writer.EndArray(); // Discarded test runs + } + writer.EndObject(); + + return stringBuffer.GetString(); + } + + AZStd::string SerializeSequenceReport(const Client::SafeImpactAnalysisSequenceReport& sequenceReport) + { + rapidjson::StringBuffer stringBuffer; + rapidjson::PrettyWriter writer(stringBuffer); + + writer.StartObject(); + { + SerializeDraftingSequenceReportMembers(sequenceReport, writer); + + // Discarded test runs + writer.Key(SequenceReportFields::Keys[SequenceReportFields::DiscardedTestRuns]); + SerializeTestSelection(sequenceReport.GetDiscardedTestRuns(), writer); + + // Discarded test run report + writer.Key(SequenceReportFields::Keys[SequenceReportFields::DiscardedTestRunReport]); + SerializeTestRunReport(sequenceReport.GetDiscardedTestRunReport(), writer); + } + writer.EndObject(); + + return stringBuffer.GetString(); + } +} // namespace TestImpact diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactClientTestRun.cpp b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactClientTestRun.cpp index 0a258c5dac..6f50145716 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactClientTestRun.cpp +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactClientTestRun.cpp @@ -8,11 +8,13 @@ #include +#include + namespace TestImpact { namespace Client { - TestRun::TestRun( + TestRunBase::TestRunBase( const AZStd::string& name, const AZStd::string& commandString, AZStd::chrono::high_resolution_clock::time_point startTime, @@ -26,107 +28,145 @@ namespace TestImpact { } - const AZStd::string& TestRun::GetTargetName() const + const AZStd::string& TestRunBase::GetTargetName() const { return m_targetName; } - const AZStd::string& TestRun::GetCommandString() const + const AZStd::string& TestRunBase::GetCommandString() const { return m_commandString; } - AZStd::chrono::high_resolution_clock::time_point TestRun::GetStartTime() const + AZStd::chrono::high_resolution_clock::time_point TestRunBase::GetStartTime() const { return m_startTime; } - AZStd::chrono::high_resolution_clock::time_point TestRun::GetEndTime() const + AZStd::chrono::high_resolution_clock::time_point TestRunBase::GetEndTime() const { return m_startTime + m_duration; } - AZStd::chrono::milliseconds TestRun::GetDuration() const + AZStd::chrono::milliseconds TestRunBase::GetDuration() const { return m_duration; } - TestRunResult TestRun::GetResult() const + TestRunResult TestRunBase::GetResult() const { return m_result; } - TestFailure::TestFailure(const AZStd::string& testName, const AZStd::string& errorMessage) + TestRunWithExecutionFailure::TestRunWithExecutionFailure(TestRunBase&& testRun) + : TestRunBase(AZStd::move(testRun)) + { + } + + TimedOutTestRun::TimedOutTestRun(TestRunBase&& testRun) + : TestRunBase(AZStd::move(testRun)) + { + } + + UnexecutedTestRun::UnexecutedTestRun(TestRunBase&& testRun) + : TestRunBase(AZStd::move(testRun)) + { + } + + Test::Test(const AZStd::string& testName, TestResult result) : m_name(testName) - , m_errorMessage(errorMessage) + , m_result(result) { } - const AZStd::string& TestFailure::GetName() const + const AZStd::string& Test::GetName() const { return m_name; } - const AZStd::string& TestFailure::GetErrorMessage() const + TestResult Test::GetResult() const { - return m_errorMessage; + return m_result; } - TestCaseFailure::TestCaseFailure(const AZStd::string& testCaseName, AZStd::vector&& testFailures) - : m_name(testCaseName) - , m_testFailures(AZStd::move(testFailures)) + AZStd::tuple CalculateTestCaseMetrics(const AZStd::vector& tests) { - } + size_t totalNumPassingTests = 0; + size_t totalNumFailingTests = 0; + size_t totalNumDisabledTests = 0; - const AZStd::string& TestCaseFailure::GetName() const - { - return m_name; - } - - const AZStd::vector& TestCaseFailure::GetTestFailures() const - { - return m_testFailures; - } - - static size_t CalculateNumTestRunFailures(const AZStd::vector& testFailures) - { - size_t numTestFailures = 0; - for (const auto& testCase : testFailures) + for (const auto& test : tests) { - numTestFailures += testCase.GetTestFailures().size(); + if (test.GetResult() == Client::TestResult::Passed) + { + totalNumPassingTests++; + } + else if (test.GetResult() == Client::TestResult::Failed) + { + totalNumFailingTests++; + } + else + { + totalNumDisabledTests++; + } } - return numTestFailures; + return { totalNumPassingTests, totalNumFailingTests, totalNumDisabledTests }; } - TestRunWithTestFailures::TestRunWithTestFailures( + CompletedTestRun::CompletedTestRun( const AZStd::string& name, const AZStd::string& commandString, AZStd::chrono::high_resolution_clock::time_point startTime, AZStd::chrono::milliseconds duration, TestRunResult result, - AZStd::vector&& testFailures) - : TestRun(name, commandString, startTime, duration, result) - , m_testCaseFailures(AZStd::move(testFailures)) + AZStd::vector&& tests) + : TestRunBase(name, commandString, startTime, duration, result) + , m_tests(AZStd::move(tests)) { - m_numTestFailures = CalculateNumTestRunFailures(m_testCaseFailures); + AZStd::tie(m_totalNumPassingTests, m_totalNumFailingTests, m_totalNumDisabledTests) = CalculateTestCaseMetrics(m_tests); } - TestRunWithTestFailures::TestRunWithTestFailures(TestRun&& testRun, AZStd::vector&& testFailures) - : TestRun(AZStd::move(testRun)) - , m_testCaseFailures(AZStd::move(testFailures)) + CompletedTestRun::CompletedTestRun(TestRunBase&& testRun, AZStd::vector&& tests) + : TestRunBase(AZStd::move(testRun)) + , m_tests(AZStd::move(tests)) { - m_numTestFailures = CalculateNumTestRunFailures(m_testCaseFailures); + AZStd::tie(m_totalNumPassingTests, m_totalNumFailingTests, m_totalNumDisabledTests) = CalculateTestCaseMetrics(m_tests); } - size_t TestRunWithTestFailures::GetNumTestFailures() const + size_t CompletedTestRun::GetTotalNumTests() const { - return m_numTestFailures; + return m_tests.size(); } - const AZStd::vector& TestRunWithTestFailures::GetTestCaseFailures() const + size_t CompletedTestRun::GetTotalNumPassingTests() const + { + return m_totalNumPassingTests; + } + + size_t CompletedTestRun::GetTotalNumFailingTests() const + { + return m_totalNumFailingTests; + } + + size_t CompletedTestRun::GetTotalNumDisabledTests() const + { + return m_totalNumDisabledTests; + } + + const AZStd::vector& CompletedTestRun::GetTests() const + { + return m_tests; + } + + PassingTestRun::PassingTestRun(TestRunBase&& testRun, AZStd::vector&& tests) + : CompletedTestRun(AZStd::move(testRun), AZStd::move(tests)) + { + } + + FailingTestRun::FailingTestRun(TestRunBase&& testRun, AZStd::vector&& tests) + : CompletedTestRun(AZStd::move(testRun), AZStd::move(tests)) { - return m_testCaseFailures; } } // namespace Client } // namespace TestImpact diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactRuntime.cpp b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactRuntime.cpp index 478b63e8b2..8a9d96bca8 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactRuntime.cpp +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactRuntime.cpp @@ -6,7 +6,7 @@ * */ -#include +#include #include #include @@ -81,7 +81,7 @@ namespace TestImpact { if (m_testCompleteCallback.has_value()) { - Client::TestRun testRun( + Client::TestRunBase testRun( testJob.GetTestTarget()->GetName(), testJob.GetCommandString(), testJob.GetStartTime(), @@ -110,8 +110,140 @@ namespace TestImpact return result; } + //! Utility structure for holding the pertinent data for test run reports. + template + struct TestRunData + { + TestSequenceResult m_result = TestSequenceResult::Success; + AZStd::vector m_jobs; + AZStd::chrono::high_resolution_clock::time_point m_relativeStartTime; + AZStd::chrono::milliseconds m_duration = AZStd::chrono::milliseconds{ 0 }; + }; + + //! Wrapper for the impact analysis test sequence to handle both the updating and non-updating policies through a common pathway. + //! @tparam TestRunnerFunctor The functor for running the specified tests. + //! @tparam TestJob The test engine job type returned by the functor. + //! @param maxConcurrency The maximum concurrency being used for this sequence. + //! @param policyState The policy state being used for the sequence. + //! @param suiteType The suite type used for this sequence. + //! @param timer The timer to use for the test run timings. + //! @param testRunner The test runner functor to use for each of the test runs. + //! @param includedSelectedTestTargets The subset of test targets that were selected to run and not also fully excluded from running. + //! @param excludedSelectedTestTargets The subset of test targets that were selected to run but were fully excluded running. + //! @param discardedTestTargets The subset of test targets that were discarded from the test selection and will not be run. + //! @param globalTimeout The maximum duration the entire test sequence may run for (infinite if empty). + //! @param testSequenceStartCallback The client function to be called after the test targets have been selected but prior to running the + //! tests. + //! @param testSequenceCompleteCallback The client function to be called after the test sequence has completed. + //! @param testRunCompleteCallback The client function to be called after an individual test run has completed. + //! @param updateCoverage The function to call to update the dynamic dependency map with test coverage (if any). + template + Client::ImpactAnalysisSequenceReport ImpactAnalysisTestSequenceWrapper( + size_t maxConcurrency, + const ImpactAnalysisSequencePolicyState& policyState, + SuiteType suiteType, + const Timer& sequenceTimer, + const TestRunnerFunctor& testRunner, + const AZStd::vector& includedSelectedTestTargets, + const AZStd::vector& excludedSelectedTestTargets, + const AZStd::vector& discardedTestTargets, + const AZStd::vector& draftedTestTargets, + const AZStd::optional& testTargetTimeout, + const AZStd::optional& globalTimeout, + AZStd::optional testSequenceStartCallback, + AZStd::optional> testSequenceEndCallback, + AZStd::optional testCompleteCallback, + AZStd::optional& jobs)>> updateCoverage) + { + TestRunData selectedTestRunData, draftedTestRunData; + AZStd::optional sequenceTimeout = globalTimeout; + + // Extract the client facing representation of selected, discarded and drafted test targets + const Client::TestRunSelection selectedTests( + ExtractTestTargetNames(includedSelectedTestTargets), ExtractTestTargetNames(excludedSelectedTestTargets)); + const auto discardedTests = ExtractTestTargetNames(discardedTestTargets); + const auto draftedTests = ExtractTestTargetNames(draftedTestTargets); + + // Inform the client that the sequence is about to start + if (testSequenceStartCallback.has_value()) + { + (*testSequenceStartCallback)(suiteType, selectedTests, discardedTests, draftedTests); + } + + // We share the test run complete handler between the selected and drafted test runs as to present them together as one + // continuous test sequence to the client rather than two discrete test runs + const size_t totalNumTestRuns = includedSelectedTestTargets.size() + draftedTestTargets.size(); + TestRunCompleteCallbackHandler testRunCompleteHandler(totalNumTestRuns, testCompleteCallback); + + const auto gatherTestRunData = [&sequenceTimer, &testRunner, &testRunCompleteHandler, &globalTimeout] + (const AZStd::vector& testsTargets, TestRunData& testRunData) + { + const Timer testRunTimer; + testRunData.m_relativeStartTime = testRunTimer.GetStartTimePointRelative(sequenceTimer); + auto [result, jobs] = testRunner(testsTargets, testRunCompleteHandler, globalTimeout); + testRunData.m_result = result; + testRunData.m_jobs = AZStd::move(jobs); + testRunData.m_duration = testRunTimer.GetElapsedMs(); + }; + + if (!includedSelectedTestTargets.empty()) + { + // Run the selected test targets and collect the test run results + gatherTestRunData(includedSelectedTestTargets, selectedTestRunData); + + // Carry the remaining global sequence time over to the drafted test run + if (globalTimeout.has_value()) + { + const auto elapsed = selectedTestRunData.m_duration; + sequenceTimeout = elapsed < globalTimeout.value() ? globalTimeout.value() - elapsed : AZStd::chrono::milliseconds(0); + } + } + + if (!draftedTestTargets.empty()) + { + // Run the drafted test targets and collect the test run results + gatherTestRunData(draftedTestTargets, draftedTestRunData); + } + + // Generate the sequence report for the client + const auto sequenceReport = Client::ImpactAnalysisSequenceReport( + maxConcurrency, + testTargetTimeout, + globalTimeout, + policyState, + suiteType, + selectedTests, + discardedTests, + draftedTests, + GenerateTestRunReport( + selectedTestRunData.m_result, + selectedTestRunData.m_relativeStartTime, + selectedTestRunData.m_duration, + selectedTestRunData.m_jobs), + GenerateTestRunReport( + draftedTestRunData.m_result, + draftedTestRunData.m_relativeStartTime, + draftedTestRunData.m_duration, + draftedTestRunData.m_jobs)); + + // Inform the client that the sequence has ended + if (testSequenceEndCallback.has_value()) + { + (*testSequenceEndCallback)(sequenceReport); + } + + // Update the dynamic dependency map with the latest coverage data (if any) + if (updateCoverage.has_value()) + { + (*updateCoverage)(ConcatenateVectors(selectedTestRunData.m_jobs, draftedTestRunData.m_jobs)); + } + + return sequenceReport; + } + Runtime::Runtime( RuntimeConfig&& config, + AZStd::optional dataFile, SuiteType suiteFilter, Policy::ExecutionFailure executionFailurePolicy, Policy::FailedTestCoverage failedTestCoveragePolicy, @@ -151,27 +283,22 @@ namespace TestImpact try { + if (dataFile.has_value()) + { + m_sparTiaFile = dataFile.value().String(); + } + else + { + m_sparTiaFile = m_config.m_workspace.m_active.m_sparTiaFiles[static_cast(m_suiteFilter)].String(); + } + // Populate the dynamic dependency map with the existing source coverage data (if any) - m_sparTIAFile = m_config.m_workspace.m_active.m_sparTIAFiles[static_cast(m_suiteFilter)].String(); - const auto tiaDataRaw = ReadFileContents(m_sparTIAFile); + const auto tiaDataRaw = ReadFileContents(m_sparTiaFile); const auto tiaData = DeserializeSourceCoveringTestsList(tiaDataRaw); if (tiaData.GetNumSources()) { m_dynamicDependencyMap->ReplaceSourceCoverage(tiaData); m_hasImpactAnalysisData = true; - - // Enumerate new test targets - const auto testTargetsWithNoEnumeration = m_dynamicDependencyMap->GetNotCoveringTests(); - if (!testTargetsWithNoEnumeration.empty()) - { - m_testEngine->UpdateEnumerationCache( - testTargetsWithNoEnumeration, - Policy::ExecutionFailure::Ignore, - Policy::TestFailure::Continue, - AZStd::nullopt, - AZStd::nullopt, - AZStd::nullopt); - } } } catch (const DependencyException& e) @@ -186,7 +313,7 @@ namespace TestImpact AZ_Printf( LogCallSite, AZStd::string::format( - "No test impact analysis data found for suite '%s' at %s\n", GetSuiteTypeName(m_suiteFilter).c_str(), m_sparTIAFile.c_str()).c_str()); + "No test impact analysis data found for suite '%s' at %s\n", SuiteTypeAsString(m_suiteFilter).c_str(), m_sparTiaFile.c_str()).c_str()); } } @@ -230,7 +357,7 @@ namespace TestImpact } } - AZStd::pair, AZStd::vector> Runtime::SelectCoveringTestTargetsAndUpdateEnumerationCache( + AZStd::pair, AZStd::vector> Runtime::SelectCoveringTestTargets( const ChangeList& changeList, Policy::TestPrioritization testPrioritizationPolicy) { @@ -243,9 +370,6 @@ namespace TestImpact // Populate a set with the selected test targets so that we can infer the discarded test target not selected for this change list const AZStd::unordered_set selectedTestTargetSet(selectedTestTargets.begin(), selectedTestTargets.end()); - // Update the enumeration caches of mutated targets regardless of the current sharding policy - EnumerateMutatedTestTargets(changeDependencyList); - // The test targets in the main list not in the selected test target set are the test targets not selected for this change list for (const auto& testTarget : m_dynamicDependencyMap->GetTestTargetList().GetTargets()) { @@ -287,7 +411,7 @@ namespace TestImpact void Runtime::ClearDynamicDependencyMapAndRemoveExistingFile() { m_dynamicDependencyMap->ClearAllSourceCoverage(); - DeleteFile(m_sparTIAFile); + DeleteFile(m_sparTiaFile); } SourceCoveringTestsList Runtime::CreateSourceCoveringTestFromTestCoverages(const AZStd::vector& jobs) @@ -368,9 +492,9 @@ namespace TestImpact } m_dynamicDependencyMap->ReplaceSourceCoverage(sourceCoverageTestsList); - const auto sparTIA = m_dynamicDependencyMap->ExportSourceCoverage(); - const auto sparTIAData = SerializeSourceCoveringTestsList(sparTIA); - WriteFileContents(sparTIAData, m_sparTIAFile); + const auto sparTia = m_dynamicDependencyMap->ExportSourceCoverage(); + const auto sparTiaData = SerializeSourceCoveringTestsList(sparTia); + WriteFileContents(sparTiaData, m_sparTiaFile); m_hasImpactAnalysisData = true; } catch(const RuntimeException& e) @@ -386,11 +510,42 @@ namespace TestImpact } } - Client::SequenceReport Runtime::RegularTestSequence( + PolicyStateBase Runtime::GeneratePolicyStateBase() const + { + PolicyStateBase policyState; + + policyState.m_executionFailurePolicy = m_executionFailurePolicy; + policyState.m_failedTestCoveragePolicy = m_failedTestCoveragePolicy; + policyState.m_integrityFailurePolicy = m_integrationFailurePolicy; + policyState.m_targetOutputCapture = m_targetOutputCapture; + policyState.m_testFailurePolicy = m_testFailurePolicy; + policyState.m_testShardingPolicy = m_testShardingPolicy; + + return policyState; + } + + SequencePolicyState Runtime::GenerateSequencePolicyState() const + { + return { GeneratePolicyStateBase() }; + } + + SafeImpactAnalysisSequencePolicyState Runtime::GenerateSafeImpactAnalysisSequencePolicyState( + Policy::TestPrioritization testPrioritizationPolicy) const + { + return { GeneratePolicyStateBase(), testPrioritizationPolicy }; + } + + ImpactAnalysisSequencePolicyState Runtime::GenerateImpactAnalysisSequencePolicyState( + Policy::TestPrioritization testPrioritizationPolicy, Policy::DynamicDependencyMap dynamicDependencyMapPolicy) const + { + return { GeneratePolicyStateBase(), testPrioritizationPolicy, dynamicDependencyMapPolicy }; + } + + Client::RegularSequenceReport Runtime::RegularTestSequence( AZStd::optional testTargetTimeout, AZStd::optional globalTimeout, AZStd::optional testSequenceStartCallback, - AZStd::optional> testSequenceEndCallback, + AZStd::optional> testSequenceEndCallback, AZStd::optional testCompleteCallback) { const Timer sequenceTimer; @@ -434,7 +589,11 @@ namespace TestImpact const auto testRunDuration = testRunTimer.GetElapsedMs(); // Generate the sequence report for the client - const auto sequenceReport = Client::SequenceReport( + const auto sequenceReport = Client::RegularSequenceReport( + m_maxConcurrency, + testTargetTimeout, + globalTimeout, + GenerateSequencePolicyState(), m_suiteFilter, selectedTests, GenerateTestRunReport(result, testRunTimer.GetStartTimePointRelative(sequenceTimer), testRunDuration, testJobs)); @@ -448,95 +607,6 @@ namespace TestImpact return sequenceReport; } - //! Wrapper for the impact analysis test sequence to handle both the updating and non-updating policies through a common pathway. - //! @tparam TestRunnerFunctor The functor for running the specified tests. - //! @tparam TestJob The test engine job type returned by the functor. - //! @param suiteType The suite type used for this sequence. - //! @param timer The timer to use for the test run timings. - //! @param testRunner The test runner functor to use for each of the test runs. - //! @param includedSelectedTestTargets The subset of test targets that were selected to run and not also fully excluded from running. - //! @param excludedSelectedTestTargets The subset of test targets that were selected to run but were fully excluded running. - //! @param discardedTestTargets The subset of test targets that were discarded from the test selection and will not be run. - //! @param globalTimeout The maximum duration the entire test sequence may run for (infinite if empty). - //! @param testSequenceStartCallback The client function to be called after the test targets have been selected but prior to running the tests. - //! @param testSequenceCompleteCallback The client function to be called after the test sequence has completed. - //! @param testRunCompleteCallback The client function to be called after an individual test run has completed. - //! @param updateCoverage The function to call to update the dynamic dependency map with test coverage (if any). - template - Client::ImpactAnalysisSequenceReport ImpactAnalysisTestSequenceWrapper( - SuiteType suiteType, - const Timer& sequenceTimer, - const TestRunnerFunctor& testRunner, - const AZStd::vector& includedSelectedTestTargets, - const AZStd::vector& excludedSelectedTestTargets, - const AZStd::vector& discardedTestTargets, - const AZStd::vector& draftedTestTargets, - const AZStd::optional globalTimeout, - AZStd::optional testSequenceStartCallback, - AZStd::optional> testSequenceEndCallback, - AZStd::optional testCompleteCallback, - AZStd::optional& jobs)>> updateCoverage) - { - AZStd::optional sequenceTimeout = globalTimeout; - - // Extract the client facing representation of selected, discarded and drafted test targets - const Client::TestRunSelection selectedTests( - ExtractTestTargetNames(includedSelectedTestTargets), ExtractTestTargetNames(excludedSelectedTestTargets)); - const auto discardedTests = ExtractTestTargetNames(discardedTestTargets); - const auto draftedTests = ExtractTestTargetNames(draftedTestTargets); - - // Inform the client that the sequence is about to start - if (testSequenceStartCallback.has_value()) - { - (*testSequenceStartCallback)(suiteType, selectedTests, discardedTests, draftedTests); - } - - // We share the test run complete handler between the selected and drafted test runs as to present them together as one - // continuous test sequence to the client rather than two discrete test runs - const size_t totalNumTestRuns = includedSelectedTestTargets.size() + draftedTestTargets.size(); - TestRunCompleteCallbackHandler testRunCompleteHandler(totalNumTestRuns, testCompleteCallback); - - // Run the selected test targets and collect the test run results - const Timer selectedTestRunTimer; - const auto [selectedResult, selectedTestJobs] = testRunner(includedSelectedTestTargets, testRunCompleteHandler, globalTimeout); - const auto selectedTestRunDuration = selectedTestRunTimer.GetElapsedMs(); - - // Carry the remaining global sequence time over to the drafted test run - if (globalTimeout.has_value()) - { - const auto elapsed = selectedTestRunDuration; - sequenceTimeout = elapsed < globalTimeout.value() ? globalTimeout.value() - elapsed : AZStd::chrono::milliseconds(0); - } - - // Run the drafted test targets and collect the test run results - Timer draftedTestRunTimer; - const auto [draftedResult, draftedTestJobs] = testRunner(draftedTestTargets, testRunCompleteHandler, globalTimeout); - const auto draftedTestRunDuration = draftedTestRunTimer.GetElapsedMs(); - - // Generate the sequence report for the client - const auto sequenceReport = Client::ImpactAnalysisSequenceReport( - suiteType, - selectedTests, - discardedTests, - draftedTests, - GenerateTestRunReport(selectedResult, selectedTestRunTimer.GetStartTimePointRelative(sequenceTimer), selectedTestRunDuration, selectedTestJobs), - GenerateTestRunReport(draftedResult, draftedTestRunTimer.GetStartTimePointRelative(sequenceTimer), draftedTestRunDuration, draftedTestJobs)); - - // Inform the client that the sequence has ended - if (testSequenceEndCallback.has_value()) - { - (*testSequenceEndCallback)(sequenceReport); - } - - // Update the dynamic dependency map with the latest coverage data (if any) - if (updateCoverage.has_value()) - { - (*updateCoverage)(ConcatenateVectors(selectedTestJobs, draftedTestJobs)); - } - - return sequenceReport; - } - Client::ImpactAnalysisSequenceReport Runtime::ImpactAnalysisTestSequence( const ChangeList& changeList, Policy::TestPrioritization testPrioritizationPolicy, @@ -550,10 +620,30 @@ namespace TestImpact const Timer sequenceTimer; // Draft in the test targets that have no coverage entries in the dynamic dependency map - AZStd::vector draftedTestTargets = m_dynamicDependencyMap->GetNotCoveringTests(); + const AZStd::vector draftedTestTargets = m_dynamicDependencyMap->GetNotCoveringTests(); - // The test targets that were selected for the change list by the dynamic dependency map and the test targets that were not - auto [selectedTestTargets, discardedTestTargets] = SelectCoveringTestTargetsAndUpdateEnumerationCache(changeList, testPrioritizationPolicy); + const auto selectCoveringTestTargetsAndPruneDraftedFromDiscarded = + [this, &draftedTestTargets, &changeList, testPrioritizationPolicy]() + { + // The test targets that were selected for the change list by the dynamic dependency map and the test targets that were not + const auto [selectedTestTargets, discardedTestTargets] = + SelectCoveringTestTargets(changeList, testPrioritizationPolicy); + + const AZStd::unordered_set draftedTestTargetsSet(draftedTestTargets.begin(), draftedTestTargets.end()); + + AZStd::vector discardedNotDraftedTestTargets; + for (const auto* testTarget : discardedTestTargets) + { + if (!draftedTestTargetsSet.count(testTarget)) + { + discardedNotDraftedTestTargets.push_back(testTarget); + } + } + + return AZStd::pair{ selectedTestTargets, discardedNotDraftedTestTargets }; + }; + + const auto [selectedTestTargets, discardedTestTargets] = selectCoveringTestTargetsAndPruneDraftedFromDiscarded(); // The subset of selected test targets that are not on the configuration's exclude list and those that are auto [includedSelectedTestTargets, excludedSelectedTestTargets] = SelectTestTargetsByExcludeList(selectedTestTargets); @@ -604,6 +694,8 @@ namespace TestImpact }; return ImpactAnalysisTestSequenceWrapper( + m_maxConcurrency, + GenerateImpactAnalysisSequencePolicyState(testPrioritizationPolicy, dynamicDependencyMapPolicy), m_suiteFilter, sequenceTimer, instrumentedTestRun, @@ -611,6 +703,7 @@ namespace TestImpact excludedSelectedTestTargets, discardedTestTargets, draftedTestTargets, + testTargetTimeout, globalTimeout, testSequenceStartCallback, testSequenceEndCallback, @@ -620,6 +713,8 @@ namespace TestImpact else { return ImpactAnalysisTestSequenceWrapper( + m_maxConcurrency, + GenerateImpactAnalysisSequencePolicyState(testPrioritizationPolicy, dynamicDependencyMapPolicy), m_suiteFilter, sequenceTimer, regularTestRun, @@ -627,6 +722,7 @@ namespace TestImpact excludedSelectedTestTargets, discardedTestTargets, draftedTestTargets, + testTargetTimeout, globalTimeout, testSequenceStartCallback, testSequenceEndCallback, @@ -645,13 +741,15 @@ namespace TestImpact AZStd::optional testCompleteCallback) { const Timer sequenceTimer; - auto sequenceTimeout = globalTimeout; + TestRunData selectedTestRunData, draftedTestRunData; + TestRunData discardedTestRunData; + AZStd::optional sequenceTimeout = globalTimeout; // Draft in the test targets that have no coverage entries in the dynamic dependency map AZStd::vector draftedTestTargets = m_dynamicDependencyMap->GetNotCoveringTests(); // The test targets that were selected for the change list by the dynamic dependency map and the test targets that were not - auto [selectedTestTargets, discardedTestTargets] = SelectCoveringTestTargetsAndUpdateEnumerationCache(changeList, testPrioritizationPolicy); + const auto [selectedTestTargets, discardedTestTargets] = SelectCoveringTestTargets(changeList, testPrioritizationPolicy); // The subset of selected test targets that are not on the configuration's exclude list and those that are auto [includedSelectedTestTargets, excludedSelectedTestTargets] = SelectTestTargetsByExcludeList(selectedTestTargets); @@ -675,71 +773,107 @@ namespace TestImpact // continuous test sequence to the client rather than three discrete test runs const size_t totalNumTestRuns = includedSelectedTestTargets.size() + draftedTestTargets.size() + includedDiscardedTestTargets.size(); TestRunCompleteCallbackHandler testRunCompleteHandler(totalNumTestRuns, testCompleteCallback); - - // Run the selected test targets and collect the test run results - const Timer selectedTestRunTimer; - const auto [selectedResult, selectedTestJobs] = m_testEngine->InstrumentedRun( - includedSelectedTestTargets, - m_testShardingPolicy, - m_executionFailurePolicy, - m_integrationFailurePolicy, - m_testFailurePolicy, - m_targetOutputCapture, - testTargetTimeout, - sequenceTimeout, - AZStd::ref(testRunCompleteHandler)); - const auto selectedTestRunDuration = selectedTestRunTimer.GetElapsedMs(); - - // Carry the remaining global sequence time over to the discarded test run - if (globalTimeout.has_value()) + + // Functor for running instrumented test targets + const auto instrumentedTestRun = + [this, &testTargetTimeout, &sequenceTimeout, &testRunCompleteHandler](const AZStd::vector& testsTargets) { - const auto elapsed = selectedTestRunDuration; - sequenceTimeout = elapsed < globalTimeout.value() ? globalTimeout.value() - elapsed : AZStd::chrono::milliseconds(0); + return m_testEngine->InstrumentedRun( + testsTargets, + m_testShardingPolicy, + m_executionFailurePolicy, + m_integrationFailurePolicy, + m_testFailurePolicy, + m_targetOutputCapture, + testTargetTimeout, + sequenceTimeout, + AZStd::ref(testRunCompleteHandler)); + }; + + // Functor for running uninstrumented test targets + const auto regularTestRun = + [this, &testTargetTimeout, &sequenceTimeout, &testRunCompleteHandler](const AZStd::vector& testsTargets) + { + return m_testEngine->RegularRun( + testsTargets, + m_testShardingPolicy, + m_executionFailurePolicy, + m_testFailurePolicy, + m_targetOutputCapture, + testTargetTimeout, + sequenceTimeout, + AZStd::ref(testRunCompleteHandler)); + }; + + // Functor for running instrumented test targets + const auto gatherTestRunData = [&sequenceTimer] + (const AZStd::vector& testsTargets, const auto& testRunner, auto& testRunData) + { + const Timer testRunTimer; + testRunData.m_relativeStartTime = testRunTimer.GetStartTimePointRelative(sequenceTimer); + auto [result, jobs] = testRunner(testsTargets); + testRunData.m_result = result; + testRunData.m_jobs = AZStd::move(jobs); + testRunData.m_duration = testRunTimer.GetElapsedMs(); + }; + + if (!includedSelectedTestTargets.empty()) + { + // Run the selected test targets and collect the test run results + gatherTestRunData(includedSelectedTestTargets, instrumentedTestRun, selectedTestRunData); + + // Carry the remaining global sequence time over to the discarded test run + if (globalTimeout.has_value()) + { + const auto elapsed = selectedTestRunData.m_duration; + sequenceTimeout = elapsed < globalTimeout.value() ? globalTimeout.value() - elapsed : AZStd::chrono::milliseconds(0); + } } - // Run the discarded test targets and collect the test run results - const Timer discardedTestRunTimer; - const auto [discardedResult, discardedTestJobs] = m_testEngine->RegularRun( - includedDiscardedTestTargets, - m_testShardingPolicy, - m_executionFailurePolicy, - m_testFailurePolicy, - m_targetOutputCapture, - testTargetTimeout, - sequenceTimeout, - AZStd::ref(testRunCompleteHandler)); - const auto discardedTestRunDuration = discardedTestRunTimer.GetElapsedMs(); - - // Carry the remaining global sequence time over to the drafted test run - if (globalTimeout.has_value()) + if (!includedDiscardedTestTargets.empty()) { - const auto elapsed = selectedTestRunDuration + discardedTestRunDuration; - sequenceTimeout = elapsed < globalTimeout.value() ? globalTimeout.value() - elapsed : AZStd::chrono::milliseconds(0); + // Run the discarded test targets and collect the test run results + gatherTestRunData(includedDiscardedTestTargets, regularTestRun, discardedTestRunData); + + // Carry the remaining global sequence time over to the drafted test run + if (globalTimeout.has_value()) + { + const auto elapsed = selectedTestRunData.m_duration + discardedTestRunData.m_duration; + sequenceTimeout = elapsed < globalTimeout.value() ? globalTimeout.value() - elapsed : AZStd::chrono::milliseconds(0); + } } - // Run the drafted test targets and collect the test run results - const Timer draftedTestRunTimer; - const auto [draftedResult, draftedTestJobs] = m_testEngine->InstrumentedRun( - draftedTestTargets, - m_testShardingPolicy, - m_executionFailurePolicy, - m_integrationFailurePolicy, - m_testFailurePolicy, - m_targetOutputCapture, - testTargetTimeout, - sequenceTimeout, - AZStd::ref(testRunCompleteHandler)); - const auto draftedTestRunDuration = draftedTestRunTimer.GetElapsedMs(); + if (!draftedTestTargets.empty()) + { + // Run the drafted test targets and collect the test run results + gatherTestRunData(draftedTestTargets, instrumentedTestRun, draftedTestRunData); + } // Generate the sequence report for the client const auto sequenceReport = Client::SafeImpactAnalysisSequenceReport( + m_maxConcurrency, + testTargetTimeout, + globalTimeout, + GenerateSafeImpactAnalysisSequencePolicyState(testPrioritizationPolicy), m_suiteFilter, selectedTests, discardedTests, draftedTests, - GenerateTestRunReport(selectedResult, selectedTestRunTimer.GetStartTimePointRelative(sequenceTimer), selectedTestRunDuration, selectedTestJobs), - GenerateTestRunReport(discardedResult, discardedTestRunTimer.GetStartTimePointRelative(sequenceTimer), discardedTestRunDuration, discardedTestJobs), - GenerateTestRunReport(draftedResult, draftedTestRunTimer.GetStartTimePointRelative(sequenceTimer), draftedTestRunDuration, draftedTestJobs)); + GenerateTestRunReport( + selectedTestRunData.m_result, + selectedTestRunData.m_relativeStartTime, + selectedTestRunData.m_duration, + selectedTestRunData.m_jobs), + GenerateTestRunReport( + discardedTestRunData.m_result, + discardedTestRunData.m_relativeStartTime, + discardedTestRunData.m_duration, + discardedTestRunData.m_jobs), + GenerateTestRunReport( + draftedTestRunData.m_result, + draftedTestRunData.m_relativeStartTime, + draftedTestRunData.m_duration, + draftedTestRunData.m_jobs)); // Inform the client that the sequence has ended if (testSequenceEndCallback.has_value()) @@ -747,15 +881,15 @@ namespace TestImpact (*testSequenceEndCallback)(sequenceReport); } - UpdateAndSerializeDynamicDependencyMap(ConcatenateVectors(selectedTestJobs, draftedTestJobs)); + UpdateAndSerializeDynamicDependencyMap(ConcatenateVectors(selectedTestRunData.m_jobs, draftedTestRunData.m_jobs)); return sequenceReport; } - Client::SequenceReport Runtime::SeededTestSequence( + Client::SeedSequenceReport Runtime::SeededTestSequence( AZStd::optional testTargetTimeout, AZStd::optional globalTimeout, AZStd::optional testSequenceStartCallback, - AZStd::optional> testSequenceEndCallback, + AZStd::optional> testSequenceEndCallback, AZStd::optional testCompleteCallback) { const Timer sequenceTimer; @@ -799,7 +933,11 @@ namespace TestImpact const auto testRunDuration = testRunTimer.GetElapsedMs(); // Generate the sequence report for the client - const auto sequenceReport = Client::SequenceReport( + const auto sequenceReport = Client::SeedSequenceReport( + m_maxConcurrency, + testTargetTimeout, + globalTimeout, + GenerateSequencePolicyState(), m_suiteFilter, selectedTests, GenerateTestRunReport(result, testRunTimer.GetStartTimePointRelative(sequenceTimer), testRunDuration, testJobs)); diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactRuntimeUtils.cpp b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactRuntimeUtils.cpp index 0c61c5f426..fec3d90471 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactRuntimeUtils.cpp +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactRuntimeUtils.cpp @@ -6,7 +6,7 @@ * */ -#include +#include #include #include diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactRuntimeUtils.h b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactRuntimeUtils.h index 33e15bfd20..23d78ee329 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactRuntimeUtils.h +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactRuntimeUtils.h @@ -38,34 +38,44 @@ namespace TestImpact //! Extracts the name information from the specified test targets. AZStd::vector ExtractTestTargetNames(const AZStd::vector& testTargets); - //! Generates a test run failure report from the specified test engine job information. + //! Generates the test suites from the specified test engine job information. //! @tparam TestJob The test engine job type. template - AZStd::vector GenerateTestCaseFailures(const TestJob& testJob) + AZStd::vector GenerateClientTests(const TestJob& testJob) { - AZStd::vector testCaseFailures; + AZStd::vector tests; if (testJob.GetTestRun().has_value()) { for (const auto& testSuite : testJob.GetTestRun()->GetTestSuites()) { - AZStd::vector testFailures; for (const auto& testCase : testSuite.m_tests) { - if (testCase.m_result.value_or(TestRunResult::Passed) == TestRunResult::Failed) + auto result = Client::TestResult::NotRun; + if (testCase.m_result.has_value()) { - testFailures.push_back(Client::TestFailure(testCase.m_name, "No error message retrieved")); + if (testCase.m_result.value() == TestRunResult::Passed) + { + result = Client::TestResult::Passed; + } + else if (testCase.m_result.value() == TestRunResult::Failed) + { + result = Client::TestResult::Failed; + } + else + { + throw RuntimeException(AZStd::string::format( + "Unexpected test run result: %u", aznumeric_cast(testCase.m_result.value()))); + } } - } - - if (!testFailures.empty()) - { - testCaseFailures.push_back(Client::TestCaseFailure(testSuite.m_name, AZStd::move(testFailures))); + + const auto name = AZStd::string::format("%s.%s", testSuite.m_name.c_str(), testCase.m_name.c_str()); + tests.push_back(Client::Test(name, result)); } } } - return testCaseFailures; + return tests; } template @@ -75,11 +85,11 @@ namespace TestImpact AZStd::chrono::milliseconds duration, const AZStd::vector& testJobs) { - AZStd::vector passingTests; - AZStd::vector failingTests; - AZStd::vector executionFailureTests; - AZStd::vector timedOutTests; - AZStd::vector unexecutedTests; + AZStd::vector passingTests; + AZStd::vector failingTests; + AZStd::vector executionFailureTests; + AZStd::vector timedOutTests; + AZStd::vector unexecutedTests; for (const auto& testJob : testJobs) { @@ -88,7 +98,7 @@ namespace TestImpact AZStd::chrono::high_resolution_clock::time_point() + AZStd::chrono::duration_cast(testJob.GetStartTime() - startTime); - Client::TestRun clientTestRun( + Client::TestRunBase clientTestRun( testJob.GetTestTarget()->GetName(), testJob.GetCommandString(), relativeStartTime, testJob.GetDuration(), testJob.GetTestResult()); @@ -96,27 +106,27 @@ namespace TestImpact { case Client::TestRunResult::FailedToExecute: { - executionFailureTests.push_back(clientTestRun); + executionFailureTests.emplace_back(AZStd::move(clientTestRun)); break; } case Client::TestRunResult::NotRun: { - unexecutedTests.push_back(clientTestRun); + unexecutedTests.emplace_back(AZStd::move(clientTestRun)); break; } case Client::TestRunResult::Timeout: { - timedOutTests.push_back(clientTestRun); + timedOutTests.emplace_back(AZStd::move(clientTestRun)); break; } case Client::TestRunResult::AllTestsPass: { - passingTests.push_back(clientTestRun); + passingTests.emplace_back(AZStd::move(clientTestRun), GenerateClientTests(testJob)); break; } case Client::TestRunResult::TestFailures: { - failingTests.emplace_back(AZStd::move(clientTestRun), GenerateTestCaseFailures(testJob)); + failingTests.emplace_back(AZStd::move(clientTestRun), GenerateClientTests(testJob)); break; } default: diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactUtils.cpp b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactUtils.cpp new file mode 100644 index 0000000000..993aee9af5 --- /dev/null +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactUtils.cpp @@ -0,0 +1,244 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include + +#include + +namespace TestImpact +{ + //! Delete the files that match the pattern from the specified directory. + //! @param path The path to the directory to pattern match the files for deletion. + //! @param pattern The pattern to match files for deletion. + size_t DeleteFiles(const RepoPath& path, const AZStd::string& pattern) + { + size_t numFilesDeleted = 0; + + AZ::IO::SystemFile::FindFiles( + AZStd::string::format("%s/%s", path.c_str(), pattern.c_str()).c_str(), + [&path, &numFilesDeleted](const char* file, bool isFile) + { + if (isFile) + { + AZ::IO::SystemFile::Delete(AZStd::string::format("%s/%s", path.c_str(), file).c_str()); + numFilesDeleted++; + } + + return true; + }); + + return numFilesDeleted; + } + + //! Deletes the specified file. + void DeleteFile(const RepoPath& file) + { + DeleteFiles(file.ParentPath(), file.Filename().Native()); + } + + //! User-friendly names for the test suite types. + AZStd::string SuiteTypeAsString(SuiteType suiteType) + { + switch (suiteType) + { + case SuiteType::Main: + return "main"; + case SuiteType::Periodic: + return "periodic"; + case SuiteType::Sandbox: + return "sandbox"; + default: + throw(Exception("Unexpected suite type")); + } + } + + AZStd::string SequenceReportTypeAsString(Client::SequenceReportType type) + { + switch (type) + { + case Client::SequenceReportType::RegularSequence: + return "regular"; + case Client::SequenceReportType::SeedSequence: + return "seed"; + case Client::SequenceReportType::ImpactAnalysisSequence: + return "impact_analysis"; + case Client::SequenceReportType::SafeImpactAnalysisSequence: + return "safe_impact_analysis"; + default: + throw(Exception(AZStd::string::format("Unexpected sequence report type: %u", aznumeric_cast(type)))); + } + } + + AZStd::string TestSequenceResultAsString(TestSequenceResult result) + { + switch (result) + { + case TestSequenceResult::Failure: + return "failure"; + case TestSequenceResult::Success: + return "success"; + case TestSequenceResult::Timeout: + return "timeout"; + default: + throw(Exception(AZStd::string::format("Unexpected test sequence result: %u", aznumeric_cast(result)))); + } + } + + AZStd::string TestRunResultAsString(Client::TestRunResult result) + { + switch (result) + { + case Client::TestRunResult::AllTestsPass: + return "all_tests_pass"; + case Client::TestRunResult::FailedToExecute: + return "failed_to_execute"; + case Client::TestRunResult::NotRun: + return "not_run"; + case Client::TestRunResult::TestFailures: + return "test_failures"; + case Client::TestRunResult::Timeout: + return "timeout"; + default: + throw(Exception(AZStd::string::format("Unexpected test run result: %u", aznumeric_cast(result)))); + } + } + + AZStd::string ExecutionFailurePolicyAsString(Policy::ExecutionFailure executionFailurePolicy) + { + switch (executionFailurePolicy) + { + case Policy::ExecutionFailure::Abort: + return "abort"; + case Policy::ExecutionFailure::Continue: + return "continue"; + case Policy::ExecutionFailure::Ignore: + return "ignore"; + default: + throw(Exception( + AZStd::string::format("Unexpected execution failure policy: %u", aznumeric_cast(executionFailurePolicy)))); + } + } + + AZStd::string FailedTestCoveragePolicyAsString(Policy::FailedTestCoverage failedTestCoveragePolicy) + { + switch (failedTestCoveragePolicy) + { + case Policy::FailedTestCoverage::Discard: + return "discard"; + case Policy::FailedTestCoverage::Keep: + return "keep"; + default: + throw(Exception( + AZStd::string::format("Unexpected failed test coverage policy: %u", aznumeric_cast(failedTestCoveragePolicy)))); + } + } + + AZStd::string TestPrioritizationPolicyAsString(Policy::TestPrioritization testPrioritizationPolicy) + { + switch (testPrioritizationPolicy) + { + case Policy::TestPrioritization::DependencyLocality: + return "dependency_locality"; + case Policy::TestPrioritization::None: + return "none"; + default: + throw(Exception( + AZStd::string::format("Unexpected test prioritization policy: %u", aznumeric_cast(testPrioritizationPolicy)))); + } + } + + AZStd::string TestFailurePolicyAsString(Policy::TestFailure testFailurePolicy) + { + switch (testFailurePolicy) + { + case Policy::TestFailure::Abort: + return "abort"; + case Policy::TestFailure::Continue: + return "continue"; + default: + throw( + Exception(AZStd::string::format("Unexpected test failure policy: %u", aznumeric_cast(testFailurePolicy)))); + } + } + + AZStd::string IntegrityFailurePolicyAsString(Policy::IntegrityFailure integrityFailurePolicy) + { + switch (integrityFailurePolicy) + { + case Policy::IntegrityFailure::Abort: + return "abort"; + case Policy::IntegrityFailure::Continue: + return "continue"; + default: + throw(Exception( + AZStd::string::format("Unexpected integration failure policy: %u", aznumeric_cast(integrityFailurePolicy)))); + } + } + + AZStd::string DynamicDependencyMapPolicyAsString(Policy::DynamicDependencyMap dynamicDependencyMapPolicy) + { + switch (dynamicDependencyMapPolicy) + { + case Policy::DynamicDependencyMap::Discard: + return "discard"; + case Policy::DynamicDependencyMap::Update: + return "update"; + default: + throw(Exception(AZStd::string::format( + "Unexpected dynamic dependency map policy: %u", aznumeric_cast(dynamicDependencyMapPolicy)))); + } + } + + AZStd::string TestShardingPolicyAsString(Policy::TestSharding testShardingPolicy) + { + switch (testShardingPolicy) + { + case Policy::TestSharding::Always: + return "always"; + case Policy::TestSharding::Never: + return "never"; + default: + throw(Exception( + AZStd::string::format("Unexpected test sharding policy: %u", aznumeric_cast(testShardingPolicy)))); + } + } + + AZStd::string TargetOutputCapturePolicyAsString(Policy::TargetOutputCapture targetOutputCapturePolicy) + { + switch (targetOutputCapturePolicy) + { + case Policy::TargetOutputCapture::File: + return "file"; + case Policy::TargetOutputCapture::None: + return "none"; + case Policy::TargetOutputCapture::StdOut: + return "stdout"; + case Policy::TargetOutputCapture::StdOutAndFile: + return "stdout_file"; + default: + throw(Exception( + AZStd::string::format("Unexpected target output capture policy: %u", aznumeric_cast(targetOutputCapturePolicy)))); + } + } + + AZStd::string ClientTestResultAsString(Client::TestResult result) + { + switch (result) + { + case Client::TestResult::Failed: + return "failed"; + case Client::TestResult::NotRun: + return "not_run"; + case Client::TestResult::Passed: + return "passed"; + default: + throw(Exception(AZStd::string::format("Unexpected client test case result: %u", aznumeric_cast(result)))); + } + } +} // namespace TestImpact diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/testimpactframework_runtime_files.cmake b/Code/Tools/TestImpactFramework/Runtime/Code/testimpactframework_runtime_files.cmake index 76673d9f40..75f253ad27 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/testimpactframework_runtime_files.cmake +++ b/Code/Tools/TestImpactFramework/Runtime/Code/testimpactframework_runtime_files.cmake @@ -16,11 +16,14 @@ set(FILES Include/TestImpactFramework/TestImpactChangelist.h Include/TestImpactFramework/TestImpactChangelistSerializer.h Include/TestImpactFramework/TestImpactChangelistException.h + Include/TestImpactFramework/TestImpactPolicy.h Include/TestImpactFramework/TestImpactTestSequence.h Include/TestImpactFramework/TestImpactClientTestSelection.h Include/TestImpactFramework/TestImpactClientTestRun.h Include/TestImpactFramework/TestImpactClientSequenceReport.h - Include/TestImpactFramework/TestImpactFileUtils.h + Include/TestImpactFramework/TestImpactUtils.h + Include/TestImpactFramework/TestImpactClientSequenceReportSerializer.h + Include/TestImpactFramework/TestImpactSequenceReportException.h Source/Artifact/TestImpactArtifactException.h Source/Artifact/Factory/TestImpactBuildTargetDescriptorFactory.cpp Source/Artifact/Factory/TestImpactBuildTargetDescriptorFactory.h @@ -125,5 +128,7 @@ set(FILES Source/TestImpactClientTestRun.cpp Source/TestImpactClientSequenceReport.cpp Source/TestImpactChangeListSerializer.cpp + Source/TestImpactClientSequenceReportSerializer.cpp Source/TestImpactRepoPath.cpp + Source/TestImpactUtils.cpp ) diff --git a/cmake/TestImpactFramework/ConsoleFrontendConfig.in b/cmake/TestImpactFramework/ConsoleFrontendConfig.in index e4111fb9cd..17fbd217d7 100644 --- a/cmake/TestImpactFramework/ConsoleFrontendConfig.in +++ b/cmake/TestImpactFramework/ConsoleFrontendConfig.in @@ -1,7 +1,8 @@ { "meta": { "platform": "${platform}", - "timestamp": "${timestamp}" + "timestamp": "${timestamp}", + "build_config": "${build_config}" }, "jenkins": { "use_test_impact_analysis": ${use_tiaf} @@ -32,8 +33,7 @@ "historic": { "root": "${historic_dir}", "relative_paths": { - "last_run_hash_file": "last_run.hash", - "last_build_target_list_file": "LastRunBuildTargets.json" + "data": "historic_data.json" } } }, diff --git a/cmake/TestImpactFramework/LYTestImpactFramework.cmake b/cmake/TestImpactFramework/LYTestImpactFramework.cmake index 61cc8c200a..7dd2617582 100644 --- a/cmake/TestImpactFramework/LYTestImpactFramework.cmake +++ b/cmake/TestImpactFramework/LYTestImpactFramework.cmake @@ -22,10 +22,10 @@ set(LY_TEST_IMPACT_CONSOLE_TARGET "TestImpact.Frontend.Console") set(LY_TEST_IMPACT_WORKING_DIR "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/TestImpactFramework") # Directory for artifacts generated at runtime -set(LY_TEST_IMPACT_TEMP_DIR "${LY_TEST_IMPACT_WORKING_DIR}/Temp") +set(LY_TEST_IMPACT_TEMP_DIR "${LY_TEST_IMPACT_WORKING_DIR}/$/Temp") # Directory for files that persist between runtime runs -set(LY_TEST_IMPACT_PERSISTENT_DIR "${LY_TEST_IMPACT_WORKING_DIR}/Persistent") +set(LY_TEST_IMPACT_PERSISTENT_DIR "${LY_TEST_IMPACT_WORKING_DIR}/$/Persistent") # Directory for static artifacts produced as part of the build system generation process set(LY_TEST_IMPACT_ARTIFACT_DIR "${LY_TEST_IMPACT_WORKING_DIR}/Artifact") @@ -43,7 +43,7 @@ set(LY_TEST_IMPACT_TEST_TYPE_FILE "${LY_TEST_IMPACT_ARTIFACT_DIR}/TestType/All.t set(LY_TEST_IMPACT_GEM_TARGET_FILE "${LY_TEST_IMPACT_ARTIFACT_DIR}/BuildType/All.gems") # Path to the config file for each build configuration -set(LY_TEST_IMPACT_CONFIG_FILE_PATH "${LY_TEST_IMPACT_PERSISTENT_DIR}/tiaf.$.json") +set(LY_TEST_IMPACT_CONFIG_FILE_PATH "${LY_TEST_IMPACT_PERSISTENT_DIR}/tiaf.json") # Preprocessor directive for the config file path set(LY_TEST_IMPACT_CONFIG_FILE_PATH_DEFINITION "LY_TEST_IMPACT_DEFAULT_CONFIG_FILE=\"${LY_TEST_IMPACT_CONFIG_FILE_PATH}\"") @@ -379,6 +379,9 @@ function(ly_test_impact_write_config_file CONFIG_TEMPLATE_FILE BIN_DIR) # Timestamp this config file was generated at string(TIMESTAMP timestamp "%Y-%m-%d %H:%M:%S") + # Build configuration this config file is being generated for + set(build_config "$") + # Instrumentation binary if(NOT LY_TEST_IMPACT_INSTRUMENTATION_BIN) # No binary specified is not an error, it just means that the test impact analysis part of the framework is disabled diff --git a/scripts/build/Platform/Windows/build_config.json b/scripts/build/Platform/Windows/build_config.json index 235e1406ab..8ac0b5241c 100644 --- a/scripts/build/Platform/Windows/build_config.json +++ b/scripts/build/Platform/Windows/build_config.json @@ -89,7 +89,7 @@ "CONFIGURATION": "profile", "SCRIPT_PATH": "scripts/build/TestImpactAnalysis/tiaf_driver.py", "SCRIPT_PARAMETERS": - "--config=\"!OUTPUT_DIRECTORY!/bin/TestImpactFramework/persistent/tiaf.profile.json\" --suite=main --test-failure-policy=continue --src-branch=!BRANCH_NAME! --dst-branch=!CHANGE_TARGET! --pipeline=!PIPELINE_NAME! --dest-commit=!CHANGE_ID! --seeding-branches=!BUILD_SNAPSHOTS! --seeding-pipelines=default" + "--config=\"!OUTPUT_DIRECTORY!/bin/TestImpactFramework/profile/Persistent/tiaf.json\" --src-branch=!BRANCH_NAME! --dst-branch=!BRANCH_NAME! --commit=!CHANGE_ID! --s3-bucket=!TEST_IMPACT_S3_BUCKET! --mars-index-prefix=jonawals --suite=main --test-failure-policy=continue" } }, "debug_vs2019": { diff --git a/scripts/build/TestImpactAnalysis/git_utils.py b/scripts/build/TestImpactAnalysis/git_utils.py index ec31ab1f53..04d994ba4a 100644 --- a/scripts/build/TestImpactAnalysis/git_utils.py +++ b/scripts/build/TestImpactAnalysis/git_utils.py @@ -6,34 +6,67 @@ # # -import os import subprocess import git +import pathlib -# Returns True if the dst commit descends from the src commit, otherwise False -def is_descendent(src_commit_hash, dst_commit_hash): - if src_commit_hash is None or dst_commit_hash is None: - return False - result = subprocess.run(["git", "merge-base", "--is-ancestor", src_commit_hash, dst_commit_hash]) - return result.returncode == 0 - -# Attempts to create a diff from the src and dst commits and write to the specified output file -def create_diff_file(src_commit_hash, dst_commit_hash, output_path): - if os.path.isfile(output_path): - os.remove(output_path) - os.makedirs(os.path.dirname(output_path), exist_ok=True) - # git diff will only write to the output file if both commit hashes are valid - subprocess.run(["git", "diff", "--name-status", f"--output={output_path}", src_commit_hash, dst_commit_hash]) - if not os.path.isfile(output_path): - raise FileNotFoundError(f"Source commit '{src_commit_hash}' and/or destination commit '{dst_commit_hash}' are invalid") - -# Basic representation of a repository +# Basic representation of a git repository class Repo: - def __init__(self, repo_path): - self.__repo = git.Repo(repo_path) + def __init__(self, repo_path: str): + self._repo = git.Repo(repo_path) # Returns the current branch @property def current_branch(self): - branch = self.__repo.active_branch + branch = self._repo.active_branch return branch.name + + def create_diff_file(self, src_commit_hash: str, dst_commit_hash: str, output_path: pathlib.Path): + """ + Attempts to create a diff from the src and dst commits and write to the specified output file. + + @param src_commit_hash: The hash for the source commit. + @param dst_commit_hash: The hash for the destination commit. + @param output_path: The path to the file to write the diff to. + """ + + try: + # Remove the existing file (if any) and create the parent directory + output_path.unlink(missing_ok=True) + output_path.parent.mkdir(exist_ok=True) + except EnvironmentError as e: + raise RuntimeError(f"Could not create path for output file '{output_path}'") + + # git diff will only write to the output file if both commit hashes are valid + subprocess.run(["git", "diff", "--name-status", f"--output={output_path}", src_commit_hash, dst_commit_hash]) + if not output_path.is_file(): + raise RuntimeError(f"Source commit '{src_commit_hash}' and/or destination commit '{dst_commit_hash}' are invalid") + + def is_descendent(self, src_commit_hash: str, dst_commit_hash: str): + """ + Determines whether or not dst_commit is a descendent of src_commit. + + @param src_commit_hash: The hash for the source commit. + @param dst_commit_hash: The hash for the destination commit. + @return: True if the dst commit descends from the src commit, otherwise False. + """ + + if not src_commit_hash and not dst_commit_hash: + return False + result = subprocess.run(["git", "merge-base", "--is-ancestor", src_commit_hash, dst_commit_hash]) + return result.returncode == 0 + + # Returns the distance between two commits + def commit_distance(self, src_commit_hash: str, dst_commit_hash: str): + """ + Determines the number of commits between src_commit and dst_commit. + + @param src_commit_hash: The hash for the source commit. + @param dst_commit_hash: The hash for the destination commit. + @return: The distance between src_commit and dst_commit (if both are valid commits), otherwise None. + """ + + if not src_commit_hash and not dst_commit_hash: + return None + commits = self._repo.iter_commits(src_commit_hash + '..' + dst_commit_hash) + return len(list(commits)) diff --git a/scripts/build/TestImpactAnalysis/mars_utils.py b/scripts/build/TestImpactAnalysis/mars_utils.py new file mode 100644 index 0000000000..d25aafb664 --- /dev/null +++ b/scripts/build/TestImpactAnalysis/mars_utils.py @@ -0,0 +1,452 @@ +# +# Copyright (c) Contributors to the Open 3D Engine Project. +# For complete copyright and license terms please see the LICENSE at the root of this distribution. +# +# SPDX-License-Identifier: Apache-2.0 OR MIT +# +# + +import datetime +import json +import socket +from tiaf_logger import get_logger + +logger = get_logger(__file__) + +MARS_JOB_KEY = "job" +SRC_COMMIT_KEY = "src_commit" +DST_COMMIT_KEY = "src_commit" +COMMIT_DISTANCE_KEY = "commit_distance" +SRC_BRANCH_KEY = "src_branch" +DST_BRANCH_KEY = "dst_branch" +SUITE_KEY = "suite" +SOURCE_OF_TRUTH_BRANCH_KEY = "source_of_truth_branch" +IS_SOURCE_OF_TRUTH_BRANCH_KEY = "is_source_of_truth_branch" +USE_TEST_IMPACT_ANALYSIS_KEY = "use_test_impact_analysis" +HAS_CHANGE_LIST_KEY = "has_change_list" +HAS_HISTORIC_DATA_KEY = "has_historic_data" +S3_BUCKET_KEY = "s3_bucket" +DRIVER_ARGS_KEY = "driver_args" +RUNTIME_ARGS_KEY = "runtime_args" +RUNTIME_RETURN_CODE_KEY = "return_code" +NAME_KEY = "name" +RESULT_KEY = "result" +NUM_PASSING_TESTS_KEY = "num_passing_tests" +NUM_FAILING_TESTS_KEY = "num_failing_tests" +NUM_DISABLED_TESTS_KEY = "num_disabled_tests" +COMMAND_ARGS_STRING = "command_args" +NUM_PASSING_TEST_RUNS_KEY = "num_passing_test_runs" +NUM_FAILING_TEST_RUNS_KEY = "num_failing_test_runs" +NUM_EXECUTION_FAILURE_TEST_RUNS_KEY = "num_execution_failure_test_runs" +NUM_TIMED_OUT_TEST_RUNS_KEY = "num_timed_out_test_runs" +NUM_UNEXECUTED_TEST_RUNS_KEY = "num_unexecuted_test_runs" +TOTAL_NUM_PASSING_TESTS_KEY = "total_num_passing_tests" +TOTAL_NUM_FAILING_TESTS_KEY = "total_num_failing_tests" +TOTAL_NUM_DISABLED_TESTS_KEY = "total_num_disabled_tests" +START_TIME_KEY = "start_time" +END_TIME_KEY = "end_time" +DURATION_KEY = "duration" +INCLUDED_TEST_RUNS_KEY = "included_test_runs" +EXCLUDED_TEST_RUNS_KEY = "excluded_test_runs" +NUM_INCLUDED_TEST_RUNS_KEY = "num_included_test_runs" +NUM_EXCLUDED_TEST_RUNS_KEY = "num_excluded_test_runs" +TOTAL_NUM_TEST_RUNS_KEY = "total_num_test_runs" +PASSING_TEST_RUNS_KEY = "passing_test_runs" +FAILING_TEST_RUNS_KEY = "failing_test_runs" +EXECUTION_FAILURE_TEST_RUNS_KEY = "execution_failure_test_runs" +TIMED_OUT_TEST_RUNS_KEY = "timed_out_test_runs" +UNEXECUTED_TEST_RUNS_KEY = "unexecuted_test_runs" +TOTAL_NUM_PASSING_TEST_RUNS_KEY = "total_num_passing_test_runs" +TOTAL_NUM_FAILING_TEST_RUNS_KEY = "total_num_failing_test_runs" +TOTAL_NUM_EXECUTION_FAILURE_TEST_RUNS_KEY = "total_num_execution_failure_test_runs" +TOTAL_NUM_TIMED_OUT_TEST_RUNS_KEY = "total_num_timed_out_test_runs" +TOTAL_NUM_UNEXECUTED_TEST_RUNS_KEY = "total_num_unexecuted_test_runs" +SEQUENCE_TYPE_KEY = "type" +IMPACT_ANALYSIS_SEQUENCE_TYPE_KEY = "impact_analysis" +SAFE_IMPACT_ANALYSIS_SEQUENCE_TYPE_KEY = "safe_impact_analysis" +SEED_SEQUENCE_TYPE_KEY = "seed" +TEST_TARGET_TIMEOUT_KEY = "test_target_timeout" +GLOBAL_TIMEOUT_KEY = "global_timeout" +MAX_CONCURRENCY_KEY = "max_concurrency" +SELECTED_KEY = "selected" +DRAFTED_KEY = "drafted" +DISCARDED_KEY = "discarded" +SELECTED_TEST_RUN_REPORT_KEY = "selected_test_run_report" +DISCARDED_TEST_RUN_REPORT_KEY = "discarded_test_run_report" +DRAFTED_TEST_RUN_REPORT_KEY = "drafted_test_run_report" +SELECTED_TEST_RUNS_KEY = "selected_test_runs" +DRAFTED_TEST_RUNS_KEY = "drafted_test_runs" +DISCARDED_TEST_RUNS_KEY = "discarded_test_runs" +INSTRUMENTATION_KEY = "instrumentation" +EFFICIENCY_KEY = "efficiency" +CONFIG_KEY = "config" +POLICY_KEY = "policy" +CHANGE_LIST_KEY = "change_list" +TEST_RUN_SELECTION_KEY = "test_run_selection" +DYNAMIC_DEPENDENCY_MAP_POLICY_KEY = "dynamic_dependency_map" +DYNAMIC_DEPENDENCY_MAP_POLICY_UPDATE_KEY = "update" +REPORT_KEY = "report" + +class FilebeatExn(Exception): + pass + +class FilebeatClient(object): + def __init__(self, host="127.0.0.1", port=9000, timeout=20): + self._filebeat_host = host + self._filebeat_port = port + self._socket_timeout = timeout + self._socket = None + + self._open_socket() + + def send_event(self, payload, index, timestamp=None, pipeline="filebeat"): + if timestamp is None: + timestamp = datetime.datetime.utcnow().timestamp() + + event = { + "index": index, + "timestamp": timestamp, + "pipeline": pipeline, + "payload": json.dumps(payload) + } + + # Serialise event, add new line and encode as UTF-8 before sending to Filebeat. + data = json.dumps(event, sort_keys=True) + "\n" + data = data.encode() + + #print(f"-> {data}") + self._send_data(data) + + def _open_socket(self): + logger.info(f"Connecting to Filebeat on {self._filebeat_host}:{self._filebeat_port}") + + self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self._socket.settimeout(self._socket_timeout) + + try: + self._socket.connect((self._filebeat_host, self._filebeat_port)) + except (ConnectionError, socket.timeout): + raise FilebeatExn("Failed to connect to Filebeat") from None + + def _send_data(self, data): + total_sent = 0 + + while total_sent < len(data): + try: + sent = self._socket.send(data[total_sent:]) + except BrokenPipeError: + logging.error("Filebeat socket closed by peer") + self._socket.close() + self._open_socket() + total_sent = 0 + else: + total_sent = total_sent + sent + +def format_timestamp(timestamp: float): + """ + Formats the given floating point timestamp into "yyyy-MM-dd'T'HH:mm:ss.SSSXX" format. + + @param timestamp: The timestamp to format. + @return: The formatted timestamp. + """ + return datetime.datetime.utcfromtimestamp(timestamp).strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3] + "Z" + +def generate_mars_timestamp(t0_offset_milliseconds: int, t0_timestamp: float): + """ + Generates a MARS timestamp in the format "yyyy-MM-dd'T'HH:mm:ss.SSSXX" by offsetting the T0 timestamp + by the specified amount of milliseconds. + + @param t0_offset_milliseconds: The amount of time to offset from T0. + @param t0_timestamp: The T0 timestamp that TIAF timings will be offst from. + @return: The formatted timestamp offset from T0 by the specified amount of milliseconds. + """ + + t0_offset_seconds = get_duration_in_seconds(t0_offset_milliseconds) + t0_offset_timestamp = t0_timestamp + t0_offset_seconds + return format_timestamp(t0_offset_timestamp) + +def get_duration_in_seconds(duration_in_milliseconds: int): + """ + Gets the specified duration in milliseconds (as used by TIAF) in seconds (as used my MARS documents). + + @param duration_in_milliseconds: The millisecond duration to transform into seconds. + @return: The duration in seconds. + """ + + return duration_in_milliseconds * 0.001 + +def generate_mars_job(tiaf_result, driver_args): + """ + Generates a MARS job document using the job meta-data used to drive the TIAF sequence. + + @param tiaf_result: The result object generated by the TIAF script. + @param driver_args: The arguments specified to the driver script. + @return: The MARS job document with the job meta-data. + """ + + mars_job = {key:tiaf_result[key] for key in + [ + SRC_COMMIT_KEY, + DST_COMMIT_KEY, + COMMIT_DISTANCE_KEY, + SRC_BRANCH_KEY, + DST_BRANCH_KEY, + SUITE_KEY, + SOURCE_OF_TRUTH_BRANCH_KEY, + IS_SOURCE_OF_TRUTH_BRANCH_KEY, + USE_TEST_IMPACT_ANALYSIS_KEY, + HAS_CHANGE_LIST_KEY, + HAS_HISTORIC_DATA_KEY, + S3_BUCKET_KEY, + RUNTIME_ARGS_KEY, + RUNTIME_RETURN_CODE_KEY + ]} + + mars_job[DRIVER_ARGS_KEY] = driver_args + return mars_job + +def generate_test_run_list(test_runs): + """ + Generates a list of test run name strings from the list of TIAF test runs. + + @param test_runs: The list of TIAF test runs to generate the name strings from. + @return: The list of test run name strings. + """ + + test_run_list = [] + for test_run in test_runs: + test_run_list.append(test_run[NAME_KEY]) + return test_run_list + +def generate_mars_test_run_selections(test_run_selection, test_run_report, t0_timestamp: float): + """ + Generates a list of MARS test run selections from a TIAF test run selection and report. + + @param test_run_selection: The TIAF test run selection. + @param test_run_report: The TIAF test run report. + @param t0_timestamp: The T0 timestamp that TIAF timings will be offst from. + @return: The list of TIAF test runs. + """ + + mars_test_run_selection = {key:test_run_report[key] for key in + [ + RESULT_KEY, + NUM_PASSING_TEST_RUNS_KEY, + NUM_FAILING_TEST_RUNS_KEY, + NUM_EXECUTION_FAILURE_TEST_RUNS_KEY, + NUM_TIMED_OUT_TEST_RUNS_KEY, + NUM_UNEXECUTED_TEST_RUNS_KEY, + TOTAL_NUM_PASSING_TESTS_KEY, + TOTAL_NUM_FAILING_TESTS_KEY, + TOTAL_NUM_DISABLED_TESTS_KEY + ]} + + mars_test_run_selection[START_TIME_KEY] = generate_mars_timestamp(test_run_report[START_TIME_KEY], t0_timestamp) + mars_test_run_selection[END_TIME_KEY] = generate_mars_timestamp(test_run_report[END_TIME_KEY], t0_timestamp) + mars_test_run_selection[DURATION_KEY] = get_duration_in_seconds(test_run_report[DURATION_KEY]) + + mars_test_run_selection[INCLUDED_TEST_RUNS_KEY] = test_run_selection[INCLUDED_TEST_RUNS_KEY] + mars_test_run_selection[EXCLUDED_TEST_RUNS_KEY] = test_run_selection[EXCLUDED_TEST_RUNS_KEY] + mars_test_run_selection[NUM_INCLUDED_TEST_RUNS_KEY] = test_run_selection[NUM_INCLUDED_TEST_RUNS_KEY] + mars_test_run_selection[NUM_EXCLUDED_TEST_RUNS_KEY] = test_run_selection[NUM_EXCLUDED_TEST_RUNS_KEY] + mars_test_run_selection[TOTAL_NUM_TEST_RUNS_KEY] = test_run_selection[TOTAL_NUM_TEST_RUNS_KEY] + + mars_test_run_selection[PASSING_TEST_RUNS_KEY] = generate_test_run_list(test_run_report[PASSING_TEST_RUNS_KEY]) + mars_test_run_selection[FAILING_TEST_RUNS_KEY] = generate_test_run_list(test_run_report[FAILING_TEST_RUNS_KEY]) + mars_test_run_selection[EXECUTION_FAILURE_TEST_RUNS_KEY] = generate_test_run_list(test_run_report[EXECUTION_FAILURE_TEST_RUNS_KEY]) + mars_test_run_selection[TIMED_OUT_TEST_RUNS_KEY] = generate_test_run_list(test_run_report[TIMED_OUT_TEST_RUNS_KEY]) + mars_test_run_selection[UNEXECUTED_TEST_RUNS_KEY] = generate_test_run_list(test_run_report[UNEXECUTED_TEST_RUNS_KEY]) + + return mars_test_run_selection + +def generate_test_runs_from_list(test_run_list: list): + """ + Generates a list of TIAF test runs from a list of test target name strings. + + @param test_run_list: The list of test target names. + @return: The list of TIAF test runs. + """ + + test_run_list = { + TOTAL_NUM_TEST_RUNS_KEY: len(test_run_list), + NUM_INCLUDED_TEST_RUNS_KEY: len(test_run_list), + NUM_EXCLUDED_TEST_RUNS_KEY: 0, + INCLUDED_TEST_RUNS_KEY: test_run_list, + EXCLUDED_TEST_RUNS_KEY: [] + } + + return test_run_list + +def generate_mars_sequence(sequence_report: dict, mars_job: dict, change_list:dict, t0_timestamp: float): + """ + Generates the MARS sequence document from the specified TIAF sequence report. + + @param sequence_report: The TIAF runtime sequence report. + @param mars_job: The MARS job for this sequence. + @param change_list: The change list for which the TIAF sequence was run. + @param t0_timestamp: The T0 timestamp that TIAF timings will be offst from. + @return: The MARS sequence document for the specified TIAF sequence report. + """ + + mars_sequence = {key:sequence_report[key] for key in + [ + SEQUENCE_TYPE_KEY, + RESULT_KEY, + POLICY_KEY, + TOTAL_NUM_TEST_RUNS_KEY, + TOTAL_NUM_PASSING_TEST_RUNS_KEY, + TOTAL_NUM_FAILING_TEST_RUNS_KEY, + TOTAL_NUM_EXECUTION_FAILURE_TEST_RUNS_KEY, + TOTAL_NUM_TIMED_OUT_TEST_RUNS_KEY, + TOTAL_NUM_UNEXECUTED_TEST_RUNS_KEY, + TOTAL_NUM_PASSING_TESTS_KEY, + TOTAL_NUM_FAILING_TESTS_KEY, + TOTAL_NUM_DISABLED_TESTS_KEY + ]} + + mars_sequence[START_TIME_KEY] = generate_mars_timestamp(sequence_report[START_TIME_KEY], t0_timestamp) + mars_sequence[END_TIME_KEY] = generate_mars_timestamp(sequence_report[END_TIME_KEY], t0_timestamp) + mars_sequence[DURATION_KEY] = get_duration_in_seconds(sequence_report[DURATION_KEY]) + + config = {key:sequence_report[key] for key in + [ + TEST_TARGET_TIMEOUT_KEY, + GLOBAL_TIMEOUT_KEY, + MAX_CONCURRENCY_KEY + ]} + + test_run_selection = {} + test_run_selection[SELECTED_KEY] = generate_mars_test_run_selections(sequence_report[SELECTED_TEST_RUNS_KEY], sequence_report[SELECTED_TEST_RUN_REPORT_KEY], t0_timestamp) + if sequence_report[SEQUENCE_TYPE_KEY] == IMPACT_ANALYSIS_SEQUENCE_TYPE_KEY or sequence_report[SEQUENCE_TYPE_KEY] == SAFE_IMPACT_ANALYSIS_SEQUENCE_TYPE_KEY: + total_test_runs = sequence_report[TOTAL_NUM_TEST_RUNS_KEY] + if total_test_runs > 0: + test_run_selection[SELECTED_KEY][EFFICIENCY_KEY] = (1.0 - (test_run_selection[SELECTED_KEY][TOTAL_NUM_TEST_RUNS_KEY] / total_test_runs)) * 100 + else: + test_run_selection[SELECTED_KEY][EFFICIENCY_KEY] = 100 + test_run_selection[DRAFTED_KEY] = generate_mars_test_run_selections(generate_test_runs_from_list(sequence_report[DRAFTED_TEST_RUNS_KEY]), sequence_report[DRAFTED_TEST_RUN_REPORT_KEY], t0_timestamp) + if sequence_report[SEQUENCE_TYPE_KEY] == SAFE_IMPACT_ANALYSIS_SEQUENCE_TYPE_KEY: + test_run_selection[DISCARDED_KEY] = generate_mars_test_run_selections(sequence_report[DISCARDED_TEST_RUNS_KEY], sequence_report[DISCARDED_TEST_RUN_REPORT_KEY], t0_timestamp) + else: + test_run_selection[SELECTED_KEY][EFFICIENCY_KEY] = 0 + + mars_sequence[MARS_JOB_KEY] = mars_job + mars_sequence[CONFIG_KEY] = config + mars_sequence[TEST_RUN_SELECTION_KEY] = test_run_selection + mars_sequence[CHANGE_LIST_KEY] = change_list + + return mars_sequence + +def extract_mars_test_target(test_run, instrumentation, mars_job, t0_timestamp: float): + """ + Extracts a MARS test target from the specified TIAF test run. + + @param test_run: The TIAF test run. + @param instrumentation: Flag specifying whether or not instrumentation was used for the test targets in this run. + @param mars_job: The MARS job for this test target. + @param t0_timestamp: The T0 timestamp that TIAF timings will be offst from. + @return: The MARS test target documents for the specified TIAF test target. + """ + + mars_test_run = {key:test_run[key] for key in + [ + NAME_KEY, + RESULT_KEY, + NUM_PASSING_TESTS_KEY, + NUM_FAILING_TESTS_KEY, + NUM_DISABLED_TESTS_KEY, + COMMAND_ARGS_STRING + ]} + + mars_test_run[START_TIME_KEY] = generate_mars_timestamp(test_run[START_TIME_KEY], t0_timestamp) + mars_test_run[END_TIME_KEY] = generate_mars_timestamp(test_run[END_TIME_KEY], t0_timestamp) + mars_test_run[DURATION_KEY] = get_duration_in_seconds(test_run[DURATION_KEY]) + + mars_test_run[MARS_JOB_KEY] = mars_job + mars_test_run[INSTRUMENTATION_KEY] = instrumentation + return mars_test_run + +def extract_mars_test_targets_from_report(test_run_report, instrumentation, mars_job, t0_timestamp: float): + """ + Extracts the MARS test targets from the specified TIAF test run report. + + @param test_run_report: The TIAF runtime test run report. + @param instrumentation: Flag specifying whether or not instrumentation was used for the test targets in this run. + @param mars_job: The MARS job for these test targets. + @param t0_timestamp: The T0 timestamp that TIAF timings will be offst from. + @return: The list of all MARS test target documents for the test targets in the TIAF test run report. + """ + + mars_test_targets = [] + + for test_run in test_run_report[PASSING_TEST_RUNS_KEY]: + mars_test_targets.append(extract_mars_test_target(test_run, instrumentation, mars_job, t0_timestamp)) + for test_run in test_run_report[FAILING_TEST_RUNS_KEY]: + mars_test_targets.append(extract_mars_test_target(test_run, instrumentation, mars_job, t0_timestamp)) + for test_run in test_run_report[EXECUTION_FAILURE_TEST_RUNS_KEY]: + mars_test_targets.append(extract_mars_test_target(test_run, instrumentation, mars_job, t0_timestamp)) + for test_run in test_run_report[TIMED_OUT_TEST_RUNS_KEY]: + mars_test_targets.append(extract_mars_test_target(test_run, instrumentation, mars_job, t0_timestamp)) + for test_run in test_run_report[UNEXECUTED_TEST_RUNS_KEY]: + mars_test_targets.append(extract_mars_test_target(test_run, instrumentation, mars_job, t0_timestamp)) + + return mars_test_targets + +def generate_mars_test_targets(sequence_report: dict, mars_job: dict, t0_timestamp: float): + """ + Generates a MARS test target document for each test target in the TIAF sequence report. + + @param sequence_report: The TIAF runtime sequence report. + @param mars_job: The MARS job for this sequence. + @param t0_timestamp: The T0 timestamp that TIAF timings will be offst from. + @return: The list of all MARS test target documents for the test targets in the TIAF sequence report. + """ + + mars_test_targets = [] + + # Determine whether or not the test targets were executed with instrumentation + if sequence_report[SEQUENCE_TYPE_KEY] == SEED_SEQUENCE_TYPE_KEY or sequence_report[SEQUENCE_TYPE_KEY] == SAFE_IMPACT_ANALYSIS_SEQUENCE_TYPE_KEY or (sequence_report[SEQUENCE_TYPE_KEY] == IMPACT_ANALYSIS_SEQUENCE_TYPE_KEY and sequence_report[POLICY_KEY][DYNAMIC_DEPENDENCY_MAP_POLICY_KEY] == DYNAMIC_DEPENDENCY_MAP_POLICY_UPDATE_KEY): + instrumentation = True + else: + instrumentation = False + + # Extract the MARS test target documents from each of the test run reports + mars_test_targets += extract_mars_test_targets_from_report(sequence_report[SELECTED_TEST_RUN_REPORT_KEY], instrumentation, mars_job, t0_timestamp) + if sequence_report[SEQUENCE_TYPE_KEY] == IMPACT_ANALYSIS_SEQUENCE_TYPE_KEY or sequence_report[SEQUENCE_TYPE_KEY] == SAFE_IMPACT_ANALYSIS_SEQUENCE_TYPE_KEY: + mars_test_targets += extract_mars_test_targets_from_report(sequence_report[DRAFTED_TEST_RUN_REPORT_KEY], instrumentation, mars_job, t0_timestamp) + if sequence_report[SEQUENCE_TYPE_KEY] == SAFE_IMPACT_ANALYSIS_SEQUENCE_TYPE_KEY: + mars_test_targets += extract_mars_test_targets_from_report(sequence_report[DISCARDED_TEST_RUN_REPORT_KEY], instrumentation, mars_job, t0_timestamp) + + return mars_test_targets + +def transmit_report_to_mars(mars_index_prefix: str, tiaf_result: dict, driver_args: list): + """ + Transforms the TIAF result into the appropriate MARS documents and transmits them to MARS. + + @param mars_index_prefix: The index prefix to be used for all MARS documents. + @param tiaf_result: The result object from the TIAF script. + @param driver_args: The arguments passed to the TIAF driver script. + """ + + try: + filebeat = FilebeatClient("localhost", 9000, 60) + + # T0 is the current timestamp that the report timings will be offset from + t0_timestamp = datetime.datetime.now().timestamp() + + # Generate and transmit the MARS job document + mars_job = generate_mars_job(tiaf_result, driver_args) + filebeat.send_event(mars_job, f"{mars_index_prefix}.tiaf.job") + + if tiaf_result[REPORT_KEY] is not None: + # Generate and transmit the MARS sequence document + mars_sequence = generate_mars_sequence(tiaf_result[REPORT_KEY], mars_job, tiaf_result[CHANGE_LIST_KEY], t0_timestamp) + filebeat.send_event(mars_sequence, f"{mars_index_prefix}.tiaf.sequence") + + # Generate and transmit the MARS test target documents + mars_test_targets = generate_mars_test_targets(tiaf_result[REPORT_KEY], mars_job, t0_timestamp) + for mars_test_target in mars_test_targets: + filebeat.send_event(mars_test_target, f"{mars_index_prefix}.tiaf.test_target") + except FilebeatExn as e: + logger.error(e) + except KeyError as e: + logger.error(f"The report does not contain the key {str(e)}.") \ No newline at end of file diff --git a/scripts/build/TestImpactAnalysis/tiaf.py b/scripts/build/TestImpactAnalysis/tiaf.py index ce869b975a..c368465ecc 100644 --- a/scripts/build/TestImpactAnalysis/tiaf.py +++ b/scripts/build/TestImpactAnalysis/tiaf.py @@ -6,237 +6,299 @@ # # -import os import json import subprocess import re -import git_utils +import uuid +import pathlib from git_utils import Repo -from enum import Enum +from tiaf_persistent_storage_local import PersistentStorageLocal +from tiaf_persistent_storage_s3 import PersistentStorageS3 +from tiaf_logger import get_logger -# Returns True if the specified child path is a child of the specified parent path, otherwise False -def is_child_path(parent_path, child_path): - parent_path = os.path.abspath(parent_path) - child_path = os.path.abspath(child_path) - return os.path.commonpath([os.path.abspath(parent_path)]) == os.path.commonpath([os.path.abspath(parent_path), os.path.abspath(child_path)]) +logger = get_logger(__file__) class TestImpact: - def __init__(self, config_file, dst_commit, src_branch, dst_branch, pipeline, seeding_branches, seeding_pipelines): - # Commit - self.__dst_commit = dst_commit - print(f"Commit: '{self.__dst_commit}'.") - self.__src_commit = None - self.__has_src_commit = False - # Branch - self.__src_branch = src_branch - print(f"Source branch: '{self.__src_branch}'.") - self.__dst_branch = dst_branch - print(f"Destination branch: '{self.__dst_branch}'.") - print(f"Seeding branches: '{seeding_branches}'.") - if self.__src_branch in seeding_branches: - self.__is_seeding_branch = True - else: - self.__is_seeding_branch = False - print(f"Is seeding branch: '{self.__is_seeding_branch}'.") - # Pipeline - self.__pipeline = pipeline - print(f"Pipeline: '{self.__pipeline}'.") - print(f"Seeding pipelines: '{seeding_pipelines}'.") - if self.__pipeline in seeding_pipelines: - self.__is_seeding_pipeline = True - else: - self.__is_seeding_pipeline = False - print(f"Is seeding pipeline: '{self.__is_seeding_pipeline}'.") - # Config - self.__parse_config_file(config_file) - # Sequence - if self.__is_seeding_branch and self.__is_seeding_pipeline: - self.__is_seeding = True - else: - self.__is_seeding = False - print(f"Is seeding: '{self.__is_seeding}'.") - if self.__use_test_impact_analysis and not self.__is_seeding: - self.__generate_change_list() + def __init__(self, config_file: str): + """ + Initializes the test impact model with the commit, branches as runtime configuration. - # Parse the configuration file and retrieve the data needed for launching the test impact analysis runtime - def __parse_config_file(self, config_file): - print(f"Attempting to parse configuration file '{config_file}'...") - with open(config_file, "r") as config_data: - config = json.load(config_data) - self.__repo_dir = config["repo"]["root"] - self.__repo = Repo(self.__repo_dir) - # TIAF - self.__use_test_impact_analysis = config["jenkins"]["use_test_impact_analysis"] - print(f"Is using test impact analysis: '{self.__use_test_impact_analysis}'.") - self.__tiaf_bin = config["repo"]["tiaf_bin"] - if self.__use_test_impact_analysis and not os.path.isfile(self.__tiaf_bin): - raise FileNotFoundError("Could not find tiaf binary") - # Workspaces - self.__active_workspace = config["workspace"]["active"]["root"] - self.__historic_workspace = config["workspace"]["historic"]["root"] - self.__temp_workspace = config["workspace"]["temp"]["root"] - # Last commit hash - last_commit_hash_path_file = config["workspace"]["historic"]["relative_paths"]["last_run_hash_file"] - self.__last_commit_hash_path = os.path.join(self.__historic_workspace, last_commit_hash_path_file) - print("The configuration file was parsed successfully.") + @param config_file: The runtime config file to obtain the runtime configuration data from. + """ - # Restricts change lists from checking in test impact analysis files - def __check_for_restricted_files(self, file_path): - if is_child_path(self.__active_workspace, file_path) or is_child_path(self.__historic_workspace, file_path) or is_child_path(self.__temp_workspace, file_path): - raise ValueError(f"Checking in test impact analysis framework files is illegal: '{file_path}''.") + self._has_change_list = False + self._parse_config_file(config_file) - def __read_last_run_hash(self): - self.__has_src_commit = False - if os.path.isfile(self.__last_commit_hash_path): - print(f"Previous commit hash found at '{self.__last_commit_hash_path}'.") - with open(self.__last_commit_hash_path) as file: - self.__src_commit = file.read() - self.__has_src_commit = True + def _parse_config_file(self, config_file: str): + """ + Parse the configuration file and retrieve the data needed for launching the test impact analysis runtime. - def __write_last_run_hash(self, last_run_hash): - os.makedirs(self.__historic_workspace, exist_ok=True) - f = open(self.__last_commit_hash_path, "w") - f.write(last_run_hash) - f.close() + @param config_file: The runtime config file to obtain the runtime configuration data from. + """ + + logger.info(f"Attempting to parse configuration file '{config_file}'...") + try: + with open(config_file, "r") as config_data: + self._config = json.load(config_data) + self._repo_dir = self._config["repo"]["root"] + self._repo = Repo(self._repo_dir) + + # TIAF + self._use_test_impact_analysis = self._config["jenkins"]["use_test_impact_analysis"] + self._tiaf_bin = pathlib.Path(self._config["repo"]["tiaf_bin"]) + if self._use_test_impact_analysis and not self._tiaf_bin.is_file(): + logger.warning(f"Could not find TIAF binary at location {self._tiaf_bin}, TIAF will be turned off.") + self._use_test_impact_analysis = False + + # Workspaces + self._active_workspace = self._config["workspace"]["active"]["root"] + self._historic_workspace = self._config["workspace"]["historic"]["root"] + self._temp_workspace = self._config["workspace"]["temp"]["root"] + logger.info("The configuration file was parsed successfully.") + except KeyError as e: + logger.error(f"The config does not contain the key {str(e)}.") + return + + def _attempt_to_generate_change_list(self, last_commit_hash, instance_id: str): + """ + Attempts to determine the change list bewteen now and the last tiaf run (if any). + + @param last_commit_hash: The commit hash of the last TIAF run. + @param instance_id: The unique id to derive the change list file name from. + """ + + self._has_change_list = False + self._change_list_path = None - # Determines the change list bewteen now and the last tiaf run (if any) - def __generate_change_list(self): - self.__has_change_list = False - self.__change_list_path = None # Check whether or not a previous commit hash exists (no hash is not a failure) - self.__read_last_run_hash() - if self.__has_src_commit == True: - if git_utils.is_descendent(self.__src_commit, self.__dst_commit) == False: - print(f"Source commit '{self.__src_commit}' and destination commit '{self.__dst_commit}' are not related.") + self._src_commit = last_commit_hash + if self._src_commit is not None: + if self._repo.is_descendent(self._src_commit, self._dst_commit) == False: + logger.info(f"Source commit '{self._src_commit}' and destination commit '{self._dst_commit}' are not related.") return - diff_path = os.path.join(self.__temp_workspace, "changelist.diff") + self._commit_distance = self._repo.commit_distance(self._src_commit, self._dst_commit) + diff_path = pathlib.Path(pathlib.PurePath(self._temp_workspace).joinpath(f"changelist.{instance_id}.diff")) try: - git_utils.create_diff_file(self.__src_commit, self.__dst_commit, diff_path) - except FileNotFoundError as e: - print(e) + self._repo.create_diff_file(self._src_commit, self._dst_commit, diff_path) + except RuntimeError as e: + logger.error(e) return + # A diff was generated, attempt to parse the diff and construct the change list - print(f"Generated diff between commits '{self.__src_commit}' and '{self.__dst_commit}': '{diff_path}'.") - change_list = {} - change_list["createdFiles"] = [] - change_list["updatedFiles"] = [] - change_list["deletedFiles"] = [] + logger.info(f"Generated diff between commits '{self._src_commit}' and '{self._dst_commit}': '{diff_path}'.") with open(diff_path, "r") as diff_data: lines = diff_data.readlines() for line in lines: match = re.split("^R[0-9]+\\s(\\S+)\\s(\\S+)", line) if len(match) > 1: # File rename - self.__check_for_restricted_files(match[1]) - self.__check_for_restricted_files(match[2]) # Treat renames as a deletion and an addition - change_list["deletedFiles"].append(match[1]) - change_list["createdFiles"].append(match[2]) + self._change_list["deletedFiles"].append(match[1]) + self._change_list["createdFiles"].append(match[2]) else: match = re.split("^[AMD]\\s(\\S+)", line) - self.__check_for_restricted_files(match[1]) if len(match) > 1: if line[0] == 'A': # File addition - change_list["createdFiles"].append(match[1]) + self._change_list["createdFiles"].append(match[1]) elif line[0] == 'M': # File modification - change_list["updatedFiles"].append(match[1]) + self._change_list["updatedFiles"].append(match[1]) elif line[0] == 'D': # File Deletion - change_list["deletedFiles"].append(match[1]) + self._change_list["deletedFiles"].append(match[1]) + # Serialize the change list to the JSON format the test impact analysis runtime expects - change_list_json = json.dumps(change_list, indent = 4) - change_list_path = os.path.join(self.__temp_workspace, "changelist.json") + change_list_json = json.dumps(self._change_list, indent = 4) + change_list_path = pathlib.PurePath(self._temp_workspace).joinpath(f"changelist.{instance_id}.json") f = open(change_list_path, "w") f.write(change_list_json) f.close() - print(f"Change list constructed successfully: '{change_list_path}'.") - print(f"{len(change_list['createdFiles'])} created files, {len(change_list['updatedFiles'])} updated files and {len(change_list['deletedFiles'])} deleted files.") + logger.info(f"Change list constructed successfully: '{change_list_path}'.") + logger.info(f"{len(self._change_list['createdFiles'])} created files, {len(self._change_list['updatedFiles'])} updated files and {len(self._change_list['deletedFiles'])} deleted files.") + # Note: an empty change list generated due to no changes between last and current commit is valid - self.__has_change_list = True - self.__change_list_path = change_list_path + self._has_change_list = True + self._change_list_path = change_list_path else: - print("No previous commit hash found, regular or seeded sequences only will be run.") - self.__has_change_list = False + logger.error("No previous commit hash found, regular or seeded sequences only will be run.") + self._has_change_list = False return - # Runs the specified test sequence - def run(self, suite, test_failure_policy, safe_mode, test_timeout, global_timeout): + def _generate_result(self, s3_bucket: str, suite: str, return_code: int, report: dict, runtime_args: list): + """ + Generates the result object from the pertinent runtime meta-data and sequence report. + + @param The generated result object. + """ + + result = {} + result["src_commit"] = self._src_commit + result["dst_commit"] = self._dst_commit + result["commit_distance"] = self._commit_distance + result["src_branch"] = self._src_branch + result["dst_branch"] = self._dst_branch + result["suite"] = suite + result["use_test_impact_analysis"] = self._use_test_impact_analysis + result["source_of_truth_branch"] = self._source_of_truth_branch + result["is_source_of_truth_branch"] = self._is_source_of_truth_branch + result["has_change_list"] = self._has_change_list + result["has_historic_data"] = self._has_historic_data + result["s3_bucket"] = s3_bucket + result["runtime_args"] = runtime_args + result["return_code"] = return_code + result["report"] = report + result["change_list"] = self._change_list + return result + + def run(self, commit: str, src_branch: str, dst_branch: str, s3_bucket: str, suite: str, test_failure_policy: str, safe_mode: bool, test_timeout: int, global_timeout: int): + """ + Determins the type of sequence to run based on the commit, source branch and test branch before running the + sequence with the specified values. + + @param commit: The commit hash of the changes to run test impact analysis on. + @param src_branch: If not equal to dst_branch, the branch that is being built. + @param dst_branch: If not equal to src_branch, the destination branch for the PR being built. + @param s3_bucket: Location of S3 bucket to use for persistent storage, otherwise local disk storage will be used. + @param suite: Test suite to run. + @param test_failure_policy: Test failure policy for regular and test impact sequences (ignored when seeding). + @param safe_mode: Flag to run impact analysis tests in safe mode (ignored when seeding). + @param test_timeout: Maximum run time (in seconds) of any test target before being terminated (unlimited if None). + @param global_timeout: Maximum run time of the sequence before being terminated (unlimited if None). + """ + args = [] - seed_sequence_test_failure_policy = "continue" - # Suite - args.append(f"--suite={suite}") - print(f"Test suite is set to '{suite}'.") - # Timeouts - if test_timeout != None: - args.append(f"--ttimeout={test_timeout}") - print(f"Test target timeout is set to {test_timeout} seconds.") - if global_timeout != None: - args.append(f"--gtimeout={global_timeout}") - print(f"Global sequence timeout is set to {test_timeout} seconds.") - if self.__use_test_impact_analysis: - print("Test impact analysis is enabled.") - # Seed sequences - if self.__is_seeding: + persistent_storage = None + self._has_historic_data = False + self._change_list = {} + self._change_list["createdFiles"] = [] + self._change_list["updatedFiles"] = [] + self._change_list["deletedFiles"] = [] + + # Branches + self._src_branch = src_branch + self._dst_branch = dst_branch + logger.info(f"Src branch: '{self._src_branch}'.") + logger.info(f"Dst branch: '{self._dst_branch}'.") + + # Source of truth (the branch from which the coverage data will be stored/retrieved from) + if self._dst_branch is None or self._src_branch == self._dst_branch: + # Branch builds are their own source of truth and will update the coverage data for the source of truth after any instrumented sequences complete + self._is_source_of_truth_branch = True + self._source_of_truth_branch = self._src_branch + else: + # PR builds use their destination as the source of truth and never update the coverage data for the source of truth + self._is_source_of_truth_branch = False + self._source_of_truth_branch = self._dst_branch + + logger.info(f"Source of truth branch: '{self._source_of_truth_branch}'.") + logger.info(f"Is source of truth branch: '{self._is_source_of_truth_branch}'.") + + # Commit + self._dst_commit = commit + logger.info(f"Commit: '{self._dst_commit}'.") + self._src_commit = None + self._commit_distance = None + + # Generate a unique ID to be used as part of the file name for required runtime dynamic artifacts. + instance_id = uuid.uuid4().hex + + if self._use_test_impact_analysis: + logger.info("Test impact analysis is enabled.") + try: + # Persistent storage location + if s3_bucket is not None: + persistent_storage = PersistentStorageS3(self._config, suite, s3_bucket, self._source_of_truth_branch) + else: + persistent_storage = PersistentStorageLocal(self._config, suite) + except SystemError as e: + logger.warning(f"The persistent storage encountered an irrecoverable error, test impact analysis will be disabled: '{e}'") + persistent_storage = None + + if persistent_storage is not None: + if persistent_storage.has_historic_data: + logger.info("Historic data found.") + self._attempt_to_generate_change_list(persistent_storage.last_commit_hash, instance_id) + else: + logger.info("No historic data found.") + # Sequence type - args.append("--sequence=seed") - print("Sequence type is set to 'seed'.") - # Test failure policy - args.append(f"--fpolicy={seed_sequence_test_failure_policy}") - print(f"Test failure policy is set to '{seed_sequence_test_failure_policy}'.") - # Impact analysis sequences - else: - if self.__has_change_list: - # Change list - args.append(f"--changelist={self.__change_list_path}") - print(f"Change list is set to '{self.__change_list_path}'.") - # Sequence type - args.append("--sequence=tianowrite") - print("Sequence type is set to 'tianowrite'.") - # Integrity failure policy - args.append("--ipolicy=continue") - print("Integration failure policy is set to 'continue'.") + if self._has_change_list: + if self._is_source_of_truth_branch: + # Use TIA sequence (instrumented subset of tests) for coverage updating branches so we can update the coverage data with the generated coverage + sequence_type = "tia" + else: + # Use TIA no-write sequence (regular subset of tests) for non coverage updating branche + sequence_type = "tianowrite" + # Ignore integrity failures for non coverage updating branches as our confidence in the + args.append("--ipolicy=continue") + logger.info("Integration failure policy is set to 'continue'.") # Safe mode if safe_mode: args.append("--safemode=on") - print("Safe mode set to 'on'.") + logger.info("Safe mode set to 'on'.") else: args.append("--safemode=off") - print("Safe mode set to 'off'.") + logger.info("Safe mode set to 'off'.") + # Change list + args.append(f"--changelist={self._change_list_path}") + logger.info(f"Change list is set to '{self._change_list_path}'.") else: - args.append("--sequence=regular") - print("Sequence type is set to 'regular'.") - # Test failure policy - args.append(f"--fpolicy={test_failure_policy}") - print(f"Test failure policy is set to '{test_failure_policy}'.") - else: - print("Test impact analysis is disabled.") - # Sequence type - args.append("--sequence=regular") - print("Sequence type is set to 'regular'.") - # Seeding job - if self.__is_seeding: - # Test failure policy - args.append(f"--fpolicy={seed_sequence_test_failure_policy}") - print(f"Test failure policy is set to '{seed_sequence_test_failure_policy}'.") - # Non seeding job + if self._is_source_of_truth_branch: + # Use seed sequence (instrumented all tests) for coverage updating branches so we can generate the coverage bed for future sequences + sequence_type = "seed" + # We always continue after test failures when seeding to ensure we capture the coverage for all test targets + test_failure_policy = "continue" + else: + # Use regular sequence (regular all tests) for non coverage updating branches as we have no coverage to use nor coverage to update + sequence_type = "regular" + # Ignore integrity failures for non coverage updating branches as our confidence in the + args.append("--ipolicy=continue") + logger.info("Integration failure policy is set to 'continue'.") else: - # Test failure policy - args.append(f"--fpolicy={test_failure_policy}") - print(f"Test failure policy is set to '{test_failure_policy}'.") - - print("Args: ", end='') - print(*args) - result = subprocess.run([self.__tiaf_bin] + args) - # If the sequence completed (with or without failures) we will update the historical meta-data - if result.returncode == 0 or result.returncode == 7: - print("Test impact analysis runtime returned successfully.") - if self.__is_seeding: - print("Writing historical meta-data...") - self.__write_last_run_hash(self.__dst_commit) - print("Complete!") + # Use regular sequence (regular all tests) when the persistent storage fails to avoid wasting time generating seed data that will not be preserved + sequence_type = "regular" else: - print(f"The test impact analysis runtime returned with error: '{result.returncode}'.") - return result.returncode - \ No newline at end of file + # Use regular sequence (regular all tests) when test impact analysis is disabled + sequence_type = "regular" + args.append(f"--sequence={sequence_type}") + logger.info(f"Sequence type is set to '{sequence_type}'.") + + # Test failure policy + args.append(f"--fpolicy={test_failure_policy}") + logger.info(f"Test failure policy is set to '{test_failure_policy}'.") + + # Sequence report + report_file = pathlib.PurePath(self._temp_workspace).joinpath(f"report.{instance_id}.json") + args.append(f"--report={report_file}") + logger.info(f"Sequence report file is set to '{report_file}'.") + + # Suite + args.append(f"--suite={suite}") + logger.info(f"Test suite is set to '{suite}'.") + + # Timeouts + if test_timeout != None: + args.append(f"--ttimeout={test_timeout}") + logger.info(f"Test target timeout is set to {test_timeout} seconds.") + if global_timeout != None: + args.append(f"--gtimeout={global_timeout}") + logger.info(f"Global sequence timeout is set to {test_timeout} seconds.") + + # Run sequence + unpacked_args = " ".join(args) + logger.info(f"Args: {unpacked_args}") + runtime_result = subprocess.run([self._tiaf_bin] + args) + report = None + + # If the sequence completed (with or without failures) we will update the historical meta-data + if runtime_result.returncode == 0 or runtime_result.returncode == 7: + logger.info("Test impact analysis runtime returned successfully.") + if self._is_source_of_truth_branch and persistent_storage is not None: + persistent_storage.update_and_store_historic_data(self._dst_commit) + with open(report_file) as json_file: + report = json.load(json_file) + else: + logger.error(f"The test impact analysis runtime returned with error: '{runtime_result.returncode}'.") + + return self._generate_result(s3_bucket, suite, runtime_result.returncode, report, args) \ No newline at end of file diff --git a/scripts/build/TestImpactAnalysis/tiaf_driver.py b/scripts/build/TestImpactAnalysis/tiaf_driver.py index 77fc8c1fc2..c44232a38e 100644 --- a/scripts/build/TestImpactAnalysis/tiaf_driver.py +++ b/scripts/build/TestImpactAnalysis/tiaf_driver.py @@ -7,60 +7,136 @@ # import argparse -from tiaf import TestImpact - +import mars_utils import sys -import os -import datetime -import json -import socket +import pathlib +from tiaf import TestImpact +from tiaf_logger import get_logger + +logger = get_logger(__file__) def parse_args(): - def file_path(value): - if os.path.isfile(value): + def valid_file_path(value): + if pathlib.Path(value).is_file(): return value else: raise FileNotFoundError(value) - def timout_type(value): + def valid_timout_type(value): value = int(value) if value <= 0: raise ValueError("Timer values must be positive integers") return value - def test_failure_policy(value): + def valid_test_failure_policy(value): if value == "continue" or value == "abort" or value == "ignore": return value else: raise ValueError("Test failure policy must be 'abort', 'continue' or 'ignore'") parser = argparse.ArgumentParser() - parser.add_argument('--config', dest="config", type=file_path, help="Path to the test impact analysis framework configuration file", required=True) - parser.add_argument('--src-branch', dest="src_branch", help="The branch that is being build", required=True) - parser.add_argument('--dst-branch', dest="dst_branch", help="For PR builds, the destination branch to be merged to, otherwise empty") - parser.add_argument('--seeding-branches', dest="seeding_branches", type=lambda arg: arg.split(','), help="Comma separated branches that seeding will occur on", required=True) - parser.add_argument('--pipeline', dest="pipeline", help="Pipeline the test impact analysis framework is running on", required=True) - parser.add_argument('--seeding-pipelines', dest="seeding_pipelines", type=lambda arg: arg.split(','), help="Comma separated pipeline that seeding will occur on", required=True) - parser.add_argument('--dest-commit', dest="dst_commit", help="Commit to run test impact analysis on (ignored when seeding)", required=True) - parser.add_argument('--suite', dest="suite", help="Test suite to run", required=True) - parser.add_argument('--test-failure-policy', dest="test_failure_policy", type=test_failure_policy, help="Test failure policy for regular and test impact sequences (ignored when seeding)", required=True) - parser.add_argument('--safeMode', dest="safe_mode", action='store_true', help="Run impact analysis tests in safe mode (ignored when seeding)") - parser.add_argument('--testTimeout', dest="test_timeout", type=timout_type, help="Maximum run time (in seconds) of any test target before being terminated", required=False) - parser.add_argument('--globalTimeout', dest="global_timeout", type=timout_type, help="Maximum run time of the sequence before being terminated", required=False) - parser.set_defaults(test_timeout=None) - parser.set_defaults(global_timeout=None) + + # Configuration file path + parser.add_argument( + '--config', + type=valid_file_path, + help="Path to the test impact analysis framework configuration file", + required=True + ) + + # Source branch + parser.add_argument( + '--src-branch', + help="Branch that is being built", + required=True + ) + + # Destination branch + parser.add_argument( + '--dst-branch', + help="For PR builds, the destination branch to be merged to, otherwise empty", + required=False + ) + + # Commit hash + parser.add_argument( + '--commit', + help="Commit that is being built", + required=True + ) + + # S3 bucket + parser.add_argument( + '--s3-bucket', + help="Location of S3 bucket to use for persistent storage, otherwise local disk storage will be used", + required=False + ) + + # MARS index prefix + parser.add_argument( + '--mars-index-prefix', + help="Index prefix to use for MARS, otherwise no data will be tramsmitted to MARS", + required=False + ) + + # Test suite + parser.add_argument( + '--suite', + help="Test suite to run", + required=True + ) + + # Test failure policy + parser.add_argument( + '--test-failure-policy', + type=valid_test_failure_policy, + help="Test failure policy for regular and test impact sequences (ignored when seeding)", + required=True + ) + + # Safe mode + parser.add_argument( + '--safe-mode', + action='store_true', + help="Run impact analysis tests in safe mode (ignored when seeding)", + required=False + ) + + # Test timeout + parser.add_argument( + '--test-timeout', + type=valid_timout_type, + help="Maximum run time (in seconds) of any test target before being terminated", + required=False + ) + + # Global timeout + parser.add_argument( + '--global-timeout', + type=valid_timout_type, + help="Maximum run time of the sequence before being terminated", + required=False + ) + args = parser.parse_args() return args if __name__ == "__main__": + try: args = parse_args() - tiaf = TestImpact(args.config, args.dst_commit, args.src_branch, args.dst_branch, args.pipeline, args.seeding_branches, args.seeding_pipelines) - return_code = tiaf.run(args.suite, args.test_failure_policy, args.safe_mode, args.test_timeout, args.global_timeout) + tiaf = TestImpact(args.config) + tiaf_result = tiaf.run(args.commit, args.src_branch, args.dst_branch, args.s3_bucket, args.suite, args.test_failure_policy, args.safe_mode, args.test_timeout, args.global_timeout) + + if args.mars_index_prefix is not None: + logger.info("Transmitting report to MARS...") + mars_utils.transmit_report_to_mars(args.mars_index_prefix, tiaf_result, sys.argv) + + logger.info("Complete!") # Non-gating will be removed from this script and handled at the job level in SPEC-7413 - #sys.exit(return_code) + #sys.exit(result.return_code) sys.exit(0) except Exception as e: # Non-gating will be removed from this script and handled at the job level in SPEC-7413 - print(f"Exception caught by TIAF driver: {e}") + logger.error(f"Exception caught by TIAF driver: '{e}'.") diff --git a/scripts/build/TestImpactAnalysis/tiaf_logger.py b/scripts/build/TestImpactAnalysis/tiaf_logger.py new file mode 100644 index 0000000000..0acb9349d4 --- /dev/null +++ b/scripts/build/TestImpactAnalysis/tiaf_logger.py @@ -0,0 +1,20 @@ +# +# Copyright (c) Contributors to the Open 3D Engine Project. +# For complete copyright and license terms please see the LICENSE at the root of this distribution. +# +# SPDX-License-Identifier: Apache-2.0 OR MIT +# +# + +import logging +import sys + +def get_logger(name: str): + logger = logging.getLogger(name) + logger.setLevel(logging.INFO) + handler = logging.StreamHandler(sys.stdout) + handler.setLevel(logging.DEBUG) + formatter = logging.Formatter('[%(asctime)s][TIAF][%(levelname)s] %(message)s') + handler.setFormatter(formatter) + logger.addHandler(handler) + return logger \ No newline at end of file diff --git a/scripts/build/TestImpactAnalysis/tiaf_persistent_storage.py b/scripts/build/TestImpactAnalysis/tiaf_persistent_storage.py new file mode 100644 index 0000000000..750353651b --- /dev/null +++ b/scripts/build/TestImpactAnalysis/tiaf_persistent_storage.py @@ -0,0 +1,118 @@ +# +# Copyright (c) Contributors to the Open 3D Engine Project. +# For complete copyright and license terms please see the LICENSE at the root of this distribution. +# +# SPDX-License-Identifier: Apache-2.0 OR MIT +# +# + +import json +import pathlib +from abc import ABC, abstractmethod +from tiaf_logger import get_logger + +logger = get_logger(__file__) + +# Abstraction for the persistent storage required by TIAF to store and retrieve the branch coverage data and other meta-data +class PersistentStorage(ABC): + def __init__(self, config: dict, suite: str): + """ + Initializes the persistent storage into a state for which there is no historic data available. + + @param config: The runtime configuration to obtain the data file paths from. + @param suite: The test suite for which the historic data will be obtained for. + """ + + # Work on the assumption that there is no historic meta-data (a valid state to be in, should none exist) + self._last_commit_hash = None + self._has_historic_data = False + + try: + # The runtime expects the coverage data to be in the location specified in the config file (unless overridden with + # the --datafile command line argument, which the TIAF scripts do not do) + self._active_workspace = pathlib.Path(config["workspace"]["active"]["root"]) + unpacked_coverage_data_file = config["workspace"]["active"]["relative_paths"]["test_impact_data_files"][suite] + except KeyError as e: + raise SystemError(f"The config does not contain the key {str(e)}.") + + self._unpacked_coverage_data_file = self._active_workspace.joinpath(unpacked_coverage_data_file) + + def _unpack_historic_data(self, historic_data_json: str): + """ + Unpacks the historic data into the appropriate memory and disk locations. + + @param historic_data_json: The historic data in JSON format. + """ + + self._has_historic_data = False + + try: + historic_data = json.loads(historic_data_json) + self._last_commit_hash = historic_data["last_commit_hash"] + + # Create the active workspace directory where the coverage data file will be placed and unpack the coverage data so + # it is accessible by the runtime + self._active_workspace.mkdir(exist_ok=True) + with open(self._unpacked_coverage_data_file, "w", newline='\n') as coverage_data: + coverage_data.write(historic_data["coverage_data"]) + + self._has_historic_data = True + except json.JSONDecodeError: + logger.error("The historic data does not contain valid JSON.") + except KeyError as e: + logger.error(f"The historic data does not contain the key {str(e)}.") + except EnvironmentError as e: + logger.error(f"There was a problem the coverage data file '{self._unpacked_coverage_data_file}': '{e}'.") + + def _pack_historic_data(self, last_commit_hash: str): + """ + Packs the current historic data into a JSON file for serializing. + + @param last_commit_hash: The commit hash to associate the coverage data (and any other meta data) with. + @return: The packed historic data in JSON format. + """ + + try: + # Attempt to read the existing coverage data + if self._unpacked_coverage_data_file.is_file(): + with open(self._unpacked_coverage_data_file, "r") as coverage_data: + historic_data = {"last_commit_hash": last_commit_hash, "coverage_data": coverage_data.read()} + return json.dumps(historic_data) + else: + logger.info(f"No coverage data exists at location '{self._unpacked_coverage_data_file}'.") + except EnvironmentError as e: + logger.error(f"There was a problem the coverage data file '{self._unpacked_coverage_data_file}': '{e}'.") + except TypeError: + logger.error("The historic data could not be serialized to valid JSON.") + + return None + + @abstractmethod + def _store_historic_data(self, historic_data_json: str): + """ + Stores the historic data in the designated persistent storage location. + + @param historic_data_json: The historic data (in JSON format) to be stored in persistent storage. + """ + pass + + def update_and_store_historic_data(self, last_commit_hash: str): + """ + Updates the historic data and stores it in the designated persistent storage location. + + @param last_commit_hash: The commit hash to associate the coverage data (and any other meta data) with. + """ + + historic_data_json = self._pack_historic_data(last_commit_hash) + if historic_data_json is not None: + self._store_historic_data(historic_data_json) + else: + logger.info("The historic data could not be successfully stored.") + + @property + def has_historic_data(self): + return self._has_historic_data + + @property + def last_commit_hash(self): + return self._last_commit_hash \ No newline at end of file diff --git a/scripts/build/TestImpactAnalysis/tiaf_persistent_storage_local.py b/scripts/build/TestImpactAnalysis/tiaf_persistent_storage_local.py new file mode 100644 index 0000000000..ba9b58fbf3 --- /dev/null +++ b/scripts/build/TestImpactAnalysis/tiaf_persistent_storage_local.py @@ -0,0 +1,56 @@ +# +# Copyright (c) Contributors to the Open 3D Engine Project. +# For complete copyright and license terms please see the LICENSE at the root of this distribution. +# +# SPDX-License-Identifier: Apache-2.0 OR MIT +# +# + +import pathlib +import logging +from tiaf_persistent_storage import PersistentStorage +from tiaf_logger import get_logger + +logger = get_logger(__file__) + +# Implementation of local persistent storage +class PersistentStorageLocal(PersistentStorage): + def __init__(self, config: str, suite: str): + """ + Initializes the persistent storage with any local historic data available. + + @param config: The runtime config file to obtain the data file paths from. + @param suite: The test suite for which the historic data will be obtained for. + """ + + super().__init__(config, suite) + try: + # Attempt to obtain the local persistent data location specified in the runtime config file + self._historic_workspace = pathlib.Path(config["workspace"]["historic"]["root"]) + historic_data_file = pathlib.Path(config["workspace"]["historic"]["relative_paths"]["data"]) + + # Attempt to unpack the local historic data file + self._historic_data_file = self._historic_workspace.joinpath(historic_data_file) + if self._historic_data_file.is_file(): + with open(self._historic_data_file, "r") as historic_data_raw: + historic_data_json = historic_data_raw.read() + self._unpack_historic_data(historic_data_json) + + except KeyError as e: + raise SystemError(f"The config does not contain the key {str(e)}.") + except EnvironmentError as e: + raise SystemError(f"There was a problem the historic data file '{self._historic_data_file}': '{e}'.") + + def _store_historic_data(self, historic_data_json: str): + """ + Stores then historical data in historic workspace location specified in the runtime config file. + + @param historic_data_json: The historic data (in JSON format) to be stored in persistent storage. + """ + + try: + self._historic_workspace.mkdir(exist_ok=True) + with open(self._historic_data_file, "w") as historic_data_file: + historic_data_file.write(historic_data_json) + except EnvironmentError as e: + logger.error(f"There was a problem the historic data file '{self._historic_data_file}': '{e}'.") \ No newline at end of file diff --git a/scripts/build/TestImpactAnalysis/tiaf_persistent_storage_s3.py b/scripts/build/TestImpactAnalysis/tiaf_persistent_storage_s3.py new file mode 100644 index 0000000000..75c4bc93d5 --- /dev/null +++ b/scripts/build/TestImpactAnalysis/tiaf_persistent_storage_s3.py @@ -0,0 +1,87 @@ +# +# Copyright (c) Contributors to the Open 3D Engine Project. +# For complete copyright and license terms please see the LICENSE at the root of this distribution. +# +# SPDX-License-Identifier: Apache-2.0 OR MIT +# +# + +import boto3 +import botocore.exceptions +import zlib +import logging +from io import BytesIO +from tiaf_persistent_storage import PersistentStorage +from tiaf_logger import get_logger + +logger = get_logger(__file__) + +# Implementation of s3 bucket persistent storage +class PersistentStorageS3(PersistentStorage): + def __init__(self, config: dict, suite: str, s3_bucket: str, branch: str): + """ + Initializes the persistent storage with the specified s3 bucket. + + @param config: The runtime config file to obtain the data file paths from. + @param suite: The test suite for which the historic data will be obtained for. + @param s3_bucket: The s3 bucket to use for storing nd retrieving historic data. + """ + + super().__init__(config, suite) + + try: + # We store the historic data as compressed JSON + object_extension = "json.zip" + + # historic_data.json.zip is the file containing the coverage and meta-data of the last TIAF sequence run + historic_data_file = f"historic_data.{object_extension}" + + # The location of the data is in the form / so the build config of each branch gets its own historic data + self._dir = f'{branch}/{config["meta"]["build_config"]}' + self._historic_data_key = f'{self._dir}/{historic_data_file}' + + logger.info(f"Attempting to retrieve historic data for branch '{branch}' at location '{self._historic_data_key}' on bucket '{s3_bucket}'...") + self._s3 = boto3.resource("s3") + self._bucket = self._s3.Bucket(s3_bucket) + + # There is only one historic_data.json.zip in the specified location + for object in self._bucket.objects.filter(Prefix=self._historic_data_key): + logger.info(f"Historic data found for branch '{branch}'.") + + # Archive the existing object with the name of the existing last commit hash + archive_key = f"{self._dir}/archive/{self._last_commit_hash}.{object_extension}" + logger.info(f"Archiving existing historic data to {archive_key}...") + self._bucket.copy({"Bucket": self._bucket.name, "Key": self._historic_data_key}, archive_key) + + # Decode the historic data object into raw bytes + response = object.get() + file_stream = response['Body'] + + # Decompress and unpack the zipped historic data JSON + historic_data_json = zlib.decompress(file_stream.read()).decode('UTF-8') + self._unpack_historic_data(historic_data_json) + + return + except KeyError as e: + raise SystemError(f"The config does not contain the key {str(e)}.") + except botocore.exceptions.BotoCoreError as e: + raise SystemError(f"There was a problem with the s3 bucket: {e}") + except botocore.exceptions.ClientError as e: + raise SystemError(f"There was a problem with the s3 client: {e}") + + def _store_historic_data(self, historic_data_json: str): + """ + Stores then historical data in specified s3 bucket at the location //historical_data.json.zip. + + @param historic_data_json: The historic data (in JSON format) to be stored in persistent storage. + """ + + try: + data = BytesIO(zlib.compress(bytes(historic_data_json, "UTF-8"))) + logger.info(f"Uploading historic data to location '{self._historic_data_key}'...") + self._bucket.upload_fileobj(data, self._historic_data_key) + logger.info("Upload complete.") + except botocore.exceptions.BotoCoreError as e: + logger.error(f"There was a problem with the s3 bucket: {e}") + except botocore.exceptions.ClientError as e: + logger.error(f"There was a problem with the s3 client: {e}") \ No newline at end of file From 0005f2b9da7914fcbcac7a4eb799584bac7e81f4 Mon Sep 17 00:00:00 2001 From: AMZN-stankowi <4838196+AMZN-stankowi@users.noreply.github.com> Date: Tue, 10 Aug 2021 06:47:14 -0700 Subject: [PATCH 242/803] Updated skeleton logic: (#2957) Import all nodes as bones. O3DE's concept of a bone is different than AssImp's. Updated GetLocalSpaceBindPoseTransform to only use the offset matrix if the parent is also a bone. Results: All test assets I've tried match Blender's "Rest Position" when loaded in the Character tool. All test animations I've tried work generally as well as they worked before, and a few better. This resolves the issue that was originally opened, an internal test asset loaded the skeleton incorrectly. Signed-off-by: stankowi <4838196+AMZN-stankowi@users.noreply.github.com> --- .../SceneAPI/SceneBuilder/Importers/AssImpBoneImporter.cpp | 4 ---- .../SceneBuilder/Importers/AssImpImporterUtilities.cpp | 7 +------ 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpBoneImporter.cpp b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpBoneImporter.cpp index eeddf4a0b3..a42870c426 100644 --- a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpBoneImporter.cpp +++ b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpBoneImporter.cpp @@ -103,10 +103,6 @@ namespace AZ } } - if(!isBone) - { - return Events::ProcessingResult::Ignored; - } // If the current scene node (our eventual parent) contains bone data, we are not a root bone AZStd::shared_ptr createdBoneData; diff --git a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpImporterUtilities.cpp b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpImporterUtilities.cpp index 81feff7d69..d416324240 100644 --- a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpImporterUtilities.cpp +++ b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpImporterUtilities.cpp @@ -135,18 +135,13 @@ namespace AZ const aiBone* bone = FindFirstBoneByNodeName(node, boneByNameMap); if (bone) { - const DataTypes::MatrixType inverseOffsetMatrix = AssImpSDKWrapper::AssImpTypeConverter::ToTransform(bone->mOffsetMatrix).GetInverseFull(); - const aiBone* parentBone = FindFirstBoneByNodeName(node->mParent, boneByNameMap); if (parentBone) { + DataTypes::MatrixType inverseOffsetMatrix = AssImpSDKWrapper::AssImpTypeConverter::ToTransform(bone->mOffsetMatrix).GetInverseFull(); const DataTypes::MatrixType parentBoneOffsetMatrix = AssImpSDKWrapper::AssImpTypeConverter::ToTransform(parentBone->mOffsetMatrix); return parentBoneOffsetMatrix * inverseOffsetMatrix; } - else - { - return inverseOffsetMatrix; - } } return AssImpSDKWrapper::AssImpTypeConverter::ToTransform(GetConcatenatedLocalTransform(node)); From 2bf64879daa2a3210647a3737613c876775ea022 Mon Sep 17 00:00:00 2001 From: John Jones-Steele Date: Tue, 10 Aug 2021 14:52:09 +0100 Subject: [PATCH 243/803] Fixed the SpinBox tests Signed-off-by: John Jones-Steele --- .../AzToolsFramework/Tests/SpinBoxTests.cpp | 38 +++++++++++++------ 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/Code/Framework/AzToolsFramework/Tests/SpinBoxTests.cpp b/Code/Framework/AzToolsFramework/Tests/SpinBoxTests.cpp index eb09c68cee..a88cb68638 100644 --- a/Code/Framework/AzToolsFramework/Tests/SpinBoxTests.cpp +++ b/Code/Framework/AzToolsFramework/Tests/SpinBoxTests.cpp @@ -245,12 +245,15 @@ namespace UnitTest { using testing::StrEq; + QLocale testLocale{ QLocale() }; + QString testString = "10" + QString(testLocale.decimalPoint()) + "0"; + m_doubleSpinBox->setSuffix("m"); m_doubleSpinBox->setValue(10.0); // test internal logic (textFromValue() calls private StringValue()) QString value = m_doubleSpinBox->textFromValue(10.0); - EXPECT_THAT(value.toUtf8().constData(), StrEq("10.0")); + EXPECT_THAT(value.toUtf8().constData(), testString); m_doubleSpinBox->setFocus(); EXPECT_THAT(m_doubleSpinBox->suffix().toUtf8().constData(), StrEq("")); @@ -293,31 +296,44 @@ namespace UnitTest TEST_F(SpinBoxFixture, SpinBoxCheckHighValueTruncatesCorrectly) { - QString value = setupTruncationTest("0.9999999"); + QLocale testLocale{ QLocale() }; + QString testString = "0" + QString(testLocale.decimalPoint()) + "9999999"; + QString value = setupTruncationTest(testString); - EXPECT_TRUE(value == "0.999"); + testString = "0" + QString(testLocale.decimalPoint()) + "999"; + EXPECT_TRUE(value == testString); } TEST_F(SpinBoxFixture, SpinBoxCheckLowValueTruncatesCorrectly) { - QString value = setupTruncationTest("0.0000001"); + QLocale testLocale{ QLocale() }; + QString testString = "0" + QString(testLocale.decimalPoint()) + "0000001"; + QString value = setupTruncationTest(testString); - EXPECT_TRUE(value == "0.0"); + testString = "0" + QString(testLocale.decimalPoint()) + "0"; + EXPECT_TRUE(value == testString); } TEST_F(SpinBoxFixture, SpinBoxCheckBugValuesTruncatesCorrectly) { - QString value = setupTruncationTest("0.12395"); + QLocale testLocale{ QLocale() }; + QString testString = "0" + QString(testLocale.decimalPoint()) + "12395"; + QString value = setupTruncationTest(testString); - EXPECT_TRUE(value == "0.123"); + testString = "0" + QString(testLocale.decimalPoint()) + "123"; + EXPECT_TRUE(value == testString); - value = setupTruncationTest("0.94496"); + testString = "0" + QString(testLocale.decimalPoint()) + "94496"; + value = setupTruncationTest(testString); - EXPECT_TRUE(value == "0.944"); + testString = "0" + QString(testLocale.decimalPoint()) + "944"; + EXPECT_TRUE(value == testString); - value = setupTruncationTest("0.0009999"); + testString = "0" + QString(testLocale.decimalPoint()) + "0009999"; + value = setupTruncationTest(testString); - EXPECT_TRUE(value == "0.0"); + testString = "0" + QString(testLocale.decimalPoint()) + "0"; + EXPECT_TRUE(value == testString); } } // namespace UnitTest From 2be043ca96ccd08dbd74d114d6ca98158d381f1d Mon Sep 17 00:00:00 2001 From: John Date: Tue, 10 Aug 2021 15:13:19 +0100 Subject: [PATCH 244/803] Fix None comparisons in TIAF scripts. Signed-off-by: John --- scripts/build/TestImpactAnalysis/mars_utils.py | 4 ++-- scripts/build/TestImpactAnalysis/tiaf.py | 14 ++++++++------ scripts/build/TestImpactAnalysis/tiaf_driver.py | 2 +- .../TestImpactAnalysis/tiaf_persistent_storage.py | 2 +- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/scripts/build/TestImpactAnalysis/mars_utils.py b/scripts/build/TestImpactAnalysis/mars_utils.py index d25aafb664..69374512a3 100644 --- a/scripts/build/TestImpactAnalysis/mars_utils.py +++ b/scripts/build/TestImpactAnalysis/mars_utils.py @@ -100,7 +100,7 @@ class FilebeatClient(object): self._open_socket() def send_event(self, payload, index, timestamp=None, pipeline="filebeat"): - if timestamp is None: + if not timestamp: timestamp = datetime.datetime.utcnow().timestamp() event = { @@ -437,7 +437,7 @@ def transmit_report_to_mars(mars_index_prefix: str, tiaf_result: dict, driver_ar mars_job = generate_mars_job(tiaf_result, driver_args) filebeat.send_event(mars_job, f"{mars_index_prefix}.tiaf.job") - if tiaf_result[REPORT_KEY] is not None: + if tiaf_result[REPORT_KEY]: # Generate and transmit the MARS sequence document mars_sequence = generate_mars_sequence(tiaf_result[REPORT_KEY], mars_job, tiaf_result[CHANGE_LIST_KEY], t0_timestamp) filebeat.send_event(mars_sequence, f"{mars_index_prefix}.tiaf.sequence") diff --git a/scripts/build/TestImpactAnalysis/tiaf.py b/scripts/build/TestImpactAnalysis/tiaf.py index c368465ecc..c4d1449dbf 100644 --- a/scripts/build/TestImpactAnalysis/tiaf.py +++ b/scripts/build/TestImpactAnalysis/tiaf.py @@ -49,6 +49,8 @@ class TestImpact: if self._use_test_impact_analysis and not self._tiaf_bin.is_file(): logger.warning(f"Could not find TIAF binary at location {self._tiaf_bin}, TIAF will be turned off.") self._use_test_impact_analysis = False + else: + logger.info(f"Runtime binary found at location {self._tiaf_bin}") # Workspaces self._active_workspace = self._config["workspace"]["active"]["root"] @@ -72,7 +74,7 @@ class TestImpact: # Check whether or not a previous commit hash exists (no hash is not a failure) self._src_commit = last_commit_hash - if self._src_commit is not None: + if self._src_commit: if self._repo.is_descendent(self._src_commit, self._dst_commit) == False: logger.info(f"Source commit '{self._src_commit}' and destination commit '{self._dst_commit}' are not related.") return @@ -182,7 +184,7 @@ class TestImpact: logger.info(f"Dst branch: '{self._dst_branch}'.") # Source of truth (the branch from which the coverage data will be stored/retrieved from) - if self._dst_branch is None or self._src_branch == self._dst_branch: + if not self._dst_branch or self._src_branch == self._dst_branch: # Branch builds are their own source of truth and will update the coverage data for the source of truth after any instrumented sequences complete self._is_source_of_truth_branch = True self._source_of_truth_branch = self._src_branch @@ -207,7 +209,7 @@ class TestImpact: logger.info("Test impact analysis is enabled.") try: # Persistent storage location - if s3_bucket is not None: + if s3_bucket: persistent_storage = PersistentStorageS3(self._config, suite, s3_bucket, self._source_of_truth_branch) else: persistent_storage = PersistentStorageLocal(self._config, suite) @@ -215,7 +217,7 @@ class TestImpact: logger.warning(f"The persistent storage encountered an irrecoverable error, test impact analysis will be disabled: '{e}'") persistent_storage = None - if persistent_storage is not None: + if persistent_storage: if persistent_storage.has_historic_data: logger.info("Historic data found.") self._attempt_to_generate_change_list(persistent_storage.last_commit_hash, instance_id) @@ -278,10 +280,10 @@ class TestImpact: logger.info(f"Test suite is set to '{suite}'.") # Timeouts - if test_timeout != None: + if test_timeout is not None: args.append(f"--ttimeout={test_timeout}") logger.info(f"Test target timeout is set to {test_timeout} seconds.") - if global_timeout != None: + if global_timeout is not None: args.append(f"--gtimeout={global_timeout}") logger.info(f"Global sequence timeout is set to {test_timeout} seconds.") diff --git a/scripts/build/TestImpactAnalysis/tiaf_driver.py b/scripts/build/TestImpactAnalysis/tiaf_driver.py index c44232a38e..99f9de6eb9 100644 --- a/scripts/build/TestImpactAnalysis/tiaf_driver.py +++ b/scripts/build/TestImpactAnalysis/tiaf_driver.py @@ -129,7 +129,7 @@ if __name__ == "__main__": tiaf = TestImpact(args.config) tiaf_result = tiaf.run(args.commit, args.src_branch, args.dst_branch, args.s3_bucket, args.suite, args.test_failure_policy, args.safe_mode, args.test_timeout, args.global_timeout) - if args.mars_index_prefix is not None: + if args.mars_index_prefix: logger.info("Transmitting report to MARS...") mars_utils.transmit_report_to_mars(args.mars_index_prefix, tiaf_result, sys.argv) diff --git a/scripts/build/TestImpactAnalysis/tiaf_persistent_storage.py b/scripts/build/TestImpactAnalysis/tiaf_persistent_storage.py index 750353651b..18ea25091f 100644 --- a/scripts/build/TestImpactAnalysis/tiaf_persistent_storage.py +++ b/scripts/build/TestImpactAnalysis/tiaf_persistent_storage.py @@ -104,7 +104,7 @@ class PersistentStorage(ABC): """ historic_data_json = self._pack_historic_data(last_commit_hash) - if historic_data_json is not None: + if historic_data_json: self._store_historic_data(historic_data_json) else: logger.info("The historic data could not be successfully stored.") From e3221224bef798c5a51fd7d24b7f980173ef56a9 Mon Sep 17 00:00:00 2001 From: John Date: Tue, 10 Aug 2021 15:34:27 +0100 Subject: [PATCH 245/803] Add traceback to tiaf exception handler. Signed-off-by: John --- scripts/build/TestImpactAnalysis/tiaf_driver.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/build/TestImpactAnalysis/tiaf_driver.py b/scripts/build/TestImpactAnalysis/tiaf_driver.py index 99f9de6eb9..5ad16abaa0 100644 --- a/scripts/build/TestImpactAnalysis/tiaf_driver.py +++ b/scripts/build/TestImpactAnalysis/tiaf_driver.py @@ -10,6 +10,7 @@ import argparse import mars_utils import sys import pathlib +import traceback from tiaf import TestImpact from tiaf_logger import get_logger @@ -140,3 +141,4 @@ if __name__ == "__main__": except Exception as e: # Non-gating will be removed from this script and handled at the job level in SPEC-7413 logger.error(f"Exception caught by TIAF driver: '{e}'.") + traceback.print_exc() From 5dbbb93a06b95670e2983f804495d76eb5dfafcb Mon Sep 17 00:00:00 2001 From: John Date: Tue, 10 Aug 2021 15:49:19 +0100 Subject: [PATCH 246/803] Fix path for subprocess Signed-off-by: John --- scripts/build/TestImpactAnalysis/tiaf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/build/TestImpactAnalysis/tiaf.py b/scripts/build/TestImpactAnalysis/tiaf.py index c4d1449dbf..3c94c2b5f4 100644 --- a/scripts/build/TestImpactAnalysis/tiaf.py +++ b/scripts/build/TestImpactAnalysis/tiaf.py @@ -290,7 +290,7 @@ class TestImpact: # Run sequence unpacked_args = " ".join(args) logger.info(f"Args: {unpacked_args}") - runtime_result = subprocess.run([self._tiaf_bin] + args) + runtime_result = subprocess.run([str(self._tiaf_bin)] + args) report = None # If the sequence completed (with or without failures) we will update the historical meta-data From 44b053df58e135e087870910514b0dae3d8bbd76 Mon Sep 17 00:00:00 2001 From: SJ Date: Tue, 10 Aug 2021 08:10:37 -0700 Subject: [PATCH 247/803] [Mac] Building and running game projects from an SDK (#2943) * 1. Initial support for loading dylibs outside the bundle. 2. Child processes inherit parent's environment if no environment is explicitly specified(should change to append the parent's environment even if environment variables are explicitly specified). 3. Update some time functions to use system uptime instead of wall clock time when computing elapsed time. This fixes false timeouts when the OS goes to sleep. 4. Increase wait times for AssetBuilders and some Atom tools to connect to the AssetProcessor. This is needed because GateKeeper slows down first time bootup which results in asset processing failures. With this change we'll be able to run Editor and AssetProcessor from an install on Mac and we will also be able to build and run projects using the installed engine as an SDK. Signed-off-by: amzn-sj * 1. Remove debug messages. 2. Fix license 3. Pass parent's environment variables to child processes by default(on Mac). Signed-off-by: amzn-sj * 1. Add more detailed comments.2. Use a custom ly_copy for Mac and leave the default as is. Signed-off-by: amzn-sj * Address some feedback from review Signed-off-by: amzn-sj --- CMakeLists.txt | 2 +- Code/Editor/Platform/Mac/editor_mac.cmake | 24 ++++++ Code/Editor/Platform/Mac/gui_info.plist | 2 +- Code/Editor/Platform/Mac/main_dummy.cpp | 75 +++++++++++++++++++ .../Settings/SettingsRegistryMergeUtils.h | 1 + .../Common/Apple/AzCore/std/time_Apple.cpp | 48 +----------- .../Process/ProcessWatcher_Mac.cpp | 38 ++++------ .../Platform/Mac/assetprocessor_mac.cmake | 24 ++++++ .../Platform/Mac/gui_info.plist | 2 +- .../Platform/Mac/main_dummy.cpp | 75 +++++++++++++++++++ .../native/utilities/BuilderManager.cpp | 2 +- Gems/Atom/RHI/Code/Source/RHI.Edit/Utils.cpp | 2 +- cmake/Platform/Common/Install_common.cmake | 8 +- cmake/Platform/Mac/Install_mac.cmake | 50 +++++++++++++ cmake/Platform/Mac/LYWrappers_mac.cmake | 1 + 15 files changed, 278 insertions(+), 76 deletions(-) create mode 100644 Code/Editor/Platform/Mac/main_dummy.cpp create mode 100644 Code/Tools/AssetProcessor/Platform/Mac/main_dummy.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 0a38177714..bd02eeb7ff 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,8 +28,8 @@ include(cmake/FileUtil.cmake) include(cmake/PAL.cmake) include(cmake/PALTools.cmake) include(cmake/RuntimeDependencies.cmake) -include(cmake/Install.cmake) include(cmake/Configurations.cmake) # Requires to be after PAL so we get platform variable definitions +include(cmake/Install.cmake) include(cmake/Dependencies.cmake) include(cmake/Deployment.cmake) include(cmake/3rdParty.cmake) diff --git a/Code/Editor/Platform/Mac/editor_mac.cmake b/Code/Editor/Platform/Mac/editor_mac.cmake index 2afbee4251..fdccfafb46 100644 --- a/Code/Editor/Platform/Mac/editor_mac.cmake +++ b/Code/Editor/Platform/Mac/editor_mac.cmake @@ -13,3 +13,27 @@ set_target_properties(Editor PROPERTIES RESOURCE ${CMAKE_CURRENT_LIST_DIR}/Images.xcassets XCODE_ATTRIBUTE_ASSETCATALOG_COMPILER_APPICON_NAME EditorAppIcon ) + +# We cannot use ly_add_target here because we're already including this file from inside ly_add_target +# So we need to setup target, dependencies and install logic manually. +add_executable(EditorDummy Platform/Mac/main_dummy.cpp) +add_executable(AZ::EditorDummy ALIAS EditorDummy) + +ly_target_link_libraries(EditorDummy + PRIVATE + AZ::AzCore + AZ::AzFramework) + +ly_add_dependencies(Editor EditorDummy) + +# Store the aliased target into a DIRECTORY property +set_property(DIRECTORY APPEND PROPERTY LY_DIRECTORY_TARGETS AZ::EditorDummy) + +# Store the directory path in a GLOBAL property so that it can be accessed +# in the layout install logic. Skip if the directory has already been added +get_property(ly_all_target_directories GLOBAL PROPERTY LY_ALL_TARGET_DIRECTORIES) +if(NOT CMAKE_CURRENT_SOURCE_DIR IN_LIST ly_all_target_directories) + set_property(GLOBAL APPEND PROPERTY LY_ALL_TARGET_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}) +endif() + +ly_install_add_install_path_setreg(Editor) \ No newline at end of file diff --git a/Code/Editor/Platform/Mac/gui_info.plist b/Code/Editor/Platform/Mac/gui_info.plist index 5b5f94e977..cc87cbbb47 100644 --- a/Code/Editor/Platform/Mac/gui_info.plist +++ b/Code/Editor/Platform/Mac/gui_info.plist @@ -3,7 +3,7 @@ CFBundleExecutable - Editor + EditorDummy CFBundleIdentifier org.O3DE.Editor CFBundlePackageType diff --git a/Code/Editor/Platform/Mac/main_dummy.cpp b/Code/Editor/Platform/Mac/main_dummy.cpp new file mode 100644 index 0000000000..fb4a431295 --- /dev/null +++ b/Code/Editor/Platform/Mac/main_dummy.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include +#include +#include +#include + +#include + +int main(int argc, char* argv[]) +{ + // Create a ComponentApplication to initialize the AZ::SystemAllocator and initialize the SettingsRegistry + AZ::ComponentApplication::Descriptor desc; + AZ::ComponentApplication application; + application.Create(desc); + + AZStd::vector envVars; + + const char* homePath = std::getenv("HOME"); + envVars.push_back(AZStd::string::format("HOME=%s", homePath)); + + if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr) + { + const char* dyldLibPathOrig = std::getenv("DYLD_LIBRARY_PATH"); + AZStd::string dyldSearchPath = AZStd::string::format("DYLD_LIBRARY_PATH=%s", dyldLibPathOrig); + if (AZ::IO::FixedMaxPath projectModulePath; + settingsRegistry->Get(projectModulePath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_ProjectConfigurationBinPath)) + { + dyldSearchPath.append(":"); + dyldSearchPath.append(projectModulePath.c_str()); + } + + if (AZ::IO::FixedMaxPath installedBinariesFolder; + settingsRegistry->Get(installedBinariesFolder.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_InstalledBinaryFolder)) + { + if (AZ::IO::FixedMaxPath engineRootFolder; + settingsRegistry->Get(engineRootFolder.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_EngineRootFolder)) + { + installedBinariesFolder = engineRootFolder / installedBinariesFolder; + dyldSearchPath.append(":"); + dyldSearchPath.append(installedBinariesFolder.c_str()); + } + } + envVars.push_back(dyldSearchPath); + } + + AZStd::string commandArgs; + for (int i = 1; i < argc; i++) + { + commandArgs.append(argv[i]); + commandArgs.append(" "); + } + + AzFramework::ProcessLauncher::ProcessLaunchInfo processLaunchInfo; + AZ::IO::Path processPath{ AZ::IO::PathView(AZ::Utils::GetExecutableDirectory()) }; + processPath /= "Editor"; + processLaunchInfo.m_processExecutableString = AZStd::move(processPath.Native()); + processLaunchInfo.m_commandlineParameters = commandArgs; + processLaunchInfo.m_environmentVariables = &envVars; + processLaunchInfo.m_showWindow = true; + + AzFramework::ProcessWatcher* processWatcher = AzFramework::ProcessWatcher::LaunchProcess(processLaunchInfo, AzFramework::ProcessCommunicationType::COMMUNICATOR_TYPE_NONE); + + application.Destroy(); + + return 0; +} + diff --git a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.h b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.h index 2926a40252..02346c2ba1 100644 --- a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.h +++ b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.h @@ -28,6 +28,7 @@ namespace AZ::SettingsRegistryMergeUtils inline static constexpr char FilePathsRootKey[] = "/Amazon/AzCore/Runtime/FilePaths"; inline static constexpr char FilePathKey_BinaryFolder[] = "/Amazon/AzCore/Runtime/FilePaths/BinaryFolder"; inline static constexpr char FilePathKey_EngineRootFolder[] = "/Amazon/AzCore/Runtime/FilePaths/EngineRootFolder"; + inline static constexpr char FilePathKey_InstalledBinaryFolder[] = "/Amazon/AzCore/Runtime/FilePaths/InstalledBinariesFolder"; //! Stores the absolute path to root of a project's cache. No asset platform in this path, this is where the asset database file lives. //! i.e. /Cache diff --git a/Code/Framework/AzCore/Platform/Common/Apple/AzCore/std/time_Apple.cpp b/Code/Framework/AzCore/Platform/Common/Apple/AzCore/std/time_Apple.cpp index 4c67c5cfc5..a8a6ffea21 100644 --- a/Code/Framework/AzCore/Platform/Common/Apple/AzCore/std/time_Apple.cpp +++ b/Code/Framework/AzCore/Platform/Common/Apple/AzCore/std/time_Apple.cpp @@ -25,29 +25,7 @@ namespace AZStd AZStd::sys_time_t GetTimeNowTicks() { AZStd::sys_time_t timeNow; - struct timespec ts; - clock_serv_t cclock; - mach_timespec_t mts; - kern_return_t ret = host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock); - if (ret == KERN_SUCCESS) - { - ret = clock_get_time(cclock, &mts); - if (ret == KERN_SUCCESS) - { - ts.tv_sec = mts.tv_sec; - ts.tv_nsec = mts.tv_nsec; - } - else - { - AZ_Assert(false, "clock_get_time error: %d\n", ret); - } - mach_port_deallocate(mach_task_self(), cclock); - } - else - { - AZ_Assert(false, "clock_get_time error: %d\n", ret); - } - timeNow = ts.tv_sec * GetTimeTicksPerSecond() + ts.tv_nsec; + timeNow = clock_gettime_nsec_np(CLOCK_UPTIME_RAW); return timeNow; } @@ -62,29 +40,7 @@ namespace AZStd AZStd::sys_time_t GetTimeNowSecond() { AZStd::sys_time_t timeNowSecond; - struct timespec ts; - clock_serv_t cclock; - mach_timespec_t mts; - kern_return_t ret = host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock); - if (ret == KERN_SUCCESS) - { - ret = clock_get_time(cclock, &mts); - if (ret == KERN_SUCCESS) - { - ts.tv_sec = mts.tv_sec; - ts.tv_nsec = mts.tv_nsec; - } - else - { - AZ_Assert(false, "clock_get_time error: %d\n", ret); - } - mach_port_deallocate(mach_task_self(), cclock); - } - else - { - AZ_Assert(false, "clock_get_time error: %d\n", ret); - } - timeNowSecond = ts.tv_sec; + timeNowSecond = GetTimeNowTicks()/GetTimeTicksPerSecond(); return timeNowSecond; } diff --git a/Code/Framework/AzFramework/Platform/Mac/AzFramework/Process/ProcessWatcher_Mac.cpp b/Code/Framework/AzFramework/Platform/Mac/AzFramework/Process/ProcessWatcher_Mac.cpp index 68e7c4e483..148b1cbdfe 100644 --- a/Code/Framework/AzFramework/Platform/Mac/AzFramework/Process/ProcessWatcher_Mac.cpp +++ b/Code/Framework/AzFramework/Platform/Mac/AzFramework/Process/ProcessWatcher_Mac.cpp @@ -24,7 +24,9 @@ #include #include // for iopolicy #include +#include +extern char **environ; namespace AzFramework { @@ -45,7 +47,7 @@ namespace AzFramework // result == 0 means child PID is still running, nothing to check if (result == -1) { - AZ_TracePrintf("ProcessWatcher", "IsChildProcessDone could not determine child process status (waitpid errno %d). assuming process either failed to launch or terminated unexpectedly\n", errno); + AZ_TracePrintf("ProcessWatcher", "IsChildProcessDone could not determine child process status (waitpid errno %d(%s)). assuming process either failed to launch or terminated unexpectedly\n", errno, strerror(errno)); exitCode = 0; } else if (result == childProcessId) @@ -274,28 +276,27 @@ namespace AzFramework azstrcat(commandAndArgs[i], token.size(), token.c_str()); } commandAndArgs[commandTokens.size()] = nullptr; - - char** environmentVariables = nullptr; - int numEnvironmentVars = 0; + + constexpr int MaxEnvVariables = 128; + using EnvironmentVariableContainer = AZStd::fixed_vector; + EnvironmentVariableContainer environmentVariables; + for (char **env = ::environ; *env; env++) + { + environmentVariables.push_back(*env); + } if (processLaunchInfo.m_environmentVariables) { - const int numEnvironmentVars = processLaunchInfo.m_environmentVariables->size(); - // Adding one more as exec expects the array to have a nullptr as the last element - environmentVariables = new char*[numEnvironmentVars + 1]; - for (int i = 0; i < numEnvironmentVars; i++) + for (AZStd::string& processLaunchEnv : *processLaunchInfo.m_environmentVariables) { - const AZStd::string& envVarString = processLaunchInfo.m_environmentVariables->at(i); - environmentVariables[i] = new char[envVarString.size() + 1]; - environmentVariables[i][0] = '\0'; - azstrcat(environmentVariables[i], envVarString.size(), envVarString.c_str()); + environmentVariables.push_back(processLaunchEnv.data()); } - environmentVariables[numEnvironmentVars] = NULL; } + environmentVariables.push_back(nullptr); pid_t child_pid = fork(); if (IsIdChildProcess(child_pid)) { - ExecuteCommandAsChild(commandAndArgs, environmentVariables, processLaunchInfo, processData.m_startupInfo); + ExecuteCommandAsChild(commandAndArgs, environmentVariables.data(), processLaunchInfo, processData.m_startupInfo); } processData.m_childProcessId = child_pid; @@ -303,15 +304,6 @@ namespace AzFramework // Close these handles as they are only to be used by the child process processData.m_startupInfo.CloseAllHandles(); - if (processLaunchInfo.m_environmentVariables) - { - for (int i = 0; i < numEnvironmentVars; i++) - { - delete [] environmentVariables[i]; - } - delete [] environmentVariables; - } - for (int i = 0; i < commandTokens.size(); i++) { delete [] commandAndArgs[i]; diff --git a/Code/Tools/AssetProcessor/Platform/Mac/assetprocessor_mac.cmake b/Code/Tools/AssetProcessor/Platform/Mac/assetprocessor_mac.cmake index 54ed70c496..e34ce9d341 100644 --- a/Code/Tools/AssetProcessor/Platform/Mac/assetprocessor_mac.cmake +++ b/Code/Tools/AssetProcessor/Platform/Mac/assetprocessor_mac.cmake @@ -13,3 +13,27 @@ set_target_properties(AssetProcessor PROPERTIES RESOURCE ${CMAKE_CURRENT_SOURCE_DIR}/Platform/Mac/Images.xcassets XCODE_ATTRIBUTE_ASSETCATALOG_COMPILER_APPICON_NAME AssetProcessorAppIcon ) + +# We cannot use ly_add_target here because we're already including this file from inside ly_add_target +# So we need to setup target, dependencies and install logic manually. +add_executable(AssetProcessorDummy Platform/Mac/main_dummy.cpp) +add_executable(AZ::AssetProcessorDummy ALIAS AssetProcessorDummy) + +ly_target_link_libraries(AssetProcessorDummy + PRIVATE + AZ::AzCore + AZ::AzFramework) + +ly_add_dependencies(AssetProcessor AssetProcessorDummy) + +# Store the aliased target into a DIRECTORY property +set_property(DIRECTORY APPEND PROPERTY LY_DIRECTORY_TARGETS AZ::AssetProcessorDummy) + +# Store the directory path in a GLOBAL property so that it can be accessed +# in the layout install logic. Skip if the directory has already been added +get_property(ly_all_target_directories GLOBAL PROPERTY LY_ALL_TARGET_DIRECTORIES) +if(NOT CMAKE_CURRENT_SOURCE_DIR IN_LIST ly_all_target_directories) + set_property(GLOBAL APPEND PROPERTY LY_ALL_TARGET_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}) +endif() + +ly_install_add_install_path_setreg(AssetProcessor) \ No newline at end of file diff --git a/Code/Tools/AssetProcessor/Platform/Mac/gui_info.plist b/Code/Tools/AssetProcessor/Platform/Mac/gui_info.plist index 665abea1d3..301f0c5cee 100644 --- a/Code/Tools/AssetProcessor/Platform/Mac/gui_info.plist +++ b/Code/Tools/AssetProcessor/Platform/Mac/gui_info.plist @@ -11,7 +11,7 @@ CFBundleSignature ASPR CFBundleExecutable - AssetProcessor + AssetProcessorDummy CFBundleIdentifier com.Amazon.AssetProcessor diff --git a/Code/Tools/AssetProcessor/Platform/Mac/main_dummy.cpp b/Code/Tools/AssetProcessor/Platform/Mac/main_dummy.cpp new file mode 100644 index 0000000000..12832cc488 --- /dev/null +++ b/Code/Tools/AssetProcessor/Platform/Mac/main_dummy.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include +#include +#include +#include + +#include + +int main(int argc, char* argv[]) +{ + // Create a ComponentApplication to initialize the AZ::SystemAllocator and initialize the SettingsRegistry + AZ::ComponentApplication::Descriptor desc; + AZ::ComponentApplication application; + application.Create(desc); + + AZStd::vector envVars; + + const char* homePath = std::getenv("HOME"); + envVars.push_back(AZStd::string::format("HOME=%s", homePath)); + + if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr) + { + const char* dyldLibPathOrig = std::getenv("DYLD_LIBRARY_PATH"); + AZStd::string dyldSearchPath = AZStd::string::format("DYLD_LIBRARY_PATH=%s", dyldLibPathOrig); + if (AZ::IO::FixedMaxPath projectModulePath; + settingsRegistry->Get(projectModulePath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_ProjectConfigurationBinPath)) + { + dyldSearchPath.append(":"); + dyldSearchPath.append(projectModulePath.c_str()); + } + + if (AZ::IO::FixedMaxPath installedBinariesFolder; + settingsRegistry->Get(installedBinariesFolder.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_InstalledBinaryFolder)) + { + if (AZ::IO::FixedMaxPath engineRootFolder; + settingsRegistry->Get(engineRootFolder.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_EngineRootFolder)) + { + installedBinariesFolder = engineRootFolder / installedBinariesFolder; + dyldSearchPath.append(":"); + dyldSearchPath.append(installedBinariesFolder.c_str()); + } + } + envVars.push_back(dyldSearchPath); + } + + AZStd::string commandArgs; + for (int i = 1; i < argc; i++) + { + commandArgs.append(argv[i]); + commandArgs.append(" "); + } + + AzFramework::ProcessLauncher::ProcessLaunchInfo processLaunchInfo; + AZ::IO::Path processPath{ AZ::IO::PathView(AZ::Utils::GetExecutableDirectory()) }; + processPath /= "AssetProcessor"; + processLaunchInfo.m_processExecutableString = AZStd::move(processPath.Native()); + processLaunchInfo.m_commandlineParameters = commandArgs; + processLaunchInfo.m_environmentVariables = &envVars; + processLaunchInfo.m_showWindow = true; + + AzFramework::ProcessWatcher* processWatcher = AzFramework::ProcessWatcher::LaunchProcess(processLaunchInfo, AzFramework::ProcessCommunicationType::COMMUNICATOR_TYPE_NONE); + + application.Destroy(); + + return 0; +} + diff --git a/Code/Tools/AssetProcessor/native/utilities/BuilderManager.cpp b/Code/Tools/AssetProcessor/native/utilities/BuilderManager.cpp index 5ef2ebd2f4..751afc1a5d 100644 --- a/Code/Tools/AssetProcessor/native/utilities/BuilderManager.cpp +++ b/Code/Tools/AssetProcessor/native/utilities/BuilderManager.cpp @@ -28,7 +28,7 @@ namespace AssetProcessor //! Amount of time in seconds to wait for a builder to start up and connect // sometimes, builders take a long time to start because of things like virus scanners scanning each // builder DLL, so we give them a large margin. - static const int s_StartupConnectionWaitTimeS = 120; + static const int s_StartupConnectionWaitTimeS = 300; static const int s_MillisecondsInASecond = 1000; diff --git a/Gems/Atom/RHI/Code/Source/RHI.Edit/Utils.cpp b/Gems/Atom/RHI/Code/Source/RHI.Edit/Utils.cpp index 5cc69bc9a1..8c64f1611f 100644 --- a/Gems/Atom/RHI/Code/Source/RHI.Edit/Utils.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI.Edit/Utils.cpp @@ -304,7 +304,7 @@ namespace AZ uint32_t exitCode = 0; bool timedOut = false; - const AZStd::sys_time_t maxWaitTimeSeconds = 120; + const AZStd::sys_time_t maxWaitTimeSeconds = 300; const AZStd::sys_time_t startTimeSeconds = AZStd::GetTimeNowSecond(); const AZStd::sys_time_t startTime = AZStd::GetTimeNowTicks(); diff --git a/cmake/Platform/Common/Install_common.cmake b/cmake/Platform/Common/Install_common.cmake index 353c015fd3..2b56a1f0b4 100644 --- a/cmake/Platform/Common/Install_common.cmake +++ b/cmake/Platform/Common/Install_common.cmake @@ -448,11 +448,15 @@ endfunction() function(ly_setup_runtime_dependencies) # Common functions used by the bellow code - install(CODE + if(COMMAND ly_install_code_function_override) + ly_install_code_function_override() + else() + install(CODE "function(ly_copy source_file target_directory) file(COPY \"\${source_file}\" DESTINATION \"\${target_directory}\" FILE_PERMISSIONS ${LY_COPY_PERMISSIONS}) endfunction()" - ) + ) + endif() unset(runtime_commands) get_property(all_targets GLOBAL PROPERTY LY_ALL_TARGETS) diff --git a/cmake/Platform/Mac/Install_mac.cmake b/cmake/Platform/Mac/Install_mac.cmake index 808299e09d..c7f22e9149 100644 --- a/cmake/Platform/Mac/Install_mac.cmake +++ b/cmake/Platform/Mac/Install_mac.cmake @@ -6,6 +6,34 @@ # # +# This is used to generate a setreg file which will be placed inside the bundle +# for targets that request it(eg. AssetProcessor/Editor). This is the relative path +# to the bundle from the installed engine's root. This will be used to compute the +# absolute path to bundle which may contain dependent dylibs(eg. Gems) used by a project. +set(installed_binaries_path_template [[ +{ + "Amazon": { + "AzCore": { + "Runtime": { + "FilePaths": { + "InstalledBinariesFolder": "bin/Mac/$" + } + } + } + } +}]] +) + +unset(target_conf_dir) +foreach(conf IN LISTS CMAKE_CONFIGURATION_TYPES) + string(TOUPPER ${conf} UCONF) + string(APPEND target_conf_dir $<$:${CMAKE_RUNTIME_OUTPUT_DIRECTORY_${UCONF}}>) +endforeach() + +set(installed_binaries_setreg_path ${target_conf_dir}/Registry/installed_binaries_path.setreg) + +file(GENERATE OUTPUT ${installed_binaries_setreg_path} CONTENT ${installed_binaries_path_template}) + #! ly_install_target_override: Mac specific target installation function(ly_install_target_override) @@ -49,4 +77,26 @@ function(ly_install_target_override) endif() endfunction() +#! ly_install_add_install_path_setreg: Adds the install path setreg file as a dependency +function(ly_install_add_install_path_setreg NAME) + set_property(TARGET ${NAME} APPEND PROPERTY INTERFACE_LY_TARGET_FILES "${installed_binaries_setreg_path}\nRegistry") +endfunction() + +#! ly_install_code_function_override: Mac specific copy function to handle frameworks +function(ly_install_code_function_override) + + install(CODE +"function(ly_copy source_file target_directory) + if(\"\${source_file}\" MATCHES \"\\\\.[Ff]ramework[^\\\\.]\") + + # fixup origin to copy the whole Framework folder + string(REGEX REPLACE \"(.*\\\\.[Ff]ramework).*\" \"\\\\1\" source_file \"\${source_file}\") + get_filename_component(target_filename \"\${source_file}\" NAME) + + endif() + file(COPY \"\${source_file}\" DESTINATION \"\${target_directory}\" FILE_PERMISSIONS ${LY_COPY_PERMISSIONS}) +endfunction()") + +endfunction() + include(cmake/Platform/Common/Install_common.cmake) diff --git a/cmake/Platform/Mac/LYWrappers_mac.cmake b/cmake/Platform/Mac/LYWrappers_mac.cmake index 2254d422b0..578f6fe041 100644 --- a/cmake/Platform/Mac/LYWrappers_mac.cmake +++ b/cmake/Platform/Mac/LYWrappers_mac.cmake @@ -11,6 +11,7 @@ function(ly_apply_platform_properties target) set_target_properties(${target} PROPERTIES BUILD_RPATH "@executable_path/;@executable_path/../Frameworks" + INSTALL_RPATH "@executable_path/;@executable_path/../Frameworks" ) endfunction() From adaeb7c203b2287da0f6cc99ddd201c37b2e6374 Mon Sep 17 00:00:00 2001 From: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> Date: Tue, 10 Aug 2021 10:16:14 -0500 Subject: [PATCH 248/803] Converted the AZStd implementations of unintialized construct to use std (#2843) * Converted the AZStd implementations of unintialized construct to use std The uninitialized_default_construct and uninitialized_value_construct functions implementations have been removed and the Standard library implementations have been brought into the AZStd namespace scope Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Added a default construct to the UninitializedValueConstruct test case which value initializes the int member which uses zero initialization to initalize it to zero. Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> --- .../AzCore/AzCore/std/createdestroy.h | 112 ++---------------- .../AzCore/Tests/AZStd/CreateDestroy.cpp | 44 +++++++ 2 files changed, 55 insertions(+), 101 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/std/createdestroy.h b/Code/Framework/AzCore/AzCore/std/createdestroy.h index 3c60266562..94b86a58e4 100644 --- a/Code/Framework/AzCore/AzCore/std/createdestroy.h +++ b/Code/Framework/AzCore/AzCore/std/createdestroy.h @@ -21,7 +21,18 @@ namespace AZStd { // alias std::pointer_traits into the AZStd::namespace using std::pointer_traits; + + //! Bring the names of uninitialized_default_construct and + //! uninitialized_default_construct_n into the AZStd namespace + using std::uninitialized_default_construct; + using std::uninitialized_default_construct_n; + + //! uninitialized_value_construct and uninitialized_value_construct_n + //! are now brought into scope of the AZStd namespace + using std::uninitialized_value_construct; + using std::uninitialized_value_construct_n; } + namespace AZStd::Internal { template @@ -223,107 +234,6 @@ namespace AZStd } } -namespace AZStd -{ - //! C++20 implementation of uninitialized_default_construct - //! Initializes objects by default-initialization via placement new - //! Ex. `new(declval()) T` - Notice no parenthesis after T - //! This performs default initialization instead of value initialization - //! Default initialization performs the following actions - //! # If T is a class type it considers constructors which can be invoked - //! with an empty argument list. The selected constructor is invoked - //! to provide the initial value of the object - //! # If T is an array type, then default initialization is performed - //! on each array element - //! # Otherwise nothing is done and objects with automatic storage duration(i.e scope) - //! are initialized with indeterminate values - //! For example given the following struct - //! struct Foo - //! { - //! int mint; - //! double bubble; - //! }; - //! Invoking uninitialized_default_construct(FooPtr, FooPtr + 1) - //! Will default initialize the FooPtr object (Foo has an implicitly-defined default constructor) - //! The values of mint and bubble are indeterminate - template - constexpr auto uninitialized_default_construct(ForwardIt first, ForwardIt last) - -> enable_if_t, void> - { - for (; first != last; ++first) - { - return ::new (AZStd::addressof(*first)) typename AZStd::iterator_traits::value_type; - } - } - // C++20 implementation of uninitialized_default_construct_n - // Constructs "n" objects starting at first via default-initialization - template - constexpr auto uninitialized_default_construct_n(ForwardIt first, Size numElements) - -> enable_if_t, ForwardIt> - { - for (; numElements > 0; ++first, --numElements) - { - return ::new (AZStd::addressof(*first)) typename AZStd::iterator_traits::value_type; - } - - return first; - } -} - -namespace AZStd -{ - //! C++20 implementation of uninitialized_value_construct - //! Initializes objects by value-initialization via placement new - //! Ex. `new(declval()) T()` - Notice parenthesis are here after T - //! value-initialization of an object performs different rules depending - //! on the type of T - //! Value initialization performs the following actions - //! # If T is a class type with no default constructor or with a user-provided - //! constructor or a deleted default constructor, then default-initialization - //! is performed - //! # If T is a class type with a default constructor that is neither - //! user-provided nor deleted(i.e a class with an implicitly-defined or defaulted - //! default constructor), then the object is zero-initialized and then it is - //! default-initialized if it has a non-trivial default constructor - //! # If T is an array type, then value initialization is performed - //! on each array element - //! # Otherwise the object is zero-initialized - //! (i.e sets arithmetic and enum objects to 0, bool objects to false, pointers to nullptr) - //! For example given the following struct - //! struct Foo - //! { - //! int mint; - //! double bubble; - //! }; - //! Invoking uninitialized_default_construct(FooPtr, FooPtr + 1) - //! Will value-initialize the FooPtr object. - //! The Foo has an implicitly-defined default constructor. - //! For aggregates such as int and double this will perform zero-initialization - //! which will set their values to 0 - //! Therefore The values of mint will be 0 and and bubble 0.0 - template - constexpr auto uninitialized_value_construct(ForwardIt first, ForwardIt last) - -> enable_if_t, void> - { - for (; first != last; ++first) - { - return ::new (AZStd::addressof(*first)) typename AZStd::iterator_traits::value_type(); - } - } - // C++20 implementation of uninitialized_default_construct_n - // Constructs "n" objects starting at the first via by value-initialization - template - constexpr auto uninitialized_value_construct_n(ForwardIt first, Size numElements) - -> enable_if_t, ForwardIt> - { - for (; numElements > 0; ++first, --numElements) - { - return ::new (AZStd::addressof(*first)) typename AZStd::iterator_traits::value_type(); - } - - return first; - } -} namespace AZStd::Internal { diff --git a/Code/Framework/AzCore/Tests/AZStd/CreateDestroy.cpp b/Code/Framework/AzCore/Tests/AZStd/CreateDestroy.cpp index 9ccd1b0742..f9c72f6260 100644 --- a/Code/Framework/AzCore/Tests/AZStd/CreateDestroy.cpp +++ b/Code/Framework/AzCore/Tests/AZStd/CreateDestroy.cpp @@ -134,4 +134,48 @@ namespace UnitTest EXPECT_FLOAT_EQ(4.0f, resultAddress->m_floatValue); AZStd::destroy_at(resultAddress); } + + TEST(CreateDestroy, UninitializedDefaultConstruct_IsAbleToConstructMultipleElements_Succeeds) + { + struct RefWrapper + { + RefWrapper() + {} + int m_intValue{ 2 }; + }; + constexpr size_t ArraySize = 2; + AZStd::aligned_storage_for_t testArray[ArraySize]; + RefWrapper(&uninitializedAddress)[2] = reinterpret_cast(testArray); + AZStd::uninitialized_default_construct(AZStd::begin(uninitializedAddress), AZStd::end(uninitializedAddress)); + + + EXPECT_EQ(2, uninitializedAddress[0].m_intValue); + EXPECT_EQ(2, uninitializedAddress[1].m_intValue); + // Reset uninitializedAddress to Debug pattern + memset(uninitializedAddress, 0xCD, ArraySize * sizeof(RefWrapper)); + AZStd::uninitialized_default_construct_n(AZStd::data(uninitializedAddress), AZStd::size(uninitializedAddress)); + EXPECT_EQ(2, uninitializedAddress[0].m_intValue); + EXPECT_EQ(2, uninitializedAddress[1].m_intValue); + } + + TEST(CreateDestroy, UninitializedValueConstruct_IsAbleToConstructMultipleElements_Succeeds) + { + struct RefWrapper + { + int m_intValue; + }; + constexpr size_t ArraySize = 2; + AZStd::aligned_storage_for_t testArray[ArraySize]; + RefWrapper(&uninitializedAddress)[2] = reinterpret_cast(testArray); + AZStd::uninitialized_value_construct(AZStd::begin(uninitializedAddress), AZStd::end(uninitializedAddress)); + + + EXPECT_EQ(0, uninitializedAddress[0].m_intValue); + EXPECT_EQ(0, uninitializedAddress[1].m_intValue); + // Reset uninitializedAddress to Debug pattern + memset(uninitializedAddress, 0xCD, ArraySize * sizeof(RefWrapper)); + AZStd::uninitialized_value_construct_n(AZStd::data(uninitializedAddress), AZStd::size(uninitializedAddress)); + EXPECT_EQ(0, uninitializedAddress[0].m_intValue); + EXPECT_EQ(0, uninitializedAddress[1].m_intValue); + } } From 0953a75a94c59a7bce60cbbe5e2a48397475d35f Mon Sep 17 00:00:00 2001 From: Chris Burel Date: Mon, 9 Aug 2021 12:04:57 -0700 Subject: [PATCH 249/803] Replace MCore::SmallArray usage with AZStd::vector Signed-off-by: Chris Burel --- .../CommandSystem/Source/MetaData.cpp | 8 +- .../Source/NodeGroupCommands.cpp | 8 +- .../ExporterLib/Exporter/NodeExport.cpp | 6 +- .../EMotionFX/Code/EMotionFX/Source/Actor.cpp | 87 ++-- Gems/EMotionFX/Code/EMotionFX/Source/Actor.h | 13 +- .../Code/EMotionFX/Source/ActorInstance.cpp | 4 +- .../Code/EMotionFX/Source/NodeGroup.cpp | 37 +- .../Code/EMotionFX/Source/NodeGroup.h | 18 +- .../NodeGroups/NodeGroupManagementWidget.cpp | 16 +- .../Source/NodeGroups/NodeGroupWidget.cpp | 18 +- .../Source/NodeWindow/ActorInfo.cpp | 4 +- .../Source/NodeWindow/NodeGroupInfo.cpp | 4 +- Gems/EMotionFX/Code/MCore/Source/SmallArray.h | 414 ------------------ Gems/EMotionFX/Code/MCore/mcore_files.cmake | 1 - 14 files changed, 103 insertions(+), 535 deletions(-) delete mode 100644 Gems/EMotionFX/Code/MCore/Source/SmallArray.h diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MetaData.cpp b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MetaData.cpp index 9a0913a5db..f98e88a760 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MetaData.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MetaData.cpp @@ -41,15 +41,15 @@ namespace CommandSystem void MetaData::GenerateNodeGroupMetaData(EMotionFX::Actor* actor, AZStd::string& outMetaDataString) { AZStd::string nodeNameList; - const AZ::u32 numNodeGroups = actor->GetNumNodeGroups(); - for (uint32 i = 0; i < numNodeGroups; ++i) + const size_t numNodeGroups = actor->GetNumNodeGroups(); + for (size_t i = 0; i < numNodeGroups; ++i) { EMotionFX::NodeGroup* nodeGroup = actor->GetNodeGroup(i); outMetaDataString += AZStd::string::format("AddNodeGroup -actorID $(ACTORID) -name \"%s\"\n", nodeGroup->GetName()); nodeNameList.clear(); - const AZ::u16 numNodes = nodeGroup->GetNumNodes(); - for (AZ::u16 n = 0; n < numNodes; ++n) + const size_t numNodes = nodeGroup->GetNumNodes(); + for (size_t n = 0; n < numNodes; ++n) { const AZ::u16 nodeIndex = nodeGroup->GetNode(n); EMotionFX::Node* node = actor->GetSkeleton()->GetNode(nodeIndex); diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/NodeGroupCommands.cpp b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/NodeGroupCommands.cpp index c65429ab83..adaa9802d9 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/NodeGroupCommands.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/NodeGroupCommands.cpp @@ -80,7 +80,7 @@ namespace CommandSystem { if (*m_nodeAction == NodeAction::Replace) { - nodeGroup->GetNodeArray().Clear(); + nodeGroup->GetNodeArray().clear(); } for (const AZStd::string& nodeName : *m_nodeNames) { @@ -146,12 +146,12 @@ namespace CommandSystem if (m_nodeNames.has_value()) { // clear previous nodes - nodeGroup->GetNodeArray().Clear(); - const uint16 numNodes = m_oldNodeGroup->GetNumNodes(); + nodeGroup->GetNodeArray().clear(); + const size_t numNodes = m_oldNodeGroup->GetNumNodes(); nodeGroup->SetNumNodes(numNodes); // add all nodes to the group - for (uint16 i = 0; i < numNodes; ++i) + for (size_t i = 0; i < numNodes; ++i) { nodeGroup->SetNode(i, m_oldNodeGroup->GetNode(i)); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/NodeExport.cpp b/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/NodeExport.cpp index 91727b2113..d8404cc991 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/NodeExport.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/NodeExport.cpp @@ -249,7 +249,7 @@ namespace ExporterLib { chunkHeader.m_sizeInBytes += sizeof(EMotionFX::FileFormat::Actor_NodeGroup); chunkHeader.m_sizeInBytes += GetStringChunkSize(nodeGroup->GetNameString()); - chunkHeader.m_sizeInBytes += sizeof(uint16) * nodeGroup->GetNumNodes(); + chunkHeader.m_sizeInBytes += sizeof(uint16) * aznumeric_cast(nodeGroup->GetNumNodes()); } // endian conversion @@ -277,14 +277,14 @@ namespace ExporterLib MCORE_ASSERT(actor); // get the number of node groups - const uint32 numGroups = actor->GetNumNodeGroups(); + const size_t numGroups = actor->GetNumNodeGroups(); // create the node group array and reserve some elements AZStd::vector nodeGroups; nodeGroups.reserve(numGroups); // iterate through the node groups and add them to the array - for (uint32 i = 0; i < numGroups; ++i) + for (size_t i = 0; i < numGroups; ++i) { nodeGroups.emplace_back(actor->GetNodeGroup(i)); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp index df039b7186..94a56cc0d5 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp @@ -142,9 +142,9 @@ namespace EMotionFX result->RecursiveAddDependencies(this); // clone all nodes groups - for (uint32 i = 0; i < m_nodeGroups.GetLength(); ++i) + for (const NodeGroup* nodeGroup : m_nodeGroups) { - result->AddNodeGroup(aznew NodeGroup(*m_nodeGroups[i])); + result->AddNodeGroup(aznew NodeGroup(*nodeGroup)); } // clone the materials @@ -948,12 +948,11 @@ namespace EMotionFX // remove all node groups void Actor::RemoveAllNodeGroups() { - const uint32 numGroups = m_nodeGroups.GetLength(); - for (uint32 i = 0; i < numGroups; ++i) + for (NodeGroup*& nodeGroup : m_nodeGroups) { - delete m_nodeGroups[i]; + delete nodeGroup; } - m_nodeGroups.Clear(); + m_nodeGroups.clear(); } @@ -1965,13 +1964,13 @@ namespace EMotionFX } - uint32 Actor::GetNumNodeGroups() const + size_t Actor::GetNumNodeGroups() const { - return m_nodeGroups.GetLength(); + return m_nodeGroups.size(); } - NodeGroup* Actor::GetNodeGroup(uint32 index) const + NodeGroup* Actor::GetNodeGroup(size_t index) const { return m_nodeGroups[index]; } @@ -1979,90 +1978,76 @@ namespace EMotionFX void Actor::AddNodeGroup(NodeGroup* newGroup) { - m_nodeGroups.Add(newGroup); + m_nodeGroups.emplace_back(newGroup); } - void Actor::RemoveNodeGroup(uint32 index, bool delFromMem) + void Actor::RemoveNodeGroup(size_t index, bool delFromMem) { if (delFromMem) { delete m_nodeGroups[index]; } - m_nodeGroups.Remove(index); + m_nodeGroups.erase(AZStd::next(begin(m_nodeGroups), index)); } void Actor::RemoveNodeGroup(NodeGroup* group, bool delFromMem) { - m_nodeGroups.RemoveByValue(group); - if (delFromMem) + const auto found = AZStd::find(begin(m_nodeGroups), end(m_nodeGroups), group); + if (found != end(m_nodeGroups)) { - delete group; + m_nodeGroups.erase(found); + if (delFromMem) + { + delete group; + } } } // find a group index by its name - uint32 Actor::FindNodeGroupIndexByName(const char* groupName) const + size_t Actor::FindNodeGroupIndexByName(const char* groupName) const { - const uint32 numGroups = m_nodeGroups.GetLength(); - for (uint32 i = 0; i < numGroups; ++i) + const auto found = AZStd::find_if(begin(m_nodeGroups), end(m_nodeGroups), [groupName](const NodeGroup* nodeGroup) { - if (m_nodeGroups[i]->GetNameString() == groupName) - { - return i; - } - } - - return MCORE_INVALIDINDEX32; + return nodeGroup->GetNameString() == groupName; + }); + return found != end(m_nodeGroups) ? AZStd::distance(begin(m_nodeGroups), found) : InvalidIndex; } // find a group index by its name, but not case sensitive - uint32 Actor::FindNodeGroupIndexByNameNoCase(const char* groupName) const + size_t Actor::FindNodeGroupIndexByNameNoCase(const char* groupName) const { - const uint32 numGroups = m_nodeGroups.GetLength(); - for (uint32 i = 0; i < numGroups; ++i) + const auto found = AZStd::find_if(begin(m_nodeGroups), end(m_nodeGroups), [groupName](const NodeGroup* nodeGroup) { - if (AzFramework::StringFunc::Equal(m_nodeGroups[i]->GetNameString().c_str(), groupName, false /* no case */)) - { - return i; - } - } - - return MCORE_INVALIDINDEX32; + return AzFramework::StringFunc::Equal(nodeGroup->GetNameString(), groupName, false /* no case */); + }); + return found != end(m_nodeGroups) ? AZStd::distance(begin(m_nodeGroups), found) : InvalidIndex; } // find a group by its name NodeGroup* Actor::FindNodeGroupByName(const char* groupName) const { - const uint32 numGroups = m_nodeGroups.GetLength(); - for (uint32 i = 0; i < numGroups; ++i) + const auto found = AZStd::find_if(begin(m_nodeGroups), end(m_nodeGroups), [groupName](const NodeGroup* nodeGroup) { - if (m_nodeGroups[i]->GetNameString() == groupName) - { - return m_nodeGroups[i]; - } - } - return nullptr; + return nodeGroup->GetNameString() == groupName; + }); + return found != end(m_nodeGroups) ? *found : nullptr; } // find a group by its name, but without case sensitivity NodeGroup* Actor::FindNodeGroupByNameNoCase(const char* groupName) const { - const uint32 numGroups = m_nodeGroups.GetLength(); - for (uint32 i = 0; i < numGroups; ++i) + const auto found = AZStd::find_if(begin(m_nodeGroups), end(m_nodeGroups), [groupName](const NodeGroup* nodeGroup) { - if (AzFramework::StringFunc::Equal(m_nodeGroups[i]->GetNameString().c_str(), groupName, false /* no case */)) - { - return m_nodeGroups[i]; - } - } - return nullptr; + return AzFramework::StringFunc::Equal(nodeGroup->GetNameString(), groupName, false /* no case */); + }); + return found != end(m_nodeGroups) ? *found : nullptr; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Actor.h b/Gems/EMotionFX/Code/EMotionFX/Source/Actor.h index 5c4a15e2d8..aa5c5df45c 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Actor.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Actor.h @@ -23,7 +23,6 @@ // include MCore related files #include #include -#include #include // include required headers @@ -567,13 +566,13 @@ namespace EMotionFX * Get the number of node groups inside this actor object. * @result The number of node groups. */ - uint32 GetNumNodeGroups() const; + size_t GetNumNodeGroups() const; /** * Get a pointer to a given node group. * @param index The node group index, which must be in range of [0..GetNumNodeGroups()-1]. */ - NodeGroup* GetNodeGroup(uint32 index) const; + NodeGroup* GetNodeGroup(size_t index) const; /** * Add a node group. @@ -586,7 +585,7 @@ namespace EMotionFX * @param index The node group number to remove. This value must be in range of [0..GetNumNodeGroups()-1]. * @param delFromMem Set to true (default) when you wish to also delete the specified group from memory. */ - void RemoveNodeGroup(uint32 index, bool delFromMem = true); + void RemoveNodeGroup(size_t index, bool delFromMem = true); /** * Remove a given node group by its pointer. @@ -601,14 +600,14 @@ namespace EMotionFX * @param groupName The name of the group to search for. This is case sensitive. * @result The group number, or MCORE_INVALIDINDEX32 when it cannot be found. */ - uint32 FindNodeGroupIndexByName(const char* groupName) const; + size_t FindNodeGroupIndexByName(const char* groupName) const; /** * Find a group index by its name, on a non-case sensitive way. * @param groupName The name of the group to search for. This is NOT case sensitive. * @result The group number, or MCORE_INVALIDINDEX32 when it cannot be found. */ - uint32 FindNodeGroupIndexByNameNoCase(const char* groupName) const; + size_t FindNodeGroupIndexByNameNoCase(const char* groupName) const; /** * Find a node group by its name. @@ -925,7 +924,7 @@ namespace EMotionFX AZStd::vector m_nodeMirrorInfos; /**< The array of node mirror info. */ AZStd::vector< AZStd::vector< Material* > > m_materials; /**< A collection of materials (for each lod). */ AZStd::vector< MorphSetup* > m_morphSetups; /**< A morph setup for each geometry LOD. */ - MCore::SmallArray m_nodeGroups; /**< The set of node groups. */ + AZStd::vector m_nodeGroups; /**< The set of node groups. */ AZStd::shared_ptr m_physicsSetup; /**< Hit detection, ragdoll and cloth colliders, joint limits and rigid bodies. */ AZStd::shared_ptr m_simulatedObjectSetup; /**< Setup for simulated objects */ MCore::Distance::EUnitType m_unitType; /**< The unit type used on export. */ diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.cpp index 6097784e2f..13927f3fd3 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.cpp @@ -84,8 +84,8 @@ namespace EMotionFX EnableAllNodes(); // apply actor node group default states (disable groups of nodes that are disabled on default) - const uint32 numGroups = m_actor->GetNumNodeGroups(); - for (uint32 i = 0; i < numGroups; ++i) + const size_t numGroups = m_actor->GetNumNodeGroups(); + for (size_t i = 0; i < numGroups; ++i) { if (m_actor->GetNodeGroup(i)->GetIsEnabledOnDefault() == false) // if this group is disabled on default { diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/NodeGroup.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/NodeGroup.cpp index 293d64775d..74e59150e0 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/NodeGroup.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/NodeGroup.cpp @@ -17,7 +17,7 @@ namespace EMotionFX AZ_CLASS_ALLOCATOR_IMPL(NodeGroup, NodeAllocator, 0) - NodeGroup::NodeGroup(const AZStd::string& groupName, uint16 numNodes, bool enabledOnDefault) + NodeGroup::NodeGroup(const AZStd::string& groupName, size_t numNodes, bool enabledOnDefault) : m_name(groupName) , m_nodes(numNodes) , m_enabledOnDefault(enabledOnDefault) @@ -47,28 +47,28 @@ namespace EMotionFX // set the number of nodes - void NodeGroup::SetNumNodes(const uint16 numNodes) + void NodeGroup::SetNumNodes(const size_t numNodes) { - m_nodes.Resize(numNodes); + m_nodes.resize(numNodes); } // get the number of nodes - uint16 NodeGroup::GetNumNodes() const + size_t NodeGroup::GetNumNodes() const { - return static_cast(m_nodes.GetLength()); + return m_nodes.size(); } // set a given node to a given node number - void NodeGroup::SetNode(uint16 index, uint16 nodeIndex) + void NodeGroup::SetNode(size_t index, uint16 nodeIndex) { m_nodes[index] = nodeIndex; } // get the node number of a given index - uint16 NodeGroup::GetNode(uint16 index) const + uint16 NodeGroup::GetNode(size_t index) const { return m_nodes[index]; } @@ -77,10 +77,9 @@ namespace EMotionFX // enable all nodes in the group inside a given actor instance void NodeGroup::EnableNodes(ActorInstance* targetActorInstance) { - const uint16 numNodes = static_cast(m_nodes.GetLength()); - for (uint16 i = 0; i < numNodes; ++i) + for (uint16 node : m_nodes) { - targetActorInstance->EnableNode(m_nodes[i]); + targetActorInstance->EnableNode(node); } } @@ -88,10 +87,9 @@ namespace EMotionFX // disable all nodes in the group inside a given actor instance void NodeGroup::DisableNodes(ActorInstance* targetActorInstance) { - const uint16 numNodes = static_cast(m_nodes.GetLength()); - for (uint16 i = 0; i < numNodes; ++i) + for (uint16 node : m_nodes) { - targetActorInstance->DisableNode(m_nodes[i]); + targetActorInstance->DisableNode(node); } } @@ -99,26 +97,29 @@ namespace EMotionFX // add a given node to the group (performs a realloc internally) void NodeGroup::AddNode(uint16 nodeIndex) { - m_nodes.Add(nodeIndex); + m_nodes.emplace_back(nodeIndex); } // remove a given node by its node number void NodeGroup::RemoveNodeByNodeIndex(uint16 nodeIndex) { - m_nodes.RemoveByValue(nodeIndex); + if (const auto found = AZStd::find(begin(m_nodes), end(m_nodes), nodeIndex); found) + { + m_nodes.erase(found); + } } // remove a given array element from the list of nodes - void NodeGroup::RemoveNodeByGroupIndex(uint16 index) + void NodeGroup::RemoveNodeByGroupIndex(size_t index) { - m_nodes.Remove(index); + m_nodes.erase(AZStd::next(begin(m_nodes), index)); } // get the node array directly - MCore::SmallArray& NodeGroup::GetNodeArray() + AZStd::vector& NodeGroup::GetNodeArray() { return m_nodes; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/NodeGroup.h b/Gems/EMotionFX/Code/EMotionFX/Source/NodeGroup.h index 7ee74415c0..02dc7d70a9 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/NodeGroup.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/NodeGroup.h @@ -11,8 +11,8 @@ // include required files #include "EMotionFXConfig.h" #include "BaseObject.h" -#include #include +#include namespace EMotionFX @@ -34,7 +34,7 @@ namespace EMotionFX public: AZ_CLASS_ALLOCATOR_DECL - NodeGroup(const AZStd::string& groupName = {}, uint16 numNodes = 0, bool enabledOnDefault = true); + NodeGroup(const AZStd::string& groupName = {}, size_t numNodes = 0, bool enabledOnDefault = true); NodeGroup(const NodeGroup& aOther); NodeGroup& operator=(const NodeGroup& aOther); @@ -61,13 +61,13 @@ namespace EMotionFX * This will resize the array of node indices. Don't forget to initialize the node values after increasing the number of nodes though. * @param numNodes The number of nodes that are inside this group. */ - void SetNumNodes(const uint16 numNodes); + void SetNumNodes(size_t numNodes); /** * Get the number of nodes that remain inside this group. * @result The number of nodes inside this group. */ - uint16 GetNumNodes() const; + size_t GetNumNodes() const; /** * Set the value of a given node. @@ -75,14 +75,14 @@ namespace EMotionFX * @param nodeIndex The value for the given node. This is the node index which points inside the Actor object where this group will belong to. * To get access to the actual node object use Actor::GetNode( nodeIndex ). */ - void SetNode(uint16 index, uint16 nodeIndex); + void SetNode(size_t index, uint16 nodeIndex); /** * Get the node index for a given node inside the group. * @param index The node number inside this group, which must be in range of [0..GetNumNodes()-1]. * @result The node number, which points inside the Actor object. Use Actor::GetNode( returnValue ) to get access to the node information. */ - uint16 GetNode(uint16 index) const; + uint16 GetNode(size_t index) const; /** * Enable all nodes that remain inside this group, for a given actor instance. @@ -127,13 +127,13 @@ namespace EMotionFX * @param index The node index in the group. So for example an index value of 5 will remove the sixth node from the group. * The index value must be in range of [0..GetNumNodes() - 1]. */ - void RemoveNodeByGroupIndex(uint16 index); + void RemoveNodeByGroupIndex(size_t index); /** * Get direct access to the array of node indices that are part of this group. * @result A reference to the array of nodes inside this group. Please use this with care. */ - MCore::SmallArray& GetNodeArray(); + AZStd::vector& GetNodeArray(); /** * Check whether this group is enabled after actor instance creation time. @@ -155,7 +155,7 @@ namespace EMotionFX private: AZStd::string m_name; /**< The name of the group. */ - MCore::SmallArray m_nodes; /**< The node index numbers that are inside this group. */ + AZStd::vector m_nodes; /**< The node index numbers that are inside this group. */ bool m_enabledOnDefault; /**< Specifies whether this group is enabled on default (true) or disabled (false). With on default we mean after directly after the actor instance using this group has been created. */ }; } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeGroups/NodeGroupManagementWidget.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeGroups/NodeGroupManagementWidget.cpp index 67aee6a5af..bd5a93a0ae 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeGroups/NodeGroupManagementWidget.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeGroups/NodeGroupManagementWidget.cpp @@ -262,11 +262,11 @@ namespace EMStudio m_clearButton->setDisabled(disableButtons); // set the row count - m_nodeGroupsTable->setRowCount(m_actor->GetNumNodeGroups()); + m_nodeGroupsTable->setRowCount(aznumeric_caster(m_actor->GetNumNodeGroups())); // fill the table with the existing node groups - const uint32 numNodeGroups = m_actor->GetNumNodeGroups(); - for (uint32 i = 0; i < numNodeGroups; ++i) + const size_t numNodeGroups = m_actor->GetNumNodeGroups(); + for (size_t i = 0; i < numNodeGroups; ++i) { // get the nodegroup EMotionFX::NodeGroup* nodeGroup = m_actor->GetNodeGroup(i); @@ -287,16 +287,16 @@ namespace EMStudio // create table items QTableWidgetItem* tableItemGroupName = new QTableWidgetItem(nodeGroup->GetName()); - AZStd::string numGroupString = AZStd::string::format("%i", nodeGroup->GetNumNodes()); + AZStd::string numGroupString = AZStd::string::format("%zu", nodeGroup->GetNumNodes()); QTableWidgetItem* tableItemNumNodes = new QTableWidgetItem(numGroupString.c_str()); // add items to the table - m_nodeGroupsTable->setCellWidget(i, 0, checkbox); - m_nodeGroupsTable->setItem(i, 1, tableItemGroupName); - m_nodeGroupsTable->setItem(i, 2, tableItemNumNodes); + m_nodeGroupsTable->setCellWidget(aznumeric_caster(i), 0, checkbox); + m_nodeGroupsTable->setItem(aznumeric_caster(i), 1, tableItemGroupName); + m_nodeGroupsTable->setItem(aznumeric_caster(i), 2, tableItemNumNodes); // set the row height - m_nodeGroupsTable->setRowHeight(i, 21); + m_nodeGroupsTable->setRowHeight(aznumeric_caster(i), 21); } // set the old selected row if any one diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeGroups/NodeGroupWidget.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeGroups/NodeGroupWidget.cpp index 7ce09a55d7..8a20070505 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeGroups/NodeGroupWidget.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeGroups/NodeGroupWidget.cpp @@ -150,17 +150,17 @@ namespace EMStudio m_removeNodesButton->setEnabled((m_nodeTable->rowCount() != 0) && (m_nodeTable->selectedItems().size() != 0)); // clear the table widget - m_nodeTable->setRowCount(m_nodeGroup->GetNumNodes()); + m_nodeTable->setRowCount(aznumeric_caster(m_nodeGroup->GetNumNodes())); // set header items for the table - AZStd::string headerText = AZStd::string::format("%s Nodes (%i / %zu)", ((m_nodeGroup->GetIsEnabledOnDefault()) ? "Enabled" : "Disabled"), m_nodeGroup->GetNumNodes(), m_actor->GetNumNodes()); + AZStd::string headerText = AZStd::string::format("%s Nodes (%zu / %zu)", ((m_nodeGroup->GetIsEnabledOnDefault()) ? "Enabled" : "Disabled"), m_nodeGroup->GetNumNodes(), m_actor->GetNumNodes()); QTableWidgetItem* nameHeaderItem = new QTableWidgetItem(headerText.c_str()); nameHeaderItem->setTextAlignment(Qt::AlignVCenter | Qt::AlignCenter); m_nodeTable->setHorizontalHeaderItem(0, nameHeaderItem); // fill the table with content - const uint16 numNodes = m_nodeGroup->GetNumNodes(); - for (uint16 i = 0; i < numNodes; ++i) + const size_t numNodes = m_nodeGroup->GetNumNodes(); + for (size_t i = 0; i < numNodes; ++i) { // get the nodegroup EMotionFX::Node* node = m_actor->GetSkeleton()->GetNode(m_nodeGroup->GetNode(i)); @@ -173,10 +173,10 @@ namespace EMStudio // create table items QTableWidgetItem* tableItemNodeName = new QTableWidgetItem(node->GetName()); - m_nodeTable->setItem(i, 0, tableItemNodeName); + m_nodeTable->setItem(aznumeric_caster(i), 0, tableItemNodeName); // set the row height - m_nodeTable->setRowHeight(i, 21); + m_nodeTable->setRowHeight(aznumeric_caster(i), 21); } // resize to contents and adjust header @@ -257,11 +257,9 @@ namespace EMStudio m_nodeSelectionList.Clear(); if (senderWidget == m_selectNodesButton) { - MCore::SmallArray& nodes = m_nodeGroup->GetNodeArray(); - const uint16 numNodes = nodes.GetLength(); - for (uint16 i = 0; i < numNodes; ++i) + for (const uint16 i : m_nodeGroup->GetNodeArray()) { - EMotionFX::Node* node = m_actor->GetSkeleton()->GetNode(nodes[i]); + EMotionFX::Node* node = m_actor->GetSkeleton()->GetNode(i); m_nodeSelectionList.AddNode(node); } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/ActorInfo.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/ActorInfo.cpp index 6bd00a2b94..9936410231 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/ActorInfo.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/ActorInfo.cpp @@ -32,9 +32,9 @@ namespace EMStudio m_nodeCount = actor->GetNumNodes(); // node groups - const uint32 numNodeGroups = actor->GetNumNodeGroups(); + const size_t numNodeGroups = actor->GetNumNodeGroups(); m_nodeGroups.reserve(numNodeGroups); - for (uint32 i = 0; i < numNodeGroups; ++i) + for (size_t i = 0; i < numNodeGroups; ++i) { m_nodeGroups.emplace_back(actor, actor->GetNodeGroup(i)); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/NodeGroupInfo.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/NodeGroupInfo.cpp index 07a31f4402..f25158ae0d 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/NodeGroupInfo.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/NodeGroupInfo.cpp @@ -23,8 +23,8 @@ namespace EMStudio m_name = nodeGroup->GetNameString(); // iterate over the nodes inside the node group - const uint32 numGroupNodes = nodeGroup->GetNumNodes(); - for (uint32 j = 0; j < numGroupNodes; ++j) + const size_t numGroupNodes = nodeGroup->GetNumNodes(); + for (size_t j = 0; j < numGroupNodes; ++j) { const uint16 nodeIndex = nodeGroup->GetNode(j); const EMotionFX::Node* node = actor->GetSkeleton()->GetNode(nodeIndex); diff --git a/Gems/EMotionFX/Code/MCore/Source/SmallArray.h b/Gems/EMotionFX/Code/MCore/Source/SmallArray.h deleted file mode 100644 index ab94cabbfe..0000000000 --- a/Gems/EMotionFX/Code/MCore/Source/SmallArray.h +++ /dev/null @@ -1,414 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -#pragma once - -#include "StandardHeaders.h" -#include "MCoreSystem.h" -#include "Algorithms.h" -#include "MemoryManager.h" - - -namespace MCore -{ - -/** - * Dynamic array template with a maximum of 65536 items. - * It also doesn't store a memory category and maximum number of elements like the MCore::Array template. - */ -template -class SmallArray -{ - public: - /** - * The memory block ID, used inside the memory manager. - * This will make all arrays remain in the same memory blocks, which is more efficient in a lot of cases. - * However, array data can still remain in other blocks. - */ - enum { MEMORYBLOCK_ID = 2 }; - - /** - * Default constructor. - * Initializes the array so it's empty and has no memory allocated. - */ - MCORE_INLINE SmallArray() : m_data(nullptr), m_length(0) {} - - /** - * Constructor which creates a given number of elements. - * @param elems The element data. - * @param num The number of elements in 'elems'. - */ - MCORE_INLINE explicit SmallArray(T* elems, uint32 num) : m_length(num) { m_data = (T*)MCore::Allocate(m_length * sizeof(T), MCORE_MEMCATEGORY_SMALLARRAY, MEMORYBLOCK_ID, MCORE_FILE, MCORE_LINE); for (uint32 i=0; i 0) { m_data = (T*)MCore::Allocate(m_length * sizeof(T), MCORE_MEMCATEGORY_SMALLARRAY, MEMORYBLOCK_ID, MCORE_FILE, MCORE_LINE); for (uint32 i=0; i& other) : m_data(nullptr), m_length(0) { *this = other; } - - /** - * Move constructor. - * @param other The array to move the data from. - */ - SmallArray(SmallArray&& other) { m_data=other.m_data; m_length=other.m_length; other.m_data=nullptr; other.m_length=0; } - - /** - * Destructor. Deletes all entry data. - * However, if you store pointers to objects, these objects won't be deleted.
- * Example:
- *
-         * SmallArray< Object* > data;
-         * for (uint32 i=0; i<10; i++)
-         *    data.Add( new Object() );
-         * 
- * Now when the array 'data' will be destructed, it will NOT free up the memory of the integers which you allocated by hand, using new. - * In order to free up this memory, you can do this: - *
-         * for (uint32 i=0; i
-         */
-        ~SmallArray()                                                            { for (uint32 i=0; i); return result; }
-
-        /**
-         * Set a given element to a given value.
-         * @param pos The element number.
-         * @param value The value to store at that element number.
-         */
-        MCORE_INLINE void SetElem(uint32 pos, const T& value)                    { m_data[pos] = value; }
-
-        /**
-         * Add a given element to the back of the array.
-         * @param x The element to add.
-         */
-        MCORE_INLINE void Add(const T& x)                                        { Grow(++m_length); Construct(m_length-1, x); }
-
-        /**
-         * Add a given array to the back of this array.
-         * @param a The array to add.
-         */
-        MCORE_INLINE void Add(const SmallArray& a)                            { uint32 l=m_length; Grow(m_length+a.m_length); for (uint32 i=0; i 0) Remove((uint32)0); }
-
-        /**
-         * Remove the last array element.
-         */
-        MCORE_INLINE void RemoveLast()                                            { if (m_length > 0) Destruct(--m_length); }
-
-        /**
-         * Insert an empty element (default constructed) at a given position in the array.
-         * @param pos The position to create the empty element.
-         */
-        MCORE_INLINE void Insert(uint32 pos)                                    { Grow(m_length+1); MoveElements(pos+1, pos, m_length-pos-1); Construct(pos); }
-
-        /**
-         * Insert a given element at a given position in the array.
-         * @param pos The position to insert the empty element.
-         * @param x The element to store at this position.
-         */
-        MCORE_INLINE void Insert(uint32 pos, const T& x)                        { Grow(m_length+1); MoveElements(pos+1, pos, m_length-pos-1); Construct(pos, x); }
-
-        /**
-         * Remove an element at a given position.
-         * @param pos The element number to remove.
-         */
-        MCORE_INLINE void Remove(uint32 pos)                                    { Destruct(pos); MoveElements(pos, pos+1, m_length-pos-1); m_length--; }
-
-        /**
-         * Remove a given number of elements starting at a given position in the array.
-         * @param pos The start element, so to start removing from.
-         * @param num The number of elements to remove from this position.
-         */
-        MCORE_INLINE void Remove(uint32 pos, uint32 num)                        { for (uint32 i=pos; i
-         * And we perform a SwapRemove(2), we will remove element C and place the last element (G) at the empty created position where C was located.
-         * So we will get this:
- * AB.DEFG [where . is empty, after we did the SwapRemove(2)]
- * ABGDEF [this is the result. G has been moved to the empty position]. - */ - MCORE_INLINE void SwapRemove(uint32 pos) { Destruct(pos); if (pos != m_length-1) { Construct(pos, m_data[m_length-1]); Destruct(m_length-1); } m_length--; } // remove element at and place the last element of the array in that position - - /** - * Swap two elements. - * @param pos1 The first element number. - * @param pos2 The second element number. - */ - MCORE_INLINE void Swap(uint32 pos1, uint32 pos2) { if (pos1 != pos2) MCore::Swap(GetItem(pos1), GetItem(pos2)); } - - /** - * Clear the array contents. So GetLength() will return 0 after performing this method. - * @param clearMem If set to true (default) the allocated memory will also be released. If set to false, GetMaxLength() will still return the number of elements - * which the array contained before calling the Clear() method. - */ - MCORE_INLINE void Clear(bool clearMem=true) { for (uint32 i=0; i= newLength) return; uint32 oldLen=m_length; Grow(newLength); for (uint32 i=oldLen; i operators). - * The method will sort all elements between the given 'first' and 'last' element (first and last are also included in the sort). - * @param first The first element to start sorting. - * @param last The last element to sort (when set to MCORE_INVALIDINDEX32, GetLength()-1 will be used). - * @param cmp The compare function. - */ - MCORE_INLINE void Sort(uint32 first=0, uint32 last=MCORE_INVALIDINDEX32, CmpFunc cmp=StdCmp) { if (last==MCORE_INVALIDINDEX32) last=m_length-1; InnerSort(first, last, cmp); } - - /** - * Performs a sort on a given part of the array. - * @param first The first element to start the sorting at. - * @param last The last element to end the sorting. - * @param cmp The compare function. - */ - MCORE_INLINE void InnerSort(int32 first, int32 last, CmpFunc cmp) { if (first >= last) return; int32 split=Partition(first, last, cmp); InnerSort(first, split-1, cmp); InnerSort(split+1, last, cmp); } - - /** - * Resize the array to a given size. - * This does not mean an actual realloc will be made. This will only happen when the new length is bigger than the maxLength of the array. - * @param newLength The new length the array should be. - * @result returns false if the allocation/reallocation of the array failed - */ - bool Resize(uint32 newLength) - { - // check for growing or shrinking array - if (newLength > m_length) - { - // growing array, construct empty elements at end of array - uint32 oldLen = m_length; - GrowExact(newLength); - if (m_data == nullptr) - { - return false; - } - for (uint32 i=oldLen; i 0) - MCore::MemMove(m_data+destIndex, m_data+sourceIndex, numElements * sizeof(T)); - } - - // operators - bool operator==(const SmallArray& other) const { if (m_length != other.m_length) return false; for (uint32 i=0; i& operator= (const SmallArray& other) { if (&other != this) { Clear(); Grow(other.m_length); for (uint32 i=0; i& operator= (SmallArray&& other) { MCORE_ASSERT(&other != this); if (m_data!=nullptr) MCore::Free(m_data); m_data=other.m_data; m_length=other.m_length; other.m_data=nullptr; other.m_length=0; return *this; } - SmallArray& operator+=(const T& other) { Add(other); return *this; } - SmallArray& operator+=(const SmallArray& other) { Add(other); return *this; } - MCORE_INLINE T& operator[](const uint32 index) { MCORE_ASSERT(indexFree(); return; } - if (m_data) - m_data = (T*)MCore::Realloc(m_data, newSize * sizeof(T), MCORE_MEMCATEGORY_SMALLARRAY, MEMORYBLOCK_ID, MCORE_FILE, MCORE_LINE); - else - m_data = (T*)MCore::Allocate(newSize * sizeof(T), MCORE_MEMCATEGORY_SMALLARRAY, MEMORYBLOCK_ID, MCORE_FILE, MCORE_LINE); - } - MCORE_INLINE void Free() { m_length=0; if (m_data) MCore::Free(m_data); m_data=nullptr; } - MCORE_INLINE void Construct(uint32 index, const T& original) { ::new(m_data+index) T(original); } // copy-construct an element at which is a copy of - MCORE_INLINE void Construct(uint32 index) { ::new(m_data+index) T; } // construct an element at place - MCORE_INLINE void Destruct(uint32 index) - { - #if (MCORE_COMPILER == MCORE_COMPILER_MSVC) // work around a compiler bug, marking this index parameter as unused - MCORE_UNUSED(index); - #endif - (m_data+index)->~T(); - } // destruct an element at - - // partition part of array (for sorting) - int32 Partition(int32 left, int32 right, CmpFunc cmp) - { - ::MCore::Swap(m_data[left], m_data[ (left+right)>>1 ]); - - T& target = m_data[right]; - int32 i = left-1; - int32 j = right; - - bool neverQuit = true; // workaround to disable a "warning C4127: conditional expression is constant" - while (neverQuit) - { - while (i < j) { if (cmp(m_data[++i], target) >= 0) break; } - while (j > i) { if (cmp(m_data[--j], target) <= 0) break; } - if (i >= j) break; - ::MCore::Swap(m_data[i], m_data[j]); - } - - ::MCore::Swap(m_data[i], m_data[right]); - return i; - } -}; - -} // namespace MCore diff --git a/Gems/EMotionFX/Code/MCore/mcore_files.cmake b/Gems/EMotionFX/Code/MCore/mcore_files.cmake index 47b35e004b..8b57d0b7f3 100644 --- a/Gems/EMotionFX/Code/MCore/mcore_files.cmake +++ b/Gems/EMotionFX/Code/MCore/mcore_files.cmake @@ -106,7 +106,6 @@ set(FILES Source/StaticAllocator.cpp Source/StaticAllocator.h Source/StaticString.h - Source/SmallArray.h Source/StandardHeaders.h Source/Stream.h Source/StringConversions.cpp From 7c5120b72fadb51ebee07a408e3f62e6b7a63679 Mon Sep 17 00:00:00 2001 From: Jacob Hilliard <64656371+jcbhl@users.noreply.github.com> Date: Tue, 10 Aug 2021 09:57:04 -0700 Subject: [PATCH 250/803] [ATOM-16021] Initial continuous capture support (#2624) * Profiler: Implement continuous capture internals Signed-off-by: Jacob Hilliard * Profiler: extend ProfileCaptureSystemComponent Implements dumping of saved CPU profiling data to a local file, blocking call. Signed-off-by: Jacob Hilliard * Profiler: Working IO thread for serialization Signed-off-by: Jacob Hilliard * Profiler: switch to AZ::JobFunction for IO Signed-off-by: Jacob Hilliard * Profiler: move to a ring buffer for storage Signed-off-by: Jacob Hilliard * Profiler: switch back to IO thread Signed-off-by: Jacob Hilliard * Profiler: add TODO Signed-off-by: Jacob Hilliard * Profiler: correct thread safety issues Signed-off-by: Jacob Hilliard --- .../Atom/Feature/Utils/ProfilingCaptureBus.h | 8 +- .../ProfilingCaptureSystemComponent.cpp | 166 ++++++++++++------ .../Source/ProfilingCaptureSystemComponent.h | 8 + .../RHI/Code/Include/Atom/RHI/CpuProfiler.h | 9 + .../Code/Include/Atom/RHI/CpuProfilerImpl.h | 23 ++- .../RHI/Code/Source/RHI/CpuProfilerImpl.cpp | 63 ++++++- .../Include/Atom/Utils/ImGuiCpuProfiler.inl | 28 +++ 7 files changed, 243 insertions(+), 62 deletions(-) diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/ProfilingCaptureBus.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/ProfilingCaptureBus.h index 03f522ba44..b22e82f456 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/ProfilingCaptureBus.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/ProfilingCaptureBus.h @@ -28,9 +28,15 @@ namespace AZ //! Dump the PipelineStatistics from passes to a json file. virtual bool CapturePassPipelineStatistics(const AZStd::string& outputFilePath) = 0; - //! Dump the Cpu Profiling Statistics to a json file. + //! Dump a single frame of Cpu profiling data virtual bool CaptureCpuProfilingStatistics(const AZStd::string& outputFilePath) = 0; + //! Start a multiframe capture of CPU profiling data. + virtual bool BeginContinuousCpuProfilingCapture() = 0; + + //! End and dump an in-progress continuous capture. + virtual bool EndContinuousCpuProfilingCapture(const AZStd::string& outputFilePath) = 0; + //! Dump the benchmark metadata to a json file. virtual bool CaptureBenchmarkMetadata(const AZStd::string& benchmarkName, const AZStd::string& outputFilePath) = 0; }; diff --git a/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.cpp b/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.cpp index 1e2d549e7a..add6d0e098 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.cpp @@ -25,6 +25,7 @@ #include #include #include +#include namespace AZ { @@ -157,14 +158,15 @@ namespace AZ Name m_groupName; Name m_regionName; uint16_t m_stackDepth; - AZStd::sys_time_t m_elapsedInNanoseconds; + AZStd::sys_time_t m_startTick; + AZStd::sys_time_t m_endTick; }; AZ_TYPE_INFO(CpuProfilingStatisticsSerializer, "{D5B02946-0D27-474F-9A44-364C2706DD41}"); static void Reflect(AZ::ReflectContext* context); CpuProfilingStatisticsSerializer() = default; - CpuProfilingStatisticsSerializer(const RHI::CpuProfiler::TimeRegionMap& timeRegionMap); + CpuProfilingStatisticsSerializer(const AZStd::ring_buffer& continuousData); AZStd::vector m_cpuProfilingStatisticsSerializerEntries; }; @@ -327,17 +329,20 @@ namespace AZ // --- CpuProfilingStatisticsSerializer --- - CpuProfilingStatisticsSerializer::CpuProfilingStatisticsSerializer(const RHI::CpuProfiler::TimeRegionMap& timeRegionMap) + CpuProfilingStatisticsSerializer::CpuProfilingStatisticsSerializer(const AZStd::ring_buffer& continuousData) { // Create serializable entries - for (auto& threadEntry : timeRegionMap) + for (const auto& timeRegionMap : continuousData) { - for (auto& cachedRegionEntry : threadEntry.second) + for (const auto& threadEntry : timeRegionMap) { - m_cpuProfilingStatisticsSerializerEntries.insert( - m_cpuProfilingStatisticsSerializerEntries.end(), - cachedRegionEntry.second.begin(), - cachedRegionEntry.second.end()); + for (const auto& cachedRegionEntry : threadEntry.second) + { + m_cpuProfilingStatisticsSerializerEntries.insert( + m_cpuProfilingStatisticsSerializerEntries.end(), + cachedRegionEntry.second.begin(), + cachedRegionEntry.second.end()); + } } } } @@ -359,19 +364,11 @@ namespace AZ CpuProfilingStatisticsSerializer::CpuProfilingStatisticsSerializerEntry::CpuProfilingStatisticsSerializerEntry(const RHI::CachedTimeRegion& cachedTimeRegion) { - // Converts ticks to Nanoseconds - static const auto ticksToNanoSeconds = [](AZStd::sys_time_t elapsedInTicks) -> AZStd::sys_time_t - { - const AZStd::sys_time_t ticksPerSecond = AZStd::GetTimeTicksPerSecond(); - - const AZStd::sys_time_t timeInNanoseconds = (elapsedInTicks * 1000000) / (ticksPerSecond / 1000); - return timeInNanoseconds; - }; - m_groupName = cachedTimeRegion.m_groupRegionName->m_groupName; m_regionName = cachedTimeRegion.m_groupRegionName->m_regionName; m_stackDepth = cachedTimeRegion.m_stackDepth; - m_elapsedInNanoseconds = ticksToNanoSeconds(cachedTimeRegion.m_endTick - cachedTimeRegion.m_startTick); + m_startTick = cachedTimeRegion.m_startTick; + m_endTick = cachedTimeRegion.m_endTick; } void CpuProfilingStatisticsSerializer::CpuProfilingStatisticsSerializerEntry::Reflect(AZ::ReflectContext* context) @@ -383,7 +380,8 @@ namespace AZ ->Field("groupName", &CpuProfilingStatisticsSerializerEntry::m_groupName) ->Field("regionName", &CpuProfilingStatisticsSerializerEntry::m_regionName) ->Field("stackDepth", &CpuProfilingStatisticsSerializerEntry::m_stackDepth) - ->Field("elapsedInNanoseconds", &CpuProfilingStatisticsSerializerEntry::m_elapsedInNanoseconds) + ->Field("startTick", &CpuProfilingStatisticsSerializerEntry::m_startTick) + ->Field("endTick", &CpuProfilingStatisticsSerializerEntry::m_endTick) ; } } @@ -474,6 +472,12 @@ namespace AZ TickBus::Handler::BusDisconnect(); ProfilingCaptureRequestBus::Handler::BusDisconnect(); + + // Block deactivation until the IO thread has finished serializing the CPU data + if (m_cpuDataSerializationThread.joinable()) + { + m_cpuDataSerializationThread.join(); + } } bool ProfilingCaptureSystemComponent::CapturePassTimestamp(const AZStd::string& outputFilePath) @@ -641,6 +645,43 @@ namespace AZ return captureStarted; } + bool SerializeCpuProfilingData(const AZStd::ring_buffer& data, AZStd::string outputFilePath, bool wasEnabled) + { + AZ_TracePrintf("ProfilingCaptureSystemComponent", "Beginning serialization of %zu frames of profiling data\n", data.size()); + JsonSerializerSettings serializationSettings; + serializationSettings.m_keepDefaults = true; + + CpuProfilingStatisticsSerializer serializer(data); + + const auto saveResult = JsonSerializationUtils::SaveObjectToFile(&serializer, + outputFilePath, (CpuProfilingStatisticsSerializer*)nullptr, &serializationSettings); + + AZStd::string captureInfo = outputFilePath; + if (!saveResult.IsSuccess()) + { + captureInfo = AZStd::string::format("Failed to save Cpu Profiling Statistics data to file '%s'. Error: %s", + outputFilePath.c_str(), + saveResult.GetError().c_str()); + AZ_Warning("ProfilingCaptureSystemComponent", false, captureInfo.c_str()); + } + else + { + AZ_Printf("ProfilingCaptureSystemComponent", "Cpu profiling statistics was saved to file [%s]\n", outputFilePath.c_str()); + } + + // Disable the profiler again + if (!wasEnabled) + { + RHI::CpuProfiler::Get()->SetProfilerEnabled(false); + } + + // Notify listeners that the pass' PipelineStatistics queries capture has finished. + ProfilingCaptureNotificationBus::Broadcast(&ProfilingCaptureNotificationBus::Events::OnCaptureCpuProfilingStatisticsFinished, + saveResult.IsSuccess(), + captureInfo); + return saveResult.IsSuccess(); + } + bool ProfilingCaptureSystemComponent::CaptureCpuProfilingStatistics(const AZStd::string& outputFilePath) { // Start the cpu profiling @@ -652,40 +693,10 @@ namespace AZ const bool captureStarted = m_cpuProfilingStatisticsCapture.StartCapture([this, outputFilePath, wasEnabled]() { - JsonSerializerSettings serializationSettings; - serializationSettings.m_keepDefaults = true; - - // Get time Cpu profiled time regions - const RHI::CpuProfiler::TimeRegionMap& timeRegionMap = RHI::CpuProfiler::Get()->GetTimeRegionMap(); - - CpuProfilingStatisticsSerializer serializer(timeRegionMap); - const auto saveResult = JsonSerializationUtils::SaveObjectToFile(&serializer, - outputFilePath, (CpuProfilingStatisticsSerializer*)nullptr, &serializationSettings); - - AZStd::string captureInfo = outputFilePath; - if (!saveResult.IsSuccess()) - { - captureInfo = AZStd::string::format("Failed to save Cpu Profiling Statistics data to file '%s'. Error: %s", - outputFilePath.c_str(), - saveResult.GetError().c_str()); - AZ_Warning("ProfilingCaptureSystemComponent", false, captureInfo.c_str()); - } - else - { - AZ_Printf("ProfilingCaptureSystemComponent", "Cpu profiling statistics was saved to file [%s]\n", outputFilePath.c_str()); - } - - // Disable the profiler again - if (!wasEnabled) - { - RHI::CpuProfiler::Get()->SetProfilerEnabled(false); - } - - // Notify listeners that the pass' PipelineStatistics queries capture has finished. - ProfilingCaptureNotificationBus::Broadcast(&ProfilingCaptureNotificationBus::Events::OnCaptureCpuProfilingStatisticsFinished, - saveResult.IsSuccess(), - captureInfo); - + // Blocking call for a single frame of data, avoid thread overhead + AZStd::ring_buffer singleFrameData; + singleFrameData.push_back(RHI::CpuProfiler::Get()->GetTimeRegionMap()); + SerializeCpuProfilingData(singleFrameData, outputFilePath, wasEnabled); }); // Start the TickBus. @@ -697,6 +708,53 @@ namespace AZ return captureStarted; } + bool ProfilingCaptureSystemComponent::BeginContinuousCpuProfilingCapture() + { + return AZ::RHI::CpuProfiler::Get()->BeginContinuousCapture(); + } + + bool ProfilingCaptureSystemComponent::EndContinuousCpuProfilingCapture(const AZStd::string& outputFilePath) + { + bool expected = false; + if (m_cpuDataSerializationInProgress.compare_exchange_strong(expected, true)) + { + AZStd::ring_buffer captureResult; + const bool captureEnded = AZ::RHI::CpuProfiler::Get()->EndContinuousCapture(captureResult); + if (!captureEnded) + { + AZ_TracePrintf("ProfilingCaptureSystemComponent", "Could not end the continuous capture, is one in progress?\n"); + m_cpuDataSerializationInProgress.store(false); + return false; + } + + // cpuProfilingData could be 1GB+ once saved, so use an IO thread to write it to disk. + auto threadIoFunction = + [data = AZStd::move(captureResult), filePath = AZStd::string(outputFilePath), &flag = m_cpuDataSerializationInProgress]() + { + SerializeCpuProfilingData(data, filePath, true); + flag.store(false); + }; + + // If the thread object already exists (ex. we have already serialized data), join. This will not block since + // m_cpuDataSerializationInProgress was false, meaning the IO thread has already completed execution. + // TODO Use a reusable thread implementation over repeated creation + destruction of threads [ATOM-16214] + if (m_cpuDataSerializationThread.joinable()) + { + m_cpuDataSerializationThread.join(); + } + + auto thread = AZStd::thread(threadIoFunction); + m_cpuDataSerializationThread = AZStd::move(thread); + + return true; + } + + AZ_TracePrintf( + "ProfilingSystemCaptureComponent", + "Cannot end a continuous capture - another serialization is currently in progress\n"); + return false; + } + bool ProfilingCaptureSystemComponent::CaptureBenchmarkMetadata(const AZStd::string& benchmarkName, const AZStd::string& outputFilePath) { const bool captureStarted = m_benchmarkMetadataCapture.StartCapture([this, benchmarkName, outputFilePath]() diff --git a/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.h b/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.h index c401d27f30..1846767139 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.h +++ b/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.h @@ -12,6 +12,7 @@ #include #include +#include namespace AZ { @@ -71,6 +72,8 @@ namespace AZ bool CaptureCpuFrameTime(const AZStd::string& outputFilePath) override; bool CapturePassPipelineStatistics(const AZStd::string& outputFilePath) override; bool CaptureCpuProfilingStatistics(const AZStd::string& outputFilePath) override; + bool BeginContinuousCpuProfilingCapture() override; + bool EndContinuousCpuProfilingCapture(const AZStd::string& outputFilePath) override; bool CaptureBenchmarkMetadata(const AZStd::string& benchmarkName, const AZStd::string& outputFilePath) override; private: @@ -86,6 +89,11 @@ namespace AZ DelayedQueryCaptureHelper m_pipelineStatisticsCapture; DelayedQueryCaptureHelper m_cpuProfilingStatisticsCapture; DelayedQueryCaptureHelper m_benchmarkMetadataCapture; + + // Flag passed by reference to the CPU profiling data serialization job, blocks new continuous capture requests when set. + AZStd::atomic_bool m_cpuDataSerializationInProgress = false; + + AZStd::thread m_cpuDataSerializationThread; }; } } diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/CpuProfiler.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/CpuProfiler.h index 1c10b8829f..2248474820 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/CpuProfiler.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/CpuProfiler.h @@ -10,6 +10,7 @@ #include #include +#include #include #include @@ -82,6 +83,14 @@ namespace AZ //! Get the last frame's TimeRegionMap virtual const TimeRegionMap& GetTimeRegionMap() const = 0; + //! Begin a continuous capture. Blocks the profiler from being toggled off until EndContinuousCapture is called. + [[nodiscard]] virtual bool BeginContinuousCapture() = 0; + + //! Flush the CPU Profiler's saved data into the passed ring buffer . + [[nodiscard]] virtual bool EndContinuousCapture(AZStd::ring_buffer& flushTarget) = 0; + + virtual bool IsContinuousCaptureInProgress() const = 0; + //! Enable/Disable the CpuProfiler virtual void SetProfilerEnabled(bool enabled) = 0; diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/CpuProfilerImpl.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/CpuProfilerImpl.h index 640c67858b..7d3b0c5b81 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/CpuProfilerImpl.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/CpuProfilerImpl.h @@ -106,13 +106,18 @@ namespace AZ void OnSystemTick() final override; //! CpuProfiler overrides... - void BeginTimeRegion(TimeRegion& timeRegion) final; - void EndTimeRegion() final; - const TimeRegionMap& GetTimeRegionMap() const final; - void SetProfilerEnabled(bool enabled) final; - bool IsProfilerEnabled() const final; + void BeginTimeRegion(TimeRegion& timeRegion) final override; + void EndTimeRegion() final override; + const TimeRegionMap& GetTimeRegionMap() const final override; + bool BeginContinuousCapture() final override; + bool EndContinuousCapture(AZStd::ring_buffer& flushTarget) final override; + bool IsContinuousCaptureInProgress() const final override; + void SetProfilerEnabled(bool enabled) final override; + bool IsProfilerEnabled() const final override; private: + static constexpr AZStd::size_t MaxFramesToSave = 2 * 60 * 120; // 2 minutes of 120fps + // Lazily create and register the local thread data void RegisterThreadStorage(); @@ -134,6 +139,14 @@ namespace AZ AZStd::shared_mutex m_shutdownMutex; bool m_initialized = false; + + AZStd::mutex m_continuousCaptureEndingMutex; + + AZStd::atomic_bool m_continuousCaptureInProgress; + + // Stores multiple frames of profiling data, size is controlled by MaxFramesToSave. Flushed when EndContinuousCapture is called. + // Ring buffer so that we can have fast append of new data + removal of old profiling data with good cache locality. + AZStd::ring_buffer m_continuousCaptureData; }; }; // namespace RPI diff --git a/Gems/Atom/RHI/Code/Source/RHI/CpuProfilerImpl.cpp b/Gems/Atom/RHI/Code/Source/RHI/CpuProfilerImpl.cpp index 73a1881ead..cdfd4ac469 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/CpuProfilerImpl.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/CpuProfilerImpl.cpp @@ -81,6 +81,7 @@ namespace AZ Interface::Register(this); m_initialized = true; SystemTickBus::Handler::BusConnect(); + m_continuousCaptureData.set_capacity(10); } void CpuProfilerImpl::Shutdown() @@ -101,6 +102,8 @@ namespace AZ m_registeredThreads.clear(); m_timeRegionMap.clear(); m_initialized = false; + m_continuousCaptureInProgress.store(false); + m_continuousCaptureData.clear(); SystemTickBus::Handler::BusDisconnect(); } @@ -141,12 +144,54 @@ namespace AZ return m_timeRegionMap; } + bool CpuProfilerImpl::BeginContinuousCapture() + { + bool expected = false; + if (m_continuousCaptureInProgress.compare_exchange_strong(expected, true)) + { + m_enabled = true; + AZ_TracePrintf("Profiler", "Continuous capture started\n"); + return true; + } + + AZ_TracePrintf("Profiler", "Attempting to start a continuous capture while one already in progress"); + return false; + } + + bool CpuProfilerImpl::EndContinuousCapture(AZStd::ring_buffer& flushTarget) + { + if (!m_continuousCaptureInProgress.load()) + { + AZ_TracePrintf("Profiler", "Attempting to end a continuous capture while one not in progress"); + return false; + } + + if (m_continuousCaptureEndingMutex.try_lock()) + { + m_enabled = false; + flushTarget = AZStd::move(m_continuousCaptureData); + m_continuousCaptureData.clear(); + AZ_TracePrintf("Profiler", "Continuous capture ended\n"); + m_continuousCaptureInProgress.store(false); + + m_continuousCaptureEndingMutex.unlock(); + return true; + } + + return false; + } + + bool CpuProfilerImpl::IsContinuousCaptureInProgress() const + { + return m_continuousCaptureInProgress.load(); + } + void CpuProfilerImpl::SetProfilerEnabled(bool enabled) { AZStd::unique_lock lock(m_threadRegisterMutex); - // Early out if the state is already the same - if (m_enabled == enabled) + // Early out if the state is already the same or a continuous capture is in progress + if (m_enabled == enabled || m_continuousCaptureInProgress.load()) { return; } @@ -179,6 +224,20 @@ namespace AZ { return; } + + if (m_continuousCaptureInProgress.load() && m_continuousCaptureEndingMutex.try_lock()) + { + if (m_continuousCaptureData.full() && m_continuousCaptureData.size() != MaxFramesToSave) + { + const AZStd::size_t size = m_continuousCaptureData.size(); + m_continuousCaptureData.set_capacity(AZStd::min(MaxFramesToSave, size + size / 2)); + } + + m_continuousCaptureData.push_back(AZStd::move(m_timeRegionMap)); + m_timeRegionMap.clear(); + m_continuousCaptureEndingMutex.unlock(); + } + AZStd::unique_lock lock(m_threadRegisterMutex); // Iterate through all the threads, and collect the thread's cached time regions diff --git a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl index ae707a10a7..ffc9a60c00 100644 --- a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl +++ b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl @@ -129,6 +129,34 @@ namespace AZ m_captureToFile = true; } + ImGui::SameLine(); + bool isInProgress = RHI::CpuProfiler::Get()->IsContinuousCaptureInProgress(); + if (ImGui::Button(isInProgress ? "End" : "Begin")) + { + if (isInProgress) + { + AZStd::sys_time_t timeNow = AZStd::GetTimeNowSecond(); + AZStd::string timeString; + AZStd::to_string(timeString, timeNow); + u64 currentTick = AZ::RPI::RPISystemInterface::Get()->GetCurrentTick(); + const AZStd::string frameDataFilePath = AZStd::string::format( + "@user@/CpuProfiler/%s_%llu.json", + timeString.c_str(), + currentTick); + char resolvedPath[AZ::IO::MaxPathLength]; + AZ::IO::FileIOBase::GetInstance()->ResolvePath(frameDataFilePath.c_str(), resolvedPath, AZ::IO::MaxPathLength); + m_lastCapturedFilePath = resolvedPath; + AZ::Render::ProfilingCaptureRequestBus::Broadcast( + &AZ::Render::ProfilingCaptureRequestBus::Events::EndContinuousCpuProfilingCapture, frameDataFilePath); + } + + else + { + AZ::Render::ProfilingCaptureRequestBus::Broadcast( + &AZ::Render::ProfilingCaptureRequestBus::Events::BeginContinuousCpuProfilingCapture); + } + } + if (!m_lastCapturedFilePath.empty()) { ImGui::SameLine(); From 43ae25b49b40b888d2e99d8d570e4fd23c0fdb13 Mon Sep 17 00:00:00 2001 From: antonmic <56370189+antonmic@users.noreply.github.com> Date: Tue, 10 Aug 2021 10:00:42 -0700 Subject: [PATCH 251/803] fixed compiler loss of precision warning Signed-off-by: antonmic <56370189+antonmic@users.noreply.github.com> --- Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RasterPass.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RasterPass.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RasterPass.cpp index 2e61542c36..4da5560908 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RasterPass.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RasterPass.cpp @@ -172,7 +172,7 @@ namespace AZ if (viewDrawList.size() > 0 && drawLists.size() == 0) { m_drawListView = viewDrawList; - m_drawItemCount += viewDrawList.size(); + m_drawItemCount += (u32)viewDrawList.size(); PassSystemInterface::Get()->IncrementFrameDrawItemCount(m_drawItemCount); return; } @@ -183,7 +183,7 @@ namespace AZ // combine draw items from mutiple draw lists to one draw list and sort it. for (auto drawList : drawLists) { - m_drawItemCount += drawList.size(); + m_drawItemCount += (u32)drawList.size(); } PassSystemInterface::Get()->IncrementFrameDrawItemCount(m_drawItemCount); m_combinedDrawList.resize(m_drawItemCount); From e3b22f51b2f210ff67e8d21d9bbcffb567406745 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Tue, 10 Aug 2021 10:50:24 -0700 Subject: [PATCH 252/803] @lumberyard-employee-dm suggestion to use (w)string_view as the src to simplify functions in conversions.h Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Editor/CryEdit.cpp | 2 +- .../AzCore/AzCore/std/string/conversions.h | 154 +++++------------- .../Keyboard/InputDeviceKeyboard_WinAPI.h | 4 +- .../Keyboard/InputDeviceKeyboard_Windows.cpp | 2 +- Code/Legacy/CrySystem/SystemWin32.cpp | 2 +- Code/Legacy/CrySystem/XConsole.cpp | 2 +- .../Support/include/CrashSupport.h | 2 +- Code/Tools/GridHub/GridHub/main.cpp | 6 +- .../RHI/DX12/Code/Source/RHI/MemoryView.cpp | 2 +- .../Source/RHI/RayTracingPipelineState.cpp | 6 +- .../Code/Source/RHI/RayTracingShaderTable.cpp | 2 +- .../AtomFont/Code/Source/FFont.cpp | 2 +- .../Code/Source/UiTextInputComponent.cpp | 2 +- 13 files changed, 56 insertions(+), 132 deletions(-) diff --git a/Code/Editor/CryEdit.cpp b/Code/Editor/CryEdit.cpp index 408de7be2c..0fc283c5c3 100644 --- a/Code/Editor/CryEdit.cpp +++ b/Code/Editor/CryEdit.cpp @@ -3225,7 +3225,7 @@ bool CCryEditApp::CreateLevel(bool& wasCreateLevelOperationCancelled) #ifdef WIN32 wchar_t windowsErrorMessageW[ERROR_LEN]; - windowsErrorMessageW = L'\0'; + windowsErrorMessageW[0] = L'\0'; FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, dw, diff --git a/Code/Framework/AzCore/AzCore/std/string/conversions.h b/Code/Framework/AzCore/AzCore/std/string/conversions.h index c5c9b29cdb..40378467db 100644 --- a/Code/Framework/AzCore/AzCore/std/string/conversions.h +++ b/Code/Framework/AzCore/AzCore/std/string/conversions.h @@ -32,79 +32,79 @@ namespace AZStd { static_assert(Size == size_t{ 2 } || Size == size_t{ 4 }, "only wchar_t types of size 2 or 4 can be converted to utf8"); - template - static inline void to_string(AZStd::basic_string& dest, const wchar_t* first, const wchar_t* last) + template + static inline void to_string(AZStd::basic_string& dest, AZStd::wstring_view src) { if constexpr (Size == 2) { - Utf8::Unchecked::utf16to8(first, last, AZStd::back_inserter(dest), dest.max_size()); + Utf8::Unchecked::utf16to8(src.begin(), src.end(), AZStd::back_inserter(dest), dest.max_size()); } else if constexpr (Size == 4) { - Utf8::Unchecked::utf32to8(first, last, AZStd::back_inserter(dest), dest.max_size()); + Utf8::Unchecked::utf32to8(src.begin(), src.end(), AZStd::back_inserter(dest), dest.max_size()); } } template - static inline void to_string(AZStd::basic_fixed_string& dest, const wchar_t* first, const wchar_t* last) + static inline void to_string(AZStd::basic_fixed_string& dest, AZStd::wstring_view src) { if constexpr (Size == 2) { - Utf8::Unchecked::utf16to8(first, last, AZStd::back_inserter(dest), dest.max_size()); + Utf8::Unchecked::utf16to8(src.begin(), src.end(), AZStd::back_inserter(dest), dest.max_size()); } else if constexpr (Size == 4) { - Utf8::Unchecked::utf32to8(first, last, AZStd::back_inserter(dest), dest.max_size()); + Utf8::Unchecked::utf32to8(src.begin(), src.end(), AZStd::back_inserter(dest), dest.max_size()); } } - static inline char* to_string(char* dest, size_t destSize, const wchar_t* first, const wchar_t* last) + static inline char* to_string(char* dest, size_t destSize, AZStd::wstring_view src) { if constexpr (Size == 2) { - return Utf8::Unchecked::utf16to8(first, last, dest, destSize); + return Utf8::Unchecked::utf16to8(src.begin(), src.end(), dest, destSize); } else if constexpr (Size == 4) { - return Utf8::Unchecked::utf32to8(first, last, dest, destSize); + return Utf8::Unchecked::utf32to8(src.begin(), src.end(), dest, destSize); } } - template - static inline void to_wstring(AZStd::basic_string& dest, const char* first, const char* last) + template + static inline void to_wstring(AZStd::basic_string& dest, AZStd::string_view src) { if constexpr (Size == 2) { - Utf8::Unchecked::utf8to16(first, last, AZStd::back_inserter(dest), dest.max_size()); + Utf8::Unchecked::utf8to16(src.begin(), src.end(), AZStd::back_inserter(dest), dest.max_size()); } else if constexpr (Size == 4) { - Utf8::Unchecked::utf8to32(first, last, AZStd::back_inserter(dest), dest.max_size()); + Utf8::Unchecked::utf8to32(src.begin(), src.end(), AZStd::back_inserter(dest), dest.max_size()); } } template - static inline void to_wstring(AZStd::basic_fixed_string& dest, const char* first, const char* last) + static inline void to_wstring(AZStd::basic_fixed_string& dest, AZStd::string_view src) { if constexpr (Size == 2) { - Utf8::Unchecked::utf8to16(first, last, AZStd::back_inserter(dest), dest.max_size()); + Utf8::Unchecked::utf8to16(src.begin(), src.end(), AZStd::back_inserter(dest), dest.max_size()); } else if constexpr (Size == 4) { - Utf8::Unchecked::utf8to32(first, last, AZStd::back_inserter(dest), dest.max_size()); + Utf8::Unchecked::utf8to32(src.begin(), src.end(), AZStd::back_inserter(dest), dest.max_size()); } } - static inline wchar_t* to_wstring(wchar_t* dest, size_t destSize, const char* first, const char* last) + static inline wchar_t* to_wstring(wchar_t* dest, size_t destSize, AZStd::string_view src) { if constexpr (Size == 2) { - return Utf8::Unchecked::utf8to16(first, last, dest, destSize); + return Utf8::Unchecked::utf8to16(src.begin(), src.end(), dest, destSize); } else if constexpr (Size == 4) { - return Utf8::Unchecked::utf8to32(first, last, dest, destSize); + return Utf8::Unchecked::utf8to32(src.begin(), src.end(), dest, destSize); } } }; @@ -284,64 +284,26 @@ namespace AZStd inline AZStd::string to_string(long double val) { AZStd::string str; to_string(str, val); return str; } // In our engine we assume AZStd::string is Utf8 encoded! - template - void to_string(AZStd::basic_string& dest, const wchar_t* str, size_t srcLen = 0) + template + void to_string(AZStd::basic_string& dest, AZStd::wstring_view src) { dest.clear(); - - if (srcLen == 0) - { - srcLen = wcslen(str); - } - - if (srcLen > 0) - { - Internal::WCharTPlatformConverter<>::to_string(dest, str, str + srcLen); - } - } - - template - void to_string(AZStd::basic_string& dest, const AZStd::basic_string& src) - { - return to_string(dest, src.c_str(), src.length()); + Internal::WCharTPlatformConverter<>::to_string(dest, src); } template - void to_string(AZStd::basic_fixed_string& dest, const wchar_t* str, size_t srcLen = 0) + void to_string(AZStd::basic_fixed_string& dest, AZStd::wstring_view src) { dest.clear(); - - if (srcLen == 0) - { - srcLen = wcslen(str); - } - - if (srcLen > 0) - { - Internal::WCharTPlatformConverter<>::to_string(dest, str, str + srcLen); - } + Internal::WCharTPlatformConverter<>::to_string(dest, src); } - template - void to_string(AZStd::basic_fixed_string& dest, const AZStd::basic_fixed_string& src) + inline void to_string(char* dest, size_t destSize, AZStd::wstring_view src) { - return to_string(dest, src.c_str(), src.length()); - } - - inline void to_string(char* dest, size_t destSize, const wchar_t* str, size_t srcLen = 0) - { - if (srcLen == 0) + char* endStr = Internal::WCharTPlatformConverter<>::to_string(dest, destSize, src); + if (endStr < (dest + destSize)) { - srcLen = wcslen(str); - } - - if (srcLen > 0) - { - char* endStr = Internal::WCharTPlatformConverter<>::to_string(dest, destSize, str, str + srcLen); - if (endStr < (dest + destSize)) - { - *endStr = '\0'; // null terminator - } + *endStr = '\0'; // null terminator } } @@ -441,64 +403,26 @@ namespace AZStd inline AZStd::wstring to_wstring(unsigned long long val) { AZStd::wstring wstr; to_wstring(wstr, val); return wstr; } inline AZStd::wstring to_wstring(long double val) { AZStd::wstring wstr; to_wstring(wstr, val); return wstr; } - template - void to_wstring(AZStd::basic_string& dest, const char* str, size_t strLen = 0) + template + void to_wstring(AZStd::basic_string& dest, AZStd::string_view src) { dest.clear(); - - if (strLen == 0) - { - strLen = strlen(str); - } - - if (strLen > 0) - { - Internal::WCharTPlatformConverter<>::to_wstring(dest, str, str + strLen); - } + Internal::WCharTPlatformConverter<>::to_wstring(dest, src); } - template - void to_wstring(AZStd::basic_string& dest, const AZStd::basic_string& src) - { - return to_wstring(dest, src.c_str(), src.length()); - } - - template - void to_wstring(AZStd::basic_fixed_string& dest, const char* str, size_t strLen = 0) + template + void to_wstring(AZStd::basic_fixed_string& dest, AZStd::string_view src) { dest.clear(); - - if (strLen == 0) - { - strLen = strlen(str); - } - - if (strLen > 0) - { - Internal::WCharTPlatformConverter<>::to_wstring(dest, str, str + strLen); - } + Internal::WCharTPlatformConverter<>::to_wstring(dest, src); } - template - void to_wstring(AZStd::basic_fixed_string& dest, const AZStd::basic_fixed_string& src) + inline void to_wstring(wchar_t* dest, size_t destSize, AZStd::string_view src) { - return to_wstring(dest, src.c_str(), src.length()); - } - - inline void to_wstring(wchar_t* dest, size_t destSize, const char* str, size_t srcLen = 0) - { - if (srcLen == 0) + wchar_t* endWStr = Internal::WCharTPlatformConverter<>::to_wstring(dest, destSize, src); + if (endWStr < (dest + destSize)) { - srcLen = strlen(str); - } - - if (srcLen > 0) - { - wchar_t* endWStr = Internal::WCharTPlatformConverter<>::to_wstring(dest, destSize, str, str + srcLen); - if (endWStr < (dest + destSize)) - { - *endWStr = '\0'; // null terminator - } + *endWStr = '\0'; // null terminator } } diff --git a/Code/Framework/AzFramework/Platform/Common/WinAPI/AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard_WinAPI.h b/Code/Framework/AzFramework/Platform/Common/WinAPI/AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard_WinAPI.h index 591f8421b9..4c90b83bc4 100644 --- a/Code/Framework/AzFramework/Platform/Common/WinAPI/AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard_WinAPI.h +++ b/Code/Framework/AzFramework/Platform/Common/WinAPI/AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard_WinAPI.h @@ -59,7 +59,7 @@ namespace AzFramework { // Convert the valid UTF-16 surrogate pair to a UTF-8 code point const wchar_t codePointUTF16[2] = { m_leadSurrogate, codeUnitUTF16 }; - AZStd::to_string(codePointUTF8, codePointUTF16, 2); + AZStd::to_string(codePointUTF8, { codePointUTF16, 2 }); m_leadSurrogate = 0; } else @@ -72,7 +72,7 @@ namespace AzFramework { // Convert the standalone UTF-16 code point to a UTF-8 code point const wchar_t codePointUTF16[1] = { codeUnitUTF16 }; - AZStd::to_string(codePointUTF8, codePointUTF16, 1); + AZStd::to_string(codePointUTF8, { codePointUTF16, 1 }); m_leadSurrogate = 0; } diff --git a/Code/Framework/AzFramework/Platform/Windows/AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard_Windows.cpp b/Code/Framework/AzFramework/Platform/Windows/AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard_Windows.cpp index 78364fbd0d..f3112ab89c 100644 --- a/Code/Framework/AzFramework/Platform/Windows/AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard_Windows.cpp +++ b/Code/Framework/AzFramework/Platform/Windows/AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard_Windows.cpp @@ -253,7 +253,7 @@ namespace AzFramework if (stringLength != 0) { // Convert UTF-16 to UTF-8 - AZStd::to_string(o_keyOrButtonText, buffer, stringLength); + AZStd::to_string(o_keyOrButtonText, { buffer, aznumeric_cast(stringLength) }); } } diff --git a/Code/Legacy/CrySystem/SystemWin32.cpp b/Code/Legacy/CrySystem/SystemWin32.cpp index b114c9bf12..da8e966b0a 100644 --- a/Code/Legacy/CrySystem/SystemWin32.cpp +++ b/Code/Legacy/CrySystem/SystemWin32.cpp @@ -126,7 +126,7 @@ const char* CSystem::GetUserName() DWORD dwSize = iNameBufferSize; wchar_t nameW[iNameBufferSize]; ::GetUserNameW(nameW, &dwSize); - AZStd::to_string(szNameBuffer, iNameBufferSize, nameW, dwSize); + AZStd::to_string(szNameBuffer, iNameBufferSize, { nameW, dwSize }); return szNameBuffer; #else #if defined(LINUX) diff --git a/Code/Legacy/CrySystem/XConsole.cpp b/Code/Legacy/CrySystem/XConsole.cpp index 8e598c481d..ae07f86312 100644 --- a/Code/Legacy/CrySystem/XConsole.cpp +++ b/Code/Legacy/CrySystem/XConsole.cpp @@ -2861,7 +2861,7 @@ void CXConsole::Paste() { // Convert UCS code-point into UTF-8 string AZStd::fixed_string<5> utf8_buf = {0}; - AZStd::to_string(utf8_buf.data(), 5, &cp, 1); + AZStd::to_string(utf8_buf.data(), 5, { &cp, 1 }); AddInputUTF8(utf8_buf.c_str()); } } diff --git a/Code/Tools/CrashHandler/Support/include/CrashSupport.h b/Code/Tools/CrashHandler/Support/include/CrashSupport.h index 1393930913..e0bec5818b 100644 --- a/Code/Tools/CrashHandler/Support/include/CrashSupport.h +++ b/Code/Tools/CrashHandler/Support/include/CrashSupport.h @@ -41,7 +41,7 @@ namespace CrashHandler std::string returnPath; GetExecutablePath(returnPath); wchar_t currentFileNameW[CRASH_HANDLER_MAX_PATH_LEN] = { 0 }; - AZStd::to_wstring(currentFileNameW, CRASH_HANDLER_MAX_PATH_LEN, returnPath.c_str(), returnPath.size()); + AZStd::to_wstring(currentFileNameW, CRASH_HANDLER_MAX_PATH_LEN, { returnPath.c_str(), returnPath.size() }); returnPathW = currentFileNameW; } diff --git a/Code/Tools/GridHub/GridHub/main.cpp b/Code/Tools/GridHub/GridHub/main.cpp index 670367bf06..bfb82efd0d 100644 --- a/Code/Tools/GridHub/GridHub/main.cpp +++ b/Code/Tools/GridHub/GridHub/main.cpp @@ -408,7 +408,7 @@ GridHubApplication::Create(const Descriptor& descriptor, const StartupParameters if (AZ::Utils::GetExecutablePath(originalExeFileName, AZ_ARRAY_SIZE(originalExeFileName)).m_pathStored == AZ::Utils::ExecutablePathResult::Success) { wchar_t originalExeFileNameW[MAX_PATH]; - AZStd::to_wstring(originalExeFileNameW, MAX_PATH, originalExeFileName, MAX_PATH); + AZStd::to_wstring(originalExeFileNameW, MAX_PATH, originalExeFileName); PathRemoveFileSpec(originalExeFileNameW); PathAppend(originalExeFileNameW, GRIDHUB_IMAGE_NAME); @@ -489,7 +489,7 @@ void CopyAndRun(bool failSilently) if (AZ::Utils::GetExecutablePath(myFileName, MAX_PATH).m_pathStored == AZ::Utils::ExecutablePathResult::Success) { wchar_t myFileNameW[MAX_PATH] = { 0 }; - AZStd::to_wstring(myFileNameW, MAX_PATH, myFileName, MAX_PATH); + AZStd::to_wstring(myFileNameW, MAX_PATH, myFileName); wchar_t sourceProcPath[MAX_PATH] = { 0 }; wchar_t targetProcPath[MAX_PATH] = { 0 }; wchar_t procDrive[MAX_PATH] = { 0 }; @@ -567,7 +567,7 @@ void RelaunchImage() if (AZ::Utils::GetExecutablePath(myFileName, MAX_PATH).m_pathStored == AZ::Utils::ExecutablePathResult::Success) { wchar_t myFileNameW[MAX_PATH] = { 0 }; - AZStd::to_wstring(myFileNameW, MAX_PATH, myFileName, MAX_PATH); + AZStd::to_wstring(myFileNameW, MAX_PATH, myFileName); wchar_t targetProcPath[MAX_PATH] = { 0 }; wchar_t procDrive[MAX_PATH] = { 0 }; wchar_t procDir[MAX_PATH] = { 0 }; diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/MemoryView.cpp b/Gems/Atom/RHI/DX12/Code/Source/RHI/MemoryView.cpp index 1246fb5b1a..c9d932afb1 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI/MemoryView.cpp +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/MemoryView.cpp @@ -94,7 +94,7 @@ namespace AZ if (m_memoryAllocation.m_memory) { AZStd::wstring wname; - AZStd::to_wstring(wname, name.data(), name.size()); + AZStd::to_wstring(wname, name); m_memoryAllocation.m_memory->SetName(wname.data()); } } diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/RayTracingPipelineState.cpp b/Gems/Atom/RHI/DX12/Code/Source/RHI/RayTracingPipelineState.cpp index aebf705790..be0c084d95 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI/RayTracingPipelineState.cpp +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/RayTracingPipelineState.cpp @@ -84,15 +84,15 @@ namespace AZ for (const RHI::RayTracingHitGroup& hitGroup : descriptor->GetHitGroups()) { AZStd::wstring hitGroupNameWstring; - AZStd::to_wstring(hitGroupNameWstring, hitGroup.m_hitGroupName.GetStringView().data(), hitGroup.m_hitGroupName.GetStringView().size()); + AZStd::to_wstring(hitGroupNameWstring, hitGroup.m_hitGroupName.GetStringView()); hitGroupNameWstrings.push_back(hitGroupNameWstring); AZStd::wstring closestHitShaderNameWstring; - AZStd::to_wstring(closestHitShaderNameWstring, hitGroup.m_closestHitShaderName.GetStringView().data(), hitGroup.m_closestHitShaderName.GetStringView().size()); + AZStd::to_wstring(closestHitShaderNameWstring, hitGroup.m_closestHitShaderName.GetStringView()); closestHitShaderNameWstrings.push_back(closestHitShaderNameWstring); AZStd::wstring anyHitShaderNameWstring; - AZStd::to_wstring(anyHitShaderNameWstring, hitGroup.m_anyHitShaderName.GetStringView().data(), hitGroup.m_anyHitShaderName.GetStringView().size()); + AZStd::to_wstring(anyHitShaderNameWstring, hitGroup.m_anyHitShaderName.GetStringView()); anyHitShaderNameWstrings.push_back(anyHitShaderNameWstring); D3D12_HIT_GROUP_DESC hitGroupDesc = {}; diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/RayTracingShaderTable.cpp b/Gems/Atom/RHI/DX12/Code/Source/RHI/RayTracingShaderTable.cpp index eefb1a28aa..21e7dbc82e 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI/RayTracingShaderTable.cpp +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/RayTracingShaderTable.cpp @@ -85,7 +85,7 @@ namespace AZ uint8_t* nextRecord = RHI::AlignUp(mappedData + shaderRecordSize, D3D12_RAYTRACING_SHADER_RECORD_BYTE_ALIGNMENT); AZStd::wstring shaderExportNameWstring; - AZStd::to_wstring(shaderExportNameWstring, record.m_shaderExportName.GetStringView().data(), record.m_shaderExportName.GetStringView().size()); + AZStd::to_wstring(shaderExportNameWstring, record.m_shaderExportName.GetStringView()); void* shaderIdentifier = stateObjectProperties->GetShaderIdentifier(shaderExportNameWstring.c_str()); memcpy(mappedData, shaderIdentifier, D3D12_SHADER_IDENTIFIER_SIZE_IN_BYTES); mappedData += D3D12_SHADER_IDENTIFIER_SIZE_IN_BYTES; diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp b/Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp index fd59b7aed4..9317cae846 100644 --- a/Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp +++ b/Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp @@ -1236,7 +1236,7 @@ void AZ::FFont::WrapText(AZStd::string& result, float maxWidth, const char* str, // get char width and sum it to the line width // Note: This is not unicode compatible, since char-width depends on surrounding context (ie, combining diacritics etc) char codepoint[5]; - AZStd::to_string(codepoint, 5, (wchar_t*)&ch, 1); + AZStd::to_string(codepoint, 5, { (wchar_t*)&ch, 1 }); curCharWidth = GetTextSize(codepoint, true, ctx).x; // keep track of spaces diff --git a/Gems/LyShine/Code/Source/UiTextInputComponent.cpp b/Gems/LyShine/Code/Source/UiTextInputComponent.cpp index 0c61116945..0d9fc09063 100644 --- a/Gems/LyShine/Code/Source/UiTextInputComponent.cpp +++ b/Gems/LyShine/Code/Source/UiTextInputComponent.cpp @@ -1186,7 +1186,7 @@ void UiTextInputComponent::UpdateDisplayedTextFunction() // work for cases tested but may not in general. wchar_t wcharString[2] = { static_cast(this->GetReplacementCharacter()), 0 }; AZStd::string replacementCharString; - AZStd::to_string(replacementCharString, wcharString, 1); + AZStd::to_string(replacementCharString, { wcharString, 1 }); int numReplacementChars = LyShine::GetUtf8StringLength(originalText); From 3b9044ce5d583114b15aaa5049ffbbf5191411bd Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Tue, 10 Aug 2021 11:31:16 -0700 Subject: [PATCH 253/803] Addressing missing test identified by @hultonha Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../AzCore/AzCore/std/string/conversions.h | 17 +++++++++++++++++ .../Common/WinAPI/AzCore/Utils/Utils_WinAPI.cpp | 2 +- Code/Framework/AzCore/Tests/AZStd/String.cpp | 6 ++++++ 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/Code/Framework/AzCore/AzCore/std/string/conversions.h b/Code/Framework/AzCore/AzCore/std/string/conversions.h index 40378467db..b7887339e2 100644 --- a/Code/Framework/AzCore/AzCore/std/string/conversions.h +++ b/Code/Framework/AzCore/AzCore/std/string/conversions.h @@ -70,6 +70,18 @@ namespace AZStd } } + static inline size_t to_string_length(AZStd::wstring_view src) + { + if constexpr (Size == 2) + { + return Utf8::Unchecked::utf16ToUtf8BytesRequired(src.begin(), src.end()); + } + else if constexpr (Size == 4) + { + return Utf8::Unchecked::utf32ToUtf8BytesRequired(src.begin(), src.end()); + } + } + template static inline void to_wstring(AZStd::basic_string& dest, AZStd::string_view src) { @@ -307,6 +319,11 @@ namespace AZStd } } + inline size_t to_string_length(AZStd::wstring_view src) + { + return Internal::WCharTPlatformConverter<>::to_string_length(src); + } + template int stoi(const AZStd::basic_string& str, AZStd::size_t* idx = 0, int base = 10) { diff --git a/Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/Utils/Utils_WinAPI.cpp b/Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/Utils/Utils_WinAPI.cpp index 4d8c9c8cfc..bcba24b768 100644 --- a/Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/Utils/Utils_WinAPI.cpp +++ b/Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/Utils/Utils_WinAPI.cpp @@ -43,7 +43,7 @@ namespace AZ } else { - size_t utf8PathSize = Utf8::Unchecked::utf16ToUtf8BytesRequired(pathBufferW, pathBufferW + pathLen); + size_t utf8PathSize = AZStd::to_string_length({ pathBufferW, pathLen }); if (utf8PathSize >= exeStorageSize) { result.m_pathStored = ExecutablePathResult::BufferSizeNotLargeEnough; diff --git a/Code/Framework/AzCore/Tests/AZStd/String.cpp b/Code/Framework/AzCore/Tests/AZStd/String.cpp index 309f561a75..9dae4a3d3f 100644 --- a/Code/Framework/AzCore/Tests/AZStd/String.cpp +++ b/Code/Framework/AzCore/Tests/AZStd/String.cpp @@ -674,6 +674,7 @@ namespace UnitTest string str1; to_string(str1, wstr); AZ_TEST_ASSERT(str1 == "BlaBla 5"); + EXPECT_EQ(8, to_string_length(wstr)); str1 = string::format("%ls", wstr.c_str()); AZ_TEST_ASSERT(str1 == "BlaBla 5"); @@ -690,6 +691,11 @@ namespace UnitTest char strBuffer[9]; to_string(strBuffer, 9, wstr1.c_str()); AZ_TEST_ASSERT(0 == azstricmp(strBuffer, "BLABLA 5")); + EXPECT_EQ(8, to_string_length(wstr1)); + + // wstring to char with unicode + wstring ws1InfinityEscaped = L"Infinity: \u221E"; // escaped + EXPECT_EQ(13, to_string_length(ws1InfinityEscaped)); // wchar_t buffer to char buffer wchar_t wstrBuffer[9] = L"BLABLA 5"; From e6259882b87d1096523c4167862b05ecfa5788cb Mon Sep 17 00:00:00 2001 From: Chris Burel Date: Tue, 10 Aug 2021 09:58:11 -0700 Subject: [PATCH 254/803] Replace `MCore::AlignedArray` with `AZStd::vector` Signed-off-by: Chris Burel --- Gems/EMotionFX/Code/EMotionFX/Source/Pose.cpp | 159 ++-- Gems/EMotionFX/Code/EMotionFX/Source/Pose.h | 18 +- .../Code/MCore/Source/AlignedArray.h | 783 ------------------ Gems/EMotionFX/Code/MCore/mcore_files.cmake | 1 - 4 files changed, 87 insertions(+), 874 deletions(-) delete mode 100644 Gems/EMotionFX/Code/MCore/Source/AlignedArray.h diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Pose.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Pose.cpp index 23390bf69b..99f1474c89 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Pose.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Pose.cpp @@ -24,10 +24,6 @@ namespace EMotionFX m_actorInstance = nullptr; m_actor = nullptr; m_skeleton = nullptr; - m_localSpaceTransforms.SetMemoryCategory(EMFX_MEMCATEGORY_ANIMGRAPH_POSE); - m_modelSpaceTransforms.SetMemoryCategory(EMFX_MEMCATEGORY_ANIMGRAPH_POSE); - m_flags.SetMemoryCategory(EMFX_MEMCATEGORY_ANIMGRAPH_POSE); - m_morphWeights.SetMemoryCategory(EMFX_MEMCATEGORY_ANIMGRAPH_POSE); } @@ -55,10 +51,10 @@ namespace EMotionFX // resize the buffers const size_t numTransforms = m_actor->GetSkeleton()->GetNumNodes(); - m_localSpaceTransforms.ResizeFast(numTransforms); - m_modelSpaceTransforms.ResizeFast(numTransforms); - m_flags.ResizeFast(numTransforms); - m_morphWeights.ResizeFast(actorInstance->GetMorphSetupInstance()->GetNumMorphTargets()); + m_localSpaceTransforms.resize_no_construct(numTransforms); + m_modelSpaceTransforms.resize_no_construct(numTransforms); + m_flags.resize_no_construct(numTransforms); + m_morphWeights.resize_no_construct(actorInstance->GetMorphSetupInstance()->GetNumMorphTargets()); for (const auto& poseDataItem : m_poseDatas) { @@ -79,11 +75,11 @@ namespace EMotionFX // resize the buffers const size_t numTransforms = m_actor->GetSkeleton()->GetNumNodes(); - m_localSpaceTransforms.ResizeFast(numTransforms); - m_modelSpaceTransforms.ResizeFast(numTransforms); + m_localSpaceTransforms.resize_no_construct(numTransforms); + m_modelSpaceTransforms.resize_no_construct(numTransforms); - const size_t oldSize = m_flags.GetLength(); - m_flags.ResizeFast(numTransforms); + const size_t oldSize = m_flags.size(); + m_flags.resize_no_construct(numTransforms); if (oldSize < numTransforms && clearAllFlags == false) { for (size_t i = oldSize; i < numTransforms; ++i) @@ -93,7 +89,7 @@ namespace EMotionFX } MorphSetup* morphSetup = m_actor->GetMorphSetup(0); - m_morphWeights.ResizeFast((morphSetup) ? morphSetup->GetNumMorphTargets() : 0); + m_morphWeights.resize_no_construct((morphSetup) ? morphSetup->GetNumMorphTargets() : 0); for (const auto& poseDataItem : m_poseDatas) { @@ -111,11 +107,11 @@ namespace EMotionFX void Pose::SetNumTransforms(size_t numTransforms) { // resize the buffers - m_localSpaceTransforms.ResizeFast(numTransforms); - m_modelSpaceTransforms.ResizeFast(numTransforms); + m_localSpaceTransforms.resize_no_construct(numTransforms); + m_modelSpaceTransforms.resize_no_construct(numTransforms); - const size_t oldSize = m_flags.GetLength(); - m_flags.ResizeFast(numTransforms); + const size_t oldSize = m_flags.size(); + m_flags.resize_no_construct(numTransforms); for (size_t i = oldSize; i < numTransforms; ++i) { @@ -127,10 +123,18 @@ namespace EMotionFX void Pose::Clear(bool clearMem) { - m_localSpaceTransforms.Clear(clearMem); - m_modelSpaceTransforms.Clear(clearMem); - m_flags.Clear(clearMem); - m_morphWeights.Clear(clearMem); + const auto clear = [clearMem](auto& vector) + { + vector.clear(); + if (clearMem) + { + vector.shrink_to_fit(); + } + }; + clear(m_localSpaceTransforms); + clear(m_modelSpaceTransforms); + clear(m_flags); + clear(m_morphWeights); ClearPoseDatas(); } @@ -139,7 +143,7 @@ namespace EMotionFX // clear the pose flags void Pose::ClearFlags(uint8 newFlags) { - MCore::MemSet((uint8*)m_flags.GetPtr(), newFlags, sizeof(uint8) * m_flags.GetLength()); + MCore::MemSet((uint8*)m_flags.data(), newFlags, sizeof(uint8) * m_flags.size()); } @@ -398,30 +402,27 @@ namespace EMotionFX // invalidate all local transforms void Pose::InvalidateAllLocalSpaceTransforms() { - const size_t numFlags = m_flags.GetLength(); - for (size_t i = 0; i < numFlags; ++i) + for (uint8& flag : m_flags) { - m_flags[i] &= ~FLAG_LOCALTRANSFORMREADY; + flag &= ~FLAG_LOCALTRANSFORMREADY; } } void Pose::InvalidateAllModelSpaceTransforms() { - const size_t numFlags = m_flags.GetLength(); - for (size_t i = 0; i < numFlags; ++i) + for (uint8& flag : m_flags) { - m_flags[i] &= ~FLAG_MODELTRANSFORMREADY; + flag &= ~FLAG_MODELTRANSFORMREADY; } } void Pose::InvalidateAllLocalAndModelSpaceTransforms() { - const size_t numFlags = m_flags.GetLength(); - for (size_t i = 0; i < numFlags; ++i) + for (uint8& flag : m_flags) { - m_flags[i] &= ~(FLAG_LOCALTRANSFORMREADY | FLAG_MODELTRANSFORMREADY); + flag &= ~(FLAG_LOCALTRANSFORMREADY | FLAG_MODELTRANSFORMREADY); } } @@ -469,8 +470,8 @@ namespace EMotionFX // make sure the number of transforms are equal MCORE_ASSERT(destPose); MCORE_ASSERT(outPose); - MCORE_ASSERT(m_localSpaceTransforms.GetLength() == destPose->m_localSpaceTransforms.GetLength()); - MCORE_ASSERT(m_localSpaceTransforms.GetLength() == outPose->m_localSpaceTransforms.GetLength()); + MCORE_ASSERT(m_localSpaceTransforms.size() == destPose->m_localSpaceTransforms.size()); + MCORE_ASSERT(m_localSpaceTransforms.size() == outPose->m_localSpaceTransforms.size()); MCORE_ASSERT(instance->GetIsMixing() == false); // get some motion instance properties which we use to decide the optimized blending routine @@ -509,7 +510,7 @@ namespace EMotionFX } // blend the morph weights - const size_t numMorphs = m_morphWeights.GetLength(); + const size_t numMorphs = m_morphWeights.size(); MCORE_ASSERT(actorInstance->GetMorphSetupInstance()->GetNumMorphTargets() == numMorphs); MCORE_ASSERT(numMorphs == destPose->GetNumMorphWeights()); for (size_t i = 0; i < numMorphs; ++i) @@ -533,7 +534,7 @@ namespace EMotionFX outPose->InvalidateAllModelSpaceTransforms(); // blend the morph weights - const size_t numMorphs = m_morphWeights.GetLength(); + const size_t numMorphs = m_morphWeights.size(); MCORE_ASSERT(actorInstance->GetMorphSetupInstance()->GetNumMorphTargets() == numMorphs); MCORE_ASSERT(numMorphs == destPose->GetNumMorphWeights()); for (size_t i = 0; i < numMorphs; ++i) @@ -550,8 +551,8 @@ namespace EMotionFX // make sure the number of transforms are equal MCORE_ASSERT(destPose); MCORE_ASSERT(outPose); - MCORE_ASSERT(m_localSpaceTransforms.GetLength() == destPose->m_localSpaceTransforms.GetLength()); - MCORE_ASSERT(m_localSpaceTransforms.GetLength() == outPose->m_localSpaceTransforms.GetLength()); + MCORE_ASSERT(m_localSpaceTransforms.size() == destPose->m_localSpaceTransforms.size()); + MCORE_ASSERT(m_localSpaceTransforms.size() == outPose->m_localSpaceTransforms.size()); MCORE_ASSERT(instance->GetIsMixing()); const bool additive = (instance->GetBlendMode() == BLENDMODE_ADDITIVE); @@ -564,7 +565,7 @@ namespace EMotionFX Transform result; const MotionLinkData* motionLinkData = instance->GetMotion()->GetMotionData()->FindMotionLinkData(actorInstance->GetActor()); - AZ_Assert(motionLinkData->GetJointDataLinks().size() == m_localSpaceTransforms.GetLength(), "Expecting there to be the same amount of motion links as pose transforms."); + AZ_Assert(motionLinkData->GetJointDataLinks().size() == m_localSpaceTransforms.size(), "Expecting there to be the same amount of motion links as pose transforms."); // blend all transforms if (!additive) @@ -589,7 +590,7 @@ namespace EMotionFX outPose->InvalidateAllModelSpaceTransforms(); // blend the morph weights - const size_t numMorphs = m_morphWeights.GetLength(); + const size_t numMorphs = m_morphWeights.size(); MCORE_ASSERT(actorInstance->GetMorphSetupInstance()->GetNumMorphTargets() == numMorphs); MCORE_ASSERT(numMorphs == destPose->GetNumMorphWeights()); for (size_t i = 0; i < numMorphs; ++i) @@ -619,7 +620,7 @@ namespace EMotionFX outPose->InvalidateAllModelSpaceTransforms(); // blend the morph weights - const size_t numMorphs = m_morphWeights.GetLength(); + const size_t numMorphs = m_morphWeights.size(); MCORE_ASSERT(actorInstance->GetMorphSetupInstance()->GetNumMorphTargets() == numMorphs); MCORE_ASSERT(numMorphs == destPose->GetNumMorphWeights()); for (size_t i = 0; i < numMorphs; ++i) @@ -647,10 +648,10 @@ namespace EMotionFX return; } - m_modelSpaceTransforms.MemCopyContentsFrom(sourcePose->m_modelSpaceTransforms); - m_localSpaceTransforms.MemCopyContentsFrom(sourcePose->m_localSpaceTransforms); - m_flags.MemCopyContentsFrom(sourcePose->m_flags); - m_morphWeights.MemCopyContentsFrom(sourcePose->m_morphWeights); + m_modelSpaceTransforms = sourcePose->m_modelSpaceTransforms; + m_localSpaceTransforms = sourcePose->m_localSpaceTransforms; + m_flags = sourcePose->m_flags; + m_morphWeights = sourcePose->m_morphWeights; // Deactivate pose datas from the current pose that are not in the source that we copy from. // This is needed in order to prevent leftover pose datas and to avoid de-/allocations. @@ -727,11 +728,11 @@ namespace EMotionFX m_localSpaceTransforms[nodeNr].Zero(); } - const size_t numMorphs = m_morphWeights.GetLength(); + const size_t numMorphs = m_morphWeights.size(); MCORE_ASSERT(m_actorInstance->GetMorphSetupInstance()->GetNumMorphTargets() == numMorphs); - for (size_t i = 0; i < numMorphs; ++i) + for (float& morphWeight : m_morphWeights) { - m_morphWeights[i] = 0.0f; + morphWeight = 0.0f; } } else @@ -742,11 +743,11 @@ namespace EMotionFX m_localSpaceTransforms[i].Zero(); } - const size_t numMorphs = m_morphWeights.GetLength(); + const size_t numMorphs = m_morphWeights.size(); MCORE_ASSERT(m_actor->GetMorphSetup(0)->GetNumMorphTargets() == numMorphs); - for (size_t i = 0; i < numMorphs; ++i) + for (float& morphWeight : m_morphWeights) { - m_morphWeights[i] = 0.0f; + morphWeight = 0.0f; } } @@ -795,7 +796,7 @@ namespace EMotionFX } // blend the morph weights - const size_t numMorphs = m_morphWeights.GetLength(); + const size_t numMorphs = m_morphWeights.size(); MCORE_ASSERT(m_actorInstance->GetMorphSetupInstance()->GetNumMorphTargets() == numMorphs); MCORE_ASSERT(numMorphs == other->GetNumMorphWeights()); for (size_t i = 0; i < numMorphs; ++i) @@ -814,7 +815,7 @@ namespace EMotionFX } // blend the morph weights - const size_t numMorphs = m_morphWeights.GetLength(); + const size_t numMorphs = m_morphWeights.size(); MCORE_ASSERT(m_actor->GetMorphSetup(0)->GetNumMorphTargets() == numMorphs); MCORE_ASSERT(numMorphs == other->GetNumMorphWeights()); for (size_t i = 0; i < numMorphs; ++i) @@ -841,7 +842,7 @@ namespace EMotionFX } // blend the morph weights - const size_t numMorphs = m_morphWeights.GetLength(); + const size_t numMorphs = m_morphWeights.size(); MCORE_ASSERT(m_actorInstance->GetMorphSetupInstance()->GetNumMorphTargets() == numMorphs); MCORE_ASSERT(numMorphs == destPose->GetNumMorphWeights()); for (size_t i = 0; i < numMorphs; ++i) @@ -865,7 +866,7 @@ namespace EMotionFX } // blend the morph weights - const size_t numMorphs = m_morphWeights.GetLength(); + const size_t numMorphs = m_morphWeights.size(); MCORE_ASSERT(m_actor->GetMorphSetup(0)->GetNumMorphTargets() == numMorphs); MCORE_ASSERT(numMorphs == destPose->GetNumMorphWeights()); for (size_t i = 0; i < numMorphs; ++i) @@ -886,7 +887,7 @@ namespace EMotionFX Pose& Pose::MakeRelativeTo(const Pose& other) { - AZ_Assert(m_localSpaceTransforms.GetLength() == other.m_localSpaceTransforms.GetLength(), "Poses must be of the same size"); + AZ_Assert(m_localSpaceTransforms.size() == other.m_localSpaceTransforms.size(), "Poses must be of the same size"); if (m_actorInstance) { const size_t numNodes = m_actorInstance->GetNumEnabledNodes(); @@ -899,7 +900,7 @@ namespace EMotionFX } else { - const size_t numNodes = m_localSpaceTransforms.GetLength(); + const size_t numNodes = m_localSpaceTransforms.size(); for (size_t i = 0; i < numNodes; ++i) { Transform& transform = const_cast(GetLocalSpaceTransform(i)); @@ -907,7 +908,7 @@ namespace EMotionFX } } - const size_t numMorphs = m_morphWeights.GetLength(); + const size_t numMorphs = m_morphWeights.size(); AZ_Assert(numMorphs == other.GetNumMorphWeights(), "Number of morphs in the pose doesn't match the number of morphs inside the provided input pose."); for (size_t i = 0; i < numMorphs; ++i) { @@ -921,7 +922,7 @@ namespace EMotionFX Pose& Pose::ApplyAdditive(const Pose& additivePose, float weight) { - AZ_Assert(m_localSpaceTransforms.GetLength() == additivePose.m_localSpaceTransforms.GetLength(), "Poses must be of the same size"); + AZ_Assert(m_localSpaceTransforms.size() == additivePose.m_localSpaceTransforms.size(), "Poses must be of the same size"); if (m_actorInstance) { AZ_Assert(weight > -MCore::Math::epsilon && weight < (1 + MCore::Math::epsilon), "Expected weight to be between 0..1"); @@ -939,7 +940,7 @@ namespace EMotionFX } else { - AZ_Assert(m_localSpaceTransforms.GetLength() == additivePose.m_localSpaceTransforms.GetLength(), "Poses must be of the same size"); + AZ_Assert(m_localSpaceTransforms.size() == additivePose.m_localSpaceTransforms.size(), "Poses must be of the same size"); if (m_actorInstance) { const size_t numNodes = m_actorInstance->GetNumEnabledNodes(); @@ -959,7 +960,7 @@ namespace EMotionFX } else { - const size_t numNodes = m_localSpaceTransforms.GetLength(); + const size_t numNodes = m_localSpaceTransforms.size(); for (size_t i = 0; i < numNodes; ++i) { Transform& transform = const_cast(GetLocalSpaceTransform(i)); @@ -974,7 +975,7 @@ namespace EMotionFX } } - const size_t numMorphs = m_morphWeights.GetLength(); + const size_t numMorphs = m_morphWeights.size(); AZ_Assert(numMorphs == additivePose.GetNumMorphWeights(), "Number of morphs in the pose doesn't match the number of morphs inside the provided input pose."); for (size_t i = 0; i < numMorphs; ++i) { @@ -989,7 +990,7 @@ namespace EMotionFX Pose& Pose::ApplyAdditive(const Pose& additivePose) { - AZ_Assert(m_localSpaceTransforms.GetLength() == additivePose.m_localSpaceTransforms.GetLength(), "Poses must be of the same size"); + AZ_Assert(m_localSpaceTransforms.size() == additivePose.m_localSpaceTransforms.size(), "Poses must be of the same size"); if (m_actorInstance) { const size_t numNodes = m_actorInstance->GetNumEnabledNodes(); @@ -1009,7 +1010,7 @@ namespace EMotionFX } else { - const size_t numNodes = m_localSpaceTransforms.GetLength(); + const size_t numNodes = m_localSpaceTransforms.size(); for (size_t i = 0; i < numNodes; ++i) { Transform& transform = const_cast(GetLocalSpaceTransform(i)); @@ -1024,7 +1025,7 @@ namespace EMotionFX } } - const size_t numMorphs = m_morphWeights.GetLength(); + const size_t numMorphs = m_morphWeights.size(); AZ_Assert(numMorphs == additivePose.GetNumMorphWeights(), "Number of morphs in the pose doesn't match the number of morphs inside the provided input pose."); for (size_t i = 0; i < numMorphs; ++i) { @@ -1038,7 +1039,7 @@ namespace EMotionFX Pose& Pose::MakeAdditive(const Pose& refPose) { - AZ_Assert(m_localSpaceTransforms.GetLength() == refPose.m_localSpaceTransforms.GetLength(), "Poses must be of the same size"); + AZ_Assert(m_localSpaceTransforms.size() == refPose.m_localSpaceTransforms.size(), "Poses must be of the same size"); if (m_actorInstance) { const size_t numNodes = m_actorInstance->GetNumEnabledNodes(); @@ -1057,7 +1058,7 @@ namespace EMotionFX } else { - const size_t numNodes = m_localSpaceTransforms.GetLength(); + const size_t numNodes = m_localSpaceTransforms.size(); for (size_t i = 0; i < numNodes; ++i) { Transform& transform = const_cast(GetLocalSpaceTransform(i)); @@ -1071,7 +1072,7 @@ namespace EMotionFX } } - const size_t numMorphs = m_morphWeights.GetLength(); + const size_t numMorphs = m_morphWeights.size(); AZ_Assert(numMorphs == refPose.GetNumMorphWeights(), "Number of morphs in the pose doesn't match the number of morphs inside the provided input pose."); for (size_t i = 0; i < numMorphs; ++i) { @@ -1101,7 +1102,7 @@ namespace EMotionFX } // blend the morph weights - const size_t numMorphs = m_morphWeights.GetLength(); + const size_t numMorphs = m_morphWeights.size(); MCORE_ASSERT(m_actorInstance->GetMorphSetupInstance()->GetNumMorphTargets() == numMorphs); MCORE_ASSERT(numMorphs == destPose->GetNumMorphWeights()); for (size_t i = 0; i < numMorphs; ++i) @@ -1123,7 +1124,7 @@ namespace EMotionFX } // blend the morph weights - const size_t numMorphs = m_morphWeights.GetLength(); + const size_t numMorphs = m_morphWeights.size(); MCORE_ASSERT(m_actor->GetMorphSetup(0)->GetNumMorphTargets() == numMorphs); MCORE_ASSERT(numMorphs == destPose->GetNumMorphWeights()); for (size_t i = 0; i < numMorphs; ++i) @@ -1274,23 +1275,19 @@ namespace EMotionFX // zero all morph weights void Pose::ZeroMorphWeights() { - const size_t numMorphs = m_morphWeights.GetLength(); - for (size_t m = 0; m < numMorphs; ++m) - { - m_morphWeights[m] = 0.0f; - } + AZStd::fill(begin(m_morphWeights), end(m_morphWeights), 0.0f); } void Pose::ResizeNumMorphs(size_t numMorphTargets) { - m_morphWeights.Resize(numMorphTargets); + m_morphWeights.resize(numMorphTargets); } Pose& Pose::PreMultiply(const Pose& other) { - AZ_Assert(m_localSpaceTransforms.GetLength() == other.m_localSpaceTransforms.GetLength(), "Poses must be of the same size"); + AZ_Assert(m_localSpaceTransforms.size() == other.m_localSpaceTransforms.size(), "Poses must be of the same size"); if (m_actorInstance) { const size_t numNodes = m_actorInstance->GetNumEnabledNodes(); @@ -1304,7 +1301,7 @@ namespace EMotionFX } else { - const size_t numNodes = m_localSpaceTransforms.GetLength(); + const size_t numNodes = m_localSpaceTransforms.size(); for (size_t i = 0; i < numNodes; ++i) { Transform& transform = const_cast(GetLocalSpaceTransform(i)); @@ -1320,7 +1317,7 @@ namespace EMotionFX Pose& Pose::Multiply(const Pose& other) { - AZ_Assert(m_localSpaceTransforms.GetLength() == other.m_localSpaceTransforms.GetLength(), "Poses must be of the same size"); + AZ_Assert(m_localSpaceTransforms.size() == other.m_localSpaceTransforms.size(), "Poses must be of the same size"); if (m_actorInstance) { const size_t numNodes = m_actorInstance->GetNumEnabledNodes(); @@ -1333,7 +1330,7 @@ namespace EMotionFX } else { - const size_t numNodes = m_localSpaceTransforms.GetLength(); + const size_t numNodes = m_localSpaceTransforms.size(); for (size_t i = 0; i < numNodes; ++i) { Transform& transform = const_cast(GetLocalSpaceTransform(i)); @@ -1348,7 +1345,7 @@ namespace EMotionFX Pose& Pose::MultiplyInverse(const Pose& other) { - AZ_Assert(m_localSpaceTransforms.GetLength() == other.m_localSpaceTransforms.GetLength(), "Poses must be of the same size"); + AZ_Assert(m_localSpaceTransforms.size() == other.m_localSpaceTransforms.size(), "Poses must be of the same size"); if (m_actorInstance) { const size_t numNodes = m_actorInstance->GetNumEnabledNodes(); @@ -1363,7 +1360,7 @@ namespace EMotionFX } else { - const size_t numNodes = m_localSpaceTransforms.GetLength(); + const size_t numNodes = m_localSpaceTransforms.size(); for (size_t i = 0; i < numNodes; ++i) { Transform& transform = const_cast(GetLocalSpaceTransform(i)); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Pose.h b/Gems/EMotionFX/Code/EMotionFX/Source/Pose.h index 32c7a33bd2..b7844276be 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Pose.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Pose.h @@ -9,7 +9,7 @@ #pragma once #include -#include +#include #include #include @@ -98,9 +98,9 @@ namespace EMotionFX Transform CalcTrajectoryTransform() const; - MCORE_INLINE const Transform* GetLocalSpaceTransforms() const { return m_localSpaceTransforms.GetReadPtr(); } - MCORE_INLINE const Transform* GetModelSpaceTransforms() const { return m_modelSpaceTransforms.GetReadPtr(); } - MCORE_INLINE size_t GetNumTransforms() const { return m_localSpaceTransforms.GetLength(); } + MCORE_INLINE const Transform* GetLocalSpaceTransforms() const { return m_localSpaceTransforms.data(); } + MCORE_INLINE const Transform* GetModelSpaceTransforms() const { return m_modelSpaceTransforms.data(); } + MCORE_INLINE size_t GetNumTransforms() const { return m_localSpaceTransforms.size(); } MCORE_INLINE const ActorInstance* GetActorInstance() const { return m_actorInstance; } MCORE_INLINE const Actor* GetActor() const { return m_actor; } MCORE_INLINE const Skeleton* GetSkeleton() const { return m_skeleton; } @@ -116,7 +116,7 @@ namespace EMotionFX MCORE_INLINE void SetMorphWeight(size_t index, float weight) { m_morphWeights[index] = weight; } MCORE_INLINE float GetMorphWeight(size_t index) const { return m_morphWeights[index]; } - MCORE_INLINE size_t GetNumMorphWeights() const { return m_morphWeights.GetLength(); } + MCORE_INLINE size_t GetNumMorphWeights() const { return m_morphWeights.size(); } void ResizeNumMorphs(size_t numMorphTargets); /** @@ -193,11 +193,11 @@ namespace EMotionFX T* GetAndPreparePoseData(ActorInstance* linkToActorInstance) { return azdynamic_cast(GetAndPreparePoseData(azrtti_typeid(), linkToActorInstance)); } private: - mutable MCore::AlignedArray m_localSpaceTransforms; - mutable MCore::AlignedArray m_modelSpaceTransforms; - mutable MCore::AlignedArray m_flags; + mutable AZStd::vector m_localSpaceTransforms; + mutable AZStd::vector m_modelSpaceTransforms; + mutable AZStd::vector m_flags; AZStd::unordered_map > m_poseDatas; - MCore::AlignedArray m_morphWeights; /**< The morph target weights. */ + AZStd::vector m_morphWeights; /**< The morph target weights. */ const ActorInstance* m_actorInstance; const Actor* m_actor; const Skeleton* m_skeleton; diff --git a/Gems/EMotionFX/Code/MCore/Source/AlignedArray.h b/Gems/EMotionFX/Code/MCore/Source/AlignedArray.h deleted file mode 100644 index 5ffaac2e40..0000000000 --- a/Gems/EMotionFX/Code/MCore/Source/AlignedArray.h +++ /dev/null @@ -1,783 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -#pragma once - -#include "StandardHeaders.h" -#include "MCoreSystem.h" -#include "Algorithms.h" -#include "MemoryManager.h" - - -namespace MCore -{ - /** - * Dynamic array template, using aligned memory allocations. - * This array template allows dynamic sizing. It also stores the memory category of the data. - * It can theoretically store 18446744073709551614 items (maximum size_t value - 1 for the invalid index). - */ - template - class AlignedArray - { - public: - /** - * The memory block ID, used inside the memory manager. - * This will make all arrays remain in the same memory blocks, which is more efficient in a lot of cases. - * However, array data can still remain in other blocks. - */ - enum - { - MEMORYBLOCK_ID = 3 - }; - - /** - * Default constructor. - * Initializes the array so it's empty and has no memory allocated. - */ - MCORE_INLINE AlignedArray() - : m_data(nullptr) - , m_length(0) - , m_maxLength(0) - , m_memCategory(MCORE_MEMCATEGORY_ARRAY) {} - - /** - * Constructor which creates a given number of elements. - * @param elems The element data. - * @param num The number of elements in 'elems'. - * @param memCategory The memory category the array is in. - */ - MCORE_INLINE explicit AlignedArray(T* elems, size_t num, uint16 memCategory = MCORE_MEMCATEGORY_ARRAY) - : m_length(num) - , m_maxLength(AllocSize(num)) - , m_memCategory(memCategory) - { - m_data = (T*)AlignedAllocate(m_maxLength * sizeof(T), alignment, m_memCategory, MEMORYBLOCK_ID, MCORE_FILE, MCORE_LINE); - for (size_t i = 0; i < m_length; ++i) - { - Construct(i, elems[i]); - } - } - - /** - * Constructor which initializes the length of the array on a given number. - * @param initSize The number of ellements to allocate space for. - * @param memCategory The memory category the array is in. - */ - MCORE_INLINE explicit AlignedArray(size_t initSize, uint16 memCategory = MCORE_MEMCATEGORY_ARRAY) - : m_data(nullptr) - , m_length(initSize) - , m_maxLength(initSize) - , m_memCategory(memCategory) - { - if (m_maxLength > 0) - { - m_data = (T*)AlignedAllocate(m_maxLength * sizeof(T), alignment, m_memCategory, MEMORYBLOCK_ID, MCORE_FILE, MCORE_LINE); - for (size_t i = 0; i < m_length; ++i) - { - Construct(i); - } - } - } - - /** - * Copy constructor. - * @param other The other array to copy the data from. - */ - AlignedArray(const AlignedArray& other) - : m_data(nullptr) - , m_length(0) - , m_maxLength(0) - , m_memCategory(MCORE_MEMCATEGORY_ARRAY) { *this = other; } - - /** - * Move constructor. - * @param other The array to move the data from. - */ - AlignedArray(AlignedArray&& other) { m_data = other.m_data; m_length = other.m_length; m_maxLength = other.m_maxLength; m_memCategory = other.m_memCategory; other.m_data = nullptr; other.m_length = 0; other.m_maxLength = 0; } - - /** - * Destructor. Deletes all entry data. - * However, if you store pointers to objects, these objects won't be deleted.
- * Example:
- *
-         * AlignedArray< Object*, 16 > data;
-         * for (size_t i=0; i<10; i++)
-         *    data.Add( new Object() );
-         * 
- * Now when the array 'data' will be destructed, it will NOT free up the memory of the integers which you allocated by hand, using new. - * In order to free up this memory, you can do this: - *
-         * for (size_t i=0; i
-         */
-        ~AlignedArray()
-        {
-            for (size_t i = 0; i < m_length; ++i)
-            {
-                Destruct(i);
-            }
-            if (m_data)
-            {
-                AlignedFree(m_data);
-            }
-        }
-
-        /**
-         * Get the memory category ID where allocations made by this array belong to.
-         * On default the memory category is 0, which means unknown.
-         * @result The memory category ID.
-         */
-        MCORE_INLINE uint16 GetMemoryCategory() const                           { return m_memCategory; }
-
-        /**
-         * Set the memory category ID, where allocations made by this array will belong to.
-         * On default, after construction of the array, the category ID is 0, which means it is unknown.
-         * @param categoryID The memory category ID where this arrays allocations belong to.
-         */
-        MCORE_INLINE void SetMemoryCategory(uint16 categoryID)                  { m_memCategory = categoryID; }
-
-        /**
-         * Get a pointer to the first element.
-         * @result A pointer to the first element.
-         */
-        MCORE_INLINE T* GetPtr()                                                { return m_data; }
-
-        /**
-         * Get a pointer to the first element.
-         * @result A pointer to the first element.
-         */
-        MCORE_INLINE T* GetPtr() const                                          { return m_data; }
-
-        /**
-         * Get a given item/element.
-         * @param pos The item/element number.
-         * @result A reference to the element.
-         */
-        MCORE_INLINE T& GetItem(size_t pos)                                     { return m_data[pos]; }
-
-        /**
-         * Get the first element.
-         * @result A reference to the first element.
-         */
-        MCORE_INLINE T& GetFirst()                                              { return m_data[0]; }
-
-        /**
-         * Get the last element.
-         * @result A reference to the last element.
-         */
-        MCORE_INLINE T& GetLast()                                               { return m_data[m_length - 1]; }
-
-        /**
-         * Get a read-only pointer to the first element.
-         * @result A read-only pointer to the first element.
-         */
-        MCORE_INLINE const T* GetReadPtr() const                                { return m_data; }
-
-        /**
-         * Get a read-only reference to a given element number.
-         * @param pos The element number.
-         * @result A read-only reference to the given element.
-         */
-        MCORE_INLINE const T& GetItem(size_t pos) const                         { return m_data[pos]; }
-
-        /**
-         * Get a read-only reference to the first element.
-         * @result A read-only reference to the first element.
-         */
-        MCORE_INLINE const T& GetFirst() const                                  { return m_data[0]; }
-
-        /**
-         * Get a read-only reference to the last element.
-         * @result A read-only reference to the last element.
-         */
-        MCORE_INLINE const T& GetLast() const                                   { return m_data[m_length - 1]; }
-
-        /**
-         * Check if the array is empty or not.
-         * @result Returns true when there are no elements in the array, otherwise false is returned.
-         */
-        MCORE_INLINE bool GetIsEmpty() const                                    { return (m_length == 0); }
-
-        /**
-         * Checks if the passed index is in the array's range.
-         * @param index The index to check.
-         * @return True if the passed index is valid, false if not.
-         */
-        MCORE_INLINE bool GetIsValidIndex(size_t index) const                   { return (index < m_length); }
-
-        /**
-         * Get the number of elements in the array.
-         * @result The number of elements in the array.
-         */
-        MCORE_INLINE size_t GetLength() const                                   { return m_length; }
-
-        /**
-         * Get the maximum number of elements. This is the number of elements there currently is space for to store.
-         * However, never use this to make for-loops to iterate through all elements. Use GetLength() instead for that.
-         * This purely has to do with pre-allocating, to reduce the number of reallocs.
-         * @result The maximum array length.
-         */
-        MCORE_INLINE size_t GetMaxLength() const                                { return m_maxLength; }
-
-        /**
-         * Calculates the memory usage used by this array.
-         * @param includeMembers Include the class members in the calculation? (default=true).
-         * @result The number of bytes allocated by this array.
-         */
-        MCORE_INLINE size_t CalcMemoryUsage(bool includeMembers = true) const
-        {
-            size_t result = m_maxLength * sizeof(T);
-            if (includeMembers)
-            {
-                result += sizeof(AlignedArray);
-            }
-            return result;
-        }
-
-        /**
-         * Set a given element to a given value.
-         * @param pos The element number.
-         * @param value The value to store at that element number.
-         */
-        MCORE_INLINE void SetElem(size_t pos, const T& value)                   { m_data[pos] = value; }
-
-        /**
-         * Add a given element to the back of the array.
-         * @param x The element to add.
-         */
-        MCORE_INLINE void Add(const T& x)                                       { Grow(++m_length); Construct(m_length - 1, x); }
-
-        /**
-         * Add a given element to the back of the array, but without pre-allocation caching.
-         * @param x The element to add.
-         */
-        MCORE_INLINE void AddExact(const T& x)                                  { GrowExact(++m_length); Construct(m_length - 1, x); }
-
-        /**
-         * Add a given array to the back of this array.
-         * @param a The array to add.
-         */
-        MCORE_INLINE void Add(const AlignedArray& a)
-        {
-            size_t l = m_length;
-            Grow(m_length + a.m_length);
-            for (size_t i = 0; i < a.GetLength(); ++i)
-            {
-                Construct(l + i, a[i]);
-            }
-        }                                                                                                                                                                                   // TODO: a.GetLength() can be precaled before loop?
-
-        /**
-         * Add an empty (default constructed) element to the back of the array.
-         */
-        MCORE_INLINE void AddEmpty()                                            { Grow(++m_length); Construct(m_length - 1); }
-
-        /**
-         * Add an empty (default constructed) element to the back of the array, but without pre-allocation caching.
-         */
-        MCORE_INLINE void AddEmptyExact()                                       { GrowExact(++m_length); Construct(m_length - 1); }
-
-        /**
-         * Remove the first array element.
-         */
-        MCORE_INLINE void RemoveFirst()
-        {
-            if (m_length > 0)
-            {
-                Remove(0);
-            }
-        }
-
-        /**
-         * Remove the last array element.
-         */
-        MCORE_INLINE void RemoveLast()
-        {
-            if (m_length > 0)
-            {
-                Destruct(--m_length);
-            }
-        }
-
-        /**
-         * Insert an empty element (default constructed) at a given position in the array.
-         * @param pos The position to create the empty element.
-         */
-        MCORE_INLINE void Insert(size_t pos)                                    { Grow(m_length + 1); MoveElements(pos + 1, pos, m_length - pos - 1); Construct(pos); }
-
-        /**
-         * Insert a given element at a given position in the array.
-         * @param pos The position to insert the empty element.
-         * @param x The element to store at this position.
-         */
-        MCORE_INLINE void Insert(size_t pos, const T& x)                        { Grow(m_length + 1); MoveElements(pos + 1, pos, m_length - pos - 1); Construct(pos, x); }
-
-        /**
-         * Remove an element at a given position.
-         * @param pos The element number to remove.
-         */
-        MCORE_INLINE void Remove(size_t pos)
-        {
-            Destruct(pos);
-            if (m_length > 1)
-            {
-                MoveElements(pos, pos + 1, m_length - pos - 1);
-            }
-            m_length--;
-        }
-
-        /**
-         * Remove a given number of elements starting at a given position in the array.
-         * @param pos The start element, so to start removing from.
-         * @param num The number of elements to remove from this position.
-         */
-        MCORE_INLINE void Remove(size_t pos, size_t num)
-        {
-            for (size_t i = pos; i < pos + num; ++i)
-            {
-                Destruct(i);
-            }
-            MoveElements(pos, pos + num, m_length - pos - num);
-            m_length -= num;
-        }
-
-        /**
-         * Remove a given element with a given value.
-         * Only the first element with the given value will be removed.
-         * @param item The item/element to remove.
-         */
-        MCORE_INLINE bool RemoveByValue(const T& item)
-        {
-            size_t index = Find(item);
-            if (index == InvalidIndex)
-            {
-                return false;
-            }
-            Remove(index);
-            return true;
-        }
-
-        /**
-         * Remove a given element in the array and place the last element in the array at the created empty position.
-         * So if we have an array with the following characters : ABCDEFG
- * And we perform a SwapRemove(2), we will remove element C and place the last element (G) at the empty created position where C was located. - * So we will get this:
- * AB.DEFG [where . is empty, after we did the SwapRemove(2)]
- * ABGDEF [this is the result. G has been moved to the empty position]. - */ - MCORE_INLINE void SwapRemove(size_t pos) - { - Destruct(pos); - if (pos != m_length - 1) - { - Construct(pos, m_data[m_length - 1]); - Destruct(m_length - 1); - } - m_length--; - } // remove element at and place the last element of the array in that position - - /** - * Swap two elements. - * @param pos1 The first element number. - * @param pos2 The second element number. - */ - MCORE_INLINE void Swap(size_t pos1, size_t pos2) - { - if (pos1 != pos2) - { - Swap(GetItem(pos1), GetItem(pos2)); - } - } - - /** - * Clear the array contents. So GetLength() will return 0 after performing this method. - * @param clearMem If set to true (default) the allocated memory will also be released. If set to false, GetMaxLength() will still return the number of elements - * which the array contained before calling the Clear() method. - */ - MCORE_INLINE void Clear(bool clearMem = true) - { - for (size_t i = 0; i < m_length; ++i) - { - Destruct(i); - } - m_length = 0; - if (clearMem) - { - this->Free(); - } - } - - /** - * Make sure the array has enough space to store a given number of elements. - * @param newLength The number of elements we want to make sure that will fit in the array. - */ - MCORE_INLINE void AssureSize(size_t newLength) - { - if (m_length >= newLength) - { - return; - } - size_t oldLen = m_length; - Grow(newLength); - for (size_t i = oldLen; i < newLength; ++i) - { - Construct(i); - } - } - - /** - * Make sure this array has enough allocated storage to grow to a given number of elements elements without having to realloc. - * @param minLength The minimum length the array should have (actually the minimum maxLength, because this has no influence on what GetLength() will return). - */ - MCORE_INLINE void Reserve(size_t minLength) - { - if (m_maxLength < minLength) - { - Realloc(minLength); - } - } - - /** - * Make the array as small as possible. So remove all extra pre-allocated data, so that the array consumes the least possible amount of memory. - */ - MCORE_INLINE void Shrink() - { - if (m_length == m_maxLength) - { - return; - } - MCORE_ASSERT(m_maxLength >= m_length); - Realloc(m_length); - } - - /** - * Check if the array contains a given element. - * @param x The element to check. - * @result Returns true when the array contains the element, otherwise false is returned. - */ - MCORE_INLINE bool Contains(const T& x) const { return (Find(x) != InvalidIndex); } - - /** - * Find the position of a given element. - * @param x The element to find. - * @result Returns the index in the array, ranging from [0 to GetLength()-1] when found, otherwise InvalidIndex is returned. - */ - MCORE_INLINE size_t Find(const T& x) const - { - for (size_t i = 0; i < m_length; ++i) - { - if (m_data[i] == x) - { - return i; - } - } - return InvalidIndex; - } - - /** - * Copy the contents of another array into this one using a direct memory copy. - * This does not call copy constructors of the objects, but just copies the raw memory data. - * This resizes this array to be the exact length of the array we will copy the data from. - * @param other The array to copy the data from. - */ - MCORE_INLINE void MemCopyContentsFrom(const AlignedArray& other) { Resize(other.GetLength()); MemCopy((uint8*)m_data, (uint8*)other.m_data, sizeof(T) * other.m_length); } - - // sort function and standard sort function - typedef int32 (MCORE_CDECL * CmpFunc)(const T& itemA, const T& itemB); - static int32 MCORE_CDECL StdCmp(const T& itemA, const T& itemB) - { - if (itemA < itemB) - { - return -1; - } - else if (itemA == itemB) - { - return 0; - } - else - { - return 1; - } - } - static int32 MCORE_CDECL StdPtrObjCmp(const T& itemA, const T& itemB) - { - if (*itemA < *itemB) - { - return -1; - } - else if (*itemA == *itemB) - { - return 0; - } - else - { - return 1; - } - } - - /** - * Sort the complete array using a given sort function. - * @param cmp The sort function to use. - */ - MCORE_INLINE void Sort(CmpFunc cmp) { InnerSort(0, m_length - 1, cmp); } - - /** - * Sort a given part of the array using a given sort function. - * The default parameters are set so that it will sort the compelete array with a default compare function (which uses the < and > operators). - * The method will sort all elements between the given 'first' and 'last' element (first and last are also included in the sort). - * @param first The first element to start sorting. - * @param last The last element to sort (when set to InvalidIndex, GetLength()-1 will be used). - * @param cmp The compare function. - */ - MCORE_INLINE void Sort(size_t first = 0, size_t last = InvalidIndex, CmpFunc cmp = StdCmp) - { - if (last == InvalidIndex) - { - last = m_length - 1; - } - InnerSort(first, last, cmp); - } - - /** - * Performs a sort on a given part of the array. - * @param first The first element to start the sorting at. - * @param last The last element to end the sorting. - * @param cmp The compare function. - */ - MCORE_INLINE void InnerSort(int32 first, int32 last, CmpFunc cmp) - { - if (first >= last) - { - return; - } - int32 split = Partition(first, last, cmp); - InnerSort(first, split - 1, cmp); - InnerSort(split + 1, last, cmp); - } - - // resize in a fast way that doesn't call constructors or destructors - void ResizeFast(size_t newLength) - { - if (m_length == newLength) - { - return; - } - - if (newLength > m_length) - { - GrowExact(newLength); - } - - m_length = newLength; - } - - /** - * Resize the array to a given size. - * This does not mean an actual realloc will be made. This will only happen when the new length is bigger than the maxLength of the array. - * @param newLength The new length the array should be. - */ - void Resize(size_t newLength) - { - if (m_length == newLength) - { - return; - } - - // check for growing or shrinking array - if (newLength > m_length) - { - // growing array, construct empty elements at end of array - const size_t oldLen = m_length; - GrowExact(newLength); - for (size_t i = oldLen; i < newLength; ++i) - { - Construct(i); - } - } - else - { - // shrinking array, destruct elements at end of array - for (size_t i = newLength; i < m_length; ++i) - { - Destruct(i); - } - - m_length = newLength; - } - } - - /** - * Move "numElements" elements starting from the source index, to the dest index. - * Please note thate the array has to be large enough. You can't move data past the end of the array. - * @param destIndex The destination index. - * @param sourceIndex The source index, where the source elements start. - * @param numElements The number of elements to move. - */ - MCORE_INLINE void MoveElements(size_t destIndex, size_t sourceIndex, size_t numElements) - { - if (numElements > 0) - { - MemMove(m_data + destIndex, m_data + sourceIndex, numElements * sizeof(T)); - } - } - - // operators - bool operator==(const AlignedArray& other) const - { - if (m_length != other.m_length) - { - return false; - } - for (size_t i = 0; i < m_length; ++i) - { - if (m_data[i] != other.m_data[i]) - { - return false; - } - } - return true; - } - AlignedArray& operator= (const AlignedArray& other) - { - if (&other != this) - { - Clear(false); - m_memCategory = other.m_memCategory; - Grow(other.m_length); - for (size_t i = 0; i < m_length; ++i) - { - Construct(i, other.m_data[i]); - } - } - return *this; - } - AlignedArray& operator= (AlignedArray&& other) - { - MCORE_ASSERT(&other != this); - if (m_data) - { - AlignedFree(m_data); - } - m_data = other.m_data; - m_memCategory = other.m_memCategory; - m_length = other.m_length; - m_maxLength = other.m_maxLength; - other.m_data = nullptr; - other.m_length = 0; - other.m_maxLength = 0; - return *this; - } - AlignedArray& operator+=(const T& other) { Add(other); return *this; } - AlignedArray& operator+=(const AlignedArray& other) { Add(other); return *this; } - MCORE_INLINE T& operator[](size_t index) { MCORE_ASSERT(index < m_length); return m_data[index]; } - MCORE_INLINE const T& operator[](size_t index) const { MCORE_ASSERT(index < m_length); return m_data[index]; } - - private: - T* m_data; /**< The element data. */ - size_t m_length; /**< The number of used elements in the array. */ - size_t m_maxLength; /**< The number of elements that we have allocated memory for. */ - uint16 m_memCategory; /**< The memory category ID. */ - - // private functions - MCORE_INLINE void Grow(size_t newLength) - { - m_length = newLength; - if (m_maxLength >= newLength) - { - return; - } - Realloc(AllocSize(newLength)); - } - MCORE_INLINE void GrowExact(size_t newLength) - { - m_length = newLength; - if (m_maxLength < newLength) - { - Realloc(newLength); - } - } - MCORE_INLINE size_t AllocSize(size_t num) { return 1 + num /*+num/8*/; } - MCORE_INLINE void Alloc(size_t num) { m_data = (T*)AlignedAllocate(num * sizeof(T), alignment, m_memCategory, MEMORYBLOCK_ID, MCORE_FILE, MCORE_LINE); } - MCORE_INLINE void Realloc(size_t newSize) - { - if (newSize == 0) - { - this->Free(); - return; - } - if (m_data) - { - m_data = (T*)AlignedRealloc(m_data, newSize * sizeof(T), m_maxLength * sizeof(T), alignment, m_memCategory, MEMORYBLOCK_ID, MCORE_FILE, MCORE_LINE); - } - else - { - m_data = (T*)AlignedAllocate(newSize * sizeof(T), alignment, m_memCategory, MEMORYBLOCK_ID, MCORE_FILE, MCORE_LINE); - } - - m_maxLength = newSize; - } - void Free() - { - m_length = 0; - m_maxLength = 0; - if (m_data) - { - AlignedFree(m_data); - m_data = nullptr; - } - } - MCORE_INLINE void Construct(size_t index, const T& original) { ::new(m_data + index)T(original); } // copy-construct an element at which is a copy of - MCORE_INLINE void Construct(size_t index) { ::new(m_data + index)T; } // construct an element at place - MCORE_INLINE void Destruct(size_t index) - { - #if (MCORE_COMPILER == MCORE_COMPILER_MSVC) - MCORE_UNUSED(index); // work around an MSVC compiler bug, where it triggers a warning that parameter 'index' is unused - #endif - (m_data + index)->~T(); - } - - // partition part of array (for sorting) - int32 Partition(int32 left, int32 right, CmpFunc cmp) - { - ::MCore::Swap(m_data[left], m_data[ (left + right) >> 1 ]); - - T& target = m_data[right]; - int32 i = left - 1; - int32 j = right; - - bool neverQuit = true; // workaround to disable a "warning C4127: conditional expression is constant" - while (neverQuit) - { - while (i < j) - { - if (cmp(m_data[++i], target) >= 0) - { - break; - } - } - while (j > i) - { - if (cmp(m_data[--j], target) <= 0) - { - break; - } - } - if (i >= j) - { - break; - } - ::MCore::Swap(m_data[i], m_data[j]); - } - - ::MCore::Swap(m_data[i], m_data[right]); - return i; - } - }; -} // namespace MCore diff --git a/Gems/EMotionFX/Code/MCore/mcore_files.cmake b/Gems/EMotionFX/Code/MCore/mcore_files.cmake index 47b35e004b..bb9c0f4447 100644 --- a/Gems/EMotionFX/Code/MCore/mcore_files.cmake +++ b/Gems/EMotionFX/Code/MCore/mcore_files.cmake @@ -11,7 +11,6 @@ set(FILES Source/Algorithms.cpp Source/Algorithms.h Source/Algorithms.inl - Source/AlignedArray.h Source/Array2D.h Source/Array2D.inl Source/Attribute.cpp From 8d0f9f4114630a35ebceb677086f7e16ff5c1df2 Mon Sep 17 00:00:00 2001 From: Scott Romero <24445312+AMZN-ScottR@users.noreply.github.com> Date: Tue, 10 Aug 2021 12:19:31 -0700 Subject: [PATCH 255/803] [development] updated file regex when uploading latest tagged installer (#2987) The "Latest" tagged installer uploads were failing the file filter because the upload script now collects files as full path before performing the regex. Signed-off-by: AMZN-ScottR 24445312+AMZN-ScottR@users.noreply.github.com --- cmake/Platform/Windows/PackagingPostBuild.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/Platform/Windows/PackagingPostBuild.cmake b/cmake/Platform/Windows/PackagingPostBuild.cmake index 3f364b89c5..5e09743373 100644 --- a/cmake/Platform/Windows/PackagingPostBuild.cmake +++ b/cmake/Platform/Windows/PackagingPostBuild.cmake @@ -189,7 +189,7 @@ if(CPACK_AUTO_GEN_TAG) upload_to_s3( ${_latest_upload_url} ${_temp_dir} - "(${_non_versioned_exe}|build_tag.txt)$" + ".*(${_non_versioned_exe}|build_tag.txt)$" ) # cleanup the temp files From a9cd126026e2a27ed531b097717cdb8f3a0d10e3 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Tue, 10 Aug 2021 12:30:04 -0700 Subject: [PATCH 256/803] Adding PLATFORM_H_SECTION_15 back since it is used in restricted Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Legacy/CryCommon/platform.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Code/Legacy/CryCommon/platform.h b/Code/Legacy/CryCommon/platform.h index 9ff461543f..88d06c9b1e 100644 --- a/Code/Legacy/CryCommon/platform.h +++ b/Code/Legacy/CryCommon/platform.h @@ -24,6 +24,7 @@ #define PLATFORM_H_SECTION_12 12 #define PLATFORM_H_SECTION_13 13 #define PLATFORM_H_SECTION_14 14 +#define PLATFORM_H_SECTION_15 15 #endif #if (defined(LINUX) && !defined(ANDROID)) || defined(APPLE) @@ -414,4 +415,9 @@ threadID CryGetCurrentThreadId(); #endif #endif +#if defined(AZ_RESTRICTED_PLATFORM) + #define AZ_RESTRICTED_SECTION PLATFORM_H_SECTION_15 + #include AZ_RESTRICTED_FILE(platform_h) +#endif + void InitRootDir(char szExeFileName[] = nullptr, uint nExeSize = 0, char szExeRootName[] = nullptr, uint nRootSize = 0); From ab1b6ff3b40640ce502a340b447ab8939f143189 Mon Sep 17 00:00:00 2001 From: michabr <82236305+michabr@users.noreply.github.com> Date: Tue, 10 Aug 2021 12:41:24 -0700 Subject: [PATCH 257/803] Add LyShine gem runtime dependency to Material Editor in AutomatedTesting project (#2996) Signed-off-by: abrmich --- AutomatedTesting/Gem/Code/CMakeLists.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/AutomatedTesting/Gem/Code/CMakeLists.txt b/AutomatedTesting/Gem/Code/CMakeLists.txt index 76c0db3f5c..58ffd957d6 100644 --- a/AutomatedTesting/Gem/Code/CMakeLists.txt +++ b/AutomatedTesting/Gem/Code/CMakeLists.txt @@ -57,6 +57,12 @@ if (PAL_TRAIT_BUILD_HOST_TOOLS) TARGETS Editor VARIANTS Tools) + # The Material Editor needs the Lyshine "Tools" gem variant for the custom LyShine pass + ly_enable_gems( + PROJECT_NAME AutomatedTesting GEMS LyShine + TARGETS MaterialEditor + VARIANTS Tools) + # The pipeline tools use "Builders" gem variants: ly_enable_gems( PROJECT_NAME AutomatedTesting GEM_FILE enabled_gems.cmake From 5472d6768e8a3ceb81f901251858bb58600439d0 Mon Sep 17 00:00:00 2001 From: antonmic <56370189+antonmic@users.noreply.github.com> Date: Tue, 10 Aug 2021 12:48:26 -0700 Subject: [PATCH 258/803] Minor improvements Signed-off-by: antonmic <56370189+antonmic@users.noreply.github.com> --- .../RPI/Code/Include/Atom/RPI.Public/Pass/RasterPass.h | 6 +++--- .../RPI/Code/Source/RPI.Public/Pass/RasterPass.cpp | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/RasterPass.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/RasterPass.h index cdbf983561..2c884ceedf 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/RasterPass.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/RasterPass.h @@ -38,12 +38,12 @@ namespace AZ void SetDrawListTag(Name drawListName); - void SetPipelineStateDataIndex(u32 index); + void SetPipelineStateDataIndex(uint32_t index); //! Expose shader resource group. ShaderResourceGroup* GetShaderResourceGroup(); - u32 GetDrawItemCount(); + uint32_t GetDrawItemCount(); protected: explicit RasterPass(const PassDescriptor& descriptor); @@ -78,7 +78,7 @@ namespace AZ RHI::Viewport m_viewportState; bool m_overrideScissorSate = false; bool m_overrideViewportState = false; - u32 m_drawItemCount = 0; + uint32_t m_drawItemCount = 0; }; } // namespace RPI } // namespace AZ diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RasterPass.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RasterPass.cpp index 4da5560908..ce02e1c570 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RasterPass.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RasterPass.cpp @@ -104,7 +104,7 @@ namespace AZ m_flags.m_hasDrawListTag = true; } - void RasterPass::SetPipelineStateDataIndex(u32 index) + void RasterPass::SetPipelineStateDataIndex(uint32_t index) { m_pipelineStateDataIndex.m_index = index; } @@ -114,7 +114,7 @@ namespace AZ return m_shaderResourceGroup.get(); } - u32 RasterPass::GetDrawItemCount() + uint32_t RasterPass::GetDrawItemCount() { return m_drawItemCount; } @@ -172,7 +172,7 @@ namespace AZ if (viewDrawList.size() > 0 && drawLists.size() == 0) { m_drawListView = viewDrawList; - m_drawItemCount += (u32)viewDrawList.size(); + m_drawItemCount += static_cast(viewDrawList.size()); PassSystemInterface::Get()->IncrementFrameDrawItemCount(m_drawItemCount); return; } @@ -183,7 +183,7 @@ namespace AZ // combine draw items from mutiple draw lists to one draw list and sort it. for (auto drawList : drawLists) { - m_drawItemCount += (u32)drawList.size(); + m_drawItemCount += static_cast(drawList.size()); } PassSystemInterface::Get()->IncrementFrameDrawItemCount(m_drawItemCount); m_combinedDrawList.resize(m_drawItemCount); @@ -211,7 +211,7 @@ namespace AZ void RasterPass::SetupFrameGraphDependencies(RHI::FrameGraphInterface frameGraph) { RenderPass::SetupFrameGraphDependencies(frameGraph); - frameGraph.SetEstimatedItemCount(static_cast(m_drawListView.size())); + frameGraph.SetEstimatedItemCount(static_cast(m_drawListView.size())); } void RasterPass::CompileResources(const RHI::FrameGraphCompileContext& context) From c229191fad3a1595658502e9ee767764305891a9 Mon Sep 17 00:00:00 2001 From: evanchia Date: Tue, 10 Aug 2021 13:09:42 -0700 Subject: [PATCH 259/803] removing unused output for aztestrunner Signed-off-by: evanchia --- Code/Tools/AzTestRunner/src/main.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Code/Tools/AzTestRunner/src/main.cpp b/Code/Tools/AzTestRunner/src/main.cpp index d9ee727447..231e4e8059 100644 --- a/Code/Tools/AzTestRunner/src/main.cpp +++ b/Code/Tools/AzTestRunner/src/main.cpp @@ -120,12 +120,6 @@ namespace AzTestRunner { const char* cwd = AzTestRunner::get_current_working_directory(); std::cout << "cwd = " << cwd << std::endl; - - for (int i = 0; i < argc; i++) - { - std::cout << "arg[" << i << "] " << argv[i] << std::endl; - } - std::cout << "LIB: " << lib << std::endl; } From 4450eb4e224c1352addf25db767a61ef3a812e39 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Tue, 10 Aug 2021 13:24:20 -0700 Subject: [PATCH 260/803] fix new warning hit Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../Source/MorphTargetsWindow/PhonemeSelectionWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/PhonemeSelectionWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/PhonemeSelectionWindow.cpp index 4f1aa5b42b..a0d0e62abd 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/PhonemeSelectionWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/MorphTargetsWindow/PhonemeSelectionWindow.cpp @@ -330,7 +330,7 @@ namespace EMStudio const size_t numMorphTargets = m_morphSetup->GetNumMorphTargets(); const uint32 numPhonemeSets = m_morphTarget->GetNumAvailablePhonemeSets(); int insertPosition = 0; - for (int i = 1; i < numPhonemeSets; ++i) + for (uint32 i = 1; i < numPhonemeSets; ++i) { // check if another morph target already has this phoneme set. bool phonemeSetFound = false; From 181998f8107f8776c3bc137732059f0a3b67639e Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Tue, 10 Aug 2021 14:05:14 -0700 Subject: [PATCH 261/803] Fixes a nightly build and a CMake warning (#2941) * Addressing CMake warning and removing timeouts that are the same as the default Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> * missed this one Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> * Making it an error so developers stops putting timeouts longer than the allowed one since it causes AR issues Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> * fixing warning from the nightly build Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> * disabling test that is triggering a timeout Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../Gem/PythonTests/Blast/CMakeLists.txt | 1 - .../Gem/PythonTests/NvCloth/CMakeLists.txt | 1 - .../PythonAssetBuilder/CMakeLists.txt | 1 - .../Gem/PythonTests/WhiteBox/CMakeLists.txt | 1 - .../asset_processor_tests/CMakeLists.txt | 24 +++++++++---------- .../Gem/PythonTests/editor/CMakeLists.txt | 4 ---- .../PythonTests/largeworlds/CMakeLists.txt | 11 --------- .../Gem/PythonTests/physics/CMakeLists.txt | 3 --- .../Gem/PythonTests/prefab/CMakeLists.txt | 1 - .../Gem/PythonTests/scripting/CMakeLists.txt | 2 -- .../Gem/PythonTests/smoke/CMakeLists.txt | 1 - Gems/PhysX/Code/CMakeLists.txt | 1 - cmake/LYTestWrappers.cmake | 2 +- 13 files changed, 12 insertions(+), 41 deletions(-) diff --git a/AutomatedTesting/Gem/PythonTests/Blast/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/Blast/CMakeLists.txt index 7048a6bd46..172eded09a 100644 --- a/AutomatedTesting/Gem/PythonTests/Blast/CMakeLists.txt +++ b/AutomatedTesting/Gem/PythonTests/Blast/CMakeLists.txt @@ -12,7 +12,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) TEST_SUITE main TEST_SERIAL TRUE PATH ${CMAKE_CURRENT_LIST_DIR}/TestSuite_Active.py - TIMEOUT 1500 RUNTIME_DEPENDENCIES Legacy::Editor AZ::AssetProcessor diff --git a/AutomatedTesting/Gem/PythonTests/NvCloth/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/NvCloth/CMakeLists.txt index a39cdf04cf..3913041f88 100644 --- a/AutomatedTesting/Gem/PythonTests/NvCloth/CMakeLists.txt +++ b/AutomatedTesting/Gem/PythonTests/NvCloth/CMakeLists.txt @@ -13,7 +13,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) TEST_REQUIRES gpu TEST_SERIAL PATH ${CMAKE_CURRENT_LIST_DIR}/TestSuite_Active.py - TIMEOUT 1500 RUNTIME_DEPENDENCIES Legacy::Editor AZ::AssetProcessor diff --git a/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/CMakeLists.txt index 9b6542b3e3..905470e08f 100644 --- a/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/CMakeLists.txt +++ b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/CMakeLists.txt @@ -12,7 +12,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) TEST_SUITE periodic TEST_SERIAL PATH ${CMAKE_CURRENT_LIST_DIR} - TIMEOUT 1500 RUNTIME_DEPENDENCIES Legacy::Editor AZ::AssetProcessor diff --git a/AutomatedTesting/Gem/PythonTests/WhiteBox/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/WhiteBox/CMakeLists.txt index b5fcfcc44c..1c7a02862d 100644 --- a/AutomatedTesting/Gem/PythonTests/WhiteBox/CMakeLists.txt +++ b/AutomatedTesting/Gem/PythonTests/WhiteBox/CMakeLists.txt @@ -12,7 +12,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) TEST_SUITE main TEST_SERIAL PATH ${CMAKE_CURRENT_LIST_DIR}/TestSuite_Active.py - TIMEOUT 1500 RUNTIME_DEPENDENCIES Legacy::Editor AZ::AssetProcessor diff --git a/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/CMakeLists.txt index 0170d73af0..3d7a9204e2 100644 --- a/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/CMakeLists.txt +++ b/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/CMakeLists.txt @@ -92,17 +92,17 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) AZ::AssetProcessor ) - ly_add_pytest( - NAME AssetPipelineTests.AssetBundler - PATH ${CMAKE_CURRENT_LIST_DIR}/asset_bundler_batch_tests.py - EXCLUDE_TEST_RUN_TARGET_FROM_IDE - TEST_SERIAL - TIMEOUT 2400 - TEST_SUITE periodic - RUNTIME_DEPENDENCIES - AZ::AssetProcessor - AZ::AssetBundlerBatch - ) + # Issue #3017 + #ly_add_pytest( + # NAME AssetPipelineTests.AssetBundler + # PATH ${CMAKE_CURRENT_LIST_DIR}/asset_bundler_batch_tests.py + # EXCLUDE_TEST_RUN_TARGET_FROM_IDE + # TEST_SERIAL + # TEST_SUITE periodic + # RUNTIME_DEPENDENCIES + # AZ::AssetProcessor + # AZ::AssetBundlerBatch + #) ly_add_pytest( NAME AssetPipelineTests.AssetBundler_SandBox @@ -111,7 +111,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) PYTEST_MARKS "SUITE_sandbox" # run only sandbox tests in this file EXCLUDE_TEST_RUN_TARGET_FROM_IDE TEST_SERIAL - TIMEOUT 1500 RUNTIME_DEPENDENCIES AZ::AssetProcessor AZ::AssetBundlerBatch @@ -133,7 +132,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) PATH ${CMAKE_CURRENT_LIST_DIR}/missing_dependency_tests.py EXCLUDE_TEST_RUN_TARGET_FROM_IDE TEST_SERIAL - TIMEOUT 1500 TEST_SUITE periodic RUNTIME_DEPENDENCIES AZ::AssetProcessorBatch diff --git a/AutomatedTesting/Gem/PythonTests/editor/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/editor/CMakeLists.txt index afde0a0d94..fa35bb25c6 100644 --- a/AutomatedTesting/Gem/PythonTests/editor/CMakeLists.txt +++ b/AutomatedTesting/Gem/PythonTests/editor/CMakeLists.txt @@ -13,7 +13,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_ TEST_SERIAL PATH ${CMAKE_CURRENT_LIST_DIR} PYTEST_MARKS "SUITE_main and not REQUIRES_gpu" - TIMEOUT 1500 RUNTIME_DEPENDENCIES Legacy::Editor AZ::AssetProcessor @@ -28,7 +27,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_ TEST_SERIAL PATH ${CMAKE_CURRENT_LIST_DIR} PYTEST_MARKS "SUITE_periodic and not REQUIRES_gpu" - TIMEOUT 1500 RUNTIME_DEPENDENCIES Legacy::Editor AZ::AssetProcessor @@ -44,7 +42,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_ TEST_REQUIRES gpu PATH ${CMAKE_CURRENT_LIST_DIR} PYTEST_MARKS "SUITE_main and REQUIRES_gpu" - TIMEOUT 1500 RUNTIME_DEPENDENCIES Legacy::Editor AZ::AssetProcessor @@ -59,7 +56,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_ TEST_SERIAL PATH ${CMAKE_CURRENT_LIST_DIR} PYTEST_MARKS "SUITE_sandbox" - TIMEOUT 1500 RUNTIME_DEPENDENCIES Legacy::Editor AZ::AssetProcessor diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/largeworlds/CMakeLists.txt index 351ca19031..043485d869 100644 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/CMakeLists.txt +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/CMakeLists.txt @@ -16,7 +16,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_ TEST_SUITE main PATH ${CMAKE_CURRENT_LIST_DIR}/dyn_veg PYTEST_MARKS "not SUITE_sandbox and not SUITE_periodic and not SUITE_benchmark" - TIMEOUT 1500 RUNTIME_DEPENDENCIES AZ::AssetProcessor Legacy::Editor @@ -33,7 +32,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_ TEST_SUITE sandbox PATH ${CMAKE_CURRENT_LIST_DIR}/dyn_veg PYTEST_MARKS "SUITE_sandbox" - TIMEOUT 1500 RUNTIME_DEPENDENCIES AZ::AssetProcessor Legacy::Editor @@ -49,7 +47,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_ TEST_SUITE periodic PATH ${CMAKE_CURRENT_LIST_DIR}/dyn_veg PYTEST_MARKS "SUITE_periodic and dynveg_filter" - TIMEOUT 1500 RUNTIME_DEPENDENCIES AZ::AssetProcessor Legacy::Editor @@ -64,7 +61,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_ TEST_SUITE periodic PATH ${CMAKE_CURRENT_LIST_DIR}/dyn_veg PYTEST_MARKS "SUITE_periodic and dynveg_modifier" - TIMEOUT 1500 RUNTIME_DEPENDENCIES AZ::AssetProcessor Legacy::Editor @@ -79,7 +75,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_ TEST_SUITE periodic PATH ${CMAKE_CURRENT_LIST_DIR}/dyn_veg PYTEST_MARKS "SUITE_periodic and dynveg_regression" - TIMEOUT 1500 RUNTIME_DEPENDENCIES AZ::AssetProcessor Legacy::Editor @@ -94,7 +89,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_ TEST_SUITE periodic PATH ${CMAKE_CURRENT_LIST_DIR}/dyn_veg PYTEST_MARKS "SUITE_periodic and dynveg_area" - TIMEOUT 1500 RUNTIME_DEPENDENCIES AZ::AssetProcessor Legacy::Editor @@ -109,7 +103,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_ TEST_SUITE periodic PATH ${CMAKE_CURRENT_LIST_DIR}/dyn_veg PYTEST_MARKS "SUITE_periodic and dynveg_misc" - TIMEOUT 1500 RUNTIME_DEPENDENCIES AZ::AssetProcessor Legacy::Editor @@ -124,7 +117,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_ TEST_SUITE periodic PATH ${CMAKE_CURRENT_LIST_DIR}/dyn_veg PYTEST_MARKS "SUITE_periodic and dynveg_surfacetagemitter" - TIMEOUT 1500 RUNTIME_DEPENDENCIES AZ::AssetProcessor Legacy::Editor @@ -140,7 +132,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_ TEST_SUITE main PATH ${CMAKE_CURRENT_LIST_DIR}/landscape_canvas PYTEST_MARKS "not SUITE_sandbox and not SUITE_periodic and not SUITE_benchmark" - TIMEOUT 1500 RUNTIME_DEPENDENCIES AZ::AssetProcessor Legacy::Editor @@ -155,7 +146,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_ TEST_SUITE periodic PATH ${CMAKE_CURRENT_LIST_DIR}/landscape_canvas PYTEST_MARKS "SUITE_periodic" - TIMEOUT 1500 RUNTIME_DEPENDENCIES AZ::AssetProcessor Legacy::Editor @@ -170,7 +160,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_ TEST_SERIAL TEST_SUITE periodic PATH ${CMAKE_CURRENT_LIST_DIR}/gradient_signal - TIMEOUT 1500 RUNTIME_DEPENDENCIES AZ::AssetProcessor Legacy::Editor diff --git a/AutomatedTesting/Gem/PythonTests/physics/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/physics/CMakeLists.txt index 248bf3fdc5..eb37db1943 100644 --- a/AutomatedTesting/Gem/PythonTests/physics/CMakeLists.txt +++ b/AutomatedTesting/Gem/PythonTests/physics/CMakeLists.txt @@ -12,7 +12,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) TEST_SUITE main TEST_SERIAL PATH ${CMAKE_CURRENT_LIST_DIR}/TestSuite_Main.py - TIMEOUT 1500 RUNTIME_DEPENDENCIES Legacy::Editor AZ::AssetProcessor @@ -25,7 +24,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) TEST_SUITE periodic TEST_SERIAL PATH ${CMAKE_CURRENT_LIST_DIR}/TestSuite_Periodic.py - TIMEOUT 1500 RUNTIME_DEPENDENCIES Legacy::Editor AZ::AssetProcessor @@ -38,7 +36,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) TEST_SUITE sandbox TEST_SERIAL PATH ${CMAKE_CURRENT_LIST_DIR}/TestSuite_Sandbox.py - TIMEOUT 1500 RUNTIME_DEPENDENCIES Legacy::Editor AZ::AssetProcessor diff --git a/AutomatedTesting/Gem/PythonTests/prefab/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/prefab/CMakeLists.txt index 1d9c54fa40..48c24d1ebf 100644 --- a/AutomatedTesting/Gem/PythonTests/prefab/CMakeLists.txt +++ b/AutomatedTesting/Gem/PythonTests/prefab/CMakeLists.txt @@ -13,7 +13,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) TEST_SUITE main TEST_SERIAL PATH ${CMAKE_CURRENT_LIST_DIR}/TestSuite_Main.py - TIMEOUT 1500 RUNTIME_DEPENDENCIES Legacy::Editor AZ::AssetProcessor diff --git a/AutomatedTesting/Gem/PythonTests/scripting/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/scripting/CMakeLists.txt index 80b6e9a54e..25988216b2 100644 --- a/AutomatedTesting/Gem/PythonTests/scripting/CMakeLists.txt +++ b/AutomatedTesting/Gem/PythonTests/scripting/CMakeLists.txt @@ -12,7 +12,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) TEST_SUITE periodic TEST_SERIAL PATH ${CMAKE_CURRENT_LIST_DIR}/TestSuite_Periodic.py - TIMEOUT 1500 RUNTIME_DEPENDENCIES Legacy::Editor AZ::AssetProcessor @@ -25,7 +24,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) TEST_SUITE sandbox TEST_SERIAL PATH ${CMAKE_CURRENT_LIST_DIR}/TestSuite_Sandbox.py - TIMEOUT 1500 RUNTIME_DEPENDENCIES Legacy::Editor AZ::AssetProcessor diff --git a/AutomatedTesting/Gem/PythonTests/smoke/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/smoke/CMakeLists.txt index 2c1d03b5a2..3fc4f3db0e 100644 --- a/AutomatedTesting/Gem/PythonTests/smoke/CMakeLists.txt +++ b/AutomatedTesting/Gem/PythonTests/smoke/CMakeLists.txt @@ -18,7 +18,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) TEST_SERIAL PATH ${CMAKE_CURRENT_LIST_DIR} PYTEST_MARKS "SUITE_smoke" - TIMEOUT 1500 RUNTIME_DEPENDENCIES AZ::AssetProcessor AZ::PythonBindingsExample diff --git a/Gems/PhysX/Code/CMakeLists.txt b/Gems/PhysX/Code/CMakeLists.txt index a69019249f..80e8bee8e3 100644 --- a/Gems/PhysX/Code/CMakeLists.txt +++ b/Gems/PhysX/Code/CMakeLists.txt @@ -186,7 +186,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) ly_add_googlebenchmark( NAME Gem::PhysX.Benchmarks TARGET Gem::PhysX.Tests - TIMEOUT 1500 #25mins ) list(APPEND testTargets PhysX.Tests) diff --git a/cmake/LYTestWrappers.cmake b/cmake/LYTestWrappers.cmake index efb19a20dd..8e71cb3db1 100644 --- a/cmake/LYTestWrappers.cmake +++ b/cmake/LYTestWrappers.cmake @@ -114,7 +114,7 @@ function(ly_add_test) if(NOT ly_add_test_TIMEOUT) set(ly_add_test_TIMEOUT ${LY_TEST_DEFAULT_TIMEOUT}) elseif(ly_add_test_TIMEOUT GREATER LY_TEST_DEFAULT_TIMEOUT) - message(WARNING "TIMEOUT for test ${ly_add_test_NAME} set at ${ly_add_test_TIMEOUT} seconds which is longer than the default of ${LY_TEST_DEFAULT_TIMEOUT}. Allowing a single module to run exceedingly long creates problems in a CI pipeline.") + message(FATAL_ERROR "TIMEOUT for test ${ly_add_test_NAME} set at ${ly_add_test_TIMEOUT} seconds which is longer than the default of ${LY_TEST_DEFAULT_TIMEOUT}. Allowing a single module to run exceedingly long creates problems in a CI pipeline.") endif() if(NOT ly_add_test_TEST_COMMAND) From a70a106fd2e2f5b7b83739ab37355b06689afe33 Mon Sep 17 00:00:00 2001 From: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> Date: Tue, 10 Aug 2021 14:48:33 -0700 Subject: [PATCH 262/803] Test code to add merge detection on Settings Registry keys Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> --- .../AzCore/Component/ComponentApplication.cpp | 1 + .../AzCore/AzCore/Settings/SettingsRegistry.h | 44 ++++++++ .../AzCore/Settings/SettingsRegistryImpl.cpp | 49 +++++++++ .../AzCore/Settings/SettingsRegistryImpl.h | 9 ++ .../Settings/EditorSettingsOriginTracker.cpp | 103 ++++++++++++++++++ .../Settings/EditorSettingsOriginTracker.h | 39 +++++++ .../aztoolsframework_files.cmake | 2 + 7 files changed, 247 insertions(+) create mode 100644 Code/Framework/AzToolsFramework/AzToolsFramework/Editor/Settings/EditorSettingsOriginTracker.cpp create mode 100644 Code/Framework/AzToolsFramework/AzToolsFramework/Editor/Settings/EditorSettingsOriginTracker.h diff --git a/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp b/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp index c68fce6f4d..7b1060a10f 100644 --- a/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp +++ b/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp @@ -728,6 +728,7 @@ namespace AZ DestroyReflectionManager(); static_cast(m_settingsRegistry.get())->ClearNotifiers(); + static_cast(m_settingsRegistry.get())->ClearMergeEvents(); // Uninit and unload any dynamic modules. m_moduleManager->UnloadModules(); diff --git a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistry.h b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistry.h index 3bcf0ae89b..e27e4452ee 100644 --- a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistry.h +++ b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistry.h @@ -123,6 +123,36 @@ namespace AZ using NotifyEvent = AZ::Event; using NotifyEventHandler = typename NotifyEvent::Handler; + using PreMergeEventCallback = AZStd::function; + using PostMergeEventCallback = AZStd::function; + using PreMergeEvent = AZ::Event; + using PostMergeEvent = AZ::Event; + using PreMergeEventHandler = typename PreMergeEvent::Handler; + using PostMergeEventHandler = typename PostMergeEvent::Handler; + + struct ScopedMergeEvent + { + ScopedMergeEvent( + PreMergeEvent& preMergeEvent, PostMergeEvent& postMergeEvent, AZStd::string_view filePath, AZStd::string_view rootKey) + : m_preMergeEvent{ preMergeEvent } + , m_postMergeEvent{ postMergeEvent } + , m_filePath{ filePath } + , m_rootKey{ rootKey } + { + preMergeEvent.Signal(m_filePath, m_rootKey); + } + + ~ScopedMergeEvent() + { + m_postMergeEvent.Signal(m_filePath, m_rootKey); + } + + PreMergeEvent& m_preMergeEvent; + PostMergeEvent& m_postMergeEvent; + AZStd::string_view m_filePath; + AZStd::string_view m_rootKey; + }; + using VisitorCallback = AZStd::function; //! Base class for the visitor class during traversal over the Settings Registry. The type-agnostic function is always @@ -169,6 +199,20 @@ namespace AZ //! @callback The function to call when an entry gets a new/updated value. [[nodiscard]] virtual NotifyEventHandler RegisterNotifier(NotifyCallback&& callback) = 0; + //! Register a callback that will be called before an entry is merged. + //! @callback The function to call when an entry gets a new/updated value. + [[nodiscard]] virtual PreMergeEventHandler RegisterPreMergeEvent(const PreMergeEventCallback& callback) = 0; + //! Register a callback that will be called before an entry is merged. + //! @callback The function to call when an entry gets a new/updated value. + [[nodiscard]] virtual PreMergeEventHandler RegisterPreMergeEvent (PreMergeEventCallback&& callback) = 0; + + //! Register a callback that will be called after an entry is merged. + //! @callback The function to call when an entry gets a new/updated value. + [[nodiscard]] virtual PostMergeEventHandler RegisterPostMergeEvent(const PostMergeEventCallback& callback) = 0; + //! Register a callback that will be called after an entry is merged. + //! @callback The function to call when an entry gets a new/updated value. + [[nodiscard]] virtual PostMergeEventHandler RegisterPostMergeEvent (PostMergeEventCallback&& callback) = 0; + //! Gets the boolean value at the provided path. //! @param result The target to write the result to. //! @param path The path to the value. diff --git a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryImpl.cpp b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryImpl.cpp index 0882e1b7f2..4a7b4183f3 100644 --- a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryImpl.cpp +++ b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryImpl.cpp @@ -229,6 +229,53 @@ namespace AZ m_notifiers.DisconnectAllHandlers(); } + auto SettingsRegistryImpl::RegisterPreMergeEvent(const PreMergeEventCallback& callback) -> PreMergeEventHandler + { + PreMergeEventHandler preMergeHandler{ callback }; + { + AZStd::scoped_lock lock(m_settingMutex); + preMergeHandler.Connect(m_preMergeEvent); + } + return preMergeHandler; + } + + auto SettingsRegistryImpl::RegisterPreMergeEvent(PreMergeEventCallback&& callback) -> PreMergeEventHandler + { + PreMergeEventHandler preMergeHandler{ AZStd::move(callback) }; + { + AZStd::scoped_lock lock(m_settingMutex); + preMergeHandler.Connect(m_preMergeEvent); + } + return preMergeHandler; + } + + auto SettingsRegistryImpl::RegisterPostMergeEvent(const PostMergeEventCallback& callback) -> PostMergeEventHandler + { + PostMergeEventHandler postMergeHandler{ callback }; + { + AZStd::scoped_lock lock(m_settingMutex); + postMergeHandler.Connect(m_postMergeEvent); + } + return postMergeHandler; + } + + auto SettingsRegistryImpl::RegisterPostMergeEvent(PostMergeEventCallback&& callback) -> PostMergeEventHandler + { + PostMergeEventHandler postMergeHandler{ AZStd::move(callback) }; + { + AZStd::scoped_lock lock(m_settingMutex); + postMergeHandler.Connect(m_postMergeEvent); + } + return postMergeHandler; + } + + void SettingsRegistryImpl::ClearMergeEvents() + { + AZStd::scoped_lock lock(m_settingMutex); + m_preMergeEvent.DisconnectAllHandlers(); + m_postMergeEvent.DisconnectAllHandlers(); + } + SettingsRegistryInterface::Type SettingsRegistryImpl::GetType(AZStd::string_view path) const { if (path.empty()) @@ -1115,6 +1162,8 @@ namespace AZ return false; } + ScopedMergeEvent(m_preMergeEvent, m_postMergeEvent, path, rootKey); + JsonSerializationResult::ResultCode mergeResult(JsonSerializationResult::Tasks::Merge); if (rootKey.empty()) { diff --git a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryImpl.h b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryImpl.h index 41a628cf22..babcafe701 100644 --- a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryImpl.h +++ b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryImpl.h @@ -48,6 +48,12 @@ namespace AZ [[nodiscard]] NotifyEventHandler RegisterNotifier(NotifyCallback&& callback) override; void ClearNotifiers(); + [[nodiscard]] PreMergeEventHandler RegisterPreMergeEvent(const PreMergeEventCallback& callback) override; + [[nodiscard]] PreMergeEventHandler RegisterPreMergeEvent(PreMergeEventCallback&& callback) override; + [[nodiscard]] PostMergeEventHandler RegisterPostMergeEvent(const PostMergeEventCallback& callback) override; + [[nodiscard]] PostMergeEventHandler RegisterPostMergeEvent(PostMergeEventCallback&& callback) override; + void ClearMergeEvents(); + bool Get(bool& result, AZStd::string_view path) const override; bool Get(s64& result, AZStd::string_view path) const override; bool Get(u64& result, AZStd::string_view path) const override; @@ -103,6 +109,9 @@ namespace AZ mutable AZStd::recursive_mutex m_settingMutex; NotifyEvent m_notifiers; + PreMergeEvent m_preMergeEvent; + PostMergeEvent m_postMergeEvent; + rapidjson::Document m_settings; JsonSerializerSettings m_serializationSettings; JsonDeserializerSettings m_deserializationSettings; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/Settings/EditorSettingsOriginTracker.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/Settings/EditorSettingsOriginTracker.cpp new file mode 100644 index 0000000000..13a0610f5c --- /dev/null +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/Settings/EditorSettingsOriginTracker.cpp @@ -0,0 +1,103 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include + +#include +#include + +namespace AzToolsFramework +{ + EditorPreferencesSettingsOriginTracker::SettingsNotificationHandler::SettingsNotificationHandler( + AZ::SettingsRegistryInterface& registry) + : m_settingsRegistry(registry) + { + AZ::JsonApplyPatchSettings applyPatchSettings; + m_settingsRegistry.GetApplyPatchSettings(applyPatchSettings); + // Wrap any existing callbacks into the reporting callback, so that both this struct + // reporting callbacks and the existing callbacks can be invoked + m_prevReportingCallback = applyPatchSettings.m_reporting; + applyPatchSettings.m_reporting = [this]( + AZStd::string_view message, AZ::JsonSerializationResult::ResultCode result, + AZStd::string_view path) -> AZ::JsonSerializationResult::ResultCode + { + m_prevReportingCallback(message, result, path); + (*this)(message, result, path); + return result; + }; + m_settingsRegistry.SetApplyPatchSettings(applyPatchSettings); + } + + EditorPreferencesSettingsOriginTracker::SettingsNotificationHandler::~SettingsNotificationHandler() + { + // Restore previous reporting callback + AZ::JsonApplyPatchSettings applyPatchSettings; + m_settingsRegistry.GetApplyPatchSettings(applyPatchSettings); + applyPatchSettings.m_reporting = m_prevReportingCallback; + m_settingsRegistry.SetApplyPatchSettings(applyPatchSettings); + } + + // Use the Json Serialization Issue Callback system + // to determine when a merge option modifies a value + AZ::JsonSerializationResult::ResultCode EditorPreferencesSettingsOriginTracker::SettingsNotificationHandler::operator()( + AZStd::string_view /*message*/, AZ::JsonSerializationResult::ResultCode result, AZStd::string_view path) + { + using FixedValueString = AZ::SettingsRegistryInterface::FixedValueString; + + AZ::IO::PathView preferencesRootKey{ "/Amazon/Preferences", AZ::IO::PosixPathSeparator }; + AZ::IO::PathView inputKey{ path, AZ::IO::PosixPathSeparator }; + + // Delegate to the Notifier Handler callable below + if (result.GetTask() == AZ::JsonSerializationResult::Tasks::Merge && + result.GetProcessing() == AZ::JsonSerializationResult::Processing::Completed && inputKey.IsRelativeTo(preferencesRootKey)) + { + if (auto type = m_settingsRegistry.GetType(path); type != AZ::SettingsRegistryInterface::Type::NoType) + { + operator()(path, type); + } + } + + return result; + } + + void EditorPreferencesSettingsOriginTracker::SettingsNotificationHandler::operator()( + AZStd::string_view path, AZ::SettingsRegistryInterface::Type /*type*/) + { + constexpr AZ::IO::PathView preferencesRootKey{ "/Amazon/Preferences", AZ::IO::PosixPathSeparator }; + AZ::IO::PathView inputKey{ path, AZ::IO::PosixPathSeparator }; + if (inputKey.IsRelativeTo(preferencesRootKey)) + { + // Do stuff with key + } + } + + EditorPreferencesSettingsOriginTracker::EditorPreferencesSettingsOriginTracker(AZ::SettingsRegistryInterface& registry) + : m_settingsRegistry(registry) + { + auto PreMergeEvent = [this](AZStd::string_view filePath, AZStd::string_view /*rootKey*/) + { + AZ::IO::FixedMaxPath editorPreferencesPath = AZ::Utils::GetProjectPath(); + editorPreferencesPath = editorPreferencesPath / "user" / "Registry" / "editorpreferences.setreg"; + + if (AZ::IO::PathView(filePath) == editorPreferencesPath) + { + m_notifyHandler = m_settingsRegistry.RegisterNotifier(SettingsNotificationHandler(m_settingsRegistry)); + } + }; + + auto PostMergeEvent = [this](AZStd::string_view /*filePath*/, AZStd::string_view /*rootKey*/) + { + // Clear the notification handler so that it goes out of scope + // and this tracker instance no handles settings updates + m_notifyHandler = {}; + }; + + m_preMergeEventHandler = m_settingsRegistry.RegisterPreMergeEvent(PreMergeEvent); + m_postMergeEventHandler = m_settingsRegistry.RegisterPostMergeEvent(PostMergeEvent); + } +} diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/Settings/EditorSettingsOriginTracker.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/Settings/EditorSettingsOriginTracker.h new file mode 100644 index 0000000000..63249a8ecd --- /dev/null +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/Settings/EditorSettingsOriginTracker.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include +#include + +namespace AzToolsFramework +{ + struct EditorPreferencesSettingsOriginTracker + { + explicit EditorPreferencesSettingsOriginTracker(AZ::SettingsRegistryInterface& registry); + + struct SettingsNotificationHandler + { + SettingsNotificationHandler(AZ::SettingsRegistryInterface& registry); + ~SettingsNotificationHandler(); + + AZ::JsonSerializationResult::ResultCode operator()( + AZStd::string_view message, AZ::JsonSerializationResult::ResultCode result, AZStd::string_view path); + void operator()(AZStd::string_view path, AZ::SettingsRegistryInterface::Type type); + + private: + AZ::SettingsRegistryInterface& m_settingsRegistry; + AZ::JsonSerializationResult::JsonIssueCallback m_prevReportingCallback; + }; + + private: + AZ::SettingsRegistryInterface& m_settingsRegistry; + AZ::SettingsRegistryInterface::PreMergeEventHandler m_preMergeEventHandler; + AZ::SettingsRegistryInterface::PostMergeEventHandler m_postMergeEventHandler; + AZ::SettingsRegistryInterface::NotifyEventHandler m_notifyHandler; + }; +} // namespace AZ diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake b/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake index 53173f83af..6e7446d74d 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake @@ -113,6 +113,8 @@ set(FILES Component/EditorLevelComponentAPIComponent.h Editor/EditorContextMenuBus.h Editor/EditorSettingsAPIBus.h + Editor/Settings/EditorSettingsOriginTracker.cpp + Editor/Settings/EditorSettingsOriginTracker.h Entity/EditorEntityStartStatus.h Entity/EditorEntityAPIBus.h Entity/EditorEntityContextComponent.cpp From 6f6b88ec2f785ff3ef8c2e56b6c4134df54d345a Mon Sep 17 00:00:00 2001 From: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> Date: Tue, 10 Aug 2021 15:27:01 -0700 Subject: [PATCH 263/803] Rename EditorSettingsOriginTracker Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> --- .../Editor/Settings/EditorSettingsOriginTracker.cpp | 10 +++++----- .../Editor/Settings/EditorSettingsOriginTracker.h | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/Settings/EditorSettingsOriginTracker.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/Settings/EditorSettingsOriginTracker.cpp index 13a0610f5c..bdeb4e41b4 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/Settings/EditorSettingsOriginTracker.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/Settings/EditorSettingsOriginTracker.cpp @@ -13,7 +13,7 @@ namespace AzToolsFramework { - EditorPreferencesSettingsOriginTracker::SettingsNotificationHandler::SettingsNotificationHandler( + EditorSettingsOriginTracker::SettingsNotificationHandler::SettingsNotificationHandler( AZ::SettingsRegistryInterface& registry) : m_settingsRegistry(registry) { @@ -33,7 +33,7 @@ namespace AzToolsFramework m_settingsRegistry.SetApplyPatchSettings(applyPatchSettings); } - EditorPreferencesSettingsOriginTracker::SettingsNotificationHandler::~SettingsNotificationHandler() + EditorSettingsOriginTracker::SettingsNotificationHandler::~SettingsNotificationHandler() { // Restore previous reporting callback AZ::JsonApplyPatchSettings applyPatchSettings; @@ -44,7 +44,7 @@ namespace AzToolsFramework // Use the Json Serialization Issue Callback system // to determine when a merge option modifies a value - AZ::JsonSerializationResult::ResultCode EditorPreferencesSettingsOriginTracker::SettingsNotificationHandler::operator()( + AZ::JsonSerializationResult::ResultCode EditorSettingsOriginTracker::SettingsNotificationHandler::operator()( AZStd::string_view /*message*/, AZ::JsonSerializationResult::ResultCode result, AZStd::string_view path) { using FixedValueString = AZ::SettingsRegistryInterface::FixedValueString; @@ -65,7 +65,7 @@ namespace AzToolsFramework return result; } - void EditorPreferencesSettingsOriginTracker::SettingsNotificationHandler::operator()( + void EditorSettingsOriginTracker::SettingsNotificationHandler::operator()( AZStd::string_view path, AZ::SettingsRegistryInterface::Type /*type*/) { constexpr AZ::IO::PathView preferencesRootKey{ "/Amazon/Preferences", AZ::IO::PosixPathSeparator }; @@ -76,7 +76,7 @@ namespace AzToolsFramework } } - EditorPreferencesSettingsOriginTracker::EditorPreferencesSettingsOriginTracker(AZ::SettingsRegistryInterface& registry) + EditorSettingsOriginTracker::EditorSettingsOriginTracker(AZ::SettingsRegistryInterface& registry) : m_settingsRegistry(registry) { auto PreMergeEvent = [this](AZStd::string_view filePath, AZStd::string_view /*rootKey*/) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/Settings/EditorSettingsOriginTracker.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/Settings/EditorSettingsOriginTracker.h index 63249a8ecd..3ef3f141a2 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/Settings/EditorSettingsOriginTracker.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/Settings/EditorSettingsOriginTracker.h @@ -12,9 +12,9 @@ namespace AzToolsFramework { - struct EditorPreferencesSettingsOriginTracker + struct EditorSettingsOriginTracker { - explicit EditorPreferencesSettingsOriginTracker(AZ::SettingsRegistryInterface& registry); + explicit EditorSettingsOriginTracker(AZ::SettingsRegistryInterface& registry); struct SettingsNotificationHandler { From 88762b2b69992b6d28e37e94a163cf7e4691040c Mon Sep 17 00:00:00 2001 From: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> Date: Tue, 10 Aug 2021 15:33:24 -0700 Subject: [PATCH 264/803] Add #pragma once to EditorSettingsOriginTracker to make it build :) Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> --- .../Editor/Settings/EditorSettingsOriginTracker.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/Settings/EditorSettingsOriginTracker.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/Settings/EditorSettingsOriginTracker.h index 3ef3f141a2..fbfdc1af25 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/Settings/EditorSettingsOriginTracker.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/Settings/EditorSettingsOriginTracker.h @@ -6,6 +6,8 @@ * */ +#pragma once + #include #include #include From d71674579a372c17af98f522f5b96949f2495667 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Tue, 10 Aug 2021 16:22:03 -0700 Subject: [PATCH 265/803] fixing startup on game launcher Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Legacy/CryCommon/platform_impl.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Code/Legacy/CryCommon/platform_impl.cpp b/Code/Legacy/CryCommon/platform_impl.cpp index 3d7b2180fc..3d23d8783e 100644 --- a/Code/Legacy/CryCommon/platform_impl.cpp +++ b/Code/Legacy/CryCommon/platform_impl.cpp @@ -290,14 +290,14 @@ void InitRootDir(char szExeFileName[], uint nExeSize, char szExeRootName[], uint // Check if the engineroot exists azstrcat(szPath, AZ_ARRAY_SIZE(szPath), "\\engine.json"); WIN32_FILE_ATTRIBUTE_DATA data; - AZStd::wstring szPathW; - AZStd::to_wstring(szPathW, szPath); - BOOL res = GetFileAttributesExW(szPathW.c_str(), GetFileExInfoStandard, &data); + wchar_t szPathW[_MAX_PATH]; + AZStd::to_wstring(szPathW, _MAX_PATH, szPath); + BOOL res = GetFileAttributesExW(szPathW, GetFileExInfoStandard, &data); if (res != 0 && data.dwFileAttributes != INVALID_FILE_ATTRIBUTES) { // Found file szPath[n] = 0; - SetCurrentDirectoryW(szPathW.c_str()); + SetCurrentDirectoryW(szPathW); break; } } From cfa6e259f3bc5ddeb690afb6e74f6aa27b25062c Mon Sep 17 00:00:00 2001 From: Jeremy Ong Date: Tue, 10 Aug 2021 17:24:07 -0600 Subject: [PATCH 266/803] Hide RenderDoc integration behind LY_RENDERDOC_ENABLED option Signed-off-by: Jeremy Ong --- Gems/Atom/RHI/Code/CMakeLists.txt | 8 +++----- Gems/Atom/RHI/Code/Platform/Linux/renderdoc_linux.cmake | 7 ------- .../RHI/Code/Platform/Windows/renderdoc_windows.cmake | 9 +-------- 3 files changed, 4 insertions(+), 20 deletions(-) diff --git a/Gems/Atom/RHI/Code/CMakeLists.txt b/Gems/Atom/RHI/Code/CMakeLists.txt index eeb8f73bac..343736ff7c 100644 --- a/Gems/Atom/RHI/Code/CMakeLists.txt +++ b/Gems/Atom/RHI/Code/CMakeLists.txt @@ -11,20 +11,19 @@ ly_get_list_relative_pal_filename(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Sourc include(${pal_dir}/AtomRHITests_traits_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) +set(LY_RENDERDOC_ENABLED OFF CACHE BOOL "Enable RenderDoc integration.") set(RENDERDOC_CMAKE ${CMAKE_CURRENT_SOURCE_DIR}/${pal_dir}/renderdoc_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) if(EXISTS ${RENDERDOC_CMAKE}) include(${RENDERDOC_CMAKE}) endif() -if(TARGET "3rdParty::renderdoc") +if(LY_RENDERDOC_ENABLED AND TARGET "3rdParty::renderdoc") message(STATUS "Renderdoc found, adding as runtime dependency") set(USE_RENDERDOC_DEFINE "USE_RENDERDOC") set(RENDERDOC_BUILD_DEPENDENCY "3rdParty::renderdoc") - set(RENDERDOC_API_DEPENDENCY "3rdParty::renderdoc_api") else() set(USE_RENDERDOC_DEFINE "") set(RENDERDOC_BUILD_DEPENDENCY "") - set(RENDERDOC_API_DEPENDENCY "") endif() ly_add_target( @@ -62,9 +61,8 @@ ly_add_target( AZ::AzCore AZ::AzFramework Gem::Atom_RHI.Reflect - ${RENDERDOC_BUILD_DEPENDENCY} PUBLIC - ${RENDERDOC_API_DEPENDENCY} + ${RENDERDOC_BUILD_DEPENDENCY} COMPILE_DEFINITIONS PUBLIC ${USE_RENDERDOC_DEFINE} diff --git a/Gems/Atom/RHI/Code/Platform/Linux/renderdoc_linux.cmake b/Gems/Atom/RHI/Code/Platform/Linux/renderdoc_linux.cmake index 0faccf80ec..222a3d5768 100644 --- a/Gems/Atom/RHI/Code/Platform/Linux/renderdoc_linux.cmake +++ b/Gems/Atom/RHI/Code/Platform/Linux/renderdoc_linux.cmake @@ -24,13 +24,6 @@ if(NOT LY_MONOLITHIC_GAME) INCLUDE_DIRECTORIES "." RUNTIME_DEPENDENCIES "${RENDERDOC_PATH}/librenderdoc.so" ) - - ly_add_external_target( - NAME renderdoc_api - VERSION - 3RDPARTY_ROOT_DIRECTORY ${RENDERDOC_PATH} - INCLUDE_DIRECTORIES "." - ) endif() endif() endif() \ No newline at end of file diff --git a/Gems/Atom/RHI/Code/Platform/Windows/renderdoc_windows.cmake b/Gems/Atom/RHI/Code/Platform/Windows/renderdoc_windows.cmake index 499321b2ab..90c44bcb7c 100644 --- a/Gems/Atom/RHI/Code/Platform/Windows/renderdoc_windows.cmake +++ b/Gems/Atom/RHI/Code/Platform/Windows/renderdoc_windows.cmake @@ -9,7 +9,7 @@ # Prevent bundling the renderdoc dll with a packaged title if(NOT LY_MONOLITHIC_GAME) # Common installation path for renderdoc path - set(RENDERDOC_PATH "C:/Program Files/RenderDoc") + set(RENDERDOC_PATH "$ENV{PROGRAMFILES}/RenderDoc") if(DEFINED ENV{"ATOM_RENDERDOC_PATH"}) set(RENDERDOC_PATH ENV{"ATOM_RENDERDOC_PATH"}) endif() @@ -26,13 +26,6 @@ if(NOT LY_MONOLITHIC_GAME) INCLUDE_DIRECTORIES "." RUNTIME_DEPENDENCIES "${RENDERDOC_PATH}/renderdoc.dll" ) - - ly_add_external_target( - NAME renderdoc_api - VERSION - 3RDPARTY_ROOT_DIRECTORY ${RENDERDOC_PATH} - INCLUDE_DIRECTORIES "." - ) endif() endif() endif() \ No newline at end of file From 25844a9ed6cff59d07e6cce1bdc63f01da6a8412 Mon Sep 17 00:00:00 2001 From: AMZN-mnaumov <82239319+AMZN-mnaumov@users.noreply.github.com> Date: Tue, 10 Aug 2021 16:40:51 -0700 Subject: [PATCH 267/803] Selecting entities when duplicating prefabs (#2995) * Selecting entitie when duplicating prefabs Signed-off-by: mnaumov * PR feedback Signed-off-by: mnaumov --- .../AzToolsFramework/Prefab/PrefabPublicHandler.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp index 69efe33d72..bb394720c9 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp @@ -1727,6 +1727,7 @@ namespace AzToolsFramework AliasPath absoluteInstancePath = commonOwningInstance.GetAbsoluteInstanceAliasPath(); absoluteInstancePath.Append(newInstanceAlias); + absoluteInstancePath.Append(PrefabDomUtils::ContainerEntityName); AZ::EntityId newEntityId = InstanceEntityIdMapper::GenerateEntityIdForAliasPath(absoluteInstancePath); duplicatedEntityIds.push_back(newEntityId); From c0ed0a792520cd98bf6f2443eea8dbb1f24e1fff Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Tue, 10 Aug 2021 16:59:21 -0700 Subject: [PATCH 268/803] Added more tool tip data to repeater. Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- .../Core/RepeaterNodeable.ScriptCanvasNodeable.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/RepeaterNodeable.ScriptCanvasNodeable.xml b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/RepeaterNodeable.ScriptCanvasNodeable.xml index 14634ff959..951a30ceb1 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/RepeaterNodeable.ScriptCanvasNodeable.xml +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/RepeaterNodeable.ScriptCanvasNodeable.xml @@ -10,17 +10,17 @@ Category="Nodeables" GeneratePropertyFriend="True" Namespace="ScriptCanvas" - Description="Repeats the output signal the given number of times using the specified delay to space the signals out"> + Description="Repeats the output signal the given number of times using the specified delay to space the signals out."> - + - + From 4cee263033090c4464607eb53f198ab3db8c54e3 Mon Sep 17 00:00:00 2001 From: Artur K <96597+nemerle@users.noreply.github.com> Date: Wed, 11 Aug 2021 02:07:01 +0200 Subject: [PATCH 269/803] Minimal TypeInfo header/reduce std interdependencies. (#2688) * Minimal TypeInfo header/reduce std interdependencies. TypeInfoSimple.h is a small header that can replace the use of TypeInfo.h in some cases. Signed-off-by: Nemerle * Windows build fixed Removed algorithm.h from string_view.h smoke-test passed Signed-off-by: nemerle <96597+nemerle@users.noreply.github.com> * Resotore dynamic_pointer_cast in intrusive_ptr Requested by reviewer. Signed-off-by: nemerle <96597+nemerle@users.noreply.github.com> * Fix CI build string.h - missed alogorithm.h, since it was removed from string_view NodeWrapper.h - missing smart_ptr.h Signed-off-by: nemerle <96597+nemerle@users.noreply.github.com> Co-authored-by: Nemerle --- .../EditorCommon/DrawingPrimitives/Ruler.cpp | 1 + .../std/containers/fixed_vector_set.h | 1 + .../AzCore/AzCore/Component/ComponentExport.h | 2 +- .../AzCore/AzCore/Component/EntityId.h | 2 +- .../AzCore/AzCore/Debug/IEventLogger.h | 2 +- .../AzCore/AzCore/EBus/OrderedEvent.inl | 1 + Code/Framework/AzCore/AzCore/IO/Path/Path.h | 1 + .../AzCore/AzCore/Interface/Interface.h | 1 + Code/Framework/AzCore/AzCore/Math/Crc.h | 4 +- .../AzCore/AzCore/Math/PackedVector3.h | 1 + Code/Framework/AzCore/AzCore/Math/Random.h | 4 +- Code/Framework/AzCore/AzCore/Math/Vector2.h | 2 +- Code/Framework/AzCore/AzCore/Math/Vector3.h | 2 +- Code/Framework/AzCore/AzCore/RTTI/TypeInfo.h | 36 +----------------- .../AzCore/AzCore/RTTI/TypeInfoSimple.h | 38 +++++++++++++++++++ .../AzCore/AzCore/Serialization/DataOverlay.h | 2 +- .../Serialization/Json/ArraySerializer.h | 2 +- .../Serialization/Json/DoubleSerializer.h | 2 +- .../AzCore/Serialization/Json/IntSerializer.h | 2 +- .../AzCore/AzCore/azcore_files.cmake | 1 + Code/Framework/AzCore/AzCore/std/allocator.h | 2 +- .../AzCore/AzCore/std/allocator_traits.h | 1 + .../AzCore/AzCore/std/chrono/types.h | 1 - .../AzCore/AzCore/std/containers/deque.h | 4 +- .../AzCore/AzCore/std/containers/list.h | 3 +- .../AzCore/std/containers/ring_buffer.h | 1 - .../AzCore/AzCore/std/containers/vector.h | 7 +--- .../AzCore/AzCore/std/createdestroy.h | 1 + .../AzCore/std/function/function_base.h | 1 + .../AzCore/std/function/function_template.h | 1 + Code/Framework/AzCore/AzCore/std/hash_table.h | 1 - Code/Framework/AzCore/AzCore/std/iterator.h | 3 +- .../AzCore/AzCore/std/parallel/atomic.h | 2 - .../AzCore/std/smart_ptr/intrusive_ptr.h | 24 +++++------- .../AzCore/AzCore/std/string/string.h | 1 + .../AzCore/AzCore/std/string/string_view.h | 15 +++++--- .../AzCore/std/typetraits/conjunction.h | 1 + .../AzCore/std/typetraits/static_storage.h | 3 +- Code/Framework/AzCore/AzCore/std/utils.h | 2 +- .../IO/Streamer/StreamerContext_Default.h | 1 + .../AzCore/Debug/StackTracer_Windows.cpp | 1 + .../Framework/AzCore/Tests/AZStd/SmartPtr.cpp | 5 ++- .../AzFramework/Archive/IArchive.h | 1 + .../AzFramework/Asset/CfgFileAsset.h | 2 +- .../Physics/Collision/CollisionGroups.h | 2 +- .../Physics/Collision/CollisionLayers.h | 2 +- .../Configuration/CollisionConfiguration.h | 2 +- .../Configuration/SceneConfiguration.h | 2 +- .../Slice/SliceInstantiationTicket.h | 2 +- .../AzFramework/Viewport/CameraState.h | 5 +++ .../AzFramework/Viewport/ScreenGeometry.h | 3 +- .../AzNetworking/PacketLayer/IPacket.h | 2 +- .../AzToolsFramework/API/ViewPaneOptions.h | 2 +- .../AzToolsFramework/Asset/AssetDebugInfo.h | 2 +- .../AzToolsFramework/Viewport/ViewportTypes.h | 1 + Code/Legacy/CryCommon/LyShine/UiAssetTypes.h | 2 +- .../native/ui/AssetTreeFilterModel.h | 1 + .../native/ui/SourceAssetDetailsPanel.h | 1 + Code/Tools/SceneAPI/SDKWrapper/NodeWrapper.h | 1 + .../SceneCore/Utilities/DebugOutput.h | 1 + .../Include/Private/ClientConfiguration.h | 1 + .../MaterialFunctorSourceDataRegistration.h | 1 + .../Code/Editor/Utilities/RecentFiles.cpp | 1 + 63 files changed, 129 insertions(+), 96 deletions(-) create mode 100644 Code/Framework/AzCore/AzCore/RTTI/TypeInfoSimple.h diff --git a/Code/Editor/Plugins/EditorCommon/DrawingPrimitives/Ruler.cpp b/Code/Editor/Plugins/EditorCommon/DrawingPrimitives/Ruler.cpp index 866a8206d6..1f0bd9ad88 100644 --- a/Code/Editor/Plugins/EditorCommon/DrawingPrimitives/Ruler.cpp +++ b/Code/Editor/Plugins/EditorCommon/DrawingPrimitives/Ruler.cpp @@ -12,6 +12,7 @@ #include #include #include +#include namespace DrawingPrimitives { diff --git a/Code/Framework/AtomCore/AtomCore/std/containers/fixed_vector_set.h b/Code/Framework/AtomCore/AtomCore/std/containers/fixed_vector_set.h index 1d5c9c2edd..c014f4b44e 100644 --- a/Code/Framework/AtomCore/AtomCore/std/containers/fixed_vector_set.h +++ b/Code/Framework/AtomCore/AtomCore/std/containers/fixed_vector_set.h @@ -8,6 +8,7 @@ #pragma once #include +#include namespace AZStd { diff --git a/Code/Framework/AzCore/AzCore/Component/ComponentExport.h b/Code/Framework/AzCore/AzCore/Component/ComponentExport.h index c31c739160..0b3f9ea617 100644 --- a/Code/Framework/AzCore/AzCore/Component/ComponentExport.h +++ b/Code/Framework/AzCore/AzCore/Component/ComponentExport.h @@ -9,7 +9,7 @@ #pragma once #include -#include +#include #include diff --git a/Code/Framework/AzCore/AzCore/Component/EntityId.h b/Code/Framework/AzCore/AzCore/Component/EntityId.h index 8e00cc70a9..e95813b388 100644 --- a/Code/Framework/AzCore/AzCore/Component/EntityId.h +++ b/Code/Framework/AzCore/AzCore/Component/EntityId.h @@ -9,7 +9,7 @@ #define AZCORE_ENTITY_ID_H #include -#include +#include #include /** @file diff --git a/Code/Framework/AzCore/AzCore/Debug/IEventLogger.h b/Code/Framework/AzCore/AzCore/Debug/IEventLogger.h index f04199e923..a11b411ded 100644 --- a/Code/Framework/AzCore/AzCore/Debug/IEventLogger.h +++ b/Code/Framework/AzCore/AzCore/Debug/IEventLogger.h @@ -10,7 +10,7 @@ #include #include -#include +#include #include #include diff --git a/Code/Framework/AzCore/AzCore/EBus/OrderedEvent.inl b/Code/Framework/AzCore/AzCore/EBus/OrderedEvent.inl index 7c2e92d25b..aa3ac7d5ef 100644 --- a/Code/Framework/AzCore/AzCore/EBus/OrderedEvent.inl +++ b/Code/Framework/AzCore/AzCore/EBus/OrderedEvent.inl @@ -7,6 +7,7 @@ */ #pragma once +#include namespace AZ { diff --git a/Code/Framework/AzCore/AzCore/IO/Path/Path.h b/Code/Framework/AzCore/AzCore/IO/Path/Path.h index 6f7e995a74..36640e821d 100644 --- a/Code/Framework/AzCore/AzCore/IO/Path/Path.h +++ b/Code/Framework/AzCore/AzCore/IO/Path/Path.h @@ -9,6 +9,7 @@ #pragma once #include +#include #include #include diff --git a/Code/Framework/AzCore/AzCore/Interface/Interface.h b/Code/Framework/AzCore/AzCore/Interface/Interface.h index 8131f5b08f..8664e2905f 100644 --- a/Code/Framework/AzCore/AzCore/Interface/Interface.h +++ b/Code/Framework/AzCore/AzCore/Interface/Interface.h @@ -9,6 +9,7 @@ #pragma once #include +#include #include #include #include diff --git a/Code/Framework/AzCore/AzCore/Math/Crc.h b/Code/Framework/AzCore/AzCore/Math/Crc.h index e8e8414f72..9ba2a83139 100644 --- a/Code/Framework/AzCore/AzCore/Math/Crc.h +++ b/Code/Framework/AzCore/AzCore/Math/Crc.h @@ -8,7 +8,7 @@ #pragma once #include - +#include #include ////////////////////////////////////////////////////////////////////////// @@ -108,7 +108,7 @@ namespace AZ namespace AZStd { - template<> + template<> struct hash { size_t operator()(const AZ::Crc32& id) const diff --git a/Code/Framework/AzCore/AzCore/Math/PackedVector3.h b/Code/Framework/AzCore/AzCore/Math/PackedVector3.h index 88108350c8..9a9acacdf3 100644 --- a/Code/Framework/AzCore/AzCore/Math/PackedVector3.h +++ b/Code/Framework/AzCore/AzCore/Math/PackedVector3.h @@ -8,6 +8,7 @@ #pragma once #include +#include namespace AZ { diff --git a/Code/Framework/AzCore/AzCore/Math/Random.h b/Code/Framework/AzCore/AzCore/Math/Random.h index 3c87824b1d..4912d9ad29 100644 --- a/Code/Framework/AzCore/AzCore/Math/Random.h +++ b/Code/Framework/AzCore/AzCore/Math/Random.h @@ -9,8 +9,10 @@ #pragma once #include -#include +#include #include +#include +#include namespace AZ { diff --git a/Code/Framework/AzCore/AzCore/Math/Vector2.h b/Code/Framework/AzCore/AzCore/Math/Vector2.h index bd20618f06..c667f48010 100644 --- a/Code/Framework/AzCore/AzCore/Math/Vector2.h +++ b/Code/Framework/AzCore/AzCore/Math/Vector2.h @@ -9,7 +9,7 @@ #pragma once #include -#include +#include namespace AZ { diff --git a/Code/Framework/AzCore/AzCore/Math/Vector3.h b/Code/Framework/AzCore/AzCore/Math/Vector3.h index 4be70aa02e..6b7ded5641 100644 --- a/Code/Framework/AzCore/AzCore/Math/Vector3.h +++ b/Code/Framework/AzCore/AzCore/Math/Vector3.h @@ -9,7 +9,7 @@ #pragma once #include -#include +#include namespace AZ { diff --git a/Code/Framework/AzCore/AzCore/RTTI/TypeInfo.h b/Code/Framework/AzCore/AzCore/RTTI/TypeInfo.h index 8ec55274f5..022025a3df 100644 --- a/Code/Framework/AzCore/AzCore/RTTI/TypeInfo.h +++ b/Code/Framework/AzCore/AzCore/RTTI/TypeInfo.h @@ -1006,12 +1006,6 @@ namespace AZ AZ_TYPE_INFO_INTERNAL_FUNCTION_VARIATION_SPECIALIZATION(AZStd::function, "{C9F9C644-CCC3-4F77-A792-F5B5DBCA746E}"); } // namespace AZ -#define AZ_TYPE_INFO_INTERNAL_1(_ClassName) static_assert(false, "You must provide a ClassName,ClassUUID") -#define AZ_TYPE_INFO_INTERNAL_2(_ClassName, _ClassUuid) \ - void TYPEINFO_Enable(){} \ - static const char* TYPEINFO_Name() { return #_ClassName; } \ - static const AZ::TypeId& TYPEINFO_Uuid() { static AZ::TypeId s_uuid(_ClassUuid); return s_uuid; } - // Template class type info #define AZ_TYPE_INFO_INTERNAL_TEMPLATE(_ClassName, _ClassUuid, ...)\ void TYPEINFO_Enable() {}\ @@ -1050,39 +1044,11 @@ namespace AZ #define AZ_TYPE_INFO_INTERNAL_17 AZ_TYPE_INFO_INTERNAL_TEMPLATE #define AZ_TYPE_INFO_INTERNAL(...) AZ_MACRO_SPECIALIZE(AZ_TYPE_INFO_INTERNAL_, AZ_VA_NUM_ARGS(__VA_ARGS__), (__VA_ARGS__)) -#define AZ_TYPE_INFO_1 AZ_TYPE_INFO_INTERNAL_1 -#define AZ_TYPE_INFO_2 AZ_TYPE_INFO_INTERNAL_2 -#define AZ_TYPE_INFO_3 AZ_TYPE_INFO_INTERNAL_TEMPLATE_DEPRECATED -#define AZ_TYPE_INFO_4 AZ_TYPE_INFO_INTERNAL_TEMPLATE_DEPRECATED -#define AZ_TYPE_INFO_5 AZ_TYPE_INFO_INTERNAL_TEMPLATE_DEPRECATED -#define AZ_TYPE_INFO_6 AZ_TYPE_INFO_INTERNAL_TEMPLATE_DEPRECATED -#define AZ_TYPE_INFO_7 AZ_TYPE_INFO_INTERNAL_TEMPLATE_DEPRECATED -#define AZ_TYPE_INFO_8 AZ_TYPE_INFO_INTERNAL_TEMPLATE_DEPRECATED -#define AZ_TYPE_INFO_9 AZ_TYPE_INFO_INTERNAL_TEMPLATE_DEPRECATED -#define AZ_TYPE_INFO_10 AZ_TYPE_INFO_INTERNAL_TEMPLATE_DEPRECATED -#define AZ_TYPE_INFO_11 AZ_TYPE_INFO_INTERNAL_TEMPLATE_DEPRECATED -#define AZ_TYPE_INFO_12 AZ_TYPE_INFO_INTERNAL_TEMPLATE_DEPRECATED -#define AZ_TYPE_INFO_13 AZ_TYPE_INFO_INTERNAL_TEMPLATE_DEPRECATED -#define AZ_TYPE_INFO_14 AZ_TYPE_INFO_INTERNAL_TEMPLATE_DEPRECATED -#define AZ_TYPE_INFO_15 AZ_TYPE_INFO_INTERNAL_TEMPLATE_DEPRECATED -#define AZ_TYPE_INFO_16 AZ_TYPE_INFO_INTERNAL_TEMPLATE_DEPRECATED -#define AZ_TYPE_INFO_17 AZ_TYPE_INFO_INTERNAL_TEMPLATE_DEPRECATED - // Fall-back for the original version of AZ_TYPE_INFO that accepted template arguments. This should not be used, unless // to fix issues where AZ_TYPE_INFO was incorrectly used and the old UUID has to be maintained. #define AZ_TYPE_INFO_LEGACY AZ_TYPE_INFO_INTERNAL -/** -* Use this macro inside a class to allow it to be identified across modules and serialized (in different contexts). -* The expected input is the class and the assigned uuid as a string or an instance of a uuid. -* Example: -* class MyClass -* { -* public: -* AZ_TYPE_INFO(MyClass, "{BD5B1568-D232-4EBF-93BD-69DB66E3773F}"); -* ... -*/ -#define AZ_TYPE_INFO(...) AZ_MACRO_SPECIALIZE(AZ_TYPE_INFO_, AZ_VA_NUM_ARGS(__VA_ARGS__), (__VA_ARGS__)) +#include /** * Use this macro outside a class to allow it to be identified across modules and serialized (in different contexts). diff --git a/Code/Framework/AzCore/AzCore/RTTI/TypeInfoSimple.h b/Code/Framework/AzCore/AzCore/RTTI/TypeInfoSimple.h new file mode 100644 index 0000000000..4da514f931 --- /dev/null +++ b/Code/Framework/AzCore/AzCore/RTTI/TypeInfoSimple.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ +#pragma once + +#include +#include + +namespace AZ +{ + using TypeId = AZ::Uuid; +} + +#define AZ_TYPE_INFO_INTERNAL_1(_ClassName) static_assert(false, "You must provide a ClassName,ClassUUID") +#define AZ_TYPE_INFO_INTERNAL_2(_ClassName, _ClassUuid) \ + void TYPEINFO_Enable(){} \ + static const char* TYPEINFO_Name() { return #_ClassName; } \ + static const AZ::TypeId& TYPEINFO_Uuid() { static AZ::TypeId s_uuid(_ClassUuid); return s_uuid; } + +#define AZ_TYPE_INFO_1 AZ_TYPE_INFO_INTERNAL_1 +#define AZ_TYPE_INFO_2 AZ_TYPE_INFO_INTERNAL_2 + +/** +* Use this macro inside a class to allow it to be identified across modules and serialized (in different contexts). +* The expected input is the class and the assigned uuid as a string or an instance of a uuid. +* Example: +* class MyClass +* { +* public: +* AZ_TYPE_INFO(MyClass, "{BD5B1568-D232-4EBF-93BD-69DB66E3773F}"); +* ... +*/ +#define AZ_TYPE_INFO(...) AZ_MACRO_SPECIALIZE(AZ_TYPE_INFO_, AZ_VA_NUM_ARGS(__VA_ARGS__), (__VA_ARGS__)) + diff --git a/Code/Framework/AzCore/AzCore/Serialization/DataOverlay.h b/Code/Framework/AzCore/AzCore/Serialization/DataOverlay.h index 41f0b129e2..0fc4c5b362 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/DataOverlay.h +++ b/Code/Framework/AzCore/AzCore/Serialization/DataOverlay.h @@ -9,7 +9,7 @@ #define AZCORE_DATA_OVERLAY_H #include -#include +#include namespace AZ { diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/ArraySerializer.h b/Code/Framework/AzCore/AzCore/Serialization/Json/ArraySerializer.h index eb7fd250d0..084e46194b 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/ArraySerializer.h +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/ArraySerializer.h @@ -10,7 +10,7 @@ #include #include -#include +#include namespace AZ { diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/DoubleSerializer.h b/Code/Framework/AzCore/AzCore/Serialization/Json/DoubleSerializer.h index f3da5d6b1c..4ba5c2b011 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/DoubleSerializer.h +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/DoubleSerializer.h @@ -10,7 +10,7 @@ #include #include -#include +#include namespace AZ { diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/IntSerializer.h b/Code/Framework/AzCore/AzCore/Serialization/Json/IntSerializer.h index b7a1989c83..4a22e84bad 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/IntSerializer.h +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/IntSerializer.h @@ -10,7 +10,7 @@ #include #include -#include +#include namespace AZ { diff --git a/Code/Framework/AzCore/AzCore/azcore_files.cmake b/Code/Framework/AzCore/AzCore/azcore_files.cmake index c33d678730..0c95b9d592 100644 --- a/Code/Framework/AzCore/AzCore/azcore_files.cmake +++ b/Code/Framework/AzCore/AzCore/azcore_files.cmake @@ -434,6 +434,7 @@ set(FILES Preprocessor/Sequences.h RTTI/RTTI.h RTTI/TypeInfo.h + RTTI/TypeInfoSimple.h RTTI/ReflectContext.h RTTI/ReflectContext.cpp RTTI/ReflectionManager.h diff --git a/Code/Framework/AzCore/AzCore/std/allocator.h b/Code/Framework/AzCore/AzCore/std/allocator.h index 0e024bbb5f..0fee5481e2 100644 --- a/Code/Framework/AzCore/AzCore/std/allocator.h +++ b/Code/Framework/AzCore/AzCore/std/allocator.h @@ -10,7 +10,7 @@ #include #include -#include +#include namespace AZStd { diff --git a/Code/Framework/AzCore/AzCore/std/allocator_traits.h b/Code/Framework/AzCore/AzCore/std/allocator_traits.h index 227727f694..95e64bbc49 100644 --- a/Code/Framework/AzCore/AzCore/std/allocator_traits.h +++ b/Code/Framework/AzCore/AzCore/std/allocator_traits.h @@ -11,6 +11,7 @@ #include #include #include +#include namespace AZStd { diff --git a/Code/Framework/AzCore/AzCore/std/chrono/types.h b/Code/Framework/AzCore/AzCore/std/chrono/types.h index 19ef2c8469..ce42482132 100644 --- a/Code/Framework/AzCore/AzCore/std/chrono/types.h +++ b/Code/Framework/AzCore/AzCore/std/chrono/types.h @@ -10,7 +10,6 @@ #include #include -#include #include #include #include diff --git a/Code/Framework/AzCore/AzCore/std/containers/deque.h b/Code/Framework/AzCore/AzCore/std/containers/deque.h index 170f3316f0..215845a8f4 100644 --- a/Code/Framework/AzCore/AzCore/std/containers/deque.h +++ b/Code/Framework/AzCore/AzCore/std/containers/deque.h @@ -5,14 +5,17 @@ * SPDX-License-Identifier: Apache-2.0 OR MIT * */ +#pragma once #ifndef AZSTD_DEQUE_H #define AZSTD_DEQUE_H 1 + #include #include #include #include #include +#include namespace AZStd { @@ -1242,4 +1245,3 @@ namespace AZStd } #endif // AZSTD_DEQUE_H -#pragma once diff --git a/Code/Framework/AzCore/AzCore/std/containers/list.h b/Code/Framework/AzCore/AzCore/std/containers/list.h index 4d78c01364..124d8b7d7c 100644 --- a/Code/Framework/AzCore/AzCore/std/containers/list.h +++ b/Code/Framework/AzCore/AzCore/std/containers/list.h @@ -7,12 +7,14 @@ */ #ifndef AZSTD_LIST_H #define AZSTD_LIST_H 1 +#pragma once #include #include #include #include #include +#include namespace AZStd { @@ -1346,4 +1348,3 @@ namespace AZStd } #endif // AZSTD_LIST_H -#pragma once diff --git a/Code/Framework/AzCore/AzCore/std/containers/ring_buffer.h b/Code/Framework/AzCore/AzCore/std/containers/ring_buffer.h index 31fbdd85e9..7e84124958 100644 --- a/Code/Framework/AzCore/AzCore/std/containers/ring_buffer.h +++ b/Code/Framework/AzCore/AzCore/std/containers/ring_buffer.h @@ -12,7 +12,6 @@ #include #include #include -//#include namespace AZStd { diff --git a/Code/Framework/AzCore/AzCore/std/containers/vector.h b/Code/Framework/AzCore/AzCore/std/containers/vector.h index 5c1c4da16c..bf02527d77 100644 --- a/Code/Framework/AzCore/AzCore/std/containers/vector.h +++ b/Code/Framework/AzCore/AzCore/std/containers/vector.h @@ -5,13 +5,13 @@ * SPDX-License-Identifier: Apache-2.0 OR MIT * */ -#ifndef AZSTD_VECTOR_H -#define AZSTD_VECTOR_H 1 +#pragma once #include #include #include #include +#include namespace AZStd { @@ -1395,6 +1395,3 @@ namespace AZStd return removedCount; } } - -#endif // AZSTD_VECTOR_H -#pragma once diff --git a/Code/Framework/AzCore/AzCore/std/createdestroy.h b/Code/Framework/AzCore/AzCore/std/createdestroy.h index 94b86a58e4..0fa6e4ed40 100644 --- a/Code/Framework/AzCore/AzCore/std/createdestroy.h +++ b/Code/Framework/AzCore/AzCore/std/createdestroy.h @@ -16,6 +16,7 @@ #include #include #include +#include // AZStd::addressof namespace AZStd { diff --git a/Code/Framework/AzCore/AzCore/std/function/function_base.h b/Code/Framework/AzCore/AzCore/std/function/function_base.h index 409c3824a4..c1dd669f51 100644 --- a/Code/Framework/AzCore/AzCore/std/function/function_base.h +++ b/Code/Framework/AzCore/AzCore/std/function/function_base.h @@ -16,6 +16,7 @@ #include #include #include +#include #include #include diff --git a/Code/Framework/AzCore/AzCore/std/function/function_template.h b/Code/Framework/AzCore/AzCore/std/function/function_template.h index 4f7d41dbd9..586b02e671 100644 --- a/Code/Framework/AzCore/AzCore/std/function/function_template.h +++ b/Code/Framework/AzCore/AzCore/std/function/function_template.h @@ -9,6 +9,7 @@ #include #include +#include #include #include diff --git a/Code/Framework/AzCore/AzCore/std/hash_table.h b/Code/Framework/AzCore/AzCore/std/hash_table.h index c364720b3b..9a31020c49 100644 --- a/Code/Framework/AzCore/AzCore/std/hash_table.h +++ b/Code/Framework/AzCore/AzCore/std/hash_table.h @@ -7,7 +7,6 @@ */ #pragma once -#include #include #include #include diff --git a/Code/Framework/AzCore/AzCore/std/iterator.h b/Code/Framework/AzCore/AzCore/std/iterator.h index 6135b6f450..8d0d49b649 100644 --- a/Code/Framework/AzCore/AzCore/std/iterator.h +++ b/Code/Framework/AzCore/AzCore/std/iterator.h @@ -8,8 +8,9 @@ #pragma once #include -#include #include +#include +#include #include // use by ConstIteratorCast #include diff --git a/Code/Framework/AzCore/AzCore/std/parallel/atomic.h b/Code/Framework/AzCore/AzCore/std/parallel/atomic.h index 09b6f68166..8516dd976a 100644 --- a/Code/Framework/AzCore/AzCore/std/parallel/atomic.h +++ b/Code/Framework/AzCore/AzCore/std/parallel/atomic.h @@ -8,8 +8,6 @@ #pragma once #include -#include -#include #include namespace AZStd diff --git a/Code/Framework/AzCore/AzCore/std/smart_ptr/intrusive_ptr.h b/Code/Framework/AzCore/AzCore/std/smart_ptr/intrusive_ptr.h index 20bc51a18b..9ee9b94fd0 100644 --- a/Code/Framework/AzCore/AzCore/std/smart_ptr/intrusive_ptr.h +++ b/Code/Framework/AzCore/AzCore/std/smart_ptr/intrusive_ptr.h @@ -5,8 +5,7 @@ * SPDX-License-Identifier: Apache-2.0 OR MIT * */ -#ifndef AZSTD_SMART_PTR_INTRUSIVE_PTR_H -#define AZSTD_SMART_PTR_INTRUSIVE_PTR_H +#pragma once // // intrusive_ptr.hpp @@ -19,10 +18,10 @@ // // See http://www.boost.org/libs/smart_ptr/intrusive_ptr.html for documentation. // - -#include #include +#include #include +#include namespace AZStd { @@ -112,7 +111,7 @@ namespace AZStd CountPolicy::add_ref(px); } } - + ~intrusive_ptr() { if (px != 0) @@ -120,7 +119,7 @@ namespace AZStd CountPolicy::release(px); } } - + template enable_if_t::value, intrusive_ptr&> operator=(intrusive_ptr const& rhs) { @@ -157,28 +156,28 @@ namespace AZStd this_type(rhs).swap(*this); return *this; } - + intrusive_ptr& operator=(T* rhs) { this_type(rhs).swap(*this); return *this; } - + void reset() { this_type().swap(*this); } - + void reset(T* rhs) { this_type(rhs).swap(*this); } - + T* get() const { return px; } - + T& operator*() const { AZ_Assert(px != 0, "You can't dereference a null pointer"); @@ -298,6 +297,3 @@ namespace AZStd // operator<< - not supported } // namespace AZStd - -#endif // #ifndef AZSTD_SMART_PTR_INTRUSIVE_PTR_H -#pragma once diff --git a/Code/Framework/AzCore/AzCore/std/string/string.h b/Code/Framework/AzCore/AzCore/std/string/string.h index 4d8fb0c5b5..ad3546ab09 100644 --- a/Code/Framework/AzCore/AzCore/std/string/string.h +++ b/Code/Framework/AzCore/AzCore/std/string/string.h @@ -16,6 +16,7 @@ #include #include #include +#include #include #include diff --git a/Code/Framework/AzCore/AzCore/std/string/string_view.h b/Code/Framework/AzCore/AzCore/std/string/string_view.h index a3d243dae7..9a98795554 100644 --- a/Code/Framework/AzCore/AzCore/std/string/string_view.h +++ b/Code/Framework/AzCore/AzCore/std/string/string_view.h @@ -8,15 +8,16 @@ #pragma once #include -#include #include #include -#include + namespace AZStd { namespace StringInternal { + constexpr size_t min_size(size_t left, size_t right) { return (left < right) ? left : right; } + template constexpr SizeT char_find(const CharT* s, size_t count, CharT ch, SizeT npos = static_cast(-1)) noexcept { @@ -83,7 +84,7 @@ namespace AZStd } // Add one to offset so that for loop condition can check against 0 as the breakout condition - size_t lastIndex = (AZStd::min)(offset, size - count) + 1; + size_t lastIndex = StringInternal::min_size(offset, size - count) + 1; for (; lastIndex; --lastIndex) { @@ -576,7 +577,7 @@ namespace AZStd { return 0; } - size_type rlen = AZStd::min(count, size() - pos); + size_type rlen = StringInternal::min_size(count, size() - pos); Traits::copy(dest, data() + pos, rlen); return rlen; } @@ -584,12 +585,12 @@ namespace AZStd constexpr basic_string_view substr(size_type pos = 0, size_type count = npos) const { AZ_Assert(pos <= size(), "Cannot create substring where position is larger than size"); - return pos > size() ? basic_string_view() : basic_string_view(data() + pos, AZStd::min(count, size() - pos)); + return pos > size() ? basic_string_view() : basic_string_view(data() + pos, StringInternal::min_size(count, size() - pos)); } constexpr int compare(basic_string_view other) const { - size_t cmpSize = AZStd::min(size(), other.size()); + size_t cmpSize = StringInternal::min_size(size(), other.size()); int cmpval = cmpSize == 0 ? 0 : Traits::compare(data(), other.data(), cmpSize); if (cmpval == 0) { @@ -891,6 +892,8 @@ namespace AZStd return hash; } + template + struct hash; template struct hash> { diff --git a/Code/Framework/AzCore/AzCore/std/typetraits/conjunction.h b/Code/Framework/AzCore/AzCore/std/typetraits/conjunction.h index c6084e020e..64f923a40e 100644 --- a/Code/Framework/AzCore/AzCore/std/typetraits/conjunction.h +++ b/Code/Framework/AzCore/AzCore/std/typetraits/conjunction.h @@ -8,6 +8,7 @@ #pragma once #include +#include // for true_type namespace AZStd { diff --git a/Code/Framework/AzCore/AzCore/std/typetraits/static_storage.h b/Code/Framework/AzCore/AzCore/std/typetraits/static_storage.h index 449c9d85c0..00a683b0a8 100644 --- a/Code/Framework/AzCore/AzCore/std/typetraits/static_storage.h +++ b/Code/Framework/AzCore/AzCore/std/typetraits/static_storage.h @@ -9,11 +9,12 @@ #include #include -#include +#include #include namespace AZStd { + using std::forward; // Extension: static_storage: Used to initialize statics in a thread-safe manner // These are similar to default_delete/no_delete, except they just invoke the destructor (or not) template diff --git a/Code/Framework/AzCore/AzCore/std/utils.h b/Code/Framework/AzCore/AzCore/std/utils.h index 0de56cedcb..4c918250de 100644 --- a/Code/Framework/AzCore/AzCore/std/utils.h +++ b/Code/Framework/AzCore/AzCore/std/utils.h @@ -23,7 +23,7 @@ #include #include -#include +#include namespace AZStd { diff --git a/Code/Framework/AzCore/Platform/Common/Default/AzCore/IO/Streamer/StreamerContext_Default.h b/Code/Framework/AzCore/Platform/Common/Default/AzCore/IO/Streamer/StreamerContext_Default.h index 1478f663fa..3052c3f874 100644 --- a/Code/Framework/AzCore/Platform/Common/Default/AzCore/IO/Streamer/StreamerContext_Default.h +++ b/Code/Framework/AzCore/Platform/Common/Default/AzCore/IO/Streamer/StreamerContext_Default.h @@ -11,6 +11,7 @@ #include #include #include +#include namespace AZ::Platform { diff --git a/Code/Framework/AzCore/Platform/Windows/AzCore/Debug/StackTracer_Windows.cpp b/Code/Framework/AzCore/Platform/Windows/AzCore/Debug/StackTracer_Windows.cpp index d2cdac84c7..e6be83bde1 100644 --- a/Code/Framework/AzCore/Platform/Windows/AzCore/Debug/StackTracer_Windows.cpp +++ b/Code/Framework/AzCore/Platform/Windows/AzCore/Debug/StackTracer_Windows.cpp @@ -7,6 +7,7 @@ */ #include #include +#include #include #include diff --git a/Code/Framework/AzCore/Tests/AZStd/SmartPtr.cpp b/Code/Framework/AzCore/Tests/AZStd/SmartPtr.cpp index 6fe55b5672..c852fd35bb 100644 --- a/Code/Framework/AzCore/Tests/AZStd/SmartPtr.cpp +++ b/Code/Framework/AzCore/Tests/AZStd/SmartPtr.cpp @@ -2051,10 +2051,11 @@ namespace UnitTest TEST_F(SmartPtr, IntrusivePtr_DynamicCast) { + AZStd::intrusive_ptr basePointer = new RefCountedSubclass; - AZStd::intrusive_ptr correctCast = dynamic_pointer_cast(basePointer); - AZStd::intrusive_ptr wrongCast = dynamic_pointer_cast(basePointer); + AZStd::intrusive_ptr correctCast = azdynamic_cast(basePointer); + AZStd::intrusive_ptr wrongCast = azdynamic_cast(basePointer); EXPECT_TRUE(correctCast.get() == basePointer.get()); EXPECT_TRUE(wrongCast.get() == nullptr); diff --git a/Code/Framework/AzFramework/AzFramework/Archive/IArchive.h b/Code/Framework/AzFramework/AzFramework/Archive/IArchive.h index 3de63169b2..8866c1b74d 100644 --- a/Code/Framework/AzFramework/AzFramework/Archive/IArchive.h +++ b/Code/Framework/AzFramework/AzFramework/Archive/IArchive.h @@ -11,6 +11,7 @@ #include #include +#include #include #include #include diff --git a/Code/Framework/AzFramework/AzFramework/Asset/CfgFileAsset.h b/Code/Framework/AzFramework/AzFramework/Asset/CfgFileAsset.h index aacf4303a7..2aadf9ae6c 100644 --- a/Code/Framework/AzFramework/AzFramework/Asset/CfgFileAsset.h +++ b/Code/Framework/AzFramework/AzFramework/Asset/CfgFileAsset.h @@ -7,7 +7,7 @@ */ #pragma once -#include +#include #include namespace AzFramework diff --git a/Code/Framework/AzFramework/AzFramework/Physics/Collision/CollisionGroups.h b/Code/Framework/AzFramework/AzFramework/Physics/Collision/CollisionGroups.h index f83a042577..5340a1a344 100644 --- a/Code/Framework/AzFramework/AzFramework/Physics/Collision/CollisionGroups.h +++ b/Code/Framework/AzFramework/AzFramework/Physics/Collision/CollisionGroups.h @@ -8,7 +8,7 @@ #pragma once -#include +#include #include #include #include diff --git a/Code/Framework/AzFramework/AzFramework/Physics/Collision/CollisionLayers.h b/Code/Framework/AzFramework/AzFramework/Physics/Collision/CollisionLayers.h index 25675e311a..6b5a4cd2a9 100644 --- a/Code/Framework/AzFramework/AzFramework/Physics/Collision/CollisionLayers.h +++ b/Code/Framework/AzFramework/AzFramework/Physics/Collision/CollisionLayers.h @@ -8,7 +8,7 @@ #pragma once -#include +#include #include #include #include diff --git a/Code/Framework/AzFramework/AzFramework/Physics/Configuration/CollisionConfiguration.h b/Code/Framework/AzFramework/AzFramework/Physics/Configuration/CollisionConfiguration.h index e784c2339b..b6308e19e0 100644 --- a/Code/Framework/AzFramework/AzFramework/Physics/Configuration/CollisionConfiguration.h +++ b/Code/Framework/AzFramework/AzFramework/Physics/Configuration/CollisionConfiguration.h @@ -8,7 +8,7 @@ #pragma once -#include +#include #include #include #include diff --git a/Code/Framework/AzFramework/AzFramework/Physics/Configuration/SceneConfiguration.h b/Code/Framework/AzFramework/AzFramework/Physics/Configuration/SceneConfiguration.h index 246059bde9..a6590d3702 100644 --- a/Code/Framework/AzFramework/AzFramework/Physics/Configuration/SceneConfiguration.h +++ b/Code/Framework/AzFramework/AzFramework/Physics/Configuration/SceneConfiguration.h @@ -9,7 +9,7 @@ #include #include -#include +#include #include #include diff --git a/Code/Framework/AzFramework/AzFramework/Slice/SliceInstantiationTicket.h b/Code/Framework/AzFramework/AzFramework/Slice/SliceInstantiationTicket.h index 092fcd7822..3097c18d60 100644 --- a/Code/Framework/AzFramework/AzFramework/Slice/SliceInstantiationTicket.h +++ b/Code/Framework/AzFramework/AzFramework/Slice/SliceInstantiationTicket.h @@ -10,7 +10,7 @@ #include #include -#include +#include #include #include diff --git a/Code/Framework/AzFramework/AzFramework/Viewport/CameraState.h b/Code/Framework/AzFramework/AzFramework/Viewport/CameraState.h index 0887754bdf..e174771c3b 100644 --- a/Code/Framework/AzFramework/AzFramework/Viewport/CameraState.h +++ b/Code/Framework/AzFramework/AzFramework/Viewport/CameraState.h @@ -11,6 +11,11 @@ #include #include +namespace AZ +{ + class SerializeContext; +} // namespace AZ + namespace AzFramework { //! Represents the camera state populated by the viewport camera. diff --git a/Code/Framework/AzFramework/AzFramework/Viewport/ScreenGeometry.h b/Code/Framework/AzFramework/AzFramework/Viewport/ScreenGeometry.h index 1063709343..c0fa1ad631 100644 --- a/Code/Framework/AzFramework/AzFramework/Viewport/ScreenGeometry.h +++ b/Code/Framework/AzFramework/AzFramework/Viewport/ScreenGeometry.h @@ -11,7 +11,8 @@ #include #include #include -#include +#include +#include namespace AZ { diff --git a/Code/Framework/AzNetworking/AzNetworking/PacketLayer/IPacket.h b/Code/Framework/AzNetworking/AzNetworking/PacketLayer/IPacket.h index 021ca54cca..9962382f9f 100644 --- a/Code/Framework/AzNetworking/AzNetworking/PacketLayer/IPacket.h +++ b/Code/Framework/AzNetworking/AzNetworking/PacketLayer/IPacket.h @@ -8,7 +8,7 @@ #pragma once -#include +#include #include #include diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/API/ViewPaneOptions.h b/Code/Framework/AzToolsFramework/AzToolsFramework/API/ViewPaneOptions.h index a05a57e138..be93e1af1a 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/API/ViewPaneOptions.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/API/ViewPaneOptions.h @@ -8,7 +8,7 @@ #pragma once -#include +#include #include #include diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Asset/AssetDebugInfo.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Asset/AssetDebugInfo.h index 38bee8a1e5..56eaeb0f75 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Asset/AssetDebugInfo.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Asset/AssetDebugInfo.h @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportTypes.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportTypes.h index 0ce80261ce..1cfb0dbe74 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportTypes.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportTypes.h @@ -19,6 +19,7 @@ namespace AZ { class ReflectContext; + class SerializeContext; } namespace AzToolsFramework diff --git a/Code/Legacy/CryCommon/LyShine/UiAssetTypes.h b/Code/Legacy/CryCommon/LyShine/UiAssetTypes.h index a9c810c025..fef5f4d348 100644 --- a/Code/Legacy/CryCommon/LyShine/UiAssetTypes.h +++ b/Code/Legacy/CryCommon/LyShine/UiAssetTypes.h @@ -7,7 +7,7 @@ */ #pragma once -#include +#include #include //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Code/Tools/AssetProcessor/native/ui/AssetTreeFilterModel.h b/Code/Tools/AssetProcessor/native/ui/AssetTreeFilterModel.h index 05fd3d73d7..70b10e915f 100644 --- a/Code/Tools/AssetProcessor/native/ui/AssetTreeFilterModel.h +++ b/Code/Tools/AssetProcessor/native/ui/AssetTreeFilterModel.h @@ -10,6 +10,7 @@ #if !defined(Q_MOC_RUN) #include +#include #include #endif diff --git a/Code/Tools/AssetProcessor/native/ui/SourceAssetDetailsPanel.h b/Code/Tools/AssetProcessor/native/ui/SourceAssetDetailsPanel.h index 99610467a6..dec4749e03 100644 --- a/Code/Tools/AssetProcessor/native/ui/SourceAssetDetailsPanel.h +++ b/Code/Tools/AssetProcessor/native/ui/SourceAssetDetailsPanel.h @@ -10,6 +10,7 @@ #if !defined(Q_MOC_RUN) #include "AssetDetailsPanel.h" +#include #include #endif diff --git a/Code/Tools/SceneAPI/SDKWrapper/NodeWrapper.h b/Code/Tools/SceneAPI/SDKWrapper/NodeWrapper.h index e011bf213f..bef3cf0db4 100644 --- a/Code/Tools/SceneAPI/SDKWrapper/NodeWrapper.h +++ b/Code/Tools/SceneAPI/SDKWrapper/NodeWrapper.h @@ -7,6 +7,7 @@ */ #pragma once #include +#include struct aiNode; diff --git a/Code/Tools/SceneAPI/SceneCore/Utilities/DebugOutput.h b/Code/Tools/SceneAPI/SceneCore/Utilities/DebugOutput.h index 5bb57a6167..5fe5b98243 100644 --- a/Code/Tools/SceneAPI/SceneCore/Utilities/DebugOutput.h +++ b/Code/Tools/SceneAPI/SceneCore/Utilities/DebugOutput.h @@ -13,6 +13,7 @@ #include #include #include +#include #include namespace AZ::SceneAPI::Utilities diff --git a/Gems/AWSMetrics/Code/Include/Private/ClientConfiguration.h b/Gems/AWSMetrics/Code/Include/Private/ClientConfiguration.h index 7bcb60d325..ddda2299d4 100644 --- a/Gems/AWSMetrics/Code/Include/Private/ClientConfiguration.h +++ b/Gems/AWSMetrics/Code/Include/Private/ClientConfiguration.h @@ -8,6 +8,7 @@ #pragma once #include +#include namespace AWSMetrics { diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialFunctorSourceDataRegistration.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialFunctorSourceDataRegistration.h index 8d8700f284..6ec4641fd8 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialFunctorSourceDataRegistration.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialFunctorSourceDataRegistration.h @@ -9,6 +9,7 @@ #pragma once #include +#include #include #include #include diff --git a/Gems/ScriptCanvas/Code/Editor/Utilities/RecentFiles.cpp b/Gems/ScriptCanvas/Code/Editor/Utilities/RecentFiles.cpp index fa665bb48f..84ee2a8ff8 100644 --- a/Gems/ScriptCanvas/Code/Editor/Utilities/RecentFiles.cpp +++ b/Gems/ScriptCanvas/Code/Editor/Utilities/RecentFiles.cpp @@ -8,6 +8,7 @@ #include "RecentFiles.h" #include "CommonSettingsConfigurations.h" +#include #include #include From f3fe8439a71a15fdfab6af58b384315efe8b9698 Mon Sep 17 00:00:00 2001 From: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> Date: Tue, 10 Aug 2021 17:29:27 -0700 Subject: [PATCH 270/803] Fix local variable declaration. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> --- Code/Framework/AzCore/AzCore/Settings/SettingsRegistryImpl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryImpl.cpp b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryImpl.cpp index 4a7b4183f3..8b10013408 100644 --- a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryImpl.cpp +++ b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryImpl.cpp @@ -1162,7 +1162,7 @@ namespace AZ return false; } - ScopedMergeEvent(m_preMergeEvent, m_postMergeEvent, path, rootKey); + ScopedMergeEvent scopedMergeEvent(m_preMergeEvent, m_postMergeEvent, path, rootKey); JsonSerializationResult::ResultCode mergeResult(JsonSerializationResult::Tasks::Merge); if (rootKey.empty()) From 6db547302ea047479af2649db8f80da535412a8e Mon Sep 17 00:00:00 2001 From: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> Date: Tue, 10 Aug 2021 17:32:39 -0700 Subject: [PATCH 271/803] Remove EditorSettingsOriginTracker (moved to prototype branch) Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> --- .../Settings/EditorSettingsOriginTracker.cpp | 103 ------------------ .../Settings/EditorSettingsOriginTracker.h | 41 ------- .../aztoolsframework_files.cmake | 2 - 3 files changed, 146 deletions(-) delete mode 100644 Code/Framework/AzToolsFramework/AzToolsFramework/Editor/Settings/EditorSettingsOriginTracker.cpp delete mode 100644 Code/Framework/AzToolsFramework/AzToolsFramework/Editor/Settings/EditorSettingsOriginTracker.h diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/Settings/EditorSettingsOriginTracker.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/Settings/EditorSettingsOriginTracker.cpp deleted file mode 100644 index bdeb4e41b4..0000000000 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/Settings/EditorSettingsOriginTracker.cpp +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -#include - -#include -#include - -namespace AzToolsFramework -{ - EditorSettingsOriginTracker::SettingsNotificationHandler::SettingsNotificationHandler( - AZ::SettingsRegistryInterface& registry) - : m_settingsRegistry(registry) - { - AZ::JsonApplyPatchSettings applyPatchSettings; - m_settingsRegistry.GetApplyPatchSettings(applyPatchSettings); - // Wrap any existing callbacks into the reporting callback, so that both this struct - // reporting callbacks and the existing callbacks can be invoked - m_prevReportingCallback = applyPatchSettings.m_reporting; - applyPatchSettings.m_reporting = [this]( - AZStd::string_view message, AZ::JsonSerializationResult::ResultCode result, - AZStd::string_view path) -> AZ::JsonSerializationResult::ResultCode - { - m_prevReportingCallback(message, result, path); - (*this)(message, result, path); - return result; - }; - m_settingsRegistry.SetApplyPatchSettings(applyPatchSettings); - } - - EditorSettingsOriginTracker::SettingsNotificationHandler::~SettingsNotificationHandler() - { - // Restore previous reporting callback - AZ::JsonApplyPatchSettings applyPatchSettings; - m_settingsRegistry.GetApplyPatchSettings(applyPatchSettings); - applyPatchSettings.m_reporting = m_prevReportingCallback; - m_settingsRegistry.SetApplyPatchSettings(applyPatchSettings); - } - - // Use the Json Serialization Issue Callback system - // to determine when a merge option modifies a value - AZ::JsonSerializationResult::ResultCode EditorSettingsOriginTracker::SettingsNotificationHandler::operator()( - AZStd::string_view /*message*/, AZ::JsonSerializationResult::ResultCode result, AZStd::string_view path) - { - using FixedValueString = AZ::SettingsRegistryInterface::FixedValueString; - - AZ::IO::PathView preferencesRootKey{ "/Amazon/Preferences", AZ::IO::PosixPathSeparator }; - AZ::IO::PathView inputKey{ path, AZ::IO::PosixPathSeparator }; - - // Delegate to the Notifier Handler callable below - if (result.GetTask() == AZ::JsonSerializationResult::Tasks::Merge && - result.GetProcessing() == AZ::JsonSerializationResult::Processing::Completed && inputKey.IsRelativeTo(preferencesRootKey)) - { - if (auto type = m_settingsRegistry.GetType(path); type != AZ::SettingsRegistryInterface::Type::NoType) - { - operator()(path, type); - } - } - - return result; - } - - void EditorSettingsOriginTracker::SettingsNotificationHandler::operator()( - AZStd::string_view path, AZ::SettingsRegistryInterface::Type /*type*/) - { - constexpr AZ::IO::PathView preferencesRootKey{ "/Amazon/Preferences", AZ::IO::PosixPathSeparator }; - AZ::IO::PathView inputKey{ path, AZ::IO::PosixPathSeparator }; - if (inputKey.IsRelativeTo(preferencesRootKey)) - { - // Do stuff with key - } - } - - EditorSettingsOriginTracker::EditorSettingsOriginTracker(AZ::SettingsRegistryInterface& registry) - : m_settingsRegistry(registry) - { - auto PreMergeEvent = [this](AZStd::string_view filePath, AZStd::string_view /*rootKey*/) - { - AZ::IO::FixedMaxPath editorPreferencesPath = AZ::Utils::GetProjectPath(); - editorPreferencesPath = editorPreferencesPath / "user" / "Registry" / "editorpreferences.setreg"; - - if (AZ::IO::PathView(filePath) == editorPreferencesPath) - { - m_notifyHandler = m_settingsRegistry.RegisterNotifier(SettingsNotificationHandler(m_settingsRegistry)); - } - }; - - auto PostMergeEvent = [this](AZStd::string_view /*filePath*/, AZStd::string_view /*rootKey*/) - { - // Clear the notification handler so that it goes out of scope - // and this tracker instance no handles settings updates - m_notifyHandler = {}; - }; - - m_preMergeEventHandler = m_settingsRegistry.RegisterPreMergeEvent(PreMergeEvent); - m_postMergeEventHandler = m_settingsRegistry.RegisterPostMergeEvent(PostMergeEvent); - } -} diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/Settings/EditorSettingsOriginTracker.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/Settings/EditorSettingsOriginTracker.h deleted file mode 100644 index fbfdc1af25..0000000000 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/Settings/EditorSettingsOriginTracker.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -#pragma once - -#include -#include -#include - -namespace AzToolsFramework -{ - struct EditorSettingsOriginTracker - { - explicit EditorSettingsOriginTracker(AZ::SettingsRegistryInterface& registry); - - struct SettingsNotificationHandler - { - SettingsNotificationHandler(AZ::SettingsRegistryInterface& registry); - ~SettingsNotificationHandler(); - - AZ::JsonSerializationResult::ResultCode operator()( - AZStd::string_view message, AZ::JsonSerializationResult::ResultCode result, AZStd::string_view path); - void operator()(AZStd::string_view path, AZ::SettingsRegistryInterface::Type type); - - private: - AZ::SettingsRegistryInterface& m_settingsRegistry; - AZ::JsonSerializationResult::JsonIssueCallback m_prevReportingCallback; - }; - - private: - AZ::SettingsRegistryInterface& m_settingsRegistry; - AZ::SettingsRegistryInterface::PreMergeEventHandler m_preMergeEventHandler; - AZ::SettingsRegistryInterface::PostMergeEventHandler m_postMergeEventHandler; - AZ::SettingsRegistryInterface::NotifyEventHandler m_notifyHandler; - }; -} // namespace AZ diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake b/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake index 6e7446d74d..53173f83af 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake @@ -113,8 +113,6 @@ set(FILES Component/EditorLevelComponentAPIComponent.h Editor/EditorContextMenuBus.h Editor/EditorSettingsAPIBus.h - Editor/Settings/EditorSettingsOriginTracker.cpp - Editor/Settings/EditorSettingsOriginTracker.h Entity/EditorEntityStartStatus.h Entity/EditorEntityAPIBus.h Entity/EditorEntityContextComponent.cpp From 737cf3093791efb073ad226cbe7703e840c958d5 Mon Sep 17 00:00:00 2001 From: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> Date: Tue, 10 Aug 2021 17:36:43 -0700 Subject: [PATCH 272/803] Fix documentation comments to be more accurate. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> --- .../AzCore/AzCore/Settings/SettingsRegistry.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistry.h b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistry.h index e27e4452ee..106e232904 100644 --- a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistry.h +++ b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistry.h @@ -199,18 +199,18 @@ namespace AZ //! @callback The function to call when an entry gets a new/updated value. [[nodiscard]] virtual NotifyEventHandler RegisterNotifier(NotifyCallback&& callback) = 0; - //! Register a callback that will be called before an entry is merged. - //! @callback The function to call when an entry gets a new/updated value. + //! Register a function that will be called before a file is merged. + //! @callback The function to call before a file is merged. [[nodiscard]] virtual PreMergeEventHandler RegisterPreMergeEvent(const PreMergeEventCallback& callback) = 0; - //! Register a callback that will be called before an entry is merged. - //! @callback The function to call when an entry gets a new/updated value. + //! Register a function that will be called before a file is merged. + //! @callback The function to call before a file is merged. [[nodiscard]] virtual PreMergeEventHandler RegisterPreMergeEvent (PreMergeEventCallback&& callback) = 0; - //! Register a callback that will be called after an entry is merged. - //! @callback The function to call when an entry gets a new/updated value. + //! Register a function that will be called after a file is merged. + //! @callback The function to call after a file is merged. [[nodiscard]] virtual PostMergeEventHandler RegisterPostMergeEvent(const PostMergeEventCallback& callback) = 0; - //! Register a callback that will be called after an entry is merged. - //! @callback The function to call when an entry gets a new/updated value. + //! Register a function that will be called after a file is merged. + //! @callback The function to call after a file is merged. [[nodiscard]] virtual PostMergeEventHandler RegisterPostMergeEvent (PostMergeEventCallback&& callback) = 0; //! Gets the boolean value at the provided path. From a7a0e8d2ef6778153deb28fedfc495832f162842 Mon Sep 17 00:00:00 2001 From: jonawals Date: Wed, 11 Aug 2021 02:43:44 +0100 Subject: [PATCH 273/803] Fix for PathLib unlink wrong version parameter. (#3020) * Fix for PathLib unlink wrong version parameter. * Fix dst target for TIAF. * Remove TIAF historic data arhciving on s3 buckets * Change permissions for TIAF bucket upload Signed-off-by: John --- scripts/build/Platform/Windows/build_config.json | 2 +- scripts/build/TestImpactAnalysis/git_utils.py | 4 +++- .../TestImpactAnalysis/tiaf_persistent_storage_s3.py | 9 +++------ 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/scripts/build/Platform/Windows/build_config.json b/scripts/build/Platform/Windows/build_config.json index 8ac0b5241c..4c275a49cf 100644 --- a/scripts/build/Platform/Windows/build_config.json +++ b/scripts/build/Platform/Windows/build_config.json @@ -89,7 +89,7 @@ "CONFIGURATION": "profile", "SCRIPT_PATH": "scripts/build/TestImpactAnalysis/tiaf_driver.py", "SCRIPT_PARAMETERS": - "--config=\"!OUTPUT_DIRECTORY!/bin/TestImpactFramework/profile/Persistent/tiaf.json\" --src-branch=!BRANCH_NAME! --dst-branch=!BRANCH_NAME! --commit=!CHANGE_ID! --s3-bucket=!TEST_IMPACT_S3_BUCKET! --mars-index-prefix=jonawals --suite=main --test-failure-policy=continue" + "--config=\"!OUTPUT_DIRECTORY!/bin/TestImpactFramework/profile/Persistent/tiaf.json\" --src-branch=!BRANCH_NAME! --dst-branch=!CHANGE_TARGET! --commit=!CHANGE_ID! --s3-bucket=!TEST_IMPACT_S3_BUCKET! --mars-index-prefix=jonawals --suite=main --test-failure-policy=continue" } }, "debug_vs2019": { diff --git a/scripts/build/TestImpactAnalysis/git_utils.py b/scripts/build/TestImpactAnalysis/git_utils.py index 04d994ba4a..3561b337f3 100644 --- a/scripts/build/TestImpactAnalysis/git_utils.py +++ b/scripts/build/TestImpactAnalysis/git_utils.py @@ -32,7 +32,9 @@ class Repo: try: # Remove the existing file (if any) and create the parent directory - output_path.unlink(missing_ok=True) + # output_path.unlink(missing_ok=True) # missing_ok is only available in Python 3.8+ + if output_path.is_file(): + output_path.unlink() output_path.parent.mkdir(exist_ok=True) except EnvironmentError as e: raise RuntimeError(f"Could not create path for output file '{output_path}'") diff --git a/scripts/build/TestImpactAnalysis/tiaf_persistent_storage_s3.py b/scripts/build/TestImpactAnalysis/tiaf_persistent_storage_s3.py index 75c4bc93d5..09b4df0564 100644 --- a/scripts/build/TestImpactAnalysis/tiaf_persistent_storage_s3.py +++ b/scripts/build/TestImpactAnalysis/tiaf_persistent_storage_s3.py @@ -48,14 +48,11 @@ class PersistentStorageS3(PersistentStorage): for object in self._bucket.objects.filter(Prefix=self._historic_data_key): logger.info(f"Historic data found for branch '{branch}'.") - # Archive the existing object with the name of the existing last commit hash - archive_key = f"{self._dir}/archive/{self._last_commit_hash}.{object_extension}" - logger.info(f"Archiving existing historic data to {archive_key}...") - self._bucket.copy({"Bucket": self._bucket.name, "Key": self._historic_data_key}, archive_key) - # Decode the historic data object into raw bytes + logger.info(f"Attempting to decode historic data object...") response = object.get() file_stream = response['Body'] + logger.info(f"Decoding complete.") # Decompress and unpack the zipped historic data JSON historic_data_json = zlib.decompress(file_stream.read()).decode('UTF-8') @@ -79,7 +76,7 @@ class PersistentStorageS3(PersistentStorage): try: data = BytesIO(zlib.compress(bytes(historic_data_json, "UTF-8"))) logger.info(f"Uploading historic data to location '{self._historic_data_key}'...") - self._bucket.upload_fileobj(data, self._historic_data_key) + self._bucket.upload_fileobj(data, self._historic_data_key, ExtraArgs={'ACL': 'bucket-owner-full-control'}) logger.info("Upload complete.") except botocore.exceptions.BotoCoreError as e: logger.error(f"There was a problem with the s3 bucket: {e}") From fa2032d21d406b959f4c94025cb94f412807cde3 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Tue, 10 Aug 2021 19:02:38 -0700 Subject: [PATCH 274/803] Linux fixes Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Editor/GameEngine.h | 1 + Code/Editor/Include/IObjectManager.h | 1 + Code/Editor/QtUtil.h | 1 + .../Platform/Linux/Launcher_Linux.cpp | 1 + Code/Legacy/CryCommon/AppleSpecific.h | 4 ---- Code/Legacy/CryCommon/CryThread_pthreads.h | 20 ------------------- Code/Legacy/CryCommon/LinuxSpecific.h | 16 +++++++++++++-- Code/Legacy/CryCommon/Linux_Win32Wrapper.h | 2 -- Code/Legacy/CryCommon/VectorMap.h | 1 + 9 files changed, 19 insertions(+), 28 deletions(-) diff --git a/Code/Editor/GameEngine.h b/Code/Editor/GameEngine.h index 84df8bf002..829baec55a 100644 --- a/Code/Editor/GameEngine.h +++ b/Code/Editor/GameEngine.h @@ -20,6 +20,7 @@ #include "LogFile.h" #include "CryListenerSet.h" #include "Util/ModalWindowDismisser.h" +#include #endif class CStartupLogoDialog; diff --git a/Code/Editor/Include/IObjectManager.h b/Code/Editor/Include/IObjectManager.h index efc1955a56..360cc8fe34 100644 --- a/Code/Editor/Include/IObjectManager.h +++ b/Code/Editor/Include/IObjectManager.h @@ -12,6 +12,7 @@ #pragma once #include +#include #include #include #include diff --git a/Code/Editor/QtUtil.h b/Code/Editor/QtUtil.h index bb1f8ba427..a16eb1e692 100644 --- a/Code/Editor/QtUtil.h +++ b/Code/Editor/QtUtil.h @@ -12,6 +12,7 @@ #include #include #include "UnicodeFunctions.h" +#include #include #include diff --git a/Code/LauncherUnified/Platform/Linux/Launcher_Linux.cpp b/Code/LauncherUnified/Platform/Linux/Launcher_Linux.cpp index 1e87b902a6..3030dcc740 100644 --- a/Code/LauncherUnified/Platform/Linux/Launcher_Linux.cpp +++ b/Code/LauncherUnified/Platform/Linux/Launcher_Linux.cpp @@ -10,6 +10,7 @@ #include #include // for AZ_MAX_PATH_LEN +#include #include diff --git a/Code/Legacy/CryCommon/AppleSpecific.h b/Code/Legacy/CryCommon/AppleSpecific.h index 87aea0fbb5..df3b7578eb 100644 --- a/Code/Legacy/CryCommon/AppleSpecific.h +++ b/Code/Legacy/CryCommon/AppleSpecific.h @@ -355,13 +355,9 @@ enum #define wcsnicmp wcsncasecmp //#define memcpy_s(dest,bytes,src,n) memcpy(dest,src,n) #define _isnan ISNAN -#define _wtof(str) wcstod(str, 0) - #define TARGET_DEFAULT_ALIGN (0x8U) - - #define _msize malloc_size diff --git a/Code/Legacy/CryCommon/CryThread_pthreads.h b/Code/Legacy/CryCommon/CryThread_pthreads.h index 2c6b389dbb..17f7e5d2a0 100644 --- a/Code/Legacy/CryCommon/CryThread_pthreads.h +++ b/Code/Legacy/CryCommon/CryThread_pthreads.h @@ -653,15 +653,9 @@ private: typedef CryEventTimed CryEvent; -#if !PLATFORM_SUPPORTS_THREADLOCAL -TLS_DECLARE(class CrySimpleThreadSelf*, g_CrySimpleThreadSelf); -#endif - class CrySimpleThreadSelf { protected: -#if PLATFORM_SUPPORTS_THREADLOCAL - static CrySimpleThreadSelf* GetSelf() { return m_Self; @@ -673,20 +667,6 @@ protected: } private: static AZ_THREAD_LOCAL CrySimpleThreadSelf* m_Self; - -#else - - static CrySimpleThreadSelf* GetSelf() - { - return TLS_GET(CrySimpleThreadSelf*, g_CrySimpleThreadSelf); - } - - static void SetSelf(CrySimpleThreadSelf* pSelf) - { - TLS_SET(g_CrySimpleThreadSelf, pSelf); - } - -#endif }; template diff --git a/Code/Legacy/CryCommon/LinuxSpecific.h b/Code/Legacy/CryCommon/LinuxSpecific.h index a587350cb2..112e965555 100644 --- a/Code/Legacy/CryCommon/LinuxSpecific.h +++ b/Code/Legacy/CryCommon/LinuxSpecific.h @@ -209,8 +209,20 @@ typedef unsigned long int threadID; #define wcsicmp wcscasecmp #define wcsnicmp wcsncasecmp - -#define _wtof(str) wcstod(str, 0) +typedef union _LARGE_INTEGER +{ + struct + { + DWORD LowPart; + LONG HighPart; + }; + struct + { + DWORD LowPart; + LONG HighPart; + } u; + long long QuadPart; +} LARGE_INTEGER; // stdlib.h stuff #define _MAX_DRIVE 3 // max. length of drive component diff --git a/Code/Legacy/CryCommon/Linux_Win32Wrapper.h b/Code/Legacy/CryCommon/Linux_Win32Wrapper.h index 2de17e6b28..625add59ad 100644 --- a/Code/Legacy/CryCommon/Linux_Win32Wrapper.h +++ b/Code/Legacy/CryCommon/Linux_Win32Wrapper.h @@ -324,8 +324,6 @@ inline uint32 GetTickCount() #define _strlwr_s(BUF, SIZE) strlwr(BUF) #define _strups strupr -#define _wtof(str) wcstod(str, 0) - // Need to include this before using it's used in finddata, but after the strnicmp definition #include "CryString.h" diff --git a/Code/Legacy/CryCommon/VectorMap.h b/Code/Legacy/CryCommon/VectorMap.h index 1a42f0e48f..75b1562c4d 100644 --- a/Code/Legacy/CryCommon/VectorMap.h +++ b/Code/Legacy/CryCommon/VectorMap.h @@ -14,6 +14,7 @@ #define CRYINCLUDE_CRYCOMMON_VECTORMAP_H #pragma once +#include //-------------------------------------------------------------------------- // VectorMap From 2361490c8bf0f89d4e32b84e60aa7dcc10e85a64 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Tue, 10 Aug 2021 20:18:59 -0700 Subject: [PATCH 275/803] Fixes for Android Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Legacy/CryCommon/platform.h | 2 +- .../AtomFont/Code/Include/AtomLyIntegration/AtomFont/AtomFont.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Code/Legacy/CryCommon/platform.h b/Code/Legacy/CryCommon/platform.h index 88d06c9b1e..030fd4186e 100644 --- a/Code/Legacy/CryCommon/platform.h +++ b/Code/Legacy/CryCommon/platform.h @@ -192,7 +192,7 @@ #else #if defined(WIN64) #include "Win64specific.h" - #elif defined(LINUX64) + #elif defined(LINUX64) && !defined(ANDROID) #include "Linux64Specific.h" #elif defined(MAC) #include "MacSpecific.h" diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/AtomFont.h b/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/AtomFont.h index 7dd2629bd0..44de9656d2 100644 --- a/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/AtomFont.h +++ b/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/AtomFont.h @@ -20,6 +20,7 @@ #include #include #include +#include #include #include From f99f1f00f4de5696275db77cbbca5ee168891dab Mon Sep 17 00:00:00 2001 From: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> Date: Tue, 10 Aug 2021 20:35:55 -0700 Subject: [PATCH 276/803] [redcode/crythread-2nd-pass] removed or replaced remaining CryMutex/CryLock usage with equivalent AZStd version Signed-off-by: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> --- Code/Editor/CryEdit.cpp | 18 +++++++++--------- Code/Editor/GameEngine.h | 4 ++-- Code/Editor/GameExporter.cpp | 2 +- Code/Editor/IEditorImpl.cpp | 6 +++--- Code/Editor/IEditorImpl.h | 2 +- .../PerforcePlugin/PerforceSourceControl.cpp | 8 ++++---- Code/Legacy/CryCommon/CryAssert_Linux.h | 4 ++-- Code/Legacy/CryCommon/CryAssert_Mac.h | 2 -- Code/Legacy/CryCommon/IMaterial.h | 2 -- .../Legacy/CryCommon/MultiThread_Containers.h | 6 +++--- .../Legacy/CrySystem/LocalizedStringManager.h | 4 ++-- Code/Legacy/CrySystem/Log.cpp | 19 ++++--------------- Code/Legacy/CrySystem/Log.h | 4 +--- .../CrySystem/SystemEventDispatcher.cpp | 12 ++++++------ Code/Legacy/CrySystem/SystemEventDispatcher.h | 2 +- 15 files changed, 39 insertions(+), 56 deletions(-) diff --git a/Code/Editor/CryEdit.cpp b/Code/Editor/CryEdit.cpp index 5a5b17f799..fdde069e6f 100644 --- a/Code/Editor/CryEdit.cpp +++ b/Code/Editor/CryEdit.cpp @@ -891,7 +891,7 @@ CCrySingleDocTemplate::Confidence CCrySingleDocTemplate::MatchDocType(LPCTSTR lp ///////////////////////////////////////////////////////////////////////////// namespace { - CryMutex g_splashScreenStateLock; + AZStd::mutex g_splashScreenStateLock; enum ESplashScreenState { eSplashScreenState_Init, eSplashScreenState_Started, eSplashScreenState_Destroy @@ -922,7 +922,7 @@ QString FormatRichTextCopyrightNotice() ///////////////////////////////////////////////////////////////////////////// void CCryEditApp::ShowSplashScreen(CCryEditApp* app) { - g_splashScreenStateLock.Lock(); + g_splashScreenStateLock.lock(); CStartupLogoDialog* splashScreen = new CStartupLogoDialog(FormatVersion(app->m_pEditor->GetFileVersion()), FormatRichTextCopyrightNotice()); @@ -930,7 +930,7 @@ void CCryEditApp::ShowSplashScreen(CCryEditApp* app) g_splashScreen = splashScreen; g_splashScreenState = eSplashScreenState_Started; - g_splashScreenStateLock.Unlock(); + g_splashScreenStateLock.unlock(); splashScreen->show(); // Make sure the initial paint of the splash screen occurs so we dont get stuck with a blank window @@ -938,10 +938,10 @@ void CCryEditApp::ShowSplashScreen(CCryEditApp* app) QObject::connect(splashScreen, &QObject::destroyed, splashScreen, [=] { - g_splashScreenStateLock.Lock(); + g_splashScreenStateLock.lock(); g_pInitializeUIInfo = nullptr; g_splashScreen = nullptr; - g_splashScreenStateLock.Unlock(); + g_splashScreenStateLock.unlock(); }); } @@ -971,9 +971,9 @@ void CCryEditApp::CloseSplashScreen() if (CStartupLogoDialog::instance()) { delete CStartupLogoDialog::instance(); - g_splashScreenStateLock.Lock(); + g_splashScreenStateLock.lock(); g_splashScreenState = eSplashScreenState_Destroy; - g_splashScreenStateLock.Unlock(); + g_splashScreenStateLock.unlock(); } GetIEditor()->Notify(eNotify_OnSplashScreenDestroyed); @@ -982,12 +982,12 @@ void CCryEditApp::CloseSplashScreen() ///////////////////////////////////////////////////////////////////////////// void CCryEditApp::OutputStartupMessage(QString str) { - g_splashScreenStateLock.Lock(); + g_splashScreenStateLock.lock(); if (g_pInitializeUIInfo) { g_pInitializeUIInfo->SetInfoText(str.toUtf8().data()); } - g_splashScreenStateLock.Unlock(); + g_splashScreenStateLock.unlock(); } ////////////////////////////////////////////////////////////////////////// diff --git a/Code/Editor/GameEngine.h b/Code/Editor/GameEngine.h index 84df8bf002..4d183cc38e 100644 --- a/Code/Editor/GameEngine.h +++ b/Code/Editor/GameEngine.h @@ -116,11 +116,11 @@ public: //! mutex used by other threads to lock up the PAK modification, //! so only one thread can modify the PAK at once - static CryMutex& GetPakModifyMutex() + static AZStd::recursive_mutex& GetPakModifyMutex() { //! mutex used to halt copy process while the export to game //! or other pak operation is done in the main thread - static CryMutex s_pakModifyMutex; + static AZStd::recursive_mutex s_pakModifyMutex; return s_pakModifyMutex; } diff --git a/Code/Editor/GameExporter.cpp b/Code/Editor/GameExporter.cpp index 006eb9189c..d2a16ccc30 100644 --- a/Code/Editor/GameExporter.cpp +++ b/Code/Editor/GameExporter.cpp @@ -136,7 +136,7 @@ bool CGameExporter::Export(unsigned int flags, [[maybe_unused]] EEndian eExportE m_settings.SetHiQuality(); } - CryAutoLock autoLock(CGameEngine::GetPakModifyMutex()); + AZStd::lock_guard autoLock(CGameEngine::GetPakModifyMutex()); // Close this pak file. if (!CloseLevelPack(m_levelPak, true)) diff --git a/Code/Editor/IEditorImpl.cpp b/Code/Editor/IEditorImpl.cpp index c09c0a8e62..3c166fbca2 100644 --- a/Code/Editor/IEditorImpl.cpp +++ b/Code/Editor/IEditorImpl.cpp @@ -251,7 +251,7 @@ void CEditorImpl::Uninitialize() void CEditorImpl::UnloadPlugins() { - CryAutoLock lock(m_pluginMutex); + AZStd::lock_guard lock(m_pluginMutex); // Flush core buses. We're about to unload DLLs and need to ensure we don't have module-owned functions left behind. AZ::Data::AssetBus::ExecuteQueuedEvents(); @@ -272,7 +272,7 @@ void CEditorImpl::UnloadPlugins() void CEditorImpl::LoadPlugins() { - CryAutoLock lock(m_pluginMutex); + AZStd::lock_guard lock(m_pluginMutex); static const QString editor_plugins_folder("EditorPlugins"); @@ -1457,7 +1457,7 @@ void CEditorImpl::UnregisterNotifyListener(IEditorNotifyListener* listener) ISourceControl* CEditorImpl::GetSourceControl() { - CryAutoLock lock(m_pluginMutex); + AZStd::lock_guard lock(m_pluginMutex); if (m_pSourceControl) { diff --git a/Code/Editor/IEditorImpl.h b/Code/Editor/IEditorImpl.h index 65389a212e..275214bc57 100644 --- a/Code/Editor/IEditorImpl.h +++ b/Code/Editor/IEditorImpl.h @@ -401,7 +401,7 @@ protected: IImageUtil* m_pImageUtil; // Vladimir@conffx ILogFile* m_pLogFile; // Vladimir@conffx - CryMutex m_pluginMutex; // protect any pointers that come from plugins, such as the source control cached pointer. + AZStd::mutex m_pluginMutex; // protect any pointers that come from plugins, such as the source control cached pointer. static const char* m_crashLogFileName; }; diff --git a/Code/Editor/Plugins/PerforcePlugin/PerforceSourceControl.cpp b/Code/Editor/Plugins/PerforcePlugin/PerforceSourceControl.cpp index 581f9a576d..34514b8ef1 100644 --- a/Code/Editor/Plugins/PerforcePlugin/PerforceSourceControl.cpp +++ b/Code/Editor/Plugins/PerforcePlugin/PerforceSourceControl.cpp @@ -22,7 +22,7 @@ namespace { - CryCriticalSection g_cPerforceValues; + AZStd::mutex g_cPerforceValues; } //////////////////////////////////////////////////////////// @@ -30,9 +30,9 @@ ULONG STDMETHODCALLTYPE CPerforceSourceControl::Release() { if ((--m_ref) == 0) { - g_cPerforceValues.Lock(); + g_cPerforceValues.lock(); delete this; - g_cPerforceValues.Unlock(); + g_cPerforceValues.unlock(); return 0; } else @@ -56,7 +56,7 @@ void CPerforceSourceControl::ShowSettings() void CPerforceSourceControl::SetSourceControlState(SourceControlState state) { - CryAutoLock lock(g_cPerforceValues); + AZStd::lock_guard lock(g_cPerforceValues); switch (state) { diff --git a/Code/Legacy/CryCommon/CryAssert_Linux.h b/Code/Legacy/CryCommon/CryAssert_Linux.h index 3debe2bd5d..355194caba 100644 --- a/Code/Legacy/CryCommon/CryAssert_Linux.h +++ b/Code/Legacy/CryCommon/CryAssert_Linux.h @@ -72,7 +72,7 @@ bool CryAssert(const char* szCondition, const char* szFile, unsigned int line, b static const int max_len = 4096; static char gs_command_str[4096]; - static CryLockT lock; + static AZStd::recursive_mutex lock; gEnv->pSystem->OnAssert(szCondition, gs_szMessage, szFile, line); @@ -80,7 +80,7 @@ bool CryAssert(const char* szCondition, const char* szFile, unsigned int line, b if (!gEnv->bNoAssertDialog && !gEnv->bIgnoreAllAsserts) { - CryAutoLock< CryLockT > lk (lock); + AZStd::lock_guard lk (lock); snprintf(gs_command_str, max_len, "xterm -geometry 100x20 -n 'Assert Dialog [Linux Launcher]' -T 'Assert Dialog [Linux Launcher]' -e 'BinLinux/assert_term \"%s\" \"%s\" %d \"%s\"; echo \"$?\" > .assert_return'", szCondition, (file_len > 60) ? szFile + (file_len - 61) : szFile, line, gs_szMessage); int ret = system(gs_command_str); diff --git a/Code/Legacy/CryCommon/CryAssert_Mac.h b/Code/Legacy/CryCommon/CryAssert_Mac.h index ce65b352ab..f0a893630e 100644 --- a/Code/Legacy/CryCommon/CryAssert_Mac.h +++ b/Code/Legacy/CryCommon/CryAssert_Mac.h @@ -70,8 +70,6 @@ bool CryAssert(const char* szCondition, const char* szFile, unsigned int line, b static const int max_len = 4096; static char gs_command_str[4096]; - static CryLockT lock; - gEnv->pSystem->OnAssert(szCondition, gs_szMessage, szFile, line); size_t file_len = strlen(szFile); diff --git a/Code/Legacy/CryCommon/IMaterial.h b/Code/Legacy/CryCommon/IMaterial.h index 1faee0eef9..97a5100018 100644 --- a/Code/Legacy/CryCommon/IMaterial.h +++ b/Code/Legacy/CryCommon/IMaterial.h @@ -432,8 +432,6 @@ struct IMaterial virtual uint32 GetDccMaterialHash() const = 0; virtual void SetDccMaterialHash(uint32 hash) = 0; - virtual CryCriticalSection& GetSubMaterialResizeLock() = 0; - virtual void UpdateShaderItems() = 0; // diff --git a/Code/Legacy/CryCommon/MultiThread_Containers.h b/Code/Legacy/CryCommon/MultiThread_Containers.h index 23f7cd1e0c..8a60adfa6b 100644 --- a/Code/Legacy/CryCommon/MultiThread_Containers.h +++ b/Code/Legacy/CryCommon/MultiThread_Containers.h @@ -34,7 +34,7 @@ namespace CryMT public: typedef T value_type; typedef std::vector container_type; - typedef CryAutoCriticalSection AutoLock; + typedef AZStd::lock_guard AutoLock; ////////////////////////////////////////////////////////////////////////// // std::queue interface @@ -46,7 +46,7 @@ namespace CryMT // classic pop function of queue should not be used for thread safety, use try_pop instead //void pop() { AutoLock lock(m_cs); return v.erase(v.begin()); }; - CryCriticalSection& get_lock() const { return m_cs; } + AZStd::recursive_mutex& get_lock() const { return m_cs; } bool empty() const { AutoLock lock(m_cs); return v.empty(); } int size() const { AutoLock lock(m_cs); return v.size(); } @@ -92,7 +92,7 @@ namespace CryMT } private: container_type v; - mutable CryCriticalSection m_cs; + mutable AZStd::recursive_mutex m_cs; }; }; // namespace CryMT diff --git a/Code/Legacy/CrySystem/LocalizedStringManager.h b/Code/Legacy/CrySystem/LocalizedStringManager.h index 581a657c81..6916dee3c3 100644 --- a/Code/Legacy/CrySystem/LocalizedStringManager.h +++ b/Code/Legacy/CrySystem/LocalizedStringManager.h @@ -309,8 +309,8 @@ private: TLocalizationBitfield m_availableLocalizations; //Lock for - mutable CryCriticalSection m_cs; - typedef CryAutoCriticalSection AutoLock; + mutable AZStd::mutex m_cs; + typedef AZStd::lock_guard AutoLock; }; diff --git a/Code/Legacy/CrySystem/Log.cpp b/Code/Legacy/CrySystem/Log.cpp index 96bc29b58a..e7ba8f5ba7 100644 --- a/Code/Legacy/CrySystem/Log.cpp +++ b/Code/Legacy/CrySystem/Log.cpp @@ -32,17 +32,6 @@ #include #endif - -// Only accept logging from the main thread. -#ifdef WIN32 - -#define THREAD_SAFE_LOG -//#define THREAD_SAFE_LOG CryAutoCriticalSection scope_lock(m_logCriticalSection); - -#else -#define THREAD_SAFE_LOG -#endif //WIN32 - #define LOG_BACKUP_PATH "@log@/LogBackups" #if defined(IOS) @@ -822,13 +811,13 @@ void CLog::PushAssetScopeName(const char* sAssetType, const char* sName) SAssetScopeInfo as; as.sType = sAssetType; as.sName = sName; - CryAutoCriticalSection scope_lock(m_assetScopeQueueLock); + AZStd::lock_guard scope_lock(m_assetScopeQueueLock); m_assetScopeQueue.push_back(as); } void CLog::PopAssetScopeName() { - CryAutoCriticalSection scope_lock(m_assetScopeQueueLock); + AZStd::lock_guard scope_lock(m_assetScopeQueueLock); assert(!m_assetScopeQueue.empty()); if (!m_assetScopeQueue.empty()) { @@ -839,7 +828,7 @@ void CLog::PopAssetScopeName() ////////////////////////////////////////////////////////////////////////// const char* CLog::GetAssetScopeString() { - CryAutoCriticalSection scope_lock(m_assetScopeQueueLock); + AZStd::lock_guard scope_lock(m_assetScopeQueueLock); m_assetScopeString.clear(); for (size_t i = 0; i < m_assetScopeQueue.size(); i++) @@ -1470,7 +1459,7 @@ void CLog::Update() { if (!m_threadSafeMsgQueue.empty()) { - CryAutoCriticalSection lock(m_threadSafeMsgQueue.get_lock()); // Get the lock and hold onto it until we clear the entire queue (prevents other threads adding more things in while we clear it) + AZStd::lock_guard lock(m_threadSafeMsgQueue.get_lock()); // Get the lock and hold onto it until we clear the entire queue (prevents other threads adding more things in while we clear it) // Must be called from main thread SLogMsg msg; while (m_threadSafeMsgQueue.try_pop(msg)) diff --git a/Code/Legacy/CrySystem/Log.h b/Code/Legacy/CrySystem/Log.h index 5b1956b12f..d6b6dcea3e 100644 --- a/Code/Legacy/CrySystem/Log.h +++ b/Code/Legacy/CrySystem/Log.h @@ -168,7 +168,7 @@ private: // ------------------------------------------------------------------- }; std::vector m_assetScopeQueue; - CryCriticalSection m_assetScopeQueueLock; + AZStd::mutex m_assetScopeQueueLock; string m_assetScopeString; #endif @@ -176,8 +176,6 @@ private: // ------------------------------------------------------------------- IConsole* m_pConsole; // - CryCriticalSection m_logCriticalSection; - struct SLogHistoryItem { char str[MAX_WARNING_LENGTH]; diff --git a/Code/Legacy/CrySystem/SystemEventDispatcher.cpp b/Code/Legacy/CrySystem/SystemEventDispatcher.cpp index eb8113c501..525bf1a005 100644 --- a/Code/Legacy/CrySystem/SystemEventDispatcher.cpp +++ b/Code/Legacy/CrySystem/SystemEventDispatcher.cpp @@ -17,17 +17,17 @@ CSystemEventDispatcher::CSystemEventDispatcher() bool CSystemEventDispatcher::RegisterListener(ISystemEventListener* pListener) { - m_listenerRegistrationLock.Lock(); + m_listenerRegistrationLock.lock(); bool ret = m_listeners.Add(pListener); - m_listenerRegistrationLock.Unlock(); + m_listenerRegistrationLock.unlock(); return ret; } bool CSystemEventDispatcher::RemoveListener(ISystemEventListener* pListener) { - m_listenerRegistrationLock.Lock(); + m_listenerRegistrationLock.lock(); m_listeners.Remove(pListener); - m_listenerRegistrationLock.Unlock(); + m_listenerRegistrationLock.unlock(); return true; } @@ -35,12 +35,12 @@ bool CSystemEventDispatcher::RemoveListener(ISystemEventListener* pListener) ////////////////////////////////////////////////////////////////////////// void CSystemEventDispatcher::OnSystemEventAnyThread(ESystemEvent event, UINT_PTR wparam, UINT_PTR lparam) { - m_listenerRegistrationLock.Lock(); + m_listenerRegistrationLock.lock(); for (TSystemEventListeners::Notifier notifier(m_listeners); notifier.IsValid(); notifier.Next()) { notifier->OnSystemEventAnyThread(event, wparam, lparam); } - m_listenerRegistrationLock.Unlock(); + m_listenerRegistrationLock.unlock(); } diff --git a/Code/Legacy/CrySystem/SystemEventDispatcher.h b/Code/Legacy/CrySystem/SystemEventDispatcher.h index 37ce170abd..a5d33b2542 100644 --- a/Code/Legacy/CrySystem/SystemEventDispatcher.h +++ b/Code/Legacy/CrySystem/SystemEventDispatcher.h @@ -46,7 +46,7 @@ private: typedef CryMT::queue TSystemEventQueue; TSystemEventQueue m_systemEventQueue; - CryCriticalSection m_listenerRegistrationLock; + AZStd::recursive_mutex m_listenerRegistrationLock; }; #endif // CRYINCLUDE_CRYSYSTEM_SYSTEMEVENTDISPATCHER_H From ccc4f27129a7a98fe7cab82eb66e44ac23ae9067 Mon Sep 17 00:00:00 2001 From: dmcdiar Date: Tue, 10 Aug 2021 21:09:55 -0700 Subject: [PATCH 277/803] Changed check for latest garbage to a for loop. Signed-off-by: dmcdiar --- Gems/Atom/RHI/Code/Include/Atom/RHI/ObjectCollector.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/ObjectCollector.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/ObjectCollector.h index 3f9fed056f..cd8a85a385 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/ObjectCollector.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/ObjectCollector.h @@ -180,15 +180,16 @@ namespace AZ m_pendingGarbage.push_back({ AZStd::move(m_pendingObjects), m_currentIteration }); } - if (m_pendingNotifies.size()) + if (!m_pendingNotifies.empty()) { - if (m_pendingGarbage.size()) + if (!m_pendingGarbage.empty()) { // find the newest garbage entry and add any pending notifies Garbage& latestGarbage = m_pendingGarbage.front(); size_t latestGarbageAge = m_currentIteration - latestGarbage.m_collectIteration; - size_t i = 1; - while (i < m_pendingGarbage.size()) + + // check the rest of the entries to see if they are newer + for (size_t i = 1; i < m_pendingGarbage.size(); ++i) { size_t age = m_currentIteration - m_pendingGarbage[i].m_collectIteration; if (age < latestGarbageAge) From 6f2b7baae8032203e5466384c255e1e3ea5bbda3 Mon Sep 17 00:00:00 2001 From: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> Date: Tue, 10 Aug 2021 21:27:22 -0700 Subject: [PATCH 278/803] [redcode/crythread-2nd-pass] removed CryThread*.h files Signed-off-by: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> --- Code/Editor/Include/IObjectManager.h | 1 + Code/Editor/Objects/ObjectLoader.h | 2 + Code/Editor/QtUtil.h | 1 + Code/Editor/Util/FileUtil.h | 1 - Code/Editor/Util/Variable.h | 2 + Code/Legacy/CryCommon/CryThread.h | 110 ---------- Code/Legacy/CryCommon/CryThreadImpl.h | 29 --- Code/Legacy/CryCommon/CryThreadImpl_windows.h | 78 ------- Code/Legacy/CryCommon/CryThread_pthreads.h | 199 ------------------ Code/Legacy/CryCommon/CryThread_windows.h | 95 --------- Code/Legacy/CryCommon/Synchronization.h | 1 - Code/Legacy/CryCommon/crycommon_files.cmake | 5 - Code/Legacy/CryCommon/platform.h | 1 - Code/Legacy/CryCommon/platform_impl.cpp | 4 - Code/Legacy/CrySystem/Log.h | 1 - Code/Legacy/CrySystem/SystemEventDispatcher.h | 1 + 16 files changed, 7 insertions(+), 524 deletions(-) delete mode 100644 Code/Legacy/CryCommon/CryThread.h delete mode 100644 Code/Legacy/CryCommon/CryThreadImpl.h delete mode 100644 Code/Legacy/CryCommon/CryThreadImpl_windows.h delete mode 100644 Code/Legacy/CryCommon/CryThread_pthreads.h delete mode 100644 Code/Legacy/CryCommon/CryThread_windows.h diff --git a/Code/Editor/Include/IObjectManager.h b/Code/Editor/Include/IObjectManager.h index ce9d69681b..efc1955a56 100644 --- a/Code/Editor/Include/IObjectManager.h +++ b/Code/Editor/Include/IObjectManager.h @@ -14,6 +14,7 @@ #include #include #include +#include // forward declarations. class CEntityObject; diff --git a/Code/Editor/Objects/ObjectLoader.h b/Code/Editor/Objects/ObjectLoader.h index ccfaeb78f0..fc526970dd 100644 --- a/Code/Editor/Objects/ObjectLoader.h +++ b/Code/Editor/Objects/ObjectLoader.h @@ -15,6 +15,8 @@ #include "Util/GuidUtil.h" #include "ErrorReport.h" +#include + class CPakFile; class CErrorRecord; struct IObjectManager; diff --git a/Code/Editor/QtUtil.h b/Code/Editor/QtUtil.h index bb1f8ba427..69fe03baa1 100644 --- a/Code/Editor/QtUtil.h +++ b/Code/Editor/QtUtil.h @@ -12,6 +12,7 @@ #include #include #include "UnicodeFunctions.h" +#include #include #include diff --git a/Code/Editor/Util/FileUtil.h b/Code/Editor/Util/FileUtil.h index 3be66d6e96..6b2800dd27 100644 --- a/Code/Editor/Util/FileUtil.h +++ b/Code/Editor/Util/FileUtil.h @@ -9,7 +9,6 @@ #pragma once -#include "CryThread.h" #include "StringUtils.h" #include "../Include/SandboxAPI.h" #include diff --git a/Code/Editor/Util/Variable.h b/Code/Editor/Util/Variable.h index 83afee0924..ecd54e42ae 100644 --- a/Code/Editor/Util/Variable.h +++ b/Code/Editor/Util/Variable.h @@ -22,6 +22,8 @@ AZ_PUSH_DISABLE_WARNING(4458, "-Wunknown-warning-option") AZ_POP_DISABLE_WARNING #include +#include + inline const char* to_c_str(const char* str) { return str; } #define MAX_VAR_STRING_LENGTH 4096 diff --git a/Code/Legacy/CryCommon/CryThread.h b/Code/Legacy/CryCommon/CryThread.h deleted file mode 100644 index fcd7be16ba..0000000000 --- a/Code/Legacy/CryCommon/CryThread.h +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - -// Description : Public include file for the multi-threading API. - - -#pragma once - - -// Include basic multithread primitives. -#include "MultiThread.h" -#include "BitFiddling.h" -#include -////////////////////////////////////////////////////////////////////////// -// Lock types: -// -// CRYLOCK_FAST -// A fast potentially (non-recursive) mutex. -// CRYLOCK_RECURSIVE -// A recursive mutex. -////////////////////////////////////////////////////////////////////////// -enum CryLockType -{ - CRYLOCK_FAST = 1, - CRYLOCK_RECURSIVE = 2, -}; - -#define CRYLOCK_HAVE_FASTLOCK 1 - -///////////////////////////////////////////////////////////////////////////// -// -// Primitive locks and conditions. -// -// Primitive locks are represented by instance of class CryLockT -// -// -template -class CryLockT -{ - /* Unsupported lock type. */ -}; - -////////////////////////////////////////////////////////////////////////// -// Typedefs. -////////////////////////////////////////////////////////////////////////// -typedef CryLockT CryCriticalSection; -typedef CryLockT CryCriticalSectionNonRecursive; -////////////////////////////////////////////////////////////////////////// - - -////////////////////////////////////////////////////////////////////////// -// -// CryAutoCriticalSection implements a helper class to automatically -// lock critical section in constructor and release on destructor. -// -////////////////////////////////////////////////////////////////////////// -template -class CryAutoLock -{ -private: - LockClass* m_pLock; - - CryAutoLock(); - CryAutoLock(const CryAutoLock&); - CryAutoLock& operator = (const CryAutoLock&); - -public: - CryAutoLock(LockClass& Lock) - : m_pLock(&Lock) { m_pLock->Lock(); } - CryAutoLock(const LockClass& Lock) - : m_pLock(const_cast(&Lock)) { m_pLock->Lock(); } - ~CryAutoLock() { m_pLock->Unlock(); } -}; - -////////////////////////////////////////////////////////////////////////// -// -// Auto critical section is the most commonly used type of auto lock. -// -////////////////////////////////////////////////////////////////////////// -typedef CryAutoLock CryAutoCriticalSection; - -/////////////////////////////////////////////////////////////////////////////// -// Include architecture specific code. -#if AZ_LEGACY_CRYCOMMON_TRAIT_USE_PTHREADS -#include -#define AZ_RESTRICTED_SECTION_IMPLEMENTED -#elif defined(WIN32) || defined(WIN64) -#include -#define AZ_RESTRICTED_SECTION_IMPLEMENTED -#elif defined(AZ_RESTRICTED_PLATFORM) - #include AZ_RESTRICTED_FILE(CryThread_h) -#endif -#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED) -#undef AZ_RESTRICTED_SECTION_IMPLEMENTED -#else -// Put other platform specific includes here! -#endif - -#if !defined _CRYTHREAD_CONDLOCK_GLITCH -typedef CryLockT CryMutex; -#endif // !_CRYTHREAD_CONDLOCK_GLITCH - -// Include all multithreading containers. -#include "MultiThread_Containers.h" diff --git a/Code/Legacy/CryCommon/CryThreadImpl.h b/Code/Legacy/CryCommon/CryThreadImpl.h deleted file mode 100644 index 4ff2cc6438..0000000000 --- a/Code/Legacy/CryCommon/CryThreadImpl.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - -#pragma once - - -#include - -// Include architecture specific code. -#if defined(LINUX) || defined(APPLE) -// noting to include -#define AZ_RESTRICTED_SECTION_IMPLEMENTED -#elif defined(WIN32) || defined(WIN64) -#include -#define AZ_RESTRICTED_SECTION_IMPLEMENTED -#elif defined(AZ_RESTRICTED_PLATFORM) - #include AZ_RESTRICTED_FILE(CryThreadImpl_h) -#endif -#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED) -#undef AZ_RESTRICTED_SECTION_IMPLEMENTED -#else -// Put other platform specific includes here! -#endif diff --git a/Code/Legacy/CryCommon/CryThreadImpl_windows.h b/Code/Legacy/CryCommon/CryThreadImpl_windows.h deleted file mode 100644 index 9157bde9bc..0000000000 --- a/Code/Legacy/CryCommon/CryThreadImpl_windows.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - -#pragma once - -#include -#include // for CreateSemaphore - - -////////////////////////////////////////////////////////////////////////// -// CryLock_WinMutex -////////////////////////////////////////////////////////////////////////// - -////////////////////////////////////////////////////////////////////////// -CryLock_WinMutex::CryLock_WinMutex() - : m_hdl(CreateMutex(NULL, FALSE, NULL)) {} -CryLock_WinMutex::~CryLock_WinMutex() -{ - CloseHandle(m_hdl); -} - -////////////////////////////////////////////////////////////////////////// -void CryLock_WinMutex::Lock() -{ - WaitForSingleObject(m_hdl, INFINITE); -} - -////////////////////////////////////////////////////////////////////////// -void CryLock_WinMutex::Unlock() -{ - ReleaseMutex(m_hdl); -} - -////////////////////////////////////////////////////////////////////////// -bool CryLock_WinMutex::TryLock() -{ - return WaitForSingleObject(m_hdl, 0) != WAIT_TIMEOUT; -} - -////////////////////////////////////////////////////////////////////////// -// CryLock_CritSection -////////////////////////////////////////////////////////////////////////// - -////////////////////////////////////////////////////////////////////////// -CryLock_CritSection::CryLock_CritSection() -{ - InitializeCriticalSection((CRITICAL_SECTION*)&m_cs); -} - -////////////////////////////////////////////////////////////////////////// -CryLock_CritSection::~CryLock_CritSection() -{ - DeleteCriticalSection((CRITICAL_SECTION*)&m_cs); -} - -////////////////////////////////////////////////////////////////////////// -void CryLock_CritSection::Lock() -{ - EnterCriticalSection((CRITICAL_SECTION*)&m_cs); -} - -////////////////////////////////////////////////////////////////////////// -void CryLock_CritSection::Unlock() -{ - LeaveCriticalSection((CRITICAL_SECTION*)&m_cs); -} - -////////////////////////////////////////////////////////////////////////// -bool CryLock_CritSection::TryLock() -{ - return TryEnterCriticalSection((CRITICAL_SECTION*)&m_cs) != FALSE; -} diff --git a/Code/Legacy/CryCommon/CryThread_pthreads.h b/Code/Legacy/CryCommon/CryThread_pthreads.h deleted file mode 100644 index 9e04784f3f..0000000000 --- a/Code/Legacy/CryCommon/CryThread_pthreads.h +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - -#pragma once - -#include - - -#include -#include -#include -#include -#include - -#include -#include -#include - -// Section dictionary -#if defined(AZ_RESTRICTED_PLATFORM) -#define CRYTHREAD_PTHREADS_H_SECTION_REGISTER_THREAD 1 -#define CRYTHREAD_PTHREADS_H_SECTION_TRAITS 2 -#define CRYTHREAD_PTHREADS_H_SECTION_PTHREADCOND 3 -#define CRYTHREAD_PTHREADS_H_SECTION_SEMAPHORE_CONSTRUCT 4 -#define CRYTHREAD_PTHREADS_H_SECTION_SEMAPHORE_DESTROY 5 -#define CRYTHREAD_PTHREADS_H_SECTION_SEMAPHORE_ACQUIRE 6 -#define CRYTHREAD_PTHREADS_H_SECTION_SEMAPHORE_RELEASE 7 -#define CRYTHREAD_PTHREADS_H_SECTION_TRY_RLOCK 8 -#define CRYTHREAD_PTHREADS_H_SECTION_TRY_WLOCK 9 -#define CRYTHREAD_PTHREADS_H_SECTION_START_RUNNABLE 10 -#define CRYTHREAD_PTHREADS_H_SECTION_START_CPUMASK 11 -#define CRYTHREAD_PTHREADS_H_SECTION_START_CPUMASK_POSTCREATE 12 -#define CRYTHREAD_PTHREADS_H_SECTION_SETCPUMASK 13 -#define CRYTHREAD_PTHREADS_H_SECTION_START_RUNNABLE_CPUMASK_POSTCREATE 14 -#endif - -#if defined(AZ_RESTRICTED_PLATFORM) - #define AZ_RESTRICTED_SECTION CRYTHREAD_PTHREADS_H_SECTION_REGISTER_THREAD - #include AZ_RESTRICTED_FILE(CryThread_pthreads_h) -#endif -#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED) - #undef AZ_RESTRICTED_SECTION_IMPLEMENTED -#endif - -#if defined(APPLE) || defined(ANDROID) -// PTHREAD_MUTEX_FAST_NP is only defined by Pthreads-w32, thus not on MAC - #define PTHREAD_MUTEX_FAST_NP PTHREAD_MUTEX_NORMAL -#endif - -#if !defined _CRYTHREAD_HAVE_LOCK -template -class _PthreadLockBase; - -template -class _PthreadLockAttr -{ - friend class _PthreadLockBase; - -protected: - _PthreadLockAttr() - { - pthread_mutexattr_init(&m_Attr); - pthread_mutexattr_settype(&m_Attr, PthreadMutexType); - } - ~_PthreadLockAttr() - { - pthread_mutexattr_destroy(&m_Attr); - } - pthread_mutexattr_t m_Attr; -}; - -template -class _PthreadLockBase -{ -protected: - static pthread_mutexattr_t& GetAttr() - { - static _PthreadLockAttr m_Attr; - return m_Attr.m_Attr; - } -}; - -template -class _PthreadLock - : public _PthreadLockBase -{ - //#if defined(_DEBUG) -public: - //#endif - pthread_mutex_t m_Lock; - -public: - _PthreadLock() - : LockCount(0) - { - pthread_mutex_init( - &m_Lock, - &_PthreadLockBase::GetAttr()); - } - ~_PthreadLock() { pthread_mutex_destroy(&m_Lock); } - - void Lock() { pthread_mutex_lock(&m_Lock); CryInterlockedIncrement(&LockCount); } - - bool TryLock() - { - const int rc = pthread_mutex_trylock(&m_Lock); - if (0 == rc) - { - CryInterlockedIncrement(&LockCount); - return true; - } - return false; - } - - void Unlock() { CryInterlockedDecrement(&LockCount); pthread_mutex_unlock(&m_Lock); } - - // Get the POSIX pthread_mutex_t. - // Warning: - // This method will not be available in the Win32 port of CryThread. - pthread_mutex_t& Get_pthread_mutex_t() { return m_Lock; } - - bool IsLocked() - { -#if defined(LINUX) || defined(APPLE) - // implementation taken from CrysisWars - return LockCount > 0; -#else - return true; -#endif - } - -private: - volatile int LockCount; -}; - -#if defined CRYLOCK_HAVE_FASTLOCK - #if defined(_DEBUG) && defined(PTHREAD_MUTEX_ERRORCHECK_NP) -template<> -class CryLockT - : public _PthreadLock, PTHREAD_MUTEX_ERRORCHECK_NP> - #else -template<> -class CryLockT - : public _PthreadLock, PTHREAD_MUTEX_FAST_NP> - #endif -{ - CryLockT(const CryLockT&); - void operator = (const CryLockT&); - -public: - CryLockT() { } -}; -#endif // CRYLOCK_HAVE_FASTLOCK - -template<> -class CryLockT - : public _PthreadLock, PTHREAD_MUTEX_RECURSIVE> -{ - CryLockT(const CryLockT&); - void operator = (const CryLockT&); - -public: - CryLockT() { } -}; - -#if defined(AZ_RESTRICTED_PLATFORM) - #define AZ_RESTRICTED_SECTION CRYTHREAD_PTHREADS_H_SECTION_TRAITS - #include AZ_RESTRICTED_FILE(CryThread_pthreads_h) -#else -#if !defined(LINUX) && !defined(APPLE) -#define CRYTHREAD_PTHREADS_H_TRAIT_DEFINE_CRYMUTEX 1 -#endif -#endif - -#if CRYTHREAD_PTHREADS_H_TRAIT_DEFINE_CRYMUTEX -#if defined CRYLOCK_HAVE_FASTLOCK -class CryMutex - : public CryLockT -{ -}; -#else -class CryMutex - : public CryLockT -{ -}; -#endif -#endif // CRYTHREAD_PTHREADS_TRAIT_DEFINE_CRYMUTEX - -#define _CRYTHREAD_HAVE_LOCK 1 - -#endif // !defined _CRYTHREAD_HAVE_LOCK - -#include "MemoryAccess.h" diff --git a/Code/Legacy/CryCommon/CryThread_windows.h b/Code/Legacy/CryCommon/CryThread_windows.h deleted file mode 100644 index 5f83aa48e0..0000000000 --- a/Code/Legacy/CryCommon/CryThread_windows.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - -#pragma once - -#include - -#if defined(AZ_RESTRICTED_PLATFORM) -#undef AZ_RESTRICTED_SECTION -#define CRYTHREAD_WINDOWS_H_SECTION_1 1 -#define CRYTHREAD_WINDOWS_H_SECTION_2 2 -#endif - -////////////////////////////////////////////////////////////////////////// - -////////////////////////////////////////////////////////////////////////// -// from winnt.h -struct CRY_CRITICAL_SECTION -{ - void* DebugInfo; - long LockCount; - long RecursionCount; - threadID OwningThread; - void* LockSemaphore; - unsigned long* SpinCount; // force size on 64-bit systems when packed -}; - -////////////////////////////////////////////////////////////////////////// - -// kernel mutex - don't use... use CryMutex instead -class CryLock_WinMutex -{ -public: - CryLock_WinMutex(); - ~CryLock_WinMutex(); - - void Lock(); - void Unlock(); - bool TryLock(); - - void* _get_win32_handle() { return m_hdl; } - -private: - CryLock_WinMutex(const CryLock_WinMutex&); - CryLock_WinMutex& operator = (const CryLock_WinMutex&); - -private: - void* m_hdl; -}; - -// critical section... don't use... use CryCriticalSection instead -class CryLock_CritSection -{ -public: - CryLock_CritSection(); - ~CryLock_CritSection(); - - void Lock(); - void Unlock(); - bool TryLock(); - - bool IsLocked() - { - return m_cs.RecursionCount > 0 && m_cs.OwningThread == CryGetCurrentThreadId(); - } - -private: - CryLock_CritSection(const CryLock_CritSection&); - CryLock_CritSection& operator = (const CryLock_CritSection&); - -private: - CRY_CRITICAL_SECTION m_cs; -}; - -template <> -class CryLockT - : public CryLock_CritSection -{ -}; -template <> -class CryLockT - : public CryLock_CritSection -{ -}; -class CryMutex - : public CryLock_WinMutex -{ -}; -#define _CRYTHREAD_CONDLOCK_GLITCH 1 diff --git a/Code/Legacy/CryCommon/Synchronization.h b/Code/Legacy/CryCommon/Synchronization.h index 4caa466cb8..3bac215998 100644 --- a/Code/Legacy/CryCommon/Synchronization.h +++ b/Code/Legacy/CryCommon/Synchronization.h @@ -22,7 +22,6 @@ //--------------------------------------------------------------------------- #include "MultiThread.h" -#include "CryThread.h" namespace stl { diff --git a/Code/Legacy/CryCommon/crycommon_files.cmake b/Code/Legacy/CryCommon/crycommon_files.cmake index 487d08b13c..d9d4493632 100644 --- a/Code/Legacy/CryCommon/crycommon_files.cmake +++ b/Code/Legacy/CryCommon/crycommon_files.cmake @@ -89,8 +89,6 @@ set(FILES CrySizer.h CryString.h CrySystemBus.h - CryThread.h - CryThreadImpl.h CryTypeInfo.h CryVersion.h FrameProfiler.h @@ -160,9 +158,6 @@ set(FILES CryAssert_Mac.h CryLibrary.cpp CryLibrary.h - CryThread_pthreads.h - CryThread_windows.h - CryThreadImpl_windows.h CryWindows.h Linux32Specific.h Linux64Specific.h diff --git a/Code/Legacy/CryCommon/platform.h b/Code/Legacy/CryCommon/platform.h index 851da316e0..9f6e8b212d 100644 --- a/Code/Legacy/CryCommon/platform.h +++ b/Code/Legacy/CryCommon/platform.h @@ -732,7 +732,6 @@ typedef int socklen_t; // Include MultiThreading support. -#include "CryThread.h" #include "MultiThread.h" // In RELEASE disable printf and fprintf diff --git a/Code/Legacy/CryCommon/platform_impl.cpp b/Code/Legacy/CryCommon/platform_impl.cpp index 09d7493ae7..e16b18bc06 100644 --- a/Code/Legacy/CryCommon/platform_impl.cpp +++ b/Code/Legacy/CryCommon/platform_impl.cpp @@ -38,10 +38,6 @@ struct SSystemGlobalEnvironment* gEnv = nullptr; #include AZ_RESTRICTED_FILE(platform_impl_h) #endif -////////////////////////////////////////////////////////////////////////// -// If not in static library. -#include - #if defined(WIN32) || defined(WIN64) void CryPureCallHandler() { diff --git a/Code/Legacy/CrySystem/Log.h b/Code/Legacy/CrySystem/Log.h index d6b6dcea3e..447186e613 100644 --- a/Code/Legacy/CrySystem/Log.h +++ b/Code/Legacy/CrySystem/Log.h @@ -10,7 +10,6 @@ #pragma once #include -#include #include #include diff --git a/Code/Legacy/CrySystem/SystemEventDispatcher.h b/Code/Legacy/CrySystem/SystemEventDispatcher.h index a5d33b2542..550292add7 100644 --- a/Code/Legacy/CrySystem/SystemEventDispatcher.h +++ b/Code/Legacy/CrySystem/SystemEventDispatcher.h @@ -14,6 +14,7 @@ #include #include +#include class CSystemEventDispatcher : public ISystemEventDispatcher From adf7a34ef58196fac2863509d35077efb19a050e Mon Sep 17 00:00:00 2001 From: antonmic <56370189+antonmic@users.noreply.github.com> Date: Tue, 10 Aug 2021 23:07:23 -0700 Subject: [PATCH 279/803] Got PassBuilder shader dependency working and removed critical flag from shader builder Signed-off-by: antonmic <56370189+antonmic@users.noreply.github.com> --- .../Editor/ShaderVariantAssetBuilder.cpp | 2 +- .../AuxGeom/DynamicPrimitiveProcessor.cpp | 2 +- .../Source/AuxGeom/FixedShapeProcessor.cpp | 4 +- .../DiffuseProbeGridBlendDistancePass.cpp | 2 +- .../DiffuseProbeGridBlendIrradiancePass.cpp | 2 +- .../DiffuseProbeGridBorderUpdatePass.cpp | 2 +- .../DiffuseProbeGridClassificationPass.cpp | 2 +- .../DiffuseProbeGridFeatureProcessor.cpp | 2 +- .../DiffuseProbeGridRayTracingPass.cpp | 6 +- .../DiffuseProbeGridRelocationPass.cpp | 2 +- .../DiffuseProbeGridRenderPass.cpp | 2 +- .../Common/Code/Source/ImGui/ImGuiPass.cpp | 2 +- .../ReflectionProbeFeatureProcessor.cpp | 2 +- .../ReflectionScreenSpaceBlurPass.cpp | 4 +- .../Code/Include/Atom/RPI.Public/RPIUtils.h | 4 +- .../Source/RPI.Builders/Pass/PassBuilder.cpp | 127 +++++++----------- .../RPI.Public/Pass/AttachmentReadback.cpp | 2 +- .../RPI/Code/Source/RPI.Public/RPIUtils.cpp | 28 +++- Gems/LyShine/Code/Source/Draw2d.cpp | 2 +- Gems/LyShine/Code/Source/UiRenderer.cpp | 2 +- 20 files changed, 103 insertions(+), 98 deletions(-) diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp index ee02ae8452..1da4623774 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp @@ -321,7 +321,7 @@ namespace AZ AssetBuilderSDK::JobDescriptor jobDescriptor; jobDescriptor.m_priority = -5000; - jobDescriptor.m_critical = true; + jobDescriptor.m_critical = false; jobDescriptor.m_jobKey = ShaderVariantAssetBuilderJobKey; jobDescriptor.SetPlatformIdentifier(info.m_identifier.data()); diff --git a/Gems/Atom/Feature/Common/Code/Source/AuxGeom/DynamicPrimitiveProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/AuxGeom/DynamicPrimitiveProcessor.cpp index ea726dd914..3a7d50d2a9 100644 --- a/Gems/Atom/Feature/Common/Code/Source/AuxGeom/DynamicPrimitiveProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/AuxGeom/DynamicPrimitiveProcessor.cpp @@ -322,7 +322,7 @@ namespace AZ { const char* auxGeomWorldShaderFilePath = "Shaders/auxgeom/auxgeomworld.azshader"; - m_shader = RPI::LoadShader(auxGeomWorldShaderFilePath); + m_shader = RPI::LoadCriticalShader(auxGeomWorldShaderFilePath); if (!m_shader) { AZ_Error("DynamicPrimitiveProcessor", false, "Failed to get shader"); diff --git a/Gems/Atom/Feature/Common/Code/Source/AuxGeom/FixedShapeProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/AuxGeom/FixedShapeProcessor.cpp index 63feee115d..f2b3a93a53 100644 --- a/Gems/Atom/Feature/Common/Code/Source/AuxGeom/FixedShapeProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/AuxGeom/FixedShapeProcessor.cpp @@ -1385,9 +1385,9 @@ namespace AZ const char* litObjectShaderFilePath = "Shaders/auxgeom/auxgeomobjectlit.azshader"; // constant color shader - m_unlitShader = RPI::LoadShader(unlitObjectShaderFilePath); + m_unlitShader = RPI::LoadCriticalShader(unlitObjectShaderFilePath); // direction light shader - m_litShader = RPI::LoadShader(litObjectShaderFilePath); + m_litShader = RPI::LoadCriticalShader(litObjectShaderFilePath); if (m_unlitShader.get() == nullptr || m_litShader == nullptr) { diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBlendDistancePass.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBlendDistancePass.cpp index 5fe472c7f8..a3927b802d 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBlendDistancePass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBlendDistancePass.cpp @@ -38,7 +38,7 @@ namespace AZ // load shader // Note: the shader may not be available on all platforms AZStd::string shaderFilePath = "Shaders/DiffuseGlobalIllumination/DiffuseProbeGridBlendDistance.azshader"; - m_shader = RPI::LoadShader(shaderFilePath); + m_shader = RPI::LoadCriticalShader(shaderFilePath); if (m_shader == nullptr) { return; diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBlendIrradiancePass.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBlendIrradiancePass.cpp index c1b6653024..6ff8bdd867 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBlendIrradiancePass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBlendIrradiancePass.cpp @@ -38,7 +38,7 @@ namespace AZ // load shader // Note: the shader may not be available on all platforms AZStd::string shaderFilePath = "Shaders/DiffuseGlobalIllumination/DiffuseProbeGridBlendIrradiance.azshader"; - m_shader = RPI::LoadShader(shaderFilePath); + m_shader = RPI::LoadCriticalShader(shaderFilePath); if (m_shader == nullptr) { return; diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBorderUpdatePass.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBorderUpdatePass.cpp index 0d47b3bd54..ddfe0f11b1 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBorderUpdatePass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBorderUpdatePass.cpp @@ -51,7 +51,7 @@ namespace AZ { // load shader // Note: the shader may not be available on all platforms - shader = RPI::LoadShader(shaderFilePath); + shader = RPI::LoadCriticalShader(shaderFilePath); if (shader == nullptr) { return; diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridClassificationPass.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridClassificationPass.cpp index bb7f87cc61..4c6b07d780 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridClassificationPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridClassificationPass.cpp @@ -42,7 +42,7 @@ namespace AZ // load shader // Note: the shader may not be available on all platforms AZStd::string shaderFilePath = "Shaders/DiffuseGlobalIllumination/DiffuseProbeGridClassification.azshader"; - m_shader = RPI::LoadShader(shaderFilePath); + m_shader = RPI::LoadCriticalShader(shaderFilePath); if (m_shader == nullptr) { return; diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridFeatureProcessor.cpp index f4df4f126a..378e1923f7 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridFeatureProcessor.cpp @@ -74,7 +74,7 @@ namespace AZ // load shader // Note: the shader may not be available on all platforms - Data::Instance shader = RPI::LoadShader("Shaders/DiffuseGlobalIllumination/DiffuseProbeGridRender.azshader"); + Data::Instance shader = RPI::LoadCriticalShader("Shaders/DiffuseGlobalIllumination/DiffuseProbeGridRender.azshader"); if (shader) { m_probeGridRenderData.m_drawListTag = shader->GetDrawListTag(); diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRayTracingPass.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRayTracingPass.cpp index dd8985935f..958823ef91 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRayTracingPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRayTracingPass.cpp @@ -52,7 +52,7 @@ namespace AZ // load the ray tracing shader // Note: the shader may not be available on all platforms AZStd::string shaderFilePath = "Shaders/DiffuseGlobalIllumination/DiffuseProbeGridRayTracing.azshader"; - m_rayTracingShader = RPI::LoadShader(shaderFilePath); + m_rayTracingShader = RPI::LoadCriticalShader(shaderFilePath); if (m_rayTracingShader == nullptr) { return; @@ -64,7 +64,7 @@ namespace AZ // closest hit shader AZStd::string closestHitShaderFilePath = "Shaders/DiffuseGlobalIllumination/DiffuseProbeGridRayTracingClosestHit.azshader"; - m_closestHitShader = RPI::LoadShader(closestHitShaderFilePath); + m_closestHitShader = RPI::LoadCriticalShader(closestHitShaderFilePath); auto closestHitShaderVariant = m_closestHitShader->GetVariant(RPI::ShaderAsset::RootShaderVariantStableId); RHI::PipelineStateDescriptorForRayTracing closestHitShaderDescriptor; @@ -72,7 +72,7 @@ namespace AZ // miss shader AZStd::string missShaderFilePath = "Shaders/DiffuseGlobalIllumination/DiffuseProbeGridRayTracingMiss.azshader"; - m_missShader = RPI::LoadShader(missShaderFilePath); + m_missShader = RPI::LoadCriticalShader(missShaderFilePath); auto missShaderVariant = m_missShader->GetVariant(RPI::ShaderAsset::RootShaderVariantStableId); RHI::PipelineStateDescriptorForRayTracing missShaderDescriptor; diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRelocationPass.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRelocationPass.cpp index 56ae50069e..54cf9783cd 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRelocationPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRelocationPass.cpp @@ -42,7 +42,7 @@ namespace AZ // load shader // Note: the shader may not be available on all platforms AZStd::string shaderFilePath = "Shaders/DiffuseGlobalIllumination/DiffuseProbeGridRelocation.azshader"; - m_shader = RPI::LoadShader(shaderFilePath); + m_shader = RPI::LoadCriticalShader(shaderFilePath); if (m_shader == nullptr) { return; diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRenderPass.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRenderPass.cpp index 55d8ca5cba..a4cc101222 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRenderPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRenderPass.cpp @@ -30,7 +30,7 @@ namespace AZ // create the shader resource group // Note: the shader may not be available on all platforms AZStd::string shaderFilePath = "Shaders/DiffuseGlobalIllumination/DiffuseProbeGridRender.azshader"; - m_shader = RPI::LoadShader(shaderFilePath); + m_shader = RPI::LoadCriticalShader(shaderFilePath); if (m_shader == nullptr) { return; diff --git a/Gems/Atom/Feature/Common/Code/Source/ImGui/ImGuiPass.cpp b/Gems/Atom/Feature/Common/Code/Source/ImGui/ImGuiPass.cpp index 821b9c52b4..cd781390a3 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ImGui/ImGuiPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ImGui/ImGuiPass.cpp @@ -446,7 +446,7 @@ namespace AZ } { - m_shader = RPI::LoadShader(ImguiShaderFilePath); + m_shader = RPI::LoadCriticalShader(ImguiShaderFilePath); m_pipelineState = aznew RPI::PipelineStateForDraw; m_pipelineState->Init(m_shader); diff --git a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp index a9078e1dd8..c0e25e3da9 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp @@ -487,7 +487,7 @@ namespace AZ RHI::DrawListTag& drawListTag) { // load shader - shader = RPI::LoadShader(filePath); + shader = RPI::LoadCriticalShader(filePath); AZ_Error("ReflectionProbeFeatureProcessor", shader, "Failed to find asset for shader [%s]", filePath); // store drawlist tag diff --git a/Gems/Atom/Feature/Common/Code/Source/ReflectionScreenSpace/ReflectionScreenSpaceBlurPass.cpp b/Gems/Atom/Feature/Common/Code/Source/ReflectionScreenSpace/ReflectionScreenSpaceBlurPass.cpp index f0f947ba03..4f5caca108 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ReflectionScreenSpace/ReflectionScreenSpaceBlurPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ReflectionScreenSpace/ReflectionScreenSpaceBlurPass.cpp @@ -52,7 +52,7 @@ namespace AZ // load shaders AZStd::string verticalBlurShaderFilePath = "Shaders/Reflections/ReflectionScreenSpaceBlurVertical.azshader"; - Data::Instance verticalBlurShader = RPI::LoadShader(verticalBlurShaderFilePath); + Data::Instance verticalBlurShader = RPI::LoadCriticalShader(verticalBlurShaderFilePath); if (verticalBlurShader == nullptr) { AZ_Error("PassSystem", false, "[ReflectionScreenSpaceBlurPass '%s']: Failed to load shader '%s'!", GetPathName().GetCStr(), verticalBlurShaderFilePath.c_str()); @@ -60,7 +60,7 @@ namespace AZ } AZStd::string horizontalBlurShaderFilePath = "Shaders/Reflections/ReflectionScreenSpaceBlurHorizontal.azshader"; - Data::Instance horizontalBlurShader = RPI::LoadShader(horizontalBlurShaderFilePath); + Data::Instance horizontalBlurShader = RPI::LoadCriticalShader(horizontalBlurShaderFilePath); if (horizontalBlurShader == nullptr) { AZ_Error("PassSystem", false, "[ReflectionScreenSpaceBlurPass '%s']: Failed to load shader '%s'!", GetPathName().GetCStr(), horizontalBlurShaderFilePath.c_str()); diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RPIUtils.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RPIUtils.h index e6d2bdad82..a2972ff0fd 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RPIUtils.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RPIUtils.h @@ -22,19 +22,21 @@ namespace AZ class Shader; //! Get the asset ID for a given shader file path - Data::AssetId GetShaderAssetId(const AZStd::string& shaderFilePath); + Data::AssetId GetShaderAssetId(const AZStd::string& shaderFilePath, bool isCritical = false); //! Finds a shader asset for the given shader asset ID. Optional shaderFilePath param for debugging. Data::Asset FindShaderAsset(Data::AssetId shaderAssetId, const AZStd::string& shaderFilePath = ""); //! Finds a shader asset for the given shader file path Data::Asset FindShaderAsset(const AZStd::string& shaderFilePath); + Data::Asset FindCriticalShaderAsset(const AZStd::string& shaderFilePath); //! Loads a shader for the given shader asset ID. Optional shaderFilePath param for debugging. Data::Instance LoadShader(Data::AssetId shaderAssetId, const AZStd::string& shaderFilePath = ""); //! Loads a shader for the given shader file path Data::Instance LoadShader(const AZStd::string& shaderFilePath); + Data::Instance LoadCriticalShader(const AZStd::string& shaderFilePath); //! Loads a streaming image asset for the given file path Data::Instance LoadStreamingTexture(AZStd::string_view path); diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Pass/PassBuilder.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/Pass/PassBuilder.cpp index f582f3ba04..a803ecf31a 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Pass/PassBuilder.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Pass/PassBuilder.cpp @@ -67,6 +67,7 @@ namespace AZ // --- Code related to dependency shader asset handling --- + // Helper class to pass parameters to the AddDependency and FindReferencedAssets functions below struct FindPassReferenceAssetParams { void* passAssetObject; @@ -77,50 +78,28 @@ namespace AZ const char* jobKey; // Job key for adding job dependency }; - //! Adds all relevant dependencies for a referenced source file, considering that the path might be relative to the original file location or a full asset path. - //! This will usually include multiple source dependencies and a single job dependency, but will include only source dependencies if the file is not found. - //! Note the AssetBuilderSDK::JobDependency::m_platformIdentifier will not be set by this function. The calling code must set this value before passing back - //! to the AssetBuilderSDK::CreateJobsResponse. - void AddPossibleDependencies( - FindPassReferenceAssetParams& params, - AssetBuilderSDK::CreateJobsResponse& response, - AssetBuilderSDK::JobDescriptor& job) + // Helper function to get a file reference and create a corresponding job dependency + void AddDependency(FindPassReferenceAssetParams& params, AssetBuilderSDK::JobDescriptor* job) { - bool dependencyFileFound = false; + AZStd::string_view& file = params.dependencySourceFile; + AZ::Data::AssetInfo sourceInfo; + AZStd::string watchFolder; + bool fileFound = false; + AzToolsFramework::AssetSystemRequestBus::BroadcastResult(fileFound, &AzToolsFramework::AssetSystem::AssetSystemRequest::GetSourceInfoBySourcePath, file.data(), sourceInfo, watchFolder); - AZStd::vector possibleDependencies = RPI::AssetUtils::GetPossibleDepenencyPaths(params.passAssetSourceFile, params.dependencySourceFile); - for (auto& file : possibleDependencies) + if (fileFound) { - AssetBuilderSDK::SourceFileDependency sourceFileDependency; - sourceFileDependency.m_sourceFileDependencyPath = file; - response.m_sourceFileDependencyList.push_back(sourceFileDependency); - - // The first path found is the highest priority, and will have a job dependency, as this is the one - // the builder will actually use - if (!dependencyFileFound) - { - AZ::Data::AssetInfo sourceInfo; - AZStd::string watchFolder; - AzToolsFramework::AssetSystemRequestBus::BroadcastResult(dependencyFileFound, &AzToolsFramework::AssetSystem::AssetSystemRequest::GetSourceInfoBySourcePath, file.c_str(), sourceInfo, watchFolder); - - if (dependencyFileFound) - { - AssetBuilderSDK::JobDependency jobDependency; - jobDependency.m_jobKey = params.jobKey; - jobDependency.m_type = AssetBuilderSDK::JobDependencyType::Order; - jobDependency.m_sourceFile.m_sourceFileDependencyPath = file; - job.m_jobDependencyList.push_back(jobDependency); - } - } + AssetBuilderSDK::JobDependency jobDependency; + jobDependency.m_jobKey = params.jobKey; + jobDependency.m_type = AssetBuilderSDK::JobDependencyType::Order; + jobDependency.m_sourceFile.m_sourceFileDependencyPath = file; + job->m_jobDependencyList.push_back(jobDependency); + AZ_TracePrintf(PassBuilderName, "Creating job dependency on file [%s] \n", file.data()); } } // Helper function to find all assetId's and object references - bool FindPassReferencedAssets(FindPassReferenceAssetParams& params, - AZStd::unordered_set& referencedAssetList, - AssetBuilderSDK::CreateJobsResponse& response, - AssetBuilderSDK::JobDescriptor& job, - bool jobCreationPhase) + bool FindReferencedAssets(FindPassReferenceAssetParams& params, AssetBuilderSDK::JobDescriptor* job) { SerializeContext::ErrorHandler errorLogger; errorLogger.Reset(); @@ -141,10 +120,10 @@ namespace AZ const AZStd::string& path = assetReference->m_filePath; uint32_t subId = 0; - if (jobCreationPhase) + if (job != nullptr) // Create Job Phase { params.dependencySourceFile = path; - AddPossibleDependencies(params, response, job); + AddDependency(params, job); } else // Process Job Phase { @@ -161,12 +140,6 @@ namespace AZ } } } - - // If the asset ID is valid, add it as a dependency - if (assetReference->m_assetId.IsValid()) - { - referencedAssetList.insert(assetReference->m_assetId); - } } return true; }; @@ -196,15 +169,16 @@ namespace AZ void PassBuilder::CreateJobs(const AssetBuilderSDK::CreateJobsRequest& request, AssetBuilderSDK::CreateJobsResponse& response) const { + // --- Handle shutdown case --- + if (m_isShuttingDown) { response.m_result = AssetBuilderSDK::CreateJobsResultCode::ShuttingDown; return; } - AssetBuilderSDK::JobDescriptor job; + // --- Get serialization context --- - // Get serialization context SerializeContext* serializeContext = nullptr; ComponentApplicationBus::BroadcastResult(serializeContext, &ComponentApplicationBus::Events::GetSerializeContext); if (!serializeContext) @@ -213,7 +187,8 @@ namespace AZ return; } - // Load PassAsset + // --- Load PassAsset --- + AZStd::string fullPath; AzFramework::StringFunc::Path::ConstructFull(request.m_watchFolder.c_str(), request.m_sourceFile.c_str(), fullPath, true); @@ -227,7 +202,12 @@ namespace AZ return; } - // Find all Asset IDs we depend on + AssetBuilderSDK::JobDescriptor job; + job.m_jobKey = PassBuilderJobKey; + job.m_critical = true; // Passes are a critical part of the rendering system + + // --- Find all dependencies --- + AZStd::unordered_set dependentList; Uuid passAssetUuid = AzTypeInfo::Uuid(); @@ -238,30 +218,30 @@ namespace AZ params.serializeContext = serializeContext; params.jobKey = "Shader Asset"; - if (!FindPassReferencedAssets(params, dependentList, response, job, true)) + if (!FindReferencedAssets(params, &job)) { return; } + // --- Create a job per platform --- + for (const AssetBuilderSDK::PlatformInfo& platformInfo : request.m_enabledPlatforms) { - job.m_jobKey = PassBuilderJobKey; + for (auto& jobDependency : job.m_jobDependencyList) + { + jobDependency.m_platformIdentifier = platformInfo.m_identifier.c_str(); + } job.SetPlatformIdentifier(platformInfo.m_identifier.c_str()); - - // Passes are a critical part of the rendering system - job.m_critical = true; - response.m_createJobOutputs.push_back(job); } response.m_result = AssetBuilderSDK::CreateJobsResultCode::Success; } - - void PassBuilder::ProcessJob(const AssetBuilderSDK::ProcessJobRequest& request, AssetBuilderSDK::ProcessJobResponse& response) const { - // Handle job cancellation and shutdown cases + // --- Handle job cancellation and shutdown cases --- + AssetBuilderSDK::JobCancelListener jobCancelListener(request.m_jobId); if (jobCancelListener.IsCancelled() || m_isShuttingDown) { @@ -269,7 +249,8 @@ namespace AZ return; } - // Get serialization context + // --- Get serialization context --- + SerializeContext* serializeContext = nullptr; ComponentApplicationBus::BroadcastResult(serializeContext, &ComponentApplicationBus::Events::GetSerializeContext); if (!serializeContext) @@ -278,7 +259,8 @@ namespace AZ return; } - // Load PassAsset + // --- Load PassAsset --- + PassAsset passAsset; AZ::Outcome loadResult = JsonSerializationUtils::LoadObjectFromFile(passAsset, request.m_fullPath); @@ -289,8 +271,8 @@ namespace AZ return; } - // Find all Asset IDs we depend on - AZStd::unordered_set dependentList; + // --- Find all dependencies --- + Uuid passAssetUuid = AzTypeInfo::Uuid(); FindPassReferenceAssetParams params; @@ -300,21 +282,20 @@ namespace AZ params.serializeContext = serializeContext; params.jobKey = "Shader Asset"; - AssetBuilderSDK::CreateJobsResponse dummyResponse; - AssetBuilderSDK::JobDescriptor dummyJob; - - if (!FindPassReferencedAssets(params, dependentList, dummyResponse, dummyJob, false)) + if (!FindReferencedAssets(params, nullptr)) { return; } - // Get destination file name and path + // --- Get destination file name and path --- + AZStd::string destFileName; AZStd::string destPath; AzFramework::StringFunc::Path::GetFullFileName(request.m_fullPath.c_str(), destFileName); AzFramework::StringFunc::Path::ConstructFull(request.m_tempDirPath.c_str(), destFileName.c_str(), destPath, true); - // Save the asset to binary format for production + // --- Save the asset to binary format for production --- + bool result = Utils::SaveObjectToFile(destPath, DataStream::ST_BINARY, &passAsset, passAssetUuid, serializeContext); if (result == false) { @@ -322,14 +303,10 @@ namespace AZ return; } - // Success. Save output product(s) to response - AssetBuilderSDK::JobProduct jobProduct(destPath, PassAsset::RTTI_Type(), 0); - for (auto& assetId : dependentList) - { - jobProduct.m_dependencies.emplace_back(AssetBuilderSDK::ProductDependency(assetId, 0)); - } + // --- Save output product(s) to response --- - jobProduct.m_dependenciesHandled = true; // We've output the dependencies immediately above so it's OK to tell the AP we've handled dependencies + AssetBuilderSDK::JobProduct jobProduct(destPath, PassAsset::RTTI_Type(), 0); + jobProduct.m_dependenciesHandled = true; response.m_outputProducts.push_back(jobProduct); response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Success; } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/AttachmentReadback.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/AttachmentReadback.cpp index 29a17dc9a8..29af8b7b63 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/AttachmentReadback.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/AttachmentReadback.cpp @@ -121,7 +121,7 @@ namespace AZ // Load shader and srg const char* ShaderPath = "shader/decomposemsimage.azshader"; - m_decomposeShader = LoadShader(ShaderPath); + m_decomposeShader = LoadCriticalShader(ShaderPath); if (m_decomposeShader == nullptr) { diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/RPIUtils.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/RPIUtils.cpp index ebccc87cac..9173b47fad 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/RPIUtils.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/RPIUtils.cpp @@ -8,6 +8,7 @@ #include +#include #include #include @@ -20,7 +21,7 @@ namespace AZ namespace RPI { - Data::AssetId GetShaderAssetId(const AZStd::string& shaderFilePath) + Data::AssetId GetShaderAssetId(const AZStd::string& shaderFilePath, bool isCritical) { Data::AssetId shaderAssetId; @@ -34,6 +35,19 @@ namespace AZ if (!shaderAssetId.IsValid()) { + if (isCritical) + { + Data::Asset shaderAsset = RPI::AssetUtils::LoadCriticalAsset(shaderFilePath); + if (shaderAsset.IsReady()) + { + return shaderAsset.GetId(); + } + else + { + AZ_Error("RPI Utils", false, "Could not load critical shader [%s]", shaderFilePath.c_str()); + } + } + AZ_Error("RPI Utils", false, "Failed to get asset id for shader [%s]", shaderFilePath.c_str()); } @@ -83,11 +97,23 @@ namespace AZ return FindShaderAsset(GetShaderAssetId(shaderFilePath), shaderFilePath); } + Data::Asset FindCriticalShaderAsset(const AZStd::string& shaderFilePath) + { + const bool isCritical = true; + return FindShaderAsset(GetShaderAssetId(shaderFilePath, isCritical), shaderFilePath); + } + Data::Instance LoadShader(const AZStd::string& shaderFilePath) { return LoadShader(GetShaderAssetId(shaderFilePath), shaderFilePath); } + Data::Instance LoadCriticalShader(const AZStd::string& shaderFilePath) + { + const bool isCritical = true; + return LoadShader(GetShaderAssetId(shaderFilePath, isCritical), shaderFilePath); + } + AZ::Data::Instance LoadStreamingTexture(AZStd::string_view path) { AzFramework::AssetSystem::AssetStatus status = AzFramework::AssetSystem::AssetStatus_Unknown; diff --git a/Gems/LyShine/Code/Source/Draw2d.cpp b/Gems/LyShine/Code/Source/Draw2d.cpp index 2d3612fc07..b4c8d58fae 100644 --- a/Gems/LyShine/Code/Source/Draw2d.cpp +++ b/Gems/LyShine/Code/Source/Draw2d.cpp @@ -79,7 +79,7 @@ void CDraw2d::OnBootstrapSceneReady([[maybe_unused]] AZ::RPI::Scene* bootstrapSc // Load the shader to be used for 2d drawing const char* shaderFilepath = "Shaders/SimpleTextured.azshader"; - AZ::Data::Instance shader = AZ::RPI::LoadShader(shaderFilepath); + AZ::Data::Instance shader = AZ::RPI::LoadCriticalShader(shaderFilepath); // Set scene to be associated with the dynamic draw context AZ::RPI::ScenePtr scene; diff --git a/Gems/LyShine/Code/Source/UiRenderer.cpp b/Gems/LyShine/Code/Source/UiRenderer.cpp index 357431c80a..c52c249d20 100644 --- a/Gems/LyShine/Code/Source/UiRenderer.cpp +++ b/Gems/LyShine/Code/Source/UiRenderer.cpp @@ -58,7 +58,7 @@ void UiRenderer::OnBootstrapSceneReady([[maybe_unused]] AZ::RPI::Scene* bootstra // Load the UI shader const char* uiShaderFilepath = "Shaders/LyShineUI.azshader"; - AZ::Data::Instance uiShader = AZ::RPI::LoadShader(uiShaderFilepath); + AZ::Data::Instance uiShader = AZ::RPI::LoadCriticalShader(uiShaderFilepath); // Create scene to be used by the dynamic draw context if (m_viewportContext) From 6a5a7740ad59ef5db87ba08e2c4ceff74851d038 Mon Sep 17 00:00:00 2001 From: Benjamin Jillich <43751992+amzn-jillich@users.noreply.github.com> Date: Wed, 11 Aug 2021 00:45:27 -0700 Subject: [PATCH 280/803] EMotion FX: Selecting Motion Properties crashes the Editor (#3005) Signed-off-by: Benjamin Jillich --- Gems/EMotionFX/Code/MysticQt/Source/DialogStack.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/EMotionFX/Code/MysticQt/Source/DialogStack.cpp b/Gems/EMotionFX/Code/MysticQt/Source/DialogStack.cpp index 27f83b07a3..5e9cf66fa7 100644 --- a/Gems/EMotionFX/Code/MysticQt/Source/DialogStack.cpp +++ b/Gems/EMotionFX/Code/MysticQt/Source/DialogStack.cpp @@ -498,7 +498,7 @@ namespace MysticQt } if (findPreviousMaximizedDialogNeeded) { - for (auto curDialog = AZStd::make_reverse_iterator(dialog) + 1; curDialog != m_dialogs.rend(); ++curDialog) + for (auto curDialog = AZStd::make_reverse_iterator(dialog); curDialog != m_dialogs.rend(); ++curDialog) { if (curDialog->m_maximizeSize && curDialog->m_frame->isHidden() == false) { From 5c90bc0d58f359306352f845a094531b6e184c98 Mon Sep 17 00:00:00 2001 From: Benjamin Jillich <43751992+amzn-jillich@users.noreply.github.com> Date: Wed, 11 Aug 2021 00:45:47 -0700 Subject: [PATCH 281/803] Skip blend shapes that influence multiple meshes (#3009) Signed-off-by: Benjamin Jillich --- .../Source/RPI.Builders/Model/MorphTargetExporter.cpp | 11 ++++++++--- .../MeshOptimizer/MeshOptimizerComponent.cpp | 6 ++++-- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MorphTargetExporter.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MorphTargetExporter.cpp index 0a1fb49ab5..fa437c002f 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MorphTargetExporter.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MorphTargetExporter.cpp @@ -159,9 +159,14 @@ namespace AZ::RPI // Determine the vertex index range for the morph target. const uint32_t numVertices = blendShapeData->GetVertexCount(); - AZ_Assert(blendShapeData->GetVertexCount() == sourceMesh.m_meshData->GetVertexCount(), - "Blend shape (%s) contains more/less vertices (%d) than the neutral mesh (%d).", - blendShapeName.c_str(), numVertices, sourceMesh.m_meshData->GetVertexCount()); + if (blendShapeData->GetVertexCount() != sourceMesh.m_meshData->GetVertexCount()) + { + AZ_Error(ModelAssetBuilderComponent::s_builderName, false, + "Skipping blend shape (%s) as it contains more/less vertices (%d) than the neutral mesh (%d). " + "The blend shape is most likely influencing multiple meshes, which is currently not supported.", + blendShapeName.c_str(), numVertices, sourceMesh.m_meshData->GetVertexCount()); + return; + } // The start index is after any previously added deltas metaData.m_startIndex = aznumeric_cast(packedCompressedMorphTargetVertexData.size()); diff --git a/Gems/SceneProcessing/Code/Source/Generation/Components/MeshOptimizer/MeshOptimizerComponent.cpp b/Gems/SceneProcessing/Code/Source/Generation/Components/MeshOptimizer/MeshOptimizerComponent.cpp index 7541e2fce7..a410c4e6c9 100644 --- a/Gems/SceneProcessing/Code/Source/Generation/Components/MeshOptimizer/MeshOptimizerComponent.cpp +++ b/Gems/SceneProcessing/Code/Source/Generation/Components/MeshOptimizer/MeshOptimizerComponent.cpp @@ -379,10 +379,12 @@ namespace AZ::SceneGenerationComponents auto [optimizedMesh, optimizedUVs, optimizedTangents, optimizedBitangents, optimizedVertexColors, optimizedSkinWeights] = OptimizeMesh(mesh, mesh, uvDatas, tangentDatas, bitangentDatas, colorDatas, skinWeightDatas, meshGroup, hasBlendShapes); - AZ_TracePrintf(AZ::SceneAPI::Utilities::LogWindow, "Base mesh: %zu vertices, optimized mesh: %zu vertices, %0.02f%% of the original", + AZ_TracePrintf(AZ::SceneAPI::Utilities::LogWindow, "Optimized mesh '%s': Original: %zu vertices -> optimized: %zu vertices, %0.02f%% of the original (hasBlendShapes=%s)", + graph.GetNodeName(nodeIndex).GetName(), mesh->GetUsedControlPointCount(), optimizedMesh->GetUsedControlPointCount(), - ((float)optimizedMesh->GetUsedControlPointCount() / (float)mesh->GetUsedControlPointCount()) * 100.0f + ((float)optimizedMesh->GetUsedControlPointCount() / (float)mesh->GetUsedControlPointCount()) * 100.0f, + hasBlendShapes ? "Yes" : "No" ); const NodeIndex optimizedMeshNodeIndex = graph.AddChild(graph.GetNodeParent(nodeIndex), name.c_str(), AZStd::move(optimizedMesh)); From da4dfea9caccf66a3a14072d27a64c66ec9250f5 Mon Sep 17 00:00:00 2001 From: AMZN-AlexOteiza <82234181+AMZN-AlexOteiza@users.noreply.github.com> Date: Wed, 11 Aug 2021 10:15:41 +0100 Subject: [PATCH 282/803] Adjustment to property row so the label is more visible (#2866) Signed-off-by: Garcia Ruiz Co-authored-by: Garcia Ruiz --- .../AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.cpp index 5ea36bb30e..05c04872e3 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.cpp @@ -70,7 +70,7 @@ namespace AzToolsFramework m_leftAreaContainer = new QWidget(this); m_middleAreaContainer = new QWidget(this); - const int minimumControlWidth = 192; + const int minimumControlWidth = 142; m_middleAreaContainer->setMinimumWidth(minimumControlWidth); m_mainLayout->addWidget(m_leftAreaContainer, LabelColumnStretch, Qt::AlignLeft); m_mainLayout->addWidget(m_middleAreaContainer, ValueColumnStretch); From 9ecd0ff9df47b0930d9dacc3fe0dd1860a95ce7f Mon Sep 17 00:00:00 2001 From: AMZN-Alexandre Corcia Aguilera <82398284+aaguilea@users.noreply.github.com> Date: Wed, 11 Aug 2021 10:00:12 +0100 Subject: [PATCH 283/803] Bad Merge fix Signed-off-by: aaguilea --- Code/Editor/editor_lib_files.cmake | 2 -- 1 file changed, 2 deletions(-) diff --git a/Code/Editor/editor_lib_files.cmake b/Code/Editor/editor_lib_files.cmake index b921d4a559..ce11d013dd 100644 --- a/Code/Editor/editor_lib_files.cmake +++ b/Code/Editor/editor_lib_files.cmake @@ -803,8 +803,6 @@ set(FILES EditorViewportCamera.h ViewportManipulatorController.cpp ViewportManipulatorController.h - RenderViewport.cpp - RenderViewport.h TopRendererWnd.cpp TopRendererWnd.h ViewManager.cpp From 3845f430881bcd6770fca90c1c4425cf53d3700c Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Wed, 11 Aug 2021 08:13:38 -0700 Subject: [PATCH 284/803] missing header include after merge Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Framework/AzCore/AzCore/std/string/conversions.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Code/Framework/AzCore/AzCore/std/string/conversions.h b/Code/Framework/AzCore/AzCore/std/string/conversions.h index b7887339e2..be71e12275 100644 --- a/Code/Framework/AzCore/AzCore/std/string/conversions.h +++ b/Code/Framework/AzCore/AzCore/std/string/conversions.h @@ -8,6 +8,7 @@ #pragma once #include +#include #include #include From fbcb6510e68721c19ac17c5618fd1d021514d901 Mon Sep 17 00:00:00 2001 From: sconel <32552662+sconel@users.noreply.github.com> Date: Wed, 11 Aug 2021 10:45:31 -0700 Subject: [PATCH 285/803] Update storage of Prefab Dom info to be best effort (#2862) * Update storage of Prefab Dom info to be best effort Signed-off-by: sconel * Update IssueReporter to Skipped instead of PartialSkip Signed-off-by: sconel * Address PR feedback Signed-off-by: sconel * Fix failing Prefab Unit Test that expected default values to be stripped Signed-off-by: sconel --- .../Instance/InstanceToTemplatePropagator.cpp | 20 +--- .../AzToolsFramework/Prefab/Link/Link.cpp | 3 +- .../Prefab/PrefabDomUtils.cpp | 94 +++++++++++++++---- .../AzToolsFramework/Prefab/PrefabDomUtils.h | 28 ++++-- .../AzToolsFramework/Prefab/PrefabLoader.cpp | 2 +- .../AzToolsFramework/Prefab/PrefabUndo.cpp | 4 +- .../Prefab/Spawnable/EditorInfoRemover.cpp | 2 +- .../Prefab/Spawnable/SpawnableUtils.cpp | 2 +- ...refabInstanceToTemplatePropagatorTests.cpp | 93 ++++++++++++++++++ .../Tests/Prefab/PrefabTestComponent.cpp | 14 +++ .../Tests/Prefab/PrefabTestComponent.h | 18 ++++ .../Tests/Prefab/PrefabTestFixture.cpp | 1 + .../Prefab/PrefabUpdateWithPatchesTests.cpp | 5 +- .../Pipeline/NetworkPrefabProcessor.cpp | 2 +- 14 files changed, 241 insertions(+), 47 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceToTemplatePropagator.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceToTemplatePropagator.cpp index 814c4e2a7f..36b39f3a72 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceToTemplatePropagator.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceToTemplatePropagator.cpp @@ -46,7 +46,6 @@ namespace AzToolsFramework bool InstanceToTemplatePropagator::GenerateDomForEntity(PrefabDom& generatedEntityDom, const AZ::Entity& entity) { - //grab the owning instance so we can use the entityIdMapper in settings InstanceOptionalReference owningInstance = m_instanceEntityMapperInterface->FindOwningInstance(entity.GetId()); if (!owningInstance) @@ -54,19 +53,8 @@ namespace AzToolsFramework AZ_Error("Prefab", false, "Entity does not belong to an instance"); return false; } - - InstanceEntityIdMapper entityIdMapper; - entityIdMapper.SetStoringInstance(owningInstance->get()); - //create settings so that the serialized entity dom undergoes mapping from entity id to entity alias - AZ::JsonSerializerSettings settings; - settings.m_metadata.Add(static_cast(&entityIdMapper)); - - //generate PrefabDom using Json serialization system - AZ::JsonSerializationResult::ResultCode result = AZ::JsonSerialization::Store( - generatedEntityDom, generatedEntityDom.GetAllocator(), entity, settings); - - return result.GetOutcome() == AZ::JsonSerializationResult::Outcomes::Success; + return PrefabDomUtils::StoreEntityInPrefabDomFormat(entity, owningInstance->get(), generatedEntityDom); } bool InstanceToTemplatePropagator::GenerateDomForInstance(PrefabDom& generatedInstanceDom, const Prefab::Instance& instance) @@ -185,8 +173,10 @@ namespace AzToolsFramework else { AZ_Error( - "Prefab", result.GetOutcome() != AZ::JsonSerializationResult::Outcomes::PartialSkip, - "Some of the patches are not successfully applied."); + "Prefab", + (result.GetOutcome() != AZ::JsonSerializationResult::Outcomes::Skipped) && + (result.GetOutcome() != AZ::JsonSerializationResult::Outcomes::PartialSkip), + "Some of the patches were not successfully applied."); m_prefabSystemComponentInterface->SetTemplateDirtyFlag(templateId, true); m_prefabSystemComponentInterface->PropagateTemplateChanges(templateId, instanceToExclude); return true; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Link/Link.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Link/Link.cpp index 3c7e5ff3f8..940a2787cb 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Link/Link.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Link/Link.cpp @@ -196,7 +196,8 @@ namespace AzToolsFramework m_sourceTemplateId, m_targetTemplateId); return false; } - if (applyPatchResult.GetOutcome() == AZ::JsonSerializationResult::Outcomes::PartialSkip) + if (applyPatchResult.GetOutcome() == AZ::JsonSerializationResult::Outcomes::PartialSkip || + applyPatchResult.GetOutcome() == AZ::JsonSerializationResult::Outcomes::Skipped) { AZ_Error( "Prefab", false, diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.cpp index 86983d7912..1ad88e53d2 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.cpp @@ -26,6 +26,30 @@ namespace AzToolsFramework { namespace PrefabDomUtils { + namespace Internal + { + AZ::JsonSerializationResult::ResultCode JsonIssueReporter(AZStd::string& scratchBuffer, + AZStd::string_view message, AZ::JsonSerializationResult::ResultCode result, AZStd::string_view path) + { + namespace JSR = AZ::JsonSerializationResult; + + if (result.GetProcessing() == JSR::Processing::Halted) + { + scratchBuffer.append(message.begin(), message.end()); + scratchBuffer.append("\n Reason: "); + result.AppendToString(scratchBuffer, path); + scratchBuffer.append("."); + AZ_Warning("Prefab Serialization", false, "%s", scratchBuffer.c_str()); + + scratchBuffer.clear(); + + return JSR::ResultCode(result.GetTask(), JSR::Outcomes::Skipped); + } + + return result; + } + } + PrefabDomValueReference FindPrefabDomValue(PrefabDomValue& parentValue, const char* valueName) { PrefabDomValue::MemberIterator valueIterator = parentValue.FindMember(valueName); @@ -48,7 +72,7 @@ namespace AzToolsFramework return valueIterator->value; } - bool StoreInstanceInPrefabDom(const Instance& instance, PrefabDom& prefabDom, StoreInstanceFlags flags) + bool StoreInstanceInPrefabDom(const Instance& instance, PrefabDom& prefabDom, StoreFlags flags) { InstanceEntityIdMapper entityIdMapper; entityIdMapper.SetStoringInstance(instance); @@ -59,11 +83,21 @@ namespace AzToolsFramework settings.m_metadata.Add(static_cast(&entityIdMapper)); settings.m_metadata.Add(&entityIdMapper); - if ((flags & StoreInstanceFlags::StripDefaultValues) != StoreInstanceFlags::StripDefaultValues) + if ((flags & StoreFlags::StripDefaultValues) != StoreFlags::StripDefaultValues) { settings.m_keepDefaults = true; } + AZStd::string scratchBuffer; + auto issueReportingCallback = [&scratchBuffer] + (AZStd::string_view message, AZ::JsonSerializationResult::ResultCode result, + AZStd::string_view path) -> AZ::JsonSerializationResult::ResultCode + { + return Internal::JsonIssueReporter(scratchBuffer, message, result, path); + }; + + settings.m_reporting = AZStd::move(issueReportingCallback); + AZ::JsonSerializationResult::ResultCode result = AZ::JsonSerialization::Store(prefabDom, prefabDom.GetAllocator(), instance, settings); @@ -80,7 +114,38 @@ namespace AzToolsFramework return true; } - bool LoadInstanceFromPrefabDom(Instance& instance, const PrefabDom& prefabDom, LoadInstanceFlags flags) + bool StoreEntityInPrefabDomFormat(const AZ::Entity& entity, Instance& owningInstance, PrefabDom& prefabDom, StoreFlags flags) + { + InstanceEntityIdMapper entityIdMapper; + entityIdMapper.SetStoringInstance(owningInstance); + + //create settings so that the serialized entity dom undergoes mapping from entity id to entity alias + AZ::JsonSerializerSettings settings; + settings.m_metadata.Add(static_cast(&entityIdMapper)); + + if ((flags & StoreFlags::StripDefaultValues) != StoreFlags::StripDefaultValues) + { + settings.m_keepDefaults = true; + } + + AZStd::string scratchBuffer; + auto issueReportingCallback = [&scratchBuffer] + (AZStd::string_view message, AZ::JsonSerializationResult::ResultCode result, + AZStd::string_view path) -> AZ::JsonSerializationResult::ResultCode + { + return Internal::JsonIssueReporter(scratchBuffer, message, result, path); + }; + + settings.m_reporting = AZStd::move(issueReportingCallback); + + //generate PrefabDom using Json serialization system + AZ::JsonSerializationResult::ResultCode result = AZ::JsonSerialization::Store( + prefabDom, prefabDom.GetAllocator(), entity, settings); + + return result.GetOutcome() == AZ::JsonSerializationResult::Outcomes::Success; + } + + bool LoadInstanceFromPrefabDom(Instance& instance, const PrefabDom& prefabDom, LoadFlags flags) { // When entities are rebuilt they are first destroyed. As a result any assets they were exclusively holding on to will // be released and reloaded once the entities are built up again. By suspending asset release temporarily the asset reload @@ -89,7 +154,7 @@ namespace AzToolsFramework InstanceEntityIdMapper entityIdMapper; entityIdMapper.SetLoadingInstance(instance); - if ((flags & LoadInstanceFlags::AssignRandomEntityId) == LoadInstanceFlags::AssignRandomEntityId) + if ((flags & LoadFlags::AssignRandomEntityId) == LoadFlags::AssignRandomEntityId) { entityIdMapper.SetEntityIdGenerationApproach(InstanceEntityIdMapper::EntityIdGenerationApproach::Random); } @@ -119,7 +184,7 @@ namespace AzToolsFramework } bool LoadInstanceFromPrefabDom( - Instance& instance, const PrefabDom& prefabDom, AZStd::vector>& referencedAssets, LoadInstanceFlags flags) + Instance& instance, const PrefabDom& prefabDom, AZStd::vector>& referencedAssets, LoadFlags flags) { // When entities are rebuilt they are first destroyed. As a result any assets they were exclusively holding on to will // be released and reloaded once the entities are built up again. By suspending asset release temporarily the asset reload @@ -128,7 +193,7 @@ namespace AzToolsFramework InstanceEntityIdMapper entityIdMapper; entityIdMapper.SetLoadingInstance(instance); - if ((flags & LoadInstanceFlags::AssignRandomEntityId) == LoadInstanceFlags::AssignRandomEntityId) + if ((flags & LoadFlags::AssignRandomEntityId) == LoadFlags::AssignRandomEntityId) { entityIdMapper.SetEntityIdGenerationApproach(InstanceEntityIdMapper::EntityIdGenerationApproach::Random); } @@ -161,7 +226,7 @@ namespace AzToolsFramework } bool LoadInstanceFromPrefabDom( - Instance& instance, Instance::EntityList& newlyAddedEntities, const PrefabDom& prefabDom, LoadInstanceFlags flags) + Instance& instance, Instance::EntityList& newlyAddedEntities, const PrefabDom& prefabDom, LoadFlags flags) { // When entities are rebuilt they are first destroyed. As a result any assets they were exclusively holding on to will // be released and reloaded once the entities are built up again. By suspending asset release temporarily the asset reload @@ -170,7 +235,7 @@ namespace AzToolsFramework InstanceEntityIdMapper entityIdMapper; entityIdMapper.SetLoadingInstance(instance); - if ((flags & LoadInstanceFlags::AssignRandomEntityId) == LoadInstanceFlags::AssignRandomEntityId) + if ((flags & LoadFlags::AssignRandomEntityId) == LoadFlags::AssignRandomEntityId) { entityIdMapper.SetEntityIdGenerationApproach(InstanceEntityIdMapper::EntityIdGenerationApproach::Random); } @@ -240,15 +305,12 @@ namespace AzToolsFramework AZ::JsonSerializationResult::ResultCode ApplyPatches( PrefabDomValue& prefabDomToApplyPatchesOn, PrefabDom::AllocatorType& allocator, const PrefabDomValue& patches) { - auto issueReportingCallback = [](AZStd::string_view, AZ::JsonSerializationResult::ResultCode result, - AZStd::string_view) -> AZ::JsonSerializationResult::ResultCode + AZStd::string scratchBuffer; + auto issueReportingCallback = [&scratchBuffer] + (AZStd::string_view message, AZ::JsonSerializationResult::ResultCode result, + AZStd::string_view path) -> AZ::JsonSerializationResult::ResultCode { - using namespace AZ::JsonSerializationResult; - if (result.GetProcessing() == Processing::Halted) - { - return ResultCode(result.GetTask(), Outcomes::PartialSkip); - } - return result; + return Internal::JsonIssueReporter(scratchBuffer, message, result, path); }; AZ::JsonApplyPatchSettings applyPatchSettings; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.h index e773b581dd..b04cf9f57d 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.h @@ -38,7 +38,7 @@ namespace AzToolsFramework PrefabDomValueReference FindPrefabDomValue(PrefabDomValue& parentValue, const char* valueName); PrefabDomValueConstReference FindPrefabDomValue(const PrefabDomValue& parentValue, const char* valueName); - enum class StoreInstanceFlags : uint8_t + enum class StoreFlags : uint8_t { //! No flags used during the call to LoadInstanceFromPrefabDom. None = 0, @@ -47,7 +47,7 @@ namespace AzToolsFramework //! such as saving to disk, this flag will control that behavior. StripDefaultValues = 1 << 0 }; - AZ_DEFINE_ENUM_BITWISE_OPERATORS(StoreInstanceFlags); + AZ_DEFINE_ENUM_BITWISE_OPERATORS(StoreFlags); /** * Stores a valid Prefab Instance within a Prefab Dom. Useful for generating Templates @@ -56,9 +56,21 @@ namespace AzToolsFramework * @param flags Controls behavior such as whether to store default values * @return bool on whether the operation succeeded */ - bool StoreInstanceInPrefabDom(const Instance& instance, PrefabDom& prefabDom, StoreInstanceFlags flags = StoreInstanceFlags::None); + bool StoreInstanceInPrefabDom(const Instance& instance, PrefabDom& prefabDom, StoreFlags flags = StoreFlags::None); - enum class LoadInstanceFlags : uint8_t + /** + * Stores a valid entity in Prefab Dom format. + * @param entity The entity to store + * @param owningInstance The instance owning the passed in entity. + * Used for contextualizing the entity's place in a Prefab hierarchy. + * @param prefabDom The prefabDom that will be used to store the entity data + * @param flags controls behavior such as whether to store default values + * @return bool on whether the operation succeeded + */ + bool StoreEntityInPrefabDomFormat(const AZ::Entity& entity, Instance& owningInstance, PrefabDom& prefabDom, + StoreFlags flags = StoreFlags::None); + + enum class LoadFlags : uint8_t { //! No flags used during the call to LoadInstanceFromPrefabDom. None = 0, @@ -66,7 +78,7 @@ namespace AzToolsFramework //! unique, e.g. when they are duplicates of live entities, this flag will assign them a random new id. AssignRandomEntityId = 1 << 0 }; - AZ_DEFINE_ENUM_BITWISE_OPERATORS(LoadInstanceFlags); + AZ_DEFINE_ENUM_BITWISE_OPERATORS(LoadFlags); /** * Loads a valid Prefab Instance from a Prefab Dom. Useful for generating Instances. @@ -76,7 +88,7 @@ namespace AzToolsFramework * @return bool on whether the operation succeeded. */ bool LoadInstanceFromPrefabDom( - Instance& instance, const PrefabDom& prefabDom, LoadInstanceFlags flags = LoadInstanceFlags::None); + Instance& instance, const PrefabDom& prefabDom, LoadFlags flags = LoadFlags::None); /** * Loads a valid Prefab Instance from a Prefab Dom. Useful for generating Instances. @@ -88,7 +100,7 @@ namespace AzToolsFramework */ bool LoadInstanceFromPrefabDom( Instance& instance, const PrefabDom& prefabDom, AZStd::vector>& referencedAssets, - LoadInstanceFlags flags = LoadInstanceFlags::None); + LoadFlags flags = LoadFlags::None); /** * Loads a valid Prefab Instance from a Prefab Dom. Useful for generating Instances. @@ -101,7 +113,7 @@ namespace AzToolsFramework */ bool LoadInstanceFromPrefabDom( Instance& instance, Instance::EntityList& newlyAddedEntities, const PrefabDom& prefabDom, - LoadInstanceFlags flags = LoadInstanceFlags::None); + LoadFlags flags = LoadFlags::None); inline PrefabDomPath GetPrefabDomInstancePath(const char* instanceName) { diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp index ea54c9d10c..5091a2d1bc 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp @@ -328,7 +328,7 @@ namespace AzToolsFramework PrefabDom storedPrefabDom(&savingTemplateDom->get().GetAllocator()); if (!PrefabDomUtils::StoreInstanceInPrefabDom(savingPrefabInstance, storedPrefabDom, - PrefabDomUtils::StoreInstanceFlags::StripDefaultValues)) + PrefabDomUtils::StoreFlags::StripDefaultValues)) { return false; } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabUndo.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabUndo.cpp index 955af18a66..fc64e0b5b3 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabUndo.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabUndo.cpp @@ -266,8 +266,8 @@ namespace AzToolsFramework AZ_Error( "Prefab", - result.GetOutcome() == AZ::JsonSerializationResult::Outcomes::PartialSkip || - result.GetOutcome() == AZ::JsonSerializationResult::Outcomes::Success, + (result.GetOutcome() != AZ::JsonSerializationResult::Outcomes::Skipped) && + (result.GetOutcome() != AZ::JsonSerializationResult::Outcomes::PartialSkip), "Some of the patches are not successfully applied."); //remove the link id placed into the instance diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/EditorInfoRemover.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/EditorInfoRemover.cpp index 1d856fa395..dfba1d54ba 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/EditorInfoRemover.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/EditorInfoRemover.cpp @@ -513,7 +513,7 @@ exportComponent, prefabProcessorContext); // convert Prefab DOM into Prefab Instance. AZStd::unique_ptr instance(aznew Instance()); if (!Prefab::PrefabDomUtils::LoadInstanceFromPrefabDom(*instance, prefab, - Prefab::PrefabDomUtils::LoadInstanceFlags::AssignRandomEntityId)) + Prefab::PrefabDomUtils::LoadFlags::AssignRandomEntityId)) { PrefabDomValueReference sourceReference = PrefabDomUtils::FindPrefabDomValue(prefab, PrefabDomUtils::SourceName); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/SpawnableUtils.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/SpawnableUtils.cpp index 1373d2fa75..902f439280 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/SpawnableUtils.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/SpawnableUtils.cpp @@ -30,7 +30,7 @@ namespace AzToolsFramework::Prefab::SpawnableUtils { Instance instance; if (Prefab::PrefabDomUtils::LoadInstanceFromPrefabDom(instance, prefabDom, referencedAssets, - Prefab::PrefabDomUtils::LoadInstanceFlags::AssignRandomEntityId)) // Always assign random entity ids because the spawnable is + Prefab::PrefabDomUtils::LoadFlags::AssignRandomEntityId)) // Always assign random entity ids because the spawnable is // going to be used to create clones of the entities. { AzFramework::Spawnable::EntityList& entities = spawnable.GetEntities(); diff --git a/Code/Framework/AzToolsFramework/Tests/Prefab/PrefabInstanceToTemplatePropagatorTests.cpp b/Code/Framework/AzToolsFramework/Tests/Prefab/PrefabInstanceToTemplatePropagatorTests.cpp index 8379992553..ebe35a5402 100644 --- a/Code/Framework/AzToolsFramework/Tests/Prefab/PrefabInstanceToTemplatePropagatorTests.cpp +++ b/Code/Framework/AzToolsFramework/Tests/Prefab/PrefabInstanceToTemplatePropagatorTests.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include @@ -18,6 +19,98 @@ namespace UnitTest { using PrefabInstanceToTemplateTests = PrefabTestFixture; + TEST_F(PrefabInstanceToTemplateTests, GenerateEntityDom_InvalidType_InvalidTypeSkipped) + { + const char* newEntityName = "New Entity"; + AZ::Entity* newEntity = CreateEntity(newEntityName, false); + ASSERT_TRUE(newEntity); + + // Add a component with a member that is missing reflection info + // and a member that is properly reflected + PrefabTestComponentWithUnReflectedTypeMember* newComponent = + newEntity->CreateComponent(); + + ASSERT_TRUE(newComponent); + + AZStd::unique_ptr prefabInstance = m_prefabSystemComponent->CreatePrefab({ newEntity }, {}, "test/path"); + ASSERT_TRUE(prefabInstance); + + PrefabDom entityDom; + m_instanceToTemplateInterface->GenerateDomForEntity(entityDom, *newEntity); + + auto componentListDom = entityDom.FindMember("Components"); + + // Confirm that there is only one component in the entityDom + ASSERT_NE(componentListDom, entityDom.MemberEnd()); + ASSERT_TRUE(componentListDom->value.IsObject()); + ASSERT_EQ(componentListDom->value.MemberCount(), 1); + + auto testComponentDom = componentListDom->value.MemberBegin(); + ASSERT_TRUE(testComponentDom->value.IsObject()); + + // Confirm that the componentDom does not contained the invalid UnReflectedType + // We want to skip over it and produce a best effort entityDom + auto unReflectedTypeDom = testComponentDom->value.FindMember("UnReflectedType"); + ASSERT_EQ(unReflectedTypeDom, testComponentDom->value.MemberEnd()); + + // Confirm the presence of the valid ReflectedType + auto reflectedTypeDom = testComponentDom->value.FindMember("ReflectedType"); + ASSERT_NE(reflectedTypeDom, testComponentDom->value.MemberEnd()); + + // Confirm the reflected type has the correct type and value + ASSERT_TRUE(reflectedTypeDom->value.IsInt()); + EXPECT_EQ(reflectedTypeDom->value.GetInt(), newComponent->m_reflectedType); + } + + TEST_F(PrefabInstanceToTemplateTests, GenerateInstanceDom_InvalidType_InvalidTypeSkipped) + { + const char* newEntityName = "New Entity"; + AZ::Entity* newEntity = CreateEntity(newEntityName, false); + ASSERT_TRUE(newEntity); + + // Add a component with a member that is missing reflection info + // and a member that is properly reflected + PrefabTestComponentWithUnReflectedTypeMember* newComponent = + newEntity->CreateComponent(); + + ASSERT_TRUE(newComponent); + + AZStd::unique_ptr prefabInstance = m_prefabSystemComponent->CreatePrefab({ newEntity }, {}, "test/path"); + ASSERT_TRUE(prefabInstance); + + PrefabDom instanceDom; + m_instanceToTemplateInterface->GenerateDomForInstance(instanceDom, *prefabInstance); + + // Acquire the entity out of the instanceDom + auto entitiesDom = instanceDom.FindMember(PrefabDomUtils::EntitiesName); + ASSERT_NE(entitiesDom, instanceDom.MemberEnd()); + ASSERT_EQ(entitiesDom->value.MemberCount(), 1); + + auto entityDom = entitiesDom->value.MemberBegin(); + auto componentListDom = entityDom->value.FindMember("Components"); + + // Confirm that there is only one component in the entityDom + ASSERT_NE(componentListDom, entityDom->value.MemberEnd()); + ASSERT_TRUE(componentListDom->value.IsObject()); + ASSERT_EQ(componentListDom->value.MemberCount(), 1); + + auto testComponentDom = componentListDom->value.MemberBegin(); + ASSERT_TRUE(testComponentDom->value.IsObject()); + + // Confirm that the componentDom does not contained the invalid UnReflectedType + // We want to skip over it and produce a best effort entityDom + auto unReflectedTypeDom = testComponentDom->value.FindMember("UnReflectedType"); + ASSERT_EQ(unReflectedTypeDom, testComponentDom->value.MemberEnd()); + + // Confirm the presence of the valid ReflectedType + auto reflectedTypeDom = testComponentDom->value.FindMember("ReflectedType"); + ASSERT_NE(reflectedTypeDom, testComponentDom->value.MemberEnd()); + + // Confirm the reflected type has the correct type and value + ASSERT_TRUE(reflectedTypeDom->value.IsInt()); + EXPECT_EQ(reflectedTypeDom->value.GetInt(), newComponent->m_reflectedType); + } + TEST_F(PrefabInstanceToTemplateTests, PrefabUpdateTemplate_UpdateEntityOnInstance) { //create template with single entity diff --git a/Code/Framework/AzToolsFramework/Tests/Prefab/PrefabTestComponent.cpp b/Code/Framework/AzToolsFramework/Tests/Prefab/PrefabTestComponent.cpp index 8f7ee398a0..5d29b179c4 100644 --- a/Code/Framework/AzToolsFramework/Tests/Prefab/PrefabTestComponent.cpp +++ b/Code/Framework/AzToolsFramework/Tests/Prefab/PrefabTestComponent.cpp @@ -28,4 +28,18 @@ namespace UnitTest : m_boolProperty(boolProperty) { } + + void PrefabTestComponentWithUnReflectedTypeMember::Reflect(AZ::ReflectContext* reflection) + { + AZ::SerializeContext* serializeContext = AZ::RttiCast(reflection); + + // We reflect our member but not its type this will result in missing reflection data + // when we try to store or load this field + if (serializeContext) + { + serializeContext->Class() + ->Field("UnReflectedType", &PrefabTestComponentWithUnReflectedTypeMember::m_unReflectedType) + ->Field("ReflectedType", &PrefabTestComponentWithUnReflectedTypeMember::m_reflectedType); + } + } } diff --git a/Code/Framework/AzToolsFramework/Tests/Prefab/PrefabTestComponent.h b/Code/Framework/AzToolsFramework/Tests/Prefab/PrefabTestComponent.h index 0ed8f6d9c9..e0e986b7db 100644 --- a/Code/Framework/AzToolsFramework/Tests/Prefab/PrefabTestComponent.h +++ b/Code/Framework/AzToolsFramework/Tests/Prefab/PrefabTestComponent.h @@ -27,4 +27,22 @@ namespace UnitTest int m_intProperty = 0; AZ::EntityId m_entityIdProperty; }; + + class UnReflectedType + { + public: + AZ_TYPE_INFO(UnReflectedType, "{FB65262C-CE9A-45CA-99EB-4DDCB19B32DB}"); + int m_unReflectedInt = 42; + }; + + class PrefabTestComponentWithUnReflectedTypeMember + : public AzToolsFramework::Components::EditorComponentBase + { + public: + AZ_EDITOR_COMPONENT(PrefabTestComponentWithUnReflectedTypeMember, "{726281E1-8E47-46AB-8018-D3F4BA823D74}"); + static void Reflect(AZ::ReflectContext* reflection); + + UnReflectedType m_unReflectedType; + int m_reflectedType = 52; + }; } diff --git a/Code/Framework/AzToolsFramework/Tests/Prefab/PrefabTestFixture.cpp b/Code/Framework/AzToolsFramework/Tests/Prefab/PrefabTestFixture.cpp index ded88d2da3..ed30de09c4 100644 --- a/Code/Framework/AzToolsFramework/Tests/Prefab/PrefabTestFixture.cpp +++ b/Code/Framework/AzToolsFramework/Tests/Prefab/PrefabTestFixture.cpp @@ -49,6 +49,7 @@ namespace UnitTest EXPECT_TRUE(m_instanceToTemplateInterface); GetApplication()->RegisterComponentDescriptor(PrefabTestComponent::CreateDescriptor()); + GetApplication()->RegisterComponentDescriptor(PrefabTestComponentWithUnReflectedTypeMember::CreateDescriptor()); } AZStd::unique_ptr PrefabTestFixture::CreateTestApplication() diff --git a/Code/Framework/AzToolsFramework/Tests/Prefab/PrefabUpdateWithPatchesTests.cpp b/Code/Framework/AzToolsFramework/Tests/Prefab/PrefabUpdateWithPatchesTests.cpp index 72e88c6336..c17763f778 100644 --- a/Code/Framework/AzToolsFramework/Tests/Prefab/PrefabUpdateWithPatchesTests.cpp +++ b/Code/Framework/AzToolsFramework/Tests/Prefab/PrefabUpdateWithPatchesTests.cpp @@ -136,7 +136,10 @@ namespace UnitTest PrefabDomValueReference wheelEntityComponentBoolPropertyValue = PrefabDomUtils::FindPrefabDomValue(wheelEntityComponentValue->get(), PrefabTestDomUtils::BoolPropertyName); - ASSERT_FALSE(wheelEntityComponentBoolPropertyValue.has_value()); + + ASSERT_TRUE(wheelEntityComponentBoolPropertyValue.has_value()); + ASSERT_TRUE(wheelEntityComponentBoolPropertyValue->get().IsBool()); + ASSERT_FALSE(wheelEntityComponentBoolPropertyValue->get().GetBool()); // Validate that the axles under the car have the same DOM as the axle template. PrefabTestDomUtils::ValidatePrefabDomInstances(axleInstanceAliasesUnderCar, carTemplateDom, axleTemplateDom); diff --git a/Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.cpp b/Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.cpp index d49f6901f3..acfec5eb38 100644 --- a/Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.cpp +++ b/Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.cpp @@ -56,7 +56,7 @@ namespace Multiplayer // convert Prefab DOM into Prefab Instance. AZStd::unique_ptr sourceInstance(aznew Instance()); - if (!PrefabDomUtils::LoadInstanceFromPrefabDom(*sourceInstance, prefab, PrefabDomUtils::LoadInstanceFlags::AssignRandomEntityId)) + if (!PrefabDomUtils::LoadInstanceFromPrefabDom(*sourceInstance, prefab, PrefabDomUtils::LoadFlags::AssignRandomEntityId)) { PrefabDomValueConstReference sourceReference = PrefabDomUtils::FindPrefabDomValue(prefab, PrefabDomUtils::SourceName); From 39d56a8834c7aa08db5b0c7ac1b2b507bedf40f8 Mon Sep 17 00:00:00 2001 From: antonmic <56370189+antonmic@users.noreply.github.com> Date: Wed, 11 Aug 2021 10:45:48 -0700 Subject: [PATCH 286/803] Removing product dependency check from pass builder test since shaders references are now registered as a job dependency and not a product dependency Signed-off-by: antonmic <56370189+antonmic@users.noreply.github.com> --- Gems/Atom/RPI/Code/Tests.Builders/PassBuilderTest.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/Gems/Atom/RPI/Code/Tests.Builders/PassBuilderTest.cpp b/Gems/Atom/RPI/Code/Tests.Builders/PassBuilderTest.cpp index ad1df41824..4e088cece5 100644 --- a/Gems/Atom/RPI/Code/Tests.Builders/PassBuilderTest.cpp +++ b/Gems/Atom/RPI/Code/Tests.Builders/PassBuilderTest.cpp @@ -112,9 +112,6 @@ namespace UnitTest EXPECT_TRUE(response.m_resultCode == AssetBuilderSDK::ProcessJobResult_Success); EXPECT_TRUE(response.m_outputProducts.size() == 1); - // Verify the dependency was registered - EXPECT_TRUE(response.m_outputProducts[0].m_dependencies.size() == 1); - // Verify input and output names are the same Data::Asset readAsset = LoadAssetFromFile(response.m_outputProducts[0].m_productFileName.c_str()); RPI::PassAsset* readPassAsset = static_cast(readAsset.GetData()); From 6d1bb8e439eb2b0b8aeaebd45e69115b156275f7 Mon Sep 17 00:00:00 2001 From: jromnoa <80134229+jromnoa@users.noreply.github.com> Date: Wed, 11 Aug 2021 11:19:22 -0700 Subject: [PATCH 287/803] Add Light component GPU (screenshot) test to AutomatedTesting nightly o3de runs. (#2923) * adds the Light component GPU screenshot test to AutomatedTesting Signed-off-by: jromnoa * add LIGHT_TYPE_PROPERTY constant to test script since it is re-used multiple times Signed-off-by: jromnoa * removes redundant f strings, adds LIGHT_COMPONENT and LIGHT_TYPE_PROPERTY constants for re-use, removed formattng errors, increase CMakeLists.txt timeout, add attach_component_to_entity() to hydra_editor_utils.py Signed-off-by: jromnoa * fix ImportError Signed-off-by: jromnoa * moves the LIGHT_TYPES constant to a new file since scripts rely on it that do not have the Editor launched (can't see hydra bindings so failes with ModuleNotFound error) Signed-off-by: jromnoa --- .../hydra_editor_utils.py | 30 ++ .../PythonTests/atom_renderer/CMakeLists.txt | 2 +- ...dra_AtomEditorComponents_LightComponent.py | 2 +- .../hydra_GPUTest_LightComponent.py | 268 ++++++++++++++++++ .../atom_utils/atom_component_helper.py | 191 ++++++++++++- .../atom_utils/atom_constants.py | 19 ++ .../atom_utils/screenshot_utils.py | 17 ++ .../golden_images/AreaLight_1.ppm | 3 + .../golden_images/AreaLight_2.ppm | 3 + .../golden_images/AreaLight_3.ppm | 3 + .../golden_images/AreaLight_4.ppm | 3 + .../golden_images/AreaLight_5.ppm | 3 + .../golden_images/SpotLight_1.ppm | 3 + .../golden_images/SpotLight_2.ppm | 3 + .../golden_images/SpotLight_3.ppm | 3 + .../golden_images/SpotLight_4.ppm | 3 + .../golden_images/SpotLight_5.ppm | 3 + .../golden_images/SpotLight_6.ppm | 3 + .../atom_renderer/test_Atom_GPUTests.py | 61 +++- .../atom_renderer/test_Atom_MainSuite.py | 2 +- 20 files changed, 607 insertions(+), 18 deletions(-) create mode 100644 AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_GPUTest_LightComponent.py create mode 100644 AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/atom_constants.py create mode 100644 AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/AreaLight_1.ppm create mode 100644 AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/AreaLight_2.ppm create mode 100644 AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/AreaLight_3.ppm create mode 100644 AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/AreaLight_4.ppm create mode 100644 AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/AreaLight_5.ppm create mode 100644 AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/SpotLight_1.ppm create mode 100644 AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/SpotLight_2.ppm create mode 100644 AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/SpotLight_3.ppm create mode 100644 AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/SpotLight_4.ppm create mode 100644 AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/SpotLight_5.ppm create mode 100644 AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/SpotLight_6.ppm diff --git a/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/hydra_editor_utils.py b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/hydra_editor_utils.py index cec1b6456b..985e32ede5 100644 --- a/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/hydra_editor_utils.py +++ b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/hydra_editor_utils.py @@ -8,6 +8,7 @@ SPDX-License-Identifier: Apache-2.0 OR MIT import azlmbr.bus as bus import azlmbr.editor as editor import azlmbr.entity as entity +import azlmbr.legacy.general as general import azlmbr.object from typing import List @@ -428,3 +429,32 @@ def get_component_type_id_map(component_name_list): type_ids_by_component[component_names[i]] = typeId return type_ids_by_component + + +def attach_component_to_entity(entity_id, component_name): + # type: (azlmbr.entity.EntityId, str) -> azlmbr.entity.EntityComponentIdPair + """ + Adds the component if not added already. + :param entity_id: EntityId of the entity to attach the component to + :param component_name: name of the component + :return: If successful, returns the EntityComponentIdPair, otherwise returns None. + """ + type_ids_list = editor.EditorComponentAPIBus( + bus.Broadcast, 'FindComponentTypeIdsByEntityType', [component_name], 0) + general.log(f"Components found = {len(type_ids_list)}") + if len(type_ids_list) < 1: + general.log(f"ERROR: A component class with name {component_name} doesn't exist") + return None + elif len(type_ids_list) > 1: + general.log(f"ERROR: Found more than one component classes with same name: {component_name}") + return None + # Before adding the component let's check if it is already attached to the entity. + component_outcome = editor.EditorComponentAPIBus(bus.Broadcast, 'GetComponentOfType', entity_id, type_ids_list[0]) + if component_outcome.IsSuccess(): + return component_outcome.GetValue() # In this case the value is not a list. + component_outcome = editor.EditorComponentAPIBus(bus.Broadcast, 'AddComponentsOfType', entity_id, type_ids_list) + if component_outcome.IsSuccess(): + general.log(f"{component_name} Component added to entity.") + return component_outcome.GetValue()[0] + general.log(f"ERROR: Failed to add component [{component_name}] to entity") + return None diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/atom_renderer/CMakeLists.txt index d4f036faeb..f056623ecd 100644 --- a/AutomatedTesting/Gem/PythonTests/atom_renderer/CMakeLists.txt +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/CMakeLists.txt @@ -39,7 +39,7 @@ if(PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_BUILD_TESTS_SUPPORTED AND AutomatedT TEST_SUITE main TEST_REQUIRES gpu TEST_SERIAL - TIMEOUT 800 + TIMEOUT 1200 PATH ${CMAKE_CURRENT_LIST_DIR}/test_Atom_GPUTests.py RUNTIME_DEPENDENCIES AssetProcessor diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_LightComponent.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_LightComponent.py index ec8dc199ae..24866f3b19 100644 --- a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_LightComponent.py +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_LightComponent.py @@ -19,7 +19,7 @@ import azlmbr.legacy.general as general sys.path.append(os.path.join(azlmbr.paths.devassets, "Gem", "PythonTests")) import editor_python_test_tools.hydra_editor_utils as hydra -from atom_renderer.atom_utils.atom_component_helper import LIGHT_TYPES +from atom_renderer.atom_utils.atom_constants import LIGHT_TYPES LIGHT_TYPE_PROPERTY = 'Controller|Configuration|Light type' SPHERE_AND_SPOT_DISK_LIGHT_PROPERTIES = [ diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_GPUTest_LightComponent.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_GPUTest_LightComponent.py new file mode 100644 index 0000000000..08f921e68b --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_GPUTest_LightComponent.py @@ -0,0 +1,268 @@ +""" +Copyright (c) Contributors to the Open 3D Engine Project. +For complete copyright and license terms please see the LICENSE at the root of this distribution. + +SPDX-License-Identifier: Apache-2.0 OR MIT + +Hydra script that is used to create an entity with a Light component attached. +It then updates the property values of the Light component and takes a screenshot. +The screenshot is compared against an expected golden image for test verification. + +See the run() function for more in-depth test info. +""" +import os +import sys + +import azlmbr.asset as asset +import azlmbr.bus as bus +import azlmbr.editor as editor +import azlmbr.math as math +import azlmbr.paths +import azlmbr.legacy.general as general + +sys.path.append(os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Gem", "PythonTests")) + +import editor_python_test_tools.hydra_editor_utils as hydra +from atom_renderer.atom_utils import screenshot_utils +from atom_renderer.atom_utils import atom_component_helper +from editor_python_test_tools.editor_test_helper import EditorTestHelper + +helper = EditorTestHelper(log_prefix="Atom_EditorTestHelper") + +LEVEL_NAME = "auto_test" +LIGHT_COMPONENT = "Light" +LIGHT_TYPE_PROPERTY = 'Controller|Configuration|Light type' +DEGREE_RADIAN_FACTOR = 0.0174533 + + +def run(): + """ + Sets up the tests by making sure the required level is created & setup correctly. + It then executes 2 test cases - see each associated test function's docstring for more info. + + Finally prints the string "Light component tests completed" after completion + + Tests will fail immediately if any of these log lines are found: + 1. Trace::Assert + 2. Trace::Error + 3. Traceback (most recent call last): + + :return: None + """ + atom_component_helper.create_basic_atom_level(level_name=LEVEL_NAME) + + # Run tests. + area_light_test() + spot_light_test() + general.log("Light component tests completed.") + + +def area_light_test(): + """ + Basic test for the "Light" component attached to an "area_light" entity. + + Test Case - Light Component: Capsule, Spot (disk), and Point (sphere): + 1. Creates "area_light" entity w/ a Light component that has a Capsule Light type w/ the color set to 255, 0, 0 + 2. Enters game mode to take a screenshot for comparison, then exits game mode. + 3. Sets the Light component Intensity Mode to Lumens (default). + 4. Ensures the Light component Mode is Automatic (default). + 5. Sets the Intensity value of the Light component to 0.0 + 6. Enters game mode again, takes another screenshot for comparison, then exits game mode. + 7. Updates the Intensity value of the Light component to 1000.0 + 8. Enters game mode again, takes another screenshot for comparison, then exits game mode. + 9. Swaps the Capsule light type option to Spot (disk) light type on the Light component + 10. Updates "area_light" entity Transform rotate value to x: 90.0, y:0.0, z:0.0 + 11. Enters game mode again, takes another screenshot for comparison, then exits game mode. + 12. Swaps the Spot (disk) light type for the Point (sphere) light type in the Light component. + 13. Enters game mode again, takes another screenshot for comparison, then exits game mode. + 14. Deletes the Light component from the "area_light" entity and verifies its successful. + """ + # Create an "area_light" entity with "Light" component using Light type of "Capsule" + area_light_entity_name = "area_light" + area_light = hydra.Entity(area_light_entity_name) + area_light.create_entity(math.Vector3(-1.0, -2.0, 3.0), [LIGHT_COMPONENT]) + general.log( + f"{area_light_entity_name}_test: Component added to the entity: " + f"{hydra.has_components(area_light.id, [LIGHT_COMPONENT])}") + light_component_id_pair = hydra.attach_component_to_entity(area_light.id, LIGHT_COMPONENT) + + # Select the "Capsule" light type option. + azlmbr.editor.EditorComponentAPIBus( + azlmbr.bus.Broadcast, + 'SetComponentProperty', + light_component_id_pair, + LIGHT_TYPE_PROPERTY, + atom_component_helper.LIGHT_TYPES['capsule'] + ) + + # Update color and take screenshot in game mode + color = math.Color(255.0, 0.0, 0.0, 0.0) + area_light.get_set_test(0, "Controller|Configuration|Color", color) + general.idle_wait(1.0) + screenshot_utils.take_screenshot_game_mode("AreaLight_1", area_light_entity_name) + + # Update intensity value to 0.0 and take screenshot in game mode + area_light.get_set_test(0, "Controller|Configuration|Attenuation Radius|Mode", 1) + area_light.get_set_test(0, "Controller|Configuration|Intensity", 0.0) + general.idle_wait(1.0) + screenshot_utils.take_screenshot_game_mode("AreaLight_2", area_light_entity_name) + + # Update intensity value to 1000.0 and take screenshot in game mode + area_light.get_set_test(0, "Controller|Configuration|Intensity", 1000.0) + general.idle_wait(1.0) + screenshot_utils.take_screenshot_game_mode("AreaLight_3", area_light_entity_name) + + # Swap the "Capsule" light type option to "Spot (disk)" light type + azlmbr.editor.EditorComponentAPIBus( + azlmbr.bus.Broadcast, + 'SetComponentProperty', + light_component_id_pair, + LIGHT_TYPE_PROPERTY, + atom_component_helper.LIGHT_TYPES['spot_disk'] + ) + area_light_rotation = math.Vector3(DEGREE_RADIAN_FACTOR * 90.0, 0.0, 0.0) + azlmbr.components.TransformBus(azlmbr.bus.Event, "SetLocalRotation", area_light.id, area_light_rotation) + general.idle_wait(1.0) + screenshot_utils.take_screenshot_game_mode("AreaLight_4", area_light_entity_name) + + # Swap the "Spot (disk)" light type to the "Point (sphere)" light type and take screenshot. + azlmbr.editor.EditorComponentAPIBus( + azlmbr.bus.Broadcast, + 'SetComponentProperty', + light_component_id_pair, + LIGHT_TYPE_PROPERTY, + atom_component_helper.LIGHT_TYPES['sphere'] + ) + general.idle_wait(1.0) + screenshot_utils.take_screenshot_game_mode("AreaLight_5", area_light_entity_name) + + editor.ToolsApplicationRequestBus(bus.Broadcast, "DeleteEntityById", area_light.id) + + +def spot_light_test(): + """ + Basic test for the Light component attached to a "spot_light" entity. + + Test Case - Light Component: Spot (disk) with shadows & colors: + 1. Creates "spot_light" entity w/ a Light component attached to it. + 2. Selects the "directional_light" entity already present in the level and disables it. + 3. Selects the "global_skylight" entity already present in the level and disables the HDRi Skybox component, + as well as the Global Skylight (IBL) component. + 4. Enters game mode to take a screenshot for comparison, then exits game mode. + 5. Selects the "ground_plane" entity and changes updates the material to a new material. + 6. Enters game mode to take a screenshot for comparison, then exits game mode. + 7. Selects the "spot_light" entity and increases the Light component Intensity to 800 lm + 8. Enters game mode to take a screenshot for comparison, then exits game mode. + 9. Selects the "spot_light" entity and sets the Light component Color to 47, 75, 37 + 10. Enters game mode to take a screenshot for comparison, then exits game mode. + 11. Selects the "spot_light" entity and modifies the Shutter controls to the following values: + - Enable shutters: True + - Inner Angle: 60.0 + - Outer Angle: 75.0 + 12. Enters game mode to take a screenshot for comparison, then exits game mode. + 13. Selects the "spot_light" entity and modifies the Shadow controls to the following values: + - Enable Shadow: True + - ShadowmapSize: 256 + 14. Modifies the world translate position of the "spot_light" entity to 0.7, -2.0, 1.9 (for casting shadows better) + 15. Enters game mode to take a screenshot for comparison, then exits game mode. + """ + # Disable "Directional Light" component for the "directional_light" entity + # "directional_light" entity is created by the create_basic_atom_level() function by default. + directional_light_entity_id = hydra.find_entity_by_name("directional_light") + directional_light = hydra.Entity(name='directional_light', id=directional_light_entity_id) + directional_light_component_type = azlmbr.editor.EditorComponentAPIBus( + azlmbr.bus.Broadcast, 'FindComponentTypeIdsByEntityType', ["Directional Light"], 0)[0] + directional_light_component = azlmbr.editor.EditorComponentAPIBus( + azlmbr.bus.Broadcast, 'GetComponentOfType', directional_light.id, directional_light_component_type + ).GetValue() + editor.EditorComponentAPIBus(bus.Broadcast, "DisableComponents", [directional_light_component]) + general.idle_wait(0.5) + + # Disable "Global Skylight (IBL)" and "HDRi Skybox" components for the "global_skylight" entity + global_skylight_entity_id = hydra.find_entity_by_name("global_skylight") + global_skylight = hydra.Entity(name='global_skylight', id=global_skylight_entity_id) + global_skylight_component_type = azlmbr.editor.EditorComponentAPIBus( + azlmbr.bus.Broadcast, 'FindComponentTypeIdsByEntityType', ["Global Skylight (IBL)"], 0)[0] + global_skylight_component = azlmbr.editor.EditorComponentAPIBus( + azlmbr.bus.Broadcast, 'GetComponentOfType', global_skylight.id, global_skylight_component_type + ).GetValue() + editor.EditorComponentAPIBus(bus.Broadcast, "DisableComponents", [global_skylight_component]) + hdri_skybox_component_type = azlmbr.editor.EditorComponentAPIBus( + azlmbr.bus.Broadcast, 'FindComponentTypeIdsByEntityType', ["HDRi Skybox"], 0)[0] + hdri_skybox_component = azlmbr.editor.EditorComponentAPIBus( + azlmbr.bus.Broadcast, 'GetComponentOfType', global_skylight.id, hdri_skybox_component_type + ).GetValue() + editor.EditorComponentAPIBus(bus.Broadcast, "DisableComponents", [hdri_skybox_component]) + general.idle_wait(0.5) + + # Create a "spot_light" entity with "Light" component using Light Type of "Spot (disk)" + spot_light_entity_name = "spot_light" + spot_light = hydra.Entity(spot_light_entity_name) + spot_light.create_entity(math.Vector3(0.7, -2.0, 1.0), [LIGHT_COMPONENT]) + general.log( + f"{spot_light_entity_name}_test: Component added to the entity: " + f"{hydra.has_components(spot_light.id, [LIGHT_COMPONENT])}") + rotation = math.Vector3(DEGREE_RADIAN_FACTOR * 300.0, 0.0, 0.0) + azlmbr.components.TransformBus(azlmbr.bus.Event, "SetLocalRotation", spot_light.id, rotation) + light_component_type = hydra.attach_component_to_entity(spot_light.id, LIGHT_COMPONENT) + editor.EditorComponentAPIBus( + azlmbr.bus.Broadcast, + 'SetComponentProperty', + light_component_type, + LIGHT_TYPE_PROPERTY, + atom_component_helper.LIGHT_TYPES['spot_disk'] + ) + + general.idle_wait(1.0) + screenshot_utils.take_screenshot_game_mode("SpotLight_1", spot_light_entity_name) + + # Change default material of ground plane entity and take screenshot + ground_plane_entity_id = hydra.find_entity_by_name("ground_plane") + ground_plane = hydra.Entity(name='ground_plane', id=ground_plane_entity_id) + ground_plane_asset_path = os.path.join("Materials", "Presets", "MacBeth", "22_neutral_5-0_0-70d.azmaterial") + ground_plane_asset_value = asset.AssetCatalogRequestBus( + bus.Broadcast, "GetAssetIdByPath", ground_plane_asset_path, math.Uuid(), False) + material_property_path = "Default Material|Material Asset" + material_component_type = azlmbr.editor.EditorComponentAPIBus( + azlmbr.bus.Broadcast, 'FindComponentTypeIdsByEntityType', ["Material"], 0)[0] + material_component = azlmbr.editor.EditorComponentAPIBus( + azlmbr.bus.Broadcast, 'GetComponentOfType', ground_plane.id, material_component_type).GetValue() + editor.EditorComponentAPIBus( + azlmbr.bus.Broadcast, + 'SetComponentProperty', + material_component, + material_property_path, + ground_plane_asset_value + ) + general.idle_wait(1.0) + screenshot_utils.take_screenshot_game_mode("SpotLight_2", spot_light_entity_name) + + # Increase intensity value of the Spot light and take screenshot in game mode + spot_light.get_set_test(0, "Controller|Configuration|Intensity", 800.0) + general.idle_wait(1.0) + screenshot_utils.take_screenshot_game_mode("SpotLight_3", spot_light_entity_name) + + # Update the Spot light color and take screenshot in game mode + color_value = math.Color(47.0 / 255.0, 75.0 / 255.0, 37.0 / 255.0, 255.0 / 255.0) + spot_light.get_set_test(0, "Controller|Configuration|Color", color_value) + general.idle_wait(1.0) + screenshot_utils.take_screenshot_game_mode("SpotLight_4", spot_light_entity_name) + + # Update the Shutter controls of the Light component and take screenshot + spot_light.get_set_test(0, "Controller|Configuration|Shutters|Enable shutters", True) + spot_light.get_set_test(0, "Controller|Configuration|Shutters|Inner angle", 60.0) + spot_light.get_set_test(0, "Controller|Configuration|Shutters|Outer angle", 75.0) + general.idle_wait(1.0) + screenshot_utils.take_screenshot_game_mode("SpotLight_5", spot_light_entity_name) + + # Update the Shadow controls, move the spot_light entity world translate position and take screenshot + spot_light.get_set_test(0, "Controller|Configuration|Shadows|Enable shadow", True) + spot_light.get_set_test(0, "Controller|Configuration|Shadows|Shadowmap size", 256.0) + azlmbr.components.TransformBus( + azlmbr.bus.Event, "SetWorldTranslation", spot_light.id, math.Vector3(0.7, -2.0, 1.9)) + general.idle_wait(1.0) + screenshot_utils.take_screenshot_game_mode("SpotLight_6", spot_light_entity_name) + + +if __name__ == "__main__": + run() diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/atom_component_helper.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/atom_component_helper.py index de4e28bb36..58b72ef01a 100644 --- a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/atom_component_helper.py +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/atom_component_helper.py @@ -3,17 +3,184 @@ Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright SPDX-License-Identifier: Apache-2.0 OR MIT -File to assist with common hydra component functions or constants used across various Atom tests. +File to assist with common hydra component functions used across various Atom tests. """ +import os -# Light type options for the Light component. -LIGHT_TYPES = { - 'unknown': 0, - 'sphere': 1, - 'spot_disk': 2, - 'capsule': 3, - 'quad': 4, - 'polygon': 5, - 'simple_point': 6, - 'simple_spot': 7, -} +from editor_python_test_tools.editor_test_helper import EditorTestHelper + +helper = EditorTestHelper(log_prefix="Atom_EditorTestHelper") + + +def create_basic_atom_level(level_name): + """ + Creates a new level inside the Editor matching level_name & adds the following: + 1. "default_level" entity to hold all other entities. + 2. Adds Grid, Global Skylight (IBL), ground Mesh, Directional Light, Sphere w/ material+mesh, & Camera components. + 3. Each of these components has its settings tweaked slightly to match the ideal scene to test Atom rendering. + :param level_name: name of the level to create and apply this basic setup to. + :return: None + """ + import azlmbr.asset as asset + import azlmbr.bus as bus + import azlmbr.camera as camera + import azlmbr.editor as editor + import azlmbr.entity as entity + import azlmbr.legacy.general as general + import azlmbr.math as math + import azlmbr.object + + import editor_python_test_tools.hydra_editor_utils as hydra + + # Create a new level. + new_level_name = level_name + heightmap_resolution = 512 + heightmap_meters_per_pixel = 1 + terrain_texture_resolution = 412 + use_terrain = False + + # Return codes are ECreateLevelResult defined in CryEdit.h + return_code = general.create_level_no_prompt( + new_level_name, heightmap_resolution, heightmap_meters_per_pixel, terrain_texture_resolution, use_terrain) + if return_code == 1: + general.log(f"{new_level_name} level already exists") + elif return_code == 2: + general.log("Failed to create directory") + elif return_code == 3: + general.log("Directory length is too long") + elif return_code != 0: + general.log("Unknown error, failed to create level") + else: + general.log(f"{new_level_name} level created successfully") + + # Enable idle and update viewport. + general.idle_enable(True) + general.idle_wait(1.0) + general.update_viewport() + general.idle_wait(0.5) # half a second is more than enough for updating the viewport. + + # Close out problematic windows, FPS meters, and anti-aliasing. + if general.is_helpers_shown(): # Turn off the helper gizmos if visible + general.toggle_helpers() + general.idle_wait(1.0) + if general.is_pane_visible("Error Report"): # Close Error Report windows that block focus. + general.close_pane("Error Report") + if general.is_pane_visible("Error Log"): # Close Error Log windows that block focus. + general.close_pane("Error Log") + general.idle_wait(1.0) + general.run_console("r_displayInfo=0") + general.run_console("r_antialiasingmode=0") + general.idle_wait(1.0) + + # Delete all existing entities & create default_level entity + search_filter = azlmbr.entity.SearchFilter() + all_entities = entity.SearchBus(azlmbr.bus.Broadcast, "SearchEntities", search_filter) + editor.ToolsApplicationRequestBus(bus.Broadcast, "DeleteEntities", all_entities) + default_level = hydra.Entity("default_level") + default_position = math.Vector3(0.0, 0.0, 0.0) + default_level.create_entity(default_position, ["Grid"]) + default_level.get_set_test(0, "Controller|Configuration|Secondary Grid Spacing", 1.0) + + # Set the viewport up correctly after adding the parent default_level entity. + screen_width = 1280 + screen_height = 720 + degree_radian_factor = 0.0174533 # Used by "Rotation" property for the Transform component. + general.set_viewport_size(screen_width, screen_height) + general.update_viewport() + helper.wait_for_condition( + function=lambda: helper.isclose(a=general.get_viewport_size().x, b=screen_width, rel_tol=0.1) + and helper.isclose(a=general.get_viewport_size().y, b=screen_height, rel_tol=0.1), + timeout_in_seconds=4.0 + ) + result = helper.isclose(a=general.get_viewport_size().x, b=screen_width, rel_tol=0.1) and helper.isclose( + a=general.get_viewport_size().y, b=screen_height, rel_tol=0.1) + general.log(general.get_viewport_size().x) + general.log(general.get_viewport_size().y) + general.log(general.get_viewport_size().z) + general.log(f"Viewport is set to the expected size: {result}") + general.log("Basic level created") + general.run_console("r_DisplayInfo = 0") + + # Create global_skylight entity and set the properties + global_skylight = hydra.Entity("global_skylight") + global_skylight.create_entity( + entity_position=default_position, + components=["HDRi Skybox", "Global Skylight (IBL)"], + parent_id=default_level.id) + global_skylight_asset_path = os.path.join( + "LightingPresets", "greenwich_park_02_4k_iblskyboxcm_iblspecular.exr.streamingimage") + global_skylight_asset_value = asset.AssetCatalogRequestBus( + bus.Broadcast, "GetAssetIdByPath", global_skylight_asset_path, math.Uuid(), False) + global_skylight.get_set_test(0, "Controller|Configuration|Cubemap Texture", global_skylight_asset_value) + global_skylight.get_set_test(1, "Controller|Configuration|Diffuse Image", global_skylight_asset_value) + global_skylight.get_set_test(1, "Controller|Configuration|Specular Image", global_skylight_asset_value) + + # Create ground_plane entity and set the properties + ground_plane = hydra.Entity("ground_plane") + ground_plane.create_entity( + entity_position=default_position, + components=["Material"], + parent_id=default_level.id) + azlmbr.components.TransformBus(azlmbr.bus.Event, "SetLocalUniformScale", ground_plane.id, 32.0) + ground_plane_material_asset_path = os.path.join( + "Materials", "Presets", "PBR", "metal_chrome.azmaterial") + ground_plane_material_asset_value = asset.AssetCatalogRequestBus( + bus.Broadcast, "GetAssetIdByPath", ground_plane_material_asset_path, math.Uuid(), False) + ground_plane.get_set_test(0, "Default Material|Material Asset", ground_plane_material_asset_value) + + # Work around to add the correct Atom Mesh component + mesh_type_id = azlmbr.globals.property.EditorMeshComponentTypeId + ground_plane.components.append( + editor.EditorComponentAPIBus( + bus.Broadcast, "AddComponentsOfType", ground_plane.id, [mesh_type_id] + ).GetValue()[0] + ) + ground_plane_mesh_asset_path = os.path.join("Models", "plane.azmodel") + ground_plane_mesh_asset_value = asset.AssetCatalogRequestBus( + bus.Broadcast, "GetAssetIdByPath", ground_plane_mesh_asset_path, math.Uuid(), False) + ground_plane.get_set_test(1, "Controller|Configuration|Mesh Asset", ground_plane_mesh_asset_value) + + # Create directional_light entity and set the properties + directional_light = hydra.Entity("directional_light") + directional_light.create_entity( + entity_position=math.Vector3(0.0, 0.0, 10.0), + components=["Directional Light"], + parent_id=default_level.id) + directional_light_rotation = math.Vector3(degree_radian_factor * -90.0, 0.0, 0.0) + azlmbr.components.TransformBus( + azlmbr.bus.Event, "SetLocalRotation", directional_light.id, directional_light_rotation) + + # Create sphere entity and set the properties + sphere_entity = hydra.Entity("sphere") + sphere_entity.create_entity( + entity_position=math.Vector3(0.0, 0.0, 1.0), + components=["Material"], + parent_id=default_level.id) + sphere_material_asset_path = os.path.join("Materials", "Presets", "PBR", "metal_brass_polished.azmaterial") + sphere_material_asset_value = asset.AssetCatalogRequestBus( + bus.Broadcast, "GetAssetIdByPath", sphere_material_asset_path, math.Uuid(), False) + sphere_entity.get_set_test(0, "Default Material|Material Asset", sphere_material_asset_value) + + # Work around to add the correct Atom Mesh component + sphere_entity.components.append( + editor.EditorComponentAPIBus( + bus.Broadcast, "AddComponentsOfType", sphere_entity.id, [mesh_type_id] + ).GetValue()[0] + ) + sphere_mesh_asset_path = os.path.join("Models", "sphere.azmodel") + sphere_mesh_asset_value = asset.AssetCatalogRequestBus( + bus.Broadcast, "GetAssetIdByPath", sphere_mesh_asset_path, math.Uuid(), False) + sphere_entity.get_set_test(1, "Controller|Configuration|Mesh Asset", sphere_mesh_asset_value) + + # Create camera component and set the properties + camera_entity = hydra.Entity("camera") + camera_entity.create_entity( + entity_position=math.Vector3(5.5, -12.0, 9.0), + components=["Camera"], + parent_id=default_level.id) + rotation = math.Vector3( + degree_radian_factor * -27.0, degree_radian_factor * -12.0, degree_radian_factor * 25.0 + ) + azlmbr.components.TransformBus(azlmbr.bus.Event, "SetLocalRotation", camera_entity.id, rotation) + camera_entity.get_set_test(0, "Controller|Configuration|Field of view", 60.0) + camera.EditorCameraViewRequestBus(azlmbr.bus.Event, "ToggleCameraAsActiveView", camera_entity.id) diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/atom_constants.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/atom_constants.py new file mode 100644 index 0000000000..88a959f198 --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/atom_constants.py @@ -0,0 +1,19 @@ +""" +Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. + +SPDX-License-Identifier: Apache-2.0 OR MIT + +Hold constants used across both hydra and non-hydra scripts. +""" + +# Light type options for the Light component. +LIGHT_TYPES = { + 'unknown': 0, + 'sphere': 1, + 'spot_disk': 2, + 'capsule': 3, + 'quad': 4, + 'polygon': 5, + 'simple_point': 6, + 'simple_spot': 7, +} diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/screenshot_utils.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/screenshot_utils.py index 28a4037dcc..a7a02816ac 100644 --- a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/screenshot_utils.py +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/screenshot_utils.py @@ -91,3 +91,20 @@ class ScreenshotHelper(object): else: frames_waited = frames_waited + 1 general.log(f"(waited {frames_waited} frames)") + + +def take_screenshot_game_mode(screenshot_name, entity_name=None): + """ + Enters game mode & takes a screenshot, then exits game mode after. + :param screenshot_name: name to give the captured screenshot .ppm file. + :param entity_name: name of the entity being tested (for generating unique log lines). + :return: None + """ + general.enter_game_mode() + helper.wait_for_condition(lambda: general.is_in_game_mode(), 2.0) + general.log(f"{entity_name}_test: Entered game mode: {general.is_in_game_mode()}") + ScreenshotHelper(general.idle_wait_frames).capture_screenshot_blocking(f"{screenshot_name}.ppm") + general.idle_wait(1.0) + general.exit_game_mode() + helper.wait_for_condition(lambda: not general.is_in_game_mode(), 2.0) + general.log(f"{entity_name}_test: Exit game mode: {not general.is_in_game_mode()}") diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/AreaLight_1.ppm b/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/AreaLight_1.ppm new file mode 100644 index 0000000000..0725999dcf --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/AreaLight_1.ppm @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:954d7d0df47c840a24e313893800eb3126d0c0d47c3380926776b51833778db7 +size 6220817 diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/AreaLight_2.ppm b/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/AreaLight_2.ppm new file mode 100644 index 0000000000..3a45bd31e3 --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/AreaLight_2.ppm @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e81c19128f42ba362a2d5f3ccf159dfbc942d67ceeb1ac8c21f295a6fd9d2ce5 +size 6220817 diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/AreaLight_3.ppm b/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/AreaLight_3.ppm new file mode 100644 index 0000000000..15d679b784 --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/AreaLight_3.ppm @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5e20801213e065b6ea8c95ede81c23faa9b6dc70a2002dc5bced293e1bed989f +size 6220817 diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/AreaLight_4.ppm b/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/AreaLight_4.ppm new file mode 100644 index 0000000000..85c083a386 --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/AreaLight_4.ppm @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e250f812e594e5152bf2d6f23caa8b53b78276bfdf344d7a8d355dd96cb995c0 +size 6220817 diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/AreaLight_5.ppm b/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/AreaLight_5.ppm new file mode 100644 index 0000000000..d575de761e --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/AreaLight_5.ppm @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:95be359041f8291c74b335297a4dfe9902a180510f24a181b15e1a5ba4d3b024 +size 6220817 diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/SpotLight_1.ppm b/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/SpotLight_1.ppm new file mode 100644 index 0000000000..bbbd127929 --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/SpotLight_1.ppm @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:118e43e4b915e262726183467cc4b82f244565213fea5b6bfe02be07f0851ab1 +size 6220817 diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/SpotLight_2.ppm b/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/SpotLight_2.ppm new file mode 100644 index 0000000000..8e716fabcc --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/SpotLight_2.ppm @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dc2ce3256a6552975962c9e113c52c1a22bf3817d417151f6f60640dd568e0fa +size 6220817 diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/SpotLight_3.ppm b/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/SpotLight_3.ppm new file mode 100644 index 0000000000..6b6a5a5d6e --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/SpotLight_3.ppm @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:287d98890b35427688999760f9d066bcbff1a3bc9001534241dc212b32edabd8 +size 6220817 diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/SpotLight_4.ppm b/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/SpotLight_4.ppm new file mode 100644 index 0000000000..eb05228cc2 --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/SpotLight_4.ppm @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:66e91c92c868167c850078cd91714db47e10a96e23cc30191994486bd79c353f +size 6220817 diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/SpotLight_5.ppm b/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/SpotLight_5.ppm new file mode 100644 index 0000000000..5e12edc46d --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/SpotLight_5.ppm @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d950d173f5101820c5e18205401ca08ce5feeff2302ac2920b292750d86a8fa4 +size 6220817 diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/SpotLight_6.ppm b/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/SpotLight_6.ppm new file mode 100644 index 0000000000..d442d90287 --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/SpotLight_6.ppm @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:72eddb7126eae0c839b933886e0fb69d78229f72d49ef13199de28df2b7879db +size 6220817 diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_GPUTests.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_GPUTests.py index 9165bced90..7be1ed1b12 100644 --- a/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_GPUTests.py +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_GPUTests.py @@ -15,11 +15,11 @@ import pytest import ly_test_tools.environment.file_system as file_system from ly_test_tools.image.screenshot_compare_qssim import qssim as compare_screenshots from ly_test_tools.benchmark.data_aggregator import BenchmarkDataAggregator + import editor_python_test_tools.hydra_test_utils as hydra logger = logging.getLogger(__name__) DEFAULT_SUBFOLDER_PATH = 'user/PythonTests/Automated/Screenshots' -EDITOR_TIMEOUT = 600 TEST_DIRECTORY = os.path.join(os.path.dirname(__file__), "atom_hydra_scripts") @@ -67,6 +67,7 @@ class TestAllComponentsIndepthTests(object): "Trace::Assert", "Trace::Error", "Traceback (most recent call last):", + "Screenshot failed" ] hydra.launch_and_validate_results( @@ -74,7 +75,7 @@ class TestAllComponentsIndepthTests(object): TEST_DIRECTORY, editor, "hydra_GPUTest_BasicLevelSetup.py", - timeout=EDITOR_TIMEOUT, + timeout=180, expected_lines=level_creation_expected_lines, unexpected_lines=unexpected_lines, halt_on_unexpected=True, @@ -85,6 +86,60 @@ class TestAllComponentsIndepthTests(object): for test_screenshot, golden_screenshot in zip(test_screenshots, golden_images): compare_screenshots(test_screenshot, golden_screenshot) + def test_LightComponent_ScreenshotMatchesGoldenImage( + self, request, editor, workspace, project, launcher_platform, level): + """ + Please review the hydra script run by this test for more specific test info. + Tests that the Light component screenshots in a rendered level appear the same as the golden images. + """ + screenshot_names = [ + "AreaLight_1.ppm", + "AreaLight_2.ppm", + "AreaLight_3.ppm", + "AreaLight_4.ppm", + "AreaLight_5.ppm", + "SpotLight_1.ppm", + "SpotLight_2.ppm", + "SpotLight_3.ppm", + "SpotLight_4.ppm", + "SpotLight_5.ppm", + "SpotLight_6.ppm", + ] + test_screenshots = [] + for screenshot in screenshot_names: + screenshot_path = os.path.join(workspace.paths.project(), DEFAULT_SUBFOLDER_PATH, screenshot) + test_screenshots.append(screenshot_path) + file_system.delete(test_screenshots, True, True) + + golden_images = [] + for golden_image in screenshot_names: + golden_image_path = os.path.join(golden_images_directory(), golden_image) + golden_images.append(golden_image_path) + + expected_lines = ["Light component tests completed."] + unexpected_lines = [ + "Trace::Assert", + "Trace::Error", + "Traceback (most recent call last):", + "Screenshot failed", + ] + hydra.launch_and_validate_results( + request, + TEST_DIRECTORY, + editor, + "hydra_GPUTest_LightComponent.py", + timeout=180, + expected_lines=expected_lines, + unexpected_lines=unexpected_lines, + halt_on_unexpected=True, + cfg_args=[level], + null_renderer=False, + ) + + for test_screenshot, golden_screenshot in zip(test_screenshots, golden_images): + compare_screenshots(test_screenshot, golden_screenshot) + + @pytest.mark.parametrize('rhi', ['dx12', 'vulkan']) @pytest.mark.parametrize("project", ["AutomatedTesting"]) @pytest.mark.parametrize("launcher_platform", ["windows_editor"]) @@ -116,7 +171,7 @@ class TestPerformanceBenchmarkSuite(object): TEST_DIRECTORY, editor, "hydra_GPUTest_AtomFeatureIntegrationBenchmark.py", - timeout=EDITOR_TIMEOUT, + timeout=600, expected_lines=expected_lines, unexpected_lines=unexpected_lines, halt_on_unexpected=True, diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_MainSuite.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_MainSuite.py index 98d2ba0632..39689816b8 100644 --- a/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_MainSuite.py +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_MainSuite.py @@ -12,7 +12,7 @@ import os import pytest import editor_python_test_tools.hydra_test_utils as hydra -from atom_renderer.atom_utils.atom_component_helper import LIGHT_TYPES +from atom_renderer.atom_utils.atom_constants import LIGHT_TYPES logger = logging.getLogger(__name__) EDITOR_TIMEOUT = 120 From 2564e8f8dce6fc65804500dee166f72a574477f9 Mon Sep 17 00:00:00 2001 From: smurly Date: Wed, 11 Aug 2021 12:15:31 -0700 Subject: [PATCH 288/803] MaterialEditor BasicTests added to AutomatedTesting for AR (#3022) * MaterialEditor BasicTests added to AutomatedTesting for AR Signed-off-by: Scott Murray * launch_and_validate_results adding a waiter.wait_for to the log monitor so the log file exists Signed-off-by: Scott Murray --- .../AssetProcessorGamePlatformConfig.setreg | 19 ++ .../hydra_test_utils.py | 15 +- .../hydra_AtomMaterialEditor_BasicTests.py | 183 ++++++++++++ .../atom_utils/material_editor_utils.py | 274 ++++++++++++++++++ .../atom_renderer/test_Atom_MainSuite.py | 63 ++++ 5 files changed, 552 insertions(+), 2 deletions(-) create mode 100644 AutomatedTesting/AssetProcessorGamePlatformConfig.setreg create mode 100644 AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomMaterialEditor_BasicTests.py create mode 100644 AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/material_editor_utils.py diff --git a/AutomatedTesting/AssetProcessorGamePlatformConfig.setreg b/AutomatedTesting/AssetProcessorGamePlatformConfig.setreg new file mode 100644 index 0000000000..5457b3f1ca --- /dev/null +++ b/AutomatedTesting/AssetProcessorGamePlatformConfig.setreg @@ -0,0 +1,19 @@ +{ + "Amazon": { + "AssetProcessor": { + "Settings": { + "RC cgf": { + "ignore": true + }, + "RC fbx": { + "ignore": true + }, + "ScanFolder AtomTestData": { + "watch": "@ENGINEROOT@/Gems/Atom/TestData", + "recursive": 1, + "order": 1000 + } + } + } + } +} diff --git a/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/hydra_test_utils.py b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/hydra_test_utils.py index 3004b9ec7d..3d4d9ea419 100644 --- a/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/hydra_test_utils.py +++ b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/hydra_test_utils.py @@ -29,7 +29,7 @@ def teardown_editor(editor): def launch_and_validate_results(request, test_directory, editor, editor_script, expected_lines, unexpected_lines=[], halt_on_unexpected=False, run_python="--runpythontest", auto_test_mode=True, null_renderer=True, cfg_args=[], - timeout=300): + timeout=300, log_file_name="Editor.log"): """ Runs the Editor with the specified script, and monitors for expected log lines. :param request: Special fixture providing information of the requesting test function. @@ -44,6 +44,7 @@ def launch_and_validate_results(request, test_directory, editor, editor_script, :param null_renderer: Specifies the test does not require the renderer. Defaults to True. :param cfg_args: Additional arguments for CFG, such as LevelName. :param timeout: Length of time for test to run. Default is 60. + :param log_file_name: Name of the log file created by the editor. Defaults to 'Editor.log' """ test_case = os.path.join(test_directory, editor_script) request.addfinalizer(lambda: teardown_editor(editor)) @@ -58,7 +59,17 @@ def launch_and_validate_results(request, test_directory, editor, editor_script, with editor.start(): - editorlog_file = os.path.join(editor.workspace.paths.project_log(), 'Editor.log') + editorlog_file = os.path.join(editor.workspace.paths.project_log(), log_file_name) + + # Log monitor requires the file to exist. + logger.debug(f"Waiting until log file <{editorlog_file}> exists...") + waiter.wait_for( + lambda: os.path.exists(editorlog_file), + timeout=60, + exc=f"Log file '{editorlog_file}' was never created by another process.", + interval=1, + ) + logger.debug(f"Done! log file <{editorlog_file}> exists.") # Initialize the log monitor and set time to wait for log creation log_monitor = ly_test_tools.log.log_monitor.LogMonitor(launcher=editor, log_file_path=editorlog_file) diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomMaterialEditor_BasicTests.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomMaterialEditor_BasicTests.py new file mode 100644 index 0000000000..b3c51ca912 --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomMaterialEditor_BasicTests.py @@ -0,0 +1,183 @@ +""" +Copyright (c) Contributors to the Open 3D Engine Project. +For complete copyright and license terms please see the LICENSE at the root of this distribution. + +SPDX-License-Identifier: Apache-2.0 OR MIT + +import azlmbr.materialeditor will fail with a ModuleNotFound error when using this script with Editor.exe +This is because azlmbr.materialeditor only binds to MaterialEditor.exe and not Editor.exe +You need to launch this script with MaterialEditor.exe in order for azlmbr.materialeditor to appear. +""" + +import os +import sys +import time + +import azlmbr.math as math +import azlmbr.paths + +sys.path.append(os.path.join(azlmbr.paths.devassets, "Gem", "PythonTests")) + +import atom_renderer.atom_utils.material_editor_utils as material_editor + +NEW_MATERIAL = "test_material.material" +NEW_MATERIAL_1 = "test_material_1.material" +NEW_MATERIAL_2 = "test_material_2.material" +TEST_MATERIAL_1 = "001_DefaultWhite.material" +TEST_MATERIAL_2 = "002_BaseColorLerp.material" +TEST_MATERIAL_3 = "003_MetalMatte.material" +TEST_DATA_PATH = os.path.join( + azlmbr.paths.devroot, "Gems", "Atom", "TestData", "TestData", "Materials", "StandardPbrTestCases" +) +MATERIAL_TYPE_PATH = os.path.join( + azlmbr.paths.devroot, "Gems", "Atom", "Feature", "Common", "Assets", + "Materials", "Types", "StandardPBR.materialtype", +) + + +def run(): + """ + Summary: + Material Editor basic tests including the below + 1. Opening an Existing Asset + 2. Creating a New Asset + 3. Closing Selected Material + 4. Closing All Materials + 5. Closing all but Selected Material + 6. Saving Material + 7. Saving as a New Material + 8. Saving as a Child Material + 9. Saving all Open Materials + + Expected Result: + All the above functions work as expected in Material Editor. + + :return: None + """ + + # 1) Test Case: Opening an Existing Asset + document_id = material_editor.open_material(MATERIAL_TYPE_PATH) + print(f"Material opened: {material_editor.is_open(document_id)}") + + # Verify if the test material exists initially + target_path = os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Materials", NEW_MATERIAL) + print(f"Test asset doesn't exist initially: {not os.path.exists(target_path)}") + + # 2) Test Case: Creating a New Material Using Existing One + material_editor.save_document_as_child(document_id, target_path) + material_editor.wait_for_condition(lambda: os.path.exists(target_path), 2.0) + print(f"New asset created: {os.path.exists(target_path)}") + + # Verify if the newly created document is open + new_document_id = material_editor.open_material(target_path) + material_editor.wait_for_condition(lambda: material_editor.is_open(new_document_id)) + print(f"New Material opened: {material_editor.is_open(new_document_id)}") + + # 3) Test Case: Closing Selected Material + print(f"Material closed: {material_editor.close_document(new_document_id)}") + + # Open materials initially + document1_id, document2_id, document3_id = ( + material_editor.open_material(os.path.join(TEST_DATA_PATH, material)) + for material in [TEST_MATERIAL_1, TEST_MATERIAL_2, TEST_MATERIAL_3] + ) + + # 4) Test Case: Closing All Materials + print(f"All documents closed: {material_editor.close_all_documents()}") + + # 5) Test Case: Closing all but Selected Material + document1_id, document2_id, document3_id = ( + material_editor.open_material(os.path.join(TEST_DATA_PATH, material)) + for material in [TEST_MATERIAL_1, TEST_MATERIAL_2, TEST_MATERIAL_3] + ) + result = material_editor.close_all_except_selected(document1_id) + print(f"Close All Except Selected worked as expected: {result and material_editor.is_open(document1_id)}") + + # 6) Test Case: Saving Material + document_id = material_editor.open_material(os.path.join(TEST_DATA_PATH, TEST_MATERIAL_1)) + property_name = azlmbr.name.Name("baseColor.color") + initial_color = material_editor.get_property(document_id, property_name) + # Assign new color to the material file and save the actual material + expected_color = math.Color(0.25, 0.25, 0.25, 1.0) + material_editor.set_property(document_id, property_name, expected_color) + material_editor.save_document(document_id) + + # 7) Test Case: Saving as a New Material + # Assign new color to the material file and save the document as copy + expected_color_1 = math.Color(0.5, 0.5, 0.5, 1.0) + material_editor.set_property(document_id, property_name, expected_color_1) + target_path_1 = os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Materials", NEW_MATERIAL_1) + material_editor.save_document_as_copy(document_id, target_path_1) + time.sleep(2.0) + + # 8) Test Case: Saving as a Child Material + # Assign new color to the material file save the document as child + expected_color_2 = math.Color(0.75, 0.75, 0.75, 1.0) + material_editor.set_property(document_id, property_name, expected_color_2) + target_path_2 = os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Materials", NEW_MATERIAL_2) + material_editor.save_document_as_child(document_id, target_path_2) + time.sleep(2.0) + + # Close/Reopen documents + material_editor.close_all_documents() + document_id = material_editor.open_material(os.path.join(TEST_DATA_PATH, TEST_MATERIAL_1)) + document1_id = material_editor.open_material(target_path_1) + document2_id = material_editor.open_material(target_path_2) + + # Verify if the changes are saved in the actual document + actual_color = material_editor.get_property(document_id, property_name) + print(f"Actual Document saved with changes: {material_editor.compare_colors(actual_color, expected_color)}") + + # Verify if the changes are saved in the document saved as copy + actual_color = material_editor.get_property(document1_id, property_name) + result_copy = material_editor.compare_colors(actual_color, expected_color_1) + print(f"Document saved as copy is saved with changes: {result_copy}") + + # Verify if the changes are saved in the document saved as child + actual_color = material_editor.get_property(document2_id, property_name) + result_child = material_editor.compare_colors(actual_color, expected_color_2) + print(f"Document saved as child is saved with changes: {result_child}") + + # Revert back the changes in the actual document + material_editor.set_property(document_id, property_name, initial_color) + material_editor.save_document(document_id) + material_editor.close_all_documents() + + # 9) Test Case: Saving all Open Materials + # Open first material and make change to the values + document1_id = material_editor.open_material(os.path.join(TEST_DATA_PATH, TEST_MATERIAL_1)) + property1_name = azlmbr.name.Name("metallic.factor") + initial_metallic_factor = material_editor.get_property(document1_id, property1_name) + expected_metallic_factor = 0.444 + material_editor.set_property(document1_id, property1_name, expected_metallic_factor) + + # Open second material and make change to the values + document2_id = material_editor.open_material(os.path.join(TEST_DATA_PATH, TEST_MATERIAL_2)) + property2_name = azlmbr.name.Name("baseColor.color") + initial_color = material_editor.get_property(document2_id, property2_name) + expected_color = math.Color(0.4156, 0.0196, 0.6862, 1.0) + material_editor.set_property(document2_id, property2_name, expected_color) + + # Save all and close all documents + material_editor.save_all() + material_editor.close_all_documents() + + # Reopen materials and verify values + document1_id = material_editor.open_material(os.path.join(TEST_DATA_PATH, TEST_MATERIAL_1)) + result = material_editor.is_close( + material_editor.get_property(document1_id, property1_name), expected_metallic_factor, 0.00001 + ) + document2_id = material_editor.open_material(os.path.join(TEST_DATA_PATH, TEST_MATERIAL_2)) + result = result and material_editor.compare_colors( + expected_color, material_editor.get_property(document2_id, property2_name)) + print(f"Save All worked as expected: {result}") + + # Revert the changes made + material_editor.set_property(document1_id, property1_name, initial_metallic_factor) + material_editor.set_property(document2_id, property2_name, initial_color) + material_editor.save_all() + material_editor.close_all_documents() + + +if __name__ == "__main__": + run() diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/material_editor_utils.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/material_editor_utils.py new file mode 100644 index 0000000000..77d1285188 --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/material_editor_utils.py @@ -0,0 +1,274 @@ +""" +Copyright (c) Contributors to the Open 3D Engine Project. +For complete copyright and license terms please see the LICENSE at the root of this distribution. + +SPDX-License-Identifier: Apache-2.0 OR MIT + +import azlmbr.materialeditor will fail with a ModuleNotFound error when using this script with Editor.exe +This is because azlmbr.materialeditor only binds to MaterialEditor.exe and not Editor.exe +You need to launch this script with MaterialEditor.exe in order for azlmbr.materialeditor to appear. +""" + +import os +import sys +import time +import azlmbr.atom +import azlmbr.materialeditor as materialeditor +import azlmbr.bus as bus +import azlmbr.atomtools.general as general + + +def is_close(actual, expected, buffer=sys.float_info.min): + """ + :param actual: actual value + :param expected: expected value + :param buffer: acceptable variation from expected + :return: bool + """ + return abs(actual - expected) < buffer + + +def compare_colors(color1, color2, buffer=0.00001): + """ + Compares the red, green and blue properties of a color allowing a slight variance of buffer + :param color1: first color to compare + :param color2: second color + :param buffer: allowed variance in individual color value + :return: bool + """ + return ( + is_close(color1.r, color2.r, buffer) + and is_close(color1.g, color2.g, buffer) + and is_close(color1.b, color2.b, buffer) + ) + + +def open_material(file_path): + """ + :return: uuid of material document opened + """ + return materialeditor.MaterialDocumentSystemRequestBus(bus.Broadcast, "OpenDocument", file_path) + + +def is_open(document_id): + """ + :return: bool + """ + return materialeditor.MaterialDocumentRequestBus(bus.Event, "IsOpen", document_id) + + +def save_document(document_id): + """ + :return: bool success + """ + return materialeditor.MaterialDocumentSystemRequestBus(bus.Broadcast, "SaveDocument", document_id) + + +def save_document_as_copy(document_id, target_path): + """ + :return: bool success + """ + return materialeditor.MaterialDocumentSystemRequestBus( + bus.Broadcast, "SaveDocumentAsCopy", document_id, target_path + ) + + +def save_document_as_child(document_id, target_path): + """ + :return: bool success + """ + return materialeditor.MaterialDocumentSystemRequestBus( + bus.Broadcast, "SaveDocumentAsChild", document_id, target_path + ) + + +def save_all(): + """ + :return: bool success + """ + return materialeditor.MaterialDocumentSystemRequestBus(bus.Broadcast, "SaveAllDocuments") + + +def close_document(document_id): + """ + :return: bool success + """ + return materialeditor.MaterialDocumentSystemRequestBus(bus.Broadcast, "CloseDocument", document_id) + + +def close_all_documents(): + """ + :return: bool success + """ + return materialeditor.MaterialDocumentSystemRequestBus(bus.Broadcast, "CloseAllDocuments") + + +def close_all_except_selected(document_id): + """ + :return: bool success + """ + return materialeditor.MaterialDocumentSystemRequestBus(bus.Broadcast, "CloseAllDocumentsExcept", document_id) + + +def get_property(document_id, property_name): + """ + :return: property value or invalid value if the document is not open or the property_name can't be found + """ + return materialeditor.MaterialDocumentRequestBus(bus.Event, "GetPropertyValue", document_id, property_name) + + +def set_property(document_id, property_name, value): + materialeditor.MaterialDocumentRequestBus(bus.Event, "SetPropertyValue", document_id, property_name, value) + + +def is_pane_visible(pane_name): + """ + :return: bool + """ + return materialeditor.MaterialEditorWindowRequestBus(bus.Broadcast, "IsDockWidgetVisible", pane_name) + + +def set_pane_visibility(pane_name, value): + materialeditor.MaterialEditorWindowRequestBus(bus.Broadcast, "SetDockWidgetVisible", pane_name, value) + + +def select_lighting_config(config_name): + azlmbr.materialeditor.MaterialViewportRequestBus(azlmbr.bus.Broadcast, "SelectLightingPresetByName", config_name) + + +def set_grid_enable_disable(value): + azlmbr.materialeditor.MaterialViewportRequestBus(azlmbr.bus.Broadcast, "SetGridEnabled", value) + + +def get_grid_enable_disable(): + """ + :return: bool + """ + return azlmbr.materialeditor.MaterialViewportRequestBus(azlmbr.bus.Broadcast, "GetGridEnabled") + + +def set_shadowcatcher_enable_disable(value): + azlmbr.materialeditor.MaterialViewportRequestBus(azlmbr.bus.Broadcast, "SetShadowCatcherEnabled", value) + + +def get_shadowcatcher_enable_disable(): + """ + :return: bool + """ + return azlmbr.materialeditor.MaterialViewportRequestBus(azlmbr.bus.Broadcast, "GetShadowCatcherEnabled") + + +def select_model_config(configname): + azlmbr.materialeditor.MaterialViewportRequestBus(azlmbr.bus.Broadcast, "SelectModelPresetByName", configname) + + +def wait_for_condition(function, timeout_in_seconds=1.0): + # type: (function, float) -> bool + """ + Function to run until it returns True or timeout is reached + the function can have no parameters and + waiting idle__wait_* is handled here not in the function + + :param function: a function that returns a boolean indicating a desired condition is achieved + :param timeout_in_seconds: when reached, function execution is abandoned and False is returned + """ + with Timeout(timeout_in_seconds) as t: + while True: + try: + general.idle_wait_frames(1) + except Exception: + print("WARNING: Couldn't wait for frame") + + if t.timed_out: + return False + + ret = function() + if not isinstance(ret, bool): + raise TypeError("return value for wait_for_condition function must be a bool") + if ret: + return True + + +class Timeout: + # type: (float) -> None + """ + contextual timeout + :param seconds: float seconds to allow before timed_out is True + """ + + def __init__(self, seconds): + self.seconds = seconds + + def __enter__(self): + self.die_after = time.time() + self.seconds + return self + + def __exit__(self, type, value, traceback): + pass + + @property + def timed_out(self): + return time.time() > self.die_after + + +screenshotsFolder = os.path.join(azlmbr.paths.devroot, "AtomTest", "Cache" "pc", "Screenshots") + + +class ScreenshotHelper: + """ + A helper to capture screenshots and wait for them. + """ + + def __init__(self, idle_wait_frames_callback): + super().__init__() + self.done = False + self.capturedScreenshot = False + self.max_frames_to_wait = 60 + + self.idle_wait_frames_callback = idle_wait_frames_callback + + def capture_screenshot_blocking(self, filename): + """ + Capture a screenshot and block the execution until the screenshot has been written to the disk. + """ + self.handler = azlmbr.atom.FrameCaptureNotificationBusHandler() + self.handler.connect() + self.handler.add_callback("OnCaptureFinished", self.on_screenshot_captured) + + self.done = False + self.capturedScreenshot = False + success = azlmbr.atom.FrameCaptureRequestBus(azlmbr.bus.Broadcast, "CaptureScreenshot", filename) + if success: + self.wait_until_screenshot() + print("Screenshot taken.") + else: + print("screenshot failed") + return self.capturedScreenshot + + def on_screenshot_captured(self, parameters): + # the parameters come in as a tuple + if parameters[0]: + print("screenshot saved: {}".format(parameters[1])) + self.capturedScreenshot = True + else: + print("screenshot failed: {}".format(parameters[1])) + self.done = True + self.handler.disconnect() + + def wait_until_screenshot(self): + frames_waited = 0 + while self.done == False: + self.idle_wait_frames_callback(1) + if frames_waited > self.max_frames_to_wait: + print("timeout while waiting for the screenshot to be written") + self.handler.disconnect() + break + else: + frames_waited = frames_waited + 1 + print("(waited {} frames)".format(frames_waited)) + + +def capture_screenshot(file_path): + return ScreenshotHelper(azlmbr.atomtools.general.idle_wait_frames).capture_screenshot_blocking( + os.path.join(file_path) + ) diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_MainSuite.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_MainSuite.py index 39689816b8..be75801b63 100644 --- a/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_MainSuite.py +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_MainSuite.py @@ -11,6 +11,7 @@ import os import pytest +import ly_test_tools.environment.file_system as file_system import editor_python_test_tools.hydra_test_utils as hydra from atom_renderer.atom_utils.atom_constants import LIGHT_TYPES @@ -242,3 +243,65 @@ class TestAtomEditorComponentsMain(object): null_renderer=True, cfg_args=cfg_args, ) + + +@pytest.mark.parametrize("project", ["AutomatedTesting"]) +@pytest.mark.parametrize("launcher_platform", ['windows_generic']) +@pytest.mark.system +class TestMaterialEditorBasicTests(object): + @pytest.fixture(autouse=True) + def setup_teardown(self, request, workspace, project): + def delete_files(): + file_system.delete( + [ + os.path.join(workspace.paths.project(), "Materials", "test_material.material"), + os.path.join(workspace.paths.project(), "Materials", "test_material_1.material"), + os.path.join(workspace.paths.project(), "Materials", "test_material_2.material"), + ], + True, + True, + ) + # Cleanup our newly created materials + delete_files() + + def teardown(): + # Cleanup our newly created materials + delete_files() + + request.addfinalizer(teardown) + + @pytest.mark.parametrize("exe_file_name", ["MaterialEditor"]) + def test_MaterialEditorBasicTests( + self, request, workspace, project, launcher_platform, generic_launcher, exe_file_name): + + expected_lines = [ + "Material opened: True", + "Test asset doesn't exist initially: True", + "New asset created: True", + "New Material opened: True", + "Material closed: True", + "All documents closed: True", + "Close All Except Selected worked as expected: True", + "Actual Document saved with changes: True", + "Document saved as copy is saved with changes: True", + "Document saved as child is saved with changes: True", + "Save All worked as expected: True", + ] + unexpected_lines = [ + # "Trace::Assert", + # "Trace::Error", + "Traceback (most recent call last):" + ] + + hydra.launch_and_validate_results( + request, + TEST_DIRECTORY, + generic_launcher, + "hydra_AtomMaterialEditor_BasicTests.py", + run_python="--runpython", + timeout=80, + expected_lines=expected_lines, + unexpected_lines=unexpected_lines, + halt_on_unexpected=True, + log_file_name="MaterialEditor.log", + ) From f1e8d37b86cc0eadad974a77c8e128af5317f1ba Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Wed, 11 Aug 2021 14:55:28 -0500 Subject: [PATCH 289/803] holding pen for refactor Signed-off-by: Guthrie Adams --- .../Window/AtomToolsMainWindow.h | 5 +- .../Code/Source/AtomToolsFrameworkModule.cpp | 7 +- .../Source/Window/AtomToolsMainWindow.cpp | 18 +- .../AtomToolsMainWindowSystemComponent.cpp | 73 +++++++ .../AtomToolsMainWindowSystemComponent.h | 36 ++++ .../Code/atomtoolsframework_files.cmake | 2 + .../MaterialDocumentNotificationBus.h | 48 ++--- .../Document/MaterialDocumentRequestBus.h | 32 +-- .../MaterialDocumentSystemRequestBus.h | 40 ++-- .../MaterialDocumentSystemComponent.cpp | 66 +++--- .../Source/Window/MaterialEditorWindow.cpp | 53 ++--- .../Window/MaterialEditorWindowComponent.cpp | 35 +--- .../Scripts/GenerateAllMaterialScreenshots.py | 7 +- ...ManagementConsoleDocumentNotificationBus.h | 27 +++ ...haderManagementConsoleDocumentRequestBus.h | 9 +- ...anagementConsoleDocumentSystemRequestBus.h | 11 +- .../ShaderManagementConsoleDocument.cpp | 67 ++++-- .../ShaderManagementConsoleDocument.h | 8 +- ...nagementConsoleDocumentSystemComponent.cpp | 136 ++++++++---- ...ManagementConsoleDocumentSystemComponent.h | 8 +- .../Window/ShaderManagementConsoleWindow.cpp | 198 ++++++++++-------- .../Window/ShaderManagementConsoleWindow.h | 7 +- ...ShaderManagementConsoleWindowComponent.cpp | 19 +- 23 files changed, 569 insertions(+), 343 deletions(-) create mode 100644 Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindowSystemComponent.cpp create mode 100644 Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindowSystemComponent.h diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindow.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindow.h index 82444246fd..751b30a907 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindow.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindow.h @@ -16,8 +16,8 @@ #include #include +#include #include -#include #include namespace AtomToolsFramework @@ -53,10 +53,9 @@ namespace AtomToolsFramework virtual void SelectNextTab(); AzQtComponents::FancyDocking* m_advancedDockManager = nullptr; - QWidget* m_centralWidget = nullptr; QMenuBar* m_menuBar = nullptr; AzQtComponents::TabWidget* m_tabWidget = nullptr; - QStatusBar* m_statusBar = nullptr; + QLabel* m_statusMessage = nullptr; AZStd::unordered_map m_dockWidgets; }; diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/AtomToolsFrameworkModule.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/AtomToolsFrameworkModule.cpp index bee27dfdca..b601596032 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/AtomToolsFrameworkModule.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/AtomToolsFrameworkModule.cpp @@ -8,20 +8,23 @@ #include #include +#include namespace AtomToolsFramework { AtomToolsFrameworkModule::AtomToolsFrameworkModule() { m_descriptors.insert(m_descriptors.end(), { - AtomToolsFrameworkSystemComponent::CreateDescriptor(), - }); + AtomToolsFrameworkSystemComponent::CreateDescriptor(), + AtomToolsMainWindowSystemComponent::CreateDescriptor(), + }); } AZ::ComponentTypeList AtomToolsFrameworkModule::GetRequiredSystemComponents() const { return AZ::ComponentTypeList{ azrtti_typeid(), + azrtti_typeid(), }; } } diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp index f6e56b1ff6..55bec32dc7 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp @@ -7,6 +7,8 @@ */ #include +#include +#include namespace AtomToolsFramework { @@ -21,11 +23,15 @@ namespace AtomToolsFramework setCorner(Qt::TopRightCorner, Qt::RightDockWidgetArea); setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea); - m_statusBar = new QStatusBar(this); - m_statusBar->setObjectName("StatusBar"); - statusBar()->addPermanentWidget(m_statusBar, 1); + m_statusMessage = new QLabel(statusBar()); + statusBar()->addPermanentWidget(m_statusMessage, 1); - m_centralWidget = new QWidget(this); + auto centralWidget = new QWidget(this); + auto centralWidgetLayout = new QVBoxLayout(centralWidget); + centralWidgetLayout->setMargin(0); + centralWidgetLayout->setContentsMargins(0, 0, 0, 0); + centralWidget->setLayout(centralWidgetLayout); + setCentralWidget(centralWidget); AtomToolsMainWindowRequestBus::Handler::BusConnect(); } @@ -111,7 +117,7 @@ namespace AtomToolsFramework void AtomToolsMainWindow::CreateTabBar() { - m_tabWidget = new AzQtComponents::TabWidget(m_centralWidget); + m_tabWidget = new AzQtComponents::TabWidget(centralWidget()); m_tabWidget->setObjectName("TabWidget"); m_tabWidget->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Preferred); m_tabWidget->setContentsMargins(0, 0, 0, 0); @@ -131,6 +137,8 @@ namespace AtomToolsFramework { OpenTabContextMenu(); }); + + centralWidget()->layout()->addWidget(m_tabWidget); } void AtomToolsMainWindow::AddTabForDocumentId( diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindowSystemComponent.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindowSystemComponent.cpp new file mode 100644 index 0000000000..3114a5d9f7 --- /dev/null +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindowSystemComponent.cpp @@ -0,0 +1,73 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include +#include +#include +#include +#include + +namespace AtomToolsFramework +{ + void AtomToolsMainWindowSystemComponent::Reflect(AZ::ReflectContext* context) + { + if (AZ::SerializeContext* serialize = azrtti_cast(context)) + { + serialize->Class() + ->Version(0); + } + + if (AZ::BehaviorContext* behaviorContext = azrtti_cast(context)) + { + behaviorContext->EBus("AtomToolsMainWindowFactoryRequestBus") + ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) + ->Attribute(AZ::Script::Attributes::Category, "Editor") + ->Attribute(AZ::Script::Attributes::Module, "atomtools") + ->Event("CreateMainWindow", &AtomToolsMainWindowFactoryRequestBus::Events::CreateMainWindow) + ->Event("DestroyMainWindow", &AtomToolsMainWindowFactoryRequestBus::Events::DestroyMainWindow) + ; + + behaviorContext->EBus("AtomToolsMainWindowRequestBus") + ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) + ->Attribute(AZ::Script::Attributes::Category, "Editor") + ->Attribute(AZ::Script::Attributes::Module, "atomtools") + ->Event("ActivateWindow", &AtomToolsMainWindowRequestBus::Events::ActivateWindow) + ->Event("SetDockWidgetVisible", &AtomToolsMainWindowRequestBus::Events::SetDockWidgetVisible) + ->Event("IsDockWidgetVisible", &AtomToolsMainWindowRequestBus::Events::IsDockWidgetVisible) + ->Event("GetDockWidgetNames", &AtomToolsMainWindowRequestBus::Events::GetDockWidgetNames) + ->Event("ResizeViewportRenderTarget", &AtomToolsMainWindowRequestBus::Events::ResizeViewportRenderTarget) + ->Event("LockViewportRenderTargetSize", &AtomToolsMainWindowRequestBus::Events::LockViewportRenderTargetSize) + ->Event("UnlockViewportRenderTargetSize", &AtomToolsMainWindowRequestBus::Events::UnlockViewportRenderTargetSize) + ; + } + } + + void AtomToolsMainWindowSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) + { + provided.push_back(AZ_CRC_CE("AtomToolsMainWindowSystemService")); + } + + void AtomToolsMainWindowSystemComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) + { + incompatible.push_back(AZ_CRC_CE("AtomToolsMainWindowSystemService")); + } + + void AtomToolsMainWindowSystemComponent::Init() + { + } + + void AtomToolsMainWindowSystemComponent::Activate() + { + } + + void AtomToolsMainWindowSystemComponent::Deactivate() + { + } + +} // namespace AtomToolsFramework diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindowSystemComponent.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindowSystemComponent.h new file mode 100644 index 0000000000..b982327326 --- /dev/null +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindowSystemComponent.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#pragma once + +#include + +namespace AtomToolsFramework +{ + //! AtomToolsMainWindowSystemComponent is used for initialization and registration of other classes. + class AtomToolsMainWindowSystemComponent + : public AZ::Component + { + public: + AZ_COMPONENT(AtomToolsMainWindowSystemComponent, "{6E42380B-4ECD-47CF-B904-E16AB4E87D0D}"); + + static void Reflect(AZ::ReflectContext* context); + + static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided); + static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible); + + private: + + //////////////////////////////////////////////////////////////////////// + // AZ::Component interface implementation + void Init() override; + void Activate() override; + void Deactivate() override; + //////////////////////////////////////////////////////////////////////// + }; +} diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake b/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake index 49e641eb9c..8eb82778e3 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake @@ -45,4 +45,6 @@ set(FILES Source/Viewport/RenderViewportWidget.cpp Source/Viewport/ModularViewportCameraController.cpp Source/Window/AtomToolsMainWindow.cpp + Source/Window/AtomToolsMainWindowSystemComponent.cpp + Source/Window/AtomToolsMainWindowSystemComponent.h ) \ No newline at end of file diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentNotificationBus.h b/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentNotificationBus.h index aafd0a0a57..963a348697 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentNotificationBus.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentNotificationBus.h @@ -25,58 +25,58 @@ namespace MaterialEditor static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple; - //! Signal that a material document was created - //! @param documentId unique id of material document for which the notification is sent + //! Signal that a document was created + //! @param documentId unique id of document for which the notification is sent virtual void OnDocumentCreated([[maybe_unused]] const AZ::Uuid& documentId) {} - //! Signal that a material document was destroyed - //! @param documentId unique id of material document for which the notification is sent + //! Signal that a document was destroyed + //! @param documentId unique id of document for which the notification is sent virtual void OnDocumentDestroyed([[maybe_unused]] const AZ::Uuid& documentId) {} - //! Signal that a material document was opened - //! @param documentId unique id of material document for which the notification is sent + //! Signal that a document was opened + //! @param documentId unique id of document for which the notification is sent virtual void OnDocumentOpened([[maybe_unused]] const AZ::Uuid& documentId) {} - //! Signal that a material document was closed - //! @param documentId unique id of material document for which the notification is sent + //! Signal that a document was closed + //! @param documentId unique id of document for which the notification is sent virtual void OnDocumentClosed([[maybe_unused]] const AZ::Uuid& documentId) {} - //! Signal that a material document was saved - //! @param documentId unique id of material document for which the notification is sent + //! Signal that a document was saved + //! @param documentId unique id of document for which the notification is sent virtual void OnDocumentSaved([[maybe_unused]] const AZ::Uuid& documentId) {} - //! Signal that a material document was selected - //! @param documentId unique id of material document for which the notification is sent + //! Signal that a document was selected + //! @param documentId unique id of document for which the notification is sent virtual void OnDocumentSelected([[maybe_unused]] const AZ::Uuid& documentId) {} - //! Signal that a material document was modified - //! @param documentId unique id of material document for which the notification is sent + //! Signal that a document was modified + //! @param documentId unique id of document for which the notification is sent virtual void OnDocumentModified([[maybe_unused]] const AZ::Uuid& documentId) {} - //! Signal that a material document dependency was modified - //! @param documentId unique id of material document for which the notification is sent + //! Signal that a document dependency was modified + //! @param documentId unique id of document for which the notification is sent virtual void OnDocumentDependencyModified([[maybe_unused]] const AZ::Uuid& documentId) {} - //! Signal that a material document was modified externally - //! @param documentId unique id of material document for which the notification is sent + //! Signal that a document was modified externally + //! @param documentId unique id of document for which the notification is sent virtual void OnDocumentExternallyModified([[maybe_unused]] const AZ::Uuid& documentId) {} - //! Signal that a material document undo state was updated - //! @param documentId unique id of material document for which the notification is sent + //! Signal that a document undo state was updated + //! @param documentId unique id of document for which the notification is sent virtual void OnDocumentUndoStateChanged([[maybe_unused]] const AZ::Uuid& documentId) {} - //! Signal that a material property changed - //! @param documentId unique id of material document for which the notification is sent + //! Signal that a property changed + //! @param documentId unique id of document for which the notification is sent //! @param property object containing the property value and configuration that was modified virtual void OnDocumentPropertyValueModified([[maybe_unused]] const AZ::Uuid& documentId, [[maybe_unused]] const AtomToolsFramework::DynamicProperty& property) {} //! Signal that the property configuration has been changed. - //! @param documentId unique id of material document for which the notification is sent + //! @param documentId unique id of document for which the notification is sent //! @param property object containing the property value and configuration that was modified virtual void OnDocumentPropertyConfigModified([[maybe_unused]] const AZ::Uuid& documentId, [[maybe_unused]] const AtomToolsFramework::DynamicProperty& property) {} //! Signal that the property group visibility has been changed. - //! @param documentId unique id of material document for which the notification is sent + //! @param documentId unique id of document for which the notification is sent //! @param groupId id of the group that changed //! @param visible whether the property group is visible virtual void OnDocumentPropertyGroupVisibilityChanged([[maybe_unused]] const AZ::Uuid& documentId, [[maybe_unused]] const AZ::Name& groupId, [[maybe_unused]] bool visible) {} diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentRequestBus.h b/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentRequestBus.h index f81476a3a9..23b5749554 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentRequestBus.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentRequestBus.h @@ -39,10 +39,10 @@ namespace MaterialEditor static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById; typedef AZ::Uuid BusIdType; - //! Get absolute path of material source file + //! Get absolute path of document virtual AZStd::string_view GetAbsolutePath() const = 0; - //! Get relative path of material source file + //! Get relative path of document virtual AZStd::string_view GetRelativePath() const = 0; //! Get material asset created by MaterialDocument @@ -72,52 +72,52 @@ namespace MaterialEditor //! Modify material property value virtual void SetPropertyValue(const AZ::Name& propertyFullName, const AZStd::any& value) = 0; - //! Load source material and related data - //! @param loadPath Absolute path of material to load + //! Load document and related data + //! @param loadPath Absolute path of document to load virtual bool Open(AZStd::string_view loadPath) = 0; //! Reload document preserving edits virtual bool Rebuild() = 0; - //! Save material to source file + //! Save document to file virtual bool Save() = 0; - //! Save material to a new source file - //! @param savePath Absolute path where material is saved + //! Save document copy + //! @param savePath Absolute path where document is saved virtual bool SaveAsCopy(AZStd::string_view savePath) = 0; //! Save material to a new source file as a child of the open material //! @param savePath Absolute path where material is saved virtual bool SaveAsChild(AZStd::string_view savePath) = 0; - //! Close material document and reset its data + //! Close document and reset its data virtual bool Close() = 0; - //! Material is loaded + //! document is loaded virtual bool IsOpen() const = 0; - //! Material has changes pending + //! document has changes pending virtual bool IsModified() const = 0; //! Can the document be saved virtual bool IsSavable() const = 0; - //! Returns true if there are reversible modifications to the material document + //! Returns true if there are reversible modifications to the document virtual bool CanUndo() const = 0; - //! Returns true if there are changes that were reversed and can be re-applied to the material document + //! Returns true if there are changes that were reversed and can be re-applied to the document virtual bool CanRedo() const = 0; - //! Restores the previous state of the material document + //! Restores the previous state of the document virtual bool Undo() = 0; - //! Restores the next state of the material document + //! Restores the next state of the document virtual bool Redo() = 0; - //! Signal that property editing is about to begin, like beginning to drag a slider control + //! Signal that editing is about to begin, like beginning to drag a slider control virtual bool BeginEdit() = 0; - //! Signal that property editing has completed, like after releasing the mouse button after continuously dragging a slider control + //! Signal that editing has completed, like after releasing the mouse button after continuously dragging a slider control virtual bool EndEdit() = 0; }; diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentSystemRequestBus.h b/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentSystemRequestBus.h index 18534b3d2d..47fa5dab85 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentSystemRequestBus.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentSystemRequestBus.h @@ -23,53 +23,53 @@ namespace MaterialEditor static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single; static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; - //! Create a material document object - //! @return Uuid of new material document, or null Uuid if failed + //! Create a document object + //! @return Uuid of new document, or null Uuid if failed virtual AZ::Uuid CreateDocument() = 0; - //! Destroy a material document object with the specified id + //! Destroy a document object with the specified id //! @return true if Uuid was found and removed, otherwise false virtual bool DestroyDocument(const AZ::Uuid& documentId) = 0; - //! Open a material document for editing - //! @param sourcePath material document to open. - //! @return unique id of new material document if successful, otherwise null Uuid + //! Open a document for editing + //! @param sourcePath document to open. + //! @return unique id of new document if successful, otherwise null Uuid virtual AZ::Uuid OpenDocument(AZStd::string_view sourcePath) = 0; //! Create a new document by specifying a source and prompting the user for destination path. //! If the source file is a material type then this results in creating a new material based on that type. //! If the source file is a material this results in creating a child material with the source file as its parent. - //! @param sourcePath material document to open. + //! @param sourcePath document to open. //! @param targetPath location where document is saved. - //! @return unique id of new material document if successful, otherwise null Uuid + //! @return unique id of new document if successful, otherwise null Uuid virtual AZ::Uuid CreateDocumentFromFile(AZStd::string_view sourcePath, AZStd::string_view targetPath) = 0; - //! Close the specified material document - //! @param documentId unique id of material document to close + //! Close the specified document + //! @param documentId unique id of document to close virtual bool CloseDocument(const AZ::Uuid& documentId) = 0; - //! Close all material documents + //! Close all documents virtual bool CloseAllDocuments() = 0; - //! Close all material documents except for documentId - //! @param documentId unique id of material document to not close + //! Close all documents except for documentId + //! @param documentId unique id of document to not close virtual bool CloseAllDocumentsExcept(const AZ::Uuid& documentId) = 0; - //! Save the specified material document - //! @param documentId unique id of material document to save + //! Save the specified document + //! @param documentId unique id of document to save virtual bool SaveDocument(const AZ::Uuid& documentId) = 0; - //! Save the specified material document to a different file - //! @param documentId unique id of material document to save + //! Save the specified document to a different file + //! @param documentId unique id of document to save //! @param targetPath location where document is saved. virtual bool SaveDocumentAsCopy(const AZ::Uuid& documentId, AZStd::string_view targetPath) = 0; - //! Save the specified material document to a different file, referencing the original material as its parent - //! @param documentId unique id of material document to save + //! Save the specified document to a different file, referencing the original material as its parent + //! @param documentId unique id of document to save //! @param targetPath location where document is saved. virtual bool SaveDocumentAsChild(const AZ::Uuid& documentId, AZStd::string_view targetPath) = 0; - //! Save all material documents + //! Save all documents virtual bool SaveAllDocuments() = 0; }; diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentSystemComponent.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentSystemComponent.cpp index e4a3b8235d..3ecabaabcc 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentSystemComponent.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentSystemComponent.cpp @@ -189,7 +189,7 @@ namespace MaterialEditor if (m_settings->m_showReloadDocumentPrompt && (QMessageBox::question(QApplication::activeWindow(), - QString("Material document was externally modified"), + QString("Document was externally modified"), QString("Would you like to reopen the document:\n%1?").arg(documentPath.c_str()), QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes)) { @@ -203,7 +203,7 @@ namespace MaterialEditor if (!openResult) { QMessageBox::critical( - QApplication::activeWindow(), QString("Material document could not be opened"), + QApplication::activeWindow(), QString("Document could not be opened"), QString("Failed to open: \n%1\n\n%2").arg(documentPath.c_str()).arg(traceRecorder.GetDump().c_str())); MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::CloseDocument, documentId); } @@ -216,7 +216,7 @@ namespace MaterialEditor if (m_settings->m_showReloadDocumentPrompt && (QMessageBox::question(QApplication::activeWindow(), - QString("Material document dependencies have changed"), + QString("Document dependencies have changed"), QString("Would you like to update the document with these changes:\n%1?").arg(documentPath.c_str()), QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes)) { @@ -230,7 +230,7 @@ namespace MaterialEditor if (!openResult) { QMessageBox::critical( - QApplication::activeWindow(), QString("Material document could not be opened"), + QApplication::activeWindow(), QString("Document could not be opened"), QString("Failed to open: \n%1\n\n%2").arg(documentPath.c_str()).arg(traceRecorder.GetDump().c_str())); MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::CloseDocument, documentId); } @@ -284,7 +284,7 @@ namespace MaterialEditor if (isModified) { auto selection = QMessageBox::question(QApplication::activeWindow(), - QString("Material document has unsaved changes"), + QString("Document has unsaved changes"), QString("Do you want to save changes to\n%1?").arg(documentPath.c_str()), QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); if (selection == QMessageBox::Cancel) @@ -309,7 +309,7 @@ namespace MaterialEditor if (!closeResult) { QMessageBox::critical( - QApplication::activeWindow(), QString("Material document could not be closed"), + QApplication::activeWindow(), QString("Document could not be closed"), QString("Failed to close: \n%1\n\n%2").arg(documentPath.c_str()).arg(traceRecorder.GetDump().c_str())); return false; } @@ -353,18 +353,18 @@ namespace MaterialEditor bool MaterialDocumentSystemComponent::SaveDocument(const AZ::Uuid& documentId) { - AZStd::string saveMaterialPath; - MaterialDocumentRequestBus::EventResult(saveMaterialPath, documentId, &MaterialDocumentRequestBus::Events::GetAbsolutePath); + AZStd::string saveDocumentPath; + MaterialDocumentRequestBus::EventResult(saveDocumentPath, documentId, &MaterialDocumentRequestBus::Events::GetAbsolutePath); - if (saveMaterialPath.empty() || !AzFramework::StringFunc::Path::Normalize(saveMaterialPath)) + if (saveDocumentPath.empty() || !AzFramework::StringFunc::Path::Normalize(saveDocumentPath)) { return false; } - const QFileInfo saveInfo(saveMaterialPath.c_str()); + const QFileInfo saveInfo(saveDocumentPath.c_str()); if (saveInfo.exists() && !saveInfo.isWritable()) { - QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Material document could not be overwritten:\n%1").arg(saveMaterialPath.c_str())); + QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Document could not be overwritten:\n%1").arg(saveDocumentPath.c_str())); return false; } @@ -375,8 +375,8 @@ namespace MaterialEditor if (!result) { QMessageBox::critical( - QApplication::activeWindow(), QString("Material document could not be saved"), - QString("Failed to save: \n%1\n\n%2").arg(saveMaterialPath.c_str()).arg(traceRecorder.GetDump().c_str())); + QApplication::activeWindow(), QString("Document could not be saved"), + QString("Failed to save: \n%1\n\n%2").arg(saveDocumentPath.c_str()).arg(traceRecorder.GetDump().c_str())); return false; } @@ -385,28 +385,28 @@ namespace MaterialEditor bool MaterialDocumentSystemComponent::SaveDocumentAsCopy(const AZ::Uuid& documentId, AZStd::string_view targetPath) { - AZStd::string saveMaterialPath = targetPath; - if (saveMaterialPath.empty() || !AzFramework::StringFunc::Path::Normalize(saveMaterialPath)) + AZStd::string saveDocumentPath = targetPath; + if (saveDocumentPath.empty() || !AzFramework::StringFunc::Path::Normalize(saveDocumentPath)) { return false; } - const QFileInfo saveInfo(saveMaterialPath.c_str()); + const QFileInfo saveInfo(saveDocumentPath.c_str()); if (saveInfo.exists() && !saveInfo.isWritable()) { - QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Material document could not be overwritten:\n%1").arg(saveMaterialPath.c_str())); + QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Document could not be overwritten:\n%1").arg(saveDocumentPath.c_str())); return false; } AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); bool result = false; - MaterialDocumentRequestBus::EventResult(result, documentId, &MaterialDocumentRequestBus::Events::SaveAsCopy, saveMaterialPath); + MaterialDocumentRequestBus::EventResult(result, documentId, &MaterialDocumentRequestBus::Events::SaveAsCopy, saveDocumentPath); if (!result) { QMessageBox::critical( - QApplication::activeWindow(), QString("Material document could not be saved"), - QString("Failed to save: \n%1\n\n%2").arg(saveMaterialPath.c_str()).arg(traceRecorder.GetDump().c_str())); + QApplication::activeWindow(), QString("Document could not be saved"), + QString("Failed to save: \n%1\n\n%2").arg(saveDocumentPath.c_str()).arg(traceRecorder.GetDump().c_str())); return false; } @@ -415,28 +415,28 @@ namespace MaterialEditor bool MaterialDocumentSystemComponent::SaveDocumentAsChild(const AZ::Uuid& documentId, AZStd::string_view targetPath) { - AZStd::string saveMaterialPath = targetPath; - if (saveMaterialPath.empty() || !AzFramework::StringFunc::Path::Normalize(saveMaterialPath)) + AZStd::string saveDocumentPath = targetPath; + if (saveDocumentPath.empty() || !AzFramework::StringFunc::Path::Normalize(saveDocumentPath)) { return false; } - const QFileInfo saveInfo(saveMaterialPath.c_str()); + const QFileInfo saveInfo(saveDocumentPath.c_str()); if (saveInfo.exists() && !saveInfo.isWritable()) { - QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Material document could not be overwritten:\n%1").arg(saveMaterialPath.c_str())); + QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Document could not be overwritten:\n%1").arg(saveDocumentPath.c_str())); return false; } AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); bool result = false; - MaterialDocumentRequestBus::EventResult(result, documentId, &MaterialDocumentRequestBus::Events::SaveAsChild, saveMaterialPath); + MaterialDocumentRequestBus::EventResult(result, documentId, &MaterialDocumentRequestBus::Events::SaveAsChild, saveDocumentPath); if (!result) { QMessageBox::critical( - QApplication::activeWindow(), QString("Material document could not be saved"), - QString("Failed to save: \n%1\n\n%2").arg(saveMaterialPath.c_str()).arg(traceRecorder.GetDump().c_str())); + QApplication::activeWindow(), QString("Document could not be saved"), + QString("Failed to save: \n%1\n\n%2").arg(saveDocumentPath.c_str()).arg(traceRecorder.GetDump().c_str())); return false; } @@ -467,7 +467,7 @@ namespace MaterialEditor if (!AzFramework::StringFunc::Path::Normalize(requestedPath)) { - QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Material document path is invalid:\n%1").arg(requestedPath.c_str())); + QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Document path is invalid:\n%1").arg(requestedPath.c_str())); return AZ::Uuid::CreateNull(); } @@ -476,9 +476,9 @@ namespace MaterialEditor { for (const auto& documentPair : m_documentMap) { - AZStd::string openMaterialPath; - MaterialDocumentRequestBus::EventResult(openMaterialPath, documentPair.first, &MaterialDocumentRequestBus::Events::GetAbsolutePath); - if (openMaterialPath == requestedPath) + AZStd::string openDocumentPath; + MaterialDocumentRequestBus::EventResult(openDocumentPath, documentPair.first, &MaterialDocumentRequestBus::Events::GetAbsolutePath); + if (openDocumentPath == requestedPath) { MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentOpened, documentPair.first); return documentPair.first; @@ -493,7 +493,7 @@ namespace MaterialEditor if (documentId.IsNull()) { QMessageBox::critical( - QApplication::activeWindow(), QString("Material document could not be created"), + QApplication::activeWindow(), QString("Document could not be created"), QString("Failed to create: \n%1\n\n%2").arg(requestedPath.c_str()).arg(traceRecorder.GetDump().c_str())); return AZ::Uuid::CreateNull(); } @@ -505,7 +505,7 @@ namespace MaterialEditor if (!openResult) { QMessageBox::critical( - QApplication::activeWindow(), QString("Material document could not be opened"), + QApplication::activeWindow(), QString("Document could not be opened"), QString("Failed to open: \n%1\n\n%2").arg(requestedPath.c_str()).arg(traceRecorder.GetDump().c_str())); MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::DestroyDocument, documentId); return AZ::Uuid::CreateNull(); diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp index f4dfa3df1b..52ce217834 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp @@ -36,8 +36,6 @@ AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnin #include #include #include -#include -#include #include AZ_POP_DISABLE_WARNING @@ -77,20 +75,13 @@ namespace MaterialEditor m_toolBar->setObjectName("ToolBar"); addToolBar(m_toolBar); - m_materialViewport = new MaterialViewportWidget(m_centralWidget); - m_materialViewport->setObjectName("Viewport"); - m_materialViewport->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); - CreateMenu(); CreateTabBar(); - QVBoxLayout* vl = new QVBoxLayout(m_centralWidget); - vl->setMargin(0); - vl->setContentsMargins(0, 0, 0, 0); - vl->addWidget(m_tabWidget); - vl->addWidget(m_materialViewport); - m_centralWidget->setLayout(vl); - setCentralWidget(m_centralWidget); + m_materialViewport = new MaterialViewportWidget(centralWidget()); + m_materialViewport->setObjectName("Viewport"); + m_materialViewport->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); + centralWidget()->layout()->addWidget(m_materialViewport); AddDockWidget("Asset Browser", new MaterialBrowserWidget, Qt::BottomDockWidgetArea, Qt::Vertical); AddDockWidget("Inspector", new MaterialInspector, Qt::RightDockWidgetArea, Qt::Horizontal); @@ -200,7 +191,7 @@ namespace MaterialEditor // Create a new tab for the document ID and assign it's label to the file name of the document. AddTabForDocumentId(documentId, filename, absolutePath, [this]{ // The tab widget requires a dummy page per tab - auto contentWidget = new QWidget(m_centralWidget); + auto contentWidget = new QWidget(centralWidget()); contentWidget->setContentsMargins(0, 0, 0, 0); contentWidget->setFixedSize(0, 0); return contentWidget; @@ -247,8 +238,8 @@ namespace MaterialEditor const QString documentPath = GetDocumentPath(documentId); if (!documentPath.isEmpty()) { - const QString status = QString("Material closed: %1").arg(documentPath); - m_statusBar->setWindowIconText(QString("%1").arg(status)); + const QString status = QString("Document closed: %1").arg(documentPath); + m_statusMessage->setText(QString("%1").arg(status)); } } @@ -258,7 +249,7 @@ namespace MaterialEditor const QString documentPath = GetDocumentPath(documentId); const QString status = QString("Material closed: %1").arg(documentPath); - m_statusBar->setWindowIconText(QString("%1").arg(status)); + m_statusMessage->setText(QString("%1").arg(status)); } void MaterialEditorWindow::OnDocumentModified(const AZ::Uuid& documentId) @@ -296,8 +287,8 @@ namespace MaterialEditor UpdateTabForDocumentId(documentId, filename, absolutePath, isModified); const QString documentPath = GetDocumentPath(documentId); - const QString status = QString("Material closed: %1").arg(documentPath); - m_statusBar->setWindowIconText(QString("%1").arg(status)); + const QString status = QString("Document closed: %1").arg(documentPath); + m_statusMessage->setText(QString("%1").arg(status)); } void MaterialEditorWindow::CreateMenu() @@ -341,8 +332,8 @@ namespace MaterialEditor if (!result) { const QString documentPath = GetDocumentPath(documentId); - const QString status = QString("Failed to save material: %1").arg(documentPath); - m_statusBar->setWindowIconText(QString("%1").arg(status)); + const QString status = QString("Failed to save document: %1").arg(documentPath); + m_statusMessage->setText(QString("%1").arg(status)); } }, QKeySequence::Save); @@ -355,8 +346,8 @@ namespace MaterialEditor documentId, AtomToolsFramework::GetSaveFileInfo(documentPath).absoluteFilePath().toUtf8().constData()); if (!result) { - const QString status = QString("Failed to save material: %1").arg(documentPath); - m_statusBar->setWindowIconText(QString("%1").arg(status)); + const QString status = QString("Failed to save document: %1").arg(documentPath); + m_statusMessage->setText(QString("%1").arg(status)); } }, QKeySequence::SaveAs); @@ -369,8 +360,8 @@ namespace MaterialEditor documentId, AtomToolsFramework::GetSaveFileInfo(documentPath).absoluteFilePath().toUtf8().constData()); if (!result) { - const QString status = QString("Failed to save material: %1").arg(documentPath); - m_statusBar->setWindowIconText(QString("%1").arg(status)); + const QString status = QString("Failed to save document: %1").arg(documentPath); + m_statusMessage->setText(QString("%1").arg(status)); } }); @@ -379,8 +370,8 @@ namespace MaterialEditor MaterialDocumentSystemRequestBus::BroadcastResult(result, &MaterialDocumentSystemRequestBus::Events::SaveAllDocuments); if (!result) { - const QString status = QString("Failed to save materials."); - m_statusBar->setWindowIconText(QString("%1").arg(status)); + const QString status = QString("Failed to save documents."); + m_statusMessage->setText(QString("%1").arg(status)); } }); @@ -425,8 +416,8 @@ namespace MaterialEditor if (!result) { const QString documentPath = GetDocumentPath(documentId); - const QString status = QString("Failed to perform Undo in material: %1").arg(documentPath); - m_statusBar->setWindowIconText(QString("%1").arg(status)); + const QString status = QString("Failed to perform Undo on document: %1").arg(documentPath); + m_statusMessage->setText(QString("%1").arg(status)); } }, QKeySequence::Undo); @@ -437,8 +428,8 @@ namespace MaterialEditor if (!result) { const QString documentPath = GetDocumentPath(documentId); - const QString status = QString("Failed to perform Undo in material: %1").arg(documentPath); - m_statusBar->setWindowIconText(QString("%1").arg(status)); + const QString status = QString("Failed to perform Redo on document: %1").arg(documentPath); + m_statusMessage->setText(QString("%1").arg(status)); } }, QKeySequence::Redo); diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowComponent.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowComponent.cpp index 8406ae891f..5359ba8e53 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowComponent.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowComponent.cpp @@ -30,47 +30,24 @@ namespace MaterialEditor serialize->Class() ->Version(0); } - - if (AZ::BehaviorContext* behaviorContext = azrtti_cast(context)) - { - behaviorContext->EBus("MaterialEditorWindowAtomRequestBus") - ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) - ->Attribute(AZ::Script::Attributes::Category, "Editor") - ->Attribute(AZ::Script::Attributes::Module, "materialeditor") - ->Event("CreateMaterialEditorWindow", &AtomToolsFramework::AtomToolsMainWindowFactoryRequestBus::Events::CreateMainWindow) - ->Event("DestroyMaterialEditorWindow", &AtomToolsFramework::AtomToolsMainWindowFactoryRequestBus::Events::DestroyMainWindow) - ; - - behaviorContext->EBus("MaterialEditorWindowRequestBus") - ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) - ->Attribute(AZ::Script::Attributes::Category, "Editor") - ->Attribute(AZ::Script::Attributes::Module, "materialeditor") - ->Event("ActivateWindow", &AtomToolsFramework::AtomToolsMainWindowRequestBus::Events::ActivateWindow) - ->Event("SetDockWidgetVisible", &AtomToolsFramework::AtomToolsMainWindowRequestBus::Events::SetDockWidgetVisible) - ->Event("IsDockWidgetVisible", &AtomToolsFramework::AtomToolsMainWindowRequestBus::Events::IsDockWidgetVisible) - ->Event("GetDockWidgetNames", &AtomToolsFramework::AtomToolsMainWindowRequestBus::Events::GetDockWidgetNames) - ->Event("ResizeViewportRenderTarget", &AtomToolsFramework::AtomToolsMainWindowRequestBus::Events::ResizeViewportRenderTarget) - ->Event("LockViewportRenderTargetSize", &AtomToolsFramework::AtomToolsMainWindowRequestBus::Events::LockViewportRenderTargetSize) - ->Event("UnlockViewportRenderTargetSize", &AtomToolsFramework::AtomToolsMainWindowRequestBus::Events::UnlockViewportRenderTargetSize) - ; - } } void MaterialEditorWindowComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) { - required.push_back(AZ_CRC("AssetBrowserService", 0x1e54fffb)); - required.push_back(AZ_CRC("PropertyManagerService", 0x63a3d7ad)); - required.push_back(AZ_CRC("SourceControlService", 0x67f338fd)); + required.push_back(AZ_CRC_CE("AssetBrowserService")); + required.push_back(AZ_CRC_CE("PropertyManagerService")); + required.push_back(AZ_CRC_CE("SourceControlService")); + required.push_back(AZ_CRC_CE("AtomToolsMainWindowSystemService")); } void MaterialEditorWindowComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) { - provided.push_back(AZ_CRC("MaterialEditorWindowService", 0xb6e7d922)); + provided.push_back(AZ_CRC_CE("MaterialEditorWindowService")); } void MaterialEditorWindowComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) { - incompatible.push_back(AZ_CRC("MaterialEditorWindowService", 0xb6e7d922)); + incompatible.push_back(AZ_CRC_CE("MaterialEditorWindowService")); } void MaterialEditorWindowComponent::Init() diff --git a/Gems/Atom/Tools/MaterialEditor/Scripts/GenerateAllMaterialScreenshots.py b/Gems/Atom/Tools/MaterialEditor/Scripts/GenerateAllMaterialScreenshots.py index d7f52d7a24..2116a3de6c 100755 --- a/Gems/Atom/Tools/MaterialEditor/Scripts/GenerateAllMaterialScreenshots.py +++ b/Gems/Atom/Tools/MaterialEditor/Scripts/GenerateAllMaterialScreenshots.py @@ -6,6 +6,7 @@ SPDX-License-Identifier: Apache-2.0 OR MIT """ import azlmbr.bus +import azlmbr.atomtools import azlmbr.materialeditor import azlmbr.name import azlmbr.render @@ -122,12 +123,12 @@ def CaptureScreenshot(screenshotOutputPath): def ResizeViewport(width, height): # This locks the size of the render target to the desired resolution - azlmbr.materialeditor.MaterialEditorWindowRequestBus(azlmbr.bus.Broadcast, 'LockViewportRenderTargetSize', width, height) + azlmbr.atomtools.AtomToolsMainWindowRequestBus(azlmbr.bus.Broadcast, 'LockViewportRenderTargetSize', width, height) # This resizes the window to closely match the render target resolution so it doesn't appear stretched while the script is running - azlmbr.materialeditor.MaterialEditorWindowRequestBus(azlmbr.bus.Broadcast, 'ResizeViewportRenderTarget', width, height) + azlmbr.atomtools.AtomToolsMainWindowRequestBus(azlmbr.bus.Broadcast, 'ResizeViewportRenderTarget', width, height) def ReleaseViewportResolutionLock(): - azlmbr.materialeditor.MaterialEditorWindowRequestBus(azlmbr.bus.Broadcast, 'UnlockViewportRenderTargetSize') + azlmbr.atomtools.AtomToolsMainWindowRequestBus(azlmbr.bus.Broadcast, 'UnlockViewportRenderTargetSize') def GenerateMaterialScreenshot(materialName, uniqueSuffix="", diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Include/Atom/Document/ShaderManagementConsoleDocumentNotificationBus.h b/Gems/Atom/Tools/ShaderManagementConsole/Code/Include/Atom/Document/ShaderManagementConsoleDocumentNotificationBus.h index e497b2bc2f..68325beabb 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Include/Atom/Document/ShaderManagementConsoleDocumentNotificationBus.h +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Include/Atom/Document/ShaderManagementConsoleDocumentNotificationBus.h @@ -10,6 +10,9 @@ #include #include +#include +#include + namespace ShaderManagementConsole { class ShaderManagementConsoleDocumentNotifications @@ -47,9 +50,33 @@ namespace ShaderManagementConsole //! @param documentId unique id of document for which the notification is sent virtual void OnDocumentModified([[maybe_unused]] const AZ::Uuid& documentId) {} + //! Signal that a document dependency was modified + //! @param documentId unique id of document for which the notification is sent + virtual void OnDocumentDependencyModified([[maybe_unused]] const AZ::Uuid& documentId) {} + + //! Signal that a document was modified externally + //! @param documentId unique id of document for which the notification is sent + virtual void OnDocumentExternallyModified([[maybe_unused]] const AZ::Uuid& documentId) {} + //! Signal that a document undo state was updated //! @param documentId unique id of document for which the notification is sent virtual void OnDocumentUndoStateChanged([[maybe_unused]] const AZ::Uuid& documentId) {} + + //! Signal that a property changed + //! @param documentId unique id of document for which the notification is sent + //! @param property object containing the property value and configuration that was modified + virtual void OnDocumentPropertyValueModified([[maybe_unused]] const AZ::Uuid& documentId, [[maybe_unused]] const AtomToolsFramework::DynamicProperty& property) {} + + //! Signal that the property configuration has been changed. + //! @param documentId unique id of document for which the notification is sent + //! @param property object containing the property value and configuration that was modified + virtual void OnDocumentPropertyConfigModified([[maybe_unused]] const AZ::Uuid& documentId, [[maybe_unused]] const AtomToolsFramework::DynamicProperty& property) {} + + //! Signal that the property group visibility has been changed. + //! @param documentId unique id of document for which the notification is sent + //! @param groupId id of the group that changed + //! @param visible whether the property group is visible + virtual void OnDocumentPropertyGroupVisibilityChanged([[maybe_unused]] const AZ::Uuid& documentId, [[maybe_unused]] const AZ::Name& groupId, [[maybe_unused]] bool visible) {} }; using ShaderManagementConsoleDocumentNotificationBus = AZ::EBus; diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Include/Atom/Document/ShaderManagementConsoleDocumentRequestBus.h b/Gems/Atom/Tools/ShaderManagementConsole/Code/Include/Atom/Document/ShaderManagementConsoleDocumentRequestBus.h index 25e157d1f3..ed002f65ed 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Include/Atom/Document/ShaderManagementConsoleDocumentRequestBus.h +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Include/Atom/Document/ShaderManagementConsoleDocumentRequestBus.h @@ -18,7 +18,6 @@ namespace ShaderManagementConsole { - using ShaderManagementConsoleDocumentResult = AZ::Outcome; class ShaderManagementConsoleDocumentRequests : public AZ::EBusTraits @@ -48,17 +47,17 @@ namespace ShaderManagementConsole //! Load document and related data //! @param loadPath Absolute path of document to load - virtual ShaderManagementConsoleDocumentResult Open(AZStd::string_view loadPath) = 0; + virtual bool Open(AZStd::string_view loadPath) = 0; //! Save document to file - virtual ShaderManagementConsoleDocumentResult Save() = 0; + virtual bool Save() = 0; //! Save document copy //! @param savePath Absolute path where document is saved - virtual ShaderManagementConsoleDocumentResult SaveAsCopy(AZStd::string_view savePath) = 0; + virtual bool SaveAsCopy(AZStd::string_view savePath) = 0; //! Close document and reset its data - virtual ShaderManagementConsoleDocumentResult Close() = 0; + virtual bool Close() = 0; //! document is loaded virtual bool IsOpen() const = 0; diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Include/Atom/Document/ShaderManagementConsoleDocumentSystemRequestBus.h b/Gems/Atom/Tools/ShaderManagementConsole/Code/Include/Atom/Document/ShaderManagementConsoleDocumentSystemRequestBus.h index b21686ebaf..93c46f442f 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Include/Atom/Document/ShaderManagementConsoleDocumentSystemRequestBus.h +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Include/Atom/Document/ShaderManagementConsoleDocumentSystemRequestBus.h @@ -29,9 +29,9 @@ namespace ShaderManagementConsole virtual bool DestroyDocument(const AZ::Uuid& documentId) = 0; //! Open a document for editing - //! @param path document to edit. + //! @param sourcePath document to open. //! @return unique id of new document if successful, otherwise null Uuid - virtual AZ::Uuid OpenDocument(AZStd::string_view path) = 0; + virtual AZ::Uuid OpenDocument(AZStd::string_view sourcePath) = 0; //! Close the specified document //! @param documentId unique id of document to close @@ -40,13 +40,18 @@ namespace ShaderManagementConsole //! Close all documents virtual bool CloseAllDocuments() = 0; + //! Close all documents except for documentId + //! @param documentId unique id of document to not close + virtual bool CloseAllDocumentsExcept(const AZ::Uuid& documentId) = 0; + //! Save the specified document //! @param documentId unique id of document to save virtual bool SaveDocument(const AZ::Uuid& documentId) = 0; //! Save the specified document to a different file //! @param documentId unique id of document to save - virtual bool SaveDocumentAsCopy(const AZ::Uuid& documentId) = 0; + //! @param targetPath location where document is saved. + virtual bool SaveDocumentAsCopy(const AZ::Uuid& documentId, AZStd::string_view targetPath) = 0; //! Save all documents virtual bool SaveAllDocuments() = 0; diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocument.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocument.cpp index 67990d4b71..9dae9c10cc 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocument.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocument.cpp @@ -28,6 +28,7 @@ namespace ShaderManagementConsole { ShaderManagementConsoleDocumentNotificationBus::Broadcast(&ShaderManagementConsoleDocumentNotificationBus::Events::OnDocumentDestroyed, m_id); ShaderManagementConsoleDocumentRequestBus::Handler::BusDisconnect(); + Clear(); } const AZ::Uuid& ShaderManagementConsoleDocument::GetId() const @@ -71,19 +72,21 @@ namespace ShaderManagementConsole return m_shaderVariantListSourceData.m_shaderVariants[index]; } - ShaderManagementConsoleDocumentResult ShaderManagementConsoleDocument::Open(AZStd::string_view loadPath) + bool ShaderManagementConsoleDocument::Open(AZStd::string_view loadPath) { Clear(); m_absolutePath = loadPath; if (!AzFramework::StringFunc::Path::Normalize(m_absolutePath)) { - return AZ::Failure(AZStd::string::format("Document path could not be normalized: '%s'.", m_absolutePath.c_str())); + AZ_Error("ShaderManagementConsoleDocument", false, "Document path could not be normalized: '%s'.", m_absolutePath.c_str()); + return false; } if (AzFramework::StringFunc::Path::IsRelative(m_absolutePath.c_str())) { - return AZ::Failure(AZStd::string::format("Document path must be absolute: '%s'.", m_absolutePath.c_str())); + AZ_Error("ShaderManagementConsoleDocument", false, "Document path must be absolute: '%s'.", m_absolutePath.c_str()); + return false; } if (AzFramework::StringFunc::Path::IsExtension(m_absolutePath.c_str(), AZ::RPI::ShaderVariantListSourceData::Extension)) @@ -91,7 +94,8 @@ namespace ShaderManagementConsole // Load the shader config data and create a shader config asset from it if (!AZ::RPI::JsonUtils::LoadObjectFromFile(m_absolutePath, m_shaderVariantListSourceData)) { - return AZ::Failure(AZStd::string::format("Failed loading shader variant list data: '%s.'", m_absolutePath.c_str())); + AZ_Error("ShaderManagementConsoleDocument", false, "Failed loading shader variant list data: '%s.'", m_absolutePath.c_str()); + return false; } } @@ -103,13 +107,15 @@ namespace ShaderManagementConsole watchFolder); if (!result) { - return AZ::Failure(AZStd::string::format("Could not find source data: '%s'.", m_absolutePath.c_str())); + AZ_Error("ShaderManagementConsoleDocument", false, "Could not find source data: '%s'.", m_absolutePath.c_str()); + return false; } m_relativePath = m_shaderVariantListSourceData.m_shaderFilePath; if (!AzFramework::StringFunc::Path::Normalize(m_relativePath)) { - return AZ::Failure(AZStd::string::format("Shader path could not be normalized: '%s'.", m_relativePath.c_str())); + AZ_Error("ShaderManagementConsoleDocument", false, "Shader path could not be normalized: '%s'.", m_relativePath.c_str()); + return false; } AZStd::string shaderPath = m_relativePath; @@ -118,27 +124,32 @@ namespace ShaderManagementConsole m_shaderAsset = AZ::RPI::AssetUtils::LoadAssetByProductPath(shaderPath.c_str()); if (!m_shaderAsset) { - return AZ::Failure(AZStd::string::format("Could not load shader asset: %s.", shaderPath.c_str())); + AZ_Error("ShaderManagementConsoleDocument", false, "Could not load shader asset: %s.", shaderPath.c_str()); + return false; } ShaderManagementConsoleDocumentNotificationBus::Broadcast(&ShaderManagementConsoleDocumentNotificationBus::Events::OnDocumentOpened, m_id); - return AZ::Success(AZStd::string::format("Document loaded: '%s'", m_absolutePath.c_str())); + AZ_TracePrintf("ShaderManagementConsoleDocument", "Document loaded: '%s'", m_absolutePath.c_str()); + return true; } - ShaderManagementConsoleDocumentResult ShaderManagementConsoleDocument::Save() + bool ShaderManagementConsoleDocument::Save() { if (!IsOpen()) { - return AZ::Failure(AZStd::string::format("Document is not open to be saved: '%s'.", m_absolutePath.c_str())); + AZ_Error("ShaderManagementConsoleDocument", false, "Document is not open to be saved: '%s'.", m_absolutePath.c_str()); + return false; } if (!IsSavable()) { - return AZ::Failure(AZStd::string::format("Document can not be saved: '%s'.", m_absolutePath.c_str())); + AZ_Error("ShaderManagementConsoleDocument", false, "Document can not be saved: '%s'.", m_absolutePath.c_str()); + return false; } - return AZ::Failure(AZStd::string::format("%s is not implemented!", __FUNCTION__)); + AZ_Error("ShaderManagementConsoleDocument", false, "%s is not implemented!", __FUNCTION__); + return false; // Auto add or checkout saved file //AzToolsFramework::SourceControlCommandBus::Broadcast(&AzToolsFramework::SourceControlCommandBus::Events::RequestEdit, @@ -147,28 +158,33 @@ namespace ShaderManagementConsole //ShaderManagementConsoleDocumentNotificationBus::Broadcast(&ShaderManagementConsoleDocumentNotificationBus::Events::OnDocumentSaved, m_id); - //return AZ::Success(AZStd::string::format("Document saved: %s", m_absolutePath.data())); + //AZ_TracePrintf("ShaderManagementConsoleDocument", "Document saved: %s", m_absolutePath.data()); + //return true; } - ShaderManagementConsoleDocumentResult ShaderManagementConsoleDocument::SaveAsCopy(AZStd::string_view savePath) + bool ShaderManagementConsoleDocument::SaveAsCopy(AZStd::string_view savePath) { if (!IsOpen()) { - return AZ::Failure(AZStd::string::format("Document is not open to be saved: '%s'.", m_absolutePath.c_str())); + AZ_Error("ShaderManagementConsoleDocument", false, "Document is not open to be saved: '%s'.", m_absolutePath.c_str()); + return false; } if (!IsSavable()) { - return AZ::Failure(AZStd::string::format("Document can not be saved: '%s'.", m_absolutePath.c_str())); + AZ_Error("ShaderManagementConsoleDocument", false, "Document can not be saved: '%s'.", m_absolutePath.c_str()); + return false; } AZStd::string normalizedSavePath = savePath; if (!AzFramework::StringFunc::Path::Normalize(normalizedSavePath)) { - return AZ::Failure(AZStd::string::format("Document save path could not be normalized: '%s'.", normalizedSavePath.c_str())); + AZ_Error("ShaderManagementConsoleDocument", false, "Document save path could not be normalized: '%s'.", normalizedSavePath.c_str()); + return false; } - return AZ::Failure(AZStd::string::format("%s is not implemented!", __FUNCTION__)); + AZ_Error("ShaderManagementConsoleDocument", false, "%s is not implemented!", __FUNCTION__); + return false; // Auto add or checkout saved file //AzToolsFramework::SourceControlCommandBus::Broadcast(&AzToolsFramework::SourceControlCommandBus::Events::RequestEdit, @@ -177,19 +193,22 @@ namespace ShaderManagementConsole //ShaderManagementConsoleDocumentNotificationBus::Broadcast(&ShaderManagementConsoleDocumentNotificationBus::Events::OnDocumentSaved, m_id); - //return AZ::Success(AZStd::string::format("Document saved: %s", normalizedSavePath.c_str())); + //AZ_TracePrintf("ShaderManagementConsoleDocument", "Document saved: %s", normalizedSavePath.c_str()); + //return true; } - ShaderManagementConsoleDocumentResult ShaderManagementConsoleDocument::Close() + bool ShaderManagementConsoleDocument::Close() { if (!IsOpen()) { - return AZ::Failure(AZStd::string("Document is not open")); + AZ_Error("ShaderManagementConsoleDocument", false, "Document is not open"); + return false; } Clear(); ShaderManagementConsoleDocumentNotificationBus::Broadcast(&ShaderManagementConsoleDocumentNotificationBus::Events::OnDocumentClosed, m_id); - return AZ::Success(AZStd::string("Document was closed")); + AZ_TracePrintf("ShaderManagementConsoleDocument", "Document was closed"); + return true; } bool ShaderManagementConsoleDocument::IsOpen() const @@ -269,5 +288,9 @@ namespace ShaderManagementConsole { m_absolutePath.clear(); m_relativePath.clear(); + m_shaderVariantListSourceData = {}; + m_shaderAsset = {}; + m_undoHistory = {}; + m_undoHistoryIndex = {}; } } // namespace ShaderManagementConsole diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocument.h b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocument.h index 6c9580c086..3d1a88c62e 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocument.h +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocument.h @@ -41,10 +41,10 @@ namespace ShaderManagementConsole const AZ::RPI::ShaderOptionDescriptor& GetShaderOptionDescriptor(size_t index) const override; size_t GetShaderVariantCount() const override; const AZ::RPI::ShaderVariantListSourceData::VariantInfo& GetShaderVariantInfo(size_t index) const override; - ShaderManagementConsoleDocumentResult Open(AZStd::string_view loadPath) override; - ShaderManagementConsoleDocumentResult Save() override; - ShaderManagementConsoleDocumentResult SaveAsCopy(AZStd::string_view savePath) override; - ShaderManagementConsoleDocumentResult Close() override; + bool Open(AZStd::string_view loadPath) override; + bool Save() override; + bool SaveAsCopy(AZStd::string_view savePath) override; + bool Close() override; bool IsOpen() const override; bool IsModified() const override; bool IsSavable() const override; diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocumentSystemComponent.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocumentSystemComponent.cpp index fae9ec75ef..f06aae29d7 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocumentSystemComponent.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocumentSystemComponent.cpp @@ -8,9 +8,11 @@ #include -#include -#include +#include +#include #include +#include +#include #include #include @@ -67,6 +69,7 @@ namespace ShaderManagementConsole ->Event("OpenDocument", &ShaderManagementConsoleDocumentSystemRequestBus::Events::OpenDocument) ->Event("CloseDocument", &ShaderManagementConsoleDocumentSystemRequestBus::Events::CloseDocument) ->Event("CloseAllDocuments", &ShaderManagementConsoleDocumentSystemRequestBus::Events::CloseAllDocuments) + ->Event("CloseAllDocumentsExcept", &ShaderManagementConsoleDocumentSystemRequestBus::Events::CloseAllDocumentsExcept) ->Event("SaveDocument", &ShaderManagementConsoleDocumentSystemRequestBus::Events::SaveDocument) ->Event("SaveDocumentAsCopy", &ShaderManagementConsoleDocumentSystemRequestBus::Events::SaveDocumentAsCopy) ->Event("SaveAllDocuments", &ShaderManagementConsoleDocumentSystemRequestBus::Events::SaveAllDocuments) @@ -152,9 +155,9 @@ namespace ShaderManagementConsole return m_documentMap.erase(documentId) != 0; } - AZ::Uuid ShaderManagementConsoleDocumentSystemComponent::OpenDocument(AZStd::string_view path) + AZ::Uuid ShaderManagementConsoleDocumentSystemComponent::OpenDocument(AZStd::string_view sourcePath) { - return OpenDocumentImpl(path, true); + return OpenDocumentImpl(sourcePath, true); } bool ShaderManagementConsoleDocumentSystemComponent::CloseDocument(const AZ::Uuid& documentId) @@ -163,26 +166,46 @@ namespace ShaderManagementConsole ShaderManagementConsoleDocumentRequestBus::EventResult(isOpen, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::IsOpen); if (!isOpen) { + // immediately destroy unopened documents + ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::DestroyDocument, documentId); return true; } + AZStd::string documentPath; + ShaderManagementConsoleDocumentRequestBus::EventResult(documentPath, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::GetAbsolutePath); + bool isModified = false; ShaderManagementConsoleDocumentRequestBus::EventResult(isModified, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::IsModified); if (isModified) { - if (QMessageBox::question(QApplication::activeWindow(), "document has unsaved changes", "Would you like to close anyway?", - QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) + auto selection = QMessageBox::question(QApplication::activeWindow(), + QString("Document has unsaved changes"), + QString("Do you want to save changes to\n%1?").arg(documentPath.c_str()), + QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); + if (selection == QMessageBox::Cancel) { + AZ_TracePrintf("ShaderManagementConsoleDocument", "Close document canceled: %s", documentPath.c_str()); return false; } + if (selection == QMessageBox::Yes) + { + if (!SaveDocument(documentId)) + { + AZ_Error("ShaderManagementConsoleDocument", false, "Close document failed because document was not saved: %s", documentPath.c_str()); + return false; + } + } } - ShaderManagementConsoleDocumentResult closeResult = AZ::Success(AZStd::string("There is no active document")); + AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); + + bool closeResult = true; ShaderManagementConsoleDocumentRequestBus::EventResult(closeResult, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::Close); if (!closeResult) { - QMessageBox::critical(QApplication::activeWindow(), "Failed to close document", - QString::fromUtf8(closeResult.GetError().data(), (int)closeResult.GetError().size())); + QMessageBox::critical( + QApplication::activeWindow(), QString("Document could not be closed"), + QString("Failed to close: \n%1\n\n%2").arg(documentPath.c_str()).arg(traceRecorder.GetDump().c_str())); return false; } @@ -205,60 +228,83 @@ namespace ShaderManagementConsole return result; } + bool ShaderManagementConsoleDocumentSystemComponent::CloseAllDocumentsExcept(const AZ::Uuid& documentId) + { + bool result = true; + auto documentMap = m_documentMap; + for (const auto& documentPair : documentMap) + { + if (documentPair.first != documentId) + { + if (!CloseDocument(documentPair.first)) + { + result = false; + } + } + } + + return result; + } + bool ShaderManagementConsoleDocumentSystemComponent::SaveDocument(const AZ::Uuid& documentId) { - AZStd::string documentPath; - ShaderManagementConsoleDocumentRequestBus::EventResult(documentPath, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::GetAbsolutePath); + AZStd::string saveDocumentPath; + ShaderManagementConsoleDocumentRequestBus::EventResult(saveDocumentPath, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::GetAbsolutePath); - const QFileInfo saveInfo(documentPath.c_str()); - if (saveInfo.absoluteFilePath().isEmpty()) + if (saveDocumentPath.empty() || !AzFramework::StringFunc::Path::Normalize(saveDocumentPath)) { return false; } + const QFileInfo saveInfo(saveDocumentPath.c_str()); if (saveInfo.exists() && !saveInfo.isWritable()) { - QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Unable to save document. File can not be overwritten.")); + QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Document could not be overwritten:\n%1").arg(saveDocumentPath.c_str())); return false; } - ShaderManagementConsoleDocumentResult result = AZ::Failure(AZStd::string("There is no active document")); + AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); + + bool result = false; ShaderManagementConsoleDocumentRequestBus::EventResult(result, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::Save); if (!result) { - QMessageBox::critical(QApplication::activeWindow(), "document not saved", - QString::fromUtf8(result.GetError().data(), (int)result.GetError().size())); + QMessageBox::critical( + QApplication::activeWindow(), QString("Document could not be saved"), + QString("Failed to save: \n%1\n\n%2").arg(saveDocumentPath.c_str()).arg(traceRecorder.GetDump().c_str())); return false; } - AZ_TracePrintf("ShaderManagementConsole", "%s\n", result.GetValue().c_str()); return true; } - bool ShaderManagementConsoleDocumentSystemComponent::SaveDocumentAsCopy(const AZ::Uuid& documentId) + bool ShaderManagementConsoleDocumentSystemComponent::SaveDocumentAsCopy(const AZ::Uuid& documentId, AZStd::string_view targetPath) { - AZStd::string documentPath; - ShaderManagementConsoleDocumentRequestBus::EventResult(documentPath, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::GetAbsolutePath); - - const QFileInfo& saveInfo = AtomToolsFramework::GetSaveFileInfo(documentPath.c_str()); - if (saveInfo.absoluteFilePath().isEmpty()) + AZStd::string saveDocumentPath = targetPath; + if (saveDocumentPath.empty() || !AzFramework::StringFunc::Path::Normalize(saveDocumentPath)) { return false; } - AZStd::string saveDocumentPath = saveInfo.absoluteFilePath().toUtf8().constData(); - AzFramework::StringFunc::Path::Normalize(saveDocumentPath); + const QFileInfo saveInfo(saveDocumentPath.c_str()); + if (saveInfo.exists() && !saveInfo.isWritable()) + { + QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Document could not be overwritten:\n%1").arg(saveDocumentPath.c_str())); + return false; + } - ShaderManagementConsoleDocumentResult result = AZ::Failure(AZStd::string("There is no active document")); + AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); + + bool result = false; ShaderManagementConsoleDocumentRequestBus::EventResult(result, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::SaveAsCopy, saveDocumentPath); if (!result) { - QMessageBox::critical(QApplication::activeWindow(), "document copy not saved", - QString::fromUtf8(result.GetError().data(), (int)result.GetError().size())); + QMessageBox::critical( + QApplication::activeWindow(), QString("Document could not be saved"), + QString("Failed to save: \n%1\n\n%2").arg(saveDocumentPath.c_str()).arg(traceRecorder.GetDump().c_str())); return false; } - AZ_TracePrintf("ShaderManagementConsole", "%s\n", result.GetValue().c_str()); return true; } @@ -276,13 +322,17 @@ namespace ShaderManagementConsole return result; } - AZ::Uuid ShaderManagementConsoleDocumentSystemComponent::OpenDocumentImpl(AZStd::string_view path, bool checkIfAlreadyOpen) + AZ::Uuid ShaderManagementConsoleDocumentSystemComponent::OpenDocumentImpl(AZStd::string_view sourcePath, bool checkIfAlreadyOpen) { - AZStd::string requestedPath = path; - if (requestedPath.empty() || !AzFramework::StringFunc::Path::Normalize(requestedPath)) + AZStd::string requestedPath = sourcePath; + if (requestedPath.empty()) { - QMessageBox::critical(QApplication::activeWindow(), "document path is invalid", - QString::fromUtf8(requestedPath.data(), (int)requestedPath.size())); + return AZ::Uuid::CreateNull(); + } + + if (!AzFramework::StringFunc::Path::Normalize(requestedPath)) + { + QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Document path is invalid:\n%1").arg(requestedPath.c_str())); return AZ::Uuid::CreateNull(); } @@ -301,21 +351,27 @@ namespace ShaderManagementConsole } } + AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); + AZ::Uuid documentId = AZ::Uuid::CreateNull(); ShaderManagementConsoleDocumentSystemRequestBus::BroadcastResult(documentId, &ShaderManagementConsoleDocumentSystemRequestBus::Events::CreateDocument); if (documentId.IsNull()) { - QMessageBox::critical(QApplication::activeWindow(), "Failed to create document", - QString::fromUtf8(requestedPath.data(), (int)requestedPath.size())); + QMessageBox::critical( + QApplication::activeWindow(), QString("Document could not be created"), + QString("Failed to create: \n%1\n\n%2").arg(requestedPath.c_str()).arg(traceRecorder.GetDump().c_str())); return AZ::Uuid::CreateNull(); } - ShaderManagementConsoleDocumentResult openResult = AZ::Failure(AZStd::string("Failed to open document")); + traceRecorder.GetDump().clear(); + + bool openResult = false; ShaderManagementConsoleDocumentRequestBus::EventResult(openResult, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::Open, requestedPath); if (!openResult) { - QMessageBox::critical(QApplication::activeWindow(), "Failed to open document", - QString::fromUtf8(openResult.GetError().data(), (int)openResult.GetError().size())); + QMessageBox::critical( + QApplication::activeWindow(), QString("Document could not be opened"), + QString("Failed to open: \n%1\n\n%2").arg(requestedPath.c_str()).arg(traceRecorder.GetDump().c_str())); ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::DestroyDocument, documentId); return AZ::Uuid::CreateNull(); } diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocumentSystemComponent.h b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocumentSystemComponent.h index 245222976e..05c61ce058 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocumentSystemComponent.h +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocumentSystemComponent.h @@ -53,16 +53,18 @@ namespace ShaderManagementConsole // ShaderManagementConsoleDocumentSystemRequestBus::Handler overrides... AZ::Uuid CreateDocument() override; bool DestroyDocument(const AZ::Uuid& documentId) override; - AZ::Uuid OpenDocument(AZStd::string_view path) override; + AZ::Uuid OpenDocument(AZStd::string_view sourcePath) override; bool CloseDocument(const AZ::Uuid& documentId) override; bool CloseAllDocuments() override; + bool CloseAllDocumentsExcept(const AZ::Uuid& documentId) override; bool SaveDocument(const AZ::Uuid& documentId) override; - bool SaveDocumentAsCopy(const AZ::Uuid& documentId) override; + bool SaveDocumentAsCopy(const AZ::Uuid& documentId, AZStd::string_view targetPath) override; bool SaveAllDocuments() override; //////////////////////////////////////////////////////////////////////// - AZ::Uuid OpenDocumentImpl(AZStd::string_view path, bool checkIfAlreadyOpen); + AZ::Uuid OpenDocumentImpl(AZStd::string_view sourcePath, bool checkIfAlreadyOpen); AZStd::unordered_map> m_documentMap; + const size_t m_maxMessageBoxLineCount = 15; }; } diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp index 0a082f3c33..b23e828d5e 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp @@ -8,6 +8,8 @@ #include #include +#include +#include #include #include #include @@ -23,11 +25,8 @@ AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnin #include #include #include -#include #include #include -#include -#include #include AZ_POP_DISABLE_WARNING @@ -36,6 +35,14 @@ namespace ShaderManagementConsole ShaderManagementConsoleWindow::ShaderManagementConsoleWindow(QWidget* parent /* = 0 */) : AtomToolsFramework::AtomToolsMainWindow(parent) { + resize(1280, 1024); + + // Among other things, we need the window wrapper to save the main window size, position, and state + auto mainWindowWrapper = + new AzQtComponents::WindowDecorationWrapper(AzQtComponents::WindowDecorationWrapper::OptionAutoTitleBarButtons); + mainWindowWrapper->setGuest(this); + mainWindowWrapper->enableSaveRestoreGeometry("O3DE", "ShaderManagementConsole", "mainWindowGeometry"); + setWindowTitle("Shader Management Console"); setObjectName("ShaderManagementConsoleWindow"); @@ -47,16 +54,14 @@ namespace ShaderManagementConsole CreateMenu(); CreateTabBar(); - QVBoxLayout* vl = new QVBoxLayout(m_centralWidget); - vl->setMargin(0); - vl->setContentsMargins(0, 0, 0, 0); - vl->addWidget(m_tabWidget); - m_centralWidget->setLayout(vl); - setCentralWidget(m_centralWidget); - AddDockWidget("Asset Browser", new ShaderManagementConsoleBrowserWidget, Qt::BottomDockWidgetArea, Qt::Vertical); AddDockWidget("Python Terminal", new AzToolsFramework::CScriptTermDialog, Qt::BottomDockWidgetArea, Qt::Horizontal); + SetDockWidgetVisible("Python Terminal", false); + + // Restore geometry and show the window + mainWindowWrapper->showFromSettings(); + ShaderManagementConsoleDocumentNotificationBus::Handler::BusConnect(); OnDocumentOpened(AZ::Uuid::CreateNull()); } @@ -103,8 +108,7 @@ namespace ShaderManagementConsole // Create a new tab for the document ID and assign it's label to the file name of the document. AddTabForDocumentId(documentId, filename, absolutePath, [this, documentId]{ // The document tab contains a table view. - auto contentWidget = new QTableView(m_centralWidget); - contentWidget->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + auto contentWidget = new QTableView(centralWidget()); contentWidget->setSelectionBehavior(QAbstractItemView::SelectRows); contentWidget->setModel(CreateDocumentContent(documentId)); return contentWidget; @@ -142,11 +146,22 @@ namespace ShaderManagementConsole activateWindow(); raise(); + + const QString documentPath = GetDocumentPath(documentId); + if (!documentPath.isEmpty()) + { + const QString status = QString("Document closed: %1").arg(documentPath); + m_statusMessage->setText(QString("%1").arg(status)); + } } void ShaderManagementConsoleWindow::OnDocumentClosed(const AZ::Uuid& documentId) { RemoveTabForDocumentId(documentId); + + const QString documentPath = GetDocumentPath(documentId); + const QString status = QString("Document closed: %1").arg(documentPath); + m_statusMessage->setText(QString("%1").arg(status)); } void ShaderManagementConsoleWindow::OnDocumentModified(const AZ::Uuid& documentId) @@ -182,6 +197,10 @@ namespace ShaderManagementConsole AZStd::string filename; AzFramework::StringFunc::Path::GetFullFileName(absolutePath.c_str(), filename); UpdateTabForDocumentId(documentId, filename, absolutePath, isModified); + + const QString documentPath = GetDocumentPath(documentId); + const QString status = QString("Document closed: %1").arg(documentPath); + m_statusMessage->setText(QString("%1").arg(status)); } void ShaderManagementConsoleWindow::CreateMenu() @@ -206,8 +225,47 @@ namespace ShaderManagementConsole m_menuFile->addSeparator(); + m_actionSave = m_menuFile->addAction("&Save", [this]() { + const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex()); + bool result = false; + ShaderManagementConsoleDocumentSystemRequestBus::BroadcastResult(result, &ShaderManagementConsoleDocumentSystemRequestBus::Events::SaveDocument, documentId); + if (!result) + { + const QString documentPath = GetDocumentPath(documentId); + const QString status = QString("Failed to save document: %1").arg(documentPath); + m_statusMessage->setText(QString("%1").arg(status)); + } + }, QKeySequence::Save); + + m_actionSaveAsCopy = m_menuFile->addAction("Save &As...", [this]() { + const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex()); + const QString documentPath = GetDocumentPath(documentId); + + bool result = false; + ShaderManagementConsoleDocumentSystemRequestBus::BroadcastResult(result, &ShaderManagementConsoleDocumentSystemRequestBus::Events::SaveDocumentAsCopy, + documentId, AtomToolsFramework::GetSaveFileInfo(documentPath).absoluteFilePath().toUtf8().constData()); + if (!result) + { + const QString status = QString("Failed to save document: %1").arg(documentPath); + m_statusMessage->setText(QString("%1").arg(status)); + } + }, QKeySequence::SaveAs); + + m_actionSaveAll = m_menuFile->addAction("Save A&ll", [this]() { + bool result = false; + ShaderManagementConsoleDocumentSystemRequestBus::BroadcastResult(result, &ShaderManagementConsoleDocumentSystemRequestBus::Events::SaveAllDocuments); + if (!result) + { + const QString status = QString("Failed to save documents."); + m_statusMessage->setText(QString("%1").arg(status)); + } + }); + + m_menuFile->addSeparator(); + m_actionClose = m_menuFile->addAction("&Close", [this]() { - CloseDocumentForTab(m_tabWidget->currentIndex()); + const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex()); + ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::CloseDocument, documentId); }, QKeySequence::Close); m_actionCloseAll = m_menuFile->addAction("Close All", [this]() { @@ -215,23 +273,8 @@ namespace ShaderManagementConsole }); m_actionCloseOthers = m_menuFile->addAction("Close Others", [this]() { - CloseAllExceptDocumentForTab(m_tabWidget->currentIndex()); - }); - - m_menuFile->addSeparator(); - - m_actionSave = m_menuFile->addAction("&Save", [this]() { const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex()); - ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::SaveDocument, documentId); - }, QKeySequence::Save); - - m_actionSaveAsCopy = m_menuFile->addAction("Save &As...", [this]() { - const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex()); - ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::SaveDocumentAsCopy, documentId); - }, QKeySequence::SaveAs); - - m_actionSaveAll = m_menuFile->addAction("Save A&ll", [this]() { - ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::SaveAllDocuments); + ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::CloseAllDocumentsExcept, documentId); }); m_menuFile->addSeparator(); @@ -254,37 +297,46 @@ namespace ShaderManagementConsole m_actionUndo = m_menuEdit->addAction("&Undo", [this]() { const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex()); - ShaderManagementConsoleDocumentRequestBus::Event(documentId, &ShaderManagementConsoleDocumentRequestBus::Events::Undo); + bool result = false; + ShaderManagementConsoleDocumentRequestBus::EventResult(result, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::Undo); + if (!result) + { + const QString documentPath = GetDocumentPath(documentId); + const QString status = QString("Failed to perform Undo on document: %1").arg(documentPath); + m_statusMessage->setText(QString("%1").arg(status)); + } }, QKeySequence::Undo); m_actionRedo = m_menuEdit->addAction("&Redo", [this]() { const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex()); - ShaderManagementConsoleDocumentRequestBus::Event(documentId, &ShaderManagementConsoleDocumentRequestBus::Events::Redo); + bool result = false; + ShaderManagementConsoleDocumentRequestBus::EventResult(result, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::Redo); + if (!result) + { + const QString documentPath = GetDocumentPath(documentId); + const QString status = QString("Failed to perform Redo on document: %1").arg(documentPath); + m_statusMessage->setText(QString("%1").arg(status)); + } }, QKeySequence::Redo); m_menuEdit->addSeparator(); - m_actionSettings = m_menuEdit->addAction("&Preferences...", [this]() { + m_actionSettings = m_menuEdit->addAction("&Settings...", [this]() { }, QKeySequence::Preferences); m_actionSettings->setEnabled(false); m_menuView = m_menuBar->addMenu("&View"); - m_actionAssetBrowser = m_menuView->addAction( - "&Asset Browser", - [this]() - { - const AZStd::string label = "Asset Browser"; - SetDockWidgetVisible(label, !IsDockWidgetVisible(label)); - }); + m_actionAssetBrowser = m_menuView->addAction("&Asset Browser", [this]() { + const AZStd::string label = "Asset Browser"; + SetDockWidgetVisible(label, !IsDockWidgetVisible(label)); + }); + + m_actionPythonTerminal = m_menuView->addAction("Python &Terminal", [this]() { + const AZStd::string label = "Python Terminal"; + SetDockWidgetVisible(label, !IsDockWidgetVisible(label)); + }); - m_actionPythonTerminal = m_menuView->addAction( - "Python &Terminal", - [this]() - { - const AZStd::string label = "Python Terminal"; - SetDockWidgetVisible(label, !IsDockWidgetVisible(label)); - }); m_menuView->addSeparator(); @@ -313,14 +365,23 @@ namespace ShaderManagementConsole // When the last tab is removed tabIndex will be -1 and the document ID will be null // This should automatically clear the active document connect(m_tabWidget, &QTabWidget::currentChanged, this, [this](int tabIndex) { - SelectDocumentForTab(tabIndex); + const AZ::Uuid documentId = GetDocumentIdFromTab(tabIndex); + ShaderManagementConsoleDocumentNotificationBus::Broadcast(&ShaderManagementConsoleDocumentNotificationBus::Events::OnDocumentOpened, documentId); }); connect(m_tabWidget, &QTabWidget::tabCloseRequested, this, [this](int tabIndex) { - CloseDocumentForTab(tabIndex); + const AZ::Uuid documentId = GetDocumentIdFromTab(tabIndex); + ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::CloseDocument, documentId); }); } + QString ShaderManagementConsoleWindow::GetDocumentPath(const AZ::Uuid& documentId) const + { + AZStd::string absolutePath; + ShaderManagementConsoleDocumentRequestBus::EventResult(absolutePath, documentId, &ShaderManagementConsoleDocumentRequestBus::Handler::GetAbsolutePath); + return absolutePath.c_str(); + } + void ShaderManagementConsoleWindow::OpenTabContextMenu() { const QTabBar* tabBar = m_tabWidget->tabBar(); @@ -332,51 +393,22 @@ namespace ShaderManagementConsole QMenu tabMenu; const QString selectActionName = (currentTabIndex == clickedTabIndex) ? "Select in Browser" : "Select"; tabMenu.addAction(selectActionName, [this, clickedTabIndex]() { - SelectDocumentForTab(clickedTabIndex); + const AZ::Uuid documentId = GetDocumentIdFromTab(clickedTabIndex); + ShaderManagementConsoleDocumentNotificationBus::Broadcast(&ShaderManagementConsoleDocumentNotificationBus::Events::OnDocumentOpened, documentId); }); tabMenu.addAction("Close", [this, clickedTabIndex]() { - CloseDocumentForTab(clickedTabIndex); + const AZ::Uuid documentId = GetDocumentIdFromTab(clickedTabIndex); + ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::CloseDocument, documentId); }); auto closeOthersAction = tabMenu.addAction("Close Others", [this, clickedTabIndex]() { - CloseAllExceptDocumentForTab(clickedTabIndex); + const AZ::Uuid documentId = GetDocumentIdFromTab(clickedTabIndex); + ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::CloseAllDocumentsExcept, documentId); }); closeOthersAction->setEnabled(tabBar->count() > 1); tabMenu.exec(QCursor::pos()); } } - void ShaderManagementConsoleWindow::SelectDocumentForTab(const int tabIndex) - { - const AZ::Uuid documentId = GetDocumentIdFromTab(tabIndex); - ShaderManagementConsoleDocumentNotificationBus::Broadcast(&ShaderManagementConsoleDocumentNotificationBus::Events::OnDocumentOpened, documentId); - } - - void ShaderManagementConsoleWindow::CloseDocumentForTab(const int tabIndex) - { - const AZ::Uuid documentId = GetDocumentIdFromTab(tabIndex); - ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::CloseDocument, documentId); - } - - void ShaderManagementConsoleWindow::CloseAllExceptDocumentForTab(const int tabIndex) - { - AZStd::vector documentIdsToClose; - documentIdsToClose.reserve(m_tabWidget->count()); - const AZ::Uuid documentIdToKeepOpen = GetDocumentIdFromTab(tabIndex); - for (int tabI = 0; tabI < m_tabWidget->count(); ++tabI) - { - const AZ::Uuid documentId = GetDocumentIdFromTab(tabI); - if (documentId != documentIdToKeepOpen) - { - documentIdsToClose.push_back(documentId); - } - } - - for (const AZ::Uuid& documentId : documentIdsToClose) - { - ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::CloseDocument, documentId); - } - } - QStandardItemModel* ShaderManagementConsoleWindow::CreateDocumentContent(const AZ::Uuid& documentId) { AZStd::unordered_set optionNames; diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.h b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.h index aae31d1000..7f3f772961 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.h +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.h @@ -52,11 +52,10 @@ namespace ShaderManagementConsole void CreateMenu() override; void CreateTabBar() override; - void OpenTabContextMenu() override; - void SelectDocumentForTab(const int tabIndex); - void CloseDocumentForTab(const int tabIndex); - void CloseAllExceptDocumentForTab(const int tabIndex); + QString GetDocumentPath(const AZ::Uuid& documentId) const; + + void OpenTabContextMenu() override; void closeEvent(QCloseEvent* closeEvent) override; diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindowComponent.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindowComponent.cpp index 44715ef64f..a89cdfddb8 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindowComponent.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindowComponent.cpp @@ -44,14 +44,6 @@ namespace ShaderManagementConsole if (AZ::BehaviorContext* behaviorContext = azrtti_cast(context)) { - behaviorContext->EBus("ShaderManagementConsoleWindowRequestBus") - ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation) - ->Attribute(AZ::Script::Attributes::Category, "Editor") - ->Attribute(AZ::Script::Attributes::Module, "shadermanagementconsole") - ->Event("CreateShaderManagementConsoleWindow", &AtomToolsFramework::AtomToolsMainWindowFactoryRequestBus::Events::CreateMainWindow) - ->Event("DestroyShaderManagementConsoleWindow", &AtomToolsFramework::AtomToolsMainWindowFactoryRequestBus::Events::DestroyMainWindow) - ; - behaviorContext->EBus("ShaderManagementConsoleRequestBus") ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation) ->Attribute(AZ::Script::Attributes::Category, "Editor") @@ -65,19 +57,20 @@ namespace ShaderManagementConsole void ShaderManagementConsoleWindowComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) { - required.push_back(AZ_CRC("AssetBrowserService", 0x1e54fffb)); - required.push_back(AZ_CRC("PropertyManagerService", 0x63a3d7ad)); - required.push_back(AZ_CRC("SourceControlService", 0x67f338fd)); + required.push_back(AZ_CRC_CE("AssetBrowserService")); + required.push_back(AZ_CRC_CE("PropertyManagerService")); + required.push_back(AZ_CRC_CE("SourceControlService")); + required.push_back(AZ_CRC_CE("AtomToolsMainWindowSystemService")); } void ShaderManagementConsoleWindowComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) { - provided.push_back(AZ_CRC("ShaderManagementConsoleWindowService", 0xb6e7d922)); + provided.push_back(AZ_CRC_CE("ShaderManagementConsoleWindowService")); } void ShaderManagementConsoleWindowComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) { - incompatible.push_back(AZ_CRC("ShaderManagementConsoleWindowService", 0xb6e7d922)); + incompatible.push_back(AZ_CRC_CE("ShaderManagementConsoleWindowService")); } void ShaderManagementConsoleWindowComponent::Init() From ce7598c10bbc615ba3a954e6bdbfd7ced16c9e61 Mon Sep 17 00:00:00 2001 From: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> Date: Wed, 11 Aug 2021 12:59:32 -0700 Subject: [PATCH 290/803] [redcode/crythread-2nd-pass] fixed missing includes Signed-off-by: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> --- Code/LauncherUnified/Platform/Linux/Launcher_Linux.cpp | 1 + Code/LauncherUnified/Platform/Mac/Launcher_Mac.mm | 2 ++ Code/Legacy/CryCommon/VectorMap.h | 1 + .../AtomFont/Code/Include/AtomLyIntegration/AtomFont/AtomFont.h | 2 +- 4 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Code/LauncherUnified/Platform/Linux/Launcher_Linux.cpp b/Code/LauncherUnified/Platform/Linux/Launcher_Linux.cpp index 1e87b902a6..3030dcc740 100644 --- a/Code/LauncherUnified/Platform/Linux/Launcher_Linux.cpp +++ b/Code/LauncherUnified/Platform/Linux/Launcher_Linux.cpp @@ -10,6 +10,7 @@ #include #include // for AZ_MAX_PATH_LEN +#include #include diff --git a/Code/LauncherUnified/Platform/Mac/Launcher_Mac.mm b/Code/LauncherUnified/Platform/Mac/Launcher_Mac.mm index cfba0d8aac..f4ea67c6e6 100644 --- a/Code/LauncherUnified/Platform/Mac/Launcher_Mac.mm +++ b/Code/LauncherUnified/Platform/Mac/Launcher_Mac.mm @@ -11,6 +11,8 @@ #include <../Common/Apple/Launcher_Apple.h> #include <../Common/UnixLike/Launcher_UnixLike.h> +#include + #if AZ_TESTS_ENABLED int main(int argc, char* argv[]) diff --git a/Code/Legacy/CryCommon/VectorMap.h b/Code/Legacy/CryCommon/VectorMap.h index 1a42f0e48f..ee99c6f952 100644 --- a/Code/Legacy/CryCommon/VectorMap.h +++ b/Code/Legacy/CryCommon/VectorMap.h @@ -14,6 +14,7 @@ #define CRYINCLUDE_CRYCOMMON_VECTORMAP_H #pragma once +#include // for stl::free_container //-------------------------------------------------------------------------- // VectorMap diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/AtomFont.h b/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/AtomFont.h index 7dd2629bd0..018bc74877 100644 --- a/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/AtomFont.h +++ b/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/AtomFont.h @@ -96,7 +96,7 @@ namespace AZ void UnregisterFont(const char* fontName); private: - using FontMap = std::unordered_map; + using FontMap = AZStd::unordered_map; using FontMapItor = FontMap::iterator; using FontMapConstItor = FontMap::const_iterator; From 3142367fa8910475223b1556ec1144fca75186ae Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Wed, 11 Aug 2021 15:21:54 -0500 Subject: [PATCH 291/803] move main window bus reflection to atom tools update python scripts Signed-off-by: Guthrie Adams --- .../Code/Source/AtomToolsFrameworkModule.cpp | 7 +- .../AtomToolsMainWindowSystemComponent.cpp | 73 +++++++++++++++++++ .../AtomToolsMainWindowSystemComponent.h | 36 +++++++++ .../Code/atomtoolsframework_files.cmake | 2 + .../Window/MaterialEditorWindowComponent.cpp | 35 ++------- .../Scripts/GenerateAllMaterialScreenshots.py | 7 +- ...ShaderManagementConsoleWindowComponent.cpp | 19 ++--- 7 files changed, 132 insertions(+), 47 deletions(-) create mode 100644 Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindowSystemComponent.cpp create mode 100644 Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindowSystemComponent.h diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/AtomToolsFrameworkModule.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/AtomToolsFrameworkModule.cpp index bee27dfdca..b601596032 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/AtomToolsFrameworkModule.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/AtomToolsFrameworkModule.cpp @@ -8,20 +8,23 @@ #include #include +#include namespace AtomToolsFramework { AtomToolsFrameworkModule::AtomToolsFrameworkModule() { m_descriptors.insert(m_descriptors.end(), { - AtomToolsFrameworkSystemComponent::CreateDescriptor(), - }); + AtomToolsFrameworkSystemComponent::CreateDescriptor(), + AtomToolsMainWindowSystemComponent::CreateDescriptor(), + }); } AZ::ComponentTypeList AtomToolsFrameworkModule::GetRequiredSystemComponents() const { return AZ::ComponentTypeList{ azrtti_typeid(), + azrtti_typeid(), }; } } diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindowSystemComponent.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindowSystemComponent.cpp new file mode 100644 index 0000000000..3114a5d9f7 --- /dev/null +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindowSystemComponent.cpp @@ -0,0 +1,73 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include +#include +#include +#include +#include + +namespace AtomToolsFramework +{ + void AtomToolsMainWindowSystemComponent::Reflect(AZ::ReflectContext* context) + { + if (AZ::SerializeContext* serialize = azrtti_cast(context)) + { + serialize->Class() + ->Version(0); + } + + if (AZ::BehaviorContext* behaviorContext = azrtti_cast(context)) + { + behaviorContext->EBus("AtomToolsMainWindowFactoryRequestBus") + ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) + ->Attribute(AZ::Script::Attributes::Category, "Editor") + ->Attribute(AZ::Script::Attributes::Module, "atomtools") + ->Event("CreateMainWindow", &AtomToolsMainWindowFactoryRequestBus::Events::CreateMainWindow) + ->Event("DestroyMainWindow", &AtomToolsMainWindowFactoryRequestBus::Events::DestroyMainWindow) + ; + + behaviorContext->EBus("AtomToolsMainWindowRequestBus") + ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) + ->Attribute(AZ::Script::Attributes::Category, "Editor") + ->Attribute(AZ::Script::Attributes::Module, "atomtools") + ->Event("ActivateWindow", &AtomToolsMainWindowRequestBus::Events::ActivateWindow) + ->Event("SetDockWidgetVisible", &AtomToolsMainWindowRequestBus::Events::SetDockWidgetVisible) + ->Event("IsDockWidgetVisible", &AtomToolsMainWindowRequestBus::Events::IsDockWidgetVisible) + ->Event("GetDockWidgetNames", &AtomToolsMainWindowRequestBus::Events::GetDockWidgetNames) + ->Event("ResizeViewportRenderTarget", &AtomToolsMainWindowRequestBus::Events::ResizeViewportRenderTarget) + ->Event("LockViewportRenderTargetSize", &AtomToolsMainWindowRequestBus::Events::LockViewportRenderTargetSize) + ->Event("UnlockViewportRenderTargetSize", &AtomToolsMainWindowRequestBus::Events::UnlockViewportRenderTargetSize) + ; + } + } + + void AtomToolsMainWindowSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) + { + provided.push_back(AZ_CRC_CE("AtomToolsMainWindowSystemService")); + } + + void AtomToolsMainWindowSystemComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) + { + incompatible.push_back(AZ_CRC_CE("AtomToolsMainWindowSystemService")); + } + + void AtomToolsMainWindowSystemComponent::Init() + { + } + + void AtomToolsMainWindowSystemComponent::Activate() + { + } + + void AtomToolsMainWindowSystemComponent::Deactivate() + { + } + +} // namespace AtomToolsFramework diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindowSystemComponent.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindowSystemComponent.h new file mode 100644 index 0000000000..b982327326 --- /dev/null +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindowSystemComponent.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#pragma once + +#include + +namespace AtomToolsFramework +{ + //! AtomToolsMainWindowSystemComponent is used for initialization and registration of other classes. + class AtomToolsMainWindowSystemComponent + : public AZ::Component + { + public: + AZ_COMPONENT(AtomToolsMainWindowSystemComponent, "{6E42380B-4ECD-47CF-B904-E16AB4E87D0D}"); + + static void Reflect(AZ::ReflectContext* context); + + static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided); + static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible); + + private: + + //////////////////////////////////////////////////////////////////////// + // AZ::Component interface implementation + void Init() override; + void Activate() override; + void Deactivate() override; + //////////////////////////////////////////////////////////////////////// + }; +} diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake b/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake index 49e641eb9c..8eb82778e3 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake @@ -45,4 +45,6 @@ set(FILES Source/Viewport/RenderViewportWidget.cpp Source/Viewport/ModularViewportCameraController.cpp Source/Window/AtomToolsMainWindow.cpp + Source/Window/AtomToolsMainWindowSystemComponent.cpp + Source/Window/AtomToolsMainWindowSystemComponent.h ) \ No newline at end of file diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowComponent.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowComponent.cpp index 8406ae891f..5359ba8e53 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowComponent.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowComponent.cpp @@ -30,47 +30,24 @@ namespace MaterialEditor serialize->Class() ->Version(0); } - - if (AZ::BehaviorContext* behaviorContext = azrtti_cast(context)) - { - behaviorContext->EBus("MaterialEditorWindowAtomRequestBus") - ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) - ->Attribute(AZ::Script::Attributes::Category, "Editor") - ->Attribute(AZ::Script::Attributes::Module, "materialeditor") - ->Event("CreateMaterialEditorWindow", &AtomToolsFramework::AtomToolsMainWindowFactoryRequestBus::Events::CreateMainWindow) - ->Event("DestroyMaterialEditorWindow", &AtomToolsFramework::AtomToolsMainWindowFactoryRequestBus::Events::DestroyMainWindow) - ; - - behaviorContext->EBus("MaterialEditorWindowRequestBus") - ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) - ->Attribute(AZ::Script::Attributes::Category, "Editor") - ->Attribute(AZ::Script::Attributes::Module, "materialeditor") - ->Event("ActivateWindow", &AtomToolsFramework::AtomToolsMainWindowRequestBus::Events::ActivateWindow) - ->Event("SetDockWidgetVisible", &AtomToolsFramework::AtomToolsMainWindowRequestBus::Events::SetDockWidgetVisible) - ->Event("IsDockWidgetVisible", &AtomToolsFramework::AtomToolsMainWindowRequestBus::Events::IsDockWidgetVisible) - ->Event("GetDockWidgetNames", &AtomToolsFramework::AtomToolsMainWindowRequestBus::Events::GetDockWidgetNames) - ->Event("ResizeViewportRenderTarget", &AtomToolsFramework::AtomToolsMainWindowRequestBus::Events::ResizeViewportRenderTarget) - ->Event("LockViewportRenderTargetSize", &AtomToolsFramework::AtomToolsMainWindowRequestBus::Events::LockViewportRenderTargetSize) - ->Event("UnlockViewportRenderTargetSize", &AtomToolsFramework::AtomToolsMainWindowRequestBus::Events::UnlockViewportRenderTargetSize) - ; - } } void MaterialEditorWindowComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) { - required.push_back(AZ_CRC("AssetBrowserService", 0x1e54fffb)); - required.push_back(AZ_CRC("PropertyManagerService", 0x63a3d7ad)); - required.push_back(AZ_CRC("SourceControlService", 0x67f338fd)); + required.push_back(AZ_CRC_CE("AssetBrowserService")); + required.push_back(AZ_CRC_CE("PropertyManagerService")); + required.push_back(AZ_CRC_CE("SourceControlService")); + required.push_back(AZ_CRC_CE("AtomToolsMainWindowSystemService")); } void MaterialEditorWindowComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) { - provided.push_back(AZ_CRC("MaterialEditorWindowService", 0xb6e7d922)); + provided.push_back(AZ_CRC_CE("MaterialEditorWindowService")); } void MaterialEditorWindowComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) { - incompatible.push_back(AZ_CRC("MaterialEditorWindowService", 0xb6e7d922)); + incompatible.push_back(AZ_CRC_CE("MaterialEditorWindowService")); } void MaterialEditorWindowComponent::Init() diff --git a/Gems/Atom/Tools/MaterialEditor/Scripts/GenerateAllMaterialScreenshots.py b/Gems/Atom/Tools/MaterialEditor/Scripts/GenerateAllMaterialScreenshots.py index d7f52d7a24..2116a3de6c 100755 --- a/Gems/Atom/Tools/MaterialEditor/Scripts/GenerateAllMaterialScreenshots.py +++ b/Gems/Atom/Tools/MaterialEditor/Scripts/GenerateAllMaterialScreenshots.py @@ -6,6 +6,7 @@ SPDX-License-Identifier: Apache-2.0 OR MIT """ import azlmbr.bus +import azlmbr.atomtools import azlmbr.materialeditor import azlmbr.name import azlmbr.render @@ -122,12 +123,12 @@ def CaptureScreenshot(screenshotOutputPath): def ResizeViewport(width, height): # This locks the size of the render target to the desired resolution - azlmbr.materialeditor.MaterialEditorWindowRequestBus(azlmbr.bus.Broadcast, 'LockViewportRenderTargetSize', width, height) + azlmbr.atomtools.AtomToolsMainWindowRequestBus(azlmbr.bus.Broadcast, 'LockViewportRenderTargetSize', width, height) # This resizes the window to closely match the render target resolution so it doesn't appear stretched while the script is running - azlmbr.materialeditor.MaterialEditorWindowRequestBus(azlmbr.bus.Broadcast, 'ResizeViewportRenderTarget', width, height) + azlmbr.atomtools.AtomToolsMainWindowRequestBus(azlmbr.bus.Broadcast, 'ResizeViewportRenderTarget', width, height) def ReleaseViewportResolutionLock(): - azlmbr.materialeditor.MaterialEditorWindowRequestBus(azlmbr.bus.Broadcast, 'UnlockViewportRenderTargetSize') + azlmbr.atomtools.AtomToolsMainWindowRequestBus(azlmbr.bus.Broadcast, 'UnlockViewportRenderTargetSize') def GenerateMaterialScreenshot(materialName, uniqueSuffix="", diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindowComponent.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindowComponent.cpp index 44715ef64f..a89cdfddb8 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindowComponent.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindowComponent.cpp @@ -44,14 +44,6 @@ namespace ShaderManagementConsole if (AZ::BehaviorContext* behaviorContext = azrtti_cast(context)) { - behaviorContext->EBus("ShaderManagementConsoleWindowRequestBus") - ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation) - ->Attribute(AZ::Script::Attributes::Category, "Editor") - ->Attribute(AZ::Script::Attributes::Module, "shadermanagementconsole") - ->Event("CreateShaderManagementConsoleWindow", &AtomToolsFramework::AtomToolsMainWindowFactoryRequestBus::Events::CreateMainWindow) - ->Event("DestroyShaderManagementConsoleWindow", &AtomToolsFramework::AtomToolsMainWindowFactoryRequestBus::Events::DestroyMainWindow) - ; - behaviorContext->EBus("ShaderManagementConsoleRequestBus") ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation) ->Attribute(AZ::Script::Attributes::Category, "Editor") @@ -65,19 +57,20 @@ namespace ShaderManagementConsole void ShaderManagementConsoleWindowComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) { - required.push_back(AZ_CRC("AssetBrowserService", 0x1e54fffb)); - required.push_back(AZ_CRC("PropertyManagerService", 0x63a3d7ad)); - required.push_back(AZ_CRC("SourceControlService", 0x67f338fd)); + required.push_back(AZ_CRC_CE("AssetBrowserService")); + required.push_back(AZ_CRC_CE("PropertyManagerService")); + required.push_back(AZ_CRC_CE("SourceControlService")); + required.push_back(AZ_CRC_CE("AtomToolsMainWindowSystemService")); } void ShaderManagementConsoleWindowComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) { - provided.push_back(AZ_CRC("ShaderManagementConsoleWindowService", 0xb6e7d922)); + provided.push_back(AZ_CRC_CE("ShaderManagementConsoleWindowService")); } void ShaderManagementConsoleWindowComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) { - incompatible.push_back(AZ_CRC("ShaderManagementConsoleWindowService", 0xb6e7d922)); + incompatible.push_back(AZ_CRC_CE("ShaderManagementConsoleWindowService")); } void ShaderManagementConsoleWindowComponent::Init() From 633cf818f7498f7a764629693cfd01663290eb07 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Wed, 11 Aug 2021 15:54:13 -0500 Subject: [PATCH 292/803] updating test scripts Signed-off-by: Guthrie Adams --- .../atom_renderer/atom_utils/material_editor_utils.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/material_editor_utils.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/material_editor_utils.py index 77d1285188..1d72885504 100644 --- a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/material_editor_utils.py +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/material_editor_utils.py @@ -13,9 +13,9 @@ import os import sys import time import azlmbr.atom +import azlmbr.atomtools as atomtools import azlmbr.materialeditor as materialeditor import azlmbr.bus as bus -import azlmbr.atomtools.general as general def is_close(actual, expected, buffer=sys.float_info.min): @@ -125,11 +125,11 @@ def is_pane_visible(pane_name): """ :return: bool """ - return materialeditor.MaterialEditorWindowRequestBus(bus.Broadcast, "IsDockWidgetVisible", pane_name) + return atomtools.AtomToolsWindowRequestBus(bus.Broadcast, "IsDockWidgetVisible", pane_name) def set_pane_visibility(pane_name, value): - materialeditor.MaterialEditorWindowRequestBus(bus.Broadcast, "SetDockWidgetVisible", pane_name, value) + atomtools.AtomToolsWindowRequestBus(bus.Broadcast, "SetDockWidgetVisible", pane_name, value) def select_lighting_config(config_name): @@ -175,7 +175,7 @@ def wait_for_condition(function, timeout_in_seconds=1.0): with Timeout(timeout_in_seconds) as t: while True: try: - general.idle_wait_frames(1) + atomtools.general.idle_wait_frames(1) except Exception: print("WARNING: Couldn't wait for frame") @@ -269,6 +269,6 @@ class ScreenshotHelper: def capture_screenshot(file_path): - return ScreenshotHelper(azlmbr.atomtools.general.idle_wait_frames).capture_screenshot_blocking( + return ScreenshotHelper(atomtools.general.idle_wait_frames).capture_screenshot_blocking( os.path.join(file_path) ) From 041aa42307fcf42bfdb41871530acac7464efe82 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Wed, 11 Aug 2021 13:56:03 -0700 Subject: [PATCH 293/803] fixes after merge Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Editor/Include/IFileUtil.h | 1 + Code/Legacy/CryCommon/CrySizer.h | 1 + Code/Legacy/CryCommon/WinBase.cpp | 3 ++- Gems/LyShine/Code/Source/Animation/UiAnimationSystem.cpp | 4 ++-- Gems/Maestro/Code/Source/Cinematics/Movie.cpp | 8 ++++---- 5 files changed, 10 insertions(+), 7 deletions(-) diff --git a/Code/Editor/Include/IFileUtil.h b/Code/Editor/Include/IFileUtil.h index 746a81b87c..700e04f6d3 100644 --- a/Code/Editor/Include/IFileUtil.h +++ b/Code/Editor/Include/IFileUtil.h @@ -9,6 +9,7 @@ #pragma once #include "../Include/SandboxAPI.h" +#include class QWidget; diff --git a/Code/Legacy/CryCommon/CrySizer.h b/Code/Legacy/CryCommon/CrySizer.h index b541b698f9..3f9eed84f6 100644 --- a/Code/Legacy/CryCommon/CrySizer.h +++ b/Code/Legacy/CryCommon/CrySizer.h @@ -30,6 +30,7 @@ #include #include #include +#include // forward declarations for overloads struct AABB; diff --git a/Code/Legacy/CryCommon/WinBase.cpp b/Code/Legacy/CryCommon/WinBase.cpp index 4e48d29ed7..a2b4056a56 100644 --- a/Code/Legacy/CryCommon/WinBase.cpp +++ b/Code/Legacy/CryCommon/WinBase.cpp @@ -12,6 +12,7 @@ #include "platform.h" // Note: This should be first to get consistent debugging definitions +#include #include #if defined(AZ_RESTRICTED_PLATFORM) @@ -29,7 +30,7 @@ #include AZ_RESTRICTED_FILE(WinBase_cpp) #endif #if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED) -#undef AZ_RESTRICTED_SECTION_IMPLEMENTED + #undef AZ_RESTRICTED_SECTION_IMPLEMENTED #else #include #endif diff --git a/Gems/LyShine/Code/Source/Animation/UiAnimationSystem.cpp b/Gems/LyShine/Code/Source/Animation/UiAnimationSystem.cpp index 5d6cbe90eb..35fde93e83 100644 --- a/Gems/LyShine/Code/Source/Animation/UiAnimationSystem.cpp +++ b/Gems/LyShine/Code/Source/Animation/UiAnimationSystem.cpp @@ -27,11 +27,11 @@ // Serialization for anim nodes & param types #define REGISTER_NODE_TYPE(name) assert(g_animNodeEnumToStringMap.find(eUiAnimNodeType_ ## name) == g_animNodeEnumToStringMap.end()); \ g_animNodeEnumToStringMap[eUiAnimNodeType_ ## name] = AZ_STRINGIZE(name); \ - g_animNodeStringToEnumMap[string(STRINGIFY(name))] = eUiAnimNodeType_ ## name; + g_animNodeStringToEnumMap[AZStd::string(AZ_STRINGIZE(name))] = eUiAnimNodeType_ ## name; #define REGISTER_PARAM_TYPE(name) assert(g_animParamEnumToStringMap.find(eUiAnimParamType_ ## name) == g_animParamEnumToStringMap.end()); \ g_animParamEnumToStringMap[eUiAnimParamType_ ## name] = AZ_STRINGIZE(name); \ - g_animParamStringToEnumMap[string(STRINGIFY(name))] = eUiAnimParamType_ ## name; + g_animParamStringToEnumMap[AZStd::string(AZ_STRINGIZE(name))] = eUiAnimParamType_ ## name; namespace { diff --git a/Gems/Maestro/Code/Source/Cinematics/Movie.cpp b/Gems/Maestro/Code/Source/Cinematics/Movie.cpp index 8bbaf6e0c8..cf51ef3729 100644 --- a/Gems/Maestro/Code/Source/Cinematics/Movie.cpp +++ b/Gems/Maestro/Code/Source/Cinematics/Movie.cpp @@ -74,12 +74,12 @@ static SMovieSequenceAutoComplete s_movieSequenceAutoComplete; ////////////////////////////////////////////////////////////////////////// // Serialization for anim nodes & param types #define REGISTER_NODE_TYPE(name) assert(g_animNodeEnumToStringMap.find(AnimNodeType::name) == g_animNodeEnumToStringMap.end()); \ - g_animNodeEnumToStringMap[AnimNodeType::name] = AZ_STRINGIZE(name); \ - g_animNodeStringToEnumMap[string(STRINGIFY(name))] = AnimNodeType::name; + g_animNodeEnumToStringMap[AnimNodeType::name] = AZ_STRINGIZE(name); \ + g_animNodeStringToEnumMap[AZStd::string(AZ_STRINGIZE(name))] = AnimNodeType::name; #define REGISTER_PARAM_TYPE(name) assert(g_animParamEnumToStringMap.find(AnimParamType::name) == g_animParamEnumToStringMap.end()); \ - g_animParamEnumToStringMap[AnimParamType::name] = AZ_STRINGIZE(name); \ - g_animParamStringToEnumMap[string(STRINGIFY(name))] = AnimParamType::name; + g_animParamEnumToStringMap[AnimParamType::name] = AZ_STRINGIZE(name); \ + g_animParamStringToEnumMap[AZStd::string(AZ_STRINGIZE(name))] = AnimParamType::name; namespace { From c6714595b1edb22748a68f25c9d9e59a479390fa Mon Sep 17 00:00:00 2001 From: Junbo Liang <68558268+junbo75@users.noreply.github.com> Date: Wed, 11 Aug 2021 13:59:29 -0700 Subject: [PATCH 294/803] Define a new Jenkins build script to deploy AWS resources (#2983) * Define a new Jenkins job to deploy AWS resources Signed-off-by: junbo * Address PR comments Signed-off-by: junbo * Add error checking for all the calls Signed-off-by: junbo * Remove the weekly-build-metrics tag Signed-off-by: junbo * Parameterize ARN/Region and move it to a Jenkins envvar. Signed-off-by: junbo * Revert the changes for build_config.json Signed-off-by: junbo --- .../Windows/deploy_cdk_applications.cmd | 105 ++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 scripts/build/Platform/Windows/deploy_cdk_applications.cmd diff --git a/scripts/build/Platform/Windows/deploy_cdk_applications.cmd b/scripts/build/Platform/Windows/deploy_cdk_applications.cmd new file mode 100644 index 0000000000..2845707923 --- /dev/null +++ b/scripts/build/Platform/Windows/deploy_cdk_applications.cmd @@ -0,0 +1,105 @@ +@ECHO OFF +REM +REM Copyright (c) Contributors to the Open 3D Engine Project. +REM For complete copyright and license terms please see the LICENSE at the root of this distribution. +REM +REM SPDX-License-Identifier: Apache-2.0 OR MIT +REM +REM + +REM Deploy the CDK applcations for AWS gems (Windows only) +REM Prerequisites: +REM 1) Node.js is installed +REM 2) Node.js version >= 10.13.0, except for versions 13.0.0 - 13.6.0. A version in active long-term support is recommended. +SETLOCAL EnableDelayedExpansion + +SET SOURCE_DIRECTORY=%CD% +SET PATH=%SOURCE_DIRECTORY%\python;%PATH% +SET GEM_DIRECTORY=%SOURCE_DIRECTORY%\Gems + +REM Create and activate a virtualenv for the CDK deployment +CALL python -m venv .env +IF ERRORLEVEL 1 ( + ECHO [cdk_bootstrap] Failed to create a virtualenv for the CDK deployment + exit /b 1 +) +CALL .env\Scripts\activate.bat +IF ERRORLEVEL 1 ( + ECHO [cdk_bootstrap] Failed to activate the virtualenv for the CDK deployment + exit /b 1 +) + +ECHO [cdk_installation] Install the latest version of CDK +CALL npm uninstall -g aws-cdk +IF ERRORLEVEL 1 ( + ECHO [cdk_bootstrap] Failed to uninstall the current version of CDK + exit /b 1 +) +CALL npm install -g aws-cdk@latest +IF ERRORLEVEL 1 ( + ECHO [cdk_bootstrap] Failed to install the latest version of CDK + exit /b 1 +) + +REM Set temporary AWS credentials from the assume role +FOR /f "tokens=1,2,3" %%a IN ('CALL aws sts assume-role --query Credentials.[SecretAccessKey^,SessionToken^,AccessKeyId] --output text --role-arn %ASSUME_ROLE_ARN% --role-session-name o3de-Automation-session') DO ( + SET AWS_SECRET_ACCESS_KEY=%%a + SET AWS_SESSION_TOKEN=%%b + SET AWS_ACCESS_KEY_ID=%%c +) +FOR /F "tokens=4 delims=:" %%a IN ("%ASSUME_ROLE_ARN%") DO SET O3DE_AWS_DEPLOY_ACCOUNT=%%a + +REM Bootstrap and deploy the CDK applications +ECHO [cdk_bootstrap] Bootstrap CDK +CALL cdk bootstrap aws://%O3DE_AWS_DEPLOY_ACCOUNT%/%O3DE_AWS_DEPLOY_REGION% +IF ERRORLEVEL 1 ( + ECHO [cdk_bootstrap] Failed to bootstrap CDK + exit /b 1 +) + +CALL :DeployCDKApplication AWSCore --all +IF ERRORLEVEL 1 ( + exit /b 1 +) +CALL :DeployCDKApplication AWSClientAuth +IF ERRORLEVEL 1 ( + exit /b 1 +) +CALL :DeployCDKApplication AWSMetrics "-c batch_processing=true" +IF ERRORLEVEL 1 ( + exit /b 1 +) + +EXIT /b 0 + +:DeployCDKApplication +REM Deploy the CDK application for a specific AWS gem +SET GEM_NAME=%~1 +SET ADDITIONAL_ARGUMENTS=%~2 +ECHO [cdk_deployment] Deploy the CDK application for the %GEM_NAME% gem +PUSHD %GEM_DIRECTORY%\%GEM_NAME%\cdk + +REM Revert the CDK application code to a stable state using the provided commit ID +CALL git checkout %COMMIT_ID% -- . +IF ERRORLEVEL 1 ( + ECHO [git_checkout] Failed to checkout the CDK application for the %GEM_NAME% gem using commit ID %COMMIT_ID% + POPD + exit /b 1 +) + +REM Install required packages for the CDK application +CALL python -m pip install -r requirements.txt +IF ERRORLEVEL 1 ( + ECHO [cdk_deployment] Failed to install required packages for the %GEM_NAME% gem + POPD + exit /b 1 +) + +REM Deploy the CDK application +CALL cdk deploy %ADDITIONAL_ARGUMENTS% --require-approval never +IF ERRORLEVEL 1 ( + ECHO [cdk_deployment] Failed to deploy the CDK application for the %GEM_NAME% gem + POPD + exit /b 1 +) +POPD From 8b8e249e05852e4d2d6da1435df7275f92f894f6 Mon Sep 17 00:00:00 2001 From: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> Date: Wed, 11 Aug 2021 13:59:41 -0700 Subject: [PATCH 295/803] Add new functions to mock unit test class. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> --- .../AzCore/AzCore/UnitTest/Mocks/MockSettingsRegistry.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Code/Framework/AzCore/AzCore/UnitTest/Mocks/MockSettingsRegistry.h b/Code/Framework/AzCore/AzCore/UnitTest/Mocks/MockSettingsRegistry.h index 7c132b29a3..a63e782146 100644 --- a/Code/Framework/AzCore/AzCore/UnitTest/Mocks/MockSettingsRegistry.h +++ b/Code/Framework/AzCore/AzCore/UnitTest/Mocks/MockSettingsRegistry.h @@ -25,6 +25,10 @@ namespace AZ MOCK_CONST_METHOD2(Visit, bool(const VisitorCallback&, AZStd::string_view)); MOCK_METHOD1(RegisterNotifier, NotifyEventHandler(const NotifyCallback&)); MOCK_METHOD1(RegisterNotifier, NotifyEventHandler(NotifyCallback&&)); + MOCK_METHOD1(RegisterPreMergeEvent, PreMergeEventHandler(const PreMergeEventCallback&)); + MOCK_METHOD1(RegisterPreMergeEvent, PreMergeEventHandler(PreMergeEventCallback&&)); + MOCK_METHOD1(PostMergeEventHandler, PreMergeEventHandler(const PostMergeEventCallback&)); + MOCK_METHOD1(PostMergeEventHandler, PreMergeEventHandler(PostMergeEventCallback&&)); MOCK_CONST_METHOD2(Get, bool(bool&, AZStd::string_view)); MOCK_CONST_METHOD2(Get, bool(s64&, AZStd::string_view)); From 7e5cbdab1e26fa829fdc70c0978914a22ac128ca Mon Sep 17 00:00:00 2001 From: chiyenteng <82238204+chiyenteng@users.noreply.github.com> Date: Wed, 11 Aug 2021 14:11:26 -0700 Subject: [PATCH 296/803] Create a new automated test for Prefab basic workflows (#2715) Adds a new ebus for prefab apis and refactored the apis Removed an empty test level Auto delete tmp level when teardown tests Add Base test level in Prefab folder Removed unused comments Checked if absolute path as an input of Create Prefab functions Changed created prefab file path to support all platfroms Added missing includes Signed-off-by: chiyteng --- .../prefab/PrefabLevel_BasicWorkflow.py | 66 ++++++++++++++++ .../Gem/PythonTests/prefab/TestSuite_Main.py | 6 ++ .../Levels/Prefab/Base/Base.prefab | 53 +++++++++++++ .../API/ToolsApplicationAPI.h | 4 +- .../Application/ToolsApplication.cpp | 1 - .../Prefab/PrefabPublicHandler.cpp | 48 +++++++---- .../Prefab/PrefabPublicHandler.h | 7 +- .../Prefab/PrefabPublicInterface.h | 21 ++++- .../Prefab/PrefabPublicRequestBus.h | 56 +++++++++++++ .../Prefab/PrefabPublicRequestHandler.cpp | 79 +++++++++++++++++++ .../Prefab/PrefabPublicRequestHandler.h | 41 ++++++++++ .../Prefab/PrefabSystemComponent.cpp | 4 +- .../Prefab/PrefabSystemComponent.h | 4 + .../UI/Prefab/PrefabIntegrationManager.cpp | 8 +- .../aztoolsframework_files.cmake | 3 + 15 files changed, 372 insertions(+), 29 deletions(-) create mode 100644 AutomatedTesting/Gem/PythonTests/prefab/PrefabLevel_BasicWorkflow.py create mode 100644 AutomatedTesting/Levels/Prefab/Base/Base.prefab create mode 100644 Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicRequestBus.h create mode 100644 Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicRequestHandler.cpp create mode 100644 Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicRequestHandler.h diff --git a/AutomatedTesting/Gem/PythonTests/prefab/PrefabLevel_BasicWorkflow.py b/AutomatedTesting/Gem/PythonTests/prefab/PrefabLevel_BasicWorkflow.py new file mode 100644 index 0000000000..44b7dc2ee4 --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/prefab/PrefabLevel_BasicWorkflow.py @@ -0,0 +1,66 @@ +""" +Copyright (c) Contributors to the Open 3D Engine Project. +For complete copyright and license terms please see the LICENSE at the root of this distribution. + +SPDX-License-Identifier: Apache-2.0 OR MIT +""" + +# fmt:off +class Tests(): + create_new_entity = ("Entity: 'CreateNewEntity' passed", "Entity: 'CreateNewEntity' failed") + create_prefab = ("Prefab: 'CreatePrefab' passed", "Prefab: 'CreatePrefab' failed") + instantiate_prefab = ("Prefab: 'InstantiatePrefab' passed", "Prefab: 'InstantiatePrefab' failed") + new_prefab_position = ("Prefab: new prefab's position is at the expected position", "Prefab: new prefab's position is *not* at the expected position") +# fmt:on + +def PrefabLevel_BasicWorkflow(): + """ + This test will help verify if the following functions related to Prefab work as expected: + - CreatePrefab + - InstantiatePrefab + """ + + import os + import sys + + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper + import editor_python_test_tools.hydra_editor_utils as hydra + + import azlmbr.bus as bus + import azlmbr.entity as entity + from azlmbr.entity import EntityId + import azlmbr.editor as editor + import azlmbr.prefab as prefab + from azlmbr.math import Vector3 + import azlmbr.legacy.general as general + + EXPECTED_NEW_PREFAB_POSITION = Vector3(10.00, 20.0, 30.0) + + helper.init_idle() + helper.open_level("Prefab", "Base") + +# Create a new Entity at the root level + new_entity_id = editor.ToolsApplicationRequestBus(bus.Broadcast, 'CreateNewEntity', EntityId()) + Report.result(Tests.create_new_entity, new_entity_id.IsValid()) + +# Checks for prefab creation passed or not + new_prefab_file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'new_prefab.prefab') + create_prefab_result = prefab.PrefabPublicRequestBus(bus.Broadcast, 'CreatePrefabInMemory', [new_entity_id], new_prefab_file_path) + Report.result(Tests.create_prefab, create_prefab_result) + +# Checks for prefab instantiation passed or not + container_entity_id = prefab.PrefabPublicRequestBus(bus.Broadcast, 'InstantiatePrefab', new_prefab_file_path, EntityId(), EXPECTED_NEW_PREFAB_POSITION) + Report.result(Tests.instantiate_prefab, container_entity_id.IsValid()) + +# Checks if the new prefab is at the correct position and if it fails, it will provide the expected postion and the actual postion of the entity in the Editor log + new_prefab_position = azlmbr.components.TransformBus(azlmbr.bus.Event, "GetWorldTranslation", container_entity_id) + is_at_position = new_prefab_position.IsClose(EXPECTED_NEW_PREFAB_POSITION) + Report.result(Tests.new_prefab_position, is_at_position) + if not is_at_position: + Report.info(f'Expected position: {EXPECTED_NEW_PREFAB_POSITION.ToString()}, actual position: {new_prefab_position.ToString()}') + + +if __name__ == "__main__": + from editor_python_test_tools.utils import Report + Report.start_test(PrefabLevel_BasicWorkflow) diff --git a/AutomatedTesting/Gem/PythonTests/prefab/TestSuite_Main.py b/AutomatedTesting/Gem/PythonTests/prefab/TestSuite_Main.py index acd8f60b07..4e3d6ba77f 100644 --- a/AutomatedTesting/Gem/PythonTests/prefab/TestSuite_Main.py +++ b/AutomatedTesting/Gem/PythonTests/prefab/TestSuite_Main.py @@ -16,6 +16,7 @@ from ly_test_tools import LAUNCHERS sys.path.append (os.path.dirname (os.path.abspath (__file__)) + '/../automatedtesting_shared') +import ly_test_tools.environment.file_system as file_system from base import TestAutomationBase @pytest.mark.SUITE_main @@ -29,3 +30,8 @@ class TestAutomation(TestAutomationBase): def test_PrefabLevel_OpensLevelWithEntities(self, request, workspace, editor, launcher_platform): from . import PrefabLevel_OpensLevelWithEntities as test_module self._run_prefab_test(request, workspace, editor, test_module) + + def test_PrefabLevel_BasicWorkflow(self, request, workspace, editor, launcher_platform): + from . import PrefabLevel_BasicWorkflow as test_module + self._run_prefab_test(request, workspace, editor, test_module) + diff --git a/AutomatedTesting/Levels/Prefab/Base/Base.prefab b/AutomatedTesting/Levels/Prefab/Base/Base.prefab new file mode 100644 index 0000000000..f7e42e7731 --- /dev/null +++ b/AutomatedTesting/Levels/Prefab/Base/Base.prefab @@ -0,0 +1,53 @@ +{ + "ContainerEntity": { + "Id": "Entity_[1146574390643]", + "Name": "Level", + "Components": { + "Component_[10641544592923449938]": { + "$type": "EditorInspectorComponent", + "Id": 10641544592923449938 + }, + "Component_[12039882709170782873]": { + "$type": "EditorOnlyEntityComponent", + "Id": 12039882709170782873 + }, + "Component_[12265484671603697631]": { + "$type": "EditorPendingCompositionComponent", + "Id": 12265484671603697631 + }, + "Component_[14126657869720434043]": { + "$type": "EditorEntitySortComponent", + "Id": 14126657869720434043 + }, + "Component_[15230859088967841193]": { + "$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent", + "Id": 15230859088967841193, + "Parent Entity": "" + }, + "Component_[16239496886950819870]": { + "$type": "EditorDisabledCompositionComponent", + "Id": 16239496886950819870 + }, + "Component_[5688118765544765547]": { + "$type": "EditorEntityIconComponent", + "Id": 5688118765544765547 + }, + "Component_[6545738857812235305]": { + "$type": "SelectionComponent", + "Id": 6545738857812235305 + }, + "Component_[7247035804068349658]": { + "$type": "EditorPrefabComponent", + "Id": 7247035804068349658 + }, + "Component_[9307224322037797205]": { + "$type": "EditorLockComponent", + "Id": 9307224322037797205 + }, + "Component_[9562516168917670048]": { + "$type": "EditorVisibilityComponent", + "Id": 9562516168917670048 + } + } + } +} \ No newline at end of file diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/API/ToolsApplicationAPI.h b/Code/Framework/AzToolsFramework/AzToolsFramework/API/ToolsApplicationAPI.h index 0ba10d7388..f6046b9f25 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/API/ToolsApplicationAPI.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/API/ToolsApplicationAPI.h @@ -600,8 +600,8 @@ namespace AzToolsFramework * Open 3D Engine Internal use only. * * Run a specific redo command separate from the undo/redo system. - * In many cases before a modifcation on an entity takes place, it is first packaged into - * undo/redo commands. Running the modification's redo command separete from the undo/redo + * In many cases before a modification on an entity takes place, it is first packaged into + * undo/redo commands. Running the modification's redo command separate from the undo/redo * system simulates its execution, and avoids some code duplication. */ virtual void RunRedoSeparately(UndoSystem::URSequencePoint* redoCommand) = 0; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.cpp index 970f5aa28c..56ef749247 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.cpp @@ -1781,5 +1781,4 @@ namespace AzToolsFramework { appType.m_maskValue = AZ::ApplicationTypeQuery::Masks::Tool; }; - } // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp index bb394720c9..7af953efca 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp @@ -61,7 +61,7 @@ namespace AzToolsFramework m_prefabUndoCache.Destroy(); } - PrefabOperationResult PrefabPublicHandler::CreatePrefab(const AZStd::vector& entityIds, AZ::IO::PathView absolutePath) + PrefabOperationResult PrefabPublicHandler::CreatePrefabInMemory(const AZStd::vector& entityIds, AZ::IO::PathView filePath) { EntityList inputEntityList, topLevelEntities; AZ::EntityId commonRootEntityId; @@ -73,8 +73,6 @@ namespace AzToolsFramework return findCommonRootOutcome; } - AZ_Assert(absolutePath.IsAbsolute(), "CreatePrefab requires an absolute path for saving the initial prefab file."); - InstanceOptionalReference instanceToCreate; { // Initialize Undo Batch object @@ -125,7 +123,7 @@ namespace AzToolsFramework PrefabDom linkPatchesCopy; linkPatchesCopy.CopyFrom(linkPatches->get(), linkPatchesCopy.GetAllocator()); nestedInstanceLinkPatchesMap.emplace(nestedInstance, AZStd::move(linkPatchesCopy)); - + RemoveLink(outInstance, commonRootEntityOwningInstance->get().GetTemplateId(), undoBatch.GetUndoBatch()); instancePtrs.emplace_back(AZStd::move(outInstance)); @@ -139,18 +137,20 @@ namespace AzToolsFramework if (!prefabEditorEntityOwnershipInterface) { return AZ::Failure(AZStd::string("Could not create a new prefab out of the entities provided - internal error " - "(PrefabEditorEntityOwnershipInterface unavailable).")); + "(PrefabEditorEntityOwnershipInterface unavailable).")); } // Create the Prefab + AZ_Assert(filePath.IsAbsolute(), "CreatePrefabInMemory requires an absolute file path."); + instanceToCreate = prefabEditorEntityOwnershipInterface->CreatePrefab( - entities, AZStd::move(instancePtrs), m_prefabLoaderInterface->GenerateRelativePath(absolutePath), + entities, AZStd::move(instancePtrs), m_prefabLoaderInterface->GenerateRelativePath(filePath), commonRootEntityOwningInstance); if (!instanceToCreate) { return AZ::Failure(AZStd::string("Could not create a new prefab out of the entities provided - internal error " - "(A null instance is returned).")); + "(A null instance is returned).")); } AZ::EntityId containerEntityId = instanceToCreate->get().GetContainerEntityId(); @@ -218,7 +218,7 @@ namespace AzToolsFramework linkUpdate.Redo(); } }); - + // Create a link between the templates of the newly created instance and the instance it's being parented under. CreateLink( instanceToCreate->get(), commonRootEntityOwningInstance->get().GetTemplateId(), undoBatch.GetUndoBatch(), @@ -255,18 +255,35 @@ namespace AzToolsFramework // Select Container Entity { - auto selectionUndo = aznew SelectionCommand({containerEntityId}, "Select Prefab Container Entity"); + auto selectionUndo = aznew SelectionCommand({ containerEntityId }, "Select Prefab Container Entity"); selectionUndo->SetParent(undoBatch.GetUndoBatch()); ToolsApplicationRequestBus::Broadcast(&ToolsApplicationRequestBus::Events::RunRedoSeparately, selectionUndo); } } - // Save Template to file - m_prefabLoaderInterface->SaveTemplateToFile(instanceToCreate->get().GetTemplateId(), absolutePath); - return AZ::Success(); } + PrefabOperationResult PrefabPublicHandler::CreatePrefabInDisk(const AZStd::vector& entityIds, AZ::IO::PathView filePath) + { + auto result = CreatePrefabInMemory(entityIds, filePath); + if (result.IsSuccess()) + { + // Save Template to file + auto relativePath = m_prefabLoaderInterface->GenerateRelativePath(filePath); + Prefab::TemplateId templateId = m_prefabSystemComponentInterface->GetTemplateIdFromFilePath(relativePath); + if (!m_prefabLoaderInterface->SaveTemplateToFile(templateId, filePath)) + { + AZStd::string_view filePathString(filePath); + return AZ::Failure(AZStd::string::format( + "Could not save the newly created prefab to file path %.*s - internal error ", + AZ_STRING_ARG(filePathString))); + } + } + + return result; + } + PrefabDom PrefabPublicHandler::ApplyContainerTransformAndGeneratePatch(AZ::EntityId containerEntityId, AZ::EntityId parentEntityId, const EntityList& childEntities) { AZ::Entity* containerEntity = GetEntityById(containerEntityId); @@ -301,7 +318,7 @@ namespace AzToolsFramework return AZStd::move(patch); } - PrefabOperationResult PrefabPublicHandler::InstantiatePrefab( + InstantiatePrefabResult PrefabPublicHandler::InstantiatePrefab( AZStd::string_view filePath, AZ::EntityId parent, const AZ::Vector3& position) { auto prefabEditorEntityOwnershipInterface = AZ::Interface::Get(); @@ -347,6 +364,7 @@ namespace AzToolsFramework relativePath.Native().c_str(), instanceToParentUnder->get().GetTemplateSourcePath().Native().c_str())); } + AZ::EntityId containerEntityId; { // Initialize Undo Batch object ScopedUndoBatch undoBatch("Instantiate Prefab"); @@ -367,7 +385,7 @@ namespace AzToolsFramework instanceToParentUnder->get(), "Update prefab instance", instanceToParentUnderDomBeforeCreate, undoBatch.GetUndoBatch()); // Create Link with correct container patches - AZ::EntityId containerEntityId = instanceToCreate->get().GetContainerEntityId(); + containerEntityId = instanceToCreate->get().GetContainerEntityId(); AZ::Entity* containerEntity = GetEntityById(containerEntityId); AZ_Assert(containerEntity, "Invalid container entity detected in InstantiatePrefab."); @@ -394,7 +412,7 @@ namespace AzToolsFramework &AzToolsFramework::ToolsApplicationRequestBus::Events::ClearDirtyEntities); } - return AZ::Success(); + return AZ::Success(containerEntityId); } PrefabOperationResult PrefabPublicHandler::FindCommonRootOwningInstance( diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.h index 0e24b0841d..8f124e8edd 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.h @@ -42,8 +42,11 @@ namespace AzToolsFramework void UnregisterPrefabPublicHandlerInterface(); // PrefabPublicInterface... - PrefabOperationResult CreatePrefab(const AZStd::vector& entityIds, AZ::IO::PathView absolutePath) override; - PrefabOperationResult InstantiatePrefab(AZStd::string_view filePath, AZ::EntityId parent, const AZ::Vector3& position) override; + PrefabOperationResult CreatePrefabInDisk( + const AZStd::vector& entityIds, AZ::IO::PathView filePath) override; + PrefabOperationResult CreatePrefabInMemory( + const AZStd::vector& entityIds, AZ::IO::PathView filePath) override; + InstantiatePrefabResult InstantiatePrefab(AZStd::string_view filePath, AZ::EntityId parent, const AZ::Vector3& position) override; PrefabOperationResult SavePrefab(AZ::IO::Path filePath) override; PrefabEntityResult CreateEntity(AZ::EntityId parentId, const AZ::Vector3& position) override; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicInterface.h index 6b3fdcd391..67d65dfca6 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicInterface.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicInterface.h @@ -25,6 +25,7 @@ namespace AzToolsFramework namespace Prefab { typedef AZ::Outcome PrefabOperationResult; + typedef AZ::Outcome InstantiatePrefabResult; typedef AZ::Outcome PrefabRequestResult; typedef AZ::Outcome PrefabEntityResult; @@ -39,22 +40,34 @@ namespace AzToolsFramework AZ_RTTI(PrefabPublicInterface, "{931AAE9D-C775-4818-9070-A2DA69489CBE}"); /** - * Create a prefab out of the entities provided, at the path provided. + * Create a prefab out of the entities provided, at the path provided, and save it in disk immediately. * Automatically detects descendants of entities, and discerns between entities and child instances. * @param entityIds The entities that should form the new prefab (along with their descendants). * @param filePath The absolute path for the new prefab file. * @return An outcome object; on failure, it comes with an error message detailing the cause of the error. */ - virtual PrefabOperationResult CreatePrefab(const AZStd::vector& entityIds, AZ::IO::PathView absolutePath) = 0; + virtual PrefabOperationResult CreatePrefabInDisk( + const AZStd::vector& entityIds, AZ::IO::PathView filePath) = 0; + + /** + * Create a prefab out of the entities provided, at the path provided, and keep it in memory. + * Automatically detects descendants of entities, and discerns between entities and child instances. + * @param entityIds The entities that should form the new prefab (along with their descendants). + * @param filePath The absolute path for the new prefab file. + * @return An outcome object; on failure, it comes with an error message detailing the cause of the error. + */ + virtual PrefabOperationResult CreatePrefabInMemory( + const AZStd::vector& entityIds, AZ::IO::PathView filePath) = 0; /** * Instantiate a prefab from a prefab file. * @param filePath The path to the prefab file to instantiate. * @param parent The entity the prefab should be a child of in the transform hierarchy. * @param position The position in world space the prefab should be instantiated in. - * @return An outcome object; on failure, it comes with an error message detailing the cause of the error. + * @return An outcome object with an entityId of the new prefab's container entity; + * on failure, it comes with an error message detailing the cause of the error. */ - virtual PrefabOperationResult InstantiatePrefab(AZStd::string_view filePath, AZ::EntityId parent, const AZ::Vector3& position) = 0; + virtual InstantiatePrefabResult InstantiatePrefab(AZStd::string_view filePath, AZ::EntityId parent, const AZ::Vector3& position) = 0; /** * Saves changes to prefab to disk. diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicRequestBus.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicRequestBus.h new file mode 100644 index 0000000000..1b86d3cd4e --- /dev/null +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicRequestBus.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#pragma once + +#include +#include +#include +#include +#include + +namespace AzToolsFramework +{ + namespace Prefab + { + /** + * The primary purpose of this bus is to facilitate writing automated tests for prefabs. + * It calls PrefabPublicInterface internally to talk to the prefab system. + * If you would like to integrate prefabs into your system, please call PrefabPublicInterface + * directly for better performance. + */ + class PrefabPublicRequests + : public AZ::EBusTraits + { + public: + using Bus = AZ::EBus; + + ////////////////////////////////////////////////////////////////////////// + // EBusTraits overrides + static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single; + ////////////////////////////////////////////////////////////////////////// + + virtual ~PrefabPublicRequests() = default; + + /** + * Create a prefab out of the entities provided, at the path provided, and keep it in memory. + * Automatically detects descendants of entities, and discerns between entities and child instances. + */ + virtual bool CreatePrefabInMemory( + const AZStd::vector& entityIds, AZStd::string_view filePath) = 0; + + /** + * Instantiate a prefab from a prefab file. + */ + virtual AZ::EntityId InstantiatePrefab(AZStd::string_view filePath, AZ::EntityId parent, const AZ::Vector3& position) = 0; + }; + + using PrefabPublicRequestBus = AZ::EBus; + + } // namespace Prefab +} // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicRequestHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicRequestHandler.cpp new file mode 100644 index 0000000000..0e68a286a6 --- /dev/null +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicRequestHandler.cpp @@ -0,0 +1,79 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include + +#include + +namespace AzToolsFramework +{ + namespace Prefab + { + void PrefabPublicRequestHandler::Reflect(AZ::ReflectContext* context) + { + AZ::BehaviorContext* behaviorContext = azrtti_cast(context); + if (behaviorContext) + { + behaviorContext->EBus("PrefabPublicRequestBus") + ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation) + ->Attribute(AZ::Script::Attributes::Category, "Prefab") + ->Attribute(AZ::Script::Attributes::Module, "prefab") + ->Event("CreatePrefabInMemory", &PrefabPublicRequests::CreatePrefabInMemory) + ->Event("InstantiatePrefab", &PrefabPublicRequests::InstantiatePrefab) + ; + } + } + + void PrefabPublicRequestHandler::Connect() + { + m_prefabPublicInterface = AZ::Interface::Get(); + AZ_Assert(m_prefabPublicInterface, "PrefabPublicRequestHandler - Could not retrieve instance of PrefabPublicInterface"); + + PrefabPublicRequestBus::Handler::BusConnect(); + } + + void PrefabPublicRequestHandler::Disconnect() + { + PrefabPublicRequestBus::Handler::BusDisconnect(); + + m_prefabPublicInterface = nullptr; + } + + bool PrefabPublicRequestHandler::CreatePrefabInMemory(const AZStd::vector& entityIds, AZStd::string_view filePath) + { + auto createPrefabOutcome = m_prefabPublicInterface->CreatePrefabInMemory(entityIds, filePath); + if (!createPrefabOutcome.IsSuccess()) + { + AZ_Error("CreatePrefabInMemory", false, + "Failed to create Prefab on file path '%.*s'. Error message: %s.", + AZ_STRING_ARG(filePath), + createPrefabOutcome.GetError().c_str()); + + return false; + } + + return true; + } + + AZ::EntityId PrefabPublicRequestHandler::InstantiatePrefab(AZStd::string_view filePath, AZ::EntityId parent, const AZ::Vector3& position) + { + auto instantiatePrefabOutcome = m_prefabPublicInterface->InstantiatePrefab(filePath, parent, position); + if (!instantiatePrefabOutcome.IsSuccess()) + { + AZ_Error("InstantiatePrefab", false, + "Failed to instantiate Prefab on file path '%.*s'. Error message: %s.", + AZ_STRING_ARG(filePath), + instantiatePrefabOutcome.GetError().c_str()); + + return AZ::EntityId(); + } + + return instantiatePrefabOutcome.GetValue(); + } + } // namespace Prefab +} // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicRequestHandler.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicRequestHandler.h new file mode 100644 index 0000000000..548bc8e04a --- /dev/null +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicRequestHandler.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#pragma once + +#include +#include + +#include + +namespace AzToolsFramework +{ + namespace Prefab + { + class PrefabPublicInterface; + + class PrefabPublicRequestHandler final + : public PrefabPublicRequestBus::Handler + { + public: + AZ_CLASS_ALLOCATOR(PrefabPublicRequestHandler, AZ::SystemAllocator, 0); + AZ_RTTI(PrefabPublicRequestHandler, "{83FBDDF9-10BE-4373-B1DC-44B47EE4805C}"); + + static void Reflect(AZ::ReflectContext* context); + + void Connect(); + void Disconnect(); + + bool CreatePrefabInMemory(const AZStd::vector& entityIds, AZStd::string_view filePath) override; + AZ::EntityId InstantiatePrefab(AZStd::string_view filePath, AZ::EntityId parent, const AZ::Vector3& position) override; + + private: + PrefabPublicInterface* m_prefabPublicInterface = nullptr; + }; + } // namespace Prefab +} // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp index bfdb6b79f2..1051e530c8 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp @@ -35,12 +35,14 @@ namespace AzToolsFramework m_instanceUpdateExecutor.RegisterInstanceUpdateExecutorInterface(); m_instanceToTemplatePropagator.RegisterInstanceToTemplateInterface(); m_prefabPublicHandler.RegisterPrefabPublicHandlerInterface(); + m_prefabPublicRequestHandler.Connect(); AZ::SystemTickBus::Handler::BusConnect(); } void PrefabSystemComponent::Deactivate() { AZ::SystemTickBus::Handler::BusDisconnect(); + m_prefabPublicRequestHandler.Disconnect(); m_prefabPublicHandler.UnregisterPrefabPublicHandlerInterface(); m_instanceToTemplatePropagator.UnregisterInstanceToTemplateInterface(); m_instanceUpdateExecutor.UnregisterInstanceUpdateExecutorInterface(); @@ -54,6 +56,7 @@ namespace AzToolsFramework AzToolsFramework::Prefab::PrefabConversionUtils::PrefabConversionPipeline::Reflect(context); AzToolsFramework::Prefab::PrefabConversionUtils::PrefabCatchmentProcessor::Reflect(context); AzToolsFramework::Prefab::PrefabConversionUtils::EditorInfoRemover::Reflect(context); + PrefabPublicRequestHandler::Reflect(context); AZ::SerializeContext* serialize = azrtti_cast(context); if (serialize) @@ -62,7 +65,6 @@ namespace AzToolsFramework } AZ::JsonRegistrationContext* jsonRegistration = azrtti_cast(context); - if (jsonRegistration) { jsonRegistration->Serializer()->HandlesType(); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h index 04457b5a97..b07ccbada6 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -369,6 +370,9 @@ namespace AzToolsFramework // Used for updating Templates when Instances are modified InstanceToTemplatePropagator m_instanceToTemplatePropagator; + + // Handler of the public Prefab requests + PrefabPublicRequestHandler m_prefabPublicRequestHandler; }; } // namespace Prefab } // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp index 5bf9b15abe..eb9cf2b65f 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp @@ -256,11 +256,11 @@ namespace AzToolsFramework void PrefabIntegrationManager::HandleSourceFileType(AZStd::string_view sourceFilePath, AZ::EntityId parentId, AZ::Vector3 position) const { - auto createPrefabOutcome = s_prefabPublicInterface->InstantiatePrefab(sourceFilePath, parentId, position); + auto instantiatePrefabOutcome = s_prefabPublicInterface->InstantiatePrefab(sourceFilePath, parentId, position); - if (!createPrefabOutcome.IsSuccess()) + if (!instantiatePrefabOutcome.IsSuccess()) { - WarnUserOfError("Prefab Instantiation Error", createPrefabOutcome.GetError()); + WarnUserOfError("Prefab Instantiation Error", instantiatePrefabOutcome.GetError()); } } @@ -348,7 +348,7 @@ namespace AzToolsFramework } } - auto createPrefabOutcome = s_prefabPublicInterface->CreatePrefab(selectedEntities, prefabFilePath.data()); + auto createPrefabOutcome = s_prefabPublicInterface->CreatePrefabInDisk(selectedEntities, prefabFilePath.data()); if (!createPrefabOutcome.IsSuccess()) { diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake b/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake index 53173f83af..14c5f34f90 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake @@ -657,6 +657,9 @@ set(FILES Prefab/PrefabPublicHandler.cpp Prefab/PrefabPublicInterface.h Prefab/PrefabPublicNotificationBus.h + Prefab/PrefabPublicRequestBus.h + Prefab/PrefabPublicRequestHandler.h + Prefab/PrefabPublicRequestHandler.cpp Prefab/PrefabUndo.h Prefab/PrefabUndo.cpp Prefab/PrefabUndoCache.cpp From e0410385d568f7377439ed23c3a6c102d1d08fdd Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Wed, 11 Aug 2021 16:38:13 -0500 Subject: [PATCH 297/803] AtomTools: fixing status bar messages fixed problems with status bar messages not appearing added status bar messages to shader management console got rid of central widget variable and moved layout to atom tools window base class Signed-off-by: Guthrie Adams --- .../Window/AtomToolsMainWindow.h | 5 +- .../Source/Window/AtomToolsMainWindow.cpp | 18 +++-- .../Source/Window/MaterialEditorWindow.cpp | 55 ++++++------- .../Window/ShaderManagementConsoleWindow.cpp | 80 ++++++++++++++----- .../Window/ShaderManagementConsoleWindow.h | 3 + 5 files changed, 100 insertions(+), 61 deletions(-) diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindow.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindow.h index 82444246fd..751b30a907 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindow.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindow.h @@ -16,8 +16,8 @@ #include #include +#include #include -#include #include namespace AtomToolsFramework @@ -53,10 +53,9 @@ namespace AtomToolsFramework virtual void SelectNextTab(); AzQtComponents::FancyDocking* m_advancedDockManager = nullptr; - QWidget* m_centralWidget = nullptr; QMenuBar* m_menuBar = nullptr; AzQtComponents::TabWidget* m_tabWidget = nullptr; - QStatusBar* m_statusBar = nullptr; + QLabel* m_statusMessage = nullptr; AZStd::unordered_map m_dockWidgets; }; diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp index f6e56b1ff6..55bec32dc7 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp @@ -7,6 +7,8 @@ */ #include +#include +#include namespace AtomToolsFramework { @@ -21,11 +23,15 @@ namespace AtomToolsFramework setCorner(Qt::TopRightCorner, Qt::RightDockWidgetArea); setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea); - m_statusBar = new QStatusBar(this); - m_statusBar->setObjectName("StatusBar"); - statusBar()->addPermanentWidget(m_statusBar, 1); + m_statusMessage = new QLabel(statusBar()); + statusBar()->addPermanentWidget(m_statusMessage, 1); - m_centralWidget = new QWidget(this); + auto centralWidget = new QWidget(this); + auto centralWidgetLayout = new QVBoxLayout(centralWidget); + centralWidgetLayout->setMargin(0); + centralWidgetLayout->setContentsMargins(0, 0, 0, 0); + centralWidget->setLayout(centralWidgetLayout); + setCentralWidget(centralWidget); AtomToolsMainWindowRequestBus::Handler::BusConnect(); } @@ -111,7 +117,7 @@ namespace AtomToolsFramework void AtomToolsMainWindow::CreateTabBar() { - m_tabWidget = new AzQtComponents::TabWidget(m_centralWidget); + m_tabWidget = new AzQtComponents::TabWidget(centralWidget()); m_tabWidget->setObjectName("TabWidget"); m_tabWidget->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Preferred); m_tabWidget->setContentsMargins(0, 0, 0, 0); @@ -131,6 +137,8 @@ namespace AtomToolsFramework { OpenTabContextMenu(); }); + + centralWidget()->layout()->addWidget(m_tabWidget); } void AtomToolsMainWindow::AddTabForDocumentId( diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp index f4dfa3df1b..fca3cc59eb 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp @@ -36,8 +36,6 @@ AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnin #include #include #include -#include -#include #include AZ_POP_DISABLE_WARNING @@ -77,20 +75,13 @@ namespace MaterialEditor m_toolBar->setObjectName("ToolBar"); addToolBar(m_toolBar); - m_materialViewport = new MaterialViewportWidget(m_centralWidget); - m_materialViewport->setObjectName("Viewport"); - m_materialViewport->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); - CreateMenu(); CreateTabBar(); - QVBoxLayout* vl = new QVBoxLayout(m_centralWidget); - vl->setMargin(0); - vl->setContentsMargins(0, 0, 0, 0); - vl->addWidget(m_tabWidget); - vl->addWidget(m_materialViewport); - m_centralWidget->setLayout(vl); - setCentralWidget(m_centralWidget); + m_materialViewport = new MaterialViewportWidget(centralWidget()); + m_materialViewport->setObjectName("Viewport"); + m_materialViewport->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); + centralWidget()->layout()->addWidget(m_materialViewport); AddDockWidget("Asset Browser", new MaterialBrowserWidget, Qt::BottomDockWidgetArea, Qt::Vertical); AddDockWidget("Inspector", new MaterialInspector, Qt::RightDockWidgetArea, Qt::Horizontal); @@ -200,7 +191,7 @@ namespace MaterialEditor // Create a new tab for the document ID and assign it's label to the file name of the document. AddTabForDocumentId(documentId, filename, absolutePath, [this]{ // The tab widget requires a dummy page per tab - auto contentWidget = new QWidget(m_centralWidget); + auto contentWidget = new QWidget(centralWidget()); contentWidget->setContentsMargins(0, 0, 0, 0); contentWidget->setFixedSize(0, 0); return contentWidget; @@ -247,8 +238,8 @@ namespace MaterialEditor const QString documentPath = GetDocumentPath(documentId); if (!documentPath.isEmpty()) { - const QString status = QString("Material closed: %1").arg(documentPath); - m_statusBar->setWindowIconText(QString("%1").arg(status)); + const QString status = QString("Document closed: %1").arg(documentPath); + m_statusMessage->setText(QString("%1").arg(status)); } } @@ -257,8 +248,8 @@ namespace MaterialEditor RemoveTabForDocumentId(documentId); const QString documentPath = GetDocumentPath(documentId); - const QString status = QString("Material closed: %1").arg(documentPath); - m_statusBar->setWindowIconText(QString("%1").arg(status)); + const QString status = QString("Document closed: %1").arg(documentPath); + m_statusMessage->setText(QString("%1").arg(status)); } void MaterialEditorWindow::OnDocumentModified(const AZ::Uuid& documentId) @@ -296,8 +287,8 @@ namespace MaterialEditor UpdateTabForDocumentId(documentId, filename, absolutePath, isModified); const QString documentPath = GetDocumentPath(documentId); - const QString status = QString("Material closed: %1").arg(documentPath); - m_statusBar->setWindowIconText(QString("%1").arg(status)); + const QString status = QString("Document closed: %1").arg(documentPath); + m_statusMessage->setText(QString("%1").arg(status)); } void MaterialEditorWindow::CreateMenu() @@ -341,8 +332,8 @@ namespace MaterialEditor if (!result) { const QString documentPath = GetDocumentPath(documentId); - const QString status = QString("Failed to save material: %1").arg(documentPath); - m_statusBar->setWindowIconText(QString("%1").arg(status)); + const QString status = QString("Failed to save document: %1").arg(documentPath); + m_statusMessage->setText(QString("%1").arg(status)); } }, QKeySequence::Save); @@ -355,8 +346,8 @@ namespace MaterialEditor documentId, AtomToolsFramework::GetSaveFileInfo(documentPath).absoluteFilePath().toUtf8().constData()); if (!result) { - const QString status = QString("Failed to save material: %1").arg(documentPath); - m_statusBar->setWindowIconText(QString("%1").arg(status)); + const QString status = QString("Failed to save document: %1").arg(documentPath); + m_statusMessage->setText(QString("%1").arg(status)); } }, QKeySequence::SaveAs); @@ -369,8 +360,8 @@ namespace MaterialEditor documentId, AtomToolsFramework::GetSaveFileInfo(documentPath).absoluteFilePath().toUtf8().constData()); if (!result) { - const QString status = QString("Failed to save material: %1").arg(documentPath); - m_statusBar->setWindowIconText(QString("%1").arg(status)); + const QString status = QString("Failed to save document: %1").arg(documentPath); + m_statusMessage->setText(QString("%1").arg(status)); } }); @@ -379,8 +370,8 @@ namespace MaterialEditor MaterialDocumentSystemRequestBus::BroadcastResult(result, &MaterialDocumentSystemRequestBus::Events::SaveAllDocuments); if (!result) { - const QString status = QString("Failed to save materials."); - m_statusBar->setWindowIconText(QString("%1").arg(status)); + const QString status = QString("Failed to save documents."); + m_statusMessage->setText(QString("%1").arg(status)); } }); @@ -425,8 +416,8 @@ namespace MaterialEditor if (!result) { const QString documentPath = GetDocumentPath(documentId); - const QString status = QString("Failed to perform Undo in material: %1").arg(documentPath); - m_statusBar->setWindowIconText(QString("%1").arg(status)); + const QString status = QString("Failed to perform Undo on document: %1").arg(documentPath); + m_statusMessage->setText(QString("%1").arg(status)); } }, QKeySequence::Undo); @@ -437,8 +428,8 @@ namespace MaterialEditor if (!result) { const QString documentPath = GetDocumentPath(documentId); - const QString status = QString("Failed to perform Undo in material: %1").arg(documentPath); - m_statusBar->setWindowIconText(QString("%1").arg(status)); + const QString status = QString("Failed to perform Redo on document: %1").arg(documentPath); + m_statusMessage->setText(QString("%1").arg(status)); } }, QKeySequence::Redo); diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp index 0a082f3c33..ec9ad08e21 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp @@ -8,6 +8,8 @@ #include #include +#include +#include #include #include #include @@ -23,11 +25,8 @@ AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnin #include #include #include -#include #include #include -#include -#include #include AZ_POP_DISABLE_WARNING @@ -36,6 +35,14 @@ namespace ShaderManagementConsole ShaderManagementConsoleWindow::ShaderManagementConsoleWindow(QWidget* parent /* = 0 */) : AtomToolsFramework::AtomToolsMainWindow(parent) { + resize(1280, 1024); + + // Among other things, we need the window wrapper to save the main window size, position, and state + auto mainWindowWrapper = + new AzQtComponents::WindowDecorationWrapper(AzQtComponents::WindowDecorationWrapper::OptionAutoTitleBarButtons); + mainWindowWrapper->setGuest(this); + mainWindowWrapper->enableSaveRestoreGeometry("O3DE", "ShaderManagementConsole", "mainWindowGeometry"); + setWindowTitle("Shader Management Console"); setObjectName("ShaderManagementConsoleWindow"); @@ -47,16 +54,14 @@ namespace ShaderManagementConsole CreateMenu(); CreateTabBar(); - QVBoxLayout* vl = new QVBoxLayout(m_centralWidget); - vl->setMargin(0); - vl->setContentsMargins(0, 0, 0, 0); - vl->addWidget(m_tabWidget); - m_centralWidget->setLayout(vl); - setCentralWidget(m_centralWidget); - AddDockWidget("Asset Browser", new ShaderManagementConsoleBrowserWidget, Qt::BottomDockWidgetArea, Qt::Vertical); AddDockWidget("Python Terminal", new AzToolsFramework::CScriptTermDialog, Qt::BottomDockWidgetArea, Qt::Horizontal); + SetDockWidgetVisible("Python Terminal", false); + + // Restore geometry and show the window + mainWindowWrapper->showFromSettings(); + ShaderManagementConsoleDocumentNotificationBus::Handler::BusConnect(); OnDocumentOpened(AZ::Uuid::CreateNull()); } @@ -103,8 +108,7 @@ namespace ShaderManagementConsole // Create a new tab for the document ID and assign it's label to the file name of the document. AddTabForDocumentId(documentId, filename, absolutePath, [this, documentId]{ // The document tab contains a table view. - auto contentWidget = new QTableView(m_centralWidget); - contentWidget->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + auto contentWidget = new QTableView(centralWidget()); contentWidget->setSelectionBehavior(QAbstractItemView::SelectRows); contentWidget->setModel(CreateDocumentContent(documentId)); return contentWidget; @@ -142,11 +146,22 @@ namespace ShaderManagementConsole activateWindow(); raise(); + + const QString documentPath = GetDocumentPath(documentId); + if (!documentPath.isEmpty()) + { + const QString status = QString("Document closed: %1").arg(documentPath); + m_statusMessage->setText(QString("%1").arg(status)); + } } void ShaderManagementConsoleWindow::OnDocumentClosed(const AZ::Uuid& documentId) { RemoveTabForDocumentId(documentId); + + const QString documentPath = GetDocumentPath(documentId); + const QString status = QString("Document closed: %1").arg(documentPath); + m_statusMessage->setText(QString("%1").arg(status)); } void ShaderManagementConsoleWindow::OnDocumentModified(const AZ::Uuid& documentId) @@ -182,6 +197,10 @@ namespace ShaderManagementConsole AZStd::string filename; AzFramework::StringFunc::Path::GetFullFileName(absolutePath.c_str(), filename); UpdateTabForDocumentId(documentId, filename, absolutePath, isModified); + + const QString documentPath = GetDocumentPath(documentId); + const QString status = QString("Document closed: %1").arg(documentPath); + m_statusMessage->setText(QString("%1").arg(status)); } void ShaderManagementConsoleWindow::CreateMenu() @@ -254,12 +273,26 @@ namespace ShaderManagementConsole m_actionUndo = m_menuEdit->addAction("&Undo", [this]() { const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex()); - ShaderManagementConsoleDocumentRequestBus::Event(documentId, &ShaderManagementConsoleDocumentRequestBus::Events::Undo); + bool result = false; + ShaderManagementConsoleDocumentRequestBus::EventResult(result, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::Undo); + if (!result) + { + const QString documentPath = GetDocumentPath(documentId); + const QString status = QString("Failed to perform Undo on document: %1").arg(documentPath); + m_statusMessage->setText(QString("%1").arg(status)); + } }, QKeySequence::Undo); m_actionRedo = m_menuEdit->addAction("&Redo", [this]() { const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex()); - ShaderManagementConsoleDocumentRequestBus::Event(documentId, &ShaderManagementConsoleDocumentRequestBus::Events::Redo); + bool result = false; + ShaderManagementConsoleDocumentRequestBus::EventResult(result, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::Redo); + if (!result) + { + const QString documentPath = GetDocumentPath(documentId); + const QString status = QString("Failed to perform Redo on document: %1").arg(documentPath); + m_statusMessage->setText(QString("%1").arg(status)); + } }, QKeySequence::Redo); m_menuEdit->addSeparator(); @@ -278,13 +311,11 @@ namespace ShaderManagementConsole SetDockWidgetVisible(label, !IsDockWidgetVisible(label)); }); - m_actionPythonTerminal = m_menuView->addAction( - "Python &Terminal", - [this]() - { - const AZStd::string label = "Python Terminal"; - SetDockWidgetVisible(label, !IsDockWidgetVisible(label)); - }); + m_actionPythonTerminal = m_menuView->addAction("Python &Terminal", [this]() { + const AZStd::string label = "Python Terminal"; + SetDockWidgetVisible(label, !IsDockWidgetVisible(label)); + }); + m_menuView->addSeparator(); @@ -321,6 +352,13 @@ namespace ShaderManagementConsole }); } + QString ShaderManagementConsoleWindow::GetDocumentPath(const AZ::Uuid& documentId) const + { + AZStd::string absolutePath; + ShaderManagementConsoleDocumentRequestBus::EventResult(absolutePath, documentId, &ShaderManagementConsoleDocumentRequestBus::Handler::GetAbsolutePath); + return absolutePath.c_str(); + } + void ShaderManagementConsoleWindow::OpenTabContextMenu() { const QTabBar* tabBar = m_tabWidget->tabBar(); diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.h b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.h index aae31d1000..37efcb1b45 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.h +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.h @@ -52,6 +52,9 @@ namespace ShaderManagementConsole void CreateMenu() override; void CreateTabBar() override; + + QString GetDocumentPath(const AZ::Uuid& documentId) const; + void OpenTabContextMenu() override; void SelectDocumentForTab(const int tabIndex); From aaa847a56931f1ba9a5ebffe6a1ea1911d9aae1e Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Wed, 11 Aug 2021 14:40:34 -0700 Subject: [PATCH 298/803] Remove empty User Functions and Script Event sections Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- .../View/Widgets/ScriptCanvasNodePaletteDockWidget.cpp | 5 ++--- .../Code/Include/ScriptCanvas/Core/SubgraphInterface.cpp | 3 ++- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Gems/ScriptCanvas/Code/Editor/View/Widgets/ScriptCanvasNodePaletteDockWidget.cpp b/Gems/ScriptCanvas/Code/Editor/View/Widgets/ScriptCanvasNodePaletteDockWidget.cpp index 8341cc1e24..96b0ac353f 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Widgets/ScriptCanvasNodePaletteDockWidget.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Widgets/ScriptCanvasNodePaletteDockWidget.cpp @@ -80,12 +80,11 @@ namespace ScriptCanvasEditor GraphCanvas::NodePaletteTreeItem* variablesRoot = root->CreateChildNode("Variables"); root->RegisterCategoryNode(variablesRoot, "Variables"); - // We always want to keep these around as place holders GraphCanvas::NodePaletteTreeItem* customEventRoot = root->GetCategoryNode("Script Events"); - customEventRoot->SetAllowPruneOnEmpty(false); + customEventRoot->SetAllowPruneOnEmpty(true); GraphCanvas::NodePaletteTreeItem* globalFunctionRoot = root->GetCategoryNode("User Functions"); - globalFunctionRoot->SetAllowPruneOnEmpty(false); + globalFunctionRoot->SetAllowPruneOnEmpty(true); } diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/SubgraphInterface.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/SubgraphInterface.cpp index 81d6445556..9d1626fb73 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/SubgraphInterface.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/SubgraphInterface.cpp @@ -509,7 +509,8 @@ namespace ScriptCanvas bool SubgraphInterface::HasAnyFunctionality() const { - return IsActiveDefaultObject() || HasPublicFunctionality(); + // \todo restore default object addition when ndoes can define an variable, as well + return /*IsActiveDefaultObject() || */ HasPublicFunctionality(); } bool SubgraphInterface::HasBranches() const From fb1ee0f037b0bda8f9cf87e7c4690956804d5c67 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Wed, 11 Aug 2021 16:45:51 -0500 Subject: [PATCH 299/803] updated undo/redo messages Signed-off-by: Guthrie Adams --- .../Code/Source/Window/MaterialEditorWindow.cpp | 4 ++-- .../Code/Source/Window/ShaderManagementConsoleWindow.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp index fca3cc59eb..ffe5ec408a 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp @@ -416,7 +416,7 @@ namespace MaterialEditor if (!result) { const QString documentPath = GetDocumentPath(documentId); - const QString status = QString("Failed to perform Undo on document: %1").arg(documentPath); + const QString status = QString("Failed to perform undo on document: %1").arg(documentPath); m_statusMessage->setText(QString("%1").arg(status)); } }, QKeySequence::Undo); @@ -428,7 +428,7 @@ namespace MaterialEditor if (!result) { const QString documentPath = GetDocumentPath(documentId); - const QString status = QString("Failed to perform Redo on document: %1").arg(documentPath); + const QString status = QString("Failed to perform redo on document: %1").arg(documentPath); m_statusMessage->setText(QString("%1").arg(status)); } }, QKeySequence::Redo); diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp index ec9ad08e21..a7c8d79130 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp @@ -278,7 +278,7 @@ namespace ShaderManagementConsole if (!result) { const QString documentPath = GetDocumentPath(documentId); - const QString status = QString("Failed to perform Undo on document: %1").arg(documentPath); + const QString status = QString("Failed to perform undo on document: %1").arg(documentPath); m_statusMessage->setText(QString("%1").arg(status)); } }, QKeySequence::Undo); @@ -290,7 +290,7 @@ namespace ShaderManagementConsole if (!result) { const QString documentPath = GetDocumentPath(documentId); - const QString status = QString("Failed to perform Redo on document: %1").arg(documentPath); + const QString status = QString("Failed to perform redo on document: %1").arg(documentPath); m_statusMessage->setText(QString("%1").arg(status)); } }, QKeySequence::Redo); From 584c125fbc2a69d79934c5ef478f53f9526e5213 Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Wed, 11 Aug 2021 15:11:20 -0700 Subject: [PATCH 300/803] rename serializer Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- ...ScriptUserDataSerializer.cpp => RuntimeVariableSerializer.cpp} | 0 .../{ScriptUserDataSerializer.h => RuntimeVariableSerializer.h} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename Gems/ScriptCanvas/Code/Include/ScriptCanvas/Serialization/{ScriptUserDataSerializer.cpp => RuntimeVariableSerializer.cpp} (100%) rename Gems/ScriptCanvas/Code/Include/ScriptCanvas/Serialization/{ScriptUserDataSerializer.h => RuntimeVariableSerializer.h} (100%) diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Serialization/ScriptUserDataSerializer.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Serialization/RuntimeVariableSerializer.cpp similarity index 100% rename from Gems/ScriptCanvas/Code/Include/ScriptCanvas/Serialization/ScriptUserDataSerializer.cpp rename to Gems/ScriptCanvas/Code/Include/ScriptCanvas/Serialization/RuntimeVariableSerializer.cpp diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Serialization/ScriptUserDataSerializer.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Serialization/RuntimeVariableSerializer.h similarity index 100% rename from Gems/ScriptCanvas/Code/Include/ScriptCanvas/Serialization/ScriptUserDataSerializer.h rename to Gems/ScriptCanvas/Code/Include/ScriptCanvas/Serialization/RuntimeVariableSerializer.h From 935bef61b2dff21624c197dd52aa30ecf46ae2d5 Mon Sep 17 00:00:00 2001 From: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> Date: Wed, 11 Aug 2021 15:29:42 -0700 Subject: [PATCH 301/803] Rename NonUniformScale svg icon to fix warning. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> --- .../Viewport/{Non Uniform Scale.svg => NonUniformScale.svg} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Assets/Editor/Icons/Components/Viewport/{Non Uniform Scale.svg => NonUniformScale.svg} (100%) diff --git a/Assets/Editor/Icons/Components/Viewport/Non Uniform Scale.svg b/Assets/Editor/Icons/Components/Viewport/NonUniformScale.svg similarity index 100% rename from Assets/Editor/Icons/Components/Viewport/Non Uniform Scale.svg rename to Assets/Editor/Icons/Components/Viewport/NonUniformScale.svg From 016cfef6ca569b3a407e819481ef6a83d661202c Mon Sep 17 00:00:00 2001 From: Jacob Hilliard <64656371+jcbhl@users.noreply.github.com> Date: Wed, 11 Aug 2021 15:32:11 -0700 Subject: [PATCH 302/803] Visualizer: fix empty rows being shown (#2881) Fixes a bug with the visualizer where there would be empty rows shown, e.g. threads without any profiling regions. This was especially noticable when going from a high thread count sample (MultiThread) to a low thread count sample, where most of the visualizer would be empty lines. This adds a data culling step to remove the threads without any remaining execution data + an early out so that all threads shown onscreen must have some regions recorded. Signed-off-by: Jacob Hilliard --- .../Code/Include/Atom/Utils/ImGuiCpuProfiler.inl | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl index ffc9a60c00..a24fdbf1d8 100644 --- a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl +++ b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl @@ -329,7 +329,7 @@ namespace AZ ImGui::Text("Viewport width: %.3f ms", CpuProfilerImGuiHelper::TicksToMs(GetViewportTickWidth())); ImGui::Text("Ticks [%lld , %lld]", m_viewportStartTick, m_viewportEndTick); - ImGui::Text("Recording %ld threads", RHI::CpuProfiler::Get()->GetTimeRegionMap().size()); + ImGui::Text("Recording %zu threads", m_savedData.size()); ImGui::Text("%llu profiling events saved", m_savedRegionCount); ImGui::NextColumn(); @@ -389,6 +389,11 @@ namespace AZ return wrapper.m_startTick < target; }); + if (regionItr == singleThreadData.end()) + { + continue; + } + // Draw all of the blocks for a given thread/row u64 maxDepth = 0; while (regionItr != singleThreadData.end()) @@ -559,6 +564,14 @@ namespace AZ m_savedRegionCount -= sizeBeforeRemove - savedRegions.size(); } + + // Remove any threads from the top-level map that no longer hold data + AZStd::erase_if( + m_savedData, + [](const auto& singleThreadDataEntry) + { + return singleThreadDataEntry.second.empty(); + }); } inline void ImGuiCpuProfiler::DrawBlock(const TimeRegion& block, u64 targetRow) From 6c83dcd702ed015d9f6d6a3b08685a4f59752673 Mon Sep 17 00:00:00 2001 From: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> Date: Wed, 11 Aug 2021 15:44:04 -0700 Subject: [PATCH 303/803] [redcode/crythread-2nd-pass] fixed another missing include Signed-off-by: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> --- Code/LauncherUnified/Platform/Windows/Launcher_Windows.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Code/LauncherUnified/Platform/Windows/Launcher_Windows.cpp b/Code/LauncherUnified/Platform/Windows/Launcher_Windows.cpp index 5cc3070cdb..44426f6d01 100644 --- a/Code/LauncherUnified/Platform/Windows/Launcher_Windows.cpp +++ b/Code/LauncherUnified/Platform/Windows/Launcher_Windows.cpp @@ -9,6 +9,7 @@ #include #include +#include int APIENTRY WinMain([[maybe_unused]] HINSTANCE hInstance, [[maybe_unused]] HINSTANCE hPrevInstance, [[maybe_unused]] LPSTR lpCmdLine, [[maybe_unused]] int nCmdShow) { From 0c05c9f20462a708de228e5ff06acd96d9b3a533 Mon Sep 17 00:00:00 2001 From: Kyle B Date: Wed, 11 Aug 2021 15:49:50 -0700 Subject: [PATCH 304/803] [not working] Made lod selection more generic for further work Signed-off-by: Kyle B --- .../Code/Source/Mesh/MeshFeatureProcessor.cpp | 2 +- .../Code/Include/Atom/RPI.Public/Culling.h | 26 +++++------ .../RPI/Code/Source/RPI.Public/Culling.cpp | 27 ++++++----- .../QuadSphere_Default.material | 28 +++++++++++ .../Code/Source/Mesh/EditorMeshComponent.cpp | 9 +++- .../Source/Mesh/MeshComponentController.cpp | 46 +++++++++++++++++-- .../Source/Mesh/MeshComponentController.h | 11 +++-- 7 files changed, 113 insertions(+), 36 deletions(-) create mode 100644 Gems/Atom/Tools/MaterialEditor/Assets/MaterialEditor/ViewportModels/QuadSphere_Default.material diff --git a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp index 679e64e283..363723f7da 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp @@ -376,7 +376,7 @@ namespace AZ else { AZ_Assert(false, "Invalid mesh handle"); - return {0,0,0.0f,0.0f}; + return {RPI::Cullable::LodType::Default, 0, 0.0f, 0.0f }; } } diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Culling.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Culling.h index e89e180540..82e9c733c8 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Culling.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Culling.h @@ -70,17 +70,22 @@ namespace AZ }; CullData m_cullData; - using LodType = uint8_t; + enum LodType : uint8_t + { + Default = 0, + ScreenCoverage, + SpecificLod, + }; using LodOverride = uint8_t; - static constexpr uint8_t NoLodOverride = AZStd::numeric_limits::max(); - static constexpr uint8_t DefaultLodType = AZStd::numeric_limits::max(); struct LodConfiguration { - LodType m_lodType; - LodOverride m_lodOverride; - float m_minimumScreenCoverage; - float m_qualityDecayRate; + LodType m_lodType = LodType::Default; + LodOverride m_lodOverride = 0; + // the minimum possibe area a sphere enclosing a mesh projected onto the screen should have before it is culled. + float m_minimumScreenCoverage = 1.0f / 1080.0f; // For default, mesh should cover at least a screen pixel at 1080p to be drawn; + // The screen area decay between 0 and 1, i.e. closer to 1 -> lose quality immediately, closer to 0 -> never lose quality + float m_qualityDecayRate = 0.5f; }; struct LodData @@ -98,12 +103,7 @@ namespace AZ //! Suggest setting to: 0.5f*localAabb.GetExtents().GetMaxElement() float m_lodSelectionRadius = 1.0f; - // the minimum possibe area a sphere enclosing a mesh projected onto the screen should have before it is culled. - static constexpr float DefaultMinimumScreenCoverage = 1.0f / 1080.0f; //For default, mesh should cover at least a screen pixel at 1080p to be drawn - // The screen area decay between 0 and 1, i.e. closer to 1 -> lose quality immediately, closer to 0 -> never lose quality - static constexpr float DefaultQualityDecayRate = 0.5f; - - LodConfiguration m_lodConfiguration = { DefaultLodType, NoLodOverride, DefaultMinimumScreenCoverage, DefaultQualityDecayRate }; + LodConfiguration m_lodConfiguration; }; LodData m_lodData; diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Culling.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Culling.cpp index f22d5c7224..c0d9023fa9 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Culling.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Culling.cpp @@ -672,20 +672,25 @@ namespace AZ } }; - if (lodData.m_lodConfiguration.m_lodOverride == Cullable::NoLodOverride) + switch (lodData.m_lodConfiguration.m_lodType) { - for (const Cullable::LodData::Lod& lod : lodData.m_lods) - { - //Note that this supports overlapping lod ranges (to suport cross-fading lods, for example) - if (approxScreenPercentage >= lod.m_screenCoverageMin && approxScreenPercentage <= lod.m_screenCoverageMax) + case Cullable::LodType::SpecificLod: + if (lodData.m_lodConfiguration.m_lodOverride < lodData.m_lods.size()) { - addLodToDrawPacket(lod); + addLodToDrawPacket(lodData.m_lods.at(lodData.m_lodConfiguration.m_lodOverride)); } - } - } - else if(lodData.m_lodConfiguration.m_lodOverride < lodData.m_lods.size()) - { - addLodToDrawPacket(lodData.m_lods.at(lodData.m_lodConfiguration.m_lodOverride)); + break; + case Cullable::LodType::ScreenCoverage: + default: + for (const Cullable::LodData::Lod& lod : lodData.m_lods) + { + // Note that this supports overlapping lod ranges (to suport cross-fading lods, for example) + if (approxScreenPercentage >= lod.m_screenCoverageMin && approxScreenPercentage <= lod.m_screenCoverageMax) + { + addLodToDrawPacket(lod); + } + } + break; } return numVisibleDrawPackets; diff --git a/Gems/Atom/Tools/MaterialEditor/Assets/MaterialEditor/ViewportModels/QuadSphere_Default.material b/Gems/Atom/Tools/MaterialEditor/Assets/MaterialEditor/ViewportModels/QuadSphere_Default.material new file mode 100644 index 0000000000..4905c302fe --- /dev/null +++ b/Gems/Atom/Tools/MaterialEditor/Assets/MaterialEditor/ViewportModels/QuadSphere_Default.material @@ -0,0 +1,28 @@ +{ + "description": "", + "materialType": "Materials/Types/StandardPBR.materialtype", + "parentMaterial": "", + "propertyLayoutVersion": 3, + "properties": { + "baseColor": { + "color": [ + 0.800000011920929, + 0.800000011920929, + 0.800000011920929, + 1.0 + ], + "textureMap": "MaterialEditor/ViewportModels/_dev_shaderball_00_basecolor.png" + }, + "emissive": { + "color": [ + 0.0, + 0.0, + 0.0, + 1.0 + ] + }, + "opacity": { + "factor": 1.0 + } + } +} \ No newline at end of file diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp index 0719d9f2bb..ff0741fc31 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp @@ -79,20 +79,25 @@ namespace AZ ->DataElement(AZ::Edit::UIHandlers::CheckBox, &MeshComponentConfig::m_useForwardPassIblSpecular, "Use Forward Pass IBL Specular", "Renders IBL specular reflections in the forward pass, using only the most influential probe (based on the position of the entity) and the global IBL cubemap. Can reduce rendering costs, but only recommended for static objects that are affected by at most one reflection probe.") ->Attribute(AZ::Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) - ->ClassElement(AZ::Edit::ClassElements::Group, "Lod Configuration") - ->Attribute(AZ::Edit::Attributes::AutoExpand, false) ->DataElement(AZ::Edit::UIHandlers::ComboBox, &MeshComponentConfig::m_lodType, "Lod Type", "Lod Method.") ->Attribute(AZ::Edit::Attributes::EnumValues, &MeshComponentConfig::GetLodTypeValues) + ->Attribute(AZ::Edit::Attributes::Visibility, &MeshComponentConfig::IsAssetSet) + ->ClassElement(AZ::Edit::ClassElements::Group, "Lod Configuration") + ->Attribute(AZ::Edit::Attributes::AutoExpand, false) + ->Attribute(AZ::Edit::Attributes::Visibility, &MeshComponentConfig::ShowLodConfig) ->DataElement(AZ::Edit::UIHandlers::ComboBox, &MeshComponentConfig::m_lodOverride, "Lod Override", "Allows the rendered LOD to be overridden instead of being calculated automatically.") ->Attribute(AZ::Edit::Attributes::EnumValues, &MeshComponentConfig::GetLodOverrideValues) + ->Attribute(AZ::Edit::Attributes::Visibility, &MeshComponentConfig::LodTypeIsSpecificLOD) ->DataElement(AZ::Edit::UIHandlers::Slider, &MeshComponentConfig::m_minimumScreenCoverage, "Minimum Screen Coverage", "Minimum proportion of screen area an entitiy takes up, after that the entitiy is culled.") ->Attribute(AZ::Edit::Attributes::Min, 0.f) ->Attribute(AZ::Edit::Attributes::Max, 1.f) ->Attribute(AZ::Edit::Attributes::Suffix, " percent") + ->Attribute(AZ::Edit::Attributes::Visibility, &MeshComponentConfig::LodTypeIsScreenCoverage) ->DataElement(AZ::Edit::UIHandlers::Slider, &MeshComponentConfig::m_qualityDecayRate, "Quality Decay Rate", "Rate at which mesh quality decays (0 -> always stay highest quality, 1 -> quality falls off to lowest quality immediately).") ->Attribute(AZ::Edit::Attributes::Min, 0.f) ->Attribute(AZ::Edit::Attributes::Max, 1.f) + ->Attribute(AZ::Edit::Attributes::Visibility, &MeshComponentConfig::LodTypeIsScreenCoverage) ; } } diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp index adcf570899..3d049d0f97 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp @@ -31,11 +31,30 @@ namespace AZ { namespace Render { + + namespace MeshComponentControllerVersionUtility + { + bool VersionConverter(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement) + { + if (classElement.GetVersion() < 2) + { + RPI::Cullable::LodOverride lodOverride = classElement.FindElement(AZ_CRC("LodOverride")); + static constexpr uint8_t old_NoLodOverride = AZStd::numeric_limits ::max(); + if (lodOverride == old_NoLodOverride) + { + classElement.AddElementWithData(context, "LodType", RPI::Cullable::LodType::SpecificLod); + } + } + return true; + } + } // namespace MeshComponentControllerVersionUtility + void MeshComponentConfig::Reflect(ReflectContext* context) { if (auto* serializeContext = azrtti_cast(context)) { serializeContext->Class() + //->Version(2, &MeshComponentControllerVersionUtility::VersionConverter) ->Version(1) ->Field("ModelAsset", &MeshComponentConfig::m_modelAsset) ->Field("SortKey", &MeshComponentConfig::m_sortKey) @@ -53,6 +72,21 @@ namespace AZ return m_modelAsset.GetId().IsValid(); } + bool MeshComponentConfig::LodTypeIsScreenCoverage() + { + return m_lodType == RPI::Cullable::LodType::ScreenCoverage; + } + + bool MeshComponentConfig::LodTypeIsSpecificLOD() + { + return m_lodType == RPI::Cullable::LodType::SpecificLod; + } + + bool MeshComponentConfig::ShowLodConfig() + { + return LodTypeIsScreenCoverage() && LodTypeIsSpecificLOD(); + } + AZStd::vector> MeshComponentConfig::GetLodOverrideValues() { AZStd::vector> values; @@ -75,9 +109,9 @@ namespace AZ } values.reserve(lodCount + 1); - values.push_back({ RPI::Cullable::NoLodOverride, "Not Set" }); + values.push_back({0, "Default (Highest)" }); - for (uint32_t i = 0; i < lodCount; ++i) + for (uint32_t i = 1; i < lodCount; ++i) { AZStd::string enumDescription = AZStd::string::format("Lod %i", i); values.push_back({ aznumeric_cast(i), enumDescription.c_str() }); @@ -89,7 +123,9 @@ namespace AZ AZStd::vector> MeshComponentConfig::GetLodTypeValues() { return { - {RPI::Cullable::DefaultLodType, "Default"} + {aznumeric_cast(0), "Default"}, + {aznumeric_cast(1), "Screen Coverage" }, + {aznumeric_cast(2), "Specific Lod" } }; } @@ -112,12 +148,12 @@ namespace AZ if (AZ::BehaviorContext* behaviorContext = azrtti_cast(context)) { - behaviorContext->ConstantProperty("NoLodOverride", BehaviorConstant(RPI::Cullable::NoLodOverride)) + behaviorContext->ConstantProperty("DefaultLodOverride", BehaviorConstant(0)) ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) ->Attribute(AZ::Script::Attributes::Category, "render") ->Attribute(AZ::Script::Attributes::Module, "render"); - behaviorContext->ConstantProperty("DefaultLodType", BehaviorConstant(RPI::Cullable::DefaultLodType)) + behaviorContext->ConstantProperty("DefaultLodType", BehaviorConstant(RPI::Cullable::LodType::Default)) ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) ->Attribute(AZ::Script::Attributes::Category, "render") ->Attribute(AZ::Script::Attributes::Module, "render"); diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h index 1b479ed3eb..5f38088ca3 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h @@ -44,6 +44,9 @@ namespace AZ // Editor helper functions bool IsAssetSet(); + bool LodTypeIsScreenCoverage(); + bool LodTypeIsSpecificLOD(); + bool ShowLodConfig(); AZStd::vector> GetLodOverrideValues(); AZStd::vector> GetLodTypeValues(); @@ -52,10 +55,10 @@ namespace AZ bool m_excludeFromReflectionCubeMaps = false; bool m_useForwardPassIblSpecular = false; - RPI::Cullable::LodType m_lodType = RPI::Cullable::DefaultLodType; - RPI::Cullable::LodOverride m_lodOverride = RPI::Cullable::NoLodOverride; - float m_minimumScreenCoverage = RPI::Cullable::LodData::DefaultMinimumScreenCoverage; - float m_qualityDecayRate = RPI::Cullable::LodData::DefaultQualityDecayRate; + RPI::Cullable::LodType m_lodType = RPI::Cullable::LodType::Default; + RPI::Cullable::LodOverride m_lodOverride = aznumeric_cast(0); + float m_minimumScreenCoverage = 1.0f / 1080.0f; + float m_qualityDecayRate = 0.5f; }; class MeshComponentController final From 5a891c8cbdd769744a75c1118b6445199ce249fd Mon Sep 17 00:00:00 2001 From: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> Date: Wed, 11 Aug 2021 15:54:59 -0700 Subject: [PATCH 305/803] [redcode/crythread-2nd-pass] replaced remaining CrySpinLock/CryWriteLock usage with equivalent AZStd version Signed-off-by: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> --- Code/Legacy/CryCommon/Synchronization.h | 33 ++++-------------------- Code/Legacy/CryCommon/physinterface.h | 6 +++-- Code/Legacy/CrySystem/DebugCallStack.cpp | 7 ++--- 3 files changed, 13 insertions(+), 33 deletions(-) diff --git a/Code/Legacy/CryCommon/Synchronization.h b/Code/Legacy/CryCommon/Synchronization.h index 3bac215998..d38160c967 100644 --- a/Code/Legacy/CryCommon/Synchronization.h +++ b/Code/Legacy/CryCommon/Synchronization.h @@ -21,7 +21,7 @@ // //--------------------------------------------------------------------------- -#include "MultiThread.h" +#include namespace stl { @@ -51,43 +51,20 @@ namespace stl struct PSyncMultiThread { - PSyncMultiThread() - : _Semaphore(0) {} + PSyncMultiThread() {} void Lock() { - CryWriteLock(&_Semaphore); + m_lock.lock(); } void Unlock() { - CryReleaseWriteLock(&_Semaphore); - } - int IsLocked() const volatile - { - return _Semaphore; + m_lock.unlock(); } private: - volatile int _Semaphore; + AZStd::spin_mutex m_lock; }; - -#ifdef _DEBUG - - struct PSyncDebug - : public PSyncMultiThread - { - void Lock() - { - assert(!IsLocked()); - PSyncMultiThread::Lock(); - } - }; - -#else - - typedef PSyncNone PSyncDebug; - -#endif }; #endif // CRYINCLUDE_CRYCOMMON_SYNCHRONIZATION_H diff --git a/Code/Legacy/CryCommon/physinterface.h b/Code/Legacy/CryCommon/physinterface.h index 89b7318eaa..b1aaa5aef4 100644 --- a/Code/Legacy/CryCommon/physinterface.h +++ b/Code/Legacy/CryCommon/physinterface.h @@ -26,6 +26,8 @@ #include +#include + ////////////////////////////////////////////////////////////////////////// // Physics defines. ////////////////////////////////////////////////////////////////////////// @@ -2834,8 +2836,8 @@ struct IGeometry virtual int PointInsideStatus(const Vec3& pt) = 0; // for meshes, will create an auxiliary hashgrid for acceleration // IntersectLocked - the main function for geomtries. pdata1,pdata2,pparams can be 0 - defaults will be assumed. // returns a pointer to an internal thread-specific contact buffer, locked with the lock argument - virtual int IntersectLocked(IGeometry* pCollider, geom_world_data* pdata1, geom_world_data* pdata2, intersection_params* pparams, geom_contact*& pcontacts, WriteLockCond& lock) = 0; - virtual int IntersectLocked(IGeometry* pCollider, geom_world_data* pdata1, geom_world_data* pdata2, intersection_params* pparams, geom_contact*& pcontacts, WriteLockCond& lock, int iCaller) = 0; + virtual int IntersectLocked(IGeometry* pCollider, geom_world_data* pdata1, geom_world_data* pdata2, intersection_params* pparams, geom_contact*& pcontacts, AZStd::spin_mutex& lock) = 0; + virtual int IntersectLocked(IGeometry* pCollider, geom_world_data* pdata1, geom_world_data* pdata2, intersection_params* pparams, geom_contact*& pcontacts, AZStd::spin_mutex& lock, int iCaller) = 0; // Intersect - same as Intersect, but doesn't lock pcontacts virtual int Intersect(IGeometry* pCollider, geom_world_data* pdata1, geom_world_data* pdata2, intersection_params* pparams, geom_contact*& pcontacts) = 0; // FindClosestPoint - for non-convex meshes only does local search, doesn't guarantee global minimum diff --git a/Code/Legacy/CrySystem/DebugCallStack.cpp b/Code/Legacy/CrySystem/DebugCallStack.cpp index 576c3ee9fb..a043f16756 100644 --- a/Code/Legacy/CrySystem/DebugCallStack.cpp +++ b/Code/Legacy/CrySystem/DebugCallStack.cpp @@ -18,6 +18,7 @@ #include #include +#include #define VS_VERSION_INFO 1 #define IDD_CRITICAL_ERROR 101 @@ -152,13 +153,13 @@ void DebugCallStack::SetUserDialogEnable(const bool bUserDialogEnable) DWORD g_idDebugThreads[10]; const char* g_nameDebugThreads[10]; int g_nDebugThreads = 0; -volatile int g_lockThreadDumpList = 0; +AZStd::spin_mutex g_lockThreadDumpList = 0; void MarkThisThreadForDebugging(const char* name) { EBUS_EVENT(AZ::Debug::EventTraceDrillerSetupBus, SetThreadName, AZStd::this_thread::get_id(), name); - WriteLock lock(g_lockThreadDumpList); + AZStd::lock_guard lock(g_lockThreadDumpList); DWORD id = GetCurrentThreadId(); if (g_nDebugThreads == sizeof(g_idDebugThreads) / sizeof(g_idDebugThreads[0])) { @@ -178,7 +179,7 @@ void MarkThisThreadForDebugging(const char* name) void UnmarkThisThreadFromDebugging() { - WriteLock lock(g_lockThreadDumpList); + AZStd::lock_guard lock(g_lockThreadDumpList); DWORD id = GetCurrentThreadId(); for (int i = g_nDebugThreads - 1; i >= 0; i--) { From 337ea488b6539ced5d2e9bf2518b52c93b8fdf56 Mon Sep 17 00:00:00 2001 From: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> Date: Wed, 11 Aug 2021 15:57:49 -0700 Subject: [PATCH 306/803] [redcode/crythread-2nd-pass] replaced remaining CryInterlocked* usage with equivalent AZStd version Signed-off-by: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> --- Code/Legacy/CryCommon/IFunctorBase.h | 8 +++-- Code/Legacy/CryCommon/smartptr.h | 36 ++++++++----------- .../Code/Source/Engine/AudioRequests.cpp | 2 +- 3 files changed, 20 insertions(+), 26 deletions(-) diff --git a/Code/Legacy/CryCommon/IFunctorBase.h b/Code/Legacy/CryCommon/IFunctorBase.h index 2a8af50d33..c7d39ee923 100644 --- a/Code/Legacy/CryCommon/IFunctorBase.h +++ b/Code/Legacy/CryCommon/IFunctorBase.h @@ -15,6 +15,8 @@ #pragma once +#include + // Base class for functor storage. // Not intended for direct usage. class IFunctorBase @@ -27,19 +29,19 @@ public: void AddRef() { - CryInterlockedIncrement(&m_nReferences); + m_nReferences.fetch_add(1, AZStd::memory_order_acq_rel); } void Release() { - if (CryInterlockedDecrement(&m_nReferences) <= 0) + if (m_nReferences.fetch_sub(1, AZStd::memory_order_acq_rel) == 1) { delete this; } } protected: - volatile int m_nReferences; + AZStd::atomic_int m_nReferences; }; // Base Template for specialization. diff --git a/Code/Legacy/CryCommon/smartptr.h b/Code/Legacy/CryCommon/smartptr.h index 246e18d541..fd833b12e3 100644 --- a/Code/Legacy/CryCommon/smartptr.h +++ b/Code/Legacy/CryCommon/smartptr.h @@ -18,6 +18,9 @@ void CryFatalError(const char*, ...) PRINTF_PARAMS(1, 2); #if defined(APPLE) #include #endif + +#include + ////////////////////////////////////////////////////////////////// // SMART POINTER ////////////////////////////////////////////////////////////////// @@ -352,38 +355,32 @@ protected: class CMultiThreadRefCount { public: - CMultiThreadRefCount() - : m_cnt(0) {} + CMultiThreadRefCount() {} virtual ~CMultiThreadRefCount() {} inline int AddRef() { - return CryInterlockedIncrement(&m_cnt); + return m_count.fetch_add(1, AZStd::memory_order_acq_rel) + 1; // because we get the original value back } inline int Release() { - const int nCount = CryInterlockedDecrement(&m_cnt); - assert(nCount >= 0); + const int nCount = m_count.fetch_sub(1, AZStd::memory_order_acq_rel) - 1; // because we get the original value back + AZ_Assert(nCount >= 0, "Deleting Reference Counted Object Twice"); if (nCount == 0) { delete this; } - else if (nCount < 0) - { - assert(0); - CryFatalError("Deleting Reference Counted Object Twice"); - } return nCount; } - inline int GetRefCount() const { return m_cnt; } + inline int GetRefCount() const { return m_count.load(AZStd::memory_order_acquire); } protected: // Allows the memory for the object to be deallocated in the dynamic module where it was originally constructed, as it may use different memory manager (Debug/Release configurations) virtual void DeleteThis() { delete this; } private: - volatile int m_cnt; + AZStd::atomic_int m_count{ 0 }; }; // base class for interfaces implementing reference counting that needs to be thread-safe @@ -404,29 +401,24 @@ public: virtual void AddRef() { - CryInterlockedIncrement(&m_nRefCounter); + m_nRefCounter.fetch_add(1, AZStd::memory_order_acq_rel); } virtual void Release() { - const int nCount = CryInterlockedDecrement(&m_nRefCounter); - assert(nCount >= 0); + const int nCount = m_nRefCounter.fetch_sub(1, AZStd::memory_order_acq_rel) - 1; // because we get the original value back + AZ_Assert(nCount >= 0, "Deleting Reference Counted Object Twice"); if (nCount == 0) { delete this; } - else if (nCount < 0) - { - assert(0); - CryFatalError("Deleting Reference Counted Object Twice"); - } } - Counter NumRefs() const { return m_nRefCounter; } + Counter NumRefs() const { return m_nRefCounter.load(AZStd::memory_order_acquire); } protected: - volatile Counter m_nRefCounter; + AZStd::atomic m_nRefCounter{ 0 }; }; typedef _i_reference_target _i_reference_target_t; diff --git a/Gems/AudioSystem/Code/Source/Engine/AudioRequests.cpp b/Gems/AudioSystem/Code/Source/Engine/AudioRequests.cpp index 35da74b0de..0862483ab8 100644 --- a/Gems/AudioSystem/Code/Source/Engine/AudioRequests.cpp +++ b/Gems/AudioSystem/Code/Source/Engine/AudioRequests.cpp @@ -153,7 +153,7 @@ namespace Audio /////////////////////////////////////////////////////////////////////////////////////////////////// void SAudioRequestDataInternal::Release() { - const int nCount = CryInterlockedDecrement(&m_nRefCounter); + const int nCount = m_nRefCounter.fetch_sub(1, AZStd::memory_order_acq_rel) - 1; // because we get the original value back AZ_Assert(nCount >= 0, "AudioRequests Release - Decremented reference counter too many times!"); if (nCount == 0) From dba26cc2357b001da4a890ca211a78db3afce335 Mon Sep 17 00:00:00 2001 From: Chris Burel Date: Wed, 11 Aug 2021 16:07:46 -0700 Subject: [PATCH 307/803] Fix code that trips -Wsign-compare (#3046) Signed-off-by: Chris Burel --- .../Code/Editor/Animation/UiAnimViewNewSequenceDialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/LyShine/Code/Editor/Animation/UiAnimViewNewSequenceDialog.cpp b/Gems/LyShine/Code/Editor/Animation/UiAnimViewNewSequenceDialog.cpp index ac824bfc4d..3dd49574fd 100644 --- a/Gems/LyShine/Code/Editor/Animation/UiAnimViewNewSequenceDialog.cpp +++ b/Gems/LyShine/Code/Editor/Animation/UiAnimViewNewSequenceDialog.cpp @@ -43,7 +43,7 @@ void CUiAVNewSequenceDialog::OnOK() return; } - for (int k = 0; k < CUiAnimViewSequenceManager::GetSequenceManager()->GetCount(); ++k) + for (unsigned int k = 0; k < CUiAnimViewSequenceManager::GetSequenceManager()->GetCount(); ++k) { CUiAnimViewSequence* pSequence = CUiAnimViewSequenceManager::GetSequenceManager()->GetSequenceByIndex(k); QString fullname = pSequence->GetName(); From 094d06f1e370c04fe0edd0a8abea190f71994253 Mon Sep 17 00:00:00 2001 From: Chris Burel Date: Wed, 11 Aug 2021 16:08:05 -0700 Subject: [PATCH 308/803] Update EMotionFX layouts to deal with changed QObject names (#3045) Commit 1837d05169 changed some of the EMotionFX editor's QObject names to match their new class member names. Unfortunately this broke the EMotionFX layouts. This recreates the good layouts to contain the new QObject names. Signed-off-by: Chris Burel --- .../Assets/Editor/Layouts/AnimGraph.layout | Bin 6480 -> 7200 bytes .../Editor/Layouts/SimulatedObjects.layout | Bin 7203 -> 6901 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/Gems/EMotionFX/Assets/Editor/Layouts/AnimGraph.layout b/Gems/EMotionFX/Assets/Editor/Layouts/AnimGraph.layout index 85fa2f2253311fb9b538d0953c5951658f46a683..e85d6054a3e54df86030125994f050171e52f622 100644 GIT binary patch literal 7200 zcmc&&Ux-vy82@J1RWV4TAPb8tSZD~{bN|epD^YD~F8q?~xIc5abQ$-r z#FKHU8_%6MAKsaqe;wnAW7@lZ^nT{i?kT~|RO7Bu;?HhIpOfFO*Yf53#aZKqrigE* zPVEd5Gxiv~Wf&OE zN$Sh_e8;x6-m2DX*5+3$wbq2Zq3zuB#|}sPBj#sDuV@aBYtZfKX#CN2XRlCCBcJcd ztI^lYH}8M94r{wse)rYY((tb0&^E^lY{&7Pg0fvl)*f5_4e`ynamhc^>Ccm^Kh^TC zAD`ie@-9xUzSKGHlM^2&_*)@SApLatvr`;r^rF7Q^)c(YYHhTBNHXNXwN>akFt|_0!w3PjeU!^k zIbjCzu(LW|v7W6~4oQ|gATJ69#|=G(MCfF|!}dm{Rvfl=RBEG@rl}MQUMH1rdyZ3Z z1B8R^N(MYc>&1j*%Y);qLf*B*07;?zEb3&uZjMy2T4Wdxj$c4x6r3>3E6IWftQYmB zwY6L;k5!ryub>N`7eVMLN99o;@?PH0ATI`M)p4uXEI0N`mOQwg3Y79)aAAAF0`stb z1$R<+zmMG|YLndL-QVbayb$R>A~LXQn!Ccj8#t_$k_^i(Daw#+6D7Xb;)#P_L0k!N z4)N3$H{M5bzP!v`8)t8ly;6~JsY^?$IM!qWSCcZT?hPa&T1CZf&D>((@^3Zb?~Ql6~3$1^jqM9O60+f4^Cho6-k&vRvwc< z%&)?=MPQVrA^Tz0LAZ8IBX5umc((%*D6t7gQ`RP2?~?;S%v}da`>ScLpHw6p+R#6F zuuQgj&Wlftj-j{Ebpthv`T-i??n097Te&~t+SSf8P7K8{jK3G73f1Z*wIv-o z+z#6jlQT(;6++bm1sIK=uLGBaFbf%WxhJ6HZ=D)Hp2{_YV6O$2R1p-DxTo}(rVf%b(l<}J2OUCrWdsg9Eje#&@|LUDZ%v6wGdf9u*yh; znSFnvhx!4{WWMO~lP)^wNtOzlN?&#wH&6i92_vev##!*B4PUy52>2exajjYk!*Z<7 zx>4ejshqVJ7Ie>?fjWR5iZF$Xz>*)q(W7{9t-UJsykc`9=6c3}XUH1g^>OKVTbDy9 zaT=X@{ZX<$rnR~;pZ87y_Xl*{dhb2vFf))Vqo)_7B(1mOy;`>#g_u}82?L&v&Cn^9 zZkgMQN_UGY1;iyoK>N89@tKrSHWp{f{6%5Oukh;q20uFMl-0S3dwoV6>I*E9`kbtk zTw%DzFnqY^J2*y_5=YKw!Gt2C3 zq6bkyFk)i7c+n^u$VtJAU=H!%E#%-q5QJPrQ3wiNL=tt)`hC@1o9WC>7;%!Wrn;)T z|N0-_|EQYTJ-(+j{M_Wey{jU3Nz{fHnwC|t9NV$Q8a#A*ITL@tuzdNOkNEuRwr|h< z`I^Y%6Qh?tKY1m$|MJ!|n(i0tG^x3yosXd(HFP9GGyKhHzW-zoj0^a8leguq=RY>` z^cX)I`m3;q&FE*|3-lxXDq2L5(}U4ZBzm^TmOdn%S${3N=@9KT>!YK~Iivk!V)3i5M^@rbQfkau&sOWRjpLFc z4z8_2*C7^4c|kt*$4;Z<9l&9DM#sZwb+OfGz9NbIH2%H)@!%JHAKeK(Cy-Qd*wv`j z%Jo_6>2g!j!$G;O=PTPsxeS#PrVtNteb`e$R-}l7;};4Ar{IKPUP&4_ATJtCYrI@9 z&sCa|R$ize^pvCWp6}$nyq`im?5)-+)-%=0aY+*g)JcSc8v=*W3!M~j7_L`qRNT99#u)CBPWstt~EBpmDu?#?v)dkI0Ksk(xB5B~{$(vWVG|%<88_ zjPszd+AeM!3KGcKmON!Zvz)>Yip>}w0MqZ#A#LEqnx;9N5VObdcn)7KQ1}YX*+dl{ zOBmpSDMh$oA7D;HR4g!06SktiiLM*hKblzY!)#w)9BDkk2+Yd)c%ksfdN1_-0ppiY z==u#rw}1qKnV6xk%TEklr@6+jLd^$ z<_ehb*OYFZeo~QaXhZ+xfiltNm=~WKy^YRL(+$w%{s7YePoE~yUeEmz)~RB5y)6N@mh2IF=Cw7Pam118hx_KeY$=_MnS z-1`@r2AU`(m>#+oBI~o?L(pNJQh4|sJ;aMs$sFq~I_OE33Ytn^wi~yh0Iu(&>(*c6 zEO^p}FI_|gd=KNeS0!B*$=$&JL0AR2dFTo=kq=nT#ye_8L$o~X?;LOIel{$Iqtkv%rr92@Q)12im>B)F|<6FZ#o(i^&6>o7R< zSdl>4w?YG6Z2iM%o$UM17tJE(7YJ^?i|p`X!YNp!89q1vJ;iBELY?{e0IRy`f;JM6vX4+v1p Eza4RxFaQ7m diff --git a/Gems/EMotionFX/Assets/Editor/Layouts/SimulatedObjects.layout b/Gems/EMotionFX/Assets/Editor/Layouts/SimulatedObjects.layout index 9deac32edb492ea4d405a1bceca49df4954e0511..a7879584a9601f005f1c5aeba8d04f3320c8c66c 100644 GIT binary patch literal 6901 zcmc&&U2IfE6h7PSpAdc&H5!R7k(g=>xxah&qERbiEh%i%+CYN}h26lGcDJ^>k?^32 zL?Z^GQ9<+teK5Xgf>G2&A9ye^A;cIHCHSJe7=L0!eL@iYzS%o_?=A~&Y3a^pX71cO z^PO|PIcI)$_1eL{?&0*%qZ=Q0TBV%2OWP8rk+2NQlnY3F`!>FxeMZDc$1*2kVSDrF zzFxMwkePx?)lr;R7FLfx*dp?s?u>CSy5;ZTtKq{0dEm?{B~O7z3a!uS{$onM(edS1 zQ9O~}!)$B3{*U(bQ%~Iw;)V9;?~DH~%h7G!Uu0O}e9%+YPxGPi`**)^>L1|fq{r8` zHJ-Ld+ioOb}GAW`t1Ev{e43{z3VK~cMRKfZQHXPNA@iGkoa9eJ#pMU z66OD`Wp5~XKkp6sp}eD|Wyhoa4(>lt#ouBnd*Rn74!y^IS}*FGp2+5V`Vs@#d?q`Y zSf9&h3Qx(L^I#jE>6>2CNqLsJF;Wh zVj-VMmx^P#e0EZru|AlV;o7F$qbq*(WmZ1RgH1^)E8_{YpB=R@+$=56LFU%D5DyC^?jQnZi>^GO9I& zdIx$W>i#V8#SoN0Yuhank7HXcApbH`WD}?^eh!e^7emecW#stxGeBO?5j}xJ&w_PllvNdSxA;sW!n)z?*C0DE3ZYawh`6|AlJDC_P4%n5|};u91pmM+&ghT`F|2K=um zBbcJC$~*a-gO_Gyvc@mzGi1z0NvW8VKqASIQAGxbyA5XCf)}4xn{h{#87@GQV8>UW zu7Y(mGZ-8@h(e{=H6jc&8!~-_fTk^+QA)f|xp)osRIyJ1-zE_51rWId2#8gY=UFfjvvwkBKfM9|0A1kNXr-tVXpMi10Z(uw6GvBj zm!&+*MQN(h2F7u`kCx5xLl{!w5Z=}LDPC^C%QY3Jt>axDW|!_tr5F*mQjRovoNIV! zY!dZ7#JE@~dI%z4VNgL=;n*ClXpX%K9p1(GuE1A1mjLiLyl4%TVkBVQXhB~j1{ftP zT}Ne5O-Tt8F@jYz3-Z(O+)+GjMSDHIW-vinJeMbE6INSJ;-yCPs`Ypx7+=6N1``OG zZMQ>iiApfh+S!Yx&5%sab5LlGwBKv4-# z*@$tiF9G$7h^RVKp%%5-w3)6-zoL&Y^qs(`LKDeyW5)Hv0~na&YPPvrg)`T};Mp88 zF7^kA<;xm}TG>#PQ`DFeQ_W%fBH(?ZP*Geh2jPON)+&(Iz7TdyL?z~BwXBtgWrM7k zMsWOJ-^+zX>@Vo>O;m?_8)9)l1sOw(D`wSn-4C=i8WC>a@){ZtgH#p&%d55!N3AqG zYj7_zRSQchXo|0Zio6D2;<5Gg%@2d@hDUTz~}%GoLe z0gETJ*!%!Is8r1G9}S#Yq?0w*3kDQ79@f>{4UZw*w+-b?T%&Q`K{Pt$C?wJ9D2sv7 z)P~0NkFa$PZNPaMxpG{lhDfd00c4jtL&X{o{>$yV3U-$&!-8#+#Z0m~NfwemM_&6J z2t0rn)3>$GF%md?k!x*@@5jpxp{+AmeE_5qH}q&4K%<_W`c%8{2iSQAou+SRxMfwY zCBUgSr?GK3;K|U=#uoHT?pA?)v6I1rt~TSLo~`<()cz;F^KdZ}TPqhO;MAK_+8RF= z+B)+&jUR)kNK%1c&rW@B>v$S=<}qSsb_Ulr;2cG+^<8eKQ9I{&-+@LsQ)VT@;>*vJ_?`1A*(1~gG^h#inuQ_5x^lHwW&8BsF4XWJT0_!-t Y4c;%&vwCCXjrZX^v&L2S3#q1|L}Cc7woP`n~y zQP8T0ulCtDUwrVvrxFl^A{E3pL46Q?6Kmr4otfE7I*FU?W(uBgX3osc`Tqa^{>wQh zC#M&t#?QXbn-?-hHe+apCY$?cL`k6cjk6Eg|EDP1R;d)K#mtGq z+P?hJFDG+Ti}}eJLw7CB)NRvr49kjBk$?u7t~E-vYG%P}tj8(7MW4@unRT*;k<%?b zn{(|r6$yD5ua+vA{92)YF;3|%8a90%Y&Yw;hHLAlW#nR2B;;YX?p5@+D@DS(c+<0X_gBOub7!Vzv3-7VswQn5(R?1cYKe*7N7n>PjV2pn|vDj8<(f#tawt9nlz+@YgN`U zYD!T(t>eCmFEWvThPa{$u0R`lT_lyl_NRvaOTWlEP;LBKKpwseYF_b?Q$O^NtceA! zZ6J@_1LVW#=b`&Pkquxul9Md{$c804kPp8AeZhMAKA?ZPKb>{p>A-Wqg$8s}93UT> zgezZzz8?emC3NgJM_$JB)tlUTrf=ecmUOswzy=>kTDZiN`+4Xi6lc-6d5pK0xG93+&GxOos!kh)xi{$(WY z1x3%8jN!K#P*wz0{HBKA>PYt*h+G8%a#iFl^fzQw?vHXL?PoL~9-s>X8&5gv1X@$q zG4pvsuyJ;GbQvnLY+Q9UTf;ogckyI${vxKdI7D=%-tpr)ajX@z5z*zqy9`$<#f&hO za-_+juMwe%QQS`v<5r~@A;^4%K?QAvV{*2l8L}n$8Rowd#LDmy0M_y1$F@?;1k{b> z2e_lWBEcwG>AE5d$|X%WqJS#uf&5uS?g~cBcs`9^i*S&KvG1U>sJ3+CPBSJ|J+24y zYj9)WK*$_oE;gwI8?7B&F15punMAI1NE}5;Nc^hA;S!XD)K!eX=q94K=o|+P4VY8{ zMNN#n4&&1A0ri^>Q4y|CMQxBaGgKK@j1i{36~@%JP~<_FxJj0KGj0wMz{IR5Z?jsp zJ(pzioI_U)JSKie=gZ3!(hjJxp0b>x%1TT(hr@RQ@k?LG!378luBufatJ_H=t12gD zTAr3AIlhPF_^)qwON+#x;PSgps~_))#d(!vOfgo>E_Xc%v}Z#^xGVV~9v}v-EB_zv zT0$&UX}H(mTBNHdlvL1^It~@jsQI`YROWIAMahifp~w6n^JP-vGd+=#4Ln`u)yHXdclO^!oz#_zJc2iuG^XlCe~=|caV*i zpM?YtkTJF0hA`aw7B*tj2AucNTia!7h?eGV`jXm1C3;W(-PTn}^@3uy4BZ2cS`gU7WSMYMFZEGLZ2SBPVg@fQek9(Az;jZ?`Pq6bZ ze6)8v+e=pKSOT0VpC&2@z#DBldn@QWu2z9*i5tNnyq&`!%GU6tH2epC{|z7YV{7Z6 z1e_?J($>_qwypj9G<6N4I+{xSC_BS*8&4e1~%wzTLyA3tzJxguSgjV28c^SJnP%Rd4cl+@_PNe*rXS By>S2l From 0f347c11bff9b1978a77c6f10a860f5e314d6ad7 Mon Sep 17 00:00:00 2001 From: SJ Date: Wed, 11 Aug 2021 16:08:21 -0700 Subject: [PATCH 309/803] Add header file needed for no unity builds (#3047) Signed-off-by: amzn-sj --- .../Platform/Mac/AzFramework/Process/ProcessWatcher_Mac.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Code/Framework/AzFramework/Platform/Mac/AzFramework/Process/ProcessWatcher_Mac.cpp b/Code/Framework/AzFramework/Platform/Mac/AzFramework/Process/ProcessWatcher_Mac.cpp index 148b1cbdfe..4099443913 100644 --- a/Code/Framework/AzFramework/Platform/Mac/AzFramework/Process/ProcessWatcher_Mac.cpp +++ b/Code/Framework/AzFramework/Platform/Mac/AzFramework/Process/ProcessWatcher_Mac.cpp @@ -15,6 +15,7 @@ #include #include +#include #include #include From c173dee2bcf8c348babdb93b1ea9368b0027050b Mon Sep 17 00:00:00 2001 From: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> Date: Wed, 11 Aug 2021 16:38:54 -0700 Subject: [PATCH 310/803] [redcode/crythread-2nd-pass] removed MultiThread.h along with external CryInterlocked* definitions Signed-off-by: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> --- Code/Legacy/CryCommon/MultiThread.h | 277 -------------------- Code/Legacy/CryCommon/WinBase.cpp | 85 +----- Code/Legacy/CryCommon/crycommon_files.cmake | 1 - Code/Legacy/CryCommon/platform.h | 4 - Code/Legacy/CryCommon/platform_impl.cpp | 52 ---- Code/Legacy/CrySystem/Log.h | 1 - 6 files changed, 1 insertion(+), 419 deletions(-) delete mode 100644 Code/Legacy/CryCommon/MultiThread.h diff --git a/Code/Legacy/CryCommon/MultiThread.h b/Code/Legacy/CryCommon/MultiThread.h deleted file mode 100644 index c3aa892d14..0000000000 --- a/Code/Legacy/CryCommon/MultiThread.h +++ /dev/null @@ -1,277 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - -#pragma once - -#if defined(APPLE) || defined(LINUX) -#include -#endif - -#include - -#include "CryAssert.h" - -// Section dictionary -#if defined(AZ_RESTRICTED_PLATFORM) -#define MULTITHREAD_H_SECTION_TRAITS 1 -#define MULTITHREAD_H_SECTION_DEFINE_CRYINTERLOCKEXCHANGE 2 -#define MULTITHREAD_H_SECTION_IMPLEMENT_CRYSPINLOCK 3 -#define MULTITHREAD_H_SECTION_IMPLEMENT_CRYINTERLOCKEDADD 4 -#define MULTITHREAD_H_SECTION_IMPLEMENT_CRYINTERLOCKEDADDSIZE 5 -#define MULTITHREAD_H_SECTION_CRYINTERLOCKEDFLUSHSLIST_PT1 6 -#define MULTITHREAD_H_SECTION_CRYINTERLOCKEDFLUSHSLIST_PT2 7 -#define MULTITHREAD_H_SECTION_IMPLEMENT_CRYINTERLOCKEDCOMPAREEXCHANGE64 8 -#endif - -#define WRITE_LOCK_VAL (1 << 16) - -// Traits -#if defined(AZ_RESTRICTED_PLATFORM) - #define AZ_RESTRICTED_SECTION MULTITHREAD_H_SECTION_TRAITS - #include AZ_RESTRICTED_FILE(MultiThread_h) -#endif - -void CrySpinLock(volatile int* pLock, int checkVal, int setVal); -void CryReleaseSpinLock (volatile int*, int); - -LONG CryInterlockedIncrement(int volatile* lpAddend); -LONG CryInterlockedDecrement(int volatile* lpAddend); -LONG CryInterlockedOr(LONG volatile* Destination, LONG Value); -LONG CryInterlockedExchangeAdd(LONG volatile* lpAddend, LONG Value); -LONG CryInterlockedCompareExchange(LONG volatile* dst, LONG exchange, LONG comperand); -void* CryInterlockedCompareExchangePointer(void* volatile* dst, void* exchange, void* comperand); -void* CryInterlockedExchangePointer (void* volatile* dst, void* exchange); - -#if defined(AZ_RESTRICTED_PLATFORM) - #define AZ_RESTRICTED_SECTION MULTITHREAD_H_SECTION_DEFINE_CRYINTERLOCKEXCHANGE - #include AZ_RESTRICTED_FILE(MultiThread_h) -#endif - -ILINE void CrySpinLock(volatile int* pLock, int checkVal, int setVal) -{ -#ifdef _CPU_X86 -# ifdef __GNUC__ - int val; - __asm__ __volatile__ ( - "0: mov %[checkVal], %%eax\n" - " lock cmpxchg %[setVal], (%[pLock])\n" - " jnz 0b" - : "=m" (*pLock) - : [pLock] "r" (pLock), "m" (*pLock), - [checkVal] "m" (checkVal), - [setVal] "r" (setVal) - : "eax", "cc", "memory" - ); -# else //!__GNUC__ - __asm - { - mov edx, setVal - mov ecx, pLock -Spin: - // Trick from Intel Optimizations guide -#ifdef _CPU_SSE - pause -#endif - mov eax, checkVal - lock cmpxchg [ecx], edx - jnz Spin - } -# endif //!__GNUC__ -#else // !_CPU_X86 -# if defined(AZ_RESTRICTED_PLATFORM) - #define AZ_RESTRICTED_SECTION MULTITHREAD_H_SECTION_IMPLEMENT_CRYSPINLOCK - #include AZ_RESTRICTED_FILE(MultiThread_h) -# endif -# if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED) -# undef AZ_RESTRICTED_SECTION_IMPLEMENTED -# elif defined(APPLE) || defined(LINUX) - // register int val; - // __asm__ __volatile__ ( - // "0: mov %[checkVal], %%eax\n" - // " lock cmpxchg %[setVal], (%[pLock])\n" - // " jnz 0b" - // : "=m" (*pLock) - // : [pLock] "r" (pLock), "m" (*pLock), - // [checkVal] "m" (checkVal), - // [setVal] "r" (setVal) - // : "eax", "cc", "memory" - // ); - //while(CryInterlockedCompareExchange((volatile long*)pLock,setVal,checkVal)!=checkVal) ; - uint loops = 0; - while (__sync_val_compare_and_swap((volatile int32_t*)pLock, (int32_t)checkVal, (int32_t)setVal) != checkVal) - { -# if !defined (ANDROID) && !defined(IOS) - _mm_pause(); -# endif - - if (!(++loops & 0x7F)) - { - usleep(1); // give threads with other prio chance to run - } - else if (!(loops & 0x3F)) - { - sched_yield(); // give threads with same prio chance to run - } - } -# else - // NOTE: The code below will fail on 64bit architectures! - while (_InterlockedCompareExchange((volatile LONG*)pLock, setVal, checkVal) != checkVal) - { - _mm_pause(); - } -# endif -#endif -} - -ILINE void CryReleaseSpinLock(volatile int* pLock, int setVal) -{ - *pLock = setVal; -} - -////////////////////////////////////////////////////////////////////////// -ILINE void CryInterlockedAdd(volatile int* pVal, int iAdd) -{ -#ifdef _CPU_X86 -# ifdef __GNUC__ - __asm__ __volatile__ ( - " lock add %[iAdd], (%[pVal])\n" - : "=m" (*pVal) - : [pVal] "r" (pVal), "m" (*pVal), [iAdd] "r" (iAdd) - ); -# else - __asm - { - mov edx, pVal - mov eax, iAdd - lock add [edx], eax - } -# endif -#else - // NOTE: The code below will fail on 64bit architectures! -#if defined(_WIN64) - _InterlockedExchangeAdd((volatile LONG*)pVal, iAdd); -#define AZ_RESTRICTED_SECTION_IMPLEMENTED -#elif defined(AZ_RESTRICTED_PLATFORM) - #define AZ_RESTRICTED_SECTION MULTITHREAD_H_SECTION_IMPLEMENT_CRYINTERLOCKEDADD - #include AZ_RESTRICTED_FILE(MultiThread_h) -#endif -#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED) -#undef AZ_RESTRICTED_SECTION_IMPLEMENTED -#elif defined(APPLE) || defined(LINUX) - CryInterlockedExchangeAdd((volatile LONG*)pVal, iAdd); -#elif defined(APPLE) - OSAtomicAdd32(iAdd, (volatile LONG*)pVal); -#else - InterlockedExchangeAdd((volatile LONG*)pVal, iAdd); -#endif - -#endif -} - -ILINE void CryInterlockedAddSize(volatile size_t* pVal, ptrdiff_t iAdd) -{ -#if defined(PLATFORM_64BIT) -#if defined(_WIN64) - _InterlockedExchangeAdd64((volatile __int64*)pVal, iAdd); -#define AZ_RESTRICTED_SECTION_IMPLEMENTED -#elif defined(AZ_RESTRICTED_PLATFORM) - #define AZ_RESTRICTED_SECTION MULTITHREAD_H_SECTION_IMPLEMENT_CRYINTERLOCKEDADDSIZE - #include AZ_RESTRICTED_FILE(MultiThread_h) -#endif -#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED) -#undef AZ_RESTRICTED_SECTION_IMPLEMENTED -#elif defined(WIN32) - InterlockedExchangeAdd64((volatile LONG64*)pVal, iAdd); -#elif defined(APPLE) || defined(LINUX) - (void)__sync_fetch_and_add((int64_t*)pVal, (int64_t)iAdd); -#else - int64 x, n; - do - { - x = (int64) * pVal; - n = x + iAdd; - } - while (CryInterlockedCompareExchange64((volatile int64*)pVal, n, x) != x); -#endif -#else - CryInterlockedAdd((volatile int*)pVal, (int)iAdd); -#endif -} - - - -////////////////////////////////////////////////////////////////////////// -ILINE void CryWriteLock(volatile int* rw) -{ - CrySpinLock(rw, 0, WRITE_LOCK_VAL); -} - -ILINE void CryReleaseWriteLock(volatile int* rw) -{ - CryInterlockedAdd(rw, -WRITE_LOCK_VAL); -} - -////////////////////////////////////////////////////////////////////////// -struct WriteLock -{ - ILINE WriteLock(volatile int& rw) { CryWriteLock(&rw); prw = &rw; } - ~WriteLock() { CryReleaseWriteLock(prw); } -private: - volatile int* prw; -}; - -////////////////////////////////////////////////////////////////////////// -struct WriteLockCond -{ - ILINE WriteLockCond(volatile int& rw, int bActive = 1) - { - if (bActive) - { - CrySpinLock(&rw, 0, iActive = WRITE_LOCK_VAL); - } - else - { - iActive = 0; - } - prw = &rw; - } - ILINE WriteLockCond() { prw = &(iActive = 0); } - ~WriteLockCond() - { - CryInterlockedAdd(prw, -iActive); - } - void SetActive(int bActive = 1) { iActive = -bActive & WRITE_LOCK_VAL; } - void Release() { CryInterlockedAdd(prw, -iActive); } - volatile int* prw; - int iActive; -}; - - -#if defined(LINUX) || defined(APPLE) -ILINE int64 CryInterlockedCompareExchange64(volatile int64* addr, int64 exchange, int64 comperand) -{ - return __sync_val_compare_and_swap(addr, comperand, exchange); - // This is OK, because long is signed int64 on Linux x86_64 - //return CryInterlockedCompareExchange((volatile long*)addr, (long)exchange, (long)comperand); -} -#else -ILINE int64 CryInterlockedCompareExchange64(volatile int64* addr, int64 exchange, int64 compare) -{ - // forward to system call -#if defined(AZ_RESTRICTED_PLATFORM) - #define AZ_RESTRICTED_SECTION MULTITHREAD_H_SECTION_IMPLEMENT_CRYINTERLOCKEDCOMPAREEXCHANGE64 - #include AZ_RESTRICTED_FILE(MultiThread_h) -#endif -#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED) -#undef AZ_RESTRICTED_SECTION_IMPLEMENTED -#else - return _InterlockedCompareExchange64((volatile int64*)addr, exchange, compare); -#endif -} -#endif diff --git a/Code/Legacy/CryCommon/WinBase.cpp b/Code/Legacy/CryCommon/WinBase.cpp index 15146fbac1..a11787fef0 100644 --- a/Code/Legacy/CryCommon/WinBase.cpp +++ b/Code/Legacy/CryCommon/WinBase.cpp @@ -1292,90 +1292,7 @@ short CryGetAsyncKeyState(int vKey) return 0; } -#if defined(LINUX) || defined(APPLE) || defined(DEFINE_CRY_INTERLOCKED_INCREMENT) -//[K01]: http://www.memoryhole.net/kyle/2007/05/atomic_incrementing.html -//http://forums.devx.com/archive/index.php/t-160558.html -////////////////////////////////////////////////////////////////////////// -DLL_EXPORT LONG CryInterlockedIncrement(LONG volatile* lpAddend) -{ - /*int r; - __asm__ __volatile__ ( - "lock ; xaddl %0, (%1) \n\t" - : "=r" (r) - : "r" (lpAddend), "0" (1) - : "memory" - ); - return (LONG) (r + 1); */// add, since we get the original value back. - return __sync_fetch_and_add(lpAddend, 1) + 1; -} - -////////////////////////////////////////////////////////////////////////// -DLL_EXPORT LONG CryInterlockedDecrement(LONG volatile* lpAddend) -{ - /*int r; - __asm__ __volatile__ ( - "lock ; xaddl %0, (%1) \n\t" - : "=r" (r) - : "r" (lpAddend), "0" (-1) - : "memory" - ); - return (LONG) (r - 1); */// subtract, since we get the original value back. - return __sync_fetch_and_sub(lpAddend, 1) - 1; -} - -////////////////////////////////////////////////////////////////////////// -DLL_EXPORT LONG CryInterlockedExchangeAdd(LONG volatile* lpAddend, LONG Value) -{ - /* LONG r; - __asm__ __volatile__ ( - #if defined(LINUX64) || defined(APPLE) // long is 64 bits on amd64. - "lock ; xaddq %0, (%1) \n\t" - #else - "lock ; xaddl %0, (%1) \n\t" - #endif - : "=r" (r) - : "r" (lpAddend), "0" (Value) - : "memory" - ); - return r;*/ - return __sync_fetch_and_add(lpAddend, Value); -} - -DLL_EXPORT LONG CryInterlockedOr(LONG volatile* Destination, LONG Value) -{ - return __sync_fetch_and_or(Destination, Value); -} - -DLL_EXPORT LONG CryInterlockedCompareExchange(LONG volatile* dst, LONG exchange, LONG comperand) -{ - return __sync_val_compare_and_swap(dst, comperand, exchange); - /*LONG r; - __asm__ __volatile__ ( - #if defined(LINUX64) || defined(APPLE) // long is 64 bits on amd64. - "lock ; cmpxchgq %2, (%1) \n\t" - #else - "lock ; cmpxchgl %2, (%1) \n\t" - #endif - : "=a" (r) - : "r" (dst), "r" (exchange), "0" (comperand) - : "memory" - ); - return r;*/ -} - - -DLL_EXPORT void* CryInterlockedCompareExchangePointer(void* volatile* dst, void* exchange, void* comperand) -{ - return __sync_val_compare_and_swap(dst, comperand, exchange); - //return (void*)CryInterlockedCompareExchange((long volatile*)dst, (long)exchange, (long)comperand); -} - -DLL_EXPORT void* CryInterlockedExchangePointer(void* volatile* dst, void* exchange) -{ - __sync_synchronize(); - return __sync_lock_test_and_set(dst, exchange); - //return (void*)CryInterlockedCompareExchange((long volatile*)dst, (long)exchange, (long)comperand); -} +#if defined(LINUX) || defined(APPLE) threadID CryGetCurrentThreadId() { diff --git a/Code/Legacy/CryCommon/crycommon_files.cmake b/Code/Legacy/CryCommon/crycommon_files.cmake index d9d4493632..4c1440c67d 100644 --- a/Code/Legacy/CryCommon/crycommon_files.cmake +++ b/Code/Legacy/CryCommon/crycommon_files.cmake @@ -96,7 +96,6 @@ set(FILES LegacyAllocator.h MetaUtils.h MiniQueue.h - MultiThread.h MultiThread_Containers.h NullAudioSystem.h PNoise3.h diff --git a/Code/Legacy/CryCommon/platform.h b/Code/Legacy/CryCommon/platform.h index 9f6e8b212d..842325af9f 100644 --- a/Code/Legacy/CryCommon/platform.h +++ b/Code/Legacy/CryCommon/platform.h @@ -730,10 +730,6 @@ enum ETriState typedef int socklen_t; #endif - -// Include MultiThreading support. -#include "MultiThread.h" - // In RELEASE disable printf and fprintf #if defined(_RELEASE) && !defined(RELEASE_LOGGING) #if defined(AZ_RESTRICTED_PLATFORM) diff --git a/Code/Legacy/CryCommon/platform_impl.cpp b/Code/Legacy/CryCommon/platform_impl.cpp index e16b18bc06..becd88c0b5 100644 --- a/Code/Legacy/CryCommon/platform_impl.cpp +++ b/Code/Legacy/CryCommon/platform_impl.cpp @@ -308,58 +308,6 @@ short CryGetAsyncKeyState([[maybe_unused]] int vKey) #endif } -////////////////////////////////////////////////////////////////////////// -LONG CryInterlockedIncrement(int volatile* lpAddend) -{ - return InterlockedIncrement((volatile LONG*)lpAddend); -} - -////////////////////////////////////////////////////////////////////////// -LONG CryInterlockedDecrement(int volatile* lpAddend) -{ - return InterlockedDecrement((volatile LONG*)lpAddend); -} - -////////////////////////////////////////////////////////////////////////// -LONG CryInterlockedExchangeAdd(LONG volatile* lpAddend, LONG Value) -{ - return InterlockedExchangeAdd(lpAddend, Value); -} - -LONG CryInterlockedOr(LONG volatile* Destination, LONG Value) -{ - return InterlockedOr(Destination, Value); -} - -LONG CryInterlockedCompareExchange(LONG volatile* dst, LONG exchange, LONG comperand) -{ - return InterlockedCompareExchange(dst, exchange, comperand); -} - -void* CryInterlockedCompareExchangePointer(void* volatile* dst, void* exchange, void* comperand) -{ - return InterlockedCompareExchangePointer(dst, exchange, comperand); -} - -void* CryInterlockedExchangePointer(void* volatile* dst, void* exchange) -{ - return InterlockedExchangePointer(dst, exchange); -} - -void CryInterlockedAdd(volatile size_t* pVal, ptrdiff_t iAdd) -{ -#if defined (PLATFORM_64BIT) -#if !defined(NDEBUG) - size_t v = (size_t) -#endif - InterlockedAdd64((volatile int64*)pVal, iAdd); -#else - size_t v = (size_t)CryInterlockedExchangeAdd((volatile long*)pVal, (long)iAdd); - v += iAdd; -#endif - assert((iAdd == 0) || (iAdd < 0 && v < v - (size_t)iAdd) || (iAdd > 0 && v > v - (size_t)iAdd)); -} - ////////////////////////////////////////////////////////////////////////// uint32 CryGetFileAttributes(const char* lpFileName) { diff --git a/Code/Legacy/CrySystem/Log.h b/Code/Legacy/CrySystem/Log.h index 447186e613..085e05e714 100644 --- a/Code/Legacy/CrySystem/Log.h +++ b/Code/Legacy/CrySystem/Log.h @@ -10,7 +10,6 @@ #pragma once #include -#include #include ////////////////////////////////////////////////////////////////////// From c28026a02244666f2a35c19038272d6613f7a9cf Mon Sep 17 00:00:00 2001 From: Chris Burel Date: Wed, 11 Aug 2021 10:35:13 -0700 Subject: [PATCH 311/803] [EMotionFX] Avoid using invalid Aabbs Signed-off-by: Chris Burel --- Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.cpp index 13927f3fd3..5a8fcda907 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.cpp @@ -621,7 +621,7 @@ namespace EMotionFX } // Expand the bounding volume by a tolerance area in case set. - if (!AZ::IsClose(m_boundsExpandBy, 0.0f)) + if (!AZ::IsClose(m_boundsExpandBy, 0.0f) && m_aabb.IsValid()) { const AZ::Vector3 center = m_aabb.GetCenter(); const AZ::Vector3 halfExtents = m_aabb.GetExtents() * 0.5f; @@ -1416,8 +1416,12 @@ namespace EMotionFX *outResult = m_staticAabb; EMFX_SCALECODE( - outResult->SetMin(m_staticAabb.GetMin() * m_worldTransform.m_scale); - outResult->SetMax(m_staticAabb.GetMax() * m_worldTransform.m_scale);) + if (m_staticAabb.IsValid()) + { + outResult->SetMin(m_staticAabb.GetMin() * m_worldTransform.m_scale); + outResult->SetMax(m_staticAabb.GetMax() * m_worldTransform.m_scale); + } + ) outResult->Translate(m_worldTransform.m_position); } From 04e64e274f1b8cbd927fb3942cfcee55ecb14a7b Mon Sep 17 00:00:00 2001 From: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> Date: Wed, 11 Aug 2021 16:53:41 -0700 Subject: [PATCH 312/803] Fix typo in copypasting... Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> --- .../AzCore/AzCore/UnitTest/Mocks/MockSettingsRegistry.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/UnitTest/Mocks/MockSettingsRegistry.h b/Code/Framework/AzCore/AzCore/UnitTest/Mocks/MockSettingsRegistry.h index a63e782146..7e6bb3d7b4 100644 --- a/Code/Framework/AzCore/AzCore/UnitTest/Mocks/MockSettingsRegistry.h +++ b/Code/Framework/AzCore/AzCore/UnitTest/Mocks/MockSettingsRegistry.h @@ -27,8 +27,8 @@ namespace AZ MOCK_METHOD1(RegisterNotifier, NotifyEventHandler(NotifyCallback&&)); MOCK_METHOD1(RegisterPreMergeEvent, PreMergeEventHandler(const PreMergeEventCallback&)); MOCK_METHOD1(RegisterPreMergeEvent, PreMergeEventHandler(PreMergeEventCallback&&)); - MOCK_METHOD1(PostMergeEventHandler, PreMergeEventHandler(const PostMergeEventCallback&)); - MOCK_METHOD1(PostMergeEventHandler, PreMergeEventHandler(PostMergeEventCallback&&)); + MOCK_METHOD1(RegisterPostMergeEvent, PostMergeEventHandler(const PostMergeEventCallback&)); + MOCK_METHOD1(RegisterPostMergeEvent, PostMergeEventHandler(PostMergeEventCallback&&)); MOCK_CONST_METHOD2(Get, bool(bool&, AZStd::string_view)); MOCK_CONST_METHOD2(Get, bool(s64&, AZStd::string_view)); From 2b4bd100285d0637d1b240b2d74b2ba5cbaf66a0 Mon Sep 17 00:00:00 2001 From: lsemp3d <58790905+lsemp3d@users.noreply.github.com> Date: Wed, 11 Aug 2021 17:08:09 -0700 Subject: [PATCH 313/803] Updated path to icon that was emitting a warning Signed-off-by: lsemp3d <58790905+lsemp3d@users.noreply.github.com> --- Gems/ScriptCanvas/Code/Editor/SystemComponent.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/ScriptCanvas/Code/Editor/SystemComponent.cpp b/Gems/ScriptCanvas/Code/Editor/SystemComponent.cpp index 5ec2637231..b80bba75c2 100644 --- a/Gems/ScriptCanvas/Code/Editor/SystemComponent.cpp +++ b/Gems/ScriptCanvas/Code/Editor/SystemComponent.cpp @@ -311,7 +311,7 @@ namespace ScriptCanvasEditor { if (AZStd::wildcard_match("*.scriptcanvas", fullSourceFileName)) { - return AzToolsFramework::AssetBrowser::SourceFileDetails("Icons/AssetBrowser/ScriptCanvas_16.png"); + return AzToolsFramework::AssetBrowser::SourceFileDetails("Editor/Icons/AssetBrowser/ScriptCanvas_16.png"); } // not one of our types. From d2c87fd21ffa3406b5f0c774d337d6b7564b4eb5 Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Wed, 11 Aug 2021 17:30:16 -0700 Subject: [PATCH 314/803] initial json serialization for editor sc properties Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- .../Code/Include/ScriptCanvas/Core/Datum.h | 3 + .../Serialization/DatumSerializer.cpp | 196 ++++++++++++++++++ .../Serialization/DatumSerializer.h | 37 ++++ .../RuntimeVariableSerializer.cpp | 28 +-- .../Serialization/RuntimeVariableSerializer.h | 4 +- .../Code/Source/SystemComponent.cpp | 12 +- .../Code/scriptcanvasgem_common_files.cmake | 6 +- 7 files changed, 265 insertions(+), 21 deletions(-) create mode 100644 Gems/ScriptCanvas/Code/Include/ScriptCanvas/Serialization/DatumSerializer.cpp create mode 100644 Gems/ScriptCanvas/Code/Include/ScriptCanvas/Serialization/DatumSerializer.h diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Datum.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Datum.h index 83db8fc242..4cbc25b500 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Datum.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Datum.h @@ -20,6 +20,7 @@ namespace AZ { class ReflectContext; + class DatumSerializer; } namespace ScriptCanvas @@ -33,6 +34,8 @@ namespace ScriptCanvas /// in the editor, regardless of their actual ScriptCanvas or BehaviorContext type. class Datum final { + friend class AZ::DatumSerializer; + public: AZ_TYPE_INFO(Datum, "{8B836FC0-98A8-4A81-8651-35C7CA125451}"); AZ_CLASS_ALLOCATOR(Datum, AZ::SystemAllocator, 0); diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Serialization/DatumSerializer.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Serialization/DatumSerializer.cpp new file mode 100644 index 0000000000..207eb842fd --- /dev/null +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Serialization/DatumSerializer.cpp @@ -0,0 +1,196 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include +#include + +using namespace ScriptCanvas; + +namespace AZ +{ + AZ_CLASS_ALLOCATOR_IMPL(DatumSerializer, SystemAllocator, 0); + + JsonSerializationResult::Result DatumSerializer::Load + ( void* outputValue + , [[maybe_unused]] const Uuid& outputValueTypeId + , const rapidjson::Value& inputValue + , JsonDeserializerContext& context) + { + namespace JSR = JsonSerializationResult; + + AZ_Assert(outputValueTypeId == azrtti_typeid(), "DatumSerializer Load against output typeID that was not Datum"); + AZ_Assert(outputValue, "DatumSerializer Load against null output"); + + JsonSerializationResult::ResultCode result(JSR::Tasks::ReadField); + auto outputDatum = reinterpret_cast(outputValue); + + bool isOverloadedStorage = false; + AZ_Assert(azrtti_typeidm_isOverloadedStorage)>() == azrtti_typeid() + , "overloaded storage type changed and won't load properly"); + result.Combine(ContinueLoadingFromJsonObjectField + ( &isOverloadedStorage + , azrtti_typeidm_isOverloadedStorage)>() + , inputValue + , "isOverloadedStorage" + , context)); + + ScriptCanvas::Data::Type scType; + AZ_Assert(azrtti_typeidm_type)>() == azrtti_typeid() + , "ScriptCanvas::Data::Type type changed and won't load properly"); + result.Combine(ContinueLoadingFromJsonObjectField + ( &scType + , azrtti_typeidm_type)>() + , inputValue + , "scriptCanvasType" + , context)); + + ScriptCanvas::Datum::eOriginality originality; + AZ_Assert(azrtti_typeidm_originality)>() == azrtti_typeid() + , "m_originality type changed and won't load properly"); + result.Combine(ContinueLoadingFromJsonObjectField + ( &originality + , azrtti_typeidm_originality)>() + , inputValue + , "originality" + , context)); + + AZStd::any storage; + { // datum storage begin + AZ::Uuid typeId = AZ::Uuid::CreateNull(); + + auto typeIdMember = inputValue.FindMember(JsonSerialization::TypeIdFieldIdentifier); + if (typeIdMember == inputValue.MemberEnd()) + { + return context.Report + ( JSR::Tasks::ReadField + , JSR::Outcomes::Missing + , AZStd::string::format("DatumSerializer::Load failed to load the %s member" + , JsonSerialization::TypeIdFieldIdentifier)); + } + + result.Combine(LoadTypeId(typeId, typeIdMember->value, context)); + if (typeId.IsNull()) + { + return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Catastrophic + , "DatumSerializer::Load failed to load the AZ TypeId of the value"); + } + + storage = context.GetSerializeContext()->CreateAny(typeId); + if (storage.empty() || storage.type() != typeId) + { + return context.Report(result, "DatumSerializer::Load failed to load a value matched the reported AZ TypeId. " + "The C++ declaration may have been deleted or changed."); + } + + result.Combine(ContinueLoadingFromJsonObjectField(AZStd::any_cast(&storage), typeId, inputValue, "value", context)); + } // datum storage end + + AZStd::string label; + AZ_Assert(azrtti_typeidm_datumLabel)>() == azrtti_typeid() + , "m_datumLabel type changed and won't load properly"); + result.Combine(ContinueLoadingFromJsonObjectField + ( &label + , azrtti_typeidm_datumLabel)>() + , inputValue + , "originality" + , context)); + + Datum copy(scType, originality, AZStd::any_cast(&storage), scType.GetAZType()); + copy.SetLabel(label); + *outputDatum = copy; + + return context.Report(result, result.GetProcessing() != JSR::Processing::Halted + ? "DatumSerializer Load finished loading Datum" + : "DatumSerializer Load failed to load Datum"); + } + + JsonSerializationResult::Result DatumSerializer::Store + ( rapidjson::Value& outputValue + , const void* inputValue + , const void* defaultValue + , [[maybe_unused]] const Uuid& valueTypeId + , JsonSerializerContext& context) + { + namespace JSR = JsonSerializationResult; + + AZ_Assert(valueTypeId == azrtti_typeid(), "DatumSerializer Store against value typeID that was not Datum"); + AZ_Assert(inputValue, "DatumSerializer Store against null inputValue pointer "); + + auto inputScriptDataPtr = reinterpret_cast(inputValue); + auto defaultScriptDataPtr = reinterpret_cast(defaultValue); + + if (defaultScriptDataPtr) + { + if (*inputScriptDataPtr == *defaultScriptDataPtr) + { + return context.Report + ( JSR::Tasks::WriteValue, JSR::Outcomes::DefaultsUsed, "DatumSerializer Store used defaults for Datum"); + } + } + + JSR::ResultCode result(JSR::Tasks::WriteValue); + outputValue.SetObject(); + + result.Combine(ContinueStoringToJsonObjectField + ( outputValue + , "isOverloadedStorage" + , &inputScriptDataPtr->m_isOverloadedStorage + , defaultScriptDataPtr ? &defaultScriptDataPtr->m_isOverloadedStorage : nullptr + , azrtti_typeidm_isOverloadedStorage)>() + , context)); + + result.Combine(ContinueStoringToJsonObjectField + ( outputValue + , "scriptCanvasType" + , &inputScriptDataPtr->GetType() + , defaultScriptDataPtr ? &defaultScriptDataPtr->GetType() : nullptr + , azrtti_typeidGetType())>() + , context)); + + result.Combine(ContinueStoringToJsonObjectField + ( outputValue + , "originality" + , &inputScriptDataPtr->m_originality + , defaultScriptDataPtr ? &defaultScriptDataPtr->m_originality : nullptr + , azrtti_typeidm_originality)>() + , context)); + + { // datum storage begin + { + rapidjson::Value typeValue; + result.Combine(StoreTypeId(typeValue, inputScriptDataPtr->GetType().GetAZType(), context)); + outputValue.AddMember + ( rapidjson::StringRef(JsonSerialization::TypeIdFieldIdentifier) + , AZStd::move(typeValue) + , context.GetJsonAllocator()); + } + + result.Combine(ContinueStoringToJsonObjectField + ( outputValue + , "value" + , inputScriptDataPtr->GetAsDanger() + , defaultScriptDataPtr ? defaultScriptDataPtr->GetAsDanger() : nullptr + , inputScriptDataPtr->GetType().GetAZType() + , context)); + } // datum storage end + + result.Combine(ContinueStoringToJsonObjectField + ( outputValue + , "label" + , &inputScriptDataPtr->m_datumLabel + , defaultScriptDataPtr ? &defaultScriptDataPtr->m_datumLabel : nullptr + , azrtti_typeidm_datumLabel)>() + , context)); + + return context.Report(result, result.GetProcessing() != JSR::Processing::Halted + ? "DatumSerializer Store finished saving Datum" + : "DatumSerializer Store failed to save Datum"); + } + +} diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Serialization/DatumSerializer.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Serialization/DatumSerializer.h new file mode 100644 index 0000000000..003c5c0383 --- /dev/null +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Serialization/DatumSerializer.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#pragma once + +#include +#include +#include + +namespace AZ +{ + class DatumSerializer + : public BaseJsonSerializer + { + public: + AZ_RTTI(DatumSerializer, "{FBEBF833-465F-49F4-AFB1-CC9D3B25C16C}", BaseJsonSerializer); + AZ_CLASS_ALLOCATOR_DECL; + + private: + JsonSerializationResult::Result Load + ( void* outputValue + , const Uuid& outputValueTypeId + , const rapidjson::Value& inputValue + , JsonDeserializerContext& context) override; + + JsonSerializationResult::Result Store + ( rapidjson::Value& outputValue + , const void* inputValue + , const void* defaultValue + , const Uuid& valueTypeId, JsonSerializerContext& context) override; + }; +} diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Serialization/RuntimeVariableSerializer.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Serialization/RuntimeVariableSerializer.cpp index 64cf665305..763206df38 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Serialization/RuntimeVariableSerializer.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Serialization/RuntimeVariableSerializer.cpp @@ -8,15 +8,15 @@ #include #include -#include +#include using namespace ScriptCanvas; namespace AZ { - AZ_CLASS_ALLOCATOR_IMPL(ScriptUserDataSerializer, SystemAllocator, 0); + AZ_CLASS_ALLOCATOR_IMPL(RuntimeVariableSerializer, SystemAllocator, 0); - JsonSerializationResult::Result ScriptUserDataSerializer::Load + JsonSerializationResult::Result RuntimeVariableSerializer::Load ( void* outputValue , [[maybe_unused]] const Uuid& outputValueTypeId , const rapidjson::Value& inputValue @@ -24,8 +24,8 @@ namespace AZ { namespace JSR = JsonSerializationResult; - AZ_Assert(outputValueTypeId == azrtti_typeid(), "ScriptUserDataSerializer Load against output typeID that was not RuntimeVariable"); - AZ_Assert(outputValue, "ScriptUserDataSerializer Load against null output"); + AZ_Assert(outputValueTypeId == azrtti_typeid(), "RuntimeVariableSerializer Load against output typeID that was not RuntimeVariable"); + AZ_Assert(outputValue, "RuntimeVariableSerializer Load against null output"); auto outputVariable = reinterpret_cast(outputValue); JsonSerializationResult::ResultCode result(JSR::Tasks::ReadField); @@ -34,28 +34,28 @@ namespace AZ auto typeIdMember = inputValue.FindMember(JsonSerialization::TypeIdFieldIdentifier); if (typeIdMember == inputValue.MemberEnd()) { - return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Missing, AZStd::string::format("ScriptUserDataSerializer::Load failed to load the %s member", JsonSerialization::TypeIdFieldIdentifier)); + return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Missing, AZStd::string::format("RuntimeVariableSerializer::Load failed to load the %s member", JsonSerialization::TypeIdFieldIdentifier)); } result.Combine(LoadTypeId(typeId, typeIdMember->value, context)); if (typeId.IsNull()) { - return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Catastrophic, "ScriptUserDataSerializer::Load failed to load the AZ TypeId of the value"); + return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Catastrophic, "RuntimeVariableSerializer::Load failed to load the AZ TypeId of the value"); } outputVariable->value = context.GetSerializeContext()->CreateAny(typeId); if (outputVariable->value.empty() || outputVariable->value.type() != typeId) { - return context.Report(result, "ScriptUserDataSerializer::Load failed to load a value matched the reported AZ TypeId. The C++ declaration may have been deleted or changed."); + return context.Report(result, "RuntimeVariableSerializer::Load failed to load a value matched the reported AZ TypeId. The C++ declaration may have been deleted or changed."); } result.Combine(ContinueLoadingFromJsonObjectField(AZStd::any_cast(&outputVariable->value), typeId, inputValue, "value", context)); return context.Report(result, result.GetProcessing() != JSR::Processing::Halted - ? "ScriptUserDataSerializer Load finished loading RuntimeVariable" - : "ScriptUserDataSerializer Load failed to load RuntimeVariable"); + ? "RuntimeVariableSerializer Load finished loading RuntimeVariable" + : "RuntimeVariableSerializer Load failed to load RuntimeVariable"); } - JsonSerializationResult::Result ScriptUserDataSerializer::Store + JsonSerializationResult::Result RuntimeVariableSerializer::Store ( rapidjson::Value& outputValue , const void* inputValue , const void* defaultValue @@ -79,7 +79,7 @@ namespace AZ if (inputDatum == defaultDatum) { - return context.Report(JSR::Tasks::WriteValue, JSR::Outcomes::DefaultsUsed, "ScriptUserDataSerializer Store used defaults for RuntimeVariable"); + return context.Report(JSR::Tasks::WriteValue, JSR::Outcomes::DefaultsUsed, "RuntimeVariableSerializer Store used defaults for RuntimeVariable"); } } @@ -95,8 +95,8 @@ namespace AZ result.Combine(ContinueStoringToJsonObjectField(outputValue, "value", AZStd::any_cast(inputAnyPtr), AZStd::any_cast(defaultAnyPtr), inputAnyPtr->type(), context)); return context.Report(result, result.GetProcessing() != JSR::Processing::Halted - ? "ScriptUserDataSerializer Store finished saving RuntimeVariable" - : "ScriptUserDataSerializer Store failed to save RuntimeVariable"); + ? "RuntimeVariableSerializer Store finished saving RuntimeVariable" + : "RuntimeVariableSerializer Store failed to save RuntimeVariable"); } } diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Serialization/RuntimeVariableSerializer.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Serialization/RuntimeVariableSerializer.h index 720f9481f3..a55770c79f 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Serialization/RuntimeVariableSerializer.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Serialization/RuntimeVariableSerializer.h @@ -14,11 +14,11 @@ namespace AZ { - class ScriptUserDataSerializer + class RuntimeVariableSerializer : public BaseJsonSerializer { public: - AZ_RTTI(ScriptUserDataSerializer, "{7E5FC193-8CDB-4251-A68B-F337027381DF}", BaseJsonSerializer); + AZ_RTTI(RuntimeVariableSerializer, "{7E5FC193-8CDB-4251-A68B-F337027381DF}", BaseJsonSerializer); AZ_CLASS_ALLOCATOR_DECL; private: diff --git a/Gems/ScriptCanvas/Code/Source/SystemComponent.cpp b/Gems/ScriptCanvas/Code/Source/SystemComponent.cpp index 9efbb13639..0a82b8cf2a 100644 --- a/Gems/ScriptCanvas/Code/Source/SystemComponent.cpp +++ b/Gems/ScriptCanvas/Code/Source/SystemComponent.cpp @@ -23,7 +23,8 @@ #include #include #include -#include +#include +#include #include #include @@ -87,8 +88,13 @@ namespace ScriptCanvas if (AZ::JsonRegistrationContext* jsonContext = azrtti_cast(context)) { - jsonContext->Serializer() - ->HandlesType(); + jsonContext->Serializer() + ->HandlesType() + ; + + jsonContext->Serializer() + ->HandlesType() + ; } #if defined(SC_EXECUTION_TRACE_ENABLED) diff --git a/Gems/ScriptCanvas/Code/scriptcanvasgem_common_files.cmake b/Gems/ScriptCanvas/Code/scriptcanvasgem_common_files.cmake index 84ba39cc72..f1215dd580 100644 --- a/Gems/ScriptCanvas/Code/scriptcanvasgem_common_files.cmake +++ b/Gems/ScriptCanvas/Code/scriptcanvasgem_common_files.cmake @@ -539,8 +539,10 @@ set(FILES Include/ScriptCanvas/Profiler/Aggregator.cpp Include/ScriptCanvas/Profiler/DrillerEvents.h Include/ScriptCanvas/Profiler/DrillerEvents.cpp - Include/ScriptCanvas/Serialization/ScriptUserDataSerializer.h - Include/ScriptCanvas/Serialization/ScriptUserDataSerializer.cpp + Include/ScriptCanvas/Serialization/DatumSerializer.h + Include/ScriptCanvas/Serialization/DatumSerializer.cpp + Include/ScriptCanvas/Serialization/RuntimeVariableSerializer.h + Include/ScriptCanvas/Serialization/RuntimeVariableSerializer.cpp Include/ScriptCanvas/Data/DataTrait.cpp Include/ScriptCanvas/Data/DataTrait.h Include/ScriptCanvas/Data/PropertyTraits.cpp From 6f4951234d458fafb07c2f7a3740c910cc98c498 Mon Sep 17 00:00:00 2001 From: abrmich Date: Wed, 11 Aug 2021 17:35:19 -0700 Subject: [PATCH 315/803] Fix for input not being reenabled after game mode Signed-off-by: abrmich --- Code/Editor/EditorViewportWidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Editor/EditorViewportWidget.cpp b/Code/Editor/EditorViewportWidget.cpp index dd89d96dc3..cba82f7765 100644 --- a/Code/Editor/EditorViewportWidget.cpp +++ b/Code/Editor/EditorViewportWidget.cpp @@ -640,7 +640,7 @@ void EditorViewportWidget::OnEditorNotifyEvent(EEditorNotifyEvent event) if (m_renderViewport) { - m_renderViewport->GetControllerList()->SetEnabled(true); + m_renderViewport->SetInputProcessingEnabled(true); } break; From 8dd44075c85a98214dfa679e330de30cf6c5792f Mon Sep 17 00:00:00 2001 From: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> Date: Wed, 11 Aug 2021 21:04:19 -0700 Subject: [PATCH 316/803] [redcode/crythread-2nd-pass] post merge include fixes Signed-off-by: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> --- Code/Editor/GameEngine.h | 1 - Code/Editor/Plugins/PerforcePlugin/PerforceSourceControl.cpp | 1 - .../Platform/Android/GridMate/Session/LANSession_Android.cpp | 1 + Code/Legacy/CryCommon/CryLibrary.h | 2 +- Code/Legacy/CryCommon/IFunctorBase.h | 2 -- Code/Legacy/CryCommon/IMaterial.h | 1 - Code/Legacy/CryCommon/smartptr.h | 1 - 7 files changed, 2 insertions(+), 7 deletions(-) diff --git a/Code/Editor/GameEngine.h b/Code/Editor/GameEngine.h index 64fd20a9aa..4d183cc38e 100644 --- a/Code/Editor/GameEngine.h +++ b/Code/Editor/GameEngine.h @@ -20,7 +20,6 @@ #include "LogFile.h" #include "CryListenerSet.h" #include "Util/ModalWindowDismisser.h" -#include #endif class CStartupLogoDialog; diff --git a/Code/Editor/Plugins/PerforcePlugin/PerforceSourceControl.cpp b/Code/Editor/Plugins/PerforcePlugin/PerforceSourceControl.cpp index f8f4711631..34514b8ef1 100644 --- a/Code/Editor/Plugins/PerforcePlugin/PerforceSourceControl.cpp +++ b/Code/Editor/Plugins/PerforcePlugin/PerforceSourceControl.cpp @@ -9,7 +9,6 @@ #include "CryFile.h" #include "PerforceSourceControl.h" #include "PasswordDlg.h" -#include #include #include diff --git a/Code/Framework/GridMate/Platform/Android/GridMate/Session/LANSession_Android.cpp b/Code/Framework/GridMate/Platform/Android/GridMate/Session/LANSession_Android.cpp index 05fb56dfc1..3fa2a369a6 100644 --- a/Code/Framework/GridMate/Platform/Android/GridMate/Session/LANSession_Android.cpp +++ b/Code/Framework/GridMate/Platform/Android/GridMate/Session/LANSession_Android.cpp @@ -7,6 +7,7 @@ */ #include +#include namespace GridMate { diff --git a/Code/Legacy/CryCommon/CryLibrary.h b/Code/Legacy/CryCommon/CryLibrary.h index 787085af00..a034a2a04b 100644 --- a/Code/Legacy/CryCommon/CryLibrary.h +++ b/Code/Legacy/CryCommon/CryLibrary.h @@ -49,7 +49,7 @@ */ #include -#include +#include #include #define INJECT_ENVIRONMENT_FUNCTION "InjectEnvironment" diff --git a/Code/Legacy/CryCommon/IFunctorBase.h b/Code/Legacy/CryCommon/IFunctorBase.h index a64e811516..6fb3a5d981 100644 --- a/Code/Legacy/CryCommon/IFunctorBase.h +++ b/Code/Legacy/CryCommon/IFunctorBase.h @@ -14,8 +14,6 @@ #define CRYINCLUDE_CRYCOMMON_IFUNCTORBASE_H #pragma once -#include - #include // Base class for functor storage. diff --git a/Code/Legacy/CryCommon/IMaterial.h b/Code/Legacy/CryCommon/IMaterial.h index c484c10482..83f9140be7 100644 --- a/Code/Legacy/CryCommon/IMaterial.h +++ b/Code/Legacy/CryCommon/IMaterial.h @@ -37,7 +37,6 @@ struct IRenderMesh; #include #include #include -#include #ifdef MAX_SUB_MATERIALS // This checks that the values are in sync in the different files. diff --git a/Code/Legacy/CryCommon/smartptr.h b/Code/Legacy/CryCommon/smartptr.h index 0ff6a61b60..baf51d5030 100644 --- a/Code/Legacy/CryCommon/smartptr.h +++ b/Code/Legacy/CryCommon/smartptr.h @@ -13,7 +13,6 @@ #include #include -#include void CryFatalError(const char*, ...) PRINTF_PARAMS(1, 2); #if defined(APPLE) From 3fc0a197a0afa0206593aad40983e95f7917e13e Mon Sep 17 00:00:00 2001 From: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> Date: Wed, 11 Aug 2021 21:32:02 -0700 Subject: [PATCH 317/803] [redcode/crythread-2nd-pass] removed re-implemented stubs of Windows synchapi.h functions and CrySimpleThread define in platform.h Signed-off-by: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> --- Code/Legacy/CryCommon/Linux_Win32Wrapper.h | 55 ----------- Code/Legacy/CryCommon/WinBase.cpp | 104 --------------------- Code/Legacy/CryCommon/platform.h | 10 +- 3 files changed, 1 insertion(+), 168 deletions(-) diff --git a/Code/Legacy/CryCommon/Linux_Win32Wrapper.h b/Code/Legacy/CryCommon/Linux_Win32Wrapper.h index 7b556b0f62..ffdf3fe998 100644 --- a/Code/Legacy/CryCommon/Linux_Win32Wrapper.h +++ b/Code/Legacy/CryCommon/Linux_Win32Wrapper.h @@ -413,67 +413,12 @@ inline void SetLastError(DWORD dwErrCode) { errno = dwErrCode; } ////////////////////////////////////////////////////////////////////////// extern threadID GetCurrentThreadId(); -////////////////////////////////////////////////////////////////////////// -extern HANDLE CreateEvent( - LPSECURITY_ATTRIBUTES lpEventAttributes, - BOOL bManualReset, - BOOL bInitialState, - LPCSTR lpName - ); - ////////////////////////////////////////////////////////////////////////// extern DWORD Sleep(DWORD dwMilliseconds); ////////////////////////////////////////////////////////////////////////// extern DWORD SleepEx(DWORD dwMilliseconds, BOOL bAlertable); -////////////////////////////////////////////////////////////////////////// -extern DWORD WaitForSingleObjectEx( - HANDLE hHandle, - DWORD dwMilliseconds, - BOOL bAlertable); - -////////////////////////////////////////////////////////////////////////// -extern DWORD WaitForMultipleObjectsEx( - DWORD nCount, - const HANDLE* lpHandles, - BOOL bWaitAll, - DWORD dwMilliseconds, - BOOL bAlertable); - -////////////////////////////////////////////////////////////////////////// -extern DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds); - -////////////////////////////////////////////////////////////////////////// -extern BOOL SetEvent(HANDLE hEvent); - -////////////////////////////////////////////////////////////////////////// -extern BOOL ResetEvent(HANDLE hEvent); - -////////////////////////////////////////////////////////////////////////// -extern HANDLE CreateMutex( - LPSECURITY_ATTRIBUTES lpMutexAttributes, - BOOL bInitialOwner, - LPCSTR lpName - ); - -////////////////////////////////////////////////////////////////////////// -extern BOOL ReleaseMutex(HANDLE hMutex); - -////////////////////////////////////////////////////////////////////////// -typedef DWORD (* PTHREAD_START_ROUTINE)(LPVOID lpThreadParameter); -typedef PTHREAD_START_ROUTINE LPTHREAD_START_ROUTINE; - -////////////////////////////////////////////////////////////////////////// -extern HANDLE CreateThread( - LPSECURITY_ATTRIBUTES lpThreadAttributes, - SIZE_T dwStackSize, - LPTHREAD_START_ROUTINE lpStartAddress, - LPVOID lpParameter, - DWORD dwCreationFlags, - LPDWORD lpThreadId - ); - extern BOOL GetComputerName(LPSTR lpBuffer, LPDWORD lpnSize); //required for CryOnline extern DWORD GetCurrentProcessId(void); diff --git a/Code/Legacy/CryCommon/WinBase.cpp b/Code/Legacy/CryCommon/WinBase.cpp index 732920f890..ae646e9e1c 100644 --- a/Code/Legacy/CryCommon/WinBase.cpp +++ b/Code/Legacy/CryCommon/WinBase.cpp @@ -923,21 +923,6 @@ threadID GetCurrentThreadId() } #endif -////////////////////////////////////////////////////////////////////////// -HANDLE CreateEvent -( - LPSECURITY_ATTRIBUTES lpEventAttributes, - BOOL bManualReset, - BOOL bInitialState, - LPCSTR lpName -) -{ - //TODO: implement - CRY_ASSERT_MESSAGE(0, "CreateEvent not implemented yet"); - return 0; -} - - ////////////////////////////////////////////////////////////////////////// DWORD Sleep(DWORD dwMilliseconds) { @@ -1003,95 +988,6 @@ DWORD SleepEx(DWORD dwMilliseconds, BOOL bAlertable) return 0; } -////////////////////////////////////////////////////////////////////////// -DWORD WaitForSingleObjectEx(HANDLE hHandle, DWORD dwMilliseconds, BOOL bAlertable) -{ - //TODO: implement - CRY_ASSERT_MESSAGE(0, "WaitForSingleObjectEx not implemented yet"); - return 0; -} - -#if 0 -////////////////////////////////////////////////////////////////////////// -DWORD WaitForMultipleObjectsEx( - DWORD nCount, - const HANDLE* lpHandles, - BOOL bWaitAll, - DWORD dwMilliseconds, - BOOL bAlertable) -{ - //TODO: implement - return 0; -} -#endif - -////////////////////////////////////////////////////////////////////////// -DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds) -{ - //TODO: implement - CRY_ASSERT_MESSAGE(0, "WaitForSingleObject not implemented yet"); - return 0; -} - -////////////////////////////////////////////////////////////////////////// -BOOL SetEvent(HANDLE hEvent) -{ - //TODO: implement - CRY_ASSERT_MESSAGE(0, "SetEvent not implemented yet"); - return TRUE; -} - -////////////////////////////////////////////////////////////////////////// -BOOL ResetEvent(HANDLE hEvent) -{ - //TODO: implement - CRY_ASSERT_MESSAGE(0, "ResetEvent not implemented yet"); - return TRUE; -} - -////////////////////////////////////////////////////////////////////////// -HANDLE CreateMutex -( - LPSECURITY_ATTRIBUTES lpMutexAttributes, - BOOL bInitialOwner, - LPCSTR lpName -) -{ - //TODO: implement - CRY_ASSERT_MESSAGE(0, "CreateMutex not implemented yet"); - return 0; -} - -////////////////////////////////////////////////////////////////////////// -BOOL ReleaseMutex(HANDLE hMutex) -{ - //TODO: implement - CRY_ASSERT_MESSAGE(0, "ReleaseMutex not implemented yet"); - return TRUE; -} - -////////////////////////////////////////////////////////////////////////// - - -typedef DWORD (* PTHREAD_START_ROUTINE)(LPVOID lpThreadParameter); -typedef PTHREAD_START_ROUTINE LPTHREAD_START_ROUTINE; - -////////////////////////////////////////////////////////////////////////// -HANDLE CreateThread -( - LPSECURITY_ATTRIBUTES lpThreadAttributes, - SIZE_T dwStackSize, - LPTHREAD_START_ROUTINE lpStartAddress, - LPVOID lpParameter, - DWORD dwCreationFlags, - LPDWORD lpThreadId -) -{ - //TODO: implement - CRY_ASSERT_MESSAGE(0, "CreateThread not implemented yet"); - return 0; -} - #if defined(LINUX) || defined(APPLE) BOOL GetComputerName(LPSTR lpBuffer, LPDWORD lpnSize) { diff --git a/Code/Legacy/CryCommon/platform.h b/Code/Legacy/CryCommon/platform.h index 38c0ec7eb5..1b541a293e 100644 --- a/Code/Legacy/CryCommon/platform.h +++ b/Code/Legacy/CryCommon/platform.h @@ -142,14 +142,6 @@ #endif #if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED) #undef AZ_RESTRICTED_SECTION_IMPLEMENTED -#elif defined(LINUX) || defined(APPLE) - #if !defined(_DEBUG) - #define SIMPLE_THREAD_STACK_SIZE_KB (256) - #else - #define SIMPLE_THREAD_STACK_SIZE_KB (256 * 4) - #endif -#else - #define SIMPLE_THREAD_STACK_SIZE_KB (32) #endif #include @@ -198,7 +190,7 @@ #elif defined(ANDROID) #include "AndroidSpecific.h" #elif defined(IOS) - #include "iOSSpecific.h" + #include "iOSSpecific.h" #endif #endif From cea334dbc40d076b0d4d3fc052f89a660466f662 Mon Sep 17 00:00:00 2001 From: Kyle B Date: Wed, 11 Aug 2021 22:23:06 -0700 Subject: [PATCH 318/803] Fixed enum value problems Signed-off-by: Kyle B --- .../Code/Source/Mesh/EditorMeshComponent.cpp | 4 +++- .../Code/Source/Mesh/MeshComponentController.cpp | 13 ++----------- .../Code/Source/Mesh/MeshComponentController.h | 1 - 3 files changed, 5 insertions(+), 13 deletions(-) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp index ff0741fc31..63b32f6892 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp @@ -80,7 +80,9 @@ namespace AZ "Renders IBL specular reflections in the forward pass, using only the most influential probe (based on the position of the entity) and the global IBL cubemap. Can reduce rendering costs, but only recommended for static objects that are affected by at most one reflection probe.") ->Attribute(AZ::Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) ->DataElement(AZ::Edit::UIHandlers::ComboBox, &MeshComponentConfig::m_lodType, "Lod Type", "Lod Method.") - ->Attribute(AZ::Edit::Attributes::EnumValues, &MeshComponentConfig::GetLodTypeValues) + ->EnumAttribute(RPI::Cullable::LodType::Default, "Default") + ->EnumAttribute(RPI::Cullable::LodType::ScreenCoverage, "Screen Coverage") + ->EnumAttribute(RPI::Cullable::LodType::SpecificLod, "Specific Lod") ->Attribute(AZ::Edit::Attributes::Visibility, &MeshComponentConfig::IsAssetSet) ->ClassElement(AZ::Edit::ClassElements::Group, "Lod Configuration") ->Attribute(AZ::Edit::Attributes::AutoExpand, false) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp index 3d049d0f97..9aa3685c34 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp @@ -54,8 +54,7 @@ namespace AZ if (auto* serializeContext = azrtti_cast(context)) { serializeContext->Class() - //->Version(2, &MeshComponentControllerVersionUtility::VersionConverter) - ->Version(1) + ->Version(2, &MeshComponentControllerVersionUtility::VersionConverter) ->Field("ModelAsset", &MeshComponentConfig::m_modelAsset) ->Field("SortKey", &MeshComponentConfig::m_sortKey) ->Field("ExcludeFromReflectionCubeMaps", &MeshComponentConfig::m_excludeFromReflectionCubeMaps) @@ -65,6 +64,7 @@ namespace AZ ->Field("MinimumScreenCoverage", &MeshComponentConfig::m_minimumScreenCoverage) ->Field("QualityDecayRate", &MeshComponentConfig::m_qualityDecayRate); } + } bool MeshComponentConfig::IsAssetSet() @@ -120,15 +120,6 @@ namespace AZ return values; } - AZStd::vector> MeshComponentConfig::GetLodTypeValues() - { - return { - {aznumeric_cast(0), "Default"}, - {aznumeric_cast(1), "Screen Coverage" }, - {aznumeric_cast(2), "Specific Lod" } - }; - } - MeshComponentController::~MeshComponentController() { // Release memory, disconnect from buses in the right order and broadcast events so that other components are aware. diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h index 5f38088ca3..aba560b6e8 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h @@ -48,7 +48,6 @@ namespace AZ bool LodTypeIsSpecificLOD(); bool ShowLodConfig(); AZStd::vector> GetLodOverrideValues(); - AZStd::vector> GetLodTypeValues(); Data::Asset m_modelAsset = { AZ::Data::AssetLoadBehavior::QueueLoad }; RHI::DrawItemSortKey m_sortKey = 0; From 87922af706dc9c8cc3ee2188e5b8c2cd0a15d26b Mon Sep 17 00:00:00 2001 From: Benjamin Jillich <43751992+amzn-jillich@users.noreply.github.com> Date: Thu, 12 Aug 2021 00:07:04 -0700 Subject: [PATCH 319/803] Jack remains in A-pose while it's animation is playing (#3038) * Removed a couple of legacy cgf/mtl and removed unused texture files. * Replaced Jack with the correct version (the previous version had different joint names than the animations used). * Increased the version in the actor group exporter to reprocess the actors due to PR #2957 Signed-off-by: Benjamin Jillich --- .../Objects/Characters/Jack/Jack.fbx | 4 +- .../Characters/Jack/Jack.fbx.assetinfo | 328 ++++++++++++++++++ .../Objects/Characters/Jack/Jack.mtl | 12 - .../Jack/attachments/arm_plates_lower_01.cgf | 3 - .../Jack/attachments/arm_plates_upper_01.cgf | 3 - .../Jack/attachments/back_pack_01.cgf | 3 - .../Jack/attachments/head_aerial_01.cgf | 3 - .../Jack/attachments/jack_matGroup.mtl | 14 - .../Jack/attachments/leg_plate_l_01.cgf | 3 - .../Jack/attachments/leg_plate_r_01.cgf | 3 - .../Characters/Jack/dummyPlane_mat_group.mtl | 8 - .../Characters/Jack/enemy_matGroup.mtl | 14 - .../Characters/Jack/enemy_runner_matGroup.mtl | 14 - .../Characters/Jack/enemy_tank_matGroup.mtl | 14 - .../Objects/Characters/Jack/jack_matGroup.mtl | 14 - .../Jack/textures/BrokenRobot_01_ddna.tif | 3 - .../BrokenRobot_01_ddna.tif.exportsettings | 1 - .../Jack/textures/BrokenRobot_White_diff.tif | 3 - .../BrokenRobot_White_diff.tif.exportsettings | 1 - .../Jack/textures/BrokenRobot_White_emis.tif | 3 - .../BrokenRobot_White_emis.tif.exportsettings | 1 - .../Jack/textures/BrokenRobot_black_diff.tif | 3 - .../Jack/textures/BrokenRobot_emis.tif | 3 - .../BrokenRobot_emis.tif.exportsettings | 1 - .../Jack/textures/BrokenRobot_green_diff.tif | 3 - .../BrokenRobot_green_diff.tif.exportsettings | 1 - .../Jack/textures/BrokenRobot_red_diff.tif | 3 - .../BrokenRobot_red_diff.tif.exportsettings | 1 - .../Jack/textures/BrokenRobot_spec.tif | 3 - .../BrokenRobot_spec.tif.exportsettings | 1 - .../Jack/textures/BrokenRobot_yellow_diff.tif | 3 - ...BrokenRobot_yellow_diff.tif.exportsettings | 1 - .../Jack/textures/BrokenRobot_yellow_emis.tif | 3 - ...BrokenRobot_yellow_emis.tif.exportsettings | 1 - .../Characters/Jack/textures/jack_ddna.tif | 3 - .../textures/jack_ddna.tif.exportsettings | 1 - .../Characters/Jack/textures/jack_diff.tif | 3 - .../textures/jack_diff.tif.exportsettings | 1 - .../Characters/Jack/textures/jack_emis.tif | 3 - .../textures/jack_emis.tif.exportsettings | 1 - .../Characters/Jack/textures/jack_spec.tif | 3 - .../textures/jack_spec.tif.exportsettings | 1 - .../Jack/textures/jack_spec_02_spec.tif | 3 - .../jack_spec_02_spec.tif.exportsettings | 1 - .../RCExt/Actor/ActorGroupExporter.cpp | 2 +- 45 files changed, 331 insertions(+), 170 deletions(-) create mode 100644 AutomatedTesting/Objects/Characters/Jack/Jack.fbx.assetinfo delete mode 100644 AutomatedTesting/Objects/Characters/Jack/Jack.mtl delete mode 100644 AutomatedTesting/Objects/Characters/Jack/attachments/arm_plates_lower_01.cgf delete mode 100644 AutomatedTesting/Objects/Characters/Jack/attachments/arm_plates_upper_01.cgf delete mode 100644 AutomatedTesting/Objects/Characters/Jack/attachments/back_pack_01.cgf delete mode 100644 AutomatedTesting/Objects/Characters/Jack/attachments/head_aerial_01.cgf delete mode 100644 AutomatedTesting/Objects/Characters/Jack/attachments/jack_matGroup.mtl delete mode 100644 AutomatedTesting/Objects/Characters/Jack/attachments/leg_plate_l_01.cgf delete mode 100644 AutomatedTesting/Objects/Characters/Jack/attachments/leg_plate_r_01.cgf delete mode 100644 AutomatedTesting/Objects/Characters/Jack/dummyPlane_mat_group.mtl delete mode 100644 AutomatedTesting/Objects/Characters/Jack/enemy_matGroup.mtl delete mode 100644 AutomatedTesting/Objects/Characters/Jack/enemy_runner_matGroup.mtl delete mode 100644 AutomatedTesting/Objects/Characters/Jack/enemy_tank_matGroup.mtl delete mode 100644 AutomatedTesting/Objects/Characters/Jack/jack_matGroup.mtl delete mode 100644 AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_01_ddna.tif delete mode 100644 AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_01_ddna.tif.exportsettings delete mode 100644 AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_White_diff.tif delete mode 100644 AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_White_diff.tif.exportsettings delete mode 100644 AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_White_emis.tif delete mode 100644 AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_White_emis.tif.exportsettings delete mode 100644 AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_black_diff.tif delete mode 100644 AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_emis.tif delete mode 100644 AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_emis.tif.exportsettings delete mode 100644 AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_green_diff.tif delete mode 100644 AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_green_diff.tif.exportsettings delete mode 100644 AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_red_diff.tif delete mode 100644 AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_red_diff.tif.exportsettings delete mode 100644 AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_spec.tif delete mode 100644 AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_spec.tif.exportsettings delete mode 100644 AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_yellow_diff.tif delete mode 100644 AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_yellow_diff.tif.exportsettings delete mode 100644 AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_yellow_emis.tif delete mode 100644 AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_yellow_emis.tif.exportsettings delete mode 100644 AutomatedTesting/Objects/Characters/Jack/textures/jack_ddna.tif delete mode 100644 AutomatedTesting/Objects/Characters/Jack/textures/jack_ddna.tif.exportsettings delete mode 100644 AutomatedTesting/Objects/Characters/Jack/textures/jack_diff.tif delete mode 100644 AutomatedTesting/Objects/Characters/Jack/textures/jack_diff.tif.exportsettings delete mode 100644 AutomatedTesting/Objects/Characters/Jack/textures/jack_emis.tif delete mode 100644 AutomatedTesting/Objects/Characters/Jack/textures/jack_emis.tif.exportsettings delete mode 100644 AutomatedTesting/Objects/Characters/Jack/textures/jack_spec.tif delete mode 100644 AutomatedTesting/Objects/Characters/Jack/textures/jack_spec.tif.exportsettings delete mode 100644 AutomatedTesting/Objects/Characters/Jack/textures/jack_spec_02_spec.tif delete mode 100644 AutomatedTesting/Objects/Characters/Jack/textures/jack_spec_02_spec.tif.exportsettings diff --git a/AutomatedTesting/Objects/Characters/Jack/Jack.fbx b/AutomatedTesting/Objects/Characters/Jack/Jack.fbx index bccd5cce24..2e55fdd1e7 100644 --- a/AutomatedTesting/Objects/Characters/Jack/Jack.fbx +++ b/AutomatedTesting/Objects/Characters/Jack/Jack.fbx @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ba9a2cd047a5ee696aaeed882869017a02fd4f5eeee91b6b2bfb830ad1e5ee15 -size 10927631 +oid sha256:c285cdf72ebe4c274f8d1fbab6ff558f9344d4fa62fb9d07cf11f7511ffaaac9 +size 2177072 diff --git a/AutomatedTesting/Objects/Characters/Jack/Jack.fbx.assetinfo b/AutomatedTesting/Objects/Characters/Jack/Jack.fbx.assetinfo new file mode 100644 index 0000000000..2de6d987d7 --- /dev/null +++ b/AutomatedTesting/Objects/Characters/Jack/Jack.fbx.assetinfo @@ -0,0 +1,328 @@ +{ + "values": [ + { + "$type": "ActorGroup", + "name": "Jack", + "selectedRootBone": "RootNode.jack_root", + "id": "{B7194F91-D8A1-5D5D-AC6D-DDEBC087D80D}", + "rules": { + "rules": [ + { + "$type": "MetaDataRule", + "metaData": "AdjustActor -actorID $(ACTORID) -name \"Jack\"\nActorSetCollisionMeshes -actorID $(ACTORID) -lod 0 -nodeList \"\"\nAdjustActor -actorID $(ACTORID) -nodesExcludedFromBounds \"\" -nodeAction \"select\"\nAdjustActor -actorID $(ACTORID) -nodeAction \"replace\" -attachmentNodes \"\"\nAdjustActor -actorID $(ACTORID) -motionExtractionNodeName \"jack_root\"\nAdjustActor -actorID $(ACTORID) -mirrorSetup \"\"\n" + } + ] + } + }, + { + "$type": "{5B03C8E6-8CEE-4DA0-A7FA-CD88689DD45B} MeshGroup", + "id": "{BF2CCF49-9BE0-5103-987A-84649A974991}", + "name": "Jack", + "NodeSelectionList": { + "unselectedNodes": [ + "RootNode", + "RootNode.jack_root", + "RootNode.jack_meshZUp", + "RootNode.jack_root.Bip01__pelvis", + "RootNode.jack_meshZUp.jack_meshZUp_1", + "RootNode.jack_meshZUp.jack_meshZUp_2", + "RootNode.jack_root.Bip01__pelvis.transform", + "RootNode.jack_root.Bip01__pelvis.l_upLeg", + "RootNode.jack_root.Bip01__pelvis.r_upLeg", + "RootNode.jack_root.Bip01__pelvis.spine1", + "RootNode.jack_meshZUp.jack_meshZUp_1.Bitangent", + "RootNode.jack_meshZUp.jack_meshZUp_1.SkinWeight_", + "RootNode.jack_meshZUp.jack_meshZUp_1.transform", + "RootNode.jack_meshZUp.jack_meshZUp_1.Tangent", + "RootNode.jack_meshZUp.jack_meshZUp_1.map1", + "RootNode.jack_meshZUp.jack_meshZUp_1.jack", + "RootNode.jack_meshZUp.jack_meshZUp_2.Bitangent", + "RootNode.jack_meshZUp.jack_meshZUp_2.SkinWeight_", + "RootNode.jack_meshZUp.jack_meshZUp_2.transform", + "RootNode.jack_meshZUp.jack_meshZUp_2.Tangent", + "RootNode.jack_meshZUp.jack_meshZUp_2.map1", + "RootNode.jack_meshZUp.jack_meshZUp_2.jack", + "RootNode.jack_root.Bip01__pelvis.l_upLeg.transform", + "RootNode.jack_root.Bip01__pelvis.l_upLeg.l_upLegRoll", + "RootNode.jack_root.Bip01__pelvis.l_upLeg.l_loLeg", + "RootNode.jack_root.Bip01__pelvis.r_upLeg.transform", + "RootNode.jack_root.Bip01__pelvis.r_upLeg.r_upLegRoll", + "RootNode.jack_root.Bip01__pelvis.r_upLeg.r_loLeg", + "RootNode.jack_root.Bip01__pelvis.spine1.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2", + "RootNode.jack_root.Bip01__pelvis.l_upLeg.l_upLegRoll.transform", + "RootNode.jack_root.Bip01__pelvis.l_upLeg.l_loLeg.transform", + "RootNode.jack_root.Bip01__pelvis.l_upLeg.l_loLeg.l_ankle", + "RootNode.jack_root.Bip01__pelvis.r_upLeg.r_upLegRoll.transform", + "RootNode.jack_root.Bip01__pelvis.r_upLeg.r_loLeg.transform", + "RootNode.jack_root.Bip01__pelvis.r_upLeg.r_loLeg.r_ankle", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3", + "RootNode.jack_root.Bip01__pelvis.l_upLeg.l_loLeg.l_ankle.transform", + "RootNode.jack_root.Bip01__pelvis.l_upLeg.l_loLeg.l_ankle.l_ball", + "RootNode.jack_root.Bip01__pelvis.r_upLeg.r_loLeg.r_ankle.transform", + "RootNode.jack_root.Bip01__pelvis.r_upLeg.r_loLeg.r_ankle.r_ball", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.neck", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr", + "RootNode.jack_root.Bip01__pelvis.l_upLeg.l_loLeg.l_ankle.l_ball.transform", + "RootNode.jack_root.Bip01__pelvis.r_upLeg.r_loLeg.r_ankle.r_ball.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.neck.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.neck.head", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.neck.head.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_upArmRoll", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_upArmRoll", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_upArmRoll.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_loArmRoll", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_upArmRoll.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_loArmRoll", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_loArmRoll.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_thumb1", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_index1", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_mid1", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_metacarpal", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_handProp", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_loArmRoll.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_thumb1", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_index1", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_mid1", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_metacarpal", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_handProp", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_thumb1.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_thumb1.l_thumb2", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_index1.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_index1.l_index2", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_mid1.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_mid1.l_mid2", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_metacarpal.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_metacarpal.l_ring1", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_metacarpal.l_pinky1", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_handProp.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_thumb1.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_thumb1.r_thumb2", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_index1.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_index1.r_index2", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_mid1.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_mid1.r_mid2", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_metacarpal.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_metacarpal.r_ring1", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_metacarpal.r_pinky1", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_handProp.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_thumb1.l_thumb2.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_thumb1.l_thumb2.l_thumb3", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_index1.l_index2.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_index1.l_index2.l_index3", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_mid1.l_mid2.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_mid1.l_mid2.l_mid3", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_metacarpal.l_ring1.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_metacarpal.l_ring1.l_ring2", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_metacarpal.l_pinky1.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_metacarpal.l_pinky1.l_pinky2", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_thumb1.r_thumb2.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_thumb1.r_thumb2.r_thumb3", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_index1.r_index2.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_index1.r_index2.r_index3", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_mid1.r_mid2.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_mid1.r_mid2.r_mid3", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_metacarpal.r_ring1.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_metacarpal.r_ring1.r_ring2", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_metacarpal.r_pinky1.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_metacarpal.r_pinky1.r_pinky2", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_thumb1.l_thumb2.l_thumb3.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_index1.l_index2.l_index3.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_mid1.l_mid2.l_mid3.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_metacarpal.l_ring1.l_ring2.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_metacarpal.l_ring1.l_ring2.l_ring3", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_metacarpal.l_pinky1.l_pinky2.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_metacarpal.l_pinky1.l_pinky2.l_pinky3", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_thumb1.r_thumb2.r_thumb3.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_index1.r_index2.r_index3.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_mid1.r_mid2.r_mid3.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_metacarpal.r_ring1.r_ring2.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_metacarpal.r_ring1.r_ring2.r_ring3", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_metacarpal.r_pinky1.r_pinky2.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_metacarpal.r_pinky1.r_pinky2.r_pinky3", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_metacarpal.l_ring1.l_ring2.l_ring3.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_metacarpal.l_pinky1.l_pinky2.l_pinky3.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_metacarpal.r_ring1.r_ring2.r_ring3.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_metacarpal.r_pinky1.r_pinky2.r_pinky3.transform" + ] + } + }, + { + "$type": "{07B356B7-3635-40B5-878A-FAC4EFD5AD86} MeshGroup", + "name": "Jack", + "nodeSelectionList": { + "selectedNodes": [ + "RootNode", + "RootNode.jack_root", + "RootNode.jack_meshZUp", + "RootNode.jack_root.Bip01__pelvis", + "RootNode.jack_meshZUp.jack_meshZUp_1", + "RootNode.jack_meshZUp.jack_meshZUp_2", + "RootNode.jack_root.Bip01__pelvis.transform", + "RootNode.jack_root.Bip01__pelvis.l_upLeg", + "RootNode.jack_root.Bip01__pelvis.r_upLeg", + "RootNode.jack_root.Bip01__pelvis.spine1", + "RootNode.jack_meshZUp.jack_meshZUp_1.Bitangent", + "RootNode.jack_meshZUp.jack_meshZUp_1.SkinWeight_", + "RootNode.jack_meshZUp.jack_meshZUp_1.transform", + "RootNode.jack_meshZUp.jack_meshZUp_1.Tangent", + "RootNode.jack_meshZUp.jack_meshZUp_1.map1", + "RootNode.jack_meshZUp.jack_meshZUp_1.jack", + "RootNode.jack_meshZUp.jack_meshZUp_2.Bitangent", + "RootNode.jack_meshZUp.jack_meshZUp_2.SkinWeight_", + "RootNode.jack_meshZUp.jack_meshZUp_2.transform", + "RootNode.jack_meshZUp.jack_meshZUp_2.Tangent", + "RootNode.jack_meshZUp.jack_meshZUp_2.map1", + "RootNode.jack_meshZUp.jack_meshZUp_2.jack", + "RootNode.jack_root.Bip01__pelvis.l_upLeg.transform", + "RootNode.jack_root.Bip01__pelvis.l_upLeg.l_upLegRoll", + "RootNode.jack_root.Bip01__pelvis.l_upLeg.l_loLeg", + "RootNode.jack_root.Bip01__pelvis.r_upLeg.transform", + "RootNode.jack_root.Bip01__pelvis.r_upLeg.r_upLegRoll", + "RootNode.jack_root.Bip01__pelvis.r_upLeg.r_loLeg", + "RootNode.jack_root.Bip01__pelvis.spine1.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2", + "RootNode.jack_root.Bip01__pelvis.l_upLeg.l_upLegRoll.transform", + "RootNode.jack_root.Bip01__pelvis.l_upLeg.l_loLeg.transform", + "RootNode.jack_root.Bip01__pelvis.l_upLeg.l_loLeg.l_ankle", + "RootNode.jack_root.Bip01__pelvis.r_upLeg.r_upLegRoll.transform", + "RootNode.jack_root.Bip01__pelvis.r_upLeg.r_loLeg.transform", + "RootNode.jack_root.Bip01__pelvis.r_upLeg.r_loLeg.r_ankle", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3", + "RootNode.jack_root.Bip01__pelvis.l_upLeg.l_loLeg.l_ankle.transform", + "RootNode.jack_root.Bip01__pelvis.l_upLeg.l_loLeg.l_ankle.l_ball", + "RootNode.jack_root.Bip01__pelvis.r_upLeg.r_loLeg.r_ankle.transform", + "RootNode.jack_root.Bip01__pelvis.r_upLeg.r_loLeg.r_ankle.r_ball", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.neck", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr", + "RootNode.jack_root.Bip01__pelvis.l_upLeg.l_loLeg.l_ankle.l_ball.transform", + "RootNode.jack_root.Bip01__pelvis.r_upLeg.r_loLeg.r_ankle.r_ball.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.neck.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.neck.head", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.neck.head.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_upArmRoll", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_upArmRoll", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_upArmRoll.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_loArmRoll", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_upArmRoll.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_loArmRoll", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_loArmRoll.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_thumb1", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_index1", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_mid1", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_metacarpal", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_handProp", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_loArmRoll.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_thumb1", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_index1", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_mid1", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_metacarpal", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_handProp", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_thumb1.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_thumb1.l_thumb2", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_index1.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_index1.l_index2", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_mid1.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_mid1.l_mid2", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_metacarpal.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_metacarpal.l_ring1", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_metacarpal.l_pinky1", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_handProp.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_thumb1.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_thumb1.r_thumb2", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_index1.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_index1.r_index2", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_mid1.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_mid1.r_mid2", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_metacarpal.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_metacarpal.r_ring1", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_metacarpal.r_pinky1", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_handProp.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_thumb1.l_thumb2.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_thumb1.l_thumb2.l_thumb3", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_index1.l_index2.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_index1.l_index2.l_index3", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_mid1.l_mid2.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_mid1.l_mid2.l_mid3", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_metacarpal.l_ring1.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_metacarpal.l_ring1.l_ring2", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_metacarpal.l_pinky1.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_metacarpal.l_pinky1.l_pinky2", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_thumb1.r_thumb2.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_thumb1.r_thumb2.r_thumb3", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_index1.r_index2.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_index1.r_index2.r_index3", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_mid1.r_mid2.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_mid1.r_mid2.r_mid3", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_metacarpal.r_ring1.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_metacarpal.r_ring1.r_ring2", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_metacarpal.r_pinky1.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_metacarpal.r_pinky1.r_pinky2", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_thumb1.l_thumb2.l_thumb3.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_index1.l_index2.l_index3.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_mid1.l_mid2.l_mid3.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_metacarpal.l_ring1.l_ring2.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_metacarpal.l_ring1.l_ring2.l_ring3", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_metacarpal.l_pinky1.l_pinky2.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_metacarpal.l_pinky1.l_pinky2.l_pinky3", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_thumb1.r_thumb2.r_thumb3.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_index1.r_index2.r_index3.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_mid1.r_mid2.r_mid3.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_metacarpal.r_ring1.r_ring2.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_metacarpal.r_ring1.r_ring2.r_ring3", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_metacarpal.r_pinky1.r_pinky2.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_metacarpal.r_pinky1.r_pinky2.r_pinky3", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_metacarpal.l_ring1.l_ring2.l_ring3.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.l_shldr.l_upArm.l_loArm.l_hand.l_metacarpal.l_pinky1.l_pinky2.l_pinky3.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_metacarpal.r_ring1.r_ring2.r_ring3.transform", + "RootNode.jack_root.Bip01__pelvis.spine1.spine2.spine3.r_shldr.r_upArm.r_loArm.r_hand.r_metacarpal.r_pinky1.r_pinky2.r_pinky3.transform" + ] + }, + "rules": { + "rules": [ + { + "$type": "SkinRule" + }, + { + "$type": "MaterialRule" + } + ] + }, + "id": "{59B1DB76-5B27-5569-8DF6-55296FD0E5D8}" + } + ] +} \ No newline at end of file diff --git a/AutomatedTesting/Objects/Characters/Jack/Jack.mtl b/AutomatedTesting/Objects/Characters/Jack/Jack.mtl deleted file mode 100644 index 2af23cc798..0000000000 --- a/AutomatedTesting/Objects/Characters/Jack/Jack.mtl +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/AutomatedTesting/Objects/Characters/Jack/attachments/arm_plates_lower_01.cgf b/AutomatedTesting/Objects/Characters/Jack/attachments/arm_plates_lower_01.cgf deleted file mode 100644 index a9530b6d1b..0000000000 --- a/AutomatedTesting/Objects/Characters/Jack/attachments/arm_plates_lower_01.cgf +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:bb1c97394454a0a0c3b4aaf8380878aac3f7bedc9091ec920963932ad6ad2290 -size 30484 diff --git a/AutomatedTesting/Objects/Characters/Jack/attachments/arm_plates_upper_01.cgf b/AutomatedTesting/Objects/Characters/Jack/attachments/arm_plates_upper_01.cgf deleted file mode 100644 index 781ff1fe50..0000000000 --- a/AutomatedTesting/Objects/Characters/Jack/attachments/arm_plates_upper_01.cgf +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d090219fc20e7c1d9f0c187f976a7cb55e5b27b39e087aa8281ac794f314cb32 -size 22364 diff --git a/AutomatedTesting/Objects/Characters/Jack/attachments/back_pack_01.cgf b/AutomatedTesting/Objects/Characters/Jack/attachments/back_pack_01.cgf deleted file mode 100644 index 0e59a1393d..0000000000 --- a/AutomatedTesting/Objects/Characters/Jack/attachments/back_pack_01.cgf +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8fa78264ca46a2f201e24c3ba6a543e713bf9fd984df0a10f52b191d21077227 -size 106676 diff --git a/AutomatedTesting/Objects/Characters/Jack/attachments/head_aerial_01.cgf b/AutomatedTesting/Objects/Characters/Jack/attachments/head_aerial_01.cgf deleted file mode 100644 index cc54ba4b64..0000000000 --- a/AutomatedTesting/Objects/Characters/Jack/attachments/head_aerial_01.cgf +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ebf610eecec9a4da2d5c9260c48b81f6a04eaf7686d69850ad9f5d06fdbcf183 -size 12940 diff --git a/AutomatedTesting/Objects/Characters/Jack/attachments/jack_matGroup.mtl b/AutomatedTesting/Objects/Characters/Jack/attachments/jack_matGroup.mtl deleted file mode 100644 index ebade464ec..0000000000 --- a/AutomatedTesting/Objects/Characters/Jack/attachments/jack_matGroup.mtl +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/AutomatedTesting/Objects/Characters/Jack/attachments/leg_plate_l_01.cgf b/AutomatedTesting/Objects/Characters/Jack/attachments/leg_plate_l_01.cgf deleted file mode 100644 index 3ffabb1464..0000000000 --- a/AutomatedTesting/Objects/Characters/Jack/attachments/leg_plate_l_01.cgf +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:30afe8cf6e4aca846b07ef81747607afb47c0ff88283f363aca29ded9818c3db -size 8148 diff --git a/AutomatedTesting/Objects/Characters/Jack/attachments/leg_plate_r_01.cgf b/AutomatedTesting/Objects/Characters/Jack/attachments/leg_plate_r_01.cgf deleted file mode 100644 index e98083d030..0000000000 --- a/AutomatedTesting/Objects/Characters/Jack/attachments/leg_plate_r_01.cgf +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:dba25dd8b3840d01aefb69007919b07befc5365fff714493c87cf1eff644d5dc -size 8148 diff --git a/AutomatedTesting/Objects/Characters/Jack/dummyPlane_mat_group.mtl b/AutomatedTesting/Objects/Characters/Jack/dummyPlane_mat_group.mtl deleted file mode 100644 index 4545010b7e..0000000000 --- a/AutomatedTesting/Objects/Characters/Jack/dummyPlane_mat_group.mtl +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/AutomatedTesting/Objects/Characters/Jack/enemy_matGroup.mtl b/AutomatedTesting/Objects/Characters/Jack/enemy_matGroup.mtl deleted file mode 100644 index 523dac897f..0000000000 --- a/AutomatedTesting/Objects/Characters/Jack/enemy_matGroup.mtl +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/AutomatedTesting/Objects/Characters/Jack/enemy_runner_matGroup.mtl b/AutomatedTesting/Objects/Characters/Jack/enemy_runner_matGroup.mtl deleted file mode 100644 index 95c40eeb65..0000000000 --- a/AutomatedTesting/Objects/Characters/Jack/enemy_runner_matGroup.mtl +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/AutomatedTesting/Objects/Characters/Jack/enemy_tank_matGroup.mtl b/AutomatedTesting/Objects/Characters/Jack/enemy_tank_matGroup.mtl deleted file mode 100644 index e0f18e9f69..0000000000 --- a/AutomatedTesting/Objects/Characters/Jack/enemy_tank_matGroup.mtl +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/AutomatedTesting/Objects/Characters/Jack/jack_matGroup.mtl b/AutomatedTesting/Objects/Characters/Jack/jack_matGroup.mtl deleted file mode 100644 index 3927661f97..0000000000 --- a/AutomatedTesting/Objects/Characters/Jack/jack_matGroup.mtl +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_01_ddna.tif b/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_01_ddna.tif deleted file mode 100644 index 378e0ea6ed..0000000000 --- a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_01_ddna.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ca5c900fabf8b5c8c9313a0144886f4da3f812c82e8cffd652d9c61b9bb5b953 -size 4221960 diff --git a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_01_ddna.tif.exportsettings b/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_01_ddna.tif.exportsettings deleted file mode 100644 index 10f3182ac9..0000000000 --- a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_01_ddna.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /preset=NormalsWithSmoothness /reduce=0 \ No newline at end of file diff --git a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_White_diff.tif b/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_White_diff.tif deleted file mode 100644 index 5b4a3c3518..0000000000 --- a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_White_diff.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:80f40a78e4b21dd27f5ddf34337e7d0e2119b7cfa08f0eea38d4b1d63808821f -size 3178996 diff --git a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_White_diff.tif.exportsettings b/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_White_diff.tif.exportsettings deleted file mode 100644 index 2d1dccbf99..0000000000 --- a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_White_diff.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /preset=Albedo /reduce=0 \ No newline at end of file diff --git a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_White_emis.tif b/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_White_emis.tif deleted file mode 100644 index a85ac62f6c..0000000000 --- a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_White_emis.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e5f5e327624e0f1fd35fac141019941b12ad0642c25853be9f7fd5b9b6f91bc5 -size 3168212 diff --git a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_White_emis.tif.exportsettings b/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_White_emis.tif.exportsettings deleted file mode 100644 index 2d1dccbf99..0000000000 --- a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_White_emis.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /preset=Albedo /reduce=0 \ No newline at end of file diff --git a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_black_diff.tif b/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_black_diff.tif deleted file mode 100644 index c861056eea..0000000000 --- a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_black_diff.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:089e74ca9a41967038e16a9107099a73f8e93d39c487ff5bacdde18f418bf761 -size 3176732 diff --git a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_emis.tif b/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_emis.tif deleted file mode 100644 index 6909252726..0000000000 --- a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_emis.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d45cd564d2b52575d1ad37b907a7d378871f05f6c9e5569ec73d7973d56599c9 -size 3167984 diff --git a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_emis.tif.exportsettings b/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_emis.tif.exportsettings deleted file mode 100644 index 2d1dccbf99..0000000000 --- a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_emis.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /preset=Albedo /reduce=0 \ No newline at end of file diff --git a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_green_diff.tif b/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_green_diff.tif deleted file mode 100644 index 3254f98355..0000000000 --- a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_green_diff.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:83a872c07f7cbbcb868903429dd8d5a71e8c0b7b0e2cb16cb08b5cb26b02251c -size 3177492 diff --git a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_green_diff.tif.exportsettings b/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_green_diff.tif.exportsettings deleted file mode 100644 index 2d1dccbf99..0000000000 --- a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_green_diff.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /preset=Albedo /reduce=0 \ No newline at end of file diff --git a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_red_diff.tif b/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_red_diff.tif deleted file mode 100644 index b00a8cd13b..0000000000 --- a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_red_diff.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:81c1bc9545a17232523fd97561013534221b3bf8927feefa52bdc757e294c2e2 -size 3179140 diff --git a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_red_diff.tif.exportsettings b/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_red_diff.tif.exportsettings deleted file mode 100644 index 2d1dccbf99..0000000000 --- a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_red_diff.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /preset=Albedo /reduce=0 \ No newline at end of file diff --git a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_spec.tif b/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_spec.tif deleted file mode 100644 index 3e2fb9a003..0000000000 --- a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_spec.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:99f476a56205c80878be7472857a6430ce6dc40f2eb1558de4933a5b79fa2420 -size 814244 diff --git a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_spec.tif.exportsettings b/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_spec.tif.exportsettings deleted file mode 100644 index aaaf14a9fe..0000000000 --- a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_spec.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /preset=Reflectance /reduce=0 \ No newline at end of file diff --git a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_yellow_diff.tif b/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_yellow_diff.tif deleted file mode 100644 index 2c44044576..0000000000 --- a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_yellow_diff.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:366959c8a31356669d47f58d07157171ed369b3e7549b3b65a8b8d153a1477a6 -size 3179956 diff --git a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_yellow_diff.tif.exportsettings b/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_yellow_diff.tif.exportsettings deleted file mode 100644 index 2d1dccbf99..0000000000 --- a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_yellow_diff.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /preset=Albedo /reduce=0 \ No newline at end of file diff --git a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_yellow_emis.tif b/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_yellow_emis.tif deleted file mode 100644 index 4dea311abb..0000000000 --- a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_yellow_emis.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e839924e03ba99459547df1cf5334de3bdad75b18e76176e430e343a979d9f05 -size 3168472 diff --git a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_yellow_emis.tif.exportsettings b/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_yellow_emis.tif.exportsettings deleted file mode 100644 index 2d1dccbf99..0000000000 --- a/AutomatedTesting/Objects/Characters/Jack/textures/BrokenRobot_yellow_emis.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /preset=Albedo /reduce=0 \ No newline at end of file diff --git a/AutomatedTesting/Objects/Characters/Jack/textures/jack_ddna.tif b/AutomatedTesting/Objects/Characters/Jack/textures/jack_ddna.tif deleted file mode 100644 index 57d61f505a..0000000000 --- a/AutomatedTesting/Objects/Characters/Jack/textures/jack_ddna.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:36f537bb5be89fccba1502e9e8f8dfffbf05ea8aa82ac439305e8c2502b01691 -size 16804800 diff --git a/AutomatedTesting/Objects/Characters/Jack/textures/jack_ddna.tif.exportsettings b/AutomatedTesting/Objects/Characters/Jack/textures/jack_ddna.tif.exportsettings deleted file mode 100644 index a90d724812..0000000000 --- a/AutomatedTesting/Objects/Characters/Jack/textures/jack_ddna.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=NormalsWithSmoothness /reduce=0 \ No newline at end of file diff --git a/AutomatedTesting/Objects/Characters/Jack/textures/jack_diff.tif b/AutomatedTesting/Objects/Characters/Jack/textures/jack_diff.tif deleted file mode 100644 index a8f5db9a96..0000000000 --- a/AutomatedTesting/Objects/Characters/Jack/textures/jack_diff.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b0457cbbbe1fe7e52fdb9af7ee2bc32df96a453fe248738b35ffe0b8087a28c5 -size 12615988 diff --git a/AutomatedTesting/Objects/Characters/Jack/textures/jack_diff.tif.exportsettings b/AutomatedTesting/Objects/Characters/Jack/textures/jack_diff.tif.exportsettings deleted file mode 100644 index f35416077f..0000000000 --- a/AutomatedTesting/Objects/Characters/Jack/textures/jack_diff.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /M=50,50,50,0,50,50 /preset=Albedo /reduce=0 \ No newline at end of file diff --git a/AutomatedTesting/Objects/Characters/Jack/textures/jack_emis.tif b/AutomatedTesting/Objects/Characters/Jack/textures/jack_emis.tif deleted file mode 100644 index f5ee4b43b2..0000000000 --- a/AutomatedTesting/Objects/Characters/Jack/textures/jack_emis.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4ba741103d039bddf72d4834c92a5e069285e31b8be2e7f4e8103f9c5c81694f -size 3167864 diff --git a/AutomatedTesting/Objects/Characters/Jack/textures/jack_emis.tif.exportsettings b/AutomatedTesting/Objects/Characters/Jack/textures/jack_emis.tif.exportsettings deleted file mode 100644 index 8177b5abe6..0000000000 --- a/AutomatedTesting/Objects/Characters/Jack/textures/jack_emis.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=Albedo /reduce=0 \ No newline at end of file diff --git a/AutomatedTesting/Objects/Characters/Jack/textures/jack_spec.tif b/AutomatedTesting/Objects/Characters/Jack/textures/jack_spec.tif deleted file mode 100644 index 20fb2114c0..0000000000 --- a/AutomatedTesting/Objects/Characters/Jack/textures/jack_spec.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4d7cb58f48e4df76214509fc01d5170fd38bc447d56af61f008c04a1653c2d20 -size 12614884 diff --git a/AutomatedTesting/Objects/Characters/Jack/textures/jack_spec.tif.exportsettings b/AutomatedTesting/Objects/Characters/Jack/textures/jack_spec.tif.exportsettings deleted file mode 100644 index 7fbb585758..0000000000 --- a/AutomatedTesting/Objects/Characters/Jack/textures/jack_spec.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /M=50,50,50,0,50,50 /preset=Reflectance /reduce=0 \ No newline at end of file diff --git a/AutomatedTesting/Objects/Characters/Jack/textures/jack_spec_02_spec.tif b/AutomatedTesting/Objects/Characters/Jack/textures/jack_spec_02_spec.tif deleted file mode 100644 index 3334a5c39b..0000000000 --- a/AutomatedTesting/Objects/Characters/Jack/textures/jack_spec_02_spec.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:80a2c56bfcb8c98bf5a72ec9fdb5fcc6eae28ba1c3c26efad5c8a36e6105f1d0 -size 3173936 diff --git a/AutomatedTesting/Objects/Characters/Jack/textures/jack_spec_02_spec.tif.exportsettings b/AutomatedTesting/Objects/Characters/Jack/textures/jack_spec_02_spec.tif.exportsettings deleted file mode 100644 index aaaf14a9fe..0000000000 --- a/AutomatedTesting/Objects/Characters/Jack/textures/jack_spec_02_spec.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /preset=Reflectance /reduce=0 \ No newline at end of file diff --git a/Gems/EMotionFX/Code/EMotionFX/Pipeline/RCExt/Actor/ActorGroupExporter.cpp b/Gems/EMotionFX/Code/EMotionFX/Pipeline/RCExt/Actor/ActorGroupExporter.cpp index a498ed2cb7..efd3d84aa0 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Pipeline/RCExt/Actor/ActorGroupExporter.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Pipeline/RCExt/Actor/ActorGroupExporter.cpp @@ -49,7 +49,7 @@ namespace EMotionFX if (serializeContext) { // Increasing the version number of the actor group exporter will make sure all actor products will be force re-generated. - serializeContext->Class()->Version(3); + serializeContext->Class()->Version(4); } } From f6e7760e85bc1fcd0cdfe3129315806ec14bb548 Mon Sep 17 00:00:00 2001 From: abrmich Date: Thu, 12 Aug 2021 00:06:13 -0700 Subject: [PATCH 320/803] Fix for checking environment variable existence Signed-off-by: abrmich --- .../Input/Devices/Keyboard/InputDeviceKeyboard_Windows.cpp | 4 +++- .../Input/Devices/Mouse/InputDeviceMouse_Windows.cpp | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Code/Framework/AzFramework/Platform/Windows/AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard_Windows.cpp b/Code/Framework/AzFramework/Platform/Windows/AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard_Windows.cpp index f3112ab89c..650dd14a1c 100644 --- a/Code/Framework/AzFramework/Platform/Windows/AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard_Windows.cpp +++ b/Code/Framework/AzFramework/Platform/Windows/AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard_Windows.cpp @@ -117,9 +117,11 @@ namespace AzFramework , m_hasFocus(false) , m_hasTextEntryStarted(false) { + static const char* s_keyboardCountEnvironmentVarName = "InputDeviceKeyboardInstanceCount"; + s_instanceCount = AZ::Environment::FindVariable(s_keyboardCountEnvironmentVarName); if (!s_instanceCount) { - s_instanceCount = AZ::Environment::CreateVariable("InputDeviceKeyboardInstanceCount", 1); + s_instanceCount = AZ::Environment::CreateVariable(s_keyboardCountEnvironmentVarName, 1); // Register for raw keyboard input RAWINPUTDEVICE rawInputDevice; diff --git a/Code/Framework/AzFramework/Platform/Windows/AzFramework/Input/Devices/Mouse/InputDeviceMouse_Windows.cpp b/Code/Framework/AzFramework/Platform/Windows/AzFramework/Input/Devices/Mouse/InputDeviceMouse_Windows.cpp index 464f49d620..d5d313eaab 100644 --- a/Code/Framework/AzFramework/Platform/Windows/AzFramework/Input/Devices/Mouse/InputDeviceMouse_Windows.cpp +++ b/Code/Framework/AzFramework/Platform/Windows/AzFramework/Input/Devices/Mouse/InputDeviceMouse_Windows.cpp @@ -138,9 +138,11 @@ namespace AzFramework { memset(&m_lastClientRect, 0, sizeof(m_lastClientRect)); + static const char* s_mouseCountEnvironmentVarName = "InputDeviceMouseInstanceCount"; + s_instanceCount = AZ::Environment::FindVariable(s_mouseCountEnvironmentVarName); if (!s_instanceCount) { - s_instanceCount = AZ::Environment::CreateVariable("InputDeviceMouseInstanceCount", 1); + s_instanceCount = AZ::Environment::CreateVariable(s_mouseCountEnvironmentVarName, 1); // Register for raw mouse input RAWINPUTDEVICE rawInputDevice; From f4e8ecd35e07a9cebcaa9126e7f36f5ae1932a62 Mon Sep 17 00:00:00 2001 From: jonawals Date: Thu, 12 Aug 2021 10:21:33 +0100 Subject: [PATCH 321/803] TIAF script fixes (#3044) * Fix typo in MARS document key. Signed-off-by: John * Add diff support for commits on different branches. Signed-off-by: John * Restore archiving of historic data objects. Signed-off-by: John * Correctly handle commit diffs for PR builds. Signed-off-by: John * Comment out archiving of historic data objects. Signed-off-by: John * Fix python typo Signed-off-by: John * Remove comment pertaining to s3 bucket. Signed-off-by: John * Fix test selection efficiency for MARS. Signed-off-by: John --- scripts/build/TestImpactAnalysis/git_utils.py | 13 ++++++-- .../build/TestImpactAnalysis/mars_utils.py | 4 +-- scripts/build/TestImpactAnalysis/tiaf.py | 32 +++++++++++++------ .../tiaf_persistent_storage_s3.py | 6 ++++ 4 files changed, 41 insertions(+), 14 deletions(-) diff --git a/scripts/build/TestImpactAnalysis/git_utils.py b/scripts/build/TestImpactAnalysis/git_utils.py index 3561b337f3..ddc17ca146 100644 --- a/scripts/build/TestImpactAnalysis/git_utils.py +++ b/scripts/build/TestImpactAnalysis/git_utils.py @@ -21,12 +21,14 @@ class Repo: branch = self._repo.active_branch return branch.name - def create_diff_file(self, src_commit_hash: str, dst_commit_hash: str, output_path: pathlib.Path): + def create_diff_file(self, src_commit_hash: str, dst_commit_hash: str, output_path: pathlib.Path, multi_branch: bool): """ Attempts to create a diff from the src and dst commits and write to the specified output file. @param src_commit_hash: The hash for the source commit. @param dst_commit_hash: The hash for the destination commit. + @param multi_branch: The two commits are on different branches so view the changes on the + branch containing and up to dst_commit, starting at a common ancestor of both. @param output_path: The path to the file to write the diff to. """ @@ -39,8 +41,15 @@ class Repo: except EnvironmentError as e: raise RuntimeError(f"Could not create path for output file '{output_path}'") + args = ["git", "diff", "--name-status", f"--output={output_path}"] + if multi_branch: + args.append(f"{src_commit_hash}...{dst_commit_hash}") + else: + args.append(src_commit_hash) + args.append(dst_commit_hash) + # git diff will only write to the output file if both commit hashes are valid - subprocess.run(["git", "diff", "--name-status", f"--output={output_path}", src_commit_hash, dst_commit_hash]) + subprocess.run(args) if not output_path.is_file(): raise RuntimeError(f"Source commit '{src_commit_hash}' and/or destination commit '{dst_commit_hash}' are invalid") diff --git a/scripts/build/TestImpactAnalysis/mars_utils.py b/scripts/build/TestImpactAnalysis/mars_utils.py index 69374512a3..e2394ed6e1 100644 --- a/scripts/build/TestImpactAnalysis/mars_utils.py +++ b/scripts/build/TestImpactAnalysis/mars_utils.py @@ -15,7 +15,7 @@ logger = get_logger(__file__) MARS_JOB_KEY = "job" SRC_COMMIT_KEY = "src_commit" -DST_COMMIT_KEY = "src_commit" +DST_COMMIT_KEY = "dst_commit" COMMIT_DISTANCE_KEY = "commit_distance" SRC_BRANCH_KEY = "src_branch" DST_BRANCH_KEY = "dst_branch" @@ -318,7 +318,7 @@ def generate_mars_sequence(sequence_report: dict, mars_job: dict, change_list:di test_run_selection = {} test_run_selection[SELECTED_KEY] = generate_mars_test_run_selections(sequence_report[SELECTED_TEST_RUNS_KEY], sequence_report[SELECTED_TEST_RUN_REPORT_KEY], t0_timestamp) if sequence_report[SEQUENCE_TYPE_KEY] == IMPACT_ANALYSIS_SEQUENCE_TYPE_KEY or sequence_report[SEQUENCE_TYPE_KEY] == SAFE_IMPACT_ANALYSIS_SEQUENCE_TYPE_KEY: - total_test_runs = sequence_report[TOTAL_NUM_TEST_RUNS_KEY] + total_test_runs = sequence_report[TOTAL_NUM_TEST_RUNS_KEY] + len(sequence_report[DISCARDED_TEST_RUNS_KEY]) if total_test_runs > 0: test_run_selection[SELECTED_KEY][EFFICIENCY_KEY] = (1.0 - (test_run_selection[SELECTED_KEY][TOTAL_NUM_TEST_RUNS_KEY] / total_test_runs)) * 100 else: diff --git a/scripts/build/TestImpactAnalysis/tiaf.py b/scripts/build/TestImpactAnalysis/tiaf.py index 3c94c2b5f4..255a34759a 100644 --- a/scripts/build/TestImpactAnalysis/tiaf.py +++ b/scripts/build/TestImpactAnalysis/tiaf.py @@ -50,7 +50,7 @@ class TestImpact: logger.warning(f"Could not find TIAF binary at location {self._tiaf_bin}, TIAF will be turned off.") self._use_test_impact_analysis = False else: - logger.info(f"Runtime binary found at location {self._tiaf_bin}") + logger.info(f"Runtime binary found at location '{self._tiaf_bin}'") # Workspaces self._active_workspace = self._config["workspace"]["active"]["root"] @@ -71,21 +71,33 @@ class TestImpact: self._has_change_list = False self._change_list_path = None + self._src_commit = last_commit_hash # Check whether or not a previous commit hash exists (no hash is not a failure) - self._src_commit = last_commit_hash if self._src_commit: - if self._repo.is_descendent(self._src_commit, self._dst_commit) == False: - logger.info(f"Source commit '{self._src_commit}' and destination commit '{self._dst_commit}' are not related.") - return - self._commit_distance = self._repo.commit_distance(self._src_commit, self._dst_commit) - diff_path = pathlib.Path(pathlib.PurePath(self._temp_workspace).joinpath(f"changelist.{instance_id}.diff")) + if self._is_source_of_truth_branch: + # For branch builds, the dst commit must be descended from the src commit + if not self._repo.is_descendent(self._src_commit, self._dst_commit): + logger.error(f"Source commit '{self._src_commit}' and destination commit '{self._dst_commit}' must be related for branch builds.") + return + + # Calculate the distance (in commits) between the src and dst commits + self._commit_distance = self._repo.commit_distance(self._src_commit, self._dst_commit) + logger.info(f"The distance between '{self._src_commit}' and '{self._dst_commit}' commits is '{self._commit_distance}' commits.") + multi_branch = False + else: + # For pull request builds, the src and dst commits are on different branches so we need to ensure a common ancestor is used for the diff + multi_branch = True + try: - self._repo.create_diff_file(self._src_commit, self._dst_commit, diff_path) + # Attempt to generate a diff between the src and dst commits + logger.error(f"Source '{self._src_commit}' and destination '{self._dst_commit}' will be diff'd.") + diff_path = pathlib.Path(pathlib.PurePath(self._temp_workspace).joinpath(f"changelist.{instance_id}.diff")) + self._repo.create_diff_file(self._src_commit, self._dst_commit, diff_path, multi_branch) except RuntimeError as e: logger.error(e) return - + # A diff was generated, attempt to parse the diff and construct the change list logger.info(f"Generated diff between commits '{self._src_commit}' and '{self._dst_commit}': '{diff_path}'.") with open(diff_path, "r") as diff_data: @@ -189,7 +201,7 @@ class TestImpact: self._is_source_of_truth_branch = True self._source_of_truth_branch = self._src_branch else: - # PR builds use their destination as the source of truth and never update the coverage data for the source of truth + # Pull request builds use their destination as the source of truth and never update the coverage data for the source of truth self._is_source_of_truth_branch = False self._source_of_truth_branch = self._dst_branch diff --git a/scripts/build/TestImpactAnalysis/tiaf_persistent_storage_s3.py b/scripts/build/TestImpactAnalysis/tiaf_persistent_storage_s3.py index 09b4df0564..24101c7cba 100644 --- a/scripts/build/TestImpactAnalysis/tiaf_persistent_storage_s3.py +++ b/scripts/build/TestImpactAnalysis/tiaf_persistent_storage_s3.py @@ -48,6 +48,12 @@ class PersistentStorageS3(PersistentStorage): for object in self._bucket.objects.filter(Prefix=self._historic_data_key): logger.info(f"Historic data found for branch '{branch}'.") + # Archive the existing object with the name of the existing last commit hash + #archive_key = f"{self._dir}/archive/{self._last_commit_hash}.{object_extension}" + #logger.info(f"Archiving existing historic data to '{archive_key}' in bucket '{self._bucket.name}'...") + #self._bucket.copy({"Bucket": self._bucket.name, "Key": self._historic_data_key}, archive_key) + #logger.info(f"Archiving complete.") + # Decode the historic data object into raw bytes logger.info(f"Attempting to decode historic data object...") response = object.get() From 268a7f547e25a38cf6086659c912145d5e36620f Mon Sep 17 00:00:00 2001 From: John Date: Thu, 12 Aug 2021 11:19:27 +0100 Subject: [PATCH 322/803] Add additional logging to s3 storage. Signed-off-by: John --- scripts/build/TestImpactAnalysis/tiaf_persistent_storage.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scripts/build/TestImpactAnalysis/tiaf_persistent_storage.py b/scripts/build/TestImpactAnalysis/tiaf_persistent_storage.py index 18ea25091f..ec646ee484 100644 --- a/scripts/build/TestImpactAnalysis/tiaf_persistent_storage.py +++ b/scripts/build/TestImpactAnalysis/tiaf_persistent_storage.py @@ -49,6 +49,7 @@ class PersistentStorage(ABC): try: historic_data = json.loads(historic_data_json) self._last_commit_hash = historic_data["last_commit_hash"] + logger.info(f"Last commit hash '{self._last_commit_hash}' found.") # Create the active workspace directory where the coverage data file will be placed and unpack the coverage data so # it is accessible by the runtime @@ -105,7 +106,10 @@ class PersistentStorage(ABC): historic_data_json = self._pack_historic_data(last_commit_hash) if historic_data_json: + logger.info(f"Attempting to store historic data with new last commit hash '{self._last_commit_hash}'...") self._store_historic_data(historic_data_json) + logger.info("The historic data was successfully stored.") + else: logger.info("The historic data could not be successfully stored.") From 9601db55aa96a9185943d81e49a43135bf557e32 Mon Sep 17 00:00:00 2001 From: John Date: Thu, 12 Aug 2021 11:19:48 +0100 Subject: [PATCH 323/803] Add sanity checking to last commit hash. Signed-off-by: John --- scripts/build/TestImpactAnalysis/tiaf.py | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/scripts/build/TestImpactAnalysis/tiaf.py b/scripts/build/TestImpactAnalysis/tiaf.py index 255a34759a..a06a01cf38 100644 --- a/scripts/build/TestImpactAnalysis/tiaf.py +++ b/scripts/build/TestImpactAnalysis/tiaf.py @@ -61,17 +61,13 @@ class TestImpact: logger.error(f"The config does not contain the key {str(e)}.") return - def _attempt_to_generate_change_list(self, last_commit_hash, instance_id: str): + def _attempt_to_generate_change_list(self): """ Attempts to determine the change list bewteen now and the last tiaf run (if any). - - @param last_commit_hash: The commit hash of the last TIAF run. - @param instance_id: The unique id to derive the change list file name from. """ self._has_change_list = False self._change_list_path = None - self._src_commit = last_commit_hash # Check whether or not a previous commit hash exists (no hash is not a failure) if self._src_commit: @@ -92,7 +88,7 @@ class TestImpact: try: # Attempt to generate a diff between the src and dst commits logger.error(f"Source '{self._src_commit}' and destination '{self._dst_commit}' will be diff'd.") - diff_path = pathlib.Path(pathlib.PurePath(self._temp_workspace).joinpath(f"changelist.{instance_id}.diff")) + diff_path = pathlib.Path(pathlib.PurePath(self._temp_workspace).joinpath(f"changelist.{self._instance_id}.diff")) self._repo.create_diff_file(self._src_commit, self._dst_commit, diff_path, multi_branch) except RuntimeError as e: logger.error(e) @@ -124,7 +120,7 @@ class TestImpact: # Serialize the change list to the JSON format the test impact analysis runtime expects change_list_json = json.dumps(self._change_list, indent = 4) - change_list_path = pathlib.PurePath(self._temp_workspace).joinpath(f"changelist.{instance_id}.json") + change_list_path = pathlib.PurePath(self._temp_workspace).joinpath(f"changelist.{self._instance_id}.json") f = open(change_list_path, "w") f.write(change_list_json) f.close() @@ -215,7 +211,7 @@ class TestImpact: self._commit_distance = None # Generate a unique ID to be used as part of the file name for required runtime dynamic artifacts. - instance_id = uuid.uuid4().hex + self._instance_id = uuid.uuid4().hex if self._use_test_impact_analysis: logger.info("Test impact analysis is enabled.") @@ -232,7 +228,14 @@ class TestImpact: if persistent_storage: if persistent_storage.has_historic_data: logger.info("Historic data found.") - self._attempt_to_generate_change_list(persistent_storage.last_commit_hash, instance_id) + self._src_commit = persistent_storage.last_commit_hash + + # Perform some basic sanity checks on the commit hashes to ensure confidence in the integrity of of the environment + if self._src_commit == self._dst_commit: + logger.error(f"Source commit '{self._src_commit}' and destination commit '{self._dst_commit}', implying the integrity of the historic data is compromised.") + persistent_storage = None + else: + self._attempt_to_generate_change_list(self._instance_id) else: logger.info("No historic data found.") @@ -283,7 +286,7 @@ class TestImpact: logger.info(f"Test failure policy is set to '{test_failure_policy}'.") # Sequence report - report_file = pathlib.PurePath(self._temp_workspace).joinpath(f"report.{instance_id}.json") + report_file = pathlib.PurePath(self._temp_workspace).joinpath(f"report.{self._instance_id}.json") args.append(f"--report={report_file}") logger.info(f"Sequence report file is set to '{report_file}'.") From 199273b880a9266af7a5eeb1e93c76beb8bbf2c9 Mon Sep 17 00:00:00 2001 From: John Date: Thu, 12 Aug 2021 12:00:51 +0100 Subject: [PATCH 324/803] Remove positional argument from change list generaiton. Signed-off-by: John --- scripts/build/TestImpactAnalysis/tiaf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/build/TestImpactAnalysis/tiaf.py b/scripts/build/TestImpactAnalysis/tiaf.py index a06a01cf38..11ca24f830 100644 --- a/scripts/build/TestImpactAnalysis/tiaf.py +++ b/scripts/build/TestImpactAnalysis/tiaf.py @@ -235,7 +235,7 @@ class TestImpact: logger.error(f"Source commit '{self._src_commit}' and destination commit '{self._dst_commit}', implying the integrity of the historic data is compromised.") persistent_storage = None else: - self._attempt_to_generate_change_list(self._instance_id) + self._attempt_to_generate_change_list() else: logger.info("No historic data found.") From 83e56b6ab5d473ba0a912957d7f0a6b42bb644c3 Mon Sep 17 00:00:00 2001 From: AMZN-Alexandre Corcia Aguilera <82398284+aaguilea@users.noreply.github.com> Date: Thu, 12 Aug 2021 15:06:16 +0100 Subject: [PATCH 325/803] Remove new camera flag functions and legacy code paths (#3071) Signed-off-by: aaguilea --- .../EditorPreferencesPageViewportMovement.cpp | 50 +++------- Code/Editor/EditorViewportSettings.h | 4 - Code/Editor/EditorViewportWidget.cpp | 8 -- Code/Editor/GotoPositionDlg.cpp | 22 +---- .../SandboxIntegration.cpp | 98 +++++++------------ Code/Editor/ViewportTitleDlg.cpp | 17 +--- 6 files changed, 56 insertions(+), 143 deletions(-) diff --git a/Code/Editor/EditorPreferencesPageViewportMovement.cpp b/Code/Editor/EditorPreferencesPageViewportMovement.cpp index 1efe64488d..988b4954d1 100644 --- a/Code/Editor/EditorPreferencesPageViewportMovement.cpp +++ b/Code/Editor/EditorPreferencesPageViewportMovement.cpp @@ -68,45 +68,21 @@ QIcon& CEditorPreferencesPage_ViewportMovement::GetIcon() void CEditorPreferencesPage_ViewportMovement::OnApply() { - if (SandboxEditor::UsingNewCameraSystem()) - { - SandboxEditor::SetCameraTranslateSpeed(m_cameraMovementSettings.m_moveSpeed); - SandboxEditor::SetCameraRotateSpeed(m_cameraMovementSettings.m_rotateSpeed); - SandboxEditor::SetCameraBoostMultiplier(m_cameraMovementSettings.m_fastMoveSpeed); - SandboxEditor::SetCameraScrollSpeed(m_cameraMovementSettings.m_wheelZoomSpeed); - SandboxEditor::SetCameraOrbitYawRotationInverted(m_cameraMovementSettings.m_invertYRotation); - SandboxEditor::SetCameraPanInvertedX(m_cameraMovementSettings.m_invertPan); - SandboxEditor::SetCameraPanInvertedY(m_cameraMovementSettings.m_invertPan); - } - else - { - gSettings.cameraMoveSpeed = m_cameraMovementSettings.m_moveSpeed; - gSettings.cameraRotateSpeed = m_cameraMovementSettings.m_rotateSpeed; - gSettings.cameraFastMoveSpeed = m_cameraMovementSettings.m_fastMoveSpeed; - gSettings.wheelZoomSpeed = m_cameraMovementSettings.m_wheelZoomSpeed; - gSettings.invertYRotation = m_cameraMovementSettings.m_invertYRotation; - gSettings.invertPan = m_cameraMovementSettings.m_invertPan; - } + SandboxEditor::SetCameraTranslateSpeed(m_cameraMovementSettings.m_moveSpeed); + SandboxEditor::SetCameraRotateSpeed(m_cameraMovementSettings.m_rotateSpeed); + SandboxEditor::SetCameraBoostMultiplier(m_cameraMovementSettings.m_fastMoveSpeed); + SandboxEditor::SetCameraScrollSpeed(m_cameraMovementSettings.m_wheelZoomSpeed); + SandboxEditor::SetCameraOrbitYawRotationInverted(m_cameraMovementSettings.m_invertYRotation); + SandboxEditor::SetCameraPanInvertedX(m_cameraMovementSettings.m_invertPan); + SandboxEditor::SetCameraPanInvertedY(m_cameraMovementSettings.m_invertPan); } void CEditorPreferencesPage_ViewportMovement::InitializeSettings() { - if (SandboxEditor::UsingNewCameraSystem()) - { - m_cameraMovementSettings.m_moveSpeed = SandboxEditor::CameraTranslateSpeed(); - m_cameraMovementSettings.m_rotateSpeed = SandboxEditor::CameraRotateSpeed(); - m_cameraMovementSettings.m_fastMoveSpeed = SandboxEditor::CameraBoostMultiplier(); - m_cameraMovementSettings.m_wheelZoomSpeed = SandboxEditor::CameraScrollSpeed(); - m_cameraMovementSettings.m_invertYRotation = SandboxEditor::CameraOrbitYawRotationInverted(); - m_cameraMovementSettings.m_invertPan = SandboxEditor::CameraPanInvertedX() && SandboxEditor::CameraPanInvertedY(); - } - else - { - m_cameraMovementSettings.m_moveSpeed = gSettings.cameraMoveSpeed; - m_cameraMovementSettings.m_rotateSpeed = gSettings.cameraRotateSpeed; - m_cameraMovementSettings.m_fastMoveSpeed = gSettings.cameraFastMoveSpeed; - m_cameraMovementSettings.m_wheelZoomSpeed = gSettings.wheelZoomSpeed; - m_cameraMovementSettings.m_invertYRotation = gSettings.invertYRotation; - m_cameraMovementSettings.m_invertPan = gSettings.invertPan; - } + m_cameraMovementSettings.m_moveSpeed = SandboxEditor::CameraTranslateSpeed(); + m_cameraMovementSettings.m_rotateSpeed = SandboxEditor::CameraRotateSpeed(); + m_cameraMovementSettings.m_fastMoveSpeed = SandboxEditor::CameraBoostMultiplier(); + m_cameraMovementSettings.m_wheelZoomSpeed = SandboxEditor::CameraScrollSpeed(); + m_cameraMovementSettings.m_invertYRotation = SandboxEditor::CameraOrbitYawRotationInverted(); + m_cameraMovementSettings.m_invertPan = SandboxEditor::CameraPanInvertedX() && SandboxEditor::CameraPanInvertedY(); } diff --git a/Code/Editor/EditorViewportSettings.h b/Code/Editor/EditorViewportSettings.h index 1898cf642a..b1488c5528 100644 --- a/Code/Editor/EditorViewportSettings.h +++ b/Code/Editor/EditorViewportSettings.h @@ -118,8 +118,4 @@ namespace SandboxEditor SANDBOX_API AzFramework::InputChannelId CameraOrbitPanChannelId(); SANDBOX_API void SetCameraOrbitPanChannelId(AZStd::string_view cameraOrbitPanId); - - //! Return if the new editor camera system is enabled or not. - //! @note This is implemented in EditorViewportWidget.cpp - SANDBOX_API bool UsingNewCameraSystem(); } // namespace SandboxEditor diff --git a/Code/Editor/EditorViewportWidget.cpp b/Code/Editor/EditorViewportWidget.cpp index 2ca3739033..96a7e77ecd 100644 --- a/Code/Editor/EditorViewportWidget.cpp +++ b/Code/Editor/EditorViewportWidget.cpp @@ -106,14 +106,6 @@ AZ_CVAR( bool, ed_visibility_logTiming, false, nullptr, AZ::ConsoleFunctorFlags::Null, "Output the timing of the new IVisibilitySystem query"); AZ_CVAR(bool, ed_showCursorCameraLook, true, nullptr, AZ::ConsoleFunctorFlags::Null, "Show the cursor when using free look with the new camera system"); -namespace SandboxEditor -{ - bool UsingNewCameraSystem() - { - return true; - } -} // namespace SandboxEditor - EditorViewportWidget* EditorViewportWidget::m_pPrimaryViewport = nullptr; #if AZ_TRAIT_OS_PLATFORM_APPLE diff --git a/Code/Editor/GotoPositionDlg.cpp b/Code/Editor/GotoPositionDlg.cpp index c1e64ed1a9..aec5f03fbd 100644 --- a/Code/Editor/GotoPositionDlg.cpp +++ b/Code/Editor/GotoPositionDlg.cpp @@ -108,24 +108,12 @@ void GotoPositionDialog::OnUpdateNumbers() void GotoPositionDialog::accept() { - if (SandboxEditor::UsingNewCameraSystem()) - { - SandboxEditor::InterpolateDefaultViewportCameraToTransform( - AZ::Vector3( - aznumeric_cast(m_ui->m_dymX->value()), aznumeric_cast(m_ui->m_dymY->value()), - aznumeric_cast(m_ui->m_dymZ->value())), - AZ::DegToRad(aznumeric_cast(m_ui->m_dymAnglePitch->value())), - AZ::DegToRad(aznumeric_cast(m_ui->m_dymAngleYaw->value()))); - } - else - { - SandboxEditor::SetDefaultViewportCameraPosition(AZ::Vector3( + SandboxEditor::InterpolateDefaultViewportCameraToTransform( + AZ::Vector3( aznumeric_cast(m_ui->m_dymX->value()), aznumeric_cast(m_ui->m_dymY->value()), - aznumeric_cast(m_ui->m_dymZ->value()))); - SandboxEditor::SetDefaultViewportCameraRotation( - AZ::DegToRad(aznumeric_cast(m_ui->m_dymAnglePitch->value())), - AZ::DegToRad(aznumeric_cast(m_ui->m_dymAngleYaw->value()))); - } + aznumeric_cast(m_ui->m_dymZ->value())), + AZ::DegToRad(aznumeric_cast(m_ui->m_dymAnglePitch->value())), + AZ::DegToRad(aznumeric_cast(m_ui->m_dymAngleYaw->value()))); QDialog::accept(); } diff --git a/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp b/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp index 072625936b..2ed2a30f08 100644 --- a/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp +++ b/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp @@ -1704,74 +1704,44 @@ void SandboxIntegrationManager::GoToEntitiesInViewports(const AzToolsFramework:: return; } - if (SandboxEditor::UsingNewCameraSystem()) + const AZ::Aabb aabb = AZStd::accumulate( + AZStd::begin(entityIds), AZStd::end(entityIds), AZ::Aabb::CreateNull(), [](AZ::Aabb acc, const AZ::EntityId entityId) { + const AZ::Aabb aabb = AzFramework::CalculateEntityWorldBoundsUnion(AzToolsFramework::GetEntityById(entityId)); + acc.AddAabb(aabb); + return acc; + }); + + float radius; + AZ::Vector3 center; + aabb.GetAsSphere(center, radius); + + // minimum center size is 40cm + const float minSelectionRadius = 0.4f; + const float selectionSize = AZ::GetMax(minSelectionRadius, radius); + + auto viewportContextManager = AZ::Interface::Get(); + + const int viewCount = GetIEditor()->GetViewManager()->GetViewCount(); // legacy call + for (int viewIndex = 0; viewIndex < viewCount; ++viewIndex) { - const AZ::Aabb aabb = AZStd::accumulate( - AZStd::begin(entityIds), AZStd::end(entityIds), AZ::Aabb::CreateNull(), [](AZ::Aabb acc, const AZ::EntityId entityId) { - const AZ::Aabb aabb = AzFramework::CalculateEntityWorldBoundsUnion(AzToolsFramework::GetEntityById(entityId)); - acc.AddAabb(aabb); - return acc; - }); - - float radius; - AZ::Vector3 center; - aabb.GetAsSphere(center, radius); - - // minimum center size is 40cm - const float minSelectionRadius = 0.4f; - const float selectionSize = AZ::GetMax(minSelectionRadius, radius); - - auto viewportContextManager = AZ::Interface::Get(); - - const int viewCount = GetIEditor()->GetViewManager()->GetViewCount(); // legacy call - for (int viewIndex = 0; viewIndex < viewCount; ++viewIndex) + if (auto viewportContext = viewportContextManager->GetViewportContextById(viewIndex)) { - if (auto viewportContext = viewportContextManager->GetViewportContextById(viewIndex)) - { - const AZ::Transform cameraTransform = viewportContext->GetCameraTransform(); - const AZ::Vector3 forward = (center - cameraTransform.GetTranslation()).GetNormalized(); + const AZ::Transform cameraTransform = viewportContext->GetCameraTransform(); + const AZ::Vector3 forward = (center - cameraTransform.GetTranslation()).GetNormalized(); - // move camera 25% further back than required - const float centerScale = 1.25f; - // compute new camera transform - const float fov = AzFramework::RetrieveFov(viewportContext->GetCameraProjectionMatrix()); - const float fovScale = (1.0f / AZStd::tan(fov * 0.5f)); - const float distanceToLookAt = selectionSize * fovScale * centerScale; - const AZ::Transform nextCameraTransform = - AZ::Transform::CreateLookAt(aabb.GetCenter() - (forward * distanceToLookAt), aabb.GetCenter()); + // move camera 25% further back than required + const float centerScale = 1.25f; + // compute new camera transform + const float fov = AzFramework::RetrieveFov(viewportContext->GetCameraProjectionMatrix()); + const float fovScale = (1.0f / AZStd::tan(fov * 0.5f)); + const float distanceToLookAt = selectionSize * fovScale * centerScale; + const AZ::Transform nextCameraTransform = + AZ::Transform::CreateLookAt(aabb.GetCenter() - (forward * distanceToLookAt), aabb.GetCenter()); - AtomToolsFramework::ModularViewportCameraControllerRequestBus::Event( - viewportContext->GetId(), - &AtomToolsFramework::ModularViewportCameraControllerRequestBus::Events::InterpolateToTransform, nextCameraTransform, - distanceToLookAt); - } - } - } - else - { - AABB selectionBounds; - selectionBounds.Reset(); - bool entitiesAvailableForGoTo = false; - - for (const AZ::EntityId& entityId : entityIds) - { - if (CollectEntityBoundingBoxesForZoom(entityId, selectionBounds)) - { - entitiesAvailableForGoTo = true; - } - } - - if (entitiesAvailableForGoTo) - { - int numViews = GetIEditor()->GetViewManager()->GetViewCount(); - for (int viewIndex = 0; viewIndex < numViews; ++viewIndex) - { - CViewport* viewport = GetIEditor()->GetViewManager()->GetView(viewIndex); - if (viewport) - { - viewport->CenterOnAABB(selectionBounds); - } - } + AtomToolsFramework::ModularViewportCameraControllerRequestBus::Event( + viewportContext->GetId(), + &AtomToolsFramework::ModularViewportCameraControllerRequestBus::Events::InterpolateToTransform, nextCameraTransform, + distanceToLookAt); } } } diff --git a/Code/Editor/ViewportTitleDlg.cpp b/Code/Editor/ViewportTitleDlg.cpp index 530e11b01b..f5515b9c18 100644 --- a/Code/Editor/ViewportTitleDlg.cpp +++ b/Code/Editor/ViewportTitleDlg.cpp @@ -172,8 +172,7 @@ void CViewportTitleDlg::SetupCameraDropdownMenu() cameraSpeedActionWidget->setDefaultWidget(cameraSpeedContainer); // Save off the move speed here since setting up the combo box can cause it to update values in the background. - const float cameraMoveSpeed = SandboxEditor::UsingNewCameraSystem() ? SandboxEditor::CameraTranslateSpeed() : gSettings.cameraMoveSpeed; - + const float cameraMoveSpeed = SandboxEditor::CameraTranslateSpeed(); // Populate the presets in the ComboBox for (float presetValue : m_speedPresetValues) { @@ -947,21 +946,13 @@ void CViewportTitleDlg::OnSpeedComboBoxEnter() void CViewportTitleDlg::OnUpdateMoveSpeedText(const QString& text) { - if (SandboxEditor::UsingNewCameraSystem()) - { - SandboxEditor::SetCameraTranslateSpeed(aznumeric_cast(Round(text.toDouble(), m_speedStep))); - } - else - { - gSettings.cameraMoveSpeed = aznumeric_cast(Round(text.toDouble(), m_speedStep)); - } + SandboxEditor::SetCameraTranslateSpeed(aznumeric_cast(Round(text.toDouble(), m_speedStep))); } void CViewportTitleDlg::CheckForCameraSpeedUpdate() { - if (const float currentCameraMoveSpeed = - SandboxEditor::UsingNewCameraSystem() ? SandboxEditor::CameraTranslateSpeed() : gSettings.cameraMoveSpeed; - currentCameraMoveSpeed != m_prevMoveSpeed && !m_cameraSpeed->lineEdit()->hasFocus()) + const float currentCameraMoveSpeed = SandboxEditor::CameraTranslateSpeed(); + if (currentCameraMoveSpeed != m_prevMoveSpeed && !m_cameraSpeed->lineEdit()->hasFocus()) { m_prevMoveSpeed = currentCameraMoveSpeed; SetSpeedComboBox(currentCameraMoveSpeed); From 5fd2d8e7eedac494aab05a17c7e2ee0694f5b74a Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Thu, 12 Aug 2021 10:48:09 -0500 Subject: [PATCH 326/803] updating comments Signed-off-by: Guthrie Adams --- .../Code/Include/Atom/Document/MaterialDocumentRequestBus.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentRequestBus.h b/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentRequestBus.h index 23b5749554..515cc44edc 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentRequestBus.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentRequestBus.h @@ -93,10 +93,10 @@ namespace MaterialEditor //! Close document and reset its data virtual bool Close() = 0; - //! document is loaded + //! Document is loaded virtual bool IsOpen() const = 0; - //! document has changes pending + //! Document has changes pending virtual bool IsModified() const = 0; //! Can the document be saved From 288d366c2ac6fdf5a2df626d4ab37c42b41ff010 Mon Sep 17 00:00:00 2001 From: AMZN-tpeng <82184807+AMZN-tpeng@users.noreply.github.com> Date: Thu, 12 Aug 2021 09:04:38 -0700 Subject: [PATCH 327/803] =?UTF-8?q?[Atom][RHI][Vulkan][Android]=20-=20Add?= =?UTF-8?q?=202D=20image=20array=20null=20descriptors=20fo=E2=80=A6=20(#27?= =?UTF-8?q?22)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [Atom][RHI][Vulkan][Android] - Add 2D image array null descriptors for devices without the null descriptor extension. Signed-off-by: Peng * [Atom][RHI][Vulkan][Android] - Fix spacing. Signed-off-by: Peng --- .../Code/Source/RHI/NullDescriptorManager.cpp | 46 ++++++++++++++++++- .../Code/Source/RHI/NullDescriptorManager.h | 5 ++ 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/NullDescriptorManager.cpp b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/NullDescriptorManager.cpp index 1b3a533f34..316144f323 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/NullDescriptorManager.cpp +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/NullDescriptorManager.cpp @@ -117,6 +117,35 @@ namespace AZ m_imageNullDescriptor.m_images[static_cast(ImageTypes::MultiSampleReadOnly2D)].m_sampleCountFlag = VK_SAMPLE_COUNT_4_BIT; m_imageNullDescriptor.m_images[static_cast(ImageTypes::MultiSampleReadOnly2D)].m_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + m_imageNullDescriptor.m_images[static_cast(ImageTypes::GeneralArray2D)] = {}; + m_imageNullDescriptor.m_images[static_cast(ImageTypes::GeneralArray2D)].m_name = "NULL_DESCRIPTOR_GENERAL_ARRAY_2D"; + m_imageNullDescriptor.m_images[static_cast(ImageTypes::GeneralArray2D)].m_sampleCountFlag = VK_SAMPLE_COUNT_1_BIT; + m_imageNullDescriptor.m_images[static_cast(ImageTypes::GeneralArray2D)].m_format = VK_FORMAT_R8G8B8A8_SRGB; + m_imageNullDescriptor.m_images[static_cast(ImageTypes::GeneralArray2D)].m_usageFlagBits =VkImageUsageFlagBits(VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); + m_imageNullDescriptor.m_images[static_cast(ImageTypes::GeneralArray2D)].m_arrayLayers = 1; + m_imageNullDescriptor.m_images[static_cast(ImageTypes::GeneralArray2D)].m_imageCreateFlagBits = VkImageCreateFlagBits(0); + m_imageNullDescriptor.m_images[static_cast(ImageTypes::GeneralArray2D)].m_layout = VK_IMAGE_LAYOUT_GENERAL; + m_imageNullDescriptor.m_images[static_cast(ImageTypes::GeneralArray2D)].m_dimension = imageDimension; + + m_imageNullDescriptor.m_images[static_cast(ImageTypes::ReadOnlyArray2D)] = m_imageNullDescriptor.m_images[static_cast(NullDescriptorManager::ImageTypes::GeneralArray2D)]; + m_imageNullDescriptor.m_images[static_cast(ImageTypes::ReadOnlyArray2D)].m_name = "NULL_DESCRIPTOR_READONLY_ARRAY_2D"; + m_imageNullDescriptor.m_images[static_cast(ImageTypes::ReadOnlyArray2D)].m_sampleCountFlag = VK_SAMPLE_COUNT_1_BIT; + m_imageNullDescriptor.m_images[static_cast(ImageTypes::ReadOnlyArray2D)].m_format = VK_FORMAT_R8G8B8A8_SRGB; + m_imageNullDescriptor.m_images[static_cast(ImageTypes::ReadOnlyArray2D)].m_usageFlagBits = VkImageUsageFlagBits(VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); + m_imageNullDescriptor.m_images[static_cast(ImageTypes::ReadOnlyArray2D)].m_arrayLayers = 1; + m_imageNullDescriptor.m_images[static_cast(ImageTypes::ReadOnlyArray2D)].m_imageCreateFlagBits = VkImageCreateFlagBits(0); + m_imageNullDescriptor.m_images[static_cast(ImageTypes::ReadOnlyArray2D)].m_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + m_imageNullDescriptor.m_images[static_cast(ImageTypes::ReadOnlyArray2D)].m_dimension = imageDimension; + + m_imageNullDescriptor.m_images[static_cast(ImageTypes::StorageArray2D)] = m_imageNullDescriptor.m_images[static_cast(NullDescriptorManager::ImageTypes::General2D)]; + m_imageNullDescriptor.m_images[static_cast(ImageTypes::StorageArray2D)].m_name = "NULL_DESCRIPTOR_STORAGE_ARRAY_2D"; + m_imageNullDescriptor.m_images[static_cast(ImageTypes::StorageArray2D)].m_sampleCountFlag = VK_SAMPLE_COUNT_1_BIT; + m_imageNullDescriptor.m_images[static_cast(ImageTypes::StorageArray2D)].m_format = VK_FORMAT_R32G32B32A32_UINT; + m_imageNullDescriptor.m_images[static_cast(ImageTypes::StorageArray2D)].m_usageFlagBits = VkImageUsageFlagBits(VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT); + m_imageNullDescriptor.m_images[static_cast(ImageTypes::StorageArray2D)].m_arrayLayers = 1; + m_imageNullDescriptor.m_images[static_cast(ImageTypes::StorageArray2D)].m_layout = VK_IMAGE_LAYOUT_GENERAL; + m_imageNullDescriptor.m_images[static_cast(ImageTypes::StorageArray2D)].m_dimension = 256; + m_imageNullDescriptor.m_images[static_cast(ImageTypes::GeneralCube)] = m_imageNullDescriptor.m_images[static_cast(NullDescriptorManager::ImageTypes::General2D)]; m_imageNullDescriptor.m_images[static_cast(ImageTypes::GeneralCube)].m_name = "NULL_DESCRIPTOR_GENERAL_CUBE"; m_imageNullDescriptor.m_images[static_cast(ImageTypes::GeneralCube)].m_arrayLayers = 6; @@ -243,6 +272,10 @@ namespace AZ { imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_3D; } + else if (imageIndex >= static_cast(ImageTypes::GeneralArray2D) && imageIndex <= static_cast(ImageTypes::StorageArray2D)) + { + imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY; + } result = vkCreateImageView(device.GetNativeDevice(), &imageViewCreateInfo, nullptr, &m_imageNullDescriptor.m_images[imageIndex].m_view); RETURN_RESULT_IF_UNSUCCESSFUL(ConvertResult(result)); @@ -366,7 +399,7 @@ namespace AZ VkDescriptorImageInfo NullDescriptorManager::GetDescriptorImageInfo(RHI::ShaderInputImageType imageType, bool storageImage) { - if (imageType == RHI::ShaderInputImageType::Image2D || imageType == RHI::ShaderInputImageType::Image2DArray) + if (imageType == RHI::ShaderInputImageType::Image2D) { if (storageImage) { @@ -377,6 +410,17 @@ namespace AZ return GetImage(ImageTypes::ReadOnly2D); } } + else if (imageType == RHI::ShaderInputImageType::Image2DArray) + { + if (storageImage) + { + return GetImage(ImageTypes::StorageArray2D); + } + else + { + return GetImage(ImageTypes::ReadOnlyArray2D); + } + } else if (imageType == RHI::ShaderInputImageType::Image2DMultisample) { if (storageImage) diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/NullDescriptorManager.h b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/NullDescriptorManager.h index 52d12b97c4..e5c4dab22e 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/NullDescriptorManager.h +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/NullDescriptorManager.h @@ -30,6 +30,11 @@ namespace AZ MultiSampleGeneral2D, MultiSampleReadOnly2D, + // 2d image arrays + GeneralArray2D, + ReadOnlyArray2D, + StorageArray2D, + // cube images GeneralCube, ReadOnlyCube, From b5828e327ddf9bbec62c53a990e89b86173c6293 Mon Sep 17 00:00:00 2001 From: Chris Galvan Date: Thu, 12 Aug 2021 11:15:55 -0500 Subject: [PATCH 328/803] Moved custom tree view dragging logic from Entity Outliner to common class so it could be re-used for the UI Editor tree view. Signed-off-by: Chris Galvan --- .../Components/Widgets/TreeView.cpp | 105 ++++++++++++++++++ .../Components/Widgets/TreeView.h | 45 ++++++++ .../UI/Outliner/EntityOutlinerTreeView.cpp | 84 +------------- .../UI/Outliner/EntityOutlinerTreeView.hxx | 9 +- Gems/LyShine/Code/Editor/HierarchyWidget.cpp | 4 +- Gems/LyShine/Code/Editor/HierarchyWidget.h | 4 +- 6 files changed, 165 insertions(+), 86 deletions(-) diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/TreeView.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/TreeView.cpp index 3d0b78ece7..89639ff1d7 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/TreeView.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/TreeView.cpp @@ -8,6 +8,7 @@ #include +#include #include #include #include @@ -252,5 +253,109 @@ namespace AzQtComponents return qobject_cast(widget) && !qobject_cast(widget); } + StyledTreeView::StyledTreeView(QWidget* parent) + : QTreeView(parent) + { + } + + void StyledTreeView::startDrag(Qt::DropActions supportedActions) + { + if (!selectionModel()->selectedIndexes().empty()) + { + StartCustomDrag(selectionModel()->selectedIndexes(), supportedActions); + } + } + + void StyledTreeView::StartCustomDrag(const QModelIndexList& indexList, Qt::DropActions supportedActions) + { + StartCustomDragInternal(this, indexList, supportedActions); + } + + void StyledTreeView::StartCustomDragInternal(QAbstractItemView* itemView, const QModelIndexList& indexList, Qt::DropActions supportedActions) + { + QMimeData* mimeData = itemView->model()->mimeData(indexList); + if (mimeData) + { + QDrag* drag = new QDrag(itemView); + drag->setPixmap(QPixmap::fromImage(CreateDragImage(itemView, indexList))); + drag->setMimeData(mimeData); + + Qt::DropAction defDropAction = Qt::IgnoreAction; + if (itemView->defaultDropAction() != Qt::IgnoreAction && (supportedActions & itemView->defaultDropAction())) + { + defDropAction = itemView->defaultDropAction(); + } + else if (supportedActions & Qt::CopyAction && itemView->dragDropMode() != QAbstractItemView::InternalMove) + { + defDropAction = Qt::CopyAction; + } + + drag->exec(supportedActions, defDropAction); + } + } + + QImage StyledTreeView::CreateDragImage(QAbstractItemView* itemView, const QModelIndexList& indexList) + { + // Generate a drag image of the item icon and text, normally done internally, and inaccessible + QRect rect(0, 0, 0, 0); + for (const auto& index : indexList) + { + if (index.column() != 0) + { + continue; + } + + QRect itemRect = itemView->visualRect(index); + rect.setHeight(rect.height() + itemRect.height()); + rect.setWidth(AZStd::GetMax(rect.width(), itemRect.width())); + } + + QImage dragImage(rect.size(), QImage::Format_ARGB32_Premultiplied); + + QPainter dragPainter(&dragImage); + dragPainter.setCompositionMode(QPainter::CompositionMode_Source); + dragPainter.fillRect(dragImage.rect(), Qt::transparent); + dragPainter.setCompositionMode(QPainter::CompositionMode_SourceOver); + dragPainter.setOpacity(0.35f); + dragPainter.fillRect(rect, QColor("#222222")); + dragPainter.setOpacity(1.0f); + + int imageY = 0; + for (const auto& index : indexList) + { + if (index.column() != 0) + { + continue; + } + + QRect itemRect = itemView->visualRect(index); + dragPainter.drawPixmap(QPoint(0, imageY), + itemView->model()->data(index, Qt::DecorationRole).value().pixmap(QSize(16, 16))); + dragPainter.setPen( + itemView->model()->data(index, Qt::ForegroundRole).value().color()); + dragPainter.setFont( + itemView->font()); + dragPainter.drawText(QRect(20, imageY, rect.width() - 20, rect.height()), + itemView->model()->data(index, Qt::DisplayRole).value()); + imageY += itemRect.height(); + } + + dragPainter.end(); + return dragImage; + } + + StyledTreeWidget::StyledTreeWidget(QWidget* parent) + : QTreeWidget(parent) + { + } + + void StyledTreeWidget::startDrag(Qt::DropActions supportedActions) + { + if (!selectionModel()->selectedIndexes().empty()) + { + StyledTreeView::StartCustomDragInternal(this, selectionModel()->selectedIndexes(), supportedActions); + } + } + } // namespace AzQtComponents #include diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/TreeView.h b/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/TreeView.h index 8fdcc24a8b..7510819e23 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/TreeView.h +++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/TreeView.h @@ -9,8 +9,11 @@ #pragma once #if !defined(Q_MOC_RUN) +#include #include #include + +#include #endif namespace AzQtComponents @@ -68,4 +71,46 @@ namespace AzQtComponents void updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const override; }; + //! For most of the custom QTreeView styling, we override in AzQtComponents::Style class, + //! but there are some cases (e.g. drag/drop) that can only be overriden by an actual + //! subclass of the QTreeView + class AZ_QT_COMPONENTS_API StyledTreeView + : public QTreeView + { + Q_OBJECT + + public: + AZ_CLASS_ALLOCATOR(StyledTreeView, AZ::SystemAllocator, 0); + + explicit StyledTreeView(QWidget* parent = nullptr); + + //! NOTE: QTreeWidget derives from QTreeView, but because we need a custom dervied class + //! of QTreeView, then we can't inherit our custom drag methods in our custom derived + //! class of QTreeWidget, so these functions are made static so they can be shared + static void StartCustomDragInternal(QAbstractItemView* itemView, const QModelIndexList& indexList, Qt::DropActions supportedActions); + static QImage CreateDragImage(QAbstractItemView* itemView, const QModelIndexList& indexList); + + protected: + void startDrag(Qt::DropActions supportedActions) override; + + virtual void StartCustomDrag(const QModelIndexList& indexList, Qt::DropActions supportedActions); + }; + + //! For most of the custom QTreeWidget styling, we override in AzQtComponents::Style class, + //! but there are some cases (e.g. drag/drop) that can only be overriden by an actual + //! subclass of the QTreeWidget. + class AZ_QT_COMPONENTS_API StyledTreeWidget + : public QTreeWidget + { + Q_OBJECT + + public: + AZ_CLASS_ALLOCATOR(StyledTreeWidget, AZ::SystemAllocator, 0); + + explicit StyledTreeWidget(QWidget* parent = nullptr); + + protected: + void startDrag(Qt::DropActions supportedActions) override; + }; + } // namespace AzQtComponents diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerTreeView.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerTreeView.cpp index eaee196c09..0549c600d3 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerTreeView.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerTreeView.cpp @@ -27,7 +27,7 @@ namespace AzToolsFramework { EntityOutlinerTreeView::EntityOutlinerTreeView(QWidget* pParent) - : QTreeView(pParent) + : AzQtComponents::StyledTreeView(pParent) , m_queuedMouseEvent(nullptr) , m_draggingUnselectedItem(false) { @@ -144,16 +144,12 @@ namespace AzToolsFramework if (!selectionModel()->isSelected(index)) { - startCustomDrag({ index }, supportedActions); + StartCustomDrag({ index }, supportedActions); return; } } - if (!selectionModel()->selectedIndexes().empty()) - { - startCustomDrag(selectionModel()->selectedIndexes(), supportedActions); - return; - } + StyledTreeView::startDrag(supportedActions); } void EntityOutlinerTreeView::dragMoveEvent(QDragMoveEvent* event) @@ -243,14 +239,14 @@ namespace AzToolsFramework QTreeView::mousePressEvent(&mousePressedEvent); } - void EntityOutlinerTreeView::startCustomDrag(const QModelIndexList& indexList, Qt::DropActions supportedActions) + void EntityOutlinerTreeView::StartCustomDrag(const QModelIndexList& indexList, Qt::DropActions supportedActions) { m_draggingUnselectedItem = true; //sort by container entity depth and order in hierarchy for proper drag image and drop order QModelIndexList indexListSorted = indexList; AZStd::unordered_map> locations; - for (auto index : indexListSorted) + for (const auto& index : indexListSorted) { AZ::EntityId entityId(index.data(EntityOutlinerListModel::EntityIdRole).value()); AzToolsFramework::GetEntityLocationInHierarchy(entityId, locations[entityId]); @@ -263,76 +259,8 @@ namespace AzToolsFramework return AZStd::lexicographical_compare(locationsE1.begin(), locationsE1.end(), locationsE2.begin(), locationsE2.end()); }); - //get the data for the unselected item(s) - QMimeData* mimeData = model()->mimeData(indexListSorted); - if (mimeData) - { - //initiate drag/drop for the item - QDrag* drag = new QDrag(this); - drag->setPixmap(QPixmap::fromImage(createDragImage(indexListSorted))); - drag->setMimeData(mimeData); - Qt::DropAction defDropAction = Qt::IgnoreAction; - if (defaultDropAction() != Qt::IgnoreAction && (supportedActions & defaultDropAction())) - { - defDropAction = defaultDropAction(); - } - else if (supportedActions & Qt::CopyAction && dragDropMode() != QAbstractItemView::InternalMove) - { - defDropAction = Qt::CopyAction; - } - drag->exec(supportedActions, defDropAction); - } + StyledTreeView::StartCustomDrag(indexListSorted, supportedActions); } - - QImage EntityOutlinerTreeView::createDragImage(const QModelIndexList& indexList) - { - //generate a drag image of the item icon and text, normally done internally, and inaccessible - QRect rect(0, 0, 0, 0); - for (auto index : indexList) - { - if (index.column() != 0) - { - continue; - } - QRect itemRect = visualRect(index); - rect.setHeight(rect.height() + itemRect.height()); - rect.setWidth(AZStd::GetMax(rect.width(), itemRect.width())); - } - - QImage dragImage(rect.size(), QImage::Format_ARGB32_Premultiplied); - - QPainter dragPainter(&dragImage); - dragPainter.setCompositionMode(QPainter::CompositionMode_Source); - dragPainter.fillRect(dragImage.rect(), Qt::transparent); - dragPainter.setCompositionMode(QPainter::CompositionMode_SourceOver); - dragPainter.setOpacity(0.35f); - dragPainter.fillRect(rect, QColor("#222222")); - dragPainter.setOpacity(1.0f); - - int imageY = 0; - for (auto index : indexList) - { - if (index.column() != 0) - { - continue; - } - - QRect itemRect = visualRect(index); - dragPainter.drawPixmap(QPoint(0, imageY), - model()->data(index, Qt::DecorationRole).value().pixmap(QSize(16, 16))); - dragPainter.setPen( - model()->data(index, Qt::ForegroundRole).value().color()); - dragPainter.setFont( - font()); - dragPainter.drawText(QRect(20, imageY, rect.width() - 20, rect.height()), - model()->data(index, Qt::DisplayRole).value()); - imageY += itemRect.height(); - } - - dragPainter.end(); - return dragImage; - } - } #include diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerTreeView.hxx b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerTreeView.hxx index 89471de228..66cd082407 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerTreeView.hxx +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerTreeView.hxx @@ -14,7 +14,8 @@ #include #include -#include + +#include #endif #pragma once @@ -33,7 +34,7 @@ namespace AzToolsFramework //! allow for dragging and dropping of entities from the outliner into the property editor //! of other entities. If the selection updates instantly, this would never be possible. class EntityOutlinerTreeView - : public QTreeView + : public AzQtComponents::StyledTreeView { Q_OBJECT; public: @@ -68,9 +69,7 @@ namespace AzToolsFramework void processQueuedMousePressedEvent(QMouseEvent* event); - void startCustomDrag(const QModelIndexList& indexList, Qt::DropActions supportedActions); - - QImage createDragImage(const QModelIndexList& indexList); + void StartCustomDrag(const QModelIndexList& indexList, Qt::DropActions supportedActions) override; void PaintBranchBackground(QPainter* painter, const QRect& rect, const QModelIndex& index) const; diff --git a/Gems/LyShine/Code/Editor/HierarchyWidget.cpp b/Gems/LyShine/Code/Editor/HierarchyWidget.cpp index 0b56382237..30cb7e51dc 100644 --- a/Gems/LyShine/Code/Editor/HierarchyWidget.cpp +++ b/Gems/LyShine/Code/Editor/HierarchyWidget.cpp @@ -21,7 +21,7 @@ #include HierarchyWidget::HierarchyWidget(EditorWindow* editorWindow) - : QTreeWidget() + : AzQtComponents::StyledTreeWidget() , m_isDeleting(false) , m_editorWindow(editorWindow) , m_entityItemMap() @@ -391,7 +391,7 @@ void HierarchyWidget::startDrag(Qt::DropActions supportedActions) // Remember the current selection so that we can revert back to it when the items are dragged back into the hierarchy m_dragSelection = selectedItems(); - QTreeView::startDrag(supportedActions); + AzQtComponents::StyledTreeWidget::startDrag(supportedActions); } void HierarchyWidget::dragEnterEvent(QDragEnterEvent* event) diff --git a/Gems/LyShine/Code/Editor/HierarchyWidget.h b/Gems/LyShine/Code/Editor/HierarchyWidget.h index 525aaa8a3a..324eda207b 100644 --- a/Gems/LyShine/Code/Editor/HierarchyWidget.h +++ b/Gems/LyShine/Code/Editor/HierarchyWidget.h @@ -10,6 +10,8 @@ #if !defined(Q_MOC_RUN) #include "EditorCommon.h" +#include + #include #include @@ -19,7 +21,7 @@ class QMimeData; class HierarchyWidget - : public QTreeWidget + : public AzQtComponents::StyledTreeWidget , private AzToolsFramework::EditorPickModeNotificationBus::Handler , private AzToolsFramework::EntityHighlightMessages::Bus::Handler { From 117bd0e680d6af8b4f6df98e0d9030f12fb62be3 Mon Sep 17 00:00:00 2001 From: jackalbe <23512001+jackalbe@users.noreply.github.com> Date: Thu, 12 Aug 2021 11:19:15 -0500 Subject: [PATCH 329/803] {LYN-2336} Fix: Python Console script help opens empty (#3060) * {LYN-2336} Fix: Python Console script help opens empty Fixes: Python Console: Script Help opens empty in AutomatedTesting project This fixes the missing Python symbols in the Editor This also fixes the PYI files to write out for the AutomatedTesting project Signed-off-by: Jackson <23512001+jackalbe@users.noreply.github.com> * Fixing proper symbol log execution times Signed-off-by: Jackson <23512001+jackalbe@users.noreply.github.com> * annotating input values with const Signed-off-by: Jackson <23512001+jackalbe@users.noreply.github.com> --- .../Code/Source/PythonLogSymbolsComponent.cpp | 25 ++++++++--- .../Code/Source/PythonLogSymbolsComponent.h | 19 ++++++--- .../Code/Source/PythonProxyBus.cpp | 2 +- .../Code/Source/PythonProxyObject.cpp | 8 ++-- .../Code/Source/PythonReflectionComponent.cpp | 8 ++-- .../Code/Source/PythonSymbolsBus.h | 36 +++++++++++++--- .../Code/Source/PythonSystemComponent.cpp | 42 +++++++++++++++++-- .../Code/Source/PythonSystemComponent.h | 3 ++ 8 files changed, 113 insertions(+), 30 deletions(-) diff --git a/Gems/EditorPythonBindings/Code/Source/PythonLogSymbolsComponent.cpp b/Gems/EditorPythonBindings/Code/Source/PythonLogSymbolsComponent.cpp index 221e1fdcea..d39ca83000 100644 --- a/Gems/EditorPythonBindings/Code/Source/PythonLogSymbolsComponent.cpp +++ b/Gems/EditorPythonBindings/Code/Source/PythonLogSymbolsComponent.cpp @@ -90,6 +90,11 @@ namespace EditorPythonBindings PythonSymbolEventBus::Handler::BusConnect(); EditorPythonBindingsNotificationBus::Handler::BusConnect(); AZ::Interface::Register(this); + + if (PythonSymbolEventBus::GetTotalNumOfEventHandlers() > 1) + { + OnPostInitialize(); + } } void PythonLogSymbolsComponent::Deactivate() @@ -111,6 +116,7 @@ namespace EditorPythonBindings m_basePath = pythonSymbolsPath; } EditorPythonBindingsNotificationBus::Handler::BusDisconnect(); + PythonSymbolEventBus::ExecuteQueuedEvents(); } void PythonLogSymbolsComponent::WriteMethod(AZ::IO::HandleType handle, AZStd::string_view methodName, const AZ::BehaviorMethod& behaviorMethod, const AZ::BehaviorClass* behaviorClass) @@ -206,12 +212,12 @@ namespace EditorPythonBindings AZ::IO::FileIOBase::GetInstance()->Write(handle, buffer.c_str(), buffer.size()); } - void PythonLogSymbolsComponent::LogClass(AZStd::string_view moduleName, AZ::BehaviorClass* behaviorClass) + void PythonLogSymbolsComponent::LogClass(const AZStd::string moduleName, const AZ::BehaviorClass* behaviorClass) { LogClassWithName(moduleName, behaviorClass, behaviorClass->m_name.c_str()); } - void PythonLogSymbolsComponent::LogClassWithName(AZStd::string_view moduleName, AZ::BehaviorClass* behaviorClass, AZStd::string_view className) + void PythonLogSymbolsComponent::LogClassWithName(const AZStd::string moduleName, const AZ::BehaviorClass* behaviorClass, const AZStd::string className) { Internal::FileHandle fileHandle(OpenModuleAt(moduleName)); if (fileHandle.IsValid()) @@ -255,7 +261,11 @@ namespace EditorPythonBindings } } - void PythonLogSymbolsComponent::LogClassMethod(AZStd::string_view moduleName, AZStd::string_view globalMethodName, AZ::BehaviorClass* behaviorClass, AZ::BehaviorMethod* behaviorMethod) + void PythonLogSymbolsComponent::LogClassMethod( + const AZStd::string moduleName, + const AZStd::string globalMethodName, + const AZ::BehaviorClass* behaviorClass, + const AZ::BehaviorMethod* behaviorMethod) { AZ_UNUSED(behaviorClass); Internal::FileHandle fileHandle(OpenModuleAt(moduleName)); @@ -265,7 +275,7 @@ namespace EditorPythonBindings } } - void PythonLogSymbolsComponent::LogBus(AZStd::string_view moduleName, AZStd::string_view busName, AZ::BehaviorEBus* behaviorEBus) + void PythonLogSymbolsComponent::LogBus(const AZStd::string moduleName, const AZStd::string busName, const AZ::BehaviorEBus* behaviorEBus) { if (behaviorEBus->m_events.empty()) { @@ -404,7 +414,7 @@ namespace EditorPythonBindings } } - void PythonLogSymbolsComponent::LogGlobalMethod(AZStd::string_view moduleName, AZStd::string_view methodName, AZ::BehaviorMethod* behaviorMethod) + void PythonLogSymbolsComponent::LogGlobalMethod(const AZStd::string moduleName, const AZStd::string methodName, const AZ::BehaviorMethod* behaviorMethod) { Internal::FileHandle fileHandle(OpenModuleAt(moduleName)); if (fileHandle.IsValid()) @@ -428,7 +438,10 @@ namespace EditorPythonBindings } } - void PythonLogSymbolsComponent::LogGlobalProperty(AZStd::string_view moduleName, AZStd::string_view propertyName, AZ::BehaviorProperty* behaviorProperty) + void PythonLogSymbolsComponent::LogGlobalProperty( + const AZStd::string moduleName, + const AZStd::string propertyName, + const AZ::BehaviorProperty* behaviorProperty) { if (!behaviorProperty->m_getter || !behaviorProperty->m_getter->GetResult()) { diff --git a/Gems/EditorPythonBindings/Code/Source/PythonLogSymbolsComponent.h b/Gems/EditorPythonBindings/Code/Source/PythonLogSymbolsComponent.h index 54285198cf..5fbd1c3f37 100644 --- a/Gems/EditorPythonBindings/Code/Source/PythonLogSymbolsComponent.h +++ b/Gems/EditorPythonBindings/Code/Source/PythonLogSymbolsComponent.h @@ -51,12 +51,19 @@ namespace EditorPythonBindings //////////////////////////////////////////////////////////////////////// // PythonSymbolEventBus::Handler - void LogClass(AZStd::string_view moduleName, AZ::BehaviorClass* behaviorClass) override; - void LogClassWithName(AZStd::string_view moduleName, AZ::BehaviorClass* behaviorClass, AZStd::string_view className) override; - void LogClassMethod(AZStd::string_view moduleName, AZStd::string_view globalMethodName, AZ::BehaviorClass* behaviorClass, AZ::BehaviorMethod* behaviorMethod) override; - void LogBus(AZStd::string_view moduleName, AZStd::string_view busName, AZ::BehaviorEBus* behaviorEBus) override; - void LogGlobalMethod(AZStd::string_view moduleName, AZStd::string_view methodName, AZ::BehaviorMethod* behaviorMethod) override; - void LogGlobalProperty(AZStd::string_view moduleName, AZStd::string_view propertyName, AZ::BehaviorProperty* behaviorProperty) override; + void LogClass(const AZStd::string moduleName, const AZ::BehaviorClass* behaviorClass) override; + void LogClassWithName(const AZStd::string moduleName, const AZ::BehaviorClass* behaviorClass, const AZStd::string className) override; + void LogClassMethod( + const AZStd::string moduleName, + const AZStd::string globalMethodName, + const AZ::BehaviorClass* behaviorClass, + const AZ::BehaviorMethod* behaviorMethod) override; + void LogBus(const AZStd::string moduleName, const AZStd::string busName, const AZ::BehaviorEBus* behaviorEBus) override; + void LogGlobalMethod(const AZStd::string moduleName, const AZStd::string methodName, const AZ::BehaviorMethod* behaviorMethod) override; + void LogGlobalProperty( + const AZStd::string moduleName, + const AZStd::string propertyName, + const AZ::BehaviorProperty* behaviorProperty) override; void Finalize() override; AZStd::string FetchPythonTypeName(const AZ::BehaviorParameter& param) override; diff --git a/Gems/EditorPythonBindings/Code/Source/PythonProxyBus.cpp b/Gems/EditorPythonBindings/Code/Source/PythonProxyBus.cpp index 89f8248202..e640778bbe 100644 --- a/Gems/EditorPythonBindings/Code/Source/PythonProxyBus.cpp +++ b/Gems/EditorPythonBindings/Code/Source/PythonProxyBus.cpp @@ -394,7 +394,7 @@ namespace EditorPythonBindings // log the bus symbol AZStd::string subModuleName = pybind11::cast(thisBusModule.attr("__name__")); - PythonSymbolEventBus::Broadcast(&PythonSymbolEventBus::Events::LogBus, subModuleName, ebusName, behaviorEBus); + PythonSymbolEventBus::QueueBroadcast(&PythonSymbolEventBus::Events::LogBus, subModuleName, ebusName, behaviorEBus); } } diff --git a/Gems/EditorPythonBindings/Code/Source/PythonProxyObject.cpp b/Gems/EditorPythonBindings/Code/Source/PythonProxyObject.cpp index de8009830b..706ca48156 100644 --- a/Gems/EditorPythonBindings/Code/Source/PythonProxyObject.cpp +++ b/Gems/EditorPythonBindings/Code/Source/PythonProxyObject.cpp @@ -756,7 +756,7 @@ namespace EditorPythonBindings } AZStd::string subModuleName = pybind11::cast(subModule.attr("__name__")); - PythonSymbolEventBus::Broadcast(&PythonSymbolEventBus::Events::LogClassMethod, subModuleName, globalMethodName, behaviorClass, behaviorMethod); + PythonSymbolEventBus::QueueBroadcast(&PythonSymbolEventBus::Events::LogClassMethod, subModuleName, globalMethodName, behaviorClass, behaviorMethod); } else { @@ -782,7 +782,7 @@ namespace EditorPythonBindings pybind11::setattr(subModule, constantPropertyName.c_str(), constantValue); AZStd::string subModuleName = pybind11::cast(subModule.attr("__name__")); - PythonSymbolEventBus::Broadcast(&PythonSymbolEventBus::Events::LogGlobalProperty, subModuleName, constantPropertyName, behaviorProperty); + PythonSymbolEventBus::QueueBroadcast(&PythonSymbolEventBus::Events::LogGlobalProperty, subModuleName, constantPropertyName, behaviorProperty); } } @@ -809,11 +809,11 @@ namespace EditorPythonBindings { return ConstructPythonProxyObjectByTypename(behaviorClassName, pythonArgs); }); - PythonSymbolEventBus::Broadcast(&PythonSymbolEventBus::Events::LogClassWithName, subModuleName, behaviorClass, properSyntax); + PythonSymbolEventBus::QueueBroadcast(&PythonSymbolEventBus::Events::LogClassWithName, subModuleName, behaviorClass, properSyntax); } else { - PythonSymbolEventBus::Broadcast(&PythonSymbolEventBus::Events::LogClass, subModuleName, behaviorClass); + PythonSymbolEventBus::QueueBroadcast(&PythonSymbolEventBus::Events::LogClass, subModuleName, behaviorClass); } } } diff --git a/Gems/EditorPythonBindings/Code/Source/PythonReflectionComponent.cpp b/Gems/EditorPythonBindings/Code/Source/PythonReflectionComponent.cpp index 0404e81380..38e00e73ed 100644 --- a/Gems/EditorPythonBindings/Code/Source/PythonReflectionComponent.cpp +++ b/Gems/EditorPythonBindings/Code/Source/PythonReflectionComponent.cpp @@ -153,7 +153,7 @@ namespace EditorPythonBindings StaticPropertyHolderMapEntry& entry = iter->second; entry.second->AddProperty(propertyName, behaviorProperty); } - PythonSymbolEventBus::Broadcast(&PythonSymbolEventBus::Events::LogGlobalProperty, scopeName, propertyName, behaviorProperty); + PythonSymbolEventBus::QueueBroadcast(&PythonSymbolEventBus::Events::LogGlobalProperty, scopeName, propertyName, behaviorProperty); } pybind11::module DetermineScope(pybind11::module scope, const AZStd::string& fullName) @@ -302,7 +302,7 @@ namespace EditorPythonBindings // log global method symbol AZStd::string subModuleName = pybind11::cast(targetModule.attr("__name__")); - PythonSymbolEventBus::Broadcast(&PythonSymbolEventBus::Events::LogGlobalMethod, subModuleName, methodName, behaviorMethod); + PythonSymbolEventBus::QueueBroadcast(&PythonSymbolEventBus::Events::LogGlobalMethod, subModuleName, methodName, behaviorMethod); } } @@ -325,7 +325,7 @@ namespace EditorPythonBindings // log global property symbol AZStd::string subModuleName = pybind11::cast(globalsModule.attr("__name__")); - PythonSymbolEventBus::Broadcast(&PythonSymbolEventBus::Events::LogGlobalProperty, subModuleName, propertyName, behaviorProperty); + PythonSymbolEventBus::QueueBroadcast(&PythonSymbolEventBus::Events::LogGlobalProperty, subModuleName, propertyName, behaviorProperty); if (behaviorProperty->m_getter && behaviorProperty->m_setter) { @@ -377,7 +377,7 @@ namespace EditorPythonBindings PythonProxyBusManagement::CreateSubmodule(parentModule); Internal::RegisterPaths(parentModule); - PythonSymbolEventBus::Broadcast(&PythonSymbolEventBus::Events::Finalize); + PythonSymbolEventBus::QueueBroadcast(&PythonSymbolEventBus::Events::Finalize); } } } diff --git a/Gems/EditorPythonBindings/Code/Source/PythonSymbolsBus.h b/Gems/EditorPythonBindings/Code/Source/PythonSymbolsBus.h index 242225e87a..9c6d3bab37 100644 --- a/Gems/EditorPythonBindings/Code/Source/PythonSymbolsBus.h +++ b/Gems/EditorPythonBindings/Code/Source/PythonSymbolsBus.h @@ -9,6 +9,14 @@ #include +namespace AZ +{ + class BehaviorClass; + class BehaviorMethod; + class BehaviorEBus; + class BehaviorProperty; +} + namespace EditorPythonBindings { //! An interface to track exported Python symbols @@ -16,23 +24,39 @@ namespace EditorPythonBindings : public AZ::EBusTraits { public: + // the symbols will be written out in the future + static const bool EnableEventQueue = true; + //! logs a behavior class type - virtual void LogClass(AZStd::string_view moduleName, AZ::BehaviorClass* behaviorClass) = 0; + virtual void LogClass(const AZStd::string moduleName, const AZ::BehaviorClass* behaviorClass) = 0; //! logs a behavior class type with an override to its name - virtual void LogClassWithName(AZStd::string_view moduleName, AZ::BehaviorClass* behaviorClass, AZStd::string_view className) = 0; + virtual void LogClassWithName( + const AZStd::string moduleName, + const AZ::BehaviorClass* behaviorClass, + const AZStd::string className) = 0; //! logs a static class method with a specified global method name - virtual void LogClassMethod(AZStd::string_view moduleName, AZStd::string_view globalMethodName, AZ::BehaviorClass* behaviorClass, AZ::BehaviorMethod* behaviorMethod) = 0; + virtual void LogClassMethod( + const AZStd::string moduleName, + const AZStd::string globalMethodName, + const AZ::BehaviorClass* behaviorClass, + const AZ::BehaviorMethod* behaviorMethod) = 0; //! logs a behavior bus with a specified bus name - virtual void LogBus(AZStd::string_view moduleName, AZStd::string_view busName, AZ::BehaviorEBus* behaviorEBus) = 0; + virtual void LogBus(const AZStd::string moduleName, const AZStd::string busName, const AZ::BehaviorEBus* behaviorEBus) = 0; //! logs a global method from the behavior context registry with a specified method name - virtual void LogGlobalMethod(AZStd::string_view moduleName, AZStd::string_view methodName, AZ::BehaviorMethod* behaviorMethod) = 0; + virtual void LogGlobalMethod( + const AZStd::string moduleName, + const AZStd::string methodName, + const AZ::BehaviorMethod* behaviorMethod) = 0; //! logs a global property, enum, or constant from the behavior context registry with a specified property name - virtual void LogGlobalProperty(AZStd::string_view moduleName, AZStd::string_view propertyName, AZ::BehaviorProperty* behaviorProperty) = 0; + virtual void LogGlobalProperty( + const AZStd::string moduleName, + const AZStd::string propertyName, + const AZ::BehaviorProperty* behaviorProperty) = 0; //! signals the end of the logging of symbols virtual void Finalize() = 0; diff --git a/Gems/EditorPythonBindings/Code/Source/PythonSystemComponent.cpp b/Gems/EditorPythonBindings/Code/Source/PythonSystemComponent.cpp index 32411e9417..8df196e7cb 100644 --- a/Gems/EditorPythonBindings/Code/Source/PythonSystemComponent.cpp +++ b/Gems/EditorPythonBindings/Code/Source/PythonSystemComponent.cpp @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -25,6 +26,7 @@ #include #include #include +#include #include #include @@ -39,7 +41,7 @@ namespace Platform { - // Implemented in each different platform's implentation files, as it differs per platform. + // Implemented in each different platform's implementation files, as it differs per platform. bool InsertPythonBinaryLibraryPaths(AZStd::unordered_set& paths, const char* pythonPackage, const char* engineRoot); AZStd::string GetPythonHomePath(const char* pythonPackage, const char* engineRoot); } @@ -225,6 +227,37 @@ namespace RedirectOutput namespace EditorPythonBindings { + // A stand in bus to capture the log symbol queue events + // so that when/if the PythonLogSymbolsComponent becomes + // active it can write out the python symbols to disk + class PythonSystemComponent::SymbolLogHelper final + : public PythonSymbolEventBus::Handler + { + public: + SymbolLogHelper() + { + PythonSymbolEventBus::Handler::BusConnect(); + } + + ~SymbolLogHelper() + { + PythonSymbolEventBus::ExecuteQueuedEvents(); + PythonSymbolEventBus::Handler::BusDisconnect(); + } + + void LogClass(const AZStd::string, const AZ::BehaviorClass*) override {} + void LogClassWithName(const AZStd::string, const AZ::BehaviorClass*, const AZStd::string) override {} + void LogClassMethod( + const AZStd::string, + const AZStd::string, + const AZ::BehaviorClass*, + const AZ::BehaviorMethod*) override {} + void LogBus(const AZStd::string, const AZStd::string, const AZ::BehaviorEBus*) override {} + void LogGlobalMethod(const AZStd::string, const AZStd::string, const AZ::BehaviorMethod*) override {} + void LogGlobalProperty(const AZStd::string, const AZStd::string, const AZ::BehaviorProperty*) override {} + void Finalize() override {} + }; + void PythonSystemComponent::Reflect(AZ::ReflectContext* context) { if (AZ::SerializeContext* serialize = azrtti_cast(context)) @@ -471,8 +504,6 @@ namespace EditorPythonBindings } } - - bool PythonSystemComponent::StartPythonInterpreter(const PythonPathStack& pythonPathStack) { AZStd::unordered_set pyPackageSites(pythonPathStack.begin(), pythonPathStack.end()); @@ -520,6 +551,11 @@ namespace EditorPythonBindings AZStd::lock_guard lock(m_lock); pybind11::gil_scoped_acquire acquire; + if (EditorPythonBindings::PythonSymbolEventBus::GetTotalNumOfEventHandlers() == 0) + { + m_symbolLogHelper = AZStd::make_shared(); + } + // print Python version using AZ logging const int verRet = PyRun_SimpleStringFlags("import sys \nprint (sys.version) \n", nullptr); AZ_Error("python", verRet == 0, "Error trying to fetch the version number in Python!"); diff --git a/Gems/EditorPythonBindings/Code/Source/PythonSystemComponent.h b/Gems/EditorPythonBindings/Code/Source/PythonSystemComponent.h index 679da3ccab..48ac27a036 100644 --- a/Gems/EditorPythonBindings/Code/Source/PythonSystemComponent.h +++ b/Gems/EditorPythonBindings/Code/Source/PythonSystemComponent.h @@ -59,10 +59,13 @@ namespace EditorPythonBindings //////////////////////////////////////////////////////////////////////// private: + class SymbolLogHelper; + // handle multiple Python initializers and threads AZStd::atomic_int m_initalizeWaiterCount {0}; AZStd::semaphore m_initalizeWaiter; AZStd::recursive_mutex m_lock; + AZStd::shared_ptr m_symbolLogHelper; enum class Result { From 85d4abae83e3f5954a88c9cf21222a940bfbda34 Mon Sep 17 00:00:00 2001 From: Gene Walters Date: Thu, 12 Aug 2021 09:22:56 -0700 Subject: [PATCH 330/803] Move MultiplayerComponent destructor to cpp (which #includes the controller) so that when it comes time to destroy the unique_ptr it can do so on a complete type. Also, minor spelling error fix Signed-off-by: Gene Walters --- Code/Framework/AzCore/AzCore/RTTI/BehaviorContext.h | 2 +- .../Code/Source/AutoGen/AutoComponent_Header.jinja | 4 ++-- .../Code/Source/AutoGen/AutoComponent_Source.jinja | 4 ++++ 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/RTTI/BehaviorContext.h b/Code/Framework/AzCore/AzCore/RTTI/BehaviorContext.h index 42fc762769..9c37a0b0ed 100644 --- a/Code/Framework/AzCore/AzCore/RTTI/BehaviorContext.h +++ b/Code/Framework/AzCore/AzCore/RTTI/BehaviorContext.h @@ -1855,7 +1855,7 @@ namespace AZ * { * // do any conversion of caching of the "data" here and forward this to behavior (often the reason for this is that you can't pass everything to behavior * // plus behavior can't really handle all constructs pointer to pointer, rvalues, etc. as they don't make sense for most script environments - * int result = 0; // set the default value for your result if the behavior if there is no implmentation + * int result = 0; // set the default value for your result if the behavior if there is no implementation * // The AZ_EBUS_BEHAVIOR_BINDER defines FN_EventName for each index. You can also cache it yourself (but it's slower), static int cacheIndex = GetFunctionIndex("OnEvent1"); and use that . * CallResult(result, FN_OnEvent1, data); // forward to the binding (there can be none, this is why we need to always have properly set result, when there is one) * return result; // return the result like you will in any normal EBus even with result diff --git a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Header.jinja b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Header.jinja index 84fdc9ae54..d92ffdc086 100644 --- a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Header.jinja +++ b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Header.jinja @@ -445,8 +445,8 @@ namespace {{ Component.attrib['Namespace'] }} static AZStd::unique_ptr AllocateComponentInput(); - {{ ComponentBaseName }}() = default; - ~{{ ComponentBaseName }}() override = default; + {{ ComponentBaseName }}(); + ~{{ ComponentBaseName }}() override; void Init() override; void Activate() override; diff --git a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja index d2be2f682a..c8ccc537db 100644 --- a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja +++ b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja @@ -1491,6 +1491,10 @@ namespace {{ Component.attrib['Namespace'] }} {% endif %} } + {{ ComponentBaseName }}::{{ ComponentBaseName }}() = default; + + {{ ComponentBaseName }}::~{{ ComponentBaseName }}() = default; + void {{ ComponentBaseName }}::Init() { if (m_netBindComponent == nullptr) From 538276c99366112e1c8a3d5f585bd70b50abe39d Mon Sep 17 00:00:00 2001 From: Alex Peterson <26804013+AMZN-alexpete@users.noreply.github.com> Date: Thu, 12 Aug 2021 09:32:23 -0700 Subject: [PATCH 331/803] Allow project path changing and auto-completion (#3057) * Allow project path changing and auto-complete Signed-off-by: AMZN-alexpete <26804013+AMZN-alexpete@users.noreply.github.com> * Improved error message regarding the absolute path requirement Signed-off-by: AMZN-alexpete <26804013+AMZN-alexpete@users.noreply.github.com> --- .../Source/NewProjectSettingsScreen.cpp | 31 ++++++++++++++++++- .../Source/NewProjectSettingsScreen.h | 7 +++++ .../Source/ProjectSettingsScreen.cpp | 31 ++++++++++++------- .../Source/ProjectSettingsScreen.h | 7 +++-- .../Source/UpdateProjectSettingsScreen.cpp | 5 +-- 5 files changed, 64 insertions(+), 17 deletions(-) diff --git a/Code/Tools/ProjectManager/Source/NewProjectSettingsScreen.cpp b/Code/Tools/ProjectManager/Source/NewProjectSettingsScreen.cpp index a9086a0c2b..4febb65782 100644 --- a/Code/Tools/ProjectManager/Source/NewProjectSettingsScreen.cpp +++ b/Code/Tools/ProjectManager/Source/NewProjectSettingsScreen.cpp @@ -39,7 +39,7 @@ namespace O3DE::ProjectManager NewProjectSettingsScreen::NewProjectSettingsScreen(QWidget* parent) : ProjectSettingsScreen(parent) { - const QString defaultName{ "NewProject" }; + const QString defaultName = GetDefaultProjectName(); const QString defaultPath = QDir::toNativeSeparators(GetDefaultProjectPath() + "/" + defaultName); m_projectName->lineEdit()->setText(defaultName); @@ -162,6 +162,17 @@ namespace O3DE::ProjectManager return defaultPath; } + QString NewProjectSettingsScreen::GetDefaultProjectName() + { + return "NewProject"; + } + + QString NewProjectSettingsScreen::GetProjectAutoPath() + { + const QString projectName = m_projectName->lineEdit()->text(); + return QDir::toNativeSeparators(GetDefaultProjectPath() + "/" + projectName); + } + ProjectManagerScreen NewProjectSettingsScreen::GetScreenEnum() { return ProjectManagerScreen::NewProjectSettings; @@ -260,4 +271,22 @@ namespace O3DE::ProjectManager m_projectTemplateButtonGroup->blockSignals(false); } } + void NewProjectSettingsScreen::OnProjectNameUpdated() + { + if (ValidateProjectName() && !m_userChangedProjectPath) + { + m_projectPath->setText(GetProjectAutoPath()); + } + } + + void NewProjectSettingsScreen::OnProjectPathUpdated() + { + const QString defaultPath = QDir::toNativeSeparators(GetDefaultProjectPath() + "/" + GetDefaultProjectName()); + const QString autoPath = GetProjectAutoPath(); + const QString path = m_projectPath->lineEdit()->text(); + m_userChangedProjectPath = path != defaultPath && path != autoPath; + + ValidateProjectPath(); + } + } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/NewProjectSettingsScreen.h b/Code/Tools/ProjectManager/Source/NewProjectSettingsScreen.h index ebe40de05c..42c47cb1ff 100644 --- a/Code/Tools/ProjectManager/Source/NewProjectSettingsScreen.h +++ b/Code/Tools/ProjectManager/Source/NewProjectSettingsScreen.h @@ -40,8 +40,14 @@ namespace O3DE::ProjectManager signals: void OnTemplateSelectionChanged(int oldIndex, int newIndex); + protected: + void OnProjectNameUpdated() override; + void OnProjectPathUpdated() override; + private: + QString GetDefaultProjectName(); QString GetDefaultProjectPath(); + QString GetProjectAutoPath(); QFrame* CreateTemplateDetails(int margin); void UpdateTemplateDetails(const ProjectTemplateInfo& templateInfo); @@ -51,6 +57,7 @@ namespace O3DE::ProjectManager TagContainerWidget* m_templateIncludedGems; QVector m_templates; int m_selectedTemplateIndex = -1; + bool m_userChangedProjectPath = false; inline constexpr static int s_spacerSize = 20; inline constexpr static int s_templateDetailsContentMargin = 20; diff --git a/Code/Tools/ProjectManager/Source/ProjectSettingsScreen.cpp b/Code/Tools/ProjectManager/Source/ProjectSettingsScreen.cpp index 4c79117d96..88ae3d6319 100644 --- a/Code/Tools/ProjectManager/Source/ProjectSettingsScreen.cpp +++ b/Code/Tools/ProjectManager/Source/ProjectSettingsScreen.cpp @@ -40,12 +40,11 @@ namespace O3DE::ProjectManager m_verticalLayout->setAlignment(Qt::AlignTop); m_projectName = new FormLineEditWidget(tr("Project name"), "", this); - connect(m_projectName->lineEdit(), &QLineEdit::textChanged, this, &ProjectSettingsScreen::ValidateProjectName); + connect(m_projectName->lineEdit(), &QLineEdit::textChanged, this, &ProjectSettingsScreen::OnProjectNameUpdated); m_verticalLayout->addWidget(m_projectName); m_projectPath = new FormFolderBrowseEditWidget(tr("Project Location"), "", this); - m_projectPath->lineEdit()->setReadOnly(true); - connect(m_projectPath->lineEdit(), &QLineEdit::textChanged, this, &ProjectSettingsScreen::Validate); + connect(m_projectPath->lineEdit(), &QLineEdit::textChanged, this, &ProjectSettingsScreen::OnProjectPathUpdated); m_verticalLayout->addWidget(m_projectPath); projectSettingsFrame->setLayout(m_verticalLayout); @@ -110,28 +109,36 @@ namespace O3DE::ProjectManager m_projectName->setErrorLabelVisible(!projectNameIsValid); return projectNameIsValid; } + bool ProjectSettingsScreen::ValidateProjectPath() { bool projectPathIsValid = true; - if (m_projectPath->lineEdit()->text().isEmpty()) + QDir path(m_projectPath->lineEdit()->text()); + if (!path.isAbsolute()) { projectPathIsValid = false; - m_projectPath->setErrorLabelText(tr("Please provide a valid location.")); + m_projectPath->setErrorLabelText(tr("Please provide an absolute path for the project location.")); } - else + else if (path.exists() && !path.isEmpty()) { - QDir path(m_projectPath->lineEdit()->text()); - if (path.exists() && !path.isEmpty()) - { - projectPathIsValid = false; - m_projectPath->setErrorLabelText(tr("This folder exists and isn't empty. Please choose a different location.")); - } + projectPathIsValid = false; + m_projectPath->setErrorLabelText(tr("This folder exists and isn't empty. Please choose a different location.")); } m_projectPath->setErrorLabelVisible(!projectPathIsValid); return projectPathIsValid; } + void ProjectSettingsScreen::OnProjectNameUpdated() + { + ValidateProjectName(); + } + + void ProjectSettingsScreen::OnProjectPathUpdated() + { + Validate(); + } + bool ProjectSettingsScreen::Validate() { return ValidateProjectName() && ValidateProjectPath(); diff --git a/Code/Tools/ProjectManager/Source/ProjectSettingsScreen.h b/Code/Tools/ProjectManager/Source/ProjectSettingsScreen.h index b2544660e8..752e286ce1 100644 --- a/Code/Tools/ProjectManager/Source/ProjectSettingsScreen.h +++ b/Code/Tools/ProjectManager/Source/ProjectSettingsScreen.h @@ -33,10 +33,13 @@ namespace O3DE::ProjectManager virtual bool Validate(); protected slots: - virtual bool ValidateProjectName(); - virtual bool ValidateProjectPath(); + virtual void OnProjectNameUpdated(); + virtual void OnProjectPathUpdated(); protected: + bool ValidateProjectName(); + virtual bool ValidateProjectPath(); + QString GetDefaultProjectPath(); QHBoxLayout* m_horizontalLayout; diff --git a/Code/Tools/ProjectManager/Source/UpdateProjectSettingsScreen.cpp b/Code/Tools/ProjectManager/Source/UpdateProjectSettingsScreen.cpp index 8e9337bcae..6f7f7e1bed 100644 --- a/Code/Tools/ProjectManager/Source/UpdateProjectSettingsScreen.cpp +++ b/Code/Tools/ProjectManager/Source/UpdateProjectSettingsScreen.cpp @@ -108,10 +108,11 @@ namespace O3DE::ProjectManager bool UpdateProjectSettingsScreen::ValidateProjectPath() { bool projectPathIsValid = true; - if (m_projectPath->lineEdit()->text().isEmpty()) + QDir path(m_projectPath->lineEdit()->text()); + if (!path.isAbsolute()) { projectPathIsValid = false; - m_projectPath->setErrorLabelText(tr("Please provide a valid location.")); + m_projectPath->setErrorLabelText(tr("Please provide an absolute path for the project location.")); } m_projectPath->setErrorLabelVisible(!projectPathIsValid); From 2063e7f2dd205d156df30bbc0eba25f9cd70768a Mon Sep 17 00:00:00 2001 From: Chris Galvan Date: Thu, 12 Aug 2021 11:43:23 -0500 Subject: [PATCH 332/803] Added missing header include. Signed-off-by: Chris Galvan --- .../AzQtComponents/Components/Widgets/TreeView.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/TreeView.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/TreeView.cpp index 89639ff1d7..e4d10a321d 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/TreeView.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/TreeView.cpp @@ -13,6 +13,8 @@ #include #include +#include + #include #include #include From 6d5d042e4054b3b601b2f4131d2ba69be1f48748 Mon Sep 17 00:00:00 2001 From: Junbo Liang <68558268+junbo75@users.noreply.github.com> Date: Thu, 12 Aug 2021 10:05:13 -0700 Subject: [PATCH 333/803] Set the default region for the Resource Mapping Tool when no region is configured via AWS CLI (#2856) Ensure a valid region is always present when generating resource mapping files. --- .../controller/view_edit_controller.py | 11 +++++++++++ .../Code/Tools/ResourceMappingTool/model/constants.py | 1 + .../model/notification_label_text.py | 8 ++++++++ .../unit/controller/test_view_edit_controller.py | 3 ++- 4 files changed, 22 insertions(+), 1 deletion(-) diff --git a/Gems/AWSCore/Code/Tools/ResourceMappingTool/controller/view_edit_controller.py b/Gems/AWSCore/Code/Tools/ResourceMappingTool/controller/view_edit_controller.py index 7e058e6a4e..54d0a29fea 100755 --- a/Gems/AWSCore/Code/Tools/ResourceMappingTool/controller/view_edit_controller.py +++ b/Gems/AWSCore/Code/Tools/ResourceMappingTool/controller/view_edit_controller.py @@ -105,6 +105,8 @@ class ViewEditController(QObject): def _create_new_config_file(self) -> None: configuration: Configuration = self._configuration_manager.configuration + self._set_default_region(configuration) + try: new_config_file_path: str = file_utils.join_path( configuration.config_directory, constants.RESOURCE_MAPPING_DEFAULT_CONFIG_FILE_NAME) @@ -117,6 +119,15 @@ class ViewEditController(QObject): self._rescan_config_directory() + def _set_default_region(self, configuration: Configuration): + default_region = configuration.region + if not default_region or default_region == 'aws-global': + self.set_notification_frame_text_sender.emit( + notification_label_text.VIEW_EDIT_PAGE_CREATE_NEW_CONFIG_FILE_NO_DEFAULT_REGION_MESSAGE) + logger.warning(notification_label_text.VIEW_EDIT_PAGE_CREATE_NEW_CONFIG_FILE_NO_DEFAULT_REGION_MESSAGE) + + configuration.region = constants.RESOURCE_MAPPING_DEFAULT_CONFIG_FILE_REGION + def _delete_table_row(self) -> None: indices: List[QModelIndex] = self._table_view.selectedIndexes() self._proxy_model.remove_resources(indices) diff --git a/Gems/AWSCore/Code/Tools/ResourceMappingTool/model/constants.py b/Gems/AWSCore/Code/Tools/ResourceMappingTool/model/constants.py index 857925499b..94846fc6b5 100755 --- a/Gems/AWSCore/Code/Tools/ResourceMappingTool/model/constants.py +++ b/Gems/AWSCore/Code/Tools/ResourceMappingTool/model/constants.py @@ -24,6 +24,7 @@ AWS_RESOURCE_REGIONS: List[str] = ["us-east-2", "us-east-1", "us-west-1", "us-we # Default client&server config file name RESOURCE_MAPPING_CONFIG_FILE_NAME_SUFFIX: str = "_aws_resource_mappings.json" RESOURCE_MAPPING_DEFAULT_CONFIG_FILE_NAME: str = "default" + RESOURCE_MAPPING_CONFIG_FILE_NAME_SUFFIX +RESOURCE_MAPPING_DEFAULT_CONFIG_FILE_REGION: str = "us-east-1" # View related constants SEARCH_TYPED_RESOURCES_VERSION: str = "Import AWS Resources" diff --git a/Gems/AWSCore/Code/Tools/ResourceMappingTool/model/notification_label_text.py b/Gems/AWSCore/Code/Tools/ResourceMappingTool/model/notification_label_text.py index 4fbff42aba..ecd6d8282c 100755 --- a/Gems/AWSCore/Code/Tools/ResourceMappingTool/model/notification_label_text.py +++ b/Gems/AWSCore/Code/Tools/ResourceMappingTool/model/notification_label_text.py @@ -5,6 +5,8 @@ For complete copyright and license terms please see the LICENSE at the root of t SPDX-License-Identifier: Apache-2.0 OR MIT """ +from model import constants + NOTIFICATION_LOADING_MESSAGE: str = "Loading..." ERROR_PAGE_OK_TEXT: str = "OK" @@ -21,6 +23,12 @@ VIEW_EDIT_PAGE_RESCAN_TEXT: str = "Rescan" VIEW_EDIT_PAGE_CONFIG_FILES_PLACEHOLDER_TEXT: str = "Found {} config files" VIEW_EDIT_PAGE_SEARCH_PLACEHOLDER_TEXT: str = "Search by Key Name, Type, Name/ID, Account ID or Region" VIEW_EDIT_PAGE_IMPORT_RESOURCES_PLACEHOLDER_TEXT: str = "Import Additional Resources" +VIEW_EDIT_PAGE_CREATE_NEW_CONFIG_FILE_NO_DEFAULT_REGION_MESSAGE: str = \ + f"Resource mapping file {constants.RESOURCE_MAPPING_DEFAULT_CONFIG_FILE_NAME} is created"\ + f" with {constants.RESOURCE_MAPPING_DEFAULT_CONFIG_FILE_REGION} as the default region. "\ + f"See "\ + f"documentation "\ + f"for configuring the AWS credentials and default region." VIEW_EDIT_PAGE_SELECT_CONFIG_FILE_MESSAGE: str = "Please select the Config file you would like to view and modify..." VIEW_EDIT_PAGE_NO_CONFIG_FILE_FOUND_MESSAGE: str = \ diff --git a/Gems/AWSCore/Code/Tools/ResourceMappingTool/tests/unit/controller/test_view_edit_controller.py b/Gems/AWSCore/Code/Tools/ResourceMappingTool/tests/unit/controller/test_view_edit_controller.py index d76ae12940..f854d2cd68 100755 --- a/Gems/AWSCore/Code/Tools/ResourceMappingTool/tests/unit/controller/test_view_edit_controller.py +++ b/Gems/AWSCore/Code/Tools/ResourceMappingTool/tests/unit/controller/test_view_edit_controller.py @@ -482,6 +482,7 @@ class TestViewEditController(TestCase): mock_json_utils.create_empty_resource_mapping_file.assert_called_once() mock_file_utils.find_files_with_suffix_under_directory.assert_called_once() self._mocked_view_edit_page.set_config_files.assert_called_with(expected_config_files) + self._test_view_edit_controller.set_notification_frame_text_sender.emit.assert_called_once() @patch("controller.view_edit_controller.file_utils") @patch("controller.view_edit_controller.json_utils") @@ -496,7 +497,7 @@ class TestViewEditController(TestCase): mock_file_utils.join_path.assert_called_once() mock_json_utils.create_empty_resource_mapping_file.assert_called_once() mock_file_utils.find_files_with_suffix_under_directory.assert_not_called() - self._test_view_edit_controller.set_notification_frame_text_sender.emit.assert_called_once() + assert len(self._test_view_edit_controller.set_notification_frame_text_sender.emit.mock_calls) == 2 @patch("controller.view_edit_controller.file_utils") def test_page_rescan_button_post_notification_when_find_files_throw_exception( From 4ceff99ba149547f82b50521e5fae0fef2442d83 Mon Sep 17 00:00:00 2001 From: Chris Galvan Date: Thu, 12 Aug 2021 12:10:13 -0500 Subject: [PATCH 334/803] Prevent EMFX notifications from being modal, which was blocking input while visible. Signed-off-by: Chris Galvan --- .../EMotionStudio/EMStudioSDK/Source/NotificationWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NotificationWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NotificationWindow.cpp index 0b277c6195..a186d94c49 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NotificationWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NotificationWindow.cpp @@ -28,7 +28,7 @@ namespace EMStudio setWindowTitle("Notification"); // window, no border, no focus, stays on top - setWindowFlags(Qt::Popup | Qt::FramelessWindowHint | Qt::WindowDoesNotAcceptFocus); + setWindowFlags(Qt::Window | Qt::FramelessWindowHint | Qt::WindowDoesNotAcceptFocus | Qt::WindowStaysOnTopHint); // enable the translucent background setAttribute(Qt::WA_TranslucentBackground); From fe21b89d8eeca6529e92b0ca852d47593f1632c5 Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Thu, 12 Aug 2021 10:24:16 -0700 Subject: [PATCH 335/803] working support for editor property json serialization Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- .../EditorScriptCanvasComponent.cpp | 9 +++---- .../Framework/ScriptCanvasGraphUtilities.inl | 2 +- .../Execution/RuntimeComponent.cpp | 4 ++-- .../ScriptCanvas/Execution/RuntimeComponent.h | 2 +- .../Serialization/DatumSerializer.cpp | 24 +++---------------- 5 files changed, 10 insertions(+), 31 deletions(-) diff --git a/Gems/ScriptCanvas/Code/Editor/Components/EditorScriptCanvasComponent.cpp b/Gems/ScriptCanvas/Code/Editor/Components/EditorScriptCanvasComponent.cpp index dbc525e8e1..2708f95f92 100644 --- a/Gems/ScriptCanvas/Code/Editor/Components/EditorScriptCanvasComponent.cpp +++ b/Gems/ScriptCanvas/Code/Editor/Components/EditorScriptCanvasComponent.cpp @@ -322,11 +322,9 @@ namespace ScriptCanvasEditor return; } - auto& variableOverrides = parseOutcome.GetValue(); - if (!m_variableOverrides.IsEmpty()) { - variableOverrides.CopyPreviousOverriddenValues(m_variableOverrides); + parseOutcome.GetValue().CopyPreviousOverriddenValues(m_variableOverrides); } m_variableOverrides = parseOutcome.TakeValue(); @@ -351,8 +349,7 @@ namespace ScriptCanvasEditor } auto runtimeComponent = gameEntity->CreateComponent(); - auto runtimeOverrides = ConvertToRuntime(m_variableOverrides); - runtimeComponent->SetRuntimeDataOverrides(runtimeOverrides); + runtimeComponent->TakeRuntimeDataOverrides(ConvertToRuntime(m_variableOverrides)); } void EditorScriptCanvasComponent::OnCatalogAssetAdded(const AZ::Data::AssetId& assetId) @@ -518,8 +515,8 @@ namespace ScriptCanvasEditor [[maybe_unused]] AZ::Entity* scriptCanvasEntity = assetData->GetScriptCanvasEntity(); AZ_Assert(scriptCanvasEntity, "This graph must have a valid entity"); BuildGameEntityData(); - AzToolsFramework::ToolsApplicationNotificationBus::Broadcast(&AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_EntireTree_NewContent); UpdateName(); + AzToolsFramework::ToolsApplicationNotificationBus::Broadcast(&AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_EntireTree_NewContent); } } diff --git a/Gems/ScriptCanvas/Code/Editor/Framework/ScriptCanvasGraphUtilities.inl b/Gems/ScriptCanvas/Code/Editor/Framework/ScriptCanvasGraphUtilities.inl index 4b22864b6e..05541196f7 100644 --- a/Gems/ScriptCanvas/Code/Editor/Framework/ScriptCanvasGraphUtilities.inl +++ b/Gems/ScriptCanvas/Code/Editor/Framework/ScriptCanvasGraphUtilities.inl @@ -283,7 +283,7 @@ namespace ScriptCanvasEditor loadResult.m_runtimeAsset.Get()->GetData().m_debugMap = luaAssetResult.m_debugMap; loadResult.m_runtimeComponent = loadResult.m_entity->CreateComponent(); CopyAssetEntityIdsToOverrides(runtimeDataOverrides); - loadResult.m_runtimeComponent->SetRuntimeDataOverrides(runtimeDataOverrides); + loadResult.m_runtimeComponent->TakeRuntimeDataOverrides(AZStd::move(runtimeDataOverrides)); Execution::Context::InitializeActivationData(loadResult.m_runtimeAsset->GetData()); Execution::InitializeInterpretedStatics(loadResult.m_runtimeAsset->GetData()); } diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/RuntimeComponent.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/RuntimeComponent.cpp index 2d3fd355e2..ac19028fd5 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/RuntimeComponent.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/RuntimeComponent.cpp @@ -93,9 +93,9 @@ namespace ScriptCanvas return m_runtimeOverrides; } - void RuntimeComponent::SetRuntimeDataOverrides(const RuntimeDataOverrides& overrideData) + void RuntimeComponent::TakeRuntimeDataOverrides(RuntimeDataOverrides&& overrideData) { - m_runtimeOverrides = overrideData; + m_runtimeOverrides = AZStd::move(overrideData); m_runtimeOverrides.EnforcePreloadBehavior(); } diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/RuntimeComponent.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/RuntimeComponent.h index 38ff219d4c..8650433b0a 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/RuntimeComponent.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/RuntimeComponent.h @@ -54,7 +54,7 @@ namespace ScriptCanvas const RuntimeDataOverrides& GetRuntimeDataOverrides() const; - void SetRuntimeDataOverrides(const RuntimeDataOverrides& overrideData); + void TakeRuntimeDataOverrides(RuntimeDataOverrides&& overrideData); protected: static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Serialization/DatumSerializer.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Serialization/DatumSerializer.cpp index 207eb842fd..44ca1730a8 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Serialization/DatumSerializer.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Serialization/DatumSerializer.cpp @@ -50,16 +50,6 @@ namespace AZ , "scriptCanvasType" , context)); - ScriptCanvas::Datum::eOriginality originality; - AZ_Assert(azrtti_typeidm_originality)>() == azrtti_typeid() - , "m_originality type changed and won't load properly"); - result.Combine(ContinueLoadingFromJsonObjectField - ( &originality - , azrtti_typeidm_originality)>() - , inputValue - , "originality" - , context)); - AZStd::any storage; { // datum storage begin AZ::Uuid typeId = AZ::Uuid::CreateNull(); @@ -98,10 +88,10 @@ namespace AZ ( &label , azrtti_typeidm_datumLabel)>() , inputValue - , "originality" + , "label" , context)); - Datum copy(scType, originality, AZStd::any_cast(&storage), scType.GetAZType()); + Datum copy(scType, Datum::eOriginality::Original, AZStd::any_cast(&storage), scType.GetAZType()); copy.SetLabel(label); *outputDatum = copy; @@ -152,15 +142,7 @@ namespace AZ , defaultScriptDataPtr ? &defaultScriptDataPtr->GetType() : nullptr , azrtti_typeidGetType())>() , context)); - - result.Combine(ContinueStoringToJsonObjectField - ( outputValue - , "originality" - , &inputScriptDataPtr->m_originality - , defaultScriptDataPtr ? &defaultScriptDataPtr->m_originality : nullptr - , azrtti_typeidm_originality)>() - , context)); - + { // datum storage begin { rapidjson::Value typeValue; From bbe6ff7b905e1d6b02fd2bfd00d2aa9252bc60d8 Mon Sep 17 00:00:00 2001 From: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> Date: Thu, 12 Aug 2021 10:55:32 -0700 Subject: [PATCH 336/803] [redcode/crythread-2nd-pass] re-add LARGE_INTEGER definition to AppleSpecific.h Signed-off-by: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> --- Code/Legacy/CryCommon/AppleSpecific.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Code/Legacy/CryCommon/AppleSpecific.h b/Code/Legacy/CryCommon/AppleSpecific.h index c572250b26..ec7cd8306e 100644 --- a/Code/Legacy/CryCommon/AppleSpecific.h +++ b/Code/Legacy/CryCommon/AppleSpecific.h @@ -458,6 +458,21 @@ typedef HANDLE HMENU; #endif //__cplusplus +typedef union _LARGE_INTEGER +{ + struct + { + DWORD LowPart; + LONG HighPart; + }; + struct + { + DWORD LowPart; + LONG HighPart; + } u; + long long QuadPart; +} LARGE_INTEGER; + extern bool QueryPerformanceCounter(LARGE_INTEGER*); extern bool QueryPerformanceFrequency(LARGE_INTEGER* frequency); From 9579826b5c9cbfe2dfd89074964111dff761c555 Mon Sep 17 00:00:00 2001 From: Vincent Liu <5900509+onecent1101@users.noreply.github.com> Date: Thu, 12 Aug 2021 10:56:51 -0700 Subject: [PATCH 337/803] [SPEC-7971] Update gem module name to match cmake target name (#3055) Fixes for module names so they match cmake target name --- .../Code/AWSGameLiftClient/Source/AWSGameLiftClientModule.cpp | 2 +- .../Code/AWSGameLiftServer/Source/AWSGameLiftServerModule.cpp | 2 +- Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugModule.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/AWSGameLiftClientModule.cpp b/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/AWSGameLiftClientModule.cpp index 4155aaca80..8a9ea5003a 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/AWSGameLiftClientModule.cpp +++ b/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/AWSGameLiftClientModule.cpp @@ -42,4 +42,4 @@ namespace AWSGameLift }; }// namespace AWSGameLift -AZ_DECLARE_MODULE_CLASS(Gem_AWSGameLift_Client, AWSGameLift::AWSGameLiftClientModule) +AZ_DECLARE_MODULE_CLASS(Gem_AWSGameLift_Clients, AWSGameLift::AWSGameLiftClientModule) diff --git a/Gems/AWSGameLift/Code/AWSGameLiftServer/Source/AWSGameLiftServerModule.cpp b/Gems/AWSGameLift/Code/AWSGameLiftServer/Source/AWSGameLiftServerModule.cpp index dfdf541049..9feacafec5 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftServer/Source/AWSGameLiftServerModule.cpp +++ b/Gems/AWSGameLift/Code/AWSGameLiftServer/Source/AWSGameLiftServerModule.cpp @@ -42,4 +42,4 @@ namespace AWSGameLift }; }// namespace AWSGameLift -AZ_DECLARE_MODULE_CLASS(Gem_AWSGameLift_Server, AWSGameLift::AWSGameLiftServerModule) +AZ_DECLARE_MODULE_CLASS(Gem_AWSGameLift_Servers, AWSGameLift::AWSGameLiftServerModule) diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugModule.cpp b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugModule.cpp index b320959dd7..bb80ffad29 100644 --- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugModule.cpp +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugModule.cpp @@ -28,4 +28,4 @@ namespace Multiplayer } } -AZ_DECLARE_MODULE_CLASS(Gem_Multiplayer_Imgui, Multiplayer::MultiplayerDebugModule); +AZ_DECLARE_MODULE_CLASS(Gem_Multiplayer_Debug, Multiplayer::MultiplayerDebugModule); From 28c477997d9e97564424c6afbeccaa915b2bf8b1 Mon Sep 17 00:00:00 2001 From: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> Date: Thu, 12 Aug 2021 10:58:41 -0700 Subject: [PATCH 338/803] [redcode/crythread-2nd-pass] fixed missing iOS include Signed-off-by: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> --- .../GridMate/Platform/iOS/GridMate/Session/LANSession_iOS.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Code/Framework/GridMate/Platform/iOS/GridMate/Session/LANSession_iOS.cpp b/Code/Framework/GridMate/Platform/iOS/GridMate/Session/LANSession_iOS.cpp index 05fb56dfc1..3fa2a369a6 100644 --- a/Code/Framework/GridMate/Platform/iOS/GridMate/Session/LANSession_iOS.cpp +++ b/Code/Framework/GridMate/Platform/iOS/GridMate/Session/LANSession_iOS.cpp @@ -7,6 +7,7 @@ */ #include +#include namespace GridMate { From 72e99dd52b83272f0b57fd48015ead570cdb7dcb Mon Sep 17 00:00:00 2001 From: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> Date: Thu, 12 Aug 2021 11:02:44 -0700 Subject: [PATCH 339/803] [redcode/crythread-2nd-pass] removed platform.h include hack linked to CryThread.h for apple platforms in ILog.h and ISystem.h Signed-off-by: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> --- Code/Legacy/CryCommon/ILog.h | 7 ------- Code/Legacy/CryCommon/ISystem.h | 7 ------- 2 files changed, 14 deletions(-) diff --git a/Code/Legacy/CryCommon/ILog.h b/Code/Legacy/CryCommon/ILog.h index e71e1f036d..23257ea59b 100644 --- a/Code/Legacy/CryCommon/ILog.h +++ b/Code/Legacy/CryCommon/ILog.h @@ -6,13 +6,6 @@ * */ - -// In Mac, including ILog without including platform.h first fails because platform.h -// includes CryThread.h which includes CryThread_pthreads.h which uses ILog. -// So plaform.h needs the contents of ILog.h. -// By including platform.h outside of the guard, we give platform.h the right include order -#include - #ifndef CRYINCLUDE_CRYCOMMON_ILOG_H #define CRYINCLUDE_CRYCOMMON_ILOG_H #pragma once diff --git a/Code/Legacy/CryCommon/ISystem.h b/Code/Legacy/CryCommon/ISystem.h index e0996fc927..ff72c2e60f 100644 --- a/Code/Legacy/CryCommon/ISystem.h +++ b/Code/Legacy/CryCommon/ISystem.h @@ -6,13 +6,6 @@ * */ - -// In Mac, including ISystem without including platform.h first fails because platform.h -// includes CryThread.h which includes CryThread_pthreads.h which uses ISystem (gEnv). -// So plaform.h needs the contents of ISystem.h. -// By including platform.h outside of the guard, we give platform.h the right include order -#include // Needed for LARGE_INTEGER (for consoles). - #ifndef CRYINCLUDE_CRYCOMMON_ISYSTEM_H #define CRYINCLUDE_CRYCOMMON_ISYSTEM_H #pragma once From c9df7c69a45289f0d8512853d184e52e609a855f Mon Sep 17 00:00:00 2001 From: Chris Galvan Date: Thu, 12 Aug 2021 13:20:55 -0500 Subject: [PATCH 340/803] Updated slice entity outliner to use new consolidated StyledTreeView as well. Signed-off-by: Chris Galvan --- .../UI/Outliner/OutlinerTreeView.cpp | 83 ++----------------- .../UI/Outliner/OutlinerTreeView.hxx | 9 +- 2 files changed, 10 insertions(+), 82 deletions(-) diff --git a/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerTreeView.cpp b/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerTreeView.cpp index 017f59cdc3..158e45d6e2 100644 --- a/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerTreeView.cpp +++ b/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerTreeView.cpp @@ -20,7 +20,7 @@ #include OutlinerTreeView::OutlinerTreeView(QWidget* pParent) - : QTreeView(pParent) + : AzQtComponents::StyledTreeView(pParent) , m_queuedMouseEvent(nullptr) , m_draggingUnselectedItem(false) { @@ -135,16 +135,12 @@ void OutlinerTreeView::startDrag(Qt::DropActions supportedActions) if (!selectionModel()->isSelected(index)) { - startCustomDrag({ index }, supportedActions); + StartCustomDrag({ index }, supportedActions); return; } } - if (!selectionModel()->selectedIndexes().empty()) - { - startCustomDrag(selectionModel()->selectedIndexes(), supportedActions); - return; - } + StyledTreeView::startDrag(supportedActions); } void OutlinerTreeView::dragMoveEvent(QDragMoveEvent* event) @@ -336,14 +332,14 @@ void OutlinerTreeView::processQueuedMousePressedEvent(QMouseEvent* event) QTreeView::mousePressEvent(&mousePressedEvent); } -void OutlinerTreeView::startCustomDrag(const QModelIndexList& indexList, Qt::DropActions supportedActions) +void OutlinerTreeView::StartCustomDrag(const QModelIndexList& indexList, Qt::DropActions supportedActions) { m_draggingUnselectedItem = true; //sort by container entity depth and order in hierarchy for proper drag image and drop order QModelIndexList indexListSorted = indexList; AZStd::unordered_map> locations; - for (auto index : indexListSorted) + for (const auto& index : indexListSorted) { AZ::EntityId entityId(index.data(OutlinerListModel::EntityIdRole).value()); AzToolsFramework::GetEntityLocationInHierarchy(entityId, locations[entityId]); @@ -356,74 +352,7 @@ void OutlinerTreeView::startCustomDrag(const QModelIndexList& indexList, Qt::Dro return AZStd::lexicographical_compare(locationsE1.begin(), locationsE1.end(), locationsE2.begin(), locationsE2.end()); }); - //get the data for the unselected item(s) - QMimeData* mimeData = model()->mimeData(indexListSorted); - if (mimeData) - { - //initiate drag/drop for the item - QDrag* drag = new QDrag(this); - drag->setPixmap(QPixmap::fromImage(createDragImage(indexListSorted))); - drag->setMimeData(mimeData); - Qt::DropAction defDropAction = Qt::IgnoreAction; - if (defaultDropAction() != Qt::IgnoreAction && (supportedActions & defaultDropAction())) - { - defDropAction = defaultDropAction(); - } - else if (supportedActions & Qt::CopyAction && dragDropMode() != QAbstractItemView::InternalMove) - { - defDropAction = Qt::CopyAction; - } - drag->exec(supportedActions, defDropAction); - } -} - -QImage OutlinerTreeView::createDragImage(const QModelIndexList& indexList) -{ - //generate a drag image of the item icon and text, normally done internally, and inaccessible - QRect rect(0, 0, 0, 0); - for (auto index : indexList) - { - if (index.column() != 0) - { - continue; - } - QRect itemRect = visualRect(index); - rect.setHeight(rect.height() + itemRect.height()); - rect.setWidth(AZStd::GetMax(rect.width(), itemRect.width())); - } - - QImage dragImage(rect.size(), QImage::Format_ARGB32_Premultiplied); - - QPainter dragPainter(&dragImage); - dragPainter.setCompositionMode(QPainter::CompositionMode_Source); - dragPainter.fillRect(dragImage.rect(), Qt::transparent); - dragPainter.setCompositionMode(QPainter::CompositionMode_SourceOver); - dragPainter.setOpacity(0.35f); - dragPainter.fillRect(rect, QColor("#222222")); - dragPainter.setOpacity(1.0f); - - int imageY = 0; - for (auto index : indexList) - { - if (index.column() != 0) - { - continue; - } - - QRect itemRect = visualRect(index); - dragPainter.drawPixmap(QPoint(0, imageY), - model()->data(index, Qt::DecorationRole).value().pixmap(QSize(16, 16))); - dragPainter.setPen( - model()->data(index, Qt::ForegroundRole).value().color()); - dragPainter.setFont( - font()); - dragPainter.drawText(QRect(20, imageY, rect.width() - 20, rect.height()), - model()->data(index, Qt::DisplayRole).value()); - imageY += itemRect.height(); - } - - dragPainter.end(); - return dragImage; + StyledTreeView::StartCustomDrag(indexListSorted, supportedActions); } #include diff --git a/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerTreeView.hxx b/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerTreeView.hxx index fe7a494be4..b597b70092 100644 --- a/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerTreeView.hxx +++ b/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerTreeView.hxx @@ -15,7 +15,8 @@ #include #include -#include + +#include #endif #pragma once @@ -31,7 +32,7 @@ class OutlinerTreeViewModel; //! allow for dragging and dropping of entities from the outliner into the property editor //! of other entities. If the selection updates instantly, this would never be possible. class OutlinerTreeView - : public QTreeView + : public AzQtComponents::StyledTreeView { Q_OBJECT; public: @@ -66,9 +67,7 @@ private: void processQueuedMousePressedEvent(QMouseEvent* event); - void startCustomDrag(const QModelIndexList& indexList, Qt::DropActions supportedActions); - - QImage createDragImage(const QModelIndexList& indexList); + void StartCustomDrag(const QModelIndexList& indexList, Qt::DropActions supportedActions) override; void DrawLayerUI(QPainter* painter, const QRect& rect, const QModelIndex& index) const; From c2b8542bbd0e4e71fa9d77877607ff9c76e152b4 Mon Sep 17 00:00:00 2001 From: moudgils <47460854+moudgils@users.noreply.github.com> Date: Thu, 12 Aug 2021 12:07:46 -0700 Subject: [PATCH 341/803] Support for refresh rate and sync interval (#2989) * Add support for querying the refresh rate and sync interval --- .../AzFramework/Windowing/NativeWindow.cpp | 27 +++++++++++++++++++ .../AzFramework/Windowing/NativeWindow.h | 3 +++ .../AzFramework/Windowing/WindowBus.h | 9 +++++++ .../Windowing/NativeWindow_Android.cpp | 7 ++++- .../Windowing/NativeWindow_Linux.cpp | 6 +++++ .../AzFramework/Windowing/NativeWindow_Mac.mm | 18 +++++++++++++ .../Windowing/NativeWindow_Windows.cpp | 20 ++++++++++++++ .../AzFramework/Windowing/NativeWindow_ios.mm | 9 ++++++- Gems/Atom/RHI/Code/Include/Atom/RHI/Device.h | 1 - .../Windows/RHI/NsightAftermath_Windows.cpp | 2 +- .../Source/Platform/Mac/RHI/Conversions_Mac.h | 2 ++ .../Source/Platform/iOS/RHI/Conversions_iOS.h | 2 ++ .../Atom/RHI/Metal/Code/Source/RHI/Device.cpp | 1 - .../RHI/Metal/Code/Source/RHI/SwapChain.cpp | 18 ++++++------- .../RHI/Metal/Code/Source/RHI/SwapChain.h | 2 +- .../Code/Source/RPI.Public/WindowContext.cpp | 19 ++++--------- .../Viewport/RenderViewportWidget.h | 2 ++ .../Source/Viewport/RenderViewportWidget.cpp | 10 +++++++ 18 files changed, 128 insertions(+), 30 deletions(-) diff --git a/Code/Framework/AzFramework/AzFramework/Windowing/NativeWindow.cpp b/Code/Framework/AzFramework/AzFramework/Windowing/NativeWindow.cpp index df1549cc31..c89d12a8ae 100644 --- a/Code/Framework/AzFramework/AzFramework/Windowing/NativeWindow.cpp +++ b/Code/Framework/AzFramework/AzFramework/Windowing/NativeWindow.cpp @@ -10,6 +10,17 @@ #include +void OnVsyncIntervalChanged(uint32_t const& interval) +{ + AzFramework::WindowNotificationBus::Broadcast( + &AzFramework::WindowNotificationBus::Events::OnVsyncIntervalChanged, AZ::GetClamp(interval, 0u, 4u)); +} + +// NOTE: On change, broadcasts the new requested vsync interval to all windows. +// The value of the vsync interval is constrained between 0 and 4 +// Vsync intervals greater than 1 are not currently supported on the Vulkan RHI (see #2061 for discussion) +AZ_CVAR(uint32_t, vsync_interval, 1, OnVsyncIntervalChanged, AZ::ConsoleFunctorFlags::Null, "Set swapchain vsync interval"); + namespace AzFramework { ////////////////////////////////////////////////////////////////////////// @@ -122,6 +133,16 @@ namespace AzFramework return m_pimpl->GetDpiScaleFactor(); } + uint32_t NativeWindow::GetDisplayRefreshRate() const + { + return m_pimpl->GetDisplayRefreshRate(); + } + + uint32_t NativeWindow::GetSyncInterval() const + { + return vsync_interval; + } + /*static*/ bool NativeWindow::GetFullScreenStateOfDefaultWindow() { NativeWindowHandle defaultWindowHandle = nullptr; @@ -240,4 +261,10 @@ namespace AzFramework return 1.0f; } + uint32_t NativeWindow::Implementation::GetDisplayRefreshRate() const + { + // Default to 60 + return 60; + } + } // namespace AzFramework diff --git a/Code/Framework/AzFramework/AzFramework/Windowing/NativeWindow.h b/Code/Framework/AzFramework/AzFramework/Windowing/NativeWindow.h index 52157d920f..7479b0d1e1 100644 --- a/Code/Framework/AzFramework/AzFramework/Windowing/NativeWindow.h +++ b/Code/Framework/AzFramework/AzFramework/Windowing/NativeWindow.h @@ -130,6 +130,8 @@ namespace AzFramework bool CanToggleFullScreenState() const override; void ToggleFullScreenState() override; float GetDpiScaleFactor() const override; + uint32_t GetSyncInterval() const override; + uint32_t GetDisplayRefreshRate() const override; //! Get the full screen state of the default window. //! \return True if the default window is currently in full screen, false otherwise. @@ -172,6 +174,7 @@ namespace AzFramework virtual void SetFullScreenState(bool fullScreenState); virtual bool CanToggleFullScreenState() const; virtual float GetDpiScaleFactor() const; + virtual uint32_t GetDisplayRefreshRate() const; protected: uint32_t m_width = 0; diff --git a/Code/Framework/AzFramework/AzFramework/Windowing/WindowBus.h b/Code/Framework/AzFramework/AzFramework/Windowing/WindowBus.h index 776cd43787..d3bd0ce82c 100644 --- a/Code/Framework/AzFramework/AzFramework/Windowing/WindowBus.h +++ b/Code/Framework/AzFramework/AzFramework/Windowing/WindowBus.h @@ -74,6 +74,12 @@ namespace AzFramework //! to a "standard" value of 96, the default for Windows in a DPI unaware setting. This can //! be used to scale user interface elements to ensure legibility on high density displays. virtual float GetDpiScaleFactor() const = 0; + + //! Returns the sync interval which tells the drivers the number of v-blanks to synchronize with + virtual uint32_t GetSyncInterval() const = 0; + + //! Returns the refresh rate of the main display + virtual uint32_t GetDisplayRefreshRate() const = 0; }; using WindowRequestBus = AZ::EBus; @@ -101,6 +107,9 @@ namespace AzFramework //! This is called when vsync interval is changed. virtual void OnVsyncIntervalChanged(uint32_t interval) { AZ_UNUSED(interval); }; + + //! This is called if the main display's refresh rate changes + virtual void OnRefreshRateChanged([[maybe_unused]] uint32_t refreshRate) {} }; using WindowNotificationBus = AZ::EBus; diff --git a/Code/Framework/AzFramework/Platform/Android/AzFramework/Windowing/NativeWindow_Android.cpp b/Code/Framework/AzFramework/Platform/Android/AzFramework/Windowing/NativeWindow_Android.cpp index 8da63e9a5e..e655435011 100644 --- a/Code/Framework/AzFramework/Platform/Android/AzFramework/Windowing/NativeWindow_Android.cpp +++ b/Code/Framework/AzFramework/Platform/Android/AzFramework/Windowing/NativeWindow_Android.cpp @@ -25,7 +25,7 @@ namespace AzFramework const WindowGeometry& geometry, const WindowStyleMasks& styleMasks) override; NativeWindowHandle GetWindowHandle() const override; - + uint32_t GetDisplayRefreshRate() const override; private: ANativeWindow* m_nativeWindow = nullptr; }; @@ -55,4 +55,9 @@ namespace AzFramework return reinterpret_cast(m_nativeWindow); } + uint32_t NativeWindowImpl_Android::GetDisplayRefreshRate() const + { + // Using 60 for now until proper support is added + return 60; + } } // namespace AzFramework diff --git a/Code/Framework/AzFramework/Platform/Linux/AzFramework/Windowing/NativeWindow_Linux.cpp b/Code/Framework/AzFramework/Platform/Linux/AzFramework/Windowing/NativeWindow_Linux.cpp index 5d738f8bdd..0ab1281eda 100644 --- a/Code/Framework/AzFramework/Platform/Linux/AzFramework/Windowing/NativeWindow_Linux.cpp +++ b/Code/Framework/AzFramework/Platform/Linux/AzFramework/Windowing/NativeWindow_Linux.cpp @@ -23,6 +23,7 @@ namespace AzFramework const WindowGeometry& geometry, const WindowStyleMasks& styleMasks) override; NativeWindowHandle GetWindowHandle() const override; + uint32_t GetDisplayRefreshRate() const override; }; NativeWindow::Implementation* NativeWindow::Implementation::Create() @@ -44,4 +45,9 @@ namespace AzFramework return nullptr; } + uint32_t NativeWindowImpl_Linux::GetDisplayRefreshRate() const + { + //Using 60 for now until proper support is added + return 60; + } } // namespace AzFramework diff --git a/Code/Framework/AzFramework/Platform/Mac/AzFramework/Windowing/NativeWindow_Mac.mm b/Code/Framework/AzFramework/Platform/Mac/AzFramework/Windowing/NativeWindow_Mac.mm index 6e6b801e79..2f9e3ab934 100644 --- a/Code/Framework/AzFramework/Platform/Mac/AzFramework/Windowing/NativeWindow_Mac.mm +++ b/Code/Framework/AzFramework/Platform/Mac/AzFramework/Windowing/NativeWindow_Mac.mm @@ -34,12 +34,14 @@ namespace AzFramework bool GetFullScreenState() const override; void SetFullScreenState(bool fullScreenState) override; bool CanToggleFullScreenState() const override { return true; } + uint32_t GetMainDisplayRefreshRate() const override; private: static NSWindowStyleMask ConvertToNSWindowStyleMask(const WindowStyleMasks& styleMasks); NSWindow* m_nativeWindow; NSString* m_windowTitle; + uint32_t m_mainDisplayRefreshRate = 0; }; NativeWindow::Implementation* NativeWindow::Implementation::Create() @@ -76,6 +78,17 @@ namespace AzFramework // Make the window active [m_nativeWindow makeKeyAndOrderFront:nil]; m_nativeWindow.title = m_windowTitle; + + CGDirectDisplayID display = CGMainDisplayID(); + CGDisplayModeRef currentMode = CGDisplayCopyDisplayMode(display); + m_mainDisplayRefreshRate = CGDisplayModeGetRefreshRate(currentMode); + + // Assume 60hz if 0 is returned. + // This can happen on OSX. In future we can hopefully use maximumFramesPerSecond which wont have this issue + if (m_mainDisplayRefreshRate == 0) + { + m_mainDisplayRefreshRate = 60; + } } NativeWindowHandle NativeWindowImpl_Darwin::GetWindowHandle() const @@ -128,4 +141,9 @@ namespace AzFramework const NSWindowStyleMask defaultMask = NSWindowStyleMaskResizable | NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable; return nativeMask ? nativeMask : defaultMask; } + + uint32_t NativeWindowImpl_Darwin::GetMainDisplayRefreshRate() const + { + return m_mainDisplayRefreshRate; + } } // namespace AzFramework diff --git a/Code/Framework/AzFramework/Platform/Windows/AzFramework/Windowing/NativeWindow_Windows.cpp b/Code/Framework/AzFramework/Platform/Windows/AzFramework/Windowing/NativeWindow_Windows.cpp index 22a293891c..2c1d97dcf6 100644 --- a/Code/Framework/AzFramework/Platform/Windows/AzFramework/Windowing/NativeWindow_Windows.cpp +++ b/Code/Framework/AzFramework/Platform/Windows/AzFramework/Windowing/NativeWindow_Windows.cpp @@ -37,6 +37,7 @@ namespace AzFramework void SetFullScreenState(bool fullScreenState) override; bool CanToggleFullScreenState() const override { return true; } float GetDpiScaleFactor() const override; + uint32_t GetDisplayRefreshRate() const override; private: static DWORD ConvertToWin32WindowStyleMask(const WindowStyleMasks& styleMasks); @@ -56,6 +57,7 @@ namespace AzFramework using GetDpiForWindowType = UINT(HWND hwnd); GetDpiForWindowType* m_getDpiFunction = nullptr; + uint32_t m_mainDisplayRefreshRate = 0; }; const wchar_t* NativeWindowImpl_Win32::s_defaultClassName = L"O3DEWin32Class"; @@ -144,6 +146,10 @@ namespace AzFramework { SetWindowLongPtr(m_win32Handle, GWLP_USERDATA, reinterpret_cast(this)); } + + DEVMODE DisplayConfig; + EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &DisplayConfig); + m_mainDisplayRefreshRate = DisplayConfig.dmDisplayFrequency; } void NativeWindowImpl_Win32::Activate() @@ -263,6 +269,15 @@ namespace AzFramework WindowNotificationBus::Event(nativeWindowImpl->GetWindowHandle(), &WindowNotificationBus::Events::OnDpiScaleFactorChanged, newScaleFactor); break; } + case WM_WINDOWPOSCHANGED: + { + DEVMODE DisplayConfig; + EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &DisplayConfig); + uint32_t refreshRate = DisplayConfig.dmDisplayFrequency; + WindowNotificationBus::Event( + nativeWindowImpl->GetWindowHandle(), &WindowNotificationBus::Events::OnRefreshRateChanged, refreshRate); + break; + } default: return DefWindowProc(hWnd, message, wParam, lParam); break; @@ -367,6 +382,11 @@ namespace AzFramework return aznumeric_cast(dotsPerInch) / aznumeric_cast(defaultDotsPerInch); } + uint32_t NativeWindowImpl_Win32::GetDisplayRefreshRate() const + { + return m_mainDisplayRefreshRate; + } + void NativeWindowImpl_Win32::EnterBorderlessWindowFullScreen() { if (m_isInBorderlessWindowFullScreenState) diff --git a/Code/Framework/AzFramework/Platform/iOS/AzFramework/Windowing/NativeWindow_ios.mm b/Code/Framework/AzFramework/Platform/iOS/AzFramework/Windowing/NativeWindow_ios.mm index b14db37d23..3c829ec055 100644 --- a/Code/Framework/AzFramework/Platform/iOS/AzFramework/Windowing/NativeWindow_ios.mm +++ b/Code/Framework/AzFramework/Platform/iOS/AzFramework/Windowing/NativeWindow_ios.mm @@ -27,9 +27,11 @@ namespace AzFramework const WindowGeometry& geometry, const WindowStyleMasks& styleMasks) override; NativeWindowHandle GetWindowHandle() const override; - + uint32_t GetMainDisplayRefreshRate() const override; + private: UIWindow* m_nativeWindow; + uint32_t m_mainDisplayRefreshRate = 0; }; NativeWindow::Implementation* NativeWindow::Implementation::Create() @@ -56,6 +58,7 @@ namespace AzFramework m_width = geometry.m_width; m_height = geometry.m_height; + m_mainDisplayRefreshRate = [[UIScreen mainScreen] maximumFramesPerSecond]; } NativeWindowHandle NativeWindowImpl_Ios::GetWindowHandle() const @@ -63,5 +66,9 @@ namespace AzFramework return m_nativeWindow; } + uint32_t NativeWindowImpl_Ios::GetMainDisplayRefreshRate() const + { + return m_mainDisplayRefreshRate; + } } // namespace AzFramework diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/Device.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/Device.h index 4232658980..e7ad98c074 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/Device.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/Device.h @@ -125,7 +125,6 @@ namespace AZ Format GetNearestSupportedFormat(Format requestedFormat, FormatCapabilities requestedCapabilities) const; //! Small API to support getting supported/working swapchain formats for a window. - //! [GFX TODO]ATOM-1125] [RHI] Device::GetValidSwapChainImageFormats() //! Returns the set of supported formats for swapchain images. virtual AZStd::vector GetValidSwapChainImageFormats(const WindowHandle& windowHandle) const; diff --git a/Gems/Atom/RHI/DX12/Code/Source/Platform/Windows/RHI/NsightAftermath_Windows.cpp b/Gems/Atom/RHI/DX12/Code/Source/Platform/Windows/RHI/NsightAftermath_Windows.cpp index 4ee35b7675..199efbb139 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/Platform/Windows/RHI/NsightAftermath_Windows.cpp +++ b/Gems/Atom/RHI/DX12/Code/Source/Platform/Windows/RHI/NsightAftermath_Windows.cpp @@ -85,7 +85,7 @@ namespace Aftermath #if defined(USE_NSIGHT_AFTERMATH) AZStd::vector cntxtHandles = static_cast(crashTracker)->GetContextHandles(); GFSDK_Aftermath_ContextData* outContextData = new GFSDK_Aftermath_ContextData[cntxtHandles.size()]; - GFSDK_Aftermath_Result result = GFSDK_Aftermath_GetData(cntxtHandles.size(), cntxtHandles.data(), outContextData); + GFSDK_Aftermath_Result result = GFSDK_Aftermath_GetData(static_cast(cntxtHandles.size()), cntxtHandles.data(), outContextData); AssertOnError(result); for (int i = 0; i < cntxtHandles.size(); i++) { diff --git a/Gems/Atom/RHI/Metal/Code/Source/Platform/Mac/RHI/Conversions_Mac.h b/Gems/Atom/RHI/Metal/Code/Source/Platform/Mac/RHI/Conversions_Mac.h index cb1f48cfea..a4dc13a6f1 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/Platform/Mac/RHI/Conversions_Mac.h +++ b/Gems/Atom/RHI/Metal/Code/Source/Platform/Mac/RHI/Conversions_Mac.h @@ -5,6 +5,8 @@ * SPDX-License-Identifier: Apache-2.0 OR MIT * */ +#pragma once + namespace AZ { namespace Metal diff --git a/Gems/Atom/RHI/Metal/Code/Source/Platform/iOS/RHI/Conversions_iOS.h b/Gems/Atom/RHI/Metal/Code/Source/Platform/iOS/RHI/Conversions_iOS.h index cb1f48cfea..a4dc13a6f1 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/Platform/iOS/RHI/Conversions_iOS.h +++ b/Gems/Atom/RHI/Metal/Code/Source/Platform/iOS/RHI/Conversions_iOS.h @@ -5,6 +5,8 @@ * SPDX-License-Identifier: Apache-2.0 OR MIT * */ +#pragma once + namespace AZ { namespace Metal diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/Device.cpp b/Gems/Atom/RHI/Metal/Code/Source/RHI/Device.cpp index dbd2204e93..5591bcc843 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/Device.cpp +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/Device.cpp @@ -77,7 +77,6 @@ namespace AZ m_samplerCache = [[NSCache alloc]init]; [m_samplerCache setName:@"SamplerCache"]; - return RHI::ResultCode::Success; } diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/SwapChain.cpp b/Gems/Atom/RHI/Metal/Code/Source/RHI/SwapChain.cpp index 638f9bd184..df0961564d 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/SwapChain.cpp +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/SwapChain.cpp @@ -74,21 +74,16 @@ namespace AZ AddSubView(); } - m_refreshRate = Platform::GetRefreshRate(); - - //Assume 60hz if 0 is returned. - //Internal OSX displays have 'flexible' refresh rates, with a max of 60Hz - but report 0hz - if (m_refreshRate < 0.1f) - { - m_refreshRate = 60.0f; - } - m_drawables.resize(descriptor.m_dimensions.m_imageCount); if (nativeDimensions) { *nativeDimensions = descriptor.m_dimensions; } + + AzFramework::WindowRequestBus::EventResult( + m_refreshRate, m_nativeWindow, &AzFramework::WindowRequestBus::Events::GetDisplayRefreshRate); + return RHI::ResultCode::Success; } @@ -160,7 +155,10 @@ namespace AZ const uint32_t currentImageIndex = GetCurrentImageIndex(); //Preset the drawable - Platform::PresentInternal(m_mtlCommandBuffer, m_drawables[currentImageIndex], GetDescriptor().m_verticalSyncInterval, m_refreshRate); + Platform::PresentInternal( + m_mtlCommandBuffer, + m_drawables[currentImageIndex], GetDescriptor().m_verticalSyncInterval, + m_refreshRate); [m_drawables[currentImageIndex] release]; m_drawables[currentImageIndex] = nil; diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/SwapChain.h b/Gems/Atom/RHI/Metal/Code/Source/RHI/SwapChain.h index 571f12faf8..51dfe9258b 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/SwapChain.h +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/SwapChain.h @@ -53,7 +53,7 @@ namespace AZ id m_mtlDevice = nil; NativeWindowType* m_nativeWindow = nullptr; AZStd::vector> m_drawables; - float m_refreshRate = 0.0f; + uint32_t m_refreshRate = 0; }; } } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/WindowContext.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/WindowContext.cpp index 7c269b86d4..9720a88176 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/WindowContext.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/WindowContext.cpp @@ -17,19 +17,6 @@ #include #include - -void OnVsyncIntervalChanged(uint32_t const& interval) -{ - AzFramework::WindowNotificationBus::Broadcast( - &AzFramework::WindowNotificationBus::Events::OnVsyncIntervalChanged, - AZ::GetClamp(interval, 0u, 4u)); -} - -// NOTE: On change, broadcasts the new requested vsync interval to all windows. -// The value of the vsync interval is constrained between 0 and 4 -// Vsync intervals greater than 1 are not currently supported on the Vulkan RHI (see #2061 for discussion) -AZ_CVAR(uint32_t, rpi_vsync_interval, 1, OnVsyncIntervalChanged, AZ::ConsoleFunctorFlags::Null, "Set swapchain vsync interval"); - namespace AZ { namespace RPI @@ -158,9 +145,13 @@ namespace AZ const RHI::WindowHandle windowHandle = RHI::WindowHandle(reinterpret_cast(m_windowHandle)); + uint32_t syncInterval = 1; + AzFramework::WindowRequestBus::EventResult( + syncInterval, m_windowHandle, &AzFramework::WindowRequestBus::Events::GetSyncInterval); + RHI::SwapChainDescriptor descriptor; descriptor.m_window = windowHandle; - descriptor.m_verticalSyncInterval = rpi_vsync_interval; + descriptor.m_verticalSyncInterval = syncInterval; descriptor.m_dimensions.m_imageWidth = width; descriptor.m_dimensions.m_imageHeight = height; descriptor.m_dimensions.m_imageCount = 3; diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/RenderViewportWidget.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/RenderViewportWidget.h index cd670f3048..bb26e116af 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/RenderViewportWidget.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/RenderViewportWidget.h @@ -121,6 +121,8 @@ namespace AtomToolsFramework bool CanToggleFullScreenState() const override; void ToggleFullScreenState() override; float GetDpiScaleFactor() const override; + uint32_t GetSyncInterval() const override; + uint32_t GetDisplayRefreshRate() const; protected: // AzFramework::InputChannelEventListener ... diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/RenderViewportWidget.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/RenderViewportWidget.cpp index 5167e3d3f6..bf356d2b99 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/RenderViewportWidget.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/RenderViewportWidget.cpp @@ -465,4 +465,14 @@ namespace AtomToolsFramework { return aznumeric_cast(devicePixelRatioF()); } + + uint32_t RenderViewportWidget::GetDisplayRefreshRate() const + { + return 60; + } + + uint32_t RenderViewportWidget::GetSyncInterval() const + { + return 1; + } } //namespace AtomToolsFramework From cc3d2e9969cfc2f3ba00ebeaa9405d1d1886b37c Mon Sep 17 00:00:00 2001 From: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> Date: Thu, 12 Aug 2021 12:40:03 -0700 Subject: [PATCH 342/803] [redcode/crythread-2nd-pass] replaced instances of AZStd::lock_guard<> with AZStd::scoped_lock as per feedback Signed-off-by: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> --- Code/Editor/CryEdit.cpp | 3 +-- Code/Editor/GameExporter.cpp | 2 +- Code/Editor/IEditorImpl.cpp | 6 +++--- .../PerforcePlugin/PerforceSourceControl.cpp | 2 +- Code/Legacy/CryCommon/CryAssert_Linux.h | 2 +- Code/Legacy/CrySystem/DebugCallStack.cpp | 6 +++--- Code/Legacy/CrySystem/Log.cpp | 8 ++++---- .../RemoteConsole/Core/RemoteConsoleCore.cpp | 17 +++++++++-------- 8 files changed, 23 insertions(+), 23 deletions(-) diff --git a/Code/Editor/CryEdit.cpp b/Code/Editor/CryEdit.cpp index 25a6313efe..8444f81317 100644 --- a/Code/Editor/CryEdit.cpp +++ b/Code/Editor/CryEdit.cpp @@ -938,10 +938,9 @@ void CCryEditApp::ShowSplashScreen(CCryEditApp* app) QObject::connect(splashScreen, &QObject::destroyed, splashScreen, [=] { - g_splashScreenStateLock.lock(); + AZStd::scoped_lock lock(g_splashScreenStateLock); g_pInitializeUIInfo = nullptr; g_splashScreen = nullptr; - g_splashScreenStateLock.unlock(); }); } diff --git a/Code/Editor/GameExporter.cpp b/Code/Editor/GameExporter.cpp index 3cd64f9fed..415103e10d 100644 --- a/Code/Editor/GameExporter.cpp +++ b/Code/Editor/GameExporter.cpp @@ -136,7 +136,7 @@ bool CGameExporter::Export(unsigned int flags, [[maybe_unused]] EEndian eExportE m_settings.SetHiQuality(); } - AZStd::lock_guard autoLock(CGameEngine::GetPakModifyMutex()); + AZStd::scoped_lock autoLock(CGameEngine::GetPakModifyMutex()); // Close this pak file. if (!CloseLevelPack(m_levelPak, true)) diff --git a/Code/Editor/IEditorImpl.cpp b/Code/Editor/IEditorImpl.cpp index 7800c7943e..1459139f66 100644 --- a/Code/Editor/IEditorImpl.cpp +++ b/Code/Editor/IEditorImpl.cpp @@ -252,7 +252,7 @@ void CEditorImpl::Uninitialize() void CEditorImpl::UnloadPlugins() { - AZStd::lock_guard lock(m_pluginMutex); + AZStd::scoped_lock lock(m_pluginMutex); // Flush core buses. We're about to unload DLLs and need to ensure we don't have module-owned functions left behind. AZ::Data::AssetBus::ExecuteQueuedEvents(); @@ -273,7 +273,7 @@ void CEditorImpl::UnloadPlugins() void CEditorImpl::LoadPlugins() { - AZStd::lock_guard lock(m_pluginMutex); + AZStd::scoped_lock lock(m_pluginMutex); static const QString editor_plugins_folder("EditorPlugins"); @@ -1460,7 +1460,7 @@ void CEditorImpl::UnregisterNotifyListener(IEditorNotifyListener* listener) ISourceControl* CEditorImpl::GetSourceControl() { - AZStd::lock_guard lock(m_pluginMutex); + AZStd::scoped_lock lock(m_pluginMutex); if (m_pSourceControl) { diff --git a/Code/Editor/Plugins/PerforcePlugin/PerforceSourceControl.cpp b/Code/Editor/Plugins/PerforcePlugin/PerforceSourceControl.cpp index 34514b8ef1..10c43c3d1b 100644 --- a/Code/Editor/Plugins/PerforcePlugin/PerforceSourceControl.cpp +++ b/Code/Editor/Plugins/PerforcePlugin/PerforceSourceControl.cpp @@ -56,7 +56,7 @@ void CPerforceSourceControl::ShowSettings() void CPerforceSourceControl::SetSourceControlState(SourceControlState state) { - AZStd::lock_guard lock(g_cPerforceValues); + AZStd::scoped_lock lock(g_cPerforceValues); switch (state) { diff --git a/Code/Legacy/CryCommon/CryAssert_Linux.h b/Code/Legacy/CryCommon/CryAssert_Linux.h index 355194caba..112c60a80c 100644 --- a/Code/Legacy/CryCommon/CryAssert_Linux.h +++ b/Code/Legacy/CryCommon/CryAssert_Linux.h @@ -80,7 +80,7 @@ bool CryAssert(const char* szCondition, const char* szFile, unsigned int line, b if (!gEnv->bNoAssertDialog && !gEnv->bIgnoreAllAsserts) { - AZStd::lock_guard lk (lock); + AZStd::scoped_lock lk(lock); snprintf(gs_command_str, max_len, "xterm -geometry 100x20 -n 'Assert Dialog [Linux Launcher]' -T 'Assert Dialog [Linux Launcher]' -e 'BinLinux/assert_term \"%s\" \"%s\" %d \"%s\"; echo \"$?\" > .assert_return'", szCondition, (file_len > 60) ? szFile + (file_len - 61) : szFile, line, gs_szMessage); int ret = system(gs_command_str); diff --git a/Code/Legacy/CrySystem/DebugCallStack.cpp b/Code/Legacy/CrySystem/DebugCallStack.cpp index 640afe8da1..cdfc5de21e 100644 --- a/Code/Legacy/CrySystem/DebugCallStack.cpp +++ b/Code/Legacy/CrySystem/DebugCallStack.cpp @@ -154,13 +154,13 @@ void DebugCallStack::SetUserDialogEnable(const bool bUserDialogEnable) DWORD g_idDebugThreads[10]; const char* g_nameDebugThreads[10]; int g_nDebugThreads = 0; -AZStd::spin_mutex g_lockThreadDumpList = 0; +AZStd::spin_mutex g_lockThreadDumpList; void MarkThisThreadForDebugging(const char* name) { EBUS_EVENT(AZ::Debug::EventTraceDrillerSetupBus, SetThreadName, AZStd::this_thread::get_id(), name); - AZStd::lock_guard lock(g_lockThreadDumpList); + AZStd::scoped_lock lock(g_lockThreadDumpList); DWORD id = GetCurrentThreadId(); if (g_nDebugThreads == sizeof(g_idDebugThreads) / sizeof(g_idDebugThreads[0])) { @@ -180,7 +180,7 @@ void MarkThisThreadForDebugging(const char* name) void UnmarkThisThreadFromDebugging() { - AZStd::lock_guard lock(g_lockThreadDumpList); + AZStd::scoped_lock lock(g_lockThreadDumpList); DWORD id = GetCurrentThreadId(); for (int i = g_nDebugThreads - 1; i >= 0; i--) { diff --git a/Code/Legacy/CrySystem/Log.cpp b/Code/Legacy/CrySystem/Log.cpp index 2417c58d4f..d248274b1d 100644 --- a/Code/Legacy/CrySystem/Log.cpp +++ b/Code/Legacy/CrySystem/Log.cpp @@ -810,13 +810,13 @@ void CLog::PushAssetScopeName(const char* sAssetType, const char* sName) SAssetScopeInfo as; as.sType = sAssetType; as.sName = sName; - AZStd::lock_guard scope_lock(m_assetScopeQueueLock); + AZStd::scoped_lock scope_lock(m_assetScopeQueueLock); m_assetScopeQueue.push_back(as); } void CLog::PopAssetScopeName() { - AZStd::lock_guard scope_lock(m_assetScopeQueueLock); + AZStd::scoped_lock scope_lock(m_assetScopeQueueLock); assert(!m_assetScopeQueue.empty()); if (!m_assetScopeQueue.empty()) { @@ -827,7 +827,7 @@ void CLog::PopAssetScopeName() ////////////////////////////////////////////////////////////////////////// const char* CLog::GetAssetScopeString() { - AZStd::lock_guard scope_lock(m_assetScopeQueueLock); + AZStd::scoped_lock scope_lock(m_assetScopeQueueLock); m_assetScopeString.clear(); for (size_t i = 0; i < m_assetScopeQueue.size(); i++) @@ -1450,7 +1450,7 @@ void CLog::Update() { if (!m_threadSafeMsgQueue.empty()) { - AZStd::lock_guard lock(m_threadSafeMsgQueue.get_lock()); // Get the lock and hold onto it until we clear the entire queue (prevents other threads adding more things in while we clear it) + AZStd::scoped_lock lock(m_threadSafeMsgQueue.get_lock()); // Get the lock and hold onto it until we clear the entire queue (prevents other threads adding more things in while we clear it) // Must be called from main thread SLogMsg msg; while (m_threadSafeMsgQueue.try_pop(msg)) diff --git a/Code/Tools/RemoteConsole/Core/RemoteConsoleCore.cpp b/Code/Tools/RemoteConsole/Core/RemoteConsoleCore.cpp index b59f697467..5a137d1664 100644 --- a/Code/Tools/RemoteConsole/Core/RemoteConsoleCore.cpp +++ b/Code/Tools/RemoteConsole/Core/RemoteConsoleCore.cpp @@ -133,19 +133,20 @@ void SRemoteServer::StopServer() AZ::AzSock::CloseSocket(m_socket); m_socket = SOCKET_ERROR; { - AZStd::lock_guard lock(m_mutex); + AZStd::scoped_lock lock(m_mutex); for (TClients::iterator it = m_clients.begin(); it != m_clients.end(); ++it) { it->pClient->StopClient(); } } AZStd::unique_lock lock(m_mutex); - m_stopCondition.wait(lock, [this] { return m_clients.empty(); });} + m_stopCondition.wait(lock, [this] { return m_clients.empty(); }); +} ///////////////////////////////////////////////////////////////////////////////////////////// void SRemoteServer::ClientDone(SRemoteClient* pClient) { - AZStd::lock_guard lock(m_mutex); + AZStd::scoped_lock lock(m_mutex); for (TClients::iterator it = m_clients.begin(); it != m_clients.end(); ++it) { if (it->pClient == pClient) @@ -253,7 +254,7 @@ void SRemoteServer::Run() continue; } - AZStd::lock_guard lock(m_mutex); + AZStd::scoped_lock lock(m_mutex); SRemoteClient* pClient = new SRemoteClient(this); m_clients.push_back(SRemoteClientInfo(pClient)); pClient->StartClient(sClient); @@ -266,7 +267,7 @@ void SRemoteServer::Run() ///////////////////////////////////////////////////////////////////////////////////////////// void SRemoteServer::AddEvent(IRemoteEvent* pEvent) { - AZStd::lock_guard lock(m_mutex); + AZStd::scoped_lock lock(m_mutex); for (TClients::iterator it = m_clients.begin(); it != m_clients.end(); ++it) { it->pEvents->push_back(pEvent->Clone()); @@ -277,7 +278,7 @@ void SRemoteServer::AddEvent(IRemoteEvent* pEvent) ///////////////////////////////////////////////////////////////////////////////////////////// void SRemoteServer::GetEvents(TEventBuffer& buffer) { - AZStd::lock_guard lock(m_mutex); + AZStd::scoped_lock lock(m_mutex); buffer = m_eventBuffer; m_eventBuffer.clear(); } @@ -287,7 +288,7 @@ bool SRemoteServer::WriteBuffer(SRemoteClient* pClient, char* buffer, int& size { IRemoteEvent* pEvent = nullptr; { - AZStd::lock_guard lock(m_mutex); + AZStd::scoped_lock lock(m_mutex); for (TClients::iterator it = m_clients.begin(); it != m_clients.end(); ++it) { if (it->pClient == pClient) @@ -330,7 +331,7 @@ bool SRemoteServer::ReadBuffer(const char* buffer, int data) { if (event->GetType() != eCET_Noop) { - AZStd::lock_guard lock(m_mutex); + AZStd::scoped_lock lock(m_mutex); m_eventBuffer.push_back(event); } else From ff659fbbb6eff884139641d78fad738e3d19386d Mon Sep 17 00:00:00 2001 From: jonawals Date: Thu, 12 Aug 2021 20:48:23 +0100 Subject: [PATCH 343/803] Tiaf bucket top level fix (#3085) * Revert to regular run when invalid commits used. * Cirrect s3 logging of last commit hash storage * Add s3 top level url and build number script params. * Use existing REPOSITORY_NAME env var. Signed-off-by: John --- .../build/Platform/Windows/build_config.json | 2 +- scripts/build/TestImpactAnalysis/git_utils.py | 6 ++++ .../build/TestImpactAnalysis/mars_utils.py | 14 ++++++---- scripts/build/TestImpactAnalysis/tiaf.py | 17 +++++++---- .../build/TestImpactAnalysis/tiaf_driver.py | 28 +++++++++++++++++-- .../tiaf_persistent_storage.py | 2 +- .../tiaf_persistent_storage_s3.py | 6 ++-- 7 files changed, 57 insertions(+), 18 deletions(-) diff --git a/scripts/build/Platform/Windows/build_config.json b/scripts/build/Platform/Windows/build_config.json index 4c275a49cf..0268412aea 100644 --- a/scripts/build/Platform/Windows/build_config.json +++ b/scripts/build/Platform/Windows/build_config.json @@ -89,7 +89,7 @@ "CONFIGURATION": "profile", "SCRIPT_PATH": "scripts/build/TestImpactAnalysis/tiaf_driver.py", "SCRIPT_PARAMETERS": - "--config=\"!OUTPUT_DIRECTORY!/bin/TestImpactFramework/profile/Persistent/tiaf.json\" --src-branch=!BRANCH_NAME! --dst-branch=!CHANGE_TARGET! --commit=!CHANGE_ID! --s3-bucket=!TEST_IMPACT_S3_BUCKET! --mars-index-prefix=jonawals --suite=main --test-failure-policy=continue" + "--config=\"!OUTPUT_DIRECTORY!/bin/TestImpactFramework/profile/Persistent/tiaf.json\" --src-branch=!BRANCH_NAME! --dst-branch=!CHANGE_TARGET! --commit=!CHANGE_ID! --s3-bucket=!TEST_IMPACT_S3_BUCKET! --mars-index-prefix=jonawals --s3-top-level-dir=!REPOSITORY_NAME! --build-number=!BUILD_NUMBER! --suite=main --test-failure-policy=continue" } }, "debug_vs2019": { diff --git a/scripts/build/TestImpactAnalysis/git_utils.py b/scripts/build/TestImpactAnalysis/git_utils.py index ddc17ca146..61380ecb74 100644 --- a/scripts/build/TestImpactAnalysis/git_utils.py +++ b/scripts/build/TestImpactAnalysis/git_utils.py @@ -14,6 +14,7 @@ import pathlib class Repo: def __init__(self, repo_path: str): self._repo = git.Repo(repo_path) + self._remote_url = self._repo.remotes[0].config_reader.get("url") # Returns the current branch @property @@ -21,6 +22,11 @@ class Repo: branch = self._repo.active_branch return branch.name + # Returns the remote URL + @property + def remote_url(self): + return self._remote_url + def create_diff_file(self, src_commit_hash: str, dst_commit_hash: str, output_path: pathlib.Path, multi_branch: bool): """ Attempts to create a diff from the src and dst commits and write to the specified output file. diff --git a/scripts/build/TestImpactAnalysis/mars_utils.py b/scripts/build/TestImpactAnalysis/mars_utils.py index e2394ed6e1..8fa1f123c7 100644 --- a/scripts/build/TestImpactAnalysis/mars_utils.py +++ b/scripts/build/TestImpactAnalysis/mars_utils.py @@ -14,6 +14,7 @@ from tiaf_logger import get_logger logger = get_logger(__file__) MARS_JOB_KEY = "job" +BUILD_NUMBER_KEY = "build_number" SRC_COMMIT_KEY = "src_commit" DST_COMMIT_KEY = "dst_commit" COMMIT_DISTANCE_KEY = "commit_distance" @@ -175,12 +176,14 @@ def get_duration_in_seconds(duration_in_milliseconds: int): return duration_in_milliseconds * 0.001 -def generate_mars_job(tiaf_result, driver_args): +def generate_mars_job(tiaf_result, driver_args, build_number: int): """ Generates a MARS job document using the job meta-data used to drive the TIAF sequence. - @param tiaf_result: The result object generated by the TIAF script. - @param driver_args: The arguments specified to the driver script. + @param tiaf_result: The result object generated by the TIAF script. + @param driver_args: The arguments specified to the driver script. + @param driver_args: The arguments specified to the driver script. + @param build_number: The build number this job corresponds to. @return: The MARS job document with the job meta-data. """ @@ -203,6 +206,7 @@ def generate_mars_job(tiaf_result, driver_args): ]} mars_job[DRIVER_ARGS_KEY] = driver_args + mars_job[BUILD_NUMBER_KEY] = build_number return mars_job def generate_test_run_list(test_runs): @@ -418,7 +422,7 @@ def generate_mars_test_targets(sequence_report: dict, mars_job: dict, t0_timesta return mars_test_targets -def transmit_report_to_mars(mars_index_prefix: str, tiaf_result: dict, driver_args: list): +def transmit_report_to_mars(mars_index_prefix: str, tiaf_result: dict, driver_args: list, build_number: int): """ Transforms the TIAF result into the appropriate MARS documents and transmits them to MARS. @@ -434,7 +438,7 @@ def transmit_report_to_mars(mars_index_prefix: str, tiaf_result: dict, driver_ar t0_timestamp = datetime.datetime.now().timestamp() # Generate and transmit the MARS job document - mars_job = generate_mars_job(tiaf_result, driver_args) + mars_job = generate_mars_job(tiaf_result, driver_args, build_number) filebeat.send_event(mars_job, f"{mars_index_prefix}.tiaf.job") if tiaf_result[REPORT_KEY]: diff --git a/scripts/build/TestImpactAnalysis/tiaf.py b/scripts/build/TestImpactAnalysis/tiaf.py index 11ca24f830..6a43ad3c70 100644 --- a/scripts/build/TestImpactAnalysis/tiaf.py +++ b/scripts/build/TestImpactAnalysis/tiaf.py @@ -161,7 +161,7 @@ class TestImpact: result["change_list"] = self._change_list return result - def run(self, commit: str, src_branch: str, dst_branch: str, s3_bucket: str, suite: str, test_failure_policy: str, safe_mode: bool, test_timeout: int, global_timeout: int): + def run(self, commit: str, src_branch: str, dst_branch: str, s3_bucket: str, s3_top_level_dir: str, suite: str, test_failure_policy: str, safe_mode: bool, test_timeout: int, global_timeout: int): """ Determins the type of sequence to run based on the commit, source branch and test branch before running the sequence with the specified values. @@ -170,6 +170,7 @@ class TestImpact: @param src_branch: If not equal to dst_branch, the branch that is being built. @param dst_branch: If not equal to src_branch, the destination branch for the PR being built. @param s3_bucket: Location of S3 bucket to use for persistent storage, otherwise local disk storage will be used. + @param s3_top_level_dir: Top level directory to use in the S3 bucket. @param suite: Test suite to run. @param test_failure_policy: Test failure policy for regular and test impact sequences (ignored when seeding). @param safe_mode: Flag to run impact analysis tests in safe mode (ignored when seeding). @@ -218,7 +219,7 @@ class TestImpact: try: # Persistent storage location if s3_bucket: - persistent_storage = PersistentStorageS3(self._config, suite, s3_bucket, self._source_of_truth_branch) + persistent_storage = PersistentStorageS3(self._config, suite, s3_bucket, s3_top_level_dir, self._source_of_truth_branch) else: persistent_storage = PersistentStorageLocal(self._config, suite) except SystemError as e: @@ -226,14 +227,20 @@ class TestImpact: persistent_storage = None if persistent_storage: + # Flag to signify whether or not this is a re-run (multiple runs of the same commit) + # Right now, we don't fully support re-runs but in the future we will have an extra subfolder for each commit hash with the + # last run hash that was used for the first run for the commit so we can retreive the same reference point for building the + # change list to ensure each subsequent run is using the same data but for the time being, just perform a regular run + is_rerun = False if persistent_storage.has_historic_data: logger.info("Historic data found.") self._src_commit = persistent_storage.last_commit_hash - # Perform some basic sanity checks on the commit hashes to ensure confidence in the integrity of of the environment + # Perform some basic sanity checks on the commit hashes to ensure confidence in the integrity of the environment if self._src_commit == self._dst_commit: - logger.error(f"Source commit '{self._src_commit}' and destination commit '{self._dst_commit}', implying the integrity of the historic data is compromised.") + logger.info(f"Source commit '{self._src_commit}' and destination commit '{self._dst_commit}', implying this is a re-run. A regular sequence will instead be performed.") persistent_storage = None + is_rerun = True else: self._attempt_to_generate_change_list() else: @@ -261,7 +268,7 @@ class TestImpact: args.append(f"--changelist={self._change_list_path}") logger.info(f"Change list is set to '{self._change_list_path}'.") else: - if self._is_source_of_truth_branch: + if self._is_source_of_truth_branch and not is_rerun: # Use seed sequence (instrumented all tests) for coverage updating branches so we can generate the coverage bed for future sequences sequence_type = "seed" # We always continue after test failures when seeding to ensure we capture the coverage for all test targets diff --git a/scripts/build/TestImpactAnalysis/tiaf_driver.py b/scripts/build/TestImpactAnalysis/tiaf_driver.py index 5ad16abaa0..ad49d98102 100644 --- a/scripts/build/TestImpactAnalysis/tiaf_driver.py +++ b/scripts/build/TestImpactAnalysis/tiaf_driver.py @@ -11,6 +11,7 @@ import mars_utils import sys import pathlib import traceback +import re from tiaf import TestImpact from tiaf_logger import get_logger @@ -66,13 +67,20 @@ def parse_args(): required=True ) - # S3 bucket + # S3 bucket name parser.add_argument( '--s3-bucket', help="Location of S3 bucket to use for persistent storage, otherwise local disk storage will be used", required=False ) + # S3 bucket top level directory + parser.add_argument( + '--s3-top-level-dir', + help="The top level directory to use in the S3 bucket", + required=False + ) + # MARS index prefix parser.add_argument( '--mars-index-prefix', @@ -80,6 +88,13 @@ def parse_args(): required=False ) + # Build number + parser.add_argument( + '--build-number', + help="The build number this run of TIAF corresponds to", + required=True + ) + # Test suite parser.add_argument( '--suite', @@ -127,12 +142,19 @@ if __name__ == "__main__": try: args = parse_args() + + s3_top_level_dir = None + if args.s3_top_level_dir: + s3_top_level_dir = args.s3_top_level_dir + else: + s3_top_level_dir = "tiaf" + tiaf = TestImpact(args.config) - tiaf_result = tiaf.run(args.commit, args.src_branch, args.dst_branch, args.s3_bucket, args.suite, args.test_failure_policy, args.safe_mode, args.test_timeout, args.global_timeout) + tiaf_result = tiaf.run(args.commit, args.src_branch, args.dst_branch, args.s3_bucket, s3_top_level_dir, args.suite, args.test_failure_policy, args.safe_mode, args.test_timeout, args.global_timeout) if args.mars_index_prefix: logger.info("Transmitting report to MARS...") - mars_utils.transmit_report_to_mars(args.mars_index_prefix, tiaf_result, sys.argv) + mars_utils.transmit_report_to_mars(args.mars_index_prefix, tiaf_result, sys.argv, args.build_number) logger.info("Complete!") # Non-gating will be removed from this script and handled at the job level in SPEC-7413 diff --git a/scripts/build/TestImpactAnalysis/tiaf_persistent_storage.py b/scripts/build/TestImpactAnalysis/tiaf_persistent_storage.py index ec646ee484..1ee3ac7e8c 100644 --- a/scripts/build/TestImpactAnalysis/tiaf_persistent_storage.py +++ b/scripts/build/TestImpactAnalysis/tiaf_persistent_storage.py @@ -106,7 +106,7 @@ class PersistentStorage(ABC): historic_data_json = self._pack_historic_data(last_commit_hash) if historic_data_json: - logger.info(f"Attempting to store historic data with new last commit hash '{self._last_commit_hash}'...") + logger.info(f"Attempting to store historic data with new last commit hash '{last_commit_hash}'...") self._store_historic_data(historic_data_json) logger.info("The historic data was successfully stored.") diff --git a/scripts/build/TestImpactAnalysis/tiaf_persistent_storage_s3.py b/scripts/build/TestImpactAnalysis/tiaf_persistent_storage_s3.py index 24101c7cba..1a279855ea 100644 --- a/scripts/build/TestImpactAnalysis/tiaf_persistent_storage_s3.py +++ b/scripts/build/TestImpactAnalysis/tiaf_persistent_storage_s3.py @@ -18,7 +18,7 @@ logger = get_logger(__file__) # Implementation of s3 bucket persistent storage class PersistentStorageS3(PersistentStorage): - def __init__(self, config: dict, suite: str, s3_bucket: str, branch: str): + def __init__(self, config: dict, suite: str, s3_bucket: str, root_dir: str, branch: str): """ Initializes the persistent storage with the specified s3 bucket. @@ -36,8 +36,8 @@ class PersistentStorageS3(PersistentStorage): # historic_data.json.zip is the file containing the coverage and meta-data of the last TIAF sequence run historic_data_file = f"historic_data.{object_extension}" - # The location of the data is in the form / so the build config of each branch gets its own historic data - self._dir = f'{branch}/{config["meta"]["build_config"]}' + # The location of the data is in the form // so the build config of each branch gets its own historic data + self._dir = f'{root_dir}/{branch}/{config["meta"]["build_config"]}' self._historic_data_key = f'{self._dir}/{historic_data_file}' logger.info(f"Attempting to retrieve historic data for branch '{branch}' at location '{self._historic_data_key}' on bucket '{s3_bucket}'...") From ecd3b015eea1eb49bab8d0eb02f43b16054f82c4 Mon Sep 17 00:00:00 2001 From: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> Date: Thu, 12 Aug 2021 15:10:33 -0500 Subject: [PATCH 344/803] Fixed Signed/Unsigned Mismatch fix in LyShine UiAnimViewAnimNode.cpp (#3062) Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> --- Gems/LyShine/Code/Editor/Animation/UiAnimViewAnimNode.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/LyShine/Code/Editor/Animation/UiAnimViewAnimNode.cpp b/Gems/LyShine/Code/Editor/Animation/UiAnimViewAnimNode.cpp index 697820d75c..3646e5a413 100644 --- a/Gems/LyShine/Code/Editor/Animation/UiAnimViewAnimNode.cpp +++ b/Gems/LyShine/Code/Editor/Animation/UiAnimViewAnimNode.cpp @@ -1482,7 +1482,7 @@ bool CUiAnimViewAnimNode::PasteNodesFromClipboard(QWidget* context) const bool bLightAnimationSetActive = GetSequence()->GetFlags() & IUiAnimSequence::eSeqFlags_LightAnimationSet; const unsigned int numNodes = animNodesRoot->getChildCount(); - for (int i = 0; i < numNodes; ++i) + for (unsigned int i = 0; i < numNodes; ++i) { XmlNodeRef xmlNode = animNodesRoot->getChild(i); From c3ee798acc817aadc7b1bab8e51e67c3c31cfbf4 Mon Sep 17 00:00:00 2001 From: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> Date: Thu, 12 Aug 2021 14:18:10 -0700 Subject: [PATCH 345/803] [redcode/crythread-2nd-pass] updated condition variable handling in Remote Console runtime to cut out extra unlock/lock Signed-off-by: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> --- Code/Tools/RemoteConsole/Core/RemoteConsoleCore.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/Code/Tools/RemoteConsole/Core/RemoteConsoleCore.cpp b/Code/Tools/RemoteConsole/Core/RemoteConsoleCore.cpp index 5a137d1664..a4e7bd24fa 100644 --- a/Code/Tools/RemoteConsole/Core/RemoteConsoleCore.cpp +++ b/Code/Tools/RemoteConsole/Core/RemoteConsoleCore.cpp @@ -132,14 +132,12 @@ void SRemoteServer::StopServer() m_bAcceptClients = false; AZ::AzSock::CloseSocket(m_socket); m_socket = SOCKET_ERROR; - { - AZStd::scoped_lock lock(m_mutex); - for (TClients::iterator it = m_clients.begin(); it != m_clients.end(); ++it) - { - it->pClient->StopClient(); - } - } + AZStd::unique_lock lock(m_mutex); + for (TClients::iterator it = m_clients.begin(); it != m_clients.end(); ++it) + { + it->pClient->StopClient(); + } m_stopCondition.wait(lock, [this] { return m_clients.empty(); }); } From 11d5009f466d394b4f71a3f791f7073e2b65a00f Mon Sep 17 00:00:00 2001 From: Chris Galvan Date: Thu, 12 Aug 2021 16:31:39 -0500 Subject: [PATCH 346/803] Fixed creating entities in the viewport logic to use hit test detection. Signed-off-by: Chris Galvan --- Code/Editor/EditorViewportWidget.cpp | 3 +- .../SandboxIntegration.cpp | 2 +- Code/Editor/Viewport.cpp | 42 +++++++++++-------- Code/Editor/Viewport.h | 2 + 4 files changed, 28 insertions(+), 21 deletions(-) diff --git a/Code/Editor/EditorViewportWidget.cpp b/Code/Editor/EditorViewportWidget.cpp index 9ef20e02fb..28e8cce33e 100644 --- a/Code/Editor/EditorViewportWidget.cpp +++ b/Code/Editor/EditorViewportWidget.cpp @@ -2697,8 +2697,7 @@ void EditorViewportWidget::RestoreViewportAfterGameMode() QString( tr("When leaving \" Game Mode \" the engine will automatically restore your camera position to the default position before you " "had entered Game mode.

If you dislike this setting you can always change this anytime in the global " - "preferences.

")) - .arg(EditorPreferencesGeneralRestoreViewportCameraSettingName); + "preferences.

")); QString restoreOnExitGameModePopupDisabledRegKey("Editor/AutoHide/ViewportCameraRestoreOnExitGameMode"); // Read the popup disabled registry value diff --git a/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp b/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp index 2ed2a30f08..66c57361be 100644 --- a/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp +++ b/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp @@ -1452,7 +1452,7 @@ void SandboxIntegrationManager::ContextMenu_NewEntity() if (view) { const QPoint viewPoint(m_contextMenuViewPoint.GetX(), m_contextMenuViewPoint.GetY()); - worldPosition = LYVec3ToAZVec3(view->SnapToGrid(view->ViewToWorld(viewPoint))); + worldPosition = view->GetHitLocation(viewPoint); } CreateNewEntityAtPosition(worldPosition); diff --git a/Code/Editor/Viewport.cpp b/Code/Editor/Viewport.cpp index 2bc1b21216..873f555c80 100644 --- a/Code/Editor/Viewport.cpp +++ b/Code/Editor/Viewport.cpp @@ -46,24 +46,7 @@ void QtViewport::BuildDragDropContext(AzQtComponents::ViewportDragContext& conte PreWidgetRendering(); // required so that the current render cam is set. - Vec3 pos = Vec3(ZERO); - HitContext hit; - if (HitTest(pt, hit)) - { - pos = hit.raySrc + hit.rayDir * hit.dist; - pos = SnapToGrid(pos); - } - else - { - bool hitTerrain; - pos = ViewToWorld(pt, &hitTerrain); - if (hitTerrain) - { - pos.z = GetIEditor()->GetTerrainElevation(pos.x, pos.y); - } - pos = SnapToGrid(pos); - } - context.m_hitLocation = AZ::Vector3(pos.x, pos.y, pos.z); + context.m_hitLocation = GetHitLocation(pt); PostWidgetRendering(); } @@ -1154,6 +1137,29 @@ bool QtViewport::HitTest(const QPoint& point, HitContext& hitInfo) return false; } +AZ::Vector3 QtViewport::GetHitLocation(const QPoint& point) +{ + Vec3 pos = Vec3(ZERO); + HitContext hit; + if (HitTest(point, hit)) + { + pos = hit.raySrc + hit.rayDir * hit.dist; + pos = SnapToGrid(pos); + } + else + { + bool hitTerrain; + pos = ViewToWorld(point, &hitTerrain); + if (hitTerrain) + { + pos.z = GetIEditor()->GetTerrainElevation(pos.x, pos.y); + } + pos = SnapToGrid(pos); + } + + return AZ::Vector3(pos.x, pos.y, pos.z); +} + ////////////////////////////////////////////////////////////////////////// void QtViewport::SetZoomFactor(float fZoomFactor) { diff --git a/Code/Editor/Viewport.h b/Code/Editor/Viewport.h index 823b8c77b1..6b5bfb5c34 100644 --- a/Code/Editor/Viewport.h +++ b/Code/Editor/Viewport.h @@ -201,6 +201,7 @@ public: //! Performs hit testing of 2d point in view to find which object hit. virtual bool HitTest(const QPoint& point, HitContext& hitInfo) = 0; + virtual AZ::Vector3 GetHitLocation(const QPoint& point) = 0; virtual void MakeConstructionPlane(int axis) = 0; @@ -436,6 +437,7 @@ public: //! Performs hit testing of 2d point in view to find which object hit. bool HitTest(const QPoint& point, HitContext& hitInfo) override; + AZ::Vector3 GetHitLocation(const QPoint& point) override; //! Do 2D hit testing of line in world space. // pToCameraDistance is an optional output parameter in which distance from the camera to the line is returned. From f7da64a5183f61bee2a057ee4eb9b82c6c4e8630 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Mon, 12 Apr 2021 19:52:01 -0700 Subject: [PATCH 347/803] =?UTF-8?q?=EF=BB=BFAllowing=20to=20build=20with?= =?UTF-8?q?=20ASan=20enabled?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- cmake/Configurations.cmake | 127 +++++++++--------- .../Common/MSVC/Configurations_msvc.cmake | 23 +++- cmake/cmake_files.cmake | 1 + 3 files changed, 83 insertions(+), 68 deletions(-) diff --git a/cmake/Configurations.cmake b/cmake/Configurations.cmake index a580f1c572..693cc23c7d 100644 --- a/cmake/Configurations.cmake +++ b/cmake/Configurations.cmake @@ -20,24 +20,33 @@ include_guard(GLOBAL) # \arg:LINK_STATIC_${CONFIGURATION} # \arg:LINK_NON_STATIC # \arg:LINK_NON_STATIC_${CONFIGURATION} -# \arg:LINK_EXECUTABLE -# \arg:LINK_EXECUTABLE_${CONFIGURATION} +# \arg:LINK_EXE +# \arg:LINK_EXE_${CONFIGURATION} +# \arg:LINK_MODULE +# \arg:LINK_MODULE_${CONFIGURATION} +# \arg:LINK_SHARED +# \arg:LINK_SHARED_${CONFIGURATION} # function(ly_append_configurations_options) set(options) set(oneValueArgs) - set(multiValueArgs + set(multiArgs DEFINES COMPILATION LINK LINK_STATIC LINK_NON_STATIC - LINK_EXECUTABLE + LINK_EXE + LINK_MODULE + LINK_SHARED ) - foreach(conf IN LISTS CMAKE_CONFIGURATION_TYPES) - string(TOUPPER ${conf} UCONF) - set(multiValueArgs ${multiValueArgs} DEFINES_${UCONF} COMPILATION_${UCONF} LINK_${UCONF} LINK_STATIC_${UCONF} LINK_NON_STATIC_${UCONF} LINK_EXECUTABLE_${UCONF}) + foreach(arg IN LISTS multiArgs) + list(APPEND multiValueArgs ${arg}) + foreach(conf IN LISTS CMAKE_CONFIGURATION_TYPES) + string(TOUPPER ${conf} UCONF) + list(APPEND multiValueArgs ${arg}_${UCONF}) + endforeach() endforeach() cmake_parse_arguments(ly_append_configurations_options "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) @@ -45,48 +54,46 @@ function(ly_append_configurations_options) if(ly_append_configurations_options_DEFINES) add_compile_definitions(${ly_append_configurations_options_DEFINES}) endif() + if(ly_append_configurations_options_COMPILATION) string(REPLACE ";" " " COMPILATION_STR "${ly_append_configurations_options_COMPILATION}") - string(APPEND CMAKE_C_FLAGS " " ${COMPILATION_STR}) - string(APPEND CMAKE_CXX_FLAGS " " ${COMPILATION_STR}) - set(CMAKE_C_FLAGS ${CMAKE_C_FLAGS} PARENT_SCOPE) - set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} PARENT_SCOPE) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COMPILATION_STR}" PARENT_SCOPE) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COMPILATION_STR}" PARENT_SCOPE) endif() + if(ly_append_configurations_options_LINK) string(REPLACE ";" " " LINK_STR "${ly_append_configurations_options_LINK}") - string(APPEND LINK_OPTIONS " " ${LINK_STR}) - set(LINK_OPTIONS ${LINK_OPTIONS} PARENT_SCOPE) - - # Not defining these issue warnings, TODO: investigate - set(CMAKE_STATIC_LINKER_FLAGS ${LINK_OPTIONS} PARENT_SCOPE) - set(CMAKE_MODULE_LINKER_FLAGS ${LINK_OPTIONS} PARENT_SCOPE) - set(CMAKE_SHARED_LINKER_FLAGS ${LINK_OPTIONS} PARENT_SCOPE) - set(CMAKE_EXE_LINKER_FLAGS ${LINK_OPTIONS} PARENT_SCOPE) + set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} ${LINK_STR}" PARENT_SCOPE) + set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${LINK_STR}" PARENT_SCOPE) + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${LINK_STR}" PARENT_SCOPE) + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LINK_OPTIONS}" PARENT_SCOPE) endif() - if(ly_append_configurations_options_LINK_STATIC) - string(REPLACE ";" " " LINK_STATIC_STR "${ly_append_configurations_options_LINK_STATIC}") - string(APPEND LINK_STATIC_OPTIONS " " ${LINK_STATIC_STR}) - set(LINK_STATIC_OPTIONS ${LINK_STATIC_OPTIONS} PARENT_SCOPE) - set(CMAKE_STATIC_LINKER_FLAGS ${LINK_STATIC_OPTIONS} PARENT_SCOPE) + if(ly_append_configurations_options_LINK_STATIC) + string(REPLACE ";" " " LINK_STR "${ly_append_configurations_options_LINK_STATIC}") + set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} ${LINK_STR}" PARENT_SCOPE) endif() if(ly_append_configurations_options_LINK_NON_STATIC) - string(REPLACE ";" " " LINK_NON_STATIC_STR "${ly_append_configurations_options_LINK_NON_STATIC}") - string(APPEND LINK_NON_STATIC_OPTIONS " " ${LINK_NON_STATIC_STR}) - set(LINK_NON_STATIC_OPTIONS ${LINK_NON_STATIC_OPTIONS} PARENT_SCOPE) - - set(CMAKE_MODULE_LINKER_FLAGS ${LINK_NON_STATIC_OPTIONS} PARENT_SCOPE) - set(CMAKE_SHARED_LINKER_FLAGS ${LINK_NON_STATIC_OPTIONS} PARENT_SCOPE) - set(CMAKE_EXE_LINKER_FLAGS ${LINK_NON_STATIC_OPTIONS} PARENT_SCOPE) + string(REPLACE ";" " " LINK_STR "${ly_append_configurations_options_LINK_NON_STATIC}") + set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${LINK_STR}" PARENT_SCOPE) + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${LINK_STR}" PARENT_SCOPE) + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LINK_STR}" PARENT_SCOPE) endif() - if(ly_append_configurations_options_LINK_EXECUTABLE) - string(REPLACE ";" " " LINK_EXECUTABLE_STR "${ly_append_configurations_options_LINK_EXECUTABLE}") - string(APPEND LINK_EXECUTABLE_OPTIONS " " ${LINK_EXECUTABLE_STR}) - set(LINK_EXECUTABLE_OPTIONS ${LINK_EXECUTABLE_OPTIONS} PARENT_SCOPE) + if(ly_append_configurations_options_LINK_EXE) + string(REPLACE ";" " " LINK_STR "${ly_append_configurations_options_LINK_EXE}") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LINK_STR}" PARENT_SCOPE) + endif() - set(CMAKE_EXE_LINKER_FLAGS ${LINK_EXECUTABLE_OPTIONS} PARENT_SCOPE) + if(ly_append_configurations_options_LINK_MODULE) + string(REPLACE ";" " " LINK_STR "${ly_append_configurations_options_LINK_MODULE}") + set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${LINK_STR}" PARENT_SCOPE) + endif() + + if(ly_append_configurations_options_LINK_SHARED) + string(REPLACE ";" " " LINK_STR "${ly_append_configurations_options_LINK_SHARED}") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${LINK_STR}" PARENT_SCOPE) endif() foreach(conf IN LISTS CMAKE_CONFIGURATION_TYPES) @@ -100,43 +107,33 @@ function(ly_append_configurations_options) endif() if(ly_append_configurations_options_COMPILATION_${UCONF}) string(REPLACE ";" " " COMPILATION_STR "${ly_append_configurations_options_COMPILATION_${UCONF}}") - string(APPEND CMAKE_C_FLAGS_${UCONF} " " ${COMPILATION_STR}) - string(APPEND CMAKE_CXX_FLAGS_${UCONF} " " ${COMPILATION_STR}) - set(CMAKE_C_FLAGS_${UCONF} ${CMAKE_C_FLAGS_${UCONF}} PARENT_SCOPE) - set(CMAKE_CXX_FLAGS_${UCONF} ${CMAKE_CXX_FLAGS_${UCONF}} PARENT_SCOPE) + set(CMAKE_C_FLAGS_${UCONF} "${CMAKE_C_FLAGS_${UCONF}} ${COMPILATION_STR}" PARENT_SCOPE) + set(CMAKE_CXX_FLAGS_${UCONF} "${CMAKE_CXX_FLAGS_${UCONF}} ${COMPILATION_STR}" PARENT_SCOPE) endif() if(ly_append_configurations_options_LINK_${UCONF}) string(REPLACE ";" " " LINK_STR "${ly_append_configurations_options_LINK_${UCONF}}") - string(APPEND LINK_OPTIONS_${UCONF} " " ${LINK_STR}) - set(LINK_OPTIONS_${UCONF} ${LINK_OPTIONS_${UCONF}} PARENT_SCOPE) - - set(CMAKE_STATIC_LINKER_FLAGS_${UCONF} ${LINK_OPTIONS_${UCONF}} PARENT_SCOPE) - set(CMAKE_MODULE_LINKER_FLAGS_${UCONF} ${LINK_OPTIONS_${UCONF}} PARENT_SCOPE) - set(CMAKE_SHARED_LINKER_FLAGS_${UCONF} ${LINK_OPTIONS_${UCONF}} PARENT_SCOPE) - set(CMAKE_EXE_LINKER_FLAGS_${UCONF} ${LINK_OPTIONS_${UCONF}} PARENT_SCOPE) + set(CMAKE_STATIC_LINKER_FLAGS_${UCONF} "${CMAKE_STATIC_LINKER_FLAGS_${UCONF}} ${LINK_STR}" PARENT_SCOPE) + set(CMAKE_MODULE_LINKER_FLAGS_${UCONF} "${CMAKE_MODULE_LINKER_FLAGS_${UCONF}} ${LINK_STR}" PARENT_SCOPE) + set(CMAKE_SHARED_LINKER_FLAGS_${UCONF} "${CMAKE_SHARED_LINKER_FLAGS_${UCONF}} ${LINK_STR}" PARENT_SCOPE) + set(CMAKE_EXE_LINKER_FLAGS_${UCONF} "${CMAKE_EXE_LINKER_FLAGS_${UCONF}} ${LINK_STR}" PARENT_SCOPE) endif() if(ly_append_configurations_options_LINK_STATIC_${UCONF}) - string(REPLACE ";" " " LINK_STATIC_STR "${ly_append_configurations_options_LINK_STATIC_${UCONF}}") - string(APPEND LINK_STATIC_OPTIONS_${UCONF} " " ${LINK_STATIC_STR}) - set(LINK_STATIC_OPTIONS_${UCONF} ${LINK_STATIC_OPTIONS_${UCONF}} PARENT_SCOPE) - - set(CMAKE_STATIC_LINKER_FLAGS_${UCONF} ${LINK_STATIC_OPTIONS_${UCONF}} PARENT_SCOPE) + string(REPLACE ";" " " LINK_STR "${ly_append_configurations_options_LINK_STATIC_${UCONF}}") + set(CMAKE_STATIC_LINKER_FLAGS_${UCONF} "${CMAKE_STATIC_LINKER_FLAGS_${UCONF}} ${LINK_STR}" PARENT_SCOPE) endif() if(ly_append_configurations_options_LINK_NON_STATIC_${UCONF}) - string(REPLACE ";" " " LINK_NON_STATIC_STR "${ly_append_configurations_options_LINK_NON_STATIC_${UCONF}}") - string(APPEND LINK_NON_STATIC_OPTIONS_${UCONF} " " ${LINK_NON_STATIC_STR}) - set(LINK_NON_STATIC_OPTIONS_${UCONF} ${LINK_NON_STATIC_OPTIONS_${UCONF}} PARENT_SCOPE) - - set(CMAKE_MODULE_LINKER_FLAGS_${UCONF} ${LINK_NON_STATIC_OPTIONS_${UCONF}} PARENT_SCOPE) - set(CMAKE_SHARED_LINKER_FLAGS_${UCONF} ${LINK_NON_STATIC_OPTIONS_${UCONF}} PARENT_SCOPE) - set(CMAKE_EXE_LINKER_FLAGS_${UCONF} ${LINK_NON_STATIC_OPTIONS_${UCONF}} PARENT_SCOPE) + string(REPLACE ";" " " LINK_STR "${ly_append_configurations_options_LINK_NON_STATIC_${UCONF}}") + set(CMAKE_MODULE_LINKER_FLAGS_${UCONF} "${CMAKE_MODULE_LINKER_FLAGS_${UCONF}} ${LINK_STR}" PARENT_SCOPE) + set(CMAKE_SHARED_LINKER_FLAGS_${UCONF} "${CMAKE_SHARED_LINKER_FLAGS_${UCONF}} ${LINK_STR}" PARENT_SCOPE) + set(CMAKE_EXE_LINKER_FLAGS_${UCONF} "${CMAKE_EXE_LINKER_FLAGS_${UCONF}} ${LINK_STR}" PARENT_SCOPE) endif() - if(ly_append_configurations_options_LINK_EXECUTABLE_${UCONF}) - string(REPLACE ";" " " LINK_EXECUTABLE_STR "${ly_append_configurations_options_LINK_EXECUTABLE_${UCONF}}") - string(APPEND LINK_EXECUTABLE_OPTIONS_${UCONF} " " ${LINK_EXECUTABLE_STR}) - set(LINK_EXECUTABLE_OPTIONS_${UCONF} ${LINK_EXECUTABLE_OPTIONS_${UCONF}} PARENT_SCOPE) - - set(CMAKE_EXE_LINKER_FLAGS_${UCONF} ${LINK_EXECUTABLE_OPTIONS_${UCONF}} PARENT_SCOPE) + if(ly_append_configurations_options_LINK_EXE_${UCONF}) + string(REPLACE ";" " " LINK_STR "${ly_append_configurations_options_LINK_EXE_${UCONF}}") + set(CMAKE_EXE_LINKER_FLAGS_${UCONF} "${CMAKE_EXE_LINKER_FLAGS_${UCONF}} ${LINK_STR}" PARENT_SCOPE) + endif() + if(ly_append_configurations_options_LINK_MODULE_${UCONF}) + string(REPLACE ";" " " LINK_STR "${ly_append_configurations_options_LINK_MODULE_${UCONF}}") + set(CMAKE_MODULE_LINKER_FLAGS_${UCONF} "${CMAKE_MODULE_LINKER_FLAGS_${UCONF}} ${LINK_STR}" PARENT_SCOPE) endif() endforeach() diff --git a/cmake/Platform/Common/MSVC/Configurations_msvc.cmake b/cmake/Platform/Common/MSVC/Configurations_msvc.cmake index 118a515e30..c0d0809b0f 100644 --- a/cmake/Platform/Common/MSVC/Configurations_msvc.cmake +++ b/cmake/Platform/Common/MSVC/Configurations_msvc.cmake @@ -64,9 +64,6 @@ ly_append_configurations_options( # It also causes the compiler to place the library name MSVCRTD.lib into the .obj file. /Ob0 # Disables inline expansions /Od # Disables optimization - /RTCsu # Run-Time Error Checks: c Reports when a value is assigned to a smaller data type and results in a data loss (Not supoported by the STL) - # s Enables stack frame run-time error checking - # u Reports when a variable is used without having been initialized COMPILATION_PROFILE /GF # Enable string pooling /Gy # Function level linking @@ -96,6 +93,26 @@ ly_append_configurations_options( /INCREMENTAL:NO ) +set(LY_BUILD_WITH_ADDRESS_SANITIZER FALSE CACHE BOOL "Builds using AddressSanitizer (ASan). Will disable Edit/Continue, Incremental building and Run-Time checks (default = FALSE)") +if(LY_BUILD_WITH_ADDRESS_SANITIZER) + set(LY_BUILD_WITH_INCREMENTAL_LINKING_DEBUG FALSE) + ly_append_configurations_options( + COMPILATION_DEBUG + /fsanitize=address + ) + get_filename_component(link_tools_dir ${CMAKE_LINKER} DIRECTORY) + file(COPY + ${link_tools_dir}/clang_rt.asan_dbg_dynamic-x86_64.dll + DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG}) +else() + ly_append_configurations_options( + COMPILATION_DEBUG + /RTCsu # Run-Time Error Checks: c Reports when a value is assigned to a smaller data type and results in a data loss (Not supoported by the STL) + # s Enables stack frame run-time error checking + # u Reports when a variable is used without having been initialized + ) +endif() + set(LY_BUILD_WITH_INCREMENTAL_LINKING_DEBUG FALSE CACHE BOOL "Indicates if incremental linking is used in debug configurations (default = FALSE)") if(LY_BUILD_WITH_INCREMENTAL_LINKING_DEBUG) ly_append_configurations_options( diff --git a/cmake/cmake_files.cmake b/cmake/cmake_files.cmake index aa275b634a..10676b384e 100644 --- a/cmake/cmake_files.cmake +++ b/cmake/cmake_files.cmake @@ -20,6 +20,7 @@ set(FILES Findo3de.cmake Gems.cmake GeneralSettings.cmake + Initialize.cmake Install.cmake LyAutoGen.cmake LYPackage_S3Downloader.cmake From 3fe5901a77519ceb135243f58d70144096ba0848 Mon Sep 17 00:00:00 2001 From: mnaumov Date: Wed, 11 Aug 2021 23:25:41 -0700 Subject: [PATCH 348/803] Fixing a crash when unparenting prefab instance in a new level Signed-off-by: mnaumov --- .../PrefabEditorEntityOwnershipService.cpp | 2 +- .../Prefab/PrefabPublicHandler.cpp | 36 +++++++++++++------ .../Prefab/PrefabSystemComponent.cpp | 18 ++++++++++ .../Prefab/PrefabSystemComponent.h | 2 ++ .../Prefab/PrefabSystemComponentInterface.h | 2 ++ 5 files changed, 48 insertions(+), 12 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp index b5cf5fb878..127f04424b 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp @@ -202,7 +202,7 @@ namespace AzToolsFramework m_rootInstance->SetTemplateId(templateId); m_rootInstance->SetTemplateSourcePath(m_loaderInterface->GenerateRelativePath(filename)); m_rootInstance->SetContainerEntityName("Level"); - m_prefabSystemComponent->PropagateTemplateChanges(templateId); + m_prefabSystemComponent->PropagateTemplateChangesDown(templateId); return true; } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp index 69efe33d72..85fe30c252 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp @@ -482,22 +482,36 @@ namespace AzToolsFramework AZStd::unique_ptr& sourceInstance, TemplateId targetTemplateId, UndoSystem::URSequencePoint* undoBatch) { LinkReference nestedInstanceLink = m_prefabSystemComponentInterface->FindLink(sourceInstance->GetLinkId()); - AZ_Assert( - nestedInstanceLink.has_value(), - "A valid link was not found for one of the instances provided as input for the CreatePrefab operation."); + if (!nestedInstanceLink) + { + AZ_Assert( + false, + "A valid link was not found for one of the instances provided as input for the CreatePrefab operation."); + return; + } PrefabDomReference nestedInstanceLinkDom = nestedInstanceLink->get().GetLinkDom(); - AZ_Assert( - nestedInstanceLinkDom.has_value(), - "A valid DOM was not found for the link corresponding to one of the instances provided as input for the " - "CreatePrefab operation."); + + if (!nestedInstanceLinkDom) + { + AZ_Assert( + false, + "A valid DOM was not found for the link corresponding to one of the instances provided as input for the " + "CreatePrefab operation."); + return; + } PrefabDomValueReference nestedInstanceLinkPatches = PrefabDomUtils::FindPrefabDomValue(nestedInstanceLinkDom->get(), PrefabDomUtils::PatchesName); - AZ_Assert( - nestedInstanceLinkPatches.has_value(), - "A valid DOM for patches was not found for the link corresponding to one of the instances provided as input for the " - "CreatePrefab operation."); + + if (!nestedInstanceLinkPatches) + { + AZ_Assert( + false, + "A valid DOM for patches was not found for the link corresponding to one of the instances provided as input for the " + "CreatePrefab operation."); + return; + } PrefabDom patchesCopyForUndoSupport; patchesCopyForUndoSupport.CopyFrom(nestedInstanceLinkPatches->get(), patchesCopyForUndoSupport.GetAllocator()); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp index bfdb6b79f2..b75f50198c 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp @@ -153,6 +153,24 @@ namespace AzToolsFramework } } + void PrefabSystemComponent::PropagateTemplateChangesDown(TemplateId templateId, InstanceOptionalReference instanceToExclude) + { + PropagateTemplateChanges(templateId, instanceToExclude); + + auto templateIterator = m_templateIdMap.find(templateId); + if (templateIterator != m_templateIdMap.end()) + { + for (LinkId linkId : templateIterator->second.GetLinks()) + { + auto linkIterator = m_linkIdMap.find(linkId); + if (linkIterator != m_linkIdMap.end()) + { + PropagateTemplateChangesDown(linkIterator->second.GetSourceTemplateId(), instanceToExclude); + } + } + } + } + void PrefabSystemComponent::UpdatePrefabTemplate(TemplateId templateId, const PrefabDom& updatedDom) { auto templateToUpdate = FindTemplate(templateId); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h index 04457b5a97..ccc17af133 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h @@ -213,6 +213,8 @@ namespace AzToolsFramework void PropagateTemplateChanges(TemplateId templateId, InstanceOptionalReference instanceToExclude = AZStd::nullopt) override; + void PropagateTemplateChangesDown(TemplateId templateIdd, InstanceOptionalReference instanceToExclude = AZStd::nullopt) override; + /** * Updates all Instances owned by a Template. * diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponentInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponentInterface.h index 0c758a21af..9792ec0fab 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponentInterface.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponentInterface.h @@ -53,6 +53,8 @@ namespace AzToolsFramework virtual PrefabDom& FindTemplateDom(TemplateId templateId) = 0; virtual void UpdatePrefabTemplate(TemplateId templateId, const PrefabDom& updatedDom) = 0; virtual void PropagateTemplateChanges(TemplateId templateId, InstanceOptionalReference instanceToExclude = AZStd::nullopt) = 0; + //! Propagates template changes recursively down to its dependents + virtual void PropagateTemplateChangesDown(TemplateId templateIdd, InstanceOptionalReference instanceToExclude = AZStd::nullopt) = 0; virtual AZStd::unique_ptr InstantiatePrefab(AZ::IO::PathView filePath) = 0; virtual AZStd::unique_ptr InstantiatePrefab(const TemplateId& templateId) = 0; From 8f21563ba95d042fc8263eacdd9821c4a93ab4f9 Mon Sep 17 00:00:00 2001 From: mnaumov Date: Thu, 12 Aug 2021 14:37:01 -0700 Subject: [PATCH 349/803] Undoing old changes and storing linkId to prefabDom Signed-off-by: mnaumov --- .../PrefabEditorEntityOwnershipService.cpp | 2 +- .../Prefab/Instance/InstanceSerializer.cpp | 7 +++++++ .../Prefab/PrefabSystemComponent.cpp | 18 ------------------ .../Prefab/PrefabSystemComponent.h | 2 -- .../Prefab/PrefabSystemComponentInterface.h | 2 -- 5 files changed, 8 insertions(+), 23 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp index 127f04424b..b5cf5fb878 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp @@ -202,7 +202,7 @@ namespace AzToolsFramework m_rootInstance->SetTemplateId(templateId); m_rootInstance->SetTemplateSourcePath(m_loaderInterface->GenerateRelativePath(filename)); m_rootInstance->SetContainerEntityName("Level"); - m_prefabSystemComponent->PropagateTemplateChangesDown(templateId); + m_prefabSystemComponent->PropagateTemplateChanges(templateId); return true; } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceSerializer.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceSerializer.cpp index b5a354ee74..89e0136b12 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceSerializer.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceSerializer.cpp @@ -81,6 +81,13 @@ namespace AzToolsFramework result.Combine(resultInstances); } + { + AZ::ScopedContextPath subPathSource(context, "m_linkId"); + + result = ContinueStoringToJsonObjectField( + outputValue, "LinkId", &(instance->m_linkId), &InvalidLinkId, azrtti_typeid(), context); + } + return context.Report(result, result.GetProcessing() == JSR::Processing::Completed ? "Successfully stored Instance information for Prefab." : "Failed to store Instance information for Prefab."); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp index b75f50198c..bfdb6b79f2 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp @@ -153,24 +153,6 @@ namespace AzToolsFramework } } - void PrefabSystemComponent::PropagateTemplateChangesDown(TemplateId templateId, InstanceOptionalReference instanceToExclude) - { - PropagateTemplateChanges(templateId, instanceToExclude); - - auto templateIterator = m_templateIdMap.find(templateId); - if (templateIterator != m_templateIdMap.end()) - { - for (LinkId linkId : templateIterator->second.GetLinks()) - { - auto linkIterator = m_linkIdMap.find(linkId); - if (linkIterator != m_linkIdMap.end()) - { - PropagateTemplateChangesDown(linkIterator->second.GetSourceTemplateId(), instanceToExclude); - } - } - } - } - void PrefabSystemComponent::UpdatePrefabTemplate(TemplateId templateId, const PrefabDom& updatedDom) { auto templateToUpdate = FindTemplate(templateId); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h index ccc17af133..04457b5a97 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h @@ -213,8 +213,6 @@ namespace AzToolsFramework void PropagateTemplateChanges(TemplateId templateId, InstanceOptionalReference instanceToExclude = AZStd::nullopt) override; - void PropagateTemplateChangesDown(TemplateId templateIdd, InstanceOptionalReference instanceToExclude = AZStd::nullopt) override; - /** * Updates all Instances owned by a Template. * diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponentInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponentInterface.h index 9792ec0fab..0c758a21af 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponentInterface.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponentInterface.h @@ -53,8 +53,6 @@ namespace AzToolsFramework virtual PrefabDom& FindTemplateDom(TemplateId templateId) = 0; virtual void UpdatePrefabTemplate(TemplateId templateId, const PrefabDom& updatedDom) = 0; virtual void PropagateTemplateChanges(TemplateId templateId, InstanceOptionalReference instanceToExclude = AZStd::nullopt) = 0; - //! Propagates template changes recursively down to its dependents - virtual void PropagateTemplateChangesDown(TemplateId templateIdd, InstanceOptionalReference instanceToExclude = AZStd::nullopt) = 0; virtual AZStd::unique_ptr InstantiatePrefab(AZ::IO::PathView filePath) = 0; virtual AZStd::unique_ptr InstantiatePrefab(const TemplateId& templateId) = 0; From c8cd3b1923971bf0b17b0b0fbcb7ad8d44c699ea Mon Sep 17 00:00:00 2001 From: mnaumov Date: Thu, 12 Aug 2021 14:39:15 -0700 Subject: [PATCH 350/803] reverting another file Signed-off-by: mnaumov --- .../Prefab/PrefabPublicHandler.cpp | 36 ++++++------------- 1 file changed, 11 insertions(+), 25 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp index 85fe30c252..69efe33d72 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp @@ -482,36 +482,22 @@ namespace AzToolsFramework AZStd::unique_ptr& sourceInstance, TemplateId targetTemplateId, UndoSystem::URSequencePoint* undoBatch) { LinkReference nestedInstanceLink = m_prefabSystemComponentInterface->FindLink(sourceInstance->GetLinkId()); - if (!nestedInstanceLink) - { - AZ_Assert( - false, - "A valid link was not found for one of the instances provided as input for the CreatePrefab operation."); - return; - } + AZ_Assert( + nestedInstanceLink.has_value(), + "A valid link was not found for one of the instances provided as input for the CreatePrefab operation."); PrefabDomReference nestedInstanceLinkDom = nestedInstanceLink->get().GetLinkDom(); - - if (!nestedInstanceLinkDom) - { - AZ_Assert( - false, - "A valid DOM was not found for the link corresponding to one of the instances provided as input for the " - "CreatePrefab operation."); - return; - } + AZ_Assert( + nestedInstanceLinkDom.has_value(), + "A valid DOM was not found for the link corresponding to one of the instances provided as input for the " + "CreatePrefab operation."); PrefabDomValueReference nestedInstanceLinkPatches = PrefabDomUtils::FindPrefabDomValue(nestedInstanceLinkDom->get(), PrefabDomUtils::PatchesName); - - if (!nestedInstanceLinkPatches) - { - AZ_Assert( - false, - "A valid DOM for patches was not found for the link corresponding to one of the instances provided as input for the " - "CreatePrefab operation."); - return; - } + AZ_Assert( + nestedInstanceLinkPatches.has_value(), + "A valid DOM for patches was not found for the link corresponding to one of the instances provided as input for the " + "CreatePrefab operation."); PrefabDom patchesCopyForUndoSupport; patchesCopyForUndoSupport.CopyFrom(nestedInstanceLinkPatches->get(), patchesCopyForUndoSupport.GetAllocator()); From bdbab1090a6970f057de0ac65e074204eefdbc2c Mon Sep 17 00:00:00 2001 From: Kyle B Date: Thu, 12 Aug 2021 14:49:25 -0700 Subject: [PATCH 351/803] removed accidental file addition Signed-off-by: Kyle B --- .../QuadSphere_Default.material | 28 ------------------- 1 file changed, 28 deletions(-) delete mode 100644 Gems/Atom/Tools/MaterialEditor/Assets/MaterialEditor/ViewportModels/QuadSphere_Default.material diff --git a/Gems/Atom/Tools/MaterialEditor/Assets/MaterialEditor/ViewportModels/QuadSphere_Default.material b/Gems/Atom/Tools/MaterialEditor/Assets/MaterialEditor/ViewportModels/QuadSphere_Default.material deleted file mode 100644 index 4905c302fe..0000000000 --- a/Gems/Atom/Tools/MaterialEditor/Assets/MaterialEditor/ViewportModels/QuadSphere_Default.material +++ /dev/null @@ -1,28 +0,0 @@ -{ - "description": "", - "materialType": "Materials/Types/StandardPBR.materialtype", - "parentMaterial": "", - "propertyLayoutVersion": 3, - "properties": { - "baseColor": { - "color": [ - 0.800000011920929, - 0.800000011920929, - 0.800000011920929, - 1.0 - ], - "textureMap": "MaterialEditor/ViewportModels/_dev_shaderball_00_basecolor.png" - }, - "emissive": { - "color": [ - 0.0, - 0.0, - 0.0, - 1.0 - ] - }, - "opacity": { - "factor": 1.0 - } - } -} \ No newline at end of file From 8f05c7aa2f9d63a46e5350a19587cf273492eee5 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Thu, 12 Aug 2021 16:42:18 -0700 Subject: [PATCH 352/803] Several build fixes --- .../Mac/AzFramework/Windowing/NativeWindow_Mac.mm | 2 +- .../iOS/AzFramework/Windowing/NativeWindow_ios.mm | 2 +- .../GridMate/Session/LANSession_Android.cpp | 1 + .../iOS/GridMate/Session/LANSession_iOS.cpp | 1 + Code/LauncherUnified/Platform/Mac/Launcher_Mac.mm | 1 + .../Platform/Windows/Launcher_Windows.cpp | 1 + Code/Legacy/CryCommon/AppleSpecific.h | 15 +++++++++++++++ Code/Legacy/CryCommon/CryLibrary.h | 2 +- Code/Legacy/CryCommon/MacSpecific.h | 2 ++ .../Scheduler/TestImpactProcessScheduler.cpp | 2 +- .../Enumeration/TestImpactTestEnumerator.cpp | 2 +- Gems/Atom/RHI/Metal/Code/Source/RHI/SwapChain.cpp | 1 + 12 files changed, 27 insertions(+), 5 deletions(-) diff --git a/Code/Framework/AzFramework/Platform/Mac/AzFramework/Windowing/NativeWindow_Mac.mm b/Code/Framework/AzFramework/Platform/Mac/AzFramework/Windowing/NativeWindow_Mac.mm index 2f9e3ab934..f9eef9170a 100644 --- a/Code/Framework/AzFramework/Platform/Mac/AzFramework/Windowing/NativeWindow_Mac.mm +++ b/Code/Framework/AzFramework/Platform/Mac/AzFramework/Windowing/NativeWindow_Mac.mm @@ -34,7 +34,7 @@ namespace AzFramework bool GetFullScreenState() const override; void SetFullScreenState(bool fullScreenState) override; bool CanToggleFullScreenState() const override { return true; } - uint32_t GetMainDisplayRefreshRate() const override; + uint32_t GetMainDisplayRefreshRate() const; private: static NSWindowStyleMask ConvertToNSWindowStyleMask(const WindowStyleMasks& styleMasks); diff --git a/Code/Framework/AzFramework/Platform/iOS/AzFramework/Windowing/NativeWindow_ios.mm b/Code/Framework/AzFramework/Platform/iOS/AzFramework/Windowing/NativeWindow_ios.mm index 3c829ec055..83e176b9ef 100644 --- a/Code/Framework/AzFramework/Platform/iOS/AzFramework/Windowing/NativeWindow_ios.mm +++ b/Code/Framework/AzFramework/Platform/iOS/AzFramework/Windowing/NativeWindow_ios.mm @@ -27,7 +27,7 @@ namespace AzFramework const WindowGeometry& geometry, const WindowStyleMasks& styleMasks) override; NativeWindowHandle GetWindowHandle() const override; - uint32_t GetMainDisplayRefreshRate() const override; + uint32_t GetMainDisplayRefreshRate() const; private: UIWindow* m_nativeWindow; diff --git a/Code/Framework/GridMate/Platform/Android/GridMate/Session/LANSession_Android.cpp b/Code/Framework/GridMate/Platform/Android/GridMate/Session/LANSession_Android.cpp index 05fb56dfc1..3fa2a369a6 100644 --- a/Code/Framework/GridMate/Platform/Android/GridMate/Session/LANSession_Android.cpp +++ b/Code/Framework/GridMate/Platform/Android/GridMate/Session/LANSession_Android.cpp @@ -7,6 +7,7 @@ */ #include +#include namespace GridMate { diff --git a/Code/Framework/GridMate/Platform/iOS/GridMate/Session/LANSession_iOS.cpp b/Code/Framework/GridMate/Platform/iOS/GridMate/Session/LANSession_iOS.cpp index 05fb56dfc1..3fa2a369a6 100644 --- a/Code/Framework/GridMate/Platform/iOS/GridMate/Session/LANSession_iOS.cpp +++ b/Code/Framework/GridMate/Platform/iOS/GridMate/Session/LANSession_iOS.cpp @@ -7,6 +7,7 @@ */ #include +#include namespace GridMate { diff --git a/Code/LauncherUnified/Platform/Mac/Launcher_Mac.mm b/Code/LauncherUnified/Platform/Mac/Launcher_Mac.mm index cfba0d8aac..cbd5a043e1 100644 --- a/Code/LauncherUnified/Platform/Mac/Launcher_Mac.mm +++ b/Code/LauncherUnified/Platform/Mac/Launcher_Mac.mm @@ -10,6 +10,7 @@ #include #include <../Common/Apple/Launcher_Apple.h> #include <../Common/UnixLike/Launcher_UnixLike.h> +#include #if AZ_TESTS_ENABLED diff --git a/Code/LauncherUnified/Platform/Windows/Launcher_Windows.cpp b/Code/LauncherUnified/Platform/Windows/Launcher_Windows.cpp index 5cc3070cdb..44426f6d01 100644 --- a/Code/LauncherUnified/Platform/Windows/Launcher_Windows.cpp +++ b/Code/LauncherUnified/Platform/Windows/Launcher_Windows.cpp @@ -9,6 +9,7 @@ #include #include +#include int APIENTRY WinMain([[maybe_unused]] HINSTANCE hInstance, [[maybe_unused]] HINSTANCE hPrevInstance, [[maybe_unused]] LPSTR lpCmdLine, [[maybe_unused]] int nCmdShow) { diff --git a/Code/Legacy/CryCommon/AppleSpecific.h b/Code/Legacy/CryCommon/AppleSpecific.h index c572250b26..cd3146403a 100644 --- a/Code/Legacy/CryCommon/AppleSpecific.h +++ b/Code/Legacy/CryCommon/AppleSpecific.h @@ -226,6 +226,21 @@ typedef uint64 __uint64; #define _PTRDIFF_T_DEFINED 1 +typedef union _LARGE_INTEGER +{ + struct + { + DWORD LowPart; + LONG HighPart; + }; + struct + { + DWORD LowPart; + LONG HighPart; + } u; + long long QuadPart; +} LARGE_INTEGER; + #define _A_RDONLY (0x01) /* Read only file */ #define _A_HIDDEN (0x02) /* Hidden file */ #define _A_SUBDIR (0x10) /* Subdirectory */ diff --git a/Code/Legacy/CryCommon/CryLibrary.h b/Code/Legacy/CryCommon/CryLibrary.h index 787085af00..a034a2a04b 100644 --- a/Code/Legacy/CryCommon/CryLibrary.h +++ b/Code/Legacy/CryCommon/CryLibrary.h @@ -49,7 +49,7 @@ */ #include -#include +#include #include #define INJECT_ENVIRONMENT_FUNCTION "InjectEnvironment" diff --git a/Code/Legacy/CryCommon/MacSpecific.h b/Code/Legacy/CryCommon/MacSpecific.h index 0533a1b556..1bc8c8a34b 100644 --- a/Code/Legacy/CryCommon/MacSpecific.h +++ b/Code/Legacy/CryCommon/MacSpecific.h @@ -26,4 +26,6 @@ typedef uint64_t threadID; +#define VK_CONTROL 0 + #endif // CRYINCLUDE_CRYCOMMON_MACSPECIFIC_H diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Source/Process/Scheduler/TestImpactProcessScheduler.cpp b/Code/Tools/TestImpactFramework/Runtime/Code/Source/Process/Scheduler/TestImpactProcessScheduler.cpp index a7e20a76f7..94df662a1d 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Source/Process/Scheduler/TestImpactProcessScheduler.cpp +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Source/Process/Scheduler/TestImpactProcessScheduler.cpp @@ -230,7 +230,7 @@ namespace TestImpact processInFlight.m_process = LaunchProcess(AZStd::move(processInfo)); processInFlight.m_startTime = createTime; } - catch (ProcessException& e) + catch ([[maybe_unused]] ProcessException& e) { AZ_Warning("ProcessScheduler", false, e.what()); createResult = LaunchResult::Failure; diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Enumeration/TestImpactTestEnumerator.cpp b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Enumeration/TestImpactTestEnumerator.cpp index e564b93f6c..756b1c75d6 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Enumeration/TestImpactTestEnumerator.cpp +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Enumeration/TestImpactTestEnumerator.cpp @@ -169,7 +169,7 @@ namespace TestImpact WriteFileContents(SerializeTestEnumeration(enumeration.value()), jobInfo->GetCache()->m_file); } } - catch (const Exception& e) + catch ([[maybe_unused]] const Exception& e) { AZ_Warning("Enumerate", false, e.what()); enumerations[jobId] = AZStd::nullopt; diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/SwapChain.cpp b/Gems/Atom/RHI/Metal/Code/Source/RHI/SwapChain.cpp index df0961564d..0065ea724e 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/SwapChain.cpp +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/SwapChain.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include #include From b4f6dc5bff2640fbef603f11099250310f4bd757 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Thu, 12 Aug 2021 16:44:01 -0700 Subject: [PATCH 353/803] fixes after merge Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- cmake/Platform/Common/MSVC/Configurations_msvc.cmake | 2 +- cmake/cmake_files.cmake | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/cmake/Platform/Common/MSVC/Configurations_msvc.cmake b/cmake/Platform/Common/MSVC/Configurations_msvc.cmake index c0d0809b0f..891d48ddb2 100644 --- a/cmake/Platform/Common/MSVC/Configurations_msvc.cmake +++ b/cmake/Platform/Common/MSVC/Configurations_msvc.cmake @@ -95,7 +95,7 @@ ly_append_configurations_options( set(LY_BUILD_WITH_ADDRESS_SANITIZER FALSE CACHE BOOL "Builds using AddressSanitizer (ASan). Will disable Edit/Continue, Incremental building and Run-Time checks (default = FALSE)") if(LY_BUILD_WITH_ADDRESS_SANITIZER) - set(LY_BUILD_WITH_INCREMENTAL_LINKING_DEBUG FALSE) + set(LY_BUILD_WITH_INCREMENTAL_LINKING_DEBUG FALSE) ly_append_configurations_options( COMPILATION_DEBUG /fsanitize=address diff --git a/cmake/cmake_files.cmake b/cmake/cmake_files.cmake index 10676b384e..aa275b634a 100644 --- a/cmake/cmake_files.cmake +++ b/cmake/cmake_files.cmake @@ -20,7 +20,6 @@ set(FILES Findo3de.cmake Gems.cmake GeneralSettings.cmake - Initialize.cmake Install.cmake LyAutoGen.cmake LYPackage_S3Downloader.cmake From a087fc06a9bc833aba1eaf42aa8a1eeb5295cc77 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Thu, 12 Aug 2021 16:44:25 -0700 Subject: [PATCH 354/803] fixes for ASAn Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Framework/AzCore/AzCore/std/string/string_view.h | 5 ++++- Code/Framework/AzCore/Tests/AZStd/String.cpp | 8 ++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/std/string/string_view.h b/Code/Framework/AzCore/AzCore/std/string/string_view.h index 9a98795554..4ded44644f 100644 --- a/Code/Framework/AzCore/AzCore/std/string/string_view.h +++ b/Code/Framework/AzCore/AzCore/std/string/string_view.h @@ -7,7 +7,6 @@ */ #pragma once -#include #include #include @@ -46,6 +45,10 @@ namespace AZStd return npos; } size_t foundIndex = searchIndex + charFindIndex; + if (foundIndex + count > size) + { + return npos; // the rest of the string doesnt fit in the remainder of the data buffer + } if (Traits::compare(&data[foundIndex], ptr, count) == 0) { return foundIndex; diff --git a/Code/Framework/AzCore/Tests/AZStd/String.cpp b/Code/Framework/AzCore/Tests/AZStd/String.cpp index 9dae4a3d3f..a88de48b9b 100644 --- a/Code/Framework/AzCore/Tests/AZStd/String.cpp +++ b/Code/Framework/AzCore/Tests/AZStd/String.cpp @@ -1458,17 +1458,17 @@ namespace UnitTest constexpr double v15 = 0; constexpr const char* v16 = "Hello"; constexpr const wchar_t* v17 = L"Hello"; - constexpr void* v18 = 0; + constexpr void* v18 = nullptr; // This shouldn't give a compile error AZStd::string::format( - "%i %c %uc %c %c %i %i %u %i %lu %li %llu %lli %f %f %s %ls %p", + "%i %c %uc %hc %lc %i %i %u %i %lu %li %llu %lli %f %f %hs %ls %p", v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18); // This shouldn't give a compile error AZStd::wstring::format( - L"%i %c %uc %c %lc %i %i %u %i %lu %li %llu %lli %f %f %s %ls %p", - v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18); + L"%i %c %uc %hc %lc %i %i %u %i %lu %li %llu %lli %f %f %hs %ls %p", + v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18); class WrappedInt { From 89e1b6db255fa4f09ccd2a306d76cd58a70985f4 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Thu, 12 Aug 2021 16:44:59 -0700 Subject: [PATCH 355/803] Making allocator use the MallocSchema so we can take full advantage of ASan Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Framework/AzCore/AzCore/IO/Path/Path.inl | 1 + .../AzCore/AzCore/Memory/SystemAllocator.cpp | 66 ++++---- Code/Framework/AzCore/CMakeLists.txt | 9 + .../AzFramework/Physics/Common/PhysicsTypes.h | 1 + Code/Legacy/CryCommon/LegacyAllocator.cpp | 79 +++++++++ Code/Legacy/CryCommon/LegacyAllocator.h | 157 ++---------------- Code/Legacy/CryCommon/crycommon_files.cmake | 1 + 7 files changed, 138 insertions(+), 176 deletions(-) create mode 100644 Code/Legacy/CryCommon/LegacyAllocator.cpp diff --git a/Code/Framework/AzCore/AzCore/IO/Path/Path.inl b/Code/Framework/AzCore/AzCore/IO/Path/Path.inl index 4e8356b436..ad1d09bc01 100644 --- a/Code/Framework/AzCore/AzCore/IO/Path/Path.inl +++ b/Code/Framework/AzCore/AzCore/IO/Path/Path.inl @@ -10,6 +10,7 @@ #include #include +#include // extern instantiations of Path templates to prevent implicit instantiations namespace AZ::IO diff --git a/Code/Framework/AzCore/AzCore/Memory/SystemAllocator.cpp b/Code/Framework/AzCore/AzCore/Memory/SystemAllocator.cpp index ada6c8f330..07c919cf00 100644 --- a/Code/Framework/AzCore/AzCore/Memory/SystemAllocator.cpp +++ b/Code/Framework/AzCore/AzCore/Memory/SystemAllocator.cpp @@ -17,15 +17,23 @@ #include -#define AZCORE_SYS_ALLOCATOR_HPPA // If you disable this make sure you start building the heapschema.cpp -//#define AZCORE_SYS_ALLOCATOR_MALLOC +#define AZCORE_SYSTEM_ALLOCATOR_HPHA 1 +#define AZCORE_SYSTEM_ALLOCATOR_MALLOC 2 +#define AZCORE_SYSTEM_ALLOCATOR_HEAP 3 -#ifdef AZCORE_SYS_ALLOCATOR_HPPA -# include -#elif defined(AZCORE_SYS_ALLOCATOR_MALLOC) -#include +#if !defined(AZCORE_SYSTEM_ALLOCATOR) + // define the default + #define AZCORE_SYSTEM_ALLOCATOR AZCORE_SYSTEM_ALLOCATOR_HPHA +#endif + +#if AZCORE_SYSTEM_ALLOCATOR == AZCORE_SYSTEM_ALLOCATOR_HPHA + #include +#elif AZCORE_SYSTEM_ALLOCATOR == AZCORE_SYSTEM_ALLOCATOR_MALLOC + #include +#elif AZCORE_SYSTEM_ALLOCATOR == AZCORE_SYSTEM_ALLOCATOR_HEAP + #include #else -# include + #error "Invalid allocator selected for SystemAllocator" #endif @@ -34,12 +42,12 @@ using namespace AZ; ////////////////////////////////////////////////////////////////////////// // Globals - we use global storage for the first memory schema, since we can't use dynamic memory! static bool g_isSystemSchemaUsed = false; -#ifdef AZCORE_SYS_ALLOCATOR_HPPA -static AZStd::aligned_storage::value>::type g_systemSchema; -#elif defined(AZCORE_SYS_ALLOCATOR_MALLOC) -static AZStd::aligned_storage::value>::type g_systemSchema; -#else -static AZStd::aligned_storage::value>::type g_systemSchema; +#if AZCORE_SYSTEM_ALLOCATOR == AZCORE_SYSTEM_ALLOCATOR_HPHA + static AZStd::aligned_storage::value>::type g_systemSchema; +#elif AZCORE_SYSTEM_ALLOCATOR == AZCORE_SYSTEM_ALLOCATOR_MALLOC + static AZStd::aligned_storage::value>::type g_systemSchema; +#elif AZCORE_SYSTEM_ALLOCATOR == AZCORE_SYSTEM_ALLOCATOR_HEAP + static AZStd::aligned_storage::value>::type g_systemSchema; #endif ////////////////////////////////////////////////////////////////////////// @@ -97,9 +105,9 @@ SystemAllocator::Create(const Descriptor& desc) else { m_isCustom = false; -#ifdef AZCORE_SYS_ALLOCATOR_HPPA - HphaSchema::Descriptor heapDesc; - heapDesc.m_pageSize = desc.m_heap.m_pageSize; +#if AZCORE_SYSTEM_ALLOCATOR == AZCORE_SYSTEM_ALLOCATOR_HPHA + HphaSchema::Descriptor heapDesc; + heapDesc.m_pageSize = desc.m_heap.m_pageSize; heapDesc.m_poolPageSize = desc.m_heap.m_poolPageSize; AZ_Assert(desc.m_heap.m_numFixedMemoryBlocks <= 1, "We support max1 memory block at the moment!"); if (desc.m_heap.m_numFixedMemoryBlocks > 0) @@ -111,11 +119,10 @@ SystemAllocator::Create(const Descriptor& desc) heapDesc.m_isPoolAllocations = desc.m_heap.m_isPoolAllocations; // Fix SystemAllocator from growing in small chunks heapDesc.m_systemChunkSize = desc.m_heap.m_systemChunkSize; - -#elif defined(AZCORE_SYS_ALLOCATOR_MALLOC) +#elif AZCORE_SYSTEM_ALLOCATOR == AZCORE_SYSTEM_ALLOCATOR_MALLOC MallocSchema::Descriptor heapDesc; -#else - HeapSchema::Descriptor heapDesc; +#elif AZCORE_SYSTEM_ALLOCATOR == AZCORE_SYSTEM_ALLOCATOR_HEAP + HeapSchema::Descriptor heapDesc; memcpy(heapDesc.m_memoryBlocks, desc.m_heap.m_memoryBlocks, sizeof(heapDesc.m_memoryBlocks)); memcpy(heapDesc.m_memoryBlocksByteSize, desc.m_heap.m_memoryBlocksByteSize, sizeof(heapDesc.m_memoryBlocksByteSize)); heapDesc.m_numMemoryBlocks = desc.m_heap.m_numMemoryBlocks; @@ -124,11 +131,11 @@ SystemAllocator::Create(const Descriptor& desc) { AZ_Assert(!g_isSystemSchemaUsed, "AZ::SystemAllocator MUST be created first! It's the source of all allocations!"); -#ifdef AZCORE_SYS_ALLOCATOR_HPPA +#if AZCORE_SYSTEM_ALLOCATOR == AZCORE_SYSTEM_ALLOCATOR_HPHA m_allocator = new(&g_systemSchema)HphaSchema(heapDesc); -#elif defined(AZCORE_SYS_ALLOCATOR_MALLOC) +#elif AZCORE_SYSTEM_ALLOCATOR == AZCORE_SYSTEM_ALLOCATOR_MALLOC m_allocator = new(&g_systemSchema)MallocSchema(heapDesc); -#else +#elif AZCORE_SYSTEM_ALLOCATOR == AZCORE_SYSTEM_ALLOCATOR_HEAP m_allocator = new(&g_systemSchema)HeapSchema(heapDesc); #endif g_isSystemSchemaUsed = true; @@ -139,14 +146,13 @@ SystemAllocator::Create(const Descriptor& desc) // this class should be inheriting from SystemAllocator AZ_Assert(AllocatorInstance::IsReady(), "System allocator must be created before any other allocator! They allocate from it."); -#ifdef AZCORE_SYS_ALLOCATOR_HPPA +#if AZCORE_SYSTEM_ALLOCATOR == AZCORE_SYSTEM_ALLOCATOR_HPHA m_allocator = azcreate(HphaSchema, (heapDesc), SystemAllocator); -#elif defined(AZCORE_SYS_ALLOCATOR_MALLOC) +#elif AZCORE_SYSTEM_ALLOCATOR == AZCORE_SYSTEM_ALLOCATOR_MALLOC m_allocator = azcreate(MallocSchema, (heapDesc), SystemAllocator); -#else +#elif AZCORE_SYSTEM_ALLOCATOR == AZCORE_SYSTEM_ALLOCATOR_HEAP m_allocator = azcreate(HeapSchema, (heapDesc), SystemAllocator); #endif - if (m_allocator == NULL) { isReady = false; @@ -178,11 +184,11 @@ SystemAllocator::Destroy() { if ((void*)m_allocator == (void*)&g_systemSchema) { -#ifdef AZCORE_SYS_ALLOCATOR_HPPA +#if AZCORE_SYSTEM_ALLOCATOR == AZCORE_SYSTEM_ALLOCATOR_HPHA static_cast(m_allocator)->~HphaSchema(); -#elif defined(AZCORE_SYS_ALLOCATOR_MALLOC) +#elif AZCORE_SYSTEM_ALLOCATOR == AZCORE_SYSTEM_ALLOCATOR_MALLOC static_cast(m_allocator)->~MallocSchema(); -#else +#elif AZCORE_SYSTEM_ALLOCATOR == AZCORE_SYSTEM_ALLOCATOR_HEAP static_cast(m_allocator)->~HeapSchema(); #endif g_isSystemSchemaUsed = false; diff --git a/Code/Framework/AzCore/CMakeLists.txt b/Code/Framework/AzCore/CMakeLists.txt index ea7cc27af5..e3898ec17e 100644 --- a/Code/Framework/AzCore/CMakeLists.txt +++ b/Code/Framework/AzCore/CMakeLists.txt @@ -54,6 +54,15 @@ ly_add_source_properties( VALUES ${LY_PAL_TOOLS_DEFINES} ) +if(LY_BUILD_WITH_ADDRESS_SANITIZER) + # Default to use Malloc schema so ASan works well + ly_add_source_properties( + SOURCES AzCore/Memory/SystemAllocator.cpp + PROPERTY COMPILE_DEFINITIONS + VALUES AZCORE_SYSTEM_ALLOCATOR=AZCORE_SYSTEM_ALLOCATOR_MALLOC + ) +endif() + ################################################################################ # Tests ################################################################################ diff --git a/Code/Framework/AzFramework/AzFramework/Physics/Common/PhysicsTypes.h b/Code/Framework/AzFramework/AzFramework/Physics/Common/PhysicsTypes.h index bb53d6d3dd..e224c0ab22 100644 --- a/Code/Framework/AzFramework/AzFramework/Physics/Common/PhysicsTypes.h +++ b/Code/Framework/AzFramework/AzFramework/Physics/Common/PhysicsTypes.h @@ -13,6 +13,7 @@ #include #include #include +#include namespace Physics { diff --git a/Code/Legacy/CryCommon/LegacyAllocator.cpp b/Code/Legacy/CryCommon/LegacyAllocator.cpp new file mode 100644 index 0000000000..9c4258530a --- /dev/null +++ b/Code/Legacy/CryCommon/LegacyAllocator.cpp @@ -0,0 +1,79 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#pragma once + +#include + +namespace AZ +{ + LegacyAllocator::pointer_type LegacyAllocator::Allocate(size_type byteSize, size_type alignment, int flags, const char* name, const char* fileName, int lineNum, unsigned int suppressStackRecord) + { + if (alignment == 0) + { + // Some STL containers, like std::vector, are assuming a specific minimum alignment. seems to have a requirement + // Take a look at _Allocate_manually_vector_aligned in xmemory0 + alignment = sizeof(void*) * 2; + } + + pointer_type ptr = m_schema->Allocate(byteSize, alignment, flags, name, fileName, lineNum, suppressStackRecord); + AZ_PROFILE_MEMORY_ALLOC_EX(AZ::Debug::ProfileCategory::MemoryReserved, fileName, lineNum, ptr, byteSize, name ? name : GetName()); + AZ_MEMORY_PROFILE(ProfileAllocation(ptr, byteSize, alignment, name, fileName, lineNum, suppressStackRecord)); + AZ_Assert(ptr || byteSize == 0, "OOM - Failed to allocate %zu bytes from LegacyAllocator", byteSize); + return ptr; + } + + // DeAllocate with file/line, to track when allocs were freed from Cry + void LegacyAllocator::DeAllocate(pointer_type ptr, [[maybe_unused]] const char* file, [[maybe_unused]] const int line, size_type byteSize, size_type alignment) + { + AZ_PROFILE_MEMORY_FREE_EX(AZ::Debug::ProfileCategory::MemoryReserved, file, line, ptr); + AZ_MEMORY_PROFILE(ProfileDeallocation(ptr, byteSize, alignment, nullptr)); + m_schema->DeAllocate(ptr, byteSize, alignment); + } + + // Realloc with file/line, because Cry uses realloc(nullptr) and realloc(ptr, 0) to mimic malloc/free + LegacyAllocator::pointer_type LegacyAllocator::ReAllocate(pointer_type ptr, size_type newSize, size_type newAlignment, [[maybe_unused]] const char* file, [[maybe_unused]] const int line) + { + if (newAlignment == 0) + { + // Some STL containers, like std::vector, are assuming a specific minimum alignment. seems to have a requirement + // Take a look at _Allocate_manually_vector_aligned in xmemory0 + newAlignment = sizeof(void*) * 2; + } + + AZ_MEMORY_PROFILE(ProfileReallocationBegin(ptr, newSize)); + AZ_PROFILE_MEMORY_FREE_EX(AZ::Debug::ProfileCategory::MemoryReserved, file, line, ptr); + pointer_type newPtr = m_schema->ReAllocate(ptr, newSize, newAlignment); + AZ_PROFILE_MEMORY_ALLOC_EX(AZ::Debug::ProfileCategory::MemoryReserved, file, line, newPtr, newSize, "LegacyAllocator Realloc"); + AZ_MEMORY_PROFILE(ProfileReallocationEnd(ptr, newPtr, newSize, newAlignment)); + AZ_Assert(newPtr || newSize == 0, "OOM - Failed to reallocate %zu bytes from LegacyAllocator", newSize); + return newPtr; + } + + void LegacyAllocator::DeAllocate(pointer_type ptr, size_type byteSize, size_type alignment) + { + AZ_MEMORY_PROFILE(ProfileDeallocation(ptr, 0, 0, nullptr)); + Base::DeAllocate(ptr, byteSize, alignment); + } + + LegacyAllocator::pointer_type LegacyAllocator::ReAllocate(pointer_type ptr, size_type newSize, size_type newAlignment) + { + if (newAlignment == 0) + { + // Some STL containers, like std::vector, are assuming a specific minimum alignment. seems to have a requirement + // Take a look at _Allocate_manually_vector_aligned in xmemory0 + newAlignment = sizeof(void*) * 2; + } + + AZ_MEMORY_PROFILE(ProfileReallocationBegin(ptr, newSize)); + pointer_type newPtr = Base::ReAllocate(ptr, newSize, newAlignment); + AZ_MEMORY_PROFILE(ProfileReallocationEnd(ptr, newPtr, newSize, newAlignment)); + AZ_Assert(newPtr || newSize == 0, "OOM - Failed to reallocate %zu bytes from LegacyAllocator", newSize); + return newPtr; + } +} diff --git a/Code/Legacy/CryCommon/LegacyAllocator.h b/Code/Legacy/CryCommon/LegacyAllocator.h index 074c183de4..2b1055958b 100644 --- a/Code/Legacy/CryCommon/LegacyAllocator.h +++ b/Code/Legacy/CryCommon/LegacyAllocator.h @@ -11,118 +11,36 @@ #include #include -#define AZCORE_SYS_ALLOCATOR_HPPA -//#define AZCORE_SYS_ALLOCATOR_MALLOC - -#ifdef AZCORE_SYS_ALLOCATOR_HPPA -# include -#elif defined(AZCORE_SYS_ALLOCATOR_MALLOC) -# include -#else -# include -#endif - namespace AZ { - -#ifdef AZCORE_SYS_ALLOCATOR_HPPA - typedef AZ::HphaSchema LegacyAllocatorSchema; -#elif defined(AZCORE_SYS_ALLOCATOR_MALLOC) - typedef AZ::MallocSchema LegacyAllocatorSchema; -#else - typedef AZ::HeapSchema LegacyAllocatorSchema; -#endif - - struct LegacyAllocatorDescriptor - : public LegacyAllocatorSchema::Descriptor - { - LegacyAllocatorDescriptor() - { - // pull 32MB from the OS at a time -#ifdef AZCORE_SYS_ALLOCATOR_HPPA - m_systemChunkSize = 32 * 1024 * 1024; -#endif - } - }; - class LegacyAllocator - : public SimpleSchemaAllocator + : public SimpleSchemaAllocator { public: AZ_TYPE_INFO(LegacyAllocator, "{17FC25A4-92D9-48C5-BB85-7F860FCA2C6F}"); - using Descriptor = LegacyAllocatorDescriptor; - using Base = SimpleSchemaAllocator; + using Descriptor = AZ::HphaSchema::Descriptor; + using Base = SimpleSchemaAllocator; + using pointer_type = typename Base::pointer_type; + using size_type = typename Base::size_type; + using difference_type = typename Base::difference_type; LegacyAllocator() : Base("LegacyAllocator", "Allocator for Legacy CryEngine systems") { } - pointer_type Allocate(size_type byteSize, size_type alignment, int flags = 0, const char* name = 0, const char* fileName = 0, int lineNum = 0, unsigned int suppressStackRecord = 0) override - { - if (alignment == 0) - { - // Some STL containers, like std::vector, are assuming a specific minimum alignment. seems to have a requirement - // Take a look at _Allocate_manually_vector_aligned in xmemory0 - alignment = sizeof(void*) * 2; - } - - pointer_type ptr = m_schema->Allocate(byteSize, alignment, flags, name, fileName, lineNum, suppressStackRecord); - AZ_PROFILE_MEMORY_ALLOC_EX(AZ::Debug::ProfileCategory::MemoryReserved, fileName, lineNum, ptr, byteSize, name ? name : GetName()); - AZ_MEMORY_PROFILE(ProfileAllocation(ptr, byteSize, alignment, name, fileName, lineNum, suppressStackRecord)); - AZ_Assert(ptr || byteSize == 0, "OOM - Failed to allocate %zu bytes from LegacyAllocator", byteSize); - return ptr; - } + pointer_type Allocate(size_type byteSize, size_type alignment, int flags = 0, const char* name = 0, const char* fileName = 0, int lineNum = 0, unsigned int suppressStackRecord = 0) override; // DeAllocate with file/line, to track when allocs were freed from Cry - void DeAllocate(pointer_type ptr, [[maybe_unused]] const char* file, [[maybe_unused]] const int line, size_type byteSize = 0, size_type alignment = 0) - { - AZ_PROFILE_MEMORY_FREE_EX(AZ::Debug::ProfileCategory::MemoryReserved, file, line, ptr); - AZ_MEMORY_PROFILE(ProfileDeallocation(ptr, byteSize, alignment, nullptr)); - m_schema->DeAllocate(ptr, byteSize, alignment); - } + void DeAllocate(pointer_type ptr, const char* file, const int line, size_type byteSize = 0, size_type alignment = 0); // Realloc with file/line, because Cry uses realloc(nullptr) and realloc(ptr, 0) to mimic malloc/free - pointer_type ReAllocate(pointer_type ptr, size_type newSize, size_type newAlignment, [[maybe_unused]] const char* file, [[maybe_unused]] const int line) - { - if (newAlignment == 0) - { - // Some STL containers, like std::vector, are assuming a specific minimum alignment. seems to have a requirement - // Take a look at _Allocate_manually_vector_aligned in xmemory0 - newAlignment = sizeof(void*) * 2; - } + pointer_type ReAllocate(pointer_type ptr, size_type newSize, size_type newAlignment, const char* file, const int line); - AZ_MEMORY_PROFILE(ProfileReallocationBegin(ptr, newSize)); - AZ_PROFILE_MEMORY_FREE_EX(AZ::Debug::ProfileCategory::MemoryReserved, file, line, ptr); - pointer_type newPtr = m_schema->ReAllocate(ptr, newSize, newAlignment); - AZ_PROFILE_MEMORY_ALLOC_EX(AZ::Debug::ProfileCategory::MemoryReserved, file, line, newPtr, newSize, "LegacyAllocator Realloc"); - AZ_MEMORY_PROFILE(ProfileReallocationEnd(ptr, newPtr, newSize, newAlignment)); - AZ_Assert(newPtr || newSize == 0, "OOM - Failed to reallocate %zu bytes from LegacyAllocator", newSize); - return newPtr; - } + void DeAllocate(pointer_type ptr, size_type byteSize = 0, size_type alignment = 0) override; - void DeAllocate(pointer_type ptr, size_type byteSize = 0, size_type alignment = 0) override - { - AZ_MEMORY_PROFILE(ProfileDeallocation(ptr, 0, 0, nullptr)); - Base::DeAllocate(ptr, byteSize, alignment); - } - - pointer_type ReAllocate(pointer_type ptr, size_type newSize, size_type newAlignment) override - { - if (newAlignment == 0) - { - // Some STL containers, like std::vector, are assuming a specific minimum alignment. seems to have a requirement - // Take a look at _Allocate_manually_vector_aligned in xmemory0 - newAlignment = sizeof(void*) * 2; - } - - AZ_MEMORY_PROFILE(ProfileReallocationBegin(ptr, newSize)); - pointer_type newPtr = Base::ReAllocate(ptr, newSize, newAlignment); - AZ_MEMORY_PROFILE(ProfileReallocationEnd(ptr, newPtr, newSize, newAlignment)); - AZ_Assert(newPtr || newSize == 0, "OOM - Failed to reallocate %zu bytes from LegacyAllocator", newSize); - return newPtr; - } + pointer_type ReAllocate(pointer_type ptr, size_type newSize, size_type newAlignment) override; }; using StdLegacyAllocator = AZStdAlloc; @@ -133,57 +51,4 @@ namespace AZ class AllocatorInstance : public Internal::AllocatorInstanceBase { }; - -#if defined(AZ_PLATFORM_PROVO) || defined(AZ_PLATFORM_JASPER) - struct GlobalAllocatorDescriptor - : public AZ::HphaSchema::Descriptor - { - GlobalAllocatorDescriptor() - { - // pull 1MB from the OS at a time - m_systemChunkSize = 1024 * 1024; - } - }; - - class GlobalAllocator - : public SimpleSchemaAllocator - { - public: - AZ_TYPE_INFO(GlobalAllocator, "{BC7861DA-AF7F-4FFD-A2F5-BAD89BDD77FD}"); - - using Descriptor = GlobalAllocatorDescriptor; - using Base = SimpleSchemaAllocator; - - GlobalAllocator() - : Base("GlobalAllocator", "Allocator for untracked new/delete/malloc/free") - { - } - - //--------------------------------------------------------------------- - // IAllocatorAllocate - //--------------------------------------------------------------------- - pointer_type Allocate(size_type byteSize, size_type alignment, int flags = 0, const char* name = 0, const char* fileName = 0, int lineNum = 0, unsigned int suppressStackRecord = 0) override - { - // Note: We cannot put the asserts in the AllocateBase class because various allocators depend on allocations failing from some heap classes. - pointer_type ptr = Base::Allocate(byteSize, alignment, flags, name, fileName, lineNum, suppressStackRecord); - AZ_Assert(ptr, "OOM - Failed to allocate %zu bytes from GlobalAllocator", byteSize); - return ptr; - } - - pointer_type ReAllocate(pointer_type ptr, size_type newSize, size_type newAlignment) override - { - pointer_type newPtr = Base::ReAllocate(ptr, newSize, newAlignment); - AZ_Assert(newPtr, "OOM - Failed to reallocate %zu bytes from GlobalAllocator", newSize); - return newPtr; - } - - }; - - // Specialize for the GlobalAllocator to provide one per module that does not use the - // environment for its storage - template <> - class AllocatorInstance : public Internal::AllocatorInstanceBase> - { - }; -#endif } diff --git a/Code/Legacy/CryCommon/crycommon_files.cmake b/Code/Legacy/CryCommon/crycommon_files.cmake index 8d33b85eff..d3613baed6 100644 --- a/Code/Legacy/CryCommon/crycommon_files.cmake +++ b/Code/Legacy/CryCommon/crycommon_files.cmake @@ -92,6 +92,7 @@ set(FILES CryVersion.h FrameProfiler.h HeapAllocator.h + LegacyAllocator.cpp LegacyAllocator.h MetaUtils.h MiniQueue.h From f0ff8da1d772a74c6c880c7a003ccf57f2c13473 Mon Sep 17 00:00:00 2001 From: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> Date: Thu, 12 Aug 2021 16:51:54 -0700 Subject: [PATCH 356/803] [redcode/crythread-2nd-pass] post merge duplicates removed Signed-off-by: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> --- Code/LauncherUnified/Platform/Mac/Launcher_Mac.mm | 2 -- Code/Legacy/CryCommon/AppleSpecific.h | 15 --------------- 2 files changed, 17 deletions(-) diff --git a/Code/LauncherUnified/Platform/Mac/Launcher_Mac.mm b/Code/LauncherUnified/Platform/Mac/Launcher_Mac.mm index 3396200b87..cbd5a043e1 100644 --- a/Code/LauncherUnified/Platform/Mac/Launcher_Mac.mm +++ b/Code/LauncherUnified/Platform/Mac/Launcher_Mac.mm @@ -12,8 +12,6 @@ #include <../Common/UnixLike/Launcher_UnixLike.h> #include -#include - #if AZ_TESTS_ENABLED int main(int argc, char* argv[]) diff --git a/Code/Legacy/CryCommon/AppleSpecific.h b/Code/Legacy/CryCommon/AppleSpecific.h index 92fa318b87..cd3146403a 100644 --- a/Code/Legacy/CryCommon/AppleSpecific.h +++ b/Code/Legacy/CryCommon/AppleSpecific.h @@ -473,21 +473,6 @@ typedef HANDLE HMENU; #endif //__cplusplus -typedef union _LARGE_INTEGER -{ - struct - { - DWORD LowPart; - LONG HighPart; - }; - struct - { - DWORD LowPart; - LONG HighPart; - } u; - long long QuadPart; -} LARGE_INTEGER; - extern bool QueryPerformanceCounter(LARGE_INTEGER*); extern bool QueryPerformanceFrequency(LARGE_INTEGER* frequency); From 6acbea722ef101227896366bd6e9518f9d691da7 Mon Sep 17 00:00:00 2001 From: Kyle B Date: Thu, 12 Aug 2021 18:15:17 -0700 Subject: [PATCH 357/803] minor syntax changes and adding a refresh tree attributeto the editor component Signed-off-by: Kyle B --- .../Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h | 2 +- .../Include/Atom/Feature/Mesh/MeshFeatureProcessorInterface.h | 2 +- .../Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp | 2 +- .../CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp | 1 + 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h index daf4a493c2..a448f7121f 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h @@ -155,7 +155,7 @@ namespace AZ void SetSortKey(const MeshHandle& meshHandle, RHI::DrawItemSortKey sortKey) override; RHI::DrawItemSortKey GetSortKey(const MeshHandle& meshHandle) override; - void SetMeshLodConfiguration(const MeshHandle& meshHandle, RPI::Cullable::LodConfiguration meshLodConfig); + void SetMeshLodConfiguration(const MeshHandle& meshHandle, const RPI::Cullable::LodConfiguration meshLodConfig); RPI::Cullable::LodConfiguration GetMeshLodConfiguration(const MeshHandle& meshHandle) const; void SetExcludeFromReflectionCubeMaps(const MeshHandle& meshHandle, bool excludeFromReflectionCubeMaps) override; diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessorInterface.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessorInterface.h index 8c7a200ff5..c341cd8854 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessorInterface.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessorInterface.h @@ -95,7 +95,7 @@ namespace AZ //! Gets the sort key for a given mesh handle. virtual RHI::DrawItemSortKey GetSortKey(const MeshHandle& meshHandle) = 0; //! Sets LOD mesh configurations to be used in the Mesh Feature Processor - virtual void SetMeshLodConfiguration(const MeshHandle& meshHandle, RPI::Cullable::LodConfiguration meshLodConfig) = 0; + virtual void SetMeshLodConfiguration(const MeshHandle& meshHandle, const RPI::Cullable::LodConfiguration meshLodConfig) = 0; //! Gets the LOD mesh configurations being used in the Mesh Feature Processor virtual RPI::Cullable::LodConfiguration GetMeshLodConfiguration(const MeshHandle& meshHandle) const = 0; //! Sets the option to exclude this mesh from baked reflection probe cubemaps diff --git a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp index 363723f7da..e07c7a0309 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp @@ -359,7 +359,7 @@ namespace AZ } } - void MeshFeatureProcessor::SetMeshLodConfiguration(const MeshHandle& meshHandle, RPI::Cullable::LodConfiguration meshLodConfig) + void MeshFeatureProcessor::SetMeshLodConfiguration(const MeshHandle& meshHandle, const RPI::Cullable::LodConfiguration meshLodConfig) { if (meshHandle.IsValid()) { diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp index 63b32f6892..8f81bd620d 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp @@ -84,6 +84,7 @@ namespace AZ ->EnumAttribute(RPI::Cullable::LodType::ScreenCoverage, "Screen Coverage") ->EnumAttribute(RPI::Cullable::LodType::SpecificLod, "Specific Lod") ->Attribute(AZ::Edit::Attributes::Visibility, &MeshComponentConfig::IsAssetSet) + ->Attribute(AZ::Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::EntireTree) ->ClassElement(AZ::Edit::ClassElements::Group, "Lod Configuration") ->Attribute(AZ::Edit::Attributes::AutoExpand, false) ->Attribute(AZ::Edit::Attributes::Visibility, &MeshComponentConfig::ShowLodConfig) From 30fee96c435cae1276a6457d287382f610f62f23 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Thu, 12 Aug 2021 22:11:18 -0500 Subject: [PATCH 358/803] Moved material editor document system buses and system components to atom tools framework Renamed document related buses and components to have generic names Added a base document class with default implementation from which other application specific documents can be derived to work with the document system Added document factory function registration to the document system request bus so that each application can specify the type of document it creates Updated all comments and messaging to only refer to documents, not materials or material documents Updated material editor and shader management console to conform to the new buses This will provide a first pass of a common interface for a document management system that can be shared by multiple applications Corrected status bar message copy and paste errors Updated all test scripts to use the new buses Signed-off-by: Guthrie Adams --- .../atom_utils/material_editor_utils.py | 26 +- .../Document/AtomToolsDocument.h | 71 +++ .../AtomToolsDocumentNotificationBus.h} | 8 +- .../Document/AtomToolsDocumentRequestBus.h | 95 ++++ .../AtomToolsDocumentSystemRequestBus.h} | 20 +- .../AtomToolsDocumentSystemSettings.h | 30 + .../Code/Source/AtomToolsFrameworkModule.cpp | 3 + .../Source/Document/AtomToolsDocument.cpp | 154 ++++++ .../AtomToolsDocumentSystemComponent.cpp | 511 ++++++++++++++++++ .../AtomToolsDocumentSystemComponent.h | 92 ++++ .../AtomToolsDocumentSystemSettings.cpp | 47 ++ .../Code/atomtoolsframework_files.cmake | 9 + .../Core/MaterialDocumentFactoryRequestBus.h | 36 -- .../MaterialDocumentNotificationBus.h | 86 --- .../Document/MaterialDocumentRequestBus.h | 76 +-- .../Atom/Document/MaterialDocumentSettings.h | 3 +- .../Code/Source/Document/MaterialDocument.cpp | 62 +-- .../Code/Source/Document/MaterialDocument.h | 34 +- .../Document/MaterialDocumentModule.cpp | 4 +- .../Document/MaterialDocumentSettings.cpp | 5 +- .../MaterialDocumentSystemComponent.cpp | 465 +--------------- .../MaterialDocumentSystemComponent.h | 57 +- .../Code/Source/MaterialEditorApplication.cpp | 4 +- .../Code/Source/MaterialEditorApplication.h | 2 +- .../Viewport/MaterialViewportRenderer.cpp | 4 +- .../Viewport/MaterialViewportRenderer.h | 16 +- .../Viewport/MaterialViewportSettings.cpp | 2 +- .../Source/Window/MaterialBrowserWidget.cpp | 26 +- .../Source/Window/MaterialBrowserWidget.h | 8 +- .../MaterialEditorBrowserInteractions.cpp | 54 +- .../Source/Window/MaterialEditorWindow.cpp | 89 ++- .../Code/Source/Window/MaterialEditorWindow.h | 6 +- .../Window/MaterialEditorWindowSettings.cpp | 2 +- .../MaterialInspector/MaterialInspector.cpp | 46 +- .../MaterialInspector/MaterialInspector.h | 14 +- .../Window/SettingsDialog/SettingsWidget.cpp | 23 +- .../Window/SettingsDialog/SettingsWidget.h | 5 +- .../Code/materialeditordocument_files.cmake | 2 - .../Scripts/GenerateAllMaterialScreenshots.py | 4 +- ...haderManagementConsoleDocumentRequestBus.h | 55 +- ...anagementConsoleDocumentSystemRequestBus.h | 62 --- .../ShaderManagementConsoleDocument.cpp | 165 +----- .../ShaderManagementConsoleDocument.h | 54 +- .../ShaderManagementConsoleDocumentModule.cpp | 4 +- ...nagementConsoleDocumentSystemComponent.cpp | 331 +----------- ...ManagementConsoleDocumentSystemComponent.h | 35 +- .../ShaderManagementConsoleApplication.cpp | 6 +- .../ShaderManagementConsoleApplication.h | 2 +- ...erManagementConsoleBrowserInteractions.cpp | 30 +- .../ShaderManagementConsoleBrowserWidget.cpp | 43 +- .../ShaderManagementConsoleBrowserWidget.h | 7 +- .../Window/ShaderManagementConsoleWindow.cpp | 79 ++- .../Window/ShaderManagementConsoleWindow.h | 6 +- ...ShaderManagementConsoleWindowComponent.cpp | 23 +- .../Code/shadermanagementconsole_files.cmake | 2 - ...hadermanagementconsoledocument_files.cmake | 8 +- .../GenerateShaderVariantListForMaterials.py | 2 +- 57 files changed, 1397 insertions(+), 1718 deletions(-) create mode 100644 Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocument.h rename Gems/Atom/Tools/{ShaderManagementConsole/Code/Include/Atom/Document/ShaderManagementConsoleDocumentNotificationBus.h => AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentNotificationBus.h} (94%) create mode 100644 Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentRequestBus.h rename Gems/Atom/Tools/{MaterialEditor/Code/Include/Atom/Document/MaterialDocumentSystemRequestBus.h => AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h} (80%) create mode 100644 Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentSystemSettings.h create mode 100644 Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocument.cpp create mode 100644 Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.cpp create mode 100644 Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.h create mode 100644 Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemSettings.cpp delete mode 100644 Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Core/MaterialDocumentFactoryRequestBus.h delete mode 100644 Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentNotificationBus.h delete mode 100644 Gems/Atom/Tools/ShaderManagementConsole/Code/Include/Atom/Document/ShaderManagementConsoleDocumentSystemRequestBus.h diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/material_editor_utils.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/material_editor_utils.py index 1d72885504..ef0a592df0 100644 --- a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/material_editor_utils.py +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/material_editor_utils.py @@ -47,28 +47,28 @@ def open_material(file_path): """ :return: uuid of material document opened """ - return materialeditor.MaterialDocumentSystemRequestBus(bus.Broadcast, "OpenDocument", file_path) + return azlmbr.atomtools.AtomToolsDocumentSystemRequestBus(bus.Broadcast, "OpenDocument", file_path) def is_open(document_id): """ :return: bool """ - return materialeditor.MaterialDocumentRequestBus(bus.Event, "IsOpen", document_id) + return azlmbr.atomtools.AtomToolsDocumentRequestBus(bus.Event, "IsOpen", document_id) def save_document(document_id): """ :return: bool success """ - return materialeditor.MaterialDocumentSystemRequestBus(bus.Broadcast, "SaveDocument", document_id) + return azlmbr.atomtools.AtomToolsDocumentSystemRequestBus(bus.Broadcast, "SaveDocument", document_id) def save_document_as_copy(document_id, target_path): """ :return: bool success """ - return materialeditor.MaterialDocumentSystemRequestBus( + return azlmbr.atomtools.AtomToolsDocumentSystemRequestBus( bus.Broadcast, "SaveDocumentAsCopy", document_id, target_path ) @@ -77,7 +77,7 @@ def save_document_as_child(document_id, target_path): """ :return: bool success """ - return materialeditor.MaterialDocumentSystemRequestBus( + return azlmbr.atomtools.AtomToolsDocumentSystemRequestBus( bus.Broadcast, "SaveDocumentAsChild", document_id, target_path ) @@ -86,39 +86,39 @@ def save_all(): """ :return: bool success """ - return materialeditor.MaterialDocumentSystemRequestBus(bus.Broadcast, "SaveAllDocuments") + return azlmbr.atomtools.AtomToolsDocumentSystemRequestBus(bus.Broadcast, "SaveAllDocuments") def close_document(document_id): """ :return: bool success """ - return materialeditor.MaterialDocumentSystemRequestBus(bus.Broadcast, "CloseDocument", document_id) + return azlmbr.atomtools.AtomToolsDocumentSystemRequestBus(bus.Broadcast, "CloseDocument", document_id) def close_all_documents(): """ :return: bool success """ - return materialeditor.MaterialDocumentSystemRequestBus(bus.Broadcast, "CloseAllDocuments") + return azlmbr.atomtools.AtomToolsDocumentSystemRequestBus(bus.Broadcast, "CloseAllDocuments") def close_all_except_selected(document_id): """ :return: bool success """ - return materialeditor.MaterialDocumentSystemRequestBus(bus.Broadcast, "CloseAllDocumentsExcept", document_id) + return azlmbr.atomtools.AtomToolsDocumentSystemRequestBus(bus.Broadcast, "CloseAllDocumentsExcept", document_id) def get_property(document_id, property_name): """ :return: property value or invalid value if the document is not open or the property_name can't be found """ - return materialeditor.MaterialDocumentRequestBus(bus.Event, "GetPropertyValue", document_id, property_name) + return azlmbr.atomtools.AtomToolsDocumentRequestBus(bus.Event, "GetPropertyValue", document_id, property_name) def set_property(document_id, property_name, value): - materialeditor.MaterialDocumentRequestBus(bus.Event, "SetPropertyValue", document_id, property_name, value) + azlmbr.atomtools.AtomToolsDocumentRequestBus(bus.Event, "SetPropertyValue", document_id, property_name, value) def is_pane_visible(pane_name): @@ -175,7 +175,7 @@ def wait_for_condition(function, timeout_in_seconds=1.0): with Timeout(timeout_in_seconds) as t: while True: try: - atomtools.general.idle_wait_frames(1) + azlmbr.atomtools.general.idle_wait_frames(1) except Exception: print("WARNING: Couldn't wait for frame") @@ -269,6 +269,6 @@ class ScreenshotHelper: def capture_screenshot(file_path): - return ScreenshotHelper(atomtools.general.idle_wait_frames).capture_screenshot_blocking( + return ScreenshotHelper(azlmbr.atomtools.general.idle_wait_frames).capture_screenshot_blocking( os.path.join(file_path) ) diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocument.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocument.h new file mode 100644 index 0000000000..390a08e5b1 --- /dev/null +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocument.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ +#pragma once + +#include +#include + +namespace AtomToolsFramework +{ + /** + * AtomToolsDocument provides an API for modifying and saving documents. + */ + class AtomToolsDocument + : public AtomToolsDocumentRequestBus::Handler + { + public: + AZ_RTTI(AtomToolsDocument, "{8992DF74-88EC-438C-B280-6E71D4C0880B}"); + AZ_CLASS_ALLOCATOR(AtomToolsDocument, AZ::SystemAllocator, 0); + AZ_DISABLE_COPY(AtomToolsDocument); + + AtomToolsDocument(); + virtual ~AtomToolsDocument(); + + const AZ::Uuid& GetId() const; + + //////////////////////////////////////////////////////////////////////// + // AtomToolsDocumentRequestBus::Handler implementation + AZStd::string_view GetAbsolutePath() const override; + AZStd::string_view GetRelativePath() const override; + const AZStd::any& GetPropertyValue(const AZ::Name& propertyFullName) const override; + const AtomToolsFramework::DynamicProperty& GetProperty(const AZ::Name& propertyFullName) const override; + bool IsPropertyGroupVisible(const AZ::Name& propertyGroupFullName) const override; + void SetPropertyValue(const AZ::Name& propertyFullName, const AZStd::any& value) override; + bool Open(AZStd::string_view loadPath) override; + bool Rebuild() override; + bool Save() override; + bool SaveAsCopy(AZStd::string_view savePath) override; + bool SaveAsChild(AZStd::string_view savePath) override; + bool Close() override; + bool IsOpen() const override; + bool IsModified() const override; + bool IsSavable() const override; + bool CanUndo() const override; + bool CanRedo() const override; + bool Undo() override; + bool Redo() override; + bool BeginEdit() override; + bool EndEdit() override; + //////////////////////////////////////////////////////////////////////// + + protected: + + // Unique id of this document + AZ::Uuid m_id = AZ::Uuid::CreateRandom(); + + // Relative path to the material source file + AZStd::string m_relativePath; + + // Absolute path to the material source file + AZStd::string m_absolutePath; + + AZStd::any m_invalidValue; + + AtomToolsFramework::DynamicProperty m_invalidProperty; + }; +} // namespace AtomToolsFramework diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Include/Atom/Document/ShaderManagementConsoleDocumentNotificationBus.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentNotificationBus.h similarity index 94% rename from Gems/Atom/Tools/ShaderManagementConsole/Code/Include/Atom/Document/ShaderManagementConsoleDocumentNotificationBus.h rename to Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentNotificationBus.h index 68325beabb..9c3a536333 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Include/Atom/Document/ShaderManagementConsoleDocumentNotificationBus.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentNotificationBus.h @@ -13,9 +13,9 @@ #include #include -namespace ShaderManagementConsole +namespace AtomToolsFramework { - class ShaderManagementConsoleDocumentNotifications + class AtomToolsDocumentNotifications : public AZ::EBusTraits { public: @@ -79,5 +79,5 @@ namespace ShaderManagementConsole virtual void OnDocumentPropertyGroupVisibilityChanged([[maybe_unused]] const AZ::Uuid& documentId, [[maybe_unused]] const AZ::Name& groupId, [[maybe_unused]] bool visible) {} }; - using ShaderManagementConsoleDocumentNotificationBus = AZ::EBus; -} // namespace ShaderManagementConsole + using AtomToolsDocumentNotificationBus = AZ::EBus; +} // namespace AtomToolsFramework diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentRequestBus.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentRequestBus.h new file mode 100644 index 0000000000..42fcab95ae --- /dev/null +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentRequestBus.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ +#pragma once + +#include +#include +#include + +namespace AtomToolsFramework +{ + class AtomToolsDocumentRequests + : public AZ::EBusTraits + { + public: + static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple; + static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById; + typedef AZ::Uuid BusIdType; + + //! Get absolute path of document + virtual AZStd::string_view GetAbsolutePath() const = 0; + + //! Get relative path of document + virtual AZStd::string_view GetRelativePath() const = 0; + + //! Return property value + //! If the document is not open or the id can't be found, an invalid value is returned instead. + virtual const AZStd::any& GetPropertyValue(const AZ::Name& propertyFullName) const = 0; + + //! Returns a property object + //! If the document is not open or the id can't be found, an invalid property is returned. + virtual const AtomToolsFramework::DynamicProperty& GetProperty(const AZ::Name& propertyFullName) const = 0; + + //! Returns whether a property group is visible + //! If the document is not open or the id can't be found, returns false. + virtual bool IsPropertyGroupVisible(const AZ::Name& propertyGroupFullName) const = 0; + + //! Modify document property value + virtual void SetPropertyValue(const AZ::Name& propertyFullName, const AZStd::any& value) = 0; + + //! Load document and related data + //! @param loadPath absolute path of document to load + virtual bool Open(AZStd::string_view loadPath) = 0; + + //! Reload document preserving edits + virtual bool Rebuild() = 0; + + //! Save document to file + virtual bool Save() = 0; + + //! Save document copy + //! @param savePath absolute path where document is saved + virtual bool SaveAsCopy(AZStd::string_view savePath) = 0; + + //! Save document to a new source file derived from of the open document + //! @param savePath absolute path where document is saved + virtual bool SaveAsChild(AZStd::string_view savePath) = 0; + + //! Close document and reset its data + virtual bool Close() = 0; + + //! Document is loaded + virtual bool IsOpen() const = 0; + + //! Document has changes pending + virtual bool IsModified() const = 0; + + //! Can the document be saved + virtual bool IsSavable() const = 0; + + //! Returns true if there are reversible modifications to the document + virtual bool CanUndo() const = 0; + + //! Returns true if there are changes that were reversed and can be re-applied to the document + virtual bool CanRedo() const = 0; + + //! Restores the previous state of the document + virtual bool Undo() = 0; + + //! Restores the next state of the document + virtual bool Redo() = 0; + + //! Signal that editing is about to begin, like beginning to drag a slider control + virtual bool BeginEdit() = 0; + + //! Signal that editing has completed, like after releasing the mouse button after continuously dragging a slider control + virtual bool EndEdit() = 0; + }; + + using AtomToolsDocumentRequestBus = AZ::EBus; +} // namespace AtomToolsFramework diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentSystemRequestBus.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h similarity index 80% rename from Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentSystemRequestBus.h rename to Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h index 47fa5dab85..f751915a9a 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentSystemRequestBus.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h @@ -10,19 +10,21 @@ #include -namespace MaterialEditor +namespace AtomToolsFramework { - static const char* MaterialExtension = "material"; - static const char* MaterialTypeExtension = "materialtype"; + class AtomToolsDocument; - //! MaterialDocumentSystemRequestBus provides high level file requests for menus, scripts, etc. - class MaterialDocumentSystemRequests + //! AtomToolsDocumentSystemRequestBus provides high level requests for menus, scripts, etc. + class AtomToolsDocumentSystemRequests : public AZ::EBusTraits { public: static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single; static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; + //! Register a document factory function used to create specific document types + virtual void RegisterDocumentType(AZStd::function documentCreator) = 0; + //! Create a document object //! @return Uuid of new document, or null Uuid if failed virtual AZ::Uuid CreateDocument() = 0; @@ -37,8 +39,6 @@ namespace MaterialEditor virtual AZ::Uuid OpenDocument(AZStd::string_view sourcePath) = 0; //! Create a new document by specifying a source and prompting the user for destination path. - //! If the source file is a material type then this results in creating a new material based on that type. - //! If the source file is a material this results in creating a child material with the source file as its parent. //! @param sourcePath document to open. //! @param targetPath location where document is saved. //! @return unique id of new document if successful, otherwise null Uuid @@ -64,7 +64,7 @@ namespace MaterialEditor //! @param targetPath location where document is saved. virtual bool SaveDocumentAsCopy(const AZ::Uuid& documentId, AZStd::string_view targetPath) = 0; - //! Save the specified document to a different file, referencing the original material as its parent + //! Save the specified document to a different file, referencing the original document as its parent //! @param documentId unique id of document to save //! @param targetPath location where document is saved. virtual bool SaveDocumentAsChild(const AZ::Uuid& documentId, AZStd::string_view targetPath) = 0; @@ -73,6 +73,6 @@ namespace MaterialEditor virtual bool SaveAllDocuments() = 0; }; - using MaterialDocumentSystemRequestBus = AZ::EBus; + using AtomToolsDocumentSystemRequestBus = AZ::EBus; -} // namespace MaterialEditor +} // namespace AtomToolsFramework diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentSystemSettings.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentSystemSettings.h new file mode 100644 index 0000000000..9b4c1d77fe --- /dev/null +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentSystemSettings.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#pragma once + +#if !defined(Q_MOC_RUN) +#include +#include +#include +#include +#endif + +namespace AtomToolsFramework +{ + struct AtomToolsDocumentSystemSettings + : public AZ::UserSettings + { + AZ_RTTI(AtomToolsDocumentSystemSettings, "{9E576D4F-A74A-4326-9135-C07284D0A3B9}", AZ::UserSettings); + AZ_CLASS_ALLOCATOR(AtomToolsDocumentSystemSettings, AZ::SystemAllocator, 0); + + static void Reflect(AZ::ReflectContext* context); + + bool m_showReloadDocumentPrompt = true; + }; +} // namespace AtomToolsFramework diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/AtomToolsFrameworkModule.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/AtomToolsFrameworkModule.cpp index b601596032..21a185b290 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/AtomToolsFrameworkModule.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/AtomToolsFrameworkModule.cpp @@ -8,6 +8,7 @@ #include #include +#include #include namespace AtomToolsFramework @@ -16,6 +17,7 @@ namespace AtomToolsFramework { m_descriptors.insert(m_descriptors.end(), { AtomToolsFrameworkSystemComponent::CreateDescriptor(), + AtomToolsDocumentSystemComponent::CreateDescriptor(), AtomToolsMainWindowSystemComponent::CreateDescriptor(), }); } @@ -24,6 +26,7 @@ namespace AtomToolsFramework { return AZ::ComponentTypeList{ azrtti_typeid(), + azrtti_typeid(), azrtti_typeid(), }; } diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocument.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocument.cpp new file mode 100644 index 0000000000..c3216c6d9d --- /dev/null +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocument.cpp @@ -0,0 +1,154 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include + +namespace AtomToolsFramework +{ + AtomToolsDocument::AtomToolsDocument() + { + AtomToolsDocumentRequestBus::Handler::BusConnect(m_id); + AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsDocumentNotificationBus::Events::OnDocumentCreated, m_id); + } + + AtomToolsDocument::~AtomToolsDocument() + { + AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsDocumentNotificationBus::Events::OnDocumentDestroyed, m_id); + AtomToolsDocumentRequestBus::Handler::BusDisconnect(); + } + + const AZ::Uuid& AtomToolsDocument::GetId() const + { + return m_id; + } + + AZStd::string_view AtomToolsDocument::GetAbsolutePath() const + { + return m_absolutePath; + } + + AZStd::string_view AtomToolsDocument::GetRelativePath() const + { + return m_relativePath; + } + + const AZStd::any& AtomToolsDocument::GetPropertyValue(const AZ::Name& propertyFullName) const + { + AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); + return m_invalidValue; + } + + const AtomToolsFramework::DynamicProperty& AtomToolsDocument::GetProperty(const AZ::Name& propertyFullName) const + { + AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); + return m_invalidProperty; + } + + bool AtomToolsDocument::IsPropertyGroupVisible(const AZ::Name& propertyGroupFullName) const + { + AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); + return false; + } + + void AtomToolsDocument::SetPropertyValue(const AZ::Name& propertyFullName, const AZStd::any& value) + { + AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); + } + + bool AtomToolsDocument::Open(AZStd::string_view loadPath) + { + AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); + return false; + } + + bool AtomToolsDocument::Rebuild() + { + AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); + return false; + } + + bool AtomToolsDocument::Save() + { + AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); + return false; + } + + bool AtomToolsDocument::SaveAsCopy(AZStd::string_view savePath) + { + AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); + return false; + } + + + bool AtomToolsDocument::SaveAsChild(AZStd::string_view savePath) + { + AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); + return false; + } + + bool AtomToolsDocument::Close() + { + AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); + return false; + } + + bool AtomToolsDocument::IsOpen() const + { + AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); + return false; + } + + bool AtomToolsDocument::IsModified() const + { + AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); + return false; + } + + bool AtomToolsDocument::IsSavable() const + { + AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); + return false; + } + + bool AtomToolsDocument::CanUndo() const + { + AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); + return false; + } + + bool AtomToolsDocument::CanRedo() const + { + AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); + return false; + } + + bool AtomToolsDocument::Undo() + { + AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); + return false; + } + + bool AtomToolsDocument::Redo() + { + AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); + return false; + } + + bool AtomToolsDocument::BeginEdit() + { + AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); + return false; + } + + bool AtomToolsDocument::EndEdit() + { + AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); + return false; + } +} // namespace AtomToolsFramework diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.cpp new file mode 100644 index 0000000000..fa7280068e --- /dev/null +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.cpp @@ -0,0 +1,511 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT +#include +#include +#include +AZ_POP_DISABLE_WARNING + +namespace AtomToolsFramework +{ + AtomToolsDocumentSystemComponent::AtomToolsDocumentSystemComponent() + { + } + + void AtomToolsDocumentSystemComponent::Reflect(AZ::ReflectContext* context) + { + AtomToolsDocumentSystemSettings::Reflect(context); + + if (AZ::SerializeContext* serialize = azrtti_cast(context)) + { + serialize->Class() + ->Version(0); + + if (AZ::EditContext* ec = serialize->GetEditContext()) + { + ec->Class("AtomToolsDocumentSystemComponent", "") + ->ClassElement(AZ::Edit::ClassElements::EditorData, "") + ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC_CE("System")) + ->Attribute(AZ::Edit::Attributes::AutoExpand, true) + ; + } + } + + if (AZ::BehaviorContext* behaviorContext = azrtti_cast(context)) + { + behaviorContext->EBus("AtomToolsDocumentSystemRequestBus") + ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) + ->Attribute(AZ::Script::Attributes::Category, "Editor") + ->Attribute(AZ::Script::Attributes::Module, "atomtools") + ->Event("CreateDocument", &AtomToolsDocumentSystemRequestBus::Events::CreateDocument) + ->Event("DestroyDocument", &AtomToolsDocumentSystemRequestBus::Events::DestroyDocument) + ->Event("OpenDocument", &AtomToolsDocumentSystemRequestBus::Events::OpenDocument) + ->Event("CreateDocumentFromFile", &AtomToolsDocumentSystemRequestBus::Events::CreateDocumentFromFile) + ->Event("CloseDocument", &AtomToolsDocumentSystemRequestBus::Events::CloseDocument) + ->Event("CloseAllDocuments", &AtomToolsDocumentSystemRequestBus::Events::CloseAllDocuments) + ->Event("CloseAllDocumentsExcept", &AtomToolsDocumentSystemRequestBus::Events::CloseAllDocumentsExcept) + ->Event("SaveDocument", &AtomToolsDocumentSystemRequestBus::Events::SaveDocument) + ->Event("SaveDocumentAsCopy", &AtomToolsDocumentSystemRequestBus::Events::SaveDocumentAsCopy) + ->Event("SaveDocumentAsChild", &AtomToolsDocumentSystemRequestBus::Events::SaveDocumentAsChild) + ->Event("SaveAllDocuments", &AtomToolsDocumentSystemRequestBus::Events::SaveAllDocuments) + ; + + behaviorContext->EBus("AtomToolsDocumentRequestBus") + ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) + ->Attribute(AZ::Script::Attributes::Category, "Editor") + ->Attribute(AZ::Script::Attributes::Module, "atomtools") + ->Event("GetAbsolutePath", &AtomToolsDocumentRequestBus::Events::GetAbsolutePath) + ->Event("GetRelativePath", &AtomToolsDocumentRequestBus::Events::GetRelativePath) + ->Event("GetPropertyValue", &AtomToolsDocumentRequestBus::Events::GetPropertyValue) + ->Event("SetPropertyValue", &AtomToolsDocumentRequestBus::Events::SetPropertyValue) + ->Event("Open", &AtomToolsDocumentRequestBus::Events::Open) + ->Event("Rebuild", &AtomToolsDocumentRequestBus::Events::Rebuild) + ->Event("Close", &AtomToolsDocumentRequestBus::Events::Close) + ->Event("Save", &AtomToolsDocumentRequestBus::Events::Save) + ->Event("SaveAsChild", &AtomToolsDocumentRequestBus::Events::SaveAsChild) + ->Event("SaveAsCopy", &AtomToolsDocumentRequestBus::Events::SaveAsCopy) + ->Event("IsOpen", &AtomToolsDocumentRequestBus::Events::IsOpen) + ->Event("IsModified", &AtomToolsDocumentRequestBus::Events::IsModified) + ->Event("IsSavable", &AtomToolsDocumentRequestBus::Events::IsSavable) + ->Event("CanUndo", &AtomToolsDocumentRequestBus::Events::CanUndo) + ->Event("CanRedo", &AtomToolsDocumentRequestBus::Events::CanRedo) + ->Event("Undo", &AtomToolsDocumentRequestBus::Events::Undo) + ->Event("Redo", &AtomToolsDocumentRequestBus::Events::Redo) + ->Event("BeginEdit", &AtomToolsDocumentRequestBus::Events::BeginEdit) + ->Event("EndEdit", &AtomToolsDocumentRequestBus::Events::EndEdit) + ; + } + } + + void AtomToolsDocumentSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) + { + provided.push_back(AZ_CRC_CE("AtomToolsDocumentSystemService")); + } + + void AtomToolsDocumentSystemComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) + { + incompatible.push_back(AZ_CRC_CE("AtomToolsDocumentSystemService")); + } + + void AtomToolsDocumentSystemComponent::Init() + { + } + + void AtomToolsDocumentSystemComponent::Activate() + { + m_documentMap.clear(); + m_settings = AZ::UserSettings::CreateFind(AZ_CRC_CE("AtomToolsDocumentSystemSettings"), AZ::UserSettings::CT_GLOBAL); + AtomToolsDocumentSystemRequestBus::Handler::BusConnect(); + AtomToolsDocumentNotificationBus::Handler::BusConnect(); + } + + void AtomToolsDocumentSystemComponent::Deactivate() + { + AZ::TickBus::Handler::BusDisconnect(); + AtomToolsDocumentNotificationBus::Handler::BusDisconnect(); + AtomToolsDocumentSystemRequestBus::Handler::BusDisconnect(); + m_documentMap.clear(); + } + + void AtomToolsDocumentSystemComponent::RegisterDocumentType(AZStd::function documentCreator) + { + m_documentCreator = documentCreator; + } + + AZ::Uuid AtomToolsDocumentSystemComponent::CreateDocument() + { + if (!m_documentCreator) + { + AZ_Error("AtomToolsDocument", false, "Failed to create new document"); + return AZ::Uuid::CreateNull(); + } + + AZStd::unique_ptr document(m_documentCreator()); + if (!document) + { + AZ_Error("AtomToolsDocument", false, "Failed to create new document"); + return AZ::Uuid::CreateNull(); + } + + AZ::Uuid documentId = document->GetId(); + m_documentMap.emplace(documentId, document.release()); + return documentId; + } + + bool AtomToolsDocumentSystemComponent::DestroyDocument(const AZ::Uuid& documentId) + { + return m_documentMap.erase(documentId) != 0; + } + + void AtomToolsDocumentSystemComponent::OnDocumentExternallyModified(const AZ::Uuid& documentId) + { + m_documentIdsToReopen.insert(documentId); + if (!AZ::TickBus::Handler::BusIsConnected()) + { + AZ::TickBus::Handler::BusConnect(); + } + } + + void AtomToolsDocumentSystemComponent::OnDocumentDependencyModified(const AZ::Uuid& documentId) + { + m_documentIdsToRebuild.insert(documentId); + if (!AZ::TickBus::Handler::BusIsConnected()) + { + AZ::TickBus::Handler::BusConnect(); + } + } + + void AtomToolsDocumentSystemComponent::OnTick([[maybe_unused]] float deltaTime, [[maybe_unused]] AZ::ScriptTimePoint time) + { + for (const AZ::Uuid& documentId : m_documentIdsToReopen) + { + AZStd::string documentPath; + AtomToolsDocumentRequestBus::EventResult(documentPath, documentId, &AtomToolsDocumentRequestBus::Events::GetAbsolutePath); + + if (m_settings->m_showReloadDocumentPrompt && + (QMessageBox::question(QApplication::activeWindow(), + QString("Document was externally modified"), + QString("Would you like to reopen the document:\n%1?").arg(documentPath.c_str()), + QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes)) + { + continue; + } + + AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); + + bool openResult = false; + AtomToolsDocumentRequestBus::EventResult(openResult, documentId, &AtomToolsDocumentRequestBus::Events::Open, documentPath); + if (!openResult) + { + QMessageBox::critical( + QApplication::activeWindow(), QString("Document could not be opened"), + QString("Failed to open: \n%1\n\n%2").arg(documentPath.c_str()).arg(traceRecorder.GetDump().c_str())); + AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsDocumentSystemRequestBus::Events::CloseDocument, documentId); + } + } + + for (const AZ::Uuid& documentId : m_documentIdsToRebuild) + { + AZStd::string documentPath; + AtomToolsDocumentRequestBus::EventResult(documentPath, documentId, &AtomToolsDocumentRequestBus::Events::GetAbsolutePath); + + if (m_settings->m_showReloadDocumentPrompt && + (QMessageBox::question(QApplication::activeWindow(), + QString("Document dependencies have changed"), + QString("Would you like to update the document with these changes:\n%1?").arg(documentPath.c_str()), + QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes)) + { + continue; + } + + AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); + + bool openResult = false; + AtomToolsDocumentRequestBus::EventResult(openResult, documentId, &AtomToolsDocumentRequestBus::Events::Rebuild); + if (!openResult) + { + QMessageBox::critical( + QApplication::activeWindow(), QString("Document could not be opened"), + QString("Failed to open: \n%1\n\n%2").arg(documentPath.c_str()).arg(traceRecorder.GetDump().c_str())); + AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsDocumentSystemRequestBus::Events::CloseDocument, documentId); + } + } + + m_documentIdsToRebuild.clear(); + m_documentIdsToReopen.clear(); + AZ::TickBus::Handler::BusDisconnect(); + } + + AZ::Uuid AtomToolsDocumentSystemComponent::OpenDocument(AZStd::string_view sourcePath) + { + return OpenDocumentImpl(sourcePath, true); + } + + AZ::Uuid AtomToolsDocumentSystemComponent::CreateDocumentFromFile(AZStd::string_view sourcePath, AZStd::string_view targetPath) + { + const AZ::Uuid documentId = OpenDocumentImpl(sourcePath, false); + if (documentId.IsNull()) + { + return AZ::Uuid::CreateNull(); + } + + if (!SaveDocumentAsChild(documentId, targetPath)) + { + CloseDocument(documentId); + return AZ::Uuid::CreateNull(); + } + + // Send document open notification after creating new one + AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsDocumentNotificationBus::Events::OnDocumentOpened, documentId); + return documentId; + } + + bool AtomToolsDocumentSystemComponent::CloseDocument(const AZ::Uuid& documentId) + { + bool isOpen = false; + AtomToolsDocumentRequestBus::EventResult(isOpen, documentId, &AtomToolsDocumentRequestBus::Events::IsOpen); + if (!isOpen) + { + // immediately destroy unopened documents + AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsDocumentSystemRequestBus::Events::DestroyDocument, documentId); + return true; + } + + AZStd::string documentPath; + AtomToolsDocumentRequestBus::EventResult(documentPath, documentId, &AtomToolsDocumentRequestBus::Events::GetAbsolutePath); + + bool isModified = false; + AtomToolsDocumentRequestBus::EventResult(isModified, documentId, &AtomToolsDocumentRequestBus::Events::IsModified); + if (isModified) + { + auto selection = QMessageBox::question(QApplication::activeWindow(), + QString("Document has unsaved changes"), + QString("Do you want to save changes to\n%1?").arg(documentPath.c_str()), + QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); + if (selection == QMessageBox::Cancel) + { + AZ_TracePrintf("AtomToolsDocument", "Close document canceled: %s", documentPath.c_str()); + return false; + } + if (selection == QMessageBox::Yes) + { + if (!SaveDocument(documentId)) + { + AZ_Error("AtomToolsDocument", false, "Close document failed because document was not saved: %s", documentPath.c_str()); + return false; + } + } + } + + AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); + + bool closeResult = true; + AtomToolsDocumentRequestBus::EventResult(closeResult, documentId, &AtomToolsDocumentRequestBus::Events::Close); + if (!closeResult) + { + QMessageBox::critical( + QApplication::activeWindow(), QString("Document could not be closed"), + QString("Failed to close: \n%1\n\n%2").arg(documentPath.c_str()).arg(traceRecorder.GetDump().c_str())); + return false; + } + + AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsDocumentSystemRequestBus::Events::DestroyDocument, documentId); + return true; + } + + bool AtomToolsDocumentSystemComponent::CloseAllDocuments() + { + bool result = true; + auto documentMap = m_documentMap; + for (const auto& documentPair : documentMap) + { + if (!CloseDocument(documentPair.first)) + { + result = false; + } + } + + return result; + } + + bool AtomToolsDocumentSystemComponent::CloseAllDocumentsExcept(const AZ::Uuid& documentId) + { + bool result = true; + auto documentMap = m_documentMap; + for (const auto& documentPair : documentMap) + { + if (documentPair.first != documentId) + { + if (!CloseDocument(documentPair.first)) + { + result = false; + } + } + } + + return result; + } + + bool AtomToolsDocumentSystemComponent::SaveDocument(const AZ::Uuid& documentId) + { + AZStd::string saveDocumentPath; + AtomToolsDocumentRequestBus::EventResult(saveDocumentPath, documentId, &AtomToolsDocumentRequestBus::Events::GetAbsolutePath); + + if (saveDocumentPath.empty() || !AzFramework::StringFunc::Path::Normalize(saveDocumentPath)) + { + return false; + } + + const QFileInfo saveInfo(saveDocumentPath.c_str()); + if (saveInfo.exists() && !saveInfo.isWritable()) + { + QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Document could not be overwritten:\n%1").arg(saveDocumentPath.c_str())); + return false; + } + + AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); + + bool result = false; + AtomToolsDocumentRequestBus::EventResult(result, documentId, &AtomToolsDocumentRequestBus::Events::Save); + if (!result) + { + QMessageBox::critical( + QApplication::activeWindow(), QString("Document could not be saved"), + QString("Failed to save: \n%1\n\n%2").arg(saveDocumentPath.c_str()).arg(traceRecorder.GetDump().c_str())); + return false; + } + + return true; + } + + bool AtomToolsDocumentSystemComponent::SaveDocumentAsCopy(const AZ::Uuid& documentId, AZStd::string_view targetPath) + { + AZStd::string saveDocumentPath = targetPath; + if (saveDocumentPath.empty() || !AzFramework::StringFunc::Path::Normalize(saveDocumentPath)) + { + return false; + } + + const QFileInfo saveInfo(saveDocumentPath.c_str()); + if (saveInfo.exists() && !saveInfo.isWritable()) + { + QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Document could not be overwritten:\n%1").arg(saveDocumentPath.c_str())); + return false; + } + + AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); + + bool result = false; + AtomToolsDocumentRequestBus::EventResult(result, documentId, &AtomToolsDocumentRequestBus::Events::SaveAsCopy, saveDocumentPath); + if (!result) + { + QMessageBox::critical( + QApplication::activeWindow(), QString("Document could not be saved"), + QString("Failed to save: \n%1\n\n%2").arg(saveDocumentPath.c_str()).arg(traceRecorder.GetDump().c_str())); + return false; + } + + return true; + } + + bool AtomToolsDocumentSystemComponent::SaveDocumentAsChild(const AZ::Uuid& documentId, AZStd::string_view targetPath) + { + AZStd::string saveDocumentPath = targetPath; + if (saveDocumentPath.empty() || !AzFramework::StringFunc::Path::Normalize(saveDocumentPath)) + { + return false; + } + + const QFileInfo saveInfo(saveDocumentPath.c_str()); + if (saveInfo.exists() && !saveInfo.isWritable()) + { + QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Document could not be overwritten:\n%1").arg(saveDocumentPath.c_str())); + return false; + } + + AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); + + bool result = false; + AtomToolsDocumentRequestBus::EventResult(result, documentId, &AtomToolsDocumentRequestBus::Events::SaveAsChild, saveDocumentPath); + if (!result) + { + QMessageBox::critical( + QApplication::activeWindow(), QString("Document could not be saved"), + QString("Failed to save: \n%1\n\n%2").arg(saveDocumentPath.c_str()).arg(traceRecorder.GetDump().c_str())); + return false; + } + + return true; + } + + bool AtomToolsDocumentSystemComponent::SaveAllDocuments() + { + bool result = true; + for (const auto& documentPair : m_documentMap) + { + if (!SaveDocument(documentPair.first)) + { + result = false; + } + } + + return result; + } + + AZ::Uuid AtomToolsDocumentSystemComponent::OpenDocumentImpl(AZStd::string_view sourcePath, bool checkIfAlreadyOpen) + { + AZStd::string requestedPath = sourcePath; + if (requestedPath.empty()) + { + return AZ::Uuid::CreateNull(); + } + + if (!AzFramework::StringFunc::Path::Normalize(requestedPath)) + { + QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Document path is invalid:\n%1").arg(requestedPath.c_str())); + return AZ::Uuid::CreateNull(); + } + + // Determine if the file is already open and select it + if (checkIfAlreadyOpen) + { + for (const auto& documentPair : m_documentMap) + { + AZStd::string openDocumentPath; + AtomToolsDocumentRequestBus::EventResult(openDocumentPath, documentPair.first, &AtomToolsDocumentRequestBus::Events::GetAbsolutePath); + if (openDocumentPath == requestedPath) + { + AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsDocumentNotificationBus::Events::OnDocumentOpened, documentPair.first); + return documentPair.first; + } + } + } + + AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); + + AZ::Uuid documentId = AZ::Uuid::CreateNull(); + AtomToolsDocumentSystemRequestBus::BroadcastResult(documentId, &AtomToolsDocumentSystemRequestBus::Events::CreateDocument); + if (documentId.IsNull()) + { + QMessageBox::critical( + QApplication::activeWindow(), QString("Document could not be created"), + QString("Failed to create: \n%1\n\n%2").arg(requestedPath.c_str()).arg(traceRecorder.GetDump().c_str())); + return AZ::Uuid::CreateNull(); + } + + traceRecorder.GetDump().clear(); + + bool openResult = false; + AtomToolsDocumentRequestBus::EventResult(openResult, documentId, &AtomToolsDocumentRequestBus::Events::Open, requestedPath); + if (!openResult) + { + QMessageBox::critical( + QApplication::activeWindow(), QString("Document could not be opened"), + QString("Failed to open: \n%1\n\n%2").arg(requestedPath.c_str()).arg(traceRecorder.GetDump().c_str())); + AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsDocumentSystemRequestBus::Events::DestroyDocument, documentId); + return AZ::Uuid::CreateNull(); + } + + return documentId; + } +} diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.h new file mode 100644 index 0000000000..9c556a07e7 --- /dev/null +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#pragma once + +#include +#include +#include +#include + +#include +#include +#include +#include + +AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT +#include +#include +AZ_POP_DISABLE_WARNING + +namespace AtomToolsFramework +{ + //! AtomToolsDocumentSystemComponent is the central component of the Material Editor Core gem + class AtomToolsDocumentSystemComponent + : public AZ::Component + , private AZ::TickBus::Handler + , private AtomToolsDocumentNotificationBus::Handler + , private AtomToolsDocumentSystemRequestBus::Handler + { + public: + AZ_COMPONENT(AtomToolsDocumentSystemComponent, "{343A3383-6A59-4343-851B-BF84FC6CB18E}"); + + AtomToolsDocumentSystemComponent(); + ~AtomToolsDocumentSystemComponent() = default; + AtomToolsDocumentSystemComponent(const AtomToolsDocumentSystemComponent&) = delete; + AtomToolsDocumentSystemComponent& operator=(const AtomToolsDocumentSystemComponent&) = delete; + + static void Reflect(AZ::ReflectContext* context); + + static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided); + static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible); + + private: + //////////////////////////////////////////////////////////////////////// + // AZ::Component interface implementation + void Init() override; + void Activate() override; + void Deactivate() override; + //////////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////////////////// + // AtomToolsDocumentNotificationBus::Handler overrides... + void OnDocumentDependencyModified(const AZ::Uuid& documentId) override; + void OnDocumentExternallyModified(const AZ::Uuid& documentId) override; + ////////////////////////////////////////////////////////////////////////// + + //////////////////////////////////////////////////////////////////////// + // AZ::TickBus::Handler overrides... + void OnTick(float deltaTime, AZ::ScriptTimePoint time) override; + //////////////////////////////////////////////////////////////////////// + + //////////////////////////////////////////////////////////////////////// + // AtomToolsDocumentSystemRequestBus::Handler overrides... + void RegisterDocumentType(AZStd::function documentCreator) override; + AZ::Uuid CreateDocument() override; + bool DestroyDocument(const AZ::Uuid& documentId) override; + AZ::Uuid OpenDocument(AZStd::string_view sourcePath) override; + AZ::Uuid CreateDocumentFromFile(AZStd::string_view sourcePath, AZStd::string_view targetPath) override; + bool CloseDocument(const AZ::Uuid& documentId) override; + bool CloseAllDocuments() override; + bool CloseAllDocumentsExcept(const AZ::Uuid& documentId) override; + bool SaveDocument(const AZ::Uuid& documentId) override; + bool SaveDocumentAsCopy(const AZ::Uuid& documentId, AZStd::string_view targetPath) override; + bool SaveDocumentAsChild(const AZ::Uuid& documentId, AZStd::string_view targetPath) override; + bool SaveAllDocuments() override; + //////////////////////////////////////////////////////////////////////// + + AZ::Uuid OpenDocumentImpl(AZStd::string_view sourcePath, bool checkIfAlreadyOpen); + + AZStd::intrusive_ptr m_settings; + AZStd::function m_documentCreator; + AZStd::unordered_map> m_documentMap; + AZStd::unordered_set m_documentIdsToRebuild; + AZStd::unordered_set m_documentIdsToReopen; + const size_t m_maxMessageBoxLineCount = 15; + }; +} // namespace AtomToolsFramework diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemSettings.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemSettings.cpp new file mode 100644 index 0000000000..94af43e524 --- /dev/null +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemSettings.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include +#include + +namespace AtomToolsFramework +{ + void AtomToolsDocumentSystemSettings::Reflect(AZ::ReflectContext* context) + { + if (auto serializeContext = azrtti_cast(context)) + { + serializeContext->Class() + ->Version(1) + ->Field("showReloadDocumentPrompt", &AtomToolsDocumentSystemSettings::m_showReloadDocumentPrompt) + ; + + if (auto editContext = serializeContext->GetEditContext()) + { + editContext->Class( + "AtomToolsDocumentSystemSettings", "") + ->ClassElement(AZ::Edit::ClassElements::EditorData, "") + ->Attribute(AZ::Edit::Attributes::AutoExpand, true) + ->DataElement(AZ::Edit::UIHandlers::Default, &AtomToolsDocumentSystemSettings::m_showReloadDocumentPrompt, "Show Reload Document Prompt", "") + ; + } + } + + if (auto behaviorContext = azrtti_cast(context)) + { + behaviorContext->Class("AtomToolsDocumentSystemSettings") + ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) + ->Attribute(AZ::Script::Attributes::Category, "Editor") + ->Attribute(AZ::Script::Attributes::Module, "atomtools") + ->Constructor() + ->Constructor() + ->Property("showReloadDocumentPrompt", BehaviorValueProperty(&AtomToolsDocumentSystemSettings::m_showReloadDocumentPrompt)) + ; + } + } +} // namespace AtomToolsFramework diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake b/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake index 8eb82778e3..cd056f5fcf 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake @@ -11,6 +11,11 @@ set(FILES Include/AtomToolsFramework/Communication/LocalServer.h Include/AtomToolsFramework/Communication/LocalSocket.h Include/AtomToolsFramework/Debug/TraceRecorder.h + Include/AtomToolsFramework/Document/AtomToolsDocument.h + Include/AtomToolsFramework/Document/AtomToolsDocumentSystemSettings.h + Include/AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h + Include/AtomToolsFramework/Document/AtomToolsDocumentNotificationBus.h + Include/AtomToolsFramework/Document/AtomToolsDocumentRequestBus.h Include/AtomToolsFramework/DynamicProperty/DynamicProperty.h Include/AtomToolsFramework/DynamicProperty/DynamicPropertyGroup.h Include/AtomToolsFramework/Inspector/InspectorWidget.h @@ -32,6 +37,10 @@ set(FILES Source/Communication/LocalServer.cpp Source/Communication/LocalSocket.cpp Source/Debug/TraceRecorder.cpp + Source/Document/AtomToolsDocument.cpp + Source/Document/AtomToolsDocumentSystemSettings.cpp + Source/Document/AtomToolsDocumentSystemComponent.cpp + Source/Document/AtomToolsDocumentSystemComponent.h Source/DynamicProperty/DynamicProperty.cpp Source/DynamicProperty/DynamicPropertyGroup.cpp Source/Inspector/InspectorWidget.cpp diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Core/MaterialDocumentFactoryRequestBus.h b/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Core/MaterialDocumentFactoryRequestBus.h deleted file mode 100644 index e936d5159b..0000000000 --- a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Core/MaterialDocumentFactoryRequestBus.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ -#pragma once - -#include -#include -#include - -namespace MaterialEditor -{ - //! MaterialDocumentFactoryRequestBus provides a factory interface for creating and destroying material documents (in memory) - class MaterialDocumentFactoryRequests - : public AZ::EBusTraits - { - public: - // Only a single handler is allowed - static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; - static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single; - - //! Create a material document object - //! @return Uuid of new material document, or null Uuid if failed - virtual AZ::Uuid CreateDocument() = 0; - - //! Destroy a material document object with the specified id - //! @return true if Uuid was found and removed, otherwise false - virtual bool DestroyDocument(const AZ::Uuid& documentId) = 0; - }; - - using MaterialDocumentFactoryRequestBus = AZ::EBus; - -} // namespace MaterialEditor diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentNotificationBus.h b/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentNotificationBus.h deleted file mode 100644 index 963a348697..0000000000 --- a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentNotificationBus.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ -#pragma once - -#include -#include - -#include -#include - -#include -#include - -namespace MaterialEditor -{ - class MaterialDocumentNotifications - : public AZ::EBusTraits - { - public: - static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; - static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple; - - //! Signal that a document was created - //! @param documentId unique id of document for which the notification is sent - virtual void OnDocumentCreated([[maybe_unused]] const AZ::Uuid& documentId) {} - - //! Signal that a document was destroyed - //! @param documentId unique id of document for which the notification is sent - virtual void OnDocumentDestroyed([[maybe_unused]] const AZ::Uuid& documentId) {} - - //! Signal that a document was opened - //! @param documentId unique id of document for which the notification is sent - virtual void OnDocumentOpened([[maybe_unused]] const AZ::Uuid& documentId) {} - - //! Signal that a document was closed - //! @param documentId unique id of document for which the notification is sent - virtual void OnDocumentClosed([[maybe_unused]] const AZ::Uuid& documentId) {} - - //! Signal that a document was saved - //! @param documentId unique id of document for which the notification is sent - virtual void OnDocumentSaved([[maybe_unused]] const AZ::Uuid& documentId) {} - - //! Signal that a document was selected - //! @param documentId unique id of document for which the notification is sent - virtual void OnDocumentSelected([[maybe_unused]] const AZ::Uuid& documentId) {} - - //! Signal that a document was modified - //! @param documentId unique id of document for which the notification is sent - virtual void OnDocumentModified([[maybe_unused]] const AZ::Uuid& documentId) {} - - //! Signal that a document dependency was modified - //! @param documentId unique id of document for which the notification is sent - virtual void OnDocumentDependencyModified([[maybe_unused]] const AZ::Uuid& documentId) {} - - //! Signal that a document was modified externally - //! @param documentId unique id of document for which the notification is sent - virtual void OnDocumentExternallyModified([[maybe_unused]] const AZ::Uuid& documentId) {} - - //! Signal that a document undo state was updated - //! @param documentId unique id of document for which the notification is sent - virtual void OnDocumentUndoStateChanged([[maybe_unused]] const AZ::Uuid& documentId) {} - - //! Signal that a property changed - //! @param documentId unique id of document for which the notification is sent - //! @param property object containing the property value and configuration that was modified - virtual void OnDocumentPropertyValueModified([[maybe_unused]] const AZ::Uuid& documentId, [[maybe_unused]] const AtomToolsFramework::DynamicProperty& property) {} - - //! Signal that the property configuration has been changed. - //! @param documentId unique id of document for which the notification is sent - //! @param property object containing the property value and configuration that was modified - virtual void OnDocumentPropertyConfigModified([[maybe_unused]] const AZ::Uuid& documentId, [[maybe_unused]] const AtomToolsFramework::DynamicProperty& property) {} - - //! Signal that the property group visibility has been changed. - //! @param documentId unique id of document for which the notification is sent - //! @param groupId id of the group that changed - //! @param visible whether the property group is visible - virtual void OnDocumentPropertyGroupVisibilityChanged([[maybe_unused]] const AZ::Uuid& documentId, [[maybe_unused]] const AZ::Name& groupId, [[maybe_unused]] bool visible) {} - }; - - using MaterialDocumentNotificationBus = AZ::EBus; -} // namespace MaterialEditor diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentRequestBus.h b/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentRequestBus.h index 515cc44edc..c95aa4f215 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentRequestBus.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentRequestBus.h @@ -7,15 +7,10 @@ */ #pragma once +#include #include #include -#include - #include -#include - -#include -#include namespace AZ { @@ -39,12 +34,6 @@ namespace MaterialEditor static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById; typedef AZ::Uuid BusIdType; - //! Get absolute path of document - virtual AZStd::string_view GetAbsolutePath() const = 0; - - //! Get relative path of document - virtual AZStd::string_view GetRelativePath() const = 0; - //! Get material asset created by MaterialDocument virtual AZ::Data::Asset GetAsset() const = 0; @@ -56,69 +45,6 @@ namespace MaterialEditor //! Get the internal material type source data virtual const AZ::RPI::MaterialTypeSourceData* GetMaterialTypeSourceData() const = 0; - - //! Return property value - //! If the document is not open or the id can't be found, an invalid value is returned instead. - virtual const AZStd::any& GetPropertyValue(const AZ::Name& propertyFullName) const = 0; - - //! Returns a property object - //! If the document is not open or the id can't be found, an invalid property is returned. - virtual const AtomToolsFramework::DynamicProperty& GetProperty(const AZ::Name& propertyFullName) const = 0; - - //! Returns whether a property group is visible - //! If the document is not open or the id can't be found, returns false. - virtual bool IsPropertyGroupVisible(const AZ::Name& propertyGroupFullName) const = 0; - - //! Modify material property value - virtual void SetPropertyValue(const AZ::Name& propertyFullName, const AZStd::any& value) = 0; - - //! Load document and related data - //! @param loadPath Absolute path of document to load - virtual bool Open(AZStd::string_view loadPath) = 0; - - //! Reload document preserving edits - virtual bool Rebuild() = 0; - - //! Save document to file - virtual bool Save() = 0; - - //! Save document copy - //! @param savePath Absolute path where document is saved - virtual bool SaveAsCopy(AZStd::string_view savePath) = 0; - - //! Save material to a new source file as a child of the open material - //! @param savePath Absolute path where material is saved - virtual bool SaveAsChild(AZStd::string_view savePath) = 0; - - //! Close document and reset its data - virtual bool Close() = 0; - - //! Document is loaded - virtual bool IsOpen() const = 0; - - //! Document has changes pending - virtual bool IsModified() const = 0; - - //! Can the document be saved - virtual bool IsSavable() const = 0; - - //! Returns true if there are reversible modifications to the document - virtual bool CanUndo() const = 0; - - //! Returns true if there are changes that were reversed and can be re-applied to the document - virtual bool CanRedo() const = 0; - - //! Restores the previous state of the document - virtual bool Undo() = 0; - - //! Restores the next state of the document - virtual bool Redo() = 0; - - //! Signal that editing is about to begin, like beginning to drag a slider control - virtual bool BeginEdit() = 0; - - //! Signal that editing has completed, like after releasing the mouse button after continuously dragging a slider control - virtual bool EndEdit() = 0; }; using MaterialDocumentRequestBus = AZ::EBus; diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentSettings.h b/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentSettings.h index d9c835b14b..5f39c50717 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentSettings.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentSettings.h @@ -20,12 +20,11 @@ namespace MaterialEditor struct MaterialDocumentSettings : public AZ::UserSettings { - AZ_RTTI(MaterialDocumentSettings, "{FA4F4BF3-BF39-4753-AAF7-AF383B868881}", AZ::UserSettings); + AZ_RTTI(MaterialDocumentSettings, "{12E8461F-65AD-4AD2-8A1D-82C3B1183522}", AZ::UserSettings); AZ_CLASS_ALLOCATOR(MaterialDocumentSettings, AZ::SystemAllocator, 0); static void Reflect(AZ::ReflectContext* context); - bool m_showReloadDocumentPrompt = true; AZStd::string m_defaultMaterialTypeName = "StandardPBR"; }; } // namespace MaterialEditor diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp index f2e012e158..298d38f650 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp @@ -6,53 +6,39 @@ * */ -#include -#include -#include #include #include +#include #include #include -#include #include #include +#include +#include +#include #include -#include -#include +#include #include #include #include +#include namespace MaterialEditor { MaterialDocument::MaterialDocument() + : AtomToolsFramework::AtomToolsDocument() { MaterialDocumentRequestBus::Handler::BusConnect(m_id); - MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentCreated, m_id); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentCreated, m_id); } MaterialDocument::~MaterialDocument() { - MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentDestroyed, m_id); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentDestroyed, m_id); MaterialDocumentRequestBus::Handler::BusDisconnect(); Clear(); } - const AZ::Uuid& MaterialDocument::GetId() const - { - return m_id; - } - - AZStd::string_view MaterialDocument::GetAbsolutePath() const - { - return m_absolutePath; - } - - AZStd::string_view MaterialDocument::GetRelativePath() const - { - return m_relativePath; - } - AZ::Data::Asset MaterialDocument::GetAsset() const { return m_materialAsset; @@ -170,17 +156,17 @@ namespace MaterialEditor EditorMaterialFunctorResult result = RunEditorMaterialFunctors(dirtyFlags); for (const Name& changedPropertyGroupName : result.m_updatedPropertyGroups) { - MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentPropertyGroupVisibilityChanged, m_id, changedPropertyGroupName, IsPropertyGroupVisible(changedPropertyGroupName)); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentPropertyGroupVisibilityChanged, m_id, changedPropertyGroupName, IsPropertyGroupVisible(changedPropertyGroupName)); } for (const Name& changedPropertyName : result.m_updatedProperties) { - MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentPropertyConfigModified, m_id, GetProperty(changedPropertyName)); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentPropertyConfigModified, m_id, GetProperty(changedPropertyName)); } } } - MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentPropertyValueModified, m_id, property); - MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentModified, m_id); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentPropertyValueModified, m_id, property); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentModified, m_id); } bool MaterialDocument::Open(AZStd::string_view loadPath) @@ -192,7 +178,7 @@ namespace MaterialEditor return false; } - MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentOpened, m_id); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentOpened, m_id); return true; } @@ -222,7 +208,7 @@ namespace MaterialEditor RestorePropertyValues(propertyValuesToRestore); AZStd::swap(undoHistoryToRestore, m_undoHistory); AZStd::swap(undoHistoryIndexToRestore, m_undoHistoryIndex); - MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentOpened, m_id); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentOpened, m_id); return true; } @@ -285,7 +271,7 @@ namespace MaterialEditor AZ_TracePrintf("MaterialDocument", "Material document saved: '%s'.\n", m_absolutePath.data()); - MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentSaved, m_id); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentSaved, m_id); m_saveTriggeredInternally = true; return true; @@ -348,7 +334,7 @@ namespace MaterialEditor AZ_TracePrintf("MaterialDocument", "Material document saved: '%s'.\n", normalizedSavePath.c_str()); - MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentSaved, m_id); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentSaved, m_id); // If the document is saved to a new file we need to reopen the new document to update assets, paths, property deltas. if (!Open(normalizedSavePath)) @@ -424,7 +410,7 @@ namespace MaterialEditor AZ_TracePrintf("MaterialDocument", "Material document saved: '%s'.\n", normalizedSavePath.c_str()); - MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentSaved, m_id); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentSaved, m_id); // If the document is saved to a new file we need to reopen the new document to update assets, paths, property deltas. if (!Open(normalizedSavePath)) @@ -450,7 +436,7 @@ namespace MaterialEditor AZ_TracePrintf("MaterialDocument", "Material document closed: '%s'.\n", m_absolutePath.c_str()); - MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentClosed, m_id); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentClosed, m_id); // Clearing after notification so paths are still available Clear(); @@ -496,7 +482,7 @@ namespace MaterialEditor // The history index is one beyond the last executed command. Decrement the index then execute undo. m_undoHistory[--m_undoHistoryIndex].first(); AZ_TracePrintf("MaterialDocument", "Material document undo: '%s'.\n", m_absolutePath.c_str()); - MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentUndoStateChanged, m_id); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentUndoStateChanged, m_id); return true; } return false; @@ -509,7 +495,7 @@ namespace MaterialEditor // Execute the current redo command then move the history index to the next position. m_undoHistory[m_undoHistoryIndex++].second(); AZ_TracePrintf("MaterialDocument", "Material document redo: '%s'.\n", m_absolutePath.c_str()); - MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentUndoStateChanged, m_id); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentUndoStateChanged, m_id); return true; } return false; @@ -557,7 +543,7 @@ namespace MaterialEditor // Assign the index to the end of history m_undoHistoryIndex = aznumeric_cast(m_undoHistory.size()); - MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentUndoStateChanged, m_id); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentUndoStateChanged, m_id); } m_propertyValuesBeforeEdit.clear(); @@ -584,7 +570,7 @@ namespace MaterialEditor if (!m_saveTriggeredInternally) { AZ_TracePrintf("MaterialDocument", "Material document changed externally: '%s'.\n", m_absolutePath.c_str()); - MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentExternallyModified, m_id); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentExternallyModified, m_id); } m_saveTriggeredInternally = false; } @@ -595,7 +581,7 @@ namespace MaterialEditor if (m_dependentAssetIds.find(asset->GetId()) != m_dependentAssetIds.end()) { AZ_TracePrintf("MaterialDocument", "Material document dependency changed: '%s'.\n", m_absolutePath.c_str()); - MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentDependencyModified, m_id); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentDependencyModified, m_id); } } diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.h index 63d98259ad..09a1873dcf 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.h @@ -18,8 +18,7 @@ #include #include #include - -#include +#include namespace MaterialEditor { @@ -27,7 +26,8 @@ namespace MaterialEditor * MaterialDocument provides an API for modifying and saving material document properties. */ class MaterialDocument - : public MaterialDocumentRequestBus::Handler + : public AtomToolsFramework::AtomToolsDocument + , public MaterialDocumentRequestBus::Handler , private AZ::TickBus::Handler , private AZ::Data::AssetBus::MultiHandler , private AzToolsFramework::AssetSystemBus::Handler @@ -40,16 +40,9 @@ namespace MaterialEditor MaterialDocument(); virtual ~MaterialDocument(); - const AZ::Uuid& GetId() const; - //////////////////////////////////////////////////////////////////////// - // MaterialDocumentRequestBus::Handler implementation - AZStd::string_view GetAbsolutePath() const override; - AZStd::string_view GetRelativePath() const override; - AZ::Data::Asset GetAsset() const override; - AZ::Data::Instance GetInstance() const override; - const AZ::RPI::MaterialSourceData* GetMaterialSourceData() const override; - const AZ::RPI::MaterialTypeSourceData* GetMaterialTypeSourceData() const override; + // AtomToolsFramework::AtomToolsDocument + //////////////////////////////////////////////////////////////////////// const AZStd::any& GetPropertyValue(const AZ::Name& propertyFullName) const override; const AtomToolsFramework::DynamicProperty& GetProperty(const AZ::Name& propertyFullName) const override; bool IsPropertyGroupVisible(const AZ::Name& propertyGroupFullName) const override; @@ -71,6 +64,14 @@ namespace MaterialEditor bool EndEdit() override; //////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////// + // MaterialDocumentRequestBus::Handler implementation + AZ::Data::Asset GetAsset() const override; + AZ::Data::Instance GetInstance() const override; + const AZ::RPI::MaterialSourceData* GetMaterialSourceData() const override; + const AZ::RPI::MaterialTypeSourceData* GetMaterialTypeSourceData() const override; + //////////////////////////////////////////////////////////////////////// + private: // Predicate for evaluating properties @@ -130,21 +131,12 @@ namespace MaterialEditor // @return names for the set of properties and groups that have been changed or need update. EditorMaterialFunctorResult RunEditorMaterialFunctors(AZ::RPI::MaterialPropertyFlags dirtyFlags); - // Unique id of this material document - AZ::Uuid m_id = AZ::Uuid::CreateRandom(); - // Underlying material asset AZ::Data::Asset m_materialAsset; // Material instance being edited AZ::Data::Instance m_materialInstance; - // Relative path to the material source file - AZStd::string m_relativePath; - - // Absolute path to the material source file - AZStd::string m_absolutePath; - // Asset used to open document AZ::Data::AssetId m_sourceAssetId; diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentModule.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentModule.cpp index 5780cd45c0..c721798cfd 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentModule.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentModule.cpp @@ -7,10 +7,8 @@ */ #include -#include - -#include #include +#include namespace MaterialEditor { diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentSettings.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentSettings.cpp index b0d6e35d7f..4823b8c67c 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentSettings.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentSettings.cpp @@ -18,7 +18,6 @@ namespace MaterialEditor { serializeContext->Class() ->Version(1) - ->Field("showReloadDocumentPrompt", &MaterialDocumentSettings::m_showReloadDocumentPrompt) ->Field("defaultMaterialTypeName", &MaterialDocumentSettings::m_defaultMaterialTypeName) ; @@ -28,7 +27,6 @@ namespace MaterialEditor "MaterialDocumentSettings", "") ->ClassElement(AZ::Edit::ClassElements::EditorData, "") ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->DataElement(AZ::Edit::UIHandlers::Default, &MaterialDocumentSettings::m_showReloadDocumentPrompt, "Show Reload Document Prompt", "") ->DataElement(AZ::Edit::UIHandlers::Default, &MaterialDocumentSettings::m_defaultMaterialTypeName, "Default Material Type Name", "") ; } @@ -39,10 +37,9 @@ namespace MaterialEditor behaviorContext->Class("MaterialDocumentSettings") ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) ->Attribute(AZ::Script::Attributes::Category, "Editor") - ->Attribute(AZ::Script::Attributes::Module, "render") + ->Attribute(AZ::Script::Attributes::Module, "materialeditor") ->Constructor() ->Constructor() - ->Property("showReloadDocumentPrompt", BehaviorValueProperty(&MaterialDocumentSettings::m_showReloadDocumentPrompt)) ->Property("defaultMaterialTypeName", BehaviorValueProperty(&MaterialDocumentSettings::m_defaultMaterialTypeName)) ; } diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentSystemComponent.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentSystemComponent.cpp index 3ecabaabcc..9302b5ac5c 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentSystemComponent.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentSystemComponent.cpp @@ -6,40 +6,17 @@ * */ -#include - -#include #include #include -#include -#include -#include -#include -#include +#include #include #include #include -#include -#include -#include -#include -#include -#include - -AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT -#include -#include -#include -#include -#include -AZ_POP_DISABLE_WARNING +#include +#include namespace MaterialEditor { - MaterialDocumentSystemComponent::MaterialDocumentSystemComponent() - { - } - void MaterialDocumentSystemComponent::Reflect(AZ::ReflectContext* context) { MaterialDocumentSettings::Reflect(context); @@ -53,7 +30,7 @@ namespace MaterialEditor { ec->Class("MaterialDocumentSystemComponent", "Tool for editing Atom material files") ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("System", 0xc94d118b)) + ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC_CE("System")) ->Attribute(AZ::Edit::Attributes::AutoExpand, true) ; } @@ -61,66 +38,31 @@ namespace MaterialEditor if (AZ::BehaviorContext* behaviorContext = azrtti_cast(context)) { - behaviorContext->EBus("MaterialDocumentSystemRequestBus") - ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) - ->Attribute(AZ::Script::Attributes::Category, "Editor") - ->Attribute(AZ::Script::Attributes::Module, "materialeditor") - ->Event("CreateDocument", &MaterialDocumentSystemRequestBus::Events::CreateDocument) - ->Event("DestroyDocument", &MaterialDocumentSystemRequestBus::Events::DestroyDocument) - ->Event("OpenDocument", &MaterialDocumentSystemRequestBus::Events::OpenDocument) - ->Event("CreateDocumentFromFile", &MaterialDocumentSystemRequestBus::Events::CreateDocumentFromFile) - ->Event("CloseDocument", &MaterialDocumentSystemRequestBus::Events::CloseDocument) - ->Event("CloseAllDocuments", &MaterialDocumentSystemRequestBus::Events::CloseAllDocuments) - ->Event("CloseAllDocumentsExcept", &MaterialDocumentSystemRequestBus::Events::CloseAllDocumentsExcept) - ->Event("SaveDocument", &MaterialDocumentSystemRequestBus::Events::SaveDocument) - ->Event("SaveDocumentAsCopy", &MaterialDocumentSystemRequestBus::Events::SaveDocumentAsCopy) - ->Event("SaveDocumentAsChild", &MaterialDocumentSystemRequestBus::Events::SaveDocumentAsChild) - ->Event("SaveAllDocuments", &MaterialDocumentSystemRequestBus::Events::SaveAllDocuments) - ; - behaviorContext->EBus("MaterialDocumentRequestBus") ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) ->Attribute(AZ::Script::Attributes::Category, "Editor") ->Attribute(AZ::Script::Attributes::Module, "materialeditor") - ->Event("GetAbsolutePath", &MaterialDocumentRequestBus::Events::GetAbsolutePath) - ->Event("GetRelativePath", &MaterialDocumentRequestBus::Events::GetRelativePath) - ->Event("GetPropertyValue", &MaterialDocumentRequestBus::Events::GetPropertyValue) - ->Event("SetPropertyValue", &MaterialDocumentRequestBus::Events::SetPropertyValue) - ->Event("Open", &MaterialDocumentRequestBus::Events::Open) - ->Event("Rebuild", &MaterialDocumentRequestBus::Events::Rebuild) - ->Event("Close", &MaterialDocumentRequestBus::Events::Close) - ->Event("Save", &MaterialDocumentRequestBus::Events::Save) - ->Event("SaveAsChild", &MaterialDocumentRequestBus::Events::SaveAsChild) - ->Event("SaveAsCopy", &MaterialDocumentRequestBus::Events::SaveAsCopy) - ->Event("IsOpen", &MaterialDocumentRequestBus::Events::IsOpen) - ->Event("IsModified", &MaterialDocumentRequestBus::Events::IsModified) - ->Event("IsSavable", &MaterialDocumentRequestBus::Events::IsSavable) - ->Event("CanUndo", &MaterialDocumentRequestBus::Events::CanUndo) - ->Event("CanRedo", &MaterialDocumentRequestBus::Events::CanRedo) - ->Event("Undo", &MaterialDocumentRequestBus::Events::Undo) - ->Event("Redo", &MaterialDocumentRequestBus::Events::Redo) - ->Event("BeginEdit", &MaterialDocumentRequestBus::Events::BeginEdit) - ->Event("EndEdit", &MaterialDocumentRequestBus::Events::EndEdit) ; } } void MaterialDocumentSystemComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) { - required.push_back(AZ_CRC("AssetProcessorToolsConnection", 0x734669bc)); - required.push_back(AZ_CRC("AssetDatabaseService", 0x3abf5601)); - required.push_back(AZ_CRC("PropertyManagerService", 0x63a3d7ad)); - required.push_back(AZ_CRC("RPISystem", 0xf2add773)); + required.push_back(AZ_CRC_CE("AtomToolsDocumentSystemService")); + required.push_back(AZ_CRC_CE("AssetProcessorToolsConnection")); + required.push_back(AZ_CRC_CE("AssetDatabaseService")); + required.push_back(AZ_CRC_CE("PropertyManagerService")); + required.push_back(AZ_CRC_CE("RPISystem")); } void MaterialDocumentSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) { - provided.push_back(AZ_CRC("MaterialDocumentSystemService")); + provided.push_back(AZ_CRC_CE("MaterialDocumentSystemService")); } void MaterialDocumentSystemComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) { - incompatible.push_back(AZ_CRC("MaterialDocumentSystemService")); + incompatible.push_back(AZ_CRC_CE("MaterialDocumentSystemService")); } void MaterialDocumentSystemComponent::Init() @@ -129,388 +71,15 @@ namespace MaterialEditor void MaterialDocumentSystemComponent::Activate() { - m_documentMap.clear(); - m_settings = AZ::UserSettings::CreateFind(AZ::Crc32("MaterialDocumentSettings"), AZ::UserSettings::CT_GLOBAL); - MaterialDocumentSystemRequestBus::Handler::BusConnect(); - MaterialDocumentNotificationBus::Handler::BusConnect(); + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast( + &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Handler::RegisterDocumentType, + []() + { + return aznew MaterialDocument(); + }); } void MaterialDocumentSystemComponent::Deactivate() { - AZ::TickBus::Handler::BusDisconnect(); - MaterialDocumentNotificationBus::Handler::BusDisconnect(); - MaterialDocumentSystemRequestBus::Handler::BusDisconnect(); - m_documentMap.clear(); - } - - AZ::Uuid MaterialDocumentSystemComponent::CreateDocument() - { - auto document = AZStd::make_unique(); - if (!document) - { - AZ_Error("MaterialDocument", false, "Failed to create new document"); - return AZ::Uuid::CreateNull(); - } - - AZ::Uuid documentId = document->GetId(); - m_documentMap.emplace(documentId, document.release()); - return documentId; - } - - bool MaterialDocumentSystemComponent::DestroyDocument(const AZ::Uuid& documentId) - { - return m_documentMap.erase(documentId) != 0; - } - - void MaterialDocumentSystemComponent::OnDocumentExternallyModified(const AZ::Uuid& documentId) - { - m_documentIdsToReopen.insert(documentId); - if (!AZ::TickBus::Handler::BusIsConnected()) - { - AZ::TickBus::Handler::BusConnect(); - } - } - - void MaterialDocumentSystemComponent::OnDocumentDependencyModified(const AZ::Uuid& documentId) - { - m_documentIdsToRebuild.insert(documentId); - if (!AZ::TickBus::Handler::BusIsConnected()) - { - AZ::TickBus::Handler::BusConnect(); - } - } - - void MaterialDocumentSystemComponent::OnTick([[maybe_unused]] float deltaTime, [[maybe_unused]] AZ::ScriptTimePoint time) - { - for (const AZ::Uuid& documentId : m_documentIdsToReopen) - { - AZStd::string documentPath; - MaterialDocumentRequestBus::EventResult(documentPath, documentId, &MaterialDocumentRequestBus::Events::GetAbsolutePath); - - if (m_settings->m_showReloadDocumentPrompt && - (QMessageBox::question(QApplication::activeWindow(), - QString("Document was externally modified"), - QString("Would you like to reopen the document:\n%1?").arg(documentPath.c_str()), - QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes)) - { - continue; - } - - AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); - - bool openResult = false; - MaterialDocumentRequestBus::EventResult(openResult, documentId, &MaterialDocumentRequestBus::Events::Open, documentPath); - if (!openResult) - { - QMessageBox::critical( - QApplication::activeWindow(), QString("Document could not be opened"), - QString("Failed to open: \n%1\n\n%2").arg(documentPath.c_str()).arg(traceRecorder.GetDump().c_str())); - MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::CloseDocument, documentId); - } - } - - for (const AZ::Uuid& documentId : m_documentIdsToRebuild) - { - AZStd::string documentPath; - MaterialDocumentRequestBus::EventResult(documentPath, documentId, &MaterialDocumentRequestBus::Events::GetAbsolutePath); - - if (m_settings->m_showReloadDocumentPrompt && - (QMessageBox::question(QApplication::activeWindow(), - QString("Document dependencies have changed"), - QString("Would you like to update the document with these changes:\n%1?").arg(documentPath.c_str()), - QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes)) - { - continue; - } - - AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); - - bool openResult = false; - MaterialDocumentRequestBus::EventResult(openResult, documentId, &MaterialDocumentRequestBus::Events::Rebuild); - if (!openResult) - { - QMessageBox::critical( - QApplication::activeWindow(), QString("Document could not be opened"), - QString("Failed to open: \n%1\n\n%2").arg(documentPath.c_str()).arg(traceRecorder.GetDump().c_str())); - MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::CloseDocument, documentId); - } - } - - m_documentIdsToRebuild.clear(); - m_documentIdsToReopen.clear(); - AZ::TickBus::Handler::BusDisconnect(); - } - - AZ::Uuid MaterialDocumentSystemComponent::OpenDocument(AZStd::string_view sourcePath) - { - return OpenDocumentImpl(sourcePath, true); - } - - AZ::Uuid MaterialDocumentSystemComponent::CreateDocumentFromFile(AZStd::string_view sourcePath, AZStd::string_view targetPath) - { - const AZ::Uuid documentId = OpenDocumentImpl(sourcePath, false); - if (documentId.IsNull()) - { - return AZ::Uuid::CreateNull(); - } - - if (!SaveDocumentAsChild(documentId, targetPath)) - { - CloseDocument(documentId); - return AZ::Uuid::CreateNull(); - } - - // Send document open notification after creating new material - MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentOpened, documentId); - return documentId; - } - - bool MaterialDocumentSystemComponent::CloseDocument(const AZ::Uuid& documentId) - { - bool isOpen = false; - MaterialDocumentRequestBus::EventResult(isOpen, documentId, &MaterialDocumentRequestBus::Events::IsOpen); - if (!isOpen) - { - // immediately destroy unopened documents - MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::DestroyDocument, documentId); - return true; - } - - AZStd::string documentPath; - MaterialDocumentRequestBus::EventResult(documentPath, documentId, &MaterialDocumentRequestBus::Events::GetAbsolutePath); - - bool isModified = false; - MaterialDocumentRequestBus::EventResult(isModified, documentId, &MaterialDocumentRequestBus::Events::IsModified); - if (isModified) - { - auto selection = QMessageBox::question(QApplication::activeWindow(), - QString("Document has unsaved changes"), - QString("Do you want to save changes to\n%1?").arg(documentPath.c_str()), - QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); - if (selection == QMessageBox::Cancel) - { - AZ_TracePrintf("MaterialDocument", "Close document canceled: %s", documentPath.c_str()); - return false; - } - if (selection == QMessageBox::Yes) - { - if (!SaveDocument(documentId)) - { - AZ_Error("MaterialDocument", false, "Close document failed because document was not saved: %s", documentPath.c_str()); - return false; - } - } - } - - AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); - - bool closeResult = true; - MaterialDocumentRequestBus::EventResult(closeResult, documentId, &MaterialDocumentRequestBus::Events::Close); - if (!closeResult) - { - QMessageBox::critical( - QApplication::activeWindow(), QString("Document could not be closed"), - QString("Failed to close: \n%1\n\n%2").arg(documentPath.c_str()).arg(traceRecorder.GetDump().c_str())); - return false; - } - - MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::DestroyDocument, documentId); - return true; - } - - bool MaterialDocumentSystemComponent::CloseAllDocuments() - { - bool result = true; - auto documentMap = m_documentMap; - for (const auto& documentPair : documentMap) - { - if (!CloseDocument(documentPair.first)) - { - result = false; - } - } - - return result; - } - - bool MaterialDocumentSystemComponent::CloseAllDocumentsExcept(const AZ::Uuid& documentId) - { - bool result = true; - auto documentMap = m_documentMap; - for (const auto& documentPair : documentMap) - { - if (documentPair.first != documentId) - { - if (!CloseDocument(documentPair.first)) - { - result = false; - } - } - } - - return result; - } - - bool MaterialDocumentSystemComponent::SaveDocument(const AZ::Uuid& documentId) - { - AZStd::string saveDocumentPath; - MaterialDocumentRequestBus::EventResult(saveDocumentPath, documentId, &MaterialDocumentRequestBus::Events::GetAbsolutePath); - - if (saveDocumentPath.empty() || !AzFramework::StringFunc::Path::Normalize(saveDocumentPath)) - { - return false; - } - - const QFileInfo saveInfo(saveDocumentPath.c_str()); - if (saveInfo.exists() && !saveInfo.isWritable()) - { - QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Document could not be overwritten:\n%1").arg(saveDocumentPath.c_str())); - return false; - } - - AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); - - bool result = false; - MaterialDocumentRequestBus::EventResult(result, documentId, &MaterialDocumentRequestBus::Events::Save); - if (!result) - { - QMessageBox::critical( - QApplication::activeWindow(), QString("Document could not be saved"), - QString("Failed to save: \n%1\n\n%2").arg(saveDocumentPath.c_str()).arg(traceRecorder.GetDump().c_str())); - return false; - } - - return true; - } - - bool MaterialDocumentSystemComponent::SaveDocumentAsCopy(const AZ::Uuid& documentId, AZStd::string_view targetPath) - { - AZStd::string saveDocumentPath = targetPath; - if (saveDocumentPath.empty() || !AzFramework::StringFunc::Path::Normalize(saveDocumentPath)) - { - return false; - } - - const QFileInfo saveInfo(saveDocumentPath.c_str()); - if (saveInfo.exists() && !saveInfo.isWritable()) - { - QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Document could not be overwritten:\n%1").arg(saveDocumentPath.c_str())); - return false; - } - - AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); - - bool result = false; - MaterialDocumentRequestBus::EventResult(result, documentId, &MaterialDocumentRequestBus::Events::SaveAsCopy, saveDocumentPath); - if (!result) - { - QMessageBox::critical( - QApplication::activeWindow(), QString("Document could not be saved"), - QString("Failed to save: \n%1\n\n%2").arg(saveDocumentPath.c_str()).arg(traceRecorder.GetDump().c_str())); - return false; - } - - return true; - } - - bool MaterialDocumentSystemComponent::SaveDocumentAsChild(const AZ::Uuid& documentId, AZStd::string_view targetPath) - { - AZStd::string saveDocumentPath = targetPath; - if (saveDocumentPath.empty() || !AzFramework::StringFunc::Path::Normalize(saveDocumentPath)) - { - return false; - } - - const QFileInfo saveInfo(saveDocumentPath.c_str()); - if (saveInfo.exists() && !saveInfo.isWritable()) - { - QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Document could not be overwritten:\n%1").arg(saveDocumentPath.c_str())); - return false; - } - - AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); - - bool result = false; - MaterialDocumentRequestBus::EventResult(result, documentId, &MaterialDocumentRequestBus::Events::SaveAsChild, saveDocumentPath); - if (!result) - { - QMessageBox::critical( - QApplication::activeWindow(), QString("Document could not be saved"), - QString("Failed to save: \n%1\n\n%2").arg(saveDocumentPath.c_str()).arg(traceRecorder.GetDump().c_str())); - return false; - } - - return true; - } - - bool MaterialDocumentSystemComponent::SaveAllDocuments() - { - bool result = true; - for (const auto& documentPair : m_documentMap) - { - if (!SaveDocument(documentPair.first)) - { - result = false; - } - } - - return result; - } - - AZ::Uuid MaterialDocumentSystemComponent::OpenDocumentImpl(AZStd::string_view sourcePath, bool checkIfAlreadyOpen) - { - AZStd::string requestedPath = sourcePath; - if (requestedPath.empty()) - { - return AZ::Uuid::CreateNull(); - } - - if (!AzFramework::StringFunc::Path::Normalize(requestedPath)) - { - QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Document path is invalid:\n%1").arg(requestedPath.c_str())); - return AZ::Uuid::CreateNull(); - } - - // Determine if the file is already open and select it - if (checkIfAlreadyOpen) - { - for (const auto& documentPair : m_documentMap) - { - AZStd::string openDocumentPath; - MaterialDocumentRequestBus::EventResult(openDocumentPath, documentPair.first, &MaterialDocumentRequestBus::Events::GetAbsolutePath); - if (openDocumentPath == requestedPath) - { - MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentOpened, documentPair.first); - return documentPair.first; - } - } - } - - AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); - - AZ::Uuid documentId = AZ::Uuid::CreateNull(); - MaterialDocumentSystemRequestBus::BroadcastResult(documentId, &MaterialDocumentSystemRequestBus::Events::CreateDocument); - if (documentId.IsNull()) - { - QMessageBox::critical( - QApplication::activeWindow(), QString("Document could not be created"), - QString("Failed to create: \n%1\n\n%2").arg(requestedPath.c_str()).arg(traceRecorder.GetDump().c_str())); - return AZ::Uuid::CreateNull(); - } - - traceRecorder.GetDump().clear(); - - bool openResult = false; - MaterialDocumentRequestBus::EventResult(openResult, documentId, &MaterialDocumentRequestBus::Events::Open, requestedPath); - if (!openResult) - { - QMessageBox::critical( - QApplication::activeWindow(), QString("Document could not be opened"), - QString("Failed to open: \n%1\n\n%2").arg(requestedPath.c_str()).arg(traceRecorder.GetDump().c_str())); - MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::DestroyDocument, documentId); - return AZ::Uuid::CreateNull(); - } - - return documentId; } } diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentSystemComponent.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentSystemComponent.h index 3b20f40b4f..af19956088 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentSystemComponent.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentSystemComponent.h @@ -9,34 +9,17 @@ #pragma once #include -#include -#include -#include - -#include -#include -#include -#include -#include - -AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT -#include -#include -AZ_POP_DISABLE_WARNING namespace MaterialEditor { - //! MaterialDocumentSystemComponent is the central component of the Material Editor Core gem + //! MaterialDocumentSystemComponent class MaterialDocumentSystemComponent : public AZ::Component - , private AZ::TickBus::Handler - , private MaterialDocumentNotificationBus::Handler - , private MaterialDocumentSystemRequestBus::Handler { public: - AZ_COMPONENT(MaterialDocumentSystemComponent, "{58ABE0AE-2710-41E2-ADFD-E2D67407427D}"); + AZ_COMPONENT(MaterialDocumentSystemComponent, "{E011DA51-855D-45FA-87A3-1C1CD6379091}"); - MaterialDocumentSystemComponent(); + MaterialDocumentSystemComponent() = default; ~MaterialDocumentSystemComponent() = default; MaterialDocumentSystemComponent(const MaterialDocumentSystemComponent&) = delete; MaterialDocumentSystemComponent& operator=(const MaterialDocumentSystemComponent&) = delete; @@ -54,39 +37,5 @@ namespace MaterialEditor void Activate() override; void Deactivate() override; //////////////////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////////////////////////////// - // MaterialDocumentNotificationBus::Handler overrides... - void OnDocumentDependencyModified(const AZ::Uuid& documentId) override; - void OnDocumentExternallyModified(const AZ::Uuid& documentId) override; - ////////////////////////////////////////////////////////////////////////// - - //////////////////////////////////////////////////////////////////////// - // AZ::TickBus::Handler overrides... - void OnTick(float deltaTime, AZ::ScriptTimePoint time) override; - //////////////////////////////////////////////////////////////////////// - - //////////////////////////////////////////////////////////////////////// - // MaterialDocumentSystemRequestBus::Handler overrides... - AZ::Uuid CreateDocument() override; - bool DestroyDocument(const AZ::Uuid& documentId) override; - AZ::Uuid OpenDocument(AZStd::string_view sourcePath) override; - AZ::Uuid CreateDocumentFromFile(AZStd::string_view sourcePath, AZStd::string_view targetPath) override; - bool CloseDocument(const AZ::Uuid& documentId) override; - bool CloseAllDocuments() override; - bool CloseAllDocumentsExcept(const AZ::Uuid& documentId) override; - bool SaveDocument(const AZ::Uuid& documentId) override; - bool SaveDocumentAsCopy(const AZ::Uuid& documentId, AZStd::string_view targetPath) override; - bool SaveDocumentAsChild(const AZ::Uuid& documentId, AZStd::string_view targetPath) override; - bool SaveAllDocuments() override; - //////////////////////////////////////////////////////////////////////// - - AZ::Uuid OpenDocumentImpl(AZStd::string_view sourcePath, bool checkIfAlreadyOpen); - - AZStd::intrusive_ptr m_settings; - AZStd::unordered_map> m_documentMap; - AZStd::unordered_set m_documentIdsToRebuild; - AZStd::unordered_set m_documentIdsToReopen; - const size_t m_maxMessageBoxLineCount = 15; }; } // namespace MaterialEditor diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp index bdd9e6fbaf..cec882cabb 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp @@ -7,9 +7,9 @@ */ #include -#include #include #include +#include #include #include #include @@ -68,7 +68,7 @@ namespace MaterialEditor const AZStd::string openDocumentPath = commandLine.GetMiscValue(openDocumentIndex); AZ_Printf(GetBuildTargetName().c_str(), "Opening document: %s", openDocumentPath.c_str()); - MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::OpenDocument, openDocumentPath); + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::OpenDocument, openDocumentPath); } Base::ProcessCommandLine(commandLine); diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h index da691feff7..e91bce48f0 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h @@ -8,8 +8,8 @@ #pragma once -#include #include +#include namespace MaterialEditor { diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.cpp index 23e37b2f7c..f98cdce91b 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.cpp @@ -243,7 +243,7 @@ namespace MaterialEditor OnFieldOfViewChanged(viewportSettings->m_fieldOfView); OnDisplayMapperOperationTypeChanged(viewportSettings->m_displayMapperOperationType); - MaterialDocumentNotificationBus::Handler::BusConnect(); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusConnect(); MaterialViewportNotificationBus::Handler::BusConnect(); AZ::TickBus::Handler::BusConnect(); AZ::TransformNotificationBus::MultiHandler::BusConnect(m_cameraEntity->GetId()); @@ -255,7 +255,7 @@ namespace MaterialEditor AzFramework::WindowSystemRequestBus::Handler::BusDisconnect(); AZ::TransformNotificationBus::MultiHandler::BusDisconnect(); AZ::TickBus::Handler::BusDisconnect(); - MaterialDocumentNotificationBus::Handler::BusDisconnect(); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusDisconnect(); MaterialViewportNotificationBus::Handler::BusDisconnect(); AZ::Data::AssetBus::Handler::BusDisconnect(); diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.h index 4efaf51d01..240d66fd43 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.h @@ -8,16 +8,14 @@ #pragma once -#include -#include -#include - -#include -#include #include #include +#include #include - +#include +#include +#include +#include #include #include @@ -45,7 +43,7 @@ namespace MaterialEditor class MaterialViewportRenderer : public AZ::Data::AssetBus::Handler , public AZ::TickBus::Handler - , public MaterialDocumentNotificationBus::Handler + , public AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler , public MaterialViewportNotificationBus::Handler , public AZ::TransformNotificationBus::MultiHandler , public AzFramework::WindowSystemRequestBus::Handler @@ -60,7 +58,7 @@ namespace MaterialEditor private: - // MaterialDocumentNotificationBus::Handler interface overrides... + // AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler interface overrides... void OnDocumentOpened(const AZ::Uuid& documentId) override; // MaterialViewportNotificationBus::Handler interface overrides... diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportSettings.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportSettings.cpp index 52f277d984..c2c35119c2 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportSettings.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportSettings.cpp @@ -54,7 +54,7 @@ namespace MaterialEditor behaviorContext->Class("MaterialViewportSettings") ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) ->Attribute(AZ::Script::Attributes::Category, "Editor") - ->Attribute(AZ::Script::Attributes::Module, "render") + ->Attribute(AZ::Script::Attributes::Module, "materialeditor") ->Constructor() ->Constructor() ->Property("enableGrid", BehaviorValueProperty(&MaterialViewportSettings::m_enableGrid)) diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserWidget.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserWidget.cpp index 20098f461b..4df76b4dac 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserWidget.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserWidget.cpp @@ -7,9 +7,12 @@ */ #include -#include +#include +#include #include #include +#include +#include #include #include #include @@ -18,9 +21,8 @@ #include #include #include - -#include -#include +#include +#include AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT #include @@ -91,14 +93,14 @@ namespace MaterialEditor } }); - MaterialDocumentNotificationBus::Handler::BusConnect(); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusConnect(); } MaterialBrowserWidget::~MaterialBrowserWidget() { // Maintains the tree expansion state between runs m_ui->m_assetBrowserTreeViewWidget->SaveState(); - MaterialDocumentNotificationBus::Handler::BusDisconnect(); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusDisconnect(); AZ::TickBus::Handler::BusDisconnect(); } @@ -144,13 +146,13 @@ namespace MaterialEditor { if (entry) { - if (AzFramework::StringFunc::Path::IsExtension(entry->GetFullPath().c_str(), MaterialExtension)) + if (AzFramework::StringFunc::Path::IsExtension(entry->GetFullPath().c_str(), AZ::RPI::MaterialSourceData::Extension)) { - MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::OpenDocument, entry->GetFullPath()); + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::OpenDocument, entry->GetFullPath()); } - else if (AzFramework::StringFunc::Path::IsExtension(entry->GetFullPath().c_str(), MaterialTypeExtension)) + else if (AzFramework::StringFunc::Path::IsExtension(entry->GetFullPath().c_str(), AZ::RPI::MaterialTypeSourceData::Extension)) { - //ignore MaterialTypeExtension + //ignore AZ::RPI::MaterialTypeSourceData::Extension } else { @@ -163,7 +165,7 @@ namespace MaterialEditor void MaterialBrowserWidget::OnDocumentOpened(const AZ::Uuid& documentId) { AZStd::string absolutePath; - MaterialDocumentRequestBus::EventResult(absolutePath, documentId, &MaterialDocumentRequestBus::Events::GetAbsolutePath); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(absolutePath, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::GetAbsolutePath); if (!absolutePath.empty()) { // Selecting a new asset in the browser is not guaranteed to happen immediately. @@ -230,4 +232,4 @@ namespace MaterialEditor } // namespace MaterialEditor -#include +#include diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserWidget.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserWidget.h index 2ded270af0..24a244bc3c 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserWidget.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserWidget.h @@ -9,15 +9,15 @@ #pragma once #if !defined(Q_MOC_RUN) -#include +#include #include #include #include #include AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT -#include #include +#include AZ_POP_DISABLE_WARNING #endif @@ -45,7 +45,7 @@ namespace MaterialEditor class MaterialBrowserWidget : public QWidget , protected AZ::TickBus::Handler - , protected MaterialDocumentNotificationBus::Handler + , protected AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler { Q_OBJECT public: @@ -56,7 +56,7 @@ namespace MaterialEditor AzToolsFramework::AssetBrowser::FilterConstType CreateFilter() const; void OpenSelectedEntries(); - // MaterialDocumentNotificationBus::Handler implementation + // AtomToolsDocumentNotificationBus::Handler implementation void OnDocumentOpened(const AZ::Uuid& documentId) override; // AZ::TickBus::Handler diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorBrowserInteractions.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorBrowserInteractions.cpp index b957c550e6..3440d9c316 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorBrowserInteractions.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorBrowserInteractions.cpp @@ -6,32 +6,28 @@ * */ -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include - #include -#include - -#include -#include - -#include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include namespace MaterialEditor { @@ -66,11 +62,11 @@ namespace MaterialEditor if (entry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Source) { const auto source = azalias_cast(entry); - if (AzFramework::StringFunc::Path::IsExtension(entry->GetFullPath().c_str(), MaterialExtension)) + if (AzFramework::StringFunc::Path::IsExtension(entry->GetFullPath().c_str(), AZ::RPI::MaterialSourceData::Extension)) { AddContextMenuActionsForMaterialSource(caller, menu, source); } - else if (AzFramework::StringFunc::Path::IsExtension(entry->GetFullPath().c_str(), MaterialTypeExtension)) + else if (AzFramework::StringFunc::Path::IsExtension(entry->GetFullPath().c_str(), AZ::RPI::MaterialTypeSourceData::Extension)) { AddContextMenuActionsForMaterialTypeSource(caller, menu, source); } @@ -115,7 +111,7 @@ namespace MaterialEditor AZ_CORRECT_FILESYSTEM_SEPARATOR + "untitled." + AZ::RPI::MaterialSourceData::Extension).absoluteFilePath(); - MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::CreateDocumentFromFile, + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CreateDocumentFromFile, entry->GetFullPath(), AtomToolsFramework::GetSaveFileInfo(defaultPath).absoluteFilePath().toUtf8().constData()); }); @@ -157,7 +153,7 @@ namespace MaterialEditor { menu->addAction("Open", [entry]() { - MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::OpenDocument, entry->GetFullPath()); + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::OpenDocument, entry->GetFullPath()); }); menu->addAction("Duplicate...", [entry, caller]() @@ -191,7 +187,7 @@ namespace MaterialEditor AZ_CORRECT_FILESYSTEM_SEPARATOR + "untitled." + AZ::RPI::MaterialSourceData::Extension).absoluteFilePath(); - MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::CreateDocumentFromFile, + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CreateDocumentFromFile, entry->GetFullPath(), AtomToolsFramework::GetSaveFileInfo(defaultPath).absoluteFilePath().toUtf8().constData()); }); @@ -258,7 +254,7 @@ namespace MaterialEditor !createDialog.m_materialFileInfo.absoluteFilePath().isEmpty() && !createDialog.m_materialTypeFileInfo.absoluteFilePath().isEmpty()) { - MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::CreateDocumentFromFile, + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CreateDocumentFromFile, createDialog.m_materialTypeFileInfo.absoluteFilePath().toUtf8().constData(), createDialog.m_materialFileInfo.absoluteFilePath().toUtf8().constData()); } diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp index ffe5ec408a..ca938c3745 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp @@ -6,7 +6,11 @@ * */ +#include #include +#include +#include +#include #include #include #include @@ -15,11 +19,6 @@ #include #include #include - -#include -#include -#include - #include #include #include @@ -106,13 +105,13 @@ namespace MaterialEditor m_advancedDockManager->restoreState(windowState); } - MaterialDocumentNotificationBus::Handler::BusConnect(); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusConnect(); OnDocumentOpened(AZ::Uuid::CreateNull()); } MaterialEditorWindow::~MaterialEditorWindow() { - MaterialDocumentNotificationBus::Handler::BusDisconnect(); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusDisconnect(); } @@ -150,7 +149,7 @@ namespace MaterialEditor void MaterialEditorWindow::closeEvent(QCloseEvent* closeEvent) { bool didClose = true; - MaterialDocumentSystemRequestBus::BroadcastResult(didClose, &MaterialDocumentSystemRequestBus::Events::CloseAllDocuments); + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::BroadcastResult(didClose, &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CloseAllDocuments); if (!didClose) { closeEvent->ignore(); @@ -171,17 +170,17 @@ namespace MaterialEditor void MaterialEditorWindow::OnDocumentOpened(const AZ::Uuid& documentId) { bool isOpen = false; - MaterialDocumentRequestBus::EventResult(isOpen, documentId, &MaterialDocumentRequestBus::Events::IsOpen); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(isOpen, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::IsOpen); bool isSavable = false; - MaterialDocumentRequestBus::EventResult(isSavable, documentId, &MaterialDocumentRequestBus::Events::IsSavable); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(isSavable, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::IsSavable); bool isModified = false; - MaterialDocumentRequestBus::EventResult(isModified, documentId, &MaterialDocumentRequestBus::Events::IsModified); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(isModified, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::IsModified); bool canUndo = false; - MaterialDocumentRequestBus::EventResult(canUndo, documentId, &MaterialDocumentRequestBus::Events::CanUndo); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(canUndo, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::CanUndo); bool canRedo = false; - MaterialDocumentRequestBus::EventResult(canRedo, documentId, &MaterialDocumentRequestBus::Events::CanRedo); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(canRedo, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::CanRedo); AZStd::string absolutePath; - MaterialDocumentRequestBus::EventResult(absolutePath, documentId, &MaterialDocumentRequestBus::Events::GetAbsolutePath); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(absolutePath, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::GetAbsolutePath); AZStd::string filename; AzFramework::StringFunc::Path::GetFullFileName(absolutePath.c_str(), filename); @@ -238,7 +237,7 @@ namespace MaterialEditor const QString documentPath = GetDocumentPath(documentId); if (!documentPath.isEmpty()) { - const QString status = QString("Document closed: %1").arg(documentPath); + const QString status = QString("Document opened: %1").arg(documentPath); m_statusMessage->setText(QString("%1").arg(status)); } } @@ -255,9 +254,9 @@ namespace MaterialEditor void MaterialEditorWindow::OnDocumentModified(const AZ::Uuid& documentId) { bool isModified = false; - MaterialDocumentRequestBus::EventResult(isModified, documentId, &MaterialDocumentRequestBus::Events::IsModified); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(isModified, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::IsModified); AZStd::string absolutePath; - MaterialDocumentRequestBus::EventResult(absolutePath, documentId, &MaterialDocumentRequestBus::Events::GetAbsolutePath); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(absolutePath, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::GetAbsolutePath); AZStd::string filename; AzFramework::StringFunc::Path::GetFullFileName(absolutePath.c_str(), filename); UpdateTabForDocumentId(documentId, filename, absolutePath, isModified); @@ -268,9 +267,9 @@ namespace MaterialEditor if (documentId == GetDocumentIdFromTab(m_tabWidget->currentIndex())) { bool canUndo = false; - MaterialDocumentRequestBus::EventResult(canUndo, documentId, &MaterialDocumentRequestBus::Events::CanUndo); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(canUndo, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::CanUndo); bool canRedo = false; - MaterialDocumentRequestBus::EventResult(canRedo, documentId, &MaterialDocumentRequestBus::Events::CanRedo); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(canRedo, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::CanRedo); m_actionUndo->setEnabled(canUndo); m_actionRedo->setEnabled(canRedo); } @@ -279,15 +278,15 @@ namespace MaterialEditor void MaterialEditorWindow::OnDocumentSaved(const AZ::Uuid& documentId) { bool isModified = false; - MaterialDocumentRequestBus::EventResult(isModified, documentId, &MaterialDocumentRequestBus::Events::IsModified); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(isModified, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::IsModified); AZStd::string absolutePath; - MaterialDocumentRequestBus::EventResult(absolutePath, documentId, &MaterialDocumentRequestBus::Events::GetAbsolutePath); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(absolutePath, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::GetAbsolutePath); AZStd::string filename; AzFramework::StringFunc::Path::GetFullFileName(absolutePath.c_str(), filename); UpdateTabForDocumentId(documentId, filename, absolutePath, isModified); const QString documentPath = GetDocumentPath(documentId); - const QString status = QString("Document closed: %1").arg(documentPath); + const QString status = QString("Document saved: %1").arg(documentPath); m_statusMessage->setText(QString("%1").arg(status)); } @@ -306,7 +305,7 @@ namespace MaterialEditor !createDialog.m_materialFileInfo.absoluteFilePath().isEmpty() && !createDialog.m_materialTypeFileInfo.absoluteFilePath().isEmpty()) { - MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::CreateDocumentFromFile, + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CreateDocumentFromFile, createDialog.m_materialTypeFileInfo.absoluteFilePath().toUtf8().constData(), createDialog.m_materialFileInfo.absoluteFilePath().toUtf8().constData()); } @@ -317,7 +316,7 @@ namespace MaterialEditor const AZStd::string filePath = AtomToolsFramework::GetOpenFileInfo(assetTypes).absoluteFilePath().toUtf8().constData(); if (!filePath.empty()) { - MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::OpenDocument, filePath); + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::OpenDocument, filePath); } }, QKeySequence::Open); @@ -328,11 +327,11 @@ namespace MaterialEditor m_actionSave = m_menuFile->addAction("&Save", [this]() { const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex()); bool result = false; - MaterialDocumentSystemRequestBus::BroadcastResult(result, &MaterialDocumentSystemRequestBus::Events::SaveDocument, documentId); + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::BroadcastResult(result, &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::SaveDocument, documentId); if (!result) { const QString documentPath = GetDocumentPath(documentId); - const QString status = QString("Failed to save document: %1").arg(documentPath); + const QString status = QString("Document save failed: %1").arg(documentPath); m_statusMessage->setText(QString("%1").arg(status)); } }, QKeySequence::Save); @@ -342,11 +341,11 @@ namespace MaterialEditor const QString documentPath = GetDocumentPath(documentId); bool result = false; - MaterialDocumentSystemRequestBus::BroadcastResult(result, &MaterialDocumentSystemRequestBus::Events::SaveDocumentAsCopy, + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::BroadcastResult(result, &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::SaveDocumentAsCopy, documentId, AtomToolsFramework::GetSaveFileInfo(documentPath).absoluteFilePath().toUtf8().constData()); if (!result) { - const QString status = QString("Failed to save document: %1").arg(documentPath); + const QString status = QString("Document save failed: %1").arg(documentPath); m_statusMessage->setText(QString("%1").arg(status)); } }, QKeySequence::SaveAs); @@ -356,21 +355,21 @@ namespace MaterialEditor const QString documentPath = GetDocumentPath(documentId); bool result = false; - MaterialDocumentSystemRequestBus::BroadcastResult(result, &MaterialDocumentSystemRequestBus::Events::SaveDocumentAsChild, + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::BroadcastResult(result, &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::SaveDocumentAsChild, documentId, AtomToolsFramework::GetSaveFileInfo(documentPath).absoluteFilePath().toUtf8().constData()); if (!result) { - const QString status = QString("Failed to save document: %1").arg(documentPath); + const QString status = QString("Document save failed: %1").arg(documentPath); m_statusMessage->setText(QString("%1").arg(status)); } }); m_actionSaveAll = m_menuFile->addAction("Save A&ll", [this]() { bool result = false; - MaterialDocumentSystemRequestBus::BroadcastResult(result, &MaterialDocumentSystemRequestBus::Events::SaveAllDocuments); + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::BroadcastResult(result, &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::SaveAllDocuments); if (!result) { - const QString status = QString("Failed to save documents."); + const QString status = QString("Document save all failed."); m_statusMessage->setText(QString("%1").arg(status)); } }); @@ -379,16 +378,16 @@ namespace MaterialEditor m_actionClose = m_menuFile->addAction("&Close", [this]() { const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex()); - MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::CloseDocument, documentId); + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CloseDocument, documentId); }, QKeySequence::Close); m_actionCloseAll = m_menuFile->addAction("Close All", [this]() { - MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::CloseAllDocuments); + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CloseAllDocuments); }); m_actionCloseOthers = m_menuFile->addAction("Close Others", [this]() { const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex()); - MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::CloseAllDocumentsExcept, documentId); + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CloseAllDocumentsExcept, documentId); }); m_menuFile->addSeparator(); @@ -412,11 +411,11 @@ namespace MaterialEditor m_actionUndo = m_menuEdit->addAction("&Undo", [this]() { const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex()); bool result = false; - MaterialDocumentRequestBus::EventResult(result, documentId, &MaterialDocumentRequestBus::Events::Undo); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(result, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::Undo); if (!result) { const QString documentPath = GetDocumentPath(documentId); - const QString status = QString("Failed to perform undo on document: %1").arg(documentPath); + const QString status = QString("Document undo failed: %1").arg(documentPath); m_statusMessage->setText(QString("%1").arg(status)); } }, QKeySequence::Undo); @@ -424,11 +423,11 @@ namespace MaterialEditor m_actionRedo = m_menuEdit->addAction("&Redo", [this]() { const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex()); bool result = false; - MaterialDocumentRequestBus::EventResult(result, documentId, &MaterialDocumentRequestBus::Events::Redo); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(result, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::Redo); if (!result) { const QString documentPath = GetDocumentPath(documentId); - const QString status = QString("Failed to perform redo on document: %1").arg(documentPath); + const QString status = QString("Document redo failed: %1").arg(documentPath); m_statusMessage->setText(QString("%1").arg(status)); } }, QKeySequence::Redo); @@ -501,19 +500,19 @@ namespace MaterialEditor // This should automatically clear the active document connect(m_tabWidget, &QTabWidget::currentChanged, this, [this](int tabIndex) { const AZ::Uuid documentId = GetDocumentIdFromTab(tabIndex); - MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentOpened, documentId); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentOpened, documentId); }); connect(m_tabWidget, &QTabWidget::tabCloseRequested, this, [this](int tabIndex) { const AZ::Uuid documentId = GetDocumentIdFromTab(tabIndex); - MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::CloseDocument, documentId); + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CloseDocument, documentId); }); } QString MaterialEditorWindow::GetDocumentPath(const AZ::Uuid& documentId) const { AZStd::string absolutePath; - MaterialDocumentRequestBus::EventResult(absolutePath, documentId, &MaterialDocumentRequestBus::Handler::GetAbsolutePath); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(absolutePath, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Handler::GetAbsolutePath); return absolutePath.c_str(); } @@ -529,15 +528,15 @@ namespace MaterialEditor const QString selectActionName = (currentTabIndex == clickedTabIndex) ? "Select in Browser" : "Select"; tabMenu.addAction(selectActionName, [this, clickedTabIndex]() { const AZ::Uuid documentId = GetDocumentIdFromTab(clickedTabIndex); - MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentOpened, documentId); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentOpened, documentId); }); tabMenu.addAction("Close", [this, clickedTabIndex]() { const AZ::Uuid documentId = GetDocumentIdFromTab(clickedTabIndex); - MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::CloseDocument, documentId); + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CloseDocument, documentId); }); auto closeOthersAction = tabMenu.addAction("Close Others", [this, clickedTabIndex]() { const AZ::Uuid documentId = GetDocumentIdFromTab(clickedTabIndex); - MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::CloseAllDocumentsExcept, documentId); + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CloseAllDocumentsExcept, documentId); }); closeOthersAction->setEnabled(tabBar->count() > 1); tabMenu.exec(QCursor::pos()); diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.h index 43151b9c03..b7d0cbf8da 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.h @@ -9,7 +9,7 @@ #pragma once #if !defined(Q_MOC_RUN) -#include +#include #include #include @@ -30,7 +30,7 @@ namespace MaterialEditor */ class MaterialEditorWindow : public AtomToolsFramework::AtomToolsMainWindow - , private MaterialDocumentNotificationBus::Handler + , private AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler { Q_OBJECT public: @@ -46,7 +46,7 @@ namespace MaterialEditor void LockViewportRenderTargetSize(uint32_t width, uint32_t height) override; void UnlockViewportRenderTargetSize() override; - // MaterialDocumentNotificationBus::Handler overrides... + // AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler overrides... void OnDocumentOpened(const AZ::Uuid& documentId) override; void OnDocumentClosed(const AZ::Uuid& documentId) override; void OnDocumentModified(const AZ::Uuid& documentId) override; diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowSettings.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowSettings.cpp index 62a1b207de..71c71e8b75 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowSettings.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowSettings.cpp @@ -37,7 +37,7 @@ namespace MaterialEditor behaviorContext->Class("MaterialEditorWindowSettings") ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) ->Attribute(AZ::Script::Attributes::Category, "Editor") - ->Attribute(AZ::Script::Attributes::Module, "render") + ->Attribute(AZ::Script::Attributes::Module, "materialeditor") ->Constructor() ->Constructor() ; diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialInspector/MaterialInspector.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialInspector/MaterialInspector.cpp index ccf07c2136..28d7d3d3f5 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialInspector/MaterialInspector.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialInspector/MaterialInspector.cpp @@ -6,17 +6,15 @@ * */ +#include #include #include #include #include - -#include - +#include #include #include #include - #include namespace MaterialEditor @@ -27,12 +25,12 @@ namespace MaterialEditor m_windowSettings = AZ::UserSettings::CreateFind( AZ::Crc32("MaterialEditorWindowSettings"), AZ::UserSettings::CT_GLOBAL); - MaterialDocumentNotificationBus::Handler::BusConnect(); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusConnect(); } MaterialInspector::~MaterialInspector() { - MaterialDocumentNotificationBus::Handler::BusDisconnect(); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusDisconnect(); AtomToolsFramework::InspectorRequestBus::Handler::BusDisconnect(); } @@ -69,9 +67,9 @@ namespace MaterialEditor m_documentId = documentId; bool isOpen = false; - MaterialDocumentRequestBus::EventResult(isOpen, m_documentId, &MaterialDocumentRequestBus::Events::IsOpen); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(isOpen, m_documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::IsOpen); - MaterialDocumentRequestBus::EventResult(m_documentPath, m_documentId, &MaterialDocumentRequestBus::Events::GetAbsolutePath); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(m_documentPath, m_documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::GetAbsolutePath); if (!m_documentId.IsNull() && isOpen) { @@ -113,13 +111,13 @@ namespace MaterialEditor auto& group = m_groups[groupNameId]; AtomToolsFramework::DynamicProperty property; - MaterialDocumentRequestBus::EventResult( - property, m_documentId, &MaterialDocumentRequestBus::Events::GetProperty, AZ::Name("overview.materialType")); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult( + property, m_documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::GetProperty, AZ::Name("overview.materialType")); group.m_properties.push_back(property); property = {}; - MaterialDocumentRequestBus::EventResult( - property, m_documentId, &MaterialDocumentRequestBus::Events::GetProperty, AZ::Name("overview.parentMaterial")); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult( + property, m_documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::GetProperty, AZ::Name("overview.parentMaterial")); group.m_properties.push_back(property); // Passing in same group as main and comparison instance to enable custom value comparison for highlighting modified properties @@ -145,8 +143,8 @@ namespace MaterialEditor for (const auto& uvNamePair : uvNameMap) { AtomToolsFramework::DynamicProperty property; - MaterialDocumentRequestBus::EventResult( - property, m_documentId, &MaterialDocumentRequestBus::Events::GetProperty, + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult( + property, m_documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::GetProperty, AZ::RPI::MaterialPropertyId(groupNameId, uvNamePair.m_shaderInput.ToString()).GetFullName()); group.m_properties.push_back(property); @@ -182,8 +180,8 @@ namespace MaterialEditor for (const auto& propertyDefinition : propertyListItr->second) { AtomToolsFramework::DynamicProperty property; - MaterialDocumentRequestBus::EventResult( - property, m_documentId, &MaterialDocumentRequestBus::Events::GetProperty, + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult( + property, m_documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::GetProperty, AZ::RPI::MaterialPropertyId(groupNameId, propertyDefinition.m_nameId).GetFullName()); group.m_properties.push_back(property); } @@ -196,8 +194,8 @@ namespace MaterialEditor AddGroup(groupNameId, groupDisplayName, groupDescription, propertyGroupWidget); bool isGroupVisible = false; - MaterialDocumentRequestBus::EventResult( - isGroupVisible, m_documentId, &MaterialDocumentRequestBus::Events::IsPropertyGroupVisible, AZ::Name{groupNameId}); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult( + isGroupVisible, m_documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::IsPropertyGroupVisible, AZ::Name{groupNameId}); SetGroupVisible(groupNameId, isGroupVisible); } } @@ -264,7 +262,7 @@ namespace MaterialEditor if (m_activeProperty != property) { m_activeProperty = property; - MaterialDocumentRequestBus::Event(m_documentId, &MaterialDocumentRequestBus::Events::BeginEdit); + AtomToolsFramework::AtomToolsDocumentRequestBus::Event(m_documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::BeginEdit); } } } @@ -276,8 +274,8 @@ namespace MaterialEditor { if (m_activeProperty == property) { - MaterialDocumentRequestBus::Event( - m_documentId, &MaterialDocumentRequestBus::Events::SetPropertyValue, property->GetId(), property->GetValue()); + AtomToolsFramework::AtomToolsDocumentRequestBus::Event( + m_documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::SetPropertyValue, property->GetId(), property->GetValue()); } } } @@ -292,10 +290,10 @@ namespace MaterialEditor { if (m_activeProperty == property) { - MaterialDocumentRequestBus::Event( - m_documentId, &MaterialDocumentRequestBus::Events::SetPropertyValue, property->GetId(), property->GetValue()); + AtomToolsFramework::AtomToolsDocumentRequestBus::Event( + m_documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::SetPropertyValue, property->GetId(), property->GetValue()); - MaterialDocumentRequestBus::Event(m_documentId, &MaterialDocumentRequestBus::Events::EndEdit); + AtomToolsFramework::AtomToolsDocumentRequestBus::Event(m_documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::EndEdit); m_activeProperty = nullptr; } } diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialInspector/MaterialInspector.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialInspector/MaterialInspector.h index ccef72ea3f..845a8cb0f7 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialInspector/MaterialInspector.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialInspector/MaterialInspector.h @@ -9,14 +9,12 @@ #pragma once #if !defined(Q_MOC_RUN) -#include -#include - +#include +#include #include #include - -#include -#include +#include +#include #endif namespace MaterialEditor @@ -25,7 +23,7 @@ namespace MaterialEditor //! The settings can be divided into cards, with each one showing a subset of properties. class MaterialInspector : public AtomToolsFramework::InspectorWidget - , public MaterialDocumentNotificationBus::Handler + , public AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler , public AzToolsFramework::IPropertyEditorNotify { Q_OBJECT @@ -52,7 +50,7 @@ namespace MaterialEditor void AddUvNamesGroup(); void AddPropertiesGroup(); - // MaterialDocumentNotificationBus::Handler implementation + // AtomToolsDocumentNotificationBus::Handler implementation void OnDocumentOpened(const AZ::Uuid& documentId) override; void OnDocumentPropertyValueModified(const AZ::Uuid& documentId, const AtomToolsFramework::DynamicProperty& property) override; void OnDocumentPropertyConfigModified(const AZ::Uuid& documentId, const AtomToolsFramework::DynamicProperty& property) override; diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/SettingsDialog/SettingsWidget.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/SettingsDialog/SettingsWidget.cpp index 22a85d84a7..e8254edb28 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/SettingsDialog/SettingsWidget.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/SettingsDialog/SettingsWidget.cpp @@ -15,7 +15,9 @@ namespace MaterialEditor : AtomToolsFramework::InspectorWidget(parent) { m_documentSettings = - AZ::UserSettings::CreateFind(AZ::Crc32("MaterialDocumentSettings"), AZ::UserSettings::CT_GLOBAL); + AZ::UserSettings::CreateFind(AZ_CRC_CE("MaterialDocumentSettings"), AZ::UserSettings::CT_GLOBAL); + m_documentSystemSettings = AZ::UserSettings::CreateFind( + AZ_CRC_CE("AtomToolsDocumentSystemSettings"), AZ::UserSettings::CT_GLOBAL); } SettingsWidget::~SettingsWidget() @@ -26,23 +28,36 @@ namespace MaterialEditor void SettingsWidget::Populate() { AddGroupsBegin(); - AddDocumentGroup(); + AddDocumentSystemSettingsGroup(); + AddDocumentSettingsGroup(); AddGroupsEnd(); } - void SettingsWidget::AddDocumentGroup() + void SettingsWidget::AddDocumentSettingsGroup() { const AZStd::string groupNameId = "documentSettings"; const AZStd::string groupDisplayName = "Document Settings"; const AZStd::string groupDescription = "Document Settings"; - const AZ::Crc32 saveStateKey(AZStd::string::format("SettingsWidget::DocumentGroup")); + const AZ::Crc32 saveStateKey(AZStd::string::format("SettingsWidget::DocumentSettingsGroup")); AddGroup( groupNameId, groupDisplayName, groupDescription, new AtomToolsFramework::InspectorPropertyGroupWidget( m_documentSettings.get(), nullptr, m_documentSettings->TYPEINFO_Uuid(), this, this, saveStateKey)); } + void SettingsWidget::AddDocumentSystemSettingsGroup() + { + const AZStd::string groupNameId = "documentSystemSettings"; + const AZStd::string groupDisplayName = "Document System Settings"; + const AZStd::string groupDescription = "Document System Settings"; + + const AZ::Crc32 saveStateKey(AZStd::string::format("SettingsWidget::DocumentSystemSettingsGroup")); AddGroup( + groupNameId, groupDisplayName, groupDescription, + new AtomToolsFramework::InspectorPropertyGroupWidget( + m_documentSystemSettings.get(), nullptr, m_documentSystemSettings->TYPEINFO_Uuid(), this, this, saveStateKey)); + } + void SettingsWidget::Reset() { AtomToolsFramework::InspectorRequestBus::Handler::BusDisconnect(); diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/SettingsDialog/SettingsWidget.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/SettingsDialog/SettingsWidget.h index 56fc7fbebb..fea98eeda1 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/SettingsDialog/SettingsWidget.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/SettingsDialog/SettingsWidget.h @@ -10,6 +10,7 @@ #if !defined(Q_MOC_RUN) #include +#include #include #include #endif @@ -31,7 +32,8 @@ namespace MaterialEditor void Populate(); private: - void AddDocumentGroup(); + void AddDocumentSettingsGroup(); + void AddDocumentSystemSettingsGroup(); // AtomToolsFramework::InspectorRequestBus::Handler overrides... void Reset() override; @@ -46,5 +48,6 @@ namespace MaterialEditor void PropertySelectionChanged(AzToolsFramework::InstanceDataNode*, bool) override {} AZStd::intrusive_ptr m_documentSettings; + AZStd::intrusive_ptr m_documentSystemSettings; }; } // namespace MaterialEditor diff --git a/Gems/Atom/Tools/MaterialEditor/Code/materialeditordocument_files.cmake b/Gems/Atom/Tools/MaterialEditor/Code/materialeditordocument_files.cmake index 0c657361f1..d86dd03749 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/materialeditordocument_files.cmake +++ b/Gems/Atom/Tools/MaterialEditor/Code/materialeditordocument_files.cmake @@ -8,8 +8,6 @@ set(FILES Include/Atom/Document/MaterialDocumentModule.h - Include/Atom/Document/MaterialDocumentSystemRequestBus.h - Include/Atom/Document/MaterialDocumentNotificationBus.h Include/Atom/Document/MaterialDocumentRequestBus.h Include/Atom/Document/MaterialDocumentSettings.h Source/Document/MaterialDocumentModule.cpp diff --git a/Gems/Atom/Tools/MaterialEditor/Scripts/GenerateAllMaterialScreenshots.py b/Gems/Atom/Tools/MaterialEditor/Scripts/GenerateAllMaterialScreenshots.py index 2116a3de6c..6708553e20 100755 --- a/Gems/Atom/Tools/MaterialEditor/Scripts/GenerateAllMaterialScreenshots.py +++ b/Gems/Atom/Tools/MaterialEditor/Scripts/GenerateAllMaterialScreenshots.py @@ -93,11 +93,11 @@ def ToRadians(degrees): return 3.14159 * degrees / 180.0; def OpenMaterial(filename): - documentId = azlmbr.materialeditor.MaterialDocumentSystemRequestBus(azlmbr.bus.Broadcast, 'OpenDocument', os.path.join(g_materialTestFolder, filename)) + documentId = azlmbr.atomtools.AtomToolsDocumentSystemRequestBus(azlmbr.bus.Broadcast, 'OpenDocument', os.path.join(g_materialTestFolder, filename)) return documentId def CloseMaterial(documentId): - azlmbr.materialeditor.MaterialDocumentSystemRequestBus(azlmbr.bus.Broadcast, 'CloseDocument', documentId) + azlmbr.atomtools.AtomToolsDocumentSystemRequestBus(azlmbr.bus.Broadcast, 'CloseDocument', documentId) def SelectLightingPreset(presetName): azlmbr.materialeditor.MaterialViewportRequestBus(azlmbr.bus.Broadcast, 'SelectLightingPresetByName', presetName) diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Include/Atom/Document/ShaderManagementConsoleDocumentRequestBus.h b/Gems/Atom/Tools/ShaderManagementConsole/Code/Include/Atom/Document/ShaderManagementConsoleDocumentRequestBus.h index ed002f65ed..d0e6aea5b9 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Include/Atom/Document/ShaderManagementConsoleDocumentRequestBus.h +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Include/Atom/Document/ShaderManagementConsoleDocumentRequestBus.h @@ -7,14 +7,10 @@ */ #pragma once -#include -#include -#include -#include - -#include #include #include +#include +#include namespace ShaderManagementConsole { @@ -27,12 +23,6 @@ namespace ShaderManagementConsole static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById; typedef AZ::Uuid BusIdType; - //! Get absolute path of document - virtual AZStd::string_view GetAbsolutePath() const = 0; - - //! Get relative path of document - virtual AZStd::string_view GetRelativePath() const = 0; - //! Get the number of options virtual size_t GetShaderOptionCount() const = 0; @@ -44,47 +34,6 @@ namespace ShaderManagementConsole //! Get the information for the shader variant at the specified index virtual const AZ::RPI::ShaderVariantListSourceData::VariantInfo& GetShaderVariantInfo(size_t index) const = 0; - - //! Load document and related data - //! @param loadPath Absolute path of document to load - virtual bool Open(AZStd::string_view loadPath) = 0; - - //! Save document to file - virtual bool Save() = 0; - - //! Save document copy - //! @param savePath Absolute path where document is saved - virtual bool SaveAsCopy(AZStd::string_view savePath) = 0; - - //! Close document and reset its data - virtual bool Close() = 0; - - //! document is loaded - virtual bool IsOpen() const = 0; - - //! document has changes pending - virtual bool IsModified() const = 0; - - //! Can the document be saved - virtual bool IsSavable() const = 0; - - //! Returns true if there are reversible modifications to the document - virtual bool CanUndo() const = 0; - - //! Returns true if there are changes that were reversed and can be re-applied to the document - virtual bool CanRedo() const = 0; - - //! Restores the previous state of the document - virtual bool Undo() = 0; - - //! Restores the next state of the document - virtual bool Redo() = 0; - - //! Signal that editing is about to begin, like beginning to drag a slider control - virtual bool BeginEdit() = 0; - - //! Signal that editing has completed, like after releasing the mouse button after continuously dragging a slider control - virtual bool EndEdit() = 0; }; using ShaderManagementConsoleDocumentRequestBus = AZ::EBus; diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Include/Atom/Document/ShaderManagementConsoleDocumentSystemRequestBus.h b/Gems/Atom/Tools/ShaderManagementConsole/Code/Include/Atom/Document/ShaderManagementConsoleDocumentSystemRequestBus.h deleted file mode 100644 index 93c46f442f..0000000000 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Include/Atom/Document/ShaderManagementConsoleDocumentSystemRequestBus.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -#pragma once - -#include - -namespace ShaderManagementConsole -{ - //! ShaderManagementConsoleDocumentSystemRequestBus provides high level file requests for menus, scripts, etc. - class ShaderManagementConsoleDocumentSystemRequests - : public AZ::EBusTraits - { - public: - static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single; - static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; - - //! Create a document object - //! @return Uuid of new document, or null Uuid if failed - virtual AZ::Uuid CreateDocument() = 0; - - //! Destroy a document object with the specified id - //! @return true if Uuid was found and removed, otherwise false - virtual bool DestroyDocument(const AZ::Uuid& documentId) = 0; - - //! Open a document for editing - //! @param sourcePath document to open. - //! @return unique id of new document if successful, otherwise null Uuid - virtual AZ::Uuid OpenDocument(AZStd::string_view sourcePath) = 0; - - //! Close the specified document - //! @param documentId unique id of document to close - virtual bool CloseDocument(const AZ::Uuid& documentId) = 0; - - //! Close all documents - virtual bool CloseAllDocuments() = 0; - - //! Close all documents except for documentId - //! @param documentId unique id of document to not close - virtual bool CloseAllDocumentsExcept(const AZ::Uuid& documentId) = 0; - - //! Save the specified document - //! @param documentId unique id of document to save - virtual bool SaveDocument(const AZ::Uuid& documentId) = 0; - - //! Save the specified document to a different file - //! @param documentId unique id of document to save - //! @param targetPath location where document is saved. - virtual bool SaveDocumentAsCopy(const AZ::Uuid& documentId, AZStd::string_view targetPath) = 0; - - //! Save all documents - virtual bool SaveAllDocuments() = 0; - }; - - using ShaderManagementConsoleDocumentSystemRequestBus = AZ::EBus; - -} // namespace ShaderManagementConsole diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocument.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocument.cpp index 9dae9c10cc..9a836c5c05 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocument.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocument.cpp @@ -8,49 +8,32 @@ #include #include - -#include -#include - +#include #include #include #include +#include namespace ShaderManagementConsole { ShaderManagementConsoleDocument::ShaderManagementConsoleDocument() + : AtomToolsFramework::AtomToolsDocument() { ShaderManagementConsoleDocumentRequestBus::Handler::BusConnect(m_id); - ShaderManagementConsoleDocumentNotificationBus::Broadcast(&ShaderManagementConsoleDocumentNotificationBus::Events::OnDocumentCreated, m_id); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentCreated, m_id); } ShaderManagementConsoleDocument::~ShaderManagementConsoleDocument() { - ShaderManagementConsoleDocumentNotificationBus::Broadcast(&ShaderManagementConsoleDocumentNotificationBus::Events::OnDocumentDestroyed, m_id); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentDestroyed, m_id); ShaderManagementConsoleDocumentRequestBus::Handler::BusDisconnect(); Clear(); } - const AZ::Uuid& ShaderManagementConsoleDocument::GetId() const - { - return m_id; - } - - AZStd::string_view ShaderManagementConsoleDocument::GetAbsolutePath() const - { - return m_absolutePath; - } - - AZStd::string_view ShaderManagementConsoleDocument::GetRelativePath() const - { - return m_relativePath; - } - size_t ShaderManagementConsoleDocument::GetShaderOptionCount() const { auto layout = m_shaderAsset->GetShaderOptionGroupLayout(); auto& shaderOptionDescriptors = layout->GetShaderOptions(); - return shaderOptionDescriptors.size(); } @@ -58,7 +41,6 @@ namespace ShaderManagementConsole { auto layout = m_shaderAsset->GetShaderOptionGroupLayout(); auto& shaderOptionDescriptors = layout->GetShaderOptions(); - return shaderOptionDescriptors[index]; } @@ -128,75 +110,12 @@ namespace ShaderManagementConsole return false; } - ShaderManagementConsoleDocumentNotificationBus::Broadcast(&ShaderManagementConsoleDocumentNotificationBus::Events::OnDocumentOpened, m_id); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentOpened, m_id); AZ_TracePrintf("ShaderManagementConsoleDocument", "Document loaded: '%s'", m_absolutePath.c_str()); return true; } - bool ShaderManagementConsoleDocument::Save() - { - if (!IsOpen()) - { - AZ_Error("ShaderManagementConsoleDocument", false, "Document is not open to be saved: '%s'.", m_absolutePath.c_str()); - return false; - } - - if (!IsSavable()) - { - AZ_Error("ShaderManagementConsoleDocument", false, "Document can not be saved: '%s'.", m_absolutePath.c_str()); - return false; - } - - AZ_Error("ShaderManagementConsoleDocument", false, "%s is not implemented!", __FUNCTION__); - return false; - - // Auto add or checkout saved file - //AzToolsFramework::SourceControlCommandBus::Broadcast(&AzToolsFramework::SourceControlCommandBus::Events::RequestEdit, - // m_absolutePath.c_str(), true, - // [](bool, const AzToolsFramework::SourceControlFileInfo&) {}); - - //ShaderManagementConsoleDocumentNotificationBus::Broadcast(&ShaderManagementConsoleDocumentNotificationBus::Events::OnDocumentSaved, m_id); - - //AZ_TracePrintf("ShaderManagementConsoleDocument", "Document saved: %s", m_absolutePath.data()); - //return true; - } - - bool ShaderManagementConsoleDocument::SaveAsCopy(AZStd::string_view savePath) - { - if (!IsOpen()) - { - AZ_Error("ShaderManagementConsoleDocument", false, "Document is not open to be saved: '%s'.", m_absolutePath.c_str()); - return false; - } - - if (!IsSavable()) - { - AZ_Error("ShaderManagementConsoleDocument", false, "Document can not be saved: '%s'.", m_absolutePath.c_str()); - return false; - } - - AZStd::string normalizedSavePath = savePath; - if (!AzFramework::StringFunc::Path::Normalize(normalizedSavePath)) - { - AZ_Error("ShaderManagementConsoleDocument", false, "Document save path could not be normalized: '%s'.", normalizedSavePath.c_str()); - return false; - } - - AZ_Error("ShaderManagementConsoleDocument", false, "%s is not implemented!", __FUNCTION__); - return false; - - // Auto add or checkout saved file - //AzToolsFramework::SourceControlCommandBus::Broadcast(&AzToolsFramework::SourceControlCommandBus::Events::RequestEdit, - // normalizedSavePath.c_str(), true, - // [](bool, const AzToolsFramework::SourceControlFileInfo&) {}); - - //ShaderManagementConsoleDocumentNotificationBus::Broadcast(&ShaderManagementConsoleDocumentNotificationBus::Events::OnDocumentSaved, m_id); - - //AZ_TracePrintf("ShaderManagementConsoleDocument", "Document saved: %s", normalizedSavePath.c_str()); - //return true; - } - bool ShaderManagementConsoleDocument::Close() { if (!IsOpen()) @@ -206,7 +125,7 @@ namespace ShaderManagementConsole } Clear(); - ShaderManagementConsoleDocumentNotificationBus::Broadcast(&ShaderManagementConsoleDocumentNotificationBus::Events::OnDocumentClosed, m_id); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentClosed, m_id); AZ_TracePrintf("ShaderManagementConsoleDocument", "Document was closed"); return true; } @@ -216,81 +135,11 @@ namespace ShaderManagementConsole return !m_absolutePath.empty() && !m_relativePath.empty(); } - bool ShaderManagementConsoleDocument::IsModified() const - { - return false; - } - - bool ShaderManagementConsoleDocument::IsSavable() const - { - return true; - } - - bool ShaderManagementConsoleDocument::CanUndo() const - { - // Undo will only be allowed if something has been recorded and we're not at the beginning of history - return IsOpen() && !m_undoHistory.empty() && m_undoHistoryIndex > 0; - } - - bool ShaderManagementConsoleDocument::CanRedo() const - { - // Redo will only be allowed if something has been recorded and we're not at the end of history - return IsOpen() && !m_undoHistory.empty() && m_undoHistoryIndex < m_undoHistory.size(); - } - - bool ShaderManagementConsoleDocument::Undo() - { - if (CanUndo()) - { - // The history index is one beyond the last executed command. Decrement the index then execute undo. - m_undoHistory[--m_undoHistoryIndex].first(); - ShaderManagementConsoleDocumentNotificationBus::Broadcast(&ShaderManagementConsoleDocumentNotificationBus::Events::OnDocumentUndoStateChanged, m_id); - return true; - } - return false; - } - - bool ShaderManagementConsoleDocument::Redo() - { - if (CanRedo()) - { - // Execute the current redo command then move the history index to the next position. - m_undoHistory[m_undoHistoryIndex++].second(); - ShaderManagementConsoleDocumentNotificationBus::Broadcast(&ShaderManagementConsoleDocumentNotificationBus::Events::OnDocumentUndoStateChanged, m_id); - return true; - } - return false; - } - - bool ShaderManagementConsoleDocument::BeginEdit() - { - return true; - } - - bool ShaderManagementConsoleDocument::EndEdit() - { - // Wipe any state beyond the current history index - m_undoHistory.erase(m_undoHistory.begin() + m_undoHistoryIndex, m_undoHistory.end()); - - // Add undo and redo operations using lambdas that will capture property state and restore it when executed - m_undoHistory.emplace_back( - [this]() { /**/ }, - [this]() { /**/ }); - - // Assign the index to the end of history - m_undoHistoryIndex = aznumeric_cast(m_undoHistory.size()); - ShaderManagementConsoleDocumentNotificationBus::Broadcast(&ShaderManagementConsoleDocumentNotificationBus::Events::OnDocumentUndoStateChanged, m_id); - - return true; - } - void ShaderManagementConsoleDocument::Clear() { m_absolutePath.clear(); m_relativePath.clear(); m_shaderVariantListSourceData = {}; m_shaderAsset = {}; - m_undoHistory = {}; - m_undoHistoryIndex = {}; } } // namespace ShaderManagementConsole diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocument.h b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocument.h index 3d1a88c62e..eb7d6b87a0 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocument.h +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocument.h @@ -7,13 +7,12 @@ */ #pragma once -#include -#include - -#include -#include - #include +#include +#include +#include +#include +#include namespace ShaderManagementConsole { @@ -21,7 +20,8 @@ namespace ShaderManagementConsole * ShaderManagementConsoleDocument provides an API for modifying and saving document properties. */ class ShaderManagementConsoleDocument - : public ShaderManagementConsoleDocumentRequestBus::Handler + : public AtomToolsFramework::AtomToolsDocument + , public ShaderManagementConsoleDocumentRequestBus::Handler { public: AZ_RTTI(ShaderManagementConsoleDocument, "{DBA269AE-892B-415C-8FA1-166B94B0E045}"); @@ -31,29 +31,20 @@ namespace ShaderManagementConsole ShaderManagementConsoleDocument(); virtual ~ShaderManagementConsoleDocument(); - const AZ::Uuid& GetId() const; + //////////////////////////////////////////////////////////////////////// + // AtomToolsFramework::AtomToolsDocument + //////////////////////////////////////////////////////////////////////// + bool Open(AZStd::string_view loadPath) override; + bool Close() override; + bool IsOpen() const override; + //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// // ShaderManagementConsoleDocumentRequestBus::Handler implementation - AZStd::string_view GetAbsolutePath() const override; - AZStd::string_view GetRelativePath() const override; size_t GetShaderOptionCount() const override; const AZ::RPI::ShaderOptionDescriptor& GetShaderOptionDescriptor(size_t index) const override; size_t GetShaderVariantCount() const override; const AZ::RPI::ShaderVariantListSourceData::VariantInfo& GetShaderVariantInfo(size_t index) const override; - bool Open(AZStd::string_view loadPath) override; - bool Save() override; - bool SaveAsCopy(AZStd::string_view savePath) override; - bool Close() override; - bool IsOpen() const override; - bool IsModified() const override; - bool IsSavable() const override; - bool CanUndo() const override; - bool CanRedo() const override; - bool Undo() override; - bool Redo() override; - bool BeginEdit() override; - bool EndEdit() override; //////////////////////////////////////////////////////////////////////// private: @@ -67,28 +58,11 @@ namespace ShaderManagementConsole using UndoRedoHistory = AZStd::vector; void Clear(); - - // Unique id of this document - AZ::Uuid m_id = AZ::Uuid::CreateRandom(); - - // Relative path to the document - AZStd::string m_relativePath; - - // Absolute path to the document - AZStd::string m_absolutePath; // Source data for shader variant list AZ::RPI::ShaderVariantListSourceData m_shaderVariantListSourceData; // Shader asset for the corresponding shader variant list AZ::Data::Asset m_shaderAsset; - - // Variables needed for tracking the undo and redo state of this document - - // Container of undo commands - UndoRedoHistory m_undoHistory; - - // The current position in the undo redo history - int m_undoHistoryIndex = 0; }; } // namespace ShaderManagementConsole diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocumentModule.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocumentModule.cpp index 4987b0528f..a9415fd85b 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocumentModule.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocumentModule.cpp @@ -7,10 +7,8 @@ */ #include -#include - -#include #include +#include namespace ShaderManagementConsole { diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocumentSystemComponent.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocumentSystemComponent.cpp index f06aae29d7..55b800067a 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocumentSystemComponent.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocumentSystemComponent.cpp @@ -6,41 +6,16 @@ * */ -#include - -#include -#include +#include +#include #include #include #include - -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT -#include -#include -#include -#include -AZ_POP_DISABLE_WARNING +#include +#include namespace ShaderManagementConsole { - ShaderManagementConsoleDocumentSystemComponent::ShaderManagementConsoleDocumentSystemComponent() - { - } - void ShaderManagementConsoleDocumentSystemComponent::Reflect(AZ::ReflectContext* context) { if (AZ::SerializeContext* serialize = azrtti_cast(context)) @@ -52,7 +27,7 @@ namespace ShaderManagementConsole { ec->Class("ShaderManagementConsoleDocumentSystemComponent", "Manages documents") ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("System", 0xc94d118b)) + ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC_CE("System")) ->Attribute(AZ::Edit::Attributes::AutoExpand, true) ; } @@ -60,64 +35,35 @@ namespace ShaderManagementConsole if (AZ::BehaviorContext* behaviorContext = azrtti_cast(context)) { - behaviorContext->EBus("ShaderManagementConsoleDocumentSystemRequestBus") - ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) - ->Attribute(AZ::Script::Attributes::Category, "Editor") - ->Attribute(AZ::Script::Attributes::Module, "shadermanagementconsole") - ->Event("CreateDocument", &ShaderManagementConsoleDocumentSystemRequestBus::Events::CreateDocument) - ->Event("DestroyDocument", &ShaderManagementConsoleDocumentSystemRequestBus::Events::DestroyDocument) - ->Event("OpenDocument", &ShaderManagementConsoleDocumentSystemRequestBus::Events::OpenDocument) - ->Event("CloseDocument", &ShaderManagementConsoleDocumentSystemRequestBus::Events::CloseDocument) - ->Event("CloseAllDocuments", &ShaderManagementConsoleDocumentSystemRequestBus::Events::CloseAllDocuments) - ->Event("CloseAllDocumentsExcept", &ShaderManagementConsoleDocumentSystemRequestBus::Events::CloseAllDocumentsExcept) - ->Event("SaveDocument", &ShaderManagementConsoleDocumentSystemRequestBus::Events::SaveDocument) - ->Event("SaveDocumentAsCopy", &ShaderManagementConsoleDocumentSystemRequestBus::Events::SaveDocumentAsCopy) - ->Event("SaveAllDocuments", &ShaderManagementConsoleDocumentSystemRequestBus::Events::SaveAllDocuments) - ; - behaviorContext->EBus("ShaderManagementConsoleDocumentRequestBus") ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) ->Attribute(AZ::Script::Attributes::Category, "Editor") ->Attribute(AZ::Script::Attributes::Module, "shadermanagementconsole") - ->Event("GetAbsolutePath", &ShaderManagementConsoleDocumentRequestBus::Events::GetAbsolutePath) - ->Event("GetRelativePath", &ShaderManagementConsoleDocumentRequestBus::Events::GetRelativePath) ->Event("GetShaderOptionCount", &ShaderManagementConsoleDocumentRequestBus::Events::GetShaderOptionCount) ->Event("GetShaderOptionDescriptor", &ShaderManagementConsoleDocumentRequestBus::Events::GetShaderOptionDescriptor) ->Event("GetShaderVariantCount", &ShaderManagementConsoleDocumentRequestBus::Events::GetShaderVariantCount) ->Event("GetShaderVariantInfo", &ShaderManagementConsoleDocumentRequestBus::Events::GetShaderVariantInfo) - ->Event("Open", &ShaderManagementConsoleDocumentRequestBus::Events::Open) - ->Event("Close", &ShaderManagementConsoleDocumentRequestBus::Events::Close) - ->Event("Save", &ShaderManagementConsoleDocumentRequestBus::Events::Save) - ->Event("SaveAsCopy", &ShaderManagementConsoleDocumentRequestBus::Events::SaveAsCopy) - ->Event("IsOpen", &ShaderManagementConsoleDocumentRequestBus::Events::IsOpen) - ->Event("IsModified", &ShaderManagementConsoleDocumentRequestBus::Events::IsModified) - ->Event("IsSavable", &ShaderManagementConsoleDocumentRequestBus::Events::IsSavable) - ->Event("CanUndo", &ShaderManagementConsoleDocumentRequestBus::Events::CanUndo) - ->Event("CanRedo", &ShaderManagementConsoleDocumentRequestBus::Events::CanRedo) - ->Event("Undo", &ShaderManagementConsoleDocumentRequestBus::Events::Undo) - ->Event("Redo", &ShaderManagementConsoleDocumentRequestBus::Events::Redo) - ->Event("BeginEdit", &ShaderManagementConsoleDocumentRequestBus::Events::BeginEdit) - ->Event("EndEdit", &ShaderManagementConsoleDocumentRequestBus::Events::EndEdit) ; } } void ShaderManagementConsoleDocumentSystemComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) { - required.push_back(AZ_CRC("AssetProcessorToolsConnection", 0x734669bc)); - required.push_back(AZ_CRC("AssetDatabaseService", 0x3abf5601)); - required.push_back(AZ_CRC("PropertyManagerService", 0x63a3d7ad)); - required.push_back(AZ_CRC("RPISystem", 0xf2add773)); + required.push_back(AZ_CRC_CE("AtomToolsDocumentSystemService")); + required.push_back(AZ_CRC_CE("AssetProcessorToolsConnection")); + required.push_back(AZ_CRC_CE("AssetDatabaseService")); + required.push_back(AZ_CRC_CE("PropertyManagerService")); + required.push_back(AZ_CRC_CE("RPISystem")); } void ShaderManagementConsoleDocumentSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) { - provided.push_back(AZ_CRC("ShaderManagementConsoleDocumentSystemService")); + provided.push_back(AZ_CRC_CE("ShaderManagementConsoleDocumentSystemService")); } void ShaderManagementConsoleDocumentSystemComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) { - incompatible.push_back(AZ_CRC("ShaderManagementConsoleDocumentSystemService")); + incompatible.push_back(AZ_CRC_CE("ShaderManagementConsoleDocumentSystemService")); } void ShaderManagementConsoleDocumentSystemComponent::Init() @@ -126,256 +72,15 @@ namespace ShaderManagementConsole void ShaderManagementConsoleDocumentSystemComponent::Activate() { - m_documentMap.clear(); - ShaderManagementConsoleDocumentSystemRequestBus::Handler::BusConnect(); + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast( + &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Handler::RegisterDocumentType, + []() + { + return aznew ShaderManagementConsoleDocument(); + }); } void ShaderManagementConsoleDocumentSystemComponent::Deactivate() { - ShaderManagementConsoleDocumentSystemRequestBus::Handler::BusDisconnect(); - m_documentMap.clear(); - } - - AZ::Uuid ShaderManagementConsoleDocumentSystemComponent::CreateDocument() - { - auto document = AZStd::make_unique(); - if (!document) - { - AZ_Error("ShaderManagementConsoleDocument", false, "Failed to create new document"); - return AZ::Uuid::CreateNull(); - } - - AZ::Uuid documentId = document->GetId(); - m_documentMap.emplace(documentId, document.release()); - return documentId; - } - - bool ShaderManagementConsoleDocumentSystemComponent::DestroyDocument(const AZ::Uuid& documentId) - { - return m_documentMap.erase(documentId) != 0; - } - - AZ::Uuid ShaderManagementConsoleDocumentSystemComponent::OpenDocument(AZStd::string_view sourcePath) - { - return OpenDocumentImpl(sourcePath, true); - } - - bool ShaderManagementConsoleDocumentSystemComponent::CloseDocument(const AZ::Uuid& documentId) - { - bool isOpen = false; - ShaderManagementConsoleDocumentRequestBus::EventResult(isOpen, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::IsOpen); - if (!isOpen) - { - // immediately destroy unopened documents - ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::DestroyDocument, documentId); - return true; - } - - AZStd::string documentPath; - ShaderManagementConsoleDocumentRequestBus::EventResult(documentPath, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::GetAbsolutePath); - - bool isModified = false; - ShaderManagementConsoleDocumentRequestBus::EventResult(isModified, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::IsModified); - if (isModified) - { - auto selection = QMessageBox::question(QApplication::activeWindow(), - QString("Document has unsaved changes"), - QString("Do you want to save changes to\n%1?").arg(documentPath.c_str()), - QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); - if (selection == QMessageBox::Cancel) - { - AZ_TracePrintf("ShaderManagementConsoleDocument", "Close document canceled: %s", documentPath.c_str()); - return false; - } - if (selection == QMessageBox::Yes) - { - if (!SaveDocument(documentId)) - { - AZ_Error("ShaderManagementConsoleDocument", false, "Close document failed because document was not saved: %s", documentPath.c_str()); - return false; - } - } - } - - AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); - - bool closeResult = true; - ShaderManagementConsoleDocumentRequestBus::EventResult(closeResult, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::Close); - if (!closeResult) - { - QMessageBox::critical( - QApplication::activeWindow(), QString("Document could not be closed"), - QString("Failed to close: \n%1\n\n%2").arg(documentPath.c_str()).arg(traceRecorder.GetDump().c_str())); - return false; - } - - ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::DestroyDocument, documentId); - return true; - } - - bool ShaderManagementConsoleDocumentSystemComponent::CloseAllDocuments() - { - bool result = true; - auto documentMap = m_documentMap; - for (const auto& documentPair : documentMap) - { - if (!CloseDocument(documentPair.first)) - { - result = false; - } - } - - return result; - } - - bool ShaderManagementConsoleDocumentSystemComponent::CloseAllDocumentsExcept(const AZ::Uuid& documentId) - { - bool result = true; - auto documentMap = m_documentMap; - for (const auto& documentPair : documentMap) - { - if (documentPair.first != documentId) - { - if (!CloseDocument(documentPair.first)) - { - result = false; - } - } - } - - return result; - } - - bool ShaderManagementConsoleDocumentSystemComponent::SaveDocument(const AZ::Uuid& documentId) - { - AZStd::string saveDocumentPath; - ShaderManagementConsoleDocumentRequestBus::EventResult(saveDocumentPath, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::GetAbsolutePath); - - if (saveDocumentPath.empty() || !AzFramework::StringFunc::Path::Normalize(saveDocumentPath)) - { - return false; - } - - const QFileInfo saveInfo(saveDocumentPath.c_str()); - if (saveInfo.exists() && !saveInfo.isWritable()) - { - QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Document could not be overwritten:\n%1").arg(saveDocumentPath.c_str())); - return false; - } - - AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); - - bool result = false; - ShaderManagementConsoleDocumentRequestBus::EventResult(result, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::Save); - if (!result) - { - QMessageBox::critical( - QApplication::activeWindow(), QString("Document could not be saved"), - QString("Failed to save: \n%1\n\n%2").arg(saveDocumentPath.c_str()).arg(traceRecorder.GetDump().c_str())); - return false; - } - - return true; - } - - bool ShaderManagementConsoleDocumentSystemComponent::SaveDocumentAsCopy(const AZ::Uuid& documentId, AZStd::string_view targetPath) - { - AZStd::string saveDocumentPath = targetPath; - if (saveDocumentPath.empty() || !AzFramework::StringFunc::Path::Normalize(saveDocumentPath)) - { - return false; - } - - const QFileInfo saveInfo(saveDocumentPath.c_str()); - if (saveInfo.exists() && !saveInfo.isWritable()) - { - QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Document could not be overwritten:\n%1").arg(saveDocumentPath.c_str())); - return false; - } - - AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); - - bool result = false; - ShaderManagementConsoleDocumentRequestBus::EventResult(result, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::SaveAsCopy, saveDocumentPath); - if (!result) - { - QMessageBox::critical( - QApplication::activeWindow(), QString("Document could not be saved"), - QString("Failed to save: \n%1\n\n%2").arg(saveDocumentPath.c_str()).arg(traceRecorder.GetDump().c_str())); - return false; - } - - return true; - } - - bool ShaderManagementConsoleDocumentSystemComponent::SaveAllDocuments() - { - bool result = true; - for (const auto& documentPair : m_documentMap) - { - if (!SaveDocument(documentPair.first)) - { - result = false; - } - } - - return result; - } - - AZ::Uuid ShaderManagementConsoleDocumentSystemComponent::OpenDocumentImpl(AZStd::string_view sourcePath, bool checkIfAlreadyOpen) - { - AZStd::string requestedPath = sourcePath; - if (requestedPath.empty()) - { - return AZ::Uuid::CreateNull(); - } - - if (!AzFramework::StringFunc::Path::Normalize(requestedPath)) - { - QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Document path is invalid:\n%1").arg(requestedPath.c_str())); - return AZ::Uuid::CreateNull(); - } - - // Determine if the file is already open and select it - if (checkIfAlreadyOpen) - { - for (const auto& documentPair : m_documentMap) - { - AZStd::string openDocumentPath; - ShaderManagementConsoleDocumentRequestBus::EventResult(openDocumentPath, documentPair.first, &ShaderManagementConsoleDocumentRequestBus::Events::GetAbsolutePath); - if (openDocumentPath == requestedPath) - { - ShaderManagementConsoleDocumentNotificationBus::Broadcast(&ShaderManagementConsoleDocumentNotificationBus::Events::OnDocumentOpened, documentPair.first); - return documentPair.first; - } - } - } - - AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); - - AZ::Uuid documentId = AZ::Uuid::CreateNull(); - ShaderManagementConsoleDocumentSystemRequestBus::BroadcastResult(documentId, &ShaderManagementConsoleDocumentSystemRequestBus::Events::CreateDocument); - if (documentId.IsNull()) - { - QMessageBox::critical( - QApplication::activeWindow(), QString("Document could not be created"), - QString("Failed to create: \n%1\n\n%2").arg(requestedPath.c_str()).arg(traceRecorder.GetDump().c_str())); - return AZ::Uuid::CreateNull(); - } - - traceRecorder.GetDump().clear(); - - bool openResult = false; - ShaderManagementConsoleDocumentRequestBus::EventResult(openResult, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::Open, requestedPath); - if (!openResult) - { - QMessageBox::critical( - QApplication::activeWindow(), QString("Document could not be opened"), - QString("Failed to open: \n%1\n\n%2").arg(requestedPath.c_str()).arg(traceRecorder.GetDump().c_str())); - ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::DestroyDocument, documentId); - return AZ::Uuid::CreateNull(); - } - - return documentId; } } diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocumentSystemComponent.h b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocumentSystemComponent.h index 05c61ce058..1ee825f6de 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocumentSystemComponent.h +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocumentSystemComponent.h @@ -9,28 +9,17 @@ #pragma once #include -#include - -#include -#include -#include - -AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT -#include -#include -AZ_POP_DISABLE_WARNING namespace ShaderManagementConsole { - //! ShaderManagementConsoleDocumentSystemComponent is the central component of the Shader Management Console Core gem + //! ShaderManagementConsoleDocumentSystemComponent class ShaderManagementConsoleDocumentSystemComponent : public AZ::Component - , private ShaderManagementConsoleDocumentSystemRequestBus::Handler { public: - AZ_COMPONENT(ShaderManagementConsoleDocumentSystemComponent, "{58ABE0AE-2710-41E2-ADFD-E2D67407427D}"); + AZ_COMPONENT(ShaderManagementConsoleDocumentSystemComponent, "{1610159D-59DC-48B1-B2D1-FCE7AFD3B012}"); - ShaderManagementConsoleDocumentSystemComponent(); + ShaderManagementConsoleDocumentSystemComponent() = default; ~ShaderManagementConsoleDocumentSystemComponent() = default; ShaderManagementConsoleDocumentSystemComponent(const ShaderManagementConsoleDocumentSystemComponent&) = delete; ShaderManagementConsoleDocumentSystemComponent& operator =(const ShaderManagementConsoleDocumentSystemComponent&) = delete; @@ -48,23 +37,5 @@ namespace ShaderManagementConsole void Activate() override; void Deactivate() override; //////////////////////////////////////////////////////////////////////// - - //////////////////////////////////////////////////////////////////////// - // ShaderManagementConsoleDocumentSystemRequestBus::Handler overrides... - AZ::Uuid CreateDocument() override; - bool DestroyDocument(const AZ::Uuid& documentId) override; - AZ::Uuid OpenDocument(AZStd::string_view sourcePath) override; - bool CloseDocument(const AZ::Uuid& documentId) override; - bool CloseAllDocuments() override; - bool CloseAllDocumentsExcept(const AZ::Uuid& documentId) override; - bool SaveDocument(const AZ::Uuid& documentId) override; - bool SaveDocumentAsCopy(const AZ::Uuid& documentId, AZStd::string_view targetPath) override; - bool SaveAllDocuments() override; - //////////////////////////////////////////////////////////////////////// - - AZ::Uuid OpenDocumentImpl(AZStd::string_view sourcePath, bool checkIfAlreadyOpen); - - AZStd::unordered_map> m_documentMap; - const size_t m_maxMessageBoxLineCount = 15; }; } diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp index 313522a256..3d07a0de15 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp @@ -7,8 +7,8 @@ */ #include -#include #include +#include #include #include #include @@ -66,8 +66,8 @@ namespace ShaderManagementConsole const AZStd::string openDocumentPath = commandLine.GetMiscValue(openDocumentIndex); AZ_Printf(GetBuildTargetName().c_str(), "Opening document: %s", openDocumentPath.c_str()); - ShaderManagementConsoleDocumentSystemRequestBus::Broadcast( - &ShaderManagementConsoleDocumentSystemRequestBus::Events::OpenDocument, openDocumentPath); + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast( + &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::OpenDocument, openDocumentPath); } Base::ProcessCommandLine(commandLine); diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h index 24b2020dad..6596429577 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h @@ -8,8 +8,8 @@ #pragma once -#include #include +#include namespace ShaderManagementConsole { diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleBrowserInteractions.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleBrowserInteractions.cpp index c0b9f5502c..b82d348df3 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleBrowserInteractions.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleBrowserInteractions.cpp @@ -6,28 +6,24 @@ * */ -#include -#include -#include -#include -#include -#include - -#include - +#include +#include +#include #include - +#include #include +#include #include #include -#include #include -#include +#include -#include -#include - -#include +#include +#include +#include +#include +#include +#include namespace ShaderManagementConsole { @@ -80,7 +76,7 @@ namespace ShaderManagementConsole { if (AzFramework::StringFunc::Path::IsExtension(entry->GetFullPath().c_str(), AZ::RPI::ShaderVariantListSourceData::Extension)) { - ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::OpenDocument, entry->GetFullPath().c_str()); + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::OpenDocument, entry->GetFullPath().c_str()); } else { diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleBrowserWidget.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleBrowserWidget.cpp index 588dccca1b..eb863a195a 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleBrowserWidget.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleBrowserWidget.cpp @@ -6,26 +6,21 @@ * */ -#include - -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include #include - -#include - -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT #include @@ -85,14 +80,14 @@ namespace ShaderManagementConsole }); AssetBrowserModelNotificationBus::Handler::BusConnect(); - ShaderManagementConsoleDocumentNotificationBus::Handler::BusConnect(); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusConnect(); } ShaderManagementConsoleBrowserWidget::~ShaderManagementConsoleBrowserWidget() { // Maintains the tree expansion state between runs m_ui->m_assetBrowserTreeViewWidget->SaveState(); - ShaderManagementConsoleDocumentNotificationBus::Handler::BusDisconnect(); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusDisconnect(); AssetBrowserModelNotificationBus::Handler::BusDisconnect(); } @@ -150,7 +145,7 @@ namespace ShaderManagementConsole { if (AzFramework::StringFunc::Path::IsExtension(sourceEntry->GetFullPath().c_str(), AZ::RPI::ShaderVariantListSourceData::Extension)) { - ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::OpenDocument, sourceEntry->GetFullPath()); + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::OpenDocument, sourceEntry->GetFullPath()); } else { @@ -192,7 +187,7 @@ namespace ShaderManagementConsole void ShaderManagementConsoleBrowserWidget::OnDocumentOpened(const AZ::Uuid& documentId) { AZStd::string absolutePath; - ShaderManagementConsoleDocumentRequestBus::EventResult(absolutePath, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::GetAbsolutePath); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(absolutePath, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::GetAbsolutePath); if (!absolutePath.empty()) { m_pathToSelect = absolutePath; @@ -203,4 +198,4 @@ namespace ShaderManagementConsole } // namespace ShaderManagementConsole -#include +#include diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleBrowserWidget.h b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleBrowserWidget.h index d251ab26f9..73a2a24aa9 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleBrowserWidget.h +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleBrowserWidget.h @@ -9,11 +9,10 @@ #pragma once #if !defined(Q_MOC_RUN) +#include #include -#include #include #include -#include AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT #include @@ -44,7 +43,7 @@ namespace ShaderManagementConsole class ShaderManagementConsoleBrowserWidget : public QWidget , public AzToolsFramework::AssetBrowser::AssetBrowserModelNotificationBus::Handler - , public ShaderManagementConsoleDocumentNotificationBus::Handler + , public AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler { Q_OBJECT public: @@ -64,7 +63,7 @@ namespace ShaderManagementConsole // AssetBrowserModelNotificationBus::Handler implementation void EntryAdded(const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry) override; - // ShaderManagementConsoleDocumentNotificationBus::Handler implementation + // AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler implementation void OnDocumentOpened(const AZ::Uuid& documentId) override; }; } // namespace ShaderManagementConsole diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp index 34487e0cb5..0b4802640b 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp @@ -13,12 +13,11 @@ #include #include #include - #include #include - #include -#include +#include +#include #include AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT @@ -62,19 +61,19 @@ namespace ShaderManagementConsole // Restore geometry and show the window mainWindowWrapper->showFromSettings(); - ShaderManagementConsoleDocumentNotificationBus::Handler::BusConnect(); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusConnect(); OnDocumentOpened(AZ::Uuid::CreateNull()); } ShaderManagementConsoleWindow::~ShaderManagementConsoleWindow() { - ShaderManagementConsoleDocumentNotificationBus::Handler::BusDisconnect(); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusDisconnect(); } void ShaderManagementConsoleWindow::closeEvent(QCloseEvent* closeEvent) { bool didClose = true; - ShaderManagementConsoleDocumentSystemRequestBus::BroadcastResult(didClose, &ShaderManagementConsoleDocumentSystemRequestBus::Events::CloseAllDocuments); + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::BroadcastResult(didClose, &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CloseAllDocuments); if (!didClose) { closeEvent->ignore(); @@ -88,17 +87,17 @@ namespace ShaderManagementConsole void ShaderManagementConsoleWindow::OnDocumentOpened(const AZ::Uuid& documentId) { bool isOpen = false; - ShaderManagementConsoleDocumentRequestBus::EventResult(isOpen, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::IsOpen); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(isOpen, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::IsOpen); bool isSavable = false; - ShaderManagementConsoleDocumentRequestBus::EventResult(isSavable, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::IsSavable); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(isSavable, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::IsSavable); bool isModified = false; - ShaderManagementConsoleDocumentRequestBus::EventResult(isModified, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::IsModified); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(isModified, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::IsModified); bool canUndo = false; - ShaderManagementConsoleDocumentRequestBus::EventResult(canUndo, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::CanUndo); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(canUndo, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::CanUndo); bool canRedo = false; - ShaderManagementConsoleDocumentRequestBus::EventResult(canRedo, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::CanRedo); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(canRedo, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::CanRedo); AZStd::string absolutePath; - ShaderManagementConsoleDocumentRequestBus::EventResult(absolutePath, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::GetAbsolutePath); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(absolutePath, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::GetAbsolutePath); AZStd::string filename; AzFramework::StringFunc::Path::GetFullFileName(absolutePath.c_str(), filename); @@ -150,7 +149,7 @@ namespace ShaderManagementConsole const QString documentPath = GetDocumentPath(documentId); if (!documentPath.isEmpty()) { - const QString status = QString("Document closed: %1").arg(documentPath); + const QString status = QString("Document opened: %1").arg(documentPath); m_statusMessage->setText(QString("%1").arg(status)); } } @@ -167,9 +166,9 @@ namespace ShaderManagementConsole void ShaderManagementConsoleWindow::OnDocumentModified(const AZ::Uuid& documentId) { bool isModified = false; - ShaderManagementConsoleDocumentRequestBus::EventResult(isModified, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::IsModified); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(isModified, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::IsModified); AZStd::string absolutePath; - ShaderManagementConsoleDocumentRequestBus::EventResult(absolutePath, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::GetAbsolutePath); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(absolutePath, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::GetAbsolutePath); AZStd::string filename; AzFramework::StringFunc::Path::GetFullFileName(absolutePath.c_str(), filename); UpdateTabForDocumentId(documentId, filename, absolutePath, isModified); @@ -180,9 +179,9 @@ namespace ShaderManagementConsole if (documentId == GetDocumentIdFromTab(m_tabWidget->currentIndex())) { bool canUndo = false; - ShaderManagementConsoleDocumentRequestBus::EventResult(canUndo, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::CanUndo); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(canUndo, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::CanUndo); bool canRedo = false; - ShaderManagementConsoleDocumentRequestBus::EventResult(canRedo, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::CanRedo); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(canRedo, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::CanRedo); m_actionUndo->setEnabled(canUndo); m_actionRedo->setEnabled(canRedo); } @@ -191,15 +190,15 @@ namespace ShaderManagementConsole void ShaderManagementConsoleWindow::OnDocumentSaved(const AZ::Uuid& documentId) { bool isModified = false; - ShaderManagementConsoleDocumentRequestBus::EventResult(isModified, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::IsModified); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(isModified, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::IsModified); AZStd::string absolutePath; - ShaderManagementConsoleDocumentRequestBus::EventResult(absolutePath, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::GetAbsolutePath); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(absolutePath, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::GetAbsolutePath); AZStd::string filename; AzFramework::StringFunc::Path::GetFullFileName(absolutePath.c_str(), filename); UpdateTabForDocumentId(documentId, filename, absolutePath, isModified); const QString documentPath = GetDocumentPath(documentId); - const QString status = QString("Document closed: %1").arg(documentPath); + const QString status = QString("Document saved: %1").arg(documentPath); m_statusMessage->setText(QString("%1").arg(status)); } @@ -217,7 +216,7 @@ namespace ShaderManagementConsole const AZStd::string filePath = AtomToolsFramework::GetOpenFileInfo(assetTypes).absoluteFilePath().toUtf8().constData(); if (!filePath.empty()) { - ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::OpenDocument, filePath); + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::OpenDocument, filePath); } }, QKeySequence::Open); @@ -228,11 +227,11 @@ namespace ShaderManagementConsole m_actionSave = m_menuFile->addAction("&Save", [this]() { const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex()); bool result = false; - ShaderManagementConsoleDocumentSystemRequestBus::BroadcastResult(result, &ShaderManagementConsoleDocumentSystemRequestBus::Events::SaveDocument, documentId); + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::BroadcastResult(result, &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::SaveDocument, documentId); if (!result) { const QString documentPath = GetDocumentPath(documentId); - const QString status = QString("Failed to save document: %1").arg(documentPath); + const QString status = QString("Document save failed: %1").arg(documentPath); m_statusMessage->setText(QString("%1").arg(status)); } }, QKeySequence::Save); @@ -242,21 +241,21 @@ namespace ShaderManagementConsole const QString documentPath = GetDocumentPath(documentId); bool result = false; - ShaderManagementConsoleDocumentSystemRequestBus::BroadcastResult(result, &ShaderManagementConsoleDocumentSystemRequestBus::Events::SaveDocumentAsCopy, + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::BroadcastResult(result, &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::SaveDocumentAsCopy, documentId, AtomToolsFramework::GetSaveFileInfo(documentPath).absoluteFilePath().toUtf8().constData()); if (!result) { - const QString status = QString("Failed to save document: %1").arg(documentPath); + const QString status = QString("Document save failed: %1").arg(documentPath); m_statusMessage->setText(QString("%1").arg(status)); } }, QKeySequence::SaveAs); m_actionSaveAll = m_menuFile->addAction("Save A&ll", [this]() { bool result = false; - ShaderManagementConsoleDocumentSystemRequestBus::BroadcastResult(result, &ShaderManagementConsoleDocumentSystemRequestBus::Events::SaveAllDocuments); + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::BroadcastResult(result, &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::SaveAllDocuments); if (!result) { - const QString status = QString("Failed to save documents."); + const QString status = QString("Document save all failed."); m_statusMessage->setText(QString("%1").arg(status)); } }); @@ -265,16 +264,16 @@ namespace ShaderManagementConsole m_actionClose = m_menuFile->addAction("&Close", [this]() { const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex()); - ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::CloseDocument, documentId); + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CloseDocument, documentId); }, QKeySequence::Close); m_actionCloseAll = m_menuFile->addAction("Close All", [this]() { - ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::CloseAllDocuments); + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CloseAllDocuments); }); m_actionCloseOthers = m_menuFile->addAction("Close Others", [this]() { const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex()); - ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::CloseAllDocumentsExcept, documentId); + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CloseAllDocumentsExcept, documentId); }); m_menuFile->addSeparator(); @@ -298,11 +297,11 @@ namespace ShaderManagementConsole m_actionUndo = m_menuEdit->addAction("&Undo", [this]() { const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex()); bool result = false; - ShaderManagementConsoleDocumentRequestBus::EventResult(result, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::Undo); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(result, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::Undo); if (!result) { const QString documentPath = GetDocumentPath(documentId); - const QString status = QString("Failed to perform undo on document: %1").arg(documentPath); + const QString status = QString("Document undo failed: %1").arg(documentPath); m_statusMessage->setText(QString("%1").arg(status)); } }, QKeySequence::Undo); @@ -310,11 +309,11 @@ namespace ShaderManagementConsole m_actionRedo = m_menuEdit->addAction("&Redo", [this]() { const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex()); bool result = false; - ShaderManagementConsoleDocumentRequestBus::EventResult(result, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::Redo); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(result, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::Redo); if (!result) { const QString documentPath = GetDocumentPath(documentId); - const QString status = QString("Failed to perform redo on document: %1").arg(documentPath); + const QString status = QString("Document redo failed: %1").arg(documentPath); m_statusMessage->setText(QString("%1").arg(status)); } }, QKeySequence::Redo); @@ -366,19 +365,19 @@ namespace ShaderManagementConsole // This should automatically clear the active document connect(m_tabWidget, &QTabWidget::currentChanged, this, [this](int tabIndex) { const AZ::Uuid documentId = GetDocumentIdFromTab(tabIndex); - ShaderManagementConsoleDocumentNotificationBus::Broadcast(&ShaderManagementConsoleDocumentNotificationBus::Events::OnDocumentOpened, documentId); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentOpened, documentId); }); connect(m_tabWidget, &QTabWidget::tabCloseRequested, this, [this](int tabIndex) { const AZ::Uuid documentId = GetDocumentIdFromTab(tabIndex); - ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::CloseDocument, documentId); + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CloseDocument, documentId); }); } QString ShaderManagementConsoleWindow::GetDocumentPath(const AZ::Uuid& documentId) const { AZStd::string absolutePath; - ShaderManagementConsoleDocumentRequestBus::EventResult(absolutePath, documentId, &ShaderManagementConsoleDocumentRequestBus::Handler::GetAbsolutePath); + AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(absolutePath, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Handler::GetAbsolutePath); return absolutePath.c_str(); } @@ -394,15 +393,15 @@ namespace ShaderManagementConsole const QString selectActionName = (currentTabIndex == clickedTabIndex) ? "Select in Browser" : "Select"; tabMenu.addAction(selectActionName, [this, clickedTabIndex]() { const AZ::Uuid documentId = GetDocumentIdFromTab(clickedTabIndex); - ShaderManagementConsoleDocumentNotificationBus::Broadcast(&ShaderManagementConsoleDocumentNotificationBus::Events::OnDocumentOpened, documentId); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentOpened, documentId); }); tabMenu.addAction("Close", [this, clickedTabIndex]() { const AZ::Uuid documentId = GetDocumentIdFromTab(clickedTabIndex); - ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::CloseDocument, documentId); + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CloseDocument, documentId); }); auto closeOthersAction = tabMenu.addAction("Close Others", [this, clickedTabIndex]() { const AZ::Uuid documentId = GetDocumentIdFromTab(clickedTabIndex); - ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::CloseAllDocumentsExcept, documentId); + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CloseAllDocumentsExcept, documentId); }); closeOthersAction->setEnabled(tabBar->count() > 1); tabMenu.exec(QCursor::pos()); diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.h b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.h index 7f3f772961..2b682f6c09 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.h +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.h @@ -9,9 +9,9 @@ #pragma once #if !defined(Q_MOC_RUN) -#include #include #include +#include #include #include @@ -31,7 +31,7 @@ namespace ShaderManagementConsole */ class ShaderManagementConsoleWindow : public AtomToolsFramework::AtomToolsMainWindow - , private ShaderManagementConsoleDocumentNotificationBus::Handler + , private AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler { Q_OBJECT public: @@ -43,7 +43,7 @@ namespace ShaderManagementConsole ~ShaderManagementConsoleWindow(); private: - // ShaderManagementConsoleDocumentNotificationBus::Handler overrides... + // AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler overrides... void OnDocumentOpened(const AZ::Uuid& documentId) override; void OnDocumentClosed(const AZ::Uuid& documentId) override; void OnDocumentModified(const AZ::Uuid& documentId) override; diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindowComponent.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindowComponent.cpp index a89cdfddb8..a59712d572 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindowComponent.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindowComponent.cpp @@ -6,25 +6,20 @@ * */ -#include - -#include -#include -#include - #include - -#include -#include +#include +#include +#include +#include +#include #include - +#include +#include #include #include #include - -#include -#include -#include +#include +#include AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT #include diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/shadermanagementconsole_files.cmake b/Gems/Atom/Tools/ShaderManagementConsole/Code/shadermanagementconsole_files.cmake index 6442df4832..e832ba2784 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/shadermanagementconsole_files.cmake +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/shadermanagementconsole_files.cmake @@ -10,7 +10,5 @@ set(FILES Source/main.cpp Source/ShaderManagementConsoleApplication.cpp Source/ShaderManagementConsoleApplication.h - Include/Atom/Document/ShaderManagementConsoleDocumentModule.h - Source/Document/ShaderManagementConsoleDocumentModule.cpp ../Scripts/GenerateShaderVariantListForMaterials.py ) diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/shadermanagementconsoledocument_files.cmake b/Gems/Atom/Tools/ShaderManagementConsole/Code/shadermanagementconsoledocument_files.cmake index e703f5efcc..220d2895ac 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/shadermanagementconsoledocument_files.cmake +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/shadermanagementconsoledocument_files.cmake @@ -7,11 +7,11 @@ # set(FILES - Include/Atom/Document/ShaderManagementConsoleDocumentSystemRequestBus.h - Include/Atom/Document/ShaderManagementConsoleDocumentNotificationBus.h + Include/Atom/Document/ShaderManagementConsoleDocumentModule.h Include/Atom/Document/ShaderManagementConsoleDocumentRequestBus.h - Source/Document/ShaderManagementConsoleDocumentSystemComponent.cpp - Source/Document/ShaderManagementConsoleDocumentSystemComponent.h Source/Document/ShaderManagementConsoleDocument.cpp Source/Document/ShaderManagementConsoleDocument.h + Source/Document/ShaderManagementConsoleDocumentModule.cpp + Source/Document/ShaderManagementConsoleDocumentSystemComponent.cpp + Source/Document/ShaderManagementConsoleDocumentSystemComponent.h ) diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Scripts/GenerateShaderVariantListForMaterials.py b/Gems/Atom/Tools/ShaderManagementConsole/Scripts/GenerateShaderVariantListForMaterials.py index 6c5e8df3dd..7bd65568ed 100755 --- a/Gems/Atom/Tools/ShaderManagementConsole/Scripts/GenerateShaderVariantListForMaterials.py +++ b/Gems/Atom/Tools/ShaderManagementConsole/Scripts/GenerateShaderVariantListForMaterials.py @@ -153,7 +153,7 @@ def main(): azlmbr.shader.SaveShaderVariantListSourceData(shaderVariantListFilePath, shaderVariantList) # Open the document in shader management console - result = azlmbr.shadermanagementconsole.ShaderManagementConsoleDocumentSystemRequestBus( + result = azlmbr.atomtools.AtomToolsDocumentSystemRequestBus( azlmbr.bus.Broadcast, 'OpenDocument', shaderVariantListFilePath From 4cf384c2c555919e9e234c02c4d87fa0aef21840 Mon Sep 17 00:00:00 2001 From: moudgils <47460854+moudgils@users.noreply.github.com> Date: Thu, 12 Aug 2021 21:12:41 -0700 Subject: [PATCH 359/803] Fix minor typo (#3095) Signed-off-by: moudgils --- .../Platform/Mac/AzFramework/Windowing/NativeWindow_Mac.mm | 4 ++-- .../Platform/iOS/AzFramework/Windowing/NativeWindow_ios.mm | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Code/Framework/AzFramework/Platform/Mac/AzFramework/Windowing/NativeWindow_Mac.mm b/Code/Framework/AzFramework/Platform/Mac/AzFramework/Windowing/NativeWindow_Mac.mm index f9eef9170a..272faeb4c1 100644 --- a/Code/Framework/AzFramework/Platform/Mac/AzFramework/Windowing/NativeWindow_Mac.mm +++ b/Code/Framework/AzFramework/Platform/Mac/AzFramework/Windowing/NativeWindow_Mac.mm @@ -34,7 +34,7 @@ namespace AzFramework bool GetFullScreenState() const override; void SetFullScreenState(bool fullScreenState) override; bool CanToggleFullScreenState() const override { return true; } - uint32_t GetMainDisplayRefreshRate() const; + uint32_t GetDisplayRefreshRate() const override; private: static NSWindowStyleMask ConvertToNSWindowStyleMask(const WindowStyleMasks& styleMasks); @@ -142,7 +142,7 @@ namespace AzFramework return nativeMask ? nativeMask : defaultMask; } - uint32_t NativeWindowImpl_Darwin::GetMainDisplayRefreshRate() const + uint32_t NativeWindowImpl_Darwin::GetDisplayRefreshRate() const { return m_mainDisplayRefreshRate; } diff --git a/Code/Framework/AzFramework/Platform/iOS/AzFramework/Windowing/NativeWindow_ios.mm b/Code/Framework/AzFramework/Platform/iOS/AzFramework/Windowing/NativeWindow_ios.mm index 83e176b9ef..0486ca1b92 100644 --- a/Code/Framework/AzFramework/Platform/iOS/AzFramework/Windowing/NativeWindow_ios.mm +++ b/Code/Framework/AzFramework/Platform/iOS/AzFramework/Windowing/NativeWindow_ios.mm @@ -27,7 +27,7 @@ namespace AzFramework const WindowGeometry& geometry, const WindowStyleMasks& styleMasks) override; NativeWindowHandle GetWindowHandle() const override; - uint32_t GetMainDisplayRefreshRate() const; + uint32_t GetDisplayRefreshRate() const override; private: UIWindow* m_nativeWindow; @@ -66,7 +66,7 @@ namespace AzFramework return m_nativeWindow; } - uint32_t NativeWindowImpl_Ios::GetMainDisplayRefreshRate() const + uint32_t NativeWindowImpl_Ios::GetDisplayRefreshRate() const { return m_mainDisplayRefreshRate; } From 364ac5150272c2931a1df36e277af8a913d1e00c Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Fri, 13 Aug 2021 00:19:43 -0500 Subject: [PATCH 360/803] Removed errors from unimplemented status functions Updated shader management console trace messages Renamed document rebuild function to reopen Signed-off-by: Guthrie Adams --- .../AtomToolsFramework/Document/AtomToolsDocument.h | 2 +- .../Document/AtomToolsDocumentRequestBus.h | 4 ++-- .../Code/Source/Document/AtomToolsDocument.cpp | 7 +------ .../Document/AtomToolsDocumentSystemComponent.cpp | 10 +++++----- .../Code/Source/Document/MaterialDocument.cpp | 2 +- .../Code/Source/Document/MaterialDocument.h | 2 +- .../Document/ShaderManagementConsoleDocument.cpp | 4 ++-- 7 files changed, 13 insertions(+), 18 deletions(-) diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocument.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocument.h index 390a08e5b1..565c9f00a3 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocument.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocument.h @@ -37,7 +37,7 @@ namespace AtomToolsFramework bool IsPropertyGroupVisible(const AZ::Name& propertyGroupFullName) const override; void SetPropertyValue(const AZ::Name& propertyFullName, const AZStd::any& value) override; bool Open(AZStd::string_view loadPath) override; - bool Rebuild() override; + bool Reopen() override; bool Save() override; bool SaveAsCopy(AZStd::string_view savePath) override; bool SaveAsChild(AZStd::string_view savePath) override; diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentRequestBus.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentRequestBus.h index 42fcab95ae..a8ef7852ea 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentRequestBus.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentRequestBus.h @@ -46,8 +46,8 @@ namespace AtomToolsFramework //! @param loadPath absolute path of document to load virtual bool Open(AZStd::string_view loadPath) = 0; - //! Reload document preserving edits - virtual bool Rebuild() = 0; + //! Reopen document preserving edits + virtual bool Reopen() = 0; //! Save document to file virtual bool Save() = 0; diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocument.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocument.cpp index c3216c6d9d..48212fe154 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocument.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocument.cpp @@ -67,7 +67,7 @@ namespace AtomToolsFramework return false; } - bool AtomToolsDocument::Rebuild() + bool AtomToolsDocument::Reopen() { AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); return false; @@ -100,31 +100,26 @@ namespace AtomToolsFramework bool AtomToolsDocument::IsOpen() const { - AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); return false; } bool AtomToolsDocument::IsModified() const { - AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); return false; } bool AtomToolsDocument::IsSavable() const { - AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); return false; } bool AtomToolsDocument::CanUndo() const { - AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); return false; } bool AtomToolsDocument::CanRedo() const { - AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); return false; } diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.cpp index fa7280068e..5652e9fe23 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.cpp @@ -79,7 +79,7 @@ namespace AtomToolsFramework ->Event("GetPropertyValue", &AtomToolsDocumentRequestBus::Events::GetPropertyValue) ->Event("SetPropertyValue", &AtomToolsDocumentRequestBus::Events::SetPropertyValue) ->Event("Open", &AtomToolsDocumentRequestBus::Events::Open) - ->Event("Rebuild", &AtomToolsDocumentRequestBus::Events::Rebuild) + ->Event("Reopen", &AtomToolsDocumentRequestBus::Events::Reopen) ->Event("Close", &AtomToolsDocumentRequestBus::Events::Close) ->Event("Save", &AtomToolsDocumentRequestBus::Events::Save) ->Event("SaveAsChild", &AtomToolsDocumentRequestBus::Events::SaveAsChild) @@ -168,7 +168,7 @@ namespace AtomToolsFramework void AtomToolsDocumentSystemComponent::OnDocumentDependencyModified(const AZ::Uuid& documentId) { - m_documentIdsToRebuild.insert(documentId); + m_documentIdsToReopen.insert(documentId); if (!AZ::TickBus::Handler::BusIsConnected()) { AZ::TickBus::Handler::BusConnect(); @@ -204,7 +204,7 @@ namespace AtomToolsFramework } } - for (const AZ::Uuid& documentId : m_documentIdsToRebuild) + for (const AZ::Uuid& documentId : m_documentIdsToReopen) { AZStd::string documentPath; AtomToolsDocumentRequestBus::EventResult(documentPath, documentId, &AtomToolsDocumentRequestBus::Events::GetAbsolutePath); @@ -221,7 +221,7 @@ namespace AtomToolsFramework AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); bool openResult = false; - AtomToolsDocumentRequestBus::EventResult(openResult, documentId, &AtomToolsDocumentRequestBus::Events::Rebuild); + AtomToolsDocumentRequestBus::EventResult(openResult, documentId, &AtomToolsDocumentRequestBus::Events::Reopen); if (!openResult) { QMessageBox::critical( @@ -231,7 +231,7 @@ namespace AtomToolsFramework } } - m_documentIdsToRebuild.clear(); + m_documentIdsToReopen.clear(); m_documentIdsToReopen.clear(); AZ::TickBus::Handler::BusDisconnect(); } diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp index 298d38f650..11834beb73 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp @@ -182,7 +182,7 @@ namespace MaterialEditor return true; } - bool MaterialDocument::Rebuild() + bool MaterialDocument::Reopen() { // Store history and property changes that should be reapplied after reload auto undoHistoryToRestore = m_undoHistory; diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.h index 09a1873dcf..d732680b7b 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.h @@ -48,7 +48,7 @@ namespace MaterialEditor bool IsPropertyGroupVisible(const AZ::Name& propertyGroupFullName) const override; void SetPropertyValue(const AZ::Name& propertyFullName, const AZStd::any& value) override; bool Open(AZStd::string_view loadPath) override; - bool Rebuild() override; + bool Reopen() override; bool Save() override; bool SaveAsCopy(AZStd::string_view savePath) override; bool SaveAsChild(AZStd::string_view savePath) override; diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocument.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocument.cpp index 9a836c5c05..2b7767635e 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocument.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocument.cpp @@ -112,7 +112,7 @@ namespace ShaderManagementConsole AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentOpened, m_id); - AZ_TracePrintf("ShaderManagementConsoleDocument", "Document loaded: '%s'", m_absolutePath.c_str()); + AZ_TracePrintf("ShaderManagementConsoleDocument", "Document opened: '%s'\n", m_absolutePath.c_str()); return true; } @@ -126,7 +126,7 @@ namespace ShaderManagementConsole Clear(); AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentClosed, m_id); - AZ_TracePrintf("ShaderManagementConsoleDocument", "Document was closed"); + AZ_TracePrintf("ShaderManagementConsoleDocument", "Document closed\n"); return true; } From 706333466e2137f11ba96105907f75291722d4c3 Mon Sep 17 00:00:00 2001 From: antonmic <56370189+antonmic@users.noreply.github.com> Date: Thu, 12 Aug 2021 23:58:51 -0700 Subject: [PATCH 361/803] Addressing PR feedback and making PassBuilder error if referenced shader isn't found Signed-off-by: antonmic <56370189+antonmic@users.noreply.github.com> --- .../Source/RPI.Builders/Pass/PassBuilder.cpp | 27 ++++++++++++------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Pass/PassBuilder.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/Pass/PassBuilder.cpp index a803ecf31a..f74792049f 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Pass/PassBuilder.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Pass/PassBuilder.cpp @@ -70,16 +70,16 @@ namespace AZ // Helper class to pass parameters to the AddDependency and FindReferencedAssets functions below struct FindPassReferenceAssetParams { - void* passAssetObject; + void* passAssetObject = nullptr; Uuid passAssetUuid; - SerializeContext* serializeContext; - AZStd::string_view passAssetSourceFile; // File path of the pass asset - AZStd::string_view dependencySourceFile; // File pass of the asset the pass asset depends on - const char* jobKey; // Job key for adding job dependency + SerializeContext* serializeContext = nullptr; + AZStd::string_view passAssetSourceFile; // File path of the pass asset + AZStd::string_view dependencySourceFile; // File pass of the asset the pass asset depends on + const char* jobKey = nullptr; // Job key for adding job dependency }; // Helper function to get a file reference and create a corresponding job dependency - void AddDependency(FindPassReferenceAssetParams& params, AssetBuilderSDK::JobDescriptor* job) + bool AddDependency(FindPassReferenceAssetParams& params, AssetBuilderSDK::JobDescriptor* job) { AZStd::string_view& file = params.dependencySourceFile; AZ::Data::AssetInfo sourceInfo; @@ -95,6 +95,12 @@ namespace AZ jobDependency.m_sourceFile.m_sourceFileDependencyPath = file; job->m_jobDependencyList.push_back(jobDependency); AZ_TracePrintf(PassBuilderName, "Creating job dependency on file [%s] \n", file.data()); + return true; + } + else + { + AZ_Error(PassBuilderName, false, "Could not find referenced file [%s]", file.data()); + return false; } } @@ -104,7 +110,7 @@ namespace AZ SerializeContext::ErrorHandler errorLogger; errorLogger.Reset(); - bool foundProblems = false; + bool success = true; // This callback will check whether the given element is an asset reference. If so, it will add it to the list of asset references auto beginCallback = [&](void* ptr, const SerializeContext::ClassData* classData, [[maybe_unused]] const SerializeContext::ClassElement* classElement) @@ -123,7 +129,8 @@ namespace AZ if (job != nullptr) // Create Job Phase { params.dependencySourceFile = path; - AddDependency(params, job); + bool dependencyAddedSuccessfully = AddDependency(params, job); + success = dependencyAddedSuccessfully && success; } else // Process Job Phase { @@ -136,7 +143,7 @@ namespace AZ else { AZ_Error(PassBuilderName, false, "Could not get AssetId for [%s]", assetReference->m_filePath.c_str()); - foundProblems = true; + success = false; } } } @@ -162,7 +169,7 @@ namespace AZ , nullptr ); - return !foundProblems; + return success; } // --- Code related to dependency shader asset handling --- From 4dd39c392979db451abbb22b1f4bae6220a7ed27 Mon Sep 17 00:00:00 2001 From: John Date: Fri, 13 Aug 2021 09:55:06 +0100 Subject: [PATCH 362/803] Address commit re-run corner case. Signed-off-by: John --- scripts/build/TestImpactAnalysis/tiaf.py | 47 ++++++---- .../tiaf_persistent_storage.py | 90 +++++++++++++++---- .../tiaf_persistent_storage_local.py | 13 ++- .../tiaf_persistent_storage_s3.py | 17 ++-- 4 files changed, 124 insertions(+), 43 deletions(-) diff --git a/scripts/build/TestImpactAnalysis/tiaf.py b/scripts/build/TestImpactAnalysis/tiaf.py index 6a43ad3c70..28de00d6ba 100644 --- a/scripts/build/TestImpactAnalysis/tiaf.py +++ b/scripts/build/TestImpactAnalysis/tiaf.py @@ -87,7 +87,7 @@ class TestImpact: try: # Attempt to generate a diff between the src and dst commits - logger.error(f"Source '{self._src_commit}' and destination '{self._dst_commit}' will be diff'd.") + logger.info(f"Source '{self._src_commit}' and destination '{self._dst_commit}' will be diff'd.") diff_path = pathlib.Path(pathlib.PurePath(self._temp_workspace).joinpath(f"changelist.{self._instance_id}.diff")) self._repo.create_diff_file(self._src_commit, self._dst_commit, diff_path, multi_branch) except RuntimeError as e: @@ -219,28 +219,37 @@ class TestImpact: try: # Persistent storage location if s3_bucket: - persistent_storage = PersistentStorageS3(self._config, suite, s3_bucket, s3_top_level_dir, self._source_of_truth_branch) + persistent_storage = PersistentStorageS3(self._config, suite, self._dst_commit, s3_bucket, s3_top_level_dir, self._source_of_truth_branch) else: - persistent_storage = PersistentStorageLocal(self._config, suite) + persistent_storage = PersistentStorageLocal(self._config, suite, self._dst_commit) except SystemError as e: logger.warning(f"The persistent storage encountered an irrecoverable error, test impact analysis will be disabled: '{e}'") persistent_storage = None if persistent_storage: - # Flag to signify whether or not this is a re-run (multiple runs of the same commit) - # Right now, we don't fully support re-runs but in the future we will have an extra subfolder for each commit hash with the - # last run hash that was used for the first run for the commit so we can retreive the same reference point for building the - # change list to ensure each subsequent run is using the same data but for the time being, just perform a regular run - is_rerun = False + + # Flag for corner case where: + # 1. TIAF was already run previously for this commit. + # 2. There was no last commit hash when TIAF last ran on this commit (due to no coverage data existing get for this branch) + # 3. TIAF has not been run on any other commits between the run for this commit and the last run for this commit. + # The above results in TIAF being stuck in a state of generating an empty change list (and thus doing no work until another + # commit comes in) which is problematic if the commit needs to be re-run for whatever reason so in these conditions we revert + # back to a regular test run until another commit comes in + cannot_rerun_with_instrumentation = False + if persistent_storage.has_historic_data: logger.info("Historic data found.") self._src_commit = persistent_storage.last_commit_hash - # Perform some basic sanity checks on the commit hashes to ensure confidence in the integrity of the environment - if self._src_commit == self._dst_commit: - logger.info(f"Source commit '{self._src_commit}' and destination commit '{self._dst_commit}', implying this is a re-run. A regular sequence will instead be performed.") - persistent_storage = None - is_rerun = True + # Check to see if this is a re-run for this commit before any other changes have come in + if persistent_storage.is_repeat_sequence: + if persistent_storage.can_rerun_sequence: + logger.info(f"This sequence is being re-run before any other changes have come in so the last commit '{persistent_storage.this_commit_last_commit_hash}' used for the previous sequence will be used instead.") + self._src_commit = persistent_storage.this_commit_last_commit_hash + else: + logger.info(f"This sequence is being re-run before any other changes have come in but there is no useful historic data. A regular sequence will be performed instead.") + persistent_storage = None + cannot_rerun_with_instrumentation = True else: self._attempt_to_generate_change_list() else: @@ -268,7 +277,7 @@ class TestImpact: args.append(f"--changelist={self._change_list_path}") logger.info(f"Change list is set to '{self._change_list_path}'.") else: - if self._is_source_of_truth_branch and not is_rerun: + if self._is_source_of_truth_branch and not cannot_rerun_with_instrumentation: # Use seed sequence (instrumented all tests) for coverage updating branches so we can generate the coverage bed for future sequences sequence_type = "seed" # We always continue after test failures when seeding to ensure we capture the coverage for all test targets @@ -314,14 +323,18 @@ class TestImpact: logger.info(f"Args: {unpacked_args}") runtime_result = subprocess.run([str(self._tiaf_bin)] + args) report = None - + # If the sequence completed (with or without failures) we will update the historical meta-data if runtime_result.returncode == 0 or runtime_result.returncode == 7: logger.info("Test impact analysis runtime returned successfully.") - if self._is_source_of_truth_branch and persistent_storage is not None: - persistent_storage.update_and_store_historic_data(self._dst_commit) + + # Get the sequence report the runtime generated with open(report_file) as json_file: report = json.load(json_file) + + # Attempt to store the historic data for this branch and sequence + if self._is_source_of_truth_branch and persistent_storage is not None: + persistent_storage.update_and_store_historic_data() else: logger.error(f"The test impact analysis runtime returned with error: '{runtime_result.returncode}'.") diff --git a/scripts/build/TestImpactAnalysis/tiaf_persistent_storage.py b/scripts/build/TestImpactAnalysis/tiaf_persistent_storage.py index 1ee3ac7e8c..3fff05b549 100644 --- a/scripts/build/TestImpactAnalysis/tiaf_persistent_storage.py +++ b/scripts/build/TestImpactAnalysis/tiaf_persistent_storage.py @@ -15,23 +15,39 @@ logger = get_logger(__file__) # Abstraction for the persistent storage required by TIAF to store and retrieve the branch coverage data and other meta-data class PersistentStorage(ABC): - def __init__(self, config: dict, suite: str): + + WORKSPACE_KEY = "workspace" + LAST_RUNS_KEY = "last_runs" + ACTIVE_KEY = "active" + ROOT_KEY = "root" + RELATIVE_PATHS_KEY = "relative_paths" + TEST_IMPACT_DATA_FILES_KEY = "test_impact_data_files" + LAST_COMMIT_HASH_KEY = "last_commit_hash" + COVERAGE_DATA_KEY = "coverage_data" + + def __init__(self, config: dict, suite: str, commit: str): """ Initializes the persistent storage into a state for which there is no historic data available. @param config: The runtime configuration to obtain the data file paths from. @param suite: The test suite for which the historic data will be obtained for. + @param commit: The commit hash for this build. """ # Work on the assumption that there is no historic meta-data (a valid state to be in, should none exist) self._last_commit_hash = None self._has_historic_data = False + self._has_previous_last_commit_hash = False + self._this_commit_hash = commit + self._this_commit_hash_last_commit_hash = None + self._historic_data = None + logger.info(f"Attempting to access persistent storage for the commit {self._this_commit_hash}") try: # The runtime expects the coverage data to be in the location specified in the config file (unless overridden with # the --datafile command line argument, which the TIAF scripts do not do) - self._active_workspace = pathlib.Path(config["workspace"]["active"]["root"]) - unpacked_coverage_data_file = config["workspace"]["active"]["relative_paths"]["test_impact_data_files"][suite] + self._active_workspace = pathlib.Path(config[self.WORKSPACE_KEY][self.ACTIVE_KEY][self.ROOT_KEY]) + unpacked_coverage_data_file = config[self.WORKSPACE_KEY][self.ACTIVE_KEY][self.RELATIVE_PATHS_KEY][self.TEST_IMPACT_DATA_FILES_KEY][suite] except KeyError as e: raise SystemError(f"The config does not contain the key {str(e)}.") @@ -45,17 +61,36 @@ class PersistentStorage(ABC): """ self._has_historic_data = False + self._has_previous_last_commit_hash = False try: - historic_data = json.loads(historic_data_json) - self._last_commit_hash = historic_data["last_commit_hash"] + self._historic_data = json.loads(historic_data_json) + + # Last commit hash for this branch + self._last_commit_hash = self._historic_data[self.LAST_COMMIT_HASH_KEY] logger.info(f"Last commit hash '{self._last_commit_hash}' found.") + if self.LAST_RUNS_KEY in self._historic_data: + # Last commit hash for the sequence that was run for this commit previously (if any) + if self._this_commit_hash in self._historic_data[self.LAST_RUNS_KEY]: + # 'None' is a valid value for the previously used last commit hash if there was no coverage data at that time + self._this_commit_hash_last_commit_hash = self._historic_data[self.LAST_RUNS_KEY][self._this_commit_hash] + self._has_previous_last_commit_hash = self._this_commit_hash_last_commit_hash is not None + + if self._has_previous_last_commit_hash: + logger.info(f"Last commit hash '{self._this_commit_hash_last_commit_hash}' was used previously for this commit.") + else: + logger.info(f"Prior sequence data found for this commit but it is empty (there was no coverage data vailable at that time).") + else: + logger.info(f"No prior sequence data found for commit '{self._this_commit_hash}', this is the first sequence for this commit.") + else: + logger.info(f"No prior sequence data found for any commits.") + # Create the active workspace directory where the coverage data file will be placed and unpack the coverage data so # it is accessible by the runtime self._active_workspace.mkdir(exist_ok=True) with open(self._unpacked_coverage_data_file, "w", newline='\n') as coverage_data: - coverage_data.write(historic_data["coverage_data"]) + coverage_data.write(self._historic_data[self.COVERAGE_DATA_KEY]) self._has_historic_data = True except json.JSONDecodeError: @@ -65,20 +100,31 @@ class PersistentStorage(ABC): except EnvironmentError as e: logger.error(f"There was a problem the coverage data file '{self._unpacked_coverage_data_file}': '{e}'.") - def _pack_historic_data(self, last_commit_hash: str): + def _pack_historic_data(self): """ Packs the current historic data into a JSON file for serializing. - @param last_commit_hash: The commit hash to associate the coverage data (and any other meta data) with. - @return: The packed historic data in JSON format. + @return: The packed historic data in JSON format. """ try: # Attempt to read the existing coverage data if self._unpacked_coverage_data_file.is_file(): + if not self._historic_data: + self._historic_data = {} + + # Last commit hash for this branch + self._historic_data[self.LAST_COMMIT_HASH_KEY] = self._this_commit_hash + + # Last commit hash for this commit + if not self.LAST_RUNS_KEY in self._historic_data: + self._historic_data[self.LAST_RUNS_KEY] = {} + self._historic_data[self.LAST_RUNS_KEY][self._this_commit_hash] = self._last_commit_hash + + # Coverage data for this branch with open(self._unpacked_coverage_data_file, "r") as coverage_data: - historic_data = {"last_commit_hash": last_commit_hash, "coverage_data": coverage_data.read()} - return json.dumps(historic_data) + self._historic_data[self.COVERAGE_DATA_KEY] = coverage_data.read() + return json.dumps(self._historic_data) else: logger.info(f"No coverage data exists at location '{self._unpacked_coverage_data_file}'.") except EnvironmentError as e: @@ -97,16 +143,14 @@ class PersistentStorage(ABC): """ pass - def update_and_store_historic_data(self, last_commit_hash: str): + def update_and_store_historic_data(self): """ Updates the historic data and stores it in the designated persistent storage location. - - @param last_commit_hash: The commit hash to associate the coverage data (and any other meta data) with. """ - historic_data_json = self._pack_historic_data(last_commit_hash) + historic_data_json = self._pack_historic_data() if historic_data_json: - logger.info(f"Attempting to store historic data with new last commit hash '{last_commit_hash}'...") + logger.info(f"Attempting to store historic data with new last commit hash '{self._this_commit_hash}'...") self._store_historic_data(historic_data_json) logger.info("The historic data was successfully stored.") @@ -119,4 +163,16 @@ class PersistentStorage(ABC): @property def last_commit_hash(self): - return self._last_commit_hash \ No newline at end of file + return self._last_commit_hash + + @property + def is_repeat_sequence(self): + return self._last_commit_hash == self._this_commit_hash + + @property + def this_commit_last_commit_hash(self): + return self._this_commit_hash_last_commit_hash + + @property + def can_rerun_sequence(self): + return self._has_previous_last_commit_hash \ No newline at end of file diff --git a/scripts/build/TestImpactAnalysis/tiaf_persistent_storage_local.py b/scripts/build/TestImpactAnalysis/tiaf_persistent_storage_local.py index ba9b58fbf3..c72fafc580 100644 --- a/scripts/build/TestImpactAnalysis/tiaf_persistent_storage_local.py +++ b/scripts/build/TestImpactAnalysis/tiaf_persistent_storage_local.py @@ -15,19 +15,24 @@ logger = get_logger(__file__) # Implementation of local persistent storage class PersistentStorageLocal(PersistentStorage): - def __init__(self, config: str, suite: str): + + HISTORIC_KEY = "historic" + DATA_KEY = "data" + + def __init__(self, config: str, suite: str, commit: str): """ Initializes the persistent storage with any local historic data available. @param config: The runtime config file to obtain the data file paths from. @param suite: The test suite for which the historic data will be obtained for. + @param commit: The commit hash for this build. """ - super().__init__(config, suite) + super().__init__(config, suite, commit) try: # Attempt to obtain the local persistent data location specified in the runtime config file - self._historic_workspace = pathlib.Path(config["workspace"]["historic"]["root"]) - historic_data_file = pathlib.Path(config["workspace"]["historic"]["relative_paths"]["data"]) + self._historic_workspace = pathlib.Path(config[self.WORKSPACE_KEY][self.HISTORIC_KEY][self.ROOT_KEY]) + historic_data_file = pathlib.Path(config[self.WORKSPACE_KEY][self.HISTORIC_KEY][self.RELATIVE_PATHS_KEY][self.DATA_KEY]) # Attempt to unpack the local historic data file self._historic_data_file = self._historic_workspace.joinpath(historic_data_file) diff --git a/scripts/build/TestImpactAnalysis/tiaf_persistent_storage_s3.py b/scripts/build/TestImpactAnalysis/tiaf_persistent_storage_s3.py index 1a279855ea..074caf73a1 100644 --- a/scripts/build/TestImpactAnalysis/tiaf_persistent_storage_s3.py +++ b/scripts/build/TestImpactAnalysis/tiaf_persistent_storage_s3.py @@ -18,16 +18,23 @@ logger = get_logger(__file__) # Implementation of s3 bucket persistent storage class PersistentStorageS3(PersistentStorage): - def __init__(self, config: dict, suite: str, s3_bucket: str, root_dir: str, branch: str): + + META_KEY = "meta" + BUILD_CONFIG_KEY = "build_config" + + def __init__(self, config: dict, suite: str, commit: str, s3_bucket: str, root_dir: str, branch: str): """ Initializes the persistent storage with the specified s3 bucket. @param config: The runtime config file to obtain the data file paths from. @param suite: The test suite for which the historic data will be obtained for. + @param commit: The commit hash for this build. @param s3_bucket: The s3 bucket to use for storing nd retrieving historic data. + @param root_dir: The root directory to use for the historic data object. + @branch branch: The branch to retrieve the historic data for. """ - super().__init__(config, suite) + super().__init__(config, suite, commit) try: # We store the historic data as compressed JSON @@ -37,8 +44,8 @@ class PersistentStorageS3(PersistentStorage): historic_data_file = f"historic_data.{object_extension}" # The location of the data is in the form // so the build config of each branch gets its own historic data - self._dir = f'{root_dir}/{branch}/{config["meta"]["build_config"]}' - self._historic_data_key = f'{self._dir}/{historic_data_file}' + self._historic_data_dir = f'{root_dir}/{branch}/{config[self.META_KEY][self.BUILD_CONFIG_KEY]}' + self._historic_data_key = f'{self._historic_data_dir}/{historic_data_file}' logger.info(f"Attempting to retrieve historic data for branch '{branch}' at location '{self._historic_data_key}' on bucket '{s3_bucket}'...") self._s3 = boto3.resource("s3") @@ -49,7 +56,7 @@ class PersistentStorageS3(PersistentStorage): logger.info(f"Historic data found for branch '{branch}'.") # Archive the existing object with the name of the existing last commit hash - #archive_key = f"{self._dir}/archive/{self._last_commit_hash}.{object_extension}" + #archive_key = f"{self._historic_data_dir}/archive/{self._last_commit_hash}.{object_extension}" #logger.info(f"Archiving existing historic data to '{archive_key}' in bucket '{self._bucket.name}'...") #self._bucket.copy({"Bucket": self._bucket.name, "Key": self._historic_data_key}, archive_key) #logger.info(f"Archiving complete.") From a1d855a920f2f741a2aff48b4251b84628598e78 Mon Sep 17 00:00:00 2001 From: John Date: Fri, 13 Aug 2021 10:03:09 +0100 Subject: [PATCH 363/803] Invert corner case flag for readability. Signed-off-by: John --- scripts/build/TestImpactAnalysis/tiaf.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/build/TestImpactAnalysis/tiaf.py b/scripts/build/TestImpactAnalysis/tiaf.py index 28de00d6ba..e8faef30e3 100644 --- a/scripts/build/TestImpactAnalysis/tiaf.py +++ b/scripts/build/TestImpactAnalysis/tiaf.py @@ -235,7 +235,7 @@ class TestImpact: # The above results in TIAF being stuck in a state of generating an empty change list (and thus doing no work until another # commit comes in) which is problematic if the commit needs to be re-run for whatever reason so in these conditions we revert # back to a regular test run until another commit comes in - cannot_rerun_with_instrumentation = False + can_rerun_with_instrumentation = True if persistent_storage.has_historic_data: logger.info("Historic data found.") @@ -249,7 +249,7 @@ class TestImpact: else: logger.info(f"This sequence is being re-run before any other changes have come in but there is no useful historic data. A regular sequence will be performed instead.") persistent_storage = None - cannot_rerun_with_instrumentation = True + can_rerun_with_instrumentation = False else: self._attempt_to_generate_change_list() else: @@ -277,7 +277,7 @@ class TestImpact: args.append(f"--changelist={self._change_list_path}") logger.info(f"Change list is set to '{self._change_list_path}'.") else: - if self._is_source_of_truth_branch and not cannot_rerun_with_instrumentation: + if self._is_source_of_truth_branch and can_rerun_with_instrumentation: # Use seed sequence (instrumented all tests) for coverage updating branches so we can generate the coverage bed for future sequences sequence_type = "seed" # We always continue after test failures when seeding to ensure we capture the coverage for all test targets From 99b369198bb9a8b1e62e870b075031033a69b63e Mon Sep 17 00:00:00 2001 From: Kevin Y <88146293+kev197@users.noreply.github.com> Date: Fri, 13 Aug 2021 08:59:38 -0400 Subject: [PATCH 364/803] Typo fix in duplicate project progress window (#2969) Signed-off-by: Kevin Yu --- Code/Tools/ProjectManager/Source/ProjectUtils.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Tools/ProjectManager/Source/ProjectUtils.cpp b/Code/Tools/ProjectManager/Source/ProjectUtils.cpp index 52900f1b28..fb0ea23ece 100644 --- a/Code/Tools/ProjectManager/Source/ProjectUtils.cpp +++ b/Code/Tools/ProjectManager/Source/ProjectUtils.cpp @@ -189,7 +189,7 @@ namespace O3DE::ProjectManager const QString copiedFileSizeString = locale.formattedDataSize(outCopiedFileSize); const QString totalFileSizeString = locale.formattedDataSize(totalSizeToCopy); - progressDialog->setLabelText(QString("Coping file %1 of %2 (%3 of %4) ...").arg(QString::number(outNumCopiedFiles), + progressDialog->setLabelText(QString("Copying file %1 of %2 (%3 of %4) ...").arg(QString::number(outNumCopiedFiles), QString::number(filesToCopyCount), copiedFileSizeString, totalFileSizeString)); From a55cb3e35fa4ac69f6082a101ac7faab66c75a27 Mon Sep 17 00:00:00 2001 From: Alex Peterson <26804013+AMZN-alexpete@users.noreply.github.com> Date: Fri, 13 Aug 2021 09:09:55 -0700 Subject: [PATCH 365/803] Fixed white-bar at bottom of Project Manager screen (#3091) Signed-off-by: AMZN-alexpete <26804013+AMZN-alexpete@users.noreply.github.com> --- Code/Tools/ProjectManager/Source/Application.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Code/Tools/ProjectManager/Source/Application.cpp b/Code/Tools/ProjectManager/Source/Application.cpp index c977698152..9ca107dae5 100644 --- a/Code/Tools/ProjectManager/Source/Application.cpp +++ b/Code/Tools/ProjectManager/Source/Application.cpp @@ -168,9 +168,13 @@ namespace O3DE::ProjectManager // the decoration wrapper is intended to remember window positioning and sizing auto wrapper = new AzQtComponents::WindowDecorationWrapper(); wrapper->setGuest(m_mainWindow.data()); + + // show the main window here to apply the stylesheet before restoring geometry or we + // can end up with empty white space at the bottom of the window until the frame is resized again + m_mainWindow->show(); + wrapper->enableSaveRestoreGeometry("O3DE", "ProjectManager", "mainWindowGeometry"); wrapper->showFromSettings(); - m_mainWindow->show(); qApp->setQuitOnLastWindowClosed(true); From 716089e803645f5b08f2b847d5e8c83d75a831e2 Mon Sep 17 00:00:00 2001 From: kberg-amzn Date: Fri, 13 Aug 2021 09:57:40 -0700 Subject: [PATCH 366/803] More fixes and some temp debugging logs Signed-off-by: kberg-amzn --- .../LocalPredictionPlayerInputComponent.cpp | 59 +++++++------------ .../Source/Components/NetBindComponent.cpp | 6 +- 2 files changed, 25 insertions(+), 40 deletions(-) diff --git a/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp b/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp index ca970de37b..72f5aa8e1c 100644 --- a/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp @@ -66,6 +66,11 @@ namespace Multiplayer } } + inline double ConvertTimeMsToSeconds(AZ::TimeMs value) + { + return static_cast(static_cast(value)) / 1000.0; + } + void LocalPredictionPlayerInputComponent::LocalPredictionPlayerInputComponent::Reflect(AZ::ReflectContext* context) { AZ::SerializeContext* serializeContext = azrtti_cast(context); @@ -151,7 +156,7 @@ namespace Multiplayer } const AZ::TimeMs currentTimeMs = AZ::GetElapsedTimeMs(); - const double clientInputRateSec = static_cast(static_cast(cl_InputRateMs)) / 1000.0; + const double clientInputRateSec = ConvertTimeMsToSeconds(cl_InputRateMs); m_lastInputReceivedTimeMs = currentTimeMs; // Keep track of last inputs received, also allows us to update frame ids @@ -176,8 +181,8 @@ namespace Multiplayer if (m_clientBankedTime < sv_MaxBankTimeWindowSec) { // Client blends from previous frame to target so here we subtract blend factor to get to that state - const float blendFactor = AZStd::min(AZStd::max(0.f, input.GetHostBlendFactor()), 1.f); - const AZ::TimeMs blendMs = AZ::TimeMs(static_cast(static_cast(cl_InputRateMs)) * (1.f - blendFactor)); + const float blendFactor = AZStd::min(AZStd::max(0.f, input.GetHostBlendFactor()), 1.0f); + const AZ::TimeMs blendMs = AZ::TimeMs(static_cast(static_cast(cl_InputRateMs)) * (1.0f - blendFactor)); m_clientBankedTime = AZStd::min(m_clientBankedTime + clientInputRateSec, (double)sv_MaxBankTimeWindowSec); // clamp to boundary { ScopedAlterTime scopedTime(input.GetHostFrameId(), input.GetHostTimeMs() - blendMs, input.GetHostBlendFactor(), invokingConnection->GetConnectionId()); @@ -259,7 +264,7 @@ namespace Multiplayer return; } - const float clientInputRateSec = static_cast(static_cast(cl_InputRateMs)) / 1000.0; + const double clientInputRateSec = ConvertTimeMsToSeconds(cl_InputRateMs); // Copy array so we can modify input ids NetworkInputMigrationVector inputArrayCopy = inputArray; @@ -334,7 +339,7 @@ namespace Multiplayer // If this correction is for a move outside our input history window, just start replaying from the oldest move we have available const uint32_t startReplayIndex = (inputHistorySize > historicalDelta) ? (inputHistorySize - historicalDelta) : 0; - const float clientInputRateSec = static_cast(static_cast(cl_InputRateMs)) / 1000.0; + const double clientInputRateSec = ConvertTimeMsToSeconds(cl_InputRateMs); for (uint32_t replayIndex = startReplayIndex; replayIndex < inputHistorySize; ++replayIndex) { // Reprocess the input for this frame @@ -405,9 +410,9 @@ namespace Multiplayer void LocalPredictionPlayerInputComponentController::UpdateAutonomous(AZ::TimeMs deltaTimeMs) { - const double deltaTime = static_cast(deltaTimeMs) / 1000.0; - const double inputRate = static_cast(static_cast(cl_InputRateMs)) / 1000.0; - const double maxRewindHistory = static_cast(static_cast(cl_MaxRewindHistoryMs)) / 1000.0; + const double deltaTime = ConvertTimeMsToSeconds(deltaTimeMs); + const double clientInputRateSec = ConvertTimeMsToSeconds(cl_InputRateMs); + const double maxRewindHistory = ConvertTimeMsToSeconds(cl_MaxRewindHistoryMs); #ifndef AZ_RELEASE_BUILD m_moveAccumulator += deltaTime * cl_DebugHackTimeMultiplier; @@ -415,13 +420,13 @@ namespace Multiplayer m_moveAccumulator += deltaTime; #endif - const uint32_t maxClientInputs = inputRate > 0.0 ? static_cast(maxRewindHistory / inputRate) : 0; + const uint32_t maxClientInputs = clientInputRateSec > 0.0 ? static_cast(maxRewindHistory / clientInputRateSec) : 0; IMultiplayer* multiplayer = GetMultiplayer(); INetworkTime* networkTime = GetNetworkTime(); - while (m_moveAccumulator >= inputRate) + while (m_moveAccumulator >= clientInputRateSec) { - m_moveAccumulator -= inputRate; + m_moveAccumulator -= clientInputRateSec; ++m_clientInputId; NetworkInputArray inputArray(GetEntityHandle()); @@ -433,10 +438,10 @@ namespace Multiplayer input.SetHostBlendFactor(multiplayer->GetCurrentBlendFactor()); // Allow components to form the input for this frame - GetNetBindComponent()->CreateInput(input, inputRate); + GetNetBindComponent()->CreateInput(input, clientInputRateSec); // Process the input for this frame - GetNetBindComponent()->ProcessInput(input, inputRate); + GetNetBindComponent()->ProcessInput(input, clientInputRateSec); AZLOG(NET_Prediction, "Processed InputId=%d", aznumeric_cast(m_clientInputId)); @@ -444,28 +449,6 @@ namespace Multiplayer AzNetworking::HashSerializer hashSerializer; GetNetBindComponent()->SerializeEntityCorrection(hashSerializer); - // In debug, send the entire client output state to the server to make it easier to debug desync issues - AzNetworking::PacketEncodingBuffer processInputResult; -#ifndef AZ_RELEASE_BUILD - if (cl_EnableDesyncDebugging) - { - AzNetworking::NetworkInputSerializer processInputResultSerializer(processInputResult.GetBuffer(), processInputResult.GetCapacity()); - GetNetBindComponent()->SerializeEntityCorrection(processInputResultSerializer); - processInputResult.Resize(processInputResultSerializer.GetSize()); - } -#endif - - // In debug, send the entire client output state to the server to make it easier to debug desync issues - AzNetworking::PacketEncodingBuffer processInputResult; -#ifndef AZ_RELEASE_BUILD - if (cl_EnableDesyncDebugging) - { - AzNetworking::NetworkInputSerializer processInputResultSerializer(processInputResult.GetBuffer(), static_cast(processInputResult.GetCapacity())); - GetNetBindComponent()->SerializeEntityCorrection(processInputResultSerializer); - processInputResult.Resize(processInputResultSerializer.GetSize()); - } -#endif - // Save this input and discard move history outside our client rewind window m_inputHistory.PushBack(input); while (m_inputHistory.Size() > maxClientInputs) @@ -508,7 +491,7 @@ namespace Multiplayer void LocalPredictionPlayerInputComponentController::UpdateBankedTime(AZ::TimeMs deltaTimeMs) { const double deltaTime = static_cast(deltaTimeMs) / 1000.0; - const double inputRate = static_cast(static_cast(cl_InputRateMs)) / 1000.0; + const double clientInputRateSec = static_cast(static_cast(cl_InputRateMs)) / 1000.0; const double maxRewindHistory = static_cast(static_cast(cl_MaxRewindHistoryMs)) / 1000.0; // Update banked time accumulator @@ -522,8 +505,8 @@ namespace Multiplayer NetworkInput& input = m_lastInputReceived[0]; { - ScopedAlterTime scopedTime(input.GetHostFrameId(), input.GetHostTimeMs(), DefaultBlendFactor, AzNetworking::InvalidConnectionId); - GetNetBindComponent()->ProcessInput(input, inputRate); + ScopedAlterTime scopedTime(input.GetHostFrameId(), input.GetHostTimeMs(), DefaultBlendFactor, GetNetBindComponent()->GetOwningConnectionId()); + GetNetBindComponent()->ProcessInput(input, clientInputRateSec); } AZLOG(NET_Prediction, "Forced InputId=%d", aznumeric_cast(input.GetClientInputId())); diff --git a/Gems/Multiplayer/Code/Source/Components/NetBindComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetBindComponent.cpp index 070655e768..ef1bf8c8e8 100644 --- a/Gems/Multiplayer/Code/Source/Components/NetBindComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/NetBindComponent.cpp @@ -274,8 +274,8 @@ namespace Multiplayer void NetBindComponent::CreateInput(NetworkInput& networkInput, float deltaTime) { - // Only autonomous or authority runs this logic - AZ_Assert(m_netEntityRole == NetEntityRole::Autonomous || m_netEntityRole == NetEntityRole::Authority, "Incorrect network role for input creation"); + // Only autonomous runs this logic + AZ_Assert(IsNetEntityRoleAutonomous(), "Incorrect network role for input creation"); for (MultiplayerComponent* multiplayerComponent : m_multiplayerInputComponentVector) { multiplayerComponent->GetController()->CreateInput(networkInput, deltaTime); @@ -284,6 +284,8 @@ namespace Multiplayer void NetBindComponent::ProcessInput(NetworkInput& networkInput, float deltaTime) { + AZ_TracePrintf("gathers", "Processing input, inputId=%d", static_cast(networkInput.GetClientInputId())); + m_isProcessingInput = true; // Only autonomous and authority runs this logic AZ_Assert((NetworkRoleHasController(m_netEntityRole)), "Incorrect network role for input processing"); From b26107e98df688e1d411c397bdbb6e696d633d45 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 13 Aug 2021 10:07:35 -0700 Subject: [PATCH 367/803] Fix for NameDictionary Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../AzCore/AzCore/Name/NameDictionary.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/Code/Framework/AzCore/AzCore/Name/NameDictionary.cpp b/Code/Framework/AzCore/AzCore/Name/NameDictionary.cpp index c04ae0ea5e..4c4d6b31e8 100644 --- a/Code/Framework/AzCore/AzCore/Name/NameDictionary.cpp +++ b/Code/Framework/AzCore/AzCore/Name/NameDictionary.cpp @@ -185,8 +185,25 @@ namespace AZ return; } + // Get the hash before locking since another thread could be deleting the object within the lock + Internal::NameData::Hash hash = nameData->GetHash(); + AZStd::unique_lock lock(m_sharedMutex); + auto dictIt = m_dictionary.find(hash); + if (dictIt == m_dictionary.end()) + { + // This check is to safeguard around the following scenario + // T1, gets into TryReleaseName + // T2 gets into MakeName, acquires the lock, returns a new Name that increments the counter + // T2 deletes the Name decrements the counter, gets into TryReleaseName + // T1 gets the lock, goes to the compare_exchange if and has a counter of 0, deletes + // Then T2 continues, gets the lock and crashes because nameData was deleted + return; + } + + nameData = dictIt->second; // restore the pointer in case the intrusive ptr was already assigned by other thread + // Check m_hashCollision again inside the m_sharedMutex because a new collision could have happened // on another thread before taking the lock. if (nameData->m_hashCollision) From 9571a15769fc88c2713ca5ea6b834523b525c08e Mon Sep 17 00:00:00 2001 From: mrieggeramzn <61609885+mrieggeramzn@users.noreply.github.com> Date: Fri, 13 Aug 2021 11:36:58 -0700 Subject: [PATCH 368/803] Atom/mriegger/explicit set pcf address mode (#3061) * Explicit setting the addressing mode for the pcf shadowing * Explicitly setting addressing mode for sampler --- .../Assets/ShaderResourceGroups/CoreLights/SceneSrg.azsli | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Gems/Atom/Feature/Common/Assets/ShaderResourceGroups/CoreLights/SceneSrg.azsli b/Gems/Atom/Feature/Common/Assets/ShaderResourceGroups/CoreLights/SceneSrg.azsli index d1a916dfac..67ccedd720 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderResourceGroups/CoreLights/SceneSrg.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderResourceGroups/CoreLights/SceneSrg.azsli @@ -30,6 +30,9 @@ partial ShaderResourceGroup SceneSrg // Hardware PCF comparison sampler that is used when sampling the shadow maps SamplerComparisonState m_hwPcfSampler { + AddressU = Clamp; + AddressV = Clamp; + AddressW = Clamp; MagFilter = Linear; MinFilter = Linear; MipFilter = Point; From cd5081a7c3006d72b88dc196ffac0b3a66049673 Mon Sep 17 00:00:00 2001 From: michabr <82236305+michabr@users.noreply.github.com> Date: Fri, 13 Aug 2021 13:31:46 -0700 Subject: [PATCH 369/803] Fix byte alignment issue for index/vertex buffers (#3110) * Fix byte alignment issue for index/vertex buffers * Remove default alignment value when getting dynamic buffer Signed-off-by: abrmich --- .../Code/Source/AuxGeom/DynamicPrimitiveProcessor.cpp | 4 ++-- .../Include/Atom/RPI.Public/DynamicDraw/DynamicBuffer.h | 4 ++-- .../Atom/RPI.Public/DynamicDraw/DynamicDrawInterface.h | 2 +- .../Include/Atom/RPI.Public/DynamicDraw/DynamicDrawSystem.h | 2 +- .../Source/RPI.Public/DynamicDraw/DynamicDrawContext.cpp | 6 +++--- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Gems/Atom/Feature/Common/Code/Source/AuxGeom/DynamicPrimitiveProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/AuxGeom/DynamicPrimitiveProcessor.cpp index 3a7d50d2a9..10d1bdc2c6 100644 --- a/Gems/Atom/Feature/Common/Code/Source/AuxGeom/DynamicPrimitiveProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/AuxGeom/DynamicPrimitiveProcessor.cpp @@ -196,7 +196,7 @@ namespace AZ { const size_t sourceByteSize = source.size() * sizeof(AuxGeomIndex); - RHI::Ptr dynamicBuffer = RPI::DynamicDrawInterface::Get()->GetDynamicBuffer(static_cast(sourceByteSize)); + RHI::Ptr dynamicBuffer = RPI::DynamicDrawInterface::Get()->GetDynamicBuffer(static_cast(sourceByteSize), RHI::Alignment::InputAssembly); if (!dynamicBuffer) { AZ_WarningOnce("AuxGeom", false, "Failed to allocate dynamic buffer of size %d.", sourceByteSize); @@ -211,7 +211,7 @@ namespace AZ { const size_t sourceByteSize = source.size() * sizeof(AuxGeomDynamicVertex); - RHI::Ptr dynamicBuffer = RPI::DynamicDrawInterface::Get()->GetDynamicBuffer(static_cast(sourceByteSize)); + RHI::Ptr dynamicBuffer = RPI::DynamicDrawInterface::Get()->GetDynamicBuffer(static_cast(sourceByteSize), RHI::Alignment::InputAssembly); if (!dynamicBuffer) { AZ_WarningOnce("AuxGeom", false, "Failed to allocate dynamic buffer of size %d.", sourceByteSize); diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/DynamicDraw/DynamicBuffer.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/DynamicDraw/DynamicBuffer.h index 0c13efbd4b..c50ba2dc9b 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/DynamicDraw/DynamicBuffer.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/DynamicDraw/DynamicBuffer.h @@ -25,8 +25,8 @@ namespace AZ //! DynamicBuffers are allocated by DynamicBufferAllocator. Check the description of DynamicBufferAllocator class for detail. //! The typical usage: //! // For every frame - //! auto buffer = DynamicDrawInterface::Get()->GetDynamicBuffer(size); - //! if (buffer) // the buffer could be empty if the allocation failed.e + //! auto buffer = DynamicDrawInterface::Get()->GetDynamicBuffer(size, RHI::Alignment::InputAssembly); + //! if (buffer) // the buffer could be empty if the allocation failed. //! { //! // write data to the buffer //! buffer->Write(data, size); diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/DynamicDraw/DynamicDrawInterface.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/DynamicDraw/DynamicDrawInterface.h index cc2125af95..23a93481fd 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/DynamicDraw/DynamicDrawInterface.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/DynamicDraw/DynamicDrawInterface.h @@ -54,7 +54,7 @@ namespace AZ //! Get a DynamicBuffer from DynamicDrawSystem. //! The returned buffer will be invalidated every time the RPISystem's RenderTick is called - virtual RHI::Ptr GetDynamicBuffer(uint32_t size, uint32_t alignment = 1) = 0; + virtual RHI::Ptr GetDynamicBuffer(uint32_t size, uint32_t alignment) = 0; //! Draw a geometry to a scene with a given material virtual void DrawGeometry(Data::Instance material, const GeometryData& geometry, ScenePtr scene) = 0; diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/DynamicDraw/DynamicDrawSystem.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/DynamicDraw/DynamicDrawSystem.h index 4210bca1db..4a00566632 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/DynamicDraw/DynamicDrawSystem.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/DynamicDraw/DynamicDrawSystem.h @@ -32,7 +32,7 @@ namespace AZ // DynamicDrawInterface overrides... RHI::Ptr CreateDynamicDrawContext() override; - RHI::Ptr GetDynamicBuffer(uint32_t size, uint32_t alignment = 1) override; + RHI::Ptr GetDynamicBuffer(uint32_t size, uint32_t alignment) override; void DrawGeometry(Data::Instance material, const GeometryData& geometry, ScenePtr scene) override; void AddDrawPacket(Scene* scene, AZStd::unique_ptr drawPacket) override; AZStd::vector GetDrawListsForPass(const RasterPass* pass) override; diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/DynamicDraw/DynamicDrawContext.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/DynamicDraw/DynamicDrawContext.cpp index 7ca2bdcee5..29f57d6e0f 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/DynamicDraw/DynamicDrawContext.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/DynamicDraw/DynamicDrawContext.cpp @@ -474,10 +474,10 @@ namespace AZ // Get dynamic buffers for vertex and index buffer. Skip draw if failed to allocate buffers uint32_t vertexDataSize = vertexCount * m_perVertexDataSize; RHI::Ptr vertexBuffer; - vertexBuffer = DynamicDrawInterface::Get()->GetDynamicBuffer(vertexDataSize); + vertexBuffer = DynamicDrawInterface::Get()->GetDynamicBuffer(vertexDataSize, RHI::Alignment::InputAssembly); uint32_t indexDataSize = indexCount * RHI::GetIndexFormatSize(indexFormat); - RHI::Ptr indexBuffer = DynamicDrawInterface::Get()->GetDynamicBuffer(indexDataSize); + RHI::Ptr indexBuffer = DynamicDrawInterface::Get()->GetDynamicBuffer(indexDataSize, RHI::Alignment::InputAssembly); if (indexBuffer == nullptr || vertexBuffer == nullptr) { @@ -572,7 +572,7 @@ namespace AZ // Get dynamic buffers for vertex and index buffer. Skip draw if failed to allocate buffers uint32_t vertexDataSize = vertexCount * m_perVertexDataSize; RHI::Ptr vertexBuffer; - vertexBuffer = DynamicDrawInterface::Get()->GetDynamicBuffer(vertexDataSize); + vertexBuffer = DynamicDrawInterface::Get()->GetDynamicBuffer(vertexDataSize, RHI::Alignment::InputAssembly); if (vertexBuffer == nullptr) { From 80aa4c42ce8082de578c8d3a78b1a95908aeea08 Mon Sep 17 00:00:00 2001 From: evanchia-ly-sdets <80914607+evanchia-ly-sdets@users.noreply.github.com> Date: Fri, 13 Aug 2021 13:41:56 -0700 Subject: [PATCH 370/803] moving smoke test to sandbox suite to investigate failures (#3109) Signed-off-by: evanchia --- .../Gem/PythonTests/smoke/CMakeLists.txt | 12 ++++++++++++ .../smoke/test_RemoteConsole_CPULoadLevel_Works.py | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/AutomatedTesting/Gem/PythonTests/smoke/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/smoke/CMakeLists.txt index 3fc4f3db0e..5374b0d318 100644 --- a/AutomatedTesting/Gem/PythonTests/smoke/CMakeLists.txt +++ b/AutomatedTesting/Gem/PythonTests/smoke/CMakeLists.txt @@ -73,5 +73,17 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) AutomatedTesting.GameLauncher AutomatedTesting.Assets ) + ly_add_pytest( + NAME AutomatedTesting::LoadLevelCPU + TEST_SUITE sandbox + PATH ${CMAKE_CURRENT_LIST_DIR}/test_RemoteConsole_CPULoadLevel_Works.py + TIMEOUT 100 + RUNTIME_DEPENDENCIES + AZ::AssetProcessor + AZ::PythonBindingsExample + Legacy::Editor + AutomatedTesting.GameLauncher + AutomatedTesting.Assets + ) endif() diff --git a/AutomatedTesting/Gem/PythonTests/smoke/test_RemoteConsole_CPULoadLevel_Works.py b/AutomatedTesting/Gem/PythonTests/smoke/test_RemoteConsole_CPULoadLevel_Works.py index 6522514f2f..701dcfab10 100644 --- a/AutomatedTesting/Gem/PythonTests/smoke/test_RemoteConsole_CPULoadLevel_Works.py +++ b/AutomatedTesting/Gem/PythonTests/smoke/test_RemoteConsole_CPULoadLevel_Works.py @@ -24,7 +24,7 @@ from ly_remote_console.remote_console_commands import ( @pytest.mark.parametrize("launcher_platform", ["windows"]) @pytest.mark.parametrize("project", ["AutomatedTesting"]) @pytest.mark.parametrize("level", ["Simple"]) -@pytest.mark.SUITE_smoke +@pytest.mark.SUITE_sandbox class TestRemoteConsoleLoadLevelWorks(object): @pytest.fixture def remote_console_instance(self, request): From 63a78b906ad04e3fc19d0dfb570f5e7173303e11 Mon Sep 17 00:00:00 2001 From: jromnoa <80134229+jromnoa@users.noreply.github.com> Date: Fri, 13 Aug 2021 14:16:34 -0700 Subject: [PATCH 371/803] fixes light component GPU test AttributeError (I forgot to update atom_component_helper to atom_constants since constants were split from hydra functions into a new module) (#3115) Signed-off-by: jromnoa --- .../hydra_GPUTest_LightComponent.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_GPUTest_LightComponent.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_GPUTest_LightComponent.py index 08f921e68b..8063445608 100644 --- a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_GPUTest_LightComponent.py +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_GPUTest_LightComponent.py @@ -23,8 +23,7 @@ import azlmbr.legacy.general as general sys.path.append(os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Gem", "PythonTests")) import editor_python_test_tools.hydra_editor_utils as hydra -from atom_renderer.atom_utils import screenshot_utils -from atom_renderer.atom_utils import atom_component_helper +from atom_renderer.atom_utils import atom_component_helper, atom_constants, screenshot_utils from editor_python_test_tools.editor_test_helper import EditorTestHelper helper = EditorTestHelper(log_prefix="Atom_EditorTestHelper") @@ -92,7 +91,7 @@ def area_light_test(): 'SetComponentProperty', light_component_id_pair, LIGHT_TYPE_PROPERTY, - atom_component_helper.LIGHT_TYPES['capsule'] + atom_constants.LIGHT_TYPES['capsule'] ) # Update color and take screenshot in game mode @@ -118,7 +117,7 @@ def area_light_test(): 'SetComponentProperty', light_component_id_pair, LIGHT_TYPE_PROPERTY, - atom_component_helper.LIGHT_TYPES['spot_disk'] + atom_constants.LIGHT_TYPES['spot_disk'] ) area_light_rotation = math.Vector3(DEGREE_RADIAN_FACTOR * 90.0, 0.0, 0.0) azlmbr.components.TransformBus(azlmbr.bus.Event, "SetLocalRotation", area_light.id, area_light_rotation) @@ -131,7 +130,7 @@ def area_light_test(): 'SetComponentProperty', light_component_id_pair, LIGHT_TYPE_PROPERTY, - atom_component_helper.LIGHT_TYPES['sphere'] + atom_constants.LIGHT_TYPES['sphere'] ) general.idle_wait(1.0) screenshot_utils.take_screenshot_game_mode("AreaLight_5", area_light_entity_name) @@ -210,7 +209,7 @@ def spot_light_test(): 'SetComponentProperty', light_component_type, LIGHT_TYPE_PROPERTY, - atom_component_helper.LIGHT_TYPES['spot_disk'] + atom_constants.LIGHT_TYPES['spot_disk'] ) general.idle_wait(1.0) From 906042359243d215cd05303f732a3422a8fa20a1 Mon Sep 17 00:00:00 2001 From: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> Date: Fri, 13 Aug 2021 16:20:08 -0500 Subject: [PATCH 372/803] Settings registry notification deadlock fix (#3065) * Added a StealHandlers function to AZ Event The StealHandlers function is able to take all the handlers from an AZ Event parameter and register them with the current AZ Event This allows stealing handlers from expiring AZ Events, which is useful for a lock and swap algorithm for thread safety. 1. Lock persistent AZ::Event 2. Swap persistent AZ::Event with local AZ::Event 3. Unlock persistent AZ::Event - Other threads can now add to this AZ::Event 4. Invoke handlers from local AZ::Event 5. Relock persistent AZ::Event 5. Swap local AZ::Event with persistent AZ::Event 6. Local AZ::Event now contains handlers that were added when the lock was free 7. Persistent AZ::Event now steals from local AZ::Event 8. Unlock persistent AZ::Event Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Separated SettingRegistry update/query mutex from Notifier update mutex The Settings Registry update/query mutex is also better scoped to reduce the amount of lock time. The Notifier mutex being separate allows the Settings Registry to signal a notification event without being under any mutex, by locking and swapping the notifier event with a local instance Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Renamed StealHandlers function to ClaimHandlers Replaced decltype keywords in ClaimHandlers to auto Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> --- Code/Framework/AzCore/AzCore/EBus/Event.h | 6 + Code/Framework/AzCore/AzCore/EBus/Event.inl | 26 ++++ .../AzCore/Settings/SettingsRegistryImpl.cpp | 111 +++++++++++++----- .../AzCore/Settings/SettingsRegistryImpl.h | 5 +- Code/Framework/AzCore/Tests/EventTests.cpp | 31 +++++ 5 files changed, 151 insertions(+), 28 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/EBus/Event.h b/Code/Framework/AzCore/AzCore/EBus/Event.h index b3c29b63a2..00310f4dbc 100644 --- a/Code/Framework/AzCore/AzCore/EBus/Event.h +++ b/Code/Framework/AzCore/AzCore/EBus/Event.h @@ -58,6 +58,12 @@ namespace AZ Event& operator=(Event&& rhs); + //! Take the handlers registered with the other event + //! and move them to this event. The other will event + //! will be cleared after call + //! @param other event to move handlers + Event& ClaimHandlers(Event&& other); + //! Returns true if at least one handler is connected to this event. bool HasHandlerConnected() const; diff --git a/Code/Framework/AzCore/AzCore/EBus/Event.inl b/Code/Framework/AzCore/AzCore/EBus/Event.inl index dfb1781991..ffa8c8b9c5 100644 --- a/Code/Framework/AzCore/AzCore/EBus/Event.inl +++ b/Code/Framework/AzCore/AzCore/EBus/Event.inl @@ -207,6 +207,32 @@ namespace AZ } + template + auto Event::ClaimHandlers(Event&& other) -> Event& + { + auto handlers = AZStd::move(other.m_handlers); + auto addList = AZStd::move(other.m_addList); + other.m_freeList = {}; + other.m_updating = false; + + AZStd::array handlerContainers{ &handlers, &addList }; + for (AZStd::vector* handlerList : handlerContainers) + { + for (Handler* handler : *handlerList) + { + if (handler != nullptr) + { + handler->m_index = 0; + handler->m_event = this; + Connect(*handler); + } + } + } + + return *this; + } + + template bool Event::HasHandlerConnected() const { diff --git a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryImpl.cpp b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryImpl.cpp index 0882e1b7f2..3dc2d4145e 100644 --- a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryImpl.cpp +++ b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryImpl.cpp @@ -20,7 +20,7 @@ namespace AZ { template - bool SettingsRegistryImpl::SetValueInternal(AZStd::string_view path, T value, SettingsRegistryInterface::Type type) + bool SettingsRegistryImpl::SetValueInternal(AZStd::string_view path, T value) { if (path.empty()) { @@ -56,7 +56,6 @@ namespace AZ static_assert(!AZStd::is_same_v, "SettingsRegistryImpl::SetValueInternal called with unsupported type."); } - m_notifiers.Signal(path, type); return true; } return false; @@ -157,11 +156,11 @@ namespace AZ // Setting to empty string to prevent assert path = ""; } - AZStd::scoped_lock lock(m_settingMutex); rapidjson::Pointer pointer(path.data(), path.length()); if (pointer.IsValid()) { + AZStd::scoped_lock lock(m_settingMutex); const rapidjson::Value* value = pointer.Get(m_settings); if (value) { @@ -207,7 +206,7 @@ namespace AZ { NotifyEventHandler notifyHandler{ callback }; { - AZStd::scoped_lock lock(m_settingMutex); + AZStd::scoped_lock lock(m_notifierMutex); notifyHandler.Connect(m_notifiers); } return notifyHandler; @@ -217,7 +216,7 @@ namespace AZ { NotifyEventHandler notifyHandler{ AZStd::move(callback) }; { - AZStd::scoped_lock lock(m_settingMutex); + AZStd::scoped_lock lock(m_notifierMutex); notifyHandler.Connect(m_notifiers); } return notifyHandler; @@ -225,10 +224,35 @@ namespace AZ void SettingsRegistryImpl::ClearNotifiers() { - AZStd::scoped_lock lock(m_settingMutex); + AZStd::scoped_lock lock(m_notifierMutex); m_notifiers.DisconnectAllHandlers(); } + void SettingsRegistryImpl::SignalNotifier(AZStd::string_view jsonPath, Type type) + { + // Move the Notifier AZ::Event to a local AZ::Event in order to allow + // the notifier handlers to be signaled outside of the notifier mutex + // This allows other threads to register notifiers while this thread + // is invoking the handlers + decltype(m_notifiers) localNotifierEvent; + { + AZStd::scoped_lock lock(m_notifierMutex); + localNotifierEvent = AZStd::move(m_notifiers); + } + + localNotifierEvent.Signal(jsonPath, type); + + { + // Swap the local handlers with the current m_notifiers which + // will contain any handlers added during the signaling of the + // local event + AZStd::scoped_lock lock(m_notifierMutex); + AZStd::swap(m_notifiers, localNotifierEvent); + // Append any added handlers to the m_notifier structure + m_notifiers.ClaimHandlers(AZStd::move(localNotifierEvent)); + } + } + SettingsRegistryInterface::Type SettingsRegistryImpl::GetType(AZStd::string_view path) const { if (path.empty()) @@ -239,11 +263,11 @@ namespace AZ path = ""; } - AZStd::scoped_lock lock(m_settingMutex); rapidjson::Pointer pointer(path.data(), path.length()); if (pointer.IsValid()) { + AZStd::scoped_lock lock(m_settingMutex); const rapidjson::Value* value = pointer.Get(m_settings); if (value) { @@ -316,11 +340,11 @@ namespace AZ // Setting to empty string to prevent assert path = ""; } - AZStd::scoped_lock lock(m_settingMutex); rapidjson::Pointer pointer(path.data(), path.length()); if (pointer.IsValid()) { + AZStd::scoped_lock lock(m_settingMutex); const rapidjson::Value* value = pointer.Get(m_settings); if (value) { @@ -333,32 +357,52 @@ namespace AZ bool SettingsRegistryImpl::Set(AZStd::string_view path, bool value) { - AZStd::scoped_lock lock(m_settingMutex); - return SetValueInternal(path, value, Type::Boolean); + if (AZStd::scoped_lock lock(m_settingMutex); !SetValueInternal(path, value)) + { + return false; + } + SignalNotifier(path, Type::Boolean); + return true; } bool SettingsRegistryImpl::Set(AZStd::string_view path, s64 value) { - AZStd::scoped_lock lock(m_settingMutex); - return SetValueInternal(path, value, Type::Integer); + if (AZStd::scoped_lock lock(m_settingMutex); !SetValueInternal(path, value)) + { + return false; + } + SignalNotifier(path, Type::Integer); + return true; } bool SettingsRegistryImpl::Set(AZStd::string_view path, u64 value) { - AZStd::scoped_lock lock(m_settingMutex); - return SetValueInternal(path, value, Type::Integer); + if (AZStd::scoped_lock lock(m_settingMutex); !SetValueInternal(path, value)) + { + return false; + } + SignalNotifier(path, Type::Integer); + return true; } bool SettingsRegistryImpl::Set(AZStd::string_view path, double value) { - AZStd::scoped_lock lock(m_settingMutex); - return SetValueInternal(path, value, Type::FloatingPoint); + if (AZStd::scoped_lock lock(m_settingMutex); !SetValueInternal(path, value)) + { + return false; + } + SignalNotifier(path, Type::FloatingPoint); + return true; } bool SettingsRegistryImpl::Set(AZStd::string_view path, AZStd::string_view value) { - AZStd::scoped_lock lock(m_settingMutex); - return SetValueInternal(path, value, Type::String); + if (AZStd::scoped_lock lock(m_settingMutex); !SetValueInternal(path, value)) + { + return false; + } + SignalNotifier(path, Type::String); + return true; } bool SettingsRegistryImpl::Set(AZStd::string_view path, const char* value) @@ -376,7 +420,6 @@ namespace AZ path = ""; } - AZStd::scoped_lock lock(m_settingMutex); rapidjson::Pointer pointer(path.data(), path.length()); if (pointer.IsValid()) @@ -386,9 +429,10 @@ namespace AZ value, nullptr, valueTypeID, m_serializationSettings); if (jsonResult.GetProcessing() != JsonSerializationResult::Processing::Halted) { + AZStd::scoped_lock lock(m_settingMutex); rapidjson::Value& setting = pointer.Create(m_settings, m_settings.GetAllocator()); setting = AZStd::move(store); - m_notifiers.Signal(path, Type::Object); + SignalNotifier(path, Type::Object); return true; } } @@ -404,13 +448,13 @@ namespace AZ // Setting to empty string to prevent assert path = ""; } - AZStd::scoped_lock lock(m_settingMutex); rapidjson::Pointer pointerPath(path.data(), path.size()); if (!pointerPath.IsValid()) { return false; } + AZStd::scoped_lock lock(m_settingMutex); return pointerPath.Erase(m_settings); } @@ -540,7 +584,7 @@ namespace AZ return false; } - m_notifiers.Signal("", Type::Object); + SignalNotifier("", Type::Object); return true; } @@ -562,8 +606,6 @@ namespace AZ scratchBuffer = &buffer; } - AZStd::scoped_lock lock(m_settingMutex); - bool result = false; if (path[path.length()] == 0) { @@ -577,6 +619,8 @@ namespace AZ R"(Path "%.*s" is too long. Either make sure that the provided path is terminated or use a shorter path.)", static_cast(path.length()), path.data()); Pointer pointer(AZ_SETTINGS_REGISTRY_HISTORY_KEY "/-"); + + AZStd::scoped_lock lock(m_settingMutex); Value pathValue(path.data(), aznumeric_caster(path.length()), m_settings.GetAllocator()); pointer.Create(m_settings, m_settings.GetAllocator()).SetObject() .AddMember(StringRef("Error"), StringRef("Unable to read registry file."), m_settings.GetAllocator()) @@ -622,6 +666,7 @@ namespace AZ { AZ_Error("Settings Registry", false, "Folder path for the Setting Registry is too long: %.*s", static_cast(path.size()), path.data()); + AZStd::scoped_lock lock(m_settingMutex); pointer.Create(m_settings, m_settings.GetAllocator()).SetObject() .AddMember(StringRef("Error"), StringRef("Folder path for the Setting Registry is too long."), m_settings.GetAllocator()) .AddMember(StringRef("Path"), Value(path.data(), aznumeric_caster(path.length()), m_settings.GetAllocator()), m_settings.GetAllocator()); @@ -659,6 +704,7 @@ namespace AZ if (fileList.size() >= MaxRegistryFolderEntries) { AZ_Error("Settings Registry", false, "Too many files in registry folder."); + AZStd::scoped_lock lock(m_settingMutex); pointer.Create(m_settings, m_settings.GetAllocator()).SetObject() .AddMember(StringRef("Error"), StringRef("Too many files in registry folder."), m_settings.GetAllocator()) .AddMember(StringRef("Path"), Value(folderPath.c_str(), aznumeric_caster(folderPath.size()), m_settings.GetAllocator()), m_settings.GetAllocator()) @@ -678,7 +724,6 @@ namespace AZ SystemFile::FindFiles(folderPath.c_str(), callback); - AZStd::scoped_lock lock(m_settingMutex); if (!platform.empty()) { // Move the folderPath prefix back to the supplied path before the wildcard @@ -696,6 +741,7 @@ namespace AZ if (fileList.size() >= MaxRegistryFolderEntries) { AZ_Error("Settings Registry", false, "Too many files in registry folder."); + AZStd::scoped_lock lock(m_settingMutex); pointer.Create(m_settings, m_settings.GetAllocator()).SetObject() .AddMember(StringRef("Error"), StringRef("Too many files in registry folder."), m_settings.GetAllocator()) .AddMember(StringRef("Path"), Value(folderPath.c_str(), aznumeric_caster(folderPath.size()), m_settings.GetAllocator()), m_settings.GetAllocator()) @@ -923,6 +969,8 @@ namespace AZ collisionFound = true; AZ_Error("Settings Registry", false, R"(Two registry files in "%.*s" point to the same specialization: "%s" and "%s")", AZ_STRING_ARG(folderPath), lhs.m_relativePath.c_str(), rhs.m_relativePath.c_str()); + + AZStd::scoped_lock lock(m_settingMutex); historyPointer.Create(m_settings, m_settings.GetAllocator()).SetObject() .AddMember(StringRef("Error"), StringRef("Too many files in registry folder."), m_settings.GetAllocator()) .AddMember(StringRef("Path"), @@ -1077,6 +1125,7 @@ namespace AZ } } + AZStd::scoped_lock lock(m_settingMutex); pointer.Create(m_settings, m_settings.GetAllocator()).SetObject() .AddMember(StringRef("Error"), StringRef("Unable to parse registry file due to invalid json."), m_settings.GetAllocator()) .AddMember(StringRef("Path"), Value(path, m_settings.GetAllocator()), m_settings.GetAllocator()) @@ -1102,6 +1151,7 @@ namespace AZ R"(To merge the supplied settings registry file, the settings within it must be placed within a JSON Object '{}')" R"( in order to allow moving of its fields using the root-key as an anchor.)", path); + AZStd::scoped_lock lock(m_settingMutex); pointer.Create(m_settings, m_settings.GetAllocator()).SetObject() .AddMember(StringRef("Error"), StringRef("Cannot merge registry file with a root which is not a JSON Object," " an empty root key and a merge approach of JsonMergePatch. Otherwise the Settings Registry would be overridden." @@ -1118,6 +1168,7 @@ namespace AZ JsonSerializationResult::ResultCode mergeResult(JsonSerializationResult::Tasks::Merge); if (rootKey.empty()) { + AZStd::scoped_lock lock(m_settingMutex); mergeResult = JsonSerialization::ApplyPatch(m_settings, m_settings.GetAllocator(), jsonPatch, mergeApproach, m_applyPatchSettings); } else @@ -1125,6 +1176,7 @@ namespace AZ Pointer root(rootKey.data(), rootKey.length()); if (root.IsValid()) { + AZStd::scoped_lock lock(m_settingMutex); Value& rootValue = root.Create(m_settings, m_settings.GetAllocator()); mergeResult = JsonSerialization::ApplyPatch(rootValue, m_settings.GetAllocator(), jsonPatch, mergeApproach, m_applyPatchSettings); } @@ -1132,6 +1184,7 @@ namespace AZ { AZ_Error("Settings Registry", false, R"(Failed to root path "%.*s" is invalid.)", aznumeric_cast(rootKey.length()), rootKey.data()); + AZStd::scoped_lock lock(m_settingMutex); pointer.Create(m_settings, m_settings.GetAllocator()).SetObject() .AddMember(StringRef("Error"), StringRef("Invalid root key."), m_settings.GetAllocator()) .AddMember(StringRef("Path"), Value(path, m_settings.GetAllocator()), m_settings.GetAllocator()); @@ -1141,15 +1194,19 @@ namespace AZ if (mergeResult.GetProcessing() != JsonSerializationResult::Processing::Completed) { AZ_Error("Settings Registry", false, R"(Failed to fully merge registry file "%s".)", path); + AZStd::scoped_lock lock(m_settingMutex); pointer.Create(m_settings, m_settings.GetAllocator()).SetObject() .AddMember(StringRef("Error"), StringRef("Failed to fully merge registry file."), m_settings.GetAllocator()) .AddMember(StringRef("Path"), Value(path, m_settings.GetAllocator()), m_settings.GetAllocator()); return false; } - pointer.Create(m_settings, m_settings.GetAllocator()).SetString(path, m_settings.GetAllocator()); + { + AZStd::scoped_lock lock(m_settingMutex); + pointer.Create(m_settings, m_settings.GetAllocator()).SetString(path, m_settings.GetAllocator()); + } - m_notifiers.Signal("", Type::Object); + SignalNotifier("", Type::Object); return true; } diff --git a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryImpl.h b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryImpl.h index 41a628cf22..4126e19322 100644 --- a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryImpl.h +++ b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryImpl.h @@ -89,7 +89,7 @@ namespace AZ using RegistryFileList = AZStd::fixed_vector; template - bool SetValueInternal(AZStd::string_view path, T value, SettingsRegistryInterface::Type type); + bool SetValueInternal(AZStd::string_view path, T value); template bool GetValueInternal(T& result, AZStd::string_view path) const; VisitResponse Visit(Visitor& visitor, StackedString& path, AZStd::string_view valueName, @@ -100,8 +100,11 @@ namespace AZ const rapidjson::Pointer& historyPointer, AZStd::string_view folderPath); bool ExtractFileDescription(RegistryFile& output, const char* filename, const Specializations& specializations); bool MergeSettingsFileInternal(const char* path, Format format, AZStd::string_view rootKey, AZStd::vector& scratchBuffer); + + void SignalNotifier(AZStd::string_view jsonPath, Type type); mutable AZStd::recursive_mutex m_settingMutex; + mutable AZStd::recursive_mutex m_notifierMutex; NotifyEvent m_notifiers; rapidjson::Document m_settings; JsonSerializerSettings m_serializationSettings; diff --git a/Code/Framework/AzCore/Tests/EventTests.cpp b/Code/Framework/AzCore/Tests/EventTests.cpp index 358c1a62ae..aaa70344e7 100644 --- a/Code/Framework/AzCore/Tests/EventTests.cpp +++ b/Code/Framework/AzCore/Tests/EventTests.cpp @@ -240,6 +240,37 @@ namespace UnitTest static_assert(!AZStd::is_copy_assignable_v>, "AZ Events should not be copy assignable"); } + TEST_F(EventTests, TestClaimHandlers_TakesAllSourceHandlers) + { + AZ::Event<> testEvent1; + AZ::Event<> testEvent2; + + int32_t handlerInvokeCount{}; + auto handlerCallback = [&handlerInvokeCount]() + { + ++handlerInvokeCount; + }; + AZ::Event<>::Handler testHandler1(handlerCallback); + AZ::Event<>::Handler testHandler2(handlerCallback); + + testHandler1.Connect(testEvent1); + testHandler2.Connect(testEvent2); + + EXPECT_TRUE(testEvent1.HasHandlerConnected()); + EXPECT_TRUE(testEvent2.HasHandlerConnected()); + + testEvent1.ClaimHandlers(AZStd::move(testEvent2)); + EXPECT_TRUE(testEvent1.HasHandlerConnected()); + EXPECT_FALSE(testEvent2.HasHandlerConnected()); + + // testEvent1 should have both handlers + testEvent1.Signal(); + EXPECT_EQ(2, handlerInvokeCount); + // testEvent2 should have neither of the handlers + testEvent2.Signal(); + EXPECT_EQ(2, handlerInvokeCount); + } + TEST_F(EventTests, HandlerMoveAssignment_ProperlyDisconnectsFromOldEvent) { AZ::Event<> testEvent1; From 093a03cfbc98993d799883d9426ef3a7fda1a6a8 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 13 Aug 2021 15:58:01 -0700 Subject: [PATCH 373/803] fix for non-unity mac build (#3118) Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Editor/Util/StringHelpers.cpp | 2 -- Code/Editor/Util/StringHelpers.h | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/Code/Editor/Util/StringHelpers.cpp b/Code/Editor/Util/StringHelpers.cpp index 6c819270bd..d0999d6ae2 100644 --- a/Code/Editor/Util/StringHelpers.cpp +++ b/Code/Editor/Util/StringHelpers.cpp @@ -10,8 +10,6 @@ #include "StringHelpers.h" #include "Util.h" -#include - int StringHelpers::CompareIgnoreCase(const AZStd::string& str0, const AZStd::string& str1) { const size_t minLength = Util::getMin(str0.length(), str1.length()); diff --git a/Code/Editor/Util/StringHelpers.h b/Code/Editor/Util/StringHelpers.h index b5c84d7fe3..8a0883b24c 100644 --- a/Code/Editor/Util/StringHelpers.h +++ b/Code/Editor/Util/StringHelpers.h @@ -12,7 +12,7 @@ #pragma once #include -#include +#include namespace StringHelpers { From 693b205747809ab0b6804fdd6975654e37c17cc4 Mon Sep 17 00:00:00 2001 From: kberg-amzn Date: Fri, 13 Aug 2021 16:56:27 -0700 Subject: [PATCH 374/803] Removing debug code, and fixing vector/array not respecting replication record dirty bits Signed-off-by: kberg-amzn --- .../Code/Source/AutoGen/AutoComponent_Source.jinja | 11 +++++------ .../Code/Source/Components/NetBindComponent.cpp | 2 -- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja index d2be2f682a..56ab828ffe 100644 --- a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja +++ b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja @@ -643,16 +643,15 @@ bool {{ ClassName }}::Serialize{{ AutoComponentMacros.GetNetPropertiesSetName(Re const uint32_t lastBit = static_cast({{ AutoComponentMacros.GetNetPropertiesQualifiedPropertyDirtyEnum(Component.attrib['Name'], ReplicateFrom, ReplicateTo, Property, 'End') }}); {% endif %} -{% if Property.attrib['IsRewindable']|booleanTrue %} AzNetworking::FixedSizeBitsetView deltaRecord(replicationRecord.m_{{ LowerFirst(AutoComponentMacros.GetNetPropertiesSetName(ReplicateFrom, ReplicateTo)) }}, firstBit, lastBit - firstBit + 1); - m_{{ LowerFirst(Property.attrib['Name']) }}.Serialize(serializer, deltaRecord); -{% else %} + if (deltaRecord.AnySet()) + { {% if Property.attrib['Container'] == 'Vector' %} - serializer.Serialize>(m_{{ LowerFirst(Property.attrib['Name']) }}, "{{ LowerFirst(Property.attrib['Name']) }}"); + serializer.Serialize>(m_{{ LowerFirst(Property.attrib['Name']) }}, "{{ LowerFirst(Property.attrib['Name']) }}"); {% elif Property.attrib['Container'] == 'Array' %} - serializer.Serialize>(m_{{ LowerFirst(Property.attrib['Name']) }}, "{{ LowerFirst(Property.attrib['Name']) }}"); + serializer.Serialize>(m_{{ LowerFirst(Property.attrib['Name']) }}, "{{ LowerFirst(Property.attrib['Name']) }}"); {% endif %} -{% endif %} + } } {% else %} Multiplayer::SerializeNetworkPropertyHelper diff --git a/Gems/Multiplayer/Code/Source/Components/NetBindComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetBindComponent.cpp index dfe2b6b561..d8e8a765ce 100644 --- a/Gems/Multiplayer/Code/Source/Components/NetBindComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/NetBindComponent.cpp @@ -284,8 +284,6 @@ namespace Multiplayer void NetBindComponent::ProcessInput(NetworkInput& networkInput, float deltaTime) { - AZ_TracePrintf("gathers", "Processing input, inputId=%d", static_cast(networkInput.GetClientInputId())); - m_isProcessingInput = true; // Only autonomous and authority runs this logic AZ_Assert((NetworkRoleHasController(m_netEntityRole)), "Incorrect network role for input processing"); From a56be14677fc82376a3a68ec1e637190a58550d0 Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Fri, 13 Aug 2021 17:25:01 -0700 Subject: [PATCH 375/803] JSON saving of SC editor assets Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- .../Assets/ScriptCanvasAssetHandler.cpp | 99 ++++++++----------- .../Serialization/DatumSerializer.cpp | 3 +- 2 files changed, 44 insertions(+), 58 deletions(-) diff --git a/Gems/ScriptCanvas/Code/Editor/Assets/ScriptCanvasAssetHandler.cpp b/Gems/ScriptCanvas/Code/Editor/Assets/ScriptCanvasAssetHandler.cpp index 55da572939..c355797f27 100644 --- a/Gems/ScriptCanvas/Code/Editor/Assets/ScriptCanvasAssetHandler.cpp +++ b/Gems/ScriptCanvas/Code/Editor/Assets/ScriptCanvasAssetHandler.cpp @@ -6,29 +6,33 @@ * */ - -#include -#include - -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include #include #include +#include +#include +#include +#include +#include +#include #include - #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// \todo move out and replace with JsonUtils.h when it can get moved +#include +#include +#include +#include + namespace ScriptCanvasEditor { @@ -75,14 +79,16 @@ namespace ScriptCanvasEditor } } - AZ::Data::AssetHandler::LoadResult ScriptCanvasAssetHandler::LoadAssetData( const AZ::Data::Asset& asset, AZStd::shared_ptr stream, const AZ::Data::AssetFilterCB& assetLoadFilterCB) { auto* scriptCanvasAsset = asset.GetAs(); - AZ_Assert(scriptCanvasAsset, "This should be an scene slice asset, as this is the only type we process!"); + AZ_Assert(scriptCanvasAsset, "This should be a ScriptCanvasAsset, as this is the only type we process!"); + + // static_assert(false, "load the json here, and only if it failed, conditionally load the block below"); + if (scriptCanvasAsset && m_serializeContext) { stream->Seek(0U, AZ::IO::GenericStream::ST_SEEK_BEGIN); @@ -91,10 +97,8 @@ namespace ScriptCanvasEditor return loadSuccess ? AZ::Data::AssetHandler::LoadResult::LoadComplete : AZ::Data::AssetHandler::LoadResult::Error; } return AZ::Data::AssetHandler::LoadResult::Error; - } - bool ScriptCanvasAssetHandler::SaveAssetData(const AZ::Data::Asset& asset, AZ::IO::GenericStream* stream) { return SaveAssetData(asset.GetAs(), stream); @@ -105,17 +109,24 @@ namespace ScriptCanvasEditor return SaveAssetData(assetData, stream, AZ::DataStream::ST_XML); } - bool ScriptCanvasAssetHandler::SaveAssetData(const ScriptCanvasAsset* assetData, AZ::IO::GenericStream* stream, AZ::DataStream::StreamType streamType) + bool ScriptCanvasAssetHandler::SaveAssetData(const ScriptCanvasAsset* assetData, AZ::IO::GenericStream* stream, [[maybe_unused]] AZ::DataStream::StreamType streamType) { + namespace JSR = AZ::JsonSerializationResult; + if (assetData && m_serializeContext) - { - AZStd::vector byteBuffer; - AZ::IO::ByteContainerStream byteStream(&byteBuffer); - AZ::ObjectStream* objStream = AZ::ObjectStream::Create(&byteStream, *m_serializeContext, streamType); - bool scriptCanvasAssetSaved = objStream->WriteClass(&assetData->GetScriptCanvasData()); - objStream->Finalize(); - scriptCanvasAssetSaved = stream->Write(byteBuffer.size(), byteBuffer.data()) == byteBuffer.size() && scriptCanvasAssetSaved; - return scriptCanvasAssetSaved; + { + AZ::JsonSerializerSettings settings; + settings.m_keepDefaults = false; + settings.m_serializeContext = m_serializeContext; + rapidjson::Document document; + + if (AZ::JsonSerialization::Store(document, document.GetAllocator(), assetData->GetScriptCanvasData(), settings).GetProcessing() != JSR::Processing::Halted) + { + // \todo replace with with exact function from JsonUtils.cpp once it is moved to AzToolsFramework + AZ::IO::RapidJSONStreamWriter jsonStreamWriter(stream); + rapidjson::PrettyWriter writer(jsonStreamWriter); + return document.Accept(writer); + } } return false; @@ -126,17 +137,11 @@ namespace ScriptCanvasEditor delete ptr; } - //========================================================================= - // GetSerializeContext - //=========================================================================. AZ::SerializeContext* ScriptCanvasAssetHandler::GetSerializeContext() const { return m_serializeContext; } - //========================================================================= - // SetSerializeContext - //=========================================================================. void ScriptCanvasAssetHandler::SetSerializeContext(AZ::SerializeContext* context) { m_serializeContext = context; @@ -152,17 +157,11 @@ namespace ScriptCanvasEditor } } - //========================================================================= - // GetHandledAssetTypes - //=========================================================================. void ScriptCanvasAssetHandler::GetHandledAssetTypes(AZStd::vector& assetTypes) { assetTypes.push_back(GetAssetType()); } - //========================================================================= - // GetAssetType - //=========================================================================. AZ::Data::AssetType ScriptCanvasAssetHandler::GetAssetType() const { return ScriptCanvasAssetHandler::GetAssetTypeStatic(); @@ -178,38 +177,24 @@ namespace ScriptCanvasEditor return azrtti_typeid(); } - //========================================================================= - // GetAssetTypeExtensions - //=========================================================================. void ScriptCanvasAssetHandler::GetAssetTypeExtensions(AZStd::vector& extensions) { ScriptCanvasAsset::Description description; extensions.push_back(description.GetExtensionImpl()); } - //========================================================================= - // GetComponentTypeId - //=========================================================================. AZ::Uuid ScriptCanvasAssetHandler::GetComponentTypeId() const { return azrtti_typeid(); } - //========================================================================= - // GetGroup - //=========================================================================. const char* ScriptCanvasAssetHandler::GetGroup() const { return ScriptCanvas::AssetDescription::GetGroup(); } - //========================================================================= - // GetBrowserIcon - //=========================================================================. const char* ScriptCanvasAssetHandler::GetBrowserIcon() const { return ScriptCanvas::AssetDescription::GetIconPath(); } - - } diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Serialization/DatumSerializer.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Serialization/DatumSerializer.cpp index 44ca1730a8..003ef05774 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Serialization/DatumSerializer.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Serialization/DatumSerializer.cpp @@ -84,7 +84,8 @@ namespace AZ AZStd::string label; AZ_Assert(azrtti_typeidm_datumLabel)>() == azrtti_typeid() , "m_datumLabel type changed and won't load properly"); - result.Combine(ContinueLoadingFromJsonObjectField + + result.Combine( ContinueLoadingFromJsonObjectField ( &label , azrtti_typeidm_datumLabel)>() , inputValue From 87ae7e865365707ba7d7fc453fdd0c43b34f489a Mon Sep 17 00:00:00 2001 From: Steve Pham <82231385+spham-amzn@users.noreply.github.com> Date: Fri, 13 Aug 2021 18:22:40 -0700 Subject: [PATCH 376/803] Fix android gradle scripts to prevent cmake_dependencies.._gamelauncher from being wiped out of the APK Update gradle script generation to correct task dependencies (#3120) - copyNativeArtifacts must run after syncLYLayoutMode - syncLYLayoutMode must must after externalNativeBuild Signed-off-by: Steve Pham --- .../Tools/Platform/Android/android_support.py | 40 ++++++++++++------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/cmake/Tools/Platform/Android/android_support.py b/cmake/Tools/Platform/Android/android_support.py index d820eb1d8c..77c8a37a35 100755 --- a/cmake/Tools/Platform/Android/android_support.py +++ b/cmake/Tools/Platform/Android/android_support.py @@ -372,9 +372,12 @@ CUSTOM_GRADLE_COPY_NATIVE_CONFIG_BUILD_ARTIFACTS_FORMAT_STR = """ }} compile{config}Sources.dependsOn copyNativeArtifacts{config} +""" + +CUSTOM_GRADLE_COPY_NATIVE_CONFIG_BUILD_ARTIFACTS_DEPENDENCY_FORMAT_STR = """ copyNativeArtifacts{config}.mustRunAfter {{ - tasks.findAll {{ task->task.name.contains('externalNativeBuild{config}') }} + tasks.findAll {{ task->task.name.contains('syncLYLayoutMode{config}') }} }} """ @@ -383,7 +386,13 @@ CUSTOM_APPLY_ASSET_LAYOUT_TASK_FORMAT_STR = """ workingDir '{working_dir}' commandLine '{python_full_path}', 'layout_tool.py', '--project-path', '{project_path}', '-p', 'Android', '-a', '{asset_type}', '-m', '{asset_mode}', '--create-layout-root', '-l', '{asset_layout_folder}' }} + compile{config}Sources.dependsOn syncLYLayoutMode{config} + + syncLYLayoutMode{config}.mustRunAfter {{ + tasks.findAll {{ task->task.name.contains('externalNativeBuild{config}') }} + }} + """ @@ -832,25 +841,28 @@ class AndroidProjectGenerator(object): asset_layout_folder=(self.build_dir / 'app/src/main/assets').resolve().as_posix(), file_includes='Test.Assets/**/*.*') else: - # Copy over settings registry files from the Registry folder with build output directory gradle_build_env[f'CUSTOM_APPLY_ASSET_LAYOUT_{native_config_upper}_TASK'] = \ + CUSTOM_APPLY_ASSET_LAYOUT_TASK_FORMAT_STR.format(working_dir=common.normalize_path_for_settings(self.engine_root / 'cmake/Tools'), + python_full_path=common.normalize_path_for_settings(self.engine_root / 'python' / PYTHON_SCRIPT), + asset_type=self.asset_type, + project_path=self.project_path.as_posix(), + asset_mode=self.asset_mode if native_config != 'Release' else 'PAK', + asset_layout_folder=(self.build_dir / 'app/src/main/assets').resolve().as_posix(), + config=native_config) + # Copy over settings registry files from the Registry folder with build output directory + gradle_build_env[f'CUSTOM_APPLY_ASSET_LAYOUT_{native_config_upper}_TASK'] += \ CUSTOM_GRADLE_COPY_NATIVE_CONFIG_BUILD_ARTIFACTS_FORMAT_STR.format(config=native_config, config_lower=native_config_lower, asset_layout_folder=(self.build_dir / 'app/src/main/assets').resolve().as_posix(), file_includes='**/Registry/*.setreg') - - if self.include_assets_in_apk: - if not self.is_test_project: + if self.include_assets_in_apk: + # This is a dependency of the layout sync only if we are including assets in the APK gradle_build_env[f'CUSTOM_APPLY_ASSET_LAYOUT_{native_config_upper}_TASK'] += \ - CUSTOM_APPLY_ASSET_LAYOUT_TASK_FORMAT_STR.format(working_dir=common.normalize_path_for_settings(self.engine_root / 'cmake/Tools'), - python_full_path=common.normalize_path_for_settings(self.engine_root / 'python' / PYTHON_SCRIPT), - asset_type=self.asset_type, - project_path=self.project_path.as_posix(), - asset_mode=self.asset_mode if native_config != 'Release' else 'PAK', - asset_layout_folder=(self.build_dir / 'app/src/main/assets').resolve().as_posix(), - config=native_config) - else: - gradle_build_env[f'CUSTOM_APPLY_ASSET_LAYOUT_{native_config_upper}_TASK'] = '' + CUSTOM_GRADLE_COPY_NATIVE_CONFIG_BUILD_ARTIFACTS_DEPENDENCY_FORMAT_STR.format(config=native_config) + + + + if self.signing_config: gradle_build_env[f'SIGNING_{native_config_upper}_CONFIG'] = f'signingConfig signingConfigs.{native_config_lower}' if self.signing_config else '' else: From 2fa9a831b3d09240d786d0636a173f9c9d169fd7 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Fri, 13 Aug 2021 20:26:49 -0500 Subject: [PATCH 377/803] AtomTools: prepend asterisk to denote modified document tabs Appending is standard and preferred but the tabs elide from the end (instead of middle) and cut it off Signed-off-by: Guthrie Adams --- .../Code/Source/Window/AtomToolsMainWindow.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp index 55bec32dc7..e869e0eb98 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp @@ -199,8 +199,10 @@ namespace AtomToolsFramework { if (documentId == GetDocumentIdFromTab(tabIndex)) { - // We use an asterisk appended to the file name to denote modified document - const AZStd::string modifiedLabel = isModified ? label + " *" : label; + // We use an asterisk prepended to the file name to denote modified document + // Appending is standard and preferred but the tabs elide from the + // end (instead of middle) and cut it off + const AZStd::string modifiedLabel = isModified ? "* " + label : label; m_tabWidget->setTabText(tabIndex, modifiedLabel.c_str()); m_tabWidget->setTabToolTip(tabIndex, toolTip.c_str()); m_tabWidget->repaint(); From 83f6cb813ae42e0e8420a48f791d5c52f3f3178c Mon Sep 17 00:00:00 2001 From: Steve Pham <82231385+spham-amzn@users.noreply.github.com> Date: Fri, 13 Aug 2021 18:38:48 -0700 Subject: [PATCH 378/803] Fix Non-Unity compile error with Atom Sample Viewer and the Atom Gem (#3119) Signed-off-by: spham-amzn --- Gems/Atom/Utils/Code/Include/Atom/Utils/StableDynamicArray.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Gems/Atom/Utils/Code/Include/Atom/Utils/StableDynamicArray.h b/Gems/Atom/Utils/Code/Include/Atom/Utils/StableDynamicArray.h index 7c77838330..454a6d4086 100644 --- a/Gems/Atom/Utils/Code/Include/Atom/Utils/StableDynamicArray.h +++ b/Gems/Atom/Utils/Code/Include/Atom/Utils/StableDynamicArray.h @@ -10,6 +10,7 @@ #include #include #include +#include #include #include From e633b5bdc70ca5b4ea3bb8cc7cd55e7e0acd3e8d Mon Sep 17 00:00:00 2001 From: mnaumov Date: Fri, 13 Aug 2021 19:43:38 -0700 Subject: [PATCH 379/803] Addressing Ronald's feedback Signed-off-by: mnaumov --- .../Prefab/Instance/InstanceSerializer.cpp | 3 +++ .../AzToolsFramework/Prefab/PrefabDomUtils.cpp | 6 ++++++ .../AzToolsFramework/Prefab/PrefabDomUtils.h | 12 +++++++++++- .../AzToolsFramework/Prefab/PrefabLoader.cpp | 2 +- 4 files changed, 21 insertions(+), 2 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceSerializer.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceSerializer.cpp index 89e0136b12..af42919637 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceSerializer.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceSerializer.cpp @@ -15,6 +15,7 @@ #include #include #include +#include namespace AzToolsFramework { @@ -81,6 +82,8 @@ namespace AzToolsFramework result.Combine(resultInstances); } + PrefabDomUtils::LinkIdMetadata** linkIdMetadata = context.GetMetadata().Find(); + if (linkIdMetadata && *linkIdMetadata) { AZ::ScopedContextPath subPathSource(context, "m_linkId"); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.cpp index 86983d7912..c58cb21295 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.cpp @@ -64,6 +64,12 @@ namespace AzToolsFramework settings.m_keepDefaults = true; } + if ((flags & StoreInstanceFlags::StoreLinkIds) != StoreInstanceFlags::None) + { + LinkIdMetadata linkIdMetadata; + settings.m_metadata.Add(&linkIdMetadata); + } + AZ::JsonSerializationResult::ResultCode result = AZ::JsonSerialization::Store(prefabDom, prefabDom.GetAllocator(), instance, settings); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.h index e773b581dd..fe38eb9e0f 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.h @@ -45,7 +45,11 @@ namespace AzToolsFramework //! By default an instance will be stored with default values. In cases where we want to store less json without defaults //! such as saving to disk, this flag will control that behavior. - StripDefaultValues = 1 << 0 + StripDefaultValues = 1 << 0, + + //! We do not save linkIds to file. However when loading a level we want to temporarily save + //! linkIds to instance dom so any nested prefabs will have linkIds correctly set. + StoreLinkIds = 1 << 1 }; AZ_DEFINE_ENUM_BITWISE_OPERATORS(StoreInstanceFlags); @@ -138,6 +142,12 @@ namespace AzToolsFramework [[maybe_unused]] const AZStd::string_view printMessage, [[maybe_unused]] const AzToolsFramework::Prefab::PrefabDomValue& prefabDomValue); + //! An empty struct for passing to JsonSerializerSettings.m_metadata that is consumed by InstanceSerializer::Store. + //! If present in metadata, linkIds will be stored to instance dom. + struct LinkIdMetadata + { + AZ_RTTI(LinkIdMetadata, "{8FF7D299-14E3-41D4-90C5-393A240FAE7C}"); + }; } // namespace PrefabDomUtils } // namespace Prefab } // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp index ea54c9d10c..2b16134744 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp @@ -300,7 +300,7 @@ namespace AzToolsFramework } PrefabDom storedPrefabDom(&loadedTemplateDom->get().GetAllocator()); - if (!PrefabDomUtils::StoreInstanceInPrefabDom(loadedPrefabInstance, storedPrefabDom)) + if (!PrefabDomUtils::StoreInstanceInPrefabDom(loadedPrefabInstance, storedPrefabDom, PrefabDomUtils::StoreInstanceFlags::StoreLinkIds)) { return false; } From 9aa391bf7413d15f3814cb6115eac95163733fa1 Mon Sep 17 00:00:00 2001 From: mnaumov Date: Fri, 13 Aug 2021 16:54:57 -0700 Subject: [PATCH 380/803] Fixing Level Save As Signed-off-by: mnaumov --- .../PrefabEditorEntityOwnershipService.cpp | 36 ++----------------- 1 file changed, 2 insertions(+), 34 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp index b5cf5fb878..7df1e1b5c1 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp @@ -219,42 +219,10 @@ namespace AzToolsFramework bool PrefabEditorEntityOwnershipService::SaveToStream(AZ::IO::GenericStream& stream, AZStd::string_view filename) { AZ::IO::Path relativePath = m_loaderInterface->GenerateRelativePath(filename); - AzToolsFramework::Prefab::TemplateId templateId = m_prefabSystemComponent->GetTemplateIdFromFilePath(relativePath); m_rootInstance->SetTemplateSourcePath(relativePath); - - if (templateId == AzToolsFramework::Prefab::InvalidTemplateId) - { - m_rootInstance->m_containerEntity->AddComponent(aznew Prefab::EditorPrefabComponent()); - HandleEntitiesAdded({ m_rootInstance->m_containerEntity.get() }); - - AzToolsFramework::Prefab::PrefabDom dom; - bool success = AzToolsFramework::Prefab::PrefabDomUtils::StoreInstanceInPrefabDom(*m_rootInstance, dom); - if (!success) - { - AZ_Error("Prefab", false, "Failed to convert current root instance into a DOM when saving file '%.*s'", AZ_STRING_ARG(filename)); - return false; - } - templateId = m_prefabSystemComponent->AddTemplate(relativePath, AZStd::move(dom)); - - if (templateId == AzToolsFramework::Prefab::InvalidTemplateId) - { - AZ_Error("Prefab", false, "Couldn't add new template id '%i' when saving file '%.*s'", templateId, AZ_STRING_ARG(filename)); - return false; - } - } - - Prefab::TemplateId prevTemplateId = m_rootInstance->GetTemplateId(); - m_rootInstance->SetTemplateId(templateId); - - if (prevTemplateId != Prefab::InvalidTemplateId && templateId != prevTemplateId) - { - // Make sure we only have one level template loaded at a time - m_prefabSystemComponent->RemoveTemplate(prevTemplateId); - } - + AZStd::string out; - if (!m_loaderInterface->SaveTemplateToString(m_rootInstance->GetTemplateId(), out)) { return false; @@ -266,7 +234,7 @@ namespace AzToolsFramework { return false; } - m_prefabSystemComponent->SetTemplateDirtyFlag(templateId, false); + m_prefabSystemComponent->SetTemplateDirtyFlag(m_rootInstance->GetTemplateId(), false); return true; } From 504420483925d67cf380715f14588eebc8492151 Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Fri, 13 Aug 2021 21:53:20 -0700 Subject: [PATCH 381/803] Move JsonUtils.h for support of SC serialization Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- .../AtomCore/AtomCore/atomcore_files.cmake | 2 - .../Tests/JsonSerializationUtilsTests.cpp | 2 +- .../Serialization/Json/JsonUtils.cpp | 7 +- .../Serialization/Json/JsonUtils.h | 2 + .../aztoolsframework_files.cmake | 2 + .../BuilderSettings/BuilderSettingManager.cpp | 2 +- .../Code/Source/Editor/AtomShaderConfig.cpp | 2 +- .../Code/Source/Editor/AzslCompiler.cpp | 2 +- .../Editor/CommonFiles/GlobalBuildOptions.cpp | 2 +- .../Editor/CommonFiles/Preprocessor.cpp | 2 +- .../Editor/PrecompiledShaderBuilder.cpp | 2 +- .../Code/Source/Editor/ShaderAssetBuilder.cpp | 2 +- .../Source/Editor/ShaderBuilderUtility.cpp | 2 +- .../Editor/ShaderVariantAssetBuilder.cpp | 2 +- Gems/Atom/Feature/Common/Code/CMakeLists.txt | 4 + .../Source/FrameCaptureSystemComponent.cpp | 2 +- .../ProfilingCaptureSystemComponent.cpp | 2 +- Gems/Atom/RHI/Code/Source/RHI.Edit/Utils.cpp | 2 +- Gems/Atom/RPI/Code/CMakeLists.txt | 3 + .../Include/Atom/RPI.Edit/Common/JsonUtils.h | 2 +- .../RPI.Builders/Common/AnyAssetBuilder.cpp | 2 +- .../RPI.Builders/Material/MaterialBuilder.cpp | 2 +- .../Source/RPI.Builders/Pass/PassBuilder.cpp | 2 +- .../ResourcePool/ResourcePoolBuilder.cpp | 2 +- .../MaterialFunctorSourceDataSerializer.cpp | 2 +- .../MaterialPropertyValueSerializer.cpp | 2 +- .../RPI.Edit/Material/MaterialSourceData.cpp | 2 +- .../Material/MaterialSourceDataSerializer.cpp | 2 +- .../RPI.Edit/Material/MaterialUtils.cpp | 2 +- .../RPI.Public/Pass/AttachmentReadback.cpp | 2 +- .../Source/RPI.Public/Pass/PassSystem.cpp | 2 +- .../Shader/Metrics/ShaderMetrics.cpp | 2 +- .../Shader/Metrics/ShaderMetricsSystem.cpp | 2 +- .../Tests.Builders/AnyAssetBuilderTest.cpp | 2 +- .../Code/Tests.Builders/PassBuilderTest.cpp | 2 +- .../ResourcePoolBuilderTest.cpp | 2 +- .../RPI/Code/Tests/Common/JsonTestUtils.h | 2 +- .../Tests/Material/MaterialFunctorTests.cpp | 2 +- .../MaterialPropertySerializerTests.cpp | 2 +- .../Material/MaterialTypeSourceDataTests.cpp | 2 +- .../Viewport/MaterialViewportComponent.cpp | 2 +- ...ssetCollectionAsyncLoaderTestComponent.cpp | 2 +- .../Assets/ScriptCanvasAssetHandler.cpp | 79 +++++++++++-------- 43 files changed, 96 insertions(+), 75 deletions(-) rename Code/Framework/{AtomCore/AtomCore => AzToolsFramework/AzToolsFramework}/Serialization/Json/JsonUtils.cpp (99%) rename Code/Framework/{AtomCore/AtomCore => AzToolsFramework/AzToolsFramework}/Serialization/Json/JsonUtils.h (99%) diff --git a/Code/Framework/AtomCore/AtomCore/atomcore_files.cmake b/Code/Framework/AtomCore/AtomCore/atomcore_files.cmake index bcfbfb2764..c90263468f 100644 --- a/Code/Framework/AtomCore/AtomCore/atomcore_files.cmake +++ b/Code/Framework/AtomCore/AtomCore/atomcore_files.cmake @@ -13,8 +13,6 @@ set(FILES Instance/InstanceData.h Instance/InstanceData.cpp Instance/InstanceDatabase.h - Serialization/Json/JsonUtils.h - Serialization/Json/JsonUtils.cpp std/containers/array_view.h std/containers/fixed_vector_set.h std/containers/lru_cache.h diff --git a/Code/Framework/AtomCore/Tests/JsonSerializationUtilsTests.cpp b/Code/Framework/AtomCore/Tests/JsonSerializationUtilsTests.cpp index 77bcb0c08d..79e0bf86ee 100644 --- a/Code/Framework/AtomCore/Tests/JsonSerializationUtilsTests.cpp +++ b/Code/Framework/AtomCore/Tests/JsonSerializationUtilsTests.cpp @@ -13,7 +13,7 @@ #include -#include +#include namespace UnitTest { diff --git a/Code/Framework/AtomCore/AtomCore/Serialization/Json/JsonUtils.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Serialization/Json/JsonUtils.cpp similarity index 99% rename from Code/Framework/AtomCore/AtomCore/Serialization/Json/JsonUtils.cpp rename to Code/Framework/AzToolsFramework/AzToolsFramework/Serialization/Json/JsonUtils.cpp index 1d3a9674a0..89cf667958 100644 --- a/Code/Framework/AtomCore/AtomCore/Serialization/Json/JsonUtils.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Serialization/Json/JsonUtils.cpp @@ -6,7 +6,6 @@ * */ -#include #include #include #include @@ -23,6 +22,8 @@ #include #include +#include "JsonUtils.h" + namespace AZ { namespace JsonSerializationUtils @@ -343,9 +344,9 @@ namespace AZ { return AZ::Failure(deserializeErrors); } + return AZ::Success(); - } - + } AZ::Outcome LoadAnyObjectFromStream(IO::GenericStream& stream, const JsonDeserializerSettings* settings) { diff --git a/Code/Framework/AtomCore/AtomCore/Serialization/Json/JsonUtils.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Serialization/Json/JsonUtils.h similarity index 99% rename from Code/Framework/AtomCore/AtomCore/Serialization/Json/JsonUtils.h rename to Code/Framework/AzToolsFramework/AzToolsFramework/Serialization/Json/JsonUtils.h index c7777feec0..62020d81d0 100644 --- a/Code/Framework/AtomCore/AtomCore/Serialization/Json/JsonUtils.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Serialization/Json/JsonUtils.h @@ -15,6 +15,8 @@ #include #include +// hello? + namespace AZ { namespace IO diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake b/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake index 14c5f34f90..0c49da841f 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake @@ -205,6 +205,8 @@ set(FILES PropertyTreeEditor/PropertyTreeEditorComponent.h Render/EditorIntersectorComponent.cpp Render/EditorIntersectorComponent.h + Serialization/Json/JsonUtils.h + Serialization/Json/JsonUtils.cpp Slice/SliceDataFlagsCommand.h Slice/SliceDataFlagsCommand.cpp Slice/SliceUtilities.h diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/BuilderSettingManager.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/BuilderSettingManager.cpp index 46b684493b..764a19d549 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/BuilderSettingManager.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/BuilderSettingManager.cpp @@ -37,7 +37,7 @@ #include #include -#include +#include namespace ImageProcessingAtom { diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/AtomShaderConfig.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/AtomShaderConfig.cpp index fcb486ec32..b299108518 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/AtomShaderConfig.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/AtomShaderConfig.cpp @@ -12,7 +12,7 @@ #include #include -#include +#include namespace AZ diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/AzslCompiler.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/AzslCompiler.cpp index cc42fac422..397d47ef21 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/AzslCompiler.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/AzslCompiler.cpp @@ -19,7 +19,7 @@ #include -#include +#include #include #include // [GFX TODO] Remove when [ATOM-15472] diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/CommonFiles/GlobalBuildOptions.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/CommonFiles/GlobalBuildOptions.cpp index 66b4d2e833..1b3b7c595d 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/CommonFiles/GlobalBuildOptions.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/CommonFiles/GlobalBuildOptions.cpp @@ -14,7 +14,7 @@ #include #include -#include +#include namespace AZ { diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/CommonFiles/Preprocessor.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/CommonFiles/Preprocessor.cpp index 945f9734ca..adec465a9f 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/CommonFiles/Preprocessor.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/CommonFiles/Preprocessor.cpp @@ -29,7 +29,7 @@ #include #include -#include +#include #include diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/PrecompiledShaderBuilder.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/PrecompiledShaderBuilder.cpp index 5d712a4a8a..6d876c0ad4 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/PrecompiledShaderBuilder.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/PrecompiledShaderBuilder.cpp @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderAssetBuilder.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderAssetBuilder.cpp index b1a3de2794..d3fa043fa2 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderAssetBuilder.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderAssetBuilder.cpp @@ -24,7 +24,7 @@ #include #include -#include +#include #include #include diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuilderUtility.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuilderUtility.cpp index d7c3de48c0..df0d9b10a2 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuilderUtility.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuilderUtility.cpp @@ -21,7 +21,7 @@ #include #include -#include +#include #include #include diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp index 1da4623774..8bbae7502b 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp @@ -18,7 +18,7 @@ #include #include -#include +#include #include #include diff --git a/Gems/Atom/Feature/Common/Code/CMakeLists.txt b/Gems/Atom/Feature/Common/Code/CMakeLists.txt index 8ed02f2c2f..8a9fe3b07c 100644 --- a/Gems/Atom/Feature/Common/Code/CMakeLists.txt +++ b/Gems/Atom/Feature/Common/Code/CMakeLists.txt @@ -34,6 +34,7 @@ ly_add_target( PRIVATE AZ::AzCore AZ::AzFramework + AZ::AzToolsFramework PUBLIC Gem::Atom_RPI.Public Gem::Atom_Utils.Static @@ -62,6 +63,7 @@ ly_add_target( PRIVATE AZ::AzCore AZ::AzFramework + AZ::AzToolsFramework PUBLIC Gem::Atom_RPI.Public Gem::Atom_Utils.Static @@ -85,6 +87,7 @@ ly_add_target( PRIVATE AZ::AzCore AZ::AzFramework + AZ::AzToolsFramework Gem::Atom_Feature_Common.Static Gem::Atom_Feature_Common.Public 3rdParty::lux_core @@ -161,6 +164,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) BUILD_DEPENDENCIES PRIVATE AZ::AzFramework + AZ::AzToolsFramework AZ::AzTest Gem::Atom_Feature_Common.Static Gem::Atom_Feature_Common.Public diff --git a/Gems/Atom/Feature/Common/Code/Source/FrameCaptureSystemComponent.cpp b/Gems/Atom/Feature/Common/Code/Source/FrameCaptureSystemComponent.cpp index 4b1a6ec7f6..4eb5ab0a76 100644 --- a/Gems/Atom/Feature/Common/Code/Source/FrameCaptureSystemComponent.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/FrameCaptureSystemComponent.cpp @@ -17,7 +17,7 @@ #include #include -#include +#include #include #include diff --git a/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.cpp b/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.cpp index add6d0e098..da194d4d4e 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.cpp @@ -19,7 +19,7 @@ #include #include -#include +#include #include #include diff --git a/Gems/Atom/RHI/Code/Source/RHI.Edit/Utils.cpp b/Gems/Atom/RHI/Code/Source/RHI.Edit/Utils.cpp index 8c64f1611f..f0fbf40a14 100644 --- a/Gems/Atom/RHI/Code/Source/RHI.Edit/Utils.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI.Edit/Utils.cpp @@ -8,7 +8,7 @@ #include -#include +#include #include #include diff --git a/Gems/Atom/RPI/Code/CMakeLists.txt b/Gems/Atom/RPI/Code/CMakeLists.txt index 521178be20..54e74b756b 100644 --- a/Gems/Atom/RPI/Code/CMakeLists.txt +++ b/Gems/Atom/RPI/Code/CMakeLists.txt @@ -40,6 +40,7 @@ ly_add_target( AZ::AtomCore AZ::AzCore AZ::AzFramework + AZ::AzToolsFramework PUBLIC Gem::Atom_RHI.Public ) @@ -62,6 +63,7 @@ ly_add_target( AZ::AtomCore AZ::AzCore AZ::AzFramework + AZ::AzToolsFramework Gem::Atom_RPI.Public Gem::Atom_RHI.Public Gem::Atom_RHI.Reflect @@ -107,6 +109,7 @@ if(PAL_TRAIT_BUILD_HOST_TOOLS) AZ::AtomCore AZ::AzCore AZ::AzFramework + AZ::AzToolsFramework Gem::Atom_RPI.Public Gem::Atom_RHI.Public ) diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Common/JsonUtils.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Common/JsonUtils.h index 3e3fbec8fe..22baf5776a 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Common/JsonUtils.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Common/JsonUtils.h @@ -10,7 +10,7 @@ #include #include -#include +#include #include #include diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Common/AnyAssetBuilder.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/Common/AnyAssetBuilder.cpp index 4074568fbe..031b928543 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Common/AnyAssetBuilder.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Common/AnyAssetBuilder.cpp @@ -19,7 +19,7 @@ #include -#include +#include #include #include diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp index d07f073d4f..70230cfffb 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #include diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Pass/PassBuilder.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/Pass/PassBuilder.cpp index 652130dea2..2949125fc1 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Pass/PassBuilder.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Pass/PassBuilder.cpp @@ -11,7 +11,7 @@ #include -#include +#include #include #include diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/ResourcePool/ResourcePoolBuilder.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/ResourcePool/ResourcePoolBuilder.cpp index 1dcab2679f..24a105a4f4 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/ResourcePool/ResourcePoolBuilder.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/ResourcePool/ResourcePoolBuilder.cpp @@ -16,7 +16,7 @@ #include -#include +#include #include #include diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialFunctorSourceDataSerializer.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialFunctorSourceDataSerializer.cpp index 3ba115f3e6..52b56f254a 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialFunctorSourceDataSerializer.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialFunctorSourceDataSerializer.cpp @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include #include diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialPropertyValueSerializer.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialPropertyValueSerializer.cpp index 708644ae20..3c702b84a0 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialPropertyValueSerializer.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialPropertyValueSerializer.cpp @@ -21,7 +21,7 @@ #include #include -#include +#include namespace AZ { diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp index 1fee57759c..8d799fe440 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp @@ -22,7 +22,7 @@ #include #include -#include +#include #include #include diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceDataSerializer.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceDataSerializer.cpp index e65c65a39a..466fd79dd8 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceDataSerializer.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceDataSerializer.cpp @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #include diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialUtils.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialUtils.cpp index 67c143c074..7fb9d3d70f 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialUtils.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialUtils.cpp @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/AttachmentReadback.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/AttachmentReadback.cpp index 29a17dc9a8..15fadd894b 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/AttachmentReadback.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/AttachmentReadback.cpp @@ -23,7 +23,7 @@ #include #include -#include +#include #include diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/PassSystem.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/PassSystem.cpp index d73521763f..6d470427b5 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/PassSystem.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/PassSystem.cpp @@ -17,7 +17,7 @@ #include #include -#include +#include #include #include diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/Metrics/ShaderMetrics.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/Metrics/ShaderMetrics.cpp index 5df21f3964..7e5c268112 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/Metrics/ShaderMetrics.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/Metrics/ShaderMetrics.cpp @@ -6,7 +6,7 @@ * */ #include -#include +#include namespace AZ { diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/Metrics/ShaderMetricsSystem.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/Metrics/ShaderMetricsSystem.cpp index d0d76e62de..47c8dedd8d 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/Metrics/ShaderMetricsSystem.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/Metrics/ShaderMetricsSystem.cpp @@ -15,7 +15,7 @@ #include #include -#include +#include #include diff --git a/Gems/Atom/RPI/Code/Tests.Builders/AnyAssetBuilderTest.cpp b/Gems/Atom/RPI/Code/Tests.Builders/AnyAssetBuilderTest.cpp index fcec484fa9..33b4bc61fe 100644 --- a/Gems/Atom/RPI/Code/Tests.Builders/AnyAssetBuilderTest.cpp +++ b/Gems/Atom/RPI/Code/Tests.Builders/AnyAssetBuilderTest.cpp @@ -13,7 +13,7 @@ #include #include -#include +#include #include #include diff --git a/Gems/Atom/RPI/Code/Tests.Builders/PassBuilderTest.cpp b/Gems/Atom/RPI/Code/Tests.Builders/PassBuilderTest.cpp index ad1df41824..993bd8ded2 100644 --- a/Gems/Atom/RPI/Code/Tests.Builders/PassBuilderTest.cpp +++ b/Gems/Atom/RPI/Code/Tests.Builders/PassBuilderTest.cpp @@ -16,7 +16,7 @@ #include #include -#include +#include #include diff --git a/Gems/Atom/RPI/Code/Tests.Builders/ResourcePoolBuilderTest.cpp b/Gems/Atom/RPI/Code/Tests.Builders/ResourcePoolBuilderTest.cpp index d6107cda9e..2623cade02 100644 --- a/Gems/Atom/RPI/Code/Tests.Builders/ResourcePoolBuilderTest.cpp +++ b/Gems/Atom/RPI/Code/Tests.Builders/ResourcePoolBuilderTest.cpp @@ -8,7 +8,7 @@ #include -#include +#include #include #include diff --git a/Gems/Atom/RPI/Code/Tests/Common/JsonTestUtils.h b/Gems/Atom/RPI/Code/Tests/Common/JsonTestUtils.h index 2c38090b43..3b66565f99 100644 --- a/Gems/Atom/RPI/Code/Tests/Common/JsonTestUtils.h +++ b/Gems/Atom/RPI/Code/Tests/Common/JsonTestUtils.h @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include namespace UnitTest diff --git a/Gems/Atom/RPI/Code/Tests/Material/MaterialFunctorTests.cpp b/Gems/Atom/RPI/Code/Tests/Material/MaterialFunctorTests.cpp index cf64fd12f3..9b82f501d2 100644 --- a/Gems/Atom/RPI/Code/Tests/Material/MaterialFunctorTests.cpp +++ b/Gems/Atom/RPI/Code/Tests/Material/MaterialFunctorTests.cpp @@ -19,7 +19,7 @@ #include #include -//#include +//#include namespace UnitTest { using namespace AZ; diff --git a/Gems/Atom/RPI/Code/Tests/Material/MaterialPropertySerializerTests.cpp b/Gems/Atom/RPI/Code/Tests/Material/MaterialPropertySerializerTests.cpp index 759842cf96..fdd8edf5e5 100644 --- a/Gems/Atom/RPI/Code/Tests/Material/MaterialPropertySerializerTests.cpp +++ b/Gems/Atom/RPI/Code/Tests/Material/MaterialPropertySerializerTests.cpp @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include #include diff --git a/Gems/Atom/RPI/Code/Tests/Material/MaterialTypeSourceDataTests.cpp b/Gems/Atom/RPI/Code/Tests/Material/MaterialTypeSourceDataTests.cpp index 44b59059ba..85beba6721 100644 --- a/Gems/Atom/RPI/Code/Tests/Material/MaterialTypeSourceDataTests.cpp +++ b/Gems/Atom/RPI/Code/Tests/Material/MaterialTypeSourceDataTests.cpp @@ -20,7 +20,7 @@ #include #include -#include +#include #include #include diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportComponent.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportComponent.cpp index d957ea327c..ec2f200ff2 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportComponent.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportComponent.cpp @@ -25,7 +25,7 @@ #include #include -#include +#include #include #include diff --git a/Gems/AtomLyIntegration/AtomBridge/Code/Source/Editor/AssetCollectionAsyncLoaderTestComponent.cpp b/Gems/AtomLyIntegration/AtomBridge/Code/Source/Editor/AssetCollectionAsyncLoaderTestComponent.cpp index b51e3b0e29..f0a8e35699 100644 --- a/Gems/AtomLyIntegration/AtomBridge/Code/Source/Editor/AssetCollectionAsyncLoaderTestComponent.cpp +++ b/Gems/AtomLyIntegration/AtomBridge/Code/Source/Editor/AssetCollectionAsyncLoaderTestComponent.cpp @@ -13,7 +13,7 @@ #include -#include +#include // Included so we can deduce the asset type from asset paths. #include diff --git a/Gems/ScriptCanvas/Code/Editor/Assets/ScriptCanvasAssetHandler.cpp b/Gems/ScriptCanvas/Code/Editor/Assets/ScriptCanvasAssetHandler.cpp index c355797f27..ee78a71772 100644 --- a/Gems/ScriptCanvas/Code/Editor/Assets/ScriptCanvasAssetHandler.cpp +++ b/Gems/ScriptCanvas/Code/Editor/Assets/ScriptCanvasAssetHandler.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -27,13 +28,6 @@ #include #include -// \todo move out and replace with JsonUtils.h when it can get moved -#include -#include -#include -#include - - namespace ScriptCanvasEditor { ScriptCanvasAssetHandler::ScriptCanvasAssetHandler(AZ::SerializeContext* context) @@ -79,23 +73,45 @@ namespace ScriptCanvasEditor } } - AZ::Data::AssetHandler::LoadResult ScriptCanvasAssetHandler::LoadAssetData( - const AZ::Data::Asset& asset, - AZStd::shared_ptr stream, - const AZ::Data::AssetFilterCB& assetLoadFilterCB) + AZ::Data::AssetHandler::LoadResult ScriptCanvasAssetHandler::LoadAssetData + ( const AZ::Data::Asset& assetTarget + , AZStd::shared_ptr streamSource + , const AZ::Data::AssetFilterCB& assetLoadFilterCB) { - auto* scriptCanvasAsset = asset.GetAs(); - AZ_Assert(scriptCanvasAsset, "This should be a ScriptCanvasAsset, as this is the only type we process!"); + namespace JSRU = AZ::JsonSerializationUtils; + using namespace ScriptCanvas; - // static_assert(false, "load the json here, and only if it failed, conditionally load the block below"); + auto* scriptCanvasAssetTarget = assetTarget.GetAs(); + AZ_Assert(scriptCanvasAssetTarget, "This should be a ScriptCanvasAsset, as this is the only type we process!"); - if (scriptCanvasAsset && m_serializeContext) + if (scriptCanvasAssetTarget && m_serializeContext && streamSource) { - stream->Seek(0U, AZ::IO::GenericStream::ST_SEEK_BEGIN); - // tolerate unknown classes in the editor. Let the asset processor warn about bad nodes... - bool loadSuccess = AZ::Utils::LoadObjectFromStreamInPlace(*stream, scriptCanvasAsset->GetScriptCanvasData(), m_serializeContext, AZ::ObjectStream::FilterDescriptor(assetLoadFilterCB, AZ::ObjectStream::FILTERFLAG_IGNORE_UNKNOWN_CLASSES)); - return loadSuccess ? AZ::Data::AssetHandler::LoadResult::LoadComplete : AZ::Data::AssetHandler::LoadResult::Error; + AZ::JsonDeserializerSettings settings; + // more mapping stuff + settings.m_serializeContext = m_serializeContext; + streamSource->Seek(0U, AZ::IO::GenericStream::ST_SEEK_BEGIN); + // presume JSON serialization... + if (JSRU::LoadObjectFromStreamByType + ( scriptCanvasAssetTarget + , azrtti_typeid() + , *streamSource + , &settings).IsSuccess()) + { + return AZ::Data::AssetHandler::LoadResult::LoadComplete; + } + else + { + // ...if there is a failure, check if it is saved in the old format + streamSource->Seek(0U, AZ::IO::GenericStream::ST_SEEK_BEGIN); + // tolerate unknown classes in the editor. Let the asset processor warn about bad nodes... + bool loadSuccess = AZ::Utils::LoadObjectFromStreamInPlace(*streamSource, scriptCanvasAssetTarget->GetScriptCanvasData() + , m_serializeContext + , AZ::ObjectStream::FilterDescriptor(assetLoadFilterCB, AZ::ObjectStream::FILTERFLAG_IGNORE_UNKNOWN_CLASSES)); + + return loadSuccess ? AZ::Data::AssetHandler::LoadResult::LoadComplete : AZ::Data::AssetHandler::LoadResult::Error; + } } + return AZ::Data::AssetHandler::LoadResult::Error; } @@ -111,25 +127,20 @@ namespace ScriptCanvasEditor bool ScriptCanvasAssetHandler::SaveAssetData(const ScriptCanvasAsset* assetData, AZ::IO::GenericStream* stream, [[maybe_unused]] AZ::DataStream::StreamType streamType) { - namespace JSR = AZ::JsonSerializationResult; - - if (assetData && m_serializeContext) - { + namespace JSRU = AZ::JsonSerializationUtils; + using namespace ScriptCanvas; + + if (assetData && stream && m_serializeContext) + { AZ::JsonSerializerSettings settings; settings.m_keepDefaults = false; settings.m_serializeContext = m_serializeContext; - rapidjson::Document document; - - if (AZ::JsonSerialization::Store(document, document.GetAllocator(), assetData->GetScriptCanvasData(), settings).GetProcessing() != JSR::Processing::Halted) - { - // \todo replace with with exact function from JsonUtils.cpp once it is moved to AzToolsFramework - AZ::IO::RapidJSONStreamWriter jsonStreamWriter(stream); - rapidjson::PrettyWriter writer(jsonStreamWriter); - return document.Accept(writer); - } + return JSRU::SaveObjectToStream(&assetData->GetScriptCanvasData(), *stream, nullptr, &settings).IsSuccess(); + } + else + { + return false; } - - return false; } void ScriptCanvasAssetHandler::DestroyAsset(AZ::Data::AssetPtr ptr) From fe3b30e42ca96e97c4609de60daacde6d3f4fe60 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Sat, 14 Aug 2021 14:07:36 -0500 Subject: [PATCH 382/803] AtomTools: Fix python terminal help crash ATOM-16242 Checking EditorWindowRequests::GetAppMainWindow before searching for main window Signed-off-by: Guthrie Adams --- .../PythonTerminal/ScriptHelpDialog.cpp | 41 ++++++++++++++++++- .../PythonTerminal/ScriptHelpDialog.h | 34 +-------------- 2 files changed, 42 insertions(+), 33 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/PythonTerminal/ScriptHelpDialog.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/PythonTerminal/ScriptHelpDialog.cpp index ea13d368cd..ba85911060 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/PythonTerminal/ScriptHelpDialog.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/PythonTerminal/ScriptHelpDialog.cpp @@ -6,7 +6,6 @@ * */ - // Description : For listing available script commands with their descriptions #include "ScriptHelpDialog.h" @@ -23,6 +22,7 @@ // AzToolsFramework #include // for EditorPythonConsoleInterface +#include AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING #include @@ -313,6 +313,45 @@ namespace AzToolsFramework connect(ui->tableView, &ScriptTableView::doubleClicked, this, &CScriptHelpDialog::OnDoubleClick); } + CScriptHelpDialog* CScriptHelpDialog::GetInstance() + { + static CScriptHelpDialog* pInstance = nullptr; + if (!pInstance) + { + QMainWindow* mainWindow = GetMainWindowOfCurrentApplication(); + if (!mainWindow) + { + AZ_Assert(false, "Failed to find MainWindow."); + return nullptr; + } + + QWidget* parentWidget = mainWindow->window() + ? mainWindow->window() + : mainWindow; // MainWindow might have a WindowDecorationWrapper parent. Makes a difference on macOS. + pInstance = new CScriptHelpDialog(parentWidget); + } + return pInstance; + } + + QMainWindow* CScriptHelpDialog::GetMainWindowOfCurrentApplication() + { + QWidget* widget = nullptr; + EditorWindowRequestBus::BroadcastResult(widget, &EditorWindowRequests::GetAppMainWindow); + if (QMainWindow* mainWindow = qobject_cast(widget)) + { + return mainWindow; + } + + for (QWidget* widget : qApp->topLevelWidgets()) + { + if (QMainWindow* mainWindow = qobject_cast(widget)) + { + return mainWindow; + } + } + return nullptr; + } + void CScriptHelpDialog::OnDoubleClick(const QModelIndex& index) { if (!index.isValid()) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/PythonTerminal/ScriptHelpDialog.h b/Code/Framework/AzToolsFramework/AzToolsFramework/PythonTerminal/ScriptHelpDialog.h index e34d652e1b..3cefa919c9 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/PythonTerminal/ScriptHelpDialog.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/PythonTerminal/ScriptHelpDialog.h @@ -132,43 +132,13 @@ namespace AzToolsFramework { Q_OBJECT public: - static CScriptHelpDialog* GetInstance() - { - static CScriptHelpDialog* pInstance = nullptr; - if (!pInstance) - { - QMainWindow* mainWindow = GetMainWindowOfCurrentApplication(); - if (!mainWindow) - { - AZ_Assert(false, "Failed to find MainWindow."); - return nullptr; - } - - QWidget* parentWidget = mainWindow->window() ? mainWindow->window() : mainWindow; // MainWindow might have a WindowDecorationWrapper parent. Makes a difference on macOS. - pInstance = new CScriptHelpDialog(parentWidget); - } - return pInstance; - } - + static CScriptHelpDialog* GetInstance(); private Q_SLOTS: void OnDoubleClick(const QModelIndex&); private: - static QMainWindow* GetMainWindowOfCurrentApplication() - { - QMainWindow* mainWindow = nullptr; - for (QWidget* w : qApp->topLevelWidgets()) - { - mainWindow = qobject_cast(w); - if (mainWindow) - { - return mainWindow; - } - } - return nullptr; - } - explicit CScriptHelpDialog(QWidget* parent = nullptr); + static QMainWindow* GetMainWindowOfCurrentApplication(); QScopedPointer ui; }; } // namespace AzToolsFramework From d6c5f1444ba8595df24ce84776a8fec881377e72 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Sat, 14 Aug 2021 14:30:54 -0500 Subject: [PATCH 383/803] fixing hidden variable warning Signed-off-by: Guthrie Adams --- .../PythonTerminal/ScriptHelpDialog.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/PythonTerminal/ScriptHelpDialog.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/PythonTerminal/ScriptHelpDialog.cpp index ba85911060..e9f6cd9e53 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/PythonTerminal/ScriptHelpDialog.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/PythonTerminal/ScriptHelpDialog.cpp @@ -335,16 +335,16 @@ namespace AzToolsFramework QMainWindow* CScriptHelpDialog::GetMainWindowOfCurrentApplication() { - QWidget* widget = nullptr; - EditorWindowRequestBus::BroadcastResult(widget, &EditorWindowRequests::GetAppMainWindow); - if (QMainWindow* mainWindow = qobject_cast(widget)) + QWidget* mainWindowWidget = nullptr; + EditorWindowRequestBus::BroadcastResult(mainWindowWidget, &EditorWindowRequests::GetAppMainWindow); + if (QMainWindow* mainWindow = qobject_cast(mainWindowWidget)) { return mainWindow; } - for (QWidget* widget : qApp->topLevelWidgets()) + for (QWidget* topLevelWidget : qApp->topLevelWidgets()) { - if (QMainWindow* mainWindow = qobject_cast(widget)) + if (QMainWindow* mainWindow = qobject_cast(topLevelWidget)) { return mainWindow; } From 1322a59e9e1ea9c1368da59c8a180bf513ee54a3 Mon Sep 17 00:00:00 2001 From: Pinfel Date: Sat, 14 Aug 2021 16:20:15 -0400 Subject: [PATCH 384/803] Corrected audio component links to documentation Note that the "Audio Animation" component has no documentation so I did not add for it. Signed-off-by: Pinfel --- Gems/LmbrCentral/Code/Source/Audio/AudioProxyComponent.cpp | 2 +- .../Code/Source/Audio/EditorAudioAreaEnvironmentComponent.cpp | 2 +- .../Code/Source/Audio/EditorAudioEnvironmentComponent.cpp | 2 +- .../Code/Source/Audio/EditorAudioListenerComponent.cpp | 2 +- .../Code/Source/Audio/EditorAudioMultiPositionComponent.cpp | 2 +- .../Code/Source/Audio/EditorAudioPreloadComponent.cpp | 2 +- Gems/LmbrCentral/Code/Source/Audio/EditorAudioRtpcComponent.cpp | 2 +- .../Code/Source/Audio/EditorAudioSwitchComponent.cpp | 2 +- .../Code/Source/Audio/EditorAudioTriggerComponent.cpp | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Gems/LmbrCentral/Code/Source/Audio/AudioProxyComponent.cpp b/Gems/LmbrCentral/Code/Source/Audio/AudioProxyComponent.cpp index 8be8aa042e..659fff55d9 100644 --- a/Gems/LmbrCentral/Code/Source/Audio/AudioProxyComponent.cpp +++ b/Gems/LmbrCentral/Code/Source/Audio/AudioProxyComponent.cpp @@ -39,7 +39,7 @@ namespace LmbrCentral ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/AudioProxy.svg") ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) ->Attribute(AZ::Edit::Attributes::AddableByUser, true) - ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/audio-proxy/") + ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/audio/proxy/") ; } } diff --git a/Gems/LmbrCentral/Code/Source/Audio/EditorAudioAreaEnvironmentComponent.cpp b/Gems/LmbrCentral/Code/Source/Audio/EditorAudioAreaEnvironmentComponent.cpp index 2b4741331f..7861244ea4 100644 --- a/Gems/LmbrCentral/Code/Source/Audio/EditorAudioAreaEnvironmentComponent.cpp +++ b/Gems/LmbrCentral/Code/Source/Audio/EditorAudioAreaEnvironmentComponent.cpp @@ -40,7 +40,7 @@ namespace LmbrCentral ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/AudioAreaEnvironment.svg") ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/audio-area-environment/") + ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/audio/area-environment/") ->DataElement(AZ::Edit::UIHandlers::Default, &EditorAudioAreaEnvironmentComponent::m_broadPhaseTriggerArea, "Broad-phase trigger area", "The entity that contains a Trigger Area component for broad-phase checks") ->Attribute(AZ::Edit::Attributes::RequiredService, AZ_CRC("ProximityTriggerService", 0x561f262c)) diff --git a/Gems/LmbrCentral/Code/Source/Audio/EditorAudioEnvironmentComponent.cpp b/Gems/LmbrCentral/Code/Source/Audio/EditorAudioEnvironmentComponent.cpp index b4dd5c4d74..b2633a9cb0 100644 --- a/Gems/LmbrCentral/Code/Source/Audio/EditorAudioEnvironmentComponent.cpp +++ b/Gems/LmbrCentral/Code/Source/Audio/EditorAudioEnvironmentComponent.cpp @@ -33,7 +33,7 @@ namespace LmbrCentral ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/AudioEnvironment.png") ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/audio-environment/") + ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/audio/environment/") ->DataElement("AudioControl", &EditorAudioEnvironmentComponent::m_defaultEnvironment, "Default Environment", "Name of the default ATL Environment control to use") ; } diff --git a/Gems/LmbrCentral/Code/Source/Audio/EditorAudioListenerComponent.cpp b/Gems/LmbrCentral/Code/Source/Audio/EditorAudioListenerComponent.cpp index 205267db73..c9f80ed398 100644 --- a/Gems/LmbrCentral/Code/Source/Audio/EditorAudioListenerComponent.cpp +++ b/Gems/LmbrCentral/Code/Source/Audio/EditorAudioListenerComponent.cpp @@ -36,7 +36,7 @@ namespace LmbrCentral ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/AudioListener.svg") ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/audio-listener/") + ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/audio/listener/") ->DataElement(AZ::Edit::UIHandlers::Default, &EditorAudioListenerComponent::m_rotationEntity, "Rotation Entity", "The Entity whose rotation the audio listener will adopt. If none set, will assume 'this' Entity") ->DataElement(AZ::Edit::UIHandlers::Default, &EditorAudioListenerComponent::m_positionEntity, diff --git a/Gems/LmbrCentral/Code/Source/Audio/EditorAudioMultiPositionComponent.cpp b/Gems/LmbrCentral/Code/Source/Audio/EditorAudioMultiPositionComponent.cpp index 987fa6e0e4..51386b1c02 100644 --- a/Gems/LmbrCentral/Code/Source/Audio/EditorAudioMultiPositionComponent.cpp +++ b/Gems/LmbrCentral/Code/Source/Audio/EditorAudioMultiPositionComponent.cpp @@ -38,7 +38,7 @@ namespace LmbrCentral ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/AudioMultiPosition.svg") ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - // Followup: Need Help URL + ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/audio/multi-position/") ->DataElement(AZ::Edit::UIHandlers::Default, &EditorAudioMultiPositionComponent::m_entityRefs, "Entity References", "The entities from which positions will be obtained for multi-position audio") ->DataElement(AZ::Edit::UIHandlers::ComboBox, &EditorAudioMultiPositionComponent::m_behaviorType, "Behavior Type", "Determines how multi-postion sounds are treated, Separate or Blended") ; diff --git a/Gems/LmbrCentral/Code/Source/Audio/EditorAudioPreloadComponent.cpp b/Gems/LmbrCentral/Code/Source/Audio/EditorAudioPreloadComponent.cpp index a5d137c1b2..a24acac292 100644 --- a/Gems/LmbrCentral/Code/Source/Audio/EditorAudioPreloadComponent.cpp +++ b/Gems/LmbrCentral/Code/Source/Audio/EditorAudioPreloadComponent.cpp @@ -43,7 +43,7 @@ namespace LmbrCentral // Icon todo: //->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/AudioPreload.png") - ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/audio-preload/") + ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/audio/preload/") ->DataElement("AudioControl", &EditorAudioPreloadComponent::m_defaultPreload, "Preload Name", "The default ATL Preload control to use") ->DataElement(AZ::Edit::UIHandlers::ComboBox, &EditorAudioPreloadComponent::m_loadType, "Load Type", "Automatically when the component activates/deactivates, or Manually at user's request") diff --git a/Gems/LmbrCentral/Code/Source/Audio/EditorAudioRtpcComponent.cpp b/Gems/LmbrCentral/Code/Source/Audio/EditorAudioRtpcComponent.cpp index ab98692a50..4426c21ff6 100644 --- a/Gems/LmbrCentral/Code/Source/Audio/EditorAudioRtpcComponent.cpp +++ b/Gems/LmbrCentral/Code/Source/Audio/EditorAudioRtpcComponent.cpp @@ -34,7 +34,7 @@ namespace LmbrCentral ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/AudioRtpc.svg") ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/audio-rtpc/") + ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/audio/rtpc/") ->DataElement("AudioControl", &EditorAudioRtpcComponent::m_defaultRtpc, "Default Rtpc", "The default ATL Rtpc control to use") ; } diff --git a/Gems/LmbrCentral/Code/Source/Audio/EditorAudioSwitchComponent.cpp b/Gems/LmbrCentral/Code/Source/Audio/EditorAudioSwitchComponent.cpp index 6ea89ee31e..1aafbd5c21 100644 --- a/Gems/LmbrCentral/Code/Source/Audio/EditorAudioSwitchComponent.cpp +++ b/Gems/LmbrCentral/Code/Source/Audio/EditorAudioSwitchComponent.cpp @@ -34,7 +34,7 @@ namespace LmbrCentral ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/AudioSwitch.svg") ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/audio-switch/") + ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/audio/switch/") ->DataElement("AudioControl", &EditorAudioSwitchComponent::m_defaultSwitch, "Default Switch", "The default ATL Switch to use when Activated") ->DataElement("AudioControl", &EditorAudioSwitchComponent::m_defaultState, "Default State", "The default ATL State to set on the default Switch when Activated") ; diff --git a/Gems/LmbrCentral/Code/Source/Audio/EditorAudioTriggerComponent.cpp b/Gems/LmbrCentral/Code/Source/Audio/EditorAudioTriggerComponent.cpp index e38caf303b..adecf3c4d0 100644 --- a/Gems/LmbrCentral/Code/Source/Audio/EditorAudioTriggerComponent.cpp +++ b/Gems/LmbrCentral/Code/Source/Audio/EditorAudioTriggerComponent.cpp @@ -43,7 +43,7 @@ namespace LmbrCentral ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/AudioTrigger.svg") ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/audio-trigger/") + ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/audio/trigger/") ->DataElement("AudioControl", &EditorAudioTriggerComponent::m_defaultPlayTrigger, "Default 'play' Trigger", "The default ATL Trigger control used by 'Play'") ->DataElement("AudioControl", &EditorAudioTriggerComponent::m_defaultStopTrigger, "Default 'stop' Trigger", "The default ATL Trigger control used by 'Stop'") ->DataElement(AZ::Edit::UIHandlers::ComboBox, &EditorAudioTriggerComponent::m_obstructionType, "Obstruction Type", "Ray-casts used in calculation of obstruction and occlusion") From 885357a6b54637e407e156313e9b3fb1db592921 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Sat, 14 Aug 2021 16:58:31 -0500 Subject: [PATCH 385/803] AtomTools: restoring log message filter to ignore source control spam Added message filter support to TraceLogger Signed-off-by: Guthrie Adams --- .../AzToolsFramework/Logger/TraceLogger.cpp | 36 +++++++++++++++---- .../AzToolsFramework/Logger/TraceLogger.h | 12 +++++-- .../Application/AtomToolsApplication.cpp | 11 +++--- 3 files changed, 47 insertions(+), 12 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Logger/TraceLogger.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Logger/TraceLogger.cpp index 5f1546bf83..547d328c45 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Logger/TraceLogger.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Logger/TraceLogger.cpp @@ -5,11 +5,9 @@ * */ -#include - #include #include - +#include namespace AzToolsFramework { @@ -25,6 +23,22 @@ namespace AzToolsFramework bool TraceLogger::OnOutput(const char* window, const char* message) { + for (const auto& filter : m_windowFilters) + { + if (AZ::StringFunc::Contains(window, filter)) + { + return true; + } + } + + for (const auto& filter : m_messageFilters) + { + if (AZ::StringFunc::Contains(message, filter)) + { + return true; + } + } + if (m_logFile) { m_logFile->AppendLog(AzFramework::LogFile::SEV_NORMAL, window, message); @@ -36,10 +50,10 @@ namespace AzToolsFramework return false; } - void TraceLogger::WriteStartupLog(const AZStd::string& logFileName) - { + void TraceLogger::PrepareLogFile(const AZStd::string& logFileName) + { using namespace AzFramework; - + AZ::IO::FileIOBase* fileIO = AZ::IO::FileIOBase::GetInstance(); AZ_Assert(fileIO != nullptr, "FileIO should be running at this point"); @@ -71,4 +85,14 @@ namespace AzToolsFramework m_logFile->FlushLog(); } } + + void TraceLogger::AddWindowFilter(const AZStd::string& filter) + { + m_windowFilters.insert(filter); + } + + void TraceLogger::AddMessageFilter(const AZStd::string& filter) + { + m_messageFilters.insert(filter); + } } // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Logger/TraceLogger.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Logger/TraceLogger.h index a10f4fc2df..ac1455452a 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Logger/TraceLogger.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Logger/TraceLogger.h @@ -22,8 +22,14 @@ namespace AzToolsFramework TraceLogger(); ~TraceLogger(); - //! Intalize logging for O3DEToolsApplications - void WriteStartupLog(const AZStd::string& logFileName); + //! Open log file and dump log sink into it + void PrepareLogFile(const AZStd::string& logFileName); + + //! Ignore messages sent to windowd with names matching filter + void AddWindowFilter(const AZStd::string& filter); + + //! Ignore messages with text matching filter + void AddMessageFilter(const AZStd::string& filter); protected: ////////////////////////////////////////////////////////////////////////// @@ -38,6 +44,8 @@ namespace AzToolsFramework AZStd::string message; }; AZStd::vector m_startupLogSink; + AZStd::unordered_set m_windowFilters; + AZStd::unordered_set m_messageFilters; AZStd::unique_ptr m_logFile; }; } // namespace AzToolsFramework diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp index aedad7706b..efd3fec0e8 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp @@ -7,15 +7,15 @@ #include #include - -#include #include +#include #include #include #include -#include #include +#include + #include #include #include @@ -66,6 +66,9 @@ namespace AtomToolsFramework this->PumpSystemEventLoopUntilEmpty(); this->Tick(); }); + + // Suppress spam from the Source Control system + m_traceLogger.AddWindowFilter(AzToolsFramework::SCC_WINDOW); } AtomToolsApplication ::~AtomToolsApplication() @@ -396,7 +399,7 @@ namespace AtomToolsFramework AZStd::string fileName = GetBuildTargetName() + ".log"; - m_traceLogger.WriteStartupLog(fileName.c_str()); + m_traceLogger.PrepareLogFile(fileName.c_str()); if (!LaunchDiscoveryService()) { From 9ecb746563909b6092156ffade30d25077508e44 Mon Sep 17 00:00:00 2001 From: lsemp3d <58790905+lsemp3d@users.noreply.github.com> Date: Sat, 14 Aug 2021 16:50:57 -0700 Subject: [PATCH 386/803] Completed namespace support for the ScriptCanvasGrammar template Signed-off-by: lsemp3d <58790905+lsemp3d@users.noreply.github.com> --- .../AutoGen/ScriptCanvasGrammar_Header.jinja | 2 +- .../AutoGen/ScriptCanvasGrammar_Source.jinja | 21 ++++++++++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/AutoGen/ScriptCanvasGrammar_Header.jinja b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/AutoGen/ScriptCanvasGrammar_Header.jinja index 00c23b9f35..d743a95ee1 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/AutoGen/ScriptCanvasGrammar_Header.jinja +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/AutoGen/ScriptCanvasGrammar_Header.jinja @@ -77,7 +77,7 @@ public: \ {% if Class.attrib['GraphEntryPoint'] is defined %} bool IsEntryPoint() const override { return {%if Class.attrib['GraphEntryPoint'] == "True" %}true{%else%}false{%endif%}; } \ {% endif %} public: \ - friend struct ::{{ className | replace(' ','') }}Property; + friend struct {% if attribute_Namespace is not defined %}::{% endif %}{{ className | replace(' ','') }}Property; // Helpers for easily accessing properties and slots struct {{ className | replace(' ','') }}Property diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/AutoGen/ScriptCanvasGrammar_Source.jinja b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/AutoGen/ScriptCanvasGrammar_Source.jinja index 205e6ebd8c..6a381398c1 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/AutoGen/ScriptCanvasGrammar_Source.jinja +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/AutoGen/ScriptCanvasGrammar_Source.jinja @@ -26,6 +26,20 @@ SPDX-License-Identifier: Apache-2.0 OR MIT #include "{{ xml.attrib['Include'] }}" {% for Class in xml.iter('Class') %} + +{% set attribute_Namespace = undefined %} +{%- if Class.attrib['Namespace'] is defined %} +{% if Class.attrib['Namespace'] != "None" %} +{% set attribute_Namespace = Class.attrib['Namespace'] %} +{% endif %} +{% endif %} + +{% if attribute_Namespace is defined %} +namespace {{attribute_Namespace}} +{ +{% endif %} + + void {{ Class.attrib['QualifiedName'] }}::ConfigureSlots() { {% if Class.attrib['Base'] is defined %} @@ -269,7 +283,12 @@ void {{ Class.attrib['QualifiedName'] }}::Reflect(AZ::ReflectContext* context) return datumValue ? *datumValue : {{ Property.attrib['Type'] }}(); } - {% endfor %} + +{% if attribute_Namespace is defined %} +} +{% endif %} + + {% endfor %} {% endfor %} From 181698b950e63236d77c525964d9af5bbe617932 Mon Sep 17 00:00:00 2001 From: sphrose <82213493+sphrose@users.noreply.github.com> Date: Mon, 16 Aug 2021 10:54:15 +0100 Subject: [PATCH 387/803] LY-91616 Dyn Veg: Push (up) and Pop (down) Items in Descriptor List (#3013) * LY-91616 Dyn Veg: Push (up) and Pop (down) Items in Descriptor List Signed-off-by: sphrose <82213493+sphrose@users.noreply.github.com> * Changes as per reviews. Signed-off-by: sphrose <82213493+sphrose@users.noreply.github.com> * Additional review changes. Signed-off-by: sphrose <82213493+sphrose@users.noreply.github.com> * review change Signed-off-by: sphrose <82213493+sphrose@users.noreply.github.com> --- .../Components/FancyDocking.cpp | 5 +- .../PropertyEditor/EntityPropertyEditor.cpp | 1117 ++++++++++++++--- .../PropertyEditor/EntityPropertyEditor.hxx | 70 +- .../UI/PropertyEditor/PropertyRowWidget.cpp | 183 ++- .../UI/PropertyEditor/PropertyRowWidget.hxx | 21 + .../ReflectedPropertyEditor.cpp | 224 +++- .../ReflectedPropertyEditor.hxx | 10 + 7 files changed, 1441 insertions(+), 189 deletions(-) diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/FancyDocking.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Components/FancyDocking.cpp index c5aa1a3f88..4ced4ea635 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Components/FancyDocking.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/FancyDocking.cpp @@ -1882,7 +1882,10 @@ namespace AzQtComponents return; } - QApplication::setOverrideCursor(m_dragCursor); + if (!QApplication::overrideCursor()) + { + QApplication::setOverrideCursor(m_dragCursor); + } QPoint relativePressPos = pressPos; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.cpp index f166e85ff9..2c46bb2d26 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.cpp @@ -16,6 +16,7 @@ AZ_POP_DISABLE_WARNING #include #include #include +#include #include #include #include @@ -106,7 +107,11 @@ void initEntityPropertyEditorResources() namespace AzToolsFramework { - static const char* kComponentEditorIndexMimeType = "editor/componentEditorIndices"; + constexpr const char* kComponentEditorIndexMimeType = "editor/componentEditorIndices"; + constexpr const char* kComponentEditorRowWidgetType = "editor/componentEditorRowWidget"; + + constexpr const char* kPropertyEditorMenuActionMoveUp("editor/propertyEditorMoveUp"); + constexpr const char* kPropertyEditorMenuActionMoveDown("editor/propertyEditorMoveDown"); //since component editors are spaced apart to make room for drop indicator, //giving drop logic simple buffer so drops between editors don't go to the bottom @@ -149,6 +154,7 @@ namespace AzToolsFramework : QWidget(parent) , m_editor(editor) , m_dropIndicatorOffset(8) + , m_dropIndicatorRowWidgetOffset(2) { setPalette(Qt::transparent); setWindowFlags(Qt::FramelessWindowHint); @@ -158,22 +164,137 @@ namespace AzToolsFramework } protected: - void paintEvent(QPaintEvent* event) override + static constexpr int TopMargin = 1; + static constexpr int RightMargin = 2; + static constexpr int BottomMargin = 5; + static constexpr int LeftMargin = 2; + static constexpr int RowHighlightIndent = 2; + + void paintDraggingRowWidget(QPainter& painter) { - const int TopMargin = 1; - const int RightMargin = 2; - const int BottomMargin = 5; - const int LeftMargin = 2; + ComponentEditor* rowWidgetEditor = m_editor->GetEditorForCurrentReorderRowWidget(); + PropertyRowWidget* dragRowWidget = m_editor->GetReorderRowWidget(); + PropertyRowWidget* dropTarget = m_editor->GetReorderDropTarget(); + EntityPropertyEditor::DropArea dropArea = m_editor->GetReorderDropArea(); - QWidget::paintEvent(event); + // The user is dragging a row widget. + for (auto componentEditor : m_editor->m_componentEditors) + { + if (!componentEditor->isVisible()) + { + continue; + } - QPainter painter(this); - painter.setCompositionMode(QPainter::CompositionMode_SourceOver); + if (componentEditor != rowWidgetEditor) + { + continue; + } - QRect currRect; + for (auto& [dataNode, rowWidget] : componentEditor->GetPropertyEditor()->GetWidgets()) + { + if (!rowWidget->isVisible()) + { + continue; + } + + QRect globalRect = m_editor->GetWidgetAndVisibleChildrenGlobalRect(rowWidget); + + QRect currRect = QRect( + QPoint(mapFromGlobal(globalRect.topLeft()) + QPoint(LeftMargin, TopMargin)), + QPoint(mapFromGlobal(globalRect.bottomRight()) - QPoint(RightMargin, BottomMargin))); + + currRect.setLeft(LeftMargin + RowHighlightIndent); + currRect.setWidth(rowWidget->GetContainingEditorFrameWidth() - (RightMargin + LeftMargin)); + + if (rowWidget == dragRowWidget) + { + QStyleOption opt; + opt.init(this); + opt.rect = currRect; + qobject_cast (style())->drawDragIndicator(&opt, &painter, this); + } + + if (rowWidget == dropTarget) + { + QRect dropRect = currRect; + if (dropArea == EntityPropertyEditor::DropArea::Above) + { + dropRect.setTop(currRect.top() - m_dropIndicatorRowWidgetOffset); + } + else + { + dropRect.setTop(currRect.bottom()); + } + + dropRect.setHeight(0); + + QStyleOption opt; + opt.init(this); + opt.rect = dropRect; + style()->drawPrimitive(QStyle::PE_IndicatorItemViewItemDrop, &opt, &painter, this); + } + } + } + }; + + void paintMenuHighlight(QPainter& painter, float alpha) + { + // If a RowWidget can be moved up or down, highlight it. + PropertyRowWidget* dragRowWidget = m_editor->GetReorderRowWidget(); + if (!dragRowWidget) + { + return; + } + + PropertyRowWidget* dropTarget = m_editor->GetReorderDropTarget(); + EntityPropertyEditor::DropArea dropArea = m_editor->GetReorderDropArea(); + QPixmap dragImage = m_editor->GetReorderRowWidgetImage(); + + // User has the context menu open with a movable row selected. + QRect globalRect = m_editor->GetWidgetAndVisibleChildrenGlobalRect(dragRowWidget); + + int top = mapFromGlobal(globalRect.topLeft()).y(); + int imageHeight = dragImage.height() / dragImage.devicePixelRatioF(); + int imageWidth = dragImage.width() / dragImage.devicePixelRatioF(); + QRect currRect = QRect(QPoint(LeftMargin + 1, top), QPoint(LeftMargin + 1 + imageWidth, top + imageHeight)); + + painter.setOpacity(alpha); + painter.drawPixmap(currRect, dragImage); + + if (dropTarget) + { + // A move row menu command is highlighted. Draw an indicator to show where the current row will move to. + globalRect = m_editor->GetWidgetAndVisibleChildrenGlobalRect(dropTarget); + QRect dropRect = QRect( + QPoint(mapFromGlobal(globalRect.topLeft()) + QPoint(LeftMargin, TopMargin)), + QPoint(mapFromGlobal(globalRect.bottomRight()) - QPoint(RightMargin, TopMargin))); + + if (dropArea == EntityPropertyEditor::DropArea::Above) + { + dropRect.setTop(dropRect.top() - m_dropIndicatorRowWidgetOffset); + } + else + { + dropRect.setTop(dropRect.bottom()); + } + dropRect.setHeight(0); + + painter.setOpacity(alpha); + QStyleOption lineOpt; + lineOpt.init(this); + lineOpt.rect = dropRect; + style()->drawPrimitive(QStyle::PE_IndicatorItemViewItemDrop, &lineOpt, &painter, this); + painter.setOpacity(1.0f); + } + }; + + void paintDraggingComponent(QPainter& painter) + { bool drag = false; bool drop = false; + QRect currRect; + // Check for a component editor being dragged. for (auto componentEditor : m_editor->m_componentEditors) { if (!componentEditor->isVisible()) @@ -185,8 +306,7 @@ namespace AzToolsFramework currRect = QRect( QPoint(mapFromGlobal(globalRect.topLeft()) + QPoint(LeftMargin, TopMargin)), - QPoint(mapFromGlobal(globalRect.bottomRight()) - QPoint(RightMargin, BottomMargin)) - ); + QPoint(mapFromGlobal(globalRect.bottomRight()) - QPoint(RightMargin, BottomMargin))); currRect.setWidth(currRect.width() - 1); currRect.setHeight(currRect.height() - 1); @@ -226,6 +346,67 @@ namespace AzToolsFramework opt.rect = dropRect; style()->drawPrimitive(QStyle::PE_IndicatorItemViewItemDrop, &opt, &painter, this); } + }; + + void paintMovedRow(QPainter& painter, float alpha) + { + // After a move has been carried out, briefly highlight the moved row. + PropertyRowWidget* rowWidget = m_editor->GetRowToHighlight(); + + if (!rowWidget) + { + return; + } + + QRect globalRect = m_editor->GetWidgetAndVisibleChildrenGlobalRect(rowWidget); + QRect currRect = QRect( + QPoint(mapFromGlobal(globalRect.topLeft()) + QPoint(LeftMargin, TopMargin)), + QPoint(mapFromGlobal(globalRect.bottomRight()) - QPoint(RightMargin, BottomMargin))); + + currRect.setLeft(LeftMargin + 2); + currRect.setWidth(rowWidget->GetContainingEditorFrameWidth() - (RightMargin + LeftMargin)); + + painter.setOpacity(alpha); + + QPen pen; + QColor drawColor = Qt::white; + drawColor.setAlphaF(alpha); + pen.setColor(drawColor); + pen.setWidth(1); + painter.setPen(pen); + painter.drawRect(currRect); + } + + void paintEvent(QPaintEvent* event) override + { + QWidget::paintEvent(event); + + QPainter painter(this); + painter.setCompositionMode(QPainter::CompositionMode_SourceOver); + + EntityPropertyEditor::ReorderState currentState = m_editor->GetReorderState(); + float indicatorAlpha = m_editor->GetMoveIndicatorAlpha(); + + switch (currentState) + { + case EntityPropertyEditor::ReorderState::DraggingRowWidget: + paintDraggingRowWidget(painter); + break; + case EntityPropertyEditor::ReorderState::UsingMenu: + paintMenuHighlight(painter, 1.0f); + break; + case EntityPropertyEditor::ReorderState::MenuOperationInProgress: + paintMenuHighlight(painter, indicatorAlpha); + break; + case EntityPropertyEditor::ReorderState::DraggingComponent: + paintDraggingComponent(painter); + break; + case EntityPropertyEditor::ReorderState::HighlightMovedRow: + paintMovedRow(painter, indicatorAlpha); + break; + default: + break; + } } bool event(QEvent* ev) override @@ -280,6 +461,7 @@ namespace AzToolsFramework private: EntityPropertyEditor* m_editor; int m_dropIndicatorOffset; + int m_dropIndicatorRowWidgetOffset; }; EntityPropertyEditor::SharedComponentInfo::SharedComponentInfo(AZ::Component* component, AZ::Component* sliceReferenceComponent) @@ -382,6 +564,9 @@ namespace AzToolsFramework m_emptyIcon = QIcon(); m_clearIcon = QIcon(":/AssetBrowser/Resources/close.png"); + m_dragIcon = QIcon(QStringLiteral(":/Cursors/Grabbing.svg")); + m_dragCursor = QCursor(m_dragIcon.pixmap(16), 10, 5); + m_serializeContext = nullptr; AZ::ComponentApplicationBus::BroadcastResult(m_serializeContext, &AZ::ComponentApplicationRequests::GetSerializeContext); AZ_Assert(m_serializeContext, "Failed to acquire application serialize context."); @@ -1867,6 +2052,12 @@ namespace AzToolsFramework return; } + // Don't show if a move operation is pending. + if (m_currentReorderState != ReorderState::Inactive) + { + return; + } + // Locate the owning component and class data corresponding to the clicked node. InstanceDataNode* componentNode = node; while (componentNode->GetParent()) @@ -1905,7 +2096,12 @@ namespace AzToolsFramework if (!menu.actions().empty()) { + m_currentReorderState = EntityPropertyEditor::ReorderState::UsingMenu; menu.exec(position); + if (m_currentReorderState != EntityPropertyEditor::ReorderState::MenuOperationInProgress) + { + m_currentReorderState = EntityPropertyEditor::ReorderState::Inactive; + } } } } @@ -1956,129 +2152,179 @@ namespace AzToolsFramework AZ::SliceComponent* rootSlice = nullptr; AzFramework::SliceEntityOwnershipServiceRequestBus::EventResult(rootSlice, contextId, &AzFramework::SliceEntityOwnershipServiceRequestBus::Events::GetRootSlice); - if (!rootSlice) + if (rootSlice) { - return; - } - - AZ::SliceComponent::SliceInstanceAddress address; - AzFramework::SliceEntityRequestBus::EventResult(address, entity->GetId(), - &AzFramework::SliceEntityRequests::GetOwningSlice); - AZ::SliceComponent::SliceReference* sliceReference = address.GetReference(); - if (sliceReference) - { - // This entity is instanced from a slice, so show data push/pull options - AZ::SliceComponent::EntityAncestorList ancestors; - sliceReference->GetInstanceEntityAncestry(entity->GetId(), ancestors); - - AZ_Error("PropertyEditor", !ancestors.empty(), "Entity \"%s\" belongs to a slice, but its source entity could not be located.", entity->GetName().c_str()); - if (!ancestors.empty()) + AZ::SliceComponent::SliceInstanceAddress address; + AzFramework::SliceEntityRequestBus::EventResult(address, entity->GetId(), &AzFramework::SliceEntityRequests::GetOwningSlice); + AZ::SliceComponent::SliceReference* sliceReference = address.GetReference(); + if (sliceReference) { - menu.addSeparator(); + // This entity is instanced from a slice, so show data push/pull options + AZ::SliceComponent::EntityAncestorList ancestors; + sliceReference->GetInstanceEntityAncestry(entity->GetId(), ancestors); - // Populate slice push options. - // Address should start with the fully-addressable component Id to resolve within the target entity. - InstanceDataHierarchy::Address pushFieldAddress; - CalculateAndAdjustNodeAddress(*fieldNode, AddressRootType::RootAtEntity, pushFieldAddress); - if (!pushFieldAddress.empty()) + AZ_Error( + "PropertyEditor", !ancestors.empty(), "Entity \"%s\" belongs to a slice, but its source entity could not be located.", + entity->GetName().c_str()); + if (!ancestors.empty()) { - SliceUtilities::PopulateQuickPushMenu( - menu, - entity->GetId(), - pushFieldAddress, - SliceUtilities::QuickPushMenuOptions("Save field override", SliceUtilities::QuickPushMenuOverrideDisplayCount::ShowOverrideCountOnlyWhenMultiple)); + menu.addSeparator(); + + // Populate slice push options. + // Address should start with the fully-addressable component Id to resolve within the target entity. + InstanceDataHierarchy::Address pushFieldAddress; + CalculateAndAdjustNodeAddress(*fieldNode, AddressRootType::RootAtEntity, pushFieldAddress); + if (!pushFieldAddress.empty()) + { + SliceUtilities::PopulateQuickPushMenu( + menu, entity->GetId(), pushFieldAddress, + SliceUtilities::QuickPushMenuOptions( + "Save field override", + SliceUtilities::QuickPushMenuOverrideDisplayCount::ShowOverrideCountOnlyWhenMultiple)); + } } } - } - menu.addSeparator(); + menu.addSeparator(); - // by leaf node, we mean a visual leaf node in the property editor (ie, we do not have any visible children) - bool isLeafNode = !fieldNode->GetClassMetadata() || !fieldNode->GetClassMetadata()->m_container; + // by leaf node, we mean a visual leaf node in the property editor (ie, we do not have any visible children) + bool isLeafNode = !fieldNode->GetClassMetadata() || !fieldNode->GetClassMetadata()->m_container; - if (isLeafNode) - { - for (const InstanceDataNode& childNode : fieldNode->GetChildren()) + if (isLeafNode) { - if (HasAnyVisibleElements(childNode)) + for (const InstanceDataNode& childNode : fieldNode->GetChildren()) { - // If we have any visible children, we must not be a leaf node - isLeafNode = false; - break; + if (HasAnyVisibleElements(childNode)) + { + // If we have any visible children, we must not be a leaf node + isLeafNode = false; + break; + } } } - } #ifdef ENABLE_SLICE_EDITOR - // Show PreventOverride & HideProperty options - if (GetEntityDataPatchAddress(fieldNode, m_dataPatchAddressBuffer)) - { - AZ::DataPatch::Flags nodeFlags = rootSlice->GetEntityDataFlagsAtAddress(entity->GetId(), m_dataPatchAddressBuffer); + // Show PreventOverride & HideProperty options + if (GetEntityDataPatchAddress(fieldNode, m_dataPatchAddressBuffer)) + { + AZ::DataPatch::Flags nodeFlags = rootSlice->GetEntityDataFlagsAtAddress(entity->GetId(), m_dataPatchAddressBuffer); - if (nodeFlags & AZ::DataPatch::Flag::PreventOverrideSet) - { - QAction* PreventOverrideAction = menu.addAction(tr("Allow property override")); - PreventOverrideAction->setEnabled(isLeafNode); - connect(PreventOverrideAction, &QAction::triggered, this, [this, fieldNode] + if (nodeFlags & AZ::DataPatch::Flag::PreventOverrideSet) { - ContextMenuActionSetDataFlag(fieldNode, AZ::DataPatch::Flag::PreventOverrideSet, false); - InvalidatePropertyDisplay(Refresh_AttributesAndValues); + QAction* PreventOverrideAction = menu.addAction(tr("Allow property override")); + PreventOverrideAction->setEnabled(isLeafNode); + connect( + PreventOverrideAction, &QAction::triggered, this, + [this, fieldNode] + { + ContextMenuActionSetDataFlag(fieldNode, AZ::DataPatch::Flag::PreventOverrideSet, false); + InvalidatePropertyDisplay(Refresh_AttributesAndValues); + }); } - ); - } - else - { - QAction* PreventOverrideAction = menu.addAction(tr("Prevent property override")); - PreventOverrideAction->setEnabled(isLeafNode); - connect(PreventOverrideAction, &QAction::triggered, this, [this, fieldNode] + else { - ContextMenuActionSetDataFlag(fieldNode, AZ::DataPatch::Flag::PreventOverrideSet, true); - InvalidatePropertyDisplay(Refresh_AttributesAndValues); + QAction* PreventOverrideAction = menu.addAction(tr("Prevent property override")); + PreventOverrideAction->setEnabled(isLeafNode); + connect( + PreventOverrideAction, &QAction::triggered, this, + [this, fieldNode] + { + ContextMenuActionSetDataFlag(fieldNode, AZ::DataPatch::Flag::PreventOverrideSet, true); + InvalidatePropertyDisplay(Refresh_AttributesAndValues); + }); } - ); - } - if (nodeFlags & AZ::DataPatch::Flag::HidePropertySet) - { - QAction* HideProperyAction = menu.addAction(tr("Show property on instances")); - HideProperyAction->setEnabled(isLeafNode); - connect(HideProperyAction, &QAction::triggered, this, [this, fieldNode] + if (nodeFlags & AZ::DataPatch::Flag::HidePropertySet) { - ContextMenuActionSetDataFlag(fieldNode, AZ::DataPatch::Flag::HidePropertySet, false); - InvalidatePropertyDisplay(Refresh_AttributesAndValues); + QAction* HideProperyAction = menu.addAction(tr("Show property on instances")); + HideProperyAction->setEnabled(isLeafNode); + connect( + HideProperyAction, &QAction::triggered, this, + [this, fieldNode] + { + ContextMenuActionSetDataFlag(fieldNode, AZ::DataPatch::Flag::HidePropertySet, false); + InvalidatePropertyDisplay(Refresh_AttributesAndValues); + }); } - ); - } - else - { - QAction* HideProperyAction = menu.addAction(tr("Hide property on instances")); - HideProperyAction->setEnabled(isLeafNode); - connect(HideProperyAction, &QAction::triggered, this, [this, fieldNode] + else { - ContextMenuActionSetDataFlag(fieldNode, AZ::DataPatch::Flag::HidePropertySet, true); - InvalidatePropertyDisplay(Refresh_AttributesAndValues); + QAction* HideProperyAction = menu.addAction(tr("Hide property on instances")); + HideProperyAction->setEnabled(isLeafNode); + connect( + HideProperyAction, &QAction::triggered, this, + [this, fieldNode] + { + ContextMenuActionSetDataFlag(fieldNode, AZ::DataPatch::Flag::HidePropertySet, true); + InvalidatePropertyDisplay(Refresh_AttributesAndValues); + }); } - ); } - } #endif - if (sliceReference) - { - // This entity is referenced from a slice, so show property override options - bool hasChanges = fieldNode->HasChangesVersusComparison(false); - - if (!hasChanges && isLeafNode) + if (sliceReference) { - // Add an option to set the ForceOverride flag for this field - menu.setToolTipsVisible(true); - QAction* forceOverrideAction = menu.addAction(tr("Force property override")); - forceOverrideAction->setToolTip(tr("Prevents a property from inheriting from its source slice")); - connect(forceOverrideAction, &QAction::triggered, this, [this, fieldNode]() - { - ContextMenuActionSetDataFlag(fieldNode, AZ::DataPatch::Flag::ForceOverrideSet, true); - } - ); + // This entity is referenced from a slice, so show property override options + bool hasChanges = fieldNode->HasChangesVersusComparison(false); + + if (!hasChanges && isLeafNode) + { + // Add an option to set the ForceOverride flag for this field + menu.setToolTipsVisible(true); + QAction* forceOverrideAction = menu.addAction(tr("Force property override")); + forceOverrideAction->setToolTip(tr("Prevents a property from inheriting from its source slice")); + connect( + forceOverrideAction, &QAction::triggered, this, + [this, fieldNode]() + { + ContextMenuActionSetDataFlag(fieldNode, AZ::DataPatch::Flag::ForceOverrideSet, true); + }); + } + } + } + + m_reorderRowWidget = nullptr; + // Add move up/down actions if appropriate + auto componentEditorIterator = m_componentToEditorMap.find(componentInstance); + AZ_Assert(componentEditorIterator != m_componentToEditorMap.end(), "Unable to find a component editor for the given component"); + if (componentEditorIterator != m_componentToEditorMap.end()) + { + m_reorderRowWidgetEditor = componentEditorIterator->second; + PropertyRowWidget* widget = componentEditorIterator->second->GetPropertyEditor()->GetWidgetFromNode(fieldNode); + if (widget->CanBeReordered()) + { + m_reorderRowWidget = widget; + SetRowWidgetHighlighted(widget); + + QAction* moveUpAction = menu.addAction(tr("Move %1 Up").arg(widget->GetNameLabel()->text())); + moveUpAction->setEnabled(false); + moveUpAction->setData(kPropertyEditorMenuActionMoveUp); + + if (widget->CanMoveUp()) + { + moveUpAction->setEnabled(true); + connect( + moveUpAction, &QAction::triggered, this, + [this, widget] + { + ContextMenuActionMoveItemUp(m_reorderRowWidgetEditor, widget); + }); + } + + QAction* moveDownAction = menu.addAction(tr("Move %1 Down").arg(widget->GetNameLabel()->text())); + moveDownAction->setEnabled(false); + moveDownAction->setData(kPropertyEditorMenuActionMoveDown); + if (widget->CanMoveDown()) + { + moveDownAction->setEnabled(true); + connect( + moveDownAction, &QAction::triggered, this, + [this, widget] + { + ContextMenuActionMoveItemDown(m_reorderRowWidgetEditor, widget); + }); + } + + menu.addSeparator(); } } } @@ -2380,6 +2626,98 @@ namespace AzToolsFramework } } + void EntityPropertyEditor::BeginMoveRowWidgetFade() + { + // Fade out the highlights and indicator bar for two seconds before moving. + m_moveFadeSecondsRemaining = MoveFadeSeconds; + m_currentReorderState = EntityPropertyEditor::ReorderState::MenuOperationInProgress; + AZ::TickBus::Handler::BusConnect(); + } + + void EntityPropertyEditor::HighlightMovedRowWidget() + { + if (m_currentReorderState != ReorderState::WaitForRedraw) + { + return; + } + UpdateOverlay(); + + m_currentReorderState = ReorderState::HighlightMovedRow; + m_moveFadeSecondsRemaining = MoveFadeSeconds; + + AZ::TickBus::Handler::BusConnect(); + m_overlay->setVisible(true); + } + + void EntityPropertyEditor::OnTick(float deltaTime, AZ::ScriptTimePoint /*time*/) + { + m_moveFadeSecondsRemaining -= deltaTime; + m_overlay->setVisible(true); + if (m_moveFadeSecondsRemaining <= 0.0f) + { + m_moveFadeSecondsRemaining = 0.0f; + + if (m_currentReorderState == ReorderState::MenuOperationInProgress) + { + m_reorderRowWidgetEditor->GetPropertyEditor()->MoveNodeToIndex(m_nodeToMove, m_indexMapOfMovedRow[0]); + + // Ensure the highlight gets drawn once the RPE is updated. + m_currentReorderState = ReorderState::WaitForRedraw; + AZ::TickBus::Handler::BusDisconnect(); + ScrollToNewComponent(); + } + else + { + m_currentReorderState = ReorderState::Inactive; + AZ::TickBus::Handler::BusDisconnect(); + m_overlay->setVisible(false); + } + } + + // Force a repaint to show the fade. + repaint(0, 0, -1, -1); + } + + void EntityPropertyEditor::GenerateRowWidgetIndexMapToChildIndex(PropertyRowWidget* parent, int destIndex) + { + m_indexMapOfMovedRow.clear(); + m_indexMapOfMovedRow.push_back(destIndex); + + while (parent) + { + int index = parent->GetIndexInParent(); + if (index < 0) + { + // Top level widget. + break; + } + m_indexMapOfMovedRow.push_back(parent->GetIndexInParent()); + parent = parent->GetParentRow(); + } + } + + void EntityPropertyEditor::ContextMenuActionMoveItemUp(ComponentEditor* componentEditor, PropertyRowWidget* rowWidget) + { + // After the RPE is rebuilt, there'll be no way to work out which is the moved RowWidget. + // Generate a map of the child indices up to the root. + PropertyRowWidget* parent = rowWidget->GetParentRow(); + GenerateRowWidgetIndexMapToChildIndex(parent, rowWidget->GetIndexInParent() - 1); + + m_reorderRowWidgetEditor = componentEditor; + m_nodeToMove = rowWidget->GetNode(); + BeginMoveRowWidgetFade(); + } + + void EntityPropertyEditor::ContextMenuActionMoveItemDown(ComponentEditor* componentEditor, PropertyRowWidget* rowWidget) + { + PropertyRowWidget* parent = rowWidget->GetParentRow(); + GenerateRowWidgetIndexMapToChildIndex(parent, rowWidget->GetIndexInParent() + 1); + + m_reorderRowWidgetEditor = componentEditor; + m_nodeToMove = rowWidget->GetNode(); + BeginMoveRowWidgetFade(); + } + void EntityPropertyEditor::CalculateAndAdjustNodeAddress(const InstanceDataNode& componentFieldNode, AddressRootType rootType, InstanceDataNode::Address& outAddress) const { outAddress = componentFieldNode.ComputeAddress(); @@ -2763,9 +3101,7 @@ namespace AzToolsFramework if (!menu.actions().empty()) { - m_isShowingContextMenu = true; menu.exec(position); - m_isShowingContextMenu = false; } } @@ -3463,6 +3799,76 @@ namespace AzToolsFramework return this == widget || isAncestorOf(widget); } + AZ::u32 EntityPropertyEditor::GetHeightOfRowAndVisibleChildren(const PropertyRowWidget* row) const + { + if (!row->isVisible()) + { + return 0; + } + + QRect rect = QRect(row->mapToGlobal(row->rect().topLeft()), row->mapToGlobal(row->rect().bottomRight())); + + AZ::u32 height = rect.height() + 1; + + for (AZ::u32 childIndex = 0; childIndex < row->GetChildRowCount(); childIndex++) + { + PropertyRowWidget* childRow = row->GetChildRowByIndex(childIndex); + if (childRow->isVisible()) + { + height += GetHeightOfRowAndVisibleChildren(childRow); + } + } + + return height; + } + + QRect EntityPropertyEditor::GetWidgetAndVisibleChildrenGlobalRect(const PropertyRowWidget* widget) const + { + QRect rect = QRect(widget->mapToGlobal(widget->rect().topLeft()), widget->mapToGlobal(widget->rect().bottomRight())); + rect.setHeight(GetHeightOfRowAndVisibleChildren(widget)); + + return rect; + } + + PropertyRowWidget* EntityPropertyEditor::GetRowWidgetAtSameLevelAfter(PropertyRowWidget* widget) const + { + PropertyRowWidget* parent = widget->GetParentRow(); + + bool found = false; + for (PropertyRowWidget* child : parent->GetChildrenRows()) + { + if (found) + { + return child; + } + + if (child == widget) + { + found = true; + } + } + + return nullptr; + } + + PropertyRowWidget* EntityPropertyEditor::GetRowWidgetAtSameLevelBefore(PropertyRowWidget* widget) const + { + PropertyRowWidget* parent = widget->GetParentRow(); + + PropertyRowWidget* previous = nullptr; + for (PropertyRowWidget* child : parent->GetChildrenRows()) + { + if (child == widget) + { + return previous; + } + + previous = child; + } + + return nullptr; + } + QRect EntityPropertyEditor::GetWidgetGlobalRect(const QWidget* widget) const { return QRect( @@ -3757,6 +4163,8 @@ namespace AzToolsFramework m_shouldScrollToNewComponents = false; m_shouldScrollToNewComponentsQueued = false; m_newComponentId.reset(); + + HighlightMovedRowWidget(); } void EntityPropertyEditor::QueueScrollToNewComponent() @@ -3909,9 +4317,64 @@ namespace AzToolsFramework event->accept(); } + bool EntityPropertyEditor::HandleMenuEvent(QObject* /*object*/, QEvent* event) + { + QMenu* menu = qobject_cast(QApplication::activePopupWidget()); + if (!menu) + { + return false; + } + + PropertyRowWidget* lastReorderDropTarget = m_reorderDropTarget; + + switch (event->type()) + { + case QEvent::Leave: + m_reorderDropTarget = nullptr; + break; + case QEvent::Enter: + // Drop through. + case QEvent::MouseMove: + QMouseEvent* originalMouseEvent = static_cast(event); + QAction* action = menu->actionAt(originalMouseEvent->pos()); + if (!action) + { + m_reorderDropTarget = nullptr; + break; + } + + if (action->data() == kPropertyEditorMenuActionMoveUp) + { + m_reorderDropTarget = GetRowWidgetAtSameLevelBefore(m_reorderRowWidget); + + m_reorderDropArea = EntityPropertyEditor::DropArea::Above; + } + else if (action->data() == kPropertyEditorMenuActionMoveDown) + { + m_reorderDropTarget = GetRowWidgetAtSameLevelAfter(m_reorderRowWidget); + + if (m_reorderDropTarget) + { + m_reorderDropArea = EntityPropertyEditor::DropArea::Below; + } + } + + break; + } + + if (lastReorderDropTarget != m_reorderDropTarget) + { + // Force a redraw as the menu is preventing automatic updates. + repaint(0, 0, -1, -1); + } + + return false; + } + //overridden to intercept application level mouse events for component editor selection bool EntityPropertyEditor::eventFilter(QObject* object, QEvent* event) { + HandleMenuEvent(object, event); HandleSelectionEvents(object, event); return false; } @@ -3919,11 +4382,23 @@ namespace AzToolsFramework void EntityPropertyEditor::mousePressEvent(QMouseEvent* event) { ResetDrag(event); + + PropertyRowWidget* rowWidget = FindPropertyRowWidgetAt(event->globalPos()); + if (rowWidget && rowWidget->CanBeReordered() && event->buttons() & Qt::LeftButton) + { + QApplication::setOverrideCursor(m_dragCursor); + } } void EntityPropertyEditor::mouseReleaseEvent(QMouseEvent* event) { ResetDrag(event); + + Qt::MouseButtons realButtons = QApplication::mouseButtons(); + if (QApplication::overrideCursor() && !(event->buttons() & Qt::LeftButton)) + { + QApplication::restoreOverrideCursor(); + } } void EntityPropertyEditor::mouseMoveEvent(QMouseEvent* event) @@ -3963,6 +4438,21 @@ namespace AzToolsFramework void EntityPropertyEditor::dropEvent(QDropEvent* event) { HandleDrop(event); + + if (QApplication::overrideCursor()) + { + QApplication::restoreOverrideCursor(); + } + } + + void EntityPropertyEditor::DragStopped() + { + if (QApplication::overrideCursor()) + { + QApplication::restoreOverrideCursor(); + } + + EndRowWidgetReorder(); } bool EntityPropertyEditor::HandleSelectionEvents(QObject* object, QEvent* event) @@ -4319,11 +4809,110 @@ namespace AzToolsFramework return true; } + bool EntityPropertyEditor::FindAllowedRowWidgetReorderDropTarget(const QPoint& globalPos) + { + const QRect globalRect(globalPos, globalPos); + + AZ_Assert(m_reorderRowWidgetEditor, "Missing editor for row widget drag."); + + AzToolsFramework::ReflectedPropertyEditor::WidgetList widgets = m_reorderRowWidgetEditor->GetPropertyEditor()->GetWidgets(); + for (auto widgetPair : widgets) + { + PropertyRowWidget* widget = widgetPair.second; + if (!widget) + { + continue; + } + + if (DoesIntersectWidget(globalRect, reinterpret_cast(widget))) + { + if (widget->CanBeReordered() && widget->GetParentRow() == m_reorderRowWidget->GetParentRow()) + { + m_reorderDropTarget = widget; + + QRect widgetRect = GetWidgetAndVisibleChildrenGlobalRect(widget); + if (globalPos.y() < widgetRect.center().y()) + { + m_reorderDropArea = EntityPropertyEditor::DropArea::Above; + } + else + { + m_reorderDropArea = EntityPropertyEditor::DropArea::Below; + } + + return true; + } + + // We're hovering over a child of a reorderable ancestor, use the ancestor as the drop target. + PropertyRowWidget* parent = widget->GetParentRow(); + while (parent) + { + if (parent->CanBeReordered() && parent->GetParentRow() == m_reorderRowWidget->GetParentRow()) + { + m_reorderDropTarget = parent; + + QRect widgetRect = GetWidgetAndVisibleChildrenGlobalRect(parent); + if (globalPos.y() < widgetRect.center().y()) + { + m_reorderDropArea = EntityPropertyEditor::DropArea::Above; + } + else + { + m_reorderDropArea = EntityPropertyEditor::DropArea::Below; + } + + return true; + } + parent = parent->GetParentRow(); + } + } + } + + return false; + } + + bool EntityPropertyEditor::UpdateRowWidgetDrag(const QPoint& localPos, Qt::MouseButtons mouseButtons, const QMimeData* /*mimeData*/) + { + const QPoint globalPos(mapToGlobal(localPos)); + const QRect globalRect(globalPos, globalPos); + + if (!m_reorderRowWidget) + { + return false; + } + + if (m_reorderDropTarget) + { + m_reorderDropTarget = nullptr; + } + + UpdateOverlay(); + + // additional checks since handling is done in event filter + if ((mouseButtons & Qt::LeftButton) && DoesIntersectWidget(globalRect, this)) + { + FindAllowedRowWidgetReorderDropTarget(globalPos); + { + UpdateOverlay(); + return true; + } + } + return false; + } + bool EntityPropertyEditor::UpdateDrag(const QPoint& localPos, Qt::MouseButtons mouseButtons, const QMimeData* mimeData) { const QPoint globalPos(mapToGlobal(localPos)); const QRect globalRect(globalPos, globalPos); + if (m_reorderRowWidget) + { + UpdateRowWidgetDrag(localPos, mouseButtons, mimeData); + QueueAutoScroll(); + UpdateOverlay(); + return true; + } + //reset drop indicators for (auto componentEditor : m_componentEditors) { @@ -4357,6 +4946,28 @@ namespace AzToolsFramework return false; } + PropertyRowWidget* EntityPropertyEditor::FindPropertyRowWidgetAt(QPoint globalPos) + { + const QRect globalRect(globalPos, globalPos); + + const bool dragSelected = DoesIntersectSelectedComponentEditor(globalRect); + const auto& componentEditors = dragSelected ? GetSelectedComponentEditors() : GetIntersectingComponentEditors(globalRect); + + for (auto componentEditor : componentEditors) + { + AzToolsFramework::ReflectedPropertyEditor::WidgetList widgets = componentEditor->GetPropertyEditor()->GetWidgets(); + for (auto& [dataNode, rowWidget] : widgets) + { + if (DoesIntersectWidget(globalRect, reinterpret_cast(rowWidget)) && rowWidget->CanBeReordered()) + { + return rowWidget; + } + } + } + + return nullptr; + } + bool EntityPropertyEditor::StartDrag(QMouseEvent* event) { // do not initiate a drag if property editor is disabled @@ -4402,7 +5013,27 @@ namespace AzToolsFramework if (!intersectsHeader) { - return false; + for (auto componentEditor : componentEditors) + { + AzToolsFramework::ReflectedPropertyEditor::WidgetList widgets = componentEditor->GetPropertyEditor()->GetWidgets(); + for (AZStd::pair w : widgets) + { + if (w.second) + { + if (DoesIntersectWidget(dragRect, reinterpret_cast(w.second)) && w.second->CanBeReordered()) + { + m_currentReorderState = EntityPropertyEditor::ReorderState::DraggingRowWidget; + m_reorderRowWidget = w.second; + m_reorderRowWidgetEditor = componentEditor; + if (m_reorderDropTarget) + { + m_reorderDropTarget = nullptr; + } + break; + } + } + } + } } m_dragStarted = true; @@ -4412,105 +5043,166 @@ namespace AzToolsFramework QRect dragImageRect; - AZStd::vector componentEditorIndices; - componentEditorIndices.reserve(componentEditors.size()); - for (auto componentEditor : componentEditors) + if (m_reorderRowWidget) { - //compute the drag image size - if (componentEditorIndices.empty()) - { - dragImageRect = componentEditor->rect(); - } - else - { - dragImageRect.setHeight(dragImageRect.height() + componentEditor->rect().height()); - } + // We're dragging a PropertyRowWidget, grab the image from that. + mimeData->setData(kComponentEditorRowWidgetType, QByteArray()); - //add component editor index to drag data - auto componentEditorIndex = GetComponentEditorIndex(componentEditor); - if (componentEditorIndex >= 0) - { - componentEditorIndices.push_back(GetComponentEditorIndex(componentEditor)); - } + drag->setMimeData(mimeData); + drag->setPixmap(m_reorderRowWidget->createDragImage( + QColor("#8E863E"), QColor("#EAECAA"), 0.5f, PropertyRowWidget::DragImageType::SingleRow)); + drag->setHotSpot(m_dragStartPosition - GetWidgetGlobalRect(m_reorderRowWidget).topLeft()); + drag->setDragCursor(m_dragIcon.pixmap(32), Qt::DropAction::MoveAction); + // Ensure we can tidy up if the drop happens elsewhere. + connect(drag, &QObject::destroyed, this, &EntityPropertyEditor::DragStopped); + drag->exec(Qt::MoveAction, Qt::MoveAction); } - - //build image from dragged editor UI - QImage dragImage(dragImageRect.size(), QImage::Format_ARGB32_Premultiplied); - QPainter painter(&dragImage); - painter.setCompositionMode(QPainter::CompositionMode_Source); - painter.fillRect(dragImageRect, Qt::transparent); - painter.setCompositionMode(QPainter::CompositionMode_SourceOver); - painter.setOpacity(0.5f); - - //render a vertical stack of component editors, may change to render just the headers - QPoint dragImageOffset(0, 0); - for (AZ::s32 index : componentEditorIndices) + else { - auto componentEditor = GetComponentEditorsFromIndex(index); - if (componentEditor) + AZStd::vector componentEditorIndices; + componentEditorIndices.reserve(componentEditors.size()); + for (auto componentEditor : componentEditors) { - if (DoesIntersectWidget(dragRect, componentEditor)) + // compute the drag image size + if (componentEditorIndices.empty()) { - //offset drag image from the drag start position - drag->setHotSpot(dragImageOffset + (m_dragStartPosition - GetWidgetGlobalRect(componentEditor).topLeft())); + dragImageRect = componentEditor->rect(); + } + else + { + dragImageRect.setHeight(dragImageRect.height() + componentEditor->rect().height()); } - //render the component editor to the drag image - componentEditor->render(&painter, dragImageOffset); - - //update the render offset by the component editor height - dragImageOffset.setY(dragImageOffset.y() + componentEditor->rect().height()); + // add component editor index to drag data + auto componentEditorIndex = GetComponentEditorIndex(componentEditor); + if (componentEditorIndex >= 0) + { + componentEditorIndices.push_back(GetComponentEditorIndex(componentEditor)); + } } - } - painter.end(); - //mark dragged components after drag initiated to draw indicators - for (AZ::s32 index : componentEditorIndices) - { - auto componentEditor = GetComponentEditorsFromIndex(index); - if (componentEditor) + // build image from dragged editor UI + QImage dragImage(dragImageRect.size(), QImage::Format_ARGB32_Premultiplied); + QPainter painter(&dragImage); + painter.setCompositionMode(QPainter::CompositionMode_Source); + painter.fillRect(dragImageRect, Qt::transparent); + painter.setCompositionMode(QPainter::CompositionMode_SourceOver); + painter.setOpacity(0.5f); + + // render a vertical stack of component editors, may change to render just the headers + QPoint dragImageOffset(0, 0); + for (AZ::s32 index : componentEditorIndices) { - componentEditor->SetDragged(true); + auto componentEditor = GetComponentEditorsFromIndex(index); + if (componentEditor) + { + if (DoesIntersectWidget(dragRect, componentEditor)) + { + // offset drag image from the drag start position + drag->setHotSpot(dragImageOffset + (m_dragStartPosition - GetWidgetGlobalRect(componentEditor).topLeft())); + } + + // render the component editor to the drag image + componentEditor->render(&painter, dragImageOffset); + + // update the render offset by the component editor height + dragImageOffset.setY(dragImageOffset.y() + componentEditor->rect().height()); + } } - } - UpdateOverlay(); + painter.end(); - //encode component editor indices as internal drag data - mimeData->setData( - kComponentEditorIndexMimeType, - QByteArray(reinterpret_cast(componentEditorIndices.data()), static_cast(componentEditorIndices.size() * sizeof(AZ::s32)))); - - drag->setMimeData(mimeData); - drag->setPixmap(QPixmap::fromImage(dragImage)); - drag->exec(Qt::MoveAction, Qt::MoveAction); - - //mark dragged components after drag completed to stop drawing indicators - for (AZ::s32 index : componentEditorIndices) - { - auto componentEditor = GetComponentEditorsFromIndex(index); - if (componentEditor) + // mark dragged components after drag initiated to draw indicators + for (AZ::s32 index : componentEditorIndices) { - componentEditor->SetDragged(false); + auto componentEditor = GetComponentEditorsFromIndex(index); + if (componentEditor) + { + componentEditor->SetDragged(true); + } + } + UpdateOverlay(); + + // encode component editor indices as internal drag data + mimeData->setData( + kComponentEditorIndexMimeType, + QByteArray( + reinterpret_cast(componentEditorIndices.data()), + static_cast(componentEditorIndices.size() * sizeof(AZ::s32)))); + + drag->setMimeData(mimeData); + drag->setPixmap(QPixmap::fromImage(dragImage)); + drag->exec(Qt::MoveAction, Qt::MoveAction); + + // mark dragged components after drag completed to stop drawing indicators + for (AZ::s32 index : componentEditorIndices) + { + auto componentEditor = GetComponentEditorsFromIndex(index); + if (componentEditor) + { + componentEditor->SetDragged(false); + } } } + UpdateOverlay(); return true; } + void EntityPropertyEditor::SetRowWidgetHighlighted(PropertyRowWidget* rowWidget) + { + m_reorderRowWidget = rowWidget; + m_reorderRowImage = rowWidget->createDragImage( + QColor("#8E863E"), QColor("#EAECAA"), 0.5f, PropertyRowWidget::DragImageType::IncludeVisibleChildren); + } + + void EntityPropertyEditor::EndRowWidgetReorder() + { + m_reorderDropTarget = nullptr; + m_reorderRowWidget = nullptr; + m_reorderDropTarget = nullptr; + m_currentReorderState = EntityPropertyEditor::ReorderState::Inactive; + m_overlay->setVisible(false); + } + bool EntityPropertyEditor::HandleDrop(QDropEvent* event) { const QPoint globalPos(mapToGlobal(event->pos())); const QMimeData* mimeData = event->mimeData(); - if (IsDropAllowed(mimeData, globalPos)) + + if (m_currentReorderState == EntityPropertyEditor::ReorderState::DraggingRowWidget) { - //handle drop for supported mime types - HandleDropForComponentTypes(event); - HandleDropForComponentAssets(event); - HandleDropForAssetBrowserEntries(event); - HandleDropForComponentReorder(event); + if (FindAllowedRowWidgetReorderDropTarget(globalPos)) + { + if (m_reorderDropArea == EntityPropertyEditor::DropArea::Above) + { + m_reorderRowWidgetEditor->GetPropertyEditor()->MoveNodeBefore( + m_reorderRowWidget->GetNode(), m_reorderDropTarget->GetNode()); + } + else + { + m_reorderRowWidgetEditor->GetPropertyEditor()->MoveNodeAfter( + m_reorderRowWidget->GetNode(), m_reorderDropTarget->GetNode()); + } + } + event->acceptProposedAction(); - return true; + + EndRowWidgetReorder(); } + else + { + if (IsDropAllowed(mimeData, globalPos)) + { + // handle drop for supported mime types + HandleDropForComponentTypes(event); + HandleDropForComponentAssets(event); + HandleDropForAssetBrowserEntries(event); + HandleDropForComponentReorder(event); + event->acceptProposedAction(); + return true; + } + } + return false; } @@ -5036,6 +5728,69 @@ namespace AzToolsFramework componentEditor->ActiveComponentModeChanged(componentType); } } + + EntityPropertyEditor::ReorderState EntityPropertyEditor::GetReorderState() const + { + return m_currentReorderState; + } + + ComponentEditor* EntityPropertyEditor::GetEditorForCurrentReorderRowWidget() const + { + return m_reorderRowWidgetEditor; + } + + PropertyRowWidget* EntityPropertyEditor::GetReorderRowWidget() const + { + return m_reorderRowWidget; + } + + PropertyRowWidget* EntityPropertyEditor::GetReorderDropTarget() const + { + return m_reorderDropTarget; + } + + EntityPropertyEditor::DropArea EntityPropertyEditor::GetReorderDropArea() const + { + return m_reorderDropArea; + } + + QPixmap EntityPropertyEditor::GetReorderRowWidgetImage() const + { + return m_reorderRowImage; + } + + float EntityPropertyEditor::GetMoveIndicatorAlpha() const + { + if (m_currentReorderState != ReorderState::MenuOperationInProgress) + { + return 1.0f; + } + + return m_moveFadeSecondsRemaining / MoveFadeSeconds; + } + + PropertyRowWidget* EntityPropertyEditor::GetRowToHighlight() + { + // Use the pregenerated map to find the RowWidget that's in the new position. + QSet rowWidgets = m_reorderRowWidgetEditor->GetPropertyEditor()->GetTopLevelWidgets(); + if (rowWidgets.isEmpty()) + { + return nullptr; + } + + PropertyRowWidget* highlightRow = *rowWidgets.begin(); + + int mapIndex = static_cast(m_indexMapOfMovedRow.size() - 1); + + while (mapIndex >= 0) + { + int mapEntry = m_indexMapOfMovedRow[mapIndex]; + highlightRow = highlightRow->GetChildrenRows()[mapEntry]; + mapIndex--; + } + + return highlightRow; + } } StatusComboBox::StatusComboBox(QWidget* parent) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.hxx b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.hxx index 166d4c4392..3ff69f80e0 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.hxx +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.hxx @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -110,6 +111,7 @@ namespace AzToolsFramework , public EditorInspectorComponentNotificationBus::MultiHandler , private AzToolsFramework::ComponentModeFramework::EditorComponentModeNotificationBus::Handler , public AZ::EntitySystemBus::Handler + , public AZ::TickBus::Handler , private EditorWindowUIRequestBus::Handler { Q_OBJECT; @@ -117,6 +119,23 @@ namespace AzToolsFramework AZ_CLASS_ALLOCATOR(EntityPropertyEditor, AZ::SystemAllocator, 0) + enum class ReorderState + { + Inactive, // No row widget reordering operation is in progress. + DraggingComponent, // User is dragging a component editor. + DraggingRowWidget, // User is dragging a row widget around. + UsingMenu, // User has the context menu open and may hover over a move up/down operation. + MenuOperationInProgress, // User has selected a move/up down menu item. + WaitForRedraw, // Wait for rebuild of RPE. + HighlightMovedRow // User has moved a row, highlight the new position. + }; + + enum class DropArea + { + Above, + Below + }; + EntityPropertyEditor(QWidget* pParent = NULL, Qt::WindowFlags flags = Qt::WindowFlags(), bool isLevelEntityEditor = false); virtual ~EntityPropertyEditor(); @@ -151,6 +170,16 @@ namespace AzToolsFramework bool IsLockedToSpecificEntities() const { return !m_overrideSelectedEntityIds.empty(); } static bool AreComponentsCopyable(const AZ::Entity::ComponentArrayType& components, const ComponentFilter& filter); + + ReorderState GetReorderState() const; + ComponentEditor* GetEditorForCurrentReorderRowWidget() const; + PropertyRowWidget* GetReorderRowWidget() const; + PropertyRowWidget* GetReorderDropTarget() const; + DropArea GetReorderDropArea() const; + QPixmap GetReorderRowWidgetImage() const; + float GetMoveIndicatorAlpha() const; + PropertyRowWidget* GetRowToHighlight(); + Q_SIGNALS: void SelectedEntityNameChanged(const AZ::EntityId& entityId, const AZStd::string& name); @@ -211,6 +240,9 @@ namespace AzToolsFramework void GetSelectedEntities(EntityIdList& selectedEntityIds) override; void SetNewComponentId(AZ::ComponentId componentId) override; + // TickBus + void OnTick(float deltaTime, AZ::ScriptTimePoint time) override; + // EditorWindowRequestBus overrides void SetEditorUiEnabled(bool enable) override; @@ -253,6 +285,10 @@ namespace AzToolsFramework void ContextMenuActionPullFieldData(AZ::Component* parentComponent, InstanceDataNode* fieldNode); void ContextMenuActionSetDataFlag(InstanceDataNode* node, AZ::DataPatch::Flag flag, bool additive); + void GenerateRowWidgetIndexMapToChildIndex(PropertyRowWidget* parent, int destIndex); + void ContextMenuActionMoveItemUp(ComponentEditor* componentEditor, PropertyRowWidget* rowWidget); + void ContextMenuActionMoveItemDown(ComponentEditor* componentEditor, PropertyRowWidget* rowWidget); + /// Given an InstanceDataNode, calculate a DataPatch address relative to the entity. /// @return true if successful. bool GetEntityDataPatchAddress(const InstanceDataNode* componentFieldNode, AZ::DataPatch::AddressType& dataPatchAddressOut, AZ::EntityId* entityIdOut = nullptr) const; @@ -341,8 +377,6 @@ namespace AzToolsFramework QAction* m_actionToMoveComponentsBottom = nullptr; QAction* m_resetToSliceAction = nullptr; - bool m_isShowingContextMenu = false; - void CreateActions(); void UpdateActions(); @@ -390,6 +424,10 @@ namespace AzToolsFramework void ResetToSlice(); bool DoesOwnFocus() const; + AZ::u32 GetHeightOfRowAndVisibleChildren(const PropertyRowWidget* row) const; + QRect GetWidgetAndVisibleChildrenGlobalRect(const PropertyRowWidget* widget) const; + PropertyRowWidget* GetRowWidgetAtSameLevelAfter(PropertyRowWidget* widget) const; + PropertyRowWidget* GetRowWidgetAtSameLevelBefore(PropertyRowWidget* widget) const; QRect GetWidgetGlobalRect(const QWidget* widget) const; bool DoesIntersectWidget(const QRect& globalRect, const QWidget* widget) const; bool DoesIntersectSelectedComponentEditor(const QRect& globalRect) const; @@ -445,6 +483,8 @@ namespace AzToolsFramework bool HandleSelectionEvents(QObject* object, QEvent* event); bool m_selectionEventAccepted; + bool HandleMenuEvent(QObject* object, QEvent* event); + // drag and drop events QRect GetInflatedRectFromPoint(const QPoint& point, int radius) const; bool GetComponentsAtDropEventPosition(QDropEvent* event, AZ::Entity::ComponentArrayType& targetComponents); @@ -458,8 +498,12 @@ namespace AzToolsFramework ComponentEditor* GetReorderDropTarget(const QRect& globalRect) const; bool ResetDrag(QMouseEvent* event); + bool FindAllowedRowWidgetReorderDropTarget(const QPoint& globalPos); + bool UpdateRowWidgetDrag(const QPoint& localPos, Qt::MouseButtons mouseButtons, const QMimeData* mimeData); + PropertyRowWidget* FindPropertyRowWidgetAt(QPoint globalPos); bool UpdateDrag(const QPoint& localPos, Qt::MouseButtons mouseButtons, const QMimeData* mimeData); bool StartDrag(QMouseEvent* event); + void EndRowWidgetReorder(); bool HandleDrop(QDropEvent* event); bool HandleDropForComponentTypes(QDropEvent* event); bool HandleDropForComponentAssets(QDropEvent* event); @@ -468,6 +512,8 @@ namespace AzToolsFramework bool CanDropForComponentTypes(const QMimeData* mimeData) const; bool CanDropForComponentAssets(const QMimeData* mimeData) const; bool CanDropForAssetBrowserEntries(const QMimeData* mimeData) const; + void SetRowWidgetHighlighted(PropertyRowWidget* rowWidget); + AZStd::vector ExtractComponentEditorIndicesFromMimeData(const QMimeData* mimeData) const; ComponentEditorVector GetComponentEditorsFromIndices(const AZStd::vector& indices) const; ComponentEditor* GetComponentEditorsFromIndex(const AZ::s32 index) const; @@ -559,6 +605,8 @@ namespace AzToolsFramework QIcon m_emptyIcon; QIcon m_clearIcon; + QIcon m_dragIcon; + QCursor m_dragCursor; QStandardItem* m_comboItems[StatusItems]; EntityIdSet m_overrideSelectedEntityIds; @@ -566,6 +614,19 @@ namespace AzToolsFramework Prefab::PrefabPublicInterface* m_prefabPublicInterface = nullptr; bool m_prefabsAreEnabled = false; + // Reordering row widgets within the RPE. + static constexpr float MoveFadeSeconds = 0.5f; + + ReorderState m_currentReorderState = ReorderState::Inactive; + ComponentEditor* m_reorderRowWidgetEditor = nullptr; + InstanceDataNode* m_nodeToMove = nullptr; + PropertyRowWidget* m_reorderRowWidget = nullptr; + PropertyRowWidget* m_reorderDropTarget = nullptr; + DropArea m_reorderDropArea = DropArea::Above; + QPixmap m_reorderRowImage; + float m_moveFadeSecondsRemaining; + AZStd::vector m_indexMapOfMovedRow; + // When m_initiatingPropertyChangeNotification is set to true, it means this EntityPropertyEditor is // broadcasting a change to all listeners about a property change for a given entity. This is needed // so that we don't update the values twice for this inspector @@ -573,6 +634,9 @@ namespace AzToolsFramework void ConnectToEntityBuses(const AZ::EntityId& entityId); void DisconnectFromEntityBuses(const AZ::EntityId& entityId); + void BeginMoveRowWidgetFade(); + void HighlightMovedRowWidget(); + //! Stores a component id to be focused on next time the UI updates. AZStd::optional m_newComponentId; @@ -594,6 +658,8 @@ namespace AzToolsFramework bool SelectedEntitiesAreFromSameSourceSliceEntity() const; + void DragStopped(); + AZ::Entity* GetSelectedEntityById(AZ::EntityId& entityId) const; }; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.cpp index 05c04872e3..c3da1e69b0 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.cpp @@ -368,10 +368,15 @@ namespace AzToolsFramework delete m_containerAddButton; } + this->unsetCursor(); + if ((m_parentRow) && (m_parentRow->IsContainerEditable())) { if (!m_elementRemoveButton) { + QIcon icon = QIcon(QStringLiteral(":/Cursors/Grab_release.svg")); + this->setCursor(QCursor(icon.pixmap(16), 5, 2)); + static QIcon s_iconRemove(QStringLiteral(":/stylesheet/img/UI20/delete-16.svg")); m_elementRemoveButton = new QToolButton(this); m_elementRemoveButton->setAutoRaise(true); @@ -570,7 +575,12 @@ namespace AzToolsFramework AZ_Assert(m_selectionEnabled, "Property is not selectable"); m_isSelected = selected; m_nameLabel->setProperty("selected", selected); - } + } + + bool PropertyRowWidget::GetSelected() + { + return m_isSelected; + } void PropertyRowWidget::SetSelectionEnabled(bool selectionEnabled) { @@ -1395,6 +1405,21 @@ namespace AzToolsFramework return !m_childrenRows.empty(); } + AZ::u32 PropertyRowWidget::GetChildRowCount() const + { + return static_cast(m_childrenRows.size()); + } + + PropertyRowWidget* PropertyRowWidget::GetChildRowByIndex(AZ::u32 index) const + { + if (index >= m_childrenRows.size()) + { + return nullptr; + } + + return m_childrenRows[index]; + } + bool PropertyRowWidget::ShouldPreValidatePropertyChange() const { return (m_changeValidators.size() > 0); @@ -1722,6 +1747,162 @@ namespace AzToolsFramework return m_parentRow->CanChildrenBeReordered(); } + + int PropertyRowWidget::GetIndexInParent() const + { + if (!GetParentRow()) + { + return -1; + } + + for (int index = 0; index < GetParentRow()->GetChildRowCount(); index++) + { + if (GetParentRow()->GetChildrenRows()[index] == this) + { + return index; + } + } + + return -1; + } + + bool PropertyRowWidget::CanMoveUp() const + { + if (!CanBeReordered()) + { + return false; + } + + return this != m_parentRow->GetChildRowByIndex(0); + } + + bool PropertyRowWidget::CanMoveDown() const + { + if (!CanBeReordered()) + { + return false; + } + + AZ::u32 numChildrenOfParent = m_parentRow->GetChildRowCount(); + + return this != m_parentRow->GetChildRowByIndex(numChildrenOfParent - 1); + } + + int PropertyRowWidget::GetContainingEditorFrameWidth() + { + QWidget* parent = parentWidget(); + + // Find the first ancestor that can be cast to a QFrame, this will be the RPE. + while (!qobject_cast(parent)) + { + parent = parent->parentWidget(); + } + + if (!parent) + { + return 0; + } + + // The parent of the RPE is the size we want. + parent = parent->parentWidget(); + + return parent->rect().width(); + } + + int PropertyRowWidget::GetHeightOfRowAndVisibleChildren() + { + int height = rect().height(); + + if (!GetChildRowCount() || !IsExpanded()) + { + return height; + } + + for (auto childRow : GetChildrenRows()) + { + height += childRow->GetHeightOfRowAndVisibleChildren(); + } + + return height; + } + + int PropertyRowWidget::DrawDragImageAndVisibleChildrenInto(QPainter& painter, int xpos, int ypos) + { + // Render our image into the given painter. + int ystart = ypos; + + render(&painter, QPoint(xpos, ypos)); + + if (!GetChildRowCount() || !IsExpanded()) + { + return rect().height(); + } + + ypos += rect().height(); + + // Recursively draw any children. + for (auto childRow : GetChildrenRows()) + { + ypos += childRow->DrawDragImageAndVisibleChildrenInto(painter, xpos, ypos); + } + + return ypos - ystart; + } + + QPixmap PropertyRowWidget::createDragImage( + const QColor backgroundColor, const QColor borderColor, const float alpha, DragImageType imageType) + { + // Make the drag box as wide as the containing editor minus a gap each side for the border. + static constexpr int ParentEditorBorderSize = 2; + int width = GetContainingEditorFrameWidth() - ParentEditorBorderSize * 2; + int height = 0; + + if (imageType == DragImageType::IncludeVisibleChildren) + { + height = GetHeightOfRowAndVisibleChildren(); + } + else + { + height = rect().height(); + } + + const auto dpr = devicePixelRatioF(); + QPixmap dragImage(width * dpr, height * dpr); + dragImage.setDevicePixelRatio(dpr); + dragImage.fill(Qt::transparent); + + QRect imageRect = QRect(0, 0, width, height); + + QPainter dragPainter(&dragImage); + dragPainter.setCompositionMode(QPainter::CompositionMode_Source); + dragPainter.fillRect(imageRect, Qt::transparent); + dragPainter.setCompositionMode(QPainter::CompositionMode_SourceOver); + dragPainter.setOpacity(alpha); + dragPainter.fillRect(imageRect, backgroundColor); + + dragPainter.setOpacity(1.0f); + + int marginWidth = (imageRect.width() - rect().width()) / 2 + ParentEditorBorderSize - 1; + + if (imageType == DragImageType::IncludeVisibleChildren) + { + DrawDragImageAndVisibleChildrenInto(dragPainter, marginWidth, 0); + } + else + { + render(&dragPainter, QPoint(marginWidth, 0)); + } + + QPen pen; + pen.setColor(QColor(borderColor)); + pen.setWidth(1); + dragPainter.setPen(pen); + dragPainter.drawRect(0, 0, imageRect.width() - 1, imageRect.height() - 1); + + dragPainter.end(); + + return dragImage; + } } #include "UI/PropertyEditor/moc_PropertyRowWidget.cpp" diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.hxx b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.hxx index ebf7c67b21..68cc9b9cf9 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.hxx +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.hxx @@ -45,6 +45,13 @@ namespace AzToolsFramework Q_PROPERTY(bool appendDefaultLabelToName READ GetAppendDefaultLabelToName WRITE AppendDefaultLabelToName) public: AZ_CLASS_ALLOCATOR(PropertyRowWidget, AZ::SystemAllocator, 0) + + enum class DragImageType + { + SingleRow, + IncludeVisibleChildren + }; + PropertyRowWidget(QWidget* pParent); virtual ~PropertyRowWidget(); @@ -86,6 +93,9 @@ namespace AzToolsFramework bool GetAppendDefaultLabelToName(); void AppendDefaultLabelToName(bool doAppend); + AZ::u32 GetChildRowCount() const; + PropertyRowWidget* GetChildRowByIndex(AZ::u32 index) const; + AZStd::vector& GetChildrenRows() { return m_childrenRows; } bool HasChildRows() const; @@ -124,6 +134,7 @@ namespace AzToolsFramework void SetSelectionEnabled(bool selectionEnabled); void SetSelected(bool selected); + bool GetSelected(); bool eventFilter(QObject *watched, QEvent *event) override; void paintEvent(QPaintEvent*) override; @@ -152,9 +163,18 @@ namespace AzToolsFramework bool CanChildrenBeReordered() const; bool CanBeReordered() const; + int GetIndexInParent() const; + bool CanMoveUp() const; + bool CanMoveDown() const; + + int GetContainingEditorFrameWidth(); + QPixmap createDragImage(const QColor backgroundColor, const QColor borderColor, const float alpha, DragImageType imageType); protected: int CalculateLabelWidth() const; + int GetHeightOfRowAndVisibleChildren(); + int DrawDragImageAndVisibleChildrenInto(QPainter& painter, int xpos, int ypos); + bool IsHidden(InstanceDataNode* node) const; struct ChangeNotification; @@ -216,6 +236,7 @@ namespace AzToolsFramework bool m_isMultiSizeContainer = false; bool m_isFixedSizeOrSmartPtrContainer = false; bool m_custom = false; + bool m_canChildrenBeReordered = false; bool m_isSelected = false; bool m_selectionEnabled = false; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ReflectedPropertyEditor.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ReflectedPropertyEditor.cpp index 36462bca66..5d5b00e83d 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ReflectedPropertyEditor.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ReflectedPropertyEditor.cpp @@ -19,6 +19,7 @@ #include #include #include +#include AZ_PUSH_DISABLE_WARNING(4251, "-Wunknown-warning-option") // 'QTextFormat::d': class 'QSharedDataPointer' needs to have dll-interface to be used by clients of class 'QTextFormat' #include AZ_POP_DISABLE_WARNING @@ -1343,7 +1344,7 @@ namespace AzToolsFramework // calculate the index/offset of the instance data node in the container // (useful for notifying which element in a vector was modified/removed) - static size_t CalculateElementIndexInContainer( + static int CalculateElementIndexInContainer( InstanceDataNode* node, void* parentInstanceNode, AZ::SerializeContext::IDataContainer* container, AZStd::vector& nodeInstancesOut) { @@ -1358,7 +1359,7 @@ namespace AzToolsFramework } } - size_t elementIndex = 0; + int elementIndex = 0; void* elementPtr = nodeInstancesOut.empty() ? nullptr : nodeInstancesOut.front(); // find the index of the element we are about to remove @@ -1429,7 +1430,7 @@ namespace AzToolsFramework // if the element being modified exists in a container, calculate // the index to be passed through to PropertyNotify - const auto calculateElementIndex = [](InstanceDataNode* node) -> size_t { + const auto calculateElementIndex = [](InstanceDataNode* node) -> int { if (InstanceDataNode* parent = node->GetParent()) { if (AZ::SerializeContext::IDataContainer* container = parent->GetClassMetadata()->m_container) @@ -1656,6 +1657,221 @@ namespace AzToolsFramework AzToolsFramework::Refresh_EntireTree); } + InstanceDataNode* ReflectedPropertyEditor::FindContainerNodeForNode(InstanceDataNode* node) const + { + // Locate the owning container. There may be a level of indirection due to wrappers, such as DynamicSerializableField. + InstanceDataNode* pContainerNode = node->GetParent(); + if (!pContainerNode) + { + return nullptr; + } + + while (pContainerNode && !pContainerNode->GetClassMetadata()->m_container) + { + pContainerNode = pContainerNode->GetParent(); + node = node->GetParent(); + } + + // Check for pContainerNode again, can happen if a node is deleted during operation. + if (!pContainerNode) + { + return nullptr; + } + + if (IsParentAssociativeContainer(pContainerNode) && IsPairContainer(pContainerNode)) + { + // Go up one more level to the associative container, we'll remove the pair from that container + pContainerNode = pContainerNode->GetParent(); + node = node->GetParent(); + } + + AZ_Assert( + pContainerNode, "Failed to locate parent container for element \"%s\" of type %s.", + node->GetElementMetadata() ? node->GetElementMetadata()->m_name : node->GetClassMetadata()->m_name, + node->GetClassMetadata()->m_typeId.ToString().c_str()); + + return pContainerNode; + } + + InstanceDataNode* ReflectedPropertyEditor::GetNodeAtIndex(int index) + { + if (index >= m_impl->m_widgetsInDisplayOrder.size()) + { + return nullptr; + } + + return GetNodeFromWidget(m_impl->m_widgetsInDisplayOrder[index]); + } + + QSet ReflectedPropertyEditor::GetTopLevelWidgets() + { + return m_impl->getTopLevelWidgets(); + } + + void ReflectedPropertyEditor::ChangeNodeIndex(InstanceDataNode* containerNode, InstanceDataNode* node, int fromIndex, int toIndex) + { + auto container = containerNode->GetElementMetadata() + ? containerNode->GetElementMetadata()->m_genericClassInfo->GetClassData()->m_container + : nullptr; + + if (fromIndex == toIndex) + { + return; + } + + if (!container || container->GetAssociativeContainerInterface()) + { + return; + } + + AZ::Uuid typeId = node->GetClassMetadata()->m_typeId; + + if (m_impl->m_ptrNotify) + { + m_impl->m_ptrNotify->BeforePropertyModified(containerNode); + } + + const AZ::SerializeContext::ClassElement* containerClassElement = container->GetElement(container->GetDefaultElementNameCrc()); + + AZ::SerializeContext* serializeContext = nullptr; + AZ::ComponentApplicationBus::BroadcastResult(serializeContext, &AZ::ComponentApplicationBus::Events::GetSerializeContext); + + // Backup the item we're moving. + void* srcElement = nullptr; + void* destElement = nullptr; + + int destIndex = -1; + int srcIndex = fromIndex; + + srcElement = container->GetElementByIndex(containerNode->GetInstance(0), containerClassElement, srcIndex); + + void* tmpBuffer = serializeContext->CloneObject(srcElement, typeId); + + // Shuffle all intervening items up (or down). + int indexOffset = (toIndex < fromIndex) ? -1 : 1; + + while (destIndex != toIndex - indexOffset) + { + destIndex = srcIndex; + srcIndex += indexOffset; + + destElement = srcElement; + + srcElement = container->GetElementByIndex(containerNode->GetInstance(0), containerClassElement, srcIndex); + + serializeContext->CloneObjectInplace(destElement, srcElement, typeId); + } + + // Now replace the final element with the one backed up previously. + destElement = srcElement; + + serializeContext->CloneObjectInplace(destElement, tmpBuffer, typeId); + + if (m_impl->m_ptrNotify) + { + m_impl->m_ptrNotify->AfterPropertyModified(containerNode); + m_impl->m_ptrNotify->SealUndoStack(); + } + + // Need to refresh any pinned inspectors as well to keep the container state in sync + QueueInvalidation(Refresh_Values); + AzToolsFramework::ToolsApplicationEvents::Bus::Broadcast( + &AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_Values); + } + + void ReflectedPropertyEditor::MoveNodeToIndex(InstanceDataNode* node, int index) + { + InstanceDataNode* pContainerNode = FindContainerNodeForNode(node); + + if (!pContainerNode) + { + return; + } + + AZ::SerializeContext::IDataContainer* container = pContainerNode->GetClassMetadata()->m_container; + + AZStd::vector nodeInstancesOut; + const int elementIndex = CalculateElementIndexInContainer(node, pContainerNode->GetInstance(0), container, nodeInstancesOut); + + ChangeNodeIndex(pContainerNode, node, elementIndex, index); + } + + void ReflectedPropertyEditor::MoveNodeBefore(InstanceDataNode* nodeToMove, InstanceDataNode* nodeToMoveBefore) + { + InstanceDataNode* pContainerNode = FindContainerNodeForNode(nodeToMove); + InstanceDataNode* pContainerNodeTarget = FindContainerNodeForNode(nodeToMoveBefore); + + if (nodeToMove == nodeToMoveBefore) + { + return; + } + + // Can only move nodes within the same parent. + if (pContainerNode != pContainerNodeTarget) + { + return; + } + + AZ::SerializeContext::IDataContainer* container = pContainerNode->GetClassMetadata()->m_container; + + AZStd::vector nodeInstancesOut; + int elementIndex = CalculateElementIndexInContainer(nodeToMove, pContainerNode->GetInstance(0), container, nodeInstancesOut); + nodeInstancesOut.clear(); + int elementIndexTarget = + CalculateElementIndexInContainer(nodeToMoveBefore, pContainerNode->GetInstance(0), container, nodeInstancesOut); + + if (elementIndex < elementIndexTarget) + { + elementIndexTarget -= 1; + } + + ChangeNodeIndex(pContainerNode, nodeToMove, elementIndex, elementIndexTarget); + } + + void ReflectedPropertyEditor::MoveNodeAfter(InstanceDataNode* nodeToMove, InstanceDataNode* nodeToMoveBefore) + { + InstanceDataNode* pContainerNode = FindContainerNodeForNode(nodeToMove); + InstanceDataNode* pContainerNodeTarget = FindContainerNodeForNode(nodeToMoveBefore); + + if (nodeToMove == nodeToMoveBefore) + { + return; + } + + // Can only move nodes within the same parent. + if (pContainerNode != pContainerNodeTarget) + { + return; + } + + AZ::SerializeContext::IDataContainer* container = pContainerNode->GetClassMetadata()->m_container; + + AZStd::vector nodeInstancesOut; + int elementIndex = CalculateElementIndexInContainer(nodeToMove, pContainerNode->GetInstance(0), container, nodeInstancesOut); + nodeInstancesOut.clear(); + int elementIndexTarget = + CalculateElementIndexInContainer(nodeToMoveBefore, pContainerNode->GetInstance(0), container, nodeInstancesOut); + + if (elementIndex > elementIndexTarget) + { + elementIndexTarget += 1; + } + + ChangeNodeIndex(pContainerNode, nodeToMove, elementIndex, elementIndexTarget); + } + + int ReflectedPropertyEditor::GetNodeIndexInContainer(InstanceDataNode* node) + { + InstanceDataNode* pContainerNode = FindContainerNodeForNode(node); + + AZ::SerializeContext::IDataContainer* container = pContainerNode->GetClassMetadata()->m_container; + + AZStd::vector nodeInstancesOut; + int elementIndex = CalculateElementIndexInContainer(node, pContainerNode->GetInstance(0), container, nodeInstancesOut); + + return elementIndex; + } + void ReflectedPropertyEditor::OnPropertyRowRequestContainerRemoveItem(PropertyRowWidget* widget, InstanceDataNode* node) { // Locate the owning container. There may be a level of indirection due to wrappers, such as DynamicSerializableField. @@ -1690,7 +1906,7 @@ namespace AzToolsFramework // the index of the element being removed AZStd::vector nodeInstancesOut; - const size_t elementIndex = CalculateElementIndexInContainer( + const int elementIndex = CalculateElementIndexInContainer( node, pContainerNode->GetInstance(0), container, nodeInstancesOut); // pass the context as the last parameter to actually delete the related data. diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ReflectedPropertyEditor.hxx b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ReflectedPropertyEditor.hxx index b10e153162..28da540098 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ReflectedPropertyEditor.hxx +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ReflectedPropertyEditor.hxx @@ -155,9 +155,19 @@ namespace AzToolsFramework using VisibilityCallback = AZStd::function; void SetVisibilityCallback(VisibilityCallback callback); + void MoveNodeToIndex(InstanceDataNode* node, int index); + void MoveNodeBefore(InstanceDataNode* nodeToMove, InstanceDataNode* nodeToMoveBefore); + void MoveNodeAfter(InstanceDataNode* nodeToMove, InstanceDataNode* nodeToMoveBefore); + + int GetNodeIndexInContainer(InstanceDataNode* node); + InstanceDataNode* GetNodeAtIndex(int index); + QSet GetTopLevelWidgets(); signals: void OnExpansionContractionDone(); private: + InstanceDataNode* FindContainerNodeForNode(InstanceDataNode* node) const; + void ChangeNodeIndex(InstanceDataNode* containerNode, InstanceDataNode* node, int oldIndex, int newIndex); + class Impl; std::unique_ptr m_impl; From f7e536bfb1868203c53e20c2895718da45f4784e Mon Sep 17 00:00:00 2001 From: sphrose <82213493+sphrose@users.noreply.github.com> Date: Mon, 16 Aug 2021 12:37:12 +0100 Subject: [PATCH 388/803] compile fix - signed/unsigned mismatch (#3139) Signed-off-by: sphrose <82213493+sphrose@users.noreply.github.com> --- .../AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.cpp index c3da1e69b0..604c6141d7 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.cpp @@ -1755,7 +1755,7 @@ namespace AzToolsFramework return -1; } - for (int index = 0; index < GetParentRow()->GetChildRowCount(); index++) + for (AZ::u32 index = 0; index < GetParentRow()->GetChildRowCount(); index++) { if (GetParentRow()->GetChildrenRows()[index] == this) { From 5925bd22f6e0607f9fda0a705c6b3738c81bda24 Mon Sep 17 00:00:00 2001 From: jonawals Date: Mon, 16 Aug 2021 14:15:02 +0100 Subject: [PATCH 389/803] Further subdivide TIAF data by suite. (#3128) * Further subdivide TIAF data by suite. * Key fix typo. Signed-off-by: John --- .../TestImpactRuntimeConfigurationFactory.cpp | 25 ++++--------- .../TestImpactClientSequenceReport.h | 2 +- .../TestImpactConfiguration.h | 4 +-- .../Runtime/Code/Source/TestImpactRuntime.cpp | 5 +-- .../ConsoleFrontendConfig.in | 11 ++---- scripts/build/TestImpactAnalysis/tiaf.py | 3 +- .../tiaf_persistent_storage.py | 35 +++++++++++-------- .../tiaf_persistent_storage_local.py | 2 ++ .../tiaf_persistent_storage_s3.py | 6 ++-- 9 files changed, 42 insertions(+), 51 deletions(-) diff --git a/Code/Tools/TestImpactFramework/Frontend/Console/Code/Source/TestImpactRuntimeConfigurationFactory.cpp b/Code/Tools/TestImpactFramework/Frontend/Console/Code/Source/TestImpactRuntimeConfigurationFactory.cpp index 8ea32d6447..c2bc95a906 100644 --- a/Code/Tools/TestImpactFramework/Frontend/Console/Code/Source/TestImpactRuntimeConfigurationFactory.cpp +++ b/Code/Tools/TestImpactFramework/Frontend/Console/Code/Source/TestImpactRuntimeConfigurationFactory.cpp @@ -27,7 +27,7 @@ namespace TestImpact "relative_paths", "artifact_dir", "enumeration_cache_dir", - "test_impact_data_files", + "test_impact_data_file", "temp", "active", "target_sources", @@ -72,7 +72,7 @@ namespace TestImpact RelativePaths, ArtifactDir, EnumerationCacheDir, - TestImpactDataFiles, + TestImpactDataFile, TempWorkspace, ActiveWorkspace, TargetSources, @@ -138,31 +138,18 @@ namespace TestImpact tempWorkspaceConfig.m_artifactDirectory = GetAbsPathFromRelPath( tempWorkspaceConfig.m_root, tempWorkspace[Config::Keys[Config::RelativePaths]][Config::Keys[Config::ArtifactDir]].GetString()); + tempWorkspaceConfig.m_enumerationCacheDirectory = GetAbsPathFromRelPath( + tempWorkspaceConfig.m_root, + tempWorkspace[Config::Keys[Config::RelativePaths]][Config::Keys[Config::EnumerationCacheDir]].GetString()); return tempWorkspaceConfig; } - AZStd::array ParseTestImpactAnalysisDataFiles(const RepoPath& root, const rapidjson::Value& sparTiaFile) - { - AZStd::array sparTiaFiles; - sparTiaFiles[static_cast(SuiteType::Main)] = - GetAbsPathFromRelPath(root, sparTiaFile[SuiteTypeAsString(SuiteType::Main).c_str()].GetString()); - sparTiaFiles[static_cast(SuiteType::Periodic)] = - GetAbsPathFromRelPath(root, sparTiaFile[SuiteTypeAsString(SuiteType::Periodic).c_str()].GetString()); - sparTiaFiles[static_cast(SuiteType::Sandbox)] = - GetAbsPathFromRelPath(root, sparTiaFile[SuiteTypeAsString(SuiteType::Sandbox).c_str()].GetString()); - - return sparTiaFiles; - } - WorkspaceConfig::Active ParseActiveWorkspaceConfig(const rapidjson::Value& activeWorkspace) { WorkspaceConfig::Active activeWorkspaceConfig; const auto& relativePaths = activeWorkspace[Config::Keys[Config::RelativePaths]]; activeWorkspaceConfig.m_root = activeWorkspace[Config::Keys[Config::Root]].GetString(); - activeWorkspaceConfig.m_enumerationCacheDirectory - = GetAbsPathFromRelPath(activeWorkspaceConfig.m_root, relativePaths[Config::Keys[Config::EnumerationCacheDir]].GetString()); - activeWorkspaceConfig.m_sparTiaFiles = - ParseTestImpactAnalysisDataFiles(activeWorkspaceConfig.m_root, relativePaths[Config::Keys[Config::TestImpactDataFiles]]); + activeWorkspaceConfig.m_sparTiaFile = relativePaths[Config::Keys[Config::TestImpactDataFile]].GetString(); return activeWorkspaceConfig; } diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactClientSequenceReport.h b/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactClientSequenceReport.h index e86123ddc7..1ddd1042e6 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactClientSequenceReport.h +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactClientSequenceReport.h @@ -530,7 +530,7 @@ namespace TestImpact size_t GetTotalNumTimedOutTestRuns() const override; size_t GetTotalNumUnexecutedTestRuns() const override; - //! Returns the report for the discarded test runs. + // ImpactAnalysisSequenceReport overrides ... const TestRunSelection GetDiscardedTestRuns() const; //! Returns the report for the discarded test runs. diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactConfiguration.h b/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactConfiguration.h index fcacd90e71..92dd454b01 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactConfiguration.h +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactConfiguration.h @@ -37,14 +37,14 @@ namespace TestImpact { RepoPath m_root; //!< Path to the temporary workspace (cleaned prior to use). RepoPath m_artifactDirectory; //!< Path to read and write runtime artifacts to and from. + RepoPath m_enumerationCacheDirectory; //!< Path to the test enumerations cache. }; //! Active persistent data workspace configuration. struct Active { RepoPath m_root; //!< Path to the persistent workspace tracked by the repository. - RepoPath m_enumerationCacheDirectory; //!< Path to the test enumerations cache. - AZStd::array m_sparTiaFiles; //!< Paths to the test impact analysis data files for each test suite. + RepoPath m_sparTiaFile; //!< Paths to the test impact analysis data file. }; Temp m_temp; diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactRuntime.cpp b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactRuntime.cpp index 8a9d96bca8..515118dd7a 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactRuntime.cpp +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactRuntime.cpp @@ -275,7 +275,7 @@ namespace TestImpact m_testEngine = AZStd::make_unique( m_config.m_repo.m_root, m_config.m_target.m_outputDirectory, - m_config.m_workspace.m_active.m_enumerationCacheDirectory, + m_config.m_workspace.m_temp.m_enumerationCacheDirectory, m_config.m_workspace.m_temp.m_artifactDirectory, m_config.m_testEngine.m_testRunner.m_binary, m_config.m_testEngine.m_instrumentation.m_binary, @@ -289,7 +289,8 @@ namespace TestImpact } else { - m_sparTiaFile = m_config.m_workspace.m_active.m_sparTiaFiles[static_cast(m_suiteFilter)].String(); + m_sparTiaFile = + m_config.m_workspace.m_active.m_root / RepoPath(SuiteTypeAsString(m_suiteFilter)) / m_config.m_workspace.m_active.m_sparTiaFile; } // Populate the dynamic dependency map with the existing source coverage data (if any) diff --git a/cmake/TestImpactFramework/ConsoleFrontendConfig.in b/cmake/TestImpactFramework/ConsoleFrontendConfig.in index 17fbd217d7..3b6318e1e0 100644 --- a/cmake/TestImpactFramework/ConsoleFrontendConfig.in +++ b/cmake/TestImpactFramework/ConsoleFrontendConfig.in @@ -15,19 +15,14 @@ "temp": { "root": "${temp_dir}", "relative_paths": { - "artifact_dir": "RuntimeArtifact" + "artifact_dir": "RuntimeArtifact", + "enumeration_cache_dir": "EnumerationCache" } }, "active": { "root": "${active_dir}", "relative_paths": { - "test_impact_data_files": { - "main": "TestImpactData.main.spartia", - "periodic": "TestImpactData.periodic.spartia", - "sandbox": "TestImpactData.sandbox.spartia" - }, - "enumeration_cache_dir": "EnumerationCache", - "last_build_target_list_file": "LastRunBuildTargets.json" + "test_impact_data_file": "TestImpactData.spartia" } }, "historic": { diff --git a/scripts/build/TestImpactAnalysis/tiaf.py b/scripts/build/TestImpactAnalysis/tiaf.py index e8faef30e3..27fbaf451f 100644 --- a/scripts/build/TestImpactAnalysis/tiaf.py +++ b/scripts/build/TestImpactAnalysis/tiaf.py @@ -230,7 +230,7 @@ class TestImpact: # Flag for corner case where: # 1. TIAF was already run previously for this commit. - # 2. There was no last commit hash when TIAF last ran on this commit (due to no coverage data existing get for this branch) + # 2. There was no last commit hash when TIAF last ran on this commit (due to no coverage data existing yet for this branch) # 3. TIAF has not been run on any other commits between the run for this commit and the last run for this commit. # The above results in TIAF being stuck in a state of generating an empty change list (and thus doing no work until another # commit comes in) which is problematic if the commit needs to be re-run for whatever reason so in these conditions we revert @@ -323,7 +323,6 @@ class TestImpact: logger.info(f"Args: {unpacked_args}") runtime_result = subprocess.run([str(self._tiaf_bin)] + args) report = None - # If the sequence completed (with or without failures) we will update the historical meta-data if runtime_result.returncode == 0 or runtime_result.returncode == 7: logger.info("Test impact analysis runtime returned successfully.") diff --git a/scripts/build/TestImpactAnalysis/tiaf_persistent_storage.py b/scripts/build/TestImpactAnalysis/tiaf_persistent_storage.py index 3fff05b549..5445c1f955 100644 --- a/scripts/build/TestImpactAnalysis/tiaf_persistent_storage.py +++ b/scripts/build/TestImpactAnalysis/tiaf_persistent_storage.py @@ -17,11 +17,11 @@ logger = get_logger(__file__) class PersistentStorage(ABC): WORKSPACE_KEY = "workspace" - LAST_RUNS_KEY = "last_runs" + HISTORIC_SEQUENCES_KEY = "historic_sequences" ACTIVE_KEY = "active" ROOT_KEY = "root" RELATIVE_PATHS_KEY = "relative_paths" - TEST_IMPACT_DATA_FILES_KEY = "test_impact_data_files" + TEST_IMPACT_DATA_FILE_KEY = "test_impact_data_file" LAST_COMMIT_HASH_KEY = "last_commit_hash" COVERAGE_DATA_KEY = "coverage_data" @@ -35,19 +35,21 @@ class PersistentStorage(ABC): """ # Work on the assumption that there is no historic meta-data (a valid state to be in, should none exist) + self._suite = suite self._last_commit_hash = None self._has_historic_data = False self._has_previous_last_commit_hash = False self._this_commit_hash = commit self._this_commit_hash_last_commit_hash = None self._historic_data = None - logger.info(f"Attempting to access persistent storage for the commit {self._this_commit_hash}") + logger.info(f"Attempting to access persistent storage for the commit '{self._this_commit_hash}' for suite '{self._suite}'") try: # The runtime expects the coverage data to be in the location specified in the config file (unless overridden with # the --datafile command line argument, which the TIAF scripts do not do) self._active_workspace = pathlib.Path(config[self.WORKSPACE_KEY][self.ACTIVE_KEY][self.ROOT_KEY]) - unpacked_coverage_data_file = config[self.WORKSPACE_KEY][self.ACTIVE_KEY][self.RELATIVE_PATHS_KEY][self.TEST_IMPACT_DATA_FILES_KEY][suite] + self._active_workspace = self._active_workspace.joinpath(pathlib.Path(self._suite)) + unpacked_coverage_data_file = config[self.WORKSPACE_KEY][self.ACTIVE_KEY][self.RELATIVE_PATHS_KEY][self.TEST_IMPACT_DATA_FILE_KEY] except KeyError as e: raise SystemError(f"The config does not contain the key {str(e)}.") @@ -70,25 +72,27 @@ class PersistentStorage(ABC): self._last_commit_hash = self._historic_data[self.LAST_COMMIT_HASH_KEY] logger.info(f"Last commit hash '{self._last_commit_hash}' found.") - if self.LAST_RUNS_KEY in self._historic_data: - # Last commit hash for the sequence that was run for this commit previously (if any) - if self._this_commit_hash in self._historic_data[self.LAST_RUNS_KEY]: + # Last commit hash for the sequence that was run for this commit previously (if any) + if self.HISTORIC_SEQUENCES_KEY in self._historic_data: + if self._this_commit_hash in self._historic_data[self.HISTORIC_SEQUENCES_KEY]: # 'None' is a valid value for the previously used last commit hash if there was no coverage data at that time - self._this_commit_hash_last_commit_hash = self._historic_data[self.LAST_RUNS_KEY][self._this_commit_hash] + self._this_commit_hash_last_commit_hash = self._historic_data[self.HISTORIC_SEQUENCES_KEY][self._this_commit_hash] self._has_previous_last_commit_hash = self._this_commit_hash_last_commit_hash is not None if self._has_previous_last_commit_hash: logger.info(f"Last commit hash '{self._this_commit_hash_last_commit_hash}' was used previously for this commit.") else: - logger.info(f"Prior sequence data found for this commit but it is empty (there was no coverage data vailable at that time).") + logger.info(f"Prior sequence data found for this commit but it is empty (there was no coverage data available at that time).") else: logger.info(f"No prior sequence data found for commit '{self._this_commit_hash}', this is the first sequence for this commit.") else: logger.info(f"No prior sequence data found for any commits.") - # Create the active workspace directory where the coverage data file will be placed and unpack the coverage data so - # it is accessible by the runtime + # Create the active workspace directory for the unpacked historic data files so they are accessible by the runtime self._active_workspace.mkdir(exist_ok=True) + + # Coverage file + logger.info(f"Writing coverage data to '{self._unpacked_coverage_data_file}'.") with open(self._unpacked_coverage_data_file, "w", newline='\n') as coverage_data: coverage_data.write(self._historic_data[self.COVERAGE_DATA_KEY]) @@ -117,9 +121,12 @@ class PersistentStorage(ABC): self._historic_data[self.LAST_COMMIT_HASH_KEY] = self._this_commit_hash # Last commit hash for this commit - if not self.LAST_RUNS_KEY in self._historic_data: - self._historic_data[self.LAST_RUNS_KEY] = {} - self._historic_data[self.LAST_RUNS_KEY][self._this_commit_hash] = self._last_commit_hash + if not self.HISTORIC_SEQUENCES_KEY in self._historic_data: + self._historic_data[self.HISTORIC_SEQUENCES_KEY] = {} + self._historic_data[self.HISTORIC_SEQUENCES_KEY][self._this_commit_hash] = self._last_commit_hash + + # Test runs for this completed sequence + self._historic_data[self.PREVIOUS_TEST_RUNS_KEY] = test_runs # Coverage data for this branch with open(self._unpacked_coverage_data_file, "r") as coverage_data: diff --git a/scripts/build/TestImpactAnalysis/tiaf_persistent_storage_local.py b/scripts/build/TestImpactAnalysis/tiaf_persistent_storage_local.py index c72fafc580..7ad9155a41 100644 --- a/scripts/build/TestImpactAnalysis/tiaf_persistent_storage_local.py +++ b/scripts/build/TestImpactAnalysis/tiaf_persistent_storage_local.py @@ -32,10 +32,12 @@ class PersistentStorageLocal(PersistentStorage): try: # Attempt to obtain the local persistent data location specified in the runtime config file self._historic_workspace = pathlib.Path(config[self.WORKSPACE_KEY][self.HISTORIC_KEY][self.ROOT_KEY]) + self._historic_workspace = self._historic_workspace.joinpath(pathlib.Path(self._suite)) historic_data_file = pathlib.Path(config[self.WORKSPACE_KEY][self.HISTORIC_KEY][self.RELATIVE_PATHS_KEY][self.DATA_KEY]) # Attempt to unpack the local historic data file self._historic_data_file = self._historic_workspace.joinpath(historic_data_file) + logger.info(f"Attempting to retrieve historic data at location '{self._historic_data_file}'...") if self._historic_data_file.is_file(): with open(self._historic_data_file, "r") as historic_data_raw: historic_data_json = historic_data_raw.read() diff --git a/scripts/build/TestImpactAnalysis/tiaf_persistent_storage_s3.py b/scripts/build/TestImpactAnalysis/tiaf_persistent_storage_s3.py index 074caf73a1..175eb3148d 100644 --- a/scripts/build/TestImpactAnalysis/tiaf_persistent_storage_s3.py +++ b/scripts/build/TestImpactAnalysis/tiaf_persistent_storage_s3.py @@ -43,9 +43,9 @@ class PersistentStorageS3(PersistentStorage): # historic_data.json.zip is the file containing the coverage and meta-data of the last TIAF sequence run historic_data_file = f"historic_data.{object_extension}" - # The location of the data is in the form // so the build config of each branch gets its own historic data - self._historic_data_dir = f'{root_dir}/{branch}/{config[self.META_KEY][self.BUILD_CONFIG_KEY]}' - self._historic_data_key = f'{self._historic_data_dir}/{historic_data_file}' + # The location of the data is in the form /// so the build config of each branch gets its own historic data + self._historic_data_dir = f"{root_dir}/{branch}/{config[self.META_KEY][self.BUILD_CONFIG_KEY]}/{self._suite}" + self._historic_data_key = f"{self._historic_data_dir}/{historic_data_file}" logger.info(f"Attempting to retrieve historic data for branch '{branch}' at location '{self._historic_data_key}' on bucket '{s3_bucket}'...") self._s3 = boto3.resource("s3") From e630e3324dc5836fcfea328d9e002fa0877f060b Mon Sep 17 00:00:00 2001 From: amzn-sean <75276488+amzn-sean@users.noreply.github.com> Date: Mon, 16 Aug 2021 15:46:46 +0100 Subject: [PATCH 390/803] fixed joint crash when no lead entity is selected (#2867) Signed-off-by: amzn-sean <75276488+amzn-sean@users.noreply.github.com> --- Gems/PhysX/Code/Source/BallJointComponent.cpp | 19 +++++- .../PhysX/Code/Source/FixedJointComponent.cpp | 18 ++++- .../PhysX/Code/Source/HingeJointComponent.cpp | 18 ++++- .../Code/Source/Joint/PhysXJointUtils.cpp | 15 +++-- Gems/PhysX/Code/Tests/PhysXJointsTest.cpp | 66 +++++++++++++++++-- 5 files changed, 121 insertions(+), 15 deletions(-) diff --git a/Gems/PhysX/Code/Source/BallJointComponent.cpp b/Gems/PhysX/Code/Source/BallJointComponent.cpp index 12323e5077..60f7888b0d 100644 --- a/Gems/PhysX/Code/Source/BallJointComponent.cpp +++ b/Gems/PhysX/Code/Source/BallJointComponent.cpp @@ -46,11 +46,26 @@ namespace PhysX JointComponent::LeadFollowerInfo leadFollowerInfo; ObtainLeadFollowerInfo(leadFollowerInfo); - if (!leadFollowerInfo.m_followerActor) + if (leadFollowerInfo.m_followerActor == nullptr || + leadFollowerInfo.m_followerBody == nullptr) { return; } + // if there is no lead body, this will be a constraint of the follower's global position, so use invalid body handle. + AzPhysics::SimulatedBodyHandle parentHandle = AzPhysics::InvalidSimulatedBodyHandle; + if (leadFollowerInfo.m_leadBody != nullptr) + { + parentHandle = leadFollowerInfo.m_leadBody->m_bodyHandle; + } + else + { + AZ_TracePrintf( + "PhysX", "Entity [%s] Ball Joint component missing lead entity. This joint will be a global constraint on the follower's global position.", + GetEntity()->GetName().c_str()); + } + + BallJointConfiguration configuration; configuration.m_parentLocalPosition = leadFollowerInfo.m_leadLocal.GetTranslation(); configuration.m_parentLocalRotation = leadFollowerInfo.m_leadLocal.GetRotation(); @@ -65,7 +80,7 @@ namespace PhysX m_jointHandle = sceneInterface->AddJoint( leadFollowerInfo.m_followerBody->m_sceneOwner, &configuration, - leadFollowerInfo.m_leadBody->m_bodyHandle, + parentHandle, leadFollowerInfo.m_followerBody->m_bodyHandle); m_jointSceneOwner = leadFollowerInfo.m_followerBody->m_sceneOwner; } diff --git a/Gems/PhysX/Code/Source/FixedJointComponent.cpp b/Gems/PhysX/Code/Source/FixedJointComponent.cpp index 53a9946998..82c8cc485c 100644 --- a/Gems/PhysX/Code/Source/FixedJointComponent.cpp +++ b/Gems/PhysX/Code/Source/FixedJointComponent.cpp @@ -54,11 +54,25 @@ namespace PhysX JointComponent::LeadFollowerInfo leadFollowerInfo; ObtainLeadFollowerInfo(leadFollowerInfo); - if (!leadFollowerInfo.m_followerActor) + if (leadFollowerInfo.m_followerActor == nullptr || + leadFollowerInfo.m_followerBody == nullptr) { return; } + // if there is no lead body, this will be a constraint of the follower's global position, so use invalid body handle. + AzPhysics::SimulatedBodyHandle parentHandle = AzPhysics::InvalidSimulatedBodyHandle; + if (leadFollowerInfo.m_leadBody != nullptr) + { + parentHandle = leadFollowerInfo.m_leadBody->m_bodyHandle; + } + else + { + AZ_TracePrintf("PhysX", + "Entity [%s] Fixed Joint component missing lead entity. This joint will be a global constraint on the follower's global position.", + GetEntity()->GetName().c_str()); + } + FixedJointConfiguration configuration; configuration.m_parentLocalPosition = leadFollowerInfo.m_leadLocal.GetTranslation(); configuration.m_parentLocalRotation = leadFollowerInfo.m_leadLocal.GetRotation(); @@ -72,7 +86,7 @@ namespace PhysX m_jointHandle = sceneInterface->AddJoint( leadFollowerInfo.m_followerBody->m_sceneOwner, &configuration, - leadFollowerInfo.m_leadBody->m_bodyHandle, + parentHandle, leadFollowerInfo.m_followerBody->m_bodyHandle); m_jointSceneOwner = leadFollowerInfo.m_followerBody->m_sceneOwner; } diff --git a/Gems/PhysX/Code/Source/HingeJointComponent.cpp b/Gems/PhysX/Code/Source/HingeJointComponent.cpp index f275d32dc7..5edf1803c4 100644 --- a/Gems/PhysX/Code/Source/HingeJointComponent.cpp +++ b/Gems/PhysX/Code/Source/HingeJointComponent.cpp @@ -48,12 +48,24 @@ namespace PhysX JointComponent::LeadFollowerInfo leadFollowerInfo; ObtainLeadFollowerInfo(leadFollowerInfo); if (leadFollowerInfo.m_followerActor == nullptr || - leadFollowerInfo.m_leadBody == nullptr || leadFollowerInfo.m_followerBody == nullptr) { return; } + // if there is no lead body, this will be a constraint of the follower's global position, so use invalid body handle. + AzPhysics::SimulatedBodyHandle parentHandle = AzPhysics::InvalidSimulatedBodyHandle; + if (leadFollowerInfo.m_leadBody != nullptr) + { + parentHandle = leadFollowerInfo.m_leadBody->m_bodyHandle; + } + else + { + AZ_TracePrintf( + "PhysX", "Entity [%s] Hinge Joint component missing lead entity. This joint will be a global constraint on the follower's global position.", + GetEntity()->GetName().c_str()); + } + HingeJointConfiguration configuration; configuration.m_parentLocalPosition = leadFollowerInfo.m_leadLocal.GetTranslation(); configuration.m_parentLocalRotation = leadFollowerInfo.m_leadLocal.GetRotation(); @@ -66,7 +78,9 @@ namespace PhysX if (auto* sceneInterface = AZ::Interface::Get()) { m_jointHandle = sceneInterface->AddJoint( - leadFollowerInfo.m_followerBody->m_sceneOwner, &configuration, leadFollowerInfo.m_leadBody->m_bodyHandle, + leadFollowerInfo.m_followerBody->m_sceneOwner, + &configuration, + parentHandle, leadFollowerInfo.m_followerBody->m_bodyHandle); m_jointSceneOwner = leadFollowerInfo.m_followerBody->m_sceneOwner; } diff --git a/Gems/PhysX/Code/Source/Joint/PhysXJointUtils.cpp b/Gems/PhysX/Code/Source/Joint/PhysXJointUtils.cpp index 5b63a43966..3558c9fb56 100644 --- a/Gems/PhysX/Code/Source/Joint/PhysXJointUtils.cpp +++ b/Gems/PhysX/Code/Source/Joint/PhysXJointUtils.cpp @@ -190,8 +190,9 @@ namespace PhysX { { PxJointActorData actorData = GetJointPxActors(sceneHandle, parentBodyHandle, childBodyHandle); - if (!actorData.parentActor || !actorData.childActor) + if (actorData.parentActor == nullptr && actorData.childActor == nullptr) { + AZ_Warning("PhysX Joint", false, "CreateJoint failed - at least one body must be a PxRigidActor."); return nullptr; } @@ -239,7 +240,8 @@ namespace PhysX { { PxJointActorData actorData = GetJointPxActors(sceneHandle, parentBodyHandle, childBodyHandle); - if (!actorData.parentActor || !actorData.childActor) + //only check the child actor, as a null parent actor means this joint is a global constraint. + if (!actorData.childActor) { return nullptr; } @@ -252,7 +254,8 @@ namespace PhysX { { PHYSX_SCENE_READ_LOCK(actorData.childActor->getScene()); - joint = physx::PxFixedJointCreate(PxGetPhysics(), + joint = physx::PxFixedJointCreate( + PxGetPhysics(), actorData.parentActor, PxMathConvert(parentLocalTM), actorData.childActor, PxMathConvert(childLocalTM)); } @@ -272,7 +275,8 @@ namespace PhysX { { PxJointActorData actorData = GetJointPxActors(sceneHandle, parentBodyHandle, childBodyHandle); - if (!actorData.parentActor || !actorData.childActor) + // only check the child actor, as a null parent actor means this joint is a global constraint. + if (!actorData.childActor) { return nullptr; } @@ -306,7 +310,8 @@ namespace PhysX { { PxJointActorData actorData = GetJointPxActors(sceneHandle, parentBodyHandle, childBodyHandle); - if (!actorData.parentActor || !actorData.childActor) + // only check the child actor, as a null parent actor means this joint is a global constraint. + if (!actorData.childActor) { return nullptr; } diff --git a/Gems/PhysX/Code/Tests/PhysXJointsTest.cpp b/Gems/PhysX/Code/Tests/PhysXJointsTest.cpp index ff9cf11cca..ac5a99e29a 100644 --- a/Gems/PhysX/Code/Tests/PhysXJointsTest.cpp +++ b/Gems/PhysX/Code/Tests/PhysXJointsTest.cpp @@ -123,7 +123,7 @@ namespace PhysX const AZ::Vector3 followerEndPosition = RunJointTest(m_defaultScene, followerEntity->GetId()); - EXPECT_TRUE(followerEndPosition.GetX() > followerPosition.GetX()); + EXPECT_GT(followerEndPosition.GetX(), followerPosition.GetX()); } TEST_F(PhysXJointsTest, Joint_HingeJoint_FollowerSwingsAroundLead) @@ -164,8 +164,8 @@ namespace PhysX const AZ::Vector3 followerEndPosition = RunJointTest(m_defaultScene, followerEntity->GetId()); - EXPECT_TRUE(followerEndPosition.GetX() > followerPosition.GetX()); - EXPECT_TRUE(abs(followerEndPosition.GetZ()) > FLT_EPSILON); + EXPECT_GT(followerEndPosition.GetX(), followerPosition.GetX()); + EXPECT_GT(abs(followerEndPosition.GetZ()), FLT_EPSILON); } TEST_F(PhysXJointsTest, Joint_BallJoint_FollowerSwingsUpAboutLead) @@ -206,7 +206,65 @@ namespace PhysX const AZ::Vector3 followerEndPosition = RunJointTest(m_defaultScene, followerEntity->GetId()); - EXPECT_TRUE(followerEndPosition.GetZ() > followerPosition.GetZ()); + EXPECT_GT(followerEndPosition.GetZ(), followerPosition.GetZ()); + } + + TEST_F(PhysXJointsTest, Joint_BallJoint_GlobalConstraint) + { + // Place an entity in the world with a rigid body, physx collider, and a ball joint components. + // Do not set a lead entity on the ball joint component. + // Set entity's initial velocity to 10 in the X and Y directions on the rigid body component. + // The entity should swing up on the global constraint. + + const AZ::Vector3 followerPosition(0.0f, 0.0f, -1.0f); + const AZ::Vector3 followerInitialLinearVelocity(10.0f, 10.0f, 0.0f); + + const AZ::Vector3 jointLocalPosition(0.0f, 0.0f, 2.0f); + const AZ::Quaternion jointLocalRotation = AZ::Quaternion::CreateRotationY(90.0f); + const AZ::Transform jointLocalTransform = AZ::Transform::CreateFromQuaternionAndTranslation(jointLocalRotation, jointLocalPosition); + + //we want a global constraint, so leave the lead entity unset. + auto jointConfig = AZStd::make_shared(); + jointConfig->m_localTransformFromFollower = jointLocalTransform; + + auto jointLimits = AZStd::make_shared(); + jointLimits->m_isLimited = false; + + auto followerEntity = AddBodyColliderEntity( + m_testSceneHandle, followerPosition, followerInitialLinearVelocity, jointConfig, nullptr, jointLimits); + + const AZ::Vector3 followerEndPosition = RunJointTest(m_defaultScene, followerEntity->GetId()); + + EXPECT_GT(followerEndPosition.GetZ(), followerPosition.GetZ()); + } + + TEST_F(PhysXJointsTest, Joint_HingeJoint_GlobalConstraint) + { + // Place an entity in the world with a rigid body, physx collider, and a hinge joint components. + // Do not set a lead entity on the hinge joint component. + // Set entity's initial velocity to 10 in the X and Y directions on the rigid body component. + // The entity should swing up on the global constraint. + + const AZ::Vector3 followerPosition(0.0f, 0.0f, -1.0f); + const AZ::Vector3 followerInitialLinearVelocity(10.0f, 10.0f, 0.0f); + + const AZ::Vector3 jointLocalPosition(0.0f, 0.0f, 2.0f); + const AZ::Quaternion jointLocalRotation = AZ::Quaternion::CreateFromEulerAnglesDegrees(AZ::Vector3(0.0f, 180.0f, 90.0f)); + const AZ::Transform jointLocalTransform = AZ::Transform::CreateFromQuaternionAndTranslation(jointLocalRotation, jointLocalPosition); + + // do not set the lead entity as that makes this a global constraint + auto jointConfig = AZStd::make_shared(); + jointConfig->m_localTransformFromFollower = jointLocalTransform; + + auto jointLimits = AZStd::make_shared(); + jointLimits->m_isLimited = false; + + auto followerEntity = AddBodyColliderEntity( + m_testSceneHandle, followerPosition, followerInitialLinearVelocity, jointConfig, nullptr, jointLimits); + + const AZ::Vector3 followerEndPosition = RunJointTest(m_defaultScene, followerEntity->GetId()); + + EXPECT_GT(followerEndPosition.GetZ(), followerPosition.GetZ()); } // for some reason TYPED_TEST_CASE with the fixture is not working on Android + Linux From 252c268ffdf340ce43411f1b93c05a39eb92b35b Mon Sep 17 00:00:00 2001 From: jonawals Date: Mon, 16 Aug 2021 16:09:36 +0100 Subject: [PATCH 391/803] Fix corrupt merge. (#3142) * Further subdivide TIAF data by suite. * Key fix typo. Signed-off-by: John --- scripts/build/TestImpactAnalysis/tiaf_persistent_storage.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/scripts/build/TestImpactAnalysis/tiaf_persistent_storage.py b/scripts/build/TestImpactAnalysis/tiaf_persistent_storage.py index 5445c1f955..e499b0303c 100644 --- a/scripts/build/TestImpactAnalysis/tiaf_persistent_storage.py +++ b/scripts/build/TestImpactAnalysis/tiaf_persistent_storage.py @@ -125,9 +125,6 @@ class PersistentStorage(ABC): self._historic_data[self.HISTORIC_SEQUENCES_KEY] = {} self._historic_data[self.HISTORIC_SEQUENCES_KEY][self._this_commit_hash] = self._last_commit_hash - # Test runs for this completed sequence - self._historic_data[self.PREVIOUS_TEST_RUNS_KEY] = test_runs - # Coverage data for this branch with open(self._unpacked_coverage_data_file, "r") as coverage_data: self._historic_data[self.COVERAGE_DATA_KEY] = coverage_data.read() From 4f2d4d00ec612a5a7a9ad946ebedf6d04841640c Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Mon, 16 Aug 2021 08:40:27 -0700 Subject: [PATCH 392/803] Auto-completing the inserted text by pressing TAB within Editor's Console results in a silent crash Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Legacy/CrySystem/XConsole.cpp | 57 ++++++++---------------------- 1 file changed, 14 insertions(+), 43 deletions(-) diff --git a/Code/Legacy/CrySystem/XConsole.cpp b/Code/Legacy/CrySystem/XConsole.cpp index ae07f86312..36443fb9ee 100644 --- a/Code/Legacy/CrySystem/XConsole.cpp +++ b/Code/Legacy/CrySystem/XConsole.cpp @@ -2873,7 +2873,7 @@ void CXConsole::Paste() ////////////////////////////////////////////////////////////////////////// int CXConsole::GetNumVars() { - return (int)m_mapVariables.size(); + return static_cast(m_mapVariables.size()); } ////////////////////////////////////////////////////////////////////////// @@ -3132,7 +3132,6 @@ char* CXConsole::GetCheatVarAt(uint32 nOffset) ////////////////////////////////////////////////////////////////////////// size_t CXConsole::GetSortedVars(AZStd::vector& pszArray, const char* szPrefix) { - size_t i = 0; size_t iPrefixLen = szPrefix ? strlen(szPrefix) : 0; // variables @@ -3140,11 +3139,6 @@ size_t CXConsole::GetSortedVars(AZStd::vector& pszArray, con ConsoleVariablesMap::const_iterator it, end = m_mapVariables.end(); for (it = m_mapVariables.begin(); it != end; ++it) { - if (i >= pszArray.size()) - { - break; - } - if (szPrefix) { if (_strnicmp(it->first, szPrefix, iPrefixLen) != 0) @@ -3158,9 +3152,7 @@ size_t CXConsole::GetSortedVars(AZStd::vector& pszArray, con continue; } - pszArray[i] = it->first; - - i++; + pszArray.push_back(it->first); } } @@ -3169,11 +3161,6 @@ size_t CXConsole::GetSortedVars(AZStd::vector& pszArray, con ConsoleCommandsMap::iterator it, end = m_mapCommands.end(); for (it = m_mapCommands.begin(); it != end; ++it) { - if (i >= pszArray.size()) - { - break; - } - if (szPrefix) { if (_strnicmp(it->first.c_str(), szPrefix, iPrefixLen) != 0) @@ -3187,25 +3174,18 @@ size_t CXConsole::GetSortedVars(AZStd::vector& pszArray, con continue; } - pszArray[i] = it->first.c_str(); - - i++; + pszArray.push_back(it->first.c_str()); } } - if (i != 0) - { - std::sort(pszArray.begin(), pszArray.end()); - } - - return i; + std::sort(pszArray.begin(), pszArray.end()); + return pszArray.size(); } ////////////////////////////////////////////////////////////////////////// void CXConsole::FindVar(const char* substr) { AZStd::vector cmds; - cmds.resize(GetNumVars() + m_mapCommands.size()); size_t cmdCount = GetSortedVars(cmds); for (size_t i = 0; i < cmdCount; i++) @@ -3231,10 +3211,9 @@ const char* CXConsole::AutoComplete(const char* substr) // following code can be optimized AZStd::vector cmds; - cmds.resize(GetNumVars() + m_mapCommands.size()); size_t cmdCount = GetSortedVars(cmds); - size_t substrLen = strlen(substr); + size_t substrLen = substr ? strlen(substr) : 0; // If substring is empty return first command. if (substrLen == 0 && cmdCount > 0) @@ -3246,7 +3225,7 @@ const char* CXConsole::AutoComplete(const char* substr) for (size_t i = 0; i < cmdCount; i++) { const char* szCmd = cmds[i].data(); - size_t cmdlen = strlen(szCmd); + size_t cmdlen = cmds[i].size(); if (cmdlen >= substrLen && memcmp(szCmd, substr, substrLen) == 0) { if (substrLen == cmdlen) @@ -3267,7 +3246,7 @@ const char* CXConsole::AutoComplete(const char* substr) { const char* szCmd = cmds[i].data(); - size_t cmdlen = strlen(szCmd); + size_t cmdlen = cmds[i].size(); if (cmdlen >= substrLen && azstrnicmp(szCmd, substr, substrLen) == 0) { if (substrLen == cmdlen) @@ -3301,27 +3280,19 @@ void CXConsole::SetInputLine(const char* szLine) const char* CXConsole::AutoCompletePrev(const char* substr) { AZStd::vector cmds; - cmds.resize(GetNumVars() + m_mapCommands.size()); - size_t cmdCount = GetSortedVars(cmds); + GetSortedVars(cmds); // If substring is empty return last command. - if (strlen(substr) == 0 && cmds.size() > 0) + if (strlen(substr) == 0 && !cmds.empty()) { - return cmds[cmdCount - 1].data(); + return cmds.back().data(); } - for (unsigned int i = 0; i < cmdCount; i++) + for (const AZStd::string_view& cmd : cmds) { - if (azstricmp(substr, cmds[i].data()) == 0) + if (azstricmp(substr, cmd.data()) == 0) { - if (i > 0) - { - return cmds[i - 1].data(); - } - else - { - return cmds[0].data(); - } + return cmd.data(); } } return AutoComplete(substr); From 994403bfa018dd96e8494c5b57fa8ba08b849819 Mon Sep 17 00:00:00 2001 From: Chris Galvan Date: Mon, 16 Aug 2021 11:56:50 -0500 Subject: [PATCH 393/803] Updated Radius Weight Modifier component name for consistency. Signed-off-by: Chris Galvan --- .../EditorRadiusWeightModifierComponent.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/RadiusWeightModifier/EditorRadiusWeightModifierComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/RadiusWeightModifier/EditorRadiusWeightModifierComponent.cpp index 039255276c..219ab6acb9 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/RadiusWeightModifier/EditorRadiusWeightModifierComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/RadiusWeightModifier/EditorRadiusWeightModifierComponent.cpp @@ -25,7 +25,7 @@ namespace AZ if (AZ::EditContext* editContext = serializeContext->GetEditContext()) { editContext->Class( - "Radius Weight Modifier", "Modifies PostFX override factor based on proximity of an influencer against this entity's bounding sphere") + "PostFX Radius Weight Modifier", "Modifies PostFX override factor based on proximity of an influencer against this entity's bounding sphere") ->ClassElement(Edit::ClassElements::EditorData, "") ->Attribute(Edit::Attributes::Category, "Atom") ->Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/Component_Placeholder.svg") From e2b4d8e50249727294bfdd0856b0d935f311aaa2 Mon Sep 17 00:00:00 2001 From: Jacob Hilliard <64656371+jcbhl@users.noreply.github.com> Date: Mon, 16 Aug 2021 10:13:24 -0700 Subject: [PATCH 394/803] Profiler: Runtime region name support (#2924) * Profiler: add support for runtime region names * Profiler: fix group name collisions * Profiler: use set of GroupRegionNames * Profiler: add comments + named constant Signed-off-by: Jacob Hilliard --- .../RHI/Code/Include/Atom/RHI/CpuProfiler.h | 16 +++++++++++ .../Code/Include/Atom/RHI/CpuProfilerImpl.h | 12 +++++++++ .../RHI/Code/Source/RHI/CpuProfilerImpl.cpp | 27 +++++++++++++++++++ 3 files changed, 55 insertions(+) diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/CpuProfiler.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/CpuProfiler.h index 2248474820..3fedc99566 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/CpuProfiler.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/CpuProfiler.h @@ -30,6 +30,12 @@ namespace AZ const char* const m_groupName = nullptr; const char* const m_regionName = nullptr; + + struct Hash + { + AZStd::size_t operator()(const GroupRegionName& name) const; + }; + bool operator==(const GroupRegionName& other) const; }; CachedTimeRegion() = default; @@ -95,6 +101,9 @@ namespace AZ virtual void SetProfilerEnabled(bool enabled) = 0; virtual bool IsProfilerEnabled() const = 0 ; + + //! Used by AZ_ATOM_PROFILE_DYNAMIC to create GroupRegionNames with known lifetimes. + virtual const CachedTimeRegion::GroupRegionName& InsertDynamicName(const char* groupName, const AZStd::string& regionName) = 0; }; } // namespace RPI @@ -120,3 +129,10 @@ namespace AZ #define AZ_ATOM_PROFILE_FUNCTION(groupName, regionName) \ AZ_TRACE_METHOD(); \ AZ_ATOM_PROFILE_TIME_GROUP_REGION(groupName, regionName) \ + +//! Macro that allows for region names to be submitted at runtime. Use sparingly - this acquires a lock and allocates new objects within a map. +#define AZ_ATOM_PROFILE_DYNAMIC(groupName, regionName) \ + static_assert(AZStd::is_convertible_v, "Runtime group names are not allowed, use a static string literal instead."); \ + const AZ::RHI::CachedTimeRegion::GroupRegionName& AZ_JOIN(groupRegionName, __LINE__) = \ + AZ::RHI::CpuProfiler::Get()->InsertDynamicName(groupName, regionName); \ + AZ::RHI::TimeRegion AZ_JOIN(timeRegion, __LINE__)(&AZ_JOIN(groupRegionName, __LINE__)); diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/CpuProfilerImpl.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/CpuProfilerImpl.h index 7d3b0c5b81..2e4ca67db8 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/CpuProfilerImpl.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/CpuProfilerImpl.h @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -114,9 +115,11 @@ namespace AZ bool IsContinuousCaptureInProgress() const final override; void SetProfilerEnabled(bool enabled) final override; bool IsProfilerEnabled() const final override; + const CachedTimeRegion::GroupRegionName& InsertDynamicName(const char* groupName, const AZStd::string& regionName) final override; private: static constexpr AZStd::size_t MaxFramesToSave = 2 * 60 * 120; // 2 minutes of 120fps + static constexpr AZStd::size_t MaxRegionStringPoolSize = 16384; // Max amount of unique strings to save in the pool before throwing warnings. // Lazily create and register the local thread data void RegisterThreadStorage(); @@ -129,6 +132,15 @@ namespace AZ AZStd::vector, AZ::OSStdAllocator> m_registeredThreads; AZStd::mutex m_threadRegisterMutex; + // Pool for GroupRegionNames that are generated at runtime through AZ_ATOM_PROFILE_DYNAMIC. Each unique + // combination of group name and region name submitted will be stored in this pool to emulate static lifetime. + AZStd::unordered_set m_dynamicGroupRegionNamePool; + + // String pool for storing region names submitted at runtime. Each call to AZ_ATOM_PROFILE_DYNAMIC will either construct + // a string in this pool or use an already-existing entry. + AZStd::unordered_set m_regionNameStringPool; + AZStd::mutex m_dynamicNameMutex; + // Thread local storage, gets lazily allocated when a thread is created static thread_local CpuTimingLocalStorage* ms_threadLocalStorage; diff --git a/Gems/Atom/RHI/Code/Source/RHI/CpuProfilerImpl.cpp b/Gems/Atom/RHI/Code/Source/RHI/CpuProfilerImpl.cpp index cdfd4ac469..d41b5d656e 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/CpuProfilerImpl.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/CpuProfilerImpl.cpp @@ -74,6 +74,20 @@ namespace AZ { } + AZStd::size_t CachedTimeRegion::GroupRegionName::Hash::operator()(const CachedTimeRegion::GroupRegionName& name) const + { + AZStd::size_t seed = 0; + AZStd::hash_combine(seed, name.m_groupName); + AZStd::hash_combine(seed, name.m_regionName); + return seed; + } + + bool CachedTimeRegion::GroupRegionName::operator==(const GroupRegionName& other) const + { + return (m_groupName == other.m_groupName) && (m_regionName == other.m_regionName); + } + + // --- CpuProfilerImpl --- void CpuProfilerImpl::Init() @@ -218,6 +232,19 @@ namespace AZ return m_enabled; } + const CachedTimeRegion::GroupRegionName& CpuProfilerImpl::InsertDynamicName(const char* groupName, const AZStd::string& regionName) + { + AZStd::scoped_lock lock(m_dynamicNameMutex); + AZ_Warning("CpuProfiler", m_regionNameStringPool.size() < MaxRegionStringPoolSize, + "Stored dynamic region names are accumulating. Consider removing a AZ_ATOM_PROFILE_DYNAMIC invocation."); + auto [regionNameItr, wasRegionInserted] = m_regionNameStringPool.insert(regionName); + + CachedTimeRegion::GroupRegionName newGroupRegionName(groupName, regionNameItr->c_str()); + auto [groupRegionNameItr, wasGroupRegionInserted] = m_dynamicGroupRegionNamePool.insert(newGroupRegionName); + + return *groupRegionNameItr; + } + void CpuProfilerImpl::OnSystemTick() { if (!m_enabled) From 1c7f71f93a5bd42700f7f750d97ce50424048b13 Mon Sep 17 00:00:00 2001 From: Chris Galvan Date: Mon, 16 Aug 2021 12:13:32 -0500 Subject: [PATCH 395/803] Updated Atom automated test that uses the PostFX Radius Weight Modifier. Signed-off-by: Chris Galvan --- ...ydra_AtomEditorComponents_AddedToEntity.py | 4 +-- .../atom_renderer/test_Atom_MainSuite.py | 26 +++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_AddedToEntity.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_AddedToEntity.py index b4031d2ffa..cd10caf57b 100644 --- a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_AddedToEntity.py +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_AddedToEntity.py @@ -206,8 +206,8 @@ def run(): # PostFX Layer Component ComponentTests("PostFX Layer") - # Radius Weight Modifier Component - ComponentTests("Radius Weight Modifier") + # PostFX Radius Weight Modifier Component + ComponentTests("PostFX Radius Weight Modifier") # Light Component ComponentTests("Light") diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_MainSuite.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_MainSuite.py index be75801b63..55c049b929 100644 --- a/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_MainSuite.py +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_MainSuite.py @@ -32,7 +32,7 @@ class TestAtomEditorComponentsMain(object): Tests the following Atom components and verifies all "expected_lines" appear in Editor.log: 1. Display Mapper 2. Light - 3. Radius Weight Modifier + 3. PostFX Radius Weight Modifier 4. PostFX Layer 5. Physical Sky 6. Global Skylight (IBL) @@ -126,18 +126,18 @@ class TestAtomEditorComponentsMain(object): "PostFX Layer_test: Entity deleted: True", "PostFX Layer_test: UNDO entity deletion works: True", "PostFX Layer_test: REDO entity deletion works: True", - # Radius Weight Modifier Component - "Radius Weight Modifier Entity successfully created", - "Radius Weight Modifier_test: Component added to the entity: True", - "Radius Weight Modifier_test: Component removed after UNDO: True", - "Radius Weight Modifier_test: Component added after REDO: True", - "Radius Weight Modifier_test: Entered game mode: True", - "Radius Weight Modifier_test: Exit game mode: True", - "Radius Weight Modifier_test: Entity is hidden: True", - "Radius Weight Modifier_test: Entity is shown: True", - "Radius Weight Modifier_test: Entity deleted: True", - "Radius Weight Modifier_test: UNDO entity deletion works: True", - "Radius Weight Modifier_test: REDO entity deletion works: True", + # PostFX Radius Weight Modifier Component + "PostFX Radius Weight Modifier Entity successfully created", + "PostFX Radius Weight Modifier_test: Component added to the entity: True", + "PostFX Radius Weight Modifier_test: Component removed after UNDO: True", + "PostFX Radius Weight Modifier_test: Component added after REDO: True", + "PostFX Radius Weight Modifier_test: Entered game mode: True", + "PostFX Radius Weight Modifier_test: Exit game mode: True", + "PostFX Radius Weight Modifier_test: Entity is hidden: True", + "PostFX Radius Weight Modifier_test: Entity is shown: True", + "PostFX Radius Weight Modifier_test: Entity deleted: True", + "PostFX Radius Weight Modifier_test: UNDO entity deletion works: True", + "PostFX Radius Weight Modifier_test: REDO entity deletion works: True", # Light Component "Light Entity successfully created", "Light_test: Component added to the entity: True", From b88a7faf642e102282b45021d91ea50d7ef18cc3 Mon Sep 17 00:00:00 2001 From: AMZN-stankowi <4838196+AMZN-stankowi@users.noreply.github.com> Date: Mon, 16 Aug 2021 10:18:45 -0700 Subject: [PATCH 396/803] Fixed issues with blend shape animations (#3080) Duplicate blend shape animations are now handled correctly. Invalid animation targets are now an error instead of a crash in the builder. Signed-off-by: stankowi <4838196+AMZN-stankowi@users.noreply.github.com> --- .../SDKWrapper/AssImpSceneWrapper.cpp | 3 + .../Importers/AssImpAnimationImporter.cpp | 32 ++++++- .../Importers/AssImpBlendShapeImporter.cpp | 87 ++++++++++++++++--- 3 files changed, 107 insertions(+), 15 deletions(-) diff --git a/Code/Tools/SceneAPI/SDKWrapper/AssImpSceneWrapper.cpp b/Code/Tools/SceneAPI/SDKWrapper/AssImpSceneWrapper.cpp index 0680b41eca..12aefca00c 100644 --- a/Code/Tools/SceneAPI/SDKWrapper/AssImpSceneWrapper.cpp +++ b/Code/Tools/SceneAPI/SDKWrapper/AssImpSceneWrapper.cpp @@ -70,6 +70,9 @@ namespace AZ // This results in the loss of the offset matrix data for nodes without a mesh which is required for the Transform Importer. m_importer.SetPropertyBool(AI_CONFIG_IMPORT_FBX_PRESERVE_PIVOTS, false); m_importer.SetPropertyBool(AI_CONFIG_IMPORT_FBX_OPTIMIZE_EMPTY_ANIMATION_CURVES, false); + // The remove empty bones flag is on by default, but doesn't do anything internal to AssImp right now. + // This is here as a bread crumb to save others times investigating issues with empty bones. + // m_importer.SetPropertyBool(AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES, false); m_sceneFileName = fileName; m_assImpScene = m_importer.ReadFile(fileName, aiProcess_Triangulate //Triangulates all faces of all meshes diff --git a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpAnimationImporter.cpp b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpAnimationImporter.cpp index 150a50138e..97b5960a8d 100644 --- a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpAnimationImporter.cpp +++ b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpAnimationImporter.cpp @@ -147,7 +147,9 @@ namespace AZ SerializeContext* serializeContext = azrtti_cast(context); if (serializeContext) { - serializeContext->Class()->Version(5); // [LYN-4226] Invert PostRotation matrix in animation chains + // Revision 5: [LYN-4226] Invert PostRotation matrix in animation chains + // Revision 6: Handle duplicate blend shape animations + serializeContext->Class()->Version(6); } } @@ -631,6 +633,15 @@ namespace AZ for (const auto& [meshIdx, keys] : valueToKeyDataMap) { + + if (static_cast(meshIdx) >= mesh->mNumAnimMeshes) + { + AZ_Error( + "AnimationImporter", false, + "Mesh %s has an animation mesh index reference of %d, but only has %d animation meshes. Skipping importing this. This is an error in the source scene file that should be corrected.", + mesh->mName.C_Str(), meshIdx, mesh->mNumAnimMeshes); + continue; + } AZStd::shared_ptr morphAnimNode = AZStd::make_shared(); @@ -656,12 +667,29 @@ namespace AZ morphAnimNode->AddKeyFrame(weight); } + // Some DCC tools, like Maya, include a full path separated by '.' in the node names. + // For example, "cone_skin_blendShapeNode.cone_squash" + // Downstream processing doesn't want anything but the last part of that node name, + // so find the last '.' and remove anything before it. const size_t dotIndex = nodeName.find_last_of('.'); nodeName = nodeName.substr(dotIndex + 1); morphAnimNode->SetBlendShapeName(nodeName.data()); - AZStd::string animNodeName(AZStd::string::format("%s_%s", s_animationNodeName, nodeName.data())); + // Duplicates can exist if an anim mesh had a name with a suffix like .001, in that case + // AssImp will strip off that suffix. Note that this behavior is separate from the + // scan for a period in the node name that came before this. + AZStd::string originalNodeName(AZStd::string::format("%s_%s", s_animationNodeName, nodeName.data())); + AZStd::string animNodeName(originalNodeName); + if (RenamedNodesMap::SanitizeNodeName( + animNodeName, context.m_scene.GetGraph(), context.m_currentGraphPosition, originalNodeName.c_str())) + { + AZ_Warning( + "AnimationImporter", false, + "Duplicate animations were found with the name %s on mesh %s. The duplicate will be named %s.", + originalNodeName.c_str(), mesh->mName.C_Str(), animNodeName.c_str()); + } + Containers::SceneGraph::NodeIndex addNode = context.m_scene.GetGraph().AddChild( context.m_currentGraphPosition, animNodeName.c_str(), AZStd::move(morphAnimNode)); context.m_scene.GetGraph().MakeEndPoint(addNode); diff --git a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpBlendShapeImporter.cpp b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpBlendShapeImporter.cpp index e8eb5ecf68..8e447f9d79 100644 --- a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpBlendShapeImporter.cpp +++ b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpBlendShapeImporter.cpp @@ -40,7 +40,9 @@ namespace AZ SerializeContext* serializeContext = azrtti_cast(context); if (serializeContext) { - serializeContext->Class()->Version(3); // LYN-2576 + // Revision 3: Fixed an issue where jack.fbx was failing to process + // Revision 4: Handle duplicate blend shape animations + serializeContext->Class()->Version(4); } } @@ -80,7 +82,32 @@ namespace AZ // AssImp separates meshes that have multiple materials. // This code re-combines them to match previous FBX SDK behavior, // so they can be separated by engine code instead. - AZStd::map>> animToMeshToAnimMeshIndices; + // Can't de-dupe nodes in the first loop because we can't generate names until we create nodes later. + // Because meshes are split on material at this point and need to be recombined, we can be in a position where + // There is a legit duped anim mesh that needs to be combined based on the outer non-anim mesh, + // or this is a duplicately named anim mesh that needs to be de-duped. There is also the case where both are true, + // it's a duplicate name and the non-anim mesh has to be deduped. + + // Helper struct to track an anim mesh and its associated mesh. + struct AnimMeshAndSceneMeshIndex + { + AnimMeshAndSceneMeshIndex(const aiAnimMesh* aiAnimMesh, const aiMesh* aiMesh) + : m_aiAnimMesh(aiAnimMesh) + , m_aiMesh(aiMesh) + { + } + const aiAnimMesh* m_aiAnimMesh = nullptr; + const aiMesh* m_aiMesh = nullptr; + }; + + // Helper struct to track all anim meshes at an index for all scene meshes. + struct AnimMeshAndSceneMeshes + { + AZStd::vector m_animMeshAndSceneMeshIndex; + }; + + // Map the animation index to the list of anim meshes at that index, and the mesh associated with those anim meshes. + AZStd::map animMeshIndexToSceneMeshes; for (int nodeMeshIdx = 0; nodeMeshIdx < numMesh; nodeMeshIdx++) { int sceneMeshIdx = context.m_sourceNode.GetAssImpNode()->mMeshes[nodeMeshIdx]; @@ -88,20 +115,57 @@ namespace AZ for (unsigned int animIdx = 0; animIdx < aiMesh->mNumAnimMeshes; animIdx++) { aiAnimMesh* aiAnimMesh = aiMesh->mAnimMeshes[animIdx]; - animToMeshToAnimMeshIndices[aiAnimMesh->mName.C_Str()].emplace_back(nodeMeshIdx, animIdx); + + // This code executes if: + // A mesh in the FBX file had multiple materials and blend shapes. + // This means that AssImp splits that mesh to one material per mesh. + // AssImp creates a set of anim meshes for each mesh based on that split. + // This verifies that those anim mesh arrays are in the same order across all split meshes, if it fails + // it means this logic needs to be updated, but it also catches that here earlier in an obvious way, + // instead of failing later in a harder to track way. + if (animMeshIndexToSceneMeshes.contains(animIdx)) + { + const AnimMeshAndSceneMeshIndex& firstExistingAnim( + animMeshIndexToSceneMeshes[animIdx].m_animMeshAndSceneMeshIndex[0]); + if (strcmp( + firstExistingAnim.m_aiAnimMesh->mName.C_Str(), + aiAnimMesh->mName.C_Str()) != 0) + { + AZ_Error( + Utilities::ErrorWindow, false, + "Meshes %s and %s on node %s have mismatched animations %s and %s at index %d. This can be resolved by " + "either manually separating meshes by material in the source scene file, or by updating this logic to " + "handle out of order animation indices.", + firstExistingAnim.m_aiMesh->mName.C_Str(), + aiMesh->mName.C_Str(), + context.m_sourceNode.GetName(), + firstExistingAnim.m_aiAnimMesh->mName.C_Str(), + aiAnimMesh->mName.C_Str(), animIdx); + return Events::ProcessingResult::Failure; + } + } + + animMeshIndexToSceneMeshes[animIdx].m_animMeshAndSceneMeshIndex.emplace_back( + AnimMeshAndSceneMeshIndex(aiAnimMesh, aiMesh)); } } - for (const auto& animToMeshIndex : animToMeshToAnimMeshIndices) + for (const auto& animMeshToSceneMeshes : animMeshIndexToSceneMeshes) { AZStd::shared_ptr blendShapeData = AZStd::make_shared(); + if (animMeshToSceneMeshes.second.m_animMeshAndSceneMeshIndex.size() == 0) + { + AZ_Error(Utilities::ErrorWindow, false, "Blend shape animations were expected but missing on node %s.", + context.m_sourceNode.GetName()); + return Events::ProcessingResult::Failure; + } // Some DCC tools, like Maya, include a full path separated by '.' in the node names. // For example, "cone_skin_blendShapeNode.cone_squash" // Downstream processing doesn't want anything but the last part of that node name, // so find the last '.' and remove anything before it. - AZStd::string nodeName(animToMeshIndex.first); + AZStd::string nodeName(animMeshToSceneMeshes.second.m_animMeshAndSceneMeshIndex[0].m_aiAnimMesh->mName.C_Str()); size_t dotIndex = nodeName.rfind('.'); if (dotIndex != AZStd::string::npos) { @@ -109,12 +173,11 @@ namespace AZ } int vertexOffset = 0; RenamedNodesMap::SanitizeNodeName(nodeName, context.m_scene.GetGraph(), context.m_currentGraphPosition, "BlendShape"); - AZ_TraceContext("Blend shape name", nodeName); - for (const auto& meshIndex : animToMeshIndex.second) + + for (const auto& animMeshAndSceneIndex : animMeshToSceneMeshes.second.m_animMeshAndSceneMeshIndex) { - int sceneMeshIdx = context.m_sourceNode.GetAssImpNode()->mMeshes[meshIndex.first]; - const aiMesh* aiMesh = context.m_sourceScene.GetAssImpScene()->mMeshes[sceneMeshIdx]; - const aiAnimMesh* aiAnimMesh = aiMesh->mAnimMeshes[meshIndex.second]; + const aiAnimMesh* aiAnimMesh = animMeshAndSceneIndex.m_aiAnimMesh; + const aiMesh* aiMesh = animMeshAndSceneIndex.m_aiMesh; AZStd::bitset uvSetUsedFlags; for (AZ::u8 uvSetIndex = 0; uvSetIndex < SceneData::GraphData::BlendShapeData::MaxNumUVSets; ++uvSetIndex) @@ -199,6 +262,7 @@ namespace AZ face.mNumIndices); continue; } + for (unsigned int idx = 0; idx < face.mNumIndices; ++idx) { blendFace.vertexIndex[idx] = face.mIndices[idx] + vertexOffset; @@ -207,11 +271,8 @@ namespace AZ blendShapeData->AddFace(blendFace); } vertexOffset += aiMesh->mNumVertices; - - } - // Report problem if no vertex or face converted to MeshData if (blendShapeData->GetVertexCount() <= 0 || blendShapeData->GetFaceCount() <= 0) { From d6b268e84e54b3d606e129bf346010b88be4b1ba Mon Sep 17 00:00:00 2001 From: amzn-phist <52085794+amzn-phist@users.noreply.github.com> Date: Mon, 16 Aug 2021 12:41:24 -0500 Subject: [PATCH 397/803] Remove ResourceSelectorHost and clean up/refactor related bits (#3050) * Sever dependency on legacy resource selector host Audio resource selectors (browse dialogs) no longer need to be registered with the legacy IResourceSelectorHost system. Set up a new EBus specifically to handle browse button presses and directly invokes the dialog. Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com> * Hook up legacy audio control selector to new EBus Remaining use of legacy audio selectors (trackview) need to be able to bypass ResourceSelectorHost now. Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com> * Removes ResourceSelectorHost and legacy selectors This removes various Variable types that were tied to resource selectors, such as GeomCache, Model, Animation, File. Removes the ResourceSelectorHost completely. The two things that still appeared to have selectors in TrackView are Audio Controls and Texture. Fixed the audio control selector to work via EBus and the Texture selector didn't seem to work at all, but left it in as it was. Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com> * Make the default audio selector return old value Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com> * Fix some signed/unsigned comparison warnings Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com> * Remove deleted function from Editor Mock Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com> * Change audio selector api to use string_view Per feedback. Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com> --- .../ReflectedPropertyControl/PropertyCtrl.cpp | 3 - .../PropertyGenericCtrl.cpp | 10 -- .../PropertyGenericCtrl.h | 10 -- .../PropertyResourceCtrl.cpp | 78 ++++----- .../ReflectedPropertiesPanel.cpp | 93 ---------- .../ReflectedPropertiesPanel.h | 46 ----- .../ReflectedPropertyItem.cpp | 10 -- .../ReflectedPropertyControl/ReflectedVar.cpp | 14 -- .../ReflectedPropertyControl/ReflectedVar.h | 25 --- .../ReflectedVarWrapper.cpp | 21 +-- .../ReflectedVarWrapper.h | 14 -- Code/Editor/EditorPanelUtils.cpp | 4 +- Code/Editor/IEditor.h | 2 - Code/Editor/IEditorImpl.cpp | 2 - Code/Editor/IEditorImpl.h | 2 - Code/Editor/IEditorPanelUtils.h | 2 +- Code/Editor/Include/IResourceSelectorHost.h | 135 --------------- Code/Editor/Lib/Tests/IEditorMock.h | 1 - .../ComponentEntityEditorPlugin.cpp | 3 - .../SandboxIntegration.cpp | 11 -- .../SandboxIntegration.h | 1 - Code/Editor/ResourceSelectorHost.cpp | 163 ------------------ Code/Editor/ResourceSelectorHost.h | 18 -- Code/Editor/Util/Variable.cpp | 2 +- Code/Editor/Util/Variable.h | 6 - Code/Editor/Util/VariablePropertyType.cpp | 33 ---- Code/Editor/Util/VariablePropertyType.h | 6 - Code/Editor/editor_lib_files.cmake | 8 - .../API/ToolsApplicationAPI.h | 3 - .../UI/PropertyEditor/PropertyAudioCtrl.cpp | 19 +- .../UI/PropertyEditor/PropertyAudioCtrl.h | 21 +++ .../PropertyEditor/PropertyAudioCtrlTypes.h | 10 +- .../Editor/ATLControlsResourceDialog.cpp | 2 + .../Editor/AudioControlsEditorPlugin.cpp | 3 - .../Source/Editor/AudioControlsEditorPlugin.h | 4 +- .../Source/Editor/AudioResourceSelectors.cpp | 105 ++++------- .../Source/Editor/AudioResourceSelectors.h | 11 +- 37 files changed, 125 insertions(+), 776 deletions(-) delete mode 100644 Code/Editor/Controls/ReflectedPropertyControl/ReflectedPropertiesPanel.cpp delete mode 100644 Code/Editor/Controls/ReflectedPropertyControl/ReflectedPropertiesPanel.h delete mode 100644 Code/Editor/Include/IResourceSelectorHost.h delete mode 100644 Code/Editor/ResourceSelectorHost.cpp delete mode 100644 Code/Editor/ResourceSelectorHost.h diff --git a/Code/Editor/Controls/ReflectedPropertyControl/PropertyCtrl.cpp b/Code/Editor/Controls/ReflectedPropertyControl/PropertyCtrl.cpp index bf87f2017d..c228fbda09 100644 --- a/Code/Editor/Controls/ReflectedPropertyControl/PropertyCtrl.cpp +++ b/Code/Editor/Controls/ReflectedPropertyControl/PropertyCtrl.cpp @@ -10,7 +10,6 @@ // Editor #include "PropertyCtrl.h" -#include "PropertyAnimationCtrl.h" #include "PropertyResourceCtrl.h" #include "PropertyGenericCtrl.h" #include "PropertyMiscCtrl.h" @@ -22,9 +21,7 @@ void RegisterReflectedVarHandlers() if (!registered) { registered = true; - EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew AnimationPropertyWidgetHandler()); EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew FileResourceSelectorWidgetHandler()); - EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew ReverbPresetPropertyHandler()); EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew SequencePropertyHandler()); EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew SequenceIdPropertyHandler()); EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew LocalStringPropertyHandler()); diff --git a/Code/Editor/Controls/ReflectedPropertyControl/PropertyGenericCtrl.cpp b/Code/Editor/Controls/ReflectedPropertyControl/PropertyGenericCtrl.cpp index a2c66b8b10..8ff83dd894 100644 --- a/Code/Editor/Controls/ReflectedPropertyControl/PropertyGenericCtrl.cpp +++ b/Code/Editor/Controls/ReflectedPropertyControl/PropertyGenericCtrl.cpp @@ -73,16 +73,6 @@ void GenericPopupPropertyEditor::SetPropertyType(PropertyType type) m_propertyType = type; } -void ReverbPresetPropertyEditor::onEditClicked() -{ - CSelectEAXPresetDlg PresetDlg(this); - PresetDlg.SetCurrPreset(GetValue()); - if (PresetDlg.exec() == QDialog::Accepted) - { - SetValue(PresetDlg.GetCurrPreset()); - } -} - void SequencePropertyEditor::onEditClicked() { CSelectSequenceDialog gtDlg(this); diff --git a/Code/Editor/Controls/ReflectedPropertyControl/PropertyGenericCtrl.h b/Code/Editor/Controls/ReflectedPropertyControl/PropertyGenericCtrl.h index 2296773f0a..b6b14cf125 100644 --- a/Code/Editor/Controls/ReflectedPropertyControl/PropertyGenericCtrl.h +++ b/Code/Editor/Controls/ReflectedPropertyControl/PropertyGenericCtrl.h @@ -96,15 +96,6 @@ public: } }; -class ReverbPresetPropertyEditor - : public GenericPopupPropertyEditor -{ -public: - ReverbPresetPropertyEditor(QWidget* pParent = nullptr) - : GenericPopupPropertyEditor(pParent){} - void onEditClicked() override; -}; - class MissionObjPropertyEditor : public GenericPopupPropertyEditor { @@ -155,7 +146,6 @@ public: // So we use our own #define CONST_AZ_CRC(name, value) AZ::u32(value) -using ReverbPresetPropertyHandler = GenericPopupWidgetHandler; using MissionObjPropertyHandler = GenericPopupWidgetHandler; using SequencePropertyHandler = GenericPopupWidgetHandler; using SequenceIdPropertyHandler = GenericPopupWidgetHandler; diff --git a/Code/Editor/Controls/ReflectedPropertyControl/PropertyResourceCtrl.cpp b/Code/Editor/Controls/ReflectedPropertyControl/PropertyResourceCtrl.cpp index d3ae6aaecf..c5ccc599d6 100644 --- a/Code/Editor/Controls/ReflectedPropertyControl/PropertyResourceCtrl.cpp +++ b/Code/Editor/Controls/ReflectedPropertyControl/PropertyResourceCtrl.cpp @@ -17,9 +17,9 @@ // AzToolsFramework #include #include +#include // Editor -#include "IResourceSelectorHost.h" #include "Controls/QToolTipWidget.h" #include "Controls/BitmapToolTip.h" @@ -35,8 +35,8 @@ BrowseButton::BrowseButton(PropertyType type, QWidget* parent /*= nullptr*/) void BrowseButton::SetPathAndEmit(const QString& path) { - //only emit if path changes, except for ePropertyGeomCache. Old property control - if (path != m_path || m_propertyType == ePropertyGeomCache) + //only emit if path changes. Old property control + if (path != m_path) { m_path = path; emit PathChanged(m_path); @@ -78,21 +78,6 @@ private: // Filters for texture. selection = AssetSelectionModel::AssetGroupSelection("Texture"); } - else if (m_propertyType == ePropertyModel) - { - // Filters for models. - selection = AssetSelectionModel::AssetGroupSelection("Geometry"); - } - else if (m_propertyType == ePropertyGeomCache) - { - // Filters for geom caches. - selection = AssetSelectionModel::AssetTypeSelection("Geom Cache"); - } - else if (m_propertyType == ePropertyFile) - { - // Filters for files. - selection = AssetSelectionModel::AssetTypeSelection("File"); - } else { return; @@ -106,14 +91,7 @@ private: switch (m_propertyType) { case ePropertyTexture: - case ePropertyModel: newPath.replace("\\\\", "/"); - } - switch (m_propertyType) - { - case ePropertyTexture: - case ePropertyModel: - case ePropertyFile: if (newPath.size() > MAX_PATH) { newPath.resize(MAX_PATH); @@ -125,26 +103,51 @@ private: } }; -class ResourceSelectorButton +class AudioControlSelectorButton : public BrowseButton { public: - AZ_CLASS_ALLOCATOR(ResourceSelectorButton, AZ::SystemAllocator, 0); + AZ_CLASS_ALLOCATOR(AudioControlSelectorButton, AZ::SystemAllocator, 0); - ResourceSelectorButton(PropertyType type, QWidget* pParent = nullptr) + AudioControlSelectorButton(PropertyType type, QWidget* pParent = nullptr) : BrowseButton(type, pParent) { - setToolTip(tr("Select resource")); + setToolTip(tr("Select Audio Control")); } private: void OnClicked() override { - SResourceSelectorContext x; - x.parentWidget = this; - x.typeName = Prop::GetPropertyTypeToResourceType(m_propertyType); - QString newPath = GetIEditor()->GetResourceSelectorHost()->SelectResource(x, m_path); - SetPathAndEmit(newPath); + AZStd::string resourceResult; + auto ConvertLegacyAudioPropertyType = [](const PropertyType type) -> AzToolsFramework::AudioPropertyType + { + switch (type) + { + case ePropertyAudioTrigger: + return AzToolsFramework::AudioPropertyType::Trigger; + case ePropertyAudioRTPC: + return AzToolsFramework::AudioPropertyType::Rtpc; + case ePropertyAudioSwitch: + return AzToolsFramework::AudioPropertyType::Switch; + case ePropertyAudioSwitchState: + return AzToolsFramework::AudioPropertyType::SwitchState; + case ePropertyAudioEnvironment: + return AzToolsFramework::AudioPropertyType::Environment; + case ePropertyAudioPreloadRequest: + return AzToolsFramework::AudioPropertyType::Preload; + default: + return AzToolsFramework::AudioPropertyType::NumTypes; + } + }; + + auto propType = ConvertLegacyAudioPropertyType(m_propertyType); + if (propType != AzToolsFramework::AudioPropertyType::NumTypes) + { + AzToolsFramework::AudioControlSelectorRequestBus::EventResult( + resourceResult, propType, &AzToolsFramework::AudioControlSelectorRequestBus::Events::SelectResource, + AZStd::string_view{ m_path.toUtf8().constData() }); + SetPathAndEmit(QString{ resourceResult.c_str() }); + } } }; @@ -235,18 +238,13 @@ void FileResourceSelectorWidget::SetPropertyType(PropertyType type) AddButton(new TextureEditButton); m_previewToolTip.reset(new CBitmapToolTip); break; - case ePropertyModel: - case ePropertyGeomCache: case ePropertyAudioTrigger: case ePropertyAudioSwitch: case ePropertyAudioSwitchState: case ePropertyAudioRTPC: case ePropertyAudioEnvironment: case ePropertyAudioPreloadRequest: - AddButton(new ResourceSelectorButton(type)); - break; - case ePropertyFile: - AddButton(new FileBrowseButton(type)); + AddButton(new AudioControlSelectorButton(type)); break; default: break; diff --git a/Code/Editor/Controls/ReflectedPropertyControl/ReflectedPropertiesPanel.cpp b/Code/Editor/Controls/ReflectedPropertyControl/ReflectedPropertiesPanel.cpp deleted file mode 100644 index 8651db7e96..0000000000 --- a/Code/Editor/Controls/ReflectedPropertyControl/ReflectedPropertiesPanel.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - -// Description : implementation file - -#include "EditorDefs.h" - -#include "ReflectedPropertiesPanel.h" - -///////////////////////////////////////////////////////////////////////////// -// ReflectedPropertiesPanel dialog - - -ReflectedPropertiesPanel::ReflectedPropertiesPanel(QWidget* pParent) - : ReflectedPropertyControl(pParent) -{ -} - -////////////////////////////////////////////////////////////////////////// -void ReflectedPropertiesPanel::DeleteVars() -{ - ClearVarBlock(); - m_updateCallbacks.clear(); - m_varBlock = nullptr; -} - -////////////////////////////////////////////////////////////////////////// -void ReflectedPropertiesPanel::SetVarBlock(class CVarBlock* vb, ReflectedPropertyControl::UpdateVarCallback* updCallback, const char* category) -{ - assert(vb); - - m_varBlock = vb; - - RemoveAllItems(); - m_varBlock = vb; - AddVarBlock(m_varBlock, category); - - SetUpdateCallback(AZStd::bind(&ReflectedPropertiesPanel::OnPropertyChanged, this, AZStd::placeholders::_1)); - - // When new object set all previous callbacks freed. - m_updateCallbacks.clear(); - if (updCallback) - { - stl::push_back_unique(m_updateCallbacks, updCallback); - } -} - -////////////////////////////////////////////////////////////////////////// -void ReflectedPropertiesPanel::AddVars(CVarBlock* vb, ReflectedPropertyControl::UpdateVarCallback* updCallback, const char* category) -{ - assert(vb); - - bool bNewBlock = false; - // Make a clone of properties. - if (!m_varBlock) - { - RemoveAllItems(); - m_varBlock = vb->Clone(true); - AddVarBlock(m_varBlock, category); - bNewBlock = true; - } - m_varBlock->Wire(vb); - - if (bNewBlock) - { - SetUpdateCallback(AZStd::bind(&ReflectedPropertiesPanel::OnPropertyChanged, this, AZStd::placeholders::_1)); - - // When new object set all previous callbacks freed. - m_updateCallbacks.clear(); - } - - if (updCallback) - { - stl::push_back_unique(m_updateCallbacks, updCallback); - } -} - -void ReflectedPropertiesPanel::OnPropertyChanged(IVariable* pVar) -{ - std::list::iterator iter; - for (iter = m_updateCallbacks.begin(); iter != m_updateCallbacks.end(); ++iter) - { - (*iter)->operator()(pVar); - } -} - - diff --git a/Code/Editor/Controls/ReflectedPropertyControl/ReflectedPropertiesPanel.h b/Code/Editor/Controls/ReflectedPropertyControl/ReflectedPropertiesPanel.h deleted file mode 100644 index cd551c63e2..0000000000 --- a/Code/Editor/Controls/ReflectedPropertyControl/ReflectedPropertiesPanel.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -#ifndef CRYINCLUDE_EDITOR_REFLECTEDPROPERTIESPANEL_H -#define CRYINCLUDE_EDITOR_REFLECTEDPROPERTIESPANEL_H - -#pragma once - -#include "Controls/ReflectedPropertyControl/ReflectedPropertyCtrl.h" -#include "Util/Variable.h" - -///////////////////////////////////////////////////////////////////////////// -// ReflectedPropertiesPanel dialog - -AZ_PUSH_DISABLE_DLL_EXPORT_BASECLASS_WARNING -//This class is a port of ReflectedPropertiesPanel to use the ReflectedPropertyControl -class SANDBOX_API ReflectedPropertiesPanel - : public ReflectedPropertyControl -{ -AZ_POP_DISABLE_DLL_EXPORT_BASECLASS_WARNING -public: - ReflectedPropertiesPanel(QWidget* pParent = nullptr); // standard constructor - - void DeleteVars(); - void AddVars(class CVarBlock* vb, ReflectedPropertyControl::UpdateVarCallback* func = nullptr, const char* category = nullptr); - - void SetVarBlock(class CVarBlock* vb, ReflectedPropertyControl::UpdateVarCallback* func = nullptr, const char* category = nullptr); - -protected: - void OnPropertyChanged(IVariable* pVar); - -protected: - AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING - TSmartPtr m_varBlock; - - std::list m_updateCallbacks; - AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING -}; - - -#endif // CRYINCLUDE_EDITOR_REFLECTEDPROPERTIESPANEL_H diff --git a/Code/Editor/Controls/ReflectedPropertyControl/ReflectedPropertyItem.cpp b/Code/Editor/Controls/ReflectedPropertyControl/ReflectedPropertyItem.cpp index 5a9d61be42..303f86d270 100644 --- a/Code/Editor/Controls/ReflectedPropertyControl/ReflectedPropertyItem.cpp +++ b/Code/Editor/Controls/ReflectedPropertyControl/ReflectedPropertyItem.cpp @@ -255,9 +255,6 @@ void ReflectedPropertyItem::SetVariable(IVariable *var) case ePropertySelection: m_reflectedVarAdapter = new ReflectedVarEnumAdapter; break; - case ePropertyAnimation: - m_reflectedVarAdapter = new ReflectedVarAnimationAdapter; - break; case ePropertyColor: m_reflectedVarAdapter = new ReflectedVarColorAdapter; break; @@ -265,7 +262,6 @@ void ReflectedPropertyItem::SetVariable(IVariable *var) m_reflectedVarAdapter = new ReflectedVarUserAdapter; break; case ePropertyEquip: - case ePropertyReverbPreset: case ePropertyGameToken: case ePropertyMissionObj: case ePropertySequence: @@ -276,15 +272,12 @@ void ReflectedPropertyItem::SetVariable(IVariable *var) m_reflectedVarAdapter = new ReflectedVarGenericPropertyAdapter(desc.m_type); break; case ePropertyTexture: - case ePropertyModel: - case ePropertyGeomCache: case ePropertyAudioTrigger: case ePropertyAudioSwitch: case ePropertyAudioSwitchState: case ePropertyAudioRTPC: case ePropertyAudioEnvironment: case ePropertyAudioPreloadRequest: - case ePropertyFile: m_reflectedVarAdapter = new ReflectedVarResourceAdapter; break; case ePropertyFloatCurve: @@ -569,7 +562,6 @@ void ReflectedPropertyItem::SetValue(const QString& sValue, bool bRecordUndo, bo break; case ePropertyTexture: - case ePropertyModel: value.replace('\\', '/'); break; } @@ -578,8 +570,6 @@ void ReflectedPropertyItem::SetValue(const QString& sValue, bool bRecordUndo, bo switch (m_type) { case ePropertyTexture: - case ePropertyModel: - case ePropertyFile: if (value.length() >= MAX_PATH) { value = value.left(MAX_PATH); diff --git a/Code/Editor/Controls/ReflectedPropertyControl/ReflectedVar.cpp b/Code/Editor/Controls/ReflectedPropertyControl/ReflectedVar.cpp index 5b9c5b8063..263c17a8bb 100644 --- a/Code/Editor/Controls/ReflectedPropertyControl/ReflectedVar.cpp +++ b/Code/Editor/Controls/ReflectedPropertyControl/ReflectedVar.cpp @@ -31,12 +31,6 @@ void ReflectedVarInit::setupReflection(AZ::SerializeContext* serializeContext) ->Field("description", &CReflectedVar::m_description) ->Field("varName", &CReflectedVar::m_varName); - serializeContext->Class () - ->Version(1) - ->Field("animation", &CReflectedVarAnimation::m_animation) - ->Field("entityID", &CReflectedVarAnimation::m_entityID) - ; - serializeContext->Class () ->Version(1) ->Field("path", &CReflectedVarResource::m_path) @@ -76,12 +70,6 @@ void ReflectedVarInit::setupReflection(AZ::SerializeContext* serializeContext) AZ::EditContext* ec = serializeContext->GetEditContext(); if (ec) { - ec->Class< CReflectedVarAnimation >("VarAnimation", "Animation") - ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->Attribute(AZ::Edit::Attributes::NameLabelOverride, &CReflectedVarAnimation::varName) - ->Attribute(AZ::Edit::Attributes::DescriptionTextOverride, &CReflectedVarAnimation::description) - ; - ec->Class< CReflectedVarResource >("VarResource", "Resource") ->ClassElement(AZ::Edit::ClassElements::EditorData, "") ->Attribute(AZ::Edit::Attributes::NameLabelOverride, &CReflectedVarResource::varName) @@ -284,8 +272,6 @@ AZ::u32 CReflectedVarGenericProperty::handler() return AZ_CRC("ePropertyShader", 0xc40932f1); case ePropertyEquip: return AZ_CRC("ePropertyEquip", 0x66ffd290); - case ePropertyReverbPreset: - return AZ_CRC("ePropertyReverbPreset", 0x51469f38); case ePropertyDeprecated0: return AZ_CRC("ePropertyCustomAction", 0x4ffa5ba5); case ePropertyGameToken: diff --git a/Code/Editor/Controls/ReflectedPropertyControl/ReflectedVar.h b/Code/Editor/Controls/ReflectedPropertyControl/ReflectedVar.h index 634f2efd3a..a15f8326d1 100644 --- a/Code/Editor/Controls/ReflectedPropertyControl/ReflectedVar.h +++ b/Code/Editor/Controls/ReflectedPropertyControl/ReflectedVar.h @@ -265,32 +265,8 @@ public: AZ::Vector3 m_color; }; -//Class to hold ePropertyAnimation (IVariable::DT_ANIMATION ) -class CReflectedVarAnimation - : public CReflectedVar -{ -public: - AZ_RTTI(CReflectedVarAnimation, "{635D982E-23EC-463F-8F33-4FC2C19D5673}", CReflectedVar) - - CReflectedVarAnimation(const AZStd::string& name) - : CReflectedVar(name) - , m_entityID(0) - {} - CReflectedVarAnimation() - : m_entityID(0){} - - AZStd::string varName() const { return m_varName; } - AZStd::string description() const { return m_description; } - - AZStd::string m_animation; - AZ::EntityId m_entityID; -}; - //Class to hold: // ePropertyTexture (IVariable::DT_TEXTURE) -// ePropertyMaterial (IVariable::DT_MATERIAL) -// ePropertyModel (IVariable::DT_OBJECT) -// ePropertyGeomCache (IVariable::DT_GEOM_CACHE) // ePropertyAudioTrigger (IVariable::DT_AUDIO_TRIGGER) // ePropertyAudioSwitch (IVariable::DT_AUDIO_SWITCH ) // ePropertyAudioSwitchState (IVariable::DT_AUDIO_SWITCH_STATE) @@ -344,7 +320,6 @@ public: AZStd::vector m_itemDescriptions; }; -//Class to hold ePropertyAnimation (IVariable::DT_ANIMATION ) class CReflectedVarSpline : public CReflectedVar { diff --git a/Code/Editor/Controls/ReflectedPropertyControl/ReflectedVarWrapper.cpp b/Code/Editor/Controls/ReflectedPropertyControl/ReflectedVarWrapper.cpp index 5639fa95b0..aba346ce6a 100644 --- a/Code/Editor/Controls/ReflectedPropertyControl/ReflectedVarWrapper.cpp +++ b/Code/Editor/Controls/ReflectedPropertyControl/ReflectedVarWrapper.cpp @@ -392,25 +392,6 @@ void ReflectedVarColorAdapter::SyncIVarToReflectedVar(IVariable *pVariable) -void ReflectedVarAnimationAdapter::SetVariable(IVariable *pVariable) -{ - m_reflectedVar.reset(new CReflectedVarAnimation(pVariable->GetHumanName().toUtf8().data())); - m_reflectedVar->m_description = pVariable->GetDescription().toUtf8().data(); -} - -void ReflectedVarAnimationAdapter::SyncReflectedVarToIVar(IVariable *pVariable) -{ - m_reflectedVar->m_entityID = static_cast(pVariable->GetUserData().value()); - m_reflectedVar->m_animation = pVariable->GetDisplayValue().toUtf8().data(); -} - -void ReflectedVarAnimationAdapter::SyncIVarToReflectedVar(IVariable *pVariable) -{ - pVariable->SetUserData(static_cast(m_reflectedVar->m_entityID)); - pVariable->SetDisplayValue(m_reflectedVar->m_animation.c_str()); - -} - void ReflectedVarResourceAdapter::SetVariable(IVariable *pVariable) { m_reflectedVar.reset(new CReflectedVarResource(pVariable->GetHumanName().toUtf8().data())); @@ -429,7 +410,7 @@ void ReflectedVarResourceAdapter::SyncReflectedVarToIVar(IVariable *pVariable) void ReflectedVarResourceAdapter::SyncIVarToReflectedVar(IVariable *pVariable) { - const bool bForceModified = (m_reflectedVar->m_propertyType == ePropertyGeomCache); + const bool bForceModified = false; pVariable->SetForceModified(bForceModified); pVariable->SetDisplayValue(m_reflectedVar->m_path.c_str()); diff --git a/Code/Editor/Controls/ReflectedPropertyControl/ReflectedVarWrapper.h b/Code/Editor/Controls/ReflectedPropertyControl/ReflectedVarWrapper.h index 07bb72413a..9c49f1ae1a 100644 --- a/Code/Editor/Controls/ReflectedPropertyControl/ReflectedVarWrapper.h +++ b/Code/Editor/Controls/ReflectedPropertyControl/ReflectedVarWrapper.h @@ -218,20 +218,6 @@ AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING }; -class EDITOR_CORE_API ReflectedVarAnimationAdapter - : public ReflectedVarAdapter -{ -public: - void SetVariable(IVariable* pVariable) override; - void SyncReflectedVarToIVar(IVariable* pVariable) override; - void SyncIVarToReflectedVar(IVariable* pVariable) override; - CReflectedVar* GetReflectedVar() override { return m_reflectedVar.data(); } -private: -AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING - QScopedPointer m_reflectedVar; -AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING -}; - class EDITOR_CORE_API ReflectedVarResourceAdapter : public ReflectedVarAdapter { diff --git a/Code/Editor/EditorPanelUtils.cpp b/Code/Editor/EditorPanelUtils.cpp index b19bde4583..12e9457474 100644 --- a/Code/Editor/EditorPanelUtils.cpp +++ b/Code/Editor/EditorPanelUtils.cpp @@ -130,7 +130,7 @@ public: HotKey_BuildDefaults(); for (QPair key : keys) { - for (unsigned int j = 0; j < hotkeys.count(); j++) + for (int j = 0; j < hotkeys.count(); j++) { if (hotkeys[j].path.compare(key.first, Qt::CaseInsensitive) == 0) { @@ -256,7 +256,7 @@ public: hotkey.second = settings.value("keySequence").toString(); if (!hotkey.first.isEmpty()) { - for (unsigned int j = 0; j < hotkeys.count(); j++) + for (int j = 0; j < hotkeys.count(); j++) { if (hotkeys[j].path.compare(hotkey.first, Qt::CaseInsensitive) == 0) { diff --git a/Code/Editor/IEditor.h b/Code/Editor/IEditor.h index f66dca412e..7d0fc653fa 100644 --- a/Code/Editor/IEditor.h +++ b/Code/Editor/IEditor.h @@ -68,7 +68,6 @@ class CDisplaySettings; struct SGizmoParameters; class CLevelIndependentFileMan; class CSelectionTreeManager; -struct IResourceSelectorHost; struct SEditorSettings; class CGameExporter; class IAWSResourceManager; @@ -714,7 +713,6 @@ struct IEditor virtual ESystemConfigSpec GetEditorConfigSpec() const = 0; virtual ESystemConfigPlatform GetEditorConfigPlatform() const = 0; virtual void ReloadTemplates() = 0; - virtual IResourceSelectorHost* GetResourceSelectorHost() = 0; virtual void ShowStatusText(bool bEnable) = 0; // Provides a way to extend the context menu of an object. The function gets called every time the menu is opened. diff --git a/Code/Editor/IEditorImpl.cpp b/Code/Editor/IEditorImpl.cpp index 1459139f66..1e268d64ef 100644 --- a/Code/Editor/IEditorImpl.cpp +++ b/Code/Editor/IEditorImpl.cpp @@ -67,7 +67,6 @@ AZ_POP_DISABLE_WARNING #include "EditorFileMonitor.h" #include "MainStatusBar.h" -#include "ResourceSelectorHost.h" #include "Util/FileUtil_impl.h" #include "Util/ImageUtil_impl.h" #include "LogFileImpl.h" @@ -187,7 +186,6 @@ CEditorImpl::CEditorImpl() m_pAnimationContext = new CAnimationContext; m_pImageUtil = new CImageUtil_impl(); - m_pResourceSelectorHost.reset(CreateResourceSelectorHost()); m_selectedRegion.min = Vec3(0, 0, 0); m_selectedRegion.max = Vec3(0, 0, 0); DetectVersion(); diff --git a/Code/Editor/IEditorImpl.h b/Code/Editor/IEditorImpl.h index 02be8bb8e3..2cf6c7805b 100644 --- a/Code/Editor/IEditorImpl.h +++ b/Code/Editor/IEditorImpl.h @@ -290,7 +290,6 @@ public: ESystemConfigPlatform GetEditorConfigPlatform() const; void ReloadTemplates(); void AddErrorMessage(const QString& text, const QString& caption); - IResourceSelectorHost* GetResourceSelectorHost() { return m_pResourceSelectorHost.get(); } virtual void ShowStatusText(bool bEnable); void OnObjectContextMenuOpened(QMenu* pMenu, const CBaseObject* pObject); @@ -374,7 +373,6 @@ protected: //! Export manager for exporting objects and a terrain from the game to DCC tools CExportManager* m_pExportManager; std::unique_ptr m_pEditorFileMonitor; - std::unique_ptr m_pResourceSelectorHost; QString m_selectFileBuffer; QString m_levelNameBuffer; diff --git a/Code/Editor/IEditorPanelUtils.h b/Code/Editor/IEditorPanelUtils.h index 5df15bd86b..4649213ae7 100644 --- a/Code/Editor/IEditorPanelUtils.h +++ b/Code/Editor/IEditorPanelUtils.h @@ -65,7 +65,7 @@ struct HotKey int size = (m_catSize < o_catSize) ? m_catSize : o_catSize; //sort categories to keep them together - for (unsigned int i = 0; i < size; i++) + for (int i = 0; i < size; i++) { if (m_categories[i] < o_categories[i]) { diff --git a/Code/Editor/Include/IResourceSelectorHost.h b/Code/Editor/Include/IResourceSelectorHost.h deleted file mode 100644 index 55ce4e15d3..0000000000 --- a/Code/Editor/Include/IResourceSelectorHost.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - -#pragma once -// The aim of IResourceSelectorHost is to unify resource selection dialogs in a one -// API that can be reused with plugins. It also makes possible to register new -// resource selectors dynamically, e.g. inside plugins. -// -// Here is how new selectors are created. In your implementation file you add handler function: -// -// #include "IResourceSelectorHost.h" -// -// QString SoundFileSelector(const SResourceSelectorContext& x, const QString& previousValue) -// { -// CMyModalDialog dialog(CWnd::FromHandle(x.parentWindow)); -// ... -// return previousValue; -// } -// REGISTER_RESOURCE_SELECTOR("Sound", SoundFileSelector, "Icons/sound_16x16.png") -// -// Here is how it can be invoked directly: -// -// SResourceSelectorContext x; -// x.parentWindow = parent.GetSafeHwnd(); -// x.typeName = "Sound"; -// string newValue = GetIEditor()->GetResourceSelector()->SelectResource(x, previousValue).c_str(); -// -// If you have your own resource selectors in the plugin you will need to run -// -// RegisterModuleResourceSelectors(GetIEditor()->GetResourceSelector()) -// -// during plugin initialization. -// -// If you want to be able to pass some custom context to the selector (e.g. source of the information for the -// list of items or something similar) then you can add a poitner argument to your selector function, i.e.: -// -// QString SoundFileSelector(const SResourceSelectorContext& x, const QString& previousValue, -// SoundFileList* list) // your context argument - -#include - -class QWidget; - -struct SResourceSelectorContext -{ - const char* typeName; - - // use either parentWidget or parentWindow (not both) until everything porting to QWidget. - QWidget* parentWidget; - - unsigned int entityId; - void* contextObject; - - SResourceSelectorContext() - : parentWidget(0) - , typeName(0) - , entityId(0) - , contextObject() - { - } -}; - -// TResourceSelecitonFunction is used to declare handlers for specific types. -// -// For canceled dialogs previousValue should be returned. -typedef QString (* TResourceSelectionFunction)(const SResourceSelectorContext& selectorContext, const QString& previousValue); -typedef QString (* TResourceSelectionFunctionWithContext)(const SResourceSelectorContext& selectorContext, const QString& previousValue, void* contextObject); - -struct SStaticResourceSelectorEntry; - -// See note at the beginning of the file. -struct IResourceSelectorHost -{ - virtual ~IResourceSelectorHost() = default; - virtual QString SelectResource(const SResourceSelectorContext& context, const QString& previousValue) = 0; - virtual const char* ResourceIconPath(const char* typeName) const = 0; - - virtual void RegisterResourceSelector(const SStaticResourceSelectorEntry* entry) = 0; - - // secondary responsibility of this class is to store global selections - virtual void SetGlobalSelection(const char* resourceType, const char* value) = 0; - virtual const char* GetGlobalSelection(const char* resourceType) const = 0; -}; - -// --------------------------------------------------------------------------- -#define INTERNAL_RSH_COMBINE_UTIL(A, B) A##B -#define INTERNAL_RSH_COMBINE(A, B) INTERNAL_RSH_COMBINE_UTIL(A, B) -#define REGISTER_RESOURCE_SELECTOR(name, function, icon) \ - static SStaticResourceSelectorEntry INTERNAL_RSH_COMBINE(selector_##function, __LINE__)((name), (function), (icon)); - -struct SStaticResourceSelectorEntry -{ - const char* typeName; - TResourceSelectionFunction function; - TResourceSelectionFunctionWithContext functionWithContext; - const char* iconPath; - - static SStaticResourceSelectorEntry*& GetFirst() { static SStaticResourceSelectorEntry* first; return first; } - SStaticResourceSelectorEntry* next; - - SStaticResourceSelectorEntry(const char* typeName, TResourceSelectionFunction function, const char* icon) - : typeName(typeName) - , function(function) - , functionWithContext() - , iconPath(icon) - { - next = GetFirst(); - GetFirst() = this; - } - - template - SStaticResourceSelectorEntry(const char* typeName, QString (*function)(const SResourceSelectorContext&, const QString& previousValue, T * context), const char* icon) - : typeName(typeName) - , function() - , functionWithContext(TResourceSelectionFunctionWithContext(function)) - , iconPath(icon) - { - next = GetFirst(); - GetFirst() = this; - } -}; - -inline void RegisterModuleResourceSelectors(IResourceSelectorHost* editorResourceSelector) -{ - for (SStaticResourceSelectorEntry* current = SStaticResourceSelectorEntry::GetFirst(); current != 0; current = current->next) - { - editorResourceSelector->RegisterResourceSelector(current); - } -} diff --git a/Code/Editor/Lib/Tests/IEditorMock.h b/Code/Editor/Lib/Tests/IEditorMock.h index 9f99b0cd9d..242bf4d25c 100644 --- a/Code/Editor/Lib/Tests/IEditorMock.h +++ b/Code/Editor/Lib/Tests/IEditorMock.h @@ -178,7 +178,6 @@ public: MOCK_CONST_METHOD0(GetEditorConfigSpec, ESystemConfigSpec()); MOCK_CONST_METHOD0(GetEditorConfigPlatform, ESystemConfigPlatform()); MOCK_METHOD0(ReloadTemplates, void()); - MOCK_METHOD0(GetResourceSelectorHost, IResourceSelectorHost* ()); MOCK_METHOD1(ShowStatusText, void(bool )); MOCK_METHOD1(RegisterObjectContextMenuExtension, void(TContextMenuExtensionFunc )); MOCK_METHOD0(GetEnv, SSystemGlobalEnvironment* ()); diff --git a/Code/Editor/Plugins/ComponentEntityEditorPlugin/ComponentEntityEditorPlugin.cpp b/Code/Editor/Plugins/ComponentEntityEditorPlugin/ComponentEntityEditorPlugin.cpp index 3f4cd1b566..50b315b9c3 100644 --- a/Code/Editor/Plugins/ComponentEntityEditorPlugin/ComponentEntityEditorPlugin.cpp +++ b/Code/Editor/Plugins/ComponentEntityEditorPlugin/ComponentEntityEditorPlugin.cpp @@ -9,7 +9,6 @@ #include "ComponentEntityEditorPlugin.h" #include -#include "IResourceSelectorHost.h" #include "UI/QComponentEntityEditorMainWindow.h" #include "UI/QComponentEntityEditorOutlinerWindow.h" @@ -180,8 +179,6 @@ ComponentEntityEditorPlugin::ComponentEntityEditorPlugin([[maybe_unused]] IEdito RegisterViewPane(LyViewPane::SliceRelationships, LyViewPane::CategoryTools, options); } - RegisterModuleResourceSelectors(GetIEditor()->GetResourceSelectorHost()); - ComponentEntityEditorPluginInternal::RegisterSandboxObjects(); // Check for common mistakes in component declarations diff --git a/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp b/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp index 66c57361be..b10fe35513 100644 --- a/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp +++ b/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp @@ -82,7 +82,6 @@ #include #include #include -#include #include "CryEdit.h" #include "Undo/Undo.h" @@ -1387,16 +1386,6 @@ AZStd::string SandboxIntegrationManager::GetLevelName() return AZStd::string(GetIEditor()->GetGameEngine()->GetLevelName().toUtf8().constData()); } -AZStd::string SandboxIntegrationManager::SelectResource(const AZStd::string& resourceType, const AZStd::string& previousValue) -{ - SResourceSelectorContext context; - context.parentWidget = GetMainWindow(); - context.typeName = resourceType.c_str(); - - QString resource = GetEditor()->GetResourceSelectorHost()->SelectResource(context, previousValue.c_str()); - return AZStd::string(resource.toUtf8().constData()); -} - void SandboxIntegrationManager::OnContextReset() { // Deselect everything. diff --git a/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.h b/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.h index a2ec3b579b..d14ba80bce 100644 --- a/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.h +++ b/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.h @@ -158,7 +158,6 @@ private: void LaunchLuaEditor(const char* files) override; bool IsLevelDocumentOpen() override; AZStd::string GetLevelName() override; - AZStd::string SelectResource(const AZStd::string& resourceType, const AZStd::string& previousValue) override; void OpenPinnedInspector(const AzToolsFramework::EntityIdSet& entities) override; void ClosePinnedInspector(AzToolsFramework::EntityPropertyEditor* editor) override; void GoToSelectedOrHighlightedEntitiesInViewports() override; diff --git a/Code/Editor/ResourceSelectorHost.cpp b/Code/Editor/ResourceSelectorHost.cpp deleted file mode 100644 index eb82b57ab4..0000000000 --- a/Code/Editor/ResourceSelectorHost.cpp +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - -#include "EditorDefs.h" - -#include "ResourceSelectorHost.h" - -// Qt -#include -#include - -// AzToolsFramework -#include -#include -#include - - -class CResourceSelectorHost - : public IResourceSelectorHost -{ -public: - CResourceSelectorHost() - { - RegisterModuleResourceSelectors(this); - } - - QString SelectResource(const SResourceSelectorContext& context, const QString& previousValue) override - { - if (!context.typeName) - { - assert(false && "SResourceSelectorContext::typeName is not specified"); - return QString(); - } - - TTypeMap::iterator it = m_typeMap.find(context.typeName); - if (it == m_typeMap.end()) - { - QMessageBox::critical(QApplication::activeWindow(), QString(), QObject::tr("No Resource Selector is registered for resource type \"%1\"").arg(context.typeName)); - return previousValue; - } - - QString result = previousValue; - if (it->second->function) - { - result = it->second->function(context, previousValue); - } - else if (it->second->functionWithContext) - { - result = it->second->functionWithContext(context, previousValue, context.contextObject); - } - - return result; - } - - const char* ResourceIconPath(const char* typeName) const override - { - TTypeMap::const_iterator it = m_typeMap.find(typeName); - if (it != m_typeMap.end()) - { - return it->second->iconPath; - } - return ""; - } - - void RegisterResourceSelector(const SStaticResourceSelectorEntry* entry) override - { - m_typeMap[entry->typeName] = entry; - } - - void SetGlobalSelection(const char* resourceType, const char* value) override - { - if (!resourceType || !value) - { - return; - } - m_globallySelectedResources[resourceType] = value; - } - - const char* GetGlobalSelection(const char* resourceType) const override - { - if (!resourceType) - { - return ""; - } - auto it = m_globallySelectedResources.find(resourceType); - if (it != m_globallySelectedResources.end()) - { - return it->second.c_str(); - } - return ""; - } - -private: - using TTypeMap = std::map>; - TTypeMap m_typeMap; - - std::map m_globallySelectedResources; -}; - -// --------------------------------------------------------------------------- - -IResourceSelectorHost* CreateResourceSelectorHost() -{ - return new CResourceSelectorHost(); -} - -// --------------------------------------------------------------------------- - -QString SoundFileSelector([[maybe_unused]] const SResourceSelectorContext& x, const QString& previousValue) -{ - AssetSelectionModel selection = AssetSelectionModel::AssetTypeSelection("Audio"); - AzToolsFramework::EditorRequests::Bus::Broadcast(&AzToolsFramework::EditorRequests::BrowseForAssets, selection); - if (selection.IsValid()) - { - return Path::FullPathToGamePath(QString(selection.GetResult()->GetFullPath().c_str())); - } - else - { - return Path::FullPathToGamePath(previousValue); - } -} -REGISTER_RESOURCE_SELECTOR("Sound", SoundFileSelector, "") - -// --------------------------------------------------------------------------- -QString ModelFileSelector([[maybe_unused]] const SResourceSelectorContext& x, const QString& previousValue) -{ - AssetSelectionModel selection = AssetSelectionModel::AssetGroupSelection("Geometry"); - AzToolsFramework::EditorRequests::Bus::Broadcast(&AzToolsFramework::EditorRequests::BrowseForAssets, selection); - if (selection.IsValid()) - { - return Path::FullPathToGamePath(QString(selection.GetResult()->GetFullPath().c_str())); - } - else - { - return Path::FullPathToGamePath(previousValue); - } -} -REGISTER_RESOURCE_SELECTOR("Model", ModelFileSelector, "") - -// --------------------------------------------------------------------------- -QString GeomCacheFileSelector([[maybe_unused]] const SResourceSelectorContext& x, const QString& previousValue) -{ - AssetSelectionModel selection = AssetSelectionModel::AssetTypeSelection("Geom Cache"); - AzToolsFramework::EditorRequests::Bus::Broadcast(&AzToolsFramework::EditorRequests::BrowseForAssets, selection); - if (selection.IsValid()) - { - return Path::FullPathToGamePath(QString(selection.GetResult()->GetFullPath().c_str())); - } - else - { - return Path::FullPathToGamePath(previousValue); - } -} - -REGISTER_RESOURCE_SELECTOR("GeomCache", GeomCacheFileSelector, "") - - diff --git a/Code/Editor/ResourceSelectorHost.h b/Code/Editor/ResourceSelectorHost.h deleted file mode 100644 index 266b7c39d1..0000000000 --- a/Code/Editor/ResourceSelectorHost.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - -#ifndef CRYINCLUDE_EDITOR_RESOURCESELECTORHOST_H -#define CRYINCLUDE_EDITOR_RESOURCESELECTORHOST_H -#pragma once - -#include "IResourceSelectorHost.h" - -IResourceSelectorHost* CreateResourceSelectorHost(); - -#endif // CRYINCLUDE_EDITOR_RESOURCESELECTORHOST_H diff --git a/Code/Editor/Util/Variable.cpp b/Code/Editor/Util/Variable.cpp index ee5ccc9879..97c2a1e8af 100644 --- a/Code/Editor/Util/Variable.cpp +++ b/Code/Editor/Util/Variable.cpp @@ -351,7 +351,7 @@ void CVarBlock::EnableUpdateCallbacks(bool boEnable) void CVarBlock::GatherUsedResourcesInVar(IVariable* pVar, CUsedResources& resources) { int type = pVar->GetDataType(); - if (type == IVariable::DT_FILE || type == IVariable::DT_OBJECT || type == IVariable::DT_TEXTURE) + if (type == IVariable::DT_TEXTURE) { // this is file. QString filename; diff --git a/Code/Editor/Util/Variable.h b/Code/Editor/Util/Variable.h index ecd54e42ae..da506b9db0 100644 --- a/Code/Editor/Util/Variable.h +++ b/Code/Editor/Util/Variable.h @@ -142,15 +142,10 @@ struct IVariable DT_PERCENT, //!< Percent data type, (Same as simple but value is from 0-1 and UI will be from 0-100). DT_COLOR, DT_ANGLE, - DT_FILE, DT_TEXTURE, - DT_ANIMATION, - DT_OBJECT, DT_SHADER, DT_LOCAL_STRING, DT_EQUIP, - DT_REVERBPRESET, - DT_DEPRECATED0, // formerly DT_MATERIAL DT_MATERIALLOOKUP, DT_EXTARRAY, // Extendable Array DT_SEQUENCE, // Movie Sequence (DEPRECATED, use DT_SEQUENCE_ID, instead.) @@ -160,7 +155,6 @@ struct IVariable DT_SEQUENCE_ID, // Movie Sequence DT_LIGHT_ANIMATION, // Light Animation Node in the global Light Animation Set DT_PARTICLE_EFFECT, - DT_GEOM_CACHE, // Geometry cache DT_DEPRECATED, // formerly DT_FLARE DT_AUDIO_TRIGGER, DT_AUDIO_SWITCH, diff --git a/Code/Editor/Util/VariablePropertyType.cpp b/Code/Editor/Util/VariablePropertyType.cpp index 014995467b..17c80a505c 100644 --- a/Code/Editor/Util/VariablePropertyType.cpp +++ b/Code/Editor/Util/VariablePropertyType.cpp @@ -37,17 +37,12 @@ namespace Prop { IVariable::DT_CURVE | IVariable::DT_PERCENT, "FloatCurve", ePropertyFloatCurve, 13 }, { IVariable::DT_CURVE | IVariable::DT_COLOR, "ColorCurve", ePropertyColorCurve, 1 }, { IVariable::DT_ANGLE, "Angle", ePropertyAngle, 0 }, - { IVariable::DT_FILE, "File", ePropertyFile, 7 }, { IVariable::DT_TEXTURE, "Texture", ePropertyTexture, 4 }, - { IVariable::DT_ANIMATION, "Animation", ePropertyAnimation, -1 }, { IVariable::DT_MOTION, "Motion", ePropertyMotion, -1 }, - { IVariable::DT_OBJECT, "Model", ePropertyModel, 5 }, { IVariable::DT_SIMPLE, "Selection", ePropertySelection, -1 }, { IVariable::DT_SIMPLE, "List", ePropertyList, -1 }, { IVariable::DT_SHADER, "Shader", ePropertyShader, 9 }, - { IVariable::DT_DEPRECATED0, "DEPRECATED", ePropertyDeprecated2, -1 }, { IVariable::DT_EQUIP, "Equip", ePropertyEquip, 11 }, - { IVariable::DT_REVERBPRESET, "ReverbPreset", ePropertyReverbPreset, 11 }, { IVariable::DT_LOCAL_STRING, "LocalString", ePropertyLocalString, 3 }, { IVariable::DT_SEQUENCE, "Sequence", ePropertySequence, -1 }, { IVariable::DT_MISSIONOBJ, "Mission Objective", ePropertyMissionObj, -1 }, @@ -55,7 +50,6 @@ namespace Prop { IVariable::DT_SEQUENCE_ID, "SequenceId", ePropertySequenceId, -1 }, { IVariable::DT_LIGHT_ANIMATION, "LightAnimation", ePropertyLightAnimation, -1 }, { IVariable::DT_PARTICLE_EFFECT, "ParticleEffect", ePropertyParticleName, 3 }, - { IVariable::DT_GEOM_CACHE, "Geometry Cache", ePropertyGeomCache, 5 }, { IVariable::DT_AUDIO_TRIGGER, "Audio Trigger", ePropertyAudioTrigger, 6 }, { IVariable::DT_AUDIO_SWITCH, "Audio Switch", ePropertyAudioSwitch, 6 }, { IVariable::DT_AUDIO_SWITCH_STATE, "Audio Switch", ePropertyAudioSwitchState, 6 }, @@ -301,31 +295,4 @@ namespace Prop return -1; } - - const char* GetPropertyTypeToResourceType(PropertyType type) - { - // The strings below are names used together with - // REGISTER_RESOURCE_SELECTOR. See IResourceSelector.h. - switch (type) - { - case ePropertyModel: - return "Model"; - case ePropertyGeomCache: - return "GeomCache"; - case ePropertyAudioTrigger: - return "AudioTrigger"; - case ePropertyAudioSwitch: - return "AudioSwitch"; - case ePropertyAudioSwitchState: - return "AudioSwitchState"; - case ePropertyAudioRTPC: - return "AudioRTPC"; - case ePropertyAudioEnvironment: - return "AudioEnvironment"; - case ePropertyAudioPreloadRequest: - return "AudioPreloadRequest"; - default: - return nullptr; - } - } } diff --git a/Code/Editor/Util/VariablePropertyType.h b/Code/Editor/Util/VariablePropertyType.h index af2865add1..decb930cb3 100644 --- a/Code/Editor/Util/VariablePropertyType.h +++ b/Code/Editor/Util/VariablePropertyType.h @@ -28,16 +28,11 @@ enum PropertyType ePropertyAngle, ePropertyFloatCurve, ePropertyColorCurve, - ePropertyFile, ePropertyTexture, - ePropertyAnimation, - ePropertyModel, ePropertySelection, ePropertyList, ePropertyShader, - ePropertyDeprecated2, // formerly ePropertyMaterial ePropertyEquip, - ePropertyReverbPreset, ePropertyLocalString, ePropertyDeprecated0, // formerly ePropertyCustomAction ePropertyGameToken, @@ -48,7 +43,6 @@ enum PropertyType ePropertyLightAnimation, ePropertyDeprecated1, // formerly ePropertyFlare ePropertyParticleName, - ePropertyGeomCache, ePropertyAudioTrigger, ePropertyAudioSwitch, ePropertyAudioSwitchState, diff --git a/Code/Editor/editor_lib_files.cmake b/Code/Editor/editor_lib_files.cmake index 4b80a5d461..c10db3bac5 100644 --- a/Code/Editor/editor_lib_files.cmake +++ b/Code/Editor/editor_lib_files.cmake @@ -289,7 +289,6 @@ set(FILES Include/IPlugin.h Include/IPreferencesPage.h Include/IRenderListener.h - Include/IResourceSelectorHost.h Include/ISourceControl.h Include/ISubObjectSelectionReferenceFrameCalculator.h Include/ITextureDatabaseUpdater.h @@ -360,8 +359,6 @@ set(FILES Controls/TimelineCtrl.cpp Controls/TimelineCtrl.h Controls/WndGridHelper.h - Controls/ReflectedPropertyControl/PropertyAnimationCtrl.cpp - Controls/ReflectedPropertyControl/PropertyAnimationCtrl.h Controls/ReflectedPropertyControl/PropertyGenericCtrl.cpp Controls/ReflectedPropertyControl/PropertyGenericCtrl.h Controls/ReflectedPropertyControl/PropertyMiscCtrl.cpp @@ -372,8 +369,6 @@ set(FILES Controls/ReflectedPropertyControl/PropertyResourceCtrl.h Controls/ReflectedPropertyControl/PropertyCtrl.cpp Controls/ReflectedPropertyControl/PropertyCtrl.h - Controls/ReflectedPropertyControl/ReflectedPropertiesPanel.cpp - Controls/ReflectedPropertyControl/ReflectedPropertiesPanel.h MainStatusBar.cpp MainStatusBar.h MainStatusBarItems.h @@ -590,8 +585,6 @@ set(FILES FBXExporterDialog.ui FileTypeUtils.cpp LightmapCompiler/SimpleTriangleRasterizer.cpp - ResourceSelectorHost.cpp - ResourceSelectorHost.h ToolBox.cpp TrackViewNewSequenceDialog.cpp TrackViewNewSequenceDialog.ui @@ -668,7 +661,6 @@ set(FILES TrackView/2DBezierKeyUIControls.cpp TrackView/AssetBlendKeyUIControls.cpp TrackView/CaptureKeyUIControls.cpp - TrackView/CharacterKeyUIControls.cpp TrackView/ConsoleKeyUIControls.cpp TrackView/EventKeyUIControls.cpp TrackView/GotoKeyUIControls.cpp diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/API/ToolsApplicationAPI.h b/Code/Framework/AzToolsFramework/AzToolsFramework/API/ToolsApplicationAPI.h index f6046b9f25..9e5db5b5b7 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/API/ToolsApplicationAPI.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/API/ToolsApplicationAPI.h @@ -841,9 +841,6 @@ namespace AzToolsFramework */ virtual AZStd::string GetComponentIconPath(const AZ::Uuid& /*componentType*/, AZ::Crc32 /*componentIconAttrib*/, AZ::Component* /*component*/) { return AZStd::string(); } - /// Resource Selector hook, returns a path for a resource. - virtual AZStd::string SelectResource(const AZStd::string& /*resourceType*/, const AZStd::string& /*previousValue*/) { return AZStd::string(); } - /** * Calculate the navigation 2D radius in units of an agent given its Navigation Type Name * @param angentTypeName the name that identifies the agent navigation type diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAudioCtrl.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAudioCtrl.cpp index 6951d7ae8c..274db35da2 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAudioCtrl.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAudioCtrl.cpp @@ -7,8 +7,8 @@ */ -#include "PropertyAudioCtrl.h" -#include "PropertyQTConstants.h" +#include +#include #include #include @@ -34,7 +34,7 @@ namespace AzToolsFramework : QWidget(parent) , m_browseEdit(nullptr) , m_mainLayout(nullptr) - , m_propertyType(AudioPropertyType::Invalid) + , m_propertyType(AudioPropertyType::NumTypes) { // create the gui m_mainLayout = new QHBoxLayout(); @@ -96,7 +96,7 @@ namespace AzToolsFramework return; } - if (type != AudioPropertyType::Invalid) + if (type != AudioPropertyType::NumTypes) { m_propertyType = type; } @@ -136,10 +136,11 @@ namespace AzToolsFramework void AudioControlSelectorWidget::OnOpenAudioControlSelector() { - AZStd::string resourceResult; - AZStd::string resourceType(GetResourceSelectorNameFromType(m_propertyType)); AZStd::string currentValue(m_controlName.toStdString().c_str()); - EditorRequests::Bus::BroadcastResult(resourceResult, &EditorRequests::Bus::Events::SelectResource, resourceType, currentValue); + AZStd::string resourceResult; + AudioControlSelectorRequestBus::EventResult( + resourceResult, m_propertyType, + &AudioControlSelectorRequestBus::Events::SelectResource, currentValue); SetControlName(QString(resourceResult.c_str())); } @@ -167,12 +168,12 @@ namespace AzToolsFramework { case AudioPropertyType::Trigger: return { "AudioTrigger" }; + case AudioPropertyType::Rtpc: + return { "AudioRTPC" }; case AudioPropertyType::Switch: return { "AudioSwitch" }; case AudioPropertyType::SwitchState: return { "AudioSwitchState" }; - case AudioPropertyType::Rtpc: - return { "AudioRTPC" }; case AudioPropertyType::Environment: return { "AudioEnvironment" }; case AudioPropertyType::Preload: diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAudioCtrl.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAudioCtrl.h index 4996806a8d..dbc45a592d 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAudioCtrl.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAudioCtrl.h @@ -29,6 +29,27 @@ class QMimeData; namespace AzToolsFramework { + //============================================================================= + // Audio Control Selector Request Bus + // For connecting UI proper + //============================================================================= + class AudioControlSelectorRequests + : public AZ::EBusTraits + { + public: + // EBusTraits + static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById; + static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single; + using BusIdType = AudioPropertyType; + + virtual AZStd::string SelectResource(AZStd::string_view previousValue) + { + return previousValue; + } + }; + + using AudioControlSelectorRequestBus = AZ::EBus; + //============================================================================= // Audio Control Selector Widget //============================================================================= diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAudioCtrlTypes.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAudioCtrlTypes.h index df31e297cd..c23e082a44 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAudioCtrlTypes.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAudioCtrlTypes.h @@ -18,15 +18,15 @@ namespace AzToolsFramework { //========================================================================= - enum class AudioPropertyType + enum class AudioPropertyType : AZ::u32 { - Invalid = 0, - Trigger, + Trigger = 0, + Rtpc, Switch, SwitchState, - Rtpc, Environment, Preload, + NumTypes, }; //========================================================================= @@ -40,7 +40,7 @@ namespace AzToolsFramework virtual ~CReflectedVarAudioControl() = default; AZStd::string m_controlName; - AudioPropertyType m_propertyType = AudioPropertyType::Invalid; + AudioPropertyType m_propertyType = AudioPropertyType::NumTypes; static void Reflect(AZ::ReflectContext* context) { diff --git a/Gems/AudioSystem/Code/Source/Editor/ATLControlsResourceDialog.cpp b/Gems/AudioSystem/Code/Source/Editor/ATLControlsResourceDialog.cpp index 46941baf17..d3121f6245 100644 --- a/Gems/AudioSystem/Code/Source/Editor/ATLControlsResourceDialog.cpp +++ b/Gems/AudioSystem/Code/Source/Editor/ATLControlsResourceDialog.cpp @@ -30,6 +30,8 @@ namespace AudioControls : QDialog(pParent) , m_eType(eType) { + AZ_Assert(CAudioControlsEditorPlugin::GetATLModel() != nullptr, "ATLControlsDialog - ATL Model is null!"); + setWindowTitle(GetWindowTitle(m_eType)); setWindowModality(Qt::ApplicationModal); diff --git a/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorPlugin.cpp b/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorPlugin.cpp index 2b7023df61..f3d5a03ffc 100644 --- a/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorPlugin.cpp +++ b/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorPlugin.cpp @@ -14,8 +14,6 @@ #include #include -#include - #include #include #include @@ -41,7 +39,6 @@ CAudioControlsEditorPlugin::CAudioControlsEditorPlugin(IEditor* editor) QtViewOptions options; options.canHaveMultipleInstances = true; RegisterQtViewPane(editor, LyViewPane::AudioControlsEditor, LyViewPane::CategoryOther, options); - RegisterAudioControlsResourceSelectors(); Audio::AudioSystemRequestBus::BroadcastResult(ms_pIAudioProxy, &Audio::AudioSystemRequestBus::Events::GetFreeAudioProxy); diff --git a/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorPlugin.h b/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorPlugin.h index 4e5c528901..f8288a5d7f 100644 --- a/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorPlugin.h +++ b/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorPlugin.h @@ -13,6 +13,7 @@ #include #include +#include #include #include #include @@ -68,6 +69,7 @@ private: static AudioControls::FilepathSet ms_currentFilenames; static Audio::IAudioProxy* ms_pIAudioProxy; static Audio::TAudioControlID ms_nAudioTriggerID; - static CImplementationManager ms_implementationManager; + + AudioControls::AudioControlSelectorHandler m_controlSelector; }; diff --git a/Gems/AudioSystem/Code/Source/Editor/AudioResourceSelectors.cpp b/Gems/AudioSystem/Code/Source/Editor/AudioResourceSelectors.cpp index 74233be2e9..a6ab3878b8 100644 --- a/Gems/AudioSystem/Code/Source/Editor/AudioResourceSelectors.cpp +++ b/Gems/AudioSystem/Code/Source/Editor/AudioResourceSelectors.cpp @@ -10,88 +10,45 @@ #include #include #include -#include -#include #include +#include + namespace AudioControls { //-------------------------------------------------------------------------------------------// - QString ShowSelectDialog(const SResourceSelectorContext& context, const QString& pPreviousValue, const EACEControlType controlType) + AudioControlSelectorHandler::AudioControlSelectorHandler() { - AZ_Assert(CAudioControlsEditorPlugin::GetATLModel() != nullptr, "AudioResourceSelectors - ATL Model is null!"); - - AZStd::string levelName; - AzToolsFramework::EditorRequestBus::BroadcastResult(levelName, &AzToolsFramework::EditorRequests::GetLevelName); - - ATLControlsDialog dialog(context.parentWidget, controlType); - dialog.SetScope(levelName); - return dialog.ChooseItem(pPreviousValue.toUtf8().constData()); - } - - //-------------------------------------------------------------------------------------------// - QString AudioTriggerSelector(const SResourceSelectorContext& context, const QString& pPreviousValue) - { - return ShowSelectDialog(context, pPreviousValue, eACET_TRIGGER); - } - - //-------------------------------------------------------------------------------------------// - QString AudioSwitchSelector(const SResourceSelectorContext& context, const QString& pPreviousValue) - { - return ShowSelectDialog(context, pPreviousValue, eACET_SWITCH); - } - - //-------------------------------------------------------------------------------------------// - QString AudioSwitchStateSelector(const SResourceSelectorContext& context, const QString& pPreviousValue) - { - return ShowSelectDialog(context, pPreviousValue, eACET_SWITCH_STATE); - } - - //-------------------------------------------------------------------------------------------// - QString AudioRTPCSelector(const SResourceSelectorContext& context, const QString& pPreviousValue) - { - return ShowSelectDialog(context, pPreviousValue, eACET_RTPC); - } - - //-------------------------------------------------------------------------------------------// - QString AudioEnvironmentSelector(const SResourceSelectorContext& context, const QString& pPreviousValue) - { - return ShowSelectDialog(context, pPreviousValue, eACET_ENVIRONMENT); - } - - //-------------------------------------------------------------------------------------------// - QString AudioPreloadRequestSelector(const SResourceSelectorContext& context, const QString& pPreviousValue) - { - return ShowSelectDialog(context, pPreviousValue, eACET_PRELOAD); - } - - //-------------------------------------------------------------------------------------------// - static SStaticResourceSelectorEntry audioTriggerSelector( - "AudioTrigger", AudioTriggerSelector, ":/Icons/Trigger_Icon.svg"); - static SStaticResourceSelectorEntry audioSwitchSelector( - "AudioSwitch", AudioSwitchSelector, ":/Icons/Switch_Icon.svg"); - static SStaticResourceSelectorEntry audioStateSelector( - "AudioSwitchState", AudioSwitchStateSelector, ":/Icons/Property_Icon.png"); - static SStaticResourceSelectorEntry audioRtpcSelector( - "AudioRTPC", AudioRTPCSelector, ":/Icons/RTPC_Icon.svg"); - static SStaticResourceSelectorEntry audioEnvironmentSelector( - "AudioEnvironment", AudioEnvironmentSelector, ":/Icons/Environment_Icon.svg"); - static SStaticResourceSelectorEntry audioPreloadSelector( - "AudioPreloadRequest", AudioPreloadRequestSelector, ":/Icons/Bank_Icon.png"); - - //-------------------------------------------------------------------------------------------// - void RegisterAudioControlsResourceSelectors() - { - if (IResourceSelectorHost* host = GetIEditor()->GetResourceSelectorHost(); - host != nullptr) + for (AZ::u32 type = 0; type < static_cast(AzToolsFramework::AudioPropertyType::NumTypes); ++type) { - host->RegisterResourceSelector(&audioTriggerSelector); - host->RegisterResourceSelector(&audioSwitchSelector); - host->RegisterResourceSelector(&audioStateSelector); - host->RegisterResourceSelector(&audioRtpcSelector); - host->RegisterResourceSelector(&audioEnvironmentSelector); - host->RegisterResourceSelector(&audioPreloadSelector); + AzToolsFramework::AudioControlSelectorRequestBus::MultiHandler::BusConnect( + static_cast(type)); } } + AudioControlSelectorHandler::~AudioControlSelectorHandler() + { + AzToolsFramework::AudioControlSelectorRequestBus::MultiHandler::BusDisconnect(); + } + + AZStd::string AudioControlSelectorHandler::SelectResource(AZStd::string_view previousValue) + { + using namespace AzToolsFramework; + if (auto busId = AudioControlSelectorRequestBus::GetCurrentBusId(); + busId != nullptr) + { + auto controlType = static_cast(*busId); + QWidget* parentWidget = nullptr; + AzToolsFramework::EditorRequestBus::BroadcastResult(parentWidget, &AzToolsFramework::EditorRequestBus::Events::GetMainWindow); + + AZStd::string levelName; + AzToolsFramework::EditorRequestBus::BroadcastResult(levelName, &AzToolsFramework::EditorRequests::GetLevelName); + + ATLControlsDialog dialog(parentWidget, controlType); + dialog.SetScope(levelName); + return dialog.ChooseItem(previousValue.data()); + } + return previousValue; + } + } // namespace AudioControls diff --git a/Gems/AudioSystem/Code/Source/Editor/AudioResourceSelectors.h b/Gems/AudioSystem/Code/Source/Editor/AudioResourceSelectors.h index d2bff7c799..127cfb15b4 100644 --- a/Gems/AudioSystem/Code/Source/Editor/AudioResourceSelectors.h +++ b/Gems/AudioSystem/Code/Source/Editor/AudioResourceSelectors.h @@ -8,7 +8,16 @@ #pragma once +#include + namespace AudioControls { - void RegisterAudioControlsResourceSelectors(); + class AudioControlSelectorHandler + : public AzToolsFramework::AudioControlSelectorRequestBus::MultiHandler + { + public: + AudioControlSelectorHandler(); + ~AudioControlSelectorHandler(); + AZStd::string SelectResource(AZStd::string_view previousValue) override; + }; } From 88bef1074bc20ac4e8dd543af1bc7f345bddfd5f Mon Sep 17 00:00:00 2001 From: Chris Galvan Date: Mon, 16 Aug 2021 15:43:01 -0500 Subject: [PATCH 398/803] Replaced some Lumberyard references with O3DE. Signed-off-by: Chris Galvan --- .../Gem/PythonTests/EditorPythonTestTools/README.txt | 4 ++-- .../PythonTests/editor/EditorScripts/AssetPicker_UI_UX.py | 2 +- .../BasicEditorWorkflows_LevelEntityComponentCRUD.py | 4 ++-- .../editor/EditorScripts/Menus_EditMenuOptions.py | 2 +- .../editor/EditorScripts/Menus_FileMenuOptions.py | 2 +- .../editor/EditorScripts/Menus_ViewMenuOptions.py | 2 +- .../scripting/Pane_PropertiesChanged_RetainsOnRestart.py | 2 +- .../Gem/PythonTests/smoke/Editor_NewExistingLevels_Works.py | 2 +- Gems/QtForPython/Editor/Scripts/tests/log_main_window.py | 2 +- .../Include/ScriptCanvas/Libraries/Entity/EntityNodes.h | 6 +++--- .../Include/ScriptCanvas/Libraries/Math/TransformNodes.h | 6 +++--- 11 files changed, 17 insertions(+), 17 deletions(-) diff --git a/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/README.txt b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/README.txt index 0405dacbf4..90afee39bc 100644 --- a/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/README.txt +++ b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/README.txt @@ -8,7 +8,7 @@ INTRODUCTION ------------ EditorPythonBindings is a Python project that contains a collection of editor testing tools -developed by the Lumberyard feature teams. The project contains tools for system level +developed by the O3DE feature teams. The project contains tools for system level editor tests. @@ -23,7 +23,7 @@ installed on your system. INSTALL ----------- -It is recommended to set up these these tools with Lumberyard's CMake build commands. +It is recommended to set up these these tools with O3DE's CMake build commands. Assuming CMake is already setup on your operating system, below are some sample build commands: cd /path/to/od3e/ mkdir windows_vs2019 diff --git a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/AssetPicker_UI_UX.py b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/AssetPicker_UI_UX.py index f728714125..068f25fb1e 100644 --- a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/AssetPicker_UI_UX.py +++ b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/AssetPicker_UI_UX.py @@ -61,7 +61,7 @@ class AssetPickerUIUXTest(EditorTestHelper): 5) Verify if Mesh Asset is assigned via both OK/Enter options Note: - - This test file must be called from the Lumberyard Editor command terminal + - This test file must be called from the O3DE Editor command terminal - Any passed and failed tests are written to the Editor.log file. Parsing the file or running a log_monitor are required to observe the test results. diff --git a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/BasicEditorWorkflows_LevelEntityComponentCRUD.py b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/BasicEditorWorkflows_LevelEntityComponentCRUD.py index 32d20ea2b4..994fc661ed 100644 --- a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/BasicEditorWorkflows_LevelEntityComponentCRUD.py +++ b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/BasicEditorWorkflows_LevelEntityComponentCRUD.py @@ -37,7 +37,7 @@ class TestBasicEditorWorkflows(EditorTestHelper): async def run_test(self): """ Summary: - Open Lumberyard editor and check if basic Editor workflows are completable. + Open O3DE editor and check if basic Editor workflows are completable. Expected Behavior: - A new level can be created @@ -48,7 +48,7 @@ class TestBasicEditorWorkflows(EditorTestHelper): - Level can be exported Note: - - This test file must be called from the Lumberyard Editor command terminal + - This test file must be called from the O3DE Editor command terminal - Any passed and failed tests are written to the Editor.log file. Parsing the file or running a log_monitor are required to observe the test results. diff --git a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/Menus_EditMenuOptions.py b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/Menus_EditMenuOptions.py index 6b861894c0..53a8da4116 100644 --- a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/Menus_EditMenuOptions.py +++ b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/Menus_EditMenuOptions.py @@ -36,7 +36,7 @@ class TestEditMenuOptions(EditorTestHelper): 2) Interact with Edit Menu options Note: - - This test file must be called from the Lumberyard Editor command terminal + - This test file must be called from the O3DE Editor command terminal - Any passed and failed tests are written to the Editor.log file. Parsing the file or running a log_monitor are required to observe the test results. diff --git a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/Menus_FileMenuOptions.py b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/Menus_FileMenuOptions.py index ab9aa1d326..77ee9ac61d 100644 --- a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/Menus_FileMenuOptions.py +++ b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/Menus_FileMenuOptions.py @@ -32,7 +32,7 @@ class TestFileMenuOptions(EditorTestHelper): 2) Interact with File Menu options Note: - - This test file must be called from the Lumberyard Editor command terminal + - This test file must be called from the O3DE Editor command terminal - Any passed and failed tests are written to the Editor.log file. Parsing the file or running a log_monitor are required to observe the test results. diff --git a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/Menus_ViewMenuOptions.py b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/Menus_ViewMenuOptions.py index d1233e9815..d2db4210ce 100644 --- a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/Menus_ViewMenuOptions.py +++ b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/Menus_ViewMenuOptions.py @@ -36,7 +36,7 @@ class TestViewMenuOptions(EditorTestHelper): 2) Interact with View Menu options Note: - - This test file must be called from the Lumberyard Editor command terminal + - This test file must be called from the O3DE Editor command terminal - Any passed and failed tests are written to the Editor.log file. Parsing the file or running a log_monitor are required to observe the test results. diff --git a/AutomatedTesting/Gem/PythonTests/scripting/Pane_PropertiesChanged_RetainsOnRestart.py b/AutomatedTesting/Gem/PythonTests/scripting/Pane_PropertiesChanged_RetainsOnRestart.py index 5c74754449..338389b1c4 100644 --- a/AutomatedTesting/Gem/PythonTests/scripting/Pane_PropertiesChanged_RetainsOnRestart.py +++ b/AutomatedTesting/Gem/PythonTests/scripting/Pane_PropertiesChanged_RetainsOnRestart.py @@ -52,7 +52,7 @@ def Pane_PropertiesChanged_RetainsOnRestart(): from utils import TestHelper as helper import pyside_utils - # Lumberyard Imports + # O3DE Imports import azlmbr.legacy.general as general # Pyside imports diff --git a/AutomatedTesting/Gem/PythonTests/smoke/Editor_NewExistingLevels_Works.py b/AutomatedTesting/Gem/PythonTests/smoke/Editor_NewExistingLevels_Works.py index 9a54de856c..71956488fc 100644 --- a/AutomatedTesting/Gem/PythonTests/smoke/Editor_NewExistingLevels_Works.py +++ b/AutomatedTesting/Gem/PythonTests/smoke/Editor_NewExistingLevels_Works.py @@ -53,7 +53,7 @@ def Editor_NewExistingLevels_Works(): 10) Save, Load and Export an existing level and close editor Note: - - This test file must be called from the Lumberyard Editor command terminal + - This test file must be called from the O3DE Editor command terminal - Any passed and failed tests are written to the Editor.log file. Parsing the file or running a log_monitor are required to observe the test results. diff --git a/Gems/QtForPython/Editor/Scripts/tests/log_main_window.py b/Gems/QtForPython/Editor/Scripts/tests/log_main_window.py index 528e869d8c..6971731cb0 100755 --- a/Gems/QtForPython/Editor/Scripts/tests/log_main_window.py +++ b/Gems/QtForPython/Editor/Scripts/tests/log_main_window.py @@ -5,7 +5,7 @@ For complete copyright and license terms please see the LICENSE at the root of t SPDX-License-Identifier: Apache-2.0 OR MIT """ -# bit more complex example set to demo connecting Lumberyard tech to PySide2 widgets +# bit more complex example set to demo connecting O3DE tech to PySide2 widgets import azlmbr.bus from PySide2 import QtWidgets from PySide2 import QtGui diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Entity/EntityNodes.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Entity/EntityNodes.h index 701c3a0869..191635757c 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Entity/EntityNodes.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Entity/EntityNodes.h @@ -35,7 +35,7 @@ namespace ScriptCanvas vector.SetLength(aznumeric_cast(scale)); return vector; } - SCRIPT_CANVAS_GENERIC_FUNCTION_NODE_WITH_DEFAULTS(GetEntityRight, DefaultScale<1>, k_categoryName, "{C12282BE-29D2-497D-8C22-75B940E254E2}", "returns the right direction vector from the specified entity's world transform, scaled by a given value (Lumberyard uses Z up, right handed)", "EntityId", "Scale"); + SCRIPT_CANVAS_GENERIC_FUNCTION_NODE_WITH_DEFAULTS(GetEntityRight, DefaultScale<1>, k_categoryName, "{C12282BE-29D2-497D-8C22-75B940E254E2}", "returns the right direction vector from the specified entity's world transform, scaled by a given value (O3DE uses Z up, right handed)", "EntityId", "Scale"); AZ_INLINE Vector3Type GetEntityForward(AZ::EntityId entityId, NumberType scale) { @@ -46,7 +46,7 @@ namespace ScriptCanvas vector.SetLength(aznumeric_cast(scale)); return vector; } - SCRIPT_CANVAS_GENERIC_FUNCTION_NODE_WITH_DEFAULTS(GetEntityForward, DefaultScale<1>, k_categoryName, "{719D9F76-84D4-4B0F-BCEB-26D5D097C7D6}", "returns the forward direction vector from the specified entity' world transform, scaled by a given value (Lumberyard uses Z up, right handed)", "EntityId", "Scale"); + SCRIPT_CANVAS_GENERIC_FUNCTION_NODE_WITH_DEFAULTS(GetEntityForward, DefaultScale<1>, k_categoryName, "{719D9F76-84D4-4B0F-BCEB-26D5D097C7D6}", "returns the forward direction vector from the specified entity' world transform, scaled by a given value (O3DE uses Z up, right handed)", "EntityId", "Scale"); AZ_INLINE Vector3Type GetEntityUp(AZ::EntityId entityId, NumberType scale) { @@ -57,7 +57,7 @@ namespace ScriptCanvas vector.SetLength(aznumeric_cast(scale)); return vector; } - SCRIPT_CANVAS_GENERIC_FUNCTION_NODE_WITH_DEFAULTS(GetEntityUp, DefaultScale<1>, k_categoryName, "{96B86F3F-F022-4611-9AEA-175EA952C562}", "returns the up direction vector from the specified entity's world transform, scaled by a given value (Lumberyard uses Z up, right handed)", "EntityId", "Scale"); + SCRIPT_CANVAS_GENERIC_FUNCTION_NODE_WITH_DEFAULTS(GetEntityUp, DefaultScale<1>, k_categoryName, "{96B86F3F-F022-4611-9AEA-175EA952C562}", "returns the up direction vector from the specified entity's world transform, scaled by a given value (O3DE uses Z up, right handed)", "EntityId", "Scale"); AZ_INLINE BooleanType IsActive(const EntityIDType& entityId) { diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Math/TransformNodes.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Math/TransformNodes.h index ddbe5ac5f7..f2088dbf6d 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Math/TransformNodes.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Math/TransformNodes.h @@ -74,7 +74,7 @@ namespace ScriptCanvas vector.SetLength(aznumeric_cast(scale)); return vector; } - SCRIPT_CANVAS_GENERIC_FUNCTION_NODE_WITH_DEFAULTS(GetRight, DefaultScale<1>, k_categoryName, "{65811752-711F-4566-869E-5AEF53206342}", "returns the right direction vector from the specified transform scaled by a given value (Lumberyard uses Z up, right handed)", "Source", "Scale"); + SCRIPT_CANVAS_GENERIC_FUNCTION_NODE_WITH_DEFAULTS(GetRight, DefaultScale<1>, k_categoryName, "{65811752-711F-4566-869E-5AEF53206342}", "returns the right direction vector from the specified transform scaled by a given value (O3DE uses Z up, right handed)", "Source", "Scale"); AZ_INLINE Vector3Type GetForward(const TransformType& source, NumberType scale) { @@ -82,7 +82,7 @@ namespace ScriptCanvas vector.SetLength(aznumeric_cast(scale)); return vector; } - SCRIPT_CANVAS_GENERIC_FUNCTION_NODE_WITH_DEFAULTS(GetForward, DefaultScale<1>, k_categoryName, "{3602a047-9f12-46d4-9648-8f53770c8130}", "returns the forward direction vector from the specified transform scaled by a given value (Lumberyard uses Z up, right handed)", "Source", "Scale"); + SCRIPT_CANVAS_GENERIC_FUNCTION_NODE_WITH_DEFAULTS(GetForward, DefaultScale<1>, k_categoryName, "{3602a047-9f12-46d4-9648-8f53770c8130}", "returns the forward direction vector from the specified transform scaled by a given value (O3DE uses Z up, right handed)", "Source", "Scale"); AZ_INLINE Vector3Type GetUp(const TransformType& source, NumberType scale) { @@ -90,7 +90,7 @@ namespace ScriptCanvas vector.SetLength(aznumeric_cast(scale)); return vector; } - SCRIPT_CANVAS_GENERIC_FUNCTION_NODE_WITH_DEFAULTS(GetUp, DefaultScale<1>, k_categoryName, "{F10F52D2-E6F2-4E39-84D5-B4A561F186D3}", "returns the up direction vector from the specified transform scaled by a given value (Lumberyard uses Z up, right handed)", "Source", "Scale"); + SCRIPT_CANVAS_GENERIC_FUNCTION_NODE_WITH_DEFAULTS(GetUp, DefaultScale<1>, k_categoryName, "{F10F52D2-E6F2-4E39-84D5-B4A561F186D3}", "returns the up direction vector from the specified transform scaled by a given value (O3DE uses Z up, right handed)", "Source", "Scale"); AZ_INLINE Vector3Type GetTranslation(const TransformType& source) { From a461a82030e5aa7f77e0a8337b61d7f8abfc3885 Mon Sep 17 00:00:00 2001 From: mgwynn Date: Mon, 16 Aug 2021 18:13:35 -0400 Subject: [PATCH 399/803] Remove non-existant files from icon contents.json files (#3148) Signed-off-by: mgwynn --- .../AppIcon.appiconset/Contents.json | 32 +------------ .../Contents.json | 32 +------------ .../LaunchImage.launchimage/Contents.json | 47 +------------------ 3 files changed, 3 insertions(+), 108 deletions(-) diff --git a/AutomatedTesting/Gem/Resources/IOSLauncher/Images.xcassets/AppIcon.appiconset/Contents.json b/AutomatedTesting/Gem/Resources/IOSLauncher/Images.xcassets/AppIcon.appiconset/Contents.json index 09621469c3..94e3dcd84d 100644 --- a/AutomatedTesting/Gem/Resources/IOSLauncher/Images.xcassets/AppIcon.appiconset/Contents.json +++ b/AutomatedTesting/Gem/Resources/IOSLauncher/Images.xcassets/AppIcon.appiconset/Contents.json @@ -1,17 +1,5 @@ { "images" : [ - { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "iPhoneNotificationIcon40x40.png", - "scale" : "2x" - }, - { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "iPhoneNotificationIcon60x60.png", - "scale" : "3x" - }, { "size" : "29x29", "idiom" : "iphone", @@ -48,18 +36,6 @@ "filename" : "iPhoneAppIcon180x180.png", "scale" : "3x" }, - { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "iPadNotificationIcon20x20.png", - "scale" : "1x" - }, - { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "iPadNotificationIcon40x40.png", - "scale" : "2x" - }, { "size" : "29x29", "idiom" : "ipad", @@ -101,16 +77,10 @@ "idiom" : "ipad", "filename" : "iPadProAppIcon167x167.png", "scale" : "2x" - }, - { - "size" : "1024x1024", - "idiom" : "ios-marketing", - "filename" : "iOSAppStoreIcon1024x1024.png", - "scale" : "1x" } ], "info" : { "version" : 1, "author" : "xcode" } -} \ No newline at end of file +} diff --git a/AutomatedTesting/Gem/Resources/IOSLauncher/Images.xcassets/AutomatedTestingAppIcon.appiconset/Contents.json b/AutomatedTesting/Gem/Resources/IOSLauncher/Images.xcassets/AutomatedTestingAppIcon.appiconset/Contents.json index 09621469c3..94e3dcd84d 100644 --- a/AutomatedTesting/Gem/Resources/IOSLauncher/Images.xcassets/AutomatedTestingAppIcon.appiconset/Contents.json +++ b/AutomatedTesting/Gem/Resources/IOSLauncher/Images.xcassets/AutomatedTestingAppIcon.appiconset/Contents.json @@ -1,17 +1,5 @@ { "images" : [ - { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "iPhoneNotificationIcon40x40.png", - "scale" : "2x" - }, - { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "iPhoneNotificationIcon60x60.png", - "scale" : "3x" - }, { "size" : "29x29", "idiom" : "iphone", @@ -48,18 +36,6 @@ "filename" : "iPhoneAppIcon180x180.png", "scale" : "3x" }, - { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "iPadNotificationIcon20x20.png", - "scale" : "1x" - }, - { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "iPadNotificationIcon40x40.png", - "scale" : "2x" - }, { "size" : "29x29", "idiom" : "ipad", @@ -101,16 +77,10 @@ "idiom" : "ipad", "filename" : "iPadProAppIcon167x167.png", "scale" : "2x" - }, - { - "size" : "1024x1024", - "idiom" : "ios-marketing", - "filename" : "iOSAppStoreIcon1024x1024.png", - "scale" : "1x" } ], "info" : { "version" : 1, "author" : "xcode" } -} \ No newline at end of file +} diff --git a/AutomatedTesting/Gem/Resources/IOSLauncher/Images.xcassets/LaunchImage.launchimage/Contents.json b/AutomatedTesting/Gem/Resources/IOSLauncher/Images.xcassets/LaunchImage.launchimage/Contents.json index f836f07ee7..67b253d091 100644 --- a/AutomatedTesting/Gem/Resources/IOSLauncher/Images.xcassets/LaunchImage.launchimage/Contents.json +++ b/AutomatedTesting/Gem/Resources/IOSLauncher/Images.xcassets/LaunchImage.launchimage/Contents.json @@ -1,50 +1,5 @@ { "images" : [ - { - "extent" : "full-screen", - "idiom" : "iphone", - "subtype" : "2436h", - "filename" : "iPhoneLaunchImage1125x2436.png", - "minimum-system-version" : "11.0", - "orientation" : "portrait", - "scale" : "3x" - }, - { - "extent" : "full-screen", - "idiom" : "iphone", - "subtype" : "2436h", - "filename" : "iPhoneLaunchImage2436x1125.png", - "minimum-system-version" : "11.0", - "orientation" : "landscape", - "scale" : "3x" - }, - { - "extent" : "full-screen", - "idiom" : "iphone", - "subtype" : "736h", - "filename" : "iPhoneLaunchImage1242x2208.png", - "minimum-system-version" : "8.0", - "orientation" : "portrait", - "scale" : "3x" - }, - { - "extent" : "full-screen", - "idiom" : "iphone", - "subtype" : "736h", - "filename" : "iPhoneLaunchImage2208x1242.png", - "minimum-system-version" : "8.0", - "orientation" : "landscape", - "scale" : "3x" - }, - { - "extent" : "full-screen", - "idiom" : "iphone", - "subtype" : "667h", - "filename" : "iPhoneLaunchImage750x1334.png", - "minimum-system-version" : "8.0", - "orientation" : "portrait", - "scale" : "2x" - }, { "orientation" : "portrait", "idiom" : "iphone", @@ -166,4 +121,4 @@ "version" : 1, "author" : "xcode" } -} \ No newline at end of file +} From c67a9f3d12e619abc8e4f919bf424f4cfd409e5c Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Mon, 16 Aug 2021 17:13:43 -0500 Subject: [PATCH 400/803] Updated material component request bus to better support script canvas Change all name parameters to use standard string so that they could be headed in in script canvas nodes and RPE Added explicitly type functions for getting and saving property overrides Signed-off-by: Guthrie Adams --- .../Material/MaterialComponentBus.h | 54 ++++- .../Material/MaterialComponentController.cpp | 187 +++++++++++++++++- .../Material/MaterialComponentController.h | 30 ++- 3 files changed, 254 insertions(+), 17 deletions(-) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Material/MaterialComponentBus.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Material/MaterialComponentBus.h index 234ea99066..01c87fa2fb 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Material/MaterialComponentBus.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Material/MaterialComponentBus.h @@ -41,12 +41,56 @@ namespace AZ virtual const AZ::Data::AssetId GetMaterialOverride(const MaterialAssignmentId& materialAssignmentId) const = 0; //! Clear material override virtual void ClearMaterialOverride(const MaterialAssignmentId& materialAssignmentId) = 0; - //! Set a material property value override - virtual void SetPropertyOverride(const MaterialAssignmentId& materialAssignmentId, const Name& propertyName, const AZStd::any& propertyValue) = 0; - //! Get a material property value override - virtual AZStd::any GetPropertyOverride(const MaterialAssignmentId& materialAssignmentId, const Name& propertyName) const = 0; + //! Set a material property override value wrapped by an AZStd::any + virtual void SetPropertyOverride(const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName, const AZStd::any& value) = 0; + //! Set a material property override value to a bool + virtual void SetPropertyOverrideBool(const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName, const bool& value) = 0; + //! Set a material property override value to a integer + virtual void SetPropertyOverrideInt32(const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName, const int32_t& value) = 0; + //! Set a material property override value to a unsigned integer + virtual void SetPropertyOverrideUInt32(const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName, const uint32_t& value) = 0; + //! Set a material property override value to a float + virtual void SetPropertyOverrideFloat(const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName, const float& value) = 0; + //! Set a material property override value to a Vector2 + virtual void SetPropertyOverrideVector2(const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName, const AZ::Vector2& value) = 0; + //! Set a material property override value to a Vector3 + virtual void SetPropertyOverrideVector3(const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName, const AZ::Vector3& value) = 0; + //! Set a material property override value to a Vector4 + virtual void SetPropertyOverrideVector4(const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName, const AZ::Vector4& value) = 0; + //! Set a material property override value to a color + virtual void SetPropertyOverrideColor(const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName, const AZ::Color& value) = 0; + //! Set a material property override value to an image asset + virtual void SetPropertyOverrideImageAsset(const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName, const AZ::Data::Asset& value) = 0; + //! Set a material property override value to an image instance + virtual void SetPropertyOverrideImageInstance(const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName, const AZ::Data::Instance& value) = 0; + //! Set a material property override value to a string + virtual void SetPropertyOverrideString(const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName, const AZStd::string& value) = 0; + //! Get a material property override value wrapped by an AZStd::any + virtual AZStd::any GetPropertyOverride(const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName) const = 0; + //! Get a material property override value as a bool + virtual bool GetPropertyOverrideBool(const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName) const = 0; + //! Get a material property override value as an integer + virtual int32_t GetPropertyOverrideInt32(const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName) const = 0; + //! Get a material property override value as an unsigned integer + virtual uint32_t GetPropertyOverrideUInt32(const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName) const = 0; + //! Get a material property override value as a float + virtual float GetPropertyOverrideFloat(const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName) const = 0; + //! Get a material property override value as a Vector2 + virtual AZ::Vector2 GetPropertyOverrideVector2(const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName) const = 0; + //! Get a material property override value as a Vector3 + virtual AZ::Vector3 GetPropertyOverrideVector3(const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName) const = 0; + //! Get a material property override value as a Vector4 + virtual AZ::Vector4 GetPropertyOverrideVector4(const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName) const = 0; + //! Get a material property override value as a Color + virtual AZ::Color GetPropertyOverrideColor(const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName) const = 0; + //! Get a material property override value as an image asset + virtual AZ::Data::Asset GetPropertyOverrideImageAsset(const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName) const = 0; + //! Get a material property override value as an image instance + virtual AZ::Data::Instance GetPropertyOverrideImageInstance(const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName) const = 0; + //! Get a material property override value as a string + virtual AZStd::string GetPropertyOverrideString(const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName) const = 0; //! Clear property override for a specific material assignment - virtual void ClearPropertyOverride(const MaterialAssignmentId& materialAssignmentId, const Name& propertyName) = 0; + virtual void ClearPropertyOverride(const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName) = 0; //! Clear property overrides for a specific material assignment virtual void ClearPropertyOverrides(const MaterialAssignmentId& materialAssignmentId) = 0; //! Clear all property overrides diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.cpp index e39f5cfad5..91ac73a209 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.cpp @@ -44,7 +44,29 @@ namespace AZ ->Event("GetMaterialOverride", &MaterialComponentRequestBus::Events::GetMaterialOverride) ->Event("ClearMaterialOverride", &MaterialComponentRequestBus::Events::ClearMaterialOverride) ->Event("SetPropertyOverride", &MaterialComponentRequestBus::Events::SetPropertyOverride) + ->Event("SetPropertyOverrideBool", &MaterialComponentRequestBus::Events::SetPropertyOverrideBool) + ->Event("SetPropertyOverrideInt32", &MaterialComponentRequestBus::Events::SetPropertyOverrideInt32) + ->Event("SetPropertyOverrideUInt32", &MaterialComponentRequestBus::Events::SetPropertyOverrideUInt32) + ->Event("SetPropertyOverrideFloat", &MaterialComponentRequestBus::Events::SetPropertyOverrideFloat) + ->Event("SetPropertyOverrideVector2", &MaterialComponentRequestBus::Events::SetPropertyOverrideVector2) + ->Event("SetPropertyOverrideVector3", &MaterialComponentRequestBus::Events::SetPropertyOverrideVector3) + ->Event("SetPropertyOverrideVector4", &MaterialComponentRequestBus::Events::SetPropertyOverrideVector4) + ->Event("SetPropertyOverrideColor", &MaterialComponentRequestBus::Events::SetPropertyOverrideColor) + ->Event("SetPropertyOverrideImageAsset", &MaterialComponentRequestBus::Events::SetPropertyOverrideImageAsset) + ->Event("SetPropertyOverrideImageInstance", &MaterialComponentRequestBus::Events::SetPropertyOverrideImageInstance) + ->Event("SetPropertyOverrideString", &MaterialComponentRequestBus::Events::SetPropertyOverrideString) ->Event("GetPropertyOverride", &MaterialComponentRequestBus::Events::GetPropertyOverride) + ->Event("GetPropertyOverrideBool", &MaterialComponentRequestBus::Events::GetPropertyOverrideBool) + ->Event("GetPropertyOverrideInt32", &MaterialComponentRequestBus::Events::GetPropertyOverrideInt32) + ->Event("GetPropertyOverrideUInt32", &MaterialComponentRequestBus::Events::GetPropertyOverrideUInt32) + ->Event("GetPropertyOverrideFloat", &MaterialComponentRequestBus::Events::GetPropertyOverrideFloat) + ->Event("GetPropertyOverrideVector2", &MaterialComponentRequestBus::Events::GetPropertyOverrideVector2) + ->Event("GetPropertyOverrideVector3", &MaterialComponentRequestBus::Events::GetPropertyOverrideVector3) + ->Event("GetPropertyOverrideVector4", &MaterialComponentRequestBus::Events::GetPropertyOverrideVector4) + ->Event("GetPropertyOverrideColor", &MaterialComponentRequestBus::Events::GetPropertyOverrideColor) + ->Event("GetPropertyOverrideImageAsset", &MaterialComponentRequestBus::Events::GetPropertyOverrideImageAsset) + ->Event("GetPropertyOverrideImageInstance", &MaterialComponentRequestBus::Events::GetPropertyOverrideImageInstance) + ->Event("GetPropertyOverrideString", &MaterialComponentRequestBus::Events::GetPropertyOverrideString) ->Event("ClearPropertyOverride", &MaterialComponentRequestBus::Events::ClearPropertyOverride) ->Event("ClearPropertyOverrides", &MaterialComponentRequestBus::Events::ClearPropertyOverrides) ->Event("ClearAllPropertyOverrides", &MaterialComponentRequestBus::Events::ClearAllPropertyOverrides) @@ -331,27 +353,97 @@ namespace AZ } } - void MaterialComponentController::SetPropertyOverride(const MaterialAssignmentId& materialAssignmentId, const Name& propertyName, const AZStd::any& propertyValue) + void MaterialComponentController::SetPropertyOverride(const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName, const AZStd::any& value) { auto& materialAssignment = m_configuration.m_materials[materialAssignmentId]; // When applying property overrides for the first time, new instance needs to be created in case the current instance is already used somewhere else to keep overrides local if (materialAssignment.m_propertyOverrides.empty()) { - materialAssignment.m_propertyOverrides[propertyName] = propertyValue; + materialAssignment.m_propertyOverrides[AZ::Name(propertyName)] = value; materialAssignment.RebuildInstance(); QueueMaterialUpdateNotification(); } else { - materialAssignment.m_propertyOverrides[propertyName] = propertyValue; + materialAssignment.m_propertyOverrides[AZ::Name(propertyName)] = value; } QueuePropertyChanges(materialAssignmentId); MaterialComponentNotificationBus::Event(m_entityId, &MaterialComponentNotifications::OnMaterialsEdited, m_configuration.m_materials); } - AZStd::any MaterialComponentController::GetPropertyOverride(const MaterialAssignmentId& materialAssignmentId, const Name& propertyName) const + void MaterialComponentController::SetPropertyOverrideBool( + const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName, const bool& value) + { + SetPropertyOverride(materialAssignmentId, propertyName, AZStd::any(value)); + } + + void MaterialComponentController::SetPropertyOverrideInt32( + const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName, const int32_t& value) + { + SetPropertyOverride(materialAssignmentId, propertyName, AZStd::any(value)); + } + + void MaterialComponentController::SetPropertyOverrideUInt32( + const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName, const uint32_t& value) + { + SetPropertyOverride(materialAssignmentId, propertyName, AZStd::any(value)); + } + + void MaterialComponentController::SetPropertyOverrideFloat( + const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName, const float& value) + { + SetPropertyOverride(materialAssignmentId, propertyName, AZStd::any(value)); + } + + void MaterialComponentController::SetPropertyOverrideVector2( + const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName, const AZ::Vector2& value) + { + SetPropertyOverride(materialAssignmentId, propertyName, AZStd::any(value)); + } + + void MaterialComponentController::SetPropertyOverrideVector3( + const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName, const AZ::Vector3& value) + { + SetPropertyOverride(materialAssignmentId, propertyName, AZStd::any(value)); + } + + void MaterialComponentController::SetPropertyOverrideVector4( + const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName, const AZ::Vector4& value) + { + SetPropertyOverride(materialAssignmentId, propertyName, AZStd::any(value)); + } + + void MaterialComponentController::SetPropertyOverrideColor( + const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName, const AZ::Color& value) + { + SetPropertyOverride(materialAssignmentId, propertyName, AZStd::any(value)); + } + + void MaterialComponentController::SetPropertyOverrideImageAsset( + const MaterialAssignmentId& materialAssignmentId, + const AZStd::string& propertyName, + const AZ::Data::Asset& value) + { + SetPropertyOverride(materialAssignmentId, propertyName, AZStd::any(value)); + } + + void MaterialComponentController::SetPropertyOverrideImageInstance( + const MaterialAssignmentId& materialAssignmentId, + const AZStd::string& propertyName, + const AZ::Data::Instance& value) + { + SetPropertyOverride(materialAssignmentId, propertyName, AZStd::any(value)); + } + + void MaterialComponentController::SetPropertyOverrideString( + const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName, const AZStd::string& value) + { + SetPropertyOverride(materialAssignmentId, propertyName, AZStd::any(value)); + } + + AZStd::any MaterialComponentController::GetPropertyOverride(const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName) const { const auto materialIt = m_configuration.m_materials.find(materialAssignmentId); if (materialIt == m_configuration.m_materials.end()) @@ -360,17 +452,94 @@ namespace AZ return {}; } - const auto propertyIt = materialIt->second.m_propertyOverrides.find(propertyName); + const auto propertyIt = materialIt->second.m_propertyOverrides.find(AZ::Name(propertyName)); if (propertyIt == materialIt->second.m_propertyOverrides.end()) { - AZ_Error("MaterialComponentController", false, "Property not found: %s.", propertyName.GetCStr()); + AZ_Error("MaterialComponentController", false, "Property not found: %s.", propertyName.c_str()); return {}; } return propertyIt->second; } - void MaterialComponentController::ClearPropertyOverride(const MaterialAssignmentId& materialAssignmentId, const Name& propertyName) + bool MaterialComponentController::GetPropertyOverrideBool( + const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName) const + { + const AZStd::any& value = GetPropertyOverride(materialAssignmentId, propertyName); + return !value.empty() && value.is() ? AZStd::any_cast(value) : false; + } + + int32_t MaterialComponentController::GetPropertyOverrideInt32( + const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName) const + { + const AZStd::any& value = GetPropertyOverride(materialAssignmentId, propertyName); + return !value.empty() && value.is() ? AZStd::any_cast(value) : 0; + } + + uint32_t MaterialComponentController::GetPropertyOverrideUInt32( + const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName) const + { + const AZStd::any& value = GetPropertyOverride(materialAssignmentId, propertyName); + return !value.empty() && value.is() ? AZStd::any_cast(value) : 0; + } + + float MaterialComponentController::GetPropertyOverrideFloat( + const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName) const + { + const AZStd::any& value = GetPropertyOverride(materialAssignmentId, propertyName); + return !value.empty() && value.is() ? AZStd::any_cast(value) : 0.0f; + } + + AZ::Vector2 MaterialComponentController::GetPropertyOverrideVector2( + const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName) const + { + const AZStd::any& value = GetPropertyOverride(materialAssignmentId, propertyName); + return !value.empty() && value.is() ? AZStd::any_cast(value) : AZ::Vector2::CreateZero(); + } + + AZ::Vector3 MaterialComponentController::GetPropertyOverrideVector3( + const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName) const + { + const AZStd::any& value = GetPropertyOverride(materialAssignmentId, propertyName); + return !value.empty() && value.is() ? AZStd::any_cast(value) : AZ::Vector3::CreateZero(); + } + + AZ::Vector4 MaterialComponentController::GetPropertyOverrideVector4( + const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName) const + { + const AZStd::any& value = GetPropertyOverride(materialAssignmentId, propertyName); + return !value.empty() && value.is() ? AZStd::any_cast(value) : AZ::Vector4::CreateZero(); + } + + AZ::Color MaterialComponentController::GetPropertyOverrideColor( + const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName) const + { + const AZStd::any& value = GetPropertyOverride(materialAssignmentId, propertyName); + return !value.empty() && value.is() ? AZStd::any_cast(value) : AZ::Color::CreateZero(); + } + + AZ::Data::Asset MaterialComponentController::GetPropertyOverrideImageAsset( + const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName) const + { + const AZStd::any& value = GetPropertyOverride(materialAssignmentId, propertyName); + return !value.empty() && value.is>() ? AZStd::any_cast>(value) : AZ::Data::Asset(); + } + + AZ::Data::Instance MaterialComponentController::GetPropertyOverrideImageInstance( + const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName) const + { + const AZStd::any& value = GetPropertyOverride(materialAssignmentId, propertyName); + return !value.empty() && value.is>() ? AZStd::any_cast>(value) : AZ::Data::Instance(); + } + + AZStd::string MaterialComponentController::GetPropertyOverrideString( + const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName) const + { + const AZStd::any& value = GetPropertyOverride(materialAssignmentId, propertyName); + return !value.empty() && value.is() ? AZStd::any_cast(value) : AZStd::string(); + } + + void MaterialComponentController::ClearPropertyOverride(const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName) { auto materialIt = m_configuration.m_materials.find(materialAssignmentId); if (materialIt == m_configuration.m_materials.end()) @@ -379,10 +548,10 @@ namespace AZ return; } - auto propertyIt = materialIt->second.m_propertyOverrides.find(propertyName); + auto propertyIt = materialIt->second.m_propertyOverrides.find(AZ::Name(propertyName)); if (propertyIt == materialIt->second.m_propertyOverrides.end()) { - AZ_Error("MaterialComponentController", false, "Property not found: %s.", propertyName.GetCStr()); + AZ_Error("MaterialComponentController", false, "Property not found: %s.", propertyName.c_str()); return; } diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.h index de7f991d60..8866493998 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.h @@ -57,9 +57,33 @@ namespace AZ const AZ::Data::AssetId GetMaterialOverride(const MaterialAssignmentId& materialAssignmentId) const override; void ClearMaterialOverride(const MaterialAssignmentId& materialAssignmentId) override; - void SetPropertyOverride(const MaterialAssignmentId& materialAssignmentId, const Name& propertyName, const AZStd::any& propertyValue) override; - AZStd::any GetPropertyOverride(const MaterialAssignmentId& materialAssignmentId, const Name& propertyName) const override; - void ClearPropertyOverride(const MaterialAssignmentId& materialAssignmentId, const Name& propertyName) override; + void SetPropertyOverride(const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName, const AZStd::any& value) override; + void SetPropertyOverrideBool(const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName, const bool& value) override; + void SetPropertyOverrideInt32(const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName, const int32_t& value) override; + void SetPropertyOverrideUInt32(const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName, const uint32_t& value) override; + void SetPropertyOverrideFloat(const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName, const float& value) override; + void SetPropertyOverrideVector2(const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName, const AZ::Vector2& value) override; + void SetPropertyOverrideVector3(const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName, const AZ::Vector3& value) override; + void SetPropertyOverrideVector4(const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName, const AZ::Vector4& value) override; + void SetPropertyOverrideColor(const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName, const AZ::Color& value) override; + void SetPropertyOverrideImageAsset(const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName, const AZ::Data::Asset& value) override; + void SetPropertyOverrideImageInstance(const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName, const AZ::Data::Instance& value) override; + void SetPropertyOverrideString(const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName, const AZStd::string& value) override; + + AZStd::any GetPropertyOverride(const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName) const override; + bool GetPropertyOverrideBool(const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName) const override; + int32_t GetPropertyOverrideInt32(const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName) const override; + uint32_t GetPropertyOverrideUInt32(const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName) const override; + float GetPropertyOverrideFloat(const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName) const override; + AZ::Vector2 GetPropertyOverrideVector2(const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName) const override; + AZ::Vector3 GetPropertyOverrideVector3(const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName) const override; + AZ::Vector4 GetPropertyOverrideVector4(const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName) const override; + AZ::Color GetPropertyOverrideColor(const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName) const override; + AZ::Data::Asset GetPropertyOverrideImageAsset(const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName) const override; + AZ::Data::Instance GetPropertyOverrideImageInstance(const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName) const override; + AZStd::string GetPropertyOverrideString(const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName) const override; + + void ClearPropertyOverride(const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName) override; void ClearPropertyOverrides(const MaterialAssignmentId& materialAssignmentId) override; void ClearAllPropertyOverrides() override; MaterialPropertyOverrideMap GetPropertyOverrides(const MaterialAssignmentId& materialAssignmentId) const override; From 7da5b032e77536e6a03353b5e9c750ae986aecc0 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Mon, 16 Aug 2021 17:41:51 -0500 Subject: [PATCH 401/803] updated test scripts Signed-off-by: Guthrie Adams --- .../Common/Assets/Scripts/material_find_overrides_demo.lua | 6 +++--- .../Assets/Scripts/material_property_overrides_demo.lua | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Gems/Atom/Feature/Common/Assets/Scripts/material_find_overrides_demo.lua b/Gems/Atom/Feature/Common/Assets/Scripts/material_find_overrides_demo.lua index dda3974043..41df35e355 100644 --- a/Gems/Atom/Feature/Common/Assets/Scripts/material_find_overrides_demo.lua +++ b/Gems/Atom/Feature/Common/Assets/Scripts/material_find_overrides_demo.lua @@ -66,20 +66,20 @@ function FindMaterialAssignmentTest:OnActivate() end function FindMaterialAssignmentTest:UpdateFactor(assignmentId) - local propertyName = Name("baseColor.factor") + local propertyName = "baseColor.factor" local propertyValue = math.random() MaterialComponentRequestBus.Event.SetPropertyOverride(self.entityId, assignmentId, propertyName, propertyValue); end function FindMaterialAssignmentTest:UpdateColor(assignmentId, color) - local propertyName = Name("baseColor.color") + local propertyName = "baseColor.color" local propertyValue = color MaterialComponentRequestBus.Event.SetPropertyOverride(self.entityId, assignmentId, propertyName, propertyValue); end function FindMaterialAssignmentTest:UpdateTexture(assignmentId) if (#self.Properties.Textures > 0) then - local propertyName = Name("baseColor.textureMap") + local propertyName = "baseColor.textureMap" local textureName = self.Properties.Textures[ math.random( #self.Properties.Textures ) ] Debug.Log(textureName) local textureAssetId = AssetCatalogRequestBus.Broadcast.GetAssetIdByPath(textureName, Uuid(), false) diff --git a/Gems/Atom/Feature/Common/Assets/Scripts/material_property_overrides_demo.lua b/Gems/Atom/Feature/Common/Assets/Scripts/material_property_overrides_demo.lua index 685fd8310b..0495dccbc0 100644 --- a/Gems/Atom/Feature/Common/Assets/Scripts/material_property_overrides_demo.lua +++ b/Gems/Atom/Feature/Common/Assets/Scripts/material_property_overrides_demo.lua @@ -64,20 +64,20 @@ function PropertyOverrideTest:OnActivate() end function PropertyOverrideTest:UpdateFactor(assignmentId) - local propertyName = Name("baseColor.factor") + local propertyName = "baseColor.factor" local propertyValue = math.random() MaterialComponentRequestBus.Event.SetPropertyOverride(self.entityId, assignmentId, propertyName, propertyValue); end function PropertyOverrideTest:UpdateColor(assignmentId, color) - local propertyName = Name("baseColor.color") + local propertyName = "baseColor.color" local propertyValue = color MaterialComponentRequestBus.Event.SetPropertyOverride(self.entityId, assignmentId, propertyName, propertyValue); end function PropertyOverrideTest:UpdateTexture(assignmentId) if (#self.Properties.Textures > 0) then - local propertyName = Name("baseColor.textureMap") + local propertyName = "baseColor.textureMap" local textureName = self.Properties.Textures[ math.random( #self.Properties.Textures ) ] Debug.Log(textureName) local textureAssetId = AssetCatalogRequestBus.Broadcast.GetAssetIdByPath(textureName, Uuid(), false) From 0884f96997ab18916b4b83ce01f167eb75d1eea6 Mon Sep 17 00:00:00 2001 From: mnaumov Date: Mon, 16 Aug 2021 16:00:18 -0700 Subject: [PATCH 402/803] PR feedback Signed-off-by: mnaumov --- .../AzToolsFramework/Prefab/Instance/InstanceSerializer.cpp | 6 +++--- .../AzToolsFramework/Prefab/PrefabDomUtils.cpp | 3 +-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceSerializer.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceSerializer.cpp index af42919637..92b37b10db 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceSerializer.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceSerializer.cpp @@ -82,13 +82,13 @@ namespace AzToolsFramework result.Combine(resultInstances); } - PrefabDomUtils::LinkIdMetadata** linkIdMetadata = context.GetMetadata().Find(); - if (linkIdMetadata && *linkIdMetadata) + PrefabDomUtils::LinkIdMetadata* subPathLinkId = context.GetMetadata().Find(); + if (subPathLinkId) { AZ::ScopedContextPath subPathSource(context, "m_linkId"); result = ContinueStoringToJsonObjectField( - outputValue, "LinkId", &(instance->m_linkId), &InvalidLinkId, azrtti_typeid(), context); + outputValue, "LinkId", &(instance->m_linkId), &InvalidLinkId, azrtti_typeidm_linkId)>(), context); } return context.Report(result, diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.cpp index 2462bc0348..dcc14d3b91 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.cpp @@ -90,8 +90,7 @@ namespace AzToolsFramework if ((flags & StoreFlags::StoreLinkIds) != StoreFlags::None) { - LinkIdMetadata linkIdMetadata; - settings.m_metadata.Add(&linkIdMetadata); + settings.m_metadata.Create(); } AZStd::string scratchBuffer; From e648dbcf0811ecaaf9e19bef5053e81ff728fd50 Mon Sep 17 00:00:00 2001 From: pappeste Date: Thu, 24 Jun 2021 19:04:19 -0700 Subject: [PATCH 403/803] enabling the warning Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- cmake/Platform/Common/MSVC/Configurations_msvc.cmake | 1 - 1 file changed, 1 deletion(-) diff --git a/cmake/Platform/Common/MSVC/Configurations_msvc.cmake b/cmake/Platform/Common/MSVC/Configurations_msvc.cmake index 118a515e30..161783caa1 100644 --- a/cmake/Platform/Common/MSVC/Configurations_msvc.cmake +++ b/cmake/Platform/Common/MSVC/Configurations_msvc.cmake @@ -38,7 +38,6 @@ ly_append_configurations_options( /wd4201 # nonstandard extension used: nameless struct/union. This actually became part of the C++11 std, MS has an open issue: https://developercommunity.visualstudio.com/t/warning-level-4-generates-a-bogus-warning-c4201-no/103064 # Disabling these warnings while they get fixed - /wd4244 # conversion, possible loss of data /wd4245 # conversion, signed/unsigned mismatch /wd4389 # comparison, signed/unsigned mismatch From 81d26d322dc568b275e7b69da8bac3290ef1e3d0 Mon Sep 17 00:00:00 2001 From: pappeste Date: Thu, 24 Jun 2021 19:05:30 -0700 Subject: [PATCH 404/803] Code/Framework fixes Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Framework/AzCore/AzCore/Console/Console.cpp | 8 ++++---- Code/Framework/AzCore/AzCore/IO/Path/Path.inl | 2 +- .../AzCore/AzCore/IO/Streamer/BlockCache.cpp | 2 +- .../AzCore/AzCore/IO/Streamer/DedicatedCache.cpp | 2 +- .../Framework/AzCore/AzCore/StringFunc/StringFunc.cpp | 5 +++-- .../Tests/AZTestShared/Math/MathTestHelpers.cpp | 2 +- .../Tests/Serialization/Json/IntSerializerTests.cpp | 4 ++-- .../AzFramework/AzFramework/Archive/ZipDirCache.cpp | 2 +- .../AzFramework/Archive/ZipDirStructures.cpp | 10 +++++----- .../Windows/ScopedAutoTempDirectory_Windows.cpp | 2 +- Code/Framework/Crcfix/crcfix.cpp | 11 ++++++----- 11 files changed, 26 insertions(+), 24 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/Console/Console.cpp b/Code/Framework/AzCore/AzCore/Console/Console.cpp index 8bb50f77e0..0166e964b8 100644 --- a/Code/Framework/AzCore/AzCore/Console/Console.cpp +++ b/Code/Framework/AzCore/AzCore/Console/Console.cpp @@ -182,7 +182,7 @@ namespace AZ ConsoleFunctorBase* Console::FindCommand(const char* command) { CVarFixedString lowerName(command); - AZStd::transform(lowerName.begin(), lowerName.end(), lowerName.begin(), [](char value) { return std::tolower(value); }); + AZStd::to_lower(lowerName.begin(), lowerName.end()); CommandMap::iterator iter = m_commands.find(lowerName); if (iter != m_commands.end()) @@ -270,7 +270,7 @@ namespace AZ } CVarFixedString lowerName = functor->GetName(); - AZStd::transform(lowerName.begin(), lowerName.end(), lowerName.begin(), [](char value) { return std::tolower(value); }); + AZStd::to_lower(lowerName.begin(), lowerName.end()); CommandMap::iterator iter = m_commands.find(lowerName); if (iter != m_commands.end()) { @@ -313,7 +313,7 @@ namespace AZ } CVarFixedString lowerName = functor->GetName(); - AZStd::transform(lowerName.begin(), lowerName.end(), lowerName.begin(), [](char value) { return std::tolower(value); }); + AZStd::to_lower(lowerName.begin(), lowerName.end()); CommandMap::iterator iter = m_commands.find(lowerName); if (iter != m_commands.end()) { @@ -389,7 +389,7 @@ namespace AZ ConsoleFunctorFlags flags = ConsoleFunctorFlags::Null; CVarFixedString lowerName(command); - AZStd::transform(lowerName.begin(), lowerName.end(), lowerName.begin(), [](char value) { return std::tolower(value); }); + AZStd::to_lower(lowerName.begin(), lowerName.end()); CommandMap::iterator iter = m_commands.find(lowerName); if (iter != m_commands.end()) diff --git a/Code/Framework/AzCore/AzCore/IO/Path/Path.inl b/Code/Framework/AzCore/AzCore/IO/Path/Path.inl index 4e8356b436..a6d41b0ef8 100644 --- a/Code/Framework/AzCore/AzCore/IO/Path/Path.inl +++ b/Code/Framework/AzCore/AzCore/IO/Path/Path.inl @@ -221,7 +221,7 @@ namespace AZ::IO::Internal ? strncmp(left.data(), right.data(), maxCharsToCompare) : azstrnicmp(left.data(), right.data(), maxCharsToCompare); return charCompareResult == 0 - ? aznumeric_cast(left.size()) - aznumeric_cast(right.size()) + ? aznumeric_cast(aznumeric_cast(left.size()) - aznumeric_cast(right.size())) : charCompareResult; } } diff --git a/Code/Framework/AzCore/AzCore/IO/Streamer/BlockCache.cpp b/Code/Framework/AzCore/AzCore/IO/Streamer/BlockCache.cpp index f358370be5..3d8cbc7480 100644 --- a/Code/Framework/AzCore/AzCore/IO/Streamer/BlockCache.cpp +++ b/Code/Framework/AzCore/AzCore/IO/Streamer/BlockCache.cpp @@ -38,7 +38,7 @@ namespace AZ break; } - u32 cacheSize = m_cacheSizeMib * 1_mib; + u32 cacheSize = static_cast(m_cacheSizeMib * 1_mib); if (blockSize * 2 > cacheSize) { AZ_Warning("Streamer", false, "Size (%u) for BlockCache isn't big enough to hold at least two cache blocks of size (%zu). " diff --git a/Code/Framework/AzCore/AzCore/IO/Streamer/DedicatedCache.cpp b/Code/Framework/AzCore/AzCore/IO/Streamer/DedicatedCache.cpp index 6ec3fb295c..e0e512e21f 100644 --- a/Code/Framework/AzCore/AzCore/IO/Streamer/DedicatedCache.cpp +++ b/Code/Framework/AzCore/AzCore/IO/Streamer/DedicatedCache.cpp @@ -36,7 +36,7 @@ namespace AZ break; } - u32 cacheSize = m_cacheSizeMib * 1_mib; + u32 cacheSize = static_cast(m_cacheSizeMib * 1_mib); if (blockSize > cacheSize) { AZ_Warning("Streamer", false, "Size (%u) for DedicatedCache isn't big enough to hold at least one cache blocks of size (%zu). " diff --git a/Code/Framework/AzCore/AzCore/StringFunc/StringFunc.cpp b/Code/Framework/AzCore/AzCore/StringFunc/StringFunc.cpp index da7a78e1b3..d4f874c667 100644 --- a/Code/Framework/AzCore/AzCore/StringFunc/StringFunc.cpp +++ b/Code/Framework/AzCore/AzCore/StringFunc/StringFunc.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -342,8 +343,8 @@ namespace AZ::StringFunc::Internal { for (const char stripCharacter : stripCharacters) { - const char lower = tolower(stripCharacter); - const char upper = toupper(stripCharacter); + const char lower = azlossy_cast(tolower(stripCharacter)); + const char upper = azlossy_cast(toupper(stripCharacter)); if (lower != upper) { combinedStripCharacters.push_back(lower); diff --git a/Code/Framework/AzCore/Tests/AZTestShared/Math/MathTestHelpers.cpp b/Code/Framework/AzCore/Tests/AZTestShared/Math/MathTestHelpers.cpp index bf0a1023ab..fc707c9751 100644 --- a/Code/Framework/AzCore/Tests/AZTestShared/Math/MathTestHelpers.cpp +++ b/Code/Framework/AzCore/Tests/AZTestShared/Math/MathTestHelpers.cpp @@ -95,7 +95,7 @@ namespace AZ auto printElement = [&os, &mat](int64_t row, int64_t col) -> std::ostream& { const std::streamsize width = 10; - os << std::setw(width) << std::fixed << mat.GetElement(row, col); + os << std::setw(width) << std::fixed << mat.GetElement(static_cast(row), static_cast(col)); return os; }; diff --git a/Code/Framework/AzCore/Tests/Serialization/Json/IntSerializerTests.cpp b/Code/Framework/AzCore/Tests/Serialization/Json/IntSerializerTests.cpp index be06e76f68..c971535f0b 100644 --- a/Code/Framework/AzCore/Tests/Serialization/Json/IntSerializerTests.cpp +++ b/Code/Framework/AzCore/Tests/Serialization/Json/IntSerializerTests.cpp @@ -32,12 +32,12 @@ namespace JsonSerializationTests AZStd::shared_ptr CreateDefaultInstance() override { - return AZStd::make_shared(0); + return AZStd::make_shared(NumberType(0)); } AZStd::shared_ptr CreateFullySetInstance() override { - return AZStd::make_shared(4); + return AZStd::make_shared(NumberType(4)); } AZStd::string_view GetJsonForFullySetInstance() override diff --git a/Code/Framework/AzFramework/AzFramework/Archive/ZipDirCache.cpp b/Code/Framework/AzFramework/AzFramework/Archive/ZipDirCache.cpp index baabfb35cc..d74f69e27b 100644 --- a/Code/Framework/AzFramework/AzFramework/Archive/ZipDirCache.cpp +++ b/Code/Framework/AzFramework/AzFramework/Archive/ZipDirCache.cpp @@ -75,7 +75,7 @@ namespace AZ::IO::ZipDir for (i = 0; i < AZ_ARRAY_SIZE(szBuf) - 1; ++i) { int r = distrib(gen); - szBuf[i] = r > 9 ? (r - 10) + 'a' : '0' + r; + szBuf[i] = static_cast(r > 9 ? (r - 10) + 'a' : '0' + r); } szBuf[i] = '\0'; return szBuf; diff --git a/Code/Framework/AzFramework/AzFramework/Archive/ZipDirStructures.cpp b/Code/Framework/AzFramework/AzFramework/Archive/ZipDirStructures.cpp index 445bba63f4..b3b2328222 100644 --- a/Code/Framework/AzFramework/AzFramework/Archive/ZipDirStructures.cpp +++ b/Code/Framework/AzFramework/AzFramework/Archive/ZipDirStructures.cpp @@ -832,18 +832,18 @@ namespace AZ::IO::ZipDir // conversion routines for the date/time fields used in Zip uint16_t DOSDate(tm* t) { - return + return static_cast( ((t->tm_year - 80) << 9) | (t->tm_mon << 5) - | t->tm_mday; + | t->tm_mday); } uint16_t DOSTime(tm* t) { - return + return static_cast( ((t->tm_hour) << 11) | ((t->tm_min) << 5) - | ((t->tm_sec) >> 1); + | ((t->tm_sec) >> 1)); } // sets the current time to modification time @@ -872,7 +872,7 @@ namespace AZ::IO::ZipDir // we'll need CRC32 of the file to pack it this->desc.lCRC32 = AZ::Crc32(pUncompressed, nSize); - this->nMethod = nCompressionMethod; + this->nMethod = static_cast(nCompressionMethod); } uint64_t FileEntry::GetModificationTime() diff --git a/Code/Framework/AzTest/AzTest/Platform/Windows/ScopedAutoTempDirectory_Windows.cpp b/Code/Framework/AzTest/AzTest/Platform/Windows/ScopedAutoTempDirectory_Windows.cpp index dc4b31c9be..fcda5d351a 100644 --- a/Code/Framework/AzTest/AzTest/Platform/Windows/ScopedAutoTempDirectory_Windows.cpp +++ b/Code/Framework/AzTest/AzTest/Platform/Windows/ScopedAutoTempDirectory_Windows.cpp @@ -30,7 +30,7 @@ namespace AZ while (maxAttempts > 0) { // Use the system's tick count to base the folder name - DWORD currentTick = GetTickCount64(); + ULONGLONG currentTick = GetTickCount64(); azsnprintf(workingTempPathBuffer, bufferSize, "%sUnitTest-%X", tempDir, aznumeric_cast(currentTick)); // Check if the requested directory name is available and re-generate if it already exists diff --git a/Code/Framework/Crcfix/crcfix.cpp b/Code/Framework/Crcfix/crcfix.cpp index 778b9e2185..c788d2a0c6 100644 --- a/Code/Framework/Crcfix/crcfix.cpp +++ b/Code/Framework/Crcfix/crcfix.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -284,7 +285,7 @@ char* CRCfix::GetToken(FILE* infile, FILE* outfile) { if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '#' || c == '_') { - token[i++] = c; + token[i++] = azlossy_cast(c); continue; } else @@ -375,7 +376,7 @@ void CRCfix::GetPreviousCRC(char* token, FILE* infile) int c; while ((c = fgetc(infile)) != ')') { - *token++ = c; + *token++ = azlossy_cast(c); } *token = 0; } @@ -426,7 +427,7 @@ int CRCfix::Fix(Filename srce) if (strcmp(token, "AZ_CRC") == 0 && lastchar == '(') { size_t i = strlen(token); - token[i++] = lastchar; + token[i++] = azlossy_cast(lastchar); int c = fgetc(infile); if (c == '"') @@ -435,11 +436,11 @@ int CRCfix::Fix(Filename srce) do { - token[i++] = c; + token[i++] = azlossy_cast(c); c = fgetc(infile); } while (c != '"'); - token[i++] = c; + token[i++] = azlossy_cast(c); c = fgetc(infile); int oldcrc = 0, newcrc; From f6cdcddc522b20079f43f8c747c46fe3796671bc Mon Sep 17 00:00:00 2001 From: pappeste Date: Fri, 25 Jun 2021 13:28:51 -0700 Subject: [PATCH 405/803] =?UTF-8?q?=EF=BB=BFfixes=20for=20Code/CryEngine?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../AzCore/Tests/Memory/HphaSchemaErrorDetection.cpp | 3 ++- Code/Legacy/CryCommon/ISplines.h | 2 +- Code/Legacy/CryCommon/PNoise3.h | 4 ++-- Code/Legacy/CryCommon/Vertex.h | 2 +- Code/Legacy/CrySystem/LocalizedStringManager.cpp | 2 +- Code/Legacy/CrySystem/Log.cpp | 2 +- Code/Legacy/CrySystem/XConsole.cpp | 5 +++-- Code/Legacy/CrySystem/XML/SerializeXMLReader.cpp | 2 +- Code/Legacy/CrySystem/XML/XMLBinaryNode.cpp | 2 +- Code/Legacy/CrySystem/XML/XMLBinaryWriter.cpp | 4 ++-- Code/Legacy/CrySystem/XML/xml.cpp | 2 +- .../SceneBuilder/Importers/AssImpAnimationImporter.cpp | 4 ++-- 12 files changed, 18 insertions(+), 16 deletions(-) diff --git a/Code/Framework/AzCore/Tests/Memory/HphaSchemaErrorDetection.cpp b/Code/Framework/AzCore/Tests/Memory/HphaSchemaErrorDetection.cpp index 3bda826313..2b0e7bee92 100644 --- a/Code/Framework/AzCore/Tests/Memory/HphaSchemaErrorDetection.cpp +++ b/Code/Framework/AzCore/Tests/Memory/HphaSchemaErrorDetection.cpp @@ -17,6 +17,7 @@ #include #include #include +#include namespace Internal @@ -297,7 +298,7 @@ AZ_POP_DISABLE_WARNING // the overflow guard is generated out of rand, so we set a fixed seed before doing the allocation // to get a deterministic guard srand(0); - const unsigned char expectedInitialGuard = rand(); + const unsigned char expectedInitialGuard = azlossy_cast(rand()); srand(0); TestClass<16>* someObject = aznew TestClass<16>(); diff --git a/Code/Legacy/CryCommon/ISplines.h b/Code/Legacy/CryCommon/ISplines.h index ad59f1328d..2353489163 100644 --- a/Code/Legacy/CryCommon/ISplines.h +++ b/Code/Legacy/CryCommon/ISplines.h @@ -466,7 +466,7 @@ namespace spline ILINE void flag_clr(int flag) { m_flags &= ~flag; }; ILINE int flag(int flag) { return m_flags & flag; }; - ILINE void ORT(int ort) { m_ORT = ort; }; + ILINE void ORT(int ort) { m_ORT = static_cast(ort); }; ILINE int ORT() const { return m_ORT; }; ILINE int isORT(int o) const { return (m_ORT == o); }; diff --git a/Code/Legacy/CryCommon/PNoise3.h b/Code/Legacy/CryCommon/PNoise3.h index 1cb7f0d65b..fe19997ef4 100644 --- a/Code/Legacy/CryCommon/PNoise3.h +++ b/Code/Legacy/CryCommon/PNoise3.h @@ -205,7 +205,7 @@ public: // Initialize the permutation table for(i = 0; i < NOISE_TABLE_SIZE; i++) - m_p[i] = i; + m_p[i] = static_cast(i); for(i = 0; i < NOISE_TABLE_SIZE; i++) { @@ -213,7 +213,7 @@ public: nSwap = m_p[i]; m_p[i] = m_p[j]; - m_p[j] = nSwap; + m_p[j] = static_cast(nSwap); } // Generate the gradient lookup tables diff --git a/Code/Legacy/CryCommon/Vertex.h b/Code/Legacy/CryCommon/Vertex.h index 2e61524cab..b9e0b25d38 100644 --- a/Code/Legacy/CryCommon/Vertex.h +++ b/Code/Legacy/CryCommon/Vertex.h @@ -1037,7 +1037,7 @@ namespace AZ } AZ_Assert(stride < (0x1 << (sizeof(m_stride) * 8)), "Vertex stride is larger than the maximum supported, update the type for m_stride in Vertex.h"); - m_stride = stride; + m_stride = static_cast(stride); } diff --git a/Code/Legacy/CrySystem/LocalizedStringManager.cpp b/Code/Legacy/CrySystem/LocalizedStringManager.cpp index 68a8a6659b..db77eda3e8 100644 --- a/Code/Legacy/CrySystem/LocalizedStringManager.cpp +++ b/Code/Legacy/CrySystem/LocalizedStringManager.cpp @@ -473,7 +473,7 @@ void CLocalizedStringsManager::ParseFirstLine(IXmlTableReader* pXmlTableReader, const char* pFind = strstr(sCellContent.c_str(), sLocalizedColumnNames[i]); if (pFind != 0) { - nCellIndexToType[nCellIndex] = i; + nCellIndexToType[nCellIndex] = static_cast(i); // find SoundMood if (i == ELOCALIZED_COLUMN_SOUNDMOOD) diff --git a/Code/Legacy/CrySystem/Log.cpp b/Code/Legacy/CrySystem/Log.cpp index d248274b1d..32d5e995ab 100644 --- a/Code/Legacy/CrySystem/Log.cpp +++ b/Code/Legacy/CrySystem/Log.cpp @@ -1227,7 +1227,7 @@ void CLog::CreateBackupFile() const while (!fileSystem->Eof(inFileHandle)) { - uint8 c = AZ::IO::GetC(inFileHandle); + uint8 c = static_cast(AZ::IO::GetC(inFileHandle)); if (c == '\"') { diff --git a/Code/Legacy/CrySystem/XConsole.cpp b/Code/Legacy/CrySystem/XConsole.cpp index 36443fb9ee..a69fd348f5 100644 --- a/Code/Legacy/CrySystem/XConsole.cpp +++ b/Code/Legacy/CrySystem/XConsole.cpp @@ -2464,8 +2464,9 @@ void CXConsole::DisplayVarValue(ICVar* pVar) sValue += " ("; if (nonAlphaBits != 0) { - char nonAlphaChars[3]; // 1..63 + '\0' - sValue += azitoa(nonAlphaBits, nonAlphaChars, AZ_ARRAY_SIZE(nonAlphaChars), 10); + char nonAlphaChars[3] = { 0 }; // 1..63 + '\0' + azitoa(nonAlphaBits, nonAlphaChars, AZ_ARRAY_SIZE(nonAlphaChars), 10); + sValue += nonAlphaChars; sValue += ", "; } sValue += alphaChars; diff --git a/Code/Legacy/CrySystem/XML/SerializeXMLReader.cpp b/Code/Legacy/CrySystem/XML/SerializeXMLReader.cpp index e74b457191..841697ecdb 100644 --- a/Code/Legacy/CrySystem/XML/SerializeXMLReader.cpp +++ b/Code/Legacy/CrySystem/XML/SerializeXMLReader.cpp @@ -44,7 +44,7 @@ bool CSerializeXMLReaderImpl::Value(const char* name, int8& value) } else { - value = temp; + value = static_cast(temp); } return bResult; } diff --git a/Code/Legacy/CrySystem/XML/XMLBinaryNode.cpp b/Code/Legacy/CrySystem/XML/XMLBinaryNode.cpp index 257fc3ca69..d209478957 100644 --- a/Code/Legacy/CrySystem/XML/XMLBinaryNode.cpp +++ b/Code/Legacy/CrySystem/XML/XMLBinaryNode.cpp @@ -320,7 +320,7 @@ bool CBinaryXmlNode::getAttr(const char* key, ColorB& value) const // If we only found 3 values, a should be unchanged, and still be 255 if (r < 256 && g < 256 && b < 256 && a < 256) { - value = ColorB(r, g, b, a); + value = ColorB(static_cast(r), static_cast(g), static_cast(b), static_cast(a)); return true; } } diff --git a/Code/Legacy/CrySystem/XML/XMLBinaryWriter.cpp b/Code/Legacy/CrySystem/XML/XMLBinaryWriter.cpp index a2a35cfe8b..265953850f 100644 --- a/Code/Legacy/CrySystem/XML/XMLBinaryWriter.cpp +++ b/Code/Legacy/CrySystem/XML/XMLBinaryWriter.cpp @@ -244,7 +244,7 @@ bool XMLBinary::CXMLBinaryWriter::CompileTablesForNode(XmlNodeRef node, int nPar nd.nContentStringOffset = nContentStringOffset; nd.nParentIndex = nParentIndex; nd.nFirstAttributeIndex = nFirstAttributeIndex; - nd.nAttributeCount = nAttributeCount; + nd.nAttributeCount = static_cast(nAttributeCount); m_nodes.push_back(nd); } @@ -271,7 +271,7 @@ bool XMLBinary::CXMLBinaryWriter::CompileTablesForNode(XmlNodeRef node, int nPar } } - m_nodes[nIndex].nChildCount = nChildCount; + m_nodes[nIndex].nChildCount = static_cast(nChildCount); return true; } diff --git a/Code/Legacy/CrySystem/XML/xml.cpp b/Code/Legacy/CrySystem/XML/xml.cpp index 7a9bb4bc36..adbfcc5f3e 100644 --- a/Code/Legacy/CrySystem/XML/xml.cpp +++ b/Code/Legacy/CrySystem/XML/xml.cpp @@ -641,7 +641,7 @@ bool CXmlNode::getAttr(const char* key, ColorB& value) const // If we only found 3 values, a should be unchanged, and still be 255 if (r < 256 && g < 256 && b < 256 && a < 256) { - value = ColorB(r, g, b, a); + value = ColorB(static_cast(r), static_cast(g), static_cast(b), static_cast(a)); return true; } } diff --git a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpAnimationImporter.cpp b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpAnimationImporter.cpp index 97b5960a8d..a76cb3531d 100644 --- a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpAnimationImporter.cpp +++ b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpAnimationImporter.cpp @@ -49,7 +49,7 @@ namespace AZ double totalFramesAtDefaultTimeStep = totalTicks / AssImpAnimationImporter::s_defaultTimeStepBetweenFrames + 1; if (!AZ::IsClose(totalFramesAtDefaultTimeStep, numKeys, 1)) { - numKeys = AZStd::ceilf(totalFramesAtDefaultTimeStep); + numKeys = AZStd::ceilf(static_cast(totalFramesAtDefaultTimeStep)); } return numKeys; } @@ -620,7 +620,7 @@ namespace AZ for (unsigned int valIdx = 0; valIdx < key.mNumValuesAndWeights; ++valIdx) { int currentValue = key.mValues[valIdx]; - KeyData thisKey(key.mWeights[valIdx], key.mTime); + KeyData thisKey(static_cast(key.mWeights[valIdx]), key.mTime); valueToKeyDataMap[currentValue].insert( AZStd::upper_bound(valueToKeyDataMap[currentValue].begin(), valueToKeyDataMap[currentValue].end(),thisKey), thisKey); From 38fd7f0013f417cb2109cd9c77ccd4d36051df1a Mon Sep 17 00:00:00 2001 From: pappeste Date: Fri, 25 Jun 2021 16:07:36 -0700 Subject: [PATCH 406/803] fixing Atom Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../Code/Source/Editor/AzslCompiler.cpp | 6 +- .../Source/AuxGeom/FixedShapeProcessor.cpp | 76 +++++++++---------- .../CoreLights/CascadedShadowmapsPass.cpp | 2 +- .../DirectionalLightFeatureProcessor.cpp | 4 +- .../Code/Source/Decals/DecalTextureArray.cpp | 2 +- .../DiffuseProbeGridBlendDistancePass.cpp | 6 +- .../DiffuseProbeGridBlendIrradiancePass.cpp | 6 +- .../DiffuseProbeGridBorderUpdatePass.cpp | 6 +- .../DiffuseProbeGridClassificationPass.cpp | 6 +- .../DiffuseProbeGridRelocationPass.cpp | 6 +- .../Common/Code/Source/ImGui/ImGuiPass.cpp | 16 ++-- .../Code/Source/Mesh/MeshFeatureProcessor.cpp | 10 +-- .../MorphTargets/MorphTargetDispatchItem.cpp | 6 +- .../Source/PostProcessing/BloomBlurPass.cpp | 4 +- .../PostProcessing/BloomCompositePass.cpp | 8 +- .../PostProcessing/BloomDownsamplePass.cpp | 2 +- .../Code/Source/PostProcessing/TaaPass.cpp | 2 +- .../ReflectionProbe/ReflectionProbe.cpp | 2 +- .../ReflectionScreenSpaceBlurChildPass.cpp | 2 +- .../ReflectionScreenSpaceBlurPass.cpp | 4 +- .../SkinnedMesh/SkinnedMeshDispatchItem.cpp | 6 +- .../SkinnedMesh/SkinnedMeshInputBuffers.cpp | 2 +- .../RHI/Code/Include/Atom/RHI/ImageProperty.h | 8 +- .../RHI/Code/Source/RHI/CpuProfilerImpl.cpp | 2 +- Gems/Atom/RHI/Code/Source/RHI/FrameGraph.cpp | 2 +- Gems/Atom/RHI/Code/Source/RHI/Image.cpp | 2 +- .../RHI/Code/Tests/ImagePropertyTests.cpp | 2 +- .../RHI.Reflect/BufferPoolDescriptor.cpp | 2 +- .../RHI/DX12/Code/Source/RHI/BufferPool.cpp | 2 +- .../RHI/DX12/Code/Source/RHI/Conversions.cpp | 6 +- Gems/Atom/RHI/DX12/Code/Source/RHI/Device.cpp | 4 +- .../DX12/Code/Source/RHI/PipelineLayout.cpp | 4 +- .../Code/Source/RHI/StreamingImagePool.cpp | 2 +- .../RHI.Reflect/BufferPoolDescriptor.cpp | 2 +- .../Code/Source/RHI/AsyncUploadQueue.cpp | 6 +- .../RHI/Vulkan/Code/Source/RHI/Conversion.cpp | 2 +- .../RHI/Vulkan/Code/Source/RHI/ImageView.cpp | 6 +- .../Vulkan/Code/Source/RHI/PipelineLayout.cpp | 2 +- .../Code/Source/RHI/StreamingImagePool.cpp | 8 +- .../RPI.Public/Image/StreamingImage.cpp | 2 +- .../Pass/FullscreenTrianglePass.cpp | 2 +- .../RPI/Code/Tests/Buffer/BufferTests.cpp | 3 +- Gems/Atom/RPI/Code/Tests/Model/ModelTests.cpp | 3 +- .../Utils/Code/Source/ImageComparison.cpp | 6 +- 44 files changed, 132 insertions(+), 130 deletions(-) diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/AzslCompiler.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/AzslCompiler.cpp index cc42fac422..f5fb73182a 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/AzslCompiler.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/AzslCompiler.cpp @@ -211,11 +211,11 @@ namespace AZ case rapidjson::kNumberType: if (name == "cols") { - inputStructParams.m_variable.m_cols = itr2->value.GetInt(); + inputStructParams.m_variable.m_cols = static_cast(itr2->value.GetInt()); } else if (name == "rows") { - inputStructParams.m_variable.m_rows = itr2->value.GetInt(); + inputStructParams.m_variable.m_rows = static_cast(itr2->value.GetInt()); } else if (name == "semanticIndex") { @@ -304,7 +304,7 @@ namespace AZ case rapidjson::kNumberType: if (name == "cols") { - outputStructParams.m_variable.m_cols = itr2->value.GetInt(); + outputStructParams.m_variable.m_cols = static_cast(itr2->value.GetInt()); } else if (name == "semanticIndex") { diff --git a/Gems/Atom/Feature/Common/Code/Source/AuxGeom/FixedShapeProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/AuxGeom/FixedShapeProcessor.cpp index f2b3a93a53..8a274beb2f 100644 --- a/Gems/Atom/Feature/Common/Code/Source/AuxGeom/FixedShapeProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/AuxGeom/FixedShapeProcessor.cpp @@ -405,15 +405,15 @@ namespace AZ for (uint16_t ring = 0; ring < numRings - 2; ++ring) { - uint16_t firstVertOfThisRing = 1 + ring * numSections; - uint16_t firstVertOfNextRing = 1 + (ring + 1) * numSections; + uint16_t firstVertOfThisRing = static_cast(1 + ring * numSections); + uint16_t firstVertOfNextRing = static_cast(1 + (ring + 1) * numSections); for (uint16_t section = 0; section < numSections; ++section) { uint32_t nextSection = (section + 1) % numSections; // line around ring indices.push_back(firstVertOfThisRing + section); - indices.push_back(firstVertOfThisRing + nextSection); + indices.push_back(static_cast(firstVertOfThisRing + nextSection)); // line around section indices.push_back(firstVertOfThisRing + section); @@ -423,15 +423,15 @@ namespace AZ // build faces for end caps (to connect "inner" vertices with poles) uint16_t firstPoleVert = 0; - uint16_t firstVertOfFirstRing = 1 + (0) * numSections; + uint16_t firstVertOfFirstRing = static_cast(1 + (0) * numSections); for (uint16_t section = 0; section < numSections; ++section) { indices.push_back(firstPoleVert); indices.push_back(firstVertOfFirstRing + section); } - uint16_t lastPoleVert = (numRings - 1) * numSections + 1; - uint16_t firstVertOfLastRing = 1 + (numRings - 2) * numSections; + uint16_t lastPoleVert = static_cast((numRings - 1) * numSections + 1); + uint16_t firstVertOfLastRing = static_cast(1 + (numRings - 2) * numSections); for (uint16_t section = 0; section < numSections; ++section) { indices.push_back(firstVertOfLastRing + section); @@ -457,13 +457,13 @@ namespace AZ for (uint32_t section = 0; section < numSections; ++section) { uint32_t nextSection = (section + 1) % numSections; - indices.push_back((uint16_t)firstVertOfThisRing + nextSection); - indices.push_back((uint16_t)firstVertOfThisRing + section); - indices.push_back((uint16_t)firstVertOfNextRing + nextSection); + indices.push_back(static_cast(firstVertOfThisRing + nextSection)); + indices.push_back(static_cast(firstVertOfThisRing + section)); + indices.push_back(static_cast(firstVertOfNextRing + nextSection)); - indices.push_back((uint16_t)firstVertOfNextRing + section); - indices.push_back((uint16_t)firstVertOfNextRing + nextSection); - indices.push_back((uint16_t)firstVertOfThisRing + section); + indices.push_back(static_cast(firstVertOfNextRing + section)); + indices.push_back(static_cast(firstVertOfNextRing + nextSection)); + indices.push_back(static_cast(firstVertOfThisRing + section)); } } @@ -473,9 +473,9 @@ namespace AZ for (uint32_t section = 0; section < numSections; ++section) { uint32_t nextSection = (section + 1) % numSections; - indices.push_back((uint16_t)firstVertOfFirstRing + section); - indices.push_back((uint16_t)firstVertOfFirstRing + nextSection); - indices.push_back((uint16_t)firstPoleVert); + indices.push_back(static_cast(firstVertOfFirstRing + section)); + indices.push_back(static_cast(firstVertOfFirstRing + nextSection)); + indices.push_back(static_cast(firstPoleVert)); } uint32_t lastPoleVert = (numRings - 1) * numSections + 1; @@ -483,9 +483,9 @@ namespace AZ for (uint32_t section = 0; section < numSections; ++section) { uint32_t nextSection = (section + 1) % numSections; - indices.push_back((uint16_t)firstVertOfLastRing + nextSection); - indices.push_back((uint16_t)firstVertOfLastRing + section); - indices.push_back((uint16_t)lastPoleVert); + indices.push_back(static_cast(firstVertOfLastRing + nextSection)); + indices.push_back(static_cast(firstVertOfLastRing + section)); + indices.push_back(static_cast(lastPoleVert)); } } } @@ -637,12 +637,12 @@ namespace AZ { // Line from center of disk to outer edge meshData.m_lineIndices.push_back(centerIndex); - meshData.m_lineIndices.push_back(firstSection + section); + meshData.m_lineIndices.push_back(static_cast(firstSection + section)); // Line from outer edge to next edge - meshData.m_lineIndices.push_back(firstSection + section); + meshData.m_lineIndices.push_back(static_cast(firstSection + section)); uint32_t nextSection = (section + 1) % numSections; - meshData.m_lineIndices.push_back(firstSection + nextSection); + meshData.m_lineIndices.push_back(static_cast(firstSection + nextSection)); } // Create triangle indices @@ -652,13 +652,13 @@ namespace AZ meshData.m_triangleIndices.push_back(centerIndex); if (isUp) { - meshData.m_triangleIndices.push_back(firstSection + nextSection); - meshData.m_triangleIndices.push_back(firstSection + section); + meshData.m_triangleIndices.push_back(static_cast(firstSection + nextSection)); + meshData.m_triangleIndices.push_back(static_cast(firstSection + section)); } else { - meshData.m_triangleIndices.push_back(firstSection + section); - meshData.m_triangleIndices.push_back(firstSection + nextSection); + meshData.m_triangleIndices.push_back(static_cast(firstSection + section)); + meshData.m_triangleIndices.push_back(static_cast(firstSection + nextSection)); } } } @@ -776,7 +776,7 @@ namespace AZ normals.push_back(AuxGeomNormal(0.0f, 1.0f, 0.0f)); // vertex indexes for start of the cone sides and for the cone point - uint16_t indexOfSidesStart = numSections + 1; + uint16_t indexOfSidesStart = static_cast(numSections + 1); uint32_t indexOfConePoint = indexOfSidesStart + numRings * numSections; // indices for points @@ -795,8 +795,8 @@ namespace AZ // build lines between already completed cap for each section for (uint16_t section = 0; section < numSections; ++section) { - indices.push_back(indexOfSidesStart + numRings * section); - indices.push_back(indexOfConePoint); + indices.push_back(static_cast(indexOfSidesStart + numRings * section)); + indices.push_back(static_cast(indexOfConePoint)); } } @@ -812,19 +812,19 @@ namespace AZ // faces from end cap to close to point for (uint32_t ring = 0; ring < numRings - 1; ++ring) { - indices.push_back(indexOfSidesStart + numRings * nextSection + ring + 1); - indices.push_back(indexOfSidesStart + numRings * nextSection + ring); - indices.push_back(indexOfSidesStart + numRings * section + ring); + indices.push_back(static_cast(indexOfSidesStart + numRings * nextSection + ring + 1)); + indices.push_back(static_cast(indexOfSidesStart + numRings * nextSection + ring)); + indices.push_back(static_cast(indexOfSidesStart + numRings * section + ring)); - indices.push_back(indexOfSidesStart + numRings * section + ring); - indices.push_back(indexOfSidesStart + numRings * section + ring + 1); - indices.push_back(indexOfSidesStart + numRings * nextSection + ring + 1); + indices.push_back(static_cast(indexOfSidesStart + numRings * section + ring)); + indices.push_back(static_cast(indexOfSidesStart + numRings * section + ring + 1)); + indices.push_back(static_cast(indexOfSidesStart + numRings * nextSection + ring + 1)); } // faces for point (from last ring of verts to point) - indices.push_back(indexOfConePoint); - indices.push_back(indexOfSidesStart + numRings * nextSection + numRings - 1); - indices.push_back(indexOfSidesStart + numRings * section + numRings - 1); + indices.push_back(static_cast(indexOfConePoint)); + indices.push_back(static_cast(indexOfSidesStart + numRings * nextSection + numRings - 1)); + indices.push_back(static_cast(indexOfSidesStart + numRings * section + numRings - 1)); } } } @@ -912,7 +912,7 @@ namespace AZ //uint16_t indexOfBottomStart = 1; //uint16_t indexOfTopCenter = numSections + 1; //uint16_t indexOfTopStart = numSections + 2; - uint16_t indexOfSidesStart = 2 * numSections + 2; + uint16_t indexOfSidesStart = static_cast(2 * numSections + 2); // build point indices { diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/CascadedShadowmapsPass.cpp b/Gems/Atom/Feature/Common/Code/Source/CoreLights/CascadedShadowmapsPass.cpp index 33123d67a1..5529a2916b 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/CascadedShadowmapsPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/CascadedShadowmapsPass.cpp @@ -126,7 +126,7 @@ namespace AZ return; } - SetCascadesCount(m_arraySize); + SetCascadesCount(static_cast(m_arraySize)); const RHI::Size imageSize { aznumeric_cast(m_shadowmapSize), diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp index 4aa749f7d7..1fff70ce59 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp @@ -225,7 +225,7 @@ namespace AZ } if (segmentsNeedUpdate) { - UpdateViewsOfCascadeSegments(m_shadowingLightHandle, cascadeCount); + UpdateViewsOfCascadeSegments(m_shadowingLightHandle, static_cast(cascadeCount)); SetShadowmapImageSizeArraySize(m_shadowingLightHandle); } @@ -1216,7 +1216,7 @@ namespace AZ else { // If ESM is not used, set filter offsets and filter counts zero in ESM data. - for (uint32_t index = 0; index < GetCascadeCount(handle); ++index) + for (uint16_t index = 0; index < GetCascadeCount(handle); ++index) { EsmShadowmapsPass::FilterParameter& filterParameter = m_esmParameterData.at(cameraView).GetData(index); filterParameter.m_isEnabled = false; diff --git a/Gems/Atom/Feature/Common/Code/Source/Decals/DecalTextureArray.cpp b/Gems/Atom/Feature/Common/Code/Source/Decals/DecalTextureArray.cpp index 6531a04e22..ebdc884ecf 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Decals/DecalTextureArray.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Decals/DecalTextureArray.cpp @@ -147,7 +147,7 @@ namespace AZ RPI::ImageMipChainAssetCreator assetCreator; const uint32_t mipLevels = GetNumMipLevels(); - assetCreator.Begin(Data::AssetId(AZ::Uuid::CreateRandom()), mipLevels, aznumeric_cast(numTexturesToCreate)); + assetCreator.Begin(Data::AssetId(AZ::Uuid::CreateRandom()), static_cast(mipLevels), aznumeric_cast(numTexturesToCreate)); for (uint32_t mipLevel = 0; mipLevel < mipLevels; ++mipLevel) { diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBlendDistancePass.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBlendDistancePass.cpp index a3927b802d..69a4ecdee5 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBlendDistancePass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBlendDistancePass.cpp @@ -72,9 +72,9 @@ namespace AZ return; } - m_dispatchArgs.m_threadsPerGroupX = AZStd::any_cast(args[0]); - m_dispatchArgs.m_threadsPerGroupY = AZStd::any_cast(args[1]); - m_dispatchArgs.m_threadsPerGroupZ = AZStd::any_cast(args[2]); + m_dispatchArgs.m_threadsPerGroupX = static_cast(AZStd::any_cast(args[0])); + m_dispatchArgs.m_threadsPerGroupY = static_cast(AZStd::any_cast(args[1])); + m_dispatchArgs.m_threadsPerGroupZ = static_cast(AZStd::any_cast(args[2])); } } diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBlendIrradiancePass.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBlendIrradiancePass.cpp index 6ff8bdd867..83ef312bf4 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBlendIrradiancePass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBlendIrradiancePass.cpp @@ -72,9 +72,9 @@ namespace AZ return; } - m_dispatchArgs.m_threadsPerGroupX = AZStd::any_cast(args[0]); - m_dispatchArgs.m_threadsPerGroupY = AZStd::any_cast(args[1]); - m_dispatchArgs.m_threadsPerGroupZ = AZStd::any_cast(args[2]); + m_dispatchArgs.m_threadsPerGroupX = static_cast(AZStd::any_cast(args[0])); + m_dispatchArgs.m_threadsPerGroupY = static_cast(AZStd::any_cast(args[1])); + m_dispatchArgs.m_threadsPerGroupZ = static_cast(AZStd::any_cast(args[2])); } } diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBorderUpdatePass.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBorderUpdatePass.cpp index ddfe0f11b1..b251526cb4 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBorderUpdatePass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBorderUpdatePass.cpp @@ -85,9 +85,9 @@ namespace AZ return; } - dispatchArgs.m_threadsPerGroupX = AZStd::any_cast(args[0]); - dispatchArgs.m_threadsPerGroupY = AZStd::any_cast(args[1]); - dispatchArgs.m_threadsPerGroupZ = AZStd::any_cast(args[2]); + dispatchArgs.m_threadsPerGroupX = static_cast(AZStd::any_cast(args[0])); + dispatchArgs.m_threadsPerGroupY = static_cast(AZStd::any_cast(args[1])); + dispatchArgs.m_threadsPerGroupZ = static_cast(AZStd::any_cast(args[2])); } } diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridClassificationPass.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridClassificationPass.cpp index 4c6b07d780..2690f90a7d 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridClassificationPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridClassificationPass.cpp @@ -76,9 +76,9 @@ namespace AZ return; } - m_dispatchArgs.m_threadsPerGroupX = AZStd::any_cast(args[0]); - m_dispatchArgs.m_threadsPerGroupY = AZStd::any_cast(args[1]); - m_dispatchArgs.m_threadsPerGroupZ = AZStd::any_cast(args[2]); + m_dispatchArgs.m_threadsPerGroupX = static_cast(AZStd::any_cast(args[0])); + m_dispatchArgs.m_threadsPerGroupY = static_cast(AZStd::any_cast(args[1])); + m_dispatchArgs.m_threadsPerGroupZ = static_cast(AZStd::any_cast(args[2])); } } diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRelocationPass.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRelocationPass.cpp index 54cf9783cd..67fb95a833 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRelocationPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRelocationPass.cpp @@ -76,9 +76,9 @@ namespace AZ return; } - m_dispatchArgs.m_threadsPerGroupX = AZStd::any_cast(args[0]); - m_dispatchArgs.m_threadsPerGroupY = AZStd::any_cast(args[1]); - m_dispatchArgs.m_threadsPerGroupZ = AZStd::any_cast(args[2]); + m_dispatchArgs.m_threadsPerGroupX = static_cast(AZStd::any_cast(args[0])); + m_dispatchArgs.m_threadsPerGroupY = static_cast(AZStd::any_cast(args[1])); + m_dispatchArgs.m_threadsPerGroupZ = static_cast(AZStd::any_cast(args[2])); } } diff --git a/Gems/Atom/Feature/Common/Code/Source/ImGui/ImGuiPass.cpp b/Gems/Atom/Feature/Common/Code/Source/ImGui/ImGuiPass.cpp index cd781390a3..9f2a7303a5 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ImGui/ImGuiPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ImGui/ImGuiPass.cpp @@ -396,12 +396,12 @@ namespace AZ { auto imguiContextScope = ImguiContextScope(m_imguiContext); - m_viewportWidth = params.m_viewportState.m_maxX - params.m_viewportState.m_minX; - m_viewportHeight = params.m_viewportState.m_maxY - params.m_viewportState.m_minY; + m_viewportWidth = static_cast(params.m_viewportState.m_maxX - params.m_viewportState.m_minX); + m_viewportHeight = static_cast(params.m_viewportState.m_maxY - params.m_viewportState.m_minY); auto& io = ImGui::GetIO(); - io.DisplaySize.x = AZStd::max(1.0f, m_viewportWidth); - io.DisplaySize.y = AZStd::max(1.0f, m_viewportHeight); + io.DisplaySize.x = AZStd::max(1.0f, static_cast(m_viewportWidth)); + io.DisplaySize.y = AZStd::max(1.0f, static_cast(m_viewportHeight)); Matrix4x4 projectionMatrix = Matrix4x4::CreateFromRows( @@ -547,8 +547,8 @@ namespace AZ for (const ImDrawCmd& drawCmd : drawList->CmdBuffer) { AZ_Assert(drawCmd.UserCallback == nullptr, "ImGui UserCallbacks are not supported by the ImGui Pass"); - uint32_t scissorMaxX = drawCmd.ClipRect.z; - uint32_t scissorMaxY = drawCmd.ClipRect.w; + uint32_t scissorMaxX = static_cast(drawCmd.ClipRect.z); + uint32_t scissorMaxY = static_cast(drawCmd.ClipRect.w); //scissorMaxX/scissorMaxY can be a frame stale from imgui (ImGui::NewFrame runs after this) hence we clamp it to viewport bounds //otherwise it is possible to have a frame where scissor bounds can be bigger than window's bounds if we resize the window @@ -559,8 +559,8 @@ namespace AZ { RHI::DrawIndexed(1, 0, vertexOffset, drawCmd.ElemCount, indexOffset), RHI::Scissor( - (drawCmd.ClipRect.x), - (drawCmd.ClipRect.y), + static_cast(drawCmd.ClipRect.x), + static_cast(drawCmd.ClipRect.y), scissorMaxX, scissorMaxY ) diff --git a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp index 8e2c6f2e9b..54ef40ce6c 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp @@ -800,19 +800,19 @@ namespace AZ // note that the element count is the size of the entire buffer, even though this mesh may only // occupy a portion of the vertex buffer. This is necessary since we are accessing it using // a ByteAddressBuffer in the raytracing shaders and passing the byte offset to the shader in a constant buffer. - uint32_t positionBufferByteCount = const_cast(streamBufferViews[0].GetBuffer())->GetDescriptor().m_byteCount; + uint32_t positionBufferByteCount = static_cast(const_cast(streamBufferViews[0].GetBuffer())->GetDescriptor().m_byteCount); RHI::BufferViewDescriptor positionBufferDescriptor = RHI::BufferViewDescriptor::CreateRaw(0, positionBufferByteCount); - uint32_t normalBufferByteCount = const_cast(streamBufferViews[1].GetBuffer())->GetDescriptor().m_byteCount; + uint32_t normalBufferByteCount = static_cast(const_cast(streamBufferViews[1].GetBuffer())->GetDescriptor().m_byteCount); RHI::BufferViewDescriptor normalBufferDescriptor = RHI::BufferViewDescriptor::CreateRaw(0, normalBufferByteCount); - uint32_t tangentBufferByteCount = const_cast(streamBufferViews[2].GetBuffer())->GetDescriptor().m_byteCount; + uint32_t tangentBufferByteCount = static_cast(const_cast(streamBufferViews[2].GetBuffer())->GetDescriptor().m_byteCount); RHI::BufferViewDescriptor tangentBufferDescriptor = RHI::BufferViewDescriptor::CreateRaw(0, tangentBufferByteCount); - uint32_t bitangentBufferByteCount = const_cast(streamBufferViews[3].GetBuffer())->GetDescriptor().m_byteCount; + uint32_t bitangentBufferByteCount = static_cast(const_cast(streamBufferViews[3].GetBuffer())->GetDescriptor().m_byteCount); RHI::BufferViewDescriptor bitangentBufferDescriptor = RHI::BufferViewDescriptor::CreateRaw(0, bitangentBufferByteCount); - uint32_t uvBufferByteCount = const_cast(streamBufferViews[4].GetBuffer())->GetDescriptor().m_byteCount; + uint32_t uvBufferByteCount = static_cast(const_cast(streamBufferViews[4].GetBuffer())->GetDescriptor().m_byteCount); RHI::BufferViewDescriptor uvBufferDescriptor = RHI::BufferViewDescriptor::CreateRaw(0, uvBufferByteCount); const RHI::IndexBufferView& indexBufferView = mesh.m_indexBufferView; diff --git a/Gems/Atom/Feature/Common/Code/Source/MorphTargets/MorphTargetDispatchItem.cpp b/Gems/Atom/Feature/Common/Code/Source/MorphTargets/MorphTargetDispatchItem.cpp index 0f8a30d8aa..19f379b17d 100644 --- a/Gems/Atom/Feature/Common/Code/Source/MorphTargets/MorphTargetDispatchItem.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/MorphTargets/MorphTargetDispatchItem.cpp @@ -85,9 +85,9 @@ namespace AZ { const auto& args = *numThreads; // Check that the arguments are valid integers, and fall back to 1,1,1 if there is an error - arguments.m_threadsPerGroupX = args[0].type() == azrtti_typeid() ? AZStd::any_cast(args[0]) : 1; - arguments.m_threadsPerGroupY = args[1].type() == azrtti_typeid() ? AZStd::any_cast(args[1]) : 1; - arguments.m_threadsPerGroupZ = args[2].type() == azrtti_typeid() ? AZStd::any_cast(args[2]) : 1; + arguments.m_threadsPerGroupX = static_cast(args[0].type() == azrtti_typeid() ? AZStd::any_cast(args[0]) : 1); + arguments.m_threadsPerGroupY = static_cast(args[1].type() == azrtti_typeid() ? AZStd::any_cast(args[1]) : 1); + arguments.m_threadsPerGroupZ = static_cast(args[2].type() == azrtti_typeid() ? AZStd::any_cast(args[2]) : 1); } arguments.m_totalNumberOfThreadsX = m_morphTargetMetaData.m_vertexCount; diff --git a/Gems/Atom/Feature/Common/Code/Source/PostProcessing/BloomBlurPass.cpp b/Gems/Atom/Feature/Common/Code/Source/PostProcessing/BloomBlurPass.cpp index b93e847fd2..3fcff54eaa 100644 --- a/Gems/Atom/Feature/Common/Code/Source/PostProcessing/BloomBlurPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/PostProcessing/BloomBlurPass.cpp @@ -153,8 +153,8 @@ namespace AZ inBinding.m_connectedBinding = isHorizontalPass ? &parentInOutBinding : &parentInBinding; RHI::ImageViewDescriptor viewDesc; - viewDesc.m_mipSliceMin = mipLevel; - viewDesc.m_mipSliceMax = mipLevel; + viewDesc.m_mipSliceMin = static_cast(mipLevel); + viewDesc.m_mipSliceMax = static_cast(mipLevel); inBinding.m_unifiedScopeDesc.SetAsImage(viewDesc); pass->AddAttachmentBinding(inBinding); diff --git a/Gems/Atom/Feature/Common/Code/Source/PostProcessing/BloomCompositePass.cpp b/Gems/Atom/Feature/Common/Code/Source/PostProcessing/BloomCompositePass.cpp index 11e53e8805..e9b428c877 100644 --- a/Gems/Atom/Feature/Common/Code/Source/PostProcessing/BloomCompositePass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/PostProcessing/BloomCompositePass.cpp @@ -133,8 +133,8 @@ namespace AZ inBinding.m_connectedBinding = &parentInBinding; RHI::ImageViewDescriptor inViewDesc; - inViewDesc.m_mipSliceMin = mipLevel; - inViewDesc.m_mipSliceMax = mipLevel; + inViewDesc.m_mipSliceMin = static_cast(mipLevel); + inViewDesc.m_mipSliceMax = static_cast(mipLevel); inBinding.m_unifiedScopeDesc.SetAsImage(inViewDesc); pass->AddAttachmentBinding(inBinding); @@ -151,8 +151,8 @@ namespace AZ if (mipLevel != 0) { RHI::ImageViewDescriptor outViewDesc; - outViewDesc.m_mipSliceMin = mipLevel - 1; - outViewDesc.m_mipSliceMax = mipLevel - 1; + outViewDesc.m_mipSliceMin = static_cast(mipLevel - 1); + outViewDesc.m_mipSliceMax = static_cast(mipLevel - 1); outBinding.m_unifiedScopeDesc.SetAsImage(outViewDesc); } diff --git a/Gems/Atom/Feature/Common/Code/Source/PostProcessing/BloomDownsamplePass.cpp b/Gems/Atom/Feature/Common/Code/Source/PostProcessing/BloomDownsamplePass.cpp index 1481a7999e..8b824a424d 100644 --- a/Gems/Atom/Feature/Common/Code/Source/PostProcessing/BloomDownsamplePass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/PostProcessing/BloomDownsamplePass.cpp @@ -47,7 +47,7 @@ namespace AZ { RPI::Ptr outAttachment = m_ownedAttachments[0]; - for (uint32_t i = 0; i < Render::Bloom::MaxStageCount; ++i) + for (uint16_t i = 0; i < Render::Bloom::MaxStageCount; ++i) { // Create bindings diff --git a/Gems/Atom/Feature/Common/Code/Source/PostProcessing/TaaPass.cpp b/Gems/Atom/Feature/Common/Code/Source/PostProcessing/TaaPass.cpp index d1f42069fb..779f02cba0 100644 --- a/Gems/Atom/Feature/Common/Code/Source/PostProcessing/TaaPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/PostProcessing/TaaPass.cpp @@ -76,7 +76,7 @@ namespace AZ::Render void TaaPass::FrameBeginInternal(FramePrepareParams params) { RHI::Size inputSize = m_inputColorBinding->m_attachment->m_descriptor.m_image.m_size; - Vector2 rcpInputSize = Vector2(1.0 / inputSize.m_width, 1.0 / inputSize.m_height); + Vector2 rcpInputSize = Vector2(1.0f / inputSize.m_width, 1.0f / inputSize.m_height); RPI::ViewPtr view = GetRenderPipeline()->GetDefaultView(); m_offsetIndex = (m_offsetIndex + 1) % m_subPixelOffsets.size(); diff --git a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp index a6e41a3ce1..276ea7683f 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp @@ -361,7 +361,7 @@ namespace AZ drawRequest.m_listTag = drawListTag; drawRequest.m_pipelineState = pipelineState->GetRHIPipelineState(); drawRequest.m_streamBufferViews = m_reflectionRenderData->m_boxPositionBufferView; - drawRequest.m_stencilRef = stencilRef; + drawRequest.m_stencilRef = static_cast(stencilRef); drawRequest.m_sortKey = m_sortKey; drawPacketBuilder.AddDrawItem(drawRequest); diff --git a/Gems/Atom/Feature/Common/Code/Source/ReflectionScreenSpace/ReflectionScreenSpaceBlurChildPass.cpp b/Gems/Atom/Feature/Common/Code/Source/ReflectionScreenSpace/ReflectionScreenSpaceBlurChildPass.cpp index c3125e0bbe..fce32cf448 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ReflectionScreenSpace/ReflectionScreenSpaceBlurChildPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ReflectionScreenSpace/ReflectionScreenSpaceBlurChildPass.cpp @@ -38,7 +38,7 @@ namespace AZ if (m_imageSize != size) { m_imageSize = size; - m_outputScale = (m_passType == PassType::Vertical) ? pow(2.0f, m_mipLevel) : 1.0f; + m_outputScale = (m_passType == PassType::Vertical) ? static_cast(pow(2.0f, m_mipLevel)) : 1.0f; m_updateSrg = true; } diff --git a/Gems/Atom/Feature/Common/Code/Source/ReflectionScreenSpace/ReflectionScreenSpaceBlurPass.cpp b/Gems/Atom/Feature/Common/Code/Source/ReflectionScreenSpace/ReflectionScreenSpaceBlurPass.cpp index 4f5caca108..394a6fd406 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ReflectionScreenSpace/ReflectionScreenSpaceBlurPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ReflectionScreenSpace/ReflectionScreenSpaceBlurPass.cpp @@ -190,8 +190,8 @@ namespace AZ RPI::PassAttachmentBinding& outputAttachmentBinding = horizontalBlurChildPass->GetInputOutputBinding(1); uint32_t mipLevel = attachmentIndex + 1; RHI::ImageViewDescriptor outputViewDesc; - outputViewDesc.m_mipSliceMin = mipLevel; - outputViewDesc.m_mipSliceMax = mipLevel; + outputViewDesc.m_mipSliceMin = static_cast(mipLevel); + outputViewDesc.m_mipSliceMax = static_cast(mipLevel); outputAttachmentBinding.m_unifiedScopeDesc.SetAsImage(outputViewDesc); outputAttachmentBinding.SetAttachment(reflectionImageAttachment); diff --git a/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshDispatchItem.cpp b/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshDispatchItem.cpp index cd181f7011..bfc533763e 100644 --- a/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshDispatchItem.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshDispatchItem.cpp @@ -205,9 +205,9 @@ namespace AZ if (numThreads) { const auto& args = *numThreads; - arguments.m_threadsPerGroupX = args[0].type() == azrtti_typeid() ? AZStd::any_cast(args[0]) : 1; - arguments.m_threadsPerGroupY = args[1].type() == azrtti_typeid() ? AZStd::any_cast(args[1]) : 1; - arguments.m_threadsPerGroupZ = args[2].type() == azrtti_typeid() ? AZStd::any_cast(args[2]) : 1; + arguments.m_threadsPerGroupX = static_cast(args[0].type() == azrtti_typeid() ? AZStd::any_cast(args[0]) : 1); + arguments.m_threadsPerGroupY = static_cast(args[1].type() == azrtti_typeid() ? AZStd::any_cast(args[1]) : 1); + arguments.m_threadsPerGroupZ = static_cast(args[2].type() == azrtti_typeid() ? AZStd::any_cast(args[2]) : 1); } arguments.m_totalNumberOfThreadsX = xThreads; diff --git a/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshInputBuffers.cpp b/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshInputBuffers.cpp index af427eb554..2f40ea82d8 100644 --- a/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshInputBuffers.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshInputBuffers.cpp @@ -445,7 +445,7 @@ namespace AZ MorphTargetInstanceMetaData instanceMetaData; // Positions start at the beginning of the allocation - instanceMetaData.m_accumulatedPositionDeltaOffsetInBytes = allocation->GetVirtualAddress().m_ptr; + instanceMetaData.m_accumulatedPositionDeltaOffsetInBytes = static_cast(allocation->GetVirtualAddress().m_ptr); uint32_t deltaStreamSizeInBytes = static_cast(vertexCount * MorphTargetConstants::s_unpackedMorphTargetDeltaSizeInBytes); // Followed by normals, tangents, and bitangents diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/ImageProperty.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/ImageProperty.h index 00f329059c..23027083a4 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/ImageProperty.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/ImageProperty.h @@ -183,7 +183,7 @@ namespace AZ else { // Insert intervals by mip level. - for (uint32_t mipLevel = subResourceRange.m_mipSliceMin; mipLevel <= subResourceRange.m_mipSliceMax; ++mipLevel) + for (uint16_t mipLevel = subResourceRange.m_mipSliceMin; mipLevel <= subResourceRange.m_mipSliceMax; ++mipLevel) { m_intervalMap.assign( ConvertSubresourceToIndex(aspect, mipLevel, subResourceRange.m_arraySliceMin), @@ -273,7 +273,7 @@ namespace AZ else { // Traverse one mip level at a time. - for (uint32_t mipLevel = subResourceRange.m_mipSliceMin; mipLevel <= subResourceRange.m_mipSliceMax; ++mipLevel) + for (uint16_t mipLevel = subResourceRange.m_mipSliceMin; mipLevel <= subResourceRange.m_mipSliceMax; ++mipLevel) { getIntervals( ConvertSubresourceToIndex(aspect, mipLevel, subResourceRange.m_arraySliceMin), @@ -332,8 +332,8 @@ namespace AZ { const uint32_t subresourcesPerAspect = m_imageDescriptor.m_mipLevels * m_imageDescriptor.m_arraySize; return ImageSubresource( - (index % subresourcesPerAspect) / m_imageDescriptor.m_arraySize, - (index % subresourcesPerAspect) % m_imageDescriptor.m_arraySize, + static_cast((index % subresourcesPerAspect) / m_imageDescriptor.m_arraySize), + static_cast((index % subresourcesPerAspect) % m_imageDescriptor.m_arraySize), static_cast(index/ subresourcesPerAspect)); } diff --git a/Gems/Atom/RHI/Code/Source/RHI/CpuProfilerImpl.cpp b/Gems/Atom/RHI/Code/Source/RHI/CpuProfilerImpl.cpp index d41b5d656e..8d6be17ad3 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/CpuProfilerImpl.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/CpuProfilerImpl.cpp @@ -320,7 +320,7 @@ namespace AZ m_cachedTimeRegions.clear(); } - timeRegion.m_stackDepth = m_stackLevel; + timeRegion.m_stackDepth = static_cast(m_stackLevel); AZ_Assert(m_timeRegionStack.size() < TimeRegionStackSize, "Adding too many time regions to the stack. Increase the size of TimeRegionStackSize."); m_timeRegionStack.push_back(&timeRegion); diff --git a/Gems/Atom/RHI/Code/Source/RHI/FrameGraph.cpp b/Gems/Atom/RHI/Code/Source/RHI/FrameGraph.cpp index d2298cda3f..ff6ecb4df5 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/FrameGraph.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/FrameGraph.cpp @@ -497,7 +497,7 @@ namespace AZ for (const uint32_t edgeIndex : graphEdges[producerIndex]) { const GraphEdge& graphEdge = m_graphEdges[edgeIndex]; - const uint16_t consumerIndex = graphEdge.m_consumerIndex; + const uint16_t consumerIndex = static_cast(graphEdge.m_consumerIndex); if (--m_graphNodes[consumerIndex].m_unsortedProducerCount == 0) { NodeId newNode; diff --git a/Gems/Atom/RHI/Code/Source/RHI/Image.cpp b/Gems/Atom/RHI/Code/Source/RHI/Image.cpp index acefcca9e7..e864849a30 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/Image.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/Image.cpp @@ -61,7 +61,7 @@ namespace AZ imageStats->m_bindFlags = descriptor.m_bindFlags; ImageSubresourceRange subresourceRange; - subresourceRange.m_mipSliceMin = GetResidentMipLevel(); + subresourceRange.m_mipSliceMin = static_cast(GetResidentMipLevel()); GetSubresourceLayouts(subresourceRange, nullptr, &imageStats->m_sizeInBytes); } diff --git a/Gems/Atom/RHI/Code/Tests/ImagePropertyTests.cpp b/Gems/Atom/RHI/Code/Tests/ImagePropertyTests.cpp index 60d6bfdf96..d53a9d31e6 100644 --- a/Gems/Atom/RHI/Code/Tests/ImagePropertyTests.cpp +++ b/Gems/Atom/RHI/Code/Tests/ImagePropertyTests.cpp @@ -106,7 +106,7 @@ namespace UnitTest range.m_arraySliceMax -= 1; auto overlapInterval = m_property.Get(range); EXPECT_EQ(overlapInterval.size(), m_imageDescriptor.m_mipLevels); - for (uint32_t i = 0; i < overlapInterval.size(); ++i) + for (uint16_t i = 0; i < overlapInterval.size(); ++i) { RHI::ImageSubresourceRange mipRange = range; mipRange.m_mipSliceMin = i; diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI.Reflect/BufferPoolDescriptor.cpp b/Gems/Atom/RHI/DX12/Code/Source/RHI.Reflect/BufferPoolDescriptor.cpp index 0cc8fd0202..5007b21976 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI.Reflect/BufferPoolDescriptor.cpp +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI.Reflect/BufferPoolDescriptor.cpp @@ -26,7 +26,7 @@ namespace AZ BufferPoolDescriptor::BufferPoolDescriptor() { - m_bufferPoolPageSizeInBytes = RHI::RHISystemInterface::Get()->GetPlatformLimitsDescriptor()->m_platformDefaultValues.m_bufferPoolPageSizeInBytes; + m_bufferPoolPageSizeInBytes = static_cast(RHI::RHISystemInterface::Get()->GetPlatformLimitsDescriptor()->m_platformDefaultValues.m_bufferPoolPageSizeInBytes); } } } diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/BufferPool.cpp b/Gems/Atom/RHI/DX12/Code/Source/RHI/BufferPool.cpp index 680669776c..c7b78a3945 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI/BufferPool.cpp +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/BufferPool.cpp @@ -203,7 +203,7 @@ namespace AZ RHI::HeapMemoryUsage& heapMemoryUsage = m_memoryUsage.GetHeapMemoryUsage(descriptorBase.m_heapMemoryLevel); - uint32_t bufferPageSize = RHI::RHISystemInterface::Get()->GetPlatformLimitsDescriptor()->m_platformDefaultValues.m_bufferPoolPageSizeInBytes; + uint32_t bufferPageSize = static_cast(RHI::RHISystemInterface::Get()->GetPlatformLimitsDescriptor()->m_platformDefaultValues.m_bufferPoolPageSizeInBytes); // The DX12 descriptor provides an explicit buffer page size override. if (const DX12::BufferPoolDescriptor* descriptor = azrtti_cast(&descriptorBase)) diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/Conversions.cpp b/Gems/Atom/RHI/DX12/Code/Source/RHI/Conversions.cpp index 98dc2965fb..6018e180ef 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI/Conversions.cpp +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/Conversions.cpp @@ -1264,7 +1264,7 @@ namespace AZ dst.BlendOpAlpha = ConvertBlendOp(src.m_blendAlphaOp); dst.DestBlend = ConvertBlendFactor(src.m_blendDest); dst.DestBlendAlpha = ConvertBlendFactor(src.m_blendAlphaDest); - dst.RenderTargetWriteMask = ConvertColorWriteMask(src.m_writeMask); + dst.RenderTargetWriteMask = ConvertColorWriteMask(static_cast(src.m_writeMask)); dst.SrcBlend = ConvertBlendFactor(src.m_blendSource); dst.SrcBlendAlpha = ConvertBlendFactor(src.m_blendAlphaSource); dst.LogicOp = D3D12_LOGIC_OP_CLEAR; @@ -1399,8 +1399,8 @@ namespace AZ desc.DepthFunc = ConvertComparisonFunc(depthStencil.m_depth.m_func); desc.DepthWriteMask = ConvertDepthWriteMask(depthStencil.m_depth.m_writeMask); desc.StencilEnable = depthStencil.m_stencil.m_enable; - desc.StencilReadMask = depthStencil.m_stencil.m_readMask; - desc.StencilWriteMask = depthStencil.m_stencil.m_writeMask; + desc.StencilReadMask = static_cast(depthStencil.m_stencil.m_readMask); + desc.StencilWriteMask = static_cast(depthStencil.m_stencil.m_writeMask); return desc; } } diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/Device.cpp b/Gems/Atom/RHI/DX12/Code/Source/RHI/Device.cpp index 9d23dfa43d..722952bc6d 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI/Device.cpp +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/Device.cpp @@ -80,8 +80,8 @@ namespace AZ StagingMemoryAllocator::Descriptor allocatorDesc; allocatorDesc.m_device = this; - allocatorDesc.m_mediumPageSizeInBytes = RHI::RHISystemInterface::Get()->GetPlatformLimitsDescriptor()->m_platformDefaultValues.m_mediumStagingBufferPageSizeInBytes; - allocatorDesc.m_largePageSizeInBytes = RHI::RHISystemInterface::Get()->GetPlatformLimitsDescriptor()->m_platformDefaultValues.m_largestStagingBufferPageSizeInBytes; + allocatorDesc.m_mediumPageSizeInBytes = static_cast(RHI::RHISystemInterface::Get()->GetPlatformLimitsDescriptor()->m_platformDefaultValues.m_mediumStagingBufferPageSizeInBytes); + allocatorDesc.m_largePageSizeInBytes = static_cast(RHI::RHISystemInterface::Get()->GetPlatformLimitsDescriptor()->m_platformDefaultValues.m_largestStagingBufferPageSizeInBytes); allocatorDesc.m_collectLatency = descriptor.m_frameCountMax; m_stagingMemoryAllocator.Init(allocatorDesc); } diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/PipelineLayout.cpp b/Gems/Atom/RHI/DX12/Code/Source/RHI/PipelineLayout.cpp index 1336642d8b..3fdeec1c51 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI/PipelineLayout.cpp +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/PipelineLayout.cpp @@ -139,8 +139,8 @@ namespace AZ const RHI::ShaderResourceGroupLayout& groupLayout = *descriptor.GetShaderResourceGroupLayout(groupLayoutIndex); const uint32_t srgLayoutSlot = groupLayout.GetBindingSlot(); - m_slotToIndexTable[srgLayoutSlot] = groupLayoutIndex; - m_indexToSlotTable[groupLayoutIndex] = srgLayoutSlot; + m_slotToIndexTable[srgLayoutSlot] = static_cast(groupLayoutIndex); + m_indexToSlotTable[groupLayoutIndex] = static_cast(srgLayoutSlot); } // Construct a list of indexes sorted by frequency. diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/StreamingImagePool.cpp b/Gems/Atom/RHI/DX12/Code/Source/RHI/StreamingImagePool.cpp index 6f35bb32ae..b6c4c029cf 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI/StreamingImagePool.cpp +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/StreamingImagePool.cpp @@ -129,7 +129,7 @@ namespace AZ residentImageDescriptor.m_size = imageDescriptor.m_size.GetReducedMip(residentMipLevel); residentImageDescriptor.m_size.m_width = RHI::AlignUp(residentImageDescriptor.m_size.m_width, alignment); residentImageDescriptor.m_size.m_height = RHI::AlignUp(residentImageDescriptor.m_size.m_height, alignment); - residentImageDescriptor.m_mipLevels = imageDescriptor.m_mipLevels - residentMipLevel; + residentImageDescriptor.m_mipLevels = static_cast(imageDescriptor.m_mipLevels - residentMipLevel); D3D12_RESOURCE_ALLOCATION_INFO allocationInfo; GetDevice().GetImageAllocationInfo(residentImageDescriptor, allocationInfo); diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI.Reflect/BufferPoolDescriptor.cpp b/Gems/Atom/RHI/Metal/Code/Source/RHI.Reflect/BufferPoolDescriptor.cpp index 160dce12d5..c80b04bc73 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI.Reflect/BufferPoolDescriptor.cpp +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI.Reflect/BufferPoolDescriptor.cpp @@ -26,7 +26,7 @@ namespace AZ BufferPoolDescriptor::BufferPoolDescriptor() { - m_bufferPoolPageSizeInBytes = RHI::RHISystemInterface::Get()->GetPlatformLimitsDescriptor()->m_platformDefaultValues.m_bufferPoolPageSizeInBytes; + m_bufferPoolPageSizeInBytes = static_cast(RHI::RHISystemInterface::Get()->GetPlatformLimitsDescriptor()->m_platformDefaultValues.m_bufferPoolPageSizeInBytes); } } } diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/AsyncUploadQueue.cpp b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/AsyncUploadQueue.cpp index 18b5d83ed3..0d947085ba 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/AsyncUploadQueue.cpp +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/AsyncUploadQueue.cpp @@ -173,7 +173,7 @@ namespace AZ auto* image = static_cast(request.m_image); auto& device = static_cast(GetDevice()); - const uint16_t startMip = residentMip - 1; + const uint16_t startMip = static_cast(residentMip - 1); const uint16_t endMip = static_cast(residentMip - request.m_mipSlices.size()); RHI::Ptr uploadFence = Fence::Create(); @@ -277,7 +277,7 @@ namespace AZ copyDescriptor.m_sourceSize.m_depth = 1; copyDescriptor.m_destinationImage = image; copyDescriptor.m_destinationSubresource.m_mipSlice = curMip; - copyDescriptor.m_destinationSubresource.m_arraySlice = arraySlice; + copyDescriptor.m_destinationSubresource.m_arraySlice = static_cast(arraySlice); copyDescriptor.m_destinationOrigin.m_left = 0; copyDescriptor.m_destinationOrigin.m_top = 0; copyDescriptor.m_destinationOrigin.m_front = depth; @@ -309,7 +309,7 @@ namespace AZ copyDescriptor.m_sourceSize.m_depth = 1; copyDescriptor.m_destinationImage = image; copyDescriptor.m_destinationSubresource.m_mipSlice = curMip; - copyDescriptor.m_destinationSubresource.m_arraySlice = arraySlice; + copyDescriptor.m_destinationSubresource.m_arraySlice = static_cast(arraySlice); copyDescriptor.m_destinationOrigin.m_left = 0; copyDescriptor.m_destinationOrigin.m_top = 0; copyDescriptor.m_destinationOrigin.m_front = depth; diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Conversion.cpp b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Conversion.cpp index 18ddc0f4df..d5671cff05 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Conversion.cpp +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Conversion.cpp @@ -257,7 +257,7 @@ namespace AZ state.srcAlphaBlendFactor = ConvertBlendFactor(targetBlendState.m_blendAlphaSource); state.dstAlphaBlendFactor = ConvertBlendFactor(targetBlendState.m_blendAlphaDest); state.alphaBlendOp = ConvertBlendOp(targetBlendState.m_blendAlphaOp); - state.colorWriteMask = ConvertComponentFlags(targetBlendState.m_writeMask); + state.colorWriteMask = ConvertComponentFlags(static_cast(targetBlendState.m_writeMask)); } VkBlendFactor ConvertBlendFactor(const RHI::BlendFactor& blendFactor) diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/ImageView.cpp b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/ImageView.cpp index d4697cbd32..44c36f5c70 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/ImageView.cpp +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/ImageView.cpp @@ -117,8 +117,8 @@ namespace AZ const auto& device = static_cast(GetDevice()); const auto& physicalDevice = static_cast(GetDevice().GetPhysicalDevice()); - const uint16_t width = imgDesc.m_size.m_width; - const uint16_t height = imgDesc.m_size.m_height; + const uint16_t width = static_cast(imgDesc.m_size.m_width); + const uint16_t height = static_cast(imgDesc.m_size.m_height); const uint16_t depth = AZStd::min(static_cast(imgViewDesc.m_depthSliceMax - imgViewDesc.m_depthSliceMin), static_cast(imgDesc.m_size.m_depth - 1)) + 1; const uint16_t samples = imgDesc.m_multisampleState.m_samples; const uint16_t arrayLayers = AZStd::min(static_cast(imgViewDesc.m_arraySliceMax - imgViewDesc.m_arraySliceMin), static_cast(imgDesc.m_arraySize - 1)) + 1; @@ -233,7 +233,7 @@ namespace AZ // https://www.khronos.org/registry/vulkan/specs/1.1/html/chap11.html#VkImageSubresourceRange { range.m_arraySliceMin = descriptor.m_depthSliceMin; - range.m_arraySliceMax = AZStd::GetMin(descriptor.m_depthSliceMax, imageDesc.m_size.m_depth - 1); + range.m_arraySliceMax = AZStd::GetMin(descriptor.m_depthSliceMax, static_cast(imageDesc.m_size.m_depth - 1)); break; } case VK_IMAGE_VIEW_TYPE_3D: diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/PipelineLayout.cpp b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/PipelineLayout.cpp index 5c7a78fd89..f627ddf2cc 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/PipelineLayout.cpp +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/PipelineLayout.cpp @@ -134,7 +134,7 @@ namespace AZ uint32_t bindingSlot = srgLayout->GetBindingSlot(); m_indexToSlot[bindingInfo.m_spaceId].set(bindingSlot); - m_slotToIndex[bindingSlot] = bindingInfo.m_spaceId; + m_slotToIndex[bindingSlot] = static_cast(bindingInfo.m_spaceId); } m_descriptorSetLayouts.reserve(srgCount); diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/StreamingImagePool.cpp b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/StreamingImagePool.cpp index 9189c2e177..586470da0a 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/StreamingImagePool.cpp +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/StreamingImagePool.cpp @@ -108,7 +108,7 @@ namespace AZ WaitFinishUploading(image); - const uint16_t residentMipLevelBefore = image.GetResidentMipLevel(); + const uint16_t residentMipLevelBefore = static_cast(image.GetResidentMipLevel()); const uint16_t residentMipLevelAfter = residentMipLevelBefore - static_cast(request.m_mipSlices.size()); const VkMemoryRequirements memoryRequirements = GetMemoryRequirements(image.GetDescriptor(), residentMipLevelAfter); @@ -149,11 +149,11 @@ namespace AZ // Set streamed mip level to target mip level. if (image.GetStreamedMipLevel() < targetMipLevel) { - image.SetStreamedMipLevel(targetMipLevel); + image.SetStreamedMipLevel(static_cast(targetMipLevel)); } const VkMemoryRequirements memoryRequirements = GetMemoryRequirements(image.GetDescriptor(), targetMipLevel); - const uint16_t residentMipLevelBefore = image.GetResidentMipLevel(); + const uint16_t residentMipLevelBefore = static_cast(image.GetResidentMipLevel()); RHI::HeapMemoryUsage& memoryUsage = m_memoryUsage.GetHeapMemoryUsage(RHI::HeapMemoryLevel::Device); const size_t imageSizeBefore = image.GetResidentSizeInBytes(); @@ -203,7 +203,7 @@ namespace AZ residentImageDescriptor.m_size = imageDescriptor.m_size.GetReducedMip(residentMipLevel); residentImageDescriptor.m_size.m_width = RHI::AlignUp(residentImageDescriptor.m_size.m_width, alignment); residentImageDescriptor.m_size.m_height = RHI::AlignUp(residentImageDescriptor.m_size.m_height, alignment); - residentImageDescriptor.m_mipLevels = imageDescriptor.m_mipLevels - residentMipLevel; + residentImageDescriptor.m_mipLevels = imageDescriptor.m_mipLevels - static_cast(residentMipLevel); return device.GetImageMemoryRequirements(imageDescriptor); } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Image/StreamingImage.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Image/StreamingImage.cpp index 45070371d6..8629588ea2 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Image/StreamingImage.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Image/StreamingImage.cpp @@ -247,7 +247,7 @@ namespace AZ uint16_t StreamingImage::GetResidentMipLevel() { - return m_image->GetResidentMipLevel(); + return static_cast(m_image->GetResidentMipLevel()); } RHI::ResultCode StreamingImage::TrimToMipChainLevel(size_t mipChainIndex) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/FullscreenTrianglePass.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/FullscreenTrianglePass.cpp index 94421e2ca4..8a4206f0d8 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/FullscreenTrianglePass.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/FullscreenTrianglePass.cpp @@ -155,7 +155,7 @@ namespace AZ m_item.m_arguments = RHI::DrawArguments(draw); m_item.m_pipelineState = m_shader->AcquirePipelineState(pipelineStateDescriptor); - m_item.m_stencilRef = m_stencilRef; + m_item.m_stencilRef = static_cast(m_stencilRef); } void FullscreenTrianglePass::FrameBeginInternal(FramePrepareParams params) diff --git a/Gems/Atom/RPI/Code/Tests/Buffer/BufferTests.cpp b/Gems/Atom/RPI/Code/Tests/Buffer/BufferTests.cpp index 3b113b78f8..f648de6997 100644 --- a/Gems/Atom/RPI/Code/Tests/Buffer/BufferTests.cpp +++ b/Gems/Atom/RPI/Code/Tests/Buffer/BufferTests.cpp @@ -67,7 +67,8 @@ namespace UnitTest bufferData.resize(bufferSize); // The actual data doesn't matter - for (uint32_t i = 0; i < bufferData.size(); ++i) + const uint8_t bufferDataSize = static_cast(bufferData.size()); + for (uint8_t i = 0; i < bufferDataSize; ++i) { bufferData[i] = i; } diff --git a/Gems/Atom/RPI/Code/Tests/Model/ModelTests.cpp b/Gems/Atom/RPI/Code/Tests/Model/ModelTests.cpp index 21f3239698..ff998ad4d3 100644 --- a/Gems/Atom/RPI/Code/Tests/Model/ModelTests.cpp +++ b/Gems/Atom/RPI/Code/Tests/Model/ModelTests.cpp @@ -38,7 +38,8 @@ namespace UnitTest bufferData.resize(bufferSize); //The actual data doesn't matter - for (uint32_t i = 0; i < bufferData.size(); ++i) + const uint8_t bufferDataSize = static_cast(bufferData.size()); + for (uint8_t i = 0; i < bufferDataSize; ++i) { bufferData[i] = i; } diff --git a/Gems/Atom/Utils/Code/Source/ImageComparison.cpp b/Gems/Atom/Utils/Code/Source/ImageComparison.cpp index e226d0b2b4..a17d07ed3f 100644 --- a/Gems/Atom/Utils/Code/Source/ImageComparison.cpp +++ b/Gems/Atom/Utils/Code/Source/ImageComparison.cpp @@ -67,9 +67,9 @@ namespace AZ { // We use the max error from a single channel instead of accumulating the error from each channel. // This normalizes differences so that for example black vs red has the same weight as black vs yellow. - const int16_t diffR = abs(aznumeric_cast(bufferA[i]) - aznumeric_cast(bufferB[i])); - const int16_t diffG = abs(aznumeric_cast(bufferA[i + 1]) - aznumeric_cast(bufferB[i + 1])); - const int16_t diffB = abs(aznumeric_cast(bufferA[i + 2]) - aznumeric_cast(bufferB[i + 2])); + const int16_t diffR = static_cast(abs(aznumeric_cast(bufferA[i]) - aznumeric_cast(bufferB[i]))); + const int16_t diffG = static_cast(abs(aznumeric_cast(bufferA[i + 1]) - aznumeric_cast(bufferB[i + 1]))); + const int16_t diffB = static_cast(abs(aznumeric_cast(bufferA[i + 2]) - aznumeric_cast(bufferB[i + 2]))); const int16_t maxDiff = AZ::GetMax(AZ::GetMax(diffR, diffG), diffB); const float finalDiffNormalized = maxDiff / 255.0f; From b3e895d10c697354ee6a9580f533494a722b3a1f Mon Sep 17 00:00:00 2001 From: pappeste Date: Fri, 25 Jun 2021 16:21:12 -0700 Subject: [PATCH 407/803] =?UTF-8?q?=EF=BB=BFfixed=20AtomLyIntegration?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp | 6 +++--- .../AtomFont/Code/Source/FontRenderer.cpp | 4 ++-- .../AtomFont/Code/Source/FontTexture.cpp | 10 +++++----- .../AtomFont/Code/Source/GlyphBitmap.cpp | 2 +- .../Source/AtomViewportDisplayInfoSystemComponent.cpp | 2 +- .../Source/CoreLights/AreaLightComponentController.cpp | 4 ++-- .../CoreLights/DirectionalLightComponentController.cpp | 3 ++- .../Code/Source/CoreLights/DiskLightDelegate.cpp | 4 ++-- .../Code/Source/Mesh/MeshComponentController.cpp | 2 +- 9 files changed, 19 insertions(+), 18 deletions(-) diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp b/Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp index 9317cae846..a29815f08c 100644 --- a/Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp +++ b/Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp @@ -1070,7 +1070,7 @@ int AZ::FFont::CreateQuadsForText(const RHI::Viewport& viewport, float x, float uint32_t packedColor = 0xffffffff; { ColorB tempColor = color; - tempColor.a = ((uint32_t) tempColor.a * alphaBlend) >> 8; + tempColor.a = static_cast(((uint32_t) tempColor.a * alphaBlend) >> 8); packedColor = tempColor.pack_argb8888(); //note: this ends up in r,g,b,a order on little-endian machines } @@ -1220,7 +1220,7 @@ void AZ::FFont::WrapText(AZStd::string& result, float maxWidth, const char* str, if (ctx.m_processSpecialChars && ch == '$') { ++pChar; - char nextChar = *pChar; + char nextChar = static_cast(*pChar); if (isdigit(nextChar) || nextChar == 'O' || nextChar == 'o') { @@ -1516,7 +1516,7 @@ bool AZ::FFont::InitCache() char* p = buf; // precache all [normal] printable characters to the string (missing ones are updated on demand) - for (int i = first; i <= last; ++i) + for (char i = first; i <= last; ++i) { *p++ = i; } diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Source/FontRenderer.cpp b/Gems/AtomLyIntegration/AtomFont/Code/Source/FontRenderer.cpp index 8c023f9353..053a2eb419 100644 --- a/Gems/AtomLyIntegration/AtomFont/Code/Source/FontRenderer.cpp +++ b/Gems/AtomLyIntegration/AtomFont/Code/Source/FontRenderer.cpp @@ -235,12 +235,12 @@ int AZ::FontRenderer::GetGlyph(GlyphBitmap* glyphBitmap, int* horizontalAdvance, if (glyphWidth) { - *glyphWidth = m_glyph->bitmap.width; + *glyphWidth = static_cast(m_glyph->bitmap.width); } if (glyphHeight) { - *glyphHeight = m_glyph->bitmap.rows; + *glyphHeight = static_cast(m_glyph->bitmap.rows); } unsigned char* buffer = glyphBitmap->GetBuffer(); diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Source/FontTexture.cpp b/Gems/AtomLyIntegration/AtomFont/Code/Source/FontTexture.cpp index 1ee7f80eda..773b19e740 100644 --- a/Gems/AtomLyIntegration/AtomFont/Code/Source/FontTexture.cpp +++ b/Gems/AtomLyIntegration/AtomFont/Code/Source/FontTexture.cpp @@ -496,8 +496,8 @@ int AZ::FontTexture::UpdateSlot(int slotIndex, uint16_t slotUsage, uint32_t char return 0; } - slot->m_characterWidth = width; - slot->m_characterHeight = height; + slot->m_characterWidth = static_cast(width); + slot->m_characterHeight = static_cast(height); // Add a pixel along width and height to avoid artifacts being rendered // from a previous glyph in this slot due to bilinear filtering. The source @@ -519,8 +519,8 @@ void AZ::FontTexture::CreateGradientSlot() assert(slot->m_currentCharacter == (uint32_t)~0); // 0 needs to be unused spot slot->Reset(); - slot->m_characterWidth = m_cellWidth - 2; - slot->m_characterHeight = m_cellHeight - 2; + slot->m_characterWidth = static_cast(m_cellWidth - 2); + slot->m_characterHeight = static_cast(m_cellHeight - 2); slot->SetNotReusable(); int x = slot->m_textureSlot % m_widthCellCount; @@ -533,7 +533,7 @@ void AZ::FontTexture::CreateGradientSlot() { for (uint32_t dwX = 0; dwX < slot->m_characterWidth; ++dwX) { - buffer[dwX + dwY * m_width] = dwY * 255 / (slot->m_characterHeight - 1); + buffer[dwX + dwY * m_width] = static_cast(dwY * 255 / (slot->m_characterHeight - 1)); } } } diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Source/GlyphBitmap.cpp b/Gems/AtomLyIntegration/AtomFont/Code/Source/GlyphBitmap.cpp index 09bc27783b..395a161b83 100644 --- a/Gems/AtomLyIntegration/AtomFont/Code/Source/GlyphBitmap.cpp +++ b/Gems/AtomLyIntegration/AtomFont/Code/Source/GlyphBitmap.cpp @@ -118,7 +118,7 @@ int AZ::GlyphBitmap::Blur(AZ::FontSmoothAmount smoothAmount) colorSum += m_buffer[yOffset + x]; } - m_buffer[yOffset + x] = colorSum >> 2; + m_buffer[yOffset + x] = static_cast(colorSum >> 2); } } } diff --git a/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.cpp b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.cpp index 40c4f8e48f..c1f459e1ee 100644 --- a/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.cpp +++ b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.cpp @@ -135,7 +135,7 @@ namespace AZ::Render return; } - m_fpsInterval = AZStd::chrono::seconds(r_fpsCalcInterval); + m_fpsInterval = AZStd::chrono::seconds(static_cast(r_fpsCalcInterval)); UpdateFramerate(); diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.cpp index b90b145320..0a5598a74a 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.cpp @@ -535,7 +535,7 @@ namespace AZ::Render void AreaLightComponentController::SetPredictionSampleCount(uint32_t count) { - m_configuration.m_predictionSampleCount = count; + m_configuration.m_predictionSampleCount = static_cast(count); if (m_lightShapeDelegate) { m_lightShapeDelegate->SetPredictionSampleCount(count); @@ -549,7 +549,7 @@ namespace AZ::Render void AreaLightComponentController::SetFilteringSampleCount(uint32_t count) { - m_configuration.m_filteringSampleCount = count; + m_configuration.m_filteringSampleCount = static_cast(count); if (m_lightShapeDelegate) { m_lightShapeDelegate->SetFilteringSampleCount(count); diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DirectionalLightComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DirectionalLightComponentController.cpp index 031d935513..642e50d104 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DirectionalLightComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DirectionalLightComponentController.cpp @@ -259,7 +259,8 @@ namespace AZ void DirectionalLightComponentController::SetCascadeCount(uint32_t cascadeCount) { - const uint16_t cascadeCount16 = cascadeCount = GetMin(Shadow::MaxNumberOfCascades, GetMax(1, aznumeric_cast(cascadeCount))); + const uint16_t cascadeCount16 = GetMin(static_cast(Shadow::MaxNumberOfCascades), GetMax(1, aznumeric_cast(cascadeCount))); + cascadeCount = cascadeCount16; m_configuration.m_cascadeCount = cascadeCount16; if (m_featureProcessor) { diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.cpp index c6e4441d57..91856f7ee5 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.cpp @@ -159,7 +159,7 @@ namespace AZ::Render { if (GetShadowsEnabled() && GetLightHandle().IsValid()) { - GetFeatureProcessor()->SetPredictionSampleCount(GetLightHandle(), count); + GetFeatureProcessor()->SetPredictionSampleCount(GetLightHandle(), static_cast(count)); } } @@ -167,7 +167,7 @@ namespace AZ::Render { if (GetShadowsEnabled() && GetLightHandle().IsValid()) { - GetFeatureProcessor()->SetFilteringSampleCount(GetLightHandle(), count); + GetFeatureProcessor()->SetFilteringSampleCount(GetLightHandle(), static_cast(count)); } } diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp index 68276a7320..bb38f932fb 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp @@ -442,7 +442,7 @@ namespace AZ RPI::Cullable::LodOverride MeshComponentController::GetLodOverride() const { - return m_meshFeatureProcessor->GetSortKey(m_meshHandle); + return static_cast(m_meshFeatureProcessor->GetSortKey(m_meshHandle)); } void MeshComponentController::SetVisibility(bool visible) From 0fae5d0aa0c3c4a99213cf1f3b1a509739a7aa3d Mon Sep 17 00:00:00 2001 From: pappeste Date: Fri, 25 Jun 2021 16:27:59 -0700 Subject: [PATCH 408/803] =?UTF-8?q?=EF=BB=BFAWSGameLift?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../Source/Activity/AWSGameLiftCreateSessionActivity.cpp | 2 +- .../Source/Activity/AWSGameLiftCreateSessionOnQueueActivity.cpp | 2 +- .../Source/Activity/AWSGameLiftJoinSessionActivity.cpp | 2 +- .../Source/Activity/AWSGameLiftSearchSessionsActivity.cpp | 2 +- .../Code/AWSGameLiftServer/Source/AWSGameLiftServerManager.cpp | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftCreateSessionActivity.cpp b/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftCreateSessionActivity.cpp index 667a8de679..16d0cf4241 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftCreateSessionActivity.cpp +++ b/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftCreateSessionActivity.cpp @@ -48,7 +48,7 @@ namespace AWSGameLift { request.SetFleetId(createSessionRequest.m_fleetId.c_str()); } - request.SetMaximumPlayerSessionCount(createSessionRequest.m_maxPlayer); + request.SetMaximumPlayerSessionCount(static_cast(createSessionRequest.m_maxPlayer)); AZ_TracePrintf(AWSGameLiftCreateSessionActivityName, "Built CreateGameSessionRequest with CreatorId=%s, Name=%s, IdempotencyToken=%s, GameProperties=%s, AliasId=%s, FleetId=%s and MaximumPlayerSessionCount=%d", diff --git a/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftCreateSessionOnQueueActivity.cpp b/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftCreateSessionOnQueueActivity.cpp index a8a393aa18..1ac9c7db1c 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftCreateSessionOnQueueActivity.cpp +++ b/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftCreateSessionOnQueueActivity.cpp @@ -33,7 +33,7 @@ namespace AWSGameLift // Required attributes request.SetGameSessionQueueName(createSessionOnQueueRequest.m_queueName.c_str()); - request.SetMaximumPlayerSessionCount(createSessionOnQueueRequest.m_maxPlayer); + request.SetMaximumPlayerSessionCount(static_cast(createSessionOnQueueRequest.m_maxPlayer)); request.SetPlacementId(createSessionOnQueueRequest.m_placementId.c_str()); AZ_TracePrintf(AWSGameLiftCreateSessionOnQueueActivityName, diff --git a/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftJoinSessionActivity.cpp b/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftJoinSessionActivity.cpp index d54907aa71..a47e59255f 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftJoinSessionActivity.cpp +++ b/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftJoinSessionActivity.cpp @@ -47,7 +47,7 @@ namespace AWSGameLift //sessionConnectionConfig.m_dnsName = createPlayerSessionResult.GetPlayerSession().GetDnsName().c_str(); sessionConnectionConfig.m_ipAddress = createPlayerSessionResult.GetPlayerSession().GetIpAddress().c_str(); sessionConnectionConfig.m_playerSessionId = createPlayerSessionResult.GetPlayerSession().GetPlayerSessionId().c_str(); - sessionConnectionConfig.m_port = createPlayerSessionResult.GetPlayerSession().GetPort(); + sessionConnectionConfig.m_port = static_cast(createPlayerSessionResult.GetPlayerSession().GetPort()); AZ_TracePrintf(AWSGameLiftJoinSessionActivityName, "Built SessionConnectionConfig with IpAddress=%s, PlayerSessionId=%s and Port=%d", diff --git a/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftSearchSessionsActivity.cpp b/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftSearchSessionsActivity.cpp index ec592735ae..3d29fa2b71 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftSearchSessionsActivity.cpp +++ b/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftSearchSessionsActivity.cpp @@ -99,7 +99,7 @@ namespace AWSGameLift session.m_currentPlayer = gameSession.GetCurrentPlayerSessionCount(); session.m_ipAddress = gameSession.GetIpAddress().c_str(); session.m_maxPlayer = gameSession.GetMaximumPlayerSessionCount(); - session.m_port = gameSession.GetPort(); + session.m_port = static_cast(gameSession.GetPort()); session.m_sessionId = gameSession.GetGameSessionId().c_str(); session.m_sessionName = gameSession.GetName().c_str(); session.m_status = AWSGameLiftSessionStatusNames[(int)gameSession.GetStatus()]; diff --git a/Gems/AWSGameLift/Code/AWSGameLiftServer/Source/AWSGameLiftServerManager.cpp b/Gems/AWSGameLift/Code/AWSGameLiftServer/Source/AWSGameLiftServerManager.cpp index f98ae7b6f1..94d6a7dac1 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftServer/Source/AWSGameLiftServerManager.cpp +++ b/Gems/AWSGameLift/Code/AWSGameLiftServer/Source/AWSGameLiftServerManager.cpp @@ -70,7 +70,7 @@ namespace AWSGameLift sessionConfig.m_ipAddress = gameSession.GetIpAddress().c_str(); sessionConfig.m_maxPlayer = gameSession.GetMaximumPlayerSessionCount(); sessionConfig.m_sessionName = gameSession.GetName().c_str(); - sessionConfig.m_port = gameSession.GetPort(); + sessionConfig.m_port = static_cast(gameSession.GetPort()); sessionConfig.m_status = AWSGameLiftSessionStatusNames[(int)gameSession.GetStatus()]; AZ_TracePrintf(AWSGameLiftServerManagerName, From c14c23c9c76f63e59d5bcf3d0c86af4ab74872fa Mon Sep 17 00:00:00 2001 From: pappeste Date: Fri, 25 Jun 2021 16:28:13 -0700 Subject: [PATCH 409/803] AWSMetrics Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Gems/AWSMetrics/Code/Source/ClientConfiguration.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/AWSMetrics/Code/Source/ClientConfiguration.cpp b/Gems/AWSMetrics/Code/Source/ClientConfiguration.cpp index eabac5a5c3..13cbf924c3 100644 --- a/Gems/AWSMetrics/Code/Source/ClientConfiguration.cpp +++ b/Gems/AWSMetrics/Code/Source/ClientConfiguration.cpp @@ -99,7 +99,7 @@ namespace AWSMetrics AZ::s64 ClientConfiguration::GetMaxQueueSizeInBytes() const { - return m_maxQueueSizeInMb * 1000000; + return static_cast(m_maxQueueSizeInMb * 1000000); } AZ::s64 ClientConfiguration::GetQueueFlushPeriodInSeconds() const From bed57208da52648913cd7442f5cb9b12213ca208 Mon Sep 17 00:00:00 2001 From: pappeste Date: Fri, 25 Jun 2021 16:29:00 -0700 Subject: [PATCH 410/803] =?UTF-8?q?=EF=BB=BFEMotionFX?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../EMotionFX/Code/EMotionFX/Source/AnimGraphBindPoseNode.h | 4 ++-- Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphMotionNode.h | 4 ++-- .../Code/EMotionFX/Source/BlendTreeBlend2NodeBase.h | 4 ++-- Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlendNNode.h | 4 ++-- .../Code/EMotionFX/Source/BlendTreeFloatConditionNode.h | 4 ++-- .../Code/EMotionFX/Source/BlendTreeTwoLinkIKNode.h | 4 ++-- .../StandardPlugins/Source/NodeWindow/NodeGroupInfo.cpp | 2 +- Gems/EMotionFX/Code/Tests/AnimGraphDeferredInitTests.cpp | 6 +++--- Gems/EMotionFX/Code/Tests/BlendTreeBlendNNodeTests.cpp | 6 +++--- Gems/EMotionFX/Code/Tests/BlendTreeMaskNodeTests.cpp | 2 +- Gems/EMotionFX/Code/Tests/BoolLogicNodeTests.cpp | 4 ++-- .../Code/Tests/Vector2ToVector3CompatibilityTests.cpp | 4 ++-- 12 files changed, 24 insertions(+), 24 deletions(-) diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphBindPoseNode.h b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphBindPoseNode.h index 042799192d..2d83d21d0d 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphBindPoseNode.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphBindPoseNode.h @@ -28,12 +28,12 @@ namespace EMotionFX AZ_CLASS_ALLOCATOR_DECL // - enum + enum : uint16 { OUTPUTPORT_RESULT = 0 }; - enum + enum : uint16 { PORTID_OUTPUT_POSE = 0 }; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphMotionNode.h b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphMotionNode.h index a07bbc625c..692b81b70e 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphMotionNode.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphMotionNode.h @@ -32,7 +32,7 @@ namespace EMotionFX AZ_RTTI(AnimGraphMotionNode, "{B8B8AAE6-E532-4BF8-898F-3D40AA41BC82}", AnimGraphNode) AZ_CLASS_ALLOCATOR_DECL - enum + enum : uint16 { INPUTPORT_PLAYSPEED = 0, INPUTPORT_INPLACE = 1, @@ -41,7 +41,7 @@ namespace EMotionFX OUTPUTPORT_MOTION = 1 }; - enum + enum : uint16 { PORTID_INPUT_PLAYSPEED = 0, PORTID_INPUT_INPLACE = 1, diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlend2NodeBase.h b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlend2NodeBase.h index 9a9b51b5d1..991fb03472 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlend2NodeBase.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlend2NodeBase.h @@ -26,7 +26,7 @@ namespace EMotionFX using WeightedMaskEntry = AZStd::pair; - enum + enum : uint16 { INPUTPORT_POSE_A = 0, INPUTPORT_POSE_B = 1, @@ -34,7 +34,7 @@ namespace EMotionFX OUTPUTPORT_POSE = 0 }; - enum + enum : uint16 { PORTID_INPUT_POSE_A = 0, PORTID_INPUT_POSE_B = 1, diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlendNNode.h b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlendNNode.h index 72d6ad120c..4f4b8a7ac3 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlendNNode.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlendNNode.h @@ -49,7 +49,7 @@ namespace EMotionFX AZ_RTTI(BlendTreeBlendNNode, "{CBFFDE41-008D-45A1-AC2A-E9A25C8CE62A}", AnimGraphNode) AZ_CLASS_ALLOCATOR_DECL - enum + enum : uint16 { INPUTPORT_POSE_0 = 0, INPUTPORT_POSE_1 = 1, @@ -65,7 +65,7 @@ namespace EMotionFX OUTPUTPORT_POSE = 0 }; - enum + enum : uint16 { PORTID_INPUT_POSE_0 = 0, PORTID_INPUT_POSE_1 = 1, diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeFloatConditionNode.h b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeFloatConditionNode.h index 756f6a4bab..fc922934ed 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeFloatConditionNode.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeFloatConditionNode.h @@ -26,7 +26,7 @@ namespace EMotionFX AZ_CLASS_ALLOCATOR_DECL // - enum + enum : uint16 { INPUTPORT_X = 0, INPUTPORT_Y = 1, @@ -34,7 +34,7 @@ namespace EMotionFX OUTPUTPORT_BOOL = 1 }; - enum + enum : uint16 { PORTID_INPUT_X = 0, PORTID_INPUT_Y = 1, diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeTwoLinkIKNode.h b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeTwoLinkIKNode.h index e39cd7258e..29b497457e 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeTwoLinkIKNode.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeTwoLinkIKNode.h @@ -27,7 +27,7 @@ namespace EMotionFX AZ_RTTI(BlendTreeTwoLinkIKNode, "{0C3E8B7F-F810-47A6-B1A9-27BD4E4B5500}", AnimGraphNode) AZ_CLASS_ALLOCATOR_DECL - enum + enum : uint16 { INPUTPORT_POSE = 0, INPUTPORT_GOALPOS = 1, @@ -37,7 +37,7 @@ namespace EMotionFX OUTPUTPORT_POSE = 0 }; - enum + enum : uint16 { PORTID_INPUT_POSE = 0, PORTID_INPUT_GOALPOS = 1, diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/NodeGroupInfo.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/NodeGroupInfo.cpp index f25158ae0d..06b87c2bc2 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/NodeGroupInfo.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/NodeGroupInfo.cpp @@ -26,7 +26,7 @@ namespace EMStudio const size_t numGroupNodes = nodeGroup->GetNumNodes(); for (size_t j = 0; j < numGroupNodes; ++j) { - const uint16 nodeIndex = nodeGroup->GetNode(j); + const uint16 nodeIndex = nodeGroup->GetNode(static_cast(j)); const EMotionFX::Node* node = actor->GetSkeleton()->GetNode(nodeIndex); m_nodes.emplace_back(node->GetNameString()); } diff --git a/Gems/EMotionFX/Code/Tests/AnimGraphDeferredInitTests.cpp b/Gems/EMotionFX/Code/Tests/AnimGraphDeferredInitTests.cpp index aa1bde295a..710cfb790e 100644 --- a/Gems/EMotionFX/Code/Tests/AnimGraphDeferredInitTests.cpp +++ b/Gems/EMotionFX/Code/Tests/AnimGraphDeferredInitTests.cpp @@ -126,8 +126,8 @@ namespace EMotionFX blendNNode->SetName(blendNNodeName); blendTree->AddChildNode(blendNNode); - const int motionNodeCount = 5; - for (AZ::u32 i = 0; i < motionNodeCount; ++i) + const uint16 motionNodeCount = 5; + for (uint16 i = 0; i < motionNodeCount; ++i) { AnimGraphMotionNode* motionNode = aznew AnimGraphMotionNode(); motionNode->SetName(AZStd::string::format("Motion %i (%s)", i, blendNNodeName).c_str()); @@ -172,7 +172,7 @@ namespace EMotionFX finalNode->AddConnection(blendNNode, BlendTreeBlendNNode::PORTID_OUTPUT_POSE, BlendTreeFinalNode::PORTID_INPUT_POSE); // Creates 5x blend N nodes as input for the blend N node created here. Each of these five blend N nodes have 5x input motions. - for (AZ::u32 i = 0; i < 5; ++i) + for (uint16 i = 0; i < 5; ++i) { BlendTreeBlendNNode* inputNode = CreateBlendNNode(testBlendTree, parameterNode, AZStd::string::format("InputBlendNode%i", i).c_str()); blendNNode->AddConnection(inputNode, AnimGraphMotionNode::PORTID_OUTPUT_POSE, i); diff --git a/Gems/EMotionFX/Code/Tests/BlendTreeBlendNNodeTests.cpp b/Gems/EMotionFX/Code/Tests/BlendTreeBlendNNodeTests.cpp index 1f9fb9cae3..1f5fb9a512 100644 --- a/Gems/EMotionFX/Code/Tests/BlendTreeBlendNNodeTests.cpp +++ b/Gems/EMotionFX/Code/Tests/BlendTreeBlendNNodeTests.cpp @@ -51,8 +51,8 @@ namespace EMotionFX m_blendTree->AddChildNode(finalNode); finalNode->AddConnection(m_blendNNode, BlendTreeBlendNNode::PORTID_OUTPUT_POSE, BlendTreeFinalNode::PORTID_INPUT_POSE); - const int motionNodeCount = 3; - for (int i = 0; i < motionNodeCount; ++i) + const uint16 motionNodeCount = 3; + for (uint16 i = 0; i < motionNodeCount; ++i) { AnimGraphMotionNode* motionNode = aznew AnimGraphMotionNode(); m_blendTree->AddChildNode(motionNode); @@ -213,7 +213,7 @@ namespace EMotionFX finalNode->AddConnection(m_blendNNode, BlendTreeBlendNNode::PORTID_OUTPUT_POSE, BlendTreeFinalNode::PORTID_INPUT_POSE); ASSERT_TRUE(param.m_motionNodeCount <= 10) << "The blend N node only has 10 pose inputs."; - for (AZ::u32 i = 0; i < param.m_motionNodeCount; ++i) + for (uint16 i = 0; i < param.m_motionNodeCount; ++i) { AnimGraphMotionNode* motionNode = aznew AnimGraphMotionNode(); m_blendTree->AddChildNode(motionNode); diff --git a/Gems/EMotionFX/Code/Tests/BlendTreeMaskNodeTests.cpp b/Gems/EMotionFX/Code/Tests/BlendTreeMaskNodeTests.cpp index b86041c7aa..8bd66ced88 100644 --- a/Gems/EMotionFX/Code/Tests/BlendTreeMaskNodeTests.cpp +++ b/Gems/EMotionFX/Code/Tests/BlendTreeMaskNodeTests.cpp @@ -173,7 +173,7 @@ namespace EMotionFX m_blendTree->AddChildNode(m_basePoseNode); m_maskNode->AddConnection(m_basePoseNode, BlendTreeTestInputNode::OUTPUTPORT_RESULT, BlendTreeMaskNode::INPUTPORT_BASEPOSE); - for (AZ::u32 i = 0; i < m_numMaskInputNodes; ++i) + for (uint16 i = 0; i < m_numMaskInputNodes; ++i) { BlendTreeTestInputNode* inputNode = aznew BlendTreeTestInputNode(static_cast(i)); m_blendTree->AddChildNode(inputNode); diff --git a/Gems/EMotionFX/Code/Tests/BoolLogicNodeTests.cpp b/Gems/EMotionFX/Code/Tests/BoolLogicNodeTests.cpp index 6214005a71..dbf9f18e9e 100644 --- a/Gems/EMotionFX/Code/Tests/BoolLogicNodeTests.cpp +++ b/Gems/EMotionFX/Code/Tests/BoolLogicNodeTests.cpp @@ -53,8 +53,8 @@ namespace EMotionFX m_blendTree->AddChildNode(finalNode); finalNode->AddConnection(m_blendNNode, BlendTreeBlendNNode::PORTID_OUTPUT_POSE, BlendTreeFinalNode::PORTID_INPUT_POSE); - const int motionNodeCount = 2; - for (int i = 0; i < motionNodeCount; ++i) + const uint16 motionNodeCount = 2; + for (uint16 i = 0; i < motionNodeCount; ++i) { AnimGraphMotionNode* motionNode = aznew AnimGraphMotionNode(); m_blendTree->AddChildNode(motionNode); diff --git a/Gems/EMotionFX/Code/Tests/Vector2ToVector3CompatibilityTests.cpp b/Gems/EMotionFX/Code/Tests/Vector2ToVector3CompatibilityTests.cpp index 26702af550..d5ce41cfeb 100644 --- a/Gems/EMotionFX/Code/Tests/Vector2ToVector3CompatibilityTests.cpp +++ b/Gems/EMotionFX/Code/Tests/Vector2ToVector3CompatibilityTests.cpp @@ -46,8 +46,8 @@ namespace EMotionFX m_blendTree->AddChildNode(finalNode); finalNode->AddUnitializedConnection(m_blendNNode, BlendTreeBlendNNode::PORTID_OUTPUT_POSE, BlendTreeFinalNode::PORTID_INPUT_POSE); - const int motionNodeCount = 3; - for (int i = 0; i < motionNodeCount; ++i) + const uint16 motionNodeCount = 3; + for (uint16 i = 0; i < motionNodeCount; ++i) { AnimGraphMotionNode* motionNode = aznew AnimGraphMotionNode(); m_blendTree->AddChildNode(motionNode); From 48fcd462c69114e3f5bc92265b35325284651b58 Mon Sep 17 00:00:00 2001 From: pappeste Date: Fri, 25 Jun 2021 16:29:20 -0700 Subject: [PATCH 411/803] FastNoise Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Gems/FastNoise/Code/External/FastNoise/FastNoise.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gems/FastNoise/Code/External/FastNoise/FastNoise.cpp b/Gems/FastNoise/Code/External/FastNoise/FastNoise.cpp index 51980ca08a..443fe0ce72 100644 --- a/Gems/FastNoise/Code/External/FastNoise/FastNoise.cpp +++ b/Gems/FastNoise/Code/External/FastNoise/FastNoise.cpp @@ -201,14 +201,14 @@ void FastNoise::SetSeed(int seed) std::mt19937_64 gen(seed); - for (int i = 0; i < 256; i++) + for (unsigned char i = 0; i < 256; i++) m_perm[i] = i; for (int j = 0; j < 256; j++) { int rng = (int)(gen() % (256 - j)); int k = rng + j; - int l = m_perm[j]; + unsigned char l = m_perm[j]; m_perm[j] = m_perm[j + 256] = m_perm[k]; m_perm[k] = l; m_perm12[j] = m_perm12[j + 256] = m_perm[j] % 12; From 4ee9adf522de2dfde166beb51498d8647d2d93f8 Mon Sep 17 00:00:00 2001 From: pappeste Date: Fri, 25 Jun 2021 16:34:20 -0700 Subject: [PATCH 412/803] GraphCanvas Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../Nodes/Group/NodeGroupFrameComponent.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Gems/GraphCanvas/Code/Source/Components/Nodes/Group/NodeGroupFrameComponent.cpp b/Gems/GraphCanvas/Code/Source/Components/Nodes/Group/NodeGroupFrameComponent.cpp index fa265ad644..c317e8044a 100644 --- a/Gems/GraphCanvas/Code/Source/Components/Nodes/Group/NodeGroupFrameComponent.cpp +++ b/Gems/GraphCanvas/Code/Source/Components/Nodes/Group/NodeGroupFrameComponent.cpp @@ -2493,18 +2493,18 @@ namespace GraphCanvas { if (growOnly) { - int left = blockBoundingRect.left(); + int left = static_cast(blockBoundingRect.left()); if (left >= calculatedBounds.left()) { - left = calculatedBounds.left() - gridStep.GetX(); + left = static_cast(calculatedBounds.left() - gridStep.GetX()); } - int right = blockBoundingRect.right(); + int right = static_cast(blockBoundingRect.right()); if (right <= calculatedBounds.right()) { - right = calculatedBounds.right() + gridStep.GetX(); + right = static_cast(calculatedBounds.right() + gridStep.GetX()); } blockBoundingRect.setX(left); @@ -2521,18 +2521,18 @@ namespace GraphCanvas { if (growOnly) { - int top = blockBoundingRect.top(); + int top = static_cast(blockBoundingRect.top()); if (top >= calculatedBounds.top()) { - top = calculatedBounds.top() - gridStep.GetY(); + top = static_cast(calculatedBounds.top() - gridStep.GetY()); } - int bottom = blockBoundingRect.bottom(); + int bottom = static_cast(blockBoundingRect.bottom()); if (bottom <= calculatedBounds.bottom()) { - bottom = calculatedBounds.bottom() + gridStep.GetY(); + bottom = static_cast(calculatedBounds.bottom() + gridStep.GetY()); } blockBoundingRect.setY(top); From 23b2a51757b1a96fd2d57ab74f639033b16ad0b9 Mon Sep 17 00:00:00 2001 From: pappeste Date: Fri, 25 Jun 2021 16:34:48 -0700 Subject: [PATCH 413/803] ImGui Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../Code/Source/LYCommonMenu/ImGuiLYEntityOutliner.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Gems/ImGui/Code/Source/LYCommonMenu/ImGuiLYEntityOutliner.cpp b/Gems/ImGui/Code/Source/LYCommonMenu/ImGuiLYEntityOutliner.cpp index 8e0e23652c..7f4877347f 100644 --- a/Gems/ImGui/Code/Source/LYCommonMenu/ImGuiLYEntityOutliner.cpp +++ b/Gems/ImGui/Code/Source/LYCommonMenu/ImGuiLYEntityOutliner.cpp @@ -770,8 +770,8 @@ namespace ImGui { AZStd::string name1 = com1->RTTI_GetTypeName(); AZStd::string name2 = com2->RTTI_GetTypeName(); - AZStd::transform(name1.begin(), name1.end(), name1.begin(), ::tolower); - AZStd::transform(name2.begin(), name2.end(), name2.begin(), ::tolower); + AZStd::to_lower(name1.begin(), name1.end()); + AZStd::to_lower(name2.begin(), name2.end()); return name1 < name2; }; AZStd::sort(components.begin(), components.end(), sortByComponentName); @@ -1017,8 +1017,8 @@ namespace ImGui AZStd::string name1, name2; AZ::ComponentApplicationBus::BroadcastResult(name1, &AZ::ComponentApplicationBus::Events::GetEntityName, ent1->m_entityId); AZ::ComponentApplicationBus::BroadcastResult(name2, &AZ::ComponentApplicationBus::Events::GetEntityName, ent2->m_entityId); - AZStd::transform(name1.begin(), name1.end(), name1.begin(), ::tolower); - AZStd::transform(name2.begin(), name2.end(), name2.begin(), ::tolower); + AZStd::to_lower(name1.begin(), name1.end()); + AZStd::to_lower(name2.begin(), name2.end()); return name1 < name2; }; AZStd::sort(entityInfo->m_children.begin(), entityInfo->m_children.end(), sortByEntityName); From 4a3d438c22dae4ca5d209753a73a7b2ae3e73f1c Mon Sep 17 00:00:00 2001 From: pappeste Date: Fri, 25 Jun 2021 16:35:06 -0700 Subject: [PATCH 414/803] =?UTF-8?q?=EF=BB=BFLyShine?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Gems/LyShine/Code/Source/Animation/2DSpline.h | 2 +- Gems/LyShine/Code/Source/LyShineDebug.cpp | 2 +- Gems/LyShine/Code/Source/RenderGraph.cpp | 6 +++--- Gems/LyShine/Code/Source/Sprite.cpp | 2 +- Gems/LyShine/Code/Source/UiImageComponent.cpp | 20 +++++++++---------- .../Source/UiParticleEmitterComponent.cpp | 4 ++-- Gems/LyShine/Code/Source/UiTextComponent.cpp | 2 +- 7 files changed, 19 insertions(+), 19 deletions(-) diff --git a/Gems/LyShine/Code/Source/Animation/2DSpline.h b/Gems/LyShine/Code/Source/Animation/2DSpline.h index 60589e1344..b831bd669a 100644 --- a/Gems/LyShine/Code/Source/Animation/2DSpline.h +++ b/Gems/LyShine/Code/Source/Animation/2DSpline.h @@ -62,7 +62,7 @@ namespace UiSpline ILINE void flag_clr(int flag) { m_flags &= ~flag; }; ILINE int flag(int flag) { return m_flags & flag; }; - ILINE void ORT(int ort) { m_ORT = ort; }; + ILINE void ORT(int ort) { m_ORT = static_cast(ort); }; ILINE int ORT() const { return m_ORT; }; ILINE int isORT(int o) const { return (m_ORT == o); }; diff --git a/Gems/LyShine/Code/Source/LyShineDebug.cpp b/Gems/LyShine/Code/Source/LyShineDebug.cpp index c7dccc162f..a30f816c73 100644 --- a/Gems/LyShine/Code/Source/LyShineDebug.cpp +++ b/Gems/LyShine/Code/Source/LyShineDebug.cpp @@ -115,7 +115,7 @@ static int Create2DTexture(int width, int height, byte* data, ETEX_Format format static AZ::Vector2 GetTextureSize(AZ::Data::Instance image) { AZ::RHI::Size size = image->GetDescriptor().m_size; - return AZ::Vector2(size.m_width, size.m_height); + return AZ::Vector2(static_cast(size.m_width), static_cast(size.m_height)); } #endif diff --git a/Gems/LyShine/Code/Source/RenderGraph.cpp b/Gems/LyShine/Code/Source/RenderGraph.cpp index b07aab78c7..85f9c7deb5 100644 --- a/Gems/LyShine/Code/Source/RenderGraph.cpp +++ b/Gems/LyShine/Code/Source/RenderGraph.cpp @@ -386,7 +386,7 @@ namespace LyShine curBaseState.m_stencilState.m_backFace = stencilOpState; // set up for stencil write - dynamicDraw->SetStencilReference(uiRenderer->GetStencilRef()); + dynamicDraw->SetStencilReference(static_cast(uiRenderer->GetStencilRef())); curBaseState.m_stencilState.m_enable = true; curBaseState.m_stencilState.m_writeMask = 0xFF; } @@ -420,7 +420,7 @@ namespace LyShine uiRenderer->DecrementStencilRef(); } - dynamicDraw->SetStencilReference(uiRenderer->GetStencilRef()); + dynamicDraw->SetStencilReference(static_cast(uiRenderer->GetStencilRef())); if (firstPass) { @@ -790,7 +790,7 @@ namespace LyShine { for (int i = 0; i < primitive->m_numVertices; ++i) { - primitive->m_vertices[i].texIndex = texUnit; + primitive->m_vertices[i].texIndex = static_cast(texUnit); } } diff --git a/Gems/LyShine/Code/Source/Sprite.cpp b/Gems/LyShine/Code/Source/Sprite.cpp index a097e23dfe..7f293e57a3 100644 --- a/Gems/LyShine/Code/Source/Sprite.cpp +++ b/Gems/LyShine/Code/Source/Sprite.cpp @@ -368,7 +368,7 @@ AZ::Vector2 CSprite::GetSize() } AZ::RHI::Size size = image->GetRHIImage()->GetDescriptor().m_size; - return AZ::Vector2(size.m_width, size.m_height); + return AZ::Vector2(static_cast(size.m_width), static_cast(size.m_height)); } else { diff --git a/Gems/LyShine/Code/Source/UiImageComponent.cpp b/Gems/LyShine/Code/Source/UiImageComponent.cpp index 83c184cfc8..d279beeee9 100644 --- a/Gems/LyShine/Code/Source/UiImageComponent.cpp +++ b/Gems/LyShine/Code/Source/UiImageComponent.cpp @@ -1666,7 +1666,7 @@ void UiImageComponent::RenderRadialFilledQuad(const AZ::Vector2* positions, cons const int numIndices = 15; uint16 indices[numIndices]; - for (int ix = 0; ix < 5; ++ix) + for (uint16 ix = 0; ix < 5; ++ix) { indices[ix * 3 + firstIndexOffset] = ix + 1; indices[ix * 3 + secondIndexOffset] = ix + 2; @@ -2268,20 +2268,20 @@ int UiImageComponent::ClipToLine(const SVF_P2F_C4B_T2F_F4B* vertices, const uint int indicesAdded = 0; if (verticesAdded == 3) { - renderIndices[renderIndexOffset] = vertexOffset - 3; - renderIndices[renderIndexOffset + 1] = vertexOffset - 2; - renderIndices[renderIndexOffset + 2] = vertexOffset - 1; + renderIndices[renderIndexOffset] = static_cast(vertexOffset - 3); + renderIndices[renderIndexOffset + 1] = static_cast(vertexOffset - 2); + renderIndices[renderIndexOffset + 2] = static_cast(vertexOffset - 1); indicesAdded = 3; } else if (verticesAdded == 4) { - renderIndices[renderIndexOffset] = vertexOffset - 4; - renderIndices[renderIndexOffset + 1] = vertexOffset - 3; - renderIndices[renderIndexOffset + 2] = vertexOffset - 2; + renderIndices[renderIndexOffset] = static_cast(vertexOffset - 4); + renderIndices[renderIndexOffset + 1] = static_cast(vertexOffset - 3); + renderIndices[renderIndexOffset + 2] = static_cast(vertexOffset - 2); - renderIndices[renderIndexOffset + 3] = vertexOffset - 4; - renderIndices[renderIndexOffset + 4] = vertexOffset - 2; - renderIndices[renderIndexOffset + 5] = vertexOffset - 1; + renderIndices[renderIndexOffset + 3] = static_cast(vertexOffset - 4); + renderIndices[renderIndexOffset + 4] = static_cast(vertexOffset - 2); + renderIndices[renderIndexOffset + 5] = static_cast(vertexOffset - 1); indicesAdded = 6; } diff --git a/Gems/LyShine/Code/Source/UiParticleEmitterComponent.cpp b/Gems/LyShine/Code/Source/UiParticleEmitterComponent.cpp index a8b678947b..0adf2fb2de 100644 --- a/Gems/LyShine/Code/Source/UiParticleEmitterComponent.cpp +++ b/Gems/LyShine/Code/Source/UiParticleEmitterComponent.cpp @@ -1825,8 +1825,8 @@ void UiParticleEmitterComponent::ResetParticleBuffers() } m_cachedPrimitive.m_indices = new uint16[numIndices]; - const int verticesPerParticle = 4; - int baseIndex = 0; + const uint16 verticesPerParticle = 4; + uint16 baseIndex = 0; for (AZ::u32 i = 0; i < numIndices; i += indicesPerParticle) { m_cachedPrimitive.m_indices[i + 0] = 0 + baseIndex; diff --git a/Gems/LyShine/Code/Source/UiTextComponent.cpp b/Gems/LyShine/Code/Source/UiTextComponent.cpp index 35f351a9e6..a996a489cc 100644 --- a/Gems/LyShine/Code/Source/UiTextComponent.cpp +++ b/Gems/LyShine/Code/Source/UiTextComponent.cpp @@ -1096,7 +1096,7 @@ UiTextComponent::InlineImage::InlineImage(const AZStd::string& texturePathname, if (m_texture) { AZ::RHI::Size size = m_texture->GetDescriptor().m_size; - m_size = AZ::Vector2(size.m_width, size.m_height); + m_size = AZ::Vector2(static_cast(size.m_width), static_cast(size.m_height)); } } From 90527649801736ac8830a5faae9a025179f8a1f0 Mon Sep 17 00:00:00 2001 From: pappeste Date: Fri, 25 Jun 2021 16:35:25 -0700 Subject: [PATCH 415/803] =?UTF-8?q?=EF=BB=BFMultiplayer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../Source/Components/LocalPredictionPlayerInputComponent.cpp | 2 +- Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp b/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp index 72f5aa8e1c..de4ea67467 100644 --- a/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp @@ -464,7 +464,7 @@ namespace Multiplayer { // Clamp to oldest element if history is too small const int64_t historyIndex = AZStd::max(inputHistorySize - 1 - i, 0); - inputArray[i] = m_inputHistory[historyIndex]; + inputArray[static_cast(i)] = m_inputHistory[historyIndex]; } #ifndef AZ_RELEASE_BUILD diff --git a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp index 61dbf9289f..497d35db7e 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp +++ b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp @@ -1006,7 +1006,7 @@ namespace Multiplayer const char* addressStr = mutableAddress; const char* portStr = &(mutableAddress[portSeparator + 1]); int32_t portNumber = atol(portStr); - AZ::Interface::Get()->Connect(addressStr, portNumber); + AZ::Interface::Get()->Connect(addressStr, static_cast(portNumber)); } } AZ_CONSOLEFREEFUNC(connect, AZ::ConsoleFunctorFlags::DontReplicate, "Opens a multiplayer connection to a remote host"); From 2943f16d111f2e5c49f5701e22fb71fb8de60d7a Mon Sep 17 00:00:00 2001 From: pappeste Date: Fri, 25 Jun 2021 16:37:59 -0700 Subject: [PATCH 416/803] PhysX Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Gems/PhysX/Code/Source/System/PhysXSystem.cpp | 4 ++-- Gems/PhysX/Code/Source/SystemComponent.cpp | 2 +- Gems/PhysX/Code/Tests/PhysXSceneTests.cpp | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Gems/PhysX/Code/Source/System/PhysXSystem.cpp b/Gems/PhysX/Code/Source/System/PhysXSystem.cpp index cc55255e24..0c3e6d0b31 100644 --- a/Gems/PhysX/Code/Source/System/PhysXSystem.cpp +++ b/Gems/PhysX/Code/Source/System/PhysXSystem.cpp @@ -251,7 +251,7 @@ namespace PhysX if (sceneItr != m_sceneList.end()) { - return AzPhysics::SceneHandle((*sceneItr)->GetId(), AZStd::distance(m_sceneList.begin(), sceneItr)); + return AzPhysics::SceneHandle((*sceneItr)->GetId(), static_cast(AZStd::distance(m_sceneList.begin(), sceneItr))); } return AzPhysics::InvalidSceneHandle; } @@ -312,7 +312,7 @@ namespace PhysX { m_sceneRemovedEvent.Signal(handle); m_sceneList[index].reset(); - m_freeSceneSlots.push(index); + m_freeSceneSlots.push(static_cast(index)); } } } diff --git a/Gems/PhysX/Code/Source/SystemComponent.cpp b/Gems/PhysX/Code/Source/SystemComponent.cpp index d8c4b47a2a..42c78d2c1d 100644 --- a/Gems/PhysX/Code/Source/SystemComponent.cpp +++ b/Gems/PhysX/Code/Source/SystemComponent.cpp @@ -396,7 +396,7 @@ namespace PhysX void SystemComponent::SetCollisionLayerName(int index, const AZStd::string& layerName) { - m_physXSystem->SetCollisionLayerName(aznumeric_cast(index), layerName); + m_physXSystem->SetCollisionLayerName(aznumeric_cast(index), layerName); } void SystemComponent::CreateCollisionGroup(const AZStd::string& groupName, const AzPhysics::CollisionGroup& group) diff --git a/Gems/PhysX/Code/Tests/PhysXSceneTests.cpp b/Gems/PhysX/Code/Tests/PhysXSceneTests.cpp index ff112a75dd..5b90ef0004 100644 --- a/Gems/PhysX/Code/Tests/PhysXSceneTests.cpp +++ b/Gems/PhysX/Code/Tests/PhysXSceneTests.cpp @@ -94,7 +94,7 @@ namespace PhysX //invalid scene handle returns empty AzPhysics::SimulatedBodyHandleList emptyBodies = sceneInterface->AddSimulatedBodies(AzPhysics::InvalidSceneHandle, configs); EXPECT_TRUE(emptyBodies.empty()); - emptyBodies = sceneInterface->AddSimulatedBodies(AzPhysics::SceneHandle(2347892347890, 7), configs); + emptyBodies = sceneInterface->AddSimulatedBodies(AzPhysics::SceneHandle(static_cast(2347892347890), AzPhysics::SceneIndex(7)), configs); EXPECT_TRUE(emptyBodies.empty()); //add some rigid bodies @@ -165,7 +165,7 @@ namespace PhysX //invalid scene handle returns null AzPhysics::SimulatedBody* nullBody = sceneInterface->GetSimulatedBodyFromHandle(AzPhysics::InvalidSceneHandle, newBodies[0]); EXPECT_TRUE(nullBody == nullptr); - nullBody = sceneInterface->GetSimulatedBodyFromHandle(AzPhysics::SceneHandle(2347892347890, 7), newBodies[0]); + nullBody = sceneInterface->GetSimulatedBodyFromHandle(AzPhysics::SceneHandle(static_cast(2347892347890), AzPhysics::SceneIndex(7)), newBodies[0]); EXPECT_TRUE(nullBody == nullptr); //invalid simulated body handle returns null From b52516cdecd91f1717c57a24eafea95eaa5f85ef Mon Sep 17 00:00:00 2001 From: pappeste Date: Fri, 25 Jun 2021 16:40:27 -0700 Subject: [PATCH 417/803] =?UTF-8?q?=EF=BB=BFScripCanvas?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Datum.cpp | 2 +- .../Execution/Interpreted/ExecutionInterpretedEBusAPI.cpp | 4 ++-- .../Code/Include/ScriptCanvas/Libraries/Math/AABBNodes.h | 2 +- .../Code/Include/ScriptCanvas/Libraries/Math/TransformNodes.h | 4 ++-- .../Include/ScriptCanvas/Libraries/Spawning/SpawnNodeable.cpp | 2 +- .../Include/ScriptCanvas/Libraries/Time/DelayNodeable.cpp | 4 ++-- .../Include/ScriptCanvas/Libraries/Time/DurationNodeable.cpp | 2 +- .../Code/Tests/ScriptCanvas_NodeGenerics.cpp | 2 +- 8 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Datum.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Datum.cpp index e4569af820..4dae63d71b 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Datum.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Datum.cpp @@ -2219,7 +2219,7 @@ namespace ScriptCanvas const_cast(this)->InitializeOverloadedStorage(Data::FromAZType(description.m_typeId), eOriginality::Copy); - if (!Data::IsValueType(m_type) && !SatisfiesTraits(description.m_traits)) + if (!Data::IsValueType(m_type) && !SatisfiesTraits(static_cast(description.m_traits))) { return AZ::Failure(AZStd::string("Attempting to convert null value to BehaviorValueParameter that expects reference or value")); } diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/Interpreted/ExecutionInterpretedEBusAPI.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/Interpreted/ExecutionInterpretedEBusAPI.cpp index 64553ed5e0..d33f78c8b4 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/Interpreted/ExecutionInterpretedEBusAPI.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/Interpreted/ExecutionInterpretedEBusAPI.cpp @@ -116,7 +116,7 @@ namespace ScriptCanvas auto nodeable = AZ::ScriptValue::StackRead(lua, k_nodeableIndex); AZ_Assert(nodeable, "Failed to read EBusHandler"); - const int eventIndex = lua_tointeger(lua, k_eventNameIndex); + const int eventIndex = static_cast(lua_tointeger(lua, k_eventNameIndex)); AZ_Assert(eventIndex != -1, "Event index was not found for %s", nodeable->GetEBusName().data()); // install the generic hook for the event nodeable->HandleEvent(eventIndex); @@ -143,7 +143,7 @@ namespace ScriptCanvas auto nodeable = AZ::ScriptValue::StackRead(lua, k_nodeableIndex); AZ_Assert(nodeable, "Failed to read EBusHandler"); - const int eventIndex = lua_tointeger(lua, k_eventNameIndex); + const int eventIndex = static_cast(lua_tointeger(lua, k_eventNameIndex)); AZ_Assert(eventIndex != -1, "Event index was not found for %s", nodeable->GetEBusName().data()); // install the generic hook for the event nodeable->HandleEvent(eventIndex); diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Math/AABBNodes.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Math/AABBNodes.h index ec44953ba9..198ff0c421 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Math/AABBNodes.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Math/AABBNodes.h @@ -92,7 +92,7 @@ namespace ScriptCanvas AZ_INLINE AABBType FromCenterRadius(const Vector3Type center, const NumberType radius) { - return AABBType::CreateCenterRadius(center, radius); + return AABBType::CreateCenterRadius(center, static_cast(radius)); } SCRIPT_CANVAS_GENERIC_FUNCTION_NODE(FromCenterRadius, k_categoryName, "{5FEFD1BF-DC5B-4AFA-892F-082D92492548}", "returns the AABB with Min = Center - Vector3(radius, radius, radius), Max = Center + Vector3(radius, radius, radius)", "Center", "Radius"); diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Math/TransformNodes.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Math/TransformNodes.h index f2088dbf6d..8af9ee8ca2 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Math/TransformNodes.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Math/TransformNodes.h @@ -55,7 +55,7 @@ namespace ScriptCanvas AZ_INLINE TransformType FromScale(NumberType scale) { - return TransformType::CreateUniformScale(scale); + return TransformType::CreateUniformScale(static_cast(scale)); } SCRIPT_CANVAS_GENERIC_FUNCTION_NODE(FromScale, k_categoryName, "{4B6454BC-015C-41BB-9C78-34ADBCF70187}", "returns a transform which applies the specified uniform Scale, but no rotation or translation", "Scale"); @@ -143,7 +143,7 @@ namespace ScriptCanvas AZ_INLINE TransformType MultiplyByUniformScale(TransformType source, NumberType scale) { - source.MultiplyByUniformScale(scale); + source.MultiplyByUniformScale(static_cast(scale)); return source; } SCRIPT_CANVAS_GENERIC_FUNCTION_NODE(MultiplyByUniformScale, k_categoryName, "{90472D62-65A8-40C1-AB08-FA66D793F689}", "returns Source multiplied uniformly by Scale", "Source", "Scale"); diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Spawning/SpawnNodeable.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Spawning/SpawnNodeable.cpp index 4c92c9408a..d11e916d42 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Spawning/SpawnNodeable.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Spawning/SpawnNodeable.cpp @@ -114,7 +114,7 @@ namespace ScriptCanvas::Nodeables::Spawning AZ::Vector3 rotationCopy = rotation; AZ::Quaternion rotationQuat = AZ::Quaternion::CreateFromEulerAnglesDegrees(rotationCopy); - entityTransform->SetWorldTM(AZ::Transform(translation, rotationQuat, scale)); + entityTransform->SetWorldTM(AZ::Transform(translation, rotationQuat, static_cast(scale))); } }; diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Time/DelayNodeable.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Time/DelayNodeable.cpp index 168b6d825a..179c5b008a 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Time/DelayNodeable.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Time/DelayNodeable.cpp @@ -82,12 +82,12 @@ namespace ScriptCanvas void DelayNodeable::Reset(Data::NumberType countdownSeconds, Data::BooleanType looping, Data::NumberType holdTime) { - InitiateCountdown(true, countdownSeconds, looping, holdTime); + InitiateCountdown(true, static_cast(countdownSeconds), looping, static_cast(holdTime)); } void DelayNodeable::Start(Data::NumberType countdownSeconds, Data::BooleanType looping, Data::NumberType holdTime) { - InitiateCountdown(false, countdownSeconds, looping, holdTime); + InitiateCountdown(false, static_cast(countdownSeconds), looping, static_cast(holdTime)); } } } diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Time/DurationNodeable.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Time/DurationNodeable.cpp index 942271ad3a..5c281c55fe 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Time/DurationNodeable.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Time/DurationNodeable.cpp @@ -47,7 +47,7 @@ namespace ScriptCanvas void DurationNodeable::Start(Data::NumberType duration) { m_elapsedTime = 0.0f; - m_duration = duration; + m_duration = static_cast(duration); AZ::TickBus::Handler::BusConnect(); } } diff --git a/Gems/ScriptCanvasTesting/Code/Tests/ScriptCanvas_NodeGenerics.cpp b/Gems/ScriptCanvasTesting/Code/Tests/ScriptCanvas_NodeGenerics.cpp index 09ebd3d360..f6e5b361f4 100644 --- a/Gems/ScriptCanvasTesting/Code/Tests/ScriptCanvas_NodeGenerics.cpp +++ b/Gems/ScriptCanvasTesting/Code/Tests/ScriptCanvas_NodeGenerics.cpp @@ -110,7 +110,7 @@ namespace ScriptCanvas AZ_INLINE AZ::Vector3 NormalizeWithDefault(const AZ::Vector3& source, const Data::NumberType tolerance, [[maybe_unused]] const Data::BooleanType fakeValueForTestingDefault) { AZ_TracePrintf("SC", "The fake value for testing default is %s\n", fakeValueForTestingDefault ? "True" : "False"); - return source.GetNormalizedSafe(tolerance); + return source.GetNormalizedSafe(static_cast(tolerance)); } void NormalizeWithDefaultInputOverrides(Node& node) { SetDefaultValuesByIndex< 1, 2 >::_(node, 3.3, true); } From 63f36dfe706362af781799bf9adcafeb082ad3a8 Mon Sep 17 00:00:00 2001 From: pappeste Date: Fri, 25 Jun 2021 16:44:13 -0700 Subject: [PATCH 418/803] LauncherUnified Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/LauncherUnified/Platform/Windows/Launcher_Windows.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Code/LauncherUnified/Platform/Windows/Launcher_Windows.cpp b/Code/LauncherUnified/Platform/Windows/Launcher_Windows.cpp index 44426f6d01..d1e6a69e5e 100644 --- a/Code/LauncherUnified/Platform/Windows/Launcher_Windows.cpp +++ b/Code/LauncherUnified/Platform/Windows/Launcher_Windows.cpp @@ -73,8 +73,8 @@ void CVar_OnViewportPosition(const AZ::Vector2& value) if (HWND windowHandle = GetActiveWindow()) { SetWindowPos(windowHandle, nullptr, - value.GetX(), - value.GetY(), + static_cast(value.GetX()), + static_cast(value.GetY()), 0, 0, SWP_NOOWNERZORDER | SWP_NOSIZE); } } From b0456691c7517db5d5c21abfb89d5d695cd15c37 Mon Sep 17 00:00:00 2001 From: pappeste Date: Fri, 25 Jun 2021 16:44:29 -0700 Subject: [PATCH 419/803] FbxSceneBuilder Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../SceneBuilder/Importers/AssImpAnimationImporter.cpp | 6 +++--- .../SceneBuilder/Importers/AssImpSkinWeightsImporter.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpAnimationImporter.cpp b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpAnimationImporter.cpp index a76cb3531d..16f8d85509 100644 --- a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpAnimationImporter.cpp +++ b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpAnimationImporter.cpp @@ -49,7 +49,7 @@ namespace AZ double totalFramesAtDefaultTimeStep = totalTicks / AssImpAnimationImporter::s_defaultTimeStepBetweenFrames + 1; if (!AZ::IsClose(totalFramesAtDefaultTimeStep, numKeys, 1)) { - numKeys = AZStd::ceilf(static_cast(totalFramesAtDefaultTimeStep)); + numKeys = static_cast(AZStd::ceilf(static_cast(totalFramesAtDefaultTimeStep))); } return numKeys; } @@ -122,7 +122,7 @@ namespace AZ if (keys[lastIndex + 1].mTime != keys[lastIndex].mTime) { normalizedTimeBetweenFrames = - (time - keys[lastIndex].mTime) / (keys[lastIndex + 1].mTime - keys[lastIndex].mTime); + static_cast((time - keys[lastIndex].mTime) / (keys[lastIndex + 1].mTime - keys[lastIndex].mTime)); } else { @@ -620,7 +620,7 @@ namespace AZ for (unsigned int valIdx = 0; valIdx < key.mNumValuesAndWeights; ++valIdx) { int currentValue = key.mValues[valIdx]; - KeyData thisKey(static_cast(key.mWeights[valIdx]), key.mTime); + KeyData thisKey(static_cast(key.mWeights[valIdx]), static_cast(key.mTime)); valueToKeyDataMap[currentValue].insert( AZStd::upper_bound(valueToKeyDataMap[currentValue].begin(), valueToKeyDataMap[currentValue].end(),thisKey), thisKey); diff --git a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpSkinWeightsImporter.cpp b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpSkinWeightsImporter.cpp index 1e298aca5c..014d1bc5bf 100644 --- a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpSkinWeightsImporter.cpp +++ b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpSkinWeightsImporter.cpp @@ -97,7 +97,7 @@ namespace AZ } Pending pending; pending.m_bone = bone; - pending.m_numVertices = totalVertices; + pending.m_numVertices = static_cast(totalVertices); pending.m_skinWeightData = skinWeightData; pending.m_vertOffset = vertexCount; m_pendingSkinWeights.push_back(pending); From 52cba32bedca3e844f8318e055094960fa6e3892 Mon Sep 17 00:00:00 2001 From: pappeste Date: Fri, 25 Jun 2021 16:44:49 -0700 Subject: [PATCH 420/803] TestImpactFramework Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../Source/TestImpactConsoleTestSequenceEventHandler.cpp | 4 ++-- .../Artifact/Factory/TestImpactTestRunSuiteFactory.cpp | 2 +- .../Source/TestEngine/Run/TestImpactTestRunSerializer.cpp | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Code/Tools/TestImpactFramework/Frontend/Console/Code/Source/TestImpactConsoleTestSequenceEventHandler.cpp b/Code/Tools/TestImpactFramework/Frontend/Console/Code/Source/TestImpactConsoleTestSequenceEventHandler.cpp index e7430fe90b..a90f2cf4a2 100644 --- a/Code/Tools/TestImpactFramework/Frontend/Console/Code/Source/TestImpactConsoleTestSequenceEventHandler.cpp +++ b/Code/Tools/TestImpactFramework/Frontend/Console/Code/Source/TestImpactConsoleTestSequenceEventHandler.cpp @@ -26,8 +26,8 @@ namespace TestImpact void ImpactAnalysisTestSelection(size_t numSelectedTests, size_t numDiscardedTests, size_t numExcludedTests, size_t numDraftedTests) { - const float totalTests = numSelectedTests + numDiscardedTests; - const float saving = (1.0 - (numSelectedTests / totalTests)) * 100.0f; + const float totalTests = static_cast(numSelectedTests + numDiscardedTests); + const float saving = (1.0f - (numSelectedTests / totalTests)) * 100.0f; std::cout << numSelectedTests << " tests selected, " << numDiscardedTests << " tests discarded (" << saving << "% test saving)\n"; std::cout << "Of which " << numExcludedTests << " tests have been excluded and " << numDraftedTests << " tests have been drafted.\n"; diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Source/Artifact/Factory/TestImpactTestRunSuiteFactory.cpp b/Code/Tools/TestImpactFramework/Runtime/Code/Source/Artifact/Factory/TestImpactTestRunSuiteFactory.cpp index aa03292047..5fe7c08535 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Source/Artifact/Factory/TestImpactTestRunSuiteFactory.cpp +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Source/Artifact/Factory/TestImpactTestRunSuiteFactory.cpp @@ -67,7 +67,7 @@ namespace TestImpact const auto getDuration = [&Keys](const AZ::rapidxml::xml_node<>* node) { const AZStd::string duration = node->first_attribute(Keys[DurationKey])->value(); - return AZStd::chrono::milliseconds(AZStd::stof(duration) * 1000.f); + return AZStd::chrono::milliseconds(static_cast(AZStd::stof(duration) * 1000.f)); }; TestRunSuite testSuite; diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Run/TestImpactTestRunSerializer.cpp b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Run/TestImpactTestRunSerializer.cpp index 62d251c074..c0ca2caeae 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Run/TestImpactTestRunSerializer.cpp +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestEngine/Run/TestImpactTestRunSerializer.cpp @@ -52,7 +52,7 @@ namespace TestImpact // Run duration writer.Key(TestRunFields::Keys[TestRunFields::DurationKey]); - writer.Uint(testRun.GetDuration().count()); + writer.Uint(static_cast(testRun.GetDuration().count())); // Suites writer.Key(TestRunFields::Keys[TestRunFields::SuitesKey]); @@ -69,7 +69,7 @@ namespace TestImpact // Suite duration writer.Key(TestRunFields::Keys[TestRunFields::DurationKey]); - writer.Uint(suite.m_duration.count()); + writer.Uint(static_cast(suite.m_duration.count())); // Suite enabled writer.Key(TestRunFields::Keys[TestRunFields::EnabledKey]); @@ -93,7 +93,7 @@ namespace TestImpact // Test duration writer.Key(TestRunFields::Keys[TestRunFields::DurationKey]); - writer.Uint(test.m_duration.count()); + writer.Uint(static_cast(test.m_duration.count())); // Test status writer.Key(TestRunFields::Keys[TestRunFields::StatusKey]); From 8ba0807cfc793ddc711f4ee5fe2419b8dba81881 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Tue, 10 Aug 2021 21:06:42 -0700 Subject: [PATCH 421/803] Code/Framework/AzCore Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Framework/AzCore/AzCore/Math/MatrixUtils.cpp | 2 +- Code/Framework/AzCore/AzCore/Task/TaskExecutor.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/Math/MatrixUtils.cpp b/Code/Framework/AzCore/AzCore/Math/MatrixUtils.cpp index eabfcd8cf0..edf481a590 100644 --- a/Code/Framework/AzCore/AzCore/Math/MatrixUtils.cpp +++ b/Code/Framework/AzCore/AzCore/Math/MatrixUtils.cpp @@ -57,7 +57,7 @@ namespace AZ float GetPerspectiveMatrixFOV(const Matrix4x4& m) { - return 2.0 * AZStd::atan(1.0f / m.GetElement(1, 1)); + return 2.0f * AZStd::atan(1.0f / m.GetElement(1, 1)); } Matrix4x4* MakeFrustumMatrixRH(Matrix4x4& out, float left, float right, float bottom, float top, float nearDist, float farDist, bool reverseDepth) diff --git a/Code/Framework/AzCore/AzCore/Task/TaskExecutor.cpp b/Code/Framework/AzCore/AzCore/Task/TaskExecutor.cpp index 13db590291..5edb09edf0 100644 --- a/Code/Framework/AzCore/AzCore/Task/TaskExecutor.cpp +++ b/Code/Framework/AzCore/AzCore/Task/TaskExecutor.cpp @@ -41,7 +41,7 @@ namespace AZ { Task& task = m_tasks[i]; task.m_graph = this; - task.m_successorOffset = cursor - m_successors.data(); + task.m_successorOffset = static_cast(cursor - m_successors.data()); cursor += task.m_outboundLinkCount; AZ_Assert(task.m_outboundLinkCount == links[i].size(), "Task outbound link information mismatch"); From 90cad016de438e3fe23f631d969c6b462f5e3ff3 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Tue, 10 Aug 2021 21:07:02 -0700 Subject: [PATCH 422/803] Gems/Atom Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../Code/Source/Converters/ColorChart.cpp | 6 +++--- .../Code/Source/Processing/ImageAssetProducer.cpp | 6 +++--- .../Code/Source/Processing/PixelFormatInfo.h | 2 +- .../ReflectionScreenSpaceBlurChildPass.cpp | 4 ++-- .../RPI.Builders/Model/ModelAssetBuilderComponent.cpp | 2 +- .../Source/RPI.Public/Pass/FullscreenTrianglePass.cpp | 8 ++++---- .../Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl | 2 +- .../Utils/Code/Include/Atom/Utils/ImGuiGpuProfiler.inl | 4 ++-- .../Source/AtomViewportDisplayInfoSystemComponent.cpp | 2 +- .../Code/Source/CoreLights/SphereLightDelegate.cpp | 4 ++-- 10 files changed, 20 insertions(+), 20 deletions(-) diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Converters/ColorChart.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Converters/ColorChart.cpp index c6046bb5a2..f50ae41c8a 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Converters/ColorChart.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Converters/ColorChart.cpp @@ -76,9 +76,9 @@ namespace ImageProcessingAtom for (int r = 0; r < ePS_Red; ++r) { SColor col; - col.r = 255 * r / (ePS_Red); - col.g = 255 * g / (ePS_Green); - col.b = 255 * b / (ePS_Blue); + col.r = aznumeric_cast(255 * r / (ePS_Red)); + col.g = aznumeric_cast(255 * g / (ePS_Green)); + col.b = aznumeric_cast(255 * b / (ePS_Blue)); int l = 255 - (col.r * 3 + col.g * 6 + col.b) / 10; col.r = col.g = col.b = (unsigned char)l; m_mapping.push_back(col); diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageAssetProducer.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageAssetProducer.cpp index 0b0a241d40..1e4133b5b2 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageAssetProducer.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageAssetProducer.cpp @@ -97,8 +97,8 @@ namespace ImageProcessingAtom RHI::Format format = Utils::PixelFormatToRHIFormat(m_imageObject->GetPixelFormat(), m_imageObject->HasImageFlags(EIF_SRGBRead)); RHI::ImageBindFlags bindFlag = RHI::ImageBindFlags::ShaderRead; - RHI::ImageDescriptor imageDesc = RHI::ImageDescriptor::Create2DArray(bindFlag, imageWidth, imageHeight, arraySize, format); - imageDesc.m_mipLevels = m_imageObject->GetMipCount(); + RHI::ImageDescriptor imageDesc = RHI::ImageDescriptor::Create2DArray(bindFlag, imageWidth, imageHeight, aznumeric_cast(arraySize), format); + imageDesc.m_mipLevels = aznumeric_cast(m_imageObject->GetMipCount()); if (m_imageObject->HasImageFlags(EIF_Cubemap)) { imageDesc.m_isCubemap = true; @@ -227,7 +227,7 @@ namespace ImageProcessingAtom { RPI::ImageMipChainAssetCreator builder; uint32_t arraySize = m_imageObject->HasImageFlags(EIF_Cubemap) ? 6 : 1; - builder.Begin(chainAssetId, mipLevels, arraySize); + builder.Begin(chainAssetId, aznumeric_cast(mipLevels), aznumeric_cast(arraySize)); for (uint32_t mip = startMip; mip < startMip + mipLevels; mip++) { diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/PixelFormatInfo.h b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/PixelFormatInfo.h index 5f1cbf938a..50d7ea137f 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/PixelFormatInfo.h +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/PixelFormatInfo.h @@ -52,7 +52,7 @@ namespace ImageProcessingAtom Result = ((intValue + 0x0FFFU + ((intValue >> 13U) & 1U)) >> 13U) & 0x7FFFU; } - h = (Result | Sign); + h = static_cast(Result | Sign); } operator float() const diff --git a/Gems/Atom/Feature/Common/Code/Source/ReflectionScreenSpace/ReflectionScreenSpaceBlurChildPass.cpp b/Gems/Atom/Feature/Common/Code/Source/ReflectionScreenSpace/ReflectionScreenSpaceBlurChildPass.cpp index fce32cf448..3e97277594 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ReflectionScreenSpace/ReflectionScreenSpaceBlurChildPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ReflectionScreenSpace/ReflectionScreenSpaceBlurChildPass.cpp @@ -44,8 +44,8 @@ namespace AZ } float inverseScale = 1.0f / m_outputScale; - uint32_t outputWidth = m_imageSize.m_width * inverseScale; - uint32_t outputHeight = m_imageSize.m_height * inverseScale; + uint32_t outputWidth = static_cast(m_imageSize.m_width * inverseScale); + uint32_t outputHeight = static_cast(m_imageSize.m_height * inverseScale); params.m_viewportState = RHI::Viewport(0, static_cast(outputWidth), 0, static_cast(outputHeight)); params.m_scissorState = RHI::Scissor(0, 0, outputWidth, outputHeight); diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/ModelAssetBuilderComponent.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/ModelAssetBuilderComponent.cpp index fb8708fb88..db0eff5fc1 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/ModelAssetBuilderComponent.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/ModelAssetBuilderComponent.cpp @@ -1807,7 +1807,7 @@ namespace AZ if (iter != materialAssetsByUid.end()) { ModelMaterialSlot materialSlot; - materialSlot.m_stableId = meshView.m_materialUid; + materialSlot.m_stableId = static_cast(meshView.m_materialUid); materialSlot.m_displayName = iter->second.m_name; materialSlot.m_defaultMaterialAsset = iter->second.m_asset; diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/FullscreenTrianglePass.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/FullscreenTrianglePass.cpp index 8a4206f0d8..7a9481a45c 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/FullscreenTrianglePass.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/FullscreenTrianglePass.cpp @@ -179,10 +179,10 @@ namespace AZ RHI::Size targetImageSize = outputAttachment->m_descriptor.m_image.m_size; - m_viewportState.m_maxX = AZStd::min(static_cast(params.m_viewportState.m_maxX), targetImageSize.m_width); - m_viewportState.m_maxY = AZStd::min(static_cast(params.m_viewportState.m_maxY), targetImageSize.m_height); - m_viewportState.m_minX = AZStd::min(params.m_viewportState.m_minX, m_viewportState.m_maxX); - m_viewportState.m_minY = AZStd::min(params.m_viewportState.m_minY, m_viewportState.m_maxY); + m_viewportState.m_maxX = aznumeric_cast(AZStd::min(static_cast(params.m_viewportState.m_maxX), targetImageSize.m_width)); + m_viewportState.m_maxY = aznumeric_cast(AZStd::min(static_cast(params.m_viewportState.m_maxY), targetImageSize.m_height)); + m_viewportState.m_minX = aznumeric_cast(AZStd::min(params.m_viewportState.m_minX, m_viewportState.m_maxX)); + m_viewportState.m_minY = aznumeric_cast(AZStd::min(params.m_viewportState.m_minY, m_viewportState.m_maxY)); m_scissorState.m_maxX = AZStd::min(static_cast(params.m_scissorState.m_maxX), targetImageSize.m_width); m_scissorState.m_maxY = AZStd::min(static_cast(params.m_scissorState.m_maxY), targetImageSize.m_height); diff --git a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl index a24fdbf1d8..4e28658cc0 100644 --- a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl +++ b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl @@ -618,7 +618,7 @@ namespace AZ else // We have enough space to draw the entire label, draw and center text. { const float remainingWidth = regionPixelWidth - textWidth; - const float offset = remainingWidth * .5; + const float offset = remainingWidth * .5f; drawList->AddText({ startPoint.x + offset, startPoint.y }, IM_COL32_WHITE, label.c_str()); } diff --git a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiGpuProfiler.inl b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiGpuProfiler.inl index ec7b30cd3e..47a9fa6772 100644 --- a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiGpuProfiler.inl +++ b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiGpuProfiler.inl @@ -1092,8 +1092,8 @@ namespace AZ AZStd::sort(m_tableRows.begin(), m_tableRows.end(), [ascending](const TableRow& lhs, const TableRow& rhs) { - const float lhsSize = lhs.m_sizeInBytes; - const float rhsSize = rhs.m_sizeInBytes; + const float lhsSize = aznumeric_cast(lhs.m_sizeInBytes); + const float rhsSize = aznumeric_cast(rhs.m_sizeInBytes); return ascending ? lhsSize < rhsSize : lhsSize > rhsSize; }); break; diff --git a/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.cpp b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.cpp index c1f459e1ee..45757c2c6c 100644 --- a/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.cpp +++ b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.cpp @@ -156,7 +156,7 @@ namespace AZ::Render m_drawParams.m_drawViewportId = viewportContext->GetId(); auto viewportSize = viewportContext->GetViewportSize(); - m_drawParams.m_position = AZ::Vector3(viewportSize.m_width, 0.0f, 1.0f) + AZ::Vector3(r_topRightBorderPadding) * viewportContext->GetDpiScalingFactor(); + m_drawParams.m_position = AZ::Vector3(static_cast(viewportSize.m_width), 0.0f, 1.0f) + AZ::Vector3(r_topRightBorderPadding) * viewportContext->GetDpiScalingFactor(); m_drawParams.m_color = AZ::Colors::White; m_drawParams.m_scale = AZ::Vector2(BaseFontSize); m_drawParams.m_hAlign = AzFramework::TextHorizontalAlignment::Right; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SphereLightDelegate.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SphereLightDelegate.cpp index edf08ba8c9..b48098819b 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SphereLightDelegate.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SphereLightDelegate.cpp @@ -104,7 +104,7 @@ namespace AZ::Render { if (GetShadowsEnabled() && GetLightHandle().IsValid()) { - GetFeatureProcessor()->SetPredictionSampleCount(GetLightHandle(), count); + GetFeatureProcessor()->SetPredictionSampleCount(GetLightHandle(), aznumeric_cast(count)); } } @@ -112,7 +112,7 @@ namespace AZ::Render { if (GetShadowsEnabled() && GetLightHandle().IsValid()) { - GetFeatureProcessor()->SetFilteringSampleCount(GetLightHandle(), count); + GetFeatureProcessor()->SetFilteringSampleCount(GetLightHandle(), aznumeric_cast(count)); } } From a6cdb1e58c2b626863ce027ef81812c8e0c900e0 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Tue, 10 Aug 2021 21:07:26 -0700 Subject: [PATCH 423/803] Gems/EMotionFX Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../Code/Tests/AnimGraphDeferredInitTests.cpp | 2 +- .../Code/Tests/AnimGraphMotionNodeTests.cpp | 2 +- .../Tests/BlendTreeFloatMath1NodeTests.cpp | 2 +- .../Tests/BlendTreeTwoLinkIKNodeTests.cpp | 30 +++++++++---------- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/Gems/EMotionFX/Code/Tests/AnimGraphDeferredInitTests.cpp b/Gems/EMotionFX/Code/Tests/AnimGraphDeferredInitTests.cpp index 710cfb790e..0449005659 100644 --- a/Gems/EMotionFX/Code/Tests/AnimGraphDeferredInitTests.cpp +++ b/Gems/EMotionFX/Code/Tests/AnimGraphDeferredInitTests.cpp @@ -36,7 +36,7 @@ namespace EMotionFX m_blendTree->AddChildNode(paramNode); paramNode->InitAfterLoading(m_animGraph.get()); paramNode->InvalidateUniqueData(m_animGraphInstance); - m_blend2Node->AddConnection(paramNode, paramNode->FindOutputPortByName("weightParam")->m_portId, BlendTreeBlend2Node::PORTID_INPUT_WEIGHT); + m_blend2Node->AddConnection(paramNode, static_cast(paramNode->FindOutputPortByName("weightParam")->m_portId), BlendTreeBlend2Node::PORTID_INPUT_WEIGHT); } void ConstructGraph() diff --git a/Gems/EMotionFX/Code/Tests/AnimGraphMotionNodeTests.cpp b/Gems/EMotionFX/Code/Tests/AnimGraphMotionNodeTests.cpp index 121f438d82..a377495d6c 100644 --- a/Gems/EMotionFX/Code/Tests/AnimGraphMotionNodeTests.cpp +++ b/Gems/EMotionFX/Code/Tests/AnimGraphMotionNodeTests.cpp @@ -303,7 +303,7 @@ namespace EMotionFX TEST_F(AnimGraphMotionNodeFixture, InPlaceInputAndNoEffectOutputsCorrectMotionAndPose) { - m_motionNode->AddConnection(m_paramNode, m_paramNode->FindOutputPortByName("InPlace")->m_portId, AnimGraphMotionNode::INPUTPORT_INPLACE); + m_motionNode->AddConnection(m_paramNode, static_cast(m_paramNode->FindOutputPortByName("InPlace")->m_portId), AnimGraphMotionNode::INPUTPORT_INPLACE); ParamSetValue("InPlace", true); m_animGraphInstance->FindOrCreateUniqueNodeData(m_motionNode); diff --git a/Gems/EMotionFX/Code/Tests/BlendTreeFloatMath1NodeTests.cpp b/Gems/EMotionFX/Code/Tests/BlendTreeFloatMath1NodeTests.cpp index 3ece046845..5827c5f186 100644 --- a/Gems/EMotionFX/Code/Tests/BlendTreeFloatMath1NodeTests.cpp +++ b/Gems/EMotionFX/Code/Tests/BlendTreeFloatMath1NodeTests.cpp @@ -98,7 +98,7 @@ namespace EMotionFX void TestInput(const AZStd::string& paramName, std::vector xInputs) { BlendTreeConnection* connection = m_floatMath1Node->AddConnection(m_paramNode, - m_paramNode->FindOutputPortByName(paramName)->m_portId, BlendTreeFloatMath1Node::PORTID_INPUT_X); + aznumeric_cast(m_paramNode->FindOutputPortByName(paramName)->m_portId), BlendTreeFloatMath1Node::PORTID_INPUT_X); for (inputType i : xInputs) { diff --git a/Gems/EMotionFX/Code/Tests/BlendTreeTwoLinkIKNodeTests.cpp b/Gems/EMotionFX/Code/Tests/BlendTreeTwoLinkIKNodeTests.cpp index d68bf9db83..ede6f5dcbe 100644 --- a/Gems/EMotionFX/Code/Tests/BlendTreeTwoLinkIKNodeTests.cpp +++ b/Gems/EMotionFX/Code/Tests/BlendTreeTwoLinkIKNodeTests.cpp @@ -137,9 +137,9 @@ namespace EMotionFX TEST_P(BlendTreeTwoLinkIKNodeFixture, ReachablePositionsOutputCorrectPose) { // Set values for vector3 and twoLinkIKNode weight parameter - m_twoLinkIKNode->AddConnection(m_paramNode, m_paramNode->FindOutputPortByName("WeightParam")->m_portId, BlendTreeTwoLinkIKNode::INPUTPORT_WEIGHT); + m_twoLinkIKNode->AddConnection(m_paramNode, aznumeric_cast(m_paramNode->FindOutputPortByName("WeightParam")->m_portId), BlendTreeTwoLinkIKNode::INPUTPORT_WEIGHT); m_twoLinkIKNode->AddConnection(m_paramNode, - m_paramNode->FindOutputPortByName("GoalPosParam")->m_portId, BlendTreeTwoLinkIKNode::INPUTPORT_GOALPOS); + aznumeric_cast(m_paramNode->FindOutputPortByName("GoalPosParam")->m_portId), BlendTreeTwoLinkIKNode::INPUTPORT_GOALPOS); GetEMotionFX().Update(1.0f / 60.0f); const float weight = testing::get<0>(GetParam()); @@ -179,7 +179,7 @@ namespace EMotionFX TEST_P(BlendTreeTwoLinkIKNodeFixture, ReachableAlignToNodeOutputCorrectPose) { - m_twoLinkIKNode->AddConnection(m_paramNode, m_paramNode->FindOutputPortByName("WeightParam")->m_portId, + m_twoLinkIKNode->AddConnection(m_paramNode, aznumeric_cast(m_paramNode->FindOutputPortByName("WeightParam")->m_portId), BlendTreeTwoLinkIKNode::INPUTPORT_WEIGHT); GetEMotionFX().Update(1.0f / 60.0f); @@ -224,10 +224,10 @@ namespace EMotionFX TEST_P(BlendTreeTwoLinkIKNodeFixture, UnreachablePositionsOutputCorrectPose) { - m_twoLinkIKNode->AddConnection(m_paramNode, m_paramNode->FindOutputPortByName("WeightParam")->m_portId, + m_twoLinkIKNode->AddConnection(m_paramNode, aznumeric_cast(m_paramNode->FindOutputPortByName("WeightParam")->m_portId), BlendTreeTwoLinkIKNode::INPUTPORT_WEIGHT); m_twoLinkIKNode->AddConnection(m_paramNode, - m_paramNode->FindOutputPortByName("GoalPosParam")->m_portId, BlendTreeTwoLinkIKNode::INPUTPORT_GOALPOS); + static_cast(m_paramNode->FindOutputPortByName("GoalPosParam")->m_portId), BlendTreeTwoLinkIKNode::INPUTPORT_GOALPOS); GetEMotionFX().Update(1.0f / 60.0f); const float weight = testing::get<0>(GetParam()); @@ -272,12 +272,12 @@ namespace EMotionFX TEST_P(BlendTreeTwoLinkIKNodeFixture, RotatedPositionsOutputCorrectPose) { - m_twoLinkIKNode->AddConnection(m_paramNode, m_paramNode->FindOutputPortByName("WeightParam")->m_portId, + m_twoLinkIKNode->AddConnection(m_paramNode, static_cast(m_paramNode->FindOutputPortByName("WeightParam")->m_portId), BlendTreeTwoLinkIKNode::INPUTPORT_WEIGHT); m_twoLinkIKNode->AddConnection(m_paramNode, - m_paramNode->FindOutputPortByName("GoalPosParam")->m_portId, BlendTreeTwoLinkIKNode::INPUTPORT_GOALPOS); + aznumeric_cast(m_paramNode->FindOutputPortByName("GoalPosParam")->m_portId), BlendTreeTwoLinkIKNode::INPUTPORT_GOALPOS); m_twoLinkIKNode->AddConnection(m_paramNode, - m_paramNode->FindOutputPortByName("RotationParam")->m_portId, BlendTreeTwoLinkIKNode::INPUTPORT_GOALROT); + static_cast(m_paramNode->FindOutputPortByName("RotationParam")->m_portId), BlendTreeTwoLinkIKNode::INPUTPORT_GOALROT); m_twoLinkIKNode->SetRotationEnabled(true); GetEMotionFX().Update(1.0f / 60.0f); @@ -315,12 +315,12 @@ namespace EMotionFX TEST_P(BlendTreeTwoLinkIKNodeFixture, BendDirectionOutputCorrectPose) { - m_twoLinkIKNode->AddConnection(m_paramNode, m_paramNode->FindOutputPortByName("WeightParam")->m_portId, + m_twoLinkIKNode->AddConnection(m_paramNode, static_cast(m_paramNode->FindOutputPortByName("WeightParam")->m_portId), BlendTreeTwoLinkIKNode::INPUTPORT_WEIGHT); m_twoLinkIKNode->AddConnection(m_paramNode, - m_paramNode->FindOutputPortByName("GoalPosParam")->m_portId, BlendTreeTwoLinkIKNode::INPUTPORT_GOALPOS); + static_cast(m_paramNode->FindOutputPortByName("GoalPosParam")->m_portId), BlendTreeTwoLinkIKNode::INPUTPORT_GOALPOS); m_twoLinkIKNode->AddConnection(m_paramNode, - m_paramNode->FindOutputPortByName("BendDirParam")->m_portId, BlendTreeTwoLinkIKNode::INPUTPORT_BENDDIR); + static_cast(m_paramNode->FindOutputPortByName("BendDirParam")->m_portId), BlendTreeTwoLinkIKNode::INPUTPORT_BENDDIR); m_twoLinkIKNode->SetRelativeBendDir(true); GetEMotionFX().Update(1.0f / 60.0f); @@ -382,14 +382,14 @@ namespace EMotionFX TEST_P(BlendTreeTwoLinkIKNodeFixture, CombinedFunctionsOutputCorrectPose) { // Two Link IK Node should not break when using all of its functions at the same time - m_twoLinkIKNode->AddConnection(m_paramNode, m_paramNode->FindOutputPortByName("WeightParam")->m_portId, + m_twoLinkIKNode->AddConnection(m_paramNode, static_cast(m_paramNode->FindOutputPortByName("WeightParam")->m_portId), BlendTreeTwoLinkIKNode::INPUTPORT_WEIGHT); m_twoLinkIKNode->AddConnection(m_paramNode, - m_paramNode->FindOutputPortByName("GoalPosParam")->m_portId, BlendTreeTwoLinkIKNode::INPUTPORT_GOALPOS); + static_cast(m_paramNode->FindOutputPortByName("GoalPosParam")->m_portId), BlendTreeTwoLinkIKNode::INPUTPORT_GOALPOS); m_twoLinkIKNode->AddConnection(m_paramNode, - m_paramNode->FindOutputPortByName("RotationParam")->m_portId, BlendTreeTwoLinkIKNode::INPUTPORT_GOALROT); + static_cast(m_paramNode->FindOutputPortByName("RotationParam")->m_portId), BlendTreeTwoLinkIKNode::INPUTPORT_GOALROT); m_twoLinkIKNode->AddConnection(m_paramNode, - m_paramNode->FindOutputPortByName("BendDirParam")->m_portId, BlendTreeTwoLinkIKNode::INPUTPORT_BENDDIR); + static_cast(m_paramNode->FindOutputPortByName("BendDirParam")->m_portId), BlendTreeTwoLinkIKNode::INPUTPORT_BENDDIR); m_twoLinkIKNode->SetRotationEnabled(true); m_twoLinkIKNode->SetRelativeBendDir(true); GetEMotionFX().Update(1.0f / 60.0f); From 500f84d4697cda65a0ac8e63ff65660c638c928e Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Tue, 10 Aug 2021 21:07:42 -0700 Subject: [PATCH 424/803] Gems/LyShine Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Gems/LyShine/Code/Source/LyShinePass.cpp | 2 +- Gems/LyShine/Code/Source/RenderGraph.cpp | 4 ++-- Gems/LyShine/Code/Source/UiFaderComponent.cpp | 2 +- Gems/LyShine/Code/Source/UiMaskComponent.cpp | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Gems/LyShine/Code/Source/LyShinePass.cpp b/Gems/LyShine/Code/Source/LyShinePass.cpp index fbf7f34e14..8245294696 100644 --- a/Gems/LyShine/Code/Source/LyShinePass.cpp +++ b/Gems/LyShine/Code/Source/LyShinePass.cpp @@ -135,7 +135,7 @@ namespace LyShine passData->m_pipelineViewTag = AZ::Name("MainCamera"); auto size = attachmentImage->GetRHIImage()->GetDescriptor().m_size; passData->m_overrideScissor = AZ::RHI::Scissor(0, 0, size.m_width, size.m_height); - passData->m_overrideViewport = AZ::RHI::Viewport(0, size.m_width, 0, size.m_height); + passData->m_overrideViewport = AZ::RHI::Viewport(0, static_cast(size.m_width), 0, static_cast(size.m_height)); passTemplate->m_passData = AZStd::move(passData); // Create a pass descriptor for the new child pass AZ::RPI::PassDescriptor childDesc; diff --git a/Gems/LyShine/Code/Source/RenderGraph.cpp b/Gems/LyShine/Code/Source/RenderGraph.cpp index 85f9c7deb5..51f62fc7ad 100644 --- a/Gems/LyShine/Code/Source/RenderGraph.cpp +++ b/Gems/LyShine/Code/Source/RenderGraph.cpp @@ -881,8 +881,8 @@ namespace LyShine { for (int i = 0; i < primitive->m_numVertices; ++i) { - primitive->m_vertices[i].texIndex = texUnit0; - primitive->m_vertices[i].texIndex2 = texUnit1; + primitive->m_vertices[i].texIndex = aznumeric_cast(texUnit0); + primitive->m_vertices[i].texIndex2 = aznumeric_cast(texUnit1); } } diff --git a/Gems/LyShine/Code/Source/UiFaderComponent.cpp b/Gems/LyShine/Code/Source/UiFaderComponent.cpp index f195689a43..acdf462df7 100644 --- a/Gems/LyShine/Code/Source/UiFaderComponent.cpp +++ b/Gems/LyShine/Code/Source/UiFaderComponent.cpp @@ -463,7 +463,7 @@ void UiFaderComponent::CreateOrResizeRenderTarget(const AZ::Vector2& pixelAligne // Create a render target that this element and its children will be rendered to AZ::EntityId canvasEntityId; EBUS_EVENT_ID_RESULT(canvasEntityId, GetEntityId(), UiElementBus, GetCanvasEntityId); - AZ::RHI::Size imageSize(renderTargetSize.GetX(), renderTargetSize.GetY(), 1); + AZ::RHI::Size imageSize(aznumeric_cast(renderTargetSize.GetX()), aznumeric_cast(renderTargetSize.GetY()), 1); EBUS_EVENT_ID_RESULT(m_attachmentImageId, canvasEntityId, LyShine::RenderToTextureRequestBus, UseRenderTarget, AZ::Name(m_renderTargetName.c_str()), imageSize); if (m_attachmentImageId.IsEmpty()) { diff --git a/Gems/LyShine/Code/Source/UiMaskComponent.cpp b/Gems/LyShine/Code/Source/UiMaskComponent.cpp index 2c1763e4ec..869529560f 100644 --- a/Gems/LyShine/Code/Source/UiMaskComponent.cpp +++ b/Gems/LyShine/Code/Source/UiMaskComponent.cpp @@ -564,7 +564,7 @@ void UiMaskComponent::CreateOrResizeRenderTarget(const AZ::Vector2& pixelAligned // Create a render target that this element and its children will be rendered to AZ::EntityId canvasEntityId; EBUS_EVENT_ID_RESULT(canvasEntityId, GetEntityId(), UiElementBus, GetCanvasEntityId); - AZ::RHI::Size imageSize(renderTargetSize.GetX(), renderTargetSize.GetY(), 1); + AZ::RHI::Size imageSize(aznumeric_cast(renderTargetSize.GetX()), aznumeric_cast(renderTargetSize.GetY()), 1); EBUS_EVENT_ID_RESULT(m_contentAttachmentImageId, canvasEntityId, LyShine::RenderToTextureRequestBus, UseRenderTarget, AZ::Name(m_renderTargetName.c_str()), imageSize); if (m_contentAttachmentImageId.IsEmpty()) { @@ -762,7 +762,7 @@ void UiMaskComponent::RenderUsingGradientMask(LyShine::IRenderGraph* renderGraph { // go through all the cached vertices and update the alpha values UCol desiredPackedColor = m_cachedPrimitive.m_vertices[0].color; - desiredPackedColor.a = desiredPackedAlpha; + desiredPackedColor.a = aznumeric_cast(desiredPackedAlpha); for (int i = 0; i < m_cachedPrimitive.m_numVertices; ++i) { m_cachedPrimitive.m_vertices[i].color = desiredPackedColor; From f914f7680a22b5e2225d26e3b4b1d39ef380c000 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Tue, 10 Aug 2021 21:07:57 -0700 Subject: [PATCH 425/803] Gems/ScriptCanvas Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../Code/Include/ScriptCanvas/Libraries/Math/Vector2Nodes.h | 2 +- .../Code/Include/ScriptCanvas/Libraries/Math/Vector3Nodes.h | 2 +- .../Code/Include/ScriptCanvas/Libraries/Math/Vector4Nodes.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Math/Vector2Nodes.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Math/Vector2Nodes.h index 670c9f31a1..c815470540 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Math/Vector2Nodes.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Math/Vector2Nodes.h @@ -254,7 +254,7 @@ namespace ScriptCanvas { Vector2Type r = to - from; float length = r.NormalizeWithLength(); - r.SetLength(optionalScale); + r.SetLength(static_cast(optionalScale)); return std::make_tuple(r, length); } SCRIPT_CANVAS_GENERIC_FUNCTION_NODE_WITH_DEFAULTS(DirectionTo, DirectionToDefaults, k_categoryName, "{49A2D7F6-6CD3-420E-8A79-D46B00DB6CED}", "Returns a direction vector between two points and the distance between them, by default the direction will be normalized, but it may be optionally scaled using the Scale parameter if different from 1.0", "From", "To", "Scale"); diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Math/Vector3Nodes.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Math/Vector3Nodes.h index 492bc83e33..3e70d1fed7 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Math/Vector3Nodes.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Math/Vector3Nodes.h @@ -340,7 +340,7 @@ namespace ScriptCanvas { Vector3Type r = to - from; float length = r.NormalizeWithLength(); - r.SetLength(optionalScale); + r.SetLength(static_cast(optionalScale)); return std::make_tuple(r, length); } SCRIPT_CANVAS_GENERIC_FUNCTION_NODE_WITH_DEFAULTS(DirectionTo, DirectionToDefaults, k_categoryName, "{28FBD529-4C9A-4E34-B8A0-A13B5DB3C331}", "Returns a direction vector between two points and the distance between them, by default the direction will be normalized, but it may be optionally scaled using the Scale parameter if different from 1.0", "From", "To", "Scale"); diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Math/Vector4Nodes.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Math/Vector4Nodes.h index 14256fc969..d7bee1f940 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Math/Vector4Nodes.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Math/Vector4Nodes.h @@ -225,7 +225,7 @@ namespace ScriptCanvas { Vector4Type r = to - from; float length = r.NormalizeWithLength(); - r.SetLength(optionalScale); + r.SetLength(static_cast(optionalScale)); return std::make_tuple(r, length); } SCRIPT_CANVAS_GENERIC_FUNCTION_NODE_WITH_DEFAULTS(DirectionTo, DirectionToDefaults, k_categoryName, "{463762DE-E541-4AFE-80C2-FED1C5273319}", "Returns a direction vector between two points and the distance between them, by default the direction will be normalized, but it may be optionally scaled using the Scale parameter if different from 1.0", "From", "To", "Scale"); From 37663910c14dc400fb544e90d0d5beb111e1c23b Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Tue, 10 Aug 2021 21:08:10 -0700 Subject: [PATCH 426/803] Others Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Editor/Objects/DisplayContext.h | 10 +++--- Code/Editor/Util/GuidUtil.h | 16 ++++----- Code/Editor/Util/Variable.h | 2 +- .../Code/Source/BarrierInputClient.cpp | 34 ++++++++++++++++--- .../Source/ViewportCameraSelectorWindow.cpp | 2 +- 5 files changed, 44 insertions(+), 20 deletions(-) diff --git a/Code/Editor/Objects/DisplayContext.h b/Code/Editor/Objects/DisplayContext.h index 4b09d4afe9..6459497199 100644 --- a/Code/Editor/Objects/DisplayContext.h +++ b/Code/Editor/Objects/DisplayContext.h @@ -83,12 +83,12 @@ struct SANDBOX_API DisplayContext // Draw functions ////////////////////////////////////////////////////////////////////////// //! Set current materialc color. - void SetColor(float r, float g, float b, float a = 1) { m_color4b = ColorB(int(r * 255.0f), int(g * 255.0f), int(b * 255.0f), int(a * 255.0f)); }; - void SetColor(const Vec3& color, float a = 1) { m_color4b = ColorB(int(color.x * 255.0f), int(color.y * 255.0f), int(color.z * 255.0f), int(a * 255.0f)); }; - void SetColor(const QColor& rgb, float a) { m_color4b = ColorB(rgb.red(), rgb.green(), rgb.blue(), int(a * 255.0f)); }; - void SetColor(const QColor& color) { m_color4b = ColorB(color.red(), color.green(), color.blue(), color.alpha()); }; + void SetColor(float r, float g, float b, float a = 1) { m_color4b = ColorB(aznumeric_cast(r * 255.0f), aznumeric_cast(g * 255.0f), aznumeric_cast(b * 255.0f), aznumeric_cast(a * 255.0f)); }; + void SetColor(const Vec3& color, float a = 1) { m_color4b = ColorB(aznumeric_cast(color.x * 255.0f), aznumeric_cast(color.y * 255.0f), aznumeric_cast(color.z * 255.0f), aznumeric_cast(a * 255.0f)); }; + void SetColor(const QColor& rgb, float a) { m_color4b = ColorB(aznumeric_cast(rgb.red()), aznumeric_cast(rgb.green()), aznumeric_cast(rgb.blue()), aznumeric_cast(a * 255.0f)); }; + void SetColor(const QColor& color) { m_color4b = ColorB(aznumeric_cast(color.red()), aznumeric_cast(color.green()), aznumeric_cast(color.blue()), aznumeric_cast(color.alpha())); }; void SetColor(const ColorB& color) { m_color4b = color; }; - void SetAlpha(float a = 1) { m_color4b.a = int(a * 255.0f); }; + void SetAlpha(float a = 1) { m_color4b.a = aznumeric_cast(a * 255.0f); }; ColorB GetColor() const { return m_color4b; } void SetSelectedColor(float fAlpha = 1); diff --git a/Code/Editor/Util/GuidUtil.h b/Code/Editor/Util/GuidUtil.h index 2a82e3682b..138b221c70 100644 --- a/Code/Editor/Util/GuidUtil.h +++ b/Code/Editor/Util/GuidUtil.h @@ -64,14 +64,14 @@ inline GUID GuidUtil::FromString(const char* guidString) guid.Data3 = 0; azsscanf(guidString, "{%8" SCNx32 "-%4hX-%4hX-%2X%2X-%2X%2X%2X%2X%2X%2X}", &guid.Data1, &guid.Data2, &guid.Data3, &d[0], &d[1], &d[2], &d[3], &d[4], &d[5], &d[6], &d[7]); - guid.Data4[0] = d[0]; - guid.Data4[1] = d[1]; - guid.Data4[2] = d[2]; - guid.Data4[3] = d[3]; - guid.Data4[4] = d[4]; - guid.Data4[5] = d[5]; - guid.Data4[6] = d[6]; - guid.Data4[7] = d[7]; + guid.Data4[0] = aznumeric_cast(d[0]); + guid.Data4[1] = aznumeric_cast(d[1]); + guid.Data4[2] = aznumeric_cast(d[2]); + guid.Data4[3] = aznumeric_cast(d[3]); + guid.Data4[4] = aznumeric_cast(d[4]); + guid.Data4[5] = aznumeric_cast(d[5]); + guid.Data4[6] = aznumeric_cast(d[6]); + guid.Data4[7] = aznumeric_cast(d[7]); return guid; } diff --git a/Code/Editor/Util/Variable.h b/Code/Editor/Util/Variable.h index da506b9db0..6cd69a8cb1 100644 --- a/Code/Editor/Util/Variable.h +++ b/Code/Editor/Util/Variable.h @@ -405,7 +405,7 @@ public: unsigned char GetDataType() const { return m_dataType; }; void SetDataType(unsigned char dataType) { m_dataType = dataType; } - void SetFlags(int flags) { m_flags = flags; } + void SetFlags(int flags) { m_flags = aznumeric_cast(flags); } int GetFlags() const { return m_flags; } void SetFlagRecursive(EFlags flag) { m_flags |= flag; } diff --git a/Gems/BarrierInput/Code/Source/BarrierInputClient.cpp b/Gems/BarrierInput/Code/Source/BarrierInputClient.cpp index 495ef88467..25a95752ac 100644 --- a/Gems/BarrierInput/Code/Source/BarrierInputClient.cpp +++ b/Gems/BarrierInput/Code/Source/BarrierInputClient.cpp @@ -55,11 +55,35 @@ namespace BarrierInput void Eat(int len) { data += len; } void InsertString(const char* str) { int len = static_cast(strlen(str)); memcpy(end, str, len); end += len; } - void InsertU32(int a) { end[0] = a >> 24; end[1] = a >> 16; end[2] = a >> 8; end[3] = a; end += 4; } - void InsertU16(int a) { end[0] = a >> 8; end[1] = a; end += 2; } - void InsertU8(int a) { end[0] = a; end += 1; } + void InsertU32(int a) + { + end[0] = aznumeric_cast(a >> 24); + end[1] = aznumeric_cast(a >> 16); + end[2] = aznumeric_cast(a >> 8); + end[3] = aznumeric_cast(a); + end += 4; + } + void InsertU16(int a) + { + end[0] = aznumeric_cast(a >> 8); + end[1] = aznumeric_cast(a); + end += 2; + } + void InsertU8(int a) + { + end[0] = aznumeric_cast(a); + end += 1; + } void OpenPacket() { packet = end; end += 4; } - void ClosePacket() { int len = GetLength() - sizeof(AZ::u32); packet[0] = len >> 24; packet[1] = len >> 16; packet[2] = len >> 8; packet[3] = len; packet = NULL; } + void ClosePacket() + { + int len = GetLength() - sizeof(AZ::u32); + packet[0] = aznumeric_cast(len >> 24); + packet[1] = aznumeric_cast(len >> 16); + packet[2] = aznumeric_cast(len >> 8); + packet[3] = aznumeric_cast(len); + packet = nullptr; + } }; enum ArgType @@ -381,7 +405,7 @@ namespace BarrierInput if (AZ::AzSock::IsAzSocketValid(m_socket)) { AZ::AzSock::AzSocketAddress socketAddress; - if (socketAddress.SetAddress(m_serverHostName.c_str(), m_connectionPort)) + if (socketAddress.SetAddress(m_serverHostName.c_str(), aznumeric_cast(m_connectionPort))) { const int result = AZ::AzSock::Connect(m_socket, socketAddress); if (!AZ::AzSock::SocketErrorOccured(result)) diff --git a/Gems/Camera/Code/Source/ViewportCameraSelectorWindow.cpp b/Gems/Camera/Code/Source/ViewportCameraSelectorWindow.cpp index 87624b1c8d..828601c5d6 100644 --- a/Gems/Camera/Code/Source/ViewportCameraSelectorWindow.cpp +++ b/Gems/Camera/Code/Source/ViewportCameraSelectorWindow.cpp @@ -125,7 +125,7 @@ namespace Camera }); if (cameraIt != m_cameraItems.end()) { - int listIndex = cameraIt - m_cameraItems.begin(); + int listIndex = aznumeric_cast(cameraIt - m_cameraItems.begin()); beginRemoveRows(QModelIndex(), listIndex, listIndex); m_cameraItems.erase(cameraIt); endRemoveRows(); From 27c0ed987891b8ab9e0e6da689314474d668de67 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Wed, 11 Aug 2021 12:39:16 -0700 Subject: [PATCH 427/803] warning fixes for new code Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Legacy/CrySystem/XConsole.cpp | 2 +- Gems/LyShine/Code/Source/StringUtfUtils.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Code/Legacy/CrySystem/XConsole.cpp b/Code/Legacy/CrySystem/XConsole.cpp index a69fd348f5..2293352f7e 100644 --- a/Code/Legacy/CrySystem/XConsole.cpp +++ b/Code/Legacy/CrySystem/XConsole.cpp @@ -2857,7 +2857,7 @@ void CXConsole::Paste() Utf8::Unchecked::octet_iterator end(data.end()); for (Utf8::Unchecked::octet_iterator it(data.begin()); it != end; ++it) { - const wchar_t cp = *it; + const wchar_t cp = static_cast(*it); if (cp != '\r') { // Convert UCS code-point into UTF-8 string diff --git a/Gems/LyShine/Code/Source/StringUtfUtils.h b/Gems/LyShine/Code/Source/StringUtfUtils.h index 40dd22dd33..247eb07bca 100644 --- a/Gems/LyShine/Code/Source/StringUtfUtils.h +++ b/Gems/LyShine/Code/Source/StringUtfUtils.h @@ -31,7 +31,7 @@ namespace LyShine // work for cases tested but may not in general. // In the long run it would be better to eliminate // this function and use some sequence_lenght function that is not internal. - return Utf8::Internal::sequence_length(&multiByteChar); + return aznumeric_cast(Utf8::Internal::sequence_length(&multiByteChar)); } inline int GetByteLengthOfUtf8Chars(const char* utf8String, int numUtf8Chars) From 75c388b746501fb610c8e2ac3672ebe5bfc1696c Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Wed, 11 Aug 2021 17:03:54 -0700 Subject: [PATCH 428/803] change conversions to static_cast Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Editor/Objects/DisplayContext.h | 10 ++++---- Code/Editor/Util/GuidUtil.h | 16 ++++++------- Code/Editor/Util/Variable.h | 2 +- Code/Framework/AzCore/AzCore/IO/Path/Path.inl | 2 +- .../AzCore/AzCore/StringFunc/StringFunc.cpp | 5 ++-- .../Tests/Memory/HphaSchemaErrorDetection.cpp | 3 +-- Code/Framework/Crcfix/crcfix.cpp | 11 ++++----- .../Code/Source/Converters/ColorChart.cpp | 6 ++--- .../Source/Processing/ImageAssetProducer.cpp | 6 ++--- .../Pass/FullscreenTrianglePass.cpp | 8 +++---- .../Include/Atom/Utils/ImGuiGpuProfiler.inl | 4 ++-- .../Source/CoreLights/SphereLightDelegate.cpp | 4 ++-- .../Code/Source/BarrierInputClient.cpp | 24 +++++++++---------- .../Source/ViewportCameraSelectorWindow.cpp | 2 +- .../Tests/BlendTreeFloatMath1NodeTests.cpp | 2 +- .../Tests/BlendTreeTwoLinkIKNodeTests.cpp | 10 ++++---- Gems/LyShine/Code/Source/StringUtfUtils.h | 2 +- Gems/LyShine/Code/Source/UiFaderComponent.cpp | 2 +- Gems/LyShine/Code/Source/UiMaskComponent.cpp | 4 ++-- 19 files changed, 60 insertions(+), 63 deletions(-) diff --git a/Code/Editor/Objects/DisplayContext.h b/Code/Editor/Objects/DisplayContext.h index 6459497199..47fd450220 100644 --- a/Code/Editor/Objects/DisplayContext.h +++ b/Code/Editor/Objects/DisplayContext.h @@ -83,12 +83,12 @@ struct SANDBOX_API DisplayContext // Draw functions ////////////////////////////////////////////////////////////////////////// //! Set current materialc color. - void SetColor(float r, float g, float b, float a = 1) { m_color4b = ColorB(aznumeric_cast(r * 255.0f), aznumeric_cast(g * 255.0f), aznumeric_cast(b * 255.0f), aznumeric_cast(a * 255.0f)); }; - void SetColor(const Vec3& color, float a = 1) { m_color4b = ColorB(aznumeric_cast(color.x * 255.0f), aznumeric_cast(color.y * 255.0f), aznumeric_cast(color.z * 255.0f), aznumeric_cast(a * 255.0f)); }; - void SetColor(const QColor& rgb, float a) { m_color4b = ColorB(aznumeric_cast(rgb.red()), aznumeric_cast(rgb.green()), aznumeric_cast(rgb.blue()), aznumeric_cast(a * 255.0f)); }; - void SetColor(const QColor& color) { m_color4b = ColorB(aznumeric_cast(color.red()), aznumeric_cast(color.green()), aznumeric_cast(color.blue()), aznumeric_cast(color.alpha())); }; + void SetColor(float r, float g, float b, float a = 1) { m_color4b = ColorB(static_cast(r * 255.0f), static_cast(g * 255.0f), static_cast(b * 255.0f), static_cast(a * 255.0f)); }; + void SetColor(const Vec3& color, float a = 1) { m_color4b = ColorB(static_cast(color.x * 255.0f), static_cast(color.y * 255.0f), static_cast(color.z * 255.0f), static_cast(a * 255.0f)); }; + void SetColor(const QColor& rgb, float a) { m_color4b = ColorB(static_cast(rgb.red()), static_cast(rgb.green()), static_cast(rgb.blue()), static_cast(a * 255.0f)); }; + void SetColor(const QColor& color) { m_color4b = ColorB(static_cast(color.red()), static_cast(color.green()), static_cast(color.blue()), static_cast(color.alpha())); }; void SetColor(const ColorB& color) { m_color4b = color; }; - void SetAlpha(float a = 1) { m_color4b.a = aznumeric_cast(a * 255.0f); }; + void SetAlpha(float a = 1) { m_color4b.a = static_cast(a * 255.0f); }; ColorB GetColor() const { return m_color4b; } void SetSelectedColor(float fAlpha = 1); diff --git a/Code/Editor/Util/GuidUtil.h b/Code/Editor/Util/GuidUtil.h index 138b221c70..9952d6b4ed 100644 --- a/Code/Editor/Util/GuidUtil.h +++ b/Code/Editor/Util/GuidUtil.h @@ -64,14 +64,14 @@ inline GUID GuidUtil::FromString(const char* guidString) guid.Data3 = 0; azsscanf(guidString, "{%8" SCNx32 "-%4hX-%4hX-%2X%2X-%2X%2X%2X%2X%2X%2X}", &guid.Data1, &guid.Data2, &guid.Data3, &d[0], &d[1], &d[2], &d[3], &d[4], &d[5], &d[6], &d[7]); - guid.Data4[0] = aznumeric_cast(d[0]); - guid.Data4[1] = aznumeric_cast(d[1]); - guid.Data4[2] = aznumeric_cast(d[2]); - guid.Data4[3] = aznumeric_cast(d[3]); - guid.Data4[4] = aznumeric_cast(d[4]); - guid.Data4[5] = aznumeric_cast(d[5]); - guid.Data4[6] = aznumeric_cast(d[6]); - guid.Data4[7] = aznumeric_cast(d[7]); + guid.Data4[0] = static_cast(d[0]); + guid.Data4[1] = static_cast(d[1]); + guid.Data4[2] = static_cast(d[2]); + guid.Data4[3] = static_cast(d[3]); + guid.Data4[4] = static_cast(d[4]); + guid.Data4[5] = static_cast(d[5]); + guid.Data4[6] = static_cast(d[6]); + guid.Data4[7] = static_cast(d[7]); return guid; } diff --git a/Code/Editor/Util/Variable.h b/Code/Editor/Util/Variable.h index 6cd69a8cb1..9c3f96a3f6 100644 --- a/Code/Editor/Util/Variable.h +++ b/Code/Editor/Util/Variable.h @@ -405,7 +405,7 @@ public: unsigned char GetDataType() const { return m_dataType; }; void SetDataType(unsigned char dataType) { m_dataType = dataType; } - void SetFlags(int flags) { m_flags = aznumeric_cast(flags); } + void SetFlags(int flags) { m_flags = static_cast(flags); } int GetFlags() const { return m_flags; } void SetFlagRecursive(EFlags flag) { m_flags |= flag; } diff --git a/Code/Framework/AzCore/AzCore/IO/Path/Path.inl b/Code/Framework/AzCore/AzCore/IO/Path/Path.inl index a6d41b0ef8..d0bf4c1dbe 100644 --- a/Code/Framework/AzCore/AzCore/IO/Path/Path.inl +++ b/Code/Framework/AzCore/AzCore/IO/Path/Path.inl @@ -221,7 +221,7 @@ namespace AZ::IO::Internal ? strncmp(left.data(), right.data(), maxCharsToCompare) : azstrnicmp(left.data(), right.data(), maxCharsToCompare); return charCompareResult == 0 - ? aznumeric_cast(aznumeric_cast(left.size()) - aznumeric_cast(right.size())) + ? static_cast(aznumeric_cast(left.size()) - aznumeric_cast(right.size())) : charCompareResult; } } diff --git a/Code/Framework/AzCore/AzCore/StringFunc/StringFunc.cpp b/Code/Framework/AzCore/AzCore/StringFunc/StringFunc.cpp index d4f874c667..ff30291a70 100644 --- a/Code/Framework/AzCore/AzCore/StringFunc/StringFunc.cpp +++ b/Code/Framework/AzCore/AzCore/StringFunc/StringFunc.cpp @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include @@ -343,8 +342,8 @@ namespace AZ::StringFunc::Internal { for (const char stripCharacter : stripCharacters) { - const char lower = azlossy_cast(tolower(stripCharacter)); - const char upper = azlossy_cast(toupper(stripCharacter)); + const char lower = static_cast(tolower(stripCharacter)); + const char upper = static_cast(toupper(stripCharacter)); if (lower != upper) { combinedStripCharacters.push_back(lower); diff --git a/Code/Framework/AzCore/Tests/Memory/HphaSchemaErrorDetection.cpp b/Code/Framework/AzCore/Tests/Memory/HphaSchemaErrorDetection.cpp index 2b0e7bee92..44c1b1641d 100644 --- a/Code/Framework/AzCore/Tests/Memory/HphaSchemaErrorDetection.cpp +++ b/Code/Framework/AzCore/Tests/Memory/HphaSchemaErrorDetection.cpp @@ -17,7 +17,6 @@ #include #include #include -#include namespace Internal @@ -298,7 +297,7 @@ AZ_POP_DISABLE_WARNING // the overflow guard is generated out of rand, so we set a fixed seed before doing the allocation // to get a deterministic guard srand(0); - const unsigned char expectedInitialGuard = azlossy_cast(rand()); + const unsigned char expectedInitialGuard = static_cast(rand()); srand(0); TestClass<16>* someObject = aznew TestClass<16>(); diff --git a/Code/Framework/Crcfix/crcfix.cpp b/Code/Framework/Crcfix/crcfix.cpp index c788d2a0c6..a07054998b 100644 --- a/Code/Framework/Crcfix/crcfix.cpp +++ b/Code/Framework/Crcfix/crcfix.cpp @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include @@ -285,7 +284,7 @@ char* CRCfix::GetToken(FILE* infile, FILE* outfile) { if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '#' || c == '_') { - token[i++] = azlossy_cast(c); + token[i++] = static_cast(c); continue; } else @@ -376,7 +375,7 @@ void CRCfix::GetPreviousCRC(char* token, FILE* infile) int c; while ((c = fgetc(infile)) != ')') { - *token++ = azlossy_cast(c); + *token++ = static_cast(c); } *token = 0; } @@ -427,7 +426,7 @@ int CRCfix::Fix(Filename srce) if (strcmp(token, "AZ_CRC") == 0 && lastchar == '(') { size_t i = strlen(token); - token[i++] = azlossy_cast(lastchar); + token[i++] = static_cast(lastchar); int c = fgetc(infile); if (c == '"') @@ -436,11 +435,11 @@ int CRCfix::Fix(Filename srce) do { - token[i++] = azlossy_cast(c); + token[i++] = static_cast(c); c = fgetc(infile); } while (c != '"'); - token[i++] = azlossy_cast(c); + token[i++] = static_cast(c); c = fgetc(infile); int oldcrc = 0, newcrc; diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Converters/ColorChart.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Converters/ColorChart.cpp index f50ae41c8a..0b06e00a9f 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Converters/ColorChart.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Converters/ColorChart.cpp @@ -76,9 +76,9 @@ namespace ImageProcessingAtom for (int r = 0; r < ePS_Red; ++r) { SColor col; - col.r = aznumeric_cast(255 * r / (ePS_Red)); - col.g = aznumeric_cast(255 * g / (ePS_Green)); - col.b = aznumeric_cast(255 * b / (ePS_Blue)); + col.r = static_cast(255 * r / (ePS_Red)); + col.g = static_cast(255 * g / (ePS_Green)); + col.b = static_cast(255 * b / (ePS_Blue)); int l = 255 - (col.r * 3 + col.g * 6 + col.b) / 10; col.r = col.g = col.b = (unsigned char)l; m_mapping.push_back(col); diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageAssetProducer.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageAssetProducer.cpp index 1e4133b5b2..c254d172ad 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageAssetProducer.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageAssetProducer.cpp @@ -97,8 +97,8 @@ namespace ImageProcessingAtom RHI::Format format = Utils::PixelFormatToRHIFormat(m_imageObject->GetPixelFormat(), m_imageObject->HasImageFlags(EIF_SRGBRead)); RHI::ImageBindFlags bindFlag = RHI::ImageBindFlags::ShaderRead; - RHI::ImageDescriptor imageDesc = RHI::ImageDescriptor::Create2DArray(bindFlag, imageWidth, imageHeight, aznumeric_cast(arraySize), format); - imageDesc.m_mipLevels = aznumeric_cast(m_imageObject->GetMipCount()); + RHI::ImageDescriptor imageDesc = RHI::ImageDescriptor::Create2DArray(bindFlag, imageWidth, imageHeight, static_cast(arraySize), format); + imageDesc.m_mipLevels = static_cast(m_imageObject->GetMipCount()); if (m_imageObject->HasImageFlags(EIF_Cubemap)) { imageDesc.m_isCubemap = true; @@ -227,7 +227,7 @@ namespace ImageProcessingAtom { RPI::ImageMipChainAssetCreator builder; uint32_t arraySize = m_imageObject->HasImageFlags(EIF_Cubemap) ? 6 : 1; - builder.Begin(chainAssetId, aznumeric_cast(mipLevels), aznumeric_cast(arraySize)); + builder.Begin(chainAssetId, static_cast(mipLevels), static_cast(arraySize)); for (uint32_t mip = startMip; mip < startMip + mipLevels; mip++) { diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/FullscreenTrianglePass.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/FullscreenTrianglePass.cpp index 7a9481a45c..40dce7d138 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/FullscreenTrianglePass.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/FullscreenTrianglePass.cpp @@ -179,10 +179,10 @@ namespace AZ RHI::Size targetImageSize = outputAttachment->m_descriptor.m_image.m_size; - m_viewportState.m_maxX = aznumeric_cast(AZStd::min(static_cast(params.m_viewportState.m_maxX), targetImageSize.m_width)); - m_viewportState.m_maxY = aznumeric_cast(AZStd::min(static_cast(params.m_viewportState.m_maxY), targetImageSize.m_height)); - m_viewportState.m_minX = aznumeric_cast(AZStd::min(params.m_viewportState.m_minX, m_viewportState.m_maxX)); - m_viewportState.m_minY = aznumeric_cast(AZStd::min(params.m_viewportState.m_minY, m_viewportState.m_maxY)); + m_viewportState.m_maxX = static_cast(AZStd::min(static_cast(params.m_viewportState.m_maxX), targetImageSize.m_width)); + m_viewportState.m_maxY = static_cast(AZStd::min(static_cast(params.m_viewportState.m_maxY), targetImageSize.m_height)); + m_viewportState.m_minX = static_cast(AZStd::min(params.m_viewportState.m_minX, m_viewportState.m_maxX)); + m_viewportState.m_minY = static_cast(AZStd::min(params.m_viewportState.m_minY, m_viewportState.m_maxY)); m_scissorState.m_maxX = AZStd::min(static_cast(params.m_scissorState.m_maxX), targetImageSize.m_width); m_scissorState.m_maxY = AZStd::min(static_cast(params.m_scissorState.m_maxY), targetImageSize.m_height); diff --git a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiGpuProfiler.inl b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiGpuProfiler.inl index 47a9fa6772..e6bde136f8 100644 --- a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiGpuProfiler.inl +++ b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiGpuProfiler.inl @@ -1092,8 +1092,8 @@ namespace AZ AZStd::sort(m_tableRows.begin(), m_tableRows.end(), [ascending](const TableRow& lhs, const TableRow& rhs) { - const float lhsSize = aznumeric_cast(lhs.m_sizeInBytes); - const float rhsSize = aznumeric_cast(rhs.m_sizeInBytes); + const float lhsSize = static_cast(lhs.m_sizeInBytes); + const float rhsSize = static_cast(rhs.m_sizeInBytes); return ascending ? lhsSize < rhsSize : lhsSize > rhsSize; }); break; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SphereLightDelegate.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SphereLightDelegate.cpp index b48098819b..b4728c0c38 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SphereLightDelegate.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SphereLightDelegate.cpp @@ -104,7 +104,7 @@ namespace AZ::Render { if (GetShadowsEnabled() && GetLightHandle().IsValid()) { - GetFeatureProcessor()->SetPredictionSampleCount(GetLightHandle(), aznumeric_cast(count)); + GetFeatureProcessor()->SetPredictionSampleCount(GetLightHandle(), static_cast(count)); } } @@ -112,7 +112,7 @@ namespace AZ::Render { if (GetShadowsEnabled() && GetLightHandle().IsValid()) { - GetFeatureProcessor()->SetFilteringSampleCount(GetLightHandle(), aznumeric_cast(count)); + GetFeatureProcessor()->SetFilteringSampleCount(GetLightHandle(), static_cast(count)); } } diff --git a/Gems/BarrierInput/Code/Source/BarrierInputClient.cpp b/Gems/BarrierInput/Code/Source/BarrierInputClient.cpp index 25a95752ac..e6d5399561 100644 --- a/Gems/BarrierInput/Code/Source/BarrierInputClient.cpp +++ b/Gems/BarrierInput/Code/Source/BarrierInputClient.cpp @@ -57,31 +57,31 @@ namespace BarrierInput void InsertString(const char* str) { int len = static_cast(strlen(str)); memcpy(end, str, len); end += len; } void InsertU32(int a) { - end[0] = aznumeric_cast(a >> 24); - end[1] = aznumeric_cast(a >> 16); - end[2] = aznumeric_cast(a >> 8); - end[3] = aznumeric_cast(a); + end[0] = static_cast(a >> 24); + end[1] = static_cast(a >> 16); + end[2] = static_cast(a >> 8); + end[3] = static_cast(a); end += 4; } void InsertU16(int a) { - end[0] = aznumeric_cast(a >> 8); - end[1] = aznumeric_cast(a); + end[0] = static_cast(a >> 8); + end[1] = static_cast(a); end += 2; } void InsertU8(int a) { - end[0] = aznumeric_cast(a); + end[0] = static_cast(a); end += 1; } void OpenPacket() { packet = end; end += 4; } void ClosePacket() { int len = GetLength() - sizeof(AZ::u32); - packet[0] = aznumeric_cast(len >> 24); - packet[1] = aznumeric_cast(len >> 16); - packet[2] = aznumeric_cast(len >> 8); - packet[3] = aznumeric_cast(len); + packet[0] = static_cast(len >> 24); + packet[1] = static_cast(len >> 16); + packet[2] = static_cast(len >> 8); + packet[3] = static_cast(len); packet = nullptr; } }; @@ -405,7 +405,7 @@ namespace BarrierInput if (AZ::AzSock::IsAzSocketValid(m_socket)) { AZ::AzSock::AzSocketAddress socketAddress; - if (socketAddress.SetAddress(m_serverHostName.c_str(), aznumeric_cast(m_connectionPort))) + if (socketAddress.SetAddress(m_serverHostName.c_str(), static_cast(m_connectionPort))) { const int result = AZ::AzSock::Connect(m_socket, socketAddress); if (!AZ::AzSock::SocketErrorOccured(result)) diff --git a/Gems/Camera/Code/Source/ViewportCameraSelectorWindow.cpp b/Gems/Camera/Code/Source/ViewportCameraSelectorWindow.cpp index 828601c5d6..7a8d6be020 100644 --- a/Gems/Camera/Code/Source/ViewportCameraSelectorWindow.cpp +++ b/Gems/Camera/Code/Source/ViewportCameraSelectorWindow.cpp @@ -125,7 +125,7 @@ namespace Camera }); if (cameraIt != m_cameraItems.end()) { - int listIndex = aznumeric_cast(cameraIt - m_cameraItems.begin()); + int listIndex = static_cast(cameraIt - m_cameraItems.begin()); beginRemoveRows(QModelIndex(), listIndex, listIndex); m_cameraItems.erase(cameraIt); endRemoveRows(); diff --git a/Gems/EMotionFX/Code/Tests/BlendTreeFloatMath1NodeTests.cpp b/Gems/EMotionFX/Code/Tests/BlendTreeFloatMath1NodeTests.cpp index 5827c5f186..f4b11a3f8a 100644 --- a/Gems/EMotionFX/Code/Tests/BlendTreeFloatMath1NodeTests.cpp +++ b/Gems/EMotionFX/Code/Tests/BlendTreeFloatMath1NodeTests.cpp @@ -98,7 +98,7 @@ namespace EMotionFX void TestInput(const AZStd::string& paramName, std::vector xInputs) { BlendTreeConnection* connection = m_floatMath1Node->AddConnection(m_paramNode, - aznumeric_cast(m_paramNode->FindOutputPortByName(paramName)->m_portId), BlendTreeFloatMath1Node::PORTID_INPUT_X); + static_cast(m_paramNode->FindOutputPortByName(paramName)->m_portId), BlendTreeFloatMath1Node::PORTID_INPUT_X); for (inputType i : xInputs) { diff --git a/Gems/EMotionFX/Code/Tests/BlendTreeTwoLinkIKNodeTests.cpp b/Gems/EMotionFX/Code/Tests/BlendTreeTwoLinkIKNodeTests.cpp index ede6f5dcbe..eab445ddfe 100644 --- a/Gems/EMotionFX/Code/Tests/BlendTreeTwoLinkIKNodeTests.cpp +++ b/Gems/EMotionFX/Code/Tests/BlendTreeTwoLinkIKNodeTests.cpp @@ -137,9 +137,9 @@ namespace EMotionFX TEST_P(BlendTreeTwoLinkIKNodeFixture, ReachablePositionsOutputCorrectPose) { // Set values for vector3 and twoLinkIKNode weight parameter - m_twoLinkIKNode->AddConnection(m_paramNode, aznumeric_cast(m_paramNode->FindOutputPortByName("WeightParam")->m_portId), BlendTreeTwoLinkIKNode::INPUTPORT_WEIGHT); + m_twoLinkIKNode->AddConnection(m_paramNode, static_cast(m_paramNode->FindOutputPortByName("WeightParam")->m_portId), BlendTreeTwoLinkIKNode::INPUTPORT_WEIGHT); m_twoLinkIKNode->AddConnection(m_paramNode, - aznumeric_cast(m_paramNode->FindOutputPortByName("GoalPosParam")->m_portId), BlendTreeTwoLinkIKNode::INPUTPORT_GOALPOS); + static_cast(m_paramNode->FindOutputPortByName("GoalPosParam")->m_portId), BlendTreeTwoLinkIKNode::INPUTPORT_GOALPOS); GetEMotionFX().Update(1.0f / 60.0f); const float weight = testing::get<0>(GetParam()); @@ -179,7 +179,7 @@ namespace EMotionFX TEST_P(BlendTreeTwoLinkIKNodeFixture, ReachableAlignToNodeOutputCorrectPose) { - m_twoLinkIKNode->AddConnection(m_paramNode, aznumeric_cast(m_paramNode->FindOutputPortByName("WeightParam")->m_portId), + m_twoLinkIKNode->AddConnection(m_paramNode, static_cast(m_paramNode->FindOutputPortByName("WeightParam")->m_portId), BlendTreeTwoLinkIKNode::INPUTPORT_WEIGHT); GetEMotionFX().Update(1.0f / 60.0f); @@ -224,7 +224,7 @@ namespace EMotionFX TEST_P(BlendTreeTwoLinkIKNodeFixture, UnreachablePositionsOutputCorrectPose) { - m_twoLinkIKNode->AddConnection(m_paramNode, aznumeric_cast(m_paramNode->FindOutputPortByName("WeightParam")->m_portId), + m_twoLinkIKNode->AddConnection(m_paramNode, static_cast(m_paramNode->FindOutputPortByName("WeightParam")->m_portId), BlendTreeTwoLinkIKNode::INPUTPORT_WEIGHT); m_twoLinkIKNode->AddConnection(m_paramNode, static_cast(m_paramNode->FindOutputPortByName("GoalPosParam")->m_portId), BlendTreeTwoLinkIKNode::INPUTPORT_GOALPOS); @@ -275,7 +275,7 @@ namespace EMotionFX m_twoLinkIKNode->AddConnection(m_paramNode, static_cast(m_paramNode->FindOutputPortByName("WeightParam")->m_portId), BlendTreeTwoLinkIKNode::INPUTPORT_WEIGHT); m_twoLinkIKNode->AddConnection(m_paramNode, - aznumeric_cast(m_paramNode->FindOutputPortByName("GoalPosParam")->m_portId), BlendTreeTwoLinkIKNode::INPUTPORT_GOALPOS); + static_cast(m_paramNode->FindOutputPortByName("GoalPosParam")->m_portId), BlendTreeTwoLinkIKNode::INPUTPORT_GOALPOS); m_twoLinkIKNode->AddConnection(m_paramNode, static_cast(m_paramNode->FindOutputPortByName("RotationParam")->m_portId), BlendTreeTwoLinkIKNode::INPUTPORT_GOALROT); m_twoLinkIKNode->SetRotationEnabled(true); diff --git a/Gems/LyShine/Code/Source/StringUtfUtils.h b/Gems/LyShine/Code/Source/StringUtfUtils.h index 247eb07bca..9c185d48ef 100644 --- a/Gems/LyShine/Code/Source/StringUtfUtils.h +++ b/Gems/LyShine/Code/Source/StringUtfUtils.h @@ -31,7 +31,7 @@ namespace LyShine // work for cases tested but may not in general. // In the long run it would be better to eliminate // this function and use some sequence_lenght function that is not internal. - return aznumeric_cast(Utf8::Internal::sequence_length(&multiByteChar)); + return static_cast(Utf8::Internal::sequence_length(&multiByteChar)); } inline int GetByteLengthOfUtf8Chars(const char* utf8String, int numUtf8Chars) diff --git a/Gems/LyShine/Code/Source/UiFaderComponent.cpp b/Gems/LyShine/Code/Source/UiFaderComponent.cpp index acdf462df7..e7eca04c59 100644 --- a/Gems/LyShine/Code/Source/UiFaderComponent.cpp +++ b/Gems/LyShine/Code/Source/UiFaderComponent.cpp @@ -463,7 +463,7 @@ void UiFaderComponent::CreateOrResizeRenderTarget(const AZ::Vector2& pixelAligne // Create a render target that this element and its children will be rendered to AZ::EntityId canvasEntityId; EBUS_EVENT_ID_RESULT(canvasEntityId, GetEntityId(), UiElementBus, GetCanvasEntityId); - AZ::RHI::Size imageSize(aznumeric_cast(renderTargetSize.GetX()), aznumeric_cast(renderTargetSize.GetY()), 1); + AZ::RHI::Size imageSize(static_cast(renderTargetSize.GetX()), static_cast(renderTargetSize.GetY()), 1); EBUS_EVENT_ID_RESULT(m_attachmentImageId, canvasEntityId, LyShine::RenderToTextureRequestBus, UseRenderTarget, AZ::Name(m_renderTargetName.c_str()), imageSize); if (m_attachmentImageId.IsEmpty()) { diff --git a/Gems/LyShine/Code/Source/UiMaskComponent.cpp b/Gems/LyShine/Code/Source/UiMaskComponent.cpp index 869529560f..d6ed468deb 100644 --- a/Gems/LyShine/Code/Source/UiMaskComponent.cpp +++ b/Gems/LyShine/Code/Source/UiMaskComponent.cpp @@ -564,7 +564,7 @@ void UiMaskComponent::CreateOrResizeRenderTarget(const AZ::Vector2& pixelAligned // Create a render target that this element and its children will be rendered to AZ::EntityId canvasEntityId; EBUS_EVENT_ID_RESULT(canvasEntityId, GetEntityId(), UiElementBus, GetCanvasEntityId); - AZ::RHI::Size imageSize(aznumeric_cast(renderTargetSize.GetX()), aznumeric_cast(renderTargetSize.GetY()), 1); + AZ::RHI::Size imageSize(static_cast(renderTargetSize.GetX()), static_cast(renderTargetSize.GetY()), 1); EBUS_EVENT_ID_RESULT(m_contentAttachmentImageId, canvasEntityId, LyShine::RenderToTextureRequestBus, UseRenderTarget, AZ::Name(m_renderTargetName.c_str()), imageSize); if (m_contentAttachmentImageId.IsEmpty()) { @@ -762,7 +762,7 @@ void UiMaskComponent::RenderUsingGradientMask(LyShine::IRenderGraph* renderGraph { // go through all the cached vertices and update the alpha values UCol desiredPackedColor = m_cachedPrimitive.m_vertices[0].color; - desiredPackedColor.a = aznumeric_cast(desiredPackedAlpha); + desiredPackedColor.a = static_cast(desiredPackedAlpha); for (int i = 0; i < m_cachedPrimitive.m_numVertices; ++i) { m_cachedPrimitive.m_vertices[i].color = desiredPackedColor; From 52068911bb7c9ff39126dca6bdbc3ec2576a48bc Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Wed, 11 Aug 2021 19:35:13 -0700 Subject: [PATCH 429/803] More fixes that are failing on Jenkins but not locally Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../AzToolsFramework/Input/QtEventToAzInputManager.cpp | 4 ++-- .../AzToolsFramework/UI/Outliner/EntityOutlinerListModel.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Input/QtEventToAzInputManager.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Input/QtEventToAzInputManager.cpp index f8665d583e..feb7a35433 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Input/QtEventToAzInputManager.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Input/QtEventToAzInputManager.cpp @@ -307,9 +307,9 @@ namespace AzToolsFramework // Generate movement events based on the pixel delta divided by the DPI scaling factor, to calculate a rough approximation // of cursor movement velocity. movementXChannel->ProcessRawInputEvent( - m_cursorPosition->m_normalizedPositionDelta.GetX() * aznumeric_cast(m_sourceWidget->width()) / m_sourceWidget->devicePixelRatioF()); + static_cast(m_cursorPosition->m_normalizedPositionDelta.GetX()) * aznumeric_cast(m_sourceWidget->width()) / m_sourceWidget->devicePixelRatioF()); movementYChannel->ProcessRawInputEvent( - m_cursorPosition->m_normalizedPositionDelta.GetY() * aznumeric_cast(m_sourceWidget->height()) / m_sourceWidget->devicePixelRatioF()); + static_cast(m_cursorPosition->m_normalizedPositionDelta.GetY()) * aznumeric_cast(m_sourceWidget->height()) / m_sourceWidget->devicePixelRatioF()); mouseWheelChannel->ProcessRawInputEvent(0.f); NotifyUpdateChannelIfNotIdle(systemCursorChannel, nullptr); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerListModel.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerListModel.cpp index 4115fe409e..44dbbee025 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerListModel.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerListModel.cpp @@ -2180,7 +2180,7 @@ namespace AzToolsFramework QPainterPath path; auto newRect = option.rect; - newRect.setHeight(newRect.height() - 1.0); + newRect.setHeight(newRect.height() - 1); path.addRect(newRect); // Get the foreground color of the current object to draw our sub-object-selected box From 8b3ab8eb0bb5c6c535c9b0b49df0d1bbc5c5e599 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Thu, 12 Aug 2021 17:26:56 -0700 Subject: [PATCH 430/803] fixing warning issued in Jenkins Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../AzToolsFramework/Input/QtEventToAzInputManager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Input/QtEventToAzInputManager.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Input/QtEventToAzInputManager.cpp index feb7a35433..4f238ac336 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Input/QtEventToAzInputManager.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Input/QtEventToAzInputManager.cpp @@ -307,9 +307,9 @@ namespace AzToolsFramework // Generate movement events based on the pixel delta divided by the DPI scaling factor, to calculate a rough approximation // of cursor movement velocity. movementXChannel->ProcessRawInputEvent( - static_cast(m_cursorPosition->m_normalizedPositionDelta.GetX()) * aznumeric_cast(m_sourceWidget->width()) / m_sourceWidget->devicePixelRatioF()); + m_cursorPosition->m_normalizedPositionDelta.GetX() * aznumeric_cast(m_sourceWidget->width()) / static_cast(m_sourceWidget->devicePixelRatioF())); movementYChannel->ProcessRawInputEvent( - static_cast(m_cursorPosition->m_normalizedPositionDelta.GetY()) * aznumeric_cast(m_sourceWidget->height()) / m_sourceWidget->devicePixelRatioF()); + m_cursorPosition->m_normalizedPositionDelta.GetY() * aznumeric_cast(m_sourceWidget->height()) / static_cast(m_sourceWidget->devicePixelRatioF())); mouseWheelChannel->ProcessRawInputEvent(0.f); NotifyUpdateChannelIfNotIdle(systemCursorChannel, nullptr); From 3522f622f38d7fe8f5bdb3e274583e31e3528a57 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Thu, 12 Aug 2021 18:37:59 -0700 Subject: [PATCH 431/803] more castings Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Editor/Objects/DisplayContextShared.inl | 7 +++++-- Code/Editor/editor_lib_files.cmake | 1 + .../Tests/EditorTransformComponentSelectionTests.cpp | 2 +- .../Prefab/Benchmark/PrefabCreateBenchmarks.cpp | 8 ++++---- .../Prefab/Benchmark/PrefabInstantiateBenchmarks.cpp | 2 +- .../Benchmark/PrefabUpdateInstancesBenchmarks.cpp | 10 +++++----- .../Prefab/Benchmark/SpawnableCreateBenchmarks.cpp | 2 +- .../Code/Source/Converters/FIR-Weights.cpp | 10 +++++----- .../Source/ActionHistory/ActionHistoryPlugin.cpp | 2 +- .../Source/AnimGraph/GameControllerWindow.cpp | 8 ++++---- .../Code/Tests/PythonDictionaryTests.cpp | 4 ++-- .../Code/Tests/SceneBuilder/SceneBuilderTests.cpp | 12 ++++++------ .../Editor/View/Windows/ScriptCanvasContextMenus.cpp | 2 +- 13 files changed, 37 insertions(+), 33 deletions(-) diff --git a/Code/Editor/Objects/DisplayContextShared.inl b/Code/Editor/Objects/DisplayContextShared.inl index a602d8eca9..5af04d821e 100644 --- a/Code/Editor/Objects/DisplayContextShared.inl +++ b/Code/Editor/Objects/DisplayContextShared.inl @@ -63,7 +63,7 @@ void DisplayContext::InternalDrawLine(const Vec3& v0, const ColorB& colV0, const ////////////////////////////////////////////////////////////////////////// void DisplayContext::DrawPoint(const Vec3& p, int nSize) { - pRenderAuxGeom->DrawPoint(ToWorldSpacePosition(p), m_color4b, nSize); + pRenderAuxGeom->DrawPoint(ToWorldSpacePosition(p), m_color4b, static_cast(nSize)); } ////////////////////////////////////////////////////////////////////////// @@ -856,7 +856,10 @@ void DisplayContext::DrawLine(const Vec3& p1, const Vec3& p2, const ColorF& col1 ////////////////////////////////////////////////////////////////////////// void DisplayContext::DrawLine(const Vec3& p1, const Vec3& p2, const QColor& rgb1, const QColor& rgb2) { - InternalDrawLine(ToWorldSpacePosition(p1), ColorB(rgb1.red(), rgb1.green(), rgb1.blue(), 255), ToWorldSpacePosition(p2), ColorB(rgb2.red(), rgb2.green(), rgb2.blue(), 255)); + InternalDrawLine(ToWorldSpacePosition(p1), + ColorB(static_cast(rgb1.red()), static_cast(rgb1.green()), static_cast(rgb1.blue()), 255), + ToWorldSpacePosition(p2), + ColorB(static_cast(rgb2.red()), static_cast(rgb2.green()), static_cast(rgb2.blue()), 255)); } ////////////////////////////////////////////////////////////////////////// diff --git a/Code/Editor/editor_lib_files.cmake b/Code/Editor/editor_lib_files.cmake index c10db3bac5..6c5096a8f5 100644 --- a/Code/Editor/editor_lib_files.cmake +++ b/Code/Editor/editor_lib_files.cmake @@ -503,6 +503,7 @@ set(FILES LogFileImpl.h Objects/ClassDesc.cpp Objects/ClassDesc.h + Objects/DisplayContextShared.inl Objects/IEntityObjectListener.h Objects/SelectionGroup.cpp Objects/SelectionGroup.h diff --git a/Code/Framework/AzToolsFramework/Tests/EditorTransformComponentSelectionTests.cpp b/Code/Framework/AzToolsFramework/Tests/EditorTransformComponentSelectionTests.cpp index 895c91b0a4..e95f7aa271 100644 --- a/Code/Framework/AzToolsFramework/Tests/EditorTransformComponentSelectionTests.cpp +++ b/Code/Framework/AzToolsFramework/Tests/EditorTransformComponentSelectionTests.cpp @@ -583,7 +583,7 @@ namespace UnitTest AzToolsFramework::EditorInteractionSystemViewportSelectionRequestBus::EventResult( m_mouseInteractionResult, AzToolsFramework::GetEntityContextId(), &AzToolsFramework::EditorInteractionSystemViewportSelectionRequestBus::Events::InternalHandleAllMouseInteractions, - vi::MouseInteractionEvent(mouseInteraction, ev->angleDelta().y())); + vi::MouseInteractionEvent(mouseInteraction, static_cast(ev->angleDelta().y()))); } MouseInteractionResult m_mouseInteractionResult; diff --git a/Code/Framework/AzToolsFramework/Tests/Prefab/Benchmark/PrefabCreateBenchmarks.cpp b/Code/Framework/AzToolsFramework/Tests/Prefab/Benchmark/PrefabCreateBenchmarks.cpp index 12efea1cc8..64c4058a47 100644 --- a/Code/Framework/AzToolsFramework/Tests/Prefab/Benchmark/PrefabCreateBenchmarks.cpp +++ b/Code/Framework/AzToolsFramework/Tests/Prefab/Benchmark/PrefabCreateBenchmarks.cpp @@ -16,7 +16,7 @@ namespace Benchmark BENCHMARK_DEFINE_F(BM_PrefabCreate, CreatePrefabs_SingleEntityEach)(::benchmark::State& state) { - const unsigned int numEntities = state.range(); + const unsigned int numEntities = static_cast(state.range()); const unsigned int numInstances = numEntities; CreateFakePaths(numInstances); @@ -58,7 +58,7 @@ namespace Benchmark BENCHMARK_DEFINE_F(BM_PrefabCreate, CreatePrefab_FromEntities)(::benchmark::State& state) { - const unsigned int numEntities = state.range(); + const unsigned int numEntities = static_cast(state.range()); for (auto _ : state) { @@ -93,7 +93,7 @@ namespace Benchmark BENCHMARK_DEFINE_F(BM_PrefabCreate, CreatePrefab_FromSingleDepthInstances)(::benchmark::State& state) { - const unsigned int numInstancesToAdd = state.range(); + const unsigned int numInstancesToAdd = static_cast(state.range()); const unsigned int numEntities = numInstancesToAdd; // Create fake paths for all the nested instances @@ -144,7 +144,7 @@ namespace Benchmark BENCHMARK_DEFINE_F(BM_PrefabCreate, CreatePrefab_FromLinearNestingOfInstances)(::benchmark::State& state) { - const unsigned int numInstances = state.range(); + const unsigned int numInstances = static_cast(state.range()); // Create fake paths for all the nested instances // plus the root instance diff --git a/Code/Framework/AzToolsFramework/Tests/Prefab/Benchmark/PrefabInstantiateBenchmarks.cpp b/Code/Framework/AzToolsFramework/Tests/Prefab/Benchmark/PrefabInstantiateBenchmarks.cpp index 90ff30a30e..f2f3cf82b0 100644 --- a/Code/Framework/AzToolsFramework/Tests/Prefab/Benchmark/PrefabInstantiateBenchmarks.cpp +++ b/Code/Framework/AzToolsFramework/Tests/Prefab/Benchmark/PrefabInstantiateBenchmarks.cpp @@ -16,7 +16,7 @@ namespace Benchmark BENCHMARK_DEFINE_F(BM_PrefabInstantiate, InstantiatePrefab_SingleEntityInstance)(::benchmark::State& state) { - const unsigned int numInstances = state.range(); + const unsigned int numInstances = static_cast(state.range()); AZStd::unique_ptr firstInstance = m_prefabSystemComponent->CreatePrefab( { CreateEntity("Entity1") }, diff --git a/Code/Framework/AzToolsFramework/Tests/Prefab/Benchmark/PrefabUpdateInstancesBenchmarks.cpp b/Code/Framework/AzToolsFramework/Tests/Prefab/Benchmark/PrefabUpdateInstancesBenchmarks.cpp index f1e319b28a..0d95049e76 100644 --- a/Code/Framework/AzToolsFramework/Tests/Prefab/Benchmark/PrefabUpdateInstancesBenchmarks.cpp +++ b/Code/Framework/AzToolsFramework/Tests/Prefab/Benchmark/PrefabUpdateInstancesBenchmarks.cpp @@ -18,7 +18,7 @@ namespace Benchmark BENCHMARK_DEFINE_F(BM_PrefabUpdateInstances, UpdateInstances_SingeEntityInstances)(::benchmark::State& state) { - const unsigned int numInstances = state.range(); + const unsigned int numInstances = static_cast(state.range()); CreateFakePaths(2); const auto& nestedTemplatePath = m_paths.front(); @@ -80,7 +80,7 @@ namespace Benchmark BENCHMARK_DEFINE_F(BM_PrefabUpdateInstances, UpdateInstances_SingleLinearNestingOfInstances)(::benchmark::State& state) { - const unsigned int maxDepth = state.range(); + const unsigned int maxDepth = static_cast(state.range()); CreateFakePaths(maxDepth); const unsigned int numInstances = maxDepth; @@ -131,8 +131,8 @@ namespace Benchmark BENCHMARK_DEFINE_F(BM_PrefabUpdateInstances, UpdateInstances_MultipleLinearNestingOfInstances)(::benchmark::State& state) { - const unsigned int numRootInstances = state.range(); - const unsigned int maxDepth = state.range(); + const unsigned int numRootInstances = static_cast(state.range()); + const unsigned int maxDepth = static_cast(state.range()); CreateFakePaths(maxDepth); const unsigned int numInstances = numRootInstances * maxDepth; @@ -192,7 +192,7 @@ namespace Benchmark BENCHMARK_DEFINE_F(BM_PrefabUpdateInstances, UpdateInstances_BinaryTreeNestedInstanceHierarchy)(::benchmark::State& state) { - const unsigned int maxDepth = state.range(); + const unsigned int maxDepth = static_cast(state.range()); CreateFakePaths(maxDepth); const unsigned int numInstances = (1 << maxDepth) - 1; diff --git a/Code/Framework/AzToolsFramework/Tests/Prefab/Benchmark/SpawnableCreateBenchmarks.cpp b/Code/Framework/AzToolsFramework/Tests/Prefab/Benchmark/SpawnableCreateBenchmarks.cpp index 54e53a6ebc..d9024114a5 100644 --- a/Code/Framework/AzToolsFramework/Tests/Prefab/Benchmark/SpawnableCreateBenchmarks.cpp +++ b/Code/Framework/AzToolsFramework/Tests/Prefab/Benchmark/SpawnableCreateBenchmarks.cpp @@ -18,7 +18,7 @@ namespace Benchmark BENCHMARK_DEFINE_F(BM_SpawnableCreate, CreateSpawnable_SingleEntityInstance)(::benchmark::State& state) { - const unsigned int numSpawnables = state.range(); + const unsigned int numSpawnables = static_cast(state.range()); AZStd::unique_ptr instance(m_prefabSystemComponent->CreatePrefab( { CreateEntity("Entity1") }, diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Converters/FIR-Weights.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Converters/FIR-Weights.cpp index a7689a86ba..170805aa57 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Converters/FIR-Weights.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Converters/FIR-Weights.cpp @@ -17,7 +17,7 @@ namespace ImageProcessingAtom { float round(float x) { - return ((x) >= 0) ? floor((x) + 0.5) : ceil((x)-0.5); + return ((x) >= 0.f) ? floor((x) + 0.5f) : ceil((x) - 0.5f); } void calculateFilterRange(unsigned int srcFactor, int& srcFirst, int& srcLast, @@ -220,7 +220,7 @@ namespace ImageProcessingAtom /* normalize against the peak sumWeights, because the sums are not allowed to leave -32768/32767 */ fWeight = fWeight * nrmWeights; - iWeight = int(round(fWeight)); + iWeight = int(round(static_cast(fWeight))); /* find first nonzero */ if (stillzero && (iWeight == 0)) @@ -246,7 +246,7 @@ namespace ImageProcessingAtom /* add weight to table, interleaved sign */ for (n = 0; n < -numRepetitions; n++) { - *weightsPtr++ = sgnextend(n, -iWeight); + *weightsPtr++ = static_cast(sgnextend(n, -iWeight)); } } else @@ -254,7 +254,7 @@ namespace ImageProcessingAtom /* add weight to table */ for (n = 0; n < numRepetitions; n++) { - *weightsPtr++ = -iWeight; + *weightsPtr++ = static_cast(-iWeight); } } @@ -311,7 +311,7 @@ namespace ImageProcessingAtom for (n = 0, weightsPtr = weightsMem + (i - i0) * numRepetitions; n < numRepetitions; n++) { - *weightsPtr++ -= iWeight; + *weightsPtr++ -= static_cast(iWeight); } } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/ActionHistory/ActionHistoryPlugin.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/ActionHistory/ActionHistoryPlugin.cpp index d84bbebbc6..728ceb059b 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/ActionHistory/ActionHistoryPlugin.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/ActionHistory/ActionHistoryPlugin.cpp @@ -114,7 +114,7 @@ namespace EMStudio } // Set the current history index in case the user called undo. - m_list->setCurrentRow(commandManager->GetHistoryIndex()); + m_list->setCurrentRow(static_cast(commandManager->GetHistoryIndex())); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GameControllerWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GameControllerWindow.cpp index c17ff12947..6434799773 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GameControllerWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/GameControllerWindow.cpp @@ -1176,7 +1176,7 @@ namespace EMStudio } else { - settingsInfo->m_axis = elementID; + settingsInfo->m_axis = static_cast(elementID); } } else @@ -1188,7 +1188,7 @@ namespace EMStudio } else { - settingsInfo->m_axis = value - 1; + settingsInfo->m_axis = static_cast(value - 1); } } #else @@ -1619,7 +1619,7 @@ namespace EMStudio const uint32 numButtons = m_gameController->GetNumButtons(); for (uint32 i = 0; i < numButtons; ++i) { - const bool isPressed = m_gameController->GetIsButtonPressed(i); + const bool isPressed = m_gameController->GetIsButtonPressed(static_cast(i)); // get the game controller settings info for the given button EMotionFX::AnimGraphGameControllerSettings::ButtonInfo* settingsInfo = activePreset->FindButtonInfo(i); @@ -1792,7 +1792,7 @@ namespace EMStudio m_string.clear(); for (uint32 i = 0; i < numButtons; ++i) { - if (m_gameController->GetIsButtonPressed(i)) + if (m_gameController->GetIsButtonPressed(static_cast(i))) { m_string += AZStd::string::format("%s%d ", (i < 10) ? "0" : "", i); } diff --git a/Gems/EditorPythonBindings/Code/Tests/PythonDictionaryTests.cpp b/Gems/EditorPythonBindings/Code/Tests/PythonDictionaryTests.cpp index 8f6abd5a17..24689bbfe3 100644 --- a/Gems/EditorPythonBindings/Code/Tests/PythonDictionaryTests.cpp +++ b/Gems/EditorPythonBindings/Code/Tests/PythonDictionaryTests.cpp @@ -52,8 +52,8 @@ namespace UnitTest } }; - MapOf m_indexOfu8tou32 { {1, 4}, {2, 5}, {3, 6}, {4, 7} }; - MapOf m_indexOfu16toFloat { {1, 0.4f}, {2, 0.5f}, {3, 0.6f}, {4, 0.7f} }; + MapOf m_indexOfu8tou32 { {AZ::u8(1), 4u}, {AZ::u8(2), 5u}, {AZ::u8(3), 6u}, {AZ::u8(4), 7u} }; + MapOf m_indexOfu16toFloat { {AZ::u16(1u), 0.4f}, {AZ::u16(2u), 0.5f}, {AZ::u16(3u), 0.6f}, {AZ::u16(4u), 0.7f} }; MapOf m_indexOfStringTos32 { {"1", -4}, {"2", 5}, {"3", -6}, {"4", 7} }; MapOf m_indexOfStringToString { {"hello", "foo"}, {"world", "bar"}, {"bye", "baz"}, {"sky", "qux"} }; MapOf m_indexOfStringToVec3{ {"up", AZ::Vector3{ 0, 1.0, 0 }}, {"down", AZ::Vector3{0, -1.0, 0}}, diff --git a/Gems/SceneProcessing/Code/Tests/SceneBuilder/SceneBuilderTests.cpp b/Gems/SceneProcessing/Code/Tests/SceneBuilder/SceneBuilderTests.cpp index 4d34725e36..46e14e6985 100644 --- a/Gems/SceneProcessing/Code/Tests/SceneBuilder/SceneBuilderTests.cpp +++ b/Gems/SceneProcessing/Code/Tests/SceneBuilder/SceneBuilderTests.cpp @@ -109,7 +109,7 @@ protected: TEST_F(SceneBuilderTests, SceneBuilderWorker_ExportProductDependencies_NoDependencies) { - SceneAPI::Events::ExportProduct exportProduct("testExportFile", AZ::Uuid::CreateRandom(), AZ::Data::AssetType::CreateNull(), 0, AZStd::nullopt); + SceneAPI::Events::ExportProduct exportProduct("testExportFile", AZ::Uuid::CreateRandom(), AZ::Data::AssetType::CreateNull(), u8(0), AZStd::nullopt); TestSuccessCaseNoDependencies(exportProduct); } @@ -122,7 +122,7 @@ TEST_F(SceneBuilderTests, SceneBuilderWorker_ExportProductDependencies_PathDepen #endif // AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS AssetBuilderSDK::ProductPathDependency expectedPathDependency(absolutePathToFile, AssetBuilderSDK::ProductPathDependencyType::SourceFile); - SceneAPI::Events::ExportProduct product("testExportFile", AZ::Uuid::CreateRandom(), AZ::Data::AssetType::CreateNull(), 0, AZStd::nullopt); + SceneAPI::Events::ExportProduct product("testExportFile", AZ::Uuid::CreateRandom(), AZ::Data::AssetType::CreateNull(), u8(0), AZStd::nullopt); product.m_legacyPathDependencies.push_back(absolutePathToFile); TestSuccessCase(product, &expectedPathDependency); @@ -134,7 +134,7 @@ TEST_F(SceneBuilderTests, SceneBuilderWorker_ExportProductDependencies_PathDepen AssetBuilderSDK::ProductPathDependency expectedPathDependency(relativeDependencyPathToFile, AssetBuilderSDK::ProductPathDependencyType::ProductFile); - SceneAPI::Events::ExportProduct product("testExportFile", AZ::Uuid::CreateRandom(), AZ::Data::AssetType::CreateNull(), 0, AZStd::nullopt); + SceneAPI::Events::ExportProduct product("testExportFile", AZ::Uuid::CreateRandom(), AZ::Data::AssetType::CreateNull(), u8(0), AZStd::nullopt); product.m_legacyPathDependencies.push_back(relativeDependencyPathToFile); TestSuccessCase(product, &expectedPathDependency); @@ -150,7 +150,7 @@ TEST_F(SceneBuilderTests, SceneBuilderWorker_ExportProductDependencies_PathDepen const char* absolutePathToFile = "/some/test/file.mtl"; #endif // AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS - SceneAPI::Events::ExportProduct exportProduct("testExportFile", AZ::Uuid::CreateRandom(), AZ::Data::AssetType::CreateNull(), 0, AZStd::nullopt); + SceneAPI::Events::ExportProduct exportProduct("testExportFile", AZ::Uuid::CreateRandom(), AZ::Data::AssetType::CreateNull(), u8(0), AZStd::nullopt); exportProduct.m_legacyPathDependencies.push_back(absolutePathToFile); exportProduct.m_legacyPathDependencies.push_back(relativeDependencyPathToFile); @@ -164,7 +164,7 @@ TEST_F(SceneBuilderTests, SceneBuilderWorker_ExportProductDependencies_PathDepen TEST_F(SceneBuilderTests, SceneBuilderWorker_ExportProductDependencies_ProductDependency) { AZ::Uuid dependencyId = AZ::Uuid::CreateRandom(); - SceneAPI::Events::ExportProduct exportProduct("testExportFile", AZ::Uuid::CreateRandom(), AZ::Data::AssetType::CreateNull(), 0, AZStd::nullopt); + SceneAPI::Events::ExportProduct exportProduct("testExportFile", AZ::Uuid::CreateRandom(), AZ::Data::AssetType::CreateNull(), u8(0), AZStd::nullopt); exportProduct.m_productDependencies.push_back(SceneAPI::Events::ExportProduct("testDependencyFile", dependencyId, AZ::Data::AssetType::CreateNull(), 0, AZStd::nullopt)); TestSuccessCase(exportProduct, nullptr, &dependencyId); @@ -173,7 +173,7 @@ TEST_F(SceneBuilderTests, SceneBuilderWorker_ExportProductDependencies_ProductDe TEST_F(SceneBuilderTests, SceneBuilderWorker_ExportProductDependencies_ProductAndPathDependencies) { AZ::Uuid dependencyId = AZ::Uuid::CreateRandom(); - SceneAPI::Events::ExportProduct exportProduct("testExportFile", AZ::Uuid::CreateRandom(), AZ::Data::AssetType::CreateNull(), 0, AZStd::nullopt); + SceneAPI::Events::ExportProduct exportProduct("testExportFile", AZ::Uuid::CreateRandom(), AZ::Data::AssetType::CreateNull(), u8(0), AZStd::nullopt); exportProduct.m_productDependencies.push_back(SceneAPI::Events::ExportProduct("testDependencyFile", dependencyId, AZ::Data::AssetType::CreateNull(), 0, AZStd::nullopt)); const char* relativeDependencyPathToFile = "some/test/file.mtl"; diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/ScriptCanvasContextMenus.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/ScriptCanvasContextMenus.cpp index b789c2e675..e4a95d7d19 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/ScriptCanvasContextMenus.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/ScriptCanvasContextMenus.cpp @@ -568,7 +568,7 @@ namespace ScriptCanvasEditor // Show the selection dialog bool createSlot = false; VariablePaletteRequests::SlotSetup selectedSlotSetup; - QPoint scenePoint(scenePos.GetX(), scenePos.GetY()); + QPoint scenePoint(static_cast(scenePos.GetX()), static_cast(scenePos.GetY())); VariablePaletteRequestBus::BroadcastResult(createSlot, &VariablePaletteRequests::ShowSlotTypeSelector, slot, scenePoint, selectedSlotSetup); bool changed = false; From e9b4f48f71c870c0374eca90aee2bef37ff41606 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 13 Aug 2021 12:29:24 -0700 Subject: [PATCH 432/803] more fixes, will merge fixes for w4245 and w4389 Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Editor/BaseLibraryItem.cpp | 4 ++-- .../ReflectedPropertyCtrl.cpp | 6 +++--- Code/Editor/EditorDefs.h | 12 ------------ Code/Editor/EditorViewportWidget.cpp | 4 ++-- Code/Editor/Objects/BaseObject.cpp | 4 ++-- .../UI/Outliner/OutlinerListModel.cpp | 2 +- Code/Editor/Plugins/EditorCommon/QtViewPane.cpp | 5 ----- Code/Editor/TrackView/TrackViewDopeSheetBase.cpp | 2 +- Code/Editor/Util/AffineParts.cpp | 2 -- Code/Editor/Util/GdiUtil.cpp | 12 ++++-------- Code/Editor/Util/ImageTIF.cpp | 4 ++-- Code/Editor/Util/Util.h | 3 --- .../AzFramework/Script/ScriptComponent.cpp | 4 ---- .../Source/GemCatalog/GemItemDelegate.cpp | 2 +- .../Include/Public/Framework/AWSApiClientJobConfig.h | 11 ----------- .../Include/Public/Framework/HttpRequestJobConfig.h | 11 ----------- .../Public/Framework/ServiceClientJobConfig.h | 10 ---------- .../Code/Include/Public/Framework/ServiceJobConfig.h | 11 ----------- .../Public/Framework/ServiceRequestJobConfig.h | 9 --------- .../Editor/Attribution/AWSCoreAttributionMetric.cpp | 2 -- .../Source/GameLiftServerSDKWrapper.cpp | 2 -- Gems/AWSMetrics/Code/Source/MetricsEventBuilder.cpp | 3 --- .../External/CubeMapGen/VectorMacros.h | 3 --- .../Window/AtomToolsMainWindowRequestBus.h | 3 --- .../Platform/Windows/GameCrashUploader_windows.cpp | 2 -- .../Editor/Animation/UiAnimViewDopeSheetBase.cpp | 2 +- Gems/LyShine/Code/Editor/EditorCommon.h | 2 -- .../Include/ScriptCanvas/Core/NodeFunctionGeneric.h | 5 ----- .../Include/ScriptCanvas/Libraries/Math/Math.cpp | 2 -- .../ScriptCanvasActions/CreateElementsActions.cpp | 4 ++-- .../Code/Tests/ScriptCanvas_NodeGenerics.cpp | 6 ------ 31 files changed, 21 insertions(+), 133 deletions(-) diff --git a/Code/Editor/BaseLibraryItem.cpp b/Code/Editor/BaseLibraryItem.cpp index 252510c951..b1fba91fad 100644 --- a/Code/Editor/BaseLibraryItem.cpp +++ b/Code/Editor/BaseLibraryItem.cpp @@ -43,7 +43,7 @@ public: //evaluate size XmlString xmlStr = m_undoCtx.node->getXML(); m_size = sizeof(CUndoBaseLibraryItem); - m_size += xmlStr.GetAllocatedMemory(); + m_size += static_cast(xmlStr.GetAllocatedMemory()); m_size += m_itemPath.length(); m_size += m_description.length(); } @@ -87,7 +87,7 @@ protected: libItem->Serialize(m_redoCtx); XmlString xmlStr = m_redoCtx.node->getXML(); - m_size += xmlStr.GetAllocatedMemory(); + m_size += static_cast(xmlStr.GetAllocatedMemory()); } //load previous saved data diff --git a/Code/Editor/Controls/ReflectedPropertyControl/ReflectedPropertyCtrl.cpp b/Code/Editor/Controls/ReflectedPropertyControl/ReflectedPropertyCtrl.cpp index 1a7060aa8d..cf80d56962 100644 --- a/Code/Editor/Controls/ReflectedPropertyControl/ReflectedPropertyCtrl.cpp +++ b/Code/Editor/Controls/ReflectedPropertyControl/ReflectedPropertyCtrl.cpp @@ -560,7 +560,7 @@ void ReflectedPropertyControl::RequestPropertyContextMenu(AzToolsFramework::Inst // Popup Menu with Event selection. QMenu menu; - UINT i = 0; + unsigned int i = 0; const int ePPA_CustomItemBase = 10; // reserved from 10 to 99 const int ePPA_CustomPopupBase = 100; // reserved from 100 to x*100+100 where x is size of m_customPopupMenuPopups @@ -595,12 +595,12 @@ void ReflectedPropertyControl::RequestPropertyContextMenu(AzToolsFramework::Inst action->setData(ePPA_CustomItemBase + i); } - for (UINT j = 0; j < m_customPopupMenuPopups.size(); ++j) + for (unsigned int j = 0; j < m_customPopupMenuPopups.size(); ++j) { SCustomPopupMenu* pMenuInfo = &m_customPopupMenuPopups[j]; QMenu* pSubMenu = menu.addMenu(pMenuInfo->m_text); - for (UINT k = 0; k < pMenuInfo->m_subMenuText.size(); ++k) + for (UINT k = 0; k < static_cast(pMenuInfo->m_subMenuText.size()); ++k) { const UINT uID = ePPA_CustomPopupBase + ePPA_CustomPopupBase * j + k; QAction *action = pSubMenu->addAction(pMenuInfo->m_subMenuText[k]); diff --git a/Code/Editor/EditorDefs.h b/Code/Editor/EditorDefs.h index 6614fa4d72..423f4c5f73 100644 --- a/Code/Editor/EditorDefs.h +++ b/Code/Editor/EditorDefs.h @@ -33,18 +33,6 @@ #include #include -// Warnings in STL -#pragma warning (disable : 4786) // identifier was truncated to 'number' characters in the debug information. -#pragma warning (disable : 4244) // conversion from 'long' to 'float', possible loss of data -#pragma warning (disable : 4018) // signed/unsigned mismatch - -// Disable warning when a function returns a value inside an __asm block -#pragma warning (disable : 4035) - -////////////////////////////////////////////////////////////////////////// -// 64-bits related warnings. -#pragma warning (disable : 4267) // conversion from 'size_t' to 'int', possible loss of data - ////////////////////////////////////////////////////////////////////////// // Simple type definitions. ////////////////////////////////////////////////////////////////////////// diff --git a/Code/Editor/EditorViewportWidget.cpp b/Code/Editor/EditorViewportWidget.cpp index 28e8cce33e..c7b1976432 100644 --- a/Code/Editor/EditorViewportWidget.cpp +++ b/Code/Editor/EditorViewportWidget.cpp @@ -1915,8 +1915,8 @@ Vec3 EditorViewportWidget::WorldToView3D(const Vec3& wp, [[maybe_unused]] int nF { out.x = (x / 100) * m_rcClient.width(); out.y = (y / 100) * m_rcClient.height(); - out.x /= QHighDpiScaling::factor(windowHandle()->screen()); - out.y /= QHighDpiScaling::factor(windowHandle()->screen()); + out.x /= static_cast(QHighDpiScaling::factor(windowHandle()->screen())); + out.y /= static_cast(QHighDpiScaling::factor(windowHandle()->screen())); out.z = z; } return out; diff --git a/Code/Editor/Objects/BaseObject.cpp b/Code/Editor/Objects/BaseObject.cpp index 482055d7ed..f40363ba98 100644 --- a/Code/Editor/Objects/BaseObject.cpp +++ b/Code/Editor/Objects/BaseObject.cpp @@ -1978,8 +1978,8 @@ bool CBaseObject::HitHelperAtTest(HitContext& hc, const Vec3& pos) { float fScreenScale = hc.view->GetScreenScaleFactor(pos); - iconSizeX *= OBJECT_TEXTURE_ICON_SCALE / fScreenScale; - iconSizeY *= OBJECT_TEXTURE_ICON_SCALE / fScreenScale; + iconSizeX = static_cast(static_cast(iconSizeX) * OBJECT_TEXTURE_ICON_SCALE / fScreenScale); + iconSizeY = static_cast(static_cast(iconSizeY) * OBJECT_TEXTURE_ICON_SCALE / fScreenScale); } // Hit Test icon of this object. diff --git a/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerListModel.cpp b/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerListModel.cpp index 02d2174fb8..c1938184db 100644 --- a/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerListModel.cpp +++ b/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerListModel.cpp @@ -2597,7 +2597,7 @@ void OutlinerItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& QString htmlStripped = layerInfoString; htmlStripped.remove(htmlMarkupRegex); const float layerInfoPadding = 1.2f; - textWidthAvailable -= fontMetrics.horizontalAdvance(htmlStripped) * layerInfoPadding; + textWidthAvailable -= static_cast(fontMetrics.horizontalAdvance(htmlStripped) * layerInfoPadding); } entityNameRichText = fontMetrics.elidedText(optionV4.text, Qt::TextElideMode::ElideRight, textWidthAvailable); diff --git a/Code/Editor/Plugins/EditorCommon/QtViewPane.cpp b/Code/Editor/Plugins/EditorCommon/QtViewPane.cpp index 7d97e6f580..3deef7e503 100644 --- a/Code/Editor/Plugins/EditorCommon/QtViewPane.cpp +++ b/Code/Editor/Plugins/EditorCommon/QtViewPane.cpp @@ -9,8 +9,6 @@ #include "platform.h" -#pragma warning(disable: 4266) // disabled warning from afk overrides - #define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS #include #include @@ -30,13 +28,10 @@ #include "QtUtil.h" // ugly dependencies: -#pragma warning(push) -#pragma warning(disable: 4244) // warning C4244: 'argument' : conversion from 'A' to 'B', possible loss of data #include "Functor.h" class CXmlArchive; #include #include "Util/PathUtil.h" -#pragma warning(pop) // ^^^ // --------------------------------------------------------------------------- diff --git a/Code/Editor/TrackView/TrackViewDopeSheetBase.cpp b/Code/Editor/TrackView/TrackViewDopeSheetBase.cpp index aa4ef94e9e..c784142b3c 100644 --- a/Code/Editor/TrackView/TrackViewDopeSheetBase.cpp +++ b/Code/Editor/TrackView/TrackViewDopeSheetBase.cpp @@ -258,7 +258,7 @@ void CTrackViewDopeSheetBase::SetTimeScale(float timeScale, float fAnchorTime) while (fPixelsPerTick >= 12.0 && steps < 100); float fCurrentOffset = -fAnchorTime * m_timeScale; - m_scrollOffset.rx() += fOldOffset - fCurrentOffset; + m_scrollOffset.rx() += static_cast(fOldOffset - fCurrentOffset); m_scrollBar->setValue(m_scrollOffset.x()); update(); diff --git a/Code/Editor/Util/AffineParts.cpp b/Code/Editor/Util/AffineParts.cpp index 7e6a1be35b..c80ceb3ffa 100644 --- a/Code/Editor/Util/AffineParts.cpp +++ b/Code/Editor/Util/AffineParts.cpp @@ -9,8 +9,6 @@ #include "EditorDefs.h" -#pragma warning ( disable : 4244 ) // conversion from 'double' to 'float', possible loss of data. - /**** Decompose.h - Basic declarations ****/ typedef struct { diff --git a/Code/Editor/Util/GdiUtil.cpp b/Code/Editor/Util/GdiUtil.cpp index eba5ac8579..8565aabf9d 100644 --- a/Code/Editor/Util/GdiUtil.cpp +++ b/Code/Editor/Util/GdiUtil.cpp @@ -61,15 +61,11 @@ QColor ScaleColor(const QColor& c, float aScale) aColor = QColor(1, 1, 1); } - int r = aColor.red(); - int g = aColor.green(); - int b = aColor.blue(); + const float r = static_cast(aColor.red()) * aScale; + const float g = static_cast(aColor.green()) * aScale; + const float b = static_cast(aColor.blue()) * aScale; - r *= aScale; - g *= aScale; - b *= aScale; - - return QColor(CLAMP(r, 0, 255), CLAMP(g, 0, 255), CLAMP(b, 0, 255)); + return QColor(CLAMP(static_cast(r), 0, 255), CLAMP(static_cast(g), 0, 255), CLAMP(static_cast(b), 0, 255)); } CAlphaBitmap::CAlphaBitmap() diff --git a/Code/Editor/Util/ImageTIF.cpp b/Code/Editor/Util/ImageTIF.cpp index 25e4296154..654b24f857 100644 --- a/Code/Editor/Util/ImageTIF.cpp +++ b/Code/Editor/Util/ImageTIF.cpp @@ -60,7 +60,7 @@ libtiffDummyReadProc (thandle_t fd, tdata_t buf, tsize_t size) memcpy(buf, &memImage->buffer[memImage->offset], size); - memImage->offset += size; + memImage->offset += static_cast(size); // Return the amount of data read return size; @@ -83,7 +83,7 @@ libtiffDummySeekProc (thandle_t fd, toff_t off, int i) break; case SEEK_CUR: - memImage->offset += off; + memImage->offset += static_cast(off); break; case SEEK_END: diff --git a/Code/Editor/Util/Util.h b/Code/Editor/Util/Util.h index b0ec0db818..61bb0eed09 100644 --- a/Code/Editor/Util/Util.h +++ b/Code/Editor/Util/Util.h @@ -137,8 +137,6 @@ namespace Util { x = x - 1; -#pragma warning(push) -#pragma warning(disable : 4293) if (sizeof(TInteger) > 0) { x |= x >> 1; @@ -163,7 +161,6 @@ namespace Util { x |= x >> 32; } -#pragma warning(pop) return x + 1; } diff --git a/Code/Framework/AzFramework/AzFramework/Script/ScriptComponent.cpp b/Code/Framework/AzFramework/AzFramework/Script/ScriptComponent.cpp index 6b25c49b88..fb8ca8b892 100644 --- a/Code/Framework/AzFramework/AzFramework/Script/ScriptComponent.cpp +++ b/Code/Framework/AzFramework/AzFramework/Script/ScriptComponent.cpp @@ -357,8 +357,6 @@ namespace AzFramework } } - #pragma warning( push ) - #pragma warning( disable : 4505 ) // StackDump is useful to debug the lua stack. Disable warning about this method being unused. //========================================================================= // DebugPrintStack // Prints the Lua stack starting from the bottom. @@ -375,8 +373,6 @@ namespace AzFramework AZ_Warning("ScriptComponent", false, "Stack Dump: '%s'", dump.c_str()); } - #pragma warning( pop ) - //========================================================================= // Properties__IndexFindSubtable diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.cpp index d5a213e80f..08e08afdd5 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.cpp @@ -208,7 +208,7 @@ namespace O3DE::ProjectManager const QPixmap& pixmap = iterator.value(); painter->drawPixmap(contentRect.left() + startX, contentRect.bottom() - s_platformIconSize, pixmap); qreal aspectRatio = static_cast(pixmap.width()) / pixmap.height(); - startX += s_platformIconSize * aspectRatio + s_platformIconSize / 2.5; + startX += static_cast(s_platformIconSize * aspectRatio + s_platformIconSize / 2.5); } } } diff --git a/Gems/AWSCore/Code/Include/Public/Framework/AWSApiClientJobConfig.h b/Gems/AWSCore/Code/Include/Public/Framework/AWSApiClientJobConfig.h index 2070bab4b6..800edffd41 100644 --- a/Gems/AWSCore/Code/Include/Public/Framework/AWSApiClientJobConfig.h +++ b/Gems/AWSCore/Code/Include/Public/Framework/AWSApiClientJobConfig.h @@ -45,15 +45,9 @@ namespace AWSCore virtual std::shared_ptr GetClient() = 0; }; -#ifdef _MSC_VER -#pragma warning( push ) -#pragma warning( disable: 4250 ) // warning C4250: 'AWSCore::AwsApiClientJobConfig': inherits 'AWSCore::AwsApiJobConfig::AWSCore::AwsApiJobConfig::GetJobContext' via dominance // Thanks to http://stackoverflow.com/questions/11965596/diamond-inheritance-scenario-compiles-fine-in-g-but-produces-warnings-errors for the explanation // This is the expected and desired behavior. The warning is superfluous. - -#endif - /// Configuration for AWS jobs using a specific client type. template class AwsApiClientJobConfig @@ -126,9 +120,4 @@ namespace AWSCore /// Set by ApplySettings std::shared_ptr m_client; }; - -#ifdef _MSC_VER -#pragma warning( pop ) // C4250 -#endif - } // namespace AWSCore diff --git a/Gems/AWSCore/Code/Include/Public/Framework/HttpRequestJobConfig.h b/Gems/AWSCore/Code/Include/Public/Framework/HttpRequestJobConfig.h index 9018c167f6..f5a089b5ca 100644 --- a/Gems/AWSCore/Code/Include/Public/Framework/HttpRequestJobConfig.h +++ b/Gems/AWSCore/Code/Include/Public/Framework/HttpRequestJobConfig.h @@ -27,15 +27,9 @@ namespace AWSCore }; -#ifdef _MSC_VER -#pragma warning( push ) -#pragma warning( disable: 4250 ) // warning C4250: 'AWSCore::HttpRequestJobConfig' : inherits 'AWSCore::AwsApiJobConfig::AWSCore::AwsApiJobConfig::GetJobContext' via dominance // Thanks to http://stackoverflow.com/questions/11965596/diamond-inheritance-scenario-compiles-fine-in-g-but-produces-warnings-errors for the explanation // This is the expected and desired behavior. The warning is superfluous. - -#endif - //! Provides service job configuration using settings properties. class HttpRequestJobConfig : public AwsApiJobConfig @@ -98,9 +92,4 @@ namespace AWSCore std::shared_ptr m_httpClient{ nullptr }; Aws::String m_userAgent{}; }; - -#ifdef _MSC_VER -#pragma warning( pop ) // C4250 -#endif - } // namespace AWSCore diff --git a/Gems/AWSCore/Code/Include/Public/Framework/ServiceClientJobConfig.h b/Gems/AWSCore/Code/Include/Public/Framework/ServiceClientJobConfig.h index 239fdfdbc0..c78fc41617 100644 --- a/Gems/AWSCore/Code/Include/Public/Framework/ServiceClientJobConfig.h +++ b/Gems/AWSCore/Code/Include/Public/Framework/ServiceClientJobConfig.h @@ -60,15 +60,10 @@ namespace AWSCore static const char* GetRESTApiStageKeyName() { return RESTAPI_STAGE; } \ }; -#ifdef _MSC_VER -#pragma warning( push ) -#pragma warning( disable: 4250 ) // warning C4250: 'AWSCore::ServiceClientJobConfig' : inherits 'AWSCore::AwsApiJobConfig::AWSCore::AwsApiJobConfig::GetJobContext' via dominance // Thanks to http://stackoverflow.com/questions/11965596/diamond-inheritance-scenario-compiles-fine-in-g-but-produces-warnings-errors for the explanation // This is the expected and desired behavior. The warning is superfluous. -#endif - /// Provides service job configuration using settings properties. template class ServiceClientJobConfig @@ -132,11 +127,6 @@ namespace AWSCore } }; - -#ifdef _MSC_VER -#pragma warning( pop ) // C4250 -#endif - } // namespace AWSCore diff --git a/Gems/AWSCore/Code/Include/Public/Framework/ServiceJobConfig.h b/Gems/AWSCore/Code/Include/Public/Framework/ServiceJobConfig.h index 0e2e2de96d..8632db7d9f 100644 --- a/Gems/AWSCore/Code/Include/Public/Framework/ServiceJobConfig.h +++ b/Gems/AWSCore/Code/Include/Public/Framework/ServiceJobConfig.h @@ -19,15 +19,9 @@ namespace AWSCore { }; -#ifdef _MSC_VER -#pragma warning( push ) -#pragma warning( disable: 4250 ) // warning C4250: 'AWSCore::ServiceJobConfig' : inherits 'AWSCore::AwsApiJobConfig::AWSCore::AwsApiJobConfig::GetJobContext' via dominance // Thanks to http://stackoverflow.com/questions/11965596/diamond-inheritance-scenario-compiles-fine-in-g-but-produces-warnings-errors for the explanation // This is the expected and desired behavior. The warning is superfluous. - -#endif - /// Provides service job configuration using settings properties. class ServiceJobConfig : public HttpRequestJobConfig @@ -63,9 +57,4 @@ namespace AWSCore private: }; - -#ifdef _MSC_VER -#pragma warning( pop ) // C4250 -#endif - } // namespace AWSCore diff --git a/Gems/AWSCore/Code/Include/Public/Framework/ServiceRequestJobConfig.h b/Gems/AWSCore/Code/Include/Public/Framework/ServiceRequestJobConfig.h index 8395384427..660b4f2537 100644 --- a/Gems/AWSCore/Code/Include/Public/Framework/ServiceRequestJobConfig.h +++ b/Gems/AWSCore/Code/Include/Public/Framework/ServiceRequestJobConfig.h @@ -25,15 +25,10 @@ namespace AWSCore virtual bool IsValid() const = 0; }; -#ifdef _MSC_VER -#pragma warning( push ) -#pragma warning( disable: 4250 ) // warning C4250: 'AWSCore::ServiceRequestJobConfig' : inherits 'AWSCore::AwsApiJobConfig::AWSCore::AwsApiJobConfig::GetJobContext' via dominance // Thanks to http://stackoverflow.com/questions/11965596/diamond-inheritance-scenario-compiles-fine-in-g-but-produces-warnings-errors for the explanation // This is the expected and desired behavior. The warning is superfluous. -#endif - template class ServiceRequestJobConfig : public ServiceClientJobConfig @@ -106,8 +101,4 @@ namespace AWSCore }; -#ifdef _MSC_VER -#pragma warning( pop ) // C4250 -#endif - } // namespace AWSCore diff --git a/Gems/AWSCore/Code/Source/Editor/Attribution/AWSCoreAttributionMetric.cpp b/Gems/AWSCore/Code/Source/Editor/Attribution/AWSCoreAttributionMetric.cpp index f54d7f71af..c4f51fcb6f 100644 --- a/Gems/AWSCore/Code/Source/Editor/Attribution/AWSCoreAttributionMetric.cpp +++ b/Gems/AWSCore/Code/Source/Editor/Attribution/AWSCoreAttributionMetric.cpp @@ -12,8 +12,6 @@ #include #include -#pragma warning(disable : 4996) - namespace AWSCore { constexpr char AWSAttributionMetricDefaultO3DEVersion[] = "1.1"; diff --git a/Gems/AWSGameLift/Code/AWSGameLiftServer/Source/GameLiftServerSDKWrapper.cpp b/Gems/AWSGameLift/Code/AWSGameLiftServer/Source/GameLiftServerSDKWrapper.cpp index ae9b868f42..ae4fe7b0f4 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftServer/Source/GameLiftServerSDKWrapper.cpp +++ b/Gems/AWSGameLift/Code/AWSGameLiftServer/Source/GameLiftServerSDKWrapper.cpp @@ -10,8 +10,6 @@ #include -#pragma warning(disable : 4996) - namespace AWSGameLift { Aws::GameLift::GenericOutcome GameLiftServerSDKWrapper::AcceptPlayerSession(const std::string& playerSessionId) diff --git a/Gems/AWSMetrics/Code/Source/MetricsEventBuilder.cpp b/Gems/AWSMetrics/Code/Source/MetricsEventBuilder.cpp index b7d9163fa9..043af2ef09 100644 --- a/Gems/AWSMetrics/Code/Source/MetricsEventBuilder.cpp +++ b/Gems/AWSMetrics/Code/Source/MetricsEventBuilder.cpp @@ -15,9 +15,6 @@ #include -#pragma warning(disable : 4996) - - namespace AWSMetrics { MetricsEventBuilder::MetricsEventBuilder() diff --git a/Gems/Atom/Asset/ImageProcessingAtom/External/CubeMapGen/VectorMacros.h b/Gems/Atom/Asset/ImageProcessingAtom/External/CubeMapGen/VectorMacros.h index c293cf1ac7..0db22d03d6 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/External/CubeMapGen/VectorMacros.h +++ b/Gems/Atom/Asset/ImageProcessingAtom/External/CubeMapGen/VectorMacros.h @@ -18,9 +18,6 @@ //-------------------------------------------------------------------------------------- // Modified from original -//disable warning about doubles being converted down to float -#pragma warning (disable : 4244 ) - #define VM_LARGE_FLOAT 3.7e37f #define VM_MIN(a, b) (((a) < (b)) ? (a) : (b)) diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindowRequestBus.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindowRequestBus.h index 6edb44bc5c..647082f553 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindowRequestBus.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindowRequestBus.h @@ -8,9 +8,6 @@ #pragma once -//! Disables "unreferenced formal parameter" warning -#pragma warning(disable : 4100) - #include #include #include diff --git a/Gems/CrashReporting/Code/Platform/Windows/GameCrashUploader_windows.cpp b/Gems/CrashReporting/Code/Platform/Windows/GameCrashUploader_windows.cpp index f65d98d7da..d8def1885e 100644 --- a/Gems/CrashReporting/Code/Platform/Windows/GameCrashUploader_windows.cpp +++ b/Gems/CrashReporting/Code/Platform/Windows/GameCrashUploader_windows.cpp @@ -15,8 +15,6 @@ #include #include -#pragma warning(disable : 4996) - namespace O3de { diff --git a/Gems/LyShine/Code/Editor/Animation/UiAnimViewDopeSheetBase.cpp b/Gems/LyShine/Code/Editor/Animation/UiAnimViewDopeSheetBase.cpp index a38736ff67..bd5c82fc9e 100644 --- a/Gems/LyShine/Code/Editor/Animation/UiAnimViewDopeSheetBase.cpp +++ b/Gems/LyShine/Code/Editor/Animation/UiAnimViewDopeSheetBase.cpp @@ -251,7 +251,7 @@ void CUiAnimViewDopeSheetBase::SetTimeScale(float timeScale, float fAnchorTime) while (fPixelsPerTick >= 12.0 && steps < 100); float fCurrentOffset = -fAnchorTime * m_timeScale; - m_scrollOffset.rx() += fOldOffset - fCurrentOffset; + m_scrollOffset.rx() += static_cast(fOldOffset - fCurrentOffset); update(); diff --git a/Gems/LyShine/Code/Editor/EditorCommon.h b/Gems/LyShine/Code/Editor/EditorCommon.h index ebe5b89cfc..9af5958c67 100644 --- a/Gems/LyShine/Code/Editor/EditorCommon.h +++ b/Gems/LyShine/Code/Editor/EditorCommon.h @@ -34,8 +34,6 @@ #include #include -#pragma warning(disable: 4355) // 'this' : used in base member initializer list - class CanvasSizeToolbarSection; class CommandCanvasPropertiesChange; class CommandCanvasSizeToolbarIndex; diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/NodeFunctionGeneric.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/NodeFunctionGeneric.h index 9cf5d04167..41a674536b 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/NodeFunctionGeneric.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/NodeFunctionGeneric.h @@ -21,9 +21,6 @@ #include "Node.h" #include "Attributes.h" -#pragma warning( push ) -#pragma warning( disable : 5046) // 'function' : Symbol involving type with internal linkage not defined - /** * NodeFunctionGeneric.h * @@ -372,5 +369,3 @@ namespace ScriptCanvas } } - -#pragma warning( pop ) diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Math/Math.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Math/Math.cpp index 67c79aaa05..62ca21f1b6 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Math/Math.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Math/Math.cpp @@ -10,8 +10,6 @@ #include -#pragma warning (disable:4503) // decorated name length exceeded, name was truncated - namespace ScriptCanvas { namespace Nodes diff --git a/Gems/ScriptCanvasDeveloper/Code/Editor/Source/EditorAutomation/EditorAutomationActions/ScriptCanvasActions/CreateElementsActions.cpp b/Gems/ScriptCanvasDeveloper/Code/Editor/Source/EditorAutomation/EditorAutomationActions/ScriptCanvasActions/CreateElementsActions.cpp index 71b157e0a9..0fa3765ac3 100644 --- a/Gems/ScriptCanvasDeveloper/Code/Editor/Source/EditorAutomation/EditorAutomationActions/ScriptCanvasActions/CreateElementsActions.cpp +++ b/Gems/ScriptCanvasDeveloper/Code/Editor/Source/EditorAutomation/EditorAutomationActions/ScriptCanvasActions/CreateElementsActions.cpp @@ -539,8 +539,8 @@ namespace ScriptCanvasDeveloper AZ::Vector2 stepDirection = AZ::Vector2::CreateZero(); - stepDirection.SetX(jutDirection.x() * stepSize.GetX()); - stepDirection.SetY(jutDirection.y() * stepSize.GetY()); + stepDirection.SetX(static_cast(jutDirection.x() * stepSize.GetX())); + stepDirection.SetY(static_cast(jutDirection.y() * stepSize.GetY())); m_scenePoint.setX(m_scenePoint.x() + stepDirection.GetX() * 2); } diff --git a/Gems/ScriptCanvasTesting/Code/Tests/ScriptCanvas_NodeGenerics.cpp b/Gems/ScriptCanvasTesting/Code/Tests/ScriptCanvas_NodeGenerics.cpp index f6e5b361f4..cbbe77fbba 100644 --- a/Gems/ScriptCanvasTesting/Code/Tests/ScriptCanvas_NodeGenerics.cpp +++ b/Gems/ScriptCanvasTesting/Code/Tests/ScriptCanvas_NodeGenerics.cpp @@ -13,9 +13,6 @@ #include -#pragma warning( push ) -#pragma warning( disable : 5046) //'function' : Symbol involving type with internal linkage not defined - using namespace ScriptCanvasTests; namespace @@ -163,6 +160,3 @@ TEST_F(ScriptCanvasTestFixture, NodeGenerics) delete graph->GetEntity(); } - - -#pragma warning( pop ) From 33cbc2db219cb77d088cb15c1774c86d9b1be9aa Mon Sep 17 00:00:00 2001 From: pappeste Date: Thu, 17 Jun 2021 16:46:04 -0700 Subject: [PATCH 433/803] =?UTF-8?q?=EF=BB=BFAtomLyIntegration?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../EMotionFXAtom/Code/Source/AtomActorInstance.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp index d5a48b900d..e85c2b92e7 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp @@ -161,7 +161,7 @@ namespace AZ const AZ::Color skeletonColor(0.604f, 0.804f, 0.196f, 1.0f); RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments lineArgs; lineArgs.m_verts = m_auxVertices.data(); - lineArgs.m_vertCount = aznumeric_caster(m_auxVertices.size()); + lineArgs.m_vertCount = static_cast(m_auxVertices.size()); lineArgs.m_colors = &skeletonColor; lineArgs.m_colorCount = 1; lineArgs.m_depthTest = RPI::AuxGeomDraw::DepthTest::Off; @@ -202,9 +202,9 @@ namespace AZ RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments lineArgs; lineArgs.m_verts = m_auxVertices.data(); - lineArgs.m_vertCount = aznumeric_caster(m_auxVertices.size()); + lineArgs.m_vertCount = static_cast(m_auxVertices.size()); lineArgs.m_colors = m_auxColors.data(); - lineArgs.m_colorCount = aznumeric_caster(m_auxColors.size()); + lineArgs.m_colorCount = static_cast(m_auxColors.size()); lineArgs.m_depthTest = RPI::AuxGeomDraw::DepthTest::Off; auxGeom->DrawLines(lineArgs); } @@ -861,7 +861,7 @@ namespace AZ // Set the weights for any active masks for (size_t i = 0; i < m_wrinkleMaskWeights.size(); ++i) { - wrinkleMaskObjectSrg->SetConstant(wrinkleMaskWeightsIndex, m_wrinkleMaskWeights[i], aznumeric_caster(i)); + wrinkleMaskObjectSrg->SetConstant(wrinkleMaskWeightsIndex, m_wrinkleMaskWeights[i], static_cast(i)); } AZ_Error("AtomActorInstance", m_wrinkleMaskWeights.size() <= s_maxActiveWrinkleMasks, "The skinning shader supports no more than %d active morph targets with wrinkle masks.", s_maxActiveWrinkleMasks); } From 4247f32eca9f9efa70941d971c22a32b82fd3f58 Mon Sep 17 00:00:00 2001 From: pappeste Date: Thu, 17 Jun 2021 16:52:06 -0700 Subject: [PATCH 434/803] =?UTF-8?q?=EF=BB=BFAWSMetrics?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Gems/AWSMetrics/Code/Source/MetricsManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/AWSMetrics/Code/Source/MetricsManager.cpp b/Gems/AWSMetrics/Code/Source/MetricsManager.cpp index 03e31770ee..c8c352f17d 100644 --- a/Gems/AWSMetrics/Code/Source/MetricsManager.cpp +++ b/Gems/AWSMetrics/Code/Source/MetricsManager.cpp @@ -256,7 +256,7 @@ namespace AWSMetrics } m_globalStats.m_numSuccesses++; - m_globalStats.m_sendSizeInBytes += static_cast(metricsEvent.GetSizeInBytes()); + m_globalStats.m_sendSizeInBytes += static_cast::value_type>(metricsEvent.GetSizeInBytes()); } else { From f76d09e2158bc6a310083f085cfc9dc99bf1be9e Mon Sep 17 00:00:00 2001 From: pereslav Date: Tue, 17 Aug 2021 00:19:57 +0100 Subject: [PATCH 435/803] Fixed assert about memory override when logged string is longer than the buffer size Signed-off-by: pereslav --- Code/Legacy/CrySystem/Log.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Code/Legacy/CrySystem/Log.cpp b/Code/Legacy/CrySystem/Log.cpp index d248274b1d..872a522a69 100644 --- a/Code/Legacy/CrySystem/Log.cpp +++ b/Code/Legacy/CrySystem/Log.cpp @@ -851,7 +851,8 @@ bool CLog::LogToMainThread(const char* szString, ELogType logType, bool bAdd, SL { // When logging from other thread then main, push all log strings to queue. SLogMsg msg; - azstrcpy(msg.msg, AZ_ARRAY_SIZE(msg.msg), szString); + constexpr size_t maxArraySize = AZ_ARRAY_SIZE(msg.msg); + azstrncpy(msg.msg, maxArraySize, szString, maxArraySize - 1); msg.bAdd = bAdd; msg.destination = destination; msg.logType = logType; From ff4d65dc2d29f57fa15f423b3c38f21c92711254 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Mon, 16 Aug 2021 18:22:37 -0500 Subject: [PATCH 436/803] added functions to remove and clear trace logger filters Signed-off-by: Guthrie Adams --- .../AzToolsFramework/Logger/TraceLogger.cpp | 20 +++++++++++++++++++ .../AzToolsFramework/Logger/TraceLogger.h | 16 +++++++++++++-- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Logger/TraceLogger.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Logger/TraceLogger.cpp index 547d328c45..e81aaed6c9 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Logger/TraceLogger.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Logger/TraceLogger.cpp @@ -91,8 +91,28 @@ namespace AzToolsFramework m_windowFilters.insert(filter); } + void TraceLogger::RemoveWindowFilter(const AZStd::string& filter) + { + m_windowFilters.erase(filter); + } + + void TraceLogger::ClearWindowFilter() + { + m_windowFilters.clear(); + } + void TraceLogger::AddMessageFilter(const AZStd::string& filter) { m_messageFilters.insert(filter); } + + void TraceLogger::RemoveMessageFilter(const AZStd::string& filter) + { + m_messageFilters.erase(filter); + } + + void TraceLogger::ClearMessageFilter() + { + m_messageFilters.clear(); + } } // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Logger/TraceLogger.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Logger/TraceLogger.h index ac1455452a..10708e3239 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Logger/TraceLogger.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Logger/TraceLogger.h @@ -25,12 +25,24 @@ namespace AzToolsFramework //! Open log file and dump log sink into it void PrepareLogFile(const AZStd::string& logFileName); - //! Ignore messages sent to windowd with names matching filter + //! Add filter to ignore messages for windows with matching names void AddWindowFilter(const AZStd::string& filter); - //! Ignore messages with text matching filter + //! Remove window filter + void RemoveWindowFilter(const AZStd::string& filter); + + //! Clear window filters + void ClearWindowFilter(); + + //! Add filter to ignore messages with matching names void AddMessageFilter(const AZStd::string& filter); + //! Remove message filter + void RemoveMessageFilter(const AZStd::string& filter); + + //! Clear message filters + void ClearMessageFilter(); + protected: ////////////////////////////////////////////////////////////////////////// // AZ::Debug::TraceMessageBus::Handler overrides... From aecb4a4eea393eb45671e9eee9429f4525ab711a Mon Sep 17 00:00:00 2001 From: pappeste Date: Fri, 18 Jun 2021 16:20:59 -0700 Subject: [PATCH 437/803] =?UTF-8?q?=EF=BB=BFVegetation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Gems/Vegetation/Code/Source/AreaSystemComponent.cpp | 6 +++--- Gems/Vegetation/Code/Source/InstanceSystemComponent.cpp | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Gems/Vegetation/Code/Source/AreaSystemComponent.cpp b/Gems/Vegetation/Code/Source/AreaSystemComponent.cpp index 7ce1a2c0a3..f5153a37b2 100644 --- a/Gems/Vegetation/Code/Source/AreaSystemComponent.cpp +++ b/Gems/Vegetation/Code/Source/AreaSystemComponent.cpp @@ -1010,7 +1010,7 @@ namespace Vegetation if (m_debugData) { - m_debugData->m_areaTaskQueueCount.store(static_cast(m_vegetationThreadTasks.size()), AZStd::memory_order_relaxed); + m_debugData->m_areaTaskQueueCount.store(static_cast(m_vegetationThreadTasks.size()), AZStd::memory_order_relaxed); } } @@ -1025,8 +1025,8 @@ namespace Vegetation if (m_debugData) { - m_debugData->m_areaTaskQueueCount.store(static_cast(m_vegetationThreadTasks.size()), AZStd::memory_order_relaxed); - m_debugData->m_areaTaskActiveCount.store(static_cast(tasks.size()), AZStd::memory_order_relaxed); + m_debugData->m_areaTaskQueueCount.store(static_cast(m_vegetationThreadTasks.size()), AZStd::memory_order_relaxed); + m_debugData->m_areaTaskActiveCount.store(static_cast(tasks.size()), AZStd::memory_order_relaxed); } } diff --git a/Gems/Vegetation/Code/Source/InstanceSystemComponent.cpp b/Gems/Vegetation/Code/Source/InstanceSystemComponent.cpp index 74fb2696ea..efdebcaff8 100644 --- a/Gems/Vegetation/Code/Source/InstanceSystemComponent.cpp +++ b/Gems/Vegetation/Code/Source/InstanceSystemComponent.cpp @@ -483,7 +483,7 @@ namespace Vegetation AZStd::lock_guard scopedLock(m_instanceMapMutex); AZ_Assert(m_instanceMap.find(instanceData.m_instanceId) == m_instanceMap.end(), "InstanceId %llu is already in use!", instanceData.m_instanceId); m_instanceMap[instanceData.m_instanceId] = AZStd::make_pair(instanceData.m_descriptorPtr, opaqueInstanceData); - m_instanceCount = static_cast(m_instanceMap.size()); + m_instanceCount = static_cast(m_instanceMap.size()); } } @@ -503,7 +503,7 @@ namespace Vegetation opaqueInstanceData = instanceItr->second.second; m_instanceMap.erase(instanceItr); } - m_instanceCount = static_cast(m_instanceMap.size()); + m_instanceCount = static_cast(m_instanceMap.size()); } if (opaqueInstanceData) From f6679cc05f11b3bd19e70c30f1fd912181c49470 Mon Sep 17 00:00:00 2001 From: pappeste Date: Fri, 18 Jun 2021 16:36:30 -0700 Subject: [PATCH 438/803] =?UTF-8?q?=EF=BB=BFSandbox?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Editor/ViewportTitleDlg.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Code/Editor/ViewportTitleDlg.cpp b/Code/Editor/ViewportTitleDlg.cpp index f5515b9c18..b54ce54ddd 100644 --- a/Code/Editor/ViewportTitleDlg.cpp +++ b/Code/Editor/ViewportTitleDlg.cpp @@ -462,7 +462,7 @@ void CViewportTitleDlg::AddFOVMenus(QMenu* menu, std::function call { fov = std::max(1.0f, f); fov = std::min(120.0f, f); - QAction* action = menu->addAction(customPreset); + QAction* action = menu->addAction(customPresets[i]); connect(action, &QAction::triggered, action, [fov, callback](){ callback(fov); }); } } @@ -536,7 +536,7 @@ void CViewportTitleDlg::AddAspectRatioMenus(QMenu* menu, std::functionaddAction(customPreset); + QAction* action = menu->addAction(customPresets[i]); connect(action, &QAction::triggered, action, [width, height, callback]() {callback(width, height); }); } } From f02957c140dccf2ebf9f9e51f3159739eb629f95 Mon Sep 17 00:00:00 2001 From: pappeste Date: Thu, 24 Jun 2021 18:10:14 -0700 Subject: [PATCH 439/803] merging from development + fixing linux Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Gems/AWSMetrics/Code/Source/MetricsManager.cpp | 2 +- Gems/Vegetation/Code/Source/AreaSystemComponent.cpp | 6 +++--- Gems/Vegetation/Code/Source/InstanceSystemComponent.cpp | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Gems/AWSMetrics/Code/Source/MetricsManager.cpp b/Gems/AWSMetrics/Code/Source/MetricsManager.cpp index c8c352f17d..03e31770ee 100644 --- a/Gems/AWSMetrics/Code/Source/MetricsManager.cpp +++ b/Gems/AWSMetrics/Code/Source/MetricsManager.cpp @@ -256,7 +256,7 @@ namespace AWSMetrics } m_globalStats.m_numSuccesses++; - m_globalStats.m_sendSizeInBytes += static_cast::value_type>(metricsEvent.GetSizeInBytes()); + m_globalStats.m_sendSizeInBytes += static_cast(metricsEvent.GetSizeInBytes()); } else { diff --git a/Gems/Vegetation/Code/Source/AreaSystemComponent.cpp b/Gems/Vegetation/Code/Source/AreaSystemComponent.cpp index f5153a37b2..7ce1a2c0a3 100644 --- a/Gems/Vegetation/Code/Source/AreaSystemComponent.cpp +++ b/Gems/Vegetation/Code/Source/AreaSystemComponent.cpp @@ -1010,7 +1010,7 @@ namespace Vegetation if (m_debugData) { - m_debugData->m_areaTaskQueueCount.store(static_cast(m_vegetationThreadTasks.size()), AZStd::memory_order_relaxed); + m_debugData->m_areaTaskQueueCount.store(static_cast(m_vegetationThreadTasks.size()), AZStd::memory_order_relaxed); } } @@ -1025,8 +1025,8 @@ namespace Vegetation if (m_debugData) { - m_debugData->m_areaTaskQueueCount.store(static_cast(m_vegetationThreadTasks.size()), AZStd::memory_order_relaxed); - m_debugData->m_areaTaskActiveCount.store(static_cast(tasks.size()), AZStd::memory_order_relaxed); + m_debugData->m_areaTaskQueueCount.store(static_cast(m_vegetationThreadTasks.size()), AZStd::memory_order_relaxed); + m_debugData->m_areaTaskActiveCount.store(static_cast(tasks.size()), AZStd::memory_order_relaxed); } } diff --git a/Gems/Vegetation/Code/Source/InstanceSystemComponent.cpp b/Gems/Vegetation/Code/Source/InstanceSystemComponent.cpp index efdebcaff8..74fb2696ea 100644 --- a/Gems/Vegetation/Code/Source/InstanceSystemComponent.cpp +++ b/Gems/Vegetation/Code/Source/InstanceSystemComponent.cpp @@ -483,7 +483,7 @@ namespace Vegetation AZStd::lock_guard scopedLock(m_instanceMapMutex); AZ_Assert(m_instanceMap.find(instanceData.m_instanceId) == m_instanceMap.end(), "InstanceId %llu is already in use!", instanceData.m_instanceId); m_instanceMap[instanceData.m_instanceId] = AZStd::make_pair(instanceData.m_descriptorPtr, opaqueInstanceData); - m_instanceCount = static_cast(m_instanceMap.size()); + m_instanceCount = static_cast(m_instanceMap.size()); } } @@ -503,7 +503,7 @@ namespace Vegetation opaqueInstanceData = instanceItr->second.second; m_instanceMap.erase(instanceItr); } - m_instanceCount = static_cast(m_instanceMap.size()); + m_instanceCount = static_cast(m_instanceMap.size()); } if (opaqueInstanceData) From ae4ad7dcac8c84736332d6c3261d03eafbb2e594 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Mon, 16 Aug 2021 18:29:16 -0500 Subject: [PATCH 440/803] fixed formatting Signed-off-by: Guthrie Adams --- .../Code/Source/Window/SettingsDialog/SettingsWidget.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/SettingsDialog/SettingsWidget.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/SettingsDialog/SettingsWidget.cpp index e8254edb28..c7d4b195a3 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/SettingsDialog/SettingsWidget.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/SettingsDialog/SettingsWidget.cpp @@ -52,7 +52,8 @@ namespace MaterialEditor const AZStd::string groupDisplayName = "Document System Settings"; const AZStd::string groupDescription = "Document System Settings"; - const AZ::Crc32 saveStateKey(AZStd::string::format("SettingsWidget::DocumentSystemSettingsGroup")); AddGroup( + const AZ::Crc32 saveStateKey(AZStd::string::format("SettingsWidget::DocumentSystemSettingsGroup")); + AddGroup( groupNameId, groupDisplayName, groupDescription, new AtomToolsFramework::InspectorPropertyGroupWidget( m_documentSystemSettings.get(), nullptr, m_documentSystemSettings->TYPEINFO_Uuid(), this, this, saveStateKey)); From 58f8b563d073d36ef5a02ff48901fd5473d9bf1d Mon Sep 17 00:00:00 2001 From: pappeste Date: Fri, 25 Jun 2021 18:33:22 -0700 Subject: [PATCH 441/803] =?UTF-8?q?=EF=BB=BFfix=20them=20all?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Editor/Geometry/TriMesh.cpp | 10 +++++----- Code/Editor/Objects/EntityObject.cpp | 2 +- Code/Editor/TrackView/TrackViewDialog.cpp | 2 +- Code/Editor/TrackView/TrackViewNodes.cpp | 2 +- .../Framework/AzCore/AzCore/IO/Streamer/BlockCache.cpp | 2 +- Code/Framework/AzCore/Tests/Math/SimdMathTests.cpp | 2 +- .../AzFramework/AzFramework/Archive/Archive.cpp | 6 +++--- .../AzFramework/Archive/ZipDirStructures.cpp | 2 +- .../SceneBuilder/Importers/AssImpUvMapImporter.cpp | 2 +- .../Code/Source/ImageLoader/DdsLoader.cpp | 4 ++-- .../PostProcessing/BlendColorGradingLutsPass.cpp | 2 +- .../Code/Source/Window/MaterialEditorWindow.cpp | 2 +- Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp | 2 +- .../Code/Source/Editor/QConnectionsWidget.cpp | 2 +- .../Code/Source/PythonMarshalComponent.cpp | 2 +- .../Code/Tests/GradientSignalImageTests.cpp | 2 +- Gems/LyShine/Code/Editor/SpriteBorderEditor.cpp | 2 +- Gems/LyShine/Code/Source/UiTextComponent.cpp | 2 +- Gems/LyShine/Code/Source/UiTextInputComponent.cpp | 2 +- .../ClothComponentMesh/ClothComponentMesh.cpp | 2 +- .../Code/Source/ScriptedEntityTweenerTask.h | 2 +- cmake/Platform/Common/MSVC/Configurations_msvc.cmake | 1 - 22 files changed, 28 insertions(+), 29 deletions(-) diff --git a/Code/Editor/Geometry/TriMesh.cpp b/Code/Editor/Geometry/TriMesh.cpp index 737886cabc..8e85de3904 100644 --- a/Code/Editor/Geometry/TriMesh.cpp +++ b/Code/Editor/Geometry/TriMesh.cpp @@ -677,11 +677,11 @@ void CTriMesh::GetEdgesByVertex(MeshElementsArray& inVertices, MeshElementsArray std::sort(inVertices.begin(), inVertices.end()); for (int i = 0; i < GetEdgeCount(); i++) { - if (stl::binary_find(inVertices.begin(), inVertices.end(), pEdges[i].v[0]) != inVertices.end()) + if (stl::binary_find(inVertices.begin(), inVertices.end(), static_cast(pEdges[i].v[0])) != inVertices.end()) { outEdges.push_back(i); } - else if (stl::binary_find(inVertices.begin(), inVertices.end(), pEdges[i].v[1]) != inVertices.end()) + else if (stl::binary_find(inVertices.begin(), inVertices.end(), static_cast(pEdges[i].v[1])) != inVertices.end()) { outEdges.push_back(i); } @@ -696,15 +696,15 @@ void CTriMesh::GetFacesByVertex(MeshElementsArray& inVertices, MeshElementsArray std::sort(inVertices.begin(), inVertices.end()); for (int i = 0; i < GetFacesCount(); i++) { - if (stl::binary_find(inVertices.begin(), inVertices.end(), pFaces[i].v[0]) != inVertices.end()) + if (stl::binary_find(inVertices.begin(), inVertices.end(), static_cast(pFaces[i].v[0])) != inVertices.end()) { outFaces.push_back(i); } - else if (stl::binary_find(inVertices.begin(), inVertices.end(), pFaces[i].v[1]) != inVertices.end()) + else if (stl::binary_find(inVertices.begin(), inVertices.end(), static_cast(pFaces[i].v[1])) != inVertices.end()) { outFaces.push_back(i); } - else if (stl::binary_find(inVertices.begin(), inVertices.end(), pFaces[i].v[2]) != inVertices.end()) + else if (stl::binary_find(inVertices.begin(), inVertices.end(), static_cast(pFaces[i].v[2])) != inVertices.end()) { outFaces.push_back(i); } diff --git a/Code/Editor/Objects/EntityObject.cpp b/Code/Editor/Objects/EntityObject.cpp index 0f4a17f3ba..77fab543f9 100644 --- a/Code/Editor/Objects/EntityObject.cpp +++ b/Code/Editor/Objects/EntityObject.cpp @@ -1283,7 +1283,7 @@ void CEntityObject::UpdateVisibility(bool bVisible) CBaseObject::UpdateVisibility(bVisible); bool bVisibleWithSpec = bVisible && !IsHiddenBySpec(); - if (bVisibleWithSpec != m_bVisible) + if (bVisibleWithSpec != static_cast(m_bVisible)) { m_bVisible = bVisibleWithSpec; } diff --git a/Code/Editor/TrackView/TrackViewDialog.cpp b/Code/Editor/TrackView/TrackViewDialog.cpp index 331daf6730..309d776b81 100644 --- a/Code/Editor/TrackView/TrackViewDialog.cpp +++ b/Code/Editor/TrackView/TrackViewDialog.cpp @@ -1559,7 +1559,7 @@ void CTrackViewDialog::OnAddSelectedNode() selectedEntitiesCount, &AzToolsFramework::ToolsApplicationRequests::GetSelectedEntitiesCount); // check to make sure all nodes were added and notify user if they weren't - if (addedNodes.GetCount() != selectedEntitiesCount) + if (addedNodes.GetCount() != static_cast(selectedEntitiesCount)) { IMovieSystem* movieSystem = GetIEditor()->GetMovieSystem(); diff --git a/Code/Editor/TrackView/TrackViewNodes.cpp b/Code/Editor/TrackView/TrackViewNodes.cpp index 16baa72709..550d36af83 100644 --- a/Code/Editor/TrackView/TrackViewNodes.cpp +++ b/Code/Editor/TrackView/TrackViewNodes.cpp @@ -1113,7 +1113,7 @@ void CTrackViewNodesCtrl::OnNMRclick(QPoint point) selectedEntitiesCount, &AzToolsFramework::ToolsApplicationRequests::GetSelectedEntitiesCount); // check to make sure all nodes were added and notify user if they weren't - if (addedNodes.GetCount() != selectedEntitiesCount) + if (addedNodes.GetCount() != static_cast(selectedEntitiesCount)) { IMovieSystem* movieSystem = GetIEditor()->GetMovieSystem(); diff --git a/Code/Framework/AzCore/AzCore/IO/Streamer/BlockCache.cpp b/Code/Framework/AzCore/AzCore/IO/Streamer/BlockCache.cpp index 3d8cbc7480..bbb54abb48 100644 --- a/Code/Framework/AzCore/AzCore/IO/Streamer/BlockCache.cpp +++ b/Code/Framework/AzCore/AzCore/IO/Streamer/BlockCache.cpp @@ -188,7 +188,7 @@ namespace AZ s32 numAvailableSlots = CalculateAvailableRequestSlots(); status.m_numAvailableSlots = AZStd::min(status.m_numAvailableSlots, numAvailableSlots); status.m_isIdle = status.m_isIdle && - numAvailableSlots == m_numBlocks && + static_cast(numAvailableSlots) == m_numBlocks && m_delayedSections.empty(); } diff --git a/Code/Framework/AzCore/Tests/Math/SimdMathTests.cpp b/Code/Framework/AzCore/Tests/Math/SimdMathTests.cpp index b05a95dbce..4570d79b83 100644 --- a/Code/Framework/AzCore/Tests/Math/SimdMathTests.cpp +++ b/Code/Framework/AzCore/Tests/Math/SimdMathTests.cpp @@ -94,7 +94,7 @@ namespace UnitTest float testStoreValues[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; VectorType::StoreUnaligned(testStoreValues, result); - for (int32_t i = 0; i < VectorType::ElementCount; ++i) + for (uint32_t i = 0; i < VectorType::ElementCount; ++i) { if (i == replaceIndex) { diff --git a/Code/Framework/AzFramework/AzFramework/Archive/Archive.cpp b/Code/Framework/AzFramework/AzFramework/Archive/Archive.cpp index a3d2103650..a0dda9f692 100644 --- a/Code/Framework/AzFramework/AzFramework/Archive/Archive.cpp +++ b/Code/Framework/AzFramework/AzFramework/Archive/Archive.cpp @@ -235,7 +235,7 @@ namespace AZ::IO::ArchiveInternal return 0; } - if (nReadBytes != nTotal) + if (static_cast(nReadBytes) != nTotal) { AZ_Warning("Archive", false, "FRead did not read expected number of byte from file, only %zu of %lld bytes read", nTotal, nReadBytes); nTotal = (size_t)nReadBytes; @@ -1791,11 +1791,11 @@ namespace AZ::IO AZ_Assert(m_pZip, "ZipFile is nullptr"); AZ_Assert(m_pFileEntry && m_pZip->IsOwnerOf(m_pFileEntry), "ZipFile is not owner of m_pFileEntry"); - if (nDataSize != m_pFileEntry->desc.lSizeUncompressed && bDecompress) + if (static_cast(nDataSize) != m_pFileEntry->desc.lSizeUncompressed && bDecompress) { return false; } - else if (nDataSize != m_pFileEntry->desc.lSizeCompressed && !bDecompress) + else if (static_cast(nDataSize) != m_pFileEntry->desc.lSizeCompressed && !bDecompress) { return false; } diff --git a/Code/Framework/AzFramework/AzFramework/Archive/ZipDirStructures.cpp b/Code/Framework/AzFramework/AzFramework/Archive/ZipDirStructures.cpp index b3b2328222..4111328224 100644 --- a/Code/Framework/AzFramework/AzFramework/Archive/ZipDirStructures.cpp +++ b/Code/Framework/AzFramework/AzFramework/Archive/ZipDirStructures.cpp @@ -104,7 +104,7 @@ namespace AZ::IO::ZipDir::ZipDirStructuresInternal if (*pReturnCode == Z_BUF_ERROR) { // As long as we consumed something, keep going. Only fail permanently if we've stalled. - if (nAvailIn != pZStream->avail_in || nAvailOut != pZStream->avail_out) + if (nAvailIn != static_cast(pZStream->avail_in) || nAvailOut != static_cast(pZStream->avail_out)) { *pReturnCode = Z_OK; } diff --git a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpUvMapImporter.cpp b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpUvMapImporter.cpp index fc0ac15244..9e0d788896 100644 --- a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpUvMapImporter.cpp +++ b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpUvMapImporter.cpp @@ -88,7 +88,7 @@ namespace AZ AZ_Error( Utilities::ErrorWindow, meshesPerTextureCoordinateIndex[texCoordIndex] == 0 || - meshesPerTextureCoordinateIndex[texCoordIndex] == currentNode->mNumMeshes, + meshesPerTextureCoordinateIndex[texCoordIndex] == static_cast(currentNode->mNumMeshes), "Texture coordinate index %d for node %s is not on all meshes on this node. " "Placeholder arbitrary texture values will be generated to allow the data to process, but the source art " "needs to be fixed to correct this. All meshes on this node should have the same number of texture coordinate channels.", diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/ImageLoader/DdsLoader.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/ImageLoader/DdsLoader.cpp index c1d2d7bf19..b9054a9911 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/ImageLoader/DdsLoader.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/ImageLoader/DdsLoader.cpp @@ -90,7 +90,7 @@ namespace ImageProcessingAtom for (i; i < ePixelFormat_Count; i++) { const PixelFormatInfo* info = CPixelFormats::GetInstance().GetPixelFormatInfo((EPixelFormat)i); - if (info->d3d10Format == dxgiFormat) + if (static_cast(info->d3d10Format) == dxgiFormat) { eFormat = (EPixelFormat)i; break; @@ -509,7 +509,7 @@ namespace ImageProcessingAtom for (i; i < ePixelFormat_Count; i++) { const PixelFormatInfo* info = CPixelFormats::GetInstance().GetPixelFormatInfo((EPixelFormat)i); - if (info->d3d10Format == dxgiFormat) + if (static_cast(info->d3d10Format) == dxgiFormat) { format = (EPixelFormat)i; break; diff --git a/Gems/Atom/Feature/Common/Code/Source/PostProcessing/BlendColorGradingLutsPass.cpp b/Gems/Atom/Feature/Common/Code/Source/PostProcessing/BlendColorGradingLutsPass.cpp index da680d80cf..fe5db0b441 100644 --- a/Gems/Atom/Feature/Common/Code/Source/PostProcessing/BlendColorGradingLutsPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/PostProcessing/BlendColorGradingLutsPass.cpp @@ -353,7 +353,7 @@ namespace AZ } // If the number of source LUTs have changed, the shader variant will need to be updated - if (m_numSourceLuts != current) + if (m_numSourceLuts != static_cast(current)) { m_numSourceLuts = current; m_needToUpdateShaderVariant = true; diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp index ffe5ec408a..1bd6067116 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp @@ -132,7 +132,7 @@ namespace MaterialEditor QSize newDeviceSize = m_materialViewport->size(); AZ_Warning( - "Material Editor", newDeviceSize.width() == width && newDeviceSize.height() == height, + "Material Editor", static_cast(newDeviceSize.width()) == width && static_cast(newDeviceSize.height()) == height, "Resizing the window did not give the expected frame size. Requested %d x %d but got %d x %d.", width, height, newDeviceSize.width(), newDeviceSize.height()); } diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp b/Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp index a29815f08c..b10edfae2e 100644 --- a/Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp +++ b/Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp @@ -1480,7 +1480,7 @@ bool AZ::FFont::UpdateTexture() return false; } - if (m_fontTexture->GetWidth() != m_fontImage->GetDescriptor().m_size.m_width || m_fontTexture->GetHeight() != m_fontImage->GetDescriptor().m_size.m_height) + if (m_fontTexture->GetWidth() != static_cast(m_fontImage->GetDescriptor().m_size.m_width) || m_fontTexture->GetHeight() != static_cast(m_fontImage->GetDescriptor().m_size.m_height)) { AZ_Assert(false, "AtomFont::FFont:::UpdateTexture size mismatch between texture and image!"); return false; diff --git a/Gems/AudioSystem/Code/Source/Editor/QConnectionsWidget.cpp b/Gems/AudioSystem/Code/Source/Editor/QConnectionsWidget.cpp index b65e690f1b..cdd7d937e3 100644 --- a/Gems/AudioSystem/Code/Source/Editor/QConnectionsWidget.cpp +++ b/Gems/AudioSystem/Code/Source/Editor/QConnectionsWidget.cpp @@ -138,7 +138,7 @@ namespace AudioControls for (int i = 0; i < size; ++i) { QListWidgetItem* listItem = m_connectionList->item(i); - if (listItem && listItem->data(eMDR_ID).toInt() == middlewareControl->GetId()) + if (listItem && listItem->data(eMDR_ID).toInt() == static_cast(middlewareControl->GetId())) { m_connectionList->clearSelection(); listItem->setSelected(true); diff --git a/Gems/EditorPythonBindings/Code/Source/PythonMarshalComponent.cpp b/Gems/EditorPythonBindings/Code/Source/PythonMarshalComponent.cpp index d1b59e7ecc..af21420b62 100644 --- a/Gems/EditorPythonBindings/Code/Source/PythonMarshalComponent.cpp +++ b/Gems/EditorPythonBindings/Code/Source/PythonMarshalComponent.cpp @@ -795,7 +795,7 @@ namespace EditorPythonBindings } } - AZ_Warning("python", PyDict_Size(pyObj.ptr()) == mapDataContainer->Size(mapInstance.m_address), "Python Dict size:%d does not match the size of the unordered_map:%d", pos, mapDataContainer->Size(mapInstance.m_address)); + AZ_Warning("python", static_cast(PyDict_Size(pyObj.ptr())) == mapDataContainer->Size(mapInstance.m_address), "Python Dict size:%d does not match the size of the unordered_map:%d", pos, mapDataContainer->Size(mapInstance.m_address)); outValue.m_value = mapInstance.m_address; outValue.m_typeId = mapInstance.m_typeId; outValue.m_traits = traits; diff --git a/Gems/GradientSignal/Code/Tests/GradientSignalImageTests.cpp b/Gems/GradientSignal/Code/Tests/GradientSignalImageTests.cpp index ea9a1d380f..4c22afac76 100644 --- a/Gems/GradientSignal/Code/Tests/GradientSignalImageTests.cpp +++ b/Gems/GradientSignal/Code/Tests/GradientSignalImageTests.cpp @@ -145,7 +145,7 @@ namespace UnitTest { for (AZ::u32 x = 0; x < width; ++x) { - if ((x == pixelX) && (y == pixelY)) + if ((x == static_cast(pixelX)) && (y == static_cast(pixelY))) { m_imageData->m_imageData.push_back(pixelValue); } diff --git a/Gems/LyShine/Code/Editor/SpriteBorderEditor.cpp b/Gems/LyShine/Code/Editor/SpriteBorderEditor.cpp index f53da64110..04f655123c 100644 --- a/Gems/LyShine/Code/Editor/SpriteBorderEditor.cpp +++ b/Gems/LyShine/Code/Editor/SpriteBorderEditor.cpp @@ -310,7 +310,7 @@ void SpriteBorderEditor::AddConfigureSection(QGridLayout* gridLayout, int& rowNu int newNumCols = numColsLineEdit->text().toInt(&colConversionSuccess); const bool positiveInputs = newNumRows > 0 && newNumCols > 0; - const bool valueChanged = m_numRows != newNumRows || m_numCols != newNumCols; + const bool valueChanged = m_numRows != static_cast(newNumRows) || m_numCols != static_cast(newNumCols); // This number of cells is just nearly unusable in the sprite editor UI. Supporting // more would likely require reworking of UX/UI and even implementation. diff --git a/Gems/LyShine/Code/Source/UiTextComponent.cpp b/Gems/LyShine/Code/Source/UiTextComponent.cpp index a996a489cc..ef9c3d4bb7 100644 --- a/Gems/LyShine/Code/Source/UiTextComponent.cpp +++ b/Gems/LyShine/Code/Source/UiTextComponent.cpp @@ -2068,7 +2068,7 @@ int UiTextComponent::GetFontEffect() //////////////////////////////////////////////////////////////////////////////////////////////////// void UiTextComponent::SetFontEffect(int effectIndex) { - if (m_fontEffectIndex != effectIndex) + if (m_fontEffectIndex != static_cast(effectIndex)) { m_fontEffectIndex = effectIndex; diff --git a/Gems/LyShine/Code/Source/UiTextInputComponent.cpp b/Gems/LyShine/Code/Source/UiTextInputComponent.cpp index 0d9fc09063..df2d85eb74 100644 --- a/Gems/LyShine/Code/Source/UiTextInputComponent.cpp +++ b/Gems/LyShine/Code/Source/UiTextInputComponent.cpp @@ -63,7 +63,7 @@ namespace //! \brief Given a UTF8 string and index, return the raw string buffer index that maps to the UTF8 index. int GetCharArrayIndexFromUtf8CharIndex(const AZStd::string& utf8String, const uint utf8Index) { - int utfIndexIter = 0; + uint utfIndexIter = 0; int rawIndex = 0; const AZStd::string::size_type stringLength = utf8String.length(); diff --git a/Gems/NvCloth/Code/Source/Components/ClothComponentMesh/ClothComponentMesh.cpp b/Gems/NvCloth/Code/Source/Components/ClothComponentMesh/ClothComponentMesh.cpp index 5a7564d72a..3d291e2e85 100644 --- a/Gems/NvCloth/Code/Source/Components/ClothComponentMesh/ClothComponentMesh.cpp +++ b/Gems/NvCloth/Code/Source/Components/ClothComponentMesh/ClothComponentMesh.cpp @@ -525,7 +525,7 @@ namespace NvCloth const int numVertices = subMeshInfo.m_numVertices; const int firstVertex = subMeshInfo.m_verticesFirstIndex; - if (subMesh.GetVertexCount() != numVertices) + if (subMesh.GetVertexCount() != static_cast(numVertices)) { AZ_Error("ClothComponentMesh", false, "Render mesh to be modified doesn't have the same number of vertices (%d) as the cloth's submesh (%d).", diff --git a/Gems/ScriptedEntityTweener/Code/Source/ScriptedEntityTweenerTask.h b/Gems/ScriptedEntityTweener/Code/Source/ScriptedEntityTweenerTask.h index 91528c08c0..a0d453c593 100644 --- a/Gems/ScriptedEntityTweener/Code/Source/ScriptedEntityTweenerTask.h +++ b/Gems/ScriptedEntityTweener/Code/Source/ScriptedEntityTweenerTask.h @@ -150,7 +150,7 @@ namespace ScriptedEntityTweener bool IsTimelineIdValid(int timelineId) { - return timelineId != AnimationProperties::InvalidTimelineId; + return timelineId != static_cast(AnimationProperties::InvalidTimelineId); } bool InitializeSubtask(ScriptedEntityTweenerSubtask& subtask, const AZStd::pair initData, AnimationParameters params); diff --git a/cmake/Platform/Common/MSVC/Configurations_msvc.cmake b/cmake/Platform/Common/MSVC/Configurations_msvc.cmake index 161783caa1..12bd2fb8f2 100644 --- a/cmake/Platform/Common/MSVC/Configurations_msvc.cmake +++ b/cmake/Platform/Common/MSVC/Configurations_msvc.cmake @@ -39,7 +39,6 @@ ly_append_configurations_options( # Disabling these warnings while they get fixed /wd4245 # conversion, signed/unsigned mismatch - /wd4389 # comparison, signed/unsigned mismatch # Enabling warnings that are disabled by default from /W4 # https://docs.microsoft.com/en-us/cpp/preprocessor/compiler-warnings-that-are-off-by-default?view=vs-2019 From f99a21e733f0e00edc470cc76d878ee3eb232f67 Mon Sep 17 00:00:00 2001 From: pappeste Date: Fri, 25 Jun 2021 18:40:01 -0700 Subject: [PATCH 442/803] last one! Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- cmake/Platform/Common/MSVC/Configurations_msvc.cmake | 3 --- 1 file changed, 3 deletions(-) diff --git a/cmake/Platform/Common/MSVC/Configurations_msvc.cmake b/cmake/Platform/Common/MSVC/Configurations_msvc.cmake index 12bd2fb8f2..4e2ec5a852 100644 --- a/cmake/Platform/Common/MSVC/Configurations_msvc.cmake +++ b/cmake/Platform/Common/MSVC/Configurations_msvc.cmake @@ -37,9 +37,6 @@ ly_append_configurations_options( # Disabling some warnings /wd4201 # nonstandard extension used: nameless struct/union. This actually became part of the C++11 std, MS has an open issue: https://developercommunity.visualstudio.com/t/warning-level-4-generates-a-bogus-warning-c4201-no/103064 - # Disabling these warnings while they get fixed - /wd4245 # conversion, signed/unsigned mismatch - # Enabling warnings that are disabled by default from /W4 # https://docs.microsoft.com/en-us/cpp/preprocessor/compiler-warnings-that-are-off-by-default?view=vs-2019 # /we4296 # 'operator': expression is always false From 75dc3e5836eecd8f183e396a07c6a8020eb0cbe5 Mon Sep 17 00:00:00 2001 From: pappeste Date: Mon, 28 Jun 2021 14:09:39 -0700 Subject: [PATCH 443/803] =?UTF-8?q?=EF=BB=BFCryEngine?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Legacy/CryCommon/CryHeaders.h | 2 +- Code/Legacy/CryCommon/ISerialize.h | 2 +- Code/Legacy/CrySystem/ViewSystem/ViewSystem.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Code/Legacy/CryCommon/CryHeaders.h b/Code/Legacy/CryCommon/CryHeaders.h index 4d037b52d9..49ea28ee0e 100644 --- a/Code/Legacy/CryCommon/CryHeaders.h +++ b/Code/Legacy/CryCommon/CryHeaders.h @@ -395,7 +395,7 @@ struct MotionParams905 MotionParams905() { m_nAssetFlags = 0; - m_nCompression = -1; + m_nCompression = std::numeric_limits::max(); m_nTicksPerFrame = 0; m_fSecsPerTick = 0; m_nStart = 0; diff --git a/Code/Legacy/CryCommon/ISerialize.h b/Code/Legacy/CryCommon/ISerialize.h index d427e222bb..b153a52487 100644 --- a/Code/Legacy/CryCommon/ISerialize.h +++ b/Code/Legacy/CryCommon/ISerialize.h @@ -31,7 +31,7 @@ class InterpolatedValue_tpl; // Unfortunately this needs to be here - should be in CryNetwork somewhere. struct SNetObjectID { - static const uint16 InvalidId = ~uint16(0); + static const uint16 InvalidId = std::numeric_limits::max(); SNetObjectID() : id(InvalidId) diff --git a/Code/Legacy/CrySystem/ViewSystem/ViewSystem.cpp b/Code/Legacy/CrySystem/ViewSystem/ViewSystem.cpp index c5df4f6570..e478ba4d36 100644 --- a/Code/Legacy/CrySystem/ViewSystem/ViewSystem.cpp +++ b/Code/Legacy/CrySystem/ViewSystem/ViewSystem.cpp @@ -339,7 +339,7 @@ void CViewSystem::SetActiveView(IView* pView) } else { - m_activeViewId = ~0; + m_activeViewId = ~0u; } m_bActiveViewFromSequence = false; From 3172a82937e8414c428bccbd7d9b52eff78d23a2 Mon Sep 17 00:00:00 2001 From: pappeste Date: Mon, 28 Jun 2021 14:10:01 -0700 Subject: [PATCH 444/803] Code/Framework Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../AzFramework/AzFramework/Archive/ZipDirStructures.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Code/Framework/AzFramework/AzFramework/Archive/ZipDirStructures.cpp b/Code/Framework/AzFramework/AzFramework/Archive/ZipDirStructures.cpp index 4111328224..1748d1578b 100644 --- a/Code/Framework/AzFramework/AzFramework/Archive/ZipDirStructures.cpp +++ b/Code/Framework/AzFramework/AzFramework/Archive/ZipDirStructures.cpp @@ -338,14 +338,13 @@ namespace AZ::IO::ZipDir else { AZ::IO::HandleType realFileHandle = m_fileHandle; - size_t nFileSize = ~0; AZ::u64 fileSize = 0; if (!m_fileIOBase->Size(realFileHandle, fileSize)) { goto error; } - nFileSize = static_cast(fileSize); + const size_t nFileSize = static_cast(fileSize); m_pInMemoryData = ZipDirStructuresInternal::CreateMemoryBlock(nFileSize, szUsage); From dcab2751ded72dbdb066e51eabc8fb7d931a704b Mon Sep 17 00:00:00 2001 From: pappeste Date: Mon, 28 Jun 2021 14:40:29 -0700 Subject: [PATCH 445/803] =?UTF-8?q?=EF=BB=BFAtom?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../Code/Source/Processing/PixelFormatInfo.h | 2 +- .../Asset/Shader/Code/Source/Editor/CommonFiles/CommonTypes.h | 2 +- .../Feature/CoreLights/DiskLightFeatureProcessorInterface.h | 2 +- .../Code/Include/Atom/Feature/Material/MaterialAssignmentId.h | 2 +- .../TransformService/TransformServiceFeatureProcessor.h | 2 +- .../Code/Include/Atom/Feature/Utils/MultiSparseVector.h | 4 ++-- .../Common/Code/Include/Atom/Feature/Utils/SparseVector.h | 4 ++-- .../Common/Code/Source/CoreLights/LightCullingPass.cpp | 4 ++-- .../Feature/Common/Code/Source/CoreLights/LightCullingPass.h | 2 +- .../Common/Code/Source/CoreLights/LightCullingRemap.cpp | 2 +- .../Common/Code/Source/CoreLights/ProjectedShadowmapsPass.h | 2 +- .../Feature/Common/Code/Source/CoreLights/ShadowmapAtlas.h | 4 ++-- .../RHI/Code/Include/Atom/RHI.Edit/ShaderPlatformInterface.h | 2 +- .../RHI/Code/Include/Atom/RHI/AliasedAttachmentAllocator.h | 2 +- Gems/Atom/RHI/DX12/Code/Source/RHI/Conversions.cpp | 4 ++-- Gems/Atom/RHI/Vulkan/Code/Source/RHI/CommandQueueContext.cpp | 2 +- Gems/Atom/RHI/Vulkan/Code/Source/RHI/Device.cpp | 2 +- Gems/Atom/RHI/Vulkan/Code/Source/RHI/Device.h | 2 +- .../RHI/Vulkan/Code/Source/RHI/MergedShaderResourceGroup.h | 2 +- .../Atom/RPI.Reflect/Material/MaterialPropertyDescriptor.h | 2 +- .../Include/Atom/RPI.Reflect/Shader/ShaderVariantTreeAsset.h | 2 +- Gems/Atom/Utils/Code/Include/Atom/Utils/StableDynamicArray.h | 2 +- 22 files changed, 27 insertions(+), 27 deletions(-) diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/PixelFormatInfo.h b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/PixelFormatInfo.h index 50d7ea137f..ec1ec1bfaf 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/PixelFormatInfo.h +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/PixelFormatInfo.h @@ -82,7 +82,7 @@ namespace ImageProcessingAtom } else // The value is zero { - Exponent = -112; + Exponent = static_cast(-112); } Result = ((h & 0x8000) << 16) | // Sign diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/CommonFiles/CommonTypes.h b/Gems/Atom/Asset/Shader/Code/Source/Editor/CommonFiles/CommonTypes.h index d5e5c7132c..fd34251277 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/CommonFiles/CommonTypes.h +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/CommonFiles/CommonTypes.h @@ -278,7 +278,7 @@ namespace AZ { AZ::Name m_nameId; uint32_t m_sizeInBytes = 0; - uint32_t m_space = -1; + uint32_t m_space = std::numeric_limits::max(); uint32_t m_registerId = RHI::UndefinedRegisterSlot; }; } // ShaderBuilder diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/DiskLightFeatureProcessorInterface.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/DiskLightFeatureProcessorInterface.h index e4986eee93..bcb470d831 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/DiskLightFeatureProcessorInterface.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/DiskLightFeatureProcessorInterface.h @@ -38,7 +38,7 @@ namespace AZ float m_cosInnerConeAngle = 0.0f; // cosine of inner cone angle float m_cosOuterConeAngle = 0.0f; // cosine of outer cone angle float m_bulbPositionOffset = 0.0f; // Distance from the light disk surface to the tip of the cone of the light. m_bulbRadius * tanf(pi/2 - m_outerConeAngle). - uint16_t m_shadowIndex = -1; // index for ProjectedShadowData. A value of 0xFFFF indicates an illegal index. + uint16_t m_shadowIndex = std::numeric_limits::max(); // index for ProjectedShadowData. A value of 0xFFFF indicates an illegal index. uint16_t m_padding; // Explicit padding. }; diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Material/MaterialAssignmentId.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Material/MaterialAssignmentId.h index e58a8397db..599f4c380e 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Material/MaterialAssignmentId.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Material/MaterialAssignmentId.h @@ -64,7 +64,7 @@ namespace AZ bool operator==(const MaterialAssignmentId& rhs) const; bool operator!=(const MaterialAssignmentId& rhs) const; - static constexpr MaterialAssignmentLodIndex NonLodIndex = -1; + static constexpr MaterialAssignmentLodIndex NonLodIndex = std::numeric_limits::max(); MaterialAssignmentLodIndex m_lodIndex = NonLodIndex; RPI::ModelMaterialSlot::StableId m_materialSlotStableId = RPI::ModelMaterialSlot::InvalidStableId; diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/TransformService/TransformServiceFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/TransformService/TransformServiceFeatureProcessor.h index 1f31701d91..6482871234 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/TransformService/TransformServiceFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/TransformService/TransformServiceFeatureProcessor.h @@ -61,7 +61,7 @@ namespace AZ }; // Flag value for when the buffers have no empty spaces. - static const uint32_t NoAvailableTransformIndices = -1; + static const uint32_t NoAvailableTransformIndices = std::numeric_limits::max(); TransformServiceFeatureProcessor(const TransformServiceFeatureProcessor&) = delete; diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/MultiSparseVector.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/MultiSparseVector.h index 2d93b4a7fd..216e90c594 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/MultiSparseVector.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/MultiSparseVector.h @@ -49,7 +49,7 @@ namespace AZ::Render private: - static constexpr size_t NoFreeSlot = -1; + static constexpr size_t NoFreeSlot = std::numeric_limits::max(); static constexpr size_t InitialReservedCount = 128; using Fn = void(&)(AZStd::vector& ...); @@ -103,7 +103,7 @@ namespace AZ::Render template inline size_t MultiSparseVector::Reserve() { - size_t slotToReturn = -1; + size_t slotToReturn = std::numeric_limits::max(); if (m_nextFreeSlot != NoFreeSlot) { // If there's a free slot, then use that space and update the linked list of free slots. diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/SparseVector.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/SparseVector.h index 525288adb0..8f388e23b9 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/SparseVector.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/SparseVector.h @@ -49,7 +49,7 @@ namespace AZ::Render private: - static constexpr size_t NoFreeSlot = -1; + static constexpr size_t NoFreeSlot = std::numeric_limits::max(); static constexpr size_t InitialReservedCount = 128; size_t m_nextFreeSlot = NoFreeSlot; @@ -66,7 +66,7 @@ namespace AZ::Render template inline size_t SparseVector::Reserve() { - size_t slotToReturn = -1; + size_t slotToReturn = std::numeric_limits::max(); if (m_nextFreeSlot != NoFreeSlot) { // If there's a free slot, then use that space and update the linked list of free slots. diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/LightCullingPass.cpp b/Gems/Atom/Feature/Common/Code/Source/CoreLights/LightCullingPass.cpp index a88c587f66..03a423f6db 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/LightCullingPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/LightCullingPass.cpp @@ -159,7 +159,7 @@ namespace AZ void LightCullingPass::ResetInternal() { - m_tileDataIndex = -1; + m_tileDataIndex = std::numeric_limits::max(); m_constantDataIndex.Reset(); for (auto& elem : m_lightdata) @@ -234,7 +234,7 @@ namespace AZ return i; } } - return -1; + return std::numeric_limits::max(); } AZ::RHI::Size LightCullingPass::GetTileDataBufferResolution() diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/LightCullingPass.h b/Gems/Atom/Feature/Common/Code/Source/CoreLights/LightCullingPass.h index af230b8d57..9fa81bd7de 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/LightCullingPass.h +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/LightCullingPass.h @@ -94,7 +94,7 @@ namespace AZ Data::Instance m_lightList; - uint32_t m_tileDataIndex = -1; + uint32_t m_tileDataIndex = std::numeric_limits::max(); }; } // namespace Render } // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/LightCullingRemap.cpp b/Gems/Atom/Feature/Common/Code/Source/CoreLights/LightCullingRemap.cpp index e4881ed665..1a03b7ef38 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/LightCullingRemap.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/LightCullingRemap.cpp @@ -101,7 +101,7 @@ namespace AZ return i; } } - return -1; + return std::numeric_limits::max(); } void LightCullingRemap::BuildInternal() diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/ProjectedShadowmapsPass.h b/Gems/Atom/Feature/Common/Code/Source/CoreLights/ProjectedShadowmapsPass.h index f1607191fc..dc7df7de78 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/ProjectedShadowmapsPass.h +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/ProjectedShadowmapsPass.h @@ -30,7 +30,7 @@ namespace AZ AZ_CLASS_ALLOCATOR(ProjectedShadowmapsPass, SystemAllocator, 0); AZ_RTTI(ProjectedShadowmapsPass, "00024B13-1095-40FA-BEC3-B0F68110BEA2", Base); - static constexpr uint16_t InvalidIndex = ~0; + static constexpr uint16_t InvalidIndex = std::numeric_limits::max(); struct ShadowmapSizeWithIndices { ShadowmapSize m_size = ShadowmapSize::None; diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/ShadowmapAtlas.h b/Gems/Atom/Feature/Common/Code/Source/CoreLights/ShadowmapAtlas.h index 5081a9ef9e..f0a372ec5b 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/ShadowmapAtlas.h +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/ShadowmapAtlas.h @@ -52,7 +52,7 @@ namespace AZ // then m_nextTableOffset == 0, which works as the terminator for seaching // a shadowmap index in a compute shader. uint32_t m_nextTableOffset = 0; - uint32_t m_shadowmapIndex = ~0; // invalid index + uint32_t m_shadowmapIndex = std::numeric_limits::max(); // invalid index }; //! This initializes the packing of shadowmap sizes. @@ -156,7 +156,7 @@ namespace AZ //! [2,2,2] indicates (0, 1024+512)-(0+511, 1024+512+511) of slice:2 (width 512). using Location = AZStd::vector; static constexpr uint8_t LocationIndexNum = 4; - static constexpr size_t InvalidIndex = ~0; + static constexpr size_t InvalidIndex = std::numeric_limits::max(); struct LocationHasher { diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI.Edit/ShaderPlatformInterface.h b/Gems/Atom/RHI/Code/Include/Atom/RHI.Edit/ShaderPlatformInterface.h index 5c5898e8d1..b2b16692b5 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI.Edit/ShaderPlatformInterface.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI.Edit/ShaderPlatformInterface.h @@ -81,7 +81,7 @@ namespace AZ struct ByProducts { AZStd::set m_intermediatePaths; //!< intermediate file paths (like dxil text form) - static constexpr uint32_t UnknownDynamicBranchCount = -1; + static constexpr uint32_t UnknownDynamicBranchCount = std::numeric_limits::max(); uint32_t m_dynamicBranchCount = UnknownDynamicBranchCount; }; diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/AliasedAttachmentAllocator.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/AliasedAttachmentAllocator.h index 5ccb48bf1c..8527d034d5 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/AliasedAttachmentAllocator.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/AliasedAttachmentAllocator.h @@ -248,7 +248,7 @@ namespace AZ // The no allocation heap is used when doing a 2 pass strategy. Internal::NoAllocationAliasedHeap::Descriptor heapAllocator; heapAllocator.m_alignment = descriptor.m_alignment; - heapAllocator.m_budgetInBytes = ~0; + heapAllocator.m_budgetInBytes = std::numeric_limits::max(); m_noAllocationHeap.Init(device, heapAllocator); typename decltype(m_garbageCollector)::Descriptor collectorDescriptor; diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/Conversions.cpp b/Gems/Atom/RHI/DX12/Code/Source/RHI/Conversions.cpp index 6018e180ef..823ec8e4e0 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI/Conversions.cpp +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/Conversions.cpp @@ -353,7 +353,7 @@ namespace AZ if (imageViewDescriptor.m_depthSliceMax == RHI::ImageViewDescriptor::HighestSliceIndex) { - renderTargetView.Texture3D.WSize = -1; + renderTargetView.Texture3D.WSize = std::numeric_limits::max(); } else { @@ -578,7 +578,7 @@ namespace AZ if (imageViewDescriptor.m_depthSliceMax == RHI::ImageViewDescriptor::HighestSliceIndex) { - unorderedAccessView.Texture3D.WSize = -1; + unorderedAccessView.Texture3D.WSize = std::numeric_limits::max(); } else { diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/CommandQueueContext.cpp b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/CommandQueueContext.cpp index 8635e8edcf..5d52dc8eeb 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/CommandQueueContext.cpp +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/CommandQueueContext.cpp @@ -304,7 +304,7 @@ namespace AZ { uint32_t m_familyIndex = InvalidFamilyIndex; bool m_newQueue = false; - uint32_t m_remainingFlags = ~0; + uint32_t m_remainingFlags = std::numeric_limits::max(); bool operator>(const QueueSelection& other) const { diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Device.cpp b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Device.cpp index 05ff8bb2a6..a3c762e327 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Device.cpp +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Device.cpp @@ -69,7 +69,7 @@ namespace AZ BuildDeviceQueueInfo(physicalDevice); - m_supportedPipelineStageFlagsMask = ~0; + m_supportedPipelineStageFlagsMask = std::numeric_limits::max(); const auto& deviceFeatures = physicalDevice.GetPhysicalDeviceFeatures(); m_enabledDeviceFeatures.samplerAnisotropy = deviceFeatures.samplerAnisotropy; diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Device.h b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Device.h index 28e56d1fa9..14eda8381d 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Device.h +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Device.h @@ -152,7 +152,7 @@ namespace AZ VkDevice m_nativeDevice = VK_NULL_HANDLE; VkPhysicalDeviceFeatures m_enabledDeviceFeatures{}; - VkPipelineStageFlags m_supportedPipelineStageFlagsMask = ~0; + VkPipelineStageFlags m_supportedPipelineStageFlagsMask = std::numeric_limits::max(); AZStd::vector m_queueFamilyProperties; RHI::Ptr m_asyncUploadQueue; diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/MergedShaderResourceGroup.h b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/MergedShaderResourceGroup.h index f285807210..649f9c3b80 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/MergedShaderResourceGroup.h +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/MergedShaderResourceGroup.h @@ -53,7 +53,7 @@ namespace AZ // Helper struct for easy initialization of the frame iteration. struct FrameIteration { - uint64_t m_frameIteration = ~0; + uint64_t m_frameIteration = std::numeric_limits::max(); }; // Utility function that merges multiple ShaderResoruceGroup data into one. diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialPropertyDescriptor.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialPropertyDescriptor.h index d3c4da27ad..085256f6d8 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialPropertyDescriptor.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialPropertyDescriptor.h @@ -103,7 +103,7 @@ namespace AZ AZ::TypeId GetStorageDataTypeId() const; //! Returns the value of the enum from its name. If this property is not an enum or the name is undefined, InvalidEnumValue is returned. - static constexpr uint32_t InvalidEnumValue = -1; + static constexpr uint32_t InvalidEnumValue = std::numeric_limits::max(); uint32_t GetEnumValue(const AZ::Name& enumName) const; //! Returns the unique name ID of this property diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Shader/ShaderVariantTreeAsset.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Shader/ShaderVariantTreeAsset.h index e2e5b5c140..e010024fa3 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Shader/ShaderVariantTreeAsset.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Shader/ShaderVariantTreeAsset.h @@ -75,7 +75,7 @@ namespace AZ private: - static constexpr uint32_t UnspecifiedIndex = -1; + static constexpr uint32_t UnspecifiedIndex = std::numeric_limits::max(); //! Returns the node associated with the provided index. const ShaderVariantTreeNode& GetNode(uint32_t index) const; diff --git a/Gems/Atom/Utils/Code/Include/Atom/Utils/StableDynamicArray.h b/Gems/Atom/Utils/Code/Include/Atom/Utils/StableDynamicArray.h index 454a6d4086..58c2a59cbf 100644 --- a/Gems/Atom/Utils/Code/Include/Atom/Utils/StableDynamicArray.h +++ b/Gems/Atom/Utils/Code/Include/Atom/Utils/StableDynamicArray.h @@ -130,7 +130,7 @@ namespace AZ template struct StableDynamicArray::Page { - static constexpr size_t InvalidPage = -1; + static constexpr size_t InvalidPage = std::numeric_limits::max(); static constexpr uint64_t FullBits = 0xFFFFFFFFFFFFFFFFull; static constexpr size_t NumUint64_t = ElementsPerPage / 64; From d5ed0cc3858645dd0f1e11198843999fd02039e4 Mon Sep 17 00:00:00 2001 From: pappeste Date: Mon, 28 Jun 2021 14:40:46 -0700 Subject: [PATCH 446/803] AtomLyIntegration Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../Code/Include/AtomLyIntegration/AtomFont/FontTexture.h | 2 +- .../Code/Include/AtomLyIntegration/AtomFont/GlyphCache.h | 2 +- .../Code/Source/Material/EditorMaterialComponentSlot.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/FontTexture.h b/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/FontTexture.h index b9bdce6810..f20b0463d9 100644 --- a/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/FontTexture.h +++ b/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/FontTexture.h @@ -39,7 +39,7 @@ namespace AZ void Reset() { m_slotUsage = 0; - m_currentCharacter = ~0; + m_currentCharacter = std::numeric_limits::max(); m_horizontalAdvance = 0; m_characterWidth = 0; m_characterHeight = 0; diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/GlyphCache.h b/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/GlyphCache.h index 8c6cf721b3..271b6810d3 100644 --- a/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/GlyphCache.h +++ b/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/GlyphCache.h @@ -46,7 +46,7 @@ namespace AZ void Reset() { m_usage = 0; - m_currentCharacter = ~0; + m_currentCharacter = std::numeric_limits::max(); m_characterWidth = 0; m_characterHeight = 0; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.h index 79fddf2611..58d6fa9ab0 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.h @@ -19,7 +19,7 @@ namespace AZ { namespace Render { - static const size_t DefaultMaterialSlotIndex = -1; + static const size_t DefaultMaterialSlotIndex = std::numeric_limits::max(); //! Details for a single editable material assignment struct EditorMaterialComponentSlot final From 80199b2ae1fc585429e94976dfef0680ebadfc60 Mon Sep 17 00:00:00 2001 From: pappeste Date: Mon, 28 Jun 2021 15:04:43 -0700 Subject: [PATCH 447/803] Audio Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Gems/AudioSystem/Code/Tests/AudioSystemTest.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gems/AudioSystem/Code/Tests/AudioSystemTest.cpp b/Gems/AudioSystem/Code/Tests/AudioSystemTest.cpp index 70d9dec330..ba1603d2e2 100644 --- a/Gems/AudioSystem/Code/Tests/AudioSystemTest.cpp +++ b/Gems/AudioSystem/Code/Tests/AudioSystemTest.cpp @@ -589,7 +589,7 @@ TEST(AudioFlagsTest, AudioFlags_OneFlag_OneFlagIsSet) { const AZ::u8 flagBit = 1 << 4; Audio::Flags testFlags(flagBit); - EXPECT_FALSE(testFlags.AreAnyFlagsActive(~flagBit)); + EXPECT_FALSE(testFlags.AreAnyFlagsActive(static_cast(~flagBit))); EXPECT_TRUE(testFlags.AreAnyFlagsActive(flagBit)); EXPECT_TRUE(testFlags.AreAnyFlagsActive(flagBit | 1)); EXPECT_TRUE(testFlags.AreAllFlagsActive(flagBit)); @@ -603,7 +603,7 @@ TEST(AudioFlagsTest, AudioFlags_MultipleFlags_MultipleFlagsAreSet) { const AZ::u8 flagBits = (1 << 5) | (1 << 2) | (1 << 3); Audio::Flags testFlags(flagBits); - EXPECT_FALSE(testFlags.AreAnyFlagsActive(~flagBits)); + EXPECT_FALSE(testFlags.AreAnyFlagsActive(static_cast(~flagBits))); EXPECT_TRUE(testFlags.AreAnyFlagsActive(flagBits)); EXPECT_TRUE(testFlags.AreAllFlagsActive(flagBits)); EXPECT_FALSE(testFlags.AreAllFlagsActive(flagBits | 1)); From 83e1615686b25ff050391489e625451b1a4003e5 Mon Sep 17 00:00:00 2001 From: pappeste Date: Mon, 28 Jun 2021 15:05:10 -0700 Subject: [PATCH 448/803] AWSGameLift Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../Tests/Activity/AWSGameLiftCreateSessionActivityTest.cpp | 2 +- .../Activity/AWSGameLiftCreateSessionOnQueueActivityTest.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Gems/AWSGameLift/Code/AWSGameLiftClient/Tests/Activity/AWSGameLiftCreateSessionActivityTest.cpp b/Gems/AWSGameLift/Code/AWSGameLiftClient/Tests/Activity/AWSGameLiftCreateSessionActivityTest.cpp index b1601e248a..70dcdba1af 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftClient/Tests/Activity/AWSGameLiftCreateSessionActivityTest.cpp +++ b/Gems/AWSGameLift/Code/AWSGameLiftClient/Tests/Activity/AWSGameLiftCreateSessionActivityTest.cpp @@ -44,7 +44,7 @@ TEST_F(AWSGameLiftCreateSessionActivityTest, ValidateCreateSessionRequest_CallWi TEST_F(AWSGameLiftCreateSessionActivityTest, ValidateCreateSessionRequest_CallWithNegativeMaxPlayer_GetFalseResult) { AWSGameLiftCreateSessionRequest request; - request.m_maxPlayer = -1; + request.m_maxPlayer = std::numeric_limits::max(); auto result = CreateSessionActivity::ValidateCreateSessionRequest(request); EXPECT_FALSE(result); diff --git a/Gems/AWSGameLift/Code/AWSGameLiftClient/Tests/Activity/AWSGameLiftCreateSessionOnQueueActivityTest.cpp b/Gems/AWSGameLift/Code/AWSGameLiftClient/Tests/Activity/AWSGameLiftCreateSessionOnQueueActivityTest.cpp index 529179b1fb..8a785d8007 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftClient/Tests/Activity/AWSGameLiftCreateSessionOnQueueActivityTest.cpp +++ b/Gems/AWSGameLift/Code/AWSGameLiftClient/Tests/Activity/AWSGameLiftCreateSessionOnQueueActivityTest.cpp @@ -40,7 +40,7 @@ TEST_F(AWSGameLiftCreateSessionOnQueueActivityTest, ValidateCreateSessionOnQueue TEST_F(AWSGameLiftCreateSessionOnQueueActivityTest, ValidateCreateSessionOnQueueRequest_CallWithNegativeMaxPlayer_GetFalseResult) { AWSGameLiftCreateSessionOnQueueRequest request; - request.m_maxPlayer = -1; + request.m_maxPlayer = std::numeric_limits::max(); auto result = CreateSessionOnQueueActivity::ValidateCreateSessionOnQueueRequest(request); EXPECT_FALSE(result); From 9b7dea6703ee0bbf71649b769147b215715bf5e0 Mon Sep 17 00:00:00 2001 From: pappeste Date: Mon, 28 Jun 2021 15:05:25 -0700 Subject: [PATCH 449/803] EMotionFX Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Gems/EMotionFX/Code/Include/Integration/ActorComponentBus.h | 2 +- .../Source/Editor/Plugins/Cloth/ClothJointInspectorPlugin.h | 2 +- .../Source/Editor/PropertyWidgets/MotionSetMotionIdHandler.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gems/EMotionFX/Code/Include/Integration/ActorComponentBus.h b/Gems/EMotionFX/Code/Include/Integration/ActorComponentBus.h index c6b18745e6..658f15786f 100644 --- a/Gems/EMotionFX/Code/Include/Integration/ActorComponentBus.h +++ b/Gems/EMotionFX/Code/Include/Integration/ActorComponentBus.h @@ -95,7 +95,7 @@ namespace EMotionFX /// Returns skinning method used by the actor. virtual SkinningMethod GetSkinningMethod() const = 0; - static const size_t s_invalidJointIndex = ~0; + static const size_t s_invalidJointIndex = std::numeric_limits::max(); }; using ActorComponentRequestBus = AZ::EBus; diff --git a/Gems/EMotionFX/Code/Source/Editor/Plugins/Cloth/ClothJointInspectorPlugin.h b/Gems/EMotionFX/Code/Source/Editor/Plugins/Cloth/ClothJointInspectorPlugin.h index ac35a6dfcd..6a920fa10d 100644 --- a/Gems/EMotionFX/Code/Source/Editor/Plugins/Cloth/ClothJointInspectorPlugin.h +++ b/Gems/EMotionFX/Code/Source/Editor/Plugins/Cloth/ClothJointInspectorPlugin.h @@ -28,7 +28,7 @@ namespace EMotionFX Q_OBJECT //AUTOMOC public: - enum + enum : uint32 { CLASS_ID = 0x8efd2bee }; diff --git a/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/MotionSetMotionIdHandler.h b/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/MotionSetMotionIdHandler.h index f5ef1ffed5..6ea49bf9ef 100644 --- a/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/MotionSetMotionIdHandler.h +++ b/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/MotionSetMotionIdHandler.h @@ -59,7 +59,7 @@ namespace EMotionFX static void ResetDisplayedRoundingError(); private: - size_t m_id = -1; + size_t m_id = std::numeric_limits::max(); bool m_displayMotionSelectionWeight = false; const IRandomMotionSelectionDataContainer* m_dataContainer = nullptr; static float s_displayedRoundingError; From 4598ec4a500ff718a106f1467c914dacd6ce1ebe Mon Sep 17 00:00:00 2001 From: pappeste Date: Mon, 28 Jun 2021 15:05:42 -0700 Subject: [PATCH 450/803] GraphModel Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Gems/GraphModel/Code/Include/GraphModel/Model/Common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/GraphModel/Code/Include/GraphModel/Model/Common.h b/Gems/GraphModel/Code/Include/GraphModel/Model/Common.h index 17ce8e8471..ec5901a4b5 100644 --- a/Gems/GraphModel/Code/Include/GraphModel/Model/Common.h +++ b/Gems/GraphModel/Code/Include/GraphModel/Model/Common.h @@ -66,6 +66,6 @@ namespace GraphModel using ModuleGraphManagerPtr = AZStd::shared_ptr; using ConstModuleGraphManagerPtr = AZStd::shared_ptr; - static const AZ::u32 DefaultWrappedNodeLayoutOrder = -1; + static const AZ::u32 DefaultWrappedNodeLayoutOrder = std::numeric_limits::max(); } // namespace GraphModel From 8fd75a340fdd819fc74e13999b07979f6b0d03b3 Mon Sep 17 00:00:00 2001 From: pappeste Date: Mon, 28 Jun 2021 15:06:10 -0700 Subject: [PATCH 451/803] GraphCanvas Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../GraphCanvas/Components/Nodes/Wrapper/WrapperNodeBus.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Components/Nodes/Wrapper/WrapperNodeBus.h b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Components/Nodes/Wrapper/WrapperNodeBus.h index a30915917f..0d45cbe536 100644 --- a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Components/Nodes/Wrapper/WrapperNodeBus.h +++ b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Components/Nodes/Wrapper/WrapperNodeBus.h @@ -34,14 +34,14 @@ namespace GraphCanvas AZ_CLASS_ALLOCATOR(WrappedNodeConfiguration, AZ::SystemAllocator, 0); WrappedNodeConfiguration() - : m_layoutOrder(-1) - , m_elementOrdering(-1) + : m_layoutOrder(std::numeric_limits::max()) + , m_elementOrdering(std::numeric_limits::max()) { } WrappedNodeConfiguration(AZ::u32 layoutOrder) : m_layoutOrder(layoutOrder) - , m_elementOrdering(-1) + , m_elementOrdering(std::numeric_limits::max()) { } From 859c5f8004394d6051e118b6453fdf0ac7742e76 Mon Sep 17 00:00:00 2001 From: pappeste Date: Mon, 28 Jun 2021 15:06:27 -0700 Subject: [PATCH 452/803] LyShine Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../Code/Editor/Animation/UiAVCustomizeTrackColorsDlg.cpp | 8 ++++---- Gems/LyShine/Code/Source/Animation/AnimTrack.h | 6 +++--- Gems/LyShine/Code/Source/UiTextComponent.cpp | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Gems/LyShine/Code/Editor/Animation/UiAVCustomizeTrackColorsDlg.cpp b/Gems/LyShine/Code/Editor/Animation/UiAVCustomizeTrackColorsDlg.cpp index cd7cb56421..8bfb3f955d 100644 --- a/Gems/LyShine/Code/Editor/Animation/UiAVCustomizeTrackColorsDlg.cpp +++ b/Gems/LyShine/Code/Editor/Animation/UiAVCustomizeTrackColorsDlg.cpp @@ -325,7 +325,7 @@ bool CUiAVCustomizeTrackColorsDlg::Import(const QString& fullPath) { continue; } - COLORREF color = -1; + COLORREF color = std::numeric_limits::max(); childNode->getAttr("color", color); m_colorButtons[entryIndex]->SetColor(color); } @@ -333,7 +333,7 @@ bool CUiAVCustomizeTrackColorsDlg::Import(const QString& fullPath) XmlNodeRef othersNode = customTrackColorsNode->findChild("others"); if (othersNode) { - COLORREF color = -1; + COLORREF color = std::numeric_limits::max(); othersNode->getAttr("color", color); m_colorButtons[kOthersEntryIndex]->SetColor(color); } @@ -341,7 +341,7 @@ bool CUiAVCustomizeTrackColorsDlg::Import(const QString& fullPath) XmlNodeRef disabledNode = customTrackColorsNode->findChild("disabled"); if (disabledNode) { - COLORREF color = -1; + COLORREF color = std::numeric_limits::max(); disabledNode->getAttr("color", color); m_colorButtons[kDisabledEntryIndex]->SetColor(color); } @@ -349,7 +349,7 @@ bool CUiAVCustomizeTrackColorsDlg::Import(const QString& fullPath) XmlNodeRef mutedNode = customTrackColorsNode->findChild("muted"); if (mutedNode) { - COLORREF color = -1; + COLORREF color = std::numeric_limits::max(); mutedNode->getAttr("color", color); m_colorButtons[kMutedEntryIndex]->SetColor(color); } diff --git a/Gems/LyShine/Code/Source/Animation/AnimTrack.h b/Gems/LyShine/Code/Source/Animation/AnimTrack.h index f73cd7ede7..97a251ebfa 100644 --- a/Gems/LyShine/Code/Source/Animation/AnimTrack.h +++ b/Gems/LyShine/Code/Source/Animation/AnimTrack.h @@ -521,7 +521,7 @@ inline int TUiAnimTrack::GetActiveKey(float time, KeyType* key) if (nkeys == 0) { m_lastTime = time; - m_currKey = -1; + m_currKey = std::numeric_limits::max(); return m_currKey; } @@ -554,7 +554,7 @@ inline int TUiAnimTrack::GetActiveKey(float time, KeyType* key) } else { - m_currKey = -1; + m_currKey = std::numeric_limits::max(); } return m_currKey; } @@ -600,6 +600,6 @@ inline int TUiAnimTrack::GetActiveKey(float time, KeyType* key) break; } } - m_currKey = -1; + m_currKey = std::numeric_limits::max(); return m_currKey; } diff --git a/Gems/LyShine/Code/Source/UiTextComponent.cpp b/Gems/LyShine/Code/Source/UiTextComponent.cpp index ef9c3d4bb7..f9544a9954 100644 --- a/Gems/LyShine/Code/Source/UiTextComponent.cpp +++ b/Gems/LyShine/Code/Source/UiTextComponent.cpp @@ -4149,7 +4149,7 @@ void UiTextComponent::RenderDrawBatchLines( imageQuad[i] = transformToViewport * imageQuad[i]; } - static const uint32 packedColor = (255 << 24) | (255 << 16) | (255 << 8) | 255; + static const uint32 packedColor = (255u << 24) | (255u << 16) | (255u << 8) | 255u; RenderCacheImageBatch* cacheImageBatch = new RenderCacheImageBatch; From 977107e59646d4d0c0574a1185ef392176f1a8c8 Mon Sep 17 00:00:00 2001 From: pappeste Date: Mon, 28 Jun 2021 15:07:11 -0700 Subject: [PATCH 453/803] Maestro Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Gems/Maestro/Code/Source/Components/EditorSequenceComponent.cpp | 2 +- Gems/Maestro/Code/Source/Components/EditorSequenceComponent.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Gems/Maestro/Code/Source/Components/EditorSequenceComponent.cpp b/Gems/Maestro/Code/Source/Components/EditorSequenceComponent.cpp index e7736cd30b..2e6491db5b 100644 --- a/Gems/Maestro/Code/Source/Components/EditorSequenceComponent.cpp +++ b/Gems/Maestro/Code/Source/Components/EditorSequenceComponent.cpp @@ -29,7 +29,7 @@ namespace Maestro { /*static*/ AZ::ScriptTimePoint EditorSequenceComponent::s_lastPropertyRefreshTime; /*static*/ const double EditorSequenceComponent::s_refreshPeriodMilliseconds = 200.0; // 5 Hz refresh rate - /*static*/ const int EditorSequenceComponent::s_invalidSequenceId = -1; + /*static*/ const uint32 EditorSequenceComponent::s_invalidSequenceId = std::numeric_limits::max(); namespace ClassConverters { diff --git a/Gems/Maestro/Code/Source/Components/EditorSequenceComponent.h b/Gems/Maestro/Code/Source/Components/EditorSequenceComponent.h index 597cd30912..83caaeea19 100644 --- a/Gems/Maestro/Code/Source/Components/EditorSequenceComponent.h +++ b/Gems/Maestro/Code/Source/Components/EditorSequenceComponent.h @@ -110,6 +110,6 @@ namespace Maestro static AZ::ScriptTimePoint s_lastPropertyRefreshTime; static const double s_refreshPeriodMilliseconds; // property refresh period for SetAnimatedPropertyValue events - static const int s_invalidSequenceId; + static const uint32 s_invalidSequenceId; }; } // namespace Maestro From 2a20231e101800d5b963e309256d032a2b87776a Mon Sep 17 00:00:00 2001 From: pappeste Date: Mon, 28 Jun 2021 15:07:26 -0700 Subject: [PATCH 454/803] MessagePopup Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Gems/MessagePopup/Code/Include/MessagePopup/MessagePopupBus.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/MessagePopup/Code/Include/MessagePopup/MessagePopupBus.h b/Gems/MessagePopup/Code/Include/MessagePopup/MessagePopupBus.h index e6f31ec08d..7dfa2ba5a8 100644 --- a/Gems/MessagePopup/Code/Include/MessagePopup/MessagePopupBus.h +++ b/Gems/MessagePopup/Code/Include/MessagePopup/MessagePopupBus.h @@ -25,7 +25,7 @@ namespace MessagePopup EPopupKind_Toaster }; - static const AZ::u32 InvalidId = -1; + static const AZ::u32 InvalidId = std::numeric_limits::max(); ////////////////////////////////////////////////////////////////////////// struct MessagePopupInfo From e24bb8fa5b125a708a3929fd33e53cc7d1c30b4a Mon Sep 17 00:00:00 2001 From: pappeste Date: Mon, 28 Jun 2021 15:07:42 -0700 Subject: [PATCH 455/803] MultiplayerCompression Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../Code/Tests/MultiplayerCompressionTest.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Gems/MultiplayerCompression/Code/Tests/MultiplayerCompressionTest.cpp b/Gems/MultiplayerCompression/Code/Tests/MultiplayerCompressionTest.cpp index 91839b1e23..bc154d24b2 100644 --- a/Gems/MultiplayerCompression/Code/Tests/MultiplayerCompressionTest.cpp +++ b/Gems/MultiplayerCompression/Code/Tests/MultiplayerCompressionTest.cpp @@ -42,9 +42,9 @@ TEST_F(MultiplayerCompressionTest, MultiplayerCompression_CompressTest) memset(buffer.GetBuffer(), 255, buffer.GetCapacity()); size_t maxCompressedSize = buffer.GetSize() + 32U; - size_t compressedSize = -1; - size_t uncompressedSize = -1; - size_t consumedSize = -1; + size_t compressedSize = std::numeric_limits::max(); + size_t uncompressedSize = std::numeric_limits::max(); + size_t consumedSize = std::numeric_limits::max(); char* pCompressedBuffer = new char[maxCompressedSize]; char* pDecompressedBuffer = new char[buffer.GetSize()]; From 82b359e80d0fdcc9544add3bf6cd889cb8c2873f Mon Sep 17 00:00:00 2001 From: pappeste Date: Mon, 28 Jun 2021 15:07:56 -0700 Subject: [PATCH 456/803] PhysX Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Gems/PhysX/Code/Source/Material.h | 2 +- .../Code/Source/SystemComponent.cpp | 26 +++++++++---------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/Gems/PhysX/Code/Source/Material.h b/Gems/PhysX/Code/Source/Material.h index 8613be7461..b30b7402c8 100644 --- a/Gems/PhysX/Code/Source/Material.h +++ b/Gems/PhysX/Code/Source/Material.h @@ -89,7 +89,7 @@ namespace PhysX PxMaterialUniquePtr m_pxMaterial; AZ::Crc32 m_surfaceType = 0; - AZ::u32 m_cryEngineSurfaceId = -1; + AZ::u32 m_cryEngineSurfaceId = std::numeric_limits::max(); AZStd::string m_surfaceString; float m_density = 1000.0f; AZ::Color m_debugColor = AZ::Colors::White; diff --git a/Gems/PhysXDebug/Code/Source/SystemComponent.cpp b/Gems/PhysXDebug/Code/Source/SystemComponent.cpp index 831a7fdf1d..e9948d2eb0 100644 --- a/Gems/PhysXDebug/Code/Source/SystemComponent.cpp +++ b/Gems/PhysXDebug/Code/Source/SystemComponent.cpp @@ -879,18 +879,18 @@ namespace PhysXDebug void SystemComponent::InitPhysXColorMappings() { AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::Physics); - m_colorMappings.m_defaultColor.FromU32(physx::PxDebugColor::eARGB_GREEN); - m_colorMappings.m_black.FromU32(physx::PxDebugColor::eARGB_BLACK); - m_colorMappings.m_red.FromU32(physx::PxDebugColor::eARGB_RED); - m_colorMappings.m_green.FromU32(physx::PxDebugColor::eARGB_GREEN); - m_colorMappings.m_blue.FromU32(physx::PxDebugColor::eARGB_BLUE); - m_colorMappings.m_yellow.FromU32(physx::PxDebugColor::eARGB_YELLOW); - m_colorMappings.m_magenta.FromU32(physx::PxDebugColor::eARGB_MAGENTA); - m_colorMappings.m_cyan.FromU32(physx::PxDebugColor::eARGB_CYAN); - m_colorMappings.m_white.FromU32(physx::PxDebugColor::eARGB_WHITE); - m_colorMappings.m_grey.FromU32(physx::PxDebugColor::eARGB_GREY); - m_colorMappings.m_darkRed.FromU32(physx::PxDebugColor::eARGB_DARKRED); - m_colorMappings.m_darkGreen.FromU32(physx::PxDebugColor::eARGB_DARKGREEN); - m_colorMappings.m_darkBlue.FromU32(physx::PxDebugColor::eARGB_DARKBLUE); + m_colorMappings.m_defaultColor.FromU32(static_cast(physx::PxDebugColor::eARGB_GREEN)); + m_colorMappings.m_black.FromU32(static_cast(physx::PxDebugColor::eARGB_BLACK)); + m_colorMappings.m_red.FromU32(static_cast(physx::PxDebugColor::eARGB_RED)); + m_colorMappings.m_green.FromU32(static_cast(physx::PxDebugColor::eARGB_GREEN)); + m_colorMappings.m_blue.FromU32(static_cast(physx::PxDebugColor::eARGB_BLUE)); + m_colorMappings.m_yellow.FromU32(static_cast(physx::PxDebugColor::eARGB_YELLOW)); + m_colorMappings.m_magenta.FromU32(static_cast(physx::PxDebugColor::eARGB_MAGENTA)); + m_colorMappings.m_cyan.FromU32(static_cast(physx::PxDebugColor::eARGB_CYAN)); + m_colorMappings.m_white.FromU32(static_cast(physx::PxDebugColor::eARGB_WHITE)); + m_colorMappings.m_grey.FromU32(static_cast(physx::PxDebugColor::eARGB_GREY)); + m_colorMappings.m_darkRed.FromU32(static_cast(physx::PxDebugColor::eARGB_DARKRED)); + m_colorMappings.m_darkGreen.FromU32(static_cast(physx::PxDebugColor::eARGB_DARKGREEN)); + m_colorMappings.m_darkBlue.FromU32(static_cast(physx::PxDebugColor::eARGB_DARKBLUE)); } } From 67a5bc98ceaa49925843f9a627e791d50025cef3 Mon Sep 17 00:00:00 2001 From: pappeste Date: Mon, 28 Jun 2021 15:08:14 -0700 Subject: [PATCH 457/803] ScriptCanvas Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Node.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Node.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Node.cpp index 6e87e52f87..ff1fadb8c2 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Node.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Node.cpp @@ -1981,7 +1981,7 @@ namespace ScriptCanvas if (slotIter == m_slots.end()) { - retVal = -1; + retVal = std::numeric_limits::max(); } return retVal; From 9c5b2768e2fd57c1a8741874c87e44e6a8ed2ada Mon Sep 17 00:00:00 2001 From: pappeste Date: Mon, 28 Jun 2021 15:13:11 -0700 Subject: [PATCH 458/803] =?UTF-8?q?=EF=BB=BFEditor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Editor/CryEdit.cpp | 2 +- Code/Editor/TrackView/TVCustomizeTrackColorsDlg.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Code/Editor/CryEdit.cpp b/Code/Editor/CryEdit.cpp index 8444f81317..80b5b091c6 100644 --- a/Code/Editor/CryEdit.cpp +++ b/Code/Editor/CryEdit.cpp @@ -3380,7 +3380,7 @@ CCryEditDoc* CCryEditApp::OpenDocumentFile(const char* lpszFileName) void CCryEditApp::OnResourcesReduceworkingset() { #ifdef WIN32 // no such thing on macOS - SetProcessWorkingSetSize(GetCurrentProcess(), -1, -1); + SetProcessWorkingSetSize(GetCurrentProcess(), std::numeric_limits::max(), std::numeric_limits::max()); #endif } diff --git a/Code/Editor/TrackView/TVCustomizeTrackColorsDlg.h b/Code/Editor/TrackView/TVCustomizeTrackColorsDlg.h index 23401453d6..d3017d8e83 100644 --- a/Code/Editor/TrackView/TVCustomizeTrackColorsDlg.h +++ b/Code/Editor/TrackView/TVCustomizeTrackColorsDlg.h @@ -56,7 +56,7 @@ private: inline void GetQColorFromXmlNode(QColor& colorOut, const XmlNodeRef& xmlNode) const { - QRgb rgb = -1; + QRgb rgb = std::numeric_limits::max(); xmlNode->getAttr("color", rgb); colorOut.setRgb(rgb); }; From e7f07147cb432473ca71a0fc3790ff21235d8f05 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 13 Aug 2021 16:04:31 -0700 Subject: [PATCH 459/803] More fixes for Code/Framework Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../AzCore/AzCore/Task/TaskExecutor.cpp | 4 +-- .../AzFramework/Script/ScriptComponent.cpp | 25 ++++++++++--------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/Task/TaskExecutor.cpp b/Code/Framework/AzCore/AzCore/Task/TaskExecutor.cpp index 5edb09edf0..2bb88fbfa2 100644 --- a/Code/Framework/AzCore/AzCore/Task/TaskExecutor.cpp +++ b/Code/Framework/AzCore/AzCore/Task/TaskExecutor.cpp @@ -78,7 +78,7 @@ namespace AZ return remaining; } - if (m_waitEvent && remaining == (m_parent ? 1 : 0)) + if (m_waitEvent && remaining == (m_parent ? 1u : 0u)) { m_waitEvent->Signal(); } @@ -259,7 +259,7 @@ namespace AZ } bool isRetained = task->m_graph->m_parent != nullptr; - if (task->m_graph->Release() == (isRetained ? 1 : 0)) + if (task->m_graph->Release() == (isRetained ? 1u : 0u)) { m_executor->ReleaseGraph(); } diff --git a/Code/Framework/AzFramework/AzFramework/Script/ScriptComponent.cpp b/Code/Framework/AzFramework/AzFramework/Script/ScriptComponent.cpp index fb8ca8b892..6db205795e 100644 --- a/Code/Framework/AzFramework/AzFramework/Script/ScriptComponent.cpp +++ b/Code/Framework/AzFramework/AzFramework/Script/ScriptComponent.cpp @@ -361,18 +361,19 @@ namespace AzFramework // DebugPrintStack // Prints the Lua stack starting from the bottom. //========================================================================= - static void DebugPrintStack(lua_State* lua, const AZStd::string& prefix = "") - { - AZStd::string dump = prefix; - const int stackSize = lua_gettop(lua); - for (int stackIdx = 1; stackIdx <= stackSize; ++stackIdx) - { - dump += PrintLuaValue(lua, stackIdx); - dump += " "; // add separator - } - - AZ_Warning("ScriptComponent", false, "Stack Dump: '%s'", dump.c_str()); - } + // DO NOT DELETE StackDump is useful to debug the lua stack. + //static void DebugPrintStack(lua_State* lua, const AZStd::string& prefix = "") + //{ + // AZStd::string dump = prefix; + // const int stackSize = lua_gettop(lua); + // for (int stackIdx = 1; stackIdx <= stackSize; ++stackIdx) + // { + // dump += PrintLuaValue(lua, stackIdx); + // dump += " "; // add separator + // } + // + // AZ_Warning("ScriptComponent", false, "Stack Dump: '%s'", dump.c_str()); + //} //========================================================================= // Properties__IndexFindSubtable From 1d4c53a77713193ee01a71f274f36befb0e317d3 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 13 Aug 2021 16:04:46 -0700 Subject: [PATCH 460/803] More fixes for Gems Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../Include/Public/Framework/AWSApiClientJobConfig.h | 3 +++ .../Include/Public/Framework/HttpRequestJobConfig.h | 3 +++ .../Public/Framework/ServiceClientJobConfig.h | 6 ++++-- .../Code/Include/Public/Framework/ServiceJobConfig.h | 10 ++++------ .../Public/Framework/ServiceRequestJobConfig.h | 3 ++- .../Editor/Attribution/AWSCoreAttributionMetric.cpp | 8 +++++++- Gems/AWSMetrics/Code/Source/MetricsEventBuilder.cpp | 8 +++++++- .../Source/RPI.Reflect/Model/ModelMaterialSlot.cpp | 2 +- .../Window/AtomToolsMainWindowRequestBus.h | 4 ++-- Gems/EMotionFX/Code/EMotionFX/Source/Mesh.h | 2 +- .../Code/MCore/Source/MCoreCommandManager.cpp | 2 +- .../Code/Editor/Animation/UiAnimViewCurveEditor.cpp | 2 +- .../Code/Editor/Animation/UiAnimViewDialog.cpp | 2 +- .../Editor/Animation/UiAnimViewDopeSheetBase.cpp | 12 ++++++------ .../Code/Editor/Animation/UiAnimViewSplineCtrl.cpp | 10 +++++----- 15 files changed, 48 insertions(+), 29 deletions(-) diff --git a/Gems/AWSCore/Code/Include/Public/Framework/AWSApiClientJobConfig.h b/Gems/AWSCore/Code/Include/Public/Framework/AWSApiClientJobConfig.h index 800edffd41..e991b2af7e 100644 --- a/Gems/AWSCore/Code/Include/Public/Framework/AWSApiClientJobConfig.h +++ b/Gems/AWSCore/Code/Include/Public/Framework/AWSApiClientJobConfig.h @@ -48,6 +48,7 @@ namespace AWSCore // warning C4250: 'AWSCore::AwsApiClientJobConfig': inherits 'AWSCore::AwsApiJobConfig::AWSCore::AwsApiJobConfig::GetJobContext' via dominance // Thanks to http://stackoverflow.com/questions/11965596/diamond-inheritance-scenario-compiles-fine-in-g-but-produces-warnings-errors for the explanation // This is the expected and desired behavior. The warning is superfluous. + AZ_PUSH_DISABLE_WARNING(4250, "-Wunknown-warning-option") /// Configuration for AWS jobs using a specific client type. template class AwsApiClientJobConfig @@ -120,4 +121,6 @@ namespace AWSCore /// Set by ApplySettings std::shared_ptr m_client; }; + AZ_POP_DISABLE_WARNING + } // namespace AWSCore diff --git a/Gems/AWSCore/Code/Include/Public/Framework/HttpRequestJobConfig.h b/Gems/AWSCore/Code/Include/Public/Framework/HttpRequestJobConfig.h index f5a089b5ca..5b348d8630 100644 --- a/Gems/AWSCore/Code/Include/Public/Framework/HttpRequestJobConfig.h +++ b/Gems/AWSCore/Code/Include/Public/Framework/HttpRequestJobConfig.h @@ -30,6 +30,7 @@ namespace AWSCore // warning C4250: 'AWSCore::HttpRequestJobConfig' : inherits 'AWSCore::AwsApiJobConfig::AWSCore::AwsApiJobConfig::GetJobContext' via dominance // Thanks to http://stackoverflow.com/questions/11965596/diamond-inheritance-scenario-compiles-fine-in-g-but-produces-warnings-errors for the explanation // This is the expected and desired behavior. The warning is superfluous. + AZ_PUSH_DISABLE_WARNING(4250, "-Wunknown-warning-option") //! Provides service job configuration using settings properties. class HttpRequestJobConfig : public AwsApiJobConfig @@ -92,4 +93,6 @@ namespace AWSCore std::shared_ptr m_httpClient{ nullptr }; Aws::String m_userAgent{}; }; + AZ_POP_DISABLE_WARNING + } // namespace AWSCore diff --git a/Gems/AWSCore/Code/Include/Public/Framework/ServiceClientJobConfig.h b/Gems/AWSCore/Code/Include/Public/Framework/ServiceClientJobConfig.h index c78fc41617..9082498e96 100644 --- a/Gems/AWSCore/Code/Include/Public/Framework/ServiceClientJobConfig.h +++ b/Gems/AWSCore/Code/Include/Public/Framework/ServiceClientJobConfig.h @@ -63,8 +63,8 @@ namespace AWSCore // warning C4250: 'AWSCore::ServiceClientJobConfig' : inherits 'AWSCore::AwsApiJobConfig::AWSCore::AwsApiJobConfig::GetJobContext' via dominance // Thanks to http://stackoverflow.com/questions/11965596/diamond-inheritance-scenario-compiles-fine-in-g-but-produces-warnings-errors for the explanation // This is the expected and desired behavior. The warning is superfluous. - -/// Provides service job configuration using settings properties. + AZ_PUSH_DISABLE_WARNING(4250, "-Wunknown-warning-option") + /// Provides service job configuration using settings properties. template class ServiceClientJobConfig : public ServiceJobConfig @@ -127,6 +127,8 @@ namespace AWSCore } }; + AZ_POP_DISABLE_WARNING + } // namespace AWSCore diff --git a/Gems/AWSCore/Code/Include/Public/Framework/ServiceJobConfig.h b/Gems/AWSCore/Code/Include/Public/Framework/ServiceJobConfig.h index 8632db7d9f..f1a01cfb7b 100644 --- a/Gems/AWSCore/Code/Include/Public/Framework/ServiceJobConfig.h +++ b/Gems/AWSCore/Code/Include/Public/Framework/ServiceJobConfig.h @@ -12,7 +12,6 @@ namespace AWSCore { - /// Provides configuration needed by service jobs. class IServiceJobConfig : public virtual IHttpRequestJobConfig @@ -22,12 +21,12 @@ namespace AWSCore // warning C4250: 'AWSCore::ServiceJobConfig' : inherits 'AWSCore::AwsApiJobConfig::AWSCore::AwsApiJobConfig::GetJobContext' via dominance // Thanks to http://stackoverflow.com/questions/11965596/diamond-inheritance-scenario-compiles-fine-in-g-but-produces-warnings-errors for the explanation // This is the expected and desired behavior. The warning is superfluous. -/// Provides service job configuration using settings properties. + AZ_PUSH_DISABLE_WARNING(4250, "-Wunknown-warning-option") + /// Provides service job configuration using settings properties. class ServiceJobConfig : public HttpRequestJobConfig , public virtual IServiceJobConfig { - public: AZ_CLASS_ALLOCATOR(ServiceJobConfig, AZ::SystemAllocator, 0); @@ -53,8 +52,7 @@ namespace AWSCore } void ApplySettings() override; - - private: - }; + AZ_POP_DISABLE_WARNING + } // namespace AWSCore diff --git a/Gems/AWSCore/Code/Include/Public/Framework/ServiceRequestJobConfig.h b/Gems/AWSCore/Code/Include/Public/Framework/ServiceRequestJobConfig.h index 660b4f2537..240331496e 100644 --- a/Gems/AWSCore/Code/Include/Public/Framework/ServiceRequestJobConfig.h +++ b/Gems/AWSCore/Code/Include/Public/Framework/ServiceRequestJobConfig.h @@ -28,7 +28,7 @@ namespace AWSCore // warning C4250: 'AWSCore::ServiceRequestJobConfig' : inherits 'AWSCore::AwsApiJobConfig::AWSCore::AwsApiJobConfig::GetJobContext' via dominance // Thanks to http://stackoverflow.com/questions/11965596/diamond-inheritance-scenario-compiles-fine-in-g-but-produces-warnings-errors for the explanation // This is the expected and desired behavior. The warning is superfluous. - + AZ_PUSH_DISABLE_WARNING(4250, "-Wunknown-warning-option") template class ServiceRequestJobConfig : public ServiceClientJobConfig @@ -100,5 +100,6 @@ namespace AWSCore std::shared_ptr m_credentialsProvider; }; + AZ_POP_DISABLE_WARNING } // namespace AWSCore diff --git a/Gems/AWSCore/Code/Source/Editor/Attribution/AWSCoreAttributionMetric.cpp b/Gems/AWSCore/Code/Source/Editor/Attribution/AWSCoreAttributionMetric.cpp index c4f51fcb6f..aee766d355 100644 --- a/Gems/AWSCore/Code/Source/Editor/Attribution/AWSCoreAttributionMetric.cpp +++ b/Gems/AWSCore/Code/Source/Editor/Attribution/AWSCoreAttributionMetric.cpp @@ -95,7 +95,13 @@ namespace AWSCore time_t now; time(&now); char buffer[50]; - strftime(buffer, sizeof(buffer), "%FT%TZ", gmtime(&now)); + tm time; +#if AZ_TRAIT_USE_SECURE_CRT_FUNCTIONS + gmtime_s(&time, &now); +#else + time = *gmtime(&now); +#endif + strftime(buffer, sizeof(buffer), "%FT%TZ", &time); return buffer; } diff --git a/Gems/AWSMetrics/Code/Source/MetricsEventBuilder.cpp b/Gems/AWSMetrics/Code/Source/MetricsEventBuilder.cpp index 043af2ef09..743a8c5849 100644 --- a/Gems/AWSMetrics/Code/Source/MetricsEventBuilder.cpp +++ b/Gems/AWSMetrics/Code/Source/MetricsEventBuilder.cpp @@ -55,7 +55,13 @@ namespace AWSMetrics time_t now; time(&now); char buffer[50]; - strftime(buffer, sizeof(buffer), "%FT%TZ", gmtime(&now)); + tm time; +#if AZ_TRAIT_USE_SECURE_CRT_FUNCTIONS + gmtime_s(&time, &now); +#else + time = *gmtime(&now); +#endif + strftime(buffer, sizeof(buffer), "%FT%TZ", &time); m_currentMetricsEvent.AddAttribute(MetricsAttribute(AwsMetricsAttributeKeyEventTimestamp, AZStd::string(buffer))); } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelMaterialSlot.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelMaterialSlot.cpp index 0900949625..b9d9200aaf 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelMaterialSlot.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelMaterialSlot.cpp @@ -15,7 +15,7 @@ namespace AZ { // Normally this would be defined in the header file and substituted by the compiler, but for // some reason clang doesn't accept it. - const ModelMaterialSlot::StableId ModelMaterialSlot::InvalidStableId = -1; + const ModelMaterialSlot::StableId ModelMaterialSlot::InvalidStableId = std::numeric_limits::max(); void ModelMaterialSlot::Reflect(AZ::ReflectContext* context) { diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindowRequestBus.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindowRequestBus.h index 647082f553..cb63ff295c 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindowRequestBus.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindowRequestBus.h @@ -50,10 +50,10 @@ namespace AtomToolsFramework //! Resizes the main window to achieve a requested size for the viewport render target. //! (This indicates the size of the render target, not the desktop-scaled QT widget size). - virtual void ResizeViewportRenderTarget(uint32_t width, uint32_t height) {}; + virtual void ResizeViewportRenderTarget([[maybe_unused]] uint32_t width, [[maybe_unused]] uint32_t height) {}; //! Forces the viewport's render target to use the given resolution, ignoring the size of the viewport widget. - virtual void LockViewportRenderTargetSize(uint32_t width, uint32_t height) {}; + virtual void LockViewportRenderTargetSize([[maybe_unused]] uint32_t width, [[maybe_unused]] uint32_t height) {}; //! Releases the viewport's render target resolution lock, allowing it to match the viewport widget again. virtual void UnlockViewportRenderTargetSize() {}; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.h b/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.h index c2d776bcdb..ebd65f833a 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Mesh.h @@ -64,7 +64,7 @@ namespace EMotionFX * VertexAttributeLayerAbstractData::GetType() values for the vertex data * Use these with the Mesh::FindVertexData() and Mesh::FindOriginalVertexData() methods. */ - enum + enum : uint32 { ATTRIB_POSITIONS = 0, /**< Vertex positions. Typecast to AZ::Vector3. Positions are always exist. */ ATTRIB_NORMALS = 1, /**< Vertex normals. Typecast to AZ::Vector3. Normals are always exist. */ diff --git a/Gems/EMotionFX/Code/MCore/Source/MCoreCommandManager.cpp b/Gems/EMotionFX/Code/MCore/Source/MCoreCommandManager.cpp index 5cdd9c2600..b59f2b69a0 100644 --- a/Gems/EMotionFX/Code/MCore/Source/MCoreCommandManager.cpp +++ b/Gems/EMotionFX/Code/MCore/Source/MCoreCommandManager.cpp @@ -1123,7 +1123,7 @@ namespace MCore for (size_t i = 0; i < numHistoryEntries; ++i) { AZStd::string text = AZStd::string::format("%.3zu: name='%s', num parameters=%zu", i, m_commandHistory[i].m_executedCommand->GetName(), m_commandHistory[i].m_parameters.GetNumParameters()); - if (i == m_historyIndex) + if (i == static_cast(m_historyIndex)) { LogDetailedInfo("-> %s", text.c_str()); } diff --git a/Gems/LyShine/Code/Editor/Animation/UiAnimViewCurveEditor.cpp b/Gems/LyShine/Code/Editor/Animation/UiAnimViewCurveEditor.cpp index 339cb4b5bc..51209c7f02 100644 --- a/Gems/LyShine/Code/Editor/Animation/UiAnimViewCurveEditor.cpp +++ b/Gems/LyShine/Code/Editor/Animation/UiAnimViewCurveEditor.cpp @@ -177,7 +177,7 @@ void CUiAnimViewCurveEditor::UpdateSplines() std::set newTracks; if (selectedTracks.AreAllOfSameType()) { - for (int i = 0; i < selectedTracks.GetCount(); i++) + for (unsigned int i = 0; i < selectedTracks.GetCount(); i++) { CUiAnimViewTrack* pTrack = selectedTracks.GetTrack(i); diff --git a/Gems/LyShine/Code/Editor/Animation/UiAnimViewDialog.cpp b/Gems/LyShine/Code/Editor/Animation/UiAnimViewDialog.cpp index ac210ba2f2..97f21e9bab 100644 --- a/Gems/LyShine/Code/Editor/Animation/UiAnimViewDialog.cpp +++ b/Gems/LyShine/Code/Editor/Animation/UiAnimViewDialog.cpp @@ -989,7 +989,7 @@ void CUiAnimViewDialog::ReloadSequencesComboBox() CUiAnimViewSequenceManager* pSequenceManager = CUiAnimViewSequenceManager::GetSequenceManager(); const unsigned int numSequences = pSequenceManager->GetCount(); - for (int k = 0; k < numSequences; ++k) + for (unsigned int k = 0; k < numSequences; ++k) { CUiAnimViewSequence* pSequence = pSequenceManager->GetSequenceByIndex(k); QString fullname = pSequence->GetName(); diff --git a/Gems/LyShine/Code/Editor/Animation/UiAnimViewDopeSheetBase.cpp b/Gems/LyShine/Code/Editor/Animation/UiAnimViewDopeSheetBase.cpp index bd5c82fc9e..12f1eeac4d 100644 --- a/Gems/LyShine/Code/Editor/Animation/UiAnimViewDopeSheetBase.cpp +++ b/Gems/LyShine/Code/Editor/Animation/UiAnimViewDopeSheetBase.cpp @@ -925,12 +925,12 @@ void CUiAnimViewDopeSheetBase::SelectAllKeysWithinTimeFrame(const QRect& rc, con CUiAnimViewTrackBundle tracks = pSequence->GetAllTracks(); CUiAnimViewSequenceNotificationContext context(pSequence); - for (int i = 0; i < tracks.GetCount(); ++i) + for (unsigned int i = 0; i < tracks.GetCount(); ++i) { CUiAnimViewTrack* pTrack = tracks.GetTrack(i); // Check which keys we intersect. - for (int j = 0; j < pTrack->GetKeyCount(); j++) + for (unsigned int j = 0; j < pTrack->GetKeyCount(); j++) { CUiAnimViewKeyHandle keyHandle = pTrack->GetKey(j); const float time = keyHandle.GetTime(); @@ -1311,7 +1311,7 @@ bool CUiAnimViewDopeSheetBase::IsOkToAddKeyHere(const CUiAnimViewTrack* pTrack, { const float timeEpsilon = 0.05f; - for (int i = 0; i < pTrack->GetKeyCount(); ++i) + for (unsigned int i = 0; i < pTrack->GetKeyCount(); ++i) { CUiAnimViewKeyHandle keyHandle = const_cast(pTrack)->GetKey(i); @@ -1425,10 +1425,10 @@ void CUiAnimViewDopeSheetBase::MouseMoveMove(const QPoint& p, [[maybe_unused]] Q const TrackMemento& trackMemento = iter->second; pTrack->RestoreFromMemento(trackMemento.m_memento); - const unsigned int numKeys = trackMemento.m_keySelectionStates.size(); - for (unsigned int i = 0; i < numKeys; ++i) + const size_t numKeys = trackMemento.m_keySelectionStates.size(); + for (size_t i = 0; i < numKeys; ++i) { - pTrack->GetKey(i).Select(trackMemento.m_keySelectionStates[i]); + pTrack->GetKey(static_cast(i)).Select(trackMemento.m_keySelectionStates[i]); } } diff --git a/Gems/LyShine/Code/Editor/Animation/UiAnimViewSplineCtrl.cpp b/Gems/LyShine/Code/Editor/Animation/UiAnimViewSplineCtrl.cpp index ba4893abb4..8edd13f8cc 100644 --- a/Gems/LyShine/Code/Editor/Animation/UiAnimViewSplineCtrl.cpp +++ b/Gems/LyShine/Code/Editor/Animation/UiAnimViewSplineCtrl.cpp @@ -667,7 +667,7 @@ void CUiAnimViewSplineCtrl::mouseMoveEvent(QMouseEvent* event) QString tipText; bool boFoundTheSelectedKey(false); - for (int splineIndex = 0, endSpline = m_splines.size(); splineIndex < endSpline; ++splineIndex) + for (size_t splineIndex = 0, endSpline = m_splines.size(); splineIndex < endSpline; ++splineIndex) { ISplineInterpolator* pSpline = m_splines[splineIndex].pSpline; CUiAnimViewTrack* pTrack = m_tracks[splineIndex]; @@ -757,7 +757,7 @@ void CUiAnimViewSplineCtrl::AdjustTCB(float d_tension, float d_continuity, float SendNotifyEvent(SPLN_BEFORE_CHANGE); - for (int splineIndex = 0, splineCount = m_splines.size(); splineIndex < splineCount; ++splineIndex) + for (size_t splineIndex = 0, splineCount = m_splines.size(); splineIndex < splineCount; ++splineIndex) { ISplineInterpolator* pSpline = m_splines[splineIndex].pSpline; CUiAnimViewTrack* pTrack = m_tracks[splineIndex]; @@ -866,16 +866,16 @@ void CUiAnimViewSplineCtrl::OnUserCommand(UINT cmd) bool CUiAnimViewSplineCtrl::IsUnifiedKeyCurrentlySelected() const { - for (int splineIndex = 0, splineCount = m_splines.size(); splineIndex < splineCount; ++splineIndex) + for (size_t splineIndex = 0, splineCount = m_splines.size(); splineIndex < splineCount; ++splineIndex) { ISplineInterpolator* pSpline = m_splines[splineIndex].pSpline; - if (pSpline == NULL) + if (!pSpline) { continue; } - for (int i = 0; i < (int)pSpline->GetKeyCount(); i++) + for (int i = 0; i < pSpline->GetKeyCount(); i++) { // If the key is selected in any dimension... for ( From 5f7b534afd3ae3b925981140e3e8125ecb58febf Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 13 Aug 2021 16:05:20 -0700 Subject: [PATCH 461/803] More fixes for Code/Editor Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Editor/BaseLibraryManager.h | 2 +- Code/Editor/Commands/CommandManager.cpp | 4 +- Code/Editor/ConfigGroup.cpp | 2 +- Code/Editor/Controls/ConsoleSCB.cpp | 2 +- Code/Editor/Controls/ImageHistogramCtrl.cpp | 6 +-- .../PropertyAnimationCtrl.cpp | 4 +- .../ReflectedPropertyCtrl.cpp | 2 +- Code/Editor/Controls/SplineCtrlEx.cpp | 38 +++++++++---------- Code/Editor/Controls/SplineCtrlEx.h | 2 +- Code/Editor/Controls/TextEditorCtrl.cpp | 2 +- Code/Editor/CryEdit.cpp | 4 +- Code/Editor/CryEditDoc.cpp | 2 +- Code/Editor/EditorViewportWidget.cpp | 2 +- Code/Editor/ErrorReportTableModel.cpp | 2 +- Code/Editor/Export/ExportManager.cpp | 6 +-- Code/Editor/Export/ExportManager.h | 24 ++++++------ Code/Editor/Export/OBJExporter.cpp | 4 +- Code/Editor/Export/OCMExporter.cpp | 12 +++--- Code/Editor/GameExporter.cpp | 14 +++---- Code/Editor/GameResourcesExporter.cpp | 21 +--------- Code/Editor/Geometry/TriMesh.cpp | 2 +- Code/Editor/LevelFileDialog.cpp | 2 +- Code/Editor/MainWindow.cpp | 2 +- Code/Editor/Objects/BaseObject.cpp | 18 ++++----- Code/Editor/Objects/EntityObject.cpp | 26 ++++++------- Code/Editor/Objects/ObjectLoader.cpp | 8 ++-- Code/Editor/Objects/ObjectManager.cpp | 14 +++---- Code/Editor/Objects/SelectionGroup.cpp | 4 +- .../UI/AssetCatalogModel.cpp | 2 +- .../ComponentPalette/ComponentDataModel.cpp | 2 +- Code/Editor/PreferencesStdPages.cpp | 2 +- Code/Editor/QtViewPaneManager.cpp | 2 +- Code/Editor/Settings.cpp | 2 +- Code/Editor/ToolBox.cpp | 4 +- Code/Editor/ToolbarManager.cpp | 2 +- Code/Editor/ToolsConfigPage.cpp | 2 +- .../Editor/TrackView/CommentKeyUIControls.cpp | 2 +- .../TrackView/ScreenFaderKeyUIControls.cpp | 2 +- .../TrackView/SequenceBatchRenderDialog.cpp | 6 +-- .../TrackView/SequenceKeyUIControls.cpp | 2 +- Code/Editor/TrackView/TVEventsDialog.cpp | 2 +- Code/Editor/TrackView/TrackViewAnimNode.cpp | 2 +- .../Editor/TrackView/TrackViewCurveEditor.cpp | 2 +- Code/Editor/TrackView/TrackViewDialog.cpp | 6 +-- .../TrackView/TrackViewDopeSheetBase.cpp | 8 ++-- Code/Editor/TrackView/TrackViewNode.cpp | 2 +- Code/Editor/TrackView/TrackViewNodes.cpp | 2 +- .../Editor/TrackView/TrackViewPythonFuncs.cpp | 4 +- Code/Editor/TrackView/TrackViewSequence.cpp | 4 +- .../TrackView/TrackViewSequenceManager.cpp | 8 ++-- Code/Editor/TrackView/TrackViewSplineCtrl.cpp | 6 +-- Code/Editor/TrackView/TrackViewUndo.cpp | 2 +- Code/Editor/TrackViewNewSequenceDialog.cpp | 2 +- Code/Editor/Undo/Undo.cpp | 8 ++-- Code/Editor/UndoDropDown.cpp | 6 +-- Code/Editor/Util/FileUtil.cpp | 26 ++++++------- Code/Editor/Util/ImageASC.cpp | 4 +- Code/Editor/Util/ImageGif.cpp | 2 +- Code/Editor/Util/ImageTIF.cpp | 6 +-- Code/Editor/Util/ImageUtil.cpp | 6 +-- Code/Editor/Util/KDTree.cpp | 4 +- Code/Editor/Util/NamedData.cpp | 6 +-- Code/Editor/Util/Variable.cpp | 2 +- Code/Editor/Util/XmlArchive.cpp | 2 +- Code/Editor/WipFeatureManager.cpp | 2 +- Code/Editor/WipFeaturesDlg.cpp | 2 +- 66 files changed, 185 insertions(+), 202 deletions(-) diff --git a/Code/Editor/BaseLibraryManager.h b/Code/Editor/BaseLibraryManager.h index 05f370e632..6f0b905760 100644 --- a/Code/Editor/BaseLibraryManager.h +++ b/Code/Editor/BaseLibraryManager.h @@ -73,7 +73,7 @@ public: virtual IDataBaseLibrary* AddLibrary(const QString& library, bool bIsLevelLibrary = false, bool bIsLoading = true) override; virtual void DeleteLibrary(const QString& library, bool forceDeleteLevel = false) override; //! Get number of libraries. - virtual int GetLibraryCount() const override { return m_libs.size(); }; + virtual int GetLibraryCount() const override { return static_cast(m_libs.size()); }; //! Get number of modified libraries. virtual int GetModifiedLibraryCount() const override; diff --git a/Code/Editor/Commands/CommandManager.cpp b/Code/Editor/Commands/CommandManager.cpp index f28ca96ac8..5f194971f5 100644 --- a/Code/Editor/Commands/CommandManager.cpp +++ b/Code/Editor/Commands/CommandManager.cpp @@ -529,8 +529,8 @@ QString CEditorCommandManager::ExecuteAndLogReturn(CCommand* pCommand, const CCo void CEditorCommandManager::GetArgsFromString(const AZStd::string& argsTxt, CCommand::CArgs& argList) { const char quoteSymbol = '\''; - int curPos = 0; - int prevPos = 0; + size_t curPos = 0; + size_t prevPos = 0; AZStd::vector tokens; AZ::StringFunc::Tokenize(argsTxt, tokens, ' '); for(AZStd::string& arg : tokens) diff --git a/Code/Editor/ConfigGroup.cpp b/Code/Editor/ConfigGroup.cpp index b18edf1142..74fe6f7b5c 100644 --- a/Code/Editor/ConfigGroup.cpp +++ b/Code/Editor/ConfigGroup.cpp @@ -33,7 +33,7 @@ namespace Config uint32 CConfigGroup::GetVarCount() { - return m_vars.size(); + return static_cast(m_vars.size()); } IConfigVar* CConfigGroup::GetVar(const char* szName) diff --git a/Code/Editor/Controls/ConsoleSCB.cpp b/Code/Editor/Controls/ConsoleSCB.cpp index 093575d445..acbd75444c 100644 --- a/Code/Editor/Controls/ConsoleSCB.cpp +++ b/Code/Editor/Controls/ConsoleSCB.cpp @@ -220,7 +220,7 @@ void ConsoleLineEdit::keyPressEvent(QKeyEvent* ev) } // If a history command was reused directly via up arrow enter, do not reset history index - if (m_history.size() > 0 && m_historyIndex < m_history.size() && m_history[m_historyIndex] == str) + if (m_history.size() > 0 && m_historyIndex < static_cast(m_history.size()) && m_history[m_historyIndex] == str) { m_bReusedHistory = true; } diff --git a/Code/Editor/Controls/ImageHistogramCtrl.cpp b/Code/Editor/Controls/ImageHistogramCtrl.cpp index 7218c0cd38..22223a3251 100644 --- a/Code/Editor/Controls/ImageHistogramCtrl.cpp +++ b/Code/Editor/Controls/ImageHistogramCtrl.cpp @@ -244,7 +244,7 @@ void CImageHistogramDisplay::paintEvent([[maybe_unused]] QPaintEvent* event) } } - crtX = rcGraph.left() + x + 1; + crtX = static_cast(rcGraph.left() + x + 1); painter.drawLine(crtX, graphBottom, crtX, graphBottom - scale * graphHeight); } } @@ -260,7 +260,7 @@ void CImageHistogramDisplay::paintEvent([[maybe_unused]] QPaintEvent* event) { i = ((float)x / graphWidth) * (kNumColorLevels - 1); i = CLAMP(i, 0, kNumColorLevels - 1); - crtX = rcGraph.left() + x + 1; + crtX = static_cast(rcGraph.left() + x + 1); scaleR = scaleG = scaleB = scaleA = 0; if (m_maxCount[0]) @@ -385,7 +385,7 @@ void CImageHistogramDisplay::paintEvent([[maybe_unused]] QPaintEvent* event) } painter.setPen(pPen); - painter.drawLine(rcGraph.left() + x + 1, graphBottom, rcGraph.left() + x + 1, graphBottom - scale * graphHeight); + painter.drawLine(rcGraph.left() + static_cast(x) + 1, graphBottom, rcGraph.left() + static_cast(x) + 1, graphBottom - scale * graphHeight); } // then draw 3 lines so we separate the channels diff --git a/Code/Editor/Controls/ReflectedPropertyControl/PropertyAnimationCtrl.cpp b/Code/Editor/Controls/ReflectedPropertyControl/PropertyAnimationCtrl.cpp index fde5642b05..4fb18e438c 100644 --- a/Code/Editor/Controls/ReflectedPropertyControl/PropertyAnimationCtrl.cpp +++ b/Code/Editor/Controls/ReflectedPropertyControl/PropertyAnimationCtrl.cpp @@ -56,8 +56,8 @@ CReflectedVarAnimation AnimationPropertyCtrl::value() const void AnimationPropertyCtrl::OnApplyClicked() { QStringList cSelectedAnimations; - size_t nTotalAnimations(0); - size_t nCurrentAnimation(0); + int nTotalAnimations(0); + int nCurrentAnimation(0); QString combinedString = GetIEditor()->GetResourceSelectorHost()->GetGlobalSelection("animation"); SplitString(combinedString, cSelectedAnimations, ','); diff --git a/Code/Editor/Controls/ReflectedPropertyControl/ReflectedPropertyCtrl.cpp b/Code/Editor/Controls/ReflectedPropertyControl/ReflectedPropertyCtrl.cpp index cf80d56962..3c7bda21d9 100644 --- a/Code/Editor/Controls/ReflectedPropertyControl/ReflectedPropertyCtrl.cpp +++ b/Code/Editor/Controls/ReflectedPropertyControl/ReflectedPropertyCtrl.cpp @@ -203,7 +203,7 @@ void ReflectedPropertyControl::CreateItems(XmlNodeRef node, CVarBlockPtr& outBlo outBlockPtr = new CVarBlock; for (size_t i = 0, iGroupCount(node->getChildCount()); i < iGroupCount; ++i) { - XmlNodeRef groupNode = node->getChild(i); + XmlNodeRef groupNode = node->getChild(static_cast(i)); if (groupNode->haveAttr("hidden")) { diff --git a/Code/Editor/Controls/SplineCtrlEx.cpp b/Code/Editor/Controls/SplineCtrlEx.cpp index 5977aff105..9eb0098762 100644 --- a/Code/Editor/Controls/SplineCtrlEx.cpp +++ b/Code/Editor/Controls/SplineCtrlEx.cpp @@ -1583,7 +1583,7 @@ bool AbstractSplineWidget::IsKeySelected(ISplineInterpolator* pSpline, int nKey, int AbstractSplineWidget::GetNumSelected() { int nSelected = 0; - for (int splineIndex = 0, splineCount = m_splines.size(); splineIndex < splineCount; ++splineIndex) + for (size_t splineIndex = 0, splineCount = m_splines.size(); splineIndex < splineCount; ++splineIndex) { if (ISplineInterpolator* pSpline = m_splines[splineIndex].pSpline) { @@ -1818,7 +1818,7 @@ AbstractSplineWidget::EHitCode AbstractSplineWidget::HitTest(const QPoint& point } // For each Spline... - for (int splineIndex = 0, splineCount = m_splines.size(); splineIndex < splineCount; ++splineIndex) + for (size_t splineIndex = 0, splineCount = m_splines.size(); splineIndex < splineCount; ++splineIndex) { ISplineInterpolator* pSpline = m_splines[splineIndex].pSpline; ISplineInterpolator* pDetailSpline = m_splines[splineIndex].pDetailSpline; @@ -1973,7 +1973,7 @@ void AbstractSplineWidget::ScaleAmplitudeKeys(float time, float startValue, floa m_nHitKeyIndex = -1; m_nHitDimension = -1; - for (int splineIndex = 0, splineCount = m_splines.size(); splineIndex < splineCount; ++splineIndex) + for (size_t splineIndex = 0, splineCount = m_splines.size(); splineIndex < splineCount; ++splineIndex) { ISplineInterpolator* pSpline = m_splines[splineIndex].pSpline; @@ -2077,7 +2077,7 @@ void AbstractSplineWidget::TimeScaleKeys(float time, float startTime, float endT float affectedRangeMin = FLT_MAX; float affectedRangeMax = -FLT_MAX; - for (int splineIndex = 0, splineCount = m_splines.size(); splineIndex < splineCount; ++splineIndex) + for (size_t splineIndex = 0, splineCount = m_splines.size(); splineIndex < splineCount; ++splineIndex) { ISplineInterpolator* pSpline = m_splines[splineIndex].pSpline; @@ -2184,7 +2184,7 @@ void AbstractSplineWidget::ValueScaleKeys(float startValue, float endValue) m_nHitKeyIndex = -1; m_nHitDimension = -1; - for (int splineIndex = 0, splineCount = m_splines.size(); splineIndex < splineCount; ++splineIndex) + for (size_t splineIndex = 0, splineCount = m_splines.size(); splineIndex < splineCount; ++splineIndex) { ISplineInterpolator* pSpline = m_splines[splineIndex].pSpline; @@ -2223,7 +2223,7 @@ void AbstractSplineWidget::MoveSelectedKeys(Vec2 offset, bool copyKeys) } // For each spline... - for (int splineIndex = 0, splineCount = m_splines.size(); splineIndex < splineCount; ++splineIndex) + for (size_t splineIndex = 0, splineCount = m_splines.size(); splineIndex < splineCount; ++splineIndex) { ISplineInterpolator* pSpline = m_splines[splineIndex].pSpline; @@ -2298,7 +2298,7 @@ void AbstractSplineWidget::RemoveSelectedKeys() m_pHitDetailSpline = nullptr; m_nHitKeyIndex = -1; - for (int splineIndex = 0, splineCount = m_splines.size(); splineIndex < splineCount; ++splineIndex) + for (size_t splineIndex = 0, splineCount = m_splines.size(); splineIndex < splineCount; ++splineIndex) { ISplineInterpolator* pSpline = m_splines[splineIndex].pSpline; @@ -2338,7 +2338,7 @@ void AbstractSplineWidget::RemoveSelectedKeyTimesImpl() StoreUndo(); SendNotifyEvent(SPLN_BEFORE_CHANGE); - for (int splineIndex = 0, end = m_splines.size(); splineIndex < end; ++splineIndex) + for (size_t splineIndex = 0, end = m_splines.size(); splineIndex < end; ++splineIndex) { std::vector::iterator itTime = m_keyTimes.begin(), endTime = m_keyTimes.end(); for (int keyIndex = 0, endIndex = m_splines[splineIndex].pSpline->GetKeyCount(); keyIndex < endIndex; ) @@ -2376,9 +2376,9 @@ void AbstractSplineWidget::RedrawWindowAroundMarker() { UpdateKeyTimes(); std::vector::iterator itKeyTime = std::lower_bound(m_keyTimes.begin(), m_keyTimes.end(), KeyTime(m_fTimeMarker, 0)); - int keyTimeIndex = (itKeyTime != m_keyTimes.end() ? itKeyTime - m_keyTimes.begin() : m_keyTimes.size()); + size_t keyTimeIndex = (itKeyTime != m_keyTimes.end() ? itKeyTime - m_keyTimes.begin() : m_keyTimes.size()); int redrawRangeStart = (keyTimeIndex >= 2 ? TimeToXOfs(m_keyTimes[keyTimeIndex - 2].time) : m_rcSpline.left()); - int redrawRangeEnd = (keyTimeIndex < int(m_keyTimes.size()) - 2 ? TimeToXOfs(m_keyTimes[keyTimeIndex + 2].time) : m_rcSpline.right() + 1); + int redrawRangeEnd = (keyTimeIndex < m_keyTimes.size() - 2 ? TimeToXOfs(m_keyTimes[keyTimeIndex + 2].time) : m_rcSpline.right() + 1); QRect rc(QPoint(redrawRangeStart, m_rcSpline.top()), QPoint(redrawRangeEnd, m_rcSpline.bottom() + 1) - QPoint(1, 1)); rc = rc.normalized().intersected(m_rcSpline); @@ -2478,7 +2478,7 @@ void AbstractSplineWidget::ClearSelection() { ConditionalStoreUndo(); - for (int splineIndex = 0, splineCount = m_splines.size(); splineIndex < splineCount; ++splineIndex) + for (size_t splineIndex = 0, splineCount = m_splines.size(); splineIndex < splineCount; ++splineIndex) { ISplineInterpolator* pSpline = m_splines[splineIndex].pSpline; @@ -2521,7 +2521,7 @@ void AbstractSplineWidget::StoreUndo() if (CUndo::IsRecording() && !m_pCurrentUndo) { std::vector splines(m_splines.size()); - for (int splineIndex = 0, splineCount = m_splines.size(); splineIndex < splineCount; ++splineIndex) + for (size_t splineIndex = 0, splineCount = m_splines.size(); splineIndex < splineCount; ++splineIndex) { splines[splineIndex] = m_splines[splineIndex].pSpline; } @@ -2564,7 +2564,7 @@ void AbstractSplineWidget::DuplicateSelectedKeys() using KeysToAddContainer = std::vector; KeysToAddContainer keysToInsert; - for (int splineIndex = 0, splineCount = m_splines.size(); splineIndex < splineCount; ++splineIndex) + for (size_t splineIndex = 0, splineCount = m_splines.size(); splineIndex < splineCount; ++splineIndex) { ISplineInterpolator* pSpline = m_splines[splineIndex].pSpline; @@ -2664,7 +2664,7 @@ void AbstractSplineWidget::KeyAll() ////////////////////////////////////////////////////////////////////////// void AbstractSplineWidget::SelectAll() { - for (int splineIndex = 0, splineCount = m_splines.size(); splineIndex < splineCount; ++splineIndex) + for (size_t splineIndex = 0, splineCount = m_splines.size(); splineIndex < splineCount; ++splineIndex) { ISplineInterpolator* pSpline = m_splines[splineIndex].pSpline; @@ -2815,7 +2815,7 @@ void AbstractSplineWidget::SelectRectangle(const QRect& rc, bool bSelect) { std::swap(t0, t1); } - for (int splineIndex = 0, splineCount = m_splines.size(); splineIndex < splineCount; ++splineIndex) + for (size_t splineIndex = 0, splineCount = m_splines.size(); splineIndex < splineCount; ++splineIndex) { ISplineInterpolator* pSpline = m_splines[splineIndex].pSpline; ISplineInterpolator* pDetailSpline = m_splines[splineIndex].pDetailSpline; @@ -3031,7 +3031,7 @@ void AbstractSplineWidget::ModifySelectedKeysFlags(int nRemoveFlags, int nAddFla SendNotifyEvent(SPLN_BEFORE_CHANGE); - for (int splineIndex = 0, splineCount = m_splines.size(); splineIndex < splineCount; ++splineIndex) + for (size_t splineIndex = 0, splineCount = m_splines.size(); splineIndex < splineCount; ++splineIndex) { ISplineInterpolator* pSpline = m_splines[splineIndex].pSpline; @@ -3188,7 +3188,7 @@ void AbstractSplineWidget::GotoNextKey(bool previousKey) { bool boFoundTheSelectedKey(false); - for (int splineIndex = 0, endSpline = m_splines.size(); splineIndex < endSpline; ++splineIndex) + for (size_t splineIndex = 0, endSpline = m_splines.size(); splineIndex < endSpline; ++splineIndex) { ISplineInterpolator* pSpline = m_splines[splineIndex].pSpline; for (int i = 0; i < pSpline->GetKeyCount(); i++) @@ -3230,7 +3230,7 @@ void AbstractSplineWidget::GotoNextKey(bool previousKey) } else { - for (int splineIndex = 0, endSpline = m_splines.size(); splineIndex < endSpline; ++splineIndex) + for (size_t splineIndex = 0, endSpline = m_splines.size(); splineIndex < endSpline; ++splineIndex) { ISplineInterpolator* pSpline = m_splines[splineIndex].pSpline; @@ -3281,7 +3281,7 @@ void AbstractSplineWidget::RemoveAllKeysButThis() { std::vector keys; - for (int splineIndex = 0, endSpline = m_splines.size(); splineIndex < endSpline; ++splineIndex) + for (size_t splineIndex = 0, endSpline = m_splines.size(); splineIndex < endSpline; ++splineIndex) { ISplineInterpolator* pSpline = m_splines[splineIndex].pSpline; diff --git a/Code/Editor/Controls/SplineCtrlEx.h b/Code/Editor/Controls/SplineCtrlEx.h index add4bcb0a9..711cbcf8d4 100644 --- a/Code/Editor/Controls/SplineCtrlEx.h +++ b/Code/Editor/Controls/SplineCtrlEx.h @@ -98,7 +98,7 @@ public: void AddSpline(ISplineInterpolator * pSpline, ISplineInterpolator * pDetailSpline, QColor anColorArray[4]); void RemoveSpline(ISplineInterpolator* pSpline); void RemoveAllSplines(); - int GetSplineCount() const { return m_splines.size(); } + int GetSplineCount() const { return static_cast(m_splines.size()); } ISplineInterpolator* GetSpline(int nIndex) const { return m_splines[nIndex].pSpline; } void SetTimeMarker(float fTime); diff --git a/Code/Editor/Controls/TextEditorCtrl.cpp b/Code/Editor/Controls/TextEditorCtrl.cpp index 5961c9d9a3..c372138d80 100644 --- a/Code/Editor/Controls/TextEditorCtrl.cpp +++ b/Code/Editor/Controls/TextEditorCtrl.cpp @@ -53,7 +53,7 @@ void CTextEditorCtrl::LoadFile(const QString& sFileName) size_t length = file.GetLength(); QByteArray text; - text.resize(length); + text.resize(static_cast(length)); file.ReadRaw(text.data(), length); setPlainText(text); diff --git a/Code/Editor/CryEdit.cpp b/Code/Editor/CryEdit.cpp index 80b5b091c6..cbc4b89d0a 100644 --- a/Code/Editor/CryEdit.cpp +++ b/Code/Editor/CryEdit.cpp @@ -613,7 +613,7 @@ public: } // Get boolean options - const int numOptions = options.size(); + const int numOptions = static_cast(options.size()); for (int i = 0; i < numOptions; ++i) { options[i].second = parser.isSet(options[i].first); @@ -3240,7 +3240,7 @@ bool CCryEditApp::CreateLevel(bool& wasCreateLevelOperationCancelled) { QFileInfo info(fullyQualifiedLevelName); const AZStd::string rawProjectDirectory = Path::GetEditingGameDataFolder(); - const QString projectDirectory = QDir::toNativeSeparators(QString::fromUtf8(rawProjectDirectory.data(), rawProjectDirectory.size())); + const QString projectDirectory = QDir::toNativeSeparators(QString::fromUtf8(rawProjectDirectory.data(), static_cast(rawProjectDirectory.size()))); const QString elidedLevelName = QStringLiteral("%1...%2").arg(levelName.left(10)).arg(levelName.right(10)); const QString elidedLevelFileName = QStringLiteral("%1...%2").arg(info.fileName().left(10)).arg(info.fileName().right(10)); const QString message = QObject::tr( diff --git a/Code/Editor/CryEditDoc.cpp b/Code/Editor/CryEditDoc.cpp index c720299ce8..789aa1bdb9 100644 --- a/Code/Editor/CryEditDoc.cpp +++ b/Code/Editor/CryEditDoc.cpp @@ -1260,7 +1260,7 @@ bool CCryEditDoc::SaveLevel(const QString& filename) if (savedEntities) { AZ_PROFILE_SCOPE(AZ::Debug::ProfileCategory::AzToolsFramework, "CCryEditDoc::SaveLevel Updated PakFile levelEntities.editor_xml"); - pakFile.UpdateFile("LevelEntities.editor_xml", entitySaveBuffer.begin(), entitySaveBuffer.size()); + pakFile.UpdateFile("LevelEntities.editor_xml", entitySaveBuffer.begin(), static_cast(entitySaveBuffer.size())); // Save XML archive to pak file. bool bSaved = xmlAr.SaveToPak(Path::GetPath(tempSaveFile), pakFile); diff --git a/Code/Editor/EditorViewportWidget.cpp b/Code/Editor/EditorViewportWidget.cpp index c7b1976432..50e6e5d67d 100644 --- a/Code/Editor/EditorViewportWidget.cpp +++ b/Code/Editor/EditorViewportWidget.cpp @@ -1477,7 +1477,7 @@ bool EditorViewportWidget::AddCameraMenuItems(QMenu* menu) Camera::CameraBus::BroadcastResult(getCameraResults, &Camera::CameraRequests::GetCameras); QVector additionalCameras; - additionalCameras.reserve(getCameraResults.values.size()); + additionalCameras.reserve(static_cast(getCameraResults.values.size())); for (const AZ::EntityId& entityId : getCameraResults.values) { diff --git a/Code/Editor/ErrorReportTableModel.cpp b/Code/Editor/ErrorReportTableModel.cpp index c0c24bb7ce..2da3110e37 100644 --- a/Code/Editor/ErrorReportTableModel.cpp +++ b/Code/Editor/ErrorReportTableModel.cpp @@ -119,7 +119,7 @@ void CErrorReportTableModel::setErrorReport(CErrorReport* report) int CErrorReportTableModel::rowCount(const QModelIndex& parent) const { - return parent.isValid() ? 0 : m_errorRecords.size(); + return parent.isValid() ? 0 : static_cast(m_errorRecords.size()); } int CErrorReportTableModel::columnCount(const QModelIndex& parent) const diff --git a/Code/Editor/Export/ExportManager.cpp b/Code/Editor/Export/ExportManager.cpp index 5abd3ab5d0..8c90d7322d 100644 --- a/Code/Editor/Export/ExportManager.cpp +++ b/Code/Editor/Export/ExportManager.cpp @@ -302,7 +302,7 @@ void CExportManager::ProcessEntityAnimationTrack( return; } - for (int trackNumber = 0; trackNumber < pEntityTrack->GetChildCount(); ++trackNumber) + for (unsigned int trackNumber = 0; trackNumber < pEntityTrack->GetChildCount(); ++trackNumber) { CTrackViewTrack* pSubTrack = static_cast(pEntityTrack->GetChild(trackNumber)); @@ -964,7 +964,7 @@ bool CExportManager::AddObjectsFromSequence(CTrackViewSequence* pSequence, XmlNo } const uint numKeys = pSequenceTrack->GetKeyCount(); - for (int keyIndex = 0; keyIndex < numKeys; ++keyIndex) + for (uint keyIndex = 0; keyIndex < numKeys; ++keyIndex) { const CTrackViewKeyHandle& keyHandle = pSequenceTrack->GetKey(keyIndex); ISequenceKey sequenceKey; @@ -1043,7 +1043,7 @@ bool CExportManager::AddSelectedRegionObjects() std::vector objects; GetIEditor()->GetObjectManager()->FindObjectsInAABB(box, objects); - int numObjects = objects.size(); + const size_t numObjects = objects.size(); if (numObjects > m_data.m_objects.size()) { m_data.m_objects.reserve(numObjects + 1); // +1 for terrain diff --git a/Code/Editor/Export/ExportManager.h b/Code/Editor/Export/ExportManager.h index 698ad3ad5d..be81591e56 100644 --- a/Code/Editor/Export/ExportManager.h +++ b/Code/Editor/Export/ExportManager.h @@ -36,7 +36,7 @@ namespace Export public: CMesh(); - virtual int GetFaceCount() const { return m_faces.size(); } + virtual int GetFaceCount() const { return static_cast(m_faces.size()); } virtual const Face* GetFaceBuffer() const { return m_faces.size() ? &m_faces[0] : 0; } private: @@ -53,22 +53,22 @@ namespace Export public: CObject(const char* pName); - virtual int GetVertexCount() const { return m_vertices.size(); } - virtual const Vector3D* GetVertexBuffer() const{ return m_vertices.size() ? &m_vertices[0] : 0; } + int GetVertexCount() const override { return static_cast(m_vertices.size()); } + const Vector3D* GetVertexBuffer() const override { return m_vertices.size() ? &m_vertices[0] : nullptr; } - virtual int GetNormalCount() const { return m_normals.size(); } - virtual const Vector3D* GetNormalBuffer() const { return m_normals.size() ? &m_normals[0] : 0; } + int GetNormalCount() const override { return static_cast(m_normals.size()); } + const Vector3D* GetNormalBuffer() const override { return m_normals.size() ? &m_normals[0] : nullptr; } - virtual int GetTexCoordCount() const { return m_texCoords.size(); } - virtual const UV* GetTexCoordBuffer() const { return m_texCoords.size() ? &m_texCoords[0] : 0; } + int GetTexCoordCount() const override { return static_cast(m_texCoords.size()); } + const UV* GetTexCoordBuffer() const override { return m_texCoords.size() ? &m_texCoords[0] : nullptr; } - virtual int GetMeshCount() const { return m_meshes.size(); } - virtual Mesh* GetMesh(int index) const { return m_meshes[index]; } + int GetMeshCount() const override { return static_cast(m_meshes.size()); } + Mesh* GetMesh(int index) const override { return m_meshes[index]; } - virtual size_t MeshHash() const{return m_MeshHash; } + size_t MeshHash() const override{return m_MeshHash; } void SetMaterialName(const char* pName); - virtual int GetEntityAnimationDataCount() const {return m_entityAnimData.size(); } + virtual int GetEntityAnimationDataCount() const {return static_cast(m_entityAnimData.size()); } virtual const EntityAnimData* GetEntityAnimationData(int index) const {return &m_entityAnimData[index]; } virtual void SetEntityAnimationData(EntityAnimData entityData){ m_entityAnimData.push_back(entityData); }; void SetLastPtr(CBaseObject* pObject){m_pLastObject = pObject; }; @@ -92,7 +92,7 @@ namespace Export : public IData { public: - virtual int GetObjectCount() const { return m_objects.size(); } + virtual int GetObjectCount() const { return static_cast(m_objects.size()); } virtual Object* GetObject(int index) const { return m_objects[index]; } virtual Object* AddObject(const char* objectName); void Clear(); diff --git a/Code/Editor/Export/OBJExporter.cpp b/Code/Editor/Export/OBJExporter.cpp index bd2696090e..6ce40f8cd3 100644 --- a/Code/Editor/Export/OBJExporter.cpp +++ b/Code/Editor/Export/OBJExporter.cpp @@ -227,7 +227,7 @@ QString COBJExporter::MakeRelativePath(const char* pMainFileName, const char* pF const char* ch = strrchr(pMainFileName, '\\'); if (ch) { - if (strlen(pFileName) > ch - pMainFileName && !_strnicmp(pMainFileName, pFileName, ch - pMainFileName)) + if (strlen(pFileName) > static_cast(ch - pMainFileName) && !_strnicmp(pMainFileName, pFileName, ch - pMainFileName)) { return QString(pFileName + (ch - pMainFileName) + 1); } @@ -256,7 +256,7 @@ const char* COBJExporter::TrimFloat(float fValue) const ++nCurBuf; sprintf_s(pBuf, bufSize, "%f", fValue); - for (int i = strlen(pBuf) - 1; i > 0; --i) + for (int i = static_cast(strlen(pBuf)) - 1; i > 0; --i) { if (pBuf[i] == '0') { diff --git a/Code/Editor/Export/OCMExporter.cpp b/Code/Editor/Export/OCMExporter.cpp index 653dc28dd3..ba5c343d0d 100644 --- a/Code/Editor/Export/OCMExporter.cpp +++ b/Code/Editor/Export/OCMExporter.cpp @@ -215,7 +215,7 @@ bool COCMExporter::ExportToFile(const char* filename, const Export::IData* pExpo for (size_t a = 0; a < MeshCount; a++) { SOCMeshInfo MeshInfo; - MeshInfo.m_MeshHash = pExportData->GetObject(a)->MeshHash(); + MeshInfo.m_MeshHash = pExportData->GetObject(static_cast(a))->MeshHash(); const tdMeshOffset::iterator it = std::find(MeshOffsets.begin(), MeshOffsets.end(), MeshInfo); if (it != MeshOffsets.end()) { @@ -223,15 +223,15 @@ bool COCMExporter::ExportToFile(const char* filename, const Export::IData* pExpo } else { - MeshInfo.m_Offset = Offset; - Offset += SaveMesh(Writer, pExportData->GetObject(a), MeshInfo.m_OBBMat); + MeshInfo.m_Offset = static_cast(Offset); + Offset += SaveMesh(Writer, pExportData->GetObject(static_cast(a)), MeshInfo.m_OBBMat); } MeshOffsets.push_back(MeshInfo); } - OffsetInstances = Offset; + OffsetInstances = static_cast(Offset); for (size_t a = 0; a < InstCount; a++) { - SaveInstance(Writer, pExportData->GetObject(a), MeshOffsets[a]); + SaveInstance(Writer, pExportData->GetObject(static_cast(a)), MeshOffsets[a]); } Writer.Seek(4); Writer.Write(static_cast(MeshOffsets.size())); @@ -263,7 +263,7 @@ const char* COCMExporter::TrimFloat(float fValue) const ++nCurBuf; sprintf_s(pBuf, bufSize, "%f", fValue); - for (int i = strlen(pBuf) - 1; i > 0; --i) + for (int i = static_cast(strlen(pBuf)) - 1; i > 0; --i) { if (pBuf[i] == '0') { diff --git a/Code/Editor/GameExporter.cpp b/Code/Editor/GameExporter.cpp index 415103e10d..1fc980fdac 100644 --- a/Code/Editor/GameExporter.cpp +++ b/Code/Editor/GameExporter.cpp @@ -252,11 +252,11 @@ void CGameExporter::ExportOcclusionMesh(const char* pszGamePath) { CMemoryBlock Temp; const size_t Size = FileIn.size(); - Temp.Allocate(Size); + Temp.Allocate(static_cast(Size)); FileIn.read(reinterpret_cast(Temp.GetBuffer()), Size); FileIn.close(); CCryMemFile FileOut; - FileOut.Write(Temp.GetBuffer(), Size); + FileOut.Write(Temp.GetBuffer(), static_cast(Size)); m_levelPak.m_pakFile.UpdateFile(levelDataFile.toUtf8().data(), FileOut); } } @@ -281,13 +281,13 @@ void CGameExporter::ExportLevelData(const QString& path, bool /*bExportMission*/ QString levelDataFile = path + "LevelData.xml"; XmlString xmlData = root->getXML(); CCryMemFile file; - file.Write(xmlData.c_str(), xmlData.length()); + file.Write(xmlData.c_str(), static_cast(xmlData.length())); m_levelPak.m_pakFile.UpdateFile(levelDataFile.toUtf8().data(), file); QString levelDataActionFile = path + "LevelDataAction.xml"; XmlString xmlDataAction = rootAction->getXML(); CCryMemFile fileAction; - fileAction.Write(xmlDataAction.c_str(), xmlDataAction.length()); + fileAction.Write(xmlDataAction.c_str(), static_cast(xmlDataAction.length())); m_levelPak.m_pakFile.UpdateFile(levelDataActionFile.toUtf8().data(), fileAction); AZStd::vector entitySaveBuffer; @@ -298,7 +298,7 @@ void CGameExporter::ExportLevelData(const QString& path, bool /*bExportMission*/ { QString entitiesFile; entitiesFile = QStringLiteral("%1%2.entities_xml").arg(path, "Mission0"); - m_levelPak.m_pakFile.UpdateFile(entitiesFile.toUtf8().data(), entitySaveBuffer.begin(), entitySaveBuffer.size()); + m_levelPak.m_pakFile.UpdateFile(entitiesFile.toUtf8().data(), entitySaveBuffer.begin(), static_cast(entitySaveBuffer.size())); } } @@ -329,7 +329,7 @@ void CGameExporter::ExportLevelInfo(const QString& path) XmlString xmlData = root->getXML(); CCryMemFile file; - file.Write(xmlData.c_str(), xmlData.length()); + file.Write(xmlData.c_str(), static_cast(xmlData.length())); m_levelPak.m_pakFile.UpdateFile(filename.toUtf8().data(), file); } @@ -342,7 +342,7 @@ void CGameExporter::ExportLevelResourceList(const QString& path) CCryMemFile memFile; for (const char* filename = pResList->GetFirst(); filename; filename = pResList->GetNext()) { - memFile.Write(filename, strlen(filename)); + memFile.Write(filename, static_cast(strlen(filename))); memFile.Write("\n", 1); } diff --git a/Code/Editor/GameResourcesExporter.cpp b/Code/Editor/GameResourcesExporter.cpp index dd16b2eca1..b47f8c63a6 100644 --- a/Code/Editor/GameResourcesExporter.cpp +++ b/Code/Editor/GameResourcesExporter.cpp @@ -97,7 +97,7 @@ void CGameResourcesExporter::Save(const QString& outputDirectory) { // Save this file in target folder. QString trgFilename = Path::Make(outputDirectory, srcFilename); - int fsize = file.GetLength(); + int fsize = static_cast(file.GetLength()); if (fsize > data.GetSize()) { data.Allocate(fsize + 16); @@ -123,23 +123,6 @@ void CGameResourcesExporter::Save(const QString& outputDirectory) m_files.clear(); } -#if defined(WIN64) || defined(APPLE) || defined(AZ_PLATFORM_LINUX) -template -void Append(Container1& a, const Container2& b) -{ - a.reserve (a.size() + b.size()); - for (auto it = b.begin(); it != b.end(); ++it) - { - a.insert(a.end(), *it); - } -} -#else -template -void Append(Container1& a, const Container2& b) -{ - a.insert (a.end(), b.begin(), b.end()); -} -#endif ////////////////////////////////////////////////////////////////////////// // // Go through all editor objects and gathers files from thier properties. @@ -150,5 +133,5 @@ void CGameResourcesExporter::GetFilesFromObjects() CUsedResources rs; GetIEditor()->GetObjectManager()->GatherUsedResources(rs); - Append(m_files, rs.files); + AZStd::copy(rs.files.begin(), rs.files.end(), AZStd::back_inserter(m_files)); } diff --git a/Code/Editor/Geometry/TriMesh.cpp b/Code/Editor/Geometry/TriMesh.cpp index 8e85de3904..2106265aca 100644 --- a/Code/Editor/Geometry/TriMesh.cpp +++ b/Code/Editor/Geometry/TriMesh.cpp @@ -420,7 +420,7 @@ void CTriMesh::UpdateIndexedMesh(IIndexedMesh* pIndexedMesh) const pIndexedMesh->SetBBox(bb); - pIndexedMesh->SetSubSetCount(usedMaterialIds.size()); + pIndexedMesh->SetSubSetCount(static_cast(usedMaterialIds.size())); for (int i = 0; i < usedMaterialIds.size(); i++) { pIndexedMesh->SetSubsetMaterialId(i, usedMaterialIds[i]); diff --git a/Code/Editor/LevelFileDialog.cpp b/Code/Editor/LevelFileDialog.cpp index cefa1330eb..c0c2b96c59 100644 --- a/Code/Editor/LevelFileDialog.cpp +++ b/Code/Editor/LevelFileDialog.cpp @@ -477,7 +477,7 @@ bool CLevelFileDialog::ValidateLevelPath(const QString& levelPath) const QString currentPath = (Path::GetEditingGameDataFolder() + "/" + kLevelsFolder).c_str(); for (size_t i = 0; i < splittedPath.size() - 1; ++i) { - currentPath += "/" + splittedPath[i]; + currentPath += "/" + splittedPath[static_cast(i)]; if (CFileUtil::FileExists(currentPath) || CheckLevelFolder(currentPath)) { diff --git a/Code/Editor/MainWindow.cpp b/Code/Editor/MainWindow.cpp index bb246c2337..8c466c47c2 100644 --- a/Code/Editor/MainWindow.cpp +++ b/Code/Editor/MainWindow.cpp @@ -1674,7 +1674,7 @@ void MainWindow::OnUpdateConnectionStatus() tooltip += m_connectionListener->LastAssetProcessorTask().c_str(); tooltip += "\n"; AZStd::set failedJobs = m_connectionListener->FailedJobsList(); - int failureCount = failedJobs.size(); + int failureCount = static_cast(failedJobs.size()); if (failureCount) { tooltip += "\n Failed Jobs\n"; diff --git a/Code/Editor/Objects/BaseObject.cpp b/Code/Editor/Objects/BaseObject.cpp index f40363ba98..e68b17b99f 100644 --- a/Code/Editor/Objects/BaseObject.cpp +++ b/Code/Editor/Objects/BaseObject.cpp @@ -840,8 +840,8 @@ void CBaseObject::DrawDefault(DisplayContext& dc, const QColor& labelColor) { dc.DrawLine(GetParentAttachPointWorldTM().GetTranslation(), wp, IsFrozen() ? kLinkColorGray : kLinkColorParent, IsFrozen() ? kLinkColorGray : kLinkColorChild); } - int nChildCount = GetChildCount(); - for (int i = 0; i < nChildCount; ++i) + size_t nChildCount = GetChildCount(); + for (size_t i = 0; i < nChildCount; ++i) { const CBaseObject* pChild = GetChild(i); dc.DrawLine(pChild->GetParentAttachPointWorldTM().GetTranslation(), pChild->GetWorldPos(), pChild->IsFrozen() ? kLinkColorGray : kLinkColorParent, pChild->IsFrozen() ? kLinkColorGray : kLinkColorChild); @@ -1375,7 +1375,7 @@ bool CBaseObject::IsHiddenBySpec() const return false; } - return (m_nMinSpec != 0 && gSettings.editorConfigSpec != 0 && m_nMinSpec > gSettings.editorConfigSpec); + return (m_nMinSpec != 0 && gSettings.editorConfigSpec != 0 && m_nMinSpec > static_cast(gSettings.editorConfigSpec)); } ////////////////////////////////////////////////////////////////////////// @@ -1893,7 +1893,7 @@ bool CBaseObject::HitTestRectBounds(HitContext& hc, const AABB& box) std::vector convexHullForRegion1; ConvexHull2D(convexHullForRegion1, pointsForRegion1); - nEdgeList1Count = convexHullForRegion1.size(); + nEdgeList1Count = static_cast(convexHullForRegion1.size()); if (nEdgeList1Count < 3 || nEdgeList1Count > kMaxSizeOfEdgeList1) { return true; @@ -2062,7 +2062,7 @@ void CBaseObject::GetAllChildren(TBaseObjects& outAllChildren, CBaseObject* pObj { const CBaseObject* pBaseObj = pObj ? pObj : this; - for (int i = 0, iChildCount(pBaseObj->GetChildCount()); i < iChildCount; ++i) + for (size_t i = 0, iChildCount(pBaseObj->GetChildCount()); i < iChildCount; ++i) { CBaseObject* pChild = pBaseObj->GetChild(i); if (pChild == nullptr) @@ -2078,7 +2078,7 @@ void CBaseObject::GetAllChildren(DynArray< _smart_ptr >& outAllChil { const CBaseObject* pBaseObj = pObj ? pObj : this; - for (int i = 0, iChildCount(pBaseObj->GetChildCount()); i < iChildCount; ++i) + for (size_t i = 0, iChildCount(pBaseObj->GetChildCount()); i < iChildCount; ++i) { CBaseObject* pChild = pBaseObj->GetChild(i); if (pChild == nullptr) @@ -2094,7 +2094,7 @@ void CBaseObject::GetAllChildren(CSelectionGroup& outAllChildren, CBaseObject* p { const CBaseObject* pBaseObj = pObj ? pObj : this; - for (int i = 0, iChildCount(pBaseObj->GetChildCount()); i < iChildCount; ++i) + for (size_t i = 0, iChildCount(pBaseObj->GetChildCount()); i < iChildCount; ++i) { CBaseObject* pChild = pBaseObj->GetChild(i); if (pChild == nullptr) @@ -2114,7 +2114,7 @@ void CBaseObject::CloneChildren(CBaseObject* pFromObject) return; } - for (int i = 0, nChildCount(pFromObject->GetChildCount()); i < nChildCount; ++i) + for (size_t i = 0, nChildCount(pFromObject->GetChildCount()); i < nChildCount; ++i) { CBaseObject* pFromChildObject = pFromObject->GetChild(i); @@ -2729,7 +2729,7 @@ void CBaseObject::SetMinSpec(uint32 nSpec, bool bSetChildren) // Set min spec for all childs. if (bSetChildren) { - for (int i = m_childs.size() - 1; i >= 0; --i) + for (size_t i = m_childs.size() - 1; i >= 0; --i) { m_childs[i]->SetMinSpec(nSpec, true); } diff --git a/Code/Editor/Objects/EntityObject.cpp b/Code/Editor/Objects/EntityObject.cpp index 77fab543f9..02f89c268f 100644 --- a/Code/Editor/Objects/EntityObject.cpp +++ b/Code/Editor/Objects/EntityObject.cpp @@ -63,7 +63,7 @@ protected: void Undo([[maybe_unused]] bool bUndo) override { - for (int i = 0, iLinkSize(m_Links.size()); i < iLinkSize; ++i) + for (int i = 0, iLinkSize = static_cast(m_Links.size()); i < iLinkSize; ++i) { SLink& link = m_Links[i]; CBaseObject* pObj = GetIEditor()->GetObjectManager()->FindObject(link.entityID); @@ -1217,7 +1217,7 @@ XmlNodeRef CEntityObject::Export([[maybe_unused]] const QString& levelPath, XmlN if (!m_links.empty()) { XmlNodeRef linksNode = objNode->newChild("EntityLinks"); - for (int i = 0, num = m_links.size(); i < num; i++) + for (size_t i = 0, num = m_links.size(); i < num; i++) { if (m_links[i].target) { @@ -1368,8 +1368,8 @@ void CEntityObject::PostClone(CBaseObject* pFromObject, CObjectCloneContext& ctx // Clone event targets. if (!pFromEntity->m_eventTargets.empty()) { - int numTargets = pFromEntity->m_eventTargets.size(); - for (int i = 0; i < numTargets; i++) + size_t numTargets = pFromEntity->m_eventTargets.size(); + for (size_t i = 0; i < numTargets; i++) { CEntityEventTarget& et = pFromEntity->m_eventTargets[i]; CBaseObject* pClonedTarget = ctx.FindClone(et.target); @@ -1386,7 +1386,7 @@ void CEntityObject::PostClone(CBaseObject* pFromObject, CObjectCloneContext& ctx // Clone links. if (!pFromEntity->m_links.empty()) { - int numTargets = pFromEntity->m_links.size(); + int numTargets = static_cast(pFromEntity->m_links.size()); for (int i = 0; i < numTargets; i++) { CEntityLink& et = pFromEntity->m_links[i]; @@ -1437,7 +1437,7 @@ void CEntityObject::RemoveAllEntityLinks() { while (!m_links.empty()) { - RemoveEntityLink(m_links.size() - 1); + RemoveEntityLink(static_cast(m_links.size() - 1)); } m_links.clear(); SetModified(false); @@ -1448,7 +1448,7 @@ void CEntityObject::ReleaseEventTargets() { while (!m_eventTargets.empty()) { - RemoveEventTarget(m_eventTargets.size() - 1, false); + RemoveEventTarget(static_cast(m_eventTargets.size() - 1), false); } m_eventTargets.clear(); SetModified(false); @@ -1518,7 +1518,7 @@ void CEntityObject::SaveLink(XmlNodeRef xmlNode) } XmlNodeRef linksNode = xmlNode->newChild("EntityLinks"); - for (int i = 0, num = m_links.size(); i < num; i++) + for (size_t i = 0, num = m_links.size(); i < num; i++) { XmlNodeRef linkNode = linksNode->newChild("Link"); linkNode->setAttr("TargetId", m_links[i].targetId); @@ -1534,7 +1534,7 @@ void CEntityObject::OnObjectEvent(CBaseObject* target, int event) if (event == CBaseObject::ON_DELETE) { // Find this target in events list and remove. - int numTargets = m_eventTargets.size(); + int numTargets = static_cast(m_eventTargets.size()); for (int i = 0; i < numTargets; i++) { if (m_eventTargets[i].target == target) @@ -1547,7 +1547,7 @@ void CEntityObject::OnObjectEvent(CBaseObject* target, int event) } else if (event == CBaseObject::ON_PREDELETE) { - int numTargets = m_links.size(); + int numTargets = static_cast(m_links.size()); for (int i = 0; i < numTargets; i++) { if (m_links[i].target == target) @@ -1589,7 +1589,7 @@ int CEntityObject::AddEventTarget(CBaseObject* target, const QString& event, con m_eventTargets.push_back(et); SetModified(false); - return m_eventTargets.size() - 1; + return static_cast(m_eventTargets.size() - 1); } ////////////////////////////////////////////////////////////////////////// @@ -1659,13 +1659,13 @@ int CEntityObject::AddEntityLink(const QString& name, GUID targetEntityId) SetModified(false); - return m_links.size() - 1; + return static_cast(m_links.size() - 1); } ////////////////////////////////////////////////////////////////////////// bool CEntityObject::EntityLinkExists(const QString& name, GUID targetEntityId) { - for (int i = 0, num = m_links.size(); i < num; ++i) + for (size_t i = 0, num = m_links.size(); i < num; ++i) { if (m_links[i].targetId == targetEntityId && name.compare(m_links[i].name, Qt::CaseInsensitive) == 0) { diff --git a/Code/Editor/Objects/ObjectLoader.cpp b/Code/Editor/Objects/ObjectLoader.cpp index 2583eb6230..9596265bb9 100644 --- a/Code/Editor/Objects/ObjectLoader.cpp +++ b/Code/Editor/Objects/ObjectLoader.cpp @@ -126,7 +126,7 @@ void CObjectArchive::ResolveObjects() ////////////////////////////////////////////////////////////////////////// // Serialize All Objects from XML. ////////////////////////////////////////////////////////////////////////// - int numObj = m_loadedObjects.size(); + int numObj = static_cast(m_loadedObjects.size()); for (i = 0; i < numObj; i++) { if (m_bProgressBarEnabled) @@ -143,7 +143,7 @@ void CObjectArchive::ResolveObjects() m_pCurrentErrorReport->SetCurrentValidatorObject(nullptr); // Objects can be added to the list here (from Groups). - numObj = m_loadedObjects.size(); + numObj = static_cast(m_loadedObjects.size()); } m_pCurrentErrorReport->SetCurrentValidatorObject(nullptr); ////////////////////////////////////////////////////////////////////////// @@ -221,7 +221,7 @@ void CObjectArchive::ResolveObjects() ////////////////////////////////////////////////////////////////////////// // Serialize All Objects from XML. ////////////////////////////////////////////////////////////////////////// - int numObj = m_loadedObjects.size(); + int numObj = static_cast(m_loadedObjects.size()); for (i = 0; i < numObj; i++) { if (m_bProgressBarEnabled) @@ -246,7 +246,7 @@ void CObjectArchive::ResolveObjects() // Call PostLoad on all these objects. ////////////////////////////////////////////////////////////////////////// { - int numObj = m_loadedObjects.size(); + int numObj = static_cast(m_loadedObjects.size()); for (i = 0; i < numObj; i++) { SLoadedObjectInfo& obj = m_loadedObjects[i]; diff --git a/Code/Editor/Objects/ObjectManager.cpp b/Code/Editor/Objects/ObjectManager.cpp index fbdd56f080..3e2a1c0d2c 100644 --- a/Code/Editor/Objects/ObjectManager.cpp +++ b/Code/Editor/Objects/ObjectManager.cpp @@ -746,7 +746,7 @@ void CObjectManager::ChangeObjectName(CBaseObject* obj, const QString& newName) ////////////////////////////////////////////////////////////////////////// int CObjectManager::GetObjectCount() const { - return m_objects.size(); + return static_cast(m_objects.size()); } ////////////////////////////////////////////////////////////////////////// @@ -765,7 +765,7 @@ void CObjectManager::GetObjects(DynArray& objects) const CBaseObjectsArray objectArray; GetObjects(objectArray); objects.clear(); - for (int i = 0, iCount(objectArray.size()); i < iCount; ++i) + for (size_t i = 0, iCount(objectArray.size()); i < iCount; ++i) { objects.push_back(objectArray[i]); } @@ -1336,11 +1336,11 @@ void CObjectManager::FindDisplayableObjects(DisplayContext& dc, [[maybe_unused]] bbox.max.zero(); pDispayedViewObjects->ClearObjects(); - pDispayedViewObjects->Reserve(m_visibleObjects.size()); + pDispayedViewObjects->Reserve(static_cast(m_visibleObjects.size())); if (dc.flags & DISPLAY_2D) { - int numVis = m_visibleObjects.size(); + int numVis = static_cast(m_visibleObjects.size()); for (int i = 0; i < numVis; i++) { CBaseObject* obj = m_visibleObjects[i]; @@ -1374,7 +1374,7 @@ void CObjectManager::FindDisplayableObjects(DisplayContext& dc, [[maybe_unused]] pSelection->GetObject(0)->CBaseObject::DrawDimensions(dc, &mergedAABB); } - int numVis = m_visibleObjects.size(); + int numVis = static_cast(m_visibleObjects.size()); for (int i = 0; i < numVis; i++) { CBaseObject* obj = m_visibleObjects[i]; @@ -2016,7 +2016,7 @@ void CObjectManager::GetClassCategories(QStringList& categories) } } categories.clear(); - categories.reserve(cset.size()); + categories.reserve(static_cast(cset.size())); for (std::set::iterator cit = cset.begin(); cit != cset.end(); ++cit) { categories.push_back(*cit); @@ -2629,7 +2629,7 @@ void CObjectManager::EnteredComponentMode(const AZStd::vector& /*compo const size_t gizmoCount = static_cast(gizmoManager->GetGizmoCount()); for (size_t i = 0; i < gizmoCount; ++i) { - gizmoManager->RemoveGizmo(gizmoManager->GetGizmoByIndex(i)); + gizmoManager->RemoveGizmo(gizmoManager->GetGizmoByIndex(static_cast(i))); } } diff --git a/Code/Editor/Objects/SelectionGroup.cpp b/Code/Editor/Objects/SelectionGroup.cpp index 027c88172e..57a86262aa 100644 --- a/Code/Editor/Objects/SelectionGroup.cpp +++ b/Code/Editor/Objects/SelectionGroup.cpp @@ -109,7 +109,7 @@ bool CSelectionGroup::SameObjectType() ////////////////////////////////////////////////////////////////////////// int CSelectionGroup::GetCount() const { - return m_objects.size(); + return static_cast(m_objects.size()); } ////////////////////////////////////////////////////////////////////////// @@ -632,7 +632,7 @@ void CSelectionGroup::IndicateSnappingVertex(DisplayContext& dc) const void CSelectionGroup::FinishChanges() { Objects selectedObjects(m_objects); - int iObjectSize(selectedObjects.size()); + int iObjectSize = static_cast(selectedObjects.size()); for (int i = 0; i < iObjectSize; ++i) { CBaseObject* pObject = selectedObjects[i]; diff --git a/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/AssetCatalogModel.cpp b/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/AssetCatalogModel.cpp index 0d661349a9..d0091f968e 100644 --- a/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/AssetCatalogModel.cpp +++ b/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/AssetCatalogModel.cpp @@ -472,7 +472,7 @@ void AssetCatalogModel::LoadDatabase() { m_fileCacheCurrentIndex = 0; Q_EMIT UpdateProgress(0); - Q_EMIT SetTotalProgress(m_fileCache.size()); + Q_EMIT SetTotalProgress(static_cast(m_fileCache.size())); }; EBUS_EVENT(AZ::Data::AssetCatalogRequestBus, EnumerateAssets, startCB, enumerateCB, endCB); diff --git a/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/ComponentPalette/ComponentDataModel.cpp b/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/ComponentPalette/ComponentDataModel.cpp index f7f2b721b7..cd0fba350f 100644 --- a/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/ComponentPalette/ComponentDataModel.cpp +++ b/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/ComponentPalette/ComponentDataModel.cpp @@ -262,7 +262,7 @@ QModelIndex ComponentDataModel::parent([[maybe_unused]] const QModelIndex &child int ComponentDataModel::rowCount([[maybe_unused]] const QModelIndex &parent /*= QModelIndex()*/) const { - return m_componentList.size(); + return static_cast(m_componentList.size()); } int ComponentDataModel::columnCount([[maybe_unused]] const QModelIndex &parent /*= QModelIndex()*/) const diff --git a/Code/Editor/PreferencesStdPages.cpp b/Code/Editor/PreferencesStdPages.cpp index a4b3ee8ba4..b593541a07 100644 --- a/Code/Editor/PreferencesStdPages.cpp +++ b/Code/Editor/PreferencesStdPages.cpp @@ -89,7 +89,7 @@ REFGUID CStdPreferencesClassDesc::ClassID() ////////////////////////////////////////////////////////////////////////// int CStdPreferencesClassDesc::GetPagesCount() { - return m_pageCreators.size(); + return static_cast(m_pageCreators.size()); } IPreferencesPage* CStdPreferencesClassDesc::CreateEditorPreferencesPage(int index) diff --git a/Code/Editor/QtViewPaneManager.cpp b/Code/Editor/QtViewPaneManager.cpp index f4f18fde83..d8111aa09c 100644 --- a/Code/Editor/QtViewPaneManager.cpp +++ b/Code/Editor/QtViewPaneManager.cpp @@ -184,7 +184,7 @@ bool QtViewPane::CloseInstance(QDockWidget* dockWidget, CloseModes closeModes) const int numTopLevel = topLevelWidgets.size(); for (size_t i = 0; i < numTopLevel; ++i) { - QWidget* widget = topLevelWidgets[i]; + QWidget* widget = topLevelWidgets[static_cast(i)]; if (widget->isModal() && widget->isVisible()) { widget->activateWindow(); diff --git a/Code/Editor/Settings.cpp b/Code/Editor/Settings.cpp index 09b0d0f4f4..259f71b69b 100644 --- a/Code/Editor/Settings.cpp +++ b/Code/Editor/Settings.cpp @@ -1061,7 +1061,7 @@ void SEditorSettings::ConvertPath(const AZStd::string_view sourcePath, AZStd::st // The reason for the difference is to have this API be consistent with the path syntax in Open 3D Engine Python APIs. // Find the last pipe separator ("|") in the path - int lastSeparator = sourcePath.find_last_of("|"); + size_t lastSeparator = sourcePath.find_last_of("|"); // Everything before the last separator is the category (since only the category is hierarchical) category = sourcePath.substr(0, lastSeparator); diff --git a/Code/Editor/ToolBox.cpp b/Code/Editor/ToolBox.cpp index d784bc2083..1f08bd74fc 100644 --- a/Code/Editor/ToolBox.cpp +++ b/Code/Editor/ToolBox.cpp @@ -237,7 +237,7 @@ CToolBoxMacro* CToolBoxManager::NewMacro(const QString& title, bool bToolbox, in { if (bToolbox) { - const int macroCount = m_macros.size(); + const int macroCount = static_cast(m_macros.size()); if (macroCount > ID_TOOL_LAST - ID_TOOL_FIRST + 1) { return nullptr; @@ -261,7 +261,7 @@ CToolBoxMacro* CToolBoxManager::NewMacro(const QString& title, bool bToolbox, in } else { - const int shelveMacroCount = m_shelveMacros.size(); + const int shelveMacroCount = static_cast(m_shelveMacros.size()); if (shelveMacroCount > ID_TOOL_SHELVE_LAST - ID_TOOL_SHELVE_FIRST + 1) { return nullptr; diff --git a/Code/Editor/ToolbarManager.cpp b/Code/Editor/ToolbarManager.cpp index d44e794b6a..1831fe6a55 100644 --- a/Code/Editor/ToolbarManager.cpp +++ b/Code/Editor/ToolbarManager.cpp @@ -503,7 +503,7 @@ void ToolbarManager::InitializeStandardToolbars() { auto macroToolbars = GetIEditor()->GetToolBoxManager()->GetToolbars(); - m_standardToolbars.reserve(5 + macroToolbars.size()); + m_standardToolbars.reserve(static_cast(5 + macroToolbars.size())); m_standardToolbars.push_back(GetEditModeToolbar()); m_standardToolbars.push_back(GetObjectToolbar()); m_standardToolbars.push_back(GetPlayConsoleToolbar()); diff --git a/Code/Editor/ToolsConfigPage.cpp b/Code/Editor/ToolsConfigPage.cpp index 965c862554..1871dc763f 100644 --- a/Code/Editor/ToolsConfigPage.cpp +++ b/Code/Editor/ToolsConfigPage.cpp @@ -840,7 +840,7 @@ void CToolsConfigPage::FillScriptCmds() { EditorPythonConsoleInterface::GlobalFunctionCollection globalFunctionCollection; editorPythonConsoleInterface->GetGlobalFunctionList(globalFunctionCollection); - commands.reserve(globalFunctionCollection.size()); + commands.reserve(static_cast(globalFunctionCollection.size())); for (const EditorPythonConsoleInterface::GlobalFunction& globalFunction : globalFunctionCollection) { const QString fullCmd = QString("%1.%2()").arg(globalFunction.m_moduleName.data()).arg(globalFunction.m_functionName.data()); diff --git a/Code/Editor/TrackView/CommentKeyUIControls.cpp b/Code/Editor/TrackView/CommentKeyUIControls.cpp index c7c5f83cbf..6b52efd8f1 100644 --- a/Code/Editor/TrackView/CommentKeyUIControls.cpp +++ b/Code/Editor/TrackView/CommentKeyUIControls.cpp @@ -122,7 +122,7 @@ void CCommentKeyUIControls::OnUIChange(IVariable* pVar, CTrackViewKeyBundle& sel for (size_t keyIndex = 0, num = selectedKeys.GetKeyCount(); keyIndex < num; keyIndex++) { - CTrackViewKeyHandle keyHandle = selectedKeys.GetKey(keyIndex); + CTrackViewKeyHandle keyHandle = selectedKeys.GetKey(static_cast(keyIndex)); CAnimParamType paramType = keyHandle.GetTrack()->GetParameterType(); if (paramType == AnimParamType::CommentText) diff --git a/Code/Editor/TrackView/ScreenFaderKeyUIControls.cpp b/Code/Editor/TrackView/ScreenFaderKeyUIControls.cpp index a62ab17cbf..d8b3a2bdf7 100644 --- a/Code/Editor/TrackView/ScreenFaderKeyUIControls.cpp +++ b/Code/Editor/TrackView/ScreenFaderKeyUIControls.cpp @@ -128,7 +128,7 @@ void CScreenFaderKeyUIControls::OnUIChange(IVariable* pVar, CTrackViewKeyBundle& for (size_t keyIndex = 0, num = selectedKeys.GetKeyCount(); keyIndex < num; ++keyIndex) { - CTrackViewKeyHandle selectedKey = selectedKeys.GetKey(keyIndex); + CTrackViewKeyHandle selectedKey = selectedKeys.GetKey(static_cast(keyIndex)); CAnimParamType paramType = selectedKey.GetTrack()->GetParameterType(); if (paramType == AnimParamType::ScreenFader) diff --git a/Code/Editor/TrackView/SequenceBatchRenderDialog.cpp b/Code/Editor/TrackView/SequenceBatchRenderDialog.cpp index 66c4f63d35..aea655e9d3 100644 --- a/Code/Editor/TrackView/SequenceBatchRenderDialog.cpp +++ b/Code/Editor/TrackView/SequenceBatchRenderDialog.cpp @@ -357,7 +357,7 @@ void CSequenceBatchRenderDialog::OnRenderItemSelChange() QString cvarsText; for (size_t i = 0; i < item.cvars.size(); ++i) { - cvarsText += item.cvars[i]; + cvarsText += item.cvars[static_cast(i)]; cvarsText += "\r\n"; } m_ui->m_cvarsEdit->setPlainText(cvarsText); @@ -894,7 +894,7 @@ void CSequenceBatchRenderDialog::CaptureItemStart() // Set up the custom config cvars for this item. for (size_t i = 0; i < renderItem.cvars.size(); ++i) { - GetIEditor()->GetSystem()->GetIConsole()->ExecuteString(renderItem.cvars[i].toUtf8().data()); + GetIEditor()->GetSystem()->GetIConsole()->ExecuteString(renderItem.cvars[static_cast(i)].toUtf8().data()); } // Set specific capture options for this item. @@ -1519,7 +1519,7 @@ void CSequenceBatchRenderDialog::OnSaveBatch() // cvars for (size_t k = 0; k < item.cvars.size(); ++k) { - itemNode->newChild("cvar")->setContent(item.cvars[k].toUtf8().data()); + itemNode->newChild("cvar")->setContent(item.cvars[static_cast(k)].toUtf8().data()); } } diff --git a/Code/Editor/TrackView/SequenceKeyUIControls.cpp b/Code/Editor/TrackView/SequenceKeyUIControls.cpp index c3bc39d65d..4199563e10 100644 --- a/Code/Editor/TrackView/SequenceKeyUIControls.cpp +++ b/Code/Editor/TrackView/SequenceKeyUIControls.cpp @@ -84,7 +84,7 @@ bool CSequenceKeyUIControls::OnKeySelectionChange(CTrackViewKeyBundle& selectedK mv_sequence->AddEnumItem(QObject::tr(""), CTrackViewDialog::GetEntityIdAsString(AZ::EntityId(AZ::EntityId::InvalidEntityId))); const CTrackViewSequenceManager* pSequenceManager = GetIEditor()->GetSequenceManager(); - for (int i = 0; i < pSequenceManager->GetCount(); ++i) + for (unsigned int i = 0; i < pSequenceManager->GetCount(); ++i) { CTrackViewSequence* pCurrentSequence = pSequenceManager->GetSequenceByIndex(i); bool bNotMe = pCurrentSequence != pSequence; diff --git a/Code/Editor/TrackView/TVEventsDialog.cpp b/Code/Editor/TrackView/TVEventsDialog.cpp index c8221b38cd..86b4c1f6bc 100644 --- a/Code/Editor/TrackView/TVEventsDialog.cpp +++ b/Code/Editor/TrackView/TVEventsDialog.cpp @@ -363,7 +363,7 @@ int TVEventsModel::GetNumberOfUsageAndFirstTimeUsed(const char* eventName, float { CTrackViewTrack* pTrack = tracks.GetTrack(currentTrack); - for (int currentKey = 0; currentKey < pTrack->GetKeyCount(); ++currentKey) + for (unsigned int currentKey = 0; currentKey < pTrack->GetKeyCount(); ++currentKey) { CTrackViewKeyHandle keyHandle = pTrack->GetKey(currentKey); diff --git a/Code/Editor/TrackView/TrackViewAnimNode.cpp b/Code/Editor/TrackView/TrackViewAnimNode.cpp index 9edac32da0..dd6fb8f936 100644 --- a/Code/Editor/TrackView/TrackViewAnimNode.cpp +++ b/Code/Editor/TrackView/TrackViewAnimNode.cpp @@ -452,7 +452,7 @@ CTrackViewAnimNode* CTrackViewAnimNode::CreateSubNode( { // Check for a duplicates CTrackViewAnimNodeBundle azEntityNodesFound = director2->GetAnimNodesByType(AnimNodeType::AzEntity); - for (int x = 0; x < azEntityNodesFound.GetCount(); x++) + for (unsigned int x = 0; x < azEntityNodesFound.GetCount(); x++) { if (azEntityNodesFound.GetNode(x)->GetAzEntityId() == owner) { diff --git a/Code/Editor/TrackView/TrackViewCurveEditor.cpp b/Code/Editor/TrackView/TrackViewCurveEditor.cpp index 83204f76a6..a757387563 100644 --- a/Code/Editor/TrackView/TrackViewCurveEditor.cpp +++ b/Code/Editor/TrackView/TrackViewCurveEditor.cpp @@ -145,7 +145,7 @@ void CTrackViewCurveEditor::UpdateSplines() std::set newTracks; if (selectedTracks.AreAllOfSameType()) { - for (int i = 0; i < selectedTracks.GetCount(); i++) + for (unsigned int i = 0; i < selectedTracks.GetCount(); i++) { CTrackViewTrack* pTrack = selectedTracks.GetTrack(i); diff --git a/Code/Editor/TrackView/TrackViewDialog.cpp b/Code/Editor/TrackView/TrackViewDialog.cpp index 309d776b81..bdec68e928 100644 --- a/Code/Editor/TrackView/TrackViewDialog.cpp +++ b/Code/Editor/TrackView/TrackViewDialog.cpp @@ -782,7 +782,7 @@ void CTrackViewDialog::UpdateActions() } bool allSelectedTracksUseMute = true; - for (int i = 0; i < selectedTrackCount; i++) + for (unsigned int i = 0; i < selectedTrackCount; i++) { CTrackViewTrack* pTrack = selectedTracks.GetTrack(i); if (pTrack && !pTrack->UsesMute()) @@ -1121,7 +1121,7 @@ void CTrackViewDialog::ReloadSequencesComboBox() CTrackViewSequenceManager* pSequenceManager = GetIEditor()->GetSequenceManager(); const unsigned int numSequences = pSequenceManager->GetCount(); - for (int k = 0; k < numSequences; ++k) + for (unsigned int k = 0; k < numSequences; ++k) { CTrackViewSequence* sequence = pSequenceManager->GetSequenceByIndex(k); QString entityIdString = GetEntityIdAsString(sequence->GetSequenceComponentEntityId()); @@ -1799,7 +1799,7 @@ void CTrackViewDialog::SaveMiscSettings() const settings.setValue(s_kFrameSnappingFPSEntry, fps); settings.setValue(s_kTickDisplayModeEntry, static_cast(m_wndDopeSheet->GetTickDisplayMode())); settings.setValue(s_kDefaultTracksEntry, QByteArray(reinterpret_cast(m_defaultTracksForEntityNode.data()), - m_defaultTracksForEntityNode.size() * sizeof(AnimParamType))); + static_cast(m_defaultTracksForEntityNode.size() * sizeof(AnimParamType)))); } ////////////////////////////////////////////////////////////////////////// diff --git a/Code/Editor/TrackView/TrackViewDopeSheetBase.cpp b/Code/Editor/TrackView/TrackViewDopeSheetBase.cpp index c784142b3c..0ff7cc6ca9 100644 --- a/Code/Editor/TrackView/TrackViewDopeSheetBase.cpp +++ b/Code/Editor/TrackView/TrackViewDopeSheetBase.cpp @@ -1028,12 +1028,12 @@ void CTrackViewDopeSheetBase::SelectAllKeysWithinTimeFrame(const QRect& rc, cons CTrackViewTrackBundle tracks = sequence->GetAllTracks(); CTrackViewSequenceNotificationContext context(sequence); - for (int i = 0; i < tracks.GetCount(); ++i) + for (unsigned int i = 0; i < tracks.GetCount(); ++i) { CTrackViewTrack* pTrack = tracks.GetTrack(i); // Check which keys we intersect. - for (int j = 0; j < pTrack->GetKeyCount(); j++) + for (unsigned int j = 0; j < pTrack->GetKeyCount(); j++) { CTrackViewKeyHandle keyHandle = pTrack->GetKey(j); const float time = keyHandle.GetTime(); @@ -1429,7 +1429,7 @@ bool CTrackViewDopeSheetBase::IsOkToAddKeyHere(const CTrackViewTrack* pTrack, fl { const float timeEpsilon = 0.05f; - for (int i = 0; i < pTrack->GetKeyCount(); ++i) + for (unsigned int i = 0; i < pTrack->GetKeyCount(); ++i) { const CTrackViewKeyConstHandle& keyHandle = pTrack->GetKey(i); @@ -1764,7 +1764,7 @@ float CTrackViewDopeSheetBase::MagnetSnap(float newTime, const CTrackViewAnimNod newTime = keys.GetKey(0).GetTime(); // But if there is an in-range key in a sibling track, use it instead. // Here a 'sibling' means a track that belongs to a same node. - for (int i = 0; i < keys.GetKeyCount(); ++i) + for (unsigned int i = 0; i < keys.GetKeyCount(); ++i) { CTrackViewKeyHandle keyHandle = keys.GetKey(i); if (keyHandle.GetTrack()->GetAnimNode() == pNode) diff --git a/Code/Editor/TrackView/TrackViewNode.cpp b/Code/Editor/TrackView/TrackViewNode.cpp index 882a23f6b0..d8507d9b0a 100644 --- a/Code/Editor/TrackView/TrackViewNode.cpp +++ b/Code/Editor/TrackView/TrackViewNode.cpp @@ -86,7 +86,7 @@ void CTrackViewKeyHandle::SetTime(float time, bool notifyListeners) if (!m_pTrack->IsSortMarkerKey(m_keyIndex)) { CTrackViewKeyBundle allKeys = m_pTrack->GetAllKeys(); - for (int x = 0; x < allKeys.GetKeyCount(); x++) + for (unsigned int x = 0; x < allKeys.GetKeyCount(); x++) { unsigned int curIndex = allKeys.GetKey(x).GetIndex(); if (m_pTrack->IsSortMarkerKey(curIndex)) diff --git a/Code/Editor/TrackView/TrackViewNodes.cpp b/Code/Editor/TrackView/TrackViewNodes.cpp index 550d36af83..4d6249288e 100644 --- a/Code/Editor/TrackView/TrackViewNodes.cpp +++ b/Code/Editor/TrackView/TrackViewNodes.cpp @@ -2306,7 +2306,7 @@ bool CTrackViewNodesCtrl::FillAddTrackMenu(STrackMenuTreeNode& menuAddTrack, con &Maestro::EditorSequenceComponentRequestBus::Events::GetAllAnimatablePropertiesForComponent, animatableProperties, azEntityId, animNode->GetComponentId()); - paramCount = animatableProperties.size(); + paramCount = static_cast(animatableProperties.size()); } } else diff --git a/Code/Editor/TrackView/TrackViewPythonFuncs.cpp b/Code/Editor/TrackView/TrackViewPythonFuncs.cpp index acabff6827..d50060269b 100644 --- a/Code/Editor/TrackView/TrackViewPythonFuncs.cpp +++ b/Code/Editor/TrackView/TrackViewPythonFuncs.cpp @@ -113,7 +113,7 @@ namespace AZStd::string PyTrackViewGetSequenceName(unsigned int index) { - if (index < PyTrackViewGetNumSequences()) + if (static_cast(index) < PyTrackViewGetNumSequences()) { const CTrackViewSequenceManager* pSequenceManager = GetIEditor()->GetSequenceManager(); return pSequenceManager->GetSequenceByIndex(index)->GetName(); @@ -378,7 +378,7 @@ namespace } CTrackViewAnimNodeBundle foundNodes = pParentDirector->GetAllAnimNodes(); - if (index < 0 || index >= foundNodes.GetCount()) + if (index < 0 || index >= static_cast(foundNodes.GetCount())) { throw std::runtime_error("Invalid node index"); } diff --git a/Code/Editor/TrackView/TrackViewSequence.cpp b/Code/Editor/TrackView/TrackViewSequence.cpp index 3647c554dc..28279be0e3 100644 --- a/Code/Editor/TrackView/TrackViewSequence.cpp +++ b/Code/Editor/TrackView/TrackViewSequence.cpp @@ -455,7 +455,7 @@ void CTrackViewSequence::OnNodeChanged(CTrackViewNode* node, ITrackViewSequenceL // Make sure to deselect any keys CTrackViewKeyBundle keys = node->GetAllKeys(); - for (int key = 0; key < keys.GetKeyCount(); key++) + for (unsigned int key = 0; key < keys.GetKeyCount(); key++) { CTrackViewKeyHandle keyHandle = keys.GetKey(key); if (keyHandle.IsSelected()) @@ -1249,7 +1249,7 @@ void CTrackViewSequence::DeselectAllKeys() CTrackViewSequenceNotificationContext context(this); CTrackViewKeyBundle selectedKeys = GetSelectedKeys(); - for (int i = 0; i < selectedKeys.GetKeyCount(); ++i) + for (unsigned int i = 0; i < selectedKeys.GetKeyCount(); ++i) { CTrackViewKeyHandle keyHandle = selectedKeys.GetKey(i); keyHandle.Select(false); diff --git a/Code/Editor/TrackView/TrackViewSequenceManager.cpp b/Code/Editor/TrackView/TrackViewSequenceManager.cpp index 277483691a..780c8f04ce 100644 --- a/Code/Editor/TrackView/TrackViewSequenceManager.cpp +++ b/Code/Editor/TrackView/TrackViewSequenceManager.cpp @@ -227,7 +227,7 @@ void CTrackViewSequenceManager::AddTrackViewSequence(CTrackViewSequence* sequenc //////////////////////////////////////////////////////////////////////////// void CTrackViewSequenceManager::DeleteSequence(CTrackViewSequence* sequence) { - const int numSequences = m_sequences.size(); + const int numSequences = static_cast(m_sequences.size()); for (int sequenceIndex = 0; sequenceIndex < numSequences; ++sequenceIndex) { if (m_sequences[sequenceIndex].get() == sequence) @@ -246,7 +246,7 @@ void CTrackViewSequenceManager::DeleteSequence(CTrackViewSequence* sequence) { AZ::ComponentTypeList requiredComponents; AzToolsFramework::EditorEntityContextRequestBus::BroadcastResult(requiredComponents, &AzToolsFramework::EditorEntityContextRequestBus::Events::GetRequiredComponentTypes); - const int numComponentToDeleteEntity = requiredComponents.size() + 1; + const int numComponentToDeleteEntity = static_cast(requiredComponents.size() + 1); AZ::Entity::ComponentArrayType entityComponents = entity->GetComponents(); if (entityComponents.size() == numComponentToDeleteEntity) @@ -413,9 +413,9 @@ void CTrackViewSequenceManager::OnDataBaseItemEvent([[maybe_unused]] IDataBaseIt { if (event != EDataBaseItemEvent::EDB_ITEM_EVENT_ADD) { - const uint numSequences = m_sequences.size(); + const size_t numSequences = m_sequences.size(); - for (uint i = 0; i < numSequences; ++i) + for (size_t i = 0; i < numSequences; ++i) { m_sequences[i]->UpdateDynamicParams(); } diff --git a/Code/Editor/TrackView/TrackViewSplineCtrl.cpp b/Code/Editor/TrackView/TrackViewSplineCtrl.cpp index c21403d1f5..4911297985 100644 --- a/Code/Editor/TrackView/TrackViewSplineCtrl.cpp +++ b/Code/Editor/TrackView/TrackViewSplineCtrl.cpp @@ -706,7 +706,7 @@ void CTrackViewSplineCtrl::mouseMoveEvent(QMouseEvent* event) QString tipText; bool boFoundTheSelectedKey(false); - for (int splineIndex = 0, endSpline = m_splines.size(); splineIndex < endSpline; ++splineIndex) + for (size_t splineIndex = 0, endSpline = m_splines.size(); splineIndex < endSpline; ++splineIndex) { ISplineInterpolator* pSpline = m_splines[splineIndex].pSpline; CTrackViewTrack* pTrack = m_tracks[splineIndex]; @@ -796,7 +796,7 @@ void CTrackViewSplineCtrl::AdjustTCB(float d_tension, float d_continuity, float SendNotifyEvent(SPLN_BEFORE_CHANGE); - for (int splineIndex = 0, splineCount = m_splines.size(); splineIndex < splineCount; ++splineIndex) + for (size_t splineIndex = 0, splineCount = m_splines.size(); splineIndex < splineCount; ++splineIndex) { ISplineInterpolator* pSpline = m_splines[splineIndex].pSpline; CTrackViewTrack* pTrack = m_tracks[splineIndex]; @@ -892,7 +892,7 @@ void CTrackViewSplineCtrl::OnUserCommand(UINT cmd) bool CTrackViewSplineCtrl::IsUnifiedKeyCurrentlySelected() const { - for (int splineIndex = 0, splineCount = m_splines.size(); splineIndex < splineCount; ++splineIndex) + for (size_t splineIndex = 0, splineCount = m_splines.size(); splineIndex < splineCount; ++splineIndex) { ISplineInterpolator* pSpline = m_splines[splineIndex].pSpline; diff --git a/Code/Editor/TrackView/TrackViewUndo.cpp b/Code/Editor/TrackView/TrackViewUndo.cpp index d0b85762a2..c9cdc62bc3 100644 --- a/Code/Editor/TrackView/TrackViewUndo.cpp +++ b/Code/Editor/TrackView/TrackViewUndo.cpp @@ -70,7 +70,7 @@ CTrackViewTrack* CUndoComponentEntityTrackObject::FindTrack(CTrackViewSequence* CTrackViewTrack* track = nullptr; CTrackViewTrackBundle allTracks = sequence->GetAllTracks(); - for (int trackIndex = 0; trackIndex < allTracks.GetCount(); trackIndex++) + for (unsigned int trackIndex = 0; trackIndex < allTracks.GetCount(); trackIndex++) { CTrackViewTrack* curTrack = allTracks.GetTrack(trackIndex); if (curTrack->GetAnimNode() && curTrack->GetAnimNode()->GetComponentId() == m_trackComponentId) diff --git a/Code/Editor/TrackViewNewSequenceDialog.cpp b/Code/Editor/TrackViewNewSequenceDialog.cpp index 0efc7a932e..287f69df47 100644 --- a/Code/Editor/TrackViewNewSequenceDialog.cpp +++ b/Code/Editor/TrackViewNewSequenceDialog.cpp @@ -78,7 +78,7 @@ void CTVNewSequenceDialog::OnOK() return; } - for (int k = 0; k < GetIEditor()->GetSequenceManager()->GetCount(); ++k) + for (unsigned int k = 0; k < GetIEditor()->GetSequenceManager()->GetCount(); ++k) { CTrackViewSequence* pSequence = GetIEditor()->GetSequenceManager()->GetSequenceByIndex(k); QString fullname = pSequence->GetName(); diff --git a/Code/Editor/Undo/Undo.cpp b/Code/Editor/Undo/Undo.cpp index 6af141b9e7..b49c6ea567 100644 --- a/Code/Editor/Undo/Undo.cpp +++ b/Code/Editor/Undo/Undo.cpp @@ -49,7 +49,7 @@ public: } void Undo(bool bUndo) override { - for (int i = m_undoSteps.size() - 1; i >= 0; i--) + for (size_t i = m_undoSteps.size() - 1; i >= 0; i--) { m_undoSteps[i]->Undo(bUndo); } @@ -624,13 +624,13 @@ void CUndoManager::SuperCancel() ////////////////////////////////////////////////////////////////////////// int CUndoManager::GetUndoStackLen() const { - return m_undoStack.size(); + return static_cast(m_undoStack.size()); } ////////////////////////////////////////////////////////////////////////// int CUndoManager::GetRedoStackLen() const { - return m_redoStack.size(); + return static_cast(m_redoStack.size()); } ////////////////////////////////////////////////////////////////////////// @@ -817,7 +817,7 @@ void CUndoManager::SignalNumUndoRedoToListeners() { for (IUndoManagerListener* listener : m_listeners) { - listener->SignalNumUndoRedo(m_undoStack.size(), m_redoStack.size()); + listener->SignalNumUndoRedo(static_cast(m_undoStack.size()), static_cast(m_redoStack.size())); } } diff --git a/Code/Editor/UndoDropDown.cpp b/Code/Editor/UndoDropDown.cpp index fbe18d5d52..6bf807ebf4 100644 --- a/Code/Editor/UndoDropDown.cpp +++ b/Code/Editor/UndoDropDown.cpp @@ -68,7 +68,7 @@ public: return 0; } - return m_stackNames.size(); + return static_cast(m_stackNames.size()); } QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override @@ -101,13 +101,13 @@ public: if (fresh.size() < m_stackNames.size()) { - beginRemoveRows(createIndex(-1, -1), fresh.size(), m_stackNames.size() - 1); + beginRemoveRows(createIndex(-1, -1), static_cast(fresh.size()), static_cast(m_stackNames.size() - 1)); m_stackNames = fresh; endRemoveRows(); } else { - beginInsertRows(createIndex(-1, -1), m_stackNames.size(), fresh.size() - 1); + beginInsertRows(createIndex(-1, -1), static_cast(m_stackNames.size()), static_cast(fresh.size() - 1)); m_stackNames = fresh; endInsertRows(); } diff --git a/Code/Editor/Util/FileUtil.cpp b/Code/Editor/Util/FileUtil.cpp index f26ffa60ec..e39adcca82 100644 --- a/Code/Editor/Util/FileUtil.cpp +++ b/Code/Editor/Util/FileUtil.cpp @@ -1228,7 +1228,7 @@ bool CFileUtil::CreatePath(const QString& strPath) nTotalPathQueueElements = cstrDirectoryQueue.size(); for (nCurrentPathQueue = 0; nCurrentPathQueue < nTotalPathQueueElements; ++nCurrentPathQueue) { - strCurrentDirectoryPath += cstrDirectoryQueue[nCurrentPathQueue]; + strCurrentDirectoryPath += cstrDirectoryQueue[static_cast(nCurrentPathQueue)]; strCurrentDirectoryPath += "\\"; // The value which will go out of this loop is the result of the attempt to create the // last directory, only. @@ -1368,8 +1368,8 @@ IFileUtil::ECopyTreeResult CFileUtil::CopyTree(const QString& strSourceDirectory return eCopyResult; } - QString sourceName = sourceDir.absoluteFilePath(cFiles[nCurrent]); - QString targetName = targetDir.absoluteFilePath(cFiles[nCurrent]); + QString sourceName = sourceDir.absoluteFilePath(cFiles[static_cast(nCurrent)]); + QString targetName = targetDir.absoluteFilePath(cFiles[static_cast(nCurrent)]); if (boConfirmOverwrite) { @@ -1387,7 +1387,7 @@ IFileUtil::ECopyTreeResult CFileUtil::CopyTree(const QString& strSourceDirectory const int ret = QMessageBox::question(AzToolsFramework::GetActiveWindow(), QObject::tr("Confirm file overwrite?"), QObject::tr("There is already a file named \"%1\" in the target folder. Do you want to move this file anyway replacing the old one?") - .arg(cFiles[nCurrent]), + .arg(cFiles[static_cast(nCurrent)]), QMessageBox::YesToAll | QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); switch (ret) { @@ -1448,8 +1448,8 @@ IFileUtil::ECopyTreeResult CFileUtil::CopyTree(const QString& strSourceDirectory bool bnLastDirectoryWasCreated(false); - QString sourceName = sourceDir.absoluteFilePath(cDirectories[nCurrent]); - QString targetName = targetDir.absoluteFilePath(cDirectories[nCurrent]); + QString sourceName = sourceDir.absoluteFilePath(cDirectories[static_cast(nCurrent)]); + QString targetName = targetDir.absoluteFilePath(cDirectories[static_cast(nCurrent)]); bnLastDirectoryWasCreated = QDir().mkpath(targetName); @@ -1473,7 +1473,7 @@ IFileUtil::ECopyTreeResult CFileUtil::CopyTree(const QString& strSourceDirectory const int ret = QMessageBox::question(AzToolsFramework::GetActiveWindow(), QObject::tr("Confirm directory overwrite?"), QObject::tr("There is already a folder named \"%1\" in the target folder. Do you want to move this folder anyway?") - .arg(cDirectories[nCurrent]), + .arg(cDirectories[static_cast(nCurrent)]), QMessageBox::YesToAll | QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); switch (ret) { @@ -1742,8 +1742,8 @@ IFileUtil::ECopyTreeResult CFileUtil::MoveTree(const QString& strSourceDirecto } bool bnLastFileWasCopied(false); - QString sourceName(sourceDir.absoluteFilePath(cFiles[nCurrent])); - QString targetName(targetDir.absoluteFilePath(cFiles[nCurrent])); + QString sourceName(sourceDir.absoluteFilePath(cFiles[static_cast(nCurrent)])); + QString targetName(targetDir.absoluteFilePath(cFiles[static_cast(nCurrent)])); if (boConfirmOverwrite) { @@ -1761,7 +1761,7 @@ IFileUtil::ECopyTreeResult CFileUtil::MoveTree(const QString& strSourceDirecto const int ret = QMessageBox::question(AzToolsFramework::GetActiveWindow(), QObject::tr("Confirm file overwrite?"), QObject::tr("There is already a file named \"%1\" in the target folder. Do you want to move this file anyway replacing the old one?") - .arg(cFiles[nCurrent]), + .arg(cFiles[static_cast(nCurrent)]), QMessageBox::YesToAll | QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); switch (ret) { @@ -1822,8 +1822,8 @@ IFileUtil::ECopyTreeResult CFileUtil::MoveTree(const QString& strSourceDirecto return eCopyResult; } - QString sourceName(sourceDir.absoluteFilePath(cDirectories[nCurrent])); - QString targetName(targetDir.absoluteFilePath(cDirectories[nCurrent])); + QString sourceName(sourceDir.absoluteFilePath(cDirectories[static_cast(nCurrent)])); + QString targetName(targetDir.absoluteFilePath(cDirectories[static_cast(nCurrent)])); bnLastDirectoryWasCreated = QDir().mkdir(targetName); @@ -1847,7 +1847,7 @@ IFileUtil::ECopyTreeResult CFileUtil::MoveTree(const QString& strSourceDirecto const int ret = QMessageBox::question(AzToolsFramework::GetActiveWindow(), QObject::tr("Confirm directory overwrite?"), QObject::tr("There is already a folder named \"%1\" in the target folder. Do you want to move this folder anyway?") - .arg(cDirectories[nCurrent]), + .arg(cDirectories[static_cast(nCurrent)]), QMessageBox::YesToAll | QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); switch (ret) { diff --git a/Code/Editor/Util/ImageASC.cpp b/Code/Editor/Util/ImageASC.cpp index 11dad7b696..8a63ebdc6a 100644 --- a/Code/Editor/Util/ImageASC.cpp +++ b/Code/Editor/Util/ImageASC.cpp @@ -55,9 +55,9 @@ bool CImageASC::Save(const QString& fileName, const CFloatImage& image) fprintf(file, fileHeader.c_str()); // Then print all the pixels. - for (int y = 0; y < height; y++) + for (uint32 y = 0; y < height; y++) { - for (int x = 0; x < width; x++) + for (uint32 x = 0; x < width; x++) { fprintf(file, "%.7f ", pixels[x + y * width]); } diff --git a/Code/Editor/Util/ImageGif.cpp b/Code/Editor/Util/ImageGif.cpp index 2c07fc9acb..383319a666 100644 --- a/Code/Editor/Util/ImageGif.cpp +++ b/Code/Editor/Util/ImageGif.cpp @@ -185,7 +185,7 @@ bool CImageGif::Load(const QString& fileName, CImageEx& outImage) CLogFile::FormatLine("File not found %s", fileName.toUtf8().data()); return false; } - long filesize = file.GetLength(); + long filesize = static_cast(file.GetLength()); data.resize(filesize); uint8* ptr = &data[0]; diff --git a/Code/Editor/Util/ImageTIF.cpp b/Code/Editor/Util/ImageTIF.cpp index 654b24f857..6544b93c6a 100644 --- a/Code/Editor/Util/ImageTIF.cpp +++ b/Code/Editor/Util/ImageTIF.cpp @@ -119,7 +119,7 @@ bool CImageTIF::Load(const QString& fileName, CImageEx& outImage) std::vector data; - memImage.size = file.GetLength(); + memImage.size = static_cast(file.GetLength()); data.resize(memImage.size); memImage.buffer = &data[0]; @@ -210,7 +210,7 @@ bool CImageTIF::Load(const QString& fileName, CFloatImage& outImage) std::vector data; - memImage.size = file.GetLength(); + memImage.size = static_cast(file.GetLength()); data.resize(memImage.size); memImage.buffer = &data[0]; @@ -460,7 +460,7 @@ const char* CImageTIF::GetPreset(const QString& fileName) MemImage memImage; - memImage.size = file.GetLength(); + memImage.size = static_cast(file.GetLength()); data.resize(memImage.size); memImage.buffer = &data[0]; diff --git a/Code/Editor/Util/ImageUtil.cpp b/Code/Editor/Util/ImageUtil.cpp index 5753e0a138..00e33162cf 100644 --- a/Code/Editor/Util/ImageUtil.cpp +++ b/Code/Editor/Util/ImageUtil.cpp @@ -106,9 +106,9 @@ bool CImageUtil::SavePGM(const QString& fileName, const CImageEx& image) fprintf(file, fileHeader.c_str()); // Then print all the pixels. - for (int32 y = 0; y < height; y++) + for (uint32 y = 0; y < height; y++) { - for (int32 x = 0; x < width; x++) + for (uint32 x = 0; x < width; x++) { fprintf(file, "%d ", pixels[x + (y * width)]); } @@ -478,7 +478,7 @@ unsigned char CImageUtil::GetBilinearFilteredAt(const int iniX256, const int ini DWORD x = (DWORD)(iniX256) >> 8; DWORD y = (DWORD)(iniY256) >> 8; - if (x >= image.GetWidth() - 1 || y >= image.GetHeight() - 1) + if (x >= static_cast(image.GetWidth() - 1) || y >= static_cast(image.GetHeight() - 1)) { return image.ValueAt(x, y); // border is not filtered, 255 to get in range 0..1 } diff --git a/Code/Editor/Util/KDTree.cpp b/Code/Editor/Util/KDTree.cpp index 4547149e9b..182b9b8eb1 100644 --- a/Code/Editor/Util/KDTree.cpp +++ b/Code/Editor/Util/KDTree.cpp @@ -190,7 +190,7 @@ bool SearchForBestSplitPos(CKDTree::ESplitAxis axis, const std::vector(indices.size()); for (int i = 0; i < nSizeOfIndices; ++i) { @@ -329,7 +329,7 @@ bool CKDTree::Build(IStatObj* pStatObj) entireBoundBox.Reset(); std::vector indices; - for (int i = 0, iStatObjSize(m_StatObjectList.size()); i < iStatObjSize; ++i) + for (int i = 0, iStatObjSize = static_cast(m_StatObjectList.size()); i < iStatObjSize; ++i) { IIndexedMesh* pMesh = m_StatObjectList[i].pStatObj->GetIndexedMesh(true); if (pMesh == nullptr) diff --git a/Code/Editor/Util/NamedData.cpp b/Code/Editor/Util/NamedData.cpp index 240d71f58d..67e69a0392 100644 --- a/Code/Editor/Util/NamedData.cpp +++ b/Code/Editor/Util/NamedData.cpp @@ -158,7 +158,7 @@ bool CNamedData::Serialize(CArchive& ar) { if (ar.IsStoring()) { - int iSize = m_blocks.size(); + int iSize = static_cast(m_blocks.size()); ar << iSize; for (TBlocks::iterator it = m_blocks.begin(); it != m_blocks.end(); it++) @@ -286,7 +286,7 @@ bool CNamedData::Load(const QString& levelPath, [[maybe_unused]] CPakFile& pakFi CCryFile cfile; if (cfile.Open(Path::Make(levelPath, filename).toUtf8().data(), "rb")) { - int fileSize = cfile.GetLength(); + int fileSize = static_cast(cfile.GetLength()); if (fileSize > 0) { QString key = Path::GetFileName(filename); @@ -307,7 +307,7 @@ bool CNamedData::Load(const QString& levelPath, [[maybe_unused]] CPakFile& pakFi CCryFile cfile; if (cfile.Open(Path::Make(levelPath, filename).toUtf8().data(), "rb")) { - int fileSize = cfile.GetLength(); + int fileSize = static_cast(cfile.GetLength()); if (fileSize > 0) { // Read uncompressed data size. diff --git a/Code/Editor/Util/Variable.cpp b/Code/Editor/Util/Variable.cpp index 97c2a1e8af..3d7c35ac1c 100644 --- a/Code/Editor/Util/Variable.cpp +++ b/Code/Editor/Util/Variable.cpp @@ -511,7 +511,7 @@ CVarGlobalEnumList::CVarGlobalEnumList(const QString& enumName) //! Get the name of specified value in enumeration. QString CVarGlobalEnumList::GetItemName(uint index) { - if (!m_pEnum || index >= m_pEnum->strings.size()) + if (!m_pEnum || index >= static_cast(m_pEnum->strings.size())) { return QString(); } diff --git a/Code/Editor/Util/XmlArchive.cpp b/Code/Editor/Util/XmlArchive.cpp index ca399632d4..e6bc93fdf4 100644 --- a/Code/Editor/Util/XmlArchive.cpp +++ b/Code/Editor/Util/XmlArchive.cpp @@ -120,7 +120,7 @@ bool CXmlArchive::SaveToPak([[maybe_unused]] const QString& levelPath, CPakFile& // Save xml file. QString xmlFilename = "Level.editor_xml"; - pakFile.UpdateFile(xmlFilename.toUtf8().data(), (void*)pXmlStrData->GetString(), pXmlStrData->GetStringLength()); + pakFile.UpdateFile(xmlFilename.toUtf8().data(), (void*)pXmlStrData->GetString(), static_cast(pXmlStrData->GetStringLength())); if (pakFile.GetArchive()) { diff --git a/Code/Editor/WipFeatureManager.cpp b/Code/Editor/WipFeatureManager.cpp index f6fbc7ac93..4fb9ed1d93 100644 --- a/Code/Editor/WipFeatureManager.cpp +++ b/Code/Editor/WipFeatureManager.cpp @@ -189,7 +189,7 @@ bool CWipFeatureManager::Load(const char* pFilename, bool bClearExisting) for (size_t i = 0, iCount = root->getChildCount(); i < iCount; ++i) { SWipFeatureInfo wf; - XmlNodeRef node = root->getChild(i); + XmlNodeRef node = root->getChild(static_cast(i)); XmlString str; node->getAttr("id", wf.m_id); diff --git a/Code/Editor/WipFeaturesDlg.cpp b/Code/Editor/WipFeaturesDlg.cpp index 0d0a179539..bc4372d7fb 100644 --- a/Code/Editor/WipFeaturesDlg.cpp +++ b/Code/Editor/WipFeaturesDlg.cpp @@ -35,7 +35,7 @@ public: int rowCount(const QModelIndex& parent = QModelIndex()) const override { - return parent.isValid() ? 0 : CWipFeatureManager::Instance()->GetFeatures().size(); + return parent.isValid() ? 0 : static_cast(CWipFeatureManager::Instance()->GetFeatures().size()); } int columnCount(const QModelIndex& parent = QModelIndex()) const override From 1f5dddcca6f6b01f991d8b76c4e09ea23ccf8bbf Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 13 Aug 2021 17:13:14 -0700 Subject: [PATCH 462/803] Code compiles Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Editor/Controls/SplineCtrlEx.cpp | 2 +- Code/Editor/CryEdit.cpp | 2 +- Code/Editor/EditorViewportWidget.cpp | 2 +- Code/Editor/Objects/EntityObject.cpp | 4 ++-- Code/Editor/TrackView/TrackViewAnimNode.cpp | 4 ++-- Code/Editor/TrackView/TrackViewDialog.cpp | 4 ++-- .../TrackView/TrackViewDopeSheetBase.cpp | 22 +++++++++---------- Code/Editor/TrackView/TrackViewNodes.cpp | 6 ++--- Code/Editor/TrackView/TrackViewSequence.cpp | 6 ++--- Code/Editor/Util/MemoryBlock.cpp | 2 +- .../Animation/UiAnimViewDopeSheetBase.cpp | 18 +++++++-------- 11 files changed, 36 insertions(+), 36 deletions(-) diff --git a/Code/Editor/Controls/SplineCtrlEx.cpp b/Code/Editor/Controls/SplineCtrlEx.cpp index 9eb0098762..5bba14f0d6 100644 --- a/Code/Editor/Controls/SplineCtrlEx.cpp +++ b/Code/Editor/Controls/SplineCtrlEx.cpp @@ -1856,7 +1856,7 @@ AbstractSplineWidget::EHitCode AbstractSplineWidget::HitTest(const QPoint& point // Check tangent handles first. { QPoint incomingHandlePt, outgoingHandlePt, pt; - if (GetTangentHandlePts(incomingHandlePt, pt, outgoingHandlePt, splineIndex, i, nCurrentDimension)) + if (GetTangentHandlePts(incomingHandlePt, pt, outgoingHandlePt, static_cast(splineIndex), static_cast(i), nCurrentDimension)) { // For the incoming handle if (abs(incomingHandlePt.x() - point.x()) < 4 && abs(incomingHandlePt.y() - point.y()) < 4) diff --git a/Code/Editor/CryEdit.cpp b/Code/Editor/CryEdit.cpp index cbc4b89d0a..280613815e 100644 --- a/Code/Editor/CryEdit.cpp +++ b/Code/Editor/CryEdit.cpp @@ -3922,7 +3922,7 @@ void CCryEditApp::OpenLUAEditor(const char* files) void CCryEditApp::PrintAlways(const AZStd::string& output) { - m_stdoutRedirection.WriteBypassingRedirect(output.c_str(), output.size()); + m_stdoutRedirection.WriteBypassingRedirect(output.c_str(), static_cast(output.size())); } QString CCryEditApp::GetRootEnginePath() const diff --git a/Code/Editor/EditorViewportWidget.cpp b/Code/Editor/EditorViewportWidget.cpp index 50e6e5d67d..701386951a 100644 --- a/Code/Editor/EditorViewportWidget.cpp +++ b/Code/Editor/EditorViewportWidget.cpp @@ -1899,7 +1899,7 @@ void EditorViewportWidget::RenderSelectedRegion() // Draw volume dc.DepthWriteOff(); dc.CullOff(); - dc.pRenderAuxGeom->DrawTriangles(&verts[0], verts.size(), &inds[0], numInds, &colors[0]); + dc.pRenderAuxGeom->DrawTriangles(&verts[0], static_cast(verts.size()), &inds[0], numInds, &colors[0]); dc.CullOn(); dc.DepthWriteOn(); } diff --git a/Code/Editor/Objects/EntityObject.cpp b/Code/Editor/Objects/EntityObject.cpp index 02f89c268f..afbf370ca8 100644 --- a/Code/Editor/Objects/EntityObject.cpp +++ b/Code/Editor/Objects/EntityObject.cpp @@ -1540,7 +1540,7 @@ void CEntityObject::OnObjectEvent(CBaseObject* target, int event) if (m_eventTargets[i].target == target) { RemoveEventTarget(i); - numTargets = m_eventTargets.size(); + numTargets = static_cast(m_eventTargets.size()); i--; } } @@ -1553,7 +1553,7 @@ void CEntityObject::OnObjectEvent(CBaseObject* target, int event) if (m_links[i].target == target) { RemoveEntityLink(i); - numTargets = m_eventTargets.size(); + numTargets = static_cast(m_eventTargets.size()); i--; } } diff --git a/Code/Editor/TrackView/TrackViewAnimNode.cpp b/Code/Editor/TrackView/TrackViewAnimNode.cpp index dd6fb8f936..4b599859e9 100644 --- a/Code/Editor/TrackView/TrackViewAnimNode.cpp +++ b/Code/Editor/TrackView/TrackViewAnimNode.cpp @@ -1477,7 +1477,7 @@ bool CTrackViewAnimNode::PasteNodesFromClipboard(QWidget* context) AZStd::map copiedIdToNodeMap; const unsigned int numNodes = animNodesRoot->getChildCount(); - for (int i = 0; i < numNodes; ++i) + for (unsigned int i = 0; i < numNodes; ++i) { XmlNodeRef xmlNode = animNodesRoot->getChild(i); @@ -2123,7 +2123,7 @@ bool CTrackViewAnimNode::ContainsComponentWithId(AZ::ComponentId componentId) co if (GetType() == AnimNodeType::AzEntity) { // search for a matching componentId on all children - for (int i = 0; i < GetChildCount(); i++) + for (unsigned int i = 0; i < GetChildCount(); i++) { CTrackViewNode* childNode = GetChild(i); if (childNode->GetNodeType() == eTVNT_AnimNode) diff --git a/Code/Editor/TrackView/TrackViewDialog.cpp b/Code/Editor/TrackView/TrackViewDialog.cpp index bdec68e928..da3e7cebe2 100644 --- a/Code/Editor/TrackView/TrackViewDialog.cpp +++ b/Code/Editor/TrackView/TrackViewDialog.cpp @@ -1991,7 +1991,7 @@ void CTrackViewDialog::UpdateTracksToolBar() &Maestro::EditorSequenceComponentRequestBus::Events::GetAllAnimatablePropertiesForComponent, animatableProperties, azEntityId, pAnimNode->GetComponentId()); - paramCount = animatableProperties.size(); + paramCount = static_cast(animatableProperties.size()); } } else @@ -2317,7 +2317,7 @@ void CTrackViewDialog::SaveCurrentSequenceToFBX() CTrackViewTrackBundle allTracks = sequence->GetAllTracks(); - for (int trackID = 0; trackID < allTracks.GetCount(); ++trackID) + for (unsigned int trackID = 0; trackID < allTracks.GetCount(); ++trackID) { CTrackViewTrack* pCurrentTrack = allTracks.GetTrack(trackID); diff --git a/Code/Editor/TrackView/TrackViewDopeSheetBase.cpp b/Code/Editor/TrackView/TrackViewDopeSheetBase.cpp index 0ff7cc6ca9..f74d51c421 100644 --- a/Code/Editor/TrackView/TrackViewDopeSheetBase.cpp +++ b/Code/Editor/TrackView/TrackViewDopeSheetBase.cpp @@ -1556,7 +1556,7 @@ void CTrackViewDopeSheetBase::MouseMoveMove(const QPoint& p, [[maybe_unused]] Qt const TrackMemento& trackMemento = iter->second; pTrack->RestoreFromMemento(trackMemento.m_memento); - const unsigned int numKeys = trackMemento.m_keySelectionStates.size(); + const unsigned int numKeys = static_cast(trackMemento.m_keySelectionStates.size()); for (unsigned int i = 0; i < numKeys; ++i) { pTrack->GetKey(i).Select(trackMemento.m_keySelectionStates[i]); @@ -1946,7 +1946,7 @@ void CTrackViewDopeSheetBase::ChangeSequenceTrackSelection(CTrackViewSequence* s CTrackViewTrackBundle prevSelectedTracks; prevSelectedTracks = sequenceWithTrack->GetSelectedTracks(); - for (int i = 0; i < prevSelectedTracks.GetCount(); i++) + for (unsigned int i = 0; i < prevSelectedTracks.GetCount(); i++) { CTrackViewTrack* prevSelectedTrack = prevSelectedTracks.GetTrack(i); if (prevSelectedTrack != trackToSelect) @@ -2023,7 +2023,7 @@ bool CTrackViewDopeSheetBase::CreateColorKey(CTrackViewTrack* pTrack, float keyT AzToolsFramework::ScopedUndoBatch undoBatch("Set Key"); const unsigned int numChildNodes = pTrack->GetChildCount(); - for (int i = 0; i < numChildNodes; ++i) + for (unsigned int i = 0; i < numChildNodes; ++i) { CTrackViewTrack* subTrack = static_cast(pTrack->GetChild(i)); if (IsOkToAddKeyHere(subTrack, keyTime)) @@ -2083,7 +2083,7 @@ void CTrackViewDopeSheetBase::UpdateColorKey(const QColor& color, bool addToUndo void CTrackViewDopeSheetBase::UpdateColorKeyHelper(const ColorF& color) { const unsigned int numChildNodes = m_colorUpdateTrack->GetChildCount(); - for (int i = 0; i < numChildNodes; ++i) + for (unsigned int i = 0; i < numChildNodes; ++i) { CTrackViewTrack* subTrack = static_cast(m_colorUpdateTrack->GetChild(i)); CTrackViewKeyHandle subTrackKey = subTrack->GetKeyByTime(m_colorUpdateKeyTime); @@ -2258,7 +2258,7 @@ void CTrackViewDopeSheetBase::AddKeys(const QPoint& point, const bool bTryAddKey } else // A compound track { - for (int k = 0; k < pCurrTrack->GetChildCount(); ++k) + for (unsigned int k = 0; k < pCurrTrack->GetChildCount(); ++k) { CTrackViewTrack* pSubTrack = static_cast(pCurrTrack->GetChild(k)); if (IsOkToAddKeyHere(pSubTrack, keyTime)) @@ -2293,7 +2293,7 @@ void CTrackViewDopeSheetBase::AddKeys(const QPoint& point, const bool bTryAddKey else { AzToolsFramework::ScopedUndoBatch undoBatch("Create Key"); - for (int i = 0; i < pTrack->GetChildCount(); ++i) + for (unsigned int i = 0; i < pTrack->GetChildCount(); ++i) { CTrackViewTrack* pSubTrack = static_cast(pTrack->GetChild(i)); if (IsOkToAddKeyHere(pSubTrack, keyTime)) @@ -3094,7 +3094,7 @@ void CTrackViewDopeSheetBase::SelectKeys(const QRect& rc, const bool bMultiSelec // note the tracks to select for the keyHandles selected CTrackViewTrackBundle tracksToSelect; - for (int i = 0; i < tracks.GetCount(); ++i) + for (unsigned int i = 0; i < tracks.GetCount(); ++i) { CTrackViewTrack* pTrack = tracks.GetTrack(i); @@ -3108,7 +3108,7 @@ void CTrackViewDopeSheetBase::SelectKeys(const QRect& rc, const bool bMultiSelec (rc.bottom() >= trackRect.top() && rc.bottom() <= trackRect.bottom())) { // Check which keys we intersect. - for (int j = 0; j < pTrack->GetKeyCount(); j++) + for (unsigned int j = 0; j < pTrack->GetKeyCount(); j++) { CTrackViewKeyHandle keyHandle = pTrack->GetKey(j); @@ -3175,7 +3175,7 @@ void CTrackViewDopeSheetBase::DrawSelectedKeyIndicators(QPainter* painter) painter->setPen(Qt::green); CTrackViewKeyBundle keys = pSequence->GetSelectedKeys(); - for (int i = 0; i < keys.GetKeyCount(); ++i) + for (unsigned int i = 0; i < keys.GetKeyCount(); ++i) { const CTrackViewKeyHandle& keyHandle = keys.GetKey(i); int x = TimeToClient(keyHandle.GetTime()); @@ -3423,7 +3423,7 @@ void CTrackViewDopeSheetBase::DrawSummary(QPainter* painter, const QRect& rcUpda // Draw a short thick line at each place where there is a key in any tracks. CTrackViewKeyBundle keys = pSequence->GetAllKeys(); - for (int i = 0; i < keys.GetKeyCount(); ++i) + for (unsigned int i = 0; i < keys.GetKeyCount(); ++i) { const CTrackViewKeyHandle& keyHandle = keys.GetKey(i); int x = TimeToClient(keyHandle.GetTime()); @@ -3635,7 +3635,7 @@ void CTrackViewDopeSheetBase::StoreMementoForTracksWithSelectedKeys() std::set tracks; const unsigned int numKeys = selectedKeys.GetKeyCount(); - for (int keyIndex = 0; keyIndex < numKeys; ++keyIndex) + for (unsigned int keyIndex = 0; keyIndex < numKeys; ++keyIndex) { CTrackViewKeyHandle keyHandle = selectedKeys.GetKey(keyIndex); tracks.insert(keyHandle.GetTrack()); diff --git a/Code/Editor/TrackView/TrackViewNodes.cpp b/Code/Editor/TrackView/TrackViewNodes.cpp index 4d6249288e..b64df7e2eb 100644 --- a/Code/Editor/TrackView/TrackViewNodes.cpp +++ b/Code/Editor/TrackView/TrackViewNodes.cpp @@ -1765,7 +1765,7 @@ void CTrackViewNodesCtrl::ImportFromFBX() pSpline->SetKeyInTangent(keyIndex, inTangent); } - if (keyIndex < (pTrack->GetKeyCount() - 1)) + if (keyIndex < static_cast(pTrack->GetKeyCount() - 1)) { CTrackViewKeyHandle nextKey = key.GetNextKey(); if (nextKey.IsValid()) @@ -2352,7 +2352,7 @@ bool CTrackViewNodesCtrl::FillAddTrackMenu(STrackMenuTreeNode& menuAddTrack, con QStringList splittedName = name.split("/", Qt::SkipEmptyParts); STrackMenuTreeNode* pCurrentNode = &menuAddTrack; - for (unsigned int j = 0; j < splittedName.size() - 1; ++j) + for (int j = 0; j < splittedName.size() - 1; ++j) { const QString& segment = splittedName[j]; auto findIter = pCurrentNode->children.find(segment); @@ -2652,7 +2652,7 @@ void CTrackViewNodesCtrl::CreateSetAnimationLayerPopupMenu(QMenu& menuSetLayer, CTrackViewTrackBundle animationTracks = pTrack->GetAnimNode()->GetTracksByParam(AnimParamType::Animation); const unsigned int numAnimationTracks = animationTracks.GetCount(); - for (int i = 0; i < numAnimationTracks; ++i) + for (unsigned int i = 0; i < numAnimationTracks; ++i) { CTrackViewTrack* pAnimationTrack = animationTracks.GetTrack(i); if (pAnimationTrack) diff --git a/Code/Editor/TrackView/TrackViewSequence.cpp b/Code/Editor/TrackView/TrackViewSequence.cpp index 28279be0e3..f66e5276cd 100644 --- a/Code/Editor/TrackView/TrackViewSequence.cpp +++ b/Code/Editor/TrackView/TrackViewSequence.cpp @@ -1403,7 +1403,7 @@ float CTrackViewSequence::ClipTimeOffsetForSliding(const float timeOffset) for (pTrackIter = tracks.begin(); pTrackIter != tracks.end(); ++pTrackIter) { CTrackViewTrack* pTrack = *pTrackIter; - for (int i = 0; i < pTrack->GetKeyCount(); ++i) + for (unsigned int i = 0; i < pTrack->GetKeyCount(); ++i) { const CTrackViewKeyHandle& keyHandle = pTrack->GetKey(i); @@ -1486,7 +1486,7 @@ void CTrackViewSequence::CloneSelectedKeys() std::vector selectedKeyTimes; for (size_t k = 0; k < selectedKeys.GetKeyCount(); ++k) { - CTrackViewKeyHandle skey = selectedKeys.GetKey(k); + CTrackViewKeyHandle skey = selectedKeys.GetKey(static_cast(k)); if (pTrack != skey.GetTrack()) { pTrack = skey.GetTrack(); @@ -1498,7 +1498,7 @@ void CTrackViewSequence::CloneSelectedKeys() // Now, do the actual cloning. for (size_t k = 0; k < selectedKeyTimes.size(); ++k) { - CTrackViewKeyHandle skey = selectedKeys.GetKey(k); + CTrackViewKeyHandle skey = selectedKeys.GetKey(static_cast(k)); skey = skey.GetTrack()->GetKeyByTime(selectedKeyTimes[k]); assert(skey.IsValid()); diff --git a/Code/Editor/Util/MemoryBlock.cpp b/Code/Editor/Util/MemoryBlock.cpp index 03d432762d..e840a1735e 100644 --- a/Code/Editor/Util/MemoryBlock.cpp +++ b/Code/Editor/Util/MemoryBlock.cpp @@ -175,7 +175,7 @@ void CMemoryBlock::Uncompress(CMemoryBlock& toBlock) const #endif uncompress((unsigned char*)toBlock.GetBuffer(), &destSize, (unsigned char*)GetBuffer(), GetSize()); assert(result == Z_OK); - assert(destSize == m_uncompressedSize); + assert(destSize == static_cast(m_uncompressedSize)); } ////////////////////////////////////////////////////////////////////////// diff --git a/Gems/LyShine/Code/Editor/Animation/UiAnimViewDopeSheetBase.cpp b/Gems/LyShine/Code/Editor/Animation/UiAnimViewDopeSheetBase.cpp index 12f1eeac4d..82d05a6f67 100644 --- a/Gems/LyShine/Code/Editor/Animation/UiAnimViewDopeSheetBase.cpp +++ b/Gems/LyShine/Code/Editor/Animation/UiAnimViewDopeSheetBase.cpp @@ -1632,7 +1632,7 @@ float CUiAnimViewDopeSheetBase::MagnetSnap(float newTime, const CUiAnimViewAnimN newTime = keys.GetKey(0).GetTime(); // But if there is an in-range key in a sibling track, use it instead. // Here a 'sibling' means a track that belongs to a same node. - for (int i = 0; i < keys.GetKeyCount(); ++i) + for (unsigned int i = 0; i < keys.GetKeyCount(); ++i) { CUiAnimViewKeyHandle keyHandle = keys.GetKey(i); if (keyHandle.GetTrack()->GetAnimNode() == pNode) @@ -1770,7 +1770,7 @@ bool CUiAnimViewDopeSheetBase::CreateColorKey(CUiAnimViewTrack* pTrack, float ke CUiAnimViewSequenceNotificationContext context(pTrack->GetSequence()); const unsigned int numChildNodes = pTrack->GetChildCount(); - for (int i = 0; i < numChildNodes; ++i) + for (unsigned int i = 0; i < numChildNodes; ++i) { CUiAnimViewTrack* subTrack = static_cast(pTrack->GetChild(i)); if (IsOkToAddKeyHere(subTrack, keyTime)) @@ -1890,7 +1890,7 @@ void CUiAnimViewDopeSheetBase::AddKeys(const QPoint& point, const bool bTryAddKe } else // A compound track { - for (int k = 0; k < pCurrTrack->GetChildCount(); ++k) + for (unsigned int k = 0; k < pCurrTrack->GetChildCount(); ++k) { CUiAnimViewTrack* pSubTrack = static_cast(pCurrTrack->GetChild(k)); if (IsOkToAddKeyHere(pSubTrack, keyTime)) @@ -1921,7 +1921,7 @@ void CUiAnimViewDopeSheetBase::AddKeys(const QPoint& point, const bool bTryAddKe else { RecordTrackUndo(pTrack); - for (int i = 0; i < pTrack->GetChildCount(); ++i) + for (unsigned int i = 0; i < pTrack->GetChildCount(); ++i) { CUiAnimViewTrack* pSubTrack = static_cast(pTrack->GetChild(i)); if (IsOkToAddKeyHere(pSubTrack, keyTime)) @@ -2619,7 +2619,7 @@ void CUiAnimViewDopeSheetBase::SelectKeys(const QRect& rc, const bool bMultiSele CUiAnimViewTrackBundle tracks = pSequence->GetAllTracks(); - for (int i = 0; i < tracks.GetCount(); ++i) + for (unsigned int i = 0; i < tracks.GetCount(); ++i) { CUiAnimViewTrack* pTrack = tracks.GetTrack(i); @@ -2633,7 +2633,7 @@ void CUiAnimViewDopeSheetBase::SelectKeys(const QRect& rc, const bool bMultiSele (rc.bottom() >= trackRect.top() && rc.bottom() <= trackRect.bottom())) { // Check which keys we intersect. - for (int j = 0; j < pTrack->GetKeyCount(); j++) + for (unsigned int j = 0; j < pTrack->GetKeyCount(); j++) { CUiAnimViewKeyHandle keyHandle = pTrack->GetKey(j); @@ -2700,7 +2700,7 @@ void CUiAnimViewDopeSheetBase::DrawSelectedKeyIndicators(QPainter* painter) painter->setPen(Qt::green); CUiAnimViewKeyBundle keys = pSequence->GetSelectedKeys(); - for (int i = 0; i < keys.GetKeyCount(); ++i) + for (unsigned int i = 0; i < keys.GetKeyCount(); ++i) { CUiAnimViewKeyHandle keyHandle = keys.GetKey(i); int x = TimeToClient(keyHandle.GetTime()); @@ -2951,7 +2951,7 @@ void CUiAnimViewDopeSheetBase::DrawSummary(QPainter* painter, const QRect& rcUpd // Draw a short thick line at each place where there is a key in any tracks. CUiAnimViewKeyBundle keys = pSequence->GetAllKeys(); - for (int i = 0; i < keys.GetKeyCount(); ++i) + for (unsigned int i = 0; i < keys.GetKeyCount(); ++i) { CUiAnimViewKeyHandle keyHandle = keys.GetKey(i); int x = TimeToClient(keyHandle.GetTime()); @@ -3112,7 +3112,7 @@ void CUiAnimViewDopeSheetBase::StoreMementoForTracksWithSelectedKeys() std::set tracks; const unsigned int numKeys = selectedKeys.GetKeyCount(); - for (int keyIndex = 0; keyIndex < numKeys; ++keyIndex) + for (unsigned int keyIndex = 0; keyIndex < numKeys; ++keyIndex) { CUiAnimViewKeyHandle keyHandle = selectedKeys.GetKey(keyIndex); tracks.insert(keyHandle.GetTrack()); From 14e77543348bbdbd6edc05379759bee797b9c994 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 13 Aug 2021 17:46:37 -0700 Subject: [PATCH 463/803] More fixes for warnings Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../Tools/Uploader/ToolsCrashUploader.cpp | 9 +++++-- .../Source/GameLiftServerSDKWrapper.cpp | 8 ++++++- .../Windows/GameCrashUploader_windows.cpp | 24 ++++++++++--------- ...AnimGraphStateMachineInterruptionTests.cpp | 2 +- .../ScriptCanvas/Core/NodeFunctionGeneric.h | 3 +++ 5 files changed, 31 insertions(+), 15 deletions(-) diff --git a/Code/Tools/CrashHandler/Tools/Uploader/ToolsCrashUploader.cpp b/Code/Tools/CrashHandler/Tools/Uploader/ToolsCrashUploader.cpp index b33aa183f3..3247e8d2bf 100644 --- a/Code/Tools/CrashHandler/Tools/Uploader/ToolsCrashUploader.cpp +++ b/Code/Tools/CrashHandler/Tools/Uploader/ToolsCrashUploader.cpp @@ -72,10 +72,15 @@ namespace O3de return true; } #if !AZ_TRAIT_OS_PLATFORM_APPLE - AZ_PUSH_DISABLE_WARNING(4996, "-Wunknown-warning-option") + #if AZ_TRAIT_USE_SECURE_CRT_FUNCTIONS + char noConfirmation[64]{}; + size_t variableSize = 0; + auto err = getenv_s(&variableSize, noConfirmation, AZ_ARRAY_SIZE(noConfirmation), "LY_NO_CONFIRM"); + if (variableSize == 0) + #else const char* noConfirmation = getenv("LY_NO_CONFIRM"); - AZ_POP_DISABLE_WARNING if (noConfirmation == nullptr) + #endif { int argCount = 0; diff --git a/Gems/AWSGameLift/Code/AWSGameLiftServer/Source/GameLiftServerSDKWrapper.cpp b/Gems/AWSGameLift/Code/AWSGameLiftServer/Source/GameLiftServerSDKWrapper.cpp index ae4fe7b0f4..7e216f33be 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftServer/Source/GameLiftServerSDKWrapper.cpp +++ b/Gems/AWSGameLift/Code/AWSGameLiftServer/Source/GameLiftServerSDKWrapper.cpp @@ -54,7 +54,13 @@ namespace AWSGameLift } char buffer[50]; - strftime(buffer, sizeof(buffer), "%FT%TZ", gmtime(&terminationTime)); + tm time; +#if AZ_TRAIT_USE_SECURE_CRT_FUNCTIONS + gmtime_s(&time, &terminationTime); +#else + time = *gmtime(&terminationTime); +#endif + strftime(buffer, sizeof(buffer), "%FT%TZ", &time); return AZStd::string(buffer); } diff --git a/Gems/CrashReporting/Code/Platform/Windows/GameCrashUploader_windows.cpp b/Gems/CrashReporting/Code/Platform/Windows/GameCrashUploader_windows.cpp index d8def1885e..c4ddb50c53 100644 --- a/Gems/CrashReporting/Code/Platform/Windows/GameCrashUploader_windows.cpp +++ b/Gems/CrashReporting/Code/Platform/Windows/GameCrashUploader_windows.cpp @@ -7,14 +7,11 @@ */ #include +#include #include #include -#include -#include -#include - namespace O3de { @@ -22,21 +19,26 @@ namespace O3de { if (!m_noConfirmation) { +#if AZ_TRAIT_USE_SECURE_CRT_FUNCTIONS + char noConfirmation[64]{}; + size_t variableSize = 0; + getenv_s(&variableSize, noConfirmation, AZ_ARRAY_SIZE(noConfirmation), "LY_NO_CONFIRM"); + if (variableSize == 0) +#else const char* noConfirmation = getenv("LY_NO_CONFIRM"); if (noConfirmation == nullptr) +#endif + { - - std::wstring sendDialogMessage; - - std::wstring_convert> converter; - sendDialogMessage = converter.from_bytes(m_executableName); + AZStd::wstring sendDialogMessage; + AZStd::to_wstring(sendDialogMessage, m_executableName.c_str()); sendDialogMessage += L" has encountered a fatal error. We're sorry for the inconvenience.\n\nA crash debugging file has been created at:\n"; - sendDialogMessage += report.file_path.value(); + sendDialogMessage += report.file_path.value().c_str(); sendDialogMessage += L"\n\nIf you are willing to submit this file to Amazon it will help us improve the Lumberyard experience. We will treat this report as confidential.\n\nWould you like to send the error report?"; int msgboxID = MessageBoxW( - NULL, + nullptr, sendDialogMessage.data(), L"Send Error Report", (MB_ICONEXCLAMATION | MB_YESNO | MB_SYSTEMMODAL) diff --git a/Gems/EMotionFX/Code/Tests/AnimGraphStateMachineInterruptionTests.cpp b/Gems/EMotionFX/Code/Tests/AnimGraphStateMachineInterruptionTests.cpp index 1f700129c0..39fc296d9f 100644 --- a/Gems/EMotionFX/Code/Tests/AnimGraphStateMachineInterruptionTests.cpp +++ b/Gems/EMotionFX/Code/Tests/AnimGraphStateMachineInterruptionTests.cpp @@ -165,7 +165,7 @@ namespace EMotionFX for (const auto& activeObjects : activeObjectsAtFrame) { - if (activeObjects.m_frameNr == frame) + if (activeObjects.m_frameNr == static_cast(frame)) { // Check which states and transitions are active and compare it to the expected ones. EXPECT_EQ(activeObjects.m_stateA, compareAgainst.m_stateA) diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/NodeFunctionGeneric.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/NodeFunctionGeneric.h index 41a674536b..e9586ac83a 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/NodeFunctionGeneric.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/NodeFunctionGeneric.h @@ -181,9 +181,12 @@ namespace ScriptCanvas : public Node { public: + AZ_PUSH_DISABLE_WARNING(5046, "-Wunknown-warning-option") // 'function' : Symbol involving type with internal linkage not defined AZ_RTTI(((NodeFunctionGenericMultiReturn), "{DC5B1799-6C5B-4190-8D90-EF0C2D1BCE4E}", t_Func, t_Traits), Node); AZ_COMPONENT_INTRUSIVE_DESCRIPTOR_TYPE(NodeFunctionGenericMultiReturn); AZ_COMPONENT_BASE(NodeFunctionGenericMultiReturn, Node); + AZ_POP_DISABLE_WARNING + static const char* GetNodeFunctionName() { From 0eacd54b14ff74ac5f615d10aafbfee1d27c8de0 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 13 Aug 2021 17:47:37 -0700 Subject: [PATCH 464/803] removing unnecessary bigobj flags from files (its applied globally) Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../Common/MSVC/editor_lib_msvc.cmake | 5 ---- .../Framework/AzToolsFramework/CMakeLists.txt | 1 - .../Common/Clang/aztoolsframework_clang.cmake | 7 ----- .../Common/MSVC/aztoolsframework_msvc.cmake | 13 --------- .../MSVC/pythonassetbuilder_tests_msvc.cmake | 10 ------- Gems/ScriptCanvasTesting/Code/CMakeLists.txt | 2 -- ...riptcanvastesting_editor_tests_clang.cmake | 7 ----- ...criptcanvastesting_editor_tests_msvc.cmake | 28 ------------------- 8 files changed, 73 deletions(-) delete mode 100644 Code/Framework/AzToolsFramework/Platform/Common/Clang/aztoolsframework_clang.cmake delete mode 100644 Code/Framework/AzToolsFramework/Platform/Common/MSVC/aztoolsframework_msvc.cmake delete mode 100644 Gems/ScriptCanvasTesting/Code/Platform/Common/Clang/scriptcanvastesting_editor_tests_clang.cmake delete mode 100644 Gems/ScriptCanvasTesting/Code/Platform/Common/MSVC/scriptcanvastesting_editor_tests_msvc.cmake diff --git a/Code/Editor/Platform/Common/MSVC/editor_lib_msvc.cmake b/Code/Editor/Platform/Common/MSVC/editor_lib_msvc.cmake index cd72cfb3d8..7a325ca97e 100644 --- a/Code/Editor/Platform/Common/MSVC/editor_lib_msvc.cmake +++ b/Code/Editor/Platform/Common/MSVC/editor_lib_msvc.cmake @@ -5,8 +5,3 @@ # SPDX-License-Identifier: Apache-2.0 OR MIT # # -ly_add_source_properties( - SOURCES MainWindow.cpp CryEdit.cpp - PROPERTY COMPILE_OPTIONS - VALUES -bigobj -) diff --git a/Code/Framework/AzToolsFramework/CMakeLists.txt b/Code/Framework/AzToolsFramework/CMakeLists.txt index 62f4f43d93..2754dd19eb 100644 --- a/Code/Framework/AzToolsFramework/CMakeLists.txt +++ b/Code/Framework/AzToolsFramework/CMakeLists.txt @@ -20,7 +20,6 @@ ly_add_target( AzToolsFramework/aztoolsframework_files.cmake AzToolsFramework/aztoolsframework_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake Platform/${PAL_PLATFORM_NAME}/platform_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake - Platform/Common/${PAL_TRAIT_COMPILER_ID}/aztoolsframework_${PAL_TRAIT_COMPILER_ID_LOWERCASE}.cmake INCLUDE_DIRECTORIES PUBLIC . diff --git a/Code/Framework/AzToolsFramework/Platform/Common/Clang/aztoolsframework_clang.cmake b/Code/Framework/AzToolsFramework/Platform/Common/Clang/aztoolsframework_clang.cmake deleted file mode 100644 index 7a325ca97e..0000000000 --- a/Code/Framework/AzToolsFramework/Platform/Common/Clang/aztoolsframework_clang.cmake +++ /dev/null @@ -1,7 +0,0 @@ -# -# Copyright (c) Contributors to the Open 3D Engine Project. -# For complete copyright and license terms please see the LICENSE at the root of this distribution. -# -# SPDX-License-Identifier: Apache-2.0 OR MIT -# -# diff --git a/Code/Framework/AzToolsFramework/Platform/Common/MSVC/aztoolsframework_msvc.cmake b/Code/Framework/AzToolsFramework/Platform/Common/MSVC/aztoolsframework_msvc.cmake deleted file mode 100644 index 1a34f54a63..0000000000 --- a/Code/Framework/AzToolsFramework/Platform/Common/MSVC/aztoolsframework_msvc.cmake +++ /dev/null @@ -1,13 +0,0 @@ -# -# Copyright (c) Contributors to the Open 3D Engine Project. -# For complete copyright and license terms please see the LICENSE at the root of this distribution. -# -# SPDX-License-Identifier: Apache-2.0 OR MIT -# -# - -ly_add_source_properties( - SOURCES AzToolsFramework/Application/ToolsApplication.cpp - PROPERTY COMPILE_OPTIONS - VALUES -bigobj -) diff --git a/Gems/PythonAssetBuilder/Code/Source/Platform/Common/MSVC/pythonassetbuilder_tests_msvc.cmake b/Gems/PythonAssetBuilder/Code/Source/Platform/Common/MSVC/pythonassetbuilder_tests_msvc.cmake index b2c4543e99..7a325ca97e 100644 --- a/Gems/PythonAssetBuilder/Code/Source/Platform/Common/MSVC/pythonassetbuilder_tests_msvc.cmake +++ b/Gems/PythonAssetBuilder/Code/Source/Platform/Common/MSVC/pythonassetbuilder_tests_msvc.cmake @@ -5,13 +5,3 @@ # SPDX-License-Identifier: Apache-2.0 OR MIT # # - -ly_add_source_properties( - SOURCES - Tests/PythonAssetBuilderTest.cpp - Tests/PythonBuilderRegisterTest.cpp - Tests/PythonBuilderCreateJobsTest.cpp - Tests/PythonBuilderProcessJobTest.cpp - PROPERTY COMPILE_OPTIONS - VALUES -bigobj -) diff --git a/Gems/ScriptCanvasTesting/Code/CMakeLists.txt b/Gems/ScriptCanvasTesting/Code/CMakeLists.txt index 23c9627e83..29360912d8 100644 --- a/Gems/ScriptCanvasTesting/Code/CMakeLists.txt +++ b/Gems/ScriptCanvasTesting/Code/CMakeLists.txt @@ -87,8 +87,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) NAMESPACE Gem FILES_CMAKE scriptcanvastestingeditor_tests_files.cmake - PLATFORM_INCLUDE_FILES - Platform/Common/${PAL_TRAIT_COMPILER_ID}/scriptcanvastesting_editor_tests_${PAL_TRAIT_COMPILER_ID_LOWERCASE}.cmake INCLUDE_DIRECTORIES PRIVATE . diff --git a/Gems/ScriptCanvasTesting/Code/Platform/Common/Clang/scriptcanvastesting_editor_tests_clang.cmake b/Gems/ScriptCanvasTesting/Code/Platform/Common/Clang/scriptcanvastesting_editor_tests_clang.cmake deleted file mode 100644 index 7a325ca97e..0000000000 --- a/Gems/ScriptCanvasTesting/Code/Platform/Common/Clang/scriptcanvastesting_editor_tests_clang.cmake +++ /dev/null @@ -1,7 +0,0 @@ -# -# Copyright (c) Contributors to the Open 3D Engine Project. -# For complete copyright and license terms please see the LICENSE at the root of this distribution. -# -# SPDX-License-Identifier: Apache-2.0 OR MIT -# -# diff --git a/Gems/ScriptCanvasTesting/Code/Platform/Common/MSVC/scriptcanvastesting_editor_tests_msvc.cmake b/Gems/ScriptCanvasTesting/Code/Platform/Common/MSVC/scriptcanvastesting_editor_tests_msvc.cmake deleted file mode 100644 index 3ea56febcb..0000000000 --- a/Gems/ScriptCanvasTesting/Code/Platform/Common/MSVC/scriptcanvastesting_editor_tests_msvc.cmake +++ /dev/null @@ -1,28 +0,0 @@ -# -# Copyright (c) Contributors to the Open 3D Engine Project. -# For complete copyright and license terms please see the LICENSE at the root of this distribution. -# -# SPDX-License-Identifier: Apache-2.0 OR MIT -# -# - -ly_add_source_properties( - SOURCES - Source/Framework/ScriptCanvasTestUtilities.cpp - Tests/ScriptCanvas_BehaviorContext.cpp - Tests/ScriptCanvas_ContainerSupport.cpp - Tests/ScriptCanvas_Core.cpp - Tests/ScriptCanvas_EventHandlers.cpp - Tests/ScriptCanvas_Math.cpp - Tests/ScriptCanvas_MethodOverload.cpp - Tests/ScriptCanvas_NodeGenerics.cpp - Tests/ScriptCanvas_Regressions.cpp - Tests/ScriptCanvas_RuntimeInterpreted.cpp - Tests/ScriptCanvas_Slots.cpp - Tests/ScriptCanvas_StringNodes.cpp - Tests/ScriptCanvas_UnitTesting.cpp - Tests/ScriptCanvas_Variables.cpp - Tests/ScriptCanvas_VM.cpp - PROPERTY COMPILE_OPTIONS - VALUES -bigobj -) From 0cb66584eb30275ff5f1d6817e92003868650674 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 13 Aug 2021 17:51:49 -0700 Subject: [PATCH 465/803] small fix, everything compiling with VS2022 Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Tools/CrashHandler/Tools/Uploader/ToolsCrashUploader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Tools/CrashHandler/Tools/Uploader/ToolsCrashUploader.cpp b/Code/Tools/CrashHandler/Tools/Uploader/ToolsCrashUploader.cpp index 3247e8d2bf..74f271e7c0 100644 --- a/Code/Tools/CrashHandler/Tools/Uploader/ToolsCrashUploader.cpp +++ b/Code/Tools/CrashHandler/Tools/Uploader/ToolsCrashUploader.cpp @@ -75,7 +75,7 @@ namespace O3de #if AZ_TRAIT_USE_SECURE_CRT_FUNCTIONS char noConfirmation[64]{}; size_t variableSize = 0; - auto err = getenv_s(&variableSize, noConfirmation, AZ_ARRAY_SIZE(noConfirmation), "LY_NO_CONFIRM"); + getenv_s(&variableSize, noConfirmation, AZ_ARRAY_SIZE(noConfirmation), "LY_NO_CONFIRM"); if (variableSize == 0) #else const char* noConfirmation = getenv("LY_NO_CONFIRM"); From 230e0c697693d5e90f835123c0b037a56e4ee253 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Mon, 16 Aug 2021 15:54:08 -0700 Subject: [PATCH 466/803] remove disabling of some warnings Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- cmake/Platform/Common/MSVC/Configurations_msvc.cmake | 2 -- 1 file changed, 2 deletions(-) diff --git a/cmake/Platform/Common/MSVC/Configurations_msvc.cmake b/cmake/Platform/Common/MSVC/Configurations_msvc.cmake index 4e2ec5a852..02db57ca21 100644 --- a/cmake/Platform/Common/MSVC/Configurations_msvc.cmake +++ b/cmake/Platform/Common/MSVC/Configurations_msvc.cmake @@ -113,8 +113,6 @@ endif() ly_set(LY_CXX_SYSTEM_INCLUDE_CONFIGURATION_FLAG /experimental:external # Turns on "external" headers feature for MSVC compilers /external:W0 # Set warning level in external headers to 0. This is used to suppress warnings 3rdParty libraries which uses the "system_includes" option in their json configuration - /wd4193 # Temporary workaround for the /experiment:external feature generating warning C4193: #pragma warning(pop): no matching '#pragma warning(push)' - /wd4702 # Despite we set it to W0, we found that 3rdParty::OpenMesh was issuing these warnings while using some template functions. Disabling it here does the trick ) if(NOT CMAKE_INCLUDE_SYSTEM_FLAG_CXX) ly_set(CMAKE_INCLUDE_SYSTEM_FLAG_CXX /external:I) From 06e6f83907d2fb423f60216d2c6bbc0489d7b563 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Mon, 16 Aug 2021 15:54:35 -0700 Subject: [PATCH 467/803] Cleanup and fixing of Code/Framework Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../Framework/AzCore/AzCore/Jobs/Algorithms.h | 9 ------ .../Math/Internal/SimdMathVec4_scalar.inl | 9 ++---- .../Framework/AzCore/AzCore/Math/Quaternion.h | 7 ---- Code/Framework/AzCore/AzCore/Math/Vector2.h | 7 ---- Code/Framework/AzCore/AzCore/Math/Vector3.h | 7 ---- Code/Framework/AzCore/AzCore/Math/Vector4.h | 8 ----- .../AzCore/AzCore/Memory/dlmalloc.inl | 25 ++++----------- Code/Framework/AzCore/AzCore/PlatformDef.h | 3 -- .../AzCore/AzCore/RTTI/BehaviorContext.h | 11 +------ .../AzCore/AzCore/Serialization/EditContext.h | 21 ++++++------ .../AzCore/AzCore/std/delegate/delegate.h | 11 ++----- .../AzCore/std/function/function_base.h | 14 -------- .../AzCore/std/function/function_template.h | 9 ------ .../internal/concurrent_hash_table.h | 32 ++++++++++--------- .../AzCore/AzCore/std/smart_ptr/weak_ptr.h | 4 --- .../AzCore/AzCore/std/string/regex.h | 9 ------ Code/Framework/AzCore/Tests/Jobs.cpp | 2 +- .../Json/MathMatrixSerializerTests.cpp | 1 - 18 files changed, 40 insertions(+), 149 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/Jobs/Algorithms.h b/Code/Framework/AzCore/AzCore/Jobs/Algorithms.h index 27efde7e64..a45846c107 100644 --- a/Code/Framework/AzCore/AzCore/Jobs/Algorithms.h +++ b/Code/Framework/AzCore/AzCore/Jobs/Algorithms.h @@ -13,11 +13,6 @@ #include -#ifdef AZ_COMPILER_MSVC -# pragma warning(push) -# pragma warning(disable: 4355) // 'this' : used in base member initializer list -#endif - // A reasonable define for a stack allocator size for the high level jobs. #define AZ_JOBS_DEFAULT_STACK_ALLOCATOR_SIZE AZStd::GetMax(2048,512 * AZStd::thread::hardware_concurrency()) @@ -769,9 +764,5 @@ namespace AZ } } -#ifdef AZ_COMPILER_MSVC -# pragma warning(pop) -#endif - #endif #pragma once diff --git a/Code/Framework/AzCore/AzCore/Math/Internal/SimdMathVec4_scalar.inl b/Code/Framework/AzCore/AzCore/Math/Internal/SimdMathVec4_scalar.inl index 7320c9be1c..484351c799 100644 --- a/Code/Framework/AzCore/AzCore/Math/Internal/SimdMathVec4_scalar.inl +++ b/Code/Framework/AzCore/AzCore/Math/Internal/SimdMathVec4_scalar.inl @@ -10,12 +10,9 @@ #include -#ifdef _MSC_VER // Unity builds on windows using the scalar backend are tripping some really strange warning behavior.. // Disable the warning so we can test the scalar implementation with unity on windows -# pragma warning (push) -# pragma warning (disable: 4723) // Potential divide by zero -#endif +AZ_PUSH_DISABLE_WARNING(4723, "-Wunknown-warning-option") // Potential divide by zero namespace AZ { @@ -1049,6 +1046,4 @@ namespace AZ } } -#ifdef _MSC_VER -# pragma warning (pop) -#endif +AZ_POP_DISABLE_WARNING \ No newline at end of file diff --git a/Code/Framework/AzCore/AzCore/Math/Quaternion.h b/Code/Framework/AzCore/AzCore/Math/Quaternion.h index 36def91817..f2c266ed3e 100644 --- a/Code/Framework/AzCore/AzCore/Math/Quaternion.h +++ b/Code/Framework/AzCore/AzCore/Math/Quaternion.h @@ -246,10 +246,6 @@ namespace AZ //! Takes the absolute value of each component of the quaternion. Quaternion GetAbs() const; -#ifdef AZ_COMPILER_MSVC -# pragma warning(push) -# pragma warning(disable:4201) // anonymous union -#endif union { Simd::Vec4::FloatType m_value; @@ -263,9 +259,6 @@ namespace AZ float m_w; }; }; -#ifdef AZ_COMPILER_MSVC -# pragma warning(pop) -#endif }; //! Non-member functionality belonging to the AZ namespace diff --git a/Code/Framework/AzCore/AzCore/Math/Vector2.h b/Code/Framework/AzCore/AzCore/Math/Vector2.h index c667f48010..b2b1ceeb4d 100644 --- a/Code/Framework/AzCore/AzCore/Math/Vector2.h +++ b/Code/Framework/AzCore/AzCore/Math/Vector2.h @@ -281,10 +281,6 @@ namespace AZ private: -#ifdef AZ_COMPILER_MSVC -# pragma warning(push) -# pragma warning(disable:4201) // anonymous union -#endif union { Simd::Vec2::FloatType m_value; @@ -296,9 +292,6 @@ namespace AZ float m_y; }; }; -#ifdef AZ_COMPILER_MSVC -# pragma warning(pop) -#endif }; //! Allows pre-multiplying by a float. diff --git a/Code/Framework/AzCore/AzCore/Math/Vector3.h b/Code/Framework/AzCore/AzCore/Math/Vector3.h index 6b7ded5641..4bf0a18894 100644 --- a/Code/Framework/AzCore/AzCore/Math/Vector3.h +++ b/Code/Framework/AzCore/AzCore/Math/Vector3.h @@ -312,10 +312,6 @@ namespace AZ private: -#ifdef AZ_COMPILER_MSVC -# pragma warning(push) -# pragma warning(disable:4201) // anonymous union -#endif union { Simd::Vec3::FloatType m_value; @@ -328,9 +324,6 @@ namespace AZ float m_z; }; }; -#ifdef AZ_COMPILER_MSVC -# pragma warning(pop) -#endif }; //! Non member functionality belonging to the AZ namespace. diff --git a/Code/Framework/AzCore/AzCore/Math/Vector4.h b/Code/Framework/AzCore/AzCore/Math/Vector4.h index 7ae0350805..6bd67e8831 100644 --- a/Code/Framework/AzCore/AzCore/Math/Vector4.h +++ b/Code/Framework/AzCore/AzCore/Math/Vector4.h @@ -283,11 +283,6 @@ namespace AZ Simd::Vec4::FloatType GetSimdValue() const; protected: - -#ifdef AZ_COMPILER_MSVC -# pragma warning(push) -# pragma warning(disable:4201) // anonymous union -#endif union { Simd::Vec4::FloatType m_value; @@ -301,9 +296,6 @@ namespace AZ float m_w; }; }; -#ifdef AZ_COMPILER_MSVC -# pragma warning(pop) -#endif }; } diff --git a/Code/Framework/AzCore/AzCore/Memory/dlmalloc.inl b/Code/Framework/AzCore/AzCore/Memory/dlmalloc.inl index 861e2de7ac..3756fbb36c 100644 --- a/Code/Framework/AzCore/AzCore/Memory/dlmalloc.inl +++ b/Code/Framework/AzCore/AzCore/Memory/dlmalloc.inl @@ -1294,14 +1294,6 @@ int mspace_mallopt(int, int); /*------------------------------ internal #includes ---------------------- */ -#ifdef WIN32 -#pragma warning(push) -#pragma warning( disable : 4146 ) /* no "unsigned" warnings */ -# ifdef AZ_PLATFORM_WINDOWS -# pragma warning( disable : 4267 ) -# endif -#endif /* WIN32 */ - #include /* for printing in malloc_stats */ #ifndef LACKS_ERRNO_H @@ -2170,7 +2162,7 @@ typedef unsigned int flag_t; /* The type of various bit flag sets */ #define align_as_chunk(A) (mchunkptr)((A) + align_offset(chunk2mem(A))) /* Bounds on request (not chunk) sizes. */ -#define MAX_REQUEST ((-MIN_CHUNK_SIZE) << 2) +#define MAX_REQUEST ((~MIN_CHUNK_SIZE + 1) << 2) #define MIN_REQUEST (MIN_CHUNK_SIZE - CHUNK_OVERHEAD - SIZE_T_ONE) /* pad request bytes into a usable size */ @@ -2881,10 +2873,10 @@ static size_t traverse_and_check(mstate m); #define treemap_is_marked(M, i) ((M)->treemap & idx2bit(i)) /* isolate the least set bit of a bitmap */ -#define least_bit(x) ((x) & - (x)) +#define least_bit(x) ((x) & (~(x)+1)) /* mask with all bits to left of least bit of x on */ -#define left_bits(x) ((x << 1) | -(x << 1)) +#define left_bits(x) ((x << 1) | (~(x << 1)+1)) /* mask with all bits to left of or equal to least bit of x on */ #define same_or_left_bits(x) ((x) | -(x)) @@ -4528,7 +4520,7 @@ static int sys_trim(mstate m, size_t pad) static void* tmalloc_large(mstate m, size_t nb) { tchunkptr v = 0; - size_t rsize = -nb; /* Unsigned negation */ + size_t rsize = ~nb+1; /* Unsigned negation */ tchunkptr t; bindex_t idx; compute_tree_index(nb, idx); @@ -4807,7 +4799,7 @@ static void* internal_memalign(mstate m, size_t alignment, size_t bytes) char* br = (char*)mem2chunk((size_t)(((size_t)(mem + alignment - SIZE_T_ONE)) & - - alignment)); + (~alignment+1))); char* pos = ((size_t)(br - (char*)(p)) >= MIN_CHUNK_SIZE) ? br : br + alignment; mchunkptr newp = (mchunkptr)pos; @@ -5489,7 +5481,7 @@ postaction: size_t msize; ensure_initialization(); msize = pad_request(sizeof(struct malloc_state)); - if (capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) + if (capacity < (~(msize + TOP_FOOT_SIZE + mparams.page_size)+1)) { size_t rs = ((capacity == 0) ? mparams.granularity : (capacity + TOP_FOOT_SIZE + msize)); @@ -5512,7 +5504,7 @@ postaction: ensure_initialization(); msize = pad_request(sizeof(struct malloc_state)); if (capacity > msize + TOP_FOOT_SIZE && - capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) + capacity < (~(msize + TOP_FOOT_SIZE + mparams.page_size)+1)) { m = init_user_mstate((char*)base, capacity); m->seg.sflags = EXTERN_BIT; @@ -6367,6 +6359,3 @@ postaction: */ -#ifdef WIN32 -#pragma warning(pop) -#endif /* WIN32 */ diff --git a/Code/Framework/AzCore/AzCore/PlatformDef.h b/Code/Framework/AzCore/AzCore/PlatformDef.h index 55126fdf4c..47f45931ba 100644 --- a/Code/Framework/AzCore/AzCore/PlatformDef.h +++ b/Code/Framework/AzCore/AzCore/PlatformDef.h @@ -87,9 +87,6 @@ #define AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING AZ_POP_DISABLE_WARNING # define AZ_FORCE_INLINE __forceinline -#if !defined(_DEBUG) -# pragma warning(disable:4714) //warning C4714 marked as __forceinline not inlined. Sadly this happens when LTCG during linking. We tried to NOT use force inline but VC 2012 is bad at inlining. -#endif /// Aligns a declaration. # define AZ_ALIGN(_decl, _alignment) \ diff --git a/Code/Framework/AzCore/AzCore/RTTI/BehaviorContext.h b/Code/Framework/AzCore/AzCore/RTTI/BehaviorContext.h index 42fc762769..0c4eaf8383 100644 --- a/Code/Framework/AzCore/AzCore/RTTI/BehaviorContext.h +++ b/Code/Framework/AzCore/AzCore/RTTI/BehaviorContext.h @@ -24,11 +24,6 @@ #include #include -#if defined(AZ_COMPILER_MSVC) -# pragma warning(push) -# pragma warning(disable: 4127) // conditional expression is constant -#endif - namespace AZStd { template @@ -4507,7 +4502,7 @@ namespace AZ params.resize(sizeof...(Args) + eBehaviorBusForwarderEventIndices::ParameterFirst); SetParameters(¶ms[eBehaviorBusForwarderEventIndices::Result], nullptr); SetParameters(¶ms[eBehaviorBusForwarderEventIndices::UserData], nullptr); - if (sizeof...(Args) > 0) + if constexpr (sizeof...(Args) > 0) { SetParameters(¶ms[eBehaviorBusForwarderEventIndices::ParameterFirst], nullptr); } @@ -4872,10 +4867,6 @@ namespace AZ } // namespace Internal } // namespace AZ -#if defined(AZ_COMPILER_MSVC) -# pragma warning(pop) -#endif - // pull AzStd on demand reflection #include #include diff --git a/Code/Framework/AzCore/AzCore/Serialization/EditContext.h b/Code/Framework/AzCore/AzCore/Serialization/EditContext.h index 492550f266..a08e971ac4 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/EditContext.h +++ b/Code/Framework/AzCore/AzCore/Serialization/EditContext.h @@ -656,26 +656,25 @@ namespace AZ using ElementType = typename AZStd::Utils::if_c::value, typename ElementTypeInfo::Type, typename ElementTypeInfo::ElementType>::type; AZ_Assert(m_classData->m_typeId == AzTypeInfo::Uuid(), "Data element (%s) belongs to a different class!", AzTypeInfo::Name()); -#if defined(AZ_COMPILER_MSVC) -# pragma warning(push) -# pragma warning(disable: 4127) // conditional expression is constant -#endif const SerializeContext::ClassData* classData = m_context->m_serializeContext.FindClassData(AzTypeInfo::Uuid()); if (classData && classData->m_editData) { return DataElement(uiId, memberVariable, classData->m_editData->m_name, classData->m_editData->m_description); } - else if (AZStd::is_enum::value && AzTypeInfo::Name() != nullptr) + else { - auto enumIter = m_context->m_enumData.find(AzTypeInfo::Uuid()); - if (enumIter != m_context->m_enumData.end()) + if constexpr (AZStd::is_enum::value) { - return DataElement(uiId, memberVariable, enumIter->second.m_name, enumIter->second.m_description); + if (AzTypeInfo::Name() != nullptr) + { + auto enumIter = m_context->m_enumData.find(AzTypeInfo::Uuid()); + if (enumIter != m_context->m_enumData.end()) + { + return DataElement(uiId, memberVariable, enumIter->second.m_name, enumIter->second.m_description); + } + } } } -#if defined(AZ_COMPILER_MSVC) -# pragma warning(pop) -#endif const char* typeName = AzTypeInfo::Name(); return DataElement(uiId, memberVariable, typeName, typeName); diff --git a/Code/Framework/AzCore/AzCore/std/delegate/delegate.h b/Code/Framework/AzCore/AzCore/std/delegate/delegate.h index 610c1982f2..1b44437f31 100644 --- a/Code/Framework/AzCore/AzCore/std/delegate/delegate.h +++ b/Code/Framework/AzCore/AzCore/std/delegate/delegate.h @@ -291,9 +291,7 @@ namespace AZStd template <> struct SimplifyMemFunc { -#if defined(AZ_COMPILER_MSVC) -# pragma warning(push) -# pragma warning(disable: 4121) // alignment of a member was sensitive to packing + AZ_PUSH_DISABLE_WARNING(4121, "-Wunknown-warning-option") // alignment of a member was sensitive to packing // GenericClass* (X::*ProbeFunc) changes it's size. From Microsoft: // Jason Shirk [MSFT] // This is a known bug/issue. Unfortunately, we can't fix it in X86 product @@ -302,7 +300,6 @@ namespace AZStd // We have addressed the issue for all future platforms (including IA64) where // binary compatibility isn't yet an issue. // We can fix this warning by adding forward decl class __single_inheritance CLASS; if the XFuncType is member function. -#endif template inline static GenericClass* Convert(X* pthis, XFuncType function_to_bind, GenericMemFuncType& bound_func) { @@ -330,11 +327,7 @@ namespace AZStd u.s.codeptr = u2.s.codeptr; return (pthis->*u.ProbeFunc)(); } - -#if defined(AZ_COMPILER_MSVC) -# pragma warning(default: 4121) // alignment of a member was sensitive to packing -# pragma warning(pop) -#endif + AZ_POP_DISABLE_WARNING }; // Nasty hack for Microsoft and Intel (IA32 and Itanium) diff --git a/Code/Framework/AzCore/AzCore/std/function/function_base.h b/Code/Framework/AzCore/AzCore/std/function/function_base.h index c1dd669f51..32892a4c03 100644 --- a/Code/Framework/AzCore/AzCore/std/function/function_base.h +++ b/Code/Framework/AzCore/AzCore/std/function/function_base.h @@ -20,13 +20,6 @@ #include #include -#if defined(AZ_COMPILER_MSVC) -# pragma warning( push ) -# pragma warning( disable : 4793 ) // complaint about native code generation -# pragma warning( disable : 4127 ) // "conditional expression is constant" -# pragma warning( disable : 4275 ) // non dll-interface class 'stdext::exception' used as base for dll-interface class 'std::bad_cast' -#endif - #define AZSTD_FUNCTION_TARGET_FIX(x) #define AZSTD_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, Type) AZStd::enable_if_t, Type> @@ -796,12 +789,5 @@ namespace AZStd //#undef aztypeid //#undef aztypeid_cmp -#if defined(AZ_COMPILER_MSVC) -# pragma warning( default : 4793 ) // complaint about native code generation -# pragma warning( default : 4127 ) // "conditional expression is constant" -# pragma warning( default : 4275 ) // non dll-interface class 'stdext::exception' used as base for dll-interface class 'std::bad_cast' -# pragma warning( pop ) -#endif - #endif // AZSTD_FUNCTION_BASE_HEADER #pragma once diff --git a/Code/Framework/AzCore/AzCore/std/function/function_template.h b/Code/Framework/AzCore/AzCore/std/function/function_template.h index 586b02e671..7f388c4006 100644 --- a/Code/Framework/AzCore/AzCore/std/function/function_template.h +++ b/Code/Framework/AzCore/AzCore/std/function/function_template.h @@ -13,11 +13,6 @@ #include #include -#if defined(AZ_COMPILER_MSVC) -# pragma warning( push ) -# pragma warning( disable : 4127 ) // "conditional expression is constant" -#endif - namespace AZStd { namespace Internal @@ -689,7 +684,3 @@ namespace AZStd } }; } // end namespace AZStd - -#if defined(AZ_COMPILER_MSVC) -# pragma warning( pop ) -#endif diff --git a/Code/Framework/AzCore/AzCore/std/parallel/containers/internal/concurrent_hash_table.h b/Code/Framework/AzCore/AzCore/std/parallel/containers/internal/concurrent_hash_table.h index 524eff7e64..c8fc709778 100644 --- a/Code/Framework/AzCore/AzCore/std/parallel/containers/internal/concurrent_hash_table.h +++ b/Code/Framework/AzCore/AzCore/std/parallel/containers/internal/concurrent_hash_table.h @@ -489,24 +489,26 @@ namespace AZStd { return; } - - float loadFactor = (float)m_numElements.load(memory_order_acquire) / (float)m_storage.get_num_buckets(); - if (loadFactor > max_load_factor()) + else { - acquire_all(); - - //check the load factor again, as another thread may have beaten us to the rehash - size_type numElements = m_numElements.load(memory_order_acquire); - float maxLoadFactor = max_load_factor(); - size_type numBuckets = m_storage.get_num_buckets(); - loadFactor = (float)numElements / (float)numBuckets; - if (loadFactor > maxLoadFactor) + float loadFactor = (float)m_numElements.load(memory_order_acquire) / (float)m_storage.get_num_buckets(); + if (loadFactor > max_load_factor()) { - size_type minNumBuckets = (size_type)((float)numElements / maxLoadFactor); - m_storage.rehash(this, minNumBuckets); - } + acquire_all(); - release_all(); + // check the load factor again, as another thread may have beaten us to the rehash + size_type numElements = m_numElements.load(memory_order_acquire); + float maxLoadFactor = max_load_factor(); + size_type numBuckets = m_storage.get_num_buckets(); + loadFactor = (float)numElements / (float)numBuckets; + if (loadFactor > maxLoadFactor) + { + size_type minNumBuckets = (size_type)((float)numElements / maxLoadFactor); + m_storage.rehash(this, minNumBuckets); + } + + release_all(); + } } } diff --git a/Code/Framework/AzCore/AzCore/std/smart_ptr/weak_ptr.h b/Code/Framework/AzCore/AzCore/std/smart_ptr/weak_ptr.h index aaaf90e8f7..80dee72d03 100644 --- a/Code/Framework/AzCore/AzCore/std/smart_ptr/weak_ptr.h +++ b/Code/Framework/AzCore/AzCore/std/smart_ptr/weak_ptr.h @@ -192,9 +192,5 @@ namespace AZStd } } // namespace AZStd -/*#ifdef AZ_COMPILER_MSVC -# pragma warning(pop) -#endif */ - #endif // #ifndef AZSTD_SMART_PTR_WEAK_PTR_H #pragma once diff --git a/Code/Framework/AzCore/AzCore/std/string/regex.h b/Code/Framework/AzCore/AzCore/std/string/regex.h index 2c120436d5..2ca223937b 100644 --- a/Code/Framework/AzCore/AzCore/std/string/regex.h +++ b/Code/Framework/AzCore/AzCore/std/string/regex.h @@ -22,11 +22,6 @@ // used for std::pointer_traits \note do an AZStd version #include -#if defined(AZ_COMPILER_MSVC) -# pragma warning(push) -# pragma warning(disable: 6011 28198) -#endif // AZ_COMPILER_MSVC - #ifndef AZ_REGEX_MAX_COMPLEXITY_COUNT #define AZ_REGEX_MAX_COMPLEXITY_COUNT 10000000L /* set to 0 to disable */ #endif /* AZ_REGEX_MAX_COMPLEXITY_COUNT */ @@ -4766,7 +4761,3 @@ namespace AZStd Trans(); } } // namespace AZStd - -#if defined(AZ_COMPILER_MSVC) -# pragma warning(pop) -#endif // AZ_COMPILER_MSVC diff --git a/Code/Framework/AzCore/Tests/Jobs.cpp b/Code/Framework/AzCore/Tests/Jobs.cpp index 4a1af4cc24..0eb46a0051 100644 --- a/Code/Framework/AzCore/Tests/Jobs.cpp +++ b/Code/Framework/AzCore/Tests/Jobs.cpp @@ -1736,7 +1736,7 @@ namespace Benchmark std::numeric_limits::max()); std::generate(m_randomPriorities.begin(), m_randomPriorities.end(), [&randomPriorityDistribution, &randomPriorityGenerator]() { - return randomPriorityDistribution(randomPriorityGenerator); + return static_cast(randomPriorityDistribution(randomPriorityGenerator)); }); // Generate some random depths diff --git a/Code/Framework/AzCore/Tests/Serialization/Json/MathMatrixSerializerTests.cpp b/Code/Framework/AzCore/Tests/Serialization/Json/MathMatrixSerializerTests.cpp index ca558d1624..1126aeb662 100644 --- a/Code/Framework/AzCore/Tests/Serialization/Json/MathMatrixSerializerTests.cpp +++ b/Code/Framework/AzCore/Tests/Serialization/Json/MathMatrixSerializerTests.cpp @@ -225,7 +225,6 @@ namespace JsonSerializationTests static_assert((RowCount >= 3 && RowCount <= 4) && (ColumnCount >= 3 && ColumnCount <= 4), "Only matrix 3x3, 3x4 or 4x4 are supported by this test."); } - return "{}"; } void ConfigureFeatures(JsonSerializerConformityTestDescriptorFeatures& features) override From 3eb658534b3c0596ee32c94b49fc0ae59dd10ade Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Mon, 16 Aug 2021 15:55:06 -0700 Subject: [PATCH 468/803] More Code/Framework Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../AzFramework/AzFramework/Archive/Archive.cpp | 13 ++++--------- .../AzFramework/Physics/Common/PhysicsTypes.h | 2 +- .../AzNetworking/Utilities/QuantizedValues.h | 2 +- .../AzNetworking/Utilities/QuantizedValues.inl | 9 +-------- .../AzQtComponents/Components/Widgets/SliderCombo.h | 4 ++++ .../Tests/Prefab/Benchmark/PrefabLoadBenchmarks.cpp | 2 +- 6 files changed, 12 insertions(+), 20 deletions(-) diff --git a/Code/Framework/AzFramework/AzFramework/Archive/Archive.cpp b/Code/Framework/AzFramework/AzFramework/Archive/Archive.cpp index a0dda9f692..962c82614f 100644 --- a/Code/Framework/AzFramework/AzFramework/Archive/Archive.cpp +++ b/Code/Framework/AzFramework/AzFramework/Archive/Archive.cpp @@ -347,17 +347,12 @@ namespace AZ::IO::ArchiveInternal return EOF; } int c = EOF; - int i; - for (i = 0; i < 1; i++) + if (m_nCurSeek == GetFileSize()) { - if (i + m_nCurSeek == GetFileSize()) - { - return c; - } - c = pData[i + m_nCurSeek]; - break; + return c; } - m_nCurSeek += i + 1; + c = pData[m_nCurSeek]; + m_nCurSeek += 1; return c; } } diff --git a/Code/Framework/AzFramework/AzFramework/Physics/Common/PhysicsTypes.h b/Code/Framework/AzFramework/AzFramework/Physics/Common/PhysicsTypes.h index bb53d6d3dd..30f3fb6297 100644 --- a/Code/Framework/AzFramework/AzFramework/Physics/Common/PhysicsTypes.h +++ b/Code/Framework/AzFramework/AzFramework/Physics/Common/PhysicsTypes.h @@ -56,7 +56,7 @@ namespace AzPhysics //! A handle to a Scene within the physics simulation. //! A SceneHandle is a tuple of a Crc of the scenes name and the index in the Scene list. using SceneHandle = AZStd::tuple; - static constexpr SceneHandle InvalidSceneHandle = { AZ::Crc32(), -1 }; + static constexpr SceneHandle InvalidSceneHandle = { AZ::Crc32(), AZ::s8(-1) }; //! Ease of use type for referencing a List of SceneHandle objects. using SceneHandleList = AZStd::vector; diff --git a/Code/Framework/AzNetworking/AzNetworking/Utilities/QuantizedValues.h b/Code/Framework/AzNetworking/AzNetworking/Utilities/QuantizedValues.h index 190a32ddc7..46e778d5b3 100644 --- a/Code/Framework/AzNetworking/AzNetworking/Utilities/QuantizedValues.h +++ b/Code/Framework/AzNetworking/AzNetworking/Utilities/QuantizedValues.h @@ -176,7 +176,7 @@ namespace AzNetworking //! Takes a quantized integral value and stores the floating point representation. void DecodeQuantizedValues(); - AZ_PUSH_DISABLE_WARNING(4201 4324, "-Wunknown-warning-option") // anonymous union, structure was padded due to alignment + AZ_PUSH_DISABLE_WARNING(4324, "-Wunknown-warning-option") // anonymous union, structure was padded due to alignment union { float m_quantizedValues[NUM_ELEMENTS]; diff --git a/Code/Framework/AzNetworking/AzNetworking/Utilities/QuantizedValues.inl b/Code/Framework/AzNetworking/AzNetworking/Utilities/QuantizedValues.inl index b0a424d48a..86e736928a 100644 --- a/Code/Framework/AzNetworking/AzNetworking/Utilities/QuantizedValues.inl +++ b/Code/Framework/AzNetworking/AzNetworking/Utilities/QuantizedValues.inl @@ -218,14 +218,7 @@ namespace AzNetworking { SerializeType serializedValue = static_cast(m_serializeValues[i]); -#ifdef AZ_COMPILER_MSVC -# pragma warning(push) -# pragma warning(disable: 4127) // conditional expression is constant -#endif - if (NUM_BYTES == 3) -#ifdef AZ_COMPILER_MSVC -# pragma warning(pop) -#endif + if constexpr (NUM_BYTES == 3) { uint8_t lowByte = static_cast((serializedValue & 0x000000FF) ); uint8_t midByte = static_cast((serializedValue & 0x0000FF00) >> 8); diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/SliderCombo.h b/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/SliderCombo.h index 7baa386784..2646162af4 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/SliderCombo.h +++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/SliderCombo.h @@ -40,6 +40,8 @@ namespace AzQtComponents //! Current value. Q_PROPERTY(int value READ value WRITE setValue NOTIFY valueChanged) public: + using value_type = int; + explicit SliderCombo(QWidget *parent = nullptr); ~SliderCombo(); @@ -142,6 +144,8 @@ namespace AzQtComponents Q_PROPERTY(double curveMidpoint READ curveMidpoint WRITE setCurveMidpoint) public: + using value_type = double; + explicit SliderDoubleCombo(QWidget *parent = nullptr); ~SliderDoubleCombo(); diff --git a/Code/Framework/AzToolsFramework/Tests/Prefab/Benchmark/PrefabLoadBenchmarks.cpp b/Code/Framework/AzToolsFramework/Tests/Prefab/Benchmark/PrefabLoadBenchmarks.cpp index a6c1e27caf..dd29654416 100644 --- a/Code/Framework/AzToolsFramework/Tests/Prefab/Benchmark/PrefabLoadBenchmarks.cpp +++ b/Code/Framework/AzToolsFramework/Tests/Prefab/Benchmark/PrefabLoadBenchmarks.cpp @@ -16,7 +16,7 @@ namespace Benchmark BENCHMARK_DEFINE_F(BM_PrefabLoad, LoadPrefab_Basic)(::benchmark::State& state) { - const unsigned int numTemplates = state.range(); + const unsigned int numTemplates = static_cast(state.range()); CreateFakePaths(numTemplates); for (auto _ : state) From 14990012f812693ea5698e42bed239c06b543745 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Mon, 16 Aug 2021 15:55:20 -0700 Subject: [PATCH 469/803] Code/Legacy Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Legacy/CrySystem/CmdLine.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Code/Legacy/CrySystem/CmdLine.cpp b/Code/Legacy/CrySystem/CmdLine.cpp index 50b8b2c092..702709ffe5 100644 --- a/Code/Legacy/CrySystem/CmdLine.cpp +++ b/Code/Legacy/CrySystem/CmdLine.cpp @@ -192,7 +192,6 @@ AZStd::string CCmdLine::Next(char*& src) return AZStd::string(org, src); } - ch = *src++; } return AZStd::string(); From b255334535b61c632adb6a803eac0791007d678f Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Mon, 16 Aug 2021 15:55:41 -0700 Subject: [PATCH 470/803] Code/Tools fixes Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../AssetProcessor/AssetBuilder/AssetBuilderComponent.cpp | 2 +- .../native/tests/resourcecompiler/RCBuilderTest.cpp | 2 +- .../native/unittests/RCcontrollerUnitTests.cpp | 2 +- .../native/utilities/BatchApplicationServer.cpp | 2 +- .../native/utilities/PlatformConfiguration.cpp | 4 ++-- .../native/utilities/UnitTestShaderCompilerServer.cpp | 2 +- .../ProjectManager/Source/GemCatalog/GemItemDelegate.cpp | 8 ++++---- .../Source/GemCatalog/GemRequirementDelegate.cpp | 6 +++--- Code/Tools/ProjectManager/Source/ProjectUtils.cpp | 6 +++--- Code/Tools/ProjectManager/Source/PythonBindings.cpp | 2 -- .../Artifact/Factory/TestImpactTestRunSuiteFactory.cpp | 2 +- 11 files changed, 18 insertions(+), 20 deletions(-) diff --git a/Code/Tools/AssetProcessor/AssetBuilder/AssetBuilderComponent.cpp b/Code/Tools/AssetProcessor/AssetBuilder/AssetBuilderComponent.cpp index 7702cc259d..eb6cc4033c 100644 --- a/Code/Tools/AssetProcessor/AssetBuilder/AssetBuilderComponent.cpp +++ b/Code/Tools/AssetProcessor/AssetBuilder/AssetBuilderComponent.cpp @@ -337,7 +337,7 @@ bool AssetBuilderComponent::ConnectToAssetProcessor() AZStd::string overridePort; if (GetParameter(s_paramPort, overridePort, false)) { - connectionSettings.m_assetProcessorPort = AZStd::stoi(overridePort); + connectionSettings.m_assetProcessorPort = static_cast(AZStd::stoi(overridePort)); } //the asset builder may have been given an optional asset platform to use diff --git a/Code/Tools/AssetProcessor/native/tests/resourcecompiler/RCBuilderTest.cpp b/Code/Tools/AssetProcessor/native/tests/resourcecompiler/RCBuilderTest.cpp index 7a78786258..2465be2b33 100644 --- a/Code/Tools/AssetProcessor/native/tests/resourcecompiler/RCBuilderTest.cpp +++ b/Code/Tools/AssetProcessor/native/tests/resourcecompiler/RCBuilderTest.cpp @@ -814,7 +814,7 @@ public: AssetRecognizer good; good.m_name = "Good"; - good.m_version = versionNumber; + good.m_version = static_cast(versionNumber); good.m_patternMatcher = AssetBuilderSDK::FilePatternMatcher("*.foo", AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard); good.m_platformSpecs["pc"] = good_spec; good.m_productAssetType = builderProductType; diff --git a/Code/Tools/AssetProcessor/native/unittests/RCcontrollerUnitTests.cpp b/Code/Tools/AssetProcessor/native/unittests/RCcontrollerUnitTests.cpp index a3f5c117ea..0f5fea5eb9 100644 --- a/Code/Tools/AssetProcessor/native/unittests/RCcontrollerUnitTests.cpp +++ b/Code/Tools/AssetProcessor/native/unittests/RCcontrollerUnitTests.cpp @@ -147,7 +147,7 @@ void RCcontrollerUnitTests::RunRCControllerTests() if (returnedCount != expectedCount) { - Q_EMIT UnitTestFailed("RCJobListModel has " + QString(returnedCount) + " elements, which is invalid. Expected " + expectedCount); + Q_EMIT UnitTestFailed("RCJobListModel has " + QString(returnedCount) + " elements, which is invalid. Expected " + QString(expectedCount)); return; } diff --git a/Code/Tools/AssetProcessor/native/utilities/BatchApplicationServer.cpp b/Code/Tools/AssetProcessor/native/utilities/BatchApplicationServer.cpp index 8a7974c615..e7ebc030e6 100644 --- a/Code/Tools/AssetProcessor/native/utilities/BatchApplicationServer.cpp +++ b/Code/Tools/AssetProcessor/native/utilities/BatchApplicationServer.cpp @@ -38,7 +38,7 @@ bool BatchApplicationServer::startListening(unsigned short port) // Since we're starting up builders ourselves and informing them of the port chosen, we can scan for a free port - while (!listen(QHostAddress::Any, m_serverListeningPort)) + while (!listen(QHostAddress::Any, static_cast(m_serverListeningPort))) { auto error = serverError(); diff --git a/Code/Tools/AssetProcessor/native/utilities/PlatformConfiguration.cpp b/Code/Tools/AssetProcessor/native/utilities/PlatformConfiguration.cpp index 782e145ad6..07106614cf 100644 --- a/Code/Tools/AssetProcessor/native/utilities/PlatformConfiguration.cpp +++ b/Code/Tools/AssetProcessor/native/utilities/PlatformConfiguration.cpp @@ -197,7 +197,7 @@ namespace AssetProcessor } else if (valueName == "order") { - scanFolderEntry.m_scanOrder = value; + scanFolderEntry.m_scanOrder = static_cast(value); } } @@ -475,7 +475,7 @@ namespace AssetProcessor RCAssetRecognizer& assetRecognizer = *assetRecognizerEntryIt; if (valueName == "priority") { - assetRecognizer.m_recognizer.m_priority = value; + assetRecognizer.m_recognizer.m_priority = static_cast(value); } } diff --git a/Code/Tools/AssetProcessor/native/utilities/UnitTestShaderCompilerServer.cpp b/Code/Tools/AssetProcessor/native/utilities/UnitTestShaderCompilerServer.cpp index 18e1730de5..88e8520e3c 100644 --- a/Code/Tools/AssetProcessor/native/utilities/UnitTestShaderCompilerServer.cpp +++ b/Code/Tools/AssetProcessor/native/utilities/UnitTestShaderCompilerServer.cpp @@ -49,7 +49,7 @@ void UnitTestShaderCompilerServer::startServer() { if (!m_server->isListening()) { - if (!m_server->listen(QHostAddress(m_serverAddress), m_serverPort)) + if (!m_server->listen(QHostAddress(m_serverAddress), static_cast(m_serverPort))) { AZ_TracePrintf(AssetProcessor::DebugChannel, "Server %s could not start.\n", m_serverAddress.toUtf8().data()); emit errorMessage("Server could not start "); diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.cpp index 08e08afdd5..21bb56daef 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.cpp @@ -29,7 +29,7 @@ namespace O3DE::ProjectManager { QPixmap pixmap(iconPath); qreal aspectRatio = static_cast(pixmap.width()) / pixmap.height(); - m_platformIcons.insert(platform, QIcon(iconPath).pixmap(s_platformIconSize * aspectRatio, s_platformIconSize)); + m_platformIcons.insert(platform, QIcon(iconPath).pixmap(static_cast(static_cast(s_platformIconSize) * aspectRatio), s_platformIconSize)); } void GemItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& modelIndex) const @@ -48,7 +48,7 @@ namespace O3DE::ProjectManager CalcRects(options, fullRect, itemRect, contentRect); QFont standardFont(options.font); - standardFont.setPixelSize(s_fontSize); + standardFont.setPixelSize(static_cast(s_fontSize)); QFontMetrics standardFontMetrics(standardFont); painter->save(); @@ -78,7 +78,7 @@ namespace O3DE::ProjectManager QString gemName = GemModel::GetName(modelIndex); QFont gemNameFont(options.font); const int firstColumnMaxTextWidth = s_summaryStartX - 30; - gemNameFont.setPixelSize(s_gemNameFontSize); + gemNameFont.setPixelSize(static_cast(s_gemNameFontSize)); gemNameFont.setBold(true); gemName = QFontMetrics(gemNameFont).elidedText(gemName, Qt::TextElideMode::ElideRight, firstColumnMaxTextWidth); QRect gemNameRect = GetTextRect(gemNameFont, gemName, s_gemNameFontSize); @@ -178,7 +178,7 @@ namespace O3DE::ProjectManager QRect GemItemDelegate::GetTextRect(QFont& font, const QString& text, qreal fontSize) const { - font.setPixelSize(fontSize); + font.setPixelSize(static_cast(fontSize)); return QFontMetrics(font).boundingRect(text); } diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemRequirementDelegate.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemRequirementDelegate.cpp index 655f6055f1..0d5f752858 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemRequirementDelegate.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemRequirementDelegate.cpp @@ -35,7 +35,7 @@ namespace O3DE::ProjectManager CalcRects(options, fullRect, itemRect, contentRect); QFont standardFont(options.font); - standardFont.setPixelSize(s_fontSize); + standardFont.setPixelSize(static_cast(s_fontSize)); QFontMetrics standardFontMetrics(standardFont); painter->save(); @@ -55,10 +55,10 @@ namespace O3DE::ProjectManager QFont gemNameFont(options.font); const int firstColumnMaxTextWidth = s_summaryStartX - 30; gemName = QFontMetrics(gemNameFont).elidedText(gemName, Qt::TextElideMode::ElideRight, firstColumnMaxTextWidth); - gemNameFont.setPixelSize(s_gemNameFontSize); + gemNameFont.setPixelSize(static_cast(s_gemNameFontSize)); gemNameFont.setBold(true); QRect gemNameRect = GetTextRect(gemNameFont, gemName, s_gemNameFontSize); - gemNameRect.moveTo(contentRect.left(), contentRect.center().y() - s_gemNameFontSize); + gemNameRect.moveTo(contentRect.left(), contentRect.center().y() - static_cast(s_gemNameFontSize)); painter->setFont(gemNameFont); painter->setPen(m_textColor); diff --git a/Code/Tools/ProjectManager/Source/ProjectUtils.cpp b/Code/Tools/ProjectManager/Source/ProjectUtils.cpp index fb0ea23ece..fb3f7e0270 100644 --- a/Code/Tools/ProjectManager/Source/ProjectUtils.cpp +++ b/Code/Tools/ProjectManager/Source/ProjectUtils.cpp @@ -117,7 +117,7 @@ namespace O3DE::ProjectManager const int updateStatusEvery = 64; if (outFileCount % updateStatusEvery == 0) { - statusCallback(outFileCount, outTotalSizeInBytes); + statusCallback(outFileCount, static_cast(outTotalSizeInBytes)); } } } @@ -163,7 +163,7 @@ namespace O3DE::ProjectManager } QLocale locale; - const float progressDialogRangeHalf = qFabs(progressDialog->maximum() - progressDialog->minimum()) * 0.5f; + const float progressDialogRangeHalf = static_cast(qFabs(progressDialog->maximum() - progressDialog->minimum()) * 0.5f); for (const QString& file : original.entryList(QDir::Files)) { if (progressDialog->wasCanceled()) @@ -184,7 +184,7 @@ namespace O3DE::ProjectManager // for cases combining many small files and some really large files. const float normalizedNumFiles = static_cast(outNumCopiedFiles) / filesToCopyCount; const float normalizedFileSize = static_cast(outCopiedFileSize) / totalSizeToCopy; - const int progress = normalizedNumFiles * progressDialogRangeHalf + normalizedFileSize * progressDialogRangeHalf; + const int progress = static_cast(normalizedNumFiles * progressDialogRangeHalf + normalizedFileSize * progressDialogRangeHalf); progressDialog->setValue(progress); const QString copiedFileSizeString = locale.formattedDataSize(outCopiedFileSize); diff --git a/Code/Tools/ProjectManager/Source/PythonBindings.cpp b/Code/Tools/ProjectManager/Source/PythonBindings.cpp index 8bdfb0f152..18901946f3 100644 --- a/Code/Tools/ProjectManager/Source/PythonBindings.cpp +++ b/Code/Tools/ProjectManager/Source/PythonBindings.cpp @@ -434,8 +434,6 @@ namespace O3DE::ProjectManager { return AZ::Success(AZStd::move(engineInfo)); } - - return AZ::Failure(); } bool PythonBindings::SetEngineInfo(const EngineInfo& engineInfo) diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Source/Artifact/Factory/TestImpactTestRunSuiteFactory.cpp b/Code/Tools/TestImpactFramework/Runtime/Code/Source/Artifact/Factory/TestImpactTestRunSuiteFactory.cpp index 5fe7c08535..f5d7d3a8a2 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Source/Artifact/Factory/TestImpactTestRunSuiteFactory.cpp +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Source/Artifact/Factory/TestImpactTestRunSuiteFactory.cpp @@ -95,7 +95,7 @@ namespace TestImpact const auto getResult = [](const AZ::rapidxml::xml_node<>* node) { - for (auto child_node = node->first_node("failure"); child_node; child_node = child_node->next_sibling()) + if (auto child_node = node->first_node("failure")) { return TestRunResult::Failed; } From 8cef306efb7e3d26fc09390f153b3a454d263837 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Mon, 16 Aug 2021 15:55:56 -0700 Subject: [PATCH 471/803] Code/Editor Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Editor/Util/Contrib/NvFloatMath.inl | 1 - Code/Editor/Util/ImageHistogram.cpp | 2 +- Code/Editor/Util/ImageTIF.cpp | 8 ++++---- Code/Editor/Util/PakFile.cpp | 2 +- Code/Editor/Util/VariablePropertyType.cpp | 2 +- 5 files changed, 7 insertions(+), 8 deletions(-) diff --git a/Code/Editor/Util/Contrib/NvFloatMath.inl b/Code/Editor/Util/Contrib/NvFloatMath.inl index 218d77b749..6bd3b9f7c5 100644 --- a/Code/Editor/Util/Contrib/NvFloatMath.inl +++ b/Code/Editor/Util/Contrib/NvFloatMath.inl @@ -103,7 +103,6 @@ it hasn't been integrated into this code drop yet. ** CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#pragma warning(disable:4996) class TVec { diff --git a/Code/Editor/Util/ImageHistogram.cpp b/Code/Editor/Util/ImageHistogram.cpp index 15f6bc2e47..acea2dc340 100644 --- a/Code/Editor/Util/ImageHistogram.cpp +++ b/Code/Editor/Util/ImageHistogram.cpp @@ -220,5 +220,5 @@ void CImageHistogram::ComputeStatisticsForChannel(int aIndex) } } - m_median[aIndex] = median; + m_median[aIndex] = static_cast(median); } diff --git a/Code/Editor/Util/ImageTIF.cpp b/Code/Editor/Util/ImageTIF.cpp index 6544b93c6a..7929d63030 100644 --- a/Code/Editor/Util/ImageTIF.cpp +++ b/Code/Editor/Util/ImageTIF.cpp @@ -79,7 +79,7 @@ libtiffDummySeekProc (thandle_t fd, toff_t off, int i) switch (i) { case SEEK_SET: - memImage->offset = off; + memImage->offset = static_cast(off); break; case SEEK_CUR: @@ -87,11 +87,11 @@ libtiffDummySeekProc (thandle_t fd, toff_t off, int i) break; case SEEK_END: - memImage->offset = memImage->size - off; + memImage->offset = static_cast(memImage->size - off); break; default: - memImage->offset = off; + memImage->offset = static_cast(off); break; } @@ -262,7 +262,7 @@ bool CImageTIF::Load(const QString& fileName, CFloatImage& outImage) } } - uint32 linesize = TIFFScanlineSize(tif); + uint32 linesize = static_cast(TIFFScanlineSize(tif)); uint8* linebuf = static_cast(_TIFFmalloc(linesize)); // We assume that a scanline has all of the samples in it. Validate the assumption. diff --git a/Code/Editor/Util/PakFile.cpp b/Code/Editor/Util/PakFile.cpp index 88d5598495..fc8431ef24 100644 --- a/Code/Editor/Util/PakFile.cpp +++ b/Code/Editor/Util/PakFile.cpp @@ -106,7 +106,7 @@ bool CPakFile::UpdateFile(const char* filename, CCryMemFile& file, bool bCompres { if (m_pArchive) { - int nSize = file.GetLength(); + int nSize = static_cast(file.GetLength()); UpdateFile(filename, file.GetMemPtr(), nSize, bCompress); file.Close(); diff --git a/Code/Editor/Util/VariablePropertyType.cpp b/Code/Editor/Util/VariablePropertyType.cpp index 17c80a505c..3f472dde72 100644 --- a/Code/Editor/Util/VariablePropertyType.cpp +++ b/Code/Editor/Util/VariablePropertyType.cpp @@ -171,7 +171,7 @@ namespace Prop { // Limit step size to 1000. int nPrec = max(3 - int(log(m_rangeMax - m_rangeMin) / log(10.f)), 0); - m_step = max(m_step, powf(10.f, -nPrec)); + m_step = max(m_step, powf(10.f, static_cast(-nPrec))); } } From e6b5342c0765cbc9dce339d39951dbf79a08af3e Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Mon, 16 Aug 2021 15:56:10 -0700 Subject: [PATCH 472/803] Gems/Atom Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../Code/Source/Converters/Cubemap.cpp | 10 +++---- .../Code/Tests/ImageProcessing_Test.cpp | 5 ++-- .../External/CubeMapGen/CCubeMapProcessor.cpp | 30 +++++++++---------- .../External/CubeMapGen/CImageSurface.cpp | 2 +- .../External/CubeMapGen/VectorMacros.h | 2 +- .../DirectionalLightFeatureProcessor.cpp | 5 ++-- .../ProjectedShadowFeatureProcessor.cpp | 14 ++++----- .../Window/ToolBar/LightingPresetComboBox.cpp | 4 +-- .../Window/ToolBar/ModelPresetComboBox.cpp | 4 +-- 9 files changed, 39 insertions(+), 37 deletions(-) diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Converters/Cubemap.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Converters/Cubemap.cpp index cd01d955d1..4f13c6f9bf 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Converters/Cubemap.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Converters/Cubemap.cpp @@ -191,7 +191,7 @@ namespace ImageProcessingAtom } //for each pixel in dst image, find it's location in src and copy the data from there - float halfSize = rectSize / 2; + float halfSize = static_cast(rectSize / 2); for (AZ::u32 row = 0; row < rectSize; row++) { for (AZ::u32 col = 0; col < rectSize; col++) @@ -201,8 +201,8 @@ namespace ImageProcessingAtom float dstY = halfSize - row - 0.5f; float srcX = dstX * mtx[0] + dstY * mtx[1]; float srcY = dstX * mtx[2] + dstY * mtx[3]; - AZ::u32 srcCol = srcX + halfSize; - AZ::u32 srcRow = halfSize - srcY; + AZ::u32 srcCol = static_cast(srcX + halfSize); + AZ::u32 srcRow = static_cast(halfSize - srcY); memcpy(&dstImageBuf[(row * rectSize + col) * bytePerPixel], &srcImageBuf[(srcRow * rectSize + srcCol) * bytePerPixel], bytePerPixel); @@ -464,7 +464,7 @@ namespace ImageProcessingAtom else { //transform the image - TransformImage(srcDir, dstDir, buf, tempBuf, sizePerPixel, faceSize); + TransformImage(srcDir, dstDir, buf, tempBuf, static_cast(sizePerPixel), faceSize); dstCubemap->SetFaceData(face, tempBuf, outSize); } } @@ -649,7 +649,7 @@ namespace ImageProcessingAtom preset.m_cubemapSetting->m_mipSlope, //MipAnglePerLevelScale, (int)preset.m_cubemapSetting->m_filter, //FilterType, CP_FILTER_TYPE_COSINE for diffuse cube preset.m_cubemapSetting->m_edgeFixup > 0 ? CP_FIXUP_PULL_LINEAR : CP_FIXUP_NONE, //FixupType, CP_FIXUP_PULL_LINEAR if FixupWidth> 0 - preset.m_cubemapSetting->m_edgeFixup, //FixupWidth, + static_cast(preset.m_cubemapSetting->m_edgeFixup), //FixupWidth, true, //bUseSolidAngle, 16, //GlossScale, 0, //GlossBias diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Tests/ImageProcessing_Test.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Tests/ImageProcessing_Test.cpp index 3ac9c334c5..4b28fbe4ef 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Tests/ImageProcessing_Test.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Tests/ImageProcessing_Test.cpp @@ -269,11 +269,11 @@ namespace UnitTest public: //helper function to save an image object to a file through QtImage - static void SaveImageToFile(const IImageObjectPtr imageObject, const AZStd::string imageName, AZ::u32 maxMipCnt = 100) + static void SaveImageToFile([[maybe_unused]] const IImageObjectPtr imageObject, [[maybe_unused]] const AZStd::string imageName, [[maybe_unused]] AZ::u32 maxMipCnt = 100) { #ifndef DEBUG_OUTPUT_IMAGES return; - #endif + #else if (imageObject == nullptr) { return; @@ -314,6 +314,7 @@ namespace UnitTest QImage qimage(imageBuf, width, height, pitch, QImage::Format_RGBA8888); qimage.save(filePath); } + #endif } static bool GetComparisonResult(IImageObjectPtr image1, IImageObjectPtr image2, QString& output) diff --git a/Gems/Atom/Asset/ImageProcessingAtom/External/CubeMapGen/CCubeMapProcessor.cpp b/Gems/Atom/Asset/ImageProcessingAtom/External/CubeMapGen/CCubeMapProcessor.cpp index fa861c739a..8a4d727e8c 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/External/CubeMapGen/CCubeMapProcessor.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/External/CubeMapGen/CCubeMapProcessor.cpp @@ -8,7 +8,7 @@ #include #include -#define CP_PI 3.14159265358979323846 +#define CP_PI 3.14159265358979323846f namespace ImageProcessingAtom @@ -259,10 +259,10 @@ namespace ImageProcessingAtom //get face idx and u, v texel coordinate in face VectToTexelCoord(a_XYZ, a_Surface[0].m_Width, &faceIdx, &u, &v ); - u = VM_MIN((int32)u, a_Surface[0].m_Width - 1); - v = VM_MIN((int32)v, a_Surface[0].m_Width - 1); + u = static_cast(VM_MIN((int32)u, a_Surface[0].m_Width - 1)); + v = static_cast(VM_MIN((int32)v, a_Surface[0].m_Width - 1)); - return( a_Surface[faceIdx].GetSurfaceTexelPtr(u, v) ); + return( a_Surface[faceIdx].GetSurfaceTexelPtr(static_cast(u), static_cast(v)) ); } //-------------------------------------------------------------------------------------- @@ -357,7 +357,7 @@ namespace ImageProcessingAtom VM_XPROD3_UNTYPED(xProdVect, edgeVect0, edgeVect1 ); texelArea += 0.5f * sqrt( VM_DOTPROD3_UNTYPED(xProdVect, xProdVect ) ); - return texelArea; + return static_cast(texelArea); } @@ -1130,7 +1130,7 @@ namespace ImageProcessingAtom // if p0 = 0 and p1 = 1, and d0 and d1 = 0, the interpolation reduces to // // p(t) = - 2t^3 + 3t^2 - fixupWeight = ((-2.0 * fixupFrac + 3.0) * fixupFrac * fixupFrac); + fixupWeight = ((-2.0f * fixupFrac + 3.0f) * fixupFrac * fixupFrac); } break; case CP_FIXUP_AVERAGE_LINEAR: @@ -1147,7 +1147,7 @@ namespace ImageProcessingAtom break; case CP_FIXUP_AVERAGE_HERMITE: { - fixupWeight = ((-2.0 * fixupFrac + 3.0) * fixupFrac * fixupFrac); + fixupWeight = ((-2.0f * fixupFrac + 3.0f) * fixupFrac * fixupFrac); //perform weighted average of edge tap value and current tap // fade off weight using hermite spline with distance from edge @@ -1538,7 +1538,7 @@ namespace ImageProcessingAtom // Find angle for which: cos(a) ^ cosinePower = epsilon const float epsilon = 0.000001f; float angle = acosf(powf(epsilon, 1.0f / cosinePower)); - angle *= 180.0f / (float)CP_PI; + angle *= 180.0f / CP_PI; angle *= 2.0f; return angle; @@ -1555,7 +1555,7 @@ namespace ImageProcessingAtom bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); - return float(bits) * 2.3283064365386963e-10; // float(bits) * 2^-32 + return float(bits) * 2.3283064365386963e-10f; // float(bits) * 2^-32 } inline void HammersleySequence(uint32 sampleIndex, uint32 sampleCount, float* vXi) @@ -1668,7 +1668,7 @@ namespace ImageProcessingAtom float mip = 0.5f * log2f(solidAngleSample / solidAngleTexel) + 1.0f; //determine surrounding mip levels - uint32 mipA = floor(mip); + uint32 mipA = static_cast(floor(mip)); uint32 mipB = mipA + 1; float lerp = 0.0f; VM_CLAMP(lerp, mip - mipA, 0.0f, 1.0f); @@ -1819,7 +1819,7 @@ namespace ImageProcessingAtom float filterAngle; //min angle a src texel can cover (in degrees) - srcTexelAngle = (180.0f / (float)CP_PI) * atan2f(1.0f, (float)a_SrcCubeMapWidth); + srcTexelAngle = (180.0f / CP_PI) * atan2f(1.0f, (float)a_SrcCubeMapWidth); //filter angle is 1/2 the cone angle filterAngle = a_FilterConeAngle / 2.0f; @@ -1870,7 +1870,7 @@ namespace ImageProcessingAtom const int32 dstSize = a_DstCubeMap[0].m_Width; //min angle a src texel can cover (in degrees) - const float srcTexelAngle = (180.0f / (float)CP_PI) * atan2f(1.0f, (float)srcSize); + const float srcTexelAngle = (180.0f / CP_PI) * atan2f(1.0f, (float)srcSize); //angle about center tap to define filter cone float filterAngle; @@ -1897,7 +1897,7 @@ namespace ImageProcessingAtom //dotProdThresh threshold based on cone angle to determine whether or not taps // reside within the cone angle - const float dotProdThresh = cosf( ((float)CP_PI / 180.0f) * filterAngle ); + const float dotProdThresh = cosf( (CP_PI / 180.0f) * filterAngle ); //thread progress m_ThreadProgress[a_ThreadIdx].m_StartFace = a_FaceIdxStart; @@ -2004,8 +2004,8 @@ namespace ImageProcessingAtom else if( a_FilterType == CP_FILTER_TYPE_ANGULAR_GAUSSIAN ) { //fit 3 standard deviations within angular extent of filter - CP_ITYPE stdDev = (a_FilterAngle * CP_PI / 180.0) / 3.0; - CP_ITYPE inv2Variance = 1.0 / (2.0 * stdDev * stdDev); + CP_ITYPE stdDev = (a_FilterAngle * CP_PI / 180.0f) / 3.0f; + CP_ITYPE inv2Variance = 1.0f / (2.0f * stdDev * stdDev); for(iLUTEntry=0; iLUTEntry>= (23 - 10); //assemble s10e5 number using logical operations - rawf16Data = (signVal << 15) | (exponent << 10) | mantissa; + rawf16Data = static_cast((signVal << 15) | (exponent << 10) | mantissa); //return re-assembled raw data as a 32 bit float return rawf16Data; diff --git a/Gems/Atom/Asset/ImageProcessingAtom/External/CubeMapGen/VectorMacros.h b/Gems/Atom/Asset/ImageProcessingAtom/External/CubeMapGen/VectorMacros.h index 0db22d03d6..42ec07e02c 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/External/CubeMapGen/VectorMacros.h +++ b/Gems/Atom/Asset/ImageProcessingAtom/External/CubeMapGen/VectorMacros.h @@ -125,7 +125,7 @@ //normalize vectors #define VM_NORM3_UNTYPED(d, s) {double __idsq; __idsq=1.0/sqrt(VM_DOTPROD3_UNTYPED(s,s)); d[0]=s[0]*__idsq; d[1]=s[1]*__idsq; d[2]=s[2]*__idsq; } -#define VM_NORM3_UNTYPED_F32(d, s) {float __idsq; __idsq=1.0/sqrt(VM_DOTPROD3_UNTYPED(s,s)); d[0]=s[0]*__idsq; d[1]=s[1]*__idsq; d[2]=s[2]*__idsq; } +#define VM_NORM3_UNTYPED_F32(d, s) {float __idsq; __idsq=1.0f/sqrt(VM_DOTPROD3_UNTYPED(s,s)); d[0]=s[0]*__idsq; d[1]=s[1]*__idsq; d[2]=s[2]*__idsq; } #define VM_NORM3(d, s) VM_NORM3_UNTYPED_F32(((float *)(d)), ((float *)(s))) #define VM_NORM4_UNTYPED(d, s) {double __idsq; __idsq=1.0/sqrt(VM_DOTPROD4_UNTYPED(s,s)); d[0]=s[0]*__idsq; d[1]=s[1]*__idsq; d[2]=s[2]*__idsq; d[3]=s[3]*__idsq; } diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp index 1fff70ce59..6a418117fc 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp @@ -933,9 +933,10 @@ namespace AZ uint16_t DirectionalLightFeatureProcessor::GetCascadeCount(LightHandle handle) const { - for (const auto& segmentIt : m_shadowProperties.GetData(handle.GetIndex()).m_segments) + const auto& segments = m_shadowProperties.GetData(handle.GetIndex()).m_segments; + if (!segments.empty()) { - return aznumeric_cast(segmentIt.second.size()); + return aznumeric_cast(segments.begin()->second.size()); } return 0; } diff --git a/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.cpp index 5a25951163..0e42c5520e 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.cpp @@ -539,9 +539,10 @@ namespace AZ::Render { esmPass->QueueForBuildAndInitialization(); } - - for (ProjectedShadowmapsPass* shadowPass : m_projectedShadowmapsPasses) + + if (!m_projectedShadowmapsPasses.empty()) { + const ProjectedShadowmapsPass* shadowPass = m_projectedShadowmapsPasses.front(); for (const auto& shadowProperty : shadowProperties) { const int16_t shadowIndexInSrg = shadowProperty.m_shadowId.GetIndex(); @@ -553,7 +554,6 @@ namespace AZ::Render filterData.m_shadowmapOriginInSlice = origin.m_originInSlice; m_deviceBufferNeedsUpdate = true; } - break; } m_shadowmapPassNeedsUpdate = false; @@ -571,8 +571,9 @@ namespace AZ::Render void ProjectedShadowFeatureProcessor::PrepareViews(const PrepareViewsPacket&, AZStd::vector>& outViews) { - for (ProjectedShadowmapsPass* pass : m_projectedShadowmapsPasses) + if (!m_projectedShadowmapsPasses.empty()) { + ProjectedShadowmapsPass* pass = m_projectedShadowmapsPasses.front(); RPI::RenderPipeline* renderPipeline = pass->GetRenderPipeline(); if (renderPipeline) { @@ -598,7 +599,6 @@ namespace AZ::Render outViews.emplace_back(AZStd::make_pair(viewTag, shadowProperty.m_shadowmapView)); } } - break; } } @@ -606,8 +606,9 @@ namespace AZ::Render { AZ_ATOM_PROFILE_FUNCTION("RPI", "ProjectedShadowFeatureProcessor: Render"); - for (const ProjectedShadowmapsPass* pass : m_projectedShadowmapsPasses) + if (!m_projectedShadowmapsPasses.empty()) { + const ProjectedShadowmapsPass* pass = m_projectedShadowmapsPasses.front(); for (const RPI::ViewPtr& view : packet.m_views) { if (view->GetUsageFlags() & RPI::View::UsageFlags::UsageCamera) @@ -622,7 +623,6 @@ namespace AZ::Render m_filterParamBufferHandler.UpdateSrg(srg); } } - break; } } diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ToolBar/LightingPresetComboBox.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ToolBar/LightingPresetComboBox.cpp index c034977aac..e0bb59cb82 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ToolBar/LightingPresetComboBox.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ToolBar/LightingPresetComboBox.cpp @@ -61,7 +61,7 @@ namespace MaterialEditor auto presetItr = AZStd::find(m_presets.begin(), m_presets.end(), preset); if (presetItr != m_presets.end()) { - setCurrentIndex(AZStd::distance(m_presets.begin(), presetItr)); + setCurrentIndex(static_cast(AZStd::distance(m_presets.begin(), presetItr))); } } @@ -80,7 +80,7 @@ namespace MaterialEditor auto presetItr = AZStd::find(m_presets.begin(), m_presets.end(), preset); if (presetItr != m_presets.end()) { - setItemText(AZStd::distance(m_presets.begin(), presetItr), preset->m_displayName.c_str()); + setItemText(static_cast(AZStd::distance(m_presets.begin(), presetItr)), preset->m_displayName.c_str()); } else { diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ToolBar/ModelPresetComboBox.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ToolBar/ModelPresetComboBox.cpp index 30b88f6f47..1e8bfec485 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ToolBar/ModelPresetComboBox.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ToolBar/ModelPresetComboBox.cpp @@ -61,7 +61,7 @@ namespace MaterialEditor auto presetItr = AZStd::find(m_presets.begin(), m_presets.end(), preset); if (presetItr != m_presets.end()) { - setCurrentIndex(AZStd::distance(m_presets.begin(), presetItr)); + setCurrentIndex(static_cast(AZStd::distance(m_presets.begin(), presetItr))); } } @@ -80,7 +80,7 @@ namespace MaterialEditor auto presetItr = AZStd::find(m_presets.begin(), m_presets.end(), preset); if (presetItr != m_presets.end()) { - setItemText(AZStd::distance(m_presets.begin(), presetItr), preset->m_displayName.c_str()); + setItemText(static_cast(AZStd::distance(m_presets.begin(), presetItr)), preset->m_displayName.c_str()); } else { From 29637392883b9138b01f149c008ca3364e4b7a76 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Mon, 16 Aug 2021 15:56:36 -0700 Subject: [PATCH 473/803] Code/Editor Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Editor/2DViewport.cpp | 80 ++++++++++--------- Code/Editor/Controls/ColorGradientCtrl.cpp | 7 +- Code/Editor/Controls/ConsoleSCB.cpp | 10 +-- Code/Editor/Controls/ImageHistogramCtrl.cpp | 20 ++--- .../Controls/QBitmapPreviewDialogImp.cpp | 4 +- .../ReflectedPropertyCtrl.cpp | 2 +- .../ReflectedVarWrapper.cpp | 28 +++---- Code/Editor/Controls/SplineCtrl.cpp | 4 +- Code/Editor/Controls/SplineCtrlEx.cpp | 18 ++--- Code/Editor/Controls/TimelineCtrl.cpp | 14 ++-- Code/Editor/CryEditDoc.cpp | 2 +- Code/Editor/DisplaySettings.cpp | 6 +- ...bjectSelectionReferenceFrameCalculator.cpp | 4 +- .../EditorPreferencesPageViewportGeneral.cpp | 36 +++++---- Code/Editor/EditorViewportWidget.cpp | 40 ++++++---- Code/Editor/ErrorReportTableModel.cpp | 6 +- Code/Editor/Export/ExportManager.cpp | 11 +-- Code/Editor/FBXExporterDialog.cpp | 4 +- Code/Editor/Geometry/TriMesh.cpp | 10 +-- Code/Editor/GotoPositionDlg.cpp | 2 +- Code/Editor/LogFile.cpp | 2 +- Code/Editor/Objects/BaseObject.cpp | 20 ++--- Code/Editor/Objects/SelectionGroup.cpp | 2 +- Code/Editor/Plugin.cpp | 2 +- Code/Editor/PluginManager.cpp | 2 +- .../Objects/ComponentEntityObject.cpp | 4 +- .../SandboxIntegration.cpp | 8 +- .../UI/Outliner/OutlinerListModel.cpp | 10 +-- .../UI/Outliner/OutlinerTreeView.cpp | 6 +- .../AssetImporterWindow.cpp | 4 +- Code/Editor/PythonEditorFuncs.cpp | 8 +- Code/Editor/QtUI/PixmapLabelPreview.cpp | 2 +- Code/Editor/QtViewPaneManager.cpp | 4 +- Code/Editor/Settings.cpp | 2 +- Code/Editor/ToolBox.cpp | 5 +- .../TrackView/SequenceBatchRenderDialog.cpp | 20 ++--- .../TrackView/TVCustomizeTrackColorsDlg.cpp | 2 +- Code/Editor/TrackView/TVSequenceProps.cpp | 12 +-- Code/Editor/TrackView/TrackViewDialog.cpp | 4 +- .../TrackView/TrackViewDopeSheetBase.cpp | 57 ++++++------- Code/Editor/TrackView/TrackViewNodes.cpp | 2 +- Code/Editor/Util/AffineParts.cpp | 46 +++++------ Code/Editor/Util/FileUtil.cpp | 2 +- Code/Editor/Util/GdiUtil.cpp | 37 --------- Code/Editor/Util/GdiUtil.h | 10 --- Code/Editor/Util/ImageASC.cpp | 4 +- Code/Editor/Util/ImageGif.cpp | 4 +- Code/Editor/Util/bitarray.h | 4 +- Code/Editor/ViewPane.cpp | 2 +- Code/Editor/Viewport.cpp | 18 ++--- Code/Editor/ViewportTitleDlg.cpp | 10 +-- 51 files changed, 286 insertions(+), 337 deletions(-) diff --git a/Code/Editor/2DViewport.cpp b/Code/Editor/2DViewport.cpp index 838d30e0b3..ed810aea29 100644 --- a/Code/Editor/2DViewport.cpp +++ b/Code/Editor/2DViewport.cpp @@ -70,9 +70,9 @@ static void OnMenuGrid() inline Vec3 SnapToSize(Vec3 v, double size) { Vec3 snapped; - snapped.x = floor((v.x / size) + 0.5) * size; - snapped.y = floor((v.y / size) + 0.5) * size; - snapped.z = floor((v.z / size) + 0.5) * size; + snapped.x = static_cast(floor((v.x / size) + 0.5) * size); + snapped.y = static_cast(floor((v.y / size) + 0.5) * size); + snapped.z = static_cast(floor((v.z / size) + 0.5) * size); return snapped; } @@ -479,8 +479,8 @@ void Q2DViewport::SetZoom(float fZoomFactor, const QPoint& center) SetZoomFactor(fZoomFactor); // Calculate new offset to center zoom on mouse. - float x2 = center.x(); - float y2 = m_rcClient.height() - center.y(); + float x2 = static_cast(center.x()); + float y2 = static_cast(m_rcClient.height() - center.y()); ofsx = -(x2 / s2 - x2 / s1 - ofsx); ofsy = -(y2 / s2 - y2 / s1 - ofsy); SetScrollOffset(ofsx, ofsy, true); @@ -544,21 +544,21 @@ void Q2DViewport::Update() QPoint Q2DViewport::WorldToView(const Vec3& wp) const { Vec3 sp = m_screenTM.TransformPoint(wp); - QPoint p = QPoint(sp.x, sp.y); + QPoint p = QPoint(static_cast(sp.x), static_cast(sp.y)); return p; } ////////////////////////////////////////////////////////////////////////// QPoint Q2DViewport::WorldToViewParticleEditor(const Vec3& wp, [[maybe_unused]] int width, [[maybe_unused]] int height) const //Eric@conffx implement for the children class of IDisplayViewport { Vec3 sp = m_screenTM.TransformPoint(wp); - QPoint p = QPoint(sp.x, sp.y); + QPoint p = QPoint(static_cast(sp.x), static_cast(sp.y)); return p; } ////////////////////////////////////////////////////////////////////////// Vec3 Q2DViewport::ViewToWorld(const QPoint& vp, [[maybe_unused]] bool* collideWithTerrain, [[maybe_unused]] bool onlyTerrain, [[maybe_unused]] bool bSkipVegetation, [[maybe_unused]] bool bTestRenderMesh, [[maybe_unused]] bool* collideWithObject) const { - Vec3 wp = m_screenTM_Inverted.TransformPoint(Vec3(vp.x(), vp.y(), 0)); + Vec3 wp = m_screenTM_Inverted.TransformPoint(Vec3(static_cast(vp.x()), static_cast(vp.y()), 0.0f)); switch (m_axis) { case VPA_XY: @@ -694,10 +694,10 @@ void Q2DViewport::DrawGrid(DisplayContext& dc, bool bNoXNumbers) Matrix34 viewTM = GetViewTM().GetInverted() * m_screenTM_Inverted; Matrix34 viewTM_Inv = m_screenTM * GetViewTM(); - Vec3 viewP0 = viewTM.TransformPoint(Vec3(0, 0, 0)); - Vec3 viewP1 = viewTM.TransformPoint(Vec3(m_rcClient.width(), m_rcClient.height(), 0)); + Vec3 viewP0 = viewTM.TransformPoint(Vec3(0.0f, 0.0f, 0.0f)); + Vec3 viewP1 = viewTM.TransformPoint(Vec3(static_cast(m_rcClient.width()), static_cast(m_rcClient.height()), 0.0f)); - Vec3 viewP_Text = viewTM.TransformPoint(Vec3(0, m_rcClient.height(), 0)); + Vec3 viewP_Text = viewTM.TransformPoint(Vec3(0.0f, static_cast(m_rcClient.height()), 0.0f)); if (m_bShowMinorGridLines && (!m_bAutoAdjustGrids || pixelsPerGrid > 5)) { @@ -806,8 +806,8 @@ void Q2DViewport::DrawGrid(DisplayContext& dc, bool bNoXNumbers) { Vec3 org = m_screenTM.TransformPoint(Vec3(0, 0, 0)); dc.SetColor(AXIS_GRID_COLOR); - dc.DrawLine(Vec3(org.x, 0, fZ), Vec3(org.x, height, fZ)); - dc.DrawLine(Vec3(0, org.y, fZ), Vec3(width, org.y, fZ)); + dc.DrawLine(Vec3(org.x, 0.0f, fZ), Vec3(org.x, static_cast(height), fZ)); + dc.DrawLine(Vec3(0.0f, org.y, fZ), Vec3(static_cast(width), org.y, fZ)); } ////////////////////////////////////////////////////////////////////////// } @@ -860,18 +860,18 @@ void Q2DViewport::DrawAxis(DisplayContext& dc) int height = m_rcClient.height(); int size = 25; - Vec3 pos(30, height - 15, 1); + Vec3 pos(30.0f, static_cast(height - 15), 1.0f); dc.SetColor(colx.x, colx.y, colx.z, 1); - dc.DrawLine(pos, pos + Vec3(size, 0, 0)); + dc.DrawLine(pos, pos + Vec3(static_cast(size), 0.0f, 0.0f)); - dc.SetColor(coly.x, coly.y, coly.z, 1); - dc.DrawLine(pos, pos - Vec3(0, size, 0)); + dc.SetColor(coly.x, coly.y, coly.z, 1.0f); + dc.DrawLine(pos, pos - Vec3(0.0f, static_cast(size), 0.0f)); dc.SetColor(m_colorAxisText); - pos.x -= 3; - pos.y -= 4; - pos.z = 2; + pos.x -= 3.0f; + pos.y -= 4.0f; + pos.z = 2.0f; dc.Draw2dTextLabel(pos.x + size + 4, pos.y - 2, 1, xstr); dc.Draw2dTextLabel(pos.x + 3, pos.y - size, 1, ystr); dc.Draw2dTextLabel(pos.x - 5, pos.y + 5, 1, zstr); @@ -910,10 +910,14 @@ void Q2DViewport::DrawSelection(DisplayContext& dc) dc.SetColor(SELECTION_RECT_COLOR.x, SELECTION_RECT_COLOR.y, SELECTION_RECT_COLOR.z, 1); QPoint p1(m_selectedRect.left(), m_selectedRect.top()); QPoint p2(m_selectedRect.right() + 1, m_selectedRect.bottom() +1); - dc.DrawLine(Vec3(p1.x(), p1.y(), 0), Vec3(p2.x(), p1.y(), 0)); - dc.DrawLine(Vec3(p1.x(), p2.y(), 0), Vec3(p2.x(), p2.y(), 0)); - dc.DrawLine(Vec3(p1.x(), p1.y(), 0), Vec3(p1.x(), p2.y(), 0)); - dc.DrawLine(Vec3(p2.x(), p1.y(), 0), Vec3(p2.x(), p2.y(), 0)); + dc.DrawLine( + Vec3(static_cast(p1.x()), static_cast(p1.y()), 0.0f), Vec3(static_cast(p2.x()), static_cast(p1.y()), 0.0f)); + dc.DrawLine( + Vec3(static_cast(p1.x()), static_cast(p2.y()), 0.0f), Vec3(static_cast(p2.x()), static_cast(p2.y()), 0.0f)); + dc.DrawLine( + Vec3(static_cast(p1.x()), static_cast(p1.y()), 0.0f), Vec3(static_cast(p1.x()), static_cast(p2.y()), 0.0f)); + dc.DrawLine( + Vec3(static_cast(p2.x()), static_cast(p1.y()), 0.0f), Vec3(static_cast(p2.x()), static_cast(p2.y()), 0.0f)); } } @@ -1038,16 +1042,16 @@ AABB Q2DViewport::GetWorldBounds(const QPoint& pnt1, const QPoint& pnt2) { case VPA_XY: case VPA_YX: - box.min.z = -maxSize; - box.max.z = maxSize; + box.min.z = static_cast(-maxSize); + box.max.z = static_cast(maxSize); break; case VPA_XZ: - box.min.y = -maxSize; - box.max.y = maxSize; + box.min.y = static_cast(-maxSize); + box.max.y = static_cast(maxSize); break; case VPA_YZ: - box.min.x = -maxSize; - box.max.x = maxSize; + box.min.x = static_cast(-maxSize); + box.max.x = static_cast(maxSize); break; } return box; @@ -1076,32 +1080,32 @@ void Q2DViewport::OnDragSelectRectangle(const QRect &rect, [[maybe_unused]] bool switch (m_axis) { case VPA_XY: - box.min.z = -maxSize; - box.max.z = maxSize; + box.min.z = static_cast(-maxSize); + box.max.z = static_cast(maxSize); w = box.max.x - box.min.x; h = box.max.y - box.min.y; sprintf_s(szNewStatusText, "X:%g Y:%g W:%g H:%g", org.x, org.y, w, h); break; case VPA_YX: - box.min.z = -maxSize; - box.max.z = maxSize; + box.min.z = static_cast(-maxSize); + box.max.z = static_cast(maxSize); w = box.max.y - box.min.y; h = box.max.x - box.min.x; sprintf_s(szNewStatusText, "X:%g Y:%g W:%g H:%g", org.x, org.y, w, h); break; case VPA_XZ: - box.min.y = -maxSize; - box.max.y = maxSize; + box.min.y = static_cast(-maxSize); + box.max.y = static_cast(maxSize); w = box.max.x - box.min.x; h = box.max.z - box.min.z; sprintf_s(szNewStatusText, "X:%g Z:%g W:%g H:%g", org.x, org.z, w, h); break; case VPA_YZ: - box.min.x = -maxSize; - box.max.x = maxSize; + box.min.x = static_cast(-maxSize); + box.max.x = static_cast(maxSize); w = box.max.y - box.min.y; h = box.max.z - box.min.z; diff --git a/Code/Editor/Controls/ColorGradientCtrl.cpp b/Code/Editor/Controls/ColorGradientCtrl.cpp index 3bd3b11690..446e5810c5 100644 --- a/Code/Editor/Controls/ColorGradientCtrl.cpp +++ b/Code/Editor/Controls/ColorGradientCtrl.cpp @@ -72,7 +72,7 @@ void CColorGradientCtrl::resizeEvent(QResizeEvent* event) m_grid.rect = m_rcGradient; if (m_bNoZoom) { - m_grid.zoom.x = m_grid.rect.width(); + m_grid.zoom.x = static_cast(m_grid.rect.width()); } m_rcKeys = rc; @@ -106,11 +106,6 @@ QPoint CColorGradientCtrl::KeyToPoint(int nKey) QPoint CColorGradientCtrl::TimeToPoint(float time) { return QPoint(m_grid.WorldToClient(Vec2(time, 0)).x(), m_rcGradient.height() / 2); - - QPoint point; - point.rx() = (time - m_fMinTime) * (m_rcGradient.width() / (m_fMaxTime - m_fMinTime)) + m_rcGradient.left(); - point.ry() = m_rcGradient.height() / 2; - return point; } ////////////////////////////////////////////////////////////////////////// diff --git a/Code/Editor/Controls/ConsoleSCB.cpp b/Code/Editor/Controls/ConsoleSCB.cpp index acbd75444c..c4f58b5297 100644 --- a/Code/Editor/Controls/ConsoleSCB.cpp +++ b/Code/Editor/Controls/ConsoleSCB.cpp @@ -833,15 +833,15 @@ static void SetEditorRange(EditorType* editor, IVariable* var) // If this variable has custom limits set, then use that as the min/max // Otherwise, the min/max for the input box will be bounded by the type // limit, but the slider will be constricted to a smaller default range - static const double defaultMin = -100.0f; - static const double defaultMax = 100.0f; + static const float defaultMin = -100.0f; + static const float defaultMax = 100.0f; if (var->HasCustomLimits()) { - editor->setRange(min, max); + editor->setRange(static_cast(min), static_cast(max)); } else { - editor->setSoftRange(defaultMin, defaultMax); + editor->setSoftRange(static_cast(defaultMin), static_cast(defaultMax)); } // Set the step size. The default variable step is 0, so if it's @@ -850,7 +850,7 @@ static void SetEditorRange(EditorType* editor, IVariable* var) // use that for the int values if (step > 0) { - editor->spinbox()->setSingleStep(step); + editor->spinbox()->setSingleStep(static_cast(step)); } else if (auto doubleSpinBox = qobject_cast(editor->spinbox())) { diff --git a/Code/Editor/Controls/ImageHistogramCtrl.cpp b/Code/Editor/Controls/ImageHistogramCtrl.cpp index 22223a3251..252bf4f09b 100644 --- a/Code/Editor/Controls/ImageHistogramCtrl.cpp +++ b/Code/Editor/Controls/ImageHistogramCtrl.cpp @@ -175,7 +175,7 @@ void CImageHistogramDisplay::paintEvent([[maybe_unused]] QPaintEvent* event) penSpikes = penColor; painter.setPen(Qt::black); painter.setBrush(Qt::white); - rcGraph = QRect(QPoint(m_graphMargin, m_graphMargin), QPoint(abs(rc.width() - m_graphMargin), abs(rc.height() * m_graphHeightPercent))); + rcGraph = QRect(QPoint(m_graphMargin, m_graphMargin), QPoint(abs(rc.width() - m_graphMargin), static_cast(abs(rc.height() * m_graphHeightPercent)))); painter.drawRect(rcGraph); painter.setPen(penSpikes); @@ -193,7 +193,7 @@ void CImageHistogramDisplay::paintEvent([[maybe_unused]] QPaintEvent* event) { float scale = 0; - i = ((float)x / graphWidth) * (kNumColorLevels - 1); + i = static_cast(((float)x / graphWidth) * (kNumColorLevels - 1)); i = CLAMP(i, 0, kNumColorLevels - 1); switch (m_drawMode) @@ -245,7 +245,7 @@ void CImageHistogramDisplay::paintEvent([[maybe_unused]] QPaintEvent* event) } crtX = static_cast(rcGraph.left() + x + 1); - painter.drawLine(crtX, graphBottom, crtX, graphBottom - scale * graphHeight); + painter.drawLine(crtX, graphBottom, crtX, static_cast(graphBottom - scale * graphHeight)); } } else @@ -258,7 +258,7 @@ void CImageHistogramDisplay::paintEvent([[maybe_unused]] QPaintEvent* event) for (size_t x = 0, xCount = abs(rcGraph.width()); x < xCount; ++x) { - i = ((float)x / graphWidth) * (kNumColorLevels - 1); + i = static_cast(((float)x / graphWidth) * (kNumColorLevels - 1)); i = CLAMP(i, 0, kNumColorLevels - 1); crtX = static_cast(rcGraph.left() + x + 1); scaleR = scaleG = scaleB = scaleA = 0; @@ -283,10 +283,10 @@ void CImageHistogramDisplay::paintEvent([[maybe_unused]] QPaintEvent* event) scaleA = (float)m_count[3][i] / m_maxCount[3]; } - heightR = graphBottom - scaleR * graphHeight; - heightG = graphBottom - scaleG * graphHeight; - heightB = graphBottom - scaleB * graphHeight; - heightA = graphBottom - scaleA * graphHeight; + heightR = static_cast(graphBottom - scaleR * graphHeight); + heightG = static_cast(graphBottom - scaleG * graphHeight); + heightB = static_cast(graphBottom - scaleB * graphHeight); + heightA = static_cast(graphBottom - scaleA * graphHeight); if (lastHeight[0] == INT_MAX) { @@ -350,7 +350,7 @@ void CImageHistogramDisplay::paintEvent([[maybe_unused]] QPaintEvent* event) for (size_t x = 0, xCount = abs(rcGraph.width()); x < xCount; ++x) { pos = (float)x / graphWidth; - i = (float)((int)(pos * kNumColorLevels) % aThirdOfNumColorLevels) / aThirdOfNumColorLevels * kNumColorLevels; + i = static_cast((float)((int)(pos * kNumColorLevels) % aThirdOfNumColorLevels) / aThirdOfNumColorLevels * kNumColorLevels); i = CLAMP(i, 0, kNumColorLevels - 1); scale = 0; @@ -385,7 +385,7 @@ void CImageHistogramDisplay::paintEvent([[maybe_unused]] QPaintEvent* event) } painter.setPen(pPen); - painter.drawLine(rcGraph.left() + static_cast(x) + 1, graphBottom, rcGraph.left() + static_cast(x) + 1, graphBottom - scale * graphHeight); + painter.drawLine(rcGraph.left() + static_cast(x) + 1, graphBottom, rcGraph.left() + static_cast(x) + 1, static_cast(graphBottom - scale * graphHeight)); } // then draw 3 lines so we separate the channels diff --git a/Code/Editor/Controls/QBitmapPreviewDialogImp.cpp b/Code/Editor/Controls/QBitmapPreviewDialogImp.cpp index c438858e81..b47a535d2a 100644 --- a/Code/Editor/Controls/QBitmapPreviewDialogImp.cpp +++ b/Code/Editor/Controls/QBitmapPreviewDialogImp.cpp @@ -422,7 +422,7 @@ void QBitmapPreviewDialogImp::paintEvent(QPaintEvent* e) curr_x = histogramRect.left() + x + 1; - int i = ((float)x / (graphWidth - 1)) * (CImageHistogram::kNumColorLevels - 1); + int i = static_cast(((float)x / (graphWidth - 1)) * (CImageHistogram::kNumColorLevels - 1)); if (m_histrogramMode == eHistogramMode_SplitRGB) { // Filter out to area which we are interested @@ -446,7 +446,7 @@ void QBitmapPreviewDialogImp::paintEvent(QPaintEvent* e) scale = (float)m_histogram.m_count[c][i] / m_histogram.m_maxCount[c]; } - int height = graphBottom - graphHeight * scale; + int height = static_cast(graphBottom - graphHeight * scale); if (last_height == INT_MAX) { last_height = height; diff --git a/Code/Editor/Controls/ReflectedPropertyControl/ReflectedPropertyCtrl.cpp b/Code/Editor/Controls/ReflectedPropertyControl/ReflectedPropertyCtrl.cpp index 3c7bda21d9..40ea71f577 100644 --- a/Code/Editor/Controls/ReflectedPropertyControl/ReflectedPropertyCtrl.cpp +++ b/Code/Editor/Controls/ReflectedPropertyControl/ReflectedPropertyCtrl.cpp @@ -308,7 +308,7 @@ void ReflectedPropertyControl::CreateItems(XmlNodeRef node, CVarBlockPtr& outBlo int nMin(0), nMax(0); if (child->getAttr("min", nMin) && child->getAttr("max", nMax)) { - intVar->SetLimits(nMin, nMax); + intVar->SetLimits(static_cast(nMin), static_cast(nMax)); } } else if (!azstricmp(type, "float")) diff --git a/Code/Editor/Controls/ReflectedPropertyControl/ReflectedVarWrapper.cpp b/Code/Editor/Controls/ReflectedPropertyControl/ReflectedVarWrapper.cpp index aba346ce6a..b3f1b35461 100644 --- a/Code/Editor/Controls/ReflectedPropertyControl/ReflectedVarWrapper.cpp +++ b/Code/Editor/Controls/ReflectedPropertyControl/ReflectedVarWrapper.cpp @@ -39,20 +39,20 @@ namespace { hardMin = desc.m_bHardMin; hardMax = desc.m_bHardMax; } - reflectedVar->m_softMinVal = min; - reflectedVar->m_softMaxVal = max; + reflectedVar->m_softMinVal = static_cast(min); + reflectedVar->m_softMaxVal = static_cast(max); if (hardMin) { - reflectedVar->m_minVal = min; + reflectedVar->m_minVal = static_cast(min); } else { - reflectedVar->m_minVal = std::numeric_limits::lowest(); + reflectedVar->m_minVal = std::numeric_limits::lowest(); } if (hardMax) { - reflectedVar->m_maxVal = max; + reflectedVar->m_maxVal = static_cast(max); } else { @@ -64,9 +64,9 @@ namespace { ../Code/Editor/Controls/ReflectedPropertyControl/ReflectedVarWrapper.cpp:59:38: error: implicit conversion from 'int' to 'float' changes value from 2147483647 to 2147483648 [-Werror,-Wimplicit-int-float-conversion] reflectedVar->m_maxVal = std::numeric_limits::max(); */ - reflectedVar->m_maxVal = static_cast(std::numeric_limits::max()); + reflectedVar->m_maxVal = static_cast(std::numeric_limits::max()); } - reflectedVar->m_stepSize = step; + reflectedVar->m_stepSize = static_cast(step); } } @@ -95,9 +95,9 @@ void ReflectedVarIntAdapter::SyncReflectedVarToIVar(IVariable *pVariable) { int intValue; pVariable->Get(intValue); - value = intValue; + value = static_cast(intValue); } - m_reflectedVar->m_value = std::round(value * m_valueMultiplier); + m_reflectedVar->m_value = static_cast(std::round(value * m_valueMultiplier)); } void ReflectedVarIntAdapter::SyncIVarToReflectedVar(IVariable *pVariable) @@ -362,14 +362,14 @@ void ReflectedVarColorAdapter::SyncReflectedVarToIVar(IVariable *pVariable) Vec3 v(0, 0, 0); pVariable->Get(v); const QColor col = ColorLinearToGamma(ColorF(v.x, v.y, v.z)); - m_reflectedVar->m_color.Set(col.redF(), col.greenF(), col.blueF()); + m_reflectedVar->m_color.Set(static_cast(col.redF()), static_cast(col.greenF()), static_cast(col.blueF())); } else { int col(0); pVariable->Get(col); const QColor qcolor = ColorToQColor((uint32)col); - m_reflectedVar->m_color.Set(qcolor.redF(), qcolor.greenF(), qcolor.blueF()); + m_reflectedVar->m_color.Set(static_cast(qcolor.redF()), static_cast(qcolor.greenF()), static_cast(qcolor.blueF())); } } @@ -382,9 +382,9 @@ void ReflectedVarColorAdapter::SyncIVarToReflectedVar(IVariable *pVariable) } else { - int ir = m_reflectedVar->m_color.GetX() * 255.0f; - int ig = m_reflectedVar->m_color.GetY() * 255.0f; - int ib = m_reflectedVar->m_color.GetZ() * 255.0f; + int ir = static_cast(m_reflectedVar->m_color.GetX() * 255.0f); + int ig = static_cast(m_reflectedVar->m_color.GetY() * 255.0f); + int ib = static_cast(m_reflectedVar->m_color.GetZ() * 255.0f); pVariable->Set(static_cast(RGB(ir, ig, ib))); } diff --git a/Code/Editor/Controls/SplineCtrl.cpp b/Code/Editor/Controls/SplineCtrl.cpp index d66fc16ade..80d30b37ad 100644 --- a/Code/Editor/Controls/SplineCtrl.cpp +++ b/Code/Editor/Controls/SplineCtrl.cpp @@ -86,13 +86,13 @@ QPoint CSplineCtrl::KeyToPoint(int nKey) QPoint CSplineCtrl::TimeToPoint(float time) { QPoint point; - point.setX((time - m_fMinTime) * (m_rcSpline.width() / (m_fMaxTime - m_fMinTime)) + m_rcSpline.left()); + point.setX(static_cast((time - m_fMinTime) * (m_rcSpline.width() / (m_fMaxTime - m_fMinTime)) + m_rcSpline.left())); float val = 0; if (m_pSpline) { m_pSpline->InterpolateFloat(time, val); } - point.setY((floor((m_fMaxValue - val) * (m_rcSpline.height() / (m_fMaxValue - m_fMinValue)) + 0.5f) + m_rcSpline.top())); + point.setY(static_cast((floor((m_fMaxValue - val) * (m_rcSpline.height() / (m_fMaxValue - m_fMinValue)) + 0.5f) + m_rcSpline.top()))); return point; } diff --git a/Code/Editor/Controls/SplineCtrlEx.cpp b/Code/Editor/Controls/SplineCtrlEx.cpp index 5bba14f0d6..f299ce185d 100644 --- a/Code/Editor/Controls/SplineCtrlEx.cpp +++ b/Code/Editor/Controls/SplineCtrlEx.cpp @@ -641,7 +641,7 @@ QPoint AbstractSplineWidget::TimeToPoint(float time, ISplineInterpolator* pSplin ////////////////////////////////////////////////////////////////////////// float AbstractSplineWidget::TimeToXOfs(float x) { - return WorldToClient(Vec2(float(x), 0.0f)).x(); + return static_cast(WorldToClient(Vec2(float(x), 0.0f)).x()); } ////////////////////////////////////////////////////////////////////////// @@ -832,8 +832,8 @@ void SplineWidget::DrawSpline(QPainter* painter, SSplineInfo& splineInfo, float int nTotalNumberOfDimensions(0); int nCurrentDimension(0); - int left = TimeToXOfs(startTime);//rcClip.left; - int right = TimeToXOfs(endTime);//rcClip.right; + int left = static_cast(TimeToXOfs(startTime));//rcClip.left; + int right = static_cast(TimeToXOfs(endTime));//rcClip.right; QPoint p0 = TimeToPoint(pSpline->GetKeyTime(0), pSpline); QPoint p1 = TimeToPoint(pSpline->GetKeyTime(pSpline->GetKeyCount() - 1), pSpline); @@ -898,7 +898,7 @@ void SplineWidget::DrawSpline(QPainter* painter, SSplineInfo& splineInfo, float if ((x == right && pointsInLine >= 0) || (pointsInLine > 0 && fabs(lineStart.y() + gradient * (pt.x() - lineStart.x()) - pt.y()) > 1.0f)) { - lineStart = QPoint(pt.x() - 1, lineStart.y() + gradient * (pt.x() - 1 - lineStart.x())); + lineStart = QPoint(pt.x() - 1, static_cast(lineStart.y() + gradient * (pt.x() - 1 - lineStart.x()))); path.lineTo(lineStart); gradient = float(pt.y() - lineStart.y()) / (pt.x() - lineStart.x()); pointsInLine = 1; @@ -1063,7 +1063,7 @@ void SplineWidget::DrawTimeMarker(QPainter* painter) float x = TimeToXOfs(m_fTimeMarker); if (x >= m_rcSpline.left() && x <= m_rcSpline.right() + 1) { - painter->drawLine(x, m_rcSpline.top(), x, m_rcSpline.bottom() + 1); + painter->drawLine(static_cast(x), m_rcSpline.top(), static_cast(x), m_rcSpline.bottom() + 1); } painter->setPen(pOldPen); } @@ -2145,8 +2145,8 @@ void AbstractSplineWidget::TimeScaleKeys(float time, float startTime, float endT } } - int rangeMin = TimeToXOfs(affectedRangeMin); - int rangeMax = TimeToXOfs(affectedRangeMax); + int rangeMin = static_cast(TimeToXOfs(affectedRangeMin)); + int rangeMax = static_cast(TimeToXOfs(affectedRangeMax)); if (m_timeRange.start == affectedRangeMin) { @@ -2377,8 +2377,8 @@ void AbstractSplineWidget::RedrawWindowAroundMarker() UpdateKeyTimes(); std::vector::iterator itKeyTime = std::lower_bound(m_keyTimes.begin(), m_keyTimes.end(), KeyTime(m_fTimeMarker, 0)); size_t keyTimeIndex = (itKeyTime != m_keyTimes.end() ? itKeyTime - m_keyTimes.begin() : m_keyTimes.size()); - int redrawRangeStart = (keyTimeIndex >= 2 ? TimeToXOfs(m_keyTimes[keyTimeIndex - 2].time) : m_rcSpline.left()); - int redrawRangeEnd = (keyTimeIndex < m_keyTimes.size() - 2 ? TimeToXOfs(m_keyTimes[keyTimeIndex + 2].time) : m_rcSpline.right() + 1); + int redrawRangeStart = (keyTimeIndex >= 2 ? static_cast(TimeToXOfs(m_keyTimes[keyTimeIndex - 2].time)) : m_rcSpline.left()); + int redrawRangeEnd = (keyTimeIndex < m_keyTimes.size() - 2 ? static_cast(TimeToXOfs(m_keyTimes[keyTimeIndex + 2].time)) : m_rcSpline.right() + 1); QRect rc(QPoint(redrawRangeStart, m_rcSpline.top()), QPoint(redrawRangeEnd, m_rcSpline.bottom() + 1) - QPoint(1, 1)); rc = rc.normalized().intersected(m_rcSpline); diff --git a/Code/Editor/Controls/TimelineCtrl.cpp b/Code/Editor/Controls/TimelineCtrl.cpp index a5a941fc78..8159084784 100644 --- a/Code/Editor/Controls/TimelineCtrl.cpp +++ b/Code/Editor/Controls/TimelineCtrl.cpp @@ -25,9 +25,9 @@ static const QColor ltgrayCol = QColor(110, 110, 110); QColor InterpolateColor(const QColor& c1, const QColor& c2, float fraction) { - const int r = (c2.red() - c1.red()) * fraction + c1.red(); - const int g = (c2.green() - c1.green()) * fraction + c1.green(); - const int b = (c2.blue() - c1.blue()) * fraction + c1.blue(); + const int r = static_cast(static_cast(c2.red() - c1.red()) * fraction + c1.red()); + const int g = static_cast(static_cast(c2.green() - c1.green()) * fraction + c1.green()); + const int b = static_cast(static_cast(c2.blue() - c1.blue()) * fraction + c1.blue()); return QColor(r, g, b); } @@ -120,7 +120,7 @@ float TimelineWidget::SnapTime(float time) { double t = floor((double)time * m_ticksStep + 0.5); t = t / m_ticksStep; - return t; + return static_cast(t); } ////////////////////////////////////////////////////////////////////////// @@ -153,10 +153,10 @@ void TimelineWidget::DrawTicks(QPainter* painter) painter->setPen(redpen); int x = TimeToClient(m_fTimeMarker); painter->setBrush(Qt::NoBrush); - painter->drawRect(QRect(QPoint(x - 3, rc.top()), QPoint(x + 2, rc.bottom()))); + painter->drawRect(QRect(QPoint(x - 3, static_cast(rc.top())), QPoint(x + 2, static_cast(rc.bottom())))); painter->setPen(redpen); - painter->drawLine(x, rc.top(), x, rc.bottom()); + painter->drawLine(x, static_cast(rc.top()), x, static_cast(rc.bottom())); painter->setBrush(Qt::NoBrush); // Draw vertical line showing current time. @@ -190,7 +190,7 @@ void TimelineWidget::DrawTicks(QPainter* painter) float keyTime = (m_pKeyTimeSet ? m_pKeyTimeSet->GetKeyTime(keyTimeIndex) : 0.0f); int x2 = TimeToClient(keyTime); - painter->drawRect(QRect(QPoint(x2 - 1, rc.top()), QPoint(x2 + 2, rc.bottom()))); + painter->drawRect(QRect(QPoint(x2 - 1, static_cast(rc.top())), QPoint(x2 + 2, static_cast(rc.bottom())))); } painter->setPen(pOldPen); diff --git a/Code/Editor/CryEditDoc.cpp b/Code/Editor/CryEditDoc.cpp index 789aa1bdb9..f3f38576b4 100644 --- a/Code/Editor/CryEditDoc.cpp +++ b/Code/Editor/CryEditDoc.cpp @@ -2091,7 +2091,7 @@ void CCryEditDoc::OnEnvironmentPropertyChanged(IVariable* pVar) } // QVariant will not convert a void * to int, so do it manually. - int nKey = reinterpret_cast(pVar->GetUserData().value()); + int nKey = static_cast(reinterpret_cast(pVar->GetUserData().value())); int nGroup = (nKey & 0xFFFF0000) >> 16; int nChild = (nKey & 0x0000FFFF); diff --git a/Code/Editor/DisplaySettings.cpp b/Code/Editor/DisplaySettings.cpp index dc4cf083a9..ed4ca180b4 100644 --- a/Code/Editor/DisplaySettings.cpp +++ b/Code/Editor/DisplaySettings.cpp @@ -46,7 +46,7 @@ void CDisplaySettings::SaveRegistry() SaveValue("Settings", "RenderFlags", m_renderFlags); SaveValue("Settings", "DisplayFlags", m_flags & SETTINGS_SERIALIZABLE_FLAGS_MASK); SaveValue("Settings", "DebugFlags", m_debugFlags); - SaveValue("Settings", "LabelsDistance", m_labelsDistance); + SaveValue("Settings", "LabelsDistance", static_cast(m_labelsDistance)); } void CDisplaySettings::LoadRegistry() @@ -56,9 +56,9 @@ void CDisplaySettings::LoadRegistry() LoadValue("Settings", "DisplayFlags", m_flags); m_flags &= SETTINGS_SERIALIZABLE_FLAGS_MASK; LoadValue("Settings", "DebugFlags", m_debugFlags); - int temp = m_labelsDistance; + int temp = static_cast(m_labelsDistance); LoadValue("Settings", "LabelsDistance", temp); - m_labelsDistance = temp; + m_labelsDistance = static_cast(temp); gSettings.objectHideMask = m_objectHideMask; } diff --git a/Code/Editor/EditMode/SubObjectSelectionReferenceFrameCalculator.cpp b/Code/Editor/EditMode/SubObjectSelectionReferenceFrameCalculator.cpp index cf7cf5e959..80368d3ec1 100644 --- a/Code/Editor/EditMode/SubObjectSelectionReferenceFrameCalculator.cpp +++ b/Code/Editor/EditMode/SubObjectSelectionReferenceFrameCalculator.cpp @@ -44,14 +44,14 @@ bool SubObjectSelectionReferenceFrameCalculator::GetFrame(Matrix34& refFrame) if (this->nNormals > 0) { - this->normal = this->normal / this->nNormals; + this->normal = this->normal / static_cast(this->nNormals); if (!this->normal.IsZero()) { this->normal.Normalize(); } // Average position. - this->pos = this->pos / this->nNormals; + this->pos = this->pos / static_cast(this->nNormals); refFrame.SetTranslation(this->pos); } diff --git a/Code/Editor/EditorPreferencesPageViewportGeneral.cpp b/Code/Editor/EditorPreferencesPageViewportGeneral.cpp index 1fc0d14988..a9eec22e69 100644 --- a/Code/Editor/EditorPreferencesPageViewportGeneral.cpp +++ b/Code/Editor/EditorPreferencesPageViewportGeneral.cpp @@ -201,20 +201,24 @@ void CEditorPreferencesPage_ViewportGeneral::OnApply() ds->SetLabelsDistance(m_textLabels.m_labelsDistance); gSettings.objectColorSettings.fChildGeomAlpha = m_selectionPreviewColor.m_childObjectGeomAlpha; - gSettings.objectColorSettings.entityHighlight = QColor(m_selectionPreviewColor.m_colorEntityBBox.GetR() * 255.0f, - m_selectionPreviewColor.m_colorEntityBBox.GetG() * 255.0f, - m_selectionPreviewColor.m_colorEntityBBox.GetB() * 255.0f); - gSettings.objectColorSettings.groupHighlight = QColor(m_selectionPreviewColor.m_colorGroupBBox.GetR() * 255.0f, - m_selectionPreviewColor.m_colorGroupBBox.GetG() * 255.0f, - m_selectionPreviewColor.m_colorGroupBBox.GetB() * 255.0f); + gSettings.objectColorSettings.entityHighlight = QColor( + static_cast(m_selectionPreviewColor.m_colorEntityBBox.GetR() * 255.0f), + static_cast(m_selectionPreviewColor.m_colorEntityBBox.GetG() * 255.0f), + static_cast(m_selectionPreviewColor.m_colorEntityBBox.GetB() * 255.0f)); + gSettings.objectColorSettings.groupHighlight = QColor( + static_cast(m_selectionPreviewColor.m_colorGroupBBox.GetR() * 255.0f), + static_cast(m_selectionPreviewColor.m_colorGroupBBox.GetG() * 255.0f), + static_cast(m_selectionPreviewColor.m_colorGroupBBox.GetB() * 255.0f)); gSettings.objectColorSettings.fBBoxAlpha = m_selectionPreviewColor.m_fBBoxAlpha; gSettings.objectColorSettings.fGeomAlpha = m_selectionPreviewColor.m_fgeomAlpha; - gSettings.objectColorSettings.geometryHighlightColor = QColor(m_selectionPreviewColor.m_geometryHighlightColor.GetR() * 255.0f, - m_selectionPreviewColor.m_geometryHighlightColor.GetG() * 255.0f, - m_selectionPreviewColor.m_geometryHighlightColor.GetB() * 255.0f); - gSettings.objectColorSettings.solidBrushGeometryColor = QColor(m_selectionPreviewColor.m_solidBrushGeometryColor.GetR() * 255.0f, - m_selectionPreviewColor.m_solidBrushGeometryColor.GetG() * 255.0f, - m_selectionPreviewColor.m_solidBrushGeometryColor.GetB() * 255.0f); + gSettings.objectColorSettings.geometryHighlightColor = QColor( + static_cast(m_selectionPreviewColor.m_geometryHighlightColor.GetR() * 255.0f), + static_cast(m_selectionPreviewColor.m_geometryHighlightColor.GetG() * 255.0f), + static_cast(m_selectionPreviewColor.m_geometryHighlightColor.GetB() * 255.0f)); + gSettings.objectColorSettings.solidBrushGeometryColor = QColor( + static_cast(m_selectionPreviewColor.m_solidBrushGeometryColor.GetR() * 255.0f), + static_cast(m_selectionPreviewColor.m_solidBrushGeometryColor.GetG() * 255.0f), + static_cast(m_selectionPreviewColor.m_solidBrushGeometryColor.GetB() * 255.0f)); } void CEditorPreferencesPage_ViewportGeneral::InitializeSettings() @@ -252,10 +256,10 @@ void CEditorPreferencesPage_ViewportGeneral::InitializeSettings() m_textLabels.m_labelsDistance = ds->GetLabelsDistance(); m_selectionPreviewColor.m_childObjectGeomAlpha = gSettings.objectColorSettings.fChildGeomAlpha; - m_selectionPreviewColor.m_colorEntityBBox.Set(gSettings.objectColorSettings.entityHighlight.redF(), gSettings.objectColorSettings.entityHighlight.greenF(), gSettings.objectColorSettings.entityHighlight.blueF(), 1.0f); - m_selectionPreviewColor.m_colorGroupBBox.Set(gSettings.objectColorSettings.groupHighlight.redF(), gSettings.objectColorSettings.groupHighlight.greenF(), gSettings.objectColorSettings.groupHighlight.blueF(), 1.0f); + m_selectionPreviewColor.m_colorEntityBBox.Set(static_cast(gSettings.objectColorSettings.entityHighlight.redF()), static_cast(gSettings.objectColorSettings.entityHighlight.greenF()), static_cast(gSettings.objectColorSettings.entityHighlight.blueF()), 1.0f); + m_selectionPreviewColor.m_colorGroupBBox.Set(static_cast(gSettings.objectColorSettings.groupHighlight.redF()), static_cast(gSettings.objectColorSettings.groupHighlight.greenF()), static_cast(gSettings.objectColorSettings.groupHighlight.blueF()), 1.0f); m_selectionPreviewColor.m_fBBoxAlpha = gSettings.objectColorSettings.fBBoxAlpha; m_selectionPreviewColor.m_fgeomAlpha = gSettings.objectColorSettings.fGeomAlpha; - m_selectionPreviewColor.m_geometryHighlightColor.Set(gSettings.objectColorSettings.geometryHighlightColor.redF(), gSettings.objectColorSettings.geometryHighlightColor.greenF(), gSettings.objectColorSettings.geometryHighlightColor.blueF(), 1.0f); - m_selectionPreviewColor.m_solidBrushGeometryColor.Set(gSettings.objectColorSettings.solidBrushGeometryColor.redF(), gSettings.objectColorSettings.solidBrushGeometryColor.greenF(), gSettings.objectColorSettings.solidBrushGeometryColor.blueF(), 1.0f); + m_selectionPreviewColor.m_geometryHighlightColor.Set(static_cast(gSettings.objectColorSettings.geometryHighlightColor.redF()), static_cast(gSettings.objectColorSettings.geometryHighlightColor.greenF()), static_cast(gSettings.objectColorSettings.geometryHighlightColor.blueF()), 1.0f); + m_selectionPreviewColor.m_solidBrushGeometryColor.Set(static_cast(gSettings.objectColorSettings.solidBrushGeometryColor.redF()), static_cast(gSettings.objectColorSettings.solidBrushGeometryColor.greenF()), static_cast(gSettings.objectColorSettings.solidBrushGeometryColor.blueF()), 1.0f); } diff --git a/Code/Editor/EditorViewportWidget.cpp b/Code/Editor/EditorViewportWidget.cpp index 701386951a..75b62f3781 100644 --- a/Code/Editor/EditorViewportWidget.cpp +++ b/Code/Editor/EditorViewportWidget.cpp @@ -284,7 +284,7 @@ void EditorViewportWidget::paintEvent([[maybe_unused]] QPaintEvent* event) const char* kFontName = "Arial"; const QColor kTextColor(255, 255, 255); const QColor kTextShadowColor(0, 0, 0); - const QFont font(kFontName, kFontSize / 10.0); + const QFont font(kFontName, static_cast(kFontSize / 10.0f)); painter.setFont(font); QString friendlyName = QFileInfo(GetIEditor()->GetLevelName()).fileName(); @@ -815,29 +815,35 @@ void EditorViewportWidget::UpdateSafeFrame() float maxSafeFrameWidth = m_safeFrame.height() * targetAspectRatio; float widthDifference = m_safeFrame.width() - maxSafeFrameWidth; - m_safeFrame.setLeft(m_safeFrame.left() + widthDifference * 0.5); - m_safeFrame.setRight(m_safeFrame.right() - widthDifference * 0.5); + m_safeFrame.setLeft(static_cast(m_safeFrame.left() + widthDifference * 0.5f)); + m_safeFrame.setRight(static_cast(m_safeFrame.right() - widthDifference * 0.5f)); } else { float maxSafeFrameHeight = m_safeFrame.width() / targetAspectRatio; float heightDifference = m_safeFrame.height() - maxSafeFrameHeight; - m_safeFrame.setTop(m_safeFrame.top() + heightDifference * 0.5); - m_safeFrame.setBottom(m_safeFrame.bottom() - heightDifference * 0.5); + m_safeFrame.setTop(static_cast(m_safeFrame.top() + heightDifference * 0.5f)); + m_safeFrame.setBottom(static_cast(m_safeFrame.bottom() - heightDifference * 0.5f)); } m_safeFrame.adjust(0, 0, -1, -1); // <-- aesthetic improvement. const float SAFE_ACTION_SCALE_FACTOR = 0.05f; m_safeAction = m_safeFrame; - m_safeAction.adjust(m_safeFrame.width() * SAFE_ACTION_SCALE_FACTOR, m_safeFrame.height() * SAFE_ACTION_SCALE_FACTOR, - -m_safeFrame.width() * SAFE_ACTION_SCALE_FACTOR, -m_safeFrame.height() * SAFE_ACTION_SCALE_FACTOR); + m_safeAction.adjust( + static_cast(m_safeFrame.width() * SAFE_ACTION_SCALE_FACTOR), + static_cast(m_safeFrame.height() * SAFE_ACTION_SCALE_FACTOR), + static_cast(-m_safeFrame.width() * SAFE_ACTION_SCALE_FACTOR), + static_cast(-m_safeFrame.height() * SAFE_ACTION_SCALE_FACTOR)); const float SAFE_TITLE_SCALE_FACTOR = 0.1f; m_safeTitle = m_safeFrame; - m_safeTitle.adjust(m_safeFrame.width() * SAFE_TITLE_SCALE_FACTOR, m_safeFrame.height() * SAFE_TITLE_SCALE_FACTOR, - -m_safeFrame.width() * SAFE_TITLE_SCALE_FACTOR, -m_safeFrame.height() * SAFE_TITLE_SCALE_FACTOR); + m_safeTitle.adjust( + static_cast(m_safeFrame.width() * SAFE_TITLE_SCALE_FACTOR), + static_cast(m_safeFrame.height() * SAFE_TITLE_SCALE_FACTOR), + static_cast(-m_safeFrame.width() * SAFE_TITLE_SCALE_FACTOR), + static_cast(-m_safeFrame.height() * SAFE_TITLE_SCALE_FACTOR)); } ////////////////////////////////////////////////////////////////////////// @@ -856,8 +862,8 @@ void EditorViewportWidget::RenderSafeFrame(const QRect& frame, float r, float g, const int LINE_WIDTH = 2; for (int i = 0; i < LINE_WIDTH; i++) { - AZ::Vector3 topLeft(frame.left() + i, frame.top() + i, 0); - AZ::Vector3 bottomRight(frame.right() - i, frame.bottom() - i, 0); + AZ::Vector3 topLeft(static_cast(frame.left() + i), static_cast(frame.top() + i), 0.0f); + AZ::Vector3 bottomRight(static_cast(frame.right() - i), static_cast(frame.bottom() - i), 0.0f); m_debugDisplay->DrawWireBox(topLeft, bottomRight); } } @@ -1936,8 +1942,8 @@ QPoint EditorViewportWidget::WorldToViewParticleEditor(const Vec3& wp, int width ProjectToScreen(wp.x, wp.y, wp.z, &x, &y, &z); if (_finite(x) || _finite(y)) { - p.rx() = (x / 100) * width; - p.ry() = (y / 100) * height; + p.rx() = static_cast((x / 100) * width); + p.ry() = static_cast((y / 100) * height); } else { @@ -2091,8 +2097,8 @@ void EditorViewportWidget::UnProjectFromScreen(float sx, float sy, float sz, flo void EditorViewportWidget::ProjectToScreen(float ptx, float pty, float ptz, float* sx, float* sy, float* sz) const { AzFramework::ScreenPoint screenPosition = m_renderViewport->ViewportWorldToScreen(AZ::Vector3{ptx, pty, ptz}); - *sx = screenPosition.m_x; - *sy = screenPosition.m_y; + *sx = static_cast(screenPosition.m_x); + *sy = static_cast(screenPosition.m_y); *sz = 0.f; } @@ -2103,7 +2109,7 @@ void EditorViewportWidget::ViewToWorldRay(const QPoint& vp, Vec3& raySrc, Vec3& Vec3 pos0, pos1; float wx, wy, wz; - UnProjectFromScreen(vp.x(), rc.bottom() - vp.y(), 0, &wx, &wy, &wz); + UnProjectFromScreen(static_cast(vp.x()), static_cast(rc.bottom() - vp.y()), 0.0f, &wx, &wy, &wz); if (!_finite(wx) || !_finite(wy) || !_finite(wz)) { return; @@ -2113,7 +2119,7 @@ void EditorViewportWidget::ViewToWorldRay(const QPoint& vp, Vec3& raySrc, Vec3& return; } pos0(wx, wy, wz); - UnProjectFromScreen(vp.x(), rc.bottom() - vp.y(), 1, &wx, &wy, &wz); + UnProjectFromScreen(static_cast(vp.x()), static_cast(rc.bottom() - vp.y()), 1.0f, &wx, &wy, &wz); if (!_finite(wx) || !_finite(wy) || !_finite(wz)) { return; diff --git a/Code/Editor/ErrorReportTableModel.cpp b/Code/Editor/ErrorReportTableModel.cpp index 2da3110e37..f5dce1a86d 100644 --- a/Code/Editor/ErrorReportTableModel.cpp +++ b/Code/Editor/ErrorReportTableModel.cpp @@ -45,7 +45,7 @@ bool GetPositionFromString(QString er, float* x, float* y, float* z) } if (ind > 0) { - *x = er.mid(0, ind).toDouble(); + *x = er.mid(0, ind).toFloat(); er = er.mid(ind); er.remove(QRegExp("^[ ,]*")); @@ -57,12 +57,12 @@ bool GetPositionFromString(QString er, float* x, float* y, float* z) } if (ind > 0) { - *y = er.mid(0, ind).toDouble(); + *y = er.mid(0, ind).toFloat(); er = er.mid(ind); er.remove(QRegExp("^[ ,]*")); if (er.length()) { - *z = er.toDouble(); + *z = er.toFloat(); return true; } } diff --git a/Code/Editor/Export/ExportManager.cpp b/Code/Editor/Export/ExportManager.cpp index 8c90d7322d..7601740033 100644 --- a/Code/Editor/Export/ExportManager.cpp +++ b/Code/Editor/Export/ExportManager.cpp @@ -40,15 +40,6 @@ namespace { - void SetTexture(Export::TPath& outName, IRenderShaderResources* pRes, int nSlot) - { - SEfResTexture* pTex = pRes->GetTextureResource(nSlot); - if (pTex) - { - azstrcat(outName, AZ_ARRAY_SIZE(outName), Path::GamePathToFullPath(pTex->m_Name.c_str()).toUtf8().data()); - } - } - inline Export::Vector3D Vec3ToVector3D(const Vec3& vec) { Export::Vector3D ret; @@ -1164,7 +1155,7 @@ bool CExportManager::Export(const char* defaultName, const char* defaultExt, con // Export the whole sequence with baked keys if (ShowFBXExportDialog()) { - m_numberOfExportFrames = pSequence->GetTimeRange().end * m_FBXBakedExportFPS; + m_numberOfExportFrames = static_cast(pSequence->GetTimeRange().end * m_FBXBakedExportFPS); if (!m_bExportOnlyPrimaryCamera) { diff --git a/Code/Editor/FBXExporterDialog.cpp b/Code/Editor/FBXExporterDialog.cpp index 86e7843ca1..bae4b9bf7e 100644 --- a/Code/Editor/FBXExporterDialog.cpp +++ b/Code/Editor/FBXExporterDialog.cpp @@ -20,7 +20,7 @@ AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING namespace { - const uint kDefaultFPS = 30.0f; + const uint kDefaultFPS = 30u; } CFBXExporterDialog::CFBXExporterDialog(bool bDisplayOnlyFPSSetting, QWidget* pParent) @@ -43,7 +43,7 @@ CFBXExporterDialog::~CFBXExporterDialog() float CFBXExporterDialog::GetFPS() const { - return m_ui->m_fpsCombo->currentText().toDouble(); + return m_ui->m_fpsCombo->currentText().toFloat(); } bool CFBXExporterDialog::GetExportCoordsLocalToTheSelectedObject() const diff --git a/Code/Editor/Geometry/TriMesh.cpp b/Code/Editor/Geometry/TriMesh.cpp index 2106265aca..d56aa038b5 100644 --- a/Code/Editor/Geometry/TriMesh.cpp +++ b/Code/Editor/Geometry/TriMesh.cpp @@ -201,7 +201,7 @@ void CTriMesh::SetFromMesh(CMesh& mesh) face.v [j] = numv; face.uv[j] = numv; face.n [j] = mesh.m_pNorms[idx].GetN(); - face.MatID = subset.nMatID; + face.MatID = static_cast(subset.nMatID); face.flags = 0; numv++; @@ -269,7 +269,7 @@ void CTriMesh::SharePositions() for (int i = 0; i < 3; i++) { const Vec3& v = pVertices[face.v[i]].pos; - uint8 nHash = RoundFloatToInt((v.x + v.y + v.z) * fHashScale); + uint8 nHash = static_cast(RoundFloatToInt((v.x + v.y + v.z) * fHashScale)); int find = FindVertexInHash(v, pNewVerts, arrHashTable[nHash], fEpsilon); if (find < 0) @@ -320,7 +320,7 @@ void CTriMesh::ShareUV() for (int i = 0; i < 3; i++) { const Vec2 uv = pUV[face.uv[i]].GetUV(); - uint8 nHash = RoundFloatToInt((uv.x + uv.y) * fHashScale); + uint8 nHash = static_cast(RoundFloatToInt((uv.x + uv.y) * fHashScale)); int find = FindTexCoordInHash(pUV[face.uv[i]], pNewUV, arrHashTable[nHash], fEpsilon); if (find < 0) @@ -380,7 +380,7 @@ void CTriMesh::UpdateIndexedMesh(IIndexedMesh* pIndexedMesh) const // To find really used materials std::vector usedMaterialIds; uint16 MatIdToSubset[MAX_SUB_MATERIALS]; - int nLastSubsetId = 0; + uint16 nLastSubsetId = 0; memset(MatIdToSubset, 0, sizeof(MatIdToSubset)); ////////////////////////////////////////////////////////////////////////// @@ -398,7 +398,7 @@ void CTriMesh::UpdateIndexedMesh(IIndexedMesh* pIndexedMesh) const MatIdToSubset[face.MatID] = 1 + nLastSubsetId++; usedMaterialIds.push_back(face.MatID); // Order of material ids in usedMaterialIds correspond to the indices of chunks. } - meshFace.nSubset = MatIdToSubset[face.MatID] - 1; + meshFace.nSubset = static_cast(MatIdToSubset[face.MatID] - 1); for (int j = 0; j < 3; ++j) { diff --git a/Code/Editor/GotoPositionDlg.cpp b/Code/Editor/GotoPositionDlg.cpp index aec5f03fbd..84d149de58 100644 --- a/Code/Editor/GotoPositionDlg.cpp +++ b/Code/Editor/GotoPositionDlg.cpp @@ -86,7 +86,7 @@ void GotoPositionDialog::OnChangeEdit() const QStringList parts = m_transform.split(QRegularExpression("[\\s,;\\t]"), Qt::SkipEmptyParts); for (int i = 0; i < argCount && i < parts.count(); ++i) { - transform[i] = parts[i].toDouble(); + transform[i] = parts[i].toFloat(); } m_ui->m_dymX->setValue(transform[0]); diff --git a/Code/Editor/LogFile.cpp b/Code/Editor/LogFile.cpp index 2295e1897f..5978356781 100644 --- a/Code/Editor/LogFile.cpp +++ b/Code/Editor/LogFile.cpp @@ -504,7 +504,7 @@ static inline QString CopyAndRemoveColorCode(const char* sText) *d++ = *s++; } - ret.resize(d - ret.data()); + ret.resize(static_cast(d - ret.data())); return QString::fromLatin1(ret); } diff --git a/Code/Editor/Objects/BaseObject.cpp b/Code/Editor/Objects/BaseObject.cpp index e68b17b99f..7126e22a4e 100644 --- a/Code/Editor/Objects/BaseObject.cpp +++ b/Code/Editor/Objects/BaseObject.cpp @@ -1022,10 +1022,10 @@ void CBaseObject::DrawLabel(DisplayContext& dc, const Vec3& pos, const QColor& l if (camDist < dc.settings->GetLabelsDistance() || (dc.flags & DISPLAY_SELECTION_HELPERS)) { float range = maxDist / 2.0f; - Vec3 c(labelColor.redF(), labelColor.greenF(), labelColor.redF()); + Vec3 c(static_cast(labelColor.redF()), static_cast(labelColor.greenF()), static_cast(labelColor.redF())); if (IsSelected()) { - c = Vec3(dc.GetSelectedColor().redF(), dc.GetSelectedColor().greenF(), dc.GetSelectedColor().blueF()); + c = Vec3(static_cast(dc.GetSelectedColor().redF()), static_cast(dc.GetSelectedColor().greenF()), static_cast(dc.GetSelectedColor().blueF())); } float col[4] = { c.x, c.y, c.z, 1 }; @@ -1033,7 +1033,7 @@ void CBaseObject::DrawLabel(DisplayContext& dc, const Vec3& pos, const QColor& l { if (IsHighlighted()) { - c = Vec3(dc.GetSelectedColor().redF(), dc.GetSelectedColor().greenF(), dc.GetSelectedColor().blueF()); + c = Vec3(static_cast(dc.GetSelectedColor().redF()), static_cast(dc.GetSelectedColor().greenF()), static_cast(dc.GetSelectedColor().blueF())); } col[0] = c.x; col[1] = c.y; @@ -1263,9 +1263,9 @@ int CBaseObject::MouseCreateCallback(CViewport* view, EMouseEvent event, QPoint& if (event == eMouseWheel) { - double angle = 1; + float angle = 1; Quat rot = GetRotation(); - rot.SetRotationXYZ(Ang3(0, 0, rot.GetRotZ() + DEG2RAD(flags > 0 ? angle * (-1) : angle))); + rot.SetRotationXYZ(Ang3(0.f, 0.f, rot.GetRotZ() + DEG2RAD(flags > 0 ? angle * (-1) : angle))); SetRotation(rot); } return MOUSECREATE_CONTINUE; @@ -1857,10 +1857,10 @@ bool CBaseObject::HitTestRectBounds(HitContext& hc, const AABB& box) const int kMaxSizeOfEdgeList0(4); Edge2D edgelist0[kMaxSizeOfEdgeList0] = { - Edge2D(Vec2(hc.rect.left(), hc.rect.top()), Vec2(hc.rect.right(), hc.rect.top())), - Edge2D(Vec2(hc.rect.right(), hc.rect.top()), Vec2(hc.rect.right(), hc.rect.bottom())), - Edge2D(Vec2(hc.rect.right(), hc.rect.bottom()), Vec2(hc.rect.left(), hc.rect.bottom())), - Edge2D(Vec2(hc.rect.left(), hc.rect.bottom()), Vec2(hc.rect.left(), hc.rect.top())) + Edge2D(Vec2(static_cast(hc.rect.left()), static_cast(hc.rect.top())), Vec2(static_cast(hc.rect.right()), static_cast(hc.rect.top()))), + Edge2D(Vec2(static_cast(hc.rect.right()), static_cast(hc.rect.top())), Vec2(static_cast(hc.rect.right()), static_cast(hc.rect.bottom()))), + Edge2D(Vec2(static_cast(hc.rect.right()), static_cast(hc.rect.bottom())), Vec2(static_cast(hc.rect.left()), static_cast(hc.rect.bottom()))), + Edge2D(Vec2(static_cast(hc.rect.left()), static_cast(hc.rect.bottom())), Vec2(static_cast(hc.rect.left()), static_cast(hc.rect.top()))) }; const int kMaxSizeOfEdgeList1(8); @@ -1888,7 +1888,7 @@ bool CBaseObject::HitTestRectBounds(HitContext& hc, const AABB& box) pointsForRegion1.reserve(kMaxSizeOfEdgeList1); for (int i = 0; i < kMaxSizeOfEdgeList1; ++i) { - pointsForRegion1.push_back(Vec3(obb_p[i].x(), obb_p[i].y(), 0)); + pointsForRegion1.push_back(Vec3(static_cast(obb_p[i].x()), static_cast(obb_p[i].y()), 0.0f)); } std::vector convexHullForRegion1; diff --git a/Code/Editor/Objects/SelectionGroup.cpp b/Code/Editor/Objects/SelectionGroup.cpp index 57a86262aa..f2b7b9ddaf 100644 --- a/Code/Editor/Objects/SelectionGroup.cpp +++ b/Code/Editor/Objects/SelectionGroup.cpp @@ -157,7 +157,7 @@ Vec3 CSelectionGroup::GetCenter() const } if (GetCount() > 0) { - c /= GetCount(); + c /= static_cast(GetCount()); } return c; } diff --git a/Code/Editor/Plugin.cpp b/Code/Editor/Plugin.cpp index e73b9daa2c..4f6fe0279d 100644 --- a/Code/Editor/Plugin.cpp +++ b/Code/Editor/Plugin.cpp @@ -136,7 +136,7 @@ IClassDesc* CClassFactory::FindClass(const char* pClassName) const return nullptr; } - QString name = QString(pClassName).left(pSubClassName - pClassName); + QString name = QString(pClassName).left(static_cast(pSubClassName - pClassName)); return stl::find_in_map(m_nameToClass, name, (IClassDesc*)nullptr); } diff --git a/Code/Editor/PluginManager.cpp b/Code/Editor/PluginManager.cpp index 350102ead2..494748dc79 100644 --- a/Code/Editor/PluginManager.cpp +++ b/Code/Editor/PluginManager.cpp @@ -262,7 +262,7 @@ void CPluginManager::RegisterPlugin(QLibrary* dllHandle, IPlugin* pPlugin) entry.hLibrary = dllHandle; entry.pPlugin = pPlugin; m_plugins.push_back(entry); - m_uuidPluginMap[m_currentUUID] = pPlugin; + m_uuidPluginMap[static_cast(m_currentUUID)] = pPlugin; ++m_currentUUID; } diff --git a/Code/Editor/Plugins/ComponentEntityEditorPlugin/Objects/ComponentEntityObject.cpp b/Code/Editor/Plugins/ComponentEntityEditorPlugin/Objects/ComponentEntityObject.cpp index 85730d327b..74187fc9c5 100644 --- a/Code/Editor/Plugins/ComponentEntityEditorPlugin/Objects/ComponentEntityObject.cpp +++ b/Code/Editor/Plugins/ComponentEntityEditorPlugin/Objects/ComponentEntityObject.cpp @@ -661,8 +661,8 @@ bool CComponentEntityObject::HitHelperTest(HitContext& hc) if (IsEntityIconVisible()) { const QPoint entityScreenPos = hc.view->WorldToView(GetWorldPos()); - const float screenPosX = entityScreenPos.x(); - const float screenPosY = entityScreenPos.y(); + const float screenPosX = static_cast(entityScreenPos.x()); + const float screenPosY = static_cast(entityScreenPos.y()); const float iconRange = static_cast(s_kIconSize / 2); if ((hc.point2d.x() >= screenPosX - iconRange && hc.point2d.x() <= screenPosX + iconRange) diff --git a/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp b/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp index b10fe35513..276e6e4c83 100644 --- a/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp +++ b/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp @@ -626,7 +626,7 @@ void SandboxIntegrationManager::PopulateEditorGlobalContextMenu(QMenu* menu, con { view->GetDimensions(&width, &height); } - m_contextMenuViewPoint.Set(width / 2, height / 2); + m_contextMenuViewPoint.Set(static_cast(width / 2), static_cast(height / 2)); } else { @@ -998,7 +998,7 @@ void SandboxIntegrationManager::HandleObjectModeSelection(const AZ::Vector2& poi if (m_inObjectPickMode) { CViewport* view = GetIEditor()->GetViewManager()->GetGameViewport(); - const QPoint viewPoint(point.GetX(), point.GetY()); + const QPoint viewPoint(static_cast(point.GetX()), static_cast(point.GetY())); HitContext hitInfo; hitInfo.view = view; @@ -1440,7 +1440,7 @@ void SandboxIntegrationManager::ContextMenu_NewEntity() // will be created at the origin. if (view) { - const QPoint viewPoint(m_contextMenuViewPoint.GetX(), m_contextMenuViewPoint.GetY()); + const QPoint viewPoint(static_cast(m_contextMenuViewPoint.GetX()), static_cast(m_contextMenuViewPoint.GetY())); worldPosition = view->GetHitLocation(viewPoint); } @@ -1630,7 +1630,7 @@ void SandboxIntegrationManager::InstantiateSliceFromAssetId(const AZ::Data::Asse // will be instantiated at the origin. if (view) { - const QPoint viewPoint(m_contextMenuViewPoint.GetX(), m_contextMenuViewPoint.GetY()); + const QPoint viewPoint(static_cast(m_contextMenuViewPoint.GetX()), static_cast(m_contextMenuViewPoint.GetY())); sliceWorldTransform = AZ::Transform::CreateTranslation(LYVec3ToAZVec3(view->SnapToGrid(view->ViewToWorld(viewPoint)))); } diff --git a/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerListModel.cpp b/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerListModel.cpp index c1938184db..95fe28f406 100644 --- a/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerListModel.cpp +++ b/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerListModel.cpp @@ -2476,10 +2476,10 @@ void OutlinerItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& auto backgroundBoxRect = option.rect; - backgroundBoxRect.setX(backgroundBoxRect.x() + 0.5); - backgroundBoxRect.setY(backgroundBoxRect.y() + 2.5); - backgroundBoxRect.setWidth(backgroundBoxRect.width() - 1.0); - backgroundBoxRect.setHeight(backgroundBoxRect.height() - 1.0); + backgroundBoxRect.setX(static_cast(backgroundBoxRect.x() + 0.5f)); + backgroundBoxRect.setY(static_cast(backgroundBoxRect.y() + 2.5f)); + backgroundBoxRect.setWidth(static_cast(backgroundBoxRect.width() - 1.0f)); + backgroundBoxRect.setHeight(static_cast(backgroundBoxRect.height() - 1.0f)); const qreal sliceBorderHeight = 0.8f; @@ -2513,7 +2513,7 @@ void OutlinerItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& else { auto newRect = option.rect; - newRect.setHeight(newRect.height() - 1.0); + newRect.setHeight(static_cast(newRect.height() - 1.0f)); path.addRect(newRect); } diff --git a/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerTreeView.cpp b/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerTreeView.cpp index 158e45d6e2..452db49d37 100644 --- a/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerTreeView.cpp +++ b/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerTreeView.cpp @@ -274,8 +274,8 @@ void OutlinerTreeView::drawBranches(QPainter* painter, const QRect& rect, const // if the item has children offset the drawn line to compensate for drawn expander buttons bool hasChildren = previousIndex.model()->index(0, 0, previousIndex).isValid(); int horizontalLineY = rect.top() + rectHalfHeight; - int horizontalLineLeft = rect.right() - indentation() * 1.5f; - int horizontalLineRight = hasChildren ? (lineBaseX - indentation()) : (lineBaseX - indentation() * 0.5f); + int horizontalLineLeft = static_cast(rect.right() - indentation() * 1.5f); + int horizontalLineRight = hasChildren ? (lineBaseX - indentation()) : static_cast(lineBaseX - indentation() * 0.5f); painter->drawLine(horizontalLineLeft, horizontalLineY, horizontalLineRight, horizontalLineY); } @@ -284,7 +284,7 @@ void OutlinerTreeView::drawBranches(QPainter* painter, const QRect& rect, const bool hasNext = previousIndex.sibling(previousIndex.row() + 1, previousIndex.column()).isValid(); if (hasNext || previousIndex == index) { - int verticalLineX = lineBaseX - indentation() * 1.5f; + int verticalLineX = static_cast(lineBaseX - indentation() * 1.5f); int verticalLineTop = rect.top(); int verticalLineBottom = hasNext ? rect.bottom() : rect.bottom() - rectHalfHeight; painter->drawLine(verticalLineX, verticalLineTop, verticalLineX, verticalLineBottom); diff --git a/Code/Editor/Plugins/EditorAssetImporter/AssetImporterWindow.cpp b/Code/Editor/Plugins/EditorAssetImporter/AssetImporterWindow.cpp index f9b2c6c023..98bf228391 100644 --- a/Code/Editor/Plugins/EditorAssetImporter/AssetImporterWindow.cpp +++ b/Code/Editor/Plugins/EditorAssetImporter/AssetImporterWindow.cpp @@ -500,10 +500,10 @@ void AssetImporterWindow::SetTitle(const char* filePath) AZStd::string extension; if (AzFramework::StringFunc::Path::GetExtension(filePath, extension, false)) { - extension[0] = toupper(extension[0]); + extension[0] = static_cast(toupper(extension[0])); for (size_t i = 1; i < extension.size(); ++i) { - extension[i] = tolower(extension[i]); + extension[i] = static_cast(tolower(extension[i])); } } else diff --git a/Code/Editor/PythonEditorFuncs.cpp b/Code/Editor/PythonEditorFuncs.cpp index 2b7bca3b0b..dff41c0a86 100644 --- a/Code/Editor/PythonEditorFuncs.cpp +++ b/Code/Editor/PythonEditorFuncs.cpp @@ -76,7 +76,7 @@ namespace } else if (pCVar->GetType() == CVAR_FLOAT) { - PySetCVarFromFloat(pName, std::stod(pValue)); + PySetCVarFromFloat(pName, static_cast(std::stod(pValue))); } else if (pCVar->GetType() != CVAR_STRING) { @@ -152,11 +152,11 @@ namespace } else if (pCVar->GetType() == CVAR_INT) { - PySetCVarFromInt(pName, AZStd::any_cast(value)); + PySetCVarFromInt(pName, static_cast(AZStd::any_cast(value))); } else if (pCVar->GetType() == CVAR_FLOAT) { - PySetCVarFromFloat(pName, AZStd::any_cast(value)); + PySetCVarFromFloat(pName, static_cast(AZStd::any_cast(value))); } else if (pCVar->GetType() == CVAR_STRING) { @@ -548,13 +548,11 @@ namespace if (title.empty()) { throw std::runtime_error("Incorrect title argument passed in. "); - return result; } if (values.size() == 0) { throw std::runtime_error("Empty value list passed in. "); - return result; } QStringList list; diff --git a/Code/Editor/QtUI/PixmapLabelPreview.cpp b/Code/Editor/QtUI/PixmapLabelPreview.cpp index a98c743afb..9c415a6c4d 100644 --- a/Code/Editor/QtUI/PixmapLabelPreview.cpp +++ b/Code/Editor/QtUI/PixmapLabelPreview.cpp @@ -31,7 +31,7 @@ int PixmapLabelPreview::heightForWidth(int width) const return width; } - return ((qreal)m_pixmap.height() * width) / m_pixmap.width(); + return static_cast(((qreal)m_pixmap.height() * width) / m_pixmap.width()); } diff --git a/Code/Editor/QtViewPaneManager.cpp b/Code/Editor/QtViewPaneManager.cpp index d8111aa09c..022bb6ecd9 100644 --- a/Code/Editor/QtViewPaneManager.cpp +++ b/Code/Editor/QtViewPaneManager.cpp @@ -1102,7 +1102,7 @@ void QtViewPaneManager::RestoreDefaultLayout(bool resetSettings) entityInspectorViewPane->m_dockWidget->setFloating(false); static const float tabWidgetWidthPercentage = 0.2f; - int newWidth = (float)screenWidth * tabWidgetWidthPercentage; + int newWidth = static_cast((float)screenWidth * tabWidgetWidthPercentage); if (levelInspectorPane) { @@ -1139,7 +1139,7 @@ void QtViewPaneManager::RestoreDefaultLayout(bool resetSettings) // so that they get an appropriate default width since the minimum sizes have // been removed from these widgets static const float entityOutlinerWidthPercentage = 0.15f; - int newWidth = (float)screenWidth * entityOutlinerWidthPercentage; + int newWidth = static_cast((float)screenWidth * entityOutlinerWidthPercentage); m_mainWindow->resizeDocks({ entityOutlinerViewPane->m_dockWidget }, { newWidth }, Qt::Horizontal); } diff --git a/Code/Editor/Settings.cpp b/Code/Editor/Settings.cpp index 259f71b69b..8672bad5c4 100644 --- a/Code/Editor/Settings.cpp +++ b/Code/Editor/Settings.cpp @@ -394,7 +394,7 @@ void SEditorSettings::LoadValue(const char* sSection, const char* sKey, float& v { const SettingsGroup sg(sSection); const QString defaultVal = s_editorSettings()->value(sKey, QString::number(value)).toString(); - value = defaultVal.toDouble(); + value = defaultVal.toFloat(); if (GetIEditor()->GetSettingsManager()) { diff --git a/Code/Editor/ToolBox.cpp b/Code/Editor/ToolBox.cpp index 1f08bd74fc..cfebc378f7 100644 --- a/Code/Editor/ToolBox.cpp +++ b/Code/Editor/ToolBox.cpp @@ -60,7 +60,7 @@ void CToolBoxCommand::Execute() const // Toggle the variable. float val = GetIEditor()->GetConsoleVar(m_text.toUtf8().data()); bool bOn = val != 0; - GetIEditor()->SetConsoleVar(m_text.toUtf8().data(), (bOn) ? 0 : 1); + GetIEditor()->SetConsoleVar(m_text.toUtf8().data(), (bOn) ? 0.0f : 1.0f); } else { @@ -186,7 +186,6 @@ const CToolBoxMacro* CToolBoxManager::GetMacro(int iIndex, bool bToolbox) const assert(0 <= iIndex && iIndex < m_shelveMacros.size()); return m_shelveMacros[iIndex]; } - return nullptr; } ////////////////////////////////////////////////////////////////////////// @@ -202,7 +201,6 @@ CToolBoxMacro* CToolBoxManager::GetMacro(int iIndex, bool bToolbox) assert(0 <= iIndex && iIndex < m_shelveMacros.size()); return m_shelveMacros[iIndex]; } - return nullptr; } ////////////////////////////////////////////////////////////////////////// @@ -275,7 +273,6 @@ CToolBoxMacro* CToolBoxManager::NewMacro(const QString& title, bool bToolbox, in m_shelveMacros.push_back(pNewTool); return pNewTool; } - return nullptr; } ////////////////////////////////////////////////////////////////////////// diff --git a/Code/Editor/TrackView/SequenceBatchRenderDialog.cpp b/Code/Editor/TrackView/SequenceBatchRenderDialog.cpp index aea655e9d3..33f1b0d441 100644 --- a/Code/Editor/TrackView/SequenceBatchRenderDialog.cpp +++ b/Code/Editor/TrackView/SequenceBatchRenderDialog.cpp @@ -93,7 +93,7 @@ static void UpdateAtomOutputFrameCaptureView(TrackView::AtomOutputFrameCapture& const AZ::EntityId activeCameraEntityId = TrackView::ActiveCameraEntityId(); atomOutputFrameCapture.UpdateView( TrackView::TransformFromEntityId(activeCameraEntityId), - TrackView::ProjectionFromCameraEntityId(activeCameraEntityId, width, height)); + TrackView::ProjectionFromCameraEntityId(activeCameraEntityId, static_cast(width), static_cast(height))); } CSequenceBatchRenderDialog::CSequenceBatchRenderDialog(float fps, QWidget* pParent /* = nullptr */) @@ -170,10 +170,10 @@ void CSequenceBatchRenderDialog::OnInitDialog() connect(m_ui->m_endFrame, editingFinished, this, &CSequenceBatchRenderDialog::OnEndFrameChange); connect(m_ui->m_imageFormatCombo, static_cast(&QComboBox::currentIndexChanged), this, &CSequenceBatchRenderDialog::OnImageFormatChange); - const float bigEnoughNumber = 1000000.0f; - m_ui->m_startFrame->setRange(0.0f, bigEnoughNumber); + const int bigEnoughNumber = 1000000; + m_ui->m_startFrame->setRange(0, bigEnoughNumber); - m_ui->m_endFrame->setRange(0.0f, bigEnoughNumber); + m_ui->m_endFrame->setRange(0, bigEnoughNumber); // Fill the sequence combo box. bool activeSequenceWasSet = false; @@ -301,8 +301,8 @@ void CSequenceBatchRenderDialog::OnRenderItemSelChange() } } // frame range - m_ui->m_startFrame->setValue(item.frameRange.start * m_fpsForTimeToFrameConversion); - m_ui->m_endFrame->setValue(item.frameRange.end * m_fpsForTimeToFrameConversion); + m_ui->m_startFrame->setValue(static_cast(item.frameRange.start * m_fpsForTimeToFrameConversion)); + m_ui->m_endFrame->setValue(static_cast(item.frameRange.end * m_fpsForTimeToFrameConversion)); // folder m_ui->m_destinationEdit->setText(item.folder); // fps @@ -580,12 +580,12 @@ void CSequenceBatchRenderDialog::OnSequenceSelected() // Adjust the frame range. float sFrame = pSequence->GetTimeRange().start * m_fpsForTimeToFrameConversion; float eFrame = pSequence->GetTimeRange().end * m_fpsForTimeToFrameConversion; - m_ui->m_startFrame->setRange(0.0f, eFrame); - m_ui->m_endFrame->setRange(0.0f, eFrame); + m_ui->m_startFrame->setRange(0, static_cast(eFrame)); + m_ui->m_endFrame->setRange(0, static_cast(eFrame)); // Set the default start/end frames properly. - m_ui->m_startFrame->setValue(sFrame); - m_ui->m_endFrame->setValue(eFrame); + m_ui->m_startFrame->setValue(static_cast(sFrame)); + m_ui->m_endFrame->setValue(static_cast(eFrame)); m_ui->m_shotCombo->clear(); // Fill the shot combo box with the names of director nodes. diff --git a/Code/Editor/TrackView/TVCustomizeTrackColorsDlg.cpp b/Code/Editor/TrackView/TVCustomizeTrackColorsDlg.cpp index e2f8a4f7a2..ae1080a9c1 100644 --- a/Code/Editor/TrackView/TVCustomizeTrackColorsDlg.cpp +++ b/Code/Editor/TrackView/TVCustomizeTrackColorsDlg.cpp @@ -367,7 +367,7 @@ bool CTVCustomizeTrackColorsDlg::Import(const QString& fullPath) { return entry.paramType == paramType; }); - int entryIndex = pEntry - g_trackEntries; + int entryIndex = static_cast(pEntry - g_trackEntries); if (entryIndex >= arraysize(g_trackEntries)) // If not found, skip this. { continue; diff --git a/Code/Editor/TrackView/TVSequenceProps.cpp b/Code/Editor/TrackView/TVSequenceProps.cpp index 1ac31d7e2b..d4e06d0c94 100644 --- a/Code/Editor/TrackView/TVSequenceProps.cpp +++ b/Code/Editor/TrackView/TVSequenceProps.cpp @@ -106,8 +106,8 @@ void CTVSequenceProps::MoveScaleKeys() // Move/Rescale the sequence to a new time range. Range timeRangeOld = m_pSequence->GetTimeRange(); Range timeRangeNew; - timeRangeNew.start = ui->START_TIME->value(); - timeRangeNew.end = ui->END_TIME->value(); + timeRangeNew.start = static_cast(ui->START_TIME->value()); + timeRangeNew.end = static_cast(ui->END_TIME->value()); if (!(timeRangeNew == timeRangeOld)) { @@ -123,14 +123,14 @@ void CTVSequenceProps::UpdateSequenceProps(const QString& name) } Range timeRange; - timeRange.start = ui->START_TIME->value(); - timeRange.end = ui->END_TIME->value(); + timeRange.start = static_cast(ui->START_TIME->value()); + timeRange.end = static_cast(ui->END_TIME->value()); if (m_timeUnit == Frames) { float invFPS = 1.0f / m_FPS; - timeRange.start = ui->START_TIME->value() * invFPS; - timeRange.end = ui->END_TIME->value() * invFPS; + timeRange.start = static_cast(ui->START_TIME->value()) * invFPS; + timeRange.end = static_cast(ui->END_TIME->value()) * invFPS; } m_pSequence->SetTimeRange(timeRange); diff --git a/Code/Editor/TrackView/TrackViewDialog.cpp b/Code/Editor/TrackView/TrackViewDialog.cpp index da3e7cebe2..f1701f9e20 100644 --- a/Code/Editor/TrackView/TrackViewDialog.cpp +++ b/Code/Editor/TrackView/TrackViewDialog.cpp @@ -1765,7 +1765,7 @@ void CTrackViewDialog::OnSnapFPS() if (ok) { m_wndDopeSheet->SetSnapFPS(fps); - m_wndCurveEditor->SetFPS(fps); + m_wndCurveEditor->SetFPS(static_cast(fps)); SetCursorPosText(GetIEditor()->GetAnimation()->GetTime()); } @@ -1828,7 +1828,7 @@ void CTrackViewDialog::ReadMiscSettings() if (settings.contains(s_kFrameSnappingFPSEntry)) { - float fps = settings.value(s_kFrameSnappingFPSEntry).toDouble(); + float fps = settings.value(s_kFrameSnappingFPSEntry).toFloat(); if (fps >= s_kMinimumFrameSnappingFPS && fps <= s_kMaximumFrameSnappingFPS) { m_wndDopeSheet->SetSnapFPS(FloatToIntRet(fps)); diff --git a/Code/Editor/TrackView/TrackViewDopeSheetBase.cpp b/Code/Editor/TrackView/TrackViewDopeSheetBase.cpp index f74d51c421..d0034b2da4 100644 --- a/Code/Editor/TrackView/TrackViewDopeSheetBase.cpp +++ b/Code/Editor/TrackView/TrackViewDopeSheetBase.cpp @@ -146,8 +146,7 @@ CTrackViewDopeSheetBase::~CTrackViewDopeSheetBase() ////////////////////////////////////////////////////////////////////////// int CTrackViewDopeSheetBase::TimeToClient(float time) const { - int x = m_leftOffset - m_scrollOffset.x() + (time * m_timeScale); - return x; + return static_cast(m_leftOffset - m_scrollOffset.x() + (time * m_timeScale)); } ////////////////////////////////////////////////////////////////////////// @@ -193,7 +192,7 @@ void CTrackViewDopeSheetBase::SetTimeRange(float start, float end) m_timeRange.Set(start, end); - SetHorizontalExtent(-m_leftOffset, m_timeRange.end * m_timeScale - m_leftOffset); + SetHorizontalExtent(-m_leftOffset, static_cast(m_timeRange.end * m_timeScale - m_leftOffset)); } ////////////////////////////////////////////////////////////////////////// @@ -263,7 +262,7 @@ void CTrackViewDopeSheetBase::SetTimeScale(float timeScale, float fAnchorTime) update(); - SetHorizontalExtent(-m_leftOffset, m_timeRange.end * m_timeScale); + SetHorizontalExtent(-m_leftOffset, static_cast(m_timeRange.end * m_timeScale)); ComputeFrameSteps(GetVisibleRange()); @@ -353,15 +352,15 @@ float CTrackViewDopeSheetBase::TickSnap(float time) const double tickTime = GetTickTime(); double t = floor(((double)time / tickTime) + 0.5); t *= tickTime; - return t; + return static_cast(t); } ////////////////////////////////////////////////////////////////////////// float CTrackViewDopeSheetBase::TimeFromPoint(const QPoint& point) const { int x = point.x() - m_leftOffset + m_scrollOffset.x(); - double t = (double)x / m_timeScale; - return (float)TickSnap(t); + float t = static_cast(x) / m_timeScale; + return TickSnap(t); } ////////////////////////////////////////////////////////////////////////// @@ -369,7 +368,7 @@ float CTrackViewDopeSheetBase::TimeFromPointUnsnapped(const QPoint& point) const { int x = point.x() - m_leftOffset + m_scrollOffset.x(); double t = (double)x / m_timeScale; - return t; + return static_cast(t); } void CTrackViewDopeSheetBase::mousePressEvent(QMouseEvent* event) @@ -1783,7 +1782,7 @@ float CTrackViewDopeSheetBase::FrameSnap(float time) const { double t = floor((double)time / m_snapFrameTime + 0.5); t = t * m_snapFrameTime; - return t; + return static_cast(t); } ////////////////////////////////////////////////////////////////////////// @@ -2003,9 +2002,10 @@ bool CTrackViewDopeSheetBase::CreateColorKey(CTrackViewTrack* pTrack, float keyT Vec3 vColor(0, 0, 0); pTrack->GetValue(keyTime, vColor); - const AZ::Color defaultColor(clamp_tpl(FloatToIntRet(vColor.x), 0, 255), - clamp_tpl(FloatToIntRet(vColor.y), 0, 255), - clamp_tpl(FloatToIntRet(vColor.z), 0, 255), + const AZ::Color defaultColor( + clamp_tpl(static_cast(FloatToIntRet(vColor.x)), 0, 255), + clamp_tpl(static_cast(FloatToIntRet(vColor.y)), 0, 255), + clamp_tpl(static_cast(FloatToIntRet(vColor.z)), 0, 255), 255); AzQtComponents::ColorPicker dlg(AzQtComponents::ColorPicker::Configuration::RGB, QString(), this); dlg.setWindowTitle(tr("Select Color")); @@ -2054,7 +2054,7 @@ void CTrackViewDopeSheetBase::OnCurrentColorChange(const AZ::Color& color) void CTrackViewDopeSheetBase::UpdateColorKey(const QColor& color, bool addToUndo) { - ColorF colArray(color.red(), color.green(), color.blue(), color.alpha()); + ColorF colArray(static_cast(color.redF()), static_cast(color.greenF()), static_cast(color.blueF()), static_cast(color.alphaF())); CTrackViewSequence* sequence = m_colorUpdateTrack->GetSequence(); if (nullptr != sequence) @@ -2119,9 +2119,10 @@ void CTrackViewDopeSheetBase::EditSelectedColorKey(CTrackViewTrack* pTrack) Vec3 color; pTrack->GetValue(m_colorUpdateKeyTime, color); - const AZ::Color defaultColor(clamp_tpl(FloatToIntRet(color.x), 0, 255), - clamp_tpl(FloatToIntRet(color.y), 0, 255), - clamp_tpl(FloatToIntRet(color.z), 0, 255), + const AZ::Color defaultColor( + clamp_tpl(static_cast(FloatToIntRet(color.x)), AZ::u8(0), AZ::u8(255)), + clamp_tpl(static_cast(FloatToIntRet(color.y)), AZ::u8(0), AZ::u8(255)), + clamp_tpl(static_cast(FloatToIntRet(color.z)), AZ::u8(0), AZ::u8(255)), 255); AzQtComponents::ColorPicker picker(AzQtComponents::ColorPicker::Configuration::RGB); @@ -2369,12 +2370,12 @@ void CTrackViewDopeSheetBase::DrawTicks(QPainter* painter, const QRect& rc, Rang nNumberTicks = 8; } - double start = TickSnap(timeRange.start); - double step = 1.0 / m_ticksStep; + float start = TickSnap(timeRange.start); + float step = 1.0f / static_cast(m_ticksStep); - for (double t = 0.0f; t <= timeRange.end + step; t += step) + for (float t = 0.0f; t <= timeRange.end + step; t += step) { - double st = TickSnap(t); + float st = TickSnap(t); if (st > timeRange.end) { st = timeRange.end; @@ -2393,7 +2394,7 @@ void CTrackViewDopeSheetBase::DrawTicks(QPainter* painter, const QRect& rc, Rang continue; } - int k = RoundFloatToInt(st * m_ticksStep); + int k = RoundFloatToInt(st * static_cast(m_ticksStep)); if (k % nNumberTicks == 0) { if (st >= start) @@ -3218,7 +3219,7 @@ void CTrackViewDopeSheetBase::ComputeFrameSteps(const Range& visRange) float nBIntermediateTicks = 5; m_fFrameLabelStep = fFact * afStepTable[nStepIdx]; - if (TimeToClient(m_fFrameLabelStep) - TimeToClient(0) > 1300) + if (TimeToClient(static_cast(m_fFrameLabelStep)) - TimeToClient(0.0f) > 1300) { nBIntermediateTicks = 10; } @@ -3230,7 +3231,7 @@ void CTrackViewDopeSheetBase::ComputeFrameSteps(const Range& visRange) void CTrackViewDopeSheetBase::DrawTimeLineInFrames(QPainter* painter, const QRect& rc, [[maybe_unused]] const QColor& lineCol, const QColor& textCol, [[maybe_unused]] double step) { float fFramesPerSec = 1.0f / m_snapFrameTime; - float fInvFrameLabelStep = 1.0f / m_fFrameLabelStep; + float fInvFrameLabelStep = 1.0f / static_cast(m_fFrameLabelStep); Range VisRange = GetVisibleRange(); const Range& timeRange = m_timeRange; @@ -3238,9 +3239,9 @@ void CTrackViewDopeSheetBase::DrawTimeLineInFrames(QPainter* painter, const QRec const QPen ltgray(QColor(90, 90, 90)); const QPen black(textCol); - for (double t = TickSnap(timeRange.start); t <= timeRange.end + m_fFrameTickStep; t += m_fFrameTickStep) + for (float t = TickSnap(timeRange.start); t <= timeRange.end + static_cast(m_fFrameTickStep); t += static_cast(m_fFrameTickStep)) { - double st = t; + float st = t; if (st > timeRange.end) { st = timeRange.end; @@ -3285,9 +3286,9 @@ void CTrackViewDopeSheetBase::DrawTimeLineInSeconds(QPainter* painter, const QRe const QPen ltgray(QColor(90, 90, 90)); const QPen black(textCol); - for (double t = TickSnap(timeRange.start); t <= timeRange.end + step; t += step) + for (float t = TickSnap(timeRange.start); t <= timeRange.end + static_cast(step); t += static_cast(step)) { - double st = TickSnap(t); + float st = TickSnap(t); if (st > timeRange.end) { st = timeRange.end; @@ -3306,7 +3307,7 @@ void CTrackViewDopeSheetBase::DrawTimeLineInSeconds(QPainter* painter, const QRe } int x = TimeToClient(st); - int k = RoundFloatToInt(st * m_ticksStep); + int k = RoundFloatToInt(st * static_cast(m_ticksStep)); if (k % nNumberTicks == 0) { painter->setPen(black); diff --git a/Code/Editor/TrackView/TrackViewNodes.cpp b/Code/Editor/TrackView/TrackViewNodes.cpp index b64df7e2eb..ae38323cc3 100644 --- a/Code/Editor/TrackView/TrackViewNodes.cpp +++ b/Code/Editor/TrackView/TrackViewNodes.cpp @@ -1419,7 +1419,7 @@ void CTrackViewNodesCtrl::OnNMRclick(QPoint point) { if (animNode) { - UINT_PTR menuId = cmd - eMI_AddTrackBase; + unsigned int menuId = cmd - eMI_AddTrackBase; if (animNode->GetType() != AnimNodeType::AzEntity) { diff --git a/Code/Editor/Util/AffineParts.cpp b/Code/Editor/Util/AffineParts.cpp index c80ceb3ffa..d83a1986b9 100644 --- a/Code/Editor/Util/AffineParts.cpp +++ b/Code/Editor/Util/AffineParts.cpp @@ -158,11 +158,11 @@ static Quatern Qt_FromMatrix(HMatrix mat) if (tr >= 0.0) { s = sqrt(tr + mat[W][W]); - qu.w = s * 0.5; + qu.w = static_cast(s * 0.5); s = 0.5 / s; - qu.x = (mat[Z][Y] - mat[Y][Z]) * s; - qu.y = (mat[X][Z] - mat[Z][X]) * s; - qu.z = (mat[Y][X] - mat[X][Y]) * s; + qu.x = static_cast((mat[Z][Y] - mat[Y][Z]) * s); + qu.y = static_cast((mat[X][Z] - mat[Z][X]) * s); + qu.z = static_cast((mat[Y][X] - mat[X][Y]) * s); } else { @@ -180,11 +180,11 @@ static Quatern Qt_FromMatrix(HMatrix mat) #define caseMacro(i, j, k, I, J, K) \ case I: \ s = sqrt((mat[I][I] - (mat[J][J] + mat[K][K])) + mat[W][W]); \ - qu.i = s * 0.5; \ + qu.i = static_cast(s * 0.5); \ s = 0.5 / s; \ - qu.j = (mat[I][J] + mat[J][I]) * s; \ - qu.k = (mat[K][I] + mat[I][K]) * s; \ - qu.w = (mat[K][J] - mat[J][K]) * s; \ + qu.j = static_cast((mat[I][J] + mat[J][I]) * s); \ + qu.k = static_cast((mat[K][I] + mat[I][K]) * s); \ + qu.w = static_cast((mat[K][J] - mat[J][K]) * s); \ break caseMacro(x, y, z, X, Y, Z); caseMacro(y, z, x, Y, Z, X); @@ -263,7 +263,7 @@ static void make_reflector(float* v, float* u) u[0] = v[0]; u[1] = v[1]; u[2] = v[2] + ((v[2] < 0.0) ? -s : s); - s = sqrt(2.0 / vdot(u, u)); + s = static_cast(sqrt(2.0f / vdot(u, u))); u[0] = u[0] * s; u[1] = u[1] * s; u[2] = u[2] * s; @@ -407,8 +407,8 @@ float polar_decomp(HMatrix M, HMatrix Q, HMatrix S) MadjT_one = norm_one(MadjTk); MadjT_inf = norm_inf(MadjTk); gamma = sqrt(sqrt((MadjT_one * MadjT_inf) / (M_one * M_inf)) / fabs(det)); - g1 = gamma * 0.5; - g2 = 0.5 / (gamma * det); + g1 = gamma * 0.5f; + g2 = 0.5f / (gamma * det); mat_copy(Ek, =, Mk, 3); mat_binop(Mk, =, g1 * Mk, +, g2 * MadjTk, 3); mat_copy(Ek, -=, Mk, 3); @@ -424,7 +424,7 @@ float polar_decomp(HMatrix M, HMatrix Q, HMatrix S) { for (int j = i; j < 3; j++) { - S[i][j] = S[j][i] = 0.5 * (S[i][j] + S[j][i]); + S[i][j] = S[j][i] = 0.5f * (S[i][j] + S[j][i]); } } return (det); @@ -454,7 +454,7 @@ HVect spect_decomp(HMatrix S, HMatrix U) OffD[Z] = S[X][Y]; for (sweep = 20; sweep > 0; sweep--) { - float sm = fabs(OffD[X]) + fabs(OffD[Y]) + fabs(OffD[Z]); + float sm = static_cast(fabs(OffD[X]) + fabs(OffD[Y]) + fabs(OffD[Z])); if (sm == 0.0) { break; @@ -496,16 +496,16 @@ HVect spect_decomp(HMatrix S, HMatrix U) { a = U[j][p]; b = U[j][q]; - U[j][p] -= s * (b + tau * a); - U[j][q] += s * (a - tau * b); + U[j][p] -= static_cast(s * (b + tau * a)); + U[j][q] += static_cast(s * (a - tau * b)); } } } } - kv.x = Diag[X]; - kv.y = Diag[Y]; - kv.z = Diag[Z]; - kv.w = 1.0; + kv.x = static_cast(Diag[X]); + kv.y = static_cast(Diag[Y]); + kv.z = static_cast(Diag[Z]); + kv.w = 1.0f; return (kv); } @@ -650,7 +650,7 @@ Quatern snuggle(Quatern q, HVect* k) } qp = Qt_Mul(q, p); t = sqrt(mag[win] + 0.5); - p = Qt_Mul(p, Qt_(0.0, 0.0, -qp.z / t, qp.w / t)); + p = Qt_Mul(p, Qt_(0.0f, 0.0f, static_cast(-qp.z / t), static_cast(qp.w / t))); p = Qt_Mul(qtoz, Qt_Conj(p)); } else @@ -721,14 +721,14 @@ Quatern snuggle(Quatern q, HVect* k) int ii; for (ii = 0; ii < 4; ii++) { - pa[ii] = sgn(neg[ii], 0.5); + pa[ii] = static_cast(sgn(neg[ii], 0.5f)); } } cycle(ka, par) } else { /*big*/ - pa[hi] = sgn(neg[hi], 1.0); + pa[hi] = static_cast(sgn(neg[hi], 1.0f)); } } else @@ -752,7 +752,7 @@ Quatern snuggle(Quatern q, HVect* k) } else { /*big*/ - pa[hi] = sgn(neg[hi], 1.0); + pa[hi] = static_cast(sgn(neg[hi], 1.0f)); } } p.x = -pa[0]; diff --git a/Code/Editor/Util/FileUtil.cpp b/Code/Editor/Util/FileUtil.cpp index e39adcca82..435ec67a99 100644 --- a/Code/Editor/Util/FileUtil.cpp +++ b/Code/Editor/Util/FileUtil.cpp @@ -455,7 +455,7 @@ bool CFileUtil::ExtractDccFilenameUsingNamingConventions(const QString& assetFil ////////////////////////////////////////////////////////////////////////// void CFileUtil::FormatFilterString(QString& filter) { - const int numPipeChars = std::count(filter.begin(), filter.end(), '|'); + const int numPipeChars = static_cast(std::count(filter.begin(), filter.end(), '|')); if (numPipeChars == 1) { filter = QStringLiteral("%1||").arg(filter); diff --git a/Code/Editor/Util/GdiUtil.cpp b/Code/Editor/Util/GdiUtil.cpp index 8565aabf9d..1048b5f4dd 100644 --- a/Code/Editor/Util/GdiUtil.cpp +++ b/Code/Editor/Util/GdiUtil.cpp @@ -15,43 +15,6 @@ #include #include -bool ComputeThumbsLayoutInfo(float aContainerWidth, float aThumbWidth, float aMargin, UINT aThumbCount, UINT& rThumbsPerRow, float& rNewMargin) -{ - rThumbsPerRow = 0; - rNewMargin = 0; - - if (aThumbWidth <= 0 || aMargin <= 0 || (aThumbWidth + aMargin * 2) <= 0) - { - return false; - } - - if (aContainerWidth <= 0) - { - return true; - } - - rThumbsPerRow = (int) aContainerWidth / (aThumbWidth + aMargin * 2); - - if ((aThumbWidth + aMargin * 2) * aThumbCount < aContainerWidth) - { - rNewMargin = aMargin; - } - else - { - if (rThumbsPerRow > 0) - { - rNewMargin = (aContainerWidth - rThumbsPerRow * aThumbWidth); - - if (rNewMargin > 0) - { - rNewMargin = (float)rNewMargin / rThumbsPerRow / 2.0f; - } - } - } - - return true; -} - QColor ScaleColor(const QColor& c, float aScale) { QColor aColor = c; diff --git a/Code/Editor/Util/GdiUtil.h b/Code/Editor/Util/GdiUtil.h index 55165b5799..f38cbc0c0e 100644 --- a/Code/Editor/Util/GdiUtil.h +++ b/Code/Editor/Util/GdiUtil.h @@ -14,16 +14,6 @@ #define CRYINCLUDE_EDITOR_UTIL_GDIUTIL_H #pragma once -//! function used to compute thumbs per row and spacing, used in asset browser and other tools where thumb layout is needed and maybe GDI canvas used -//! \param aContainerWidth the thumbs' container width -//! \param aThumbWidth the thumb image width -//! \param aMargin the thumb default minimum horizontal margin -//! \param aThumbCount the thumb count -//! \param rThumbsPerRow returned thumb count per single row -//! \param rNewMargin returned new computed margin between thumbs -//! \note The margin between thumbs will grow/shrink dynamically to keep up with the thumb count per row -bool ComputeThumbsLayoutInfo(float aContainerWidth, float aThumbWidth, float aMargin, UINT aThumbCount, UINT& rThumbsPerRow, float& rNewMargin); - QColor ScaleColor(const QColor& coor, float aScale); //! This class loads alpha-channel bitmaps and holds a DC for use with AlphaBlend function diff --git a/Code/Editor/Util/ImageASC.cpp b/Code/Editor/Util/ImageASC.cpp index 8a63ebdc6a..c166917a68 100644 --- a/Code/Editor/Util/ImageASC.cpp +++ b/Code/Editor/Util/ImageASC.cpp @@ -132,7 +132,7 @@ bool CImageASC::Load(const QString& fileName, CFloatImage& image) token = azstrtok(nullptr, 0, seps, &nextToken); validData = validData && (azstricmp(token, "nodata_value") == 0); token = azstrtok(nullptr, 0, seps, &nextToken); - nodataValue = atof(token); + nodataValue = static_cast(atof(token)); if (!validData) { @@ -157,7 +157,7 @@ bool CImageASC::Load(const QString& fileName, CFloatImage& image) if (token != nullptr) { // Negative heights aren't supported, clamp to 0. - pixelValue = max(0.0, atof(token)); + pixelValue = max(0.0f, static_cast(atof(token))); // If this is a location we specifically don't have data for, set it to 0. if (pixelValue == nodataValue) diff --git a/Code/Editor/Util/ImageGif.cpp b/Code/Editor/Util/ImageGif.cpp index 383319a666..a9ab4efdaf 100644 --- a/Code/Editor/Util/ImageGif.cpp +++ b/Code/Editor/Util/ImageGif.cpp @@ -411,7 +411,7 @@ bool CImageGif::Load(const QString& fileName, CImageEx& outImage) FreeCode = FirstFree; CurCode = OldCode = Code = ReadCode(); FinChar = CurCode & BitMask; - AddToPixel (FinChar); + AddToPixel(static_cast(FinChar)); } else { @@ -455,7 +455,7 @@ bool CImageGif::Load(const QString& fileName, CImageEx& outImage) for (i = OutCount - 1; i >= 0; i--) { - AddToPixel (OutCode[i]); + AddToPixel(static_cast(OutCode[i])); } OutCount = 0; diff --git a/Code/Editor/Util/bitarray.h b/Code/Editor/Util/bitarray.h index f55d195fd1..5a887b02d5 100644 --- a/Code/Editor/Util/bitarray.h +++ b/Code/Editor/Util/bitarray.h @@ -220,7 +220,7 @@ public: b.resize((compsize + 1) << 3); out = (char*)b.m_bits; in = (char*)m_bits; - *out++ = bsize; + *out++ = static_cast(bsize); for (i = 0; i < bsize; i++) { *out++ = in[i]; @@ -239,7 +239,7 @@ public: } } i--; - *out++ = countz; + *out++ = static_cast(countz); } } } diff --git a/Code/Editor/ViewPane.cpp b/Code/Editor/ViewPane.cpp index 466274c06e..a932f05c79 100644 --- a/Code/Editor/ViewPane.cpp +++ b/Code/Editor/ViewPane.cpp @@ -646,7 +646,7 @@ namespace if (viewPane && viewPane->GetViewport()) { const QRect rcViewport = viewPane->GetViewport()->rect(); - return AZ::Vector2(rcViewport.width(), rcViewport.height()); + return AZ::Vector2(static_cast(rcViewport.width()), static_cast(rcViewport.height())); } else { diff --git a/Code/Editor/Viewport.cpp b/Code/Editor/Viewport.cpp index 873f555c80..2646f1cd50 100644 --- a/Code/Editor/Viewport.cpp +++ b/Code/Editor/Viewport.cpp @@ -419,7 +419,7 @@ void QtViewport::Update() ////////////////////////////////////////////////////////////////////////// QPoint QtViewport::WorldToView(const Vec3& wp) const { - return QPoint(wp.x, wp.y); + return QPoint(static_cast(wp.x), static_cast(wp.y)); } ////////////////////////////////////////////////////////////////////////// @@ -427,8 +427,8 @@ Vec3 QtViewport::WorldToView3D(const Vec3& wp, [[maybe_unused]] int nFlags) cons { QPoint p = WorldToView(wp); Vec3 out; - out.x = p.x(); - out.y = p.y(); + out.x = static_cast(p.x()); + out.y = static_cast(p.y()); out.z = wp.z; return out; } @@ -437,8 +437,8 @@ Vec3 QtViewport::WorldToView3D(const Vec3& wp, [[maybe_unused]] int nFlags) cons Vec3 QtViewport::ViewToWorld(const QPoint& vp, bool* pCollideWithTerrain, [[maybe_unused]] bool onlyTerrain, [[maybe_unused]] bool bSkipVegetation, [[maybe_unused]] bool bTestRenderMesh, [[maybe_unused]] bool* collideWithObject) const { Vec3 wp; - wp.x = vp.x(); - wp.y = vp.y(); + wp.x = static_cast(vp.x()); + wp.y = static_cast(vp.y()); wp.z = 0; if (pCollideWithTerrain) { @@ -520,7 +520,7 @@ void QtViewport::mouseMoveEvent(QMouseEvent* event) void QtViewport::wheelEvent(QWheelEvent* event) { - OnMouseWheel(event->modifiers(), event->angleDelta().y(), event->position().toPoint()); + OnMouseWheel(event->modifiers(), static_cast(event->angleDelta().y()), event->position().toPoint()); event->accept(); } @@ -1276,9 +1276,9 @@ float QtViewport::GetDistanceToLine(const Vec3& lineP1, const Vec3& lineP2, cons QPoint p2 = WorldToView(lineP2); return PointToLineDistance2D( - Vec3(p1.x(), p1.y(), 0), - Vec3(p2.x(), p2.y(), 0), - Vec3(point.x(), point.y(), 0)); + Vec3(static_cast(p1.x()), static_cast(p1.y()), 0.0f), + Vec3(static_cast(p2.x()), static_cast(p2.y()), 0.0f), + Vec3(static_cast(point.x()), static_cast(point.y()), 0.0f)); } ////////////////////////////////////////////////////////////////////////// diff --git a/Code/Editor/ViewportTitleDlg.cpp b/Code/Editor/ViewportTitleDlg.cpp index b54ce54ddd..0c59c1e9b5 100644 --- a/Code/Editor/ViewportTitleDlg.cpp +++ b/Code/Editor/ViewportTitleDlg.cpp @@ -306,7 +306,7 @@ void CViewportTitleDlg::OnInitDialog() AZ::VR::VREventBus::Handler::BusConnect(); QFontMetrics metrics({}); - int width = metrics.boundingRect("-9999.99").width() * m_fieldWidthMultiplier; + int width = static_cast(metrics.boundingRect("-9999.99").width() * m_fieldWidthMultiplier); m_cameraSpeed->setFixedWidth(width); @@ -457,7 +457,7 @@ void CViewportTitleDlg::AddFOVMenus(QMenu* menu, std::function call float fov = gSettings.viewports.fDefaultFov; bool ok; - float f = customPreset.toDouble(&ok); + float f = customPreset.toFloat(&ok); if (ok) { fov = std::max(1.0f, f); @@ -477,7 +477,7 @@ void CViewportTitleDlg::OnMenuFOVCustom() if (ok) { - m_pViewPane->SetViewportFOV(fov); + m_pViewPane->SetViewportFOV(static_cast(fov)); // Update the custom presets. const QString text = QString::number(fov); @@ -973,12 +973,12 @@ void CViewportTitleDlg::OnAngleSnappingToggled() void CViewportTitleDlg::OnGridSpinBoxChanged(double value) { - SandboxEditor::SetGridSnappingSize(value); + SandboxEditor::SetGridSnappingSize(static_cast(value)); } void CViewportTitleDlg::OnAngleSpinBoxChanged(double value) { - SandboxEditor::SetAngleSnappingSize(value); + SandboxEditor::SetAngleSnappingSize(static_cast(value)); } void CViewportTitleDlg::UpdateOverFlowMenuState() From 3060b0c1bb83b087467a771805d5d9ae09d088ce Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Mon, 16 Aug 2021 15:56:49 -0700 Subject: [PATCH 474/803] Gems/EMotionFX Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../Code/EMotionFX/Source/ActorInstance.cpp | 2 +- .../Source/AnimGraph/AnimGraphModel.cpp | 12 ++++++------ .../Source/Editor/PropertyWidgets/PropertyTypes.cpp | 3 ++- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.cpp index 5a8fcda907..5a4ca95670 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.cpp @@ -1115,7 +1115,7 @@ namespace EMotionFX void ActorInstance::EnableAllNodes() { m_enabledNodes.resize(m_actor->GetNumNodes()); - std::iota(m_enabledNodes.begin(), m_enabledNodes.end(), 0); + std::iota(m_enabledNodes.begin(), m_enabledNodes.end(), uint16(0)); } // disable all nodes diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphModel.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphModel.cpp index 6e68a761de..a6733ee614 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphModel.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphModel.cpp @@ -562,9 +562,9 @@ namespace EMStudio ModelItemData modelItemData(graphInstance, animGraphObject); AZStd::pair itModelItemData = m_modelItemDataSet.equal_range(&modelItemData); - for (ModelItemDataSet::const_iterator it = itModelItemData.first; it != itModelItemData.second; ++it) + if (itModelItemData.first != itModelItemData.second) { - ModelItemData* modelItemData2 = *it; + ModelItemData* modelItemData2 = *itModelItemData.first; return createIndex(modelItemData2->m_row, 0, modelItemData2); } return QModelIndex(); @@ -590,9 +590,9 @@ namespace EMStudio // Find the model index ModelItemData modelItemData(animGraphInstance, animGraphObject); AZStd::pair itModelItemData = m_modelItemDataSet.equal_range(&modelItemData); - for (ModelItemDataSet::const_iterator it = itModelItemData.first; it != itModelItemData.second; ++it) + if (itModelItemData.first != itModelItemData.second) { - ModelItemData* modelItemData2 = *it; + ModelItemData* modelItemData2 = *itModelItemData.first; return createIndex(modelItemData2->m_row, 0, modelItemData2); } } @@ -603,9 +603,9 @@ namespace EMStudio // Find the model index ModelItemData modelItemData(nullptr, animGraphObject); AZStd::pair itModelItemData = m_modelItemDataSet.equal_range(&modelItemData); - for (ModelItemDataSet::const_iterator it = itModelItemData.first; it != itModelItemData.second; ++it) + if (itModelItemData.first != itModelItemData.second) { - ModelItemData* modelItemData2 = *it; + ModelItemData* modelItemData2 = *itModelItemData.first; return createIndex(modelItemData2->m_row, 0, modelItemData2); } } diff --git a/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/PropertyTypes.cpp b/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/PropertyTypes.cpp index e8c4ee69d8..a93ec07477 100644 --- a/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/PropertyTypes.cpp +++ b/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/PropertyTypes.cpp @@ -89,8 +89,9 @@ namespace EMotionFX AzToolsFramework::PropertyTypeRegistrationMessages::Bus::Broadcast(&AzToolsFramework::PropertyTypeRegistrationMessages::RegisterPropertyType, handler); } return propertyHandlers; -#endif +#else return AZStd::vector {}; +#endif } From 939c188448f0ef49930f560f8b1a28abb02ce88b Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Mon, 16 Aug 2021 15:57:05 -0700 Subject: [PATCH 475/803] Gems/GraphCanvas Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Gems/GraphCanvas/Code/Source/Widgets/GraphCanvasLabel.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/Gems/GraphCanvas/Code/Source/Widgets/GraphCanvasLabel.cpp b/Gems/GraphCanvas/Code/Source/Widgets/GraphCanvasLabel.cpp index fd7ac05cd2..e76487a4e8 100644 --- a/Gems/GraphCanvas/Code/Source/Widgets/GraphCanvasLabel.cpp +++ b/Gems/GraphCanvas/Code/Source/Widgets/GraphCanvasLabel.cpp @@ -432,7 +432,5 @@ namespace GraphCanvas default: return QGraphicsWidget::sizeHint(which, constraint); } - - return QGraphicsWidget::sizeHint(which, constraint); } } From 2ab9648425d922be3ebf0bb10fd408f9239350e8 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Mon, 16 Aug 2021 15:57:19 -0700 Subject: [PATCH 476/803] Gems/LyShine Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../Animation/Controls/UiTimelineCtrl.cpp | 14 +- .../Animation/UiAVCustomizeTrackColorsDlg.cpp | 2 +- .../Editor/Animation/UiAnimViewDialog.cpp | 4 +- .../Animation/UiAnimViewDopeSheetBase.cpp | 48 +++--- .../Code/Editor/Animation/UiAnimViewNodes.cpp | 144 ++++++++-------- Gems/LyShine/Code/Editor/QtHelpers.cpp | 5 +- Gems/LyShine/Code/Editor/ViewportIcon.cpp | 2 +- Gems/LyShine/Code/Editor/ViewportWidget.cpp | 8 +- Gems/LyShine/Code/Source/UiCanvasManager.cpp | 162 +++++++++--------- 9 files changed, 194 insertions(+), 195 deletions(-) diff --git a/Gems/LyShine/Code/Editor/Animation/Controls/UiTimelineCtrl.cpp b/Gems/LyShine/Code/Editor/Animation/Controls/UiTimelineCtrl.cpp index 4140cff935..3f9ba6e813 100644 --- a/Gems/LyShine/Code/Editor/Animation/Controls/UiTimelineCtrl.cpp +++ b/Gems/LyShine/Code/Editor/Animation/Controls/UiTimelineCtrl.cpp @@ -20,9 +20,9 @@ QColor InterpolateColor(const QColor& c1, const QColor& c2, float fraction) { - const int r = (c2.red() - c1.red()) * fraction + c1.red(); - const int g = (c2.green() - c1.green()) * fraction + c1.green(); - const int b = (c2.blue() - c1.blue()) * fraction + c1.blue(); + const int r = static_cast(static_cast(c2.red() - c1.red()) * fraction + c1.red()); + const int g = static_cast(static_cast(c2.green() - c1.green()) * fraction + c1.green()); + const int b = static_cast(static_cast(c2.blue() - c1.blue()) * fraction + c1.blue()); return QColor(r, g, b); } @@ -114,7 +114,7 @@ float TimelineWidget::SnapTime(float time) { double t = floor((double)time * m_ticksStep + 0.5); t = t / m_ticksStep; - return t; + return static_cast(t); } ////////////////////////////////////////////////////////////////////////// @@ -147,10 +147,10 @@ void TimelineWidget::DrawTicks(QPainter* painter) painter->setPen(redpen); int x = TimeToClient(m_fTimeMarker); painter->setBrush(Qt::NoBrush); - painter->drawRect(QRect(QPoint(x - 3, rc.top()), QPoint(x + 4, rc.bottom()))); + painter->drawRect(QRect(QPoint(x - 3, static_cast(rc.top())), QPoint(x + 4, static_cast(rc.bottom())))); painter->setPen(redpen); - painter->drawLine(x, rc.top(), x, rc.bottom()); + painter->drawLine(x, static_cast(rc.top()), x, static_cast(rc.bottom())); painter->setBrush(Qt::NoBrush); // Draw vertical line showing current time. @@ -184,7 +184,7 @@ void TimelineWidget::DrawTicks(QPainter* painter) float keyTime = (m_pKeyTimeSet ? m_pKeyTimeSet->GetKeyTime(keyTimeIndex) : 0.0f); int x2 = TimeToClient(keyTime); - painter->drawRect(QRect(QPoint(x2 - 2, rc.top()), QPoint(x2 + 3, rc.bottom()))); + painter->drawRect(QRect(QPoint(x2 - 2, static_cast(rc.top())), QPoint(x2 + 3, static_cast(rc.bottom())))); } painter->setPen(pOldPen); diff --git a/Gems/LyShine/Code/Editor/Animation/UiAVCustomizeTrackColorsDlg.cpp b/Gems/LyShine/Code/Editor/Animation/UiAVCustomizeTrackColorsDlg.cpp index 8bfb3f955d..533625c762 100644 --- a/Gems/LyShine/Code/Editor/Animation/UiAVCustomizeTrackColorsDlg.cpp +++ b/Gems/LyShine/Code/Editor/Animation/UiAVCustomizeTrackColorsDlg.cpp @@ -320,7 +320,7 @@ bool CUiAVCustomizeTrackColorsDlg::Import(const QString& fullPath) { return entry.paramType == paramType; }); - int entryIndex = pEntry - g_trackEntries; + int entryIndex = static_cast(pEntry - g_trackEntries); if (entryIndex >= arraysize(g_trackEntries)) // If not found, skip this. { continue; diff --git a/Gems/LyShine/Code/Editor/Animation/UiAnimViewDialog.cpp b/Gems/LyShine/Code/Editor/Animation/UiAnimViewDialog.cpp index 97f21e9bab..6a3afe2036 100644 --- a/Gems/LyShine/Code/Editor/Animation/UiAnimViewDialog.cpp +++ b/Gems/LyShine/Code/Editor/Animation/UiAnimViewDialog.cpp @@ -1470,7 +1470,7 @@ void CUiAnimViewDialog::OnSnapFPS() if (ok) { m_wndDopeSheet->SetSnapFPS(fps); - m_wndCurveEditor->SetFPS(fps); + m_wndCurveEditor->SetFPS(static_cast(fps)); SetCursorPosText(m_animationContext->GetTime()); } @@ -1541,7 +1541,7 @@ void CUiAnimViewDialog::ReadMiscSettings() if (settings.contains(s_kFrameSnappingFPSEntry)) { - float fps = settings.value(s_kFrameSnappingFPSEntry).toDouble(); + float fps = settings.value(s_kFrameSnappingFPSEntry).toFloat(); m_wndDopeSheet->SetSnapFPS(FloatToIntRet(fps)); m_wndCurveEditor->SetFPS(fps); } diff --git a/Gems/LyShine/Code/Editor/Animation/UiAnimViewDopeSheetBase.cpp b/Gems/LyShine/Code/Editor/Animation/UiAnimViewDopeSheetBase.cpp index 82d05a6f67..4e67fb520e 100644 --- a/Gems/LyShine/Code/Editor/Animation/UiAnimViewDopeSheetBase.cpp +++ b/Gems/LyShine/Code/Editor/Animation/UiAnimViewDopeSheetBase.cpp @@ -139,8 +139,7 @@ CUiAnimViewDopeSheetBase::~CUiAnimViewDopeSheetBase() ////////////////////////////////////////////////////////////////////////// int CUiAnimViewDopeSheetBase::TimeToClient(float time) const { - int x = m_leftOffset - m_scrollOffset.x() + (time * m_timeScale); - return x; + return static_cast(m_leftOffset - m_scrollOffset.x() + (time * m_timeScale)); } ////////////////////////////////////////////////////////////////////////// @@ -186,7 +185,7 @@ void CUiAnimViewDopeSheetBase::SetTimeRange(float start, float end) m_timeRange.Set(start, end); - SetHorizontalExtent(-m_leftOffset, m_timeRange.end * m_timeScale - m_leftOffset); + SetHorizontalExtent(-m_leftOffset, static_cast(m_timeRange.end * m_timeScale - m_leftOffset)); } ////////////////////////////////////////////////////////////////////////// @@ -255,7 +254,7 @@ void CUiAnimViewDopeSheetBase::SetTimeScale(float timeScale, float fAnchorTime) update(); - SetHorizontalExtent(-m_leftOffset, m_timeRange.end * m_timeScale); + SetHorizontalExtent(-m_leftOffset, static_cast(m_timeRange.end * m_timeScale)); ComputeFrameSteps(GetVisibleRange()); } @@ -346,15 +345,15 @@ float CUiAnimViewDopeSheetBase::TickSnap(float time) const double tickTime = GetTickTime(); double t = floor(((double)time / tickTime) + 0.5); t *= tickTime; - return t; + return static_cast(t); } ////////////////////////////////////////////////////////////////////////// float CUiAnimViewDopeSheetBase::TimeFromPoint(const QPoint& point) const { int x = point.x() - m_leftOffset + m_scrollOffset.x(); - double t = (double)x / m_timeScale; - return (float)TickSnap(t); + float t = static_cast(x) / m_timeScale; + return TickSnap(t); } ////////////////////////////////////////////////////////////////////////// @@ -362,7 +361,7 @@ float CUiAnimViewDopeSheetBase::TimeFromPointUnsnapped(const QPoint& point) cons { int x = point.x() - m_leftOffset + m_scrollOffset.x(); double t = (double)x / m_timeScale; - return t; + return static_cast(t); } void CUiAnimViewDopeSheetBase::mousePressEvent(QMouseEvent* event) @@ -1651,7 +1650,7 @@ float CUiAnimViewDopeSheetBase::FrameSnap(float time) const { double t = floor((double)time / m_snapFrameTime + 0.5); t = t * m_snapFrameTime; - return t; + return static_cast(t); } ////////////////////////////////////////////////////////////////////////// @@ -1755,9 +1754,10 @@ bool CUiAnimViewDopeSheetBase::CreateColorKey(CUiAnimViewTrack* pTrack, float ke Vec3 vColor(0, 0, 0); pTrack->GetValue(keyTime, vColor); - const AZ::Color defaultColor = AZ::Color::CreateFromRgba(clamp_tpl(FloatToIntRet(vColor.x), 0, 255), - clamp_tpl(FloatToIntRet(vColor.y), 0, 255), - clamp_tpl(FloatToIntRet(vColor.z), 0, 255), 255); + const AZ::Color defaultColor = AZ::Color::CreateFromRgba( + clamp_tpl(static_cast(FloatToIntRet(vColor.x)), AZ::u8(0), AZ::u8(255)), + clamp_tpl(static_cast(FloatToIntRet(vColor.y)), AZ::u8(0), AZ::u8(255)), + clamp_tpl(static_cast(FloatToIntRet(vColor.z)), AZ::u8(0), AZ::u8(255)), 255); AzQtComponents::ColorPicker dlg(AzQtComponents::ColorPicker::Configuration::RGB, tr("Select Color"), this); dlg.setCurrentColor(defaultColor); dlg.setSelectedColor(defaultColor); @@ -1997,12 +1997,12 @@ void CUiAnimViewDopeSheetBase::DrawTicks(QPainter* painter, const QRect& rc, Ran nNumberTicks = 8; } - double start = TickSnap(timeRange.start); - double step = 1.0 / m_ticksStep; + float start = TickSnap(timeRange.start); + float step = 1.0f / static_cast(m_ticksStep); - for (double t = 0.0f; t <= timeRange.end + step; t += step) + for (float t = 0.0f; t <= timeRange.end + step; t += step) { - double st = TickSnap(t); + float st = TickSnap(t); if (st > timeRange.end) { st = timeRange.end; @@ -2021,7 +2021,7 @@ void CUiAnimViewDopeSheetBase::DrawTicks(QPainter* painter, const QRect& rc, Ran continue; } - int k = RoundFloatToInt(st * m_ticksStep); + int k = RoundFloatToInt(st * static_cast(m_ticksStep)); if (k % nNumberTicks == 0) { if (st >= start) @@ -2743,7 +2743,7 @@ void CUiAnimViewDopeSheetBase::ComputeFrameSteps(const Range& visRange) float nBIntermediateTicks = 5; m_fFrameLabelStep = fFact * afStepTable[nStepIdx]; - if (TimeToClient(m_fFrameLabelStep) - TimeToClient(0) > 1300) + if (TimeToClient(static_cast(m_fFrameLabelStep)) - TimeToClient(0) > 1300) { nBIntermediateTicks = 10; } @@ -2755,7 +2755,7 @@ void CUiAnimViewDopeSheetBase::ComputeFrameSteps(const Range& visRange) void CUiAnimViewDopeSheetBase::DrawTimeLineInFrames(QPainter* painter, const QRect& rc, [[maybe_unused]] const QColor& lineCol, const QColor& textCol, [[maybe_unused]] double step) { float fFramesPerSec = 1.0f / m_snapFrameTime; - float fInvFrameLabelStep = 1.0f / m_fFrameLabelStep; + float fInvFrameLabelStep = 1.0f / static_cast(m_fFrameLabelStep); Range VisRange = GetVisibleRange(); const Range& timeRange = m_timeRange; @@ -2763,9 +2763,9 @@ void CUiAnimViewDopeSheetBase::DrawTimeLineInFrames(QPainter* painter, const QRe const QPen ltgray(QColor(90, 90, 90)); const QPen black(textCol); - for (double t = TickSnap(timeRange.start); t <= timeRange.end + m_fFrameTickStep; t += m_fFrameTickStep) + for (float t = TickSnap(timeRange.start); t <= timeRange.end + static_cast(m_fFrameTickStep); t += static_cast(m_fFrameTickStep)) { - double st = t; + float st = t; if (st > timeRange.end) { st = timeRange.end; @@ -2810,9 +2810,9 @@ void CUiAnimViewDopeSheetBase::DrawTimeLineInSeconds(QPainter* painter, const QR const QPen ltgray(QColor(90, 90, 90)); const QPen black(textCol); - for (double t = TickSnap(timeRange.start); t <= timeRange.end + step; t += step) + for (float t = TickSnap(timeRange.start); t <= timeRange.end + static_cast(step); t += static_cast(step)) { - double st = TickSnap(t); + float st = TickSnap(t); if (st > timeRange.end) { st = timeRange.end; @@ -2831,7 +2831,7 @@ void CUiAnimViewDopeSheetBase::DrawTimeLineInSeconds(QPainter* painter, const QR } int x = TimeToClient(st); - int k = RoundFloatToInt(st * m_ticksStep); + int k = RoundFloatToInt(st * static_cast(m_ticksStep)); if (k % nNumberTicks == 0) { painter->setPen(black); diff --git a/Gems/LyShine/Code/Editor/Animation/UiAnimViewNodes.cpp b/Gems/LyShine/Code/Editor/Animation/UiAnimViewNodes.cpp index 820849bc93..3df400ddf2 100644 --- a/Gems/LyShine/Code/Editor/Animation/UiAnimViewNodes.cpp +++ b/Gems/LyShine/Code/Editor/Animation/UiAnimViewNodes.cpp @@ -95,88 +95,88 @@ public: } protected: - void dragMoveEvent(QDragMoveEvent* event) + void dragMoveEvent([[maybe_unused]] QDragMoveEvent* event) { // For now we do not support any drag and drop in the Nodes pane return; - CUiAnimViewNodesCtrl::CRecord* pRecord = (CUiAnimViewNodesCtrl::CRecord*) itemAt(event->pos()); - if (!pRecord) - { - return; - } - CUiAnimViewNode* pTargetNode = pRecord->GetNode(); - - QTreeWidget::dragMoveEvent(event); - if (!event->isAccepted()) - { - return; - } - - if (pTargetNode && pTargetNode->IsGroupNode() /*&& !m_draggedNodes.DoesContain(pTargetNode)*/) - { - CUiAnimViewAnimNode* pDragTarget = static_cast(pTargetNode); - bool bAllValidReparenting = true; - QList nodes = draggedNodes(event); - Q_FOREACH(CUiAnimViewAnimNode * pDraggedNode, nodes) - { - if (!pDraggedNode->IsValidReparentingTo(pDragTarget)) - { - bAllValidReparenting = false; - break; - } - } - - if (!bAllValidReparenting) - { - event->ignore(); - } - - return; - } + //CUiAnimViewNodesCtrl::CRecord* pRecord = (CUiAnimViewNodesCtrl::CRecord*) itemAt(event->pos()); + //if (!pRecord) + //{ + // return; + //} + //CUiAnimViewNode* pTargetNode = pRecord->GetNode(); + // + //QTreeWidget::dragMoveEvent(event); + //if (!event->isAccepted()) + //{ + // return; + //} + // + //if (pTargetNode && pTargetNode->IsGroupNode() /*&& !m_draggedNodes.DoesContain(pTargetNode)*/) + //{ + // CUiAnimViewAnimNode* pDragTarget = static_cast(pTargetNode); + // bool bAllValidReparenting = true; + // QList nodes = draggedNodes(event); + // Q_FOREACH(CUiAnimViewAnimNode * pDraggedNode, nodes) + // { + // if (!pDraggedNode->IsValidReparentingTo(pDragTarget)) + // { + // bAllValidReparenting = false; + // break; + // } + // } + // + // if (!bAllValidReparenting) + // { + // event->ignore(); + // } + // + // return; + //} } - void dropEvent(QDropEvent* event) + void dropEvent([[maybe_unused]] QDropEvent* event) { // For now we do not support any drag and drop in the Nodes pane return; - CUiAnimViewNodesCtrl::CRecord* pRecord = (CUiAnimViewNodesCtrl::CRecord*) itemAt(event->pos()); - if (!pRecord) - { - return; - } - CUiAnimViewNode* pTargetNode = pRecord->GetNode(); - - QTreeWidget::dropEvent(event); - if (!event->isAccepted()) - { - return; - } - - if (pTargetNode && pTargetNode->IsGroupNode() /*&& !m_draggedNodes.DoesContain(pTargetNode)*/) - { - CUiAnimViewAnimNode* pDragTarget = static_cast(pTargetNode); - bool bAllValidReparenting = true; - QList nodes = draggedNodes(event); - Q_FOREACH(CUiAnimViewAnimNode * pDraggedNode, nodes) - { - if (!pDraggedNode->IsValidReparentingTo(pDragTarget)) - { - bAllValidReparenting = false; - break; - } - } - - if (bAllValidReparenting) - { - UiAnimUndo undo("Drag and Drop UiAnimView Nodes"); - Q_FOREACH(CUiAnimViewAnimNode * pDraggedNode, nodes) - { - pDraggedNode->SetNewParent(pDragTarget); - } - } - } + //CUiAnimViewNodesCtrl::CRecord* pRecord = (CUiAnimViewNodesCtrl::CRecord*) itemAt(event->pos()); + //if (!pRecord) + //{ + // return; + //} + //CUiAnimViewNode* pTargetNode = pRecord->GetNode(); + // + //QTreeWidget::dropEvent(event); + //if (!event->isAccepted()) + //{ + // return; + //} + // + //if (pTargetNode && pTargetNode->IsGroupNode() /*&& !m_draggedNodes.DoesContain(pTargetNode)*/) + //{ + // CUiAnimViewAnimNode* pDragTarget = static_cast(pTargetNode); + // bool bAllValidReparenting = true; + // QList nodes = draggedNodes(event); + // Q_FOREACH(CUiAnimViewAnimNode * pDraggedNode, nodes) + // { + // if (!pDraggedNode->IsValidReparentingTo(pDragTarget)) + // { + // bAllValidReparenting = false; + // break; + // } + // } + // + // if (bAllValidReparenting) + // { + // UiAnimUndo undo("Drag and Drop UiAnimView Nodes"); + // Q_FOREACH(CUiAnimViewAnimNode * pDraggedNode, nodes) + // { + // pDraggedNode->SetNewParent(pDragTarget); + // } + // } + //} } void keyPressEvent(QKeyEvent* event) diff --git a/Gems/LyShine/Code/Editor/QtHelpers.cpp b/Gems/LyShine/Code/Editor/QtHelpers.cpp index 8b6063a055..d9147463ed 100644 --- a/Gems/LyShine/Code/Editor/QtHelpers.cpp +++ b/Gems/LyShine/Code/Editor/QtHelpers.cpp @@ -32,8 +32,7 @@ namespace QtHelpers float GetHighDpiScaleFactor(const QWidget& widget) { - float dpiScale = QHighDpiScaling::factor(widget.windowHandle()->screen()); - return dpiScale; + return static_cast(QHighDpiScaling::factor(widget.windowHandle()->screen())); } QSize GetDpiScaledViewportSize(const QWidget& widget) @@ -41,7 +40,7 @@ namespace QtHelpers float dpiScale = GetHighDpiScaleFactor(widget); float width = ceilf(widget.size().width() * dpiScale); float height = ceilf(widget.size().height() * dpiScale); - return QSize(width, height); + return QSize(static_cast(width), static_cast(height)); } } // namespace QtHelpers diff --git a/Gems/LyShine/Code/Editor/ViewportIcon.cpp b/Gems/LyShine/Code/Editor/ViewportIcon.cpp index e4ada665d5..e3ad68922e 100644 --- a/Gems/LyShine/Code/Editor/ViewportIcon.cpp +++ b/Gems/LyShine/Code/Editor/ViewportIcon.cpp @@ -27,7 +27,7 @@ AZ::Vector2 ViewportIcon::GetTextureSize() const if (m_image) { AZ::RHI::Size size = m_image->GetDescriptor().m_size; - AZ::Vector2 scaledSize(size.m_width, size.m_height); + AZ::Vector2 scaledSize(static_cast(size.m_width), static_cast(size.m_height)); if (m_applyDpiScaleFactorToSize) { scaledSize *= m_dpiScaleFactor; diff --git a/Gems/LyShine/Code/Editor/ViewportWidget.cpp b/Gems/LyShine/Code/Editor/ViewportWidget.cpp index 1ce8f5b64d..e172d43b60 100644 --- a/Gems/LyShine/Code/Editor/ViewportWidget.cpp +++ b/Gems/LyShine/Code/Editor/ViewportWidget.cpp @@ -1001,7 +1001,7 @@ void ViewportWidget::RenderEditMode() // Render this canvas QSize scaledViewportSize = QtHelpers::GetDpiScaledViewportSize(*this); - AZ::Vector2 viewportSize(scaledViewportSize.width(), scaledViewportSize.height()); + AZ::Vector2 viewportSize(static_cast(scaledViewportSize.width()), static_cast(scaledViewportSize.height())); EBUS_EVENT_ID(canvasEntityId, UiEditorCanvasBus, RenderCanvasInEditorViewport, false, viewportSize); m_draw2d->SetSortKey(topLayerKey); @@ -1111,7 +1111,7 @@ void ViewportWidget::UpdatePreviewMode(float deltaTime) if (canvasEntityId.IsValid()) { QSize scaledViewportSize = QtHelpers::GetDpiScaledViewportSize(*this); - AZ::Vector2 viewportSize(scaledViewportSize.width(), scaledViewportSize.height()); + AZ::Vector2 viewportSize(static_cast(scaledViewportSize.width()), static_cast(scaledViewportSize.height())); // Get the canvas size AZ::Vector2 canvasSize = m_editorWindow->GetPreviewCanvasSize(); @@ -1153,7 +1153,7 @@ void ViewportWidget::RenderPreviewMode() if (canvasEntityId.IsValid()) { QSize scaledViewportSize = QtHelpers::GetDpiScaledViewportSize(*this); - AZ::Vector2 viewportSize(scaledViewportSize.width(), scaledViewportSize.height()); + AZ::Vector2 viewportSize(static_cast(scaledViewportSize.width()), static_cast(scaledViewportSize.height())); // Get the canvas size AZ::Vector2 canvasSize = m_editorWindow->GetPreviewCanvasSize(); @@ -1239,7 +1239,7 @@ void ViewportWidget::RenderViewportBackground() Draw2dHelper draw2d(m_draw2d.get()); draw2d.SetImageColor(backgroundColor.GetAsVector3()); - draw2d.DrawImage(image, AZ::Vector2(0.0f, 0.0f), AZ::Vector2(viewportSize.width(), viewportSize.height())); + draw2d.DrawImage(image, AZ::Vector2(0.0f, 0.0f), AZ::Vector2(static_cast(viewportSize.width()), static_cast(viewportSize.height()))); } void ViewportWidget::SetupShortcuts() diff --git a/Gems/LyShine/Code/Source/UiCanvasManager.cpp b/Gems/LyShine/Code/Source/UiCanvasManager.cpp index 5f2adcd20c..d13a8f5034 100644 --- a/Gems/LyShine/Code/Source/UiCanvasManager.cpp +++ b/Gems/LyShine/Code/Source/UiCanvasManager.cpp @@ -808,7 +808,7 @@ UiCanvasComponent* UiCanvasManager::FindEditorCanvasComponentByPathname(const AZ } //////////////////////////////////////////////////////////////////////////////////////////////////// -bool UiCanvasManager::HandleInputEventForInWorldCanvases(const AzFramework::InputChannel::Snapshot& inputSnapshot, const AZ::Vector2& viewportPos) +bool UiCanvasManager::HandleInputEventForInWorldCanvases([[maybe_unused]] const AzFramework::InputChannel::Snapshot& inputSnapshot, [[maybe_unused]] const AZ::Vector2& viewportPos) { // First we need to construct a ray from the either the center of the screen or the mouse position. // This requires knowledge of the camera @@ -816,86 +816,86 @@ bool UiCanvasManager::HandleInputEventForInWorldCanvases(const AzFramework::Inpu // ToDo: Re-implement by getting the camera from Atom. LYN-3680 return false; - const CCamera cam; - - // construct a ray from the camera position in the view direction of the camera - const float rayLength = 5000.0f; - Vec3 rayOrigin(cam.GetPosition()); - Vec3 rayDirection = cam.GetViewdir() * rayLength; - - // If the mouse cursor is visible we will assume that the ray should be in the direction of the - // mouse pointer. This is a temporary solution. A better solution is to be able to configure the - // LyShine system to say how ray input should be handled. - bool isCursorVisible = false; - UiCursorBus::BroadcastResult(isCursorVisible, &UiCursorInterface::IsUiCursorVisible); - if (isCursorVisible) - { - // for some reason Unproject seems to work when given the viewport pos with (0,0) at the - // bottom left as opposed to the top left - even though that function specifically sets top left - // to (0,0). - const float viewportYInverted = cam.GetViewSurfaceZ() - viewportPos.GetY(); - - // Unproject to get the screen position in world space, use arbitrary Z that is within the depth range - Vec3 flippedViewportRayOrigin(viewportPos.GetX(), viewportYInverted, 0.f); - Vec3 flippedViewportRayForward(viewportPos.GetX(), viewportYInverted, 1.f); - - cam.Unproject(flippedViewportRayOrigin, rayOrigin); - - Vec3 unprojectedPosForward; - cam.Unproject(flippedViewportRayForward, unprojectedPosForward); - - // We want a vector relative to the camera origin - Vec3 rayVec = unprojectedPosForward - rayOrigin; - - // we want to ensure that the ray is a certain length so normalize it and scale it - rayVec.NormalizeSafe(); - rayDirection = rayVec * rayLength; - } - - - AzFramework::EntityContextId gameContextId; - AzFramework::GameEntityContextRequestBus::BroadcastResult(gameContextId, - &AzFramework::GameEntityContextRequests::GetGameEntityContextId); - - AzFramework::RenderGeometry::RayRequest request; - request.m_startWorldPosition = LYVec3ToAZVec3(rayOrigin); - request.m_endWorldPosition = LYVec3ToAZVec3(rayOrigin + rayDirection); - - AzFramework::RenderGeometry::RayResult rayResult; - AzFramework::RenderGeometry::IntersectorBus::EventResult(rayResult, gameContextId, - &AzFramework::RenderGeometry::IntersectorInterface::RayIntersect, request); - - if (rayResult) - { - AZ::EntityId hitEntity = rayResult.m_entityAndComponent.GetEntityId(); - if (hitEntity.IsValid()) - { - AZ::EntityId canvasEntityId; - UiCanvasRefBus::EventResult(canvasEntityId, hitEntity, &UiCanvasRefInterface::GetCanvas); - if (canvasEntityId.IsValid()) - { - // Checkif the UI canvas referenced by the hit entity supports automatic input - bool doesCanvasSupportInput = false; - UiCanvasBus::EventResult(doesCanvasSupportInput, canvasEntityId, &UiCanvasInterface::GetIsPositionalInputSupported); - - if (doesCanvasSupportInput) - { - // set the hit details to the hit entity, it will convert into canvas coords and send to canvas - bool handled = false; - UiCanvasOnMeshBus::EventResult(handled, hitEntity, - &UiCanvasOnMeshInterface::ProcessHitInputEvent, inputSnapshot, rayResult); - - if (handled) - { - return true; - } - } - } - } - } - - - return false; + //const CCamera cam; + // + //// construct a ray from the camera position in the view direction of the camera + //const float rayLength = 5000.0f; + //Vec3 rayOrigin(cam.GetPosition()); + //Vec3 rayDirection = cam.GetViewdir() * rayLength; + // + //// If the mouse cursor is visible we will assume that the ray should be in the direction of the + //// mouse pointer. This is a temporary solution. A better solution is to be able to configure the + //// LyShine system to say how ray input should be handled. + //bool isCursorVisible = false; + //UiCursorBus::BroadcastResult(isCursorVisible, &UiCursorInterface::IsUiCursorVisible); + //if (isCursorVisible) + //{ + // // for some reason Unproject seems to work when given the viewport pos with (0,0) at the + // // bottom left as opposed to the top left - even though that function specifically sets top left + // // to (0,0). + // const float viewportYInverted = cam.GetViewSurfaceZ() - viewportPos.GetY(); + // + // // Unproject to get the screen position in world space, use arbitrary Z that is within the depth range + // Vec3 flippedViewportRayOrigin(viewportPos.GetX(), viewportYInverted, 0.f); + // Vec3 flippedViewportRayForward(viewportPos.GetX(), viewportYInverted, 1.f); + // + // cam.Unproject(flippedViewportRayOrigin, rayOrigin); + // + // Vec3 unprojectedPosForward; + // cam.Unproject(flippedViewportRayForward, unprojectedPosForward); + // + // // We want a vector relative to the camera origin + // Vec3 rayVec = unprojectedPosForward - rayOrigin; + // + // // we want to ensure that the ray is a certain length so normalize it and scale it + // rayVec.NormalizeSafe(); + // rayDirection = rayVec * rayLength; + //} + // + // + //AzFramework::EntityContextId gameContextId; + //AzFramework::GameEntityContextRequestBus::BroadcastResult(gameContextId, + // &AzFramework::GameEntityContextRequests::GetGameEntityContextId); + // + //AzFramework::RenderGeometry::RayRequest request; + //request.m_startWorldPosition = LYVec3ToAZVec3(rayOrigin); + //request.m_endWorldPosition = LYVec3ToAZVec3(rayOrigin + rayDirection); + // + //AzFramework::RenderGeometry::RayResult rayResult; + //AzFramework::RenderGeometry::IntersectorBus::EventResult(rayResult, gameContextId, + // &AzFramework::RenderGeometry::IntersectorInterface::RayIntersect, request); + // + //if (rayResult) + //{ + // AZ::EntityId hitEntity = rayResult.m_entityAndComponent.GetEntityId(); + // if (hitEntity.IsValid()) + // { + // AZ::EntityId canvasEntityId; + // UiCanvasRefBus::EventResult(canvasEntityId, hitEntity, &UiCanvasRefInterface::GetCanvas); + // if (canvasEntityId.IsValid()) + // { + // // Checkif the UI canvas referenced by the hit entity supports automatic input + // bool doesCanvasSupportInput = false; + // UiCanvasBus::EventResult(doesCanvasSupportInput, canvasEntityId, &UiCanvasInterface::GetIsPositionalInputSupported); + // + // if (doesCanvasSupportInput) + // { + // // set the hit details to the hit entity, it will convert into canvas coords and send to canvas + // bool handled = false; + // UiCanvasOnMeshBus::EventResult(handled, hitEntity, + // &UiCanvasOnMeshInterface::ProcessHitInputEvent, inputSnapshot, rayResult); + // + // if (handled) + // { + // return true; + // } + // } + // } + // } + //} + // + // + //return false; } //////////////////////////////////////////////////////////////////////////////////////////////////// From 76c452d43d36c756008ddcdd9de81751586907f7 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Mon, 16 Aug 2021 15:57:34 -0700 Subject: [PATCH 477/803] Gems/Metastream Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Gems/Metastream/Code/Source/MetastreamGem.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Gems/Metastream/Code/Source/MetastreamGem.cpp b/Gems/Metastream/Code/Source/MetastreamGem.cpp index 2bb213662c..e8c659474d 100644 --- a/Gems/Metastream/Code/Source/MetastreamGem.cpp +++ b/Gems/Metastream/Code/Source/MetastreamGem.cpp @@ -339,10 +339,9 @@ namespace Metastream // Server already started return true; } -#endif // AZ_TRAIT_METASTREAM_USE_CIVET - - // Metastream only supported on PC +#else return false; +#endif } void Metastream::MetastreamGem::StopHTTPServer() From 2d09e9c60e17fa5c671182d3dd9487a945f7cff2 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Mon, 16 Aug 2021 15:57:51 -0700 Subject: [PATCH 478/803] Gems/Multiplayer Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../Code/Source/AutoGen/AutoComponent_Source.jinja | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja index 56ab828ffe..b1946eb61f 100644 --- a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja +++ b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja @@ -1568,8 +1568,7 @@ namespace {{ Component.attrib['Namespace'] }} return s_netComponentId; } -#pragma warning(push) -#pragma warning(disable: 4065) // switch statement contains 'default' but no 'case' labels + AZ_PUSH_DISABLE_WARNING(4065, "-Wunknown-warning-option") // switch statement contains 'default' but no 'case' labels bool {{ ComponentBaseName }}::HandleRpcMessage ( [[maybe_unused]] AzNetworking::IConnection* invokingConnection, @@ -1590,7 +1589,7 @@ namespace {{ Component.attrib['Namespace'] }} AZ_Assert(0, "Got unhandled RpcType %d in {{ ComponentBaseName }}", static_cast(rpcType)); return false; } -#pragma warning(pop) + AZ_POP_DISABLE_WARNING bool {{ ComponentBaseName }}::SerializeStateDeltaMessage(Multiplayer::ReplicationRecord& replicationRecord, AzNetworking::ISerializer& serializer) { From 0b70cf2308ec7d95f90828d502b2e8d17add2342 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Mon, 16 Aug 2021 15:58:05 -0700 Subject: [PATCH 479/803] Gems/PhysX Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Gems/PhysX/Code/Source/Scene/PhysXScene.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Gems/PhysX/Code/Source/Scene/PhysXScene.cpp b/Gems/PhysX/Code/Source/Scene/PhysXScene.cpp index a47f0ba16f..ce604bd9f1 100644 --- a/Gems/PhysX/Code/Source/Scene/PhysXScene.cpp +++ b/Gems/PhysX/Code/Source/Scene/PhysXScene.cpp @@ -139,8 +139,9 @@ namespace PhysX else if (auto* shapeColliderPairList = AZStd::get_if>(&shapeData)) { bool shapeAdded = false; - for (const auto& shapeColliderConfigs : *shapeColliderPairList) + if (!shapeColliderPairList->empty()) { + const auto& shapeColliderConfigs = shapeColliderPairList->front(); auto shapePtr = AZStd::make_shared(*(shapeColliderConfigs.first), *(shapeColliderConfigs.second)); AZStd::visit([shapePtr, &shapeAdded](auto&& body) { From b9e73a823a245bf38bd4ad9dd4c8a8005301d1f0 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Mon, 16 Aug 2021 15:58:20 -0700 Subject: [PATCH 480/803] Gems/SceneProcessing Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../Code/Tests/SceneBuilder/SceneBuilderTests.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Gems/SceneProcessing/Code/Tests/SceneBuilder/SceneBuilderTests.cpp b/Gems/SceneProcessing/Code/Tests/SceneBuilder/SceneBuilderTests.cpp index 46e14e6985..a4da836aeb 100644 --- a/Gems/SceneProcessing/Code/Tests/SceneBuilder/SceneBuilderTests.cpp +++ b/Gems/SceneProcessing/Code/Tests/SceneBuilder/SceneBuilderTests.cpp @@ -164,8 +164,8 @@ TEST_F(SceneBuilderTests, SceneBuilderWorker_ExportProductDependencies_PathDepen TEST_F(SceneBuilderTests, SceneBuilderWorker_ExportProductDependencies_ProductDependency) { AZ::Uuid dependencyId = AZ::Uuid::CreateRandom(); - SceneAPI::Events::ExportProduct exportProduct("testExportFile", AZ::Uuid::CreateRandom(), AZ::Data::AssetType::CreateNull(), u8(0), AZStd::nullopt); - exportProduct.m_productDependencies.push_back(SceneAPI::Events::ExportProduct("testDependencyFile", dependencyId, AZ::Data::AssetType::CreateNull(), 0, AZStd::nullopt)); + SceneAPI::Events::ExportProduct exportProduct("testExportFile", AZ::Uuid::CreateRandom(), AZ::Data::AssetType::CreateNull(), AZ::u8(0), AZStd::nullopt); + exportProduct.m_productDependencies.push_back(SceneAPI::Events::ExportProduct("testDependencyFile", dependencyId, AZ::Data::AssetType::CreateNull(), AZ::u8(0), AZStd::nullopt)); TestSuccessCase(exportProduct, nullptr, &dependencyId); } @@ -173,8 +173,8 @@ TEST_F(SceneBuilderTests, SceneBuilderWorker_ExportProductDependencies_ProductDe TEST_F(SceneBuilderTests, SceneBuilderWorker_ExportProductDependencies_ProductAndPathDependencies) { AZ::Uuid dependencyId = AZ::Uuid::CreateRandom(); - SceneAPI::Events::ExportProduct exportProduct("testExportFile", AZ::Uuid::CreateRandom(), AZ::Data::AssetType::CreateNull(), u8(0), AZStd::nullopt); - exportProduct.m_productDependencies.push_back(SceneAPI::Events::ExportProduct("testDependencyFile", dependencyId, AZ::Data::AssetType::CreateNull(), 0, AZStd::nullopt)); + SceneAPI::Events::ExportProduct exportProduct("testExportFile", AZ::Uuid::CreateRandom(), AZ::Data::AssetType::CreateNull(), AZ::u8(0), AZStd::nullopt); + exportProduct.m_productDependencies.push_back(SceneAPI::Events::ExportProduct("testDependencyFile", dependencyId, AZ::Data::AssetType::CreateNull(), AZ::u8(0), AZStd::nullopt)); const char* relativeDependencyPathToFile = "some/test/file.mtl"; From f22d2d736b6a30e29f85bcc483310a7513eb27d3 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Mon, 16 Aug 2021 15:59:25 -0700 Subject: [PATCH 481/803] Gems/ScriptCanvas Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../Code/Include/ScriptCanvas/Utils/NodeUtils.cpp | 2 -- .../EditorAutomationActions/EditorKeyActions.cpp | 2 +- .../EditorAutomationActions/EditorMouseActions.cpp | 4 ++-- .../ScriptCanvasActions/ElementInteractions.cpp | 8 ++++---- .../EditorAutomationActions/WidgetActions.cpp | 2 +- .../EditorAutomationStates/CreateElementsStates.cpp | 4 ++-- .../EditorAutomationStates/UtilityStates.cpp | 4 ++-- .../Editor/Source/EditorAutomationTests/GroupTests.cpp | 4 ++-- 8 files changed, 14 insertions(+), 16 deletions(-) diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Utils/NodeUtils.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Utils/NodeUtils.cpp index d54e9457c1..5aa922d627 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Utils/NodeUtils.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Utils/NodeUtils.cpp @@ -77,8 +77,6 @@ namespace ScriptCanvas { return ConstructCustomNodeIdentifier(scriptCanvasNode->RTTI_GetType()); } - - return NodeTypeIdentifier(0); } NodeTypeIdentifier NodeUtils::ConstructEBusIdentifier(ScriptCanvas::EBusBusId ebusIdentifier) diff --git a/Gems/ScriptCanvasDeveloper/Code/Editor/Source/EditorAutomation/EditorAutomationActions/EditorKeyActions.cpp b/Gems/ScriptCanvasDeveloper/Code/Editor/Source/EditorAutomation/EditorAutomationActions/EditorKeyActions.cpp index a20e674063..4114292938 100644 --- a/Gems/ScriptCanvasDeveloper/Code/Editor/Source/EditorAutomation/EditorAutomationActions/EditorKeyActions.cpp +++ b/Gems/ScriptCanvasDeveloper/Code/Editor/Source/EditorAutomation/EditorAutomationActions/EditorKeyActions.cpp @@ -30,7 +30,7 @@ namespace ScriptCanvasDeveloper #if defined(AZ_COMPILER_MSVC) INPUT osInput = { 0 }; osInput.type = INPUT_KEYBOARD; - osInput.ki.wVk = m_keyValue; + osInput.ki.wVk = static_cast(m_keyValue); switch (m_keyAction) { diff --git a/Gems/ScriptCanvasDeveloper/Code/Editor/Source/EditorAutomation/EditorAutomationActions/EditorMouseActions.cpp b/Gems/ScriptCanvasDeveloper/Code/Editor/Source/EditorAutomation/EditorAutomationActions/EditorMouseActions.cpp index a5ed19a8d7..cf757af1ec 100644 --- a/Gems/ScriptCanvasDeveloper/Code/Editor/Source/EditorAutomation/EditorAutomationActions/EditorMouseActions.cpp +++ b/Gems/ScriptCanvasDeveloper/Code/Editor/Source/EditorAutomation/EditorAutomationActions/EditorMouseActions.cpp @@ -174,8 +174,8 @@ namespace ScriptCanvasDeveloper osInput.type = INPUT_MOUSE; osInput.mi.mouseData = 0; osInput.mi.time = 0; - osInput.mi.dx = targetPoint.x() - currentPosition.x(); - osInput.mi.dy = targetPoint.y() - currentPosition.y(); + osInput.mi.dx = static_cast(targetPoint.x() - currentPosition.x()); + osInput.mi.dy = static_cast(targetPoint.y() - currentPosition.y()); osInput.mi.dwFlags = MOUSEEVENTF_MOVE; ::SendInput(1, &osInput, sizeof(osInput)); diff --git a/Gems/ScriptCanvasDeveloper/Code/Editor/Source/EditorAutomation/EditorAutomationActions/ScriptCanvasActions/ElementInteractions.cpp b/Gems/ScriptCanvasDeveloper/Code/Editor/Source/EditorAutomation/EditorAutomationActions/ScriptCanvasActions/ElementInteractions.cpp index 411d176356..9a8165b5e8 100644 --- a/Gems/ScriptCanvasDeveloper/Code/Editor/Source/EditorAutomation/EditorAutomationActions/ScriptCanvasActions/ElementInteractions.cpp +++ b/Gems/ScriptCanvasDeveloper/Code/Editor/Source/EditorAutomation/EditorAutomationActions/ScriptCanvasActions/ElementInteractions.cpp @@ -78,8 +78,8 @@ namespace ScriptCanvasDeveloper { CompoundAction* compoundAction = aznew CompoundAction(); - QPoint startPoint(m_scenePoint.x() - 5, m_scenePoint.y() - 5); - QPoint endPoint(m_scenePoint.x() + 5, m_scenePoint.y() + 5); + QPoint startPoint(static_cast(m_scenePoint.x() - 5.0), static_cast(m_scenePoint.y() - 5.0)); + QPoint endPoint(static_cast(m_scenePoint.x() + 5.0), static_cast(m_scenePoint.y() + 5.0)); QRect sceneRect = QRect(startPoint, endPoint); @@ -150,8 +150,8 @@ namespace ScriptCanvasDeveloper { CompoundAction* compoundAction = aznew CompoundAction(); - QPoint startPoint(m_scenePoint.x() - 5, m_scenePoint.y() - 5); - QPoint endPoint(m_scenePoint.x() + 5, m_scenePoint.y() + 5); + QPoint startPoint(static_cast(m_scenePoint.x() - 5.0), static_cast(m_scenePoint.y() - 5.0)); + QPoint endPoint(static_cast(m_scenePoint.x() + 5.0), static_cast(m_scenePoint.y() + 5.0)); QRect sceneRect = QRect(startPoint, endPoint); diff --git a/Gems/ScriptCanvasDeveloper/Code/Editor/Source/EditorAutomation/EditorAutomationActions/WidgetActions.cpp b/Gems/ScriptCanvasDeveloper/Code/Editor/Source/EditorAutomation/EditorAutomationActions/WidgetActions.cpp index 5601c89c97..46c98ca48c 100644 --- a/Gems/ScriptCanvasDeveloper/Code/Editor/Source/EditorAutomation/EditorAutomationActions/WidgetActions.cpp +++ b/Gems/ScriptCanvasDeveloper/Code/Editor/Source/EditorAutomation/EditorAutomationActions/WidgetActions.cpp @@ -40,7 +40,7 @@ namespace ScriptCanvasDeveloper { ClearActionQueue(); - QPoint targetPoint = m_targetEdit->mapToGlobal(QPoint(5, m_targetEdit->height() * 0.5f)); + QPoint targetPoint = m_targetEdit->mapToGlobal(QPoint(5, static_cast(m_targetEdit->height() * 0.5f))); // Cheaty clear for right now. m_targetEdit->clear(); diff --git a/Gems/ScriptCanvasDeveloper/Code/Editor/Source/EditorAutomation/EditorAutomationStates/CreateElementsStates.cpp b/Gems/ScriptCanvasDeveloper/Code/Editor/Source/EditorAutomation/EditorAutomationStates/CreateElementsStates.cpp index 679cf5690e..bfb36235ef 100644 --- a/Gems/ScriptCanvasDeveloper/Code/Editor/Source/EditorAutomation/EditorAutomationStates/CreateElementsStates.cpp +++ b/Gems/ScriptCanvasDeveloper/Code/Editor/Source/EditorAutomation/EditorAutomationStates/CreateElementsStates.cpp @@ -70,7 +70,7 @@ namespace ScriptCanvasDeveloper if (dropPoint) { - QPointF qPoint = QPoint(dropPoint->GetX(), dropPoint->GetY()); + QPointF qPoint = QPoint(static_cast(dropPoint->GetX()), static_cast(dropPoint->GetY())); m_createNodeAction = aznew CreateNodeFromPaletteAction(m_nodePaletteWidget, (*graphId), m_nodeName, qPoint); } break; @@ -218,7 +218,7 @@ namespace ScriptCanvasDeveloper if (dropPoint) { - QPointF qPoint = QPoint(dropPoint->GetX(), dropPoint->GetY()); + QPointF qPoint = QPoint(static_cast(dropPoint->GetX()), static_cast(dropPoint->GetY())); m_createNodeAction = aznew CreateNodeFromContextMenuAction((*graphId), m_nodeName, qPoint); } break; diff --git a/Gems/ScriptCanvasDeveloper/Code/Editor/Source/EditorAutomation/EditorAutomationStates/UtilityStates.cpp b/Gems/ScriptCanvasDeveloper/Code/Editor/Source/EditorAutomation/EditorAutomationStates/UtilityStates.cpp index c8e82bdf90..459dc82542 100644 --- a/Gems/ScriptCanvasDeveloper/Code/Editor/Source/EditorAutomation/EditorAutomationStates/UtilityStates.cpp +++ b/Gems/ScriptCanvasDeveloper/Code/Editor/Source/EditorAutomation/EditorAutomationStates/UtilityStates.cpp @@ -54,7 +54,7 @@ namespace ScriptCanvasDeveloper qreal verticalPoint = boundingRect.top() + boundingRect.height() * m_offsets.m_verticalPosition; verticalPoint += m_offsets.m_verticalOffset; - AZ::Vector2 scenePoint(horizontalPoint, verticalPoint); + AZ::Vector2 scenePoint(static_cast(horizontalPoint), static_cast(verticalPoint)); GetStateModel()->SetStateData(m_outputId, scenePoint); } } @@ -92,7 +92,7 @@ namespace ScriptCanvasDeveloper qreal verticalPoint = groupBoundingBox.top() + groupBoundingBox.height() * m_offsets.m_verticalPosition; verticalPoint += m_offsets.m_verticalPosition; - AZ::Vector2 scenePoint(horizontalPoint, verticalPoint); + AZ::Vector2 scenePoint(static_cast(horizontalPoint), static_cast(verticalPoint)); GetStateModel()->SetStateData(m_outputId, scenePoint); } else diff --git a/Gems/ScriptCanvasDeveloper/Code/Editor/Source/EditorAutomationTests/GroupTests.cpp b/Gems/ScriptCanvasDeveloper/Code/Editor/Source/EditorAutomationTests/GroupTests.cpp index cfe5996530..0428eb6640 100644 --- a/Gems/ScriptCanvasDeveloper/Code/Editor/Source/EditorAutomationTests/GroupTests.cpp +++ b/Gems/ScriptCanvasDeveloper/Code/Editor/Source/EditorAutomationTests/GroupTests.cpp @@ -70,8 +70,8 @@ namespace ScriptCanvasDeveloper AZ::Vector2 modifiedValue = (*position); QRectF sceneBoundingBox = nodeItem->sceneBoundingRect(); - modifiedValue.SetX(position->GetX() + sceneBoundingBox.width() * m_horizontalDimension); - modifiedValue.SetY(position->GetY() + sceneBoundingBox.height() * m_verticalDimension); + modifiedValue.SetX(position->GetX() + static_cast(sceneBoundingBox.width()) * m_horizontalDimension); + modifiedValue.SetY(position->GetY() + static_cast(sceneBoundingBox.height()) * m_verticalDimension); GetStateModel()->SetStateData(m_positionId, modifiedValue); } From f0fa62bde3f962adc2a6ff5f797fb16048e66c3b Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Mon, 16 Aug 2021 16:46:48 -0700 Subject: [PATCH 482/803] PR comments/observations Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../AzFramework/Physics/Common/PhysicsTypes.h | 2 +- .../Code/Editor/Animation/UiAnimViewNodes.cpp | 72 ------------------- 2 files changed, 1 insertion(+), 73 deletions(-) diff --git a/Code/Framework/AzFramework/AzFramework/Physics/Common/PhysicsTypes.h b/Code/Framework/AzFramework/AzFramework/Physics/Common/PhysicsTypes.h index 30f3fb6297..26dfcd3b77 100644 --- a/Code/Framework/AzFramework/AzFramework/Physics/Common/PhysicsTypes.h +++ b/Code/Framework/AzFramework/AzFramework/Physics/Common/PhysicsTypes.h @@ -56,7 +56,7 @@ namespace AzPhysics //! A handle to a Scene within the physics simulation. //! A SceneHandle is a tuple of a Crc of the scenes name and the index in the Scene list. using SceneHandle = AZStd::tuple; - static constexpr SceneHandle InvalidSceneHandle = { AZ::Crc32(), AZ::s8(-1) }; + static constexpr SceneHandle InvalidSceneHandle = { AZ::Crc32(), SceneIndex(-1) }; //! Ease of use type for referencing a List of SceneHandle objects. using SceneHandleList = AZStd::vector; diff --git a/Gems/LyShine/Code/Editor/Animation/UiAnimViewNodes.cpp b/Gems/LyShine/Code/Editor/Animation/UiAnimViewNodes.cpp index 3df400ddf2..74d2c7d4fb 100644 --- a/Gems/LyShine/Code/Editor/Animation/UiAnimViewNodes.cpp +++ b/Gems/LyShine/Code/Editor/Animation/UiAnimViewNodes.cpp @@ -99,84 +99,12 @@ protected: { // For now we do not support any drag and drop in the Nodes pane return; - - //CUiAnimViewNodesCtrl::CRecord* pRecord = (CUiAnimViewNodesCtrl::CRecord*) itemAt(event->pos()); - //if (!pRecord) - //{ - // return; - //} - //CUiAnimViewNode* pTargetNode = pRecord->GetNode(); - // - //QTreeWidget::dragMoveEvent(event); - //if (!event->isAccepted()) - //{ - // return; - //} - // - //if (pTargetNode && pTargetNode->IsGroupNode() /*&& !m_draggedNodes.DoesContain(pTargetNode)*/) - //{ - // CUiAnimViewAnimNode* pDragTarget = static_cast(pTargetNode); - // bool bAllValidReparenting = true; - // QList nodes = draggedNodes(event); - // Q_FOREACH(CUiAnimViewAnimNode * pDraggedNode, nodes) - // { - // if (!pDraggedNode->IsValidReparentingTo(pDragTarget)) - // { - // bAllValidReparenting = false; - // break; - // } - // } - // - // if (!bAllValidReparenting) - // { - // event->ignore(); - // } - // - // return; - //} } void dropEvent([[maybe_unused]] QDropEvent* event) { // For now we do not support any drag and drop in the Nodes pane return; - - //CUiAnimViewNodesCtrl::CRecord* pRecord = (CUiAnimViewNodesCtrl::CRecord*) itemAt(event->pos()); - //if (!pRecord) - //{ - // return; - //} - //CUiAnimViewNode* pTargetNode = pRecord->GetNode(); - // - //QTreeWidget::dropEvent(event); - //if (!event->isAccepted()) - //{ - // return; - //} - // - //if (pTargetNode && pTargetNode->IsGroupNode() /*&& !m_draggedNodes.DoesContain(pTargetNode)*/) - //{ - // CUiAnimViewAnimNode* pDragTarget = static_cast(pTargetNode); - // bool bAllValidReparenting = true; - // QList nodes = draggedNodes(event); - // Q_FOREACH(CUiAnimViewAnimNode * pDraggedNode, nodes) - // { - // if (!pDraggedNode->IsValidReparentingTo(pDragTarget)) - // { - // bAllValidReparenting = false; - // break; - // } - // } - // - // if (bAllValidReparenting) - // { - // UiAnimUndo undo("Drag and Drop UiAnimView Nodes"); - // Q_FOREACH(CUiAnimViewAnimNode * pDraggedNode, nodes) - // { - // pDraggedNode->SetNewParent(pDragTarget); - // } - // } - //} } void keyPressEvent(QKeyEvent* event) From b8787739e112448ef6f9b60139bcc41ea71274aa Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Mon, 16 Aug 2021 17:05:50 -0700 Subject: [PATCH 483/803] more fixes after rebase Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Editor/ViewportTitleDlg.cpp | 6 +++--- .../UI/PropertyEditor/EntityPropertyEditor.cpp | 4 ++-- .../UI/PropertyEditor/PropertyRowWidget.cpp | 2 +- .../Components/LocalPredictionPlayerInputComponent.cpp | 10 +++++----- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Code/Editor/ViewportTitleDlg.cpp b/Code/Editor/ViewportTitleDlg.cpp index 0c59c1e9b5..7ffe14c899 100644 --- a/Code/Editor/ViewportTitleDlg.cpp +++ b/Code/Editor/ViewportTitleDlg.cpp @@ -462,7 +462,7 @@ void CViewportTitleDlg::AddFOVMenus(QMenu* menu, std::function call { fov = std::max(1.0f, f); fov = std::min(120.0f, f); - QAction* action = menu->addAction(customPresets[i]); + QAction* action = menu->addAction(customPreset); connect(action, &QAction::triggered, action, [fov, callback](){ callback(fov); }); } } @@ -536,7 +536,7 @@ void CViewportTitleDlg::AddAspectRatioMenus(QMenu* menu, std::functionaddAction(customPresets[i]); + QAction* action = menu->addAction(customPreset); connect(action, &QAction::triggered, action, [width, height, callback]() {callback(width, height); }); } } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.cpp index 2c46bb2d26..41cbde191a 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.cpp @@ -254,8 +254,8 @@ namespace AzToolsFramework QRect globalRect = m_editor->GetWidgetAndVisibleChildrenGlobalRect(dragRowWidget); int top = mapFromGlobal(globalRect.topLeft()).y(); - int imageHeight = dragImage.height() / dragImage.devicePixelRatioF(); - int imageWidth = dragImage.width() / dragImage.devicePixelRatioF(); + int imageHeight = static_cast(dragImage.height() / dragImage.devicePixelRatioF()); + int imageWidth = static_cast(dragImage.width() / dragImage.devicePixelRatioF()); QRect currRect = QRect(QPoint(LeftMargin + 1, top), QPoint(LeftMargin + 1 + imageWidth, top + imageHeight)); painter.setOpacity(alpha); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.cpp index 604c6141d7..c298d0d97e 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.cpp @@ -1867,7 +1867,7 @@ namespace AzToolsFramework } const auto dpr = devicePixelRatioF(); - QPixmap dragImage(width * dpr, height * dpr); + QPixmap dragImage(static_cast(width * dpr), static_cast(height * dpr)); dragImage.setDevicePixelRatio(dpr); dragImage.fill(Qt::transparent); diff --git a/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp b/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp index de4ea67467..936f2ea92c 100644 --- a/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp @@ -277,7 +277,7 @@ namespace Multiplayer input.SetClientInputId(GetLastInputId()); ScopedAlterTime scopedTime(input.GetHostFrameId(), input.GetHostTimeMs(), input.GetHostBlendFactor(), invokingConnection->GetConnectionId()); - GetNetBindComponent()->ProcessInput(input, clientInputRateSec); + GetNetBindComponent()->ProcessInput(input, static_cast(clientInputRateSec)); AZLOG(NET_Prediction, "Migrated InputId=%d", aznumeric_cast(input.GetClientInputId())); @@ -345,7 +345,7 @@ namespace Multiplayer // Reprocess the input for this frame NetworkInput& input = m_inputHistory[replayIndex]; ScopedAlterTime scopedTime(input.GetHostFrameId(), input.GetHostTimeMs(), input.GetHostBlendFactor(), invokingConnection->GetConnectionId()); - GetNetBindComponent()->ReprocessInput(input, clientInputRateSec); + GetNetBindComponent()->ReprocessInput(input, static_cast(clientInputRateSec)); AZLOG(NET_Prediction, "Replayed InputId=%d", aznumeric_cast(input.GetClientInputId())); } @@ -438,10 +438,10 @@ namespace Multiplayer input.SetHostBlendFactor(multiplayer->GetCurrentBlendFactor()); // Allow components to form the input for this frame - GetNetBindComponent()->CreateInput(input, clientInputRateSec); + GetNetBindComponent()->CreateInput(input, static_cast(clientInputRateSec)); // Process the input for this frame - GetNetBindComponent()->ProcessInput(input, clientInputRateSec); + GetNetBindComponent()->ProcessInput(input, static_cast(clientInputRateSec)); AZLOG(NET_Prediction, "Processed InputId=%d", aznumeric_cast(m_clientInputId)); @@ -506,7 +506,7 @@ namespace Multiplayer NetworkInput& input = m_lastInputReceived[0]; { ScopedAlterTime scopedTime(input.GetHostFrameId(), input.GetHostTimeMs(), DefaultBlendFactor, GetNetBindComponent()->GetOwningConnectionId()); - GetNetBindComponent()->ProcessInput(input, clientInputRateSec); + GetNetBindComponent()->ProcessInput(input, static_cast(clientInputRateSec)); } AZLOG(NET_Prediction, "Forced InputId=%d", aznumeric_cast(input.GetClientInputId())); From 239fbda10f001da672b9476ee2a75e3ee9d7e3e8 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Mon, 16 Aug 2021 17:29:25 -0700 Subject: [PATCH 484/803] OpenMesh warnings Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Gems/WhiteBox/Code/Source/Core/WhiteBoxToolApi.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Gems/WhiteBox/Code/Source/Core/WhiteBoxToolApi.cpp b/Gems/WhiteBox/Code/Source/Core/WhiteBoxToolApi.cpp index 3bcd2dbd94..a7834100b5 100644 --- a/Gems/WhiteBox/Code/Source/Core/WhiteBoxToolApi.cpp +++ b/Gems/WhiteBox/Code/Source/Core/WhiteBoxToolApi.cpp @@ -30,6 +30,7 @@ #include // OpenMesh includes +AZ_PUSH_DISABLE_WARNING(4702, "-Wunknown-warning-option") // OpenMesh\Core\Utils\Property.hh has unreachable code #include #include #include @@ -37,6 +38,7 @@ #include #include #include +AZ_POP_DISABLE_WARNING namespace OpenMesh { From 9e4c434095846b38fc176652074d6d0daa15cb16 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Mon, 16 Aug 2021 17:41:23 -0700 Subject: [PATCH 485/803] unreachable code in jinja Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja | 2 -- 1 file changed, 2 deletions(-) diff --git a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja index b1946eb61f..b89d1a2b2e 100644 --- a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja +++ b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja @@ -1586,8 +1586,6 @@ namespace {{ Component.attrib['Namespace'] }} default: return false; } - AZ_Assert(0, "Got unhandled RpcType %d in {{ ComponentBaseName }}", static_cast(rpcType)); - return false; } AZ_POP_DISABLE_WARNING From 0f26a6508ab6fc3f9788486bde9531a339342655 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Mon, 16 Aug 2021 17:54:17 -0700 Subject: [PATCH 486/803] fixing comment Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../AzNetworking/AzNetworking/Utilities/QuantizedValues.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Framework/AzNetworking/AzNetworking/Utilities/QuantizedValues.h b/Code/Framework/AzNetworking/AzNetworking/Utilities/QuantizedValues.h index 46e778d5b3..49f5533548 100644 --- a/Code/Framework/AzNetworking/AzNetworking/Utilities/QuantizedValues.h +++ b/Code/Framework/AzNetworking/AzNetworking/Utilities/QuantizedValues.h @@ -176,7 +176,7 @@ namespace AzNetworking //! Takes a quantized integral value and stores the floating point representation. void DecodeQuantizedValues(); - AZ_PUSH_DISABLE_WARNING(4324, "-Wunknown-warning-option") // anonymous union, structure was padded due to alignment + AZ_PUSH_DISABLE_WARNING(4324, "-Wunknown-warning-option") // structure was padded due to alignment union { float m_quantizedValues[NUM_ELEMENTS]; From 4e3ec08c6a1fdd0a99d4f6acee302acd211f3612 Mon Sep 17 00:00:00 2001 From: abrmich Date: Mon, 16 Aug 2021 18:03:13 -0700 Subject: [PATCH 487/803] Fix script canvases not loading if on a UI canvas element Signed-off-by: abrmich --- Gems/LyShine/Code/Source/UiCanvasFileObject.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Gems/LyShine/Code/Source/UiCanvasFileObject.h b/Gems/LyShine/Code/Source/UiCanvasFileObject.h index 4cfec60bea..167405355b 100644 --- a/Gems/LyShine/Code/Source/UiCanvasFileObject.h +++ b/Gems/LyShine/Code/Source/UiCanvasFileObject.h @@ -24,7 +24,8 @@ public: AZ_CLASS_ALLOCATOR(UiCanvasFileObject, AZ::SystemAllocator, 0); AZ_RTTI(UiCanvasFileObject, "{1F02632F-F113-49B1-85AD-8CD0FA78B8AA}"); - static UiCanvasFileObject* LoadCanvasFromStream(AZ::IO::GenericStream& stream, const AZ::ObjectStream::FilterDescriptor& filterDesc = AZ::ObjectStream::FilterDescriptor(AZ::ObjectStream::AssetFilterAssetTypesOnly)); + // Load canvas from stream with an optional asset filter. No asset references are ignored by default + static UiCanvasFileObject* LoadCanvasFromStream(AZ::IO::GenericStream& stream, const AZ::ObjectStream::FilterDescriptor& filterDesc = AZ::ObjectStream::FilterDescriptor()); static void SaveCanvasToStream(AZ::IO::GenericStream& stream, UiCanvasFileObject* canvasFileObject); static AZ::Entity* LoadCanvasEntitiesFromStream(AZ::IO::GenericStream& stream, AZ::Entity*& rootSliceEntity); From 9a8ec8bfcd7648e3f2aa0fcfb479f92559e0a82d Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Mon, 16 Aug 2021 18:13:27 -0700 Subject: [PATCH 488/803] fix for clang Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../AzFramework/Archive/ZipDirStructures.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/Code/Framework/AzFramework/AzFramework/Archive/ZipDirStructures.cpp b/Code/Framework/AzFramework/AzFramework/Archive/ZipDirStructures.cpp index 1748d1578b..5f0d58a4cb 100644 --- a/Code/Framework/AzFramework/AzFramework/Archive/ZipDirStructures.cpp +++ b/Code/Framework/AzFramework/AzFramework/Archive/ZipDirStructures.cpp @@ -342,7 +342,9 @@ namespace AZ::IO::ZipDir AZ::u64 fileSize = 0; if (!m_fileIOBase->Size(realFileHandle, fileSize)) { - goto error; + // Error + m_nSize = 0; + return; } const size_t nFileSize = static_cast(fileSize); @@ -352,16 +354,18 @@ namespace AZ::IO::ZipDir if (!m_fileIOBase->Seek(realFileHandle, 0, AZ::IO::SeekType::SeekFromStart)) { - goto error; + // Error + m_nSize = 0; + return; } if (!m_fileIOBase->Read(realFileHandle, m_pInMemoryData->m_address.get(), nFileSize, true)) { - goto error; + // Error + m_nSize = 0; + return; } return; - error: - m_nSize = 0; } } } From e3cf15a00f650545bd94e7e6303c4de8a5d26ac2 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Mon, 16 Aug 2021 19:52:00 -0700 Subject: [PATCH 489/803] Fixes for Android/Linux Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Editor/Controls/ConsoleSCB.cpp | 4 ++-- Gems/LyShine/Code/Source/Animation/AnimTrack.h | 8 +++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/Code/Editor/Controls/ConsoleSCB.cpp b/Code/Editor/Controls/ConsoleSCB.cpp index c4f58b5297..dbe7ba3472 100644 --- a/Code/Editor/Controls/ConsoleSCB.cpp +++ b/Code/Editor/Controls/ConsoleSCB.cpp @@ -837,11 +837,11 @@ static void SetEditorRange(EditorType* editor, IVariable* var) static const float defaultMax = 100.0f; if (var->HasCustomLimits()) { - editor->setRange(static_cast(min), static_cast(max)); + editor->setRange(static_cast(min), static_cast(max)); } else { - editor->setSoftRange(static_cast(defaultMin), static_cast(defaultMax)); + editor->setSoftRange(static_cast(defaultMin), static_cast(defaultMax)); } // Set the step size. The default variable step is 0, so if it's diff --git a/Gems/LyShine/Code/Source/Animation/AnimTrack.h b/Gems/LyShine/Code/Source/Animation/AnimTrack.h index 97a251ebfa..21a78ae6a1 100644 --- a/Gems/LyShine/Code/Source/Animation/AnimTrack.h +++ b/Gems/LyShine/Code/Source/Animation/AnimTrack.h @@ -221,6 +221,8 @@ protected: float m_lastTime; int m_flags; + constexpr unsigned int InvalidKey = 0x7FFFFFFF; + UiAnimParamData m_componentParamData; #ifdef UI_ANIMATION_SYSTEM_SUPPORT_EDITING @@ -521,7 +523,7 @@ inline int TUiAnimTrack::GetActiveKey(float time, KeyType* key) if (nkeys == 0) { m_lastTime = time; - m_currKey = std::numeric_limits::max(); + m_currKey = InvalidKey; return m_currKey; } @@ -554,7 +556,7 @@ inline int TUiAnimTrack::GetActiveKey(float time, KeyType* key) } else { - m_currKey = std::numeric_limits::max(); + m_currKey = InvalidKey; } return m_currKey; } @@ -600,6 +602,6 @@ inline int TUiAnimTrack::GetActiveKey(float time, KeyType* key) break; } } - m_currKey = std::numeric_limits::max(); + m_currKey = InvalidKey; return m_currKey; } From e2a9c58cae300317f0b3b80ea3cccaae26926512 Mon Sep 17 00:00:00 2001 From: Kyle B Date: Mon, 16 Aug 2021 23:01:18 -0700 Subject: [PATCH 490/803] fixed unnessisary qualifier error Signed-off-by: Kyle B --- .../CommonFeatures/Code/Source/Mesh/MeshComponentController.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h index aba560b6e8..c7f9c8f993 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h @@ -148,7 +148,7 @@ namespace AZ void UnregisterModel(); void RefreshModelRegistration(); - RPI::Cullable::LodConfiguration MeshComponentController::GetMeshLodConfiguration() const; + RPI::Cullable::LodConfiguration GetMeshLodConfiguration() const; void HandleNonUniformScaleChange(const AZ::Vector3& nonUniformScale); From 01ad7c5e4efcb95a185588c5e9ff13633e7667fd Mon Sep 17 00:00:00 2001 From: Kyle B Date: Mon, 16 Aug 2021 23:09:25 -0700 Subject: [PATCH 491/803] fixed namespace issue with the mocks Signed-off-by: Kyle B --- .../Atom/Feature/Common/Code/Mocks/MockMeshFeatureProcessor.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gems/Atom/Feature/Common/Code/Mocks/MockMeshFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Mocks/MockMeshFeatureProcessor.h index 0c03e767e7..75ce42daed 100644 --- a/Gems/Atom/Feature/Common/Code/Mocks/MockMeshFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Mocks/MockMeshFeatureProcessor.h @@ -33,8 +33,8 @@ namespace UnitTest MOCK_CONST_METHOD1(GetLocalAabb, AZ::Aabb(const MeshHandle&)); MOCK_METHOD2(SetSortKey, void (const MeshHandle&, AZ::RHI::DrawItemSortKey)); MOCK_CONST_METHOD1(GetSortKey, AZ::RHI::DrawItemSortKey(const MeshHandle&)); - MOCK_METHOD2(SetMeshLodConfiguration, void(const MeshHandle&, RPI::Cullable::LodConfiguration)); - MOCK_CONST_METHOD1(GetMeshLodConfiguration, RPI::Cullable::LodConfiguration(const MeshHandle&)); + MOCK_METHOD2(SetMeshLodConfiguration, void(const MeshHandle&, AZ::RPI::Cullable::LodConfiguration)); + MOCK_CONST_METHOD1(GetMeshLodConfiguration, AZ::RPI::Cullable::LodConfiguration(const MeshHandle&)); MOCK_METHOD2(AcquireMesh, MeshHandle (const AZ::Render::MeshHandleDescriptor&, const AZ::Render::MaterialAssignmentMap&)); MOCK_METHOD2(AcquireMesh, MeshHandle (const AZ::Render::MeshHandleDescriptor&, const AZ::Data::Instance&)); MOCK_METHOD2(SetRayTracingEnabled, void (const MeshHandle&, bool)); From d9ea329cbde12eb973a9942562c18ae40e5e052b Mon Sep 17 00:00:00 2001 From: amzn-sean <75276488+amzn-sean@users.noreply.github.com> Date: Tue, 17 Aug 2021 13:48:51 +0100 Subject: [PATCH 492/803] Fixes #2796 Collider retains phys mesh asset reference after changing to shape (#3162) Signed-off-by: amzn-sean <75276488+amzn-sean@users.noreply.github.com> --- .../PhysX/Code/Source/EditorColliderComponent.cpp | 15 ++++++++++++++- Gems/PhysX/Code/Source/EditorColliderComponent.h | 9 ++++++--- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/Gems/PhysX/Code/Source/EditorColliderComponent.cpp b/Gems/PhysX/Code/Source/EditorColliderComponent.cpp index d3f1c63974..2445aba9bd 100644 --- a/Gems/PhysX/Code/Source/EditorColliderComponent.cpp +++ b/Gems/PhysX/Code/Source/EditorColliderComponent.cpp @@ -88,7 +88,7 @@ namespace PhysX ->EnumAttribute(Physics::ShapeType::Box, "Box") ->EnumAttribute(Physics::ShapeType::Capsule, "Capsule") ->EnumAttribute(Physics::ShapeType::PhysicsAsset, "PhysicsAsset") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ::Edit::PropertyRefreshLevels::EntireTree) + ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorProxyShapeConfig::OnShapeTypeChanged) // note: we do not want the user to be able to change shape types while in ComponentMode (there will // potentially be different ComponentModes for different shape types) ->Attribute(AZ::Edit::Attributes::ReadOnly, &AzToolsFramework::ComponentModeFramework::InComponentMode) @@ -116,6 +116,19 @@ namespace PhysX } } + AZ::u32 EditorProxyShapeConfig::OnShapeTypeChanged() + { + //reset the physics asset if the shape type was Physics Asset + if (m_shapeType != Physics::ShapeType::PhysicsAsset && + m_lastShapeType == Physics::ShapeType::PhysicsAsset) + { + m_physicsAsset.m_pxAsset.Reset(); + m_physicsAsset.m_configuration = Physics::PhysicsAssetShapeConfiguration(); + } + m_lastShapeType = m_shapeType; + return AZ::Edit::PropertyRefreshLevels::EntireTree; + } + AZ::u32 EditorProxyShapeConfig::OnConfigurationChanged() { return AZ::Edit::PropertyRefreshLevels::ValuesOnly; diff --git a/Gems/PhysX/Code/Source/EditorColliderComponent.h b/Gems/PhysX/Code/Source/EditorColliderComponent.h index 8a78cc1cb8..50cf9d0c8b 100644 --- a/Gems/PhysX/Code/Source/EditorColliderComponent.h +++ b/Gems/PhysX/Code/Source/EditorColliderComponent.h @@ -58,8 +58,8 @@ namespace PhysX //! Proxy container for only displaying a specific shape configuration depending on the shapeType selected. struct EditorProxyShapeConfig { - AZ_CLASS_ALLOCATOR(EditorProxyShapeConfig, AZ::SystemAllocator, 0); - AZ_RTTI(EditorProxyShapeConfig, "{531FB42A-42A9-4234-89BA-FD349EF83D0C}"); + AZ_CLASS_ALLOCATOR(PhysX::EditorProxyShapeConfig, AZ::SystemAllocator, 0); + AZ_RTTI(PhysX::EditorProxyShapeConfig, "{531FB42A-42A9-4234-89BA-FD349EF83D0C}"); static void Reflect(AZ::ReflectContext* context); EditorProxyShapeConfig() = default; @@ -84,9 +84,12 @@ namespace PhysX AZStd::shared_ptr CloneCurrent() const; + private: bool ShowingSubdivisionLevel() const; - + AZ::u32 OnShapeTypeChanged(); AZ::u32 OnConfigurationChanged(); + + Physics::ShapeType m_lastShapeType = Physics::ShapeType::PhysicsAsset; }; class EditorColliderComponentDescriptor; From d1cedba042c4847def1101eecbf99739dfa69ed2 Mon Sep 17 00:00:00 2001 From: Nicholas Van Sickle Date: Tue, 17 Aug 2021 06:20:33 -0700 Subject: [PATCH 493/803] Fix NativeWindow_Windows returning the wrong size. (#3153) Make sure WM_WINDOWPOSCHANGED bubbles up so that we can see WM_SIZE. Signed-off-by: nvsickle --- .../AzFramework/Windowing/NativeWindow_Windows.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/Code/Framework/AzFramework/Platform/Windows/AzFramework/Windowing/NativeWindow_Windows.cpp b/Code/Framework/AzFramework/Platform/Windows/AzFramework/Windowing/NativeWindow_Windows.cpp index 2c1d97dcf6..8312f9fa63 100644 --- a/Code/Framework/AzFramework/Platform/Windows/AzFramework/Windowing/NativeWindow_Windows.cpp +++ b/Code/Framework/AzFramework/Platform/Windows/AzFramework/Windowing/NativeWindow_Windows.cpp @@ -207,7 +207,10 @@ namespace AzFramework // Handles Win32 Window Event callbacks LRESULT CALLBACK NativeWindowImpl_Win32::WindowCallback(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { - NativeWindowImpl_Win32* nativeWindowImpl = reinterpret_cast(GetWindowLongPtr(hWnd, GWLP_USERDATA)); + NativeWindowImpl_Win32* nativeWindowImpl = reinterpret_cast(GetWindowLongPtr(hWnd, GWLP_USERDATA)); + + // If set to true, call DefWindowProc to ensure the default Windows behavior occurs + bool shouldBubbleEventUp = false; switch (message) { @@ -276,14 +279,19 @@ namespace AzFramework uint32_t refreshRate = DisplayConfig.dmDisplayFrequency; WindowNotificationBus::Event( nativeWindowImpl->GetWindowHandle(), &WindowNotificationBus::Events::OnRefreshRateChanged, refreshRate); + shouldBubbleEventUp = true; break; } default: - return DefWindowProc(hWnd, message, wParam, lParam); + shouldBubbleEventUp = true; break; } - return 0; + if (!shouldBubbleEventUp) + { + return 0; + } + return DefWindowProc(hWnd, message, wParam, lParam); } void NativeWindowImpl_Win32::WindowSizeChanged(const uint32_t width, const uint32_t height) From 4cac87558901899265faec9f1bb79e7b9d42c171 Mon Sep 17 00:00:00 2001 From: galibzon <66021303+galibzon@users.noreply.github.com> Date: Tue, 17 Aug 2021 08:21:39 -0500 Subject: [PATCH 494/803] [ATOM-15058] Remove Automatic Entry Point Detection (#3150) .shader files must declare at least one entry function. Signed-off-by: garrieta --- .../AzslShaderBuilderSystemComponent.cpp | 2 +- .../Code/Source/Editor/ShaderAssetBuilder.cpp | 25 +++--- .../Source/Editor/ShaderBuilderUtility.cpp | 85 ------------------- .../Code/Source/Editor/ShaderBuilderUtility.h | 8 -- .../Editor/ShaderVariantAssetBuilder.cpp | 15 ++-- .../Materials/Special/ShadowCatcher.shader | 15 ++++ .../Assets/Shaders/Depth/DepthPass.shader | 11 +++ .../Depth/DepthPassTransparentMax.shader | 11 +++ .../Depth/DepthPassTransparentMin.shader | 11 +++ 9 files changed, 65 insertions(+), 118 deletions(-) diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/AzslShaderBuilderSystemComponent.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/AzslShaderBuilderSystemComponent.cpp index 29e6fb7a6f..16cebef6ac 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/AzslShaderBuilderSystemComponent.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/AzslShaderBuilderSystemComponent.cpp @@ -81,7 +81,7 @@ namespace AZ // Register Shader Asset Builder AssetBuilderSDK::AssetBuilderDesc shaderAssetBuilderDescriptor; shaderAssetBuilderDescriptor.m_name = "Shader Asset Builder"; - shaderAssetBuilderDescriptor.m_version = 102; // ATOM-15472 + shaderAssetBuilderDescriptor.m_version = 103; // ATOM-15058 // .shader file changes trigger rebuilds shaderAssetBuilderDescriptor.m_patterns.push_back(AssetBuilderSDK::AssetBuilderPattern( AZStd::string::format("*.%s", RPI::ShaderSourceData::Extension), AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard)); shaderAssetBuilderDescriptor.m_busId = azrtti_typeid(); diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderAssetBuilder.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderAssetBuilder.cpp index 606502fb22..2332f4522b 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderAssetBuilder.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderAssetBuilder.cpp @@ -226,11 +226,9 @@ namespace AZ if (!hasRasterProgram && !hasComputeProgram && !hasRayTracingProgram) { - AZStd::string entryPointNames = ShaderBuilderUtility::GetAcceptableDefaultEntryPointNames(azslData); return AZ::Failure( - AZStd::string::format( "Shader asset descriptor has a program variant that does not define any entry points. Either declare entry " - "points in the .shader file, or use one of the available default names (not case-sensitive): [%s]", - entryPointNames.c_str())); + AZStd::string( "Shader asset descriptor has a program variant that does not define any entry points." + " Please declare entry points in the .shader file.")); } return AZ::Success(attributeMaps); @@ -478,21 +476,18 @@ namespace AZ } } - // Discover entry points & type of programs. - MapOfStringToStageType shaderEntryPoints; if (shaderSourceData.m_programSettings.m_entryPoints.empty()) { - AZ_TracePrintf( - ShaderAssetBuilderName, - "ProgramSettings do not specify entry points, will use GetDefaultEntryPointsFromShader()\n"); - ShaderBuilderUtility::GetDefaultEntryPointsFromFunctionDataList(azslData.m_functions, shaderEntryPoints); + AZ_Error( ShaderAssetBuilderName, false, "ProgramSettings must specify entry points."); + response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Failed; + return; } - else + + // Discover entry points & type of programs. + MapOfStringToStageType shaderEntryPoints; + for (const auto& entryPoint : shaderSourceData.m_programSettings.m_entryPoints) { - for (const auto& entryPoint : shaderSourceData.m_programSettings.m_entryPoints) - { - shaderEntryPoints[entryPoint.m_name] = entryPoint.m_type; - } + shaderEntryPoints[entryPoint.m_name] = entryPoint.m_type; } bool hasRasterProgram = false; diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuilderUtility.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuilderUtility.cpp index d7c3de48c0..0018f2ead8 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuilderUtility.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuilderUtility.cpp @@ -809,91 +809,6 @@ namespace AZ return success; } - - //! Returns a list of acceptable default entry point names - static void GetAcceptableDefaultEntryPoints( - const AZStd::vector& azslFunctionDataList, - AZStd::unordered_map& defaultEntryPoints) - { - for (const auto& func : azslFunctionDataList) - { - if (!func.m_hasShaderStageVaryings) - { - // Not declaring any semantics for a shader entry is valid, but unusual. - // A shader entry with no semantics must be explicitly listed and won't be selected by default. - continue; - } - - if (func.m_name.starts_with("VS") || func.m_name.ends_with("VS")) - { - defaultEntryPoints[func.m_name] = RPI::ShaderStageType::Vertex; - AZ_TracePrintf( - ShaderBuilderUtilityName, "Assuming \"%s\" is a valid Vertex shader entry point.\n", func.m_name.c_str()); - } - else if (func.m_name.starts_with("PS") || func.m_name.ends_with("PS")) - { - defaultEntryPoints[func.m_name] = RPI::ShaderStageType::Fragment; - AZ_TracePrintf( - ShaderBuilderUtilityName, "Assuming \"%s\" is a valid Fragment shader entry point.\n", - func.m_name.c_str()); - } - else if (func.m_name.starts_with("CS") || func.m_name.ends_with("CS")) - { - defaultEntryPoints[func.m_name] = RPI::ShaderStageType::Compute; - AZ_TracePrintf( - ShaderBuilderUtilityName, "Assuming \"%s\" is a valid Compute shader entry point.\n", func.m_name.c_str()); - } - } - } - - - // DEPRECATED [ATOM-15472 - //! Returns a list of acceptable default entry point names - //! This function - static void GetAcceptableDefaultEntryPoints( - const AzslData& azslData, AZStd::unordered_map& defaultEntryPoints) - { - return GetAcceptableDefaultEntryPoints(azslData.m_functions, defaultEntryPoints); - } - - - void GetDefaultEntryPointsFromFunctionDataList( - const AZStd::vector azslFunctionDataList, - AZStd::unordered_map& shaderEntryPoints) - { - AZStd::unordered_map defaultEntryPoints; - GetAcceptableDefaultEntryPoints(azslFunctionDataList, defaultEntryPoints); - - for (const auto& functionData : azslFunctionDataList) - { - for (const auto& defaultEntryPoint : defaultEntryPoints) - { - // Equal defaults to case insensitive compares... - if (AzFramework::StringFunc::Equal(defaultEntryPoint.first.c_str(), functionData.m_name.c_str())) - { - shaderEntryPoints[defaultEntryPoint.first] = defaultEntryPoint.second; - break; // stop looping default entry points and go to the next shader function - } - } - } - } - - AZStd::string GetAcceptableDefaultEntryPointNames(const AzslData& azslData) - { - AZStd::unordered_map defaultEntryPointList; - GetAcceptableDefaultEntryPoints(azslData, defaultEntryPointList); - - AZStd::vector defaultEntryPointNamesList; - for (const auto& shaderEntryPoint : defaultEntryPointList) - { - defaultEntryPointNamesList.push_back(shaderEntryPoint.first); - } - AZStd::string shaderEntryPoints; - AzFramework::StringFunc::Join( - shaderEntryPoints, defaultEntryPointNamesList.begin(), defaultEntryPointNamesList.end(), ", "); - return AZStd::move(shaderEntryPoints); - } - } // namespace ShaderBuilderUtility } // namespace ShaderBuilder } // AZ diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuilderUtility.h b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuilderUtility.h index 9310bf2e2f..c000ba9df6 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuilderUtility.h +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuilderUtility.h @@ -94,10 +94,6 @@ namespace AZ RPI::ShaderOutputContract& shaderOutputContract, size_t& colorAttachmentCount); - //! Returns a list of acceptable default entry point names as a single string for debug messages. - AZStd::string GetAcceptableDefaultEntryPointNames(const AzslData& shaderData); - - //! Create a file from a string's content. //! That file will be named filename.api.azslin //! This is meant to be used at this stage: @@ -138,10 +134,6 @@ namespace AZ AZStd::vector GetSupervariantListFromShaderSourceData( const RPI::ShaderSourceData& shaderSourceData); - void GetDefaultEntryPointsFromFunctionDataList( - const AZStd::vector azslFunctionDataList, - AZStd::unordered_map& shaderEntryPoints); - void LogProfilingData(const char* builderName, AZStd::string_view shaderPath); //! Returns the asset path of a product artifact produced by ShaderAssetBuilder. diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp index 1da4623774..59660440e4 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp @@ -843,17 +843,14 @@ namespace AZ MapOfStringToStageType shaderEntryPoints; if (shaderSourceDescriptor.m_programSettings.m_entryPoints.empty()) { - AZ_TracePrintf( - ShaderVariantAssetBuilderName, - "ProgramSettings do not specify entry points, will use GetDefaultEntryPointsFromShader()\n"); - ShaderBuilderUtility::GetDefaultEntryPointsFromFunctionDataList(azslFunctions, shaderEntryPoints); + AZ_Error(ShaderVariantAssetBuilderName, false, "ProgramSettings must specify entry points."); + response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Failed; + return; } - else + + for (const auto& entryPoint : shaderSourceDescriptor.m_programSettings.m_entryPoints) { - for (const auto& entryPoint : shaderSourceDescriptor.m_programSettings.m_entryPoints) - { - shaderEntryPoints[entryPoint.m_name] = entryPoint.m_type; - } + shaderEntryPoints[entryPoint.m_name] = entryPoint.m_type; } // 3- hlslCode diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Special/ShadowCatcher.shader b/Gems/Atom/Feature/Common/Assets/Materials/Special/ShadowCatcher.shader index f4784440b1..7df4169498 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Special/ShadowCatcher.shader +++ b/Gems/Atom/Feature/Common/Assets/Materials/Special/ShadowCatcher.shader @@ -18,5 +18,20 @@ "BlendOp": "Add" }, + "ProgramSettings" : + { + "EntryPoints": + [ + { + "name": "ShadowCatcherVS", + "type" : "Vertex" + }, + { + "name": "ShadowCatcherPS", + "type" : "Fragment" + } + ] + }, + "DrawList": "transparent" } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/Depth/DepthPass.shader b/Gems/Atom/Feature/Common/Assets/Shaders/Depth/DepthPass.shader index fe76eb06cb..463db025e7 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/Depth/DepthPass.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/Depth/DepthPass.shader @@ -9,5 +9,16 @@ "DisableOptimizations" : false }, + "ProgramSettings" : + { + "EntryPoints": + [ + { + "name": "DepthPassVS", + "type" : "Vertex" + } + ] + }, + "DrawList" : "depth" } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/Depth/DepthPassTransparentMax.shader b/Gems/Atom/Feature/Common/Assets/Shaders/Depth/DepthPassTransparentMax.shader index a56959e357..5bfdc8bcc1 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/Depth/DepthPassTransparentMax.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/Depth/DepthPassTransparentMax.shader @@ -13,5 +13,16 @@ "CompilerHints" : { }, + "ProgramSettings" : + { + "EntryPoints": + [ + { + "name": "DepthPassVS", + "type" : "Vertex" + } + ] + }, + "DrawList" : "depthTransparentMax" } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/Depth/DepthPassTransparentMin.shader b/Gems/Atom/Feature/Common/Assets/Shaders/Depth/DepthPassTransparentMin.shader index 709e467479..5cd8ea7c33 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/Depth/DepthPassTransparentMin.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/Depth/DepthPassTransparentMin.shader @@ -11,5 +11,16 @@ "DisableOptimizations" : false }, + "ProgramSettings" : + { + "EntryPoints": + [ + { + "name": "DepthPassVS", + "type" : "Vertex" + } + ] + }, + "DrawList" : "depthTransparentMin" } From eb1593a19c7107ab5cc8f6fae8f62504da224790 Mon Sep 17 00:00:00 2001 From: amzn-victor <86271008+amzn-victor@users.noreply.github.com> Date: Tue, 17 Aug 2021 06:52:20 -0700 Subject: [PATCH 495/803] Changes to SDK wrappers and functions to allow more flexible scene file processing (#3112) These changes allow for usage of different asset import SDKs to process scene files. Move AssImp specific code out of node, scene & material wrapper parent classes and into child wrapper classes (AssImpNodeWrapper, etc.), allowing child classes to expose import SDK code. Allows for more convenient implementation of other import SDK's elsewhere (such as in a gem). Add a loadingComponentUuid parameter to LoadSceneFromVerifiedPath to allow for usage of different loading components. Changed tests and all calls to this function accordingly. * Move AssImp specific code out of wrapper parent classes and into child classes for gem usage Signed-off-by: Victor Huang * Add loadingComponentUuid parameter to LoadSceneFromVerifiedPath function Signed-off-by: Victor Huang * Make wrapper members protected, change pointer cast Signed-off-by: Victor Huang * Adding spaces to fix style Signed-off-by: Victor Huang * Fix for pointer cast causing test failures Signed-off-by: Victor Huang --- .../SceneSerializationHandler.cpp | 3 ++- .../SceneAPI/SDKWrapper/AssImpMaterialWrapper.cpp | 7 ++++++- .../SceneAPI/SDKWrapper/AssImpMaterialWrapper.h | 4 ++++ .../SceneAPI/SDKWrapper/AssImpNodeWrapper.cpp | 6 ++++-- .../Tools/SceneAPI/SDKWrapper/AssImpNodeWrapper.h | 6 +++++- .../SceneAPI/SDKWrapper/AssImpSceneWrapper.cpp | 12 ++++++------ .../SceneAPI/SDKWrapper/AssImpSceneWrapper.h | 5 +++-- .../Tools/SceneAPI/SDKWrapper/MaterialWrapper.cpp | 15 --------------- Code/Tools/SceneAPI/SDKWrapper/MaterialWrapper.h | 8 +------- Code/Tools/SceneAPI/SDKWrapper/NodeWrapper.cpp | 15 --------------- Code/Tools/SceneAPI/SDKWrapper/NodeWrapper.h | 8 +------- Code/Tools/SceneAPI/SDKWrapper/SceneWrapper.cpp | 13 ------------- Code/Tools/SceneAPI/SDKWrapper/SceneWrapper.h | 6 ------ .../Importers/AssImpMaterialImporter.cpp | 4 ++-- .../Tools/SceneAPI/SceneBuilder/SceneImporter.cpp | 7 ++++++- .../SceneCore/Events/AssetImportRequest.cpp | 4 ++-- .../SceneCore/Events/AssetImportRequest.h | 3 ++- .../Tests/Events/AssetImporterRequestTests.cpp | 13 +++++++------ .../SceneBuilder/SceneSerializationHandler.cpp | 6 ++++-- 19 files changed, 55 insertions(+), 90 deletions(-) diff --git a/Code/Editor/Plugins/EditorAssetImporter/SceneSerializationHandler.cpp b/Code/Editor/Plugins/EditorAssetImporter/SceneSerializationHandler.cpp index 441fb362d6..c087a27ba4 100644 --- a/Code/Editor/Plugins/EditorAssetImporter/SceneSerializationHandler.cpp +++ b/Code/Editor/Plugins/EditorAssetImporter/SceneSerializationHandler.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -96,7 +97,7 @@ namespace AZ } AZStd::shared_ptr scene = - AssetImportRequest::LoadSceneFromVerifiedPath(cleanPath, sceneSourceGuid, AssetImportRequest::RequestingApplication::Editor); + AssetImportRequest::LoadSceneFromVerifiedPath(cleanPath, sceneSourceGuid, AssetImportRequest::RequestingApplication::Editor, SceneAPI::SceneCore::LoadingComponent::TYPEINFO_Uuid()); if (!scene) { AZ_TracePrintf(Utilities::ErrorWindow, "Failed to load the requested scene."); diff --git a/Code/Tools/SceneAPI/SDKWrapper/AssImpMaterialWrapper.cpp b/Code/Tools/SceneAPI/SDKWrapper/AssImpMaterialWrapper.cpp index 8ea25a2ff0..68b00eb811 100644 --- a/Code/Tools/SceneAPI/SDKWrapper/AssImpMaterialWrapper.cpp +++ b/Code/Tools/SceneAPI/SDKWrapper/AssImpMaterialWrapper.cpp @@ -21,11 +21,16 @@ namespace AZ { AssImpMaterialWrapper::AssImpMaterialWrapper(aiMaterial* aiMaterial) - :SDKMaterial::MaterialWrapper(aiMaterial) + :m_assImpMaterial(aiMaterial) { AZ_Assert(aiMaterial, "Asset Importer Material cannot be null"); } + aiMaterial* AssImpMaterialWrapper::GetAssImpMaterial() const + { + return m_assImpMaterial; + } + AZStd::string AssImpMaterialWrapper::GetName() const { return m_assImpMaterial->GetName().C_Str(); diff --git a/Code/Tools/SceneAPI/SDKWrapper/AssImpMaterialWrapper.h b/Code/Tools/SceneAPI/SDKWrapper/AssImpMaterialWrapper.h index 8d7138db16..776e73ebfb 100644 --- a/Code/Tools/SceneAPI/SDKWrapper/AssImpMaterialWrapper.h +++ b/Code/Tools/SceneAPI/SDKWrapper/AssImpMaterialWrapper.h @@ -20,6 +20,7 @@ namespace AZ AZ_RTTI(AssImpMaterialWrapper, "{66992628-CFCE-441B-8849-9344A49AFAC9}", SDKMaterial::MaterialWrapper); AssImpMaterialWrapper(aiMaterial* aiMaterial); ~AssImpMaterialWrapper() override = default; + aiMaterial* GetAssImpMaterial() const; AZStd::string GetName() const override; AZ::u64 GetUniqueId() const override; AZ::Vector3 GetDiffuseColor() const override; @@ -38,6 +39,9 @@ namespace AZ AZStd::optional GetUseEmissiveMap() const; AZStd::optional GetEmissiveIntensity() const; AZStd::optional GetUseAOMap() const; + + protected: + aiMaterial* m_assImpMaterial = nullptr; }; } // namespace AssImpSDKWrapper }// namespace AZ diff --git a/Code/Tools/SceneAPI/SDKWrapper/AssImpNodeWrapper.cpp b/Code/Tools/SceneAPI/SDKWrapper/AssImpNodeWrapper.cpp index 9bd9b191ec..87583a961b 100644 --- a/Code/Tools/SceneAPI/SDKWrapper/AssImpNodeWrapper.cpp +++ b/Code/Tools/SceneAPI/SDKWrapper/AssImpNodeWrapper.cpp @@ -17,14 +17,16 @@ namespace AZ namespace AssImpSDKWrapper { AssImpNodeWrapper::AssImpNodeWrapper(aiNode* sourceNode) - :SDKNode::NodeWrapper(sourceNode) + : m_assImpNode(sourceNode) { AZ_Assert(m_assImpNode, "Asset Importer Node cannot be null"); } - AssImpNodeWrapper::~AssImpNodeWrapper() + aiNode* AssImpNodeWrapper::GetAssImpNode() const { + return m_assImpNode; } + const char* AssImpNodeWrapper::GetName() const { return m_assImpNode->mName.C_Str(); diff --git a/Code/Tools/SceneAPI/SDKWrapper/AssImpNodeWrapper.h b/Code/Tools/SceneAPI/SDKWrapper/AssImpNodeWrapper.h index bcf9eb9234..266653ca51 100644 --- a/Code/Tools/SceneAPI/SDKWrapper/AssImpNodeWrapper.h +++ b/Code/Tools/SceneAPI/SDKWrapper/AssImpNodeWrapper.h @@ -20,7 +20,8 @@ namespace AZ public: AZ_RTTI(AssImpNodeWrapper, "{1043260B-9076-49B7-AD38-EF62E85F7C1D}", SDKNode::NodeWrapper); AssImpNodeWrapper(aiNode* sourceNode); - ~AssImpNodeWrapper() override; + ~AssImpNodeWrapper() override = default; + aiNode* GetAssImpNode() const; const char* GetName() const override; AZ::u64 GetUniqueId() const override; int GetChildCount() const override; @@ -28,6 +29,9 @@ namespace AZ const bool ContainsMesh(); bool ContainsBones(const aiScene& scene) const; int GetMaterialCount() const override; + + protected: + aiNode* m_assImpNode = nullptr; }; } // namespace AssImpSDKWrapper }// namespace AZ diff --git a/Code/Tools/SceneAPI/SDKWrapper/AssImpSceneWrapper.cpp b/Code/Tools/SceneAPI/SDKWrapper/AssImpSceneWrapper.cpp index 12aefca00c..14f9bc0fe3 100644 --- a/Code/Tools/SceneAPI/SDKWrapper/AssImpSceneWrapper.cpp +++ b/Code/Tools/SceneAPI/SDKWrapper/AssImpSceneWrapper.cpp @@ -25,15 +25,10 @@ namespace AZ namespace AssImpSDKWrapper { AssImpSceneWrapper::AssImpSceneWrapper() - : SDKScene::SceneWrapperBase() { } AssImpSceneWrapper::AssImpSceneWrapper(aiScene* aiScene) - : SDKScene::SceneWrapperBase(aiScene) - { - } - - AssImpSceneWrapper::~AssImpSceneWrapper() + : m_assImpScene(aiScene) { } @@ -114,6 +109,11 @@ namespace AZ m_importer.FreeScene(); } + const aiScene* AssImpSceneWrapper::GetAssImpScene() const + { + return m_assImpScene; + } + AZStd::pair AssImpSceneWrapper::GetUpVectorAndSign() const { AZStd::pair result(AxisVector::Z, 1); diff --git a/Code/Tools/SceneAPI/SDKWrapper/AssImpSceneWrapper.h b/Code/Tools/SceneAPI/SDKWrapper/AssImpSceneWrapper.h index 5747f7025d..57f82cc4b1 100644 --- a/Code/Tools/SceneAPI/SDKWrapper/AssImpSceneWrapper.h +++ b/Code/Tools/SceneAPI/SDKWrapper/AssImpSceneWrapper.h @@ -21,13 +21,14 @@ namespace AZ AZ_RTTI(AssImpSceneWrapper, "{43A61F62-DCD4-4132-B80B-F2FBC80740BC}", SDKScene::SceneWrapperBase); AssImpSceneWrapper(); AssImpSceneWrapper(aiScene* aiScene); - ~AssImpSceneWrapper(); + ~AssImpSceneWrapper() override = default; bool LoadSceneFromFile(const char* fileName) override; bool LoadSceneFromFile(const AZStd::string& fileName) override; const std::shared_ptr GetRootNode() const override; std::shared_ptr GetRootNode() override; + virtual const aiScene* GetAssImpScene() const; void Clear() override; enum class AxisVector @@ -43,7 +44,7 @@ namespace AZ AZStd::string GetSceneFileName() const { return m_sceneFileName; } protected: - + const aiScene* m_assImpScene = nullptr; Assimp::Importer m_importer; // FBX SDK automatically resolved relative paths to textures based on the current file location. diff --git a/Code/Tools/SceneAPI/SDKWrapper/MaterialWrapper.cpp b/Code/Tools/SceneAPI/SDKWrapper/MaterialWrapper.cpp index 8209bd4bd0..9e7225ac9d 100644 --- a/Code/Tools/SceneAPI/SDKWrapper/MaterialWrapper.cpp +++ b/Code/Tools/SceneAPI/SDKWrapper/MaterialWrapper.cpp @@ -12,21 +12,6 @@ namespace AZ { namespace SDKMaterial { - MaterialWrapper::MaterialWrapper(aiMaterial* assImpMaterial) - : m_assImpMaterial(assImpMaterial) - { - } - - MaterialWrapper::~MaterialWrapper() - { - m_assImpMaterial = nullptr; - } - - aiMaterial* MaterialWrapper::GetAssImpMaterial() - { - return m_assImpMaterial; - } - AZStd::string MaterialWrapper::GetName() const { return AZStd::string(); diff --git a/Code/Tools/SceneAPI/SDKWrapper/MaterialWrapper.h b/Code/Tools/SceneAPI/SDKWrapper/MaterialWrapper.h index db351f208c..53778ea783 100644 --- a/Code/Tools/SceneAPI/SDKWrapper/MaterialWrapper.h +++ b/Code/Tools/SceneAPI/SDKWrapper/MaterialWrapper.h @@ -34,10 +34,7 @@ namespace AZ BaseColor }; - MaterialWrapper(aiMaterial* assImpmaterial); - virtual ~MaterialWrapper(); - - aiMaterial* GetAssImpMaterial(); + virtual ~MaterialWrapper() = default; virtual AZStd::string GetName() const; virtual AZ::u64 GetUniqueId() const; @@ -47,9 +44,6 @@ namespace AZ virtual AZ::Vector3 GetEmissiveColor() const; virtual float GetOpacity() const; virtual float GetShininess() const; - - protected: - aiMaterial* m_assImpMaterial = nullptr; }; } // namespace SDKMaterial } // namespace AZ diff --git a/Code/Tools/SceneAPI/SDKWrapper/NodeWrapper.cpp b/Code/Tools/SceneAPI/SDKWrapper/NodeWrapper.cpp index 21a4de7c44..6b1c4ba99a 100644 --- a/Code/Tools/SceneAPI/SDKWrapper/NodeWrapper.cpp +++ b/Code/Tools/SceneAPI/SDKWrapper/NodeWrapper.cpp @@ -12,21 +12,6 @@ namespace AZ { namespace SDKNode { - NodeWrapper::NodeWrapper(aiNode* aiNode) - : m_assImpNode(aiNode) - { - } - - NodeWrapper::~NodeWrapper() - { - m_assImpNode = nullptr; - } - - aiNode* NodeWrapper::GetAssImpNode() - { - return m_assImpNode; - } - const char* NodeWrapper::GetName() const { return ""; diff --git a/Code/Tools/SceneAPI/SDKWrapper/NodeWrapper.h b/Code/Tools/SceneAPI/SDKWrapper/NodeWrapper.h index bef3cf0db4..dfd216912a 100644 --- a/Code/Tools/SceneAPI/SDKWrapper/NodeWrapper.h +++ b/Code/Tools/SceneAPI/SDKWrapper/NodeWrapper.h @@ -20,9 +20,7 @@ namespace AZ public: AZ_RTTI(NodeWrapper, "{5EB0897B-9728-44B7-B056-BA34AAF14715}"); - NodeWrapper() = default; - NodeWrapper(aiNode* aiNode); - virtual ~NodeWrapper(); + virtual ~NodeWrapper() = default; enum CurveNodeComponent { @@ -31,16 +29,12 @@ namespace AZ Component_Z }; - aiNode* GetAssImpNode(); - virtual const char* GetName() const; virtual AZ::u64 GetUniqueId() const; virtual int GetMaterialCount() const; virtual int GetChildCount()const; virtual const std::shared_ptr GetChild(int childIndex) const; - - aiNode* m_assImpNode = nullptr; }; } //namespace Node } //namespace AZ diff --git a/Code/Tools/SceneAPI/SDKWrapper/SceneWrapper.cpp b/Code/Tools/SceneAPI/SDKWrapper/SceneWrapper.cpp index 37e92a1eac..42f07618e5 100644 --- a/Code/Tools/SceneAPI/SDKWrapper/SceneWrapper.cpp +++ b/Code/Tools/SceneAPI/SDKWrapper/SceneWrapper.cpp @@ -13,12 +13,6 @@ namespace AZ { const char* SceneWrapperBase::s_defaultSceneName = "myScene"; - SceneWrapperBase::SceneWrapperBase(aiScene* aiScene) - : m_assImpScene(aiScene) - { - } - - bool SceneWrapperBase::LoadSceneFromFile([[maybe_unused]] const char* fileName) { return false; @@ -40,12 +34,5 @@ namespace AZ void SceneWrapperBase::Clear() { } - - const aiScene* SceneWrapperBase::GetAssImpScene() const - { - return m_assImpScene; - } - - } //namespace Scene }// namespace AZ diff --git a/Code/Tools/SceneAPI/SDKWrapper/SceneWrapper.h b/Code/Tools/SceneAPI/SDKWrapper/SceneWrapper.h index d4776174d9..67128134d1 100644 --- a/Code/Tools/SceneAPI/SDKWrapper/SceneWrapper.h +++ b/Code/Tools/SceneAPI/SDKWrapper/SceneWrapper.h @@ -20,9 +20,7 @@ namespace AZ { public: AZ_RTTI(SceneWrapperBase, "{703CD344-2C75-4F30-8CE2-6BDEF2511AFD}"); - SceneWrapperBase() = default; virtual ~SceneWrapperBase() = default; - SceneWrapperBase(aiScene* aiScene); virtual bool LoadSceneFromFile(const char* fileName); virtual bool LoadSceneFromFile(const AZStd::string& fileName); @@ -31,10 +29,6 @@ namespace AZ virtual std::shared_ptr GetRootNode(); virtual void Clear(); - - virtual const aiScene* GetAssImpScene() const; - - const aiScene* m_assImpScene = nullptr; static const char* s_defaultSceneName; }; diff --git a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpMaterialImporter.cpp b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpMaterialImporter.cpp index 8983c76bac..aa53f8be9b 100644 --- a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpMaterialImporter.cpp +++ b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpMaterialImporter.cpp @@ -56,9 +56,9 @@ namespace AZ Events::ProcessingResultCombiner combinedMaterialImportResults; AZStd::unordered_map> materialMap; - for (unsigned int idx = 0; idx < context.m_sourceNode.m_assImpNode->mNumMeshes; ++idx) + for (unsigned int idx = 0; idx < context.m_sourceNode.GetAssImpNode()->mNumMeshes; ++idx) { - int meshIndex = context.m_sourceNode.m_assImpNode->mMeshes[idx]; + int meshIndex = context.m_sourceNode.GetAssImpNode()->mMeshes[idx]; const aiMesh* assImpMesh = context.m_sourceScene.GetAssImpScene()->mMeshes[meshIndex]; AZ_Assert(assImpMesh, "Asset Importer Mesh should not be null."); int materialIndex = assImpMesh->mMaterialIndex; diff --git a/Code/Tools/SceneAPI/SceneBuilder/SceneImporter.cpp b/Code/Tools/SceneAPI/SceneBuilder/SceneImporter.cpp index 3f2ec6c1eb..c0c0fe1330 100644 --- a/Code/Tools/SceneAPI/SceneBuilder/SceneImporter.cpp +++ b/Code/Tools/SceneAPI/SceneBuilder/SceneImporter.cpp @@ -222,7 +222,12 @@ namespace AZ int childCount = node.m_node->GetChildCount(); for (int i = 0; i < childCount; ++i) { - std::shared_ptr child = std::make_shared(node.m_node->GetChild(i)->GetAssImpNode()); + const std::shared_ptr nodeWrapper = node.m_node->GetChild(i); + auto assImpNodeWrapper = azrtti_cast(nodeWrapper.get()); + + AZ_Assert(assImpNodeWrapper, "Child node is not the expected AssImpNodeWrapper type"); + + std::shared_ptr child = std::make_shared(assImpNodeWrapper->GetAssImpNode()); if (child) { nodes.emplace(AZStd::move(child), newNode); diff --git a/Code/Tools/SceneAPI/SceneCore/Events/AssetImportRequest.cpp b/Code/Tools/SceneAPI/SceneCore/Events/AssetImportRequest.cpp index 7950eff130..a182e4f02d 100644 --- a/Code/Tools/SceneAPI/SceneCore/Events/AssetImportRequest.cpp +++ b/Code/Tools/SceneAPI/SceneCore/Events/AssetImportRequest.cpp @@ -104,7 +104,7 @@ namespace AZ } AZStd::shared_ptr AssetImportRequest::LoadSceneFromVerifiedPath(const AZStd::string& assetFilePath, const Uuid& sourceGuid, - RequestingApplication requester) + RequestingApplication requester, const Uuid& loadingComponentUuid) { AZStd::string sceneName; AzFramework::StringFunc::Path::GetFileName(assetFilePath.c_str(), sceneName); @@ -113,7 +113,7 @@ namespace AZ // Unique pointer, will deactivate and clean up once going out of scope. SceneCore::EntityConstructor::EntityPointer loaders = - SceneCore::EntityConstructor::BuildEntity("Scene Loading", SceneCore::LoadingComponent::TYPEINFO_Uuid()); + SceneCore::EntityConstructor::BuildEntity("Scene Loading", loadingComponentUuid); ProcessingResultCombiner areAllPrepared; AssetImportRequestBus::BroadcastResult(areAllPrepared, &AssetImportRequestBus::Events::PrepareForAssetLoading, *scene, requester); diff --git a/Code/Tools/SceneAPI/SceneCore/Events/AssetImportRequest.h b/Code/Tools/SceneAPI/SceneCore/Events/AssetImportRequest.h index 2a071a4001..8b6e119f99 100644 --- a/Code/Tools/SceneAPI/SceneCore/Events/AssetImportRequest.h +++ b/Code/Tools/SceneAPI/SceneCore/Events/AssetImportRequest.h @@ -102,8 +102,9 @@ namespace AZ //! @param sourceGuid The guid assigned to the source file (not the manifest). //! @param requester The application making the request to load the file. This can be used to optimize the type and amount of data //! to load. + //! @param loadingComponentUuid The UUID assigned to the loading component. static AZStd::shared_ptr LoadSceneFromVerifiedPath(const AZStd::string& assetFilePath, - const Uuid&sourceGuid, RequestingApplication requester); + const Uuid& sourceGuid, RequestingApplication requester, const Uuid& loadingComponentUuid); //! Utility function to determine if a given file path points to a scene manifest file (.assetinfo). //! @param filePath A relative or absolute path to the file to check. diff --git a/Code/Tools/SceneAPI/SceneCore/Tests/Events/AssetImporterRequestTests.cpp b/Code/Tools/SceneAPI/SceneCore/Tests/Events/AssetImporterRequestTests.cpp index a610cee5a4..42ddc0139c 100644 --- a/Code/Tools/SceneAPI/SceneCore/Tests/Events/AssetImporterRequestTests.cpp +++ b/Code/Tools/SceneAPI/SceneCore/Tests/Events/AssetImporterRequestTests.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include namespace AZ @@ -184,7 +185,7 @@ namespace AZ EXPECT_CALL(handler, UpdateManifest(_, _, _)).Times(0); AZStd::shared_ptr result = - AssetImportRequest::LoadSceneFromVerifiedPath("test.asset", m_testId, Events::AssetImportRequest::RequestingApplication::Generic); + AssetImportRequest::LoadSceneFromVerifiedPath("test.asset", m_testId, Events::AssetImportRequest::RequestingApplication::Generic, SceneCore::LoadingComponent::TYPEINFO_Uuid()); EXPECT_EQ(nullptr, result); } @@ -207,7 +208,7 @@ namespace AZ EXPECT_CALL(handler, UpdateManifest(_, _, _)).Times(0); AZStd::shared_ptr result = - AssetImportRequest::LoadSceneFromVerifiedPath("test.asset", m_testId, Events::AssetImportRequest::RequestingApplication::Generic); + AssetImportRequest::LoadSceneFromVerifiedPath("test.asset", m_testId, Events::AssetImportRequest::RequestingApplication::Generic, SceneCore::LoadingComponent::TYPEINFO_Uuid()); EXPECT_EQ(nullptr, result); } @@ -230,7 +231,7 @@ namespace AZ EXPECT_CALL(handler, UpdateManifest(_, _, _)).Times(0); AZStd::shared_ptr result = - AssetImportRequest::LoadSceneFromVerifiedPath("test.asset", m_testId, Events::AssetImportRequest::RequestingApplication::Generic); + AssetImportRequest::LoadSceneFromVerifiedPath("test.asset", m_testId, Events::AssetImportRequest::RequestingApplication::Generic, SceneCore::LoadingComponent::TYPEINFO_Uuid()); EXPECT_EQ(nullptr, result); } @@ -253,7 +254,7 @@ namespace AZ EXPECT_CALL(handler, UpdateManifest(_, _, _)).Times(0); AZStd::shared_ptr result = - AssetImportRequest::LoadSceneFromVerifiedPath("test.asset", m_testId, Events::AssetImportRequest::RequestingApplication::Generic); + AssetImportRequest::LoadSceneFromVerifiedPath("test.asset", m_testId, Events::AssetImportRequest::RequestingApplication::Generic, SceneCore::LoadingComponent::TYPEINFO_Uuid()); EXPECT_EQ(nullptr, result); } @@ -285,7 +286,7 @@ namespace AZ EXPECT_CALL(manifestHandler, UpdateManifest(_, _, _)).Times(1); AZStd::shared_ptr result = - AssetImportRequest::LoadSceneFromVerifiedPath("test.asset", m_testId, Events::AssetImportRequest::RequestingApplication::Generic); + AssetImportRequest::LoadSceneFromVerifiedPath("test.asset", m_testId, Events::AssetImportRequest::RequestingApplication::Generic, SceneCore::LoadingComponent::TYPEINFO_Uuid()); EXPECT_EQ(nullptr, result); } @@ -313,7 +314,7 @@ namespace AZ EXPECT_CALL(manifestHandler, UpdateManifest(_, _, _)).Times(1); AZStd::shared_ptr result = - AssetImportRequest::LoadSceneFromVerifiedPath("test.asset", m_testId, Events::AssetImportRequest::RequestingApplication::Generic); + AssetImportRequest::LoadSceneFromVerifiedPath("test.asset", m_testId, Events::AssetImportRequest::RequestingApplication::Generic, SceneCore::LoadingComponent::TYPEINFO_Uuid()); EXPECT_NE(nullptr, result); } diff --git a/Gems/SceneProcessing/Code/Source/SceneBuilder/SceneSerializationHandler.cpp b/Gems/SceneProcessing/Code/Source/SceneBuilder/SceneSerializationHandler.cpp index feab5863e6..0e3f86471c 100644 --- a/Gems/SceneProcessing/Code/Source/SceneBuilder/SceneSerializationHandler.cpp +++ b/Gems/SceneProcessing/Code/Source/SceneBuilder/SceneSerializationHandler.cpp @@ -19,6 +19,7 @@ #include #include #include +#include namespace SceneBuilder { @@ -79,8 +80,9 @@ namespace SceneBuilder return nullptr; } - AZStd::shared_ptr scene = - AssetImportRequest::LoadSceneFromVerifiedPath(filePath, sceneSourceGuid, AssetImportRequest::RequestingApplication::AssetProcessor); + AZStd::shared_ptr scene = AssetImportRequest::LoadSceneFromVerifiedPath( + filePath, sceneSourceGuid, AssetImportRequest::RequestingApplication::AssetProcessor, + AZ::SceneAPI::SceneCore::LoadingComponent::TYPEINFO_Uuid()); if (!scene) { From b98a67e836c32bd7989e7b20d574e36af222ae21 Mon Sep 17 00:00:00 2001 From: AMZN-stankowi <4838196+AMZN-stankowi@users.noreply.github.com> Date: Tue, 17 Aug 2021 08:21:40 -0700 Subject: [PATCH 496/803] Better error reporting on mixing skinned and unskinned meshes. (#3158) Signed-off-by: stankowi <4838196+AMZN-stankowi@users.noreply.github.com> --- .../Model/ModelAssetBuilderComponent.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/ModelAssetBuilderComponent.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/ModelAssetBuilderComponent.cpp index fb8708fb88..8e54e5e90f 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/ModelAssetBuilderComponent.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/ModelAssetBuilderComponent.cpp @@ -1235,7 +1235,8 @@ namespace AZ // ProductMesh. That large buffer gets set on the LOD directly // rather than a Mesh in the LOD. ProductMeshContentAllocInfo lodBufferInfo; - + + bool isFirstMesh = true; for (const ProductMeshContent& mesh : lodMeshList) { if (lodBufferInfo.m_uvSetFloatCounts.size() < mesh.m_uvSets.size()) @@ -1347,6 +1348,14 @@ namespace AZ if (!mesh.m_skinJointIndices.empty() && !mesh.m_skinWeights.empty()) { + if (!isFirstMesh && lodBufferInfo.m_skinInfluencesCount == 0) + { + AZ_Error( + s_builderName, false, + "Attempting to merge a mix of static and skinned meshes, this will fail on buffer generation later. Mesh with " + "name %s is skinned, but previous meshes were not skinned.", + mesh.m_name.GetCStr()); + } AZ_Assert(mesh.m_skinJointIndices.size() == mesh.m_skinWeights.size(), "Number of skin influence joint indices (%d) should match the number of weights (%d).", mesh.m_skinJointIndices.size(), mesh.m_skinWeights.size()); @@ -1363,6 +1372,11 @@ namespace AZ lodBufferInfo.m_skinInfluencesCount += numNewSkinInfluences; } + else if (lodBufferInfo.m_skinInfluencesCount > 0) + { + AZ_Error(s_builderName, false, "Attempting to merge a mix of static and skinned meshes, this will fail on buffer generation later. Mesh with name %s is not skinned, but previous meshes were skinned.", + mesh.m_name.GetCStr()); + } if (!mesh.m_morphTargetVertexData.empty()) { @@ -1375,6 +1389,7 @@ namespace AZ } meshViews.emplace_back(AZStd::move(meshView)); + isFirstMesh = false; } // Now that we have the views settled, we can just merge the mesh From b1444828ff96ce666d76cd3e0dfa2c1d1cfce1df Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Tue, 17 Aug 2021 08:48:40 -0700 Subject: [PATCH 497/803] make Jenkins happy Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Gems/LyShine/Code/Source/Animation/AnimTrack.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/LyShine/Code/Source/Animation/AnimTrack.h b/Gems/LyShine/Code/Source/Animation/AnimTrack.h index 21a78ae6a1..df0ae3a805 100644 --- a/Gems/LyShine/Code/Source/Animation/AnimTrack.h +++ b/Gems/LyShine/Code/Source/Animation/AnimTrack.h @@ -221,7 +221,7 @@ protected: float m_lastTime; int m_flags; - constexpr unsigned int InvalidKey = 0x7FFFFFFF; + static constexpr unsigned int InvalidKey = 0x7FFFFFFF; UiAnimParamData m_componentParamData; From 7f603c59ad99eece18a62dddd6e83dc1ee1130e9 Mon Sep 17 00:00:00 2001 From: hultonha <82228511+hultonha@users.noreply.github.com> Date: Tue, 17 Aug 2021 17:09:17 +0100 Subject: [PATCH 498/803] Fix for events that should have been consumed by manipulators (#3108) * fix for events that should have been consumed by manipulators making their way to the main viewport handler Signed-off-by: hultonha * add missing include for SANDBOX_API macro Signed-off-by: hultonha * add dependency on Qt::Test for AzToolsFrameworkTestCommon Signed-off-by: hultonha * fix order of buttons passed to QMouseEvent Signed-off-by: hultonha * potential fix for vtable error on linux Signed-off-by: hultonha * potential fix for vtable error on linux again Signed-off-by: hultonha --- Code/Editor/CMakeLists.txt | 4 + .../test_ViewportManipulatorController.cpp | 152 ++++++++++++++++++ Code/Editor/ViewportManipulatorController.cpp | 23 ++- Code/Editor/ViewportManipulatorController.h | 20 ++- Code/Editor/editor_lib_test_files.cmake | 1 + .../Input/QtEventToAzInputManager.cpp | 49 +++--- .../Input/QtEventToAzInputManager.h | 4 - .../UnitTest/AzToolsFrameworkTestHelpers.cpp | 29 ++++ .../UnitTest/AzToolsFrameworkTestHelpers.h | 15 ++ .../Viewport/ViewportMessages.h | 2 +- .../Framework/AzToolsFramework/CMakeLists.txt | 4 +- .../AzToolsFramework/Tests/SpinBoxTests.cpp | 25 --- 12 files changed, 253 insertions(+), 75 deletions(-) create mode 100644 Code/Editor/Lib/Tests/test_ViewportManipulatorController.cpp diff --git a/Code/Editor/CMakeLists.txt b/Code/Editor/CMakeLists.txt index fca16a2093..9baa83179b 100644 --- a/Code/Editor/CMakeLists.txt +++ b/Code/Editor/CMakeLists.txt @@ -238,9 +238,13 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) 3rdParty::Qt::Core 3rdParty::Qt::Gui 3rdParty::Qt::Widgets + 3rdParty::Qt::Test Legacy::CryCommon AZ::AzToolsFramework + AZ::AzToolsFramework.Tests + AZ::AzToolsFrameworkTestCommon Legacy::EditorLib + Gem::AtomToolsFramework.Static RUNTIME_DEPENDENCIES Gem::LmbrCentral ) diff --git a/Code/Editor/Lib/Tests/test_ViewportManipulatorController.cpp b/Code/Editor/Lib/Tests/test_ViewportManipulatorController.cpp new file mode 100644 index 0000000000..a2a7617083 --- /dev/null +++ b/Code/Editor/Lib/Tests/test_ViewportManipulatorController.cpp @@ -0,0 +1,152 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include +#include +#include +#include +#include + +namespace UnitTest +{ + using AzToolsFramework::ViewportInteraction::MouseInteractionEvent; + + class EditorInteractionViewportSelectionFake : public AzToolsFramework::EditorInteractionSystemViewportSelectionRequestBus::Handler + { + public: + void Connect(); + void Disconnect(); + + // EditorInteractionSystemViewportSelectionRequestBus overrides ... + void SetHandler(const AzToolsFramework::ViewportSelectionRequestsBuilderFn& interactionRequestsBuilder); + void SetDefaultHandler(); + bool InternalHandleMouseViewportInteraction(const MouseInteractionEvent& mouseInteraction); + bool InternalHandleMouseManipulatorInteraction(const MouseInteractionEvent& mouseInteraction); + + AZStd::function m_internalHandleMouseViewportInteraction; + AZStd::function m_internalHandleMouseManipulatorInteraction; + }; + + void EditorInteractionViewportSelectionFake::Connect() + { + AzToolsFramework::EditorInteractionSystemViewportSelectionRequestBus::Handler::BusConnect(AzToolsFramework::GetEntityContextId()); + } + + void EditorInteractionViewportSelectionFake::Disconnect() + { + AzToolsFramework::EditorInteractionSystemViewportSelectionRequestBus::Handler::BusDisconnect(); + } + + void EditorInteractionViewportSelectionFake::SetHandler( + [[maybe_unused]] const AzToolsFramework::ViewportSelectionRequestsBuilderFn& interactionRequestsBuilder) + { + // noop + } + + void EditorInteractionViewportSelectionFake::SetDefaultHandler() + { + // noop + } + + bool EditorInteractionViewportSelectionFake::InternalHandleMouseViewportInteraction(const MouseInteractionEvent& mouseInteraction) + { + if (m_internalHandleMouseViewportInteraction) + { + return m_internalHandleMouseViewportInteraction(mouseInteraction); + } + + return false; + } + + bool EditorInteractionViewportSelectionFake::InternalHandleMouseManipulatorInteraction(const MouseInteractionEvent& mouseInteraction) + { + if (m_internalHandleMouseManipulatorInteraction) + { + return m_internalHandleMouseManipulatorInteraction(mouseInteraction); + } + + return false; + } + + class ViewportManipulatorControllerFixture : public AllocatorsTestFixture + { + public: + static const AzFramework::ViewportId TestViewportId = AzFramework::ViewportId(0); + + void SetUp() override + { + AllocatorsTestFixture::SetUp(); + + m_rootWidget = AZStd::make_unique(); + m_rootWidget->setFixedSize(QSize(100, 100)); + + m_controllerList = AZStd::make_shared(); + m_controllerList->RegisterViewportContext(TestViewportId); + + m_inputChannelMapper = AZStd::make_unique(m_rootWidget.get(), TestViewportId); + } + + void TearDown() + { + m_inputChannelMapper.reset(); + + m_controllerList->UnregisterViewportContext(TestViewportId); + m_controllerList.reset(); + m_rootWidget.reset(); + + AllocatorsTestFixture::TearDown(); + } + + AZStd::unique_ptr m_rootWidget; + AzFramework::ViewportControllerListPtr m_controllerList; + AZStd::unique_ptr m_inputChannelMapper; + }; + + TEST_F(ViewportManipulatorControllerFixture, An_event_is_not_propagated_to_the_viewport_when_a_manipulator_handles_it_first) + { + // forward input events to our controller list + QObject::connect( + m_inputChannelMapper.get(), &AzToolsFramework::QtEventToAzInputMapper::InputChannelUpdated, m_rootWidget.get(), + [this](const AzFramework::InputChannel* inputChannel, [[maybe_unused]] QEvent* event) + { + m_controllerList->HandleInputChannelEvent( + AzFramework::ViewportControllerInputEvent{ TestViewportId, nullptr, *inputChannel }); + }); + + EditorInteractionViewportSelectionFake editorInteractionViewportFake; + editorInteractionViewportFake.m_internalHandleMouseManipulatorInteraction = [](const MouseInteractionEvent&) + { + // report the event was handled (manipulator was interacted with) + return true; + }; + + bool viewportInteractionCalled = false; + editorInteractionViewportFake.m_internalHandleMouseViewportInteraction = [&viewportInteractionCalled](const MouseInteractionEvent&) + { + // we should not call this as the manipulator will have consumed this event + viewportInteractionCalled = true; + return true; + }; + + editorInteractionViewportFake.Connect(); + + m_controllerList->Add(AZStd::make_shared()); + + // simulate a press and move + MousePressAndMove(m_rootWidget.get(), QPoint(10, 10), QPoint(10, 10), Qt::MouseButton::LeftButton); + MouseMove(m_rootWidget.get(), QPoint(20, 20), QPoint(10, 10), Qt::MouseButton::LeftButton); + MouseMove(m_rootWidget.get(), QPoint(30, 30), QPoint(0, 0), Qt::MouseButton::LeftButton); + QTest::mouseRelease(m_rootWidget.get(), Qt::MouseButton::LeftButton, Qt::KeyboardModifier::NoModifier, QPoint(30, 30)); + + // ensure the viewport did not receive the event when it was intercepted first by the manipulator + EXPECT_FALSE(viewportInteractionCalled); + + editorInteractionViewportFake.Disconnect(); + } +} // namespace UnitTest diff --git a/Code/Editor/ViewportManipulatorController.cpp b/Code/Editor/ViewportManipulatorController.cpp index 0b519f0787..5282af009f 100644 --- a/Code/Editor/ViewportManipulatorController.cpp +++ b/Code/Editor/ViewportManipulatorController.cpp @@ -28,6 +28,8 @@ namespace SandboxEditor { } + ViewportManipulatorControllerInstance::~ViewportManipulatorControllerInstance() = default; + AzToolsFramework::ViewportInteraction::MouseButton ViewportManipulatorControllerInstance::GetMouseButton( const AzFramework::InputChannel& inputChannel) { @@ -103,14 +105,21 @@ namespace SandboxEditor // Cache the ray trace results when doing manipulator interaction checks, no need to recalculate after if (event.m_priority == ManipulatorPriority) { - AzFramework::ScreenPoint screenPosition = AzFramework::ScreenPoint(0, 0); - ViewportMouseCursorRequestBus::EventResult( - screenPosition, GetViewportId(), &ViewportMouseCursorRequestBus::Events::ViewportCursorScreenPosition); + const auto* position = event.m_inputChannel.GetCustomData(); + AZ_Assert(position, "Expected PositionData2D but found nullptr"); - m_mouseInteraction.m_mousePick.m_screenCoordinates = screenPosition; + AzFramework::WindowSize windowSize; + AzFramework::WindowRequestBus::EventResult( + windowSize, event.m_windowHandle, &AzFramework::WindowRequestBus::Events::GetClientAreaSize); + + auto screenPoint = AzFramework::ScreenPoint( + position->m_normalizedPosition.GetX() * windowSize.m_width, + position->m_normalizedPosition.GetY() * windowSize.m_height); + + m_mouseInteraction.m_mousePick.m_screenCoordinates = screenPoint; AZStd::optional ray; ViewportInteractionRequestBus::EventResult( - ray, GetViewportId(), &ViewportInteractionRequestBus::Events::ViewportScreenToWorldRay, screenPosition); + ray, GetViewportId(), &ViewportInteractionRequestBus::Events::ViewportScreenToWorldRay, screenPoint); if (ray.has_value()) { @@ -118,6 +127,7 @@ namespace SandboxEditor m_mouseInteraction.m_mousePick.m_rayDirection = ray.value().direction; } } + eventType = MouseEvent::Move; } else if (auto mouseButton = GetMouseButton(event.m_inputChannel); mouseButton != MouseButton::None) @@ -217,8 +227,7 @@ namespace SandboxEditor interactionHandled, AzToolsFramework::GetEntityContextId(), targetInteractionEvent, mouseInteractionEvent); } - // Only filter button/key press events, not release events - return interactionHandled && event.m_inputChannel.IsActive(); + return interactionHandled; } void ViewportManipulatorControllerInstance::ResetInputChannels() diff --git a/Code/Editor/ViewportManipulatorController.h b/Code/Editor/ViewportManipulatorController.h index 968b6745c1..d551eb3647 100644 --- a/Code/Editor/ViewportManipulatorController.h +++ b/Code/Editor/ViewportManipulatorController.h @@ -8,25 +8,29 @@ #pragma once -#include -#include #include +#include +#include #include +#include + namespace SandboxEditor { class ViewportManipulatorControllerInstance; - using ViewportManipulatorController = AzFramework::MultiViewportController; + using ViewportManipulatorController = AzFramework:: + MultiViewportController; class ViewportManipulatorControllerInstance final : public AzFramework::MultiViewportControllerInstanceInterface { public: - explicit ViewportManipulatorControllerInstance(AzFramework::ViewportId viewport, ViewportManipulatorController* controller); + SANDBOX_API ViewportManipulatorControllerInstance(AzFramework::ViewportId viewport, ViewportManipulatorController* controller); + SANDBOX_API ~ViewportManipulatorControllerInstance(); - bool HandleInputChannelEvent(const AzFramework::ViewportControllerInputEvent& event) override; - void ResetInputChannels() override; - void UpdateViewport(const AzFramework::ViewportControllerUpdateEvent& event) override; + SANDBOX_API bool HandleInputChannelEvent(const AzFramework::ViewportControllerInputEvent& event) override; + SANDBOX_API void ResetInputChannels() override; + SANDBOX_API void UpdateViewport(const AzFramework::ViewportControllerUpdateEvent& event) override; private: bool IsDoubleClick(AzToolsFramework::ViewportInteraction::MouseButton) const; @@ -39,4 +43,4 @@ namespace SandboxEditor AZStd::unordered_map m_pendingDoubleClicks; AZ::ScriptTimePoint m_curTime; }; -} //namespace SandboxEditor +} // namespace SandboxEditor diff --git a/Code/Editor/editor_lib_test_files.cmake b/Code/Editor/editor_lib_test_files.cmake index c67e70ddbd..49f707b1f6 100644 --- a/Code/Editor/editor_lib_test_files.cmake +++ b/Code/Editor/editor_lib_test_files.cmake @@ -20,6 +20,7 @@ set(FILES Lib/Tests/test_ViewPanePythonBindings.cpp Lib/Tests/test_ViewportTitleDlgPythonBindings.cpp Lib/Tests/test_DisplaySettingsPythonBindings.cpp + Lib/Tests/test_ViewportManipulatorController.cpp DisplaySettingsPythonFuncs.cpp DisplaySettingsPythonFuncs.h ) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Input/QtEventToAzInputManager.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Input/QtEventToAzInputManager.cpp index f8665d583e..b7776238ba 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Input/QtEventToAzInputManager.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Input/QtEventToAzInputManager.cpp @@ -162,7 +162,6 @@ namespace AzToolsFramework : QObject(sourceWidget) , m_sourceWidget(sourceWidget) , m_keyboardModifiers(AZStd::make_shared()) - , m_cursorPosition(AZStd::make_shared()) { InitializeKeyMappings(); InitializeMouseButtonMappings(); @@ -230,24 +229,17 @@ namespace AzToolsFramework return false; } - // Because there's no "end" to mouse movement and wheel events, we reset mouse movement channels that have been opened - // during the next processed non-mouse event. - if (m_mouseChannelsNeedUpdate && event->type() != QEvent::Type::MouseMove && event->type() != QEvent::Type::Wheel) - { - m_cursorPosition->m_normalizedPositionDelta = AZ::Vector2::CreateZero(); - ProcessPendingMouseEvents(); - m_mouseChannelsNeedUpdate = false; - } + const auto eventType = event->type(); // Only accept mouse & key release events that originate from an object that is not our target widget, // as we don't want to erroneously intercept user input meant for another component. - if (object != m_sourceWidget && event->type() != QEvent::Type::KeyRelease && event->type() != QEvent::Type::MouseButtonRelease) + if (object != m_sourceWidget && eventType != QEvent::Type::KeyRelease && eventType != QEvent::Type::MouseButtonRelease) { return false; } // If our focus changes, go ahead and reset all input devices. - if (event->type() == QEvent::FocusIn || event->type() == QEvent::FocusOut) + if (eventType == QEvent::FocusIn || eventType == QEvent::FocusOut) { HandleFocusChange(event); } @@ -255,27 +247,28 @@ namespace AzToolsFramework // ShortcutOverride is used in lieu of KeyPress for high priority input channels like Alt // that need to be accepted and stopped before they bubble up and cause unintended behavior. else if ( - event->type() == QEvent::Type::KeyPress || event->type() == QEvent::Type::KeyRelease || - event->type() == QEvent::Type::ShortcutOverride) + eventType == QEvent::Type::KeyPress || eventType == QEvent::Type::KeyRelease || eventType == QEvent::Type::ShortcutOverride) { QKeyEvent* keyEvent = static_cast(event); HandleKeyEvent(keyEvent); } // Map mouse events to input channels. - else if (event->type() == QEvent::Type::MouseButtonPress || event->type() == QEvent::Type::MouseButtonRelease || event->type() == QEvent::Type::MouseButtonDblClick) + else if ( + eventType == QEvent::Type::MouseButtonPress || eventType == QEvent::Type::MouseButtonRelease || + eventType == QEvent::Type::MouseButtonDblClick) { QMouseEvent* mouseEvent = static_cast(event); HandleMouseButtonEvent(mouseEvent); } // Map mouse movement to the movement input channels. // This includes SystemCursorPosition alongside Movement::X and Movement::Y. - else if (event->type() == QEvent::Type::MouseMove) + else if (eventType == QEvent::Type::MouseMove) { QMouseEvent* mouseEvent = static_cast(event); HandleMouseMoveEvent(mouseEvent); } // Map wheel events to the mouse Z movement channel. - else if (event->type() == QEvent::Type::Wheel) + else if (eventType == QEvent::Type::Wheel) { QWheelEvent* wheelEvent = static_cast(event); HandleWheelEvent(wheelEvent); @@ -303,14 +296,16 @@ namespace AzToolsFramework auto mouseWheelChannel = GetInputChannel(AzFramework::InputDeviceMouse::Movement::Z); - systemCursorChannel->ProcessRawInputEvent(m_cursorPosition->m_normalizedPositionDelta.GetLength()); + systemCursorChannel->ProcessRawInputEvent(m_mouseDevice->m_cursorPositionData2D->m_normalizedPositionDelta.GetLength()); // Generate movement events based on the pixel delta divided by the DPI scaling factor, to calculate a rough approximation // of cursor movement velocity. movementXChannel->ProcessRawInputEvent( - m_cursorPosition->m_normalizedPositionDelta.GetX() * aznumeric_cast(m_sourceWidget->width()) / m_sourceWidget->devicePixelRatioF()); + m_mouseDevice->m_cursorPositionData2D->m_normalizedPositionDelta.GetX() * aznumeric_cast(m_sourceWidget->width()) / + m_sourceWidget->devicePixelRatioF()); movementYChannel->ProcessRawInputEvent( - m_cursorPosition->m_normalizedPositionDelta.GetY() * aznumeric_cast(m_sourceWidget->height()) / m_sourceWidget->devicePixelRatioF()); - mouseWheelChannel->ProcessRawInputEvent(0.f); + m_mouseDevice->m_cursorPositionData2D->m_normalizedPositionDelta.GetY() * aznumeric_cast(m_sourceWidget->height()) / + m_sourceWidget->devicePixelRatioF()); + mouseWheelChannel->ProcessRawInputEvent(0.0f); NotifyUpdateChannelIfNotIdle(systemCursorChannel, nullptr); NotifyUpdateChannelIfNotIdle(movementXChannel, nullptr); @@ -358,14 +353,13 @@ namespace AzToolsFramework void QtEventToAzInputMapper::HandleMouseMoveEvent(QMouseEvent* mouseEvent) { - AZ::Vector2 lastCursorPosition = m_cursorPosition->m_normalizedPosition; + AZ::Vector2 lastCursorPosition = m_mouseDevice->m_cursorPositionData2D->m_normalizedPosition; const QPoint mousePos = mouseEvent->pos(); const AZ::Vector2 normalizedPosition = WidgetPositionToNormalizedPosition(mousePos); - m_cursorPosition->m_normalizedPositionDelta = normalizedPosition - m_cursorPosition->m_normalizedPosition; - m_cursorPosition->m_normalizedPosition = normalizedPosition; + m_mouseDevice->m_cursorPositionData2D->m_normalizedPositionDelta = normalizedPosition - m_mouseDevice->m_cursorPositionData2D->m_normalizedPosition; + m_mouseDevice->m_cursorPositionData2D->m_normalizedPosition = normalizedPosition; ProcessPendingMouseEvents(); - m_mouseChannelsNeedUpdate = true; if (m_capturingCursor) { @@ -376,7 +370,7 @@ namespace AzToolsFramework // Even though we just set the cursor position, there are edge cases such as remote desktop that will leave // the cursor position unchanged. For safety, we re-cache our last cursor position for delta generation. QPoint actualWidgetPosition = m_sourceWidget->mapFromGlobal(QCursor::pos()); - m_cursorPosition->m_normalizedPosition = WidgetPositionToNormalizedPosition(actualWidgetPosition); + m_mouseDevice->m_cursorPositionData2D->m_normalizedPosition = WidgetPositionToNormalizedPosition(actualWidgetPosition); } } @@ -427,21 +421,18 @@ namespace AzToolsFramework } cursorZChannel->ProcessRawInputEvent(aznumeric_cast(wheelAngle)); NotifyUpdateChannelIfNotIdle(cursorZChannel, wheelEvent); - m_mouseChannelsNeedUpdate = true; } void QtEventToAzInputMapper::HandleFocusChange(QEvent* event) { for (auto& channelData : m_channels) { - // If resetting the input device changed the channel state, submit it to the mapped channel list - // for processing. + // If resetting the input device changed the channel state, submit it to the mapped channel list for processing. if (channelData.second->IsActive()) { channelData.second->UpdateState(false); NotifyUpdateChannelIfNotIdle(channelData.second, event); } } - m_mouseChannelsNeedUpdate = false; } } // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Input/QtEventToAzInputManager.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Input/QtEventToAzInputManager.h index 919d8fcc2a..0187cb2e5b 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Input/QtEventToAzInputManager.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Input/QtEventToAzInputManager.h @@ -138,8 +138,6 @@ namespace AzToolsFramework // The current keyboard modifier state used by our synthetic key input channels. AZStd::shared_ptr m_keyboardModifiers; - // The current normalized cursor position used by our synthetic system cursor event. - AZStd::shared_ptr m_cursorPosition; // A lookup table for Qt key -> AZ input channel. AZStd::unordered_map m_keyMappings; // A lookup table for Qt mouse button -> AZ input channel. @@ -152,8 +150,6 @@ namespace AzToolsFramework AZStd::unordered_map m_channels; // The source widget to map events from, used to calculate the relative mouse position within the widget bounds. QWidget* m_sourceWidget; - // Flags when mouse movement channels have been opened and may need to be closed (as there are no movement ended events). - bool m_mouseChannelsNeedUpdate = false; // Flags whether or not Qt events should currently be processed. bool m_enabled = true; // Flags whether or not the cursor is being constrained to the source widget (for invisible mouse movement). diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.cpp index 1bec929223..6608e87784 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.cpp @@ -27,6 +27,35 @@ using namespace AzToolsFramework; namespace UnitTest { + void MousePressAndMove( + QWidget* widget, const QPoint& initialPositionWidget, const QPoint& mouseDelta, const Qt::MouseButton mouseButton) + { + QPoint position = widget->mapToGlobal(initialPositionWidget); + QTest::mousePress(widget, mouseButton, Qt::NoModifier, position); + + MouseMove(widget, initialPositionWidget, mouseDelta, mouseButton); + } + + // Note: There are a series of bugs in Qt that appear to be preventing mouseMove events + // firing when sent through the QTest framework. This is a work around for our version + // of Qt. In future this can hopefully be simplified. See ^1 for workaround. + // More info: Issues with mouse move in Qt + // - https://bugreports.qt.io/browse/QTBUG-5232 + // - https://bugreports.qt.io/browse/QTBUG-69414 + // - https://lists.qt-project.org/pipermail/development/2019-July/036873.html + void MouseMove(QWidget* widget, const QPoint& initialPositionWidget, const QPoint& mouseDelta, const Qt::MouseButton mouseButton) + { + QPoint nextPosition = widget->mapToGlobal(initialPositionWidget + mouseDelta); + + // ^1 To ensure a mouse move event is fired we must call the test mouse move function + // and also send a mouse move event that matches. Each on their own do not appear to + // work - please see the links above for more context. + QTest::mouseMove(widget, nextPosition); + QMouseEvent mouseMoveEvent( + QEvent::MouseMove, QPointF(nextPosition), QPointF(nextPosition), Qt::NoButton, mouseButton, Qt::NoModifier); + QApplication::sendEvent(widget, &mouseMoveEvent); + } + bool TestWidget::eventFilter(QObject* watched, QEvent* event) { AZ_UNUSED(watched); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h index 3c413fd21e..b3a660d0f2 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h @@ -59,6 +59,21 @@ namespace UnitTest { constexpr AZStd::string_view prefabSystemSetting = "/Amazon/Preferences/EnablePrefabSystem"; + /// Performs a mouse press and move event on the provided widget. + /// @param widget The widget to perform the mouse press and move on. + /// @param initialPositionWidget The position of the mouse relative to the widget (will be remapped to a global position internally). + /// @param mouseDelta How far to move the mouse. + /// @param mouseButton The button to be used during the press and move. + void MousePressAndMove( + QWidget* widget, const QPoint& initialPositionWidget, const QPoint& mouseDelta, Qt::MouseButton mouseButton = Qt::LeftButton); + + /// Performs a mouse move event on the provided widget. + /// @param widget The widget to perform the mouse move on. + /// @param initialPositionWidget The position of the mouse relative to the widget (will be remapped to a global position internally). + /// @param mouseDelta How far to move the mouse (note: mouseDelta may be zero and the mouse will only be moved to initialPosition). + /// @param mouseButton The button to be held during the move. + void MouseMove(QWidget* widget, const QPoint& initialPosition, const QPoint& mouseDelta, Qt::MouseButton mouseButton = Qt::NoButton); + /// Test widget to store QActions generated by EditorTransformComponentSelection. class TestWidget : public QWidget { diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.h index ef1dfb0414..543d5fb3a5 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.h @@ -313,7 +313,7 @@ namespace AzToolsFramework //! Utility function to return EntityContextId. inline AzFramework::EntityContextId GetEntityContextId() { - AzFramework::EntityContextId entityContextId; + auto entityContextId = AzFramework::EntityContextId::CreateNull(); EditorEntityContextRequestBus::BroadcastResult(entityContextId, &EditorEntityContextRequests::GetEditorEntityContextId); return entityContextId; diff --git a/Code/Framework/AzToolsFramework/CMakeLists.txt b/Code/Framework/AzToolsFramework/CMakeLists.txt index 62f4f43d93..4ee329bd93 100644 --- a/Code/Framework/AzToolsFramework/CMakeLists.txt +++ b/Code/Framework/AzToolsFramework/CMakeLists.txt @@ -60,6 +60,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) PUBLIC AZ::AzTestShared PRIVATE + 3rdParty::Qt::Test 3rdParty::googletest::GMock 3rdParty::GoogleBenchmark AZ::AzToolsFramework @@ -76,8 +77,9 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) PRIVATE Tests BUILD_DEPENDENCIES - PRIVATE + PUBLIC AZ::AzTestShared + PRIVATE 3rdParty::Qt::Test AZ::AzFrameworkTestShared AZ::AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/Tests/SpinBoxTests.cpp b/Code/Framework/AzToolsFramework/Tests/SpinBoxTests.cpp index a88cb68638..2d524cbcf4 100644 --- a/Code/Framework/AzToolsFramework/Tests/SpinBoxTests.cpp +++ b/Code/Framework/AzToolsFramework/Tests/SpinBoxTests.cpp @@ -107,31 +107,6 @@ namespace UnitTest EXPECT_THAT(m_doubleSpinBoxWithLineEdit, Ne(nullptr)); } - // Note: There are a series of bugs in Qt that appear to be preventing mouseMove events - // firing when sent through the QTest framework. This is a work around for our version - // of Qt. In future this can hopefully be simplified. See ^1 for workaround. - // More info: Issues with mouse move in Qt - // - https://bugreports.qt.io/browse/QTBUG-5232 - // - https://bugreports.qt.io/browse/QTBUG-69414 - // - https://lists.qt-project.org/pipermail/development/2019-July/036873.html - void MousePressAndMove( - QWidget* widget, const QPoint& widgetScreenPosition, const QPoint& mouseDelta) - { - QPoint position = widget->mapToGlobal(widgetScreenPosition); - QPoint nextPosition = widget->mapToGlobal(widgetScreenPosition + mouseDelta); - - QTest::mousePress(widget, Qt::LeftButton, Qt::NoModifier, position); - - // ^1 To ensure a mouse move event is fired we must call the test mouse move function - // and also send a mouse move event that matches. Each on their own do not appear to - // work - please see the links above for more context. - QTest::mouseMove(widget, nextPosition); - QMouseEvent mouseMoveEvent( - QEvent::MouseMove, QPointF(nextPosition), QPointF(nextPosition), - Qt::NoButton, Qt::LeftButton, Qt::NoModifier); - QApplication::sendEvent(widget, &mouseMoveEvent); - } - TEST_F(SpinBoxFixture, SpinBoxMousePressAndMoveRightScrollsValue) { m_doubleSpinBox->setValue(10.0); From eb6569357b582882e4c9e9f4ed93eb1a13ac0391 Mon Sep 17 00:00:00 2001 From: jackalbe <23512001+jackalbe@users.noreply.github.com> Date: Tue, 17 Aug 2021 11:38:10 -0500 Subject: [PATCH 499/803] {SPEC7767} Fix for PythonAssetBuilding auto tests (#3089) Fix for PythonAssetBuilding auto tests by updating the logic plus the names of the output models fix an access violation for auto complete in the console Signed-off-by: Jackson <23512001+jackalbe@users.noreply.github.com> --- .../PythonAssetBuilder/AssetBuilder_test.py | 16 +++++++------- .../AssetBuilder_test_case.py | 22 +++++++++---------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/AssetBuilder_test.py b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/AssetBuilder_test.py index 1fe60e3707..45e633a979 100644 --- a/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/AssetBuilder_test.py +++ b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/AssetBuilder_test.py @@ -27,19 +27,19 @@ class TestPythonAssetProcessing(object): unexpected_lines = [] expected_lines = [ 'Mock asset exists', - 'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_z_positive.azmodel) found', - 'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_z_negative.azmodel) found', - 'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_y_positive.azmodel) found', - 'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_y_negative.azmodel) found', - 'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_x_positive.azmodel) found', - 'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_x_negative.azmodel) found', - 'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_center.azmodel) found' + 'AssetId found for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_z_positive_1.azmodel) found', + 'AssetId found for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_z_negative_1.azmodel) found', + 'AssetId found for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_y_positive_1.azmodel) found', + 'AssetId found for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_y_negative_1.azmodel) found', + 'AssetId found for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_x_positive_1.azmodel) found', + 'AssetId found for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_x_negative_1.azmodel) found', + 'AssetId found for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_center_1.azmodel) found' ] timeout = 180 halt_on_unexpected = False test_directory = os.path.join(os.path.dirname(__file__)) testFile = os.path.join(test_directory, 'AssetBuilder_test_case.py') - editor.args.extend(['-NullRenderer', "--skipWelcomeScreenDialog", "--autotest_mode", "--runpythontest", testFile]) + editor.args.extend(['-NullRenderer', '-rhi=Null', "--skipWelcomeScreenDialog", "--autotest_mode", "--runpythontest", testFile]) with editor.start(): editorlog_file = os.path.join(editor.workspace.paths.project_log(), 'Editor.log') diff --git a/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/AssetBuilder_test_case.py b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/AssetBuilder_test_case.py index c1519a6fdb..8d418222ce 100644 --- a/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/AssetBuilder_test_case.py +++ b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/AssetBuilder_test_case.py @@ -29,21 +29,21 @@ if (assetIdString.endswith(':528cca58') is False): print ('Mock asset exists') # These tests detect if the geom_group.fbx file turns into a number of azmodel product assets -def test_azmodel_product(generatedModelAssetPath, expectedSubId): +def test_azmodel_product(generatedModelAssetPath): azModelAssetType = azlmbr.math.Uuid_CreateString('{2C7477B6-69C5-45BE-8163-BCD6A275B6D8}', 0) assetId = azlmbr.asset.AssetCatalogRequestBus(azlmbr.bus.Broadcast, 'GetAssetIdByPath', generatedModelAssetPath, azModelAssetType, False) assetIdString = assetId.to_string() - if (assetIdString.endswith(':' + expectedSubId) is False): - raise_and_stop(f'Asset at path {generatedModelAssetPath} has unexpected asset ID ({assetIdString}) for ({generatedModelAssetPath}), expected {expectedSubId}!') + if (assetId.is_valid()): + print(f'AssetId found for asset ({generatedModelAssetPath}) found') else: - print(f'Expected subId for asset ({generatedModelAssetPath}) found') + raise_and_stop(f'Asset at path {generatedModelAssetPath} has unexpected asset ID ({assetIdString})!') -test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_z_positive.azmodel', '1024be55') -test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_z_negative.azmodel', '1052c94e') -test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_y_positive.azmodel', '10130556') -test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_y_negative.azmodel', '1065724d') -test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_x_positive.azmodel', '10d16e68') -test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_x_negative.azmodel', '10a71973') -test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_center.azmodel', '10412075') +test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_z_positive_1.azmodel') +test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_z_negative_1.azmodel') +test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_y_positive_1.azmodel') +test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_y_negative_1.azmodel') +test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_x_positive_1.azmodel') +test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_x_negative_1.azmodel') +test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_center_1.azmodel') azlmbr.editor.EditorToolsApplicationRequestBus(azlmbr.bus.Broadcast, 'ExitNoPrompt') From 2b5f77683ce5b6843c9921bf52bdf116f243b93d Mon Sep 17 00:00:00 2001 From: galibzon <66021303+galibzon@users.noreply.github.com> Date: Tue, 17 Aug 2021 11:53:22 -0500 Subject: [PATCH 500/803] [ATOM-13679] ShaderAssetBuilder: Create UnitTest To Validate (#3096) * [ATOM-13679] ShaderAssetBuilder: Create UnitTest To Validate STDOUT Data Capture From MCPP azvsnprintf was being used improperly, in particular in windows if the data to print was larger than the local buffer in the stack, then azvsnprintf returns -1. Also azvsnprintf needs a +1 in buffer size to accomodate for the '\0' character at the end and that was not done. Added UnitTest to validate all cases: 1. Data to print is smaller than the local buffer. 2. Data to print is the same size as the local buffer. 3. Data to print is bigger than the local buffer. Signed-off-by: garrieta * Fix for MacOS & Linux, they require va_start to be called each time azvsnprintf is called Signed-off-by: garrieta --- .../Editor/CommonFiles/Preprocessor.cpp | 202 +++++++++--------- .../Source/Editor/CommonFiles/Preprocessor.h | 71 ++++++ .../Shader/Code/Tests/McppBinderTests.cpp | 92 ++++++++ ...om_asset_shader_builders_tests_files.cmake | 1 + 4 files changed, 262 insertions(+), 104 deletions(-) create mode 100644 Gems/Atom/Asset/Shader/Code/Tests/McppBinderTests.cpp diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/CommonFiles/Preprocessor.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/CommonFiles/Preprocessor.cpp index 945f9734ca..9c77ae6b35 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/CommonFiles/Preprocessor.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/CommonFiles/Preprocessor.cpp @@ -8,11 +8,6 @@ #include -#define MCPP_DLL_IMPORT 1 -#define MCPP_DONT_USE_SHORT_NAMES 1 -#include -#undef MCPP_DLL_IMPORT - #include #include @@ -31,8 +26,6 @@ #include -#include - namespace AZ { namespace ShaderBuilder @@ -83,124 +76,125 @@ namespace AZ } } - //! Binder helper to Matsui C-Pre-Processor library - class McppBinder + /////////////////////////////////////////////////////////////////////// + // McppBinder starts + bool McppBinder::StartPreprocessWithCommandLine(int argc, const char* argv[]) { - public: - McppBinder(PreprocessorData& out, bool plugERR) - : m_outputData(out), - m_plugERR(plugERR) + int errorCode = mcpp_lib_main(argc, argv); + // convert from std::ostringstring to AZStd::string + m_outputData.code = m_outStream.str().c_str(); + m_outputData.diagnostics = m_errStream.str().c_str(); + return errorCode == 0; + } + + int McppBinder::Putc_StaticHinge(int c, MCPP_OUTDEST od) + { + char asString[2] = { aznumeric_cast(c), 0 }; + return Fputs_StaticHinge(asString, od); + } + + int McppBinder::Fputs_StaticHinge(const char* s, MCPP_OUTDEST od) + { + if (!OkToLog(od)) { - // single live instance - s_mcppExclusiveProtection.lock(); - s_currentInstance = this; - SetupMcppCallbacks(); + return 0; } - ~McppBinder() + // chose the proper stream + auto& selectedStream = od == MCPP_OUT ? s_currentInstance->m_outStream : s_currentInstance->m_errStream; + auto tellBefore = selectedStream.tellp(); + // append that message to it + selectedStream << s; + return aznumeric_cast(selectedStream.tellp() - tellBefore); + } + + int McppBinder::Fprintf_StaticHinge(MCPP_OUTDEST od, const char* format, ...) + { + if (!OkToLog(od)) { - s_currentInstance = nullptr; - s_mcppExclusiveProtection.unlock(); + return 0; } + // run the formatting on stack memory first, in case it's enough + char localBuffer[DefaultFprintfBufferSize]; - bool StartPreprocessWithCommandLine(int argc, const char* argv[]) + va_list args; + + va_start(args, format); + int count = azvsnprintf(localBuffer, DefaultFprintfBufferSize, format, args); + va_end(args); + + char* result = localBuffer; + + // @result will be bound to @biggerData in case @localBuffer is not big enough. + std::unique_ptr biggerData; + // ">=" is the right comparison because in case count == bufferSize + // We will need an extra byte to accomodate the '\0' ending character. + if (count >= DefaultFprintfBufferSize) { - int errorCode = mcpp_lib_main(argc, argv); - // convert from std::ostringstring to AZStd::string - m_outputData.code = m_outStream.str().c_str(); - m_outputData.diagnostics = m_errStream.str().c_str(); - return errorCode == 0; - } - - private: - - // ====== C-API compatible "Static Hinges" (plain free functions) ====== - // : capturing-lambdas, function-objects, bind-expression; can't be decayed to function pointers, - // because they hold runtime-dynamic type-erased states. So we need intermediates - - // entry point from mcpp. hijacking its output - static int Putc_StaticHinge(int c, MCPP_OUTDEST od) - { - char asString[2] = { aznumeric_cast(c), 0 }; - return Fputs_StaticHinge(asString, od); - } - - // entry point from mcpp. hijacking its output - static int Fputs_StaticHinge(const char* s, MCPP_OUTDEST od) - { - if (!OkToLog(od)) - { - return 0; - } - // chose the proper stream - auto& selectedStream = od == MCPP_OUT ? s_currentInstance->m_outStream : s_currentInstance->m_errStream; - auto tellBefore = selectedStream.tellp(); - // append that message to it - selectedStream << s; - return aznumeric_cast(selectedStream.tellp() - tellBefore); - } - - // entry point from mcpp. hijacking its output - static int Fprintf_StaticHinge(MCPP_OUTDEST od, const char* format, ...) - { - if (!OkToLog(od)) - { - return 0; - } - // run the formatting on stack memory first, in case it's enough - constexpr int bufferSize = 256; - char localBuffer[bufferSize]; - va_list args; + // There wasn't enough space in the local store. + count++; // vsnprintf returns a size that doesn't include the null character. + biggerData.reset(new char[count]); + result = &biggerData[0]; + + // Remark: for MacOS & Linux it is important to call va_start again before + // each call to azvsnprintf. Not required for Windows. va_start(args, format); - int count = azvsnprintf(localBuffer, 256, format, args); - AZStd::unique_ptr biggerData; // will be bound to a bigger array if necessary. - char* result = localBuffer; - if (count > bufferSize) - { // there wasn't enough space in the local store. - biggerData.reset(new char[count]); - result = &biggerData[0]; // change `result`'s pointee - count = azvsnprintf(result, count, format, args); - } - AZ_Error("Preprocessor", count >= 0, "String formatting of pre-precessor output failed"); + count = azvsnprintf(result, count, format, args); va_end(args); - return Fputs_StaticHinge(result, od); } - - static void IncludeReport_StaticHinge(FILE*, const char*, const char*, const char* path) + else if (count == -1) { - s_currentInstance->m_outputData.includedPaths.insert(path); + // In Windows azvsnprintf will always return -1 if @localBuffer is not big enough, + // But it will write in @localBuffer what it could. + // See: + // https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/vsnprintf-vsnprintf-vsnprintf-l-vsnwprintf-vsnwprintf-l?view=msvc-160 + // In particular: "If the number of characters to write is greater than count, + // these functions return -1 indicating that output has been truncated." + + // There wasn't enough space in the local store. + // Remark: for MacOS & Linux it is important to call va_start again before + // each call to azvsnprintf. Not required for Windows. + va_start(args, format); + count = azvscprintf(format, args) + 1; // vscprintf returns a size that doesn't include the null character. + va_end(args); + + biggerData.reset(new char[count]); + result = &biggerData[0]; + + va_start(args, format); + count = azvsnprintf(result, count, format, args); + va_end(args); } - // ====== utility methods ===== + AZ_Error("Preprocessor", count >= 0, "String formatting of pre-precessor output failed"); + return Fputs_StaticHinge(result, od); + } - static bool OkToLog(MCPP_OUTDEST od) - { - bool isErrButOk = od == MCPP_ERR && s_currentInstance->m_plugERR; - return od == MCPP_OUT || isErrButOk; - } + void McppBinder::IncludeReport_StaticHinge(FILE*, const char*, const char*, const char* path) + { + s_currentInstance->m_outputData.includedPaths.insert(path); + } - static void SetupMcppCallbacks() - { - // callback for header included notification - mcpp_set_report_include_callback(IncludeReport_StaticHinge); - // callback for output redirection - mcpp_set_out_func(Putc_StaticHinge, Fputs_StaticHinge, Fprintf_StaticHinge); - } + bool McppBinder::OkToLog(MCPP_OUTDEST od) + { + bool isErrButOk = od == MCPP_ERR && s_currentInstance->m_plugERR; + return od == MCPP_OUT || isErrButOk; + } - // ====== instance data ====== - PreprocessorData& m_outputData; - std::ostringstream m_outStream, m_errStream; - bool m_plugERR; - - // ====== shared data ====== - // MCPP is a library with tons of non TLS global states, it can only be accessed by one client at a time. - static AZStd::mutex s_mcppExclusiveProtection; - static McppBinder* s_currentInstance; - }; + void McppBinder::SetupMcppCallbacks() + { + // callback for header included notification + mcpp_set_report_include_callback(IncludeReport_StaticHinge); + // callback for output redirection + mcpp_set_out_func(Putc_StaticHinge, Fputs_StaticHinge, Fprintf_StaticHinge); + } // definitions for the linker AZStd::mutex McppBinder::s_mcppExclusiveProtection; McppBinder* McppBinder::s_currentInstance = nullptr; + // McppBinder ends + /////////////////////////////////////////////////////////////////////// + bool PreprocessFile(const AZStd::string& fullPath, PreprocessorData& outputData, const PreprocessorOptions& options , bool collectDiagnostics, bool preprocessIncludedFiles) { diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/CommonFiles/Preprocessor.h b/Gems/Atom/Asset/Shader/Code/Source/Editor/CommonFiles/Preprocessor.h index bb4388999f..9f3c770e78 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/CommonFiles/Preprocessor.h +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/CommonFiles/Preprocessor.h @@ -14,6 +14,18 @@ #include #include +#define MCPP_DLL_IMPORT 1 +#define MCPP_DONT_USE_SHORT_NAMES 1 +#include +#undef MCPP_DLL_IMPORT + +#include + +namespace UnitTest +{ + class McppBinderTests; +} + namespace AZ { namespace ShaderBuilder @@ -93,5 +105,64 @@ namespace AZ AZStd::string& sourceCode, AZStd::string newFileOrigin); + //! Binder helper to Matsui C-Pre-Processor library + class McppBinder + { + public: + McppBinder(PreprocessorData& out, bool plugERR) + : m_outputData(out) + , m_plugERR(plugERR) + { + // single live instance + s_mcppExclusiveProtection.lock(); + s_currentInstance = this; + SetupMcppCallbacks(); + } + ~McppBinder() + { + s_currentInstance = nullptr; + s_mcppExclusiveProtection.unlock(); + } + + // This constant is in the header so McppBinderTests can see it. + static constexpr int DefaultFprintfBufferSize = 256; + + bool StartPreprocessWithCommandLine(int argc, const char* argv[]); + + private: + friend class ::UnitTest::McppBinderTests; + + // ====== C-API compatible "Static Hinges" (plain free functions) ====== + // : capturing-lambdas, function-objects, bind-expression; can't be decayed to function pointers, + // because they hold runtime-dynamic type-erased states. So we need intermediates + + // entry point from mcpp. hijacking its output + static int Putc_StaticHinge(int c, MCPP_OUTDEST od); + + // entry point from mcpp. hijacking its output + static int Fputs_StaticHinge(const char* s, MCPP_OUTDEST od); + + // entry point from mcpp. hijacking its output + static int Fprintf_StaticHinge(MCPP_OUTDEST od, const char* format, ...); + + static void IncludeReport_StaticHinge(FILE*, const char*, const char*, const char* path); + + // ====== utility methods ===== + + static bool OkToLog(MCPP_OUTDEST od); + + static void SetupMcppCallbacks(); + + // ====== instance data ====== + PreprocessorData& m_outputData; + std::ostringstream m_outStream, m_errStream; + bool m_plugERR; + + // ====== shared data ====== + // MCPP is a library with tons of non TLS global states, it can only be accessed by one client at a time. + static AZStd::mutex s_mcppExclusiveProtection; + static McppBinder* s_currentInstance; + }; + } // ShaderBuilder } // AZ diff --git a/Gems/Atom/Asset/Shader/Code/Tests/McppBinderTests.cpp b/Gems/Atom/Asset/Shader/Code/Tests/McppBinderTests.cpp new file mode 100644 index 0000000000..926f9b0a76 --- /dev/null +++ b/Gems/Atom/Asset/Shader/Code/Tests/McppBinderTests.cpp @@ -0,0 +1,92 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include + +#include "Common/ShaderBuilderTestFixture.h" + +#include + +namespace UnitTest +{ + using namespace AZ; + + // The main purpose of this class is to test ShaderBuilder::McppBinder::Fprintf_StaticHinge() + // Which has three common scenarios to validate. + // 1- The formatted string is expected to yield less bytes than McppBinder::DefaultFprintfBufferSize. + // 2- The formatted string is expected to yield exactly McppBinder::DefaultFprintfBufferSize number of bytes. + // 3- The formatted string is expectedc to yield more bytes than McppBinder::DefaultFprintfBufferSize. + class McppBinderTests : public ShaderBuilderTestFixture + { + public: + + // Fills @buffer with 'a' to 'z' for up to @bufferSize number of bytes. + // This function will null('\0') char terminate @buffer. + void FillBufferWithAlphabet(char* buffer, int bufferSize) + { + for (int bufferPos = 0, rollback = 0; bufferPos < (bufferSize - 1); ++bufferPos) + { + const char value = 'a' + rollback++; + buffer[bufferPos] = value; + if (value == 'z') + { + rollback = 0; + } + } + buffer[bufferSize - 1] = '\0'; + } + + // Pushes the null terminated string, @inputString, into McppBinder capture stream + // using McppBinder::Fprintf_StaticHinge(). + // Returns the content of the McppBinder capture stream as a string. + AZStd::string PrintStringThroughStaticHinge(const char* inputString) + { + ShaderBuilder::PreprocessorData preprocessorData; + ShaderBuilder::McppBinder mcppBinder(preprocessorData, false); + ShaderBuilder::McppBinder::Fprintf_StaticHinge(MCPP_OUTDEST::MCPP_OUT, "%s", inputString); + // convert from std::ostringstring to AZStd::string + return AZStd::string(mcppBinder.m_outStream.str().c_str()); + } + }; // class McppBinderTests + + + TEST_F(McppBinderTests, ShouldPrintLessBytesThanDefaultSize) + { + constexpr int bufferSize = (ShaderBuilder::McppBinder::DefaultFprintfBufferSize / 2) + 1; + EXPECT_TRUE(bufferSize > 0); + char buffer[bufferSize] = ""; + FillBufferWithAlphabet(buffer, bufferSize); + auto printedString = PrintStringThroughStaticHinge(buffer); + EXPECT_EQ(AZStd::string(buffer), printedString); + } + + TEST_F(McppBinderTests, ShouldPrintSameBytesAsDefaultSize) + { + constexpr int bufferSize = ShaderBuilder::McppBinder::DefaultFprintfBufferSize + 1; + EXPECT_TRUE(bufferSize > 0); + char buffer[bufferSize] = ""; + FillBufferWithAlphabet(buffer, bufferSize); + auto printedString = PrintStringThroughStaticHinge(buffer); + EXPECT_EQ(AZStd::string(buffer), printedString); + } + + TEST_F(McppBinderTests, ShouldPrintMoreBytesThanDefaultSize) + { + constexpr int bufferSize = (ShaderBuilder::McppBinder::DefaultFprintfBufferSize * 2) + 1; + EXPECT_TRUE(bufferSize > 0); + char buffer[bufferSize] = ""; + FillBufferWithAlphabet(buffer, bufferSize); + auto printedString = PrintStringThroughStaticHinge(buffer); + EXPECT_EQ(AZStd::string(buffer), printedString); + } + +} //namespace UnitTest + +//AZ_UNIT_TEST_HOOK(DEFAULT_UNIT_TEST_ENV); + diff --git a/Gems/Atom/Asset/Shader/Code/atom_asset_shader_builders_tests_files.cmake b/Gems/Atom/Asset/Shader/Code/atom_asset_shader_builders_tests_files.cmake index bfddb5ce8e..033b399478 100644 --- a/Gems/Atom/Asset/Shader/Code/atom_asset_shader_builders_tests_files.cmake +++ b/Gems/Atom/Asset/Shader/Code/atom_asset_shader_builders_tests_files.cmake @@ -10,4 +10,5 @@ set(FILES Tests/Common/ShaderBuilderTestFixture.h Tests/Common/ShaderBuilderTestFixture.cpp Tests/SupervariantCmdArgumentTests.cpp + Tests/McppBinderTests.cpp ) From a20428d3933beb532430e09950ef26b104bc982f Mon Sep 17 00:00:00 2001 From: mnaumov Date: Mon, 16 Aug 2021 23:16:04 -0700 Subject: [PATCH 501/803] Fixing non unity build Signed-off-by: Mikhail Naumov --- .../AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.h index 77b4b752a6..7cab24ad9f 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.h @@ -159,6 +159,8 @@ namespace AzToolsFramework struct LinkIdMetadata { AZ_RTTI(LinkIdMetadata, "{8FF7D299-14E3-41D4-90C5-393A240FAE7C}"); + + virtual ~LinkIdMetadata() {} }; } // namespace PrefabDomUtils } // namespace Prefab From 8f4a35b146af277ad903ab5522c33a2362ce2cb7 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Tue, 17 Aug 2021 13:21:13 -0500 Subject: [PATCH 502/803] AtomTools: fix unused variable errors Signed-off-by: Guthrie Adams --- .../Code/Source/Document/AtomToolsDocument.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocument.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocument.cpp index 48212fe154..e8eb9401d4 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocument.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocument.cpp @@ -40,29 +40,35 @@ namespace AtomToolsFramework const AZStd::any& AtomToolsDocument::GetPropertyValue(const AZ::Name& propertyFullName) const { + AZ_UNUSED(propertyFullName); AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); return m_invalidValue; } const AtomToolsFramework::DynamicProperty& AtomToolsDocument::GetProperty(const AZ::Name& propertyFullName) const { + AZ_UNUSED(propertyFullName); AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); return m_invalidProperty; } bool AtomToolsDocument::IsPropertyGroupVisible(const AZ::Name& propertyGroupFullName) const { + AZ_UNUSED(propertyGroupFullName); AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); return false; } void AtomToolsDocument::SetPropertyValue(const AZ::Name& propertyFullName, const AZStd::any& value) { + AZ_UNUSED(propertyFullName); + AZ_UNUSED(value); AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); } bool AtomToolsDocument::Open(AZStd::string_view loadPath) { + AZ_UNUSED(loadPath); AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); return false; } @@ -81,6 +87,7 @@ namespace AtomToolsFramework bool AtomToolsDocument::SaveAsCopy(AZStd::string_view savePath) { + AZ_UNUSED(savePath); AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); return false; } @@ -88,6 +95,7 @@ namespace AtomToolsFramework bool AtomToolsDocument::SaveAsChild(AZStd::string_view savePath) { + AZ_UNUSED(savePath); AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); return false; } From e865ad5d2368096caf00896dd0fdb0eee846c139 Mon Sep 17 00:00:00 2001 From: Jacob Hilliard <64656371+jcbhl@users.noreply.github.com> Date: Tue, 17 Aug 2021 11:33:13 -0700 Subject: [PATCH 503/803] Profiler: implement loading from saved captures (#3026) * Profiler: implement loading from saved capture Adds functionality for finding a saved capture on disk and then deserializing it using rapidjson's built-in buffered stream reader. This does require use of raw file pointers since saved captures can be hundreds of megabytes. Actually showing the data in the visualizer is TODO. * Profiler: use heap buffer over stack buffer * Profiler: move deserialization logic to ImGuiCpuProfiler Signed-off-by: Jacob Hilliard --- .../ProfilingCaptureSystemComponent.cpp | 98 +----------- .../Code/Include/Atom/RHI/CpuProfilerImpl.h | 31 +++- .../RHI/Code/Source/RHI/CpuProfilerImpl.cpp | 63 +++++++- .../Include/Atom/RPI.Edit/Common/JsonUtils.h | 3 +- .../Include/Atom/Utils/ImGuiCpuProfiler.h | 15 ++ .../Include/Atom/Utils/ImGuiCpuProfiler.inl | 151 +++++++++++++++++- 6 files changed, 260 insertions(+), 101 deletions(-) diff --git a/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.cpp b/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.cpp index add6d0e098..7c6dfcf744 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.cpp @@ -9,6 +9,7 @@ #include "ProfilingCaptureSystemComponent.h" #include +#include #include #include #include @@ -141,36 +142,6 @@ namespace AZ AZStd::vector m_pipelineStatisticsEntries; }; - // Intermediate class to serialize Cpu TimedRegion data. - class CpuProfilingStatisticsSerializer - { - public: - class CpuProfilingStatisticsSerializerEntry - { - public: - AZ_TYPE_INFO(CpuProfilingStatisticsSerializer::CpuProfilingStatisticsSerializerEntry, "{26B78F65-EB96-46E2-BE7E-A1233880B225}"); - static void Reflect(AZ::ReflectContext* context); - - CpuProfilingStatisticsSerializerEntry() = default; - CpuProfilingStatisticsSerializerEntry(const RHI::CachedTimeRegion& cachedTimeRegion); - - private: - Name m_groupName; - Name m_regionName; - uint16_t m_stackDepth; - AZStd::sys_time_t m_startTick; - AZStd::sys_time_t m_endTick; - }; - - AZ_TYPE_INFO(CpuProfilingStatisticsSerializer, "{D5B02946-0D27-474F-9A44-364C2706DD41}"); - static void Reflect(AZ::ReflectContext* context); - - CpuProfilingStatisticsSerializer() = default; - CpuProfilingStatisticsSerializer(const AZStd::ring_buffer& continuousData); - - AZStd::vector m_cpuProfilingStatisticsSerializerEntries; - }; - // Intermediate class to serialize benchmark metadata. class BenchmarkMetadataSerializer { @@ -327,65 +298,6 @@ namespace AZ } } - // --- CpuProfilingStatisticsSerializer --- - - CpuProfilingStatisticsSerializer::CpuProfilingStatisticsSerializer(const AZStd::ring_buffer& continuousData) - { - // Create serializable entries - for (const auto& timeRegionMap : continuousData) - { - for (const auto& threadEntry : timeRegionMap) - { - for (const auto& cachedRegionEntry : threadEntry.second) - { - m_cpuProfilingStatisticsSerializerEntries.insert( - m_cpuProfilingStatisticsSerializerEntries.end(), - cachedRegionEntry.second.begin(), - cachedRegionEntry.second.end()); - } - } - } - } - - void CpuProfilingStatisticsSerializer::Reflect(AZ::ReflectContext* context) - { - if (auto* serializeContext = azrtti_cast(context)) - { - serializeContext->Class() - ->Version(1) - ->Field("cpuProfilingStatisticsSerializerEntry", &CpuProfilingStatisticsSerializer::m_cpuProfilingStatisticsSerializerEntries) - ; - } - - CpuProfilingStatisticsSerializerEntry::Reflect(context); - } - - // --- CpuProfilingStatisticsSerializerEntry --- - - CpuProfilingStatisticsSerializer::CpuProfilingStatisticsSerializerEntry::CpuProfilingStatisticsSerializerEntry(const RHI::CachedTimeRegion& cachedTimeRegion) - { - m_groupName = cachedTimeRegion.m_groupRegionName->m_groupName; - m_regionName = cachedTimeRegion.m_groupRegionName->m_regionName; - m_stackDepth = cachedTimeRegion.m_stackDepth; - m_startTick = cachedTimeRegion.m_startTick; - m_endTick = cachedTimeRegion.m_endTick; - } - - void CpuProfilingStatisticsSerializer::CpuProfilingStatisticsSerializerEntry::Reflect(AZ::ReflectContext* context) - { - if (auto* serializeContext = azrtti_cast(context)) - { - serializeContext->Class() - ->Version(1) - ->Field("groupName", &CpuProfilingStatisticsSerializerEntry::m_groupName) - ->Field("regionName", &CpuProfilingStatisticsSerializerEntry::m_regionName) - ->Field("stackDepth", &CpuProfilingStatisticsSerializerEntry::m_stackDepth) - ->Field("startTick", &CpuProfilingStatisticsSerializerEntry::m_startTick) - ->Field("endTick", &CpuProfilingStatisticsSerializerEntry::m_endTick) - ; - } - } - // --- BenchmarkMetadataSerializer --- BenchmarkMetadataSerializer::BenchmarkMetadataSerializer(const AZStd::string& benchmarkName, const RHI::PhysicalDeviceDescriptor& gpuDescriptor) @@ -458,7 +370,7 @@ namespace AZ TimestampSerializer::Reflect(context); CpuFrameTimeSerializer::Reflect(context); PipelineStatisticsSerializer::Reflect(context); - CpuProfilingStatisticsSerializer::Reflect(context); + RHI::CpuProfilingStatisticsSerializer::Reflect(context); BenchmarkMetadataSerializer::Reflect(context); } @@ -651,10 +563,10 @@ namespace AZ JsonSerializerSettings serializationSettings; serializationSettings.m_keepDefaults = true; - CpuProfilingStatisticsSerializer serializer(data); + RHI::CpuProfilingStatisticsSerializer serializer(data); const auto saveResult = JsonSerializationUtils::SaveObjectToFile(&serializer, - outputFilePath, (CpuProfilingStatisticsSerializer*)nullptr, &serializationSettings); + outputFilePath, (RHI::CpuProfilingStatisticsSerializer*)nullptr, &serializationSettings); AZStd::string captureInfo = outputFilePath; if (!saveResult.IsSuccess()) @@ -694,7 +606,7 @@ namespace AZ const bool captureStarted = m_cpuProfilingStatisticsCapture.StartCapture([this, outputFilePath, wasEnabled]() { // Blocking call for a single frame of data, avoid thread overhead - AZStd::ring_buffer singleFrameData; + AZStd::ring_buffer singleFrameData(1); singleFrameData.push_back(RHI::CpuProfiler::Get()->GetTimeRegionMap()); SerializeCpuProfilingData(singleFrameData, outputFilePath, wasEnabled); }); diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/CpuProfilerImpl.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/CpuProfilerImpl.h index 2e4ca67db8..9372977d8e 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/CpuProfilerImpl.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/CpuProfilerImpl.h @@ -12,6 +12,7 @@ #include #include +#include #include #include #include @@ -161,5 +162,33 @@ namespace AZ AZStd::ring_buffer m_continuousCaptureData; }; - }; // namespace RPI + // Intermediate class to serialize Cpu TimedRegion data. + class CpuProfilingStatisticsSerializer + { + public: + class CpuProfilingStatisticsSerializerEntry + { + public: + AZ_TYPE_INFO(CpuProfilingStatisticsSerializer::CpuProfilingStatisticsSerializerEntry, "{26B78F65-EB96-46E2-BE7E-A1233880B225}"); + static void Reflect(AZ::ReflectContext* context); + + CpuProfilingStatisticsSerializerEntry() = default; + CpuProfilingStatisticsSerializerEntry(const RHI::CachedTimeRegion& cachedTimeRegion); + + Name m_groupName; + Name m_regionName; + uint16_t m_stackDepth; + AZStd::sys_time_t m_startTick; + AZStd::sys_time_t m_endTick; + }; + + AZ_TYPE_INFO(CpuProfilingStatisticsSerializer, "{D5B02946-0D27-474F-9A44-364C2706DD41}"); + static void Reflect(AZ::ReflectContext* context); + + CpuProfilingStatisticsSerializer() = default; + CpuProfilingStatisticsSerializer(const AZStd::ring_buffer& continuousData); + + AZStd::vector m_cpuProfilingStatisticsSerializerEntries; + }; + }; // namespace RHI }; // namespace AZ diff --git a/Gems/Atom/RHI/Code/Source/RHI/CpuProfilerImpl.cpp b/Gems/Atom/RHI/Code/Source/RHI/CpuProfilerImpl.cpp index d41b5d656e..5585cc7032 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/CpuProfilerImpl.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/CpuProfilerImpl.cpp @@ -409,5 +409,64 @@ namespace AZ m_cachedTimeRegionMutex.unlock(); } } - } -} + + // --- CpuProfilingStatisticsSerializer --- + + CpuProfilingStatisticsSerializer::CpuProfilingStatisticsSerializer(const AZStd::ring_buffer& continuousData) + { + // Create serializable entries + for (const auto& timeRegionMap : continuousData) + { + for (const auto& threadEntry : timeRegionMap) + { + for (const auto& cachedRegionEntry : threadEntry.second) + { + m_cpuProfilingStatisticsSerializerEntries.insert( + m_cpuProfilingStatisticsSerializerEntries.end(), + cachedRegionEntry.second.begin(), + cachedRegionEntry.second.end()); + } + } + } + } + + void CpuProfilingStatisticsSerializer::Reflect(AZ::ReflectContext* context) + { + if (auto* serializeContext = azrtti_cast(context)) + { + serializeContext->Class() + ->Version(1) + ->Field("cpuProfilingStatisticsSerializerEntries", &CpuProfilingStatisticsSerializer::m_cpuProfilingStatisticsSerializerEntries) + ; + } + + CpuProfilingStatisticsSerializerEntry::Reflect(context); + } + + // --- CpuProfilingStatisticsSerializerEntry --- + + CpuProfilingStatisticsSerializer::CpuProfilingStatisticsSerializerEntry::CpuProfilingStatisticsSerializerEntry(const RHI::CachedTimeRegion& cachedTimeRegion) + { + m_groupName = cachedTimeRegion.m_groupRegionName->m_groupName; + m_regionName = cachedTimeRegion.m_groupRegionName->m_regionName; + m_stackDepth = cachedTimeRegion.m_stackDepth; + m_startTick = cachedTimeRegion.m_startTick; + m_endTick = cachedTimeRegion.m_endTick; + } + + void CpuProfilingStatisticsSerializer::CpuProfilingStatisticsSerializerEntry::Reflect(AZ::ReflectContext* context) + { + if (auto* serializeContext = azrtti_cast(context)) + { + serializeContext->Class() + ->Version(1) + ->Field("groupName", &CpuProfilingStatisticsSerializerEntry::m_groupName) + ->Field("regionName", &CpuProfilingStatisticsSerializerEntry::m_regionName) + ->Field("stackDepth", &CpuProfilingStatisticsSerializerEntry::m_stackDepth) + ->Field("startTick", &CpuProfilingStatisticsSerializerEntry::m_startTick) + ->Field("endTick", &CpuProfilingStatisticsSerializerEntry::m_endTick) + ; + } + } + } // namespace RHI +} // namespace AZ diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Common/JsonUtils.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Common/JsonUtils.h index 3e3fbec8fe..549f787ac9 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Common/JsonUtils.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Common/JsonUtils.h @@ -10,7 +10,9 @@ #include #include + #include + #include #include @@ -118,7 +120,6 @@ namespace AZ AZ_Error("AZ::RPI::JsonUtils", false, "Failed to load object from json string: %s", loadResult.GetError().c_str()); return false; } - } // namespace JsonUtils } // namespace RPI } // namespace AZ diff --git a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.h b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.h index 75b7ec9fdd..bdaf38a64a 100644 --- a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.h +++ b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.h @@ -9,6 +9,7 @@ #pragma once #include +#include #include #include @@ -102,6 +103,12 @@ namespace AZ //! Draws the statistical view of the CPU profiling data. void DrawStatisticsView(); + //! Callback invoked when the "Load File" button is pressed in the file picker. + void LoadFile(); + + //! Draws the file picker window. + void DrawFilePicker(); + //! Draws the CPU profiling visualizer. void DrawVisualizer(); @@ -198,6 +205,14 @@ namespace AZ AZ::RHI::CpuTimingStatistics m_cpuTimingStatisticsWhenPause; AZStd::string m_lastCapturedFilePath; + + bool m_showFilePicker = false; + + // Cached file paths to previous traces on disk, sorted with the most recent trace at the front. + AZStd::vector m_cachedCapturePaths; + + // Index into the file picker, used to determine which file to load when "Load File" is pressed. + int m_currentFileIndex = 0; }; } // namespace Render } // namespace AZ diff --git a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl index a24fdbf1d8..9b4eebf043 100644 --- a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl +++ b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl @@ -9,9 +9,14 @@ #include #include #include +#include +#include #include -#include +#include +#include +#include +#include #include #include #include @@ -45,6 +50,74 @@ namespace AZ AZ_Assert(ticksPerSecond >= 1000, "Error in converting ticks to ms, expected ticksPerSecond >= 1000"); return static_cast((ticks * 1000) / (ticksPerSecond / 1000)) / 1000.0f; } + + using DeserializedCpuData = AZStd::vector; + inline Outcome LoadSavedCpuProfilingStatistics(const AZStd::string& capturePath) + { + auto* base = IO::FileIOBase::GetInstance(); + + char resolvedPath[IO::MaxPathLength]; + if (!base->ResolvePath(capturePath.c_str(), resolvedPath, IO::MaxPathLength)) + { + return Failure(AZStd::string::format("Could not resolve the path to file %s, is the path correct?", resolvedPath)); + } + + u64 captureSizeBytes; + const IO::Result fileSizeResult = base->Size(resolvedPath, captureSizeBytes); + if (!fileSizeResult) + { + return Failure(AZStd::string::format("Could not read the size of file %s, is the path correct?", resolvedPath)); + } + + // NOTE: this uses raw file pointers over the abstractions and utility functions provided by AZ::JsonSerializationUtils because + // saved profiling captures can be upwards of 400 MB. This necessitates a buffered approach to avoid allocating huge chunks of memory. + FILE* fp = nullptr; + azfopen(&fp, resolvedPath, "rb"); + if (!fp) + { + return Failure(AZStd::string::format("Could not fopen file %s, is the path correct?\n", resolvedPath)); + } + + constexpr AZStd::size_t MaxBufSize = 65536; + const AZStd::size_t bufSize = AZStd::min(MaxBufSize, aznumeric_cast(captureSizeBytes)); + char* buf = reinterpret_cast(azmalloc(bufSize)); + + rapidjson::Document document; + rapidjson::FileReadStream inputStream(fp, buf, bufSize); + document.ParseStream(inputStream); + + azfree(buf); + fclose(fp); + + if (document.HasParseError()) + { + const auto pe = document.GetParseError(); + return Failure(AZStd::string::format( + "Rapidjson could not parse the document with ParseErrorCode %u. See 3rdParty/rapidjson/error.h for definitions.\n", pe)); + } + + if (!document.IsObject() || !document.HasMember("ClassData")) + { + return Failure(AZStd::string::format( + "Error in loading saved capture: top-level object does not have a ClassData field. Did the serialization format change recently?\n")); + } + + AZ_TracePrintf("JsonUtils", "Successfully loaded JSON into memory.\n"); + + const auto& root = document["ClassData"]; + RHI::CpuProfilingStatisticsSerializer serializer; + const JsonSerializationResult::ResultCode deserializationResult = JsonSerialization::Load(serializer, root); + if (deserializationResult.GetProcessing() == JsonSerializationResult::Processing::Halted + || serializer.m_cpuProfilingStatisticsSerializerEntries.empty()) + { + return Failure(AZStd::string::format("Error in deserializing document: %s\n", deserializationResult.ToString(capturePath.c_str()).c_str())); + } + + AZ_TracePrintf("JsonUtils", "Successfully loaded CPU profiling data with %zu profiling entries.\n", + serializer.m_cpuProfilingStatisticsSerializerEntries.size()); + + return Success(AZStd::move(serializer.m_cpuProfilingStatisticsSerializerEntries)); + } } // namespace CpuProfilerImGuiHelper inline void ImGuiCpuProfiler::Draw(bool& keepDrawing, const AZ::RHI::CpuTimingStatistics& currentCpuTimingStatistics) @@ -80,6 +153,11 @@ namespace AZ { DrawStatisticsView(); } + + if (m_showFilePicker) + { + DrawFilePicker(); + } } ImGui::End(); @@ -110,6 +188,11 @@ namespace AZ inline void ImGuiCpuProfiler::DrawCommonHeader() { + if (!m_lastCapturedFilePath.empty()) + { + ImGui::Text("Saved: %s", m_lastCapturedFilePath.c_str()); + } + if (ImGui::Button(m_enableVisualizer ? "Swap to statistics" : "Swap to visualizer")) { m_enableVisualizer = !m_enableVisualizer; @@ -157,10 +240,31 @@ namespace AZ } } - if (!m_lastCapturedFilePath.empty()) + ImGui::SameLine(); + if (ImGui::Button("Load file")) { - ImGui::SameLine(); - ImGui::Text("Saved: %s", m_lastCapturedFilePath.c_str()); + m_showFilePicker = true; + + // Only update the cached file list when opened so that we aren't making IO calls on every frame. + auto* base = AZ::IO::FileIOBase::GetInstance(); + const AZStd::string defaultSavedCapturePath = "@user@/CpuProfiler"; + + m_cachedCapturePaths.clear(); + base->FindFiles( + defaultSavedCapturePath.c_str(), "*.json", + [&paths = m_cachedCapturePaths](const char* path) -> bool + { + auto foundPath = IO::Path(path); + paths.push_back(foundPath); + return true; + }); + + // Sort by decreasing modification time (most recent at the top) + AZStd::sort(m_cachedCapturePaths.begin(), m_cachedCapturePaths.end(), + [&base](const IO::Path& lhs, const IO::Path& rhs) + { + return base->ModificationTime(lhs.c_str()) > base->ModificationTime(rhs.c_str()); + }); } } @@ -313,6 +417,45 @@ namespace AZ } } + inline void ImGuiCpuProfiler::DrawFilePicker() + { + ImGui::SetNextWindowSize({ 500, 200 }, ImGuiCond_Once); + if (ImGui::Begin("File Picker", &m_showFilePicker)) + { + if (ImGui::Button("Load selected")) + { + LoadFile(); + } + + auto getter = [](void* vectorPointer, int idx, const char** out_text) -> bool + { + const auto& pathVec = *static_cast*>(vectorPointer); + if (idx < 0 || idx >= pathVec.size()) + { + return false; + } + *out_text = pathVec[idx].c_str(); + return true; + }; + + ImGui::SetNextItemWidth(ImGui::GetWindowContentRegionWidth()); + ImGui::ListBox("", &m_currentFileIndex, getter, &m_cachedCapturePaths, aznumeric_cast(m_cachedCapturePaths.size())); + } + ImGui::End(); + } + + inline void ImGuiCpuProfiler::LoadFile() + { + const IO::Path& pathToLoad = m_cachedCapturePaths[m_currentFileIndex]; + auto res = CpuProfilerImGuiHelper::LoadSavedCpuProfilingStatistics(pathToLoad.String()); + if (!res.IsSuccess()) + { + AZ_TracePrintf("ImGuiCpuProfiler", "%s", res.GetError().c_str()); + return; + } + // TODO ATOM-16022 Parse this data and display it in the visualizer widget. + } + // -- CPU Visualizer -- inline void ImGuiCpuProfiler::DrawVisualizer() { From 7be2b0b6c37165104b80b6248370af61d6b33386 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Tue, 17 Aug 2021 11:49:51 -0700 Subject: [PATCH 504/803] Fix for a leaky test Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Framework/AzCore/AzCore/Name/Name.h | 6 ++++ .../Framework/AzCore/Tests/Name/NameTests.cpp | 31 ++++++++++++++----- 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/Name/Name.h b/Code/Framework/AzCore/AzCore/Name/Name.h index 46a9b5b7cc..16179c9cde 100644 --- a/Code/Framework/AzCore/AzCore/Name/Name.h +++ b/Code/Framework/AzCore/AzCore/Name/Name.h @@ -10,6 +10,11 @@ #include +namespace UnitTest +{ + class NameTest; +} + namespace AZ { class NameDictionary; @@ -29,6 +34,7 @@ namespace AZ class Name { friend NameDictionary; + friend UnitTest::NameTest; public: using Hash = Internal::NameData::Hash; diff --git a/Code/Framework/AzCore/Tests/Name/NameTests.cpp b/Code/Framework/AzCore/Tests/Name/NameTests.cpp index 3b6310b1de..a46c1724f6 100644 --- a/Code/Framework/AzCore/Tests/Name/NameTests.cpp +++ b/Code/Framework/AzCore/Tests/Name/NameTests.cpp @@ -171,7 +171,17 @@ namespace UnitTest azsnprintf(buffer, RandomStringBufferSize, "%d", m_random.GetRandom()); return buffer; } - + + AZ::Internal::NameData* GetNameData(AZ::Name& name) + { + return name.m_data.get(); + } + + void FreeMemoryFromNameData(AZ::Internal::NameData* nameData) + { + delete nameData; + } + AZ::SimpleLcgRandom m_random; }; @@ -488,13 +498,20 @@ namespace UnitTest TEST_F(NameTest, ReportLeakedNames) { - AZ::Name leakedName{"hello"}; - AZ_TEST_START_TRACE_SUPPRESSION; - AZ::NameDictionary::Destroy(); - AZ_TEST_STOP_TRACE_SUPPRESSION(1); + AZ::Internal::NameData* leakedNameData = nullptr; + { + AZ::Name leakedName{ "hello" }; + AZ_TEST_START_TRACE_SUPPRESSION; + AZ::NameDictionary::Destroy(); + AZ_TEST_STOP_TRACE_SUPPRESSION(1); - // Create the dictionary again to avoid error in TearDown() - AZ::NameDictionary::Create(); + leakedNameData = GetNameData(leakedName); + + // Create the dictionary again to avoid crash when the intrusive_ptr in Name tries to access NameDictionary to free it + AZ::NameDictionary::Create(); + } + + FreeMemoryFromNameData(leakedNameData); // free it to avoid memory system reporting the leak } TEST_F(NameTest, NullTerminatedTest) From 8ebaf1084057306fcbbcf247a4d1009cfb4a5b96 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Tue, 17 Aug 2021 14:04:26 -0500 Subject: [PATCH 505/803] AtomTools: added status message helper functions Signed-off-by: Guthrie Adams --- .../Window/AtomToolsMainWindow.h | 5 ++- .../Source/Window/AtomToolsMainWindow.cpp | 21 ++++++++-- .../Source/Window/MaterialEditorWindow.cpp | 42 ++++++------------- .../Window/ShaderManagementConsoleWindow.cpp | 41 ++++++------------ 4 files changed, 48 insertions(+), 61 deletions(-) diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindow.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindow.h index 751b30a907..2a304c9a8c 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindow.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindow.h @@ -52,8 +52,11 @@ namespace AtomToolsFramework virtual void SelectPreviousTab(); virtual void SelectNextTab(); + void SetStatusMessage(const QString& message); + void SetStatusWarning(const QString& message); + void SetStatusError(const QString& message); + AzQtComponents::FancyDocking* m_advancedDockManager = nullptr; - QMenuBar* m_menuBar = nullptr; AzQtComponents::TabWidget* m_tabWidget = nullptr; QLabel* m_statusMessage = nullptr; diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp index e869e0eb98..cd7d49d8d3 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp @@ -110,9 +110,9 @@ namespace AtomToolsFramework void AtomToolsMainWindow::CreateMenu() { - m_menuBar = new QMenuBar(this); - m_menuBar->setObjectName("MenuBar"); - setMenuBar(m_menuBar); + auto menuBar = new QMenuBar(this); + menuBar->setObjectName("MenuBar"); + setMenuBar(menuBar); } void AtomToolsMainWindow::CreateTabBar() @@ -246,4 +246,19 @@ namespace AtomToolsFramework m_tabWidget->setCurrentIndex((m_tabWidget->currentIndex() + 1) % m_tabWidget->count()); } } + + void AtomToolsMainWindow::SetStatusMessage(const QString& message) + { + m_statusMessage->setText(QString("%1").arg(message)); + } + + void AtomToolsMainWindow::SetStatusWarning(const QString& message) + { + m_statusMessage->setText(QString("%1").arg(message)); + } + + void AtomToolsMainWindow::SetStatusError(const QString& message) + { + m_statusMessage->setText(QString("%1").arg(message)); + } } // namespace AtomToolsFramework diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp index ca938c3745..a32f81f78e 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp @@ -237,18 +237,14 @@ namespace MaterialEditor const QString documentPath = GetDocumentPath(documentId); if (!documentPath.isEmpty()) { - const QString status = QString("Document opened: %1").arg(documentPath); - m_statusMessage->setText(QString("%1").arg(status)); + SetStatusMessage(tr("Document opened: %1").arg(documentPath)); } } void MaterialEditorWindow::OnDocumentClosed(const AZ::Uuid& documentId) { RemoveTabForDocumentId(documentId); - - const QString documentPath = GetDocumentPath(documentId); - const QString status = QString("Document closed: %1").arg(documentPath); - m_statusMessage->setText(QString("%1").arg(status)); + SetStatusMessage(tr("Document closed: %1").arg(GetDocumentPath(documentId))); } void MaterialEditorWindow::OnDocumentModified(const AZ::Uuid& documentId) @@ -284,10 +280,7 @@ namespace MaterialEditor AZStd::string filename; AzFramework::StringFunc::Path::GetFullFileName(absolutePath.c_str(), filename); UpdateTabForDocumentId(documentId, filename, absolutePath, isModified); - - const QString documentPath = GetDocumentPath(documentId); - const QString status = QString("Document saved: %1").arg(documentPath); - m_statusMessage->setText(QString("%1").arg(status)); + SetStatusMessage(tr("Document saved: %1").arg(GetDocumentPath(documentId))); } void MaterialEditorWindow::CreateMenu() @@ -295,7 +288,7 @@ namespace MaterialEditor Base::CreateMenu(); // Generating the main menu manually because it's easier and we will have some dynamic or data driven entries - m_menuFile = m_menuBar->addMenu("&File"); + m_menuFile = menuBar()->addMenu("&File"); m_actionNew = m_menuFile->addAction("&New...", [this]() { CreateMaterialDialog createDialog(this); @@ -330,9 +323,7 @@ namespace MaterialEditor AtomToolsFramework::AtomToolsDocumentSystemRequestBus::BroadcastResult(result, &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::SaveDocument, documentId); if (!result) { - const QString documentPath = GetDocumentPath(documentId); - const QString status = QString("Document save failed: %1").arg(documentPath); - m_statusMessage->setText(QString("%1").arg(status)); + SetStatusError(tr("Document save failed: %1").arg(GetDocumentPath(documentId))); } }, QKeySequence::Save); @@ -345,8 +336,7 @@ namespace MaterialEditor documentId, AtomToolsFramework::GetSaveFileInfo(documentPath).absoluteFilePath().toUtf8().constData()); if (!result) { - const QString status = QString("Document save failed: %1").arg(documentPath); - m_statusMessage->setText(QString("%1").arg(status)); + SetStatusError(tr("Document save failed: %1").arg(GetDocumentPath(documentId))); } }, QKeySequence::SaveAs); @@ -359,8 +349,7 @@ namespace MaterialEditor documentId, AtomToolsFramework::GetSaveFileInfo(documentPath).absoluteFilePath().toUtf8().constData()); if (!result) { - const QString status = QString("Document save failed: %1").arg(documentPath); - m_statusMessage->setText(QString("%1").arg(status)); + SetStatusError(tr("Document save failed: %1").arg(GetDocumentPath(documentId))); } }); @@ -369,8 +358,7 @@ namespace MaterialEditor AtomToolsFramework::AtomToolsDocumentSystemRequestBus::BroadcastResult(result, &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::SaveAllDocuments); if (!result) { - const QString status = QString("Document save all failed."); - m_statusMessage->setText(QString("%1").arg(status)); + SetStatusError(tr("Document save all failed")); } }); @@ -406,7 +394,7 @@ namespace MaterialEditor close(); }, QKeySequence::Quit); - m_menuEdit = m_menuBar->addMenu("&Edit"); + m_menuEdit = menuBar()->addMenu("&Edit"); m_actionUndo = m_menuEdit->addAction("&Undo", [this]() { const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex()); @@ -414,9 +402,7 @@ namespace MaterialEditor AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(result, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::Undo); if (!result) { - const QString documentPath = GetDocumentPath(documentId); - const QString status = QString("Document undo failed: %1").arg(documentPath); - m_statusMessage->setText(QString("%1").arg(status)); + SetStatusError(tr("Document undo failed: %1").arg(GetDocumentPath(documentId))); } }, QKeySequence::Undo); @@ -426,9 +412,7 @@ namespace MaterialEditor AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(result, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::Redo); if (!result) { - const QString documentPath = GetDocumentPath(documentId); - const QString status = QString("Document redo failed: %1").arg(documentPath); - m_statusMessage->setText(QString("%1").arg(status)); + SetStatusError(tr("Document redo failed: %1").arg(GetDocumentPath(documentId))); } }, QKeySequence::Redo); @@ -440,7 +424,7 @@ namespace MaterialEditor }, QKeySequence::Preferences); m_actionSettings->setEnabled(true); - m_menuView = m_menuBar->addMenu("&View"); + m_menuView = menuBar()->addMenu("&View"); m_actionAssetBrowser = m_menuView->addAction("&Asset Browser", [this]() { const AZStd::string label = "Asset Browser"; @@ -480,7 +464,7 @@ namespace MaterialEditor SelectNextTab(); }, Qt::CTRL | Qt::Key_Tab); //QKeySequence::NextChild works as expected but mirroring Previous - m_menuHelp = m_menuBar->addMenu("&Help"); + m_menuHelp = menuBar()->addMenu("&Help"); m_actionHelp = m_menuHelp->addAction("&Help...", [this]() { HelpDialog dialog(this); diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp index 0b4802640b..6354f8beba 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp @@ -149,18 +149,14 @@ namespace ShaderManagementConsole const QString documentPath = GetDocumentPath(documentId); if (!documentPath.isEmpty()) { - const QString status = QString("Document opened: %1").arg(documentPath); - m_statusMessage->setText(QString("%1").arg(status)); + SetStatusMessage(tr("Document opened: %1").arg(documentPath)); } } void ShaderManagementConsoleWindow::OnDocumentClosed(const AZ::Uuid& documentId) { RemoveTabForDocumentId(documentId); - - const QString documentPath = GetDocumentPath(documentId); - const QString status = QString("Document closed: %1").arg(documentPath); - m_statusMessage->setText(QString("%1").arg(status)); + SetStatusMessage(tr("Document closed: %1").arg(GetDocumentPath(documentId))); } void ShaderManagementConsoleWindow::OnDocumentModified(const AZ::Uuid& documentId) @@ -196,10 +192,7 @@ namespace ShaderManagementConsole AZStd::string filename; AzFramework::StringFunc::Path::GetFullFileName(absolutePath.c_str(), filename); UpdateTabForDocumentId(documentId, filename, absolutePath, isModified); - - const QString documentPath = GetDocumentPath(documentId); - const QString status = QString("Document saved: %1").arg(documentPath); - m_statusMessage->setText(QString("%1").arg(status)); + SetStatusMessage(tr("Document saved: %1").arg(GetDocumentPath(documentId))); } void ShaderManagementConsoleWindow::CreateMenu() @@ -207,7 +200,7 @@ namespace ShaderManagementConsole Base::CreateMenu(); // Generating the main menu manually because it's easier and we will have some dynamic or data driven entries - m_menuFile = m_menuBar->addMenu("&File"); + m_menuFile = menuBar()->addMenu("&File"); m_actionOpen = m_menuFile->addAction("&Open...", [this]() { const AZStd::vector assetTypes = { @@ -230,9 +223,7 @@ namespace ShaderManagementConsole AtomToolsFramework::AtomToolsDocumentSystemRequestBus::BroadcastResult(result, &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::SaveDocument, documentId); if (!result) { - const QString documentPath = GetDocumentPath(documentId); - const QString status = QString("Document save failed: %1").arg(documentPath); - m_statusMessage->setText(QString("%1").arg(status)); + SetStatusError(tr("Document save failed: %1").arg(GetDocumentPath(documentId))); } }, QKeySequence::Save); @@ -245,8 +236,7 @@ namespace ShaderManagementConsole documentId, AtomToolsFramework::GetSaveFileInfo(documentPath).absoluteFilePath().toUtf8().constData()); if (!result) { - const QString status = QString("Document save failed: %1").arg(documentPath); - m_statusMessage->setText(QString("%1").arg(status)); + SetStatusError(tr("Document save failed: %1").arg(GetDocumentPath(documentId))); } }, QKeySequence::SaveAs); @@ -255,8 +245,7 @@ namespace ShaderManagementConsole AtomToolsFramework::AtomToolsDocumentSystemRequestBus::BroadcastResult(result, &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::SaveAllDocuments); if (!result) { - const QString status = QString("Document save all failed."); - m_statusMessage->setText(QString("%1").arg(status)); + SetStatusError(tr("Document save all failed")); } }); @@ -278,7 +267,7 @@ namespace ShaderManagementConsole m_menuFile->addSeparator(); - m_menuFile->addAction("Run Python...", [this]() { + m_menuFile->addAction("Run &Python...", [this]() { const QString script = QFileDialog::getOpenFileName(this, "Run Script", QString(), QString("*.py")); if (!script.isEmpty()) { @@ -292,7 +281,7 @@ namespace ShaderManagementConsole close(); }, QKeySequence::Quit); - m_menuEdit = m_menuBar->addMenu("&Edit"); + m_menuEdit = menuBar()->addMenu("&Edit"); m_actionUndo = m_menuEdit->addAction("&Undo", [this]() { const AZ::Uuid documentId = GetDocumentIdFromTab(m_tabWidget->currentIndex()); @@ -300,9 +289,7 @@ namespace ShaderManagementConsole AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(result, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::Undo); if (!result) { - const QString documentPath = GetDocumentPath(documentId); - const QString status = QString("Document undo failed: %1").arg(documentPath); - m_statusMessage->setText(QString("%1").arg(status)); + SetStatusError(tr("Document undo failed: %1").arg(GetDocumentPath(documentId))); } }, QKeySequence::Undo); @@ -312,9 +299,7 @@ namespace ShaderManagementConsole AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(result, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::Redo); if (!result) { - const QString documentPath = GetDocumentPath(documentId); - const QString status = QString("Document redo failed: %1").arg(documentPath); - m_statusMessage->setText(QString("%1").arg(status)); + SetStatusError(tr("Document redo failed: %1").arg(GetDocumentPath(documentId))); } }, QKeySequence::Redo); @@ -324,7 +309,7 @@ namespace ShaderManagementConsole }, QKeySequence::Preferences); m_actionSettings->setEnabled(false); - m_menuView = m_menuBar->addMenu("&View"); + m_menuView = menuBar()->addMenu("&View"); m_actionAssetBrowser = m_menuView->addAction("&Asset Browser", [this]() { const AZStd::string label = "Asset Browser"; @@ -347,7 +332,7 @@ namespace ShaderManagementConsole SelectNextTab(); }, Qt::CTRL | Qt::Key_Tab); //QKeySequence::NextChild works as expected but mirroring Previous - m_menuHelp = m_menuBar->addMenu("&Help"); + m_menuHelp = menuBar()->addMenu("&Help"); m_actionHelp = m_menuHelp->addAction("&Help...", [this]() { }); From fb05beffe3c7059f14e0a13f269b8e150ad25456 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Tue, 17 Aug 2021 12:05:51 -0700 Subject: [PATCH 506/803] Change LY_UNITY_BUILD default to "ON" (#3244) Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- cmake/LYWrappers.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/LYWrappers.cmake b/cmake/LYWrappers.cmake index e4398099d1..1a8e805f91 100644 --- a/cmake/LYWrappers.cmake +++ b/cmake/LYWrappers.cmake @@ -6,7 +6,7 @@ # # -set(LY_UNITY_BUILD OFF CACHE BOOL "UNITY builds") +set(LY_UNITY_BUILD ON CACHE BOOL "UNITY builds") include(CMakeFindDependencyMacro) include(cmake/LyAutoGen.cmake) From 0c6a838c6f994614db2e03aedbb153d775fac3b0 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Tue, 17 Aug 2021 13:22:52 -0700 Subject: [PATCH 507/803] fix warnigns after merge Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Editor/ViewportManipulatorController.cpp | 4 ++-- .../Input/QtEventToAzInputManager.cpp | 8 ++++---- .../temp/128x128_RGBA8.tga.streamingimage | Bin 28066 -> 28861 bytes .../Shader/Code/Tests/McppBinderTests.cpp | 2 +- .../Source/Document/AtomToolsDocument.cpp | 14 +++++++------- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/Code/Editor/ViewportManipulatorController.cpp b/Code/Editor/ViewportManipulatorController.cpp index 5282af009f..a67d733cf9 100644 --- a/Code/Editor/ViewportManipulatorController.cpp +++ b/Code/Editor/ViewportManipulatorController.cpp @@ -113,8 +113,8 @@ namespace SandboxEditor windowSize, event.m_windowHandle, &AzFramework::WindowRequestBus::Events::GetClientAreaSize); auto screenPoint = AzFramework::ScreenPoint( - position->m_normalizedPosition.GetX() * windowSize.m_width, - position->m_normalizedPosition.GetY() * windowSize.m_height); + static_cast(position->m_normalizedPosition.GetX() * windowSize.m_width), + static_cast(position->m_normalizedPosition.GetY() * windowSize.m_height)); m_mouseInteraction.m_mousePick.m_screenCoordinates = screenPoint; AZStd::optional ray; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Input/QtEventToAzInputManager.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Input/QtEventToAzInputManager.cpp index b7776238ba..3e6639c29b 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Input/QtEventToAzInputManager.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Input/QtEventToAzInputManager.cpp @@ -300,11 +300,11 @@ namespace AzToolsFramework // Generate movement events based on the pixel delta divided by the DPI scaling factor, to calculate a rough approximation // of cursor movement velocity. movementXChannel->ProcessRawInputEvent( - m_mouseDevice->m_cursorPositionData2D->m_normalizedPositionDelta.GetX() * aznumeric_cast(m_sourceWidget->width()) / - m_sourceWidget->devicePixelRatioF()); + static_cast(m_mouseDevice->m_cursorPositionData2D->m_normalizedPositionDelta.GetX() * aznumeric_cast(m_sourceWidget->width()) / + m_sourceWidget->devicePixelRatioF())); movementYChannel->ProcessRawInputEvent( - m_mouseDevice->m_cursorPositionData2D->m_normalizedPositionDelta.GetY() * aznumeric_cast(m_sourceWidget->height()) / - m_sourceWidget->devicePixelRatioF()); + static_cast(m_mouseDevice->m_cursorPositionData2D->m_normalizedPositionDelta.GetY() * aznumeric_cast(m_sourceWidget->height()) / + m_sourceWidget->devicePixelRatioF())); mouseWheelChannel->ProcessRawInputEvent(0.0f); NotifyUpdateChannelIfNotIdle(systemCursorChannel, nullptr); diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Tests/TestAssets/temp/128x128_RGBA8.tga.streamingimage b/Gems/Atom/Asset/ImageProcessingAtom/Code/Tests/TestAssets/temp/128x128_RGBA8.tga.streamingimage index b867b7cfb19ea2f70157e69cd9534fd8bfb04002..6826f2a76e90456d281de0067934c304f03e7704 100644 GIT binary patch literal 28861 zcmeHQ3tW^{`u=7>gqhS)F|TcyC?QT0t9U^I)HJX_6Q@DM85C0xF|Pp{Fp65bqKFqn z&_+md(Gf2VhJTiH`xB$RzipQpT2}qph=4Is zKB-p+%XF^>2llUseGU&3aiO1O9LSt$vwHB2{sDtG>5oU$n0~m67BP3UX20_k(ZFQ= z_@$OtcYadae%+fF{xL6fS*M|jAs17k;;UZUl9sY)klmSkNjP82g_;Adwt8}lCA&-H z6Iw(Z7xHENtd-yCKC(Gf`|9E~b@L;VZKwI-wL*r8E`>gJ+>Q$^+dK1e>gV(Bk8m4$ z@9(dFbmNn=i$2EV2XaUMetX3P(c7~wTsT-dtmh`>$*)iMZkra;F;x}w*nM#ScXml- zj~(YYzh{zPiB(+4YY{nXY{1%e8;hrPn(lRUkgs}xXxZ_1d-gi$w{Gjk1Krzid-mfo z%Pu{gG_$~WeS9ZB_soX6-IlNV^x(KL_e*=Ud;Bo>=S?2#sz3YWPd)ixv>h%qbU>8L z6C5HOS!mm5s<)q4#YAXc9`yXG5577YdN*SRjyLB*-x#FW@Z^h*UjCa?KT-VtrPD&5 zdF92O7SCy|3unZJnC|3cJ;BF?T)LNj|Iy<-&xJe_`M0u1kK@rHT_=9@?xV+XerS12 zbl?+wF@%ulw> z3w>*~Xx`s(R7jGiyS~UqAZ7B*>q~5nO+}e&GDd@6`LYj;cS|J0qosj*7VWPdBcZxTFKA1=`*=LBBbo*DfyEqi5VYN{n&9k?p|Q<)&Am` zO&fgQbr0}L8Ps`*?W{>348Y6($dj0)q*Fn) zEf?A)-O~4oEe~?8Unjk9lgU0>nojncl3v!7^f22dq?i4H(mORNJz9Rb^!80jPh+Yl zb8q_xN)NJ{80ewpmrD;_eX{0rzD-F_TJc9|KFDf9dbIp<>BUV-@6?p^)GvRO^dPGV z>Cy7brN`_;6Wl|Uo~-#CTK*{M@w!b&kCtC9J+!z9>Cw`J^k`{9db~mtJ|E`tTSUA+ zrGN7D)}P!rIl0$Vy#G`4pP1{>80Am9e?r#!r`LOOp8u!MfAT2je?H=Ierv8fEiaGl zvZK6>ddlkL)cO$>i7n!27UA5OxZbaPG2&=J>+tGtcBFgSTc=34pK8Wn^QW3e{&e%` zpKezEOtbG#K3j>0&%KtNK2u*mCTd2EvSZq)PX?{H;u=m3|JffA=b!5ApNi2O``8e6 zaCNZa=D>At4{XG(IRD%H+sFN_?QKQC(F6URa6qY4@@+Z(tdy~v{GjW-$pE) z?-psrEw~XAN+(JqaJlfY$Nhb#wrIq*^gaR7NNYQL-v!QA{O9*i_rL>w8&5+2rXHFx zMq)kiH0R$?`t~sgCmc{JjrGqp1D5x5=xR^6p6?|&_ST*&eH{i7HuGEm+U8hQ{-quw z!bUz%GO(jR_#NO+nCEl3m!9#TQ0na3B<}nQ=j2~HEY*5`AIA}=FLrkDBdp;owY{W? zr!SV;3s{-R=Q`W_f8!J0BC;zzU&S|c;P`NUYKvs{z8YS_`JZ;#)=F=cM@;(SFLt%! z|Fv(yUJGutvC7>+?7#7H%ovFi4k$t3^UaUNr(NwM@CUk!`#BbTzxE2l^~GDogP*(i z{n|^;q6so54s?qHUN{z=cBO}Cfozby((J~K?gxDU|JfaY`CM_ZkNZsQ0In&7dtul zEx>FW-;k>t(EjehbDbO_1pR5)!nsKjKDBg`3RtP(EuFcBp!?wu^h1@{;J}Ue#${X5 zPHTVsxBCyK->I+$_G!uaZ@dt5y`>W%{I9V`bN`Kn{mwJ{1-}E@6x>L?dPuO}`eHYU zUyp(tYr((JpLw~GH$2dOsgH>I-(0*^GT~+Lf5lm3+jW6VS)V7FGD6S?Zm8?Q4oYLO zWOlH?KldhK@Exo1pSA~lFLwV{!1E_C`_FN=?Mm&B;y5*b=A3Z;6(?$s88hPaIoSUs z;rdE#^vH&Tqz}ULG#1^&VFKTN^gb&1hu{HshY8G?bZU`I{zC=*5VaM1i837nS%0ZCLcE(Oc4xi$pZ8zJ_v%KzMQ!qJBTBY- zu=h8b-I^E7n{|!xYc$sv5BW>MyfpAF*l&HF+Z*nTf9fwI@Z?v>{tr1&e;SM2Br$Ik z0QYquKF!5$;zi;2q6wD|aPCU{Cr@Mkz<%&hS95VsZtXnq4SSCqp5spZWoU(Xz~zoQ zGJx>L`ON;0hm;FAdlAzIE6&uy-b?L$t>>?s2mcR$KV=lV--_wr`=Y&{|M11`O7OXO za>AzT`fkIF5c4#461o#a2@9%{*7@Y_}xh5l4&5|MA5c8*%$@keRG1HK#cF_EJk@$GKq zTVY=i_aom$c_W?!-!G^F7m&X$%5w|%WSHa!6weG~`at$%G~`JaO znFTjy!v3khp%3D$Mez6V4>v;W2P^BhinpyO5aK~}ROE2N`Rgek=pi~e?|2B|Pd2f9 zplaSz;mZ14ZeJGT|HXyC(1(4SiElg3iVL#@{yEvg?f+H@~|PxmAK#Fw#XtK{&lS0z+v z4QmCQO!}b#{$PO_`G7Q;{EG(sr@Up}P5eI(e+8_YuVQ>td;mQxF$ZGf_hE%4jwh z4gO0U_#Z71{CSaHG0qF^z=C}%;J*W7uFnL&jBmZ$+Nq3x|Kaf0;9tLx;itmw2LnqB zGk||McASogn?-e^~N;>XknJ`)cl&8S^9@ zZ@%}{ObqaOeq5EZI9I~g`j_p>=m8vGrL0=Y@wMPT!_JSehOqf=@BGttzI48d&(+pd z8FsHsvE%4|no2Eq|C*5RMbh(N{#^B?c*^gS@0Xn~BKt4@%-s7fFzF-s*L{`G_#}Ts z{2$%K@Qh_og%kg~-($EJ;)i-}ttoYyz^~qQ_?xbv+Y}ST_@;P4?PL3G>wOpelYQZG zlXpkfPJCEuO{Twy?(Fu?T45%>RL}>+hfkel_Fb3?wyFzKhENba^MY{tEruz!l*2E9V6O8|y`kUs}@+q<6m3$kyV zFFmbi{(=0dLGLF0{utw*`p*np{Z-ucQ5#+qdBJ{xC3WA=hz!hh68JFarDDD|E^^u` zXA$vda1(QU-6m(uZDOpyuSSnq1ipa~!zdKNaRK6+{p)9O{V1`oaNWKdix$`4`ydYfjJ?s#60+hH#Z%%x zbRhI0q{S)n2XkvHOkSP9e{c&S9@N4gbP?a_?UQR`AwJ;`C_l)0*dM?@tb5sE4Xl}c zoNVIKg8JQR*_GM5*|)2^xh41%@;SX+F<}Vwp(?DUVDBI_X@WcXhn7b$9s`tbS~x@C zpY+#&1I1aS4-+Mnufg6G7mH@Z1pP2kLirf!!>um`{~@`E_-c?Vr1jr{@6G!i$es*x zsRVqF6e0Rh|H>U;@4q#FzxDkd(ue6L=)=wIY-5QendFHz>9luB!58ei^X2nJ#9!Hd zhHHvaSF3U0AKBRo^6xX21w=s~YIELWeA4&=^w%zp*edW(@f7FBM*3w7Snvlp{}q?4 zY;$lc_ydXu6&0>_H@bNu9+3Yg{_VKe2D{8!(C82BIRCWKGg`N`^6%o{-mca4>4LqR zk>3sP<-UgaC;wvbkjtY2+|9(lbJy$+fb!%S;P=+emd_7<(-nNm^(%?*n=Jz{9wU4t z5BJ0MyH;J4k-DL=lkdM z$Fkn$i~aWRQM`bAH(4sckF140zAF7hY^=$2{S^2CUlboeXGO_Q@C|zw`~mphord<1 z73S^m2hfMub+fm^-{+ahzd|2krw3&v5#KC7h>acjSHjF6sNw$=El3|$2>u`;At6@6 z-N^RdV$+x(%D5%z8FA?`R{q^vyRR8_{bozjm!hH~`KZ3`?Sg=Xe7;DppZx~f!7n{e z4}RCiqP^-)%SgNrp!{P5k05t*;PzR$qX?Je-@4QCT9}0LAJT`av*bUn1g<|fM-SMF z|Bm9x#6YqSx!hIC*R}Q)*)n^VO2z;A_WpDHH~5O3uv3iumrhImASC+~_%EyJQcnEe zxsVP2pJ$}}k@z(3%S!SHZgp!8#+!h(1sfT^Rr79y0LNw|W!}O|A4ivMFRhxP9R)`PfJnUn)U;JwEsSBK_>Vm{^f}G zZw!R}Kj2@E194*%=0LR5^T3~cUE(cStLrx<^ge_ObY$;0ThjXyKEIFR$8^Ep6TWrH zz1;}3le~oM?`)bb>0uJ>tMMv#aF9xouL-e;`b#Xtd8V2Fa=!L+eEh-f4K*We&|{xd zz6!b`%qGD;%{2Zb{=Pay{I4+6d<5a*oUEh)z%;)=`2B_Jgm#)wAe<0R=O>wIKAZ5k z!Aw7BzU3WYpJ##bM|{Hln4T6_lKnIO5f9pn3ex7`kMzNaPv57BJjOrhSB&$4edCYT zLx``rp{#we`xPg`Gc&_`_r)L0mlFO&$J%9x_k=GVbYI!>dP+;0Pa#}ma)*Ct7ewQ0 z!VNXoQzU<%4nH4XMfkto-~XI`-3zukRr1sqByR=yxO+7?$z!CA$GEC7hzGH;mk)z% z{82tk_|qJQUq?Pb_`@ZPPs*gqa5#OL+ zBXTT}=<(OcfBS#tKX@R+R{lrMWqe!t-;~7k!^;1G4;XIb{{Xw*%767`VCVzo_l*A! zWs*%P|2zC!O2l%RjXUuVIx6m71^G~cM*fchtVwAjUW4gKB(U`WgOZ z@c*i~HM5}(!lyUcKlmYiA^U%0U{y-X>oVB?AbW*EE{_`{@Hxur|JNt7cB}v2`#!bH zf~@}kVsX`-K&S-e`^5L1(yE(*igrO(|KD&YC#+?8O3TZ9Xt{$c?7x9tLng#a{Nukr z{y*vuYGC{_8xP_?A|f`{{7vu*kM-R=X?#fb`qd%gubZdU|L@;SSm9~)|GGu2z0vNGxwmc`x3V$+Q?zD$ z3h^Ha;OqT>Z!!M$`l6!QZ-8I$N%4xu& zz|g0?=hjj>=uuylGd=LSV-V$kQU~x~hjhtNhWwx6Kk|V``|rOE*K^p7VCzKka9XXl z{?>lU7qVmz%6Cj*VX?O^%970?-8{)2K!3=&B4F@M_5vJQr~`i!x_Mgjzf5iLiUDu| z73|^9!2`GGA zCEy$U()mROv-#Ct;0yLj<3G8)yT??2*lX3DQ8fN*0sfMwp&k6wcvK2Px2+()9fN56 zM|>aKM&~;Q(R{dEUSzoPIq~l}tN&rg&D36dWkZ+*?eU0zQdha2uU%c@08I8FkxKvj z^MQL>yZ5kOM*N$?VuSBjlt@m6C_Lk<)}J$(Xuv1?+o=#A&-LdeSgxKgiw)&kUmT6`o{|m>p7&=p#$M1^*%B{|O1| zzsg|zS-pk)FBStpDaHTF-Y! zt}hxtm|>d#AwCy`=a`@$vuOT@_}sKWz(JIsU^c*TKzGd)*spyIC)pdafAy5tf)%76#0Tyd8`v{MVaeX@P4hn$6}6UL z%^4deWkON|8}B&D^&$)A3NcI*=SVuZ3Dhwk90lKfuhiU zKinDBFD;Gq%T1v#ih1MOP2!j4BLNMoV_@IVADW*aes`|iO!^T+>$ikI({CXDXVLtx zR3SH9Jxu(!Ppc_9lPPtR8)_~SPD`Wlkkn0YXt>!H`rtUL4E|Cql^ggvlx{l8h70{G zmg@iT_)v$A(%QNT@5AXL_-d`)k~S}S()_Qk!jf?Bo02U%!%xEA$DA8c ze$t!#AMt;37xV%A(|ix%kJric#_W^cG~Z*Yh)qb3gMUCf)f1pSAwHx7+KV5=d$oGp zK&C$w@6oLG?#%Rq_(Hg^?IK>M@VqfZ@b_xOdoec>^S?jxZROqiZO;u@Irdn_AuE2~ z4t(}o6GQhafFJh=*-)W?OWWS3iY=*t3rIA07!arBR)LHxH*8;W=Yb2TrI67(TM$Pd7G-a^JF z$w&Hd=zWG?Uv?wJEw9LY@gs(<`f&9q^h1$WNbA4E|IIJk`Ubv`R!I30u+egD)&77N z(hF(+SS-mi*Hv*ZI$V9ako+wt-fFJD3x9ES?Ip@5#JRkZzbDp3cTWeO(g%=Cl!(81oF#K8*7jUb<{z#5fG zX#;=n{94oY-jp6#kK1$ZD`!9C54zjr+zgCK%b@#{KY00BX77|A5P##mn0?dxNnqd! zO2#L}2RGRFx@ioPd}QxC7BNivAOZd)6MV;{6_S4-zE24LA-$0DN8 zV?GJyZ!G^D`Y%b@MpVoJE6%Cq?mi)*!^g*>@Cc~7^kv=2@ zG5#r^C%z*Gv3ByWPzRM?cg8o1@0NyM&1HHs`~~r!kf>2T#p#N@&1e2)d$;o3)c2$L zfs9kMj#-j%$q5%AJy5>TT;Mx{o)7wsBb^zaqz_Uk#AI)V>HR^k@nLL#S6j(sh7?o9+c90DDl646WM=yA&rN{z@P6B_`gi~1o$?eDHId`m#AJ# zytQ6g`YHH-JEM-~pNQ|T4h#G{pT~Nefd9exKacq~!j}$mA0_MST}ZzOpD)sWv=W%^ zNBE0fqz}=I-^xVgq0K2dJAo-*(^V#_K3dE4f#SCoeCI4={8K(m{$SPgk}ap84^-bl zc;OhvFY!%y>X0A#CV!!HWtjPQwQ8W0Ve0SNh6K&i;Jd;6tq|WeDy0&?)I$4Z8uPiP zc>Vt#7jsKeUViBQ;&z>ElC_h3NgvG62X`CdFGh$DilX{PeIR|6xaAd38p!m4@)huJ zoIR5GPcNi+0sA+;8xH(-dLh+IO5BRgYv#1Y{n84_KE%M;?*hl9UlRO9UcGV0>Qy7B z#bne8`jKZ==4S}}U#9vJ;%i@a8^Qi*{6To#e*e??&IQq=KZN&xNc`8kSnAmQMoRb@lW|0(gW3!$tBQ_ zaXzHqI*UdXGn(lG`E%ks()UNcE9PocqaWe>rItVPjr2j&SrlAkF@Nhq{S9-6e@8y| zEBrfd^Q%5$ZYA=C)s6brPV~d{w1SK)PPi-SgQ9t681lhFtABXeiTF+{6#N71Ke!L$ zTZk9HlZLe|2>{>ZFNp7$F^q4DACj%b=7p2n2>jE0H`g=IykZ9P_cY!>_*bUC)5dq& z+Zk7AK9cNz!+hrdb4QgAAiiUCjQ`^y6@v(W@LuZ6sreh6t$5=CZU^{xA^$_|>*KYg z4=!{+u98=#%|1PBmw|Vo=Mn!)Ca2`@-1fbdUuAqqN#9-Ds(k2u$^IjUGktJ|JcP&g zC;rFzki5tT6aAclw`zRIK6I59zK<<1@_+4rwf23$=3 z;bH$H6aA2qc5DOF2W$Z8VVh}!{a)@$@uJ?W9OwxC5zk3p@Llik!u&h=JE`8R3?9h% zr~VReEv}z9tPREc%YuF&-cKLhcI3=G8CS@Eh{1nM2;-mpsdy`|oU0N1eO(ULtBB8} ziHvWWFMSw)Ncx2Kcg73+J6qf1#tQ!5neIpJZ;j%Fe1M)u{7>=|{DBX>k9JFgDs*59 z{6Vz9uXc+iF~AM{!~RJgZLLP>-I4K6@@jP!-p#(`W8=0e7s8-h*-jMvg{7g|ne2!B zxeX`l*5e_6`)m36cVGW#{$S5-pPq5-{YHP$S-g3AOaapm-mFyibYOf_f8^o7zz%|c zza;2K&tiU<^D5YP`eh-Wn-S4DO#w_FpIHOD=B?_ThE}ApaxG<>v9@ zhcNyr{t%y`L!ck}4bE1q9)xzo2Iqr9d!kb5NqpA}eByk~2zSPR7V%lhD~I)?8lxR8MRZ{Kdr*DyZ+ zUE}w^oByAC9>tG`^9cuT^K|%&M*Zl(Wt!F&Z{VG9Bhn9NyHz7+7H3@PivBF-jY@av zs+VViZ|dKze7&;I)6D(}W4vd6svq^T^)RKJu zeZimdh(GPf!1iol7zf0iq6?!_Z81qeHKj_WqgZ?P;qzr8?V;*?zR4uGoKEpC^8MAlq*=$$h+x z_Mara%=RBna>xE-;OYI?ev_fD!hU0|`Wfsu!+uiXej1Bzhz;9+Lh(k44F}KR_Xu3> zB$?U!sMKtK-v599&!h4_kNrQF3SwF@K8%Jj9IMyQ!t-fAS7JZfuY1TL#~u4|&3V%F zFxDTrSRo|&^|RT2tmvp5ciNA)XCd}uVZY7Ec@=|5-jB7cKdK(!?Q_`v+T~bLqWxBz z#x>CXy2#@pxL=}0m*j^5;)Sy*lKNj#}&vEIGZF_Otd8Rc9U#q5UZ3 zyV-uExD&#DH1X|2Y(LulvR%Udvztf!h5d(Cd}D9oY3vt`NI${$n_b!fzPm}2=jfjb zr~QN<&tdW}pS9SX_LnRl$o3CZ49b$x{(>oO9`29Y3TF=eQElUG)sIK*Mfm*+|FyQ( z<1cZno_{>-(`a}}9^aqs_gM^n%~-MD^;R7AbDS0AH9-C!vRJ+TIYU4c^+)~Zv_Iz% z_T%)~jQtwo>-8o5`vz=8`QF}h=B=oMtS$J0ew>5mSIs@~U3<41{dfjp%@*XqmD{={ z3-$D+Y`@JZbMJGfB@yvebMzY8Pw^p>ucl}@_E*)K_D*5)FQ1j;u110F!k5^73F1eC zdTRe>*dKv)S4MWy)yBO?vU0UCwx|rm-a94)th`pLfv9$xm@}i>`%B;((*l_KTt1d z(sGuPY}5}+m+h;WqsR6@lQBcs53;k*=BL6@KWf_eCaWht9)kLC90+rw`teq$$bYC& z5GZ~wDd5X?nFj_5{#T`va|LOr|7lCuXfzn2`(W`OB^=IO2id=b1zr7Ag_-Ji$$qI| zK%WU$)CG6D7ImVI_(l2d?_aO+-AJ1+w37FD{(f0(m}!6I$E@Cc{khkd zQT^=hScbR5e-NHc#g8a~ApcACkP1;{H*ZtY0FqawR)>mTL@^fr2pbF@9?#BZ^=)tB ze26E{Pek!6`s3uha-qJl>K{}epVG3lEOj-t^EDl(i=GY>>eU_a;eYS?lzUq7QLRLa z^{y(2zyJ1ess~N-=u&Q9Vj2HNW3&f^h5V%d#P7CQ zRL>#{BK-$6l7R5J z>|d!I+X?bveV+Uu%6kmyVZd0=r+5x=4W~9TT%CC%gx2#dC#imCbqsb>>S_I+ucq~R zs^`V}8W!w-ZGYTu;CY`!%WPUt#|YbW|IB`Ss+ZYNwbp?88TI*0wmwe&kJdlmpTyQb zZ@~Wns>gQ)Mm>!!_>2uzt8Jg_7Ujrv3ErZ+cKqCYYnu|AFUYOF`{ zwFq{rR^wOuvA)Pj>aqUFajEC9o=jMm$bX0b!OH2Qz*xW3R%$FITD#=%FT6L_tkGjV zSyR1*%?EclynGg|7Zto+l6wmE1ltk+XuT-Om#q&`{KI;&=4E@<9~A$ve5{djb5A>u zXnOvznbYA3Nqr}Fw(3KO2=jB8&!_wf^&RHF^=G&o_a}MxOlFw+gVt-#ti${b)@K|y z-=Ot7<8=d@pN&I4L-VoKN7#I9XRO#@xUIZ(l*ZfjE?vq`3%GI*n@=HsPV;NVEX%*KofZ2pS!RY_jGa>pDdKjpI| zf5BqNi}|RkdG>=z{=JxQru9cF-VsCd3*YF`eoVuBF6kGRZ@7w<{eh&uY$rG>P_jWKo+_f6#V|>^=sqN>e z51M&o0LJ4gb!>ZjUf=>3>-*S^?mOvkho`uce8_)2jt`^#=@TXNJR0xpsFAt#omy76 zujWPMyV!qv^SUsX$Mc;p>nYE_HP*%#Lh*c;^11lFzbo73l-53MU(F2UqbBXi0AW0G zYS(J#t{Nny5u*6PE;qV)Q~#(`>d^RRv|p}WPgg#z;O5rt=Iq{+z2sSj{?{TuC<$csbkzUI2Q*KO z-E`@|>X$B1|A(qosKE+O=y8@imWbce5v?^~K1x|Hy}+^ghk=R zkuPxCu!~~KXLozk^-v#`o%ZmQ@ci+m&Uk+hbl3&1txyk;kNZjCZ@&~_Jx0&F(D|lB z%-=3}#_Ph4=+dEh|4yvpHk3@scSuPhk%S*u$r0jsBn@!Yf1CGKgL z2s^YeDBFLVXqIj6bs@C8t9{sXwNhGrVaLQ*7q=koi$8cU9(Ub4B>2qZztAlF)aw5M D1ff2g literal 28066 zcmeHw3tUvy+Www_jG0lKM3T}r0q0=BDqi7`=Dv~mQ43nCrM-=cf zB48sNjRQ{PWiZ4M%QDSUw7?RRDKCtmj)o%_9p?YMdpYVsJ$?PNb2{G_zkWZ@Gi%T6 zz1H)-&-<>m-n9?Mah%ipf+1`2d!%I!bJ^sa^oYLfy(uHV%TVEczi2)X?Y zdpzG13{KTgS=#*4mR*gV*1q=r7fBJz9v$H`?0DLYWXsF>+O&6{Z}V-_LR_!mBCMm% zw7+{xb6%I|yR-;6F8qh&xb*Y7?M|OJzO;Dt^>?PHI?oKkV}-vUI1zEj=WV!%lRM{B zXMCM>ZH#P0(?4F>UbpMJcR#`Hhj9D<@ym)R!MwQdzu#N+LhlXo!#^GE>!uBVBtsE@ z$M4|x=Wmrr@A#bKMn0DMqRQv{qIS`76GyFCyS{AZqqB$Xe?BPEPq6IZd%d6DJ92H| z`cI$gwE2loCM-Mg@WMGILF2j7nEUHT?ii}S#^f(M z`M>BpTttN546nNgB7`i$?Xmigjw#}&D~CVdbLHQE+#hi@D;A$W$VI&Ryid;EzqG&l zZ(RoplJ_i~8UEOdeYQ0F&wQvfRuyi#vMKj28W(<|Df3$E&+T?D{ITf2ooxL%ZXMoj z+V=Nae~#-TYT{!?-$jej39&x^$-9IbwA`~35z{|)PMts8H#_>xmlqfLt{#_uBC*tt zKQ1Er_{XVt?>ILyV%93t%!bvAp4v7s<-IG4`gezZyE>foy7dE7NB;U8!S())12?kf ziY@4&8MecH(;^=J_`7v09ynyvjHFSXXxcs^DP+W>>GpS=`n_SB9)9xD5%0TE5-~I6L|MKr((2%9k3ts*}lcqYbch>GI z$HmArxQG{jX*qcpGZJzmzwWf^v({g|M}8IVQJ!-8E)N|3-sbXNcYH43Mh=suPWXKW zifrYshAX_s=T7(d-1#1#KX8xF@1LRE{rUg+-{(fYvwXvYvz#tBr0$Pgz1AiA#pUxR zhVcga;F}9a6rUdY-iB>K2|w)|@{j$|vmSrxkIr@@Hv5dadKVMy%0&pjy?*x279q@b z4A;HOoh?DI==;!-pnIn6Xt{UVey@&5@6{1F;5|Aby+0l4de4ra<+pdlO4FogH$ z2wHx7M=;E+5x)hoIe>N;&&qvuY|K~(_iLspnKL~t%-e6HTkR+Ge3fgkP zzu4#biJm8HE#n>%0LKg#Od)J9;M|13Gi6*9aw56CkaH6RN7-W}K@1n%xLy+ExV{}X z=4bm`l4$<-l+BzAem^j#T`G^|DQ0JSp5>|fu6Q81Tv^MWcfp@_JpZKpI_RYF&GxTR`duy_ISWh;|B=?v^WP_);BZob>Ao{@jK8XcxLH|9^7KzT;KxEuS;-L)rmITCf_`do4Cs5CLZ|6n4`x#i-H{2 z_wA5!w6e2kX8`M~>)4_p8-;J}@TA-dz%X%A+f%wAXSTf|Mxx=5~7i zc~hEoVlMb+uM6$B@b;omHwwvKf)@<9*glkJyR@lCO)l2;z1otF045-K(xtsfz(=7C>;J|Q;ZhaWvFwv3h+PL`#{W& z(>+ANAtQQO%L=&h1IQkF2$qH}_9YxPq>0Cc;Wd85cX&{6RB2Tk?qIn2d4|FFZFs_S zj92yD3b3XTiXUkr~^gN1|0?pt~geB2m`Yn(uTWWPr zyQn{F27U_mqJTX-Ca|BfZ(gw_5B94_X)%kSFJ9Xh9$|W-Z2WK64`$yP9Ub=V${qNi zI^~=z^{>MEoTP{I0bA)a$G~q_&T1=?`E@9%TXW`f#;;K(4(U+>ev84UXE*RI4jaJu zF2ML(i+T&E4R4Cs0sh-gbr}kNg)_&1|1$#wqh>^hpq-nmVEiwSD-0)o6C)4ID)sad z98Rj^@%$;lQ9Ho5C8_OHYM&nkJ-7`gMS|}tmms=ciT3yju#fJdksrk!lbdZ1-*b9lQ{=WZMabI`eQV~z%%Z(qsBBc-~Lk9YGH+_rR0`tj${3&!`l zn|!;0@3NF8S9<;mtI@~%!IC8H#m_}g_3GwgH5N&RJq8TE&Cl=kAbwwcmhsR0RVIF8 zL<#)=bCLIqp5V7o94{w4K=e^uK`8P6?o`IVbkWmONe@=cV*JN0inckU@tqz^{x6xH zvFf8Z1@wRMYrMZt@3Y8z2Kd$_D!_MVNzCD-gW-ylTHTD1SNFpIQ^`IR>So=90amhy z)WUGmlUm)2Pg?gjKiV$UW#}o7lxDN;S&?;EGukP>fPUShf|R3yn^#njKH~c(R{|>w> zm*;<^u9s>T+-gfGjezvkAS^PNgd*M6L;UxI8u}GF0&G>$0*{B)B_Xah?ZaJ1D zBm8}9TFDI30~&9uu~586NA@s4rWK_33sj`{;fZ;{BM0j7arH2_Mwl#;h zKjPf28|*=45_9UKUa$w^OQDQV{hFS)Zf`x`_7EJ%$x4ZLBfYU2y?y*1iskuUjQN$p z+eaezjcu9(z6+3VgKt^vXl4&Fh<8RGnK(6?*~2S{&twmq7A7>!fj*F4!hFQLbBOQn zc)kfA-3t4Fzptw-HjqA?-dA#s^1~rDgZ7bqTs~GZW96CcJil;%Vbkf7x{MS3M7tY? z)KGq4ySU^+#tBc(Zcnx#KJ;#}HvKrK%2Q;w?`{C!VtZro$*oyEcwAvw%Gn#o94*dj zGm_esz%ACReT$E_3A%B;#%5_5R(#wgn0_y%r9gM>>{aA%qG-Aw(s{1_2kS88b1`Hu z3bk2NbHKWn^qRL1*h6J8@heHC{t#cE>A)}inb!+^Q20Lh1SWeRf6kc6_@#UXP!~Ur z;pK5lL)DFD)5L+B`(6!ix8)%62YlTe@Cdc1Zu!zLSE^1lo1PF@w*?feu+sckspj*? zpFLmtpX&kqecjq6THfC)Dy;o`K9CSU&N59*`KhtUM;824Y<%3sX|AM4M)3W{aN>KK z>(j`8fhF%w;rVx^{EX~jgPPex$Bm@tg|gC2hRGicFc9z!efaJs-!%uAK6HV9QT|~4 zv7~7Z_$U9R_+Yz`P&emHKY@c^dqeDmnJYbkcQ+ViLe75uaxv{d+U?c$A~F7LAw(FZ zK>WWffBqk1TZ~Y5`}dnp=cT7H`#`woS}a%kRvvYk&f5p{ywP-pkJq~!I#(0lwO?Q0 z@gz&;A&TFX#XO&Shdq?72Zq1%`p{_BZCc3qCjTHlm%h&ME6bjqN_@W+!s8>OW(0?* z6B|vVWrd^Lu^B+Wt!_^%)gD^-m+Kw17DmhrhHuwy`MLpw+~m!X9%y3ONftyy^x-f zJ#0;5_OZs0v5M^F>&;9*NY4qM{(|8y@NcrOt3Q%Hj29E%M!ihZV)1=rbWRZX&9RU^ z*soo#Z0E%I)f3sNbq-L3*po)WDk+*=EfbXHxr**D1QK*rgbXfv)z$zvkxZ`zw^ThuQ)>U3$?1z z6fwB4`&IBw@fO$|@Ms~mSCAfnesdSWmA-)m?VEGKr&^_=^{1nrx8(=OAG4<|(LycQ zUstCDtzuwod(sccz0c5YzH`S}CW~plruX)dMGcFE9++GyKQZEig;9j3@%|1h%UwWt zvTMhU(nZAY9v$=o?G46`8(}|^%)()w?rcRkMsR&_H&y(Trxo)F6DJc{sw!4r z4f!bi)%?XK^5+#t2JIWak@(JkpJ5gs5*wFJXZ%vWtOmi+BYDj00r`8dR~~O4J+U68 zQkhL&ZR)!FuUlcI^|Z)Hm8uQ*@@HO2!oY5nA1D-&ZMY@cu#$8)!WF9xhTbAS_i^Vg zxzhFhy}i9(miev@1)sFurT6ysd25s}&p*v)$sST?`gS6Fpm;@Cznrzx^8(7g(o_3n zSBJl!{fhMAv@6-a0bgi5<=YT?cC47S1(56wS2UFIbD zqz5LGMuUi-XC2#4Uu_>!lh|Bqu0727i@ z-9K!FmGqVTJ8m3nC;d%?e}_Jc?}x3ZAbo~?sQR?a&9jEBxJ>atg?0&dWm`b)!WN1L zkr5H|C0vPCk+7Pd&-L%$-@8wH;`@>-T@Si_Li;gH>z^Bl8k(l@=2kI(tRa0 z`>%B;=C7d3T)IBDdo%d1#CXCSOxek~JpbQjTau_fabj*>6WVFL5_GF3_~ZKU71n~# zFZ}>b13R(nX+Hy4^^l-0FTlKz&j(bh*|S{*39A(e>3qINeD!#y>qT{8w^px39GW+NnQimtC$R z{x7*wf9dyZSI*6L-DKkZ-JsX&k*^_A{f>O?-_7rDylFQ=)R6{KFPnX+0ZIHR*Y@uU%n1816EZ z@ZiVMzILJCmzbXueppyb{0Go{Za%P70P^wQ6zBo*G2jv3huWV@1OK@^|6u`_rGyKx zUPtYTlY#Ny;iU6XgtHegOzWkDcjft}yTX2G{fzMOz4$#`LhC7n>rK9^UGaOEe^={) zTN=)#iT^PhI={Pt+W+hI{@3iGX|2=ca@PygU$e<%x_V~q!v0|k`&0ZQeyaC_EZ}P= zCmbUD**|pDZpCVpo^am#xqN%ajjt>t{Lbq-;-1{Ga3bE(ophYX^RQmH)qk+{;q8Tl_QoxXFJtoF6|){1e|T z4IfIy8`A#o@ZT(T@*V5cpXCE4^VKsT8_=-?E~G%-OT@XST2no=pIM;AM8PYp`r%gUp;OT=6m$}wu_r)k3QFN z9OZvLMS7$Cx>FzS@iff$|Ci){HjdMA;;xSV*e;igzmXP!{~U|iT$_0LxJRlrystmy zL(^5Nupf+JK38)C{mEazJXB`|L3bCvEG*+wnUpv{2L6`irymT&s0wXdY*gf z>9f2))BF#7>0?G+BpgTcKN&t)G4tZ3(Z25SH2)*4U%_7=Py2Cz#)Ep`f$s4%|C9OX z^=A*BC3}dc`Ja!s-q3Vo~ z8k6aoSt>aa?gM|1r~y>fmV4-}xn=%CYBCR*pa(~`g{2Z+SGmT}*qo@|zB&x;+x%(% z2YX0d{Wjq;f0}O*jvG(c_w^@#1iy))eHo_tA7Nit;y=*;HTW~}FX2o@Ew#hEh;LOy zM5Gh9BwZDp{drfYu3>dWMK>qQY&XOMTK|E38;5mc{L%h2_|;Dx2EM@`t^W|ei>5L@ zDgL0{n7iOC@fqI_`Xuw#8$Z>ZHH{wFDW2B5ee^~{m62gu|A9RiFCW`Dc{Hx4`Jeog_1wNJurXo=kWKI%jG?{ga`VQzw6-dS5A}{9LX&U zp!FYfV`60WXVSt7@Jaherbd-|-zE=zMP8Xdb|>|qH!^<-Zyy1)o`UAcrP0h@X#K~m zN>oRO5Z>lb>%q8Q9nzERW1D|4*5~p2i9Oqd6*c8<3!wEJWQSPqnf#r#@azxKsQ`us_0U z-X^S#-wOMbfZuKD^nI=*PJztNu|d(bA39>|J}XZGbxCQR$Ugs+~=hCOJtG(KYB zmP^^?!Dl;aY5WM=uXBhG(ph8=oKT|wkLL&1;W&F1!!GeWoX%{oPwSET=yTwEeS^;2 ztZw?bJpahl!|?YZH74+V?jZP{dN_dekMPm09)%Tohk1WD!{0yAO2Pl(fMSf72?S;( z0K-0L{TEQ39M0^+g7sg*lZHt3)~GVX`x-ykPhvo4W*@ZvOW*GzTR_1}Bf54j*8NIH=9Iq5@xLq$dJHjGcQA4GRU@KYO2? zad8y!tJRVo5dXO;xE`3+gJnKO!>)AMF#w%y@>zuP|e zd~|{5&EIS0oJT%+Fo3@wm*3oSDXmBP)E|N2-}%kz#-Gabw@e*1nDRLdaNQx|e@x&c zOTr;@ZF9=89q@nfzZ3Zo*~h0Jz#a<61U4Ama&+cK^@odq!9VGz3GIJ-gJIs^VJ|a7 zJY4JG*J^3MAMR_- zU&OE+`~9+_GGkdz4%tU3*#r6aciV{X%+kz5#RkG>z6747EhT*bw*B%0;mpz;%kfHK z?;>OK*_Gv^=4Doqe{td>tId+JXVf#9)np&yf--B%RbiiC@5~d#m$1Mtw>JrOF+DQD zC+wx5&~9(yK92Ep-~xLK-d+>!IWdrL&$laVmo=U--D7~kZ$Wd)HM3?@>RUesQvBvL zwdyNXY57~GO#;4l5_Buf2f_ba%0RMTojFnY{f_dUTQ@5M9enT21^;=URz4>f%wdbA-&gTQNBnx|6Sg{OUWL37na#} zWdX-$-mr%<>!FW;=Vg{s{z&|vC|gPG)s#QL-EHQtSB{-IFSDA)TiCnIYB| zic8;X{+{~Qg+R*Bxq=k=xkG82(%*{V`Gxx{t3NH@v}JQlAg$NwYSoG(TgpG#vUyS< z~<58&TpUww9dZA;4LCBWdH;Y%jp6GZKs&O&sYAczqjVQHEx|B zNV$RO+9g>hC_c3JHdH+GAmjfj+#m994erkKs|^l0)A|$PANPU(d0C#s7xDk&myCZ0KCxG`Jza0}qWQN5 z?Zv_2U7$LW8+Ek3w&&s>f#$*QLNLk=o@MT~Ew8my;qO%M(7UM2s+|je2j7%WLho%G z-{t+iitK~@{p0kNLFE6ueH7X&O0o!N*^9CM#Pu$+?#}B#_&Tkh5Z`+~r`pH9#FnU z_OSE~#y7=p=z}tTJj0}iWDiq=%JU82zwK1`x4AiGR8O?S{~de}XbTMf!MD@|f;$Vs zjLp_lUNqi>ow%^yrSGl%{kLKv7oF}Lyzb_CCwIZcOWLNK(++#^aX~&0e`q4!x)NM|kmT;2*dT@=M}BJr@2yFRMCZ z)$%wo_|HsYeAD^}>HYe5z&H4(`flP|x0u@#Q=H{V_Ct8Xd*Ht~=O+GO0r-diJFZ_h zAN<2U==X5Fa%CLjpYEqAXi+YCBaQ4Kknw9*%nv6$u<-g#`tVi=@jWY$=4Yh$69*BV z6iD@3I^=`U^ZYIFck+*X;J#wuY05x{e|Hgteba2Uc;yn`@ONi!?Y17jBcA_Oet+xr zqz|{xC#4*-2Z|RGA8SPq=WG+jZ>k>^7nRutcLd)vGfOF-6hhx$>dE|_<`>WlYxp4E z->Z4OD700){sQ5wYSKsOfpzvPJpb33e%R#k6Bz$gKgsnjlP4<~K8*b_;#)n9_|NgQ zBt7lGAIBJO;pE9Y|7d5|Crsr1-;?$`xqQ2PPAKD>?x(4>E2fWR*qitTju=e-e*ye{ z>8FAJkCqXh6iD@1qz3_y5dSfOG(RJMm$fPXw^!2Ut2N&+*?9u}tcv3#;W0lLh2+qvbmgQV0`xY13tWQ74`}+xsACUWs z!4LENSJ8PH_`mf9Pp0>D-bz?dRx!p0{Laj(4i0&(7wP@0gBahmUQPMm#K4T8ImKDm zX?{%nM+`;$hyT<1IFE;+q+g$N6Hg3ceBZcUq3~z=Px~Kq{VTqR|1lT9=VD(jzePT> zM;h{j3xU00uf+dzkH8*~FMbGqNgsSfz~GnqqpM9(JRvOK*?hI$i`Lgbze3E79c5Sl z!sly^kqSBH=YMGY{!iOO>-$suxILc`ac5^|9mw${z3{PB$UV4h)0(mzJH->&hurgl zm1F0WWu2z^hq%aI;Vof&Q+$Em%lma?_;u(B@inM3^uIXk^d{_Q16K@wf(x1n|EK*B zY9IVK>;e2cuwNI%1Ly&r52f}2?o9t_{fn?qTi~~BUc{#c^Mf93z^}pXN%hyd<`j8n zLHYjUSM9uB>zeIK2`4?++_IAIk4deN!=F!)K0^MuNVy#6x&i)+{riu8egP-=r}ar^ z?qu30w~d#GJ281j(+B+c%ItD^dv2wv*v>FlXp?soGR)hL-7bGvC@iP;DA*J6=`Q5< z5TqyuoL_TK<2|e;?rOcYPy9@B?vKUudZ8Jm17&|lT_IDdrmC?CbS z45j|7hK|AcLzf^2p3|S5KcegDyxEk;*m;xlQF}db{zUhplbX&GhEGiIUR!y%axo zKF5;ur5~NoTR)NYzdpMz9Oo~DTi@o-V+rQ!>HJ=AZs#JL$3p)r4X-St{_lL3KYtf= z%*gPzdG>GVy!{#j&con5^@d5T|86=1S@O zj5p5DdetqoGW&`A&Eo-n*PmFD*@@@3!q8tKLH#<;t5AP&yiM}Aq3nFZE6ajI=zL1? zEY|wk^~J3Q$BFJDmq+u*!W z7?0}=)L+qbx}MIL|FDjoAKh75pH1flOXAr1l48T*BsyQT;zgV%!TF)Bt9pgd`GN>3 zt2bX7x#H`rpU~c*?;d>vr)YrdF68Mo&S+1zC~GyG?Xb0P<#BOz zwS8SB@q2a?@!d{;?PR}==&r8hZB|cT40{1KEec>*y2xcH>g&zH&gc93qrS4|P&zNC zYNYpfcqT94^DVhtF}^c*ASZi?wlnD!j<@xn^awleP#B(vdUtPGPB_)GPjju$J{V5* z>J@9KUVWN)C-|lF3fB(e`m^PtlMR`N==__#e#3BqQ&+x!-je%pKH;i|Q$Byb0QG`< zXgp9q>>){|@u2e|$FtaZft{6ZIq04#Z!)VV?zpk-RH`4J)|KJ9@Y7vUFKBv_Oa9Dj z&Vm54Zv_f~WvKsF_@%o&1wA$x`ad_zm(}Zznz5L#_x(7|*Gl!kz><+dTrEm z52;y0<=Zm5`P?+|`mw0jh^Rq*{vThjeSWOd1&#Q9vJcf{ljg!Fe7*CLNtRRCyT z34gMH;bH?$c;oNVUeqsQJd)wRgzXL8E(so=%%49JiJY8%_kPo_)(>igW=&fS`Ols` zdo)+}=b}Dvg>`)cs~6n8gy9Bb>@sZktLDFedcm~|Q6JnZgs`9U&rbfR2gB@zum3~; z)6sv_``qY%5MS>%?q>fNq8{X&beyCAm-nLcz_#2S% zqDCnBH`FJb*SO@Dw?#ckvW4nLE`EagA=Gz}{iA#&aYrKhkNP39e_+*IKf>KnAHvsz ztDfa_P60n}3wRCvRjDE(J7d3Bbs+Nu>0f^ofJ8ou{$YRjAoP#=mot&?Z#>0wU}L3r z6ZU&L#Zx?zVSo4f*I4hhbc`pxm&m*g_A6Xh&Rxpab7Ft~_t$G+KQ2ha>SwUgKHFAa z?s5e66xCSa$99OiDu?ZtAFu4Vk@iFKCS!jb`{ks6wEsD+8}`GoKTi5*!uUMNnY()> z9rZee{-XRv@c?%K^Uw936#v{;%jLs`XD@}uYPA&qB&bi)__O^i%5SipX)KOqnDQC) z*LXUQt#=QpK|KT3H?M!=Ha6rLZE3YV;SlXt;gvvr1V2*!0`?1qy^Z!p+-T)0yqX;Q zkDSnk{YQ?=c%AJxa&YVOcvt7qudtt-Y{CAb(pIkNp`SV_ko2C`i)-@P{$b~8>^EQo zpmZMF51{x*_}xH;rHg9(%)lYeY=4O2AGU`hMcnM8v>!<8FXLambN<ofKH*nV7&Wx^qvZ`JerFE%d+zOV!9D_B2?sHrs2di(KgwqAA|@r~Bc zcFrZN40QB2JsA5Vz!|HSVt-VvoYaBsuNQ>odB8p*dvK<{fyuvkQvRdD`bz8kr!{W9 zUe%jxNQ*y^bDGxYu-zq}&<_1YeFEiIV)XwVf7XA>M``_97s1vm>$A^CVL!^cJ>HGq zf1vn@^(yPG#jO97?^6GFy~po2csZ~^#jiJD|HzW0!TLh(WLiJE5J>h+{eL%r_7|0b zl;6;P!lZ{V9#fTp)L+^^>cfSV1)#qp5Z|c3zjr^V^>}o{c$C6l$UeLca`_8R*<h`7iqpYj;%Kh0N&|2h5n^%#51j1T$sv&7;2dW`4cq@MixTjFrG-s-?_4`l0Y z%j0PM&aRx=mG!?a{FDdw)0Dx^)PIW?*)!H#6i;zsV**n$Zu0wk``g+cehs%l{5Xw} zNApn(hx~DFxjR^{{SbhPe$4-zn<2M=zf31`cVgd{z9V2U77w%~mOMY6ANyboy5KD^%v^UJyv_I|gB8a7|7 zdk6EyDwmN%YGV2MD6|e-!tnp<-z=XHMmN+0s&IeY9FK78{>XPwpWmg1<-7JvxcLK8{`|F2=!AbU ze)!LhKXez*)e6^h&XYM8@r$!zOYck?-vt>UdzjG?DrAhq|b{4Qd#BZ zab9G96rVge)z373xwv11;?DTn5%su^=jjiJd6mnVt;Kpc`IE$0A&+%}o?`!E)QqmY zUc@?)Ugq4yVO;tCW_1Rx@5<47vj;c(mz(#)@3r>7*T^3ZWOZB~$NOLZ6M_RN^ggw! zlX%~utx)_U-am!)CcOU!?@vsr)x1g9&ld(@cMSgeYS?iu0q1)!xh5Q1fcJr5KJ?j! zARKpuU3lyh(ZBnoP8yEp^Mm$H)^J?40Oyfm66-3Xq&SYOs^aiv-_`N-eSF6&pfSr{K=saWO8=NRT8;?Zx`_yW={G?_ z>3M}%|2-+7{aU*h-A_}SB7ciB?e&75(({KQ|FPqJMsXir60C3N=2D>-N$i~ZS$}E! zuXi`#eSL|OO?K{y*(rollback++); buffer[bufferPos] = value; if (value == 'z') { diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocument.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocument.cpp index 48212fe154..ae193298a7 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocument.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocument.cpp @@ -38,30 +38,30 @@ namespace AtomToolsFramework return m_relativePath; } - const AZStd::any& AtomToolsDocument::GetPropertyValue(const AZ::Name& propertyFullName) const + const AZStd::any& AtomToolsDocument::GetPropertyValue([[maybe_unused]] const AZ::Name& propertyFullName) const { AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); return m_invalidValue; } - const AtomToolsFramework::DynamicProperty& AtomToolsDocument::GetProperty(const AZ::Name& propertyFullName) const + const AtomToolsFramework::DynamicProperty& AtomToolsDocument::GetProperty([[maybe_unused]] const AZ::Name& propertyFullName) const { AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); return m_invalidProperty; } - bool AtomToolsDocument::IsPropertyGroupVisible(const AZ::Name& propertyGroupFullName) const + bool AtomToolsDocument::IsPropertyGroupVisible([[maybe_unused]] const AZ::Name& propertyGroupFullName) const { AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); return false; } - void AtomToolsDocument::SetPropertyValue(const AZ::Name& propertyFullName, const AZStd::any& value) + void AtomToolsDocument::SetPropertyValue([[maybe_unused]] const AZ::Name& propertyFullName, [[maybe_unused]] const AZStd::any& value) { AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); } - bool AtomToolsDocument::Open(AZStd::string_view loadPath) + bool AtomToolsDocument::Open([[maybe_unused]] AZStd::string_view loadPath) { AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); return false; @@ -79,14 +79,14 @@ namespace AtomToolsFramework return false; } - bool AtomToolsDocument::SaveAsCopy(AZStd::string_view savePath) + bool AtomToolsDocument::SaveAsCopy([[maybe_unused]] AZStd::string_view savePath) { AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); return false; } - bool AtomToolsDocument::SaveAsChild(AZStd::string_view savePath) + bool AtomToolsDocument::SaveAsChild([[maybe_unused]] AZStd::string_view savePath) { AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); return false; From 0270fb7fbef46a923fbb6ae03fd5e2397483b0e2 Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Tue, 17 Aug 2021 13:47:20 -0700 Subject: [PATCH 508/803] Initial saving/loading of JSON serialization of sc editor assets Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- .../Serialization/Json/BaseJsonSerializer.cpp | 22 ++-- .../Serialization/Json/BaseJsonSerializer.h | 3 +- .../Serialization/Json/JsonDeserializer.cpp | 20 ++-- .../Serialization/Json/JsonDeserializer.h | 10 +- .../Serialization/Json/JsonSerialization.cpp | 4 +- .../Serialization/Json/JsonSerializer.cpp | 29 ++--- .../Serialization/Json/JsonSerializer.h | 15 ++- .../Serialization/Json/JsonUtils.cpp | 2 +- .../Code/Editor/Assets/ScriptCanvasAsset.cpp | 2 + .../Assets/ScriptCanvasAssetHandler.cpp | 57 ++++++---- .../AutoGen/ScriptCanvasGrammar_Header.jinja | 16 ++- .../AutoGen/ScriptCanvasGrammar_Source.jinja | 22 ++-- .../Code/Include/ScriptCanvas/Core/Core.h | 4 +- .../Code/Include/ScriptCanvas/Core/Datum.cpp | 29 ++++- .../Code/Include/ScriptCanvas/Core/Datum.h | 19 +++- .../Include/ScriptCanvas/Core/GraphData.cpp | 10 +- .../Include/ScriptCanvas/Core/GraphData.h | 1 + .../Code/Include/ScriptCanvas/Core/Node.cpp | 7 +- .../Code/Include/ScriptCanvas/Core/Node.h | 16 +-- .../ScriptCanvas/Core/SerializationListener.h | 26 +++++ .../Data/BehaviorContextObject.cpp | 22 +--- .../ScriptCanvas/Data/BehaviorContextObject.h | 15 +-- .../Libraries/Core/EBusEventHandler.cpp | 10 +- .../Libraries/Core/EBusEventHandler.h | 2 + .../ScriptCanvas/Libraries/Core/Method.cpp | 13 ++- .../ScriptCanvas/Libraries/Core/Method.h | 8 +- .../Libraries/Core/MethodOverloaded.cpp | 17 ++- .../Libraries/Core/MethodOverloaded.h | 7 +- .../Serialization/DatumSerializer.cpp | 11 +- .../Serialization/GraphDataSerializer.cpp | 100 ++++++++++++++++++ .../Serialization/GraphDataSerializer.h | 37 +++++++ .../RuntimeVariableSerializer.cpp | 1 + .../Code/Source/SystemComponent.cpp | 15 ++- 33 files changed, 418 insertions(+), 154 deletions(-) create mode 100644 Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/SerializationListener.h create mode 100644 Gems/ScriptCanvas/Code/Include/ScriptCanvas/Serialization/GraphDataSerializer.cpp create mode 100644 Gems/ScriptCanvas/Code/Include/ScriptCanvas/Serialization/GraphDataSerializer.h diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/BaseJsonSerializer.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/BaseJsonSerializer.cpp index 56933e464a..4a02563f3a 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/BaseJsonSerializer.cpp +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/BaseJsonSerializer.cpp @@ -213,9 +213,13 @@ namespace AZ void* object, const Uuid& typeId, const rapidjson::Value& value, JsonDeserializerContext& context, ContinuationFlags flags) { bool loadAsNewInstance = (flags & ContinuationFlags::LoadAsNewInstance) == ContinuationFlags::LoadAsNewInstance; + JsonDeserializer::UseTypeDeserializer useCustom = (flags & ContinuationFlags::NoTypeSerializer) == ContinuationFlags::NoTypeSerializer + ? JsonDeserializer::UseTypeDeserializer::No + : JsonDeserializer::UseTypeDeserializer::Yes; + return (flags & ContinuationFlags::ResolvePointer) == ContinuationFlags::ResolvePointer - ? JsonDeserializer::LoadToPointer(object, typeId, value, context) - : JsonDeserializer::Load(object, typeId, value, loadAsNewInstance, context); + ? JsonDeserializer::LoadToPointer(object, typeId, value, useCustom, context) + : JsonDeserializer::Load(object, typeId, value, loadAsNewInstance, useCustom, context); } JsonSerializationResult::ResultCode BaseJsonSerializer::ContinueStoring( @@ -224,11 +228,15 @@ namespace AZ { using namespace JsonSerializationResult; + JsonSerializer::UseTypeSerializer useCustom = (flags & ContinuationFlags::NoTypeSerializer) == ContinuationFlags::NoTypeSerializer + ? JsonSerializer::UseTypeSerializer::No + : JsonSerializer::UseTypeSerializer::Yes; + if ((flags & ContinuationFlags::ReplaceDefault) == ContinuationFlags::ReplaceDefault && !context.ShouldKeepDefaults()) { if ((flags & ContinuationFlags::ResolvePointer) == ContinuationFlags::ResolvePointer) { - return JsonSerializer::StoreFromPointer(output, object, nullptr, typeId, context); + return JsonSerializer::StoreFromPointer(output, object, nullptr, typeId, useCustom, context); } else { @@ -241,19 +249,19 @@ namespace AZ { return result; } - return result.Combine(JsonSerializer::Store(output, object, nullptr, typeId, context)); + return result.Combine(JsonSerializer::Store(output, object, nullptr, typeId, useCustom, context)); } else { void* defaultObjectPtr = AZStd::any_cast(&newDefaultObject); - return JsonSerializer::Store(output, object, defaultObjectPtr, typeId, context); + return JsonSerializer::Store(output, object, defaultObjectPtr, typeId, useCustom, context); } } } return (flags & ContinuationFlags::ResolvePointer) == ContinuationFlags::ResolvePointer ? - JsonSerializer::StoreFromPointer(output, object, defaultObject, typeId, context) : - JsonSerializer::Store(output, object, defaultObject, typeId, context); + JsonSerializer::StoreFromPointer(output, object, defaultObject, typeId, useCustom, context) : + JsonSerializer::Store(output, object, defaultObject, typeId, useCustom, context); } JsonSerializationResult::ResultCode BaseJsonSerializer::LoadTypeId(Uuid& typeId, const rapidjson::Value& input, diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/BaseJsonSerializer.h b/Code/Framework/AzCore/AzCore/Serialization/Json/BaseJsonSerializer.h index fc35bdcf85..12ae01799c 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/BaseJsonSerializer.h +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/BaseJsonSerializer.h @@ -162,9 +162,10 @@ namespace AZ None = 0, //! No extra flags. ResolvePointer = 1 << 0, //! The pointer passed in contains a pointer. The (de)serializer will attempt to resolve to an instance. ReplaceDefault = 1 << 1, //! The default value provided for storing will be replaced with a newly created one. - LoadAsNewInstance = 1 << 2 //! Treats the value as if it's a newly created instance. This may trigger serializers marked with + LoadAsNewInstance = 1 << 2, //! Treats the value as if it's a newly created instance. This may trigger serializers marked with //! OperationFlags::InitializeNewInstance. Used for instance by pointers or new instances added to //! an array. + NoTypeSerializer = 1 << 3, //! Ignore the custom/specific serializer for the TypeId }; enum class OperationFlags diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonDeserializer.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonDeserializer.cpp index 840034e52f..dcc0550107 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonDeserializer.cpp +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonDeserializer.cpp @@ -38,7 +38,8 @@ namespace AZ } JsonSerializationResult::ResultCode JsonDeserializer::Load( - void* object, const Uuid& typeId, const rapidjson::Value& value, bool isNewInstance, JsonDeserializerContext& context) + void* object, const Uuid& typeId, const rapidjson::Value& value, bool isNewInstance, UseTypeDeserializer custom, + JsonDeserializerContext& context) { using namespace AZ::JsonSerializationResult; @@ -48,8 +49,8 @@ namespace AZ "Target object for Json Serialization is pointing to nothing during loading."); } - BaseJsonSerializer* serializer = context.GetRegistrationContext()->GetSerializerForType(typeId); - if (serializer) + if (BaseJsonSerializer* serializer + = (custom == UseTypeDeserializer::Yes ? context.GetRegistrationContext()->GetSerializerForType(typeId) : nullptr)) { return DeserializerDefaultCheck(serializer, object, typeId, value, isNewInstance, context); } @@ -70,8 +71,9 @@ namespace AZ // type itself has not been reflected using EnumBuilder. Treat it as an enum. return LoadEnum(object, *classData, value, context); } - serializer = context.GetRegistrationContext()->GetSerializerForType(classData->m_azRtti->GetGenericTypeId()); - if (serializer) + + if (BaseJsonSerializer* serializer + = context.GetRegistrationContext()->GetSerializerForType(classData->m_azRtti->GetGenericTypeId())) { return DeserializerDefaultCheck(serializer, object, typeId, value, isNewInstance, context); } @@ -101,7 +103,7 @@ namespace AZ } JsonSerializationResult::ResultCode JsonDeserializer::LoadToPointer(void* object, const Uuid& typeId, - const rapidjson::Value& value, JsonDeserializerContext& context) + const rapidjson::Value& value, UseTypeDeserializer useCustom, JsonDeserializerContext& context) { using namespace JsonSerializationResult; @@ -134,7 +136,7 @@ namespace AZ const SerializeContext::ClassData* resolvedClassData = context.GetSerializeContext()->FindClassData(resolvedTypeId); if (resolvedClassData) { - status = JsonDeserializer::Load(*objectPtr, resolvedTypeId, value, true, context); + status = JsonDeserializer::Load(*objectPtr, resolvedTypeId, value, true, useCustom, context); *objectPtr = resolvedClassData->m_azRtti->Cast(*objectPtr, typeId); @@ -171,11 +173,11 @@ namespace AZ } AZ_Assert(classElement.m_azRtti->GetTypeId() == classElement.m_typeId, "Type id mismatch during deserialization of a json file. (%s vs %s)"); - return LoadToPointer(object, classElement.m_typeId, value, context); + return LoadToPointer(object, classElement.m_typeId, value, UseTypeDeserializer::Yes, context); } else { - return Load(object, classElement.m_typeId, value, false, context); + return Load(object, classElement.m_typeId, value, false, UseTypeDeserializer::Yes, context); } } diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonDeserializer.h b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonDeserializer.h index ea236fe93c..d0a07b1a74 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonDeserializer.h +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonDeserializer.h @@ -28,6 +28,11 @@ namespace AZ FullyProcessed, ContinueProcessing }; + enum class UseTypeDeserializer : bool + { + No, + Yes + }; enum class TypeIdDetermination : u8 { ExplicitTypeId, // Type id was explicitly defined using "$type". @@ -55,10 +60,11 @@ namespace AZ JsonDeserializer(JsonDeserializer&& rhs) = delete; static JsonSerializationResult::ResultCode Load( - void* object, const Uuid& typeId, const rapidjson::Value& value, bool isNewInstance, JsonDeserializerContext& context); + void* object, const Uuid& typeId, const rapidjson::Value& value, bool isNewInstance, UseTypeDeserializer useCustom, + JsonDeserializerContext& context); static JsonSerializationResult::ResultCode LoadToPointer(void* object, const Uuid& typeId, const rapidjson::Value& value, - JsonDeserializerContext& context); + UseTypeDeserializer useCustom, JsonDeserializerContext& context); static JsonSerializationResult::ResultCode LoadWithClassElement(void* object, const rapidjson::Value& value, const SerializeContext::ClassElement& classElement, JsonDeserializerContext& context); diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSerialization.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSerialization.cpp index 8ade30cc6c..bc07f684f6 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSerialization.cpp +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSerialization.cpp @@ -245,7 +245,7 @@ namespace AZ { StackedString path(StackedString::Format::JsonPointer); JsonDeserializerContext context(settings); - result = JsonDeserializer::Load(object, objectType, root, false, context); + result = JsonDeserializer::Load(object, objectType, root, false, JsonDeserializer::UseTypeDeserializer::Yes, context); } return result; } @@ -322,7 +322,7 @@ namespace AZ JsonSerializerContext context(settings, allocator); StackedString path(StackedString::Format::ContextPath); - result = JsonSerializer::Store(output, object, defaultObject, objectType, context); + result = JsonSerializer::Store(output, object, defaultObject, objectType, JsonSerializer::UseTypeSerializer::Yes, context); } return result; } diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSerializer.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSerializer.cpp index 1fa0dd3c44..80a81181e5 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSerializer.cpp +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSerializer.cpp @@ -20,7 +20,7 @@ namespace AZ { JsonSerializationResult::ResultCode JsonSerializer::Store(rapidjson::Value& output, const void* object, const void* defaultObject, - const Uuid& typeId, JsonSerializerContext& context) + const Uuid& typeId, UseTypeSerializer custom, JsonSerializerContext& context) { using namespace JsonSerializationResult; @@ -32,8 +32,8 @@ namespace AZ // First check if there's a generic serializer registered for this. This makes it possible to use serializers that // are not (directly) registered with the Serialize Context. - auto serializer = context.GetRegistrationContext()->GetSerializerForType(typeId); - if (serializer) + if (BaseJsonSerializer* serializer + = (custom == UseTypeSerializer::Yes ? context.GetRegistrationContext()->GetSerializerForType(typeId) : nullptr)) { // Start by setting the object to be an explicit default. output.SetObject(); @@ -57,17 +57,18 @@ namespace AZ "No factory available to create a default object for comparison."); } void* defaultObjectPtr = AZStd::any_cast(&defaultObjectInstance); - ResultCode conversionResult = StoreWithClassData(output, object, defaultObjectPtr, *classData, StoreTypeId::No, context); + ResultCode conversionResult = StoreWithClassData(output, object, defaultObjectPtr, *classData, StoreTypeId::No + , UseTypeSerializer::Yes, context); return ResultCode::Combine(result, conversionResult); } else { - return StoreWithClassData(output, object, defaultObject, *classData, StoreTypeId::No, context); + return StoreWithClassData(output, object, defaultObject, *classData, StoreTypeId::No, custom, context); } } JsonSerializationResult::ResultCode JsonSerializer::StoreFromPointer(rapidjson::Value& output, const void* object, - const void* defaultObject, const Uuid& typeId, JsonSerializerContext& context) + const void* defaultObject, const Uuid& typeId, UseTypeSerializer custom, JsonSerializerContext& context) { using namespace JsonSerializationResult; @@ -85,19 +86,21 @@ namespace AZ AZ_Assert(classData->m_azRtti->GetTypeId() == typeId, "Type id mismatch in '%s' during serialization to a json file. (%s vs %s)", classData->m_name, classData->m_azRtti->GetTypeId().ToString().c_str(), typeId.ToString().c_str()); - return StoreWithClassDataFromPointer(output, object, defaultObject, *classData, context); + return StoreWithClassDataFromPointer(output, object, defaultObject, *classData, custom, context); } JsonSerializationResult::ResultCode JsonSerializer::StoreWithClassData(rapidjson::Value& node, const void* object, const void* defaultObject, const SerializeContext::ClassData& classData, StoreTypeId storeTypeId, - JsonSerializerContext& context) + UseTypeSerializer custom, JsonSerializerContext& context) { using namespace JsonSerializationResult; // Start by setting the object to be an explicit default. node.SetObject(); - auto serializer = context.GetRegistrationContext()->GetSerializerForType(classData.m_typeId); + auto serializer = custom == UseTypeSerializer::Yes + ? context.GetRegistrationContext()->GetSerializerForType(classData.m_typeId) : nullptr; + if (serializer) { ResultCode result = serializer->Store(node, object, defaultObject, classData.m_typeId, context); @@ -153,7 +156,7 @@ namespace AZ } JsonSerializationResult::ResultCode JsonSerializer::StoreWithClassDataFromPointer(rapidjson::Value& output, const void* object, - const void* defaultObject, const SerializeContext::ClassData& classData, JsonSerializerContext& context) + const void* defaultObject, const SerializeContext::ClassData& classData, UseTypeSerializer custom, JsonSerializerContext& context) { using namespace JsonSerializationResult; @@ -176,7 +179,7 @@ namespace AZ } else { - return StoreWithClassData(output, object, defaultObject, *resolvedClassData, storeTypeId, context); + return StoreWithClassData(output, object, defaultObject, *resolvedClassData, storeTypeId, custom, context); } } @@ -221,8 +224,8 @@ namespace AZ { rapidjson::Value value; ResultCode result = classElement.m_flags & SerializeContext::ClassElement::FLG_POINTER ? - StoreWithClassDataFromPointer(value, object, defaultObject, *elementClassData, context): - StoreWithClassData(value, object, defaultObject, *elementClassData, StoreTypeId::No, context); + StoreWithClassDataFromPointer(value, object, defaultObject, *elementClassData, UseTypeSerializer::Yes, context): + StoreWithClassData(value, object, defaultObject, *elementClassData, StoreTypeId::No, UseTypeSerializer::Yes, context); if (result.GetProcessing() != Processing::Halted) { if (parentNode.IsObject()) diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSerializer.h b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSerializer.h index 0ccf020cee..22dd768ec5 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSerializer.h +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSerializer.h @@ -26,6 +26,11 @@ namespace AZ No, Yes }; + enum class UseTypeSerializer : bool + { + No, + Yes + }; enum class ResolvePointerResult { FullyProcessed, @@ -41,16 +46,18 @@ namespace AZ JsonSerializer(JsonSerializer&& rhs) = delete; static JsonSerializationResult::ResultCode Store(rapidjson::Value& output, const void* object, const void* defaultObject, - const Uuid& typeId, JsonSerializerContext& context); + const Uuid& typeId, UseTypeSerializer useCustom, JsonSerializerContext& context); static JsonSerializationResult::ResultCode StoreFromPointer(rapidjson::Value& output, const void* object, const void* defaultObject, - const Uuid& typeId, JsonSerializerContext& context); + const Uuid& typeId, UseTypeSerializer custom, JsonSerializerContext& context); static JsonSerializationResult::ResultCode StoreWithClassData(rapidjson::Value& node, const void* object, const void* defaultObject, - const SerializeContext::ClassData& classData, StoreTypeId storeTypeId, JsonSerializerContext& context); + const SerializeContext::ClassData& classData, StoreTypeId storeTypeId, UseTypeSerializer custom, + JsonSerializerContext& context); static JsonSerializationResult::ResultCode StoreWithClassDataFromPointer(rapidjson::Value& output, const void* object, - const void* defaultObject, const SerializeContext::ClassData& classData, JsonSerializerContext& context); + const void* defaultObject, const SerializeContext::ClassData& classData, UseTypeSerializer custom, + JsonSerializerContext& context); static JsonSerializationResult::ResultCode StoreWithClassElement(rapidjson::Value& parentNode, const void* object, const void* defaultObject, const SerializeContext::ClassElement& classElement, JsonSerializerContext& context); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Serialization/Json/JsonUtils.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Serialization/Json/JsonUtils.cpp index 89cf667958..49a902de54 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Serialization/Json/JsonUtils.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Serialization/Json/JsonUtils.cpp @@ -333,7 +333,7 @@ namespace AZ // validate class name auto classData = loadSettings.m_serializeContext->FindClassData(classId); - if (azstricmp(classData->m_name, className) != 0) + if (!classData || azstricmp(classData->m_name, className) != 0) { return AZ::Failure(AZStd::string::format("Try to load class %s from class %s data", classData->m_name, className)); } diff --git a/Gems/ScriptCanvas/Code/Editor/Assets/ScriptCanvasAsset.cpp b/Gems/ScriptCanvas/Code/Editor/Assets/ScriptCanvasAsset.cpp index adada5791e..8d9f575586 100644 --- a/Gems/ScriptCanvas/Code/Editor/Assets/ScriptCanvasAsset.cpp +++ b/Gems/ScriptCanvas/Code/Editor/Assets/ScriptCanvasAsset.cpp @@ -114,11 +114,13 @@ namespace ScriptCanvasEditor ScriptCanvas::ScriptCanvasData& ScriptCanvasAsset::GetScriptCanvasData() { + AZ_Assert(m_data != nullptr, "data not initialized"); return *m_data; } const ScriptCanvas::ScriptCanvasData& ScriptCanvasAsset::GetScriptCanvasData() const { + AZ_Assert(m_data != nullptr, "data not initialized"); return *m_data; } } diff --git a/Gems/ScriptCanvas/Code/Editor/Assets/ScriptCanvasAssetHandler.cpp b/Gems/ScriptCanvas/Code/Editor/Assets/ScriptCanvasAssetHandler.cpp index ee78a71772..9af12facca 100644 --- a/Gems/ScriptCanvas/Code/Editor/Assets/ScriptCanvasAssetHandler.cpp +++ b/Gems/ScriptCanvas/Code/Editor/Assets/ScriptCanvasAssetHandler.cpp @@ -76,7 +76,7 @@ namespace ScriptCanvasEditor AZ::Data::AssetHandler::LoadResult ScriptCanvasAssetHandler::LoadAssetData ( const AZ::Data::Asset& assetTarget , AZStd::shared_ptr streamSource - , const AZ::Data::AssetFilterCB& assetLoadFilterCB) + , [[maybe_unused]] const AZ::Data::AssetFilterCB& assetLoadFilterCB) { namespace JSRU = AZ::JsonSerializationUtils; using namespace ScriptCanvas; @@ -86,30 +86,43 @@ namespace ScriptCanvasEditor if (scriptCanvasAssetTarget && m_serializeContext && streamSource) { - AZ::JsonDeserializerSettings settings; - // more mapping stuff - settings.m_serializeContext = m_serializeContext; streamSource->Seek(0U, AZ::IO::GenericStream::ST_SEEK_BEGIN); - // presume JSON serialization... - if (JSRU::LoadObjectFromStreamByType - ( scriptCanvasAssetTarget - , azrtti_typeid() - , *streamSource - , &settings).IsSuccess()) - { - return AZ::Data::AssetHandler::LoadResult::LoadComplete; - } - else - { - // ...if there is a failure, check if it is saved in the old format - streamSource->Seek(0U, AZ::IO::GenericStream::ST_SEEK_BEGIN); - // tolerate unknown classes in the editor. Let the asset processor warn about bad nodes... - bool loadSuccess = AZ::Utils::LoadObjectFromStreamInPlace(*streamSource, scriptCanvasAssetTarget->GetScriptCanvasData() - , m_serializeContext - , AZ::ObjectStream::FilterDescriptor(assetLoadFilterCB, AZ::ObjectStream::FILTERFLAG_IGNORE_UNKNOWN_CLASSES)); + auto& scriptCanvasDataTarget = scriptCanvasAssetTarget->GetScriptCanvasData(); + AZStd::vector byteBuffer(streamSource->GetLength()); + AZ::IO::ByteContainerStream byteStreamSource(&byteBuffer); + const size_t bytesRead = streamSource->Read(byteBuffer.size(), byteBuffer.data()); - return loadSuccess ? AZ::Data::AssetHandler::LoadResult::LoadComplete : AZ::Data::AssetHandler::LoadResult::Error; + if (bytesRead == streamSource->GetLength()) + { + byteStreamSource.Seek(0U, AZ::IO::GenericStream::ST_SEEK_BEGIN); + AZ::JsonDeserializerSettings settings; + // \todo more mapping stuff needs to go in the settings + settings.m_serializeContext = m_serializeContext; + byteStreamSource.Seek(0U, AZ::IO::GenericStream::ST_SEEK_BEGIN); + // attempt JSON deserialization... + if (JSRU::LoadObjectFromStreamByType + ( &scriptCanvasDataTarget + , azrtti_typeid() + , byteStreamSource + , &settings).IsSuccess()) + { + return AZ::Data::AssetHandler::LoadResult::LoadComplete; + } +#if defined(OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED) + else + { + // ...if there is a failure, check if it is saved in the old format + byteStreamSource.Seek(0U, AZ::IO::GenericStream::ST_SEEK_BEGIN); + // tolerate unknown classes in the editor. Let the asset processor warn about bad nodes... + if (AZ::Utils::LoadObjectFromStreamInPlace(byteStreamSource, scriptCanvasAssetTarget->GetScriptCanvasData() + , m_serializeContext + , AZ::ObjectStream::FilterDescriptor(assetLoadFilterCB, AZ::ObjectStream::FILTERFLAG_IGNORE_UNKNOWN_CLASSES))) + { + return AZ::Data::AssetHandler::LoadResult::LoadComplete; + } + } } +#endif } return AZ::Data::AssetHandler::LoadResult::Error; diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/AutoGen/ScriptCanvasGrammar_Header.jinja b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/AutoGen/ScriptCanvasGrammar_Header.jinja index 00c23b9f35..ebf647c7e9 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/AutoGen/ScriptCanvasGrammar_Header.jinja +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/AutoGen/ScriptCanvasGrammar_Header.jinja @@ -43,9 +43,19 @@ SPDX-License-Identifier: Apache-2.0 OR MIT namespace {{attribute_Namespace}} { {% endif %} - {% set className = Class.attrib['Name'] %} -{% set baseClass = Class.attrib['Base'] %} +{% if Class.attrib['Base'] is defined %} +{% if Class.attrib['Base'].split(';')|length > 1 %} +{% set baseClass = Class.attrib['Base'].split(';')[0] %} +{% set baseClasses = ", ".join(Class.attrib['Base'].split(';')) %} +{% else %} +{% set baseClass = Class.attrib['Base'] %} +{% set baseClasses = Class.attrib['Base'] %} +{% endif %} +{% else %} +{% set baseClass = "ScriptCanvas::Node" %} +{% set baseClasses = "ScriptCanvas::Node" %} +{% endif %} ///////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -66,7 +76,7 @@ namespace {{attribute_Namespace}} // You must #include the generated header into the source header #define SCRIPTCANVAS_NODE_{{ className }} \ public: \ - AZ_COMPONENT({{ className }}, "{{ classUuid }}"{% if baseClass is defined %}, {{ baseClass }}{% endif %}); \ + AZ_COMPONENT({{ className }}, "{{ classUuid }}", {{ baseClasses}} ); \ static void Reflect(AZ::ReflectContext* reflection); \ void ConfigureSlots() override; \ bool RequiresDynamicSlotOrdering() const override; \ diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/AutoGen/ScriptCanvasGrammar_Source.jinja b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/AutoGen/ScriptCanvasGrammar_Source.jinja index 205e6ebd8c..18b7fac688 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/AutoGen/ScriptCanvasGrammar_Source.jinja +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/AutoGen/ScriptCanvasGrammar_Source.jinja @@ -26,12 +26,22 @@ SPDX-License-Identifier: Apache-2.0 OR MIT #include "{{ xml.attrib['Include'] }}" {% for Class in xml.iter('Class') %} +{% if Class.attrib['Base'] is defined %} +{% if Class.attrib['Base'].split(';')|length > 1 %} +{% set baseClass = Class.attrib['Base'].split(';')[0] %} +{% set baseClasses = ", ".join(Class.attrib['Base'].split(';')) %} +{% else %} +{% set baseClass = Class.attrib['Base'] %} +{% set baseClasses = Class.attrib['Base'] %} +{% endif %} +{% else %} +{% set baseClass = "ScriptCanvas::Node" %} +{% set baseClasses = "ScriptCanvas::Node" %} +{% endif %} void {{ Class.attrib['QualifiedName'] }}::ConfigureSlots() { -{% if Class.attrib['Base'] is defined %} - {{ Class.attrib['Base'] }}::ConfigureSlots(); + {{ baseClass }}::ConfigureSlots(); -{% endif %} {% for Property in Class.iter('Property') %} {% if Property.attrib['IsInput'] | booleanTrue %} // {{ Property.attrib['Name'] }} @@ -194,13 +204,11 @@ void {{ Class.attrib['QualifiedName'] }}::Reflect(AZ::ReflectContext* context) {% endfor %} {% endif %} -{% if Class.attrib['Base'] is defined %} - static_assert((std::is_base_of::value), "Script Canvas nodes require the first base class to be derived from ScriptCanvas::Node"); + static_assert((std::is_base_of::value), "Script Canvas nodes require the first base class to be derived from ScriptCanvas::Node"); -{% endif %} if (AZ::SerializeContext* serializeContext = azrtti_cast(context)) { - serializeContext->Class<{{ Class.attrib['QualifiedName'] }}{% if Class.attrib['Base'] is defined %}, {{ Class.attrib['Base'] }}{% endif %}>() + serializeContext->Class<{{ Class.attrib['QualifiedName'] }}, {{ baseClass }}>() {% if Class.attrib['EventHandler'] is defined %} ->EventHandler<{{ Class.attrib['EventHandler'] }}>() {% endif %} diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Core.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Core.h index 5e4d11ac65..76542d6097 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Core.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Core.h @@ -24,6 +24,8 @@ #include #include +#define OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED + namespace AZ { class Entity; @@ -94,7 +96,7 @@ namespace ScriptCanvas struct VersionData { - AZ_TYPE_INFO(VersionData, "{14C629F6-467B-46FE-8B63-48FDFCA42175}"); + AZ_TYPE_INFO(VersionData, "{52036892-DA63-4199-AC6A-9BAFE6B74EFC}"); static void Reflect(AZ::ReflectContext* context); diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Datum.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Datum.cpp index e4569af820..c36110ef92 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Datum.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Datum.cpp @@ -2041,7 +2041,27 @@ namespace ScriptCanvas } } - void Datum::OnWriteEnd() + void Datum::OnSerializeBegin() + { + if (m_type.GetType() == Data::eType::BehaviorContextObject) + { + if (BehaviorContextObjectPtr ptr = (*AZStd::any_cast(&m_storage.value))) + { + ptr->OnSerializeBegin(); + } + else + { + AZ_Error("ScriptCanvas", false, AZStd::string::format("Datum type (%s) failed to serialized, did not store BehaviorContextObjectPtr properly", m_type.GetAZType().ToString().c_str()).c_str()); + } + } + } + + void Datum::OnReadBegin() + { + OnSerializeBegin(); + } + + void Datum::OnDeserialize() { if (m_type.GetType() == Data::eType::BehaviorContextObject) { @@ -2059,11 +2079,16 @@ namespace ScriptCanvas } else { - AZ_Error("Script Canvas", false, AZStd::string::format("Datum type (%s) de-serialized, but no such class found in the behavior context", m_type.GetAZType().ToString().c_str()).c_str()); + AZ_Error("ScriptCanvas", false, AZStd::string::format("Datum type (%s) de-serialized, but no such class found in the behavior context", m_type.GetAZType().ToString().c_str()).c_str()); } } } + void Datum::OnWriteEnd() + { + OnSerializeEnd(); + } + void Datum::Reflect(AZ::ReflectContext* reflection) { if (auto serializeContext = azrtti_cast(reflection)) diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Datum.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Datum.h index 4cbc25b500..3ad09e2297 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Datum.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Datum.h @@ -8,14 +8,15 @@ #pragma once +#include #include #include #include #include +#include +#include #include #include -#include -#include namespace AZ { @@ -33,11 +34,12 @@ namespace ScriptCanvas /// A Datum is used to provide generic storage for all data types in ScriptCanvas, and provide a common interface to accessing, modifying, and displaying them /// in the editor, regardless of their actual ScriptCanvas or BehaviorContext type. class Datum final + : public SerializationListener { friend class AZ::DatumSerializer; public: - AZ_TYPE_INFO(Datum, "{8B836FC0-98A8-4A81-8651-35C7CA125451}"); + AZ_RTTI(Datum, "{8B836FC0-98A8-4A81-8651-35C7CA125451}", SerializationListener); AZ_CLASS_ALLOCATOR(Datum, AZ::SystemAllocator, 0); enum class eOriginality : int @@ -237,6 +239,13 @@ namespace ScriptCanvas class SerializeContextEventHandler : public AZ::SerializeContext::IEventHandler { public: + /// Called after we are done writing to the instance pointed by classPtr. + void OnReadBegin(void* classPtr) override + { + Datum* datum = reinterpret_cast(classPtr); + datum->OnReadBegin(); + } + /// Called after we are done writing to the instance pointed by classPtr. void OnWriteEnd(void* classPtr) override { @@ -341,6 +350,10 @@ namespace ScriptCanvas void OnDatumEdited(); + void OnSerializeBegin() override; + + void OnDeserialize() override; + void OnReadBegin(); void OnWriteEnd(); diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/GraphData.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/GraphData.cpp index 9bed478d74..d8fd409147 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/GraphData.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/GraphData.cpp @@ -25,9 +25,7 @@ namespace ScriptCanvas /// Called to rebuild the Endpoint map void OnWriteEnd(void* classPtr) override { - auto* graphData = reinterpret_cast(classPtr); - graphData->BuildEndpointMap(); - graphData->LoadDependentAssets(); + reinterpret_cast(classPtr)->OnDeserialized(); } }; @@ -215,4 +213,10 @@ namespace ScriptCanvas m_dependentAssets.clear(); } + + void GraphData::OnDeserialized() + { + BuildEndpointMap(); + LoadDependentAssets(); + } } diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/GraphData.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/GraphData.h index f09098ca17..cdd23bbdda 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/GraphData.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/GraphData.h @@ -37,6 +37,7 @@ namespace ScriptCanvas void BuildEndpointMap(); void Clear(bool deleteData = false); void LoadDependentAssets(); + void OnDeserialized(); using NodeContainer = AZStd::unordered_set; using ConnectionContainer = AZStd::vector; diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Node.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Node.cpp index 6e87e52f87..5af59fc166 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Node.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Node.cpp @@ -67,7 +67,7 @@ namespace ScriptCanvas void OnWriteEnd(void* objectPtr) override { auto node = reinterpret_cast(objectPtr); - node->RebuildInternalState(); + node->OnDeserialize(); } }; @@ -2616,6 +2616,11 @@ namespace ScriptCanvas } } + void Node::OnDeserialize() + { + RebuildInternalState(); + } + void Node::OnEndpointConnected(const Endpoint& endpoint) { const SlotId& currentSlotId = EndpointNotificationBus::GetCurrentBusId()->GetSlotId(); diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Node.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Node.h index bf3e17156b..298eff5222 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Node.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Node.h @@ -14,25 +14,23 @@ #include #include #include - +#include #include #include #include #include -#include #include #include #include +#include #include +#include #include +#include #include #include -#include #include -#include - -#include - +#include #define SCRIPT_CANVAS_CALL_ON_INDEX_SEQUENCE(lambdaInterior)\ int dummy[]{ 0, ( lambdaInterior , 0)... };\ @@ -401,6 +399,7 @@ namespace ScriptCanvas , public DatumNotificationBus::Handler , public NodeRequestBus::Handler , public EndpointNotificationBus::MultiHandler + , public SerializationListener { friend class Graph; friend class RuntimeComponent; @@ -472,7 +471,7 @@ namespace ScriptCanvas public: - AZ_COMPONENT(Node, "{52B454AE-FA7E-4FE9-87D3-A1CAB235C691}"); + AZ_COMPONENT(Node, "{52B454AE-FA7E-4FE9-87D3-A1CAB235C691}", SerializationListener); static void Reflect(AZ::ReflectContext* reflection); Node(); @@ -821,6 +820,7 @@ namespace ScriptCanvas ////////////////////////////////////////////////////////////////////////// protected: + void OnDeserialize() override; virtual void OnReconfigurationBegin() {} virtual void OnReconfigurationEnd() {} diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/SerializationListener.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/SerializationListener.h new file mode 100644 index 0000000000..d53e66f21b --- /dev/null +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/SerializationListener.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#pragma once + +namespace ScriptCanvas +{ + class SerializationListener + { + public: + AZ_RTTI(SerializationListener, "{CA4EE281-30B3-4928-BCD8-9305CE75E463}"); + virtual ~SerializationListener() = 0 {} + + virtual void OnSerializeBegin() {} + virtual void OnSerializeEnd() {} + + virtual void OnDeserialize() {} + }; + + using SerializationListeners = AZStd::vector; +} diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Data/BehaviorContextObject.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Data/BehaviorContextObject.cpp index 09d356a2f0..2abeec6266 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Data/BehaviorContextObject.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Data/BehaviorContextObject.cpp @@ -17,7 +17,7 @@ namespace ScriptCanvas { - void BehaviorContextObject::OnReadBegin() + void BehaviorContextObject::OnSerializeBegin() { if (!IsOwned()) { @@ -25,18 +25,12 @@ namespace ScriptCanvas } } - void BehaviorContextObject::OnWriteEnd() - { - // Id Remapping invokes this method as well, not just serializing from an ObjectStream - } - void BehaviorContextObject::Reflect(AZ::ReflectContext* reflection) { if (auto serializeContext = azrtti_cast(reflection)) { serializeContext->Class() ->Version(0) - ->EventHandler() ->Field("m_flags", &BehaviorContextObject::m_flags) ->Field("m_object", &BehaviorContextObject::m_object) ; @@ -55,24 +49,11 @@ namespace ScriptCanvas } } - void BehaviorContextObject::SerializeContextEventHandler::OnReadBegin(void* classPtr) - { - BehaviorContextObject* object = reinterpret_cast(classPtr); - object->OnReadBegin(); - } - - void BehaviorContextObject::SerializeContextEventHandler::OnWriteEnd(void* classPtr) - { - BehaviorContextObject* object = reinterpret_cast(classPtr); - object->OnWriteEnd(); - } - BehaviorContextObjectPtr BehaviorContextObject::CloneObject(const AZ::BehaviorClass& behaviorClass) { if (SystemRequestBus::HasHandlers()) { AZStd::vector buffer; - { bool wasOwned = IsOwned(); m_flags |= Flags::Owned; @@ -87,7 +68,6 @@ namespace ScriptCanvas } AZ::IO::ByteContainerStream> readStream(&buffer); - BehaviorContextObject* newObject = CreateDefault(behaviorClass); AZ::Utils::LoadObjectFromStreamInPlace(readStream, (*newObject)); diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Data/BehaviorContextObject.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Data/BehaviorContextObject.h index ca4500eccc..8cb04801fc 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Data/BehaviorContextObject.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Data/BehaviorContextObject.h @@ -29,6 +29,7 @@ namespace ScriptCanvas class BehaviorContextObject final { friend struct AZStd::IntrusivePtrCountPolicy; + friend class Datum; public: AZ_TYPE_INFO(BehaviorContextObject, "{B735214D-5182-4536-B748-61EC83C1F007}"); @@ -69,16 +70,6 @@ namespace ScriptCanvas Reference = 1 << 3, }; - class SerializeContextEventHandler : public AZ::SerializeContext::IEventHandler - { - public: - /// Called right before we start reading from the instance pointed by classPtr. - void OnReadBegin(void* classPtr) override; - - /// Called after we are done writing to the instance pointed by classPtr. - void OnWriteEnd(void* classPtr) override; - }; - template static AZ::BehaviorObject InvokeConstructor(const AZ::BehaviorClass& behaviorClass, void* resultPtr, Args&&... args); @@ -128,9 +119,7 @@ namespace ScriptCanvas AZ_FORCE_INLINE bool IsOwned() const; - void OnReadBegin(); - - void OnWriteEnd(); + void OnSerializeBegin(); AZ_FORCE_INLINE void add_ref(); diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/EBusEventHandler.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/EBusEventHandler.cpp index af583738da..bfcb629225 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/EBusEventHandler.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/EBusEventHandler.cpp @@ -602,13 +602,21 @@ namespace ScriptCanvas } } - void EBusEventHandler::OnWriteEnd() + void EBusEventHandler::OnDeserialize() { AZStd::lock_guard lock(m_mutex); if (!m_ebus) { CreateHandler(m_ebusName); } + + /// \note Call super() anti-pattern https://en.wikipedia.org/wiki/Call_super + Node::OnDeserialize(); + } + + void EBusEventHandler::OnWriteEnd() + { + OnDeserialize(); } NodeTypeIdentifier EBusEventHandler::GetOutputNodeType(const SlotId& slotId) const diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/EBusEventHandler.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/EBusEventHandler.h index eb905b7c90..b36636fe1c 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/EBusEventHandler.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/EBusEventHandler.h @@ -138,6 +138,8 @@ namespace ScriptCanvas void SetAutoConnectToGraphOwner(bool enabled); + void OnDeserialize(); + void OnWriteEnd(); AZStd::string GetNodeName() const override diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/Method.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/Method.cpp index 9701e346be..5a732a1185 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/Method.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/Method.cpp @@ -313,6 +313,7 @@ namespace ScriptCanvas } PopulateNodeType(); + m_warnOnMissingFunction = true; } bool Method::InitializeOverloaded([[maybe_unused]] const NamespacePath& namespaces, AZStd::string_view className, AZStd::string_view methodName) @@ -739,10 +740,11 @@ namespace ScriptCanvas return TupleType{ nullptr, MethodType::Count, EventType::Count, nullptr }; } - void Method::OnWriteEnd() + void Method::OnDeserialize() { AZStd::lock_guard lock(m_mutex); + m_warnOnMissingFunction = true; const AZ::BehaviorClass* bcClass{}; const AZ::BehaviorMethod* method{}; EventType eventType; @@ -758,13 +760,20 @@ namespace ScriptCanvas { AZ_Warning("ScriptCanvas", !m_warnOnMissingFunction, "method node failed to deserialize properly"); } - } if (m_resultSlotIDs.empty()) { m_resultSlotIDs.emplace_back(SlotId{}); } + + /// \note Call super() anti-pattern https://en.wikipedia.org/wiki/Call_super + Node::OnDeserialize(); + } + + void Method::OnWriteEnd() + { + OnDeserialize(); } bool Method::BranchesOnResult() const diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/Method.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/Method.h index 41d4adcb84..b44539d915 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/Method.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/Method.h @@ -22,7 +22,6 @@ namespace AZ namespace ScriptCanvas { - AZ::Outcome IsExposable(const AZ::BehaviorMethod& method); Grammar::FunctionPrototype ToSignature(const AZ::BehaviorMethod& method); @@ -31,7 +30,8 @@ namespace ScriptCanvas { namespace Core { - class Method : public Node + class Method + : public Node { public: AZ_COMPONENT(Method, "{E42861BD-1956-45AE-8DD7-CCFC1E3E5ACF}", Node); @@ -107,6 +107,8 @@ namespace ScriptCanvas SlotId GetBusSlotId() const; + void OnDeserialize(); + void OnWriteEnd(); virtual bool IsMethodOverloaded() const { return false; } @@ -180,7 +182,7 @@ namespace ScriptCanvas AZStd::vector m_inputSlots; AZStd::vector m_resultSlotIDs; AZStd::recursive_mutex m_mutex; // post-serialization - bool m_warnOnMissingFunction = true; + bool m_warnOnMissingFunction = false; Method(const Method&) = delete; }; diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/MethodOverloaded.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/MethodOverloaded.cpp index c902d279bc..f20f79a6b1 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/MethodOverloaded.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/MethodOverloaded.cpp @@ -397,20 +397,16 @@ namespace ScriptCanvas return signature; } - void MethodOverloaded::OnReadBegin() - { - } - - void MethodOverloaded::OnReadEnd() - { - } - void MethodOverloaded::OnWriteBegin() { - SetWarnOnMissingFunction(false); } void MethodOverloaded::OnWriteEnd() + { + OnDeserialize(); + } + + void MethodOverloaded::OnDeserialize() { AZStd::lock_guard lock(GetMutex()); @@ -462,6 +458,9 @@ namespace ScriptCanvas } SetWarnOnMissingFunction(true); + + /// \note Call super() anti-pattern https://en.wikipedia.org/wiki/Call_super + Node::OnDeserialize(); } void MethodOverloaded::SetupMethodData(const AZ::BehaviorMethod* behaviorMethod, const AZ::BehaviorClass* behaviorClass) diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/MethodOverloaded.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/MethodOverloaded.h index c15b8f718c..a4d7ea83d8 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/MethodOverloaded.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/MethodOverloaded.h @@ -92,12 +92,13 @@ namespace ScriptCanvas Grammar::FunctionPrototype GetInputSignature() const; // SerializeContextReadWriteHandler - void OnReadBegin(); - void OnReadEnd(); + void OnReadBegin() {} + void OnReadEnd() {} void OnWriteBegin(); void OnWriteEnd(); - //// + + void OnDeserialize() override; void SetupMethodData(const AZ::BehaviorMethod* lookupMethod, const AZ::BehaviorClass* lookupClass); void ConfigureContracts(); diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Serialization/DatumSerializer.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Serialization/DatumSerializer.cpp index 003ef05774..aecf0f3db7 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Serialization/DatumSerializer.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Serialization/DatumSerializer.cpp @@ -85,7 +85,7 @@ namespace AZ AZ_Assert(azrtti_typeidm_datumLabel)>() == azrtti_typeid() , "m_datumLabel type changed and won't load properly"); - result.Combine( ContinueLoadingFromJsonObjectField + result.Combine(ContinueLoadingFromJsonObjectField ( &label , azrtti_typeidm_datumLabel)>() , inputValue @@ -95,6 +95,7 @@ namespace AZ Datum copy(scType, Datum::eOriginality::Original, AZStd::any_cast(&storage), scType.GetAZType()); copy.SetLabel(label); *outputDatum = copy; + outputDatum->OnDeserialize(); return context.Report(result, result.GetProcessing() != JSR::Processing::Halted ? "DatumSerializer Load finished loading Datum" @@ -124,7 +125,9 @@ namespace AZ ( JSR::Tasks::WriteValue, JSR::Outcomes::DefaultsUsed, "DatumSerializer Store used defaults for Datum"); } } - + + const_cast(inputScriptDataPtr)->OnSerializeBegin(); + JSR::ResultCode result(JSR::Tasks::WriteValue); outputValue.SetObject(); @@ -162,7 +165,7 @@ namespace AZ , inputScriptDataPtr->GetType().GetAZType() , context)); } // datum storage end - + result.Combine(ContinueStoringToJsonObjectField ( outputValue , "label" @@ -171,9 +174,9 @@ namespace AZ , azrtti_typeidm_datumLabel)>() , context)); + const_cast(inputScriptDataPtr)->OnSerializeEnd(); return context.Report(result, result.GetProcessing() != JSR::Processing::Halted ? "DatumSerializer Store finished saving Datum" : "DatumSerializer Store failed to save Datum"); } - } diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Serialization/GraphDataSerializer.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Serialization/GraphDataSerializer.cpp new file mode 100644 index 0000000000..ff284fce85 --- /dev/null +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Serialization/GraphDataSerializer.cpp @@ -0,0 +1,100 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include +#include +#include + +using namespace ScriptCanvas; + +namespace GraphDataSerializerCpp +{ + void CollectNodes(const GraphData::NodeContainer& container, SerializationListeners& listeners) + { + for (auto& nodeEntity : container) + { + if (nodeEntity) + { + if (auto listener = azrtti_cast(AZ::EntityUtils::FindFirstDerivedComponent(nodeEntity))) + { + listeners.push_back(listener); + } + } + } + } +} + +namespace AZ +{ + AZ_CLASS_ALLOCATOR_IMPL(GraphDataSerializer, SystemAllocator, 0); + + JsonSerializationResult::Result GraphDataSerializer::Load + ( void* outputValue + , [[maybe_unused]] const Uuid& outputValueTypeId + , const rapidjson::Value& inputValue + , JsonDeserializerContext& context) + { + namespace JSR = JsonSerializationResult; + + AZ_Assert(outputValueTypeId == azrtti_typeid() + , "RuntimeVariableSerializer Load against output typeID that was not GraphData"); + AZ_Assert(outputValue, "RuntimeVariableSerializer Load against null output"); + context.GetMetadata().Add(SerializationListeners()); + JSR::ResultCode result(JSR::Tasks::ReadField); + result.Combine(ContinueLoading(outputValue, outputValueTypeId, inputValue, context, ContinuationFlags::NoTypeSerializer)); + auto listeners = context.GetMetadata().Find(); + AZ_Assert(listeners, "Failed to create SerializationListeners"); + GraphDataSerializerCpp::CollectNodes(reinterpret_cast(outputValue)->m_nodes, *listeners); + + for (auto listener : *listeners) + { + listener->OnDeserialize(); + } + + reinterpret_cast(outputValue)->OnDeserialized(); + + return context.Report(result, result.GetProcessing() != JSR::Processing::Halted + ? "GraphDataSerializer Load finished loading GraphData" + : "GraphDataSerializer Load failed to load GraphData"); + } + + JsonSerializationResult::Result GraphDataSerializer::Store + ( rapidjson::Value& outputValue + , const void* inputValue + , const void* defaultValue + , [[maybe_unused]] const Uuid& valueTypeId + , JsonSerializerContext& context) + { + namespace JSR = JsonSerializationResult; + + AZ_Assert(valueTypeId == azrtti_typeid() + , "RuntimeVariableSerializer Store against output typeID that was not GraphData"); + AZ_Assert(inputValue, "RuntimeVariableSerializer Store against null output"); + context.GetMetadata().Add(SerializationListeners()); + auto listeners = context.GetMetadata().Find(); + GraphDataSerializerCpp::CollectNodes(reinterpret_cast(inputValue)->m_nodes, *listeners); + + for (auto listener : *listeners) + { + listener->OnSerializeBegin(); + } + + JSR::ResultCode result(JSR::Tasks::WriteValue); + result.Combine(ContinueStoring(outputValue, inputValue, defaultValue, valueTypeId, context, ContinuationFlags::NoTypeSerializer)); + + for (auto listener : *listeners) + { + listener->OnSerializeEnd(); + } + + return context.Report(result, result.GetProcessing() != JSR::Processing::Halted + ? "GraphDataSerializer::Store finished storing GraphData" + : "GraphDataSerializer::Store failed to store GraphData"); + } +} diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Serialization/GraphDataSerializer.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Serialization/GraphDataSerializer.h new file mode 100644 index 0000000000..e7f91eccb3 --- /dev/null +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Serialization/GraphDataSerializer.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#pragma once + +#include +#include +#include + +namespace AZ +{ + class GraphDataSerializer + : public BaseJsonSerializer + { + public: + AZ_RTTI(GraphDataSerializer, "{2DFF5794-785F-4434-9314-52BB3EF1D00E}", BaseJsonSerializer); + AZ_CLASS_ALLOCATOR_DECL; + + private: + JsonSerializationResult::Result Load + ( void* outputValue + , const Uuid& outputValueTypeId + , const rapidjson::Value& inputValue + , JsonDeserializerContext& context) override; + + JsonSerializationResult::Result Store + ( rapidjson::Value& outputValue + , const void* inputValue + , const void* defaultValue + , const Uuid& valueTypeId, JsonSerializerContext& context) override; + }; +} diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Serialization/RuntimeVariableSerializer.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Serialization/RuntimeVariableSerializer.cpp index 763206df38..e03a5e4096 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Serialization/RuntimeVariableSerializer.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Serialization/RuntimeVariableSerializer.cpp @@ -50,6 +50,7 @@ namespace AZ } result.Combine(ContinueLoadingFromJsonObjectField(AZStd::any_cast(&outputVariable->value), typeId, inputValue, "value", context)); + return context.Report(result, result.GetProcessing() != JSR::Processing::Halted ? "RuntimeVariableSerializer Load finished loading RuntimeVariable" : "RuntimeVariableSerializer Load failed to load RuntimeVariable"); diff --git a/Gems/ScriptCanvas/Code/Source/SystemComponent.cpp b/Gems/ScriptCanvas/Code/Source/SystemComponent.cpp index 0a82b8cf2a..9069592755 100644 --- a/Gems/ScriptCanvas/Code/Source/SystemComponent.cpp +++ b/Gems/ScriptCanvas/Code/Source/SystemComponent.cpp @@ -7,7 +7,6 @@ */ #include - #include #include #include @@ -23,8 +22,9 @@ #include #include #include -#include #include +#include +#include #include #include @@ -59,6 +59,7 @@ namespace ScriptCanvas { void SystemComponent::Reflect(AZ::ReflectContext* context) { + VersionData::Reflect(context); Nodeable::Reflect(context); ReflectLibraries(context); @@ -88,13 +89,9 @@ namespace ScriptCanvas if (AZ::JsonRegistrationContext* jsonContext = azrtti_cast(context)) { - jsonContext->Serializer() - ->HandlesType() - ; - - jsonContext->Serializer() - ->HandlesType() - ; + jsonContext->Serializer()->HandlesType(); + jsonContext->Serializer()->HandlesType(); + jsonContext->Serializer()->HandlesType(); } #if defined(SC_EXECUTION_TRACE_ENABLED) From b2dfd4d6902202a6b5f8132b526acfb90c6bed10 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Tue, 17 Aug 2021 13:53:31 -0700 Subject: [PATCH 509/803] fix Linux unit test hang Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Gems/FastNoise/Code/External/FastNoise/FastNoise.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gems/FastNoise/Code/External/FastNoise/FastNoise.cpp b/Gems/FastNoise/Code/External/FastNoise/FastNoise.cpp index 443fe0ce72..de073fe600 100644 --- a/Gems/FastNoise/Code/External/FastNoise/FastNoise.cpp +++ b/Gems/FastNoise/Code/External/FastNoise/FastNoise.cpp @@ -201,8 +201,8 @@ void FastNoise::SetSeed(int seed) std::mt19937_64 gen(seed); - for (unsigned char i = 0; i < 256; i++) - m_perm[i] = i; + for (int i = 0; i < 256; i++) + m_perm[i] = static_cast(i); for (int j = 0; j < 256; j++) { From 88121f3bb4c21dd90d3a199fbfe5281e197e1624 Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Tue, 17 Aug 2021 14:06:24 -0700 Subject: [PATCH 510/803] move JsonUtils to AzCore Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- Code/Framework/AtomCore/Tests/JsonSerializationUtilsTests.cpp | 2 +- .../AzCore}/Serialization/Json/JsonUtils.cpp | 0 .../AzCore}/Serialization/Json/JsonUtils.h | 0 Code/Framework/AzCore/AzCore/azcore_files.cmake | 2 ++ .../AzToolsFramework/aztoolsframework_files.cmake | 2 -- .../Code/Source/BuilderSettings/BuilderSettingManager.cpp | 2 +- Gems/Atom/Asset/Shader/Code/Source/Editor/AtomShaderConfig.cpp | 2 +- Gems/Atom/Asset/Shader/Code/Source/Editor/AzslCompiler.cpp | 2 +- .../Code/Source/Editor/CommonFiles/GlobalBuildOptions.cpp | 2 +- .../Shader/Code/Source/Editor/CommonFiles/Preprocessor.cpp | 2 +- .../Shader/Code/Source/Editor/PrecompiledShaderBuilder.cpp | 2 +- .../Atom/Asset/Shader/Code/Source/Editor/ShaderAssetBuilder.cpp | 2 +- .../Asset/Shader/Code/Source/Editor/ShaderBuilderUtility.cpp | 2 +- .../Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp | 2 +- .../Feature/Common/Code/Source/FrameCaptureSystemComponent.cpp | 2 +- .../Common/Code/Source/ProfilingCaptureSystemComponent.cpp | 2 +- Gems/Atom/RHI/Code/Source/RHI.Edit/Utils.cpp | 2 +- Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Common/JsonUtils.h | 2 +- .../RPI/Code/Source/RPI.Builders/Common/AnyAssetBuilder.cpp | 2 +- .../RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp | 2 +- Gems/Atom/RPI/Code/Source/RPI.Builders/Pass/PassBuilder.cpp | 2 +- .../Source/RPI.Builders/ResourcePool/ResourcePoolBuilder.cpp | 2 +- .../RPI.Edit/Material/MaterialFunctorSourceDataSerializer.cpp | 2 +- .../RPI.Edit/Material/MaterialPropertyValueSerializer.cpp | 2 +- .../RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp | 2 +- .../Source/RPI.Edit/Material/MaterialSourceDataSerializer.cpp | 2 +- Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialUtils.cpp | 2 +- .../Atom/RPI/Code/Source/RPI.Public/Pass/AttachmentReadback.cpp | 2 +- Gems/Atom/RPI/Code/Source/RPI.Public/Pass/PassSystem.cpp | 2 +- .../RPI/Code/Source/RPI.Public/Shader/Metrics/ShaderMetrics.cpp | 2 +- .../Source/RPI.Public/Shader/Metrics/ShaderMetricsSystem.cpp | 2 +- Gems/Atom/RPI/Code/Tests.Builders/AnyAssetBuilderTest.cpp | 2 +- Gems/Atom/RPI/Code/Tests.Builders/PassBuilderTest.cpp | 2 +- Gems/Atom/RPI/Code/Tests.Builders/ResourcePoolBuilderTest.cpp | 2 +- Gems/Atom/RPI/Code/Tests/Common/JsonTestUtils.h | 2 +- Gems/Atom/RPI/Code/Tests/Material/MaterialFunctorTests.cpp | 2 +- .../RPI/Code/Tests/Material/MaterialPropertySerializerTests.cpp | 2 +- .../RPI/Code/Tests/Material/MaterialTypeSourceDataTests.cpp | 2 +- .../Code/Source/Viewport/MaterialViewportComponent.cpp | 2 +- .../Source/Editor/AssetCollectionAsyncLoaderTestComponent.cpp | 2 +- .../Code/Editor/Assets/ScriptCanvasAssetHandler.cpp | 2 +- 41 files changed, 39 insertions(+), 39 deletions(-) rename Code/Framework/{AzToolsFramework/AzToolsFramework => AzCore/AzCore}/Serialization/Json/JsonUtils.cpp (100%) rename Code/Framework/{AzToolsFramework/AzToolsFramework => AzCore/AzCore}/Serialization/Json/JsonUtils.h (100%) diff --git a/Code/Framework/AtomCore/Tests/JsonSerializationUtilsTests.cpp b/Code/Framework/AtomCore/Tests/JsonSerializationUtilsTests.cpp index 79e0bf86ee..3444484246 100644 --- a/Code/Framework/AtomCore/Tests/JsonSerializationUtilsTests.cpp +++ b/Code/Framework/AtomCore/Tests/JsonSerializationUtilsTests.cpp @@ -13,7 +13,7 @@ #include -#include +#include namespace UnitTest { diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Serialization/Json/JsonUtils.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonUtils.cpp similarity index 100% rename from Code/Framework/AzToolsFramework/AzToolsFramework/Serialization/Json/JsonUtils.cpp rename to Code/Framework/AzCore/AzCore/Serialization/Json/JsonUtils.cpp diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Serialization/Json/JsonUtils.h b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonUtils.h similarity index 100% rename from Code/Framework/AzToolsFramework/AzToolsFramework/Serialization/Json/JsonUtils.h rename to Code/Framework/AzCore/AzCore/Serialization/Json/JsonUtils.h diff --git a/Code/Framework/AzCore/AzCore/azcore_files.cmake b/Code/Framework/AzCore/AzCore/azcore_files.cmake index 0c95b9d592..cf2dfc7b4a 100644 --- a/Code/Framework/AzCore/AzCore/azcore_files.cmake +++ b/Code/Framework/AzCore/AzCore/azcore_files.cmake @@ -531,6 +531,8 @@ set(FILES Serialization/Json/JsonStringConversionUtils.h Serialization/Json/JsonSystemComponent.h Serialization/Json/JsonSystemComponent.cpp + Serialization/Json/JsonUtils.h + Serialization/Json/JsonUtils.cpp Serialization/Json/MapSerializer.h Serialization/Json/MapSerializer.cpp Serialization/Json/RegistrationContext.h diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake b/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake index 0c49da841f..14c5f34f90 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake @@ -205,8 +205,6 @@ set(FILES PropertyTreeEditor/PropertyTreeEditorComponent.h Render/EditorIntersectorComponent.cpp Render/EditorIntersectorComponent.h - Serialization/Json/JsonUtils.h - Serialization/Json/JsonUtils.cpp Slice/SliceDataFlagsCommand.h Slice/SliceDataFlagsCommand.cpp Slice/SliceUtilities.h diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/BuilderSettingManager.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/BuilderSettingManager.cpp index 764a19d549..3493099d4c 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/BuilderSettingManager.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/BuilderSettingManager.cpp @@ -37,7 +37,7 @@ #include #include -#include +#include namespace ImageProcessingAtom { diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/AtomShaderConfig.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/AtomShaderConfig.cpp index b299108518..d2bcf4b985 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/AtomShaderConfig.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/AtomShaderConfig.cpp @@ -12,7 +12,7 @@ #include #include -#include +#include namespace AZ diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/AzslCompiler.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/AzslCompiler.cpp index 397d47ef21..ce01074959 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/AzslCompiler.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/AzslCompiler.cpp @@ -19,7 +19,7 @@ #include -#include +#include #include #include // [GFX TODO] Remove when [ATOM-15472] diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/CommonFiles/GlobalBuildOptions.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/CommonFiles/GlobalBuildOptions.cpp index 1b3b7c595d..da77df898b 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/CommonFiles/GlobalBuildOptions.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/CommonFiles/GlobalBuildOptions.cpp @@ -14,7 +14,7 @@ #include #include -#include +#include namespace AZ { diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/CommonFiles/Preprocessor.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/CommonFiles/Preprocessor.cpp index adec465a9f..caf20e61fb 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/CommonFiles/Preprocessor.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/CommonFiles/Preprocessor.cpp @@ -29,7 +29,7 @@ #include #include -#include +#include #include diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/PrecompiledShaderBuilder.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/PrecompiledShaderBuilder.cpp index 6d876c0ad4..21eda31ca2 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/PrecompiledShaderBuilder.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/PrecompiledShaderBuilder.cpp @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderAssetBuilder.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderAssetBuilder.cpp index d3fa043fa2..cd820d94db 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderAssetBuilder.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderAssetBuilder.cpp @@ -24,7 +24,7 @@ #include #include -#include +#include #include #include diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuilderUtility.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuilderUtility.cpp index df0d9b10a2..2fd2779749 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuilderUtility.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuilderUtility.cpp @@ -21,7 +21,7 @@ #include #include -#include +#include #include #include diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp index 8bbae7502b..0f06ccaf25 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp @@ -18,7 +18,7 @@ #include #include -#include +#include #include #include diff --git a/Gems/Atom/Feature/Common/Code/Source/FrameCaptureSystemComponent.cpp b/Gems/Atom/Feature/Common/Code/Source/FrameCaptureSystemComponent.cpp index 4eb5ab0a76..6fbdf5b3f0 100644 --- a/Gems/Atom/Feature/Common/Code/Source/FrameCaptureSystemComponent.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/FrameCaptureSystemComponent.cpp @@ -17,7 +17,7 @@ #include #include -#include +#include #include #include diff --git a/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.cpp b/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.cpp index da194d4d4e..dd58772f5a 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.cpp @@ -19,7 +19,7 @@ #include #include -#include +#include #include #include diff --git a/Gems/Atom/RHI/Code/Source/RHI.Edit/Utils.cpp b/Gems/Atom/RHI/Code/Source/RHI.Edit/Utils.cpp index f0fbf40a14..d5b626917b 100644 --- a/Gems/Atom/RHI/Code/Source/RHI.Edit/Utils.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI.Edit/Utils.cpp @@ -8,7 +8,7 @@ #include -#include +#include #include #include diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Common/JsonUtils.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Common/JsonUtils.h index 22baf5776a..1a62e1753c 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Common/JsonUtils.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Common/JsonUtils.h @@ -10,7 +10,7 @@ #include #include -#include +#include #include #include diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Common/AnyAssetBuilder.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/Common/AnyAssetBuilder.cpp index 031b928543..c9c477048f 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Common/AnyAssetBuilder.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Common/AnyAssetBuilder.cpp @@ -19,7 +19,7 @@ #include -#include +#include #include #include diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp index 70230cfffb..09f6610150 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #include diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Pass/PassBuilder.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/Pass/PassBuilder.cpp index 2949125fc1..8492843e9a 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Pass/PassBuilder.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Pass/PassBuilder.cpp @@ -11,7 +11,7 @@ #include -#include +#include #include #include diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/ResourcePool/ResourcePoolBuilder.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/ResourcePool/ResourcePoolBuilder.cpp index 24a105a4f4..6cd2709d25 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/ResourcePool/ResourcePoolBuilder.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/ResourcePool/ResourcePoolBuilder.cpp @@ -16,7 +16,7 @@ #include -#include +#include #include #include diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialFunctorSourceDataSerializer.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialFunctorSourceDataSerializer.cpp index 52b56f254a..a944a35162 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialFunctorSourceDataSerializer.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialFunctorSourceDataSerializer.cpp @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include #include diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialPropertyValueSerializer.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialPropertyValueSerializer.cpp index 3c702b84a0..060a563c53 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialPropertyValueSerializer.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialPropertyValueSerializer.cpp @@ -21,7 +21,7 @@ #include #include -#include +#include namespace AZ { diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp index 8d799fe440..9f980287cf 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp @@ -22,7 +22,7 @@ #include #include -#include +#include #include #include diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceDataSerializer.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceDataSerializer.cpp index 466fd79dd8..307d2bb80f 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceDataSerializer.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceDataSerializer.cpp @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #include diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialUtils.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialUtils.cpp index 7fb9d3d70f..0c2e9dca1f 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialUtils.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialUtils.cpp @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/AttachmentReadback.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/AttachmentReadback.cpp index 15fadd894b..172fb5750a 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/AttachmentReadback.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/AttachmentReadback.cpp @@ -23,7 +23,7 @@ #include #include -#include +#include #include diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/PassSystem.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/PassSystem.cpp index 6d470427b5..afb51afe2c 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/PassSystem.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/PassSystem.cpp @@ -17,7 +17,7 @@ #include #include -#include +#include #include #include diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/Metrics/ShaderMetrics.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/Metrics/ShaderMetrics.cpp index 7e5c268112..dbb5a30756 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/Metrics/ShaderMetrics.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/Metrics/ShaderMetrics.cpp @@ -6,7 +6,7 @@ * */ #include -#include +#include namespace AZ { diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/Metrics/ShaderMetricsSystem.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/Metrics/ShaderMetricsSystem.cpp index 47c8dedd8d..bcfa2bcbff 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/Metrics/ShaderMetricsSystem.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/Metrics/ShaderMetricsSystem.cpp @@ -15,7 +15,7 @@ #include #include -#include +#include #include diff --git a/Gems/Atom/RPI/Code/Tests.Builders/AnyAssetBuilderTest.cpp b/Gems/Atom/RPI/Code/Tests.Builders/AnyAssetBuilderTest.cpp index 33b4bc61fe..92e6957e9d 100644 --- a/Gems/Atom/RPI/Code/Tests.Builders/AnyAssetBuilderTest.cpp +++ b/Gems/Atom/RPI/Code/Tests.Builders/AnyAssetBuilderTest.cpp @@ -13,7 +13,7 @@ #include #include -#include +#include #include #include diff --git a/Gems/Atom/RPI/Code/Tests.Builders/PassBuilderTest.cpp b/Gems/Atom/RPI/Code/Tests.Builders/PassBuilderTest.cpp index 993bd8ded2..ed04b25ea3 100644 --- a/Gems/Atom/RPI/Code/Tests.Builders/PassBuilderTest.cpp +++ b/Gems/Atom/RPI/Code/Tests.Builders/PassBuilderTest.cpp @@ -16,7 +16,7 @@ #include #include -#include +#include #include diff --git a/Gems/Atom/RPI/Code/Tests.Builders/ResourcePoolBuilderTest.cpp b/Gems/Atom/RPI/Code/Tests.Builders/ResourcePoolBuilderTest.cpp index 2623cade02..c7e030f912 100644 --- a/Gems/Atom/RPI/Code/Tests.Builders/ResourcePoolBuilderTest.cpp +++ b/Gems/Atom/RPI/Code/Tests.Builders/ResourcePoolBuilderTest.cpp @@ -8,7 +8,7 @@ #include -#include +#include #include #include diff --git a/Gems/Atom/RPI/Code/Tests/Common/JsonTestUtils.h b/Gems/Atom/RPI/Code/Tests/Common/JsonTestUtils.h index 3b66565f99..56d537f236 100644 --- a/Gems/Atom/RPI/Code/Tests/Common/JsonTestUtils.h +++ b/Gems/Atom/RPI/Code/Tests/Common/JsonTestUtils.h @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include namespace UnitTest diff --git a/Gems/Atom/RPI/Code/Tests/Material/MaterialFunctorTests.cpp b/Gems/Atom/RPI/Code/Tests/Material/MaterialFunctorTests.cpp index 9b82f501d2..ca41bbac40 100644 --- a/Gems/Atom/RPI/Code/Tests/Material/MaterialFunctorTests.cpp +++ b/Gems/Atom/RPI/Code/Tests/Material/MaterialFunctorTests.cpp @@ -19,7 +19,7 @@ #include #include -//#include +//#include namespace UnitTest { using namespace AZ; diff --git a/Gems/Atom/RPI/Code/Tests/Material/MaterialPropertySerializerTests.cpp b/Gems/Atom/RPI/Code/Tests/Material/MaterialPropertySerializerTests.cpp index fdd8edf5e5..5386af1cfa 100644 --- a/Gems/Atom/RPI/Code/Tests/Material/MaterialPropertySerializerTests.cpp +++ b/Gems/Atom/RPI/Code/Tests/Material/MaterialPropertySerializerTests.cpp @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include #include diff --git a/Gems/Atom/RPI/Code/Tests/Material/MaterialTypeSourceDataTests.cpp b/Gems/Atom/RPI/Code/Tests/Material/MaterialTypeSourceDataTests.cpp index 85beba6721..5edf09b67d 100644 --- a/Gems/Atom/RPI/Code/Tests/Material/MaterialTypeSourceDataTests.cpp +++ b/Gems/Atom/RPI/Code/Tests/Material/MaterialTypeSourceDataTests.cpp @@ -20,7 +20,7 @@ #include #include -#include +#include #include #include diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportComponent.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportComponent.cpp index ec2f200ff2..24e78b5ad3 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportComponent.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportComponent.cpp @@ -25,7 +25,7 @@ #include #include -#include +#include #include #include diff --git a/Gems/AtomLyIntegration/AtomBridge/Code/Source/Editor/AssetCollectionAsyncLoaderTestComponent.cpp b/Gems/AtomLyIntegration/AtomBridge/Code/Source/Editor/AssetCollectionAsyncLoaderTestComponent.cpp index f0a8e35699..2a72641050 100644 --- a/Gems/AtomLyIntegration/AtomBridge/Code/Source/Editor/AssetCollectionAsyncLoaderTestComponent.cpp +++ b/Gems/AtomLyIntegration/AtomBridge/Code/Source/Editor/AssetCollectionAsyncLoaderTestComponent.cpp @@ -13,7 +13,7 @@ #include -#include +#include // Included so we can deduce the asset type from asset paths. #include diff --git a/Gems/ScriptCanvas/Code/Editor/Assets/ScriptCanvasAssetHandler.cpp b/Gems/ScriptCanvas/Code/Editor/Assets/ScriptCanvasAssetHandler.cpp index 9af12facca..3f5fd8441f 100644 --- a/Gems/ScriptCanvas/Code/Editor/Assets/ScriptCanvasAssetHandler.cpp +++ b/Gems/ScriptCanvas/Code/Editor/Assets/ScriptCanvasAssetHandler.cpp @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include #include From 778ebc39a2b30ecb28a22e60915e61099674c089 Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Tue, 17 Aug 2021 14:07:13 -0700 Subject: [PATCH 511/803] add listener to cmake files Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com> --- Gems/ScriptCanvas/Code/scriptcanvasgem_common_files.cmake | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Gems/ScriptCanvas/Code/scriptcanvasgem_common_files.cmake b/Gems/ScriptCanvas/Code/scriptcanvasgem_common_files.cmake index f1215dd580..49da9565f3 100644 --- a/Gems/ScriptCanvas/Code/scriptcanvasgem_common_files.cmake +++ b/Gems/ScriptCanvas/Code/scriptcanvasgem_common_files.cmake @@ -74,6 +74,7 @@ set(FILES Include/ScriptCanvas/Core/NodeableNodeOverloaded.cpp Include/ScriptCanvas/Core/NodeableNodeOverloaded.h Include/ScriptCanvas/Core/NodeFunctionGeneric.h + Include/ScriptCanvas/Core/SerializationListener.h Include/ScriptCanvas/Core/Slot.cpp Include/ScriptCanvas/Core/Slot.h Include/ScriptCanvas/Core/SlotConfigurationDefaults.h @@ -541,6 +542,8 @@ set(FILES Include/ScriptCanvas/Profiler/DrillerEvents.cpp Include/ScriptCanvas/Serialization/DatumSerializer.h Include/ScriptCanvas/Serialization/DatumSerializer.cpp + Include/ScriptCanvas/Serialization/GraphDataSerializer.cpp + Include/ScriptCanvas/Serialization/GraphDataSerializer.h Include/ScriptCanvas/Serialization/RuntimeVariableSerializer.h Include/ScriptCanvas/Serialization/RuntimeVariableSerializer.cpp Include/ScriptCanvas/Data/DataTrait.cpp From 401d0c1ad5e17a03409eb5267271ff6504df4f86 Mon Sep 17 00:00:00 2001 From: Junbo Liang <68558268+junbo75@users.noreply.github.com> Date: Tue, 17 Aug 2021 15:17:48 -0700 Subject: [PATCH 512/803] Update the AWSNativeSDK version and hash for Mac (#3259) --- cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake b/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake index e66dfdaca1..a0001d3e4e 100644 --- a/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake +++ b/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake @@ -32,7 +32,7 @@ ly_associate_package(PACKAGE_NAME DirectXShaderCompilerDxc-1.6.2104-o3de-rev2-ma ly_associate_package(PACKAGE_NAME SPIRVCross-2021.04.29-rev1-mac TARGETS SPIRVCross PACKAGE_HASH 78c6376ed2fd195b9b1f5fb2b56e5267a32c3aa21fb399e905308de470eb4515) ly_associate_package(PACKAGE_NAME freetype-2.10.4.14-mac-ios TARGETS freetype PACKAGE_HASH 67b4f57aed92082d3fd7c16aa244a7d908d90122c296b0a63f73e0a0b8761977) ly_associate_package(PACKAGE_NAME tiff-4.2.0.15-mac-ios TARGETS tiff PACKAGE_HASH a23ae1f8991a29f8e5df09d6d5b00d7768a740f90752cef465558c1768343709) -ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.7.167-rev3-mac TARGETS AWSNativeSDK PACKAGE_HASH 21920372e90355407578b45ac19580df1463a39a25a867bcd0ffd8b385c8254a) +ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.7.167-rev4-mac TARGETS AWSNativeSDK PACKAGE_HASH 89e1651cde6b4e6bd80cdb96ed6b624accad9f9688ff38bfca226777f4fcb678) ly_associate_package(PACKAGE_NAME Lua-5.3.5-rev6-mac TARGETS Lua PACKAGE_HASH b9079fd35634774c9269028447562c6b712dbc83b9c64975c095fd423ff04c08) ly_associate_package(PACKAGE_NAME PhysX-4.1.2.29882248-rev3-mac TARGETS PhysX PACKAGE_HASH 5e092a11d5c0a50c4dd99bb681a04b566a4f6f29aa08443d9bffc8dc12c27c8e) ly_associate_package(PACKAGE_NAME etc2comp-9cd0f9cae0-rev1-mac TARGETS etc2comp PACKAGE_HASH 1966ab101c89db7ecf30984917e0a48c0d02ee0e4d65b798743842b9469c0818) From 3e51240a05117c9573f91392e8ee4acecd3e9293 Mon Sep 17 00:00:00 2001 From: Shirang Jia Date: Tue, 17 Aug 2021 15:25:32 -0700 Subject: [PATCH 513/803] Allow customized Jenkins parameters for different pipelines and add aws integration deployment pipeline (#3248) Allow customized Jenkins parameters for different pipelines so that we can define different Jenkins parameters for a new pipeline and doesn't affect AR build parameters. Add aws integration deployment pipeline. --- scripts/build/Jenkins/Jenkinsfile | 34 +++++++++++++++++++ .../build/Platform/Windows/build_config.json | 5 +++ scripts/build/Platform/Windows/pipeline.json | 32 +++++++++++++++++ 3 files changed, 71 insertions(+) diff --git a/scripts/build/Jenkins/Jenkinsfile b/scripts/build/Jenkins/Jenkinsfile index 30efdc00ad..1c0409ceec 100644 --- a/scripts/build/Jenkins/Jenkinsfile +++ b/scripts/build/Jenkins/Jenkinsfile @@ -634,6 +634,40 @@ try { pipelineParameters.add(booleanParam(defaultValue: true, description: '', name: platform.key)) } } + // Add additional Jenkins parameters + pipelineConfig.platforms.each { platform -> + platformEnv = platform.value.PIPELINE_ENV + pipelineJenkinsParameters = platformEnv['PIPELINE_JENKINS_PARAMETERS'] ?: [:] + jenkinsParametersToAdd = pipelineJenkinsParameters[pipelineName] ?: [:] + jenkinsParametersToAdd.each{ jenkinsParameter -> + defaultValue = jenkinsParameter['default_value'] + // Use last run's value as default value so we can save values in different Jenkins environment + if (jenkinsParameter['use_last_run_value']?.toBoolean()) { + defaultValue = params."$jenkinsParameter['parameter_name']" ?: jenkinsParameter['default_value'] + } + switch (jenkinsParameter['parameter_type']) { + case 'string': + pipelineParameters.add(stringParam(defaultValue: defaultValue, + description: jenkinsParameter['description'], + name: jenkinsParameter['parameter_name'] + )) + break + case 'boolean': + pipelineParameters.add(booleanParam(defaultValue: defaultValue, + description: jenkinsParameter['description'], + name: jenkinsParameter['parameter_name'] + )) + break + case 'password': + pipelineParameters.add(password(defaultValue: defaultValue, + description: jenkinsParameter['description'], + name: jenkinsParameter['parameter_name'] + )) + break + } + } + } + pipelineProperties.add(parameters(pipelineParameters)) properties(pipelineProperties) diff --git a/scripts/build/Platform/Windows/build_config.json b/scripts/build/Platform/Windows/build_config.json index 0268412aea..8928794a43 100644 --- a/scripts/build/Platform/Windows/build_config.json +++ b/scripts/build/Platform/Windows/build_config.json @@ -376,5 +376,10 @@ "install_profile_vs2019", "project_engineinstall_profile_vs2019" ] + }, + "awsi_deployment": { + "TAGS": ["awsi-deployment"], + "COMMAND": "deploy_cdk_applications.cmd", + "PARAMETERS": {} } } diff --git a/scripts/build/Platform/Windows/pipeline.json b/scripts/build/Platform/Windows/pipeline.json index 622fa9d5ae..4cfc6f696a 100644 --- a/scripts/build/Platform/Windows/pipeline.json +++ b/scripts/build/Platform/Windows/pipeline.json @@ -16,5 +16,37 @@ "nightly-clean": { "CLEAN_WORKSPACE": true } + }, + "PIPELINE_JENKINS_PARAMETERS": { + "awsi-deployment": [ + { + "parameter_name": "O3DE_AWS_PROJECT_NAME", + "parameter_type": "string", + "default_value": "", + "use_last_run_value": true, + "description": "" + }, + { + "parameter_name": "O3DE_AWS_DEPLOY_REGION", + "parameter_type": "string", + "default_value": "", + "use_last_run_value": true, + "description": "" + }, + { + "parameter_name": "ASSUME_ROLE_ARN", + "parameter_type": "string", + "default_value": "", + "use_last_run_value": true, + "description": "" + }, + { + "parameter_name": "COMMIT_ID", + "parameter_type": "string", + "default_value": "", + "use_last_run_value": true, + "description": "" + } + ] } } \ No newline at end of file From e29479552b3f892f76bc82b3386ad91965024b5d Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Tue, 17 Aug 2021 15:53:14 -0700 Subject: [PATCH 514/803] alignment fix Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Framework/AzCore/Tests/Math/SfmtTests.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Code/Framework/AzCore/Tests/Math/SfmtTests.cpp b/Code/Framework/AzCore/Tests/Math/SfmtTests.cpp index f40246b8e9..397e8bd24f 100644 --- a/Code/Framework/AzCore/Tests/Math/SfmtTests.cpp +++ b/Code/Framework/AzCore/Tests/Math/SfmtTests.cpp @@ -27,8 +27,8 @@ namespace UnitTest void SetUp() override { AllocatorsFixture::SetUp(); - array1 = (AZ::u64*)azmalloc(sizeof(AZ::u64) * 2 * (BLOCK_SIZE / 4), AZStd::alignment_of::value); - array2 = (AZ::u64*)azmalloc(sizeof(AZ::u64) * 2 * (10000 / 4), AZStd::alignment_of::value); + array1 = (AZ::u64*)azmalloc(sizeof(AZ::u64) * 2 * (BLOCK_SIZE / 4), AZStd::alignment_of::value); + array2 = (AZ::u64*)azmalloc(sizeof(AZ::u64) * 2 * (10000 / 4), AZStd::alignment_of::value); } void TearDown() override From 078e0a86938699d3fce2c44027540cc5637f5735 Mon Sep 17 00:00:00 2001 From: amzn-phist <52085794+amzn-phist@users.noreply.github.com> Date: Tue, 17 Aug 2021 17:59:09 -0500 Subject: [PATCH 515/803] Audio legacy cleanup - Move global functions to be handled by AudioSystemComponent (#3283) * Removes legacy audio listener updates from ViewSys These functions were empty and logging a warning, removed. Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com> * Move more audio functions to AudioSystemComponent For global actions like Mute/Unmute, Reload, StopAll, Load/Unload Level, we move those functions to be handled by the AudioSystemComponent in LmbrCentral. This lets us remove some includes of IAudioSystem.h from Editor and Legacy/CrySystem. There were several locations where audio banks were being loaded and unloaded for a level. Now they all call into the AudioSystemComponent and we don't have multiple copies of the same code. Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com> --- Code/Editor/CryEditDoc.cpp | 50 +------ Code/Editor/MainWindow.cpp | 20 ++- Code/Editor/ViewportTitleDlg.cpp | 41 ++++-- Code/Editor/ViewportTitleDlg.h | 8 - Code/Legacy/CryCommon/IViewSystem.h | 3 - .../CrySystem/LevelSystem/LevelSystem.cpp | 52 ------- .../LevelSystem/SpawnableLevelSystem.cpp | 58 -------- Code/Legacy/CrySystem/System.cpp | 18 --- .../CrySystem/ViewSystem/DebugCamera.cpp | 6 - Code/Legacy/CrySystem/ViewSystem/View.cpp | 5 - Code/Legacy/CrySystem/ViewSystem/View.h | 1 - .../CrySystem/ViewSystem/ViewSystem.cpp | 11 -- Code/Legacy/CrySystem/ViewSystem/ViewSystem.h | 2 - .../Source/Audio/AudioSystemComponent.cpp | 138 ++++++++++++++++-- .../Code/Source/Audio/AudioSystemComponent.h | 13 ++ .../Audio/AudioSystemComponentBus.h | 11 ++ .../Code/Source/Animation/AzEntityNode.cpp | 1 - 17 files changed, 192 insertions(+), 246 deletions(-) diff --git a/Code/Editor/CryEditDoc.cpp b/Code/Editor/CryEditDoc.cpp index c720299ce8..90b020f452 100644 --- a/Code/Editor/CryEditDoc.cpp +++ b/Code/Editor/CryEditDoc.cpp @@ -32,9 +32,6 @@ #include #include -// CryCommon -#include - // Editor #include "Settings.h" @@ -60,6 +57,7 @@ #include // LmbrCentral +#include #include // for LmbrCentral::EditorLightComponentRequestBus //#define PROFILE_LOADING_WITH_VTUNE @@ -269,20 +267,7 @@ void CCryEditDoc::DeleteContents() CErrorReportDialog::Clear(); // Unload level specific audio binary data. - Audio::SAudioManagerRequestData oAMData(Audio::eADS_LEVEL_SPECIFIC); - Audio::SAudioRequest oAudioRequestData; - oAudioRequestData.nFlags = (Audio::eARF_PRIORITY_HIGH | Audio::eARF_EXECUTE_BLOCKING); - oAudioRequestData.pData = &oAMData; - Audio::AudioSystemRequestBus::Broadcast(&Audio::AudioSystemRequestBus::Events::PushRequestBlocking, oAudioRequestData); - - // Now unload level specific audio config data. - Audio::SAudioManagerRequestData oAMData2(Audio::eADS_LEVEL_SPECIFIC); - oAudioRequestData.pData = &oAMData2; - Audio::AudioSystemRequestBus::Broadcast(&Audio::AudioSystemRequestBus::Events::PushRequestBlocking, oAudioRequestData); - - Audio::SAudioManagerRequestData oAMData3(Audio::eADS_LEVEL_SPECIFIC); - oAudioRequestData.pData = &oAMData3; - Audio::AudioSystemRequestBus::Broadcast(&Audio::AudioSystemRequestBus::Events::PushRequestBlocking, oAudioRequestData); + LmbrCentral::AudioSystemComponentRequestBus::Broadcast(&LmbrCentral::AudioSystemComponentRequestBus::Events::LevelUnloadAudio); GetIEditor()->Notify(eNotify_OnSceneClosed); CrySystemEventBus::Broadcast(&CrySystemEventBus::Events::OnCryEditorSceneClosed); @@ -413,32 +398,11 @@ void CCryEditDoc::Load(TDocMultiArchive& arrXmlAr, const QString& szFilename) #ifdef PROFILE_LOADING_WITH_VTUNE VTResume(); #endif - // Parse level specific config data. - const char* controlsPath = nullptr; - Audio::AudioSystemRequestBus::BroadcastResult(controlsPath, &Audio::AudioSystemRequestBus::Events::GetControlsPath); - QString sAudioLevelPath(controlsPath); - sAudioLevelPath += "levels/"; - AZStd::string const sLevelNameOnly = PathUtil::GetFileName(fileName.toUtf8().data()); - sAudioLevelPath += sLevelNameOnly.c_str(); - QByteArray path = sAudioLevelPath.toUtf8(); - Audio::SAudioManagerRequestData oAMData(path, Audio::eADS_LEVEL_SPECIFIC); - Audio::SAudioRequest oAudioRequestData; - oAudioRequestData.nFlags = (Audio::eARF_PRIORITY_HIGH | Audio::eARF_EXECUTE_BLOCKING); // Needs to be blocking so data is available for next preloading request! - oAudioRequestData.pData = &oAMData; - Audio::AudioSystemRequestBus::Broadcast(&Audio::AudioSystemRequestBus::Events::PushRequestBlocking, oAudioRequestData); - - Audio::SAudioManagerRequestData oAMData2(path, Audio::eADS_LEVEL_SPECIFIC); - oAudioRequestData.pData = &oAMData2; - Audio::AudioSystemRequestBus::Broadcast(&Audio::AudioSystemRequestBus::Events::PushRequestBlocking, oAudioRequestData); - - Audio::TAudioPreloadRequestID nPreloadRequestID = INVALID_AUDIO_PRELOAD_REQUEST_ID; - Audio::AudioSystemRequestBus::BroadcastResult(nPreloadRequestID, &Audio::AudioSystemRequestBus::Events::GetAudioPreloadRequestID, sLevelNameOnly.c_str()); - if (nPreloadRequestID != INVALID_AUDIO_PRELOAD_REQUEST_ID) - { - Audio::SAudioManagerRequestData oAMData3(nPreloadRequestID); - oAudioRequestData.pData = &oAMData3; - Audio::AudioSystemRequestBus::Broadcast(&Audio::AudioSystemRequestBus::Events::PushRequestBlocking, oAudioRequestData); - } + // Load level-specific audio data. + AZStd::string levelFileName{ fileName.toUtf8().constData() }; + AZStd::to_lower(levelFileName.begin(), levelFileName.end()); + LmbrCentral::AudioSystemComponentRequestBus::Broadcast( + &LmbrCentral::AudioSystemComponentRequestBus::Events::LevelLoadAudio, AZStd::string_view{ levelFileName }); { CAutoLogTime logtime("Game Engine level load"); diff --git a/Code/Editor/MainWindow.cpp b/Code/Editor/MainWindow.cpp index bb246c2337..9560fd0fe7 100644 --- a/Code/Editor/MainWindow.cpp +++ b/Code/Editor/MainWindow.cpp @@ -97,6 +97,7 @@ AZ_POP_DISABLE_WARNING #include "ActionManager.h" #include +#include using namespace AZ; using namespace AzQtComponents; @@ -1474,25 +1475,22 @@ int MainWindow::ViewPaneVersion() const void MainWindow::OnStopAllSounds() { - Audio::SAudioRequest oStopAllSoundsRequest; - Audio::SAudioManagerRequestData oStopAllSoundsRequestData; - oStopAllSoundsRequest.pData = &oStopAllSoundsRequestData; - - CryLogAlways("Pixar Look Development Studio.", "canonical_tags": ["Gem"], "user_tags": ["Rendering", "Assets", "Tools"], - "icon_path": "preview.png", "requirements": "", "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/rendering/atom/atom-content/" } diff --git a/Gems/AtomLyIntegration/AtomBridge/preview.png b/Gems/AtomLyIntegration/AtomBridge/preview.png deleted file mode 100644 index 2f1ed47754..0000000000 --- a/Gems/AtomLyIntegration/AtomBridge/preview.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6d6204c6730e5675791765ca194e9b1cbec282208e280507de830afc2805e5fa -size 41127 diff --git a/Gems/AtomLyIntegration/AtomImGuiTools/preview.png b/Gems/AtomLyIntegration/AtomImGuiTools/preview.png deleted file mode 100644 index 2f1ed47754..0000000000 --- a/Gems/AtomLyIntegration/AtomImGuiTools/preview.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6d6204c6730e5675791765ca194e9b1cbec282208e280507de830afc2805e5fa -size 41127 diff --git a/Gems/AtomLyIntegration/CommonFeatures/preview.png b/Gems/AtomLyIntegration/CommonFeatures/preview.png deleted file mode 100644 index 2f1ed47754..0000000000 --- a/Gems/AtomLyIntegration/CommonFeatures/preview.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6d6204c6730e5675791765ca194e9b1cbec282208e280507de830afc2805e5fa -size 41127 diff --git a/Gems/AtomLyIntegration/ImguiAtom/preview.png b/Gems/AtomLyIntegration/ImguiAtom/preview.png deleted file mode 100644 index 2f1ed47754..0000000000 --- a/Gems/AtomLyIntegration/ImguiAtom/preview.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6d6204c6730e5675791765ca194e9b1cbec282208e280507de830afc2805e5fa -size 41127 diff --git a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/preview.png b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/preview.png deleted file mode 100644 index b48e4907fc..0000000000 --- a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/preview.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:1bda4365dc85f8abbcb2b08e942ad03e3d7d9dabe555e079185789a2e1b282bf -size 23321 diff --git a/Gems/AtomLyIntegration/gem.json b/Gems/AtomLyIntegration/gem.json index 28faf364db..5af133c8e8 100644 --- a/Gems/AtomLyIntegration/gem.json +++ b/Gems/AtomLyIntegration/gem.json @@ -7,7 +7,6 @@ "summary": "The Atom O3DE Integration Gem provides components, libraries, and functionality to support and integrate Atom Renderer in Open 3D Engine.", "canonical_tags": ["Gem"], "user_tags": ["Rendering", "Core", "Utility"], - "icon_path": "preview.png", "requirements": "", "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/rendering/atom/atom-ly-integration/" } diff --git a/Gems/AtomTressFX/gem.json b/Gems/AtomTressFX/gem.json index 5f2e25b8a9..f6ff2b41d5 100644 --- a/Gems/AtomTressFX/gem.json +++ b/Gems/AtomTressFX/gem.json @@ -7,7 +7,6 @@ "summary": "The Atom TressFX Gem provides realistic hair and fur simulation and rendering in Atom and Open 3D Engine with AMD TressFX.", "canonical_tags": ["Gem"], "user_tags": ["Rendering", "Physics", "Animation"], - "icon_path": "preview.png", "requirements": "", "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/rendering/amd/atom-tressfx/" } diff --git a/Gems/AtomTressFX/preview.png b/Gems/AtomTressFX/preview.png deleted file mode 100644 index 2f1ed47754..0000000000 --- a/Gems/AtomTressFX/preview.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6d6204c6730e5675791765ca194e9b1cbec282208e280507de830afc2805e5fa -size 41127 From f2eb8ff51fac69b65d7bf71311d1d5fa69a2d37c Mon Sep 17 00:00:00 2001 From: Qing Tao <55564570+VickyAtAZ@users.noreply.github.com> Date: Mon, 30 Aug 2021 10:10:22 -0700 Subject: [PATCH 781/803] ATOM-16237 Using setting registry to RPI system settings (#3663) * ATOM-16237 Using setting registry to RPI system settings Changes include: - Remove RHISystemDesriptor since the pre-registered draw list tag is not needed. - Remove EitorContext which was for system component settings. - Add atom_rpi.setreg file - Add getting RPISystemDescriptor from setting registry. Signed-off-by: qingtao --- .../Code/Source/CommonSystemComponent.cpp | 1 + .../Atom/RHI.Reflect/RHISystemDescriptor.h | 31 -------------- .../RHI/Code/Include/Atom/RHI/RHISystem.h | 3 +- .../RHI.Reflect/RHISystemDescriptor.cpp | 40 ------------------- .../RHI.Reflect/ReflectSystemComponent.cpp | 2 - Gems/Atom/RHI/Code/Source/RHI/RHISystem.cpp | 10 +---- .../RHI/Code/atom_rhi_reflect_files.cmake | 2 - .../RPI.Reflect/Image/ImageSystemDescriptor.h | 8 ++++ .../Atom/RPI.Reflect/RPISystemDescriptor.h | 3 -- .../Source/RPI.Private/RPISystemComponent.cpp | 11 +++-- .../RPI/Code/Source/RPI.Public/RPISystem.cpp | 4 +- .../Image/ImageSystemDescriptor.cpp | 15 ------- .../RPI.Reflect/RPISystemDescriptor.cpp | 25 +----------- Gems/Atom/RPI/Registry/atom_rpi.setreg | 24 +++++++++++ .../Code/Source/LyShineSystemComponent.cpp | 4 ++ 15 files changed, 50 insertions(+), 133 deletions(-) delete mode 100644 Gems/Atom/RHI/Code/Include/Atom/RHI.Reflect/RHISystemDescriptor.h delete mode 100644 Gems/Atom/RHI/Code/Source/RHI.Reflect/RHISystemDescriptor.cpp create mode 100644 Gems/Atom/RPI/Registry/atom_rpi.setreg diff --git a/Gems/Atom/Feature/Common/Code/Source/CommonSystemComponent.cpp b/Gems/Atom/Feature/Common/Code/Source/CommonSystemComponent.cpp index 1500079b00..de03c08c6f 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CommonSystemComponent.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/CommonSystemComponent.cpp @@ -294,6 +294,7 @@ namespace AZ void CommonSystemComponent::Deactivate() { + m_loadTemplatesHandler.Disconnect(); AZ::RPI::FeatureProcessorFactory::Get()->UnregisterFeatureProcessor(); AZ::RPI::FeatureProcessorFactory::Get()->UnregisterFeatureProcessor(); AZ::RPI::FeatureProcessorFactory::Get()->UnregisterFeatureProcessor(); diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI.Reflect/RHISystemDescriptor.h b/Gems/Atom/RHI/Code/Include/Atom/RHI.Reflect/RHISystemDescriptor.h deleted file mode 100644 index 8c512662e7..0000000000 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI.Reflect/RHISystemDescriptor.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -#pragma once - -#include -#include - -namespace AZ -{ - class ReflectContext; - - - namespace RHI - { - class PlatformLimits; - struct RHISystemDescriptor final - { - AZ_TYPE_INFO(RHISystemDescriptor, "{A506DA28-856C-483A-938D-73471D2C5A5B}"); - static void Reflect(AZ::ReflectContext* context); - - //! The set of globally declared draw list tags, which will be registered with the registry at startup. - AZStd::vector m_drawListTags; - }; - } // namespace RHI -} // namespace AZ diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/RHISystem.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/RHISystem.h index 25026b5b87..599108654a 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/RHISystem.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/RHISystem.h @@ -14,7 +14,6 @@ #include #include #include -#include namespace AZ { @@ -33,7 +32,7 @@ namespace AZ void InitDevice(); //! This function initializes the rest of the RHI/RHI backend. - void Init(const RHISystemDescriptor& descriptor); + void Init(); void Shutdown(); //! An external callback to build the frame graph. diff --git a/Gems/Atom/RHI/Code/Source/RHI.Reflect/RHISystemDescriptor.cpp b/Gems/Atom/RHI/Code/Source/RHI.Reflect/RHISystemDescriptor.cpp deleted file mode 100644 index 45463c79ac..0000000000 --- a/Gems/Atom/RHI/Code/Source/RHI.Reflect/RHISystemDescriptor.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -#include -#include - -#include -#include - -namespace AZ -{ - namespace RHI - { - void RHISystemDescriptor::Reflect(AZ::ReflectContext* context) - { - if (auto* serializeContext = azrtti_cast(context)) - { - serializeContext->Class() - ->Version(4) - ->Field("DrawItemTags", &RHISystemDescriptor::m_drawListTags) - ; - - if (AZ::EditContext* ec = serializeContext->GetEditContext()) - { - ec->Class("RHI Settings", "Settings for runtime RHI system") - ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("System", 0xc94d118b)) - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->DataElement(AZ::Edit::UIHandlers::Default, &RHISystemDescriptor::m_drawListTags, "Draw List Tags", "The set of globally declared draw list tags, which will be registered with the registry at startup.") - ; - } - } - } - } // namespace RPI -} // namespace AZ diff --git a/Gems/Atom/RHI/Code/Source/RHI.Reflect/ReflectSystemComponent.cpp b/Gems/Atom/RHI/Code/Source/RHI.Reflect/ReflectSystemComponent.cpp index 691a07b24d..c7f7e777aa 100644 --- a/Gems/Atom/RHI/Code/Source/RHI.Reflect/ReflectSystemComponent.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI.Reflect/ReflectSystemComponent.cpp @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -161,7 +160,6 @@ namespace AZ TransientAttachmentPoolBudgets::Reflect(context); PlatformLimits::Reflect(context); PlatformLimitsDescriptor::Reflect(context); - RHISystemDescriptor::Reflect(context); Origin::Reflect(context); ReflectVendorIdEnums(context); PhysicalDeviceDriverValidator::Reflect(context); diff --git a/Gems/Atom/RHI/Code/Source/RHI/RHISystem.cpp b/Gems/Atom/RHI/Code/Source/RHI/RHISystem.cpp index ed755c538a..b03cb34140 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/RHISystem.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/RHISystem.cpp @@ -36,7 +36,7 @@ namespace AZ m_device = InitInternalDevice(); } - void RHISystem::Init(const RHISystemDescriptor& descriptor) + void RHISystem::Init() { m_cpuProfiler.Init(); @@ -86,14 +86,6 @@ namespace AZ frameSchedulerDescriptor.m_platformLimitsDescriptor = platformLimitsDescriptor; m_frameScheduler.Init(*m_device, frameSchedulerDescriptor); - - // Register draw list tags declared from content. - for (const Name& drawListName : descriptor.m_drawListTags) - { - RHI::DrawListTag drawListTag = m_drawListTagRegistry->AcquireTag(drawListName); - - AZ_Warning("RHISystem", drawListTag.IsValid(), "Failed to register draw list tag '%s'. Registry at capacity.", drawListName.GetCStr()); - } } RHI::Ptr RHISystem::InitInternalDevice() diff --git a/Gems/Atom/RHI/Code/atom_rhi_reflect_files.cmake b/Gems/Atom/RHI/Code/atom_rhi_reflect_files.cmake index 9c4ca9a60d..e211462eeb 100644 --- a/Gems/Atom/RHI/Code/atom_rhi_reflect_files.cmake +++ b/Gems/Atom/RHI/Code/atom_rhi_reflect_files.cmake @@ -118,9 +118,7 @@ set(FILES Include/Atom/RHI.Reflect/SwapChainDescriptor.h Source/RHI.Reflect/SwapChainDescriptor.cpp Include/Atom/RHI.Reflect/ReflectSystemComponent.h - Include/Atom/RHI.Reflect/RHISystemDescriptor.h Source/RHI.Reflect/ReflectSystemComponent.cpp - Source/RHI.Reflect/RHISystemDescriptor.cpp Include/Atom/RHI.Reflect/AliasedHeapEnums.h Include/Atom/RHI.Reflect/TransientBufferDescriptor.h Include/Atom/RHI.Reflect/TransientImageDescriptor.h diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Image/ImageSystemDescriptor.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Image/ImageSystemDescriptor.h index 22dec8ce64..e013c1dad1 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Image/ImageSystemDescriptor.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Image/ImageSystemDescriptor.h @@ -21,8 +21,16 @@ namespace AZ AZ_TYPE_INFO(RPI::ImageSystemDescriptor, "{319D14F6-F7F2-487A-AA6B-5800E328C79B}"); static void Reflect(AZ::ReflectContext* context); + //! The maximum size of the image pool used for system streaming images. + //! Check ImageSystemInterface::GetSystemStreamingPool() for detail of this image pool uint64_t m_systemStreamingImagePoolSize = 128 * 1024 * 1024; + + //! The maximum size of the image pool used for system attachments images. + //! Check ImageSystemInterface::GetSystemAttachmentPool() for detail of this image pool uint64_t m_systemAttachmentImagePoolSize = 512 * 1024 * 1024; + + //! The maximum size of the image pool used for streaming images load from assets + //! Check ImageSystemInterface::GetStreamingPool() for detail of this image pool uint64_t m_assetStreamingImagePoolSize = 2u * 1024u * 1024u * 1024u; }; } // namespace RPI diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/RPISystemDescriptor.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/RPISystemDescriptor.h index 2076e72731..1b7b32c1e9 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/RPISystemDescriptor.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/RPISystemDescriptor.h @@ -10,7 +10,6 @@ #include #include -#include namespace AZ { @@ -31,8 +30,6 @@ namespace AZ AZ_TYPE_INFO(RPISystemDescriptor, "{96DAC3DA-40D4-4C03-8D6A-3181E843262A}"); static void Reflect(AZ::ReflectContext* context); - RHI::RHISystemDescriptor m_rhiSystemDescriptor; - //! The asset cache relative path of the only common shader asset for the RPI system that is used //! as means to load the layout for scene srg and view srg. This is used to create any RPI::Scene. AZStd::string m_commonSrgsShaderAssetPath = "shader/sceneandviewsrgs.azshader"; diff --git a/Gems/Atom/RPI/Code/Source/RPI.Private/RPISystemComponent.cpp b/Gems/Atom/RPI/Code/Source/RPI.Private/RPISystemComponent.cpp index f73673f0e4..2567d221e5 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Private/RPISystemComponent.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Private/RPISystemComponent.cpp @@ -15,9 +15,11 @@ #include +#include #include #include -#include +#include + #ifdef RPI_EDITOR #include #endif @@ -84,8 +86,11 @@ namespace AZ void RPISystemComponent::Activate() { - // [GFX TODO] [ATOM-1436] this can be removed when setup and save system component's configure from projectConfigure.exe is fixed. - m_rpiDescriptor.m_rhiSystemDescriptor.m_drawListTags.push_back(AZ::Name("forward")); + auto settingsRegistry = AZ::SettingsRegistry::Get(); + if (settingsRegistry) + { + settingsRegistry->GetObject(m_rpiDescriptor, "/O3DE/Atom/RPI/Initialization"); + } m_rpiSystem.Initialize(m_rpiDescriptor); AZ::SystemTickBus::Handler::BusConnect(); diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/RPISystem.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/RPISystem.cpp index a9028627a0..66c4f6d20a 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/RPISystem.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/RPISystem.cpp @@ -372,7 +372,7 @@ namespace AZ return; } - m_rhiSystem.Init(m_descriptor.m_rhiSystemDescriptor); + m_rhiSystem.Init(); m_imageSystem.Init(m_descriptor.m_imageSystemDescriptor); m_bufferSystem.Init(); m_dynamicDraw.Init(m_descriptor.m_dynamicDrawSystemDescriptor); @@ -396,7 +396,7 @@ namespace AZ } //Init rhi/image/buffer systems to match InitializeSystemAssets - m_rhiSystem.Init(m_descriptor.m_rhiSystemDescriptor); + m_rhiSystem.Init(); m_imageSystem.Init(m_descriptor.m_imageSystemDescriptor); m_bufferSystem.Init(); diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Image/ImageSystemDescriptor.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Image/ImageSystemDescriptor.cpp index 611a83be93..937daf3f62 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Image/ImageSystemDescriptor.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Image/ImageSystemDescriptor.cpp @@ -25,21 +25,6 @@ namespace AZ ->Field("SystemStreamingImagePoolSize", &ImageSystemDescriptor::m_systemStreamingImagePoolSize) ->Field("SystemAttachmentImagePoolSize", &ImageSystemDescriptor::m_systemAttachmentImagePoolSize) ; - - if (AZ::EditContext* ec = serializeContext->GetEditContext()) - { - ec->Class("Image System Config", "Settings for RPI Image System") - ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("System", 0xc94d118b)) - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->DataElement(AZ::Edit::UIHandlers::Default, &ImageSystemDescriptor::m_assetStreamingImagePoolSize, - "Streaming image pool size for assets", "Streaming image pool size in bytes for streaming images created from assets") - ->DataElement(AZ::Edit::UIHandlers::Default, &ImageSystemDescriptor::m_systemStreamingImagePoolSize, - "System streaming image pool size", "Streaming image pool size in bytes for streaming images created in memory") - ->DataElement(AZ::Edit::UIHandlers::Default, &ImageSystemDescriptor::m_systemAttachmentImagePoolSize, - "System attachment image pool size", "Default attachment image pool size in bytes") - ; - } } } } // namespace RPI diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/RPISystemDescriptor.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/RPISystemDescriptor.cpp index 21c6061d8e..dc379396eb 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/RPISystemDescriptor.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/RPISystemDescriptor.cpp @@ -25,35 +25,12 @@ namespace AZ ; serializeContext->Class() - ->Version(6) // ATOM-15472 - ->Field("RHISystemDescriptor", &RPISystemDescriptor::m_rhiSystemDescriptor) + ->Version(7) // ATOM-16237 ->Field("CommonSrgsShaderAssetPath", &RPISystemDescriptor::m_commonSrgsShaderAssetPath) ->Field("ImageSystemDescriptor", &RPISystemDescriptor::m_imageSystemDescriptor) ->Field("GpuQuerySystemDescriptor", &RPISystemDescriptor::m_gpuQuerySystemDescriptor) ->Field("DynamicDrawSystemDescriptor", &RPISystemDescriptor::m_dynamicDrawSystemDescriptor) ; - - if (AZ::EditContext* ec = serializeContext->GetEditContext()) - { - ec->Class("Dynamic Draw System Settings", "Settings for the Dynamic Draw System") - ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("System", 0xc94d118b)) - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->DataElement(AZ::Edit::UIHandlers::Default, &DynamicDrawSystemDescriptor::m_dynamicBufferPoolSize, "Dynamic Buffer Pool Size", "The maxinum size of pool which is used to allocate dynamic buffers") - ; - - ec->Class("RPI Settings", "Settings for runtime RPI system") - ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("System", 0xc94d118b)) - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->DataElement(AZ::Edit::UIHandlers::Default, &RPISystemDescriptor::m_commonSrgsShaderAssetPath, "Common Shader Asset Path For Scene & View SRGs", - "Shader asset path used to get the Scene and View SRGs for all RPI scenes and views respectively") - ->DataElement(AZ::Edit::UIHandlers::Default, &RPISystemDescriptor::m_rhiSystemDescriptor, "RHI System Config", "Configuration of Render Hardware Interface") - ->DataElement(AZ::Edit::UIHandlers::Default, &RPISystemDescriptor::m_imageSystemDescriptor, "Image System Config", "Configuration of Image System") - ->DataElement(AZ::Edit::UIHandlers::Default, &RPISystemDescriptor::m_gpuQuerySystemDescriptor, "Gpu Query System Config", "Configuration of Gpu Query System") - ->DataElement(AZ::Edit::UIHandlers::Default, &RPISystemDescriptor::m_dynamicDrawSystemDescriptor, "Dynamic Draw System Config", "Configuration of Dynamic Draw System") - ; - } } } } // namespace RPI diff --git a/Gems/Atom/RPI/Registry/atom_rpi.setreg b/Gems/Atom/RPI/Registry/atom_rpi.setreg new file mode 100644 index 0000000000..bcbade5d38 --- /dev/null +++ b/Gems/Atom/RPI/Registry/atom_rpi.setreg @@ -0,0 +1,24 @@ +{ + "O3DE": { + "Atom": { + "RPI": { + "Initialization": { + "CommonSrgsShaderAssetPath": "shader/sceneandviewsrgs.azshader", + "ImageSystemDescriptor": { + "AssetStreamingImagePoolSize": 2147483648, // 2 * 1024 * 1024 * 1024 + "SystemStreamingImagePoolSize": 134217728, // 128 * 1024 * 1024 + "SystemAttachmentImagePoolSize": 536870912 // 512 * 1024 * 1024 + }, + "GpuQuerySystemDescriptor": { + "OcclusionQueryCount": 128, + "StatisticsQueryCount": 256, + "TimestampQueryCount": 256 + }, + "DynamicDrawSystemDescriptor": { + "DynamicBufferPoolSize": 50331648 // 3 * 16 * 1024 * 1024 (for 3 frames) + } + } + } + } + } +} diff --git a/Gems/LyShine/Code/Source/LyShineSystemComponent.cpp b/Gems/LyShine/Code/Source/LyShineSystemComponent.cpp index d3d2d5655e..f815e2ddbd 100644 --- a/Gems/LyShine/Code/Source/LyShineSystemComponent.cpp +++ b/Gems/LyShine/Code/Source/LyShineSystemComponent.cpp @@ -205,6 +205,10 @@ namespace LyShine //////////////////////////////////////////////////////////////////////////////////////////////////// void LyShineSystemComponent::Deactivate() { +#if !defined(LYSHINE_BUILDER) && !defined(LYSHINE_TESTS) + m_loadTemplatesHandler.Disconnect(); +#endif + UiSystemBus::Handler::BusDisconnect(); UiSystemToolsBus::Handler::BusDisconnect(); UiFrameworkBus::Handler::BusDisconnect(); From 99d71cfbc58697a55402b605980e369f6b4f1a73 Mon Sep 17 00:00:00 2001 From: kberg-amzn Date: Mon, 30 Aug 2021 12:05:53 -0700 Subject: [PATCH 782/803] Added delta replication and stat tracking to vector and array network property container types, + some minor cleanup I ran into when looking for the best hook points for this functionality Signed-off-by: kberg-amzn --- .../Components/MultiplayerComponent.h | 103 ++++++++++++++++-- .../Multiplayer/MultiplayerConstants.h | 8 +- .../Include/Multiplayer/MultiplayerTypes.h | 53 +++++---- .../Source/AutoGen/AutoComponent_Common.jinja | 6 +- .../Source/AutoGen/AutoComponent_Source.jinja | 14 ++- .../Editor/MultiplayerEditorConnection.cpp | 4 +- .../MultiplayerEditorSystemComponent.cpp | 4 +- .../Source/MultiplayerSystemComponent.cpp | 4 +- 8 files changed, 144 insertions(+), 52 deletions(-) diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/MultiplayerComponent.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/MultiplayerComponent.h index 64ceb6e16f..f685d453f3 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/Components/MultiplayerComponent.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/MultiplayerComponent.h @@ -102,11 +102,34 @@ namespace Multiplayer return GetEntity()->FindComponent(); } + inline void UpdateComponentMetrics + ( + bool modifyRecord, + uint32_t prevSerializerSize, + uint32_t currSerializerSize, + NetComponentId componentId, + PropertyIndex propertyIndex, + MultiplayerStats& stats + ) + { + const uint32_t updateSize = (currSerializerSize - prevSerializerSize); + if (updateSize > 0) + { + if (modifyRecord) + { + stats.RecordPropertyReceived(componentId, propertyIndex, updateSize); + } + else + { + stats.RecordPropertySent(componentId, propertyIndex, updateSize); + } + } + } + template inline void SerializeNetworkPropertyHelper ( AzNetworking::ISerializer& serializer, - bool modifyRecord, AzNetworking::FixedSizeBitsetView& bitset, int32_t bitIndex, TYPE& value, @@ -118,6 +141,7 @@ namespace Multiplayer { if (bitset.GetBit(bitIndex)) { + const bool modifyRecord = serializer.GetSerializerMode() == AzNetworking::SerializerMode::WriteToObject; const uint32_t prevUpdateSize = serializer.GetSize(); serializer.ClearTrackedChangesFlag(); serializer.Serialize(value, name); @@ -127,19 +151,78 @@ namespace Multiplayer bitset.SetBit(bitIndex, false); } const uint32_t postUpdateSize = serializer.GetSize(); - // Network Property metrics - const uint32_t updateSize = (postUpdateSize - prevUpdateSize); - if (updateSize > 0) + UpdateComponentMetrics(modifyRecord, prevUpdateSize, postUpdateSize, componentId, propertyIndex, stats); + } + } + + template + inline void SerializeNetworkPropertyHelperArray + ( + AzNetworking::ISerializer& serializer, + AzNetworking::FixedSizeBitsetView& bitset, + AZStd::array& value, + NetComponentId componentId, + PropertyIndex propertyIndex, + MultiplayerStats& stats + ) + { + const bool modifyRecord = serializer.GetSerializerMode() == AzNetworking::SerializerMode::WriteToObject; + const uint32_t prevUpdateSize = serializer.GetSize(); + for (uint32_t i = 0; i < SIZE; ++i) + { + if (bitset.GetBit(i)) { - if (modifyRecord) + serializer.ClearTrackedChangesFlag(); + serializer.Serialize(value[i], "Element"); + if (modifyRecord && !serializer.GetTrackedChangesFlag()) { - stats.RecordPropertyReceived(componentId, propertyIndex, updateSize); - } - else - { - stats.RecordPropertySent(componentId, propertyIndex, updateSize); + bitset.SetBit(i, false); } } } + const uint32_t postUpdateSize = serializer.GetSize(); + UpdateComponentMetrics(modifyRecord, prevUpdateSize, postUpdateSize, componentId, propertyIndex, stats); + } + + template + inline void SerializeNetworkPropertyHelperVector + ( + AzNetworking::ISerializer& serializer, + AzNetworking::FixedSizeBitsetView& bitset, + AZStd::fixed_vector& value, + NetComponentId componentId, + PropertyIndex propertyIndex, + MultiplayerStats& stats + ) + { + const bool modifyRecord = serializer.GetSerializerMode() == AzNetworking::SerializerMode::WriteToObject; + const uint32_t prevUpdateSize = serializer.GetSize(); + if (bitset.GetBit(SIZE)) + { + using SizeType = typename AZ::SizeType(), false>::Type; + SizeType origSize = aznumeric_cast(value.size()); + SizeType newSize = origSize; + serializer.Serialize(newSize, "Size"); + value.resize(newSize); + if (modifyRecord && origSize == newSize) + { + bitset.SetBit(SIZE, false); + } + } + + for (uint32_t i = 0; i < value.size(); ++i) + { + if (bitset.GetBit(i)) + { + serializer.ClearTrackedChangesFlag(); + serializer.Serialize(value[i], "Element"); + if (modifyRecord && !serializer.GetTrackedChangesFlag()) + { + bitset.SetBit(i, false); + } + } + } + const uint32_t postUpdateSize = serializer.GetSize(); + UpdateComponentMetrics(modifyRecord, prevUpdateSize, postUpdateSize, componentId, propertyIndex, stats); } } diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/MultiplayerConstants.h b/Gems/Multiplayer/Code/Include/Multiplayer/MultiplayerConstants.h index b6ed0219f8..4471aa0c2b 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/MultiplayerConstants.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/MultiplayerConstants.h @@ -17,12 +17,10 @@ namespace Multiplayer { - constexpr AZStd::string_view MPNetworkInterfaceName("MultiplayerNetworkInterface"); - constexpr AZStd::string_view MPEditorInterfaceName("MultiplayerEditorNetworkInterface"); - + constexpr AZStd::string_view MpNetworkInterfaceName("MultiplayerNetworkInterface"); + constexpr AZStd::string_view MpEditorInterfaceName("MultiplayerEditorNetworkInterface"); constexpr AZStd::string_view LocalHost("127.0.0.1"); + constexpr uint16_t DefaultServerPort = 33450; constexpr uint16_t DefaultServerEditorPort = 33451; - } - diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/MultiplayerTypes.h b/Gems/Multiplayer/Code/Include/Multiplayer/MultiplayerTypes.h index 704e9d2734..4ac20abc83 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/MultiplayerTypes.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/MultiplayerTypes.h @@ -86,7 +86,7 @@ namespace Multiplayer Activate }; - // Structure for identifying a specific entity within a spawnable + //! Structure for identifying a specific entity within a spawnable. struct PrefabEntityId { AZ_TYPE_INFO(PrefabEntityId, "{EFD37465-CCAC-4E87-A825-41B4010A2C75}"); @@ -97,29 +97,10 @@ namespace Multiplayer uint32_t m_entityOffset = AllIndices; PrefabEntityId() = default; - - explicit PrefabEntityId(AZ::Name name, uint32_t entityOffset = AllIndices) - : m_prefabName(name) - , m_entityOffset(entityOffset) - { - } - - bool operator==(const PrefabEntityId& rhs) const - { - return m_prefabName == rhs.m_prefabName && m_entityOffset == rhs.m_entityOffset; - } - - bool operator!=(const PrefabEntityId& rhs) const - { - return !(*this == rhs); - } - - bool Serialize(AzNetworking::ISerializer& serializer) - { - serializer.Serialize(m_prefabName, "prefabName"); - serializer.Serialize(m_entityOffset, "entityOffset"); - return serializer.IsValid(); - } + explicit PrefabEntityId(AZ::Name name, uint32_t entityOffset = AllIndices); + bool operator==(const PrefabEntityId& rhs) const; + bool operator!=(const PrefabEntityId& rhs) const; + bool Serialize(AzNetworking::ISerializer& serializer); }; struct EntityMigrationMessage @@ -128,6 +109,30 @@ namespace Multiplayer PrefabEntityId m_prefabEntityId; AzNetworking::PacketEncodingBuffer m_propertyUpdateData; }; + + inline PrefabEntityId::PrefabEntityId(AZ::Name name, uint32_t entityOffset) + : m_prefabName(name) + , m_entityOffset(entityOffset) + { + ; + } + + inline bool PrefabEntityId::operator==(const PrefabEntityId& rhs) const + { + return m_prefabName == rhs.m_prefabName && m_entityOffset == rhs.m_entityOffset; + } + + inline bool PrefabEntityId::operator!=(const PrefabEntityId& rhs) const + { + return !(*this == rhs); + } + + inline bool PrefabEntityId::Serialize(AzNetworking::ISerializer& serializer) + { + serializer.Serialize(m_prefabName, "prefabName"); + serializer.Serialize(m_entityOffset, "entityOffset"); + return serializer.IsValid(); + } } AZ_TYPE_SAFE_INTEGRAL_SERIALIZEBINDING(Multiplayer::HostId); diff --git a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Common.jinja b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Common.jinja index 72583f9062..811039feda 100644 --- a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Common.jinja +++ b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Common.jinja @@ -5,12 +5,12 @@ #} {%- macro ParseRpcParams(property, outNames, outTypes, outDefines, use_default_value=False) -%} {%- for Param in property.iter('Param') -%} -{%- do outNames.append(Param.attrib['Name']) -%} +{%- do outNames.append(LowerFirst(Param.attrib['Name'])) -%} {%- do outTypes.append(Param.attrib['Type']) -%} {%- if use_default_value and Param.attrib['DefaultValue'] -%} -{%- do outDefines.append('const ' ~ Param.attrib['Type'] ~ '& ' + Param.attrib['Name'] + ' = ' + Param.attrib['DefaultValue']) -%} +{%- do outDefines.append('const ' ~ Param.attrib['Type'] ~ '& ' + LowerFirst(Param.attrib['Name']) + ' = ' + Param.attrib['DefaultValue']) -%} {%- else -%} -{%- do outDefines.append('const ' ~ Param.attrib['Type'] ~ '& ' ~ Param.attrib['Name']) -%} +{%- do outDefines.append('const ' ~ Param.attrib['Type'] ~ '& ' ~ LowerFirst(Param.attrib['Name'])) -%} {%- endif -%} {%- endfor -%} {%- endmacro -%} diff --git a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja index 079cac329b..35b5ac3abf 100644 --- a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja +++ b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja @@ -636,7 +636,6 @@ bool {{ ClassName }}::Serialize{{ AutoComponentMacros.GetNetPropertiesSetName(Re {% if networkPropertyCount.value > 0 %} [[maybe_unused]] Multiplayer::MultiplayerStats& stats = Multiplayer::GetMultiplayer()->GetStats(); // We modify the record if we are writing an update so that we don't notify for a change that really didn't change the value (just a duplicated send from the server) - [[maybe_unused]] bool modifyRecord = serializer.GetSerializerMode() == AzNetworking::SerializerMode::WriteToObject; {% call(Property) AutoComponentMacros.ParseNetworkProperties(Component, ReplicateFrom, ReplicateTo) %} {% if Property.attrib['Container'] != 'None' and Property.attrib['Container'] != 'Object' %} { // Serialization for Vector and Array Network Properties @@ -651,17 +650,24 @@ bool {{ ClassName }}::Serialize{{ AutoComponentMacros.GetNetPropertiesSetName(Re if (deltaRecord.AnySet()) { {% if Property.attrib['Container'] == 'Vector' %} - serializer.Serialize>(m_{{ LowerFirst(Property.attrib['Name']) }}, "{{ LowerFirst(Property.attrib['Name']) }}"); + Multiplayer::SerializeNetworkPropertyHelperVector {% elif Property.attrib['Container'] == 'Array' %} - serializer.Serialize>(m_{{ LowerFirst(Property.attrib['Name']) }}, "{{ LowerFirst(Property.attrib['Name']) }}"); + Multiplayer::SerializeNetworkPropertyHelperArray {% endif %} + ( + serializer, + deltaRecord, + m_{{ LowerFirst(Property.attrib['Name']) }}, + GetNetComponentId(), + static_cast({{ UpperFirst(Component.attrib['Name']) }}Internal::NetworkProperties::{{ UpperFirst(Property.attrib['Name']) }}), + stats + ); } } {% else %} Multiplayer::SerializeNetworkPropertyHelper ( serializer, - modifyRecord, replicationRecord.m_{{ LowerFirst(AutoComponentMacros.GetNetPropertiesSetName(ReplicateFrom, ReplicateTo)) }}, static_cast({{ AutoComponentMacros.GetNetPropertiesQualifiedPropertyDirtyEnum(Component.attrib['Name'], ReplicateFrom, ReplicateTo, Property) }}), m_{{ LowerFirst(Property.attrib['Name']) }}, diff --git a/Gems/Multiplayer/Code/Source/Editor/MultiplayerEditorConnection.cpp b/Gems/Multiplayer/Code/Source/Editor/MultiplayerEditorConnection.cpp index fc398182ef..3bf578dd03 100644 --- a/Gems/Multiplayer/Code/Source/Editor/MultiplayerEditorConnection.cpp +++ b/Gems/Multiplayer/Code/Source/Editor/MultiplayerEditorConnection.cpp @@ -31,7 +31,7 @@ namespace Multiplayer : m_byteStream(&m_buffer) { m_networkEditorInterface = AZ::Interface::Get()->CreateNetworkInterface( - AZ::Name(MPEditorInterfaceName), ProtocolType::Tcp, TrustZone::ExternalClientToServer, *this); + AZ::Name(MpEditorInterfaceName), ProtocolType::Tcp, TrustZone::ExternalClientToServer, *this); m_networkEditorInterface->SetTimeoutEnabled(false); if (editorsv_isDedicated) { @@ -109,7 +109,7 @@ namespace Multiplayer // Setup the normal multiplayer connection AZ::Interface::Get()->InitializeMultiplayer(MultiplayerAgentType::DedicatedServer); - INetworkInterface* networkInterface = AZ::Interface::Get()->RetrieveNetworkInterface(AZ::Name(MPNetworkInterfaceName)); + INetworkInterface* networkInterface = AZ::Interface::Get()->RetrieveNetworkInterface(AZ::Name(MpNetworkInterfaceName)); uint16_t serverPort = DefaultServerPort; if (auto console = AZ::Interface::Get(); console) diff --git a/Gems/Multiplayer/Code/Source/Editor/MultiplayerEditorSystemComponent.cpp b/Gems/Multiplayer/Code/Source/Editor/MultiplayerEditorSystemComponent.cpp index d557c65215..377fb1eb56 100644 --- a/Gems/Multiplayer/Code/Source/Editor/MultiplayerEditorSystemComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Editor/MultiplayerEditorSystemComponent.cpp @@ -105,7 +105,7 @@ namespace Multiplayer m_serverProcess->TerminateProcess(0); m_serverProcess = nullptr; } - INetworkInterface* editorNetworkInterface = AZ::Interface::Get()->RetrieveNetworkInterface(AZ::Name(MPEditorInterfaceName)); + INetworkInterface* editorNetworkInterface = AZ::Interface::Get()->RetrieveNetworkInterface(AZ::Name(MpEditorInterfaceName)); if (editorNetworkInterface) { editorNetworkInterface->Disconnect(m_editorConnId, AzNetworking::DisconnectReason::TerminatedByClient); @@ -194,7 +194,7 @@ namespace Multiplayer AZ::Interface::Get()->BuildSpawnablesList(); // Now that the server has launched, attempt to connect the NetworkInterface - INetworkInterface* editorNetworkInterface = AZ::Interface::Get()->RetrieveNetworkInterface(AZ::Name(MPEditorInterfaceName)); + INetworkInterface* editorNetworkInterface = AZ::Interface::Get()->RetrieveNetworkInterface(AZ::Name(MpEditorInterfaceName)); AZ_Assert(editorNetworkInterface, "MP Editor Network Interface was unregistered before Editor could connect."); m_editorConnId = editorNetworkInterface->Connect( AzNetworking::IpAddress(remoteAddress.c_str(), editorsv_port, AzNetworking::ProtocolType::Tcp)); diff --git a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp index b0a8350982..5396d53c79 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp +++ b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp @@ -180,7 +180,7 @@ namespace Multiplayer { AZ::TickBus::Handler::BusConnect(); AzFramework::SessionNotificationBus::Handler::BusConnect(); - m_networkInterface = AZ::Interface::Get()->CreateNetworkInterface(AZ::Name(MPNetworkInterfaceName), sv_protocol, TrustZone::ExternalClientToServer, *this); + m_networkInterface = AZ::Interface::Get()->CreateNetworkInterface(AZ::Name(MpNetworkInterfaceName), sv_protocol, TrustZone::ExternalClientToServer, *this); if (AZ::Interface::Get()) { m_consoleCommandHandler.Connect(AZ::Interface::Get()->GetConsoleCommandInvokedEvent()); @@ -197,7 +197,7 @@ namespace Multiplayer AZ::Interface::Unregister(this); AZ::Interface::Unregister(this); m_consoleCommandHandler.Disconnect(); - AZ::Interface::Get()->DestroyNetworkInterface(AZ::Name(MPNetworkInterfaceName)); + AZ::Interface::Get()->DestroyNetworkInterface(AZ::Name(MpNetworkInterfaceName)); AzFramework::SessionNotificationBus::Handler::BusDisconnect(); AZ::TickBus::Handler::BusDisconnect(); } From 194205c4538161cafe06ba59b0323d462837798c Mon Sep 17 00:00:00 2001 From: Chris Galvan Date: Mon, 30 Aug 2021 14:10:30 -0500 Subject: [PATCH 783/803] Replaced AzFramework::FileFunc JSON utils API calls with AzCore::JsonUtils APIs that appear to have been duplicated. Also fixed up improper Project Configurator -> Project Manager comment replacements. Signed-off-by: Chris Galvan --- .../AzCore/Serialization/Json/JsonUtils.cpp | 5 + .../AzFramework/FileFunc/FileFunc.cpp | 279 --------------- .../AzFramework/FileFunc/FileFunc.h | 75 ---- .../AzToolsFramework/Prefab/PrefabLoader.cpp | 11 +- .../AzToolsFramework/Tests/FileFunc.cpp | 327 ------------------ .../Components/SceneSystemComponent.h | 3 +- .../SceneCore/Containers/SceneManifest.cpp | 7 +- .../Tests/Containers/SceneManifestTests.cpp | 8 +- .../SceneManifest/SceneManifestRuleTests.cpp | 8 +- .../AWSResourceMappingManager.cpp | 5 +- .../Code/Source/IdentityProvider.cpp | 5 +- Gems/AWSMetrics/Code/Source/MetricsEvent.cpp | 4 +- Gems/AWSMetrics/Code/Source/MetricsQueue.cpp | 12 +- .../Exporter/MotionEventExport.cpp | 6 +- .../Source/Importer/ChunkProcessors.cpp | 6 +- .../SliceBuilder/SliceBuilderWorker.cpp | 6 +- .../PrefabBuilder/PrefabBuilderComponent.cpp | 2 +- .../PrefabBuilder/PrefabBuilderComponent.h | 2 +- .../PrefabBuilder/PrefabBuilderTests.cpp | 3 +- .../Code/SceneLoggingExampleModule.cpp | 2 +- .../SceneProcessingConfigSystemComponent.cpp | 2 +- 21 files changed, 45 insertions(+), 733 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonUtils.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonUtils.cpp index 8f2ebaba8d..af35842afc 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonUtils.cpp +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonUtils.cpp @@ -209,6 +209,11 @@ namespace AZ AZ::Outcome ReadJsonString(AZStd::string_view jsonText) { + if (jsonText.empty()) + { + return AZ::Failure(AZStd::string("Failed to parse JSON: input string is empty.")); + } + rapidjson::Document jsonDocument; jsonDocument.Parse(jsonText.data(), jsonText.size()); if (jsonDocument.HasParseError()) diff --git a/Code/Framework/AzFramework/AzFramework/FileFunc/FileFunc.cpp b/Code/Framework/AzFramework/AzFramework/FileFunc/FileFunc.cpp index 5358dd46bd..7bfdbb2f7e 100644 --- a/Code/Framework/AzFramework/AzFramework/FileFunc/FileFunc.cpp +++ b/Code/Framework/AzFramework/AzFramework/FileFunc/FileFunc.cpp @@ -36,28 +36,6 @@ namespace AzFramework { namespace Internal { - //! Save a JSON document to a stream. Otherwise returns a failure with error message. - AZ::Outcome WriteJsonToStream(const rapidjson::Document& document, AZ::IO::GenericStream& stream, WriteJsonSettings settings = WriteJsonSettings{}) - { - AZ::IO::RapidJSONStreamWriter jsonStreamWriter(&stream); - - rapidjson::PrettyWriter writer(jsonStreamWriter); - - if (settings.m_maxDecimalPlaces >= 0) - { - writer.SetMaxDecimalPlaces(settings.m_maxDecimalPlaces); - } - - if (document.Accept(writer)) - { - return AZ::Success(); - } - else - { - return AZ::Failure(AZStd::string{ "Json Writer failed" }); - } - } - static bool FindFilesInPath(const AZStd::string& folder, const AZStd::string& filter, bool recurseSubFolders, AZStd::list& fileList) { AZStd::string file_filter = folder; @@ -107,210 +85,8 @@ namespace AzFramework { return AZStd::string("(^|\\n\\s*)" + key + "([ \\t]*)=([ \\t]*)(.*)"); } - - /** - * Replaces a value in an ini-style content. - * - * \param[in] cfgContents The contents of the ini-style file - * \param[in] header The optional group title for the key - * \param[in] key The key of the value to replace - * \param[in] newValue The value to assign to the key - * - * \returns Void on success, error message on failure. - * - * If key has multiple values, it does not preserve other values. - * enabled_game_projects = oldProject1, oldProject2, oldProject3 - * becomes - * enabled_game_projects = newProject - * Cases to handle: - * 1. Key exists, value is identical -> do nothing - * This can occur if a user modifies a config file while the tooling is open. - * Example: - * 1) Load Project Manager. - * 2) Modify your bootstrap.cfg to a different project. - * 3) Tell Project Manager to set your project to the project you set in #2. - * 2. Key exists, value is missing -> stomps over key with new key value pair. - * 3. Key exists, value is different -> stomps over key with new key value pair. Ignores previous values. - * 4. Key does not exist, header is not required -> insert "key=value" at the end of file. - * 5. Key does not exist, required header does not exist -> insert "\nHeader\n" at end of file and continue to #6. - * 6. Key does not exist, required header does exist -> insert "key=value" at next line under the header. - * The header will always exist at this point, it was created in the previous check if it was missing. - */ - AZ::Outcome UpdateCfgContents(AZStd::string& cfgContents, const AZStd::string& header, const AZStd::string& key, const AZStd::string& value) - { - // Generate regex str and replacement str - AZStd::string lhsStr = key; - AZStd::string regexStr = BuildConfigKeyValueRegex(lhsStr); - AZStd::string gameFolderAssignment = "$1" + lhsStr + "$2=$03" + value; - - // Replace the current key with the new value - // AZStd's regex was not functional at the time this was authored, so convert to std from AZStd. - std::regex sysGameRegex(regexStr.c_str()); - std::smatch matchResults; - std::string settingsFileContentsStdStr = cfgContents.c_str(); - bool matchFound = std::regex_search(settingsFileContentsStdStr, matchResults, sysGameRegex); - - std::string result; - if (matchFound) - { - // Case 1, 2, and 3 - Key value pair exists, stomp over the key with a new value pair. - result = std::regex_replace(cfgContents.c_str(), sysGameRegex, gameFolderAssignment.c_str()); - } - else - { - // Cases 4 through 6 - the key does not exist. - result = cfgContents.c_str(); - std::size_t insertLocation = 0; - // Case 5 & 6 - key does not exist, header is required - if (!header.empty()) - { - insertLocation = result.find(header.c_str()); - // Case 6 - key does not exist, header does exist. - // Set the key insertion point to right after the header. - if (insertLocation != std::string::npos) - { - insertLocation += header.length(); - } - // Case 5 - key does not exist, required header does not exist. - // Insert the header at the top of the file, set the key insertion point after the header. - else - { - AZStd::string headerAndCr = AZStd::string::format("\n%s\n", header.c_str()); - result.insert(result.length(), headerAndCr.c_str()); - insertLocation = result.length() - 1; - } - } - // Case 4 - key does not exist, header is not required. - // Case 5 & 6 - the header has been added. - // Insert the key at the tracked insertion point - AZStd::string newConfigData = AZStd::string::format("\n%s=%s", key.c_str(), value.c_str()); - result.insert(insertLocation, newConfigData.c_str()); - } - cfgContents = result.c_str(); - return AZ::Success(); - } - - /** - * Updates a configuration (ini) style contents string representation with a list of replacement string rules - * - * \param[in] cfgContents The contents of the ini file to update - * \param[in] updateRules The update rules (list of update strings, see below) to apply - * - * The replace string rule format follows the following: - * ([header]/)[key]=[value] - * - * where: - * header (optional) : Optional group title for the key - * key : The key to lookup or create for the value - * value : The value to update or create - */ - AZ::Outcome UpdateCfgContents(AZStd::string& cfgContents, const AZStd::list& updateRules) - { - AZStd::string updateCfgContents = cfgContents; - for (const AZStd::string& updateRule : updateRules) - { - // Since we are parsing manually anyways, no need to do a regex validation - AZStd::string::size_type headerKeySep = updateRule.find_first_of('/'); - bool hasHeader = (headerKeySep != AZStd::string::npos); - AZStd::string::size_type keyValueSep = updateRule.find_first_of('=', !hasHeader ? 0 : headerKeySep + 1); - if (keyValueSep == AZStd::string::npos) - { - return AZ::Failure(AZStd::string::format("Invalid update config rule '%s'. Must be in the format ([header]/)[key]=[value]", updateRule.c_str())); - } - AZStd::string header = hasHeader ? updateRule.substr(0, headerKeySep) : AZStd::string(""); - AZStd::string key = hasHeader ? updateRule.substr(headerKeySep + 1, keyValueSep - (headerKeySep + 1)) : updateRule.substr(0, keyValueSep); - AZStd::string value = updateRule.substr(keyValueSep + 1); - - auto updateResult = UpdateCfgContents(updateCfgContents, header, key, value); - if (!updateResult.IsSuccess()) - { - return updateResult; - } - } - cfgContents = updateCfgContents; - return AZ::Success(); - } } // namespace Internal - AZ::Outcome WriteJsonToString(const rapidjson::Document& document, AZStd::string& jsonText, WriteJsonSettings settings) - { - AZ::IO::ByteContainerStream stream{ &jsonText }; - return Internal::WriteJsonToStream(document, stream, settings); - } - - AZ::Outcome ReadJsonFromString(AZStd::string_view jsonText) - { - if (jsonText.empty()) - { - return AZ::Failure(AZStd::string("Failed to parse JSON: input string is empty.")); - } - - rapidjson::Document jsonDocument; - jsonDocument.Parse(jsonText.data(), jsonText.size()); - if (jsonDocument.HasParseError()) - { - size_t lineNumber = 1; - - const size_t errorOffset = jsonDocument.GetErrorOffset(); - for (size_t searchOffset = jsonText.find('\n'); - searchOffset < errorOffset && searchOffset < AZStd::string::npos; - searchOffset = jsonText.find('\n', searchOffset + 1)) - { - lineNumber++; - } - - return AZ::Failure(AZStd::string::format("JSON parse error at line %zu: %s", lineNumber, rapidjson::GetParseError_En(jsonDocument.GetParseError()))); - } - else - { - return AZ::Success(AZStd::move(jsonDocument)); - } - } - - AZ::Outcome ReadJsonFile(const AZ::IO::Path& jsonFilePath, AZ::IO::FileIOBase* overrideFileIO /*= nullptr*/, size_t maxFileSize /*= AZ::Utils::DefaultMaxFileSize*/) - { - AZ::IO::FileIOBase* fileIo = overrideFileIO != nullptr ? overrideFileIO : AZ::IO::FileIOBase::GetInstance(); - if (fileIo == nullptr) - { - return AZ::Failure(AZStd::string("No FileIO instance present.")); - } - - // Read into memory first and then parse the JSON, rather than passing a file stream to rapidjson. - // This should avoid creating a large number of micro-reads from the file. - - auto readResult = AZ::Utils::ReadFile(jsonFilePath.String(), maxFileSize); - if (!readResult.IsSuccess()) - { - return AZ::Failure(readResult.GetError()); - } - - AZStd::string jsonContent = readResult.TakeValue(); - - auto result = ReadJsonFromString(jsonContent); - if (!result.IsSuccess()) - { - return AZ::Failure(AZStd::string::format("Failed to load '%s'. %s", jsonFilePath.c_str(), result.GetError().c_str())); - } - else - { - return result; - } - } - - AZ::Outcome WriteJsonFile(const rapidjson::Document& jsonDoc, const AZ::IO::Path& jsonFilePath, WriteJsonSettings settings) - { - // Write the JSON into memory first and then write the file, rather than passing a file stream to rapidjson. - // This should avoid creating a large number of micro-writes to the file. - AZStd::string fileContent; - auto outcome = WriteJsonToString(jsonDoc, fileContent, settings); - if (!outcome.IsSuccess()) - { - return outcome; - } - - return AZ::Utils::WriteFile(fileContent, jsonFilePath.String()); - } - AZ::Outcome, AZStd::string> FindFilesInPath(const AZStd::string& folder, const AZStd::string& filter, bool recurseSubFolders) { AZStd::list fileList; @@ -348,61 +124,6 @@ namespace AzFramework return AZ::Success(); } - AZ::Outcome ReplaceInCfgFile(const AZStd::string& filePath, const AZStd::list& updateRules) - { - if (!AZ::IO::SystemFile::Exists(filePath.c_str())) - { - return AZ::Failure(AZStd::string::format("Cfg file '%s' does not exist.", filePath.c_str())); - } - - // Load the settings file into a string - AZ::IO::SystemFile settingsFile; - if (!settingsFile.Open(filePath.c_str(), AZ::IO::SystemFile::SF_OPEN_READ_ONLY)) - { - return AZ::Failure(AZStd::string::format("Error reading cfg file '%s'.", filePath.c_str())); - } - - AZStd::string settingsFileContents(settingsFile.Length(), '\0'); - settingsFile.Read(settingsFileContents.size(), settingsFileContents.data()); - settingsFile.Close(); - - auto updateContentResult = Internal::UpdateCfgContents(settingsFileContents, updateRules); - if (!updateContentResult.IsSuccess()) - { - return updateContentResult; - } - - // Write the result. - if (!settingsFile.ReOpen(AZ::IO::SystemFile::SF_OPEN_WRITE_ONLY | AZ::IO::SystemFile::SF_OPEN_TRUNCATE)) - { - return AZ::Failure(AZStd::string::format("Failed to open settings file %s.", filePath.c_str())); - } - auto bytesWritten = settingsFile.Write(settingsFileContents.c_str(), settingsFileContents.size()); - settingsFile.Close(); - - if (bytesWritten != settingsFileContents.size()) - { - return AZ::Failure(AZStd::string::format("Failed to write to config file %s.", filePath.c_str())); - } - - return AZ::Success(); - } - - AZ::Outcome ReplaceInCfgFile(const AZStd::string& filePath, const char* header, const AZStd::string& key, const AZStd::string& newValue) - { - if (key.length() <= 0) - { - return AZ::Failure(AZStd::string("'key' parameter for ReplaceInCfgFile must not be empty")); - } - - AZStd::string updateRule = (header != nullptr) ? AZStd::string::format("%s/%s=%s", header, key.c_str(), newValue.c_str()) : AZStd::string::format("%s=%s", key.c_str(), newValue.c_str()); - AZStd::list updateRules{ - updateRule - }; - auto replaceResult = ReplaceInCfgFile(filePath, updateRules); - return replaceResult; - } - AZ::Outcome GetValueForKeyInCfgFile(const AZStd::string& filePath, const char* key) { AZ::Outcome subCommandResult = GetCfgFileContents(filePath); diff --git a/Code/Framework/AzFramework/AzFramework/FileFunc/FileFunc.h b/Code/Framework/AzFramework/AzFramework/FileFunc/FileFunc.h index 43609986f7..1fcef4ccfa 100644 --- a/Code/Framework/AzFramework/AzFramework/FileFunc/FileFunc.h +++ b/Code/Framework/AzFramework/AzFramework/FileFunc/FileFunc.h @@ -27,49 +27,6 @@ namespace AzFramework { namespace FileFunc { - struct WriteJsonSettings - { - int m_maxDecimalPlaces = -1; // -1 means use default - }; - - /* - * Read a string into a JSON document - * - * \param[in] jsonText The string of JSON to parse into a JSON document. - * \return Outcome ReadJsonFromString(AZStd::string_view jsonText); - - /* - * Read a text file into a JSON document - * - * \param[in] jsonFilePath The path to the JSON file path to open - * \param[in] overrideFileIO Optional file IO instance to use. If null, use the Singleton instead - * \param[in] maxFileSize The maximum size, in bytes, of the file to read. Defaults to 1 MB. - * \return Outcome(rapidjson::Document) Returns a failure with error message if the content is not valid JSON. - */ - AZ::Outcome ReadJsonFile(const AZ::IO::Path& jsonFilePath, AZ::IO::FileIOBase* overrideFileIO = nullptr, size_t maxFileSize = AZ::Utils::DefaultMaxFileSize); - - /** - * Write a JSON document to a string - * - * \param[in] jsonDoc The JSON document to write to a text file - * \param[out] jsonFilePath The string that the JSON text will be written to. - * \param[in] settings Settings to pass along to the JSON writer. - * \return StringOutcome Saves the JSON document to text. Otherwise returns a failure with error message. - */ - AZ::Outcome WriteJsonToString(const rapidjson::Document& document, AZStd::string& jsonText, WriteJsonSettings settings = WriteJsonSettings{}); - - /** - * Write a JSON document to a text file - * - * \param[in] jsonDoc The JSON document to write to a text file - * \param[in] jsonFilePath The path to the JSON file path to write to - * \param[in] settings Settings to pass along to the JSON writer. - * \return StringOutcome Saves the JSON document to a file. Otherwise returns a failure with error message. - */ - AZ::Outcome WriteJsonFile(const rapidjson::Document& jsonDoc, const AZ::IO::Path& jsonFilePath, WriteJsonSettings settings = WriteJsonSettings{}); - /** * Find all the files in a path based on an optional filter. Recurse if requested. * @@ -91,38 +48,6 @@ namespace AzFramework */ AZ::Outcome ReadTextFileByLine(const AZStd::string& filePath, AZStd::function perLineCallback); - /** - * Replaces a value in an ini-style file. - * - * \param[in] filePath The path to the config file to update - * \param[in] updateRules The update rules (list of update strings, see below) to apply - * - * The replace string rule format follows the following: - * ([header]/)[key]=[value] - * - * where: - * header (optional) : Optional group title for the key - * key : The key to lookup or create for the value - * value : The value to update or create - */ - AZ::Outcome ReplaceInCfgFile(const AZStd::string& filePath, const AZStd::list& updateRules); - - /** - * Replaces a value in an ini-style file. - * - * \param[in] filePath The path to the config file to update - * \param[in] updateRule The update rule (list of update strings, see below) to apply - * - * The replace string rule format follows the following: - * ([header]/)[key]=[value] - * - * where: - * header (optional) : Optional group title for the key - * key : The key to lookup or create for the value - * value : The value to update or create - */ - AZ::Outcome ReplaceInCfgFile(const AZStd::string& filePath, const char* header, const AZStd::string& key, const AZStd::string& newValue); - /** * Gets the value(s) for a key in an INI style config file. * diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp index 0a9c937832..85b89b93dc 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp @@ -11,11 +11,12 @@ #include #include +#include #include #include +#include #include -#include #include #include #include @@ -134,7 +135,7 @@ namespace AzToolsFramework } // Read Template's prefab file from disk and parse Prefab DOM from file. - AZ::Outcome readPrefabFileResult = AzFramework::FileFunc::ReadJsonFromString(fileContent); + AZ::Outcome readPrefabFileResult = AZ::JsonSerializationUtils::ReadJsonString(fileContent); if (!readPrefabFileResult.IsSuccess()) { AZ_Error( @@ -346,7 +347,7 @@ namespace AzToolsFramework return false; } - auto outcome = AzFramework::FileFunc::WriteJsonFile(domAndFilepath->first, GetFullPath(domAndFilepath->second)); + auto outcome = AZ::JsonSerializationUtils::WriteJsonFile(domAndFilepath->first, GetFullPath(domAndFilepath->second).Native()); if (!outcome.IsSuccess()) { AZ_Error( @@ -387,7 +388,7 @@ namespace AzToolsFramework return false; } - auto outcome = AzFramework::FileFunc::WriteJsonFile(domAndFilepath->first, absolutePath); + auto outcome = AZ::JsonSerializationUtils::WriteJsonFile(domAndFilepath->first, absolutePath.Native()); if (!outcome.IsSuccess()) { AZ_Error( @@ -410,7 +411,7 @@ namespace AzToolsFramework return false; } - auto outcome = AzFramework::FileFunc::WriteJsonToString(domAndFilepath->first, output); + auto outcome = AZ::JsonSerializationUtils::WriteJsonString(domAndFilepath->first, output); if (!outcome.IsSuccess()) { AZ_Error( diff --git a/Code/Framework/AzToolsFramework/Tests/FileFunc.cpp b/Code/Framework/AzToolsFramework/Tests/FileFunc.cpp index 80b1576b33..c4299a6ff9 100644 --- a/Code/Framework/AzToolsFramework/Tests/FileFunc.cpp +++ b/Code/Framework/AzToolsFramework/Tests/FileFunc.cpp @@ -26,20 +26,6 @@ #include #include -namespace AzFramework -{ - namespace FileFunc - { - namespace Internal - { - AZ::Outcome UpdateCfgContents(AZStd::string& cfgContents, const AZStd::list& updateRules); - AZ::Outcome UpdateCfgContents(AZStd::string& cfgContents, const AZStd::string& header, const AZStd::string& key, const AZStd::string& value); - AZ::Outcome WriteJsonToStream(const rapidjson::Document& document, AZ::IO::GenericStream& stream, - WriteJsonSettings settings = WriteJsonSettings{}); - } - } -} - namespace UnitTest { class FileFuncTest : public ScopedAllocatorSetupFixture @@ -62,110 +48,6 @@ namespace UnitTest AZ::IO::FileIOBase* m_prevFileIO; }; - TEST_F(FileFuncTest, UpdateCfgContents_InValidInput_Fail) - { - AZStd::string cfgContents = "[Foo]\n"; - AZStd::list updateRules; - - updateRules.push_back(AZStd::string("Foo/one*1")); - auto result = AzFramework::FileFunc::Internal::UpdateCfgContents(cfgContents, updateRules); - ASSERT_FALSE(result.IsSuccess()); - } - - TEST_F(FileFuncTest, UpdateCfgContents_ValidInput_Success) - { - AZStd::string cfgContents = - "[Foo]\n" - "one =2 \n" - "two= 3\n" - "three = 4\n" - "\n" - "[Bar]\n" - "four=3\n" - "five=3\n" - "six=3\n" - "eight=3\n"; - - AZStd::list updateRules; - - updateRules.push_back(AZStd::string("Foo/one=1")); - updateRules.push_back(AZStd::string("Foo/two=2")); - updateRules.push_back(AZStd::string("three=3")); - auto result = AzFramework::FileFunc::Internal::UpdateCfgContents(cfgContents, updateRules); - EXPECT_TRUE(result.IsSuccess()); - - AZStd::string compareCfgContents = - "[Foo]\n" - "one =1\n" - "two= 2\n" - "three = 3\n" - "\n" - "[Bar]\n" - "four=3\n" - "five=3\n" - "six=3\n" - "eight=3\n"; - - bool equals = cfgContents.compare(compareCfgContents) == 0; - ASSERT_TRUE(equals); - } - - TEST_F(FileFuncTest, UpdateCfgContents_ValidInputNewEntrySameHeader_Success) - { - AZStd::string cfgContents = - "[Foo]\n" - "one =2 \n" - "two= 3\n" - "three = 4\n"; - - AZStd::string header("[Foo]"); - AZStd::string key("four"); - AZStd::string value("4"); - auto result = AzFramework::FileFunc::Internal::UpdateCfgContents(cfgContents, header, key, value); - EXPECT_TRUE(result.IsSuccess()); - - AZStd::string compareCfgContents = - "[Foo]\n" - "four=4\n" - "one =2 \n" - "two= 3\n" - "three = 4\n"; - - bool equals = cfgContents.compare(compareCfgContents) == 0; - ASSERT_TRUE(equals); - } - - TEST_F(FileFuncTest, UpdateCfgContents_ValidInputNewEntryDifferentHeader_Success) - { - AZStd::string cfgContents = - ";Sample Data\n" - "[Foo]\n" - "one =2 \n" - "two= 3\n" - "three = 4\n"; - - AZStd::list updateRules; - - AZStd::string header("[Bar]"); - AZStd::string key("four"); - AZStd::string value("4"); - auto result = AzFramework::FileFunc::Internal::UpdateCfgContents(cfgContents, header, key, value); - EXPECT_TRUE(result.IsSuccess()); - - AZStd::string compareCfgContents = - ";Sample Data\n" - "[Foo]\n" - "one =2 \n" - "two= 3\n" - "three = 4\n" - "\n" - "[Bar]\n" - "four=4\n"; - - bool equals = cfgContents.compare(compareCfgContents) == 0; - ASSERT_TRUE(equals); - } - static bool CreateDummyFile(const QString& fullPathToFile, const QString& tempStr = {}) { QFileInfo fi(fullPathToFile); @@ -268,213 +150,4 @@ namespace UnitTest ASSERT_NE(findElement, result.GetValue().end()); } } - - class JsonFileFuncTest - : public FrameworkApplicationFixture - { - protected: - void SetUp() override - { - FrameworkApplicationFixture::SetUp(); - - AZ::SettingsRegistryInterface* registry = AZ::SettingsRegistry::Get(); - auto projectPathKey = - AZ::SettingsRegistryInterface::FixedValueString(AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey) + "/project_path"; - registry->Set(projectPathKey, "AutomatedTesting"); - AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddRuntimeFilePaths(*registry); - - m_serializeContext = AZStd::make_unique(); - m_jsonRegistrationContext = AZStd::make_unique(); - m_jsonSystemComponent = AZStd::make_unique(); - - m_serializationSettings.m_serializeContext = m_serializeContext.get(); - m_serializationSettings.m_registrationContext = m_jsonRegistrationContext.get(); - - m_deserializationSettings.m_serializeContext = m_serializeContext.get(); - m_deserializationSettings.m_registrationContext = m_jsonRegistrationContext.get(); - - m_jsonSystemComponent->Reflect(m_jsonRegistrationContext.get()); - } - - void TearDown() override - { - m_jsonRegistrationContext->EnableRemoveReflection(); - m_jsonSystemComponent->Reflect(m_jsonRegistrationContext.get()); - m_jsonRegistrationContext->DisableRemoveReflection(); - - m_jsonRegistrationContext.reset(); - m_serializeContext.reset(); - m_jsonSystemComponent.reset(); - - FrameworkApplicationFixture::TearDown(); - } - - AZStd::unique_ptr m_serializeContext; - AZStd::unique_ptr m_jsonRegistrationContext; - AZStd::unique_ptr m_jsonSystemComponent; - - AZ::JsonSerializerSettings m_serializationSettings; - AZ::JsonDeserializerSettings m_deserializationSettings; - }; - - TEST_F(JsonFileFuncTest, WriteJsonString_ValidJson_ExpectSuccess) - { - rapidjson::Document document; - document.SetObject(); - document.AddMember("a", 1, document.GetAllocator()); - document.AddMember("b", 2, document.GetAllocator()); - document.AddMember("c", 3, document.GetAllocator()); - - AZStd::string expectedJsonText = - R"({ - "a": 1, - "b": 2, - "c": 3 - })"; - expectedJsonText.erase(AZStd::remove_if(expectedJsonText.begin(), expectedJsonText.end(), ::isspace), expectedJsonText.end()); - - AZStd::string outString; - AZ::Outcome result = AzFramework::FileFunc::WriteJsonToString(document, outString); - EXPECT_TRUE(result.IsSuccess()); - - outString.erase(AZStd::remove_if(outString.begin(), outString.end(), ::isspace), outString.end()); - EXPECT_EQ(expectedJsonText, outString) << "expected:\n" << expectedJsonText.c_str() << "\nactual:\n" << outString.c_str(); - } - - TEST_F(JsonFileFuncTest, WriteJsonStream_ValidJson_ExpectSuccess) - { - rapidjson::Document document; - document.SetObject(); - document.AddMember("a", 1, document.GetAllocator()); - document.AddMember("b", 2, document.GetAllocator()); - document.AddMember("c", 3, document.GetAllocator()); - - AZStd::string expectedJsonText = - R"({ - "a": 1, - "b": 2, - "c": 3 - })"; - expectedJsonText.erase(AZStd::remove_if(expectedJsonText.begin(), expectedJsonText.end(), ::isspace), expectedJsonText.end()); - - AZStd::vector outBuffer; - AZ::IO::ByteContainerStream> outStream{ &outBuffer }; - AZ::Outcome result = AzFramework::FileFunc::Internal::WriteJsonToStream(document, outStream); - EXPECT_TRUE(result.IsSuccess()); - - outBuffer.push_back(0); - AZStd::string outString = outBuffer.data(); - outString.erase(AZStd::remove_if(outString.begin(), outString.end(), ::isspace), outString.end()); - EXPECT_EQ(expectedJsonText, outString) << "expected:\n" << expectedJsonText.c_str() << "\nactual:\n" << outString.c_str(); - } - - TEST_F(JsonFileFuncTest, WriteJsonFile_ValidJson_ExpectSuccess) - { - AZ::Test::ScopedAutoTempDirectory tempDir; - - rapidjson::Document document; - document.SetObject(); - document.AddMember("a", 1, document.GetAllocator()); - document.AddMember("b", 2, document.GetAllocator()); - document.AddMember("c", 3, document.GetAllocator()); - - AZStd::string expectedJsonText = - R"({ - "a": 1, - "b": 2, - "c": 3 - })"; - expectedJsonText.erase(AZStd::remove_if(expectedJsonText.begin(), expectedJsonText.end(), ::isspace), expectedJsonText.end()); - - AZStd::string pathStr; - AzFramework::StringFunc::Path::ConstructFull(tempDir.GetDirectory(), "test.json", pathStr, true); - - // Write the JSON to a file - AZ::IO::Path path(pathStr); - AZ::Outcome saveResult = AzFramework::FileFunc::WriteJsonFile(document, path); - EXPECT_TRUE(saveResult.IsSuccess()); - - // Verify that the contents of the file is what we expect - AZ::Outcome readResult = AZ::Utils::ReadFile(pathStr); - EXPECT_TRUE(readResult.IsSuccess()); - AZStd::string outString(readResult.TakeValue()); - outString.erase(AZStd::remove_if(outString.begin(), outString.end(), ::isspace), outString.end()); - EXPECT_EQ(outString, expectedJsonText); - - // Clean up - AZ::IO::FileIOBase::GetInstance()->Remove(path.c_str()); - } - - TEST_F(JsonFileFuncTest, ReadJsonString_ValidJson_ExpectSuccess) - { - const char* jsonText = - R"( - { - "a": 1, - "b": 2, - "c": 3 - })"; - - AZ::Outcome result = AzFramework::FileFunc::ReadJsonFromString(jsonText); - - EXPECT_TRUE(result.IsSuccess()); - EXPECT_TRUE(result.GetValue().IsObject()); - EXPECT_TRUE(result.GetValue().HasMember("a")); - EXPECT_TRUE(result.GetValue().HasMember("b")); - EXPECT_TRUE(result.GetValue().HasMember("c")); - EXPECT_EQ(result.GetValue()["a"].GetInt(), 1); - EXPECT_EQ(result.GetValue()["b"].GetInt(), 2); - EXPECT_EQ(result.GetValue()["c"].GetInt(), 3); - } - - TEST_F(JsonFileFuncTest, ReadJsonString_InvalidJson_ErrorReportsLineNumber) - { - const char* jsonText = - R"( - { - "a": "This line is missing a comma" - "b": 2, - "c": 3 - } - )"; - - AZ::Outcome result = AzFramework::FileFunc::ReadJsonFromString(jsonText); - - EXPECT_FALSE(result.IsSuccess()); - EXPECT_TRUE(result.GetError().find("JSON parse error at line 4:") == 0); - } - - TEST_F(JsonFileFuncTest, ReadJsonFile_ValidJson_ExpectSuccess) - { - AZ::Test::ScopedAutoTempDirectory tempDir; - - const char* inputJsonText = - R"({ - "a": 1, - "b": 2, - "c": 3 - })"; - - rapidjson::Document expectedDocument; - expectedDocument.SetObject(); - expectedDocument.AddMember("a", 1, expectedDocument.GetAllocator()); - expectedDocument.AddMember("b", 2, expectedDocument.GetAllocator()); - expectedDocument.AddMember("c", 3, expectedDocument.GetAllocator()); - - // Create test file - AZStd::string path; - AzFramework::StringFunc::Path::ConstructFull(tempDir.GetDirectory(), "test.json", path, true); - AZ::Outcome writeResult = AZ::Utils::WriteFile(inputJsonText, path); - EXPECT_TRUE(writeResult.IsSuccess()); - - - // Read the JSON from the test file - AZ::Outcome readResult = AzFramework::FileFunc::ReadJsonFile(path); - EXPECT_TRUE(readResult.IsSuccess()); - - EXPECT_EQ(expectedDocument, readResult.GetValue()); - - // Clean up - AZ::IO::FileIOBase::GetInstance()->Remove(path.c_str()); - } } // namespace UnitTest diff --git a/Code/Tools/SceneAPI/SceneCore/Components/SceneSystemComponent.h b/Code/Tools/SceneAPI/SceneCore/Components/SceneSystemComponent.h index 3f47424328..296d791f9a 100644 --- a/Code/Tools/SceneAPI/SceneCore/Components/SceneSystemComponent.h +++ b/Code/Tools/SceneAPI/SceneCore/Components/SceneSystemComponent.h @@ -19,8 +19,7 @@ namespace AZ { // Scene system components are components that can be used to create system components // in situations where the full initialization and/or construction of regular - // system components don't apply such as in the Project Manager's advanced - // settings and the ResourceCompilerScene. + // system components don't apply such as in the ResourceCompilerScene. class SCENE_CORE_CLASS SceneSystemComponent : public AZ::Component { diff --git a/Code/Tools/SceneAPI/SceneCore/Containers/SceneManifest.cpp b/Code/Tools/SceneAPI/SceneCore/Containers/SceneManifest.cpp index 8bbe9e2ed3..d68b6c52d4 100644 --- a/Code/Tools/SceneAPI/SceneCore/Containers/SceneManifest.cpp +++ b/Code/Tools/SceneAPI/SceneCore/Containers/SceneManifest.cpp @@ -21,10 +21,10 @@ #include #include #include +#include #include #include #include -#include #include #include #include @@ -163,8 +163,7 @@ namespace AZ return false; } - AZ::IO::Path fileIoPath(absoluteFilePath); - auto saveToFileOutcome = AzFramework::FileFunc::WriteJsonFile(saveToJsonOutcome.GetValue(), fileIoPath); + auto saveToFileOutcome = AZ::JsonSerializationUtils::WriteJsonFile(saveToJsonOutcome.GetValue(), absoluteFilePath); if (!saveToFileOutcome.IsSuccess()) { AZ_Error(ErrorWindowName, false, "%s%s", errorMsg.c_str(), saveToFileOutcome.GetError().c_str()); @@ -309,7 +308,7 @@ namespace AZ else { // Attempt to read the stream as JSON - auto readJsonOutcome = AzFramework::FileFunc::ReadJsonFromString(fileContents); + auto readJsonOutcome = AZ::JsonSerializationUtils::ReadJsonString(fileContents); AZStd::string errorMsg; if (!readJsonOutcome.IsSuccess()) { diff --git a/Code/Tools/SceneAPI/SceneCore/Tests/Containers/SceneManifestTests.cpp b/Code/Tools/SceneAPI/SceneCore/Tests/Containers/SceneManifestTests.cpp index 875e433bb7..1766395626 100644 --- a/Code/Tools/SceneAPI/SceneCore/Tests/Containers/SceneManifestTests.cpp +++ b/Code/Tools/SceneAPI/SceneCore/Tests/Containers/SceneManifestTests.cpp @@ -14,8 +14,8 @@ #include #include #include +#include #include -#include #include #include #include @@ -325,7 +325,7 @@ namespace AZ ASSERT_TRUE(writeToJsonResult.IsSuccess()); AZStd::string jsonText; - auto writeToStringResult = AzFramework::FileFunc::WriteJsonToString(writeToJsonResult.GetValue(), jsonText); + auto writeToStringResult = AZ::JsonSerializationUtils::WriteJsonString(writeToJsonResult.GetValue(), jsonText); ASSERT_TRUE(writeToStringResult.IsSuccess()); MockSceneManifest loaded; @@ -340,7 +340,7 @@ namespace AZ ASSERT_TRUE(writeToJsonResult.IsSuccess()); AZStd::string jsonText; - auto writeToStringResult = AzFramework::FileFunc::WriteJsonToString(writeToJsonResult.GetValue(), jsonText); + auto writeToStringResult = AZ::JsonSerializationUtils::WriteJsonString(writeToJsonResult.GetValue(), jsonText); ASSERT_TRUE(writeToStringResult.IsSuccess()); MockSceneManifest loaded; @@ -371,7 +371,7 @@ namespace AZ ASSERT_TRUE(writeToJsonResult.IsSuccess()); AZStd::string jsonText; - auto writeToStringResult = AzFramework::FileFunc::WriteJsonToString(writeToJsonResult.GetValue(), jsonText); + auto writeToStringResult = AZ::JsonSerializationUtils::WriteJsonString(writeToJsonResult.GetValue(), jsonText); ASSERT_TRUE(writeToStringResult.IsSuccess()); // Deserialize JSON diff --git a/Code/Tools/SceneAPI/SceneData/Tests/SceneManifest/SceneManifestRuleTests.cpp b/Code/Tools/SceneAPI/SceneData/Tests/SceneManifest/SceneManifestRuleTests.cpp index 428788f626..e0d5cca484 100644 --- a/Code/Tools/SceneAPI/SceneData/Tests/SceneManifest/SceneManifestRuleTests.cpp +++ b/Code/Tools/SceneAPI/SceneData/Tests/SceneManifest/SceneManifestRuleTests.cpp @@ -20,12 +20,12 @@ #include #include #include +#include #include #include #include #include #include -#include namespace AZ { @@ -154,7 +154,7 @@ namespace AZ ASSERT_TRUE(writeToJsonResult.IsSuccess()); AZStd::string jsonText; - auto writeToStringResult = AzFramework::FileFunc::WriteJsonToString(writeToJsonResult.GetValue(), jsonText); + auto writeToStringResult = AZ::JsonSerializationUtils::WriteJsonString(writeToJsonResult.GetValue(), jsonText); ASSERT_TRUE(writeToStringResult.IsSuccess()); EXPECT_THAT(jsonText.c_str(), ::testing::HasSubstr(R"("$type": "MockRotationRule")")); EXPECT_THAT(jsonText.c_str(), ::testing::HasSubstr(R"("rotation": [)")); @@ -191,7 +191,7 @@ namespace AZ ASSERT_TRUE(writeToJsonResult.IsSuccess()); AZStd::string jsonText; - auto writeToStringResult = AzFramework::FileFunc::WriteJsonToString(writeToJsonResult.GetValue(), jsonText); + auto writeToStringResult = AZ::JsonSerializationUtils::WriteJsonString(writeToJsonResult.GetValue(), jsonText); ASSERT_TRUE(writeToStringResult.IsSuccess()); EXPECT_THAT(jsonText.c_str(), ::testing::HasSubstr(R"("$type": "MockRotationRule")")); EXPECT_THAT(jsonText.c_str(), ::testing::HasSubstr(R"("rotation": [)")); @@ -230,7 +230,7 @@ namespace AZ ASSERT_TRUE(writeToJsonResult.IsSuccess()); AZStd::string jsonText; - auto writeToStringResult = AzFramework::FileFunc::WriteJsonToString(writeToJsonResult.GetValue(), jsonText); + auto writeToStringResult = AZ::JsonSerializationUtils::WriteJsonString(writeToJsonResult.GetValue(), jsonText); ASSERT_TRUE(writeToStringResult.IsSuccess()); EXPECT_THAT(jsonText.c_str(), ::testing::HasSubstr(R"("$type": "CoordinateSystemRule")")); EXPECT_THAT(jsonText.c_str(), ::testing::HasSubstr(R"("useAdvancedData": true,)")); diff --git a/Gems/AWSCore/Code/Source/ResourceMapping/AWSResourceMappingManager.cpp b/Gems/AWSCore/Code/Source/ResourceMapping/AWSResourceMappingManager.cpp index 7b5196462c..c3d87bff86 100644 --- a/Gems/AWSCore/Code/Source/ResourceMapping/AWSResourceMappingManager.cpp +++ b/Gems/AWSCore/Code/Source/ResourceMapping/AWSResourceMappingManager.cpp @@ -9,9 +9,9 @@ #include #include #include +#include #include #include -#include #include #include @@ -211,8 +211,7 @@ namespace AWSCore } AzFramework::StringFunc::Path::Normalize(configJsonPath); - AZ::IO::Path configJsonFileIOPath(configJsonPath); - auto readJsonOutcome = AzFramework::FileFunc::ReadJsonFile(configJsonFileIOPath); + auto readJsonOutcome = AZ::JsonSerializationUtils::ReadJsonFile(configJsonPath); if (readJsonOutcome.IsSuccess()) { auto jsonDocument = readJsonOutcome.TakeValue(); diff --git a/Gems/AWSMetrics/Code/Source/IdentityProvider.cpp b/Gems/AWSMetrics/Code/Source/IdentityProvider.cpp index aa0f59976f..7e4ec05aba 100644 --- a/Gems/AWSMetrics/Code/Source/IdentityProvider.cpp +++ b/Gems/AWSMetrics/Code/Source/IdentityProvider.cpp @@ -11,7 +11,7 @@ #include #include #include -#include +#include namespace AWSMetrics { @@ -39,8 +39,7 @@ namespace AWSMetrics return ""; } - AZ::IO::Path configIoPath(resolvedPath); - auto readOutcome = AzFramework::FileFunc::ReadJsonFile(configIoPath, fileIO); + auto readOutcome = AZ::JsonSerializationUtils::ReadJsonFile(resolvedPath); if (!readOutcome.IsSuccess()) { AZ_Error("AWSMetrics", false, readOutcome.GetError().c_str()); diff --git a/Gems/AWSMetrics/Code/Source/MetricsEvent.cpp b/Gems/AWSMetrics/Code/Source/MetricsEvent.cpp index e23c97a5fe..737ef6abc5 100644 --- a/Gems/AWSMetrics/Code/Source/MetricsEvent.cpp +++ b/Gems/AWSMetrics/Code/Source/MetricsEvent.cpp @@ -11,7 +11,7 @@ #include #include -#include +#include #include @@ -150,7 +150,7 @@ namespace AWSMetrics return false; } - auto result = AzFramework::FileFunc::ReadJsonFromString(stringStream.str().c_str()); + auto result = AZ::JsonSerializationUtils::ReadJsonString(stringStream.str().c_str()); if (!result.IsSuccess()) { return false; diff --git a/Gems/AWSMetrics/Code/Source/MetricsQueue.cpp b/Gems/AWSMetrics/Code/Source/MetricsQueue.cpp index 4cc037189a..ec90cf28ef 100644 --- a/Gems/AWSMetrics/Code/Source/MetricsQueue.cpp +++ b/Gems/AWSMetrics/Code/Source/MetricsQueue.cpp @@ -14,8 +14,8 @@ #include #include #include +#include #include -#include #include @@ -191,15 +191,7 @@ namespace AWSMetrics bool MetricsQueue::ReadFromJson(const AZStd::string& filePath) { - AZ::IO::FileIOBase* fileIO = AZ::IO::FileIOBase::GetDirectInstance(); - if (!fileIO) - { - AZ_Error("AWSMetrics", false, "Failed to get file IO instance"); - return false; - } - - AZ::IO::Path fileIoPath(filePath); - auto result = AzFramework::FileFunc::ReadJsonFile(fileIoPath, fileIO); + auto result = AZ::JsonSerializationUtils::ReadJsonFile(filePath); if (!result.IsSuccess() ||!ReadFromJsonDocument(result.GetValue())) { AZ_Error("AWSMetrics", false, "Failed to read metrics file %s", filePath.c_str()); diff --git a/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/MotionEventExport.cpp b/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/MotionEventExport.cpp index e1bde1ff79..d2a69bca67 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/MotionEventExport.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Exporters/ExporterLib/Exporter/MotionEventExport.cpp @@ -11,8 +11,8 @@ #include #include #include +#include #include -#include #include "Exporter.h" #include #include @@ -55,10 +55,10 @@ namespace ExporterLib } AZStd::string serializedMotionEventTable; - auto writeToStringOutcome = AzFramework::FileFunc::WriteJsonToString(jsonDocument, serializedMotionEventTable); + auto writeToStringOutcome = AZ::JsonSerializationUtils::WriteJsonString(jsonDocument, serializedMotionEventTable); if (!writeToStringOutcome.IsSuccess()) { - AZ_Error("EMotionFX", false, "WriteJsonToString failed: %s", writeToStringOutcome.GetError().c_str()); + AZ_Error("EMotionFX", false, "WriteJsonString failed: %s", writeToStringOutcome.GetError().c_str()); return; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ChunkProcessors.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ChunkProcessors.cpp index fad160407b..10f9c0dc60 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ChunkProcessors.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ChunkProcessors.cpp @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include #include @@ -1081,11 +1081,11 @@ namespace EMotionFX file->Read(&buffer[0], fileEventTable.m_size); AZStd::string_view bufferStringView(&buffer[0], buffer.size()); - auto readJsonOutcome = AzFramework::FileFunc::ReadJsonFromString(bufferStringView); + auto readJsonOutcome = AZ::JsonSerializationUtils::ReadJsonString(bufferStringView); AZStd::string errorMsg; if (!readJsonOutcome.IsSuccess()) { - AZ_Error("EMotionFX", false, "Loading motion event table failed due to ReadJsonFromString. %s", readJsonOutcome.TakeError().c_str()); + AZ_Error("EMotionFX", false, "Loading motion event table failed due to ReadJsonString. %s", readJsonOutcome.TakeError().c_str()); return false; } rapidjson::Document document = readJsonOutcome.TakeValue(); diff --git a/Gems/LmbrCentral/Code/Source/Builders/SliceBuilder/SliceBuilderWorker.cpp b/Gems/LmbrCentral/Code/Source/Builders/SliceBuilder/SliceBuilderWorker.cpp index 88284ede1d..b65a3e917c 100644 --- a/Gems/LmbrCentral/Code/Source/Builders/SliceBuilder/SliceBuilderWorker.cpp +++ b/Gems/LmbrCentral/Code/Source/Builders/SliceBuilder/SliceBuilderWorker.cpp @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -27,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -73,9 +73,7 @@ namespace SliceBuilder AzFramework::StringFunc::Path::Join(relativePath.c_str(), settingsAssetInfo.m_relativePath.c_str(), sliceBuilderSettingsPath, true, true); // Attempt to load the Slice Builder Settings file - AZ::IO::LocalFileIO localFileIO; - AZ::IO::Path sliceBuilderSettingsIoPath(sliceBuilderSettingsPath); - auto result = AzFramework::FileFunc::ReadJsonFile(sliceBuilderSettingsIoPath, &localFileIO); + auto result = AZ::JsonSerializationUtils::ReadJsonFile(sliceBuilderSettingsPath); if (result.IsSuccess()) { AZ::JsonSerializationResult::ResultCode serializaionResult = AZ::JsonSerialization::Load(m_settings, result.GetValue()); diff --git a/Gems/Prefab/PrefabBuilder/PrefabBuilderComponent.cpp b/Gems/Prefab/PrefabBuilder/PrefabBuilderComponent.cpp index bffb64e51b..a86d7b57e2 100644 --- a/Gems/Prefab/PrefabBuilder/PrefabBuilderComponent.cpp +++ b/Gems/Prefab/PrefabBuilder/PrefabBuilderComponent.cpp @@ -132,7 +132,7 @@ namespace AZ::Prefab AZ::StringFunc::Path::ConstructFull(request.m_watchFolder.c_str(), request.m_sourceFile.c_str(), fullPath); // Load the JSON Dom - AZ::Outcome readPrefabFileResult = AzFramework::FileFunc::ReadJsonFile(AZ::IO::Path(fullPath)); + AZ::Outcome readPrefabFileResult = AZ::JsonSerializationUtils::ReadJsonFile(fullPath); if (!readPrefabFileResult.IsSuccess()) { AZ_Error( diff --git a/Gems/Prefab/PrefabBuilder/PrefabBuilderComponent.h b/Gems/Prefab/PrefabBuilder/PrefabBuilderComponent.h index 1458c8dd40..9ebdd690f5 100644 --- a/Gems/Prefab/PrefabBuilder/PrefabBuilderComponent.h +++ b/Gems/Prefab/PrefabBuilder/PrefabBuilderComponent.h @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/Gems/Prefab/PrefabBuilder/PrefabBuilderTests.cpp b/Gems/Prefab/PrefabBuilder/PrefabBuilderTests.cpp index 95827d4457..7d3096a6da 100644 --- a/Gems/Prefab/PrefabBuilder/PrefabBuilderTests.cpp +++ b/Gems/Prefab/PrefabBuilder/PrefabBuilderTests.cpp @@ -9,6 +9,7 @@ #include "PrefabBuilderTests.h" #include #include +#include #include #include #include @@ -56,7 +57,7 @@ namespace UnitTest // Save to a string so we can load it as a PrefabDom and so that the nested instance becomes a Source file reference ASSERT_TRUE(prefabLoaderInterface->SaveTemplateToString(parentInstance->GetTemplateId(), serializedInstance)); - AZ::Outcome readPrefabFileResult = AzFramework::FileFunc::ReadJsonFromString(serializedInstance); + AZ::Outcome readPrefabFileResult = AZ::JsonSerializationUtils::ReadJsonString(serializedInstance); ASSERT_TRUE(readPrefabFileResult.IsSuccess()); diff --git a/Gems/SceneLoggingExample/Code/SceneLoggingExampleModule.cpp b/Gems/SceneLoggingExample/Code/SceneLoggingExampleModule.cpp index 2c12344873..9a03d7c1ce 100644 --- a/Gems/SceneLoggingExample/Code/SceneLoggingExampleModule.cpp +++ b/Gems/SceneLoggingExample/Code/SceneLoggingExampleModule.cpp @@ -42,7 +42,7 @@ namespace SceneLoggingExample } // In this example, no system components are added. You can use system components - // to set global settings for this gem from the Project Manager. + // to set global settings for this gem. // For functionality that should always be available to the SceneAPI, we recommend // that you use a BehaviorComponent instead. AZ::ComponentTypeList GetRequiredSystemComponents() const override diff --git a/Gems/SceneProcessing/Code/Source/Config/Components/SceneProcessingConfigSystemComponent.cpp b/Gems/SceneProcessing/Code/Source/Config/Components/SceneProcessingConfigSystemComponent.cpp index 93d8fc6a06..ea0c3520bf 100644 --- a/Gems/SceneProcessing/Code/Source/Config/Components/SceneProcessingConfigSystemComponent.cpp +++ b/Gems/SceneProcessing/Code/Source/Config/Components/SceneProcessingConfigSystemComponent.cpp @@ -34,7 +34,7 @@ namespace AZ ActivateSceneModule(SceneProcessing::s_sceneDataModule); ActivateSceneModule(SceneProcessing::s_sceneBuilderModule); - // Defaults in case there's no config setup in the Project Manager. + // Defaults in case there's no config setup m_softNames.push_back(aznew NodeSoftNameSetting("^.*_[Ll][Oo][Dd]1(_optimized)?$", PatternMatcher::MatchApproach::Regex, "LODMesh1", true)); m_softNames.push_back(aznew NodeSoftNameSetting("^.*_[Ll][Oo][Dd]2(_optimized)?$", PatternMatcher::MatchApproach::Regex, "LODMesh2", true)); m_softNames.push_back(aznew NodeSoftNameSetting("^.*_[Ll][Oo][Dd]3(_optimized)?$", PatternMatcher::MatchApproach::Regex, "LODMesh3", true)); From da6bdd5b43dabdac3c8980d82efa5859e59fd484 Mon Sep 17 00:00:00 2001 From: Vincent Liu <5900509+onecent1101@users.noreply.github.com> Date: Mon, 30 Aug 2021 13:06:29 -0700 Subject: [PATCH 784/803] [LYN-4065] Expose GameLift server api to notify server process ready (#2409) --- .../Code/AWSGameLiftServer/CMakeLists.txt | 2 + .../Request/IAWSGameLiftServerRequests.h | 43 +++++++++++++++ .../Source/AWSGameLiftServerManager.cpp | 55 +++++++++++++++++-- .../Source/AWSGameLiftServerManager.h | 21 ++++--- .../AWSGameLiftServerSystemComponent.cpp | 39 +------------ .../Source/AWSGameLiftServerSystemComponent.h | 4 -- .../Tests/AWSGameLiftServerManagerTest.cpp | 48 ++++++++++------ .../AWSGameLiftServerSystemComponentTest.cpp | 16 ------ .../awsgamelift_server_files.cmake | 1 + 9 files changed, 142 insertions(+), 87 deletions(-) create mode 100644 Gems/AWSGameLift/Code/AWSGameLiftServer/Include/Request/IAWSGameLiftServerRequests.h diff --git a/Gems/AWSGameLift/Code/AWSGameLiftServer/CMakeLists.txt b/Gems/AWSGameLift/Code/AWSGameLiftServer/CMakeLists.txt index 4fa2ddd82b..798c6a6a25 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftServer/CMakeLists.txt +++ b/Gems/AWSGameLift/Code/AWSGameLiftServer/CMakeLists.txt @@ -16,6 +16,8 @@ ly_add_target( FILES_CMAKE awsgamelift_server_files.cmake INCLUDE_DIRECTORIES + PUBLIC + Include PRIVATE ../AWSGameLiftCommon/Source Source diff --git a/Gems/AWSGameLift/Code/AWSGameLiftServer/Include/Request/IAWSGameLiftServerRequests.h b/Gems/AWSGameLift/Code/AWSGameLiftServer/Include/Request/IAWSGameLiftServerRequests.h new file mode 100644 index 0000000000..e5b14319a8 --- /dev/null +++ b/Gems/AWSGameLift/Code/AWSGameLiftServer/Include/Request/IAWSGameLiftServerRequests.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#pragma once + +#include +#include +#include +#include + +namespace AWSGameLift +{ + //! IAWSGameLiftServerRequests + //! Server interfaces to expose Amazon GameLift Server SDK + class IAWSGameLiftServerRequests + { + public: + AZ_RTTI(IAWSGameLiftServerRequests, "{D76CD98D-4C37-4C25-82C4-4E8772706D70}"); + + IAWSGameLiftServerRequests() = default; + virtual ~IAWSGameLiftServerRequests() = default; + + //! Notify GameLift that the server process is ready to host a game session. + //! @return Whether the ProcessReady notification is sent to GameLift. + virtual bool NotifyGameLiftProcessReady() = 0; + }; + + // IAWSGameLiftServerRequests EBus wrapper for scripting + class AWSGameLiftServerRequests + : public AZ::EBusTraits + { + public: + using MutexType = AZStd::recursive_mutex; + static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single; + static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; + }; + using AWSGameLiftServerRequestBus = AZ::EBus; +} // namespace AWSGameLift diff --git a/Gems/AWSGameLift/Code/AWSGameLiftServer/Source/AWSGameLiftServerManager.cpp b/Gems/AWSGameLift/Code/AWSGameLiftServer/Source/AWSGameLiftServerManager.cpp index 94d6a7dac1..e739933ab2 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftServer/Source/AWSGameLiftServerManager.cpp +++ b/Gems/AWSGameLift/Code/AWSGameLiftServer/Source/AWSGameLiftServerManager.cpp @@ -10,8 +10,11 @@ #include #include +#include #include #include +#include +#include #include #include #include @@ -32,6 +35,18 @@ namespace AWSGameLift m_connectedPlayers.clear(); } + void AWSGameLiftServerManager::ActivateManager() + { + AZ::Interface::Register(this); + AWSGameLiftServerRequestBus::Handler::BusConnect(); + } + + void AWSGameLiftServerManager::DeactivateManager() + { + AWSGameLiftServerRequestBus::Handler::BusDisconnect(); + AZ::Interface::Unregister(this); + } + bool AWSGameLiftServerManager::AddConnectedPlayer(const AzFramework::PlayerConnectionConfig& playerConnectionConfig) { AZStd::lock_guard lock(m_gameliftMutex); @@ -51,6 +66,37 @@ namespace AWSGameLift } } + GameLiftServerProcessDesc AWSGameLiftServerManager::BuildGameLiftServerProcessDesc() + { + GameLiftServerProcessDesc serverProcessDesc; + AZ::IO::FileIOBase* fileIO = AZ::IO::FileIOBase::GetDirectInstance(); + if (fileIO) + { + const char pathToLogFolder[] = "@log@/"; + char resolvedPath[AZ_MAX_PATH_LEN]; + if (fileIO->ResolvePath(pathToLogFolder, resolvedPath, AZ_ARRAY_SIZE(resolvedPath))) + { + serverProcessDesc.m_logPaths.push_back(resolvedPath); + } + else + { + AZ_Error(AWSGameLiftServerManagerName, false, "Failed to resolve the path to the log folder."); + } + } + else + { + AZ_Error(AWSGameLiftServerManagerName, false, "Failed to get File IO."); + } + + if (auto console = AZ::Interface::Get(); console != nullptr) + { + [[maybe_unused]] AZ::GetValueResult getCvarResult = console->GetCvarValue("sv_port", serverProcessDesc.m_port); + AZ_Error(AWSGameLiftServerManagerName, getCvarResult == AZ::GetValueResult::Success, + "Lookup of 'sv_port' console variable failed with error %s", AZ::GetEnumString(getCvarResult)); + } + return serverProcessDesc; + } + AzFramework::SessionConfig AWSGameLiftServerManager::BuildSessionConfig(const Aws::GameLift::Server::Model::GameSession& gameSession) { AzFramework::SessionConfig sessionConfig; @@ -99,12 +145,12 @@ namespace AWSGameLift return AZ::IO::Path(); } - bool AWSGameLiftServerManager::InitializeGameLiftServerSDK() + void AWSGameLiftServerManager::InitializeGameLiftServerSDK() { if (m_serverSDKInitialized) { AZ_Error(AWSGameLiftServerManagerName, false, AWSGameLiftServerSDKAlreadyInitErrorMessage); - return false; + return; } AZ_TracePrintf(AWSGameLiftServerManagerName, "Initiating Amazon GameLift Server SDK ..."); @@ -115,8 +161,6 @@ namespace AWSGameLift AZ_Error(AWSGameLiftServerManagerName, m_serverSDKInitialized, AWSGameLiftServerInitSDKErrorMessage, initOutcome.GetError().GetErrorMessage().c_str()); - - return m_serverSDKInitialized; } void AWSGameLiftServerManager::HandleDestroySession() @@ -170,7 +214,7 @@ namespace AWSGameLift playerSessionId.c_str(), disconnectOutcome.GetError().GetErrorMessage().c_str()); } - bool AWSGameLiftServerManager::NotifyGameLiftProcessReady(const GameLiftServerProcessDesc& desc) + bool AWSGameLiftServerManager::NotifyGameLiftProcessReady() { if (!m_serverSDKInitialized) { @@ -178,6 +222,7 @@ namespace AWSGameLift return false; } + GameLiftServerProcessDesc desc = BuildGameLiftServerProcessDesc(); AZ_Warning(AWSGameLiftServerManagerName, desc.m_port != 0, AWSGameLiftServerTempPortErrorMessage); AZ::JobContext* jobContext = nullptr; diff --git a/Gems/AWSGameLift/Code/AWSGameLiftServer/Source/AWSGameLiftServerManager.h b/Gems/AWSGameLift/Code/AWSGameLiftServer/Source/AWSGameLiftServerManager.h index 09c9d4a719..c0f1c00bea 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftServer/Source/AWSGameLiftServerManager.h +++ b/Gems/AWSGameLift/Code/AWSGameLiftServer/Source/AWSGameLiftServerManager.h @@ -16,6 +16,7 @@ #include #include #include +#include namespace AWSGameLift { @@ -31,7 +32,8 @@ namespace AWSGameLift //! Manage the server process for hosting game sessions via GameLiftServerSDK. class AWSGameLiftServerManager - : public AzFramework::ISessionHandlingProviderRequests + : public AWSGameLiftServerRequestBus::Handler + , public AzFramework::ISessionHandlingProviderRequests { public: static constexpr const char AWSGameLiftServerManagerName[] = "AWSGameLiftServerManager"; @@ -68,14 +70,14 @@ namespace AWSGameLift AWSGameLiftServerManager(); virtual ~AWSGameLiftServerManager(); - //! Initialize GameLift API client by calling InitSDK(). - //! @return Whether the initialization is successful. - bool InitializeGameLiftServerSDK(); + void ActivateManager(); + void DeactivateManager(); - //! Notify GameLift that the server process is ready to host a game session. - //! @param desc GameLift server process settings. - //! @return Whether the ProcessReady notification is sent to GameLift. - bool NotifyGameLiftProcessReady(const GameLiftServerProcessDesc& desc); + //! Initialize GameLift API client by calling InitSDK(). + void InitializeGameLiftServerSDK(); + + // AWSGameLiftServerRequestBus interface implementation + bool NotifyGameLiftProcessReady() override; // ISessionHandlingProviderRequests interface implementation void HandleDestroySession() override; @@ -91,6 +93,9 @@ namespace AWSGameLift bool AddConnectedPlayer(const AzFramework::PlayerConnectionConfig& playerConnectionConfig); private: + //! Build the serverProcessDesc with appropriate server port number and log paths. + GameLiftServerProcessDesc BuildGameLiftServerProcessDesc(); + //! Build session config by using AWS GameLift Server GameSession Model. AzFramework::SessionConfig BuildSessionConfig(const Aws::GameLift::Server::Model::GameSession& gameSession); diff --git a/Gems/AWSGameLift/Code/AWSGameLiftServer/Source/AWSGameLiftServerSystemComponent.cpp b/Gems/AWSGameLift/Code/AWSGameLiftServer/Source/AWSGameLiftServerSystemComponent.cpp index edcdef3c26..a3f60fb849 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftServer/Source/AWSGameLiftServerSystemComponent.cpp +++ b/Gems/AWSGameLift/Code/AWSGameLiftServer/Source/AWSGameLiftServerSystemComponent.cpp @@ -74,49 +74,16 @@ namespace AWSGameLift void AWSGameLiftServerSystemComponent::Activate() { - if (m_gameLiftServerManager->InitializeGameLiftServerSDK()) - { - GameLiftServerProcessDesc serverProcessDesc; - UpdateGameLiftServerProcessDesc(serverProcessDesc); - m_gameLiftServerManager->NotifyGameLiftProcessReady(serverProcessDesc); - } + m_gameLiftServerManager->InitializeGameLiftServerSDK(); + m_gameLiftServerManager->ActivateManager(); } void AWSGameLiftServerSystemComponent::Deactivate() { + m_gameLiftServerManager->DeactivateManager(); m_gameLiftServerManager->HandleDestroySession(); } - void AWSGameLiftServerSystemComponent::UpdateGameLiftServerProcessDesc(GameLiftServerProcessDesc& serverProcessDesc) - { - AZ::IO::FileIOBase* fileIO = AZ::IO::FileIOBase::GetDirectInstance(); - if (fileIO) - { - const char pathToLogFolder[] = "@log@/"; - char resolvedPath[AZ_MAX_PATH_LEN]; - if (fileIO->ResolvePath(pathToLogFolder, resolvedPath, AZ_ARRAY_SIZE(resolvedPath))) - { - serverProcessDesc.m_logPaths.push_back(resolvedPath); - } - else - { - AZ_Error("AWSGameLift", false, "Failed to resolve the path to the log folder."); - } - } - else - { - AZ_Error("AWSGameLift", false, "Failed to get File IO."); - } - - if (auto console = AZ::Interface::Get(); console != nullptr) - { - [[maybe_unused]] AZ::GetValueResult getCvarResult = console->GetCvarValue("sv_port", serverProcessDesc.m_port); - AZ_Error( - "AWSGameLift", getCvarResult == AZ::GetValueResult::Success, "Lookup of 'sv_port' console variable failed with error %s", - AZ::GetEnumString(getCvarResult)); - } - } - void AWSGameLiftServerSystemComponent::SetGameLiftServerManager(AZStd::unique_ptr gameLiftServerManager) { m_gameLiftServerManager.reset(); diff --git a/Gems/AWSGameLift/Code/AWSGameLiftServer/Source/AWSGameLiftServerSystemComponent.h b/Gems/AWSGameLift/Code/AWSGameLiftServer/Source/AWSGameLiftServerSystemComponent.h index 3df7629c9f..d70558254c 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftServer/Source/AWSGameLiftServerSystemComponent.h +++ b/Gems/AWSGameLift/Code/AWSGameLiftServer/Source/AWSGameLiftServerSystemComponent.h @@ -43,10 +43,6 @@ namespace AWSGameLift void SetGameLiftServerManager(AZStd::unique_ptr gameLiftServerManager); private: - //! Update the serverProcessDesc with appropriate server port number and log paths. - //! @param serverProcessDesc Desc object to update. - void UpdateGameLiftServerProcessDesc(GameLiftServerProcessDesc& serverProcessDesc); - AZStd::unique_ptr m_gameLiftServerManager; }; diff --git a/Gems/AWSGameLift/Code/AWSGameLiftServer/Tests/AWSGameLiftServerManagerTest.cpp b/Gems/AWSGameLift/Code/AWSGameLiftServer/Tests/AWSGameLiftServerManagerTest.cpp index e0a7caba24..2c8929b297 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftServer/Tests/AWSGameLiftServerManagerTest.cpp +++ b/Gems/AWSGameLift/Code/AWSGameLiftServer/Tests/AWSGameLiftServerManagerTest.cpp @@ -10,6 +10,7 @@ #include #include +#include #include #include @@ -44,26 +45,39 @@ namespace UnitTest GameLiftServerProcessDesc serverDesc; m_serverManager = AZStd::make_unique>(); + + // Set up the file IO and alias + m_localFileIO = aznew AZ::IO::LocalFileIO(); + m_priorFileIO = AZ::IO::FileIOBase::GetInstance(); + + AZ::IO::FileIOBase::SetInstance(nullptr); + AZ::IO::FileIOBase::SetInstance(m_localFileIO); + m_localFileIO->SetAlias("@log@", AZ_TRAIT_TEST_ROOT_FOLDER); } void TearDown() override { + AZ::IO::FileIOBase::SetInstance(nullptr); + delete m_localFileIO; + AZ::IO::FileIOBase::SetInstance(m_priorFileIO); + m_serverManager.reset(); AWSGameLiftServerFixture::TearDown(); } AZStd::unique_ptr> m_serverManager; + AZ::IO::FileIOBase* m_priorFileIO; + AZ::IO::FileIOBase* m_localFileIO; }; TEST_F(GameLiftServerManagerTest, InitializeGameLiftServerSDK_InitializeTwice_InitSDKCalledOnce) { EXPECT_CALL(*(m_serverManager->m_gameLiftServerSDKWrapperMockPtr), InitSDK()).Times(1); - - EXPECT_TRUE(m_serverManager->InitializeGameLiftServerSDK()); + m_serverManager->InitializeGameLiftServerSDK(); AZ_TEST_START_TRACE_SUPPRESSION; - EXPECT_FALSE(m_serverManager->InitializeGameLiftServerSDK()); + m_serverManager->InitializeGameLiftServerSDK(); AZ_TEST_STOP_TRACE_SUPPRESSION(1); } @@ -72,36 +86,34 @@ namespace UnitTest EXPECT_CALL(*(m_serverManager->m_gameLiftServerSDKWrapperMockPtr), ProcessReady(testing::_)).Times(0); AZ_TEST_START_TRACE_SUPPRESSION; - EXPECT_FALSE(m_serverManager->NotifyGameLiftProcessReady(GameLiftServerProcessDesc())); + EXPECT_FALSE(m_serverManager->NotifyGameLiftProcessReady()); AZ_TEST_STOP_TRACE_SUPPRESSION(1); } TEST_F(GameLiftServerManagerTest, NotifyGameLiftProcessReady_SDKInitialized_ProcessReadyNotificationSent) { - EXPECT_TRUE(m_serverManager->InitializeGameLiftServerSDK()); - + m_serverManager->InitializeGameLiftServerSDK(); EXPECT_CALL(*(m_serverManager->m_gameLiftServerSDKWrapperMockPtr), ProcessReady(testing::_)).Times(1); - EXPECT_TRUE(m_serverManager->NotifyGameLiftProcessReady(GameLiftServerProcessDesc())); + EXPECT_TRUE(m_serverManager->NotifyGameLiftProcessReady()); } TEST_F(GameLiftServerManagerTest, NotifyGameLiftProcessReady_ProcessReadyFails_TerminationNotificationSent) { - EXPECT_TRUE(m_serverManager->InitializeGameLiftServerSDK()); - + m_serverManager->InitializeGameLiftServerSDK(); EXPECT_CALL(*(m_serverManager->m_gameLiftServerSDKWrapperMockPtr), ProcessReady(testing::_)) .Times(1) .WillOnce(testing::Return(Aws::GameLift::GenericOutcome())); EXPECT_CALL(*(m_serverManager->m_gameLiftServerSDKWrapperMockPtr), ProcessEnding()).Times(1); AZ_TEST_START_TRACE_SUPPRESSION; - EXPECT_TRUE(m_serverManager->NotifyGameLiftProcessReady(GameLiftServerProcessDesc())); + EXPECT_TRUE(m_serverManager->NotifyGameLiftProcessReady()); AZ_TEST_STOP_TRACE_SUPPRESSION(1); } TEST_F(GameLiftServerManagerTest, OnProcessTerminate_OnDestroySessionBeginReturnsFalse_FailToNotifyGameLift) { m_serverManager->InitializeGameLiftServerSDK(); - m_serverManager->NotifyGameLiftProcessReady(GameLiftServerProcessDesc()); + m_serverManager->NotifyGameLiftProcessReady(); if (!AZ::Interface::Get()) { AZ::Interface::Register(m_serverManager.get()); @@ -122,7 +134,7 @@ namespace UnitTest TEST_F(GameLiftServerManagerTest, OnProcessTerminate_OnDestroySessionBeginReturnsTrue_TerminationNotificationSent) { m_serverManager->InitializeGameLiftServerSDK(); - m_serverManager->NotifyGameLiftProcessReady(GameLiftServerProcessDesc()); + m_serverManager->NotifyGameLiftProcessReady(); if (!AZ::Interface::Get()) { AZ::Interface::Register(m_serverManager.get()); @@ -141,7 +153,7 @@ namespace UnitTest TEST_F(GameLiftServerManagerTest, OnHealthCheck_OnSessionHealthCheckReturnsTrue_CallbackFunctionReturnsTrue) { m_serverManager->InitializeGameLiftServerSDK(); - m_serverManager->NotifyGameLiftProcessReady(GameLiftServerProcessDesc()); + m_serverManager->NotifyGameLiftProcessReady(); SessionNotificationsHandlerMock handlerMock; EXPECT_CALL(handlerMock, OnSessionHealthCheck()).Times(1).WillOnce(testing::Return(true)); EXPECT_TRUE(m_serverManager->m_gameLiftServerSDKWrapperMockPtr->m_healthCheckFunc()); @@ -150,7 +162,7 @@ namespace UnitTest TEST_F(GameLiftServerManagerTest, OnHealthCheck_OnSessionHealthCheckReturnsFalseAndTrue_CallbackFunctionReturnsFalse) { m_serverManager->InitializeGameLiftServerSDK(); - m_serverManager->NotifyGameLiftProcessReady(GameLiftServerProcessDesc()); + m_serverManager->NotifyGameLiftProcessReady(); SessionNotificationsHandlerMock handlerMock1; EXPECT_CALL(handlerMock1, OnSessionHealthCheck()).Times(1).WillOnce(testing::Return(false)); SessionNotificationsHandlerMock handlerMock2; @@ -161,7 +173,7 @@ namespace UnitTest TEST_F(GameLiftServerManagerTest, OnHealthCheck_OnSessionHealthCheckReturnsFalse_CallbackFunctionReturnsFalse) { m_serverManager->InitializeGameLiftServerSDK(); - m_serverManager->NotifyGameLiftProcessReady(GameLiftServerProcessDesc()); + m_serverManager->NotifyGameLiftProcessReady(); SessionNotificationsHandlerMock handlerMock; EXPECT_CALL(handlerMock, OnSessionHealthCheck()).Times(1).WillOnce(testing::Return(false)); EXPECT_FALSE(m_serverManager->m_gameLiftServerSDKWrapperMockPtr->m_healthCheckFunc()); @@ -170,7 +182,7 @@ namespace UnitTest TEST_F(GameLiftServerManagerTest, OnStartGameSession_OnCreateSessionBeginReturnsFalse_TerminationNotificationSent) { m_serverManager->InitializeGameLiftServerSDK(); - m_serverManager->NotifyGameLiftProcessReady(GameLiftServerProcessDesc()); + m_serverManager->NotifyGameLiftProcessReady(); SessionNotificationsHandlerMock handlerMock; EXPECT_CALL(handlerMock, OnCreateSessionBegin(testing::_)).Times(1).WillOnce(testing::Return(false)); EXPECT_CALL(handlerMock, OnDestroySessionBegin()).Times(1).WillOnce(testing::Return(true)); @@ -183,7 +195,7 @@ namespace UnitTest TEST_F(GameLiftServerManagerTest, OnStartGameSession_ActivateGameSessionSucceeds_RegisterAsHandler) { m_serverManager->InitializeGameLiftServerSDK(); - m_serverManager->NotifyGameLiftProcessReady(GameLiftServerProcessDesc()); + m_serverManager->NotifyGameLiftProcessReady(); SessionNotificationsHandlerMock handlerMock; EXPECT_CALL(handlerMock, OnCreateSessionBegin(testing::_)).Times(1).WillOnce(testing::Return(true)); EXPECT_CALL(handlerMock, OnDestroySessionBegin()).Times(1).WillOnce(testing::Return(true)); @@ -203,7 +215,7 @@ namespace UnitTest TEST_F(GameLiftServerManagerTest, OnStartGameSession_ActivateGameSessionFails_TerminationNotificationSent) { m_serverManager->InitializeGameLiftServerSDK(); - m_serverManager->NotifyGameLiftProcessReady(GameLiftServerProcessDesc()); + m_serverManager->NotifyGameLiftProcessReady(); SessionNotificationsHandlerMock handlerMock; EXPECT_CALL(handlerMock, OnCreateSessionBegin(testing::_)).Times(1).WillOnce(testing::Return(true)); EXPECT_CALL(handlerMock, OnDestroySessionBegin()).Times(1).WillOnce(testing::Return(true)); diff --git a/Gems/AWSGameLift/Code/AWSGameLiftServer/Tests/AWSGameLiftServerSystemComponentTest.cpp b/Gems/AWSGameLift/Code/AWSGameLiftServer/Tests/AWSGameLiftServerSystemComponentTest.cpp index bec4acbe70..b7cb0ef3cb 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftServer/Tests/AWSGameLiftServerSystemComponentTest.cpp +++ b/Gems/AWSGameLift/Code/AWSGameLiftServer/Tests/AWSGameLiftServerSystemComponentTest.cpp @@ -13,7 +13,6 @@ #include #include #include -#include #include namespace UnitTest @@ -37,22 +36,10 @@ namespace UnitTest m_AWSGameLiftServerSystemsComponent = aznew NiceMock(); m_entity->AddComponent(m_AWSGameLiftServerSystemsComponent); - - // Set up the file IO and alias - m_localFileIO = aznew AZ::IO::LocalFileIO(); - m_priorFileIO = AZ::IO::FileIOBase::GetInstance(); - - AZ::IO::FileIOBase::SetInstance(nullptr); - AZ::IO::FileIOBase::SetInstance(m_localFileIO); - m_localFileIO->SetAlias("@log@", AZ_TRAIT_TEST_ROOT_FOLDER); } void TearDown() override { - AZ::IO::FileIOBase::SetInstance(nullptr); - delete m_localFileIO; - AZ::IO::FileIOBase::SetInstance(m_priorFileIO); - m_entity->RemoveComponent(m_AWSGameLiftServerSystemsComponent); delete m_AWSGameLiftServerSystemsComponent; delete m_entity; @@ -70,9 +57,6 @@ namespace UnitTest AZ::Entity* m_entity; NiceMock* m_AWSGameLiftServerSystemsComponent; - - AZ::IO::FileIOBase* m_priorFileIO; - AZ::IO::FileIOBase* m_localFileIO; }; TEST_F(AWSGameLiftServerSystemComponentTest, ActivateDeactivateComponent_ExecuteInOrder_Success) diff --git a/Gems/AWSGameLift/Code/AWSGameLiftServer/awsgamelift_server_files.cmake b/Gems/AWSGameLift/Code/AWSGameLiftServer/awsgamelift_server_files.cmake index d07ef45b5f..95b5e1d2d2 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftServer/awsgamelift_server_files.cmake +++ b/Gems/AWSGameLift/Code/AWSGameLiftServer/awsgamelift_server_files.cmake @@ -8,6 +8,7 @@ set(FILES ../AWSGameLiftCommon/Source/AWSGameLiftSessionConstants.h + Include/Request/IAWSGameLiftServerRequests.h Source/AWSGameLiftServerManager.cpp Source/AWSGameLiftServerManager.h Source/AWSGameLiftServerSystemComponent.cpp From fa0f2a10073e5182f8980f0458307f4fe4749651 Mon Sep 17 00:00:00 2001 From: Steve Pham <82231385+spham-amzn@users.noreply.github.com> Date: Mon, 30 Aug 2021 13:10:41 -0700 Subject: [PATCH 785/803] Fix unused warnings release (#3677) * Release build fix for Windows * Release build fix for Android * Release build fix for Windows * Release build fix for Android * Release build fix for Linux * Release build fix for Mac * Release build fix for iOS Signed-off-by: Steve Pham --- Code/Editor/ActionManager.cpp | 1 + Code/Editor/EditorViewportWidget.cpp | 2 +- Code/Editor/TrackView/TrackViewAnimNode.cpp | 2 +- .../AzCore/AzCore/Asset/AssetContainer.cpp | 1 + .../AzCore/AzCore/Asset/AssetManager.cpp | 4 ++-- .../IO/Streamer/FullFileDecompressor.cpp | 2 ++ .../AzCore/AzCore/IO/Streamer/Scheduler.cpp | 4 +++- .../AzCore/IO/Streamer/StreamerContext.cpp | 3 ++- .../Memory/OverrunDetectionAllocator.cpp | 2 +- .../AzCore/AzCore/Name/NameDictionary.cpp | 2 +- .../Serialization/Json/RegistrationContext.cpp | 2 +- .../AzCore/Serialization/ObjectStream.cpp | 3 +++ .../AzCore/AzCore/Slice/SliceComponent.cpp | 1 + .../Platform/Mac/AzCore/Platform_Mac.cpp | 2 +- .../AzFramework/Application/Application.cpp | 4 ++-- .../Asset/Benchmark/BenchmarkCommands.cpp | 2 +- .../AzFramework/IO/RemoteFileIO.cpp | 4 ++-- .../Network/AssetProcessorConnection.cpp | 2 +- .../AzFramework/Visibility/VisibilityDebug.cpp | 2 +- .../Motion/InputDeviceMotion_Android.cpp | 2 +- .../InputDeviceVirtualKeyboard_Android.cpp | 2 +- .../Process/ProcessCommunicator_Linux.cpp | 4 ++-- .../Process/ProcessCommunicator_Mac.cpp | 4 ++-- .../AzToolsFramework/Prefab/Link/Link.cpp | 4 ++-- .../Prefab/PrefabPublicHandler.cpp | 6 +++--- .../Prefab/PrefabSystemComponent.cpp | 2 +- .../AzToolsFramework/Prefab/PrefabUndo.cpp | 2 +- .../UI/Slice/SlicePushWidget.cpp | 2 +- .../Tests/Prefab/PrefabUndoLinkTests.cpp | 2 +- .../GridMate/GridMate/Carrier/Carrier.cpp | 2 +- Code/Legacy/CrySystem/ConsoleBatchFile.cpp | 2 +- .../CrySystem/LocalizedStringManager.cpp | 5 ++++- Code/Legacy/CrySystem/Log.cpp | 2 +- Code/Legacy/CrySystem/System.cpp | 2 +- Code/Legacy/CrySystem/SystemCFG.cpp | 4 ++-- Code/Legacy/CrySystem/SystemInit.cpp | 4 ++-- Code/Legacy/CrySystem/Timer.cpp | 6 +++--- .../source/utils/applicationManager.cpp | 2 +- .../Importers/AssImpColorStreamImporter.cpp | 2 +- .../Standalone/Source/LUA/LUAEditorContext.cpp | 2 +- .../Source/Converters/ConvertPixelFormat.cpp | 2 +- .../Code/Source/Processing/ImageConvert.cpp | 6 +++--- .../Code/Tests/ImageProcessing_Test.cpp | 2 +- .../Shader/Code/Source/Editor/AzslCompiler.cpp | 6 +++--- .../Code/Source/Editor/ShaderAssetBuilder.cpp | 2 +- .../Editor/ShaderVariantAssetBuilder.cpp | 4 ++-- .../DirectionalLightFeatureProcessor.cpp | 4 ++-- .../Common/Code/Source/ImGui/ImGuiPass.cpp | 2 +- .../Code/Source/Utils/GpuBufferHandler.cpp | 2 +- .../Code/Source/RHI/FrameGraphExecuteGroup.cpp | 2 +- Gems/Atom/RHI/Code/Source/RHI/Resource.cpp | 4 ++-- Gems/Atom/RHI/Code/Tests/BufferTests.cpp | 1 + Gems/Atom/RHI/Code/Tests/FrameGraph.cpp | 2 +- Gems/Atom/RHI/Code/Tests/ImageTests.cpp | 1 + Gems/Atom/RHI/Code/Tests/QueryTests.cpp | 1 + .../RHI.Builders/ShaderPlatformInterface.cpp | 4 ++-- .../Metal/Code/Source/RHI/ArgumentBuffer.cpp | 2 +- .../RHI/Metal/Code/Source/RHI/BufferView.cpp | 2 +- .../Metal/Code/Source/RHI/PipelineState.cpp | 4 ++-- .../RHI/Vulkan/Code/Source/RHI/BufferView.cpp | 2 +- .../RHI/Vulkan/Code/Source/RHI/ImageView.cpp | 6 +++--- .../Source/RPI.Public/Image/ImageSystem.cpp | 6 +++--- .../Image/StreamingImageController.cpp | 2 +- .../Code/Source/RPI.Public/Pass/RenderPass.cpp | 1 + .../Source/RPI.Reflect/Shader/ShaderAsset.cpp | 2 +- .../RPI.Reflect/Shader/ShaderVariantAsset.cpp | 4 ++-- .../Application/AtomToolsApplication.cpp | 1 + .../Source/Window/MaterialEditorWindow.cpp | 2 +- .../Include/Atom/Utils/ImGuiGpuProfiler.inl | 4 ++-- .../AtomFont/Code/Source/FontRenderer.cpp | 2 +- .../Code/Source/AtomActorInstance.cpp | 2 +- .../CommandSystem/Source/MotionSetCommands.cpp | 2 +- .../RCExt/Motion/MotionDataBuilder.cpp | 2 +- Gems/EMotionFX/Code/EMotionFX/Source/Pose.cpp | 4 ++-- .../EMStudioSDK/Source/NodeHierarchyWidget.cpp | 4 ++-- .../Source/AnimGraph/NodeGraph.cpp | 2 +- .../Source/Integration/GraphController.cpp | 1 + Gems/ImGui/Code/Include/ImGuiContextScope.h | 2 +- .../Common/Apple/InAppPurchasesDelegate.mm | 2 +- .../SliceBuilder/SliceBuilderWorker.cpp | 18 +++++++++--------- .../Editor/Animation/UiAnimViewAnimNode.cpp | 4 ++-- Gems/LyShine/Code/Source/LyShineDebug.cpp | 8 ++++---- .../EditorSequenceAgentComponent.cpp | 2 +- .../Components/SequenceAgentComponent.cpp | 2 +- .../Debug/MultiplayerDebugPerEntityReporter.h | 4 ++-- .../Code/Tests/MultiplayerCompressionTest.cpp | 4 ++-- Gems/PhysX/Code/Source/Debug/PhysXDebug.h | 2 +- Gems/PhysX/Code/Source/Scene/PhysXScene.cpp | 4 ++-- .../Processors/ExportTrackingProcessor.cpp | 2 +- .../Code/Include/ScriptCanvas/Core/Node.cpp | 6 +++--- .../Interpreted/ExecutionInterpretedAPI.cpp | 2 +- .../Execution/NodeableOut/NodeableOutNative.h | 4 ++-- .../Libraries/Core/MethodUtility.cpp | 2 +- .../Code/Source/SystemComponent.cpp | 2 +- 94 files changed, 150 insertions(+), 130 deletions(-) diff --git a/Code/Editor/ActionManager.cpp b/Code/Editor/ActionManager.cpp index 390dbbc1bd..ff74a2c208 100644 --- a/Code/Editor/ActionManager.cpp +++ b/Code/Editor/ActionManager.cpp @@ -326,6 +326,7 @@ ActionManager::MenuWrapper ActionManager::FindMenu(const QString& menuId) return *menuIt; } + AZ_UNUSED(menuId); // Prevent unused warning in release builds AZ_Warning("ActionManager", false, "Did not find menu with menuId %s", menuId.toUtf8().data()); return nullptr; }(); diff --git a/Code/Editor/EditorViewportWidget.cpp b/Code/Editor/EditorViewportWidget.cpp index 44ac159c87..796e16dd53 100644 --- a/Code/Editor/EditorViewportWidget.cpp +++ b/Code/Editor/EditorViewportWidget.cpp @@ -1528,7 +1528,7 @@ AZ::EntityId EditorViewportWidget::GetCurrentViewEntityId() &AZ::RPI::ViewProviderBus::Events::GetView ); - const bool isViewEntityCorrect = viewEntityView == GetCurrentAtomView(); + [[maybe_unused]] const bool isViewEntityCorrect = viewEntityView == GetCurrentAtomView(); AZ_Error("EditorViewportWidget", isViewEntityCorrect, "GetCurrentViewEntityId called while the current view is being changed. " "You may get inconsistent results if you make use of the returned entity ID. " diff --git a/Code/Editor/TrackView/TrackViewAnimNode.cpp b/Code/Editor/TrackView/TrackViewAnimNode.cpp index 2119bf849f..0bb9ac5593 100644 --- a/Code/Editor/TrackView/TrackViewAnimNode.cpp +++ b/Code/Editor/TrackView/TrackViewAnimNode.cpp @@ -1942,7 +1942,7 @@ void CTrackViewAnimNode::OnSelectionChanged(const bool selected) { if (m_animNode) { - const AnimNodeType animNodeType = GetType(); + [[maybe_unused]] const AnimNodeType animNodeType = GetType(); AZ_Assert(animNodeType == AnimNodeType::AzEntity, "Expected AzEntity for selection changed"); const EAnimNodeFlags flags = (EAnimNodeFlags)m_animNode->GetFlags(); diff --git a/Code/Framework/AzCore/AzCore/Asset/AssetContainer.cpp b/Code/Framework/AzCore/AzCore/Asset/AssetContainer.cpp index 83cc1da69a..ce15c7bc4e 100644 --- a/Code/Framework/AzCore/AzCore/Asset/AssetContainer.cpp +++ b/Code/Framework/AzCore/AzCore/Asset/AssetContainer.cpp @@ -153,6 +153,7 @@ namespace AZ // behavior, we would need to rework the way filters work as well as the code in AssetSerializer.cpp to pass down // the loadParams.m_assetLoadFilterCB that was passed into the AddDependentAssets() methods to use as the dependent // asset filter instead of this lambda function. + AZ_UNUSED(handledAssetDependencyList); // Prevent unused warning in release builds AZ_Assert(AZStd::find(handledAssetDependencyList.begin(), handledAssetDependencyList.end(), filterInfo.m_assetId) != handledAssetDependencyList.end(), "Dependent Asset ID (%s) is expected to load, but the Asset Catalog has no dependency recorded. " diff --git a/Code/Framework/AzCore/AzCore/Asset/AssetManager.cpp b/Code/Framework/AzCore/AzCore/Asset/AssetManager.cpp index f31859c14d..3df751fb02 100644 --- a/Code/Framework/AzCore/AzCore/Asset/AssetManager.cpp +++ b/Code/Framework/AzCore/AzCore/Asset/AssetManager.cpp @@ -1478,7 +1478,7 @@ namespace AZ // Resolve the asset handler and account for the new asset instance. { - AssetHandlerMap::iterator handlerIt = m_handlers.find(newData->GetType()); + [[maybe_unused]] AssetHandlerMap::iterator handlerIt = m_handlers.find(newData->GetType()); AZ_Assert( handlerIt != m_handlers.end(), "No handler was registered for this asset [type:%s id:%s]!", newData->GetType().ToString().c_str(), newData->GetId().ToString().c_str()); @@ -1869,7 +1869,7 @@ namespace AZ { AZStd::scoped_lock requestLock(m_activeBlockingRequestMutex); - auto inserted = m_activeBlockingRequests.insert(AZStd::make_pair(assetId, blockingRequest)); + [[maybe_unused]] auto inserted = m_activeBlockingRequests.insert(AZStd::make_pair(assetId, blockingRequest)); AZ_Assert(inserted.second, "Failed to track blocking request for asset %s", assetId.ToString().c_str()); } diff --git a/Code/Framework/AzCore/AzCore/IO/Streamer/FullFileDecompressor.cpp b/Code/Framework/AzCore/AzCore/IO/Streamer/FullFileDecompressor.cpp index 44bf36bd9d..6427571f10 100644 --- a/Code/Framework/AzCore/AzCore/IO/Streamer/FullFileDecompressor.cpp +++ b/Code/Framework/AzCore/AzCore/IO/Streamer/FullFileDecompressor.cpp @@ -45,8 +45,10 @@ namespace AZ } } +#if AZ_STREAMER_ADD_EXTRA_PROFILING_INFO static constexpr char DecompBoundName[] = "Decompression bound"; static constexpr char ReadBoundName[] = "Read bound"; +#endif // AZ_STREAMER_ADD_EXTRA_PROFILING_INFO bool FullFileDecompressor::DecompressionInformation::IsProcessing() const { diff --git a/Code/Framework/AzCore/AzCore/IO/Streamer/Scheduler.cpp b/Code/Framework/AzCore/AzCore/IO/Streamer/Scheduler.cpp index e7f9b0fd18..9b4996ad49 100644 --- a/Code/Framework/AzCore/AzCore/IO/Streamer/Scheduler.cpp +++ b/Code/Framework/AzCore/AzCore/IO/Streamer/Scheduler.cpp @@ -14,8 +14,10 @@ namespace AZ::IO { +#if AZ_STREAMER_ADD_EXTRA_PROFILING_INFO static constexpr char SchedulerName[] = "Scheduler"; static constexpr char ImmediateReadsName[] = "Immediate reads"; +#endif // AZ_STREAMER_ADD_EXTRA_PROFILING_INFO Scheduler::Scheduler(AZStd::shared_ptr streamStack, u64 memoryAlignment, u64 sizeAlignment, u64 granularity) { @@ -337,7 +339,7 @@ namespace AZ::IO AZStd::chrono::system_clock::time_point now = AZStd::chrono::system_clock::now(); auto visitor = [this, now](auto&& args) -> void #else - auto visitor = [this](auto&& args) -> void + auto visitor = [](auto&& args) -> void #endif { using Command = AZStd::decay_t; diff --git a/Code/Framework/AzCore/AzCore/IO/Streamer/StreamerContext.cpp b/Code/Framework/AzCore/AzCore/IO/Streamer/StreamerContext.cpp index 823ab6e050..5cd483bc55 100644 --- a/Code/Framework/AzCore/AzCore/IO/Streamer/StreamerContext.cpp +++ b/Code/Framework/AzCore/AzCore/IO/Streamer/StreamerContext.cpp @@ -17,10 +17,11 @@ namespace AZ namespace IO { static constexpr char ContextName[] = "Context"; +#if AZ_STREAMER_ADD_EXTRA_PROFILING_INFO static constexpr char PredictionAccuracyName[] = "Prediction accuracy (ms)"; static constexpr char LatePredictionName[] = "Early completions"; static constexpr char MissedDeadlinesName[] = "Missed deadlines"; - +#endif // AZ_STREAMER_ADD_EXTRA_PROFILING_INFO StreamerContext::~StreamerContext() { for (FileRequest* entry : m_internalRecycleBin) diff --git a/Code/Framework/AzCore/AzCore/Memory/OverrunDetectionAllocator.cpp b/Code/Framework/AzCore/AzCore/Memory/OverrunDetectionAllocator.cpp index 63fa9250d6..e59e304c54 100644 --- a/Code/Framework/AzCore/AzCore/Memory/OverrunDetectionAllocator.cpp +++ b/Code/Framework/AzCore/AzCore/Memory/OverrunDetectionAllocator.cpp @@ -511,7 +511,7 @@ AZ::OverrunDetectionSchemaImpl::OverrunDetectionSchemaImpl(const OverrunDetectio { m_platformAllocator.reset(new Internal::PlatformOverrunDetectionSchema); - auto info = m_platformAllocator->GetSystemInformation(); + [[maybe_unused]] auto info = m_platformAllocator->GetSystemInformation(); AZ_Assert(info.m_pageSize == Internal::ODS_PAGE_SIZE, "System page size %d does not equal expected page size %d", info.m_pageSize, Internal::ODS_PAGE_SIZE); AZ_Assert(info.m_minimumAllocationSize == Internal::ODS_ALLOCATION_SIZE, "System minimum allocation size %d does not equal expected size %d", info.m_minimumAllocationSize, Internal::ODS_ALLOCATION_SIZE); diff --git a/Code/Framework/AzCore/AzCore/Name/NameDictionary.cpp b/Code/Framework/AzCore/AzCore/Name/NameDictionary.cpp index cf85e0f4e0..8e8011add9 100644 --- a/Code/Framework/AzCore/AzCore/Name/NameDictionary.cpp +++ b/Code/Framework/AzCore/AzCore/Name/NameDictionary.cpp @@ -87,7 +87,7 @@ namespace AZ { Internal::NameData* nameData = keyValue.second; const int useCount = keyValue.second->m_useCount; - const bool hadCollision = keyValue.second->m_hashCollision; + [[maybe_unused]] const bool hadCollision = keyValue.second->m_hashCollision; if (useCount == 0) { diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/RegistrationContext.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/RegistrationContext.cpp index fae67d487c..989f306b08 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/RegistrationContext.cpp +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/RegistrationContext.cpp @@ -43,7 +43,7 @@ namespace AZ if (!overwriteExisting) { - auto emplaceResult = m_context->m_handledTypesMap.try_emplace(uuid, serializer); + [[maybe_unused]] auto emplaceResult = m_context->m_handledTypesMap.try_emplace(uuid, serializer); AZ_Assert( emplaceResult.second, "Couldn't register Json serializer %s. Another serializer (%s) has already been registered for the same Uuid (%s).", diff --git a/Code/Framework/AzCore/AzCore/Serialization/ObjectStream.cpp b/Code/Framework/AzCore/AzCore/Serialization/ObjectStream.cpp index 73ab174699..6251a2e6de 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/ObjectStream.cpp +++ b/Code/Framework/AzCore/AzCore/Serialization/ObjectStream.cpp @@ -1520,6 +1520,7 @@ namespace AZ { if (m_writeElementResultStack.empty()) { + AZ_UNUSED(classData); // Prevent unused warning in release builds AZ_Error("Serialize", false, "CloseElement is attempted to be called without a corresponding WriteElement when writing class %s", classData->m_name); return true; } @@ -1581,6 +1582,7 @@ namespace AZ { if (m_writeElementResultStack.empty()) { + AZ_UNUSED(classData); // Prevent unused warning in release builds AZ_Error("Serialize", false, "CloseElement is attempted to be called without a corresponding WriteElement when writing class %s", classData->m_name); return true; } @@ -1644,6 +1646,7 @@ namespace AZ { if (m_writeElementResultStack.empty()) { + AZ_UNUSED(classData); // Prevent unused warning in release builds AZ_Error("Serialize", false, "CloseElement is attempted to be called without a corresponding WriteElement when writing class %s", classData->m_name); return true; } diff --git a/Code/Framework/AzCore/AzCore/Slice/SliceComponent.cpp b/Code/Framework/AzCore/AzCore/Slice/SliceComponent.cpp index 23a197b2ad..03ed3f6ebb 100644 --- a/Code/Framework/AzCore/AzCore/Slice/SliceComponent.cpp +++ b/Code/Framework/AzCore/AzCore/Slice/SliceComponent.cpp @@ -3839,6 +3839,7 @@ namespace AZ { if (instance->GetId() == existingInstance.GetId()) { + AZ_UNUSED(sliceReference); // Prevent unused warning in release builds AZ_Warning("Slice", false, "Multiple slice instances with the same ID from slice %s were found. The last instance found has been loaded.", sliceReference.GetSliceAsset().GetHint().c_str()); return true; diff --git a/Code/Framework/AzCore/Platform/Mac/AzCore/Platform_Mac.cpp b/Code/Framework/AzCore/Platform/Mac/AzCore/Platform_Mac.cpp index edb3d3ea0e..78e97f47c8 100644 --- a/Code/Framework/AzCore/Platform/Mac/AzCore/Platform_Mac.cpp +++ b/Code/Framework/AzCore/Platform/Mac/AzCore/Platform_Mac.cpp @@ -32,7 +32,7 @@ namespace AZ timespec wait; wait.tv_sec = 0; wait.tv_nsec = 5000; - int result = ::gethostuuid(hostId, &wait); + [[maybe_unused]] int result = ::gethostuuid(hostId, &wait); AZ_Error("System", result == 0, "gethostuuid() failed with code %d", result); Sha1 hash; AZ::u32 digest[5] = { 0 }; diff --git a/Code/Framework/AzFramework/AzFramework/Application/Application.cpp b/Code/Framework/AzFramework/AzFramework/Application/Application.cpp index fa0f14ac74..958dba2cc9 100644 --- a/Code/Framework/AzFramework/AzFramework/Application/Application.cpp +++ b/Code/Framework/AzFramework/AzFramework/Application/Application.cpp @@ -72,7 +72,7 @@ #include #include -static const char* s_azFrameworkWarningWindow = "AzFramework"; +[[maybe_unused]] static const char* s_azFrameworkWarningWindow = "AzFramework"; namespace AzFramework { @@ -602,7 +602,7 @@ namespace AzFramework void Application::SetRootPath(RootPathType type, const char* source) { - const size_t sourceLen = strlen(source); + [[maybe_unused]] const size_t sourceLen = strlen(source); // Copy the source path to the intended root path and correct the path separators as well switch (type) diff --git a/Code/Framework/AzFramework/AzFramework/Asset/Benchmark/BenchmarkCommands.cpp b/Code/Framework/AzFramework/AzFramework/Asset/Benchmark/BenchmarkCommands.cpp index d27fe8188f..30c1aa39c0 100644 --- a/Code/Framework/AzFramework/AzFramework/Asset/Benchmark/BenchmarkCommands.cpp +++ b/Code/Framework/AzFramework/AzFramework/Asset/Benchmark/BenchmarkCommands.cpp @@ -43,7 +43,7 @@ namespace AzFramework::AssetBenchmark AZStd::thread benchmarkThread([assetList = AZStd::move(sourceAssetList), loadBlocking]() { // Define the set of loading stats to track - const size_t initialRequests = assetList.size(); + [[maybe_unused]] const size_t initialRequests = assetList.size(); size_t previouslyLoadedAssets = 0; size_t newlyLoadedAssets = 0; size_t loadErrors = 0; diff --git a/Code/Framework/AzFramework/AzFramework/IO/RemoteFileIO.cpp b/Code/Framework/AzFramework/AzFramework/IO/RemoteFileIO.cpp index 3ac1b91144..041e5baf4a 100644 --- a/Code/Framework/AzFramework/AzFramework/IO/RemoteFileIO.cpp +++ b/Code/Framework/AzFramework/AzFramework/IO/RemoteFileIO.cpp @@ -24,9 +24,9 @@ namespace AZ namespace IO { ////////////////////////////////////////////////////////////////////////// - const char* const NetworkFileIOChannel = "NetworkFileIO"; + [[maybe_unused]] const char* const NetworkFileIOChannel = "NetworkFileIO"; #ifndef REMOTEFILEIO_IS_NETWORKFILEIO - const char* const RemoteFileIOChannel = "RemoteFileIO"; + [[maybe_unused]] const char* const RemoteFileIOChannel = "RemoteFileIO"; #ifdef REMOTEFILEIO_SYNC_CHECK const char* const RemoteFileCacheChannel = "RemoteFileCache"; #endif diff --git a/Code/Framework/AzFramework/AzFramework/Network/AssetProcessorConnection.cpp b/Code/Framework/AzFramework/AzFramework/Network/AssetProcessorConnection.cpp index ebea29c2d9..2e1cde443c 100644 --- a/Code/Framework/AzFramework/AzFramework/Network/AssetProcessorConnection.cpp +++ b/Code/Framework/AzFramework/AzFramework/Network/AssetProcessorConnection.cpp @@ -177,7 +177,7 @@ namespace AzFramework //trying to connect, if any error occurs start the disconnect thread void AssetProcessorConnection::ConnectThread() { - static constexpr char ConnectThreadWindow[] = "AssetProcessorConnection::ConnectThread"; + [[maybe_unused]] static constexpr char ConnectThreadWindow[] = "AssetProcessorConnection::ConnectThread"; //check for join before doing an op if (m_connectThread.m_join) diff --git a/Code/Framework/AzFramework/AzFramework/Visibility/VisibilityDebug.cpp b/Code/Framework/AzFramework/AzFramework/Visibility/VisibilityDebug.cpp index 0d74bcc54b..a71819ab45 100644 --- a/Code/Framework/AzFramework/AzFramework/Visibility/VisibilityDebug.cpp +++ b/Code/Framework/AzFramework/AzFramework/Visibility/VisibilityDebug.cpp @@ -91,7 +91,7 @@ namespace AzFramework const AZ::Frustum::PlaneId planeId3) { AZ::Vector3 corner = AZ::Vector3::CreateZero(); - const auto intersectionOkay = AZ::ShapeIntersection::IntersectThreePlanes( + [[maybe_unused]] const auto intersectionOkay = AZ::ShapeIntersection::IntersectThreePlanes( frustum.GetPlane(planeId1), frustum.GetPlane(planeId2), frustum.GetPlane(planeId3), corner); AZ_Assert(intersectionOkay, "Plane intersection of Frustum failed"); diff --git a/Code/Framework/AzFramework/Platform/Android/AzFramework/Input/Devices/Motion/InputDeviceMotion_Android.cpp b/Code/Framework/AzFramework/Platform/Android/AzFramework/Input/Devices/Motion/InputDeviceMotion_Android.cpp index 5cb3985569..74b2024fd1 100644 --- a/Code/Framework/AzFramework/Platform/Android/AzFramework/Input/Devices/Motion/InputDeviceMotion_Android.cpp +++ b/Code/Framework/AzFramework/Platform/Android/AzFramework/Input/Devices/Motion/InputDeviceMotion_Android.cpp @@ -175,7 +175,7 @@ namespace AzFramework m_packedSensorDataArray = new float[packedSensorDataLength]; // create the java instance - bool ret = m_motionSensorManager->CreateInstance("(Landroid/app/Activity;)V", AZ::Android::Utils::GetActivityRef()); + [[maybe_unused]] bool ret = m_motionSensorManager->CreateInstance("(Landroid/app/Activity;)V", AZ::Android::Utils::GetActivityRef()); AZ_Assert(ret, "Failed to create the MotionSensorManager Java instance."); } diff --git a/Code/Framework/AzFramework/Platform/Android/AzFramework/Input/Devices/VirtualKeyboard/InputDeviceVirtualKeyboard_Android.cpp b/Code/Framework/AzFramework/Platform/Android/AzFramework/Input/Devices/VirtualKeyboard/InputDeviceVirtualKeyboard_Android.cpp index 00139ffc9d..c477b0bd37 100644 --- a/Code/Framework/AzFramework/Platform/Android/AzFramework/Input/Devices/VirtualKeyboard/InputDeviceVirtualKeyboard_Android.cpp +++ b/Code/Framework/AzFramework/Platform/Android/AzFramework/Input/Devices/VirtualKeyboard/InputDeviceVirtualKeyboard_Android.cpp @@ -128,7 +128,7 @@ namespace AzFramework }); // create the java instance - bool ret = m_keyboardHandler->CreateInstance("(Landroid/app/Activity;)V", AZ::Android::Utils::GetActivityRef()); + [[maybe_unused]] bool ret = m_keyboardHandler->CreateInstance("(Landroid/app/Activity;)V", AZ::Android::Utils::GetActivityRef()); AZ_Assert(ret, "Failed to create the KeyboardHandler Java instance."); // Connect to the raw input notifications bus diff --git a/Code/Framework/AzFramework/Platform/Linux/AzFramework/Process/ProcessCommunicator_Linux.cpp b/Code/Framework/AzFramework/Platform/Linux/AzFramework/Process/ProcessCommunicator_Linux.cpp index 325ab81d41..0249a42976 100644 --- a/Code/Framework/AzFramework/Platform/Linux/AzFramework/Process/ProcessCommunicator_Linux.cpp +++ b/Code/Framework/AzFramework/Platform/Linux/AzFramework/Process/ProcessCommunicator_Linux.cpp @@ -78,7 +78,7 @@ namespace AzFramework FD_ZERO(&set); FD_SET(handle->GetHandle(), &set); - int numReady = select(handle->GetHandle() + 1, &set, NULL, NULL, NULL); + [[maybe_unused]] int numReady = select(handle->GetHandle() + 1, &set, NULL, NULL, NULL); // if numReady == -1 and errno == EINTR then the child process died unexpectedly and // the handle was closed. Not something to assert about in regards to trying to read @@ -87,7 +87,7 @@ namespace AzFramework // dead and return any error codes the child may have written to the error stream. AZ_Assert(numReady != -1 || errno == EINTR, "Could not determine if any data is available for reading due to an error. Errno: %d", errno); - const bool wasSet = FD_ISSET(handle->GetHandle(), &set); + [[maybe_unused]] const bool wasSet = FD_ISSET(handle->GetHandle(), &set); AZ_Assert(wasSet, "handle was not set when we selected it for read"); return 0; diff --git a/Code/Framework/AzFramework/Platform/Mac/AzFramework/Process/ProcessCommunicator_Mac.cpp b/Code/Framework/AzFramework/Platform/Mac/AzFramework/Process/ProcessCommunicator_Mac.cpp index ea22bc72a3..1c233c6f29 100644 --- a/Code/Framework/AzFramework/Platform/Mac/AzFramework/Process/ProcessCommunicator_Mac.cpp +++ b/Code/Framework/AzFramework/Platform/Mac/AzFramework/Process/ProcessCommunicator_Mac.cpp @@ -75,7 +75,7 @@ namespace AzFramework FD_ZERO(&set); FD_SET(handle->GetHandle(), &set); - int numReady = select(handle->GetHandle() + 1, &set, NULL, NULL, NULL); + [[maybe_unused]] int numReady = select(handle->GetHandle() + 1, &set, NULL, NULL, NULL); // if numReady == -1 and errno == EINTR then the child process died unexpectedly and // the handle was closed. Not something to assert about in regards to trying to read @@ -84,7 +84,7 @@ namespace AzFramework // dead and return any error codes the child may have written to the error stream. AZ_Assert(numReady != -1 || errno == EINTR, "Could not determine if any data is available for reading due to an error. Errno: %d", errno); - const bool wasSet = FD_ISSET(handle->GetHandle(), &set); + [[maybe_unused]] const bool wasSet = FD_ISSET(handle->GetHandle(), &set); AZ_Assert(wasSet, "handle was not set when we selected it for read"); return 0; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Link/Link.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Link/Link.cpp index 940a2787cb..800a90c622 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Link/Link.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Link/Link.cpp @@ -181,10 +181,10 @@ namespace AzToolsFramework PrefabDomUtils::ApplyPatches(sourceTemplateDomCopy, targetTemplatePrefabDom.GetAllocator(), patchesReference->get()); linkedInstanceDom.CopyFrom(sourceTemplateDomCopy, targetTemplatePrefabDom.GetAllocator()); - PrefabDomValueReference sourceTemplateName = + [[maybe_unused]] PrefabDomValueReference sourceTemplateName = PrefabDomUtils::FindPrefabDomValue(sourceTemplateDomCopy, PrefabDomUtils::SourceName); AZ_Assert(sourceTemplateName && sourceTemplateName->get().IsString(), "A valid source template name couldn't be found"); - PrefabDomValueReference targetTemplateName = + [[maybe_unused]] PrefabDomValueReference targetTemplateName = PrefabDomUtils::FindPrefabDomValue(targetTemplatePrefabDom, PrefabDomUtils::SourceName); AZ_Assert(targetTemplateName && targetTemplateName->get().IsString(), "A valid target template name couldn't be found"); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp index 24cd0f0252..c412033362 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp @@ -1259,12 +1259,12 @@ namespace AzToolsFramework auto& containerEntity = *containerEntityPtr.release(); auto editorPrefabComponent = containerEntity.FindComponent(); containerEntity.Deactivate(); - const bool editorPrefabComponentRemoved = containerEntity.RemoveComponent(editorPrefabComponent); + [[maybe_unused]] const bool editorPrefabComponentRemoved = containerEntity.RemoveComponent(editorPrefabComponent); AZ_Assert(editorPrefabComponentRemoved, "Remove EditorPrefabComponent failed."); delete editorPrefabComponent; containerEntity.Activate(); - const bool containerEntityAdded = parentInstance.AddEntity(containerEntity); + [[maybe_unused]] const bool containerEntityAdded = parentInstance.AddEntity(containerEntity); AZ_Assert(containerEntityAdded, "Add target Instance's container entity to its parent Instance failed."); EntityIdList entityIds; @@ -1281,7 +1281,7 @@ namespace AzToolsFramework [&](AZStd::unique_ptr entityPtr) { auto& entity = *entityPtr.release(); - const bool entityAdded = parentInstance.AddEntity(entity); + [[maybe_unused]] const bool entityAdded = parentInstance.AddEntity(entity); AZ_Assert(entityAdded, "Add target Instance's entity to its parent Instance failed."); entityIds.emplace_back(entity.GetId()); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp index 1051e530c8..f3250e0bfd 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp @@ -783,7 +783,7 @@ namespace AzToolsFramework PrefabDomValue& instance = instanceIterator->value; AZ_Assert(instance.IsObject(), "Nested instance DOM provided is not a valid JSON object."); - PrefabDomValueReference sourceTemplateName = PrefabDomUtils::FindPrefabDomValue(instance, PrefabDomUtils::SourceName); + [[maybe_unused]] PrefabDomValueReference sourceTemplateName = PrefabDomUtils::FindPrefabDomValue(instance, PrefabDomUtils::SourceName); AZ_Assert(sourceTemplateName, "Couldn't find source template name in the DOM of the nested instance while creating a link."); AZ_Assert( sourceTemplateName->get() == sourceTemplate.GetFilePath().c_str(), diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabUndo.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabUndo.cpp index fc64e0b5b3..fe3555a853 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabUndo.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabUndo.cpp @@ -262,7 +262,7 @@ namespace AzToolsFramework instanceDom.CopyFrom(instanceDomRef->get(), instanceDom.GetAllocator()); //apply the patch to the template within the target - AZ::JsonSerializationResult::ResultCode result = PrefabDomUtils::ApplyPatches(instanceDom, instanceDom.GetAllocator(), patch); + [[maybe_unused]] AZ::JsonSerializationResult::ResultCode result = PrefabDomUtils::ApplyPatches(instanceDom, instanceDom.GetAllocator(), patch); AZ_Error( "Prefab", diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Slice/SlicePushWidget.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Slice/SlicePushWidget.cpp index c276fc5c5a..76f91b438e 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Slice/SlicePushWidget.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Slice/SlicePushWidget.cpp @@ -2525,7 +2525,7 @@ namespace AzToolsFramework { // This is an approximate measurement of how much this slice proliferates within the currently-loaded level. // Down the line we'll actually query the asset DB's dependency tree, summing up instances. - + AZ_UNUSED(levelSlice); // Prevent unused warning in release builds AZ_Warning("SlicePush", levelSlice, "SlicePushWidget::CalculateReferenceCount could not find root slice, displayed counts will be inaccurate!"); size_t instanceCount = 0; AZ::Data::AssetBus::EnumerateHandlersId(assetId, diff --git a/Code/Framework/AzToolsFramework/Tests/Prefab/PrefabUndoLinkTests.cpp b/Code/Framework/AzToolsFramework/Tests/Prefab/PrefabUndoLinkTests.cpp index e506159fd2..8fafe1f177 100644 --- a/Code/Framework/AzToolsFramework/Tests/Prefab/PrefabUndoLinkTests.cpp +++ b/Code/Framework/AzToolsFramework/Tests/Prefab/PrefabUndoLinkTests.cpp @@ -97,7 +97,7 @@ namespace UnitTest //apply the patch PrefabDom& templateDomReference = m_prefabSystemComponent->FindTemplateDom(nestedTemplateId); - AZ::JsonSerializationResult::ResultCode result = + [[maybe_unused]] AZ::JsonSerializationResult::ResultCode result = PrefabDomUtils::ApplyPatches(templateDomReference, templateDomReference.GetAllocator(), patch); AZ_Error("Prefab", result.GetOutcome() == AZ::JsonSerializationResult::Outcomes::Success, diff --git a/Code/Framework/GridMate/GridMate/Carrier/Carrier.cpp b/Code/Framework/GridMate/GridMate/Carrier/Carrier.cpp index 0285a7fc02..8b484143de 100644 --- a/Code/Framework/GridMate/GridMate/Carrier/Carrier.cpp +++ b/Code/Framework/GridMate/GridMate/Carrier/Carrier.cpp @@ -1452,7 +1452,7 @@ void CarrierThread::NotifyRateUpdate(ThreadConnection* conn) float rtt = lifetime.m_rtt > 1.f ? lifetime.m_rtt : 100.f; //For unknown RTT use conservative 100ms to avoid buffer bloat //Note: using lifetime RTT as stand-in for smoothed RTT float ratef = (1010 * (cState.m_congestionWindow)) / rtt; //Add 10% to allow rate increases until buffer fills up - constexpr float max_rate = azlossy_cast(0x7FFFFFFF); + [[maybe_unused]] constexpr float max_rate = azlossy_cast(0x7FFFFFFF); AZ_Assert(ratef <= max_rate, " ratef %f > 0x7FFFFFFF", ratef); bytesPerSecond = static_cast(ratef); diff --git a/Code/Legacy/CrySystem/ConsoleBatchFile.cpp b/Code/Legacy/CrySystem/ConsoleBatchFile.cpp index 3d46716873..d3a0ccf4de 100644 --- a/Code/Legacy/CrySystem/ConsoleBatchFile.cpp +++ b/Code/Legacy/CrySystem/ConsoleBatchFile.cpp @@ -87,7 +87,7 @@ bool CConsoleBatchFile::ExecuteConfigFile(const char* sFilename) CCryFile file; { - const char* szLog = "Executing console batch file (try game,config,root):"; + [[maybe_unused]] const char* szLog = "Executing console batch file (try game,config,root):"; AZStd::string filenameLog; AZStd::string sfn = PathUtil::GetFile(filename); diff --git a/Code/Legacy/CrySystem/LocalizedStringManager.cpp b/Code/Legacy/CrySystem/LocalizedStringManager.cpp index 78ece6f74c..365c71252c 100644 --- a/Code/Legacy/CrySystem/LocalizedStringManager.cpp +++ b/Code/Legacy/CrySystem/LocalizedStringManager.cpp @@ -32,8 +32,11 @@ #define MAX_CELL_COUNT 32 // CVAR names +#if !defined(_RELEASE) const char c_sys_localization_debug[] = "sys_localization_debug"; const char c_sys_localization_encode[] = "sys_localization_encode"; +#endif // !defined(_RELEASE) + #define LOC_WINDOW "Localization" const char c_sys_localization_format[] = "sys_localization_format"; @@ -1754,7 +1757,7 @@ void CLocalizedStringsManager::ReloadData() void CLocalizedStringsManager::AddLocalizedString(SLanguage* pLanguage, SLocalizedStringEntry* pEntry, const uint32 keyCRC32) { pLanguage->m_vLocalizedStrings.push_back(pEntry); - int nId = (int)pLanguage->m_vLocalizedStrings.size() - 1; + [[maybe_unused]] int nId = (int)pLanguage->m_vLocalizedStrings.size() - 1; pLanguage->m_keysMap[keyCRC32] = pEntry; if (m_cvarLocalizationDebug >= 2) diff --git a/Code/Legacy/CrySystem/Log.cpp b/Code/Legacy/CrySystem/Log.cpp index a157501f0a..68b9621f74 100644 --- a/Code/Legacy/CrySystem/Log.cpp +++ b/Code/Legacy/CrySystem/Log.cpp @@ -744,7 +744,7 @@ void CLog::LogToConsolePlus(const char* szFormat, ...) ////////////////////////////////////////////////////////////////////// -static void RemoveColorCodeInPlace(CLog::LogStringType& rStr) +[[maybe_unused]] static void RemoveColorCodeInPlace(CLog::LogStringType& rStr) { char* s = (char*)rStr.c_str(); char* d = s; diff --git a/Code/Legacy/CrySystem/System.cpp b/Code/Legacy/CrySystem/System.cpp index 2d756d1352..70fb9382e1 100644 --- a/Code/Legacy/CrySystem/System.cpp +++ b/Code/Legacy/CrySystem/System.cpp @@ -1465,7 +1465,7 @@ void CSystem::SetSystemGlobalState(const ESystemGlobalState systemGlobalState) if (gEnv && gEnv->pTimer) { const CTimeValue endTime = gEnv->pTimer->GetAsyncTime(); - const float numSeconds = endTime.GetDifferenceInSeconds(s_startTime); + [[maybe_unused]] const float numSeconds = endTime.GetDifferenceInSeconds(s_startTime); CryLog("SetGlobalState %d->%d '%s'->'%s' %3.1f seconds", m_systemGlobalState, systemGlobalState, CSystem::GetSystemGlobalStateName(m_systemGlobalState), CSystem::GetSystemGlobalStateName(systemGlobalState), diff --git a/Code/Legacy/CrySystem/SystemCFG.cpp b/Code/Legacy/CrySystem/SystemCFG.cpp index 57de0be909..0f67fdc2e1 100644 --- a/Code/Legacy/CrySystem/SystemCFG.cpp +++ b/Code/Legacy/CrySystem/SystemCFG.cpp @@ -180,7 +180,7 @@ void CSystem::LogVersion() strftime(s, 128, "%d %b %y (%H %M %S)", today); #endif - const SFileVersion& ver = GetFileVersion(); + [[maybe_unused]] const SFileVersion& ver = GetFileVersion(); CryLogAlways("BackupNameAttachment=\" Build(%d) %s\" -- used by backup system\n", ver.v[0], s); // read by CreateBackupFile() @@ -251,7 +251,7 @@ void CSystem::LogVersion() ////////////////////////////////////////////////////////////////////////// void CSystem::LogBuildInfo() { - auto projectName = AZ::Utils::GetProjectName(); + [[maybe_unused]] auto projectName = AZ::Utils::GetProjectName(); CryLogAlways("GameName: %s", projectName.c_str()); CryLogAlways("BuildTime: " __DATE__ " " __TIME__); } diff --git a/Code/Legacy/CrySystem/SystemInit.cpp b/Code/Legacy/CrySystem/SystemInit.cpp index a0769d1a2c..d5efff2748 100644 --- a/Code/Legacy/CrySystem/SystemInit.cpp +++ b/Code/Legacy/CrySystem/SystemInit.cpp @@ -257,8 +257,8 @@ static void CmdCrashTest(IConsoleCmdArgs* pArgs) { float a = 1.0f; memset(&a, 0, sizeof(a)); - float* b = &a; - float c = 3; + [[maybe_unused]] float* b = &a; + [[maybe_unused]] float c = 3; CryLog("%f", (c / *b)); } break; diff --git a/Code/Legacy/CrySystem/Timer.cpp b/Code/Legacy/CrySystem/Timer.cpp index d411e76875..1e1b6859e1 100644 --- a/Code/Legacy/CrySystem/Timer.cpp +++ b/Code/Legacy/CrySystem/Timer.cpp @@ -550,7 +550,7 @@ void CTimer::Serialize(TSerialize ser) if (m_TimeDebug) { - const int64 now = CryGetTicks(); + [[maybe_unused]] const int64 now = CryGetTicks(); CryLogAlways("[CTimer]: Serialize: Last=%lld Now=%lld Off=%lld Async=%f CurrTime=%f UI=%f", (long long)m_lLastTime, (long long)now, (long long)m_lOffsetTime, GetAsyncCurTime(), GetCurrTime(ETIMER_GAME), GetCurrTime(ETIMER_UI)); } } @@ -700,8 +700,8 @@ void CTimer::EnableFixedTimeMode([[maybe_unused]] bool enable, [[maybe_unused]] void CTimer::SetOffsetToMatchGameTime(int64 ticks) { - const int64 previousOffset = m_lOffsetTime; - const float previousGameTime = GetCurrTime(ETIMER_GAME); + [[maybe_unused]] const int64 previousOffset = m_lOffsetTime; + [[maybe_unused]] const float previousGameTime = GetCurrTime(ETIMER_GAME); m_lOffsetTime = ticks - m_lLastTime; RefreshGameTime(m_lLastTime); diff --git a/Code/Tools/AssetBundler/source/utils/applicationManager.cpp b/Code/Tools/AssetBundler/source/utils/applicationManager.cpp index 0887b17682..0742035c1a 100644 --- a/Code/Tools/AssetBundler/source/utils/applicationManager.cpp +++ b/Code/Tools/AssetBundler/source/utils/applicationManager.cpp @@ -1399,7 +1399,7 @@ namespace AssetBundler AZStd::string_view{ AZ::Utils::GetEnginePath() }, AZStd::string_view{ AZ::Utils::GetEnginePath() }, AZStd::string_view{ AZ::Utils::GetProjectPath() }); - auto platformsString = AzFramework::PlatformHelper::GetCommaSeparatedPlatformList(platformFlags); + [[maybe_unused]] auto platformsString = AzFramework::PlatformHelper::GetCommaSeparatedPlatformList(platformFlags); AZ_TracePrintf(AppWindowName, "No platform specified, defaulting to platforms ( %s ).\n", platformsString.c_str()); return platformFlags; diff --git a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpColorStreamImporter.cpp b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpColorStreamImporter.cpp index 4043f529df..f9b3de6df1 100644 --- a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpColorStreamImporter.cpp +++ b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpColorStreamImporter.cpp @@ -57,7 +57,7 @@ namespace AZ // This node has at least one mesh, verify that the color channel counts are the same for all meshes. const unsigned int expectedColorChannels = scene->mMeshes[currentNode->mMeshes[0]]->GetNumColorChannels(); - const bool allMeshesHaveSameNumberOfColorChannels = + [[maybe_unused]] const bool allMeshesHaveSameNumberOfColorChannels = AZStd::all_of(currentNode->mMeshes + 1, currentNode->mMeshes + currentNode->mNumMeshes, [scene, expectedColorChannels](const unsigned int meshIndex) { return scene->mMeshes[meshIndex]->GetNumColorChannels() == expectedColorChannels; diff --git a/Code/Tools/Standalone/Source/LUA/LUAEditorContext.cpp b/Code/Tools/Standalone/Source/LUA/LUAEditorContext.cpp index 1fa127dd7d..f36724ee1a 100644 --- a/Code/Tools/Standalone/Source/LUA/LUAEditorContext.cpp +++ b/Code/Tools/Standalone/Source/LUA/LUAEditorContext.cpp @@ -1020,7 +1020,7 @@ namespace LUAEditor { AZ_TracePrintf(LUAEditorDebugName, AZStd::string::format("LUAEditor OnSaveDocumentAs" "%s\n", assetId.c_str()).c_str()); - DocumentInfoMap::iterator docInfoIter = m_documentInfoMap.find(assetId); + [[maybe_unused]] DocumentInfoMap::iterator docInfoIter = m_documentInfoMap.find(assetId); AZ_Assert(docInfoIter != m_documentInfoMap.end(), "LUAEditor OnSaveDocumentAs() : Cant find Document Info."); OnSaveDocument(assetId, bCloseAfterSave, true); diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Converters/ConvertPixelFormat.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Converters/ConvertPixelFormat.cpp index 8f851b46d1..b0f78d60a3 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Converters/ConvertPixelFormat.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Converters/ConvertPixelFormat.cpp @@ -98,7 +98,7 @@ namespace ImageProcessingAtom else { IImageObjectPtr dstImage = nullptr; - const PixelFormatInfo* compressedInfo = CPixelFormats::GetInstance().GetPixelFormatInfo(compressedFmt); + [[maybe_unused]] const PixelFormatInfo* compressedInfo = CPixelFormats::GetInstance().GetPixelFormatInfo(compressedFmt); if (isSrcUncompressed) { AZ::u64 startTime = AZStd::GetTimeUTCMilliSecond(); diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageConvert.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageConvert.cpp index a1093ffc37..1618f376b4 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageConvert.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageConvert.cpp @@ -350,7 +350,7 @@ namespace ImageProcessingAtom // output conversion log if (m_isSucceed && m_isFinished) { - const uint32 sizeTotal = m_image->Get()->GetTextureMemory(); + [[maybe_unused]] const uint32 sizeTotal = m_image->Get()->GetTextureMemory(); if (m_input->m_isPreview) { AZ_TracePrintf("Image Processing", "Image (%d bytes) converted in %f seconds\n", sizeTotal, m_processTime); @@ -971,7 +971,7 @@ namespace ImageProcessingAtom IImageObjectPtr previewImageAlpha = imageToProcess2.Get(); const uint32 imageMips = previewImage->GetMipCount(); - const uint32 alphaMips = previewImageAlpha->GetMipCount(); + [[maybe_unused]] const uint32 alphaMips = previewImageAlpha->GetMipCount(); // Get count of bytes per pixel for both rgb and alpha images uint32 imagePixelBytes = CPixelFormats::GetInstance().GetPixelFormatInfo(ePixelFormat_R8G8B8A8)->bitsPerBlock / 8; @@ -983,7 +983,7 @@ namespace ImageProcessingAtom for (uint32 mipLevel = 0; mipLevel < imageMips; ++mipLevel) { const uint32 pixelCount = previewImage->GetPixelCount(mipLevel); - const uint32 alphaPixelCount = previewImageAlpha->GetPixelCount(mipLevel); + [[maybe_unused]] const uint32 alphaPixelCount = previewImageAlpha->GetPixelCount(mipLevel); AZ_Assert(pixelCount == alphaPixelCount, "Pixel count for image and alpha image at mip level %d is not equal!", mipLevel); diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Tests/ImageProcessing_Test.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Tests/ImageProcessing_Test.cpp index fa1b092e6b..0656fb4e46 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Tests/ImageProcessing_Test.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Tests/ImageProcessing_Test.cpp @@ -830,7 +830,7 @@ namespace UnitTest continue; } - auto formatInfo = CPixelFormats::GetInstance().GetPixelFormatInfo(pixelFormat); + [[maybe_unused]] auto formatInfo = CPixelFormats::GetInstance().GetPixelFormatInfo(pixelFormat); imageToProcess.Set(srcImage); imageToProcess.ConvertFormat(pixelFormat); diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/AzslCompiler.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/AzslCompiler.cpp index 4a56c198d7..154bfdd607 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/AzslCompiler.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/AzslCompiler.cpp @@ -908,9 +908,9 @@ namespace AZ AZ_Assert(optionEntry.IsObject(), "Expected option entry to be an object!"); Name defaultValueId = optionEntry.HasMember("defaultValue") ? Name(optionEntry["defaultValue"].GetString()) : Name(); - const AZStd::string optionName = optionEntry.HasMember("name") ? optionEntry["name"].GetString() : ""; - const bool valuesAreRange = optionEntry.HasMember("range") ? optionEntry["range"].GetBool() : false; - const bool isPredefinedType = optionEntry.HasMember("kind") ? AzFramework::StringFunc::Equal(optionEntry["kind"].GetString(), "predefined") : false; + const AZStd::string optionName = optionEntry.HasMember("name") ? optionEntry["name"].GetString() : ""; + [[maybe_unused]] const bool valuesAreRange = optionEntry.HasMember("range") ? optionEntry["range"].GetBool() : false; + const bool isPredefinedType = optionEntry.HasMember("kind") ? AzFramework::StringFunc::Equal(optionEntry["kind"].GetString(), "predefined") : false; auto optionType = RPI::ShaderOptionType::Unknown; if (isPredefinedType && optionEntry.HasMember("type")) diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderAssetBuilder.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderAssetBuilder.cpp index 8ec7733d07..9ee4ff2161 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderAssetBuilder.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderAssetBuilder.cpp @@ -462,7 +462,7 @@ namespace AZ { finalShaderOptionGroupLayout = shaderOptionGroupLayout; shaderAssetCreator.SetShaderOptionGroupLayout(finalShaderOptionGroupLayout); - const uint32_t usedShaderOptionBits = shaderOptionGroupLayout->GetBitSize(); + [[maybe_unused]] const uint32_t usedShaderOptionBits = shaderOptionGroupLayout->GetBitSize(); AZ_TracePrintf( ShaderAssetBuilderName, "Note: This shader uses %u of %u available shader variant key bits. \n", usedShaderOptionBits, RPI::ShaderVariantKeyBitCount); diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp index 5dc1267dbb..12e5382b63 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp @@ -388,7 +388,7 @@ namespace AZ for (const AZ::RPI::ShaderVariantListSourceData::VariantInfo& variantInfo : shaderVariantList.m_shaderVariants) { AZStd::string variantInfoAsJsonString; - const bool convertSuccess = AZ::RPI::JsonUtils::SaveObjectToJsonString(variantInfo, variantInfoAsJsonString); + [[maybe_unused]] const bool convertSuccess = AZ::RPI::JsonUtils::SaveObjectToJsonString(variantInfo, variantInfoAsJsonString); AZ_Assert(convertSuccess, "Failed to convert VariantInfo to json string"); AssetBuilderSDK::JobDescriptor jobDescriptor; @@ -755,7 +755,7 @@ namespace AZ const AZStd::string& variantJsonString = jobParameters.at(ShaderVariantJobVariantParam); RPI::ShaderVariantListSourceData::VariantInfo variantInfo; - const bool fromJsonStringSuccess = AZ::RPI::JsonUtils::LoadObjectFromJsonString(variantJsonString, variantInfo); + [[maybe_unused]] const bool fromJsonStringSuccess = AZ::RPI::JsonUtils::LoadObjectFromJsonString(variantJsonString, variantInfo); AZ_Assert(fromJsonStringSuccess, "Failed to convert json string to VariantInfo"); RPI::ShaderSourceData shaderSourceDescriptor; diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp index 0d089a26bf..e0812f633a 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp @@ -325,11 +325,11 @@ namespace AZ DirectionalLightFeatureProcessorInterface::LightHandle DirectionalLightFeatureProcessor::AcquireLight() { const uint16_t index = m_lightData.GetFreeSlotIndex(); - const uint16_t shadowPropIndex = m_shadowProperties.GetFreeSlotIndex(); + [[maybe_unused]] const uint16_t shadowPropIndex = m_shadowProperties.GetFreeSlotIndex(); AZ_Assert(index == shadowPropIndex, "light index is illegal."); for (const auto& viewIt : m_cameraViewNames) { - const uint16_t shadowIndex = m_shadowData.at(viewIt.first).GetFreeSlotIndex(); + [[maybe_unused]] const uint16_t shadowIndex = m_shadowData.at(viewIt.first).GetFreeSlotIndex(); AZ_Assert(index == shadowIndex, "light index is illegal."); } diff --git a/Gems/Atom/Feature/Common/Code/Source/ImGui/ImGuiPass.cpp b/Gems/Atom/Feature/Common/Code/Source/ImGui/ImGuiPass.cpp index a885708a47..b6ca1191dd 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ImGui/ImGuiPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ImGui/ImGuiPass.cpp @@ -38,7 +38,7 @@ namespace AZ { namespace { - static const char* PassName = "ImGuiPass"; + [[maybe_unused]] static const char* PassName = "ImGuiPass"; static const char* ImguiShaderFilePath = "Shaders/imgui/imgui.azshader"; } diff --git a/Gems/Atom/Feature/Common/Code/Source/Utils/GpuBufferHandler.cpp b/Gems/Atom/Feature/Common/Code/Source/Utils/GpuBufferHandler.cpp index 3115c5410b..7a2827bebe 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Utils/GpuBufferHandler.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Utils/GpuBufferHandler.cpp @@ -17,7 +17,7 @@ namespace AZ { namespace Render { - static const char* ClassName = "GpuBufferHandler"; + [[maybe_unused]] static const char* ClassName = "GpuBufferHandler"; static const uint32_t BufferMinSize = 1 << 16; // Min 64Kb. GpuBufferHandler::GpuBufferHandler(const Descriptor& descriptor) diff --git a/Gems/Atom/RHI/Code/Source/RHI/FrameGraphExecuteGroup.cpp b/Gems/Atom/RHI/Code/Source/RHI/FrameGraphExecuteGroup.cpp index a493fbd143..d00991421f 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/FrameGraphExecuteGroup.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/FrameGraphExecuteGroup.cpp @@ -71,7 +71,7 @@ namespace AZ { EndContextInternal(m_contexts[contextIndex], contextIndex); - const int32_t activeCount = --m_contextCountActive; + [[maybe_unused]] const int32_t activeCount = --m_contextCountActive; AZ_Assert(activeCount >= 0, "Asymmetric calls to FrameSchedulerExecuteContext:: Begin / End."); ++m_contextCountCompleted; } diff --git a/Gems/Atom/RHI/Code/Source/RHI/Resource.cpp b/Gems/Atom/RHI/Code/Source/RHI/Resource.cpp index b7ae469f16..f27ea22d8a 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/Resource.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/Resource.cpp @@ -98,8 +98,8 @@ namespace AZ if (Validation::IsEnabled()) { // The frame attachment has tight control over lifecycle here. - const bool isAttach = (!m_frameAttachment && frameAttachment); - const bool isDetach = (m_frameAttachment && !frameAttachment); + [[maybe_unused]] const bool isAttach = (!m_frameAttachment && frameAttachment); + [[maybe_unused]] const bool isDetach = (m_frameAttachment && !frameAttachment); AZ_Assert(isAttach || isDetach, "The frame attachment for resource '%s' was not assigned properly."); } diff --git a/Gems/Atom/RHI/Code/Tests/BufferTests.cpp b/Gems/Atom/RHI/Code/Tests/BufferTests.cpp index 0ce4626b92..acf680a6d8 100644 --- a/Gems/Atom/RHI/Code/Tests/BufferTests.cpp +++ b/Gems/Atom/RHI/Code/Tests/BufferTests.cpp @@ -121,6 +121,7 @@ namespace UnitTest bufferPool->ForEach([&bufferIndex, &buffers]([[maybe_unused]] RHI::Buffer& buffer) { + AZ_UNUSED(buffers); // Prevent unused warning in release builds AZ_Assert(buffers[bufferIndex] == &buffer, "buffers don't match"); bufferIndex++; }); diff --git a/Gems/Atom/RHI/Code/Tests/FrameGraph.cpp b/Gems/Atom/RHI/Code/Tests/FrameGraph.cpp index e03c9d13b4..bc2dce056c 100644 --- a/Gems/Atom/RHI/Code/Tests/FrameGraph.cpp +++ b/Gems/Atom/RHI/Code/Tests/FrameGraph.cpp @@ -58,7 +58,7 @@ namespace UnitTest FrameGraphExecuteGroup* group = AddGroup(); group->Init(scope->GetId()); - const bool wasInserted = m_scopeIds.emplace(scope->GetId()).second; + [[maybe_unused]] const bool wasInserted = m_scopeIds.emplace(scope->GetId()).second; AZ_Assert(wasInserted, "scope was inserted already"); } } diff --git a/Gems/Atom/RHI/Code/Tests/ImageTests.cpp b/Gems/Atom/RHI/Code/Tests/ImageTests.cpp index d3f528c9cd..ebcc05abe1 100644 --- a/Gems/Atom/RHI/Code/Tests/ImageTests.cpp +++ b/Gems/Atom/RHI/Code/Tests/ImageTests.cpp @@ -108,6 +108,7 @@ namespace UnitTest imagePool->ForEach([&imageIndex, &images]([[maybe_unused]] const RHI::Image& image) { + AZ_UNUSED(images); // Prevent unused warning in release builds AZ_Assert(images[imageIndex] == &image, "images don't match"); imageIndex++; }); diff --git a/Gems/Atom/RHI/Code/Tests/QueryTests.cpp b/Gems/Atom/RHI/Code/Tests/QueryTests.cpp index f883f6a8bd..9eb45cbd96 100644 --- a/Gems/Atom/RHI/Code/Tests/QueryTests.cpp +++ b/Gems/Atom/RHI/Code/Tests/QueryTests.cpp @@ -112,6 +112,7 @@ namespace UnitTest queryPool->ForEach([&queryIndex, &queries]([[maybe_unused]] RHI::Query& query) { + AZ_UNUSED(queries); // Prevent unused warning in release builds AZ_Assert(queries[queryIndex] == &query, "Queries don't match"); queryIndex++; }); diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI.Builders/ShaderPlatformInterface.cpp b/Gems/Atom/RHI/Metal/Code/Source/RHI.Builders/ShaderPlatformInterface.cpp index 903b25e16f..7e41e50892 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI.Builders/ShaderPlatformInterface.cpp +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI.Builders/ShaderPlatformInterface.cpp @@ -191,7 +191,7 @@ namespace AZ StageDescriptor& outputDescriptor, const RHI::ShaderCompilerArguments& shaderCompilerArguments) const { - for (auto srgLayout : m_srgLayouts) + for ([[maybe_unused]] auto srgLayout : m_srgLayouts) { AZ_Assert(srgLayout != nullptr, "Most likely BuildPipelineLayoutDescriptor() was not called!"); } @@ -280,7 +280,7 @@ namespace AZ // Enable half precision types when shader model >= 6.2 int shaderModelMajor = 0; int shaderModelMinor = 0; - int numValuesRead = azsscanf(shaderModelVersion.c_str(), "%d_%d", &shaderModelMajor, &shaderModelMinor); + [[maybe_unused]] int numValuesRead = azsscanf(shaderModelVersion.c_str(), "%d_%d", &shaderModelMajor, &shaderModelMinor); AZ_Assert(numValuesRead == 2, "Unknown shader model version format"); if (shaderModelMajor >= 6 && shaderModelMinor >= 2) { diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.cpp b/Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.cpp index 05107128ad..b820a6bf76 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.cpp +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/ArgumentBuffer.cpp @@ -431,7 +431,7 @@ namespace AZ } else { - bool isBoundToGraphics = RHI::CheckBitsAny(visMaskIt->second, RHI::ShaderStageMask::Vertex) || RHI::CheckBitsAny(visMaskIt->second, RHI::ShaderStageMask::Fragment); + [[maybe_unused]] bool isBoundToGraphics = RHI::CheckBitsAny(visMaskIt->second, RHI::ShaderStageMask::Vertex) || RHI::CheckBitsAny(visMaskIt->second, RHI::ShaderStageMask::Fragment); AZ_Assert(isBoundToGraphics, "The visibility mask %i is not set for Vertex or fragment stage", visMaskIt->second); CollectResourcesForGraphics(commandEncoder, visMaskIt->second, it.second, resourcesToMakeResidentGraphics); } diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/BufferView.cpp b/Gems/Atom/RHI/Metal/Code/Source/RHI/BufferView.cpp index 9b67f5c6e2..5508086fe5 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/BufferView.cpp +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/BufferView.cpp @@ -54,7 +54,7 @@ namespace AZ usage : textureUsage]; mtlTextureDesc.textureType = MTLTextureTypeTextureBuffer; - uint32_t bytesPerRow = viewDescriptor.m_elementCount * bytesPerPixel; + [[maybe_unused]] uint32_t bytesPerRow = viewDescriptor.m_elementCount * bytesPerPixel; AZ_Assert(bytesPerRow == (viewDescriptor.m_elementCount * viewDescriptor.m_elementSize), "Mismatch for bytesPerRow"); id mtlTexture = [mtlBuffer newTextureWithDescriptor : mtlTextureDesc offset : m_memoryView.GetOffset() diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/PipelineState.cpp b/Gems/Atom/RHI/Metal/Code/Source/RHI/PipelineState.cpp index f1d9fdc3a6..8d6ab8fee3 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/PipelineState.cpp +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/PipelineState.cpp @@ -188,7 +188,7 @@ namespace AZ } else { - const char * errorStr = [ error.localizedDescription UTF8String ]; + [[maybe_unused]] const char * errorStr = [ error.localizedDescription UTF8String ]; AZ_Error("PipelineState", false, "Failed to compile compute pipeline state with error: %s.", errorStr); return RHI::ResultCode::Fail; } @@ -221,7 +221,7 @@ namespace AZ } else { - const char * errorStr = [ error.localizedDescription UTF8String ]; + [[maybe_unused]] const char * errorStr = [ error.localizedDescription UTF8String ]; AZ_Error("PipelineState", false, "Failed to compile compute pipeline state with error: %s.", errorStr); return RHI::ResultCode::Fail; } diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/BufferView.cpp b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/BufferView.cpp index d07ee5dde3..3cd016ba39 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/BufferView.cpp +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/BufferView.cpp @@ -108,7 +108,7 @@ namespace AZ VkAccelerationStructureKHR BufferView::GetNativeAccelerationStructure() const { bool hasOverrideFlags = GetDescriptor().m_overrideBindFlags != RHI::BufferBindFlags::None; - const RHI::BufferBindFlags bindFlags = hasOverrideFlags ? GetDescriptor().m_overrideBindFlags : GetBuffer().GetDescriptor().m_bindFlags; + [[maybe_unused]] const RHI::BufferBindFlags bindFlags = hasOverrideFlags ? GetDescriptor().m_overrideBindFlags : GetBuffer().GetDescriptor().m_bindFlags; AZ_Assert(RHI::CheckBitsAll(bindFlags, RHI::BufferBindFlags::RayTracingAccelerationStructure), "GetNativeAccelerationStructure() is only valid for buffers with the RayTracingAccelerationStructure bind flag"); diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/ImageView.cpp b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/ImageView.cpp index 44c36f5c70..9a92028b86 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/ImageView.cpp +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/ImageView.cpp @@ -117,10 +117,10 @@ namespace AZ const auto& device = static_cast(GetDevice()); const auto& physicalDevice = static_cast(GetDevice().GetPhysicalDevice()); - const uint16_t width = static_cast(imgDesc.m_size.m_width); - const uint16_t height = static_cast(imgDesc.m_size.m_height); + [[maybe_unused]] const uint16_t width = static_cast(imgDesc.m_size.m_width); + [[maybe_unused]] const uint16_t height = static_cast(imgDesc.m_size.m_height); const uint16_t depth = AZStd::min(static_cast(imgViewDesc.m_depthSliceMax - imgViewDesc.m_depthSliceMin), static_cast(imgDesc.m_size.m_depth - 1)) + 1; - const uint16_t samples = imgDesc.m_multisampleState.m_samples; + [[maybe_unused]] const uint16_t samples = imgDesc.m_multisampleState.m_samples; const uint16_t arrayLayers = AZStd::min(static_cast(imgViewDesc.m_arraySliceMax - imgViewDesc.m_arraySliceMin), static_cast(imgDesc.m_arraySize - 1)) + 1; // We cannot only use the number of layers of the ImageView to determinate if is a texture array. You can have a texture array with only 1 layer and the shader expects // an array type instead of a normal image type. diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Image/ImageSystem.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Image/ImageSystem.cpp index cb838eb2ba..d4a55d1c29 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Image/ImageSystem.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Image/ImageSystem.cpp @@ -254,7 +254,7 @@ namespace AZ poolAssetCreator.SetPoolDescriptor(AZStd::move(imagePoolDescriptor)); poolAssetCreator.SetControllerAsset(m_defaultStreamingImageControllerAsset); poolAssetCreator.SetPoolName(systemStreamingPoolDescriptor.m_name); - const bool created = poolAssetCreator.End(poolAsset); + [[maybe_unused]] const bool created = poolAssetCreator.End(poolAsset); AZ_Assert(created, "Failed to build streaming image pool"); m_systemStreamingPool = StreamingImagePool::FindOrCreate(poolAsset); @@ -272,7 +272,7 @@ namespace AZ poolAssetCreator.SetPoolDescriptor(AZStd::move(imagePoolDescriptor)); poolAssetCreator.SetControllerAsset(m_defaultStreamingImageControllerAsset); poolAssetCreator.SetPoolName(assetStreamingPoolDescriptor.m_name); - const bool created = poolAssetCreator.End(poolAsset); + [[maybe_unused]] const bool created = poolAssetCreator.End(poolAsset); AZ_Assert(created, "Failed to build streaming image pool for assets"); m_assetStreamingPool = StreamingImagePool::FindOrCreate(poolAsset); @@ -292,7 +292,7 @@ namespace AZ poolAssetCreator.Begin(systemAttachmentPoolDescriptor.m_assetId); poolAssetCreator.SetPoolDescriptor(AZStd::move(imagePoolDescriptor)); poolAssetCreator.SetPoolName(systemAttachmentPoolDescriptor.m_name); - const bool created = poolAssetCreator.End(poolAsset); + [[maybe_unused]] const bool created = poolAssetCreator.End(poolAsset); AZ_Assert(created, "Failed to build attachment image pool"); m_systemAttachmentPool = AttachmentImagePool::FindOrCreate(poolAsset); diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Image/StreamingImageController.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Image/StreamingImageController.cpp index 97a3eb324b..a84d8ca9b7 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Image/StreamingImageController.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Image/StreamingImageController.cpp @@ -88,7 +88,7 @@ namespace AZ { if (StreamingImage* image = context->TryGetImage()) { - const RHI::ResultCode resultCode = image->ExpandMipChain(); + [[maybe_unused]] const RHI::ResultCode resultCode = image->ExpandMipChain(); AZ_Warning("StreamingImageController", resultCode == RHI::ResultCode::Success, "Failed to expand mip chain for streaming image."); } context->m_queuedForMipExpand = false; diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RenderPass.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RenderPass.cpp index 9b182a3c4b..318ea7d11f 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RenderPass.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RenderPass.cpp @@ -494,6 +494,7 @@ namespace AZ { if (query->BeginQuery(context) == QueryResultCode::Fail) { + AZ_UNUSED(this); // Prevent unused warning in release builds AZ_WarningOnce("RenderPass", false, "BeginScopeQuery failed. Make sure AddScopeQueryToFrameGraph was called in SetupFrameGraphDependencies" " for this pass: %s", this->RTTI_GetTypeName()); } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Shader/ShaderAsset.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Shader/ShaderAsset.cpp index bd49a72f40..616aa44299 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Shader/ShaderAsset.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Shader/ShaderAsset.cpp @@ -28,7 +28,7 @@ namespace AZ static constexpr uint32_t SubProductTypeBitPosition = 0; static constexpr uint32_t SubProductTypeNumBits = SupervariantIndexBitPosition - SubProductTypeBitPosition; - static constexpr uint32_t SubProductTypeMaxValue = (1 << SubProductTypeNumBits) - 1; + [[maybe_unused]] static constexpr uint32_t SubProductTypeMaxValue = (1 << SubProductTypeNumBits) - 1; static_assert(RhiIndexMaxValue == RHI::Limits::APIType::PerPlatformApiUniqueIndexMax); diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Shader/ShaderVariantAsset.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Shader/ShaderVariantAsset.cpp index 5d31feb411..442fc6a79f 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Shader/ShaderVariantAsset.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Shader/ShaderVariantAsset.cpp @@ -25,11 +25,11 @@ namespace AZ { static constexpr uint32_t SubProductTypeBitPosition = 17; static constexpr uint32_t SubProductTypeNumBits = SupervariantIndexBitPosition - SubProductTypeBitPosition; - static constexpr uint32_t SubProductTypeMaxValue = (1 << SubProductTypeNumBits) - 1; + [[maybe_unused]] static constexpr uint32_t SubProductTypeMaxValue = (1 << SubProductTypeNumBits) - 1; static constexpr uint32_t StableIdBitPosition = 0; static constexpr uint32_t StableIdNumBits = SubProductTypeBitPosition - StableIdBitPosition; - static constexpr uint32_t StableIdMaxValue = (1 << StableIdNumBits) - 1; + [[maybe_unused]] static constexpr uint32_t StableIdMaxValue = (1 << StableIdNumBits) - 1; static_assert(RhiIndexMaxValue == RHI::Limits::APIType::PerPlatformApiUniqueIndexMax); diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp index b8426f7528..36e45bb7ca 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp @@ -238,6 +238,7 @@ namespace AtomToolsFramework connectionSettings.m_connectionIdentifier = GetBuildTargetName(); connectionSettings.m_loggingCallback = [targetName]([[maybe_unused]] AZStd::string_view logData) { + AZ_UNUSED(targetName); // Prevent unused warning in release builds AZ_TracePrintf(targetName.c_str(), "%.*s", aznumeric_cast(logData.size()), logData.data()); }; AzFramework::AssetSystemRequestBus::BroadcastResult( diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp index 0be6925701..0388af0134 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp @@ -112,7 +112,7 @@ namespace MaterialEditor requestedViewportSize.width(), requestedViewportSize.height(), m_materialViewport->size().width(), m_materialViewport->size().height()); - QSize newDeviceSize = m_materialViewport->size(); + [[maybe_unused]] QSize newDeviceSize = m_materialViewport->size(); AZ_Warning( "Material Editor", static_cast(newDeviceSize.width()) == width && static_cast(newDeviceSize.height()) == height, "Resizing the window did not give the expected frame size. Requested %d x %d but got %d x %d.", width, height, diff --git a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiGpuProfiler.inl b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiGpuProfiler.inl index 49b6430221..9b2f2b0dd9 100644 --- a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiGpuProfiler.inl +++ b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiGpuProfiler.inl @@ -390,7 +390,7 @@ namespace AZ inline void ImGuiPipelineStatisticsView::CreateAttributeRow(const PassEntry* passEntry, const PassEntry* rootEntry) { - const uint32_t columnCount = static_cast(ImGui::GetColumnsCount()); + [[maybe_unused]] const uint32_t columnCount = static_cast(ImGui::GetColumnsCount()); AZ_Assert(columnCount == ImGuiPipelineStatisticsView::HeaderAttributeCount, "The column count needs to match HeaderAttributeCount."); ImGui::Separator(); @@ -1348,7 +1348,7 @@ namespace AZ PassEntry entry(pass, parent); // Set the time stamp in the database. - const auto passEntry = passEntryDatabase.find(entry.m_path); + [[maybe_unused]] const auto passEntry = passEntryDatabase.find(entry.m_path); AZ_Assert(passEntry == passEntryDatabase.end(), "There already is an entry with the name \"%s\".", entry.m_path.GetCStr()); // Set the entry in the map. diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Source/FontRenderer.cpp b/Gems/AtomLyIntegration/AtomFont/Code/Source/FontRenderer.cpp index 053a2eb419..f1fc8be965 100644 --- a/Gems/AtomLyIntegration/AtomFont/Code/Source/FontRenderer.cpp +++ b/Gems/AtomLyIntegration/AtomFont/Code/Source/FontRenderer.cpp @@ -256,7 +256,7 @@ int AZ::FontRenderer::GetGlyph(GlyphBitmap* glyphBitmap, int* horizontalAdvance, // might happen if font characters are too big or cache dimenstions in font.xml is too small "" const bool charWidthFits = static_cast(iX + m_glyph->bitmap.width) <= textureSlotBufferWidth; const bool charHeightFits = static_cast(iY + m_glyph->bitmap.rows) <= textureSlotBufferHeight; - const bool charFitsInSlot = charWidthFits && charHeightFits; + [[maybe_unused]] const bool charFitsInSlot = charWidthFits && charHeightFits; AZ_Error("Font", charFitsInSlot, "Character code %d doesn't fit in font texture; check 'sizeRatio' attribute in font XML or adjust this character's sizing in the font.", characterCode); // Since we might be re-rendering/overwriting a glyph that already exists diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp index 16243235a2..a3161002a0 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp @@ -811,7 +811,7 @@ namespace AZ const uint64_t inputByteOffset = aznumeric_cast(inputBufferViewDescriptor.m_elementOffset) * aznumeric_cast(inputBufferViewDescriptor.m_elementSize); const uint32_t outputElementSize = SkinnedMeshVertexStreamPropertyInterface::Get()->GetOutputStreamInfo(outputStream).m_elementSize; - const uint64_t outputByteCount = aznumeric_cast(lodVertexCount) * aznumeric_cast(outputElementSize); + [[maybe_unused]] const uint64_t outputByteCount = aznumeric_cast(lodVertexCount) * aznumeric_cast(outputElementSize); const uint64_t outputByteOffset = aznumeric_cast(outputBufferOffsetsInBytes[static_cast(outputStream)]); // The byte count from input and output buffers doesn't have to match necessarily. diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MotionSetCommands.cpp b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MotionSetCommands.cpp index c3d9a88471..34fee273c2 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MotionSetCommands.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/MotionSetCommands.cpp @@ -997,7 +997,7 @@ namespace CommandSystem else { AZStd::string result; - const bool success = GetCommandManager()->ExecuteCommand(AZStd::string::format("Unselect -motionName %s", selectedMotion->GetName()), result); + [[maybe_unused]] const bool success = GetCommandManager()->ExecuteCommand(AZStd::string::format("Unselect -motionName %s", selectedMotion->GetName()), result); AZ_Error("EMotionFX", success, result.c_str()); } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Pipeline/RCExt/Motion/MotionDataBuilder.cpp b/Gems/EMotionFX/Code/EMotionFX/Pipeline/RCExt/Motion/MotionDataBuilder.cpp index 130aa41931..422baa5125 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Pipeline/RCExt/Motion/MotionDataBuilder.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Pipeline/RCExt/Motion/MotionDataBuilder.cpp @@ -406,7 +406,7 @@ namespace EMotionFX for (; iterator != sceneGraphDownardsIteratorView.end(); ++iterator) { SceneContainers::SceneGraph::HierarchyStorageConstIterator hierarchy = iterator.GetHierarchyIterator(); - SceneContainers::SceneGraph::NodeIndex currentIndex = graph.ConvertToNodeIndex(hierarchy); + [[maybe_unused]] SceneContainers::SceneGraph::NodeIndex currentIndex = graph.ConvertToNodeIndex(hierarchy); AZ_Assert(currentIndex.IsValid(), "While iterating through the Scene Graph an unexpected invalid entry was found."); AZStd::shared_ptr currentItem = iterator->second; if (hierarchy->IsEndPoint()) diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Pose.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Pose.cpp index 99f1474c89..e2bff677ad 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Pose.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Pose.cpp @@ -728,7 +728,7 @@ namespace EMotionFX m_localSpaceTransforms[nodeNr].Zero(); } - const size_t numMorphs = m_morphWeights.size(); + [[maybe_unused]] const size_t numMorphs = m_morphWeights.size(); MCORE_ASSERT(m_actorInstance->GetMorphSetupInstance()->GetNumMorphTargets() == numMorphs); for (float& morphWeight : m_morphWeights) { @@ -743,7 +743,7 @@ namespace EMotionFX m_localSpaceTransforms[i].Zero(); } - const size_t numMorphs = m_morphWeights.size(); + [[maybe_unused]] const size_t numMorphs = m_morphWeights.size(); MCORE_ASSERT(m_actor->GetMorphSetup(0)->GetNumMorphTargets() == numMorphs); for (float& morphWeight : m_morphWeights) { diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NodeHierarchyWidget.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NodeHierarchyWidget.cpp index 63934a380c..89e5363bbb 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NodeHierarchyWidget.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/NodeHierarchyWidget.cpp @@ -454,7 +454,7 @@ namespace EMStudio // get the actor instance id to which this item belongs to m_actorInstanceIdString = FromQtString(item->whatsThis(0)); int actorInstanceID; - const bool validConversion = AzFramework::StringFunc::LooksLikeInt(m_actorInstanceIdString.c_str(), &actorInstanceID); + [[maybe_unused]] const bool validConversion = AzFramework::StringFunc::LooksLikeInt(m_actorInstanceIdString.c_str(), &actorInstanceID); MCORE_ASSERT(validConversion); // remove the node from the selected nodes @@ -497,7 +497,7 @@ namespace EMStudio FromQtString(item->whatsThis(0), &m_actorInstanceIdString); int actorInstanceID; - const bool validConversion = AzFramework::StringFunc::LooksLikeInt(m_actorInstanceIdString.c_str(), &actorInstanceID); + [[maybe_unused]] const bool validConversion = AzFramework::StringFunc::LooksLikeInt(m_actorInstanceIdString.c_str(), &actorInstanceID); MCORE_ASSERT(validConversion); EMotionFX::ActorInstance* actorInstance = EMotionFX::GetActorManager().FindActorInstanceByID(actorInstanceID); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGraph.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGraph.cpp index 596f3d7e30..759adbcb1c 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGraph.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGraph.cpp @@ -2077,7 +2077,7 @@ namespace EMStudio if (visualStateConnection->GetModelIndex() == modelIndex) { // Transfer ownership from the previous visual node to where we relinked the transition to. - const bool connectionRemoveResult = visualNode->RemoveConnection(transition, false); + [[maybe_unused]] const bool connectionRemoveResult = visualNode->RemoveConnection(transition, false); AZ_Error("EMotionFX", connectionRemoveResult, "Removing connection failed."); targetGraphNode->AddConnection(visualStateConnection); diff --git a/Gems/GraphModel/Code/Source/Integration/GraphController.cpp b/Gems/GraphModel/Code/Source/Integration/GraphController.cpp index 3551e5ba41..86cfb42990 100644 --- a/Gems/GraphModel/Code/Source/Integration/GraphController.cpp +++ b/Gems/GraphModel/Code/Source/Integration/GraphController.cpp @@ -280,6 +280,7 @@ namespace GraphModelIntegration } else { + AZ_UNUSED(this); // Prevent unused warning in release builds AZ_Error(m_graph->GetSystemName(), false, "Failed to load position information for node [%d]", nodeId); } diff --git a/Gems/ImGui/Code/Include/ImGuiContextScope.h b/Gems/ImGui/Code/Include/ImGuiContextScope.h index 553430862e..f9b2df1834 100644 --- a/Gems/ImGui/Code/Include/ImGuiContextScope.h +++ b/Gems/ImGui/Code/Include/ImGuiContextScope.h @@ -39,6 +39,6 @@ namespace ImGui private: //////////////////////////////////////////////////////////////////////////////////////////// - ImGuiContext* m_previousContext = nullptr; + [[maybe_unused]] ImGuiContext* m_previousContext = nullptr; }; } diff --git a/Gems/InAppPurchases/Code/Source/Platform/Common/Apple/InAppPurchasesDelegate.mm b/Gems/InAppPurchases/Code/Source/Platform/Common/Apple/InAppPurchasesDelegate.mm index 09d087e97a..d1ec128236 100644 --- a/Gems/InAppPurchases/Code/Source/Platform/Common/Apple/InAppPurchasesDelegate.mm +++ b/Gems/InAppPurchases/Code/Source/Platform/Common/Apple/InAppPurchasesDelegate.mm @@ -131,7 +131,7 @@ -(void) productsRequest:(SKProductsRequest*) request didReceiveResponse:(SKProductsResponse*) response { - for (NSString* invalidId in response.invalidProductIdentifiers) + for ([[maybe_unused]] NSString* invalidId in response.invalidProductIdentifiers) { AZ_TracePrintf("O3DEInAppPurchases:", "Invalid product ID:", [invalidId cStringUsingEncoding:NSASCIIStringEncoding]); } diff --git a/Gems/LmbrCentral/Code/Source/Builders/SliceBuilder/SliceBuilderWorker.cpp b/Gems/LmbrCentral/Code/Source/Builders/SliceBuilder/SliceBuilderWorker.cpp index 88284ede1d..4fc350067d 100644 --- a/Gems/LmbrCentral/Code/Source/Builders/SliceBuilder/SliceBuilderWorker.cpp +++ b/Gems/LmbrCentral/Code/Source/Builders/SliceBuilder/SliceBuilderWorker.cpp @@ -388,11 +388,11 @@ namespace SliceBuilder bool sliceWritable = AZ::IO::SystemFile::IsWritable(fullPath.c_str()); if (!m_settings.m_enableSliceConversion || !sliceWritable) { - static const char* const s_OutOfDate = "This slice file is out of date: "; - static const char* const s_ToEnable = "To enable automatic upgrades:"; - static const char* const s_FixSettings1 = "In the settings file "; - static const char* const s_FixSettings2 = ", Set 'EnableSliceConversion' to true and restart the Asset Processor"; - static const char* const s_FixReadOnly = "Make sure the slice file isn't marked read-only. If using perforce, check out the slice file."; + [[maybe_unused]] static const char* const s_OutOfDate = "This slice file is out of date: "; + [[maybe_unused]] static const char* const s_ToEnable = "To enable automatic upgrades:"; + [[maybe_unused]] static const char* const s_FixSettings1 = "In the settings file "; + [[maybe_unused]] static const char* const s_FixSettings2 = ", Set 'EnableSliceConversion' to true and restart the Asset Processor"; + [[maybe_unused]] static const char* const s_FixReadOnly = "Make sure the slice file isn't marked read-only. If using perforce, check out the slice file."; // The Slice isn't marked as read only but Slice Upgrades aren't Enabled in the builder settings file if(!m_settings.m_enableSliceConversion && sliceWritable) @@ -512,10 +512,10 @@ namespace SliceBuilder // To avoid potential data loss, only delete the old file if there is a data patching error detected if (m_sliceDataPatchError) { - static const char* const s_overrideWarning = "At least one Data Patch Upgrade wasn't completed:"; - static const char* const s_checkLogs = "Please check the slice processing log for more information."; - static const char* const s_originalSliceAvailable = "The original slice file has been preserved at: "; - static const char* const s_recomendReload = "It's recomended that this slice be loaded into the editor and repaired before upgrading."; + [[maybe_unused]] static const char* const s_overrideWarning = "At least one Data Patch Upgrade wasn't completed:"; + [[maybe_unused]] static const char* const s_checkLogs = "Please check the slice processing log for more information."; + [[maybe_unused]] static const char* const s_originalSliceAvailable = "The original slice file has been preserved at: "; + [[maybe_unused]] static const char* const s_recomendReload = "It's recomended that this slice be loaded into the editor and repaired before upgrading."; AZ_Warning(s_sliceBuilder, false, "%s\n%s\n%s%s\n%s", s_overrideWarning, s_checkLogs, s_originalSliceAvailable, oldPath.c_str(), s_recomendReload); } diff --git a/Gems/LyShine/Code/Editor/Animation/UiAnimViewAnimNode.cpp b/Gems/LyShine/Code/Editor/Animation/UiAnimViewAnimNode.cpp index 41397ce265..5d62f88310 100644 --- a/Gems/LyShine/Code/Editor/Animation/UiAnimViewAnimNode.cpp +++ b/Gems/LyShine/Code/Editor/Animation/UiAnimViewAnimNode.cpp @@ -178,8 +178,8 @@ void CUiAnimViewAnimNode::UiElementPropertyChanged() AZ::Component* oldComponent = oldComponents[componentIndex]; AZ::Component* newComponent = newComponents[componentIndex]; - AZ::Uuid oldComponentType = oldComponent->RTTI_GetType(); - AZ::Uuid newComponentType = newComponent->RTTI_GetType(); + [[maybe_unused]] AZ::Uuid oldComponentType = oldComponent->RTTI_GetType(); + [[maybe_unused]] AZ::Uuid newComponentType = newComponent->RTTI_GetType(); AZ_Assert(oldComponentType == newComponentType, "Components have different types"); diff --git a/Gems/LyShine/Code/Source/LyShineDebug.cpp b/Gems/LyShine/Code/Source/LyShineDebug.cpp index a30f816c73..160df96ac9 100644 --- a/Gems/LyShine/Code/Source/LyShineDebug.cpp +++ b/Gems/LyShine/Code/Source/LyShineDebug.cpp @@ -39,7 +39,7 @@ AllocateConstIntCVar(LyShineDebug, CV_r_DebugUIDraw2dLine); AllocateConstIntCVar(LyShineDebug, CV_r_DebugUIDraw2dDefer); static const int g_numColors = 8; -static const char* g_colorNames[g_numColors] = +[[maybe_unused]] static const char* g_colorNames[g_numColors] = { "white", "red", @@ -64,7 +64,7 @@ static AZ::Vector3 g_colorVec3[g_numColors] = }; static const int g_numSrcBlendModes = 11; -static int g_srcBlendModes[g_numSrcBlendModes] = +[[maybe_unused]] static int g_srcBlendModes[g_numSrcBlendModes] = { GS_BLSRC_ZERO, GS_BLSRC_ONE, @@ -80,7 +80,7 @@ static int g_srcBlendModes[g_numSrcBlendModes] = }; static const int g_numDstBlendModes = 10; -static int g_dstBlendModes[g_numDstBlendModes] = +[[maybe_unused]] static int g_dstBlendModes[g_numDstBlendModes] = { GS_BLDST_ZERO, GS_BLDST_ONE, @@ -94,7 +94,7 @@ static int g_dstBlendModes[g_numDstBlendModes] = GS_BLDST_ONEMINUSSRC1ALPHA, // dual source blending }; -static bool g_deferDrawsToEndOfFrame = false; +[[maybe_unused]] static bool g_deferDrawsToEndOfFrame = false; //////////////////////////////////////////////////////////////////////////////////////////////////// // LOCAL STATIC FUNCTIONS diff --git a/Gems/Maestro/Code/Source/Components/EditorSequenceAgentComponent.cpp b/Gems/Maestro/Code/Source/Components/EditorSequenceAgentComponent.cpp index 4264dd0ab3..acc9713291 100644 --- a/Gems/Maestro/Code/Source/Components/EditorSequenceAgentComponent.cpp +++ b/Gems/Maestro/Code/Source/Components/EditorSequenceAgentComponent.cpp @@ -146,7 +146,7 @@ namespace Maestro AZ::EntityId sequenceEntityId = busIdToDisconnect->first; // we only process DisconnectSequence events sent over an ID'ed bus - otherwise we don't know which SequenceComponent to disconnect - auto findIter = m_sequenceEntityIds.find(sequenceEntityId); + [[maybe_unused]] auto findIter = m_sequenceEntityIds.find(sequenceEntityId); AZ_Assert(findIter != m_sequenceEntityIds.end(), "A sequence not connected to SequenceAgentComponent on %s is requesting a disconnection", GetEntity()->GetName().c_str()); m_sequenceEntityIds.erase(sequenceEntityId); diff --git a/Gems/Maestro/Code/Source/Components/SequenceAgentComponent.cpp b/Gems/Maestro/Code/Source/Components/SequenceAgentComponent.cpp index 83599d7b40..5f38334c83 100644 --- a/Gems/Maestro/Code/Source/Components/SequenceAgentComponent.cpp +++ b/Gems/Maestro/Code/Source/Components/SequenceAgentComponent.cpp @@ -74,7 +74,7 @@ namespace Maestro AZ::EntityId sequenceEntityId = busIdToDisconnect->first; // we only process DisconnectSequence events sent over an ID'ed bus - otherwise we don't know which SequenceComponent to disconnect - auto findIter = m_sequenceEntityIds.find(sequenceEntityId); + [[maybe_unused]] auto findIter = m_sequenceEntityIds.find(sequenceEntityId); AZ_Assert(findIter != m_sequenceEntityIds.end(), "A sequence not connected to SequenceAgentComponent on %s is requesting a disconnection", GetEntity()->GetName().c_str()); m_sequenceEntityIds.erase(sequenceEntityId); diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.h b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.h index 8a68110b93..2d0fe4da39 100644 --- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.h +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.h @@ -53,8 +53,8 @@ namespace Multiplayer AZStd::map m_receivingEntityReports{}; MultiplayerDebugEntityReporter m_currentReceivingEntityReport; - float m_replicatedStateKbpsWarn = 10.f; - float m_replicatedStateMaxSizeWarn = 30.f; + [[maybe_unused]] float m_replicatedStateKbpsWarn = 10.f; + [[maybe_unused]] float m_replicatedStateMaxSizeWarn = 30.f; char m_statusBuffer[100] = {}; diff --git a/Gems/MultiplayerCompression/Code/Tests/MultiplayerCompressionTest.cpp b/Gems/MultiplayerCompression/Code/Tests/MultiplayerCompressionTest.cpp index 572dffbe60..4748d0f331 100644 --- a/Gems/MultiplayerCompression/Code/Tests/MultiplayerCompressionTest.cpp +++ b/Gems/MultiplayerCompression/Code/Tests/MultiplayerCompressionTest.cpp @@ -53,7 +53,7 @@ TEST_F(MultiplayerCompressionTest, MultiplayerCompression_CompressTest) MultiplayerCompression::LZ4Compressor lz4Compressor; startTime = AZStd::chrono::system_clock::now(); AzNetworking::CompressorError compressStatus = lz4Compressor.Compress(buffer.GetBuffer(), buffer.GetSize(), pCompressedBuffer, maxCompressedSize, compressedSize); - const AZ::u64 compressTime = (AZStd::chrono::system_clock::now() - startTime).count(); + [[maybe_unused]] const AZ::u64 compressTime = (AZStd::chrono::system_clock::now() - startTime).count(); ASSERT_TRUE(compressStatus == AzNetworking::CompressorError::Ok); EXPECT_TRUE(compressedSize < maxCompressedSize); @@ -61,7 +61,7 @@ TEST_F(MultiplayerCompressionTest, MultiplayerCompression_CompressTest) //Run and test decompress startTime = AZStd::chrono::system_clock::now(); AzNetworking::CompressorError decompressStatus = lz4Compressor.Decompress(pCompressedBuffer, compressedSize, pDecompressedBuffer, buffer.GetSize(), consumedSize, uncompressedSize); - const AZ::u64 decompressTime = (AZStd::chrono::system_clock::now() - startTime).count(); + [[maybe_unused]] const AZ::u64 decompressTime = (AZStd::chrono::system_clock::now() - startTime).count(); ASSERT_TRUE(decompressStatus == AzNetworking::CompressorError::Ok); EXPECT_TRUE(uncompressedSize = buffer.GetSize()); diff --git a/Gems/PhysX/Code/Source/Debug/PhysXDebug.h b/Gems/PhysX/Code/Source/Debug/PhysXDebug.h index 8286981032..58d6f7e03e 100644 --- a/Gems/PhysX/Code/Source/Debug/PhysXDebug.h +++ b/Gems/PhysX/Code/Source/Debug/PhysXDebug.h @@ -43,7 +43,7 @@ namespace PhysX void DisconnectFromPvd() override; private: - physx::PxPvdTransport* m_pvdTransport = nullptr; + [[maybe_unused]] physx::PxPvdTransport* m_pvdTransport = nullptr; physx::PxPvd* m_pvd = nullptr; DebugConfiguration m_config; diff --git a/Gems/PhysX/Code/Source/Scene/PhysXScene.cpp b/Gems/PhysX/Code/Source/Scene/PhysXScene.cpp index a2866b5a09..3b5c98ba2d 100644 --- a/Gems/PhysX/Code/Source/Scene/PhysXScene.cpp +++ b/Gems/PhysX/Code/Source/Scene/PhysXScene.cpp @@ -182,7 +182,7 @@ namespace PhysX SimulatedBodyType* newBody = aznew SimulatedBodyType(*configuration); if (!AZStd::holds_alternative(configuration->m_colliderAndShapeData)) { - const bool shapeAdded = AddShape(newBody, configuration->m_colliderAndShapeData); + [[maybe_unused]] const bool shapeAdded = AddShape(newBody, configuration->m_colliderAndShapeData); AZ_Warning("PhysXScene", shapeAdded, "No Collider or Shape information found when creating Rigid body [%s]", configuration->m_debugName.c_str()); } crc = AZ::Crc32(newBody, sizeof(*newBody)); @@ -194,7 +194,7 @@ namespace PhysX RigidBody* newBody = aznew RigidBody(*configuration); if (!AZStd::holds_alternative(configuration->m_colliderAndShapeData)) { - const bool shapeAdded = AddShape(newBody, configuration->m_colliderAndShapeData); + [[maybe_unused]] const bool shapeAdded = AddShape(newBody, configuration->m_colliderAndShapeData); AZ_Warning("PhysXScene", shapeAdded, "No Collider or Shape information found when creating Rigid body [%s]", configuration->m_debugName.c_str()); } const AzPhysics::MassComputeFlags& flags = configuration->GetMassComputeFlags(); diff --git a/Gems/SceneLoggingExample/Code/Processors/ExportTrackingProcessor.cpp b/Gems/SceneLoggingExample/Code/Processors/ExportTrackingProcessor.cpp index 7b3b99c641..0f169d1265 100644 --- a/Gems/SceneLoggingExample/Code/Processors/ExportTrackingProcessor.cpp +++ b/Gems/SceneLoggingExample/Code/Processors/ExportTrackingProcessor.cpp @@ -171,7 +171,7 @@ namespace SceneLoggingExample { // While it's generally preferable to stick with either index- or iterator-based traversal, there may be times where switching between one // or the other becomes necessary. The SceneGraph provides utility functions to convert between the two approaches. - AZ::SceneAPI::Containers::SceneGraph::NodeIndex itNodeIndex = graph.ConvertToNodeIndex(it.GetHierarchyIterator()); + [[maybe_unused]] AZ::SceneAPI::Containers::SceneGraph::NodeIndex itNodeIndex = graph.ConvertToNodeIndex(it.GetHierarchyIterator()); // Nodes in the SceneGraph can be marked as endpoints. To the graph, this means that these nodes are not allowed to have children. // While not a true one-to-one mapping, endpoints often act as attributes to a node. For example, a transform can be marked as an endpoint. diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Node.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Node.cpp index 059b560cb0..2ae37b1253 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Node.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Node.cpp @@ -2885,7 +2885,7 @@ namespace ScriptCanvas if (node == nullptr) { AZStd::string assetName = m_graphRequestBus->GetAssetName(); - AZ::EntityId assetNodeId = m_graphRequestBus->FindAssetNodeIdByRuntimeNodeId(endpoint.GetNodeId()); + [[maybe_unused]] AZ::EntityId assetNodeId = m_graphRequestBus->FindAssetNodeIdByRuntimeNodeId(endpoint.GetNodeId()); AZ_Warning("Script Canvas", false, "Unable to find node with id (id: %s) in the graph '%s'. Most likely the node was serialized with a type that is no longer reflected", assetNodeId.ToString().data(), assetName.data()); @@ -2900,7 +2900,7 @@ namespace ScriptCanvas if (!endpointSlot) { AZStd::string assetName = m_graphRequestBus->GetAssetName(); - AZ::EntityId assetNodeId = m_graphRequestBus->FindAssetNodeIdByRuntimeNodeId(endpoint.GetNodeId()); + [[maybe_unused]] AZ::EntityId assetNodeId = m_graphRequestBus->FindAssetNodeIdByRuntimeNodeId(endpoint.GetNodeId()); AZ_Warning("Script Canvas", false, "Endpoint was missing slot. id (id: %s) in the graph '%s'.", assetNodeId.ToString().data(), assetName.data()); @@ -2934,7 +2934,7 @@ namespace ScriptCanvas if (node == nullptr) { AZStd::string assetName = m_graphRequestBus->GetAssetName(); - AZ::EntityId assetNodeId = m_graphRequestBus->FindAssetNodeIdByRuntimeNodeId(endpoint.GetNodeId()); + [[maybe_unused]] AZ::EntityId assetNodeId = m_graphRequestBus->FindAssetNodeIdByRuntimeNodeId(endpoint.GetNodeId()); AZ_Error("Script Canvas", false, "Unable to find node with id (id: %s) in the graph '%s'. Most likely the node was serialized with a type that is no longer reflected", assetNodeId.ToString().data(), assetName.data()); diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/Interpreted/ExecutionInterpretedAPI.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/Interpreted/ExecutionInterpretedAPI.cpp index cc2058f249..d7a4c360ac 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/Interpreted/ExecutionInterpretedAPI.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/Interpreted/ExecutionInterpretedAPI.cpp @@ -549,7 +549,7 @@ namespace ScriptCanvas { using namespace ExecutionInterpretedAPICpp; // Lua: usernodeable, keyCount - const int argsCount = lua_gettop(lua); + [[maybe_unused]] const int argsCount = lua_gettop(lua); AZ_Assert(argsCount == 2, "InitializeNodeableOutKeys: Error in compiled Lua file, not enough arguments"); AZ_Assert(lua_isuserdata(lua, 1), "InitializeNodeableOutKeys: Error in compiled lua file, 1st argument to SetExecutionOut is not userdata (Nodeable)"); Nodeable* nodeable = AZ::ScriptValue::StackRead(lua, 1); diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/NodeableOut/NodeableOutNative.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/NodeableOut/NodeableOutNative.h index dc428cb480..ab6859db1e 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/NodeableOut/NodeableOutNative.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/NodeableOut/NodeableOutNative.h @@ -23,7 +23,7 @@ namespace ScriptCanvas { auto nodeCallWrapper = [callable = AZStd::forward(callable)](AZ::BehaviorValueParameter* result, AZ::BehaviorValueParameter* arguments, int numArguments) mutable { - constexpr size_t numFunctorArguments = sizeof...(Args); + [[maybe_unused]] constexpr size_t numFunctorArguments = sizeof...(Args); (void)numArguments; AZ_Assert(numArguments == numFunctorArguments, "number of arguments doesn't match number of parameters"); AZ_Assert(result, "no null result allowed"); @@ -39,7 +39,7 @@ namespace ScriptCanvas { auto nodeCallWrapper = [callable = AZStd::forward(callable)](AZ::BehaviorValueParameter*, AZ::BehaviorValueParameter* arguments, int numArguments) mutable { - constexpr size_t numFunctorArguments = sizeof...(Args); + [[maybe_unused]] constexpr size_t numFunctorArguments = sizeof...(Args); (void)numArguments; AZ_Assert(numArguments == numFunctorArguments, "number of arguments doesn't match number of parameters"); AZStd::invoke(callable, *arguments[IndexSequence].GetAsUnsafe()...); diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/MethodUtility.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/MethodUtility.cpp index e2cfa8d9ad..0ddd161847 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/MethodUtility.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/MethodUtility.cpp @@ -45,7 +45,7 @@ namespace ScriptCanvas int tupleGetFuncIndex = -1; if (tupleGetFuncAttrReader.Read(tupleGetFuncIndex)) { - auto insertIter = tupleGetMethodMap.emplace(tupleGetFuncIndex, behaviorMethod); + [[maybe_unused]] auto insertIter = tupleGetMethodMap.emplace(tupleGetFuncIndex, behaviorMethod); AZ_Error("Script Canvas", insertIter.second, "Multiple methods with the same TupleGetFunctionIndex attribute" "has been registered for the class name: %s with typeid: %s", behaviorClass->m_name.data(), behaviorClass->m_typeId.ToString().data()) diff --git a/Gems/ScriptCanvas/Code/Source/SystemComponent.cpp b/Gems/ScriptCanvas/Code/Source/SystemComponent.cpp index 26af95fa8e..ba02fa8a62 100644 --- a/Gems/ScriptCanvas/Code/Source/SystemComponent.cpp +++ b/Gems/ScriptCanvas/Code/Source/SystemComponent.cpp @@ -260,7 +260,7 @@ namespace ScriptCanvas } LockType lock(m_ownedObjectsByAddressMutex); - auto emplaceResult = m_ownedObjectsByAddress.emplace(object, behaviorContextObject); + [[maybe_unused]] auto emplaceResult = m_ownedObjectsByAddress.emplace(object, behaviorContextObject); AZ_Assert(emplaceResult.second, "Adding second owned reference to memory"); } From 96a5f06ca3d627c2b9c574c72c4e464a415a91bc Mon Sep 17 00:00:00 2001 From: Artur K <96597+nemerle@users.noreply.github.com> Date: Mon, 30 Aug 2021 22:40:02 +0200 Subject: [PATCH 786/803] Legacy cleanup, part 2 (#3659) * Legacy cleanup, part 2 There are still things that can be removed, those will be likely done in part three: `The Return of the Cleanup` :) Signed-off-by: nemerle <96597+nemerle@users.noreply.github.com> * Fix windows build Somehow there were some unfixed errors from enabled warnings? I'm unsure if I've pulled repo in unstable state, or those were somehow missed. Signed-off-by: nemerle <96597+nemerle@users.noreply.github.com> --- Code/Editor/Controls/ImageHistogramCtrl.cpp | 6 +- Code/Editor/Controls/SplineCtrl.cpp | 4 +- Code/Editor/EditorViewportWidget.cpp | 3 - Code/Editor/Export/ExportManager.cpp | 7 +- Code/Editor/Geometry/TriMesh.cpp | 125 - Code/Editor/Geometry/TriMesh.h | 2 - Code/Editor/Include/Command.h | 27 +- Code/Editor/Include/IFileUtil.h | 3 +- Code/Editor/Include/IObjectManager.h | 2 +- Code/Editor/Lib/Tests/IEditorMock.h | 7 +- Code/Editor/Objects/BaseObject.cpp | 46 - Code/Editor/Objects/BaseObject.h | 4 - Code/Editor/Objects/DisplayContext.h | 1 + Code/Editor/Objects/ObjectManager.cpp | 20 +- Code/Editor/Objects/ObjectManager.h | 2 +- Code/Editor/ToolsConfigPage.cpp | 4 +- Code/Editor/Util/DynamicArray2D.cpp | 5 - Code/Editor/Util/DynamicArray2D.h | 2 - Code/Editor/Util/GdiUtil.cpp | 2 +- Code/Editor/Util/ImageHistogram.cpp | 2 +- Code/Editor/Viewport.cpp | 2 +- Code/Editor/ViewportTitleDlg.cpp | 7 +- Code/LauncherUnified/Launcher.h | 6 +- Code/Legacy/CryCommon/Common_TypeInfo.cpp | 142 +- Code/Legacy/CryCommon/CryArray.h | 1322 ----------- Code/Legacy/CryCommon/CryCommon.cpp | 53 - Code/Legacy/CryCommon/CryCustomTypes.h | 1204 ---------- Code/Legacy/CryCommon/CryHalf.inl | 2 - Code/Legacy/CryCommon/CryHalf_info.h | 28 - Code/Legacy/CryCommon/CryHeaders.h | 1506 ------------ Code/Legacy/CryCommon/CryHeaders_info.cpp | 486 ---- Code/Legacy/CryCommon/CrySizer.h | 23 - Code/Legacy/CryCommon/CryTypeInfo.cpp | 1472 ------------ Code/Legacy/CryCommon/CryTypeInfo.h | 219 -- Code/Legacy/CryCommon/Cry_Camera.h | 112 +- Code/Legacy/CryCommon/Cry_Color.h | 4 +- Code/Legacy/CryCommon/Cry_Geo.h | 5 - Code/Legacy/CryCommon/Cry_GeoOverlap.h | 1982 ---------------- Code/Legacy/CryCommon/Cry_Math.h | 2 +- Code/Legacy/CryCommon/Cry_Matrix33.h | 2 - Code/Legacy/CryCommon/Cry_Matrix34.h | 2 - Code/Legacy/CryCommon/Cry_Matrix44.h | 2 - Code/Legacy/CryCommon/Cry_Quat.h | 11 - Code/Legacy/CryCommon/Cry_Vector2.h | 2 - Code/Legacy/CryCommon/Cry_Vector3.h | 6 - Code/Legacy/CryCommon/Cry_Vector4.h | 2 - Code/Legacy/CryCommon/HMDBus.h | 46 +- Code/Legacy/CryCommon/IConsole.h | 38 +- Code/Legacy/CryCommon/IEntityRenderState.h | 555 +---- .../CryCommon/IEntityRenderState_info.cpp | 41 - Code/Legacy/CryCommon/IFont.h | 1 + Code/Legacy/CryCommon/IIndexedMesh.h | 2064 +---------------- Code/Legacy/CryCommon/IIndexedMesh_info.cpp | 46 - Code/Legacy/CryCommon/ILocalizationManager.h | 4 +- Code/Legacy/CryCommon/IMaterial.h | 395 +--- Code/Legacy/CryCommon/IMovieSystem.h | 1 - Code/Legacy/CryCommon/IPathfinder.h | 29 +- Code/Legacy/CryCommon/IPhysics.h | 38 - Code/Legacy/CryCommon/IPostEffectGroup.h | 49 - Code/Legacy/CryCommon/IRenderMesh.h | 282 --- Code/Legacy/CryCommon/ISerialize.h | 7 - Code/Legacy/CryCommon/IShader.h | 1204 +--------- Code/Legacy/CryCommon/ISplines.h | 1 + Code/Legacy/CryCommon/IStatObj.h | 190 -- Code/Legacy/CryCommon/IStereoRenderer.h | 105 - Code/Legacy/CryCommon/ISystem.h | 54 - Code/Legacy/CryCommon/ITexture.h | 309 +-- Code/Legacy/CryCommon/IViewSystem.h | 8 - .../LyShine/Animation/IUiAnimation.h | 1 - Code/Legacy/CryCommon/LyShine/UiBase.h | 4 +- Code/Legacy/CryCommon/MemoryAccess.h | 567 ----- Code/Legacy/CryCommon/Mocks/ICVarMock.h | 3 - Code/Legacy/CryCommon/Mocks/IConsoleMock.h | 7 - Code/Legacy/CryCommon/Mocks/ITextureMock.h | 148 -- Code/Legacy/CryCommon/Options.h | 90 - Code/Legacy/CryCommon/StereoRendererBus.h | 43 - Code/Legacy/CryCommon/StlUtils.h | 263 +-- Code/Legacy/CryCommon/Tarray.h | 56 - Code/Legacy/CryCommon/TimeValue.h | 2 - Code/Legacy/CryCommon/TimeValue_info.h | 21 - Code/Legacy/CryCommon/TypeInfo_decl.h | 120 - Code/Legacy/CryCommon/TypeInfo_impl.h | 213 -- Code/Legacy/CryCommon/VectorSet.h | 492 ---- Code/Legacy/CryCommon/Vertex.h | 782 +------ Code/Legacy/CryCommon/VertexFormats.h | 841 +------ Code/Legacy/CryCommon/crycommon_files.cmake | 26 - Code/Legacy/CryCommon/physinterface.h | 24 - Code/Legacy/CryCommon/platform.h | 6 - Code/Legacy/CryCommon/primitives.h | 294 --- Code/Legacy/CryCommon/smartptr.h | 2 - Code/Legacy/CryCommon/stridedptr.h | 114 - .../Legacy/CrySystem/LocalizedStringManager.h | 8 +- Code/Legacy/CrySystem/SimpleStringPool.h | 19 +- Code/Legacy/CrySystem/System.cpp | 4 +- Code/Legacy/CrySystem/ViewSystem/View.cpp | 15 +- Code/Legacy/CrySystem/ViewSystem/View.h | 2 +- .../CrySystem/ViewSystem/ViewSystem.cpp | 20 +- Code/Legacy/CrySystem/ViewSystem/ViewSystem.h | 1 - Code/Legacy/CrySystem/XConsole.cpp | 227 +- Code/Legacy/CrySystem/XConsole.h | 11 - Code/Legacy/CrySystem/XConsoleVariable.cpp | 34 - Code/Legacy/CrySystem/XConsoleVariable.h | 13 +- .../Code/Source/Ai/NavigationComponent.cpp | 11 +- .../Editor/Animation/UiAnimUndoManager.cpp | 3 +- Gems/LyShine/Code/Editor/EditorCommon.h | 1 - Gems/LyShine/Code/Editor/EditorWindow.cpp | 4 +- Gems/LyShine/Code/Editor/HierarchyHelpers.cpp | 14 +- .../Code/Editor/PropertiesContainer.cpp | 4 +- Gems/LyShine/Code/Editor/SerializeHelpers.cpp | 9 +- .../LyShine/Code/Source/UiCanvasComponent.cpp | 6 +- .../Code/Source/UiElementComponent.cpp | 10 +- .../Tests/UiDynamicScrollBoxComponentTest.cpp | 4 +- .../Code/Source/Cinematics/AnimPostFXNode.cpp | 3 +- .../Code/Source/Cinematics/MaterialNode.h | 4 +- Gems/Maestro/Code/Source/Cinematics/Movie.h | 3 + .../Code/Source/MaestroSystemComponent.h | 1 + 116 files changed, 189 insertions(+), 18706 deletions(-) delete mode 100644 Code/Legacy/CryCommon/CryArray.h delete mode 100644 Code/Legacy/CryCommon/CryCommon.cpp delete mode 100644 Code/Legacy/CryCommon/CryCustomTypes.h delete mode 100644 Code/Legacy/CryCommon/CryHalf_info.h delete mode 100644 Code/Legacy/CryCommon/CryHeaders.h delete mode 100644 Code/Legacy/CryCommon/CryHeaders_info.cpp delete mode 100644 Code/Legacy/CryCommon/CryTypeInfo.cpp delete mode 100644 Code/Legacy/CryCommon/CryTypeInfo.h delete mode 100644 Code/Legacy/CryCommon/Cry_GeoOverlap.h delete mode 100644 Code/Legacy/CryCommon/IEntityRenderState_info.cpp delete mode 100644 Code/Legacy/CryCommon/IIndexedMesh_info.cpp delete mode 100644 Code/Legacy/CryCommon/IPhysics.h delete mode 100644 Code/Legacy/CryCommon/IPostEffectGroup.h delete mode 100644 Code/Legacy/CryCommon/IRenderMesh.h delete mode 100644 Code/Legacy/CryCommon/IStereoRenderer.h delete mode 100644 Code/Legacy/CryCommon/MemoryAccess.h delete mode 100644 Code/Legacy/CryCommon/Options.h delete mode 100644 Code/Legacy/CryCommon/StereoRendererBus.h delete mode 100644 Code/Legacy/CryCommon/Tarray.h delete mode 100644 Code/Legacy/CryCommon/TimeValue_info.h delete mode 100644 Code/Legacy/CryCommon/TypeInfo_decl.h delete mode 100644 Code/Legacy/CryCommon/TypeInfo_impl.h delete mode 100644 Code/Legacy/CryCommon/VectorSet.h delete mode 100644 Code/Legacy/CryCommon/physinterface.h delete mode 100644 Code/Legacy/CryCommon/primitives.h delete mode 100644 Code/Legacy/CryCommon/stridedptr.h diff --git a/Code/Editor/Controls/ImageHistogramCtrl.cpp b/Code/Editor/Controls/ImageHistogramCtrl.cpp index 48bc7a70d2..bdb81e3655 100644 --- a/Code/Editor/Controls/ImageHistogramCtrl.cpp +++ b/Code/Editor/Controls/ImageHistogramCtrl.cpp @@ -188,7 +188,7 @@ void CImageHistogramDisplay::paintEvent([[maybe_unused]] QPaintEvent* event) float scale = 0; i = static_cast(((float)x / graphWidth) * (kNumColorLevels - 1)); - i = CLAMP(i, 0, kNumColorLevels - 1); + i = AZStd::clamp(i, 0, kNumColorLevels - 1); switch (m_drawMode) { @@ -253,7 +253,7 @@ void CImageHistogramDisplay::paintEvent([[maybe_unused]] QPaintEvent* event) for (size_t x = 0, xCount = abs(rcGraph.width()); x < xCount; ++x) { i = static_cast(((float)x / graphWidth) * (kNumColorLevels - 1)); - i = CLAMP(i, 0, kNumColorLevels - 1); + i = AZStd::clamp(i, 0, kNumColorLevels - 1); crtX = static_cast(rcGraph.left() + x + 1); scaleR = scaleG = scaleB = scaleA = 0; @@ -345,7 +345,7 @@ void CImageHistogramDisplay::paintEvent([[maybe_unused]] QPaintEvent* event) { pos = (float)x / graphWidth; i = static_cast((float)((int)(pos * kNumColorLevels) % aThirdOfNumColorLevels) / aThirdOfNumColorLevels * kNumColorLevels); - i = CLAMP(i, 0, kNumColorLevels - 1); + i = AZStd::clamp(i, 0, kNumColorLevels - 1); scale = 0; // R diff --git a/Code/Editor/Controls/SplineCtrl.cpp b/Code/Editor/Controls/SplineCtrl.cpp index 8ccf103c25..73264274b7 100644 --- a/Code/Editor/Controls/SplineCtrl.cpp +++ b/Code/Editor/Controls/SplineCtrl.cpp @@ -101,7 +101,7 @@ void CSplineCtrl::PointToTimeValue(const QPoint& point, float& time, float& valu { time = XOfsToTime(point.x()); float t = float(m_rcSpline.bottom() - point.y()) / m_rcSpline.height(); - value = LERP(m_fMinValue, m_fMaxValue, t); + value = AZ::Lerp(m_fMinValue, m_fMaxValue, t); } ////////////////////////////////////////////////////////////////////////// @@ -109,7 +109,7 @@ float CSplineCtrl::XOfsToTime(int x) { // m_fMinTime to m_fMaxTime time range. float t = float(x - m_rcSpline.left()) / m_rcSpline.width(); - return LERP(m_fMinTime, m_fMaxTime, t); + return AZ::Lerp(m_fMinTime, m_fMaxTime, t); } ////////////////////////////////////////////////////////////////////////// diff --git a/Code/Editor/EditorViewportWidget.cpp b/Code/Editor/EditorViewportWidget.cpp index 796e16dd53..5294ebbc7e 100644 --- a/Code/Editor/EditorViewportWidget.cpp +++ b/Code/Editor/EditorViewportWidget.cpp @@ -54,7 +54,6 @@ // CryCommon #include #include -#include // AzFramework #include @@ -70,7 +69,6 @@ #include "Include/IDisplayViewport.h" #include "Objects/ObjectManager.h" #include "ProcessInfo.h" -#include "IPostEffectGroup.h" #include "EditorPreferencesPageGeneral.h" #include "ViewportManipulatorController.h" #include "EditorViewportSettings.h" @@ -100,7 +98,6 @@ #include #include -#include #include AZ_CVAR( diff --git a/Code/Editor/Export/ExportManager.cpp b/Code/Editor/Export/ExportManager.cpp index 220c341f5c..5527aa6ce6 100644 --- a/Code/Editor/Export/ExportManager.cpp +++ b/Code/Editor/Export/ExportManager.cpp @@ -356,10 +356,9 @@ void CExportManager::AddMesh(Export::CObject* pObj, const IIndexedMesh* pIndMesh for (int v = 0; v < meshDesc.m_nCoorCount; ++v) { - Export::UV tc; - meshDesc.m_pTexCoord[v].ExportTo(tc.u, tc.v); - tc.v = 1.0f - tc.v; - pObj->m_texCoords.push_back(tc); + Vec2 uv = meshDesc.m_pTexCoord[v].GetUV(); + uv.y = 1.0f - uv.y; + pObj->m_texCoords.push_back({uv.x,uv.y}); } if (pIndMesh->GetSubSetCount() && !(pIndMesh->GetSubSetCount() == 1 && pIndMesh->GetSubSet(0).nNumIndices == 0)) diff --git a/Code/Editor/Geometry/TriMesh.cpp b/Code/Editor/Geometry/TriMesh.cpp index d56aa038b5..efc201095d 100644 --- a/Code/Editor/Geometry/TriMesh.cpp +++ b/Code/Editor/Geometry/TriMesh.cpp @@ -161,61 +161,6 @@ void* CTriMesh::ReAllocElements(void* old_ptr, int new_elem_num, int size_of_ele return realloc(old_ptr, new_elem_num * size_of_element); } -////////////////////////////////////////////////////////////////////////// -// Unshare all vertices and split on 3 arrays, positions/texcoords. -////////////////////////////////////////////////////////////////////////// -void CTriMesh::SetFromMesh(CMesh& mesh) -{ - bbox = mesh.m_bbox; - - int maxVerts = mesh.GetIndexCount(); - - SetVertexCount(maxVerts); - SetUVCount(maxVerts); - if (mesh.m_pColor0) - { - SetColorsCount(maxVerts); - } - - SetFacesCount(mesh.GetIndexCount()); - - int numv = 0; - int numface = 0; - for (int nSubset = 0; nSubset < mesh.GetSubSetCount(); nSubset++) - { - SMeshSubset& subset = mesh.m_subsets[nSubset]; - for (int i = subset.nFirstIndexId; i < subset.nFirstIndexId + subset.nNumIndices; i += 3) - { - CTriFace& face = pFaces[numface++]; - for (int j = 0; j < 3; j++) - { - int idx = mesh.m_pIndices[i + j]; - pVertices[numv].pos = mesh.m_pPositions ? mesh.m_pPositions[idx] : mesh.m_pPositionsF16[idx].ToVec3(); - pWeights[numv] = 0.0f; - pUV[numv] = mesh.m_pTexCoord[idx]; - if (mesh.m_pColor0) - { - pColors[numv] = mesh.m_pColor0[idx]; - } - - face.v [j] = numv; - face.uv[j] = numv; - face.n [j] = mesh.m_pNorms[idx].GetN(); - face.MatID = static_cast(subset.nMatID); - face.flags = 0; - - numv++; - } - } - } - SetFacesCount(numface); - SharePositions(); - ShareUV(); - UpdateEdges(); - - CalcFaceNormals(); -} - ///////////////////////////////////////////////////////////////////////////////////// inline int FindVertexInHash(const Vec3& vPosToFind, const CTriVertex* pVectors, std::vector& hash, float fEpsilon) { @@ -360,76 +305,6 @@ void CTriMesh::CalcFaceNormals() #define TEX_EPS 0.001f #define VER_EPS 0.001f -////////////////////////////////////////////////////////////////////////// -void CTriMesh::UpdateIndexedMesh(IIndexedMesh* pIndexedMesh) const -{ - { - const int maxVerts = nFacesCount * 3; - - pIndexedMesh->SetVertexCount(maxVerts); - pIndexedMesh->SetTexCoordCount(maxVerts); - if (pColors) - { - pIndexedMesh->SetColorCount(maxVerts); - } - pIndexedMesh->SetIndexCount(0); - pIndexedMesh->SetFaceCount(nFacesCount); - } - - ////////////////////////////////////////////////////////////////////////// - // To find really used materials - std::vector usedMaterialIds; - uint16 MatIdToSubset[MAX_SUB_MATERIALS]; - uint16 nLastSubsetId = 0; - memset(MatIdToSubset, 0, sizeof(MatIdToSubset)); - ////////////////////////////////////////////////////////////////////////// - - CMesh& mesh = *pIndexedMesh->GetMesh(); - AABB bb; - bb.Reset(); - for (int i = 0; i < nFacesCount; ++i) - { - const CTriFace& face = pFaces[i]; - SMeshFace& meshFace = mesh.m_pFaces[i]; - - // Remap new used material ID to index of chunk id. - if (!MatIdToSubset[face.MatID]) - { - MatIdToSubset[face.MatID] = 1 + nLastSubsetId++; - usedMaterialIds.push_back(face.MatID); // Order of material ids in usedMaterialIds correspond to the indices of chunks. - } - meshFace.nSubset = static_cast(MatIdToSubset[face.MatID] - 1); - - for (int j = 0; j < 3; ++j) - { - const int dstVIdx = i * 3 + j; - - mesh.m_pPositions[dstVIdx] = pVertices[face.v[j]].pos; - mesh.m_pNorms[dstVIdx] = SMeshNormal(face.n[j]); - mesh.m_pTexCoord[dstVIdx] = pUV[face.uv[j]]; - if (pColors) - { - mesh.m_pColor0[dstVIdx] = pColors[face.v[j]]; - } - - meshFace.v[j] = dstVIdx; - - bb.Add(mesh.m_pPositions[dstVIdx]); - } - } - - pIndexedMesh->SetBBox(bb); - - pIndexedMesh->SetSubSetCount(static_cast(usedMaterialIds.size())); - for (int i = 0; i < usedMaterialIds.size(); i++) - { - pIndexedMesh->SetSubsetMaterialId(i, usedMaterialIds[i]); - } - - pIndexedMesh->Optimize(); -} - - ////////////////////////////////////////////////////////////////////////// void CTriMesh::CopyStream(CTriMesh& fromMesh, int stream) { diff --git a/Code/Editor/Geometry/TriMesh.h b/Code/Editor/Geometry/TriMesh.h index 9bb73f945d..a6c58b8f9d 100644 --- a/Code/Editor/Geometry/TriMesh.h +++ b/Code/Editor/Geometry/TriMesh.h @@ -198,8 +198,6 @@ public: void GetStreamInfo(int stream, void*& pStream, int& nElementSize) const; int GetStreamSize(int stream) const { return m_streamSize[stream]; }; - void SetFromMesh(CMesh& mesh); - void UpdateIndexedMesh(IIndexedMesh* pIndexedMesh) const; // Calculate per face normal. void CalcFaceNormals(); diff --git a/Code/Editor/Include/Command.h b/Code/Editor/Include/Command.h index e4fea5a3e7..dfdcec78ef 100644 --- a/Code/Editor/Include/Command.h +++ b/Code/Editor/Include/Command.h @@ -8,14 +8,12 @@ // Description : Classes to deal with commands - - -#ifndef CRYINCLUDE_EDITOR_INCLUDE_COMMAND_H -#define CRYINCLUDE_EDITOR_INCLUDE_COMMAND_H #pragma once #include - +#include +#include +#include #include "Util/EditorUtils.h" inline AZStd::string ToString(const QString& s) @@ -23,8 +21,20 @@ inline AZStd::string ToString(const QString& s) return s.toUtf8().data(); } + class CCommand { + static inline bool FromString(int32 &val, const char* s) { + if(!s) + { + return false; + } + val = (int)strtol(s, nullptr, 10); + if(val==0 && errno!=0) { + return false; + } + return true; + } public: CCommand( const AZStd::string& module, @@ -77,7 +87,7 @@ public: return false; } } - int GetArgCount() const + size_t GetArgCount() const { return m_args.size(); } const AZStd::string& GetArg(int i) const { @@ -85,7 +95,7 @@ public: return m_args[i]; } private: - DynArray m_args; + AZStd::vector m_args; unsigned char m_stringFlags; // This is needed to quote string parameters when logging a command. }; @@ -115,7 +125,7 @@ protected: static inline AZStd::string ToString_(const char* val) { return val; } template - static bool FromString_(T& t, const char* s) { return ::FromString(t, s); } + static bool FromString_(T& t, const char* s) { return FromString(t, s); } static inline bool FromString_(const char*& val, const char* s) { return (val = s) != 0; } @@ -789,4 +799,3 @@ QString CCommand6::Execute(const CCommand::CArgs& args) } return ""; } -#endif // CRYINCLUDE_EDITOR_INCLUDE_COMMAND_H diff --git a/Code/Editor/Include/IFileUtil.h b/Code/Editor/Include/IFileUtil.h index 700e04f6d3..e179f892d9 100644 --- a/Code/Editor/Include/IFileUtil.h +++ b/Code/Editor/Include/IFileUtil.h @@ -9,6 +9,7 @@ #pragma once #include "../Include/SandboxAPI.h" +#include #include class QWidget; @@ -103,7 +104,7 @@ struct IFileUtil } }; - typedef DynArray FileArray; + using FileArray = AZStd::vector; typedef bool (* ScanDirectoryUpdateCallBack)(const QString& msg); diff --git a/Code/Editor/Include/IObjectManager.h b/Code/Editor/Include/IObjectManager.h index 360cc8fe34..fb99a50bb0 100644 --- a/Code/Editor/Include/IObjectManager.h +++ b/Code/Editor/Include/IObjectManager.h @@ -89,7 +89,7 @@ public: //! Get array of objects, managed by manager (not contain sub objects of groups). //! @param layer if 0 get objects for all layers, or layer to get objects from. virtual void GetObjects(CBaseObjectsArray& objects) const = 0; - virtual void GetObjects(DynArray& objects) const = 0; + //virtual void GetObjects(DynArray& objects) const = 0; //! Get array of objects that pass the filter. //! @param filter The filter functor, return true if you want to get the certain obj, return false if want to skip it. diff --git a/Code/Editor/Lib/Tests/IEditorMock.h b/Code/Editor/Lib/Tests/IEditorMock.h index 242bf4d25c..30f1d23576 100644 --- a/Code/Editor/Lib/Tests/IEditorMock.h +++ b/Code/Editor/Lib/Tests/IEditorMock.h @@ -9,7 +9,6 @@ #include #include -#include #include class CEditorMock @@ -85,8 +84,8 @@ public: MOCK_METHOD0(GetObjectManager, struct IObjectManager* ()); MOCK_METHOD0(GetSettingsManager, CSettingsManager* ()); MOCK_METHOD1(GetDBItemManager, IDataBaseManager* (EDataBaseItemType)); - MOCK_METHOD0(GetMaterialManagerLibrary, IBaseLibraryManager* ()); - MOCK_METHOD0(GetIEditorMaterialManager, IEditorMaterialManager* ()); + MOCK_METHOD0(GetMaterialManagerLibrary, IBaseLibraryManager* ()); + MOCK_METHOD0(GetIEditorMaterialManager, IEditorMaterialManager* ()); MOCK_METHOD0(GetIconManager, IIconManager* ()); MOCK_METHOD0(GetMusicManager, CMusicManager* ()); MOCK_METHOD2(GetTerrainElevation, float(float , float )); @@ -183,7 +182,7 @@ public: MOCK_METHOD0(GetEnv, SSystemGlobalEnvironment* ()); MOCK_METHOD0(GetImageUtil, IImageUtil* ()); MOCK_METHOD0(GetEditorSettings, SEditorSettings* ()); - MOCK_METHOD0(GetLogFile, ILogFile* ()); + MOCK_METHOD0(GetLogFile, ILogFile* ()); MOCK_METHOD0(UnloadPlugins, void()); MOCK_METHOD0(LoadPlugins, void()); MOCK_METHOD1(GetSearchPath, QString(EEditorPathName)); diff --git a/Code/Editor/Objects/BaseObject.cpp b/Code/Editor/Objects/BaseObject.cpp index c653830e70..0d5f982bd4 100644 --- a/Code/Editor/Objects/BaseObject.cpp +++ b/Code/Editor/Objects/BaseObject.cpp @@ -2057,53 +2057,7 @@ bool CBaseObject::IsChildOf(CBaseObject* node) } ////////////////////////////////////////////////////////////////////////// -void CBaseObject::GetAllChildren(TBaseObjects& outAllChildren, CBaseObject* pObj) const -{ - const CBaseObject* pBaseObj = pObj ? pObj : this; - for (size_t i = 0, iChildCount(pBaseObj->GetChildCount()); i < iChildCount; ++i) - { - CBaseObject* pChild = pBaseObj->GetChild(i); - if (pChild == nullptr) - { - continue; - } - outAllChildren.push_back(pChild); - GetAllChildren(outAllChildren, pChild); - } -} - -void CBaseObject::GetAllChildren(DynArray< _smart_ptr >& outAllChildren, CBaseObject* pObj) const -{ - const CBaseObject* pBaseObj = pObj ? pObj : this; - - for (size_t i = 0, iChildCount(pBaseObj->GetChildCount()); i < iChildCount; ++i) - { - CBaseObject* pChild = pBaseObj->GetChild(i); - if (pChild == nullptr) - { - continue; - } - outAllChildren.push_back(pChild); - GetAllChildren(outAllChildren, pChild); - } -} - -void CBaseObject::GetAllChildren(CSelectionGroup& outAllChildren, CBaseObject* pObj) const -{ - const CBaseObject* pBaseObj = pObj ? pObj : this; - - for (size_t i = 0, iChildCount(pBaseObj->GetChildCount()); i < iChildCount; ++i) - { - CBaseObject* pChild = pBaseObj->GetChild(i); - if (pChild == nullptr) - { - continue; - } - outAllChildren.AddObject(pChild); - GetAllChildren(outAllChildren, pChild); - } -} ////////////////////////////////////////////////////////////////////////// void CBaseObject::CloneChildren(CBaseObject* pFromObject) diff --git a/Code/Editor/Objects/BaseObject.h b/Code/Editor/Objects/BaseObject.h index ece0bf67c3..89e47ae881 100644 --- a/Code/Editor/Objects/BaseObject.h +++ b/Code/Editor/Objects/BaseObject.h @@ -408,10 +408,6 @@ public: CBaseObject* GetParent() const { return m_parent; }; //! Scans hierarchy up to determine if we child of specified node. virtual bool IsChildOf(CBaseObject* node); - //! Get all child objects - void GetAllChildren(TBaseObjects& outAllChildren, CBaseObject* pObj = nullptr) const; - void GetAllChildren(DynArray< _smart_ptr >& outAllChildren, CBaseObject* pObj = nullptr) const; - void GetAllChildren(CSelectionGroup& outAllChildren, CBaseObject* pObj = nullptr) const; //! Clone Children void CloneChildren(CBaseObject* pFromObject); //! Attach new child node. diff --git a/Code/Editor/Objects/DisplayContext.h b/Code/Editor/Objects/DisplayContext.h index a78e35cdba..0f0f0e665a 100644 --- a/Code/Editor/Objects/DisplayContext.h +++ b/Code/Editor/Objects/DisplayContext.h @@ -18,6 +18,7 @@ #include "SandboxAPI.h" #include #include +#include #include diff --git a/Code/Editor/Objects/ObjectManager.cpp b/Code/Editor/Objects/ObjectManager.cpp index f8eebb1b19..9c452ac1ad 100644 --- a/Code/Editor/Objects/ObjectManager.cpp +++ b/Code/Editor/Objects/ObjectManager.cpp @@ -759,16 +759,16 @@ void CObjectManager::GetObjects(CBaseObjectsArray& objects) const } } -void CObjectManager::GetObjects(DynArray& objects) const -{ - CBaseObjectsArray objectArray; - GetObjects(objectArray); - objects.clear(); - for (size_t i = 0, iCount(objectArray.size()); i < iCount; ++i) - { - objects.push_back(objectArray[i]); - } -} +//void CObjectManager::GetObjects(DynArray& objects) const +//{ +// CBaseObjectsArray objectArray; +// GetObjects(objectArray); +// objects.clear(); +// for (size_t i = 0, iCount(objectArray.size()); i < iCount; ++i) +// { +// objects.push_back(objectArray[i]); +// } +//} void CObjectManager::GetObjects(CBaseObjectsArray& objects, BaseObjectFilterFunctor const& filter) const { diff --git a/Code/Editor/Objects/ObjectManager.h b/Code/Editor/Objects/ObjectManager.h index aa9faab0e4..a2e0822a2b 100644 --- a/Code/Editor/Objects/ObjectManager.h +++ b/Code/Editor/Objects/ObjectManager.h @@ -122,7 +122,7 @@ public: //! Get array of objects, managed by manager (not contain sub objects of groups). //! @param layer if 0 get objects for all layers, or layer to get objects from. void GetObjects(CBaseObjectsArray& objects) const; - void GetObjects(DynArray& objects) const; + //void GetObjects(DynArray& objects) const; //! Get array of objects that pass the filter. //! @param filter The filter functor, return true if you want to get the certain obj, return false if want to skip it. diff --git a/Code/Editor/ToolsConfigPage.cpp b/Code/Editor/ToolsConfigPage.cpp index 50001dc2f0..509dca55e3 100644 --- a/Code/Editor/ToolsConfigPage.cpp +++ b/Code/Editor/ToolsConfigPage.cpp @@ -59,8 +59,8 @@ public: } const QString iconsDir = gSettings.searchPaths[EDITOR_PATH_UI_ICONS][0]; CFileUtil::ScanDirectory(iconsDir, "*.png", pngFiles); - m_iconImages.reserve(pngFiles.size()); - m_iconFiles.reserve(pngFiles.size()); + m_iconImages.reserve(static_cast(pngFiles.size())); + m_iconFiles.reserve(static_cast(pngFiles.size())); for (size_t i = 0; i < pngFiles.size(); ++i) { const QString path = Path::Make(iconsDir, pngFiles[i].filename); diff --git a/Code/Editor/Util/DynamicArray2D.cpp b/Code/Editor/Util/DynamicArray2D.cpp index 6ac3edbb6b..3f09c557de 100644 --- a/Code/Editor/Util/DynamicArray2D.cpp +++ b/Code/Editor/Util/DynamicArray2D.cpp @@ -62,11 +62,6 @@ CDynamicArray2D::~CDynamicArray2D() } -void CDynamicArray2D::GetMemoryUsage(ICrySizer* pSizer) -{ - pSizer->Add((char*)this, m_Dimension1 * m_Dimension2 * sizeof(float) + sizeof(*this)); -} - void CDynamicArray2D::ScaleImage(CDynamicArray2D* pDestination) { //////////////////////////////////////////////////////////////////////// diff --git a/Code/Editor/Util/DynamicArray2D.h b/Code/Editor/Util/DynamicArray2D.h index 80e40bfd22..20d26d2d87 100644 --- a/Code/Editor/Util/DynamicArray2D.h +++ b/Code/Editor/Util/DynamicArray2D.h @@ -24,8 +24,6 @@ public: virtual ~CDynamicArray2D(); // void ScaleImage(CDynamicArray2D* pDestination); - // - void GetMemoryUsage(ICrySizer* pSizer); float** m_Array; // diff --git a/Code/Editor/Util/GdiUtil.cpp b/Code/Editor/Util/GdiUtil.cpp index 1048b5f4dd..72e5e28605 100644 --- a/Code/Editor/Util/GdiUtil.cpp +++ b/Code/Editor/Util/GdiUtil.cpp @@ -28,7 +28,7 @@ QColor ScaleColor(const QColor& c, float aScale) const float g = static_cast(aColor.green()) * aScale; const float b = static_cast(aColor.blue()) * aScale; - return QColor(CLAMP(static_cast(r), 0, 255), CLAMP(static_cast(g), 0, 255), CLAMP(static_cast(b), 0, 255)); + return QColor(AZStd::clamp(static_cast(r), 0, 255), AZStd::clamp(static_cast(g), 0, 255), AZStd::clamp(static_cast(b), 0, 255)); } CAlphaBitmap::CAlphaBitmap() diff --git a/Code/Editor/Util/ImageHistogram.cpp b/Code/Editor/Util/ImageHistogram.cpp index acea2dc340..4cc9816065 100644 --- a/Code/Editor/Util/ImageHistogram.cpp +++ b/Code/Editor/Util/ImageHistogram.cpp @@ -105,7 +105,7 @@ void CImageHistogram::ComputeHistogram(BYTE* pImageData, UINT aWidth, UINT aHeig ++m_count[3][a]; lumIndex = (r + b + g) / 3; - lumIndex = CLAMP(lumIndex, 0, kNumColorLevels - 1); + lumIndex = AZStd::clamp(lumIndex, 0, kNumColorLevels - 1); ++m_lumCount[lumIndex]; if (m_maxCount[0] < m_count[0][r]) diff --git a/Code/Editor/Viewport.cpp b/Code/Editor/Viewport.cpp index 0ddad5c31e..92e193bddf 100644 --- a/Code/Editor/Viewport.cpp +++ b/Code/Editor/Viewport.cpp @@ -1491,7 +1491,7 @@ void QtViewport::OnRawInput([[maybe_unused]] UINT wParam, HRAWINPUT lParam) float as = 0.001f * gSettings.cameraMoveSpeed; Ang3 ypr = CCamera::CreateAnglesYPR(Matrix33(viewTM)); ypr.x += -all6DOFs[5] * as * fScaleYPR; - ypr.y = CLAMP(ypr.y + all6DOFs[3] * as * fScaleYPR, -1.5f, 1.5f); // to keep rotation in reasonable range + ypr.y = AZStd::clamp(ypr.y + all6DOFs[3] * as * fScaleYPR, -1.5f, 1.5f); // to keep rotation in reasonable range ypr.z = 0; // to have camera always upward viewTM = Matrix34(CCamera::CreateOrientationYPR(ypr), viewTM.GetTranslation()); diff --git a/Code/Editor/ViewportTitleDlg.cpp b/Code/Editor/ViewportTitleDlg.cpp index a6dee5382e..1f04f71712 100644 --- a/Code/Editor/ViewportTitleDlg.cpp +++ b/Code/Editor/ViewportTitleDlg.cpp @@ -19,9 +19,6 @@ #include -// CryCommon -#include - // Editor #include "Settings.h" #include "ViewPane.h" @@ -800,8 +797,8 @@ void CViewportTitleDlg::OnSystemEvent(ESystemEvent event, UINT_PTR wparam, UINT_ const int eventHeight = static_cast(lparam); const QWidget* viewport = m_pViewPane->GetViewport(); - // This should eventually be converted to an EBus to make it easy to connect to the correct viewport - // sending the event. But for now, just detect that we've gotten width/height values that match our + // This should eventually be converted to an EBus to make it easy to connect to the correct viewport + // sending the event. But for now, just detect that we've gotten width/height values that match our // associated viewport if (viewport && (eventWidth == viewport->width()) && (eventHeight == viewport->height())) { diff --git a/Code/LauncherUnified/Launcher.h b/Code/LauncherUnified/Launcher.h index 5ff6009e43..7c4c09c19f 100644 --- a/Code/LauncherUnified/Launcher.h +++ b/Code/LauncherUnified/Launcher.h @@ -10,7 +10,9 @@ #include // for AZ_COMMAND_LINE_LEN #include #include +#include #include +#include struct IOutputPrintSink; @@ -34,7 +36,7 @@ namespace O3DELauncher #define COMMAND_LINE_ARG_COUNT_LIMIT (AZ_COMMAND_LINE_LEN+1) / 2 // Assume that the limit to how many arguments we can maintain is the max buffer size divided by 2 // to account for an argument and a spec in between each argument (with the worse case scenario being - + struct PlatformMainInfo { typedef bool (*ResourceLimitUpdater)(); @@ -69,7 +71,7 @@ namespace O3DELauncher void* m_window = nullptr; //!< maps to \ref SSystemInitParams::hWnd void* m_instance = nullptr; //!< maps to \ref SSystemInitParams::hInstance - IOutputPrintSink* m_printSink = nullptr; //!< maps to \ref SSystemInitParams::pPrintSync + IOutputPrintSink* m_printSink = nullptr; //!< maps to \ref SSystemInitParams::pPrintSync }; enum class ReturnCode : unsigned char diff --git a/Code/Legacy/CryCommon/Common_TypeInfo.cpp b/Code/Legacy/CryCommon/Common_TypeInfo.cpp index 6a295c696f..ccb28cbc3d 100644 --- a/Code/Legacy/CryCommon/Common_TypeInfo.cpp +++ b/Code/Legacy/CryCommon/Common_TypeInfo.cpp @@ -7,150 +7,10 @@ */ -#include "TypeInfo_impl.h" #include "Cry_Geo.h" - -STRUCT_INFO_T_BEGIN(Vec2_tpl, class, F) -VAR_INFO(x) -VAR_INFO(y) -STRUCT_INFO_T_END(Vec2_tpl, class, F) - +#include "Cry_Color.h" #include "Cry_Vector3.h" -STRUCT_INFO_T_BEGIN(Vec3_tpl, typename, F) -VAR_INFO(x) -VAR_INFO(y) -VAR_INFO(z) -STRUCT_INFO_T_END(Vec3_tpl, typename, F) - -typedef TFixed TFixedUChar_1_255_0; -STRUCT_INFO_T_INSTANTIATE(Vec3_tpl, TFixedUChar_1_255_0) - -STRUCT_INFO_T_BEGIN(Vec4_tpl, typename, F) -VAR_INFO(x) -VAR_INFO(y) -VAR_INFO(z) -VAR_INFO(w) -STRUCT_INFO_T_END(Vec4_tpl, typename, F) - -STRUCT_INFO_T_INSTANTIATE(Vec4_tpl, short) - -STRUCT_INFO_T_BEGIN(Ang3_tpl, typename, F) -VAR_INFO(x) -VAR_INFO(y) -VAR_INFO(z) -STRUCT_INFO_T_END(Ang3_tpl, typename, F) - -STRUCT_INFO_T_BEGIN(Plane_tpl, typename, F) -VAR_INFO(n) -VAR_INFO(d) -STRUCT_INFO_T_END(Plane_tpl, typename, F) - -//----------------------------------------------------------------- -//#include "Cry_Quat_info.h" -STRUCT_INFO_T_BEGIN(Quat_tpl, typename, F) -VAR_INFO(v) -VAR_INFO(w) -STRUCT_INFO_T_END(Quat_tpl, typename, F) - -STRUCT_INFO_T_INSTANTIATE(Quat_tpl, float) - -STRUCT_INFO_T_BEGIN(QuatT_tpl, typename, F) -VAR_INFO(q) -VAR_INFO(t) -STRUCT_INFO_T_END(QuatT_tpl, typename, F) - -STRUCT_INFO_T_INSTANTIATE(QuatT_tpl, float) - -STRUCT_INFO_T_BEGIN(QuatTS_tpl, typename, F) -VAR_INFO(q) -VAR_INFO(t) -VAR_INFO(s) -STRUCT_INFO_T_END(QuatTS_tpl, typename, F) - -STRUCT_INFO_T_BEGIN(DualQuat_tpl, typename, F) -VAR_INFO(nq) -VAR_INFO(dq) -STRUCT_INFO_T_END(DualQuat_tpl, typename, F) - - -//------------------------------------------------------------ -//#include "Cry_Matrix_info.h" -STRUCT_INFO_T_BEGIN(Matrix33_tpl, typename, F) -VAR_INFO(m00) -VAR_INFO(m01) -VAR_INFO(m02) -VAR_INFO(m10) -VAR_INFO(m11) -VAR_INFO(m12) -VAR_INFO(m20) -VAR_INFO(m21) -VAR_INFO(m22) -STRUCT_INFO_T_END(Matrix33_tpl, typename, F) - -STRUCT_INFO_T_BEGIN(Matrix34_tpl, typename, F) -VAR_INFO(m00) -VAR_INFO(m01) -VAR_INFO(m02) -VAR_INFO(m03) -VAR_INFO(m10) -VAR_INFO(m11) -VAR_INFO(m12) -VAR_INFO(m13) -VAR_INFO(m20) -VAR_INFO(m21) -VAR_INFO(m22) -VAR_INFO(m23) -STRUCT_INFO_T_END(Matrix34_tpl, typename, F) - -STRUCT_INFO_T_INSTANTIATE(Matrix34_tpl, float) - -STRUCT_INFO_T_BEGIN(Matrix44_tpl, typename, F) -VAR_INFO(m00) -VAR_INFO(m01) -VAR_INFO(m02) -VAR_INFO(m03) -VAR_INFO(m10) -VAR_INFO(m11) -VAR_INFO(m12) -VAR_INFO(m13) -VAR_INFO(m20) -VAR_INFO(m21) -VAR_INFO(m22) -VAR_INFO(m23) -VAR_INFO(m30) -VAR_INFO(m31) -VAR_INFO(m32) -VAR_INFO(m33) -STRUCT_INFO_T_END(Matrix44_tpl, typename, F) - - -//#include "Cry_Color_info.h" -STRUCT_INFO_T_BEGIN(Color_tpl, class, T) -VAR_INFO(r) -VAR_INFO(g) -VAR_INFO(b) -VAR_INFO(a) -STRUCT_INFO_T_END(Color_tpl, class, T) - -STRUCT_INFO_T_INSTANTIATE(Color_tpl, unsigned char) - -//#include "Cry_Geo_info.h" -STRUCT_INFO_BEGIN(AABB) -VAR_INFO(min) -VAR_INFO(max) -STRUCT_INFO_END(AABB) - -STRUCT_INFO_BEGIN(RectF) -VAR_INFO(x) -VAR_INFO(y) -VAR_INFO(w) -VAR_INFO(h) -STRUCT_INFO_END(RectF) - -#include "TimeValue_info.h" -#include "CryHalf_info.h" - // Manually instantiate templates as needed here. template struct Vec3_tpl; template struct Vec4_tpl; diff --git a/Code/Legacy/CryCommon/CryArray.h b/Code/Legacy/CryCommon/CryArray.h deleted file mode 100644 index b4878ec25a..0000000000 --- a/Code/Legacy/CryCommon/CryArray.h +++ /dev/null @@ -1,1322 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - -#ifndef CRYINCLUDE_CRYCOMMON_CRYARRAY_H -#define CRYINCLUDE_CRYCOMMON_CRYARRAY_H -#pragma once - -#include -#include - -//--------------------------------------------------------------------------- -// Convenient iteration macros - -#define for_ptr(T, it, b, e) for (T* it = (b), * _e = (e); it != _e; ++it) -#define for_array_ptr(T, it, arr) for_ptr (T, it, (arr).begin(), (arr).end()) -#define for_array(i, arr) for (int i = 0, _e = (arr).size(); i < _e; i++) - -//--------------------------------------------------------------------------- -// Specify semantics for moving objects. -// If raw_movable() is true, objects will be moved with memmove(). -// If false, with the templated move_init() function. -template -bool raw_movable([[maybe_unused]] T const& dest) -{ - return false; -} - -// This container was written before C++11 and move semantics. As a result, it attempts -// to fake move semantics where possible by constructing over top of existing instances. -// This works great, unless the type being operated on has internal pointers to its own -// memory space (for instance a string with SSO, or COW semantics). -template -struct fake_move_helper -{ - static void move(T& dest, T& source) - { - ::new(&dest) T(source); - source.~T(); - } -}; - -// Generic move function: transfer an existing source object to uninitialized dest address. -// Addresses must not overlap (requirement on caller). -// May be specialized for specific types, to provide a more optimal move. -// For types that can be trivially moved (memcpy), do not specialize move_init, rather specialize raw_movable to return true. -template -void move_init(T& dest, T& source) -{ - assert(&dest != &source); - fake_move_helper::move(dest, source); -} - -/*--------------------------------------------------------------------------- -Public classes: - - Array - StaticArray - DynArray - StaticDynArray - -Support classes are placed in namespaces NArray and NAlloc to reduce global name usage. ----------------------------------------------------------------------------*/ - -namespace NArray -{ - // We should never have these defined as macros. - #undef min - #undef max - - // Define our own min/max here, to avoid including entire . - template - inline T min(T a, T b) - { return a < b ? a : b; } - template - inline T max(T a, T b) - { return a > b ? a : b; } - - // Automatic inference of signed from unsigned int type. - template - struct IntTraits - { - typedef T TSigned; - }; - - template<> - struct IntTraits - { - typedef int TSigned; - }; - template<> - struct IntTraits - { - typedef int64 TSigned; - }; -#if !defined(LINUX) && !defined(APPLE) - template<> - struct IntTraits - { - typedef long TSigned; - }; -#endif - - /*--------------------------------------------------------------------------- - // STORAGE prototype for Array. - struct Storage - { - template - struct Store - { - [const] T* begin() [const]; - I size() const; - }; - }; - ---------------------------------------------------------------------------*/ - - //--------------------------------------------------------------------------- - // ArrayStorage: Default STORAGE Array. - // Simply contains a pointer and count to an existing array, - // performs no allocation or deallocation. - - struct ArrayStorage - { - template - struct Store - { - // Construction. - Store() - : m_aElems(0) - , m_nCount(0) - {} - Store(T* elems, I count) - : m_aElems(elems) - , m_nCount(count) - {} - Store(T* start, T* finish) - : m_aElems(start) - , m_nCount(check_cast(finish - start)) - {} - - void set(T* elems, I count) - { - m_aElems = elems; - m_nCount = count; - } - - // Basic storage. - CONST_VAR_FUNCTION(T * begin(), - { return m_aElems; - }) - inline I size() const - { return m_nCount; } - - // Modifiers, alter range in place. - void erase_front(I count = 1) - { - assert(count >= 0 && count <= m_nCount); - m_nCount -= count; - m_aElems += count; - } - - void erase_back(I count = 1) - { - assert(count >= 0 && count <= m_nCount); - m_nCount -= count; - } - - void resize(I count) - { - assert(count >= 0 && count <= m_nCount); - m_nCount = count; - } - - protected: - T* m_aElems; - I m_nCount; - }; - }; - - //--------------------------------------------------------------------------- - // StaticArrayStorage: STORAGE scheme with a statically sized member array. - - template - struct StaticArrayStorage - { - template - struct Store - { - // Basic storage. - CONST_VAR_FUNCTION(T * begin(), - { return m_aElems; - }) - inline static I size() - { return (I)nSIZE; } - - protected: - T m_aElems[nSIZE]; - }; - }; -}; - -//--------------------------------------------------------------------------- -// Array: Non-growing array. -// S serves as base class, and implements storage scheme: begin(), size() - -template< class T, class I = int, class STORE = NArray::ArrayStorage > -struct Array - : STORE::template Store -{ - typedef typename STORE::template Store S; - - // Tedious redundancy. - using S::size; - using S::begin; - - // STL-compatible typedefs. - typedef T value_type; - typedef T* pointer; - typedef const T* const_pointer; - typedef T& reference; - typedef const T& const_reference; - - typedef T* iterator; - typedef const T* const_iterator; - - typedef I size_type; - typedef typename NArray::IntTraits::TSigned - difference_type; - - typedef Array array; - typedef Array const_array; - - // Construction. - Array() - {} - - // Forward single- and double-argument constructors. - template - explicit Array(const In& i) - : S(i) - {} - - template - Array(const In1& i1, const In2& i2) - : S(i1, i2) - {} - - // Accessors. - inline bool empty() const - { return size() == 0; } - inline size_type size_mem() const - { return size() * sizeof(T); } - - CONST_VAR_FUNCTION(T * data(), - { return begin(); - }) - - CONST_VAR_FUNCTION(T * end(), - { return begin() + size(); - }) - - CONST_VAR_FUNCTION(T * rbegin(), - { return begin() + size() - 1; - }) - - CONST_VAR_FUNCTION(T * rend(), - { return begin() - 1; - }) - - CONST_VAR_FUNCTION(T & front(), - { - assert(!empty()); - return *begin(); - }) - - CONST_VAR_FUNCTION(T & back(), - { - assert(!empty()); - return *rbegin(); - }) - - CONST_VAR_FUNCTION(T & at(size_type i), - { - CRY_ASSERT_TRACE(i >= 0 && i < size(), ("Index %lld is out of range (array size is %lld)", (long long int) i, (long long int) size())); - return begin()[i]; - }) - - CONST_VAR_FUNCTION(T & operator [](size_type i), - { - CRY_ASSERT_TRACE(i >= 0 && i < size(), ("Index %lld is out of range (array size is %lld)", (long long int) i, (long long int) size())); - return begin()[i]; - }) - - // Conversion to canonical array type. - operator array() - { return array(begin(), size()); } - operator const_array() const - { - return const_array(begin(), size()); - } - - // Additional conversion via operator() to full or sub array. - array operator ()(size_type i, size_type count) - { - assert(i >= 0 && i + count <= size()); - return array(begin() + i, count); - } - const_array operator ()(size_type i, size_type count) const - { - assert(i >= 0 && i + count <= size()); - return const_array(begin() + i, count); - } - - array operator ()(size_type i = 0) - { return (*this)(i, size() - i); } - const_array operator ()(size_type i = 0) const - { return (*this)(i, size() - i); } - - // Basic element assignment functions. - - // Copy values to existing elements. - void fill(const T& val) - { - for_array_ptr (T, it, *this) - * it = val; - } - - void copy(const_array source) - { - assert(source.size() >= size()); - const T* s = source.begin(); - for_array_ptr (T, it, *this) - * it = *s++; - } - - // Raw element construct/destruct functions. - iterator init() - { - for_array_ptr (T, it, *this) - new(it) T; - return begin(); - } - iterator init(const T& val) - { - for_array_ptr (T, it, *this) - new(it) T(val); - return begin(); - } - iterator init(const_array source) - { - assert(source.size() >= size()); - assert(source.end() <= begin() || source.begin() >= end()); - const_iterator s = source.begin(); - for_array_ptr (T, it, *this) - new(it) T(*s++); - return begin(); - } - - iterator move_init(array source) - { - assert(source.size() >= size()); - iterator s = source.begin(); - if (s != begin()) - { - if (raw_movable(*s)) - { - memmove(begin(), s, size_mem()); - } - else if (s > begin() || source.end() <= begin()) - { - for_array_ptr (T, it, *this) - ::move_init(*it, *s++); - } - else - { - s += size(); - for (iterator it = end(); it > begin(); ) - { - ::move_init(*--it, *--s); - } - } - } - return begin(); - } - - void destroy() - { - // Destroy in reverse order, to complement construction order. - for (iterator it = rbegin(); it > rend(); --it) - { - it->~T(); - } - } -}; - -// Type-inferring constructor. - -template -inline Array ArrayT(T* elems, I count) -{ - return Array(elems, count); -} - -template -inline Array ArrayT(T* start, T* finish) -{ - return Array(start, finish); -} - -// StaticArray -// A superior alternative to static C arrays. -// Provides standard STL-like Array interface, including bounds-checking. -// standard: Type array[256]; -// structured: StaticArray array; - -template -struct StaticArray - : Array< T, I, NArray::StaticArrayStorage > -{ -}; - -//--------------------------------------------------------------------------- -// Specify allocation for dynamic arrays - -namespace NAlloc -{ - // Multi-purpose allocation function prototype - // pMem = 0, nSize != 0: allocate new mem, nSize = actual amount alloced - // pMem != 0, nSize = 0: deallcate mem - // pMem != 0, nSize != 0: nSize = actual amount allocated - typedef void* (* Allocator)(void* pMem, size_t& nSize, size_t nAlign, bool bSlack); - - // - // Allocation utilities - // - - inline size_t realloc_size(size_t nMinSize) - { - // Choose an efficient realloc size, when growing an existing (non-zero) block. - // Find the next power-of-two, minus a bit of presumed system alloc overhead. - static const size_t nMinAlloc = 32; - static const size_t nOverhead = 16; - static const size_t nDoubleLimit = - sizeof(size_t) < 8 ? 1 << 12 // 32-bit system - : 1 << 16; // >= 64-bit system - - nMinSize += nOverhead; - size_t nAlloc = nMinAlloc; - while (nAlloc < nMinSize) - { - nAlloc <<= 1; - } - if (nAlloc > nDoubleLimit) - { - size_t nAlign = NArray::max(nAlloc >> 3, nDoubleLimit); - nAlloc = Align(nMinSize, nAlign); - } - return nAlloc - nOverhead; - } - - template - T* reallocate(A& allocator, T* old_elems, I old_size, I& new_size, size_t alignment = 1, bool allow_slack = false) - { - T* new_elems; - if (new_size) - { - size_t new_bytes = new_size * sizeof(T); - new_elems = (T*) allocator.alloc(0, new_bytes, alignment, allow_slack); - assert(IsAligned(new_elems, alignment)); - assert(new_bytes >= new_size * sizeof(T)); - new_size = check_cast(new_bytes / sizeof(T)); - } - else - { - new_elems = 0; - } - - if (old_elems) - { - Array old_elems_array(old_elems, old_size); - if (new_elems) - { - // Move elements. - ArrayT(new_elems, NArray::min(old_size, new_size)).move_init(old_elems_array); - } - - // Dealloc old. - old_elems_array.destroy(); // call destructors - size_t zero = 0; - allocator.alloc(old_elems, zero, alignment); - } - - return new_elems; - } - - template - inline size_t get_alloc_size(const A& allocator, const void* pMem, size_t nSize, size_t nAlign) - { - non_const(allocator).alloc((void*)pMem, nSize, nAlign); - return nSize; - } - - struct AllocFunction - { - Allocator m_Function; - - void* alloc(void* pMem, size_t& nSize, size_t nAlign, bool bSlack = false) - { - return m_Function(pMem, nSize, nAlign, bSlack); - } - }; - - // Adds prefix bytes to allocation, preserving alignment - template - struct AllocPrefix - : A - { - void* alloc(void* pMem, size_t& nSize, size_t nAlign, bool bSlack = false) - { - // Adjust pointer and size for prefix bytes - nAlign = NArray::max(nAlign, alignof(Prefix)); - size_t nPrefixSize = Align(sizeof(Prefix), nAlign); - - if (pMem) - { - pMem = (char*)pMem - nPrefixSize; - } - if (nSize) - { - nSize = Align(nSize, nSizeAlign); - nSize += nPrefixSize; - } - - pMem = A::alloc(pMem, nSize, nAlign, bSlack); - - if (nSize) - { - nSize -= nPrefixSize; - } - if (pMem) - { - pMem = (char*)pMem + nPrefixSize; - } - return pMem; - } - }; - - // Stores and retrieves allocator function in memory, for compatibility with diverse allocators - template - struct AllocCompatible - { - void* alloc(void* pMem, size_t& nSize, size_t nAlign, bool bSlack = false) - { - nAlign = NArray::max(nAlign, alignof(Allocator)); - if (pMem) - { - // Retrieve original allocation function, for dealloc or size query - AllocPrefix alloc_prefix; - alloc_prefix.m_Function = ((Allocator*)pMem)[-1]; - return alloc_prefix.alloc(pMem, nSize, nAlign, bSlack); - } - else if (nSize) - { - // Allocate new with this module's base_allocator, storing pointer to function - AllocPrefix alloc_prefix; - pMem = alloc_prefix.alloc(pMem, nSize, nAlign, bSlack); - if (pMem) - { - ((Allocator*)pMem)[-1] = &A::alloc; - } - } - return pMem; - } - }; - - //--------------------------------------------------------------------------- - // Allocators for DynArray. - - // Standard CryModule memory allocation, using aligned versions - struct ModuleAlloc - { - static void* alloc(void* pMem, size_t& nSize, size_t nAlign, bool bSlack = false) - { - if (pMem) - { - if (nSize) - { - // Return memory usage, adding presumed alignment padding - if (nAlign > sizeof(size_t)) - { - nSize += nAlign - sizeof(size_t); - } - } - else - { - // Dealloc - CryModuleMemalignFree(pMem); - } - } - else if (nSize) - { - // Alloc - if (bSlack) - { - nSize = realloc_size(nSize); - } - return CryModuleMemalign(nSize, nAlign); - } - return 0; - } - }; - - // Standard allocator for DynArray stores a compatibility pointer in the memory - typedef AllocCompatible StandardAlloc; -}; - -//--------------------------------------------------------------------------- -// Storage schemes for dynamic arrays -namespace NArray -{ - //--------------------------------------------------------------------------- - // SmallDynStorage: STORAGE scheme for DynArray. - // Array is just a single pointer, size and capacity information stored before the array data. - - template - struct SmallDynStorage - { - template - struct Store - : private A - { - struct Header - { - static const I nCAP_BIT = I(1) << (sizeof(I) * 8 - 1); - - ILINE char* data() const - { - assert(IsAligned(this, sizeof(I))); - return (char*)(this + 1); - } - ILINE bool is_null() const - { return m_nSizeCap == 0; } - ILINE I size() const - { return m_nSizeCap & ~nCAP_BIT; } - - I capacity() const - { - I aligned_bytes = static_cast(Align(size() * sizeof(T), sizeof(I))); - if (m_nSizeCap & nCAP_BIT) - { - // Capacity stored in word following data - return *(I*)(data() + aligned_bytes); - } - else - { - // Capacity - size < sizeof(I) - return aligned_bytes / sizeof(T); - } - } - - void set_sizes(I s, I c) - { - // Store size, and assert against overflow. - assert(s <= c); - m_nSizeCap = s; - I aligned_bytes = static_cast(Align(s * sizeof(T), sizeof(I))); - if (c * sizeof(T) >= aligned_bytes + sizeof(I)) - { - // Has extra capacity, more than word-alignment - m_nSizeCap |= nCAP_BIT; - *(I*)(data() + aligned_bytes) = c; - } - assert(size() == s); - assert(capacity() == c); - } - - protected: - I m_nSizeCap; // Store allocation size, with last bit indicating extra capacity. - - public: - - static T* null_header() - { - // m_aElems is never 0, for empty array points to a static empty header. - // Declare a big enough static var to account for alignment. - struct EmptyHeader - { - Header head; - char pad[alignof(T)]; - }; - static EmptyHeader s_EmptyHeader; - - // The actual header pointer can be anywhere in the struct, it's all initialized to 0. - static T* s_EmptyElems = (T*)Align(s_EmptyHeader.pad, alignof(T)); - - return s_EmptyElems; - } - }; - - // Construction. - Store() - { - set_null(); - } - - Store(const A& a) - : A(a) - { - set_null(); - } - - // Basic storage. - CONST_VAR_FUNCTION(T * begin(), - { return m_aElems; - }) - inline I size() const - { return header()->size(); } - inline I capacity() const - { return header()->capacity(); } - size_t get_alloc_size() const - { return is_null() ? 0 : NAlloc::get_alloc_size(allocator(), begin(), capacity() * sizeof(T), alignof(T)); } - - void resize_raw(I new_size, bool allow_slack = false) - { - I new_cap = capacity(); - if (allow_slack ? new_size > new_cap : new_size != new_cap) - { - new_cap = new_size; - m_aElems = NAlloc::reallocate(allocator(), header()->is_null() ? 0 : m_aElems, size(), new_cap, alignof(T), allow_slack); - if (!m_aElems) - { - set_null(); - return; - } - } - header()->set_sizes(new_size, new_cap); - } - - protected: - - T* m_aElems; - - CONST_VAR_FUNCTION(Header * header(), - { - assert(m_aElems); - return ((Header*)m_aElems) - 1; - }) - - void set_null() - { m_aElems = Header::null_header(); } - bool is_null() const - { return header()->is_null(); } - - typedef NAlloc::AllocPrefix AP; - - AP& allocator() - { - static_assert(sizeof(AP) == sizeof(A)); - return *(AP*)this; - } - const AP& allocator() const - { - return *(const AP*)this; - } - }; - }; - - //--------------------------------------------------------------------------- - // StaticDynStorage: STORAGE scheme with a statically sized member array. - - template - struct StaticDynStorage - { - template - struct Store - : ArrayStorage::Store - { - Store() - : ArrayStorage::Store((T*)Align(m_aData, alignof(T)), 0) {} - - static I capacity() - { return (I)nSIZE; } - static size_t get_alloc_size() - { return 0; } - - void resize_raw(I new_size, [[maybe_unused]] bool allow_slack = false) - { - // cannot realloc, just set size - assert(new_size >= 0 && new_size <= capacity()); - this->m_nCount = new_size; - } - - protected: - - char m_aData[nSIZE * sizeof(T) + alignof(T) - 1]; // Storage for elems, deferred construction - }; - }; -}; - -// Legacy base class of DynArray, only used for read-only access -#define DynArrayRef DynArray - -//--------------------------------------------------------------------------- -// DynArray: Extension of Array allowing dynamic allocation. -// S specifies storage scheme, as with Array, but adds resize(), capacity(), ... -// A specifies the actual memory allocation function: alloc() - -// NOTE: This version has been re-based on AZStd::vector for correctness and performance -// The original implementation has been retained as LegacyDynArray below, for the few -// cases where we must retain the old internal behavior -template< class T, class I = int, class STORE = NArray::SmallDynStorage<> > -struct DynArray - : public AZStd::vector -{ - typedef AZStd::vector vector_base; - using value_type = typename vector_base::value_type; - using size_type = I; - using iterator = typename vector_base::iterator; - using const_iterator = typename vector_base::const_iterator; - - using vector_base::begin; - using vector_base::end; - - DynArray() - : vector_base::vector() - { - } - - explicit DynArray(size_type numElements) - : vector_base::vector(numElements) - { - } - - DynArray(size_type numElements, const T& value) - : vector_base::vector(numElements, value) - { - } - - // Ignore any specialized allocators, they all pull from the LegacyAllocator now - // Because we mandate that all DynArrays use the StdLegacyAllocator, matching allocators - // isn't meaningful here, so it's factored out - // Note that the STORE/S& is ignored entirely, because we do not support sharing storage - // between 2 DynArrays anymore. LegacyDynArray can still do that, but this feature is no longer used - template >::value>> - explicit DynArray(const S&) - : vector_base::vector() - { - } - - size_type capacity() const - { - return static_cast(vector_base::capacity()); - } - - size_type size() const - { - return static_cast(vector_base::size()); - } - - size_type available() const - { - return capacity() - size(); - } - - size_type get_alloc_size() const - { - return capacity() * sizeof(T); - } - - // Grow array, return iterator to new raw elems. - iterator grow_raw(size_type count = 1, bool /*allow_slack*/ = true) - { - vector_base::resize(size() + count); - return end() - count; - } - - iterator grow(size_type count) - { - return grow_raw(count); - } - iterator grow(size_type count, const T& val) - { - vector_base::reserve(size() + count); - for (size_type idx = 0; idx < count; ++idx) - { - vector_base::push_back(val); - } - return end() - count; - } - - void shrink() - { - // Realloc memory to exact array size. - vector_base::shrink_to_fit(); - } - - void resize(size_type newSize) - { - vector_base::resize(newSize); - } - - void resize(size_type new_size, const T& val) - { - size_type s = size(); - if (new_size > s) - { - grow(new_size - s, val); - } - else - { - pop_back(s - new_size); - } - } - - void assign(const_iterator first, const_iterator last) - { - vector_base::assign(first, last); - } - - void assign(size_type n, const T& val) - { - clear(); - grow(n, val); - } - - iterator push_back() - { - return grow(1); - } - iterator push_back(const T& val) - { - vector_base::push_back(val); - return vector_base::end() - 1; - } - iterator push_back(const DynArray& other) - { - return insert(end(), other.begin(), other.end()); - } - - iterator insert_raw(iterator pos, size_type count = 1) - { - // Grow array, return iterator to inserted raw elems. - assert(pos >= begin() && pos <= end()); - vector_base::insert(pos, count, T()); - return pos; - } - - iterator insert(iterator it, const T& val) - { - vector_base::insert(it, 1, val); - return it; - } - iterator insert(iterator it, size_type count, const T& val) - { - vector_base::insert(it, count, val); - return it; - } - iterator insert(iterator it, const_iterator start, const_iterator finish) - { - vector_base::insert(it, start, finish); - return it; - } - - iterator insert(size_type pos) - { - return insert_raw(begin() + pos); - } - iterator insert(size_type pos, const T& val) - { - iterator it = insert_raw(begin() + pos); - *it = val; - return it; - } - - void pop_back(size_type count = 1, [[maybe_unused]] bool allow_slack = true) - { - // Destroy erased elems, change size without reallocing. - assert(count >= 0 && count <= size()); - for (size_type idx = 0; idx < count; ++idx) - { - vector_base::pop_back(); - } - } - - iterator erase(iterator pos) - { - return vector_base::erase(pos); - } - - iterator erase(iterator start, iterator finish) - { - AZ_Assert(start >= begin() && finish >= start && finish <= end(), "DynArray: Erasure range out of bounds"); - - // Copy over erased elems, destroy those at end. - iterator it = start, e = end(); - while (finish < e) - { - *it++ = *finish++; - } - pop_back(check_cast(finish - it)); - return it; - } - - iterator erase(size_type pos, size_type count = 1) - { - return erase(begin() + pos, begin() + pos + count); - } - - void clear() - { - vector_base::clear(); - vector_base::shrink_to_fit(); - } -}; - -//--------------------------------------------------------------------------- -// Original Cry DynArray -//--------------------------------------------------------------------------- -template< class T, class I = int, class STORE = NArray::SmallDynStorage<> > -struct LegacyDynArray - : Array< T, I, STORE > -{ - typedef LegacyDynArray self_type; - typedef Array super_type; - typedef typename STORE::template Store S; - - // Tedious redundancy for GCC. - using_type(super_type, size_type); - using_type(super_type, iterator); - using_type(super_type, const_iterator); - using_type(super_type, array); - using_type(super_type, const_array); - - using super_type::size; - using super_type::capacity; - using super_type::begin; - using super_type::end; - using super_type::at; - using super_type::copy; - using super_type::init; - using super_type::destroy; - - // - // Construction. - // - LegacyDynArray() - {} - - LegacyDynArray(size_type count) - { - grow(count); - } - LegacyDynArray(size_type count, const T& val) - { - grow(count, val); - } - -#if !defined(_DISALLOW_INITIALIZER_LISTS) - // Initializer-list - LegacyDynArray(std::initializer_list l) - { - push_back(Array(l.begin(), l.size())); - } -#endif - - // Copying from a generic array type. - LegacyDynArray(const_array a) - { - push_back(a); - } - self_type& operator =(const_array a) - { - if (a.begin() >= begin() && a.end() <= end()) - { - // Assigning from (partial) self; remove undesired elements. - erase((T*)a.end(), end()); - erase(begin(), (T*)a.begin()); - } - else - { - // Assert no overlap. - assert(a.end() <= begin() || a.begin() >= end()); - if (a.size() == size()) - { - // If same size, perform element copy. - copy(a); - } - else - { - // If different sizes, destroy then copy init elements. - pop_back(size()); - push_back(a); - } - } - return *this; - } - - // Copy init/assign. - inline LegacyDynArray(const self_type& a) - { - push_back(a()); - } - inline self_type& operator =(const self_type& a) - { - return *this = a(); - } - - // Init/assign from basic storage type. - inline LegacyDynArray(const S& a) - { - push_back(const_array(a.begin(), a.size())); - } - inline self_type& operator =(const S& a) - { - return *this = const_array(a.begin(), a.size()); - } - - inline ~LegacyDynArray() - { - destroy(); - S::resize_raw(0); - } - - void swap(self_type& a) - { - // Swap storage structures, no element copying - S temp = static_cast(*this); - static_cast(*this) = static_cast(a); - static_cast(a) = temp; - } - - inline size_type available() const - { - return capacity() - size(); - } - - // - // Allocation modifiers. - // - - void reserve(size_type count) - { - if (count > capacity()) - { - I s = size(); - S::resize_raw(count, false); - S::resize_raw(s, true); - } - } - - // Grow array, return iterator to new raw elems. - iterator grow_raw(size_type count = 1, bool allow_slack = true) - { - S::resize_raw(size() + count, allow_slack); - return end() - count; - } - Array append_raw(size_type count = 1, bool allow_slack = true) - { - return Array(grow_raw(count, allow_slack), count); - } - - iterator grow(size_type count) - { - return append_raw(count).init(); - } - iterator grow(size_type count, const T& val) - { - return append_raw(count).init(val); - } - - void shrink() - { - // Realloc memory to exact array size. - S::resize_raw(size()); - } - - void resize(size_type new_size) - { - size_type s = size(); - if (new_size > s) - { - append_raw(new_size - s, false).init(); - } - else - { - pop_back(s - new_size, false); - } - } - void resize(size_type new_size, const T& val) - { - size_type s = size(); - if (new_size > s) - { - append_raw(new_size - s, false).init(val); - } - else - { - pop_back(s - new_size, false); - } - } - - void assign(size_type n, const T& val) - { - resize(n); - fill(val); - } - - void assign(const_iterator start, const_iterator finish) - { - *this = const_array(start, finish); - } - - iterator push_back() - { - return grow(1); - } - iterator push_back(const T& val) - { - return grow(1, val); - } - iterator push_back(const_array a) - { - return append_raw(a.size(), false).init(a); - } - - array insert_raw(iterator pos, size_type count = 1) - { - // Grow array, return iterator to inserted raw elems. - assert(pos >= begin() && pos <= end()); - size_t i = pos - begin(); - append_raw(count); - (*this)(i + count).move_init((*this)(i)); - return (*this)(i, count); - } - - iterator insert(iterator it, const T& val) - { - return insert_raw(it, 1).init(val); - } - iterator insert(iterator it, size_type count, const T& val) - { - return insert_raw(it, count).init(val); - } - iterator insert(iterator it, const_iterator start, const_iterator finish) - { - return insert(it, const_array(start, finish)); - } - iterator insert(iterator it, const_array a) - { - return insert_raw(it, a.size()).init(a); - } - - iterator insert(size_type pos) - { - return insert_raw(&at(pos)).init(); - } - iterator insert(size_type pos, const T& val) - { - return insert_raw(&at(pos)).init(val); - } - iterator insert(size_type pos, const_array a) - { - return insert_raw(&at(pos), a.size()).init(a); - } - - void pop_back(size_type count = 1, bool allow_slack = true) - { - // Destroy erased elems, change size without reallocing. - assert(count >= 0 && count <= size()); - size_type new_size = size() - count; - (*this)(new_size).destroy(); - S::resize_raw(new_size, allow_slack); - } - - iterator erase(iterator start, iterator finish) - { - assert(start >= begin() && finish >= start && finish <= end()); - - // Copy over erased elems, destroy those at end. - iterator it = start, e = end(); - while (finish < e) - { - *it++ = *finish++; - } - pop_back(check_cast(finish - it)); - return it; - } - - iterator erase(iterator it) - { - return erase(it, it + 1); - } - - iterator erase(size_type pos, size_type count = 1) - { - return erase(begin() + pos, begin() + pos + count); - } - - void clear() - { - destroy(); - S::resize_raw(0); - } -}; - -template -struct StaticDynArray - : LegacyDynArray< T, I, NArray::StaticDynStorage > -{ -}; - - - - #include "CryPodArray.h" - - -#endif // CRYINCLUDE_CRYCOMMON_CRYARRAY_H diff --git a/Code/Legacy/CryCommon/CryCommon.cpp b/Code/Legacy/CryCommon/CryCommon.cpp deleted file mode 100644 index e2eb7c78a8..0000000000 --- a/Code/Legacy/CryCommon/CryCommon.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - - -// This contains compiled code that is used by other projects in the solution. -// Because we don't want static DLL dependencies, the CryCommon project is not compiled into a library. -// Instead, this .cpp file is included in every project which needs it. -// But we also include it in the CryCommon project (disabled in the build), -// so that CryCommon can have the same editable settings as other projects. - -// Set this to 1 to get an output of some pre-defined compiler symbols. - -#if 0 - -#ifdef _WIN32 -#pragma message("_WIN32") -#endif -#ifdef _WIN64 -#pragma message("_WIN64") -#endif - -#ifdef _M_IX86 -#pragma message("_M_IX86") -#endif -#ifdef _M_PPC -#pragma message("_M_PPC") -#endif - -#ifdef _DEBUG -#pragma message("_DEBUG") -#endif - -#ifdef _DLL -#pragma message("_DLL") -#endif -#ifdef _USRDLL -#pragma message("_USRDLL") -#endif -#ifdef _MT -#pragma message("_MT") -#endif - -#endif - -#include - -#include "TypeInfo_impl.h" diff --git a/Code/Legacy/CryCommon/CryCustomTypes.h b/Code/Legacy/CryCommon/CryCustomTypes.h deleted file mode 100644 index 58a6bc9306..0000000000 --- a/Code/Legacy/CryCommon/CryCustomTypes.h +++ /dev/null @@ -1,1204 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - -// Description : Derived CTypeInfos for structs, enums, etc. -// Compressed numerical types and associated TypeInfos - - -#ifndef CRYINCLUDE_CRYCOMMON_CRYCUSTOMTYPES_H -#define CRYINCLUDE_CRYCOMMON_CRYCUSTOMTYPES_H -#pragma once - -#include "CryTypeInfo.h" -#include -#include -#include -#include - -#define STATIC_CONST(T, name, val) \ - static inline T name() { static T t = val; return t; } - -#define ARRAY_COUNT(arr) (sizeof(arr) / sizeof *(arr)) -#define ARRAY_VAR(arr) ArrayT(&(arr)[0], (int)ARRAY_COUNT(arr)) - -//--------------------------------------------------------------------------- -// String helper function. - -template -inline bool HasString(const T& val, FToString flags, const void* def_data = 0) -{ - if (flags.SkipDefault) - { - if (val == (def_data ? *(const T*)def_data : T())) - { - return false; - } - } - return true; -} - -float NumToFromString(float val, int digits, bool floating, char buffer[], int buf_size); - -template -AZStd::string NumToString(T val, int min_digits, int max_digits, bool floating) -{ - char buffer[64]; - float f(val); - for (int digits = min_digits; digits < max_digits; digits++) - { - if (T(NumToFromString(f, digits, floating, buffer, 64)) == val) - { - break; - } - } - return buffer; -} - -//--------------------------------------------------------------------------- -// TypeInfo for structs - -struct CStructInfo - : CTypeInfo -{ - CStructInfo(cstr name, size_t size, size_t align, Array vars = Array(), Array templates = Array()); - virtual bool IsType(CTypeInfo const& Info) const; - virtual AZStd::string ToString(const void* data, FToString flags = 0, const void* def_data = 0) const; - virtual bool FromString(void* data, cstr str, FFromString flags = 0) const; - virtual bool ToValue(const void* data, void* value, const CTypeInfo& typeVal) const; - virtual bool FromValue(void* data, const void* value, const CTypeInfo& typeVal) const; - virtual bool ValueEqual(const void* data, const void* def_data) const; - virtual void SwapEndian(void* pData, size_t nCount, bool bWriting) const; - virtual void GetMemoryUsage(ICrySizer* pSizer, void const* data) const; - - virtual const CVarInfo* NextSubVar(const CVarInfo* pPrev, bool bRecurseBase = false) const; - virtual const CVarInfo* FindSubVar(cstr name) const; - - virtual CTypeInfo const* const* NextTemplateType(CTypeInfo const* const* pPrev) const - { - pPrev = pPrev ? pPrev + 1 : TemplateTypes.begin(); - return pPrev < TemplateTypes.end() ? pPrev : 0; - } - -protected: - Array Vars; - AZStd::fixed_string<16> EndianDesc; // Encodes instructions for endian swapping. - bool HasBitfields; - Array TemplateTypes; - - void MakeEndianDesc(); - size_t AddEndianDesc(cstr desc, size_t dim, size_t elem_size); - bool IsCompatibleType(CTypeInfo const& Info) const; -}; - -//--------------------------------------------------------------------------- -// Template TypeInfo for base types, using global To/FromString functions. - -template -struct TTypeInfo - : CTypeInfo -{ - TTypeInfo(cstr name) - : CTypeInfo(name, sizeof(T), alignof(T)) - {} - - virtual bool ToValue(const void* data, void* value, const CTypeInfo& typeVal) const - { - if (&typeVal == this) - { - return *(T*)value = *(const T*)data, true; - } - return false; - } - virtual bool FromValue(void* data, const void* value, const CTypeInfo& typeVal) const - { - if (&typeVal == this) - { - return *(T*)data = *(const T*)value, true; - } - return false; - } - - virtual AZStd::string ToString(const void* data, FToString flags = 0, const void* def_data = 0) const - { - if (!HasString(*(const T*)data, flags, def_data)) - { - return AZStd::string(); - } - return ::ToString(*(const T*)data); - } - virtual bool FromString(void* data, cstr str, FFromString flags = 0) const - { - if (!*str) - { - if (!flags.SkipEmpty) - { - *(T*)data = T(); - } - return true; - } - return ::FromString(*(T*)data, str); - } - virtual bool ValueEqual(const void* data, const void* def_data = 0) const - { - return *(const T*)data == (def_data ? *(const T*)def_data : T()); - } - - virtual void GetMemoryUsage([[maybe_unused]] ICrySizer* pSizer, [[maybe_unused]] void const* data) const - {} -}; - -//--------------------------------------------------------------------------- -// Template TypeInfo for modified types (e.g. compressed, range-limited) - -template -struct TProxyTypeInfo - : CTypeInfo -{ - TProxyTypeInfo(cstr name) - : CTypeInfo(name, sizeof(S), alignof(S)) - {} - - virtual bool IsType(CTypeInfo const& Info) const - { return &Info == this || ValTypeInfo().IsType(Info); } - - virtual bool ToValue(const void* data, void* value, const CTypeInfo& typeVal) const - { - if (&typeVal == this) - { - *(S*)value = *(const S*)data; - return true; - } - T val = T(*(const S*)data); - return ValTypeInfo().ToValue(&val, value, typeVal); - } - virtual bool FromValue(void* data, const void* value, const CTypeInfo& typeVal) const - { - if (&typeVal == this) - { - *(S*)data = *(const S*)value; - return true; - } - T val; - if (ValTypeInfo().FromValue(&val, value, typeVal)) - { - *(S*)data = S(val); - return true; - } - return false; - } - - virtual AZStd::string ToString(const void* data, FToString flags = 0, const void* def_data = 0) const - { - T val = T(*(const S*)data); - T def_val = def_data ? T(*(const S*)def_data) : T(); - return ValTypeInfo().ToString(&val, flags, &def_val); - } - virtual bool FromString(void* data, cstr str, FFromString flags = 0) const - { - T val; - if (!*str) - { - if (!flags.SkipEmpty) - { - *(S*)data = S(); - } - return true; - } - if (!TypeInfo(&val).FromString(&val, str)) - { - return false; - } - *(S*)data = S(val); - return true; - } - - // Forward additional TypeInfo functions. - virtual bool GetLimit(ENumericLimit eLimit, float& fVal) const - { return ValTypeInfo().GetLimit(eLimit, fVal); } - virtual cstr EnumElem(uint nIndex) const - { return ValTypeInfo().EnumElem(nIndex); } - -protected: - - static const CTypeInfo& ValTypeInfo() - { return TypeInfo((T*)0); } -}; - -//--------------------------------------------------------------------------- -// Customisation for string. - -template<> -inline AZStd::string TTypeInfo::ToString(const void* data, FToString flags, const void* def_data) const -{ - const AZStd::string& val = *(const AZStd::string*)data; - if (def_data && flags.SkipDefault) - { - if (val == *(const AZStd::string*)def_data) - { - return AZStd::string(); - } - } - return val; -} - -template<> -inline bool TTypeInfo::FromString(void* data, cstr str, FFromString flags) const -{ - if (!*str && flags.SkipEmpty) - { - return true; - } - *(AZStd::string*)data = str; - return true; -} - -template<> -void TTypeInfo::GetMemoryUsage(ICrySizer* pSizer, void const* data) const; - -//--------------------------------------------------------------------------- -// -// TypeInfo for small integer types. - - -template -struct TIntTraits -{ - static const bool bSIGNED - = T(-1) < T(0); - - static const T nMIN_FACTOR - = bSIGNED ? T(-1) : T(0); - - static const size_t nPOS_BITS - = sizeof(T) * 8 - bSIGNED; - - static const T nMIN = std::numeric_limits::min(); - - static const T nMAX = std::numeric_limits::max(); -}; - -template -struct TIntType -{}; - -template<> -struct TIntType<1> -{ - typedef int8 TType; -}; -template<> -struct TIntType<2> -{ - typedef int16 TType; -}; -template<> -struct TIntType<4> -{ - typedef int32 TType; -}; -template<> -struct TIntType<8> -{ - typedef int64 TType; -}; - -template -inline bool ConvertInt(D& dest, S src) -{ - if constexpr (TIntTraits::nPOS_BITS < TIntTraits::nPOS_BITS) - { - src = clamp_tpl(src, S(TIntTraits::nMIN), S(TIntTraits::nMAX)); - } - else if constexpr (TIntTraits::bSIGNED < TIntTraits::bSIGNED) - { - src = max(src, S(0)); - } - - dest = D(src); - assert(S(dest) == src); - return true; -} - -template -inline bool ConvertInt(D& dest, const void* src, const CTypeInfo& typeSrc) -{ - if (typeSrc.IsType()) - { - switch (typeSrc.Size) - { - case 1: - return ConvertInt(dest, *(const int8*)src); - case 2: - return ConvertInt(dest, *(const int16*)src); - case 4: - return ConvertInt(dest, *(const int32*)src); - case 8: - return ConvertInt(dest, *(const int64*)src); - } - } - else if (typeSrc.IsType()) - { - switch (typeSrc.Size) - { - case 1: - return ConvertInt(dest, *(const uint8*)src); - case 2: - return ConvertInt(dest, *(const uint16*)src); - case 4: - return ConvertInt(dest, *(const uint32*)src); - case 8: - return ConvertInt(dest, *(const uint64*)src); - } - } - return false; -} - -template -inline bool ConvertInt(void* dest, const CTypeInfo& typeDest, S src) -{ - if (typeDest.IsType()) - { - switch (typeDest.Size) - { - case 1: - return ConvertInt(*(int8*)dest, src); - case 2: - return ConvertInt(*(int16*)dest, src); - case 4: - return ConvertInt(*(int32*)dest, src); - case 8: - return ConvertInt(*(int64*)dest, src); - } - } - else if (typeDest.IsType()) - { - switch (typeDest.Size) - { - case 1: - return ConvertInt(*(uint8*)dest, src); - case 2: - return ConvertInt(*(uint16*)dest, src); - case 4: - return ConvertInt(*(uint32*)dest, src); - case 8: - return ConvertInt(*(uint64*)dest, src); - } - } - return false; -} - -template -struct TIntTypeInfo - : TTypeInfo -{ - TIntTypeInfo(cstr name) - : TTypeInfo(name) - {} - - virtual bool IsType(CTypeInfo const& Info) const - { return &Info == this || &Info == (TIntTraits::bSIGNED ? &TypeInfo((int*)0) : &TypeInfo((uint*)0)); } - - virtual bool GetLimit(ENumericLimit eLimit, float& fVal) const - { - if (eLimit == eLimit_Min) - { - return fVal = float(TIntTraits::nMIN), true; - } - if (eLimit == eLimit_Max) - { - return fVal = float(TIntTraits::nMAX), true; - } - if (eLimit == eLimit_Step) - { - return fVal = 1.f, true; - } - return false; - } - - // Override to allow int conversion - virtual bool FromValue(void* data, const void* value, const CTypeInfo& typeVal) const - { return ConvertInt(*(T*)data, value, typeVal); } - virtual bool ToValue(const void* data, void* value, const CTypeInfo& typeVal) const - { return ConvertInt(value, typeVal, *(const T*)data); } -}; - -//--------------------------------------------------------------------------- -// Store any type, such as an enum, in a small int. - -template -struct TRangedType -{ - typedef TRangedType TThis; - - TRangedType(T init = T(nDEFAULT)) - : m_Val(init) - { - CheckRange(m_Val); - } - - operator T() const - { - return m_Val; - } - - CUSTOM_STRUCT_INFO(CCustomInfo) - -protected: - T m_Val; - - static bool HasMin() - { return nMIN > INT_MIN; } - static bool HasMax() - { return nMAX < INT_MAX; } - - static bool CheckRange(T& val) - { - if (HasMin() && val < T(nMIN)) - { - val = T(nMIN); - return false; - } - else if (HasMax() && val > T(nMAX)) - { - val = T(nMAX); - return false; - } - return true; - } - - // Adaptor TypeInfo for specifying limits, and implementing range checking - struct CCustomInfo - : TProxyTypeInfo - { - CCustomInfo() - : TProxyTypeInfo(::TypeInfo((T*) 0).Name) - {} - - virtual bool GetLimit(ENumericLimit eLimit, float& fVal) const - { - if (eLimit == eLimit_Min && HasMin()) - { - return fVal = T(nMIN), true; - } - if (eLimit == eLimit_Max && HasMax()) - { - return fVal = T(nMAX), true; - } - return ::TypeInfo((T*)0).GetLimit(eLimit, fVal); - } - }; -}; - -//--------------------------------------------------------------------------- -// Store any type, such as an enum, in a small int. - -template -struct TSmall -{ - typedef TSmall TThis; - typedef T TValue; - - inline TSmall(T val = T(nDefault)) - { - set(val); - } - void set(T val = T(nDefault)) - { - m_Val = S(val) - S(nOffset); - - // The unary operator+() forces integer promotion to happen and thus - // induces a call to operator T(), which allows the equality operator to work. - assert(+(*this) == val); - } - - inline operator T() const - { return T(T(m_Val) + nOffset); } - inline T operator +() const - { return T(T(m_Val) + nOffset); } - - CUSTOM_STRUCT_INFO(CCustomInfo) - -protected: - S m_Val; - - struct CCustomInfo - : TProxyTypeInfo - { - CCustomInfo() - : TProxyTypeInfo("TSmall<>") - {} - - virtual bool GetLimit(ENumericLimit eLimit, float& fVal) const - { - if (eLimit == eLimit_Min) - { - return fVal = float(TIntTraits::nMIN + nOffset), true; - } - if (eLimit == eLimit_Max) - { - return fVal = float(TIntTraits::nMAX + nOffset), true; - } - if (eLimit == eLimit_Step) - { - return fVal = 1.f, true; - } - return false; - } - }; -}; - -//--------------------------------------------------------------------------- -// Quantise a float linearly in an int. -template::nMAX, bool bTRUNC = false> -struct TFixed -{ - typedef float TValue; - - inline TFixed() - : m_Store(0) - {} - - inline TFixed(float fIn) - { - float fStore = ToStore(fIn); - fStore = clamp_tpl(fStore, float(TIntTraits::nMIN_FACTOR * nQUANT), float(nQUANT)); - m_Store = bTRUNC ? S(fStore) : fStore < 0.f ? S(fStore - 0.5f) : S(fStore + 0.5f); - } - - // Conversion. - inline operator float() const - { return FromStore(m_Store); } - inline float operator +() const - { return FromStore(m_Store); } - inline bool operator !() const - { return !m_Store; } - - inline bool operator ==(const TFixed& x) const - { return m_Store == x.m_Store; } - inline bool operator ==(float x) const - { return m_Store == TFixed(x); } - inline S GetStore() const - { return m_Store; } - - static S GetMaxStore() - { return nQUANT; } - static float GetMaxValue() - { return float(nLIMIT); } - - CUSTOM_STRUCT_INFO(CCustomInfo) - -protected: - S m_Store; - - typedef TFixed TThis; - - static const int nMAX = nLIMIT; - static const int nMIN = TIntTraits::nMIN_FACTOR * nLIMIT; - - static inline float ToStore(float f) - { return f * float(nQUANT) / float(nLIMIT); } - static inline float FromStore(float f) - { return f * float(nLIMIT) / float(nQUANT); } - - // TypeInfo implementation. - struct CCustomInfo - : TProxyTypeInfo - { - CCustomInfo() - : TProxyTypeInfo("TFixed<>") - {} - - virtual bool GetLimit(ENumericLimit eLimit, float& fVal) const - { - if (eLimit == eLimit_Min) - { - return fVal = float(nMIN), true; - } - if (eLimit == eLimit_Max) - { - return fVal = float(nMAX), true; - } - if (eLimit == eLimit_Step) - { - return fVal = FromStore(1.f), true; - } - return false; - } - - // Override ToString: Limit to significant digits. - virtual AZStd::string ToString(const void* data, FToString flags = 0, const void* def_data = 0) const - { - if (!HasString(*(const S*)data, flags, def_data)) - { - return AZStd::string(); - } - static int digits = int_ceil(log10f(float(nQUANT))); - return NumToString(*(const TFixed*)data, 1, digits + 3, true); - } - }; -}; - - -// Define the canonical float-to-byte quantisation. -typedef TFixed UnitFloat8; - -#ifdef COMPRESSED_FLOATS - -//--------------------------------------------------------------------------- -// A floating point number, with templated storage size (and sign), and number of exponent bits -template -struct TFloat -{ - typedef float TValue; - - ILINE TFloat() - : m_Store(0) - {} - - ILINE TFloat(float fIn) - : m_Store(FromFloat(fIn)) - {} - - ILINE operator float() const - { return ToFloat(m_Store); } - ILINE float operator +() const - { return ToFloat(m_Store); } - - ILINE bool operator !() const - { return !m_Store; } - - ILINE bool operator ==(TFloat x) const - { return m_Store == x.m_Store; } - ILINE bool operator ==(float x) const - { return float(*this) == x; } - - inline TFloat& operator *=(float x) - { return *this = *this * x; } - - ILINE uint32 partial_float_conversion() const - { return (0 == m_Store) ? 0 : ToFloatCore(m_Store); } - - STATIC_CONST(float, fMAX, ToFloat(TIntTraits::nMAX)); - STATIC_CONST(float, fPOS_MIN, ToFloat(1 << nMANT_BITS)); - STATIC_CONST(float, fMIN, -fMAX() * (float)TIntTraits::bSIGNED); - - CUSTOM_STRUCT_INFO(CCustomInfo) - -protected: - S m_Store; - - typedef TFloat TThis; - - static const S nBITS = sizeof(S) * 8; - static const S nSIGN = TIntTraits::bSIGNED; - static const S nMANT_BITS = nBITS - nEXP_BITS - nSIGN; - static const S nSIGN_MASK = S(nSIGN << (nBITS - 1)); - static const S nMANT_MASK = (S(1) << nMANT_BITS) - 1; - static const S nEXP_MASK = ~S(nMANT_MASK | nSIGN_MASK); - static const int nEXP_MAX = 1 << (nEXP_BITS - 1), - nEXP_MIN = 1 - nEXP_MAX; - - STATIC_CONST(float, fROUNDER, 1.f + fPOS_MIN() * 0.5f); - - static inline S FromFloat(float fIn) - { - static_assert(sizeof(S) <= 4); - static_assert(nEXP_BITS > 0 && nEXP_BITS <= 8 && nEXP_BITS < sizeof(S) * 8 - 4); - - // Clamp to allowed range. - float fClamped = clamp_tpl(fIn * fROUNDER(), fMIN(), fMAX()); - - // Bit shift to convert from IEEE float32. - uint32 uBits = *(const uint32*)&fClamped; - - // Convert exp. - int32 iExp = (uBits >> 23) & 0xFF; - iExp -= 127 + nEXP_MIN; - IF (iExp < 0, 0) - { - // Underflow. - return 0; - } - - // Reduce mantissa. - uint32 uMant = uBits >> (23 - nMANT_BITS); - - S bits = (uMant & nMANT_MASK) - | (iExp << nMANT_BITS) - | ((uBits >> (32 - nBITS)) & nSIGN_MASK); - - #ifdef _DEBUG - fIn = clamp_tpl(fIn, fMIN(), fMAX()); - float fErr = fabs(ToFloat(bits) - fIn); - float fMaxErr = fabs(fIn) / float(1 << nMANT_BITS); - assert(fErr <= fMaxErr); - #endif - - return bits; - } - - static inline uint32 ToFloatCore(S bits) - { - // Extract FP components. - uint32 uBits = bits & nMANT_MASK, - uExp = (bits & ~nSIGN_MASK) >> nMANT_BITS, - uSign = bits & nSIGN_MASK; - - // Shift to 32-bit. - uBits <<= 23 - nMANT_BITS; - uBits |= (uExp + 127 + nEXP_MIN) << 23; - uBits |= uSign << (32 - nBITS); - - return uBits; - } - - static ILINE float ToFloat(S bits) - { - IF (bits == 0, 0) - { - return 0.f; - } - - uint32 uBits = ToFloatCore(bits); - return *(float*)&uBits; - } - - // TypeInfo implementation. - struct CCustomInfo - : TProxyTypeInfo - { - CCustomInfo() - : TProxyTypeInfo("TFloat<>") - {} - - virtual bool GetLimit(ENumericLimit eLimit, float& fVal) const - { - if (eLimit == eLimit_Min) - { - return fVal = fMIN(), true; - } - if (eLimit == eLimit_Max) - { - return fVal = fMAX(), true; - } - if (eLimit == eLimit_Step) - { - return fVal = fPOS_MIN(), true; - } - return false; - } - - // Override ToString: Limit to significant digits. - virtual string ToString(const void* data, FToString flags = 0, const void* def_data = 0) const - { - if (!HasString(*(const S*)data, flags, def_data)) - { - return string(); - } - static int digits = int_ceil(log10f(1 << nMANT_BITS)); - return NumToString(*(const TFloat*)data, 1, digits + 3, true); - } - }; -}; - -// Canonical float16 types, with range ~= 64K. -typedef TFloat SFloat16; -typedef TFloat UFloat16; - -template -ILINE T partial_float_cast(const SFloat16& s) { return static_cast(s.partial_float_conversion()); } - -template -ILINE T partial_float_cast(const UFloat16& u) { return static_cast(u.partial_float_conversion()); } - -#ifdef _DEBUG - -// Classes for unit tests. -template -void TestValues(T val) -{ - T2 val2 = val; - T2 val2c; - - bool b = TypeInfo(&val2c).FromValue(&val2c, val); - assert(b); - assert(val2 == val2c); - b = TypeInfo(&val2c).ToValue(&val2c, val); - assert(b); - assert(val2 == T2(val)); -} - -template -void TestTypes(T val) -{ - T2 val2 = val; - string s = TypeInfo(&val2).ToString(&val2); - bool b = TypeInfo(&val).FromString(&val, s); - assert(b); - assert(val2 == T2(val)); - - TestValues(val); -} - -template -void TestType(T val) -{ - TestTypes(val); -} - -#endif // _DEBUG - -#endif // COMPRESSED_FLOATS - -//--------------------------------------------------------------------------- -// TypeInfo for enums - -//--------------------------------------------------------------------------- -// Implement data features based on enum definition -/* - interface EnumDef - { - typedef TInt; - uint Count(); - TInt Value(uint i); - cstr Name(uint i); - bool MatchName(uint i, cstr str); - cstr ToName(TInt value); - } const -*/ - -template -struct TEnumInfo - : TIntTypeInfo - , TEnumDef -{ - TEnumInfo(cstr name) - : TIntTypeInfo(name) {} - - virtual cstr EnumElem(uint nIndex) const - { - if (nIndex < TEnumDef::Count()) - { - cstr name = TEnumDef::Name(nIndex); - if (*name != '_') - { - return name; - } - } - return 0; - } - - virtual bool FromValue(void* data, const void* value, const CTypeInfo& typeVal) const - { - TInt val; - if (ConvertInt(val, value, typeVal)) - { - if (TEnumDef::ToName(val)) - { - return *(TInt*)data = val, true; - } - } - return false; - } - - virtual AZStd::string ToString(const void* data, FToString flags, const void* def_data) const - { - TInt val = *(const TInt*)(data); - if (flags.SkipDefault && val == (def_data ? *(const TInt*)def_data : TInt(0))) - { - return AZStd::string(); - } - - if (cstr sName = TEnumDef::ToName(val)) - { - return sName; - } - - // Unmatched value, return as number. - return ::ToString(val); - } - - virtual bool FromString(void* data, cstr str, FFromString flags) const - { - if (!*str) - { - if (!flags.SkipEmpty) - { - *(TInt*)data = (TInt)0; - } - return true; - } - - for (int i = 0, count = TEnumDef::Count(); i < count; i++) - { - if (TEnumDef::MatchName(i, str)) - { - return *(TInt*)data = check_cast(TEnumDef::Value(i)), true; - } - } - - // No match, attempt numeric or bool conversion. - if (::FromString(*(TInt*)data, str)) - { - return true; - } - - bool b; - if (::FromString(b, str)) - { - return *(TInt*)data = b, true; - } - - return false; - } -}; - -//--------------------------------------------------------------------------- -// TypeInfo for regular enums - -struct CSimpleEnumDef -{ - void Init(Array names, char* enum_str); - - // TEnumDef implementations - ILINE uint Count() const - { return asNames.size(); } - ILINE static uint Value(uint i) - { return i; } - ILINE cstr Name(uint i) const - { return asNames[i]; } - ILINE bool MatchName(uint i, cstr str) const - { - cstr name = asNames[i]; - if (*name == '_') - { - name++; - } - return azstricmp(name, str) == 0; - } - ILINE cstr ToName(uint value) const - { - if (value < Count()) - { - return asNames[value]; - } - return 0; - } - -protected: - - Array asNames; -}; - -struct CSimpleEnumInfo - : TEnumInfo -{ - CSimpleEnumInfo(cstr name, Array names, char* enum_str) - : TEnumInfo(name) - { - Init(names, enum_str); - } -}; - -// Define a regular small enum with TypeInfo - -#define DEFINE_ENUM_VALUE(EType, E, TInt) \ - TInt Value; \ - ILINE EType(E val = E(0)) \ - : Value(aznumeric_caster(val)) {} \ - ILINE operator E() const { return E(Value); } \ - ILINE E operator +() const { return E(Value); } \ - -#define DEFINE_ENUM(EType, ...) \ - struct EType \ - { \ - enum E { __VA_ARGS__, _count }; \ - typedef uint8 TInt; \ - DEFINE_ENUM_VALUE(EType, E, TInt) \ - ILINE static uint Count() { return _count; } \ - static const CSimpleEnumInfo& TypeInfo() { \ - static cstr names[_count]; \ - static char enum_str[] = #__VA_ARGS__; \ - static CSimpleEnumInfo info( #EType, Array(&names[0], _count), enum_str); \ - return info; \ - } \ - }; - -//--------------------------------------------------------------------------- -// TypeInfo for irregular enums - -struct CEnumDef -{ - typedef int64 TValue; - - struct SElem - { - TValue Value; - cstr Name; - }; - - void Init(Array elems, char* enum_str = 0); - - // TEnumDef implementations - ILINE uint Count() const - { return Elems.size(); } - ILINE TValue Value(uint i) const - { return Elems[i].Value; } - ILINE cstr Name(uint i) const - { return *Elems[i].Name ? Elems[i].Name + nPrefixLength : ""; } - bool MatchName(uint i, cstr str) const; - cstr ToName(TValue val) const; - - struct SInit - { - static LegacyDynArray* s_pElems; - - static void Init(LegacyDynArray& elems) - { - s_pElems = &elems; - } - SInit() - { - TValue val = s_pElems->empty() ? 0 : s_pElems->back().Value + 1; - s_pElems->push_back()->Value = val; - } - SInit(TValue val) - { - s_pElems->push_back()->Value = val; - } - }; - -protected: - - Array Elems; - TValue MinValue; - bool bRegular; - uint nPrefixLength; -}; - -template -struct CEnumInfo - : TEnumInfo -{ - CEnumInfo(cstr name, Array elems, char* enum_str = 0) - : TEnumInfo(name) - { - CEnumDef::Init(elems, enum_str); - } -}; - -struct CEnumDefUuid - : public TTypeInfo -{ - struct SElem - { - AZ::Uuid Value; - cstr Name; - }; - - CEnumDefUuid(cstr name, Array elems, char* enum_str = 0) - : TTypeInfo(name) - { - CEnumDefUuid::Init(elems, enum_str); - } - void Init(Array elems, char* enum_str = 0); - - // TEnumDef implementations - ILINE uint Count() const - { - return Elems.size(); - } - ILINE AZ::Uuid Value(uint i) const - { - return Elems[i].Value; - } - ILINE cstr Name(uint i) const - { - return *Elems[i].Name ? Elems[i].Name + nPrefixLength : ""; - } - bool MatchName(uint i, cstr str) const; - cstr ToName(AZ::Uuid val) const; - - cstr EnumElem(uint nIndex) const override - { - if (nIndex < Count()) - { - cstr name = Name(nIndex); - if (*name != '_') - { - return name; - } - } - return 0; - } - - bool FromValue(void* data, const void* value, const CTypeInfo& typeVal) const override - { - if (&typeVal == this) - { - const AZ::Uuid& valueUuid = *reinterpret_cast(value); - if (ToName(valueUuid)) - { - AZ::Uuid& dataUuid = *reinterpret_cast(data); - dataUuid = valueUuid; - return true; - } - } - return false; - } - - AZStd::string ToString(const void* data, FToString flags, const void* def_data) const override - { - const AZ::Uuid& uuidData = *reinterpret_cast(data); - const AZ::Uuid& defUuidData = *reinterpret_cast(def_data); - if (flags.SkipDefault && uuidData == (def_data ? defUuidData : AZ::Uuid::CreateNull())) - { - return AZStd::string(); - } - - if (cstr sName = ToName(uuidData)) - { - return sName; - } - - return AZStd::string(); - } - - bool FromString(void* data, cstr str, FFromString flags) const override - { - AZ::Uuid& uuidData = *reinterpret_cast(data); - if (!*str) - { - if (!flags.SkipEmpty) - { - uuidData = AZ::Uuid::CreateNull(); - } - return true; - } - - for (int i = 0, count = Count(); i < count; i++) - { - if (MatchName(i, str)) - { - uuidData = Value(i); - return true; - } - } - - return false; - } - -protected: - - Array Elems; - bool bRegular; - uint nPrefixLength; -}; - -#endif // CRYINCLUDE_CRYCOMMON_CRYCUSTOMTYPES_H diff --git a/Code/Legacy/CryCommon/CryHalf.inl b/Code/Legacy/CryCommon/CryHalf.inl index b0d322f418..a9683540e1 100644 --- a/Code/Legacy/CryCommon/CryHalf.inl +++ b/Code/Legacy/CryCommon/CryHalf.inl @@ -141,7 +141,6 @@ struct CryHalf2 void GetMemoryUsage([[maybe_unused]] ICrySizer* pSizer) const {} - AUTO_STRUCT_INFO }; struct CryHalf4 @@ -197,7 +196,6 @@ struct CryHalf4 void GetMemoryUsage([[maybe_unused]] ICrySizer* pSizer) const {} - AUTO_STRUCT_INFO }; #endif // #ifndef CRY_HALF_INL diff --git a/Code/Legacy/CryCommon/CryHalf_info.h b/Code/Legacy/CryCommon/CryHalf_info.h deleted file mode 100644 index 8e4105f8b2..0000000000 --- a/Code/Legacy/CryCommon/CryHalf_info.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - -#ifndef CRYINCLUDE_CRYCOMMON_CRYHALF_INFO_H -#define CRYINCLUDE_CRYCOMMON_CRYHALF_INFO_H -#pragma once - -#include "CryHalf.inl" - -STRUCT_INFO_BEGIN(CryHalf2) -STRUCT_VAR_INFO(x, TYPE_INFO(CryHalf)) -STRUCT_VAR_INFO(y, TYPE_INFO(CryHalf)) -STRUCT_INFO_END(CryHalf2) - -STRUCT_INFO_BEGIN(CryHalf4) -STRUCT_VAR_INFO(x, TYPE_INFO(CryHalf)) -STRUCT_VAR_INFO(y, TYPE_INFO(CryHalf)) -STRUCT_VAR_INFO(z, TYPE_INFO(CryHalf)) -STRUCT_VAR_INFO(w, TYPE_INFO(CryHalf)) -STRUCT_INFO_END(CryHalf4) - -#endif // CRYINCLUDE_CRYCOMMON_CRYHALF_INFO_H diff --git a/Code/Legacy/CryCommon/CryHeaders.h b/Code/Legacy/CryCommon/CryHeaders.h deleted file mode 100644 index 49ea28ee0e..0000000000 --- a/Code/Legacy/CryCommon/CryHeaders.h +++ /dev/null @@ -1,1506 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - -#ifndef CRYINCLUDE_CRYCOMMON_CRYHEADERS_H -#define CRYINCLUDE_CRYCOMMON_CRYHEADERS_H -#pragma once - - -#include "BaseTypes.h" -#include "Cry_Math.h" - -#ifdef MAX_SUB_MATERIALS -// This checks that the values are in sync in the different files. -static_assert(MAX_SUB_MATERIALS == 128); -#else - #define MAX_SUB_MATERIALS 128 -#endif - -#include "CryEndian.h" - -// Chunk type must fit into uint16 -enum ChunkTypes -{ - ChunkType_ANY = 0, - - ChunkType_Mesh = 0x1000, // was 0xCCCC0000 in chunk files with versions <= 0x745 - ChunkType_Helper, - ChunkType_VertAnim, - ChunkType_BoneAnim, - ChunkType_GeomNameList, // obsolete - ChunkType_BoneNameList, - ChunkType_MtlList, // obsolete - ChunkType_MRM, // obsolete - ChunkType_SceneProps, // obsolete - ChunkType_Light, // obsolete - ChunkType_PatchMesh, // not implemented - ChunkType_Node, - ChunkType_Mtl, // obsolete - ChunkType_Controller, - ChunkType_Timing, - ChunkType_BoneMesh, - ChunkType_BoneLightBinding, // obsolete. describes the lights binded to bones - ChunkType_MeshMorphTarget, // describes a morph target of a mesh chunk - ChunkType_BoneInitialPos, // describes the initial position (4x3 matrix) of each bone; just an array of 4x3 matrices - ChunkType_SourceInfo, // describes the source from which the cgf was exported: source max file, machine and user - ChunkType_MtlName, // material name - ChunkType_ExportFlags, // Special export flags. - ChunkType_DataStream, // Stream data. - ChunkType_MeshSubsets, // Array of mesh subsets. - ChunkType_MeshPhysicsData, // Physicalized mesh data. - - // these are the new compiled chunks for characters - ChunkType_CompiledBones = 0x2000, // was 0xACDC0000 in chunk files with versions <= 0x745 - ChunkType_CompiledPhysicalBones, - ChunkType_CompiledMorphTargets, - ChunkType_CompiledPhysicalProxies, - ChunkType_CompiledIntFaces, - ChunkType_CompiledIntSkinVertices, - ChunkType_CompiledExt2IntMap, - - ChunkType_BreakablePhysics = 0x3000, // was 0xAAFC0000 in chunk files with versions <= 0x745 - ChunkType_FaceMap, // obsolete - ChunkType_MotionParameters, - ChunkType_FootPlantInfo, // obsolete - ChunkType_BonesBoxes, - ChunkType_FoliageInfo, - ChunkType_Timestamp, - ChunkType_GlobalAnimationHeaderCAF, - ChunkType_GlobalAnimationHeaderAIM, - ChunkType_BspTreeData -}; - -enum ECgfStreamType -{ - CGF_STREAM_POSITIONS, - CGF_STREAM_NORMALS, - CGF_STREAM_TEXCOORDS, - CGF_STREAM_COLORS, - CGF_STREAM_COLORS2, - CGF_STREAM_INDICES, - CGF_STREAM_TANGENTS, - CGF_STREAM_DUMMY0_, // used to be CGF_STREAM_SHCOEFFS, dummy is needed to keep existing assets loadable - CGF_STREAM_DUMMY1_, // used to be CGF_STREAM_SHAPEDEFORMATION, dummy is needed to keep existing assets loadable - CGF_STREAM_BONEMAPPING, - CGF_STREAM_FACEMAP, - CGF_STREAM_VERT_MATS, - CGF_STREAM_QTANGENTS, - CGF_STREAM_SKINDATA, - CGF_STREAM_DUMMY2_, // used to be old console specific, dummy is needed to keep existing assets loadable - CGF_STREAM_P3S_C4B_T2S, - CGF_STREAM_NUM_TYPES -}; - -////////////////////////////////////////////////////////////////////////// -enum EPhysicsGeomType -{ - PHYS_GEOM_TYPE_NONE = -1, - PHYS_GEOM_TYPE_DEFAULT = 0x1000 + 0, - PHYS_GEOM_TYPE_NO_COLLIDE = 0x1000 + 1, - PHYS_GEOM_TYPE_OBSTRUCT = 0x1000 + 2, - - PHYS_GEOM_TYPE_DEFAULT_PROXY = 0x1000 + 0x100, // Default physicalization, but only proxy (NoDraw geometry). -}; - -struct CryVertex -{ - Vec3 p; //position - Vec3 n; //normal vector - - AUTO_STRUCT_INFO -}; - -struct CryFace -{ - int v0, v1, v2; //vertex indices - int MatID; //mat ID - - int& operator [] (int i) {return (&v0)[i]; } - int operator [] (int i) const {return (&v0)[i]; } - bool isDegenerate () const {return v0 == v1 || v1 == v2 || v2 == v0; } - - AUTO_STRUCT_INFO -}; - -struct CryUV -{ - float u, v; //texture coordinates - AUTO_STRUCT_INFO -}; - -struct CrySkinVtx -{ - int bVolumetric; - int idx[4]; - float w[4]; - Matrix33 M; - - AUTO_STRUCT_INFO -}; - -////////////////////////////////////////////////////////////////////////// -struct CryLink -{ - int BoneID; - Vec3 offset; - float Blending; - - AUTO_STRUCT_INFO -}; - -struct CryIRGB -{ - unsigned char r, g, b; - AUTO_STRUCT_INFO -}; - -struct NAME_ENTITY -{ - char name[64]; -}; - -struct phys_geometry; - -struct CryBonePhysics -{ - phys_geometry* pPhysGeom; // id of a separate mesh for this bone // MUST not be in File Structures!!! - // additional joint parameters - int flags; - float min[3], max[3]; - float spring_angle[3]; - float spring_tension[3]; - float damping[3]; - float framemtx[3][3]; -}; - -// the compatible between 32- and 64-bits structure -struct CryBonePhysics_Comp -{ - int nPhysGeom; // id of a separate mesh for this bone - // additional joint parameters - int flags; - float min[3], max[3]; - float spring_angle[3]; - float spring_tension[3]; - float damping[3]; - float framemtx[3][3]; - - AUTO_STRUCT_INFO -}; - -#define __copy3(MEMBER) left.MEMBER[0] = right.MEMBER[0]; left.MEMBER[1] = right.MEMBER[1]; left.MEMBER[2] = right.MEMBER[2]; -inline void CopyPhysInfo(CryBonePhysics& left, const CryBonePhysics_Comp& right) -{ - left.pPhysGeom = (phys_geometry*)(INT_PTR)right.nPhysGeom; - left.flags = right.flags; - __copy3(min); - __copy3(max); - __copy3(spring_angle); - __copy3(spring_tension); - __copy3(damping); - __copy3(framemtx[0]); - __copy3(framemtx[1]); - __copy3(framemtx[2]); -} -inline void CopyPhysInfo(CryBonePhysics_Comp& left, const CryBonePhysics& right) -{ - left.nPhysGeom = (int)(INT_PTR)right.pPhysGeom; - left.flags = right.flags; - __copy3(min); - __copy3(max); - __copy3(spring_angle); - __copy3(spring_tension); - __copy3(damping); - __copy3(framemtx[0]); - __copy3(framemtx[1]); - __copy3(framemtx[2]); -} -#undef __copy3 - -struct CryBoneDescData -{ - unsigned int m_nControllerID; // unic id of bone (generated from bone name in the max) - - // [Sergiy] physics info for different lods - // lod 0 is the physics of alive body, lod 1 is the physics of a dead body - CryBonePhysics m_PhysInfo[2]; - float m_fMass; - - Matrix34 m_DefaultW2B; //intitalpose matrix World2Bone - Matrix34 m_DefaultB2W; //intitalpose matrix Bone2World - - enum - { - kBoneNameMaxSize = 256, - }; - char m_arrBoneName[CryBoneDescData::kBoneNameMaxSize]; - - int m_nLimbId; // set by model state class - - // this bone parent is this[m_nOffsetParent], 0 if the bone is root. Normally this is <= 0 - int m_nOffsetParent; - - // The whole hierarchy of bones is kept in one big array that belongs to the ModelState - // Each bone that has children has its own range of bone objects in that array, - // and this points to the beginning of that range and defines the number of bones. - unsigned m_numChildren; - // the beginning of the subarray of children is at this[m_nOffsetChildren] - // this is 0 if there are no children - int m_nOffsetChildren; -}; - -struct CryBoneDescData_Comp -{ - unsigned int m_nControllerID; // unique id of bone (generated from bone name) - - // [Sergiy] physics info for different lods - // lod 0 is the physics of alive body, lod 1 is the physics of a dead body - CryBonePhysics_Comp m_PhysInfo[2]; - float m_fMass; - - Matrix34 m_DefaultW2B; //intitalpose matrix World2Bone - Matrix34 m_DefaultB2W; //intitalpose matrix Bone2World - - char m_arrBoneName[256]; - - int m_nLimbId; // set by model state class - - // this bone parent is this[m_nOffsetParent], 0 if the bone is root. Normally this is <= 0 - int m_nOffsetParent; - - // The whole hierarchy of bones is kept in one big array that belongs to the ModelState - // Each bone that has children has its own range of bone objects in that array, - // and this points to the beginning of that range and defines the number of bones. - unsigned m_numChildren; - // the beginning of the subarray of children is at this[m_nOffsetChildren] - // this is 0 if there are no children - int m_nOffsetChildren; - - AUTO_STRUCT_INFO -}; - -inline void CopyBoneDescData(CryBoneDescData_Comp& left, const CryBoneDescData& right) -{ - left.m_nControllerID = right.m_nControllerID; - - CopyPhysInfo(left.m_PhysInfo[0], right.m_PhysInfo[0]); - CopyPhysInfo(left.m_PhysInfo[1], right.m_PhysInfo[1]); - - left.m_fMass = right.m_fMass; - left.m_DefaultW2B = right.m_DefaultW2B; - left.m_DefaultB2W = right.m_DefaultB2W; - memcpy(left.m_arrBoneName, right.m_arrBoneName, sizeof(left.m_arrBoneName)); - left.m_nLimbId = right.m_nLimbId; - left.m_nOffsetParent = right.m_nOffsetParent; - left.m_numChildren = right.m_numChildren; - left.m_nOffsetChildren = right.m_nOffsetChildren; -} - -struct BONE_ENTITY -{ - int BoneID; - int ParentID; - int nChildren; - - // Id of controller (CRC32 From name of bone). - unsigned int ControllerID; - - char prop[32]; - CryBonePhysics_Comp phys; - - AUTO_STRUCT_INFO -}; - -struct KEY_HEADER -{ - int KeyTime; //in ticks - AUTO_STRUCT_INFO -}; - -struct RANGE_ENTITY -{ - char name[32]; - int start; - int end; - AUTO_STRUCT_INFO -}; - -//======================================== -//Timing Chunk Header -//======================================== -struct TIMING_CHUNK_DESC_0918 -{ - enum - { - VERSION = 0x0918 - }; - - f32 m_SecsPerTick; // seconds/ticks - int32 m_TicksPerFrame; // ticks/Frame - - RANGE_ENTITY global_range; // covers all of the time ranges - int qqqqnSubRanges; - - AUTO_STRUCT_INFO -}; - - -struct SPEED_CHUNK_DESC_2 -{ - enum - { - VERSION = 0x0922 - }; - - float Speed; - float Distance; - float Slope; - uint32 AnimFlags; - f32 MoveDir[3]; - QuatT StartPosition; - AUTO_STRUCT_INFO -}; - - -struct MotionParams905 -{ - uint32 m_nAssetFlags; - uint32 m_nCompression; - - int32 m_nTicksPerFrame; - f32 m_fSecsPerTick; - int32 m_nStart; - int32 m_nEnd; - - f32 m_fMoveSpeed; - f32 m_fTurnSpeed; - f32 m_fAssetTurn; - f32 m_fDistance; - f32 m_fSlope; - - QuatT m_StartLocation; - QuatT m_EndLocation; - - f32 m_LHeelStart, m_LHeelEnd; - f32 m_LToe0Start, m_LToe0End; - f32 m_RHeelStart, m_RHeelEnd; - f32 m_RToe0Start, m_RToe0End; - - MotionParams905() - { - m_nAssetFlags = 0; - m_nCompression = std::numeric_limits::max(); - m_nTicksPerFrame = 0; - m_fSecsPerTick = 0; - m_nStart = 0; - m_nEnd = 0; - - m_fMoveSpeed = -1; - m_fTurnSpeed = -1; - m_fAssetTurn = -1; - m_fDistance = -1; - m_fSlope = -1; - - m_LHeelStart = -1; - m_LHeelEnd = -1; - m_LToe0Start = -1; - m_LToe0End = -1; - m_RHeelStart = -1; - m_RHeelEnd = -1; - m_RToe0Start = -1; - m_RToe0End = -1; - - m_StartLocation.SetIdentity(); - m_EndLocation.SetIdentity(); - } -}; - - -struct CHUNK_MOTION_PARAMETERS -{ - enum - { - VERSION = 0x0925 - }; - - MotionParams905 mp; -}; - - - -struct CHUNK_GAHCAF_INFO -{ - enum - { - VERSION = 0x0971 - }; - enum - { - FILEPATH_SIZE = 256 - }; - - uint32 m_Flags; - char m_FilePath[FILEPATH_SIZE]; - uint32 m_FilePathCRC32; - uint32 m_FilePathDBACRC32; - - f32 m_LHeelStart, m_LHeelEnd; - f32 m_LToe0Start, m_LToe0End; - f32 m_RHeelStart, m_RHeelEnd; - f32 m_RToe0Start, m_RToe0End; - - f32 m_fStartSec; //asset-feature: Start time in seconds. - f32 m_fEndSec; //asset-feature: End time in seconds. - f32 m_fTotalDuration; //asset-feature: asset-feature: total duration in seconds. - uint32 m_nControllers; - - //locator information - QuatT m_StartLocation; - QuatT m_LastLocatorKey; - Vec3 m_vVelocity; //asset-feature: the velocity vector for this asset - f32 m_fDistance; //asset-feature: the absolute distance this objects is moving - f32 m_fSpeed; //asset-feature: speed (meters in second) - f32 m_fSlope; //asset-feature: uphill-downhill measured in degrees - f32 m_fTurnSpeed; //asset-feature: turning speed per second - f32 m_fAssetTurn; //asset-feature: radiant between first and last frame -}; - - - - -struct CHUNK_GAHAIM_INFO -{ - struct VirtualExampleInit2 - { - Vec2 polar; - uint8 i0, i1, i2, i3; - f32 w0, w1, w2, w3; - }; - struct VirtualExample - { - uint8 i0, i1, i2, i3; - int16 v0, v1, v2, v3; - }; - - enum - { - VERSION = 0x0970 - }; - enum - { - XGRID = 17 - }; - enum - { - YGRID = 9 - }; - enum - { - FILEPATH_SIZE = 256 - }; - - uint32 m_Flags; - char m_FilePath[FILEPATH_SIZE]; - uint32 m_FilePathCRC32; - - f32 m_fStartSec; //asset-feature: Start time in seconds. - f32 m_fEndSec; //asset-feature: End time in seconds. - f32 m_fTotalDuration; //asset-feature: asset-feature: total duration in seconds. - - uint32 m_AnimTokenCRC32; - - uint64 m_nExist; - Quat m_MiddleAimPoseRot; - Quat m_MiddleAimPose; - VirtualExample m_PolarGrid[XGRID * YGRID]; - uint32 m_numAimPoses; -}; - - -//======================================== -//Material Chunk Header -//======================================== - -////////////////////////////////////////////////////////////////////////// -#define MTL_NAME_CHUNK_DESC_0800_MAX_SUB_MATERIALS (32) -struct MTL_NAME_CHUNK_DESC_0800 -{ - enum - { - VERSION = 0x0800 - }; - enum EFlags - { - FLAG_MULTI_MATERIAL = 0x0001, // Have sub materials info. - FLAG_SUB_MATERIAL = 0x0002, // This is sub material. - FLAG_SH_COEFFS = 0x0004, // This material should get spherical harmonics coefficients computed. - FLAG_SH_2SIDED = 0x0008, // This material will be used as 2 sided in the sh precomputation - FLAG_SH_AMBIENT = 0x0010, // This material will get an ambient sh term(to not shadow it entirely) - }; - - int nFlags; // see EFlags. - int nFlags2; - char name[128]; //material/shader name - int nPhysicalizeType; - int nSubMaterials; - int nSubMatChunkId[MTL_NAME_CHUNK_DESC_0800_MAX_SUB_MATERIALS]; - int nAdvancedDataChunkId; - float sh_opacity; - int reserve[32]; - - AUTO_STRUCT_INFO -}; - -struct MTL_NAME_CHUNK_DESC_0802 -{ - enum - { - VERSION = 0x0802 - }; - - char name[128]; //material/shader name - int nSubMaterials; - - // Data continues from here. - // 1) if nSubMaterials is 0, this is a single-material: we store physicalization type of the material (int32). - // 2) if nSubMaterials is not 0, this is a multi-material: we store nSubMaterials physicalization types (int32 - // value for each sub-material). After the physicalization types we store chain of ASCIIZ names of sub-materials. - - AUTO_STRUCT_INFO -}; - -//======================================== -//Mesh Chunk Header -//======================================== - -struct MESH_CHUNK_DESC_0745 -{ - // Versions 0x0744 and 0x0745 are *exactly* the same. - // Version number was increased from 0x0744 to 0x0745 just because - // it was the only way to inform *old* (existing) executables that - // NODE_CHUNK_DESC(!) chunk format was changed and cannot be read - // by them (old CLoaderCGF::LoadNodeChunk() didn't check - // NODE_CHUNK_DESC's version number). - enum - { - VERSION = 0x0745 - }; - enum - { - COMPATIBLE_OLD_VERSION = 0x0744 - }; - - enum EFlags1 - { - FLAG1_BONE_INFO = 0x01, - }; - enum EFlags2 - { - FLAG2_HAS_VERTEX_COLOR = 0x01, - FLAG2_HAS_VERTEX_ALPHA = 0x02, - FLAG2_HAS_TOPOLOGY_IDS = 0x04, - }; - unsigned char flags1; - unsigned char flags2; - int nVerts; - int nTVerts; // # of texture vertices (0 or nVerts) - int nFaces; - int VertAnimID; // id of the related vertAnim chunk if present. otherwise it is -1 - - AUTO_STRUCT_INFO -}; - -// Compiled Mesh chunk. -struct MESH_CHUNK_DESC_0801 -{ - // Versions 0x0800 and 0x0801 are *exactly* the same. - // Version number was increased from 0x0800 to 0x0801 just because - // it was the only way to inform *old* (existing) executables that - // NODE_CHUNK_DESC(!) chunk format was changed and cannot be read - // by them (old CLoaderCGF::LoadNodeChunk() didn't check - // NODE_CHUNK_DESC's version number). - enum - { - VERSION = 0x0801 - }; - enum - { - COMPATIBLE_OLD_VERSION = 0x0800 - }; - - enum EFlags - { - MESH_IS_EMPTY = 0x0001, // Empty mesh (no streams are saved) - HAS_TEX_MAPPING_DENSITY = 0x0002, // texMappingDensity contains a valid value - HAS_EXTRA_WEIGHTS = 0x0004, // The weight stream will have weights for influences 5-8 - HAS_FACE_AREA = 0x0008, // geometricMeanFaceArea contains a valid value - }; - - int nFlags; // @see EFlags - int nFlags2; - - // Just for info. - int nVerts; // Number of vertices. - int nIndices; // Number of indices. - int nSubsets; // Number of mesh subsets. - - int nSubsetsChunkId; // Chunk id of subsets. (Must be ChunkType_MeshSubsets) - int nVertAnimID; // id of the related vertAnim chunk if present. otherwise it is -1 - - // ChunkIDs of data streams (Must be ChunkType_DataStream). - int GetStreamChunkID(ECgfStreamType streamType, [[maybe_unused]] int streamIndex) const - { - // Ignore streamIndex since all chunks with version 0x0801 have only one stream per type - return nStreamChunkID[streamType]; - } - int nStreamChunkID[ECgfStreamType::CGF_STREAM_NUM_TYPES]; // Index is one of ECgfStreamType values. - - // Chunk IDs of physical mesh data. (Must be ChunkType_MeshPhysicsData) - int nPhysicsDataChunkId[4]; - - // Bounding box of the mesh. - Vec3 bboxMin; - Vec3 bboxMax; - - float texMappingDensity; - float geometricMeanFaceArea; - int reserved[31]; - AUTO_STRUCT_INFO -}; - -struct MESH_CHUNK_DESC_0802 -{ - // Version 0x0802 adds an additional dimention to the nStreamChunkID array to allow for multiple streams of the same type - enum - { - VERSION = 0x0802 - }; - enum - { - COMPATIBLE_OLD_VERSION = 0x0802 - }; - - enum EFlags - { - MESH_IS_EMPTY = 0x0001, // Empty mesh (no streams are saved) - HAS_TEX_MAPPING_DENSITY = 0x0002, // texMappingDensity contains a valid value - HAS_EXTRA_WEIGHTS = 0x0004, // The weight stream will have weights for influences 5-8 - HAS_FACE_AREA = 0x0008, // geometricMeanFaceArea contains a valid value - }; - - int nFlags; // @see EFlags - int nFlags2; - - // Just for info. - int nVerts; // Number of vertices. - int nIndices; // Number of indices. - int nSubsets; // Number of mesh subsets. - - int nSubsetsChunkId; // Chunk id of subsets. (Must be ChunkType_MeshSubsets) - int nVertAnimID; // id of the related vertAnim chunk if present. otherwise it is -1 - - // ChunkIDs of data streams (Must be ChunkType_DataStream). - int GetStreamChunkID(ECgfStreamType streamType, int streamIndex) const - { - return nStreamChunkID[streamType][streamIndex]; - } - int nStreamChunkID[ECgfStreamType::CGF_STREAM_NUM_TYPES][8]; // [ECgfStreamType value][streamIndex] e.g. [CGF_STREAM_TEXCOORDS][1] to get UV set 1 - - // Chunk IDs of physical mesh data. (Must be ChunkType_MeshPhysicsData) - int nPhysicsDataChunkId[4]; - - // Bounding box of the mesh. - Vec3 bboxMin; - Vec3 bboxMax; - - float texMappingDensity; - float geometricMeanFaceArea; - int reserved[31]; - AUTO_STRUCT_INFO -}; - - -////////////////////////////////////////////////////////////////////////// -// Stream chunk contains data about a mesh data stream (positions, normals, etc...) -////////////////////////////////////////////////////////////////////////// -struct STREAM_DATA_CHUNK_DESC_0800 -{ - enum - { - VERSION = 0x0800 - }; - - enum EFlags { }; // Not implemented. - - int nFlags; - int nStreamType; // Stream type one of ECgfStreamType. - int nCount; // Number of elements. - int nElementSize; // Element Size. - int reserved[2]; - - // Data starts here at the end of the chunk.. - //char streamData[nCount*nElementSize]; - - AUTO_STRUCT_INFO -}; - -struct STREAM_DATA_CHUNK_DESC_0801 -{ - enum - { - VERSION = 0x0801 - }; - - enum EFlags { }; // Not implemented. - - int nFlags; - int nStreamType; // Stream type one of ECgfStreamType. - int nStreamIndex; // To handle multiple streams of the same type - int nCount; // Number of elements. - int nElementSize; // Element Size. - int reserved[2]; - - // Data starts here at the end of the chunk.. - //char streamData[nCount*nElementSize]; - - AUTO_STRUCT_INFO -}; - -////////////////////////////////////////////////////////////////////////// -// Contains array of mesh subsets. -// Each subset holds an info about material id, indices ranges etc... -////////////////////////////////////////////////////////////////////////// -struct MESH_SUBSETS_CHUNK_DESC_0800 -{ - enum - { - VERSION = 0x0800 - }; - - enum EFlags - { - SH_HAS_DECOMPR_MAT = 0x0001, // obsolete - BONEINDICES = 0x0002, - HAS_SUBSET_TEXEL_DENSITY = 0x0004, - }; - - int nFlags; - int nCount; // Number of elements. - int reserved[2]; - - struct MeshSubset - { - int nFirstIndexId; - int nNumIndices; - int nFirstVertId; - int nNumVerts; - int nMatID; // Material sub-object Id. - float fRadius; - Vec3 vCenter; - - AUTO_STRUCT_INFO - }; - - struct MeshBoneIDs - { - uint32 numBoneIDs; - uint16 arrBoneIDs[0x80]; - - AUTO_STRUCT_INFO - }; - - struct MeshSubsetTexelDensity - { - float texelDensity; - - AUTO_STRUCT_INFO - }; - - // Data starts here at the end of the chunk. - //Subset streamData[nCount]; - - MESH_SUBSETS_CHUNK_DESC_0800() - : nFlags(0) - , nCount(0) - { - } - - AUTO_STRUCT_INFO -}; - -////////////////////////////////////////////////////////////////////////// -// Contain array of mesh subsets. -// Each subset holds an info about material id, indices ranges etc... -////////////////////////////////////////////////////////////////////////// -struct MESH_PHYSICS_DATA_CHUNK_DESC_0800 -{ - enum - { - VERSION = 0x0800 - }; - - int nDataSize; // Size of physical data at the end of the chunk. - int nFlags; - int nTetrahedraDataSize; - int nTetrahedraChunkId; // Chunk of physics Tetrahedra data. - int reserved[2]; - - // Data starts here at the end of the chunk. - //char physicsData[nDataSize]; - //char tetrahedraData[nTetrahedraDataSize]; - - AUTO_STRUCT_INFO -}; - - -struct VERTANIM_CHUNK_DESC_0744 -{ - enum - { - VERSION = 0x0744 - }; - - int GeomID; // ID of the related mesh chunk - int nKeys; // # of keys - int nVerts; // # of vertices this object has - int nFaces; // # of faces this object has (for double check purpose) - - AUTO_STRUCT_INFO -}; - -typedef VERTANIM_CHUNK_DESC_0744 VERTANIM_CHUNK_DESC; -#define VERTANIM_CHUNK_DESC_VERSION VERTANIM_CHUNK_DESC_0744::VERSION - -//======================================== -//Bone Anim Chunk Header -//======================================== - -struct BONEANIM_CHUNK_DESC_0290 -{ - enum - { - VERSION = 0x0290 - }; - - int nBones; - - AUTO_STRUCT_INFO -}; - -//======================================== -//Bonelist Chunk Header -//======================================== - -// this structure describes the bone names -// it's followed by numEntities packed \0-terminated strings, the list terminated by double-\0 -struct BONENAMELIST_CHUNK_DESC_0745 -{ - enum - { - VERSION = 0x0745 - }; - - int numEntities; - AUTO_STRUCT_INFO -}; - - -struct COMPILED_BONE_CHUNK_DESC_0800 -{ - enum - { - VERSION = 0x0800 - }; - - char reserved[32]; - AUTO_STRUCT_INFO -}; - -struct COMPILED_PHYSICALBONE_CHUNK_DESC_0800 -{ - enum - { - VERSION = 0x0800 - }; - - char reserved[32]; - AUTO_STRUCT_INFO -}; - -struct COMPILED_PHYSICALPROXY_CHUNK_DESC_0800 -{ - enum - { - VERSION = 0x0800 - }; - - uint32 numPhysicalProxies; - AUTO_STRUCT_INFO -}; - -struct COMPILED_MORPHTARGETS_CHUNK_DESC_0800 -{ - enum - { - VERSION = 0x0800, VERSION1 = 0x801 - }; - - uint32 numMorphTargets; - AUTO_STRUCT_INFO -}; - - -struct COMPILED_INTFACES_CHUNK_DESC_0800 -{ - enum - { - VERSION = 0x0800 - }; - - AUTO_STRUCT_INFO -}; - -struct COMPILED_INTSKINVERTICES_CHUNK_DESC_0800 -{ - enum - { - VERSION = 0x0800 - }; - - char reserved[32]; - AUTO_STRUCT_INFO -}; - -struct COMPILED_EXT2INTMAP_CHUNK_DESC_0800 -{ - enum - { - VERSION = 0x0800 - }; - - AUTO_STRUCT_INFO -}; - -struct COMPILED_BONEBOXES_CHUNK_DESC_0800 -{ - enum - { - VERSION = 0x0800, VERSION1 = 0x801 - }; - - AUTO_STRUCT_INFO -}; - -// Keyframe and Timing Primitives __________________________________________________________________________________________________________________ -struct BaseKey -{ - int time; - AUTO_STRUCT_INFO -}; - -struct BaseTCB -{ - float t, c, b; - float ein, eout; - AUTO_STRUCT_INFO -}; - -struct BaseKey1 - : BaseKey -{ - float val; - AUTO_STRUCT_INFO -}; -struct BaseKey3 - : BaseKey -{ - Vec3 val; - AUTO_STRUCT_INFO -}; -struct BaseKeyQ - : BaseKey -{ - CryQuat val; - AUTO_STRUCT_INFO -}; - -struct CryLin1Key - : BaseKey1 -{ - AUTO_STRUCT_INFO -}; -struct CryLin3Key - : BaseKey3 -{ - AUTO_STRUCT_INFO -}; -struct CryLinQKey - : BaseKeyQ -{ - AUTO_STRUCT_INFO -}; -struct CryTCB1Key - : BaseKey1 - , BaseTCB -{ - AUTO_STRUCT_INFO -}; -struct CryTCB3Key - : BaseKey3 - , BaseTCB -{ - AUTO_STRUCT_INFO -}; -struct CryTCBQKey - : BaseKeyQ - , BaseTCB -{ - AUTO_STRUCT_INFO -}; -struct CryBez1Key - : BaseKey1 -{ - float intan, outtan; - AUTO_STRUCT_INFO -}; -struct CryBez3Key - : BaseKey3 -{ - Vec3 intan, outtan; - AUTO_STRUCT_INFO -}; -struct CryBezQKey - : BaseKeyQ -{ - AUTO_STRUCT_INFO -}; - -struct CryKeyPQLog -{ - int nTime; - Vec3 vPos; - Vec3 vRotLog; // logarithm of the rotation - - // resets to initial position/rotation/time - void reset () - { - nTime = 0; - vPos.x = vPos.y = vPos.z = 0; - vRotLog.x = vRotLog.y = vRotLog.z = 0; - } - - AUTO_STRUCT_INFO -}; - -//======================================== -//Controller Chunk Header -//======================================== -enum CtrlTypes -{ - CTRL_NONE, - CTRL_CRYBONE, - CTRL_LINEER1, CTRL_LINEER3, CTRL_LINEERQ, - CTRL_BEZIER1, CTRL_BEZIER3, CTRL_BEZIERQ, - CTRL_TCB1, CTRL_TCB3, CTRL_TCBQ, - CTRL_BSPLINE_2O, // 2-byte fixed values, open - CTRL_BSPLINE_1O, // 1-byte fixed values, open - CTRL_BSPLINE_2C, // 2-byte fixed values, closed - CTRL_BSPLINE_1C, // 1-byte fixed values, closed - CTRL_CONST // constant position&rotation -}; - -enum CtrlFlags -{ - CTRL_ORT_CYCLE = 0x01, - CTRL_ORT_LOOP = 0x02 -}; - -// Used to store TCB-controllers in .anm files -struct CONTROLLER_CHUNK_DESC_0826 -{ - enum - { - VERSION = 0x0826 - }; - - CtrlTypes type; //one ot the CtrlTypes values - int nKeys; // # of keys this controller has; toatl # of knots (positional and orientational) in the case of B-Spline - - //unsigned short nSubCtrl; // # of sub controllers; not used now/reserved - unsigned int nFlags; // Flags of controller. - //int nSubCtrl; // # of sub controllers; not used now/reserved - - unsigned nControllerId; // unique generated in exporter id based on crc32 of bone name - - AUTO_STRUCT_INFO -}; - -// Format used to store uncompressed sampled animation exported from DCC into .i_caf files (earlier .caf) -struct CONTROLLER_CHUNK_DESC_0827 -{ - enum - { - VERSION = 0x0827 - }; - unsigned numKeys; - unsigned nControllerId; - - AUTO_STRUCT_INFO -}; - -// Unused format (was it introduced to fix missing header in 827?) -struct CONTROLLER_CHUNK_DESC_0828 -{ - enum - { - VERSION = 0x0828 - }; -}; - -struct CONTROLLER_CHUNK_DESC_0829 -{ - enum - { - VERSION = 0x0829 - }; - - enum - { - eKeyTimeRotation = 0, eKeyTimePosition = 1, eKeyTimeScale = 2 - }; - - unsigned int nControllerId; - - uint16 numRotationKeys; - uint16 numPositionKeys; - uint8 RotationFormat; - uint8 RotationTimeFormat; - uint8 PositionFormat; - uint8 PositionKeysInfo; - uint8 PositionTimeFormat; - uint8 TracksAligned; - - AUTO_STRUCT_INFO -}; - -// Added new controller flags field, correspond to v827 and v829 respectively -struct CONTROLLER_CHUNK_DESC_0830 -{ - enum - { - VERSION = 0x830 - }; - - CONTROLLER_CHUNK_DESC_0830(){} - - CONTROLLER_CHUNK_DESC_0830(const CONTROLLER_CHUNK_DESC_0827* oldChunk) - : numKeys(oldChunk->numKeys) - , nControllerId(oldChunk->nControllerId) - , nFlags(0) - {} - - unsigned numKeys; - unsigned nControllerId; - unsigned nFlags; - - AUTO_STRUCT_INFO -}; - -struct CONTROLLER_CHUNK_DESC_0831 -{ - enum - { - VERSION = 0x831 - }; - - CONTROLLER_CHUNK_DESC_0831(){} - - CONTROLLER_CHUNK_DESC_0831(const CONTROLLER_CHUNK_DESC_0829* oldChunk) - : nControllerId(oldChunk->nControllerId) - , nFlags(0) - , numPositionKeys(oldChunk->numPositionKeys) - , numRotationKeys(oldChunk->numRotationKeys) - , RotationFormat(oldChunk->RotationFormat) - , RotationTimeFormat(oldChunk->RotationTimeFormat) - , PositionFormat(oldChunk->PositionFormat) - , PositionKeysInfo(oldChunk->PositionKeysInfo) - , PositionTimeFormat(oldChunk->PositionTimeFormat) - , TracksAligned(oldChunk->TracksAligned) - {} - - enum - { - eKeyTimeRotation = 0, eKeyTimePosition = 1, eKeyTimeScale = 2 - }; - - unsigned int nControllerId; - unsigned int nFlags; - - uint16 numRotationKeys; - uint16 numPositionKeys; - uint8 RotationFormat; - uint8 RotationTimeFormat; - uint8 PositionFormat; - uint8 PositionKeysInfo; - uint8 PositionTimeFormat; - uint8 TracksAligned; - - AUTO_STRUCT_INFO -}; - -struct CONTROLLER_CHUNK_DESC_0905 -{ - enum - { - VERSION = 0x0905 - }; - - uint32 numKeyPos; - uint32 numKeyRot; - uint32 numKeyTime; - uint32 numAnims; - AUTO_STRUCT_INFO -}; - -//======================================== -//Node Chunk Header -//======================================== -struct NODE_CHUNK_DESC_0824 -{ - // Versions 0x0823 and 0x0824 have exactly same layout. - // The only difference between 0x0823 and 0x0824 is that some members - // are now named _obsoleteXXX_ and are not filled/used in 0x0824. - enum - { - VERSION = 0x0824 - }; - enum - { - COMPATIBLE_OLD_VERSION = 0x0823 - }; - - char name[64]; - - int ObjectID; // ID of this node's object chunk (if present) - int ParentID; // chunk ID of the parent Node's chunk - int nChildren; // # of children Nodes - int MatID; // Material chunk No - - uint8 _obsoleteA_[4]; // uint8 IsGroupHead; uint8 IsGroupMember; uint8 _padding_[2]. not used anymore. - - float tm[4][4]; // transformation matrix - - float _obsoleteB_[3]; // position component of the matrix, stored as Vec3. not used anymore. - float _obsoleteC_[4]; // rotation component of the matrix, stored as CryQuat. not used anymore. - float _obsoleteD_[3]; // scale component of the matrix, stored as Vec3. not used anymore. - - int pos_cont_id; // position controller chunk id - int rot_cont_id; // rotation controller chunk id - int scl_cont_id; // scale controller chunk id - - int PropStrLen; // length of the property string - - AUTO_STRUCT_INFO -}; - -//======================================== -//Helper Chunk Header -//======================================== -enum HelperTypes -{ - HP_POINT = 0, - HP_DUMMY = 1, - HP_XREF = 2, - HP_CAMERA = 3, - HP_GEOMETRY = 4 -}; - -struct HELPER_CHUNK_DESC_0744 -{ - enum - { - VERSION = 0x0744 - }; - - HelperTypes type; // one of the HelperTypes values - Vec3 size; // size in local x,y,z axises (for dummy only) - - AUTO_STRUCT_INFO -}; - -typedef HELPER_CHUNK_DESC_0744 HELPER_CHUNK_DESC; -#define HELPER_CHUNK_DESC_VERSION HELPER_CHUNK_DESC::VERSION - - -// ChunkType_MeshMorphTarget - morph target of a mesh chunk -// This chunk contains only the information about the vertices that are changed in the mesh -// This chunk is followed by an array of numMorphVertices structures SMeshMorphTargetVertex, -// immediately followed by the name (null-terminated, variable-length string) of the morph target. -// The string is after the array because of future alignment considerations; it may be padded with 0s. -struct MESHMORPHTARGET_CHUNK_DESC_0001 -{ - enum - { - VERSION = 0x0001 - }; - uint32 nChunkIdMesh; // the chunk id of the mesh chunk (ChunkType_Mesh) for which this morph target is - uint32 numMorphVertices; // number of MORPHED vertices - - AUTO_STRUCT_INFO -}; - - -// an array of these structures follows the MESHMORPHTARGET_CHUNK_DESC_0001 -// there are numMorphVertices of them -struct SMeshMorphTargetVertex -{ - uint32 nVertexId; // vertex index in the original (mesh) array of vertices - Vec3 ptVertex; // the target point of the morph target - void GetMemoryUsage([[maybe_unused]] ICrySizer* pSizer) const{} - AUTO_STRUCT_INFO -}; - -struct SMeshMorphTargetHeader -{ - uint32 MeshID; - uint32 NameLength; //size of the name string - uint32 numIntVertices; //type SMeshMorphTargetVertex - uint32 numExtVertices; //type SMeshMorphTargetVertex - - AUTO_STRUCT_INFO -}; - -struct SMeshPhysicalProxyHeader -{ - uint32 ChunkID; - uint32 numPoints; - uint32 numIndices; - uint32 numMaterials; - - AUTO_STRUCT_INFO -}; - -// -// ChunkType_BoneInitialPos - describes the initial position (4x3 matrix) of each bone; just an array of 4x3 matrices -// This structure is followed by -struct BONEINITIALPOS_CHUNK_DESC_0001 -{ - enum - { - VERSION = 0x0001 - }; - // the chunk id of the mesh chunk (ChunkType_Mesh) with bone info for which these bone initial positions are applicable. - // there might be some unused bones here as well. There must be the same number of bones as in the other chunks - they're placed - // in BoneId order. - unsigned nChunkIdMesh; - // this is the number of bone initial pose matrices here - unsigned numBones; - - AUTO_STRUCT_INFO -}; - -// an array of these matrices follows the BONEINITIALPOS_CHUNK_DESC_0001 header -// there are numBones of them -// TO BE REPLACED WITH Matrix43 -struct SBoneInitPosMatrix -{ - float mx[4][3]; - float* operator [] (int i) {return mx[i]; } - const float* operator [] (int i) const {return mx[i]; } - const Vec3& getOrt (int nOrt) const {return *(const Vec3*)(mx[nOrt]); } - - AUTO_STRUCT_INFO -}; - -////////////////////////////////////////////////////////////////////////// -// Custom Attributes chunk description. -////////////////////////////////////////////////////////////////////////// -struct EXPORT_FLAGS_CHUNK_DESC -{ - enum - { - VERSION = 0x0001 - }; - enum EFlags - { - MERGE_ALL_NODES = 0x0001, - HAVE_AUTO_LODS = 0x0002, - USE_CUSTOM_NORMALS = 0x0004, - WANT_F32_VERTICES = 0x0008, - EIGHT_WEIGHTS_PER_VERTEX = 0x0010, - //START: Prevent reprocessing skinning data for skinned CGF - SKINNED_CGF = 0x0020, - //END: Prevent reprocessing skinning data for skinned CGF - }; - enum ESrcFlags - { - FROM_MAX_EXPORTER = 0x0000, - FROM_COLLADA_XSI = 0x1001, - FROM_COLLADA_MAX = 0x1002, - FROM_COLLADA_MAYA = 0x1003, - }; - - unsigned int flags; // @see EFlags - unsigned int rc_version[4]; // Resource compiler version. - char rc_version_string[16]; // Version as a string. - unsigned int assetAuthorTool; - unsigned int authorToolVersion; - unsigned int reserved[30]; - - AUTO_STRUCT_INFO -}; - -struct BREAKABLE_PHYSICS_CHUNK_DESC -{ - enum - { - VERSION = 0x0001 - }; - - unsigned int granularity; - int nMode; - int nRetVtx; - int nRetTets; - int nReserved[10]; - - AUTO_STRUCT_INFO -}; - -struct FOLIAGE_INFO_CHUNK_DESC -{ - enum - { - //START: Add Skinned Geometry (.CGF) export type (for touch bending vegetation) - VERSION = 0x0001, - VERSION2 = 0x0002 - //END: Add Skinned Geometry (.CGF) export type (for touch bending vegetation) - }; - - int nSpines; - int nSpineVtx; - int nSkinnedVtx; - int nBoneIds; - - AUTO_STRUCT_INFO -}; - -struct FOLIAGE_SPINE_SUB_CHUNK -{ - unsigned char nVtx; - char _paddingA_[3]; - float len; - Vec3 navg; - unsigned char iAttachSpine; - unsigned char iAttachSeg; - char _paddingB_[2]; - - AUTO_STRUCT_INFO -}; - -#endif // CRYINCLUDE_CRYCOMMON_CRYHEADERS_H diff --git a/Code/Legacy/CryCommon/CryHeaders_info.cpp b/Code/Legacy/CryCommon/CryHeaders_info.cpp deleted file mode 100644 index 3487055013..0000000000 --- a/Code/Legacy/CryCommon/CryHeaders_info.cpp +++ /dev/null @@ -1,486 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - -#include "TypeInfo_impl.h" -#include "CryHeaders.h" - -STRUCT_INFO_BEGIN(CryVertex) -STRUCT_VAR_INFO(p, TYPE_INFO(Vec3)) -STRUCT_VAR_INFO(n, TYPE_INFO(Vec3)) -STRUCT_INFO_END(CryVertex) - -STRUCT_INFO_BEGIN(CryFace) -STRUCT_VAR_INFO(v0, TYPE_INFO(int)) -STRUCT_VAR_INFO(v1, TYPE_INFO(int)) -STRUCT_VAR_INFO(v2, TYPE_INFO(int)) -STRUCT_VAR_INFO(MatID, TYPE_INFO(int)) -STRUCT_INFO_END(CryFace) - -STRUCT_INFO_BEGIN(CryUV) -STRUCT_VAR_INFO(u, TYPE_INFO(float)) -STRUCT_VAR_INFO(v, TYPE_INFO(float)) -STRUCT_INFO_END(CryUV) - -STRUCT_INFO_BEGIN(CrySkinVtx) -STRUCT_VAR_INFO(bVolumetric, TYPE_INFO(int)) -STRUCT_VAR_INFO(idx, TYPE_INFO_ARRAY(4, TYPE_INFO(int))) -STRUCT_VAR_INFO(w, TYPE_INFO_ARRAY(4, TYPE_INFO(float))) -STRUCT_VAR_INFO(M, TYPE_INFO(Matrix33)) -STRUCT_INFO_END(CrySkinVtx) - -STRUCT_INFO_BEGIN(CryLink) -STRUCT_VAR_INFO(BoneID, TYPE_INFO(int)) -STRUCT_VAR_INFO(offset, TYPE_INFO(Vec3)) -STRUCT_VAR_INFO(Blending, TYPE_INFO(float)) -STRUCT_INFO_END(CryLink) - -STRUCT_INFO_BEGIN(CryIRGB) -STRUCT_VAR_INFO(r, TYPE_INFO(unsigned char)) -STRUCT_VAR_INFO(g, TYPE_INFO(unsigned char)) -STRUCT_VAR_INFO(b, TYPE_INFO(unsigned char)) -STRUCT_INFO_END(CryIRGB) - -STRUCT_INFO_BEGIN(CryBonePhysics_Comp) -STRUCT_VAR_INFO(nPhysGeom, TYPE_INFO(int)) -STRUCT_VAR_INFO(flags, TYPE_INFO(int)) -STRUCT_VAR_INFO(min, TYPE_ARRAY(3, TYPE_INFO(float))) -STRUCT_VAR_INFO(max, TYPE_ARRAY(3, TYPE_INFO(float))) -STRUCT_VAR_INFO(spring_angle, TYPE_ARRAY(3, TYPE_INFO(float))) -STRUCT_VAR_INFO(spring_tension, TYPE_ARRAY(3, TYPE_INFO(float))) -STRUCT_VAR_INFO(damping, TYPE_ARRAY(3, TYPE_INFO(float))) -STRUCT_VAR_INFO(framemtx, TYPE_ARRAY(3, TYPE_ARRAY(3, TYPE_INFO(float)))) -STRUCT_INFO_END(CryBonePhysics_Comp) - -STRUCT_INFO_BEGIN(CryBoneDescData_Comp) -STRUCT_VAR_INFO(m_nControllerID, TYPE_INFO(unsigned int)) -STRUCT_VAR_INFO(m_PhysInfo, TYPE_ARRAY(2, TYPE_INFO(BONE_PHYSICS_COMP))) -STRUCT_VAR_INFO(m_fMass, TYPE_INFO(float)) -STRUCT_VAR_INFO(m_DefaultW2B, TYPE_INFO(Matrix34)) -STRUCT_VAR_INFO(m_DefaultB2W, TYPE_INFO(Matrix34)) -STRUCT_VAR_INFO(m_arrBoneName, TYPE_ARRAY(256, TYPE_INFO(char))) -STRUCT_VAR_INFO(m_nLimbId, TYPE_INFO(int)) -STRUCT_VAR_INFO(m_nOffsetParent, TYPE_INFO(int)) -STRUCT_VAR_INFO(m_numChildren, TYPE_INFO(unsigned int)) -STRUCT_VAR_INFO(m_nOffsetChildren, TYPE_INFO(int)) -STRUCT_INFO_END(CryBoneDescData_Comp) - -STRUCT_INFO_BEGIN(BONE_ENTITY) -STRUCT_VAR_INFO(BoneID, TYPE_INFO(int)) -STRUCT_VAR_INFO(ParentID, TYPE_INFO(int)) -STRUCT_VAR_INFO(nChildren, TYPE_INFO(int)) -STRUCT_VAR_INFO(ControllerID, TYPE_INFO(unsigned int)) -STRUCT_VAR_INFO(prop, TYPE_ARRAY(32, TYPE_INFO(char))) -STRUCT_VAR_INFO(phys, TYPE_INFO(BONE_PHYSICS_COMP)) -STRUCT_INFO_END(BONE_ENTITY) - -ENUM_INFO_BEGIN(ChunkTypes) -ENUM_ELEM_INFO(, ChunkType_ANY) -ENUM_ELEM_INFO(, ChunkType_Mesh) -ENUM_ELEM_INFO(, ChunkType_Helper) -ENUM_ELEM_INFO(, ChunkType_VertAnim) -ENUM_ELEM_INFO(, ChunkType_BoneAnim) -ENUM_ELEM_INFO(, ChunkType_GeomNameList) -ENUM_ELEM_INFO(, ChunkType_BoneNameList) -ENUM_ELEM_INFO(, ChunkType_MtlList) -ENUM_ELEM_INFO(, ChunkType_MRM) -ENUM_ELEM_INFO(, ChunkType_SceneProps) -ENUM_ELEM_INFO(, ChunkType_Light) -ENUM_ELEM_INFO(, ChunkType_PatchMesh) -ENUM_ELEM_INFO(, ChunkType_Node) -ENUM_ELEM_INFO(, ChunkType_Mtl) -ENUM_ELEM_INFO(, ChunkType_Controller) -ENUM_ELEM_INFO(, ChunkType_Timing) -ENUM_ELEM_INFO(, ChunkType_BoneMesh) -ENUM_ELEM_INFO(, ChunkType_BoneLightBinding) -ENUM_ELEM_INFO(, ChunkType_MeshMorphTarget) -ENUM_ELEM_INFO(, ChunkType_BoneInitialPos) -ENUM_ELEM_INFO(, ChunkType_SourceInfo) -ENUM_ELEM_INFO(, ChunkType_MtlName) -ENUM_ELEM_INFO(, ChunkType_ExportFlags) -ENUM_ELEM_INFO(, ChunkType_DataStream) -ENUM_ELEM_INFO(, ChunkType_MeshSubsets) -ENUM_ELEM_INFO(, ChunkType_MeshPhysicsData) -ENUM_ELEM_INFO(, ChunkType_CompiledBones) -ENUM_ELEM_INFO(, ChunkType_CompiledPhysicalBones) -ENUM_ELEM_INFO(, ChunkType_CompiledMorphTargets) -ENUM_ELEM_INFO(, ChunkType_CompiledPhysicalProxies) -ENUM_ELEM_INFO(, ChunkType_CompiledIntFaces) -ENUM_ELEM_INFO(, ChunkType_CompiledIntSkinVertices) -ENUM_ELEM_INFO(, ChunkType_CompiledExt2IntMap) -ENUM_ELEM_INFO(, ChunkType_BreakablePhysics) -ENUM_ELEM_INFO(, ChunkType_FaceMap) -ENUM_ELEM_INFO(, ChunkType_MotionParameters) -ENUM_ELEM_INFO(, ChunkType_FootPlantInfo) -ENUM_ELEM_INFO(, ChunkType_BonesBoxes) -ENUM_ELEM_INFO(, ChunkType_FoliageInfo) -ENUM_INFO_END(ChunkTypes) - -STRUCT_INFO_BEGIN(RANGE_ENTITY) -STRUCT_VAR_INFO(name, TYPE_ARRAY(32, TYPE_INFO(char))) -STRUCT_VAR_INFO(start, TYPE_INFO(int)) -STRUCT_VAR_INFO(end, TYPE_INFO(int)) -STRUCT_INFO_END(RANGE_ENTITY) - -STRUCT_INFO_BEGIN(TIMING_CHUNK_DESC_0918) -STRUCT_VAR_INFO(m_SecsPerTick, TYPE_INFO(float)) -STRUCT_VAR_INFO(m_TicksPerFrame, TYPE_INFO(int)) -STRUCT_VAR_INFO(global_range, TYPE_INFO(RANGE_ENTITY)) -STRUCT_VAR_INFO(qqqqnSubRanges, TYPE_INFO(int)) -STRUCT_INFO_END(TIMING_CHUNK_DESC_0918) - - -STRUCT_INFO_BEGIN(SPEED_CHUNK_DESC_2) -STRUCT_VAR_INFO(Speed, TYPE_INFO(float)) -STRUCT_VAR_INFO(Distance, TYPE_INFO(float)) -STRUCT_VAR_INFO(Slope, TYPE_INFO(float)) -STRUCT_VAR_INFO(AnimFlags, TYPE_INFO(int)) -STRUCT_VAR_INFO(MoveDir, TYPE_ARRAY(3, TYPE_INFO(f32))) -STRUCT_VAR_INFO(StartPosition, TYPE_INFO(QuatT)) -STRUCT_INFO_END(SPEED_CHUNK_DESC_2) - -STRUCT_INFO_BEGIN(MTL_NAME_CHUNK_DESC_0800) -STRUCT_VAR_INFO(nFlags, TYPE_INFO(int)) -STRUCT_VAR_INFO(nFlags2, TYPE_INFO(int)) -STRUCT_VAR_INFO(name, TYPE_ARRAY(128, TYPE_INFO(char))) -STRUCT_VAR_INFO(nPhysicalizeType, TYPE_INFO(int)) -STRUCT_VAR_INFO(nSubMaterials, TYPE_INFO(int)) -STRUCT_VAR_INFO(nSubMatChunkId, TYPE_ARRAY(MTL_NAME_CHUNK_DESC_0800_MAX_SUB_MATERIALS, TYPE_INFO(int))) -STRUCT_VAR_INFO(nAdvancedDataChunkId, TYPE_INFO(int)) -STRUCT_VAR_INFO(sh_opacity, TYPE_INFO(float)) -STRUCT_VAR_INFO(reserve, TYPE_ARRAY(32, TYPE_INFO(int))) -STRUCT_INFO_END(MTL_NAME_CHUNK_DESC_0800) - -STRUCT_INFO_BEGIN(MTL_NAME_CHUNK_DESC_0802) -STRUCT_VAR_INFO(name, TYPE_ARRAY(128, TYPE_INFO(char))) -STRUCT_VAR_INFO(nSubMaterials, TYPE_INFO(int)) -STRUCT_INFO_END(MTL_NAME_CHUNK_DESC_0802) - -STRUCT_INFO_BEGIN(MESH_CHUNK_DESC_0745) -STRUCT_VAR_INFO(flags1, TYPE_INFO(unsigned char)) -STRUCT_VAR_INFO(flags2, TYPE_INFO(unsigned char)) -STRUCT_VAR_INFO(nVerts, TYPE_INFO(int)) -STRUCT_VAR_INFO(nTVerts, TYPE_INFO(int)) -STRUCT_VAR_INFO(nFaces, TYPE_INFO(int)) -STRUCT_VAR_INFO(VertAnimID, TYPE_INFO(int)) -STRUCT_INFO_END(MESH_CHUNK_DESC_0745) - -STRUCT_INFO_BEGIN(MESH_CHUNK_DESC_0801) -STRUCT_VAR_INFO(nFlags, TYPE_INFO(int)) -STRUCT_VAR_INFO(nFlags2, TYPE_INFO(int)) -STRUCT_VAR_INFO(nVerts, TYPE_INFO(int)) -STRUCT_VAR_INFO(nIndices, TYPE_INFO(int)) -STRUCT_VAR_INFO(nSubsets, TYPE_INFO(int)) -STRUCT_VAR_INFO(nSubsetsChunkId, TYPE_INFO(int)) -STRUCT_VAR_INFO(nVertAnimID, TYPE_INFO(int)) -STRUCT_VAR_INFO(nStreamChunkID, TYPE_ARRAY(16, TYPE_INFO(int))) -STRUCT_VAR_INFO(nPhysicsDataChunkId, TYPE_ARRAY(4, TYPE_INFO(int))) -STRUCT_VAR_INFO(bboxMin, TYPE_INFO(Vec3)) -STRUCT_VAR_INFO(bboxMax, TYPE_INFO(Vec3)) -STRUCT_VAR_INFO(texMappingDensity, TYPE_INFO(float)) -STRUCT_VAR_INFO(geometricMeanFaceArea, TYPE_INFO(float)) -STRUCT_VAR_INFO(reserved, TYPE_ARRAY(30, TYPE_INFO(int))) -STRUCT_INFO_END(MESH_CHUNK_DESC_0801) - -STRUCT_INFO_BEGIN(MESH_CHUNK_DESC_0802) -STRUCT_VAR_INFO(nFlags, TYPE_INFO(int)) -STRUCT_VAR_INFO(nFlags2, TYPE_INFO(int)) -STRUCT_VAR_INFO(nVerts, TYPE_INFO(int)) -STRUCT_VAR_INFO(nIndices, TYPE_INFO(int)) -STRUCT_VAR_INFO(nSubsets, TYPE_INFO(int)) -STRUCT_VAR_INFO(nSubsetsChunkId, TYPE_INFO(int)) -STRUCT_VAR_INFO(nVertAnimID, TYPE_INFO(int)) -STRUCT_VAR_INFO(nStreamChunkID, TYPE_ARRAY(16, TYPE_ARRAY(8, TYPE_INFO(int)))) -STRUCT_VAR_INFO(nPhysicsDataChunkId, TYPE_ARRAY(4, TYPE_INFO(int))) -STRUCT_VAR_INFO(bboxMin, TYPE_INFO(Vec3)) -STRUCT_VAR_INFO(bboxMax, TYPE_INFO(Vec3)) -STRUCT_VAR_INFO(texMappingDensity, TYPE_INFO(float)) -STRUCT_VAR_INFO(geometricMeanFaceArea, TYPE_INFO(float)) -STRUCT_VAR_INFO(reserved, TYPE_ARRAY(30, TYPE_INFO(int))) -STRUCT_INFO_END(MESH_CHUNK_DESC_0802) - -STRUCT_INFO_BEGIN(STREAM_DATA_CHUNK_DESC_0800) -STRUCT_VAR_INFO(nFlags, TYPE_INFO(int)) -STRUCT_VAR_INFO(nStreamType, TYPE_INFO(int)) -STRUCT_VAR_INFO(nCount, TYPE_INFO(int)) -STRUCT_VAR_INFO(nElementSize, TYPE_INFO(int)) -STRUCT_VAR_INFO(reserved, TYPE_ARRAY(2, TYPE_INFO(int))) -STRUCT_INFO_END(STREAM_DATA_CHUNK_DESC_0800) - -STRUCT_INFO_BEGIN(STREAM_DATA_CHUNK_DESC_0801) -STRUCT_VAR_INFO(nFlags, TYPE_INFO(int)) -STRUCT_VAR_INFO(nStreamType, TYPE_INFO(int)) -STRUCT_VAR_INFO(nStreamIndex, TYPE_INFO(int)) -STRUCT_VAR_INFO(nCount, TYPE_INFO(int)) -STRUCT_VAR_INFO(nElementSize, TYPE_INFO(int)) -STRUCT_VAR_INFO(reserved, TYPE_ARRAY(2, TYPE_INFO(int))) -STRUCT_INFO_END(STREAM_DATA_CHUNK_DESC_0801) - -STRUCT_INFO_BEGIN(MESH_SUBSETS_CHUNK_DESC_0800::MeshSubset) -STRUCT_VAR_INFO(nFirstIndexId, TYPE_INFO(int)) -STRUCT_VAR_INFO(nNumIndices, TYPE_INFO(int)) -STRUCT_VAR_INFO(nFirstVertId, TYPE_INFO(int)) -STRUCT_VAR_INFO(nNumVerts, TYPE_INFO(int)) -STRUCT_VAR_INFO(nMatID, TYPE_INFO(int)) -STRUCT_VAR_INFO(fRadius, TYPE_INFO(float)) -STRUCT_VAR_INFO(vCenter, TYPE_INFO(Vec3)) -STRUCT_INFO_END(MESH_SUBSETS_CHUNK_DESC_0800::MeshSubset) - -STRUCT_INFO_BEGIN(MESH_SUBSETS_CHUNK_DESC_0800::MeshBoneIDs) -STRUCT_VAR_INFO(numBoneIDs, TYPE_INFO(uint32)) -STRUCT_VAR_INFO(arrBoneIDs, TYPE_ARRAY(128, TYPE_INFO(uint16))) -STRUCT_INFO_END(MESH_SUBSETS_CHUNK_DESC_0800::MeshBoneIDs) - -STRUCT_INFO_BEGIN(MESH_SUBSETS_CHUNK_DESC_0800::MeshSubsetTexelDensity) -STRUCT_VAR_INFO(texelDensity, TYPE_INFO(float)) -STRUCT_INFO_END(MESH_SUBSETS_CHUNK_DESC_0800::MeshSubsetTexelDensity) - - -STRUCT_INFO_BEGIN(MESH_SUBSETS_CHUNK_DESC_0800) -STRUCT_VAR_INFO(nFlags, TYPE_INFO(int)) -STRUCT_VAR_INFO(nCount, TYPE_INFO(int)) -STRUCT_VAR_INFO(reserved, TYPE_ARRAY(2, TYPE_INFO(int))) -STRUCT_INFO_END(MESH_SUBSETS_CHUNK_DESC_0800) - -STRUCT_INFO_BEGIN(MESH_PHYSICS_DATA_CHUNK_DESC_0800) -STRUCT_VAR_INFO(nDataSize, TYPE_INFO(int)) -STRUCT_VAR_INFO(nFlags, TYPE_INFO(int)) -STRUCT_VAR_INFO(nTetrahedraDataSize, TYPE_INFO(int)) -STRUCT_VAR_INFO(nTetrahedraChunkId, TYPE_INFO(int)) -STRUCT_VAR_INFO(reserved, TYPE_ARRAY(2, TYPE_INFO(int))) -STRUCT_INFO_END(MESH_PHYSICS_DATA_CHUNK_DESC_0800) - -STRUCT_INFO_BEGIN(BONEANIM_CHUNK_DESC_0290) -STRUCT_VAR_INFO(nBones, TYPE_INFO(int)) -STRUCT_INFO_END(BONEANIM_CHUNK_DESC_0290) - -STRUCT_INFO_BEGIN(BONENAMELIST_CHUNK_DESC_0745) -STRUCT_VAR_INFO(numEntities, TYPE_INFO(int)) -STRUCT_INFO_END(BONENAMELIST_CHUNK_DESC_0745) - -STRUCT_INFO_BEGIN(COMPILED_BONE_CHUNK_DESC_0800) -STRUCT_VAR_INFO(reserved, TYPE_ARRAY(32, TYPE_INFO(char))) -STRUCT_INFO_END(COMPILED_BONE_CHUNK_DESC_0800) - -STRUCT_INFO_BEGIN(COMPILED_PHYSICALBONE_CHUNK_DESC_0800) -STRUCT_VAR_INFO(reserved, TYPE_ARRAY(32, TYPE_INFO(char))) -STRUCT_INFO_END(COMPILED_PHYSICALBONE_CHUNK_DESC_0800) - -STRUCT_INFO_BEGIN(COMPILED_PHYSICALPROXY_CHUNK_DESC_0800) -STRUCT_VAR_INFO(numPhysicalProxies, TYPE_INFO(uint32)) -STRUCT_INFO_END(COMPILED_PHYSICALPROXY_CHUNK_DESC_0800) - -STRUCT_INFO_BEGIN(COMPILED_MORPHTARGETS_CHUNK_DESC_0800) -STRUCT_VAR_INFO(numMorphTargets, TYPE_INFO(uint32)) -STRUCT_INFO_END(COMPILED_MORPHTARGETS_CHUNK_DESC_0800) - -STRUCT_INFO_BEGIN(COMPILED_INTSKINVERTICES_CHUNK_DESC_0800) -STRUCT_VAR_INFO(reserved, TYPE_ARRAY(32, TYPE_INFO(char))) -STRUCT_INFO_END(COMPILED_INTSKINVERTICES_CHUNK_DESC_0800) - -STRUCT_INFO_BEGIN(BaseKey) -STRUCT_VAR_INFO(time, TYPE_INFO(int)) -STRUCT_INFO_END(BaseKey) - -STRUCT_INFO_BEGIN(BaseTCB) -STRUCT_VAR_INFO(t, TYPE_INFO(float)) -STRUCT_VAR_INFO(c, TYPE_INFO(float)) -STRUCT_VAR_INFO(b, TYPE_INFO(float)) -STRUCT_VAR_INFO(ein, TYPE_INFO(float)) -STRUCT_VAR_INFO(eout, TYPE_INFO(float)) -STRUCT_INFO_END(BaseTCB) - -STRUCT_INFO_BEGIN(BaseKey3) -STRUCT_BASE_INFO(BaseKey) -STRUCT_VAR_INFO(val, TYPE_INFO(Vec3)) -STRUCT_INFO_END(BaseKey3) - -STRUCT_INFO_BEGIN(BaseKeyQ) -STRUCT_BASE_INFO(BaseKey) -STRUCT_VAR_INFO(val, TYPE_INFO(CryQuat)) -STRUCT_INFO_END(BaseKeyQ) - -STRUCT_INFO_BEGIN(CryTCB3Key) -STRUCT_BASE_INFO(BaseKey3) -STRUCT_BASE_INFO(BaseTCB) -STRUCT_INFO_END(CryTCB3Key) - -STRUCT_INFO_BEGIN(CryTCBQKey) -STRUCT_BASE_INFO(BaseKeyQ) -STRUCT_BASE_INFO(BaseTCB) -STRUCT_INFO_END(CryTCBQKey) - -STRUCT_INFO_BEGIN(CryKeyPQLog) -STRUCT_VAR_INFO(nTime, TYPE_INFO(int)) -STRUCT_VAR_INFO(vPos, TYPE_INFO(Vec3)) -STRUCT_VAR_INFO(vRotLog, TYPE_INFO(Vec3)) -STRUCT_INFO_END(CryKeyPQLog) - -ENUM_INFO_BEGIN(CtrlTypes) -ENUM_ELEM_INFO(, CTRL_NONE) -ENUM_ELEM_INFO(, CTRL_CRYBONE) -ENUM_ELEM_INFO(, CTRL_LINEER1) -ENUM_ELEM_INFO(, CTRL_LINEER3) -ENUM_ELEM_INFO(, CTRL_LINEERQ) -ENUM_ELEM_INFO(, CTRL_BEZIER1) -ENUM_ELEM_INFO(, CTRL_BEZIER3) -ENUM_ELEM_INFO(, CTRL_BEZIERQ) -ENUM_ELEM_INFO(, CTRL_TCB1) -ENUM_ELEM_INFO(, CTRL_TCB3) -ENUM_ELEM_INFO(, CTRL_TCBQ) -ENUM_ELEM_INFO(, CTRL_BSPLINE_2O) -ENUM_ELEM_INFO(, CTRL_BSPLINE_1O) -ENUM_ELEM_INFO(, CTRL_BSPLINE_2C) -ENUM_ELEM_INFO(, CTRL_BSPLINE_1C) -ENUM_ELEM_INFO(, CTRL_CONST) -ENUM_INFO_END(CtrlTypes) - -STRUCT_INFO_BEGIN(CONTROLLER_CHUNK_DESC_0826) -STRUCT_VAR_INFO(type, TYPE_INFO(CtrlTypes)) -STRUCT_VAR_INFO(nKeys, TYPE_INFO(int)) -STRUCT_VAR_INFO(nFlags, TYPE_INFO(unsigned int)) -STRUCT_VAR_INFO(nControllerId, TYPE_INFO(unsigned int)) -STRUCT_INFO_END(CONTROLLER_CHUNK_DESC_0826) - -STRUCT_INFO_BEGIN(CONTROLLER_CHUNK_DESC_0827) -STRUCT_VAR_INFO(numKeys, TYPE_INFO(unsigned int)) -STRUCT_VAR_INFO(nControllerId, TYPE_INFO(unsigned int)) -STRUCT_INFO_END(CONTROLLER_CHUNK_DESC_0827) - -STRUCT_INFO_BEGIN(CONTROLLER_CHUNK_DESC_0829) -STRUCT_VAR_INFO(nControllerId, TYPE_INFO(unsigned int)) -STRUCT_VAR_INFO(numRotationKeys, TYPE_INFO(uint16)) -STRUCT_VAR_INFO(numPositionKeys, TYPE_INFO(uint16)) -STRUCT_VAR_INFO(RotationFormat, TYPE_INFO(uint8)) -STRUCT_VAR_INFO(RotationTimeFormat, TYPE_INFO(uint8)) -STRUCT_VAR_INFO(PositionFormat, TYPE_INFO(uint8)) -STRUCT_VAR_INFO(PositionKeysInfo, TYPE_INFO(uint8)) -STRUCT_VAR_INFO(PositionTimeFormat, TYPE_INFO(uint8)) -STRUCT_VAR_INFO(TracksAligned, TYPE_INFO(uint8)) -STRUCT_INFO_END(CONTROLLER_CHUNK_DESC_0829) - -STRUCT_INFO_BEGIN(CONTROLLER_CHUNK_DESC_0830) -STRUCT_VAR_INFO(numKeys, TYPE_INFO(unsigned int)) -STRUCT_VAR_INFO(nFlags, Type_info(unsigned int)) -STRUCT_VAR_INFO(nControllerId, TYPE_INFO(unsigned int)) -STRUCT_INFO_END(CONTROLLER_CHUNK_DESC_0830) - -STRUCT_INFO_BEGIN(CONTROLLER_CHUNK_DESC_0831) -STRUCT_VAR_INFO(nControllerId, TYPE_INFO(unsigned int)) -STRUCT_VAR_INFO(nFlags, Type_info(unsigned int)) -STRUCT_VAR_INFO(numRotationKeys, TYPE_INFO(uint16)) -STRUCT_VAR_INFO(numPositionKeys, TYPE_INFO(uint16)) -STRUCT_VAR_INFO(RotationFormat, TYPE_INFO(uint8)) -STRUCT_VAR_INFO(RotationTimeFormat, TYPE_INFO(uint8)) -STRUCT_VAR_INFO(PositionFormat, TYPE_INFO(uint8)) -STRUCT_VAR_INFO(PositionKeysInfo, TYPE_INFO(uint8)) -STRUCT_VAR_INFO(PositionTimeFormat, TYPE_INFO(uint8)) -STRUCT_VAR_INFO(TracksAligned, TYPE_INFO(uint8)) -STRUCT_INFO_END(CONTROLLER_CHUNK_DESC_0831) - -STRUCT_INFO_BEGIN(CONTROLLER_CHUNK_DESC_0905) -STRUCT_VAR_INFO(numKeyPos, TYPE_INFO(uint32)) -STRUCT_VAR_INFO(numKeyRot, TYPE_INFO(uint32)) -STRUCT_VAR_INFO(numKeyTime, TYPE_INFO(uint32)) -STRUCT_VAR_INFO(numAnims, TYPE_INFO(uint32)) -STRUCT_INFO_END(CONTROLLER_CHUNK_DESC_0905) - -STRUCT_INFO_BEGIN(NODE_CHUNK_DESC_0824) -STRUCT_VAR_INFO(name, TYPE_ARRAY(64, TYPE_INFO(char))) -STRUCT_VAR_INFO(ObjectID, TYPE_INFO(int)) -STRUCT_VAR_INFO(ParentID, TYPE_INFO(int)) -STRUCT_VAR_INFO(nChildren, TYPE_INFO(int)) -STRUCT_VAR_INFO(MatID, TYPE_INFO(int)) -STRUCT_VAR_INFO(_obsoleteA_, TYPE_ARRAY(4, TYPE_INFO(uint8))) -STRUCT_VAR_INFO(tm, TYPE_ARRAY(4, TYPE_ARRAY(4, TYPE_INFO(float)))) -STRUCT_VAR_INFO(_obsoleteB_, TYPE_ARRAY(3, TYPE_INFO(float))) -STRUCT_VAR_INFO(_obsoleteC_, TYPE_ARRAY(4, TYPE_INFO(float))) -STRUCT_VAR_INFO(_obsoleteD_, TYPE_ARRAY(3, TYPE_INFO(float))) -STRUCT_VAR_INFO(pos_cont_id, TYPE_INFO(int)) -STRUCT_VAR_INFO(rot_cont_id, TYPE_INFO(int)) -STRUCT_VAR_INFO(scl_cont_id, TYPE_INFO(int)) -STRUCT_VAR_INFO(PropStrLen, TYPE_INFO(int)) -STRUCT_INFO_END(NODE_CHUNK_DESC_0824) - -ENUM_INFO_BEGIN(HelperTypes) -ENUM_ELEM_INFO(, HP_POINT) -ENUM_ELEM_INFO(, HP_DUMMY) -ENUM_ELEM_INFO(, HP_XREF) -ENUM_ELEM_INFO(, HP_CAMERA) -ENUM_ELEM_INFO(, HP_GEOMETRY) -ENUM_INFO_END(HelperTypes) - -STRUCT_INFO_BEGIN(HELPER_CHUNK_DESC_0744) -STRUCT_VAR_INFO(type, TYPE_INFO(HelperTypes)) -STRUCT_VAR_INFO(size, TYPE_INFO(Vec3)) -STRUCT_INFO_END(HELPER_CHUNK_DESC_0744) - -STRUCT_INFO_BEGIN(MESHMORPHTARGET_CHUNK_DESC_0001) -STRUCT_VAR_INFO(nChunkIdMesh, TYPE_INFO(unsigned int)) -STRUCT_VAR_INFO(numMorphVertices, TYPE_INFO(unsigned int)) -STRUCT_INFO_END(MESHMORPHTARGET_CHUNK_DESC_0001) - -STRUCT_INFO_BEGIN(SMeshMorphTargetVertex) -STRUCT_VAR_INFO(nVertexId, TYPE_INFO(unsigned int)) -STRUCT_VAR_INFO(ptVertex, TYPE_INFO(Vec3)) -STRUCT_INFO_END(SMeshMorphTargetVertex) - -STRUCT_INFO_BEGIN(SMeshMorphTargetHeader) -STRUCT_VAR_INFO(MeshID, TYPE_INFO(uint32)) -STRUCT_VAR_INFO(NameLength, TYPE_INFO(uint32)) -STRUCT_VAR_INFO(numIntVertices, TYPE_INFO(uint32)) -STRUCT_VAR_INFO(numExtVertices, TYPE_INFO(uint32)) -STRUCT_INFO_END(SMeshMorphTargetHeader) - -STRUCT_INFO_BEGIN(SMeshPhysicalProxyHeader) -STRUCT_VAR_INFO(ChunkID, TYPE_INFO(uint32)) -STRUCT_VAR_INFO(numPoints, TYPE_INFO(uint32)) -STRUCT_VAR_INFO(numIndices, TYPE_INFO(uint32)) -STRUCT_VAR_INFO(numMaterials, TYPE_INFO(uint32)) -STRUCT_INFO_END(SMeshPhysicalProxyHeader) - -STRUCT_INFO_BEGIN(BONEINITIALPOS_CHUNK_DESC_0001) -STRUCT_VAR_INFO(nChunkIdMesh, TYPE_INFO(unsigned int)) -STRUCT_VAR_INFO(numBones, TYPE_INFO(unsigned int)) -STRUCT_INFO_END(BONEINITIALPOS_CHUNK_DESC_0001) - -STRUCT_INFO_BEGIN(SBoneInitPosMatrix) -STRUCT_VAR_INFO(mx, TYPE_ARRAY(4, TYPE_ARRAY(3, TYPE_INFO(float)))) -STRUCT_INFO_END(SBoneInitPosMatrix) - -STRUCT_INFO_BEGIN(EXPORT_FLAGS_CHUNK_DESC) -STRUCT_VAR_INFO(flags, TYPE_INFO(unsigned int)) -STRUCT_VAR_INFO(rc_version, TYPE_ARRAY(4, TYPE_INFO(unsigned int))) -STRUCT_VAR_INFO(rc_version_string, TYPE_ARRAY(16, TYPE_INFO(char))) -STRUCT_VAR_INFO(assetAuthorTool, TYPE_INFO(uint32)) -STRUCT_VAR_INFO(authorToolVersion, TYPE_INFO(uint32)) -STRUCT_VAR_INFO(reserved, TYPE_ARRAY(30, TYPE_INFO(unsigned int))) -STRUCT_INFO_END(EXPORT_FLAGS_CHUNK_DESC) - -STRUCT_INFO_BEGIN(BREAKABLE_PHYSICS_CHUNK_DESC) -STRUCT_VAR_INFO(granularity, TYPE_INFO(unsigned int)) -STRUCT_VAR_INFO(nMode, TYPE_INFO(int)) -STRUCT_VAR_INFO(nRetVtx, TYPE_INFO(int)) -STRUCT_VAR_INFO(nRetTets, TYPE_INFO(int)) -STRUCT_VAR_INFO(nReserved, TYPE_ARRAY(10, TYPE_INFO(int))) -STRUCT_INFO_END(BREAKABLE_PHYSICS_CHUNK_DESC) - -STRUCT_INFO_BEGIN(FOLIAGE_INFO_CHUNK_DESC) -STRUCT_VAR_INFO(nSpines, TYPE_INFO(int)) -STRUCT_VAR_INFO(nSpineVtx, TYPE_INFO(int)) -STRUCT_VAR_INFO(nSkinnedVtx, TYPE_INFO(int)) -STRUCT_VAR_INFO(nBoneIds, TYPE_INFO(int)) -STRUCT_INFO_END(FOLIAGE_INFO_CHUNK_DESC) - -STRUCT_INFO_BEGIN(FOLIAGE_SPINE_SUB_CHUNK) -STRUCT_VAR_INFO(nVtx, TYPE_INFO(char)) -STRUCT_VAR_INFO(len, TYPE_INFO(float)) -STRUCT_VAR_INFO(navg, TYPE_INFO(Vec3)) -STRUCT_VAR_INFO(iAttachSpine, TYPE_INFO(unsigned char)) -STRUCT_VAR_INFO(iAttachSeg, TYPE_INFO(unsigned char)) -STRUCT_INFO_END(FOLIAGE_SPINE_SUB_CHUNK) diff --git a/Code/Legacy/CryCommon/CrySizer.h b/Code/Legacy/CryCommon/CrySizer.h index 3f9eed84f6..27323368ab 100644 --- a/Code/Legacy/CryCommon/CrySizer.h +++ b/Code/Legacy/CryCommon/CrySizer.h @@ -24,7 +24,6 @@ #include "Cry_Math.h" #include -#include #include #include #include @@ -36,7 +35,6 @@ struct AABB; struct SVF_P3F; struct SVF_P3F_C4B_T2F; -struct SVF_P3F_C4B_T2S; struct SVF_P3S_C4B_T2S; struct SPipTangents; @@ -237,7 +235,6 @@ public: void AddObject(const AABB&) {} void AddObject(const SVF_P3F&) {} void AddObject(const SVF_P3F_C4B_T2F&) {} - void AddObject(const SVF_P3F_C4B_T2S&) {} void AddObject(const SVF_P3S_C4B_T2S&) {} void AddObject(const SPipTangents&) {} void AddObject([[maybe_unused]] const AZ::Vector3& rObj) {} @@ -301,26 +298,6 @@ public: } } - template - void AddObject(const DynArray& rVector) - { - if (rVector.empty()) - { - this->AddObject(rVector.begin(), rVector.get_alloc_size()); - return; - } - - if (!this->AddObject(rVector.begin(), rVector.get_alloc_size())) - { - return; - } - - for (typename DynArray::const_iterator it = rVector.begin(); it != rVector.end(); ++it) - { - this->AddObject(*it); - } - } - template void AddObject(const PodArray& rVector) { diff --git a/Code/Legacy/CryCommon/CryTypeInfo.cpp b/Code/Legacy/CryCommon/CryTypeInfo.cpp deleted file mode 100644 index 82743f7eef..0000000000 --- a/Code/Legacy/CryCommon/CryTypeInfo.cpp +++ /dev/null @@ -1,1472 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - -// Description : Implementation of TypeInfo classes and functions. - -#include -#include "CryTypeInfo.h" -#include "CryCustomTypes.h" -#include "Cry_Math.h" -#include "CrySizer.h" -#include "CryEndian.h" -#include "TypeInfo_impl.h" -#include - -// Traits -#if defined(AZ_RESTRICTED_PLATFORM) - #include AZ_RESTRICTED_FILE(CryTypeInfo_cpp) -#elif defined(LINUX) || defined(APPLE) -#define CRYTYPEINFO_CPP_TRAIT_DEFINE_LTOA_S 1 -#endif - -#if CRYTYPEINFO_CPP_TRAIT_DEFINE_LTOA_S - -char* _ltoa_s(long value, char* string, size_t size, int32 radix) -{ - if (10 == radix) - { - sprintf_s(string, size, "%ld", value); - } - else - { - sprintf_s(string, size, "%lx", value); - } - return(string); -} - - -char* _i64toa_s(int64 value, char* string, size_t size, int32 radix) -{ - if (10 == radix) - { - sprintf_s(string, size, "%llu", (unsigned long long)value); - } - else - { - sprintf_s(string, size, "%llx", (unsigned long long)value); - } - return(string); -} - -char* _ultoa_s(uint32 value, char* string, size_t size, int32 radix) -{ - if (10 == radix) - { - sprintf_s(string, size, "%.d", value); - } - else - { - sprintf_s(string, size, "%.x", value); - } - return(string); -} - -#endif //LINUX || MAC - -////////////////////////////////////////////////////////////////////// -// Case-insensitive comparison helpers. - -class StrNoCase -{ -public: - inline StrNoCase(cstr str) - : m_Str(str) {} - inline bool operator == (cstr str) const { return azstricmp(m_Str, str) == 0; } - inline bool operator != (cstr str) const { return azstricmp(m_Str, str) != 0; } -private: - cstr m_Str; -}; - -// Default Endian swap function, forwards to TypeInfo. -void SwapEndian(const CTypeInfo& Info, [[maybe_unused]] size_t nSizeCheck, void* data, size_t nCount, bool bWriting) -{ - assert(nSizeCheck == Info.Size); - Info.SwapEndian(data, nCount, bWriting); -} - -////////////////////////////////////////////////////////////////////// -// Basic TypeInfo implementations. - -// Basic type infos. - -DEFINE_TYPE_INFO(void, CTypeInfo, ("void", 0, 0)) - -TYPE_INFO_BASIC(bool) -TYPE_INFO_BASIC(char) -TYPE_INFO_BASIC(wchar_t) - -TYPE_INFO_INT(signed char) -TYPE_INFO_INT(unsigned char) -TYPE_INFO_INT(short) -TYPE_INFO_INT(unsigned short) -TYPE_INFO_INT(int) -TYPE_INFO_INT(unsigned int) -TYPE_INFO_INT(long) -TYPE_INFO_INT(unsigned long) -TYPE_INFO_INT(int64) -TYPE_INFO_INT(uint64) - -TYPE_INFO_BASIC(float) -TYPE_INFO_BASIC(double) - -TYPE_INFO_BASIC(AZStd::string) - - -const CTypeInfo&PtrTypeInfo() -{ - static CTypeInfo Info(TYPE_INFO_NAME(void*), sizeof(void*), alignof(void*)); - return Info; -} - -////////////////////////////////////////////////////////////////////// -// Basic type info implementations. - -// String conversion functions needed by TypeInfo. - -// bool -AZStd::string ToString(bool const& val) -{ - return val ? "true" : "false"; -} - -bool FromString(bool& val, cstr s) -{ - if (!strcmp(s, "0") || !azstricmp(s, "false")) - { - val = false; - return true; - } - if (!strcmp(s, "1") || !azstricmp(s, "true")) - { - val = true; - return true; - } - return false; -} - -// int64 -AZStd::string ToString(int64 const& val) -{ - char buffer[64]; - _i64toa_s(val, buffer, sizeof(buffer), 10); - return buffer; -} -// uint64 -AZStd::string ToString(uint64 const& val) -{ - char buffer[64]; - sprintf_s(buffer, "%" PRIu64, val); - return buffer; -} - - - -// long -AZStd::string ToString(long const& val) -{ - char buffer[64]; - _ltoa_s(val, buffer, sizeof(buffer), 10); - return buffer; -} - -// ulong -AZStd::string ToString(unsigned long const& val) -{ - char buffer[64]; - _ultoa_s(val, buffer, sizeof(buffer), 10); - return buffer; -} - -template -bool ClampedIntFromString(T& val, const char* s) -{ - bool signbit = *s == '-'; - s += signbit; - if (signbit && !TIntTraits::bSIGNED) - { - // Negative number on unsigned. - val = T(0); - return true; - } - - uint digit = (uint8) * s - '0'; - if (digit > 9) - { - // No digits. - return false; - } - - // Extract digits until overflow. - T v = static_cast(digit); - while ((digit = (uint8) * ++s - '0') <= 9) - { - T vnew = static_cast(v * 10 + digit); - if (vnew < v) - { - // Overflow. - if (signbit) - { - val = TIntTraits::nMIN; - } - else - { - val = TIntTraits::nMAX; - } - return true; - } - v = vnew; - } - - val = signbit ? ~v + 1 : v; - return true; -} - -bool FromString(int64& val, const char* s) { return ClampedIntFromString(val, s); } -bool FromString(uint64& val, const char* s) { return ClampedIntFromString(val, s); } - -bool FromString(long& val, const char* s) { return ClampedIntFromString(val, s); } -bool FromString(unsigned long& val, const char* s) { return ClampedIntFromString(val, s); } - -AZStd::string ToString(int const& val) { return ToString(long(val)); } -bool FromString(int& val, const char* s) { return ClampedIntFromString(val, s); } - -AZStd::string ToString(unsigned int const& val) { return ToString((unsigned long)(val)); } -bool FromString(unsigned int& val, const char* s) { return ClampedIntFromString(val, s); } - -AZStd::string ToString(short const& val) { return ToString(long(val)); } -bool FromString(short& val, const char* s) { return ClampedIntFromString(val, s); } - -AZStd::string ToString(unsigned short const& val) { return ToString((unsigned long)(val)); } -bool FromString(unsigned short& val, const char* s) { return ClampedIntFromString(val, s); } - -AZStd::string ToString(char const& val) { return ToString(long(val)); } -bool FromString(char& val, const char* s) { return ClampedIntFromString(val, s); } - -AZStd::string ToString(wchar_t const& val) { return ToString(long(val)); } -bool FromString(wchar_t& val, const char* s) { return ClampedIntFromString(val, s); } - -AZStd::string ToString(signed char const& val) { return ToString(long(val)); } -bool FromString(signed char& val, const char* s) { return ClampedIntFromString(val, s); } - -AZStd::string ToString(unsigned char const& val) { return ToString((unsigned long)(val)); } -bool FromString(unsigned char& val, const char* s) { return ClampedIntFromString(val, s); } - -AZStd::string ToString(const AZ::Uuid& val) -{ - return val.ToString(); -} - -bool FromString(AZ::Uuid& val, const char* s) -{ - val = AZ::Uuid(s); - return true; -} - -float NumToFromString(float val, int digits, bool floating, char buffer[], int buf_size) -{ - assert(buf_size >= 32); - if (floating) - { - if (val >= powf(10.f, float(digits))) - { - sprintf_s(buffer, buf_size, "%.0f", val); - } - else - { - sprintf_s(buffer, buf_size, "%.*g", digits, val); - } - } - else - { - sprintf_s(buffer, buf_size, "%.*f", digits, float(val)); - } -#if !defined(NDEBUG) - int readCount = -#endif - azsscanf(buffer, "%g", &val); - assert(readCount == 1); - return val; -} - -// double -AZStd::string ToString(double const& val) -{ - char buffer[64]; - sprintf_s(buffer, "%.16g", val); - return buffer; -} -bool FromString(double& val, const char* s) -{ - return azsscanf(s, "%lg", &val) == 1; -} - -// float -AZStd::string ToString(float const& val) -{ - char buffer[64]; - for (int digits = 7; digits < 10; digits++) - { - if (NumToFromString(val, digits, true, buffer, 64) == val) - { - break; - } - } - return buffer; -} - -bool FromString(float& val, const char* s) -{ - return azsscanf(s, "%g", &val) == 1; -} - - - -// string override. -template <> -void TTypeInfo::GetMemoryUsage(ICrySizer* pSizer, void const* data) const -{ - // CRAIG: just a temp hack to try and get things working -#if !defined(LINUX) && !defined(APPLE) - pSizer->AddString(*(AZStd::string*)data); -#endif -} - -#if defined(TEST_TYPEINFO) && defined(_DEBUG) - -struct STypeInfoTest -{ - STypeInfoTest() - { - TestType(AZStd::string("well")); - - TestType(true); - - TestType(int8(-0x12)); - TestType(uint8(0x87)); - TestType(int16(-0x1234)); - TestType(uint16(0x8765)); - TestType(int32(-0x12345678)); - TestType(uint32(0x87654321)); - TestType(int64(-0x123456789ABCDEF0LL)); - TestType(uint64(0xFEDCBA9876543210LL)); - - TestType(float(1234.5678)); - TestType(float(12345678)); - TestType(float(12345678e-20)); - TestType(float(12345678e20)); - - TestType(double(987654321.0123456789)); - TestType(double(9876543210123456789.0)); - TestType(double(9876543210123456789e-40)); - TestType(double(9876543210123456789e40)); - } -}; -static STypeInfoTest _TypeInfoTest; - -#endif //TEST_TYPEINFO - - -////////////////////////////////////////////////////////////////////// -// CTypeInfo implementation - -//--------------------------------------------------------------------------- -// Endian helper functions. - -void CTypeInfo::SwapEndian(void* pData, size_t nCount, [[maybe_unused]] bool bWriting) const -{ - switch (Size) - { - case 1: - break; - case 2: - ::SwapEndianBase((uint16*)pData, nCount); - break; - case 4: - ::SwapEndianBase((uint32*)pData, nCount); - break; - case 8: - ::SwapEndianBase((uint64*)pData, nCount); - break; - default: - assert(0); - } -} - -// If attr name is found, return pointer to start of value text; else 0. -static cstr FindAttr(cstr attrs, cstr name) -{ - size_t name_len = strlen(name); - while (attrs) - { - attrs = strchr(attrs, '<'); - if (!attrs) - { - return 0; - } - - attrs++; - size_t attr_len = strcspn(attrs, "=>"); - if (attr_len == name_len && _strnicmp(attrs, name, name_len) == 0) - { - attrs += attr_len; - if (*attrs == '=') - { - ++attrs; - } - return attrs; - } - attrs += attr_len; - if (*attrs == '=') - { - attrs = strchr(attrs + 1, '>'); - } - } - return 0; -} - -bool CTypeInfo::CVarInfo::GetAttr(cstr name) const -{ - return FindAttr(Attrs, name) != 0; -} - -bool CTypeInfo::CVarInfo::GetAttr(cstr name, AZStd::string& val) const -{ - cstr valstr = FindAttr(Attrs, name); - if (!valstr) - { - return false; - } - - // Find attr delimiter. - cstr end = strchr(valstr, '>'); - if (!end) - { - return false; - } - - // Strip quotes. - if (*valstr == '"') - { - valstr++; - if (end - valstr > 1 && end[-1] == '"') - { - end--; - } - } - val = AZStd::string(valstr, end - valstr); - return true; -} - -bool CTypeInfo::CVarInfo::GetAttr(cstr name, float& val) const -{ - cstr valstr = FindAttr(Attrs, name); - if (!valstr) - { - return false; - } - val = (float)atof(valstr); - return true; -} - -cstr CTypeInfo::CVarInfo::GetComment() const -{ - cstr send = strrchr(Attrs, '>'); - if (send) - { - do - { - ++send; - } while (*send == ' '); - return send; - } - else - { - return Attrs; - } -} - -////////////////////////////////////////////////////////////////////// -// CStructInfo implementation - -inline cstr DisplayName(cstr name) -{ - // Skip prefixes in Name. - cstr dname = name; - while (islower((unsigned char)*dname) || *dname == '_') - { - dname++; - } - if (isupper((unsigned char)*dname)) - { - return dname; - } - else - { - return name; - } -} - -CStructInfo::CStructInfo(cstr name, size_t size, size_t align, Array vars, Array templates) - : CTypeInfo(name, size, align) - , Vars(vars) - , TemplateTypes(templates) - , HasBitfields(false) -{ - // Process and validate offsets and sizes. - if (Vars.size() > 0) - { - size = 0; - int bitoffset = 0; - - for (int i = 0; i < Vars.size(); i++) - { - CStructInfo::CVarInfo& var = Vars[i]; - - // Convert name. - var.Name = DisplayName(var.Name); - - if (var.bBitfield) - { - HasBitfields = true; - if (bitoffset > 0) - { - // Continuing bitfield. - var.Offset = Vars[i - 1].Offset; - var.BitWordWidth = Vars[i - 1].BitWordWidth; - - if (bitoffset + var.ArrayDim > var.GetSize() * 8) - { - // Overflows word, start on next one. - bitoffset = 0; - size += var.GetSize(); - } - } - - if (bitoffset == 0) - { - var.Offset = check_cast(size); - - // Detect real word size of bitfield, from offset of next field. - size_t next_offset = Size; - for (int j = i + 1; j < Vars.size(); j++) - { - if (!Vars[j].bBitfield) - { - next_offset = Vars[j].Offset; - break; - } - } - assert(next_offset > size); - size_t wordsize = min(next_offset - size, var.Type.Size); - size = next_offset; - switch (wordsize) - { - case 1: - var.BitWordWidth = 0; - break; - case 2: - var.BitWordWidth = 1; - break; - case 4: - var.BitWordWidth = 2; - break; - case 8: - var.BitWordWidth = 3; - break; - default: - assert(0); - } - } - - assert(var.ArrayDim <= var.GetSize() * 8); - var.BitOffset = bitoffset; - bitoffset += var.ArrayDim; - } - else - { - bitoffset = 0; - if (var.Offset >= size) - { - size = var.Offset + var.GetSize(); - } - } - } - assert(Align(size, Alignment) == Align(Size, Alignment)); - } -} - -size_t EndianDescSize(cstr desc) -{ - // Iterate the endian descriptor. - size_t nSize = 0; - for (; *desc; desc++) - { - size_t count = *desc & 0x3F; - size_t nType = *(uint8*)desc >> 6; - nSize += count << nType; - } - return nSize; -} - -size_t CStructInfo::AddEndianDesc(cstr desc, size_t dim, size_t elem_size) -{ - if (dim == 0) - { - return 0; - } - - size_t endian_size = EndianDescSize(desc); - size_t total_size = elem_size * (dim - 1) + endian_size; - - if (desc[1] || (endian_size < elem_size && dim > 1)) - { - // Composite endian descriptor, replicate it. - assert(endian_size <= elem_size); - assert(elem_size - endian_size < 0x40); - while (dim-- > 0) - { - EndianDesc += (cstr)desc; - if (dim > 1 && endian_size < elem_size) - { - EndianDesc += char(0x40 | (elem_size - endian_size)); - } - } - } - else - { - // Single endian component. Replicate using count field. - size_t subdim = desc[0] & 0x3F; - dim *= subdim; - if (!EndianDesc.empty()) - { - // Combine with previous component if possible. - char prevdesc = *(EndianDesc.end() - 1); - if ((prevdesc & ~0x3F) == (desc[0] & ~0x3F)) - { - // Combine with previous char. - size_t maxdim = min(dim, size_t(0x3F - (prevdesc & 0x3F))); - prevdesc += check_cast(maxdim); - EndianDesc.erase(EndianDesc.length() - 1, 1); - EndianDesc.append(1, prevdesc); - dim -= maxdim; - } - } - for (; dim > 0x3F; dim -= 0x3F) - { - EndianDesc += desc[0] | 0x3F; - } - if (dim > 0) - { - EndianDesc += check_cast((desc[0] & ~0x3F) | dim); - } - } - - return total_size; -} - -bool CStructInfo::FromValue(void* data, const void* value, const CTypeInfo& typeVal) const -{ - if (IsCompatibleType(typeVal)) - { - bool bOK = true; - int i = 0; - for AllSubVars(pToVar, typeVal) - { - if (!Vars[i].Type.FromValue(Vars[i].GetAddress(data), pToVar->GetAddress(value), pToVar->Type)) - { - bOK = false; - } - i++; - } - return bOK; - } - - // Check all subclasses. - for (int i = 0; i < Vars.size() && Vars[i].IsBaseClass(); i++) - { - if (Vars[i].Type.FromValue(Vars[i].GetAddress(data), value, typeVal)) - { - return true; - } - } - return false; -} - -bool CStructInfo::ToValue(const void* data, void* value, const CTypeInfo& typeVal) const -{ - if (IsCompatibleType(typeVal)) - { - bool bOK = true; - int i = 0; - for AllSubVars(pToVar, typeVal) - { - if (!Vars[i].Type.ToValue(Vars[i].GetAddress(data), pToVar->GetAddress(value), pToVar->Type)) - { - bOK = false; - } - i++; - } - return bOK; - } - - // Check all subclasses. - for (int i = 0; i < Vars.size() && Vars[i].IsBaseClass(); i++) - { - if (Vars[i].Type.ToValue(Vars[i].GetAddress(data), value, typeVal)) - { - return true; - } - } - return false; -} - -// Parse structs as comma-separated values. - -/* , 1, ,2 1,2 - - Top 1 ,2 1,2 ; strip trail commas - Child Named 1 (,2) (1,2) ; strip trail commas, paren if internal commas - Nameless , 1, ,2 1,2 ; -*/ - -static void StripCommas(AZStd::string& str) -{ - size_t nLast = str.size(); - while (nLast > 0 && str[nLast - 1] == ',') - { - nLast--; - } - str.resize(nLast); -} - -AZStd::string CStructInfo::ToString(const void* data, FToString flags, const void* def_data) const -{ - AZStd::string str; // Return str. - - for (int i = 0; i < Vars.size(); i++) - { - // Handling of empty values: Skip trailing empty values. - // If there are intermediate empty values, replace them with non-empty ones. - const CVarInfo& var = Vars[i]; - - if (!var.IsInline()) - { - // Named sub var or struct. - if (!flags.NamedFields && i > 0) - { - str += ","; - } - - AZStd::string substr = var.ToString(data, FToString(flags).Sub(0), def_data); - - if (flags.SkipDefault && substr.empty()) - { - continue; - } - - if (flags.NamedFields) - { - if (*str.c_str()) - { - str += ","; - } - if (*var.Name) - { - str += var.Name; - str += "="; - } - } - if (substr.find(',') != AZStd::string::npos || substr.find('=') != AZStd::string::npos) - { - // Encase nested composite types in parens. - str += "("; - str += substr; - str += ")"; - } - else - { - str += substr; - } - } - else - { - // Nameless base struct. Treat children as inline. - str += var.ToString(data, FToString(flags).Sub(1), def_data); - } - } - - if (flags.SkipDefault && !flags.Sub) - { - StripCommas(str); - } - return str; -} - -// Retrieve and return one subelement from src, advancing the pointer. -// Copy to tempstr if necessary. - -typedef AZStd::fixed_string<256> CTempStr; - -void ParseElement(cstr& src, cstr& varname, cstr& val, CTempStr& tempstr) -{ - varname = val = 0; - - while (*src == ' ') - { - src++; - } - if (!*src) - { - return; - } - - // Find end of var assignment. - int nest = 0; - cstr eq = 0; - - cstr end; - for (end = src; *end; end++) - { - if (*end == '(') - { - nest++; - } - else if (*end == ')') - { - nest--; - } - else if (nest == 0) - { - if (*end == '=' && !eq) - { - eq = end; - } - else if (*end == ',') - { - break; - } - } - } - - // Advance src past element. - val = src; - src = end; - - if (*src == ',') - { - src++; - } - - if (eq) - { - varname = val; - val = eq + 1; - } - - PREFAST_ASSUME(val); - if (*val == '(' && end[-1] == ')') - { - // Remove parens. - val++; - end--; - } - - if (eq) - { - if (*end) - { - // Must copy sub string to temp. - val = tempstr.c_str() + (val - varname); - eq = tempstr.c_str() + (eq - varname); - tempstr.assign(varname, end); - varname = tempstr.c_str(); - non_const(*eq) = 0; - } - else - { - // Copy just varname to temp, return val in place. - tempstr.assign(varname, eq); - varname = tempstr.c_str(); - } - } - else if (*end) - { - // Must copy sub string to temp. - tempstr.assign(val, end); - val = tempstr.c_str(); - } - - // Else can return val without copying. -} - -bool CStructInfo::FromString(void* data, cstr str, FFromString flags) const -{ - if (!flags.SkipEmpty) - { - // Initialise all to default - for (int i = 0; i < Vars.size(); i++) - { - Vars[i].FromString(data, ""); - } - } - - CTempStr tempstr; - const CVarInfo* pVar = 0; - int nErrors = 0; - - while (*str) - { - cstr varname, val; - ParseElement(str, varname, val, tempstr); - - if (varname) - { - pVar = FindSubVar(varname); - } - else - { - pVar = NextSubVar(pVar, true); - } - if (pVar) - { - if (*val || !flags.SkipEmpty) - { - nErrors += !pVar->FromString(data, val, flags); - } - } - else - { - nErrors++; - } - } - - return !nErrors; -} - -bool CStructInfo::ValueEqual(const void* data, const void* def_data) const -{ - for (int i = 0; i < Vars.size(); i++) - { - const CVarInfo& var = Vars[i]; - if (!var.Type.ValueEqual((char*)data + var.Offset, (def_data ? (char*)def_data + var.Offset : 0))) - { - return false; - } - } - return true; -} - -void CStructInfo::SwapEndian(void* data, size_t nCount, bool bWriting) const -{ - non_const(*this).MakeEndianDesc(); - - if (EndianDesc.length() == 1 && !HasBitfields && EndianDescSize(EndianDesc.c_str()) == Size) - { - // Optimised array swap. - size_t nElems = (EndianDesc[0u] & 0x3F) * nCount; - switch (EndianDesc[0u] & 0xC0) - { - case 0: // Skip bytes - break; - case 0x40: // Swap 2 bytes - ::SwapEndianBase((uint16*)data, nElems); - break; - case 0x80: // Swap 4 bytes - ::SwapEndianBase((uint32*)data, nElems); - break; - case 0xC0: // Swap 8 bytes - ::SwapEndianBase((uint64*)data, nElems); - break; - } - return; - } - - for (; nCount-- > 0; data = (char*)data + Size) - { - // First swap bits. - // Iterate the endian descriptor. - void* step = data; - for (cstr desc = EndianDesc.c_str(); *desc; desc++) - { - size_t nElems = *desc & 0x3F; - switch (*desc & 0xC0) - { - case 0: // Skip bytes - step = (uint8*)step + nElems; - break; - case 0x40: // Swap 2 bytes - ::SwapEndianBase((uint16*)step, nElems); - step = (uint16*)step + nElems; - break; - case 0x80: // Swap 4 bytes - ::SwapEndianBase((uint32*)step, nElems); - step = (uint32*)step + nElems; - break; - case 0xC0: // Swap 8 bytes - ::SwapEndianBase((uint64*)step, nElems); - step = (uint64*)step + nElems; - break; - } - } - - // Then bitfields if needed. - if (HasBitfields) - { - uint64 uOrigBits = 0, uNewBits = 0; - for (int i = 0; i < Vars.size(); i++) - { - CVarInfo const& var = Vars[i]; - if (var.bBitfield) - { - // Reverse location of all bitfields in word. - size_t nWordBits = var.GetElemSize() * 8; - assert(nWordBits <= 64); - if (var.BitOffset == 0) - { - // Initialise bitfield swapping. - var.Type.ToValue(var.GetAddress(data), uOrigBits); - uNewBits = 0; - } - size_t nSrcOffset = (GetPlatformEndian() == eLittleEndian) == bWriting ? var.BitOffset : nWordBits - var.GetBits() - var.BitOffset; - size_t nDstOffset = nWordBits - var.GetBits() - nSrcOffset; - - uint64 uFieldVal = uOrigBits >> nSrcOffset; - uFieldVal &= ((1 << var.GetBits()) - 1); - uNewBits |= uFieldVal << nDstOffset; - var.Type.FromValue(var.GetAddress(data), uNewBits); - } - } - } - } -} - -void CStructInfo::MakeEndianDesc() -{ - if (!EndianDesc.empty()) - { - return; - } - - size_t last_offset = 0; - for (int i = 0; i < Vars.size(); i++) - { - CVarInfo const& var = Vars[i]; - bool bUnionAlias = var.bBitfield ? var.BitOffset > 0 : var.Offset < last_offset; - if (!bUnionAlias) - { - // Add endian desc for member. - cstr subdesc = 0; - if (var.Type.HasSubVars()) - { - // Struct-computed endian desc. - CStructInfo const& infoSub = static_cast(var.Type); - non_const(infoSub).MakeEndianDesc(); - subdesc = infoSub.EndianDesc.c_str(); - if (!*subdesc) - { - // No swapping. - continue; - } - } - else - { - // Basic type. - switch (var.GetElemSize()) - { - case 0: - case 1: - continue; // No swapping needed. - case 2: - subdesc = "\x41"; - break; - case 4: - subdesc = "\x81"; - break; - case 8: - subdesc = "\xC1"; - break; - default: - assert(0); - } - } - - // Apply any padding to current offset. - assert(last_offset <= var.Offset); - if (last_offset < var.Offset) - { - last_offset += AddEndianDesc("\x01", var.Offset - last_offset, 1); - } - last_offset += AddEndianDesc(subdesc, var.GetDim(), var.GetElemSize()); - } - } -} - -void CStructInfo::GetMemoryUsage(ICrySizer* pSizer, void const* data) const -{ - for (int i = 0; i < Vars.size(); i++) - { - Vars[i].Type.GetMemoryUsage(pSizer, (char*)data + Vars[i].Offset); - } -} - -const CTypeInfo::CVarInfo* CStructInfo::NextSubVar(const CVarInfo* pPrev, bool bRecurseBase) const -{ - if (pPrev >= Vars.begin() && pPrev < Vars.end()) - { - // pPrev is within this struct's vars - if (++pPrev < Vars.end()) - { - return pPrev; - } - return 0; - } - - if (Vars.empty()) - { - return 0; - } - - if (bRecurseBase) - { - // Recurse into inline base structs - const CVarInfo* pBase = Vars.begin(); - if (pBase->IsInline()) - { - if (const CVarInfo* pNext = pBase->Type.NextSubVar(pPrev, true)) - { - return pNext; - } - if (++pBase < Vars.end()) - { - return pBase; - } - return 0; - } - } - - if (!pPrev) - { - // Return first var - return Vars.begin(); - } - - return 0; -} - -const CTypeInfo::CVarInfo* CStructInfo::FindSubVar(cstr name) const -{ - static int s_nLast = 0; - int nSize = Vars.size(); - if (s_nLast >= nSize) - { - s_nLast = 0; - } - - for (int i = s_nLast, iEnd = s_nLast + nSize; i < iEnd; i++) - { - int v = i >= nSize ? i - nSize : i; - const CVarInfo& var = Vars[v]; - if (var.Type.Size > 0 && StrNoCase(var.GetName()) == name) - { - s_nLast = v; - return &var; - } - if (var.IsBaseClass()) - { - if (const CVarInfo* pSubVar = var.Type.FindSubVar(name)) - { - return pSubVar; - } - } - } - return 0; -} - -bool CStructInfo::IsCompatibleType(CTypeInfo const& Info) const -{ - if (this == &Info) - { - return true; - } - - if (!TemplateTypes.empty() && Info.IsTemplate() && strcmp(Name, Info.Name) == 0) - { - CTypeInfo const* const* pA = NextTemplateType(0); - CTypeInfo const* const* pB = Info.NextTemplateType(0); - - while (pA && pB && (*pA)->IsType(**pB)) - { - pA = Info.NextTemplateType(pA); - pB = Info.NextTemplateType(pB); - } - return !pA && !pB; - } - - return false; -} - -bool CStructInfo::IsType(CTypeInfo const& Info) const -{ - if (IsCompatibleType(Info)) - { - return true; - } - - // Check all subclasses. - for (int i = 0; i < Vars.size() && Vars[i].IsBaseClass(); i++) - { - if (Vars[i].Type.IsType(Info)) - { - return true; - } - } - return false; -} - -////////////////////////////////////////////////////////////////////// -// CSimpleEnumDef implementation - -cstr ParseNextEnum(char*& rs) -{ - char* s = rs; - while (isspace(*s)) - { - s++; - } - if (!*s) - { - return 0; - } - - cstr se = s; - while (isalnum(*s) || *s == '_') - { - s++; - } - - if (*s == ',') - { - *s++ = 0; - } - else if (*s) - { - *s++ = 0; - while (*s && *s != ',') - { - s++; - } - if (*s) - { - s++; - } - } - rs = s; - return se; -} - -void CSimpleEnumDef::Init(Array names, char* enum_str) -{ - asNames = names; - - // Split copy of enums string into elements, store in array. - int i = 0; - while (cstr se = ParseNextEnum(enum_str)) - { - asNames[i++] = se; - } -} - -////////////////////////////////////////////////////////////////////// -// CEnumDef implementation - -void CEnumDef::Init(Array elems, char* enum_str) -{ - Elems = elems; - MinValue = 0; - bRegular = true; - nPrefixLength = 0; - - if (enum_str) - { - // Parse enum names from str - int i = 0; - while (cstr se = ParseNextEnum(enum_str)) - { - Elems[i++].Name = se; - } - } - - // Analyse names and values. - if (!elems.empty()) - { - cstr sPrefix = ""; - MinValue = Elems[0].Value; - for (int i = 0; i < elems.size(); i++) - { - if (Elems[i].Value != i + Elems[0].Value) - { - bRegular = false; - } - MinValue = min(MinValue, Elems[i].Value); - - // Find common prefix. - cstr sElem = Elems[i].Name; - if (*sElem) - { - if (!*sPrefix) - { - sPrefix = sElem; - nPrefixLength = static_cast(strlen(sPrefix)); - } - else - { - uint p = 0; - while (p < nPrefixLength && sElem[p] == sPrefix[p]) - { - p++; - } - nPrefixLength = p; - } - } - } - - // Ensure prefix is on underscore boundary. - while (nPrefixLength > 0 && sPrefix[nPrefixLength - 1] != '_') - { - nPrefixLength--; - } - } -} - -bool CEnumDef::MatchName(uint i, cstr str) const -{ - cstr name = Elems[i].Name; - if (*name && nPrefixLength) - { - if (azstricmp(name + nPrefixLength, str) == 0) - { - return true; - } - } - if (*name == '_') - { - name++; - } - return azstricmp(name, str) == 0; -} - -cstr CEnumDef::ToName(TValue value) const -{ - // Find matching element. - if (bRegular) - { - TValue index = value - MinValue; - if (index >= 0 && index < Elems.size()) - { - return Name((uint)index); - } - } - else - { - for (int i = 0; i < Elems.size(); i++) - { - if (Elems[i].Value == value) - { - return Name(i); - } - } - } - - // No match - return 0; -} - -LegacyDynArray* CEnumDef::SInit::s_pElems = 0; - -void CEnumDefUuid::Init(Array elems, char* enum_str) -{ - Elems = elems; - bRegular = false; - nPrefixLength = 0; - - if (enum_str) - { - // Parse enum names from str - int i = 0; - while (cstr se = ParseNextEnum(enum_str)) - { - Elems[i++].Name = se; - } - } - - // Analyse names and values. - if (!elems.empty()) - { - cstr sPrefix = ""; - for (int i = 0; i < elems.size(); i++) - { - // Find common prefix. - cstr sElem = Elems[i].Name; - if (*sElem) - { - if (!*sPrefix) - { - sPrefix = sElem; - nPrefixLength = static_cast(strlen(sPrefix)); - } - else - { - uint p = 0; - while (p < nPrefixLength && sElem[p] == sPrefix[p]) - { - p++; - } - nPrefixLength = p; - } - } - } - - // Ensure prefix is on underscore boundary. - while (nPrefixLength > 0 && sPrefix[nPrefixLength - 1] != '_') - { - nPrefixLength--; - } - } -} - -bool CEnumDefUuid::MatchName(uint i, cstr str) const -{ - cstr name = Elems[i].Name; - if (*name && nPrefixLength) - { - if (azstricmp(name + nPrefixLength, str) == 0) - { - return true; - } - } - if (*name == '_') - { - name++; - } - return azstricmp(name, str) == 0; -} - -cstr CEnumDefUuid::ToName(AZ::Uuid value) const -{ - // Find matching element. - for (int i = 0; i < Elems.size(); ++i) - { - if (Elems[i].Value == value) - { - return Elems[i].Name; - } - } - // No match - return 0; -} diff --git a/Code/Legacy/CryCommon/CryTypeInfo.h b/Code/Legacy/CryCommon/CryTypeInfo.h deleted file mode 100644 index dbc3fdb642..0000000000 --- a/Code/Legacy/CryCommon/CryTypeInfo.h +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - -// Description : Declaration of CTypeInfo and related types. - - -#ifndef CRYINCLUDE_CRYCOMMON_CRYTYPEINFO_H -#define CRYINCLUDE_CRYCOMMON_CRYTYPEINFO_H -#pragma once - -#include -#include "CryArray.h" -#include "Options.h" -#include "TypeInfo_decl.h" - -class ICrySizer; - -//--------------------------------------------------------------------------- -// Specify options for converting data to/from strings -struct FToString -{ - OPT_STRUCT(FToString) - OPT_VAR(bool, SkipDefault) // Omit default values on writing. - OPT_VAR(bool, NamedFields) // Add Name= text to sub-values. - OPT_VAR(bool, Sub) // Write sub-structures (internal usage). -}; - -struct FFromString -{ - OPT_STRUCT(FFromString) - OPT_VAR(bool, SkipEmpty) // Do not set values from empty strings (otherwise, set to zero). -}; - -// Specify which limits a variable has -enum ENumericLimit -{ - eLimit_Min, - eLimit_Max, - eLimit_SoftMin, - eLimit_SoftMax, - eLimit_MinIsInfinite, - eLimit_Step, -}; - -//--------------------------------------------------------------------------- -// Type info base class, and default implementation - -struct CTypeInfo -{ - cstr Name; - size_t Size; - size_t Alignment; - - CTypeInfo(cstr name, size_t size, size_t align) - : Name(name) - , Size(size) - , Alignment(align) {} - - virtual ~CTypeInfo() - {} - - // - // Inheritance. - // - virtual bool IsType(CTypeInfo const& Info) const - { return this == &Info; } - - template - bool IsType() const - { return IsType(TypeInfo((T*)0)); } - - // - // Data access interface. - // - - // Convert value to string. - virtual AZStd::string ToString([[maybe_unused]] const void* data, [[maybe_unused]] FToString flags = 0, [[maybe_unused]] const void* def_data = 0) const - { return ""; } - - // Write value from string, return success. - virtual bool FromString([[maybe_unused]] void* data, [[maybe_unused]] cstr str, [[maybe_unused]] FFromString flags = 0) const - { return false; } - - // Read and write values of a specified type. - virtual bool ToValue([[maybe_unused]] const void* data, [[maybe_unused]] void* value, [[maybe_unused]] const CTypeInfo& typeVal) const - { return false; } - - virtual bool FromValue([[maybe_unused]] void* data, [[maybe_unused]] const void* value, [[maybe_unused]] const CTypeInfo& typeVal) const - { return false; } - - // Templated interface to above functions. - template - bool ToValue(const void* data, T& value) const - { return ToValue(data, &value, TypeInfo(&value)); } - template - bool FromValue(void* data, const T& value) const - { return FromValue(data, &value, TypeInfo(&value)); } - - virtual bool ValueEqual(const void* data, const void* def_data = 0) const - { return ToString(data, FToString().SkipDefault(1), def_data).empty(); } - - virtual bool GetLimit([[maybe_unused]] ENumericLimit eLimit, [[maybe_unused]] float& fVal) const - { return false; } - - // Convert numeric formats from big-to-little endian or vice versa. - // Swaps bitfield order as well (which may be separate from integer bit order). - virtual void SwapEndian(void* pData, size_t nCount, bool bWriting) const; - - // Track memory used by any internal structures (not counting object size itself). - // Add to CrySizer as needed, return remaining mem count. - virtual void GetMemoryUsage([[maybe_unused]] ICrySizer* pSizer, [[maybe_unused]] const void* data) const - {} - - // - // Structure interface. - // - struct CVarInfo - { - const CTypeInfo& Type; // Info for type of variable. - cstr Name; // Display name of variable. - cstr Attrs; // Var-specific attribute string, of form: - // "" for each attr, concatenated. - // Remaining text considered as comment. - uint32 Offset; // Offset in bytes from struct start. - uint32 ArrayDim : 22, // Number of array elements, or bits if bitfield. - bBaseClass : 1, // Sub-var is actually a base class. - bBitfield : 1, // Var is a bitfield, ArrayDim is number of bits. - BitOffset : 6, // Additional offset in bits for bitfields. - // Bit offset is computed in declaration order; on some platforms, it goes high to low. - BitWordWidth : 2; // Width of bitfield = 1 byte << BitWordWidth - - - // Accessors. - cstr GetName() const { return Name; } - size_t GetDim() const { return bBitfield ? 1 : ArrayDim; } - size_t GetSize() const { return bBitfield ? (size_t)1 << BitWordWidth : Type.Size* ArrayDim; } - size_t GetElemSize() const { return bBitfield ? (size_t)1 << BitWordWidth : Type.Size; } - size_t GetBits() const { return bBitfield ? ArrayDim : ArrayDim* Type.Size* 8; } - bool IsBaseClass() const { return bBaseClass; } - bool IsInline() const - { - if (bBaseClass && Offset == 0) - { - const CVarInfo* pFirst = Type.NextSubVar(0); - if (pFirst) - { - return pFirst->IsBaseClass(); - } - } - return false; - } - - bool GetLimit(ENumericLimit eLimit, float& fVal) const - { - return Type.GetLimit(eLimit, fVal); - } - - // Useful functions. - void* GetAddress(void* base) const - { - return (char*)base + Offset; - } - const void* GetAddress(const void* base) const - { - return (const char*)base + Offset; - } - bool FromString(void* base, cstr str, FFromString flags = 0) const - { - assert(!bBitfield); - return Type.FromString((char*)base + Offset, str, flags); - } - AZStd::string ToString(const void* base, FToString flags = 0, const void* def_base = 0) const - { - assert(!bBitfield); - return Type.ToString((const char*)base + Offset, flags, def_base ? (const char*)def_base + Offset : 0); - } - - // Attribute access. Not fast. - bool GetAttr(cstr name) const; - bool GetAttr(cstr name, float& val) const; - bool GetAttr(cstr name, AZStd::string& val) const; - - // Comment, excluding attributes. - cstr GetComment() const; - }; - - // Structure var iteration. - virtual CVarInfo const* NextSubVar([[maybe_unused]] CVarInfo const* pPrev, [[maybe_unused]] bool bRecurseBase = false) const - { return 0; } - inline bool HasSubVars() const - { return NextSubVar(0) != 0; } - #define AllSubVars(pVar, Info) \ - (const CTypeInfo::CVarInfo* pVar = (Info).NextSubVar(0); pVar; pVar = (Info).NextSubVar(pVar)) - - // Named var search. - virtual const CVarInfo* FindSubVar([[maybe_unused]] cstr name) const - { return 0; } - - virtual CTypeInfo const* const* NextTemplateType([[maybe_unused]] CTypeInfo const* const* pPrev) const - { return 0; } - inline bool IsTemplate() const - { return NextTemplateType(0) != 0; } - - // - // String enumeration interface. - // Return sequential strings in enumeration, then 0 when out of range. - // String/int conversion is handled by ToString/FromString. - // - virtual cstr EnumElem([[maybe_unused]] uint nIndex) const { return 0; } -}; - - -#endif // CRYINCLUDE_CRYCOMMON_CRYTYPEINFO_H diff --git a/Code/Legacy/CryCommon/Cry_Camera.h b/Code/Legacy/CryCommon/Cry_Camera.h index 4d33260c44..852467d787 100644 --- a/Code/Legacy/CryCommon/Cry_Camera.h +++ b/Code/Legacy/CryCommon/Cry_Camera.h @@ -17,7 +17,6 @@ //DOC-IGNORE-BEGIN #include #include -#include //DOC-IGNORE-END ////////////////////////////////////////////////////////////////////// @@ -546,7 +545,7 @@ public: ILINE void SetMatrixNoUpdate(const Matrix34& mat) { assert(mat.IsOrthonormal()); m_Matrix = mat; }; ILINE const Matrix34& GetMatrix() const { return m_Matrix; }; ILINE Vec3 GetViewdir() const { return m_Matrix.GetColumn1(); }; - + ILINE void SetEntityRotation(const Quat& entityRot) { m_entityRot = entityRot; } ILINE Quat GetEntityRotation() { return m_entityRot; } ILINE void SetEntityPos(const Vec3& entityPos) { m_entityPos = entityPos; } @@ -626,11 +625,6 @@ public: uint8 IsAABBVisible_EH(const ::AABB& aabb, bool* pAllInside) const; uint8 IsAABBVisible_EH(const ::AABB& aabb) const; - // Multi-camera - bool IsAABBVisible_EHM(const ::AABB& aabb, bool* pAllInside) const; - bool IsAABBVisible_EM(const ::AABB& aabb) const; - bool IsAABBVisible_FM(const ::AABB& aabb) const; - //OBB-frustum test bool IsOBBVisible_F(const Vec3& wpos, const OBB& obb) const; uint8 IsOBBVisible_FH(const Vec3& wpos, const OBB& obb) const; @@ -648,7 +642,6 @@ public: SetFrustum(640, 480); m_zrangeMin = 0.0f; m_zrangeMax = 1.0f; - m_pMultiCamera = NULL; m_pPortal = NULL; m_JustActivated = 0; m_nPosX = m_nPosY = m_nSizeX = m_nSizeY = 0; @@ -704,8 +697,8 @@ private: Vec3 m_edge_flt; // this is the left/upper vertex of the far-clip-plane f32 m_asymLeft, m_asymRight, m_asymBottom, m_asymTop; // Shift to create asymmetric frustum (only used for GPU culling of tessellated objects) - f32 m_asymLeftProj, m_asymRightProj, m_asymBottomProj, m_asymTopProj; - f32 m_asymLeftFar, m_asymRightFar, m_asymBottomFar, m_asymTopFar; + f32 m_asymLeftProj, m_asymRightProj, m_asymBottomProj, m_asymTopProj; + f32 m_asymLeftFar, m_asymRightFar, m_asymBottomFar, m_asymTopFar; //usually we update these values every frame (they depend on m_Matrix) Vec3 m_cltp, m_crtp, m_clbp, m_crbp; //this are the 4 vertices of the projection-plane in cam-space @@ -774,7 +767,6 @@ public: uint16 x1, y1, x2, y2; }; ScissorInfo m_ScissorInfo; - class PodArray* m_pMultiCamera; // maybe used for culling instead of this camera Vec3 m_OccPosition; //Position for calculate occlusions (needed for portals rendering) inline const Vec3& GetOccPos() const { return(m_OccPosition); } @@ -930,7 +922,7 @@ inline void CCamera::SetFrustum(int nWidth, int nHeight, f32 FOV, f32 nearplane, //Apply asym shift to the camera frustum - Necessary for properly culling tessellated objects in VR //These are applied in UpdateFrustum to the camera space frustum planes - //Can't apply asym shift to frustum edges here. That would only apply to the top left corner + //Can't apply asym shift to frustum edges here. That would only apply to the top left corner //rather than the whole frustum. It would also interfere with shadow map application //m_asym is at the near plane, we want it at the projection plane too @@ -1576,102 +1568,6 @@ inline uint8 CCamera::IsAABBVisible_EH(const AABB& aabb) const return AdditionalCheck(aabb); //result is either "exclusion" or "overlap" } -// Description: -// Makes culling taking into account presence of m_pMultiCamera -// If m_pMultiCamera exists - object is visible if at least one of cameras see's it -// -// return values: -// true - box visible -// true - not visible -inline bool CCamera::IsAABBVisible_EHM(const AABB& aabb, bool* pAllInside) const -{ - assert(pAllInside && *pAllInside == false); - - if (!m_pMultiCamera) // use main camera - { - return IsAABBVisible_EH(aabb, pAllInside) != CULL_EXCLUSION; - } - - bool bVisible = false; - - for (int i = 0; i < m_pMultiCamera->Count(); i++) - { - bool bAllIn = false; - - if (m_pMultiCamera->GetAt(i).IsAABBVisible_EH(aabb, &bAllIn)) - { - bVisible = true; - - // don't break here always because another camera may include bbox completely - if (bAllIn) - { - *pAllInside = true; - break; - } - } - } - - return bVisible; -} - -// Description: -// Makes culling taking into account presence of m_pMultiCamera -// If m_pMultiCamera exists - object is visible if at least one of cameras see's it -// -// return values: -// true - box visible -// true - not visible -ILINE bool CCamera::IsAABBVisible_EM(const AABB& aabb) const -{ - if (!m_pMultiCamera) // use main camera - { - return IsAABBVisible_E(aabb) != CULL_EXCLUSION; - } - - // check several parallel cameras - object is visible if at least one camera see's it - - for (int i = 0; i < m_pMultiCamera->Count(); i++) - { - if (m_pMultiCamera->GetAt(i).IsAABBVisible_E(aabb)) - { - return true; - } - } - - return false; -} - - -// Description: -// Makes culling taking into account presence of m_pMultiCamera -// If m_pMultiCamera exists - object is visible if at least one of cameras see's it -// -// return values: -// true - box visible -// true - not visible -ILINE bool CCamera::IsAABBVisible_FM(const AABB& aabb) const -{ - PrefetchLine(&aabb, sizeof(AABB)); - - if (!m_pMultiCamera) // use main camera - { - return IsAABBVisible_F(aabb) != CULL_EXCLUSION; - } - - // check several parallel cameras - object is visible if at least one camera see's it - - for (int i = 0; i < m_pMultiCamera->Count(); i++) - { - if (m_pMultiCamera->GetAt(i).IsAABBVisible_F(aabb)) - { - return true; - } - } - - return false; -} - - // Description diff --git a/Code/Legacy/CryCommon/Cry_Color.h b/Code/Legacy/CryCommon/Cry_Color.h index abb79c6662..4f00f0c373 100644 --- a/Code/Legacy/CryCommon/Cry_Color.h +++ b/Code/Legacy/CryCommon/Cry_Color.h @@ -14,9 +14,9 @@ #define CRYINCLUDE_CRYCOMMON_CRY_COLOR_H #pragma once -#include #include #include +#include "Cry_Math.h" ILINE float FClamp(float X, float Min, float Max) { @@ -362,8 +362,6 @@ struct Color_tpl AZStd::array primitiveArray = { { r, g, b, a } }; return primitiveArray; } - - AUTO_STRUCT_INFO }; diff --git a/Code/Legacy/CryCommon/Cry_Geo.h b/Code/Legacy/CryCommon/Cry_Geo.h index f8a356c66f..95213c62dc 100644 --- a/Code/Legacy/CryCommon/Cry_Geo.h +++ b/Code/Legacy/CryCommon/Cry_Geo.h @@ -54,7 +54,6 @@ enum EGeomForm MaxGeomForm }; -AUTO_TYPE_INFO(EGeomForm) enum EGeomType { @@ -63,7 +62,6 @@ enum EGeomType GeomType_Physics, GeomType_Render, }; -AUTO_TYPE_INFO(EGeomType) struct PosNorm { @@ -104,7 +102,6 @@ struct RectF , h(1) { } - AUTO_STRUCT_INFO }; struct RectI @@ -705,8 +702,6 @@ struct AABB result.Add(c.mTip); return result; } - - AUTO_STRUCT_INFO }; ILINE bool IsEquivalent(const AABB& a, const AABB& b, float epsilon = VEC_EPSILON) diff --git a/Code/Legacy/CryCommon/Cry_GeoOverlap.h b/Code/Legacy/CryCommon/Cry_GeoOverlap.h deleted file mode 100644 index 039f292f5b..0000000000 --- a/Code/Legacy/CryCommon/Cry_GeoOverlap.h +++ /dev/null @@ -1,1982 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - -// Description : Common overlap-tests - - -#ifndef CRYINCLUDE_CRYCOMMON_CRY_GEOOVERLAP_H -#define CRYINCLUDE_CRYCOMMON_CRY_GEOOVERLAP_H -#pragma once - -#include -#include - -namespace Distance -{ - template - ILINE F Point_TriangleSq(const Vec3_tpl& p, const Triangle_tpl& t); - template - ILINE F Point_Lineseg2DSq(Vec3_tpl p, Lineseg lineseg, F& fT); - simdf Point_TriangleByPointsSq(const hwvec3& p, const hwvec3& t0, const hwvec3& t1, const hwvec3& t2); -} - - -namespace Overlap { - ILINE void FINDMINMAX(const f32 x0, const f32 x1, const f32 x2, f32& min_value, f32& max_value) - { - min_value = max_value = x0; - min_value = min(x1, min_value); - max_value = max(x1, max_value); - min_value = min(x2, min_value); - max_value = max(x2, max_value); - } - - inline bool Lineseg_AABB2D(const Lineseg&, const AABB&); - ILINE bool AABB_AABB2D(const AABB&, const AABB&); - - //////////////////////////////////////////////////////////////// - // Checks if the point is inside an AABB - /* inline bool Point_AABB(const Vec3 &p, const Vec3 &mins,const Vec3 &maxs) - { - if ((p.x>=mins.x && p.x<=maxs.x) && (p.y>=mins.y && p.y<=maxs.y) && (p.z>=mins.z && p.z<=maxs.z)) return (true); - return (false); - }*/ - - // Description: - // Checks if the point is inside an AABB - // The min value of the AABB is inclusive - // The max value of the AABB is exclusive - ILINE bool Point_AABB(const Vec3& p, const AABB& aabb) - { - return ((p.x >= aabb.min.x && p.x < aabb.max.x) && (p.y >= aabb.min.y && p.y < aabb.max.y) && (p.z >= aabb.min.z && p.z < aabb.max.z)); - } - - // Description: - // Checks if the point is inside a 2D AABB - // The min value of the AABB is inclusive - // The max value of the AABB is exclusive - template - ILINE bool Point_AABB2D(const PtType& p, const AABB& aabb) - { - return ((p.x >= aabb.min.x && p.x < aabb.max.x) && (p.y >= aabb.min.y && p.y < aabb.max.y)); - } - - // Description: - // Checks if the point is inside an AABB - // The min and max value of the AABB is inclusive - ILINE bool Point_AABB_MaxInclusive(const Vec3& p, const AABB& aabb) - { - return ((p.x >= aabb.min.x && p.x <= aabb.max.x) && (p.y >= aabb.min.y && p.y <= aabb.max.y) && (p.z >= aabb.min.z && p.z <= aabb.max.z)); - } - - // Description: - // Checks if the point is inside a 2D AABB - // The min and max value of the AABB is inclusive - template - ILINE bool Point_AABB2D_MaxInclusive(const PtType& p, const AABB& aabb) - { - return ((p.x >= aabb.min.x && p.x <= aabb.max.x) && (p.y >= aabb.min.y && p.y <= aabb.max.y)); - } - - // Description: - // Checks if a point is inside an OBB. - // Example: - // bool result=Overlap::Point_OBB( point, obb ); - ILINE bool Point_OBB(const Vec3& p, const Vec3& wpos, const OBB& obb) - { - AABB aabb = AABB(obb.c - obb.h, obb.c + obb.h); - Vec3 t = (p - wpos) * obb.m33; - return ((t.x >= aabb.min.x && t.x <= aabb.max.x) && (t.y >= aabb.min.y && t.y <= aabb.max.y) && (t.z >= aabb.min.z && t.z <= aabb.max.z)); - } - - // Description: - // Checks if a point is inside a sphere. - // Example: - // bool result=Overlap::Point_Sphere( point, sphere ); - ILINE bool Point_Sphere(const Vec3& p, const ::Sphere& s) - { - Vec3 distc = p - s.center; - f32 sqrad = s.radius * s.radius; - return (sqrad > (distc | distc)); - } - - /// Two line segments, in 2D (ignore z) - inline bool Lineseg_Lineseg2D(const Lineseg& lineA, const Lineseg& lineB) - { - const float Epsilon = 0.0000001f; - - Vec3 delta = lineB.start - lineA.start; - - Vec3 dirA = lineA.end - lineA.start; - Vec3 dirB = lineB.end - lineB.start; - - float det = dirA.x * dirB.y - dirA.y * dirB.x; - float detA = delta.x * dirB.y - delta.y * dirB.x; - float detB = delta.x * dirA.y - delta.y * dirA.x; - - float absDet = fabs_tpl(det); - - if (absDet >= Epsilon) - { - float invDet = 1.0f / det; - - float a = detA * invDet; - float b = detB * invDet; - - if ((a > 1.0f) || (a < 0.0f) || (b > 1.0f) || (b < 0.0f)) - { - return false; - } - } - else - { - return false; - } - - return true; - } - - - - /// Check if a point is within a polygon, in 2D (i.e. ignoring z coordinate) - /// The VecContainer should be a container of Vec3_tpl such that we can traverse - /// it using iterators. - /// - /// This works by checking all the lines that start/end above/below the point - /// and counting how many have the point on the right/left side. If the - /// point is inside, then left/right counts should be odd - if outside then - /// even. If it's on the edge then this algorithm will return an arbitrary - /// result. This is basically the same as casting a ray horizontally and - /// counting the intersections. - /// Don't mess with putting tolerances etc in this code, or chaning the < - /// to <= etc in case you're worried about the "ray" going through a vertex. - /// the only issue is when the point is on the edge - if you're worried about - /// that then use the separate function that indicates if a point is within - /// a certain tolerance of an edge. - template - inline bool Point_Polygon2D(const PtType& p, const VecContainer& polygon, const AABB* pAABBPolygon = 0) - { - if (pAABBPolygon && !Overlap::Point_AABB2D(p, *pAABBPolygon)) - { - return false; - } - - int count = 0; - - typename VecContainer::const_iterator li, linext; - typename VecContainer::const_iterator liend = polygon.end(); - for (li = polygon.begin(); li != liend; ++li) - { - linext = li; - ++linext; - if (linext == liend) - { - linext = polygon.begin(); - } - const PtType& l0 = *li; - const PtType& l1 = *linext; - - if ((((l1.y <= p.y) && (p.y < l0.y)) || - ((l0.y <= p.y) && (p.y < l1.y))) && - (p.x < (l0.x - l1.x) * (p.y - l1.y) / (l0.y - l1.y) + l1.x)) - { - count = !count; - } - } - return (0 != count); - } - - template - inline bool Point_Polygon2D(const PtType& p, const PtType* polygon, size_t vertexCount, const AABB* pAABBPolygon = 0) - { - if (pAABBPolygon && !Overlap::Point_AABB2D(p, *pAABBPolygon)) - { - return false; - } - - bool count = false; - - for (size_t i = 0; i < vertexCount; ++i) - { - const PtType l0 = polygon[i % vertexCount]; - const PtType l1 = polygon[(i + 1) % vertexCount]; - - if ((((l1.y <= p.y) && (p.y < l0.y)) || - ((l0.y <= p.y) && (p.y < l1.y))) && - (p.x < (l0.x - l1.x) * (p.y - l1.y) / (l0.y - l1.y) + l1.x)) - { - count = !count; - } - } - - return count; - } - - - template - inline bool Circle_Polygon2D(const Vec3_tpl& p, F radius, const VecContainer& polygon) - { - if (Overlap::Point_Polygon2D(p, polygon)) - { - return true; - } - typename VecContainer::const_iterator li, linext; - typename VecContainer::const_iterator liend = polygon.end(); - for (li = polygon.begin(); li != liend; ++li) - { - linext = li; - ++linext; - if (linext == liend) - { - linext = polygon.begin(); - } - const Vec3_tpl& l0 = *li; - const Vec3_tpl& l1 = *linext; - float junk; - if (Distance::Point_Lineseg2DSq(p, Lineseg(l0, l1), junk) < square(radius)) - { - return true; - } - } - return false; - } - /// Checks if a line segment overlaps a polygon (defined by a container of sorted - /// points) in 2D (ignoring z). If you know the polygon AABB pass it in (z is ignored) - template - inline bool Lineseg_Polygon2D(const Lineseg& lineseg, - const VecContainer& polygon, - const AABB* pAABBPolygon = 0) - { - if (pAABBPolygon && !Overlap::Lineseg_AABB2D(lineseg, *pAABBPolygon)) - { - return false; - } - - typename VecContainer::const_iterator it; - for (it = polygon.begin(); it != polygon.end(); ++it) - { - typename VecContainer::const_iterator itNext = it; - ++itNext; - if (itNext == polygon.end()) - { - itNext = polygon.begin(); - } - - Lineseg polySeg(*it, *itNext); - if (Lineseg_Lineseg2D(lineseg, polySeg)) - { - return true; - } - } - return false; - } - - /// Checks for overlap of two polygons in 2D (ignoring z) - template - inline bool Polygon_Polygon2D(const VecContainerA& polygonA, const VecContainerB& polygonB, - const AABB* pAABBA = 0, const AABB* pAABBB = 0) - { - const typename VecContainerA::const_iterator itEndA = polygonA.end(); - const typename VecContainerB::const_iterator itEndB = polygonB.end(); - typename VecContainerA::const_iterator itA; - typename VecContainerB::const_iterator itB; - - AABB aabbA, aabbB; - if (!pAABBA) - { - pAABBA = &aabbA; - aabbA.Reset(); - for (itA = polygonA.begin(); itA != itEndA; ++itA) - { - aabbA.Add(*itA); - } - } - if (!pAABBB) - { - pAABBB = &aabbB; - aabbB.Reset(); - for (itB = polygonB.begin(); itB != itEndB; ++itB) - { - aabbB.Add(*itB); - } - } - - // AABB - if (!Overlap::AABB_AABB2D(*pAABBA, *pAABBB)) - { - return false; - } - - // points of A in B - for (itA = polygonA.begin(); itA != itEndA; ++itA) - { - if (Point_Polygon2D(*itA, polygonB, pAABBB)) - { - return true; - } - } - // points of B in A - for (itB = polygonB.begin(); itB != itEndB; ++itB) - { - if (Point_Polygon2D(*itB, polygonA, pAABBA)) - { - return true; - } - } - // segments of one A against B - for (itA = polygonA.begin(); itA != itEndA; ++itA) - { - typename VecContainerA::const_iterator itNext = itA; - ++itNext; - if (itNext == itEndA) - { - itNext = polygonA.begin(); - } - if (Lineseg_Polygon2D(Lineseg(*itA, *itNext), polygonB, pAABBB)) - { - return true; - } - } - return false; - } - - - /// Checks if a triangle (defined by three vertices) overlaps a polygon (defined - /// by a container of sorted points), all in 2D only (ignoring z). - template - inline bool Triangle_Polygon2D(const Vec3_tpl& p0, const Vec3_tpl& p1, const Vec3_tpl& p2, - const VecContainer& polygon) - { - // Check for triangle points within the poly - if (Point_Polygon2D(p0, polygon)) - { - return true; - } - if (Point_Polygon2D(p1, polygon)) - { - return true; - } - if (Point_Polygon2D(p2, polygon)) - { - return true; - } - - // check the poly points against the triangle - static std::vector triangle; - triangle.clear(); - triangle.push_back(p0); - triangle.push_back(p1); - triangle.push_back(p2); - - typename VecContainer::const_iterator it; - for (it = polygon.begin(); it != polygon.end(); ++it) - { - if (Point_Polygon2D(*it, triangle)) - { - return true; - } - } - - // finally check the edges - if (Overlap::Lineseg_Polygon2D(Lineseg(p0, p1), polygon)) - { - return true; - } - if (Overlap::Lineseg_Polygon2D(Lineseg(p1, p2), polygon)) - { - return true; - } - if (Overlap::Lineseg_Polygon2D(Lineseg(p2, p0), polygon)) - { - return true; - } - return false; - } - - //----------------------------------------------------------------------------------------- - - - //! check if a Lineseg and a Sphere overlap - inline bool Lineseg_Sphere(const Lineseg& ls, const ::Sphere& s) - { - float radius2 = s.radius * s.radius; - - //check if one of the two edpoints of the line is inside the sphere - Vec3 diff = ls.end - s.center; - if (diff.x * diff.x + diff.y * diff.y + diff.z * diff.z <= radius2) - { - return true; - } - - Vec3 AC = s.center - ls.start; - if (AC.x * AC.x + AC.y * AC.y + AC.z * AC.z <= radius2) - { - return true; - } - - //check distance from the sphere to the line - Vec3 AB = ls.end - ls.start; - - float r = (AC.x * AB.x + AC.y * AB.y + AC.z * AB.z) / (AB.x * AB.x + AB.y * AB.y + AB.z * AB.z); - - //projection falls outside the line - if (r < 0 || r > 1) - { - return false; - } - - //check if the distance from the line to the center of the sphere is less than radius - Vec3 point = ls.start + r * AB; - if ((point.x - s.center.x) * (point.x - s.center.x) + (point.y - s.center.y) * (point.y - s.center.y) + (point.z - s.center.z) * (point.z - s.center.z) > radius2) - { - return false; - } - - return true; - } - - - /*! - * we use the SEPARATING AXIS TEST to check if a Linesegment overlap an AABB. - * - * Example: - * bool result=Overlap::Lineseg_AABB( ls, pos,aabb ); - */ - inline bool Lineseg_AABB (const Lineseg& ls, const AABB& aabb) - { - //calculate the half-length-vectors of the AABB - Vec3 h = (aabb.max - aabb.min) * 0.5f; - //"t" is the transfer-vector from one center to the other - Vec3 t = (ls.start + ls.end) * 0.5f - (aabb.max + aabb.min) * 0.5f; - //calculate line-direction - Vec3 ld = (ls.end - ls.start) * 0.5f; - if (fabsf(t.x) > (h.x + fabsf(ld.x))) - { - return 0; - } - if (fabsf(t.y) > (h.y + fabsf(ld.y))) - { - return 0; - } - if (fabsf(t.z) > (h.z + fabsf(ld.z))) - { - return 0; - } - if (fabsf(t.z * ld.y - t.y * ld.z) > (fabsf(h.y * ld.z) + fabsf(h.z * ld.y))) - { - return 0; - } - if (fabsf(t.x * ld.z - t.z * ld.x) > (fabsf(h.x * ld.z) + fabsf(h.z * ld.x))) - { - return 0; - } - if (fabsf(t.y * ld.x - t.x * ld.y) > (fabsf(h.x * ld.y) + fabsf(h.y * ld.x))) - { - return 0; - } - return 1; //no separating axis found, objects overlap - } - - /// 2D seaparating axis test - ignores z - inline bool Lineseg_AABB2D (const Lineseg& ls, const AABB& aabb) - { - //calculate the half-length-vectors of the AABB - Vec3 h = (aabb.max - aabb.min) * 0.5f; - //"t" is the transfer-vector from one center to the other - Vec3 t = (ls.start + ls.end) * 0.5f - (aabb.max + aabb.min) * 0.5f; - //calculate line-direction - Vec3 ld = (ls.end - ls.start) * 0.5f; - if (fabsf(t.x) > (h.x + fabsf(ld.x))) - { - return 0; - } - if (fabsf(t.y) > (h.y + fabsf(ld.y))) - { - return 0; - } - if (fabsf(t.y * ld.x - t.x * ld.y) > (fabsf(h.x * ld.y) + fabsf(h.y * ld.x))) - { - return 0; - } - return 1; //no separating axis found, objects overlap - } - - - - /*! - * we use the SEPARATING AXIS TEST to check if two OBB's overlap. - * - * Example: - * bool result=Overlap::Lineseg_OBB( lineseg, pos,obb ); - */ - inline bool Lineseg_OBB (const Lineseg& ls, const Vec3& pos, const OBB& obb) - { - //the new center-position of Lineseg and OBB in world-space - Vec3 wposobb = obb.m33 * obb.c + pos; - Vec3 wposls = (ls.start + ls.end) * 0.5f; - //"t" is the transfer-vector from one center to the other - Vec3 t = (wposls - wposobb) * obb.m33; - //calculate line-direction in local obb-space - Vec3 ld = ((ls.end - ls.start) * obb.m33) * 0.5f; - if (fabsf(t.x) > (obb.h.x + fabsf(ld.x))) - { - return 0; - } - if (fabsf(t.y) > (obb.h.y + fabsf(ld.y))) - { - return 0; - } - if (fabsf(t.z) > (obb.h.z + fabsf(ld.z))) - { - return 0; - } - if (fabsf(t.z * ld.y - t.y * ld.z) > (fabsf(obb.h.y * ld.z) + fabsf(obb.h.z * ld.y))) - { - return 0; - } - if (fabsf(t.x * ld.z - t.z * ld.x) > (fabsf(obb.h.x * ld.z) + fabsf(obb.h.z * ld.x))) - { - return 0; - } - if (fabsf(t.y * ld.x - t.x * ld.y) > (fabsf(obb.h.x * ld.y) + fabsf(obb.h.y * ld.x))) - { - return 0; - } - return 1; //no separating axis found, objects overlap - } - - - - - /*! - * - * overlap-test between a line and a triangle. - * IMPORTANT: this is a single-sided test. That means its not enough - * that the triangle and line overlap, its also important that the triangle - * is "visible" when you are looking along the line-direction. - * - * If you need a double-sided test, you'll have to call this function twice with - * reversed order of triangle vertices. - * - * return values - * return "true" if line and triangle overlap. - * - */ - inline bool Line_Triangle(const Line& line, const Vec3& v0, const Vec3& v1, const Vec3& v2) - { - const float Epsilon = 0.0000001f; - - Vec3 edgeA = v1 - v0; - Vec3 edgeB = v2 - v0; - - Vec3 dir = line.direction; - - Vec3 p = dir.Cross(edgeA); - Vec3 t = line.pointonline - v0; - Vec3 q = t.Cross(edgeB); - - float dot = edgeB.Dot(p); - - float u = t.Dot(p); - float v = dir.Dot(q); - - float DotGreaterThanEpsilon = dot - Epsilon; - float VGreaterEqualThanZero = v; - float UGreaterEqualThanZero = u; - float UVLessThanDot = dot - (u + v); - float ULessThanDot = dot - u; - - float UVGreaterEqualThanZero = (float)fsel(VGreaterEqualThanZero, UGreaterEqualThanZero, VGreaterEqualThanZero); - float UUVLessThanDot = (float)fsel(UVLessThanDot, ULessThanDot, UVLessThanDot); - float BothGood = (float)fsel(UVGreaterEqualThanZero, UUVLessThanDot, UVGreaterEqualThanZero); - float AllGood = (float)fsel(DotGreaterThanEpsilon, BothGood, DotGreaterThanEpsilon); - - return AllGood >= 0.0f; - } - - - /*! - * - * overlap-test between a ray and a triangle. - * IMPORTANT: this is a single-sided test. That means its not sufficient - * that the triangle and ray overlap, its also important that the triangle - * is "visible" when you are looking from the origin along the ray-direction. - * - * If you need a double-sided test, you'll have to call this function twice with - * reversed order of triangle vertices. - * - * return values - * return "true" if ray and triangle overlap. - */ - inline bool Ray_Triangle(const Ray& ray, const Vec3& v0, const Vec3& v1, const Vec3& v2) - { - const float Epsilon = 0.0000001f; - - Vec3 edgeA = v1 - v0; - Vec3 edgeB = v2 - v0; - - Vec3 dir = ray.direction; - - Vec3 p = dir.Cross(edgeA); - Vec3 t = ray.origin - v0; - Vec3 q = t.Cross(edgeB); - - float dot = edgeB.Dot(p); - - float u = t.Dot(p); - float v = dir.Dot(q); - - float DotGreaterThanEpsilon = dot - Epsilon; - float VGreaterEqualThanZero = v; - float UGreaterEqualThanZero = u; - float UVLessThanDot = dot - (u + v); - float ULessThanDot = dot - u; - - float UVGreaterEqualThanZero = (float)fsel(VGreaterEqualThanZero, UGreaterEqualThanZero, VGreaterEqualThanZero); - float UUVLessThanDot = (float)fsel(UVLessThanDot, ULessThanDot, UVLessThanDot); - float BothGood = (float)fsel(UVGreaterEqualThanZero, UUVLessThanDot, UVGreaterEqualThanZero); - float AllGood = (float)fsel(DotGreaterThanEpsilon, BothGood, DotGreaterThanEpsilon); - - if (AllGood < 0.0f) - { - return false; - } - - float dt = edgeA.Dot(q) / dot; - - Vec3 result = (dir * dt) + ray.origin; - - float AfterStart = (result - ray.origin).Dot(dir); - - return AfterStart >= 0.0f; - } - - /*---------------------------------------------------------------------------------- - * Sphere_AABB - * Sphere and AABB are assumed to be in the same space - * - * Example: - * bool result=Overlap::Sphere_AABB_Inside( sphere, aabb ); - * - * 0 = no overlap - * 1 = overlap - *----------------------------------------------------------------------------------*/ - ILINE bool Sphere_AABB(const ::Sphere& s, const AABB& aabb) - { - Vec3 center(s.center); - - Vec3 aabb_min(aabb.min); - Vec3 aabb_max(aabb.max); - - float radiusSq = s.radius * s.radius; - - float x = (float)fsel(aabb_min.x - center.x, center.x - aabb_min.x, fsel(center.x - aabb_max.x, center.x - aabb_max.x, 0.0f)); - float y = (float)fsel(aabb_min.y - center.y, center.y - aabb_min.y, fsel(center.y - aabb_max.y, center.y - aabb_max.y, 0.0f)); - float z = (float)fsel(aabb_min.z - center.z, center.z - aabb_min.z, fsel(center.z - aabb_max.z, center.z - aabb_max.z, 0.0f)); - - return (x * x + y * y + z * z) < radiusSq; - } - - // As Sphere_AABB but ignores z parts - ILINE bool Sphere_AABB2D(const ::Sphere& s, const AABB& aabb) - { - Vec3 center(s.center); - - Vec3 aabb_min(aabb.min); - Vec3 aabb_max(aabb.max); - - float radiusSq = s.radius * s.radius; - - float x = (float)fsel(aabb_min.x - center.x, center.x - aabb_min.x, fsel(center.x - aabb_max.x, center.x - aabb_max.x, 0.0f)); - float y = (float)fsel(aabb_min.y - center.y, center.y - aabb_min.y, fsel(center.y - aabb_max.y, center.y - aabb_max.y, 0.0f)); - - return (x * x + y * y) < radiusSq; - } - - - /*! - * - * conventional method to check if a Sphere and an AABB overlap, - * or if the Sphere is completely inside the AABB. - * Sphere and AABB are assumed to be in the same space - * - * Example: - * bool result=Overlap::Sphere_AABB_Inside( sphere, aabb ); - * - * return values: - * 0x00 = no overlap - * 0x01 = Sphere and AABB overlap - * 0x02 = Sphere in inside AABB - */ - ILINE char Sphere_AABB_Inside(const ::Sphere& s, const AABB& aabb) - { - if (Sphere_AABB(s, aabb)) - { - Vec3 amin = aabb.min - s.center; - Vec3 amax = aabb.max - s.center; - if (amin.x >= (-s.radius)) - { - return 1; - } - if (amin.y >= (-s.radius)) - { - return 1; - } - if (amin.z >= (-s.radius)) - { - return 1; - } - if (amax.x <= (+s.radius)) - { - return 1; - } - if (amax.y <= (+s.radius)) - { - return 1; - } - if (amax.z <= (+s.radius)) - { - return 1; - } - //yes, its inside - return 2; - } - return 0; - } - - //---------------------------------------------------------------------------------- - // Sphere_OBB - // VERY IMPORTANT: Sphere is assumed to be in the space of the OBB, otherwise it won't work - // - //--- 0 = no overlap --------------------------- - //--- 1 = overlap ----------------- - //---------------------------------------------------------------------------------- - inline bool Sphere_OBB(const ::Sphere& s, const OBB& obb) - { - //first we transform the sphere-center into the AABB-space of the OBB - Vec3 SphereInOBBSpace = s.center * obb.m33; - //the rest ist the same as the "Overlap::Sphere_AABB" calculation - float quatradius = s.radius * s.radius; - Vec3 quat(0, 0, 0); - AABB aabb = AABB(obb.c - obb.h, obb.c + obb.h); - if (SphereInOBBSpace.x < aabb.min.x) - { - quat.x = SphereInOBBSpace.x - aabb.min.x; - } - else if (SphereInOBBSpace.x > aabb.max.x) - { - quat.x = SphereInOBBSpace.x - aabb.max.x; - } - if (SphereInOBBSpace.y < aabb.min.y) - { - quat.y = SphereInOBBSpace.y - aabb.min.y; - } - else if (SphereInOBBSpace.y > aabb.max.y) - { - quat.y = SphereInOBBSpace.y - aabb.max.y; - } - if (SphereInOBBSpace.z < aabb.min.z) - { - quat.z = SphereInOBBSpace.z - aabb.min.z; - } - else if (SphereInOBBSpace.z > aabb.max.z) - { - quat.z = SphereInOBBSpace.z - aabb.max.z; - } - return((quat | quat) < quatradius); - } - - - //---------------------------------------------------------------------------------- - // Sphere_Sphere overlap test - // - //--- 0 = no overlap --------------------------- - //--- 1 = overlap ----------------- - //---------------------------------------------------------------------------------- - inline bool Sphere_Sphere(const ::Sphere& s1, const ::Sphere& s2) - { - Vec3 distc = s1.center - s2.center; - f32 sqrad = (s1.radius + s2.radius) * (s1.radius + s2.radius); - return (sqrad > (distc | distc)); - } - - ILINE bool HWVSphere_HWVSphere(const HWVSphere& s1, const HWVSphere& s2) - { - simdf fTotalRadius = SIMDFAdd(s1.radius, s2.radius); - hwvec3 distc = HWVSub(s1.center, s2.center); - simdf fTotalRadiusSqr = SIMDFMult(fTotalRadius, fTotalRadius); - simdf fDistanceSqr = HWV3Dot(distc, distc); - return SIMDFLessThanEqualB(fDistanceSqr, fTotalRadiusSqr); - } - - //---------------------------------------------------------------------------------- - // Sphere_Triangle overlap test - // - //--- 0 = no overlap --------------------------- - //--- 1 = overlap ----------------- - //---------------------------------------------------------------------------------- - template - ILINE bool Sphere_Triangle(const ::Sphere& s, const Triangle_tpl& t) - { - //create a "bouding sphere" around triangle for fast rejection test - Vec3_tpl middle = (t.v0 + t.v1 + t.v2) * (1 / 3.0f); - Vec3_tpl ov0 = t.v0 - middle; - Vec3_tpl ov1 = t.v1 - middle; - Vec3_tpl ov2 = t.v2 - middle; - F SqRad0 = (ov0 | ov0); - F SqRad1 = (ov1 | ov1); - F SqRad2 = (ov2 | ov2); - - SqRad0 = (F)fsel(SqRad0 - SqRad1, SqRad0, SqRad1); - SqRad0 = (F)fsel(SqRad0 - SqRad2, SqRad0, SqRad2); - - //first simple rejection-test... - if (Sphere_Sphere(s, ::Sphere(middle, sqrt_tpl(SqRad0))) == 0) - { - return 0; //overlap not possible - } - //...and now the hardcore-test! - if ((s.radius * s.radius) < Distance::Point_TriangleSq(s.center, t)) - { - return 0; - } - return 1; //sphere and triangle are overlapping - } - - ILINE bool HWVSphere_TriangleFromPoints(const HWVSphere& s, const hwvec3& t0, const hwvec3& t1, const hwvec3& t2) - { - //create a "bounding sphere" around triangle for fast rejection test - SIMDFConstant(fOneThird, 1.0f / 3.0f); - - hwvec3 middle = HWVMultiplySIMDF(HWVAdd(t0, HWVAdd(t1, t2)), fOneThird); - - hwvec3 ov0 = HWVSub(t0, middle); - hwvec3 ov1 = HWVSub(t1, middle); - hwvec3 ov2 = HWVSub(t2, middle); - - simdf SqRad0 = HWV3Dot(ov0, ov0); - simdf SqRad1 = HWV3Dot(ov1, ov1); - simdf SqRad2 = HWV3Dot(ov2, ov2); - - SqRad0 = SIMDFMax(SqRad0, SqRad1); - SqRad0 = SIMDFMax(SqRad0, SqRad2); - - //first simple rejection-test... - //if( HWVSphere_HWVSphere(s, HWVSphere(middle, SIMDFSqrtEstFast(SqRad0)))==0 ) - if (HWVSphere_HWVSphere(s, HWVSphere(middle, SIMDFSqrtEst(SqRad0))) == 0) - { - return 0; //overlap not possible - } - else - { - //...and now the hardcore-test! - simdf fRadiusSq = SIMDFMult(s.radius, s.radius); - simdf fDistToTriangleSq = Distance::Point_TriangleByPointsSq(s.center, t0, t1, t2); - - return SIMDFLessThanEqualB(fDistToTriangleSq, fRadiusSq); - } - } - - /*! - * - * we use the SEPARATING AXIS TEST to check if a triangle and AABB overlap. - * - * Example: - * bool result=Overlap::AABB_Triangle( pos,aabb, tv0,tv1,tv2 ); - * - */ - inline bool AABB_Triangle (const AABB& aabb, const Vec3& tv0, const Vec3& tv1, const Vec3& tv2) - { - //------ convert AABB into half-length AABB ----------- - Vec3 h = (aabb.max - aabb.min) * 0.5f; //calculate the half-length-vectors - Vec3 c = (aabb.max + aabb.min) * 0.5f; //the center is relative to the PIVOT - - //move everything so that the boxcenter is in (0,0,0) - Vec3 v0 = tv0 - c; - Vec3 v1 = tv1 - c; - Vec3 v2 = tv2 - c; - - //compute triangle edges - Vec3 e0 = v1 - v0; - Vec3 e1 = v2 - v1; - Vec3 e2 = v0 - v2; - - //-------------------------------------------------------------------------------------- - // use SEPARATING AXIS THEOREM to test overlap between AABB and triangle - // cross-product(edge from triangle, {x,y,z}-direction), this are 3x3=9 tests - //-------------------------------------------------------------------------------------- - float min, max, p0, p1, p2, rad, fex, fey, fez; - fex = fabsf(e0.x); - fey = fabsf(e0.y); - fez = fabsf(e0.z); - - //AXISTEST_X01(e0.z, e0.y, fez, fey); - p0 = e0.z * v0.y - e0.y * v0.z; - p2 = e0.z * v2.y - e0.y * v2.z; - if (p0 < p2) - { - min = p0; - max = p2; - } - else - { - min = p2; - max = p0; - } - rad = fez * h.y + fey * h.z; - if (min > rad || max < -rad) - { - return 0; - } - - //AXISTEST_Y02(e0.z, e0.x, fez, fex); - p0 = -e0.z * v0.x + e0.x * v0.z; - p2 = -e0.z * v2.x + e0.x * v2.z; - if (p0 < p2) - { - min = p0; - max = p2; - } - else - { - min = p2; - max = p0; - } - rad = fez * h.x + fex * h.z; - if (min > rad || max < -rad) - { - return 0; - } - - //AXISTEST_Z12(e0.y, e0.x, fey, fex); - p1 = e0.y * v1.x - e0.x * v1.y; - p2 = e0.y * v2.x - e0.x * v2.y; - if (p2 < p1) - { - min = p2; - max = p1; - } - else - { - min = p1; - max = p2; - } - rad = fey * h.x + fex * h.y; - if (min > rad || max < -rad) - { - return 0; - } - - //----------------------------------------------- - - fex = fabsf(e1.x); - fey = fabsf(e1.y); - fez = fabsf(e1.z); - //AXISTEST_X01(e1.z, e1.y, fez, fey); - p0 = e1.z * v0.y - e1.y * v0.z; - p2 = e1.z * v2.y - e1.y * v2.z; - if (p0 < p2) - { - min = p0; - max = p2; - } - else - { - min = p2; - max = p0; - } - rad = fez * h.y + fey * h.z; - if (min > rad || max < -rad) - { - return 0; - } - - //AXISTEST_Y02(e1.z, e1.x, fez, fex); - p0 = -e1.z * v0.x + e1.x * v0.z; - p2 = -e1.z * v2.x + e1.x * v2.z; - if (p0 < p2) - { - min = p0; - max = p2; - } - else - { - min = p2; - max = p0; - } - rad = fez * h.x + fex * h.z; - if (min > rad || max < -rad) - { - return 0; - } - - //AXISTEST_Z0(e1.y, e1.x, fey, fex); - p0 = e1.y * v0.x - e1.x * v0.y; - p1 = e1.y * v1.x - e1.x * v1.y; - if (p0 < p1) - { - min = p0; - max = p1; - } - else - { - min = p1; - max = p0; - } - rad = fey * h.x + fex * h.y; - if (min > rad || max < -rad) - { - return 0; - } - - //----------------------------------------------- - - fex = fabsf(e2.x); - fey = fabsf(e2.y); - fez = fabsf(e2.z); - //AXISTEST_X2(e2.z, e2.y, fez, fey); - p0 = e2.z * v0.y - e2.y * v0.z; - p1 = e2.z * v1.y - e2.y * v1.z; - if (p0 < p1) - { - min = p0; - max = p1; - } - else - { - min = p1; - max = p0; - } - rad = fez * h.y + fey * h.z; - if (min > rad || max < -rad) - { - return 0; - } - - //AXISTEST_Y1(e2.z, e2.x, fez, fex); - p0 = -e2.z * v0.x + e2.x * v0.z; - p1 = -e2.z * v1.x + e2.x * v1.z; - if (p0 < p1) - { - min = p0; - max = p1; - } - else - { - min = p1; - max = p0; - } - rad = fez * h.x + fex * h.z; - if (min > rad || max < -rad) - { - return 0; - } - - //AXISTEST_Z12(e2.y, e2.x, fey, fex); - p1 = e2.y * v1.x - e2.x * v1.y; - p2 = e2.y * v2.x - e2.x * v2.y; - if (p2 < p1) - { - min = p2; - max = p1; - } - else - { - min = p1; - max = p2; - } - rad = fey * h.x + fex * h.y; - if (min > rad || max < -rad) - { - return 0; - } - - //the {x,y,z}-directions (actually, since we use the AABB of the triangle we don't even need to test these) - //first test overlap in the {x,y,z}-directions - //find min, max of the triangle each direction, and test for overlap in that direction -- - //this is equivalent to testing a minimal AABB around the triangle against the AABB - AABB taabb; - FINDMINMAX(v0.x, v1.x, v2.x, taabb.min.x, taabb.max.x); - FINDMINMAX(v0.y, v1.y, v2.y, taabb.min.y, taabb.max.y); - FINDMINMAX(v0.z, v1.z, v2.z, taabb.min.z, taabb.max.z); - - //test in X-direction - FINDMINMAX(v0.x, v1.x, v2.x, taabb.min.x, taabb.max.x); - if (taabb.min.x > h.x || taabb.max.x < -h.x) - { - return 0; - } - - //test in Y-direction - FINDMINMAX(v0.y, v1.y, v2.y, taabb.min.y, taabb.max.y); - if (taabb.min.y > h.y || taabb.max.y < -h.y) - { - return 0; - } - - //test in Z-direction - FINDMINMAX(v0.z, v1.z, v2.z, taabb.min.z, taabb.max.z); - if (taabb.min.z > h.z || taabb.max.z < -h.z) - { - return 0; - } - - //test if the box intersects the plane of the triangle - //compute plane equation of triangle: normal*x+d=0 - Plane_tpl plane = Plane_tpl::CreatePlane((e0 % e1), v0); - - Vec3 vmin, vmax; - if (plane.n.x > 0.0f) - { - vmin.x = -h.x; - vmax.x = +h.x; - } - else - { - vmin.x = +h.x; - vmax.x = -h.x; - } - if (plane.n.y > 0.0f) - { - vmin.y = -h.y; - vmax.y = +h.y; - } - else - { - vmin.y = +h.y; - vmax.y = -h.y; - } - if (plane.n.z > 0.0f) - { - vmin.z = -h.z; - vmax.z = +h.z; - } - else - { - vmin.z = +h.z; - vmax.z = -h.z; - } - if ((plane | vmin) > 0.0f) - { - return 0; - } - if ((plane | vmax) < 0.0f) - { - return 0; - } - return 1; - } - - - - /*! - * - * we use the SEPARATING AXIS TEST to check if a triangle and an OBB overlaps. - * - * Example: - * bool result=Overlap::OBB_Trinagle( pos1,obb1, tv0,tv1,tv2 ); - * - */ - inline bool OBB_Triangle(const Vec3& pos, const OBB& obb, const Vec3& tv0, const Vec3& tv1, const Vec3& tv2) - { - Vec3 p = obb.m33 * obb.c + pos; //the new center-position in world-space - - //move everything so that the boxcenter is in (0,0,0) - Vec3 v0 = (tv0 - p) * obb.m33; //pre-transform - Vec3 v1 = (tv1 - p) * obb.m33; //pre-transform - Vec3 v2 = (tv2 - p) * obb.m33; //pre-transform - - - //compute triangle edges - Vec3 e0 = v1 - v0; - Vec3 e1 = v2 - v1; - Vec3 e2 = v0 - v2; - - //-------------------------------------------------------------------------------------- - // use SEPARATING AXIS THEOREM to test intersection between AABB and triangle - // cross-product(edge from triangle, {x,y,z}-direction), this are 3x3=9 tests - //-------------------------------------------------------------------------------------- - float min, max, p0, p1, p2, rad, fex, fey, fez; - fex = fabsf(e0.x); - fey = fabsf(e0.y); - fez = fabsf(e0.z); - - //AXISTEST_X01(e0.z, e0.y, fez, fey); - p0 = e0.z * v0.y - e0.y * v0.z; - p2 = e0.z * v2.y - e0.y * v2.z; - if (p0 < p2) - { - min = p0; - max = p2; - } - else - { - min = p2; - max = p0; - } - rad = fez * obb.h.y + fey * obb.h.z; - if (min > rad || max < -rad) - { - return 0; - } - - //AXISTEST_Y02(e0.z, e0.x, fez, fex); - p0 = -e0.z * v0.x + e0.x * v0.z; - p2 = -e0.z * v2.x + e0.x * v2.z; - if (p0 < p2) - { - min = p0; - max = p2; - } - else - { - min = p2; - max = p0; - } - rad = fez * obb.h.x + fex * obb.h.z; - if (min > rad || max < -rad) - { - return 0; - } - - //AXISTEST_Z12(e0.y, e0.x, fey, fex); - p1 = e0.y * v1.x - e0.x * v1.y; - p2 = e0.y * v2.x - e0.x * v2.y; - if (p2 < p1) - { - min = p2; - max = p1; - } - else - { - min = p1; - max = p2; - } - rad = fey * obb.h.x + fex * obb.h.y; - if (min > rad || max < -rad) - { - return 0; - } - - //----------------------------------------------- - - fex = fabsf(e1.x); - fey = fabsf(e1.y); - fez = fabsf(e1.z); - //AXISTEST_X01(e1.z, e1.y, fez, fey); - p0 = e1.z * v0.y - e1.y * v0.z; - p2 = e1.z * v2.y - e1.y * v2.z; - if (p0 < p2) - { - min = p0; - max = p2; - } - else - { - min = p2; - max = p0; - } - rad = fez * obb.h.y + fey * obb.h.z; - if (min > rad || max < -rad) - { - return 0; - } - - //AXISTEST_Y02(e1.z, e1.x, fez, fex); - p0 = -e1.z * v0.x + e1.x * v0.z; - p2 = -e1.z * v2.x + e1.x * v2.z; - if (p0 < p2) - { - min = p0; - max = p2; - } - else - { - min = p2; - max = p0; - } - rad = fez * obb.h.x + fex * obb.h.z; - if (min > rad || max < -rad) - { - return 0; - } - - //AXISTEST_Z0(e1.y, e1.x, fey, fex); - p0 = e1.y * v0.x - e1.x * v0.y; - p1 = e1.y * v1.x - e1.x * v1.y; - if (p0 < p1) - { - min = p0; - max = p1; - } - else - { - min = p1; - max = p0; - } - rad = fey * obb.h.x + fex * obb.h.y; - if (min > rad || max < -rad) - { - return 0; - } - - //----------------------------------------------- - - fex = fabsf(e2.x); - fey = fabsf(e2.y); - fez = fabsf(e2.z); - //AXISTEST_X2(e2.z, e2.y, fez, fey); - p0 = e2.z * v0.y - e2.y * v0.z; - p1 = e2.z * v1.y - e2.y * v1.z; - if (p0 < p1) - { - min = p0; - max = p1; - } - else - { - min = p1; - max = p0; - } - rad = fez * obb.h.y + fey * obb.h.z; - if (min > rad || max < -rad) - { - return 0; - } - - //AXISTEST_Y1(e2.z, e2.x, fez, fex); - p0 = -e2.z * v0.x + e2.x * v0.z; - p1 = -e2.z * v1.x + e2.x * v1.z; - if (p0 < p1) - { - min = p0; - max = p1; - } - else - { - min = p1; - max = p0; - } - rad = fez * obb.h.x + fex * obb.h.z; - if (min > rad || max < -rad) - { - return 0; - } - - //AXISTEST_Z12(e2.y, e2.x, fey, fex); - p1 = e2.y * v1.x - e2.x * v1.y; - p2 = e2.y * v2.x - e2.x * v2.y; - if (p2 < p1) - { - min = p2; - max = p1; - } - else - { - min = p1; - max = p2; - } - rad = fey * obb.h.x + fex * obb.h.y; - if (min > rad || max < -rad) - { - return 0; - } - - //the {x,y,z}-directions (actually, since we use the AABB of the triangle we don't even need to test these) - //first test overlap in the {x,y,z}-directions - //find min, max of the triangle each direction, and test for overlap in that direction -- - //this is equivalent to testing a minimal AABB around the triangle against the AABB - AABB taabb; - FINDMINMAX(v0.x, v1.x, v2.x, taabb.min.x, taabb.max.x); - FINDMINMAX(v0.y, v1.y, v2.y, taabb.min.y, taabb.max.y); - FINDMINMAX(v0.z, v1.z, v2.z, taabb.min.z, taabb.max.z); - - // test in X-direction - FINDMINMAX(v0.x, v1.x, v2.x, taabb.min.x, taabb.max.x); - if (taabb.min.x > obb.h.x || taabb.max.x < -obb.h.x) - { - return 0; - } - - // test in Y-direction - FINDMINMAX(v0.y, v1.y, v2.y, taabb.min.y, taabb.max.y); - if (taabb.min.y > obb.h.y || taabb.max.y < -obb.h.y) - { - return 0; - } - - // test in Z-direction - FINDMINMAX(v0.z, v1.z, v2.z, taabb.min.z, taabb.max.z); - if (taabb.min.z > obb.h.z || taabb.max.z < -obb.h.z) - { - return 0; - } - - //test if the box overlaps the plane of the triangle - //compute plane equation of triangle: normal*x+d=0 - Plane_tpl plane = Plane_tpl::CreatePlane((e0 % e1), v0); - - Vec3 vmin, vmax; - if (plane.n.x > 0.0f) - { - vmin.x = -obb.h.x; - vmax.x = +obb.h.x; - } - else - { - vmin.x = +obb.h.x; - vmax.x = -obb.h.x; - } - if (plane.n.y > 0.0f) - { - vmin.y = -obb.h.y; - vmax.y = +obb.h.y; - } - else - { - vmin.y = +obb.h.y; - vmax.y = -obb.h.y; - } - if (plane.n.z > 0.0f) - { - vmin.z = -obb.h.z; - vmax.z = +obb.h.z; - } - else - { - vmin.z = +obb.h.z; - vmax.z = -obb.h.z; - } - if ((plane | vmin) > 0.0f) - { - return 0; - } - if ((plane | vmax) < 0.0f) - { - return 0; - } - return 1; - } - - - - - - - - - - /*! - * - * conventional method to check if two AABB's overlap. - * both AABBs are assumed to be in the same space - * - * Example: - * bool result=Overlap::AABB_AABB( aabb1, aabb2 ); - * - */ - ILINE bool AABB_AABB(const AABB& aabb1, const AABB& aabb2) - { - if (aabb1.min.x >= aabb2.max.x) - { - return 0; - } - if (aabb1.min.y >= aabb2.max.y) - { - return 0; - } - if (aabb1.min.z >= aabb2.max.z) - { - return 0; - } - if (aabb1.max.x <= aabb2.min.x) - { - return 0; - } - if (aabb1.max.y <= aabb2.min.y) - { - return 0; - } - if (aabb1.max.z <= aabb2.min.z) - { - return 0; - } - return 1; //the aabb's overlap - } - - /// AABB overlap test - but ignores z values - ILINE bool AABB_AABB2D(const AABB& aabb1, const AABB& aabb2) - { - if (aabb1.min.x >= aabb2.max.x) - { - return 0; - } - if (aabb1.min.y >= aabb2.max.y) - { - return 0; - } - if (aabb1.max.x <= aabb2.min.x) - { - return 0; - } - if (aabb1.max.y <= aabb2.min.y) - { - return 0; - } - return 1; //the aabb's overlap - } - - - /*! - * - * Conventional method to check if two AABB's overlap. - * Both AABBs are in local object space. Used the position-vector - * to translate them into world-space - * - * Example: - * bool result=Overlap::AABB_AABB( pos1,aabb1, pos2,aabb2 ); - * - */ - ILINE bool AABB_AABB(const Vec3& pos1, const AABB& aabb1, const Vec3& pos2, const AABB& aabb2) - { - AABB waabb1(aabb1.min + pos1, aabb1.max + pos1); - AABB waabb2(aabb2.min + pos2, aabb2.max + pos2); - return AABB_AABB(waabb1, waabb2); - } - - - /*! - * - * conventional method to check if two AABB's overlap - * or if AABB1 is comletely inside AABB2. - * both AABBs are assumed to be in the same space - * - * Example: - * bool result=Overlap::AABB_AABB_Inside( aabb1, aabb2 ); - * - * return values: - * 0x00 = no overlap - * 0x01 = both AABBs one overlap - * 0x02 = AABB1 in inside AABB2 - */ - ILINE char AABB_AABB_Inside(const AABB& aabb1, const AABB& aabb2) - { - if (AABB_AABB(aabb1, aabb2)) - { - if (aabb1.min.x <= aabb2.min.x) - { - return 1; - } - if (aabb1.min.y <= aabb2.min.y) - { - return 1; - } - if (aabb1.min.z <= aabb2.min.z) - { - return 1; - } - if (aabb1.max.x >= aabb2.max.x) - { - return 1; - } - if (aabb1.max.y >= aabb2.max.y) - { - return 1; - } - if (aabb1.max.z >= aabb2.max.z) - { - return 1; - } - //yes, its inside - return 2; - } - return 0; - } - - - /*! - * - * we use the SEPARATING AXIS TEST to check if and AABB and an OBB overlap. - * - * Example: - * bool result=Overlap::AABB_OBB( aabb, pos,obb ); - * - */ - inline bool AABB_OBB (const AABB& aabb, const Vec3& pos, const OBB& obb) - { - Vec3 h = (aabb.max - aabb.min) * 0.5f; //calculate the half-length-vectors - Vec3 c = (aabb.max + aabb.min) * 0.5f; //the center in world-space - - //"t" is the transfer-vector from one center to the other - Vec3 t = obb.m33 * obb.c + pos - c; - - f32 ra, rb; - - //-------------------------------------------------------------------------- - //-- we use the vectors "1,0,0","0,1,0" and "0,0,1" as separating axis - //-------------------------------------------------------------------------- - rb = fabsf(obb.m33.m00 * obb.h.x) + fabsf(obb.m33.m01 * obb.h.y) + fabsf(obb.m33.m02 * obb.h.z); - if (fabsf(t.x) > (fabsf(h.x) + rb)) - { - return 0; - } - rb = fabsf(obb.m33.m10 * obb.h.x) + fabsf(obb.m33.m11 * obb.h.y) + fabsf(obb.m33.m12 * obb.h.z); - if (fabsf(t.y) > (fabsf(h.y) + rb)) - { - return 0; - } - rb = fabsf(obb.m33.m20 * obb.h.x) + fabsf(obb.m33.m21 * obb.h.y) + fabsf(obb.m33.m22 * obb.h.z); - if (fabsf(t.z) > (fabsf(h.z) + rb)) - { - return 0; - } - - //-------------------------------------------------------------------------- - //-- we use the orientation-vectors "Mx","My" and "Mz" as separating axis - //-------------------------------------------------------------------------- - ra = fabsf(obb.m33.m00 * h.x) + fabsf(obb.m33.m10 * h.y) + fabsf(obb.m33.m20 * h.z); - if (fabsf(t | Vec3(obb.m33.m00, obb.m33.m10, obb.m33.m20)) > (ra + obb.h.x)) - { - return 0; - } - ra = fabsf(obb.m33.m01 * h.x) + fabsf(obb.m33.m11 * h.y) + fabsf(obb.m33.m21 * h.z); - if (fabsf(t | Vec3(obb.m33.m01, obb.m33.m11, obb.m33.m21)) > (ra + obb.h.y)) - { - return 0; - } - ra = fabsf(obb.m33.m02 * h.x) + fabsf(obb.m33.m12 * h.y) + fabsf(obb.m33.m22 * h.z); - if (fabsf(t | Vec3(obb.m33.m02, obb.m33.m12, obb.m33.m22)) > (ra + obb.h.z)) - { - return 0; - } - - //--------------------------------------------------------------------- - //---- using 9 cross products we generate new separating axis - //--------------------------------------------------------------------- - const float e0 = h.x + h.y + h.z, e1 = obb.h.x + obb.h.y + obb.h.z, e = (e0 + e1 - fabsf(e0 - e1)) * 0.0001f; - ra = h.y * fabsf(obb.m33.m20) + h.z * fabsf(obb.m33.m10); - rb = obb.h.y * fabsf(obb.m33.m02) + obb.h.z * fabsf(obb.m33.m01); - if (fabsf(t.z * obb.m33.m10 - t.y * obb.m33.m20) > (ra + rb) + e) - { - return 0; - } - ra = h.y * fabsf(obb.m33.m21) + h.z * fabsf(obb.m33.m11); - rb = obb.h.x * fabsf(obb.m33.m02) + obb.h.z * fabsf(obb.m33.m00); - if (fabsf(t.z * obb.m33.m11 - t.y * obb.m33.m21) > (ra + rb) + e) - { - return 0; - } - ra = h.y * fabsf(obb.m33.m22) + h.z * fabsf(obb.m33.m12); - rb = obb.h.x * fabsf(obb.m33.m01) + obb.h.y * fabsf(obb.m33.m00); - if (fabsf(t.z * obb.m33.m12 - t.y * obb.m33.m22) > (ra + rb) + e) - { - return 0; - } - - - ra = h.x * fabsf(obb.m33.m20) + h.z * fabsf(obb.m33.m00); - rb = obb.h.y * fabsf(obb.m33.m12) + obb.h.z * fabsf(obb.m33.m11); - if (fabsf(t.x * obb.m33.m20 - t.z * obb.m33.m00) > (ra + rb) + e) - { - return 0; - } - ra = h.x * fabsf(obb.m33.m21) + h.z * fabsf(obb.m33.m01); - rb = obb.h.x * fabsf(obb.m33.m12) + obb.h.z * fabsf(obb.m33.m10); - if (fabsf(t.x * obb.m33.m21 - t.z * obb.m33.m01) > (ra + rb) + e) - { - return 0; - } - ra = h.x * fabsf(obb.m33.m22) + h.z * fabsf(obb.m33.m02); - rb = obb.h.x * fabsf(obb.m33.m11) + obb.h.y * fabsf(obb.m33.m10); - if (fabsf(t.x * obb.m33.m22 - t.z * obb.m33.m02) > (ra + rb) + e) - { - return 0; - } - - - ra = h.x * fabsf(obb.m33.m10) + h.y * fabsf(obb.m33.m00); - rb = obb.h.y * fabsf(obb.m33.m22) + obb.h.z * fabsf(obb.m33.m21); - if (fabsf(t.y * obb.m33.m00 - t.x * obb.m33.m10) > (ra + rb) + e) - { - return 0; - } - ra = h.x * fabsf(obb.m33.m11) + h.y * fabsf(obb.m33.m01); - rb = obb.h.x * fabsf(obb.m33.m22) + obb.h.z * fabsf(obb.m33.m20); - if (fabsf(t.y * obb.m33.m01 - t.x * obb.m33.m11) > (ra + rb) + e) - { - return 0; - } - ra = h.x * fabsf(obb.m33.m12) + h.y * fabsf(obb.m33.m02); - rb = obb.h.x * fabsf(obb.m33.m21) + obb.h.y * fabsf(obb.m33.m20); - if (fabsf(t.y * obb.m33.m02 - t.x * obb.m33.m12) > (ra + rb) + e) - { - return 0; - } - - //no separating axis found, we have an intersection - return 1; - } - - /*! - * - * we use the SEPARATING AXIS TEST to check if two OBB's overlap. - * - * Example: - * bool result=Overlap::OBB_OBB( pos1,obb1, pos2,obb2 ); - * - */ - inline bool OBB_OBB (const Vec3& pos1, const OBB& obb1, const Vec3& pos2, const OBB& obb2) - { - //tranform obb2 in local space of obb1 - Matrix33 M = obb1.m33.T() * obb2.m33; - - //the new center-position in world-space - Vec3 p1 = obb1.m33 * obb1.c + pos1; - Vec3 p2 = obb2.m33 * obb2.c + pos2; - - //"t" is the transfer-vector from one center to the other - Vec3 t = (p2 - p1) * obb1.m33; - - float ra, rb; - - //-------------------------------------------------------------------------- - //-- we use the vectors "1,0,0","0,1,0" and "0,0,1" as separating axis - //-------------------------------------------------------------------------- - rb = fabsf(M.m00 * obb2.h.x) + fabsf(M.m01 * obb2.h.y) + fabsf(M.m02 * obb2.h.z); - if (fabsf(t.x) > (fabsf(obb1.h.x) + rb)) - { - return 0; - } - rb = fabsf(M.m10 * obb2.h.x) + fabsf(M.m11 * obb2.h.y) + fabsf(M.m12 * obb2.h.z); - if (fabsf(t.y) > (fabsf(obb1.h.y) + rb)) - { - return 0; - } - rb = fabsf(M.m20 * obb2.h.x) + fabsf(M.m21 * obb2.h.y) + fabsf(M.m22 * obb2.h.z); - if (fabsf(t.z) > (fabsf(obb1.h.z) + rb)) - { - return 0; - } - - //-------------------------------------------------------------------------- - //-- we use the orientation-vectors "Mx","My" and "Mz" as separating axis - //-------------------------------------------------------------------------- - ra = fabsf(M.m00 * obb1.h.x) + fabsf(M.m10 * obb1.h.y) + fabsf(M.m20 * obb1.h.z); - if (fabsf(t | Vec3(M.m00, M.m10, M.m20)) > (ra + obb2.h.x)) - { - return 0; - } - ra = fabsf(M.m01 * obb1.h.x) + fabsf(M.m11 * obb1.h.y) + fabsf(M.m21 * obb1.h.z); - if (fabsf(t | Vec3(M.m01, M.m11, M.m21)) > (ra + obb2.h.y)) - { - return 0; - } - ra = fabsf(M.m02 * obb1.h.x) + fabsf(M.m12 * obb1.h.y) + fabsf(M.m22 * obb1.h.z); - if (fabsf(t | Vec3(M.m02, M.m12, M.m22)) > (ra + obb2.h.z)) - { - return 0; - } - - //--------------------------------------------------------------------- - //---- using 9 cross products we generate new separating axis - //--------------------------------------------------------------------- - ra = obb1.h.y * fabsf(M.m20) + obb1.h.z * fabsf(M.m10); - rb = obb2.h.y * fabsf(M.m02) + obb2.h.z * fabsf(M.m01); - if (fabsf(t.z * M.m10 - t.y * M.m20) > (ra + rb)) - { - return 0; - } - ra = obb1.h.y * fabsf(M.m21) + obb1.h.z * fabsf(M.m11); - rb = obb2.h.x * fabsf(M.m02) + obb2.h.z * fabsf(M.m00); - if (fabsf(t.z * M.m11 - t.y * M.m21) > (ra + rb)) - { - return 0; - } - ra = obb1.h.y * fabsf(M.m22) + obb1.h.z * fabsf(M.m12); - rb = obb2.h.x * fabsf(M.m01) + obb2.h.y * fabsf(M.m00); - if (fabsf(t.z * M.m12 - t.y * M.m22) > (ra + rb)) - { - return 0; - } - - - ra = obb1.h.x * fabsf(M.m20) + obb1.h.z * fabsf(M.m00); - rb = obb2.h.y * fabsf(M.m12) + obb2.h.z * fabsf(M.m11); - if (fabsf(t.x * M.m20 - t.z * M.m00) > (ra + rb)) - { - return 0; - } - ra = obb1.h.x * fabsf(M.m21) + obb1.h.z * fabsf(M.m01); - rb = obb2.h.x * fabsf(M.m12) + obb2.h.z * fabsf(M.m10); - if (fabsf(t.x * M.m21 - t.z * M.m01) > (ra + rb)) - { - return 0; - } - ra = obb1.h.x * fabsf(M.m22) + obb1.h.z * fabsf(M.m02); - rb = obb2.h.x * fabsf(M.m11) + obb2.h.y * fabsf(M.m10); - if (fabsf(t.x * M.m22 - t.z * M.m02) > (ra + rb)) - { - return 0; - } - - - ra = obb1.h.x * fabsf(M.m10) + obb1.h.y * fabsf(M.m00); - rb = obb2.h.y * fabsf(M.m22) + obb2.h.z * fabsf(M.m21); - if (fabsf(t.y * M.m00 - t.x * M.m10) > (ra + rb)) - { - return 0; - } - ra = obb1.h.x * fabsf(M.m11) + obb1.h.y * fabsf(M.m01); - rb = obb2.h.x * fabsf(M.m22) + obb2.h.z * fabsf(M.m20); - if (fabsf(t.y * M.m01 - t.x * M.m11) > (ra + rb)) - { - return 0; - } - ra = obb1.h.x * fabsf(M.m12) + obb1.h.y * fabsf(M.m02); - rb = obb2.h.x * fabsf(M.m21) + obb2.h.y * fabsf(M.m20); - if (fabsf(t.y * M.m02 - t.x * M.m12) > (ra + rb)) - { - return 0; - } - - return 1; //no separating axis found, we have an overlap - } - - - - - - -#define PLANE_X 0 -#define PLANE_Y 1 -#define PLANE_Z 2 -#define PLANE_NON_AXIAL 3 - - //! check if the point is inside a triangle - inline bool PointInTriangle(const Vec3& point, const Vec3& v0, const Vec3& v1, const Vec3& v2, const Vec3& normal) - { - float xt, yt; - Vec3 nn; - - int p1, p2; - - nn = normal; - nn.x = (float)fabs(nn.x); - nn.y = (float)fabs(nn.y); - nn.z = (float)fabs(nn.z); - - if ((nn.x >= nn.y) && (nn.x >= nn.z)) - { - xt = point.y; - yt = point.z; - p1 = PLANE_Y; - p2 = PLANE_Z; - } - else - if ((nn.y >= nn.x) && (nn.y >= nn.z)) - { - xt = point.x; - yt = point.z; - p1 = PLANE_X; - p2 = PLANE_Z; - } - else - { - xt = point.x; - yt = point.y; - p1 = PLANE_X; - p2 = PLANE_Y; - } - - float Ax, Ay, Bx, By; - float s; - - bool front = false; - bool back = false; - - - Ax = (v0)[p1]; - Bx = (v1)[p1]; - Ay = (v0)[p2]; - By = (v1)[p2]; - - s = ((Ay - yt) * (Bx - Ax) - (Ax - xt) * (By - Ay)); - - if (s >= 0) - { - if (back) - { - return (false); - } - front = true; - } - else - { - if (front) - { - return (false); - } - back = true; - } - - Ax = (v1)[p1]; - Bx = (v2)[p1]; - Ay = (v1)[p2]; - By = (v2)[p2]; - - s = ((Ay - yt) * (Bx - Ax) - (Ax - xt) * (By - Ay)); - - if (s >= 0) - { - if (back) - { - return (false); - } - front = true; - } - else - { - if (front) - { - return (false); - } - back = true; - } - - Ax = (v2)[p1]; - Bx = (v0)[p1]; - Ay = (v2)[p2]; - By = (v0)[p2]; - - s = ((Ay - yt) * (Bx - Ax) - (Ax - xt) * (By - Ay)); - - if (s >= 0) - { - if (back) - { - return (false); - } - front = true; - } - else - { - if (front) - { - return (false); - } - back = true; - } - - return (true); - } -} - - - -#endif // CRYINCLUDE_CRYCOMMON_CRY_GEOOVERLAP_H diff --git a/Code/Legacy/CryCommon/Cry_Math.h b/Code/Legacy/CryCommon/Cry_Math.h index 885361f4e3..74a18e8910 100644 --- a/Code/Legacy/CryCommon/Cry_Math.h +++ b/Code/Legacy/CryCommon/Cry_Math.h @@ -18,7 +18,7 @@ #include "Cry_ValidNumber.h" #include // eLittleEndian #include -#include +//#include #include /////////////////////////////////////////////////////////////////////////////// // Forward declarations // diff --git a/Code/Legacy/CryCommon/Cry_Matrix33.h b/Code/Legacy/CryCommon/Cry_Matrix33.h index 02d1586931..9e0b12fafa 100644 --- a/Code/Legacy/CryCommon/Cry_Matrix33.h +++ b/Code/Legacy/CryCommon/Cry_Matrix33.h @@ -1194,8 +1194,6 @@ struct Matrix33_tpl return true; } - - AUTO_STRUCT_INFO }; /////////////////////////////////////////////////////////////////////////////// diff --git a/Code/Legacy/CryCommon/Cry_Matrix34.h b/Code/Legacy/CryCommon/Cry_Matrix34.h index d409cfef8b..0659d3bc47 100644 --- a/Code/Legacy/CryCommon/Cry_Matrix34.h +++ b/Code/Legacy/CryCommon/Cry_Matrix34.h @@ -1213,8 +1213,6 @@ struct Matrix34_tpl m.m23 = pdotn * n.z; return m; } - - AUTO_STRUCT_INFO }; /////////////////////////////////////////////////////////////////////////////// diff --git a/Code/Legacy/CryCommon/Cry_Matrix44.h b/Code/Legacy/CryCommon/Cry_Matrix44.h index e97325141c..20d7494e16 100644 --- a/Code/Legacy/CryCommon/Cry_Matrix44.h +++ b/Code/Legacy/CryCommon/Cry_Matrix44.h @@ -655,8 +655,6 @@ struct Matrix44_tpl (fabs_tpl(m0.m30 - m1.m30) <= e) && (fabs_tpl(m0.m31 - m1.m31) <= e) && (fabs_tpl(m0.m32 - m1.m32) <= e) && (fabs_tpl(m0.m33 - m1.m33) <= e) ); } - - AUTO_STRUCT_INFO }; /////////////////////////////////////////////////////////////////////////////// diff --git a/Code/Legacy/CryCommon/Cry_Quat.h b/Code/Legacy/CryCommon/Cry_Quat.h index b062c584b7..a18d8a2ad9 100644 --- a/Code/Legacy/CryCommon/Cry_Quat.h +++ b/Code/Legacy/CryCommon/Cry_Quat.h @@ -888,9 +888,6 @@ struct Quat_tpl { return CreateNlerp(IDENTITY, *this, scale); } - - - AUTO_STRUCT_INFO }; @@ -1409,8 +1406,6 @@ struct QuatT_tpl { return QuatT_tpl(t * scale, q.GetScaled(scale)); } - - AUTO_STRUCT_INFO }; typedef QuatT_tpl QuatT; //always 32 bit @@ -1690,8 +1685,6 @@ struct QuatTS_tpl ILINE Vec3_tpl GetRow0() const { return q.GetRow0(); } ILINE Vec3_tpl GetRow1() const { return q.GetRow1(); } ILINE Vec3_tpl GetRow2() const { return q.GetRow2(); } - - AUTO_STRUCT_INFO }; typedef QuatTS_tpl QuatTS; //always 64 bit @@ -1947,8 +1940,6 @@ struct QuatTNS_tpl ILINE Vec3_tpl GetRow0() const { return q.GetRow0(); } ILINE Vec3_tpl GetRow1() const { return q.GetRow1(); } ILINE Vec3_tpl GetRow2() const { return q.GetRow2(); } - - AUTO_STRUCT_INFO }; typedef QuatTNS_tpl QuatTNS; @@ -2097,8 +2088,6 @@ struct DualQuat_tpl nq *= norm; dq *= norm; } - - AUTO_STRUCT_INFO }; #ifndef MAX_API_NUM diff --git a/Code/Legacy/CryCommon/Cry_Vector2.h b/Code/Legacy/CryCommon/Cry_Vector2.h index f17259d70f..a8722c1b02 100644 --- a/Code/Legacy/CryCommon/Cry_Vector2.h +++ b/Code/Legacy/CryCommon/Cry_Vector2.h @@ -295,8 +295,6 @@ struct Vec2_tpl { return sqrt_tpl((x - vec1.x) * (x - vec1.x) + (y - vec1.y) * (y - vec1.y)); } - - AUTO_STRUCT_INFO }; /////////////////////////////////////////////////////////////////////////////// diff --git a/Code/Legacy/CryCommon/Cry_Vector3.h b/Code/Legacy/CryCommon/Cry_Vector3.h index 7b735df0fa..bd1cc11430 100644 --- a/Code/Legacy/CryCommon/Cry_Vector3.h +++ b/Code/Legacy/CryCommon/Cry_Vector3.h @@ -845,8 +845,6 @@ struct Vec3_tpl { return Vec3_tpl(y * v.z - z * v.y, z * v.x - x * v.z, x * v.y - y * v.x); } - - AUTO_STRUCT_INFO }; // dot product (2 versions) @@ -1175,8 +1173,6 @@ struct Ang3_tpl } return true; } - - AUTO_STRUCT_INFO }; typedef Ang3_tpl Ang3; @@ -1406,8 +1402,6 @@ struct Plane_tpl Vec3_tpl MirrorPosition(const Vec3_tpl& i) { return i - n * (2 * ((n | i) + d)); } ILINE bool IsValid() const { return !n.IsZeroFast(); } //A plane with a zero normal isn't valid. - - AUTO_STRUCT_INFO }; typedef Plane_tpl Plane; //always 32 bit diff --git a/Code/Legacy/CryCommon/Cry_Vector4.h b/Code/Legacy/CryCommon/Cry_Vector4.h index bafeefe00b..bbb3395fb3 100644 --- a/Code/Legacy/CryCommon/Cry_Vector4.h +++ b/Code/Legacy/CryCommon/Cry_Vector4.h @@ -227,8 +227,6 @@ struct Vec4_tpl ILINE void SetLerp(const Vec4_tpl& p, const Vec4_tpl& q, F t) { *this = p * (1.0f - t) + q * t; } ILINE static Vec4_tpl CreateLerp(const Vec4_tpl& p, const Vec4_tpl& q, F t) { return p * (1.0f - t) + q * t; } - - AUTO_STRUCT_INFO }; diff --git a/Code/Legacy/CryCommon/HMDBus.h b/Code/Legacy/CryCommon/HMDBus.h index 674b7ffd1e..dab4c28668 100644 --- a/Code/Legacy/CryCommon/HMDBus.h +++ b/Code/Legacy/CryCommon/HMDBus.h @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -36,7 +35,7 @@ namespace AZ * Event triggered when an HMD initializes successfully */ virtual void OnHMDInitialized() {} - + /** * Event triggered when an HMD shuts down */ @@ -56,7 +55,7 @@ namespace AZ virtual ~HMDInitBus() {} /// - /// Attempt to initialize this device. If initialization is initially successful (device exists and is able to startup) then this device should connect to the + /// Attempt to initialize this device. If initialization is initially successful (device exists and is able to startup) then this device should connect to the /// HMDDeviceRequestBus in order to be used as an HMD from the main Open 3D Engine system. /// /// @return If true, initialization fully succeeded. @@ -120,21 +119,10 @@ namespace AZ }; /// - /// Get per-eye camera info from the device. The specific info to get is defined in the EyeCameraInfo struct. This function can be used to setup - /// rendering cameras per-eye. Note that each eye may have different projection matrix information. - /// - /// @param eye The specific eye to get camera data for. - /// @param nearPlane Near distance for the main render camera. - /// @param farPlane Far distance for the main render camera. - /// @param cameraInfo Returned camera information for this particular eye. - /// - virtual void GetPerEyeCameraInfo([[maybe_unused]] const EStereoEye eye, [[maybe_unused]] const float nearPlane, [[maybe_unused]] const float farPlane, [[maybe_unused]] PerEyeCameraInfo& cameraInfo) {} - - /// /// Update the HMD's internal state and handle events /// This is NOT where tracking is updated. This is for game-time /// events such as controllers connecting/disconnecting or - /// certain compositor events being triggered. + /// certain compositor events being triggered. /// virtual void UpdateInternalState() {} @@ -164,9 +152,9 @@ namespace AZ /// /// Retrieve the latest tracking state that was cached since the last call /// to UpdateTrackingStates. - /// - /// TODO: Differentiate between tracking states viable for rendering and - /// tracking states viable for game simulation. + /// + /// TODO: Differentiate between tracking states viable for rendering and + /// tracking states viable for game simulation. /// virtual TrackingState* GetTrackingState() { return nullptr; } @@ -196,7 +184,7 @@ namespace AZ /// /// Set the current tracking level of the HMD. Supported tracking levels are defined in struct TrackingLevel. - /// + /// /// @param level The tracking level we want to use with this HMD /// virtual void SetTrackingLevel([[maybe_unused]] const AZ::VR::HMDTrackingLevel level) {} @@ -209,7 +197,7 @@ namespace AZ /// /// Enable/disable debugging for this device. The device can decide what the most appropriate debugging information is /// displayed to the user (e.g. HMD position, performance info, latency timing, etc.). - /// + /// /// @param enable Set to true to enable debugging /// virtual void EnableDebugging([[maybe_unused]] bool enable) {} @@ -230,16 +218,16 @@ namespace AZ virtual HMDDeviceInfo* GetDeviceInfo() { return nullptr; } /// - /// Get whether or not the HMD has been initialized. The HMD has been initialized when it has fully established an interface - /// with its necessary SDK and is ready to be used. - /// + /// Get whether or not the HMD has been initialized. The HMD has been initialized when it has fully established an interface + /// with its necessary SDK and is ready to be used. + /// /// @return True if the device has been initialized and is usable /// virtual bool IsInitialized() { return false; } /// /// Get the play space of the device, if exists - /// + /// /// @return True if the device has been initialized and is usable /// virtual const Playspace* GetPlayspace() { return nullptr; } @@ -251,21 +239,13 @@ namespace AZ /// virtual void UpdateTrackingStates() {} - /// - /// Retrieves the current index into the VR system's swapchain that should be used. - /// This only really need to be overridden by VR implementations that keep track - /// of an internal swapchain like Oculus. OpenVR will handle swapchains - /// internally and can just return 0. - /// - virtual AZ::u32 GetSwapchainIndex([[maybe_unused]] const EStereoEye& eye) { return 0; } - protected: }; using HMDDeviceRequestBus = AZ::EBus; /// - /// Bus to define HMD debugging. This includes visualization of any HMD-specific objects as well as any + /// Bus to define HMD debugging. This includes visualization of any HMD-specific objects as well as any /// VR performance metrics displayed in the HMD. /// class HMDDebuggerBus diff --git a/Code/Legacy/CryCommon/IConsole.h b/Code/Legacy/CryCommon/IConsole.h index e03de35aa1..dcbb0399aa 100644 --- a/Code/Legacy/CryCommon/IConsole.h +++ b/Code/Legacy/CryCommon/IConsole.h @@ -6,12 +6,11 @@ * */ - -#ifndef CRYINCLUDE_CRYCOMMON_ICONSOLE_H -#define CRYINCLUDE_CRYCOMMON_ICONSOLE_H #pragma once #include +#include +#include struct SFunctor; @@ -454,24 +453,6 @@ struct IConsole virtual void DumpKeyBinds(IKeyBindDumpSink* pCallback) = 0; virtual const char* FindKeyBind(const char* sCmd) const = 0; - ////////////////////////////////////////////////////////////////////////// - // Hashing of cvars (for anti-cheat). Separates setting of range, calculation, - // and retrieval of result so calculation can be done at a known safe point - // (e.g end of frame) when we know cvars won't be modified or in temporary state - - // Get Number of cvars that can be hashed - virtual int GetNumCheatVars() = 0; - // Set the range of cvars - virtual void SetCheatVarHashRange(size_t firstVar, size_t lastVar) = 0; - // Calculate the hash from current cvars - virtual void CalcCheatVarHash() = 0; - // Since hash is calculated async, check if it's completed - virtual bool IsHashCalculated() = 0; - // Get the hash calculated - virtual uint64 GetCheatVarHash() = 0; - virtual void PrintCheatVars(bool bUseLastHashRange) = 0; - virtual char* GetCheatVarAt(uint32 nOffset) = 0; - ////////////////////////////////////////////////////////////////////////// // Console variable sink. // Adds a new console variables sink callback. @@ -644,19 +625,6 @@ struct ICVar // Returns an ID to use when getting or removing the functor virtual uint64 AddOnChangeFunctor(const SFunctor& pChangeFunctor) = 0; - ////////////////////////////////////////////////////////////////////////// - // Returns the number of registered on change functos. - virtual uint64 GetNumberOfOnChangeFunctors() const = 0; - - ////////////////////////////////////////////////////////////////////////// - // Returns the functors with the specified id. - virtual const SFunctor& GetOnChangeFunctor(uint64 nFunctorId) const = 0; - - ////////////////////////////////////////////////////////////////////////// - // Removes an on change functor - // returns true if removal was successful. - virtual bool RemoveOnChangeFunctor(uint64 nFunctorId) = 0; - ////////////////////////////////////////////////////////////////////////// // Get the current callback function. virtual ConsoleVarFunc GetOnChangeCallback() const = 0; @@ -685,5 +653,3 @@ struct ICVar // Set the data probe string value of the variable virtual void SetDataProbeString(const char* pDataProbeString) = 0; }; - -#endif // CRYINCLUDE_CRYCOMMON_ICONSOLE_H diff --git a/Code/Legacy/CryCommon/IEntityRenderState.h b/Code/Legacy/CryCommon/IEntityRenderState.h index c4267b28f2..b459a6acaa 100644 --- a/Code/Legacy/CryCommon/IEntityRenderState.h +++ b/Code/Legacy/CryCommon/IEntityRenderState.h @@ -13,9 +13,10 @@ #include #include #include +#include -namespace AZ +namespace AZ { class Vector2; } @@ -29,560 +30,16 @@ struct SFrameLodInfo; struct pe_params_area; struct pe_articgeomparams; -// @NOTE: When removing an item from this enum, replace it with a dummy - ID's from this enum are stored in data and should not change. -enum EERType -{ - eERType_NotRenderNode, - eERType_Dummy_10, - eERType_Dummy8, - eERType_Light, - eERType_Cloud, - eERType_TerrainSystem, // used to be eERType_Dummy_1 which used to be eERType_VoxelObject, preserve order for compatibility - eERType_FogVolume, - eERType_Decal, - eERType_Dummy_6, // used to be eERType_ParticleEmitter, preserve order for compatibility - eERType_WaterVolume, - eERType_Dummy_5, // used to be eERType_WaterWave, preserve order for compatibility - eERType_Dummy_7, // used to be eERType_Road, preserve order for compatibility - eERType_DistanceCloud, - eERType_VolumeObject, - eERType_Dummy_0, // used to be eERType_AutoCubeMap, preserve order for compatibility - eERType_Rope, - eERType_PrismObject, - eERType_Dummy_2, // used to be eERType_IsoMesh, preserve order for compatibility - eERType_Dummy_4, - eERType_RenderComponent, - eERType_GameEffect, - eERType_BreakableGlass, - eERType_Dummy_3, // used to be eERType_LightShape, preserve order for compatibility - eERType_Dummy_9, - eERType_GeomCache, - eERType_StaticMeshRenderComponent, - eERType_DynamicMeshRenderComponent, - eERType_SkinnedMeshRenderComponent, - eERType_TypesNum, // MUST BE AT END TOTAL NUMBER OF ERTYPES -}; - -enum ERNListType -{ - eRNListType_Unknown, - eRNListType_DecalsAndRoads, - eRNListType_ListsNum, - eRNListType_First = eRNListType_Unknown, // This should be the last member - // And it counts on eRNListType_Unknown - // being the first enum element. -}; - -enum EOcclusionObjectType -{ - eoot_OCCLUDER, - eoot_OCEAN, - eoot_OCCELL, - eoot_OCCELL_OCCLUDER, - eoot_OBJECT, - eoot_OBJECT_TO_LIGHT, - eoot_TERRAIN_NODE, - eoot_PORTAL, -}; - -// RenderNode flags - -#define ERF_GOOD_OCCLUDER BIT(0) -#define ERF_PROCEDURAL BIT(1) -#define ERF_CLONE_SOURCE BIT(2) // set if this object was cloned from another one -#define ERF_CASTSHADOWMAPS BIT(3) // if you ever set this flag, be sure also to set ERF_HAS_CASTSHADOWMAPS -#define ERF_RENDER_ALWAYS BIT(4) -#define ERF_DYNAMIC_DISTANCESHADOWS BIT(5) -#define ERF_HIDABLE BIT(6) -#define ERF_HIDABLE_SECONDARY BIT(7) -#define ERF_HIDDEN BIT(8) -#define ERF_SELECTED BIT(9) -#define ERF_PROCEDURAL_ENTITY BIT(10) // this is an object generated at runtime which has a limited lifetime (matches procedural entity) -#define ERF_OUTDOORONLY BIT(11) -#define ERF_NODYNWATER BIT(12) -#define ERF_EXCLUDE_FROM_TRIANGULATION BIT(13) -#define ERF_REGISTER_BY_BBOX BIT(14) -#define ERF_STATIC_INSTANCING BIT(15) -#define ERF_VOXELIZE_STATIC BIT(16) -#define ERF_NO_PHYSICS BIT(17) -#define ERF_NO_DECALNODE_DECALS BIT(18) -#define ERF_REGISTER_BY_POSITION BIT(19) -#define ERF_COMPONENT_ENTITY BIT(20) -#define ERF_RECVWIND BIT(21) -#define ERF_COLLISION_PROXY BIT(22) // Collision proxy is a special object that is only visible in editor -// and used for physical collisions with player and vehicles. -#define ERF_LOD_BBOX_BASED BIT(23) // Lod changes based on bounding boxes. -#define ERF_SPEC_BIT0 BIT(24) // Bit0 of min config specification. -#define ERF_SPEC_BIT1 BIT(25) // Bit1 of min config specification. -#define ERF_SPEC_BIT2 BIT(26) // Bit2 of min config specification. -#define ERF_SPEC_BITS_MASK (ERF_SPEC_BIT0 | ERF_SPEC_BIT1 | ERF_SPEC_BIT2) // Bit mask of the min spec bits. -#define ERF_SPEC_BITS_SHIFT (24) // Bit offset of the ERF_SPEC_BIT0. -#define ERF_RAYCAST_PROXY BIT(27) // raycast proxy is only used for raycasting -#define ERF_HUD BIT(28) // Hud object that can avoid some visibility tests -#define ERF_RAIN_OCCLUDER BIT(29) // Is used for rain occlusion map -#define ERF_HAS_CASTSHADOWMAPS BIT(30) // at one point had ERF_CASTSHADOWMAPS set -#define ERF_ACTIVE_LAYER BIT(31) // the node is on a currently active layer - -struct IShadowCaster -{ - // - virtual ~IShadowCaster(){} - virtual bool HasOcclusionmap([[maybe_unused]] int nLod, [[maybe_unused]] IRenderNode* pLightOwner) { return false; } - virtual CLodValue ComputeLod(int wantedLod, [[maybe_unused]] const SRenderingPassInfo& passInfo) { return CLodValue(wantedLod); } - virtual void Render(const SRendParams& RendParams, const SRenderingPassInfo& passInfo) = 0; - virtual const AABB GetBBoxVirtual() = 0; - virtual void FillBBox(AABB& aabb) = 0; - virtual EERType GetRenderNodeType() = 0; - virtual bool IsRenderNode() { return true; } - // - uint8 m_cStaticShadowLod; -}; - -// Optional filter function for octree queries to perform custom filtering of the results. -// return true to keep the render node, false to filter it out. -using ObjectTreeQueryFilterCallback = AZStd::function; - -struct IOctreeNode -{ -public: - virtual ~IOctreeNode() {}; - - virtual void GetObjectsByType(PodArray& lstObjects, EERType objType, const AABB* pBBox, ObjectTreeQueryFilterCallback filterCallback = nullptr) = 0; - - struct CVisArea* m_pVisArea; -}; - -struct SLodDistDissolveTransitionState -{ - float fStartDist; - int8 nOldLod; - int8 nNewLod; - bool bFarside; -}; - -struct SLightInfo -{ - bool operator == (const SLightInfo& other) const - { return other.vPos.IsEquivalent(vPos, 0.1f) && fabs(other.fRadius - fRadius) < 0.1f; } - Vec3 vPos; - float fRadius; - bool bAffecting; -}; - struct IRenderNode - : public IShadowCaster { - enum EInternalFlags - { - DECAL_OWNER = BIT(0), // Owns some decals. - REQUIRES_NEAREST_CUBEMAP = BIT(1), // Pick nearest cube map - UPDATE_DECALS = BIT(2), // The node changed geometry - decals must be updated. - REQUIRES_FORWARD_RENDERING = BIT(3), // Special shadow processing needed. - WAS_INVISIBLE = BIT(4), // Was invisible last frame. - WAS_IN_VISAREA = BIT(5), // Was inside vis-ares last frame. - WAS_FARAWAY = BIT(6), // Was considered 'far away' for the purposes of physics deactivation. - HAS_OCCLUSION_PROXY = BIT(7) // This node has occlusion proxy. - }; - - IRenderNode() - { - m_dwRndFlags = 0; - m_fViewDistanceMultiplier = static_cast(IRenderNode::VIEW_DISTANCE_MULTIPLIER_MAX); // By default object is not limited by distance. - m_ucLodRatio = 100; - m_pOcNode = 0; - m_fWSMaxViewDist = 0; - m_nInternalFlags = 0; - m_nMaterialLayers = 0; - m_pRNTmpData = NULL; - m_pPrev = m_pNext = NULL; - m_nSID = 0; - m_cShadowLodBias = 0; - m_cStaticShadowLod = 0; - } - - virtual bool CanExecuteRenderAsJob() { return false; } - - // - // Debug info about object. - virtual const char* GetName() const = 0; - virtual const char* GetEntityClassName() const = 0; - virtual AZStd::string GetDebugString([[maybe_unused]] char type = 0) const { return ""; } - virtual float GetImportance() const { return 1.f; } - - // Description: - // Releases IRenderNode. - virtual void ReleaseNode([[maybe_unused]] bool bImmediate = false) { delete this; } - - - virtual IRenderNode* Clone() const { return NULL; } - - // Description: - // Sets render node transformation matrix. - virtual void SetMatrix([[maybe_unused]] const Matrix34& mat) {} - - // Description: - // Gets local bounds of the render node. - virtual void GetLocalBounds(AABB& bbox) { AABB WSBBox(GetBBox()); bbox = AABB(WSBBox.min - GetPos(true), WSBBox.max - GetPos(true)); } - - virtual Vec3 GetPos(bool bWorldOnly = true) const = 0; - virtual const AABB GetBBox() const = 0; - virtual void FillBBox(AABB& aabb) { aabb = GetBBox(); } - virtual void SetBBox(const AABB& WSBBox) = 0; - - virtual void SetScale([[maybe_unused]] const Vec3& scale) {} - - //Get the scales assuming the scale is uniform or per column as needed. - virtual float GetUniformScale() { return 1.0f; } - virtual float GetColumnScale([[maybe_unused]] int column) { return 1.0f; } - - // Summary: - // Changes the world coordinates position of this node by delta - // Don't forget to call this base function when overriding it. - virtual void OffsetPosition(const Vec3& delta) = 0; - - // Return true when the node is initialized and ready to render - virtual bool IsReady() const { return true; } - - // Summary: - // Renders node geometry - virtual void Render(const struct SRendParams& EntDrawParams, const SRenderingPassInfo& passInfo) = 0; - - // Hides/disables node in renderer. - virtual void Hide(bool bHide) { SetRndFlags(ERF_HIDDEN, bHide); } - bool IsHidden() const { return (GetRndFlags() & ERF_HIDDEN) != 0; } - // Gives access to object components. - virtual struct IStatObj* GetEntityStatObj(unsigned int nPartId = 0, unsigned int nSubPartId = 0, Matrix34A* pMatrix = NULL, bool bReturnOnlyVisible = false); - virtual _smart_ptr GetEntitySlotMaterial([[maybe_unused]] unsigned int nPartId, [[maybe_unused]] bool bReturnOnlyVisible = false, [[maybe_unused]] bool* pbDrawNear = NULL) { return NULL; } - virtual void SetEntityStatObj([[maybe_unused]] unsigned int nSlot, [[maybe_unused]] IStatObj* pStatObj, [[maybe_unused]] const Matrix34A* pMatrix = NULL) {}; - virtual int GetSlotCount() const { return 1; } - - // Summary: - // Returns IRenderMesh of the object. - virtual struct IRenderMesh* GetRenderMesh([[maybe_unused]] int nLod) { return 0; }; - - // Description: - // Allows to adjust default lod distance settings, - // if fLodRatio is 100 - default lod distance is used. - virtual void SetLodRatio(int nLodRatio) { m_ucLodRatio = static_cast(min(255, max(0, nLodRatio))); } - - // Summary: - // Gets material layers mask. - virtual uint8 GetMaterialLayers() const { return m_nMaterialLayers; } - - - // Summary - // Physicalizes if it isn't already. - virtual void CheckPhysicalized() {}; - - // Summary: - // Physicalizes node. - virtual void Physicalize([[maybe_unused]] bool bInstant = false) {} - - virtual ~IRenderNode() { assert(!m_pRNTmpData); }; - - // Summary: - // Sets override material for this instance. - virtual void SetMaterial(_smart_ptr pMat) = 0; - // Summary: - // Queries override material of this instance. - virtual _smart_ptr GetMaterial(Vec3* pHitPos = NULL) = 0; - virtual _smart_ptr GetMaterialOverride() = 0; - virtual void GetMaterials(AZStd::vector<_smart_ptr>& materials) - { - _smart_ptr currentMaterial = GetMaterialOverride(); - if (!currentMaterial) - { - currentMaterial = GetMaterial(); - } - if (currentMaterial) - { - materials.push_back(currentMaterial); - } + struct IStatObj* GetEntityStatObj(unsigned int = 0, unsigned int = 0, Matrix34A* = NULL, bool = false) { + return nullptr; } - // Used by the editor during export - virtual void SetCollisionClassIndex([[maybe_unused]] int tableIndex) {} - - virtual int GetEditorObjectId() { return 0; } - virtual void SetEditorObjectId([[maybe_unused]] int nEditorObjectId) {} - virtual void SetStatObjGroupIndex([[maybe_unused]] int nVegetationGroupIndex) { } - virtual int GetStatObjGroupId() const { return -1; } - virtual void SetLayerId([[maybe_unused]] uint16 nLayerId) { } - virtual uint16 GetLayerId() { return 0; } - virtual float GetMaxViewDist() = 0; - - virtual EERType GetRenderNodeType() = 0; - virtual bool IsAllocatedOutsideOf3DEngineDLL() - { - return GetRenderNodeType() == eERType_RenderComponent || - GetRenderNodeType() == eERType_StaticMeshRenderComponent || - GetRenderNodeType() == eERType_DynamicMeshRenderComponent || - GetRenderNodeType() == eERType_SkinnedMeshRenderComponent; - } - virtual void Dephysicalize([[maybe_unused]] bool bKeepIfReferenced = false) {} - virtual void Dematerialize() {} - virtual void GetMemoryUsage(ICrySizer* pSizer) const = 0; - - virtual void Precache() {}; - - virtual const AABB GetBBoxVirtual() { return GetBBox(); } - - // virtual float GetLodForDistance(float fDistance) { return 0; } - - virtual void OnRenderNodeBecomeVisible([[maybe_unused]] const SRenderingPassInfo& passInfo) {} - virtual void OnPhysAreaChange() {} - - virtual bool IsMovableByGame() const { return false; } - - virtual uint8 GetSortPriority() { return 0; } - - // Types of voxelization for objects and lights - enum EVoxelGIMode : int - { - VM_None = 0, // No voxelization - VM_Static, // Incremental or asynchronous lazy voxelization - VM_Dynamic, // Real-time every-frame voxelization on GPU - }; - - virtual EVoxelGIMode GetVoxelGIMode() { return VM_None; } - virtual void SetDesiredVoxelGIMode([[maybe_unused]] EVoxelGIMode voxelMode) {} - - virtual void SetMinSpec(int nMinSpec) { m_dwRndFlags &= ~ERF_SPEC_BITS_MASK; m_dwRndFlags |= (nMinSpec << ERF_SPEC_BITS_SHIFT) & ERF_SPEC_BITS_MASK; }; - - // Description: - // Allows to adjust default max view distance settings, - // if fMaxViewDistRatio is 1.0f - default max view distance is used. - virtual void SetViewDistanceMultiplier(float fViewDistanceMultiplier); - // - - void CopyIRenderNodeData(IRenderNode* pDest) const - { - pDest->m_fWSMaxViewDist = m_fWSMaxViewDist; - pDest->m_dwRndFlags = m_dwRndFlags; - //pDest->m_pOcNode = m_pOcNode; // Removed to stop the registering from earlying out. - pDest->m_fViewDistanceMultiplier = m_fViewDistanceMultiplier; - pDest->m_ucLodRatio = m_ucLodRatio; - pDest->m_cShadowLodBias = m_cShadowLodBias; - pDest->m_cStaticShadowLod = m_cStaticShadowLod; - pDest->m_nInternalFlags = m_nInternalFlags; - pDest->m_nMaterialLayers = m_nMaterialLayers; - //pDestBrush->m_pRNTmpData //If this is copied from the source render node, there are two - // pointers to the same data, and if either is deleted, there will - // be a crash when the dangling pointer is used on the other - } - - // Rendering flags. - ILINE void SetRndFlags(unsigned int dwFlags) { m_dwRndFlags = dwFlags; } - ILINE void SetRndFlags(unsigned int dwFlags, bool bEnable) - { - if (bEnable) - { - SetRndFlags(m_dwRndFlags | dwFlags); - } - else - { - SetRndFlags(m_dwRndFlags & (~dwFlags)); - } - } - ILINE unsigned int GetRndFlags() const { return m_dwRndFlags; } - - // Object draw frames (set if was drawn). - ILINE void SetDrawFrame(int nFrameID, int nRecursionLevel) - { - assert(m_pRNTmpData); - int* pDrawFrames = (int*)m_pRNTmpData; - pDrawFrames[nRecursionLevel] = nFrameID; - } - - ILINE int GetDrawFrame(int nRecursionLevel = 0) const - { - IF (!m_pRNTmpData, 0) - { - return 0; - } - - int* pDrawFrames = (int*)m_pRNTmpData; - return pDrawFrames[nRecursionLevel]; - } - - // Returns: - // Current VisArea or null if in outdoors or entity was not registered in 3dengine. - ILINE IVisArea* GetEntityVisArea() const { return m_pOcNode ? (IVisArea*)(m_pOcNode->m_pVisArea) : NULL; } - - // Summary: - // Makes object visible at any distance. - ILINE void SetViewDistUnlimited() { SetViewDistanceMultiplier(100.0f); } - - // Summary: - // Retrieves the view distance settings. - ILINE float GetViewDistanceMultiplier() const - { - return m_fViewDistanceMultiplier; - } - - // Summary: - // Returns lod distance ratio. - ILINE int GetLodRatio() const { return m_ucLodRatio; } - - // Summary: - // Returns lod distance ratio - ILINE float GetLodRatioNormalized() const { return 0.01f * m_ucLodRatio; } - - virtual bool GetLodDistances([[maybe_unused]] const SFrameLodInfo& frameLodInfo, [[maybe_unused]] float* distances) const { return false; } - - // Returns distance for first lod change, not factoring in distance multiplier or lod ratio - virtual float GetFirstLodDistance() const { return FLT_MAX; } - - // Description: - // Bias value to add to the regular lod - virtual void SetShadowLodBias(int8 nShadowLodBias) { m_cShadowLodBias = nShadowLodBias; } - - // Summary: - // Returns lod distance ratio. - ILINE int GetShadowLodBias() const { return m_cShadowLodBias; } - - // Summary: - // Sets material layers mask. - ILINE void SetMaterialLayers(uint8 nMtlLayers) { m_nMaterialLayers = nMtlLayers; } - - ILINE int GetMinSpec() const { return (m_dwRndFlags & ERF_SPEC_BITS_MASK) >> ERF_SPEC_BITS_SHIFT; }; - - static const ERNListType GetRenderNodeListId(const EERType eRType) - { - switch (eRType) - { - case eERType_Decal: - return eRNListType_DecalsAndRoads; - default: - return eRNListType_Unknown; - } - } - - virtual AZ::EntityId GetEntityId() { return AZ::EntityId(); } - - ////////////////////////////////////////////////////////////////////////// - // Variables - ////////////////////////////////////////////////////////////////////////// - -public: - - // Every sector has linked list of IRenderNode objects. - IRenderNode* m_pNext, * m_pPrev; - - // Current objects tree cell. - IOctreeNode* m_pOcNode; - - // Pointer to temporary data allocated only for currently visible objects. - struct CRNTmpData* m_pRNTmpData; - - // Max view distance. - float m_fWSMaxViewDist; - - // Render flags. - int m_dwRndFlags; - - // Shadow LOD bias - // Set to SHADOW_LODBIAS_DISABLE to disable any shadow lod overrides for this rendernode - static const int8 SHADOW_LODBIAS_DISABLE = -128; - int8 m_cShadowLodBias; - - // Segment Id - int m_nSID; + int GetSlotCount() const { return 1; } // Max view distance settings. - static const int VIEW_DISTANCE_MULTIPLIER_MAX = 100; - float m_fViewDistanceMultiplier; + static constexpr int VIEW_DISTANCE_MULTIPLIER_MAX = 100; - // LOD settings. - unsigned char m_ucLodRatio; - - // Flags for render node internal usage, one or more bits from EInternalFlags. - unsigned char m_nInternalFlags; - - // Material layers bitmask -> which material layers are active. - unsigned char m_nMaterialLayers; -}; - -inline void IRenderNode::SetViewDistanceMultiplier(float fViewDistanceMultiplier) -{ - fViewDistanceMultiplier = CLAMP(fViewDistanceMultiplier, 0.0f, 100.0f); - if (fabs(m_fViewDistanceMultiplier - fViewDistanceMultiplier) > FLT_EPSILON) - { - m_fViewDistanceMultiplier = fViewDistanceMultiplier; - } -} - - -/////////////////////////////////////////////////////////////////////////////// -inline IStatObj* IRenderNode::GetEntityStatObj([[maybe_unused]] unsigned int nPartId, [[maybe_unused]] unsigned int nSubPartId, [[maybe_unused]] Matrix34A* pMatrix, [[maybe_unused]] bool bReturnOnlyVisible) -{ - return 0; -} - - -//We must use interfaces instead of unsafe type casts and unnecessary includes - -struct ILightSource - : public IRenderNode -{ - // - virtual void SetLightProperties(const CDLight& light) = 0; - virtual CDLight& GetLightProperties() = 0; - virtual const Matrix34& GetMatrix() = 0; - virtual struct ShadowMapFrustum* GetShadowFrustum(int nId = 0) = 0; - virtual bool IsLightAreasVisible() = 0; - virtual void SetCastingException(IRenderNode* pNotCaster) = 0; - virtual void SetName(const char* name) = 0; - // -}; - -struct SCloudMovementProperties -{ - bool m_autoMove; - Vec3 m_speed; - Vec3 m_spaceLoopBox; - float m_fadeDistance; -}; - -// Summary: -// ICloudRenderNode is an interface to the Cloud Render Node object. -struct ICloudRenderNode - : public IRenderNode -{ - // - // Description: - // Loads a cloud from a cloud description XML file. - virtual bool LoadCloud(const char* sCloudFilename) = 0; - virtual bool LoadCloudFromXml(XmlNodeRef cloudNode) = 0; - virtual void SetMovementProperties(const SCloudMovementProperties& properties) = 0; - // -}; - -// Summary: -// IVoxelObject is an interface to the Voxel Object Render Node object. -struct IVoxelObject - : public IRenderNode -{ - // - virtual void SetCompiledData(void* pData, int nSize, uint8 ucChildId, EEndian eEndian) = 0; - virtual void SetObjectName(const char* pName) = 0; - virtual void SetMatrix(const Matrix34& mat) = 0; - virtual bool ResetTransformation() = 0; - virtual void InterpolateVoxelData() = 0; - virtual void SetFlags(int nFlags) = 0; - virtual void Regenerate() = 0; - virtual void CopyHM() = 0; - virtual bool IsEmpty() = 0; - // -}; - -// LY renderer system spec levels. -enum class EngineSpec : AZ::u32 -{ - Low = 1, - Medium, - High, - VeryHigh, - Never = UINT_MAX, }; diff --git a/Code/Legacy/CryCommon/IEntityRenderState_info.cpp b/Code/Legacy/CryCommon/IEntityRenderState_info.cpp deleted file mode 100644 index 762c741214..0000000000 --- a/Code/Legacy/CryCommon/IEntityRenderState_info.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - -#include "TypeInfo_impl.h" -#include // <> required for Interfuscator - -ENUM_INFO_BEGIN(EERType) -ENUM_ELEM_INFO(, eERType_NotRenderNode) -ENUM_ELEM_INFO(, eERType_Dummy_10) -ENUM_ELEM_INFO(, eERType_Light) -ENUM_ELEM_INFO(, eERType_Cloud) -ENUM_ELEM_INFO(, eERType_TerrainSystem) -ENUM_ELEM_INFO(, eERType_FogVolume) -ENUM_ELEM_INFO(, eERType_Decal) -ENUM_ELEM_INFO(, eERType_Dummy_6) -ENUM_ELEM_INFO(, eERType_WaterVolume) -ENUM_ELEM_INFO(, eERType_Dummy_7) -ENUM_ELEM_INFO(, eERType_DistanceCloud) -ENUM_ELEM_INFO(, eERType_VolumeObject) -ENUM_ELEM_INFO(, eERType_Dummy_0) -ENUM_ELEM_INFO(, eERType_Rope) -ENUM_ELEM_INFO(, eERType_PrismObject) -ENUM_ELEM_INFO(, eERType_Dummy_2) -ENUM_ELEM_INFO(, eERType_Dummy_4) -ENUM_ELEM_INFO(, eERType_RenderComponent) -ENUM_ELEM_INFO(, eERType_StaticMeshRenderComponent) -ENUM_ELEM_INFO(, eERType_DynamicMeshRenderComponent) -ENUM_ELEM_INFO(, eERType_SkinnedMeshRenderComponent) -ENUM_ELEM_INFO(, eERType_GameEffect) -ENUM_ELEM_INFO(, eERType_BreakableGlass) -ENUM_ELEM_INFO(, eERType_Dummy_3) -ENUM_ELEM_INFO(, eERType_Dummy_9) -ENUM_ELEM_INFO(, eERType_GeomCache) -ENUM_ELEM_INFO(, eERType_TypesNum) -ENUM_INFO_END(EERType) diff --git a/Code/Legacy/CryCommon/IFont.h b/Code/Legacy/CryCommon/IFont.h index 41e9f5653a..15cc6568bf 100644 --- a/Code/Legacy/CryCommon/IFont.h +++ b/Code/Legacy/CryCommon/IFont.h @@ -19,6 +19,7 @@ #include #include +#include #include struct ISystem; diff --git a/Code/Legacy/CryCommon/IIndexedMesh.h b/Code/Legacy/CryCommon/IIndexedMesh.h index 1c91bb82b8..a84cebacb3 100644 --- a/Code/Legacy/CryCommon/IIndexedMesh.h +++ b/Code/Legacy/CryCommon/IIndexedMesh.h @@ -7,16 +7,12 @@ */ -#ifndef CRYINCLUDE_CRYCOMMON_IINDEXEDMESH_H -#define CRYINCLUDE_CRYCOMMON_IINDEXEDMESH_H #pragma once -#include "CryHeaders.h" #include "Cry_Color.h" #include "StlUtils.h" #include "CryEndian.h" -#include #include // for AABB #include #include @@ -58,74 +54,16 @@ public: t = other.y; } - void ExportTo(Vec2f16& other) const - { - other = Vec2f16(s, t); - } - - void ExportTo(float& others, float& othert) const - { - others = s; - othert = t; - } - - bool operator ==(const SMeshTexCoord& other) const - { - return (s == other.s) && (t == other.t); - } - - bool operator !=(const SMeshTexCoord& other) const - { - return !(*this == other); - } - - bool operator <(const SMeshTexCoord& other) const - { - return (s != other.s) ? (s < other.s) : (t < other.t); - } - - bool IsEquivalent(const Vec2& other, float epsilon = 0.003f) const - { - return - (fabs_tpl(s - other.x) <= epsilon) && - (fabs_tpl(t - other.y) <= epsilon); - } - bool IsEquivalent(const SMeshTexCoord& other, float epsilon = 0.00005f) const { return (fabs_tpl(s - other.s) <= epsilon) && (fabs_tpl(t - other.t) <= epsilon); } - ILINE Vec2 GetUV() const { return Vec2(s, t); } - - void GetUV(Vec2& otheruv) const - { - otheruv = GetUV(); - } - - void GetUV(Vec4& otheruv) const - { - otheruv = Vec4(s, t, 0.0f, 1.0f); - } - - void Lerp(const SMeshTexCoord& other, float pos) - { - Vec2 texA; - Vec2 texB; - this->GetUV(); - other.GetUV(); - - texA.SetLerp(texA, texB, pos); - - *this = SMeshTexCoord(texA); - } - - AUTO_STRUCT_INFO }; // Description: @@ -145,55 +83,6 @@ public: b = otherb; a = othera; } - - void TransferRGBTo(SMeshColor& other) const - { - other.r = r; - other.g = g; - other.b = b; - } - - void TransferATo(SMeshColor& other) const - { - other.a = a; - } - - void MaskA(uint8 maska) - { - a &= maska; - } - - bool operator ==(const SMeshColor& other) const - { - return (r == other.r) && (g == other.g) && (b == other.b) && (a == other.a); - } - - bool operator !=(const SMeshColor& other) const - { - return !(*this == other); - } - - bool operator <(const SMeshColor& other) const - { - return (r != other.r) ? (r < other.r) : (g != other.g) ? (g < other.g) : (b != other.b) ? (b < other.b) : (a < other.a); - } - - ILINE ColorB GetRGBA() const - { - return ColorB(r, g, b, a); - } - - void GetRGBA(ColorB& otherc) const - { - otherc = GetRGBA(); - } - - void GetRGBA(Vec4& otherc) const - { - otherc = Vec4(r, g, b, a); - } - - AUTO_STRUCT_INFO }; @@ -203,8 +92,6 @@ struct SMeshFace { int v[3]; // indices to vertex, normals and optionally tangent basis arrays unsigned char nSubset; // index to mesh subsets array. - - AUTO_STRUCT_INFO }; // Description: @@ -222,380 +109,11 @@ public: Normal = othern; } - bool operator ==(const SMeshNormal& othern) const - { - return (Normal.x == othern.Normal.x) && (Normal.y == othern.Normal.y) && (Normal.z == othern.Normal.z); - } + Vec3 GetN() const { return Normal; } - bool operator !=(const SMeshNormal& othern) const - { - return !(*this == othern); - } - - bool operator <(const SMeshNormal& othern) const - { - return (Normal.x != othern.Normal.x) ? (Normal.x < othern.Normal.x) : (Normal.y != othern.Normal.y) ? (Normal.y < othern.Normal.y) : (Normal.z < othern.Normal.z); - } - - bool IsEquivalent(const Vec3& othern, float epsilon = 0.00005f) const - { - return - Normal.IsEquivalent(othern, epsilon); - } - - bool IsEquivalent(const SMeshNormal& othern, float epsilon = 0.00005f) const - { - return - IsEquivalent(othern.Normal, epsilon); - } - - ILINE Vec3 GetN() const - { - return Normal; - } - - void GetN(Vec3& othern) const - { - othern = GetN(); - } - - void RotateBy(const Matrix33& rot) - { - Normal = rot * Normal; - } - - void RotateSafelyBy(const Matrix33& rot) - { - Normal = rot * Normal; - // normalize in case "rot" wasn't length-preserving - Normal.Normalize(); - } - - void RotateBy(const Matrix34& trn) - { - Normal = trn.TransformVector(Normal); - } - - void RotateSafelyBy(const Matrix34& trn) - { - Normal = trn.TransformVector(Normal); - // normalize in case "trn" wasn't length-preserving - Normal.Normalize(); - } - - void Slerp(const SMeshNormal& other, float pos) - { - Vec3 nrmA = this->GetN(); - Vec3 nrmB = other.GetN(); - - nrmA.Normalize(); - nrmB.Normalize(); - - nrmA.SetSlerp(nrmA, nrmB, pos); - - *this = SMeshNormal(nrmA); - } - - AUTO_STRUCT_INFO }; -// Description: -// Mesh tangents (tangent space normals). -struct SMeshTangents -{ - SMeshTangents() {} - -private: - Vec4sf Tangent; - Vec4sf Bitangent; - -public: - explicit SMeshTangents(const Vec4sf& othert, const Vec4sf& otherb) - { - Tangent = othert; - Bitangent = otherb; - } - - explicit SMeshTangents(const SPipTangents& other) - { - Tangent = other.Tangent; - Bitangent = other.Bitangent; - } - - explicit SMeshTangents(const Vec4& othert, const Vec4& otherb) - { - Tangent = PackingSNorm::tPackF2Bv(othert); - Bitangent = PackingSNorm::tPackF2Bv(otherb); - } - - explicit SMeshTangents(const Vec3& othert, const Vec3& otherb, const Vec3& othern) - { - // TODO: can be optimized to use only integer arithmetic - int16 othersign = 1; - if (othert.Cross(otherb).Dot(othern) < 0) - { - othersign = -1; - } - - Tangent = Vec4sf(PackingSNorm::tPackF2B(othert.x), PackingSNorm::tPackF2B(othert.y), PackingSNorm::tPackF2B(othert.z), PackingSNorm::tPackS2B(othersign)); - Bitangent = Vec4sf(PackingSNorm::tPackF2B(otherb.x), PackingSNorm::tPackF2B(otherb.y), PackingSNorm::tPackF2B(otherb.z), PackingSNorm::tPackS2B(othersign)); - } - - explicit SMeshTangents(const Vec3& othert, const Vec3& otherb, const int16& othersign) - { - Tangent = Vec4sf(PackingSNorm::tPackF2B(othert.x), PackingSNorm::tPackF2B(othert.y), PackingSNorm::tPackF2B(othert.z), PackingSNorm::tPackS2B(othersign)); - Bitangent = Vec4sf(PackingSNorm::tPackF2B(otherb.x), PackingSNorm::tPackF2B(otherb.y), PackingSNorm::tPackF2B(otherb.z), PackingSNorm::tPackS2B(othersign)); - } - - void ExportTo(Vec4sf& othert, Vec4sf& otherb) const - { - othert = Tangent; - otherb = Bitangent; - } - - void ExportTo(SPipTangents& other) const - { - other.Tangent = Tangent; - other.Bitangent = Bitangent; - } - - bool operator ==(const SMeshTangents& other) const - { - return - Tangent[0] == other.Tangent[0] || - Tangent[1] == other.Tangent[1] || - Tangent[2] == other.Tangent[2] || - Tangent[3] == other.Tangent[3] || - Bitangent[0] == other.Bitangent[0] || - Bitangent[1] == other.Bitangent[1] || - Bitangent[2] == other.Bitangent[2] || - Bitangent[3] == other.Bitangent[3]; - } - - bool operator !=(const SMeshTangents& other) const - { - return !(*this == other); - } - - bool IsEquivalent(const Vec3& othert, const Vec3& otherb, const int16& othersign, float epsilon = 0.01f) const - { - // TODO: can be optimized to use only integer arithmetic - Vec4 tng, btg; - GetTB(tng, btg); - - Vec3 tng3(tng.x, tng.y, tng.z); - Vec3 btg3(btg.x, btg.y, btg.z); - - return - (tng.w == othersign) && - (btg.w == othersign) && - (tng3.Dot(othert) >= (1.0f - epsilon)) && - (btg3.Dot(otherb) >= (1.0f - epsilon)); - } - - void GetTB(Vec4sf& othert, Vec4sf& otherb) const - { - othert = Tangent; - otherb = Bitangent; - } - - void GetTB(Vec4& othert, Vec4& otherb) const - { - othert = PackingSNorm::tPackB2F(Tangent); - otherb = PackingSNorm::tPackB2F(Bitangent); - } - - void GetTB(Vec3& othert, Vec3& otherb) const - { - const Vec4 t = PackingSNorm::tPackB2F(Tangent); - const Vec4 b = PackingSNorm::tPackB2F(Bitangent); - - othert = Vec3(t.x, t.y, t.z); - otherb = Vec3(b.x, b.y, b.z); - } - - ILINE Vec3 GetN() const - { - Vec4 tng, btg; - GetTB(tng, btg); - - Vec3 tng3(tng.x, tng.y, tng.z); - Vec3 btg3(btg.x, btg.y, btg.z); - - // assumes w 1 or -1 - return tng3.Cross(btg3) * tng.w; - } - - void GetN(Vec3& othern) const - { - othern = GetN(); - } - - void GetTBN(Vec3& othert, Vec3& otherb, Vec3& othern) const - { - Vec4 tng, btg; - GetTB(tng, btg); - - Vec3 tng3(tng.x, tng.y, tng.z); - Vec3 btg3(btg.x, btg.y, btg.z); - - // assumes w 1 or -1 - othert = tng3; - otherb = btg3; - othern = tng3.Cross(btg3) * tng.w; - } - - ILINE int16 GetR() const - { - return PackingSNorm::tPackB2S(Tangent.w); - } - - void GetR(int16& sign) const - { - sign = GetR(); - } - - void RotateBy(const Matrix33& rot) - { - Vec4 tng, btg; - GetTB(tng, btg); - - Vec3 tng3(tng.x, tng.y, tng.z); - Vec3 btg3(btg.x, btg.y, btg.z); - - tng3 = rot * tng3; - btg3 = rot * btg3; - - *this = SMeshTangents(tng3, btg3, PackingSNorm::tPackB2S(Tangent.w)); - } - - void RotateSafelyBy(const Matrix33& rot) - { - Vec4 tng, btg; - GetTB(tng, btg); - - Vec3 tng3(tng.x, tng.y, tng.z); - Vec3 btg3(btg.x, btg.y, btg.z); - - tng3 = rot * tng3; - btg3 = rot * btg3; - - // normalize in case "rot" wasn't length-preserving - tng3.Normalize(); - btg3.Normalize(); - - *this = SMeshTangents(tng3, btg3, PackingSNorm::tPackB2S(Tangent.w)); - } - - void RotateBy(const Matrix34& trn) - { - Vec4 tng, btg; - GetTB(tng, btg); - - Vec3 tng3(tng.x, tng.y, tng.z); - Vec3 btg3(btg.x, btg.y, btg.z); - - tng3 = trn.TransformVector(tng3); - btg3 = trn.TransformVector(btg3); - - *this = SMeshTangents(tng3, btg3, PackingSNorm::tPackB2S(Tangent.w)); - } - - void RotateSafelyBy(const Matrix34& trn) - { - Vec4 tng, btg; - GetTB(tng, btg); - - Vec3 tng3(tng.x, tng.y, tng.z); - Vec3 btg3(btg.x, btg.y, btg.z); - - tng3 = trn.TransformVector(tng3); - btg3 = trn.TransformVector(btg3); - - // normalize in case "rot" wasn't length-preserving - tng3.Normalize(); - btg3.Normalize(); - - *this = SMeshTangents(tng3, btg3, PackingSNorm::tPackB2S(Tangent.w)); - } - - void SlerpTowards(const SMeshTangents& other, const SMeshNormal& normal, float pos) - { - Vec3 tngA, btgA; - Vec3 tngB, btgB; - this->GetTB(tngA, btgA); - other.GetTB(tngB, btgB); - - // Q: necessary? - tngA.Normalize(); - tngB.Normalize(); - btgA.Normalize(); - btgB.Normalize(); - - tngA.SetSlerp(tngA, tngB, pos); - btgA.SetSlerp(btgA, btgB, pos); - - *this = SMeshTangents(tngA, btgA, normal.GetN()); - } - - AUTO_STRUCT_INFO -}; - -struct SMeshQTangents -{ - SMeshQTangents() {} - -private: - Vec4sf TangentBitangent; - -public: - explicit SMeshQTangents(const SPipQTangents& other) - { - TangentBitangent = other.QTangent; - } - - explicit SMeshQTangents(const Quat& other) - { - TangentBitangent.x = PackingSNorm::tPackF2B(other.v.x); - TangentBitangent.y = PackingSNorm::tPackF2B(other.v.y); - TangentBitangent.z = PackingSNorm::tPackF2B(other.v.z); - TangentBitangent.w = PackingSNorm::tPackF2B(other.w); - } - - void ExportTo(SPipQTangents& other) - { - other.QTangent = TangentBitangent; - } - - ILINE Quat GetQ() const - { - Quat q; - - q.v.x = PackingSNorm::tPackB2F(TangentBitangent.x); - q.v.y = PackingSNorm::tPackB2F(TangentBitangent.y); - q.v.z = PackingSNorm::tPackB2F(TangentBitangent.z); - q.w = PackingSNorm::tPackB2F(TangentBitangent.w); - - return q; - } - - AUTO_STRUCT_INFO -}; - -// Description: -// for skinning every vertex has 4 bones and 4 weights. -struct SMeshBoneMapping_uint16 -{ - typedef uint16 BoneId; - typedef uint8 Weight; - - BoneId boneIds[4]; - Weight weights[4]; - - AUTO_STRUCT_INFO -}; - struct SMeshBoneMapping_uint8 { typedef uint8 BoneId; @@ -603,27 +121,8 @@ struct SMeshBoneMapping_uint8 BoneId boneIds[4]; Weight weights[4]; - - AUTO_STRUCT_INFO }; -//START: Add LOD support for touch bending vegetation -struct SMeshBoneMappingInfo_uint8 -{ - SMeshBoneMappingInfo_uint8(int vertexCount) - { - //Will be deleted by ~SFoliageInfoCGF() - pBoneMapping = new SMeshBoneMapping_uint8[vertexCount]; - nVertexCount = vertexCount; - } - - int nVertexCount; - struct SMeshBoneMapping_uint8* pBoneMapping; - - AUTO_STRUCT_INFO -}; -//END: Add LOD support for touch bending vegetation - // Subset of mesh is a continuous range of vertices and indices that share same material. struct SMeshSubset { @@ -653,1529 +152,11 @@ struct SMeshSubset , nNumVerts(0) , nMatID(0) , nMatFlags(0) - , nPhysicalizeType(PHYS_GEOM_TYPE_DEFAULT) + , nPhysicalizeType(0x1000) , vertexFormat(eVF_P3S_C4B_T2S) { } - void GetMemoryUsage([[maybe_unused]] class ICrySizer* pSizer) const - { - } - - // fix numVerts - void FixRanges(vtx_idx* pIndices) - { - int startVertexToMerge = nFirstVertId; - int startIndexToMerge = nFirstIndexId; - int numIndiciesToMerge = nNumIndices; - // find good min and max AGAIN - int maxVertexInUse = 0; - for (int n = 0; n < numIndiciesToMerge; n++) - { - int i = (int)pIndices[n + startIndexToMerge]; - startVertexToMerge = (i < startVertexToMerge ? i : startVertexToMerge);// min - maxVertexInUse = (i > maxVertexInUse ? i : maxVertexInUse);// max - } - nNumVerts = maxVertexInUse - startVertexToMerge + 1; - } -}; - -class CMeshHelpers -{ -public: - template - static bool ComputeTexMappingAreas( - size_t indexCount, const TIndex* pIndices, - size_t vertexCount, - const TPosition* pPositions, size_t stridePositions, - const TTexCoordinates* pTexCoords, size_t strideTexCoords, - float& computedPosArea, float& computedTexArea, const char*& errorText) - { - static const float minPosArea = 10e-6f; - static const float minTexArea = 10e-8f; - - computedPosArea = 0; - computedTexArea = 0; - errorText = "?"; - - if (indexCount <= 0) - { - errorText = "index count is 0"; - return false; - } - - if (vertexCount <= 0) - { - errorText = "vertex count is 0"; - return false; - } - - if ((pIndices == NULL) || (pPositions == NULL)) - { - errorText = "indices and/or positions are NULL"; - return false; - } - - if (pTexCoords == NULL) - { - errorText = "texture coordinates are NULL"; - return false; - } - - if (indexCount % 3 != 0) - { - assert(0); - errorText = "bad number of indices"; - return false; - } - - // Compute average geometry area of face - - int count = 0; - float posAreaSum = 0; - float texAreaSum = 0; - for (size_t i = 0; i < indexCount; i += 3) - { - const size_t index0 = pIndices[i]; - const size_t index1 = pIndices[i + 1]; - const size_t index2 = pIndices[i + 2]; - - if ((index0 >= vertexCount) || (index1 >= vertexCount) || (index2 >= vertexCount)) - { - errorText = "bad vertex index detected"; - return false; - } - - const Vec3 pos0 = ToVec3(*(const TPosition*) (((const char*)pPositions) + index0 * stridePositions)); - const Vec3 pos1 = ToVec3(*(const TPosition*) (((const char*)pPositions) + index1 * stridePositions)); - const Vec3 pos2 = ToVec3(*(const TPosition*) (((const char*)pPositions) + index2 * stridePositions)); - - const Vec2 tex0 = ToVec2(*(const TTexCoordinates*) (((const char*)pTexCoords) + index0 * strideTexCoords)); - const Vec2 tex1 = ToVec2(*(const TTexCoordinates*) (((const char*)pTexCoords) + index1 * strideTexCoords)); - const Vec2 tex2 = ToVec2(*(const TTexCoordinates*) (((const char*)pTexCoords) + index2 * strideTexCoords)); - - const float posArea = ((pos1 - pos0).Cross(pos2 - pos0)).GetLength() * 0.5f; - const float texArea = fabsf((tex1 - tex0).Cross(tex2 - tex0)) * 0.5f; - - if ((posArea >= minPosArea) && (texArea >= minTexArea)) - { - posAreaSum += posArea; - texAreaSum += texArea; - ++count; - } - } - - if (count == 0 || (posAreaSum < minPosArea) || (texAreaSum < minTexArea)) - { - errorText = "faces are too small or have stretched mapping"; - return false; - } - - computedPosArea = posAreaSum; - computedTexArea = texAreaSum; - return true; - } - - template - static bool CollectFaceAreas(size_t indexCount, const vtx_idx* pIndices, size_t vertexCount, - const TPosition* pPositions, size_t stridePositions, std::vector& areas) - { - static const float minFaceArea = 10e-6f; - - if (indexCount % 3 != 0) - { - return false; - } - - areas.reserve(areas.size() + indexCount / 3); - - for (size_t i = 0; i < indexCount; i += 3) - { - const uint index0 = pIndices[i]; - const uint index1 = pIndices[i + 1]; - const uint index2 = pIndices[i + 2]; - - if ((index0 >= vertexCount) || (index1 >= vertexCount) || (index2 >= vertexCount)) - { - return false; - } - - const Vec3 pos0 = ToVec3(*(const TPosition*) (((const char*)pPositions) + index0 * stridePositions)); - const Vec3 pos1 = ToVec3(*(const TPosition*) (((const char*)pPositions) + index1 * stridePositions)); - const Vec3 pos2 = ToVec3(*(const TPosition*) (((const char*)pPositions) + index2 * stridePositions)); - - const float faceArea = ((pos1 - pos0).Cross(pos2 - pos0)).GetLength() * 0.5f; - - if (faceArea >= minFaceArea) - { - areas.push_back(faceArea); - } - } - - return true; - } - -private: - template - inline static Vec3 ToVec3(const T& v) - { - return v.ToVec3(); - } - - template - inline static Vec2 ToVec2(const T& v) - { - Vec2 uv; - v.GetUV(uv); - - return uv; - } -}; - -template <> -inline Vec3 CMeshHelpers::ToVec3(const Vec3& v) -{ - return v; -} - -template <> -inline Vec2 CMeshHelpers::ToVec2(const Vec2& v) -{ - return v; -} - -template <> -inline Vec2 CMeshHelpers::ToVec2(const Vec2f16& v) -{ - return v.ToVec2(); -} - -template <> -inline Vec2 CMeshHelpers::ToVec2(const SMeshTexCoord& v) -{ - return v.GetUV(); -} - - -////////////////////////////////////////////////////////////////////////// -// Description: -// General purpose mesh class. -////////////////////////////////////////////////////////////////////////// -class CMesh -{ -public: - // e.g. no more than 8 positions, 8 colors, 8 uv sets, etc. - const static uint maxStreamsPerType = 8; - enum EStream - { - POSITIONS = 0, - POSITIONSF16, - NORMALS, - FACES, - TOPOLOGY_IDS, - TEXCOORDS, - COLORS, - INDICES, - TANGENTS, - BONEMAPPING, - VERT_MATS, - QTANGENTS, - P3S_C4B_T2S, - - EXTRABONEMAPPING, // Extra stream. Does not have a stream ID in the CGF. Its data is saved at the end of the BONEMAPPING stream. - - LAST_STREAM, - }; - - SMeshFace* m_pFaces; // faces are used in mesh processing/compilation - int32* m_pTopologyIds; - - // geometry data - vtx_idx* m_pIndices; // indices are used for the final render-mesh - Vec3* m_pPositions; - Vec3f16* m_pPositionsF16; - - SMeshNormal* m_pNorms; - SMeshTangents* m_pTangents; - SMeshQTangents* m_pQTangents; - SMeshTexCoord* m_pTexCoord; - SMeshColor* m_pColor0; - SMeshColor* m_pColor1; - - int* m_pVertMats; - SVF_P3S_C4B_T2S* m_pP3S_C4B_T2S; - - SMeshBoneMapping_uint16* m_pBoneMapping; //bone-mapping for the final render-mesh - SMeshBoneMapping_uint16* m_pExtraBoneMapping; //bone indices and weights for bones 5 to 8. - - int m_nCoorCount; //number of texture coordinates in m_pTexCoord array - int m_streamSize[LAST_STREAM][maxStreamsPerType]; - - // Bounding box. - AABB m_bbox; - - // Array of mesh subsets. - DynArray m_subsets; - - // Mask that indicate if this stream is using not allocated in Mesh pointer; - // ex. if (m_sharedStreamMasks[0] & (1< the 1st normals stream is shared - // if (m_sharedStreamMasks[1] & (1< the 2nd uv set stream is shared - uint32 m_sharedStreamMasks[maxStreamsPerType]; - - // Texture space area divided by geometry area. Zero if cannot compute. - float m_texMappingDensity; - - // Geometric mean value calculated from the areas of this mesh faces. - float m_geometricMeanFaceArea; - - ////////////////////////////////////////////////////////////////////////// - void GetMemoryUsage(class ICrySizer* pSizer) const - { - pSizer->AddObject(this, sizeof(*this)); - pSizer->AddObject(m_subsets); - - for (int streamType = 0; streamType < LAST_STREAM; streamType++) - { - for (int streamIndex = 0; streamIndex < GetNumberOfStreamsByType(streamType); ++streamIndex) - { - void* pStream; - int nElementSize = 0; - GetStreamInfo(streamType, streamIndex, pStream, nElementSize); - pSizer->AddObject(pStream, m_streamSize[streamType][streamIndex] * nElementSize); - } - } - } - - ////////////////////////////////////////////////////////////////////////// - CMesh() - { - m_pFaces = NULL; - m_pTopologyIds = NULL; - m_pIndices = NULL; - m_pPositions = NULL; - m_pPositionsF16 = NULL; - m_pNorms = NULL; - m_pTangents = NULL; - m_pQTangents = NULL; - m_pTexCoord = NULL; - m_pColor0 = NULL; - m_pColor1 = NULL; - m_pVertMats = NULL; - m_pP3S_C4B_T2S = NULL; - m_pBoneMapping = NULL; - m_pExtraBoneMapping = NULL; - - m_nCoorCount = 0; - - memset(m_texCoords, 0, sizeof(m_texCoords)); - memset(m_streamSize, 0, sizeof(m_streamSize)); - - m_bbox.Reset(); - - memset(m_sharedStreamMasks, 0, sizeof(m_sharedStreamMasks)); - - m_texMappingDensity = 0.0f; - m_geometricMeanFaceArea = 0.0f; - } - - virtual ~CMesh() - { - FreeStreams(); - } - - void FreeStreams() - { - for (int streamType = 0; streamType < LAST_STREAM; ++streamType) - { - for (int streamIndex = 0; streamIndex < GetNumberOfStreamsByType(streamType); ++streamIndex) - { - ReallocStream(streamType, streamIndex, 0); - } - } - } - - int GetFaceCount() const - { - return m_streamSize[FACES][0]; - } - int GetVertexCount() const - { - return max(max(m_streamSize[POSITIONS][0], m_streamSize[POSITIONSF16][0]), m_streamSize[P3S_C4B_T2S][0]); - } - int GetTexCoordCount() const - { - return m_nCoorCount; - } - int GetTangentCount() const - { - return m_streamSize[TANGENTS][0]; - } - int GetSubSetCount() const - { - return m_subsets.size(); - } - int GetIndexCount() const - { - return m_streamSize[INDICES][0]; - } - - void SetFaceCount(int nNewCount) - { - ReallocStream(FACES, 0, nNewCount); - } - - void SetVertexCount(int nNewCount) - { - if (GetVertexCount() != nNewCount || GetVertexCount() == 0) - { - ReallocStream(POSITIONS, 0, nNewCount); - ReallocStream(POSITIONSF16, 0, 0); - ReallocStream(NORMALS, 0, nNewCount); - - if (m_pColor0) - { - ReallocStream(COLORS, 0, nNewCount); - } - - if (m_pColor1) - { - ReallocStream(COLORS, 1, nNewCount); - } - - if (m_pVertMats) - { - ReallocStream(VERT_MATS, 0, nNewCount); - } - } - } - - void SetTexCoordsCount(int nNewCount) - { - if (m_nCoorCount != nNewCount || m_nCoorCount == 0) - { - ReallocStream(TEXCOORDS, 0, nNewCount); - m_nCoorCount = nNewCount; - } - } - - void SetTexCoordsAndTangentsCount(int nNewCount) - { - if (m_nCoorCount != nNewCount || m_nCoorCount == 0) - { - ReallocStream(TEXCOORDS, 0, nNewCount); - ReallocStream(TANGENTS, 0, nNewCount); - m_nCoorCount = nNewCount; - } - } - - void SetIndexCount(int nNewCount) - { - ReallocStream(INDICES, 0, nNewCount); - } - // Once m_pTexCoords, m_pColors, etc. are wrapped in vectors, return the size of the vector - // or if we go with fixed size arrays, with a bunch of nullptrs, maybe just return the fixed size or the number of non-null ptrs - int GetNumberOfStreamsByType(int streamType) const - { - if (streamType == COLORS || streamType == TEXCOORDS) - { - return 2; - } - return 1; - } - - bool Has32BitPositions(void) const - { - return m_pPositions != nullptr; - } - - bool Has16BitPositions(void) const - { - return m_pPositionsF16 != nullptr; - } - - bool IsUVSetEmptyForSubmesh(uint submeshIndex, uint uvSet) - { - // Get a pointer to the uv set - SMeshTexCoord* texCoords = nullptr; - if (uvSet == 0) - { - texCoords = m_pTexCoord; - } - else - { - texCoords = m_texCoords[uvSet]; - } - - if (texCoords) - { - // Iterate through the vertices for the submesh - Vec2 emptyTexCoord = Vec2(0.0f, 0.0f); - for (int i = m_subsets[submeshIndex].nFirstVertId; i < m_subsets[submeshIndex].nFirstVertId + m_subsets[submeshIndex].nNumVerts; ++i) - { - // If any of the texture coordinates for the given uv set are non-zero, return false. - if (texCoords[i].GetUV() != emptyTexCoord) - { - return false; - } - } - } - // If no valid texture coordinates are found for submesh for the given uv set, return true. - return true; - } - - void SetSubmeshVertexFormats(void) - { - EVertexFormat desiredFormat = eVF_Unknown; - for (int submeshIndex = 0; submeshIndex < m_subsets.size(); ++submeshIndex) - { - // Choose float or short based on the precision of the positions - if (this->Has32BitPositions()) - { - // Choose one or two uv sets - if (IsUVSetEmptyForSubmesh(submeshIndex, 1)) - { - desiredFormat = eVF_P3F_C4B_T2F; - } - else - { - desiredFormat = eVF_P3F_C4B_T2F_T2F; - } - } - else if (this->Has16BitPositions()) - { - // Choose one or two uv sets - if (IsUVSetEmptyForSubmesh(submeshIndex, 1)) - { - desiredFormat = eVF_P3S_C4B_T2S; - } - else - { - desiredFormat = eVF_P3S_C4B_T2S_T2S; - } - } - else - { - AZ_Assert(false, "Submesh does not contain positions"); - } - - // Set the vertex format for the submesh - m_subsets[submeshIndex].vertexFormat = AZ::Vertex::Format(desiredFormat); - } - } - - AZ::Vertex::Format GetVertexFormatForSubmesh(int submeshIndex) const - { - assert(submeshIndex < m_subsets.size()); - - return m_subsets[submeshIndex].vertexFormat; - } - - AZ::Vertex::Format GetMeshGroupVertexFormat() const - { - AZ::Vertex::Format meshGroupFormat; - for (int submeshIndex = 0; submeshIndex < m_subsets.size(); ++submeshIndex) - { - if (m_subsets[submeshIndex].vertexFormat > meshGroupFormat) - { - meshGroupFormat = m_subsets[submeshIndex].vertexFormat; - } - } - - return meshGroupFormat; - } - - // Set specific stream type as shared. If there are multiple streams for a given type (such as multiple uv sets), then all streams of that type will be marked as shared - void SetSharedStream(int streamType, int streamIndex, void* pStream, int nElementCount) - { - AZ_Assert(streamType >= 0 && streamType < LAST_STREAM && streamIndex < maxStreamsPerType, "Stream type %d outside of allowable range (%d to %d) of CMesh::EStream, or stream index %d exceeds the maximum number of vertex streams (%d) per type.", streamType, 0, CMesh::LAST_STREAM, streamIndex, maxStreamsPerType); - if ((m_sharedStreamMasks[streamIndex] & (1 << streamType)) == 0) - { - ReallocStream(streamType, streamIndex, 0); - m_sharedStreamMasks[streamIndex] |= (1 << streamType); - } - SetStreamData(streamType, streamIndex, pStream, nElementCount); - } - - template - T* GetStreamPtrAndElementCount(int streamType, int streamIndex, int* pElementCount = 0) const - { - void* pStream = 0; - int nElementSize = 0; - GetStreamInfo(streamType, streamIndex, pStream, nElementSize); - - if (nElementSize != sizeof(T)) - { - AZ_Assert(false, "The element size %d returned by GetStreamInfo does not match the size %d of type T", nElementSize, sizeof(T)); - pStream = 0; - } - - const int nElementCount = (pStream ? this->m_streamSize[streamType][streamIndex] : 0); - - if (pElementCount) - { - *pElementCount = nElementCount; - } - return (T*)pStream; - } - - template - T* GetStreamPtr(int streamType, int streamIndex = 0) const - { - void* pStream = 0; - int nElementSize = 0; - GetStreamInfo(streamType, streamIndex, pStream, nElementSize); - - if (nElementSize != sizeof(T)) - { - AZ_Assert(false, "The element size %d returned by GetStreamInfo does not match the size %d of type T", nElementSize, sizeof(T)); - pStream = 0; - } - - return (T*)pStream; - } - - void GetStreamInfo(int streamType, int streamIndex, void*& pStream, int& nElementSize) const - { - pStream = 0; - nElementSize = 0; - AZ_Assert(streamType >= 0 && streamType < LAST_STREAM && streamIndex < maxStreamsPerType, "Stream type %d outside of allowable range (%d to %d) of CMesh::EStream, or stream index %d exceeds the maximum number of vertex streams (%d) per type.", streamType, 0, CMesh::LAST_STREAM, streamIndex, maxStreamsPerType); - - switch (streamType) - { - case POSITIONS: - pStream = m_pPositions; - nElementSize = sizeof(Vec3); - break; - case POSITIONSF16: - pStream = m_pPositionsF16; - nElementSize = sizeof(Vec3f16); - break; - case NORMALS: - pStream = m_pNorms; - nElementSize = sizeof(Vec3); - break; - case VERT_MATS: - pStream = m_pVertMats; - nElementSize = sizeof(int); - break; - case FACES: - pStream = m_pFaces; - nElementSize = sizeof(SMeshFace); - break; - case TOPOLOGY_IDS: - pStream = m_pTopologyIds; - nElementSize = sizeof(int32); - break; - case TEXCOORDS: - if (streamIndex == 0) - { - pStream = m_pTexCoord; - } - else - { - pStream = m_texCoords[streamIndex]; - } - nElementSize = sizeof(SMeshTexCoord); - break; - case COLORS: - if (streamIndex == 0) - { - pStream = m_pColor0; - } - else - { - pStream = m_pColor1; - } - nElementSize = sizeof(SMeshColor); - break; - case INDICES: - pStream = m_pIndices; - nElementSize = sizeof(vtx_idx); - break; - case TANGENTS: - pStream = m_pTangents; - nElementSize = sizeof(SMeshTangents); - break; - case QTANGENTS: - pStream = m_pQTangents; - nElementSize = sizeof(SMeshQTangents); - break; - case BONEMAPPING: - pStream = m_pBoneMapping; - nElementSize = sizeof(SMeshBoneMapping_uint16); - break; - case EXTRABONEMAPPING: - pStream = m_pExtraBoneMapping; - nElementSize = sizeof(SMeshBoneMapping_uint16); - break; - case P3S_C4B_T2S: - pStream = m_pP3S_C4B_T2S; - nElementSize = sizeof(SVF_P3S_C4B_T2S); - break; - default: - AZ_Assert(false, "Unknown stream"); - break; - } - } - - - virtual void ReallocStream(int streamType, int streamIndex, int nNewCount) - { - if (streamType < 0 || streamType >= LAST_STREAM || streamIndex >= maxStreamsPerType) - { - AZ_Assert(false, "Stream type %d outside of allowable range (%d to %d) of CMesh::EStream, or stream index %d exceeds the maximum number of vertex streams (%d) per type.", streamType, 0, CMesh::LAST_STREAM, streamIndex, maxStreamsPerType); - return; - } - - if (m_sharedStreamMasks[streamIndex] & (1 << streamType)) - { - m_sharedStreamMasks[streamIndex] &= ~(1 << streamType); - - if (nNewCount <= 0) - { - SetStreamData(streamType, 0, nullptr, 0); - } - else - { - const int nOldCount = m_streamSize[streamType][streamIndex]; - void* pOldElements = 0; - int nElementSize = 0; - GetStreamInfo(streamType, streamIndex, pOldElements, nElementSize); - - void* const pNewElements = realloc(0, nNewCount * nElementSize); - if (!pNewElements) - { - AZ_Assert(false, "Allocation failed"); - SetStreamData(streamType, streamIndex, nullptr, 0); - return; - } - - if (nOldCount > 0) - { - memcpy(pNewElements, pOldElements, min(nOldCount, nNewCount) * nElementSize); - } - if (nNewCount > nOldCount) - { - memset((char*)pNewElements + nOldCount * nElementSize, 0, (nNewCount - nOldCount) * nElementSize); - } - - SetStreamData(streamType, streamIndex, pNewElements, nNewCount); - } - } - else - { - const int nOldCount = m_streamSize[streamType][streamIndex]; - if (nOldCount == nNewCount) - { - // stream already has required size - return; - } - - void* pOldElements = 0; - int nElementSize = 0; - GetStreamInfo(streamType, streamIndex, pOldElements, nElementSize); - - if (nNewCount <= 0) - { - free(pOldElements); - SetStreamData(streamType, streamIndex, nullptr, 0); - } - else - { - void* const pNewElements = realloc(pOldElements, nNewCount * nElementSize); - if (!pNewElements) - { - AZ_Assert(false, "Allocation failed"); - free(pOldElements); - SetStreamData(streamType, streamIndex, nullptr, 0); - return; - } - - if (nNewCount > nOldCount) - { - memset((char*)pNewElements + nOldCount * nElementSize, 0, (nNewCount - nOldCount) * nElementSize); - } - - SetStreamData(streamType, streamIndex, pNewElements, nNewCount); - } - } - } - - // Copy mesh from source mesh. - void Copy(const CMesh& mesh) - { - for (int streamType = 0; streamType < LAST_STREAM; streamType++) - { - for (int streamIndex = 0; streamIndex < GetNumberOfStreamsByType(streamType); ++streamIndex) - { - ReallocStream(streamType, streamIndex, mesh.m_streamSize[streamType][streamIndex]); - if (mesh.m_streamSize[streamType][streamIndex] > 0) - { - void* pSrcStream = 0; - void* pTrgStream = 0; - int nElementSize = 0; - mesh.GetStreamInfo(streamType, streamIndex, pSrcStream, nElementSize); - GetStreamInfo(streamType, streamIndex, pTrgStream, nElementSize); - if (pSrcStream && pTrgStream) - { - memcpy(pTrgStream, pSrcStream, m_streamSize[streamType][streamIndex] * nElementSize); - } - } - } - } - m_bbox = mesh.m_bbox; - m_subsets = mesh.m_subsets; - m_texMappingDensity = mesh.m_texMappingDensity; - m_geometricMeanFaceArea = mesh.m_geometricMeanFaceArea; - } - - bool CompareStreams(const CMesh& mesh) const - { - for (int streamType = 0; streamType < LAST_STREAM; streamType++) - { - for (int streamIndex = 0; streamIndex < GetNumberOfStreamsByType(streamType); ++streamIndex) - { - if (m_streamSize[streamType][streamIndex] != mesh.m_streamSize[streamType][streamIndex]) - { - return false; - } - - if (m_streamSize[streamType][streamIndex]) - { - void* pStream1 = 0; - void* pStream2 = 0; - int nElementSize1 = 0; - int nElementSize2 = 0; - GetStreamInfo(streamType, streamIndex, pStream1, nElementSize1); - mesh.GetStreamInfo(streamType, streamIndex, pStream2, nElementSize2); - - assert(nElementSize1 == nElementSize2); - - if ((pStream1 && !pStream2) || (!pStream1 && pStream2)) - { - return false; - } - - if (pStream1 && pStream2) - { - if (memcmp(pStream1, pStream2, m_streamSize[streamType][streamIndex] * nElementSize1) != 0) - { - return false; - } - } - } - } - } - return true; - } - - // Add streams from source mesh to the end of existing streams. - const char* Append(const CMesh& mesh) - { - return Append(mesh, 0, -1, 0, -1); - } - - // Add streams from source mesh to the end of existing streams. - const char* Append(const CMesh& mesh, int fromVertex, int vertexCount, int fromFace, int faceCount) - { - if (GetIndexCount() > 0 || mesh.GetIndexCount() > 0) - { - assert(0); - return "Cmesh::Append() cannot handle meshes with indices, it can handle faces only"; - } - - // Non-ranged requests should start from 0th element and element count should be <0. - if ((vertexCount < 0 && fromVertex != 0) || (faceCount < 0 && fromFace != 0)) - { - assert(0); - return "Cmesh::Append(): Bad CMesh parameters"; - } - if (vertexCount < 0) - { - vertexCount = mesh.GetVertexCount(); - } - if (faceCount < 0) - { - faceCount = mesh.GetFaceCount(); - } - - const int oldVertexCount = GetVertexCount(); - const int oldFaceCount = GetFaceCount(); - - if (GetTexCoordCount() != 0 && GetTexCoordCount() != oldVertexCount) - { - assert(0); - return "Cmesh::Append(): Mismatch in target CMesh vert/tcoord counts"; - } - - if (mesh.GetTexCoordCount() != 0 && mesh.GetTexCoordCount() != mesh.GetVertexCount()) - { - assert(0); - return "Cmesh::Append(): Mismatch in source CMesh vert/tcoord counts"; - } - - for (int streamType = 0; streamType < LAST_STREAM; ++streamType) - { - for (int streamIndex = 0; streamIndex < GetNumberOfStreamsByType(streamType); ++streamIndex) - { - const int oldCount = (streamType == FACES) ? oldFaceCount : oldVertexCount; - - const int from = (streamType == FACES) ? fromFace : fromVertex; - const int count = (streamType == FACES) ? faceCount : vertexCount; - - const int oldStreamSize = m_streamSize[streamType][streamIndex]; - const int streamSize = mesh.m_streamSize[streamType][streamIndex]; - - if (oldStreamSize <= 0 && (count <= 0 || streamSize <= 0)) - { - continue; - } - - ReallocStream(streamType, streamIndex, oldCount + count); - - if (count > 0) - { - void* pSrcStream = 0; - void* pTrgStream = 0; - int srcElementSize = 0; - int trgElementSize = 0; - mesh.GetStreamInfo(streamType, streamIndex, pSrcStream, srcElementSize); - GetStreamInfo(streamType, streamIndex, pTrgStream, trgElementSize); - - assert(srcElementSize == trgElementSize); - - if (pSrcStream && pTrgStream) - { - memcpy( - (char*)pTrgStream + oldCount * trgElementSize, - (char*)pSrcStream + from * srcElementSize, - count * srcElementSize); - } - } - } - } - - { - const int nOffset = oldVertexCount - fromVertex; - const int newFaceCount = GetFaceCount(); - - for (int i = oldFaceCount; i < newFaceCount; ++i) - { - m_pFaces[i].v[0] += nOffset; - m_pFaces[i].v[1] += nOffset; - m_pFaces[i].v[2] += nOffset; - } - } - - m_bbox.Add(mesh.m_bbox.min); - m_bbox.Add(mesh.m_bbox.max); - - return 0; - } - - void RemoveRangeFromStream(int streamType, int streamIndex, int nFirst, int nCount) - { - if (streamType < 0 || streamType >= LAST_STREAM || streamIndex >= maxStreamsPerType) - { - AZ_Assert(false, "Stream type %d outside of allowable range (%d to %d) of CMesh::EStream, or stream index %d exceeds the maximum number of vertex streams (%d) per type.", streamType, 0, CMesh::LAST_STREAM, streamIndex, maxStreamsPerType); - return; - } - - if (m_sharedStreamMasks[streamIndex] & (1 << streamType)) - { - // Make shared stream non-shared - ReallocStream(streamType, streamIndex, m_streamSize[streamType][streamIndex]); - } - - const int nTotalCount = m_streamSize[streamType][streamIndex]; - - int nElementSize; - void* pStream = 0; - GetStreamInfo(streamType, streamIndex, pStream, nElementSize); - - if (nFirst >= nTotalCount || nTotalCount <= 0 || pStream == 0) - { - return; - } - if (nFirst + nCount > nTotalCount) - { - nCount = nTotalCount - nFirst; - } - if (nCount <= 0) - { - return; - } - - const int nTailCount = nTotalCount - (nFirst + nCount); - if (nTailCount > 0) - { - char* const pRangeStart = (char*)pStream + nFirst * nElementSize; - char* const pRangeEnd = (char*)pStream + (nFirst + nCount) * nElementSize; - memmove(pRangeStart, pRangeEnd, nTailCount * nElementSize); - } - - ReallocStream(streamType, streamIndex, nTotalCount - nCount); - } - - bool Validate(const char** const ppErrorDescription) const - { - const int vertexCount = GetVertexCount(); - const int faceCount = GetFaceCount(); - const int indexCount = GetIndexCount(); - - if ((faceCount <= 0) && (indexCount <= 0)) - { - if (vertexCount > 0) - { - if (ppErrorDescription) - { - ppErrorDescription[0] = "no any indices, but vertices exist"; - } - return false; - } - } - - if ((uint)vertexCount > (sizeof(vtx_idx) == 2 ? 0xffff : 0x7fffffff)) - { - if (ppErrorDescription) - { - ppErrorDescription[0] = - (sizeof(vtx_idx) == 2) - ? "vertex count is greater or equal than 64K" - : "vertex count is greater or equal than 2G"; - } - return false; - } - - if (faceCount > 0) - { - if (vertexCount <= 0) - { - if (ppErrorDescription) - { - ppErrorDescription[0] = "no any vertices, but faces exist"; - } - return false; - } - } - - if (indexCount > 0) - { - if (vertexCount <= 0) - { - if (ppErrorDescription) - { - ppErrorDescription[0] = "no any vertices, but indices exist"; - } - return false; - } - } - - for (int i = 0; i < faceCount; ++i) - { - const SMeshFace& face = m_pFaces[i]; - for (int j = 0; j < 3; ++j) - { - const int v = face.v[j]; - if ((v < 0) || (v >= vertexCount)) - { - if (ppErrorDescription) - { - ppErrorDescription[0] = "a face refers vertex outside of vertex array"; - } - return false; - } - } - } - - for (int i = 0; i < indexCount; i++) - { - if ((uint)m_pIndices[i] >= (uint)vertexCount) - { - if (ppErrorDescription) - { - ppErrorDescription[0] = "an index refers vertex outside of vertex array"; - } - return false; - } - } - - if (GetTexCoordCount() != 0 && GetTexCoordCount() != vertexCount) - { - if (ppErrorDescription) - { - ppErrorDescription[0] = "number of texture coordinates is different from number of vertices"; - } - return false; - } - - if (!_finite(m_bbox.min.x) || !_finite(m_bbox.min.y) || !_finite(m_bbox.min.z) || - !_finite(m_bbox.max.x) || !_finite(m_bbox.max.y) || !_finite(m_bbox.max.z)) - { - if (ppErrorDescription) - { - ppErrorDescription[0] = "bounding box contains damaged data"; - } - return false; - } - - if (m_bbox.IsReset()) - { - if (ppErrorDescription) - { - ppErrorDescription[0] = "bounding box is not set"; - } - return false; - } - - if (m_bbox.max.x < m_bbox.min.x || - m_bbox.max.y < m_bbox.min.y || - m_bbox.max.z < m_bbox.min.z) - { - if (ppErrorDescription) - { - ppErrorDescription[0] = "bounding box min is greater than max"; - } - return false; - } - - if (m_bbox.min.GetDistance(m_bbox.max) < 0.001f) - { - if (ppErrorDescription) - { - ppErrorDescription[0] = "bounding box is less than 1 mm in size"; - } - return false; - } - - for (int s = 0, subsetCount = m_subsets.size(); s < subsetCount; ++s) - { - const SMeshSubset& subset = m_subsets[s]; - - if (subset.nNumIndices <= 0) - { - if (subset.nNumVerts > 0) - { - if (ppErrorDescription) - { - ppErrorDescription[0] = "a mesh subset without indices contains vertices"; - } - return false; - } - continue; - } - else if (subset.nNumVerts <= 0) - { - if (ppErrorDescription) - { - ppErrorDescription[0] = "a mesh subset has indices but vertices are missing"; - } - return false; - } - - if (subset.nFirstIndexId < 0) - { - if (ppErrorDescription) - { - ppErrorDescription[0] = "a mesh subset has negative start position in index array"; - } - return false; - } - if (subset.nFirstIndexId + subset.nNumIndices > indexCount) - { - if (ppErrorDescription) - { - ppErrorDescription[0] = "a mesh subset refers indices outside of index array"; - } - return false; - } - if (subset.nFirstVertId < 0) - { - if (ppErrorDescription) - { - ppErrorDescription[0] = "a mesh subset has negative start position in vertex array"; - } - return false; - } - if (subset.nFirstVertId + subset.nNumVerts > vertexCount) - { - if (ppErrorDescription) - { - ppErrorDescription[0] = "a mesh subset refers vertices outside of vertex array"; - } - return false; - } - - for (int ii = subset.nFirstIndexId; ii < subset.nFirstIndexId + subset.nNumIndices; ++ii) - { - const uint index = m_pIndices[ii]; - if (index < (uint)subset.nFirstVertId) - { - if (ppErrorDescription) - { - ppErrorDescription[0] = "a mesh subset refers a vertex lying before subset vertices"; - } - return false; - } - if (index >= (uint)(subset.nFirstVertId + subset.nNumVerts)) - { - if (ppErrorDescription) - { - ppErrorDescription[0] = "a mesh subset refers a vertex lying after subset vertices"; - } - return false; - } - - Vec3 p(ZERO); - const Vec3* pp = &p; - if (m_pPositions) - { - pp = &m_pPositions[index]; - } - else if (m_pPositionsF16) - { - p = m_pPositionsF16[index].ToVec3(); - } - else if (m_pP3S_C4B_T2S) - { - p = m_pP3S_C4B_T2S[index].xyz.ToVec3(); - } - if (!_finite(pp->x)) - { - if (ppErrorDescription) - { - ppErrorDescription[0] = "a mesh subset contains a vertex with damaged x component"; - } - return false; - } - if (!_finite(pp->y)) - { - if (ppErrorDescription) - { - ppErrorDescription[0] = "a mesh subset contains a vertex with damaged y component"; - } - return false; - } - if (!_finite(pp->z)) - { - if (ppErrorDescription) - { - ppErrorDescription[0] = "a mesh subset contains a vertex with damaged z component"; - } - return false; - } - } - } - - return true; - } - - bool ComputeSubsetTexMappingAreas( - size_t subsetIndex, - float& computedPosArea, float& computedTexArea, const char*& errorText) - { - computedPosArea = 0.0f; - computedTexArea = 0.0f; - errorText = ""; - - if (subsetIndex >= (size_t)m_subsets.size()) - { - errorText = "subset index is bad"; - return false; - } - - if (GetIndexCount() <= 0) - { - errorText = "missing indices"; - return false; - } - - if ((GetVertexCount() <= 0) || ((m_pPositions == NULL) && (m_pPositionsF16 == NULL))) - { - errorText = "missing vertices"; - return false; - } - - if ((m_pTexCoord == NULL) || (GetTexCoordCount() <= 0)) - { - errorText = "missing texture coordinates"; - return false; - } - - const SMeshSubset& subset = m_subsets[subsetIndex]; - - if ((subset.nNumIndices <= 0) || (subset.nFirstIndexId < 0)) - { - errorText = "missing or bad indices in subset"; - return false; - } - - bool ok; - if (m_pPositions) - { - ok = CMeshHelpers::ComputeTexMappingAreas( - subset.nNumIndices, &m_pIndices[subset.nFirstIndexId], - GetVertexCount(), - &m_pPositions[0], sizeof(m_pPositions[0]), - &m_pTexCoord[0], sizeof(m_pTexCoord[0]), - computedPosArea, computedTexArea, errorText); - } - else - { - ok = CMeshHelpers::ComputeTexMappingAreas( - subset.nNumIndices, &m_pIndices[subset.nFirstIndexId], - GetVertexCount(), - &m_pPositionsF16[0], sizeof(m_pPositionsF16[0]), - &m_pTexCoord[0], sizeof(m_pTexCoord[0]), - computedPosArea, computedTexArea, errorText); - } - - return ok; - } - - // note: this function doesn't work for "old" uncompressed meshes (with faces instead of indices) - bool RecomputeTexMappingDensity() - { - m_texMappingDensity = 0; - - if (GetFaceCount() > 0) - { - // uncompressed mesh - not supported - return false; - } - - if ((GetIndexCount() <= 0) || (GetVertexCount() <= 0) || ((m_pPositions == NULL) && (m_pPositionsF16 == NULL))) - { - return false; - } - - if ((m_pTexCoord == NULL) || (GetTexCoordCount() <= 0)) - { - return false; - } - - float totalPosArea = 0; - float totalTexArea = 0; - - for (size_t i = 0, count = m_subsets.size(); i < count; ++i) - { - - float posArea; - float texArea; - const char* errorText = ""; - - const bool ok = ComputeSubsetTexMappingAreas(i, posArea, texArea, errorText); - - if (ok) - { - totalPosArea += posArea; - totalTexArea += texArea; - } - } - - if (totalPosArea <= 0) - { - return false; - } - - m_texMappingDensity = totalTexArea / totalPosArea; - return true; - } - - bool RecomputeGeometricMeanFaceArea() - { - m_geometricMeanFaceArea = 0.0f; - - if (GetFaceCount() > 0) - { - // uncompressed mesh - not supported - return false; - } - - if ((GetIndexCount() <= 0) || (GetVertexCount() <= 0) || ((m_pPositions == NULL) && (m_pPositionsF16 == NULL))) - { - return false; - } - - std::vector areas; - const size_t subsetCount = m_subsets.size(); - - for (size_t i = 0; i < subsetCount; ++i) - { - CollectSubsetFaceAreas(m_subsets[i], areas); - } - - const size_t areasCount = areas.size(); - if (areasCount == 0) - { - return false; - } - - float fGeometricTotal = 0.0f; - for (size_t i = 0; i < areasCount; ++i) - { - fGeometricTotal += logf(areas[i]); - } - - m_geometricMeanFaceArea = expf(fGeometricTotal / areasCount); - - assert(m_geometricMeanFaceArea > 0.0f); - - return true; - } - - bool CollectSubsetFaceAreas(const SMeshSubset& subset, std::vector& areas) - { - if ((subset.nNumIndices <= 0) || (subset.nFirstIndexId < 0)) - { - return false; - } - - bool ok = false; - if (m_pPositions != NULL) - { - ok = CMeshHelpers::CollectFaceAreas(subset.nNumIndices, &m_pIndices[subset.nFirstIndexId], - GetVertexCount(), &m_pPositions[0], sizeof(m_pPositions[0]), areas); - } - else if (m_pPositionsF16 != NULL) - { - ok = CMeshHelpers::CollectFaceAreas(subset.nNumIndices, &m_pIndices[subset.nFirstIndexId], - GetVertexCount(), &m_pPositionsF16[0], sizeof(m_pPositionsF16[0]), areas); - } - - return ok; - } - - ////////////////////////////////////////////////////////////////////////// - // Estimates the size of the render mesh. - uint32 EstimateRenderMeshMemoryUsage() const - { - const size_t cSizeStream[VSF_NUM] = { - 0U, - sizeof(SPipTangents), // VSF_TANGENTS - sizeof(SPipQTangents), // VSF_QTANGENTS - sizeof(SVF_W4B_I4S), // VSF_HWSKIN_INFO - sizeof(SVF_P3F), // VSF_VERTEX_VELOCITY -#if ENABLE_NORMALSTREAM_SUPPORT - sizeof(SPipNormal), // VSF_NORMALS -#endif - }; - - uint32 nMeshSize = 0; - uint32 activeStreams = (GetVertexCount()) ? 1U << VSF_GENERAL : 0U; - activeStreams |= - (m_pQTangents) ? (1U << VSF_QTANGENTS) : - (m_pTangents) ? (1U << VSF_TANGENTS) : 0U; - if (m_pBoneMapping) - { - activeStreams |= 1U << VSF_HWSKIN_INFO; - } - for (uint32 i = 0; i < VSF_NUM; i++) - { - if (activeStreams & (1U << i)) - { - nMeshSize += static_cast(((i == VSF_GENERAL) ? sizeof(SVF_P3S_C4B_T2S) : cSizeStream[i]) * GetVertexCount()); - nMeshSize += TARGET_DEFAULT_ALIGN - (nMeshSize & (TARGET_DEFAULT_ALIGN - 1)); - } - } - if (GetIndexCount()) - { - nMeshSize += GetIndexCount() * sizeof(vtx_idx); - nMeshSize += TARGET_DEFAULT_ALIGN - (nMeshSize & (TARGET_DEFAULT_ALIGN - 1)); - } - - return nMeshSize; - } - ////////////////////////////////////////////////////////////////////////// - - // This function used when we do not have an actual mesh, but only vertex/index count of it. - static uint32 ApproximateRenderMeshMemoryUsage(int nVertexCount, int nIndexCount) - { - uint32 nMeshSize = 0; - nMeshSize += nVertexCount * sizeof(SVF_P3S_C4B_T2S); - nMeshSize += nVertexCount * sizeof(SPipTangents); - - nMeshSize += nIndexCount * sizeof(vtx_idx); - return nMeshSize; - } - -private: - // Set stream size. - void SetStreamData(int streamType, int streamIndex, void* pStream, int nNewCount) - { - if (streamType < 0 || streamType >= LAST_STREAM || streamIndex >= maxStreamsPerType) - { - AZ_Assert(false, "Stream type %d outside of allowable range (%d to %d) of CMesh::EStream, or stream index %d exceeds the maximum number of vertex streams (%d) per type.", streamType, 0, CMesh::LAST_STREAM, streamIndex, maxStreamsPerType); - return; - } - m_streamSize[streamType][streamIndex] = nNewCount; - switch (streamType) - { - case POSITIONS: - m_pPositions = (Vec3*)pStream; - break; - case POSITIONSF16: - m_pPositionsF16 = (Vec3f16*)pStream; - break; - case NORMALS: - m_pNorms = (SMeshNormal*)pStream; - break; - case VERT_MATS: - m_pVertMats = (int*)pStream; - break; - case FACES: - m_pFaces = (SMeshFace*)pStream; - break; - case TOPOLOGY_IDS: - m_pTopologyIds = (int32*)pStream; - break; - case TEXCOORDS: - if (streamIndex == 0) - { - m_pTexCoord = (SMeshTexCoord*)pStream; - } - else - { - m_texCoords[streamIndex] = (SMeshTexCoord*)pStream; - } - m_nCoorCount = nNewCount; - break; - case COLORS: - if (streamIndex == 0) - { - m_pColor0 = (SMeshColor*)pStream; - } - else - { - m_pColor1 = (SMeshColor*)pStream; - } - break; - case INDICES: - m_pIndices = (vtx_idx*)pStream; - break; - case TANGENTS: - m_pTangents = (SMeshTangents*)pStream; - break; - case QTANGENTS: - m_pQTangents = (SMeshQTangents*)pStream; - break; - case BONEMAPPING: - m_pBoneMapping = (SMeshBoneMapping_uint16*)pStream; - break; - case EXTRABONEMAPPING: - m_pExtraBoneMapping = (SMeshBoneMapping_uint16*)pStream; - break; - case P3S_C4B_T2S: - m_pP3S_C4B_T2S = (SVF_P3S_C4B_T2S*)pStream; - m_nCoorCount = nNewCount; - break; - default: - AZ_Assert(false, "Unknown stream"); - break; - } - } - - SMeshTexCoord* m_texCoords[maxStreamsPerType]; }; // Description: @@ -2209,10 +190,6 @@ struct IIndexedMesh //! Gives read-only access to mesh data virtual void GetMeshDescription(SMeshDescription& meshDesc) const = 0; - virtual CMesh* GetMesh() = 0; - - virtual void SetMesh(CMesh& mesh) = 0; - /*! Frees vertex and face streams. Calling this function invalidates SMeshDescription pointers */ virtual void FreeStreams() = 0; @@ -2228,54 +205,17 @@ struct IIndexedMesh /*! Reallocates vertices, normals and colors. Calling this function invalidates SMeshDescription pointers */ virtual void SetVertexCount(int nNewCount) = 0; - /*! Reallocates colors. Calling this function invalidates SMeshDescription pointers */ - virtual void SetColorCount(int nNewCount) = 0; - //! Return number of allocated texture coordinates virtual int GetTexCoordCount() const = 0; - /*! Reallocates texture coordinates. Calling this function invalidates SMeshDescription pointers */ - virtual void SetTexCoordCount(int nNewCount, int numStreams = 1) = 0; - - //! Return number of allocated tangents. - virtual int GetTangentCount() const = 0; - - /*! Reallocates tangents. Calling this function invalidates SMeshDescription pointers */ - virtual void SetTangentCount(int nNewCount) = 0; - // Get number of indices in the mesh. virtual int GetIndexCount() const = 0; - // Set number of indices in the mesh. - virtual void SetIndexCount(int nNewCount) = 0; - - // Allocates m_pBoneMapping in CMesh - virtual void AllocateBoneMapping() = 0; - ////////////////////////////////////////////////////////////////////////// // Subset access. ////////////////////////////////////////////////////////////////////////// virtual int GetSubSetCount() const = 0; - virtual void SetSubSetCount(int nSubsets) = 0; virtual const SMeshSubset& GetSubSet(int nIndex) const = 0; - virtual void SetSubsetBounds(int nIndex, const Vec3& vCenter, float fRadius) = 0; - virtual void SetSubsetIndexVertexRanges(int nIndex, int nFirstIndexId, int nNumIndices, int nFirstVertId, int nNumVerts) = 0; - virtual void SetSubsetMaterialId(int nIndex, int nMatID) = 0; - virtual void SetSubsetMaterialProperties(int nIndex, int nMatFlags, int nPhysicalizeType, const AZ::Vertex::Format& vertexFormat) = 0; - ////////////////////////////////////////////////////////////////////////// - // Mesh bounding box. - ////////////////////////////////////////////////////////////////////////// - virtual void SetBBox(const AABB& box) = 0; - virtual AABB GetBBox() const = 0; - virtual void CalcBBox() = 0; - - virtual void RestoreFacesFromIndices() = 0; // - - // Optimizes mesh - virtual void Optimize(const char* szComment = NULL) = 0; }; - - -#endif // CRYINCLUDE_CRYCOMMON_IINDEXEDMESH_H diff --git a/Code/Legacy/CryCommon/IIndexedMesh_info.cpp b/Code/Legacy/CryCommon/IIndexedMesh_info.cpp deleted file mode 100644 index fe15ab7949..0000000000 --- a/Code/Legacy/CryCommon/IIndexedMesh_info.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - -#include "TypeInfo_impl.h" -#include // <> required for Interfuscator - -STRUCT_INFO_BEGIN(SMeshTexCoord) -STRUCT_VAR_INFO(s, TYPE_INFO(float)) -STRUCT_VAR_INFO(t, TYPE_INFO(float)) -STRUCT_INFO_END(SMeshTexCoord) - -STRUCT_INFO_BEGIN(SMeshNormal) -STRUCT_VAR_INFO(Normal, TYPE_INFO(Vec3)) -STRUCT_INFO_END(SMeshNormal) - -STRUCT_INFO_BEGIN(SMeshColor) -STRUCT_VAR_INFO(r, TYPE_INFO(uint8)) -STRUCT_VAR_INFO(g, TYPE_INFO(uint8)) -STRUCT_VAR_INFO(b, TYPE_INFO(uint8)) -STRUCT_VAR_INFO(a, TYPE_INFO(uint8)) -STRUCT_INFO_END(SMeshColor) - -STRUCT_INFO_BEGIN(SMeshTangents) -STRUCT_VAR_INFO(Tangent, TYPE_INFO(Vec4sf)) -STRUCT_VAR_INFO(Bitangent, TYPE_INFO(Vec4sf)) -STRUCT_INFO_END(SMeshTangents) - -STRUCT_INFO_BEGIN(SMeshQTangents) -STRUCT_VAR_INFO(TangentBitangent, TYPE_INFO(Vec4sf)) -STRUCT_INFO_END(SMeshQTangents) - -STRUCT_INFO_BEGIN(SMeshBoneMapping_uint16) -STRUCT_VAR_INFO(boneIds, TYPE_ARRAY(4, TYPE_INFO(SMeshBoneMapping_uint16::BoneId))) -STRUCT_VAR_INFO(weights, TYPE_ARRAY(4, TYPE_INFO(SMeshBoneMapping_uint16::Weight))) -STRUCT_INFO_END(SMeshBoneMapping_uint16) - -STRUCT_INFO_BEGIN(SMeshBoneMapping_uint8) -STRUCT_VAR_INFO(boneIds, TYPE_ARRAY(4, TYPE_INFO(SMeshBoneMapping_uint8::BoneId))) -STRUCT_VAR_INFO(weights, TYPE_ARRAY(4, TYPE_INFO(SMeshBoneMapping_uint8::Weight))) -STRUCT_INFO_END(SMeshBoneMapping_uint8) diff --git a/Code/Legacy/CryCommon/ILocalizationManager.h b/Code/Legacy/CryCommon/ILocalizationManager.h index 2cba093f21..0f0ba88250 100644 --- a/Code/Legacy/CryCommon/ILocalizationManager.h +++ b/Code/Legacy/CryCommon/ILocalizationManager.h @@ -73,11 +73,11 @@ struct SLocalizedSoundInfoGame bool bIsIntercepted; // SoundMoods. - int nNumSoundMoods; + size_t nNumSoundMoods; SLocalizedAdvancesSoundEntry* pSoundMoods; // EventParameters. - int nNumEventParameters; + size_t nNumEventParameters; SLocalizedAdvancesSoundEntry* pEventParameters; }; diff --git a/Code/Legacy/CryCommon/IMaterial.h b/Code/Legacy/CryCommon/IMaterial.h index e1502b0f1a..1b3ef258ce 100644 --- a/Code/Legacy/CryCommon/IMaterial.h +++ b/Code/Legacy/CryCommon/IMaterial.h @@ -10,36 +10,12 @@ // Description : IMaterial interface declaration. #pragma once -struct ISurfaceType; -struct ISurfaceTypeManager; -class ICrySizer; - -enum EEfResTextures : int; // Need to specify a fixed size for the forward declare to work on clang - -struct SShaderItem; -struct SShaderParam; -struct IShader; -struct IMaterial; -struct IMaterialManager; -struct CMaterialCGF; -struct IRenderMesh; - -#include -#include #include #include -#ifdef MAX_SUB_MATERIALS -// This checks that the values are in sync in the different files. -static_assert(MAX_SUB_MATERIALS == 128); -#else -#define MAX_SUB_MATERIALS 128 -#endif - -// Special names for materials. -#define MTL_SPECIAL_NAME_COLLISION_PROXY "collision_proxy" -#define MTL_SPECIAL_NAME_COLLISION_PROXY_VEHICLE "nomaterial_vehicle" -#define MTL_SPECIAL_NAME_RAYCAST_PROXY "raycast_proxy" +struct IShader; +struct ISurfaceType; +struct SShaderItem; namespace AZ { @@ -59,380 +35,15 @@ namespace AZ using MaterialNotificationEventBus = AZ::EBus; } -enum -{ - MAX_STREAM_PREDICTION_ZONES = 2 -}; - -////////////////////////////////////////////////////////////////////////// -// Description: -// IMaterial is an interface to the material object, SShaderItem host which is a combination of IShader and SShaderInputResources. -// Material bind together rendering algorithm (Shader) and resources needed to render this shader, textures, colors, etc... -// All materials except for pure sub material childs have a unique name which directly represent .mtl file on disk. -// Ex: "Materials/Fire/Burn" -// Materials can be created by Sandbox MaterialEditor. -////////////////////////////////////////////////////////////////////////// -enum EMaterialFlags -{ - MTL_FLAG_WIRE = 0x0001, // Use wire frame rendering for this material. - MTL_FLAG_2SIDED = 0x0002, // Use 2 Sided rendering for this material. - MTL_FLAG_ADDITIVE = 0x0004, // Use Additive blending for this material. - //MTL_FLAG_DETAIL_DECAL = 0x0008, // UNUSED RESERVED FOR LEGACY REASONS - MTL_FLAG_LIGHTING = 0x0010, // Should lighting be applied on this material. - MTL_FLAG_NOSHADOW = 0x0020, // Material do not cast shadows. - MTL_FLAG_ALWAYS_USED = 0x0040, // When set forces material to be export even if not explicitly used. - MTL_FLAG_PURE_CHILD = 0x0080, // Not shared sub material, sub material unique to his parent multi material. - MTL_FLAG_MULTI_SUBMTL = 0x0100, // This material is a multi sub material. - MTL_FLAG_NOPHYSICALIZE = 0x0200, // Should not physicalize this material. - MTL_FLAG_NODRAW = 0x0400, // Do not render this material. - MTL_FLAG_NOPREVIEW = 0x0800, // Cannot preview the material. - MTL_FLAG_NOTINSTANCED = 0x1000, // Do not instantiate this material. - MTL_FLAG_COLLISION_PROXY = 0x2000, // This material is the collision proxy. - MTL_FLAG_SCATTER = 0x4000, // Use scattering for this material - MTL_FLAG_REQUIRE_FORWARD_RENDERING = 0x8000, // This material has to be rendered in forward rendering passes (alpha/additive blended) - MTL_FLAG_NON_REMOVABLE = 0x10000, // Material with this flag once created are never removed from material manager (Used for decal materials, this flag should not be saved). - MTL_FLAG_HIDEONBREAK = 0x20000, // Non-physicalized subsets with such materials will be removed after the object breaks - MTL_FLAG_UIMATERIAL = 0x40000, // Used for UI in Editor. Don't need show it DB. - MTL_64BIT_SHADERGENMASK = 0x80000, // ShaderGen mask is remapped - MTL_FLAG_RAYCAST_PROXY = 0x100000, - MTL_FLAG_REQUIRE_NEAREST_CUBEMAP = 0x200000, // materials with alpha blending requires special processing for shadows - MTL_FLAG_CONSOLE_MAT = 0x400000, - MTL_FLAG_DELETE_PENDING = 0x800000, // Internal use only - MTL_FLAG_BLEND_TERRAIN = 0x1000000, - MTL_FLAG_IS_TERRAIN = 0x2000000,// indication to the loader - Terrain type - MTL_FLAG_IS_SKY = 0x4000000,// indication to the loader - Sky type - MTL_FLAG_FOG_VOLUME_SHADING_QUALITY_HIGH= 0x8000000 // high vertex shading quality behaves more accurately with fog volumes. -}; - -#define MTL_FLAGS_SAVE_MASK (MTL_FLAG_WIRE | MTL_FLAG_2SIDED | MTL_FLAG_ADDITIVE | MTL_FLAG_LIGHTING | \ - MTL_FLAG_NOSHADOW | MTL_FLAG_MULTI_SUBMTL | MTL_FLAG_SCATTER | MTL_FLAG_REQUIRE_FORWARD_RENDERING | MTL_FLAG_FOG_VOLUME_SHADING_QUALITY_HIGH | MTL_FLAG_HIDEONBREAK | MTL_FLAG_UIMATERIAL | MTL_64BIT_SHADERGENMASK | MTL_FLAG_REQUIRE_NEAREST_CUBEMAP | MTL_FLAG_CONSOLE_MAT | MTL_FLAG_BLEND_TERRAIN) - -// Post effects flags -enum EPostEffectFlags -{ - POST_EFFECT_GHOST = 0x1, - POST_EFFECT_HOLOGRAM = 0x2, - - POST_EFFECT_MASK = POST_EFFECT_GHOST | POST_EFFECT_HOLOGRAM -}; - -// Bit offsets for shader layer flags -enum EMaterialLayerFlags -{ - // Active layers flags - MTL_LAYER_FROZEN = 0x0001, - MTL_LAYER_WET = 0x0002, - MTL_LAYER_DYNAMICFROZEN = 0x0008, - - // Usage flags - MTL_LAYER_USAGE_NODRAW = 0x0001, // Layer is disabled - MTL_LAYER_USAGE_REPLACEBASE = 0x0002, // Replace base pass rendering with layer - optimization - MTL_LAYER_USAGE_FADEOUT = 0x0004, // Layer doesn't render but still causes parent to fade out - - // Blend offsets - MTL_LAYER_BLEND_FROZEN = 0xff000000, - MTL_LAYER_BLEND_WET = 0x00fe0000, - MTL_LAYER_BLEND_DYNAMICFROZEN = 0x000000ff, - - MTL_LAYER_FROZEN_MASK = 0xff, - MTL_LAYER_WET_MASK = 0xfe, // bit stolen - MTL_LAYER_DYNAMICFROZEN_MASK = 0xff, - - MTL_LAYER_BLEND_MASK = (MTL_LAYER_BLEND_FROZEN | MTL_LAYER_BLEND_WET | MTL_LAYER_BLEND_DYNAMICFROZEN), - - // Slot count - MTL_LAYER_MAX_SLOTS = 3 -}; - -// copy flags -enum EMaterialCopyFlags -{ - // copy flags - MTL_COPY_DEFAULT = 0, - MTL_COPY_NAME = BIT(0), - MTL_COPY_TEXTURES = BIT(1), -}; - struct IMaterial { // TODO: Remove it! - //! default texture mapping - uint8 m_ucDefautMappingAxis; - float m_fDefautMappingScale; - // virtual ~IMaterial() {} - - ////////////////////////////////////////////////////////////////////////// - // Reference counting. - ////////////////////////////////////////////////////////////////////////// virtual void AddRef() = 0; virtual void Release() = 0; - virtual int GetNumRefs() = 0; - virtual IMaterialManager* GetMaterialManager() = 0; - - ////////////////////////////////////////////////////////////////////////// - // material name - ////////////////////////////////////////////////////////////////////////// - //! Set material name, (Do not use this directly - virtual void SetName(const char* pName) = 0; - //! Returns material name. - virtual const char* GetName() const = 0; - - //! Set/get shader name. The shader name may include technique name so it could be deferent than GetShaderItem()->m_pShader->GetName(). - virtual void SetShaderName(const char* pName) = 0; - virtual const char* GetShaderName() const = 0; - - //! Material flags. - //! @see EMaterialFlags - virtual void SetFlags(int flags) = 0; - virtual int GetFlags() const = 0; - virtual void UpdateFlags() = 0; - - // Returns true if this is the default material. - virtual bool IsDefault() = 0; - - virtual int GetSurfaceTypeId() = 0; - - // Assign a different surface type to this material. - virtual void SetSurfaceType(const char* sSurfaceTypeName) = 0; - - virtual ISurfaceType* GetSurfaceType() = 0; - - // shader item virtual SShaderItem& GetShaderItem() = 0; virtual const SShaderItem& GetShaderItem() const = 0; - // Returns shader item for correct sub material or for single material. - // Even if this is not sub material or nSubMtlSlot is invalid it will return valid renderable shader item. - virtual SShaderItem& GetShaderItem(int nSubMtlSlot) = 0; - virtual const SShaderItem& GetShaderItem(int nSubMtlSlot) const = 0; - - // Returns true if streamed in - virtual bool IsStreamedIn(const int nMinPrecacheRoundIds[MAX_STREAM_PREDICTION_ZONES], IRenderMesh* pRenderMesh) const = 0; - - // Description: - // Fill an array of integeres representing surface ids of the sub materials or the material itself. - // Arguments: - // pSurfaceIdsTable is a pointer to the array of int with size enough to hold MAX_SUB_MATERIALS surface type ids. - // Return: - // number of filled items. - virtual int FillSurfaceTypeIds(int pSurfaceIdsTable[]) = 0; - - ////////////////////////////////////////////////////////////////////////// - // UserData used to link with the Editor. - ////////////////////////////////////////////////////////////////////////// - virtual void SetUserData(void* pUserData) = 0; - virtual void* GetUserData() const = 0; - - ////////////////////////////////////////////////////////////////////////// - //! Set or get a material parameter value. - //! \param sParamName - Name of the parameter - //! \param v - Input or output value depending on bGet - //! \param bGet - If true, v is an output; if false, v is an input - //! \param allowShaderParam - If true, and sParamName is not a built-in parameter of the Material, then custom shader parameters will be searched as well. Defaults to false to preserve legacy behavior. - //! \param materialIndex - Index of the sub-material if this is a material group - //! return - True if sParamName was found - virtual bool SetGetMaterialParamFloat(const char* sParamName, float& v, bool bGet, bool allowShaderParam = false, int materialIndex = 0) = 0; - //! Set or get a material parameter value. - //! \param sParamName - Name of the parameter - //! \param v - Input or output value depending on bGet - //! \param bGet - If true, v is an output; if false, v is an input - //! \param allowShaderParam - If true, and sParamName is not a built-in parameter of the Material, then custom shader parameters will be searched as well. Defaults to false to preserve legacy behavior. - //! \param materialIndex - Index of the sub-material if this is a material group - //! return - True if sParamName was found - virtual bool SetGetMaterialParamVec3(const char* sParamName, Vec3& v, bool bGet, bool allowShaderParam = false, int materialIndex = 0) = 0; - //! Set or get a material parameter value. - //! \param sParamName - Name of the parameter - //! \param v - Input or output value depending on bGet - //! \param bGet - If true, v is an output; if false, v is an input - //! \param allowShaderParam - If true, and sParamName is not a built-in parameter of the Material, then custom shader parameters will be searched as well. Defaults to false to preserve legacy behavior. - //! \param materialIndex - Index of the sub-material if this is a material group - //! return - True if sParamName was found - virtual bool SetGetMaterialParamVec4(const char* sParamName, Vec4& v, bool bGet, bool allowShaderParam = false, int materialIndex = 0) = 0; - - virtual void SetDirty(bool dirty = true) = 0; - virtual bool IsDirty() const = 0; - - //! Returns true if the material is the parent of a group of materials - virtual bool IsMaterialGroup() const = 0; - - //! Returns true if the material is a single material belongs to a material group - virtual bool IsSubMaterial() const = 0; - - virtual void GetMemoryUsage(ICrySizer* pSizer) const = 0; - - virtual size_t GetResourceMemoryUsage(ICrySizer* pSizer) = 0; - - ////////////////////////////////////////////////////////////////////////// - // Makes this specific material enter sketch mode. - // Current supported sketch modes: - // - 0, no sketch. - // - 1, normal sketch mode. - // - 2, fast sketch mode. - virtual void SetSketchMode(int mode) = 0; - - // Sets FT_DONT_STREAM flag for all textures used by the material - // If a stream is already in process, this will stop the stream and flush the device texture - virtual void DisableTextureStreaming() = 0; - ////////////////////////////////////////////////////////////////////////// - // Tells to texture streamer to start loading textures asynchronously - ////////////////////////////////////////////////////////////////////////// - virtual void RequestTexturesLoading(const float fMipFactor) = 0; - - virtual void PrecacheMaterial(const float fEntDistance, struct IRenderMesh* pRenderMesh, bool bFullUpdate, bool bDrawNear = false) = 0; - - // Estimates texture memory usage for this material - // When nMatID is not negative only caluclate for one sub-material - virtual int GetTextureMemoryUsage(ICrySizer* pSizer, int nMatID = -1) = 0; - - // Set & retrieve a material link name - // This value by itself is not used by the material system per-se and hence - // has no real effect, however it is used on a higher level to tie related materials - // together, for example by procedural breakable glass to determine which material to - // switch to. - virtual void SetMaterialLinkName(const char* name) = 0; - virtual const char* GetMaterialLinkName() const = 0; - virtual void SetKeepLowResSysCopyForDiffTex() = 0; - - virtual uint32 GetDccMaterialHash() const = 0; - virtual void SetDccMaterialHash(uint32 hash) = 0; - - virtual void UpdateShaderItems() = 0; - - // -}; - - - -////////////////////////////////////////////////////////////////////////// -// Description: -// IMaterialManagerListener is a callback interface to listenen -// for special events of material manager, (used by Editor). -struct IMaterialManagerListener -{ - // - virtual ~IMaterialManagerListener(){} - // Called when material manager tries to load a material. - // nLoadingFlags - Zero or a bitwise combination of the flagas defined in ELoadingFlags. - virtual void OnCreateMaterial(_smart_ptr pMaterial) = 0; - virtual void OnDeleteMaterial(_smart_ptr pMaterial) = 0; - virtual bool IsCurrentMaterial(_smart_ptr pMaterial) const = 0; - // -}; - -using IMaterialRef = _smart_ptr; -////////////////////////////////////////////////////////////////////////// -// Description: -// IMaterialManager interface provide access to the material manager -// implemented in 3d engine. -struct IMaterialManager -{ - //! Loading flags - enum ELoadingFlags - { - ELoadingFlagsPreviewMode = BIT(0), - }; - - // - virtual ~IMaterialManager(){} - - virtual void GetMemoryUsage(ICrySizer* pSizer) const = 0; - - // Summary: - // Creates a new material object and register it with the material manager - // Return Value: - // A newly created object derived from IMaterial. - virtual _smart_ptr CreateMaterial(const char* sMtlName, int nMtlFlags = 0) = 0; - - // Summary: - // Renames a material object - // Note: - // Do not use IMaterial::SetName directly. - // Arguments: - // pMtl - Pointer to a material object - // sNewName - New name to assign to the material - virtual void RenameMaterial(_smart_ptr pMtl, const char* sNewName) = 0; - - // Description: - // Finds named material. - virtual _smart_ptr FindMaterial(const char* sMtlName) const = 0; - - // Description: - // Loads material. - // nLoadingFlags - Zero or a bitwise combination of the values defined in ELoadingFlags. - virtual _smart_ptr LoadMaterial(const char* sMtlName, bool bMakeIfNotFound = true, bool bNonremovable = false, unsigned long nLoadingFlags = 0) = 0; - - // Description: - // Loads material from xml. - virtual _smart_ptr LoadMaterialFromXml(const char* sMtlName, XmlNodeRef mtlNode) = 0; - - // Description: - // Reloads the material from disk. - virtual void ReloadMaterial(_smart_ptr pMtl) = 0; - - // Description: - // Saves material. - virtual bool SaveMaterial(XmlNodeRef mtlNode, _smart_ptr pMtl) = 0; - - // Description: - // Clone single material or multi sub material. - // Arguments: - // nSubMtl - when negative all sub materials of MultiSubMtl are cloned, if positive only specified slot is cloned. - virtual _smart_ptr CloneMaterial(_smart_ptr pMtl, int nSubMtl = -1) = 0; - - // Description: - // Copy single material. - virtual void CopyMaterial(_smart_ptr pMtlSrc, _smart_ptr pMtlDest, EMaterialCopyFlags flags) = 0; - - // Description: - // Clone MultiSubMtl material. - // Arguments: - // sSubMtlName - name of the sub-material to clone, if NULL all submaterial are cloned. - virtual _smart_ptr CloneMultiMaterial(_smart_ptr pMtl, const char* sSubMtlName = 0) = 0; - - // Description: - // Associate a special listener callback with material manager inside 3d engine. - // This listener callback is used primerly by the editor. - virtual void SetListener(IMaterialManagerListener* pListener) = 0; - - // Description: - // Retrieve a default engine material. - virtual _smart_ptr GetDefaultMaterial() = 0; - - // Description: - // Retrieve a default engine material for terrain layer - virtual _smart_ptr GetDefaultTerrainLayerMaterial() = 0; - - // Description: - // Retrieve a default engine material with material layers presets. - virtual _smart_ptr GetDefaultLayersMaterial() = 0; - - // Description: - // Retrieve a default engine material for drawing helpers. - virtual _smart_ptr GetDefaultHelperMaterial() = 0; - - // Description: - // Retrieve surface type by name. - virtual ISurfaceType* GetSurfaceTypeByName(const char* sSurfaceTypeName, const char* sWhy = NULL) = 0; - virtual int GetSurfaceTypeIdByName(const char* sSurfaceTypeName, const char* sWhy = NULL) = 0; - // Description: - // Retrieve surface type by unique surface type id. - virtual ISurfaceType* GetSurfaceType(int nSurfaceTypeId, const char* sWhy = NULL) = 0; - // Description: - // Retrieve interface to surface type manager. - virtual ISurfaceTypeManager* GetSurfaceTypeManager() = 0; - - // Get IMaterial pointer from the CGF material structure. - // nLoadingFlags - Zero, or a bitwise combination of the enum items from ELoadingFlags. - virtual _smart_ptr LoadCGFMaterial(CMaterialCGF* pMaterialCGF, const char* sCgfFilename, unsigned long nLoadingFlags = 0) = 0; - - // for statistics - call once to get the count (pData==0), again to get the data(pData!=0) - virtual void GetLoadedMaterials(AZStd::vector<_smart_ptr>* pData, uint32& nObjCount) const = 0; - - // Updates material data in the renderer - virtual void RefreshMaterialRuntime() = 0; - - // }; diff --git a/Code/Legacy/CryCommon/IMovieSystem.h b/Code/Legacy/CryCommon/IMovieSystem.h index 5d878c45ec..b5302b58f5 100644 --- a/Code/Legacy/CryCommon/IMovieSystem.h +++ b/Code/Legacy/CryCommon/IMovieSystem.h @@ -21,7 +21,6 @@ #include #include #include -#include // forward declaration. struct IAnimTrack; diff --git a/Code/Legacy/CryCommon/IPathfinder.h b/Code/Legacy/CryCommon/IPathfinder.h index 781e379cf9..7a05321c99 100644 --- a/Code/Legacy/CryCommon/IPathfinder.h +++ b/Code/Legacy/CryCommon/IPathfinder.h @@ -15,11 +15,12 @@ struct IAIPathAgent; #include #include -#include #include #include +#include #include +#include #include #include @@ -131,8 +132,7 @@ struct NavigationBlocker Location location; }; -typedef DynArray NavigationBlockers; - +using NavigationBlockers = AZStd::vector; //==================================================================== // PathPointDescriptor @@ -240,8 +240,7 @@ struct PathfindingExtraConstraint UConstraint constraint; }; -typedef DynArray PathfindingExtraConstraints; - +using PathfindingExtraConstraints = AZStd::vector; struct PathfindRequest { @@ -557,26 +556,6 @@ public: virtual void Draw(const Vec3& drawOffset = ZERO) const = 0; virtual void Dump(const char* name) const = 0; - bool ArePathsEqual(const INavPath& otherNavPath) - { - const TPathPoints& path1 = this->GetPath(); - const TPathPoints& path2 = otherNavPath.GetPath(); - const TPathPoints::size_type path1Size = path1.size(); - const TPathPoints::size_type path2Size = path2.size(); - if (path1Size != path2Size) - { - return false; - } - - TPathPoints::const_iterator path1It = path1.begin(); - TPathPoints::const_iterator path1End = path1.end(); - TPathPoints::const_iterator path2It = path2.begin(); - - typedef std::pair TMismatchResult; - - TMismatchResult result = std::mismatch(path1It, path1End, path2It, PathPointDescriptor::ArePointsEquivalent); - return result.first == path1.end(); - } }; using INavPathPtr = AZStd::shared_ptr; diff --git a/Code/Legacy/CryCommon/IPhysics.h b/Code/Legacy/CryCommon/IPhysics.h deleted file mode 100644 index a1825d3e44..0000000000 --- a/Code/Legacy/CryCommon/IPhysics.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - -#pragma once -#include -#include "Cry_Math.h" -#include "primitives.h" -#include // <> required for Interfuscator - -////////////////////////////////////////////////////////////////////////// -// IDs that can be used for foreign id. -////////////////////////////////////////////////////////////////////////// -enum EPhysicsForeignIds -{ - PHYS_FOREIGN_ID_TERRAIN = 0, - PHYS_FOREIGN_ID_STATIC = 1, - PHYS_FOREIGN_ID_ENTITY = 2, - PHYS_FOREIGN_ID_FOLIAGE = 3, - PHYS_FOREIGN_ID_ROPE = 4, - PHYS_FOREIGN_ID_SOUND_OBSTRUCTION = 5, - PHYS_FOREIGN_ID_SOUND_PROXY_OBSTRUCTION = 6, - PHYS_FOREIGN_ID_SOUND_REVERB_OBSTRUCTION = 7, - PHYS_FOREIGN_ID_WATERVOLUME = 8, - PHYS_FOREIGN_ID_BREAKABLE_GLASS = 9, - PHYS_FOREIGN_ID_BREAKABLE_GLASS_FRAGMENT = 10, - PHYS_FOREIGN_ID_RIGID_PARTICLE = 11, - PHYS_FOREIGN_ID_RESERVED1 = 12, - PHYS_FOREIGN_ID_RAGDOLL = 13, - PHYS_FOREIGN_ID_COMPONENT_ENTITY = 14, - - PHYS_FOREIGN_ID_USER = 100, // All user defined foreign ids should start from this enum. -}; diff --git a/Code/Legacy/CryCommon/IPostEffectGroup.h b/Code/Legacy/CryCommon/IPostEffectGroup.h deleted file mode 100644 index d8452b75ab..0000000000 --- a/Code/Legacy/CryCommon/IPostEffectGroup.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ -#pragma once - -#include - -typedef AZStd::variant PostEffectGroupParam; - -// A prioritized group of postprocessing effect parameters. -// These are defined in XML files and can be enabled or disabled using flow graph or Lua scripts. -// Effect groups can also optionally specify blend curves to smoothly transition between effects, whether to stay enabled until explicitly disabled, -// and whether to make effect strength based on distance from the camera. -class IPostEffectGroup -{ -public: - virtual ~IPostEffectGroup(){} - - virtual const char* GetName() const = 0; - virtual void SetEnable(bool enable) = 0; - virtual bool GetEnable() const = 0; - virtual unsigned int GetPriority() const = 0; - virtual bool GetHold() const = 0; - virtual float GetFadeDistance() const = 0; - virtual void SetParam(const char* name, const PostEffectGroupParam& value) = 0; - virtual PostEffectGroupParam* GetParam(const char* name) = 0; - virtual void ClearParams() = 0; - // Increases the strength of the effects based on distance from the camera each time it's called. The effect strength is cleared each frame. - // Only applies to effect groups with the fadeDistance attribute set. - virtual void ApplyAtPosition(const Vec3& position) = 0; -}; - -typedef AZStd::list PostEffectGroupList; - -class IPostEffectGroupManager -{ -public: - virtual ~IPostEffectGroupManager(){} - - virtual IPostEffectGroup* GetGroup(const char* name) = 0; - virtual IPostEffectGroup* GetGroup(const unsigned int index) = 0; - virtual const unsigned int GetGroupCount() = 0; - // Returns a list of IPostEffectGroups who had their Enabled state toggled this frame - virtual const PostEffectGroupList& GetGroupsToggledThisFrame() = 0; -}; diff --git a/Code/Legacy/CryCommon/IRenderMesh.h b/Code/Legacy/CryCommon/IRenderMesh.h deleted file mode 100644 index 0e225579ad..0000000000 --- a/Code/Legacy/CryCommon/IRenderMesh.h +++ /dev/null @@ -1,282 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - -#ifndef CRYINCLUDE_CRYCOMMON_IRENDERMESH_H -#define CRYINCLUDE_CRYCOMMON_IRENDERMESH_H -#pragma once - -#include "VertexFormats.h" -#include -#include // PublicRenderPrimitiveType -#include -#include -#include - -class CMesh; -class CRenderObject; -struct SSkinningData; -struct IMaterial; -struct IIndexedMesh; -struct SMRendTexVert; -struct UCol; -struct GeomInfo; - -struct TFace; -struct SMeshSubset; -struct SRenderingPassInfo; -struct SRendItemSorter; -struct SRenderObjectModifier; - -namespace AZ -{ - namespace Vertex - { - class Format; - } -} - -enum eRenderPrimitiveType : int8; - -// Keep this in sync with BUFFER_USAGE hints DevBuffer.h -enum ERenderMeshType -{ - eRMT_Immmutable = 0, - eRMT_Static = 1, - eRMT_Dynamic = 2, - eRMT_Transient = 3, -}; - - -#define FSM_VERTEX_VELOCITY 1 -#define FSM_NO_TANGENTS 2 -#define FSM_CREATE_DEVICE_MESH 4 -#define FSM_SETMESH_ASYNC 8 -#define FSM_ENABLE_NORMALSTREAM 16 -#define FSM_IGNORE_TEXELDENSITY 32 - -// Invalidate video buffer flags -#define FMINV_STREAM 1 -#define FMINV_STREAM_MASK ((1 << VSF_NUM) - 1) -#define FMINV_INDICES 0x100 -#define FMINV_ALL -1 - -// Stream lock flags -#define FSL_READ 0x01 -#define FSL_WRITE 0x02 -#define FSL_DYNAMIC 0x04 -#define FSL_DISCARD 0x08 -#define FSL_VIDEO 0x10 -#define FSL_SYSTEM 0x20 -#define FSL_INSTANCED 0x40 -#define FSL_NONSTALL_MAP 0x80 // Map must not stall for VB/IB locking -#define FSL_VBIBPUSHDOWN 0x100 // Push down from vram on demand if target architecture supports it, used internally -#define FSL_DIRECT 0x200 // Access VRAM directly if target architecture supports it, used internally -#define FSL_LOCKED 0x400 // Internal use -#define FSL_SYSTEM_CREATE (FSL_WRITE | FSL_DISCARD | FSL_SYSTEM) -#define FSL_SYSTEM_UPDATE (FSL_WRITE | FSL_SYSTEM) -#define FSL_VIDEO_CREATE (FSL_WRITE | FSL_DISCARD | FSL_VIDEO) -#define FSL_VIDEO_UPDATE (FSL_WRITE | FSL_VIDEO) - -#define FSL_ASYNC_DEFER_COPY (1u << 1) -#define FSL_FREE_AFTER_ASYNC (2u << 1) - -struct IRenderMesh -{ - enum EMemoryUsageArgument - { - MEM_USAGE_COMBINED, - MEM_USAGE_ONLY_SYSTEM, - MEM_USAGE_ONLY_VIDEO, - MEM_USAGE_ONLY_STREAMS, - }; - - // Render mesh initialization parameters, that can be used to create RenderMesh from raw pointers. - struct SInitParamerers - { - AZ::Vertex::Format vertexFormat; - ERenderMeshType eType; - - void* pVertBuffer; - int nVertexCount; - SPipTangents* pTangents; - SPipNormal* pNormals; - vtx_idx* pIndices; - int nIndexCount; - PublicRenderPrimitiveType nPrimetiveType; - int nRenderChunkCount; - int nClientTextureBindID; - bool bOnlyVideoBuffer; - bool bPrecache; - bool bLockForThreadAccess; - - SInitParamerers() - : vertexFormat(eVF_P3F_C4B_T2F) - , eType(eRMT_Static) - , pVertBuffer(0) - , nVertexCount(0) - , pTangents(0) - , pNormals(0) - , pIndices(0) - , nIndexCount(0) - , nPrimetiveType(PublicRenderPrimitiveType::prtTriangleList) - , nRenderChunkCount(0) - , nClientTextureBindID(0) - , bOnlyVideoBuffer(false) - , bPrecache(true) - , bLockForThreadAccess(false) {} - }; - - struct ThreadAccessLock - { - ThreadAccessLock(IRenderMesh* pRM) - : m_pRM(pRM) - { - m_pRM->LockForThreadAccess(); - } - - ~ThreadAccessLock() - { - m_pRM->UnLockForThreadAccess(); - } - - private: - ThreadAccessLock(const ThreadAccessLock&); - ThreadAccessLock& operator = (const ThreadAccessLock&); - - private: - IRenderMesh* m_pRM; - }; - - // - virtual ~IRenderMesh(){} - - ////////////////////////////////////////////////////////////////////////// - // Reference Counting. - virtual void AddRef() = 0; - virtual int Release() = 0; - ////////////////////////////////////////////////////////////////////////// - - // Prevent rendering if video memory could not been allocated for it - virtual bool CanRender() = 0; - - // Returns type name given to the render mesh on creation time. - virtual const char* GetTypeName() = 0; - // Returns the name of the source given to the render mesh on creation time. - virtual const char* GetSourceName() const = 0; - - virtual int GetIndicesCount() = 0; - virtual int GetVerticesCount() = 0; - virtual AZ::Vertex::Format GetVertexFormat() = 0; - virtual ERenderMeshType GetMeshType() = 0; - virtual float GetGeometricMeanFaceArea() const = 0; - - virtual bool CheckUpdate(uint32 nStreamMask) = 0; - virtual int GetStreamStride(int nStream) const = 0; - - virtual int GetNumVerts() const = 0; - virtual int GetNumInds() const = 0; - virtual const eRenderPrimitiveType GetPrimitiveType() const = 0; - - virtual void SetSkinned(bool bSkinned = true) = 0; - virtual uint GetSkinningWeightCount() const = 0; - - // Create render buffers from render mesh. Returns the final size of the render mesh or ~0U on failure - virtual size_t SetMesh(CMesh& mesh, int nSecColorsSetOffset, uint32 flags, bool requiresLock) = 0; - virtual void CopyTo(IRenderMesh* pDst, int nAppendVtx = 0, bool bDynamic = false, bool fullCopy = true) = 0; - virtual void SetSkinningDataVegetation(struct SMeshBoneMapping_uint8* pBoneMapping) = 0; - virtual void SetSkinningDataCharacter(CMesh& mesh, struct SMeshBoneMapping_uint16* pBoneMapping, struct SMeshBoneMapping_uint16* pExtraBoneMapping) = 0; - // Creates an indexed mesh from this render mesh (accepts an optional pointer to an IIndexedMesh object that should be used) - virtual IIndexedMesh* GetIndexedMesh(IIndexedMesh* pIdxMesh = 0) = 0; - virtual int GetRenderChunksCount(_smart_ptr pMat, int& nRenderTrisCount) = 0; - - virtual IRenderMesh* GenerateMorphWeights() = 0; - virtual IRenderMesh* GetMorphBuddy() = 0; - virtual void SetMorphBuddy(IRenderMesh* pMorph) = 0; - - virtual bool UpdateVertices(const void* pVertBuffer, int nVertCount, int nOffset, int nStream, uint32 copyFlags, bool requiresLock = true) = 0; - virtual bool UpdateIndices(const vtx_idx* pNewInds, int nInds, int nOffsInd, uint32 copyFlags, bool requiresLock = true) = 0; - virtual void SetCustomTexID(int nCustomTID) = 0; - - virtual void GenerateQTangents() = 0; - virtual void CreateChunksSkinned() = 0; - virtual void NextDrawSkinned() = 0; - virtual IRenderMesh* GetVertexContainer() = 0; - virtual void SetVertexContainer(IRenderMesh* pBuf) = 0; - virtual void SetBBox(const Vec3& vBoxMin, const Vec3& vBoxMax) = 0; - virtual void GetBBox(Vec3& vBoxMin, Vec3& vBoxMax) = 0; - virtual void UpdateBBoxFromMesh() = 0; - virtual uint32* GetPhysVertexMap() = 0; - virtual bool IsEmpty() = 0; - - virtual int8* GetPosPtrNoCache(int32& nStride, uint32 nFlags) = 0; - virtual int8* GetPosPtr(int32& nStride, uint32 nFlags) = 0; - virtual int8* GetColorPtr(int32& nStride, uint32 nFlags) = 0; - virtual int8* GetNormPtr(int32& nStride, uint32 nFlags) = 0; - //! Returns a pointer to the first uv coordinate in the interleaved vertex stream - virtual int8* GetUVPtrNoCache(int32& nStride, uint32 nFlags, uint32 uvSetIndex = 0) = 0; - /*! Get a pointer to the mesh's uv coordinates and the stride from the beginning of one uv coordinate to the next - \param[out] nStride The stride in between successive uv coordinates. - \param nFlags Stream lock flags (FSL_READ, FSL_WRITE, etc) - \param uvSetIndex Which uv set to retrieve (defaults to 0) - \return A pointer to cached uvs which contains all of the uv coordinates contiguous in memory, or as a fallback a pointer to the first uv coordinate in the interleaved vertex stream - Either way, nStride is set such that the caller can use it to iterate over the data in the same way regardless of which pointer was returned - Returns nullptr if there is no uv coordinate stream at the given index - */ - virtual int8* GetUVPtr(int32& nStride, uint32 nFlags, uint32 uvSetIndex = 0) = 0; - - virtual int8* GetTangentPtr(int32& nStride, uint32 nFlags) = 0; - virtual int8* GetQTangentPtr(int32& nStride, uint32 nFlags) = 0; - - virtual int8* GetHWSkinPtr(int32& nStride, uint32 nFlags, bool remapped = false) = 0; - virtual int8* GetVelocityPtr(int32& nStride, uint32 nFlags) = 0; - - virtual void UnlockStream(int nStream) = 0; - virtual void UnlockIndexStream() = 0; - - virtual vtx_idx* GetIndexPtr(uint32 nFlags, int32 nOffset = 0) = 0; - virtual const PodArray >* GetTrisForPosition(const Vec3& vPos, _smart_ptr pMaterial) = 0; - - virtual float GetExtent(EGeomForm eForm) = 0; - virtual void GetRandomPos(PosNorm& ran, EGeomForm eForm, SSkinningData const* pSkinning = NULL) = 0; - - virtual void Render(const struct SRendParams& rParams, CRenderObject* pObj, _smart_ptr pMaterial, const SRenderingPassInfo& passInfo, bool bSkinned = false) = 0; - virtual void Render(CRenderObject* pObj, const SRenderingPassInfo& passInfo, const SRendItemSorter& rendItemSorter) = 0; - virtual void SetREUserData(float* pfCustomData, float fFogScale = 0, float fAlpha = 1) = 0; - - // Debug draw this render mesh. - virtual void DebugDraw(const struct SGeometryDebugDrawInfo& info, uint32 nVisibleChunksMask = ~0, float fExtrdueScale = 0.01f) = 0; - - // Returns mesh memory usage and add it to the CrySizer (if not NULL). - // Arguments: - // pSizer - Sizer interface, can be NULL if caller only want to calculate size - // nType - see EMemoryUsageArgument - virtual size_t GetMemoryUsage(ICrySizer* pSizer, EMemoryUsageArgument nType) const = 0; - virtual void GetMemoryUsage(ICrySizer* pSizer) const = 0; - - // Get allocated only in video memory or only in system memory. - virtual int GetAllocatedBytes(bool bVideoMem) const = 0; - virtual float GetAverageTrisNumPerChunk(_smart_ptr pMat) = 0; - virtual int GetTextureMemoryUsage(const _smart_ptr pMaterial, ICrySizer* pSizer = NULL, bool bStreamedIn = true) const = 0; - virtual void KeepSysMesh(bool keep) = 0; // HACK: temp workaround for GDC-888 - virtual void UnKeepSysMesh() = 0; - virtual void SetMeshLod(int nLod) = 0; - - virtual void LockForThreadAccess() = 0; - virtual void UnLockForThreadAccess() = 0; - - // Sets the async update state - will sync before rendering to this - virtual volatile int* SetAsyncUpdateState(void) = 0; - virtual void CreateRemappedBoneIndicesPair(const DynArray& arrRemapTable, const uint pairGuid) = 0; - virtual void ReleaseRemappedBoneIndicesPair(const uint pairGuid) = 0; - - virtual void OffsetPosition(const Vec3& delta) = 0; - // -}; - -#endif // CRYINCLUDE_CRYCOMMON_IRENDERMESH_H diff --git a/Code/Legacy/CryCommon/ISerialize.h b/Code/Legacy/CryCommon/ISerialize.h index b153a52487..82ba9aef0d 100644 --- a/Code/Legacy/CryCommon/ISerialize.h +++ b/Code/Legacy/CryCommon/ISerialize.h @@ -17,7 +17,6 @@ #include #include #include "MiniQueue.h" -#include #include #include #include @@ -105,8 +104,6 @@ struct SNetObjectID } void GetMemoryUsage([[maybe_unused]] ICrySizer* pSizer) const { /*nothing*/} - - AUTO_STRUCT_INFO }; // this enumeration details what "kind" of serialization we are @@ -154,8 +151,6 @@ private: ////////////////////////////////////////////////////////////////////////// struct SSerializeString { - AUTO_STRUCT_INFO - SSerializeString() {}; SSerializeString(const SSerializeString& src) { m_str.assign(src.c_str()); }; explicit SSerializeString(const char* sbegin, const char* send) @@ -571,8 +566,6 @@ public: CONTAINER_VALUE(std::list, push_back); CONTAINER_VALUE(std::set, insert); CONTAINER_VALUE(std::deque, push_back); - CONTAINER_VALUE(VectorSet, insert); - CONTAINER_VALUE(DynArray, insert); PAIR_CONTAINER_VALUE(std::list, push_back); PAIR_CONTAINER_VALUE(std::vector, push_back); diff --git a/Code/Legacy/CryCommon/IShader.h b/Code/Legacy/CryCommon/IShader.h index 93f8534dfc..e9a00d3b76 100644 --- a/Code/Legacy/CryCommon/IShader.h +++ b/Code/Legacy/CryCommon/IShader.h @@ -6,161 +6,35 @@ * */ - // Description : Shaders common interface. - #pragma once - #if defined(LINUX) || defined(APPLE) #include #endif #include "smartptr.h" - #include "Cry_Vector3.h" - #include "Cry_Color.h" -#include "smartptr.h" - #include "VertexFormats.h" #include - - -#include -#include - -struct IMaterial; -class CRendElementBase; -class CRenderObject; -class CREMesh; -struct IRenderMesh; -struct IShader; -struct IVisArea; - -class CRendElement; -class CRendElementBase; -class CTexture; -class CTexAnim; -class CShader; -class ITexAnim; -struct SShaderPass; -struct SShaderItem; -class ITexture; -struct IMaterial; -struct SParam; -struct SShaderSerializeContext; -struct IAnimNode; -struct SSkinningData; -struct SSTexSamplerFX; -struct SShaderTextureSlot; -struct IRenderElement; - -namespace AZ -{ - class LegacyJobExecutor; - - namespace Vertex - { - class Format; - } -} - -//================================================================ -// Summary: -// Geometry Culling type. -enum ECull -{ - eCULL_Back = 0, // Back culling flag. - eCULL_Front, // Front culling flag. - eCULL_None // No culling flag. -}; - -enum ERenderResource -{ - eRR_Unknown, - eRR_Mesh, - eRR_Texture, - eRR_Shader, - eRR_ShaderResource, -}; - enum EEfResTextures : int // This needs a fixed size so the enum can be forward declared (needed by IMaterial.h) { EFTT_DIFFUSE = 0, EFTT_NORMALS, EFTT_SPECULAR, - EFTT_ENV, - EFTT_DETAIL_OVERLAY, - EFTT_SECOND_SMOOTHNESS, - EFTT_HEIGHT, - EFTT_DECAL_OVERLAY, - EFTT_SUBSURFACE, - EFTT_CUSTOM, - EFTT_CUSTOM_SECONDARY, EFTT_OPACITY, EFTT_SMOOTHNESS, EFTT_EMITTANCE, - EFTT_OCCLUSION, - EFTT_SPECULAR_2, - EFTT_MAX, EFTT_UNKNOWN = EFTT_MAX }; -enum EEfResSamplers -{ - EFSS_ANISO_HIGH = 0, - EFSS_ANISO_LOW, - EFSS_TRILINEAR, - EFSS_BILINEAR, - EFSS_TRILINEAR_CLAMP, - EFSS_BILINEAR_CLAMP, - EFSS_ANISO_HIGH_BORDER, - EFSS_TRILINEAR_BORDER, - - EFSS_MAX, -}; - -//========================================================================= - -// Summary: -// Array Pointers for Shaders. - -enum ESrcPointer -{ - eSrcPointer_Unknown, - eSrcPointer_Vert, - eSrcPointer_Color, - eSrcPointer_Tex, - eSrcPointer_TexLM, - eSrcPointer_Normal, - eSrcPointer_Tangent, - eSrcPointer_Max, -}; - -struct SWaveForm; -struct SWaveForm2; - -#define FRF_REFRACTIVE 1 -// FREE 2 -#define FRF_HEAT 4 -#define MAX_HEATSCALE 4 - #if !defined(MAX_JOINT_AMOUNT) #error MAX_JOINT_AMOUNT is not defined #endif -#if (MAX_JOINT_AMOUNT <= 256) -typedef uint8 JointIdType; -#else -typedef uint16 JointIdType; -#endif - -// The soft maximum cap for the sliders for emissive intensity. Also used to clamp legacy glow calculations in MaterialHelpers::MigrateXmlLegacyData. -// Note this is a "soft max" because the Emissive Intensity slider is capped at 200, but values higher than 200 may be entered in the text field. -#define EMISSIVE_INTENSITY_SOFT_MAX 200.0f //========================================================================= @@ -176,17 +50,10 @@ enum EParamType eType_STRING, eType_FCOLOR, eType_VECTOR, - eType_TEXTURE_HANDLE, - eType_CAMERA, - eType_FCOLORA, // with alpha channel }; -enum ESamplerType -{ - eSType_UNKNOWN, - eSType_Sampler, - eSType_SamplerComp, -}; +struct IShader; +class CCamera; union UParamVal { @@ -201,999 +68,20 @@ union UParamVal CCamera* m_pCamera; }; -// Note: -// In order to facilitate the memory allocation tracking, we're using here this class; -// if you don't like it, please write a substitute for all string within the project and use them everywhere. struct SShaderParam { AZStd::string m_Name; - AZStd::string m_Script; UParamVal m_Value; EParamType m_Type; - uint8 m_eSemantic; - uint8 m_Pad[3] = { 0 }; - - void Construct() - { - memset(&m_Value, 0, sizeof(m_Value)); - m_Type = eType_UNKNOWN; - m_eSemantic = 0; - m_Name.clear(); - m_Script.clear(); - } - - SShaderParam() - { - Construct(); - } - size_t Size() - { - size_t nSize = sizeof(*this); - if (m_Type == eType_STRING) - { - nSize += strlen (m_Value.m_String) + 1; - } - - return nSize; - } - void GetMemoryUsage(ICrySizer* pSizer) const - { - pSizer->AddObject(m_Script); - if (m_Type == eType_STRING) - { - pSizer->AddObject(m_Value.m_String, strlen (m_Value.m_String) + 1); - } - } - - void Destroy() - { - if (m_Type == eType_STRING) - { - delete [] m_Value.m_String; - } - } - - ~SShaderParam() - { - Destroy(); - } - - SShaderParam (const SShaderParam& src) - { - m_Name = src.m_Name; - m_Script = src.m_Script; - m_Type = src.m_Type; - m_eSemantic = src.m_eSemantic; - if (m_Type == eType_STRING) - { - const size_t len = strlen(src.m_Value.m_String) + 1; - m_Value.m_String = new char[len]; - azstrcpy(m_Value.m_String, len, src.m_Value.m_String); - } - else - { - m_Value = src.m_Value; - } - } - - SShaderParam& operator = (const SShaderParam& src) - { - this->~SShaderParam(); - new(this)SShaderParam(src); - return *this; - } - - static bool SetParam(const char* name, AZStd::vector* Params, const UParamVal& pr) - { - uint32 i; - for (i = 0; i < (uint32)Params->size(); i++) - { - SShaderParam* sp = &(*Params)[i]; - if (!sp || &sp->m_Value == &pr) - { - continue; - } - if (azstricmp(sp->m_Name.c_str(), name) == 0) - { - if (sp->m_Type == eType_STRING) - { - delete[] sp->m_Value.m_String; - } - - - switch (sp->m_Type) - { - case eType_FLOAT: - sp->m_Value.m_Float = pr.m_Float; - break; - case eType_SHORT: - sp->m_Value.m_Short = pr.m_Short; - break; - case eType_INT: - case eType_TEXTURE_HANDLE: - sp->m_Value.m_Int = pr.m_Int; - break; - - case eType_VECTOR: - sp->m_Value.m_Vector[0] = pr.m_Vector[0]; - sp->m_Value.m_Vector[1] = pr.m_Vector[1]; - sp->m_Value.m_Vector[2] = pr.m_Vector[2]; - break; - - case eType_FCOLOR: - case eType_FCOLORA: - sp->m_Value.m_Color[0] = pr.m_Color[0]; - sp->m_Value.m_Color[1] = pr.m_Color[1]; - sp->m_Value.m_Color[2] = pr.m_Color[2]; - sp->m_Value.m_Color[3] = pr.m_Color[3]; - break; - - case eType_STRING: - { - char* str = pr.m_String; - const size_t len = strlen(str) + 1; - sp->m_Value.m_String = new char [len]; - azstrcpy(sp->m_Value.m_String, len, str); - } - break; - } - break; - } - } - if (i == Params->size()) - { - return false; - } - return true; - } - static bool GetValue(const char* szName, AZStd::vector* Params, float* v, int nID); - - static bool GetValue(uint8 eSemantic, AZStd::vector* Params, float* v, int nID); - - void CopyValue(const SShaderParam& src) - { - if (m_Type == eType_STRING && this != &src) - { - delete[] m_Value.m_String; - - if (src.m_Type == eType_STRING) - { - size_t size = strlen(src.m_Value.m_String) + 1; - m_Value.m_String = new char[size]; - azstrcpy(m_Value.m_String, size, src.m_Value.m_String); - return; - } - } - - m_Value = src.m_Value; - } - - void CopyValueNoString(const SShaderParam& src) - { - assert(m_Type != eType_STRING && src.m_Type != eType_STRING); - - m_Value = src.m_Value; - } - - void CopyType(const SShaderParam& src) - { - m_Type = src.m_Type; - } }; - -// Summary: -// Vertex modificators definitions (must be 16 bit flag). - -#define MDV_BENDING 0x100 -#define MDV_DET_BENDING 0x200 -#define MDV_DET_BENDING_GRASS 0x400 -#define MDV_WIND 0x800 -#define MDV_DEPTH_OFFSET 0x2000 - -// Does the vertex shader require position-invariant compilation? -// This would be true of shaders rendering multiple times with different vertex shaders - for example during zprepass and the gbuffer pass -// Note this is different than the technique flag FHF_POSITION_INVARIANT as that does custom behavior for terrain -#define MDV_POSITION_INVARIANT 0x4000 - - -//============================================================================== -// CRenderObject - -////////////////////////////////////////////////////////////////////// -// CRenderObject::m_ObjFlags: Flags used by shader pipeline - -enum ERenderObjectFlags -{ - FOB_VERTEX_VELOCITY = BIT(0), - FOB_RENDER_TRANS_AFTER_DOF = BIT(1), //transparencies rendered after depth of field - //Unused = BIT(2), - FOB_RENDER_AFTER_POSTPROCESSING = BIT(3), - FOB_OWNER_GEOMETRY = BIT(4), - FOB_MESH_SUBSET_INDICES = BIT(5), - FOB_SELECTED = BIT(6), - FOB_RENDERER_IDENDITY_OBJECT = BIT(7), - FOB_GLOBAL_ILLUMINATION = BIT(8), - FOB_NO_FOG = BIT(9), - FOB_DECAL = BIT(10), - FOB_OCTAGONAL = BIT(11), - FOB_POINT_SPRITE = BIT(13), - FOB_SOFT_PARTICLE = BIT(14), - FOB_REQUIRES_RESOLVE = BIT(15), - FOB_UPDATED_RTMASK = BIT(16), - FOB_AFTER_WATER = BIT(17), - FOB_BENDED = BIT(18), - FOB_ZPREPASS = BIT(19), - FOB_PARTICLE_SHADOWS = BIT(20), - FOB_DISSOLVE = BIT(21), - FOB_MOTION_BLUR = BIT(22), - FOB_NEAREST = BIT(23), // [Rendered in Camera Space] - FOB_SKINNED = BIT(24), - FOB_DISSOLVE_OUT = BIT(25), - FOB_DYNAMIC_OBJECT = BIT(26), - FOB_ALLOW_TESSELLATION = BIT(27), - FOB_DECAL_TEXGEN_2D = BIT(28), - FOB_IN_DOORS = BIT(29), - FOB_HAS_PREVMATRIX = BIT(30), - FOB_LIGHTVOLUME = BIT(31), - - FOB_DECAL_MASK = (FOB_DECAL | FOB_DECAL_TEXGEN_2D), - FOB_PARTICLE_MASK = (FOB_SOFT_PARTICLE | FOB_NO_FOG | FOB_GLOBAL_ILLUMINATION | FOB_PARTICLE_SHADOWS | FOB_NEAREST | FOB_MOTION_BLUR | FOB_LIGHTVOLUME | FOB_ALLOW_TESSELLATION | FOB_IN_DOORS | FOB_AFTER_WATER), - - // WARNING: FOB_MASK_AFFECTS_MERGING must start from 0x10000/bit 16 (important for instancing). - FOB_MASK_AFFECTS_MERGING_GEOM = (FOB_ZPREPASS | FOB_SKINNED | FOB_BENDED | FOB_DYNAMIC_OBJECT | FOB_ALLOW_TESSELLATION | FOB_NEAREST), - FOB_MASK_AFFECTS_MERGING = (FOB_ZPREPASS | FOB_MOTION_BLUR | FOB_HAS_PREVMATRIX | FOB_SKINNED | FOB_BENDED | FOB_PARTICLE_SHADOWS | FOB_AFTER_WATER | FOB_DISSOLVE | FOB_DISSOLVE_OUT | FOB_NEAREST | FOB_DYNAMIC_OBJECT | FOB_ALLOW_TESSELLATION) -}; - -struct SSkyInfo -{ - ITexture* m_SkyBox[3]; - float m_fSkyLayerHeight; - - int Size() - { - int nSize = sizeof(SSkyInfo); - return nSize; - } - SSkyInfo() - { - memset(this, 0, sizeof(SSkyInfo)); - } -}; - - -// Description: -// Interface for the skinnable objects (renderer calls its functions to get the skinning data). -// should only created by EF_CreateSkinningData -struct alignas(16) SSkinningData -{ - uint32 nNumBones; - uint32 nHWSkinningFlags; - DualQuat* pBoneQuatsS; - Matrix34* pBoneMatrices; - JointIdType* pRemapTable; - AZ::LegacyJobExecutor* pAsyncJobExecutor; - AZ::LegacyJobExecutor* pAsyncDataJobExecutor; - SSkinningData* pPreviousSkinningRenderData; // used for motion blur - uint32 remapGUID; - void* pCharInstCB; // used if per char instance cbs are available in renderdll (d3d11+); - // members below are for Software Skinning - void* pCustomData; // client specific data, used for example for sw-skinning on animation side - SSkinningData* pNextSkinningData; // List to the next element which needs SW-Skinning - [[maybe_unused]] int m_padding[2]; // padding to avoid MSVC warning 4324 -}; - -struct alignas(16) SRenderObjData -{ - uintptr_t m_uniqueObjectId; - - SSkinningData* m_pSkinningData; - - float m_fTempVars[10]; // Different useful vars (ObjVal component in shaders) - - // using a pointer, the client code has to ensure that the data stays valid - const AZStd::vector* m_pShaderParams; - - uint32 m_nHUDSilhouetteParams; - - uint64 m_nSubObjHideMask; - - - uint16 m_FogVolumeContribIdx[2]; - - uint16 m_nLightID; - uint16 m_LightVolumeId; - - uint8 m_screenBounds[4]; - - uint16 m_nCustomFlags; - uint8 m_nCustomData; - - SRenderObjData() - { - Init(); - } - - void Init() - { - m_nSubObjHideMask = 0; - m_uniqueObjectId = 0; - m_nLightID = 0; - m_LightVolumeId = 0; - m_pSkinningData = NULL; - m_screenBounds[0] = m_screenBounds[1] = m_screenBounds[2] = m_screenBounds[3] = 0; - m_nCustomData = 0; - m_nCustomFlags = 0; - m_nHUDSilhouetteParams = 0; - - m_pShaderParams = nullptr; - m_FogVolumeContribIdx[0] = m_FogVolumeContribIdx[1] = static_cast(-1); - - // The following should be changed to be something like 0xac to indicate invalid data so that by default - // data that was not set will break render features and will be traced (otherwise, default 0 just might pass) - memset(m_fTempVars, 0, 10 * sizeof(float)); - } - - void SetShaderParams(const AZStd::vector* pShaderParams) - { - m_pShaderParams = pShaderParams; - } - - void GetMemoryUsage(ICrySizer* pSizer) const - { - AZ_UNUSED(pSizer); - } -}; - -////////////////////////////////////////////////////////////////////// -// Objects using in shader pipeline - - -// Summary: -// Same as in the 3dEngine. -#define MAX_LIGHTS_NUM 32 - -struct ShadowMapFrustum; - -////////////////////////////////////////////////////////////////////// -/// -/// Objects using in shader pipeline -/// Single rendering item, that can be created from 3DEngine and persist across multiple frames -/// It can be compiled into the platform specific efficient rendering compiled object. -/// -////////////////////////////////////////////////////////////////////// -class alignas(16) CRenderObject -{ -public: - AZ_CLASS_ALLOCATOR(CRenderObject, AZ::LegacyAllocator, 0); - - struct SInstanceInfo - { - Matrix34 m_Matrix; - ColorF m_AmbColor; - }; - - struct SInstanceData - { - Matrix34 m_MatInst; - Vec4 m_vBendInfo; - Vec4 m_vDissolveInfo; - }; - - struct PerInstanceConstantBufferKey - { - PerInstanceConstantBufferKey() - : m_Id{0xFFFF} - , m_IndirectId{0xFF} - {} - - bool IsValid() const - { - return m_Id != 0xFFFF; - } - - AZ::u16 m_Id; - AZ::u8 m_IndirectId; - }; - - ////////////////////////////////////////////////////////////////////////// - SInstanceInfo m_II; //!< Per instance data - - uint64 m_ObjFlags; //!< Combination of FOB_ flags. - uint32 m_Id; - - float m_fAlpha; //!< Object alpha. - float m_fDistance; //!< Distance to the object. - - union - { - float m_fSort; //!< Custom sort value. - uint16 m_nSort; - }; - - uint64 m_nRTMask; //!< Shader runtime modification flags - uint16 m_nMDV; //!< Vertex modifier flags for Shader. - uint16 m_nRenderQuality; //!< 65535 - full quality, 0 - lowest quality, used by CStatObj - int16 m_nTextureID; //!< Custom texture id. - - union - { - uint8 m_breakableGlassSubFragIndex; - uint8 m_ParticleObjFlags; - }; - uint8 m_nClipVolumeStencilRef; //!< Per instance vis area stencil reference ID - uint8 m_DissolveRef; //!< Dissolve value - uint8 m_RState; //!< Render state used for object - - bool m_NoDecalReceiver; - - uint32 m_nMaterialLayers; //!< Which mtl layers active and how much to blend them - - - _smart_ptr m_pCurrMaterial; //!< Parent material used for render object. - - - PerInstanceConstantBufferKey m_PerInstanceConstantBufferKey; - - [[maybe_unused]] int m_padding[1]; // padding to avoid MSVC warning 4324 - - //! Embedded SRenderObjData, optional data carried by CRenderObject - SRenderObjData m_data; - -public: - - ////////////////////////////////////////////////////////////////////////// - // Methods - ////////////////////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////////////////////////////// - /// Constructor - ////////////////////////////////////////////////////////////////////////// - CRenderObject() - : m_Id(~0u) - { - Init(); - } - ~CRenderObject() {} - - //========================================================================================================= - - Vec3 GetTranslation() const { return m_II.m_Matrix.GetTranslation(); } - float GetScaleX() const { return sqrt_tpl(m_II.m_Matrix(0, 0) * m_II.m_Matrix(0, 0) + m_II.m_Matrix(0, 1) * m_II.m_Matrix(0, 1) + m_II.m_Matrix(0, 2) * m_II.m_Matrix(0, 2)); } - float GetScaleZ() const { return sqrt_tpl(m_II.m_Matrix(2, 0) * m_II.m_Matrix(2, 0) + m_II.m_Matrix(2, 1) * m_II.m_Matrix(2, 1) + m_II.m_Matrix(2, 2) * m_II.m_Matrix(2, 2)); } - - void Init() - { - m_ObjFlags = 0; - m_nRenderQuality = 65535; - - m_RState = 0; - m_fDistance = 0.0f; - - m_nClipVolumeStencilRef = 0; - m_nMaterialLayers = 0; - m_DissolveRef = 0; - - m_nMDV = 0; - m_fSort = 0; - - m_II.m_AmbColor = Col_White; - m_fAlpha = 1.0f; - m_nTextureID = -1; - m_pCurrMaterial = nullptr; - - m_PerInstanceConstantBufferKey = {}; - - m_nRTMask = 0; - - - m_NoDecalReceiver = false; - m_data.Init(); - } - void AssignId(uint32 id) { m_Id = id; } - - ILINE Matrix34A& GetMatrix() { return m_II.m_Matrix; } - - -protected: - - // Disallow copy (potential bugs with PERMANENT objects) - // alwasy use IRendeer::EF_DuplicateRO if you want a copy - // of a CRenderObject - CRenderObject& operator= (CRenderObject& other) = default; - - void CloneObject(CRenderObject* srcObj) - { - *this = *srcObj; - } - - friend class CRenderer; -}; - -enum EResClassName -{ - eRCN_Texture, - eRCN_Shader, -}; - -// className: CTexture, CHWShader_VS, CHWShader_PS, CShader -struct SResourceAsync -{ - AZ_CLASS_ALLOCATOR(SResourceAsync, AZ::SystemAllocator, 0); - int nReady; // 0: Not ready; 1: Ready; -1: Error - int8* pData; - EResClassName eClassName; // Resource class name - char* Name; // Resource name - union - { - // CTexture parameters - struct - { - int nWidth, nHeight, nMips, nTexFlags, nFormat, nTexId; - }; - // CShader parameters - struct - { - int nShaderFlags; - }; - }; - void* pResource; // Pointer to created resource - - SResourceAsync() - { - memset(this, 0, sizeof(SResourceAsync)); - } - - ~SResourceAsync() - { - delete Name; - } -}; - -#include "IRenderer.h" - -//============================================================================== - -// Summary: -// Color operations flags. -enum EColorOp -{ - eCO_NOSET = 0, - eCO_DISABLE = 1, - eCO_REPLACE = 2, - eCO_DECAL = 3, - eCO_ARG2 = 4, - eCO_MODULATE = 5, - eCO_MODULATE2X = 6, - eCO_MODULATE4X = 7, - eCO_BLENDDIFFUSEALPHA = 8, - eCO_BLENDTEXTUREALPHA = 9, - eCO_DETAIL = 10, - eCO_ADD = 11, - eCO_ADDSIGNED = 12, - eCO_ADDSIGNED2X = 13, - eCO_MULTIPLYADD = 14, - eCO_BUMPENVMAP = 15, - eCO_BLEND = 16, - eCO_MODULATEALPHA_ADDCOLOR = 17, - eCO_MODULATECOLOR_ADDALPHA = 18, - eCO_MODULATEINVALPHA_ADDCOLOR = 19, - eCO_MODULATEINVCOLOR_ADDALPHA = 20, - eCO_DOTPRODUCT3 = 21, - eCO_LERP = 22, - eCO_SUBTRACT = 23, - eCO_MODULATE_METAL_FONT_SPECIAL_MODE = 24, -}; - -enum EColorArg -{ - eCA_Unknown, - eCA_Specular, - eCA_Texture, - eCA_Texture1, - eCA_Normal, - eCA_Diffuse, - eCA_Previous, - eCA_Constant, -}; - -#define DEF_TEXARG0 (eCA_Texture | (eCA_Diffuse << 3)) -#define DEF_TEXARG1 (eCA_Texture | (eCA_Previous << 3)) - -enum ETexModRotateType -{ - ETMR_NoChange, - ETMR_Fixed, - ETMR_Constant, - ETMR_Oscillated, - ETMR_Max -}; - -enum ETexModMoveType -{ - ETMM_NoChange, - ETMM_Fixed, - ETMM_Constant, - ETMM_Jitter, - ETMM_Pan, - ETMM_Stretch, - ETMM_StretchRepeat, - ETMM_Max -}; - -enum ETexGenType -{ - ETG_Stream, - ETG_World, - ETG_Camera, - ETG_Max -}; - - - - -////////////////////////////////////////////////////////////////////// -#define FILTER_NONE -1 -#define FILTER_POINT 0 -#define FILTER_LINEAR 1 -#define FILTER_BILINEAR 2 -#define FILTER_TRILINEAR 3 -#define FILTER_ANISO2X 4 -#define FILTER_ANISO4X 5 -#define FILTER_ANISO8X 6 -#define FILTER_ANISO16X 7 - -////////////////////////////////////////////////////////////////////// -#define TADDR_WRAP 0 -#define TADDR_CLAMP 1 -#define TADDR_MIRROR 2 -#define TADDR_BORDER 3 - - -struct IRenderTarget -{ - virtual ~IRenderTarget(){} - virtual void Release() = 0; - virtual void AddRef() = 0; -}; - - struct IRenderShaderResources { - // - virtual void AddRef() = 0; virtual void UpdateConstants(IShader* pSH) = 0; - virtual void CloneConstants(const IRenderShaderResources* pSrc) = 0; - virtual bool HasLMConstants() const = 0; - // properties - - virtual ColorF GetColorValue(EEfResTextures slot) const = 0; virtual void SetColorValue(EEfResTextures slot, const ColorF& color) = 0; - - virtual float GetStrengthValue(EEfResTextures slot) const = 0; virtual void SetStrengthValue(EEfResTextures slot, float value) = 0; - - // configs - virtual const float& GetAlphaRef() const = 0; - virtual void SetAlphaRef(float v) = 0; - - virtual int GetResFlags() = 0; - virtual void SetMtlLayerNoDrawFlags(uint8 nFlags) = 0; - virtual uint8 GetMtlLayerNoDrawFlags() const = 0; - virtual SSkyInfo* GetSkyInfo() = 0; - virtual void SetMaterialName(const char* szName) = 0; - - virtual AZStd::vector& GetParameters() = 0; - - virtual ColorF GetFinalEmittance() = 0; - virtual float GetVoxelCoverage() = 0; - - virtual ~IRenderShaderResources() {} - virtual void Release() = 0; - virtual void ConvertToInputResource(struct SInputShaderResources* pDst) = 0; - virtual IRenderShaderResources* Clone() const = 0; - virtual void SetShaderParams(struct SInputShaderResources* pDst, IShader* pSH) = 0; - - virtual size_t GetResourceMemoryUsage(ICrySizer* pSizer) = 0; - - virtual void GetMemoryUsage(ICrySizer* pSizer) const = 0; - // - - bool IsEmissive() const - { - // worst: *reinterpret_cast(&) > 0x00000000 - // causes value to pass from FPU to CPU registers - return GetStrengthValue(EFTT_EMITTANCE) > 0.0f; - } - - bool IsTransparent() const - { - // worst: *reinterpret_cast(&) < 0x3f800000 - // causes value to pass from FPU to CPU registers - return GetStrengthValue(EFTT_OPACITY) < 1.0f; - } - - bool IsAlphaTested() const - { - return GetAlphaRef() > 0.0f; - } - - bool IsInvisible() const - { - const float o = GetStrengthValue(EFTT_OPACITY); - const float a = GetAlphaRef(); - - return o == 0.0f || a == 1.0f || o <= a; - } -}; - - -//=================================================================================== -// Shader gen structure (used for automatic shader script generating). - -// -#define SHGF_HIDDEN 1 -#define SHGF_PRECACHE 2 -#define SHGF_AUTO_PRECACHE 4 -#define SHGF_LOWSPEC_AUTO_PRECACHE 8 -#define SHGF_RUNTIME 0x10 - -#define SHGD_LM_DIFFUSE 0x1 -#define SHGD_TEX_DETAIL 0x2 -#define SHGD_TEX_NORMALS 0x4 -#define SHGD_TEX_ENVCM 0x8 -#define SHGD_TEX_SPECULAR 0x10 -#define SHGD_TEX_SECOND_SMOOTHNESS 0x20 -#define SHGD_TEX_HEIGHT 0x40 -#define SHGD_TEX_SUBSURFACE 0x80 -#define SHGD_HW_BILINEARFP16 0x100 -#define SHGD_HW_SEPARATEFP16 0x200 -#define SHGD_HW_ORBIS 0x800 -#define SHGD_TEX_CUSTOM 0x1000 -#define SHGD_TEX_CUSTOM_SECONDARY 0x2000 -#define SHGD_TEX_DECAL 0x4000 -#define SHGD_TEX_OCC 0x8000 -#define SHGD_TEX_SPECULAR_2 0x10000 -#define SHGD_HW_GLES3 0x20000 -#define SHGD_USER_ENABLED 0x40000 -#define SHGD_HW_SAA 0x80000 -#define SHGD_TEX_EMITTANCE 0x100000 -#define SHGD_HW_DX10 0x200000 -#define SHGD_HW_DX11 0x400000 -#define SHGD_HW_GL4 0x800000 -#define SHGD_HW_WATER_TESSELLATION 0x1000000 -#define SHGD_HW_SILHOUETTE_POM 0x2000000 -// Confetti Nicholas Baldwin: adding metal shader language support -#define SHGD_HW_METAL 0x4000000 -#define SHGD_TEX_MASK ( SHGD_TEX_DETAIL | SHGD_TEX_NORMALS | SHGD_TEX_ENVCM | SHGD_TEX_SPECULAR | SHGD_TEX_SECOND_SMOOTHNESS | \ - SHGD_TEX_HEIGHT | SHGD_TEX_SUBSURFACE | SHGD_TEX_CUSTOM | SHGD_TEX_CUSTOM_SECONDARY | SHGD_TEX_DECAL | \ - SHGD_TEX_OCC | SHGD_TEX_SPECULAR_2 | SHGD_TEX_EMITTANCE) - - -//=================================================================================== - -enum EShaderType -{ - eST_All = -1, // To set all with one call. - - eST_General = 0, - eST_Metal, - eST_Glass, - eST_Ice, - eST_Shadow, - eST_Water, - eST_FX, - eST_PostProcess, - eST_HDR, - eST_Sky, - eST_Compute, - eST_Max // To define array size. -}; - -enum EShaderDrawType -{ - eSHDT_General, - eSHDT_Light, - eSHDT_Shadow, - eSHDT_Terrain, - eSHDT_Overlay, - eSHDT_OceanShore, - eSHDT_Fur, - eSHDT_NoDraw, - eSHDT_CustomDraw, - eSHDT_Sky, - eSHDT_Volume -}; - -enum EShaderQuality -{ - eSQ_Low = 0, - eSQ_Medium = 1, - eSQ_High = 2, - eSQ_VeryHigh = 3, - eSQ_Max = 4 -}; - -enum ERenderQuality -{ - eRQ_Low = 0, - eRQ_Medium = 1, - eRQ_High = 2, - eRQ_VeryHigh = 3, - eRQ_Max = 4 -}; - - -//==================================================================================== -// Phys. material flags - -#define MATF_NOCLIP 1 - -//==================================================================================== -// Registered shader techniques ID's - -enum EShaderTechniqueID -{ - TTYPE_GENERAL = -1, - TTYPE_Z = 0, - TTYPE_SHADOWGEN, - TTYPE_GLOWPASS, - TTYPE_MOTIONBLURPASS, - TTYPE_CUSTOMRENDERPASS, - TTYPE_EFFECTLAYER, - TTYPE_SOFTALPHATESTPASS, - TTYPE_WATERREFLPASS, - TTYPE_WATERCAUSTICPASS, - TTYPE_ZPREPASS, - TTYPE_PARTICLESTHICKNESSPASS, - - // PC specific techniques must go after this point, to support shader serializing - // TTYPE_CONSOLE_MAX must equal TTYPE_MAX for console - TTYPE_CONSOLE_MAX, - TTYPE_DEBUG = TTYPE_CONSOLE_MAX, - - TTYPE_MAX -}; - - -//================================================================ -// Different preprocess flags for shaders that require preprocessing (like recursive render to texture, screen effects, visibility check, ...) -// SShader->m_nPreprocess flags in priority order - -#define SPRID_FIRST 25 -#define SPRID_SCANTEXWATER 26 -#define FSPR_SCANTEXWATER (1 << SPRID_SCANTEXWATER) -#define SPRID_SCANTEX 27 -#define FSPR_SCANTEX (1 << SPRID_SCANTEX) -#define SPRID_SCANLCM 28 -#define FSPR_SCANLCM (1 << SPRID_SCANLCM) -#define SPRID_GENSPRITES_DEPRECATED 29 -#define FSPR_GENSPRITES_DEPRECATED (1 << SPRID_GENSPRITES_DEPRECATED) -#define SPRID_CUSTOMTEXTURE 30 -#define FSPR_CUSTOMTEXTURE (1 << SPRID_CUSTOMTEXTURE) -#define SPRID_GENCLOUDS 31 -#define FSPR_GENCLOUDS (1 << SPRID_GENCLOUDS) - -#define FSPR_MASK 0xfff00000 -#define FSPR_MAX (1 << 31) - -#define FEF_DONTSETTEXTURES 1 // Set: explicit setting of samplers (e.g. tex->Apply(1,nTexStatePoint)), not set: set sampler by sematics (e.g. $ZTarget). -#define FEF_DONTSETSTATES 2 - -// SShader::m_Flags -// Different useful flags -#define EF_RELOAD 1 // Shader needs tangent vectors array. -#define EF_FORCE_RELOAD 2 -#define EF_RELOADED 4 -#define EF_NODRAW 8 -#define EF_HASCULL 0x10 -#define EF_SUPPORTSDEFERREDSHADING_MIXED 0x20 -#define EF_SUPPORTSDEFERREDSHADING_FULL 0x40 -#define EF_SUPPORTSDEFERREDSHADING (EF_SUPPORTSDEFERREDSHADING_MIXED | EF_SUPPORTSDEFERREDSHADING_FULL) -#define EF_DECAL 0x80 -#define EF_LOADED 0x100 -#define EF_LOCALCONSTANTS 0x200 -#define EF_BUILD_TREE 0x400 -#define EF_LIGHTSTYLE 0x800 -#define EF_NOCHUNKMERGING 0x1000 -#define EF_SUNFLARES 0x2000 -#define EF_NEEDNORMALS 0x4000 // Need normals operations. -#define EF_OFFSETBUMP 0x8000 -#define EF_NOTFOUND 0x10000 -#define EF_DEFAULT 0x20000 -#define EF_SKY 0x40000 -#define EF_USELIGHTS 0x80000 -#define EF_ALLOW3DC 0x100000 -#define EF_FOGSHADER 0x200000 -#define EF_FAILED_IMPORT 0x400000 // Currently just for debug, can be removed if necessary -#define EF_PRECACHESHADER 0x800000 -#define EF_FORCEREFRACTIONUPDATE 0x1000000 -#define EF_SUPPORTSINSTANCING_CONST 0x2000000 -#define EF_SUPPORTSINSTANCING_ATTR 0x4000000 -#define EF_SUPPORTSINSTANCING (EF_SUPPORTSINSTANCING_CONST | EF_SUPPORTSINSTANCING_ATTR) -#define EF_WATERPARTICLE 0x8000000 -#define EF_CLIENTEFFECT 0x10000000 -#define EF_SYSTEM 0x20000000 -#define EF_REFRACTIVE 0x40000000 -#define EF_NOPREVIEW 0x80000000 - -#define EF_PARSE_MASK (EF_SUPPORTSINSTANCING | EF_SKY | EF_HASCULL | EF_USELIGHTS | EF_REFRACTIVE) - - -// SShader::Flags2 -// Additional Different useful flags - -#define EF2_PREPR_GENSPRITES_DEPRECATED 0x1 -#define EF2_PREPR_GENCLOUDS 0x2 -#define EF2_PREPR_SCANWATER 0x4 -#define EF2_NOCASTSHADOWS 0x8 -#define EF2_NODRAW 0x10 -#define EF2_HASOPAQUE 0x40 -#define EF2_AFTERHDRPOSTPROCESS 0x80 -#define EF2_DONTSORTBYDIST 0x100 -#define EF2_FORCE_WATERPASS 0x200 -#define EF2_FORCE_GENERALPASS 0x400 -#define EF2_AFTERPOSTPROCESS 0x800 -#define EF2_IGNORERESOURCESTATES 0x1000 -#define EF2_EYE_OVERLAY 0x2000 -#define EF2_FORCE_TRANSPASS 0x4000 -#define EF2_DEFAULTVERTEXFORMAT 0x8000 -#define EF2_FORCE_ZPASS 0x10000 -#define EF2_FORCE_DRAWLAST 0x20000 -#define EF2_FORCE_DRAWAFTERWATER 0x40000 -// free 0x80000 -#define EF2_DEPTH_FIXUP 0x100000 -#define EF2_SINGLELIGHTPASS 0x200000 -#define EF2_FORCE_DRAWFIRST 0x400000 -#define EF2_HAIR 0x800000 -#define EF2_DETAILBUMPMAPPING 0x1000000 -#define EF2_HASALPHATEST 0x2000000 -#define EF2_HASALPHABLEND 0x4000000 -#define EF2_ZPREPASS 0x8000000 -#define EF2_VERTEXCOLORS 0x10000000 -#define EF2_SKINPASS 0x20000000 -#define EF2_HW_TESSELLATION 0x40000000 -#define EF2_ALPHABLENDSHADOWS 0x80000000 - -class CCryNameR; -class CCryNameTSCRC; -struct IShader -{ -public: - // - virtual ~IShader(){} - virtual int GetID() = 0; - virtual int AddRef() = 0; - virtual int Release() = 0; - virtual int ReleaseForce() = 0; - - virtual const char* GetName() = 0; - virtual const char* GetName() const = 0; - virtual int GetFlags() const = 0; - virtual int GetFlags2() const = 0; - virtual void SetFlags2(int Flags) = 0; - virtual void ClearFlags2(int Flags) = 0; - virtual bool Reload(int nFlags, const char* szShaderName) = 0; - - virtual int GetTexId () = 0; - - virtual ECull GetCull(void) = 0; - virtual int Size(int Flags) = 0; - - virtual int GetTechniqueID(int nTechnique, int nRegisteredTechnique) = 0; - virtual AZ::Vertex::Format GetVertexFormat(void) = 0; - - - virtual EShaderType GetShaderType() = 0; - virtual EShaderDrawType GetShaderDrawType() const = 0; - virtual uint32 GetVertexModificator() = 0; - - virtual void GetMemoryUsage(ICrySizer* pSizer) const = 0; - // - - static uint32 GetTextureSlot(EEfResTextures textureType) { return (uint32)textureType; } }; struct SShaderItem @@ -1203,72 +91,11 @@ struct SShaderItem int32 m_nTechnique; uint32 m_nPreprocessFlags; - SShaderItem() - { - m_pShader = NULL; - m_pShaderResources = NULL; - m_nTechnique = -1; - m_nPreprocessFlags = 1; - } - SShaderItem(IShader* pSH) - { - m_pShader = pSH; - m_pShaderResources = NULL; - m_nTechnique = -1; - m_nPreprocessFlags = 1; - } - SShaderItem(IShader* pSH, IRenderShaderResources* pRS) - { - m_pShader = pSH; - m_pShaderResources = pRS; - m_nTechnique = -1; - m_nPreprocessFlags = 1; - } - SShaderItem(IShader* pSH, IRenderShaderResources* pRS, int nTechnique) - { - m_pShader = pSH; - m_pShaderResources = pRS; - m_nTechnique = nTechnique; - m_nPreprocessFlags = 1; - } - - uint32 PostLoad(); bool Update(); bool RefreshResourceConstants(); - // Note: - // If you change this function please check bTransparent variable in CRenderMesh::Render(). - // See also: - // CRenderMesh::Render() - bool IsZWrite() const - { - IShader* pSH = m_pShader; - if (pSH->GetFlags() & (EF_NODRAW | EF_DECAL)) - { - return false; - } - if (pSH->GetFlags2() & EF2_FORCE_ZPASS) - { - return true; - } - if (m_pShaderResources && m_pShaderResources->IsTransparent()) - { - return false; - } - return true; - } inline struct SShaderTechnique* GetTechnique() const; - bool IsMergable(SShaderItem& PrevSI); - - void GetMemoryUsage(ICrySizer* pSizer) const - { - pSizer->AddObject(m_pShader); - pSizer->AddObject(m_pShaderResources); - } }; - -#include // <> required for Interfuscator - struct IAnimNode; struct ILightAnimWrapper @@ -1289,30 +116,3 @@ protected: IAnimNode* m_pNode; }; - -#define MAX_RECURSION_LEVELS 2 - -#define DECAL_HAS_NORMAL_MAP (1 << 0) -#define DECAL_STATIC (1 << 1) -#define DECAL_HAS_SPECULAR_MAP (1 << 2) - - -// Summary: -// Runtime shader flags for HW skinning. -enum EHWSkinningRuntimeFlags -{ - eHWS_MotionBlured = 0x04, - eHWS_Skinning_DQ_Linear = 0x08, // Convert dual-quaternions to matrices on the GPU - eHWS_Skinning_Matrix = 0x10, // Pass float3x4 skinning matrices directly to the GPU -}; - -// Enum of data types that can be used as bones on GPU for skinning -enum EBoneTypes -{ - eBoneType_DualQuat = 0, - eBoneType_Matrix, - eBoneType_Count, -}; - - -#include diff --git a/Code/Legacy/CryCommon/ISplines.h b/Code/Legacy/CryCommon/ISplines.h index ff67ae0d56..a1c5c674b0 100644 --- a/Code/Legacy/CryCommon/ISplines.h +++ b/Code/Legacy/CryCommon/ISplines.h @@ -12,6 +12,7 @@ #pragma once #include +#include ////////////////////////////////////////////////////////////////////////// diff --git a/Code/Legacy/CryCommon/IStatObj.h b/Code/Legacy/CryCommon/IStatObj.h index a268f40406..b2cde275c5 100644 --- a/Code/Legacy/CryCommon/IStatObj.h +++ b/Code/Legacy/CryCommon/IStatObj.h @@ -11,7 +11,6 @@ #include "smartptr.h" // TYPEDEF_AUTOPTR #include "IMaterial.h" -#include "ISerialize.h" // forward declarations ////////////////////////////////////////////////////////////////////// @@ -35,15 +34,12 @@ struct phys_geometry; struct IChunkFile; // General forward declaration. -class CRenderObject; struct SMeshLodInfo; -#include "CryHeaders.h" #include "Cry_Color.h" #include "Cry_Math.h" #include "Cry_Geo.h" #include "CrySizer.h" -#include "stridedptr.h" #define MAX_STATOBJ_LODS_NUM 6 @@ -150,70 +146,6 @@ enum EFileStreamingStatus ecss_Ready }; -// Interface for streaming of objects like CStatObj. -struct IStreamable -{ - struct SInstancePriorityInfo - { - int nRoundId; - float fMaxImportance; - }; - - IStreamable() - { - ZeroStruct(m_arrUpdateStreamingPrioriryRoundInfo); - m_eStreamingStatus = ecss_NotLoaded; - fCurImportance = 0; - m_nSelectedFrameId = 0; - m_nStatsInUse = 0; - } - - bool UpdateStreamingPrioriryLowLevel(float fImportance, int nRoundId, bool bFullUpdate) - { - bool bRegister = false; - - if (m_arrUpdateStreamingPrioriryRoundInfo[0].nRoundId != nRoundId) - { - if (!m_arrUpdateStreamingPrioriryRoundInfo[0].nRoundId) - { - bRegister = true; - } - - m_arrUpdateStreamingPrioriryRoundInfo[1] = m_arrUpdateStreamingPrioriryRoundInfo[0]; - - m_arrUpdateStreamingPrioriryRoundInfo[0].nRoundId = nRoundId; - m_arrUpdateStreamingPrioriryRoundInfo[0].fMaxImportance = fImportance; - } - else - { - m_arrUpdateStreamingPrioriryRoundInfo[0].fMaxImportance = max(m_arrUpdateStreamingPrioriryRoundInfo[0].fMaxImportance, fImportance); - } - - if (bFullUpdate) - { - m_arrUpdateStreamingPrioriryRoundInfo[1] = m_arrUpdateStreamingPrioriryRoundInfo[0]; - m_arrUpdateStreamingPrioriryRoundInfo[1].nRoundId--; - } - - return bRegister; - } - - // - virtual ~IStreamable(){} - virtual void StartStreaming(bool bFinishNow, IReadStream_AutoPtr* ppStream) = 0; - virtual int GetStreamableContentMemoryUsage(bool bJustForDebug = false) = 0; - virtual void ReleaseStreamableContent() = 0; - virtual void GetStreamableName(AZStd::string& sName) = 0; - virtual uint32 GetLastDrawMainFrameId() = 0; - virtual bool IsUnloadable() const = 0; - - SInstancePriorityInfo m_arrUpdateStreamingPrioriryRoundInfo[2]; - float fCurImportance; - EFileStreamingStatus m_eStreamingStatus; - uint32 m_nSelectedFrameId : 31; - uint32 m_nStatsInUse : 1; -}; - struct SMeshBoneMapping_uint8; struct SSpine; struct SMeshColor; @@ -221,7 +153,6 @@ struct SMeshColor; // Summary: // Interface to hold static object data struct IStatObj - : public IStreamable { //! Loading flags enum ELoadingFlags @@ -262,50 +193,6 @@ struct IStatObj }; ////////////////////////////////////////////////////////////////////////// - // Statistics information about this object. - struct SStatistics - { - int nVertices; - int nVerticesPerLod[MAX_STATOBJ_LODS_NUM]; - int nIndices; - int nIndicesPerLod[MAX_STATOBJ_LODS_NUM]; - int nMeshSize; - int nMeshSizeLoaded; - int nPhysProxySize; - int nPhysProxySizeMax; - int nPhysPrimitives; - int nDrawCalls; - int nLods; - int nSubMeshCount; - int nNumRefs; - bool bSplitLods; // Lods split between files. - - // Optional texture sizer. - ICrySizer* pTextureSizer; - ICrySizer* pTextureSizer2; - - SStatistics() { Reset(); } - - void Reset() - { - pTextureSizer = NULL; - pTextureSizer2 = NULL; - nVertices = 0; - nIndices = 0; - nMeshSize = 0; - nMeshSizeLoaded = 0; - nNumRefs = 0; - nPhysProxySize = 0; - nPhysPrimitives = 0; - nDrawCalls = 0; - nLods = 0; - nSubMeshCount = 0; - bSplitLods = false; - ZeroStruct(nVerticesPerLod); - ZeroStruct(nIndicesPerLod); - } - }; - // // Description: // Increase the reference count of the object. @@ -337,10 +224,6 @@ struct IStatObj // Retrieves the internal flag m_nVehicleOnlyPhysics. virtual unsigned int GetVehicleOnlyPhysics() = 0; - // Description: - // Retrieves the internal flag m_nIdMaterialBreakable. - virtual int GetIDMatBreakable() = 0; - // Description: // Retrieves the internal flag m_bBreakableByGame. virtual unsigned int GetBreakableByGame() = 0; @@ -364,34 +247,6 @@ struct IStatObj //! Access to rendering geometry for indoor engine ( optimized vert arrays, lists of shader pointers ) virtual struct IRenderMesh* GetRenderMesh() = 0; - // Description: - // Returns the physical representation of the object. - // Arguments: - // nType - one of PHYS_GEOM_TYPE_'s, or an explicit slot index - // Return Value: - // A pointer to a phys_geometry structure. - // Summary: - // Get the physic representation - virtual phys_geometry* GetPhysGeom(int nType = PHYS_GEOM_TYPE_DEFAULT) = 0; - - // Description: - // Updates rendermesh's vertices, normals, and tangents with the data provided - // Summary: - // Updates vertices in the range [iVtx0..iVtx0+nVtx-1], vertices are in their original order - // (as they are physicalized). Clones the object if necessary to make the modifications - // Return Value: - // modified IStatObj (a clone or this one, if it's already a clone) - virtual IStatObj* UpdateVertices(strided_pointer pVtx, strided_pointer pNormals, int iVtx0, int nVtx, int* pVtxMap = 0, float rscale = 1.f) = 0; - - // Description: - // Skins rendermesh's vertices based on skeleton vertices - // Summary: - // Skins vertices based on mtxSkelToMesh[pSkelVtx[i]] - // Clones the object if necessary to make the modifications - // Return Value: - // modified IStatObj (a clone or this one, if it's already a clone) - virtual IStatObj* SkinVertices(strided_pointer pSkelVtx, const Matrix34& mtxSkelToMesh) = 0; - // Description: // Sets and replaces the physical representation of the object. // Arguments: @@ -431,18 +286,6 @@ struct IStatObj // Get the minimal bounding box component virtual Vec3 GetBoxMax() = 0; - // Return Value: - // A Vec3 object containing the bounding box center. - // Summary: - // Get the center of bounding box - virtual const Vec3 GetVegCenter() = 0; - - // Arguments: - // Minimum bounding box component - // Summary: - // Set the minimum bounding box component - virtual void SetBBoxMin(const Vec3& vBBoxMin) = 0; - // Arguments: // Minimum bounding box component // Summary: @@ -502,17 +345,9 @@ struct IStatObj virtual int FindNearesLoadedLOD(int nLodIn, bool bSearchUp = false) = 0; virtual int FindHighestLOD(int nBias) = 0; - virtual bool LoadCGF(const char* filename, bool bLod, unsigned long nLoadingFlags, const void* pData, const int nDataSize) = 0; - virtual void DisableStreaming() = 0; - virtual void TryMergeSubObjects(bool bFromStreaming) = 0; - virtual bool IsUnloadable() const = 0; - virtual void SetCanUnload(bool value) = 0; - virtual AZStd::string& GetFileName() = 0; virtual const AZStd::string& GetFileName() const = 0; - virtual const AZStd::string& GetCGFNodeName() const = 0; - // Summary: // Returns the filename of the object // Return Value: @@ -527,25 +362,6 @@ struct IStatObj // None virtual void SetFilePath(const char* szFileName) = 0; - // Summary: - // Returns the name of the geometry - // Return Value: - // A null terminated string which contains the name of the geometry - virtual const char* GetGeoName() = 0; - - // Summary: - // Sets the name of the geometry - virtual void SetGeoName(const char* szGeoName) = 0; - - // Summary: - // Compares if another object is the same - // Arguments: - // szFileName - Filename of the object to compare - // szGeomName - Geometry name of the object to compare (optional) - // Return Value: - // A boolean which equals to true in case both object are the same, or false in the opposite case. - virtual bool IsSameObject(const char* szFileName, const char* szGeomName) = 0; - // Description: // Will return the position of the helper named in the argument. The // helper should have been specified during the exporting process of @@ -679,9 +495,6 @@ struct IStatObj // hides all non-physicalized geometry, clones the object if necessary virtual IStatObj* HideFoliage() = 0; - // serializes the StatObj's mesh into a stream - virtual int Serialize(TSerialize ser) = 0; - // Get object properties as loaded from CGF. virtual const char* GetProperties() = 0; @@ -702,9 +515,6 @@ struct IStatObj // Debug Draw this static object. virtual void DebugDraw(const struct SGeometryDebugDrawInfo& info, float fExtrdueScale = 0.01f) = 0; - // Fill statistics about the level. - virtual void GetStatistics(SStatistics& stats) = 0; - // Returns initial hide mask virtual uint64 GetInitialHideMask() = 0; diff --git a/Code/Legacy/CryCommon/IStereoRenderer.h b/Code/Legacy/CryCommon/IStereoRenderer.h deleted file mode 100644 index 63fba6d214..0000000000 --- a/Code/Legacy/CryCommon/IStereoRenderer.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - -#ifndef __ISTEREORENDERER_H__ -#define __ISTEREORENDERER_H__ - -#pragma once - -#include "StereoRendererBus.h" - -enum EStereoEye -{ - STEREO_EYE_LEFT = 0, - STEREO_EYE_RIGHT = 1, - STEREO_EYE_COUNT -}; - -enum EStereoDevice -{ - STEREO_DEVICE_NONE = 0, - STEREO_DEVICE_FRAMECOMP = 1, - STEREO_DEVICE_HDMI = 2, - STEREO_DEVICE_DRIVER = 3, //!< Nvidia and AMD drivers. - STEREO_DEVICE_DUALHEAD = 4, - STEREO_DEVICE_COUNT, - - STEREO_DEVICE_DEFAULT = 100 //!< Auto-detect device. -}; - -enum EStereoMode -{ - STEREO_MODE_NO_STEREO = 0, //!< Stereo disabled. - STEREO_MODE_DUAL_RENDERING = 1, - STEREO_MODE_COUNT, -}; - -enum EStereoOutput -{ - STEREO_OUTPUT_STANDARD = 0, - STEREO_OUTPUT_IZ3D = 1, - STEREO_OUTPUT_CHECKERBOARD = 2, - STEREO_OUTPUT_ABOVE_AND_BELOW = 3, - STEREO_OUTPUT_SIDE_BY_SIDE = 4, - STEREO_OUTPUT_LINE_BY_LINE = 5, - STEREO_OUTPUT_ANAGLYPH = 6, - STEREO_OUTPUT_HMD = 7, - STEREO_OUTPUT_COUNT, -}; - -enum EStereoDeviceState -{ - STEREO_DEVSTATE_OK = 0, - STEREO_DEVSTATE_UNSUPPORTED_DEVICE, - STEREO_DEVSTATE_REQ_1080P, - STEREO_DEVSTATE_REQ_FRAMEPACKED, - STEREO_DEVSTATE_BAD_DRIVER, - STEREO_DEVSTATE_REQ_FULLSCREEN -}; - -class IStereoRenderer - : public AZ::StereoRendererRequestBus::Handler -{ -public: - enum EHmdRender - { - eHR_Eyes = 0, - eHR_Latency - }; - - // - virtual ~IStereoRenderer(){} - - virtual EStereoDevice GetDevice() = 0; - virtual EStereoDeviceState GetDeviceState() = 0; - virtual void GetInfo(EStereoDevice* device, EStereoMode* mode, EStereoOutput* output, EStereoDeviceState* state) const = 0; - - virtual bool GetStereoEnabled() = 0; - virtual float GetStereoStrength() = 0; - virtual float GetMaxSeparationScene(bool half = true) = 0; - virtual float GetZeroParallaxPlaneDist() = 0; - - virtual void OnHmdDeviceChanged() = 0; - - virtual void OnResolutionChanged() {} - - virtual void GetNVControlValues(bool& stereoEnabled, float& stereoStrength) = 0; - // - - enum class Status - { - kRenderingFirstEye, - kRenderingSecondEye, - kIdle ///< Not currently rendering to either eye. - }; - - virtual Status GetStatus() const = 0; -}; - -#endif diff --git a/Code/Legacy/CryCommon/ISystem.h b/Code/Legacy/CryCommon/ISystem.h index 6008c4ae32..722e73c774 100644 --- a/Code/Legacy/CryCommon/ISystem.h +++ b/Code/Legacy/CryCommon/ISystem.h @@ -1095,57 +1095,6 @@ struct ISystem using CrySystemNotificationBus = AZ::EBus; }; -#if defined(USE_DISK_PROFILER) - -struct DiskOperationInfo -{ - DiskOperationInfo() - : m_nSeeksCount(0) - , m_nFileOpenCount(0) - , m_nFileReadCount(0) - , m_dOperationSize(0.) - , m_dOperationTime(0.) {} - int m_nSeeksCount; - int m_nFileOpenCount; - int m_nFileReadCount; - double m_dOperationTime; - double m_dOperationSize; - - DiskOperationInfo& operator -= (const DiskOperationInfo& rv) - { - m_nSeeksCount -= rv.m_nSeeksCount; - m_nFileOpenCount -= rv.m_nFileOpenCount; - m_nFileReadCount -= rv.m_nFileReadCount; - m_dOperationSize -= rv.m_dOperationSize; - m_dOperationTime -= rv.m_dOperationTime; - return *this; - } - - DiskOperationInfo& operator += (const DiskOperationInfo& rv) - { - m_nSeeksCount += rv.m_nSeeksCount; - m_nFileOpenCount += rv.m_nFileOpenCount; - m_nFileReadCount += rv.m_nFileReadCount; - m_dOperationSize += rv.m_dOperationSize; - m_dOperationTime += rv.m_dOperationTime; - return *this; - } - - DiskOperationInfo operator - (const DiskOperationInfo& rv) - { - DiskOperationInfo res(*this); - return res -= rv; - } - - DiskOperationInfo operator + (const DiskOperationInfo& rv) - { - DiskOperationInfo res(*this); - return res += rv; - } -}; - -#endif - ////////////////////////////////////////////////////////////////////////// // CrySystem DLL Exports. ////////////////////////////////////////////////////////////////////////// @@ -1365,9 +1314,6 @@ namespace Detail bool IsConstCVar() const { return true; } void SetOnChangeCallback(ConsoleVarFunc pChangeFunc) { (void)pChangeFunc; } uint64 AddOnChangeFunctor(const SFunctor& pChangeFunctor) { (void)pChangeFunctor; return 0; } - uint64 GetNumberOfOnChangeFunctors() const { return 0; } - const SFunctor& GetOnChangeFunctor([[maybe_unused]] uint64 nFunctorIndex) const { InvalidAccess(); SFunctor* pNull = nullptr; return *pNull; } - bool RemoveOnChangeFunctor([[maybe_unused]] const uint64 nElement) { return true; } ConsoleVarFunc GetOnChangeCallback() const { InvalidAccess(); return NULL; } void GetMemoryUsage([[maybe_unused]] class ICrySizer* pSizer) const {} int GetRealIVal() const { return GetIVal(); } diff --git a/Code/Legacy/CryCommon/ITexture.h b/Code/Legacy/CryCommon/ITexture.h index 170e3b6709..b370005f83 100644 --- a/Code/Legacy/CryCommon/ITexture.h +++ b/Code/Legacy/CryCommon/ITexture.h @@ -5,60 +5,12 @@ * SPDX-License-Identifier: Apache-2.0 OR MIT * */ - - -#ifndef CRYINCLUDE_CRYCOMMON_ITEXTURE_H -#define CRYINCLUDE_CRYCOMMON_ITEXTURE_H #pragma once -#include - -#include "Cry_Math.h" -#include "Cry_Color.h" -#include "Tarray.h" -#include -class CTexture; - -#ifndef COMPILER_SUPPORTS_ENUM_SPECIFICATION -# if defined(_MSC_VER) -# define COMPILER_SUPPORTS_ENUM_SPECIFICATION 1 -# else -# define COMPILER_SUPPORTS_ENUM_SPECIFICATION 0 -# endif -#endif - -#if COMPILER_SUPPORTS_ENUM_SPECIFICATION -enum ETEX_Type : uint8 -#else -typedef uint8 ETEX_Type; -enum eTEX_Type -#endif -{ - eTT_1D = 0, - eTT_2D, - eTT_3D, - eTT_Cube, - eTT_CubeArray, - eTT_Dyn2D, - eTT_User, - eTT_NearestCube, - - eTT_2DArray, - eTT_2DMS, - - eTT_Auto2D, - - eTT_MaxTexType, // not used -}; - +#include // Texture formats -#if COMPILER_SUPPORTS_ENUM_SPECIFICATION -enum ETEX_Format : uint8 -#else -typedef uint8 ETEX_Format; -enum eTEX_Format -#endif +enum ETEX_Format : AZ::u8 { eTF_Unknown = 0, eTF_R8G8B8A8S, @@ -147,277 +99,20 @@ enum eTEX_Format eTF_MaxFormat // unused, must be always the last in the list }; -#if COMPILER_SUPPORTS_ENUM_SPECIFICATION -enum ETEX_TileMode : uint8 -#else -typedef uint8 ETEX_TileMode; -enum eTEX_TileMode -#endif -{ - eTM_None = 0, - eTM_LinearPadded, - eTM_Optimal, -}; - - -enum ETextureFlags -{ - FT_NOMIPS = 0x00000001, - FT_TEX_NORMAL_MAP = 0x00000002, - FT_TEX_WAS_NOT_PRE_TILED = 0x00000004, - FT_USAGE_DEPTHSTENCIL = 0x00000008, - FT_USAGE_ALLOWREADSRGB = 0x00000010, - FT_FILESINGLE = 0x00000020, // suppress loading of additional files like _DDNDIF (faster, RC can tag the file for that) - FT_TEX_FONT = 0x00000040, - FT_HAS_ATTACHED_ALPHA = 0x00000080, - FT_USAGE_UNORDERED_ACCESS = 0x00000100, - FT_USAGE_READBACK = 0x00000200, - FT_USAGE_MSAA = 0x00000400, - FT_FORCE_MIPS = 0x00000800, - FT_USAGE_RENDERTARGET = 0x00001000, - FT_USAGE_DYNAMIC = 0x00002000, - FT_STAGE_READBACK = 0x00004000, - FT_STAGE_UPLOAD = 0x00008000, - FT_DONT_RELEASE = 0x00010000, - FT_ASYNC_PREPARE = 0x00020000, - FT_DONT_STREAM = 0x00040000, -#if defined(AZ_RESTRICTED_PLATFORM) - #include AZ_RESTRICTED_FILE(ITexture_h) -#endif - -#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED) - #undef AZ_RESTRICTED_SECTION_IMPLEMENTED -#else -#if defined(AZ_PLATFORM_IOS) - FT_USAGE_MEMORYLESS = 0x00080000, //reusing an unused bit for ios -#else - FT_USAGE_PREDICATED_TILING = 0x00080000, //unused -#endif -#endif - FT_FAILED = 0x00100000, - FT_FROMIMAGE = 0x00200000, - FT_STATE_CLAMP = 0x00400000, - FT_USAGE_ATLAS = 0x00800000, - FT_ALPHA = 0x01000000, - FT_REPLICATE_TO_ALL_SIDES = 0x02000000, - FT_KEEP_LOWRES_SYSCOPY = 0x04000000, // keep low res copy in system memory for voxelization on CPU - FT_SPLITTED = 0x08000000, // for split dds files - FT_USE_HTILE = 0x10000000, - FT_IGNORE_PRECACHE = 0x20000000, - FT_COMPOSITE = 0x40000000, - FT_USAGE_UAV_RWTEXTURE = 0x80000000, -}; - struct SDepthTexture; -struct STextureStreamingStats -{ - STextureStreamingStats(bool bComputeTexturesPerFrame) - : bComputeReuquiredTexturesPerFrame(bComputeTexturesPerFrame) - { - nMaxPoolSize = 0; - nCurrentPoolSize = 0; - nStreamedTexturesSize = 0; - nStaticTexturesSize = 0; - nThroughput = 0; - nNumTexturesPerFrame = 0; - nRequiredStreamedTexturesSize = 0; - nRequiredStreamedTexturesCount = 0; - bPoolOverflow = false; - bPoolOverflowTotally = false; - fPoolFragmentation = 0.0f; - } - size_t nMaxPoolSize; - size_t nCurrentPoolSize; - size_t nStreamedTexturesSize; - size_t nStaticTexturesSize; - uint32 nNumTexturesPerFrame; - size_t nThroughput; - size_t nRequiredStreamedTexturesSize; - uint32 nRequiredStreamedTexturesCount; - float fPoolFragmentation; - uint32 bPoolOverflow : 1; - uint32 bPoolOverflowTotally : 1; - const bool bComputeReuquiredTexturesPerFrame; -}; - - ////////////////////////////////////////////////////////////////////// // Texture object interface -class CDeviceTexture; class ITexture { protected: virtual ~ITexture() {} public: - - // virtual int AddRef() = 0; virtual int Release() = 0; virtual int ReleaseForce() = 0; - virtual const ColorF& GetClearColor() const = 0; - virtual const ETEX_Format GetDstFormat() const = 0; - virtual const ETEX_Format GetSrcFormat() const = 0; - virtual const ETEX_Type GetTexType() const = 0; - virtual void ApplyTexture(int nTUnit, int nState = -1) = 0; virtual const char* GetName() const = 0; - virtual const int GetWidth() const = 0; - virtual const int GetHeight() const = 0; - virtual const int GetDepth() const = 0; - virtual const int GetTextureID() const = 0; - virtual const uint32 GetFlags() const = 0; - virtual const int GetNumMips() const = 0; - virtual const int GetRequiredMip() const = 0; - virtual const int GetDeviceDataSize() const = 0; - virtual const int GetDataSize() const = 0; - virtual const ETEX_Type GetTextureType() const = 0; - // Sets the texture type of the texture to be used before the texture is loaded. - // Once the texture is loaded the type from the file will overwrite whatever - // value was set here. - virtual void SetTextureType(ETEX_Type type) = 0; - virtual const bool IsTextureLoaded() const = 0; - virtual void PrecacheAsynchronously(float fMipFactor, int nFlags, int nUpdateId, int nCounter = 1) = 0; - virtual uint8* GetData32(int nSide = 0, int nLevel = 0, uint8* pDst = NULL, ETEX_Format eDstFormat = eTF_R8G8B8A8) = 0; - virtual bool SetFilter(int nFilter) = 0; // FILTER_ flags - virtual void SetClamp(bool bEnable) = 0; // Texture addressing set - virtual float GetAvgBrightness() const = 0; - - virtual int StreamCalculateMipsSigned(float fMipFactor) const = 0; - virtual int GetStreamableMipNumber() const = 0; - virtual int GetStreamableMemoryUsage(int nStartMip) const = 0; - virtual int GetMinLoadedMip() const = 0; - - using StagingHook = AZStd::function; - virtual void Readback(AZ::u32 subresourceIndex, StagingHook callback) = 0; - - virtual bool Reload() = 0; - // Used for debugging/profiling. - virtual const char* GetFormatName() const = 0; - virtual const char* GetTypeName() const = 0; - virtual const bool IsStreamedVirtual() const = 0; - virtual const bool IsShared() const = 0; - virtual const bool IsStreamable() const = 0; - virtual bool IsStreamedIn(const int nMinPrecacheRoundIds[2]) const = 0; - virtual const int GetAccessFrameId() const = 0; - - virtual const ETEX_Format GetTextureDstFormat() const = 0; - virtual const ETEX_Format GetTextureSrcFormat() const = 0; - - virtual bool IsPostponed() const = 0; - virtual const bool IsParticularMipStreamed(float fMipFactor) const = 0; - - // get low res system memory (used for CPU voxelization) - virtual const ColorB* GetLowResSystemCopy([[maybe_unused]] uint16& nWidth, [[maybe_unused]] uint16& nHeight, [[maybe_unused]] int** ppLowResSystemCopyAtlasId) { return 0; } - - // - - void GetMemoryUsage([[maybe_unused]] ICrySizer* pSizer) const - { - static_assert(eTT_MaxTexType <= 255); - static_assert(eTF_MaxFormat <= 255); - /*LATER*/ - } - - virtual void SetKeepSystemCopy(bool bKeepSystemCopy) = 0; - virtual void UpdateTextureRegion(const uint8_t* data, int nX, int nY, int nZ, int USize, int VSize, int ZSize, ETEX_Format eTFSrc) = 0; - virtual CDeviceTexture* GetDevTexture() const = 0; - -}; - -struct STextureLoadData -{ - void* m_pData; - size_t m_DataSize; - int m_Width; - int m_Height; - ETEX_Format m_Format; - int m_NumMips; - int m_nFlags; - ITexture* m_pTexture; - STextureLoadData() - : m_pData(nullptr) - , m_Width(0) - , m_Height(0) - , m_Format(eTF_Unknown) - , m_NumMips(0) - , m_nFlags(0) - , m_pTexture(nullptr) - { - } - ~STextureLoadData() - { - if (m_pData) - { - CryModuleFree(m_pData); - } - } - - static void* AllocateData(size_t dataSize) - { - return CryModuleMalloc(dataSize); - } -}; -struct ITextureLoadHandler -{ - virtual ~ITextureLoadHandler() {} - virtual bool LoadTextureData(const char* path, STextureLoadData& loadData) = 0; - virtual bool SupportsExtension(const char* ext) const = 0; - virtual void Update() = 0; }; //========================================================================================= - -class IDynTexture -{ -public: - enum - { - fNeedRegenerate = 1ul << 0, - }; - // - virtual ~IDynTexture(){} - virtual void Release() = 0; - virtual void GetSubImageRect(uint32& nX, uint32& nY, uint32& nWidth, uint32& nHeight) = 0; - virtual void GetImageRect(uint32& nX, uint32& nY, uint32& nWidth, uint32& nHeight) = 0; - virtual int GetTextureID() = 0; - virtual void Lock() = 0; - virtual void UnLock() = 0; - virtual int GetWidth() = 0; - virtual int GetHeight() = 0; - virtual bool IsValid() = 0; - virtual uint8 GetFlags() const = 0; - virtual void SetFlags([[maybe_unused]] uint8 flags) {} - virtual bool Update(int nNewWidth, int nNewHeight) = 0; - virtual void Apply(int nTUnit, int nTS = -1) = 0; - virtual bool ClearRT() = 0; - virtual bool SetRT(int nRT, bool bPush, struct SDepthTexture* pDepthSurf, bool bScreenVP = false) = 0; - virtual bool SetRectStates() = 0; - virtual bool RestoreRT(int nRT, bool bPop) = 0; - virtual ITexture* GetTexture() = 0; - virtual void SetUpdateMask() = 0; - virtual void ResetUpdateMask() = 0; - virtual bool IsSecondFrame() = 0; - virtual bool GetImageData32([[maybe_unused]] uint8* pData, [[maybe_unused]] int nDataSize) { return 0; } - // -}; - -// Animating Texture sequence definition -class ITexAnim -{ -public: - virtual ~ITexAnim() {}; - virtual void Release() = 0; - virtual void AddRef() = 0; -}; - -struct AZ_DEPRECATED(STexAnim, "STexAnim has been deprecated and replaced by the abstract interface ITexAnim above and CTexAnim in RenderDLL/Common/Textures/Texture.h. This was done to keep proper ref counting between CryRenderDLL and EditorLib.") {}; - -struct STexComposition -{ - _smart_ptr pTexture; - uint16 nSrcSlice; - uint16 nDstSlice; -}; - -#endif // CRYINCLUDE_CRYCOMMON_ITEXTURE_H diff --git a/Code/Legacy/CryCommon/IViewSystem.h b/Code/Legacy/CryCommon/IViewSystem.h index 583c0982c9..d8514aadf6 100644 --- a/Code/Legacy/CryCommon/IViewSystem.h +++ b/Code/Legacy/CryCommon/IViewSystem.h @@ -9,12 +9,8 @@ // Description : View System interfaces. - -#ifndef CRYINCLUDE_CRYACTION_IVIEWSYSTEM_H -#define CRYINCLUDE_CRYACTION_IVIEWSYSTEM_H #pragma once -#include #include #include @@ -233,7 +229,6 @@ struct IView virtual CCamera& GetCamera() = 0; virtual const CCamera& GetCamera() const = 0; - virtual void Serialize(TSerialize ser) = 0; virtual void PostSerialize() = 0; virtual void SetCurrentParams(SViewParams& params) = 0; virtual const SViewParams* GetCurrentParams() = 0; @@ -281,7 +276,6 @@ struct IViewSystem virtual bool AddListener(IViewSystemListener* pListener) = 0; virtual bool RemoveListener(IViewSystemListener* pListener) = 0; - virtual void Serialize(TSerialize ser) = 0; virtual void PostSerialize() = 0; // Get default distance to near clipping plane. @@ -299,5 +293,3 @@ struct IViewSystem virtual void SetControlAudioListeners(bool const bActive) = 0; virtual void ForceUpdate(float elapsed) = 0; }; - -#endif // CRYINCLUDE_CRYACTION_IVIEWSYSTEM_H diff --git a/Code/Legacy/CryCommon/LyShine/Animation/IUiAnimation.h b/Code/Legacy/CryCommon/LyShine/Animation/IUiAnimation.h index 8d988d0df5..be449bb6ad 100644 --- a/Code/Legacy/CryCommon/LyShine/Animation/IUiAnimation.h +++ b/Code/Legacy/CryCommon/LyShine/Animation/IUiAnimation.h @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include diff --git a/Code/Legacy/CryCommon/LyShine/UiBase.h b/Code/Legacy/CryCommon/LyShine/UiBase.h index af6314be2c..5eef06b94e 100644 --- a/Code/Legacy/CryCommon/LyShine/UiBase.h +++ b/Code/Legacy/CryCommon/LyShine/UiBase.h @@ -12,10 +12,12 @@ #include #include #include +#include #include #include #include +#include // This is a workaround for AZCore including WinUser.h which defines DrawText to be DrawTextA #ifdef DrawText @@ -44,7 +46,7 @@ namespace LyShine typedef AZStd::string StringType; // not yet decided if we should use wchar_t or UTF8 //! Used for passing lists of entities - typedef DynArray EntityArray; + typedef AZStd::vector EntityArray; enum class BlendMode { diff --git a/Code/Legacy/CryCommon/MemoryAccess.h b/Code/Legacy/CryCommon/MemoryAccess.h deleted file mode 100644 index 8343c961a8..0000000000 --- a/Code/Legacy/CryCommon/MemoryAccess.h +++ /dev/null @@ -1,567 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - -// Description : Misc mathematical functions - -#pragma once - - -#include - -// Section dictionary -#if defined(AZ_RESTRICTED_PLATFORM) -#undef AZ_RESTRICTED_SECTION -#define MEMORYACCESS_H_SECTION_TRAITS 1 -#define MEMORYACCESS_H_SECTION_CRYPREFETCH 2 -#endif - -// Traits -#if defined(AZ_RESTRICTED_PLATFORM) - #define AZ_RESTRICTED_SECTION MEMORYACCESS_H_SECTION_TRAITS - #include AZ_RESTRICTED_FILE(MemoryAccess_h) -#else -#define MEMORYACCESS_H_TRAIT_USE_LEGACY_PREFETCHLINE 1 -#endif - -#if MEMORYACCESS_H_TRAIT_USE_LEGACY_PREFETCHLINE -#define PrefetchLine(ptr, off) cryPrefetchT0SSE((void*)((UINT_PTR)ptr + off)) -#else -#define PrefetchLine(ptr, off) (void)(0) -#endif -#define ResetLine128(ptr, off) (void)(0) -#define FlushLine128(ptr, off) (void)(0) - - - -//======================================================================================== - -// cryMemcpy flags -#define MC_CPU_TO_GPU 0x10 -#define MC_GPU_TO_CPU 0x20 -#define MC_CPU_TO_CPU 0x40 - -extern int g_CpuFlags; - -// -#define CPUF_SSE 0x01 -#define CPUF_SSE2 0x02 -#define CPUF_3DNOW 0x04 -#define CPUF_MMX 0x08 -#define CPUF_SSE3 0x10 -#define CPUF_F16C 0x20 -#define CPUF_SSE41 0x40 - -#ifdef _CPU_SSE - -#ifdef _CPU_X86 -#include -#endif - -#define _MM_PREFETCH(MemPtr, Hint) _mm_prefetch((MemPtr), (Hint)); -#define _MM_PREFETCH_LOOP(nCount, MemPtr, Hint) { for (int p = 0; p < nCount; p += 64) { _mm_prefetch((const char*)(MemPtr) + p, Hint); } \ -} -#else //_CPU_SSE -#define _MM_PREFETCH(MemPtr, Hint) -#define _MM_PREFETCH_LOOP(nCount, MemPtr, Hint) -#endif //_CPU_SSE - -void cryMemcpy(void* Dst, const void* Src, int Count); -#if defined(LINUX) || defined(APPLE) -// Define this for Mac and Linux since it is used with the pthread sources - #define mymemcpy16 memcpy -#endif - - -//========================================================================================== -// 3DNow! optimizations - -#if defined _CPU_X86 && !defined(LINUX) && !defined(APPLE) -// *************************************************************************** -inline void cryPrecacheSSE(const void* src, int nbytes) -{ - _asm - { - mov esi, src - mov ecx, nbytes - // 64 bytes per pass - shr ecx, 6 - jz endLabel - -loopMemToL1: - prefetchnta 64[ESI] // Prefetch next loop, non-temporal - prefetchnta 96[ESI] - - movq mm1, 0[ESI]// Read in source data - movq mm2, 8[ESI] - movq mm3, 16[ESI] - movq mm4, 24[ESI] - movq mm5, 32[ESI] - movq mm6, 40[ESI] - movq mm7, 48[ESI] - movq mm0, 56[ESI] - - add esi, 64 - dec ecx - jnz loopMemToL1 - - emms - -endLabel: - } -} - - -#endif - - - -ILINE void cryPrefetchT0SSE(const void* src) -{ -#if defined(WIN32) && !defined(WIN64) - _asm - { - mov esi, src - prefetchT0 [ESI] // Prefetch - } -#else - _MM_PREFETCH((char*)src, _MM_HINT_T0); -#endif -} - -//================================================================================= - -// Very optimized memcpy() routine for AMD Athlon and Duron family. -// This code uses any of FOUR different basic copy methods, depending -// on the transfer size. -// NOTE: Since this code uses MOVNTQ (also known as "Non-Temporal MOV" or -// "Streaming Store"), and also uses the software prefetch instructions, -// be sure you're running on Athlon/Duron or other recent CPU before calling! - -#define TINY_BLOCK_COPY 64 // Upper limit for movsd type copy. -// The smallest copy uses the X86 "movsd" instruction, in an optimized -// form which is an "unrolled loop". - -#define IN_CACHE_COPY 64 * 1024 // Upper limit for movq/movq copy w/SW prefetch. -// Next is a copy that uses the MMX registers to copy 8 bytes at a time, -// also using the "unrolled loop" optimization. This code uses -// the software prefetch instruction to get the data into the cache. - -#define UNCACHED_COPY 197 * 1024 // Upper limit for movq/movntq w/SW prefetch. -// For larger blocks, which will spill beyond the cache, it's faster to -// use the Streaming Store instruction MOVNTQ. This write instruction -// bypasses the cache and writes straight to main memory. This code also -// uses the software prefetch instruction to pre-read the data. -// USE 64 * 1024 FOR THIS VALUE IF YOU'RE ALWAYS FILLING A "CLEAN CACHE". - -#define BLOCK_PREFETCH_COPY infinity // No limit for movq/movntq w/block prefetch. -#define CACHEBLOCK 80h // Number of 64-byte blocks (cache lines) for block prefetch. -// For the largest size blocks, a special technique called Block Prefetch -// can be used to accelerate the read operations. Block Prefetch reads -// one address per cache line, for a series of cache lines, in a short loop. -// This is faster than using software prefetch. The technique is great for -// getting maximum read bandwidth, especially in DDR memory systems. - - -#if defined _CPU_X86 && !defined(LINUX) && !defined(APPLE) -// Inline assembly syntax for use with Visual C++ -inline void cryMemcpy(void* Dst, const void* Src, int Count) -{ - if (g_CpuFlags & CPUF_SSE) - { - __asm - { - mov ecx, [Count]; - number of bytes to copy - mov edi, [Dst]; - destination - mov esi, [Src]; - source - mov ebx, ecx; - keep a copy of count - - cld - cmp ecx, TINY_BLOCK_COPY - jb $memcpy_ic_3; - tiny ? skip mmx copy - - cmp ecx, 32 * 1024; - dont align between 32k - 64k because - jbe $memcpy_do_align; - it appears to be slower - cmp ecx, 64*1024 - jbe $memcpy_align_done - $memcpy_do_align : - mov ecx, 8; - a trick thats faster than rep movsb ... - sub ecx, edi; - align destination to qword - and ecx, 111b; - get the low bits - sub ebx, ecx; - update copy count - neg ecx; - set up to jump into the array - add ecx, offset $memcpy_align_done - jmp ecx; - jump to array of movsbs - - align 4 - movsb - movsb - movsb - movsb - movsb - movsb - movsb - movsb - -$memcpy_align_done:; - destination is dword aligned - mov ecx, ebx; - number of bytes left to copy - shr ecx, 6; - get 64 - byte block count - jz $memcpy_ic_2; - finish the last few bytes - - cmp ecx, IN_CACHE_COPY / 64; - too big 4 cache ? use uncached copy - jae $memcpy_uc_test - - // This is small block copy that uses the MMX registers to copy 8 bytes - // at a time. It uses the "unrolled loop" optimization, and also uses - // the software prefetch instruction to get the data into the cache. - align 16 - $memcpy_ic_1 :; - 64 - byte block copies, in - cache copy - - prefetchnta [esi + (200 * 64 / 34 + 192)]; - start reading ahead - - movq mm0, [esi + 0]; - read 64 bits - movq mm1, [esi + 8] - movq [edi + 0], mm0; - write 64 bits - movq [edi + 8], mm1; -note: the normal movq writes the - movq mm2, [esi + 16]; - data to cache; - a cache line will be - movq mm3, [esi + 24]; - allocated as needed, to store the data - movq [edi + 16], mm2 - movq [edi + 24], mm3 - movq mm0, [esi + 32] - movq mm1, [esi + 40] - movq [edi + 32], mm0 - movq [edi + 40], mm1 - movq mm2, [esi + 48] - movq mm3, [esi + 56] - movq [edi + 48], mm2 - movq [edi + 56], mm3 - - add esi, 64; - update source pointer - add edi, 64; - update destination pointer - dec ecx; - count down - jnz $memcpy_ic_1; - last 64 - byte block ? - - $memcpy_ic_2 : - mov ecx, ebx; - has valid low 6 bits of the byte count -$memcpy_ic_3: - shr ecx, 2; - dword count - and ecx, 1111b; - only look at the "remainder" bits - neg ecx; - set up to jump into the array - add ecx, offset $memcpy_last_few - jmp ecx; - jump to array of movsds - -$memcpy_uc_test: - cmp ecx, UNCACHED_COPY / 64; - big enough ? use block prefetch copy - jae $memcpy_bp_1 - - $memcpy_64_test : - or ecx, ecx; - tail end of block prefetch will jump here - jz $memcpy_ic_2; - no more 64 - byte blocks left - - // For larger blocks, which will spill beyond the cache, it's faster to - // use the Streaming Store instruction MOVNTQ. This write instruction - // bypasses the cache and writes straight to main memory. This code also - // uses the software prefetch instruction to pre-read the data. - align 16 -$memcpy_uc_1:; - 64 - byte blocks, uncached copy - - prefetchnta [esi + (200 * 64 / 34 + 192)]; - start reading ahead - - movq mm0, [esi + 0]; - read 64 bits - add edi, 64; - update destination pointer - movq mm1, [esi + 8] - add esi, 64; - update source pointer - movq mm2, [esi - 48] - movntq [edi - 64], mm0; - write 64 bits, bypassing the cache - movq mm0, [esi - 40]; -note: movntq also prevents the CPU - movntq [edi - 56], mm1; - from READING the destination address - movq mm1, [esi - 32]; - into the cache, only to be over - written - movntq [edi - 48], mm2; - so that also helps performance - movq mm2, [esi - 24] - movntq [edi - 40], mm0 - movq mm0, [esi - 16] - movntq [edi - 32], mm1 - movq mm1, [esi - 8] - movntq [edi - 24], mm2 - movntq [edi - 16], mm0 - dec ecx - movntq [edi - 8], mm1 - jnz $memcpy_uc_1; - last 64 - byte block ? - - jmp $memcpy_ic_2; - almost done - - // For the largest size blocks, a special technique called Block Prefetch - // can be used to accelerate the read operations. Block Prefetch reads - // one address per cache line, for a series of cache lines, in a short loop. - // This is faster than using software prefetch. The technique is great for - // getting maximum read bandwidth, especially in DDR memory systems. - $memcpy_bp_1 :; - large blocks, block prefetch copy - - cmp ecx, CACHEBLOCK; - big enough to run another prefetch loop ? - jl $memcpy_64_test; - no, back to regular uncached copy - - mov eax, CACHEBLOCK / 2; - block prefetch loop, unrolled 2X - add esi, CACHEBLOCK* 64; - move to the top of the block - align 16 - $memcpy_bp_2 : - mov edx, [esi - 64]; - grab one address per cache line - mov edx, [esi - 128]; - grab one address per cache line - sub esi, 128; - go reverse order to suppress HW prefetcher - dec eax; - count down the cache lines - jnz $memcpy_bp_2; - keep grabbing more lines into cache - - mov eax, CACHEBLOCK; - now that its in cache, do - { - the copy - align 16 -$memcpy_bp_3: - movq mm0, [esi ]; - } read 64 bits - movq mm1, [esi + 8] - movq mm2, [esi + 16] - movq mm3, [esi + 24] - movq mm4, [esi + 32] - movq mm5, [esi + 40] - movq mm6, [esi + 48] - movq mm7, [esi + 56] - add esi, 64; - update source pointer - movntq [edi ], mm0; - write 64 bits, bypassing cache - movntq [edi + 8], mm1; -note: movntq also prevents the CPU - movntq [edi + 16], mm2; - from READING the destination address - movntq [edi + 24], mm3; - into the cache, only to be over - written, - movntq [edi + 32], mm4; - so that also helps performance - movntq [edi + 40], mm5 - movntq [edi + 48], mm6 - movntq [edi + 56], mm7 - add edi, 64; - update dest pointer - - dec eax; - count down - - jnz $memcpy_bp_3; - keep copying - sub ecx, CACHEBLOCK; - update the 64 - byte block count - jmp $memcpy_bp_1; - keep processing chunks - - // The smallest copy uses the X86 "movsd" instruction, in an optimized - // form which is an "unrolled loop". Then it handles the last few bytes. - align 4 - movsd - movsd; - perform last 1 - 15 dword copies - movsd - movsd - movsd - movsd - movsd - movsd - movsd - movsd; - perform last 1 - 7 dword copies - movsd - movsd - movsd - movsd - movsd - movsd - -$memcpy_last_few:; - dword aligned from before movsds - mov ecx, ebx; - has valid low 2 bits of the byte count - and ecx, 11b; - the last few cows must come home - jz $memcpy_final; - no more, lets leave - rep movsb; - the last 1, 2, or 3 bytes - -$memcpy_final: - emms; - clean up the MMX state - sfence; - flush the write buffer - // mov eax, [dest] ; ret value = destination pointer - } - } - else - { - memcpy(Dst, Src, Count); - } -} - -inline void cryPrefetch(const void* Src, int nCount) -{ - nCount >>= 6; - if (nCount > 0) - { - _asm - { - mov esi, Src; - mov ecx, nCount; -mPr0: - align 16 - dec ecx; - mov eax, [esi]; - mov eax, 0; - lea esi, [esi + 40h]; - jne mPr0; - } - } - else - { - _asm - { - mov esi, Src; - mov ecx, nCount; -mPr1: - align 16 - inc ecx; - mov eax, [esi]; - mov eax, 0; - lea esi, [esi - 40h]; - jne mPr1; - } - } -} - -inline void cryMemcpy (void* inDst, const void* inSrc, int nCount, int nFlags) -{ - cryMemcpy(inDst, inSrc, nCount); -} - -//========================================================================================== -// SSE optimizations - - -#else - -const int PREFNTA_BLOCK = 0x4000; - -ILINE void cryMemcpy(void* Dst, const void* Src, int n) -{ - char* dst = (char*)Dst; - char* src = (char*)Src; - while (n > PREFNTA_BLOCK) - { - _MM_PREFETCH_LOOP(PREFNTA_BLOCK, src, _MM_HINT_NTA); - - memcpy(dst, src, PREFNTA_BLOCK); - src += PREFNTA_BLOCK; - dst += PREFNTA_BLOCK; - n -= PREFNTA_BLOCK; - } - _MM_PREFETCH_LOOP(n, src, _MM_HINT_NTA); - memcpy(dst, src, n); -} - -ILINE void cryMemcpy(void* Dst, const void* Src, int n, [[maybe_unused]] int nFlags) -{ - char* dst = (char*)Dst; - char* src = (char*)Src; - while (n > PREFNTA_BLOCK) - { - _MM_PREFETCH_LOOP(PREFNTA_BLOCK, src, _MM_HINT_NTA); - memcpy(dst, src, PREFNTA_BLOCK); - src += PREFNTA_BLOCK; - dst += PREFNTA_BLOCK; - n -= PREFNTA_BLOCK; - } - _MM_PREFETCH_LOOP(n, src, _MM_HINT_NTA); - memcpy(dst, src, n); -} - - -#endif - - -#if defined(AZ_RESTRICTED_PLATFORM) - #define AZ_RESTRICTED_SECTION MEMORYACCESS_H_SECTION_CRYPREFETCH - #include AZ_RESTRICTED_FILE(MemoryAccess_h) -#endif -#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED) -#undef AZ_RESTRICTED_SECTION_IMPLEMENTED -#else -//implement something usual to bring one memory location into L1 data cache -ILINE void CryPrefetch(const void* const cpSrc) -{ - cryPrefetchT0SSE(cpSrc); -} -#endif - -#define CryPrefetchInl CryPrefetch diff --git a/Code/Legacy/CryCommon/Mocks/ICVarMock.h b/Code/Legacy/CryCommon/Mocks/ICVarMock.h index 9fad05cc35..08f4471ad1 100644 --- a/Code/Legacy/CryCommon/Mocks/ICVarMock.h +++ b/Code/Legacy/CryCommon/Mocks/ICVarMock.h @@ -36,9 +36,6 @@ public: MOCK_CONST_METHOD0(IsConstCVar, bool()); MOCK_METHOD1(SetOnChangeCallback, void(ConsoleVarFunc)); MOCK_METHOD1(AddOnChangeFunctor, uint64(const SFunctor& pChangeFunctor)); - MOCK_CONST_METHOD0(GetNumberOfOnChangeFunctors, uint64()); - MOCK_CONST_METHOD1(GetOnChangeFunctor, const SFunctor&(uint64)); - MOCK_METHOD1(RemoveOnChangeFunctor, bool(uint64)); MOCK_CONST_METHOD0(GetOnChangeCallback, ConsoleVarFunc()); MOCK_CONST_METHOD1(GetMemoryUsage, void(class ICrySizer* pSizer)); MOCK_CONST_METHOD0(GetRealIVal, int()); diff --git a/Code/Legacy/CryCommon/Mocks/IConsoleMock.h b/Code/Legacy/CryCommon/Mocks/IConsoleMock.h index b416aa5f11..9c947b9c0f 100644 --- a/Code/Legacy/CryCommon/Mocks/IConsoleMock.h +++ b/Code/Legacy/CryCommon/Mocks/IConsoleMock.h @@ -69,13 +69,6 @@ public: MOCK_METHOD1(SetInputLine, void (const char* szLine)); MOCK_METHOD1(DumpKeyBinds, void (IKeyBindDumpSink * pCallback)); MOCK_CONST_METHOD1(FindKeyBind, const char*(const char* sCmd)); - MOCK_METHOD0(GetNumCheatVars, int ()); - MOCK_METHOD2(SetCheatVarHashRange, void (size_t firstVar, size_t lastVar)); - MOCK_METHOD0(CalcCheatVarHash, void ()); - MOCK_METHOD0(IsHashCalculated, bool ()); - MOCK_METHOD0(GetCheatVarHash, uint64 ()); - MOCK_METHOD1(PrintCheatVars, void (bool bUseLastHashRange)); - MOCK_METHOD1(GetCheatVarAt, char* (uint32 nOffset)); MOCK_METHOD1(AddConsoleVarSink, void (IConsoleVarSink * pSink)); MOCK_METHOD1(RemoveConsoleVarSink, void (IConsoleVarSink * pSink)); MOCK_METHOD1(GetHistoryElement, const char*(bool bUpOrDown)); diff --git a/Code/Legacy/CryCommon/Mocks/ITextureMock.h b/Code/Legacy/CryCommon/Mocks/ITextureMock.h index 1a9bca9082..8dc657195c 100644 --- a/Code/Legacy/CryCommon/Mocks/ITextureMock.h +++ b/Code/Legacy/CryCommon/Mocks/ITextureMock.h @@ -20,154 +20,6 @@ public: int()); MOCK_METHOD0(ReleaseForce, int()); - MOCK_CONST_METHOD0(GetClearColor, - const ColorF& ()); - MOCK_CONST_METHOD0(GetDstFormat, - const ETEX_Format()); - MOCK_CONST_METHOD0(GetSrcFormat, - const ETEX_Format()); - MOCK_CONST_METHOD0(GetTexType, - const ETEX_Type()); - MOCK_METHOD2(ApplyTexture, - void(int, int)); MOCK_CONST_METHOD0(GetName, const char*()); - MOCK_CONST_METHOD0(GetWidth, - const int()); - MOCK_CONST_METHOD0(GetHeight, - const int()); - MOCK_CONST_METHOD0(GetDepth, - const int()); - MOCK_CONST_METHOD0(GetTextureID, - const int()); - MOCK_CONST_METHOD0(GetFlags, - const uint32()); - MOCK_CONST_METHOD0(GetNumMips, - const int()); - MOCK_CONST_METHOD0(GetRequiredMip, - const int()); - MOCK_CONST_METHOD0(GetDeviceDataSize, - const int()); - MOCK_CONST_METHOD0(GetDataSize, - const int()); - MOCK_CONST_METHOD0(GetTextureType, - const ETEX_Type()); - MOCK_METHOD1(SetTextureType, - void(ETEX_Type type)); - MOCK_CONST_METHOD0(IsTextureLoaded, - const bool()); - MOCK_METHOD4(PrecacheAsynchronously, - void(float, int, int, int)); - MOCK_METHOD4(GetData32, - uint8 * (int nSide, int nLevel, uint8 * pDst, ETEX_Format eDstFormat)); - MOCK_METHOD1(SetFilter, - bool(int nFilter)); - MOCK_METHOD1(SetClamp, - void(bool bEnable)); - MOCK_CONST_METHOD0(GetAvgBrightness, - float()); - MOCK_CONST_METHOD1(StreamCalculateMipsSigned, - int(float fMipFactor)); - MOCK_CONST_METHOD0(GetStreamableMipNumber, - int()); - MOCK_CONST_METHOD1(GetStreamableMemoryUsage, - int(int nStartMip)); - MOCK_CONST_METHOD0(GetMinLoadedMip, - int()); - MOCK_METHOD2(Readback, - void(AZ::u32 subresourceIndex, StagingHook callback)); - MOCK_METHOD0(Reload, - bool()); - MOCK_CONST_METHOD0(GetFormatName, - const char*()); - MOCK_CONST_METHOD0(GetTypeName, - const char*()); - MOCK_CONST_METHOD0(IsStreamedVirtual, - const bool()); - MOCK_CONST_METHOD0(IsShared, - const bool()); - MOCK_CONST_METHOD0(IsStreamable, - const bool()); - MOCK_CONST_METHOD1(IsStreamedIn, - bool(const int nMinPrecacheRoundIds[2])); - MOCK_CONST_METHOD0(GetAccessFrameId, - const int()); - MOCK_CONST_METHOD0(GetTextureDstFormat, - const ETEX_Format()); - MOCK_CONST_METHOD0(GetTextureSrcFormat, - const ETEX_Format()); - MOCK_CONST_METHOD0(IsPostponed, - bool()); - MOCK_CONST_METHOD1(IsParticularMipStreamed, - const bool(float fMipFactor)); - MOCK_METHOD3(GetLowResSystemCopy, - const ColorB * (uint16 & nWidth, uint16 & nHeight, int** ppLowResSystemCopyAtlasId)); - MOCK_METHOD1(SetKeepSystemCopy, - void(bool bKeepSystemCopy)); - MOCK_METHOD8(UpdateTextureRegion, - void(const uint8_t * data, int nX, int nY, int nZ, int USize, int VSize, int ZSize, ETEX_Format eTFSrc)); - MOCK_CONST_METHOD0(GetDevTexture, - CDeviceTexture * ()); -}; - -class ITextureLoadHandlerMock - : public ITextureLoadHandler -{ -public: - MOCK_METHOD2(LoadTextureData, - bool(const char* path, STextureLoadData & loadData)); - MOCK_CONST_METHOD1(SupportsExtension, - bool(const char* ext)); - MOCK_METHOD0(Update, - void()); -}; - -class IDynTextureMock - : public IDynTexture -{ -public: - MOCK_METHOD0(Release, - void()); - MOCK_METHOD4(GetSubImageRect, - void(uint32 & nX, uint32 & nY, uint32 & nWidth, uint32 & nHeight)); - MOCK_METHOD4(GetImageRect, - void(uint32 & nX, uint32 & nY, uint32 & nWidth, uint32 & nHeight)); - MOCK_METHOD0(GetTextureID, - int()); - MOCK_METHOD0(Lock, - void()); - MOCK_METHOD0(UnLock, - void()); - MOCK_METHOD0(GetWidth, - int()); - MOCK_METHOD0(GetHeight, - int()); - MOCK_METHOD0(IsValid, - bool()); - MOCK_CONST_METHOD0(GetFlags, - uint8()); - MOCK_METHOD1(SetFlags, - void(uint8 flags)); - MOCK_METHOD2(Update, - bool(int nNewWidth, int nNewHeight)); - MOCK_METHOD2(Apply, - void(int, int)); - MOCK_METHOD0(ClearRT, - bool()); - MOCK_METHOD4(SetRT, - bool(int nRT, bool bPush, struct SDepthTexture* pDepthSurf, bool bScreenVP)); - MOCK_METHOD0(SetRectStates, - bool()); - MOCK_METHOD2(RestoreRT, - bool(int nRT, bool bPop)); - MOCK_METHOD0(GetTexture, - ITexture * ()); - MOCK_METHOD0(SetUpdateMask, - void()); - MOCK_METHOD0(ResetUpdateMask, - void()); - MOCK_METHOD0(IsSecondFrame, - bool()); - MOCK_METHOD2(GetImageData32, - bool(uint8 * pData, int nDataSize)); }; diff --git a/Code/Legacy/CryCommon/Options.h b/Code/Legacy/CryCommon/Options.h deleted file mode 100644 index 935c8bd371..0000000000 --- a/Code/Legacy/CryCommon/Options.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - -// Description : Facilities for defining and combining general-purpose or specific options, for functions or structs. - - -#ifndef CRYINCLUDE_CRYCOMMON_OPTIONS_H -#define CRYINCLUDE_CRYCOMMON_OPTIONS_H -#pragma once - - -// Facilities for collecting options in a struct, and quickly constructing them. -// Used, for example, as construction argument. Safer and more informative than bool arguments. -// -// Example: -// struct FObjectOpts; -// struct CObject { CObject(FObjectOpts = ZERO); }; -// CObject object_def(); -// CObject object( FObjectOpts().Size(8).AllowGrowth(true) ); - -template -struct TOptVar -{ - typedef T TValue; - - TOptVar() - : _val(T(NInit)) - { - offset(this); - } - TOptVar(T val) - : _val(val) {} - - operator T () const - { - return _val; - } - T operator ()() const - { return _val; } - T operator +() const - { return _val; } - bool operator !() const - { return !_val; } - - TContainer& operator()(T val) - { - _val = val; - return *(TContainer*)((char*)this - offset()); - } - -private: - T _val; - - static size_t offset(void* self = 0) - { - static size_t _offset = TContainer::static_offset(self); - return _offset; - } -}; - -#define OPT_STRUCT(TOpts) \ - typedef TOpts TThis; typedef uint TInt; \ - static size_t static_offset(void* var) { static void* _first = var; return (char*)var - (char*)_first; } \ - TOpts([[maybe_unused]] void* p = 0) {} \ - TOpts operator()() const { return TOpts(*this); } \ - -#define OPT_VAR(Type, Var) \ - enum E##Var {}; TOptVar Var; \ - -#define OPT_VAR_INIT(Type, Var, init) \ - enum E##Var {}; TOptVar Var; \ - -#define BIT_STRUCT(Struc, Int) \ - typedef Struc TThis; typedef Int TInt; \ - TInt Mask() const { return *(const TInt*)this; } \ - TInt& Mask() { return *(TInt*)this; } \ - Struc(TInt init = 0) { static_assert(sizeof(TThis) == sizeof(TInt)); Mask() = init; } \ - -#define BIT_VAR(Var) \ - TInt _##Var : 1; \ - bool Var() const { return _##Var; } \ - TThis& Var(bool val) { _##Var = val; return *this; } \ - -#endif // CRYINCLUDE_CRYCOMMON_OPTIONS_H diff --git a/Code/Legacy/CryCommon/StereoRendererBus.h b/Code/Legacy/CryCommon/StereoRendererBus.h deleted file mode 100644 index 370bbaef27..0000000000 --- a/Code/Legacy/CryCommon/StereoRendererBus.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -#pragma once - -#include - -namespace AZ -{ - /// - /// The Stereo Renderer bus allows other systems to query various properties on the stereo renderer - /// - class StereoRendererBus - : public EBusTraits - { - public: - - ////////////////////////////////////////////////////////////////////////// - // EBus Traits - static const EBusHandlerPolicy HandlerPolicy = EBusHandlerPolicy::Multiple; - static const EBusAddressPolicy AddressPolicy = EBusAddressPolicy::Single; - using MutexType = AZStd::recursive_mutex; - ////////////////////////////////////////////////////////////////////////// - - virtual ~StereoRendererBus() {} - - /// - /// Return whether the renderer is rendering to the HMD - /// - /// @return True if rendering to the HMD - /// - virtual bool IsRenderingToHMD() { return false; } - - protected: - }; - - using StereoRendererRequestBus = EBus < StereoRendererBus >; -} diff --git a/Code/Legacy/CryCommon/StlUtils.h b/Code/Legacy/CryCommon/StlUtils.h index d7e5697593..4aafd4dd0e 100644 --- a/Code/Legacy/CryCommon/StlUtils.h +++ b/Code/Legacy/CryCommon/StlUtils.h @@ -9,14 +9,13 @@ // Description : Various convenience utility functions for STL and alike // Used in Animation subsystem, and in some tools -#ifndef CRYINCLUDE_CRYCOMMON_STLUTILS_H -#define CRYINCLUDE_CRYCOMMON_STLUTILS_H #pragma once #include #include #include #include +#include #if (defined(LINUX) || defined(APPLE)) #include "platform.h" @@ -527,58 +526,6 @@ namespace stl // typedef AZStd::unordered_map, stl::equality_string_insensitive > StringToIntHash; ////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////// - // useful when the key is already the result of an hash function - // key needs to be convertible to size_t - ////////////////////////////////////////////////////////////////////////// - template - class hash_simple - { - public: - enum // parameters for hash table - { - bucket_size = 4, // 0 < bucket_size - min_buckets = 8 - };// min_buckets = 2 ^^ N, 0 < N - - size_t operator()(const Key& key) const - { - return size_t(key); - }; - bool operator()(const Key& key1, const Key& key2) const - { - return key1 < key2; - } - }; - - // simple hash class that has the avalanche property (a change in one bit affects all others) - // ... use this if you have uint32 key values! - class hash_uint32 - { - public: - enum // parameters for hash table - { - bucket_size = 4, // 0 < bucket_size - min_buckets = 8 // min_buckets = 2 ^^ N, 0 < N - }; - - ILINE size_t operator()(uint32 a) const - { - a = (a + 0x7ed55d16) + (a << 12); - a = (a ^ 0xc761c23c) ^ (a >> 19); - a = (a + 0x165667b1) + (a << 5); - a = (a + 0xd3a2646c) ^ (a << 9); - a = (a + 0xfd7046c5) + (a << 3); - a = (a ^ 0xb55a4f09) ^ (a >> 16); - return a; - }; - bool operator()(uint32 key1, uint32 key2) const - { - return key1 < key2; - } - }; - - ////////////////////////////////////////////////////////////////////////// //! Case sensitive string hash ////////////////////////////////////////////////////////////////////////// @@ -655,130 +602,6 @@ namespace stl } }; - - // Support for both Microsoft and SGI kind of hash_map. - -#if defined(_STLP_HASH_MAP) || defined(APPLE) || defined(LINUX) - // STL Port - template > - struct hash_compare - { - enum - { // parameters for hash table - bucket_size = 4, // 0 < bucket_size - min_buckets = 8 // min_buckets = 2 ^^ N, 0 < N - }; - - size_t operator()(const _Key& _Keyval) const - { - // return hash value. - uint32 a = _Keyval; - a = (a + 0x7ed55d16) + (a << 12); - a = (a ^ 0xc761c23c) ^ (a >> 19); - a = (a + 0x165667b1) + (a << 5); - a = (a + 0xd3a2646c) ^ (a << 9); - a = (a + 0xfd7046c5) + (a << 3); - a = (a ^ 0xb55a4f09) ^ (a >> 16); - return a; - } - - // Less then function. - bool operator()(const _Key& _Keyval1, const _Key& _Keyval2) const - { // test if _Keyval1 ordered before _Keyval2 - _Predicate comp; - return (comp(_Keyval1, _Keyval2)); - } - }; - - template - struct stlport_hash_equal - { - // Equal function. - bool operator()(const Key& k1, const Key& k2) const - { - HashFunc less; - // !(k1 < k2) && !(k2 < k1) - return !less(k1, k2) && !less(k2, k1); - } - }; - - template , class Alloc = std::allocator< std::pair > > - struct hash_map - : public std__hash_map, Alloc> - { - hash_map() - : std__hash_map, Alloc>(HashFunc::min_buckets) {} - }; - - template , class Alloc = std::allocator< std::pair > > - struct hash_multimap - : public std__hash_multimap, Alloc> - { - hash_multimap() - : std__hash_multimap, Alloc>(HashFunc::min_buckets) {} - }; -#endif - - ////////////////////////////////////////////////////////////////////////// - template - class intrusive_linked_list_node - { - public: - intrusive_linked_list_node() { link_to_intrusive_list(static_cast(this)); } - // Not virtual by design - ~intrusive_linked_list_node() { unlink_from_intrusive_list(static_cast(this)); } - - static T* get_intrusive_list_root() { return m_root_intrusive; }; - - static void link_to_intrusive_list(T* pNode) - { - if (m_root_intrusive) - { - // Add to the beginning of the list. - T* head = m_root_intrusive; - pNode->m_prev_intrusive = 0; - pNode->m_next_intrusive = head; - head->m_prev_intrusive = pNode; - m_root_intrusive = pNode; - } - else - { - m_root_intrusive = pNode; - pNode->m_prev_intrusive = 0; - pNode->m_next_intrusive = 0; - } - } - static void unlink_from_intrusive_list(T* pNode) - { - if (pNode == m_root_intrusive) // if head of list. - { - m_root_intrusive = pNode->m_next_intrusive; - if (m_root_intrusive) - { - m_root_intrusive->m_prev_intrusive = 0; - } - } - else - { - if (pNode->m_prev_intrusive) - { - pNode->m_prev_intrusive->m_next_intrusive = pNode->m_next_intrusive; - } - if (pNode->m_next_intrusive) - { - pNode->m_next_intrusive->m_prev_intrusive = pNode->m_prev_intrusive; - } - } - pNode->m_next_intrusive = 0; - pNode->m_prev_intrusive = 0; - } - - public: - static T* m_root_intrusive; - T* m_next_intrusive; - T* m_prev_intrusive; - }; - template inline void reconstruct(T& t) { @@ -860,30 +683,6 @@ namespace stl } }; - template - struct scoped_set - { - scoped_set(T& ref, T val) - : m_ref(&ref) - , m_oldVal(ref) - { - ref = val; - } - - ~scoped_set() - { - (*m_ref) = m_oldVal; - } - - private: - scoped_set(const scoped_set& other); - scoped_set& operator = (const scoped_set& other); - - private: - T* m_ref; - T m_oldVal; - }; - template inline void for_each_array(T (&buffer)[Length], Func func) { @@ -910,64 +709,6 @@ namespace stl template<> \ Class * stl::intrusive_linked_list_node::m_root_intrusive = nullptr; - -// Performs a less-than compare on a serial sequence space, such that earlier values compare less-than later values. -// Unlike a normal integral value, this accounts for overflowing the limit of the underlying type. -// For example, assuming a 2-bit unsigned underlying type (with possible values 0, 1, 2 and 3), the following will hold: 0 < 1 && 1 < 2 && 2 < 3 && 3 < 0 -// Assuming two equal values V1 and V2, V2 can be incremented up to "(2 ^ (bits - 1) - 1)" times and V1 < V2 will continue to hold. -// See also RFC-1982 that documents this http://tools.ietf.org/html/rfc1982 -template -struct SSerialCompare -{ - static_assert(std::is_integral::value && std::is_unsigned::value, "T must be an unsigned integral type"); - - static const T limit = (T(1) << (sizeof(T) * 8 - 1)); - - bool operator()(T lhs, T rhs) - { - return ((lhs < rhs) && (rhs - lhs < limit)) || ((lhs > rhs) && (lhs - rhs > limit)); - } -}; - -template -unsigned sizeOfVP(Container& arr) -{ - int i; - unsigned size = 0; - for (i = 0; i < (int)arr.size(); i++) - { - typename Container::value_type& T = arr[i]; - size += T->Size(); - } - size += (arr.capacity() - arr.size()) * sizeof(typename Container::value_type); - return size; -} - -template -unsigned sizeOfV(Container& arr) -{ - int i; - unsigned size = 0; - for (i = 0; i < (int)arr.size(); i++) - { - typename Container::value_type& T = arr[i]; - size += T.Size(); - } - size += (arr.capacity() - arr.size()) * sizeof(typename Container::value_type); - return size; -} -template -unsigned sizeOfA(Container& arr) -{ - int i; - unsigned size = 0; - for (i = 0; i < arr.size(); i++) - { - typename Container::value_type& T = arr[i]; - size += T.Size(); - } - return size; -} // define the maplikestruct, used to approximate the memory requirements for a map node namespace stl { @@ -1027,5 +768,3 @@ unsigned sizeOfMapS(Map& map) size += map.size() * sizeof(stl::MapLikeStruct); return size; } - -#endif // CRYINCLUDE_CRYCOMMON_STLUTILS_H diff --git a/Code/Legacy/CryCommon/Tarray.h b/Code/Legacy/CryCommon/Tarray.h deleted file mode 100644 index 77c27f0ef8..0000000000 --- a/Code/Legacy/CryCommon/Tarray.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - -#ifndef CRYINCLUDE_CRYCOMMON_TARRAY_H -#define CRYINCLUDE_CRYCOMMON_TARRAY_H -#pragma once - - -#include -#include -#include - -#ifndef CLAMP -#define CLAMP(X, mn, mx) ((X) < (mn) ? (mn) : ((X) < (mx) ? (X) : (mx))) -#endif - -#ifndef SATURATE -#define SATURATE(X) clamp_tpl(X, 0.f, 1.f) -#endif - -#ifndef SATURATEB -#define SATURATEB(X) CLAMP(X, 0, 255) -#endif - -#ifndef LERP -#define LERP(A, B, Alpha) ((A) + (Alpha) * ((B)-(A))) -#endif - -// Safe memory freeing -#ifndef SAFE_DELETE -#define SAFE_DELETE(p) { if (p) { delete (p); (p) = NULL; } \ -} -#endif - -#ifndef SAFE_DELETE_ARRAY -#define SAFE_DELETE_ARRAY(p) { if (p) { delete[] (p); (p) = NULL; } \ -} -#endif - -#ifndef SAFE_RELEASE -#define SAFE_RELEASE(p) { if (p) { (p)->Release(); (p) = NULL; } \ -} -#endif - -#ifndef SAFE_RELEASE_FORCE -#define SAFE_RELEASE_FORCE(p) { if (p) { (p)->ReleaseForce(); (p) = NULL; } \ -} -#endif - -#endif // CRYINCLUDE_CRYCOMMON_TARRAY_H diff --git a/Code/Legacy/CryCommon/TimeValue.h b/Code/Legacy/CryCommon/TimeValue.h index abe37c8608..14f402eb3d 100644 --- a/Code/Legacy/CryCommon/TimeValue.h +++ b/Code/Legacy/CryCommon/TimeValue.h @@ -164,8 +164,6 @@ public: ILINE bool operator==(const CTimeValue& inRhs) const { return m_lValue == inRhs.m_lValue; }; ILINE bool operator!=(const CTimeValue& inRhs) const { return m_lValue != inRhs.m_lValue; }; - AUTO_STRUCT_INFO - void GetMemoryStatistics(class ICrySizer*) const { /*nothing*/} private: // ---------------------------------------------------------- diff --git a/Code/Legacy/CryCommon/TimeValue_info.h b/Code/Legacy/CryCommon/TimeValue_info.h deleted file mode 100644 index 4de34e7997..0000000000 --- a/Code/Legacy/CryCommon/TimeValue_info.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - -#ifndef CRYINCLUDE_CRYCOMMON_TIMEVALUE_INFO_H -#define CRYINCLUDE_CRYCOMMON_TIMEVALUE_INFO_H -#pragma once - -#include "TimeValue.h" - -STRUCT_INFO_BEGIN(CTimeValue) -STRUCT_VAR_INFO(m_lValue, TYPE_INFO(int64)) -STRUCT_INFO_END(CTimeValue) - - -#endif // CRYINCLUDE_CRYCOMMON_TIMEVALUE_INFO_H diff --git a/Code/Legacy/CryCommon/TypeInfo_decl.h b/Code/Legacy/CryCommon/TypeInfo_decl.h deleted file mode 100644 index 28a0b370a9..0000000000 --- a/Code/Legacy/CryCommon/TypeInfo_decl.h +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - -// Description : Macros and other definitions needed for TypeInfo declarations. - - -#ifndef CRYINCLUDE_CRYCOMMON_TYPEINFO_DECL_H -#define CRYINCLUDE_CRYCOMMON_TYPEINFO_DECL_H -#pragma once - -#include -#include - -////////////////////////////////////////////////////////////////////////// -// Meta-type support. -////////////////////////////////////////////////////////////////////////// - -// Currently enable type info for all platforms. -#if !defined(ENABLE_TYPE_INFO) -#define ENABLE_TYPE_INFO -#endif -#ifdef ENABLE_TYPE_INFO - -struct CTypeInfo; - -// If TypeInfo exists for T, it is accessed via TypeInfo(T*). -// Default TypeInfo() is implemented by a struct member function. -template -inline const CTypeInfo& TypeInfo(const T* t) -{ - return t->TypeInfo(); -} - -// Declare a class's TypeInfo member -#define STRUCT_INFO \ - const CTypeInfo&TypeInfo() const; - -#define NULL_STRUCT_INFO \ - const CTypeInfo&TypeInfo() const { return *(CTypeInfo*)0; } - -// Declare an override for a type without TypeInfo() member (e.g. basic type) -#define DECLARE_TYPE_INFO(Type) \ - template<> \ - const CTypeInfo&TypeInfo(const Type*); - -// Template version. -#define DECLARE_TYPE_INFO_T(Type) \ - template \ - const CTypeInfo&TypeInfo(const Type*); - -// Type info declaration, with additional prototypes for string conversions. -#define BASIC_TYPE_INFO(Type) \ - AZStd::string ToString(Type const & val); \ - bool FromString(Type & val, const char* s); \ - DECLARE_TYPE_INFO(Type) - -#define CUSTOM_STRUCT_INFO(Struct) \ - const CTypeInfo&TypeInfo() const \ - { static Struct Info; return Info; } - -#else // ENABLE_TYPE_INFO - -#define STRUCT_INFO -#define NULL_STRUCT_INFO -#define DECLARE_TYPE_INFO(Type) -#define DECLARE_TYPE_INFO_T(Type) -#define BASIC_TYPE_INFO(T) - -#endif // ENABLE_TYPE_INFO - -// Specify automatic tool generation of TypeInfo bodies. -#define AUTO_STRUCT_INFO STRUCT_INFO -#define AUTO_TYPE_INFO DECLARE_TYPE_INFO -#define AUTO_TYPE_INFO_T DECLARE_TYPE_INFO_T - -// Obsolete "LOCAL" versions (all infos now generated in local files). -#define AUTO_STRUCT_INFO_LOCAL STRUCT_INFO -#define AUTO_TYPE_INFO_LOCAL DECLARE_TYPE_INFO -#define AUTO_TYPE_INFO_LOCAL_T DECLARE_TYPE_INFO_T - -// Overrides for basic types. -DECLARE_TYPE_INFO(void) - -BASIC_TYPE_INFO(bool) -BASIC_TYPE_INFO(char) -BASIC_TYPE_INFO(wchar_t) -BASIC_TYPE_INFO(signed char) -BASIC_TYPE_INFO(unsigned char) -BASIC_TYPE_INFO(short) -BASIC_TYPE_INFO(unsigned short) -BASIC_TYPE_INFO(int) -BASIC_TYPE_INFO(unsigned int) -BASIC_TYPE_INFO(long) -BASIC_TYPE_INFO(unsigned long) -BASIC_TYPE_INFO(int64) -BASIC_TYPE_INFO(uint64) - -BASIC_TYPE_INFO(float) -BASIC_TYPE_INFO(double) - -BASIC_TYPE_INFO(AZ::Uuid) - -DECLARE_TYPE_INFO(AZStd::string) - -// All pointers share same TypeInfo. -const CTypeInfo&PtrTypeInfo(); -template -inline const CTypeInfo& TypeInfo([[maybe_unused]] T** t) -{ - return PtrTypeInfo(); -} - - -#endif // CRYINCLUDE_CRYCOMMON_TYPEINFO_DECL_H diff --git a/Code/Legacy/CryCommon/TypeInfo_impl.h b/Code/Legacy/CryCommon/TypeInfo_impl.h deleted file mode 100644 index 9c4bb6bca7..0000000000 --- a/Code/Legacy/CryCommon/TypeInfo_impl.h +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - -// Description : Declaration of CTypeInfo, and other things to access meta-type info. - - -#ifndef CRYINCLUDE_CRYCOMMON_TYPEINFO_IMPL_H -#define CRYINCLUDE_CRYCOMMON_TYPEINFO_IMPL_H -#pragma once - - -#include "CryCustomTypes.h" - -#define ENABLE_TYPE_INFO_NAMES 1 - -//--------------------------------------------------------------------------- -// DECLARATION MACROS -// Used to construct meta TypeInfo objects in AutoTypeInfo files. -// Two possible levels of TypeInfo: default, with size and offset info only, allowing Endian conversion; -// and full, with string, attr, and enum info, allowing UI and serialisation. -// The full version is selected by the ENABLE_TYPE_INFO_NAMES macro. - -#ifdef ENABLE_TYPE_INFO - - #ifndef ENABLE_TYPE_INFO_NAMES -// This symbol must be defined only once per module. - #define ENABLE_TYPE_INFO_NAMES 0 - #endif - - #if ENABLE_TYPE_INFO_NAMES - #define TYPE_INFO_NAME(n) #n - #else - #define TYPE_INFO_NAME(n) "" - #endif - #define TYPE_INFO_NAME_T(n) #n "<>" - -// Set of template functions for automatically returning the base element type for any scalar or array variable. - -template -inline T& ElemType(T* at) -{ return *at; } - -template -inline T& ElemType(T (*at)[N]) -{ return **at; } - -template -inline T& ElemType(T (*at)[N][N2]) -{ return ***at; } - -template -inline T& ElemType(T (*at)[N][N2][N3]) -{ return ****at; } - -template -inline T& ValType([[maybe_unused]] T t) -{ static T _t; return _t; } - -//--------------------------------------------------------------------------- -// Macros for constructing StructInfos (invoked by AutoTypeInfo.h) - - #define DEFINE_TYPE_INFO(T, Type, Args) \ - template<> \ - const CTypeInfo&TypeInfo(const T*) \ - { static Type Info Args; return Info; } \ - - #define STRUCT_INFO_EMPTY_BODY(T) \ - { \ - static CStructInfo Info(#T, sizeof(T), alignof(T)); \ - return Info; \ - } \ - - #define STRUCT_INFO_EMPTY(T) \ - const CTypeInfo&T::TypeInfo() const \ - STRUCT_INFO_EMPTY_BODY(T) \ - - #define STRUCT_INFO_T_EMPTY(T, Key, Arg) \ - template \ - STRUCT_INFO_EMPTY(T) - - #define STRUCT_INFO_TYPE_EMPTY(T) \ - DEFINE_TYPE_INFO(T, CStructInfo, (#T, sizeof(T), alignof(T))) - - #define STRUCT_INFO_TYPE_T_EMPTY(T, TArgs, TDecl) \ - template TDecl const CTypeInfo&TypeInfo(const T TArgs*) \ - STRUCT_INFO_EMPTY_BODY(T TArgs) \ - -// Define TypeInfo for a primitive type, without string conversion. - #define TYPE_INFO_PLAIN(T) DEFINE_TYPE_INFO(T, CTypeInfo, (#T, sizeof(T), alignof(T))) - -// Define TypeInfo for a basic type (undecomposable as far as TypeInfo cares), with external string converters. - #define TYPE_INFO_BASIC(T) DEFINE_TYPE_INFO(T, TTypeInfo, (#T)) - -// Variant for int types, allowing conversion between sizes. - #define TYPE_INFO_INT(T) DEFINE_TYPE_INFO(T, TIntTypeInfo, (#T)) - - #define STRUCT_INFO_BEGIN(T) \ - const CTypeInfo&T::TypeInfo() const { \ - static CStructInfo::CVarInfo Vars[] = { \ - - #define STRUCT_INFO_END(T) \ - }; \ - static CStructInfo Info(#T, sizeof(T), alignof(T), ARRAY_VAR(Vars)); \ - return Info; \ - } - - #define BASE_INFO_ATTRS(BaseType, Attrs) \ - { ::TypeInfo((const BaseType*)this), "", Attrs, uint32((char*)static_cast(this) - (char*)this), 1, 1, 0, 0, 0 }, - - #define BASE_INFO(BaseType) BASE_INFO_ATTRS(BaseType, "") - - #define ALIAS_INFO_ATTRS(AliasName, VarName, Attrs) \ - { ::TypeInfo(&ElemType(&VarName)), TYPE_INFO_NAME(AliasName), Attrs, uint32((char*)&VarName - (char*)this), sizeof(VarName) / sizeof(ElemType(&VarName)), 0, 0, 0, 0 }, - - #define ALIAS_INFO_STRINGNAME_ATTR(AliasStringName, VarName, Attrs) \ - { ::TypeInfo(&ElemType(&VarName)), AliasStringName, Attrs, uint32((char*)&VarName - (char*)this), sizeof(VarName) / sizeof(ElemType(&VarName)), 0, 0, 0, 0 }, - - #define VAR_INFO_ATTRS(VarName, Attrs) \ - ALIAS_INFO_ATTRS(VarName, VarName, Attrs) - - #define VAR_INFO(VarName) \ - VAR_INFO_ATTRS(VarName, "") - - #define ALIAS_INFO(AliasName, VarName) \ - ALIAS_INFO_ATTRS(AliasName, VarName, "") - - #define ATTRS_INFO(Attrs) \ - { ::TypeInfo((void*)0), "", Attrs, 0, 0, 0, 0, 0, 0 }, - - #define BITFIELD_INFO(VarName, Bits) \ - { ::TypeInfo(&ValType(VarName)), TYPE_INFO_NAME(VarName), "", 0, Bits, 0, 1, 0, 0 }, - -// Conversion macros for older system. - #define STRUCT_BASE_INFO(BaseType) BASE_INFO(BaseType) - #define STRUCT_VAR_INFO(VarName, InfoName) VAR_INFO(VarName) - #define STRUCT_BITFIELD_INFO(VarName, VarType, Bits) BITFIELD_INFO(VarName, Bits) - -// Template versions - -template -Array TypeInfoArray1(T const* pt) -{ - static CTypeInfo const* s_info = &::TypeInfo(pt); - return ArrayT(&s_info, 1); -} - - #define STRUCT_INFO_T_BEGIN(T, Key, Arg) \ - template \ - STRUCT_INFO_BEGIN(T) - - #define STRUCT_INFO_T_END(T, Key, Arg) \ - }; \ - static CStructInfo Info(#T "<>", sizeof(T), alignof(T), ARRAY_VAR(Vars), TypeInfoArray1((Arg*)0)); \ - return Info; \ - } - - #define STRUCT_INFO_T2_BEGIN(T, Key1, Arg1, Key2, Arg2) \ - template \ - const CTypeInfo&T::TypeInfo() const { \ - typedef T TThis; \ - static CStructInfo::CVarInfo Vars[] = { \ - - #define STRUCT_INFO_T2_END(T, Key1, Arg1, Key2, Arg2) \ - }; \ - static CTypeInfo const* TemplateTypes[] = { &::TypeInfo((Arg1*)0), &::TypeInfo((Arg2*)0) }; \ - static CStructInfo Info(#T "<,>", sizeof(TThis), alignof(TThis), ARRAY_VAR(Vars), ARRAY_VAR(TemplateTypes)); \ - return Info; \ - } - - #define STRUCT_INFO_T_INSTANTIATE(T, TArgs) \ - template const CTypeInfo& T::TypeInfo() const; - -//--------------------------------------------------------------------------- -// Enum type info - - #if ENABLE_TYPE_INFO_NAMES - -// Enums represented as full CEnumInfo types, with string conversion. - #define ENUM_INFO_BEGIN(T) \ - template<> \ - const CTypeInfo&TypeInfo(const T*) { \ - static CEnumDef::SElem Elems[] = { \ - - #define ENUM_INFO_END(T) \ - }; \ - typedef TIntType::TType TInt; \ - static CEnumInfo Info(#T, ARRAY_VAR(Elems)); \ - return Info; \ - } \ - - #define ENUM_ELEM_INFO(Scope, Elem) \ - { Scope Elem, #Elem }, - - #else // ENABLE_TYPE_INFO_NAMES - -// Enums represented as simple types, with no elements or string conversion. - #define ENUM_INFO_BEGIN(T) \ - TYPE_INFO_PLAIN(T) \ - - #define ENUM_INFO_END(T) - #define ENUM_ELEM_INFO(Scope, Elem) - - #endif // ENABLE_TYPE_INFO_NAMES - -#endif // ENABLE_TYPE_INFO - -#endif // CRYINCLUDE_CRYCOMMON_TYPEINFO_IMPL_H diff --git a/Code/Legacy/CryCommon/VectorSet.h b/Code/Legacy/CryCommon/VectorSet.h deleted file mode 100644 index 15b05e62ef..0000000000 --- a/Code/Legacy/CryCommon/VectorSet.h +++ /dev/null @@ -1,492 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - -// Description : std::set replacement implemented using sorted vector. - - -#ifndef CRYINCLUDE_CRYCOMMON_VECTORSET_H -#define CRYINCLUDE_CRYCOMMON_VECTORSET_H -#pragma once - - -//-------------------------------------------------------------------------- -// VectorSet -// -// Usage Notes: -// This class is designed to be an (almost, see below) drop-in replacement -// for std::set. It features an almost identical interface, but it is -// implemented using a sorted vector rather than a tree. This is in most -// cases more efficient, as there is less dynamic memory allocation and -// pointer dereferencing. -// -// ************************************************************************* -// PLEASE NOTE: There is one vital difference between std::set and VectorSet -// that you will need to note before trying to replace std::set. Since -// VectorSet is implemented using a vector, iterators can and will be -// invalidated by many operations, such as insertions and deletions, and -// due to sorting potentially even normal lookups. Please Please PLEASE make -// sure that you are not storing any iterators to this class. -// ************************************************************************* -// -// The class varies from the std::set API in that two of the erase methods -// methods are not of void return type but return an iterator - this is -// required in practice because they invalidate iterators, as noted above. -// -// * iterator erase(iterator where); -// * iterator erase(iterator first, iterator last); -// -// It also adds operator[] to the API. -// -// -// Performance Notes: -// -// This class uses the empty base optimization hack to allow comparison -// predicate objects that have no state to take up no space in the object. -// As a result the size of the overall VectorMap instance is the same as -// that of the std::vector it uses to store the elements. -// -// In addition to the normal map interface, this class provides the -// following members that can be used to manage memory requirements: -// -// * void reserve(size_type count); -// Allocate enough space for count elements (see vector::reserve()). -// -// * size_type capacity() const; -// Report how many elements can be stored without reallocating (see -// vector::capacity()). -// -// * void resize(size_type new_size, const_reference x=key_type()); -// see vector::resize()). -// -//-------------------------------------------------------------------------- - -template , typename A = AZ::StdLegacyAllocator > -class VectorSet - : private T // Empty base optimization -{ -public: - typedef K key_type; - typedef A allocator_type; - typedef T key_compare; - typedef T value_compare; - typedef AZStd::vector container_type; - typedef typename container_type::iterator iterator; - typedef typename container_type::const_iterator const_iterator; - typedef typename container_type::reverse_iterator reverse_iterator; - typedef typename container_type::const_reverse_iterator const_reverse_iterator; - typedef typename container_type::size_type size_type; - typedef typename container_type::difference_type difference_type; - typedef key_type& reference; - typedef const key_type& const_reference; - typedef key_type* pointer; - typedef const key_type* const_pointer; - - VectorSet(); - explicit VectorSet(const key_compare& comp); - explicit VectorSet(const key_compare& comp, const allocator_type& allocator); - VectorSet(const VectorSet& right); - template - VectorSet(InputIterator first, InputIterator last); - template - VectorSet(InputIterator first, InputIterator last, const key_compare& comp); - template - VectorSet(InputIterator first, InputIterator last, const key_compare& comp, const allocator_type& allocator); - void SwapElementsWithVector(container_type& elementVector); - const_iterator begin() const; - iterator begin(); - size_type capacity() const; - void resize(size_type __new_size, const_reference __x = key_type()); - void clear(); - size_type count(const_reference key) const; - bool empty() const; - const_iterator end() const; - iterator end(); - std::pair equal_range(const_reference key) const; - std::pair equal_range(const_reference key); - iterator erase(iterator where); // See documentation above - iterator erase(iterator first, iterator last); // See documentation above - size_t erase(const_reference key); - iterator find(const_reference key); - const_iterator find(const_reference key) const; - allocator_type get_allocator() const; - std::pair insert(const_reference value); - iterator insert(iterator _Where, const_reference value); - template - void insert(InputIterator first, InputIterator last); - key_compare key_comp() const; - const_iterator lower_bound(const_reference key) const; - iterator lower_bound(const_reference key); - size_type max_size() const; - const_reverse_iterator rbegin() const; - reverse_iterator rbegin(); - const_reverse_iterator rend() const; - reverse_iterator rend(); - void reserve(size_type count); - size_type size() const; - void swap(VectorSet& right); - const_iterator upper_bound(const_reference key) const; - iterator upper_bound(const_reference key); - value_compare value_comp() const; - reference operator[](int index); // See documentation above - const_reference operator[](int index) const; // See documentation above - - template - void GetMemoryUsage(Sizer* pSizer) const - { - pSizer->AddObject(m_entries); - } -private: - container_type m_entries; -}; - -template -VectorSet::VectorSet() -{ -} - -template -VectorSet::VectorSet(const key_compare& comp) - : key_compare(comp) -{ -} - -template -VectorSet::VectorSet(const key_compare& comp, const allocator_type& allocator) - : key_compare(comp) - , m_entries(allocator) -{ -} - -template -VectorSet::VectorSet(const VectorSet& right) - : key_compare(right) - , m_entries(right.m_entries) -{ -} - -template -template -VectorSet::VectorSet(InputIterator first, InputIterator last) -{ - for (; first != last; ++first) - { - m_entries.push_back(*first); - } - std::sort(m_entries.begin(), m_entries.end(), static_cast(*this)); -} - -template -template -VectorSet::VectorSet(InputIterator first, InputIterator last, const key_compare& comp) - : key_compare(comp) -{ - for (; first != last; ++first) - { - m_entries.push_back(*first); - } - std::sort(m_entries.begin(), m_entries.end(), static_cast(*this)); -} - -template -template -VectorSet::VectorSet(InputIterator first, InputIterator last, const key_compare& comp, const allocator_type& allocator) - : key_compare(comp) - , m_entries(allocator) -{ - for (; first != last; ++first) - { - m_entries.push_back(*first); - } - std::sort(m_entries.begin(), m_entries.end(), static_cast(*this)); -} - -template -void VectorSet::SwapElementsWithVector(container_type& elementVector) -{ - m_entries.swap(elementVector); - std::sort(m_entries.begin(), m_entries.end(), static_cast(*this)); -} - -template -typename VectorSet::const_iterator VectorSet::begin() const -{ - return m_entries.begin(); -} - -template -typename VectorSet::iterator VectorSet::begin() -{ - return m_entries.begin(); -} - -template -typename VectorSet::size_type VectorSet::capacity() const -{ - return m_entries.capacity(); -} - -template -void VectorSet::clear() -{ - m_entries.clear(); -} - -template -void VectorSet::resize(size_type __new_size, const_reference __x) -{ - m_entries.resize(__new_size, __x); -} - -template -typename VectorSet::size_type VectorSet::count(const_reference key) const -{ - return size_type(std::binary_search(m_entries.begin(), m_entries.end(), key, static_cast(*this))); -} - -template -bool VectorSet::empty() const -{ - return m_entries.empty(); -} - -template -typename VectorSet::const_iterator VectorSet::end() const -{ - return m_entries.end(); -} - -template -typename VectorSet::iterator VectorSet::end() -{ - return m_entries.end(); -} - -template -std::pair::const_iterator, typename VectorSet::const_iterator> VectorSet::equal_range(const_reference key) const -{ - const_iterator lower = lower_bound(key); - if (lower != m_entries.end() && key_compare::operator()(key, *lower)) - { - lower = m_entries.end(); - } - const_iterator upper = lower; - if (upper != m_entries.end()) - { - ++upper; - } - return std::make_pair(lower, upper); -} - -template -std::pair::iterator, typename VectorSet::iterator> VectorSet::equal_range(const_reference key) -{ - iterator lower = lower_bound(key); - if (lower != m_entries.end() && key_compare::operator()(key, *lower)) - { - lower = m_entries.end(); - } - iterator upper = lower; - if (upper != m_entries.end()) - { - ++upper; - } - return std::make_pair(lower, upper); -} - -template -typename VectorSet::iterator VectorSet::erase(iterator where) -{ - return m_entries.erase(where); -} - -template -typename VectorSet::iterator VectorSet::erase(iterator first, iterator last) -{ - return m_entries.erase(first, last); -} - -template -size_t VectorSet::erase(const_reference key) -{ - iterator where = find(key); - - if (where != m_entries.end()) - { - // Note erasing entries does not invalidate the sort - no need to trigger a re-sort. - m_entries.erase(where); - return 1; - } - - return 0; -} - -template -typename VectorSet::iterator VectorSet::find(const_reference key) -{ - iterator it = lower_bound(key); - if (it != m_entries.end() && key_compare::operator()(key, *it)) - { - it = m_entries.end(); - } - return it; -} - -template -typename VectorSet::const_iterator VectorSet::find(const_reference key) const -{ - const_iterator it = lower_bound(key); - if (it != m_entries.end() && key_compare::operator()(key, *it)) - { - it = m_entries.end(); - } - return it; -} - -template -typename VectorSet::allocator_type VectorSet::get_allocator() const -{ - return m_entries.get_allocator(); -} - -template -std::pair::iterator, bool> VectorSet::insert(const_reference value) -{ - iterator it = lower_bound(value); - bool insertionMade = false; - if (it == m_entries.end() || key_compare::operator()(value, (*it))) - { - it = m_entries.insert(it, value), insertionMade = true; - } - return std::make_pair(it, insertionMade); -} - -template -typename VectorSet::iterator VectorSet::insert(iterator where, const_reference value) -{ - return insert(value); -} - -template -template -void VectorSet::insert(InputIterator first, InputIterator last) -{ - for (; first != last; ++first) - { - insert(*first); - } -} - -template -typename VectorSet::key_compare VectorSet::key_comp() const -{ - return static_cast(*this); -} - -template -typename VectorSet::const_iterator VectorSet::lower_bound(const_reference key) const -{ - return std::lower_bound(m_entries.begin(), m_entries.end(), key, static_cast(*this)); -} - -template -typename VectorSet::iterator VectorSet::lower_bound(const_reference key) -{ - return std::lower_bound(m_entries.begin(), m_entries.end(), key, static_cast(*this)); -} - -template -typename VectorSet::size_type VectorSet::max_size() const -{ - return m_entries.max_size(); -} - -template -typename VectorSet::const_reverse_iterator VectorSet::rbegin() const -{ - return m_entries.rbegin(); -} - -template -typename VectorSet::reverse_iterator VectorSet::rbegin() -{ - return m_entries.rbegin(); -} - -template -typename VectorSet::const_reverse_iterator VectorSet::rend() const -{ - return m_entries.rend(); -} - -template -typename VectorSet::reverse_iterator VectorSet::rend() -{ - return m_entries.rend(); -} - -template -void VectorSet::reserve(size_type count) -{ - m_entries.reserve(count); -} - -template -typename VectorSet::size_type VectorSet::size() const -{ - return m_entries.size(); -} - -template -void VectorSet::swap(VectorSet& other) -{ - m_entries.swap(other.m_entries); - std::swap(static_cast(*this), static_cast(other)); -} - -template -typename VectorSet::const_iterator VectorSet::upper_bound(const_reference key) const -{ - const_iterator upper = lower_bound(key); - if (upper != m_entries.end() && !key_compare::operator()(key, *upper)) - { - ++upper; - } - return upper; -} - -template -typename VectorSet::iterator VectorSet::upper_bound(const_reference key) -{ - iterator upper = lower_bound(key); - if (upper != m_entries.end() && !key_compare::operator()(key, *upper)) - { - ++upper; - } - return upper; -} - -template -typename VectorSet::value_compare VectorSet::value_comp() const -{ - return static_cast(*this); -} - -template -typename VectorSet::reference VectorSet::operator[](int index) -{ - return m_entries[index]; -} - -template -typename VectorSet::const_reference VectorSet::operator[](int index) const -{ - return m_entries[index]; -} - -#endif // CRYINCLUDE_CRYCOMMON_VECTORSET_H diff --git a/Code/Legacy/CryCommon/Vertex.h b/Code/Legacy/CryCommon/Vertex.h index b9e0b25d38..f4e8f71a56 100644 --- a/Code/Legacy/CryCommon/Vertex.h +++ b/Code/Legacy/CryCommon/Vertex.h @@ -9,6 +9,9 @@ #include #include #include +#include +#include + namespace AZ { namespace Vertex @@ -77,7 +80,7 @@ namespace AZ UInt32_4, NumTypes - }; + }; struct AttributeTypeData { @@ -127,15 +130,15 @@ namespace AZ return (static_cast(type) << kUsageBitCount) | static_cast(usage); } static AttributeUsage GetUsage(const uint8 attribute) - { + { return static_cast(attribute & kUsageMask); } static AttributeType GetType(const uint8 attribute) - { + { return static_cast((attribute & kTypeMask) >> kUsageBitCount); } static uint8 GetByteLength(const uint8 attribute) - { + { return AttributeTypeDataTable[(uint)GetType(attribute)].byteSize; } static const AZStd::string& GetSemanticName(uint8 attribute) @@ -167,126 +170,22 @@ namespace AZ AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); m_enum = eVF_P3F_C4B_T2F; break; - case eVF_P3F_C4B_T2F_T2F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Byte_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - m_enum = eVF_P3F_C4B_T2F_T2F; - break; case eVF_P3S_C4B_T2S: AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float16_4));// vec3f16 is backed by a CryHalf4 AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Byte_4)); AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float16_2)); m_enum = eVF_P3S_C4B_T2S; break; - case eVF_P3S_C4B_T2S_T2S: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float16_4));// vec3f16 is backed by a CryHalf4 - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Byte_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float16_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float16_2)); - m_enum = eVF_P3S_C4B_T2S_T2S; - break; - case eVF_P3S_N4B_C4B_T2S: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float16_4));// vec3f16 is backed by a CryHalf4 - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Normal, AttributeType::Byte_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Byte_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float16_2)); - m_enum = eVF_P3S_N4B_C4B_T2S; - break; - case eVF_P3F_C4B_T4B_N3F2: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Byte_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Byte_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Tangent, AttributeType::Float32_3));//x-axis - AddAttribute(Attribute::CreateAttribute(AttributeUsage::BiTangent, AttributeType::Float32_3));//y-axis -#ifdef PARTICLE_MOTION_BLUR // Nonfunctional and disabled. - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3));//prevPos - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Tangent, AttributeType::Float32_3));//prevXTan - AddAttribute(Attribute::CreateAttribute(AttributeUsage::BiTangent, AttributeType::Float32_3));//prevYTan -#endif - m_enum = eVF_P3F_C4B_T4B_N3F2;// Particles. - break; - case eVF_TP3F_C4B_T2F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Byte_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - m_enum = eVF_TP3F_C4B_T2F;// Fonts (28 bytes). - break; - case eVF_TP3F_T2F_T3F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); - m_enum = eVF_TP3F_T2F_T3F; - break; - case eVF_P3F_T3F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); - m_enum = eVF_P3F_T3F; // Miscellaneus. - break; - case eVF_P3F_T2F_T3F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); - m_enum = eVF_P3F_T2F_T3F; - break; // Additional streams - case eVF_T2F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - m_enum = eVF_T2F; // Light maps TC (8 bytes). - break; case eVF_W4B_I4S:// Skinned weights/indices stream. AddAttribute(Attribute::CreateAttribute(AttributeUsage::Weights, AttributeType::Byte_4)); AddAttribute(Attribute::CreateAttribute(AttributeUsage::Indices, AttributeType::UInt16_4)); m_enum = eVF_W4B_I4S; break; - case eVF_C4B_C4B:// SH coefficients. - // We use the "Weights" usage since sh coefs use an unknown usage of 4 bytes. - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Weights, AttributeType::Byte_4)); //coef0 - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Weights, AttributeType::Byte_4)); //coef1 - m_enum = eVF_C4B_C4B; - break; - case eVF_P3F_P3F_I4B:// Shape deformation stream. - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); //thin - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); //fat - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Indices, AttributeType::Byte_4)); - m_enum = eVF_P3F_P3F_I4B; - break; case eVF_P3F:// Velocity stream. AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); m_enum = eVF_P3F; break; - case eVF_C4B_T2S: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Byte_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float16_2)); - m_enum = eVF_C4B_T2S;// General (Position is merged with Tangent stream) - break; - case eVF_P2F_T4F_C4F: // Lens effects simulation - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); - m_enum = eVF_P2F_T4F_C4F; - break; - case eVF_P2F_T4F_T4F_C4F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); - m_enum = eVF_P2F_T4F_T4F_C4F; - break; - case eVF_P2S_N4B_C4B_T1F:// terrain - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float16_2));// xy-coordinates in terrain - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Normal, AttributeType::Byte_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Byte_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1));// z-coordinate in terrain - m_enum = eVF_P2S_N4B_C4B_T1F; - break; - case eVF_P3F_C4B_T2S: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Byte_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float16_2)); - m_enum = eVF_P3F_C4B_T2S; - break; case eVF_P2F_C4B_T2F_F4B: AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_2)); AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Byte_4)); @@ -299,546 +198,6 @@ namespace AZ AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Byte_4)); m_enum = eVF_P3F_C4B; break; - case eVF_P3F_C4F_T2F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - m_enum = eVF_P3F_C4F_T2F; - break; - case eVF_P3F_C4F_T2F_T3F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); - m_enum = eVF_P3F_C4F_T2F_T3F; - break; - case eVF_P3F_C4F_T2F_T3F_T3F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); - m_enum = eVF_P3F_C4F_T2F_T3F_T3F; - break; - case eVF_P3F_C4F_T2F_T1F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); - m_enum = eVF_P3F_C4F_T2F_T1F; - break; - case eVF_P3F_C4F_T2F_T1F_T3F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); - m_enum = eVF_P3F_C4F_T2F_T1F_T3F; - break; - case eVF_P3F_C4F_T2F_T1F_T3F_T3F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); - m_enum = eVF_P3F_C4F_T2F_T1F_T3F_T3F; - break; - case eVF_P3F_C4F_T4F_T2F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - m_enum = eVF_P3F_C4F_T4F_T2F; - break; - case eVF_P3F_C4F_T4F_T2F_T3F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); - m_enum = eVF_P3F_C4F_T4F_T2F_T3F; - break; - case eVF_P3F_C4F_T4F_T2F_T3F_T3F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); - m_enum = eVF_P3F_C4F_T4F_T2F_T3F_T3F; - break; - case eVF_P3F_C4F_T4F_T2F_T1F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); - m_enum = eVF_P3F_C4F_T4F_T2F_T1F; - break; - case eVF_P3F_C4F_T4F_T2F_T1F_T3F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); - m_enum = eVF_P3F_C4F_T4F_T2F_T1F_T3F; - break; - case eVF_P3F_C4F_T4F_T2F_T1F_T3F_T3F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); - m_enum = eVF_P3F_C4F_T4F_T2F_T1F_T3F_T3F; - break; - case eVF_P3F_C4F_T2F_T2F_T1F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); - m_enum = eVF_P3F_C4F_T2F_T2F_T1F; - break; - case eVF_P3F_C4F_T2F_T2F_T1F_T3F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); - m_enum = eVF_P3F_C4F_T2F_T2F_T1F_T3F; - break; - case eVF_P3F_C4F_T2F_T2F_T1F_T3F_T3F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); - m_enum = eVF_P3F_C4F_T2F_T2F_T1F_T3F_T3F; - break; - case eVF_P3F_C4F_T2F_T2F_T1F_T1F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); - m_enum = eVF_P3F_C4F_T2F_T2F_T1F_T1F; - break; - case eVF_P3F_C4F_T2F_T2F_T1F_T1F_T3F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); - m_enum = eVF_P3F_C4F_T2F_T2F_T1F_T1F_T3F; - break; - case eVF_P3F_C4F_T2F_T2F_T1F_T1F_T3F_T3F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); - m_enum = eVF_P3F_C4F_T2F_T2F_T1F_T1F_T3F_T3F; - break; - case eVF_P4F_T2F_C4F_T4F_T4F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - m_enum = eVF_P4F_T2F_C4F_T4F_T4F; - break; - case eVF_P3F_C4F_T2F_T4F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - m_enum = eVF_P3F_C4F_T2F_T4F; - break; - case eVF_P3F_C4F_T2F_T3F_T4F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - m_enum = eVF_P3F_C4F_T2F_T3F_T4F; - break; - case eVF_P3F_C4F_T2F_T3F_T3F_T4F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - m_enum = eVF_P3F_C4F_T2F_T3F_T3F_T4F; - break; - case eVF_P3F_C4F_T2F_T1F_T4F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - m_enum = eVF_P3F_C4F_T2F_T1F_T4F; - break; - case eVF_P3F_C4F_T2F_T1F_T3F_T4F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - m_enum = eVF_P3F_C4F_T2F_T1F_T3F_T4F; - break; - case eVF_P3F_C4F_T2F_T1F_T3F_T3F_T4F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - m_enum = eVF_P3F_C4F_T2F_T1F_T3F_T3F_T4F; - break; - case eVF_P3F_C4F_T4F_T2F_T4F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - m_enum = eVF_P3F_C4F_T4F_T2F_T4F; - break; - case eVF_P3F_C4F_T4F_T2F_T3F_T4F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - m_enum = eVF_P3F_C4F_T4F_T2F_T3F_T4F; - break; - case eVF_P3F_C4F_T4F_T2F_T3F_T3F_T4F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - m_enum = eVF_P3F_C4F_T4F_T2F_T3F_T3F_T4F; - break; - case eVF_P3F_C4F_T4F_T2F_T1F_T4F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - m_enum = eVF_P3F_C4F_T4F_T2F_T1F_T4F; - break; - case eVF_P3F_C4F_T4F_T2F_T1F_T3F_T4F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - m_enum = eVF_P3F_C4F_T4F_T2F_T1F_T3F_T4F; - break; - case eVF_P3F_C4F_T4F_T2F_T1F_T3F_T3F_T4F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - m_enum = eVF_P3F_C4F_T4F_T2F_T1F_T3F_T3F_T4F; - break; - case eVF_P3F_C4F_T2F_T2F_T1F_T4F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - m_enum = eVF_P3F_C4F_T2F_T2F_T1F_T4F; - break; - case eVF_P3F_C4F_T2F_T2F_T1F_T3F_T4F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - m_enum = eVF_P3F_C4F_T2F_T2F_T1F_T3F_T4F; - break; - case eVF_P3F_C4F_T2F_T2F_T1F_T3F_T3F_T4F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - m_enum = eVF_P3F_C4F_T2F_T2F_T1F_T3F_T3F_T4F; - break; - case eVF_P3F_C4F_T2F_T2F_T1F_T1F_T4F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - m_enum = eVF_P3F_C4F_T2F_T2F_T1F_T1F_T4F; - break; - case eVF_P3F_C4F_T2F_T2F_T1F_T1F_T3F_T4F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - m_enum = eVF_P3F_C4F_T2F_T2F_T1F_T1F_T3F_T4F; - break; - case eVF_P3F_C4F_T2F_T2F_T1F_T1F_T3F_T3F_T4F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - m_enum = eVF_P3F_C4F_T2F_T2F_T1F_T1F_T3F_T3F_T4F; - break; - case eVF_P4F_T2F_C4F_T4F_T4F_T4F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - m_enum = eVF_P4F_T2F_C4F_T4F_T4F_T4F; - break; - case eVF_P3F_C4F_T2F_T4F_T4F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - m_enum = eVF_P3F_C4F_T2F_T4F_T4F; - break; - case eVF_P3F_C4F_T2F_T3F_T4F_T4F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - m_enum = eVF_P3F_C4F_T2F_T3F_T4F_T4F; - break; - case eVF_P3F_C4F_T2F_T3F_T3F_T4F_T4F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - m_enum = eVF_P3F_C4F_T2F_T3F_T3F_T4F_T4F; - break; - case eVF_P3F_C4F_T2F_T1F_T4F_T4F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - m_enum = eVF_P3F_C4F_T2F_T1F_T4F_T4F; - break; - case eVF_P3F_C4F_T2F_T1F_T3F_T4F_T4F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - m_enum = eVF_P3F_C4F_T2F_T1F_T3F_T4F_T4F; - break; - case eVF_P3F_C4F_T2F_T1F_T3F_T3F_T4F_T4F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - m_enum = eVF_P3F_C4F_T2F_T1F_T3F_T3F_T4F_T4F; - break; - case eVF_P3F_C4F_T4F_T2F_T4F_T4F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - m_enum = eVF_P3F_C4F_T4F_T2F_T4F_T4F; - break; - case eVF_P3F_C4F_T4F_T2F_T3F_T4F_T4F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - m_enum = eVF_P3F_C4F_T4F_T2F_T3F_T4F_T4F; - break; - case eVF_P3F_C4F_T4F_T2F_T3F_T3F_T4F_T4F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - m_enum = eVF_P3F_C4F_T4F_T2F_T3F_T3F_T4F_T4F; - break; - case eVF_P3F_C4F_T4F_T2F_T1F_T4F_T4F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - m_enum = eVF_P3F_C4F_T4F_T2F_T1F_T4F_T4F; - break; - case eVF_P3F_C4F_T4F_T2F_T1F_T3F_T4F_T4F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - m_enum = eVF_P3F_C4F_T4F_T2F_T1F_T3F_T4F_T4F; - break; - case eVF_P3F_C4F_T4F_T2F_T1F_T3F_T3F_T4F_T4F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - m_enum = eVF_P3F_C4F_T4F_T2F_T1F_T3F_T3F_T4F_T4F; - break; - case eVF_P3F_C4F_T2F_T2F_T1F_T4F_T4F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - m_enum = eVF_P3F_C4F_T2F_T2F_T1F_T4F_T4F; - break; - case eVF_P3F_C4F_T2F_T2F_T1F_T3F_T4F_T4F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - m_enum = eVF_P3F_C4F_T2F_T2F_T1F_T3F_T4F_T4F; - break; - case eVF_P3F_C4F_T2F_T2F_T1F_T3F_T3F_T4F_T4F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - m_enum = eVF_P3F_C4F_T2F_T2F_T1F_T3F_T3F_T4F_T4F; - break; - case eVF_P3F_C4F_T2F_T2F_T1F_T1F_T4F_T4F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - m_enum = eVF_P3F_C4F_T2F_T2F_T1F_T1F_T4F_T4F; - break; - case eVF_P3F_C4F_T2F_T2F_T1F_T1F_T3F_T4F_T4F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - m_enum = eVF_P3F_C4F_T2F_T2F_T1F_T1F_T3F_T4F_T4F; - break; - case eVF_P3F_C4F_T2F_T2F_T1F_T1F_T3F_T3F_T4F_T4F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - m_enum = eVF_P3F_C4F_T2F_T2F_T1F_T1F_T3F_T3F_T4F_T4F; - break; - case eVF_P4F_T2F_C4F_T4F_T4F_T4F_T4F: - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); - m_enum = eVF_P4F_T2F_C4F_T4F_T4F_T4F_T4F; - break; case eVF_Max: default: AZ_Error("VF", false, "Invalid vertex format"); @@ -854,115 +213,19 @@ namespace AZ static const uint8 kHas16BitFloatTexCoords = 0x2; static const uint8 kHas32BitFloatTexCoords = 0x1; - - //! Helper function to check to see if the vertex format has a position attribute that uses 16 bit floats for the underlying type - bool Has16BitFloatPosition() const - { - return (m_flags & kHas16BitFloatPosition) != 0x0; - } - - //! Helper function to check to see if the vertex format has a texture coordinate attribute that uses 16 bit floats for the underlying type - bool Has16BitFloatTextureCoordinates() const - { - return (m_flags & kHas16BitFloatTexCoords) != 0x0; - } - - //! Helper function to check to see if the vertex format has a texture coordinate attribute that uses 32 bit floats for the underlying type - bool Has32BitFloatTextureCoordinates() const - { - return (m_flags & kHas32BitFloatTexCoords) != 0x0; - } - uint32 GetAttributeUsageCount(AttributeUsage usage) const { return (uint32)m_attributeUsageCounts[(uint)usage]; } - bool TryGetAttributeOffsetAndType(AttributeUsage usage, uint32 index, uint& outOffset, AttributeType& outType) const - { - outOffset = 0; - outType = AttributeType::NumTypes; - for (uint ii=0; ii < m_numAttributes; ++ii) - { - uint8 attribute = m_vertexAttributes[ii]; - if (Attribute::GetUsage(attribute) == usage) - { - if (index == 0) - { - outType = Attribute::GetType(attribute); - return true; - } - else - { - --index; - } - } - outOffset += Attribute::GetByteLength(attribute); - } - return false; - } - - uint8 GetAttributeByteLength(AttributeUsage usage) const - { - for (uint ii = 0; ii < m_numAttributes; ++ii) - { - uint8 attribute = m_vertexAttributes[ii]; - if (Attribute::GetUsage(attribute) == usage) - { - return Attribute::GetByteLength(attribute); - } - } - return 0; - } - - const uint8* GetAttributes( uint32 &outCount) const { outCount = m_numAttributes; return m_vertexAttributes; } - //! Return true if the vertex format is a superset of the input - bool IsSupersetOf(const AZ::Vertex::Format& input) const - { - uint32 count = 0; - const uint8* attributes = input.GetAttributes(count); - for ( uint8 ii=0; ii(stride); } - + #ifdef PARTICLE_MOTION_BLUR @@ -1056,34 +319,5 @@ namespace AZ uint8 m_flags = 0x0; }; - - // bNeedNormals=1 - float normals; bNeedNormals=2 - byte normals //waltont TODO (this was copied as is from vertexformats.h) this comment is out of date and the function does not even use all the parameters. This should be replaceable with the new vertex class, and should be replaced when refactoring CHWShader_D3D::mfVertexFormat which handles the shader parsing/serialization - _inline Format VertFormatForComponents([[maybe_unused]] bool bNeedCol, [[maybe_unused]] bool bHasTC, bool bHasTC2, bool bHasPS, bool bHasNormal) - { - AZ::Vertex::Format RequestedVertFormat; - - if (bHasPS) - { - RequestedVertFormat = AZ::Vertex::Format(eVF_P3F_C4B_T4B_N3F2); - } - else - if (bHasNormal) - { - RequestedVertFormat = AZ::Vertex::Format(eVF_P3S_N4B_C4B_T2S); - } - else - { - if (!bHasTC2) - { - RequestedVertFormat = AZ::Vertex::Format(eVF_P3S_C4B_T2S); - } - else - { - RequestedVertFormat = AZ::Vertex::Format(eVF_P3F_C4B_T2F_T2F); - } - } - - return RequestedVertFormat; - } } } diff --git a/Code/Legacy/CryCommon/VertexFormats.h b/Code/Legacy/CryCommon/VertexFormats.h index 2231d4dfd0..8f5d0f0923 100644 --- a/Code/Legacy/CryCommon/VertexFormats.h +++ b/Code/Legacy/CryCommon/VertexFormats.h @@ -7,12 +7,9 @@ */ -#ifndef CRYINCLUDE_CRYCOMMON_VERTEXFORMATS_H -#define CRYINCLUDE_CRYCOMMON_VERTEXFORMATS_H - #pragma once -#include +#include // Stream Configuration options #define ENABLE_NORMALSTREAM_SUPPORT 1 @@ -22,94 +19,16 @@ enum EVertexFormat : uint8 // Base stream eVF_P3F_C4B_T2F, - eVF_P3F_C4B_T2F_T2F, eVF_P3S_C4B_T2S, - eVF_P3S_C4B_T2S_T2S, // For UV2 support - eVF_P3S_N4B_C4B_T2S, - - eVF_P3F_C4B_T4B_N3F2, // Particles. - eVF_TP3F_C4B_T2F, // Fonts (28 bytes). - eVF_TP3F_T2F_T3F, // Miscellaneus. - eVF_P3F_T3F, // Miscellaneus. (AuxGeom) - eVF_P3F_T2F_T3F, // Miscellaneus. // Additional streams - eVF_T2F, // Light maps TC (8 bytes). eVF_W4B_I4S, // Skinned weights/indices stream. - eVF_C4B_C4B, // SH coefficients. - eVF_P3F_P3F_I4B, // Shape deformation stream. eVF_P3F, // Velocity stream. - eVF_C4B_T2S, // General (Position is merged with Tangent stream) - // Lens effects simulation - eVF_P2F_T4F_C4F, // primary - eVF_P2F_T4F_T4F_C4F, - eVF_P2S_N4B_C4B_T1F, - eVF_P3F_C4B_T2S, eVF_P2F_C4B_T2F_F4B, // UI eVF_P3F_C4B,// Auxiliary geometry - - - eVF_P3F_C4F_T2F, //numbering for tracking the new vertex formats and for comparison with testing 23 - eVF_P3F_C4F_T2F_T3F, - eVF_P3F_C4F_T2F_T3F_T3F, - eVF_P3F_C4F_T2F_T1F, - eVF_P3F_C4F_T2F_T1F_T3F, - eVF_P3F_C4F_T2F_T1F_T3F_T3F, - eVF_P3F_C4F_T4F_T2F, - eVF_P3F_C4F_T4F_T2F_T3F, //30 - eVF_P3F_C4F_T4F_T2F_T3F_T3F, - eVF_P3F_C4F_T4F_T2F_T1F, - eVF_P3F_C4F_T4F_T2F_T1F_T3F, - eVF_P3F_C4F_T4F_T2F_T1F_T3F_T3F, - eVF_P3F_C4F_T2F_T2F_T1F, //35 - eVF_P3F_C4F_T2F_T2F_T1F_T3F, - eVF_P3F_C4F_T2F_T2F_T1F_T3F_T3F, - eVF_P3F_C4F_T2F_T2F_T1F_T1F, - eVF_P3F_C4F_T2F_T2F_T1F_T1F_T3F, - eVF_P3F_C4F_T2F_T2F_T1F_T1F_T3F_T3F, //40 - eVF_P4F_T2F_C4F_T4F_T4F, - eVF_P3F_C4F_T2F_T4F, - eVF_P3F_C4F_T2F_T3F_T4F, - eVF_P3F_C4F_T2F_T3F_T3F_T4F, - eVF_P3F_C4F_T2F_T1F_T4F, //45 - eVF_P3F_C4F_T2F_T1F_T3F_T4F, - eVF_P3F_C4F_T2F_T1F_T3F_T3F_T4F, - eVF_P3F_C4F_T4F_T2F_T4F, - eVF_P3F_C4F_T4F_T2F_T3F_T4F, - eVF_P3F_C4F_T4F_T2F_T3F_T3F_T4F, //50 - eVF_P3F_C4F_T4F_T2F_T1F_T4F, - eVF_P3F_C4F_T4F_T2F_T1F_T3F_T4F, - eVF_P3F_C4F_T4F_T2F_T1F_T3F_T3F_T4F, - eVF_P3F_C4F_T2F_T2F_T1F_T4F, - eVF_P3F_C4F_T2F_T2F_T1F_T3F_T4F, //55 - eVF_P3F_C4F_T2F_T2F_T1F_T3F_T3F_T4F, - eVF_P3F_C4F_T2F_T2F_T1F_T1F_T4F, - eVF_P3F_C4F_T2F_T2F_T1F_T1F_T3F_T4F, - eVF_P3F_C4F_T2F_T2F_T1F_T1F_T3F_T3F_T4F, - eVF_P4F_T2F_C4F_T4F_T4F_T4F, //60 - eVF_P3F_C4F_T2F_T4F_T4F, - eVF_P3F_C4F_T2F_T3F_T4F_T4F, - eVF_P3F_C4F_T2F_T3F_T3F_T4F_T4F, - eVF_P3F_C4F_T2F_T1F_T4F_T4F, - eVF_P3F_C4F_T2F_T1F_T3F_T4F_T4F, //65 - eVF_P3F_C4F_T2F_T1F_T3F_T3F_T4F_T4F, - eVF_P3F_C4F_T4F_T2F_T4F_T4F, - eVF_P3F_C4F_T4F_T2F_T3F_T4F_T4F, - eVF_P3F_C4F_T4F_T2F_T3F_T3F_T4F_T4F, - eVF_P3F_C4F_T4F_T2F_T1F_T4F_T4F, //70 - eVF_P3F_C4F_T4F_T2F_T1F_T3F_T4F_T4F, - eVF_P3F_C4F_T4F_T2F_T1F_T3F_T3F_T4F_T4F, - eVF_P3F_C4F_T2F_T2F_T1F_T4F_T4F, - eVF_P3F_C4F_T2F_T2F_T1F_T3F_T4F_T4F, - eVF_P3F_C4F_T2F_T2F_T1F_T3F_T3F_T4F_T4F, //75 - eVF_P3F_C4F_T2F_T2F_T1F_T1F_T4F_T4F, - eVF_P3F_C4F_T2F_T2F_T1F_T1F_T3F_T4F_T4F, - eVF_P3F_C4F_T2F_T2F_T1F_T1F_T3F_T3F_T4F_T4F, - eVF_P4F_T2F_C4F_T4F_T4F_T4F_T4F, - eVF_Max, }; @@ -143,8 +62,6 @@ struct UCol (bcolor[2] - 128.0f) / 127.5f ); } - - AUTO_STRUCT_INFO }; struct Vec3f16 @@ -242,14 +159,6 @@ struct SVF_P3F_C4B_T2F Vec2 st; }; -struct SVF_P3F_C4B_T2F_T2F -{ - Vec3 xyz; - UCol color; - Vec2 st; - Vec2 st2; -}; - struct SVF_P2F_C4B_T2F_F4B { Vec2 xy; @@ -261,743 +170,23 @@ struct SVF_P2F_C4B_T2F_F4B uint8 pad; }; -struct SVF_TP3F_C4B_T2F //Fonts -{ - Vec4 pos; - UCol color; - Vec2 st; -}; struct SVF_P3S_C4B_T2S { Vec3f16 xyz; UCol color; Vec2f16 st; - - AUTO_STRUCT_INFO }; -struct SVF_P3S_C4B_T2S_T2S -{ - Vec3f16 xyz; - UCol color; - Vec2f16 st; - Vec2f16 st2; - - AUTO_STRUCT_INFO -}; - -struct SVF_P3F_C4B_T2S -{ - Vec3 xyz; - UCol color; - Vec2f16 st; -}; - -struct SVF_P3S_N4B_C4B_T2S -{ - Vec3f16 xyz; - UCol normal; - UCol color; - Vec2f16 st; -}; - -struct SVF_P2S_N4B_C4B_T1F -{ - CryHalf2 xy; - UCol normal; - UCol color; - float z; -}; - -struct SVF_T2F -{ - Vec2 st; -}; struct SVF_W4B_I4S { UCol weights; uint16 indices[4]; }; -struct SVF_C4B_C4B -{ - UCol coef0; - UCol coef1; -}; -struct SVF_P3F_P3F_I4B -{ - Vec3 thin; - Vec3 fat; - UCol index; -}; + struct SVF_P3F { Vec3 xyz; }; -struct SVF_P3F_T3F -{ - Vec3 p; - Vec3 st; -}; -struct SVF_P3F_T2F_T3F -{ - Vec3 p; - Vec2 st0; - Vec3 st1; -}; -struct SVF_TP3F_T2F_T3F -{ - Vec4 p; - Vec2 st0; - Vec3 st1; -}; -struct SVF_P2F_T4F_C4F -{ - Vec2 p; - Vec4 st; - Vec4 color; -}; - -struct SVF_P2F_T4F_T4F_C4F -{ - Vec2 p; - Vec4 st; - Vec4 st2; - Vec4 color; -}; - -struct SVF_P3F_C4B_I4B_PS4F -{ - Vec3 xyz; - Vec2 prevXaxis; - Vec2 prevYaxis; - UCol color; - Vec3 prevPos; - struct SpriteInfo - { - uint8 tex_x, tex_y, tex_z, backlight; // xyzw - } info; - Vec2 xaxis; - Vec2 yaxis; -}; - -struct SVF_P3F_C4B_T4B_N3F2 -{ - Vec3 xyz; - UCol color; - UCol st; // st is used as a color, even though st usually refers to a TexCoord - Vec3 xaxis; - Vec3 yaxis; -#ifdef PARTICLE_MOTION_BLUR - Vec3 prevPos; - Vec3 prevXTan; - Vec3 prevYTan; -#endif -}; - -struct SVF_C4B_T2S -{ - UCol color; - Vec2f16 st; -}; - -struct SVF_P3F_C4F_T2F -{ - Vec3 xyz; - Vec4 color; - Vec2 st; -}; - -struct SVF_P3F_C4F_T2F_T3F -{ - Vec3 xyz; - Vec4 color; - Vec2 st0; - Vec3 st1; -}; - -struct SVF_P3F_C4F_T2F_T3F_T3F -{ - Vec3 xyz; - Vec4 color; - Vec2 st0; - Vec3 st1; - Vec3 st2; -}; - -struct SVF_P3F_C4F_T2F_T1F -{ - Vec3 xyz; - Vec4 color; - Vec2 st; - float z; -}; - -struct SVF_P3F_C4F_T2F_T1F_T3F -{ - Vec3 xyz; - Vec4 color; - Vec2 st0; - float z; - Vec3 st1; -}; - -struct SVF_P3F_C4F_T2F_T1F_T3F_T3F -{ - Vec3 xyz; - Vec4 color; - Vec2 st0; - float z; - Vec3 st1; - Vec3 st2; -}; - - -struct SVF_P3F_C4F_T4F_T2F -{ - Vec3 xyz; - Vec4 color; - Vec4 st0; - Vec2 st1; -}; - -struct SVF_P3F_C4F_T4F_T2F_T3F -{ - Vec3 xyz; - Vec4 color; - Vec4 st0; - Vec2 st1; - Vec3 st2; -}; - -struct SVF_P3F_C4F_T4F_T2F_T3F_T3F -{ - Vec3 xyz; - Vec4 color; - Vec4 st0; - Vec2 st1; - Vec3 st2; - Vec3 st3; -}; - -struct SVF_P3F_C4F_T4F_T2F_T1F -{ - Vec3 xyz; - Vec4 color; - Vec4 st0; - Vec2 st1; - float z; -}; - -struct SVF_P3F_C4F_T4F_T2F_T1F_T3F -{ - Vec3 xyz; - Vec4 color; - Vec4 st0; - Vec2 st1; - float z; - Vec3 st2; -}; - -struct SVF_P3F_C4F_T4F_T2F_T1F_T3F_T3F -{ - Vec3 xyz; - Vec4 color; - Vec4 st0; - Vec2 st1; - float z; - Vec3 st2; - Vec3 st3; -}; - -struct SVF_P3F_C4F_T2F_T2F_T1F -{ - Vec3 xyz; - Vec4 color; - Vec2 st0; - Vec2 st1; - float z; -}; - -struct SVF_P3F_C4F_T2F_T2F_T1F_T3F -{ - Vec3 xyz; - Vec4 color; - Vec2 st0; - Vec2 st1; - float z; - Vec3 st2; -}; - -struct SVF_P3F_C4F_T2F_T2F_T1F_T3F_T3F -{ - Vec3 xyz; - Vec4 color; - Vec2 st0; - Vec2 st1; - float z; - Vec3 st2; - Vec3 st3; -}; - -struct SVF_P3F_C4F_T2F_T2F_T1F_T1F -{ - Vec3 xyz; - Vec4 color; - Vec2 st0; - Vec2 st1; - float z0; - float z1; -}; - -struct SVF_P3F_C4F_T2F_T2F_T1F_T1F_T3F -{ - Vec3 xyz; - Vec4 color; - Vec2 st0; - Vec2 st1; - float z0; - float z1; - Vec3 st2; -}; - -struct SVF_P3F_C4F_T2F_T2F_T1F_T1F_T3F_T3F -{ - Vec3 xyz; - Vec4 color; - Vec2 st0; - Vec2 st1; - float z0; - float z1; - Vec3 st2; - Vec3 st3; -}; - -struct SVF_P4F_T2F_C4F_T4F_T4F -{ - Vec4 xyzw; - Vec2 st0; - Vec4 color; - Vec4 st1; - Vec4 st2; -}; - -struct SVF_P3F_C4F_T2F_T4F -{ - Vec3 xyz; - Vec4 color; - Vec2 st0; - Vec4 st1; -}; - -struct SVF_P3F_C4F_T2F_T3F_T4F -{ - Vec3 xyz; - Vec4 color; - Vec2 st0; - Vec3 st1; - Vec4 st2; -}; - -struct SVF_P3F_C4F_T2F_T3F_T3F_T4F -{ - Vec3 xyz; - Vec4 color; - Vec2 st0; - Vec3 st1; - Vec3 st2; - Vec4 st3; -}; - -struct SVF_P3F_C4F_T2F_T1F_T4F -{ - Vec3 xyz; - Vec4 color; - Vec2 st0; - float z; - Vec4 st1; -}; - -struct SVF_P3F_C4F_T2F_T1F_T3F_T4F -{ - Vec3 xyz; - Vec4 color; - Vec2 st0; - float z; - Vec3 st1; - Vec4 st2; -}; - -struct SVF_P3F_C4F_T2F_T1F_T3F_T3F_T4F -{ - Vec3 xyz; - Vec4 color; - Vec2 st0; - float z; - Vec3 st1; - Vec3 st2; - Vec4 st3; -}; - -struct SVF_P3F_C4F_T4F_T2F_T4F -{ - Vec3 xyz; - Vec4 color; - Vec4 st0; - Vec2 st1; - Vec4 st2; -}; - -struct SVF_P3F_C4F_T4F_T2F_T3F_T4F -{ - Vec3 xyz; - Vec4 color; - Vec4 st0; - Vec2 st1; - Vec3 st2; - Vec4 st3; -}; - -struct SVF_P3F_C4F_T4F_T2F_T3F_T3F_T4F -{ - Vec3 xyz; - Vec4 color; - Vec4 st0; - Vec2 st1; - Vec3 st2; - Vec3 st3; - Vec4 st4; -}; - -struct SVF_P3F_C4F_T4F_T2F_T1F_T4F -{ - Vec3 xyz; - Vec4 color; - Vec4 st0; - Vec2 st1; - float z; - Vec4 st2; -}; - -struct SVF_P3F_C4F_T4F_T2F_T1F_T3F_T4F -{ - Vec3 xyz; - Vec4 color; - Vec4 st0; - Vec2 st1; - float z; - Vec3 st2; - Vec4 st3; -}; - -struct SVF_P3F_C4F_T4F_T2F_T1F_T3F_T3F_T4F -{ - Vec3 xyz; - Vec4 color; - Vec4 st0; - Vec2 st1; - float z; - Vec3 st2; - Vec3 st3; - Vec4 st4; -}; - -struct SVF_P3F_C4F_T2F_T2F_T1F_T4F -{ - Vec3 xyz; - Vec4 color; - Vec2 st0; - Vec2 st1; - float z; - Vec4 st2; -}; - -struct SVF_P3F_C4F_T2F_T2F_T1F_T3F_T4F -{ - Vec3 xyz; - Vec4 color; - Vec2 st0; - Vec2 st1; - float z; - Vec3 st2; - Vec4 st3; -}; - -struct SVF_P3F_C4F_T2F_T2F_T1F_T3F_T3F_T4F -{ - Vec3 xyz; - Vec4 color; - Vec2 st0; - Vec2 st1; - float z; - Vec3 st2; - Vec3 st3; - Vec4 st4; -}; - -struct SVF_P3F_C4F_T2F_T2F_T1F_T1F_T4F -{ - Vec3 xyz; - Vec4 color; - Vec2 st0; - Vec2 st1; - float z0; - float z1; - Vec4 st2; -}; - -struct SVF_P3F_C4F_T2F_T2F_T1F_T1F_T3F_T4F -{ - Vec3 xyz; - Vec4 color; - Vec2 st0; - Vec2 st1; - float z0; - float z1; - Vec3 st2; - Vec4 st3; -}; - -struct SVF_P3F_C4F_T2F_T2F_T1F_T1F_T3F_T3F_T4F -{ - Vec3 xyz; - Vec4 color; - Vec2 st0; - Vec2 st1; - float z0; - float z1; - Vec3 st2; - Vec3 st3; - Vec4 st4; -}; - -struct SVF_P4F_T2F_C4F_T4F_T4F_T4F -{ - Vec4 xyzw; - Vec2 st0; - Vec4 color; - Vec4 st1; - Vec4 st2; - Vec4 st3; -}; - -struct SVF_P3F_C4F_T2F_T4F_T4F -{ - Vec3 xyz; - Vec4 color; - Vec2 st0; - Vec4 st1; - Vec4 st2; -}; - -struct SVF_P3F_C4F_T2F_T3F_T4F_T4F -{ - Vec3 xyz; - Vec4 color; - Vec2 st0; - Vec3 st1; - Vec4 st2; - Vec4 st3; -}; - -struct SVF_P3F_C4F_T2F_T3F_T3F_T4F_T4F -{ - Vec3 xyz; - Vec4 color; - Vec2 st0; - Vec3 st1; - Vec3 st2; - Vec4 st3; - Vec4 st4; -}; - -struct SVF_P3F_C4F_T2F_T1F_T4F_T4F -{ - Vec3 xyz; - Vec4 color; - Vec2 st0; - float z; - Vec4 st1; - Vec4 st2; -}; - -struct SVF_P3F_C4F_T2F_T1F_T3F_T4F_T4F -{ - Vec3 xyz; - Vec4 color; - Vec2 st0; - float z; - Vec3 st1; - Vec4 st2; - Vec4 st3; -}; - -struct SVF_P3F_C4F_T2F_T1F_T3F_T3F_T4F_T4F -{ - Vec3 xyz; - Vec4 color; - Vec2 st0; - float z; - Vec3 st1; - Vec3 st2; - Vec4 st3; - Vec4 st4; -}; - -struct SVF_P3F_C4F_T4F_T2F_T4F_T4F -{ - Vec3 xyz; - Vec4 color; - Vec4 st0; - Vec2 st1; - Vec4 st2; - Vec4 st3; -}; - -struct SVF_P3F_C4F_T4F_T2F_T3F_T4F_T4F -{ - Vec3 xyz; - Vec4 color; - Vec4 st0; - Vec2 st1; - Vec3 st2; - Vec4 st3; - Vec4 st4; -}; - -struct SVF_P3F_C4F_T4F_T2F_T3F_T3F_T4F_T4F -{ - Vec3 xyz; - Vec4 color; - Vec4 st0; - Vec2 st1; - Vec3 st2; - Vec3 st3; - Vec4 st4; - Vec4 st5; -}; - -struct SVF_P3F_C4F_T4F_T2F_T1F_T4F_T4F -{ - Vec3 xyz; - Vec4 color; - Vec4 st0; - Vec2 st1; - float z; - Vec4 st2; - Vec4 st3; -}; - -struct SVF_P3F_C4F_T4F_T2F_T1F_T3F_T4F_T4F -{ - Vec3 xyz; - Vec4 color; - Vec4 st0; - Vec2 st1; - float z; - Vec3 st2; - Vec4 st3; - Vec4 st4; -}; - -struct SVF_P3F_C4F_T4F_T2F_T1F_T3F_T3F_T4F_T4F -{ - Vec3 xyz; - Vec4 color; - Vec4 st0; - Vec2 st1; - float z; - Vec3 st2; - Vec3 st3; - Vec4 st4; - Vec4 st5; -}; - -struct SVF_P3F_C4F_T2F_T2F_T1F_T4F_T4F -{ - Vec3 xyz; - Vec4 color; - Vec2 st0; - Vec2 st1; - float z; - Vec4 st2; - Vec4 st3; -}; - -struct SVF_P3F_C4F_T2F_T2F_T1F_T3F_T4F_T4F -{ - Vec3 xyz; - Vec4 color; - Vec2 st0; - Vec2 st1; - float z; - Vec3 st2; - Vec4 st3; - Vec4 st4; -}; - -struct SVF_P3F_C4F_T2F_T2F_T1F_T3F_T3F_T4F_T4F -{ - Vec3 xyz; - Vec4 color; - Vec2 st0; - Vec2 st1; - float z; - Vec3 st2; - Vec3 st3; - Vec4 st4; - Vec4 st5; -}; - -struct SVF_P3F_C4F_T2F_T2F_T1F_T1F_T4F_T4F -{ - Vec3 xyz; - Vec4 color; - Vec2 st0; - Vec2 st1; - float z0; - float z1; - Vec4 st2; - Vec4 st3; -}; - -struct SVF_P3F_C4F_T2F_T2F_T1F_T1F_T3F_T4F_T4F -{ - Vec3 xyz; - Vec4 color; - Vec2 st0; - Vec2 st1; - float z0; - float z1; - Vec3 st2; - Vec4 st3; - Vec4 st4; -}; - -struct SVF_P3F_C4F_T2F_T2F_T1F_T1F_T3F_T3F_T4F_T4F -{ - Vec3 xyz; - Vec4 color; - Vec2 st0; - Vec2 st1; - float z0; - float z1; - Vec3 st2; - Vec3 st3; - Vec4 st4; - Vec4 st5; -}; - -struct SVF_P4F_T2F_C4F_T4F_T4F_T4F_T4F -{ - Vec4 xyzw; - Vec2 st0; - Vec4 color; - Vec4 st1; - Vec4 st2; - Vec4 st3; - Vec4 st4; -}; - //============================================================= // Signed norm value packing [-1,+1] @@ -1240,8 +429,6 @@ public: *this = SPipTangents(tng3, btg3, PackingSNorm::tPackB2S(Tangent.w)); } - - friend struct SMeshTangents; }; struct SPipQTangents @@ -1290,8 +477,6 @@ public: const Quat q = GetQ(); return q.GetColumn2() * (q.w < 0.0f ? -1.0f : +1.0f); } - - friend struct SMeshQTangents; }; struct SPipNormal @@ -1328,8 +513,6 @@ struct SPipNormal // normalize in case "trn" wasn't length-preserving *this = SPipNormal(trn.TransformVector(*this).normalize()); } - - friend struct SMeshNormal; }; //================================================================================================== @@ -1364,24 +547,4 @@ enum EStreamIDs VSF_MORPHBUDDY_WEIGHTS = 15, // Morphing weights }; -// Stream Masks (Used during updating) -enum EStreamMasks -{ - VSM_GENERAL = 1 << VSF_GENERAL, - VSM_TANGENTS = ((1 << VSF_TANGENTS) | (1 << VSF_QTANGENTS)), - VSM_HWSKIN = 1 << VSF_HWSKIN_INFO, - VSM_VERTEX_VELOCITY = 1 << VSF_VERTEX_VELOCITY, -# if ENABLE_NORMALSTREAM_SUPPORT - VSM_NORMALS = 1 << VSF_NORMALS, -#endif - - VSM_MORPHBUDDY = 1 << VSF_MORPHBUDDY, - VSM_INSTANCED = 1 << VSF_INSTANCED, - - VSM_MASK = ((1 << VSF_NUM) - 1), -}; - //================================================================================================================== - -#endif // CRYINCLUDE_CRYCOMMON_VERTEXFORMATS_H - diff --git a/Code/Legacy/CryCommon/crycommon_files.cmake b/Code/Legacy/CryCommon/crycommon_files.cmake index 7131eb7207..2f5030ccc4 100644 --- a/Code/Legacy/CryCommon/crycommon_files.cmake +++ b/Code/Legacy/CryCommon/crycommon_files.cmake @@ -7,18 +7,15 @@ # set(FILES - CryCommon.cpp IAudioInterfacesCommonData.h IAudioSystem.h ICmdLine.h IConsole.h IEntityRenderState.h - IEntityRenderState_info.cpp IFont.h IFunctorBase.h IGem.h IIndexedMesh.h - IIndexedMesh_info.cpp ILevelSystem.h ILocalizationManager.h LocalizationManagerBus.h @@ -27,19 +24,15 @@ set(FILES IMaterial.h IMiniLog.h IMovieSystem.h - IPhysics.h - IPostEffectGroup.h IProcess.h IReadWriteXMLSink.h IRenderAuxGeom.h IRenderer.h - IRenderMesh.h ISerialize.h IShader.h ISplines.h IStatObj.h StatObjBus.h - IStereoRenderer.h ISurfaceType.h ISystem.h ITexture.h @@ -49,42 +42,31 @@ set(FILES IWindowMessageHandler.h IXml.h MicrophoneBus.h - physinterface.h HMDBus.h VRCommon.h - StereoRendererBus.h INavigationSystem.h IMNM.h SFunctor.h FunctorBaseFunction.h FunctorBaseMember.h - stridedptr.h - Options.h SerializationTypes.h CryEndian.h CryRandomInternal.h Random.h LCGRandom.h - CryTypeInfo.cpp BaseTypes.h - MemoryAccess.h AnimKey.h BitFiddling.h Common_TypeInfo.cpp - CryArray.h CryAssert.h CryCrc32.h - CryCustomTypes.h CryFile.h - CryHeaders.h - CryHeaders_info.cpp CryListenerSet.h CryLegacyAllocator.h CryPath.h CryPodArray.h CrySizer.h CrySystemBus.h - CryTypeInfo.h CryVersion.h LegacyAllocator.cpp LegacyAllocator.h @@ -93,7 +75,6 @@ set(FILES MultiThread_Containers.h NullAudioSystem.h PNoise3.h - primitives.h ProjectDefines.h Range.h ScopedVariableSetter.h @@ -102,14 +83,9 @@ set(FILES smartptr.h StlUtils.h Synchronization.h - Tarray.h Timer.h TimeValue.h - TimeValue_info.h - TypeInfo_decl.h - TypeInfo_impl.h VectorMap.h - VectorSet.h VertexFormats.h XMLBinaryHeaders.h RenderBus.h @@ -123,13 +99,11 @@ set(FILES Cry_Geo.h Cry_GeoDistance.h Cry_GeoIntersect.h - Cry_GeoOverlap.h Cry_Math.h Cry_Quat.h Cry_ValidNumber.h Cry_Vector2.h Cry_Vector3.h - CryHalf_info.h CryHalf.inl MathConversion.h Cry_HWMatrix.h diff --git a/Code/Legacy/CryCommon/physinterface.h b/Code/Legacy/CryCommon/physinterface.h deleted file mode 100644 index 06d07af82b..0000000000 --- a/Code/Legacy/CryCommon/physinterface.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - -// Description : declarations of all physics interfaces and structures -#pragma once - - -#include - -#include "Cry_Geo.h" -#include "stridedptr.h" -#include "primitives.h" -#ifdef NEED_ENDIAN_SWAP - #include "CryEndian.h" -#endif - -#include -#include diff --git a/Code/Legacy/CryCommon/platform.h b/Code/Legacy/CryCommon/platform.h index 3b80079c0f..37f0636c3a 100644 --- a/Code/Legacy/CryCommon/platform.h +++ b/Code/Legacy/CryCommon/platform.h @@ -353,12 +353,6 @@ void SetFlags(T& dest, U flags, bool b) #include AZ_RESTRICTED_FILE(platform_h) #endif -// Include support for meta-type data. -#include "TypeInfo_decl.h" - -// Include array. -#include - bool CrySetFileAttributes(const char* lpFileName, uint32 dwFileAttributes); threadID CryGetCurrentThreadId(); diff --git a/Code/Legacy/CryCommon/primitives.h b/Code/Legacy/CryCommon/primitives.h deleted file mode 100644 index e44690a977..0000000000 --- a/Code/Legacy/CryCommon/primitives.h +++ /dev/null @@ -1,294 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - -#ifndef CRYINCLUDE_CRYCOMMON_PRIMITIVES_H -#define CRYINCLUDE_CRYCOMMON_PRIMITIVES_H -#pragma once - - - -typedef int index_t; -enum -{ - PHYS_MAX_INDICES = 1 << 30 -}; - -#include "stridedptr.h" - -namespace primitives { - ////////////////////////// primitives ////////////////////// - - struct primitive - { - }; - - struct box - : primitive - { - enum entype - { - type = 0 - }; - Matrix33 Basis; // v_box = Basis*v_world; Basis = Rotation.T() - int bOriented; - Vec3 center; - Vec3 size; - AUTO_STRUCT_INFO - }; - - struct triangle - : primitive - { - enum entype - { - type = 1 - }; - Vec3 pt[3]; - Vec3 n; - AUTO_STRUCT_INFO - }; - - struct indexed_triangle - : triangle - { - int idx; - AUTO_STRUCT_INFO - }; - - typedef float (* getHeightCallback)(int ix, int iy); - typedef unsigned char (* getSurfTypeCallback)(int ix, int iy); - - struct grid - : primitive - { - Matrix33 Basis; - int bOriented; - Vec3 origin; - vector2df step, stepr; - vector2di size; - vector2di stride; - int bCyclic; - grid() { bCyclic = 0; } - int inrange(int ix, int iy) { return bCyclic | -((ix - size.x & - 1 - ix & iy - size.y & - 1 - iy) >> 31); } - int getcell_safe(int ix, int iy) { int mask = -inrange(ix, iy); return (iy & size.y - 1) * stride.y + (ix & size.x - 1) * stride.x & mask | size.x * size.y & ~mask; } - int crop(int i, int icoord, int bAllowBorder = 1) { int brd = bAllowBorder + (1 << 30 & - bCyclic); return max(-brd, min(size[icoord] - 1 + brd, i)); } - vector2di cropxy(const vector2di& ic, int bAllowBorder = 1) { int brd = bAllowBorder + (1 << 30 & - bCyclic); return vector2di(max(-brd, min(size.x - 1 + brd, ic.x)), max(-brd, min(size.y - 1 + brd, ic.y))); } - int iscyclic() { return bCyclic; } - AUTO_STRUCT_INFO - }; - - struct heightfield - : grid - { - enum entype - { - type = 2 - }; - heightfield& operator=(const heightfield& src) - { - step = src.step; - stepr = src.stepr; - size = src.size; - stride = src.stride; - heightscale = src.heightscale; - typemask = src.typemask; - typehole = src.typehole; - typepower = src.typepower; - fpGetHeightCallback = src.fpGetHeightCallback; - fpGetSurfTypeCallback = src.fpGetSurfTypeCallback; - return *this; - } - - ILINE float getheight(int ix, int iy) const - { - float result = (*fpGetHeightCallback)(ix, iy); - return result * heightscale; - } - ILINE int gettype(int ix, int iy) const - { - int itype = (((*fpGetSurfTypeCallback)(ix, iy)) & typemask) >> typepower, idelta = itype - typehole; - return itype | ((idelta - 1) >> 31 ^ idelta >> 31); - } - - float heightscale; - unsigned short typemask; - int typehole; - int typepower; - getHeightCallback fpGetHeightCallback; - getSurfTypeCallback fpGetSurfTypeCallback; - }; - - struct ray - : primitive - { - enum entype - { - type = 3 - }; - Vec3 origin; - Vec3 dir; - AUTO_STRUCT_INFO - }; - - struct sphere - : primitive - { - enum entype - { - type = 4 - }; - Vec3 center; - float r; - AUTO_STRUCT_INFO - }; - - struct cylinder - : primitive - { - enum entype - { - type = 5 - }; - Vec3 center; - Vec3 axis; - float r, hh; - AUTO_STRUCT_INFO - }; - - struct capsule - : cylinder - { - enum entype - { - type = 6 - }; - AUTO_STRUCT_INFO - }; - - struct grid3d - : primitive - { - Matrix33 Basis; - int bOriented; - Vec3 origin; - Vec3 step, stepr; - Vec3i size; - Vec3i stride; - }; - - struct voxelgrid - : grid3d - { - enum entype - { - type = 7 - }; - Matrix33 R; - Vec3 offset; - float scale, rscale; - strided_pointer pVtx; - index_t* pIndices; - Vec3* pNormals; - char* pIds; - int* pCellTris; - int* pTriBuf; - }; - - struct plane - : primitive - { - enum entype - { - type = 8 - }; - Vec3 n; - Vec3 origin; - AUTO_STRUCT_INFO - }; - - struct coord_plane - : plane - { - Vec3 axes[2]; - AUTO_STRUCT_INFO - }; -} - -AUTO_TYPE_INFO(primitives::getHeightCallback) -AUTO_TYPE_INFO(primitives::getSurfTypeCallback) - -struct prim_inters -{ - prim_inters() { minPtDist2 = 0.0f; ptbest.zero(); } - Vec3 pt[2]; - Vec3 n; - unsigned char iFeature[2][2]; - float minPtDist2; - short id[2]; - int iNode[2]; - Vec3* ptborder; - int nborderpt, nbordersz; - Vec3 ptbest; - int nBestPtVal; -}; - -struct contact -{ - real t, taux; - Vec3 pt; - Vec3 n; - unsigned int iFeature[2]; -}; - -const int NPRIMS = 8; // since plane is currently not supported in collision checks - -///////////////////// geometry contact structures /////////////////// - -struct geom_contact_area -{ - enum entype - { - polygon, polyline - }; - int type; - int npt; - int nmaxpt; - float minedge; - int* piPrim[2]; - int* piFeature[2]; - Vec3* pt; - Vec3 n1; // normal of other object surface (or edge) -}; - -const int IFEAT_LOG2 = 23; -const int IDXMASK = ~(0xFF << IFEAT_LOG2); -const int TRIEND = 0x80 << IFEAT_LOG2; - -struct geom_contact -{ - real t; - Vec3 pt; - Vec3 n; - Vec3 dir; // unprojection direction - int iUnprojMode; - float vel; // original velocity along this direction, <0 if least squares normal was used - int id[2]; // external ids for colliding geometry parts - int iPrim[2]; - int iFeature[2]; - int iNode[2]; // BV-tree nodes of contacting primitives - Vec3* ptborder; // intersection border - int (*idxborder)[2]; // primitive index | primitive's feature's id << IFEAT_LOG2 - int nborderpt; - int bClosed; - Vec3 center; - bool bBorderConsecutive; - geom_contact_area* parea; -}; - -#endif // CRYINCLUDE_CRYCOMMON_PRIMITIVES_H diff --git a/Code/Legacy/CryCommon/smartptr.h b/Code/Legacy/CryCommon/smartptr.h index baf51d5030..ec2b437696 100644 --- a/Code/Legacy/CryCommon/smartptr.h +++ b/Code/Legacy/CryCommon/smartptr.h @@ -146,8 +146,6 @@ public: { std::swap(p, other.p); } - - AUTO_STRUCT_INFO }; template diff --git a/Code/Legacy/CryCommon/stridedptr.h b/Code/Legacy/CryCommon/stridedptr.h deleted file mode 100644 index 8a74aa97b1..0000000000 --- a/Code/Legacy/CryCommon/stridedptr.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - -#ifndef CRYINCLUDE_CRYCOMMON_STRIDEDPTR_H -#define CRYINCLUDE_CRYCOMMON_STRIDEDPTR_H -#pragma once - -#include -#include - -template -class strided_pointer -{ -public: - strided_pointer() - : data(0) - , iStride(sizeof(dtype)) - { - } - - strided_pointer(dtype* pdata, int32 stride = sizeof(dtype)) - : data(pdata) - , iStride(stride) - { - } - - template - strided_pointer(dtype1* pdata) - { - set(pdata, sizeof(dtype1)); - } - - template - strided_pointer(const strided_pointer& src) - { - set(src.data, src.iStride); - } - - template - ILINE strided_pointer& operator=(const strided_pointer& src) - { - set(src.data, src.iStride); - return *this; - } - - ILINE dtype& operator[](int32 idx) { return *(dtype*)((char*)data + idx * iStride); } - ILINE const dtype& operator[](int32 idx) const { return *(const dtype*)((const char*)data + idx * iStride); } - ILINE strided_pointer operator+(int32 idx) const { return strided_pointer((dtype*)((char*)data + idx * iStride), iStride); } - ILINE strided_pointer operator-(int32 idx) const { return strided_pointer((dtype*)((char*)data - idx * iStride), iStride); } - - ILINE operator bool() const - { - return data != 0; - } - -private: - template - ILINE void set(dtype1* pdata, int32 stride) - { -# if !defined(eLittleEndian) -# error eLittleEndian is not defined, please include CryEndian.h. -# endif - static_assert(metautils::is_const::value || !metautils::is_const::value); - // note: we allow xint32 -> xint16 converting - static_assert( - (metautils::is_same::type, typename metautils::remove_const::type>::value || - ((metautils::is_same::type, sint32>::value || - metautils::is_same::type, uint32>::value || - metautils::is_same::type, sint16>::value || - metautils::is_same::type, uint16>::value) && - (metautils::is_same::type, sint16>::value || - metautils::is_same::type, uint16>::value)))); - data = (dtype*)pdata + (sizeof(dtype1) / sizeof(dtype) - 1) * (int)eLittleEndian; - iStride = stride; - } - -private: - // Prevents assignment of a structure member's address by mistake: - // stridedPtrObject = &myStruct.member; - // Use explicit constructor instead: - // stridedPtrObject = strided_pointer(&myStruct.member, sizeof(myStruct)); - // - // Keep it private and non-implemented. - strided_pointer& operator=(dtype* pdata); - - // Prevents using the address directly by mistake: - // memcpy(destination, stridedPtrObject, sizeof(baseType) * n); - // Use address of the first element instead: - // memcpy(destination, &stridedPtrObject[0], stridedPtrObject.iStride * n); - // - // Keep it private and non-implemented. - operator void*() const; - - // Prevents direct dereferencing to avoid confusing it with "normal" pointers: - // val = *stridedPtrObject; - // Use operator [] instead: - // val = stridedPtrObject[0]; - // - // Keep it private and non-implemented. - dtype& operator*() const; - -public: - dtype* data; - int32 iStride; -}; - - -#endif // CRYINCLUDE_CRYCOMMON_STRIDEDPTR_H diff --git a/Code/Legacy/CrySystem/LocalizedStringManager.h b/Code/Legacy/CrySystem/LocalizedStringManager.h index 283eaa79bf..1fba05f9ac 100644 --- a/Code/Legacy/CrySystem/LocalizedStringManager.h +++ b/Code/Legacy/CrySystem/LocalizedStringManager.h @@ -10,9 +10,11 @@ #pragma once #include +#include #include #include #include +#include #include "Huffman.h" @@ -153,9 +155,9 @@ private: CryHalf fVolume; CryHalf fRadioRatio; // SoundMoods - DynArray SoundMoods; + AZStd::vector SoundMoods; // EventParameters - DynArray EventParameters; + AZStd::vector EventParameters; // ~audio specific part // subtitle & radio flags @@ -312,5 +314,3 @@ private: mutable AZStd::mutex m_cs; typedef AZStd::lock_guard AutoLock; }; - - diff --git a/Code/Legacy/CrySystem/SimpleStringPool.h b/Code/Legacy/CrySystem/SimpleStringPool.h index d1a618425c..13be471f9e 100644 --- a/Code/Legacy/CrySystem/SimpleStringPool.h +++ b/Code/Legacy/CrySystem/SimpleStringPool.h @@ -12,7 +12,7 @@ #pragma once #include "ISystem.h" - +#include #include //TODO: Pull most of this into a cpp file! @@ -265,23 +265,6 @@ public: return ret; } - void GetMemoryUsage(ICrySizer* pSizer) const - { - BLOCK* pBlock = m_blocks; - while (pBlock) - { - pSizer->AddObject(pBlock, offsetof(BLOCK, s) + pBlock->size * sizeof(char)); - pBlock = pBlock->next; - } - - pBlock = m_free_blocks; - while (pBlock) - { - pSizer->AddObject(pBlock, offsetof(BLOCK, s) + pBlock->size * sizeof(char)); - pBlock = pBlock->next; - } - } - private: CSimpleStringPool(const CSimpleStringPool&); CSimpleStringPool& operator = (const CSimpleStringPool&); diff --git a/Code/Legacy/CrySystem/System.cpp b/Code/Legacy/CrySystem/System.cpp index 70fb9382e1..0f0a62f8c6 100644 --- a/Code/Legacy/CrySystem/System.cpp +++ b/Code/Legacy/CrySystem/System.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -28,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -641,7 +643,7 @@ void CSystem::SleepIfNeeded() allowStallCatchup = true; float totalElapsed = (now - prevNow.Front()).GetSeconds(); - float wantSleepTime = CLAMP(minTime * (prevNow.Size() - 1) - totalElapsed, 0, (minTime - elapsed) * 0.9f); + float wantSleepTime = AZStd::clamp(minTime * (prevNow.Size() - 1) - totalElapsed, 0.0f, (minTime - elapsed) * 0.9f); static float sleepTime = 0; sleepTime = (15 * sleepTime + wantSleepTime) / 16; int sleepMS = (int)(1000.0f * sleepTime + 0.5f); diff --git a/Code/Legacy/CrySystem/ViewSystem/View.cpp b/Code/Legacy/CrySystem/ViewSystem/View.cpp index 7b3883f014..36cd891e3e 100644 --- a/Code/Legacy/CrySystem/ViewSystem/View.cpp +++ b/Code/Legacy/CrySystem/ViewSystem/View.cpp @@ -13,7 +13,6 @@ #include #include "View.h" #include -#include #include #include #include @@ -541,13 +540,13 @@ void CView::GetMemoryUsage(ICrySizer* s) const s->AddObject(m_shakes); } -void CView::Serialize(TSerialize ser) -{ - if (ser.IsReading()) - { - ResetShaking(); - } -} +//void CView::Serialize(TSerialize ser) +//{ +// if (ser.IsReading()) +// { +// ResetShaking(); +// } +//} void CView::PostSerialize() { diff --git a/Code/Legacy/CrySystem/ViewSystem/View.h b/Code/Legacy/CrySystem/ViewSystem/View.h index 58d7e64869..689c254897 100644 --- a/Code/Legacy/CrySystem/ViewSystem/View.h +++ b/Code/Legacy/CrySystem/ViewSystem/View.h @@ -15,6 +15,7 @@ #include class CGameObject; +struct ISystem; namespace LegacyViewSystem { @@ -106,7 +107,6 @@ public: virtual void SetActive(const bool bActive); // ~IView - void Serialize(TSerialize ser) override; void PostSerialize() override; CCamera& GetCamera() override { return m_camera; } const CCamera& GetCamera() const override { return m_camera; } diff --git a/Code/Legacy/CrySystem/ViewSystem/ViewSystem.cpp b/Code/Legacy/CrySystem/ViewSystem/ViewSystem.cpp index 01c7340919..1d141a5e13 100644 --- a/Code/Legacy/CrySystem/ViewSystem/ViewSystem.cpp +++ b/Code/Legacy/CrySystem/ViewSystem/ViewSystem.cpp @@ -617,16 +617,16 @@ void CViewSystem::GetMemoryUsage(ICrySizer* s) const s->AddContainer(m_views); } -void CViewSystem::Serialize(TSerialize ser) -{ - TViewMap::iterator iter = m_views.begin(); - TViewMap::iterator iterEnd = m_views.end(); - while (iter != iterEnd) - { - iter->second->Serialize(ser); - ++iter; - } -} +//void CViewSystem::Serialize(TSerialize ser) +//{ +// TViewMap::iterator iter = m_views.begin(); +// TViewMap::iterator iterEnd = m_views.end(); +// while (iter != iterEnd) +// { +// iter->second->Serialize(ser); +// ++iter; +// } +//} void CViewSystem::PostSerialize() { diff --git a/Code/Legacy/CrySystem/ViewSystem/ViewSystem.h b/Code/Legacy/CrySystem/ViewSystem/ViewSystem.h index 644a197e46..dd49e09e04 100644 --- a/Code/Legacy/CrySystem/ViewSystem/ViewSystem.h +++ b/Code/Legacy/CrySystem/ViewSystem/ViewSystem.h @@ -53,7 +53,6 @@ public: virtual unsigned int GetViewId(IView* pView); virtual unsigned int GetActiveViewId(); - virtual void Serialize(TSerialize ser); virtual void PostSerialize(); virtual IView* GetViewByEntityId(const AZ::EntityId& id, bool forceCreate); diff --git a/Code/Legacy/CrySystem/XConsole.cpp b/Code/Legacy/CrySystem/XConsole.cpp index 88a7fc262e..bb8316981a 100644 --- a/Code/Legacy/CrySystem/XConsole.cpp +++ b/Code/Legacy/CrySystem/XConsole.cpp @@ -1762,7 +1762,7 @@ void CXConsole::ExecuteString(const char* command, const bool bSilentMode, const AZ::StringFunc::TrimWhiteSpace(str, true, false); // Unroll the exec command - + bool unroll = (0 == AZ::StringFunc::Find(str, "exec", 0, false, false)); if (unroll) @@ -2891,75 +2891,6 @@ int CXConsole::GetNumVisibleVars() return numVars; } - -////////////////////////////////////////////////////////////////////////// -bool CXConsole::IsHashCalculated() -{ - return m_bCheatHashDirty == false; -} - -////////////////////////////////////////////////////////////////////////// -int CXConsole::GetNumCheatVars() -{ - return static_cast(m_randomCheckedVariables.size()); -} - -////////////////////////////////////////////////////////////////////////// -uint64 CXConsole::GetCheatVarHash() -{ - return m_nCheatHash; -} - -////////////////////////////////////////////////////////////////////////// -void CXConsole::SetCheatVarHashRange(size_t firstVar, size_t lastVar) -{ - // check inputs are sane -#if !defined(NDEBUG) - size_t numVars = GetNumCheatVars(); - assert(firstVar < numVars && lastVar < numVars && lastVar >= firstVar); -#endif - -#if defined(DEFENCE_CVAR_HASH_LOGGING) - if (m_bCheatHashDirty) - { - CryLog("HASHING: WARNING - trying to set up new cvar hash range while existing hash still calculating!"); - } -#endif - - m_nCheatHashRangeFirst = firstVar; - m_nCheatHashRangeLast = lastVar; - m_bCheatHashDirty = true; -} - -////////////////////////////////////////////////////////////////////////// -void CXConsole::CalcCheatVarHash() -{ - if (!m_bCheatHashDirty) - { - return; - } - - CCrc32 runningNameCrc32; - CCrc32 runningNameValueCrc32; - - AddCVarsToHash(m_randomCheckedVariables.begin() + m_nCheatHashRangeFirst, m_randomCheckedVariables.begin() + m_nCheatHashRangeLast, runningNameCrc32, runningNameValueCrc32); - AddCVarsToHash(m_alwaysCheckedVariables.begin(), m_alwaysCheckedVariables.end() - 1, runningNameCrc32, runningNameValueCrc32); - - // store hash - m_nCheatHash = (((uint64)runningNameCrc32.Get()) << 32) | runningNameValueCrc32.Get(); - m_bCheatHashDirty = false; - -#if defined(DEFENCE_CVAR_HASH_LOGGING) - if (!gEnv->IsDedicated()) - { - CryLog("HASHING: Range %d->%d = %llx(%x,%x), max cvars = %d", m_nCheatHashRangeFirst, m_nCheatHashRangeLast, - m_nCheatHash, runningNameCrc32.Get(), runningNameValueCrc32.Get(), - GetNumCheatVars()); - PrintCheatVars(true); - } -#endif -} - void CXConsole::AddCVarsToHash(ConsoleVariablesVector::const_iterator begin, ConsoleVariablesVector::const_iterator end, CCrc32& runningNameCrc32, CCrc32& runningNameValueCrc32) { for (ConsoleVariablesVector::const_iterator it = begin; it <= end; ++it) @@ -2974,162 +2905,6 @@ void CXConsole::AddCVarsToHash(ConsoleVariablesVector::const_iterator begin, Con } } -void CXConsole::CmdDumpAllAnticheatVars([[maybe_unused]] IConsoleCmdArgs* pArgs) -{ -#if defined(DEFENCE_CVAR_HASH_LOGGING) - CXConsole* pConsole = (CXConsole*)gEnv->pConsole; - - if (pConsole->IsHashCalculated()) - { - CryLog("HASHING: Displaying Full Anticheat Cvar list:"); - pConsole->PrintCheatVars(false); - } - else - { - CryLogAlways("DumpAllAnticheatVars - cannot complete, cheat vars are in a state of flux, please retry."); - } -#endif -} - -void CXConsole::CmdDumpLastHashedAnticheatVars([[maybe_unused]] IConsoleCmdArgs* pArgs) -{ -#if defined(DEFENCE_CVAR_HASH_LOGGING) - CXConsole* pConsole = (CXConsole*)gEnv->pConsole; - - if (pConsole->IsHashCalculated()) - { - CryLog("HASHING: Displaying Last Hashed Anticheat Cvar list:"); - pConsole->PrintCheatVars(true); - } - else - { - CryLogAlways("DumpLastHashedAnticheatVars - cannot complete, cheat vars are in a state of flux, please retry."); - } -#endif -} - -void CXConsole::PrintCheatVars([[maybe_unused]] bool bUseLastHashRange) -{ -#if defined(DEFENCE_CVAR_HASH_LOGGING) - if (m_bCheatHashDirty) - { - return; - } - - size_t i = 0; - char floatFormatBuf[64]; - - size_t nStart = 0; - size_t nEnd = m_mapVariables.size(); - - if (bUseLastHashRange) - { - nStart = m_nCheatHashRangeFirst; - nEnd = m_nCheatHashRangeLast; - } - - // iterate over all const cvars in our range - // then hash the string. - CryLog("VF_CHEAT & ~VF_CHEAT_NOCHECK list:"); - - ConsoleVariablesMap::const_iterator it, end = m_mapVariables.end(); - for (it = m_mapVariables.begin(); it != end; ++it) - { - // only count cheat cvars - if ((it->second->GetFlags() & VF_CHEAT) == 0 || - (it->second->GetFlags() & VF_CHEAT_NOCHECK) != 0) - { - continue; - } - - // count up - i++; - - // if we haven't reached the first var, or have passed the last var, break out - if (i - 1 < nStart) - { - continue; - } - if (i - 1 > nEnd) - { - break; - } - - // add name & variable to string. We add both since adding only the value could cause - // many collisions with variables all having value 0 or all 1. - string hashStr = it->first; - if (it->second->GetType() == CVAR_FLOAT) - { - sprintf(floatFormatBuf, "%.1g", it->second->GetFVal()); - hashStr += floatFormatBuf; - } - else - { - hashStr += it->second->GetString(); - } - - CryLog("%s", hashStr.c_str()); - } - - // iterate over any must-check variables - CryLog("VF_CHEAT_ALWAYS_CHECK list:"); - - for (it = m_mapVariables.begin(); it != end; ++it) - { - // only count cheat cvars - if ((it->second->GetFlags() & VF_CHEAT_ALWAYS_CHECK) == 0) - { - continue; - } - - // add name & variable to string. We add both since adding only the value could cause - // many collisions with variables all having value 0 or all 1. - string hashStr = it->first; - hashStr += it->second->GetString(); - - CryLog("%s", hashStr.c_str()); - } -#endif -} - -char* CXConsole::GetCheatVarAt(uint32 nOffset) -{ - if (m_bCheatHashDirty) - { - return NULL; - } - - size_t i = 0; - size_t nStart = nOffset; - - // iterate over all const cvars in our range - // then hash the string. - ConsoleVariablesMap::const_iterator it, end = m_mapVariables.end(); - for (it = m_mapVariables.begin(); it != end; ++it) - { - // only count cheat cvars - if ((it->second->GetFlags() & VF_CHEAT) == 0 || - (it->second->GetFlags() & VF_CHEAT_NOCHECK) != 0) - { - continue; - } - - // count up - i++; - - // if we haven't reached the first var continue - if (i - 1 < nStart) - { - continue; - } - - return (char*)it->first; - } - - return NULL; -} - - ////////////////////////////////////////////////////////////////////////// size_t CXConsole::GetSortedVars(AZStd::vector& pszArray, const char* szPrefix) { diff --git a/Code/Legacy/CrySystem/XConsole.h b/Code/Legacy/CrySystem/XConsole.h index 67d9371e8d..3ff9824e6f 100644 --- a/Code/Legacy/CrySystem/XConsole.h +++ b/Code/Legacy/CrySystem/XConsole.h @@ -182,11 +182,6 @@ public: virtual int GetNumVars(); virtual int GetNumVisibleVars(); virtual size_t GetSortedVars(AZStd::vector& pszArray, const char* szPrefix = 0); - virtual int GetNumCheatVars(); - virtual void SetCheatVarHashRange(size_t firstVar, size_t lastVar); - virtual void CalcCheatVarHash(); - virtual bool IsHashCalculated(); - virtual uint64 GetCheatVarHash(); virtual void FindVar(const char* substr); virtual const char* AutoComplete(const char* substr); virtual const char* AutoCompletePrev(const char* substr); @@ -231,9 +226,6 @@ public: // 0 if the operation failed ICVar* RegisterCVarGroup(const char* sName, const char* szFileName); - virtual void PrintCheatVars(bool bUseLastHashRange); - virtual char* GetCheatVarAt(uint32 nOffset); - void SetProcessingGroup(bool isGroup) { m_bIsProcessingGroup = isGroup; } bool GetIsProcessingGroup(void) const { return m_bIsProcessingGroup; } @@ -286,9 +278,6 @@ protected: // ------------------------------------------------------------------ static const char* GetFlagsString(const uint32 dwFlags); - static void CmdDumpAllAnticheatVars(IConsoleCmdArgs* pArgs); - static void CmdDumpLastHashedAnticheatVars(IConsoleCmdArgs* pArgs); - private: // ---------------------------------------------------------- typedef std::map ConsoleVariablesMap; // key points into string stored in ICVar or in .exe/.dll diff --git a/Code/Legacy/CrySystem/XConsoleVariable.cpp b/Code/Legacy/CrySystem/XConsoleVariable.cpp index ab6ed0b078..efd5ecd495 100644 --- a/Code/Legacy/CrySystem/XConsoleVariable.cpp +++ b/Code/Legacy/CrySystem/XConsoleVariable.cpp @@ -129,40 +129,6 @@ uint64 CXConsoleVariableBase::AddOnChangeFunctor(const SFunctor& pChangeFunctor) return newId; } -uint64 CXConsoleVariableBase::GetNumberOfOnChangeFunctors() const -{ - return m_changeFunctors.size(); -} - -const SFunctor& CXConsoleVariableBase::GetOnChangeFunctor(uint64 nFunctorId) const -{ - auto predicate = [nFunctorId](const std::pair& entry) -> bool { return entry.first == nFunctorId; }; - auto changeFunctor = std::find_if(m_changeFunctors.begin(), m_changeFunctors.end(), predicate); - if (changeFunctor != m_changeFunctors.end()) - { - return (*changeFunctor).second; - } - - static SFunctor sDummyFunctor; - assert(false && "[CXConsoleVariableBase::GetOnChangeFunctor] Trying to get a functor for an id that does not exist."); - - return sDummyFunctor; -} - -bool CXConsoleVariableBase::RemoveOnChangeFunctor(const uint64 nFunctorId) -{ - auto predicate = [nFunctorId](const std::pair& entry) -> bool { return entry.first == nFunctorId; }; - auto changeFunctor = std::find_if(m_changeFunctors.begin(), m_changeFunctors.end(), predicate); - - if (changeFunctor != m_changeFunctors.end()) - { - m_changeFunctors.erase(changeFunctor); - return true; - } - - return false; -} - ConsoleVarFunc CXConsoleVariableBase::GetOnChangeCallback() const { return m_pChangeFunc; diff --git a/Code/Legacy/CrySystem/XConsoleVariable.h b/Code/Legacy/CrySystem/XConsoleVariable.h index 122389407f..f761287b41 100644 --- a/Code/Legacy/CrySystem/XConsoleVariable.h +++ b/Code/Legacy/CrySystem/XConsoleVariable.h @@ -108,9 +108,6 @@ public: virtual void ForceSet(const char* s); virtual void SetOnChangeCallback(ConsoleVarFunc pChangeFunc); virtual uint64 AddOnChangeFunctor(const SFunctor& pChangeFunctor) override; - virtual bool RemoveOnChangeFunctor(const uint64 nFunctorId) override; - virtual uint64 GetNumberOfOnChangeFunctors() const; - virtual const SFunctor& GetOnChangeFunctor(uint64 nFunctorId) const override; virtual ConsoleVarFunc GetOnChangeCallback() const; virtual bool ShouldReset() const { return (m_nFlags & VF_RESETTABLE) != 0; } @@ -250,7 +247,7 @@ public: virtual void GetMemoryUsage(class ICrySizer* pSizer) const { pSizer->AddObject(this, sizeof(*this)); } private: // -------------------------------------------------------------------------------------------- - AZStd::string m_sValue; + AZStd::string m_sValue; AZStd::string m_sDefault; //!< }; @@ -315,7 +312,7 @@ public: virtual void GetMemoryUsage(class ICrySizer* pSizer) const { pSizer->AddObject(this, sizeof(*this)); } protected: // -------------------------------------------------------------------------------------------- - int m_iValue; + int m_iValue; int m_iDefault; //!< }; @@ -382,7 +379,7 @@ public: virtual void GetMemoryUsage(class ICrySizer* pSizer) const { pSizer->AddObject(this, sizeof(*this)); } protected: // -------------------------------------------------------------------------------------------- - int64 m_iValue; + int64 m_iValue; int64 m_iDefault; //!< }; @@ -488,7 +485,7 @@ protected: private: // -------------------------------------------------------------------------------------------- - float m_fValue; + float m_fValue; float m_fDefault; //!< }; @@ -578,7 +575,7 @@ public: virtual void GetMemoryUsage(class ICrySizer* pSizer) const { pSizer->AddObject(this, sizeof(*this)); } private: // -------------------------------------------------------------------------------------------- - int& m_iValue; + int& m_iValue; int m_iDefault; //!< }; diff --git a/Gems/LmbrCentral/Code/Source/Ai/NavigationComponent.cpp b/Gems/LmbrCentral/Code/Source/Ai/NavigationComponent.cpp index 9086f40ede..9897895dcd 100644 --- a/Gems/LmbrCentral/Code/Source/Ai/NavigationComponent.cpp +++ b/Gems/LmbrCentral/Code/Source/Ai/NavigationComponent.cpp @@ -9,7 +9,6 @@ #include "EditorNavigationUtil.h" #include -#include #include #include #include @@ -47,7 +46,7 @@ namespace LmbrCentral Call(FN_OnTraversalStarted, requestId); } - void OnTraversalPathUpdate(PathfindRequest::NavigationRequestId requestId, const AZ::Vector3& nextPathPosition, const AZ::Vector3& inflectionPosition) override + void OnTraversalPathUpdate(PathfindRequest::NavigationRequestId requestId, const AZ::Vector3& nextPathPosition, const AZ::Vector3& inflectionPosition) override { Call(FN_OnTraversalPathUpdate, requestId, nextPathPosition, inflectionPosition); } @@ -460,7 +459,7 @@ namespace LmbrCentral const bool usesAZCharacterPhysics = Physics::CharacterRequestBus::FindFirstHandler(entityId) != nullptr; m_usesCharacterPhysics = usesLegacyCharacterPhysics || usesAZCharacterPhysics; - + AZ_Warning("NavigationComponent", usesAZCharacterPhysics || Physics::RigidBodyRequestBus::FindFirstHandler(entityId), "Entity %s cannot be moved physically because it is missing a physics component", GetEntity()->GetName().c_str()); @@ -791,10 +790,10 @@ namespace LmbrCentral m_lastResponseCache.SetNextPathPosition(nextPathPosition); m_lastResponseCache.SetInflectionPosition(inflectionPosition); - // when using the custom movement method we just update the path and rely on + // when using the custom movement method we just update the path and rely on // the user to move the entity NavigationComponentNotificationBus::Event(m_entity->GetId(), - &NavigationComponentNotificationBus::Events::OnTraversalPathUpdate, + &NavigationComponentNotificationBus::Events::OnTraversalPathUpdate, m_lastResponseCache.GetRequestId(), nextPathPosition, inflectionPosition); @@ -808,7 +807,7 @@ namespace LmbrCentral if (m_usesCharacterPhysics) { - Physics::CharacterRequestBus::Event(GetEntityId(), + Physics::CharacterRequestBus::Event(GetEntityId(), &Physics::CharacterRequestBus::Events::AddVelocity, targetVelocity); } else diff --git a/Gems/LyShine/Code/Editor/Animation/UiAnimUndoManager.cpp b/Gems/LyShine/Code/Editor/Animation/UiAnimUndoManager.cpp index 025b8c94d8..3a3234fdce 100644 --- a/Gems/LyShine/Code/Editor/Animation/UiAnimUndoManager.cpp +++ b/Gems/LyShine/Code/Editor/Animation/UiAnimUndoManager.cpp @@ -6,11 +6,10 @@ * */ - #include "UiAnimUndoManager.h" #include "UiAnimUndoObject.h" #include "Undo/IUndoManagerListener.h" -#include +#include // UI Editor #include "EditorCommon.h" diff --git a/Gems/LyShine/Code/Editor/EditorCommon.h b/Gems/LyShine/Code/Editor/EditorCommon.h index 9af5958c67..a13332b0fd 100644 --- a/Gems/LyShine/Code/Editor/EditorCommon.h +++ b/Gems/LyShine/Code/Editor/EditorCommon.h @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include diff --git a/Gems/LyShine/Code/Editor/EditorWindow.cpp b/Gems/LyShine/Code/Editor/EditorWindow.cpp index 663570bbf0..a4ad4d7043 100644 --- a/Gems/LyShine/Code/Editor/EditorWindow.cpp +++ b/Gems/LyShine/Code/Editor/EditorWindow.cpp @@ -2112,8 +2112,8 @@ int EditorWindow::GetCanvasMaxHierarchyDepth(const LyShine::EntityArray& rootChi return depth; } - int numChildrenCurLevel = rootChildElements.size(); - int numChildrenNextLevel = 0; + size_t numChildrenCurLevel = rootChildElements.size(); + size_t numChildrenNextLevel = 0; std::list elementList(rootChildElements.begin(), rootChildElements.end()); while (!elementList.empty()) { diff --git a/Gems/LyShine/Code/Editor/HierarchyHelpers.cpp b/Gems/LyShine/Code/Editor/HierarchyHelpers.cpp index 5d97ecb83c..91e5781608 100644 --- a/Gems/LyShine/Code/Editor/HierarchyHelpers.cpp +++ b/Gems/LyShine/Code/Editor/HierarchyHelpers.cpp @@ -186,16 +186,20 @@ namespace HierarchyHelpers if (listOfNewlyCreatedTopLevelElements.empty()) { // This happens when the serialization version numbers DON'T match. - QMessageBox(QMessageBox::Critical, - "Error", - QString("Failed to load elements. The serialization format is incompatible."), - QMessageBox::Ok, widget->GetEditorWindow()).exec(); + QMessageBox( + QMessageBox::Critical, "Error", QString("Failed to load elements. The serialization format is incompatible."), QMessageBox::Ok, + widget->GetEditorWindow()) + .exec(); // Nothing more to do. return LyShine::EntityArray(); } - completeListOfNewlyCreatedTopLevelElements.push_back(listOfNewlyCreatedTopLevelElements); + completeListOfNewlyCreatedTopLevelElements.insert( + completeListOfNewlyCreatedTopLevelElements.end(), + listOfNewlyCreatedTopLevelElements.begin(), + listOfNewlyCreatedTopLevelElements.end() + ); } } diff --git a/Gems/LyShine/Code/Editor/PropertiesContainer.cpp b/Gems/LyShine/Code/Editor/PropertiesContainer.cpp index 9f9023f84d..e86cffcc08 100644 --- a/Gems/LyShine/Code/Editor/PropertiesContainer.cpp +++ b/Gems/LyShine/Code/Editor/PropertiesContainer.cpp @@ -544,7 +544,7 @@ AzToolsFramework::ComponentEditor* PropertiesContainer::CreateComponentEditor([[ { AzToolsFramework::ComponentEditor* editor = new AzToolsFramework::ComponentEditor(m_serializeContext, m_propertiesWidget, this); connect(editor, &AzToolsFramework::ComponentEditor::OnDisplayComponentEditorMenu, this, &PropertiesContainer::OnDisplayUiComponentEditorMenu); - + m_rowLayout->addWidget(editor); editor->hide(); @@ -788,7 +788,7 @@ void PropertiesContainer::Update() } else // more than one entity selected { - displayName = (ToString(selectedEntitiesAmount) + " elements selected").c_str(); + displayName = QString::number(selectedEntitiesAmount) + " elements selected"; } // Update the selected element display name diff --git a/Gems/LyShine/Code/Editor/SerializeHelpers.cpp b/Gems/LyShine/Code/Editor/SerializeHelpers.cpp index 724b6dee14..f9ce70caec 100644 --- a/Gems/LyShine/Code/Editor/SerializeHelpers.cpp +++ b/Gems/LyShine/Code/Editor/SerializeHelpers.cpp @@ -243,11 +243,14 @@ namespace SerializeHelpers insertBefore); } - // if a list of entities was passed then add all the entities that we added + // if a list of entities was passed then add all the entities that we added // to the list if (cumulativeListOfCreatedEntities) { - cumulativeListOfCreatedEntities->push_back(validatedListOfNewlyCreatedTopLevelElements); + cumulativeListOfCreatedEntities->insert( + cumulativeListOfCreatedEntities->end(), + validatedListOfNewlyCreatedTopLevelElements.begin(), + validatedListOfNewlyCreatedTopLevelElements.end()); } } @@ -363,7 +366,7 @@ namespace SerializeHelpers entityRestoreInfos.insert(entityRestoreInfos.end(), unserializedEntities->m_entityRestoreInfos.begin(), unserializedEntities->m_entityRestoreInfos.end()); entityRestoreInfos.insert(entityRestoreInfos.end(), - unserializedEntities->m_childEntityRestoreInfos.begin(), unserializedEntities->m_childEntityRestoreInfos.end()); + unserializedEntities->m_childEntityRestoreInfos.begin(), unserializedEntities->m_childEntityRestoreInfos.end()); } } // namespace EntityHelpers diff --git a/Gems/LyShine/Code/Source/UiCanvasComponent.cpp b/Gems/LyShine/Code/Source/UiCanvasComponent.cpp index 4b5f072966..d967b88610 100644 --- a/Gems/LyShine/Code/Source/UiCanvasComponent.cpp +++ b/Gems/LyShine/Code/Source/UiCanvasComponent.cpp @@ -706,7 +706,7 @@ AZStd::string UiCanvasComponent::GetUniqueChildName(AZ::EntityId parentEntityId, if (includeChildren) { - children.push_back(*includeChildren); + children.insert(children.end(),includeChildren->begin(),includeChildren->end()); } // First, check if base name is unique @@ -1862,7 +1862,7 @@ AZ::RHI::AttachmentId UiCanvasComponent::UseRenderTarget(const AZ::Name& renderT // Notify LyShine render pass that it needs to rebuild QueueRttPassRebuild(); - + return attachmentImage->GetAttachmentId(); } @@ -4101,7 +4101,7 @@ UiCanvasComponent* UiCanvasComponent::FixupPostLoad(AZ::Entity* canvasEntity, AZ canvasComponent->m_editorToGameEntityIdMap = *previousRemapTable; ReuseOrGenerateNewIdsAndFixRefs(&entityContainer, canvasComponent->m_editorToGameEntityIdMap, context); - + AzFramework::SliceEntityOwnershipServiceRequestBus::EventResult(isLoadingRootEntitySuccessful, canvasComponent->m_entityContext->GetContextId(), &AzFramework::SliceEntityOwnershipServiceRequestBus::Events::HandleRootEntityReloadedFromStream, rootSliceEntity, false, nullptr); diff --git a/Gems/LyShine/Code/Source/UiElementComponent.cpp b/Gems/LyShine/Code/Source/UiElementComponent.cpp index 0aa57e4041..cb81ea639c 100644 --- a/Gems/LyShine/Code/Source/UiElementComponent.cpp +++ b/Gems/LyShine/Code/Source/UiElementComponent.cpp @@ -561,7 +561,7 @@ LyShine::EntityArray UiElementComponent::FindAllChildrenIntersectingRect(const A // Check children of this child first // child elements do not have to be contained in the parent element's bounds LyShine::EntityArray childMatches = childElementComponent->FindAllChildrenIntersectingRect(bound0, bound1, isInGame); - result.push_back(childMatches); + result.insert(result.end(),childMatches.begin(),childMatches.end()); bool isSelectable = true; if (!isInGame) @@ -943,7 +943,7 @@ bool UiElementComponent::GetAreElementAndAncestorsEnabled() { return m_parentElementComponent->GetAreElementAndAncestorsEnabled(); } - + return true; } @@ -1327,7 +1327,7 @@ void UiElementComponent::Reflect(AZ::ReflectContext* context) serializeContext->Class() // Persistent IDs for this are simply the entity id ->PersistentId([](const void* instance) -> AZ::u64 - { + { const ChildEntityIdOrderEntry* entry = reinterpret_cast(instance); return static_cast(entry->m_entityId); }) @@ -1680,7 +1680,7 @@ void UiElementComponent::OnPatchEnd(const AZ::DataPatchNodeInfo& patchInfo) entityIdLoaded = true; } } - + if (entityIdLoaded) { oldChildrenDataPatchFound = true; @@ -1812,7 +1812,7 @@ void UiElementComponent::OnPatchEnd(const AZ::DataPatchNodeInfo& patchInfo) m_childEntityIdOrder.push_back({elementChanged.second, m_childEntityIdOrder.size()}); } } - + // sort the added elements by index AZStd::sort(elementsAdded.begin(), elementsAdded.end()); for (auto& elementAdded : elementsAdded) diff --git a/Gems/LyShine/Code/Tests/UiDynamicScrollBoxComponentTest.cpp b/Gems/LyShine/Code/Tests/UiDynamicScrollBoxComponentTest.cpp index 3ea3550e76..425ab6bb9a 100644 --- a/Gems/LyShine/Code/Tests/UiDynamicScrollBoxComponentTest.cpp +++ b/Gems/LyShine/Code/Tests/UiDynamicScrollBoxComponentTest.cpp @@ -93,7 +93,7 @@ namespace UnitTest static int FindDescendantCount(const AZ::Entity* entity) { LyShine::EntityArray children = entity->FindComponent()->GetChildElements(); - int numDescendants = children.size(); + int numDescendants = static_cast(children.size()); for(const AZ::Entity* child : children) { numDescendants += FindDescendantCount(child); @@ -105,7 +105,7 @@ namespace UnitTest static int FindCanvasElementCount(UiCanvasComponent* uiCanvasComponent) { const LyShine::EntityArray childEntities = uiCanvasComponent->GetChildElements(); - int numCanvasElements = childEntities.size(); + int numCanvasElements = static_cast(childEntities.size()); for (const AZ::Entity* childEntity : childEntities) { numCanvasElements += FindDescendantCount(childEntity); diff --git a/Gems/Maestro/Code/Source/Cinematics/AnimPostFXNode.cpp b/Gems/Maestro/Code/Source/Cinematics/AnimPostFXNode.cpp index 39e84d24a7..7e32301b71 100644 --- a/Gems/Maestro/Code/Source/Cinematics/AnimPostFXNode.cpp +++ b/Gems/Maestro/Code/Source/Cinematics/AnimPostFXNode.cpp @@ -12,7 +12,6 @@ #include "AnimSplineTrack.h" #include "CompoundSplineTrack.h" #include "BoolTrack.h" -#include "IPostEffectGroup.h" #include "Maestro/Types/AnimNodeType.h" #include "Maestro/Types/AnimParamType.h" #include "Maestro/Types/AnimValueType.h" @@ -236,7 +235,7 @@ CAnimNode* CAnimPostFXNode::CreateNode(const int id, AnimNodeType nodeType) retNode = aznew CAnimPostFXNode(id, nodeType, pDesc); static_cast(retNode)->m_nodeType = nodeType; } - + return retNode; } diff --git a/Gems/Maestro/Code/Source/Cinematics/MaterialNode.h b/Gems/Maestro/Code/Source/Cinematics/MaterialNode.h index 63f287f513..0c8bc38f1a 100644 --- a/Gems/Maestro/Code/Source/Cinematics/MaterialNode.h +++ b/Gems/Maestro/Code/Source/Cinematics/MaterialNode.h @@ -12,6 +12,8 @@ #pragma once #include "AnimNode.h" +#include +#include class CAnimMaterialNode : public CAnimNode @@ -43,7 +45,7 @@ public: virtual void SetKeyValueRange(float fMin, float fMax){ m_fMinKeyValue = fMin; m_fMaxKeyValue = fMax; }; virtual void InitializeTrack(IAnimTrack* pTrack, const CAnimParamType& paramType); - + static void Reflect(AZ::ReflectContext* context); protected: diff --git a/Gems/Maestro/Code/Source/Cinematics/Movie.h b/Gems/Maestro/Code/Source/Cinematics/Movie.h index 7c8edd15ae..0d7d1743f1 100644 --- a/Gems/Maestro/Code/Source/Cinematics/Movie.h +++ b/Gems/Maestro/Code/Source/Cinematics/Movie.h @@ -15,6 +15,9 @@ #pragma once #include +#include +#include + #include "IMovieSystem.h" #include "IShader.h" diff --git a/Gems/Maestro/Code/Source/MaestroSystemComponent.h b/Gems/Maestro/Code/Source/MaestroSystemComponent.h index b27075dbc0..8b37dee183 100644 --- a/Gems/Maestro/Code/Source/MaestroSystemComponent.h +++ b/Gems/Maestro/Code/Source/MaestroSystemComponent.h @@ -11,6 +11,7 @@ #include #include #include +#include #include "Cinematics/Movie.h" #include "Maestro/MaestroBus.h" From 6f589ad50ccb8b43bacd466ea479ae1529f2008b Mon Sep 17 00:00:00 2001 From: Jonny Galloway Date: Mon, 30 Aug 2021 15:42:26 -0500 Subject: [PATCH 787/803] color grading workflow (#3152) * color grading workflow assets, python scripts, ~and test data for Nuke and PS. Signed-off-by: Jonny Gallowy <~gallowj@amazon.com> * minor changes Signed-off-by: Jonny Gallowy <~gallowj@amazon.com> * pep8 reformate code style, clean up, address CR Signed-off-by: Jonny Gallowy <~gallowj@amazon.com> * Pep8 refactor, some DRY refactoring. Signed-off-by: Jonny Gallowy <~gallowj@amazon.com> * simplification write_azasset() Signed-off-by: Jonny Gallowy <~gallowj@amazon.com> * corrected code and further simplified () Signed-off-by: Jonny Gallowy <~gallowj@amazon.com> * updated readme.txt, I was mistakenly converting the wrong lut to engine Signed-off-by: Jonny Gallowy <~gallowj@amazon.com> * refactoring, simplification and some re-org Signed-off-by: Jonny Gallowy <~gallowj@amazon.com> * fixed bad loop in old_lut_helper Signed-off-by: Jonny Gallowy <~gallowj@amazon.com> * improve the lut_helper and corrected lut shaping Signed-off-by: Jonny Gallowy <~gallowj@amazon.com> * skip non-digit metadata in 3DL files Signed-off-by: Jonny Gallowy <~gallowj@amazon.com> * file name fix Signed-off-by: Jonny Gallowy <~gallowj@amazon.com> * nit: renamed a tag in comment Signed-off-by: Jonny Gallowy <~gallowj@amazon.com> * style Signed-off-by: Jonny Gallowy <~gallowj@amazon.com> * cleanup, cmd readme Signed-off-by: Jonny Gallowy <~gallowj@amazon.com> * fixed WINGHOME Signed-off-by: Jonny Gallowy <~gallowj@amazon.com> * Updated the readme with basic instructions Signed-off-by: Jonny Gallowy <~gallowj@amazon.com> * fixed py bootstrapping errors Signed-off-by: Jonny Gallowy <~gallowj@amazon.com> * removed log file (shouldn't be there) Signed-off-by: Jonny Gallowy <~gallowj@amazon.com> * re-gen bad test lut (forgot) Signed-off-by: Jonny Gallowy <~gallowj@amazon.com> Co-authored-by: Jonny Gallowy <~gallowj@amazon.com> --- ...treme-grade_inv-Log2-48nits_32_LUT.azasset | 32780 ++++++++++++++++ .../test-grade_inv-Log2-48nits_32_LUT.azasset | 32780 ++++++++++++++++ .../inv-Log2-48nits/Test_3DL_32_LUT.azasset | 4922 +++ .../inv-Log2-48nits/test_clt_32_LUT.azasset | 32777 +++++++++++++++ .../test_hue-sat_32_LUT.azasset | 32777 +++++++++++++++ .../Editor/Scripts/ColorGrading/.gitignore | 1 + .../Editor/Scripts/ColorGrading/__init__.py | 258 + .../capture_displaymapperpassthrough.py | 61 + .../ColorGrading/exr_to_3dl_azasset.py | 120 + .../ColorGrading/from_3dl_to_azasset.py | 114 + .../Editor/Scripts/ColorGrading/initialize.py | 123 + .../Scripts/ColorGrading/lut_compositor.py | 110 + .../Editor/Scripts/ColorGrading/lut_helper.py | 186 + .../Common/Editor/Scripts/bootstrap.py | 60 + .../Common/Tools/ColorGrading/.gitignore | 1 + .../LUTs/base_Log2-1000nits_16_LUT.exr | 3 + .../LUTs/base_Log2-1000nits_32_LUT.exr | 3 + .../LUTs/base_Log2-1000nits_64_LUT.exr | 3 + .../LUTs/base_Log2-2000nits_16_LUT.exr | 3 + .../LUTs/base_Log2-2000nits_32_LUT.exr | 3 + .../LUTs/base_Log2-2000nits_64_LUT.exr | 3 + .../LUTs/base_Log2-4000nits_16_LUT.exr | 3 + .../LUTs/base_Log2-4000nits_32_LUT.exr | 3 + .../LUTs/base_Log2-4000nits_64_LUT.exr | 3 + .../LUTs/base_Log2-48nits_16_LUT.exr | 3 + .../LUTs/base_Log2-48nits_32_LUT.exr | 3 + .../LUTs/base_Log2-48nits_64_LUT.exr | 3 + .../Resources/LUTs/from_ACEScg_to_sRGB.icc | Bin 0 -> 394128 bytes .../Resources/LUTs/linear_16_LUT.exr | 3 + .../Resources/LUTs/linear_32_LUT.exr | 3 + .../Resources/LUTs/linear_64_LUT.exr | 3 + .../Nuke_Test_Extreme_Grade.nk | 230 + .../Nuke_Test_Extreme_Grade.nk~ | 232 + .../Shot_post_test-extreme-grade.exr | 3 + ...t-extreme-grade_inv-Log2-48nits_32_LUT.3dl | 32769 +++++++++++++++ ...treme-grade_inv-Log2-48nits_32_LUT.azasset | 32780 ++++++++++++++++ ...t-extreme-grade_inv-Log2-48nits_32_LUT.exr | 3 + .../HDR/Test_Grade/Shot_post_test-grade.exr | 3 + .../Nuke/HDR/Test_Grade/Test-Grade.nk | 225 + .../Nuke/HDR/Test_Grade/Test-Grade.nk~ | 227 + .../test-grade_inv-Log2-48nits_32_LUT.3dl | 32769 +++++++++++++++ .../test-grade_inv-Log2-48nits_32_LUT.azasset | 32780 ++++++++++++++++ .../test-grade_inv-Log2-48nits_32_LUT.exr | 3 + .../Nuke/HDR/displaymapperpassthrough.dds | 3 + .../Nuke/HDR/displaymapperpassthrough.exr | 3 + .../TestData/Nuke/O3DE_HDR_Nuke_Color_Grading | 57 + .../Nuke/O3DE_HDR_Nuke_Color_Grading.autosave | 125 + .../Photoshop/Log2-48nits/CLT_grade.psd | 3 + .../LUT_layer_composite_hue-sat_grade.psd | 3 + .../framebuffer_ACEScg_to_sRGB_icc.exr | 3 + .../Log2-48nits/i_shaped/test_clt_32_LUT.exr | 3 + .../i_shaped/test_hue-sat_32_LUT.exr | 3 + .../o_invShaped/Test_3DL_32_LUT.azasset | 4922 +++ .../o_invShaped/test_clt_32_LUT.3dl | 32769 +++++++++++++++ .../o_invShaped/test_clt_32_LUT.azasset | 32777 +++++++++++++++ .../o_invShaped/test_hue-sat_32_LUT.3dl | 32769 +++++++++++++++ .../o_invShaped/test_hue-sat_32_LUT.azasset | 32777 +++++++++++++++ .../TestData/displaymapperpassthrough.dds | 3 + .../TestData/displaymapperpassthrough.exr | 3 + .../Tools/ColorGrading/cmdline/.gitignore | 1 + .../cmdline/CMD_ColorGradingTools.bat | 52 + .../Tools/ColorGrading/cmdline/Env_Core.bat | 129 + .../Tools/ColorGrading/cmdline/Env_Python.bat | 102 + .../Tools/ColorGrading/cmdline/Env_Tools.bat | 88 + .../ColorGrading/cmdline/Env_WingIDE.bat | 67 + .../cmdline/Launch_WingIDE-7-1.bat | 99 + .../Tools/ColorGrading/cmdline/README.txt | 26 + .../cmdline/User_Env.bat.template | 41 + .../Common/Tools/ColorGrading/readme.txt | 98 + 69 files changed, 406065 insertions(+) create mode 100644 Gems/Atom/Feature/Common/Assets/ColorGrading/TestData/Nuke/test-extreme-grade_inv-Log2-48nits_32_LUT.azasset create mode 100644 Gems/Atom/Feature/Common/Assets/ColorGrading/TestData/Nuke/test-grade_inv-Log2-48nits_32_LUT.azasset create mode 100644 Gems/Atom/Feature/Common/Assets/ColorGrading/TestData/Photoshop/inv-Log2-48nits/Test_3DL_32_LUT.azasset create mode 100644 Gems/Atom/Feature/Common/Assets/ColorGrading/TestData/Photoshop/inv-Log2-48nits/test_clt_32_LUT.azasset create mode 100644 Gems/Atom/Feature/Common/Assets/ColorGrading/TestData/Photoshop/inv-Log2-48nits/test_hue-sat_32_LUT.azasset create mode 100644 Gems/Atom/Feature/Common/Editor/Scripts/ColorGrading/.gitignore create mode 100644 Gems/Atom/Feature/Common/Editor/Scripts/ColorGrading/__init__.py create mode 100644 Gems/Atom/Feature/Common/Editor/Scripts/ColorGrading/capture_displaymapperpassthrough.py create mode 100644 Gems/Atom/Feature/Common/Editor/Scripts/ColorGrading/exr_to_3dl_azasset.py create mode 100644 Gems/Atom/Feature/Common/Editor/Scripts/ColorGrading/from_3dl_to_azasset.py create mode 100644 Gems/Atom/Feature/Common/Editor/Scripts/ColorGrading/initialize.py create mode 100644 Gems/Atom/Feature/Common/Editor/Scripts/ColorGrading/lut_compositor.py create mode 100644 Gems/Atom/Feature/Common/Editor/Scripts/ColorGrading/lut_helper.py create mode 100644 Gems/Atom/Feature/Common/Editor/Scripts/bootstrap.py create mode 100644 Gems/Atom/Feature/Common/Tools/ColorGrading/.gitignore create mode 100644 Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/LUTs/base_Log2-1000nits_16_LUT.exr create mode 100644 Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/LUTs/base_Log2-1000nits_32_LUT.exr create mode 100644 Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/LUTs/base_Log2-1000nits_64_LUT.exr create mode 100644 Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/LUTs/base_Log2-2000nits_16_LUT.exr create mode 100644 Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/LUTs/base_Log2-2000nits_32_LUT.exr create mode 100644 Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/LUTs/base_Log2-2000nits_64_LUT.exr create mode 100644 Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/LUTs/base_Log2-4000nits_16_LUT.exr create mode 100644 Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/LUTs/base_Log2-4000nits_32_LUT.exr create mode 100644 Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/LUTs/base_Log2-4000nits_64_LUT.exr create mode 100644 Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/LUTs/base_Log2-48nits_16_LUT.exr create mode 100644 Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/LUTs/base_Log2-48nits_32_LUT.exr create mode 100644 Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/LUTs/base_Log2-48nits_64_LUT.exr create mode 100644 Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/LUTs/from_ACEScg_to_sRGB.icc create mode 100644 Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/LUTs/linear_16_LUT.exr create mode 100644 Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/LUTs/linear_32_LUT.exr create mode 100644 Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/LUTs/linear_64_LUT.exr create mode 100644 Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/Test_Extreme_Grade/Nuke_Test_Extreme_Grade.nk create mode 100644 Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/Test_Extreme_Grade/Nuke_Test_Extreme_Grade.nk~ create mode 100644 Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/Test_Extreme_Grade/Shot_post_test-extreme-grade.exr create mode 100644 Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/Test_Extreme_Grade/test-extreme-grade_inv-Log2-48nits_32_LUT.3dl create mode 100644 Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/Test_Extreme_Grade/test-extreme-grade_inv-Log2-48nits_32_LUT.azasset create mode 100644 Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/Test_Extreme_Grade/test-extreme-grade_inv-Log2-48nits_32_LUT.exr create mode 100644 Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/Test_Grade/Shot_post_test-grade.exr create mode 100644 Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/Test_Grade/Test-Grade.nk create mode 100644 Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/Test_Grade/Test-Grade.nk~ create mode 100644 Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/Test_Grade/test-grade_inv-Log2-48nits_32_LUT.3dl create mode 100644 Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/Test_Grade/test-grade_inv-Log2-48nits_32_LUT.azasset create mode 100644 Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/Test_Grade/test-grade_inv-Log2-48nits_32_LUT.exr create mode 100644 Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/displaymapperpassthrough.dds create mode 100644 Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/displaymapperpassthrough.exr create mode 100644 Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/O3DE_HDR_Nuke_Color_Grading create mode 100644 Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/O3DE_HDR_Nuke_Color_Grading.autosave create mode 100644 Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Photoshop/Log2-48nits/CLT_grade.psd create mode 100644 Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Photoshop/Log2-48nits/LUT_layer_composite_hue-sat_grade.psd create mode 100644 Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Photoshop/Log2-48nits/framebuffer_ACEScg_to_sRGB_icc.exr create mode 100644 Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Photoshop/Log2-48nits/i_shaped/test_clt_32_LUT.exr create mode 100644 Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Photoshop/Log2-48nits/i_shaped/test_hue-sat_32_LUT.exr create mode 100644 Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Photoshop/Log2-48nits/o_invShaped/Test_3DL_32_LUT.azasset create mode 100644 Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Photoshop/Log2-48nits/o_invShaped/test_clt_32_LUT.3dl create mode 100644 Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Photoshop/Log2-48nits/o_invShaped/test_clt_32_LUT.azasset create mode 100644 Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Photoshop/Log2-48nits/o_invShaped/test_hue-sat_32_LUT.3dl create mode 100644 Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Photoshop/Log2-48nits/o_invShaped/test_hue-sat_32_LUT.azasset create mode 100644 Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/displaymapperpassthrough.dds create mode 100644 Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/displaymapperpassthrough.exr create mode 100644 Gems/Atom/Feature/Common/Tools/ColorGrading/cmdline/.gitignore create mode 100644 Gems/Atom/Feature/Common/Tools/ColorGrading/cmdline/CMD_ColorGradingTools.bat create mode 100644 Gems/Atom/Feature/Common/Tools/ColorGrading/cmdline/Env_Core.bat create mode 100644 Gems/Atom/Feature/Common/Tools/ColorGrading/cmdline/Env_Python.bat create mode 100644 Gems/Atom/Feature/Common/Tools/ColorGrading/cmdline/Env_Tools.bat create mode 100644 Gems/Atom/Feature/Common/Tools/ColorGrading/cmdline/Env_WingIDE.bat create mode 100644 Gems/Atom/Feature/Common/Tools/ColorGrading/cmdline/Launch_WingIDE-7-1.bat create mode 100644 Gems/Atom/Feature/Common/Tools/ColorGrading/cmdline/README.txt create mode 100644 Gems/Atom/Feature/Common/Tools/ColorGrading/cmdline/User_Env.bat.template create mode 100644 Gems/Atom/Feature/Common/Tools/ColorGrading/readme.txt diff --git a/Gems/Atom/Feature/Common/Assets/ColorGrading/TestData/Nuke/test-extreme-grade_inv-Log2-48nits_32_LUT.azasset b/Gems/Atom/Feature/Common/Assets/ColorGrading/TestData/Nuke/test-extreme-grade_inv-Log2-48nits_32_LUT.azasset new file mode 100644 index 0000000000..66f3b57564 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/ColorGrading/TestData/Nuke/test-extreme-grade_inv-Log2-48nits_32_LUT.azasset @@ -0,0 +1,32780 @@ +{ + "Type": "JsonSerialization", + "Version": 1, + "ClassName": "LookupTableAsset", + "ClassData": { + "Name": "LookupTable", + "Intervals": [ + 0, 33, 66, 99, 132, 165, 198, 231, 264, 297, 330, 363, 396, 429, 462, 495, 528, 561, 594, 627, 660, 693, 726, 759, 792, 825, 858, 891, 924, 957, 990, 1023], + "Values": [ + 0, 0, 0, + 0, 40, 0, + 0, 176, 0, + 0, 310, 0, + 0, 444, 0, + 0, 578, 0, + 0, 711, 0, + 0, 844, 0, + 0, 976, 0, + 0, 1109, 0, + 0, 1241, 0, + 0, 1374, 0, + 0, 1506, 0, + 0, 1638, 0, + 0, 1770, 0, + 0, 1903, 0, + 0, 2035, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 235, 0, 150, + 0, 22, 0, + 0, 162, 0, + 0, 300, 0, + 0, 437, 0, + 0, 572, 0, + 0, 707, 0, + 0, 841, 0, + 0, 974, 0, + 0, 1107, 0, + 0, 1240, 0, + 0, 1373, 0, + 0, 1505, 0, + 0, 1638, 0, + 0, 1770, 0, + 0, 1902, 0, + 0, 2035, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 474, 0, 352, + 349, 0, 225, + 98, 143, 0, + 0, 286, 0, + 0, 427, 0, + 0, 565, 0, + 0, 701, 0, + 0, 836, 0, + 0, 971, 0, + 0, 1105, 0, + 0, 1238, 0, + 0, 1371, 0, + 0, 1504, 0, + 0, 1637, 0, + 0, 1769, 0, + 0, 1902, 0, + 0, 2034, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 672, 0, 529, + 595, 0, 448, + 467, 117, 309, + 205, 267, 14, + 0, 412, 0, + 0, 554, 0, + 0, 693, 0, + 0, 831, 0, + 0, 967, 0, + 0, 1102, 0, + 0, 1236, 0, + 0, 1370, 0, + 0, 1503, 0, + 0, 1636, 0, + 0, 1769, 0, + 0, 1901, 0, + 0, 2034, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 848, 0, 693, + 797, 0, 638, + 719, 78, 551, + 588, 240, 402, + 318, 393, 67, + 0, 540, 0, + 0, 683, 0, + 0, 823, 0, + 0, 961, 0, + 0, 1097, 0, + 0, 1233, 0, + 0, 1367, 0, + 0, 1501, 0, + 0, 1635, 0, + 0, 1768, 0, + 0, 1901, 0, + 0, 2033, 0, + 0, 2165, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1010, 0, 848, + 975, 0, 809, + 924, 22, 751, + 845, 201, 661, + 712, 365, 502, + 435, 520, 130, + 0, 669, 0, + 0, 813, 0, + 0, 953, 0, + 0, 1092, 0, + 0, 1228, 0, + 0, 1364, 0, + 0, 1499, 0, + 0, 1633, 0, + 0, 1766, 0, + 0, 1900, 0, + 0, 2033, 0, + 0, 2165, 0, + 0, 2297, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1163, 0, 996, + 1139, 0, 968, + 1104, 0, 928, + 1052, 143, 869, + 972, 326, 775, + 837, 493, 609, + 555, 649, 202, + 0, 798, 0, + 0, 943, 0, + 0, 1084, 0, + 0, 1223, 0, + 0, 1360, 0, + 0, 1496, 0, + 0, 1631, 0, + 0, 1765, 0, + 0, 1898, 0, + 0, 2032, 0, + 0, 2165, 0, + 0, 2297, 0, + 0, 2429, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1311, 0, 1139, + 1293, 0, 1119, + 1269, 0, 1091, + 1233, 52, 1050, + 1181, 267, 990, + 1101, 452, 893, + 965, 621, 721, + 678, 778, 283, + 0, 928, 0, + 0, 1073, 0, + 0, 1215, 0, + 0, 1354, 0, + 0, 1491, 0, + 0, 1627, 0, + 0, 1762, 0, + 0, 1897, 0, + 0, 2030, 0, + 0, 2163, 0, + 0, 2297, 0, + 0, 2429, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1454, 0, 1280, + 1441, 0, 1265, + 1424, 0, 1245, + 1399, 0, 1216, + 1363, 174, 1175, + 1311, 393, 1113, + 1230, 580, 1015, + 1093, 750, 837, + 804, 908, 374, + 0, 1059, 0, + 0, 1204, 0, + 0, 1346, 0, + 0, 1486, 0, + 0, 1623, 0, + 0, 1759, 0, + 0, 1894, 0, + 0, 2029, 0, + 0, 2163, 0, + 0, 2295, 0, + 0, 2429, 0, + 0, 2561, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1595, 0, 1418, + 1585, 0, 1407, + 1572, 0, 1393, + 1554, 0, 1372, + 1530, 9, 1343, + 1494, 298, 1301, + 1441, 520, 1239, + 1360, 709, 1139, + 1222, 880, 957, + 931, 1039, 472, + 0, 1190, 0, + 0, 1336, 0, + 0, 1478, 0, + 0, 1617, 0, + 0, 1755, 0, + 0, 1891, 0, + 0, 2026, 0, + 0, 2161, 0, + 0, 2295, 0, + 0, 2427, 0, + 0, 2561, 0, + 0, 2693, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1733, 0, 1555, + 1726, 0, 1547, + 1716, 0, 1536, + 1703, 0, 1521, + 1686, 0, 1501, + 1661, 130, 1471, + 1625, 424, 1429, + 1572, 649, 1366, + 1491, 839, 1265, + 1352, 1011, 1080, + 1059, 1170, 577, + 0, 1321, 0, + 0, 1467, 0, + 0, 1610, 0, + 0, 1749, 0, + 0, 1887, 0, + 0, 2023, 0, + 0, 2159, 0, + 0, 2293, 0, + 0, 2427, 0, + 0, 2559, 0, + 0, 2693, 0, + 0, 2825, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1869, 0, 1690, + 1864, 0, 1684, + 1857, 0, 1676, + 1848, 0, 1666, + 1835, 0, 1651, + 1817, 0, 1630, + 1792, 254, 1601, + 1756, 552, 1558, + 1704, 778, 1494, + 1622, 970, 1392, + 1483, 1141, 1205, + 1188, 1301, 687, + 0, 1453, 0, + 0, 1599, 0, + 0, 1741, 0, + 0, 1881, 0, + 0, 2019, 0, + 0, 2155, 0, + 0, 2291, 0, + 0, 2425, 0, + 0, 2559, 0, + 0, 2691, 0, + 0, 2825, 0, + 0, 2957, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2005, 0, 1825, + 2001, 0, 1821, + 1996, 0, 1815, + 1989, 0, 1807, + 1979, 0, 1796, + 1966, 0, 1781, + 1949, 0, 1760, + 1924, 379, 1731, + 1888, 681, 1688, + 1835, 908, 1624, + 1753, 1100, 1521, + 1614, 1272, 1332, + 1318, 1432, 803, + 0, 1584, 0, + 0, 1731, 0, + 0, 1873, 0, + 0, 2013, 0, + 0, 2151, 0, + 0, 2287, 0, + 0, 2423, 0, + 0, 2557, 0, + 0, 2691, 0, + 0, 2823, 0, + 0, 2957, 0, + 0, 3089, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2139, 0, 1959, + 2137, 0, 1956, + 2133, 0, 1951, + 2127, 0, 1945, + 2121, 0, 1937, + 2111, 0, 1927, + 2099, 0, 1912, + 2081, 0, 1891, + 2055, 506, 1861, + 2019, 810, 1818, + 1967, 1038, 1754, + 1885, 1231, 1650, + 1745, 1404, 1460, + 1448, 1564, 922, + 0, 1716, 0, + 0, 1863, 0, + 0, 2005, 0, + 0, 2145, 0, + 0, 2283, 0, + 0, 2419, 0, + 0, 2555, 0, + 0, 2689, 0, + 0, 2823, 0, + 0, 2957, 0, + 0, 3089, 0, + 0, 3221, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3885, 0, + 0, 4017, 0, + 2273, 0, 2093, + 2271, 0, 2091, + 2269, 0, 2087, + 2265, 0, 2083, + 2259, 0, 2077, + 2253, 0, 2069, + 2243, 0, 2057, + 2231, 0, 2043, + 2213, 60, 2022, + 2187, 635, 1992, + 2151, 941, 1949, + 2099, 1169, 1884, + 2016, 1363, 1781, + 1877, 1536, 1589, + 1579, 1696, 1044, + 0, 1848, 0, + 0, 1995, 0, + 0, 2137, 0, + 0, 2277, 0, + 0, 2415, 0, + 0, 2551, 0, + 0, 2687, 0, + 0, 2821, 0, + 0, 2955, 0, + 0, 3089, 0, + 0, 3221, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3885, 0, + 0, 4017, 0, + 2407, 0, 2225, + 2405, 0, 2223, + 2403, 0, 2221, + 2401, 0, 2219, + 2397, 0, 2213, + 2391, 0, 2207, + 2385, 0, 2199, + 2375, 0, 2189, + 2361, 0, 2173, + 2345, 182, 2153, + 2319, 764, 2123, + 2283, 1071, 2081, + 2231, 1301, 2015, + 2149, 1494, 1911, + 2008, 1667, 1719, + 1710, 1828, 1168, + 0, 1980, 0, + 0, 2127, 0, + 0, 2269, 0, + 0, 2409, 0, + 0, 2547, 0, + 0, 2683, 0, + 0, 2819, 0, + 0, 2953, 0, + 0, 3087, 0, + 0, 3221, 0, + 0, 3353, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4017, 0, + 2539, 0, 2359, + 2539, 0, 2357, + 2537, 0, 2355, + 2535, 0, 2353, + 2533, 0, 2349, + 2529, 0, 2345, + 2523, 0, 2339, + 2517, 0, 2331, + 2507, 0, 2321, + 2493, 0, 2305, + 2475, 306, 2285, + 2451, 894, 2255, + 2415, 1202, 2211, + 2363, 1432, 2147, + 2279, 1626, 2042, + 2141, 1799, 1850, + 1842, 1960, 1295, + 0, 2113, 0, + 0, 2259, 0, + 0, 2401, 0, + 0, 2541, 0, + 0, 2679, 0, + 0, 2815, 0, + 0, 2951, 0, + 0, 3085, 0, + 0, 3219, 0, + 0, 3353, 0, + 0, 3485, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 2673, 0, 2491, + 2671, 0, 2491, + 2671, 0, 2489, + 2669, 0, 2487, + 2667, 0, 2485, + 2665, 0, 2481, + 2661, 0, 2477, + 2655, 0, 2471, + 2649, 0, 2463, + 2639, 0, 2453, + 2625, 0, 2437, + 2607, 433, 2415, + 2583, 1025, 2387, + 2547, 1334, 2343, + 2493, 1564, 2279, + 2411, 1758, 2173, + 2273, 1931, 1981, + 1973, 2091, 1423, + 0, 2245, 0, + 0, 2391, 0, + 0, 2533, 0, + 0, 2673, 0, + 0, 2811, 0, + 0, 2947, 0, + 0, 3083, 0, + 0, 3217, 0, + 0, 3351, 0, + 0, 3485, 0, + 0, 3617, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 2805, 0, 2623, + 2805, 0, 2623, + 2803, 0, 2623, + 2803, 0, 2621, + 2801, 0, 2619, + 2799, 0, 2617, + 2797, 0, 2613, + 2793, 0, 2609, + 2787, 0, 2603, + 2781, 0, 2595, + 2771, 0, 2583, + 2757, 0, 2569, + 2741, 560, 2547, + 2715, 1155, 2517, + 2679, 1465, 2475, + 2625, 1696, 2409, + 2543, 1890, 2305, + 2403, 2063, 2111, + 2105, 2223, 1552, + 0, 2377, 0, + 0, 2523, 0, + 0, 2665, 0, + 0, 2805, 0, + 0, 2943, 0, + 0, 3079, 0, + 0, 3215, 0, + 0, 3349, 0, + 0, 3483, 0, + 0, 3617, 0, + 0, 3749, 0, + 0, 3883, 0, + 0, 4015, 0, + 2937, 0, 2757, + 2937, 0, 2755, + 2937, 0, 2755, + 2935, 0, 2755, + 2935, 0, 2753, + 2933, 0, 2751, + 2931, 0, 2749, + 2929, 0, 2745, + 2925, 0, 2741, + 2919, 0, 2735, + 2913, 0, 2727, + 2903, 0, 2715, + 2891, 0, 2701, + 2873, 689, 2679, + 2847, 1287, 2649, + 2811, 1597, 2607, + 2759, 1828, 2541, + 2675, 2022, 2437, + 2535, 2195, 2243, + 2237, 2355, 1681, + 0, 2509, 0, + 0, 2655, 0, + 0, 2797, 0, + 0, 2937, 0, + 0, 3075, 0, + 0, 3211, 0, + 0, 3347, 0, + 0, 3481, 0, + 0, 3615, 0, + 0, 3749, 0, + 0, 3881, 0, + 0, 4015, 0, + 3071, 0, 2889, + 3069, 0, 2889, + 3069, 0, 2887, + 3069, 0, 2887, + 3067, 0, 2885, + 3067, 0, 2885, + 3065, 0, 2883, + 3063, 0, 2881, + 3061, 0, 2877, + 3057, 0, 2873, + 3051, 0, 2867, + 3045, 0, 2859, + 3035, 0, 2847, + 3023, 0, 2833, + 3005, 819, 2811, + 2979, 1418, 2781, + 2943, 1729, 2739, + 2891, 1959, 2673, + 2807, 2153, 2569, + 2667, 2327, 2375, + 2369, 2487, 1811, + 0, 2641, 0, + 0, 2787, 0, + 0, 2929, 0, + 0, 3069, 0, + 0, 3207, 0, + 0, 3343, 0, + 0, 3479, 0, + 0, 3613, 0, + 0, 3747, 0, + 0, 3881, 0, + 0, 4015, 0, + 3203, 0, 3021, + 3203, 0, 3021, + 3203, 0, 3021, + 3201, 0, 3019, + 3201, 0, 3019, + 3201, 0, 3017, + 3199, 0, 3017, + 3197, 0, 3015, + 3195, 0, 3013, + 3193, 0, 3009, + 3189, 0, 3005, + 3183, 0, 2999, + 3177, 0, 2991, + 3167, 0, 2979, + 3155, 0, 2965, + 3137, 949, 2943, + 3111, 1550, 2913, + 3075, 1860, 2871, + 3023, 2091, 2805, + 2939, 2285, 2701, + 2801, 2459, 2507, + 2501, 2619, 1942, + 0, 2773, 0, + 0, 2919, 0, + 0, 3061, 0, + 0, 3201, 0, + 0, 3339, 0, + 0, 3475, 0, + 0, 3611, 0, + 0, 3745, 0, + 0, 3879, 0, + 0, 4013, 0, + 3335, 0, 3153, + 3335, 0, 3153, + 3335, 0, 3153, + 3335, 0, 3153, + 3333, 0, 3151, + 3333, 0, 3151, + 3333, 0, 3151, + 3331, 0, 3149, + 3329, 0, 3147, + 3327, 0, 3145, + 3325, 0, 3141, + 3321, 0, 3137, + 3315, 0, 3131, + 3309, 0, 3123, + 3299, 0, 3111, + 3287, 0, 3097, + 3269, 1080, 3075, + 3243, 1682, 3045, + 3207, 1992, 3003, + 3155, 2223, 2937, + 3073, 2417, 2833, + 2933, 2591, 2639, + 2633, 2751, 2073, + 0, 2905, 0, + 0, 3051, 0, + 0, 3193, 0, + 0, 3333, 0, + 0, 3471, 0, + 0, 3609, 0, + 0, 3743, 0, + 0, 3877, 0, + 0, 4011, 0, + 3467, 0, 3285, + 3467, 0, 3285, + 3467, 0, 3285, + 3467, 0, 3285, + 3467, 0, 3285, + 3465, 0, 3283, + 3465, 0, 3283, + 3465, 0, 3283, + 3463, 0, 3281, + 3461, 0, 3279, + 3459, 0, 3277, + 3457, 0, 3273, + 3453, 0, 3269, + 3447, 0, 3263, + 3441, 0, 3255, + 3431, 0, 3243, + 3419, 0, 3229, + 3401, 1211, 3207, + 3375, 1813, 3177, + 3339, 2125, 3135, + 3287, 2355, 3069, + 3205, 2549, 2965, + 3065, 2723, 2771, + 2765, 2885, 2205, + 0, 3037, 0, + 0, 3183, 0, + 0, 3327, 0, + 0, 3465, 0, + 0, 3603, 0, + 0, 3741, 0, + 0, 3875, 0, + 0, 4009, 0, + 3599, 0, 3417, + 3599, 0, 3417, + 3599, 0, 3417, + 3599, 0, 3417, + 3599, 0, 3417, + 3599, 0, 3417, + 3597, 0, 3415, + 3597, 0, 3415, + 3597, 0, 3415, + 3595, 0, 3413, + 3593, 0, 3411, + 3591, 0, 3409, + 3589, 0, 3405, + 3585, 0, 3401, + 3579, 0, 3395, + 3573, 0, 3387, + 3563, 0, 3375, + 3551, 0, 3361, + 3533, 1342, 3339, + 3507, 1945, 3309, + 3471, 2257, 3267, + 3419, 2487, 3201, + 3337, 2681, 3097, + 3197, 2855, 2903, + 2897, 3017, 2337, + 0, 3169, 0, + 0, 3315, 0, + 0, 3459, 0, + 0, 3599, 0, + 0, 3735, 0, + 0, 3873, 0, + 0, 4007, 0, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3547, + 3729, 0, 3547, + 3729, 0, 3547, + 3727, 0, 3545, + 3725, 0, 3543, + 3723, 0, 3541, + 3721, 0, 3537, + 3717, 0, 3533, + 3711, 0, 3527, + 3705, 0, 3519, + 3695, 0, 3507, + 3683, 0, 3493, + 3665, 1474, 3471, + 3639, 2077, 3441, + 3603, 2389, 3399, + 3551, 2619, 3333, + 3469, 2813, 3229, + 3329, 2987, 3035, + 3029, 3149, 2467, + 0, 3301, 0, + 0, 3447, 0, + 0, 3591, 0, + 0, 3731, 0, + 0, 3869, 0, + 0, 4005, 0, + 3863, 0, 3683, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3861, 0, 3679, + 3861, 0, 3679, + 3859, 0, 3677, + 3857, 0, 3675, + 3855, 0, 3673, + 3853, 0, 3669, + 3849, 0, 3665, + 3845, 0, 3659, + 3837, 0, 3651, + 3827, 0, 3641, + 3815, 0, 3625, + 3797, 1605, 3603, + 3771, 2209, 3573, + 3735, 2521, 3531, + 3683, 2751, 3465, + 3601, 2947, 3361, + 3461, 3119, 3167, + 3161, 3281, 2599, + 0, 3433, 0, + 0, 3579, 0, + 0, 3723, 0, + 0, 3863, 0, + 0, 4001, 0, + 3997, 0, 3815, + 3997, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3813, + 3995, 0, 3813, + 3995, 0, 3813, + 3995, 0, 3813, + 3995, 0, 3813, + 3995, 0, 3813, + 3995, 0, 3813, + 3993, 0, 3811, + 3993, 0, 3811, + 3991, 0, 3809, + 3991, 0, 3807, + 3987, 0, 3805, + 3985, 0, 3801, + 3981, 0, 3797, + 3977, 0, 3791, + 3969, 0, 3783, + 3959, 0, 3773, + 3947, 0, 3757, + 3929, 1737, 3735, + 3903, 2341, 3705, + 3867, 2653, 3663, + 3815, 2883, 3597, + 3733, 3079, 3493, + 3593, 3251, 3299, + 3293, 3413, 2731, + 0, 3565, 0, + 0, 3711, 0, + 0, 3855, 0, + 0, 3995, 0, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3943, + 4095, 0, 3943, + 4095, 0, 3941, + 4095, 0, 3939, + 4095, 0, 3937, + 4095, 0, 3933, + 4095, 0, 3929, + 4095, 0, 3923, + 4095, 0, 3915, + 4091, 0, 3905, + 4079, 0, 3889, + 4061, 1869, 3867, + 4035, 2473, 3839, + 3999, 2785, 3795, + 3947, 3015, 3729, + 3865, 3211, 3625, + 3725, 3383, 3431, + 3425, 3545, 2863, + 0, 3697, 0, + 0, 3843, 0, + 0, 3987, 0, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4075, + 4095, 0, 4075, + 4095, 0, 4073, + 4095, 0, 4071, + 4095, 0, 4069, + 4095, 0, 4065, + 4095, 0, 4061, + 4095, 0, 4055, + 4095, 0, 4047, + 4095, 0, 4037, + 4095, 0, 4021, + 4095, 2001, 4001, + 4095, 2605, 3971, + 4095, 2917, 3927, + 4079, 3149, 3861, + 3997, 3343, 3757, + 3857, 3515, 3563, + 3557, 3677, 2995, + 0, 3829, 0, + 0, 3977, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2133, 4095, + 4095, 2737, 4095, + 4095, 3049, 4059, + 4095, 3281, 3993, + 4095, 3475, 3889, + 3989, 3649, 3695, + 3689, 3809, 3127, + 0, 3961, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2265, 4095, + 4095, 2869, 4095, + 4095, 3181, 4095, + 4095, 3413, 4095, + 4095, 3607, 4021, + 4095, 3781, 3827, + 3821, 3941, 3259, + 0, 0, 13, + 0, 54, 0, + 0, 186, 0, + 0, 318, 0, + 0, 450, 0, + 0, 582, 0, + 0, 714, 0, + 0, 846, 0, + 0, 978, 0, + 0, 1110, 0, + 0, 1242, 0, + 0, 1374, 0, + 0, 1506, 0, + 0, 1639, 0, + 0, 1771, 0, + 0, 1903, 0, + 0, 2035, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 258, 0, 216, + 36, 36, 36, + 0, 172, 0, + 0, 308, 0, + 0, 442, 0, + 0, 576, 0, + 0, 710, 0, + 0, 843, 0, + 0, 976, 0, + 0, 1108, 0, + 0, 1241, 0, + 0, 1373, 0, + 0, 1506, 0, + 0, 1638, 0, + 0, 1770, 0, + 0, 1903, 0, + 0, 2035, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 488, 0, 395, + 367, 11, 282, + 129, 154, 65, + 0, 294, 0, + 0, 432, 0, + 0, 569, 0, + 0, 704, 0, + 0, 839, 0, + 0, 973, 0, + 0, 1106, 0, + 0, 1239, 0, + 0, 1372, 0, + 0, 1505, 0, + 0, 1637, 0, + 0, 1770, 0, + 0, 1902, 0, + 0, 2034, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 681, 0, 560, + 606, 0, 484, + 481, 128, 357, + 230, 275, 101, + 0, 418, 0, + 0, 559, 0, + 0, 697, 0, + 0, 833, 0, + 0, 969, 0, + 0, 1103, 0, + 0, 1237, 0, + 0, 1370, 0, + 0, 1503, 0, + 0, 1636, 0, + 0, 1769, 0, + 0, 1902, 0, + 0, 2034, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 854, 0, 714, + 804, 0, 662, + 727, 91, 580, + 599, 249, 441, + 337, 399, 146, + 0, 544, 0, + 0, 686, 0, + 0, 826, 0, + 0, 963, 0, + 0, 1099, 0, + 0, 1234, 0, + 0, 1368, 0, + 0, 1502, 0, + 0, 1635, 0, + 0, 1768, 0, + 0, 1901, 0, + 0, 2033, 0, + 0, 2165, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1015, 0, 863, + 980, 0, 825, + 929, 36, 770, + 851, 210, 683, + 720, 372, 534, + 450, 525, 199, + 0, 672, 0, + 0, 815, 0, + 0, 955, 0, + 0, 1093, 0, + 0, 1229, 0, + 0, 1365, 0, + 0, 1499, 0, + 0, 1633, 0, + 0, 1767, 0, + 0, 1900, 0, + 0, 2033, 0, + 0, 2165, 0, + 0, 2297, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1167, 0, 1007, + 1142, 0, 980, + 1107, 0, 941, + 1056, 154, 883, + 977, 333, 793, + 844, 498, 634, + 567, 652, 262, + 0, 801, 0, + 0, 945, 0, + 0, 1085, 0, + 0, 1224, 0, + 0, 1361, 0, + 0, 1496, 0, + 0, 1631, 0, + 0, 1765, 0, + 0, 1899, 0, + 0, 2032, 0, + 0, 2165, 0, + 0, 2297, 0, + 0, 2429, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1313, 0, 1147, + 1296, 0, 1128, + 1271, 0, 1100, + 1236, 65, 1060, + 1184, 275, 1001, + 1104, 458, 907, + 969, 625, 741, + 687, 781, 334, + 0, 930, 0, + 0, 1075, 0, + 0, 1216, 0, + 0, 1355, 0, + 0, 1492, 0, + 0, 1628, 0, + 0, 1763, 0, + 0, 1897, 0, + 0, 2030, 0, + 0, 2163, 0, + 0, 2297, 0, + 0, 2429, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1456, 0, 1286, + 1443, 0, 1271, + 1425, 0, 1251, + 1401, 0, 1223, + 1365, 184, 1182, + 1313, 399, 1122, + 1233, 584, 1025, + 1097, 753, 853, + 810, 910, 416, + 0, 1060, 0, + 0, 1206, 0, + 0, 1347, 0, + 0, 1486, 0, + 0, 1624, 0, + 0, 1760, 0, + 0, 1894, 0, + 0, 2029, 0, + 0, 2163, 0, + 0, 2295, 0, + 0, 2429, 0, + 0, 2561, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1596, 0, 1422, + 1586, 0, 1412, + 1574, 0, 1397, + 1556, 0, 1377, + 1531, 23, 1348, + 1495, 306, 1307, + 1443, 525, 1245, + 1362, 712, 1147, + 1225, 882, 969, + 936, 1040, 506, + 0, 1191, 0, + 0, 1337, 0, + 0, 1479, 0, + 0, 1618, 0, + 0, 1755, 0, + 0, 1891, 0, + 0, 2026, 0, + 0, 2161, 0, + 0, 2295, 0, + 0, 2427, 0, + 0, 2561, 0, + 0, 2693, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1734, 0, 1558, + 1727, 0, 1550, + 1717, 0, 1539, + 1704, 0, 1525, + 1687, 0, 1504, + 1662, 141, 1475, + 1626, 430, 1434, + 1574, 652, 1371, + 1492, 841, 1271, + 1354, 1012, 1089, + 1063, 1171, 604, + 0, 1322, 0, + 0, 1468, 0, + 0, 1610, 0, + 0, 1750, 0, + 0, 1887, 0, + 0, 2023, 0, + 0, 2159, 0, + 0, 2293, 0, + 0, 2427, 0, + 0, 2559, 0, + 0, 2693, 0, + 0, 2825, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1870, 0, 1693, + 1865, 0, 1687, + 1858, 0, 1679, + 1848, 0, 1668, + 1836, 0, 1653, + 1818, 0, 1633, + 1793, 262, 1604, + 1757, 556, 1561, + 1704, 781, 1498, + 1623, 971, 1397, + 1485, 1142, 1212, + 1191, 1302, 709, + 0, 1453, 0, + 0, 1599, 0, + 0, 1742, 0, + 0, 1881, 0, + 0, 2019, 0, + 0, 2155, 0, + 0, 2291, 0, + 0, 2425, 0, + 0, 2559, 0, + 0, 2691, 0, + 0, 2825, 0, + 0, 2957, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2005, 0, 1827, + 2001, 0, 1822, + 1996, 0, 1817, + 1989, 0, 1809, + 1980, 0, 1798, + 1967, 0, 1783, + 1949, 0, 1762, + 1924, 386, 1733, + 1888, 684, 1690, + 1836, 910, 1627, + 1754, 1101, 1524, + 1615, 1273, 1337, + 1320, 1433, 819, + 0, 1585, 0, + 0, 1731, 0, + 0, 1874, 0, + 0, 2013, 0, + 0, 2151, 0, + 0, 2287, 0, + 0, 2423, 0, + 0, 2557, 0, + 0, 2691, 0, + 0, 2823, 0, + 0, 2957, 0, + 0, 3089, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2139, 0, 1960, + 2137, 0, 1957, + 2133, 0, 1953, + 2127, 0, 1947, + 2121, 0, 1939, + 2111, 0, 1928, + 2099, 0, 1913, + 2081, 0, 1892, + 2055, 511, 1863, + 2020, 813, 1820, + 1967, 1040, 1756, + 1885, 1232, 1653, + 1746, 1405, 1464, + 1450, 1565, 935, + 0, 1717, 0, + 0, 1863, 0, + 0, 2005, 0, + 0, 2145, 0, + 0, 2283, 0, + 0, 2419, 0, + 0, 2555, 0, + 0, 2689, 0, + 0, 2823, 0, + 0, 2957, 0, + 0, 3089, 0, + 0, 3221, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3885, 0, + 0, 4017, 0, + 2273, 0, 2093, + 2271, 0, 2091, + 2269, 0, 2087, + 2265, 0, 2083, + 2259, 0, 2077, + 2253, 0, 2069, + 2243, 0, 2059, + 2231, 0, 2044, + 2213, 72, 2023, + 2187, 638, 1993, + 2151, 943, 1950, + 2099, 1171, 1886, + 2017, 1363, 1783, + 1877, 1536, 1592, + 1580, 1696, 1054, + 0, 1848, 0, + 0, 1995, 0, + 0, 2137, 0, + 0, 2277, 0, + 0, 2415, 0, + 0, 2551, 0, + 0, 2687, 0, + 0, 2821, 0, + 0, 2955, 0, + 0, 3089, 0, + 0, 3221, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3885, 0, + 0, 4017, 0, + 2407, 0, 2227, + 2405, 0, 2225, + 2403, 0, 2223, + 2401, 0, 2219, + 2397, 0, 2215, + 2391, 0, 2209, + 2385, 0, 2201, + 2375, 0, 2189, + 2363, 0, 2175, + 2345, 192, 2153, + 2319, 767, 2125, + 2283, 1073, 2081, + 2231, 1302, 2017, + 2149, 1495, 1913, + 2009, 1668, 1722, + 1711, 1828, 1176, + 0, 1980, 0, + 0, 2127, 0, + 0, 2269, 0, + 0, 2409, 0, + 0, 2547, 0, + 0, 2683, 0, + 0, 2819, 0, + 0, 2953, 0, + 0, 3087, 0, + 0, 3221, 0, + 0, 3353, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4017, 0, + 2539, 0, 2359, + 2539, 0, 2357, + 2537, 0, 2357, + 2535, 0, 2353, + 2533, 0, 2351, + 2529, 0, 2345, + 2523, 0, 2341, + 2517, 0, 2333, + 2507, 0, 2321, + 2495, 0, 2305, + 2477, 314, 2285, + 2451, 896, 2255, + 2415, 1203, 2213, + 2363, 1433, 2147, + 2281, 1626, 2043, + 2141, 1799, 1851, + 1842, 1960, 1301, + 0, 2113, 0, + 0, 2259, 0, + 0, 2401, 0, + 0, 2541, 0, + 0, 2679, 0, + 0, 2815, 0, + 0, 2951, 0, + 0, 3085, 0, + 0, 3219, 0, + 0, 3353, 0, + 0, 3485, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 2673, 0, 2491, + 2671, 0, 2491, + 2671, 0, 2489, + 2669, 0, 2487, + 2667, 0, 2485, + 2665, 0, 2481, + 2661, 0, 2477, + 2655, 0, 2471, + 2649, 0, 2463, + 2639, 0, 2453, + 2627, 0, 2437, + 2609, 438, 2417, + 2583, 1026, 2387, + 2547, 1334, 2343, + 2495, 1564, 2279, + 2413, 1758, 2175, + 2273, 1931, 1982, + 1974, 2091, 1427, + 0, 2245, 0, + 0, 2391, 0, + 0, 2533, 0, + 0, 2673, 0, + 0, 2811, 0, + 0, 2947, 0, + 0, 3083, 0, + 0, 3217, 0, + 0, 3351, 0, + 0, 3485, 0, + 0, 3617, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 2805, 0, 2625, + 2805, 0, 2623, + 2803, 0, 2623, + 2803, 0, 2621, + 2801, 0, 2619, + 2799, 0, 2617, + 2797, 0, 2613, + 2793, 0, 2609, + 2787, 0, 2603, + 2781, 0, 2595, + 2771, 0, 2585, + 2759, 0, 2569, + 2741, 565, 2549, + 2715, 1157, 2519, + 2679, 1466, 2475, + 2627, 1696, 2411, + 2543, 1890, 2305, + 2405, 2063, 2113, + 2105, 2223, 1555, + 0, 2377, 0, + 0, 2523, 0, + 0, 2665, 0, + 0, 2805, 0, + 0, 2943, 0, + 0, 3079, 0, + 0, 3215, 0, + 0, 3349, 0, + 0, 3483, 0, + 0, 3617, 0, + 0, 3749, 0, + 0, 3883, 0, + 0, 4015, 0, + 2937, 0, 2757, + 2937, 0, 2755, + 2937, 0, 2755, + 2935, 0, 2755, + 2935, 0, 2753, + 2933, 0, 2751, + 2931, 0, 2749, + 2929, 0, 2745, + 2925, 0, 2741, + 2919, 0, 2735, + 2913, 0, 2727, + 2903, 0, 2717, + 2891, 0, 2701, + 2873, 693, 2679, + 2847, 1288, 2651, + 2811, 1597, 2607, + 2759, 1828, 2541, + 2675, 2022, 2437, + 2537, 2195, 2243, + 2237, 2355, 1684, + 0, 2509, 0, + 0, 2655, 0, + 0, 2797, 0, + 0, 2937, 0, + 0, 3075, 0, + 0, 3211, 0, + 0, 3347, 0, + 0, 3481, 0, + 0, 3615, 0, + 0, 3749, 0, + 0, 3881, 0, + 0, 4015, 0, + 3071, 0, 2889, + 3071, 0, 2889, + 3069, 0, 2887, + 3069, 0, 2887, + 3069, 0, 2887, + 3067, 0, 2885, + 3065, 0, 2883, + 3063, 0, 2881, + 3061, 0, 2877, + 3057, 0, 2873, + 3051, 0, 2867, + 3045, 0, 2859, + 3035, 0, 2847, + 3023, 0, 2833, + 3005, 821, 2811, + 2979, 1419, 2781, + 2943, 1729, 2739, + 2891, 1960, 2673, + 2807, 2153, 2569, + 2669, 2327, 2375, + 2369, 2487, 1813, + 0, 2641, 0, + 0, 2787, 0, + 0, 2929, 0, + 0, 3069, 0, + 0, 3207, 0, + 0, 3343, 0, + 0, 3479, 0, + 0, 3613, 0, + 0, 3747, 0, + 0, 3881, 0, + 0, 4015, 0, + 3203, 0, 3021, + 3203, 0, 3021, + 3203, 0, 3021, + 3201, 0, 3019, + 3201, 0, 3019, + 3201, 0, 3019, + 3199, 0, 3017, + 3197, 0, 3015, + 3195, 0, 3013, + 3193, 0, 3009, + 3189, 0, 3005, + 3183, 0, 2999, + 3177, 0, 2991, + 3167, 0, 2979, + 3155, 0, 2965, + 3137, 951, 2943, + 3111, 1550, 2913, + 3075, 1861, 2871, + 3023, 2091, 2805, + 2941, 2285, 2701, + 2801, 2459, 2507, + 2501, 2619, 1944, + 0, 2773, 0, + 0, 2919, 0, + 0, 3061, 0, + 0, 3201, 0, + 0, 3339, 0, + 0, 3477, 0, + 0, 3611, 0, + 0, 3745, 0, + 0, 3879, 0, + 0, 4013, 0, + 3335, 0, 3153, + 3335, 0, 3153, + 3335, 0, 3153, + 3335, 0, 3153, + 3333, 0, 3151, + 3333, 0, 3151, + 3333, 0, 3151, + 3331, 0, 3149, + 3329, 0, 3147, + 3327, 0, 3145, + 3325, 0, 3141, + 3321, 0, 3137, + 3315, 0, 3131, + 3309, 0, 3123, + 3299, 0, 3111, + 3287, 0, 3097, + 3269, 1081, 3075, + 3243, 1682, 3045, + 3207, 1993, 3003, + 3155, 2223, 2937, + 3073, 2417, 2833, + 2933, 2591, 2639, + 2633, 2753, 2075, + 0, 2905, 0, + 0, 3051, 0, + 0, 3193, 0, + 0, 3333, 0, + 0, 3471, 0, + 0, 3609, 0, + 0, 3743, 0, + 0, 3877, 0, + 0, 4011, 0, + 3467, 0, 3285, + 3467, 0, 3285, + 3467, 0, 3285, + 3467, 0, 3285, + 3467, 0, 3285, + 3465, 0, 3283, + 3465, 0, 3283, + 3465, 0, 3283, + 3463, 0, 3281, + 3461, 0, 3279, + 3459, 0, 3277, + 3457, 0, 3273, + 3453, 0, 3269, + 3447, 0, 3263, + 3441, 0, 3255, + 3431, 0, 3243, + 3419, 0, 3229, + 3401, 1212, 3207, + 3375, 1814, 3177, + 3339, 2125, 3135, + 3287, 2355, 3069, + 3205, 2549, 2965, + 3065, 2723, 2771, + 2765, 2885, 2205, + 0, 3037, 0, + 0, 3183, 0, + 0, 3327, 0, + 0, 3467, 0, + 0, 3603, 0, + 0, 3741, 0, + 0, 3875, 0, + 0, 4009, 0, + 3599, 0, 3417, + 3599, 0, 3417, + 3599, 0, 3417, + 3599, 0, 3417, + 3599, 0, 3417, + 3599, 0, 3417, + 3597, 0, 3415, + 3597, 0, 3415, + 3597, 0, 3415, + 3595, 0, 3413, + 3593, 0, 3411, + 3591, 0, 3409, + 3589, 0, 3405, + 3585, 0, 3401, + 3579, 0, 3395, + 3573, 0, 3387, + 3563, 0, 3375, + 3551, 0, 3361, + 3533, 1343, 3339, + 3507, 1946, 3309, + 3471, 2257, 3267, + 3419, 2487, 3201, + 3337, 2681, 3097, + 3197, 2855, 2903, + 2897, 3017, 2337, + 0, 3169, 0, + 0, 3315, 0, + 0, 3459, 0, + 0, 3599, 0, + 0, 3735, 0, + 0, 3873, 0, + 0, 4007, 0, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3729, 0, 3547, + 3729, 0, 3547, + 3727, 0, 3545, + 3725, 0, 3543, + 3723, 0, 3541, + 3721, 0, 3537, + 3717, 0, 3533, + 3711, 0, 3527, + 3705, 0, 3519, + 3695, 0, 3507, + 3683, 0, 3493, + 3665, 1474, 3471, + 3639, 2077, 3441, + 3603, 2389, 3399, + 3551, 2619, 3333, + 3469, 2813, 3229, + 3329, 2987, 3035, + 3029, 3149, 2469, + 0, 3301, 0, + 0, 3447, 0, + 0, 3591, 0, + 0, 3731, 0, + 0, 3869, 0, + 0, 4005, 0, + 3863, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3861, 0, 3679, + 3861, 0, 3679, + 3859, 0, 3677, + 3857, 0, 3675, + 3855, 0, 3673, + 3853, 0, 3669, + 3849, 0, 3665, + 3845, 0, 3659, + 3837, 0, 3651, + 3827, 0, 3641, + 3815, 0, 3625, + 3797, 1606, 3603, + 3771, 2209, 3573, + 3735, 2521, 3531, + 3683, 2751, 3465, + 3601, 2947, 3361, + 3461, 3119, 3167, + 3161, 3281, 2601, + 0, 3433, 0, + 0, 3579, 0, + 0, 3723, 0, + 0, 3863, 0, + 0, 4001, 0, + 3997, 0, 3815, + 3997, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3813, + 3995, 0, 3813, + 3995, 0, 3813, + 3995, 0, 3813, + 3995, 0, 3813, + 3995, 0, 3813, + 3993, 0, 3811, + 3993, 0, 3811, + 3991, 0, 3809, + 3991, 0, 3807, + 3987, 0, 3805, + 3985, 0, 3801, + 3981, 0, 3797, + 3977, 0, 3791, + 3969, 0, 3783, + 3959, 0, 3773, + 3947, 0, 3757, + 3929, 1738, 3735, + 3903, 2341, 3707, + 3867, 2653, 3663, + 3815, 2883, 3597, + 3733, 3079, 3493, + 3593, 3251, 3299, + 3293, 3413, 2731, + 0, 3565, 0, + 0, 3711, 0, + 0, 3855, 0, + 0, 3995, 0, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3943, + 4095, 0, 3943, + 4095, 0, 3941, + 4095, 0, 3939, + 4095, 0, 3937, + 4095, 0, 3933, + 4095, 0, 3929, + 4095, 0, 3923, + 4095, 0, 3915, + 4091, 0, 3905, + 4079, 0, 3889, + 4061, 1869, 3867, + 4035, 2473, 3839, + 3999, 2785, 3795, + 3947, 3015, 3729, + 3865, 3211, 3625, + 3725, 3383, 3431, + 3425, 3545, 2863, + 0, 3697, 0, + 0, 3843, 0, + 0, 3987, 0, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4075, + 4095, 0, 4075, + 4095, 0, 4073, + 4095, 0, 4071, + 4095, 0, 4069, + 4095, 0, 4065, + 4095, 0, 4061, + 4095, 0, 4055, + 4095, 0, 4047, + 4095, 0, 4037, + 4095, 0, 4021, + 4095, 2001, 4001, + 4095, 2605, 3971, + 4095, 2917, 3927, + 4079, 3149, 3861, + 3997, 3343, 3757, + 3857, 3515, 3563, + 3557, 3677, 2995, + 0, 3829, 0, + 0, 3977, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2133, 4095, + 4095, 2737, 4095, + 4095, 3049, 4059, + 4095, 3281, 3993, + 4095, 3475, 3889, + 3989, 3649, 3695, + 3689, 3809, 3127, + 0, 3961, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2265, 4095, + 4095, 2869, 4095, + 4095, 3181, 4095, + 4095, 3413, 4095, + 4095, 3607, 4021, + 4095, 3781, 3827, + 3821, 3941, 3259, + 7, 0, 127, + 0, 71, 0, + 0, 199, 0, + 0, 328, 0, + 0, 457, 0, + 0, 587, 0, + 0, 718, 0, + 0, 849, 0, + 0, 980, 0, + 0, 1112, 0, + 0, 1243, 0, + 0, 1375, 0, + 0, 1507, 0, + 0, 1639, 0, + 0, 1771, 0, + 0, 1903, 0, + 0, 2035, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 287, 0, 292, + 83, 54, 145, + 0, 186, 0, + 0, 318, 0, + 0, 450, 0, + 0, 582, 0, + 0, 714, 0, + 0, 846, 0, + 0, 978, 0, + 0, 1110, 0, + 0, 1242, 0, + 0, 1374, 0, + 0, 1506, 0, + 0, 1639, 0, + 0, 1771, 0, + 0, 1903, 0, + 0, 2035, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 506, 0, 448, + 390, 30, 348, + 168, 168, 168, + 0, 304, 0, + 0, 440, 0, + 0, 574, 0, + 0, 708, 0, + 0, 842, 0, + 0, 975, 0, + 0, 1108, 0, + 0, 1240, 0, + 0, 1373, 0, + 0, 1505, 0, + 0, 1638, 0, + 0, 1770, 0, + 0, 1902, 0, + 0, 2035, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 693, 0, 597, + 620, 0, 527, + 499, 143, 414, + 261, 286, 197, + 0, 426, 0, + 0, 564, 0, + 0, 701, 0, + 0, 836, 0, + 0, 971, 0, + 0, 1105, 0, + 0, 1238, 0, + 0, 1371, 0, + 0, 1504, 0, + 0, 1637, 0, + 0, 1769, 0, + 0, 1902, 0, + 0, 2034, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 862, 0, 741, + 813, 0, 692, + 738, 107, 616, + 613, 260, 489, + 362, 407, 233, + 0, 550, 0, + 0, 691, 0, + 0, 829, 0, + 0, 965, 0, + 0, 1100, 0, + 0, 1235, 0, + 0, 1369, 0, + 0, 1502, 0, + 0, 1636, 0, + 0, 1768, 0, + 0, 1901, 0, + 0, 2034, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1020, 0, 882, + 986, 0, 846, + 936, 54, 794, + 859, 223, 712, + 731, 381, 573, + 469, 531, 278, + 0, 677, 0, + 0, 818, 0, + 0, 958, 0, + 0, 1095, 0, + 0, 1231, 0, + 0, 1366, 0, + 0, 1500, 0, + 0, 1634, 0, + 0, 1767, 0, + 0, 1900, 0, + 0, 2033, 0, + 0, 2165, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1171, 0, 1021, + 1146, 0, 995, + 1112, 0, 957, + 1061, 168, 902, + 983, 343, 815, + 852, 504, 666, + 582, 657, 331, + 0, 804, 0, + 0, 947, 0, + 0, 1087, 0, + 0, 1225, 0, + 0, 1362, 0, + 0, 1497, 0, + 0, 1632, 0, + 0, 1765, 0, + 0, 1899, 0, + 0, 2032, 0, + 0, 2165, 0, + 0, 2297, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1316, 0, 1158, + 1299, 0, 1139, + 1274, 0, 1112, + 1239, 82, 1073, + 1188, 286, 1015, + 1109, 465, 925, + 976, 630, 766, + 699, 784, 394, + 0, 933, 0, + 0, 1077, 0, + 0, 1217, 0, + 0, 1356, 0, + 0, 1493, 0, + 0, 1628, 0, + 0, 1763, 0, + 0, 1897, 0, + 0, 2031, 0, + 0, 2163, 0, + 0, 2297, 0, + 0, 2429, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1458, 0, 1293, + 1445, 0, 1279, + 1428, 0, 1260, + 1403, 0, 1232, + 1368, 197, 1192, + 1316, 407, 1133, + 1236, 590, 1039, + 1101, 757, 873, + 819, 913, 466, + 0, 1062, 0, + 0, 1207, 0, + 0, 1348, 0, + 0, 1487, 0, + 0, 1624, 0, + 0, 1760, 0, + 0, 1895, 0, + 0, 2029, 0, + 0, 2163, 0, + 0, 2295, 0, + 0, 2429, 0, + 0, 2561, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1597, 0, 1428, + 1588, 0, 1418, + 1575, 0, 1403, + 1558, 0, 1383, + 1533, 42, 1355, + 1497, 316, 1315, + 1445, 531, 1254, + 1365, 717, 1157, + 1229, 885, 985, + 943, 1042, 548, + 0, 1192, 0, + 0, 1338, 0, + 0, 1479, 0, + 0, 1618, 0, + 0, 1756, 0, + 0, 1892, 0, + 0, 2027, 0, + 0, 2161, 0, + 0, 2295, 0, + 0, 2427, 0, + 0, 2561, 0, + 0, 2693, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1735, 0, 1562, + 1728, 0, 1555, + 1718, 0, 1544, + 1706, 0, 1529, + 1688, 0, 1509, + 1663, 155, 1480, + 1628, 438, 1439, + 1575, 657, 1377, + 1494, 845, 1279, + 1357, 1014, 1101, + 1068, 1172, 638, + 0, 1323, 0, + 0, 1469, 0, + 0, 1611, 0, + 0, 1750, 0, + 0, 1887, 0, + 0, 2023, 0, + 0, 2159, 0, + 0, 2293, 0, + 0, 2427, 0, + 0, 2559, 0, + 0, 2693, 0, + 0, 2825, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1871, 0, 1696, + 1866, 0, 1690, + 1859, 0, 1682, + 1849, 0, 1672, + 1837, 0, 1657, + 1819, 0, 1636, + 1794, 273, 1607, + 1758, 562, 1566, + 1706, 784, 1503, + 1624, 974, 1403, + 1487, 1144, 1221, + 1195, 1303, 736, + 0, 1454, 0, + 0, 1600, 0, + 0, 1742, 0, + 0, 1882, 0, + 0, 2019, 0, + 0, 2155, 0, + 0, 2291, 0, + 0, 2425, 0, + 0, 2559, 0, + 0, 2691, 0, + 0, 2825, 0, + 0, 2957, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2006, 0, 1829, + 2002, 0, 1825, + 1997, 0, 1819, + 1990, 0, 1811, + 1981, 0, 1800, + 1968, 0, 1785, + 1950, 0, 1765, + 1925, 394, 1736, + 1889, 689, 1694, + 1837, 913, 1630, + 1755, 1103, 1529, + 1617, 1275, 1344, + 1323, 1434, 841, + 0, 1585, 0, + 0, 1732, 0, + 0, 1874, 0, + 0, 2013, 0, + 0, 2151, 0, + 0, 2287, 0, + 0, 2423, 0, + 0, 2557, 0, + 0, 2691, 0, + 0, 2825, 0, + 0, 2957, 0, + 0, 3089, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2141, 0, 1962, + 2137, 0, 1959, + 2133, 0, 1955, + 2129, 0, 1949, + 2121, 0, 1941, + 2113, 0, 1930, + 2099, 0, 1915, + 2081, 0, 1894, + 2057, 518, 1865, + 2020, 816, 1822, + 1968, 1042, 1759, + 1886, 1234, 1657, + 1747, 1405, 1470, + 1452, 1565, 952, + 0, 1717, 0, + 0, 1863, 0, + 0, 2006, 0, + 0, 2145, 0, + 0, 2283, 0, + 0, 2419, 0, + 0, 2555, 0, + 0, 2689, 0, + 0, 2823, 0, + 0, 2957, 0, + 0, 3089, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3885, 0, + 0, 4017, 0, + 2273, 0, 2095, + 2271, 0, 2093, + 2269, 0, 2089, + 2265, 0, 2085, + 2259, 0, 2079, + 2253, 0, 2071, + 2243, 0, 2061, + 2231, 0, 2045, + 2213, 89, 2024, + 2187, 643, 1995, + 2151, 945, 1952, + 2099, 1172, 1888, + 2017, 1364, 1785, + 1878, 1537, 1596, + 1582, 1697, 1067, + 0, 1849, 0, + 0, 1995, 0, + 0, 2137, 0, + 0, 2277, 0, + 0, 2415, 0, + 0, 2551, 0, + 0, 2687, 0, + 0, 2821, 0, + 0, 2955, 0, + 0, 3089, 0, + 0, 3221, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3885, 0, + 0, 4017, 0, + 2407, 0, 2227, + 2405, 0, 2225, + 2403, 0, 2223, + 2401, 0, 2219, + 2397, 0, 2215, + 2391, 0, 2209, + 2385, 0, 2201, + 2375, 0, 2191, + 2363, 0, 2175, + 2345, 205, 2155, + 2319, 771, 2125, + 2283, 1074, 2083, + 2231, 1303, 2018, + 2149, 1495, 1915, + 2010, 1668, 1725, + 1713, 1828, 1186, + 0, 1980, 0, + 0, 2127, 0, + 0, 2269, 0, + 0, 2409, 0, + 0, 2547, 0, + 0, 2683, 0, + 0, 2819, 0, + 0, 2953, 0, + 0, 3087, 0, + 0, 3221, 0, + 0, 3353, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4017, 0, + 2541, 0, 2359, + 2539, 0, 2359, + 2537, 0, 2357, + 2535, 0, 2355, + 2533, 0, 2351, + 2529, 0, 2347, + 2523, 0, 2341, + 2517, 0, 2333, + 2507, 0, 2321, + 2495, 0, 2307, + 2477, 324, 2285, + 2451, 899, 2257, + 2415, 1205, 2213, + 2363, 1434, 2149, + 2281, 1627, 2045, + 2141, 1800, 1854, + 1843, 1960, 1308, + 0, 2113, 0, + 0, 2259, 0, + 0, 2401, 0, + 0, 2541, 0, + 0, 2679, 0, + 0, 2815, 0, + 0, 2951, 0, + 0, 3085, 0, + 0, 3219, 0, + 0, 3353, 0, + 0, 3485, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 2673, 0, 2493, + 2673, 0, 2491, + 2671, 0, 2489, + 2669, 0, 2489, + 2667, 0, 2485, + 2665, 0, 2483, + 2661, 0, 2479, + 2655, 0, 2473, + 2649, 0, 2465, + 2639, 0, 2453, + 2627, 0, 2439, + 2609, 446, 2417, + 2583, 1028, 2387, + 2547, 1335, 2345, + 2495, 1565, 2279, + 2413, 1758, 2175, + 2273, 1932, 1984, + 1975, 2093, 1433, + 0, 2245, 0, + 0, 2391, 0, + 0, 2533, 0, + 0, 2673, 0, + 0, 2811, 0, + 0, 2947, 0, + 0, 3083, 0, + 0, 3217, 0, + 0, 3351, 0, + 0, 3485, 0, + 0, 3617, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 2805, 0, 2625, + 2805, 0, 2623, + 2805, 0, 2623, + 2803, 0, 2621, + 2801, 0, 2619, + 2799, 0, 2617, + 2797, 0, 2615, + 2793, 0, 2609, + 2787, 0, 2603, + 2781, 0, 2595, + 2771, 0, 2585, + 2759, 0, 2569, + 2741, 570, 2549, + 2715, 1158, 2519, + 2679, 1467, 2475, + 2627, 1697, 2411, + 2545, 1890, 2307, + 2405, 2063, 2113, + 2107, 2223, 1559, + 0, 2377, 0, + 0, 2523, 0, + 0, 2665, 0, + 0, 2805, 0, + 0, 2943, 0, + 0, 3079, 0, + 0, 3215, 0, + 0, 3349, 0, + 0, 3483, 0, + 0, 3617, 0, + 0, 3749, 0, + 0, 3883, 0, + 0, 4015, 0, + 2939, 0, 2757, + 2937, 0, 2757, + 2937, 0, 2755, + 2937, 0, 2755, + 2935, 0, 2753, + 2933, 0, 2751, + 2931, 0, 2749, + 2929, 0, 2745, + 2925, 0, 2741, + 2919, 0, 2735, + 2913, 0, 2727, + 2903, 0, 2717, + 2891, 0, 2701, + 2873, 697, 2681, + 2847, 1289, 2651, + 2811, 1598, 2607, + 2759, 1828, 2543, + 2677, 2022, 2437, + 2537, 2195, 2245, + 2237, 2355, 1687, + 0, 2509, 0, + 0, 2655, 0, + 0, 2797, 0, + 0, 2937, 0, + 0, 3075, 0, + 0, 3211, 0, + 0, 3347, 0, + 0, 3481, 0, + 0, 3615, 0, + 0, 3749, 0, + 0, 3881, 0, + 0, 4015, 0, + 3071, 0, 2889, + 3071, 0, 2889, + 3069, 0, 2889, + 3069, 0, 2887, + 3069, 0, 2887, + 3067, 0, 2885, + 3065, 0, 2883, + 3063, 0, 2881, + 3061, 0, 2877, + 3057, 0, 2873, + 3051, 0, 2867, + 3045, 0, 2859, + 3035, 0, 2849, + 3023, 0, 2833, + 3005, 825, 2811, + 2979, 1420, 2783, + 2943, 1729, 2739, + 2891, 1960, 2673, + 2809, 2153, 2569, + 2669, 2327, 2377, + 2369, 2487, 1816, + 0, 2641, 0, + 0, 2787, 0, + 0, 2929, 0, + 0, 3069, 0, + 0, 3207, 0, + 0, 3343, 0, + 0, 3479, 0, + 0, 3613, 0, + 0, 3747, 0, + 0, 3881, 0, + 0, 4015, 0, + 3203, 0, 3021, + 3203, 0, 3021, + 3203, 0, 3021, + 3201, 0, 3021, + 3201, 0, 3019, + 3201, 0, 3019, + 3199, 0, 3017, + 3197, 0, 3015, + 3195, 0, 3013, + 3193, 0, 3009, + 3189, 0, 3005, + 3183, 0, 2999, + 3177, 0, 2991, + 3167, 0, 2981, + 3155, 0, 2965, + 3137, 954, 2943, + 3111, 1551, 2913, + 3075, 1861, 2871, + 3023, 2091, 2805, + 2941, 2285, 2701, + 2801, 2459, 2507, + 2501, 2621, 1945, + 0, 2773, 0, + 0, 2919, 0, + 0, 3061, 0, + 0, 3201, 0, + 0, 3339, 0, + 0, 3477, 0, + 0, 3611, 0, + 0, 3745, 0, + 0, 3879, 0, + 0, 4013, 0, + 3335, 0, 3153, + 3335, 0, 3153, + 3335, 0, 3153, + 3335, 0, 3153, + 3333, 0, 3151, + 3333, 0, 3151, + 3333, 0, 3151, + 3331, 0, 3149, + 3329, 0, 3147, + 3327, 0, 3145, + 3325, 0, 3141, + 3321, 0, 3137, + 3315, 0, 3131, + 3309, 0, 3123, + 3299, 0, 3111, + 3287, 0, 3097, + 3269, 1083, 3075, + 3243, 1682, 3045, + 3207, 1993, 3003, + 3155, 2223, 2937, + 3073, 2417, 2833, + 2933, 2591, 2639, + 2633, 2753, 2075, + 0, 2905, 0, + 0, 3051, 0, + 0, 3193, 0, + 0, 3333, 0, + 0, 3471, 0, + 0, 3609, 0, + 0, 3743, 0, + 0, 3877, 0, + 0, 4011, 0, + 3467, 0, 3285, + 3467, 0, 3285, + 3467, 0, 3285, + 3467, 0, 3285, + 3467, 0, 3285, + 3465, 0, 3283, + 3465, 0, 3283, + 3465, 0, 3283, + 3463, 0, 3281, + 3461, 0, 3279, + 3459, 0, 3277, + 3457, 0, 3273, + 3453, 0, 3269, + 3447, 0, 3263, + 3441, 0, 3255, + 3431, 0, 3243, + 3419, 0, 3229, + 3401, 1213, 3207, + 3375, 1814, 3177, + 3339, 2125, 3135, + 3287, 2355, 3069, + 3205, 2549, 2965, + 3065, 2723, 2771, + 2765, 2885, 2207, + 0, 3037, 0, + 0, 3183, 0, + 0, 3327, 0, + 0, 3467, 0, + 0, 3603, 0, + 0, 3741, 0, + 0, 3875, 0, + 0, 4009, 0, + 3599, 0, 3417, + 3599, 0, 3417, + 3599, 0, 3417, + 3599, 0, 3417, + 3599, 0, 3417, + 3599, 0, 3417, + 3597, 0, 3417, + 3597, 0, 3415, + 3597, 0, 3415, + 3595, 0, 3413, + 3593, 0, 3411, + 3591, 0, 3409, + 3589, 0, 3405, + 3585, 0, 3401, + 3579, 0, 3395, + 3573, 0, 3387, + 3563, 0, 3377, + 3551, 0, 3361, + 3533, 1344, 3339, + 3507, 1946, 3309, + 3471, 2257, 3267, + 3419, 2487, 3201, + 3337, 2681, 3097, + 3197, 2855, 2903, + 2897, 3017, 2337, + 0, 3169, 0, + 0, 3315, 0, + 0, 3459, 0, + 0, 3599, 0, + 0, 3737, 0, + 0, 3873, 0, + 0, 4007, 0, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3729, 0, 3547, + 3729, 0, 3547, + 3727, 0, 3545, + 3725, 0, 3543, + 3723, 0, 3541, + 3721, 0, 3537, + 3717, 0, 3533, + 3711, 0, 3527, + 3705, 0, 3519, + 3695, 0, 3509, + 3683, 0, 3493, + 3665, 1475, 3471, + 3639, 2077, 3441, + 3603, 2389, 3399, + 3551, 2619, 3333, + 3469, 2813, 3229, + 3329, 2987, 3035, + 3029, 3149, 2469, + 0, 3301, 0, + 0, 3447, 0, + 0, 3591, 0, + 0, 3731, 0, + 0, 3869, 0, + 0, 4005, 0, + 3863, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3861, 0, 3679, + 3861, 0, 3679, + 3859, 0, 3677, + 3857, 0, 3675, + 3855, 0, 3673, + 3853, 0, 3669, + 3849, 0, 3665, + 3845, 0, 3659, + 3837, 0, 3651, + 3827, 0, 3641, + 3815, 0, 3625, + 3797, 1606, 3603, + 3771, 2209, 3573, + 3735, 2521, 3531, + 3683, 2751, 3465, + 3601, 2947, 3361, + 3461, 3119, 3167, + 3161, 3281, 2601, + 0, 3433, 0, + 0, 3579, 0, + 0, 3723, 0, + 0, 3863, 0, + 0, 4001, 0, + 3997, 0, 3815, + 3997, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3813, + 3995, 0, 3813, + 3995, 0, 3813, + 3995, 0, 3813, + 3995, 0, 3813, + 3995, 0, 3813, + 3993, 0, 3811, + 3993, 0, 3811, + 3991, 0, 3809, + 3991, 0, 3807, + 3987, 0, 3805, + 3985, 0, 3801, + 3981, 0, 3797, + 3977, 0, 3791, + 3969, 0, 3783, + 3959, 0, 3773, + 3947, 0, 3757, + 3929, 1738, 3735, + 3903, 2341, 3707, + 3867, 2653, 3663, + 3815, 2883, 3597, + 3733, 3079, 3493, + 3593, 3251, 3299, + 3293, 3413, 2733, + 0, 3565, 0, + 0, 3711, 0, + 0, 3855, 0, + 0, 3995, 0, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3943, + 4095, 0, 3943, + 4095, 0, 3941, + 4095, 0, 3939, + 4095, 0, 3937, + 4095, 0, 3933, + 4095, 0, 3929, + 4095, 0, 3923, + 4095, 0, 3915, + 4091, 0, 3905, + 4079, 0, 3889, + 4061, 1870, 3869, + 4035, 2473, 3839, + 3999, 2785, 3795, + 3947, 3017, 3729, + 3865, 3211, 3625, + 3725, 3383, 3431, + 3425, 3545, 2863, + 0, 3697, 0, + 0, 3843, 0, + 0, 3987, 0, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4075, + 4095, 0, 4075, + 4095, 0, 4073, + 4095, 0, 4071, + 4095, 0, 4069, + 4095, 0, 4065, + 4095, 0, 4061, + 4095, 0, 4055, + 4095, 0, 4047, + 4095, 0, 4037, + 4095, 0, 4021, + 4095, 2002, 4001, + 4095, 2605, 3971, + 4095, 2917, 3927, + 4079, 3149, 3861, + 3997, 3343, 3757, + 3857, 3515, 3563, + 3557, 3677, 2995, + 0, 3829, 0, + 0, 3977, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2133, 4095, + 4095, 2737, 4095, + 4095, 3049, 4059, + 4095, 3281, 3993, + 4095, 3475, 3889, + 3989, 3649, 3695, + 3689, 3809, 3127, + 0, 3961, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2265, 4095, + 4095, 2869, 4095, + 4095, 3181, 4095, + 4095, 3413, 4095, + 4095, 3607, 4021, + 4095, 3781, 3827, + 3821, 3941, 3259, + 73, 0, 245, + 0, 93, 78, + 0, 216, 0, + 0, 340, 0, + 0, 467, 0, + 0, 595, 0, + 0, 724, 0, + 0, 853, 0, + 0, 984, 0, + 0, 1114, 0, + 0, 1245, 0, + 0, 1377, 0, + 0, 1508, 0, + 0, 1640, 0, + 0, 1772, 0, + 0, 1904, 0, + 0, 2035, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 324, 0, 378, + 139, 77, 259, + 0, 203, 27, + 0, 331, 0, + 0, 460, 0, + 0, 589, 0, + 0, 719, 0, + 0, 850, 0, + 0, 981, 0, + 0, 1112, 0, + 0, 1244, 0, + 0, 1376, 0, + 0, 1507, 0, + 0, 1639, 0, + 0, 1771, 0, + 0, 1903, 0, + 0, 2035, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 528, 0, 510, + 420, 54, 424, + 215, 186, 277, + 0, 318, 0, + 0, 450, 0, + 0, 582, 0, + 0, 714, 0, + 0, 846, 0, + 0, 978, 0, + 0, 1110, 0, + 0, 1242, 0, + 0, 1374, 0, + 0, 1506, 0, + 0, 1639, 0, + 0, 1771, 0, + 0, 1903, 0, + 0, 2035, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 708, 0, 642, + 638, 21, 580, + 522, 162, 481, + 300, 300, 300, + 0, 437, 0, + 0, 572, 0, + 0, 707, 0, + 0, 841, 0, + 0, 974, 0, + 0, 1107, 0, + 0, 1240, 0, + 0, 1373, 0, + 0, 1505, 0, + 0, 1638, 0, + 0, 1770, 0, + 0, 1902, 0, + 0, 2035, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 873, 0, 775, + 825, 0, 729, + 752, 127, 659, + 631, 275, 546, + 393, 418, 329, + 0, 558, 0, + 0, 696, 0, + 0, 833, 0, + 0, 968, 0, + 0, 1103, 0, + 0, 1237, 0, + 0, 1370, 0, + 0, 1503, 0, + 0, 1636, 0, + 0, 1769, 0, + 0, 1902, 0, + 0, 2034, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1028, 0, 907, + 994, 0, 873, + 945, 77, 824, + 870, 239, 748, + 745, 392, 621, + 494, 539, 365, + 0, 683, 0, + 0, 823, 0, + 0, 961, 0, + 0, 1097, 0, + 0, 1233, 0, + 0, 1367, 0, + 0, 1501, 0, + 0, 1635, 0, + 0, 1768, 0, + 0, 1901, 0, + 0, 2033, 0, + 0, 2165, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1176, 0, 1039, + 1152, 0, 1014, + 1118, 0, 979, + 1068, 186, 926, + 991, 355, 844, + 863, 513, 705, + 601, 663, 410, + 0, 809, 0, + 0, 951, 0, + 0, 1090, 0, + 0, 1227, 0, + 0, 1363, 0, + 0, 1498, 0, + 0, 1632, 0, + 0, 1766, 0, + 0, 1899, 0, + 0, 2032, 0, + 0, 2165, 0, + 0, 2297, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1320, 0, 1171, + 1303, 0, 1153, + 1279, 0, 1127, + 1244, 103, 1089, + 1193, 300, 1034, + 1115, 475, 948, + 984, 636, 798, + 714, 789, 463, + 0, 936, 0, + 0, 1079, 0, + 0, 1219, 0, + 0, 1357, 0, + 0, 1494, 0, + 0, 1629, 0, + 0, 1764, 0, + 0, 1898, 0, + 0, 2031, 0, + 0, 2165, 0, + 0, 2297, 0, + 0, 2429, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1461, 0, 1304, + 1448, 0, 1290, + 1431, 0, 1271, + 1406, 0, 1244, + 1371, 214, 1205, + 1320, 418, 1147, + 1241, 597, 1057, + 1108, 762, 898, + 831, 917, 526, + 0, 1065, 0, + 0, 1209, 0, + 0, 1350, 0, + 0, 1488, 0, + 0, 1625, 0, + 0, 1760, 0, + 0, 1895, 0, + 0, 2029, 0, + 0, 2163, 0, + 0, 2297, 0, + 0, 2429, 0, + 0, 2561, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1599, 0, 1436, + 1590, 0, 1426, + 1577, 0, 1411, + 1560, 0, 1392, + 1535, 65, 1364, + 1500, 329, 1324, + 1448, 539, 1265, + 1368, 722, 1171, + 1233, 889, 1005, + 952, 1045, 598, + 0, 1194, 0, + 0, 1339, 0, + 0, 1480, 0, + 0, 1619, 0, + 0, 1756, 0, + 0, 1892, 0, + 0, 2027, 0, + 0, 2161, 0, + 0, 2295, 0, + 0, 2427, 0, + 0, 2561, 0, + 0, 2693, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1736, 0, 1568, + 1729, 0, 1560, + 1720, 0, 1550, + 1707, 0, 1535, + 1690, 0, 1515, + 1665, 174, 1487, + 1630, 448, 1447, + 1578, 663, 1386, + 1497, 849, 1289, + 1361, 1017, 1117, + 1074, 1174, 680, + 0, 1325, 0, + 0, 1470, 0, + 0, 1611, 0, + 0, 1751, 0, + 0, 1888, 0, + 0, 2024, 0, + 0, 2159, 0, + 0, 2293, 0, + 0, 2427, 0, + 0, 2559, 0, + 0, 2693, 0, + 0, 2825, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1872, 0, 1700, + 1867, 0, 1694, + 1860, 0, 1687, + 1851, 0, 1676, + 1838, 0, 1661, + 1820, 0, 1641, + 1795, 287, 1613, + 1760, 570, 1571, + 1707, 789, 1510, + 1627, 977, 1411, + 1489, 1146, 1233, + 1200, 1304, 770, + 0, 1455, 0, + 0, 1601, 0, + 0, 1743, 0, + 0, 1882, 0, + 0, 2020, 0, + 0, 2155, 0, + 0, 2291, 0, + 0, 2425, 0, + 0, 2559, 0, + 0, 2693, 0, + 0, 2825, 0, + 0, 2957, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2007, 0, 1832, + 2003, 0, 1828, + 1998, 0, 1822, + 1991, 0, 1814, + 1982, 0, 1804, + 1969, 0, 1789, + 1951, 0, 1768, + 1926, 405, 1740, + 1890, 694, 1698, + 1838, 916, 1635, + 1757, 1105, 1535, + 1619, 1276, 1354, + 1327, 1435, 868, + 0, 1586, 0, + 0, 1732, 0, + 0, 1874, 0, + 0, 2014, 0, + 0, 2151, 0, + 0, 2287, 0, + 0, 2423, 0, + 0, 2557, 0, + 0, 2691, 0, + 0, 2825, 0, + 0, 2957, 0, + 0, 3089, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2141, 0, 1964, + 2137, 0, 1961, + 2135, 0, 1957, + 2129, 0, 1951, + 2123, 0, 1943, + 2113, 0, 1932, + 2099, 0, 1918, + 2083, 6, 1897, + 2057, 526, 1868, + 2021, 821, 1826, + 1969, 1045, 1762, + 1887, 1235, 1661, + 1749, 1407, 1477, + 1455, 1566, 973, + 0, 1718, 0, + 0, 1864, 0, + 0, 2006, 0, + 0, 2145, 0, + 0, 2283, 0, + 0, 2419, 0, + 0, 2555, 0, + 0, 2689, 0, + 0, 2823, 0, + 0, 2957, 0, + 0, 3089, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3885, 0, + 0, 4017, 0, + 2275, 0, 2097, + 2273, 0, 2095, + 2269, 0, 2091, + 2265, 0, 2087, + 2261, 0, 2081, + 2253, 0, 2073, + 2245, 0, 2063, + 2231, 0, 2047, + 2213, 111, 2026, + 2189, 650, 1997, + 2153, 948, 1955, + 2099, 1174, 1891, + 2018, 1366, 1789, + 1879, 1538, 1602, + 1584, 1697, 1083, + 0, 1849, 0, + 0, 1995, 0, + 0, 2137, 0, + 0, 2277, 0, + 0, 2415, 0, + 0, 2551, 0, + 0, 2687, 0, + 0, 2821, 0, + 0, 2955, 0, + 0, 3089, 0, + 0, 3221, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3885, 0, + 0, 4017, 0, + 2407, 0, 2229, + 2405, 0, 2227, + 2403, 0, 2225, + 2401, 0, 2221, + 2397, 0, 2217, + 2393, 0, 2211, + 2385, 0, 2203, + 2375, 0, 2193, + 2363, 0, 2177, + 2345, 221, 2157, + 2319, 775, 2127, + 2285, 1077, 2085, + 2231, 1304, 2020, + 2149, 1496, 1917, + 2010, 1669, 1729, + 1714, 1829, 1199, + 0, 1981, 0, + 0, 2127, 0, + 0, 2269, 0, + 0, 2409, 0, + 0, 2547, 0, + 0, 2683, 0, + 0, 2819, 0, + 0, 2953, 0, + 0, 3087, 0, + 0, 3221, 0, + 0, 3353, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4017, 0, + 2541, 0, 2361, + 2539, 0, 2359, + 2537, 0, 2357, + 2535, 0, 2355, + 2533, 0, 2353, + 2529, 0, 2347, + 2523, 0, 2341, + 2517, 0, 2333, + 2507, 0, 2323, + 2495, 0, 2307, + 2477, 337, 2287, + 2451, 903, 2257, + 2415, 1207, 2215, + 2363, 1435, 2151, + 2281, 1628, 2047, + 2141, 1800, 1857, + 1845, 1961, 1318, + 0, 2113, 0, + 0, 2259, 0, + 0, 2401, 0, + 0, 2541, 0, + 0, 2679, 0, + 0, 2815, 0, + 0, 2951, 0, + 0, 3085, 0, + 0, 3219, 0, + 0, 3353, 0, + 0, 3485, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 2673, 0, 2493, + 2673, 0, 2493, + 2671, 0, 2491, + 2669, 0, 2489, + 2667, 0, 2487, + 2665, 0, 2483, + 2661, 0, 2479, + 2655, 0, 2473, + 2649, 0, 2465, + 2639, 0, 2453, + 2627, 0, 2439, + 2609, 456, 2417, + 2583, 1031, 2389, + 2547, 1337, 2345, + 2495, 1566, 2281, + 2413, 1759, 2177, + 2273, 1932, 1986, + 1976, 2093, 1440, + 0, 2245, 0, + 0, 2391, 0, + 0, 2533, 0, + 0, 2673, 0, + 0, 2811, 0, + 0, 2947, 0, + 0, 3083, 0, + 0, 3217, 0, + 0, 3351, 0, + 0, 3485, 0, + 0, 3617, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 2805, 0, 2625, + 2805, 0, 2625, + 2805, 0, 2623, + 2803, 0, 2623, + 2801, 0, 2621, + 2799, 0, 2617, + 2797, 0, 2615, + 2793, 0, 2611, + 2787, 0, 2605, + 2781, 0, 2597, + 2771, 0, 2585, + 2759, 0, 2571, + 2741, 578, 2549, + 2715, 1160, 2519, + 2679, 1468, 2477, + 2627, 1697, 2411, + 2545, 1891, 2307, + 2405, 2063, 2115, + 2107, 2225, 1565, + 0, 2377, 0, + 0, 2523, 0, + 0, 2665, 0, + 0, 2805, 0, + 0, 2943, 0, + 0, 3079, 0, + 0, 3215, 0, + 0, 3349, 0, + 0, 3483, 0, + 0, 3617, 0, + 0, 3749, 0, + 0, 3883, 0, + 0, 4015, 0, + 2939, 0, 2757, + 2937, 0, 2757, + 2937, 0, 2755, + 2937, 0, 2755, + 2935, 0, 2753, + 2933, 0, 2751, + 2931, 0, 2749, + 2929, 0, 2747, + 2925, 0, 2741, + 2919, 0, 2735, + 2913, 0, 2727, + 2903, 0, 2717, + 2891, 0, 2701, + 2873, 703, 2681, + 2847, 1290, 2651, + 2811, 1599, 2607, + 2759, 1829, 2543, + 2677, 2022, 2439, + 2537, 2195, 2247, + 2239, 2357, 1691, + 0, 2509, 0, + 0, 2655, 0, + 0, 2797, 0, + 0, 2937, 0, + 0, 3075, 0, + 0, 3211, 0, + 0, 3347, 0, + 0, 3481, 0, + 0, 3615, 0, + 0, 3749, 0, + 0, 3881, 0, + 0, 4015, 0, + 3071, 0, 2889, + 3071, 0, 2889, + 3069, 0, 2889, + 3069, 0, 2887, + 3069, 0, 2887, + 3067, 0, 2885, + 3065, 0, 2883, + 3063, 0, 2881, + 3061, 0, 2877, + 3057, 0, 2873, + 3051, 0, 2867, + 3045, 0, 2859, + 3035, 0, 2849, + 3023, 0, 2833, + 3005, 829, 2813, + 2979, 1421, 2783, + 2943, 1730, 2739, + 2891, 1960, 2675, + 2809, 2155, 2569, + 2669, 2327, 2377, + 2369, 2489, 1819, + 0, 2641, 0, + 0, 2787, 0, + 0, 2929, 0, + 0, 3069, 0, + 0, 3207, 0, + 0, 3343, 0, + 0, 3479, 0, + 0, 3613, 0, + 0, 3747, 0, + 0, 3881, 0, + 0, 4015, 0, + 3203, 0, 3021, + 3203, 0, 3021, + 3203, 0, 3021, + 3201, 0, 3021, + 3201, 0, 3019, + 3201, 0, 3019, + 3199, 0, 3017, + 3197, 0, 3015, + 3195, 0, 3013, + 3193, 0, 3009, + 3189, 0, 3005, + 3183, 0, 2999, + 3177, 0, 2991, + 3167, 0, 2981, + 3155, 0, 2965, + 3137, 957, 2945, + 3111, 1552, 2915, + 3075, 1862, 2871, + 3023, 2093, 2807, + 2941, 2285, 2701, + 2801, 2459, 2509, + 2501, 2621, 1948, + 0, 2773, 0, + 0, 2919, 0, + 0, 3061, 0, + 0, 3201, 0, + 0, 3339, 0, + 0, 3477, 0, + 0, 3611, 0, + 0, 3745, 0, + 0, 3879, 0, + 0, 4013, 0, + 3335, 0, 3153, + 3335, 0, 3153, + 3335, 0, 3153, + 3335, 0, 3153, + 3333, 0, 3153, + 3333, 0, 3151, + 3333, 0, 3151, + 3331, 0, 3149, + 3329, 0, 3147, + 3327, 0, 3145, + 3325, 0, 3141, + 3321, 0, 3137, + 3315, 0, 3131, + 3309, 0, 3123, + 3299, 0, 3113, + 3287, 0, 3097, + 3269, 1085, 3075, + 3243, 1683, 3047, + 3207, 1993, 3003, + 3155, 2223, 2937, + 3073, 2417, 2833, + 2933, 2591, 2639, + 2633, 2753, 2077, + 0, 2905, 0, + 0, 3051, 0, + 0, 3195, 0, + 0, 3333, 0, + 0, 3471, 0, + 0, 3609, 0, + 0, 3743, 0, + 0, 3877, 0, + 0, 4011, 0, + 3467, 0, 3285, + 3467, 0, 3285, + 3467, 0, 3285, + 3467, 0, 3285, + 3467, 0, 3285, + 3465, 0, 3285, + 3465, 0, 3283, + 3465, 0, 3283, + 3463, 0, 3281, + 3461, 0, 3279, + 3459, 0, 3277, + 3457, 0, 3273, + 3453, 0, 3269, + 3447, 0, 3263, + 3441, 0, 3255, + 3431, 0, 3245, + 3419, 0, 3229, + 3401, 1215, 3207, + 3375, 1815, 3179, + 3339, 2125, 3135, + 3287, 2355, 3069, + 3205, 2549, 2965, + 3065, 2723, 2771, + 2765, 2885, 2207, + 0, 3037, 0, + 0, 3183, 0, + 0, 3327, 0, + 0, 3467, 0, + 0, 3603, 0, + 0, 3741, 0, + 0, 3875, 0, + 0, 4011, 0, + 3599, 0, 3417, + 3599, 0, 3417, + 3599, 0, 3417, + 3599, 0, 3417, + 3599, 0, 3417, + 3599, 0, 3417, + 3597, 0, 3417, + 3597, 0, 3415, + 3597, 0, 3415, + 3595, 0, 3413, + 3593, 0, 3411, + 3591, 0, 3409, + 3589, 0, 3405, + 3585, 0, 3401, + 3579, 0, 3395, + 3573, 0, 3387, + 3563, 0, 3377, + 3551, 0, 3361, + 3533, 1345, 3339, + 3507, 1946, 3309, + 3471, 2257, 3267, + 3419, 2487, 3201, + 3337, 2681, 3097, + 3197, 2855, 2903, + 2897, 3017, 2339, + 0, 3169, 0, + 0, 3315, 0, + 0, 3459, 0, + 0, 3599, 0, + 0, 3737, 0, + 0, 3873, 0, + 0, 4007, 0, + 3731, 0, 3551, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3729, 0, 3547, + 3729, 0, 3547, + 3727, 0, 3545, + 3725, 0, 3543, + 3723, 0, 3541, + 3721, 0, 3537, + 3717, 0, 3533, + 3713, 0, 3527, + 3705, 0, 3519, + 3695, 0, 3509, + 3683, 0, 3493, + 3665, 1476, 3471, + 3639, 2077, 3441, + 3603, 2389, 3399, + 3551, 2619, 3333, + 3469, 2815, 3229, + 3329, 2987, 3035, + 3029, 3149, 2469, + 0, 3301, 0, + 0, 3447, 0, + 0, 3591, 0, + 0, 3731, 0, + 0, 3869, 0, + 0, 4005, 0, + 3863, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3861, 0, 3679, + 3861, 0, 3679, + 3859, 0, 3677, + 3857, 0, 3675, + 3855, 0, 3673, + 3853, 0, 3669, + 3849, 0, 3665, + 3845, 0, 3659, + 3837, 0, 3651, + 3827, 0, 3641, + 3815, 0, 3625, + 3797, 1607, 3603, + 3771, 2209, 3575, + 3735, 2521, 3531, + 3683, 2751, 3465, + 3601, 2947, 3361, + 3461, 3119, 3167, + 3161, 3281, 2601, + 0, 3433, 0, + 0, 3579, 0, + 0, 3723, 0, + 0, 3863, 0, + 0, 4001, 0, + 3997, 0, 3815, + 3997, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3813, + 3995, 0, 3813, + 3995, 0, 3813, + 3995, 0, 3813, + 3995, 0, 3813, + 3995, 0, 3813, + 3993, 0, 3811, + 3993, 0, 3811, + 3991, 0, 3809, + 3991, 0, 3807, + 3987, 0, 3805, + 3985, 0, 3801, + 3981, 0, 3797, + 3977, 0, 3791, + 3969, 0, 3783, + 3959, 0, 3773, + 3947, 0, 3757, + 3929, 1739, 3735, + 3903, 2341, 3707, + 3867, 2653, 3663, + 3815, 2883, 3597, + 3733, 3079, 3493, + 3593, 3251, 3299, + 3293, 3413, 2733, + 0, 3565, 0, + 0, 3711, 0, + 0, 3855, 0, + 0, 3995, 0, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3943, + 4095, 0, 3943, + 4095, 0, 3941, + 4095, 0, 3939, + 4095, 0, 3937, + 4095, 0, 3933, + 4095, 0, 3929, + 4095, 0, 3923, + 4095, 0, 3915, + 4091, 0, 3905, + 4079, 0, 3889, + 4061, 1870, 3869, + 4035, 2473, 3839, + 3999, 2785, 3795, + 3947, 3017, 3729, + 3865, 3211, 3625, + 3725, 3383, 3431, + 3425, 3545, 2865, + 0, 3697, 0, + 0, 3843, 0, + 0, 3987, 0, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4075, + 4095, 0, 4075, + 4095, 0, 4073, + 4095, 0, 4071, + 4095, 0, 4069, + 4095, 0, 4065, + 4095, 0, 4061, + 4095, 0, 4055, + 4095, 0, 4047, + 4095, 0, 4037, + 4095, 0, 4021, + 4095, 2002, 4001, + 4095, 2605, 3971, + 4095, 2917, 3927, + 4079, 3149, 3861, + 3997, 3343, 3757, + 3857, 3515, 3563, + 3557, 3677, 2997, + 0, 3829, 0, + 0, 3977, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2133, 4095, + 4095, 2737, 4095, + 4095, 3049, 4059, + 4095, 3281, 3993, + 4095, 3475, 3889, + 3989, 3649, 3695, + 3689, 3809, 3127, + 0, 3961, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2265, 4095, + 4095, 2869, 4095, + 4095, 3181, 4095, + 4095, 3413, 4095, + 4095, 3607, 4021, + 4095, 3781, 3827, + 3821, 3941, 3259, + 148, 10, 366, + 0, 122, 244, + 0, 237, 2, + 0, 357, 0, + 0, 479, 0, + 0, 604, 0, + 0, 731, 0, + 0, 859, 0, + 0, 988, 0, + 0, 1117, 0, + 0, 1247, 0, + 0, 1378, 0, + 0, 1509, 0, + 0, 1641, 0, + 0, 1772, 0, + 0, 1904, 0, + 0, 2036, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 369, 0, 471, + 205, 106, 377, + 0, 225, 210, + 0, 348, 0, + 0, 473, 0, + 0, 599, 0, + 0, 727, 0, + 0, 856, 0, + 0, 985, 0, + 0, 1115, 0, + 0, 1246, 0, + 0, 1377, 0, + 0, 1509, 0, + 0, 1640, 0, + 0, 1772, 0, + 0, 1904, 0, + 0, 2036, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 558, 0, 582, + 456, 85, 510, + 271, 209, 391, + 0, 335, 159, + 0, 463, 0, + 0, 592, 0, + 0, 721, 0, + 0, 852, 0, + 0, 982, 0, + 0, 1113, 0, + 0, 1245, 0, + 0, 1376, 0, + 0, 1508, 0, + 0, 1640, 0, + 0, 1771, 0, + 0, 1903, 0, + 0, 2035, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 728, 0, 697, + 661, 54, 642, + 552, 186, 556, + 347, 318, 409, + 0, 450, 82, + 0, 582, 0, + 0, 714, 0, + 0, 846, 0, + 0, 978, 0, + 0, 1110, 0, + 0, 1242, 0, + 0, 1374, 0, + 0, 1506, 0, + 0, 1639, 0, + 0, 1771, 0, + 0, 1903, 0, + 0, 2035, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 887, 0, 816, + 840, 10, 775, + 770, 153, 712, + 654, 294, 613, + 432, 432, 432, + 0, 569, 0, + 0, 704, 0, + 0, 839, 0, + 0, 973, 0, + 0, 1106, 0, + 0, 1239, 0, + 0, 1372, 0, + 0, 1505, 0, + 0, 1637, 0, + 0, 1770, 0, + 0, 1902, 0, + 0, 2034, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1037, 0, 938, + 1005, 0, 907, + 957, 106, 861, + 884, 259, 792, + 763, 407, 678, + 525, 550, 461, + 0, 690, 0, + 0, 829, 0, + 0, 965, 0, + 0, 1100, 0, + 0, 1235, 0, + 0, 1369, 0, + 0, 1502, 0, + 0, 1636, 0, + 0, 1768, 0, + 0, 1901, 0, + 0, 2034, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1183, 0, 1063, + 1160, 0, 1039, + 1126, 33, 1005, + 1077, 209, 956, + 1002, 371, 880, + 877, 524, 753, + 626, 672, 498, + 0, 815, 0, + 0, 955, 0, + 0, 1093, 0, + 0, 1229, 0, + 0, 1365, 0, + 0, 1499, 0, + 0, 1633, 0, + 0, 1767, 0, + 0, 1900, 0, + 0, 2033, 0, + 0, 2165, 0, + 0, 2297, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1325, 0, 1189, + 1308, 0, 1171, + 1284, 0, 1146, + 1250, 131, 1110, + 1200, 318, 1058, + 1123, 487, 976, + 995, 645, 837, + 734, 795, 542, + 0, 941, 0, + 0, 1082, 0, + 0, 1222, 0, + 0, 1359, 0, + 0, 1495, 0, + 0, 1630, 0, + 0, 1764, 0, + 0, 1898, 0, + 0, 2031, 0, + 0, 2165, 0, + 0, 2297, 0, + 0, 2429, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1465, 0, 1317, + 1452, 0, 1304, + 1435, 0, 1285, + 1411, 0, 1259, + 1376, 236, 1221, + 1325, 432, 1166, + 1247, 607, 1079, + 1116, 768, 930, + 846, 921, 595, + 0, 1068, 0, + 0, 1211, 0, + 0, 1351, 0, + 0, 1489, 0, + 0, 1626, 0, + 0, 1761, 0, + 0, 1896, 0, + 0, 2030, 0, + 0, 2163, 0, + 0, 2297, 0, + 0, 2429, 0, + 0, 2561, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1602, 0, 1446, + 1593, 0, 1436, + 1580, 0, 1422, + 1563, 0, 1403, + 1538, 95, 1376, + 1504, 346, 1337, + 1452, 550, 1279, + 1373, 729, 1189, + 1240, 894, 1030, + 963, 1048, 658, + 0, 1197, 0, + 0, 1341, 0, + 0, 1482, 0, + 0, 1620, 0, + 0, 1757, 0, + 0, 1893, 0, + 0, 2027, 0, + 0, 2161, 0, + 0, 2295, 0, + 0, 2429, 0, + 0, 2561, 0, + 0, 2693, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1738, 0, 1575, + 1732, 0, 1568, + 1722, 0, 1558, + 1710, 0, 1544, + 1692, 0, 1524, + 1667, 198, 1496, + 1632, 461, 1456, + 1580, 671, 1397, + 1501, 854, 1303, + 1366, 1021, 1137, + 1083, 1177, 730, + 0, 1327, 0, + 0, 1471, 0, + 0, 1612, 0, + 0, 1751, 0, + 0, 1888, 0, + 0, 2024, 0, + 0, 2159, 0, + 0, 2293, 0, + 0, 2427, 0, + 0, 2561, 0, + 0, 2693, 0, + 0, 2825, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1873, 0, 1706, + 1868, 0, 1700, + 1862, 0, 1692, + 1852, 0, 1682, + 1839, 0, 1668, + 1822, 0, 1648, + 1797, 306, 1619, + 1762, 580, 1579, + 1710, 795, 1518, + 1629, 981, 1422, + 1493, 1149, 1249, + 1207, 1307, 812, + 0, 1457, 0, + 0, 1602, 0, + 0, 1744, 0, + 0, 1883, 0, + 0, 2020, 0, + 0, 2155, 0, + 0, 2291, 0, + 0, 2425, 0, + 0, 2559, 0, + 0, 2693, 0, + 0, 2825, 0, + 0, 2957, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2008, 0, 1837, + 2004, 0, 1832, + 1999, 0, 1827, + 1992, 0, 1819, + 1983, 0, 1808, + 1970, 0, 1794, + 1952, 0, 1773, + 1927, 419, 1745, + 1892, 702, 1703, + 1840, 921, 1642, + 1759, 1109, 1543, + 1621, 1278, 1366, + 1332, 1437, 902, + 0, 1587, 0, + 0, 1733, 0, + 0, 1875, 0, + 0, 2014, 0, + 0, 2151, 0, + 0, 2287, 0, + 0, 2423, 0, + 0, 2557, 0, + 0, 2691, 0, + 0, 2825, 0, + 0, 2957, 0, + 0, 3089, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2141, 0, 1968, + 2139, 0, 1964, + 2135, 0, 1960, + 2129, 0, 1954, + 2123, 0, 1947, + 2113, 0, 1936, + 2101, 0, 1921, + 2083, 39, 1901, + 2059, 537, 1872, + 2022, 826, 1830, + 1970, 1048, 1767, + 1889, 1238, 1667, + 1751, 1408, 1486, + 1459, 1567, 1000, + 0, 1718, 0, + 0, 1864, 0, + 0, 2006, 0, + 0, 2145, 0, + 0, 2283, 0, + 0, 2419, 0, + 0, 2555, 0, + 0, 2689, 0, + 0, 2823, 0, + 0, 2957, 0, + 0, 3089, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3885, 0, + 0, 4017, 0, + 2275, 0, 2099, + 2273, 0, 2097, + 2271, 0, 2093, + 2267, 0, 2089, + 2261, 0, 2083, + 2255, 0, 2075, + 2245, 0, 2065, + 2231, 0, 2049, + 2215, 138, 2029, + 2189, 658, 2000, + 2153, 953, 1958, + 2101, 1177, 1895, + 2019, 1367, 1793, + 1881, 1539, 1609, + 1587, 1698, 1105, + 0, 1850, 0, + 0, 1996, 0, + 0, 2139, 0, + 0, 2277, 0, + 0, 2415, 0, + 0, 2551, 0, + 0, 2687, 0, + 0, 2821, 0, + 0, 2955, 0, + 0, 3089, 0, + 0, 3221, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3885, 0, + 0, 4017, 0, + 2407, 0, 2231, + 2407, 0, 2229, + 2405, 0, 2227, + 2401, 0, 2223, + 2397, 0, 2219, + 2393, 0, 2213, + 2385, 0, 2205, + 2377, 0, 2195, + 2363, 0, 2179, + 2345, 243, 2159, + 2321, 782, 2129, + 2285, 1080, 2087, + 2233, 1306, 2023, + 2151, 1498, 1921, + 2012, 1670, 1734, + 1716, 1830, 1216, + 0, 1981, 0, + 0, 2127, 0, + 0, 2269, 0, + 0, 2409, 0, + 0, 2547, 0, + 0, 2683, 0, + 0, 2819, 0, + 0, 2953, 0, + 0, 3087, 0, + 0, 3221, 0, + 0, 3353, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4017, 0, + 2541, 0, 2363, + 2539, 0, 2361, + 2539, 0, 2359, + 2535, 0, 2357, + 2533, 0, 2353, + 2529, 0, 2349, + 2525, 0, 2343, + 2517, 0, 2335, + 2507, 0, 2325, + 2495, 0, 2309, + 2477, 353, 2289, + 2453, 908, 2259, + 2417, 1209, 2217, + 2363, 1436, 2153, + 2281, 1629, 2049, + 2143, 1801, 1861, + 1846, 1961, 1331, + 0, 2113, 0, + 0, 2259, 0, + 0, 2401, 0, + 0, 2541, 0, + 0, 2679, 0, + 0, 2815, 0, + 0, 2951, 0, + 0, 3085, 0, + 0, 3219, 0, + 0, 3353, 0, + 0, 3485, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 2673, 0, 2493, + 2673, 0, 2493, + 2671, 0, 2491, + 2669, 0, 2489, + 2667, 0, 2487, + 2665, 0, 2485, + 2661, 0, 2479, + 2657, 0, 2475, + 2649, 0, 2465, + 2639, 0, 2455, + 2627, 0, 2441, + 2609, 469, 2419, + 2583, 1035, 2389, + 2547, 1339, 2347, + 2495, 1567, 2283, + 2413, 1760, 2179, + 2273, 1932, 1989, + 1977, 2093, 1450, + 0, 2245, 0, + 0, 2391, 0, + 0, 2533, 0, + 0, 2673, 0, + 0, 2811, 0, + 0, 2947, 0, + 0, 3083, 0, + 0, 3217, 0, + 0, 3351, 0, + 0, 3485, 0, + 0, 3617, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 2805, 0, 2625, + 2805, 0, 2625, + 2805, 0, 2625, + 2803, 0, 2623, + 2801, 0, 2621, + 2799, 0, 2619, + 2797, 0, 2615, + 2793, 0, 2611, + 2787, 0, 2605, + 2781, 0, 2597, + 2771, 0, 2587, + 2759, 0, 2571, + 2741, 588, 2551, + 2715, 1163, 2521, + 2679, 1469, 2477, + 2627, 1698, 2413, + 2545, 1891, 2309, + 2405, 2065, 2117, + 2107, 2225, 1572, + 0, 2377, 0, + 0, 2523, 0, + 0, 2665, 0, + 0, 2805, 0, + 0, 2943, 0, + 0, 3079, 0, + 0, 3215, 0, + 0, 3349, 0, + 0, 3483, 0, + 0, 3617, 0, + 0, 3749, 0, + 0, 3883, 0, + 0, 4015, 0, + 2939, 0, 2757, + 2937, 0, 2757, + 2937, 0, 2757, + 2937, 0, 2755, + 2935, 0, 2755, + 2933, 0, 2753, + 2931, 0, 2749, + 2929, 0, 2747, + 2925, 0, 2743, + 2919, 0, 2737, + 2913, 0, 2729, + 2903, 0, 2717, + 2891, 0, 2703, + 2873, 710, 2681, + 2847, 1292, 2651, + 2811, 1600, 2609, + 2759, 1829, 2543, + 2677, 2023, 2439, + 2537, 2195, 2247, + 2239, 2357, 1697, + 0, 2509, 0, + 0, 2655, 0, + 0, 2797, 0, + 0, 2937, 0, + 0, 3075, 0, + 0, 3211, 0, + 0, 3347, 0, + 0, 3481, 0, + 0, 3615, 0, + 0, 3749, 0, + 0, 3881, 0, + 0, 4015, 0, + 3071, 0, 2889, + 3071, 0, 2889, + 3069, 0, 2889, + 3069, 0, 2889, + 3069, 0, 2887, + 3067, 0, 2885, + 3065, 0, 2883, + 3063, 0, 2881, + 3061, 0, 2879, + 3057, 0, 2873, + 3051, 0, 2869, + 3045, 0, 2859, + 3035, 0, 2849, + 3023, 0, 2833, + 3005, 835, 2813, + 2979, 1422, 2783, + 2943, 1731, 2739, + 2891, 1961, 2675, + 2809, 2155, 2571, + 2669, 2327, 2379, + 2371, 2489, 1823, + 0, 2641, 0, + 0, 2787, 0, + 0, 2929, 0, + 0, 3069, 0, + 0, 3207, 0, + 0, 3343, 0, + 0, 3479, 0, + 0, 3613, 0, + 0, 3747, 0, + 0, 3881, 0, + 0, 4015, 0, + 3203, 0, 3021, + 3203, 0, 3021, + 3203, 0, 3021, + 3201, 0, 3021, + 3201, 0, 3019, + 3201, 0, 3019, + 3199, 0, 3017, + 3197, 0, 3015, + 3195, 0, 3013, + 3193, 0, 3011, + 3189, 0, 3005, + 3183, 0, 2999, + 3177, 0, 2991, + 3167, 0, 2981, + 3155, 0, 2965, + 3137, 961, 2945, + 3111, 1553, 2915, + 3075, 1862, 2871, + 3023, 2093, 2807, + 2941, 2287, 2703, + 2801, 2459, 2509, + 2501, 2621, 1951, + 0, 2773, 0, + 0, 2919, 0, + 0, 3061, 0, + 0, 3201, 0, + 0, 3339, 0, + 0, 3477, 0, + 0, 3611, 0, + 0, 3745, 0, + 0, 3879, 0, + 0, 4013, 0, + 3335, 0, 3153, + 3335, 0, 3153, + 3335, 0, 3153, + 3335, 0, 3153, + 3333, 0, 3153, + 3333, 0, 3151, + 3333, 0, 3151, + 3331, 0, 3149, + 3329, 0, 3147, + 3327, 0, 3145, + 3325, 0, 3141, + 3321, 0, 3137, + 3315, 0, 3131, + 3309, 0, 3123, + 3299, 0, 3113, + 3287, 0, 3097, + 3269, 1089, 3077, + 3243, 1684, 3047, + 3207, 1994, 3003, + 3155, 2225, 2939, + 3073, 2419, 2833, + 2933, 2591, 2641, + 2633, 2753, 2081, + 0, 2905, 0, + 0, 3051, 0, + 0, 3195, 0, + 0, 3333, 0, + 0, 3471, 0, + 0, 3609, 0, + 0, 3743, 0, + 0, 3877, 0, + 0, 4011, 0, + 3467, 0, 3285, + 3467, 0, 3285, + 3467, 0, 3285, + 3467, 0, 3285, + 3467, 0, 3285, + 3465, 0, 3285, + 3465, 0, 3283, + 3465, 0, 3283, + 3463, 0, 3281, + 3461, 0, 3279, + 3459, 0, 3277, + 3457, 0, 3273, + 3453, 0, 3269, + 3447, 0, 3263, + 3441, 0, 3255, + 3431, 0, 3245, + 3419, 0, 3229, + 3401, 1218, 3209, + 3375, 1815, 3179, + 3339, 2125, 3135, + 3287, 2357, 3069, + 3205, 2551, 2965, + 3065, 2723, 2771, + 2765, 2885, 2209, + 0, 3037, 0, + 0, 3183, 0, + 0, 3327, 0, + 0, 3467, 0, + 0, 3603, 0, + 0, 3741, 0, + 0, 3875, 0, + 0, 4011, 0, + 3599, 0, 3419, + 3599, 0, 3417, + 3599, 0, 3417, + 3599, 0, 3417, + 3599, 0, 3417, + 3599, 0, 3417, + 3599, 0, 3417, + 3597, 0, 3415, + 3597, 0, 3415, + 3595, 0, 3413, + 3593, 0, 3411, + 3591, 0, 3409, + 3589, 0, 3405, + 3585, 0, 3401, + 3579, 0, 3395, + 3573, 0, 3387, + 3563, 0, 3377, + 3551, 0, 3361, + 3533, 1347, 3339, + 3507, 1947, 3311, + 3471, 2257, 3267, + 3419, 2487, 3201, + 3337, 2683, 3097, + 3197, 2855, 2903, + 2897, 3017, 2339, + 0, 3169, 0, + 0, 3315, 0, + 0, 3459, 0, + 0, 3599, 0, + 0, 3737, 0, + 0, 3873, 0, + 0, 4007, 0, + 3731, 0, 3551, + 3731, 0, 3551, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3729, 0, 3547, + 3729, 0, 3547, + 3727, 0, 3545, + 3725, 0, 3543, + 3723, 0, 3541, + 3721, 0, 3537, + 3717, 0, 3533, + 3713, 0, 3527, + 3705, 0, 3519, + 3695, 0, 3509, + 3683, 0, 3493, + 3665, 1478, 3471, + 3639, 2079, 3443, + 3603, 2389, 3399, + 3551, 2619, 3333, + 3469, 2815, 3229, + 3329, 2987, 3035, + 3029, 3149, 2471, + 0, 3301, 0, + 0, 3447, 0, + 0, 3591, 0, + 0, 3731, 0, + 0, 3869, 0, + 0, 4005, 0, + 3863, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3861, 0, 3679, + 3861, 0, 3679, + 3859, 0, 3677, + 3857, 0, 3675, + 3855, 0, 3673, + 3853, 0, 3669, + 3849, 0, 3665, + 3845, 0, 3659, + 3837, 0, 3651, + 3827, 0, 3641, + 3815, 0, 3625, + 3797, 1608, 3603, + 3771, 2211, 3575, + 3735, 2521, 3531, + 3683, 2751, 3465, + 3601, 2947, 3361, + 3461, 3119, 3167, + 3161, 3281, 2601, + 0, 3433, 0, + 0, 3579, 0, + 0, 3723, 0, + 0, 3863, 0, + 0, 4001, 0, + 3997, 0, 3815, + 3997, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3813, + 3995, 0, 3813, + 3995, 0, 3813, + 3995, 0, 3813, + 3995, 0, 3813, + 3993, 0, 3811, + 3993, 0, 3811, + 3991, 0, 3809, + 3991, 0, 3807, + 3987, 0, 3805, + 3985, 0, 3801, + 3981, 0, 3797, + 3977, 0, 3791, + 3969, 0, 3783, + 3959, 0, 3773, + 3947, 0, 3757, + 3929, 1739, 3737, + 3903, 2341, 3707, + 3867, 2653, 3663, + 3815, 2885, 3597, + 3733, 3079, 3493, + 3593, 3251, 3299, + 3293, 3413, 2733, + 0, 3565, 0, + 0, 3711, 0, + 0, 3855, 0, + 0, 3995, 0, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3943, + 4095, 0, 3943, + 4095, 0, 3941, + 4095, 0, 3939, + 4095, 0, 3937, + 4095, 0, 3933, + 4095, 0, 3929, + 4095, 0, 3923, + 4095, 0, 3915, + 4091, 0, 3905, + 4079, 0, 3889, + 4061, 1871, 3869, + 4035, 2473, 3839, + 3999, 2785, 3795, + 3947, 3017, 3729, + 3865, 3211, 3625, + 3725, 3383, 3431, + 3425, 3545, 2865, + 0, 3697, 0, + 0, 3843, 0, + 0, 3987, 0, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4075, + 4095, 0, 4075, + 4095, 0, 4073, + 4095, 0, 4071, + 4095, 0, 4069, + 4095, 0, 4065, + 4095, 0, 4061, + 4095, 0, 4055, + 4095, 0, 4047, + 4095, 0, 4037, + 4095, 0, 4021, + 4095, 2002, 4001, + 4095, 2605, 3971, + 4095, 2917, 3927, + 4079, 3149, 3861, + 3997, 3343, 3757, + 3857, 3515, 3563, + 3557, 3677, 2997, + 0, 3829, 0, + 0, 3977, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2133, 4095, + 4095, 2737, 4095, + 4095, 3049, 4059, + 4095, 3281, 3993, + 4095, 3475, 3889, + 3989, 3649, 3695, + 3689, 3809, 3129, + 0, 3961, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2265, 4095, + 4095, 2869, 4095, + 4095, 3181, 4095, + 4095, 3413, 4095, + 4095, 3607, 4021, + 4095, 3781, 3827, + 3821, 3941, 3261, + 232, 55, 490, + 0, 157, 400, + 0, 265, 243, + 0, 378, 0, + 0, 496, 0, + 0, 617, 0, + 0, 740, 0, + 0, 866, 0, + 0, 993, 0, + 0, 1121, 0, + 0, 1251, 0, + 0, 1381, 0, + 0, 1511, 0, + 0, 1642, 0, + 0, 1773, 0, + 0, 1905, 0, + 0, 2036, 0, + 0, 2169, 0, + 0, 2301, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 422, 37, 572, + 280, 142, 498, + 0, 254, 376, + 0, 369, 134, + 0, 489, 0, + 0, 611, 0, + 0, 736, 0, + 0, 863, 0, + 0, 991, 0, + 0, 1120, 0, + 0, 1249, 0, + 0, 1380, 0, + 0, 1510, 0, + 0, 1642, 0, + 0, 1773, 0, + 0, 1904, 0, + 0, 2036, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 594, 12, 663, + 501, 123, 603, + 337, 238, 509, + 0, 358, 342, + 0, 480, 0, + 0, 605, 0, + 0, 731, 0, + 0, 859, 0, + 0, 988, 0, + 0, 1117, 0, + 0, 1248, 0, + 0, 1378, 0, + 0, 1509, 0, + 0, 1641, 0, + 0, 1772, 0, + 0, 1904, 0, + 0, 2036, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 753, 0, 761, + 690, 95, 714, + 588, 217, 642, + 403, 341, 523, + 0, 467, 291, + 0, 595, 0, + 0, 724, 0, + 0, 853, 0, + 0, 984, 0, + 0, 1114, 0, + 0, 1245, 0, + 0, 1377, 0, + 0, 1508, 0, + 0, 1640, 0, + 0, 1772, 0, + 0, 1904, 0, + 0, 2035, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 905, 0, 866, + 860, 54, 829, + 793, 186, 774, + 684, 318, 689, + 479, 450, 541, + 0, 582, 214, + 0, 714, 0, + 0, 846, 0, + 0, 978, 0, + 0, 1110, 0, + 0, 1242, 0, + 0, 1374, 0, + 0, 1506, 0, + 0, 1639, 0, + 0, 1771, 0, + 0, 1903, 0, + 0, 2035, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1050, 0, 977, + 1019, 0, 948, + 972, 142, 907, + 902, 286, 844, + 786, 426, 745, + 564, 564, 564, + 0, 701, 84, + 0, 836, 0, + 0, 971, 0, + 0, 1105, 0, + 0, 1238, 0, + 0, 1371, 0, + 0, 1504, 0, + 0, 1637, 0, + 0, 1769, 0, + 0, 1902, 0, + 0, 2034, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1193, 0, 1093, + 1170, 0, 1070, + 1137, 76, 1039, + 1089, 238, 993, + 1016, 392, 924, + 895, 539, 810, + 658, 682, 593, + 0, 823, 0, + 0, 961, 0, + 0, 1097, 0, + 0, 1232, 0, + 0, 1367, 0, + 0, 1501, 0, + 0, 1635, 0, + 0, 1768, 0, + 0, 1901, 0, + 0, 2033, 0, + 0, 2165, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1332, 0, 1212, + 1315, 0, 1195, + 1292, 0, 1171, + 1258, 165, 1137, + 1209, 341, 1088, + 1134, 503, 1012, + 1009, 656, 885, + 758, 804, 630, + 0, 947, 0, + 0, 1087, 0, + 0, 1225, 0, + 0, 1361, 0, + 0, 1497, 0, + 0, 1631, 0, + 0, 1765, 0, + 0, 1899, 0, + 0, 2032, 0, + 0, 2165, 0, + 0, 2297, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1470, 0, 1334, + 1457, 0, 1321, + 1440, 0, 1303, + 1416, 46, 1278, + 1382, 263, 1243, + 1332, 450, 1190, + 1255, 619, 1108, + 1127, 777, 970, + 866, 928, 674, + 0, 1073, 0, + 0, 1215, 0, + 0, 1354, 0, + 0, 1491, 0, + 0, 1627, 0, + 0, 1762, 0, + 0, 1896, 0, + 0, 2030, 0, + 0, 2163, 0, + 0, 2297, 0, + 0, 2429, 0, + 0, 2561, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1606, 0, 1459, + 1597, 0, 1449, + 1584, 0, 1436, + 1567, 0, 1417, + 1543, 132, 1391, + 1508, 368, 1354, + 1458, 564, 1298, + 1379, 739, 1212, + 1248, 900, 1062, + 978, 1053, 727, + 0, 1200, 0, + 0, 1343, 0, + 0, 1484, 0, + 0, 1622, 0, + 0, 1758, 0, + 0, 1893, 0, + 0, 2028, 0, + 0, 2161, 0, + 0, 2295, 0, + 0, 2429, 0, + 0, 2561, 0, + 0, 2693, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1741, 0, 1585, + 1734, 0, 1578, + 1725, 0, 1568, + 1713, 0, 1554, + 1695, 0, 1535, + 1671, 227, 1508, + 1636, 478, 1469, + 1584, 682, 1412, + 1505, 861, 1321, + 1372, 1026, 1162, + 1095, 1181, 790, + 0, 1329, 0, + 0, 1473, 0, + 0, 1614, 0, + 0, 1752, 0, + 0, 1889, 0, + 0, 2025, 0, + 0, 2159, 0, + 0, 2293, 0, + 0, 2427, 0, + 0, 2561, 0, + 0, 2693, 0, + 0, 2825, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1876, 0, 1713, + 1871, 0, 1708, + 1864, 0, 1700, + 1854, 0, 1690, + 1842, 0, 1676, + 1824, 0, 1656, + 1799, 330, 1628, + 1764, 593, 1589, + 1713, 803, 1529, + 1633, 986, 1435, + 1498, 1153, 1269, + 1216, 1309, 862, + 0, 1459, 0, + 0, 1603, 0, + 0, 1745, 0, + 0, 1883, 0, + 0, 2021, 0, + 0, 2157, 0, + 0, 2291, 0, + 0, 2425, 0, + 0, 2559, 0, + 0, 2693, 0, + 0, 2825, 0, + 0, 2957, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2009, 0, 1842, + 2006, 0, 1838, + 2001, 0, 1832, + 1994, 0, 1825, + 1984, 0, 1814, + 1972, 0, 1800, + 1954, 0, 1780, + 1929, 438, 1752, + 1894, 712, 1711, + 1842, 927, 1650, + 1761, 1113, 1554, + 1625, 1281, 1381, + 1339, 1439, 944, + 0, 1589, 0, + 0, 1734, 0, + 0, 1876, 0, + 0, 2015, 0, + 0, 2153, 0, + 0, 2289, 0, + 0, 2423, 0, + 0, 2557, 0, + 0, 2691, 0, + 0, 2825, 0, + 0, 2957, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2143, 0, 1972, + 2139, 0, 1969, + 2137, 0, 1964, + 2131, 0, 1959, + 2125, 0, 1951, + 2115, 0, 1940, + 2103, 0, 1926, + 2085, 81, 1905, + 2059, 551, 1877, + 2024, 834, 1836, + 1972, 1053, 1774, + 1891, 1241, 1675, + 1754, 1410, 1498, + 1464, 1569, 1034, + 0, 1720, 0, + 0, 1865, 0, + 0, 2007, 0, + 0, 2147, 0, + 0, 2283, 0, + 0, 2419, 0, + 0, 2555, 0, + 0, 2689, 0, + 0, 2823, 0, + 0, 2957, 0, + 0, 3089, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3885, 0, + 0, 4017, 0, + 2275, 0, 2103, + 2273, 0, 2099, + 2271, 0, 2097, + 2267, 0, 2093, + 2263, 0, 2087, + 2255, 0, 2079, + 2245, 0, 2067, + 2233, 0, 2053, + 2215, 172, 2033, + 2191, 669, 2004, + 2155, 959, 1962, + 2103, 1180, 1899, + 2021, 1370, 1799, + 1883, 1540, 1618, + 1591, 1699, 1132, + 0, 1851, 0, + 0, 1996, 0, + 0, 2139, 0, + 0, 2279, 0, + 0, 2415, 0, + 0, 2551, 0, + 0, 2687, 0, + 0, 2821, 0, + 0, 2955, 0, + 0, 3089, 0, + 0, 3221, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3885, 0, + 0, 4017, 0, + 2409, 0, 2233, + 2407, 0, 2231, + 2405, 0, 2229, + 2403, 0, 2225, + 2399, 0, 2221, + 2393, 0, 2215, + 2387, 0, 2207, + 2377, 0, 2197, + 2365, 0, 2181, + 2347, 270, 2161, + 2321, 790, 2133, + 2285, 1085, 2089, + 2233, 1309, 2027, + 2151, 1500, 1925, + 2013, 1671, 1741, + 1719, 1830, 1237, + 0, 1982, 0, + 0, 2127, 0, + 0, 2271, 0, + 0, 2409, 0, + 0, 2547, 0, + 0, 2683, 0, + 0, 2819, 0, + 0, 2953, 0, + 0, 3087, 0, + 0, 3221, 0, + 0, 3353, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4017, 0, + 2541, 0, 2363, + 2541, 0, 2363, + 2539, 0, 2361, + 2537, 0, 2359, + 2533, 0, 2355, + 2529, 0, 2351, + 2525, 0, 2345, + 2517, 0, 2337, + 2509, 0, 2327, + 2495, 0, 2311, + 2477, 375, 2291, + 2453, 914, 2261, + 2417, 1212, 2219, + 2365, 1438, 2155, + 2283, 1630, 2053, + 2143, 1802, 1866, + 1849, 1962, 1348, + 0, 2113, 0, + 0, 2259, 0, + 0, 2403, 0, + 0, 2541, 0, + 0, 2679, 0, + 0, 2815, 0, + 0, 2951, 0, + 0, 3085, 0, + 0, 3219, 0, + 0, 3353, 0, + 0, 3485, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 2673, 0, 2495, + 2673, 0, 2495, + 2671, 0, 2493, + 2671, 0, 2491, + 2669, 0, 2489, + 2665, 0, 2485, + 2661, 0, 2481, + 2657, 0, 2475, + 2649, 0, 2467, + 2641, 0, 2457, + 2627, 0, 2441, + 2609, 485, 2421, + 2585, 1039, 2391, + 2549, 1341, 2349, + 2495, 1569, 2285, + 2413, 1761, 2181, + 2275, 1933, 1993, + 1978, 2093, 1463, + 0, 2245, 0, + 0, 2391, 0, + 0, 2533, 0, + 0, 2673, 0, + 0, 2811, 0, + 0, 2947, 0, + 0, 3083, 0, + 0, 3217, 0, + 0, 3351, 0, + 0, 3485, 0, + 0, 3617, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 2807, 0, 2627, + 2805, 0, 2627, + 2805, 0, 2625, + 2803, 0, 2623, + 2801, 0, 2623, + 2799, 0, 2619, + 2797, 0, 2617, + 2793, 0, 2613, + 2789, 0, 2607, + 2781, 0, 2599, + 2771, 0, 2587, + 2759, 0, 2573, + 2741, 601, 2551, + 2715, 1167, 2521, + 2681, 1471, 2479, + 2627, 1699, 2415, + 2545, 1892, 2311, + 2405, 2065, 2121, + 2109, 2225, 1582, + 0, 2377, 0, + 0, 2523, 0, + 0, 2665, 0, + 0, 2805, 0, + 0, 2943, 0, + 0, 3079, 0, + 0, 3215, 0, + 0, 3349, 0, + 0, 3483, 0, + 0, 3617, 0, + 0, 3749, 0, + 0, 3883, 0, + 0, 4015, 0, + 2939, 0, 2759, + 2939, 0, 2759, + 2937, 0, 2757, + 2937, 0, 2757, + 2935, 0, 2755, + 2933, 0, 2753, + 2931, 0, 2751, + 2929, 0, 2747, + 2925, 0, 2743, + 2919, 0, 2737, + 2913, 0, 2729, + 2903, 0, 2719, + 2891, 0, 2703, + 2873, 720, 2683, + 2847, 1295, 2653, + 2811, 1601, 2609, + 2759, 1830, 2545, + 2677, 2023, 2441, + 2537, 2197, 2251, + 2239, 2357, 1705, + 0, 2509, 0, + 0, 2655, 0, + 0, 2797, 0, + 0, 2937, 0, + 0, 3075, 0, + 0, 3211, 0, + 0, 3347, 0, + 0, 3481, 0, + 0, 3615, 0, + 0, 3749, 0, + 0, 3881, 0, + 0, 4015, 0, + 3071, 0, 2891, + 3071, 0, 2889, + 3069, 0, 2889, + 3069, 0, 2889, + 3069, 0, 2887, + 3067, 0, 2887, + 3065, 0, 2885, + 3063, 0, 2883, + 3061, 0, 2879, + 3057, 0, 2875, + 3051, 0, 2869, + 3045, 0, 2861, + 3035, 0, 2849, + 3023, 0, 2835, + 3005, 842, 2813, + 2979, 1425, 2783, + 2943, 1732, 2741, + 2891, 1961, 2675, + 2809, 2155, 2571, + 2669, 2327, 2379, + 2371, 2489, 1829, + 0, 2641, 0, + 0, 2787, 0, + 0, 2929, 0, + 0, 3069, 0, + 0, 3207, 0, + 0, 3343, 0, + 0, 3479, 0, + 0, 3613, 0, + 0, 3747, 0, + 0, 3881, 0, + 0, 4015, 0, + 3203, 0, 3023, + 3203, 0, 3021, + 3203, 0, 3021, + 3201, 0, 3021, + 3201, 0, 3021, + 3201, 0, 3019, + 3199, 0, 3017, + 3197, 0, 3017, + 3195, 0, 3013, + 3193, 0, 3011, + 3189, 0, 3007, + 3183, 0, 3001, + 3177, 0, 2993, + 3167, 0, 2981, + 3155, 0, 2965, + 3137, 967, 2945, + 3111, 1555, 2915, + 3075, 1863, 2873, + 3023, 2093, 2807, + 2941, 2287, 2703, + 2801, 2459, 2511, + 2503, 2621, 1956, + 0, 2773, 0, + 0, 2919, 0, + 0, 3063, 0, + 0, 3201, 0, + 0, 3339, 0, + 0, 3477, 0, + 0, 3611, 0, + 0, 3745, 0, + 0, 3879, 0, + 0, 4013, 0, + 3335, 0, 3155, + 3335, 0, 3153, + 3335, 0, 3153, + 3335, 0, 3153, + 3333, 0, 3153, + 3333, 0, 3151, + 3333, 0, 3151, + 3331, 0, 3149, + 3329, 0, 3147, + 3327, 0, 3145, + 3325, 0, 3143, + 3321, 0, 3137, + 3315, 0, 3131, + 3309, 0, 3123, + 3299, 0, 3113, + 3287, 0, 3097, + 3269, 1093, 3077, + 3243, 1685, 3047, + 3207, 1994, 3003, + 3155, 2225, 2939, + 3073, 2419, 2835, + 2933, 2591, 2641, + 2635, 2753, 2083, + 0, 2905, 0, + 0, 3051, 0, + 0, 3195, 0, + 0, 3333, 0, + 0, 3471, 0, + 0, 3609, 0, + 0, 3743, 0, + 0, 3877, 0, + 0, 4011, 0, + 3467, 0, 3287, + 3467, 0, 3287, + 3467, 0, 3285, + 3467, 0, 3285, + 3467, 0, 3285, + 3465, 0, 3285, + 3465, 0, 3283, + 3465, 0, 3283, + 3463, 0, 3281, + 3461, 0, 3279, + 3459, 0, 3277, + 3457, 0, 3273, + 3453, 0, 3269, + 3447, 0, 3263, + 3441, 0, 3255, + 3431, 0, 3245, + 3419, 0, 3229, + 3401, 1221, 3209, + 3375, 1816, 3179, + 3339, 2125, 3135, + 3287, 2357, 3071, + 3205, 2551, 2965, + 3065, 2723, 2773, + 2765, 2885, 2213, + 0, 3037, 0, + 0, 3183, 0, + 0, 3327, 0, + 0, 3467, 0, + 0, 3603, 0, + 0, 3741, 0, + 0, 3875, 0, + 0, 4011, 0, + 3599, 0, 3419, + 3599, 0, 3419, + 3599, 0, 3417, + 3599, 0, 3417, + 3599, 0, 3417, + 3599, 0, 3417, + 3599, 0, 3417, + 3597, 0, 3415, + 3597, 0, 3415, + 3595, 0, 3413, + 3593, 0, 3411, + 3591, 0, 3409, + 3589, 0, 3405, + 3585, 0, 3401, + 3581, 0, 3395, + 3573, 0, 3387, + 3563, 0, 3377, + 3551, 0, 3361, + 3533, 1350, 3341, + 3507, 1947, 3311, + 3471, 2257, 3267, + 3419, 2489, 3203, + 3337, 2683, 3097, + 3197, 2855, 2903, + 2897, 3017, 2341, + 0, 3169, 0, + 0, 3315, 0, + 0, 3459, 0, + 0, 3599, 0, + 0, 3737, 0, + 0, 3873, 0, + 0, 4007, 0, + 3731, 0, 3551, + 3731, 0, 3551, + 3731, 0, 3551, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3729, 0, 3547, + 3729, 0, 3547, + 3727, 0, 3545, + 3725, 0, 3543, + 3723, 0, 3541, + 3721, 0, 3537, + 3717, 0, 3533, + 3713, 0, 3527, + 3705, 0, 3519, + 3695, 0, 3509, + 3683, 0, 3493, + 3665, 1479, 3473, + 3639, 2079, 3443, + 3603, 2389, 3399, + 3551, 2621, 3333, + 3469, 2815, 3229, + 3329, 2987, 3035, + 3029, 3149, 2473, + 0, 3301, 0, + 0, 3447, 0, + 0, 3591, 0, + 0, 3731, 0, + 0, 3869, 0, + 0, 4005, 0, + 3863, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3861, 0, 3679, + 3861, 0, 3679, + 3859, 0, 3677, + 3859, 0, 3675, + 3855, 0, 3673, + 3853, 0, 3669, + 3849, 0, 3665, + 3845, 0, 3659, + 3837, 0, 3651, + 3827, 0, 3641, + 3815, 0, 3625, + 3797, 1610, 3605, + 3771, 2211, 3575, + 3735, 2521, 3531, + 3683, 2753, 3465, + 3601, 2947, 3361, + 3461, 3119, 3167, + 3161, 3281, 2603, + 0, 3433, 0, + 0, 3579, 0, + 0, 3723, 0, + 0, 3863, 0, + 0, 4001, 0, + 3997, 0, 3815, + 3997, 0, 3815, + 3997, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3813, + 3995, 0, 3813, + 3995, 0, 3813, + 3995, 0, 3813, + 3995, 0, 3813, + 3993, 0, 3811, + 3993, 0, 3811, + 3991, 0, 3809, + 3991, 0, 3807, + 3989, 0, 3805, + 3985, 0, 3801, + 3981, 0, 3797, + 3977, 0, 3791, + 3969, 0, 3783, + 3959, 0, 3773, + 3947, 0, 3757, + 3929, 1740, 3737, + 3903, 2343, 3707, + 3867, 2653, 3663, + 3815, 2885, 3597, + 3733, 3079, 3493, + 3593, 3251, 3299, + 3293, 3413, 2733, + 0, 3565, 0, + 0, 3711, 0, + 0, 3855, 0, + 0, 3995, 0, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3943, + 4095, 0, 3943, + 4095, 0, 3941, + 4095, 0, 3939, + 4095, 0, 3937, + 4095, 0, 3933, + 4095, 0, 3929, + 4095, 0, 3923, + 4095, 0, 3915, + 4091, 0, 3905, + 4079, 0, 3889, + 4061, 1872, 3869, + 4035, 2475, 3839, + 3999, 2785, 3795, + 3947, 3017, 3729, + 3865, 3211, 3625, + 3725, 3383, 3431, + 3425, 3545, 2865, + 0, 3697, 0, + 0, 3843, 0, + 0, 3987, 0, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4075, + 4095, 0, 4075, + 4095, 0, 4073, + 4095, 0, 4071, + 4095, 0, 4069, + 4095, 0, 4065, + 4095, 0, 4061, + 4095, 0, 4055, + 4095, 0, 4047, + 4095, 0, 4037, + 4095, 0, 4021, + 4095, 2003, 4001, + 4095, 2607, 3971, + 4095, 2917, 3927, + 4079, 3149, 3861, + 3997, 3343, 3757, + 3857, 3517, 3563, + 3557, 3677, 2997, + 0, 3829, 0, + 0, 3977, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2135, 4095, + 4095, 2737, 4095, + 4095, 3049, 4059, + 4095, 3281, 3993, + 4095, 3475, 3889, + 3989, 3649, 3695, + 3689, 3809, 3129, + 0, 3961, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2267, 4095, + 4095, 2869, 4095, + 4095, 3181, 4095, + 4095, 3413, 4095, + 4095, 3607, 4021, + 4095, 3781, 3827, + 3821, 3941, 3261, + 325, 108, 616, + 140, 200, 549, + 0, 299, 442, + 0, 405, 242, + 0, 517, 0, + 0, 633, 0, + 0, 753, 0, + 0, 875, 0, + 0, 1000, 0, + 0, 1127, 0, + 0, 1255, 0, + 0, 1384, 0, + 0, 1513, 0, + 0, 1644, 0, + 0, 1775, 0, + 0, 1906, 0, + 0, 2037, 0, + 0, 2169, 0, + 0, 2301, 0, + 0, 2433, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 486, 92, 679, + 364, 187, 622, + 125, 289, 532, + 0, 397, 375, + 0, 510, 9, + 0, 628, 0, + 0, 749, 0, + 0, 872, 0, + 0, 998, 0, + 0, 1125, 0, + 0, 1253, 0, + 0, 1383, 0, + 0, 1513, 0, + 0, 1643, 0, + 0, 1774, 0, + 0, 1905, 0, + 0, 2037, 0, + 0, 2169, 0, + 0, 2301, 0, + 0, 2433, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 638, 70, 752, + 554, 169, 704, + 412, 274, 630, + 103, 386, 508, + 0, 502, 267, + 0, 621, 0, + 0, 744, 0, + 0, 868, 0, + 0, 995, 0, + 0, 1123, 0, + 0, 1252, 0, + 0, 1381, 0, + 0, 1512, 0, + 0, 1643, 0, + 0, 1774, 0, + 0, 1905, 0, + 0, 2037, 0, + 0, 2169, 0, + 0, 2301, 0, + 0, 2433, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 785, 38, 835, + 726, 144, 795, + 633, 255, 735, + 469, 370, 641, + 73, 490, 474, + 0, 612, 63, + 0, 737, 0, + 0, 863, 0, + 0, 991, 0, + 0, 1120, 0, + 0, 1249, 0, + 0, 1380, 0, + 0, 1510, 0, + 0, 1642, 0, + 0, 1773, 0, + 0, 1905, 0, + 0, 2036, 0, + 0, 2169, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 927, 0, 926, + 885, 108, 893, + 822, 227, 846, + 720, 349, 774, + 535, 473, 655, + 29, 599, 424, + 0, 727, 0, + 0, 856, 0, + 0, 986, 0, + 0, 1116, 0, + 0, 1246, 0, + 0, 1377, 0, + 0, 1509, 0, + 0, 1640, 0, + 0, 1772, 0, + 0, 1904, 0, + 0, 2036, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1067, 0, 1024, + 1036, 55, 998, + 992, 187, 961, + 925, 318, 906, + 816, 450, 821, + 611, 582, 673, + 0, 714, 346, + 0, 846, 0, + 0, 978, 0, + 0, 1110, 0, + 0, 1242, 0, + 0, 1374, 0, + 0, 1506, 0, + 0, 1639, 0, + 0, 1771, 0, + 0, 1903, 0, + 0, 2035, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1205, 0, 1129, + 1182, 0, 1109, + 1151, 127, 1080, + 1104, 274, 1039, + 1034, 418, 976, + 919, 558, 877, + 696, 696, 696, + 0, 833, 216, + 0, 968, 0, + 0, 1103, 0, + 0, 1237, 0, + 0, 1370, 0, + 0, 1503, 0, + 0, 1636, 0, + 0, 1769, 0, + 0, 1902, 0, + 0, 2034, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1341, 0, 1241, + 1325, 0, 1225, + 1302, 31, 1202, + 1269, 208, 1171, + 1221, 370, 1125, + 1148, 524, 1056, + 1027, 671, 942, + 790, 814, 725, + 0, 955, 0, + 0, 1093, 0, + 0, 1229, 0, + 0, 1365, 0, + 0, 1499, 0, + 0, 1633, 0, + 0, 1767, 0, + 0, 1900, 0, + 0, 2033, 0, + 0, 2165, 0, + 0, 2297, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1477, 0, 1356, + 1464, 0, 1344, + 1447, 0, 1327, + 1424, 100, 1303, + 1390, 297, 1269, + 1341, 473, 1220, + 1266, 635, 1144, + 1141, 788, 1017, + 891, 936, 762, + 0, 1079, 0, + 0, 1219, 0, + 0, 1357, 0, + 0, 1494, 0, + 0, 1629, 0, + 0, 1764, 0, + 0, 1897, 0, + 0, 2031, 0, + 0, 2165, 0, + 0, 2297, 0, + 0, 2429, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1611, 0, 1476, + 1602, 0, 1466, + 1590, 0, 1453, + 1572, 0, 1436, + 1549, 178, 1411, + 1514, 395, 1375, + 1464, 582, 1322, + 1388, 751, 1240, + 1259, 909, 1101, + 998, 1059, 806, + 0, 1205, 0, + 0, 1347, 0, + 0, 1486, 0, + 0, 1623, 0, + 0, 1759, 0, + 0, 1894, 0, + 0, 2029, 0, + 0, 2163, 0, + 0, 2295, 0, + 0, 2429, 0, + 0, 2561, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1745, 0, 1598, + 1738, 0, 1591, + 1729, 0, 1581, + 1716, 0, 1568, + 1699, 0, 1549, + 1675, 264, 1523, + 1640, 500, 1486, + 1590, 696, 1430, + 1511, 871, 1344, + 1380, 1032, 1194, + 1110, 1185, 859, + 0, 1332, 0, + 0, 1476, 0, + 0, 1616, 0, + 0, 1754, 0, + 0, 1890, 0, + 0, 2025, 0, + 0, 2161, 0, + 0, 2293, 0, + 0, 2427, 0, + 0, 2561, 0, + 0, 2693, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1878, 0, 1723, + 1873, 0, 1717, + 1867, 0, 1710, + 1857, 0, 1700, + 1845, 0, 1686, + 1827, 0, 1667, + 1803, 359, 1640, + 1768, 610, 1601, + 1717, 814, 1544, + 1637, 994, 1453, + 1504, 1158, 1294, + 1227, 1313, 922, + 0, 1461, 0, + 0, 1605, 0, + 0, 1746, 0, + 0, 1884, 0, + 0, 2021, 0, + 0, 2157, 0, + 0, 2291, 0, + 0, 2425, 0, + 0, 2559, 0, + 0, 2693, 0, + 0, 2825, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2011, 0, 1849, + 2008, 0, 1845, + 2003, 0, 1840, + 1996, 0, 1832, + 1987, 0, 1822, + 1974, 0, 1808, + 1956, 59, 1788, + 1932, 462, 1761, + 1896, 725, 1721, + 1845, 936, 1661, + 1765, 1118, 1568, + 1630, 1285, 1401, + 1348, 1441, 994, + 0, 1591, 0, + 0, 1735, 0, + 0, 1877, 0, + 0, 2016, 0, + 0, 2153, 0, + 0, 2289, 0, + 0, 2423, 0, + 0, 2557, 0, + 0, 2691, 0, + 0, 2825, 0, + 0, 2957, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2145, 0, 1977, + 2141, 0, 1974, + 2137, 0, 1970, + 2133, 0, 1964, + 2125, 0, 1957, + 2117, 0, 1946, + 2103, 0, 1932, + 2087, 132, 1912, + 2061, 570, 1884, + 2026, 844, 1843, + 1974, 1059, 1782, + 1893, 1245, 1686, + 1757, 1413, 1513, + 1471, 1571, 1076, + 0, 1721, 0, + 0, 1866, 0, + 0, 2008, 0, + 0, 2147, 0, + 0, 2285, 0, + 0, 2421, 0, + 0, 2555, 0, + 0, 2689, 0, + 0, 2823, 0, + 0, 2957, 0, + 0, 3089, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2277, 0, 2107, + 2275, 0, 2103, + 2273, 0, 2101, + 2269, 0, 2097, + 2263, 0, 2091, + 2257, 0, 2083, + 2247, 0, 2073, + 2235, 0, 2057, + 2217, 213, 2038, + 2191, 684, 2009, + 2157, 966, 1968, + 2103, 1185, 1906, + 2023, 1373, 1807, + 1886, 1543, 1630, + 1596, 1701, 1166, + 0, 1852, 0, + 0, 1997, 0, + 0, 2139, 0, + 0, 2279, 0, + 0, 2415, 0, + 0, 2551, 0, + 0, 2687, 0, + 0, 2821, 0, + 0, 2955, 0, + 0, 3089, 0, + 0, 3221, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3885, 0, + 0, 4017, 0, + 2409, 0, 2235, + 2407, 0, 2235, + 2405, 0, 2231, + 2403, 0, 2229, + 2399, 0, 2225, + 2395, 0, 2219, + 2387, 0, 2211, + 2377, 0, 2201, + 2365, 0, 2185, + 2347, 304, 2165, + 2323, 801, 2135, + 2287, 1090, 2095, + 2235, 1313, 2032, + 2153, 1502, 1932, + 2015, 1673, 1750, + 1723, 1831, 1264, + 0, 1983, 0, + 0, 2129, 0, + 0, 2271, 0, + 0, 2411, 0, + 0, 2547, 0, + 0, 2683, 0, + 0, 2819, 0, + 0, 2953, 0, + 0, 3087, 0, + 0, 3221, 0, + 0, 3353, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4017, 0, + 2541, 0, 2367, + 2541, 0, 2365, + 2539, 0, 2363, + 2537, 0, 2361, + 2535, 0, 2357, + 2531, 0, 2353, + 2525, 0, 2347, + 2519, 0, 2339, + 2509, 0, 2329, + 2497, 0, 2313, + 2479, 402, 2293, + 2453, 922, 2265, + 2417, 1217, 2223, + 2365, 1441, 2159, + 2283, 1632, 2057, + 2145, 1803, 1873, + 1851, 1962, 1369, + 0, 2115, 0, + 0, 2261, 0, + 0, 2403, 0, + 0, 2543, 0, + 0, 2679, 0, + 0, 2815, 0, + 0, 2951, 0, + 0, 3085, 0, + 0, 3219, 0, + 0, 3353, 0, + 0, 3485, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4017, 0, + 2675, 0, 2497, + 2673, 0, 2497, + 2673, 0, 2495, + 2671, 0, 2493, + 2669, 0, 2491, + 2665, 0, 2487, + 2661, 0, 2483, + 2657, 0, 2477, + 2649, 0, 2469, + 2641, 0, 2459, + 2627, 0, 2443, + 2609, 507, 2423, + 2585, 1046, 2393, + 2549, 1345, 2351, + 2497, 1571, 2287, + 2415, 1762, 2185, + 2275, 1934, 1998, + 1981, 2093, 1480, + 0, 2245, 0, + 0, 2391, 0, + 0, 2535, 0, + 0, 2673, 0, + 0, 2811, 0, + 0, 2947, 0, + 0, 3083, 0, + 0, 3217, 0, + 0, 3351, 0, + 0, 3485, 0, + 0, 3617, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 2807, 0, 2629, + 2805, 0, 2627, + 2805, 0, 2627, + 2803, 0, 2625, + 2803, 0, 2623, + 2801, 0, 2621, + 2797, 0, 2617, + 2793, 0, 2613, + 2789, 0, 2607, + 2781, 0, 2599, + 2773, 0, 2589, + 2759, 0, 2573, + 2741, 617, 2553, + 2717, 1172, 2523, + 2681, 1473, 2481, + 2627, 1701, 2417, + 2545, 1893, 2313, + 2407, 2065, 2125, + 2111, 2225, 1595, + 0, 2377, 0, + 0, 2523, 0, + 0, 2667, 0, + 0, 2805, 0, + 0, 2943, 0, + 0, 3079, 0, + 0, 3215, 0, + 0, 3349, 0, + 0, 3483, 0, + 0, 3617, 0, + 0, 3749, 0, + 0, 3883, 0, + 0, 4015, 0, + 2939, 0, 2759, + 2939, 0, 2759, + 2937, 0, 2759, + 2937, 0, 2757, + 2935, 0, 2755, + 2935, 0, 2755, + 2931, 0, 2751, + 2929, 0, 2749, + 2925, 0, 2745, + 2921, 0, 2739, + 2913, 0, 2731, + 2903, 0, 2719, + 2891, 0, 2705, + 2873, 733, 2683, + 2849, 1299, 2653, + 2813, 1603, 2611, + 2759, 1831, 2547, + 2677, 2024, 2443, + 2539, 2197, 2253, + 2241, 2357, 1714, + 0, 2509, 0, + 0, 2655, 0, + 0, 2799, 0, + 0, 2937, 0, + 0, 3075, 0, + 0, 3211, 0, + 0, 3347, 0, + 0, 3481, 0, + 0, 3615, 0, + 0, 3749, 0, + 0, 3881, 0, + 0, 4015, 0, + 3071, 0, 2891, + 3071, 0, 2891, + 3071, 0, 2891, + 3069, 0, 2889, + 3069, 0, 2889, + 3067, 0, 2887, + 3065, 0, 2885, + 3063, 0, 2883, + 3061, 0, 2879, + 3057, 0, 2875, + 3053, 0, 2869, + 3045, 0, 2861, + 3035, 0, 2851, + 3023, 0, 2835, + 3005, 852, 2815, + 2979, 1427, 2785, + 2943, 1733, 2741, + 2891, 1962, 2677, + 2809, 2155, 2573, + 2669, 2329, 2383, + 2371, 2489, 1837, + 0, 2641, 0, + 0, 2787, 0, + 0, 2931, 0, + 0, 3069, 0, + 0, 3207, 0, + 0, 3345, 0, + 0, 3479, 0, + 0, 3613, 0, + 0, 3747, 0, + 0, 3881, 0, + 0, 4015, 0, + 3203, 0, 3023, + 3203, 0, 3023, + 3203, 0, 3023, + 3203, 0, 3021, + 3201, 0, 3021, + 3201, 0, 3019, + 3199, 0, 3019, + 3197, 0, 3017, + 3195, 0, 3015, + 3193, 0, 3011, + 3189, 0, 3007, + 3185, 0, 3001, + 3177, 0, 2993, + 3167, 0, 2981, + 3155, 0, 2967, + 3137, 974, 2945, + 3111, 1557, 2915, + 3075, 1864, 2873, + 3023, 2093, 2809, + 2941, 2287, 2703, + 2801, 2461, 2513, + 2503, 2621, 1961, + 0, 2773, 0, + 0, 2919, 0, + 0, 3063, 0, + 0, 3201, 0, + 0, 3339, 0, + 0, 3477, 0, + 0, 3611, 0, + 0, 3745, 0, + 0, 3879, 0, + 0, 4013, 0, + 3335, 0, 3155, + 3335, 0, 3155, + 3335, 0, 3155, + 3335, 0, 3153, + 3335, 0, 3153, + 3333, 0, 3153, + 3333, 0, 3151, + 3331, 0, 3151, + 3329, 0, 3149, + 3327, 0, 3145, + 3325, 0, 3143, + 3321, 0, 3139, + 3317, 0, 3133, + 3309, 0, 3125, + 3299, 0, 3113, + 3287, 0, 3099, + 3269, 1099, 3077, + 3243, 1687, 3047, + 3207, 1995, 3005, + 3155, 2225, 2939, + 3073, 2419, 2835, + 2933, 2591, 2643, + 2635, 2753, 2087, + 0, 2905, 0, + 0, 3051, 0, + 0, 3195, 0, + 0, 3335, 0, + 0, 3471, 0, + 0, 3609, 0, + 0, 3743, 0, + 0, 3877, 0, + 0, 4011, 0, + 3467, 0, 3287, + 3467, 0, 3287, + 3467, 0, 3287, + 3467, 0, 3285, + 3467, 0, 3285, + 3467, 0, 3285, + 3465, 0, 3285, + 3465, 0, 3283, + 3463, 0, 3281, + 3461, 0, 3279, + 3459, 0, 3277, + 3457, 0, 3275, + 3453, 0, 3269, + 3449, 0, 3263, + 3441, 0, 3255, + 3431, 0, 3245, + 3419, 0, 3229, + 3401, 1225, 3209, + 3375, 1817, 3179, + 3339, 2127, 3135, + 3287, 2357, 3071, + 3205, 2551, 2967, + 3065, 2723, 2773, + 2767, 2885, 2215, + 0, 3037, 0, + 0, 3183, 0, + 0, 3327, 0, + 0, 3467, 0, + 0, 3603, 0, + 0, 3741, 0, + 0, 3875, 0, + 0, 4011, 0, + 3599, 0, 3419, + 3599, 0, 3419, + 3599, 0, 3419, + 3599, 0, 3417, + 3599, 0, 3417, + 3599, 0, 3417, + 3599, 0, 3417, + 3597, 0, 3415, + 3597, 0, 3415, + 3595, 0, 3413, + 3593, 0, 3411, + 3591, 0, 3409, + 3589, 0, 3407, + 3585, 0, 3401, + 3581, 0, 3395, + 3573, 0, 3387, + 3563, 0, 3377, + 3551, 0, 3361, + 3533, 1353, 3341, + 3507, 1948, 3311, + 3471, 2257, 3267, + 3419, 2489, 3203, + 3337, 2683, 3097, + 3197, 2855, 2905, + 2897, 3017, 2345, + 0, 3169, 0, + 0, 3315, 0, + 0, 3459, 0, + 0, 3599, 0, + 0, 3737, 0, + 0, 3873, 0, + 0, 4007, 0, + 3731, 0, 3551, + 3731, 0, 3551, + 3731, 0, 3551, + 3731, 0, 3551, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3729, 0, 3547, + 3729, 0, 3547, + 3727, 0, 3545, + 3725, 0, 3543, + 3723, 0, 3541, + 3721, 0, 3537, + 3717, 0, 3533, + 3713, 0, 3527, + 3705, 0, 3519, + 3695, 0, 3509, + 3683, 0, 3493, + 3665, 1482, 3473, + 3639, 2079, 3443, + 3603, 2389, 3399, + 3551, 2621, 3335, + 3469, 2815, 3229, + 3329, 2987, 3035, + 3029, 3149, 2473, + 0, 3301, 0, + 0, 3447, 0, + 0, 3591, 0, + 0, 3731, 0, + 0, 3869, 0, + 0, 4005, 0, + 3865, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3861, 0, 3679, + 3861, 0, 3679, + 3859, 0, 3677, + 3859, 0, 3675, + 3855, 0, 3673, + 3853, 0, 3669, + 3849, 0, 3665, + 3845, 0, 3659, + 3837, 0, 3651, + 3827, 0, 3641, + 3815, 0, 3625, + 3797, 1612, 3605, + 3771, 2211, 3575, + 3735, 2521, 3531, + 3683, 2753, 3467, + 3601, 2947, 3361, + 3461, 3119, 3167, + 3161, 3281, 2605, + 0, 3433, 0, + 0, 3579, 0, + 0, 3723, 0, + 0, 3863, 0, + 0, 4001, 0, + 3997, 0, 3815, + 3997, 0, 3815, + 3997, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3813, + 3995, 0, 3813, + 3995, 0, 3813, + 3995, 0, 3813, + 3993, 0, 3811, + 3993, 0, 3811, + 3991, 0, 3809, + 3991, 0, 3807, + 3989, 0, 3805, + 3985, 0, 3801, + 3981, 0, 3797, + 3977, 0, 3791, + 3969, 0, 3783, + 3959, 0, 3773, + 3947, 0, 3757, + 3929, 1742, 3737, + 3903, 2343, 3707, + 3867, 2653, 3663, + 3815, 2885, 3597, + 3733, 3079, 3493, + 3593, 3251, 3299, + 3293, 3413, 2735, + 0, 3565, 0, + 0, 3711, 0, + 0, 3855, 0, + 0, 3995, 0, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3943, + 4095, 0, 3943, + 4095, 0, 3941, + 4095, 0, 3939, + 4095, 0, 3937, + 4095, 0, 3933, + 4095, 0, 3929, + 4095, 0, 3923, + 4095, 0, 3915, + 4093, 0, 3905, + 4079, 0, 3889, + 4061, 1873, 3869, + 4035, 2475, 3839, + 4001, 2785, 3795, + 3947, 3017, 3729, + 3865, 3211, 3625, + 3725, 3383, 3431, + 3425, 3545, 2867, + 0, 3697, 0, + 0, 3843, 0, + 0, 3987, 0, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4075, + 4095, 0, 4075, + 4095, 0, 4073, + 4095, 0, 4071, + 4095, 0, 4069, + 4095, 0, 4067, + 4095, 0, 4061, + 4095, 0, 4055, + 4095, 0, 4047, + 4095, 0, 4037, + 4095, 0, 4021, + 4095, 2004, 4001, + 4095, 2607, 3971, + 4095, 2917, 3927, + 4079, 3149, 3861, + 3997, 3343, 3757, + 3857, 3517, 3563, + 3557, 3677, 2997, + 0, 3829, 0, + 0, 3977, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2135, 4095, + 4095, 2739, 4095, + 4095, 3049, 4059, + 4095, 3281, 3993, + 4095, 3475, 3889, + 3989, 3649, 3695, + 3689, 3809, 3129, + 0, 3961, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2267, 4095, + 4095, 2871, 4095, + 4095, 3181, 4095, + 4095, 3413, 4095, + 4095, 3607, 4021, + 4095, 3781, 3827, + 3821, 3941, 3261, + 425, 171, 743, + 284, 251, 694, + 0, 341, 618, + 0, 439, 493, + 0, 543, 240, + 0, 653, 0, + 0, 769, 0, + 0, 887, 0, + 0, 1009, 0, + 0, 1134, 0, + 0, 1260, 0, + 0, 1388, 0, + 0, 1516, 0, + 0, 1646, 0, + 0, 1776, 0, + 0, 1907, 0, + 0, 2038, 0, + 0, 2169, 0, + 0, 2301, 0, + 0, 2433, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 558, 157, 792, + 457, 240, 748, + 272, 332, 682, + 0, 431, 574, + 0, 537, 374, + 0, 649, 0, + 0, 765, 0, + 0, 885, 0, + 0, 1007, 0, + 0, 1132, 0, + 0, 1259, 0, + 0, 1387, 0, + 0, 1516, 0, + 0, 1646, 0, + 0, 1776, 0, + 0, 1907, 0, + 0, 2038, 0, + 0, 2169, 0, + 0, 2301, 0, + 0, 2433, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 691, 138, 850, + 618, 224, 811, + 496, 319, 754, + 257, 421, 664, + 0, 529, 507, + 0, 642, 141, + 0, 760, 0, + 0, 881, 0, + 0, 1004, 0, + 0, 1130, 0, + 0, 1257, 0, + 0, 1385, 0, + 0, 1515, 0, + 0, 1645, 0, + 0, 1775, 0, + 0, 1906, 0, + 0, 2038, 0, + 0, 2169, 0, + 0, 2301, 0, + 0, 2433, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 824, 111, 918, + 770, 202, 885, + 687, 301, 836, + 544, 407, 762, + 235, 518, 640, + 0, 634, 399, + 0, 753, 0, + 0, 876, 0, + 0, 1001, 0, + 0, 1127, 0, + 0, 1255, 0, + 0, 1384, 0, + 0, 1514, 0, + 0, 1644, 0, + 0, 1775, 0, + 0, 1906, 0, + 0, 2037, 0, + 0, 2169, 0, + 0, 2301, 0, + 0, 2433, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 956, 72, 995, + 917, 170, 967, + 858, 276, 927, + 765, 387, 867, + 601, 502, 773, + 205, 622, 606, + 0, 744, 196, + 0, 869, 0, + 0, 995, 0, + 0, 1123, 0, + 0, 1252, 0, + 0, 1382, 0, + 0, 1512, 0, + 0, 1643, 0, + 0, 1774, 0, + 0, 1905, 0, + 0, 2037, 0, + 0, 2169, 0, + 0, 2301, 0, + 0, 2433, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1088, 14, 1080, + 1059, 125, 1058, + 1017, 240, 1025, + 954, 359, 978, + 852, 481, 906, + 667, 605, 787, + 161, 732, 556, + 0, 859, 0, + 0, 988, 0, + 0, 1117, 0, + 0, 1248, 0, + 0, 1378, 0, + 0, 1510, 0, + 0, 1641, 0, + 0, 1772, 0, + 0, 1904, 0, + 0, 2036, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1221, 0, 1175, + 1199, 55, 1156, + 1169, 187, 1130, + 1124, 319, 1093, + 1057, 450, 1038, + 948, 582, 953, + 743, 714, 805, + 94, 846, 478, + 0, 978, 0, + 0, 1110, 0, + 0, 1242, 0, + 0, 1374, 0, + 0, 1506, 0, + 0, 1639, 0, + 0, 1771, 0, + 0, 1903, 0, + 0, 2035, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1353, 0, 1276, + 1337, 0, 1262, + 1315, 105, 1241, + 1283, 259, 1212, + 1236, 406, 1171, + 1166, 550, 1108, + 1050, 690, 1009, + 828, 828, 828, + 0, 965, 349, + 0, 1100, 0, + 0, 1235, 0, + 0, 1369, 0, + 0, 1502, 0, + 0, 1636, 0, + 0, 1768, 0, + 0, 1901, 0, + 0, 2034, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1485, 0, 1384, + 1473, 0, 1373, + 1457, 0, 1357, + 1434, 164, 1335, + 1401, 340, 1303, + 1353, 502, 1257, + 1280, 656, 1188, + 1159, 803, 1074, + 922, 947, 858, + 0, 1087, 83, + 0, 1225, 0, + 0, 1361, 0, + 0, 1497, 0, + 0, 1631, 0, + 0, 1765, 0, + 0, 1899, 0, + 0, 2032, 0, + 0, 2165, 0, + 0, 2297, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1618, 0, 1497, + 1609, 0, 1488, + 1596, 0, 1476, + 1580, 0, 1459, + 1556, 232, 1435, + 1523, 430, 1402, + 1473, 605, 1352, + 1398, 767, 1276, + 1273, 921, 1149, + 1023, 1068, 894, + 0, 1211, 0, + 0, 1351, 0, + 0, 1489, 0, + 0, 1626, 0, + 0, 1761, 0, + 0, 1896, 0, + 0, 2030, 0, + 0, 2163, 0, + 0, 2297, 0, + 0, 2429, 0, + 0, 2561, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1750, 0, 1615, + 1743, 0, 1608, + 1734, 0, 1598, + 1722, 0, 1586, + 1705, 31, 1568, + 1681, 310, 1543, + 1647, 527, 1507, + 1597, 714, 1454, + 1520, 883, 1372, + 1391, 1041, 1234, + 1130, 1192, 938, + 0, 1337, 0, + 0, 1479, 0, + 0, 1618, 0, + 0, 1755, 0, + 0, 1891, 0, + 0, 2026, 0, + 0, 2161, 0, + 0, 2295, 0, + 0, 2427, 0, + 0, 2561, 0, + 0, 2693, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1882, 0, 1736, + 1877, 0, 1730, + 1870, 0, 1723, + 1861, 0, 1713, + 1849, 0, 1700, + 1831, 75, 1681, + 1807, 397, 1655, + 1773, 632, 1618, + 1722, 828, 1562, + 1644, 1003, 1476, + 1512, 1164, 1326, + 1242, 1317, 992, + 0, 1465, 0, + 0, 1608, 0, + 0, 1748, 0, + 0, 1886, 0, + 0, 2022, 0, + 0, 2157, 0, + 0, 2293, 0, + 0, 2427, 0, + 0, 2559, 0, + 0, 2693, 0, + 0, 2825, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2014, 0, 1859, + 2010, 0, 1855, + 2005, 0, 1850, + 1999, 0, 1842, + 1989, 0, 1832, + 1977, 0, 1818, + 1959, 128, 1799, + 1935, 492, 1772, + 1900, 742, 1733, + 1849, 946, 1676, + 1770, 1125, 1585, + 1636, 1290, 1426, + 1359, 1445, 1054, + 0, 1593, 0, + 0, 1737, 0, + 0, 1878, 0, + 0, 2017, 0, + 0, 2153, 0, + 0, 2289, 0, + 0, 2423, 0, + 0, 2557, 0, + 0, 2691, 0, + 0, 2825, 0, + 0, 2957, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2147, 0, 1985, + 2143, 0, 1982, + 2139, 0, 1977, + 2135, 0, 1972, + 2127, 0, 1964, + 2119, 0, 1954, + 2105, 0, 1940, + 2089, 191, 1920, + 2063, 594, 1893, + 2029, 857, 1853, + 1977, 1067, 1793, + 1897, 1250, 1700, + 1762, 1417, 1533, + 1480, 1573, 1126, + 0, 1723, 0, + 0, 1868, 0, + 0, 2009, 0, + 0, 2147, 0, + 0, 2285, 0, + 0, 2421, 0, + 0, 2555, 0, + 0, 2689, 0, + 0, 2823, 0, + 0, 2957, 0, + 0, 3089, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2279, 0, 2111, + 2277, 0, 2109, + 2273, 0, 2107, + 2269, 0, 2103, + 2265, 0, 2097, + 2257, 0, 2089, + 2249, 0, 2079, + 2235, 0, 2063, + 2219, 264, 2044, + 2193, 702, 2016, + 2159, 976, 1975, + 2107, 1191, 1914, + 2026, 1377, 1818, + 1889, 1545, 1645, + 1603, 1703, 1208, + 0, 1853, 0, + 0, 1998, 0, + 0, 2139, 0, + 0, 2279, 0, + 0, 2417, 0, + 0, 2553, 0, + 0, 2687, 0, + 0, 2821, 0, + 0, 2955, 0, + 0, 3089, 0, + 0, 3221, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3885, 0, + 0, 4017, 0, + 2411, 0, 2241, + 2409, 0, 2239, + 2407, 0, 2237, + 2405, 0, 2233, + 2401, 0, 2229, + 2395, 0, 2223, + 2389, 0, 2215, + 2379, 0, 2205, + 2367, 0, 2189, + 2349, 345, 2169, + 2323, 816, 2141, + 2289, 1098, 2099, + 2235, 1317, 2038, + 2155, 1505, 1940, + 2018, 1675, 1762, + 1728, 1833, 1298, + 0, 1984, 0, + 0, 2129, 0, + 0, 2271, 0, + 0, 2411, 0, + 0, 2549, 0, + 0, 2685, 0, + 0, 2819, 0, + 0, 2953, 0, + 0, 3087, 0, + 0, 3221, 0, + 0, 3353, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4017, 0, + 2543, 0, 2369, + 2541, 0, 2369, + 2541, 0, 2367, + 2537, 0, 2363, + 2535, 0, 2361, + 2531, 0, 2357, + 2527, 0, 2351, + 2519, 0, 2343, + 2511, 0, 2333, + 2497, 0, 2317, + 2479, 436, 2297, + 2455, 933, 2269, + 2419, 1223, 2227, + 2367, 1445, 2163, + 2285, 1634, 2063, + 2147, 1805, 1882, + 1855, 1964, 1396, + 0, 2115, 0, + 0, 2261, 0, + 0, 2403, 0, + 0, 2543, 0, + 0, 2679, 0, + 0, 2817, 0, + 0, 2951, 0, + 0, 3085, 0, + 0, 3219, 0, + 0, 3353, 0, + 0, 3485, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4017, 0, + 2675, 0, 2499, + 2675, 0, 2499, + 2673, 0, 2497, + 2671, 0, 2495, + 2669, 0, 2493, + 2667, 0, 2489, + 2663, 0, 2485, + 2657, 0, 2479, + 2651, 0, 2471, + 2641, 0, 2461, + 2629, 0, 2447, + 2611, 534, 2425, + 2585, 1054, 2397, + 2549, 1349, 2355, + 2497, 1573, 2291, + 2415, 1764, 2189, + 2277, 1935, 2005, + 1984, 2095, 1501, + 0, 2247, 0, + 0, 2393, 0, + 0, 2535, 0, + 0, 2675, 0, + 0, 2811, 0, + 0, 2947, 0, + 0, 3083, 0, + 0, 3217, 0, + 0, 3351, 0, + 0, 3485, 0, + 0, 3617, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 2807, 0, 2629, + 2807, 0, 2629, + 2805, 0, 2629, + 2805, 0, 2627, + 2803, 0, 2625, + 2801, 0, 2623, + 2797, 0, 2619, + 2795, 0, 2615, + 2789, 0, 2609, + 2783, 0, 2601, + 2773, 0, 2591, + 2759, 0, 2575, + 2741, 639, 2555, + 2717, 1178, 2525, + 2681, 1477, 2483, + 2629, 1703, 2419, + 2547, 1894, 2317, + 2407, 2067, 2131, + 2113, 2225, 1612, + 0, 2377, 0, + 0, 2523, 0, + 0, 2667, 0, + 0, 2807, 0, + 0, 2943, 0, + 0, 3079, 0, + 0, 3215, 0, + 0, 3349, 0, + 0, 3483, 0, + 0, 3617, 0, + 0, 3749, 0, + 0, 3883, 0, + 0, 4015, 0, + 2939, 0, 2761, + 2939, 0, 2761, + 2939, 0, 2759, + 2937, 0, 2759, + 2935, 0, 2757, + 2935, 0, 2755, + 2933, 0, 2753, + 2929, 0, 2749, + 2925, 0, 2745, + 2921, 0, 2739, + 2913, 0, 2731, + 2905, 0, 2721, + 2891, 0, 2705, + 2873, 750, 2685, + 2849, 1304, 2655, + 2813, 1605, 2613, + 2759, 1833, 2549, + 2679, 2025, 2445, + 2539, 2197, 2257, + 2243, 2357, 1727, + 0, 2509, 0, + 0, 2655, 0, + 0, 2799, 0, + 0, 2937, 0, + 0, 3075, 0, + 0, 3213, 0, + 0, 3347, 0, + 0, 3481, 0, + 0, 3615, 0, + 0, 3749, 0, + 0, 3881, 0, + 0, 4015, 0, + 3071, 0, 2893, + 3071, 0, 2891, + 3071, 0, 2891, + 3069, 0, 2891, + 3069, 0, 2889, + 3067, 0, 2889, + 3067, 0, 2887, + 3065, 0, 2883, + 3061, 0, 2881, + 3057, 0, 2877, + 3053, 0, 2871, + 3045, 0, 2863, + 3037, 0, 2851, + 3023, 0, 2837, + 3005, 865, 2815, + 2981, 1431, 2785, + 2945, 1735, 2743, + 2891, 1963, 2679, + 2809, 2157, 2575, + 2671, 2329, 2385, + 2373, 2489, 1847, + 0, 2641, 0, + 0, 2787, 0, + 0, 2931, 0, + 0, 3069, 0, + 0, 3207, 0, + 0, 3345, 0, + 0, 3479, 0, + 0, 3613, 0, + 0, 3747, 0, + 0, 3881, 0, + 0, 4015, 0, + 3203, 0, 3023, + 3203, 0, 3023, + 3203, 0, 3023, + 3203, 0, 3023, + 3201, 0, 3021, + 3201, 0, 3021, + 3199, 0, 3019, + 3199, 0, 3017, + 3195, 0, 3015, + 3193, 0, 3011, + 3189, 0, 3007, + 3185, 0, 3001, + 3177, 0, 2993, + 3167, 0, 2983, + 3155, 0, 2967, + 3137, 984, 2947, + 3111, 1559, 2917, + 3077, 1865, 2873, + 3023, 2095, 2809, + 2941, 2287, 2705, + 2801, 2461, 2515, + 2505, 2621, 1969, + 0, 2773, 0, + 0, 2919, 0, + 0, 3063, 0, + 0, 3203, 0, + 0, 3339, 0, + 0, 3477, 0, + 0, 3611, 0, + 0, 3745, 0, + 0, 3879, 0, + 0, 4013, 0, + 3335, 0, 3155, + 3335, 0, 3155, + 3335, 0, 3155, + 3335, 0, 3155, + 3335, 0, 3153, + 3333, 0, 3153, + 3333, 0, 3151, + 3331, 0, 3151, + 3329, 0, 3149, + 3327, 0, 3147, + 3325, 0, 3143, + 3321, 0, 3139, + 3317, 0, 3133, + 3309, 0, 3125, + 3299, 0, 3113, + 3287, 0, 3099, + 3269, 1106, 3077, + 3243, 1689, 3049, + 3207, 1996, 3005, + 3155, 2225, 2941, + 3073, 2419, 2837, + 2933, 2593, 2645, + 2635, 2753, 2093, + 0, 2905, 0, + 0, 3051, 0, + 0, 3195, 0, + 0, 3335, 0, + 0, 3471, 0, + 0, 3609, 0, + 0, 3743, 0, + 0, 3877, 0, + 0, 4011, 0, + 3467, 0, 3287, + 3467, 0, 3287, + 3467, 0, 3287, + 3467, 0, 3287, + 3467, 0, 3285, + 3467, 0, 3285, + 3465, 0, 3285, + 3465, 0, 3283, + 3463, 0, 3283, + 3461, 0, 3281, + 3459, 0, 3277, + 3457, 0, 3275, + 3453, 0, 3271, + 3449, 0, 3265, + 3441, 0, 3257, + 3431, 0, 3245, + 3419, 0, 3231, + 3401, 1231, 3209, + 3375, 1819, 3179, + 3339, 2127, 3137, + 3287, 2357, 3071, + 3205, 2551, 2967, + 3065, 2725, 2775, + 2767, 2885, 2219, + 0, 3037, 0, + 0, 3183, 0, + 0, 3327, 0, + 0, 3467, 0, + 0, 3603, 0, + 0, 3741, 0, + 0, 3875, 0, + 0, 4011, 0, + 3599, 0, 3419, + 3599, 0, 3419, + 3599, 0, 3419, + 3599, 0, 3419, + 3599, 0, 3417, + 3599, 0, 3417, + 3599, 0, 3417, + 3597, 0, 3417, + 3597, 0, 3415, + 3595, 0, 3413, + 3593, 0, 3413, + 3591, 0, 3409, + 3589, 0, 3407, + 3585, 0, 3403, + 3581, 0, 3397, + 3573, 0, 3389, + 3563, 0, 3377, + 3551, 0, 3361, + 3533, 1357, 3341, + 3507, 1949, 3311, + 3471, 2259, 3267, + 3419, 2489, 3203, + 3337, 2683, 3099, + 3197, 2855, 2905, + 2899, 3017, 2347, + 0, 3169, 0, + 0, 3315, 0, + 0, 3459, 0, + 0, 3599, 0, + 0, 3737, 0, + 0, 3873, 0, + 0, 4007, 0, + 3731, 0, 3551, + 3731, 0, 3551, + 3731, 0, 3551, + 3731, 0, 3551, + 3731, 0, 3551, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3729, 0, 3549, + 3729, 0, 3547, + 3727, 0, 3545, + 3727, 0, 3543, + 3723, 0, 3541, + 3721, 0, 3539, + 3717, 0, 3533, + 3713, 0, 3527, + 3705, 0, 3519, + 3695, 0, 3509, + 3683, 0, 3493, + 3665, 1485, 3473, + 3639, 2081, 3443, + 3603, 2391, 3399, + 3551, 2621, 3335, + 3469, 2815, 3229, + 3329, 2987, 3037, + 3031, 3149, 2477, + 0, 3301, 0, + 0, 3447, 0, + 0, 3591, 0, + 0, 3731, 0, + 0, 3869, 0, + 0, 4005, 0, + 3865, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3861, 0, 3679, + 3861, 0, 3679, + 3859, 0, 3677, + 3859, 0, 3675, + 3855, 0, 3673, + 3853, 0, 3671, + 3849, 0, 3665, + 3845, 0, 3659, + 3837, 0, 3651, + 3827, 0, 3641, + 3815, 0, 3625, + 3797, 1614, 3605, + 3771, 2211, 3575, + 3735, 2521, 3531, + 3683, 2753, 3467, + 3601, 2947, 3361, + 3461, 3119, 3169, + 3161, 3281, 2607, + 0, 3433, 0, + 0, 3579, 0, + 0, 3723, 0, + 0, 3863, 0, + 0, 4001, 0, + 3997, 0, 3815, + 3997, 0, 3815, + 3997, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3813, + 3995, 0, 3813, + 3995, 0, 3813, + 3995, 0, 3813, + 3993, 0, 3811, + 3993, 0, 3811, + 3991, 0, 3809, + 3991, 0, 3807, + 3989, 0, 3805, + 3985, 0, 3803, + 3981, 0, 3797, + 3977, 0, 3791, + 3969, 0, 3783, + 3959, 0, 3773, + 3947, 0, 3757, + 3929, 1744, 3737, + 3903, 2343, 3707, + 3867, 2653, 3663, + 3815, 2885, 3599, + 3733, 3079, 3493, + 3593, 3251, 3299, + 3293, 3413, 2737, + 0, 3565, 0, + 0, 3711, 0, + 0, 3855, 0, + 0, 3995, 0, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3943, + 4095, 0, 3943, + 4095, 0, 3941, + 4095, 0, 3939, + 4095, 0, 3937, + 4095, 0, 3935, + 4095, 0, 3929, + 4095, 0, 3923, + 4095, 0, 3915, + 4093, 0, 3905, + 4079, 0, 3889, + 4061, 1874, 3869, + 4037, 2475, 3839, + 4001, 2785, 3795, + 3947, 3017, 3731, + 3865, 3211, 3625, + 3725, 3385, 3431, + 3425, 3545, 2867, + 0, 3697, 0, + 0, 3843, 0, + 0, 3987, 0, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4075, + 4095, 0, 4075, + 4095, 0, 4073, + 4095, 0, 4071, + 4095, 0, 4069, + 4095, 0, 4067, + 4095, 0, 4061, + 4095, 0, 4055, + 4095, 0, 4047, + 4095, 0, 4037, + 4095, 0, 4021, + 4095, 2005, 4001, + 4095, 2607, 3971, + 4095, 2917, 3927, + 4079, 3149, 3863, + 3997, 3343, 3757, + 3857, 3517, 3563, + 3557, 3677, 2999, + 0, 3829, 0, + 0, 3977, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2135, 4095, + 4095, 2739, 4095, + 4095, 3049, 4059, + 4095, 3281, 3995, + 4095, 3475, 3889, + 3989, 3649, 3695, + 3689, 3809, 3129, + 0, 3961, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2267, 4095, + 4095, 2871, 4095, + 4095, 3181, 4095, + 4095, 3413, 4095, + 4095, 3607, 4021, + 4095, 3781, 3827, + 3821, 3941, 3261, + 532, 243, 872, + 424, 313, 835, + 222, 392, 781, + 0, 480, 697, + 0, 576, 552, + 0, 680, 237, + 0, 789, 0, + 0, 903, 0, + 0, 1022, 0, + 0, 1143, 0, + 0, 1267, 0, + 0, 1393, 0, + 0, 1520, 0, + 0, 1649, 0, + 0, 1779, 0, + 0, 1909, 0, + 0, 2039, 0, + 0, 2171, 0, + 0, 2301, 0, + 0, 2433, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 640, 231, 909, + 557, 303, 875, + 416, 384, 826, + 111, 473, 750, + 0, 571, 625, + 0, 675, 372, + 0, 786, 0, + 0, 901, 0, + 0, 1020, 0, + 0, 1141, 0, + 0, 1266, 0, + 0, 1392, 0, + 0, 1520, 0, + 0, 1649, 0, + 0, 1778, 0, + 0, 1908, 0, + 0, 2039, 0, + 0, 2171, 0, + 0, 2301, 0, + 0, 2433, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 754, 215, 955, + 690, 289, 924, + 589, 372, 880, + 404, 464, 814, + 0, 563, 706, + 0, 669, 506, + 0, 781, 0, + 0, 897, 0, + 0, 1017, 0, + 0, 1139, 0, + 0, 1264, 0, + 0, 1391, 0, + 0, 1519, 0, + 0, 1648, 0, + 0, 1778, 0, + 0, 1908, 0, + 0, 2039, 0, + 0, 2169, 0, + 0, 2301, 0, + 0, 2433, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 871, 192, 1009, + 823, 270, 982, + 750, 356, 944, + 628, 451, 886, + 389, 553, 796, + 0, 661, 639, + 0, 774, 273, + 0, 892, 0, + 0, 1013, 0, + 0, 1136, 0, + 0, 1262, 0, + 0, 1389, 0, + 0, 1518, 0, + 0, 1647, 0, + 0, 1777, 0, + 0, 1908, 0, + 0, 2038, 0, + 0, 2169, 0, + 0, 2301, 0, + 0, 2433, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 992, 160, 1073, + 956, 243, 1049, + 902, 334, 1017, + 819, 433, 968, + 676, 539, 895, + 367, 650, 772, + 0, 766, 531, + 0, 885, 0, + 0, 1008, 0, + 0, 1132, 0, + 0, 1259, 0, + 0, 1387, 0, + 0, 1516, 0, + 0, 1646, 0, + 0, 1776, 0, + 0, 1907, 0, + 0, 2038, 0, + 0, 2169, 0, + 0, 2301, 0, + 0, 2433, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1116, 113, 1146, + 1088, 204, 1126, + 1049, 302, 1099, + 990, 408, 1059, + 897, 519, 1000, + 733, 634, 905, + 337, 754, 738, + 0, 876, 328, + 0, 1001, 0, + 0, 1127, 0, + 0, 1255, 0, + 0, 1384, 0, + 0, 1514, 0, + 0, 1644, 0, + 0, 1775, 0, + 0, 1906, 0, + 0, 2037, 0, + 0, 2169, 0, + 0, 2301, 0, + 0, 2433, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1241, 42, 1229, + 1221, 146, 1212, + 1191, 257, 1190, + 1149, 372, 1157, + 1086, 491, 1110, + 985, 613, 1038, + 799, 737, 919, + 293, 864, 688, + 0, 991, 0, + 0, 1120, 0, + 0, 1250, 0, + 0, 1380, 0, + 0, 1511, 0, + 0, 1642, 0, + 0, 1773, 0, + 0, 1905, 0, + 0, 2036, 0, + 0, 2169, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1368, 0, 1320, + 1353, 56, 1307, + 1331, 187, 1288, + 1301, 319, 1262, + 1256, 451, 1225, + 1189, 582, 1170, + 1080, 714, 1085, + 875, 846, 937, + 226, 978, 610, + 0, 1110, 0, + 0, 1242, 0, + 0, 1374, 0, + 0, 1507, 0, + 0, 1639, 0, + 0, 1771, 0, + 0, 1903, 0, + 0, 2035, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1497, 0, 1419, + 1485, 0, 1408, + 1469, 74, 1394, + 1447, 237, 1373, + 1415, 391, 1345, + 1369, 538, 1303, + 1298, 682, 1240, + 1183, 822, 1141, + 960, 960, 960, + 118, 1097, 481, + 0, 1232, 0, + 0, 1367, 0, + 0, 1501, 0, + 0, 1634, 0, + 0, 1768, 0, + 0, 1901, 0, + 0, 2033, 0, + 0, 2165, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1626, 0, 1525, + 1617, 0, 1516, + 1606, 0, 1505, + 1589, 97, 1489, + 1566, 296, 1467, + 1533, 472, 1435, + 1485, 634, 1389, + 1412, 788, 1320, + 1291, 935, 1206, + 1054, 1078, 990, + 0, 1219, 216, + 0, 1357, 0, + 0, 1493, 0, + 0, 1629, 0, + 0, 1763, 0, + 0, 1897, 0, + 0, 2031, 0, + 0, 2165, 0, + 0, 2297, 0, + 0, 2429, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1756, 0, 1636, + 1750, 0, 1630, + 1741, 0, 1621, + 1729, 0, 1608, + 1712, 126, 1591, + 1688, 364, 1568, + 1655, 562, 1534, + 1606, 737, 1484, + 1530, 899, 1408, + 1405, 1052, 1281, + 1155, 1200, 1026, + 0, 1343, 0, + 0, 1483, 0, + 0, 1621, 0, + 0, 1758, 0, + 0, 1893, 0, + 0, 2028, 0, + 0, 2161, 0, + 0, 2295, 0, + 0, 2429, 0, + 0, 2561, 0, + 0, 2693, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1887, 0, 1752, + 1882, 0, 1747, + 1875, 0, 1740, + 1866, 0, 1731, + 1854, 0, 1718, + 1837, 163, 1700, + 1813, 442, 1675, + 1779, 659, 1639, + 1729, 846, 1586, + 1652, 1015, 1505, + 1523, 1173, 1366, + 1262, 1324, 1070, + 0, 1469, 0, + 0, 1611, 0, + 0, 1750, 0, + 0, 1888, 0, + 0, 2024, 0, + 0, 2159, 0, + 0, 2293, 0, + 0, 2427, 0, + 0, 2559, 0, + 0, 2693, 0, + 0, 2825, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2018, 0, 1872, + 2014, 0, 1868, + 2009, 0, 1862, + 2002, 0, 1855, + 1993, 0, 1845, + 1981, 0, 1832, + 1963, 207, 1813, + 1939, 529, 1787, + 1905, 764, 1750, + 1854, 960, 1695, + 1776, 1135, 1608, + 1644, 1297, 1458, + 1374, 1450, 1123, + 0, 1597, 0, + 0, 1740, 0, + 0, 1880, 0, + 0, 2018, 0, + 0, 2155, 0, + 0, 2289, 0, + 0, 2425, 0, + 0, 2559, 0, + 0, 2691, 0, + 0, 2825, 0, + 0, 2957, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2149, 0, 1994, + 2147, 0, 1991, + 2143, 0, 1987, + 2137, 0, 1982, + 2131, 0, 1974, + 2121, 0, 1964, + 2109, 0, 1950, + 2091, 260, 1931, + 2067, 624, 1904, + 2032, 874, 1866, + 1981, 1078, 1808, + 1902, 1258, 1717, + 1768, 1422, 1559, + 1491, 1577, 1186, + 0, 1725, 0, + 0, 1869, 0, + 0, 2010, 0, + 0, 2149, 0, + 0, 2285, 0, + 0, 2421, 0, + 0, 2555, 0, + 0, 2689, 0, + 0, 2823, 0, + 0, 2957, 0, + 0, 3089, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2281, 0, 2119, + 2279, 0, 2117, + 2275, 0, 2113, + 2271, 0, 2109, + 2267, 0, 2105, + 2261, 0, 2097, + 2251, 0, 2087, + 2239, 0, 2073, + 2221, 323, 2053, + 2195, 726, 2025, + 2161, 989, 1985, + 2109, 1200, 1926, + 2029, 1382, 1832, + 1894, 1549, 1665, + 1612, 1706, 1258, + 0, 1855, 0, + 0, 2000, 0, + 0, 2141, 0, + 0, 2279, 0, + 0, 2417, 0, + 0, 2553, 0, + 0, 2687, 0, + 0, 2821, 0, + 0, 2955, 0, + 0, 3089, 0, + 0, 3221, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3885, 0, + 0, 4017, 0, + 2413, 0, 2245, + 2411, 0, 2243, + 2409, 0, 2241, + 2405, 0, 2239, + 2401, 0, 2235, + 2397, 0, 2229, + 2391, 0, 2221, + 2381, 0, 2211, + 2367, 0, 2197, + 2351, 396, 2177, + 2325, 834, 2147, + 2291, 1108, 2107, + 2239, 1323, 2047, + 2157, 1509, 1950, + 2021, 1678, 1777, + 1735, 1835, 1340, + 0, 1985, 0, + 0, 2131, 0, + 0, 2273, 0, + 0, 2411, 0, + 0, 2549, 0, + 0, 2685, 0, + 0, 2819, 0, + 0, 2953, 0, + 0, 3087, 0, + 0, 3221, 0, + 0, 3353, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4017, 0, + 2543, 0, 2373, + 2543, 0, 2373, + 2541, 0, 2371, + 2539, 0, 2369, + 2537, 0, 2365, + 2533, 0, 2361, + 2527, 0, 2355, + 2521, 0, 2347, + 2511, 0, 2337, + 2499, 0, 2323, + 2481, 477, 2301, + 2455, 948, 2273, + 2421, 1230, 2231, + 2369, 1449, 2171, + 2287, 1637, 2071, + 2149, 1807, 1894, + 1860, 1965, 1430, + 0, 2115, 0, + 0, 2261, 0, + 0, 2403, 0, + 0, 2543, 0, + 0, 2681, 0, + 0, 2817, 0, + 0, 2951, 0, + 0, 3085, 0, + 0, 3219, 0, + 0, 3353, 0, + 0, 3485, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4017, 0, + 2675, 0, 2503, + 2675, 0, 2501, + 2673, 0, 2501, + 2673, 0, 2499, + 2671, 0, 2497, + 2667, 0, 2493, + 2663, 0, 2489, + 2659, 0, 2483, + 2651, 0, 2475, + 2643, 0, 2465, + 2629, 0, 2449, + 2611, 568, 2429, + 2587, 1065, 2401, + 2551, 1355, 2359, + 2499, 1577, 2295, + 2417, 1766, 2195, + 2279, 1937, 2014, + 1987, 2095, 1528, + 0, 2247, 0, + 0, 2393, 0, + 0, 2535, 0, + 0, 2675, 0, + 0, 2813, 0, + 0, 2949, 0, + 0, 3083, 0, + 0, 3217, 0, + 0, 3351, 0, + 0, 3485, 0, + 0, 3617, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 2807, 0, 2633, + 2807, 0, 2631, + 2807, 0, 2631, + 2805, 0, 2629, + 2803, 0, 2627, + 2801, 0, 2625, + 2799, 0, 2621, + 2795, 0, 2617, + 2789, 0, 2611, + 2783, 0, 2603, + 2773, 0, 2593, + 2761, 0, 2579, + 2743, 666, 2557, + 2717, 1186, 2529, + 2681, 1481, 2487, + 2629, 1705, 2423, + 2547, 1896, 2321, + 2409, 2067, 2137, + 2115, 2227, 1633, + 0, 2379, 0, + 0, 2525, 0, + 0, 2667, 0, + 0, 2807, 0, + 0, 2943, 0, + 0, 3081, 0, + 0, 3215, 0, + 0, 3349, 0, + 0, 3483, 0, + 0, 3617, 0, + 0, 3749, 0, + 0, 3883, 0, + 0, 4015, 0, + 2939, 0, 2763, + 2939, 0, 2763, + 2939, 0, 2761, + 2937, 0, 2761, + 2937, 0, 2759, + 2935, 0, 2757, + 2933, 0, 2755, + 2931, 0, 2751, + 2927, 0, 2747, + 2921, 0, 2741, + 2915, 0, 2733, + 2905, 0, 2723, + 2891, 0, 2707, + 2875, 771, 2687, + 2849, 1310, 2657, + 2813, 1609, 2615, + 2761, 1835, 2551, + 2679, 2026, 2449, + 2541, 2199, 2263, + 2245, 2359, 1744, + 0, 2509, 0, + 0, 2657, 0, + 0, 2799, 0, + 0, 2939, 0, + 0, 3075, 0, + 0, 3213, 0, + 0, 3347, 0, + 0, 3481, 0, + 0, 3615, 0, + 0, 3749, 0, + 0, 3881, 0, + 0, 4015, 0, + 3071, 0, 2893, + 3071, 0, 2893, + 3071, 0, 2893, + 3071, 0, 2891, + 3069, 0, 2891, + 3069, 0, 2889, + 3067, 0, 2887, + 3065, 0, 2885, + 3061, 0, 2881, + 3057, 0, 2877, + 3053, 0, 2871, + 3045, 0, 2863, + 3037, 0, 2853, + 3023, 0, 2837, + 3005, 882, 2817, + 2981, 1436, 2787, + 2945, 1738, 2745, + 2891, 1965, 2681, + 2811, 2157, 2577, + 2671, 2329, 2389, + 2375, 2489, 1860, + 0, 2641, 0, + 0, 2787, 0, + 0, 2931, 0, + 0, 3071, 0, + 0, 3207, 0, + 0, 3345, 0, + 0, 3479, 0, + 0, 3613, 0, + 0, 3747, 0, + 0, 3881, 0, + 0, 4015, 0, + 3203, 0, 3025, + 3203, 0, 3025, + 3203, 0, 3023, + 3203, 0, 3023, + 3201, 0, 3023, + 3201, 0, 3021, + 3199, 0, 3021, + 3199, 0, 3019, + 3197, 0, 3015, + 3193, 0, 3013, + 3189, 0, 3009, + 3185, 0, 3003, + 3177, 0, 2995, + 3169, 0, 2983, + 3155, 0, 2969, + 3137, 997, 2947, + 3113, 1563, 2919, + 3077, 1867, 2875, + 3023, 2095, 2811, + 2941, 2289, 2707, + 2803, 2461, 2517, + 2505, 2621, 1979, + 0, 2773, 0, + 0, 2919, 0, + 0, 3063, 0, + 0, 3203, 0, + 0, 3339, 0, + 0, 3477, 0, + 0, 3611, 0, + 0, 3745, 0, + 0, 3879, 0, + 0, 4013, 0, + 3335, 0, 3155, + 3335, 0, 3155, + 3335, 0, 3155, + 3335, 0, 3155, + 3335, 0, 3155, + 3333, 0, 3153, + 3333, 0, 3153, + 3331, 0, 3151, + 3331, 0, 3149, + 3329, 0, 3147, + 3325, 0, 3143, + 3321, 0, 3139, + 3317, 0, 3133, + 3309, 0, 3125, + 3301, 0, 3115, + 3287, 0, 3099, + 3269, 1116, 3079, + 3245, 1692, 3049, + 3209, 1997, 3007, + 3155, 2227, 2941, + 3073, 2419, 2837, + 2933, 2593, 2647, + 2637, 2753, 2101, + 0, 2905, 0, + 0, 3051, 0, + 0, 3195, 0, + 0, 3335, 0, + 0, 3471, 0, + 0, 3609, 0, + 0, 3743, 0, + 0, 3877, 0, + 0, 4011, 0, + 3467, 0, 3287, + 3467, 0, 3287, + 3467, 0, 3287, + 3467, 0, 3287, + 3467, 0, 3287, + 3467, 0, 3285, + 3465, 0, 3285, + 3465, 0, 3285, + 3463, 0, 3283, + 3463, 0, 3281, + 3461, 0, 3279, + 3457, 0, 3275, + 3453, 0, 3271, + 3449, 0, 3265, + 3441, 0, 3257, + 3431, 0, 3245, + 3419, 0, 3231, + 3401, 1238, 3209, + 3375, 1821, 3181, + 3341, 2129, 3137, + 3287, 2357, 3073, + 3205, 2551, 2969, + 3065, 2725, 2777, + 2767, 2885, 2225, + 0, 3037, 0, + 0, 3183, 0, + 0, 3327, 0, + 0, 3467, 0, + 0, 3605, 0, + 0, 3741, 0, + 0, 3875, 0, + 0, 4011, 0, + 3599, 0, 3419, + 3599, 0, 3419, + 3599, 0, 3419, + 3599, 0, 3419, + 3599, 0, 3419, + 3599, 0, 3417, + 3599, 0, 3417, + 3597, 0, 3417, + 3597, 0, 3415, + 3595, 0, 3415, + 3595, 0, 3413, + 3591, 0, 3411, + 3589, 0, 3407, + 3585, 0, 3403, + 3581, 0, 3397, + 3573, 0, 3389, + 3563, 0, 3377, + 3551, 0, 3363, + 3533, 1363, 3341, + 3507, 1951, 3311, + 3471, 2259, 3269, + 3419, 2489, 3203, + 3337, 2683, 3099, + 3197, 2857, 2907, + 2899, 3017, 2351, + 0, 3169, 0, + 0, 3315, 0, + 0, 3459, 0, + 0, 3599, 0, + 0, 3737, 0, + 0, 3873, 0, + 0, 4007, 0, + 3733, 0, 3551, + 3731, 0, 3551, + 3731, 0, 3551, + 3731, 0, 3551, + 3731, 0, 3551, + 3731, 0, 3551, + 3731, 0, 3549, + 3731, 0, 3549, + 3729, 0, 3549, + 3729, 0, 3547, + 3727, 0, 3545, + 3727, 0, 3545, + 3725, 0, 3541, + 3721, 0, 3539, + 3717, 0, 3535, + 3713, 0, 3529, + 3705, 0, 3521, + 3695, 0, 3509, + 3683, 0, 3495, + 3665, 1489, 3473, + 3639, 2081, 3443, + 3603, 2391, 3401, + 3551, 2621, 3335, + 3469, 2815, 3231, + 3329, 2989, 3037, + 3031, 3149, 2479, + 0, 3301, 0, + 0, 3447, 0, + 0, 3591, 0, + 0, 3731, 0, + 0, 3869, 0, + 0, 4005, 0, + 3865, 0, 3683, + 3865, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3861, 0, 3681, + 3861, 0, 3679, + 3859, 0, 3677, + 3859, 0, 3677, + 3857, 0, 3673, + 3853, 0, 3671, + 3849, 0, 3665, + 3845, 0, 3661, + 3837, 0, 3651, + 3827, 0, 3641, + 3815, 0, 3625, + 3797, 1617, 3605, + 3771, 2213, 3575, + 3735, 2523, 3531, + 3683, 2753, 3467, + 3601, 2947, 3363, + 3461, 3121, 3169, + 3163, 3281, 2609, + 0, 3433, 0, + 0, 3579, 0, + 0, 3723, 0, + 0, 3863, 0, + 0, 4001, 0, + 3997, 0, 3815, + 3997, 0, 3815, + 3997, 0, 3815, + 3997, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3813, + 3995, 0, 3813, + 3995, 0, 3813, + 3993, 0, 3813, + 3993, 0, 3811, + 3991, 0, 3809, + 3991, 0, 3807, + 3989, 0, 3805, + 3985, 0, 3803, + 3981, 0, 3797, + 3977, 0, 3791, + 3969, 0, 3783, + 3959, 0, 3773, + 3947, 0, 3757, + 3929, 1746, 3737, + 3903, 2343, 3707, + 3869, 2653, 3663, + 3815, 2885, 3599, + 3733, 3079, 3493, + 3593, 3253, 3301, + 3295, 3413, 2739, + 0, 3565, 0, + 0, 3711, 0, + 0, 3855, 0, + 0, 3995, 0, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3943, + 4095, 0, 3941, + 4095, 0, 3939, + 4095, 0, 3937, + 4095, 0, 3935, + 4095, 0, 3929, + 4095, 0, 3923, + 4095, 0, 3915, + 4093, 0, 3905, + 4079, 0, 3889, + 4061, 1876, 3869, + 4037, 2475, 3839, + 4001, 2785, 3795, + 3947, 3017, 3731, + 3865, 3211, 3625, + 3725, 3385, 3431, + 3425, 3545, 2869, + 0, 3697, 0, + 0, 3845, 0, + 0, 3987, 0, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4075, + 4095, 0, 4073, + 4095, 0, 4071, + 4095, 0, 4069, + 4095, 0, 4067, + 4095, 0, 4061, + 4095, 0, 4055, + 4095, 0, 4047, + 4095, 0, 4037, + 4095, 0, 4021, + 4095, 2006, 4001, + 4095, 2607, 3971, + 4095, 2917, 3927, + 4079, 3149, 3863, + 3997, 3343, 3757, + 3857, 3517, 3563, + 3557, 3677, 2999, + 0, 3829, 0, + 0, 3977, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2137, 4095, + 4095, 2739, 4095, + 4095, 3049, 4059, + 4095, 3281, 3995, + 4095, 3475, 3889, + 3989, 3649, 3695, + 3689, 3809, 3131, + 0, 3961, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2267, 4095, + 4095, 2871, 4095, + 4095, 3181, 4095, + 4095, 3413, 4095, + 4095, 3607, 4021, + 4095, 3781, 3827, + 3821, 3941, 3261, + 644, 324, 1001, + 562, 383, 974, + 422, 452, 935, + 123, 530, 876, + 0, 617, 784, + 0, 713, 622, + 0, 815, 233, + 0, 924, 0, + 0, 1037, 0, + 0, 1155, 0, + 0, 1276, 0, + 0, 1400, 0, + 0, 1526, 0, + 0, 1653, 0, + 0, 1782, 0, + 0, 1911, 0, + 0, 2041, 0, + 0, 2171, 0, + 0, 2303, 0, + 0, 2433, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 731, 315, 1029, + 664, 375, 1004, + 556, 445, 967, + 354, 524, 913, + 0, 612, 829, + 0, 708, 684, + 0, 812, 369, + 0, 921, 0, + 0, 1035, 0, + 0, 1154, 0, + 0, 1275, 0, + 0, 1399, 0, + 0, 1525, 0, + 0, 1653, 0, + 0, 1781, 0, + 0, 1911, 0, + 0, 2041, 0, + 0, 2171, 0, + 0, 2303, 0, + 0, 2433, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 826, 301, 1065, + 772, 363, 1041, + 689, 435, 1008, + 548, 516, 958, + 243, 605, 883, + 0, 703, 757, + 0, 807, 504, + 0, 918, 0, + 0, 1033, 0, + 0, 1151, 0, + 0, 1273, 0, + 0, 1398, 0, + 0, 1524, 0, + 0, 1652, 0, + 0, 1781, 0, + 0, 1910, 0, + 0, 2041, 0, + 0, 2171, 0, + 0, 2303, 0, + 0, 2433, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 928, 282, 1108, + 886, 347, 1086, + 822, 421, 1056, + 721, 504, 1012, + 536, 596, 946, + 32, 695, 838, + 0, 801, 638, + 0, 913, 23, + 0, 1029, 0, + 0, 1149, 0, + 0, 1271, 0, + 0, 1396, 0, + 0, 1523, 0, + 0, 1651, 0, + 0, 1780, 0, + 0, 1910, 0, + 0, 2040, 0, + 0, 2171, 0, + 0, 2303, 0, + 0, 2433, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1036, 256, 1160, + 1003, 324, 1141, + 955, 402, 1114, + 882, 488, 1075, + 760, 583, 1018, + 521, 685, 929, + 0, 793, 771, + 0, 907, 406, + 0, 1024, 0, + 0, 1145, 0, + 0, 1268, 0, + 0, 1394, 0, + 0, 1521, 0, + 0, 1650, 0, + 0, 1779, 0, + 0, 1909, 0, + 0, 2040, 0, + 0, 2171, 0, + 0, 2301, 0, + 0, 2433, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1150, 219, 1221, + 1124, 292, 1205, + 1088, 375, 1182, + 1034, 466, 1149, + 951, 565, 1100, + 808, 671, 1026, + 500, 782, 905, + 0, 898, 663, + 0, 1017, 0, + 0, 1140, 0, + 0, 1265, 0, + 0, 1391, 0, + 0, 1519, 0, + 0, 1648, 0, + 0, 1778, 0, + 0, 1908, 0, + 0, 2039, 0, + 0, 2171, 0, + 0, 2301, 0, + 0, 2433, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1267, 163, 1292, + 1248, 245, 1278, + 1220, 336, 1259, + 1181, 435, 1231, + 1122, 540, 1191, + 1029, 651, 1131, + 865, 767, 1037, + 469, 886, 870, + 0, 1008, 460, + 0, 1133, 0, + 0, 1259, 0, + 0, 1387, 0, + 0, 1516, 0, + 0, 1646, 0, + 0, 1776, 0, + 0, 1907, 0, + 0, 2038, 0, + 0, 2169, 0, + 0, 2301, 0, + 0, 2433, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1388, 76, 1373, + 1373, 174, 1361, + 1353, 278, 1345, + 1324, 389, 1322, + 1281, 504, 1289, + 1218, 623, 1242, + 1116, 745, 1170, + 932, 870, 1051, + 425, 996, 820, + 0, 1123, 0, + 0, 1252, 0, + 0, 1382, 0, + 0, 1512, 0, + 0, 1643, 0, + 0, 1774, 0, + 0, 1905, 0, + 0, 2037, 0, + 0, 2169, 0, + 0, 2301, 0, + 0, 2433, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1512, 0, 1462, + 1501, 57, 1452, + 1485, 188, 1439, + 1463, 319, 1420, + 1433, 451, 1395, + 1388, 583, 1357, + 1321, 715, 1303, + 1212, 847, 1217, + 1008, 979, 1069, + 358, 1110, 742, + 0, 1242, 0, + 0, 1374, 0, + 0, 1507, 0, + 0, 1639, 0, + 0, 1771, 0, + 0, 1903, 0, + 0, 2035, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1638, 0, 1559, + 1629, 0, 1551, + 1617, 29, 1541, + 1601, 206, 1526, + 1579, 369, 1505, + 1547, 523, 1477, + 1501, 670, 1435, + 1430, 814, 1373, + 1315, 954, 1273, + 1092, 1092, 1092, + 250, 1229, 613, + 0, 1364, 0, + 0, 1499, 0, + 0, 1633, 0, + 0, 1767, 0, + 0, 1900, 0, + 0, 2033, 0, + 0, 2165, 0, + 0, 2297, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1765, 0, 1663, + 1758, 0, 1657, + 1750, 0, 1649, + 1738, 0, 1637, + 1721, 229, 1621, + 1698, 428, 1599, + 1665, 604, 1567, + 1617, 766, 1522, + 1544, 920, 1452, + 1423, 1067, 1338, + 1186, 1211, 1122, + 47, 1351, 348, + 0, 1489, 0, + 0, 1626, 0, + 0, 1761, 0, + 0, 1896, 0, + 0, 2030, 0, + 0, 2163, 0, + 0, 2297, 0, + 0, 2429, 0, + 0, 2561, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1893, 0, 1773, + 1888, 0, 1768, + 1882, 0, 1762, + 1873, 0, 1753, + 1861, 0, 1740, + 1844, 258, 1723, + 1820, 496, 1700, + 1787, 694, 1666, + 1738, 869, 1616, + 1662, 1031, 1540, + 1537, 1185, 1414, + 1287, 1332, 1158, + 0, 1475, 0, + 0, 1615, 0, + 0, 1753, 0, + 0, 1890, 0, + 0, 2025, 0, + 0, 2159, 0, + 0, 2293, 0, + 0, 2427, 0, + 0, 2561, 0, + 0, 2693, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2023, 0, 1888, + 2019, 0, 1884, + 2014, 0, 1879, + 2007, 0, 1872, + 1998, 0, 1863, + 1986, 0, 1850, + 1969, 295, 1832, + 1945, 574, 1807, + 1911, 791, 1771, + 1861, 978, 1718, + 1784, 1147, 1637, + 1655, 1305, 1498, + 1394, 1456, 1202, + 0, 1601, 0, + 0, 1743, 0, + 0, 1882, 0, + 0, 2020, 0, + 0, 2155, 0, + 0, 2291, 0, + 0, 2425, 0, + 0, 2559, 0, + 0, 2693, 0, + 0, 2825, 0, + 0, 2957, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2153, 0, 2007, + 2149, 0, 2004, + 2147, 0, 2000, + 2141, 0, 1995, + 2135, 0, 1987, + 2125, 0, 1978, + 2113, 0, 1964, + 2095, 339, 1946, + 2071, 661, 1920, + 2037, 896, 1882, + 1986, 1092, 1827, + 1908, 1267, 1740, + 1777, 1429, 1590, + 1507, 1582, 1256, + 0, 1729, 0, + 0, 1872, 0, + 0, 2012, 0, + 0, 2151, 0, + 0, 2287, 0, + 0, 2421, 0, + 0, 2557, 0, + 0, 2691, 0, + 0, 2823, 0, + 0, 2957, 0, + 0, 3089, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2283, 0, 2129, + 2281, 0, 2127, + 2279, 0, 2123, + 2275, 0, 2119, + 2269, 0, 2113, + 2263, 0, 2107, + 2253, 0, 2097, + 2241, 0, 2083, + 2223, 393, 2063, + 2199, 756, 2036, + 2165, 1006, 1998, + 2113, 1210, 1940, + 2034, 1390, 1850, + 1900, 1554, 1691, + 1624, 1709, 1318, + 0, 1858, 0, + 0, 2002, 0, + 0, 2143, 0, + 0, 2281, 0, + 0, 2417, 0, + 0, 2553, 0, + 0, 2687, 0, + 0, 2823, 0, + 0, 2955, 0, + 0, 3089, 0, + 0, 3221, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3885, 0, + 0, 4017, 0, + 2415, 0, 2253, + 2413, 0, 2251, + 2411, 0, 2249, + 2407, 0, 2245, + 2405, 0, 2241, + 2399, 0, 2237, + 2393, 0, 2229, + 2383, 0, 2219, + 2371, 0, 2205, + 2353, 455, 2185, + 2329, 858, 2157, + 2293, 1121, 2117, + 2241, 1332, 2057, + 2161, 1515, 1964, + 2026, 1681, 1797, + 1744, 1838, 1391, + 0, 1987, 0, + 0, 2131, 0, + 0, 2273, 0, + 0, 2411, 0, + 0, 2549, 0, + 0, 2685, 0, + 0, 2819, 0, + 0, 2953, 0, + 0, 3087, 0, + 0, 3221, 0, + 0, 3353, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4017, 0, + 2545, 0, 2379, + 2545, 0, 2377, + 2543, 0, 2377, + 2541, 0, 2373, + 2537, 0, 2371, + 2535, 0, 2367, + 2529, 0, 2361, + 2523, 0, 2353, + 2513, 0, 2343, + 2501, 0, 2329, + 2483, 528, 2309, + 2457, 966, 2281, + 2423, 1240, 2239, + 2371, 1456, 2179, + 2289, 1641, 2083, + 2153, 1810, 1910, + 1867, 1967, 1472, + 0, 2117, 0, + 0, 2263, 0, + 0, 2405, 0, + 0, 2543, 0, + 0, 2681, 0, + 0, 2817, 0, + 0, 2951, 0, + 0, 3085, 0, + 0, 3219, 0, + 0, 3353, 0, + 0, 3485, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4017, 0, + 2677, 0, 2507, + 2675, 0, 2505, + 2675, 0, 2505, + 2673, 0, 2503, + 2671, 0, 2501, + 2669, 0, 2497, + 2665, 0, 2493, + 2659, 0, 2487, + 2653, 0, 2479, + 2643, 0, 2469, + 2631, 0, 2455, + 2613, 609, 2433, + 2587, 1080, 2405, + 2553, 1362, 2365, + 2501, 1582, 2303, + 2419, 1769, 2203, + 2283, 1939, 2026, + 1993, 2097, 1562, + 0, 2249, 0, + 0, 2393, 0, + 0, 2535, 0, + 0, 2675, 0, + 0, 2813, 0, + 0, 2949, 0, + 0, 3083, 0, + 0, 3217, 0, + 0, 3351, 0, + 0, 3485, 0, + 0, 3617, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 2809, 0, 2635, + 2807, 0, 2635, + 2807, 0, 2633, + 2805, 0, 2633, + 2805, 0, 2631, + 2803, 0, 2629, + 2799, 0, 2625, + 2795, 0, 2621, + 2791, 0, 2615, + 2783, 0, 2607, + 2775, 0, 2597, + 2761, 0, 2581, + 2743, 700, 2561, + 2719, 1198, 2533, + 2683, 1487, 2491, + 2631, 1709, 2427, + 2549, 1898, 2327, + 2411, 2069, 2147, + 2119, 2227, 1661, + 0, 2379, 0, + 0, 2525, 0, + 0, 2667, 0, + 0, 2807, 0, + 0, 2945, 0, + 0, 3081, 0, + 0, 3215, 0, + 0, 3349, 0, + 0, 3483, 0, + 0, 3617, 0, + 0, 3749, 0, + 0, 3883, 0, + 0, 4015, 0, + 2941, 0, 2765, + 2939, 0, 2765, + 2939, 0, 2763, + 2939, 0, 2763, + 2937, 0, 2761, + 2935, 0, 2759, + 2933, 0, 2757, + 2931, 0, 2755, + 2927, 0, 2749, + 2921, 0, 2743, + 2915, 0, 2737, + 2905, 0, 2725, + 2893, 0, 2711, + 2875, 798, 2689, + 2849, 1319, 2661, + 2815, 1613, 2619, + 2761, 1837, 2555, + 2681, 2028, 2453, + 2541, 2199, 2269, + 2247, 2359, 1766, + 0, 2511, 0, + 0, 2657, 0, + 0, 2799, 0, + 0, 2939, 0, + 0, 3077, 0, + 0, 3213, 0, + 0, 3347, 0, + 0, 3481, 0, + 0, 3615, 0, + 0, 3749, 0, + 0, 3881, 0, + 0, 4015, 0, + 3073, 0, 2895, + 3071, 0, 2895, + 3071, 0, 2895, + 3071, 0, 2893, + 3069, 0, 2893, + 3069, 0, 2891, + 3067, 0, 2889, + 3065, 0, 2887, + 3063, 0, 2883, + 3059, 0, 2879, + 3053, 0, 2873, + 3047, 0, 2865, + 3037, 0, 2855, + 3025, 0, 2839, + 3007, 903, 2819, + 2981, 1442, 2789, + 2945, 1741, 2747, + 2893, 1967, 2683, + 2811, 2159, 2581, + 2673, 2331, 2395, + 2377, 2491, 1876, + 0, 2641, 0, + 0, 2789, 0, + 0, 2931, 0, + 0, 3071, 0, + 0, 3207, 0, + 0, 3345, 0, + 0, 3479, 0, + 0, 3613, 0, + 0, 3747, 0, + 0, 3881, 0, + 0, 4015, 0, + 3205, 0, 3025, + 3203, 0, 3025, + 3203, 0, 3025, + 3203, 0, 3025, + 3203, 0, 3023, + 3201, 0, 3023, + 3201, 0, 3021, + 3199, 0, 3019, + 3197, 0, 3017, + 3193, 0, 3015, + 3191, 0, 3009, + 3185, 0, 3003, + 3177, 0, 2995, + 3169, 0, 2985, + 3155, 0, 2971, + 3137, 1014, 2949, + 3113, 1568, 2919, + 3077, 1870, 2877, + 3025, 2097, 2813, + 2943, 2289, 2711, + 2803, 2461, 2521, + 2507, 2621, 1992, + 0, 2773, 0, + 0, 2919, 0, + 0, 3063, 0, + 0, 3203, 0, + 0, 3339, 0, + 0, 3477, 0, + 0, 3611, 0, + 0, 3745, 0, + 0, 3879, 0, + 0, 4013, 0, + 3335, 0, 3157, + 3335, 0, 3157, + 3335, 0, 3157, + 3335, 0, 3155, + 3335, 0, 3155, + 3335, 0, 3155, + 3333, 0, 3153, + 3333, 0, 3153, + 3331, 0, 3151, + 3329, 0, 3149, + 3325, 0, 3145, + 3321, 0, 3141, + 3317, 0, 3135, + 3309, 0, 3127, + 3301, 0, 3115, + 3287, 0, 3101, + 3269, 1129, 3079, + 3245, 1695, 3051, + 3209, 1999, 3007, + 3155, 2227, 2943, + 3073, 2421, 2839, + 2935, 2593, 2649, + 2637, 2753, 2111, + 0, 2905, 0, + 0, 3051, 0, + 0, 3195, 0, + 0, 3335, 0, + 0, 3473, 0, + 0, 3609, 0, + 0, 3743, 0, + 0, 3877, 0, + 0, 4011, 0, + 3469, 0, 3289, + 3467, 0, 3289, + 3467, 0, 3287, + 3467, 0, 3287, + 3467, 0, 3287, + 3467, 0, 3287, + 3465, 0, 3285, + 3465, 0, 3285, + 3463, 0, 3283, + 3463, 0, 3281, + 3461, 0, 3279, + 3457, 0, 3277, + 3453, 0, 3271, + 3449, 0, 3265, + 3441, 0, 3257, + 3433, 0, 3247, + 3419, 0, 3231, + 3401, 1248, 3211, + 3377, 1824, 3181, + 3341, 2129, 3139, + 3287, 2359, 3073, + 3205, 2551, 2969, + 3065, 2725, 2779, + 2769, 2885, 2233, + 0, 3037, 0, + 0, 3183, 0, + 0, 3327, 0, + 0, 3467, 0, + 0, 3605, 0, + 0, 3741, 0, + 0, 3875, 0, + 0, 4011, 0, + 3601, 0, 3419, + 3599, 0, 3419, + 3599, 0, 3419, + 3599, 0, 3419, + 3599, 0, 3419, + 3599, 0, 3419, + 3599, 0, 3417, + 3597, 0, 3417, + 3597, 0, 3417, + 3595, 0, 3415, + 3595, 0, 3413, + 3593, 0, 3411, + 3589, 0, 3407, + 3585, 0, 3403, + 3581, 0, 3397, + 3573, 0, 3389, + 3565, 0, 3379, + 3551, 0, 3363, + 3533, 1371, 3341, + 3509, 1953, 3313, + 3473, 2261, 3269, + 3419, 2489, 3205, + 3337, 2683, 3101, + 3197, 2857, 2909, + 2899, 3017, 2357, + 0, 3169, 0, + 0, 3315, 0, + 0, 3459, 0, + 0, 3599, 0, + 0, 3737, 0, + 0, 3873, 0, + 0, 4007, 0, + 3733, 0, 3551, + 3733, 0, 3551, + 3731, 0, 3551, + 3731, 0, 3551, + 3731, 0, 3551, + 3731, 0, 3551, + 3731, 0, 3551, + 3731, 0, 3549, + 3729, 0, 3549, + 3729, 0, 3547, + 3727, 0, 3547, + 3727, 0, 3545, + 3725, 0, 3543, + 3721, 0, 3539, + 3717, 0, 3535, + 3713, 0, 3529, + 3705, 0, 3521, + 3697, 0, 3509, + 3683, 0, 3495, + 3665, 1495, 3473, + 3641, 2083, 3443, + 3605, 2391, 3401, + 3551, 2621, 3335, + 3469, 2815, 3231, + 3329, 2989, 3039, + 3031, 3149, 2485, + 0, 3301, 0, + 0, 3447, 0, + 0, 3591, 0, + 0, 3731, 0, + 0, 3869, 0, + 0, 4005, 0, + 3865, 0, 3683, + 3865, 0, 3683, + 3865, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3681, + 3863, 0, 3681, + 3861, 0, 3681, + 3861, 0, 3679, + 3859, 0, 3679, + 3859, 0, 3677, + 3857, 0, 3673, + 3853, 0, 3671, + 3849, 0, 3667, + 3845, 0, 3661, + 3837, 0, 3653, + 3829, 0, 3641, + 3815, 0, 3627, + 3797, 1622, 3605, + 3773, 2213, 3575, + 3737, 2523, 3533, + 3683, 2753, 3467, + 3601, 2947, 3363, + 3461, 3121, 3169, + 3163, 3281, 2611, + 0, 3433, 0, + 0, 3579, 0, + 0, 3723, 0, + 0, 3863, 0, + 0, 4001, 0, + 3997, 0, 3815, + 3997, 0, 3815, + 3997, 0, 3815, + 3997, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3813, + 3995, 0, 3813, + 3993, 0, 3813, + 3993, 0, 3811, + 3991, 0, 3809, + 3991, 0, 3809, + 3989, 0, 3805, + 3985, 0, 3803, + 3981, 0, 3799, + 3977, 0, 3793, + 3969, 0, 3785, + 3961, 0, 3773, + 3947, 0, 3757, + 3929, 1749, 3737, + 3905, 2345, 3707, + 3869, 2655, 3663, + 3815, 2885, 3599, + 3733, 3079, 3495, + 3593, 3253, 3301, + 3295, 3413, 2741, + 0, 3565, 0, + 0, 3711, 0, + 0, 3855, 0, + 0, 3995, 0, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3943, + 4095, 0, 3941, + 4095, 0, 3941, + 4095, 0, 3937, + 4095, 0, 3935, + 4095, 0, 3929, + 4095, 0, 3925, + 4095, 0, 3915, + 4093, 0, 3905, + 4079, 0, 3889, + 4061, 1878, 3869, + 4037, 2475, 3839, + 4001, 2785, 3795, + 3947, 3017, 3731, + 3865, 3211, 3625, + 3725, 3385, 3433, + 3427, 3545, 2871, + 0, 3697, 0, + 0, 3845, 0, + 0, 3987, 0, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4075, + 4095, 0, 4073, + 4095, 0, 4071, + 4095, 0, 4069, + 4095, 0, 4067, + 4095, 0, 4061, + 4095, 0, 4055, + 4095, 0, 4047, + 4095, 0, 4037, + 4095, 0, 4021, + 4095, 2008, 4001, + 4095, 2607, 3971, + 4095, 2917, 3927, + 4079, 3149, 3863, + 3997, 3343, 3757, + 3857, 3517, 3563, + 3559, 3677, 3001, + 0, 3829, 0, + 0, 3977, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2139, 4095, + 4095, 2739, 4095, + 4095, 3049, 4059, + 4095, 3281, 3995, + 4095, 3475, 3889, + 3989, 3649, 3695, + 3691, 3809, 3131, + 0, 3961, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2269, 4095, + 4095, 2871, 4095, + 4095, 3181, 4095, + 4095, 3413, 4095, + 4095, 3607, 4021, + 4095, 3781, 3827, + 3823, 3941, 3263, + 761, 415, 1131, + 699, 464, 1111, + 599, 522, 1082, + 420, 590, 1041, + 0, 667, 979, + 0, 753, 880, + 0, 848, 701, + 0, 950, 229, + 0, 1058, 0, + 0, 1171, 0, + 0, 1288, 0, + 0, 1409, 0, + 0, 1533, 0, + 0, 1658, 0, + 0, 1786, 0, + 0, 1914, 0, + 0, 2043, 0, + 0, 2173, 0, + 0, 2303, 0, + 0, 2435, 0, + 0, 2567, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 829, 407, 1153, + 776, 456, 1133, + 694, 515, 1106, + 554, 584, 1067, + 255, 662, 1008, + 0, 749, 916, + 0, 845, 754, + 0, 947, 365, + 0, 1056, 0, + 0, 1169, 0, + 0, 1287, 0, + 0, 1408, 0, + 0, 1532, 0, + 0, 1658, 0, + 0, 1785, 0, + 0, 1914, 0, + 0, 2043, 0, + 0, 2173, 0, + 0, 2303, 0, + 0, 2435, 0, + 0, 2567, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 907, 396, 1180, + 863, 447, 1161, + 796, 507, 1136, + 688, 577, 1099, + 486, 656, 1045, + 0, 744, 961, + 0, 841, 817, + 0, 944, 501, + 0, 1053, 0, + 0, 1167, 0, + 0, 1286, 0, + 0, 1407, 0, + 0, 1531, 0, + 0, 1657, 0, + 0, 1785, 0, + 0, 1913, 0, + 0, 2043, 0, + 0, 2173, 0, + 0, 2303, 0, + 0, 2435, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 994, 381, 1214, + 958, 433, 1197, + 904, 495, 1173, + 821, 567, 1139, + 680, 648, 1090, + 375, 737, 1015, + 0, 835, 889, + 0, 939, 636, + 0, 1050, 0, + 0, 1165, 0, + 0, 1284, 0, + 0, 1406, 0, + 0, 1530, 0, + 0, 1656, 0, + 0, 1784, 0, + 0, 1913, 0, + 0, 2042, 0, + 0, 2173, 0, + 0, 2303, 0, + 0, 2435, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1089, 360, 1255, + 1060, 415, 1240, + 1018, 479, 1219, + 955, 553, 1188, + 853, 636, 1144, + 669, 728, 1078, + 164, 827, 970, + 0, 933, 770, + 0, 1045, 155, + 0, 1161, 0, + 0, 1281, 0, + 0, 1403, 0, + 0, 1528, 0, + 0, 1655, 0, + 0, 1783, 0, + 0, 1912, 0, + 0, 2042, 0, + 0, 2173, 0, + 0, 2303, 0, + 0, 2435, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1191, 330, 1306, + 1168, 388, 1292, + 1135, 456, 1273, + 1087, 534, 1246, + 1014, 620, 1208, + 893, 715, 1150, + 653, 817, 1060, + 0, 925, 903, + 0, 1038, 538, + 0, 1156, 0, + 0, 1277, 0, + 0, 1401, 0, + 0, 1526, 0, + 0, 1653, 0, + 0, 1782, 0, + 0, 1911, 0, + 0, 2041, 0, + 0, 2171, 0, + 0, 2303, 0, + 0, 2433, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1300, 287, 1366, + 1282, 351, 1353, + 1256, 424, 1337, + 1220, 507, 1314, + 1166, 598, 1281, + 1083, 697, 1232, + 940, 803, 1159, + 632, 914, 1036, + 0, 1030, 795, + 0, 1149, 0, + 0, 1272, 0, + 0, 1397, 0, + 0, 1523, 0, + 0, 1651, 0, + 0, 1780, 0, + 0, 1910, 0, + 0, 2040, 0, + 0, 2171, 0, + 0, 2303, 0, + 0, 2433, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1413, 222, 1435, + 1399, 295, 1425, + 1380, 377, 1410, + 1352, 468, 1391, + 1313, 567, 1363, + 1254, 672, 1323, + 1161, 783, 1264, + 997, 899, 1169, + 601, 1018, 1002, + 0, 1140, 592, + 0, 1265, 0, + 0, 1391, 0, + 0, 1519, 0, + 0, 1648, 0, + 0, 1778, 0, + 0, 1908, 0, + 0, 2039, 0, + 0, 2171, 0, + 0, 2301, 0, + 0, 2433, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1531, 118, 1514, + 1520, 208, 1505, + 1505, 306, 1493, + 1485, 411, 1477, + 1456, 521, 1454, + 1413, 636, 1421, + 1350, 755, 1374, + 1249, 877, 1302, + 1063, 1002, 1183, + 557, 1128, 952, + 0, 1255, 0, + 0, 1384, 0, + 0, 1514, 0, + 0, 1644, 0, + 0, 1775, 0, + 0, 1906, 0, + 0, 2037, 0, + 0, 2169, 0, + 0, 2301, 0, + 0, 2433, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1652, 0, 1601, + 1644, 58, 1594, + 1633, 189, 1584, + 1617, 320, 1571, + 1596, 451, 1553, + 1565, 583, 1527, + 1520, 715, 1490, + 1453, 847, 1435, + 1344, 979, 1349, + 1139, 1110, 1201, + 490, 1242, 875, + 0, 1375, 0, + 0, 1507, 0, + 0, 1639, 0, + 0, 1771, 0, + 0, 1903, 0, + 0, 2035, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1776, 0, 1697, + 1770, 0, 1691, + 1761, 0, 1683, + 1749, 161, 1673, + 1733, 338, 1658, + 1711, 501, 1638, + 1679, 655, 1609, + 1633, 803, 1567, + 1562, 946, 1505, + 1447, 1086, 1405, + 1225, 1225, 1225, + 382, 1361, 745, + 0, 1497, 0, + 0, 1631, 0, + 0, 1765, 0, + 0, 1899, 0, + 0, 2032, 0, + 0, 2165, 0, + 0, 2297, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1902, 0, 1800, + 1897, 0, 1795, + 1890, 0, 1789, + 1882, 0, 1781, + 1870, 122, 1769, + 1853, 361, 1753, + 1830, 560, 1731, + 1797, 736, 1700, + 1750, 898, 1654, + 1676, 1052, 1584, + 1556, 1199, 1471, + 1318, 1343, 1254, + 179, 1483, 480, + 0, 1621, 0, + 0, 1758, 0, + 0, 1893, 0, + 0, 2028, 0, + 0, 2161, 0, + 0, 2295, 0, + 0, 2429, 0, + 0, 2561, 0, + 0, 2693, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2029, 0, 1909, + 2025, 0, 1905, + 2021, 0, 1900, + 2014, 0, 1894, + 2005, 0, 1885, + 1993, 63, 1873, + 1976, 390, 1856, + 1952, 628, 1832, + 1919, 826, 1798, + 1870, 1001, 1748, + 1795, 1163, 1672, + 1669, 1317, 1546, + 1419, 1464, 1290, + 0, 1607, 0, + 0, 1747, 0, + 0, 1886, 0, + 0, 2022, 0, + 0, 2157, 0, + 0, 2293, 0, + 0, 2425, 0, + 0, 2559, 0, + 0, 2693, 0, + 0, 2825, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2157, 0, 2023, + 2155, 0, 2020, + 2151, 0, 2016, + 2147, 0, 2011, + 2139, 0, 2004, + 2131, 0, 1995, + 2119, 0, 1982, + 2101, 427, 1964, + 2077, 706, 1939, + 2043, 924, 1903, + 1993, 1110, 1851, + 1916, 1279, 1769, + 1787, 1437, 1630, + 1526, 1588, 1334, + 0, 1733, 0, + 0, 1875, 0, + 0, 2014, 0, + 0, 2151, 0, + 0, 2287, 0, + 0, 2423, 0, + 0, 2557, 0, + 0, 2691, 0, + 0, 2825, 0, + 0, 2957, 0, + 0, 3089, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2287, 0, 2141, + 2285, 0, 2139, + 2283, 0, 2135, + 2279, 0, 2131, + 2273, 0, 2127, + 2267, 0, 2119, + 2257, 0, 2109, + 2245, 0, 2097, + 2227, 471, 2077, + 2203, 793, 2051, + 2169, 1028, 2014, + 2119, 1224, 1959, + 2040, 1399, 1872, + 1909, 1561, 1723, + 1639, 1714, 1388, + 0, 1861, 0, + 0, 2004, 0, + 0, 2145, 0, + 0, 2283, 0, + 0, 2419, 0, + 0, 2555, 0, + 0, 2689, 0, + 0, 2823, 0, + 0, 2955, 0, + 0, 3089, 0, + 0, 3221, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3885, 0, + 0, 4017, 0, + 2417, 0, 2263, + 2415, 0, 2261, + 2413, 0, 2259, + 2411, 0, 2255, + 2407, 0, 2251, + 2401, 0, 2245, + 2395, 0, 2239, + 2385, 0, 2229, + 2373, 0, 2215, + 2355, 525, 2195, + 2331, 888, 2169, + 2297, 1138, 2129, + 2245, 1342, 2073, + 2165, 1522, 1982, + 2033, 1686, 1823, + 1756, 1841, 1450, + 0, 1990, 0, + 0, 2133, 0, + 0, 2275, 0, + 0, 2413, 0, + 0, 2549, 0, + 0, 2685, 0, + 0, 2821, 0, + 0, 2955, 0, + 0, 3087, 0, + 0, 3221, 0, + 0, 3353, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4017, 0, + 2547, 0, 2387, + 2547, 0, 2385, + 2545, 0, 2383, + 2543, 0, 2381, + 2539, 0, 2377, + 2537, 0, 2373, + 2531, 0, 2369, + 2525, 0, 2361, + 2515, 0, 2351, + 2503, 0, 2337, + 2485, 587, 2317, + 2461, 990, 2289, + 2425, 1253, 2249, + 2373, 1464, 2189, + 2293, 1647, 2097, + 2159, 1813, 1930, + 1876, 1970, 1523, + 0, 2119, 0, + 0, 2263, 0, + 0, 2405, 0, + 0, 2545, 0, + 0, 2681, 0, + 0, 2817, 0, + 0, 2951, 0, + 0, 3085, 0, + 0, 3219, 0, + 0, 3353, 0, + 0, 3485, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4017, 0, + 2679, 0, 2513, + 2677, 0, 2511, + 2677, 0, 2509, + 2675, 0, 2509, + 2673, 0, 2505, + 2669, 0, 2503, + 2667, 0, 2499, + 2661, 0, 2493, + 2655, 0, 2485, + 2645, 0, 2475, + 2633, 0, 2461, + 2615, 660, 2441, + 2589, 1098, 2413, + 2555, 1372, 2371, + 2503, 1588, 2311, + 2421, 1773, 2215, + 2285, 1942, 2042, + 1999, 2099, 1604, + 0, 2249, 0, + 0, 2395, 0, + 0, 2537, 0, + 0, 2675, 0, + 0, 2813, 0, + 0, 2949, 0, + 0, 3083, 0, + 0, 3217, 0, + 0, 3351, 0, + 0, 3485, 0, + 0, 3617, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 2809, 0, 2639, + 2809, 0, 2639, + 2809, 0, 2637, + 2807, 0, 2637, + 2805, 0, 2635, + 2803, 0, 2633, + 2801, 0, 2629, + 2797, 0, 2625, + 2791, 0, 2619, + 2785, 0, 2611, + 2775, 0, 2601, + 2763, 0, 2587, + 2745, 742, 2567, + 2721, 1212, 2537, + 2685, 1495, 2497, + 2633, 1714, 2435, + 2551, 1901, 2335, + 2415, 2071, 2159, + 2125, 2229, 1695, + 0, 2381, 0, + 0, 2525, 0, + 0, 2667, 0, + 0, 2807, 0, + 0, 2945, 0, + 0, 3081, 0, + 0, 3215, 0, + 0, 3349, 0, + 0, 3483, 0, + 0, 3617, 0, + 0, 3749, 0, + 0, 3883, 0, + 0, 4015, 0, + 2941, 0, 2769, + 2941, 0, 2767, + 2939, 0, 2767, + 2939, 0, 2765, + 2937, 0, 2765, + 2937, 0, 2763, + 2935, 0, 2761, + 2931, 0, 2757, + 2927, 0, 2753, + 2923, 0, 2747, + 2915, 0, 2739, + 2907, 0, 2729, + 2893, 0, 2713, + 2875, 832, 2693, + 2851, 1330, 2665, + 2815, 1619, 2623, + 2763, 1841, 2561, + 2681, 2030, 2461, + 2543, 2201, 2279, + 2251, 2361, 1793, + 0, 2511, 0, + 0, 2657, 0, + 0, 2799, 0, + 0, 2939, 0, + 0, 3077, 0, + 0, 3213, 0, + 0, 3347, 0, + 0, 3481, 0, + 0, 3615, 0, + 0, 3749, 0, + 0, 3883, 0, + 0, 4015, 0, + 3073, 0, 2897, + 3073, 0, 2897, + 3071, 0, 2897, + 3071, 0, 2895, + 3071, 0, 2895, + 3069, 0, 2893, + 3067, 0, 2891, + 3065, 0, 2889, + 3063, 0, 2887, + 3059, 0, 2881, + 3053, 0, 2877, + 3047, 0, 2869, + 3037, 0, 2857, + 3025, 0, 2843, + 3007, 930, 2821, + 2981, 1451, 2793, + 2947, 1745, 2751, + 2893, 1970, 2687, + 2813, 2161, 2587, + 2673, 2331, 2401, + 2379, 2491, 1898, + 0, 2643, 0, + 0, 2789, 0, + 0, 2931, 0, + 0, 3071, 0, + 0, 3209, 0, + 0, 3345, 0, + 0, 3479, 0, + 0, 3613, 0, + 0, 3747, 0, + 0, 3881, 0, + 0, 4015, 0, + 3205, 0, 3027, + 3205, 0, 3027, + 3203, 0, 3027, + 3203, 0, 3027, + 3203, 0, 3025, + 3201, 0, 3025, + 3201, 0, 3023, + 3199, 0, 3021, + 3197, 0, 3019, + 3195, 0, 3015, + 3191, 0, 3011, + 3185, 0, 3005, + 3179, 0, 2997, + 3169, 0, 2987, + 3157, 0, 2973, + 3139, 1035, 2951, + 3113, 1574, 2921, + 3077, 1873, 2879, + 3025, 2099, 2815, + 2943, 2291, 2713, + 2805, 2463, 2527, + 2509, 2623, 2008, + 0, 2775, 0, + 0, 2921, 0, + 0, 3063, 0, + 0, 3203, 0, + 0, 3341, 0, + 0, 3477, 0, + 0, 3611, 0, + 0, 3745, 0, + 0, 3879, 0, + 0, 4013, 0, + 3337, 0, 3159, + 3337, 0, 3157, + 3335, 0, 3157, + 3335, 0, 3157, + 3335, 0, 3157, + 3335, 0, 3155, + 3333, 0, 3155, + 3333, 0, 3153, + 3331, 0, 3151, + 3329, 0, 3149, + 3325, 0, 3147, + 3323, 0, 3141, + 3317, 0, 3137, + 3311, 0, 3129, + 3301, 0, 3117, + 3287, 0, 3103, + 3269, 1146, 3081, + 3245, 1700, 3051, + 3209, 2002, 3009, + 3157, 2229, 2945, + 3075, 2421, 2843, + 2935, 2593, 2653, + 2639, 2753, 2123, + 0, 2905, 0, + 0, 3053, 0, + 0, 3195, 0, + 0, 3335, 0, + 0, 3473, 0, + 0, 3609, 0, + 0, 3743, 0, + 0, 3879, 0, + 0, 4011, 0, + 3469, 0, 3289, + 3469, 0, 3289, + 3467, 0, 3289, + 3467, 0, 3289, + 3467, 0, 3289, + 3467, 0, 3287, + 3467, 0, 3287, + 3465, 0, 3285, + 3465, 0, 3285, + 3463, 0, 3283, + 3461, 0, 3281, + 3457, 0, 3277, + 3453, 0, 3273, + 3449, 0, 3267, + 3441, 0, 3259, + 3433, 0, 3247, + 3419, 0, 3233, + 3401, 1261, 3211, + 3377, 1827, 3183, + 3341, 2131, 3139, + 3287, 2359, 3075, + 3205, 2553, 2971, + 3067, 2725, 2781, + 2769, 2885, 2243, + 0, 3037, 0, + 0, 3183, 0, + 0, 3327, 0, + 0, 3467, 0, + 0, 3605, 0, + 0, 3741, 0, + 0, 3875, 0, + 0, 4011, 0, + 3601, 0, 3421, + 3601, 0, 3421, + 3599, 0, 3421, + 3599, 0, 3419, + 3599, 0, 3419, + 3599, 0, 3419, + 3599, 0, 3419, + 3599, 0, 3417, + 3597, 0, 3417, + 3595, 0, 3415, + 3595, 0, 3413, + 3593, 0, 3411, + 3589, 0, 3409, + 3585, 0, 3403, + 3581, 0, 3397, + 3573, 0, 3389, + 3565, 0, 3379, + 3551, 0, 3363, + 3533, 1380, 3343, + 3509, 1956, 3313, + 3473, 2261, 3271, + 3419, 2491, 3205, + 3337, 2683, 3101, + 3199, 2857, 2911, + 2901, 3017, 2365, + 0, 3169, 0, + 0, 3315, 0, + 0, 3459, 0, + 0, 3599, 0, + 0, 3737, 0, + 0, 3873, 0, + 0, 4007, 0, + 3733, 0, 3551, + 3733, 0, 3551, + 3733, 0, 3551, + 3731, 0, 3551, + 3731, 0, 3551, + 3731, 0, 3551, + 3731, 0, 3551, + 3731, 0, 3551, + 3729, 0, 3549, + 3729, 0, 3549, + 3727, 0, 3547, + 3727, 0, 3545, + 3725, 0, 3543, + 3721, 0, 3539, + 3717, 0, 3535, + 3713, 0, 3529, + 3705, 0, 3521, + 3697, 0, 3511, + 3683, 0, 3495, + 3665, 1503, 3475, + 3641, 2085, 3445, + 3605, 2393, 3401, + 3551, 2623, 3337, + 3469, 2815, 3233, + 3329, 2989, 3041, + 3031, 3149, 2489, + 0, 3301, 0, + 0, 3447, 0, + 0, 3591, 0, + 0, 3731, 0, + 0, 3869, 0, + 0, 4005, 0, + 3865, 0, 3683, + 3865, 0, 3683, + 3865, 0, 3683, + 3865, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3681, + 3861, 0, 3681, + 3861, 0, 3679, + 3859, 0, 3679, + 3859, 0, 3677, + 3857, 0, 3675, + 3853, 0, 3671, + 3849, 0, 3667, + 3845, 0, 3661, + 3837, 0, 3653, + 3829, 0, 3641, + 3815, 0, 3627, + 3797, 1627, 3605, + 3773, 2215, 3575, + 3737, 2523, 3533, + 3683, 2753, 3467, + 3601, 2947, 3363, + 3461, 3121, 3171, + 3163, 3281, 2617, + 0, 3433, 0, + 0, 3579, 0, + 0, 3723, 0, + 0, 3863, 0, + 0, 4001, 0, + 3997, 0, 3815, + 3997, 0, 3815, + 3997, 0, 3815, + 3997, 0, 3815, + 3997, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3813, + 3995, 0, 3813, + 3993, 0, 3813, + 3993, 0, 3811, + 3991, 0, 3811, + 3991, 0, 3809, + 3989, 0, 3807, + 3985, 0, 3803, + 3981, 0, 3799, + 3977, 0, 3793, + 3969, 0, 3785, + 3961, 0, 3773, + 3947, 0, 3759, + 3929, 1754, 3737, + 3905, 2345, 3707, + 3869, 2655, 3665, + 3815, 2885, 3599, + 3733, 3079, 3495, + 3593, 3253, 3301, + 3295, 3413, 2743, + 0, 3565, 0, + 0, 3713, 0, + 0, 3855, 0, + 0, 3995, 0, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3943, + 4095, 0, 3943, + 4095, 0, 3941, + 4095, 0, 3937, + 4095, 0, 3935, + 4095, 0, 3931, + 4095, 0, 3925, + 4095, 0, 3917, + 4093, 0, 3905, + 4079, 0, 3891, + 4061, 1881, 3869, + 4037, 2477, 3839, + 4001, 2787, 3795, + 3947, 3017, 3731, + 3865, 3211, 3627, + 3725, 3385, 3433, + 3427, 3545, 2873, + 0, 3697, 0, + 0, 3845, 0, + 0, 3987, 0, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4075, + 4095, 0, 4073, + 4095, 0, 4073, + 4095, 0, 4069, + 4095, 0, 4067, + 4095, 0, 4063, + 4095, 0, 4057, + 4095, 0, 4049, + 4095, 0, 4037, + 4095, 0, 4021, + 4095, 2010, 4001, + 4095, 2609, 3971, + 4095, 2919, 3927, + 4079, 3149, 3863, + 3997, 3343, 3757, + 3857, 3517, 3565, + 3559, 3677, 3003, + 0, 3829, 0, + 0, 3977, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2141, 4095, + 4095, 2739, 4095, + 4095, 3049, 4059, + 4095, 3281, 3995, + 4095, 3475, 3889, + 3989, 3649, 3697, + 3691, 3809, 3133, + 0, 3961, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2271, 4095, + 4095, 2871, 4095, + 4095, 3181, 4095, + 4095, 3413, 4095, + 4095, 3607, 4021, + 4095, 3781, 3827, + 3823, 3941, 3263, + 881, 513, 1262, + 834, 553, 1247, + 762, 601, 1225, + 645, 659, 1196, + 417, 726, 1152, + 0, 802, 1087, + 0, 888, 982, + 0, 982, 788, + 0, 1083, 222, + 0, 1191, 0, + 0, 1304, 0, + 0, 1421, 0, + 0, 1542, 0, + 0, 1665, 0, + 0, 1791, 0, + 0, 1918, 0, + 0, 2046, 0, + 0, 2175, 0, + 0, 2305, 0, + 0, 2437, 0, + 0, 2567, 0, + 0, 2699, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 934, 506, 1278, + 893, 547, 1263, + 831, 596, 1243, + 731, 654, 1214, + 552, 722, 1173, + 77, 799, 1111, + 0, 885, 1012, + 0, 980, 833, + 0, 1082, 361, + 0, 1190, 0, + 0, 1303, 0, + 0, 1421, 0, + 0, 1541, 0, + 0, 1665, 0, + 0, 1791, 0, + 0, 1918, 0, + 0, 2046, 0, + 0, 2175, 0, + 0, 2305, 0, + 0, 2437, 0, + 0, 2567, 0, + 0, 2699, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 997, 497, 1299, + 961, 539, 1285, + 908, 588, 1265, + 826, 648, 1238, + 686, 716, 1199, + 387, 794, 1140, + 0, 882, 1048, + 0, 977, 886, + 0, 1079, 498, + 0, 1188, 0, + 0, 1302, 0, + 0, 1419, 0, + 0, 1541, 0, + 0, 1664, 0, + 0, 1790, 0, + 0, 1917, 0, + 0, 2046, 0, + 0, 2175, 0, + 0, 2305, 0, + 0, 2435, 0, + 0, 2567, 0, + 0, 2699, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1070, 485, 1325, + 1039, 528, 1312, + 995, 579, 1294, + 928, 639, 1268, + 820, 709, 1231, + 618, 788, 1177, + 0, 876, 1093, + 0, 973, 949, + 0, 1076, 633, + 0, 1185, 0, + 0, 1299, 0, + 0, 1418, 0, + 0, 1539, 0, + 0, 1663, 0, + 0, 1789, 0, + 0, 1917, 0, + 0, 2045, 0, + 0, 2175, 0, + 0, 2305, 0, + 0, 2435, 0, + 0, 2567, 0, + 0, 2699, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1151, 469, 1358, + 1126, 513, 1346, + 1090, 565, 1329, + 1036, 627, 1305, + 954, 699, 1272, + 812, 780, 1222, + 507, 870, 1147, + 0, 967, 1021, + 0, 1071, 768, + 0, 1182, 0, + 0, 1297, 0, + 0, 1416, 0, + 0, 1538, 0, + 0, 1662, 0, + 0, 1788, 0, + 0, 1916, 0, + 0, 2045, 0, + 0, 2175, 0, + 0, 2305, 0, + 0, 2435, 0, + 0, 2567, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1242, 446, 1399, + 1221, 492, 1387, + 1192, 547, 1372, + 1150, 611, 1351, + 1086, 685, 1320, + 985, 768, 1276, + 801, 860, 1210, + 296, 960, 1102, + 0, 1065, 902, + 0, 1177, 287, + 0, 1293, 0, + 0, 1413, 0, + 0, 1536, 0, + 0, 1661, 0, + 0, 1787, 0, + 0, 1915, 0, + 0, 2044, 0, + 0, 2175, 0, + 0, 2305, 0, + 0, 2435, 0, + 0, 2567, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1340, 413, 1448, + 1323, 462, 1438, + 1300, 520, 1424, + 1267, 588, 1405, + 1219, 666, 1378, + 1146, 752, 1340, + 1024, 847, 1283, + 785, 949, 1193, + 0, 1057, 1035, + 0, 1171, 670, + 0, 1288, 0, + 0, 1409, 0, + 0, 1533, 0, + 0, 1658, 0, + 0, 1786, 0, + 0, 1914, 0, + 0, 2043, 0, + 0, 2173, 0, + 0, 2303, 0, + 0, 2435, 0, + 0, 2567, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1445, 365, 1506, + 1432, 419, 1498, + 1414, 483, 1486, + 1388, 556, 1469, + 1352, 639, 1446, + 1298, 730, 1413, + 1215, 829, 1365, + 1072, 935, 1291, + 764, 1046, 1169, + 0, 1162, 927, + 0, 1281, 0, + 0, 1404, 0, + 0, 1529, 0, + 0, 1655, 0, + 0, 1783, 0, + 0, 1912, 0, + 0, 2042, 0, + 0, 2173, 0, + 0, 2303, 0, + 0, 2435, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1556, 291, 1575, + 1546, 354, 1567, + 1531, 427, 1557, + 1512, 509, 1542, + 1485, 600, 1523, + 1445, 699, 1495, + 1386, 804, 1455, + 1293, 915, 1396, + 1129, 1031, 1301, + 733, 1150, 1134, + 0, 1272, 724, + 0, 1397, 0, + 0, 1524, 0, + 0, 1651, 0, + 0, 1780, 0, + 0, 1910, 0, + 0, 2040, 0, + 0, 2171, 0, + 0, 2303, 0, + 0, 2433, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1671, 169, 1652, + 1663, 250, 1646, + 1652, 340, 1637, + 1638, 438, 1625, + 1617, 543, 1609, + 1588, 653, 1586, + 1546, 768, 1554, + 1482, 887, 1506, + 1381, 1009, 1434, + 1196, 1134, 1315, + 689, 1260, 1084, + 0, 1388, 87, + 0, 1516, 0, + 0, 1646, 0, + 0, 1776, 0, + 0, 1907, 0, + 0, 2038, 0, + 0, 2169, 0, + 0, 2301, 0, + 0, 2433, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1790, 0, 1739, + 1784, 59, 1733, + 1776, 190, 1726, + 1765, 321, 1716, + 1749, 452, 1703, + 1728, 583, 1685, + 1697, 715, 1659, + 1653, 847, 1622, + 1585, 979, 1567, + 1476, 1111, 1481, + 1272, 1243, 1334, + 622, 1375, 1007, + 0, 1507, 0, + 0, 1639, 0, + 0, 1771, 0, + 0, 1903, 0, + 0, 2035, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1913, 0, 1833, + 1908, 0, 1829, + 1902, 0, 1823, + 1893, 93, 1816, + 1882, 293, 1805, + 1866, 470, 1790, + 1843, 633, 1770, + 1811, 787, 1741, + 1765, 935, 1699, + 1694, 1078, 1637, + 1579, 1218, 1537, + 1357, 1357, 1357, + 514, 1493, 877, + 0, 1629, 0, + 0, 1763, 0, + 0, 1897, 0, + 0, 2031, 0, + 0, 2165, 0, + 0, 2297, 0, + 0, 2429, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2037, 0, 1935, + 2034, 0, 1932, + 2029, 0, 1927, + 2023, 0, 1921, + 2014, 0, 1913, + 2002, 254, 1901, + 1985, 493, 1885, + 1962, 692, 1863, + 1930, 868, 1832, + 1882, 1030, 1786, + 1809, 1184, 1716, + 1688, 1331, 1603, + 1450, 1475, 1386, + 311, 1615, 612, + 0, 1753, 0, + 0, 1890, 0, + 0, 2025, 0, + 0, 2159, 0, + 0, 2293, 0, + 0, 2427, 0, + 0, 2561, 0, + 0, 2693, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2163, 0, 2044, + 2161, 0, 2041, + 2157, 0, 2037, + 2153, 0, 2033, + 2147, 0, 2026, + 2137, 0, 2017, + 2125, 195, 2005, + 2109, 522, 1988, + 2085, 760, 1964, + 2051, 958, 1930, + 2002, 1133, 1881, + 1927, 1295, 1805, + 1802, 1449, 1678, + 1551, 1596, 1422, + 0, 1739, 0, + 0, 1880, 0, + 0, 2018, 0, + 0, 2155, 0, + 0, 2289, 0, + 0, 2425, 0, + 0, 2559, 0, + 0, 2691, 0, + 0, 2825, 0, + 0, 2957, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2291, 0, 2157, + 2289, 0, 2155, + 2287, 0, 2153, + 2283, 0, 2149, + 2279, 0, 2143, + 2271, 0, 2137, + 2263, 0, 2127, + 2251, 102, 2115, + 2233, 559, 2097, + 2209, 838, 2071, + 2175, 1055, 2035, + 2125, 1242, 1983, + 2049, 1412, 1901, + 1920, 1570, 1762, + 1658, 1720, 1466, + 0, 1866, 0, + 0, 2007, 0, + 0, 2147, 0, + 0, 2283, 0, + 0, 2419, 0, + 0, 2555, 0, + 0, 2689, 0, + 0, 2823, 0, + 0, 2957, 0, + 0, 3089, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3885, 0, + 0, 4017, 0, + 2421, 0, 2275, + 2419, 0, 2273, + 2417, 0, 2271, + 2415, 0, 2269, + 2411, 0, 2265, + 2405, 0, 2259, + 2399, 0, 2251, + 2389, 0, 2241, + 2377, 0, 2229, + 2359, 603, 2209, + 2335, 925, 2183, + 2301, 1160, 2147, + 2251, 1356, 2091, + 2173, 1531, 2004, + 2041, 1693, 1855, + 1771, 1846, 1520, + 0, 1993, 0, + 0, 2137, 0, + 0, 2277, 0, + 0, 2415, 0, + 0, 2551, 0, + 0, 2687, 0, + 0, 2821, 0, + 0, 2955, 0, + 0, 3089, 0, + 0, 3221, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3885, 0, + 0, 4017, 0, + 2551, 0, 2395, + 2549, 0, 2395, + 2547, 0, 2393, + 2545, 0, 2391, + 2543, 0, 2387, + 2539, 0, 2383, + 2533, 0, 2379, + 2527, 0, 2371, + 2517, 0, 2361, + 2505, 0, 2347, + 2487, 657, 2327, + 2463, 1020, 2301, + 2429, 1270, 2261, + 2377, 1475, 2205, + 2299, 1654, 2113, + 2165, 1818, 1955, + 1888, 1973, 1583, + 0, 2121, 0, + 0, 2265, 0, + 0, 2407, 0, + 0, 2545, 0, + 0, 2681, 0, + 0, 2817, 0, + 0, 2953, 0, + 0, 3087, 0, + 0, 3219, 0, + 0, 3353, 0, + 0, 3485, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4017, 0, + 2681, 0, 2519, + 2679, 0, 2519, + 2679, 0, 2517, + 2677, 0, 2515, + 2675, 0, 2513, + 2673, 0, 2511, + 2669, 0, 2505, + 2663, 0, 2501, + 2657, 0, 2493, + 2647, 0, 2483, + 2635, 0, 2469, + 2617, 720, 2449, + 2593, 1122, 2421, + 2557, 1386, 2381, + 2505, 1596, 2321, + 2425, 1779, 2229, + 2291, 1946, 2061, + 2008, 2101, 1655, + 0, 2251, 0, + 0, 2397, 0, + 0, 2537, 0, + 0, 2677, 0, + 0, 2813, 0, + 0, 2949, 0, + 0, 3083, 0, + 0, 3219, 0, + 0, 3351, 0, + 0, 3485, 0, + 0, 3617, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 2811, 0, 2645, + 2811, 0, 2645, + 2809, 0, 2643, + 2809, 0, 2641, + 2807, 0, 2641, + 2805, 0, 2637, + 2803, 0, 2635, + 2799, 0, 2631, + 2793, 0, 2625, + 2787, 0, 2617, + 2777, 0, 2607, + 2765, 0, 2593, + 2747, 792, 2573, + 2721, 1230, 2545, + 2687, 1505, 2503, + 2635, 1720, 2443, + 2555, 1906, 2347, + 2417, 2073, 2173, + 2131, 2231, 1736, + 0, 2381, 0, + 0, 2527, 0, + 0, 2669, 0, + 0, 2807, 0, + 0, 2945, 0, + 0, 3081, 0, + 0, 3215, 0, + 0, 3351, 0, + 0, 3483, 0, + 0, 3617, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 2943, 0, 2773, + 2941, 0, 2771, + 2941, 0, 2771, + 2941, 0, 2769, + 2939, 0, 2769, + 2937, 0, 2767, + 2935, 0, 2765, + 2933, 0, 2761, + 2929, 0, 2757, + 2923, 0, 2751, + 2917, 0, 2743, + 2907, 0, 2733, + 2895, 0, 2719, + 2877, 874, 2699, + 2853, 1344, 2669, + 2817, 1627, 2629, + 2765, 1846, 2567, + 2683, 2034, 2469, + 2547, 2203, 2291, + 2257, 2361, 1827, + 0, 2513, 0, + 0, 2657, 0, + 0, 2799, 0, + 0, 2939, 0, + 0, 3077, 0, + 0, 3213, 0, + 0, 3347, 0, + 0, 3481, 0, + 0, 3615, 0, + 0, 3749, 0, + 0, 3883, 0, + 0, 4015, 0, + 3073, 0, 2901, + 3073, 0, 2901, + 3073, 0, 2899, + 3073, 0, 2899, + 3071, 0, 2897, + 3071, 0, 2897, + 3069, 0, 2895, + 3067, 0, 2893, + 3063, 0, 2889, + 3059, 0, 2885, + 3055, 0, 2879, + 3047, 0, 2871, + 3039, 0, 2861, + 3025, 0, 2847, + 3007, 964, 2825, + 2983, 1462, 2797, + 2947, 1751, 2755, + 2895, 1973, 2693, + 2813, 2163, 2593, + 2675, 2333, 2411, + 2383, 2493, 1925, + 0, 2643, 0, + 0, 2789, 0, + 0, 2931, 0, + 0, 3071, 0, + 0, 3209, 0, + 0, 3345, 0, + 0, 3479, 0, + 0, 3613, 0, + 0, 3747, 0, + 0, 3881, 0, + 0, 4015, 0, + 3205, 0, 3029, + 3205, 0, 3029, + 3205, 0, 3029, + 3205, 0, 3029, + 3203, 0, 3027, + 3203, 0, 3027, + 3201, 0, 3025, + 3199, 0, 3023, + 3197, 0, 3021, + 3195, 0, 3019, + 3191, 0, 3013, + 3187, 0, 3009, + 3179, 0, 3001, + 3169, 0, 2989, + 3157, 0, 2975, + 3139, 1062, 2955, + 3115, 1583, 2925, + 3079, 1877, 2883, + 3025, 2101, 2819, + 2945, 2293, 2719, + 2805, 2463, 2533, + 2513, 2623, 2030, + 0, 2775, 0, + 0, 2921, 0, + 0, 3063, 0, + 0, 3203, 0, + 0, 3341, 0, + 0, 3477, 0, + 0, 3611, 0, + 0, 3747, 0, + 0, 3879, 0, + 0, 4013, 0, + 3337, 0, 3159, + 3337, 0, 3159, + 3337, 0, 3159, + 3335, 0, 3159, + 3335, 0, 3159, + 3335, 0, 3157, + 3335, 0, 3157, + 3333, 0, 3155, + 3331, 0, 3153, + 3329, 0, 3151, + 3327, 0, 3149, + 3323, 0, 3143, + 3317, 0, 3137, + 3311, 0, 3129, + 3301, 0, 3119, + 3289, 0, 3105, + 3271, 1167, 3083, + 3245, 1707, 3055, + 3209, 2005, 3011, + 3157, 2231, 2947, + 3075, 2423, 2845, + 2937, 2595, 2659, + 2641, 2755, 2141, + 0, 2907, 0, + 0, 3053, 0, + 0, 3195, 0, + 0, 3335, 0, + 0, 3473, 0, + 0, 3609, 0, + 0, 3743, 0, + 0, 3879, 0, + 0, 4011, 0, + 3469, 0, 3291, + 3469, 0, 3291, + 3469, 0, 3291, + 3469, 0, 3289, + 3467, 0, 3289, + 3467, 0, 3289, + 3467, 0, 3289, + 3465, 0, 3287, + 3465, 0, 3285, + 3463, 0, 3283, + 3461, 0, 3281, + 3459, 0, 3279, + 3455, 0, 3275, + 3449, 0, 3269, + 3443, 0, 3261, + 3433, 0, 3249, + 3419, 0, 3235, + 3403, 1278, 3213, + 3377, 1832, 3183, + 3341, 2133, 3141, + 3289, 2361, 3077, + 3207, 2553, 2975, + 3067, 2725, 2785, + 2771, 2885, 2255, + 0, 3037, 0, + 0, 3185, 0, + 0, 3327, 0, + 0, 3467, 0, + 0, 3605, 0, + 0, 3741, 0, + 0, 3875, 0, + 0, 4011, 0, + 3601, 0, 3421, + 3601, 0, 3421, + 3601, 0, 3421, + 3601, 0, 3421, + 3599, 0, 3421, + 3599, 0, 3421, + 3599, 0, 3419, + 3599, 0, 3419, + 3597, 0, 3417, + 3597, 0, 3417, + 3595, 0, 3415, + 3593, 0, 3413, + 3589, 0, 3409, + 3587, 0, 3405, + 3581, 0, 3399, + 3573, 0, 3391, + 3565, 0, 3379, + 3551, 0, 3365, + 3533, 1393, 3345, + 3509, 1959, 3315, + 3473, 2263, 3271, + 3419, 2491, 3207, + 3339, 2685, 3103, + 3199, 2857, 2913, + 2901, 3017, 2375, + 0, 3169, 0, + 0, 3317, 0, + 0, 3459, 0, + 0, 3599, 0, + 0, 3737, 0, + 0, 3873, 0, + 0, 4007, 0, + 3733, 0, 3553, + 3733, 0, 3553, + 3733, 0, 3553, + 3733, 0, 3553, + 3731, 0, 3553, + 3731, 0, 3551, + 3731, 0, 3551, + 3731, 0, 3551, + 3731, 0, 3551, + 3729, 0, 3549, + 3729, 0, 3547, + 3727, 0, 3545, + 3725, 0, 3543, + 3721, 0, 3541, + 3717, 0, 3535, + 3713, 0, 3531, + 3705, 0, 3521, + 3697, 0, 3511, + 3683, 0, 3495, + 3665, 1513, 3475, + 3641, 2087, 3445, + 3605, 2393, 3403, + 3551, 2623, 3337, + 3469, 2817, 3233, + 3331, 2989, 3043, + 3033, 3149, 2497, + 0, 3301, 0, + 0, 3449, 0, + 0, 3591, 0, + 0, 3731, 0, + 0, 3869, 0, + 0, 4005, 0, + 3865, 0, 3685, + 3865, 0, 3685, + 3865, 0, 3683, + 3865, 0, 3683, + 3865, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3681, + 3861, 0, 3681, + 3861, 0, 3679, + 3859, 0, 3677, + 3857, 0, 3675, + 3853, 0, 3671, + 3849, 0, 3667, + 3845, 0, 3661, + 3837, 0, 3653, + 3829, 0, 3643, + 3815, 0, 3627, + 3797, 1635, 3607, + 3773, 2217, 3577, + 3737, 2525, 3533, + 3683, 2755, 3469, + 3601, 2947, 3365, + 3461, 3121, 3173, + 3163, 3281, 2621, + 0, 3433, 0, + 0, 3581, 0, + 0, 3723, 0, + 0, 3863, 0, + 0, 4001, 0, + 3997, 0, 3815, + 3997, 0, 3815, + 3997, 0, 3815, + 3997, 0, 3815, + 3997, 0, 3815, + 3997, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3813, + 3995, 0, 3813, + 3993, 0, 3813, + 3993, 0, 3811, + 3991, 0, 3809, + 3989, 0, 3807, + 3985, 0, 3803, + 3981, 0, 3799, + 3977, 0, 3793, + 3969, 0, 3785, + 3961, 0, 3773, + 3947, 0, 3759, + 3929, 1759, 3737, + 3905, 2347, 3707, + 3869, 2655, 3665, + 3815, 2885, 3599, + 3733, 3079, 3495, + 3593, 3253, 3303, + 3295, 3413, 2749, + 0, 3565, 0, + 0, 3713, 0, + 0, 3855, 0, + 0, 3995, 0, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3943, + 4095, 0, 3943, + 4095, 0, 3941, + 4095, 0, 3939, + 4095, 0, 3935, + 4095, 0, 3931, + 4095, 0, 3925, + 4095, 0, 3917, + 4093, 0, 3905, + 4079, 0, 3891, + 4061, 1886, 3869, + 4037, 2477, 3839, + 4001, 2787, 3797, + 3947, 3017, 3731, + 3865, 3211, 3627, + 3725, 3385, 3435, + 3427, 3545, 2877, + 0, 3697, 0, + 0, 3845, 0, + 0, 3987, 0, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4075, + 4095, 0, 4075, + 4095, 0, 4073, + 4095, 0, 4069, + 4095, 0, 4067, + 4095, 0, 4063, + 4095, 0, 4057, + 4095, 0, 4049, + 4095, 0, 4037, + 4095, 0, 4023, + 4095, 2014, 4001, + 4095, 2609, 3971, + 4095, 2919, 3929, + 4079, 3149, 3863, + 3997, 3343, 3759, + 3857, 3517, 3565, + 3559, 3677, 3005, + 0, 3829, 0, + 0, 3977, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2143, 4095, + 4095, 2741, 4095, + 4095, 3051, 4059, + 4095, 3281, 3995, + 4095, 3475, 3891, + 3989, 3649, 3697, + 3691, 3809, 3135, + 0, 3961, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2273, 4095, + 4095, 2871, 4095, + 4095, 3183, 4095, + 4095, 3413, 4095, + 4095, 3607, 4021, + 4095, 3781, 3829, + 3823, 3941, 3265, + 1004, 617, 1393, + 969, 649, 1381, + 916, 689, 1366, + 836, 737, 1344, + 699, 794, 1313, + 412, 861, 1269, + 0, 937, 1201, + 0, 1022, 1091, + 0, 1116, 884, + 0, 1217, 213, + 0, 1324, 0, + 0, 1437, 0, + 0, 1554, 0, + 0, 1675, 0, + 0, 1798, 0, + 0, 1923, 0, + 0, 2051, 0, + 0, 2179, 0, + 0, 2307, 0, + 0, 2437, 0, + 0, 2569, 0, + 0, 2699, 0, + 0, 2831, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1045, 612, 1405, + 1013, 645, 1394, + 966, 685, 1379, + 895, 733, 1358, + 777, 791, 1328, + 549, 858, 1284, + 0, 935, 1219, + 0, 1020, 1114, + 0, 1114, 920, + 0, 1216, 354, + 0, 1323, 0, + 0, 1436, 0, + 0, 1554, 0, + 0, 1674, 0, + 0, 1798, 0, + 0, 1923, 0, + 0, 2051, 0, + 0, 2179, 0, + 0, 2307, 0, + 0, 2437, 0, + 0, 2569, 0, + 0, 2699, 0, + 0, 2831, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1095, 605, 1421, + 1066, 638, 1410, + 1025, 679, 1395, + 963, 728, 1375, + 864, 786, 1346, + 684, 854, 1305, + 209, 931, 1243, + 0, 1018, 1144, + 0, 1112, 965, + 0, 1214, 493, + 0, 1322, 0, + 0, 1435, 0, + 0, 1553, 0, + 0, 1674, 0, + 0, 1797, 0, + 0, 1923, 0, + 0, 2049, 0, + 0, 2179, 0, + 0, 2307, 0, + 0, 2437, 0, + 0, 2569, 0, + 0, 2699, 0, + 0, 2831, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1154, 596, 1441, + 1129, 629, 1431, + 1093, 671, 1417, + 1040, 721, 1397, + 958, 780, 1370, + 818, 848, 1331, + 519, 927, 1272, + 0, 1014, 1180, + 0, 1109, 1018, + 0, 1211, 630, + 0, 1320, 0, + 0, 1434, 0, + 0, 1552, 0, + 0, 1673, 0, + 0, 1796, 0, + 0, 1922, 0, + 0, 2049, 0, + 0, 2179, 0, + 0, 2307, 0, + 0, 2437, 0, + 0, 2569, 0, + 0, 2699, 0, + 0, 2831, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1223, 583, 1467, + 1202, 617, 1457, + 1171, 660, 1444, + 1127, 711, 1426, + 1060, 771, 1400, + 952, 841, 1363, + 750, 920, 1309, + 121, 1009, 1225, + 0, 1105, 1081, + 0, 1208, 765, + 0, 1317, 0, + 0, 1432, 0, + 0, 1550, 0, + 0, 1671, 0, + 0, 1796, 0, + 0, 1922, 0, + 0, 2049, 0, + 0, 2177, 0, + 0, 2307, 0, + 0, 2437, 0, + 0, 2567, 0, + 0, 2699, 0, + 0, 2831, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1301, 565, 1499, + 1283, 601, 1490, + 1258, 645, 1478, + 1222, 697, 1461, + 1168, 759, 1437, + 1085, 831, 1404, + 944, 912, 1354, + 639, 1002, 1279, + 0, 1099, 1153, + 0, 1204, 900, + 0, 1314, 0, + 0, 1429, 0, + 0, 1548, 0, + 0, 1670, 0, + 0, 1794, 0, + 0, 1921, 0, + 0, 2049, 0, + 0, 2177, 0, + 0, 2307, 0, + 0, 2437, 0, + 0, 2567, 0, + 0, 2699, 0, + 0, 2831, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1389, 540, 1539, + 1374, 578, 1531, + 1353, 624, 1520, + 1324, 679, 1504, + 1282, 743, 1483, + 1219, 817, 1452, + 1117, 900, 1408, + 933, 992, 1342, + 429, 1091, 1234, + 0, 1197, 1034, + 0, 1309, 419, + 0, 1425, 0, + 0, 1545, 0, + 0, 1668, 0, + 0, 1793, 0, + 0, 1919, 0, + 0, 2047, 0, + 0, 2177, 0, + 0, 2307, 0, + 0, 2437, 0, + 0, 2567, 0, + 0, 2699, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1484, 504, 1587, + 1472, 545, 1580, + 1456, 594, 1570, + 1432, 652, 1556, + 1400, 721, 1537, + 1351, 798, 1510, + 1278, 885, 1472, + 1157, 979, 1415, + 917, 1081, 1325, + 0, 1189, 1167, + 0, 1303, 802, + 0, 1420, 0, + 0, 1541, 0, + 0, 1665, 0, + 0, 1790, 0, + 0, 1918, 0, + 0, 2046, 0, + 0, 2175, 0, + 0, 2305, 0, + 0, 2437, 0, + 0, 2567, 0, + 0, 2699, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1587, 451, 1645, + 1577, 497, 1639, + 1564, 551, 1630, + 1546, 615, 1618, + 1520, 688, 1601, + 1484, 771, 1578, + 1430, 862, 1545, + 1347, 961, 1497, + 1204, 1067, 1423, + 896, 1178, 1301, + 0, 1294, 1059, + 0, 1414, 0, + 0, 1536, 0, + 0, 1661, 0, + 0, 1788, 0, + 0, 1915, 0, + 0, 2044, 0, + 0, 2175, 0, + 0, 2305, 0, + 0, 2435, 0, + 0, 2567, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1695, 369, 1712, + 1688, 423, 1707, + 1678, 486, 1699, + 1664, 559, 1689, + 1644, 641, 1675, + 1617, 732, 1655, + 1577, 831, 1627, + 1518, 936, 1587, + 1425, 1047, 1528, + 1261, 1163, 1434, + 865, 1282, 1266, + 0, 1404, 856, + 0, 1529, 0, + 0, 1656, 0, + 0, 1784, 0, + 0, 1912, 0, + 0, 2042, 0, + 0, 2173, 0, + 0, 2303, 0, + 0, 2435, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1809, 230, 1789, + 1803, 301, 1784, + 1795, 382, 1778, + 1785, 472, 1769, + 1770, 570, 1757, + 1749, 675, 1741, + 1720, 785, 1718, + 1678, 900, 1686, + 1614, 1019, 1638, + 1513, 1141, 1566, + 1328, 1266, 1448, + 821, 1392, 1216, + 0, 1520, 219, + 0, 1649, 0, + 0, 1778, 0, + 0, 1908, 0, + 0, 2039, 0, + 0, 2171, 0, + 0, 2301, 0, + 0, 2433, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1927, 0, 1875, + 1923, 61, 1871, + 1917, 191, 1865, + 1908, 322, 1858, + 1897, 453, 1849, + 1881, 584, 1835, + 1860, 716, 1817, + 1829, 847, 1791, + 1785, 979, 1754, + 1717, 1111, 1699, + 1608, 1243, 1613, + 1404, 1375, 1466, + 754, 1507, 1139, + 0, 1639, 0, + 0, 1771, 0, + 0, 1903, 0, + 0, 2035, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2049, 0, 1969, + 2045, 0, 1966, + 2040, 0, 1961, + 2034, 0, 1955, + 2025, 225, 1948, + 2014, 425, 1937, + 1998, 602, 1922, + 1975, 765, 1902, + 1943, 919, 1873, + 1897, 1067, 1831, + 1827, 1210, 1769, + 1711, 1351, 1669, + 1489, 1489, 1489, + 646, 1625, 1009, + 0, 1761, 0, + 0, 1896, 0, + 0, 2029, 0, + 0, 2163, 0, + 0, 2297, 0, + 0, 2429, 0, + 0, 2561, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2173, 0, 2071, + 2169, 0, 2067, + 2165, 0, 2065, + 2161, 0, 2059, + 2155, 0, 2053, + 2145, 53, 2045, + 2135, 386, 2033, + 2117, 625, 2017, + 2095, 824, 1995, + 2061, 1000, 1964, + 2014, 1162, 1918, + 1941, 1316, 1848, + 1820, 1464, 1735, + 1582, 1607, 1518, + 443, 1747, 744, + 0, 1885, 0, + 0, 2022, 0, + 0, 2157, 0, + 0, 2291, 0, + 0, 2425, 0, + 0, 2559, 0, + 0, 2693, 0, + 0, 2825, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2297, 0, 2177, + 2295, 0, 2175, + 2293, 0, 2173, + 2289, 0, 2169, + 2285, 0, 2165, + 2279, 0, 2159, + 2269, 0, 2149, + 2257, 327, 2137, + 2241, 655, 2119, + 2217, 892, 2097, + 2183, 1090, 2063, + 2135, 1265, 2013, + 2059, 1428, 1937, + 1934, 1581, 1810, + 1683, 1728, 1554, + 0, 1871, 0, + 0, 2012, 0, + 0, 2149, 0, + 0, 2287, 0, + 0, 2421, 0, + 0, 2557, 0, + 0, 2691, 0, + 0, 2823, 0, + 0, 2957, 0, + 0, 3089, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2425, 0, 2291, + 2423, 0, 2289, + 2421, 0, 2287, + 2419, 0, 2285, + 2415, 0, 2281, + 2411, 0, 2275, + 2403, 0, 2269, + 2395, 0, 2259, + 2383, 234, 2247, + 2365, 691, 2229, + 2341, 970, 2203, + 2307, 1188, 2167, + 2257, 1374, 2115, + 2181, 1544, 2033, + 2051, 1702, 1894, + 1790, 1852, 1599, + 0, 1998, 0, + 0, 2139, 0, + 0, 2279, 0, + 0, 2417, 0, + 0, 2553, 0, + 0, 2687, 0, + 0, 2821, 0, + 0, 2955, 0, + 0, 3089, 0, + 0, 3221, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3885, 0, + 0, 4017, 0, + 2553, 0, 2409, + 2553, 0, 2407, + 2551, 0, 2405, + 2549, 0, 2403, + 2547, 0, 2401, + 2543, 0, 2397, + 2537, 0, 2391, + 2531, 0, 2383, + 2521, 0, 2375, + 2509, 69, 2361, + 2491, 735, 2343, + 2467, 1057, 2315, + 2433, 1292, 2279, + 2383, 1489, 2223, + 2305, 1663, 2137, + 2173, 1825, 1987, + 1903, 1978, 1652, + 0, 2125, 0, + 0, 2269, 0, + 0, 2409, 0, + 0, 2547, 0, + 0, 2683, 0, + 0, 2819, 0, + 0, 2953, 0, + 0, 3087, 0, + 0, 3221, 0, + 0, 3353, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4017, 0, + 2683, 0, 2529, + 2683, 0, 2527, + 2681, 0, 2527, + 2679, 0, 2525, + 2677, 0, 2523, + 2675, 0, 2519, + 2671, 0, 2515, + 2667, 0, 2511, + 2659, 0, 2503, + 2651, 0, 2493, + 2637, 0, 2479, + 2619, 789, 2459, + 2595, 1152, 2433, + 2561, 1403, 2395, + 2509, 1607, 2337, + 2431, 1786, 2245, + 2297, 1951, 2087, + 2020, 2105, 1715, + 0, 2253, 0, + 0, 2397, 0, + 0, 2539, 0, + 0, 2677, 0, + 0, 2815, 0, + 0, 2949, 0, + 0, 3085, 0, + 0, 3219, 0, + 0, 3351, 0, + 0, 3485, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 2813, 0, 2653, + 2813, 0, 2651, + 2811, 0, 2651, + 2811, 0, 2649, + 2809, 0, 2647, + 2807, 0, 2645, + 2805, 0, 2643, + 2801, 0, 2639, + 2795, 0, 2633, + 2789, 0, 2625, + 2779, 0, 2615, + 2767, 0, 2601, + 2749, 852, 2581, + 2725, 1254, 2553, + 2689, 1518, 2513, + 2637, 1728, 2455, + 2557, 1911, 2361, + 2423, 2077, 2193, + 2141, 2235, 1787, + 0, 2383, 0, + 0, 2529, 0, + 0, 2669, 0, + 0, 2809, 0, + 0, 2945, 0, + 0, 3081, 0, + 0, 3217, 0, + 0, 3351, 0, + 0, 3483, 0, + 0, 3617, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 2943, 0, 2777, + 2943, 0, 2777, + 2943, 0, 2777, + 2941, 0, 2775, + 2941, 0, 2775, + 2939, 0, 2773, + 2937, 0, 2771, + 2935, 0, 2767, + 2931, 0, 2763, + 2925, 0, 2757, + 2919, 0, 2749, + 2909, 0, 2739, + 2897, 0, 2725, + 2879, 924, 2705, + 2855, 1363, 2677, + 2819, 1637, 2635, + 2767, 1852, 2575, + 2687, 2038, 2479, + 2549, 2207, 2305, + 2263, 2363, 1869, + 0, 2513, 0, + 0, 2659, 0, + 0, 2801, 0, + 0, 2939, 0, + 0, 3077, 0, + 0, 3213, 0, + 0, 3347, 0, + 0, 3483, 0, + 0, 3615, 0, + 0, 3749, 0, + 0, 3883, 0, + 0, 4015, 0, + 3075, 0, 2905, + 3075, 0, 2905, + 3073, 0, 2903, + 3073, 0, 2903, + 3073, 0, 2903, + 3071, 0, 2901, + 3069, 0, 2899, + 3067, 0, 2897, + 3065, 0, 2893, + 3061, 0, 2889, + 3055, 0, 2883, + 3049, 0, 2875, + 3039, 0, 2865, + 3027, 0, 2851, + 3009, 1006, 2831, + 2985, 1476, 2801, + 2949, 1759, 2761, + 2897, 1978, 2699, + 2815, 2165, 2601, + 2679, 2335, 2423, + 2389, 2493, 1959, + 0, 2645, 0, + 0, 2791, 0, + 0, 2931, 0, + 0, 3071, 0, + 0, 3209, 0, + 0, 3345, 0, + 0, 3479, 0, + 0, 3615, 0, + 0, 3747, 0, + 0, 3881, 0, + 0, 4015, 0, + 3205, 0, 3033, + 3205, 0, 3033, + 3205, 0, 3033, + 3205, 0, 3031, + 3205, 0, 3031, + 3203, 0, 3031, + 3203, 0, 3029, + 3201, 0, 3027, + 3199, 0, 3025, + 3195, 0, 3021, + 3193, 0, 3017, + 3187, 0, 3011, + 3181, 0, 3003, + 3171, 0, 2993, + 3157, 0, 2979, + 3141, 1096, 2957, + 3115, 1594, 2929, + 3079, 1883, 2887, + 3027, 2105, 2825, + 2945, 2295, 2725, + 2807, 2465, 2543, + 2515, 2625, 2057, + 0, 2775, 0, + 0, 2921, 0, + 0, 3063, 0, + 0, 3203, 0, + 0, 3341, 0, + 0, 3477, 0, + 0, 3611, 0, + 0, 3747, 0, + 0, 3879, 0, + 0, 4013, 0, + 3337, 0, 3163, + 3337, 0, 3163, + 3337, 0, 3161, + 3337, 0, 3161, + 3337, 0, 3161, + 3335, 0, 3161, + 3335, 0, 3159, + 3333, 0, 3157, + 3331, 0, 3155, + 3329, 0, 3153, + 3327, 0, 3151, + 3323, 0, 3147, + 3319, 0, 3141, + 3311, 0, 3133, + 3301, 0, 3121, + 3289, 0, 3107, + 3271, 1194, 3087, + 3247, 1715, 3057, + 3211, 2010, 3015, + 3157, 2233, 2951, + 3077, 2425, 2851, + 2937, 2595, 2665, + 2645, 2755, 2161, + 0, 2907, 0, + 0, 3053, 0, + 0, 3195, 0, + 0, 3335, 0, + 0, 3473, 0, + 0, 3609, 0, + 0, 3743, 0, + 0, 3879, 0, + 0, 4011, 0, + 3469, 0, 3293, + 3469, 0, 3293, + 3469, 0, 3291, + 3469, 0, 3291, + 3469, 0, 3291, + 3467, 0, 3291, + 3467, 0, 3289, + 3467, 0, 3289, + 3465, 0, 3287, + 3463, 0, 3285, + 3461, 0, 3283, + 3459, 0, 3281, + 3455, 0, 3275, + 3449, 0, 3269, + 3443, 0, 3263, + 3433, 0, 3251, + 3421, 0, 3237, + 3403, 1299, 3215, + 3377, 1839, 3187, + 3341, 2137, 3143, + 3289, 2363, 3079, + 3207, 2555, 2977, + 3069, 2727, 2791, + 2773, 2887, 2273, + 0, 3039, 0, + 0, 3185, 0, + 0, 3327, 0, + 0, 3467, 0, + 0, 3605, 0, + 0, 3741, 0, + 0, 3875, 0, + 0, 4011, 0, + 3601, 0, 3423, + 3601, 0, 3423, + 3601, 0, 3423, + 3601, 0, 3423, + 3601, 0, 3421, + 3599, 0, 3421, + 3599, 0, 3421, + 3599, 0, 3421, + 3597, 0, 3419, + 3597, 0, 3417, + 3595, 0, 3417, + 3593, 0, 3413, + 3591, 0, 3411, + 3587, 0, 3407, + 3581, 0, 3401, + 3575, 0, 3393, + 3565, 0, 3381, + 3553, 0, 3367, + 3535, 1410, 3345, + 3509, 1964, 3317, + 3473, 2267, 3273, + 3421, 2493, 3209, + 3339, 2685, 3107, + 3199, 2857, 2917, + 2903, 3019, 2389, + 0, 3169, 0, + 0, 3317, 0, + 0, 3459, 0, + 0, 3599, 0, + 0, 3737, 0, + 0, 3873, 0, + 0, 4007, 0, + 3733, 0, 3553, + 3733, 0, 3553, + 3733, 0, 3553, + 3733, 0, 3553, + 3733, 0, 3553, + 3731, 0, 3553, + 3731, 0, 3553, + 3731, 0, 3551, + 3731, 0, 3551, + 3729, 0, 3551, + 3729, 0, 3549, + 3727, 0, 3547, + 3725, 0, 3545, + 3721, 0, 3541, + 3719, 0, 3537, + 3713, 0, 3531, + 3707, 0, 3523, + 3697, 0, 3513, + 3683, 0, 3497, + 3665, 1525, 3477, + 3641, 2091, 3447, + 3605, 2395, 3403, + 3553, 2625, 3339, + 3471, 2817, 3235, + 3331, 2989, 3045, + 3033, 3149, 2507, + 0, 3301, 0, + 0, 3449, 0, + 0, 3591, 0, + 0, 3731, 0, + 0, 3869, 0, + 0, 4005, 0, + 3865, 0, 3685, + 3865, 0, 3685, + 3865, 0, 3685, + 3865, 0, 3685, + 3865, 0, 3685, + 3865, 0, 3685, + 3863, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3683, + 3861, 0, 3681, + 3861, 0, 3679, + 3859, 0, 3679, + 3857, 0, 3675, + 3853, 0, 3673, + 3851, 0, 3669, + 3845, 0, 3663, + 3837, 0, 3655, + 3829, 0, 3643, + 3815, 0, 3629, + 3797, 1645, 3607, + 3773, 2221, 3577, + 3737, 2527, 3535, + 3683, 2755, 3469, + 3601, 2949, 3367, + 3463, 3121, 3175, + 3165, 3281, 2629, + 0, 3433, 0, + 0, 3581, 0, + 0, 3723, 0, + 0, 3863, 0, + 0, 4001, 0, + 3997, 0, 3817, + 3997, 0, 3817, + 3997, 0, 3817, + 3997, 0, 3817, + 3997, 0, 3815, + 3997, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3813, + 3993, 0, 3813, + 3993, 0, 3811, + 3991, 0, 3809, + 3989, 0, 3807, + 3985, 0, 3803, + 3981, 0, 3799, + 3977, 0, 3793, + 3969, 0, 3785, + 3961, 0, 3775, + 3947, 0, 3759, + 3929, 1767, 3739, + 3905, 2349, 3709, + 3869, 2657, 3665, + 3815, 2887, 3601, + 3733, 3079, 3497, + 3593, 3253, 3305, + 3295, 3413, 2755, + 0, 3565, 0, + 0, 3713, 0, + 0, 3855, 0, + 0, 3995, 0, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3943, + 4095, 0, 3941, + 4095, 0, 3939, + 4095, 0, 3935, + 4095, 0, 3931, + 4095, 0, 3925, + 4095, 0, 3917, + 4093, 0, 3907, + 4079, 0, 3891, + 4061, 1892, 3869, + 4037, 2479, 3841, + 4001, 2787, 3797, + 3947, 3017, 3733, + 3865, 3211, 3627, + 3725, 3385, 3435, + 3427, 3545, 2881, + 0, 3697, 0, + 0, 3845, 0, + 0, 3987, 0, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4075, + 4095, 0, 4075, + 4095, 0, 4073, + 4095, 0, 4071, + 4095, 0, 4067, + 4095, 0, 4063, + 4095, 0, 4057, + 4095, 0, 4049, + 4095, 0, 4037, + 4095, 0, 4023, + 4095, 2018, 4001, + 4095, 2611, 3971, + 4095, 2919, 3929, + 4079, 3149, 3863, + 3997, 3343, 3759, + 3857, 3517, 3567, + 3559, 3677, 3009, + 0, 3829, 0, + 0, 3977, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2145, 4095, + 4095, 2741, 4095, + 4095, 3051, 4061, + 4095, 3281, 3995, + 4095, 3475, 3891, + 3989, 3649, 3697, + 3691, 3809, 3137, + 0, 3961, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2275, 4095, + 4095, 2873, 4095, + 4095, 3183, 4095, + 4095, 3413, 4095, + 4095, 3607, 4023, + 4095, 3781, 3829, + 3823, 3941, 3267, + 1129, 728, 1524, + 1102, 753, 1516, + 1064, 785, 1504, + 1008, 824, 1488, + 919, 872, 1466, + 763, 929, 1434, + 407, 995, 1388, + 0, 1071, 1319, + 0, 1156, 1205, + 0, 1249, 987, + 0, 1350, 201, + 0, 1457, 0, + 0, 1570, 0, + 0, 1687, 0, + 0, 1807, 0, + 0, 1930, 0, + 0, 2055, 0, + 0, 2183, 0, + 0, 2311, 0, + 0, 2441, 0, + 0, 2571, 0, + 0, 2701, 0, + 0, 2831, 0, + 0, 2963, 0, + 0, 3095, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1161, 724, 1533, + 1136, 750, 1525, + 1100, 782, 1514, + 1048, 821, 1498, + 968, 869, 1476, + 832, 926, 1445, + 544, 993, 1401, + 0, 1069, 1333, + 0, 1154, 1223, + 0, 1248, 1016, + 0, 1349, 345, + 0, 1456, 0, + 0, 1569, 0, + 0, 1686, 0, + 0, 1807, 0, + 0, 1930, 0, + 0, 2055, 0, + 0, 2183, 0, + 0, 2311, 0, + 0, 2441, 0, + 0, 2569, 0, + 0, 2701, 0, + 0, 2831, 0, + 0, 2963, 0, + 0, 3095, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1200, 719, 1545, + 1177, 745, 1537, + 1145, 777, 1526, + 1098, 817, 1511, + 1026, 865, 1490, + 909, 923, 1460, + 681, 990, 1417, + 0, 1066, 1351, + 0, 1152, 1246, + 0, 1246, 1052, + 0, 1348, 486, + 0, 1455, 0, + 0, 1568, 0, + 0, 1686, 0, + 0, 1806, 0, + 0, 1930, 0, + 0, 2055, 0, + 0, 2183, 0, + 0, 2311, 0, + 0, 2439, 0, + 0, 2569, 0, + 0, 2701, 0, + 0, 2831, 0, + 0, 2963, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1248, 711, 1561, + 1227, 738, 1553, + 1198, 770, 1542, + 1157, 811, 1528, + 1095, 860, 1507, + 996, 918, 1478, + 816, 986, 1437, + 341, 1063, 1375, + 0, 1149, 1276, + 0, 1244, 1097, + 0, 1346, 625, + 0, 1454, 0, + 0, 1567, 0, + 0, 1685, 0, + 0, 1806, 0, + 0, 1929, 0, + 0, 2055, 0, + 0, 2183, 0, + 0, 2311, 0, + 0, 2439, 0, + 0, 2569, 0, + 0, 2701, 0, + 0, 2831, 0, + 0, 2963, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1304, 701, 1581, + 1286, 728, 1573, + 1261, 762, 1563, + 1225, 803, 1549, + 1172, 853, 1530, + 1090, 912, 1502, + 951, 981, 1463, + 651, 1058, 1405, + 0, 1146, 1312, + 0, 1241, 1150, + 0, 1343, 762, + 0, 1452, 0, + 0, 1566, 0, + 0, 1684, 0, + 0, 1805, 0, + 0, 1929, 0, + 0, 2055, 0, + 0, 2181, 0, + 0, 2311, 0, + 0, 2439, 0, + 0, 2569, 0, + 0, 2701, 0, + 0, 2831, 0, + 0, 2963, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1371, 688, 1606, + 1355, 715, 1599, + 1334, 750, 1589, + 1303, 792, 1576, + 1259, 843, 1558, + 1192, 903, 1532, + 1084, 973, 1496, + 882, 1052, 1441, + 253, 1140, 1357, + 0, 1237, 1213, + 0, 1340, 897, + 0, 1449, 0, + 0, 1564, 0, + 0, 1682, 0, + 0, 1804, 0, + 0, 1928, 0, + 0, 2053, 0, + 0, 2181, 0, + 0, 2309, 0, + 0, 2439, 0, + 0, 2569, 0, + 0, 2701, 0, + 0, 2831, 0, + 0, 2963, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1447, 669, 1638, + 1434, 697, 1631, + 1416, 733, 1622, + 1390, 777, 1610, + 1354, 829, 1593, + 1301, 891, 1569, + 1218, 963, 1536, + 1076, 1044, 1486, + 771, 1134, 1411, + 0, 1231, 1285, + 0, 1336, 1032, + 0, 1446, 0, + 0, 1561, 0, + 0, 1680, 0, + 0, 1802, 0, + 0, 1926, 0, + 0, 2053, 0, + 0, 2181, 0, + 0, 2309, 0, + 0, 2439, 0, + 0, 2569, 0, + 0, 2699, 0, + 0, 2831, 0, + 0, 2963, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1532, 642, 1677, + 1521, 672, 1671, + 1506, 710, 1663, + 1485, 756, 1652, + 1456, 811, 1636, + 1414, 875, 1615, + 1351, 949, 1585, + 1249, 1032, 1541, + 1065, 1124, 1474, + 561, 1224, 1367, + 0, 1330, 1166, + 0, 1441, 551, + 0, 1557, 0, + 0, 1677, 0, + 0, 1800, 0, + 0, 1925, 0, + 0, 2051, 0, + 0, 2179, 0, + 0, 2309, 0, + 0, 2439, 0, + 0, 2569, 0, + 0, 2699, 0, + 0, 2831, 0, + 0, 2963, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1625, 603, 1725, + 1616, 636, 1720, + 1604, 677, 1712, + 1588, 726, 1702, + 1565, 785, 1688, + 1532, 853, 1669, + 1484, 930, 1643, + 1410, 1017, 1604, + 1289, 1111, 1547, + 1049, 1213, 1457, + 0, 1321, 1300, + 0, 1435, 934, + 0, 1552, 0, + 0, 1673, 0, + 0, 1797, 0, + 0, 1923, 0, + 0, 2049, 0, + 0, 2179, 0, + 0, 2307, 0, + 0, 2437, 0, + 0, 2569, 0, + 0, 2699, 0, + 0, 2831, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1726, 546, 1782, + 1719, 583, 1777, + 1709, 629, 1771, + 1696, 683, 1762, + 1678, 747, 1750, + 1653, 820, 1733, + 1616, 903, 1710, + 1563, 994, 1677, + 1479, 1093, 1629, + 1336, 1199, 1555, + 1028, 1310, 1433, + 0, 1426, 1191, + 0, 1546, 0, + 0, 1668, 0, + 0, 1793, 0, + 0, 1920, 0, + 0, 2047, 0, + 0, 2177, 0, + 0, 2307, 0, + 0, 2437, 0, + 0, 2567, 0, + 0, 2699, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1833, 456, 1848, + 1827, 501, 1844, + 1820, 555, 1839, + 1810, 618, 1831, + 1796, 691, 1821, + 1776, 774, 1807, + 1749, 864, 1787, + 1709, 963, 1759, + 1650, 1068, 1719, + 1558, 1179, 1660, + 1393, 1295, 1566, + 997, 1414, 1398, + 0, 1537, 988, + 0, 1661, 0, + 0, 1788, 0, + 0, 1916, 0, + 0, 2045, 0, + 0, 2175, 0, + 0, 2305, 0, + 0, 2435, 0, + 0, 2567, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1946, 299, 1925, + 1941, 362, 1921, + 1935, 433, 1916, + 1928, 514, 1910, + 1917, 604, 1901, + 1902, 702, 1889, + 1881, 807, 1873, + 1852, 917, 1850, + 1810, 1032, 1818, + 1746, 1151, 1771, + 1645, 1273, 1698, + 1460, 1398, 1580, + 953, 1524, 1348, + 0, 1652, 351, + 0, 1781, 0, + 0, 1910, 0, + 0, 2041, 0, + 0, 2171, 0, + 0, 2303, 0, + 0, 2433, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2063, 0, 2010, + 2059, 63, 2007, + 2055, 193, 2003, + 2049, 323, 1998, + 2040, 454, 1990, + 2029, 585, 1981, + 2014, 716, 1967, + 1992, 848, 1949, + 1961, 979, 1923, + 1917, 1111, 1886, + 1850, 1243, 1831, + 1740, 1375, 1745, + 1536, 1507, 1598, + 886, 1639, 1271, + 0, 1771, 0, + 0, 1903, 0, + 0, 2035, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2183, 0, 2103, + 2181, 0, 2101, + 2177, 0, 2097, + 2173, 0, 2093, + 2167, 115, 2087, + 2157, 358, 2079, + 2145, 557, 2069, + 2129, 734, 2055, + 2107, 897, 2034, + 2075, 1051, 2005, + 2029, 1199, 1964, + 1959, 1342, 1901, + 1843, 1483, 1801, + 1621, 1621, 1621, + 778, 1758, 1141, + 0, 1893, 0, + 0, 2028, 0, + 0, 2161, 0, + 0, 2295, 0, + 0, 2429, 0, + 0, 2561, 0, + 0, 2693, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2307, 0, 2205, + 2305, 0, 2203, + 2301, 0, 2199, + 2299, 0, 2197, + 2293, 0, 2191, + 2287, 0, 2185, + 2279, 185, 2177, + 2267, 518, 2165, + 2249, 757, 2149, + 2227, 956, 2127, + 2193, 1132, 2095, + 2145, 1295, 2051, + 2073, 1448, 1981, + 1952, 1596, 1867, + 1714, 1739, 1650, + 575, 1879, 876, + 0, 2018, 0, + 0, 2155, 0, + 0, 2289, 0, + 0, 2425, 0, + 0, 2559, 0, + 0, 2691, 0, + 0, 2825, 0, + 0, 2957, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2431, 0, 2311, + 2429, 0, 2309, + 2427, 0, 2307, + 2425, 0, 2305, + 2421, 0, 2301, + 2417, 0, 2297, + 2411, 0, 2291, + 2401, 0, 2281, + 2389, 459, 2269, + 2373, 787, 2251, + 2349, 1024, 2229, + 2315, 1222, 2195, + 2267, 1398, 2145, + 2191, 1560, 2069, + 2065, 1713, 1942, + 1815, 1860, 1686, + 0, 2004, 0, + 0, 2143, 0, + 0, 2281, 0, + 0, 2419, 0, + 0, 2553, 0, + 0, 2689, 0, + 0, 2823, 0, + 0, 2955, 0, + 0, 3089, 0, + 0, 3221, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3885, 0, + 0, 4017, 0, + 2559, 0, 2425, + 2557, 0, 2423, + 2555, 0, 2421, + 2553, 0, 2419, + 2551, 0, 2417, + 2547, 0, 2413, + 2543, 0, 2407, + 2535, 0, 2401, + 2527, 0, 2391, + 2515, 366, 2379, + 2497, 823, 2361, + 2473, 1102, 2335, + 2439, 1320, 2299, + 2389, 1507, 2247, + 2313, 1676, 2165, + 2183, 1834, 2026, + 1923, 1984, 1731, + 0, 2129, 0, + 0, 2271, 0, + 0, 2411, 0, + 0, 2549, 0, + 0, 2685, 0, + 0, 2819, 0, + 0, 2953, 0, + 0, 3087, 0, + 0, 3221, 0, + 0, 3353, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4017, 0, + 2687, 0, 2541, + 2685, 0, 2541, + 2685, 0, 2539, + 2683, 0, 2537, + 2681, 0, 2535, + 2679, 0, 2533, + 2675, 0, 2529, + 2669, 0, 2523, + 2663, 0, 2515, + 2653, 0, 2507, + 2641, 201, 2493, + 2625, 868, 2475, + 2599, 1189, 2449, + 2565, 1424, 2411, + 2515, 1621, 2355, + 2437, 1796, 2269, + 2305, 1957, 2119, + 2035, 2111, 1784, + 0, 2257, 0, + 0, 2401, 0, + 0, 2541, 0, + 0, 2679, 0, + 0, 2815, 0, + 0, 2951, 0, + 0, 3085, 0, + 0, 3219, 0, + 0, 3353, 0, + 0, 3485, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 2815, 0, 2661, + 2815, 0, 2661, + 2815, 0, 2659, + 2813, 0, 2659, + 2811, 0, 2657, + 2809, 0, 2655, + 2807, 0, 2651, + 2803, 0, 2647, + 2799, 0, 2643, + 2791, 0, 2635, + 2783, 0, 2625, + 2769, 0, 2611, + 2753, 921, 2591, + 2727, 1284, 2565, + 2693, 1535, 2527, + 2641, 1739, 2469, + 2563, 1918, 2379, + 2429, 2083, 2219, + 2153, 2237, 1847, + 0, 2387, 0, + 0, 2531, 0, + 0, 2671, 0, + 0, 2809, 0, + 0, 2947, 0, + 0, 3081, 0, + 0, 3217, 0, + 0, 3351, 0, + 0, 3485, 0, + 0, 3617, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 2945, 0, 2785, + 2945, 0, 2785, + 2945, 0, 2783, + 2943, 0, 2783, + 2943, 0, 2781, + 2941, 0, 2779, + 2939, 0, 2777, + 2937, 0, 2775, + 2933, 0, 2771, + 2927, 0, 2765, + 2921, 0, 2757, + 2911, 0, 2747, + 2899, 0, 2733, + 2881, 984, 2713, + 2857, 1386, 2685, + 2821, 1650, 2645, + 2769, 1860, 2587, + 2689, 2043, 2493, + 2555, 2209, 2325, + 2273, 2367, 1919, + 0, 2515, 0, + 0, 2661, 0, + 0, 2801, 0, + 0, 2941, 0, + 0, 3077, 0, + 0, 3213, 0, + 0, 3349, 0, + 0, 3483, 0, + 0, 3617, 0, + 0, 3749, 0, + 0, 3883, 0, + 0, 4015, 0, + 3077, 0, 2911, + 3075, 0, 2909, + 3075, 0, 2909, + 3075, 0, 2909, + 3073, 0, 2907, + 3073, 0, 2907, + 3071, 0, 2905, + 3069, 0, 2903, + 3067, 0, 2899, + 3063, 0, 2895, + 3057, 0, 2889, + 3051, 0, 2881, + 3041, 0, 2871, + 3029, 0, 2857, + 3011, 1056, 2837, + 2987, 1495, 2809, + 2951, 1769, 2767, + 2899, 1984, 2707, + 2819, 2169, 2611, + 2683, 2339, 2439, + 2395, 2495, 2001, + 0, 2645, 0, + 0, 2791, 0, + 0, 2933, 0, + 0, 3071, 0, + 0, 3209, 0, + 0, 3345, 0, + 0, 3481, 0, + 0, 3615, 0, + 0, 3747, 0, + 0, 3881, 0, + 0, 4015, 0, + 3207, 0, 3037, + 3207, 0, 3037, + 3207, 0, 3037, + 3207, 0, 3035, + 3205, 0, 3035, + 3205, 0, 3035, + 3203, 0, 3033, + 3201, 0, 3031, + 3199, 0, 3029, + 3197, 0, 3025, + 3193, 0, 3021, + 3189, 0, 3015, + 3181, 0, 3007, + 3171, 0, 2997, + 3159, 0, 2983, + 3141, 1138, 2963, + 3117, 1608, 2933, + 3081, 1891, 2893, + 3029, 2111, 2831, + 2947, 2297, 2733, + 2811, 2467, 2555, + 2521, 2625, 2091, + 0, 2777, 0, + 0, 2923, 0, + 0, 3065, 0, + 0, 3203, 0, + 0, 3341, 0, + 0, 3477, 0, + 0, 3611, 0, + 0, 3747, 0, + 0, 3879, 0, + 0, 4013, 0, + 3339, 0, 3165, + 3339, 0, 3165, + 3337, 0, 3165, + 3337, 0, 3165, + 3337, 0, 3163, + 3337, 0, 3163, + 3335, 0, 3163, + 3335, 0, 3161, + 3333, 0, 3159, + 3331, 0, 3157, + 3327, 0, 3153, + 3325, 0, 3149, + 3319, 0, 3143, + 3313, 0, 3135, + 3303, 0, 3125, + 3289, 0, 3111, + 3273, 1228, 3089, + 3247, 1726, 3061, + 3211, 2015, 3019, + 3159, 2237, 2957, + 3077, 2427, 2857, + 2941, 2597, 2675, + 2649, 2757, 2189, + 0, 2907, 0, + 0, 3053, 0, + 0, 3195, 0, + 0, 3335, 0, + 0, 3473, 0, + 0, 3609, 0, + 0, 3743, 0, + 0, 3879, 0, + 0, 4013, 0, + 3469, 0, 3295, + 3469, 0, 3295, + 3469, 0, 3295, + 3469, 0, 3293, + 3469, 0, 3293, + 3469, 0, 3293, + 3467, 0, 3293, + 3467, 0, 3291, + 3465, 0, 3289, + 3465, 0, 3289, + 3461, 0, 3285, + 3459, 0, 3283, + 3455, 0, 3279, + 3451, 0, 3273, + 3443, 0, 3265, + 3435, 0, 3253, + 3421, 0, 3239, + 3403, 1326, 3219, + 3379, 1847, 3189, + 3343, 2141, 3147, + 3291, 2365, 3083, + 3209, 2557, 2983, + 3071, 2727, 2797, + 2777, 2887, 2295, + 0, 3039, 0, + 0, 3185, 0, + 0, 3327, 0, + 0, 3467, 0, + 0, 3605, 0, + 0, 3741, 0, + 0, 3875, 0, + 0, 4011, 0, + 3601, 0, 3425, + 3601, 0, 3425, + 3601, 0, 3425, + 3601, 0, 3423, + 3601, 0, 3423, + 3601, 0, 3423, + 3599, 0, 3423, + 3599, 0, 3421, + 3599, 0, 3421, + 3597, 0, 3419, + 3595, 0, 3417, + 3593, 0, 3415, + 3591, 0, 3413, + 3587, 0, 3407, + 3581, 0, 3403, + 3575, 0, 3395, + 3565, 0, 3383, + 3553, 0, 3369, + 3535, 1431, 3347, + 3509, 1971, 3319, + 3473, 2269, 3275, + 3421, 2495, 3213, + 3339, 2687, 3109, + 3201, 2859, 2923, + 2905, 3019, 2405, + 0, 3171, 0, + 0, 3317, 0, + 0, 3459, 0, + 0, 3599, 0, + 0, 3737, 0, + 0, 3873, 0, + 0, 4007, 0, + 3733, 0, 3555, + 3733, 0, 3555, + 3733, 0, 3555, + 3733, 0, 3555, + 3733, 0, 3555, + 3733, 0, 3555, + 3731, 0, 3553, + 3731, 0, 3553, + 3731, 0, 3553, + 3729, 0, 3551, + 3729, 0, 3551, + 3727, 0, 3549, + 3725, 0, 3545, + 3723, 0, 3543, + 3719, 0, 3539, + 3713, 0, 3533, + 3707, 0, 3525, + 3697, 0, 3513, + 3685, 0, 3499, + 3667, 1542, 3477, + 3641, 2097, 3449, + 3605, 2399, 3405, + 3553, 2625, 3341, + 3471, 2817, 3239, + 3331, 2991, 3049, + 3035, 3151, 2521, + 0, 3303, 0, + 0, 3449, 0, + 0, 3591, 0, + 0, 3731, 0, + 0, 3869, 0, + 0, 4005, 0, + 3865, 0, 3685, + 3865, 0, 3685, + 3865, 0, 3685, + 3865, 0, 3685, + 3865, 0, 3685, + 3865, 0, 3685, + 3865, 0, 3685, + 3863, 0, 3685, + 3863, 0, 3683, + 3863, 0, 3683, + 3861, 0, 3683, + 3861, 0, 3681, + 3859, 0, 3679, + 3857, 0, 3677, + 3855, 0, 3673, + 3851, 0, 3669, + 3845, 0, 3663, + 3839, 0, 3655, + 3829, 0, 3645, + 3815, 0, 3629, + 3797, 1658, 3609, + 3773, 2223, 3579, + 3737, 2527, 3535, + 3685, 2757, 3471, + 3603, 2949, 3369, + 3463, 3121, 3177, + 3165, 3281, 2639, + 0, 3433, 0, + 0, 3581, 0, + 0, 3723, 0, + 0, 3863, 0, + 0, 4001, 0, + 3997, 0, 3817, + 3997, 0, 3817, + 3997, 0, 3817, + 3997, 0, 3817, + 3997, 0, 3817, + 3997, 0, 3817, + 3997, 0, 3817, + 3995, 0, 3817, + 3995, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3815, + 3993, 0, 3813, + 3993, 0, 3811, + 3991, 0, 3811, + 3989, 0, 3807, + 3985, 0, 3805, + 3983, 0, 3801, + 3977, 0, 3795, + 3971, 0, 3787, + 3961, 0, 3775, + 3947, 0, 3761, + 3929, 1777, 3739, + 3905, 2353, 3709, + 3869, 2659, 3667, + 3815, 2887, 3603, + 3733, 3081, 3499, + 3595, 3253, 3307, + 3297, 3413, 2761, + 0, 3565, 0, + 0, 3713, 0, + 0, 3855, 0, + 0, 3995, 0, + 4095, 0, 3949, + 4095, 0, 3949, + 4095, 0, 3949, + 4095, 0, 3949, + 4095, 0, 3949, + 4095, 0, 3949, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3943, + 4095, 0, 3941, + 4095, 0, 3939, + 4095, 0, 3935, + 4095, 0, 3931, + 4095, 0, 3925, + 4095, 0, 3917, + 4093, 0, 3907, + 4079, 0, 3891, + 4061, 1899, 3871, + 4037, 2481, 3841, + 4001, 2789, 3797, + 3947, 3019, 3733, + 3865, 3211, 3629, + 3727, 3385, 3437, + 3429, 3545, 2887, + 0, 3697, 0, + 0, 3845, 0, + 0, 3987, 0, + 4095, 0, 4081, + 4095, 0, 4081, + 4095, 0, 4081, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4075, + 4095, 0, 4073, + 4095, 0, 4071, + 4095, 0, 4067, + 4095, 0, 4063, + 4095, 0, 4057, + 4095, 0, 4049, + 4095, 0, 4039, + 4095, 0, 4023, + 4095, 2024, 4001, + 4095, 2611, 3973, + 4095, 2919, 3929, + 4079, 3149, 3865, + 3997, 3343, 3759, + 3857, 3517, 3567, + 3559, 3677, 3013, + 0, 3829, 0, + 0, 3977, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2151, 4095, + 4095, 2743, 4095, + 4095, 3051, 4061, + 4095, 3281, 3995, + 4095, 3475, 3891, + 3989, 3649, 3699, + 3691, 3809, 3141, + 0, 3961, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2277, 4095, + 4095, 2873, 4095, + 4095, 3183, 4095, + 4095, 3413, 4095, + 4095, 3607, 4023, + 4095, 3781, 3829, + 3823, 3941, 3269, + 1256, 844, 1656, + 1236, 863, 1649, + 1208, 888, 1641, + 1167, 920, 1629, + 1106, 959, 1613, + 1010, 1006, 1590, + 837, 1063, 1558, + 399, 1129, 1511, + 0, 1204, 1440, + 0, 1289, 1323, + 0, 1382, 1096, + 0, 1483, 185, + 0, 1590, 0, + 0, 1702, 0, + 0, 1819, 0, + 0, 1940, 0, + 0, 2063, 0, + 0, 2189, 0, + 0, 2315, 0, + 0, 2443, 0, + 0, 2573, 0, + 0, 2703, 0, + 0, 2833, 0, + 0, 2963, 0, + 0, 3095, 0, + 0, 3227, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1280, 840, 1662, + 1261, 860, 1656, + 1234, 886, 1648, + 1196, 917, 1636, + 1139, 957, 1620, + 1050, 1004, 1598, + 896, 1061, 1566, + 539, 1127, 1520, + 0, 1203, 1451, + 0, 1288, 1337, + 0, 1381, 1119, + 0, 1482, 333, + 0, 1589, 0, + 0, 1702, 0, + 0, 1819, 0, + 0, 1939, 0, + 0, 2063, 0, + 0, 2187, 0, + 0, 2315, 0, + 0, 2443, 0, + 0, 2573, 0, + 0, 2703, 0, + 0, 2833, 0, + 0, 2963, 0, + 0, 3095, 0, + 0, 3227, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1310, 836, 1671, + 1293, 856, 1665, + 1268, 882, 1657, + 1233, 914, 1646, + 1180, 953, 1630, + 1100, 1001, 1608, + 964, 1058, 1578, + 676, 1125, 1533, + 0, 1201, 1465, + 0, 1286, 1355, + 0, 1380, 1148, + 0, 1481, 478, + 0, 1589, 0, + 0, 1701, 0, + 0, 1818, 0, + 0, 1939, 0, + 0, 2063, 0, + 0, 2187, 0, + 0, 2315, 0, + 0, 2443, 0, + 0, 2573, 0, + 0, 2703, 0, + 0, 2833, 0, + 0, 2963, 0, + 0, 3095, 0, + 0, 3227, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1348, 831, 1683, + 1332, 851, 1677, + 1309, 877, 1669, + 1277, 909, 1658, + 1230, 949, 1643, + 1159, 997, 1622, + 1041, 1055, 1592, + 813, 1122, 1549, + 0, 1199, 1483, + 0, 1284, 1378, + 0, 1378, 1184, + 0, 1480, 618, + 0, 1588, 0, + 0, 1701, 0, + 0, 1818, 0, + 0, 1938, 0, + 0, 2061, 0, + 0, 2187, 0, + 0, 2315, 0, + 0, 2443, 0, + 0, 2573, 0, + 0, 2703, 0, + 0, 2833, 0, + 0, 2963, 0, + 0, 3095, 0, + 0, 3227, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1394, 823, 1698, + 1380, 844, 1693, + 1359, 870, 1685, + 1331, 903, 1674, + 1289, 943, 1660, + 1227, 992, 1639, + 1128, 1050, 1611, + 948, 1118, 1569, + 474, 1195, 1507, + 0, 1282, 1408, + 0, 1376, 1229, + 0, 1478, 757, + 0, 1586, 0, + 0, 1699, 0, + 0, 1817, 0, + 0, 1938, 0, + 0, 2061, 0, + 0, 2187, 0, + 0, 2315, 0, + 0, 2443, 0, + 0, 2571, 0, + 0, 2701, 0, + 0, 2833, 0, + 0, 2963, 0, + 0, 3095, 0, + 0, 3227, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1449, 812, 1718, + 1437, 834, 1713, + 1419, 860, 1705, + 1393, 894, 1695, + 1358, 935, 1681, + 1305, 985, 1662, + 1222, 1044, 1634, + 1082, 1112, 1595, + 784, 1191, 1537, + 0, 1278, 1445, + 0, 1373, 1282, + 0, 1476, 894, + 0, 1584, 0, + 0, 1698, 0, + 0, 1816, 0, + 0, 1937, 0, + 0, 2061, 0, + 0, 2187, 0, + 0, 2313, 0, + 0, 2443, 0, + 0, 2571, 0, + 0, 2701, 0, + 0, 2833, 0, + 0, 2963, 0, + 0, 3095, 0, + 0, 3227, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1514, 798, 1743, + 1503, 820, 1738, + 1487, 847, 1731, + 1466, 882, 1721, + 1435, 924, 1708, + 1391, 975, 1690, + 1324, 1035, 1664, + 1216, 1105, 1628, + 1014, 1184, 1574, + 385, 1273, 1489, + 0, 1369, 1345, + 0, 1472, 1029, + 0, 1582, 0, + 0, 1696, 0, + 0, 1814, 0, + 0, 1936, 0, + 0, 2059, 0, + 0, 2185, 0, + 0, 2313, 0, + 0, 2441, 0, + 0, 2571, 0, + 0, 2701, 0, + 0, 2833, 0, + 0, 2963, 0, + 0, 3095, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1588, 778, 1775, + 1579, 801, 1770, + 1566, 829, 1763, + 1548, 865, 1754, + 1522, 909, 1742, + 1486, 962, 1725, + 1433, 1023, 1702, + 1350, 1095, 1668, + 1208, 1176, 1619, + 903, 1266, 1543, + 0, 1363, 1417, + 0, 1468, 1164, + 0, 1578, 0, + 0, 1693, 0, + 0, 1812, 0, + 0, 1934, 0, + 0, 2059, 0, + 0, 2185, 0, + 0, 2313, 0, + 0, 2441, 0, + 0, 2571, 0, + 0, 2701, 0, + 0, 2831, 0, + 0, 2963, 0, + 0, 3095, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1672, 750, 1814, + 1664, 774, 1809, + 1653, 804, 1803, + 1638, 842, 1795, + 1617, 888, 1784, + 1588, 943, 1768, + 1546, 1007, 1747, + 1483, 1081, 1717, + 1382, 1164, 1673, + 1197, 1256, 1606, + 693, 1356, 1499, + 0, 1462, 1298, + 0, 1573, 683, + 0, 1689, 0, + 0, 1809, 0, + 0, 1932, 0, + 0, 2057, 0, + 0, 2183, 0, + 0, 2311, 0, + 0, 2441, 0, + 0, 2571, 0, + 0, 2701, 0, + 0, 2831, 0, + 0, 2963, 0, + 0, 3095, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1764, 709, 1861, + 1757, 735, 1857, + 1748, 768, 1852, + 1736, 809, 1844, + 1720, 858, 1834, + 1697, 917, 1821, + 1664, 985, 1801, + 1616, 1062, 1775, + 1542, 1149, 1736, + 1421, 1243, 1679, + 1181, 1345, 1589, + 0, 1454, 1432, + 0, 1567, 1066, + 0, 1685, 0, + 0, 1805, 0, + 0, 1929, 0, + 0, 2055, 0, + 0, 2181, 0, + 0, 2311, 0, + 0, 2439, 0, + 0, 2569, 0, + 0, 2701, 0, + 0, 2831, 0, + 0, 2963, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1863, 648, 1918, + 1858, 678, 1914, + 1851, 715, 1909, + 1841, 761, 1903, + 1828, 815, 1894, + 1810, 879, 1882, + 1785, 953, 1865, + 1748, 1035, 1842, + 1695, 1126, 1809, + 1611, 1225, 1761, + 1469, 1331, 1687, + 1160, 1442, 1565, + 0, 1558, 1323, + 0, 1678, 55, + 0, 1800, 0, + 0, 1925, 0, + 0, 2051, 0, + 0, 2179, 0, + 0, 2309, 0, + 0, 2439, 0, + 0, 2569, 0, + 0, 2699, 0, + 0, 2831, 0, + 0, 2963, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1969, 552, 1984, + 1965, 588, 1981, + 1960, 633, 1976, + 1952, 687, 1971, + 1942, 751, 1963, + 1928, 824, 1953, + 1908, 906, 1939, + 1881, 997, 1919, + 1841, 1095, 1891, + 1783, 1200, 1852, + 1690, 1311, 1792, + 1526, 1427, 1698, + 1129, 1546, 1531, + 0, 1669, 1120, + 0, 1793, 0, + 0, 1920, 0, + 0, 2047, 0, + 0, 2177, 0, + 0, 2307, 0, + 0, 2437, 0, + 0, 2567, 0, + 0, 2699, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2081, 379, 2059, + 2077, 431, 2057, + 2073, 494, 2053, + 2067, 565, 2049, + 2059, 647, 2042, + 2049, 737, 2033, + 2034, 834, 2022, + 2013, 939, 2005, + 1984, 1049, 1982, + 1942, 1164, 1950, + 1879, 1283, 1903, + 1777, 1405, 1831, + 1592, 1530, 1712, + 1085, 1656, 1480, + 0, 1784, 483, + 0, 1913, 0, + 0, 2042, 0, + 0, 2173, 0, + 0, 2303, 0, + 0, 2435, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2197, 0, 2143, + 2195, 67, 2141, + 2191, 195, 2139, + 2187, 325, 2135, + 2181, 455, 2129, + 2173, 586, 2123, + 2161, 717, 2113, + 2145, 848, 2099, + 2125, 980, 2081, + 2093, 1111, 2055, + 2049, 1243, 2018, + 1982, 1375, 1963, + 1873, 1507, 1878, + 1668, 1639, 1730, + 1018, 1771, 1403, + 0, 1903, 0, + 0, 2035, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2317, 0, 2237, + 2315, 0, 2235, + 2313, 0, 2233, + 2309, 0, 2229, + 2305, 0, 2225, + 2299, 247, 2219, + 2289, 490, 2211, + 2279, 689, 2201, + 2261, 866, 2187, + 2239, 1029, 2167, + 2207, 1183, 2137, + 2161, 1331, 2095, + 2091, 1474, 2033, + 1975, 1615, 1934, + 1753, 1753, 1753, + 910, 1890, 1273, + 0, 2025, 0, + 0, 2159, 0, + 0, 2293, 0, + 0, 2427, 0, + 0, 2561, 0, + 0, 2693, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2439, 0, 2337, + 2439, 0, 2337, + 2437, 0, 2335, + 2433, 0, 2331, + 2431, 0, 2329, + 2425, 0, 2323, + 2419, 0, 2317, + 2411, 317, 2309, + 2399, 650, 2297, + 2381, 890, 2281, + 2359, 1088, 2259, + 2325, 1264, 2229, + 2279, 1427, 2183, + 2205, 1580, 2113, + 2085, 1728, 1999, + 1846, 1871, 1782, + 707, 2011, 1008, + 0, 2149, 0, + 0, 2287, 0, + 0, 2421, 0, + 0, 2557, 0, + 0, 2691, 0, + 0, 2823, 0, + 0, 2957, 0, + 0, 3089, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2565, 0, 2445, + 2563, 0, 2443, + 2563, 0, 2443, + 2561, 0, 2441, + 2557, 0, 2437, + 2553, 0, 2433, + 2549, 0, 2429, + 2543, 0, 2423, + 2533, 0, 2413, + 2521, 591, 2401, + 2505, 919, 2385, + 2481, 1156, 2361, + 2447, 1354, 2327, + 2399, 1530, 2277, + 2323, 1692, 2201, + 2199, 1845, 2075, + 1947, 1993, 1818, + 74, 2135, 0, + 0, 2275, 0, + 0, 2415, 0, + 0, 2551, 0, + 0, 2687, 0, + 0, 2821, 0, + 0, 2955, 0, + 0, 3087, 0, + 0, 3221, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3885, 0, + 0, 4017, 0, + 2691, 0, 2557, + 2691, 0, 2557, + 2689, 0, 2555, + 2687, 0, 2553, + 2685, 0, 2551, + 2683, 0, 2549, + 2679, 0, 2545, + 2675, 0, 2539, + 2669, 0, 2533, + 2659, 0, 2523, + 2647, 498, 2511, + 2629, 955, 2493, + 2605, 1234, 2467, + 2571, 1452, 2431, + 2521, 1639, 2379, + 2445, 1808, 2297, + 2315, 1966, 2159, + 2055, 2117, 1863, + 0, 2261, 0, + 0, 2403, 0, + 0, 2543, 0, + 0, 2681, 0, + 0, 2817, 0, + 0, 2951, 0, + 0, 3085, 0, + 0, 3219, 0, + 0, 3353, 0, + 0, 3485, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4017, 0, + 2819, 0, 2673, + 2819, 0, 2673, + 2817, 0, 2673, + 2817, 0, 2671, + 2815, 0, 2669, + 2813, 0, 2667, + 2811, 0, 2665, + 2807, 0, 2661, + 2801, 0, 2655, + 2795, 0, 2649, + 2787, 0, 2639, + 2773, 333, 2625, + 2757, 1000, 2607, + 2731, 1321, 2581, + 2697, 1556, 2543, + 2647, 1753, 2487, + 2569, 1928, 2401, + 2437, 2089, 2251, + 2167, 2243, 1916, + 0, 2389, 0, + 0, 2533, 0, + 0, 2673, 0, + 0, 2811, 0, + 0, 2947, 0, + 0, 3083, 0, + 0, 3217, 0, + 0, 3351, 0, + 0, 3485, 0, + 0, 3617, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 2949, 0, 2795, + 2947, 0, 2793, + 2947, 0, 2793, + 2947, 0, 2793, + 2945, 0, 2791, + 2943, 0, 2789, + 2941, 0, 2787, + 2939, 0, 2783, + 2935, 0, 2779, + 2931, 0, 2775, + 2923, 0, 2767, + 2915, 0, 2757, + 2901, 0, 2743, + 2885, 1053, 2725, + 2859, 1416, 2697, + 2825, 1667, 2659, + 2773, 1871, 2601, + 2695, 2051, 2511, + 2561, 2215, 2351, + 2285, 2369, 1979, + 0, 2519, 0, + 0, 2663, 0, + 0, 2803, 0, + 0, 2941, 0, + 0, 3079, 0, + 0, 3213, 0, + 0, 3349, 0, + 0, 3483, 0, + 0, 3617, 0, + 0, 3749, 0, + 0, 3883, 0, + 0, 4015, 0, + 3079, 0, 2917, + 3077, 0, 2917, + 3077, 0, 2917, + 3077, 0, 2915, + 3075, 0, 2915, + 3075, 0, 2913, + 3073, 0, 2911, + 3071, 0, 2909, + 3069, 0, 2907, + 3065, 0, 2903, + 3059, 0, 2897, + 3053, 0, 2889, + 3043, 0, 2879, + 3031, 0, 2865, + 3013, 1116, 2845, + 2989, 1518, 2817, + 2953, 1782, 2777, + 2901, 1992, 2719, + 2821, 2175, 2625, + 2687, 2341, 2459, + 2405, 2499, 2051, + 0, 2647, 0, + 0, 2793, 0, + 0, 2933, 0, + 0, 3073, 0, + 0, 3209, 0, + 0, 3345, 0, + 0, 3481, 0, + 0, 3615, 0, + 0, 3749, 0, + 0, 3881, 0, + 0, 4015, 0, + 3209, 0, 3043, + 3209, 0, 3043, + 3209, 0, 3041, + 3207, 0, 3041, + 3207, 0, 3041, + 3207, 0, 3039, + 3205, 0, 3039, + 3203, 0, 3037, + 3201, 0, 3035, + 3199, 0, 3031, + 3195, 0, 3027, + 3189, 0, 3021, + 3183, 0, 3013, + 3173, 0, 3003, + 3161, 0, 2989, + 3143, 1188, 2969, + 3119, 1627, 2941, + 3083, 1901, 2901, + 3031, 2117, 2839, + 2951, 2301, 2743, + 2815, 2471, 2571, + 2527, 2627, 2133, + 0, 2777, 0, + 0, 2923, 0, + 0, 3065, 0, + 0, 3203, 0, + 0, 3341, 0, + 0, 3477, 0, + 0, 3613, 0, + 0, 3747, 0, + 0, 3881, 0, + 0, 4013, 0, + 3339, 0, 3169, + 3339, 0, 3169, + 3339, 0, 3169, + 3339, 0, 3169, + 3339, 0, 3169, + 3337, 0, 3167, + 3337, 0, 3167, + 3335, 0, 3165, + 3333, 0, 3163, + 3331, 0, 3161, + 3329, 0, 3157, + 3325, 0, 3153, + 3321, 0, 3147, + 3313, 0, 3141, + 3305, 0, 3129, + 3291, 0, 3115, + 3273, 1270, 3095, + 3249, 1740, 3067, + 3213, 2023, 3025, + 3161, 2243, 2963, + 3079, 2429, 2865, + 2943, 2599, 2687, + 2653, 2757, 2223, + 0, 2909, 0, + 0, 3055, 0, + 0, 3197, 0, + 0, 3335, 0, + 0, 3473, 0, + 0, 3609, 0, + 0, 3745, 0, + 0, 3879, 0, + 0, 4013, 0, + 3471, 0, 3297, + 3471, 0, 3297, + 3471, 0, 3297, + 3469, 0, 3297, + 3469, 0, 3297, + 3469, 0, 3297, + 3469, 0, 3295, + 3467, 0, 3295, + 3467, 0, 3293, + 3465, 0, 3291, + 3463, 0, 3289, + 3461, 0, 3285, + 3457, 0, 3281, + 3451, 0, 3275, + 3445, 0, 3267, + 3435, 0, 3257, + 3423, 0, 3243, + 3405, 1360, 3221, + 3379, 1858, 3193, + 3343, 2147, 3151, + 3291, 2369, 3089, + 3211, 2559, 2989, + 3073, 2729, 2807, + 2781, 2889, 2321, + 0, 3039, 0, + 0, 3185, 0, + 0, 3327, 0, + 0, 3467, 0, + 0, 3605, 0, + 0, 3741, 0, + 0, 3877, 0, + 0, 4011, 0, + 3601, 0, 3427, + 3601, 0, 3427, + 3601, 0, 3427, + 3601, 0, 3427, + 3601, 0, 3427, + 3601, 0, 3425, + 3601, 0, 3425, + 3599, 0, 3425, + 3599, 0, 3423, + 3597, 0, 3423, + 3597, 0, 3421, + 3595, 0, 3417, + 3591, 0, 3415, + 3587, 0, 3411, + 3583, 0, 3405, + 3575, 0, 3397, + 3567, 0, 3385, + 3553, 0, 3371, + 3535, 1458, 3351, + 3511, 1979, 3321, + 3475, 2273, 3279, + 3423, 2499, 3215, + 3341, 2689, 3115, + 3203, 2861, 2929, + 2909, 3019, 2427, + 0, 3171, 0, + 0, 3317, 0, + 0, 3459, 0, + 0, 3599, 0, + 0, 3737, 0, + 0, 3873, 0, + 0, 4009, 0, + 3733, 0, 3557, + 3733, 0, 3557, + 3733, 0, 3557, + 3733, 0, 3557, + 3733, 0, 3557, + 3733, 0, 3555, + 3733, 0, 3555, + 3731, 0, 3555, + 3731, 0, 3555, + 3731, 0, 3553, + 3729, 0, 3551, + 3727, 0, 3551, + 3725, 0, 3547, + 3723, 0, 3545, + 3719, 0, 3541, + 3713, 0, 3535, + 3707, 0, 3527, + 3697, 0, 3515, + 3685, 0, 3501, + 3667, 1564, 3479, + 3641, 2103, 3451, + 3607, 2401, 3409, + 3553, 2627, 3345, + 3471, 2819, 3243, + 3333, 2991, 3055, + 3037, 3151, 2537, + 0, 3303, 0, + 0, 3449, 0, + 0, 3591, 0, + 0, 3731, 0, + 0, 3869, 0, + 0, 4005, 0, + 3865, 0, 3687, + 3865, 0, 3687, + 3865, 0, 3687, + 3865, 0, 3687, + 3865, 0, 3687, + 3865, 0, 3687, + 3865, 0, 3687, + 3865, 0, 3685, + 3863, 0, 3685, + 3863, 0, 3685, + 3863, 0, 3683, + 3861, 0, 3683, + 3859, 0, 3681, + 3857, 0, 3677, + 3855, 0, 3675, + 3851, 0, 3671, + 3845, 0, 3665, + 3839, 0, 3657, + 3829, 0, 3645, + 3817, 0, 3631, + 3799, 1674, 3609, + 3773, 2229, 3581, + 3737, 2531, 3537, + 3685, 2757, 3473, + 3603, 2949, 3371, + 3463, 3123, 3181, + 3167, 3283, 2653, + 0, 3435, 0, + 0, 3581, 0, + 0, 3723, 0, + 0, 3863, 0, + 0, 4001, 0, + 3997, 0, 3819, + 3997, 0, 3819, + 3997, 0, 3817, + 3997, 0, 3817, + 3997, 0, 3817, + 3997, 0, 3817, + 3997, 0, 3817, + 3997, 0, 3817, + 3995, 0, 3817, + 3995, 0, 3817, + 3995, 0, 3815, + 3993, 0, 3815, + 3993, 0, 3813, + 3991, 0, 3811, + 3989, 0, 3809, + 3987, 0, 3805, + 3983, 0, 3801, + 3977, 0, 3795, + 3971, 0, 3787, + 3961, 0, 3777, + 3949, 0, 3761, + 3931, 1790, 3741, + 3905, 2355, 3711, + 3869, 2661, 3669, + 3817, 2889, 3603, + 3735, 3081, 3501, + 3595, 3253, 3311, + 3299, 3413, 2771, + 0, 3567, 0, + 0, 3713, 0, + 0, 3855, 0, + 0, 3995, 0, + 4095, 0, 3949, + 4095, 0, 3949, + 4095, 0, 3949, + 4095, 0, 3949, + 4095, 0, 3949, + 4095, 0, 3949, + 4095, 0, 3949, + 4095, 0, 3949, + 4095, 0, 3949, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3943, + 4095, 0, 3939, + 4095, 0, 3937, + 4095, 0, 3933, + 4095, 0, 3927, + 4095, 0, 3919, + 4093, 0, 3907, + 4079, 0, 3893, + 4061, 1909, 3871, + 4037, 2485, 3841, + 4001, 2791, 3799, + 3949, 3019, 3735, + 3867, 3213, 3631, + 3727, 3385, 3439, + 3429, 3545, 2893, + 0, 3697, 0, + 0, 3845, 0, + 0, 3987, 0, + 4095, 0, 4081, + 4095, 0, 4081, + 4095, 0, 4081, + 4095, 0, 4081, + 4095, 0, 4081, + 4095, 0, 4081, + 4095, 0, 4081, + 4095, 0, 4081, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4075, + 4095, 0, 4073, + 4095, 0, 4071, + 4095, 0, 4069, + 4095, 0, 4063, + 4095, 0, 4057, + 4095, 0, 4049, + 4095, 0, 4039, + 4095, 0, 4023, + 4095, 2031, 4003, + 4095, 2613, 3973, + 4095, 2921, 3929, + 4079, 3151, 3865, + 3997, 3343, 3761, + 3859, 3517, 3569, + 3561, 3677, 3019, + 0, 3829, 0, + 0, 3977, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2155, 4095, + 4095, 2743, 4095, + 4095, 3053, 4061, + 4095, 3283, 3997, + 4095, 3475, 3893, + 3989, 3649, 3699, + 3691, 3809, 3145, + 0, 3961, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2283, 4095, + 4095, 2875, 4095, + 4095, 3183, 4095, + 4095, 3413, 4095, + 4095, 3607, 4023, + 4095, 3781, 3831, + 3823, 3941, 3273, + 1384, 963, 1787, + 1369, 978, 1782, + 1348, 998, 1776, + 1319, 1023, 1767, + 1276, 1054, 1755, + 1212, 1093, 1739, + 1109, 1140, 1716, + 920, 1196, 1684, + 388, 1262, 1636, + 0, 1338, 1564, + 0, 1422, 1444, + 0, 1515, 1210, + 0, 1616, 161, + 0, 1723, 0, + 0, 1835, 0, + 0, 1952, 0, + 0, 2071, 0, + 0, 2195, 0, + 0, 2321, 0, + 0, 2447, 0, + 0, 2575, 0, + 0, 2705, 0, + 0, 2835, 0, + 0, 2965, 0, + 0, 3095, 0, + 0, 3227, 0, + 0, 3359, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1402, 960, 1792, + 1388, 976, 1788, + 1368, 995, 1781, + 1340, 1020, 1773, + 1299, 1052, 1761, + 1238, 1091, 1745, + 1142, 1138, 1722, + 969, 1195, 1690, + 531, 1261, 1643, + 0, 1337, 1572, + 0, 1421, 1455, + 0, 1514, 1228, + 0, 1615, 317, + 0, 1722, 0, + 0, 1835, 0, + 0, 1951, 0, + 0, 2071, 0, + 0, 2195, 0, + 0, 2321, 0, + 0, 2447, 0, + 0, 2575, 0, + 0, 2705, 0, + 0, 2835, 0, + 0, 2965, 0, + 0, 3095, 0, + 0, 3227, 0, + 0, 3359, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1426, 957, 1799, + 1412, 973, 1795, + 1393, 992, 1788, + 1367, 1018, 1780, + 1328, 1049, 1768, + 1272, 1088, 1752, + 1183, 1136, 1730, + 1027, 1193, 1699, + 671, 1259, 1653, + 0, 1335, 1583, + 0, 1420, 1469, + 0, 1513, 1251, + 0, 1614, 465, + 0, 1722, 0, + 0, 1834, 0, + 0, 1951, 0, + 0, 2071, 0, + 0, 2195, 0, + 0, 2319, 0, + 0, 2447, 0, + 0, 2575, 0, + 0, 2705, 0, + 0, 2835, 0, + 0, 2965, 0, + 0, 3095, 0, + 0, 3227, 0, + 0, 3359, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1455, 953, 1808, + 1443, 968, 1804, + 1425, 988, 1797, + 1400, 1014, 1789, + 1365, 1046, 1778, + 1313, 1085, 1762, + 1232, 1133, 1740, + 1096, 1190, 1710, + 809, 1257, 1665, + 0, 1333, 1597, + 0, 1419, 1487, + 0, 1512, 1280, + 0, 1613, 610, + 0, 1721, 0, + 0, 1834, 0, + 0, 1951, 0, + 0, 2071, 0, + 0, 2195, 0, + 0, 2319, 0, + 0, 2447, 0, + 0, 2575, 0, + 0, 2705, 0, + 0, 2835, 0, + 0, 2965, 0, + 0, 3095, 0, + 0, 3227, 0, + 0, 3359, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1492, 947, 1820, + 1480, 963, 1815, + 1464, 983, 1809, + 1441, 1009, 1801, + 1409, 1041, 1790, + 1362, 1081, 1775, + 1291, 1129, 1754, + 1173, 1187, 1724, + 945, 1254, 1681, + 8, 1331, 1616, + 0, 1416, 1511, + 0, 1511, 1317, + 0, 1612, 750, + 0, 1720, 0, + 0, 1833, 0, + 0, 1950, 0, + 0, 2071, 0, + 0, 2195, 0, + 0, 2319, 0, + 0, 2447, 0, + 0, 2575, 0, + 0, 2705, 0, + 0, 2835, 0, + 0, 2965, 0, + 0, 3095, 0, + 0, 3227, 0, + 0, 3359, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1537, 939, 1835, + 1526, 955, 1831, + 1512, 976, 1825, + 1491, 1002, 1817, + 1463, 1034, 1806, + 1421, 1075, 1792, + 1359, 1124, 1771, + 1260, 1182, 1743, + 1080, 1250, 1701, + 606, 1327, 1639, + 0, 1414, 1540, + 0, 1508, 1361, + 0, 1610, 889, + 0, 1718, 0, + 0, 1832, 0, + 0, 1949, 0, + 0, 2069, 0, + 0, 2193, 0, + 0, 2319, 0, + 0, 2447, 0, + 0, 2575, 0, + 0, 2705, 0, + 0, 2835, 0, + 0, 2965, 0, + 0, 3095, 0, + 0, 3227, 0, + 0, 3359, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1591, 928, 1854, + 1582, 945, 1850, + 1569, 966, 1845, + 1551, 992, 1837, + 1526, 1026, 1827, + 1490, 1067, 1813, + 1437, 1117, 1794, + 1354, 1176, 1767, + 1215, 1245, 1727, + 916, 1323, 1669, + 0, 1410, 1577, + 0, 1505, 1414, + 0, 1608, 1026, + 0, 1716, 0, + 0, 1830, 0, + 0, 1948, 0, + 0, 2069, 0, + 0, 2193, 0, + 0, 2319, 0, + 0, 2445, 0, + 0, 2575, 0, + 0, 2703, 0, + 0, 2833, 0, + 0, 2965, 0, + 0, 3095, 0, + 0, 3227, 0, + 0, 3359, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1654, 913, 1879, + 1646, 930, 1875, + 1635, 952, 1870, + 1620, 979, 1863, + 1598, 1014, 1854, + 1568, 1056, 1840, + 1523, 1107, 1822, + 1457, 1167, 1796, + 1348, 1237, 1760, + 1146, 1317, 1706, + 517, 1405, 1621, + 0, 1501, 1477, + 0, 1604, 1161, + 0, 1714, 0, + 0, 1828, 0, + 0, 1946, 0, + 0, 2067, 0, + 0, 2191, 0, + 0, 2317, 0, + 0, 2445, 0, + 0, 2575, 0, + 0, 2703, 0, + 0, 2833, 0, + 0, 2965, 0, + 0, 3095, 0, + 0, 3227, 0, + 0, 3359, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1727, 892, 1910, + 1720, 910, 1907, + 1711, 933, 1902, + 1698, 962, 1895, + 1680, 997, 1886, + 1654, 1041, 1874, + 1618, 1093, 1857, + 1565, 1156, 1834, + 1482, 1227, 1800, + 1340, 1308, 1751, + 1035, 1398, 1675, + 0, 1495, 1549, + 0, 1600, 1296, + 0, 1710, 0, + 0, 1825, 0, + 0, 1944, 0, + 0, 2067, 0, + 0, 2191, 0, + 0, 2317, 0, + 0, 2445, 0, + 0, 2573, 0, + 0, 2703, 0, + 0, 2833, 0, + 0, 2965, 0, + 0, 3095, 0, + 0, 3227, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1810, 863, 1949, + 1804, 882, 1946, + 1796, 906, 1941, + 1785, 936, 1935, + 1770, 974, 1927, + 1750, 1020, 1916, + 1720, 1075, 1901, + 1678, 1139, 1879, + 1615, 1213, 1849, + 1514, 1297, 1805, + 1329, 1388, 1738, + 825, 1488, 1631, + 0, 1594, 1430, + 0, 1705, 815, + 0, 1822, 0, + 0, 1941, 0, + 0, 2065, 0, + 0, 2189, 0, + 0, 2315, 0, + 0, 2443, 0, + 0, 2573, 0, + 0, 2703, 0, + 0, 2833, 0, + 0, 2963, 0, + 0, 3095, 0, + 0, 3227, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1900, 820, 1996, + 1896, 841, 1993, + 1889, 868, 1989, + 1880, 900, 1984, + 1868, 941, 1976, + 1852, 990, 1966, + 1829, 1049, 1953, + 1796, 1117, 1934, + 1748, 1194, 1907, + 1674, 1281, 1868, + 1553, 1375, 1811, + 1314, 1477, 1721, + 121, 1586, 1564, + 0, 1699, 1198, + 0, 1817, 0, + 0, 1938, 0, + 0, 2061, 0, + 0, 2187, 0, + 0, 2315, 0, + 0, 2443, 0, + 0, 2571, 0, + 0, 2701, 0, + 0, 2833, 0, + 0, 2963, 0, + 0, 3095, 0, + 0, 3227, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1999, 757, 2053, + 1995, 780, 2049, + 1990, 810, 2046, + 1983, 848, 2041, + 1973, 893, 2035, + 1960, 947, 2026, + 1942, 1011, 2014, + 1917, 1084, 1998, + 1881, 1167, 1974, + 1827, 1258, 1941, + 1743, 1357, 1893, + 1601, 1463, 1819, + 1292, 1574, 1697, + 0, 1690, 1455, + 0, 1810, 187, + 0, 1932, 0, + 0, 2057, 0, + 0, 2183, 0, + 0, 2311, 0, + 0, 2441, 0, + 0, 2571, 0, + 0, 2701, 0, + 0, 2831, 0, + 0, 2963, 0, + 0, 3095, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2105, 654, 2119, + 2101, 684, 2115, + 2097, 721, 2113, + 2091, 765, 2109, + 2085, 819, 2103, + 2075, 883, 2095, + 2059, 956, 2085, + 2040, 1038, 2071, + 2013, 1128, 2051, + 1974, 1227, 2024, + 1915, 1332, 1984, + 1822, 1443, 1924, + 1658, 1559, 1830, + 1261, 1678, 1663, + 0, 1801, 1252, + 0, 1926, 0, + 0, 2053, 0, + 0, 2179, 0, + 0, 2309, 0, + 0, 2439, 0, + 0, 2569, 0, + 0, 2699, 0, + 0, 2831, 0, + 0, 2963, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2215, 467, 2193, + 2213, 511, 2191, + 2209, 563, 2189, + 2205, 626, 2185, + 2199, 698, 2181, + 2191, 779, 2175, + 2181, 869, 2165, + 2167, 966, 2153, + 2145, 1071, 2137, + 2117, 1181, 2115, + 2075, 1296, 2083, + 2011, 1415, 2035, + 1909, 1538, 1963, + 1724, 1662, 1844, + 1217, 1788, 1612, + 0, 1916, 615, + 0, 2045, 0, + 0, 2175, 0, + 0, 2305, 0, + 0, 2435, 0, + 0, 2567, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2331, 0, 2277, + 2329, 71, 2277, + 2327, 199, 2273, + 2323, 327, 2271, + 2319, 457, 2267, + 2313, 587, 2261, + 2305, 718, 2255, + 2293, 849, 2245, + 2277, 980, 2231, + 2257, 1112, 2213, + 2225, 1243, 2187, + 2181, 1375, 2151, + 2113, 1507, 2095, + 2005, 1639, 2010, + 1800, 1771, 1862, + 1150, 1903, 1535, + 0, 2035, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2451, 0, 2371, + 2449, 0, 2369, + 2447, 0, 2367, + 2445, 0, 2365, + 2441, 0, 2361, + 2437, 40, 2357, + 2431, 379, 2351, + 2421, 622, 2345, + 2411, 822, 2333, + 2395, 999, 2319, + 2371, 1161, 2299, + 2339, 1315, 2269, + 2293, 1463, 2227, + 2223, 1606, 2165, + 2107, 1747, 2065, + 1885, 1885, 1885, + 1042, 2022, 1405, + 0, 2157, 0, + 0, 2291, 0, + 0, 2425, 0, + 0, 2559, 0, + 0, 2693, 0, + 0, 2825, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2573, 0, 2471, + 2571, 0, 2469, + 2571, 0, 2469, + 2569, 0, 2467, + 2565, 0, 2463, + 2563, 0, 2461, + 2557, 0, 2455, + 2551, 0, 2449, + 2543, 449, 2441, + 2531, 782, 2429, + 2513, 1022, 2413, + 2491, 1220, 2391, + 2459, 1396, 2361, + 2411, 1559, 2315, + 2337, 1712, 2245, + 2217, 1860, 2131, + 1979, 2003, 1914, + 839, 2143, 1140, + 0, 2281, 0, + 0, 2419, 0, + 0, 2553, 0, + 0, 2689, 0, + 0, 2823, 0, + 0, 2955, 0, + 0, 3089, 0, + 0, 3221, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3885, 0, + 0, 4017, 0, + 2697, 0, 2577, + 2697, 0, 2577, + 2695, 0, 2575, + 2695, 0, 2575, + 2693, 0, 2573, + 2689, 0, 2569, + 2687, 0, 2565, + 2681, 0, 2561, + 2675, 0, 2555, + 2665, 12, 2545, + 2653, 723, 2533, + 2637, 1051, 2517, + 2613, 1289, 2493, + 2579, 1486, 2459, + 2531, 1662, 2409, + 2455, 1824, 2333, + 2331, 1977, 2207, + 2079, 2125, 1951, + 206, 2267, 0, + 0, 2409, 0, + 0, 2547, 0, + 0, 2683, 0, + 0, 2819, 0, + 0, 2953, 0, + 0, 3087, 0, + 0, 3221, 0, + 0, 3353, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4017, 0, + 2825, 0, 2689, + 2823, 0, 2689, + 2823, 0, 2689, + 2821, 0, 2687, + 2821, 0, 2685, + 2819, 0, 2683, + 2815, 0, 2681, + 2811, 0, 2677, + 2807, 0, 2671, + 2801, 0, 2665, + 2791, 0, 2655, + 2779, 630, 2643, + 2761, 1087, 2625, + 2737, 1366, 2599, + 2703, 1584, 2563, + 2653, 1771, 2511, + 2577, 1940, 2429, + 2449, 2099, 2291, + 2187, 2249, 1995, + 0, 2395, 0, + 0, 2535, 0, + 0, 2675, 0, + 0, 2813, 0, + 0, 2949, 0, + 0, 3083, 0, + 0, 3217, 0, + 0, 3351, 0, + 0, 3485, 0, + 0, 3617, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 2953, 0, 2807, + 2951, 0, 2807, + 2951, 0, 2805, + 2951, 0, 2805, + 2949, 0, 2803, + 2947, 0, 2801, + 2945, 0, 2799, + 2943, 0, 2797, + 2939, 0, 2793, + 2935, 0, 2787, + 2927, 0, 2781, + 2919, 0, 2771, + 2905, 465, 2757, + 2889, 1132, 2739, + 2865, 1453, 2713, + 2829, 1689, 2675, + 2779, 1885, 2619, + 2701, 2059, 2533, + 2569, 2221, 2383, + 2299, 2375, 2049, + 0, 2521, 0, + 0, 2665, 0, + 0, 2805, 0, + 0, 2943, 0, + 0, 3079, 0, + 0, 3215, 0, + 0, 3349, 0, + 0, 3483, 0, + 0, 3617, 0, + 0, 3749, 0, + 0, 3883, 0, + 0, 4015, 0, + 3081, 0, 2927, + 3081, 0, 2927, + 3081, 0, 2925, + 3079, 0, 2925, + 3079, 0, 2925, + 3077, 0, 2923, + 3075, 0, 2921, + 3073, 0, 2919, + 3071, 0, 2917, + 3067, 0, 2913, + 3063, 0, 2907, + 3055, 0, 2899, + 3047, 0, 2889, + 3033, 66, 2875, + 3017, 1185, 2857, + 2991, 1548, 2829, + 2957, 1799, 2791, + 2905, 2003, 2733, + 2827, 2183, 2643, + 2693, 2347, 2483, + 2417, 2501, 2111, + 0, 2651, 0, + 0, 2795, 0, + 0, 2935, 0, + 0, 3073, 0, + 0, 3211, 0, + 0, 3347, 0, + 0, 3481, 0, + 0, 3615, 0, + 0, 3749, 0, + 0, 3881, 0, + 0, 4015, 0, + 3211, 0, 3049, + 3211, 0, 3049, + 3211, 0, 3049, + 3209, 0, 3049, + 3209, 0, 3047, + 3209, 0, 3047, + 3207, 0, 3045, + 3205, 0, 3043, + 3203, 0, 3041, + 3201, 0, 3039, + 3197, 0, 3035, + 3191, 0, 3029, + 3185, 0, 3021, + 3175, 0, 3011, + 3163, 0, 2997, + 3145, 1248, 2977, + 3121, 1651, 2949, + 3085, 1914, 2909, + 3033, 2125, 2851, + 2955, 2307, 2757, + 2819, 2475, 2591, + 2537, 2631, 2183, + 0, 2779, 0, + 0, 2925, 0, + 0, 3065, 0, + 0, 3205, 0, + 0, 3341, 0, + 0, 3477, 0, + 0, 3613, 0, + 0, 3747, 0, + 0, 3881, 0, + 0, 4013, 0, + 3341, 0, 3175, + 3341, 0, 3175, + 3341, 0, 3175, + 3341, 0, 3173, + 3339, 0, 3173, + 3339, 0, 3173, + 3339, 0, 3171, + 3337, 0, 3171, + 3335, 0, 3169, + 3333, 0, 3167, + 3331, 0, 3163, + 3327, 0, 3159, + 3321, 0, 3153, + 3315, 0, 3145, + 3305, 0, 3135, + 3293, 0, 3121, + 3275, 1320, 3101, + 3251, 1759, 3073, + 3215, 2033, 3033, + 3163, 2249, 2971, + 3083, 2435, 2875, + 2947, 2603, 2703, + 2661, 2759, 2265, + 0, 2911, 0, + 0, 3055, 0, + 0, 3197, 0, + 0, 3337, 0, + 0, 3473, 0, + 0, 3609, 0, + 0, 3745, 0, + 0, 3879, 0, + 0, 4013, 0, + 3471, 0, 3301, + 3471, 0, 3301, + 3471, 0, 3301, + 3471, 0, 3301, + 3471, 0, 3301, + 3471, 0, 3301, + 3469, 0, 3299, + 3469, 0, 3299, + 3467, 0, 3297, + 3467, 0, 3295, + 3463, 0, 3293, + 3461, 0, 3289, + 3457, 0, 3285, + 3453, 0, 3279, + 3445, 0, 3273, + 3437, 0, 3261, + 3423, 0, 3247, + 3405, 1402, 3227, + 3381, 1873, 3199, + 3345, 2155, 3157, + 3293, 2375, 3095, + 3213, 2563, 2997, + 3075, 2731, 2819, + 2785, 2891, 2355, + 0, 3041, 0, + 0, 3187, 0, + 0, 3329, 0, + 0, 3467, 0, + 0, 3605, 0, + 0, 3741, 0, + 0, 3877, 0, + 0, 4011, 0, + 3603, 0, 3429, + 3603, 0, 3429, + 3603, 0, 3429, + 3603, 0, 3429, + 3603, 0, 3429, + 3601, 0, 3429, + 3601, 0, 3429, + 3601, 0, 3427, + 3599, 0, 3427, + 3599, 0, 3425, + 3597, 0, 3423, + 3595, 0, 3421, + 3593, 0, 3417, + 3589, 0, 3413, + 3583, 0, 3407, + 3577, 0, 3399, + 3567, 0, 3389, + 3555, 0, 3375, + 3537, 1492, 3355, + 3511, 1990, 3325, + 3475, 2279, 3283, + 3423, 2501, 3221, + 3343, 2691, 3121, + 3205, 2861, 2939, + 2913, 3021, 2453, + 0, 3171, 0, + 0, 3317, 0, + 0, 3459, 0, + 0, 3599, 0, + 0, 3737, 0, + 0, 3873, 0, + 0, 4009, 0, + 3735, 0, 3559, + 3735, 0, 3559, + 3735, 0, 3559, + 3733, 0, 3559, + 3733, 0, 3559, + 3733, 0, 3559, + 3733, 0, 3557, + 3733, 0, 3557, + 3731, 0, 3557, + 3731, 0, 3555, + 3729, 0, 3555, + 3729, 0, 3553, + 3727, 0, 3551, + 3723, 0, 3547, + 3719, 0, 3543, + 3715, 0, 3537, + 3707, 0, 3529, + 3699, 0, 3517, + 3685, 0, 3503, + 3667, 1591, 3483, + 3643, 2111, 3453, + 3607, 2405, 3411, + 3555, 2631, 3347, + 3473, 2821, 3247, + 3335, 2993, 3063, + 3041, 3151, 2559, + 0, 3303, 0, + 0, 3449, 0, + 0, 3591, 0, + 0, 3731, 0, + 0, 3869, 0, + 0, 4005, 0, + 3865, 0, 3689, + 3865, 0, 3689, + 3865, 0, 3689, + 3865, 0, 3689, + 3865, 0, 3689, + 3865, 0, 3689, + 3865, 0, 3687, + 3865, 0, 3687, + 3865, 0, 3687, + 3863, 0, 3687, + 3863, 0, 3685, + 3861, 0, 3683, + 3859, 0, 3683, + 3857, 0, 3679, + 3855, 0, 3677, + 3851, 0, 3673, + 3847, 0, 3667, + 3839, 0, 3659, + 3829, 0, 3647, + 3817, 0, 3633, + 3799, 1696, 3611, + 3773, 2235, 3583, + 3739, 2533, 3541, + 3685, 2759, 3477, + 3603, 2951, 3375, + 3465, 3123, 3187, + 3169, 3283, 2669, + 0, 3435, 0, + 0, 3581, 0, + 0, 3723, 0, + 0, 3863, 0, + 0, 4001, 0, + 3997, 0, 3819, + 3997, 0, 3819, + 3997, 0, 3819, + 3997, 0, 3819, + 3997, 0, 3819, + 3997, 0, 3819, + 3997, 0, 3819, + 3997, 0, 3819, + 3997, 0, 3817, + 3995, 0, 3817, + 3995, 0, 3817, + 3995, 0, 3815, + 3993, 0, 3815, + 3991, 0, 3813, + 3989, 0, 3811, + 3987, 0, 3807, + 3983, 0, 3803, + 3977, 0, 3797, + 3971, 0, 3789, + 3961, 0, 3777, + 3949, 0, 3763, + 3931, 1806, 3741, + 3905, 2361, 3713, + 3869, 2663, 3669, + 3817, 2889, 3605, + 3735, 3083, 3503, + 3595, 3255, 3315, + 3299, 3415, 2785, + 0, 3567, 0, + 0, 3713, 0, + 0, 3855, 0, + 0, 3995, 0, + 4095, 0, 3951, + 4095, 0, 3951, + 4095, 0, 3951, + 4095, 0, 3951, + 4095, 0, 3949, + 4095, 0, 3949, + 4095, 0, 3949, + 4095, 0, 3949, + 4095, 0, 3949, + 4095, 0, 3949, + 4095, 0, 3949, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3945, + 4095, 0, 3943, + 4095, 0, 3941, + 4095, 0, 3937, + 4095, 0, 3933, + 4095, 0, 3927, + 4095, 0, 3919, + 4093, 0, 3909, + 4081, 0, 3893, + 4063, 1922, 3873, + 4037, 2487, 3843, + 4001, 2793, 3801, + 3949, 3021, 3735, + 3867, 3213, 3633, + 3727, 3385, 3443, + 3431, 3547, 2903, + 0, 3699, 0, + 0, 3845, 0, + 0, 3987, 0, + 4095, 0, 4081, + 4095, 0, 4081, + 4095, 0, 4081, + 4095, 0, 4081, + 4095, 0, 4081, + 4095, 0, 4081, + 4095, 0, 4081, + 4095, 0, 4081, + 4095, 0, 4081, + 4095, 0, 4081, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4075, + 4095, 0, 4073, + 4095, 0, 4069, + 4095, 0, 4065, + 4095, 0, 4059, + 4095, 0, 4051, + 4095, 0, 4039, + 4095, 0, 4025, + 4095, 2041, 4003, + 4095, 2617, 3973, + 4095, 2923, 3931, + 4081, 3151, 3867, + 3999, 3345, 3763, + 3859, 3517, 3571, + 3561, 3677, 3025, + 0, 3831, 0, + 0, 3977, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2163, 4095, + 4095, 2745, 4095, + 4095, 3053, 4063, + 4095, 3283, 3997, + 4095, 3477, 3893, + 3991, 3649, 3701, + 3693, 3809, 3151, + 0, 3961, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2287, 4095, + 4095, 2875, 4095, + 4095, 3185, 4095, + 4095, 3415, 4095, + 4095, 3607, 4025, + 4095, 3781, 3831, + 3823, 3941, 3277, + 1513, 1085, 1919, + 1502, 1096, 1915, + 1486, 1112, 1911, + 1465, 1131, 1904, + 1434, 1156, 1895, + 1390, 1187, 1883, + 1323, 1226, 1867, + 1214, 1273, 1844, + 1011, 1329, 1811, + 373, 1395, 1763, + 0, 1470, 1689, + 0, 1555, 1568, + 0, 1648, 1328, + 0, 1748, 128, + 0, 1855, 0, + 0, 1967, 0, + 0, 2085, 0, + 0, 2205, 0, + 0, 2327, 0, + 0, 2453, 0, + 0, 2579, 0, + 0, 2707, 0, + 0, 2837, 0, + 0, 2967, 0, + 0, 3097, 0, + 0, 3227, 0, + 0, 3359, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1527, 1083, 1923, + 1516, 1095, 1919, + 1501, 1110, 1915, + 1480, 1129, 1908, + 1451, 1154, 1899, + 1408, 1186, 1888, + 1344, 1225, 1871, + 1241, 1272, 1848, + 1052, 1328, 1816, + 520, 1394, 1768, + 0, 1470, 1696, + 0, 1554, 1576, + 0, 1647, 1342, + 0, 1748, 294, + 0, 1855, 0, + 0, 1967, 0, + 0, 2083, 0, + 0, 2205, 0, + 0, 2327, 0, + 0, 2453, 0, + 0, 2579, 0, + 0, 2707, 0, + 0, 2837, 0, + 0, 2967, 0, + 0, 3097, 0, + 0, 3227, 0, + 0, 3359, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1545, 1080, 1928, + 1534, 1092, 1924, + 1520, 1108, 1920, + 1500, 1127, 1913, + 1472, 1152, 1905, + 1431, 1184, 1893, + 1370, 1223, 1877, + 1274, 1270, 1854, + 1101, 1327, 1822, + 663, 1393, 1775, + 0, 1469, 1704, + 0, 1553, 1587, + 0, 1647, 1360, + 0, 1747, 449, + 0, 1854, 0, + 0, 1967, 0, + 0, 2083, 0, + 0, 2203, 0, + 0, 2327, 0, + 0, 2453, 0, + 0, 2579, 0, + 0, 2707, 0, + 0, 2837, 0, + 0, 2967, 0, + 0, 3097, 0, + 0, 3227, 0, + 0, 3359, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1568, 1077, 1935, + 1558, 1089, 1931, + 1544, 1104, 1927, + 1525, 1124, 1920, + 1499, 1150, 1912, + 1460, 1181, 1900, + 1404, 1221, 1884, + 1315, 1268, 1862, + 1160, 1325, 1831, + 803, 1391, 1785, + 0, 1467, 1715, + 0, 1552, 1601, + 0, 1646, 1383, + 0, 1746, 597, + 0, 1854, 0, + 0, 1966, 0, + 0, 2083, 0, + 0, 2203, 0, + 0, 2327, 0, + 0, 2453, 0, + 0, 2579, 0, + 0, 2707, 0, + 0, 2837, 0, + 0, 2967, 0, + 0, 3097, 0, + 0, 3227, 0, + 0, 3359, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1597, 1073, 1944, + 1588, 1085, 1940, + 1575, 1100, 1936, + 1557, 1120, 1930, + 1532, 1146, 1921, + 1497, 1178, 1910, + 1445, 1217, 1894, + 1364, 1265, 1873, + 1228, 1322, 1842, + 941, 1389, 1797, + 0, 1465, 1729, + 0, 1551, 1619, + 0, 1644, 1412, + 0, 1745, 742, + 0, 1853, 0, + 0, 1966, 0, + 0, 2083, 0, + 0, 2203, 0, + 0, 2327, 0, + 0, 2451, 0, + 0, 2579, 0, + 0, 2707, 0, + 0, 2837, 0, + 0, 2967, 0, + 0, 3097, 0, + 0, 3227, 0, + 0, 3359, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1633, 1067, 1955, + 1624, 1079, 1952, + 1613, 1095, 1947, + 1596, 1115, 1942, + 1574, 1141, 1933, + 1541, 1173, 1922, + 1494, 1213, 1907, + 1423, 1261, 1886, + 1305, 1319, 1856, + 1077, 1386, 1813, + 140, 1463, 1748, + 0, 1549, 1643, + 0, 1643, 1449, + 0, 1744, 883, + 0, 1852, 0, + 0, 1965, 0, + 0, 2083, 0, + 0, 2203, 0, + 0, 2327, 0, + 0, 2451, 0, + 0, 2579, 0, + 0, 2707, 0, + 0, 2837, 0, + 0, 2967, 0, + 0, 3097, 0, + 0, 3227, 0, + 0, 3359, 0, + 0, 3491, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1677, 1058, 1970, + 1669, 1071, 1967, + 1659, 1087, 1963, + 1644, 1108, 1957, + 1624, 1134, 1949, + 1595, 1167, 1939, + 1553, 1207, 1924, + 1491, 1256, 1904, + 1392, 1314, 1875, + 1212, 1382, 1833, + 738, 1459, 1771, + 0, 1546, 1672, + 0, 1640, 1493, + 0, 1742, 1021, + 0, 1850, 0, + 0, 1964, 0, + 0, 2081, 0, + 0, 2203, 0, + 0, 2325, 0, + 0, 2451, 0, + 0, 2579, 0, + 0, 2707, 0, + 0, 2837, 0, + 0, 2967, 0, + 0, 3097, 0, + 0, 3227, 0, + 0, 3359, 0, + 0, 3491, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1730, 1047, 1990, + 1723, 1060, 1987, + 1714, 1076, 1982, + 1701, 1098, 1977, + 1683, 1124, 1969, + 1658, 1158, 1959, + 1622, 1199, 1945, + 1569, 1249, 1926, + 1487, 1308, 1899, + 1347, 1377, 1859, + 1048, 1455, 1801, + 0, 1542, 1709, + 0, 1637, 1546, + 0, 1740, 1158, + 0, 1848, 0, + 0, 1962, 0, + 0, 2081, 0, + 0, 2201, 0, + 0, 2325, 0, + 0, 2451, 0, + 0, 2579, 0, + 0, 2707, 0, + 0, 2835, 0, + 0, 2965, 0, + 0, 3097, 0, + 0, 3227, 0, + 0, 3359, 0, + 0, 3491, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1793, 1032, 2014, + 1787, 1045, 2011, + 1778, 1062, 2008, + 1767, 1084, 2002, + 1752, 1111, 1995, + 1730, 1146, 1986, + 1700, 1188, 1972, + 1655, 1239, 1954, + 1589, 1299, 1929, + 1481, 1369, 1892, + 1278, 1449, 1838, + 650, 1537, 1754, + 0, 1633, 1609, + 0, 1736, 1294, + 0, 1846, 0, + 0, 1960, 0, + 0, 2079, 0, + 0, 2201, 0, + 0, 2325, 0, + 0, 2451, 0, + 0, 2577, 0, + 0, 2707, 0, + 0, 2835, 0, + 0, 2965, 0, + 0, 3097, 0, + 0, 3227, 0, + 0, 3359, 0, + 0, 3491, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1865, 1011, 2045, + 1860, 1024, 2043, + 1853, 1042, 2039, + 1843, 1065, 2034, + 1830, 1093, 2028, + 1812, 1129, 2019, + 1787, 1173, 2006, + 1750, 1226, 1989, + 1697, 1288, 1966, + 1614, 1359, 1932, + 1472, 1440, 1883, + 1167, 1530, 1807, + 0, 1628, 1681, + 0, 1732, 1428, + 0, 1842, 0, + 0, 1957, 0, + 0, 2077, 0, + 0, 2199, 0, + 0, 2323, 0, + 0, 2449, 0, + 0, 2577, 0, + 0, 2705, 0, + 0, 2835, 0, + 0, 2965, 0, + 0, 3097, 0, + 0, 3227, 0, + 0, 3359, 0, + 0, 3491, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1946, 980, 2083, + 1942, 995, 2081, + 1936, 1014, 2077, + 1928, 1038, 2073, + 1917, 1068, 2067, + 1902, 1106, 2059, + 1882, 1152, 2049, + 1853, 1207, 2033, + 1810, 1271, 2011, + 1747, 1345, 1981, + 1646, 1429, 1937, + 1461, 1520, 1870, + 957, 1620, 1763, + 0, 1726, 1562, + 0, 1838, 947, + 0, 1954, 0, + 0, 2073, 0, + 0, 2197, 0, + 0, 2321, 0, + 0, 2447, 0, + 0, 2575, 0, + 0, 2705, 0, + 0, 2835, 0, + 0, 2965, 0, + 0, 3095, 0, + 0, 3227, 0, + 0, 3359, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2036, 936, 2131, + 2033, 953, 2129, + 2028, 973, 2125, + 2021, 1000, 2121, + 2013, 1032, 2115, + 2001, 1073, 2109, + 1984, 1122, 2099, + 1961, 1181, 2085, + 1928, 1249, 2065, + 1880, 1326, 2039, + 1807, 1413, 2000, + 1685, 1508, 1943, + 1446, 1610, 1853, + 253, 1718, 1696, + 0, 1831, 1330, + 0, 1949, 0, + 0, 2069, 0, + 0, 2193, 0, + 0, 2319, 0, + 0, 2447, 0, + 0, 2575, 0, + 0, 2703, 0, + 0, 2833, 0, + 0, 2965, 0, + 0, 3095, 0, + 0, 3227, 0, + 0, 3359, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2135, 870, 2187, + 2131, 889, 2185, + 2127, 913, 2181, + 2123, 942, 2179, + 2115, 980, 2173, + 2105, 1025, 2167, + 2093, 1079, 2159, + 2075, 1143, 2147, + 2049, 1217, 2129, + 2013, 1299, 2107, + 1959, 1391, 2073, + 1876, 1490, 2025, + 1733, 1595, 1951, + 1424, 1707, 1829, + 0, 1822, 1587, + 0, 1942, 319, + 0, 2065, 0, + 0, 2189, 0, + 0, 2317, 0, + 0, 2443, 0, + 0, 2573, 0, + 0, 2703, 0, + 0, 2833, 0, + 0, 2963, 0, + 0, 3095, 0, + 0, 3227, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2239, 763, 2251, + 2237, 786, 2251, + 2233, 816, 2247, + 2229, 853, 2245, + 2223, 898, 2241, + 2217, 952, 2235, + 2207, 1015, 2227, + 2193, 1088, 2217, + 2173, 1170, 2203, + 2145, 1261, 2183, + 2105, 1359, 2155, + 2047, 1464, 2115, + 1954, 1575, 2057, + 1790, 1691, 1962, + 1394, 1811, 1795, + 0, 1933, 1384, + 0, 2057, 0, + 0, 2185, 0, + 0, 2313, 0, + 0, 2441, 0, + 0, 2571, 0, + 0, 2701, 0, + 0, 2831, 0, + 0, 2963, 0, + 0, 3095, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2349, 563, 2327, + 2347, 599, 2325, + 2345, 643, 2323, + 2341, 696, 2321, + 2337, 758, 2317, + 2331, 830, 2313, + 2323, 911, 2307, + 2313, 1001, 2297, + 2299, 1098, 2285, + 2277, 1203, 2269, + 2249, 1313, 2247, + 2207, 1429, 2215, + 2143, 1548, 2167, + 2041, 1670, 2095, + 1856, 1794, 1976, + 1349, 1920, 1745, + 0, 2049, 747, + 0, 2177, 0, + 0, 2307, 0, + 0, 2437, 0, + 0, 2567, 0, + 0, 2699, 0, + 0, 2831, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2465, 0, 2411, + 2463, 77, 2409, + 2461, 203, 2409, + 2459, 331, 2407, + 2455, 460, 2403, + 2451, 589, 2399, + 2445, 719, 2393, + 2437, 850, 2387, + 2425, 981, 2377, + 2409, 1112, 2363, + 2389, 1244, 2345, + 2357, 1376, 2319, + 2313, 1507, 2283, + 2245, 1639, 2227, + 2137, 1771, 2141, + 1932, 1903, 1994, + 1282, 2035, 1667, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2583, 0, 2503, + 2583, 0, 2503, + 2581, 0, 2501, + 2579, 0, 2499, + 2577, 0, 2497, + 2573, 0, 2495, + 2569, 172, 2489, + 2563, 511, 2483, + 2553, 754, 2477, + 2543, 954, 2465, + 2527, 1130, 2451, + 2503, 1293, 2431, + 2471, 1447, 2401, + 2425, 1595, 2359, + 2355, 1739, 2297, + 2239, 1879, 2197, + 2017, 2017, 2017, + 1174, 2153, 1537, + 0, 2289, 0, + 0, 2425, 0, + 0, 2557, 0, + 0, 2691, 0, + 0, 2825, 0, + 0, 2957, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2705, 0, 2603, + 2705, 0, 2603, + 2703, 0, 2601, + 2703, 0, 2601, + 2701, 0, 2599, + 2697, 0, 2597, + 2695, 0, 2593, + 2689, 0, 2589, + 2683, 0, 2581, + 2675, 581, 2573, + 2663, 914, 2561, + 2647, 1154, 2545, + 2623, 1352, 2523, + 2591, 1528, 2493, + 2543, 1691, 2447, + 2469, 1845, 2377, + 2349, 1992, 2263, + 2111, 2135, 2046, + 972, 2275, 1272, + 0, 2413, 0, + 0, 2551, 0, + 0, 2685, 0, + 0, 2821, 0, + 0, 2955, 0, + 0, 3087, 0, + 0, 3221, 0, + 0, 3353, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3885, 0, + 0, 4017, 0, + 2831, 0, 2711, + 2829, 0, 2709, + 2829, 0, 2709, + 2827, 0, 2707, + 2827, 0, 2707, + 2825, 0, 2705, + 2821, 0, 2701, + 2819, 0, 2699, + 2813, 0, 2693, + 2807, 0, 2687, + 2797, 144, 2677, + 2785, 855, 2665, + 2769, 1183, 2649, + 2745, 1421, 2625, + 2711, 1618, 2591, + 2663, 1794, 2541, + 2587, 1956, 2465, + 2463, 2109, 2339, + 2211, 2257, 2083, + 338, 2401, 0, + 0, 2541, 0, + 0, 2679, 0, + 0, 2815, 0, + 0, 2951, 0, + 0, 3085, 0, + 0, 3219, 0, + 0, 3353, 0, + 0, 3485, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 2957, 0, 2823, + 2957, 0, 2821, + 2955, 0, 2821, + 2955, 0, 2821, + 2953, 0, 2819, + 2953, 0, 2817, + 2951, 0, 2815, + 2947, 0, 2813, + 2943, 0, 2809, + 2939, 0, 2803, + 2933, 0, 2797, + 2923, 0, 2787, + 2911, 762, 2775, + 2893, 1219, 2757, + 2869, 1499, 2731, + 2835, 1716, 2697, + 2785, 1903, 2643, + 2709, 2073, 2561, + 2581, 2231, 2423, + 2319, 2381, 2127, + 0, 2527, 0, + 0, 2667, 0, + 0, 2807, 0, + 0, 2945, 0, + 0, 3081, 0, + 0, 3215, 0, + 0, 3349, 0, + 0, 3483, 0, + 0, 3617, 0, + 0, 3749, 0, + 0, 3883, 0, + 0, 4015, 0, + 3085, 0, 2939, + 3085, 0, 2939, + 3083, 0, 2939, + 3083, 0, 2937, + 3083, 0, 2937, + 3081, 0, 2935, + 3079, 0, 2933, + 3077, 0, 2931, + 3075, 0, 2929, + 3071, 0, 2925, + 3067, 0, 2919, + 3059, 0, 2913, + 3051, 0, 2903, + 3037, 597, 2889, + 3021, 1264, 2871, + 2997, 1585, 2845, + 2961, 1821, 2807, + 2911, 2017, 2751, + 2833, 2191, 2665, + 2701, 2353, 2515, + 2431, 2507, 2181, + 0, 2653, 0, + 0, 2797, 0, + 0, 2937, 0, + 0, 3075, 0, + 0, 3211, 0, + 0, 3347, 0, + 0, 3481, 0, + 0, 3615, 0, + 0, 3749, 0, + 0, 3881, 0, + 0, 4015, 0, + 3213, 0, 3059, + 3213, 0, 3059, + 3213, 0, 3059, + 3213, 0, 3057, + 3211, 0, 3057, + 3211, 0, 3057, + 3209, 0, 3055, + 3209, 0, 3053, + 3207, 0, 3051, + 3203, 0, 3049, + 3199, 0, 3045, + 3195, 0, 3039, + 3187, 0, 3031, + 3179, 0, 3021, + 3165, 198, 3007, + 3149, 1317, 2989, + 3125, 1680, 2961, + 3089, 1931, 2923, + 3037, 2135, 2865, + 2959, 2315, 2775, + 2825, 2479, 2615, + 2549, 2635, 2243, + 0, 2783, 0, + 0, 2927, 0, + 0, 3067, 0, + 0, 3205, 0, + 0, 3343, 0, + 0, 3479, 0, + 0, 3613, 0, + 0, 3747, 0, + 0, 3881, 0, + 0, 4013, 0, + 3343, 0, 3183, + 3343, 0, 3181, + 3343, 0, 3181, + 3343, 0, 3181, + 3341, 0, 3181, + 3341, 0, 3179, + 3341, 0, 3179, + 3339, 0, 3177, + 3337, 0, 3177, + 3335, 0, 3173, + 3333, 0, 3171, + 3329, 0, 3167, + 3323, 0, 3161, + 3317, 0, 3153, + 3307, 0, 3143, + 3295, 0, 3129, + 3277, 1380, 3109, + 3253, 1783, 3081, + 3217, 2046, 3041, + 3167, 2257, 2983, + 3087, 2439, 2889, + 2951, 2607, 2723, + 2669, 2763, 2315, + 0, 2913, 0, + 0, 3057, 0, + 0, 3197, 0, + 0, 3337, 0, + 0, 3473, 0, + 0, 3609, 0, + 0, 3745, 0, + 0, 3879, 0, + 0, 4013, 0, + 3473, 0, 3307, + 3473, 0, 3307, + 3473, 0, 3307, + 3473, 0, 3307, + 3473, 0, 3307, + 3471, 0, 3305, + 3471, 0, 3305, + 3471, 0, 3303, + 3469, 0, 3303, + 3467, 0, 3301, + 3465, 0, 3299, + 3463, 0, 3295, + 3459, 0, 3291, + 3453, 0, 3285, + 3447, 0, 3277, + 3437, 0, 3267, + 3425, 0, 3253, + 3407, 1452, 3233, + 3383, 1891, 3205, + 3347, 2165, 3165, + 3295, 2381, 3103, + 3215, 2567, 3007, + 3079, 2735, 2835, + 2793, 2893, 2397, + 0, 3043, 0, + 0, 3187, 0, + 0, 3329, 0, + 0, 3469, 0, + 0, 3605, 0, + 0, 3741, 0, + 0, 3877, 0, + 0, 4011, 0, + 3603, 0, 3435, + 3603, 0, 3433, + 3603, 0, 3433, + 3603, 0, 3433, + 3603, 0, 3433, + 3603, 0, 3433, + 3603, 0, 3433, + 3601, 0, 3431, + 3601, 0, 3431, + 3599, 0, 3429, + 3599, 0, 3427, + 3597, 0, 3425, + 3593, 0, 3423, + 3589, 0, 3417, + 3585, 0, 3413, + 3577, 0, 3405, + 3569, 0, 3393, + 3555, 0, 3379, + 3537, 1534, 3359, + 3513, 2005, 3331, + 3477, 2287, 3289, + 3425, 2507, 3227, + 3345, 2695, 3129, + 3207, 2863, 2951, + 2917, 3023, 2487, + 0, 3173, 0, + 0, 3319, 0, + 0, 3461, 0, + 0, 3599, 0, + 0, 3737, 0, + 0, 3873, 0, + 0, 4009, 0, + 3735, 0, 3563, + 3735, 0, 3563, + 3735, 0, 3561, + 3735, 0, 3561, + 3735, 0, 3561, + 3735, 0, 3561, + 3733, 0, 3561, + 3733, 0, 3561, + 3733, 0, 3559, + 3731, 0, 3559, + 3731, 0, 3557, + 3729, 0, 3555, + 3727, 0, 3553, + 3725, 0, 3549, + 3721, 0, 3545, + 3715, 0, 3539, + 3709, 0, 3533, + 3699, 0, 3521, + 3687, 0, 3507, + 3669, 1625, 3487, + 3643, 2123, 3457, + 3607, 2411, 3415, + 3555, 2633, 3353, + 3475, 2823, 3253, + 3337, 2993, 3071, + 3045, 3153, 2585, + 0, 3303, 0, + 0, 3449, 0, + 0, 3593, 0, + 0, 3731, 0, + 0, 3869, 0, + 0, 4005, 0, + 3867, 0, 3691, + 3867, 0, 3691, + 3867, 0, 3691, + 3867, 0, 3691, + 3865, 0, 3691, + 3865, 0, 3691, + 3865, 0, 3691, + 3865, 0, 3689, + 3865, 0, 3689, + 3865, 0, 3689, + 3863, 0, 3687, + 3863, 0, 3687, + 3861, 0, 3685, + 3859, 0, 3683, + 3855, 0, 3679, + 3851, 0, 3675, + 3847, 0, 3669, + 3839, 0, 3661, + 3831, 0, 3651, + 3817, 0, 3635, + 3799, 1723, 3615, + 3775, 2243, 3585, + 3739, 2539, 3543, + 3687, 2763, 3481, + 3605, 2953, 3379, + 3467, 3125, 3195, + 3173, 3283, 2691, + 0, 3435, 0, + 0, 3581, 0, + 0, 3723, 0, + 0, 3863, 0, + 0, 4001, 0, + 3997, 0, 3821, + 3997, 0, 3821, + 3997, 0, 3821, + 3997, 0, 3821, + 3997, 0, 3821, + 3997, 0, 3821, + 3997, 0, 3821, + 3997, 0, 3821, + 3997, 0, 3819, + 3997, 0, 3819, + 3995, 0, 3819, + 3995, 0, 3817, + 3993, 0, 3817, + 3991, 0, 3815, + 3989, 0, 3811, + 3987, 0, 3809, + 3983, 0, 3805, + 3979, 0, 3799, + 3971, 0, 3791, + 3961, 0, 3779, + 3949, 0, 3765, + 3931, 1828, 3745, + 3907, 2367, 3715, + 3871, 2665, 3673, + 3817, 2891, 3609, + 3735, 3083, 3507, + 3597, 3255, 3319, + 3301, 3415, 2801, + 0, 3567, 0, + 0, 3713, 0, + 0, 3855, 0, + 0, 3995, 0, + 4095, 0, 3951, + 4095, 0, 3951, + 4095, 0, 3951, + 4095, 0, 3951, + 4095, 0, 3951, + 4095, 0, 3951, + 4095, 0, 3951, + 4095, 0, 3951, + 4095, 0, 3951, + 4095, 0, 3951, + 4095, 0, 3949, + 4095, 0, 3949, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3945, + 4095, 0, 3943, + 4095, 0, 3939, + 4095, 0, 3935, + 4095, 0, 3929, + 4095, 0, 3921, + 4093, 0, 3909, + 4081, 0, 3895, + 4063, 1938, 3875, + 4037, 2493, 3845, + 4001, 2795, 3801, + 3949, 3021, 3737, + 3867, 3215, 3635, + 3729, 3387, 3447, + 3431, 3547, 2917, + 0, 3699, 0, + 0, 3845, 0, + 0, 3987, 0, + 4095, 0, 4083, + 4095, 0, 4083, + 4095, 0, 4083, + 4095, 0, 4083, + 4095, 0, 4083, + 4095, 0, 4083, + 4095, 0, 4081, + 4095, 0, 4081, + 4095, 0, 4081, + 4095, 0, 4081, + 4095, 0, 4081, + 4095, 0, 4081, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4077, + 4095, 0, 4075, + 4095, 0, 4073, + 4095, 0, 4069, + 4095, 0, 4065, + 4095, 0, 4059, + 4095, 0, 4051, + 4095, 0, 4041, + 4095, 0, 4025, + 4095, 2053, 4005, + 4095, 2621, 3975, + 4095, 2925, 3933, + 4081, 3153, 3867, + 3999, 3345, 3765, + 3859, 3517, 3575, + 3563, 3679, 3035, + 0, 3831, 0, + 0, 3977, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2173, 4095, + 4095, 2749, 4095, + 4095, 3055, 4063, + 4095, 3283, 3999, + 4095, 3477, 3895, + 3991, 3649, 3703, + 3693, 3809, 3157, + 0, 3963, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2295, 4095, + 4095, 2877, 4095, + 4095, 3185, 4095, + 4095, 3415, 4095, + 4095, 3609, 4025, + 4095, 3781, 3833, + 3825, 3941, 3283, + 1643, 1209, 2051, + 1635, 1218, 2049, + 1623, 1230, 2045, + 1607, 1245, 2040, + 1585, 1264, 2033, + 1554, 1289, 2025, + 1508, 1321, 2012, + 1439, 1359, 1996, + 1326, 1406, 1972, + 1110, 1462, 1939, + 353, 1528, 1891, + 0, 1603, 1817, + 0, 1688, 1694, + 0, 1780, 1449, + 0, 1881, 80, + 0, 1987, 0, + 0, 2099, 0, + 0, 2217, 0, + 0, 2337, 0, + 0, 2459, 0, + 0, 2585, 0, + 0, 2711, 0, + 0, 2839, 0, + 0, 2969, 0, + 0, 3099, 0, + 0, 3229, 0, + 0, 3361, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3885, 0, + 0, 4017, 0, + 1653, 1208, 2053, + 1645, 1217, 2051, + 1634, 1229, 2047, + 1618, 1244, 2043, + 1597, 1263, 2036, + 1566, 1288, 2028, + 1522, 1319, 2016, + 1455, 1358, 1999, + 1346, 1405, 1976, + 1143, 1462, 1943, + 505, 1527, 1895, + 0, 1603, 1821, + 0, 1687, 1700, + 0, 1780, 1460, + 0, 1880, 260, + 0, 1987, 0, + 0, 2099, 0, + 0, 2217, 0, + 0, 2337, 0, + 0, 2459, 0, + 0, 2585, 0, + 0, 2711, 0, + 0, 2839, 0, + 0, 2969, 0, + 0, 3099, 0, + 0, 3229, 0, + 0, 3359, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3885, 0, + 0, 4017, 0, + 1667, 1206, 2057, + 1659, 1215, 2055, + 1648, 1227, 2051, + 1633, 1242, 2047, + 1612, 1262, 2040, + 1583, 1287, 2032, + 1540, 1318, 2020, + 1476, 1357, 2003, + 1373, 1404, 1980, + 1184, 1461, 1948, + 652, 1526, 1900, + 0, 1602, 1828, + 0, 1686, 1708, + 0, 1779, 1474, + 0, 1880, 426, + 0, 1987, 0, + 0, 2099, 0, + 0, 2215, 0, + 0, 2337, 0, + 0, 2459, 0, + 0, 2585, 0, + 0, 2711, 0, + 0, 2839, 0, + 0, 2969, 0, + 0, 3099, 0, + 0, 3229, 0, + 0, 3359, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3885, 0, + 0, 4017, 0, + 1685, 1204, 2063, + 1677, 1213, 2061, + 1667, 1224, 2057, + 1652, 1240, 2051, + 1632, 1259, 2046, + 1604, 1284, 2037, + 1563, 1316, 2025, + 1503, 1355, 2009, + 1406, 1403, 1986, + 1233, 1459, 1954, + 795, 1525, 1907, + 0, 1601, 1836, + 0, 1686, 1719, + 0, 1779, 1492, + 0, 1879, 581, + 0, 1986, 0, + 0, 2099, 0, + 0, 2215, 0, + 0, 2337, 0, + 0, 2459, 0, + 0, 2585, 0, + 0, 2711, 0, + 0, 2839, 0, + 0, 2969, 0, + 0, 3099, 0, + 0, 3229, 0, + 0, 3359, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3885, 0, + 0, 4017, 0, + 1707, 1200, 2069, + 1700, 1209, 2067, + 1690, 1221, 2063, + 1676, 1237, 2059, + 1657, 1256, 2053, + 1631, 1282, 2044, + 1593, 1313, 2033, + 1536, 1353, 2017, + 1447, 1400, 1994, + 1292, 1457, 1963, + 935, 1524, 1917, + 0, 1599, 1847, + 0, 1684, 1733, + 0, 1778, 1515, + 0, 1879, 730, + 0, 1986, 0, + 0, 2099, 0, + 0, 2215, 0, + 0, 2335, 0, + 0, 2459, 0, + 0, 2585, 0, + 0, 2711, 0, + 0, 2839, 0, + 0, 2969, 0, + 0, 3099, 0, + 0, 3229, 0, + 0, 3359, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3885, 0, + 0, 4017, 0, + 1736, 1196, 2079, + 1729, 1205, 2075, + 1720, 1217, 2073, + 1707, 1232, 2067, + 1689, 1252, 2061, + 1664, 1278, 2053, + 1629, 1310, 2042, + 1577, 1349, 2026, + 1496, 1397, 2005, + 1360, 1455, 1974, + 1073, 1521, 1929, + 0, 1598, 1861, + 0, 1683, 1752, + 0, 1776, 1545, + 0, 1878, 874, + 0, 1985, 0, + 0, 2097, 0, + 0, 2215, 0, + 0, 2335, 0, + 0, 2459, 0, + 0, 2585, 0, + 0, 2711, 0, + 0, 2839, 0, + 0, 2969, 0, + 0, 3099, 0, + 0, 3229, 0, + 0, 3359, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3885, 0, + 0, 4017, 0, + 1771, 1189, 2089, + 1765, 1199, 2087, + 1756, 1211, 2083, + 1745, 1227, 2079, + 1728, 1247, 2073, + 1706, 1273, 2065, + 1674, 1305, 2055, + 1627, 1345, 2039, + 1555, 1393, 2018, + 1437, 1451, 1988, + 1209, 1518, 1945, + 272, 1595, 1880, + 0, 1681, 1775, + 0, 1775, 1581, + 0, 1876, 1015, + 0, 1984, 0, + 0, 2097, 0, + 0, 2215, 0, + 0, 2335, 0, + 0, 2459, 0, + 0, 2583, 0, + 0, 2711, 0, + 0, 2839, 0, + 0, 2969, 0, + 0, 3099, 0, + 0, 3229, 0, + 0, 3359, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3885, 0, + 0, 4017, 0, + 1815, 1181, 2105, + 1809, 1191, 2103, + 1801, 1203, 2099, + 1791, 1219, 2095, + 1776, 1240, 2089, + 1756, 1266, 2081, + 1727, 1299, 2071, + 1685, 1339, 2057, + 1623, 1388, 2036, + 1524, 1446, 2007, + 1344, 1514, 1966, + 870, 1592, 1903, + 0, 1678, 1804, + 0, 1772, 1625, + 0, 1874, 1153, + 0, 1982, 0, + 0, 2095, 0, + 0, 2213, 0, + 0, 2335, 0, + 0, 2457, 0, + 0, 2583, 0, + 0, 2711, 0, + 0, 2839, 0, + 0, 2969, 0, + 0, 3099, 0, + 0, 3229, 0, + 0, 3359, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3885, 0, + 0, 4017, 0, + 1867, 1170, 2123, + 1862, 1179, 2121, + 1855, 1192, 2119, + 1846, 1209, 2115, + 1833, 1230, 2109, + 1815, 1256, 2101, + 1790, 1290, 2091, + 1754, 1331, 2077, + 1701, 1381, 2059, + 1619, 1440, 2031, + 1479, 1509, 1992, + 1180, 1587, 1933, + 0, 1674, 1841, + 0, 1769, 1678, + 0, 1872, 1290, + 0, 1981, 0, + 0, 2095, 0, + 0, 2213, 0, + 0, 2333, 0, + 0, 2457, 0, + 0, 2583, 0, + 0, 2711, 0, + 0, 2839, 0, + 0, 2969, 0, + 0, 3099, 0, + 0, 3229, 0, + 0, 3359, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3885, 0, + 0, 4017, 0, + 1929, 1154, 2149, + 1925, 1164, 2147, + 1919, 1177, 2143, + 1910, 1194, 2139, + 1899, 1216, 2135, + 1884, 1243, 2127, + 1862, 1278, 2117, + 1832, 1320, 2105, + 1788, 1371, 2087, + 1721, 1432, 2061, + 1613, 1501, 2024, + 1410, 1581, 1970, + 782, 1669, 1886, + 0, 1765, 1741, + 0, 1869, 1426, + 0, 1978, 0, + 0, 2093, 0, + 0, 2211, 0, + 0, 2333, 0, + 0, 2457, 0, + 0, 2583, 0, + 0, 2709, 0, + 0, 2839, 0, + 0, 2967, 0, + 0, 3097, 0, + 0, 3229, 0, + 0, 3359, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2001, 1132, 2179, + 1997, 1143, 2177, + 1992, 1156, 2175, + 1985, 1174, 2171, + 1975, 1197, 2167, + 1962, 1226, 2159, + 1944, 1261, 2151, + 1919, 1305, 2139, + 1883, 1358, 2121, + 1829, 1420, 2097, + 1746, 1491, 2065, + 1604, 1572, 2015, + 1299, 1662, 1939, + 0, 1760, 1813, + 0, 1864, 1560, + 0, 1974, 0, + 0, 2089, 0, + 0, 2209, 0, + 0, 2331, 0, + 0, 2455, 0, + 0, 2581, 0, + 0, 2709, 0, + 0, 2837, 0, + 0, 2967, 0, + 0, 3097, 0, + 0, 3229, 0, + 0, 3359, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2081, 1101, 2217, + 2079, 1112, 2215, + 2073, 1127, 2213, + 2069, 1146, 2211, + 2061, 1170, 2205, + 2049, 1200, 2199, + 2034, 1238, 2191, + 2014, 1284, 2181, + 1985, 1339, 2165, + 1943, 1404, 2143, + 1879, 1478, 2113, + 1778, 1561, 2069, + 1593, 1653, 2003, + 1089, 1752, 1895, + 0, 1858, 1695, + 0, 1970, 1079, + 0, 2085, 0, + 0, 2205, 0, + 0, 2329, 0, + 0, 2453, 0, + 0, 2579, 0, + 0, 2709, 0, + 0, 2837, 0, + 0, 2967, 0, + 0, 3097, 0, + 0, 3229, 0, + 0, 3359, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2171, 1056, 2265, + 2169, 1068, 2263, + 2165, 1084, 2261, + 2159, 1105, 2257, + 2153, 1132, 2253, + 2145, 1164, 2249, + 2133, 1205, 2241, + 2117, 1254, 2231, + 2093, 1313, 2217, + 2061, 1381, 2197, + 2012, 1458, 2171, + 1939, 1545, 2133, + 1817, 1640, 2075, + 1578, 1742, 1985, + 385, 1850, 1828, + 0, 1963, 1462, + 0, 2081, 0, + 0, 2201, 0, + 0, 2325, 0, + 0, 2451, 0, + 0, 2579, 0, + 0, 2707, 0, + 0, 2837, 0, + 0, 2967, 0, + 0, 3097, 0, + 0, 3227, 0, + 0, 3359, 0, + 0, 3491, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2269, 988, 2321, + 2267, 1002, 2319, + 2263, 1021, 2317, + 2259, 1044, 2315, + 2255, 1074, 2311, + 2247, 1112, 2305, + 2237, 1157, 2299, + 2225, 1211, 2291, + 2207, 1275, 2279, + 2181, 1349, 2261, + 2145, 1431, 2239, + 2091, 1523, 2205, + 2008, 1622, 2157, + 1865, 1727, 2083, + 1556, 1839, 1961, + 0, 1955, 1720, + 0, 2075, 451, + 0, 2197, 0, + 0, 2321, 0, + 0, 2449, 0, + 0, 2577, 0, + 0, 2705, 0, + 0, 2835, 0, + 0, 2965, 0, + 0, 3095, 0, + 0, 3227, 0, + 0, 3359, 0, + 0, 3491, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2373, 877, 2385, + 2371, 895, 2385, + 2369, 918, 2383, + 2365, 948, 2381, + 2361, 985, 2377, + 2357, 1029, 2373, + 2349, 1083, 2367, + 2339, 1147, 2359, + 2325, 1220, 2349, + 2305, 1302, 2335, + 2277, 1393, 2315, + 2237, 1491, 2287, + 2179, 1597, 2247, + 2087, 1708, 2189, + 1922, 1823, 2095, + 1526, 1943, 1927, + 0, 2065, 1516, + 0, 2189, 0, + 0, 2317, 0, + 0, 2445, 0, + 0, 2573, 0, + 0, 2703, 0, + 0, 2833, 0, + 0, 2963, 0, + 0, 3095, 0, + 0, 3227, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2483, 666, 2461, + 2481, 695, 2459, + 2479, 731, 2457, + 2477, 775, 2455, + 2475, 828, 2453, + 2469, 890, 2449, + 2463, 962, 2445, + 2457, 1043, 2439, + 2445, 1133, 2429, + 2431, 1230, 2417, + 2409, 1335, 2401, + 2381, 1445, 2379, + 2339, 1561, 2347, + 2275, 1680, 2299, + 2173, 1802, 2227, + 1988, 1926, 2109, + 1481, 2053, 1877, + 0, 2181, 879, + 0, 2309, 0, + 0, 2439, 0, + 0, 2569, 0, + 0, 2699, 0, + 0, 2831, 0, + 0, 2963, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2597, 0, 2543, + 2597, 84, 2543, + 2595, 209, 2541, + 2593, 335, 2541, + 2591, 463, 2539, + 2587, 592, 2535, + 2583, 721, 2531, + 2577, 852, 2527, + 2569, 982, 2519, + 2557, 1113, 2509, + 2543, 1244, 2495, + 2521, 1376, 2477, + 2489, 1508, 2451, + 2445, 1640, 2415, + 2379, 1771, 2359, + 2269, 1903, 2273, + 2065, 2035, 2127, + 1415, 2167, 1799, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2717, 0, 2637, + 2715, 0, 2635, + 2715, 0, 2635, + 2713, 0, 2633, + 2711, 0, 2631, + 2709, 0, 2629, + 2705, 0, 2627, + 2701, 304, 2621, + 2695, 644, 2617, + 2687, 886, 2609, + 2675, 1086, 2597, + 2659, 1263, 2583, + 2635, 1426, 2563, + 2605, 1580, 2533, + 2557, 1727, 2493, + 2487, 1871, 2429, + 2371, 2011, 2329, + 2149, 2149, 2149, + 1306, 2287, 1669, + 0, 2421, 0, + 0, 2557, 0, + 0, 2691, 0, + 0, 2823, 0, + 0, 2957, 0, + 0, 3089, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2839, 0, 2737, + 2837, 0, 2735, + 2837, 0, 2735, + 2837, 0, 2735, + 2835, 0, 2733, + 2833, 0, 2731, + 2831, 0, 2729, + 2827, 0, 2725, + 2821, 0, 2721, + 2815, 0, 2713, + 2807, 713, 2705, + 2795, 1046, 2693, + 2779, 1286, 2679, + 2755, 1484, 2655, + 2723, 1661, 2625, + 2675, 1823, 2579, + 2601, 1977, 2509, + 2481, 2125, 2395, + 2243, 2267, 2179, + 1103, 2407, 1404, + 0, 2547, 0, + 0, 2683, 0, + 0, 2819, 0, + 0, 2953, 0, + 0, 3087, 0, + 0, 3221, 0, + 0, 3353, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4017, 0, + 2963, 0, 2843, + 2963, 0, 2843, + 2961, 0, 2841, + 2961, 0, 2841, + 2959, 0, 2839, + 2959, 0, 2839, + 2957, 0, 2837, + 2953, 0, 2833, + 2951, 0, 2831, + 2945, 0, 2825, + 2939, 0, 2819, + 2929, 276, 2809, + 2917, 987, 2797, + 2901, 1315, 2781, + 2877, 1553, 2757, + 2843, 1750, 2723, + 2795, 1926, 2673, + 2719, 2089, 2597, + 2595, 2241, 2471, + 2343, 2389, 2215, + 471, 2533, 0, + 0, 2673, 0, + 0, 2811, 0, + 0, 2947, 0, + 0, 3083, 0, + 0, 3217, 0, + 0, 3351, 0, + 0, 3485, 0, + 0, 3617, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 3089, 0, 2955, + 3089, 0, 2955, + 3089, 0, 2955, + 3087, 0, 2953, + 3087, 0, 2953, + 3085, 0, 2951, + 3085, 0, 2949, + 3083, 0, 2947, + 3079, 0, 2945, + 3075, 0, 2941, + 3071, 0, 2937, + 3065, 0, 2929, + 3055, 0, 2919, + 3043, 894, 2907, + 3025, 1351, 2889, + 3001, 1631, 2863, + 2967, 1848, 2829, + 2917, 2035, 2775, + 2841, 2205, 2693, + 2713, 2363, 2555, + 2451, 2513, 2259, + 0, 2659, 0, + 0, 2801, 0, + 0, 2939, 0, + 0, 3077, 0, + 0, 3213, 0, + 0, 3347, 0, + 0, 3483, 0, + 0, 3615, 0, + 0, 3749, 0, + 0, 3883, 0, + 0, 4015, 0, + 3217, 0, 3071, + 3217, 0, 3071, + 3217, 0, 3071, + 3215, 0, 3071, + 3215, 0, 3069, + 3215, 0, 3069, + 3213, 0, 3067, + 3211, 0, 3065, + 3209, 0, 3063, + 3207, 0, 3061, + 3203, 0, 3057, + 3199, 0, 3051, + 3191, 0, 3045, + 3183, 0, 3035, + 3169, 729, 3021, + 3153, 1396, 3003, + 3129, 1717, 2977, + 3093, 1953, 2939, + 3043, 2149, 2883, + 2965, 2325, 2797, + 2833, 2485, 2647, + 2563, 2639, 2313, + 0, 2785, 0, + 0, 2929, 0, + 0, 3069, 0, + 0, 3207, 0, + 0, 3343, 0, + 0, 3479, 0, + 0, 3613, 0, + 0, 3747, 0, + 0, 3881, 0, + 0, 4013, 0, + 3345, 0, 3191, + 3345, 0, 3191, + 3345, 0, 3191, + 3345, 0, 3191, + 3345, 0, 3191, + 3343, 0, 3189, + 3343, 0, 3189, + 3341, 0, 3187, + 3341, 0, 3185, + 3339, 0, 3183, + 3335, 0, 3181, + 3331, 0, 3177, + 3327, 0, 3171, + 3319, 0, 3163, + 3311, 0, 3153, + 3299, 330, 3139, + 3281, 1449, 3121, + 3257, 1813, 3093, + 3221, 2063, 3055, + 3169, 2267, 2997, + 3091, 2447, 2907, + 2957, 2611, 2747, + 2681, 2767, 2375, + 0, 2915, 0, + 0, 3059, 0, + 0, 3199, 0, + 0, 3337, 0, + 0, 3475, 0, + 0, 3611, 0, + 0, 3745, 0, + 0, 3879, 0, + 0, 4013, 0, + 3475, 0, 3315, + 3475, 0, 3315, + 3475, 0, 3313, + 3475, 0, 3313, + 3475, 0, 3313, + 3473, 0, 3313, + 3473, 0, 3313, + 3473, 0, 3311, + 3471, 0, 3309, + 3469, 0, 3309, + 3467, 0, 3305, + 3465, 0, 3303, + 3461, 0, 3299, + 3457, 0, 3293, + 3449, 0, 3285, + 3439, 0, 3275, + 3427, 0, 3261, + 3409, 1512, 3241, + 3385, 1915, 3213, + 3349, 2179, 3175, + 3299, 2389, 3115, + 3219, 2571, 3021, + 3083, 2739, 2855, + 2801, 2895, 2447, + 0, 3045, 0, + 0, 3189, 0, + 0, 3331, 0, + 0, 3469, 0, + 0, 3607, 0, + 0, 3741, 0, + 0, 3877, 0, + 0, 4011, 0, + 3605, 0, 3439, + 3605, 0, 3439, + 3605, 0, 3439, + 3605, 0, 3439, + 3605, 0, 3439, + 3605, 0, 3439, + 3603, 0, 3437, + 3603, 0, 3437, + 3603, 0, 3437, + 3601, 0, 3435, + 3599, 0, 3433, + 3597, 0, 3431, + 3595, 0, 3427, + 3591, 0, 3423, + 3587, 0, 3417, + 3579, 0, 3411, + 3569, 0, 3399, + 3557, 0, 3385, + 3539, 1585, 3365, + 3515, 2023, 3337, + 3479, 2297, 3297, + 3427, 2513, 3235, + 3347, 2699, 3139, + 3211, 2867, 2967, + 2925, 3025, 2529, + 0, 3175, 0, + 0, 3319, 0, + 0, 3461, 0, + 0, 3601, 0, + 0, 3737, 0, + 0, 3873, 0, + 0, 4009, 0, + 3737, 0, 3567, + 3737, 0, 3567, + 3735, 0, 3567, + 3735, 0, 3565, + 3735, 0, 3565, + 3735, 0, 3565, + 3735, 0, 3565, + 3735, 0, 3565, + 3733, 0, 3563, + 3733, 0, 3563, + 3731, 0, 3561, + 3731, 0, 3559, + 3729, 0, 3557, + 3725, 0, 3555, + 3721, 0, 3549, + 3717, 0, 3545, + 3709, 0, 3537, + 3701, 0, 3525, + 3687, 0, 3511, + 3669, 1666, 3491, + 3645, 2137, 3463, + 3609, 2419, 3421, + 3557, 2639, 3359, + 3477, 2827, 3261, + 3339, 2995, 3083, + 3049, 3155, 2619, + 0, 3305, 0, + 0, 3451, 0, + 0, 3593, 0, + 0, 3731, 0, + 0, 3869, 0, + 0, 4005, 0, + 3867, 0, 3695, + 3867, 0, 3695, + 3867, 0, 3695, + 3867, 0, 3695, + 3867, 0, 3693, + 3867, 0, 3693, + 3867, 0, 3693, + 3867, 0, 3693, + 3865, 0, 3693, + 3865, 0, 3691, + 3865, 0, 3691, + 3863, 0, 3689, + 3861, 0, 3687, + 3859, 0, 3685, + 3857, 0, 3683, + 3853, 0, 3677, + 3847, 0, 3673, + 3841, 0, 3665, + 3831, 0, 3653, + 3819, 0, 3639, + 3801, 1757, 3619, + 3775, 2255, 3589, + 3741, 2543, 3547, + 3687, 2765, 3485, + 3607, 2955, 3385, + 3469, 3125, 3203, + 3177, 3285, 2717, + 0, 3437, 0, + 0, 3581, 0, + 0, 3725, 0, + 0, 3863, 0, + 0, 4001, 0, + 3999, 0, 3823, + 3999, 0, 3823, + 3999, 0, 3823, + 3999, 0, 3823, + 3999, 0, 3823, + 3999, 0, 3823, + 3997, 0, 3823, + 3997, 0, 3823, + 3997, 0, 3821, + 3997, 0, 3821, + 3997, 0, 3821, + 3995, 0, 3819, + 3995, 0, 3819, + 3993, 0, 3817, + 3991, 0, 3815, + 3987, 0, 3811, + 3983, 0, 3807, + 3979, 0, 3801, + 3971, 0, 3793, + 3963, 0, 3783, + 3949, 0, 3767, + 3931, 1855, 3747, + 3907, 2375, 3717, + 3871, 2671, 3675, + 3819, 2895, 3613, + 3737, 3085, 3511, + 3599, 3257, 3327, + 3305, 3415, 2823, + 0, 3567, 0, + 0, 3713, 0, + 0, 3855, 0, + 0, 3995, 0, + 4095, 0, 3953, + 4095, 0, 3953, + 4095, 0, 3953, + 4095, 0, 3953, + 4095, 0, 3953, + 4095, 0, 3953, + 4095, 0, 3953, + 4095, 0, 3953, + 4095, 0, 3953, + 4095, 0, 3951, + 4095, 0, 3951, + 4095, 0, 3951, + 4095, 0, 3949, + 4095, 0, 3949, + 4095, 0, 3947, + 4095, 0, 3945, + 4095, 0, 3941, + 4095, 0, 3937, + 4095, 0, 3931, + 4095, 0, 3923, + 4093, 0, 3911, + 4081, 0, 3897, + 4063, 1960, 3877, + 4039, 2499, 3847, + 4003, 2797, 3805, + 3949, 3023, 3741, + 3869, 3215, 3639, + 3729, 3387, 3451, + 3435, 3547, 2933, + 0, 3699, 0, + 0, 3845, 0, + 0, 3987, 0, + 4095, 0, 4083, + 4095, 0, 4083, + 4095, 0, 4083, + 4095, 0, 4083, + 4095, 0, 4083, + 4095, 0, 4083, + 4095, 0, 4083, + 4095, 0, 4083, + 4095, 0, 4083, + 4095, 0, 4083, + 4095, 0, 4083, + 4095, 0, 4081, + 4095, 0, 4081, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4077, + 4095, 0, 4075, + 4095, 0, 4071, + 4095, 0, 4067, + 4095, 0, 4061, + 4095, 0, 4053, + 4095, 0, 4043, + 4095, 0, 4027, + 4095, 2071, 4007, + 4095, 2625, 3977, + 4095, 2927, 3935, + 4081, 3155, 3869, + 3999, 3347, 3767, + 3861, 3519, 3579, + 3563, 3679, 3049, + 0, 3831, 0, + 0, 3977, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2187, 4095, + 4095, 2753, 4095, + 4095, 3057, 4065, + 4095, 3285, 4001, + 4095, 3477, 3897, + 3991, 3651, 3707, + 3695, 3811, 3167, + 0, 3963, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2305, 4095, + 4095, 2881, 4095, + 4095, 3187, 4095, + 4095, 3415, 4095, + 4095, 3609, 4027, + 4095, 3781, 3835, + 3825, 3943, 3291, + 1773, 1336, 2183, + 1767, 1342, 2181, + 1759, 1351, 2179, + 1747, 1363, 2175, + 1731, 1378, 2169, + 1708, 1398, 2163, + 1676, 1422, 2155, + 1629, 1453, 2143, + 1558, 1492, 2125, + 1442, 1539, 2101, + 1216, 1595, 2069, + 324, 1661, 2020, + 0, 1736, 1945, + 0, 1820, 1821, + 0, 1913, 1573, + 0, 2013, 6, + 0, 2119, 0, + 0, 2231, 0, + 0, 2349, 0, + 0, 2469, 0, + 0, 2591, 0, + 0, 2717, 0, + 0, 2843, 0, + 0, 2971, 0, + 0, 3101, 0, + 0, 3231, 0, + 0, 3361, 0, + 0, 3493, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 1781, 1335, 2185, + 1775, 1341, 2183, + 1767, 1350, 2181, + 1755, 1362, 2177, + 1739, 1377, 2171, + 1717, 1397, 2165, + 1686, 1421, 2157, + 1640, 1453, 2145, + 1571, 1491, 2127, + 1458, 1538, 2105, + 1242, 1594, 2071, + 485, 1660, 2023, + 0, 1735, 1949, + 0, 1820, 1826, + 0, 1912, 1582, + 0, 2013, 212, + 0, 2119, 0, + 0, 2231, 0, + 0, 2349, 0, + 0, 2469, 0, + 0, 2591, 0, + 0, 2717, 0, + 0, 2843, 0, + 0, 2971, 0, + 0, 3101, 0, + 0, 3231, 0, + 0, 3361, 0, + 0, 3493, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 1792, 1333, 2187, + 1786, 1340, 2185, + 1777, 1349, 2183, + 1766, 1361, 2179, + 1751, 1376, 2175, + 1729, 1395, 2169, + 1699, 1420, 2159, + 1654, 1452, 2147, + 1587, 1490, 2131, + 1479, 1537, 2107, + 1275, 1594, 2075, + 637, 1659, 2027, + 0, 1735, 1954, + 0, 1819, 1832, + 0, 1912, 1592, + 0, 2012, 393, + 0, 2119, 0, + 0, 2231, 0, + 0, 2349, 0, + 0, 2469, 0, + 0, 2591, 0, + 0, 2717, 0, + 0, 2843, 0, + 0, 2971, 0, + 0, 3101, 0, + 0, 3231, 0, + 0, 3361, 0, + 0, 3493, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 1805, 1331, 2191, + 1799, 1338, 2189, + 1791, 1347, 2187, + 1780, 1359, 2183, + 1765, 1374, 2179, + 1744, 1394, 2173, + 1715, 1419, 2163, + 1672, 1450, 2151, + 1608, 1489, 2135, + 1505, 1536, 2113, + 1316, 1593, 2079, + 784, 1659, 2032, + 0, 1734, 1960, + 0, 1819, 1840, + 0, 1912, 1606, + 0, 2012, 558, + 0, 2119, 0, + 0, 2231, 0, + 0, 2349, 0, + 0, 2469, 0, + 0, 2591, 0, + 0, 2717, 0, + 0, 2843, 0, + 0, 2971, 0, + 0, 3101, 0, + 0, 3231, 0, + 0, 3361, 0, + 0, 3493, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 1823, 1329, 2197, + 1817, 1336, 2195, + 1809, 1345, 2193, + 1799, 1356, 2189, + 1784, 1372, 2185, + 1764, 1392, 2177, + 1736, 1417, 2169, + 1695, 1448, 2157, + 1635, 1487, 2141, + 1538, 1535, 2119, + 1365, 1591, 2087, + 927, 1657, 2040, + 0, 1733, 1968, + 0, 1818, 1851, + 0, 1911, 1624, + 0, 2011, 713, + 0, 2119, 0, + 0, 2231, 0, + 0, 2347, 0, + 0, 2469, 0, + 0, 2591, 0, + 0, 2717, 0, + 0, 2843, 0, + 0, 2971, 0, + 0, 3101, 0, + 0, 3231, 0, + 0, 3361, 0, + 0, 3493, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 1845, 1325, 2203, + 1839, 1332, 2201, + 1832, 1341, 2199, + 1822, 1353, 2195, + 1809, 1369, 2191, + 1790, 1389, 2185, + 1763, 1414, 2177, + 1725, 1446, 2165, + 1668, 1485, 2149, + 1579, 1532, 2127, + 1424, 1589, 2095, + 1067, 1656, 2049, + 0, 1732, 1979, + 0, 1817, 1865, + 0, 1910, 1647, + 0, 2011, 862, + 0, 2117, 0, + 0, 2231, 0, + 0, 2347, 0, + 0, 2467, 0, + 0, 2591, 0, + 0, 2717, 0, + 0, 2843, 0, + 0, 2971, 0, + 0, 3101, 0, + 0, 3231, 0, + 0, 3361, 0, + 0, 3493, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 1873, 1321, 2213, + 1868, 1328, 2211, + 1861, 1337, 2207, + 1852, 1349, 2205, + 1839, 1365, 2199, + 1821, 1385, 2193, + 1797, 1410, 2185, + 1761, 1442, 2175, + 1709, 1482, 2159, + 1628, 1530, 2137, + 1492, 1587, 2107, + 1205, 1653, 2061, + 0, 1730, 1994, + 0, 1815, 1884, + 0, 1909, 1677, + 0, 2010, 1006, + 0, 2117, 0, + 0, 2229, 0, + 0, 2347, 0, + 0, 2467, 0, + 0, 2591, 0, + 0, 2717, 0, + 0, 2843, 0, + 0, 2971, 0, + 0, 3101, 0, + 0, 3231, 0, + 0, 3361, 0, + 0, 3493, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 1908, 1315, 2223, + 1904, 1322, 2221, + 1897, 1331, 2219, + 1889, 1343, 2217, + 1877, 1359, 2211, + 1861, 1379, 2205, + 1838, 1405, 2197, + 1806, 1437, 2187, + 1759, 1477, 2171, + 1687, 1526, 2151, + 1570, 1583, 2121, + 1341, 1650, 2077, + 404, 1727, 2012, + 0, 1813, 1907, + 0, 1907, 1713, + 0, 2008, 1147, + 0, 2117, 0, + 0, 2229, 0, + 0, 2347, 0, + 0, 2467, 0, + 0, 2591, 0, + 0, 2715, 0, + 0, 2843, 0, + 0, 2971, 0, + 0, 3101, 0, + 0, 3231, 0, + 0, 3361, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4017, 0, + 1951, 1306, 2239, + 1947, 1313, 2237, + 1941, 1323, 2235, + 1934, 1335, 2231, + 1923, 1351, 2227, + 1908, 1372, 2221, + 1888, 1398, 2213, + 1859, 1431, 2203, + 1818, 1471, 2189, + 1755, 1520, 2167, + 1656, 1579, 2139, + 1476, 1646, 2097, + 1002, 1724, 2036, + 0, 1810, 1936, + 0, 1905, 1757, + 0, 2007, 1285, + 0, 2115, 0, + 0, 2227, 0, + 0, 2345, 0, + 0, 2467, 0, + 0, 2589, 0, + 0, 2715, 0, + 0, 2843, 0, + 0, 2971, 0, + 0, 3101, 0, + 0, 3231, 0, + 0, 3361, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4017, 0, + 2003, 1294, 2257, + 2000, 1302, 2257, + 1994, 1312, 2253, + 1987, 1324, 2251, + 1978, 1341, 2247, + 1965, 1362, 2241, + 1947, 1389, 2233, + 1922, 1422, 2223, + 1886, 1463, 2209, + 1833, 1513, 2191, + 1751, 1572, 2163, + 1611, 1641, 2123, + 1312, 1719, 2065, + 0, 1806, 1973, + 0, 1902, 1811, + 0, 2004, 1422, + 0, 2113, 0, + 0, 2227, 0, + 0, 2345, 0, + 0, 2465, 0, + 0, 2589, 0, + 0, 2715, 0, + 0, 2843, 0, + 0, 2971, 0, + 0, 3101, 0, + 0, 3231, 0, + 0, 3361, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4017, 0, + 2065, 1278, 2283, + 2061, 1286, 2281, + 2057, 1296, 2279, + 2051, 1309, 2275, + 2043, 1326, 2271, + 2031, 1348, 2267, + 2016, 1376, 2259, + 1994, 1410, 2249, + 1964, 1452, 2237, + 1920, 1503, 2219, + 1853, 1564, 2193, + 1745, 1634, 2157, + 1543, 1713, 2103, + 914, 1801, 2018, + 0, 1897, 1873, + 0, 2001, 1558, + 0, 2111, 0, + 0, 2225, 0, + 0, 2343, 0, + 0, 2465, 0, + 0, 2589, 0, + 0, 2715, 0, + 0, 2841, 0, + 0, 2971, 0, + 0, 3099, 0, + 0, 3231, 0, + 0, 3361, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4017, 0, + 2135, 1256, 2313, + 2133, 1264, 2311, + 2129, 1275, 2309, + 2123, 1289, 2307, + 2117, 1306, 2303, + 2107, 1329, 2299, + 2095, 1358, 2291, + 2077, 1393, 2283, + 2051, 1437, 2271, + 2015, 1490, 2253, + 1961, 1552, 2231, + 1878, 1624, 2197, + 1737, 1704, 2147, + 1431, 1794, 2071, + 0, 1892, 1946, + 0, 1996, 1693, + 0, 2107, 0, + 0, 2221, 0, + 0, 2341, 0, + 0, 2463, 0, + 0, 2587, 0, + 0, 2713, 0, + 0, 2841, 0, + 0, 2969, 0, + 0, 3099, 0, + 0, 3229, 0, + 0, 3361, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4017, 0, + 2215, 1225, 2351, + 2213, 1233, 2349, + 2211, 1244, 2347, + 2205, 1259, 2345, + 2201, 1278, 2343, + 2193, 1302, 2337, + 2181, 1333, 2331, + 2167, 1370, 2323, + 2145, 1416, 2313, + 2117, 1471, 2297, + 2075, 1536, 2275, + 2011, 1610, 2245, + 1910, 1693, 2201, + 1725, 1785, 2135, + 1221, 1884, 2027, + 0, 1990, 1827, + 0, 2101, 1211, + 0, 2219, 0, + 0, 2337, 0, + 0, 2461, 0, + 0, 2585, 0, + 0, 2713, 0, + 0, 2841, 0, + 0, 2969, 0, + 0, 3099, 0, + 0, 3229, 0, + 0, 3361, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3885, 0, + 0, 4017, 0, + 2305, 1179, 2397, + 2303, 1188, 2397, + 2301, 1200, 2395, + 2297, 1217, 2393, + 2293, 1237, 2389, + 2285, 1264, 2385, + 2277, 1297, 2381, + 2265, 1337, 2373, + 2249, 1387, 2363, + 2225, 1445, 2349, + 2193, 1513, 2329, + 2145, 1591, 2303, + 2071, 1677, 2265, + 1949, 1772, 2207, + 1710, 1874, 2117, + 517, 1982, 1960, + 0, 2095, 1594, + 0, 2213, 0, + 0, 2335, 0, + 0, 2457, 0, + 0, 2583, 0, + 0, 2711, 0, + 0, 2839, 0, + 0, 2969, 0, + 0, 3099, 0, + 0, 3229, 0, + 0, 3359, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3885, 0, + 0, 4017, 0, + 2401, 1109, 2453, + 2401, 1120, 2453, + 2399, 1134, 2451, + 2395, 1153, 2449, + 2391, 1177, 2447, + 2387, 1206, 2443, + 2379, 1244, 2437, + 2369, 1289, 2431, + 2357, 1344, 2423, + 2339, 1407, 2411, + 2313, 1481, 2393, + 2277, 1564, 2371, + 2223, 1655, 2337, + 2139, 1754, 2289, + 1997, 1860, 2215, + 1688, 1971, 2093, + 0, 2087, 1852, + 0, 2207, 583, + 0, 2329, 0, + 0, 2453, 0, + 0, 2581, 0, + 0, 2709, 0, + 0, 2837, 0, + 0, 2967, 0, + 0, 3097, 0, + 0, 3229, 0, + 0, 3359, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2505, 995, 2519, + 2505, 1009, 2517, + 2503, 1027, 2517, + 2501, 1050, 2515, + 2497, 1080, 2513, + 2493, 1117, 2509, + 2489, 1162, 2505, + 2481, 1216, 2499, + 2471, 1279, 2491, + 2457, 1352, 2481, + 2437, 1434, 2467, + 2409, 1525, 2447, + 2369, 1623, 2419, + 2311, 1729, 2381, + 2219, 1840, 2321, + 2055, 1955, 2227, + 1658, 2075, 2059, + 0, 2197, 1649, + 0, 2321, 0, + 0, 2449, 0, + 0, 2577, 0, + 0, 2705, 0, + 0, 2835, 0, + 0, 2965, 0, + 0, 3097, 0, + 0, 3227, 0, + 0, 3359, 0, + 0, 3491, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2615, 775, 2593, + 2615, 798, 2593, + 2613, 827, 2591, + 2611, 863, 2589, + 2609, 907, 2587, + 2607, 960, 2585, + 2601, 1022, 2581, + 2597, 1094, 2577, + 2589, 1175, 2571, + 2577, 1265, 2561, + 2563, 1363, 2551, + 2541, 1467, 2533, + 2513, 1578, 2511, + 2471, 1693, 2479, + 2407, 1812, 2431, + 2305, 1934, 2359, + 2121, 2059, 2241, + 1614, 2185, 2009, + 0, 2313, 1012, + 0, 2441, 0, + 0, 2571, 0, + 0, 2701, 0, + 0, 2831, 0, + 0, 2963, 0, + 0, 3095, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2731, 0, 2677, + 2729, 94, 2677, + 2729, 216, 2675, + 2727, 341, 2675, + 2725, 467, 2673, + 2723, 595, 2671, + 2719, 724, 2667, + 2715, 853, 2663, + 2709, 984, 2659, + 2701, 1114, 2651, + 2689, 1245, 2641, + 2675, 1377, 2629, + 2653, 1508, 2609, + 2621, 1640, 2583, + 2577, 1772, 2547, + 2511, 1904, 2491, + 2401, 2035, 2407, + 2197, 2167, 2259, + 1547, 2299, 1931, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2849, 0, 2769, + 2849, 0, 2769, + 2847, 0, 2767, + 2847, 0, 2767, + 2845, 0, 2765, + 2843, 0, 2763, + 2841, 0, 2761, + 2837, 0, 2759, + 2833, 436, 2755, + 2827, 776, 2749, + 2819, 1018, 2741, + 2807, 1218, 2729, + 2791, 1395, 2715, + 2769, 1558, 2695, + 2737, 1712, 2665, + 2689, 1859, 2625, + 2619, 2003, 2561, + 2503, 2143, 2463, + 2281, 2281, 2281, + 1438, 2419, 1802, + 0, 2553, 0, + 0, 2689, 0, + 0, 2823, 0, + 0, 2955, 0, + 0, 3089, 0, + 0, 3221, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3885, 0, + 0, 4017, 0, + 2971, 0, 2869, + 2971, 0, 2869, + 2971, 0, 2867, + 2969, 0, 2867, + 2969, 0, 2867, + 2967, 0, 2865, + 2965, 0, 2863, + 2963, 0, 2861, + 2959, 0, 2857, + 2953, 0, 2853, + 2947, 96, 2847, + 2939, 845, 2837, + 2927, 1178, 2827, + 2911, 1418, 2811, + 2887, 1617, 2789, + 2855, 1793, 2757, + 2807, 1955, 2711, + 2733, 2109, 2641, + 2613, 2257, 2527, + 2375, 2399, 2311, + 1236, 2539, 1536, + 0, 2679, 0, + 0, 2815, 0, + 0, 2951, 0, + 0, 3085, 0, + 0, 3219, 0, + 0, 3353, 0, + 0, 3485, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 3095, 0, 2975, + 3095, 0, 2975, + 3095, 0, 2975, + 3095, 0, 2973, + 3093, 0, 2973, + 3093, 0, 2973, + 3091, 0, 2971, + 3089, 0, 2969, + 3085, 0, 2965, + 3083, 0, 2963, + 3077, 0, 2957, + 3071, 0, 2951, + 3063, 409, 2941, + 3049, 1119, 2929, + 3033, 1447, 2913, + 3009, 1685, 2889, + 2975, 1883, 2855, + 2927, 2059, 2805, + 2851, 2221, 2729, + 2727, 2373, 2603, + 2475, 2521, 2347, + 602, 2665, 0, + 0, 2805, 0, + 0, 2943, 0, + 0, 3079, 0, + 0, 3215, 0, + 0, 3349, 0, + 0, 3483, 0, + 0, 3617, 0, + 0, 3749, 0, + 0, 3883, 0, + 0, 4015, 0, + 3221, 0, 3087, + 3221, 0, 3087, + 3221, 0, 3087, + 3221, 0, 3087, + 3219, 0, 3085, + 3219, 0, 3085, + 3217, 0, 3083, + 3217, 0, 3083, + 3215, 0, 3079, + 3211, 0, 3077, + 3209, 0, 3073, + 3203, 0, 3069, + 3197, 0, 3061, + 3187, 0, 3051, + 3175, 1026, 3039, + 3159, 1483, 3021, + 3135, 1763, 2997, + 3099, 1980, 2961, + 3049, 2167, 2907, + 2973, 2337, 2825, + 2845, 2495, 2687, + 2583, 2645, 2391, + 0, 2791, 0, + 0, 2933, 0, + 0, 3071, 0, + 0, 3209, 0, + 0, 3345, 0, + 0, 3479, 0, + 0, 3615, 0, + 0, 3747, 0, + 0, 3881, 0, + 0, 4015, 0, + 3349, 0, 3203, + 3349, 0, 3203, + 3349, 0, 3203, + 3349, 0, 3203, + 3347, 0, 3203, + 3347, 0, 3201, + 3347, 0, 3201, + 3345, 0, 3199, + 3343, 0, 3199, + 3341, 0, 3195, + 3339, 0, 3193, + 3335, 0, 3189, + 3331, 0, 3183, + 3323, 0, 3177, + 3315, 0, 3167, + 3303, 861, 3153, + 3285, 1528, 3135, + 3261, 1850, 3109, + 3225, 2085, 3071, + 3175, 2281, 3015, + 3097, 2457, 2929, + 2965, 2617, 2779, + 2695, 2771, 2445, + 0, 2919, 0, + 0, 3061, 0, + 0, 3201, 0, + 0, 3339, 0, + 0, 3475, 0, + 0, 3611, 0, + 0, 3745, 0, + 0, 3879, 0, + 0, 4013, 0, + 3477, 0, 3323, + 3477, 0, 3323, + 3477, 0, 3323, + 3477, 0, 3323, + 3477, 0, 3323, + 3477, 0, 3323, + 3475, 0, 3321, + 3475, 0, 3321, + 3473, 0, 3319, + 3473, 0, 3317, + 3471, 0, 3315, + 3467, 0, 3313, + 3463, 0, 3309, + 3459, 0, 3303, + 3453, 0, 3295, + 3443, 0, 3285, + 3431, 462, 3271, + 3413, 1581, 3253, + 3389, 1945, 3225, + 3353, 2195, 3187, + 3303, 2399, 3129, + 3223, 2579, 3039, + 3089, 2743, 2879, + 2813, 2899, 2507, + 0, 3047, 0, + 0, 3191, 0, + 0, 3331, 0, + 0, 3469, 0, + 0, 3607, 0, + 0, 3743, 0, + 0, 3877, 0, + 0, 4011, 0, + 3607, 0, 3447, + 3607, 0, 3447, + 3607, 0, 3447, + 3607, 0, 3447, + 3607, 0, 3445, + 3607, 0, 3445, + 3605, 0, 3445, + 3605, 0, 3445, + 3605, 0, 3443, + 3603, 0, 3441, + 3601, 0, 3441, + 3599, 0, 3439, + 3597, 0, 3435, + 3593, 0, 3431, + 3589, 0, 3425, + 3581, 0, 3417, + 3573, 0, 3407, + 3559, 0, 3393, + 3541, 1644, 3373, + 3517, 2047, 3347, + 3483, 2311, 3307, + 3431, 2521, 3247, + 3351, 2703, 3153, + 3215, 2871, 2987, + 2933, 3027, 2579, + 0, 3177, 0, + 0, 3321, 0, + 0, 3463, 0, + 0, 3601, 0, + 0, 3739, 0, + 0, 3875, 0, + 0, 4009, 0, + 3737, 0, 3571, + 3737, 0, 3571, + 3737, 0, 3571, + 3737, 0, 3571, + 3737, 0, 3571, + 3737, 0, 3571, + 3737, 0, 3571, + 3737, 0, 3569, + 3735, 0, 3569, + 3735, 0, 3569, + 3733, 0, 3567, + 3731, 0, 3565, + 3729, 0, 3563, + 3727, 0, 3559, + 3723, 0, 3555, + 3719, 0, 3549, + 3711, 0, 3543, + 3703, 0, 3531, + 3689, 0, 3517, + 3671, 1717, 3497, + 3647, 2155, 3469, + 3611, 2429, 3429, + 3559, 2645, 3367, + 3479, 2831, 3271, + 3343, 2999, 3099, + 3057, 3157, 2661, + 0, 3307, 0, + 0, 3451, 0, + 0, 3593, 0, + 0, 3733, 0, + 0, 3869, 0, + 0, 4005, 0, + 3869, 0, 3699, + 3869, 0, 3699, + 3869, 0, 3699, + 3869, 0, 3699, + 3867, 0, 3697, + 3867, 0, 3697, + 3867, 0, 3697, + 3867, 0, 3697, + 3867, 0, 3697, + 3867, 0, 3695, + 3865, 0, 3695, + 3865, 0, 3693, + 3863, 0, 3691, + 3861, 0, 3689, + 3857, 0, 3687, + 3853, 0, 3683, + 3849, 0, 3677, + 3841, 0, 3669, + 3833, 0, 3657, + 3819, 0, 3643, + 3801, 1798, 3623, + 3777, 2269, 3595, + 3741, 2551, 3553, + 3689, 2771, 3491, + 3609, 2959, 3393, + 3471, 3129, 3215, + 3181, 3287, 2751, + 0, 3437, 0, + 0, 3583, 0, + 0, 3725, 0, + 0, 3865, 0, + 0, 4001, 0, + 3999, 0, 3827, + 3999, 0, 3827, + 3999, 0, 3827, + 3999, 0, 3827, + 3999, 0, 3827, + 3999, 0, 3827, + 3999, 0, 3825, + 3999, 0, 3825, + 3999, 0, 3825, + 3997, 0, 3825, + 3997, 0, 3823, + 3997, 0, 3823, + 3995, 0, 3821, + 3993, 0, 3819, + 3991, 0, 3817, + 3989, 0, 3815, + 3985, 0, 3809, + 3979, 0, 3805, + 3973, 0, 3797, + 3963, 0, 3785, + 3951, 0, 3771, + 3933, 1889, 3751, + 3907, 2387, 3721, + 3873, 2677, 3679, + 3819, 2899, 3617, + 3739, 3087, 3517, + 3601, 3259, 3335, + 3309, 3417, 2849, + 0, 3569, 0, + 0, 3715, 0, + 0, 3857, 0, + 0, 3995, 0, + 4095, 0, 3955, + 4095, 0, 3955, + 4095, 0, 3955, + 4095, 0, 3955, + 4095, 0, 3955, + 4095, 0, 3955, + 4095, 0, 3955, + 4095, 0, 3955, + 4095, 0, 3955, + 4095, 0, 3955, + 4095, 0, 3953, + 4095, 0, 3953, + 4095, 0, 3951, + 4095, 0, 3951, + 4095, 0, 3949, + 4095, 0, 3947, + 4095, 0, 3943, + 4095, 0, 3939, + 4095, 0, 3933, + 4095, 0, 3925, + 4095, 0, 3915, + 4081, 0, 3899, + 4063, 1987, 3879, + 4039, 2507, 3849, + 4003, 2803, 3807, + 3951, 3027, 3745, + 3869, 3217, 3643, + 3731, 3389, 3459, + 3437, 3549, 2955, + 0, 3699, 0, + 0, 3845, 0, + 0, 3987, 0, + 4095, 0, 4085, + 4095, 0, 4085, + 4095, 0, 4085, + 4095, 0, 4085, + 4095, 0, 4085, + 4095, 0, 4085, + 4095, 0, 4085, + 4095, 0, 4085, + 4095, 0, 4085, + 4095, 0, 4085, + 4095, 0, 4083, + 4095, 0, 4083, + 4095, 0, 4083, + 4095, 0, 4081, + 4095, 0, 4081, + 4095, 0, 4079, + 4095, 0, 4077, + 4095, 0, 4073, + 4095, 0, 4069, + 4095, 0, 4063, + 4095, 0, 4055, + 4095, 0, 4043, + 4095, 0, 4029, + 4095, 2093, 4009, + 4095, 2631, 3979, + 4095, 2931, 3937, + 4081, 3157, 3873, + 4001, 3347, 3771, + 3861, 3519, 3583, + 3567, 3679, 3065, + 0, 3831, 0, + 0, 3977, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2203, 4095, + 4095, 2757, 4095, + 4095, 3059, 4067, + 4095, 3287, 4003, + 4095, 3479, 3899, + 3993, 3651, 3711, + 3697, 3811, 3181, + 0, 3963, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2319, 4095, + 4095, 2885, 4095, + 4095, 3189, 4095, + 4095, 3417, 4095, + 4095, 3609, 4029, + 4095, 3783, 3839, + 3827, 3943, 3299, + 1904, 1463, 2315, + 1900, 1469, 2313, + 1893, 1475, 2311, + 1884, 1484, 2309, + 1873, 1496, 2305, + 1856, 1511, 2301, + 1833, 1530, 2293, + 1801, 1555, 2285, + 1753, 1586, 2273, + 1681, 1625, 2255, + 1561, 1672, 2233, + 1327, 1728, 2199, + 282, 1793, 2149, + 0, 1868, 2075, + 0, 1952, 1949, + 0, 2045, 1699, + 0, 2145, 0, + 0, 2253, 0, + 0, 2365, 0, + 0, 2481, 0, + 0, 2601, 0, + 0, 2723, 0, + 0, 2849, 0, + 0, 2975, 0, + 0, 3105, 0, + 0, 3233, 0, + 0, 3363, 0, + 0, 3493, 0, + 0, 3625, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 1910, 1463, 2317, + 1906, 1468, 2315, + 1899, 1475, 2313, + 1891, 1483, 2311, + 1879, 1495, 2307, + 1863, 1510, 2301, + 1840, 1530, 2295, + 1808, 1554, 2287, + 1761, 1586, 2275, + 1690, 1624, 2257, + 1574, 1671, 2235, + 1348, 1727, 2201, + 456, 1793, 2151, + 0, 1868, 2077, + 0, 1952, 1953, + 0, 2045, 1706, + 0, 2145, 138, + 0, 2251, 0, + 0, 2365, 0, + 0, 2481, 0, + 0, 2601, 0, + 0, 2723, 0, + 0, 2849, 0, + 0, 2975, 0, + 0, 3103, 0, + 0, 3233, 0, + 0, 3363, 0, + 0, 3493, 0, + 0, 3625, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 1918, 1462, 2319, + 1913, 1467, 2317, + 1907, 1474, 2315, + 1899, 1482, 2313, + 1887, 1494, 2309, + 1871, 1509, 2305, + 1849, 1529, 2297, + 1818, 1554, 2289, + 1772, 1585, 2277, + 1703, 1623, 2261, + 1590, 1670, 2237, + 1374, 1727, 2203, + 617, 1792, 2155, + 0, 1867, 2081, + 0, 1952, 1958, + 0, 2045, 1714, + 0, 2145, 344, + 0, 2251, 0, + 0, 2363, 0, + 0, 2481, 0, + 0, 2601, 0, + 0, 2723, 0, + 0, 2849, 0, + 0, 2975, 0, + 0, 3103, 0, + 0, 3233, 0, + 0, 3363, 0, + 0, 3493, 0, + 0, 3625, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 1928, 1460, 2321, + 1924, 1465, 2319, + 1918, 1472, 2317, + 1909, 1481, 2315, + 1898, 1493, 2311, + 1883, 1508, 2307, + 1861, 1528, 2301, + 1831, 1552, 2291, + 1786, 1584, 2279, + 1719, 1622, 2263, + 1611, 1670, 2241, + 1407, 1726, 2207, + 769, 1792, 2159, + 0, 1867, 2085, + 0, 1951, 1964, + 0, 2044, 1724, + 0, 2145, 525, + 0, 2251, 0, + 0, 2363, 0, + 0, 2481, 0, + 0, 2601, 0, + 0, 2723, 0, + 0, 2849, 0, + 0, 2975, 0, + 0, 3103, 0, + 0, 3233, 0, + 0, 3363, 0, + 0, 3493, 0, + 0, 3625, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 1942, 1458, 2325, + 1937, 1463, 2323, + 1931, 1470, 2321, + 1923, 1479, 2319, + 1912, 1491, 2315, + 1897, 1506, 2311, + 1877, 1526, 2305, + 1847, 1551, 2295, + 1804, 1582, 2283, + 1740, 1621, 2267, + 1637, 1668, 2245, + 1448, 1725, 2213, + 916, 1791, 2165, + 0, 1866, 2093, + 0, 1951, 1972, + 0, 2044, 1738, + 0, 2145, 690, + 0, 2251, 0, + 0, 2363, 0, + 0, 2481, 0, + 0, 2601, 0, + 0, 2723, 0, + 0, 2849, 0, + 0, 2975, 0, + 0, 3103, 0, + 0, 3233, 0, + 0, 3363, 0, + 0, 3493, 0, + 0, 3625, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 1959, 1456, 2331, + 1955, 1461, 2329, + 1949, 1468, 2327, + 1941, 1477, 2325, + 1931, 1489, 2321, + 1916, 1504, 2317, + 1896, 1524, 2309, + 1868, 1549, 2301, + 1828, 1580, 2289, + 1767, 1619, 2273, + 1670, 1667, 2251, + 1497, 1723, 2219, + 1059, 1789, 2171, + 0, 1865, 2101, + 0, 1950, 1983, + 0, 2043, 1757, + 0, 2143, 845, + 0, 2251, 0, + 0, 2363, 0, + 0, 2479, 0, + 0, 2601, 0, + 0, 2723, 0, + 0, 2849, 0, + 0, 2975, 0, + 0, 3103, 0, + 0, 3233, 0, + 0, 3363, 0, + 0, 3493, 0, + 0, 3625, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 1981, 1452, 2337, + 1977, 1457, 2335, + 1972, 1464, 2333, + 1964, 1474, 2331, + 1954, 1485, 2327, + 1941, 1501, 2323, + 1922, 1521, 2317, + 1895, 1546, 2309, + 1857, 1578, 2297, + 1800, 1617, 2281, + 1711, 1665, 2259, + 1556, 1721, 2227, + 1199, 1788, 2181, + 0, 1864, 2111, + 0, 1949, 1998, + 0, 2042, 1780, + 0, 2143, 994, + 0, 2251, 0, + 0, 2363, 0, + 0, 2479, 0, + 0, 2601, 0, + 0, 2723, 0, + 0, 2849, 0, + 0, 2975, 0, + 0, 3103, 0, + 0, 3233, 0, + 0, 3363, 0, + 0, 3493, 0, + 0, 3625, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 2009, 1448, 2345, + 2005, 1453, 2345, + 2000, 1460, 2343, + 1993, 1469, 2339, + 1984, 1481, 2337, + 1971, 1497, 2333, + 1953, 1517, 2325, + 1929, 1542, 2317, + 1893, 1574, 2307, + 1841, 1614, 2291, + 1761, 1662, 2269, + 1624, 1719, 2239, + 1337, 1786, 2193, + 0, 1862, 2125, + 0, 1947, 2016, + 0, 2041, 1809, + 0, 2141, 1138, + 0, 2249, 0, + 0, 2363, 0, + 0, 2479, 0, + 0, 2599, 0, + 0, 2723, 0, + 0, 2849, 0, + 0, 2975, 0, + 0, 3103, 0, + 0, 3233, 0, + 0, 3363, 0, + 0, 3493, 0, + 0, 3625, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 2044, 1441, 2357, + 2040, 1447, 2355, + 2036, 1454, 2353, + 2029, 1463, 2351, + 2021, 1475, 2349, + 2009, 1491, 2343, + 1993, 1511, 2337, + 1970, 1537, 2329, + 1938, 1569, 2319, + 1891, 1609, 2303, + 1819, 1658, 2283, + 1702, 1715, 2253, + 1473, 1783, 2209, + 536, 1859, 2145, + 0, 1945, 2039, + 0, 2039, 1845, + 0, 2141, 1279, + 0, 2249, 0, + 0, 2361, 0, + 0, 2479, 0, + 0, 2599, 0, + 0, 2723, 0, + 0, 2849, 0, + 0, 2975, 0, + 0, 3103, 0, + 0, 3233, 0, + 0, 3363, 0, + 0, 3493, 0, + 0, 3625, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 2087, 1433, 2371, + 2083, 1438, 2371, + 2079, 1445, 2369, + 2073, 1455, 2367, + 2065, 1467, 2363, + 2055, 1483, 2359, + 2040, 1504, 2353, + 2020, 1530, 2345, + 1991, 1563, 2335, + 1950, 1603, 2321, + 1887, 1652, 2299, + 1788, 1711, 2271, + 1609, 1779, 2229, + 1134, 1856, 2167, + 0, 1942, 2069, + 0, 2037, 1889, + 0, 2139, 1417, + 0, 2247, 0, + 0, 2361, 0, + 0, 2477, 0, + 0, 2599, 0, + 0, 2723, 0, + 0, 2847, 0, + 0, 2975, 0, + 0, 3103, 0, + 0, 3233, 0, + 0, 3363, 0, + 0, 3493, 0, + 0, 3625, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 2139, 1421, 2391, + 2135, 1427, 2389, + 2131, 1434, 2389, + 2127, 1444, 2385, + 2119, 1456, 2383, + 2111, 1473, 2379, + 2097, 1494, 2373, + 2079, 1521, 2365, + 2055, 1554, 2355, + 2018, 1595, 2341, + 1965, 1645, 2323, + 1883, 1704, 2295, + 1743, 1773, 2255, + 1444, 1851, 2197, + 0, 1938, 2105, + 0, 2034, 1943, + 0, 2137, 1554, + 0, 2245, 0, + 0, 2359, 0, + 0, 2477, 0, + 0, 2597, 0, + 0, 2721, 0, + 0, 2847, 0, + 0, 2975, 0, + 0, 3103, 0, + 0, 3233, 0, + 0, 3363, 0, + 0, 3493, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 2199, 1405, 2415, + 2197, 1411, 2415, + 2193, 1418, 2413, + 2189, 1428, 2411, + 2183, 1441, 2407, + 2175, 1458, 2403, + 2163, 1480, 2399, + 2149, 1508, 2391, + 2127, 1542, 2383, + 2097, 1584, 2369, + 2051, 1635, 2351, + 1985, 1696, 2325, + 1877, 1766, 2289, + 1675, 1845, 2235, + 1046, 1933, 2149, + 0, 2030, 2005, + 0, 2133, 1690, + 0, 2243, 0, + 0, 2357, 0, + 0, 2475, 0, + 0, 2597, 0, + 0, 2721, 0, + 0, 2847, 0, + 0, 2973, 0, + 0, 3103, 0, + 0, 3233, 0, + 0, 3363, 0, + 0, 3493, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 2269, 1382, 2447, + 2267, 1388, 2445, + 2265, 1396, 2443, + 2261, 1407, 2441, + 2255, 1421, 2439, + 2249, 1438, 2435, + 2239, 1461, 2431, + 2227, 1490, 2423, + 2209, 1526, 2415, + 2183, 1569, 2403, + 2147, 1622, 2385, + 2093, 1684, 2363, + 2010, 1756, 2329, + 1869, 1837, 2279, + 1564, 1926, 2203, + 0, 2024, 2077, + 0, 2129, 1825, + 0, 2239, 0, + 0, 2353, 0, + 0, 2473, 0, + 0, 2595, 0, + 0, 2719, 0, + 0, 2845, 0, + 0, 2973, 0, + 0, 3101, 0, + 0, 3231, 0, + 0, 3361, 0, + 0, 3493, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 2349, 1350, 2485, + 2347, 1357, 2483, + 2345, 1365, 2481, + 2343, 1377, 2481, + 2339, 1391, 2477, + 2333, 1410, 2475, + 2325, 1434, 2469, + 2313, 1465, 2463, + 2299, 1502, 2455, + 2279, 1548, 2445, + 2249, 1603, 2429, + 2207, 1668, 2407, + 2143, 1742, 2377, + 2042, 1825, 2333, + 1857, 1917, 2267, + 1353, 2016, 2159, + 0, 2123, 1959, + 0, 2233, 1343, + 0, 2351, 0, + 0, 2469, 0, + 0, 2593, 0, + 0, 2717, 0, + 0, 2845, 0, + 0, 2973, 0, + 0, 3101, 0, + 0, 3231, 0, + 0, 3361, 0, + 0, 3493, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 2439, 1303, 2531, + 2437, 1311, 2529, + 2435, 1320, 2529, + 2433, 1333, 2527, + 2429, 1349, 2525, + 2425, 1369, 2521, + 2417, 1396, 2517, + 2409, 1429, 2513, + 2397, 1469, 2505, + 2381, 1519, 2495, + 2357, 1577, 2481, + 2325, 1645, 2463, + 2277, 1723, 2435, + 2203, 1809, 2397, + 2081, 1904, 2339, + 1842, 2006, 2249, + 650, 2115, 2093, + 0, 2227, 1726, + 0, 2345, 0, + 0, 2467, 0, + 0, 2589, 0, + 0, 2715, 0, + 0, 2843, 0, + 0, 2971, 0, + 0, 3101, 0, + 0, 3231, 0, + 0, 3361, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4017, 0, + 2535, 1232, 2587, + 2535, 1241, 2585, + 2533, 1252, 2585, + 2531, 1266, 2583, + 2527, 1285, 2581, + 2523, 1309, 2579, + 2519, 1339, 2575, + 2511, 1376, 2569, + 2503, 1421, 2563, + 2489, 1476, 2555, + 2471, 1540, 2543, + 2445, 1613, 2527, + 2409, 1696, 2503, + 2355, 1787, 2469, + 2271, 1886, 2421, + 2129, 1992, 2347, + 1820, 2103, 2225, + 0, 2219, 1984, + 0, 2339, 715, + 0, 2461, 0, + 0, 2585, 0, + 0, 2713, 0, + 0, 2841, 0, + 0, 2969, 0, + 0, 3099, 0, + 0, 3229, 0, + 0, 3361, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3885, 0, + 0, 4017, 0, + 2639, 1115, 2651, + 2639, 1126, 2651, + 2637, 1141, 2649, + 2635, 1159, 2649, + 2633, 1182, 2647, + 2629, 1212, 2645, + 2625, 1249, 2641, + 2621, 1294, 2637, + 2613, 1348, 2631, + 2603, 1411, 2623, + 2589, 1484, 2613, + 2569, 1566, 2599, + 2541, 1657, 2579, + 2503, 1756, 2553, + 2443, 1861, 2513, + 2351, 1972, 2453, + 2187, 2087, 2359, + 1790, 2207, 2191, + 0, 2329, 1781, + 0, 2455, 0, + 0, 2581, 0, + 0, 2709, 0, + 0, 2837, 0, + 0, 2967, 0, + 0, 3097, 0, + 0, 3229, 0, + 0, 3359, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2749, 890, 2725, + 2749, 908, 2725, + 2747, 930, 2725, + 2745, 959, 2723, + 2743, 995, 2721, + 2741, 1039, 2719, + 2739, 1092, 2717, + 2735, 1154, 2713, + 2729, 1226, 2709, + 2721, 1307, 2703, + 2709, 1397, 2695, + 2695, 1495, 2683, + 2673, 1599, 2665, + 2645, 1710, 2643, + 2603, 1825, 2611, + 2539, 1944, 2563, + 2437, 2067, 2491, + 2253, 2191, 2373, + 1746, 2317, 2141, + 0, 2445, 1143, + 0, 2573, 0, + 0, 2703, 0, + 0, 2833, 0, + 0, 2965, 0, + 0, 3095, 0, + 0, 3227, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2863, 0, 2809, + 2863, 107, 2809, + 2863, 226, 2809, + 2861, 348, 2807, + 2859, 473, 2807, + 2857, 599, 2805, + 2855, 727, 2803, + 2851, 856, 2799, + 2847, 986, 2795, + 2841, 1116, 2791, + 2833, 1246, 2783, + 2821, 1377, 2773, + 2807, 1509, 2761, + 2785, 1640, 2741, + 2755, 1772, 2715, + 2709, 1904, 2679, + 2643, 2036, 2623, + 2533, 2167, 2539, + 2329, 2299, 2391, + 1679, 2431, 2063, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2981, 0, 2901, + 2981, 0, 2901, + 2981, 0, 2901, + 2981, 0, 2899, + 2979, 0, 2899, + 2977, 0, 2897, + 2975, 0, 2895, + 2973, 0, 2893, + 2969, 0, 2891, + 2965, 568, 2887, + 2959, 908, 2881, + 2951, 1150, 2873, + 2939, 1350, 2861, + 2923, 1527, 2847, + 2901, 1690, 2827, + 2869, 1844, 2797, + 2821, 1992, 2757, + 2751, 2135, 2693, + 2635, 2275, 2595, + 2413, 2413, 2413, + 1570, 2551, 1934, + 0, 2685, 0, + 0, 2821, 0, + 0, 2955, 0, + 0, 3087, 0, + 0, 3221, 0, + 0, 3353, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3885, 0, + 0, 4017, 0, + 3103, 0, 3001, + 3103, 0, 3001, + 3103, 0, 3001, + 3103, 0, 3001, + 3101, 0, 2999, + 3101, 0, 2999, + 3099, 0, 2997, + 3097, 0, 2995, + 3095, 0, 2993, + 3091, 0, 2989, + 3087, 0, 2985, + 3079, 228, 2979, + 3071, 978, 2969, + 3059, 1310, 2959, + 3043, 1550, 2943, + 3019, 1749, 2921, + 2987, 1925, 2889, + 2939, 2087, 2843, + 2865, 2241, 2773, + 2745, 2389, 2659, + 2507, 2531, 2443, + 1368, 2673, 1669, + 0, 2811, 0, + 0, 2947, 0, + 0, 3083, 0, + 0, 3217, 0, + 0, 3351, 0, + 0, 3485, 0, + 0, 3617, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 3227, 0, 3107, + 3227, 0, 3107, + 3227, 0, 3107, + 3227, 0, 3107, + 3227, 0, 3107, + 3225, 0, 3105, + 3225, 0, 3105, + 3223, 0, 3103, + 3221, 0, 3101, + 3219, 0, 3099, + 3215, 0, 3095, + 3209, 0, 3089, + 3203, 0, 3083, + 3195, 541, 3073, + 3183, 1251, 3061, + 3165, 1579, 3045, + 3141, 1817, 3021, + 3109, 2015, 2987, + 3059, 2191, 2937, + 2983, 2353, 2861, + 2859, 2505, 2735, + 2609, 2653, 2479, + 735, 2797, 0, + 0, 2937, 0, + 0, 3075, 0, + 0, 3211, 0, + 0, 3347, 0, + 0, 3481, 0, + 0, 3615, 0, + 0, 3749, 0, + 0, 3881, 0, + 0, 4015, 0, + 3353, 0, 3219, + 3353, 0, 3219, + 3353, 0, 3219, + 3353, 0, 3219, + 3353, 0, 3219, + 3353, 0, 3217, + 3351, 0, 3217, + 3351, 0, 3215, + 3349, 0, 3215, + 3347, 0, 3213, + 3343, 0, 3209, + 3341, 0, 3205, + 3335, 0, 3201, + 3329, 0, 3193, + 3319, 0, 3185, + 3307, 1158, 3171, + 3291, 1616, 3153, + 3267, 1895, 3129, + 3233, 2113, 3093, + 3183, 2299, 3039, + 3105, 2469, 2957, + 2977, 2627, 2819, + 2715, 2777, 2523, + 0, 2923, 0, + 0, 3065, 0, + 0, 3203, 0, + 0, 3341, 0, + 0, 3477, 0, + 0, 3613, 0, + 0, 3747, 0, + 0, 3881, 0, + 0, 4013, 0, + 3481, 0, 3337, + 3481, 0, 3335, + 3481, 0, 3335, + 3481, 0, 3335, + 3481, 0, 3335, + 3481, 0, 3335, + 3479, 0, 3333, + 3479, 0, 3333, + 3477, 0, 3331, + 3475, 0, 3331, + 3473, 0, 3327, + 3471, 0, 3325, + 3467, 0, 3321, + 3463, 0, 3315, + 3455, 0, 3309, + 3447, 0, 3299, + 3435, 994, 3285, + 3417, 1660, 3267, + 3393, 1982, 3241, + 3359, 2217, 3203, + 3307, 2413, 3147, + 3229, 2589, 3061, + 3097, 2749, 2911, + 2827, 2903, 2577, + 0, 3051, 0, + 0, 3193, 0, + 0, 3333, 0, + 0, 3471, 0, + 0, 3607, 0, + 0, 3743, 0, + 0, 3877, 0, + 0, 4011, 0, + 3611, 0, 3457, + 3611, 0, 3455, + 3609, 0, 3455, + 3609, 0, 3455, + 3609, 0, 3455, + 3609, 0, 3455, + 3609, 0, 3455, + 3607, 0, 3453, + 3607, 0, 3453, + 3605, 0, 3451, + 3605, 0, 3449, + 3603, 0, 3447, + 3599, 0, 3445, + 3595, 0, 3441, + 3591, 0, 3435, + 3585, 0, 3427, + 3575, 0, 3417, + 3563, 594, 3403, + 3545, 1714, 3385, + 3521, 2077, 3357, + 3485, 2327, 3319, + 3435, 2531, 3261, + 3355, 2711, 3171, + 3221, 2875, 3011, + 2945, 3031, 2639, + 0, 3179, 0, + 0, 3323, 0, + 0, 3463, 0, + 0, 3603, 0, + 0, 3739, 0, + 0, 3875, 0, + 0, 4009, 0, + 3739, 0, 3579, + 3739, 0, 3579, + 3739, 0, 3579, + 3739, 0, 3579, + 3739, 0, 3579, + 3739, 0, 3577, + 3739, 0, 3577, + 3739, 0, 3577, + 3737, 0, 3577, + 3737, 0, 3575, + 3735, 0, 3575, + 3733, 0, 3573, + 3731, 0, 3571, + 3729, 0, 3567, + 3725, 0, 3563, + 3721, 0, 3557, + 3713, 0, 3549, + 3705, 0, 3539, + 3691, 0, 3525, + 3673, 1776, 3505, + 3649, 2179, 3479, + 3615, 2443, 3439, + 3563, 2653, 3379, + 3483, 2835, 3285, + 3347, 3003, 3119, + 3065, 3159, 2711, + 0, 3309, 0, + 0, 3453, 0, + 0, 3595, 0, + 0, 3733, 0, + 0, 3871, 0, + 0, 4007, 0, + 3869, 0, 3703, + 3869, 0, 3703, + 3869, 0, 3703, + 3869, 0, 3703, + 3869, 0, 3703, + 3869, 0, 3703, + 3869, 0, 3703, + 3869, 0, 3703, + 3869, 0, 3701, + 3867, 0, 3701, + 3867, 0, 3701, + 3865, 0, 3699, + 3863, 0, 3697, + 3861, 0, 3695, + 3859, 0, 3691, + 3855, 0, 3687, + 3851, 0, 3683, + 3843, 0, 3675, + 3835, 0, 3663, + 3821, 0, 3649, + 3803, 1849, 3629, + 3779, 2287, 3601, + 3743, 2561, 3561, + 3691, 2777, 3499, + 3611, 2963, 3403, + 3475, 3131, 3231, + 3189, 3289, 2793, + 0, 3439, 0, + 0, 3583, 0, + 0, 3725, 0, + 0, 3865, 0, + 0, 4001, 0, + 4001, 0, 3831, + 4001, 0, 3831, + 4001, 0, 3831, + 4001, 0, 3831, + 4001, 0, 3831, + 4001, 0, 3831, + 3999, 0, 3829, + 3999, 0, 3829, + 3999, 0, 3829, + 3999, 0, 3829, + 3999, 0, 3827, + 3997, 0, 3827, + 3997, 0, 3825, + 3995, 0, 3823, + 3993, 0, 3821, + 3989, 0, 3819, + 3985, 0, 3815, + 3981, 0, 3809, + 3975, 0, 3801, + 3965, 0, 3791, + 3951, 0, 3775, + 3935, 1931, 3755, + 3909, 2401, 3727, + 3873, 2683, 3685, + 3821, 2903, 3623, + 3741, 3091, 3525, + 3603, 3261, 3347, + 3313, 3419, 2883, + 0, 3569, 0, + 0, 3715, 0, + 0, 3857, 0, + 0, 3997, 0, + 4095, 0, 3959, + 4095, 0, 3959, + 4095, 0, 3959, + 4095, 0, 3959, + 4095, 0, 3959, + 4095, 0, 3959, + 4095, 0, 3959, + 4095, 0, 3957, + 4095, 0, 3957, + 4095, 0, 3957, + 4095, 0, 3957, + 4095, 0, 3955, + 4095, 0, 3955, + 4095, 0, 3953, + 4095, 0, 3951, + 4095, 0, 3949, + 4095, 0, 3947, + 4095, 0, 3943, + 4095, 0, 3937, + 4095, 0, 3929, + 4095, 0, 3917, + 4083, 0, 3903, + 4065, 2021, 3883, + 4041, 2519, 3853, + 4005, 2809, 3811, + 3951, 3031, 3749, + 3871, 3219, 3649, + 3733, 3391, 3467, + 3441, 3549, 2981, + 0, 3701, 0, + 0, 3847, 0, + 0, 3989, 0, + 4095, 0, 4087, + 4095, 0, 4087, + 4095, 0, 4087, + 4095, 0, 4087, + 4095, 0, 4087, + 4095, 0, 4087, + 4095, 0, 4087, + 4095, 0, 4087, + 4095, 0, 4087, + 4095, 0, 4087, + 4095, 0, 4087, + 4095, 0, 4085, + 4095, 0, 4085, + 4095, 0, 4083, + 4095, 0, 4083, + 4095, 0, 4081, + 4095, 0, 4079, + 4095, 0, 4075, + 4095, 0, 4071, + 4095, 0, 4065, + 4095, 0, 4057, + 4095, 0, 4047, + 4095, 0, 4031, + 4095, 2119, 4011, + 4095, 2639, 3981, + 4095, 2935, 3939, + 4083, 3159, 3877, + 4001, 3349, 3775, + 3863, 3521, 3591, + 3569, 3681, 3087, + 0, 3831, 0, + 0, 3977, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2225, 4095, + 4095, 2763, 4095, + 4095, 3063, 4069, + 4095, 3289, 4005, + 4095, 3479, 3903, + 3993, 3651, 3715, + 3699, 3811, 3197, + 0, 3963, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2335, 4095, + 4095, 2889, 4095, + 4095, 3191, 4095, + 4095, 3419, 4095, + 4095, 3611, 4031, + 4095, 3783, 3843, + 3829, 3943, 3313, + 2035, 1592, 2447, + 2032, 1596, 2445, + 2027, 1601, 2445, + 2021, 1608, 2443, + 2012, 1617, 2439, + 2000, 1629, 2435, + 1983, 1644, 2431, + 1960, 1663, 2425, + 1927, 1688, 2415, + 1879, 1719, 2403, + 1805, 1757, 2387, + 1684, 1804, 2363, + 1443, 1860, 2329, + 219, 1926, 2281, + 0, 2001, 2205, + 0, 2085, 2079, + 0, 2177, 1827, + 0, 2277, 0, + 0, 2385, 0, + 0, 2497, 0, + 0, 2613, 0, + 0, 2733, 0, + 0, 2857, 0, + 0, 2981, 0, + 0, 3109, 0, + 0, 3237, 0, + 0, 3365, 0, + 0, 3495, 0, + 0, 3625, 0, + 0, 3757, 0, + 0, 3887, 0, + 0, 4019, 0, + 2040, 1592, 2447, + 2036, 1596, 2447, + 2032, 1601, 2445, + 2025, 1607, 2443, + 2017, 1616, 2441, + 2005, 1628, 2437, + 1988, 1643, 2433, + 1965, 1662, 2425, + 1933, 1687, 2417, + 1885, 1718, 2405, + 1813, 1757, 2387, + 1693, 1804, 2365, + 1459, 1860, 2331, + 414, 1925, 2281, + 0, 2000, 2207, + 0, 2085, 2081, + 0, 2177, 1831, + 0, 2277, 16, + 0, 2385, 0, + 0, 2497, 0, + 0, 2613, 0, + 0, 2733, 0, + 0, 2857, 0, + 0, 2981, 0, + 0, 3109, 0, + 0, 3237, 0, + 0, 3365, 0, + 0, 3495, 0, + 0, 3625, 0, + 0, 3757, 0, + 0, 3887, 0, + 0, 4019, 0, + 2046, 1591, 2449, + 2042, 1595, 2449, + 2038, 1600, 2447, + 2031, 1607, 2445, + 2023, 1616, 2443, + 2011, 1627, 2439, + 1995, 1642, 2433, + 1972, 1662, 2427, + 1940, 1687, 2419, + 1894, 1718, 2407, + 1822, 1756, 2389, + 1706, 1803, 2367, + 1480, 1859, 2333, + 588, 1925, 2285, + 0, 2000, 2209, + 0, 2085, 2085, + 0, 2177, 1838, + 0, 2277, 270, + 0, 2385, 0, + 0, 2497, 0, + 0, 2613, 0, + 0, 2733, 0, + 0, 2855, 0, + 0, 2981, 0, + 0, 3107, 0, + 0, 3237, 0, + 0, 3365, 0, + 0, 3495, 0, + 0, 3625, 0, + 0, 3757, 0, + 0, 3887, 0, + 0, 4019, 0, + 2053, 1590, 2451, + 2051, 1594, 2451, + 2046, 1599, 2449, + 2039, 1606, 2447, + 2031, 1615, 2445, + 2019, 1626, 2441, + 2004, 1641, 2437, + 1981, 1661, 2429, + 1950, 1686, 2421, + 1904, 1717, 2409, + 1835, 1756, 2393, + 1722, 1803, 2369, + 1507, 1859, 2335, + 749, 1924, 2287, + 0, 2000, 2213, + 0, 2083, 2089, + 0, 2177, 1846, + 0, 2277, 476, + 0, 2383, 0, + 0, 2497, 0, + 0, 2613, 0, + 0, 2733, 0, + 0, 2855, 0, + 0, 2981, 0, + 0, 3107, 0, + 0, 3237, 0, + 0, 3365, 0, + 0, 3495, 0, + 0, 3625, 0, + 0, 3757, 0, + 0, 3887, 0, + 0, 4019, 0, + 2063, 1588, 2455, + 2061, 1592, 2453, + 2055, 1597, 2453, + 2049, 1604, 2451, + 2042, 1613, 2447, + 2030, 1625, 2443, + 2015, 1640, 2439, + 1993, 1660, 2433, + 1963, 1685, 2423, + 1918, 1716, 2411, + 1851, 1755, 2395, + 1743, 1802, 2373, + 1540, 1858, 2339, + 902, 1924, 2291, + 0, 1999, 2217, + 0, 2083, 2097, + 0, 2177, 1857, + 0, 2277, 657, + 0, 2383, 0, + 0, 2495, 0, + 0, 2613, 0, + 0, 2733, 0, + 0, 2855, 0, + 0, 2981, 0, + 0, 3107, 0, + 0, 3237, 0, + 0, 3365, 0, + 0, 3495, 0, + 0, 3625, 0, + 0, 3757, 0, + 0, 3887, 0, + 0, 4019, 0, + 2077, 1586, 2459, + 2073, 1590, 2457, + 2069, 1596, 2455, + 2063, 1602, 2453, + 2055, 1611, 2451, + 2045, 1623, 2447, + 2030, 1638, 2443, + 2009, 1658, 2437, + 1979, 1683, 2429, + 1937, 1714, 2417, + 1872, 1753, 2399, + 1769, 1801, 2377, + 1580, 1857, 2345, + 1048, 1923, 2297, + 0, 1998, 2225, + 0, 2083, 2105, + 0, 2175, 1871, + 0, 2277, 822, + 0, 2383, 0, + 0, 2495, 0, + 0, 2613, 0, + 0, 2733, 0, + 0, 2855, 0, + 0, 2981, 0, + 0, 3107, 0, + 0, 3237, 0, + 0, 3365, 0, + 0, 3495, 0, + 0, 3625, 0, + 0, 3757, 0, + 0, 3887, 0, + 0, 4019, 0, + 2095, 1584, 2463, + 2091, 1588, 2463, + 2087, 1593, 2461, + 2081, 1600, 2459, + 2073, 1609, 2457, + 2063, 1621, 2453, + 2049, 1636, 2449, + 2029, 1656, 2441, + 2000, 1681, 2433, + 1960, 1712, 2421, + 1899, 1751, 2405, + 1802, 1799, 2383, + 1630, 1855, 2351, + 1191, 1922, 2303, + 0, 1997, 2233, + 0, 2081, 2115, + 0, 2175, 1889, + 0, 2275, 977, + 0, 2383, 0, + 0, 2495, 0, + 0, 2613, 0, + 0, 2733, 0, + 0, 2855, 0, + 0, 2981, 0, + 0, 3107, 0, + 0, 3235, 0, + 0, 3365, 0, + 0, 3495, 0, + 0, 3625, 0, + 0, 3757, 0, + 0, 3887, 0, + 0, 4019, 0, + 2117, 1580, 2471, + 2113, 1584, 2469, + 2109, 1590, 2467, + 2103, 1597, 2465, + 2097, 1606, 2463, + 2087, 1618, 2459, + 2073, 1633, 2455, + 2053, 1653, 2449, + 2027, 1678, 2441, + 1989, 1710, 2429, + 1932, 1749, 2413, + 1843, 1797, 2391, + 1688, 1854, 2359, + 1331, 1920, 2313, + 0, 1996, 2243, + 0, 2081, 2129, + 0, 2175, 1912, + 0, 2275, 1126, + 0, 2383, 0, + 0, 2495, 0, + 0, 2611, 0, + 0, 2733, 0, + 0, 2855, 0, + 0, 2981, 0, + 0, 3107, 0, + 0, 3235, 0, + 0, 3365, 0, + 0, 3495, 0, + 0, 3625, 0, + 0, 3757, 0, + 0, 3887, 0, + 0, 4019, 0, + 2143, 1576, 2479, + 2141, 1580, 2477, + 2137, 1585, 2477, + 2133, 1592, 2475, + 2125, 1601, 2473, + 2117, 1613, 2469, + 2103, 1629, 2465, + 2085, 1649, 2459, + 2061, 1674, 2449, + 2025, 1706, 2439, + 1973, 1746, 2423, + 1893, 1794, 2401, + 1756, 1851, 2371, + 1469, 1918, 2325, + 0, 1994, 2257, + 0, 2079, 2147, + 0, 2173, 1941, + 0, 2273, 1270, + 0, 2381, 0, + 0, 2495, 0, + 0, 2611, 0, + 0, 2731, 0, + 0, 2855, 0, + 0, 2981, 0, + 0, 3107, 0, + 0, 3235, 0, + 0, 3365, 0, + 0, 3495, 0, + 0, 3625, 0, + 0, 3757, 0, + 0, 3887, 0, + 0, 4019, 0, + 2179, 1569, 2491, + 2175, 1573, 2489, + 2173, 1579, 2487, + 2167, 1586, 2487, + 2161, 1595, 2483, + 2153, 1607, 2481, + 2141, 1623, 2475, + 2125, 1643, 2471, + 2103, 1669, 2461, + 2069, 1701, 2451, + 2023, 1741, 2435, + 1951, 1790, 2415, + 1834, 1848, 2385, + 1605, 1915, 2341, + 668, 1991, 2277, + 0, 2077, 2171, + 0, 2171, 1977, + 0, 2273, 1411, + 0, 2381, 0, + 0, 2493, 0, + 0, 2611, 0, + 0, 2731, 0, + 0, 2855, 0, + 0, 2981, 0, + 0, 3107, 0, + 0, 3235, 0, + 0, 3365, 0, + 0, 3495, 0, + 0, 3625, 0, + 0, 3757, 0, + 0, 3887, 0, + 0, 4019, 0, + 2221, 1561, 2505, + 2219, 1565, 2505, + 2215, 1570, 2503, + 2211, 1578, 2501, + 2205, 1587, 2499, + 2197, 1599, 2495, + 2187, 1615, 2491, + 2173, 1636, 2485, + 2153, 1662, 2477, + 2123, 1695, 2467, + 2081, 1736, 2453, + 2020, 1785, 2433, + 1920, 1843, 2403, + 1741, 1911, 2361, + 1266, 1988, 2299, + 0, 2075, 2201, + 0, 2169, 2022, + 0, 2271, 1549, + 0, 2379, 0, + 0, 2493, 0, + 0, 2609, 0, + 0, 2731, 0, + 0, 2855, 0, + 0, 2979, 0, + 0, 3107, 0, + 0, 3235, 0, + 0, 3365, 0, + 0, 3495, 0, + 0, 3625, 0, + 0, 3757, 0, + 0, 3887, 0, + 0, 4019, 0, + 2273, 1549, 2525, + 2271, 1553, 2523, + 2267, 1559, 2521, + 2263, 1566, 2521, + 2259, 1576, 2519, + 2251, 1589, 2515, + 2243, 1605, 2511, + 2229, 1626, 2505, + 2211, 1653, 2497, + 2187, 1686, 2487, + 2151, 1727, 2473, + 2097, 1777, 2455, + 2015, 1837, 2427, + 1875, 1905, 2387, + 1576, 1983, 2329, + 0, 2071, 2237, + 0, 2165, 2075, + 0, 2269, 1686, + 0, 2377, 0, + 0, 2491, 0, + 0, 2609, 0, + 0, 2729, 0, + 0, 2853, 0, + 0, 2979, 0, + 0, 3107, 0, + 0, 3235, 0, + 0, 3365, 0, + 0, 3495, 0, + 0, 3625, 0, + 0, 3757, 0, + 0, 3887, 0, + 0, 4019, 0, + 2333, 1532, 2549, + 2331, 1537, 2547, + 2329, 1543, 2547, + 2325, 1550, 2545, + 2321, 1560, 2543, + 2315, 1574, 2539, + 2307, 1591, 2537, + 2295, 1612, 2531, + 2281, 1640, 2523, + 2259, 1674, 2515, + 2229, 1717, 2501, + 2183, 1768, 2483, + 2117, 1828, 2457, + 2009, 1898, 2421, + 1807, 1977, 2367, + 1178, 2065, 2283, + 0, 2161, 2137, + 0, 2265, 1822, + 0, 2375, 0, + 0, 2489, 0, + 0, 2607, 0, + 0, 2729, 0, + 0, 2853, 0, + 0, 2979, 0, + 0, 3107, 0, + 0, 3235, 0, + 0, 3365, 0, + 0, 3495, 0, + 0, 3625, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 2403, 1510, 2579, + 2401, 1514, 2579, + 2399, 1520, 2577, + 2397, 1528, 2575, + 2393, 1539, 2573, + 2389, 1553, 2571, + 2381, 1571, 2567, + 2371, 1593, 2563, + 2359, 1622, 2557, + 2341, 1658, 2547, + 2315, 1701, 2535, + 2279, 1754, 2517, + 2225, 1816, 2495, + 2143, 1888, 2461, + 2001, 1969, 2411, + 1696, 2059, 2335, + 0, 2157, 2209, + 0, 2261, 1957, + 0, 2371, 0, + 0, 2485, 0, + 0, 2605, 0, + 0, 2727, 0, + 0, 2851, 0, + 0, 2977, 0, + 0, 3105, 0, + 0, 3235, 0, + 0, 3363, 0, + 0, 3493, 0, + 0, 3625, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 2483, 1477, 2617, + 2481, 1482, 2617, + 2481, 1489, 2615, + 2477, 1497, 2615, + 2475, 1509, 2613, + 2471, 1523, 2609, + 2465, 1542, 2607, + 2457, 1566, 2603, + 2445, 1597, 2597, + 2431, 1634, 2587, + 2411, 1680, 2577, + 2381, 1735, 2561, + 2339, 1800, 2539, + 2275, 1874, 2509, + 2175, 1957, 2465, + 1990, 2049, 2399, + 1485, 2149, 2291, + 0, 2255, 2091, + 0, 2367, 1476, + 0, 2483, 0, + 0, 2603, 0, + 0, 2725, 0, + 0, 2849, 0, + 0, 2977, 0, + 0, 3105, 0, + 0, 3233, 0, + 0, 3363, 0, + 0, 3493, 0, + 0, 3625, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 2571, 1430, 2663, + 2571, 1435, 2663, + 2569, 1443, 2661, + 2567, 1452, 2661, + 2565, 1465, 2659, + 2561, 1481, 2657, + 2557, 1502, 2653, + 2549, 1528, 2649, + 2541, 1561, 2645, + 2529, 1602, 2637, + 2513, 1651, 2627, + 2489, 1709, 2613, + 2457, 1777, 2595, + 2409, 1855, 2567, + 2335, 1941, 2529, + 2213, 2036, 2471, + 1974, 2139, 2381, + 782, 2247, 2225, + 0, 2359, 1859, + 0, 2477, 0, + 0, 2599, 0, + 0, 2721, 0, + 0, 2847, 0, + 0, 2975, 0, + 0, 3103, 0, + 0, 3233, 0, + 0, 3363, 0, + 0, 3493, 0, + 0, 3625, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 2669, 1358, 2719, + 2667, 1364, 2719, + 2667, 1373, 2717, + 2665, 1384, 2717, + 2663, 1398, 2715, + 2659, 1417, 2713, + 2655, 1441, 2711, + 2651, 1471, 2707, + 2643, 1508, 2703, + 2635, 1553, 2695, + 2621, 1608, 2687, + 2603, 1672, 2675, + 2577, 1745, 2659, + 2541, 1828, 2635, + 2487, 1919, 2601, + 2405, 2018, 2553, + 2261, 2123, 2479, + 1953, 2235, 2357, + 0, 2351, 2115, + 0, 2471, 847, + 0, 2593, 0, + 0, 2717, 0, + 0, 2845, 0, + 0, 2973, 0, + 0, 3101, 0, + 0, 3231, 0, + 0, 3361, 0, + 0, 3493, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 2771, 1239, 2783, + 2771, 1248, 2783, + 2771, 1259, 2783, + 2769, 1273, 2781, + 2767, 1291, 2781, + 2765, 1315, 2779, + 2763, 1344, 2777, + 2757, 1381, 2773, + 2753, 1426, 2769, + 2745, 1480, 2763, + 2735, 1543, 2757, + 2721, 1616, 2745, + 2701, 1698, 2731, + 2673, 1789, 2711, + 2635, 1888, 2685, + 2575, 1993, 2645, + 2483, 2105, 2585, + 2319, 2219, 2491, + 1922, 2339, 2323, + 0, 2461, 1913, + 0, 2587, 0, + 0, 2713, 0, + 0, 2841, 0, + 0, 2969, 0, + 0, 3099, 0, + 0, 3229, 0, + 0, 3361, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4017, 0, + 2881, 1008, 2859, + 2881, 1022, 2857, + 2881, 1039, 2857, + 2879, 1062, 2857, + 2877, 1091, 2855, + 2877, 1127, 2853, + 2873, 1171, 2851, + 2871, 1224, 2849, + 2867, 1286, 2845, + 2861, 1358, 2841, + 2853, 1439, 2835, + 2841, 1529, 2827, + 2827, 1627, 2815, + 2807, 1731, 2799, + 2777, 1842, 2775, + 2735, 1957, 2743, + 2671, 2077, 2695, + 2569, 2199, 2623, + 2385, 2323, 2505, + 1878, 2449, 2273, + 0, 2577, 1276, + 0, 2705, 0, + 0, 2835, 0, + 0, 2965, 0, + 0, 3097, 0, + 0, 3227, 0, + 0, 3359, 0, + 0, 3491, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2995, 13, 2941, + 2995, 124, 2941, + 2995, 239, 2941, + 2995, 358, 2941, + 2993, 481, 2939, + 2991, 605, 2939, + 2989, 731, 2937, + 2987, 859, 2935, + 2985, 988, 2931, + 2979, 1117, 2927, + 2973, 1248, 2923, + 2965, 1378, 2915, + 2955, 1510, 2905, + 2939, 1641, 2893, + 2917, 1772, 2873, + 2887, 1904, 2847, + 2841, 2036, 2811, + 2775, 2167, 2755, + 2665, 2299, 2671, + 2461, 2431, 2523, + 1811, 2563, 2195, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 3115, 0, 3035, + 3115, 0, 3033, + 3113, 0, 3033, + 3113, 0, 3033, + 3113, 0, 3033, + 3111, 0, 3031, + 3109, 0, 3029, + 3107, 0, 3029, + 3105, 0, 3025, + 3101, 0, 3023, + 3097, 700, 3019, + 3091, 1040, 3013, + 3083, 1282, 3005, + 3071, 1482, 2993, + 3055, 1659, 2979, + 3033, 1822, 2959, + 3001, 1976, 2931, + 2955, 2123, 2889, + 2883, 2267, 2825, + 2769, 2407, 2727, + 2545, 2545, 2545, + 1703, 2683, 2065, + 0, 2817, 0, + 0, 2953, 0, + 0, 3087, 0, + 0, 3221, 0, + 0, 3353, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4017, 0, + 3237, 0, 3133, + 3235, 0, 3133, + 3235, 0, 3133, + 3235, 0, 3133, + 3235, 0, 3133, + 3233, 0, 3131, + 3233, 0, 3131, + 3231, 0, 3129, + 3229, 0, 3127, + 3227, 0, 3125, + 3223, 0, 3121, + 3219, 0, 3117, + 3211, 360, 3111, + 3203, 1109, 3101, + 3191, 1442, 3091, + 3175, 1682, 3075, + 3151, 1881, 3053, + 3119, 2057, 3021, + 3071, 2219, 2975, + 2997, 2373, 2905, + 2877, 2521, 2791, + 2639, 2663, 2575, + 1500, 2805, 1801, + 0, 2943, 0, + 0, 3079, 0, + 0, 3215, 0, + 0, 3349, 0, + 0, 3483, 0, + 0, 3617, 0, + 0, 3749, 0, + 0, 3883, 0, + 0, 4015, 0, + 3361, 0, 3241, + 3359, 0, 3239, + 3359, 0, 3239, + 3359, 0, 3239, + 3359, 0, 3239, + 3359, 0, 3239, + 3357, 0, 3237, + 3357, 0, 3237, + 3355, 0, 3235, + 3353, 0, 3233, + 3351, 0, 3231, + 3347, 0, 3227, + 3341, 0, 3221, + 3335, 0, 3215, + 3327, 673, 3207, + 3315, 1383, 3193, + 3297, 1711, 3177, + 3273, 1949, 3153, + 3241, 2147, 3119, + 3191, 2323, 3069, + 3115, 2485, 2993, + 2991, 2637, 2867, + 2741, 2785, 2611, + 867, 2929, 0, + 0, 3069, 0, + 0, 3207, 0, + 0, 3343, 0, + 0, 3479, 0, + 0, 3613, 0, + 0, 3747, 0, + 0, 3881, 0, + 0, 4013, 0, + 3487, 0, 3351, + 3487, 0, 3351, + 3485, 0, 3351, + 3485, 0, 3351, + 3485, 0, 3351, + 3485, 0, 3351, + 3485, 0, 3349, + 3483, 0, 3349, + 3483, 0, 3347, + 3481, 0, 3347, + 3479, 0, 3345, + 3475, 0, 3341, + 3473, 0, 3337, + 3467, 0, 3333, + 3461, 0, 3325, + 3451, 0, 3317, + 3439, 1290, 3303, + 3423, 1748, 3285, + 3399, 2027, 3261, + 3365, 2245, 3225, + 3315, 2431, 3171, + 3237, 2601, 3091, + 3109, 2759, 2951, + 2847, 2909, 2655, + 0, 3055, 0, + 0, 3197, 0, + 0, 3335, 0, + 0, 3473, 0, + 0, 3609, 0, + 0, 3745, 0, + 0, 3879, 0, + 0, 4013, 0, + 3613, 0, 3469, + 3613, 0, 3469, + 3613, 0, 3469, + 3613, 0, 3467, + 3613, 0, 3467, + 3613, 0, 3467, + 3613, 0, 3467, + 3611, 0, 3465, + 3611, 0, 3465, + 3609, 0, 3463, + 3609, 0, 3463, + 3607, 0, 3461, + 3603, 0, 3457, + 3599, 0, 3453, + 3595, 0, 3447, + 3587, 0, 3441, + 3579, 0, 3431, + 3567, 1125, 3417, + 3549, 1792, 3399, + 3525, 2113, 3373, + 3491, 2349, 3335, + 3439, 2545, 3281, + 3361, 2721, 3193, + 3231, 2883, 3043, + 2961, 3035, 2709, + 0, 3183, 0, + 0, 3325, 0, + 0, 3465, 0, + 0, 3603, 0, + 0, 3739, 0, + 0, 3875, 0, + 0, 4009, 0, + 3743, 0, 3589, + 3743, 0, 3589, + 3743, 0, 3589, + 3743, 0, 3587, + 3741, 0, 3587, + 3741, 0, 3587, + 3741, 0, 3587, + 3741, 0, 3587, + 3741, 0, 3585, + 3739, 0, 3585, + 3739, 0, 3583, + 3737, 0, 3581, + 3735, 0, 3579, + 3731, 0, 3577, + 3729, 0, 3573, + 3723, 0, 3567, + 3717, 0, 3559, + 3707, 0, 3549, + 3695, 726, 3537, + 3677, 1846, 3517, + 3653, 2209, 3489, + 3617, 2459, 3451, + 3567, 2663, 3393, + 3487, 2843, 3303, + 3353, 3007, 3145, + 3077, 3163, 2771, + 0, 3311, 0, + 0, 3455, 0, + 0, 3595, 0, + 0, 3735, 0, + 0, 3871, 0, + 0, 4007, 0, + 3871, 0, 3711, + 3871, 0, 3711, + 3871, 0, 3711, + 3871, 0, 3711, + 3871, 0, 3711, + 3871, 0, 3711, + 3871, 0, 3711, + 3871, 0, 3709, + 3871, 0, 3709, + 3869, 0, 3709, + 3869, 0, 3707, + 3867, 0, 3707, + 3867, 0, 3705, + 3863, 0, 3703, + 3861, 0, 3699, + 3857, 0, 3695, + 3853, 0, 3689, + 3845, 0, 3683, + 3837, 0, 3671, + 3823, 0, 3657, + 3807, 1909, 3637, + 3781, 2311, 3611, + 3747, 2575, 3571, + 3695, 2785, 3511, + 3615, 2969, 3417, + 3479, 3135, 3251, + 3197, 3291, 2843, + 0, 3441, 0, + 0, 3585, 0, + 0, 3727, 0, + 0, 3865, 0, + 0, 4003, 0, + 4003, 0, 3837, + 4003, 0, 3835, + 4001, 0, 3835, + 4001, 0, 3835, + 4001, 0, 3835, + 4001, 0, 3835, + 4001, 0, 3835, + 4001, 0, 3835, + 4001, 0, 3835, + 4001, 0, 3835, + 3999, 0, 3833, + 3999, 0, 3833, + 3997, 0, 3831, + 3997, 0, 3829, + 3995, 0, 3827, + 3991, 0, 3825, + 3987, 0, 3819, + 3983, 0, 3815, + 3975, 0, 3807, + 3967, 0, 3797, + 3953, 0, 3781, + 3935, 1981, 3761, + 3911, 2419, 3733, + 3875, 2693, 3693, + 3823, 2909, 3633, + 3743, 3095, 3535, + 3607, 3263, 3363, + 3321, 3421, 2925, + 0, 3571, 0, + 0, 3715, 0, + 0, 3857, 0, + 0, 3997, 0, + 4095, 0, 3963, + 4095, 0, 3963, + 4095, 0, 3963, + 4095, 0, 3963, + 4095, 0, 3963, + 4095, 0, 3963, + 4095, 0, 3963, + 4095, 0, 3963, + 4095, 0, 3961, + 4095, 0, 3961, + 4095, 0, 3961, + 4095, 0, 3961, + 4095, 0, 3959, + 4095, 0, 3957, + 4095, 0, 3957, + 4095, 0, 3953, + 4095, 0, 3951, + 4095, 0, 3947, + 4095, 0, 3941, + 4095, 0, 3933, + 4095, 0, 3923, + 4083, 0, 3907, + 4067, 2063, 3887, + 4041, 2533, 3859, + 4005, 2815, 3817, + 3953, 3035, 3755, + 3873, 3223, 3657, + 3735, 3393, 3479, + 3447, 3551, 3015, + 0, 3701, 0, + 0, 3847, 0, + 0, 3989, 0, + 4095, 0, 4091, + 4095, 0, 4091, + 4095, 0, 4091, + 4095, 0, 4091, + 4095, 0, 4091, + 4095, 0, 4091, + 4095, 0, 4091, + 4095, 0, 4091, + 4095, 0, 4091, + 4095, 0, 4089, + 4095, 0, 4089, + 4095, 0, 4089, + 4095, 0, 4089, + 4095, 0, 4087, + 4095, 0, 4085, + 4095, 0, 4085, + 4095, 0, 4081, + 4095, 0, 4079, + 4095, 0, 4075, + 4095, 0, 4069, + 4095, 0, 4061, + 4095, 0, 4049, + 4095, 0, 4035, + 4095, 2153, 4015, + 4095, 2651, 3985, + 4095, 2941, 3945, + 4085, 3163, 3881, + 4003, 3351, 3781, + 3865, 3523, 3599, + 3573, 3681, 3115, + 0, 3833, 0, + 0, 3979, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2251, 4095, + 4095, 2771, 4095, + 4095, 3067, 4071, + 4095, 3291, 4009, + 4095, 3481, 3907, + 3995, 3653, 3723, + 3701, 3813, 3219, + 0, 3963, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2357, 4095, + 4095, 2895, 4095, + 4095, 3195, 4095, + 4095, 3421, 4095, + 4095, 3611, 4035, + 4095, 3783, 3847, + 3831, 3943, 3329, + 2167, 1722, 2579, + 2165, 1725, 2577, + 2161, 1729, 2577, + 2155, 1734, 2575, + 2149, 1741, 2573, + 2141, 1749, 2571, + 2129, 1761, 2567, + 2111, 1776, 2563, + 2089, 1795, 2555, + 2055, 1820, 2547, + 2006, 1851, 2535, + 1932, 1890, 2517, + 1809, 1937, 2493, + 1563, 1992, 2461, + 119, 2057, 2411, + 0, 2133, 2335, + 0, 2217, 2209, + 0, 2309, 1955, + 0, 2409, 0, + 0, 2517, 0, + 0, 2629, 0, + 0, 2745, 0, + 0, 2865, 0, + 0, 2989, 0, + 0, 3113, 0, + 0, 3241, 0, + 0, 3369, 0, + 0, 3497, 0, + 0, 3627, 0, + 0, 3757, 0, + 0, 3889, 0, + 0, 4019, 0, + 2171, 1722, 2579, + 2167, 1724, 2579, + 2165, 1728, 2577, + 2159, 1733, 2577, + 2153, 1740, 2575, + 2145, 1749, 2571, + 2133, 1761, 2569, + 2115, 1776, 2563, + 2093, 1795, 2557, + 2059, 1820, 2547, + 2011, 1851, 2535, + 1938, 1889, 2519, + 1816, 1936, 2495, + 1575, 1992, 2461, + 351, 2057, 2413, + 0, 2133, 2337, + 0, 2217, 2211, + 0, 2309, 1959, + 0, 2409, 0, + 0, 2517, 0, + 0, 2629, 0, + 0, 2745, 0, + 0, 2865, 0, + 0, 2989, 0, + 0, 3113, 0, + 0, 3241, 0, + 0, 3369, 0, + 0, 3497, 0, + 0, 3627, 0, + 0, 3757, 0, + 0, 3889, 0, + 0, 4019, 0, + 2175, 1721, 2581, + 2173, 1724, 2581, + 2169, 1728, 2579, + 2163, 1733, 2577, + 2157, 1740, 2575, + 2149, 1748, 2573, + 2137, 1760, 2569, + 2121, 1775, 2565, + 2097, 1795, 2557, + 2065, 1819, 2549, + 2017, 1850, 2537, + 1945, 1889, 2519, + 1825, 1936, 2497, + 1592, 1992, 2463, + 546, 2057, 2413, + 0, 2133, 2339, + 0, 2217, 2213, + 0, 2309, 1964, + 0, 2409, 148, + 0, 2517, 0, + 0, 2629, 0, + 0, 2745, 0, + 0, 2865, 0, + 0, 2989, 0, + 0, 3113, 0, + 0, 3241, 0, + 0, 3369, 0, + 0, 3497, 0, + 0, 3627, 0, + 0, 3757, 0, + 0, 3889, 0, + 0, 4019, 0, + 2181, 1720, 2583, + 2177, 1723, 2581, + 2175, 1727, 2581, + 2169, 1732, 2579, + 2163, 1739, 2577, + 2155, 1748, 2575, + 2143, 1759, 2571, + 2127, 1774, 2567, + 2105, 1794, 2559, + 2073, 1819, 2551, + 2026, 1850, 2539, + 1955, 1888, 2521, + 1838, 1935, 2499, + 1612, 1991, 2465, + 720, 2057, 2417, + 0, 2133, 2341, + 0, 2217, 2217, + 0, 2309, 1970, + 0, 2409, 403, + 0, 2517, 0, + 0, 2629, 0, + 0, 2745, 0, + 0, 2865, 0, + 0, 2989, 0, + 0, 3113, 0, + 0, 3241, 0, + 0, 3369, 0, + 0, 3497, 0, + 0, 3627, 0, + 0, 3757, 0, + 0, 3889, 0, + 0, 4019, 0, + 2189, 1719, 2585, + 2185, 1722, 2583, + 2183, 1726, 2583, + 2177, 1731, 2581, + 2171, 1738, 2579, + 2163, 1747, 2577, + 2151, 1758, 2573, + 2135, 1774, 2569, + 2113, 1793, 2561, + 2083, 1818, 2553, + 2036, 1849, 2541, + 1967, 1888, 2525, + 1854, 1935, 2501, + 1639, 1991, 2467, + 881, 2057, 2419, + 0, 2131, 2345, + 0, 2217, 2223, + 0, 2309, 1978, + 0, 2409, 608, + 0, 2515, 0, + 0, 2629, 0, + 0, 2745, 0, + 0, 2865, 0, + 0, 2989, 0, + 0, 3113, 0, + 0, 3241, 0, + 0, 3369, 0, + 0, 3497, 0, + 0, 3627, 0, + 0, 3757, 0, + 0, 3889, 0, + 0, 4019, 0, + 2199, 1718, 2587, + 2195, 1721, 2587, + 2193, 1724, 2585, + 2189, 1730, 2585, + 2181, 1736, 2583, + 2173, 1745, 2579, + 2163, 1757, 2577, + 2147, 1772, 2571, + 2125, 1792, 2565, + 2095, 1817, 2557, + 2051, 1848, 2545, + 1984, 1887, 2527, + 1875, 1934, 2505, + 1672, 1990, 2471, + 1033, 2055, 2423, + 0, 2131, 2349, + 0, 2215, 2229, + 0, 2309, 1989, + 0, 2409, 789, + 0, 2515, 0, + 0, 2627, 0, + 0, 2745, 0, + 0, 2865, 0, + 0, 2987, 0, + 0, 3113, 0, + 0, 3241, 0, + 0, 3369, 0, + 0, 3497, 0, + 0, 3627, 0, + 0, 3757, 0, + 0, 3889, 0, + 0, 4019, 0, + 2211, 1716, 2591, + 2209, 1719, 2591, + 2205, 1723, 2589, + 2201, 1728, 2587, + 2195, 1735, 2587, + 2187, 1744, 2583, + 2177, 1755, 2579, + 2161, 1771, 2575, + 2141, 1790, 2569, + 2111, 1815, 2561, + 2069, 1847, 2549, + 2004, 1885, 2531, + 1901, 1933, 2509, + 1712, 1989, 2477, + 1180, 2055, 2429, + 0, 2131, 2357, + 0, 2215, 2237, + 0, 2307, 2003, + 0, 2409, 954, + 0, 2515, 0, + 0, 2627, 0, + 0, 2745, 0, + 0, 2865, 0, + 0, 2987, 0, + 0, 3113, 0, + 0, 3239, 0, + 0, 3369, 0, + 0, 3497, 0, + 0, 3627, 0, + 0, 3757, 0, + 0, 3889, 0, + 0, 4019, 0, + 2229, 1713, 2597, + 2227, 1716, 2595, + 2223, 1720, 2595, + 2219, 1725, 2593, + 2213, 1732, 2591, + 2205, 1741, 2589, + 2195, 1753, 2585, + 2181, 1768, 2581, + 2161, 1788, 2575, + 2133, 1813, 2565, + 2091, 1845, 2553, + 2031, 1884, 2537, + 1935, 1931, 2515, + 1762, 1988, 2483, + 1323, 2053, 2435, + 0, 2129, 2365, + 0, 2215, 2247, + 0, 2307, 2021, + 0, 2407, 1109, + 0, 2515, 0, + 0, 2627, 0, + 0, 2745, 0, + 0, 2865, 0, + 0, 2987, 0, + 0, 3113, 0, + 0, 3239, 0, + 0, 3369, 0, + 0, 3497, 0, + 0, 3627, 0, + 0, 3757, 0, + 0, 3889, 0, + 0, 4019, 0, + 2251, 1710, 2603, + 2249, 1713, 2603, + 2245, 1716, 2601, + 2241, 1722, 2599, + 2235, 1729, 2597, + 2229, 1738, 2595, + 2219, 1750, 2591, + 2205, 1765, 2587, + 2185, 1785, 2581, + 2159, 1810, 2573, + 2121, 1842, 2561, + 2065, 1881, 2545, + 1975, 1929, 2523, + 1820, 1986, 2491, + 1463, 2053, 2445, + 0, 2127, 2375, + 0, 2213, 2261, + 0, 2307, 2044, + 0, 2407, 1258, + 0, 2515, 0, + 0, 2627, 0, + 0, 2743, 0, + 0, 2865, 0, + 0, 2987, 0, + 0, 3113, 0, + 0, 3239, 0, + 0, 3367, 0, + 0, 3497, 0, + 0, 3627, 0, + 0, 3757, 0, + 0, 3889, 0, + 0, 4019, 0, + 2279, 1705, 2611, + 2275, 1708, 2611, + 2273, 1712, 2609, + 2269, 1717, 2609, + 2265, 1724, 2607, + 2257, 1733, 2605, + 2249, 1745, 2601, + 2235, 1761, 2597, + 2217, 1781, 2591, + 2193, 1806, 2581, + 2157, 1838, 2571, + 2105, 1878, 2555, + 2025, 1926, 2533, + 1888, 1983, 2503, + 1601, 2049, 2457, + 0, 2127, 2389, + 0, 2211, 2281, + 0, 2305, 2073, + 0, 2407, 1402, + 0, 2513, 0, + 0, 2627, 0, + 0, 2743, 0, + 0, 2863, 0, + 0, 2987, 0, + 0, 3113, 0, + 0, 3239, 0, + 0, 3367, 0, + 0, 3497, 0, + 0, 3627, 0, + 0, 3757, 0, + 0, 3889, 0, + 0, 4019, 0, + 2313, 1698, 2623, + 2311, 1701, 2623, + 2309, 1706, 2621, + 2305, 1711, 2619, + 2299, 1718, 2619, + 2293, 1727, 2615, + 2285, 1739, 2613, + 2273, 1755, 2609, + 2257, 1776, 2603, + 2235, 1801, 2595, + 2203, 1834, 2583, + 2155, 1874, 2567, + 2083, 1922, 2547, + 1966, 1980, 2517, + 1738, 2047, 2473, + 801, 2123, 2409, + 0, 2209, 2303, + 0, 2303, 2109, + 0, 2405, 1543, + 0, 2513, 0, + 0, 2625, 0, + 0, 2743, 0, + 0, 2863, 0, + 0, 2987, 0, + 0, 3113, 0, + 0, 3239, 0, + 0, 3367, 0, + 0, 3497, 0, + 0, 3627, 0, + 0, 3757, 0, + 0, 3889, 0, + 0, 4019, 0, + 2355, 1690, 2637, + 2353, 1693, 2637, + 2351, 1697, 2637, + 2347, 1702, 2635, + 2343, 1710, 2633, + 2337, 1719, 2631, + 2329, 1732, 2627, + 2319, 1748, 2623, + 2305, 1768, 2617, + 2285, 1794, 2609, + 2255, 1827, 2599, + 2213, 1868, 2585, + 2151, 1917, 2565, + 2053, 1975, 2535, + 1873, 2043, 2495, + 1398, 2121, 2431, + 0, 2207, 2333, + 0, 2301, 2153, + 0, 2403, 1682, + 0, 2511, 0, + 0, 2625, 0, + 0, 2741, 0, + 0, 2863, 0, + 0, 2987, 0, + 0, 3111, 0, + 0, 3239, 0, + 0, 3367, 0, + 0, 3497, 0, + 0, 3627, 0, + 0, 3757, 0, + 0, 3889, 0, + 0, 4019, 0, + 2407, 1678, 2657, + 2405, 1681, 2657, + 2403, 1685, 2655, + 2399, 1691, 2655, + 2395, 1698, 2653, + 2391, 1708, 2651, + 2383, 1721, 2647, + 2375, 1737, 2643, + 2361, 1758, 2637, + 2343, 1785, 2631, + 2319, 1818, 2619, + 2283, 1860, 2605, + 2229, 1909, 2587, + 2147, 1969, 2559, + 2007, 2037, 2521, + 1708, 2115, 2461, + 0, 2203, 2369, + 0, 2297, 2207, + 0, 2401, 1818, + 0, 2509, 0, + 0, 2623, 0, + 0, 2741, 0, + 0, 2861, 0, + 0, 2985, 0, + 0, 3111, 0, + 0, 3239, 0, + 0, 3367, 0, + 0, 3497, 0, + 0, 3627, 0, + 0, 3757, 0, + 0, 3889, 0, + 0, 4019, 0, + 2467, 1661, 2681, + 2465, 1665, 2681, + 2463, 1669, 2679, + 2461, 1675, 2679, + 2457, 1683, 2677, + 2453, 1693, 2675, + 2447, 1706, 2673, + 2439, 1723, 2669, + 2427, 1744, 2663, + 2413, 1772, 2655, + 2391, 1806, 2647, + 2361, 1849, 2633, + 2317, 1900, 2615, + 2249, 1960, 2589, + 2141, 2030, 2553, + 1939, 2109, 2499, + 1310, 2197, 2415, + 0, 2293, 2269, + 0, 2397, 1954, + 0, 2507, 0, + 0, 2621, 0, + 0, 2739, 0, + 0, 2861, 0, + 0, 2985, 0, + 0, 3111, 0, + 0, 3239, 0, + 0, 3367, 0, + 0, 3497, 0, + 0, 3627, 0, + 0, 3757, 0, + 0, 3889, 0, + 0, 4019, 0, + 2537, 1638, 2711, + 2535, 1642, 2711, + 2535, 1646, 2711, + 2531, 1653, 2709, + 2529, 1661, 2707, + 2525, 1671, 2705, + 2521, 1685, 2703, + 2513, 1703, 2699, + 2503, 1725, 2695, + 2491, 1754, 2689, + 2473, 1790, 2679, + 2447, 1834, 2667, + 2411, 1886, 2651, + 2357, 1948, 2627, + 2275, 2020, 2593, + 2133, 2101, 2543, + 1828, 2191, 2467, + 0, 2289, 2341, + 0, 2393, 2089, + 0, 2503, 0, + 0, 2619, 0, + 0, 2737, 0, + 0, 2859, 0, + 0, 2983, 0, + 0, 3109, 0, + 0, 3237, 0, + 0, 3367, 0, + 0, 3495, 0, + 0, 3627, 0, + 0, 3757, 0, + 0, 3887, 0, + 0, 4019, 0, + 2617, 1606, 2749, + 2615, 1609, 2749, + 2613, 1614, 2749, + 2613, 1621, 2747, + 2609, 1630, 2747, + 2607, 1641, 2745, + 2603, 1656, 2741, + 2597, 1674, 2739, + 2589, 1699, 2735, + 2577, 1729, 2729, + 2563, 1767, 2719, + 2543, 1813, 2709, + 2513, 1868, 2693, + 2471, 1932, 2671, + 2407, 2006, 2641, + 2307, 2089, 2597, + 2121, 2181, 2531, + 1617, 2281, 2423, + 0, 2387, 2223, + 0, 2499, 1608, + 0, 2615, 0, + 0, 2735, 0, + 0, 2857, 0, + 0, 2981, 0, + 0, 3109, 0, + 0, 3237, 0, + 0, 3365, 0, + 0, 3495, 0, + 0, 3625, 0, + 0, 3757, 0, + 0, 3887, 0, + 0, 4019, 0, + 2705, 1558, 2797, + 2703, 1562, 2795, + 2703, 1568, 2795, + 2701, 1575, 2795, + 2699, 1584, 2793, + 2697, 1597, 2791, + 2693, 1613, 2789, + 2689, 1634, 2787, + 2683, 1660, 2781, + 2673, 1693, 2777, + 2661, 1734, 2769, + 2645, 1783, 2759, + 2621, 1841, 2745, + 2589, 1909, 2727, + 2541, 1987, 2699, + 2467, 2073, 2661, + 2345, 2169, 2603, + 2107, 2271, 2513, + 914, 2379, 2357, + 0, 2491, 1991, + 0, 2609, 0, + 0, 2731, 0, + 0, 2853, 0, + 0, 2979, 0, + 0, 3107, 0, + 0, 3235, 0, + 0, 3365, 0, + 0, 3495, 0, + 0, 3625, 0, + 0, 3757, 0, + 0, 3887, 0, + 0, 4019, 0, + 2801, 1485, 2851, + 2801, 1490, 2851, + 2799, 1496, 2851, + 2799, 1505, 2849, + 2797, 1516, 2849, + 2795, 1531, 2847, + 2791, 1549, 2845, + 2787, 1573, 2843, + 2783, 1603, 2839, + 2775, 1640, 2835, + 2767, 1686, 2827, + 2753, 1740, 2819, + 2735, 1804, 2807, + 2709, 1877, 2791, + 2673, 1960, 2767, + 2619, 2051, 2735, + 2537, 2151, 2685, + 2393, 2255, 2613, + 2085, 2367, 2489, + 0, 2483, 2249, + 0, 2603, 980, + 0, 2725, 0, + 0, 2851, 0, + 0, 2977, 0, + 0, 3105, 0, + 0, 3233, 0, + 0, 3363, 0, + 0, 3493, 0, + 0, 3625, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 2905, 1365, 2917, + 2903, 1371, 2915, + 2903, 1380, 2915, + 2903, 1391, 2915, + 2901, 1405, 2913, + 2899, 1423, 2913, + 2897, 1447, 2911, + 2895, 1476, 2909, + 2891, 1513, 2905, + 2885, 1558, 2901, + 2877, 1612, 2895, + 2867, 1675, 2889, + 2853, 1748, 2877, + 2833, 1830, 2863, + 2805, 1921, 2845, + 2767, 2020, 2817, + 2707, 2125, 2777, + 2615, 2237, 2717, + 2451, 2351, 2623, + 2055, 2471, 2455, + 0, 2593, 2045, + 0, 2719, 0, + 0, 2845, 0, + 0, 2973, 0, + 0, 3101, 0, + 0, 3231, 0, + 0, 3361, 0, + 0, 3493, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 3013, 1129, 2991, + 3013, 1140, 2991, + 3013, 1154, 2989, + 3013, 1172, 2989, + 3011, 1194, 2989, + 3009, 1223, 2987, + 3009, 1259, 2987, + 3005, 1303, 2985, + 3003, 1356, 2981, + 2999, 1418, 2979, + 2993, 1490, 2973, + 2985, 1571, 2967, + 2973, 1661, 2959, + 2959, 1759, 2947, + 2939, 1864, 2931, + 2909, 1974, 2907, + 2867, 2089, 2875, + 2803, 2209, 2827, + 2701, 2331, 2755, + 2517, 2455, 2637, + 2010, 2581, 2405, + 0, 2709, 1408, + 0, 2837, 0, + 0, 2967, 0, + 0, 3097, 0, + 0, 3229, 0, + 0, 3359, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 3129, 41, 3075, + 3129, 145, 3075, + 3127, 256, 3073, + 3127, 371, 3073, + 3127, 491, 3073, + 3125, 613, 3071, + 3123, 737, 3071, + 3123, 864, 3069, + 3119, 991, 3067, + 3117, 1120, 3063, + 3111, 1250, 3059, + 3105, 1380, 3055, + 3097, 1511, 3047, + 3087, 1642, 3037, + 3071, 1773, 3025, + 3049, 1905, 3007, + 3019, 2036, 2981, + 2973, 2169, 2943, + 2907, 2299, 2889, + 2797, 2431, 2803, + 2593, 2563, 2655, + 1943, 2695, 2327, + 0, 2827, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 3247, 0, 3167, + 3247, 0, 3167, + 3247, 0, 3165, + 3245, 0, 3165, + 3245, 0, 3165, + 3245, 0, 3165, + 3243, 0, 3163, + 3241, 0, 3161, + 3239, 0, 3161, + 3237, 0, 3157, + 3233, 22, 3155, + 3229, 832, 3151, + 3223, 1172, 3145, + 3215, 1414, 3137, + 3203, 1614, 3127, + 3187, 1791, 3111, + 3165, 1954, 3091, + 3133, 2109, 3063, + 3087, 2255, 3021, + 3015, 2399, 2959, + 2901, 2539, 2859, + 2677, 2677, 2677, + 1835, 2815, 2197, + 0, 2951, 0, + 0, 3085, 0, + 0, 3219, 0, + 0, 3353, 0, + 0, 3485, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 3369, 0, 3267, + 3369, 0, 3265, + 3367, 0, 3265, + 3367, 0, 3265, + 3367, 0, 3265, + 3367, 0, 3265, + 3365, 0, 3263, + 3365, 0, 3263, + 3363, 0, 3261, + 3361, 0, 3259, + 3359, 0, 3257, + 3355, 0, 3253, + 3351, 0, 3249, + 3343, 492, 3243, + 3335, 1242, 3235, + 3323, 1575, 3223, + 3307, 1814, 3207, + 3283, 2013, 3185, + 3251, 2189, 3153, + 3203, 2351, 3107, + 3129, 2505, 3037, + 3009, 2653, 2925, + 2771, 2797, 2707, + 1632, 2937, 1933, + 0, 3075, 0, + 0, 3211, 0, + 0, 3347, 0, + 0, 3481, 0, + 0, 3615, 0, + 0, 3749, 0, + 0, 3881, 0, + 0, 4015, 0, + 3493, 0, 3373, + 3493, 0, 3373, + 3493, 0, 3373, + 3491, 0, 3371, + 3491, 0, 3371, + 3491, 0, 3371, + 3491, 0, 3371, + 3489, 0, 3369, + 3489, 0, 3369, + 3487, 0, 3367, + 3485, 0, 3365, + 3483, 0, 3363, + 3479, 0, 3359, + 3473, 0, 3353, + 3467, 0, 3347, + 3459, 805, 3339, + 3447, 1516, 3325, + 3429, 1844, 3309, + 3405, 2081, 3285, + 3373, 2279, 3251, + 3323, 2455, 3201, + 3249, 2617, 3125, + 3123, 2771, 2999, + 2873, 2917, 2743, + 999, 3061, 0, + 0, 3201, 0, + 0, 3339, 0, + 0, 3475, 0, + 0, 3611, 0, + 0, 3745, 0, + 0, 3879, 0, + 0, 4013, 0, + 3619, 0, 3485, + 3619, 0, 3485, + 3619, 0, 3483, + 3617, 0, 3483, + 3617, 0, 3483, + 3617, 0, 3483, + 3617, 0, 3483, + 3617, 0, 3481, + 3615, 0, 3481, + 3615, 0, 3479, + 3613, 0, 3479, + 3611, 0, 3477, + 3609, 0, 3473, + 3605, 0, 3469, + 3599, 0, 3465, + 3593, 0, 3457, + 3583, 0, 3449, + 3571, 1422, 3435, + 3555, 1880, 3417, + 3531, 2159, 3393, + 3497, 2377, 3357, + 3447, 2563, 3303, + 3369, 2733, 3223, + 3241, 2891, 3083, + 2979, 3041, 2787, + 0, 3187, 0, + 0, 3329, 0, + 0, 3467, 0, + 0, 3605, 0, + 0, 3741, 0, + 0, 3877, 0, + 0, 4011, 0, + 3745, 0, 3601, + 3745, 0, 3601, + 3745, 0, 3601, + 3745, 0, 3601, + 3745, 0, 3599, + 3745, 0, 3599, + 3745, 0, 3599, + 3745, 0, 3599, + 3743, 0, 3599, + 3743, 0, 3597, + 3741, 0, 3597, + 3741, 0, 3595, + 3739, 0, 3593, + 3735, 0, 3589, + 3731, 0, 3585, + 3727, 0, 3581, + 3721, 0, 3573, + 3711, 0, 3563, + 3699, 1258, 3549, + 3681, 1924, 3531, + 3657, 2245, 3505, + 3623, 2481, 3467, + 3571, 2677, 3413, + 3493, 2853, 3325, + 3363, 3015, 3177, + 3093, 3167, 2841, + 0, 3315, 0, + 0, 3457, 0, + 0, 3597, 0, + 0, 3735, 0, + 0, 3873, 0, + 0, 4007, 0, + 3875, 0, 3721, + 3875, 0, 3721, + 3875, 0, 3721, + 3875, 0, 3721, + 3875, 0, 3719, + 3873, 0, 3719, + 3873, 0, 3719, + 3873, 0, 3719, + 3873, 0, 3719, + 3873, 0, 3717, + 3871, 0, 3717, + 3871, 0, 3715, + 3869, 0, 3715, + 3867, 0, 3711, + 3863, 0, 3709, + 3861, 0, 3705, + 3855, 0, 3699, + 3849, 0, 3693, + 3839, 0, 3681, + 3827, 858, 3669, + 3809, 1978, 3649, + 3785, 2341, 3623, + 3749, 2591, 3583, + 3699, 2795, 3525, + 3619, 2975, 3435, + 3485, 3139, 3277, + 3209, 3295, 2903, + 0, 3443, 0, + 0, 3587, 0, + 0, 3727, 0, + 0, 3867, 0, + 0, 4003, 0, + 4005, 0, 3843, + 4005, 0, 3843, + 4003, 0, 3843, + 4003, 0, 3843, + 4003, 0, 3843, + 4003, 0, 3843, + 4003, 0, 3843, + 4003, 0, 3843, + 4003, 0, 3841, + 4003, 0, 3841, + 4001, 0, 3841, + 4001, 0, 3839, + 3999, 0, 3839, + 3999, 0, 3837, + 3997, 0, 3835, + 3993, 0, 3831, + 3989, 0, 3827, + 3985, 0, 3821, + 3977, 0, 3815, + 3969, 0, 3803, + 3955, 0, 3789, + 3939, 2041, 3771, + 3913, 2443, 3743, + 3879, 2707, 3703, + 3827, 2917, 3643, + 3747, 3101, 3549, + 3611, 3267, 3383, + 3329, 3423, 2977, + 0, 3573, 0, + 0, 3717, 0, + 0, 3859, 0, + 0, 3997, 0, + 4095, 0, 3969, + 4095, 0, 3969, + 4095, 0, 3969, + 4095, 0, 3969, + 4095, 0, 3967, + 4095, 0, 3967, + 4095, 0, 3967, + 4095, 0, 3967, + 4095, 0, 3967, + 4095, 0, 3967, + 4095, 0, 3967, + 4095, 0, 3965, + 4095, 0, 3965, + 4095, 0, 3963, + 4095, 0, 3961, + 4095, 0, 3959, + 4095, 0, 3957, + 4095, 0, 3951, + 4095, 0, 3947, + 4095, 0, 3939, + 4095, 0, 3929, + 4085, 0, 3913, + 4067, 2113, 3893, + 4043, 2551, 3865, + 4007, 2825, 3825, + 3955, 3041, 3765, + 3875, 3227, 3667, + 3739, 3395, 3495, + 3453, 3553, 3057, + 0, 3703, 0, + 0, 3849, 0, + 0, 3989, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4093, + 4095, 0, 4093, + 4095, 0, 4093, + 4095, 0, 4093, + 4095, 0, 4091, + 4095, 0, 4089, + 4095, 0, 4089, + 4095, 0, 4085, + 4095, 0, 4083, + 4095, 0, 4079, + 4095, 0, 4073, + 4095, 0, 4065, + 4095, 0, 4055, + 4095, 0, 4039, + 4095, 2195, 4019, + 4095, 2665, 3991, + 4095, 2947, 3949, + 4085, 3167, 3887, + 4005, 3355, 3789, + 3867, 3525, 3611, + 3579, 3683, 3149, + 0, 3833, 0, + 0, 3979, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2285, 4095, + 4095, 2783, 4095, + 4095, 3073, 4077, + 4095, 3295, 4013, + 4095, 3483, 3913, + 3997, 3655, 3731, + 3705, 3813, 3247, + 0, 3965, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2383, 4095, + 4095, 2905, 4095, + 4095, 3199, 4095, + 4095, 3423, 4095, + 4095, 3613, 4039, + 4095, 3785, 3855, + 3833, 3945, 3351, + 2299, 1852, 2711, + 2297, 1854, 2711, + 2293, 1857, 2709, + 2291, 1861, 2709, + 2285, 1866, 2707, + 2279, 1873, 2705, + 2269, 1882, 2703, + 2257, 1893, 2699, + 2241, 1909, 2693, + 2217, 1928, 2687, + 2183, 1953, 2679, + 2135, 1984, 2665, + 2059, 2022, 2649, + 1935, 2069, 2625, + 1685, 2125, 2591, + 0, 2191, 2541, + 0, 2265, 2467, + 0, 2349, 2339, + 0, 2441, 2085, + 0, 2543, 0, + 0, 2649, 0, + 0, 2761, 0, + 0, 2877, 0, + 0, 2997, 0, + 0, 3121, 0, + 0, 3245, 0, + 0, 3373, 0, + 0, 3501, 0, + 0, 3629, 0, + 0, 3759, 0, + 0, 3889, 0, + 0, 4021, 0, + 2301, 1852, 2711, + 2299, 1854, 2711, + 2297, 1857, 2711, + 2293, 1861, 2709, + 2287, 1866, 2707, + 2281, 1873, 2705, + 2273, 1882, 2703, + 2261, 1893, 2699, + 2243, 1908, 2695, + 2221, 1928, 2687, + 2187, 1952, 2679, + 2139, 1983, 2667, + 2065, 2022, 2649, + 1941, 2069, 2627, + 1695, 2125, 2593, + 251, 2191, 2543, + 0, 2265, 2467, + 0, 2349, 2341, + 0, 2441, 2087, + 0, 2541, 0, + 0, 2649, 0, + 0, 2761, 0, + 0, 2877, 0, + 0, 2997, 0, + 0, 3121, 0, + 0, 3245, 0, + 0, 3373, 0, + 0, 3501, 0, + 0, 3629, 0, + 0, 3759, 0, + 0, 3889, 0, + 0, 4021, 0, + 2305, 1851, 2713, + 2303, 1854, 2711, + 2299, 1857, 2711, + 2297, 1860, 2709, + 2291, 1866, 2709, + 2285, 1872, 2707, + 2277, 1881, 2703, + 2265, 1893, 2701, + 2247, 1908, 2695, + 2225, 1927, 2689, + 2191, 1952, 2679, + 2143, 1983, 2667, + 2069, 2022, 2651, + 1948, 2069, 2627, + 1708, 2125, 2593, + 483, 2189, 2545, + 0, 2265, 2469, + 0, 2349, 2343, + 0, 2441, 2091, + 0, 2541, 0, + 0, 2649, 0, + 0, 2761, 0, + 0, 2877, 0, + 0, 2997, 0, + 0, 3121, 0, + 0, 3245, 0, + 0, 3373, 0, + 0, 3501, 0, + 0, 3629, 0, + 0, 3759, 0, + 0, 3889, 0, + 0, 4021, 0, + 2309, 1851, 2713, + 2307, 1853, 2713, + 2305, 1856, 2713, + 2301, 1860, 2711, + 2295, 1865, 2709, + 2289, 1872, 2707, + 2281, 1881, 2705, + 2269, 1892, 2701, + 2253, 1907, 2697, + 2229, 1927, 2691, + 2197, 1951, 2681, + 2149, 1983, 2669, + 2077, 2021, 2653, + 1958, 2069, 2629, + 1724, 2125, 2595, + 678, 2189, 2547, + 0, 2265, 2471, + 0, 2349, 2345, + 0, 2441, 2095, + 0, 2541, 280, + 0, 2649, 0, + 0, 2761, 0, + 0, 2877, 0, + 0, 2997, 0, + 0, 3121, 0, + 0, 3245, 0, + 0, 3373, 0, + 0, 3501, 0, + 0, 3629, 0, + 0, 3759, 0, + 0, 3889, 0, + 0, 4021, 0, + 2315, 1850, 2715, + 2313, 1852, 2715, + 2311, 1855, 2713, + 2307, 1859, 2713, + 2301, 1864, 2711, + 2295, 1871, 2709, + 2287, 1880, 2707, + 2275, 1891, 2703, + 2259, 1907, 2699, + 2237, 1926, 2691, + 2205, 1951, 2683, + 2157, 1982, 2671, + 2087, 2021, 2653, + 1970, 2067, 2631, + 1744, 2123, 2597, + 852, 2189, 2549, + 0, 2265, 2473, + 0, 2349, 2349, + 0, 2441, 2101, + 0, 2541, 535, + 0, 2649, 0, + 0, 2761, 0, + 0, 2877, 0, + 0, 2997, 0, + 0, 3121, 0, + 0, 3245, 0, + 0, 3373, 0, + 0, 3501, 0, + 0, 3629, 0, + 0, 3759, 0, + 0, 3889, 0, + 0, 4021, 0, + 2323, 1849, 2717, + 2321, 1851, 2717, + 2317, 1854, 2715, + 2315, 1858, 2715, + 2309, 1863, 2713, + 2303, 1870, 2711, + 2295, 1879, 2709, + 2283, 1890, 2705, + 2267, 1906, 2701, + 2245, 1925, 2693, + 2215, 1950, 2685, + 2169, 1981, 2673, + 2099, 2020, 2657, + 1986, 2067, 2633, + 1771, 2123, 2599, + 1013, 2189, 2551, + 0, 2263, 2477, + 0, 2349, 2355, + 0, 2441, 2111, + 0, 2541, 741, + 0, 2649, 0, + 0, 2761, 0, + 0, 2877, 0, + 0, 2997, 0, + 0, 3121, 0, + 0, 3245, 0, + 0, 3373, 0, + 0, 3501, 0, + 0, 3629, 0, + 0, 3759, 0, + 0, 3889, 0, + 0, 4021, 0, + 2333, 1848, 2721, + 2331, 1850, 2719, + 2327, 1853, 2719, + 2325, 1857, 2717, + 2321, 1862, 2717, + 2315, 1869, 2715, + 2305, 1877, 2711, + 2295, 1889, 2709, + 2279, 1904, 2703, + 2257, 1924, 2697, + 2227, 1949, 2689, + 2183, 1980, 2677, + 2115, 2019, 2659, + 2007, 2065, 2637, + 1804, 2123, 2603, + 1166, 2187, 2555, + 0, 2263, 2483, + 0, 2347, 2361, + 0, 2441, 2121, + 0, 2541, 921, + 0, 2647, 0, + 0, 2761, 0, + 0, 2877, 0, + 0, 2997, 0, + 0, 3121, 0, + 0, 3245, 0, + 0, 3373, 0, + 0, 3501, 0, + 0, 3629, 0, + 0, 3759, 0, + 0, 3889, 0, + 0, 4021, 0, + 2345, 1846, 2725, + 2343, 1848, 2723, + 2341, 1851, 2723, + 2337, 1855, 2721, + 2333, 1860, 2721, + 2327, 1867, 2719, + 2319, 1876, 2715, + 2309, 1887, 2713, + 2293, 1903, 2707, + 2273, 1922, 2701, + 2243, 1947, 2693, + 2201, 1979, 2681, + 2137, 2017, 2663, + 2034, 2065, 2641, + 1845, 2121, 2609, + 1312, 2187, 2561, + 0, 2263, 2489, + 0, 2347, 2369, + 0, 2441, 2135, + 0, 2541, 1086, + 0, 2647, 0, + 0, 2759, 0, + 0, 2877, 0, + 0, 2997, 0, + 0, 3119, 0, + 0, 3245, 0, + 0, 3373, 0, + 0, 3501, 0, + 0, 3629, 0, + 0, 3759, 0, + 0, 3889, 0, + 0, 4021, 0, + 2363, 1843, 2729, + 2361, 1845, 2729, + 2359, 1848, 2727, + 2355, 1852, 2727, + 2351, 1857, 2725, + 2345, 1864, 2723, + 2337, 1873, 2721, + 2327, 1885, 2717, + 2313, 1900, 2713, + 2293, 1920, 2707, + 2265, 1945, 2697, + 2223, 1977, 2685, + 2163, 2016, 2669, + 2067, 2063, 2647, + 1894, 2119, 2615, + 1455, 2185, 2569, + 0, 2261, 2497, + 0, 2347, 2379, + 0, 2439, 2153, + 0, 2539, 1241, + 0, 2647, 0, + 0, 2759, 0, + 0, 2877, 0, + 0, 2997, 0, + 0, 3119, 0, + 0, 3245, 0, + 0, 3371, 0, + 0, 3501, 0, + 0, 3629, 0, + 0, 3759, 0, + 0, 3889, 0, + 0, 4021, 0, + 2385, 1839, 2735, + 2383, 1842, 2735, + 2381, 1845, 2735, + 2377, 1849, 2733, + 2373, 1854, 2731, + 2367, 1861, 2729, + 2361, 1870, 2727, + 2351, 1882, 2725, + 2337, 1897, 2719, + 2319, 1917, 2713, + 2291, 1942, 2705, + 2253, 1974, 2693, + 2197, 2013, 2677, + 2107, 2061, 2655, + 1952, 2117, 2623, + 1595, 2185, 2577, + 0, 2261, 2507, + 0, 2345, 2393, + 0, 2439, 2175, + 0, 2539, 1390, + 0, 2647, 0, + 0, 2759, 0, + 0, 2875, 0, + 0, 2997, 0, + 0, 3119, 0, + 0, 3245, 0, + 0, 3371, 0, + 0, 3501, 0, + 0, 3629, 0, + 0, 3759, 0, + 0, 3889, 0, + 0, 4021, 0, + 2411, 1835, 2745, + 2411, 1837, 2743, + 2409, 1840, 2743, + 2405, 1844, 2743, + 2401, 1849, 2741, + 2397, 1856, 2739, + 2389, 1865, 2737, + 2381, 1877, 2733, + 2367, 1893, 2729, + 2349, 1913, 2723, + 2325, 1939, 2715, + 2289, 1971, 2703, + 2237, 2010, 2687, + 2157, 2059, 2665, + 2020, 2115, 2635, + 1733, 2181, 2589, + 0, 2259, 2523, + 0, 2343, 2413, + 0, 2437, 2205, + 0, 2539, 1534, + 0, 2645, 0, + 0, 2759, 0, + 0, 2875, 0, + 0, 2997, 0, + 0, 3119, 0, + 0, 3245, 0, + 0, 3371, 0, + 0, 3499, 0, + 0, 3629, 0, + 0, 3759, 0, + 0, 3889, 0, + 0, 4021, 0, + 2447, 1828, 2755, + 2445, 1831, 2755, + 2443, 1834, 2755, + 2441, 1838, 2753, + 2437, 1843, 2753, + 2433, 1850, 2751, + 2425, 1859, 2747, + 2417, 1872, 2745, + 2405, 1887, 2741, + 2389, 1908, 2735, + 2367, 1933, 2727, + 2335, 1966, 2715, + 2287, 2006, 2701, + 2215, 2055, 2679, + 2099, 2111, 2649, + 1870, 2179, 2605, + 933, 2255, 2541, + 0, 2341, 2435, + 0, 2435, 2241, + 0, 2537, 1675, + 0, 2645, 0, + 0, 2757, 0, + 0, 2875, 0, + 0, 2995, 0, + 0, 3119, 0, + 0, 3245, 0, + 0, 3371, 0, + 0, 3499, 0, + 0, 3629, 0, + 0, 3759, 0, + 0, 3889, 0, + 0, 4021, 0, + 2489, 1819, 2771, + 2487, 1822, 2771, + 2485, 1825, 2769, + 2483, 1829, 2769, + 2479, 1835, 2767, + 2475, 1842, 2765, + 2469, 1851, 2763, + 2463, 1864, 2759, + 2451, 1880, 2755, + 2437, 1900, 2749, + 2417, 1926, 2741, + 2387, 1959, 2731, + 2347, 2000, 2717, + 2283, 2049, 2697, + 2185, 2107, 2667, + 2005, 2175, 2627, + 1530, 2253, 2565, + 0, 2339, 2465, + 0, 2433, 2285, + 0, 2535, 1814, + 0, 2643, 0, + 0, 2757, 0, + 0, 2873, 0, + 0, 2995, 0, + 0, 3119, 0, + 0, 3245, 0, + 0, 3371, 0, + 0, 3499, 0, + 0, 3629, 0, + 0, 3759, 0, + 0, 3889, 0, + 0, 4021, 0, + 2539, 1807, 2789, + 2539, 1810, 2789, + 2537, 1813, 2789, + 2535, 1817, 2787, + 2531, 1823, 2787, + 2529, 1830, 2785, + 2523, 1840, 2783, + 2515, 1853, 2779, + 2507, 1869, 2775, + 2493, 1890, 2769, + 2475, 1917, 2763, + 2451, 1951, 2753, + 2415, 1992, 2739, + 2361, 2042, 2719, + 2279, 2101, 2691, + 2139, 2169, 2653, + 1840, 2247, 2593, + 0, 2335, 2501, + 0, 2431, 2339, + 0, 2533, 1951, + 0, 2641, 0, + 0, 2755, 0, + 0, 2873, 0, + 0, 2993, 0, + 0, 3117, 0, + 0, 3243, 0, + 0, 3371, 0, + 0, 3499, 0, + 0, 3629, 0, + 0, 3759, 0, + 0, 3889, 0, + 0, 4021, 0, + 2599, 1791, 2813, + 2599, 1793, 2813, + 2597, 1797, 2813, + 2595, 1801, 2811, + 2593, 1807, 2811, + 2589, 1815, 2809, + 2585, 1825, 2807, + 2579, 1838, 2805, + 2571, 1855, 2801, + 2559, 1877, 2795, + 2545, 1904, 2789, + 2523, 1938, 2779, + 2493, 1981, 2765, + 2449, 2032, 2747, + 2381, 2093, 2721, + 2273, 2163, 2685, + 2071, 2241, 2631, + 1442, 2329, 2547, + 0, 2425, 2401, + 0, 2529, 2087, + 0, 2639, 0, + 0, 2753, 0, + 0, 2871, 0, + 0, 2993, 0, + 0, 3117, 0, + 0, 3243, 0, + 0, 3371, 0, + 0, 3499, 0, + 0, 3629, 0, + 0, 3759, 0, + 0, 3889, 0, + 0, 4021, 0, + 2669, 1768, 2845, + 2669, 1770, 2845, + 2667, 1774, 2843, + 2667, 1779, 2843, + 2665, 1785, 2841, + 2661, 1793, 2841, + 2657, 1803, 2839, + 2653, 1817, 2835, + 2645, 1835, 2831, + 2635, 1857, 2827, + 2623, 1886, 2821, + 2605, 1922, 2811, + 2579, 1966, 2799, + 2543, 2018, 2783, + 2489, 2081, 2759, + 2407, 2153, 2725, + 2265, 2233, 2675, + 1960, 2323, 2601, + 0, 2421, 2475, + 0, 2525, 2221, + 0, 2635, 0, + 0, 2751, 0, + 0, 2869, 0, + 0, 2991, 0, + 0, 3115, 0, + 0, 3241, 0, + 0, 3369, 0, + 0, 3499, 0, + 0, 3627, 0, + 0, 3759, 0, + 0, 3889, 0, + 0, 4021, 0, + 2749, 1735, 2883, + 2749, 1738, 2883, + 2747, 1742, 2881, + 2747, 1747, 2881, + 2745, 1753, 2879, + 2741, 1762, 2879, + 2739, 1773, 2877, + 2735, 1788, 2875, + 2729, 1807, 2871, + 2721, 1831, 2867, + 2709, 1861, 2861, + 2695, 1899, 2853, + 2675, 1945, 2841, + 2645, 2000, 2825, + 2603, 2065, 2805, + 2539, 2139, 2773, + 2439, 2221, 2729, + 2253, 2313, 2663, + 1749, 2413, 2555, + 0, 2519, 2355, + 0, 2631, 1740, + 0, 2747, 0, + 0, 2867, 0, + 0, 2989, 0, + 0, 3113, 0, + 0, 3241, 0, + 0, 3369, 0, + 0, 3497, 0, + 0, 3627, 0, + 0, 3757, 0, + 0, 3889, 0, + 0, 4019, 0, + 2837, 1687, 2929, + 2837, 1690, 2929, + 2835, 1694, 2927, + 2835, 1700, 2927, + 2833, 1707, 2927, + 2831, 1717, 2925, + 2829, 1729, 2923, + 2825, 1745, 2921, + 2821, 1766, 2919, + 2815, 1792, 2915, + 2805, 1825, 2909, + 2793, 1866, 2901, + 2777, 1915, 2891, + 2753, 1974, 2877, + 2721, 2042, 2859, + 2673, 2119, 2831, + 2599, 2205, 2793, + 2477, 2301, 2735, + 2239, 2403, 2647, + 1046, 2511, 2489, + 0, 2623, 2123, + 0, 2741, 0, + 0, 2863, 0, + 0, 2987, 0, + 0, 3111, 0, + 0, 3239, 0, + 0, 3367, 0, + 0, 3497, 0, + 0, 3627, 0, + 0, 3757, 0, + 0, 3889, 0, + 0, 4019, 0, + 2933, 1614, 2983, + 2933, 1617, 2983, + 2933, 1622, 2983, + 2931, 1629, 2983, + 2931, 1637, 2981, + 2929, 1648, 2981, + 2927, 1663, 2979, + 2923, 1681, 2977, + 2921, 1705, 2975, + 2915, 1735, 2971, + 2907, 1772, 2967, + 2899, 1818, 2959, + 2885, 1872, 2951, + 2867, 1936, 2939, + 2841, 2009, 2923, + 2805, 2093, 2899, + 2751, 2183, 2867, + 2669, 2283, 2817, + 2525, 2389, 2745, + 2217, 2499, 2621, + 0, 2615, 2381, + 0, 2735, 1111, + 0, 2857, 0, + 0, 2983, 0, + 0, 3109, 0, + 0, 3237, 0, + 0, 3365, 0, + 0, 3495, 0, + 0, 3625, 0, + 0, 3757, 0, + 0, 3887, 0, + 0, 4019, 0, + 3037, 1492, 3049, + 3037, 1497, 3049, + 3037, 1503, 3049, + 3035, 1512, 3047, + 3035, 1523, 3047, + 3033, 1537, 3045, + 3031, 1555, 3045, + 3029, 1579, 3043, + 3027, 1608, 3041, + 3023, 1645, 3037, + 3017, 1690, 3033, + 3009, 1744, 3027, + 2999, 1807, 3021, + 2985, 1880, 3011, + 2965, 1962, 2995, + 2937, 2053, 2977, + 2899, 2151, 2949, + 2839, 2257, 2909, + 2747, 2369, 2849, + 2583, 2483, 2755, + 2187, 2603, 2587, + 0, 2725, 2177, + 0, 2851, 0, + 0, 2977, 0, + 0, 3105, 0, + 0, 3233, 0, + 0, 3363, 0, + 0, 3493, 0, + 0, 3625, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 3147, 1253, 3123, + 3147, 1261, 3123, + 3145, 1272, 3123, + 3145, 1286, 3123, + 3145, 1304, 3121, + 3143, 1327, 3121, + 3143, 1355, 3119, + 3141, 1391, 3119, + 3137, 1435, 3117, + 3135, 1488, 3113, + 3131, 1550, 3111, + 3125, 1622, 3105, + 3117, 1703, 3099, + 3105, 1793, 3091, + 3091, 1891, 3079, + 3071, 1996, 3063, + 3041, 2107, 3039, + 2999, 2221, 3007, + 2935, 2341, 2959, + 2835, 2463, 2887, + 2649, 2587, 2769, + 2143, 2713, 2537, + 0, 2841, 1540, + 0, 2969, 0, + 0, 3099, 0, + 0, 3229, 0, + 0, 3361, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4017, 0, + 3261, 75, 3207, + 3261, 173, 3207, + 3261, 278, 3207, + 3259, 388, 3205, + 3259, 504, 3205, + 3259, 623, 3205, + 3257, 745, 3203, + 3255, 869, 3203, + 3255, 996, 3201, + 3251, 1123, 3199, + 3249, 1252, 3195, + 3243, 1382, 3193, + 3237, 1512, 3187, + 3229, 1643, 3179, + 3219, 1774, 3169, + 3203, 1905, 3157, + 3181, 2037, 3139, + 3151, 2169, 3113, + 3105, 2301, 3075, + 3039, 2433, 3021, + 2929, 2563, 2935, + 2725, 2695, 2787, + 2075, 2829, 2459, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 3379, 0, 3299, + 3379, 0, 3299, + 3379, 0, 3299, + 3379, 0, 3299, + 3377, 0, 3297, + 3377, 0, 3297, + 3377, 0, 3297, + 3375, 0, 3295, + 3375, 0, 3295, + 3373, 0, 3293, + 3369, 0, 3289, + 3367, 154, 3287, + 3361, 964, 3283, + 3355, 1304, 3277, + 3347, 1546, 3269, + 3335, 1746, 3259, + 3319, 1923, 3243, + 3297, 2087, 3223, + 3265, 2241, 3195, + 3219, 2387, 3153, + 3147, 2531, 3091, + 3033, 2671, 2991, + 2811, 2811, 2811, + 1967, 2947, 2331, + 0, 3083, 0, + 0, 3217, 0, + 0, 3351, 0, + 0, 3485, 0, + 0, 3617, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 3501, 0, 3399, + 3501, 0, 3399, + 3501, 0, 3399, + 3501, 0, 3397, + 3499, 0, 3397, + 3499, 0, 3397, + 3499, 0, 3397, + 3497, 0, 3395, + 3497, 0, 3395, + 3495, 0, 3393, + 3493, 0, 3391, + 3491, 0, 3389, + 3487, 0, 3385, + 3483, 0, 3381, + 3477, 624, 3375, + 3467, 1374, 3367, + 3455, 1707, 3355, + 3439, 1946, 3339, + 3415, 2145, 3317, + 3383, 2321, 3285, + 3335, 2483, 3239, + 3261, 2637, 3169, + 3141, 2785, 3057, + 2903, 2929, 2839, + 1764, 3069, 2065, + 0, 3207, 0, + 0, 3343, 0, + 0, 3479, 0, + 0, 3613, 0, + 0, 3747, 0, + 0, 3881, 0, + 0, 4013, 0, + 3625, 0, 3505, + 3625, 0, 3505, + 3625, 0, 3505, + 3625, 0, 3505, + 3623, 0, 3503, + 3623, 0, 3503, + 3623, 0, 3503, + 3623, 0, 3503, + 3621, 0, 3501, + 3621, 0, 3501, + 3619, 0, 3499, + 3617, 0, 3497, + 3615, 0, 3495, + 3611, 0, 3491, + 3607, 0, 3485, + 3599, 0, 3479, + 3591, 937, 3471, + 3579, 1648, 3459, + 3561, 1976, 3441, + 3539, 2213, 3417, + 3505, 2411, 3383, + 3455, 2587, 3335, + 3381, 2749, 3259, + 3255, 2903, 3131, + 3005, 3049, 2875, + 1131, 3193, 0, + 0, 3333, 0, + 0, 3471, 0, + 0, 3607, 0, + 0, 3743, 0, + 0, 3877, 0, + 0, 4011, 0, + 3751, 0, 3617, + 3751, 0, 3617, + 3751, 0, 3617, + 3751, 0, 3617, + 3751, 0, 3615, + 3749, 0, 3615, + 3749, 0, 3615, + 3749, 0, 3615, + 3749, 0, 3615, + 3747, 0, 3613, + 3747, 0, 3613, + 3745, 0, 3611, + 3743, 0, 3609, + 3741, 0, 3605, + 3737, 0, 3601, + 3731, 0, 3597, + 3725, 0, 3589, + 3717, 0, 3581, + 3703, 1555, 3567, + 3687, 2012, 3549, + 3663, 2291, 3525, + 3629, 2509, 3489, + 3579, 2695, 3437, + 3501, 2865, 3355, + 3373, 3023, 3215, + 3111, 3173, 2919, + 0, 3319, 0, + 0, 3461, 0, + 0, 3601, 0, + 0, 3737, 0, + 0, 3873, 0, + 0, 4009, 0, + 3879, 0, 3733, + 3879, 0, 3733, + 3877, 0, 3733, + 3877, 0, 3733, + 3877, 0, 3733, + 3877, 0, 3733, + 3877, 0, 3731, + 3877, 0, 3731, + 3877, 0, 3731, + 3875, 0, 3731, + 3875, 0, 3729, + 3873, 0, 3729, + 3873, 0, 3727, + 3871, 0, 3725, + 3867, 0, 3721, + 3863, 0, 3717, + 3859, 0, 3713, + 3853, 0, 3705, + 3843, 0, 3695, + 3831, 1390, 3681, + 3813, 2057, 3663, + 3789, 2379, 3637, + 3755, 2613, 3599, + 3703, 2809, 3545, + 3625, 2985, 3457, + 3495, 3147, 3309, + 3225, 3299, 2973, + 0, 3447, 0, + 0, 3589, 0, + 0, 3729, 0, + 0, 3867, 0, + 0, 4005, 0, + 4007, 0, 3853, + 4007, 0, 3853, + 4007, 0, 3853, + 4007, 0, 3853, + 4007, 0, 3853, + 4007, 0, 3853, + 4007, 0, 3851, + 4005, 0, 3851, + 4005, 0, 3851, + 4005, 0, 3851, + 4005, 0, 3851, + 4003, 0, 3849, + 4003, 0, 3847, + 4001, 0, 3847, + 3999, 0, 3843, + 3997, 0, 3841, + 3993, 0, 3837, + 3987, 0, 3831, + 3981, 0, 3825, + 3971, 0, 3815, + 3959, 990, 3801, + 3941, 2109, 3781, + 3917, 2473, 3755, + 3881, 2723, 3715, + 3831, 2927, 3657, + 3751, 3107, 3567, + 3619, 3271, 3409, + 3341, 3427, 3035, + 0, 3575, 0, + 0, 3719, 0, + 0, 3861, 0, + 0, 3999, 0, + 4095, 0, 3975, + 4095, 0, 3975, + 4095, 0, 3975, + 4095, 0, 3975, + 4095, 0, 3975, + 4095, 0, 3975, + 4095, 0, 3975, + 4095, 0, 3975, + 4095, 0, 3975, + 4095, 0, 3973, + 4095, 0, 3973, + 4095, 0, 3973, + 4095, 0, 3971, + 4095, 0, 3971, + 4095, 0, 3969, + 4095, 0, 3967, + 4095, 0, 3963, + 4095, 0, 3959, + 4095, 0, 3953, + 4095, 0, 3947, + 4095, 0, 3935, + 4087, 0, 3921, + 4071, 2173, 3903, + 4045, 2575, 3875, + 4011, 2839, 3835, + 3959, 3049, 3775, + 3879, 3233, 3681, + 3743, 3399, 3515, + 3461, 3555, 3109, + 0, 3705, 0, + 0, 3849, 0, + 0, 3991, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4093, + 4095, 0, 4091, + 4095, 0, 4089, + 4095, 0, 4085, + 4095, 0, 4079, + 4095, 0, 4071, + 4095, 0, 4061, + 4095, 0, 4045, + 4095, 2245, 4025, + 4095, 2683, 3997, + 4095, 2959, 3957, + 4087, 3173, 3897, + 4007, 3359, 3799, + 3871, 3527, 3627, + 3585, 3685, 3189, + 0, 3835, 0, + 0, 3981, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2327, 4095, + 4095, 2797, 4095, + 4095, 3081, 4081, + 4095, 3299, 4019, + 4095, 3487, 3921, + 3999, 3657, 3743, + 3711, 3815, 3281, + 0, 3965, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2417, 4095, + 4095, 2915, 4095, + 4095, 3205, 4095, + 4095, 3427, 4095, + 4095, 3615, 4045, + 4095, 3787, 3865, + 3837, 3945, 3379, + 2431, 1983, 2843, + 2429, 1985, 2843, + 2427, 1987, 2841, + 2425, 1990, 2841, + 2421, 1994, 2839, + 2415, 1999, 2839, + 2409, 2005, 2837, + 2401, 2014, 2833, + 2387, 2026, 2831, + 2371, 2041, 2825, + 2347, 2061, 2819, + 2313, 2085, 2809, + 2265, 2115, 2797, + 2189, 2155, 2781, + 2063, 2201, 2757, + 1810, 2257, 2723, + 0, 2323, 2673, + 0, 2397, 2597, + 0, 2481, 2471, + 0, 2575, 2215, + 0, 2675, 0, + 0, 2781, 0, + 0, 2893, 0, + 0, 3009, 0, + 0, 3129, 0, + 0, 3253, 0, + 0, 3377, 0, + 0, 3505, 0, + 0, 3633, 0, + 0, 3761, 0, + 0, 3891, 0, + 0, 4021, 0, + 2433, 1983, 2843, + 2431, 1984, 2843, + 2429, 1987, 2843, + 2425, 1989, 2841, + 2423, 1993, 2841, + 2417, 1998, 2839, + 2411, 2005, 2837, + 2403, 2014, 2835, + 2389, 2026, 2831, + 2373, 2041, 2825, + 2349, 2061, 2819, + 2317, 2085, 2811, + 2267, 2115, 2797, + 2193, 2155, 2781, + 2067, 2201, 2757, + 1818, 2257, 2723, + 69, 2323, 2675, + 0, 2397, 2599, + 0, 2481, 2471, + 0, 2575, 2217, + 0, 2675, 0, + 0, 2781, 0, + 0, 2893, 0, + 0, 3009, 0, + 0, 3129, 0, + 0, 3253, 0, + 0, 3377, 0, + 0, 3505, 0, + 0, 3633, 0, + 0, 3761, 0, + 0, 3891, 0, + 0, 4021, 0, + 2435, 1982, 2845, + 2433, 1984, 2843, + 2431, 1986, 2843, + 2429, 1989, 2843, + 2425, 1993, 2841, + 2421, 1998, 2839, + 2413, 2005, 2837, + 2405, 2014, 2835, + 2393, 2025, 2831, + 2375, 2040, 2827, + 2353, 2059, 2819, + 2319, 2085, 2811, + 2271, 2115, 2799, + 2197, 2153, 2781, + 2073, 2201, 2759, + 1827, 2257, 2725, + 383, 2323, 2675, + 0, 2397, 2599, + 0, 2481, 2473, + 0, 2573, 2219, + 0, 2675, 0, + 0, 2781, 0, + 0, 2893, 0, + 0, 3009, 0, + 0, 3129, 0, + 0, 3253, 0, + 0, 3377, 0, + 0, 3505, 0, + 0, 3633, 0, + 0, 3761, 0, + 0, 3891, 0, + 0, 4021, 0, + 2437, 1982, 2845, + 2437, 1984, 2845, + 2435, 1986, 2843, + 2431, 1989, 2843, + 2429, 1993, 2843, + 2423, 1998, 2841, + 2417, 2004, 2839, + 2409, 2013, 2835, + 2397, 2025, 2833, + 2379, 2040, 2827, + 2357, 2059, 2821, + 2323, 2085, 2811, + 2275, 2115, 2799, + 2201, 2153, 2783, + 2081, 2201, 2759, + 1840, 2257, 2725, + 615, 2321, 2677, + 0, 2397, 2601, + 0, 2481, 2475, + 0, 2573, 2223, + 0, 2673, 39, + 0, 2781, 0, + 0, 2893, 0, + 0, 3009, 0, + 0, 3129, 0, + 0, 3253, 0, + 0, 3377, 0, + 0, 3505, 0, + 0, 3633, 0, + 0, 3761, 0, + 0, 3891, 0, + 0, 4021, 0, + 2443, 1981, 2847, + 2441, 1983, 2845, + 2439, 1985, 2845, + 2437, 1988, 2845, + 2433, 1992, 2843, + 2429, 1997, 2841, + 2421, 2004, 2839, + 2413, 2013, 2837, + 2401, 2024, 2833, + 2385, 2039, 2829, + 2361, 2059, 2823, + 2329, 2083, 2813, + 2281, 2115, 2801, + 2209, 2153, 2785, + 2089, 2201, 2761, + 1856, 2257, 2727, + 810, 2321, 2679, + 0, 2397, 2603, + 0, 2481, 2477, + 0, 2573, 2227, + 0, 2673, 413, + 0, 2781, 0, + 0, 2893, 0, + 0, 3009, 0, + 0, 3129, 0, + 0, 3253, 0, + 0, 3377, 0, + 0, 3505, 0, + 0, 3633, 0, + 0, 3761, 0, + 0, 3891, 0, + 0, 4021, 0, + 2449, 1981, 2847, + 2447, 1982, 2847, + 2445, 1984, 2847, + 2443, 1987, 2845, + 2439, 1991, 2845, + 2435, 1996, 2843, + 2427, 2003, 2841, + 2419, 2012, 2839, + 2407, 2024, 2835, + 2391, 2039, 2831, + 2369, 2059, 2823, + 2337, 2083, 2815, + 2289, 2115, 2803, + 2219, 2153, 2787, + 2103, 2199, 2763, + 1877, 2255, 2729, + 984, 2321, 2681, + 0, 2397, 2605, + 0, 2481, 2481, + 0, 2573, 2235, + 0, 2673, 667, + 0, 2781, 0, + 0, 2893, 0, + 0, 3009, 0, + 0, 3129, 0, + 0, 3253, 0, + 0, 3377, 0, + 0, 3505, 0, + 0, 3633, 0, + 0, 3761, 0, + 0, 3891, 0, + 0, 4021, 0, + 2455, 1979, 2849, + 2455, 1981, 2849, + 2453, 1983, 2849, + 2449, 1986, 2849, + 2447, 1990, 2847, + 2441, 1995, 2845, + 2435, 2002, 2843, + 2427, 2011, 2841, + 2415, 2023, 2837, + 2399, 2038, 2833, + 2377, 2057, 2827, + 2347, 2083, 2817, + 2301, 2113, 2805, + 2231, 2151, 2789, + 2119, 2199, 2765, + 1903, 2255, 2733, + 1145, 2321, 2683, + 0, 2395, 2609, + 0, 2481, 2487, + 0, 2573, 2243, + 0, 2673, 873, + 0, 2781, 0, + 0, 2893, 0, + 0, 3009, 0, + 0, 3129, 0, + 0, 3253, 0, + 0, 3377, 0, + 0, 3505, 0, + 0, 3633, 0, + 0, 3761, 0, + 0, 3891, 0, + 0, 4021, 0, + 2465, 1978, 2853, + 2465, 1980, 2853, + 2463, 1982, 2851, + 2461, 1985, 2851, + 2457, 1989, 2849, + 2453, 1994, 2849, + 2447, 2001, 2847, + 2437, 2010, 2843, + 2427, 2021, 2841, + 2411, 2036, 2835, + 2389, 2057, 2829, + 2359, 2081, 2821, + 2315, 2113, 2809, + 2247, 2151, 2791, + 2139, 2199, 2769, + 1936, 2255, 2735, + 1298, 2321, 2687, + 0, 2395, 2615, + 0, 2479, 2493, + 0, 2573, 2253, + 0, 2673, 1053, + 0, 2779, 0, + 0, 2893, 0, + 0, 3009, 0, + 0, 3129, 0, + 0, 3253, 0, + 0, 3377, 0, + 0, 3505, 0, + 0, 3633, 0, + 0, 3761, 0, + 0, 3891, 0, + 0, 4021, 0, + 2479, 1976, 2857, + 2477, 1978, 2857, + 2475, 1980, 2855, + 2473, 1983, 2855, + 2471, 1987, 2853, + 2465, 1992, 2853, + 2459, 1999, 2851, + 2451, 2008, 2847, + 2441, 2020, 2845, + 2425, 2035, 2839, + 2405, 2055, 2833, + 2375, 2079, 2825, + 2333, 2111, 2813, + 2269, 2149, 2797, + 2165, 2197, 2773, + 1977, 2253, 2741, + 1445, 2319, 2693, + 0, 2395, 2621, + 0, 2479, 2501, + 0, 2573, 2267, + 0, 2673, 1218, + 0, 2779, 0, + 0, 2891, 0, + 0, 3009, 0, + 0, 3129, 0, + 0, 3253, 0, + 0, 3377, 0, + 0, 3505, 0, + 0, 3633, 0, + 0, 3761, 0, + 0, 3891, 0, + 0, 4021, 0, + 2495, 1973, 2861, + 2495, 1975, 2861, + 2493, 1977, 2861, + 2491, 1980, 2859, + 2487, 1984, 2859, + 2483, 1989, 2857, + 2477, 1996, 2855, + 2469, 2005, 2853, + 2459, 2017, 2849, + 2445, 2032, 2845, + 2425, 2053, 2839, + 2397, 2077, 2829, + 2357, 2109, 2819, + 2295, 2147, 2801, + 2199, 2195, 2779, + 2026, 2251, 2747, + 1587, 2317, 2701, + 0, 2393, 2629, + 0, 2479, 2511, + 0, 2571, 2285, + 0, 2673, 1373, + 0, 2779, 0, + 0, 2891, 0, + 0, 3009, 0, + 0, 3129, 0, + 0, 3251, 0, + 0, 3377, 0, + 0, 3505, 0, + 0, 3633, 0, + 0, 3761, 0, + 0, 3891, 0, + 0, 4021, 0, + 2517, 1970, 2869, + 2517, 1972, 2867, + 2515, 1974, 2867, + 2513, 1977, 2867, + 2509, 1981, 2865, + 2505, 1986, 2863, + 2501, 1993, 2863, + 2493, 2002, 2859, + 2483, 2014, 2857, + 2469, 2029, 2851, + 2451, 2049, 2845, + 2423, 2075, 2837, + 2385, 2107, 2825, + 2329, 2145, 2809, + 2239, 2193, 2787, + 2085, 2249, 2755, + 1727, 2317, 2709, + 0, 2393, 2639, + 0, 2477, 2527, + 0, 2571, 2309, + 0, 2671, 1522, + 0, 2779, 0, + 0, 2891, 0, + 0, 3009, 0, + 0, 3129, 0, + 0, 3251, 0, + 0, 3377, 0, + 0, 3503, 0, + 0, 3633, 0, + 0, 3761, 0, + 0, 3891, 0, + 0, 4021, 0, + 2545, 1965, 2877, + 2543, 1967, 2877, + 2543, 1969, 2875, + 2541, 1972, 2875, + 2537, 1976, 2875, + 2533, 1981, 2873, + 2529, 1988, 2871, + 2521, 1998, 2869, + 2513, 2010, 2865, + 2499, 2025, 2861, + 2481, 2045, 2855, + 2457, 2071, 2847, + 2421, 2103, 2835, + 2369, 2143, 2819, + 2289, 2191, 2797, + 2153, 2247, 2767, + 1865, 2315, 2721, + 0, 2391, 2655, + 0, 2475, 2545, + 0, 2569, 2337, + 0, 2671, 1666, + 0, 2777, 0, + 0, 2891, 0, + 0, 3007, 0, + 0, 3129, 0, + 0, 3251, 0, + 0, 3377, 0, + 0, 3503, 0, + 0, 3633, 0, + 0, 3761, 0, + 0, 3891, 0, + 0, 4021, 0, + 2579, 1959, 2889, + 2579, 1960, 2887, + 2577, 1963, 2887, + 2575, 1966, 2887, + 2573, 1970, 2885, + 2569, 1975, 2885, + 2565, 1982, 2883, + 2557, 1992, 2881, + 2549, 2004, 2877, + 2537, 2019, 2873, + 2521, 2040, 2867, + 2499, 2065, 2859, + 2467, 2097, 2847, + 2419, 2137, 2833, + 2347, 2187, 2811, + 2231, 2243, 2781, + 2002, 2311, 2737, + 1065, 2387, 2673, + 0, 2473, 2567, + 0, 2567, 2373, + 0, 2669, 1807, + 0, 2777, 0, + 0, 2889, 0, + 0, 3007, 0, + 0, 3127, 0, + 0, 3251, 0, + 0, 3377, 0, + 0, 3503, 0, + 0, 3631, 0, + 0, 3761, 0, + 0, 3891, 0, + 0, 4021, 0, + 2621, 1950, 2903, + 2621, 1952, 2903, + 2619, 1954, 2903, + 2617, 1957, 2901, + 2615, 1961, 2901, + 2611, 1967, 2899, + 2607, 1974, 2897, + 2601, 1983, 2895, + 2595, 1996, 2891, + 2583, 2012, 2887, + 2569, 2032, 2881, + 2549, 2059, 2875, + 2519, 2091, 2863, + 2479, 2131, 2849, + 2415, 2181, 2829, + 2317, 2239, 2799, + 2137, 2307, 2759, + 1662, 2385, 2697, + 0, 2471, 2597, + 0, 2565, 2417, + 0, 2667, 1946, + 0, 2775, 0, + 0, 2889, 0, + 0, 3007, 0, + 0, 3127, 0, + 0, 3251, 0, + 0, 3377, 0, + 0, 3503, 0, + 0, 3631, 0, + 0, 3761, 0, + 0, 3891, 0, + 0, 4021, 0, + 2673, 1938, 2923, + 2671, 1940, 2921, + 2671, 1942, 2921, + 2669, 1945, 2921, + 2667, 1949, 2919, + 2663, 1955, 2919, + 2661, 1962, 2917, + 2655, 1972, 2915, + 2649, 1985, 2911, + 2639, 2001, 2907, + 2625, 2022, 2901, + 2607, 2049, 2895, + 2583, 2083, 2885, + 2547, 2123, 2871, + 2493, 2173, 2851, + 2411, 2233, 2823, + 2271, 2301, 2785, + 1972, 2379, 2725, + 0, 2467, 2633, + 0, 2563, 2471, + 0, 2665, 2083, + 0, 2773, 0, + 0, 2887, 0, + 0, 3005, 0, + 0, 3127, 0, + 0, 3249, 0, + 0, 3375, 0, + 0, 3503, 0, + 0, 3631, 0, + 0, 3761, 0, + 0, 3891, 0, + 0, 4021, 0, + 2733, 1921, 2947, + 2731, 1923, 2947, + 2731, 1926, 2945, + 2729, 1929, 2945, + 2727, 1933, 2945, + 2725, 1939, 2943, + 2721, 1947, 2941, + 2717, 1957, 2939, + 2711, 1970, 2937, + 2703, 1987, 2933, + 2693, 2009, 2927, + 2677, 2036, 2921, + 2655, 2071, 2911, + 2625, 2113, 2897, + 2581, 2163, 2879, + 2513, 2225, 2853, + 2405, 2295, 2817, + 2203, 2373, 2763, + 1574, 2461, 2679, + 0, 2559, 2533, + 0, 2661, 2219, + 0, 2771, 0, + 0, 2885, 0, + 0, 3003, 0, + 0, 3125, 0, + 0, 3249, 0, + 0, 3375, 0, + 0, 3503, 0, + 0, 3631, 0, + 0, 3761, 0, + 0, 3891, 0, + 0, 4021, 0, + 2803, 1898, 2977, + 2801, 1900, 2977, + 2801, 1903, 2977, + 2799, 1906, 2975, + 2799, 1911, 2975, + 2797, 1917, 2973, + 2793, 1925, 2973, + 2789, 1935, 2971, + 2785, 1949, 2967, + 2777, 1967, 2963, + 2767, 1990, 2959, + 2755, 2018, 2953, + 2737, 2055, 2943, + 2711, 2097, 2931, + 2675, 2151, 2915, + 2621, 2213, 2891, + 2539, 2285, 2857, + 2397, 2365, 2807, + 2093, 2455, 2733, + 0, 2553, 2607, + 0, 2657, 2353, + 0, 2767, 0, + 0, 2883, 0, + 0, 3001, 0, + 0, 3123, 0, + 0, 3247, 0, + 0, 3375, 0, + 0, 3501, 0, + 0, 3631, 0, + 0, 3761, 0, + 0, 3891, 0, + 0, 4021, 0, + 2881, 1865, 3015, + 2881, 1867, 3015, + 2881, 1870, 3015, + 2879, 1874, 3013, + 2879, 1879, 3013, + 2877, 1885, 3011, + 2875, 1894, 3011, + 2871, 1905, 3009, + 2867, 1920, 3007, + 2861, 1939, 3003, + 2853, 1963, 2999, + 2843, 1993, 2993, + 2827, 2031, 2985, + 2807, 2077, 2973, + 2777, 2131, 2957, + 2735, 2197, 2937, + 2673, 2271, 2905, + 2571, 2353, 2861, + 2387, 2445, 2795, + 1882, 2545, 2687, + 0, 2651, 2487, + 0, 2763, 1872, + 0, 2879, 0, + 0, 2999, 0, + 0, 3121, 0, + 0, 3247, 0, + 0, 3373, 0, + 0, 3501, 0, + 0, 3629, 0, + 0, 3759, 0, + 0, 3889, 0, + 0, 4021, 0, + 2969, 1817, 3061, + 2969, 1819, 3061, + 2969, 1822, 3061, + 2969, 1826, 3059, + 2967, 1832, 3059, + 2965, 1839, 3059, + 2963, 1849, 3057, + 2961, 1861, 3055, + 2957, 1877, 3053, + 2953, 1898, 3051, + 2947, 1924, 3047, + 2937, 1957, 3041, + 2925, 1998, 3033, + 2909, 2047, 3023, + 2885, 2105, 3009, + 2853, 2173, 2991, + 2805, 2251, 2963, + 2731, 2337, 2925, + 2611, 2433, 2869, + 2371, 2535, 2779, + 1178, 2643, 2621, + 0, 2757, 2255, + 0, 2873, 0, + 0, 2995, 0, + 0, 3119, 0, + 0, 3243, 0, + 0, 3371, 0, + 0, 3499, 0, + 0, 3629, 0, + 0, 3759, 0, + 0, 3889, 0, + 0, 4021, 0, + 3067, 1743, 3117, + 3065, 1746, 3117, + 3065, 1749, 3115, + 3065, 1754, 3115, + 3063, 1761, 3115, + 3063, 1769, 3113, + 3061, 1780, 3113, + 3059, 1795, 3111, + 3057, 1813, 3109, + 3053, 1837, 3107, + 3047, 1867, 3103, + 3041, 1904, 3099, + 3031, 1950, 3093, + 3017, 2004, 3083, + 2999, 2069, 3071, + 2973, 2141, 3055, + 2937, 2225, 3031, + 2883, 2315, 2999, + 2801, 2415, 2951, + 2657, 2521, 2877, + 2349, 2631, 2755, + 0, 2747, 2513, + 0, 2867, 1244, + 0, 2989, 0, + 0, 3115, 0, + 0, 3241, 0, + 0, 3369, 0, + 0, 3497, 0, + 0, 3627, 0, + 0, 3757, 0, + 0, 3889, 0, + 0, 4019, 0, + 3169, 1621, 3181, + 3169, 1624, 3181, + 3169, 1629, 3181, + 3169, 1636, 3181, + 3167, 1644, 3179, + 3167, 1655, 3179, + 3165, 1669, 3179, + 3163, 1687, 3177, + 3161, 1711, 3175, + 3159, 1741, 3173, + 3155, 1777, 3169, + 3149, 1822, 3165, + 3141, 1876, 3161, + 3131, 1940, 3153, + 3117, 2012, 3143, + 3097, 2095, 3129, + 3071, 2185, 3109, + 3031, 2285, 3081, + 2971, 2389, 3041, + 2879, 2501, 2981, + 2715, 2617, 2887, + 2319, 2735, 2719, + 0, 2857, 2309, + 0, 2983, 0, + 0, 3109, 0, + 0, 3237, 0, + 0, 3365, 0, + 0, 3495, 0, + 0, 3625, 0, + 0, 3757, 0, + 0, 3887, 0, + 0, 4019, 0, + 3279, 1379, 3255, + 3279, 1385, 3255, + 3279, 1394, 3255, + 3277, 1404, 3255, + 3277, 1418, 3255, + 3277, 1436, 3253, + 3275, 1459, 3253, + 3275, 1487, 3251, + 3273, 1523, 3251, + 3271, 1567, 3249, + 3267, 1620, 3245, + 3263, 1683, 3243, + 3257, 1754, 3237, + 3249, 1836, 3231, + 3239, 1925, 3223, + 3223, 2023, 3211, + 3203, 2127, 3195, + 3173, 2239, 3171, + 3131, 2353, 3139, + 3067, 2473, 3091, + 2967, 2595, 3019, + 2781, 2719, 2901, + 2275, 2845, 2669, + 0, 2973, 1672, + 0, 3101, 0, + 0, 3231, 0, + 0, 3361, 0, + 0, 3493, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 3393, 117, 3339, + 3393, 207, 3339, + 3393, 305, 3339, + 3393, 410, 3339, + 3391, 520, 3337, + 3391, 636, 3337, + 3391, 755, 3337, + 3389, 877, 3335, + 3389, 1001, 3335, + 3387, 1128, 3333, + 3383, 1255, 3331, + 3381, 1384, 3329, + 3375, 1514, 3325, + 3369, 1644, 3319, + 3361, 1775, 3311, + 3351, 1906, 3303, + 3335, 2037, 3289, + 3313, 2169, 3271, + 3283, 2301, 3245, + 3239, 2433, 3207, + 3171, 2565, 3153, + 3061, 2697, 3067, + 2857, 2829, 2919, + 2207, 2961, 2591, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 3511, 0, 3431, + 3511, 0, 3431, + 3511, 0, 3431, + 3511, 0, 3431, + 3511, 0, 3431, + 3509, 0, 3429, + 3509, 0, 3429, + 3509, 0, 3429, + 3507, 0, 3427, + 3507, 0, 3427, + 3505, 0, 3425, + 3501, 0, 3423, + 3499, 286, 3419, + 3493, 1096, 3415, + 3487, 1436, 3409, + 3479, 1678, 3401, + 3467, 1878, 3391, + 3451, 2055, 3375, + 3429, 2219, 3355, + 3397, 2373, 3327, + 3351, 2521, 3285, + 3279, 2663, 3223, + 3165, 2803, 3123, + 2943, 2943, 2943, + 2099, 3079, 2463, + 0, 3215, 0, + 0, 3349, 0, + 0, 3483, 0, + 0, 3617, 0, + 0, 3749, 0, + 0, 3883, 0, + 0, 4015, 0, + 3633, 0, 3531, + 3633, 0, 3531, + 3633, 0, 3531, + 3633, 0, 3531, + 3633, 0, 3529, + 3631, 0, 3529, + 3631, 0, 3529, + 3631, 0, 3529, + 3629, 0, 3527, + 3629, 0, 3527, + 3627, 0, 3525, + 3625, 0, 3523, + 3623, 0, 3521, + 3619, 0, 3517, + 3615, 0, 3513, + 3609, 756, 3507, + 3599, 1506, 3499, + 3587, 1839, 3487, + 3571, 2079, 3471, + 3547, 2277, 3449, + 3515, 2453, 3417, + 3467, 2615, 3371, + 3395, 2769, 3301, + 3273, 2917, 3189, + 3035, 3061, 2971, + 1896, 3201, 2197, + 0, 3339, 0, + 0, 3475, 0, + 0, 3611, 0, + 0, 3745, 0, + 0, 3879, 0, + 0, 4013, 0, + 3757, 0, 3637, + 3757, 0, 3637, + 3757, 0, 3637, + 3757, 0, 3637, + 3757, 0, 3637, + 3757, 0, 3637, + 3755, 0, 3635, + 3755, 0, 3635, + 3755, 0, 3635, + 3753, 0, 3633, + 3753, 0, 3633, + 3751, 0, 3631, + 3749, 0, 3629, + 3747, 0, 3627, + 3743, 0, 3623, + 3739, 0, 3619, + 3731, 0, 3611, + 3723, 1069, 3603, + 3711, 1780, 3591, + 3693, 2107, 3573, + 3671, 2345, 3549, + 3637, 2543, 3515, + 3587, 2719, 3467, + 3513, 2881, 3391, + 3387, 3035, 3263, + 3137, 3181, 3007, + 1263, 3325, 0, + 0, 3465, 0, + 0, 3603, 0, + 0, 3739, 0, + 0, 3875, 0, + 0, 4009, 0, + 3883, 0, 3749, + 3883, 0, 3749, + 3883, 0, 3749, + 3883, 0, 3749, + 3883, 0, 3749, + 3883, 0, 3747, + 3881, 0, 3747, + 3881, 0, 3747, + 3881, 0, 3747, + 3881, 0, 3747, + 3879, 0, 3745, + 3879, 0, 3745, + 3877, 0, 3743, + 3875, 0, 3741, + 3873, 0, 3737, + 3869, 0, 3733, + 3863, 0, 3729, + 3857, 0, 3721, + 3849, 0, 3713, + 3835, 1687, 3699, + 3819, 2145, 3681, + 3795, 2423, 3657, + 3761, 2641, 3621, + 3711, 2827, 3569, + 3633, 2997, 3487, + 3505, 3155, 3347, + 3243, 3305, 3053, + 0, 3451, 0, + 0, 3593, 0, + 0, 3733, 0, + 0, 3869, 0, + 0, 4005, 0, + 4011, 0, 3865, + 4011, 0, 3865, + 4011, 0, 3865, + 4011, 0, 3865, + 4009, 0, 3865, + 4009, 0, 3865, + 4009, 0, 3865, + 4009, 0, 3863, + 4009, 0, 3863, + 4009, 0, 3863, + 4007, 0, 3863, + 4007, 0, 3861, + 4005, 0, 3861, + 4005, 0, 3859, + 4003, 0, 3857, + 3999, 0, 3853, + 3997, 0, 3849, + 3991, 0, 3845, + 3985, 0, 3837, + 3975, 0, 3827, + 3963, 1522, 3815, + 3945, 2189, 3795, + 3921, 2511, 3769, + 3887, 2745, 3731, + 3835, 2941, 3677, + 3757, 3117, 3589, + 3627, 3279, 3441, + 3357, 3431, 3105, + 0, 3579, 0, + 0, 3721, 0, + 0, 3861, 0, + 0, 3999, 0, + 4095, 0, 3985, + 4095, 0, 3985, + 4095, 0, 3985, + 4095, 0, 3985, + 4095, 0, 3985, + 4095, 0, 3985, + 4095, 0, 3985, + 4095, 0, 3985, + 4095, 0, 3983, + 4095, 0, 3983, + 4095, 0, 3983, + 4095, 0, 3983, + 4095, 0, 3981, + 4095, 0, 3981, + 4095, 0, 3979, + 4095, 0, 3977, + 4095, 0, 3973, + 4095, 0, 3969, + 4095, 0, 3963, + 4095, 0, 3957, + 4095, 0, 3947, + 4091, 1122, 3933, + 4073, 2243, 3913, + 4049, 2605, 3887, + 4015, 2855, 3847, + 3963, 3061, 3789, + 3883, 3239, 3699, + 3751, 3405, 3541, + 3473, 3559, 3169, + 0, 3707, 0, + 0, 3851, 0, + 0, 3993, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4091, + 4095, 0, 4085, + 4095, 0, 4079, + 4095, 0, 4069, + 4095, 0, 4053, + 4095, 2305, 4035, + 4095, 2707, 4007, + 4095, 2971, 3967, + 4091, 3181, 3907, + 4011, 3365, 3813, + 3877, 3531, 3647, + 3593, 3687, 3241, + 0, 3837, 0, + 0, 3981, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2377, 4095, + 4095, 2815, 4095, + 4095, 3091, 4089, + 4095, 3305, 4029, + 4095, 3491, 3933, + 4003, 3659, 3759, + 3717, 3817, 3321, + 0, 3967, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2459, 4095, + 4095, 2929, 4095, + 4095, 3213, 4095, + 4095, 3431, 4095, + 4095, 3619, 4053, + 4095, 3789, 3877, + 3843, 3947, 3413, + 2563, 2115, 2975, + 2561, 2115, 2975, + 2559, 2117, 2975, + 2557, 2119, 2973, + 2555, 2123, 2973, + 2551, 2125, 2971, + 2547, 2131, 2971, + 2539, 2137, 2969, + 2531, 2147, 2965, + 2519, 2159, 2961, + 2501, 2173, 2957, + 2477, 2193, 2951, + 2445, 2217, 2941, + 2395, 2249, 2929, + 2319, 2287, 2913, + 2193, 2333, 2889, + 1937, 2389, 2855, + 0, 2455, 2805, + 0, 2529, 2729, + 0, 2613, 2601, + 0, 2707, 2345, + 0, 2807, 0, + 0, 2913, 0, + 0, 3025, 0, + 0, 3141, 0, + 0, 3261, 0, + 0, 3385, 0, + 0, 3509, 0, + 0, 3637, 0, + 0, 3765, 0, + 0, 3893, 0, + 0, 4023, 0, + 2563, 2113, 2975, + 2563, 2115, 2975, + 2561, 2117, 2975, + 2559, 2119, 2973, + 2557, 2121, 2973, + 2553, 2125, 2973, + 2547, 2131, 2971, + 2541, 2137, 2969, + 2533, 2147, 2965, + 2519, 2157, 2963, + 2503, 2173, 2957, + 2479, 2193, 2951, + 2445, 2217, 2941, + 2397, 2249, 2929, + 2321, 2287, 2913, + 2195, 2333, 2889, + 1942, 2389, 2855, + 0, 2455, 2805, + 0, 2529, 2729, + 0, 2613, 2603, + 0, 2707, 2347, + 0, 2807, 0, + 0, 2913, 0, + 0, 3025, 0, + 0, 3141, 0, + 0, 3261, 0, + 0, 3385, 0, + 0, 3509, 0, + 0, 3637, 0, + 0, 3765, 0, + 0, 3893, 0, + 0, 4023, 0, + 2565, 2113, 2975, + 2565, 2115, 2975, + 2563, 2117, 2975, + 2561, 2119, 2975, + 2559, 2121, 2973, + 2555, 2125, 2973, + 2549, 2131, 2971, + 2543, 2137, 2969, + 2535, 2147, 2967, + 2523, 2157, 2963, + 2505, 2173, 2957, + 2481, 2193, 2951, + 2449, 2217, 2943, + 2399, 2247, 2931, + 2325, 2287, 2913, + 2199, 2333, 2889, + 1950, 2389, 2855, + 201, 2455, 2807, + 0, 2529, 2731, + 0, 2613, 2603, + 0, 2707, 2349, + 0, 2807, 0, + 0, 2913, 0, + 0, 3025, 0, + 0, 3141, 0, + 0, 3261, 0, + 0, 3385, 0, + 0, 3509, 0, + 0, 3637, 0, + 0, 3765, 0, + 0, 3893, 0, + 0, 4023, 0, + 2567, 2113, 2977, + 2567, 2115, 2977, + 2565, 2117, 2975, + 2563, 2119, 2975, + 2561, 2121, 2975, + 2557, 2125, 2973, + 2553, 2131, 2971, + 2545, 2137, 2969, + 2537, 2145, 2967, + 2525, 2157, 2963, + 2509, 2173, 2959, + 2485, 2191, 2953, + 2451, 2217, 2943, + 2403, 2247, 2931, + 2329, 2287, 2913, + 2205, 2333, 2891, + 1959, 2389, 2857, + 515, 2455, 2807, + 0, 2529, 2731, + 0, 2613, 2605, + 0, 2707, 2351, + 0, 2807, 0, + 0, 2913, 0, + 0, 3025, 0, + 0, 3141, 0, + 0, 3261, 0, + 0, 3385, 0, + 0, 3509, 0, + 0, 3637, 0, + 0, 3765, 0, + 0, 3893, 0, + 0, 4023, 0, + 2571, 2113, 2977, + 2569, 2115, 2977, + 2569, 2115, 2977, + 2567, 2117, 2977, + 2563, 2121, 2975, + 2561, 2125, 2975, + 2555, 2129, 2973, + 2549, 2137, 2971, + 2541, 2145, 2969, + 2529, 2157, 2965, + 2511, 2173, 2959, + 2489, 2191, 2953, + 2455, 2217, 2945, + 2407, 2247, 2931, + 2333, 2285, 2915, + 2213, 2333, 2891, + 1972, 2389, 2857, + 748, 2455, 2809, + 0, 2529, 2733, + 0, 2613, 2607, + 0, 2705, 2355, + 0, 2807, 171, + 0, 2913, 0, + 0, 3025, 0, + 0, 3141, 0, + 0, 3261, 0, + 0, 3385, 0, + 0, 3509, 0, + 0, 3637, 0, + 0, 3765, 0, + 0, 3893, 0, + 0, 4023, 0, + 2575, 2113, 2979, + 2575, 2113, 2979, + 2573, 2115, 2977, + 2571, 2117, 2977, + 2569, 2121, 2977, + 2565, 2125, 2975, + 2561, 2129, 2973, + 2553, 2135, 2971, + 2545, 2145, 2969, + 2533, 2157, 2965, + 2517, 2171, 2961, + 2493, 2191, 2955, + 2461, 2215, 2945, + 2413, 2247, 2933, + 2341, 2285, 2917, + 2221, 2333, 2893, + 1988, 2389, 2859, + 942, 2453, 2811, + 0, 2529, 2735, + 0, 2613, 2611, + 0, 2705, 2359, + 0, 2805, 544, + 0, 2913, 0, + 0, 3025, 0, + 0, 3141, 0, + 0, 3261, 0, + 0, 3385, 0, + 0, 3509, 0, + 0, 3637, 0, + 0, 3765, 0, + 0, 3893, 0, + 0, 4023, 0, + 2581, 2111, 2981, + 2581, 2113, 2979, + 2579, 2115, 2979, + 2577, 2117, 2979, + 2575, 2119, 2979, + 2571, 2123, 2977, + 2567, 2129, 2975, + 2559, 2135, 2973, + 2551, 2145, 2971, + 2539, 2155, 2967, + 2523, 2171, 2963, + 2501, 2191, 2955, + 2469, 2215, 2947, + 2423, 2247, 2935, + 2351, 2285, 2919, + 2235, 2331, 2895, + 2009, 2387, 2861, + 1116, 2453, 2813, + 0, 2529, 2737, + 0, 2613, 2613, + 0, 2705, 2367, + 0, 2805, 799, + 0, 2913, 0, + 0, 3025, 0, + 0, 3141, 0, + 0, 3261, 0, + 0, 3385, 0, + 0, 3509, 0, + 0, 3637, 0, + 0, 3765, 0, + 0, 3893, 0, + 0, 4023, 0, + 2589, 2111, 2983, + 2587, 2111, 2983, + 2587, 2113, 2981, + 2585, 2115, 2981, + 2583, 2119, 2981, + 2579, 2123, 2979, + 2575, 2127, 2977, + 2567, 2135, 2975, + 2559, 2143, 2973, + 2547, 2155, 2969, + 2533, 2169, 2965, + 2509, 2189, 2959, + 2479, 2215, 2949, + 2433, 2245, 2937, + 2363, 2285, 2921, + 2251, 2331, 2897, + 2035, 2387, 2865, + 1277, 2453, 2815, + 0, 2529, 2741, + 0, 2613, 2619, + 0, 2705, 2375, + 0, 2805, 1005, + 0, 2913, 0, + 0, 3025, 0, + 0, 3141, 0, + 0, 3261, 0, + 0, 3385, 0, + 0, 3509, 0, + 0, 3637, 0, + 0, 3765, 0, + 0, 3893, 0, + 0, 4023, 0, + 2599, 2109, 2985, + 2597, 2111, 2985, + 2597, 2111, 2985, + 2595, 2113, 2983, + 2593, 2117, 2983, + 2589, 2121, 2983, + 2585, 2125, 2981, + 2579, 2133, 2979, + 2571, 2141, 2975, + 2559, 2153, 2973, + 2543, 2169, 2967, + 2521, 2189, 2961, + 2491, 2213, 2953, + 2447, 2245, 2941, + 2379, 2283, 2923, + 2271, 2331, 2901, + 2069, 2387, 2867, + 1430, 2453, 2819, + 0, 2527, 2747, + 0, 2611, 2625, + 0, 2705, 2385, + 0, 2805, 1185, + 0, 2913, 0, + 0, 3025, 0, + 0, 3141, 0, + 0, 3261, 0, + 0, 3385, 0, + 0, 3509, 0, + 0, 3637, 0, + 0, 3765, 0, + 0, 3893, 0, + 0, 4023, 0, + 2611, 2107, 2989, + 2611, 2109, 2989, + 2609, 2109, 2989, + 2607, 2113, 2987, + 2605, 2115, 2987, + 2603, 2119, 2985, + 2597, 2125, 2985, + 2593, 2131, 2983, + 2585, 2139, 2979, + 2573, 2151, 2977, + 2559, 2167, 2971, + 2537, 2187, 2965, + 2507, 2211, 2957, + 2465, 2243, 2945, + 2401, 2281, 2929, + 2297, 2329, 2905, + 2109, 2385, 2873, + 1577, 2451, 2825, + 0, 2527, 2753, + 0, 2611, 2633, + 0, 2705, 2399, + 0, 2805, 1350, + 0, 2911, 0, + 0, 3025, 0, + 0, 3141, 0, + 0, 3261, 0, + 0, 3385, 0, + 0, 3509, 0, + 0, 3637, 0, + 0, 3765, 0, + 0, 3893, 0, + 0, 4023, 0, + 2629, 2105, 2995, + 2627, 2105, 2993, + 2627, 2107, 2993, + 2625, 2109, 2993, + 2623, 2113, 2991, + 2619, 2117, 2991, + 2615, 2121, 2989, + 2609, 2129, 2987, + 2601, 2137, 2985, + 2591, 2149, 2981, + 2577, 2165, 2977, + 2557, 2185, 2971, + 2529, 2209, 2961, + 2489, 2241, 2951, + 2427, 2279, 2933, + 2331, 2327, 2911, + 2159, 2383, 2879, + 1720, 2451, 2833, + 0, 2525, 2761, + 0, 2611, 2645, + 0, 2703, 2417, + 0, 2805, 1506, + 0, 2911, 0, + 0, 3023, 0, + 0, 3141, 0, + 0, 3261, 0, + 0, 3385, 0, + 0, 3509, 0, + 0, 3637, 0, + 0, 3765, 0, + 0, 3893, 0, + 0, 4023, 0, + 2651, 2101, 3001, + 2649, 2101, 3001, + 2649, 2103, 2999, + 2647, 2105, 2999, + 2645, 2109, 2999, + 2641, 2113, 2997, + 2637, 2119, 2997, + 2633, 2125, 2995, + 2625, 2135, 2991, + 2615, 2147, 2989, + 2601, 2161, 2983, + 2583, 2181, 2977, + 2555, 2207, 2969, + 2517, 2239, 2957, + 2461, 2277, 2941, + 2371, 2325, 2919, + 2217, 2383, 2887, + 1860, 2449, 2841, + 0, 2525, 2773, + 0, 2609, 2659, + 0, 2703, 2441, + 0, 2803, 1654, + 0, 2911, 0, + 0, 3023, 0, + 0, 3141, 0, + 0, 3261, 0, + 0, 3383, 0, + 0, 3509, 0, + 0, 3637, 0, + 0, 3765, 0, + 0, 3893, 0, + 0, 4023, 0, + 2677, 2095, 3009, + 2677, 2097, 3009, + 2675, 2099, 3009, + 2675, 2101, 3009, + 2673, 2105, 3007, + 2669, 2109, 3007, + 2665, 2113, 3005, + 2661, 2121, 3003, + 2653, 2129, 3001, + 2645, 2141, 2997, + 2631, 2157, 2993, + 2615, 2177, 2987, + 2589, 2203, 2979, + 2553, 2235, 2967, + 2501, 2275, 2951, + 2421, 2323, 2929, + 2285, 2379, 2899, + 1998, 2447, 2855, + 0, 2523, 2787, + 0, 2607, 2677, + 0, 2701, 2469, + 0, 2803, 1798, + 0, 2909, 0, + 0, 3023, 0, + 0, 3139, 0, + 0, 3261, 0, + 0, 3383, 0, + 0, 3509, 0, + 0, 3635, 0, + 0, 3765, 0, + 0, 3893, 0, + 0, 4023, 0, + 2713, 2089, 3021, + 2711, 2091, 3021, + 2711, 2093, 3021, + 2709, 2095, 3019, + 2707, 2097, 3019, + 2705, 2101, 3017, + 2701, 2107, 3017, + 2697, 2115, 3015, + 2689, 2123, 3013, + 2681, 2135, 3009, + 2669, 2151, 3005, + 2653, 2171, 2999, + 2631, 2197, 2991, + 2599, 2231, 2979, + 2551, 2269, 2965, + 2479, 2319, 2943, + 2363, 2377, 2913, + 2133, 2443, 2869, + 1197, 2519, 2805, + 0, 2605, 2699, + 0, 2699, 2505, + 0, 2801, 1939, + 0, 2909, 0, + 0, 3021, 0, + 0, 3139, 0, + 0, 3259, 0, + 0, 3383, 0, + 0, 3509, 0, + 0, 3635, 0, + 0, 3765, 0, + 0, 3893, 0, + 0, 4023, 0, + 2755, 2081, 3035, + 2753, 2081, 3035, + 2753, 2083, 3035, + 2751, 2087, 3035, + 2749, 2089, 3033, + 2747, 2093, 3033, + 2745, 2099, 3031, + 2739, 2107, 3029, + 2735, 2115, 3027, + 2727, 2127, 3025, + 2715, 2143, 3019, + 2701, 2165, 3015, + 2681, 2191, 3007, + 2651, 2223, 2995, + 2611, 2265, 2981, + 2549, 2313, 2961, + 2449, 2371, 2931, + 2269, 2439, 2891, + 1794, 2517, 2829, + 0, 2603, 2729, + 0, 2697, 2551, + 0, 2799, 2077, + 0, 2907, 0, + 0, 3021, 0, + 0, 3139, 0, + 0, 3259, 0, + 0, 3383, 0, + 0, 3509, 0, + 0, 3635, 0, + 0, 3763, 0, + 0, 3893, 0, + 0, 4023, 0, + 2805, 2069, 3055, + 2805, 2069, 3055, + 2803, 2071, 3053, + 2803, 2075, 3053, + 2801, 2077, 3053, + 2799, 2081, 3051, + 2797, 2087, 3051, + 2793, 2095, 3049, + 2787, 2105, 3047, + 2781, 2117, 3043, + 2771, 2133, 3039, + 2757, 2155, 3033, + 2739, 2181, 3027, + 2715, 2215, 3017, + 2679, 2257, 3003, + 2625, 2305, 2983, + 2543, 2365, 2955, + 2403, 2433, 2917, + 2105, 2511, 2857, + 0, 2599, 2765, + 0, 2695, 2603, + 0, 2797, 2215, + 0, 2905, 0, + 0, 3019, 0, + 0, 3137, 0, + 0, 3259, 0, + 0, 3381, 0, + 0, 3507, 0, + 0, 3635, 0, + 0, 3763, 0, + 0, 3893, 0, + 0, 4023, 0, + 2865, 2051, 3079, + 2865, 2053, 3079, + 2865, 2055, 3079, + 2863, 2057, 3077, + 2861, 2061, 3077, + 2859, 2065, 3077, + 2857, 2071, 3075, + 2855, 2079, 3073, + 2849, 2089, 3071, + 2843, 2103, 3069, + 2835, 2119, 3065, + 2825, 2141, 3059, + 2809, 2169, 3053, + 2787, 2203, 3043, + 2757, 2245, 3029, + 2713, 2297, 3011, + 2645, 2357, 2985, + 2537, 2427, 2949, + 2335, 2505, 2895, + 1706, 2593, 2811, + 0, 2691, 2667, + 0, 2793, 2351, + 0, 2903, 0, + 0, 3017, 0, + 0, 3135, 0, + 0, 3257, 0, + 0, 3381, 0, + 0, 3507, 0, + 0, 3635, 0, + 0, 3763, 0, + 0, 3893, 0, + 0, 4023, 0, + 2935, 2029, 3109, + 2935, 2030, 3109, + 2935, 2032, 3109, + 2933, 2035, 3109, + 2933, 2038, 3107, + 2931, 2043, 3107, + 2929, 2049, 3105, + 2925, 2057, 3105, + 2921, 2067, 3103, + 2917, 2081, 3099, + 2909, 2099, 3097, + 2901, 2121, 3091, + 2887, 2151, 3085, + 2869, 2187, 3075, + 2843, 2229, 3063, + 2807, 2283, 3047, + 2753, 2345, 3023, + 2671, 2417, 2989, + 2529, 2497, 2939, + 2225, 2587, 2865, + 0, 2685, 2739, + 0, 2789, 2485, + 0, 2899, 0, + 0, 3015, 0, + 0, 3133, 0, + 0, 3255, 0, + 0, 3379, 0, + 0, 3507, 0, + 0, 3633, 0, + 0, 3763, 0, + 0, 3893, 0, + 0, 4023, 0, + 3015, 1995, 3147, + 3013, 1997, 3147, + 3013, 1999, 3147, + 3013, 2002, 3147, + 3011, 2006, 3145, + 3011, 2011, 3145, + 3009, 2017, 3143, + 3007, 2026, 3143, + 3003, 2037, 3141, + 2999, 2051, 3139, + 2993, 2071, 3135, + 2985, 2095, 3131, + 2975, 2125, 3125, + 2959, 2163, 3117, + 2939, 2209, 3105, + 2909, 2263, 3089, + 2867, 2329, 3069, + 2805, 2403, 3037, + 2703, 2485, 2993, + 2519, 2577, 2927, + 2014, 2677, 2819, + 0, 2783, 2619, + 0, 2895, 2004, + 0, 3011, 0, + 0, 3131, 0, + 0, 3253, 0, + 0, 3379, 0, + 0, 3505, 0, + 0, 3633, 0, + 0, 3761, 0, + 0, 3891, 0, + 0, 4023, 0, + 3103, 1947, 3193, + 3103, 1949, 3193, + 3101, 1951, 3193, + 3101, 1954, 3193, + 3101, 1958, 3193, + 3099, 1964, 3191, + 3097, 1971, 3191, + 3095, 1981, 3189, + 3093, 1993, 3187, + 3089, 2009, 3185, + 3085, 2030, 3183, + 3079, 2057, 3179, + 3069, 2089, 3173, + 3057, 2131, 3165, + 3041, 2179, 3155, + 3017, 2237, 3141, + 2985, 2305, 3123, + 2937, 2383, 3095, + 2863, 2469, 3057, + 2743, 2565, 3001, + 2503, 2667, 2911, + 1310, 2775, 2753, + 0, 2889, 2387, + 0, 3005, 0, + 0, 3127, 0, + 0, 3251, 0, + 0, 3377, 0, + 0, 3503, 0, + 0, 3631, 0, + 0, 3761, 0, + 0, 3891, 0, + 0, 4021, 0, + 3199, 1873, 3249, + 3199, 1875, 3249, + 3197, 1878, 3249, + 3197, 1882, 3247, + 3197, 1886, 3247, + 3195, 1893, 3247, + 3195, 1901, 3247, + 3193, 1912, 3245, + 3191, 1927, 3243, + 3189, 1946, 3241, + 3185, 1969, 3239, + 3179, 1999, 3235, + 3173, 2036, 3231, + 3163, 2081, 3225, + 3149, 2137, 3215, + 3131, 2201, 3203, + 3107, 2273, 3187, + 3069, 2357, 3163, + 3015, 2447, 3131, + 2933, 2547, 3083, + 2789, 2653, 3009, + 2481, 2763, 2887, + 0, 2879, 2645, + 0, 2999, 1376, + 0, 3121, 0, + 0, 3247, 0, + 0, 3373, 0, + 0, 3501, 0, + 0, 3629, 0, + 0, 3759, 0, + 0, 3891, 0, + 0, 4021, 0, + 3301, 1750, 3313, + 3301, 1753, 3313, + 3301, 1757, 3313, + 3301, 1761, 3313, + 3301, 1768, 3313, + 3299, 1776, 3311, + 3299, 1787, 3311, + 3297, 1801, 3311, + 3295, 1820, 3309, + 3293, 1843, 3307, + 3291, 1873, 3305, + 3287, 1909, 3301, + 3281, 1954, 3297, + 3273, 2008, 3293, + 3263, 2071, 3285, + 3249, 2145, 3275, + 3229, 2227, 3261, + 3203, 2317, 3241, + 3163, 2417, 3213, + 3103, 2521, 3173, + 3011, 2633, 3113, + 2847, 2749, 3019, + 2451, 2867, 2851, + 0, 2991, 2441, + 0, 3115, 0, + 0, 3241, 0, + 0, 3369, 0, + 0, 3497, 0, + 0, 3627, 0, + 0, 3759, 0, + 0, 3889, 0, + 0, 4019, 0, + 3411, 1507, 3387, + 3411, 1511, 3387, + 3411, 1518, 3387, + 3411, 1526, 3387, + 3409, 1536, 3387, + 3409, 1550, 3387, + 3409, 1568, 3385, + 3407, 1591, 3385, + 3407, 1620, 3383, + 3405, 1656, 3383, + 3403, 1700, 3381, + 3399, 1752, 3377, + 3395, 1815, 3375, + 3389, 1886, 3369, + 3381, 1968, 3363, + 3371, 2057, 3355, + 3355, 2155, 3343, + 3335, 2259, 3327, + 3305, 2371, 3303, + 3263, 2485, 3271, + 3199, 2605, 3223, + 3099, 2727, 3151, + 2913, 2851, 3033, + 2407, 2977, 2801, + 0, 3105, 1804, + 0, 3235, 0, + 0, 3363, 0, + 0, 3493, 0, + 0, 3625, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 3525, 167, 3471, + 3525, 249, 3471, + 3525, 339, 3471, + 3525, 437, 3471, + 3525, 542, 3471, + 3523, 652, 3471, + 3523, 768, 3469, + 3523, 887, 3469, + 3521, 1009, 3467, + 3521, 1133, 3467, + 3519, 1260, 3465, + 3515, 1387, 3463, + 3513, 1516, 3461, + 3509, 1646, 3457, + 3503, 1776, 3451, + 3493, 1907, 3443, + 3483, 2038, 3435, + 3467, 2169, 3421, + 3445, 2301, 3403, + 3415, 2433, 3377, + 3371, 2565, 3339, + 3303, 2697, 3285, + 3193, 2829, 3199, + 2989, 2961, 3051, + 2339, 3093, 2725, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 3643, 0, 3563, + 3643, 0, 3563, + 3643, 0, 3563, + 3643, 0, 3563, + 3643, 0, 3563, + 3643, 0, 3563, + 3643, 0, 3561, + 3641, 0, 3561, + 3641, 0, 3561, + 3639, 0, 3559, + 3639, 0, 3559, + 3637, 0, 3557, + 3633, 0, 3555, + 3631, 418, 3551, + 3625, 1228, 3547, + 3619, 1568, 3541, + 3611, 1811, 3533, + 3599, 2011, 3523, + 3583, 2187, 3507, + 3561, 2351, 3487, + 3529, 2505, 3459, + 3483, 2653, 3417, + 3413, 2795, 3355, + 3297, 2937, 3255, + 3075, 3075, 3075, + 2231, 3211, 2595, + 0, 3347, 0, + 0, 3481, 0, + 0, 3615, 0, + 0, 3749, 0, + 0, 3881, 0, + 0, 4015, 0, + 3765, 0, 3663, + 3765, 0, 3663, + 3765, 0, 3663, + 3765, 0, 3663, + 3765, 0, 3663, + 3765, 0, 3663, + 3763, 0, 3661, + 3763, 0, 3661, + 3763, 0, 3661, + 3763, 0, 3659, + 3761, 0, 3659, + 3759, 0, 3657, + 3757, 0, 3655, + 3755, 0, 3653, + 3751, 0, 3649, + 3747, 0, 3645, + 3741, 888, 3639, + 3731, 1638, 3631, + 3719, 1971, 3619, + 3703, 2211, 3603, + 3681, 2409, 3581, + 3647, 2585, 3549, + 3599, 2749, 3503, + 3527, 2901, 3433, + 3405, 3049, 3321, + 3167, 3193, 3103, + 2028, 3333, 2329, + 0, 3471, 0, + 0, 3607, 0, + 0, 3743, 0, + 0, 3877, 0, + 0, 4011, 0, + 3889, 0, 3769, + 3889, 0, 3769, + 3889, 0, 3769, + 3889, 0, 3769, + 3889, 0, 3769, + 3889, 0, 3769, + 3889, 0, 3769, + 3887, 0, 3767, + 3887, 0, 3767, + 3887, 0, 3767, + 3885, 0, 3765, + 3885, 0, 3765, + 3883, 0, 3763, + 3881, 0, 3761, + 3879, 0, 3759, + 3875, 0, 3755, + 3871, 0, 3751, + 3863, 0, 3743, + 3855, 1201, 3735, + 3843, 1912, 3723, + 3825, 2239, 3705, + 3803, 2477, 3681, + 3769, 2675, 3647, + 3719, 2851, 3599, + 3645, 3013, 3523, + 3519, 3167, 3395, + 3269, 3313, 3139, + 1395, 3457, 0, + 0, 3597, 0, + 0, 3735, 0, + 0, 3871, 0, + 0, 4007, 0, + 4015, 0, 3881, + 4015, 0, 3881, + 4015, 0, 3881, + 4015, 0, 3881, + 4015, 0, 3881, + 4015, 0, 3881, + 4015, 0, 3881, + 4015, 0, 3879, + 4013, 0, 3879, + 4013, 0, 3879, + 4013, 0, 3879, + 4011, 0, 3877, + 4011, 0, 3877, + 4009, 0, 3875, + 4007, 0, 3873, + 4005, 0, 3869, + 4001, 0, 3867, + 3995, 0, 3861, + 3989, 0, 3855, + 3981, 0, 3845, + 3967, 1819, 3831, + 3951, 2277, 3813, + 3927, 2555, 3789, + 3893, 2773, 3753, + 3843, 2961, 3701, + 3765, 3129, 3619, + 3637, 3287, 3479, + 3375, 3437, 3185, + 0, 3583, 0, + 0, 3725, 0, + 0, 3865, 0, + 0, 4001, 0, + 4095, 0, 3997, + 4095, 0, 3997, + 4095, 0, 3997, + 4095, 0, 3997, + 4095, 0, 3997, + 4095, 0, 3997, + 4095, 0, 3997, + 4095, 0, 3997, + 4095, 0, 3997, + 4095, 0, 3995, + 4095, 0, 3995, + 4095, 0, 3995, + 4095, 0, 3993, + 4095, 0, 3993, + 4095, 0, 3991, + 4095, 0, 3989, + 4095, 0, 3985, + 4095, 0, 3981, + 4095, 0, 3977, + 4095, 0, 3969, + 4095, 0, 3959, + 4095, 1654, 3947, + 4077, 2321, 3927, + 4053, 2643, 3901, + 4019, 2877, 3865, + 3967, 3075, 3809, + 3889, 3249, 3723, + 3759, 3411, 3573, + 3489, 3563, 3237, + 0, 3711, 0, + 0, 3853, 0, + 0, 3993, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4089, + 4095, 0, 4079, + 4095, 1254, 4065, + 4095, 2375, 4045, + 4095, 2737, 4019, + 4095, 2989, 3979, + 4095, 3193, 3923, + 4015, 3371, 3831, + 3883, 3537, 3673, + 3605, 3691, 3301, + 0, 3839, 0, + 0, 3983, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2437, 4095, + 4095, 2839, 4095, + 4095, 3103, 4095, + 4095, 3313, 4039, + 4095, 3497, 3945, + 4009, 3663, 3779, + 3725, 3819, 3373, + 0, 3969, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2509, 4095, + 4095, 2949, 4095, + 4095, 3223, 4095, + 4095, 3437, 4095, + 4095, 3623, 4065, + 4095, 3791, 3891, + 3849, 3949, 3455, + 2693, 2245, 3107, + 2693, 2247, 3107, + 2691, 2247, 3107, + 2691, 2249, 3107, + 2689, 2251, 3105, + 2685, 2255, 3105, + 2683, 2259, 3103, + 2677, 2263, 3103, + 2671, 2269, 3101, + 2661, 2279, 3097, + 2649, 2291, 3093, + 2633, 2305, 3089, + 2609, 2325, 3083, + 2575, 2349, 3073, + 2525, 2381, 3061, + 2449, 2419, 3043, + 2321, 2465, 3021, + 2065, 2521, 2987, + 0, 2587, 2937, + 0, 2661, 2861, + 0, 2745, 2733, + 0, 2839, 2477, + 0, 2939, 0, + 0, 3045, 0, + 0, 3157, 0, + 0, 3273, 0, + 0, 3393, 0, + 0, 3517, 0, + 0, 3641, 0, + 0, 3769, 0, + 0, 3897, 0, + 0, 4025, 0, + 2695, 2245, 3107, + 2695, 2247, 3107, + 2693, 2247, 3107, + 2691, 2249, 3107, + 2689, 2251, 3105, + 2687, 2255, 3105, + 2683, 2259, 3103, + 2679, 2263, 3103, + 2671, 2269, 3101, + 2663, 2279, 3097, + 2651, 2291, 3095, + 2633, 2305, 3089, + 2609, 2325, 3083, + 2577, 2349, 3073, + 2527, 2381, 3061, + 2451, 2419, 3045, + 2325, 2465, 3021, + 2069, 2521, 2987, + 0, 2587, 2937, + 0, 2661, 2861, + 0, 2745, 2733, + 0, 2839, 2477, + 0, 2939, 0, + 0, 3045, 0, + 0, 3157, 0, + 0, 3273, 0, + 0, 3393, 0, + 0, 3517, 0, + 0, 3641, 0, + 0, 3769, 0, + 0, 3897, 0, + 0, 4025, 0, + 2697, 2245, 3107, + 2695, 2247, 3107, + 2695, 2247, 3107, + 2693, 2249, 3107, + 2691, 2251, 3107, + 2689, 2253, 3105, + 2685, 2257, 3105, + 2679, 2263, 3103, + 2673, 2269, 3101, + 2665, 2279, 3099, + 2653, 2291, 3095, + 2635, 2305, 3089, + 2611, 2325, 3083, + 2577, 2349, 3073, + 2529, 2381, 3061, + 2453, 2419, 3045, + 2327, 2465, 3021, + 2075, 2521, 2987, + 0, 2587, 2937, + 0, 2661, 2861, + 0, 2745, 2735, + 0, 2839, 2479, + 0, 2939, 0, + 0, 3045, 0, + 0, 3157, 0, + 0, 3273, 0, + 0, 3393, 0, + 0, 3517, 0, + 0, 3641, 0, + 0, 3769, 0, + 0, 3897, 0, + 0, 4025, 0, + 2699, 2245, 3109, + 2697, 2245, 3109, + 2697, 2247, 3107, + 2695, 2249, 3107, + 2693, 2251, 3107, + 2691, 2253, 3105, + 2687, 2257, 3105, + 2681, 2263, 3103, + 2675, 2269, 3101, + 2667, 2279, 3099, + 2655, 2289, 3095, + 2637, 2305, 3091, + 2613, 2325, 3083, + 2581, 2349, 3075, + 2531, 2381, 3063, + 2457, 2419, 3045, + 2331, 2465, 3021, + 2081, 2521, 2987, + 333, 2587, 2939, + 0, 2661, 2863, + 0, 2745, 2735, + 0, 2839, 2481, + 0, 2939, 0, + 0, 3045, 0, + 0, 3157, 0, + 0, 3273, 0, + 0, 3393, 0, + 0, 3517, 0, + 0, 3641, 0, + 0, 3769, 0, + 0, 3897, 0, + 0, 4025, 0, + 2701, 2245, 3109, + 2699, 2245, 3109, + 2699, 2247, 3109, + 2697, 2249, 3107, + 2695, 2251, 3107, + 2693, 2253, 3107, + 2689, 2257, 3105, + 2685, 2263, 3103, + 2677, 2269, 3101, + 2669, 2277, 3099, + 2657, 2289, 3095, + 2641, 2305, 3091, + 2617, 2325, 3085, + 2583, 2349, 3075, + 2535, 2379, 3063, + 2461, 2419, 3047, + 2337, 2465, 3023, + 2091, 2521, 2989, + 647, 2587, 2939, + 0, 2661, 2863, + 0, 2745, 2737, + 0, 2839, 2483, + 0, 2939, 0, + 0, 3045, 0, + 0, 3157, 0, + 0, 3273, 0, + 0, 3393, 0, + 0, 3517, 0, + 0, 3641, 0, + 0, 3769, 0, + 0, 3897, 0, + 0, 4025, 0, + 2705, 2245, 3109, + 2703, 2245, 3109, + 2703, 2247, 3109, + 2701, 2247, 3109, + 2699, 2251, 3109, + 2697, 2253, 3107, + 2693, 2257, 3107, + 2687, 2261, 3105, + 2681, 2269, 3103, + 2673, 2277, 3101, + 2661, 2289, 3097, + 2643, 2305, 3091, + 2621, 2323, 3085, + 2587, 2349, 3077, + 2539, 2379, 3063, + 2467, 2417, 3047, + 2345, 2465, 3023, + 2103, 2521, 2989, + 880, 2587, 2941, + 0, 2661, 2865, + 0, 2745, 2739, + 0, 2839, 2487, + 0, 2939, 303, + 0, 3045, 0, + 0, 3157, 0, + 0, 3273, 0, + 0, 3393, 0, + 0, 3517, 0, + 0, 3641, 0, + 0, 3769, 0, + 0, 3897, 0, + 0, 4025, 0, + 2709, 2243, 3111, + 2707, 2245, 3111, + 2707, 2245, 3111, + 2705, 2247, 3111, + 2703, 2249, 3109, + 2701, 2253, 3109, + 2697, 2257, 3107, + 2693, 2261, 3107, + 2685, 2269, 3105, + 2677, 2277, 3101, + 2665, 2289, 3097, + 2649, 2303, 3093, + 2627, 2323, 3087, + 2593, 2347, 3077, + 2545, 2379, 3065, + 2473, 2417, 3049, + 2353, 2465, 3025, + 2121, 2521, 2991, + 1074, 2585, 2943, + 0, 2661, 2867, + 0, 2745, 2743, + 0, 2837, 2493, + 0, 2939, 677, + 0, 3045, 0, + 0, 3157, 0, + 0, 3273, 0, + 0, 3393, 0, + 0, 3517, 0, + 0, 3641, 0, + 0, 3769, 0, + 0, 3897, 0, + 0, 4025, 0, + 2715, 2243, 3113, + 2713, 2243, 3113, + 2713, 2245, 3113, + 2711, 2247, 3111, + 2709, 2249, 3111, + 2707, 2251, 3111, + 2703, 2255, 3109, + 2699, 2261, 3107, + 2693, 2267, 3105, + 2683, 2277, 3103, + 2671, 2287, 3099, + 2655, 2303, 3095, + 2633, 2323, 3089, + 2601, 2347, 3079, + 2555, 2379, 3067, + 2483, 2417, 3051, + 2367, 2463, 3027, + 2141, 2519, 2993, + 1248, 2585, 2945, + 0, 2661, 2869, + 0, 2745, 2745, + 0, 2837, 2499, + 0, 2937, 931, + 0, 3045, 0, + 0, 3157, 0, + 0, 3273, 0, + 0, 3393, 0, + 0, 3517, 0, + 0, 3641, 0, + 0, 3769, 0, + 0, 3897, 0, + 0, 4025, 0, + 2721, 2241, 3115, + 2721, 2243, 3115, + 2719, 2243, 3115, + 2719, 2245, 3113, + 2717, 2247, 3113, + 2715, 2251, 3113, + 2711, 2255, 3111, + 2707, 2259, 3109, + 2701, 2267, 3107, + 2691, 2275, 3105, + 2681, 2287, 3101, + 2665, 2303, 3097, + 2643, 2321, 3091, + 2611, 2347, 3081, + 2565, 2377, 3069, + 2495, 2417, 3053, + 2383, 2463, 3029, + 2167, 2519, 2997, + 1409, 2585, 2947, + 0, 2661, 2873, + 0, 2745, 2751, + 0, 2837, 2507, + 0, 2937, 1137, + 0, 3045, 0, + 0, 3157, 0, + 0, 3273, 0, + 0, 3393, 0, + 0, 3517, 0, + 0, 3641, 0, + 0, 3769, 0, + 0, 3897, 0, + 0, 4025, 0, + 2731, 2241, 3117, + 2731, 2241, 3117, + 2731, 2243, 3117, + 2729, 2243, 3117, + 2727, 2247, 3117, + 2725, 2249, 3115, + 2721, 2253, 3115, + 2717, 2259, 3113, + 2711, 2265, 3111, + 2703, 2273, 3109, + 2691, 2285, 3105, + 2675, 2301, 3099, + 2653, 2321, 3093, + 2623, 2345, 3085, + 2579, 2377, 3073, + 2513, 2415, 3057, + 2403, 2463, 3033, + 2201, 2519, 3001, + 1562, 2585, 2951, + 0, 2659, 2879, + 0, 2745, 2757, + 0, 2837, 2517, + 0, 2937, 1317, + 0, 3045, 0, + 0, 3157, 0, + 0, 3273, 0, + 0, 3393, 0, + 0, 3517, 0, + 0, 3641, 0, + 0, 3769, 0, + 0, 3897, 0, + 0, 4025, 0, + 2745, 2239, 3121, + 2745, 2239, 3121, + 2743, 2241, 3121, + 2741, 2241, 3121, + 2739, 2245, 3119, + 2737, 2247, 3119, + 2735, 2251, 3117, + 2731, 2257, 3117, + 2725, 2263, 3115, + 2717, 2273, 3111, + 2705, 2283, 3109, + 2691, 2299, 3103, + 2669, 2319, 3097, + 2639, 2343, 3089, + 2597, 2375, 3077, + 2533, 2413, 3061, + 2429, 2461, 3037, + 2241, 2517, 3005, + 1709, 2583, 2957, + 0, 2659, 2885, + 0, 2743, 2765, + 0, 2837, 2531, + 0, 2937, 1482, + 0, 3043, 0, + 0, 3157, 0, + 0, 3273, 0, + 0, 3393, 0, + 0, 3517, 0, + 0, 3641, 0, + 0, 3769, 0, + 0, 3897, 0, + 0, 4025, 0, + 2761, 2235, 3127, + 2761, 2237, 3127, + 2761, 2237, 3125, + 2759, 2239, 3125, + 2757, 2241, 3125, + 2755, 2245, 3125, + 2751, 2249, 3123, + 2747, 2253, 3121, + 2741, 2261, 3119, + 2735, 2269, 3117, + 2723, 2281, 3113, + 2709, 2297, 3109, + 2689, 2317, 3103, + 2661, 2341, 3095, + 2621, 2373, 3083, + 2559, 2413, 3067, + 2463, 2459, 3043, + 2291, 2517, 3011, + 1852, 2583, 2965, + 0, 2657, 2893, + 0, 2743, 2777, + 0, 2835, 2549, + 0, 2937, 1638, + 0, 3043, 0, + 0, 3155, 0, + 0, 3273, 0, + 0, 3393, 0, + 0, 3517, 0, + 0, 3641, 0, + 0, 3769, 0, + 0, 3897, 0, + 0, 4025, 0, + 2783, 2231, 3133, + 2783, 2233, 3133, + 2781, 2235, 3133, + 2781, 2235, 3133, + 2779, 2239, 3131, + 2777, 2241, 3131, + 2773, 2245, 3129, + 2769, 2251, 3129, + 2765, 2257, 3127, + 2757, 2267, 3123, + 2747, 2279, 3121, + 2733, 2293, 3115, + 2715, 2313, 3109, + 2687, 2339, 3101, + 2649, 2371, 3089, + 2593, 2409, 3073, + 2503, 2457, 3051, + 2349, 2515, 3019, + 1992, 2581, 2973, + 0, 2657, 2905, + 0, 2741, 2791, + 0, 2835, 2573, + 0, 2935, 1786, + 0, 3043, 0, + 0, 3155, 0, + 0, 3273, 0, + 0, 3393, 0, + 0, 3515, 0, + 0, 3641, 0, + 0, 3769, 0, + 0, 3897, 0, + 0, 4025, 0, + 2811, 2227, 3141, + 2811, 2229, 3141, + 2809, 2229, 3141, + 2809, 2231, 3141, + 2807, 2233, 3141, + 2805, 2237, 3139, + 2801, 2241, 3139, + 2797, 2245, 3137, + 2793, 2253, 3135, + 2787, 2261, 3133, + 2777, 2273, 3129, + 2763, 2289, 3125, + 2747, 2309, 3119, + 2721, 2335, 3111, + 2687, 2367, 3099, + 2633, 2407, 3083, + 2553, 2455, 3061, + 2417, 2511, 3031, + 2129, 2579, 2987, + 0, 2655, 2919, + 0, 2739, 2809, + 0, 2833, 2601, + 0, 2935, 1931, + 0, 3043, 0, + 0, 3155, 0, + 0, 3271, 0, + 0, 3393, 0, + 0, 3515, 0, + 0, 3641, 0, + 0, 3769, 0, + 0, 3897, 0, + 0, 4025, 0, + 2845, 2221, 3153, + 2845, 2221, 3153, + 2843, 2223, 3153, + 2843, 2225, 3153, + 2841, 2227, 3151, + 2839, 2229, 3151, + 2837, 2235, 3149, + 2833, 2239, 3149, + 2829, 2247, 3147, + 2823, 2255, 3145, + 2813, 2267, 3141, + 2801, 2283, 3137, + 2785, 2305, 3131, + 2763, 2329, 3123, + 2731, 2363, 3111, + 2683, 2403, 3097, + 2613, 2451, 3075, + 2495, 2509, 3045, + 2267, 2575, 3003, + 1329, 2653, 2937, + 0, 2737, 2831, + 0, 2831, 2637, + 0, 2933, 2071, + 0, 3041, 0, + 0, 3153, 0, + 0, 3271, 0, + 0, 3391, 0, + 0, 3515, 0, + 0, 3641, 0, + 0, 3767, 0, + 0, 3897, 0, + 0, 4025, 0, + 2887, 2211, 3167, + 2887, 2213, 3167, + 2885, 2215, 3167, + 2885, 2215, 3167, + 2883, 2219, 3167, + 2881, 2221, 3165, + 2879, 2225, 3165, + 2877, 2231, 3163, + 2873, 2239, 3161, + 2867, 2247, 3159, + 2859, 2261, 3157, + 2847, 2277, 3151, + 2833, 2297, 3147, + 2813, 2323, 3139, + 2785, 2355, 3127, + 2743, 2397, 3113, + 2681, 2445, 3093, + 2581, 2503, 3065, + 2401, 2571, 3023, + 1927, 2649, 2961, + 0, 2735, 2861, + 0, 2829, 2683, + 0, 2931, 2211, + 0, 3039, 0, + 0, 3153, 0, + 0, 3271, 0, + 0, 3391, 0, + 0, 3515, 0, + 0, 3641, 0, + 0, 3767, 0, + 0, 3895, 0, + 0, 4025, 0, + 2937, 2199, 3187, + 2937, 2201, 3187, + 2937, 2203, 3187, + 2935, 2203, 3185, + 2935, 2207, 3185, + 2933, 2209, 3185, + 2931, 2213, 3183, + 2929, 2219, 3183, + 2925, 2227, 3181, + 2919, 2237, 3179, + 2913, 2249, 3175, + 2903, 2265, 3171, + 2889, 2287, 3167, + 2873, 2313, 3159, + 2847, 2347, 3149, + 2811, 2389, 3135, + 2757, 2439, 3115, + 2675, 2497, 3087, + 2535, 2565, 3049, + 2237, 2645, 2991, + 0, 2731, 2897, + 0, 2827, 2735, + 0, 2929, 2347, + 0, 3037, 0, + 0, 3151, 0, + 0, 3269, 0, + 0, 3391, 0, + 0, 3515, 0, + 0, 3639, 0, + 0, 3767, 0, + 0, 3895, 0, + 0, 4025, 0, + 2997, 2183, 3211, + 2997, 2185, 3211, + 2997, 2185, 3211, + 2997, 2187, 3211, + 2995, 2189, 3209, + 2993, 2193, 3209, + 2993, 2197, 3209, + 2989, 2203, 3207, + 2987, 2211, 3205, + 2981, 2221, 3203, + 2975, 2235, 3201, + 2967, 2251, 3197, + 2957, 2273, 3191, + 2941, 2301, 3185, + 2919, 2335, 3175, + 2889, 2377, 3161, + 2845, 2429, 3143, + 2777, 2489, 3117, + 2669, 2559, 3081, + 2467, 2637, 3027, + 1839, 2727, 2943, + 0, 2823, 2799, + 0, 2925, 2483, + 0, 3035, 0, + 0, 3149, 0, + 0, 3267, 0, + 0, 3389, 0, + 0, 3513, 0, + 0, 3639, 0, + 0, 3767, 0, + 0, 3895, 0, + 0, 4025, 0, + 3067, 2159, 3241, + 3067, 2161, 3241, + 3067, 2163, 3241, + 3067, 2165, 3241, + 3065, 2167, 3241, + 3065, 2171, 3239, + 3063, 2175, 3239, + 3061, 2181, 3237, + 3057, 2189, 3237, + 3053, 2199, 3235, + 3049, 2213, 3231, + 3041, 2231, 3229, + 3033, 2253, 3223, + 3019, 2283, 3217, + 3001, 2319, 3207, + 2975, 2363, 3195, + 2939, 2415, 3179, + 2887, 2477, 3155, + 2803, 2549, 3121, + 2661, 2629, 3073, + 2357, 2719, 2997, + 0, 2817, 2871, + 0, 2921, 2617, + 0, 3031, 83, + 0, 3147, 0, + 0, 3265, 0, + 0, 3387, 0, + 0, 3511, 0, + 0, 3639, 0, + 0, 3765, 0, + 0, 3895, 0, + 0, 4025, 0, + 3147, 2127, 3279, + 3147, 2127, 3279, + 3147, 2129, 3279, + 3145, 2131, 3279, + 3145, 2135, 3279, + 3143, 2137, 3277, + 3143, 2143, 3277, + 3141, 2149, 3277, + 3139, 2159, 3275, + 3135, 2169, 3273, + 3131, 2185, 3271, + 3125, 2203, 3267, + 3117, 2227, 3263, + 3107, 2257, 3257, + 3091, 2295, 3249, + 3071, 2341, 3237, + 3041, 2397, 3221, + 2999, 2461, 3201, + 2937, 2535, 3171, + 2835, 2617, 3127, + 2651, 2709, 3059, + 2145, 2809, 2953, + 0, 2915, 2751, + 0, 3027, 2137, + 0, 3143, 0, + 0, 3263, 0, + 0, 3385, 0, + 0, 3511, 0, + 0, 3637, 0, + 0, 3765, 0, + 0, 3895, 0, + 0, 4023, 0, + 3235, 2077, 3325, + 3235, 2079, 3325, + 3235, 2081, 3325, + 3233, 2083, 3325, + 3233, 2087, 3325, + 3233, 2091, 3325, + 3231, 2097, 3323, + 3229, 2103, 3323, + 3227, 2113, 3321, + 3225, 2125, 3319, + 3221, 2141, 3317, + 3217, 2163, 3315, + 3211, 2189, 3311, + 3201, 2221, 3305, + 3189, 2263, 3297, + 3173, 2311, 3287, + 3151, 2369, 3273, + 3117, 2437, 3255, + 3069, 2515, 3229, + 2995, 2601, 3189, + 2875, 2697, 3133, + 2635, 2799, 3043, + 1442, 2907, 2885, + 0, 3021, 2519, + 0, 3137, 0, + 0, 3259, 0, + 0, 3383, 0, + 0, 3509, 0, + 0, 3635, 0, + 0, 3763, 0, + 0, 3893, 0, + 0, 4023, 0, + 3331, 2004, 3381, + 3331, 2005, 3381, + 3331, 2007, 3381, + 3331, 2010, 3381, + 3329, 2014, 3381, + 3329, 2019, 3379, + 3329, 2025, 3379, + 3327, 2033, 3379, + 3325, 2045, 3377, + 3323, 2059, 3375, + 3321, 2077, 3373, + 3317, 2101, 3371, + 3311, 2131, 3367, + 3305, 2169, 3363, + 3295, 2215, 3357, + 3281, 2269, 3347, + 3263, 2333, 3335, + 3239, 2405, 3319, + 3201, 2489, 3295, + 3149, 2579, 3263, + 3065, 2679, 3215, + 2923, 2785, 3141, + 2613, 2895, 3019, + 0, 3011, 2777, + 0, 3131, 1508, + 0, 3253, 0, + 0, 3379, 0, + 0, 3505, 0, + 0, 3633, 0, + 0, 3763, 0, + 0, 3891, 0, + 0, 4023, 0, + 3435, 1880, 3445, + 3433, 1882, 3445, + 3433, 1885, 3445, + 3433, 1889, 3445, + 3433, 1894, 3445, + 3433, 1900, 3445, + 3431, 1908, 3443, + 3431, 1919, 3443, + 3429, 1933, 3443, + 3427, 1952, 3441, + 3425, 1975, 3439, + 3423, 2005, 3437, + 3419, 2042, 3435, + 3413, 2087, 3429, + 3405, 2141, 3425, + 3395, 2203, 3417, + 3381, 2277, 3407, + 3361, 2359, 3393, + 3335, 2449, 3373, + 3295, 2549, 3345, + 3237, 2653, 3305, + 3143, 2765, 3245, + 2979, 2881, 3151, + 2583, 2999, 2985, + 0, 3123, 2573, + 0, 3247, 0, + 0, 3373, 0, + 0, 3501, 0, + 0, 3631, 0, + 0, 3759, 0, + 0, 3891, 0, + 0, 4021, 0, + 3543, 1635, 3519, + 3543, 1639, 3519, + 3543, 1644, 3519, + 3543, 1650, 3519, + 3543, 1658, 3519, + 3543, 1668, 3519, + 3541, 1682, 3519, + 3541, 1700, 3517, + 3539, 1723, 3517, + 3539, 1752, 3517, + 3537, 1788, 3515, + 3535, 1832, 3513, + 3531, 1885, 3511, + 3527, 1947, 3507, + 3521, 2019, 3501, + 3513, 2099, 3495, + 3503, 2189, 3487, + 3487, 2287, 3475, + 3467, 2393, 3459, + 3437, 2503, 3435, + 3395, 2617, 3403, + 3331, 2737, 3357, + 3231, 2859, 3285, + 3045, 2983, 3165, + 2539, 3109, 2933, + 0, 3237, 1936, + 0, 3367, 0, + 0, 3495, 0, + 0, 3627, 0, + 0, 3757, 0, + 0, 3887, 0, + 0, 4019, 0, + 3657, 227, 3603, + 3657, 299, 3603, + 3657, 381, 3603, + 3657, 471, 3603, + 3657, 569, 3603, + 3657, 674, 3603, + 3657, 784, 3603, + 3655, 900, 3601, + 3655, 1019, 3601, + 3653, 1141, 3601, + 3653, 1265, 3599, + 3651, 1392, 3597, + 3649, 1520, 3595, + 3645, 1648, 3593, + 3641, 1778, 3589, + 3635, 1908, 3583, + 3625, 2039, 3577, + 3615, 2171, 3567, + 3599, 2301, 3553, + 3577, 2433, 3535, + 3547, 2565, 3509, + 3503, 2697, 3471, + 3435, 2829, 3417, + 3327, 2961, 3331, + 3121, 3093, 3183, + 2471, 3225, 2857, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 3775, 0, 3695, + 3775, 0, 3695, + 3775, 0, 3695, + 3775, 0, 3695, + 3775, 0, 3695, + 3775, 0, 3695, + 3775, 0, 3695, + 3775, 0, 3693, + 3773, 0, 3693, + 3773, 0, 3693, + 3771, 0, 3691, + 3771, 0, 3691, + 3769, 0, 3689, + 3765, 0, 3687, + 3763, 550, 3683, + 3757, 1360, 3679, + 3751, 1700, 3673, + 3743, 1943, 3665, + 3731, 2143, 3655, + 3715, 2319, 3639, + 3693, 2483, 3619, + 3661, 2637, 3591, + 3615, 2785, 3549, + 3545, 2927, 3487, + 3429, 3069, 3387, + 3207, 3207, 3207, + 2363, 3343, 2727, + 0, 3479, 0, + 0, 3613, 0, + 0, 3747, 0, + 0, 3881, 0, + 0, 4013, 0, + 3897, 0, 3795, + 3897, 0, 3795, + 3897, 0, 3795, + 3897, 0, 3795, + 3897, 0, 3795, + 3897, 0, 3795, + 3897, 0, 3795, + 3897, 0, 3793, + 3895, 0, 3793, + 3895, 0, 3793, + 3895, 0, 3793, + 3893, 0, 3791, + 3891, 0, 3789, + 3889, 0, 3787, + 3887, 0, 3785, + 3883, 0, 3781, + 3879, 0, 3777, + 3873, 1021, 3771, + 3863, 1770, 3763, + 3851, 2103, 3751, + 3835, 2343, 3735, + 3813, 2541, 3713, + 3779, 2717, 3681, + 3731, 2881, 3635, + 3659, 3033, 3567, + 3537, 3181, 3453, + 3299, 3325, 3235, + 2161, 3465, 2461, + 0, 3603, 0, + 0, 3739, 0, + 0, 3875, 0, + 0, 4009, 0, + 4021, 0, 3901, + 4021, 0, 3901, + 4021, 0, 3901, + 4021, 0, 3901, + 4021, 0, 3901, + 4021, 0, 3901, + 4021, 0, 3901, + 4021, 0, 3901, + 4019, 0, 3899, + 4019, 0, 3899, + 4019, 0, 3899, + 4019, 0, 3899, + 4017, 0, 3897, + 4015, 0, 3895, + 4013, 0, 3893, + 4011, 0, 3891, + 4007, 0, 3887, + 4003, 0, 3883, + 3995, 0, 3875, + 3987, 1333, 3867, + 3975, 2044, 3855, + 3957, 2373, 3837, + 3935, 2609, 3813, + 3901, 2807, 3779, + 3851, 2983, 3731, + 3777, 3145, 3655, + 3651, 3299, 3527, + 3401, 3445, 3271, + 1527, 3589, 0, + 0, 3729, 0, + 0, 3867, 0, + 0, 4005, 0, + 4095, 0, 4013, + 4095, 0, 4013, + 4095, 0, 4013, + 4095, 0, 4013, + 4095, 0, 4013, + 4095, 0, 4013, + 4095, 0, 4013, + 4095, 0, 4013, + 4095, 0, 4011, + 4095, 0, 4011, + 4095, 0, 4011, + 4095, 0, 4011, + 4095, 0, 4009, + 4095, 0, 4009, + 4095, 0, 4007, + 4095, 0, 4005, + 4095, 0, 4003, + 4095, 0, 3999, + 4095, 0, 3993, + 4095, 0, 3987, + 4095, 0, 3977, + 4095, 1951, 3963, + 4083, 2409, 3947, + 4059, 2687, 3921, + 4025, 2905, 3885, + 3975, 3093, 3833, + 3897, 3261, 3751, + 3769, 3419, 3611, + 3509, 3569, 3317, + 0, 3715, 0, + 0, 3857, 0, + 0, 3997, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4091, + 4095, 1786, 4079, + 4095, 2453, 4059, + 4095, 2775, 4033, + 4095, 3009, 3997, + 4095, 3207, 3941, + 4021, 3381, 3855, + 3891, 3543, 3705, + 3621, 3695, 3369, + 0, 3843, 0, + 0, 3985, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 1387, 4095, + 4095, 2507, 4095, + 4095, 2869, 4095, + 4095, 3121, 4095, + 4095, 3325, 4055, + 4095, 3503, 3963, + 4015, 3669, 3805, + 3737, 3823, 3433, + 0, 3971, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2569, 4095, + 4095, 2971, 4095, + 4095, 3235, 4095, + 4095, 3445, 4095, + 4095, 3629, 4077, + 4095, 3795, 3911, + 3859, 3951, 3505, + 2825, 2377, 3239, + 2825, 2377, 3239, + 2825, 2379, 3239, + 2823, 2379, 3239, + 2821, 2381, 3237, + 2819, 2383, 3237, + 2817, 2387, 3237, + 2813, 2391, 3235, + 2809, 2395, 3233, + 2803, 2403, 3231, + 2793, 2411, 3229, + 2781, 2423, 3225, + 2763, 2437, 3221, + 2739, 2457, 3215, + 2705, 2481, 3205, + 2657, 2513, 3193, + 2579, 2551, 3175, + 2453, 2597, 3153, + 2193, 2653, 3119, + 0, 2719, 3069, + 0, 2793, 2993, + 0, 2879, 2865, + 0, 2971, 2607, + 0, 3071, 0, + 0, 3177, 0, + 0, 3289, 0, + 0, 3405, 0, + 0, 3525, 0, + 0, 3649, 0, + 0, 3775, 0, + 0, 3901, 0, + 0, 4029, 0, + 2827, 2377, 3239, + 2827, 2377, 3239, + 2825, 2379, 3239, + 2825, 2379, 3239, + 2823, 2381, 3239, + 2821, 2383, 3237, + 2817, 2387, 3237, + 2815, 2391, 3235, + 2809, 2395, 3235, + 2803, 2403, 3233, + 2793, 2411, 3229, + 2781, 2423, 3225, + 2765, 2437, 3221, + 2741, 2457, 3215, + 2707, 2481, 3205, + 2657, 2513, 3193, + 2581, 2551, 3177, + 2453, 2597, 3153, + 2197, 2653, 3119, + 0, 2719, 3069, + 0, 2793, 2993, + 0, 2877, 2865, + 0, 2971, 2609, + 0, 3071, 0, + 0, 3177, 0, + 0, 3289, 0, + 0, 3405, 0, + 0, 3525, 0, + 0, 3649, 0, + 0, 3775, 0, + 0, 3901, 0, + 0, 4029, 0, + 2827, 2377, 3239, + 2827, 2377, 3239, + 2827, 2379, 3239, + 2825, 2379, 3239, + 2823, 2381, 3239, + 2821, 2383, 3237, + 2819, 2387, 3237, + 2815, 2391, 3235, + 2811, 2395, 3235, + 2803, 2401, 3233, + 2795, 2411, 3229, + 2783, 2423, 3227, + 2765, 2437, 3221, + 2743, 2457, 3215, + 2709, 2481, 3205, + 2659, 2513, 3193, + 2583, 2551, 3177, + 2457, 2597, 3153, + 2201, 2653, 3119, + 0, 2719, 3069, + 0, 2793, 2993, + 0, 2877, 2867, + 0, 2971, 2609, + 0, 3071, 0, + 0, 3177, 0, + 0, 3289, 0, + 0, 3405, 0, + 0, 3525, 0, + 0, 3649, 0, + 0, 3775, 0, + 0, 3901, 0, + 0, 4029, 0, + 2829, 2377, 3241, + 2829, 2377, 3239, + 2827, 2379, 3239, + 2827, 2379, 3239, + 2825, 2381, 3239, + 2823, 2383, 3239, + 2821, 2387, 3237, + 2817, 2389, 3237, + 2811, 2395, 3235, + 2805, 2401, 3233, + 2797, 2411, 3231, + 2785, 2423, 3227, + 2767, 2437, 3221, + 2743, 2457, 3215, + 2711, 2481, 3207, + 2661, 2513, 3193, + 2585, 2551, 3177, + 2459, 2597, 3153, + 2207, 2653, 3119, + 0, 2719, 3069, + 0, 2793, 2993, + 0, 2877, 2867, + 0, 2971, 2611, + 0, 3071, 0, + 0, 3177, 0, + 0, 3289, 0, + 0, 3405, 0, + 0, 3525, 0, + 0, 3649, 0, + 0, 3775, 0, + 0, 3901, 0, + 0, 4029, 0, + 2831, 2377, 3241, + 2831, 2377, 3241, + 2829, 2377, 3241, + 2829, 2379, 3239, + 2827, 2381, 3239, + 2825, 2383, 3239, + 2823, 2385, 3237, + 2819, 2389, 3237, + 2813, 2395, 3235, + 2807, 2401, 3233, + 2799, 2411, 3231, + 2787, 2421, 3227, + 2769, 2437, 3223, + 2745, 2457, 3215, + 2713, 2481, 3207, + 2663, 2513, 3195, + 2589, 2551, 3177, + 2463, 2597, 3153, + 2213, 2653, 3119, + 465, 2719, 3071, + 0, 2793, 2995, + 0, 2877, 2869, + 0, 2971, 2613, + 0, 3071, 0, + 0, 3177, 0, + 0, 3289, 0, + 0, 3405, 0, + 0, 3525, 0, + 0, 3649, 0, + 0, 3775, 0, + 0, 3901, 0, + 0, 4029, 0, + 2833, 2375, 3241, + 2833, 2377, 3241, + 2833, 2377, 3241, + 2831, 2379, 3241, + 2829, 2381, 3241, + 2827, 2383, 3239, + 2825, 2385, 3239, + 2821, 2389, 3237, + 2817, 2395, 3237, + 2809, 2401, 3235, + 2801, 2411, 3231, + 2789, 2421, 3227, + 2773, 2437, 3223, + 2749, 2457, 3217, + 2715, 2481, 3207, + 2667, 2511, 3195, + 2593, 2551, 3179, + 2469, 2597, 3155, + 2223, 2653, 3121, + 779, 2719, 3071, + 0, 2793, 2995, + 0, 2877, 2869, + 0, 2971, 2615, + 0, 3071, 0, + 0, 3177, 0, + 0, 3289, 0, + 0, 3405, 0, + 0, 3525, 0, + 0, 3649, 0, + 0, 3773, 0, + 0, 3901, 0, + 0, 4029, 0, + 2837, 2375, 3243, + 2837, 2377, 3243, + 2835, 2377, 3241, + 2835, 2379, 3241, + 2833, 2379, 3241, + 2831, 2383, 3241, + 2829, 2385, 3239, + 2825, 2389, 3239, + 2819, 2395, 3237, + 2813, 2401, 3235, + 2805, 2409, 3233, + 2793, 2421, 3229, + 2777, 2437, 3223, + 2753, 2455, 3217, + 2719, 2481, 3209, + 2671, 2511, 3197, + 2599, 2551, 3179, + 2477, 2597, 3155, + 2237, 2653, 3123, + 1012, 2719, 3073, + 0, 2793, 2997, + 0, 2877, 2871, + 0, 2971, 2619, + 0, 3071, 435, + 0, 3177, 0, + 0, 3289, 0, + 0, 3405, 0, + 0, 3525, 0, + 0, 3649, 0, + 0, 3773, 0, + 0, 3901, 0, + 0, 4029, 0, + 2841, 2375, 3243, + 2841, 2375, 3243, + 2839, 2377, 3243, + 2839, 2377, 3243, + 2837, 2379, 3243, + 2835, 2381, 3241, + 2833, 2385, 3241, + 2829, 2389, 3239, + 2825, 2393, 3239, + 2819, 2401, 3237, + 2809, 2409, 3233, + 2797, 2421, 3229, + 2781, 2435, 3225, + 2759, 2455, 3219, + 2725, 2479, 3209, + 2679, 2511, 3197, + 2605, 2549, 3181, + 2487, 2597, 3157, + 2253, 2653, 3123, + 1206, 2719, 3075, + 0, 2793, 2999, + 0, 2877, 2875, + 0, 2971, 2625, + 0, 3071, 809, + 0, 3177, 0, + 0, 3289, 0, + 0, 3405, 0, + 0, 3525, 0, + 0, 3649, 0, + 0, 3773, 0, + 0, 3901, 0, + 0, 4029, 0, + 2847, 2375, 3245, + 2847, 2375, 3245, + 2845, 2375, 3245, + 2845, 2377, 3245, + 2843, 2379, 3243, + 2841, 2381, 3243, + 2839, 2383, 3243, + 2835, 2387, 3241, + 2831, 2393, 3239, + 2825, 2399, 3237, + 2815, 2409, 3235, + 2803, 2419, 3231, + 2787, 2435, 3227, + 2765, 2455, 3221, + 2733, 2479, 3211, + 2687, 2511, 3199, + 2615, 2549, 3183, + 2499, 2597, 3159, + 2273, 2653, 3125, + 1380, 2717, 3077, + 0, 2793, 3003, + 0, 2877, 2877, + 0, 2969, 2631, + 0, 3071, 1063, + 0, 3177, 0, + 0, 3289, 0, + 0, 3405, 0, + 0, 3525, 0, + 0, 3649, 0, + 0, 3773, 0, + 0, 3901, 0, + 0, 4029, 0, + 2855, 2373, 3247, + 2853, 2373, 3247, + 2853, 2375, 3247, + 2853, 2375, 3247, + 2851, 2377, 3245, + 2849, 2379, 3245, + 2847, 2383, 3245, + 2843, 2387, 3243, + 2839, 2391, 3241, + 2833, 2399, 3239, + 2823, 2407, 3237, + 2813, 2419, 3233, + 2797, 2435, 3229, + 2775, 2453, 3223, + 2743, 2479, 3213, + 2697, 2509, 3201, + 2627, 2549, 3185, + 2515, 2595, 3161, + 2299, 2651, 3129, + 1541, 2717, 3079, + 0, 2793, 3005, + 0, 2877, 2883, + 0, 2969, 2639, + 0, 3069, 1269, + 0, 3177, 0, + 0, 3289, 0, + 0, 3405, 0, + 0, 3525, 0, + 0, 3649, 0, + 0, 3773, 0, + 0, 3901, 0, + 0, 4029, 0, + 2865, 2371, 3249, + 2863, 2373, 3249, + 2863, 2373, 3249, + 2863, 2375, 3249, + 2861, 2377, 3249, + 2859, 2379, 3249, + 2857, 2381, 3247, + 2853, 2385, 3247, + 2849, 2391, 3245, + 2843, 2397, 3243, + 2835, 2405, 3241, + 2823, 2417, 3237, + 2807, 2433, 3231, + 2787, 2453, 3225, + 2755, 2477, 3217, + 2711, 2509, 3205, + 2645, 2547, 3189, + 2535, 2595, 3165, + 2333, 2651, 3133, + 1694, 2717, 3085, + 0, 2791, 3011, + 0, 2877, 2889, + 0, 2969, 2649, + 0, 3069, 1449, + 0, 3177, 0, + 0, 3289, 0, + 0, 3405, 0, + 0, 3525, 0, + 0, 3649, 0, + 0, 3773, 0, + 0, 3901, 0, + 0, 4029, 0, + 2877, 2369, 3253, + 2877, 2371, 3253, + 2877, 2371, 3253, + 2875, 2373, 3253, + 2873, 2375, 3253, + 2873, 2377, 3251, + 2869, 2379, 3251, + 2867, 2383, 3251, + 2863, 2389, 3249, + 2857, 2395, 3247, + 2849, 2405, 3245, + 2837, 2415, 3241, + 2823, 2431, 3235, + 2801, 2451, 3229, + 2773, 2475, 3221, + 2729, 2507, 3209, + 2665, 2547, 3193, + 2563, 2593, 3169, + 2373, 2649, 3137, + 1841, 2715, 3089, + 0, 2791, 3017, + 0, 2875, 2897, + 0, 2969, 2663, + 0, 3069, 1614, + 0, 3177, 0, + 0, 3289, 0, + 0, 3405, 0, + 0, 3525, 0, + 0, 3649, 0, + 0, 3773, 0, + 0, 3901, 0, + 0, 4029, 0, + 2895, 2367, 3259, + 2893, 2367, 3259, + 2893, 2369, 3259, + 2893, 2369, 3259, + 2891, 2371, 3257, + 2889, 2373, 3257, + 2887, 2377, 3257, + 2883, 2381, 3255, + 2879, 2385, 3253, + 2873, 2393, 3251, + 2867, 2401, 3249, + 2855, 2413, 3245, + 2841, 2429, 3241, + 2821, 2449, 3235, + 2793, 2473, 3227, + 2753, 2505, 3215, + 2691, 2545, 3199, + 2595, 2591, 3175, + 2423, 2649, 3143, + 1984, 2715, 3097, + 0, 2789, 3025, + 0, 2875, 2909, + 0, 2967, 2681, + 0, 3069, 1770, + 0, 3175, 0, + 0, 3289, 0, + 0, 3405, 0, + 0, 3525, 0, + 0, 3649, 0, + 0, 3773, 0, + 0, 3901, 0, + 0, 4029, 0, + 2915, 2363, 3265, + 2915, 2365, 3265, + 2915, 2365, 3265, + 2913, 2367, 3265, + 2913, 2367, 3265, + 2911, 2371, 3263, + 2909, 2373, 3263, + 2905, 2377, 3261, + 2901, 2383, 3261, + 2897, 2389, 3259, + 2889, 2399, 3255, + 2879, 2411, 3253, + 2865, 2425, 3247, + 2847, 2445, 3241, + 2819, 2471, 3233, + 2781, 2503, 3221, + 2725, 2541, 3205, + 2637, 2589, 3183, + 2481, 2647, 3151, + 2123, 2713, 3107, + 0, 2789, 3037, + 0, 2873, 2923, + 0, 2967, 2705, + 0, 3067, 1919, + 0, 3175, 0, + 0, 3287, 0, + 0, 3405, 0, + 0, 3525, 0, + 0, 3649, 0, + 0, 3773, 0, + 0, 3901, 0, + 0, 4029, 0, + 2943, 2359, 3275, + 2943, 2359, 3273, + 2943, 2361, 3273, + 2941, 2361, 3273, + 2941, 2363, 3273, + 2939, 2365, 3273, + 2937, 2369, 3271, + 2933, 2373, 3271, + 2931, 2377, 3269, + 2925, 2385, 3267, + 2919, 2393, 3265, + 2909, 2405, 3261, + 2897, 2421, 3257, + 2879, 2441, 3251, + 2853, 2467, 3243, + 2819, 2499, 3231, + 2767, 2539, 3215, + 2685, 2587, 3193, + 2549, 2643, 3163, + 2261, 2711, 3119, + 0, 2787, 3051, + 0, 2871, 2941, + 0, 2965, 2733, + 0, 3067, 2063, + 0, 3175, 0, + 0, 3287, 0, + 0, 3405, 0, + 0, 3525, 0, + 0, 3647, 0, + 0, 3773, 0, + 0, 3901, 0, + 0, 4029, 0, + 2977, 2353, 3285, + 2977, 2353, 3285, + 2977, 2353, 3285, + 2975, 2355, 3285, + 2975, 2357, 3285, + 2973, 2359, 3283, + 2971, 2363, 3283, + 2969, 2367, 3281, + 2965, 2371, 3281, + 2961, 2379, 3279, + 2955, 2387, 3277, + 2945, 2401, 3273, + 2933, 2415, 3269, + 2917, 2437, 3263, + 2895, 2461, 3255, + 2863, 2495, 3243, + 2815, 2535, 3229, + 2745, 2583, 3207, + 2627, 2641, 3177, + 2399, 2707, 3135, + 1461, 2785, 3069, + 0, 2869, 2965, + 0, 2963, 2769, + 0, 3065, 2203, + 0, 3173, 0, + 0, 3287, 0, + 0, 3403, 0, + 0, 3525, 0, + 0, 3647, 0, + 0, 3773, 0, + 0, 3901, 0, + 0, 4029, 0, + 3019, 2343, 3301, + 3019, 2343, 3299, + 3019, 2345, 3299, + 3017, 2347, 3299, + 3017, 2347, 3299, + 3015, 2351, 3299, + 3013, 2353, 3297, + 3011, 2357, 3297, + 3009, 2363, 3295, + 3005, 2371, 3293, + 2999, 2379, 3291, + 2991, 2393, 3289, + 2979, 2409, 3285, + 2965, 2429, 3279, + 2945, 2455, 3271, + 2917, 2487, 3259, + 2875, 2529, 3245, + 2813, 2577, 3225, + 2713, 2635, 3197, + 2533, 2703, 3155, + 2059, 2781, 3093, + 0, 2867, 2993, + 0, 2961, 2815, + 0, 3063, 2343, + 0, 3171, 0, + 0, 3285, 0, + 0, 3403, 0, + 0, 3523, 0, + 0, 3647, 0, + 0, 3773, 0, + 0, 3899, 0, + 0, 4029, 0, + 3071, 2331, 3319, + 3069, 2331, 3319, + 3069, 2333, 3319, + 3069, 2335, 3319, + 3067, 2335, 3319, + 3067, 2339, 3317, + 3065, 2341, 3317, + 3063, 2345, 3315, + 3061, 2351, 3315, + 3057, 2359, 3313, + 3051, 2369, 3311, + 3045, 2381, 3307, + 3035, 2397, 3303, + 3023, 2419, 3299, + 3005, 2445, 3291, + 2979, 2479, 3281, + 2943, 2521, 3267, + 2891, 2571, 3247, + 2807, 2629, 3219, + 2667, 2699, 3181, + 2369, 2777, 3123, + 0, 2863, 3031, + 0, 2959, 2867, + 0, 3061, 2479, + 0, 3169, 0, + 0, 3283, 0, + 0, 3401, 0, + 0, 3523, 0, + 0, 3647, 0, + 0, 3773, 0, + 0, 3899, 0, + 0, 4027, 0, + 3131, 2315, 3343, + 3131, 2315, 3343, + 3129, 2317, 3343, + 3129, 2317, 3343, + 3129, 2319, 3343, + 3127, 2321, 3341, + 3125, 2325, 3341, + 3125, 2329, 3341, + 3121, 2335, 3339, + 3119, 2343, 3337, + 3113, 2353, 3335, + 3107, 2367, 3333, + 3099, 2383, 3329, + 3089, 2405, 3323, + 3073, 2433, 3317, + 3051, 2467, 3307, + 3021, 2509, 3293, + 2977, 2561, 3275, + 2909, 2621, 3249, + 2801, 2691, 3213, + 2599, 2769, 3159, + 1971, 2859, 3075, + 0, 2955, 2931, + 0, 3057, 2615, + 0, 3167, 0, + 0, 3281, 0, + 0, 3399, 0, + 0, 3521, 0, + 0, 3645, 0, + 0, 3771, 0, + 0, 3899, 0, + 0, 4027, 0, + 3201, 2291, 3373, + 3199, 2291, 3373, + 3199, 2293, 3373, + 3199, 2295, 3373, + 3199, 2297, 3373, + 3197, 2299, 3373, + 3197, 2303, 3371, + 3195, 2307, 3371, + 3193, 2313, 3371, + 3189, 2321, 3369, + 3185, 2331, 3367, + 3181, 2345, 3363, + 3173, 2363, 3361, + 3165, 2387, 3355, + 3151, 2415, 3349, + 3133, 2451, 3339, + 3107, 2495, 3327, + 3071, 2547, 3311, + 3019, 2609, 3287, + 2935, 2681, 3253, + 2793, 2761, 3205, + 2489, 2851, 3129, + 0, 2949, 3003, + 0, 3053, 2749, + 0, 3163, 215, + 0, 3279, 0, + 0, 3397, 0, + 0, 3519, 0, + 0, 3645, 0, + 0, 3771, 0, + 0, 3899, 0, + 0, 4027, 0, + 3279, 2257, 3411, + 3279, 2259, 3411, + 3279, 2259, 3411, + 3279, 2261, 3411, + 3277, 2263, 3411, + 3277, 2267, 3411, + 3275, 2271, 3409, + 3275, 2275, 3409, + 3273, 2281, 3409, + 3271, 2291, 3407, + 3267, 2301, 3405, + 3263, 2317, 3403, + 3257, 2335, 3399, + 3249, 2359, 3395, + 3239, 2389, 3389, + 3223, 2427, 3381, + 3203, 2473, 3369, + 3173, 2529, 3355, + 3131, 2593, 3333, + 3069, 2667, 3303, + 2967, 2749, 3259, + 2783, 2841, 3191, + 2277, 2941, 3085, + 0, 3047, 2883, + 0, 3159, 2269, + 0, 3275, 0, + 0, 3395, 0, + 0, 3517, 0, + 0, 3643, 0, + 0, 3769, 0, + 0, 3897, 0, + 0, 4027, 0, + 3367, 2209, 3457, + 3367, 2209, 3457, + 3367, 2211, 3457, + 3367, 2213, 3457, + 3365, 2215, 3457, + 3365, 2219, 3457, + 3365, 2223, 3457, + 3363, 2229, 3455, + 3361, 2235, 3455, + 3361, 2245, 3453, + 3357, 2257, 3451, + 3353, 2273, 3449, + 3349, 2295, 3447, + 3343, 2321, 3443, + 3333, 2353, 3437, + 3321, 2395, 3429, + 3305, 2443, 3419, + 3283, 2503, 3407, + 3249, 2571, 3387, + 3201, 2647, 3361, + 3127, 2735, 3321, + 3007, 2829, 3265, + 2767, 2931, 3175, + 1574, 3039, 3017, + 0, 3153, 2651, + 0, 3271, 0, + 0, 3391, 0, + 0, 3515, 0, + 0, 3641, 0, + 0, 3767, 0, + 0, 3895, 0, + 0, 4025, 0, + 3463, 2135, 3513, + 3463, 2135, 3513, + 3463, 2137, 3513, + 3463, 2139, 3513, + 3463, 2143, 3513, + 3461, 2145, 3513, + 3461, 2151, 3511, + 3461, 2157, 3511, + 3459, 2165, 3511, + 3457, 2177, 3509, + 3455, 2191, 3507, + 3453, 2209, 3505, + 3449, 2233, 3503, + 3443, 2263, 3499, + 3437, 2301, 3495, + 3427, 2347, 3489, + 3413, 2401, 3479, + 3395, 2465, 3467, + 3371, 2537, 3451, + 3333, 2621, 3427, + 3281, 2711, 3395, + 3197, 2811, 3347, + 3055, 2917, 3273, + 2745, 3027, 3151, + 0, 3143, 2909, + 0, 3263, 1640, + 0, 3385, 0, + 0, 3511, 0, + 0, 3637, 0, + 0, 3765, 0, + 0, 3895, 0, + 0, 4023, 0, + 3567, 2011, 3577, + 3567, 2012, 3577, + 3567, 2014, 3577, + 3565, 2017, 3577, + 3565, 2021, 3577, + 3565, 2026, 3577, + 3565, 2032, 3577, + 3563, 2040, 3577, + 3563, 2051, 3575, + 3561, 2065, 3575, + 3561, 2083, 3573, + 3557, 2107, 3571, + 3555, 2137, 3569, + 3551, 2173, 3567, + 3545, 2219, 3563, + 3537, 2273, 3557, + 3527, 2335, 3549, + 3513, 2409, 3539, + 3493, 2491, 3525, + 3467, 2581, 3505, + 3427, 2681, 3477, + 3369, 2785, 3437, + 3275, 2897, 3377, + 3111, 3013, 3283, + 2715, 3131, 3117, + 0, 3255, 2705, + 0, 3379, 0, + 0, 3505, 0, + 0, 3633, 0, + 0, 3763, 0, + 0, 3891, 0, + 0, 4023, 0, + 3675, 1765, 3653, + 3675, 1767, 3653, + 3675, 1771, 3651, + 3675, 1776, 3651, + 3675, 1782, 3651, + 3675, 1790, 3651, + 3675, 1801, 3651, + 3673, 1814, 3651, + 3673, 1832, 3651, + 3671, 1855, 3649, + 3671, 1884, 3649, + 3669, 1920, 3647, + 3667, 1964, 3645, + 3663, 2017, 3643, + 3659, 2079, 3639, + 3653, 2151, 3633, + 3645, 2231, 3627, + 3635, 2321, 3619, + 3619, 2419, 3607, + 3599, 2525, 3591, + 3569, 2635, 3567, + 3527, 2749, 3535, + 3465, 2869, 3489, + 3363, 2991, 3417, + 3177, 3115, 3297, + 2671, 3241, 3065, + 0, 3369, 2069, + 0, 3499, 0, + 0, 3627, 0, + 0, 3759, 0, + 0, 3889, 0, + 0, 4021, 0, + 3789, 297, 3735, + 3789, 359, 3735, + 3789, 432, 3735, + 3789, 513, 3735, + 3789, 603, 3735, + 3789, 701, 3735, + 3789, 806, 3735, + 3789, 917, 3735, + 3787, 1032, 3733, + 3787, 1151, 3733, + 3785, 1273, 3733, + 3785, 1398, 3731, + 3783, 1524, 3729, + 3781, 1652, 3727, + 3777, 1781, 3725, + 3773, 1910, 3721, + 3767, 2040, 3715, + 3759, 2171, 3709, + 3747, 2303, 3699, + 3731, 2433, 3685, + 3709, 2565, 3667, + 3679, 2697, 3641, + 3635, 2829, 3603, + 3567, 2961, 3549, + 3459, 3093, 3463, + 3253, 3225, 3315, + 2603, 3357, 2989, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 3907, 0, 3827, + 3907, 0, 3827, + 3907, 0, 3827, + 3907, 0, 3827, + 3907, 0, 3827, + 3907, 0, 3827, + 3907, 0, 3827, + 3907, 0, 3827, + 3907, 0, 3827, + 3905, 0, 3825, + 3905, 0, 3825, + 3903, 0, 3823, + 3903, 0, 3823, + 3901, 0, 3821, + 3899, 0, 3819, + 3895, 682, 3815, + 3891, 1493, 3811, + 3883, 1832, 3805, + 3875, 2075, 3797, + 3863, 2275, 3787, + 3847, 2451, 3773, + 3825, 2615, 3751, + 3793, 2769, 3723, + 3747, 2917, 3681, + 3677, 3059, 3619, + 3561, 3201, 3519, + 3339, 3339, 3339, + 2495, 3475, 2859, + 0, 3611, 0, + 0, 3745, 0, + 0, 3879, 0, + 0, 4013, 0, + 4029, 0, 3927, + 4029, 0, 3927, + 4029, 0, 3927, + 4029, 0, 3927, + 4029, 0, 3927, + 4029, 0, 3927, + 4029, 0, 3927, + 4029, 0, 3927, + 4029, 0, 3927, + 4027, 0, 3925, + 4027, 0, 3925, + 4027, 0, 3925, + 4025, 0, 3923, + 4023, 0, 3921, + 4021, 0, 3919, + 4019, 0, 3917, + 4015, 0, 3913, + 4011, 0, 3909, + 4005, 1152, 3903, + 3995, 1902, 3895, + 3983, 2235, 3883, + 3967, 2475, 3867, + 3945, 2673, 3845, + 3911, 2849, 3813, + 3863, 3013, 3767, + 3791, 3165, 3699, + 3669, 3313, 3585, + 3433, 3457, 3367, + 2293, 3597, 2593, + 0, 3735, 0, + 0, 3871, 0, + 0, 4007, 0, + 4095, 0, 4033, + 4095, 0, 4033, + 4095, 0, 4033, + 4095, 0, 4033, + 4095, 0, 4033, + 4095, 0, 4033, + 4095, 0, 4033, + 4095, 0, 4033, + 4095, 0, 4033, + 4095, 0, 4033, + 4095, 0, 4031, + 4095, 0, 4031, + 4095, 0, 4031, + 4095, 0, 4029, + 4095, 0, 4027, + 4095, 0, 4025, + 4095, 0, 4023, + 4095, 0, 4019, + 4095, 0, 4015, + 4095, 0, 4007, + 4095, 1465, 3999, + 4095, 2177, 3987, + 4091, 2505, 3969, + 4067, 2741, 3945, + 4033, 2939, 3913, + 3983, 3115, 3863, + 3909, 3277, 3787, + 3783, 3431, 3659, + 3533, 3579, 3405, + 1659, 3721, 0, + 0, 3861, 0, + 0, 3999, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2083, 4095, + 4095, 2541, 4079, + 4095, 2819, 4053, + 4095, 3037, 4017, + 4095, 3225, 3965, + 4031, 3393, 3883, + 3901, 3551, 3743, + 3641, 3703, 3449, + 0, 3847, 0, + 0, 3989, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 1918, 4095, + 4095, 2585, 4095, + 4095, 2907, 4095, + 4095, 3141, 4095, + 4095, 3339, 4073, + 4095, 3513, 3987, + 4023, 3675, 3837, + 3753, 3827, 3501, + 0, 3975, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 1519, 4095, + 4095, 2639, 4095, + 4095, 3001, 4095, + 4095, 3253, 4095, + 4095, 3457, 4095, + 4095, 3635, 4095, + 4095, 3801, 3937, + 3869, 3955, 3565, + 2957, 2509, 3371, + 2957, 2509, 3371, + 2957, 2509, 3371, + 2955, 2511, 3371, + 2955, 2513, 3371, + 2953, 2513, 3369, + 2951, 2515, 3369, + 2949, 2519, 3369, + 2945, 2523, 3367, + 2941, 2527, 3365, + 2933, 2535, 3363, + 2925, 2543, 3361, + 2913, 2555, 3357, + 2895, 2569, 3353, + 2871, 2589, 3347, + 2837, 2613, 3337, + 2787, 2645, 3325, + 2711, 2683, 3307, + 2583, 2731, 3283, + 2323, 2785, 3251, + 0, 2851, 3201, + 0, 2927, 3125, + 0, 3011, 2997, + 0, 3103, 2739, + 0, 3203, 0, + 0, 3309, 0, + 0, 3421, 0, + 0, 3539, 0, + 0, 3659, 0, + 0, 3781, 0, + 0, 3907, 0, + 0, 4033, 0, + 2959, 2509, 3371, + 2959, 2509, 3371, + 2957, 2509, 3371, + 2957, 2511, 3371, + 2955, 2511, 3371, + 2953, 2513, 3371, + 2951, 2515, 3369, + 2949, 2519, 3369, + 2945, 2523, 3367, + 2941, 2527, 3367, + 2935, 2535, 3365, + 2925, 2543, 3361, + 2913, 2555, 3357, + 2895, 2569, 3353, + 2871, 2589, 3347, + 2839, 2613, 3337, + 2789, 2645, 3325, + 2711, 2683, 3307, + 2585, 2729, 3285, + 2327, 2785, 3251, + 0, 2851, 3201, + 0, 2927, 3125, + 0, 3011, 2997, + 0, 3103, 2739, + 0, 3203, 0, + 0, 3309, 0, + 0, 3421, 0, + 0, 3539, 0, + 0, 3659, 0, + 0, 3781, 0, + 0, 3907, 0, + 0, 4033, 0, + 2959, 2509, 3371, + 2959, 2509, 3371, + 2959, 2509, 3371, + 2957, 2511, 3371, + 2957, 2511, 3371, + 2955, 2513, 3371, + 2953, 2515, 3369, + 2951, 2519, 3369, + 2947, 2523, 3367, + 2941, 2527, 3367, + 2935, 2535, 3365, + 2925, 2543, 3361, + 2913, 2555, 3357, + 2897, 2569, 3353, + 2873, 2589, 3347, + 2839, 2613, 3337, + 2789, 2645, 3325, + 2713, 2683, 3309, + 2587, 2729, 3285, + 2329, 2785, 3251, + 0, 2851, 3201, + 0, 2927, 3125, + 0, 3011, 2997, + 0, 3103, 2741, + 0, 3203, 0, + 0, 3309, 0, + 0, 3421, 0, + 0, 3539, 0, + 0, 3659, 0, + 0, 3781, 0, + 0, 3907, 0, + 0, 4033, 0, + 2961, 2509, 3373, + 2959, 2509, 3371, + 2959, 2509, 3371, + 2959, 2511, 3371, + 2957, 2511, 3371, + 2955, 2513, 3371, + 2953, 2515, 3369, + 2951, 2519, 3369, + 2947, 2523, 3369, + 2943, 2527, 3367, + 2937, 2535, 3365, + 2927, 2543, 3361, + 2915, 2555, 3359, + 2897, 2569, 3353, + 2875, 2589, 3347, + 2841, 2613, 3337, + 2791, 2645, 3325, + 2715, 2683, 3309, + 2589, 2729, 3285, + 2333, 2785, 3251, + 0, 2851, 3201, + 0, 2925, 3125, + 0, 3011, 2999, + 0, 3103, 2741, + 0, 3203, 0, + 0, 3309, 0, + 0, 3421, 0, + 0, 3537, 0, + 0, 3659, 0, + 0, 3781, 0, + 0, 3907, 0, + 0, 4033, 0, + 2961, 2509, 3373, + 2961, 2509, 3373, + 2961, 2509, 3373, + 2959, 2511, 3371, + 2959, 2511, 3371, + 2957, 2513, 3371, + 2955, 2515, 3371, + 2953, 2519, 3369, + 2949, 2523, 3369, + 2945, 2527, 3367, + 2937, 2533, 3365, + 2929, 2543, 3363, + 2917, 2555, 3359, + 2899, 2569, 3353, + 2875, 2589, 3347, + 2843, 2613, 3339, + 2793, 2645, 3325, + 2717, 2683, 3309, + 2591, 2729, 3285, + 2339, 2785, 3251, + 0, 2851, 3201, + 0, 2925, 3125, + 0, 3011, 2999, + 0, 3103, 2743, + 0, 3203, 0, + 0, 3309, 0, + 0, 3421, 0, + 0, 3537, 0, + 0, 3659, 0, + 0, 3781, 0, + 0, 3907, 0, + 0, 4033, 0, + 2963, 2507, 3373, + 2963, 2509, 3373, + 2963, 2509, 3373, + 2961, 2511, 3373, + 2961, 2511, 3371, + 2959, 2513, 3371, + 2957, 2515, 3371, + 2955, 2517, 3371, + 2951, 2521, 3369, + 2947, 2527, 3367, + 2939, 2533, 3365, + 2931, 2543, 3363, + 2919, 2555, 3359, + 2901, 2569, 3355, + 2879, 2589, 3347, + 2845, 2613, 3339, + 2795, 2645, 3327, + 2721, 2683, 3309, + 2595, 2729, 3285, + 2347, 2785, 3253, + 597, 2851, 3203, + 0, 2925, 3127, + 0, 3009, 3001, + 0, 3103, 2745, + 0, 3203, 0, + 0, 3309, 0, + 0, 3421, 0, + 0, 3537, 0, + 0, 3659, 0, + 0, 3781, 0, + 0, 3907, 0, + 0, 4033, 0, + 2967, 2507, 3373, + 2965, 2509, 3373, + 2965, 2509, 3373, + 2965, 2509, 3373, + 2963, 2511, 3373, + 2961, 2513, 3373, + 2959, 2515, 3371, + 2957, 2517, 3371, + 2953, 2521, 3369, + 2949, 2527, 3369, + 2943, 2533, 3367, + 2933, 2543, 3363, + 2921, 2553, 3359, + 2905, 2569, 3355, + 2881, 2589, 3349, + 2847, 2613, 3339, + 2799, 2645, 3327, + 2725, 2683, 3311, + 2601, 2729, 3287, + 2355, 2785, 3253, + 912, 2851, 3203, + 0, 2925, 3127, + 0, 3009, 3001, + 0, 3103, 2749, + 0, 3203, 0, + 0, 3309, 0, + 0, 3421, 0, + 0, 3537, 0, + 0, 3659, 0, + 0, 3781, 0, + 0, 3907, 0, + 0, 4033, 0, + 2969, 2507, 3375, + 2969, 2507, 3375, + 2969, 2509, 3375, + 2967, 2509, 3373, + 2967, 2511, 3373, + 2965, 2513, 3373, + 2963, 2515, 3373, + 2961, 2517, 3371, + 2957, 2521, 3371, + 2953, 2527, 3369, + 2945, 2533, 3367, + 2937, 2541, 3365, + 2925, 2553, 3361, + 2909, 2569, 3355, + 2885, 2587, 3349, + 2853, 2613, 3341, + 2803, 2643, 3329, + 2731, 2683, 3311, + 2609, 2729, 3287, + 2369, 2785, 3255, + 1144, 2851, 3205, + 0, 2925, 3129, + 0, 3009, 3003, + 0, 3103, 2751, + 0, 3203, 567, + 0, 3309, 0, + 0, 3421, 0, + 0, 3537, 0, + 0, 3659, 0, + 0, 3781, 0, + 0, 3907, 0, + 0, 4033, 0, + 2973, 2507, 3375, + 2973, 2507, 3375, + 2973, 2507, 3375, + 2971, 2509, 3375, + 2971, 2509, 3375, + 2969, 2511, 3375, + 2967, 2513, 3373, + 2965, 2517, 3373, + 2961, 2521, 3371, + 2957, 2525, 3371, + 2951, 2533, 3369, + 2941, 2541, 3365, + 2929, 2553, 3363, + 2913, 2567, 3357, + 2891, 2587, 3351, + 2857, 2613, 3341, + 2811, 2643, 3329, + 2737, 2681, 3313, + 2619, 2729, 3289, + 2385, 2785, 3255, + 1339, 2851, 3207, + 0, 2925, 3131, + 0, 3009, 3007, + 0, 3103, 2757, + 0, 3203, 941, + 0, 3309, 0, + 0, 3421, 0, + 0, 3537, 0, + 0, 3657, 0, + 0, 3781, 0, + 0, 3907, 0, + 0, 4033, 0, + 2979, 2505, 3377, + 2979, 2507, 3377, + 2979, 2507, 3377, + 2977, 2507, 3377, + 2977, 2509, 3377, + 2975, 2511, 3375, + 2973, 2513, 3375, + 2971, 2515, 3375, + 2967, 2519, 3373, + 2963, 2525, 3371, + 2957, 2531, 3369, + 2947, 2541, 3367, + 2935, 2553, 3363, + 2919, 2567, 3359, + 2897, 2587, 3353, + 2865, 2611, 3343, + 2819, 2643, 3331, + 2747, 2681, 3315, + 2631, 2729, 3291, + 2405, 2785, 3257, + 1513, 2849, 3209, + 0, 2925, 3135, + 0, 3009, 3011, + 0, 3101, 2763, + 0, 3203, 1195, + 0, 3309, 0, + 0, 3421, 0, + 0, 3537, 0, + 0, 3657, 0, + 0, 3781, 0, + 0, 3907, 0, + 0, 4033, 0, + 2987, 2505, 3379, + 2987, 2505, 3379, + 2987, 2505, 3379, + 2985, 2507, 3379, + 2985, 2507, 3379, + 2983, 2509, 3379, + 2981, 2511, 3377, + 2979, 2515, 3377, + 2975, 2519, 3375, + 2971, 2523, 3375, + 2965, 2531, 3373, + 2955, 2539, 3369, + 2945, 2551, 3365, + 2929, 2567, 3361, + 2907, 2585, 3355, + 2875, 2611, 3345, + 2829, 2641, 3333, + 2759, 2681, 3317, + 2647, 2727, 3293, + 2431, 2783, 3261, + 1674, 2849, 3213, + 0, 2925, 3137, + 0, 3009, 3015, + 0, 3101, 2771, + 0, 3201, 1401, + 0, 3309, 0, + 0, 3421, 0, + 0, 3537, 0, + 0, 3657, 0, + 0, 3781, 0, + 0, 3905, 0, + 0, 4033, 0, + 2997, 2503, 3383, + 2997, 2503, 3383, + 2997, 2505, 3381, + 2995, 2505, 3381, + 2995, 2507, 3381, + 2993, 2509, 3381, + 2991, 2511, 3381, + 2989, 2513, 3379, + 2985, 2517, 3379, + 2981, 2523, 3377, + 2975, 2529, 3375, + 2967, 2539, 3373, + 2955, 2549, 3369, + 2939, 2565, 3365, + 2919, 2585, 3357, + 2887, 2609, 3349, + 2843, 2641, 3337, + 2777, 2679, 3321, + 2667, 2727, 3297, + 2465, 2783, 3265, + 1826, 2849, 3217, + 0, 2923, 3143, + 0, 3009, 3021, + 0, 3101, 2781, + 0, 3201, 1581, + 0, 3309, 0, + 0, 3421, 0, + 0, 3537, 0, + 0, 3657, 0, + 0, 3781, 0, + 0, 3905, 0, + 0, 4033, 0, + 3011, 2501, 3387, + 3009, 2501, 3385, + 3009, 2503, 3385, + 3009, 2503, 3385, + 3007, 2505, 3385, + 3007, 2507, 3385, + 3005, 2509, 3385, + 3001, 2511, 3383, + 2999, 2515, 3383, + 2995, 2521, 3381, + 2989, 2527, 3379, + 2981, 2537, 3377, + 2969, 2549, 3373, + 2955, 2563, 3369, + 2933, 2583, 3361, + 2905, 2607, 3353, + 2861, 2639, 3341, + 2797, 2679, 3325, + 2695, 2725, 3301, + 2505, 2781, 3269, + 1973, 2847, 3221, + 0, 2923, 3149, + 0, 3007, 3029, + 0, 3101, 2795, + 0, 3201, 1747, + 0, 3309, 0, + 0, 3421, 0, + 0, 3537, 0, + 0, 3657, 0, + 0, 3781, 0, + 0, 3905, 0, + 0, 4033, 0, + 3027, 2499, 3391, + 3027, 2499, 3391, + 3025, 2499, 3391, + 3025, 2501, 3391, + 3025, 2501, 3391, + 3023, 2503, 3389, + 3021, 2505, 3389, + 3019, 2509, 3389, + 3015, 2513, 3387, + 3011, 2517, 3385, + 3007, 2525, 3383, + 2999, 2533, 3381, + 2987, 2545, 3377, + 2973, 2561, 3373, + 2953, 2581, 3367, + 2925, 2605, 3359, + 2885, 2637, 3347, + 2823, 2677, 3331, + 2727, 2723, 3307, + 2555, 2781, 3275, + 2115, 2847, 3229, + 0, 2923, 3157, + 0, 3007, 3041, + 0, 3099, 2813, + 0, 3201, 1902, + 0, 3307, 0, + 0, 3421, 0, + 0, 3537, 0, + 0, 3657, 0, + 0, 3781, 0, + 0, 3905, 0, + 0, 4033, 0, + 3049, 2495, 3397, + 3049, 2495, 3397, + 3047, 2497, 3397, + 3047, 2497, 3397, + 3045, 2499, 3397, + 3045, 2501, 3397, + 3043, 2503, 3395, + 3041, 2505, 3395, + 3037, 2509, 3393, + 3033, 2515, 3393, + 3029, 2521, 3391, + 3021, 2531, 3389, + 3011, 2543, 3385, + 2997, 2557, 3381, + 2979, 2577, 3373, + 2953, 2603, 3365, + 2913, 2635, 3353, + 2857, 2673, 3337, + 2769, 2721, 3315, + 2613, 2779, 3285, + 2255, 2845, 3239, + 0, 2921, 3169, + 0, 3005, 3055, + 0, 3099, 2837, + 0, 3199, 2051, + 0, 3307, 0, + 0, 3419, 0, + 0, 3537, 0, + 0, 3657, 0, + 0, 3781, 0, + 0, 3905, 0, + 0, 4033, 0, + 3075, 2491, 3407, + 3075, 2491, 3407, + 3075, 2491, 3405, + 3075, 2493, 3405, + 3073, 2493, 3405, + 3073, 2495, 3405, + 3071, 2497, 3405, + 3069, 2501, 3403, + 3065, 2505, 3403, + 3063, 2509, 3401, + 3057, 2517, 3399, + 3051, 2527, 3397, + 3041, 2539, 3393, + 3029, 2553, 3389, + 3011, 2573, 3383, + 2985, 2599, 3375, + 2951, 2631, 3363, + 2899, 2671, 3347, + 2817, 2719, 3327, + 2681, 2775, 3295, + 2393, 2843, 3251, + 0, 2919, 3183, + 0, 3005, 3073, + 0, 3097, 2865, + 0, 3199, 2195, + 0, 3307, 0, + 0, 3419, 0, + 0, 3537, 0, + 0, 3657, 0, + 0, 3779, 0, + 0, 3905, 0, + 0, 4033, 0, + 3109, 2483, 3417, + 3109, 2485, 3417, + 3109, 2485, 3417, + 3109, 2485, 3417, + 3107, 2487, 3417, + 3107, 2489, 3417, + 3105, 2491, 3415, + 3103, 2495, 3415, + 3101, 2499, 3415, + 3097, 2503, 3413, + 3093, 2511, 3411, + 3087, 2521, 3409, + 3077, 2533, 3405, + 3065, 2549, 3401, + 3049, 2569, 3395, + 3027, 2595, 3387, + 2995, 2627, 3375, + 2947, 2667, 3361, + 2877, 2715, 3339, + 2759, 2773, 3309, + 2531, 2839, 3267, + 1593, 2917, 3201, + 0, 3003, 3097, + 0, 3097, 2903, + 0, 3197, 2335, + 0, 3305, 0, + 0, 3419, 0, + 0, 3535, 0, + 0, 3657, 0, + 0, 3779, 0, + 0, 3905, 0, + 0, 4033, 0, + 3153, 2475, 3433, + 3151, 2475, 3433, + 3151, 2477, 3433, + 3151, 2477, 3431, + 3151, 2479, 3431, + 3149, 2481, 3431, + 3147, 2483, 3431, + 3147, 2485, 3429, + 3143, 2489, 3429, + 3141, 2495, 3427, + 3137, 2503, 3425, + 3131, 2511, 3423, + 3123, 2525, 3421, + 3113, 2541, 3417, + 3097, 2561, 3411, + 3077, 2587, 3403, + 3049, 2619, 3391, + 3007, 2661, 3377, + 2945, 2709, 3357, + 2845, 2767, 3329, + 2665, 2835, 3287, + 2191, 2913, 3225, + 0, 2999, 3125, + 0, 3093, 2947, + 0, 3195, 2475, + 0, 3303, 0, + 0, 3417, 0, + 0, 3535, 0, + 0, 3655, 0, + 0, 3779, 0, + 0, 3905, 0, + 0, 4031, 0, + 3203, 2463, 3451, + 3203, 2463, 3451, + 3203, 2463, 3451, + 3201, 2465, 3451, + 3201, 2467, 3451, + 3201, 2469, 3451, + 3199, 2471, 3449, + 3197, 2473, 3449, + 3195, 2477, 3449, + 3193, 2483, 3447, + 3189, 2491, 3445, + 3183, 2501, 3443, + 3177, 2513, 3439, + 3167, 2529, 3435, + 3155, 2551, 3431, + 3137, 2577, 3423, + 3111, 2611, 3413, + 3075, 2653, 3399, + 3023, 2703, 3379, + 2941, 2761, 3353, + 2801, 2831, 3313, + 2501, 2909, 3255, + 0, 2995, 3163, + 0, 3091, 2999, + 0, 3193, 2611, + 0, 3301, 0, + 0, 3415, 0, + 0, 3533, 0, + 0, 3655, 0, + 0, 3779, 0, + 0, 3905, 0, + 0, 4031, 0, + 3263, 2445, 3475, + 3263, 2447, 3475, + 3263, 2447, 3475, + 3261, 2449, 3475, + 3261, 2449, 3475, + 3261, 2451, 3475, + 3259, 2455, 3475, + 3259, 2457, 3473, + 3257, 2461, 3473, + 3253, 2467, 3471, + 3251, 2475, 3469, + 3247, 2485, 3467, + 3239, 2499, 3465, + 3231, 2515, 3461, + 3221, 2537, 3455, + 3205, 2565, 3449, + 3183, 2599, 3439, + 3153, 2641, 3425, + 3109, 2693, 3407, + 3043, 2753, 3383, + 2933, 2823, 3345, + 2731, 2903, 3291, + 2103, 2991, 3207, + 0, 3087, 3063, + 0, 3189, 2747, + 0, 3299, 0, + 0, 3413, 0, + 0, 3531, 0, + 0, 3653, 0, + 0, 3777, 0, + 0, 3903, 0, + 0, 4031, 0, + 3333, 2423, 3507, + 3333, 2423, 3507, + 3331, 2423, 3505, + 3331, 2425, 3505, + 3331, 2427, 3505, + 3331, 2429, 3505, + 3329, 2431, 3505, + 3329, 2435, 3505, + 3327, 2439, 3503, + 3325, 2445, 3503, + 3321, 2453, 3501, + 3319, 2463, 3499, + 3313, 2477, 3497, + 3305, 2495, 3493, + 3297, 2519, 3487, + 3283, 2547, 3481, + 3265, 2583, 3473, + 3241, 2627, 3459, + 3203, 2679, 3443, + 3151, 2741, 3419, + 3067, 2813, 3385, + 2925, 2893, 3337, + 2621, 2983, 3261, + 0, 3081, 3135, + 0, 3185, 2881, + 0, 3295, 347, + 0, 3411, 0, + 0, 3529, 0, + 0, 3651, 0, + 0, 3777, 0, + 0, 3903, 0, + 0, 4031, 0, + 3411, 2389, 3545, + 3411, 2389, 3543, + 3411, 2391, 3543, + 3411, 2391, 3543, + 3411, 2393, 3543, + 3409, 2395, 3543, + 3409, 2399, 3543, + 3409, 2403, 3543, + 3407, 2407, 3541, + 3405, 2413, 3541, + 3403, 2423, 3539, + 3399, 2433, 3537, + 3395, 2449, 3535, + 3389, 2467, 3531, + 3381, 2491, 3527, + 3371, 2521, 3521, + 3355, 2559, 3513, + 3335, 2605, 3501, + 3305, 2661, 3487, + 3263, 2725, 3465, + 3201, 2799, 3435, + 3099, 2883, 3391, + 2915, 2973, 3323, + 2411, 3073, 3217, + 0, 3179, 3015, + 0, 3291, 2401, + 0, 3407, 0, + 0, 3527, 0, + 0, 3649, 0, + 0, 3775, 0, + 0, 3901, 0, + 0, 4029, 0, + 3499, 2341, 3591, + 3499, 2341, 3591, + 3499, 2343, 3589, + 3499, 2343, 3589, + 3499, 2345, 3589, + 3499, 2347, 3589, + 3497, 2351, 3589, + 3497, 2355, 3589, + 3495, 2361, 3587, + 3495, 2367, 3587, + 3493, 2377, 3585, + 3489, 2389, 3583, + 3485, 2405, 3581, + 3481, 2427, 3579, + 3475, 2453, 3575, + 3467, 2485, 3569, + 3455, 2527, 3563, + 3437, 2575, 3551, + 3415, 2635, 3539, + 3381, 2703, 3519, + 3333, 2779, 3493, + 3259, 2867, 3453, + 3139, 2961, 3397, + 2899, 3063, 3307, + 1706, 3171, 3149, + 0, 3285, 2783, + 0, 3403, 0, + 0, 3523, 0, + 0, 3647, 0, + 0, 3773, 0, + 0, 3899, 0, + 0, 4029, 0, + 3595, 2265, 3645, + 3595, 2267, 3645, + 3595, 2267, 3645, + 3595, 2269, 3645, + 3595, 2271, 3645, + 3595, 2275, 3645, + 3593, 2277, 3645, + 3593, 2283, 3643, + 3593, 2289, 3643, + 3591, 2297, 3643, + 3589, 2309, 3641, + 3587, 2323, 3639, + 3585, 2341, 3637, + 3581, 2365, 3635, + 3575, 2395, 3631, + 3569, 2433, 3627, + 3559, 2479, 3621, + 3545, 2533, 3611, + 3527, 2597, 3599, + 3503, 2671, 3583, + 3467, 2753, 3559, + 3413, 2845, 3527, + 3329, 2943, 3479, + 3187, 3049, 3405, + 2877, 3161, 3283, + 0, 3275, 3041, + 0, 3395, 1772, + 0, 3519, 0, + 0, 3643, 0, + 0, 3769, 0, + 0, 3897, 0, + 0, 4027, 0, + 3699, 2141, 3711, + 3699, 2143, 3711, + 3699, 2145, 3709, + 3699, 2147, 3709, + 3697, 2149, 3709, + 3697, 2153, 3709, + 3697, 2157, 3709, + 3697, 2165, 3709, + 3697, 2173, 3709, + 3695, 2183, 3707, + 3693, 2197, 3707, + 3693, 2217, 3705, + 3689, 2239, 3703, + 3687, 2269, 3701, + 3683, 2305, 3699, + 3677, 2351, 3695, + 3669, 2405, 3689, + 3659, 2469, 3681, + 3645, 2541, 3671, + 3627, 2623, 3657, + 3599, 2713, 3637, + 3559, 2813, 3609, + 3501, 2917, 3569, + 3407, 3029, 3509, + 3243, 3145, 3415, + 2847, 3263, 3249, + 0, 3387, 2837, + 0, 3511, 0, + 0, 3637, 0, + 0, 3765, 0, + 0, 3895, 0, + 0, 4025, 0, + 3807, 1895, 3785, + 3807, 1897, 3785, + 3807, 1900, 3785, + 3807, 1903, 3785, + 3807, 1908, 3783, + 3807, 1914, 3783, + 3807, 1922, 3783, + 3807, 1933, 3783, + 3805, 1946, 3783, + 3805, 1964, 3783, + 3805, 1987, 3781, + 3803, 2016, 3781, + 3801, 2051, 3779, + 3799, 2095, 3777, + 3795, 2149, 3775, + 3791, 2211, 3771, + 3785, 2283, 3767, + 3777, 2365, 3759, + 3767, 2453, 3751, + 3751, 2551, 3739, + 3731, 2657, 3723, + 3701, 2767, 3701, + 3659, 2881, 3667, + 3597, 3001, 3621, + 3495, 3123, 3549, + 3309, 3247, 3429, + 2803, 3373, 3197, + 0, 3501, 2201, + 0, 3631, 0, + 0, 3761, 0, + 0, 3891, 0, + 0, 4021, 0, + 3921, 376, 3867, + 3921, 429, 3867, + 3921, 491, 3867, + 3921, 564, 3867, + 3921, 645, 3867, + 3921, 735, 3867, + 3921, 833, 3867, + 3921, 938, 3867, + 3921, 1048, 3867, + 3919, 1164, 3865, + 3919, 1283, 3865, + 3919, 1405, 3865, + 3917, 1530, 3863, + 3915, 1656, 3861, + 3913, 1784, 3859, + 3909, 1913, 3857, + 3905, 2042, 3853, + 3899, 2173, 3847, + 3891, 2303, 3841, + 3879, 2435, 3831, + 3863, 2565, 3817, + 3841, 2697, 3799, + 3811, 2829, 3773, + 3767, 2961, 3735, + 3699, 3093, 3681, + 3591, 3225, 3595, + 3385, 3357, 3447, + 2735, 3489, 3121, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 4041, 0, 3959, + 4041, 0, 3959, + 4041, 0, 3959, + 4039, 0, 3959, + 4039, 0, 3959, + 4039, 0, 3959, + 4039, 0, 3959, + 4039, 0, 3959, + 4039, 0, 3959, + 4039, 0, 3959, + 4037, 0, 3957, + 4037, 0, 3957, + 4037, 0, 3957, + 4035, 0, 3955, + 4033, 0, 3953, + 4031, 0, 3951, + 4027, 815, 3947, + 4023, 1625, 3943, + 4015, 1965, 3937, + 4007, 2207, 3929, + 3995, 2407, 3919, + 3979, 2583, 3905, + 3957, 2747, 3883, + 3925, 2901, 3855, + 3879, 3049, 3813, + 3809, 3193, 3751, + 3693, 3333, 3651, + 3471, 3471, 3471, + 2627, 3607, 2991, + 0, 3743, 0, + 0, 3877, 0, + 0, 4011, 0, + 4095, 0, 4059, + 4095, 0, 4059, + 4095, 0, 4059, + 4095, 0, 4059, + 4095, 0, 4059, + 4095, 0, 4059, + 4095, 0, 4059, + 4095, 0, 4059, + 4095, 0, 4059, + 4095, 0, 4059, + 4095, 0, 4057, + 4095, 0, 4057, + 4095, 0, 4057, + 4095, 0, 4055, + 4095, 0, 4053, + 4095, 0, 4053, + 4095, 0, 4049, + 4095, 0, 4047, + 4095, 0, 4041, + 4095, 1285, 4035, + 4095, 2034, 4027, + 4095, 2367, 4015, + 4095, 2607, 3999, + 4077, 2805, 3977, + 4043, 2981, 3945, + 3995, 3145, 3899, + 3923, 3297, 3831, + 3801, 3445, 3717, + 3565, 3589, 3499, + 2425, 3729, 2725, + 0, 3867, 0, + 0, 4003, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 1597, 4095, + 4095, 2309, 4095, + 4095, 2637, 4095, + 4095, 2875, 4079, + 4095, 3071, 4045, + 4095, 3247, 3995, + 4041, 3409, 3919, + 3915, 3563, 3791, + 3665, 3711, 3537, + 1791, 3853, 0, + 0, 3993, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2215, 4095, + 4095, 2673, 4095, + 4095, 2951, 4095, + 4095, 3169, 4095, + 4095, 3357, 4095, + 4095, 3525, 4015, + 4033, 3683, 3877, + 3773, 3835, 3581, + 0, 3979, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2051, 4095, + 4095, 2717, 4095, + 4095, 3039, 4095, + 4095, 3275, 4095, + 4095, 3471, 4095, + 4095, 3645, 4095, + 4095, 3807, 3969, + 3885, 3961, 3633, + 3089, 2641, 3503, + 3089, 2641, 3503, + 3089, 2641, 3503, + 3089, 2643, 3503, + 3087, 2643, 3503, + 3087, 2645, 3503, + 3085, 2645, 3501, + 3083, 2649, 3501, + 3081, 2651, 3501, + 3077, 2655, 3499, + 3071, 2659, 3497, + 3065, 2667, 3495, + 3057, 2675, 3493, + 3043, 2687, 3489, + 3027, 2703, 3485, + 3003, 2721, 3479, + 2969, 2747, 3469, + 2919, 2777, 3457, + 2843, 2815, 3439, + 2715, 2863, 3415, + 2453, 2919, 3383, + 0, 2983, 3333, + 0, 3059, 3257, + 0, 3143, 3129, + 0, 3235, 2871, + 0, 3335, 0, + 0, 3441, 0, + 0, 3553, 0, + 0, 3671, 0, + 0, 3791, 0, + 0, 3913, 0, + 0, 4039, 0, + 3091, 2641, 3503, + 3091, 2641, 3503, + 3089, 2641, 3503, + 3089, 2641, 3503, + 3089, 2643, 3503, + 3087, 2645, 3503, + 3085, 2645, 3503, + 3083, 2647, 3501, + 3081, 2651, 3501, + 3077, 2655, 3499, + 3073, 2659, 3499, + 3065, 2667, 3497, + 3057, 2675, 3493, + 3045, 2687, 3489, + 3027, 2701, 3485, + 3003, 2721, 3479, + 2969, 2745, 3469, + 2919, 2777, 3457, + 2843, 2815, 3439, + 2715, 2863, 3417, + 2455, 2919, 3383, + 0, 2983, 3333, + 0, 3059, 3257, + 0, 3143, 3129, + 0, 3235, 2871, + 0, 3335, 0, + 0, 3441, 0, + 0, 3553, 0, + 0, 3671, 0, + 0, 3791, 0, + 0, 3913, 0, + 0, 4039, 0, + 3091, 2641, 3503, + 3091, 2641, 3503, + 3091, 2641, 3503, + 3089, 2641, 3503, + 3089, 2643, 3503, + 3087, 2645, 3503, + 3087, 2645, 3503, + 3085, 2647, 3501, + 3081, 2651, 3501, + 3077, 2655, 3499, + 3073, 2659, 3499, + 3067, 2667, 3497, + 3057, 2675, 3493, + 3045, 2687, 3489, + 3027, 2701, 3485, + 3005, 2721, 3479, + 2971, 2745, 3469, + 2921, 2777, 3457, + 2843, 2815, 3441, + 2717, 2863, 3417, + 2459, 2917, 3383, + 0, 2983, 3333, + 0, 3059, 3257, + 0, 3143, 3129, + 0, 3235, 2871, + 0, 3335, 0, + 0, 3441, 0, + 0, 3553, 0, + 0, 3671, 0, + 0, 3791, 0, + 0, 3913, 0, + 0, 4039, 0, + 3091, 2641, 3503, + 3091, 2641, 3503, + 3091, 2641, 3503, + 3091, 2641, 3503, + 3089, 2643, 3503, + 3089, 2643, 3503, + 3087, 2645, 3503, + 3085, 2647, 3501, + 3083, 2651, 3501, + 3079, 2655, 3499, + 3073, 2659, 3499, + 3067, 2667, 3497, + 3059, 2675, 3493, + 3045, 2687, 3491, + 3029, 2701, 3485, + 3005, 2721, 3479, + 2971, 2745, 3469, + 2921, 2777, 3457, + 2845, 2815, 3441, + 2719, 2863, 3417, + 2461, 2917, 3383, + 0, 2983, 3333, + 0, 3059, 3257, + 0, 3143, 3129, + 0, 3235, 2873, + 0, 3335, 0, + 0, 3441, 0, + 0, 3553, 0, + 0, 3671, 0, + 0, 3791, 0, + 0, 3913, 0, + 0, 4039, 0, + 3093, 2641, 3505, + 3093, 2641, 3505, + 3091, 2641, 3503, + 3091, 2641, 3503, + 3091, 2643, 3503, + 3089, 2643, 3503, + 3087, 2645, 3503, + 3085, 2647, 3503, + 3083, 2651, 3501, + 3079, 2655, 3501, + 3075, 2659, 3499, + 3069, 2667, 3497, + 3059, 2675, 3495, + 3047, 2687, 3491, + 3031, 2701, 3485, + 3007, 2721, 3479, + 2973, 2745, 3469, + 2923, 2777, 3457, + 2847, 2815, 3441, + 2721, 2861, 3417, + 2465, 2917, 3383, + 0, 2983, 3333, + 0, 3059, 3257, + 0, 3143, 3131, + 0, 3235, 2873, + 0, 3335, 0, + 0, 3441, 0, + 0, 3553, 0, + 0, 3671, 0, + 0, 3791, 0, + 0, 3913, 0, + 0, 4039, 0, + 3095, 2639, 3505, + 3093, 2641, 3505, + 3093, 2641, 3505, + 3093, 2641, 3505, + 3091, 2643, 3503, + 3091, 2643, 3503, + 3089, 2645, 3503, + 3087, 2647, 3503, + 3085, 2651, 3501, + 3081, 2655, 3501, + 3077, 2659, 3499, + 3069, 2667, 3497, + 3061, 2675, 3495, + 3049, 2687, 3491, + 3031, 2701, 3485, + 3007, 2721, 3479, + 2975, 2745, 3471, + 2925, 2777, 3459, + 2849, 2815, 3441, + 2723, 2861, 3417, + 2471, 2917, 3383, + 108, 2983, 3335, + 0, 3059, 3257, + 0, 3143, 3131, + 0, 3235, 2875, + 0, 3335, 0, + 0, 3441, 0, + 0, 3553, 0, + 0, 3671, 0, + 0, 3791, 0, + 0, 3913, 0, + 0, 4039, 0, + 3097, 2639, 3505, + 3095, 2641, 3505, + 3095, 2641, 3505, + 3095, 2641, 3505, + 3093, 2643, 3505, + 3093, 2643, 3505, + 3091, 2645, 3503, + 3089, 2647, 3503, + 3087, 2651, 3503, + 3083, 2653, 3501, + 3079, 2659, 3499, + 3071, 2665, 3497, + 3063, 2675, 3495, + 3051, 2687, 3491, + 3033, 2701, 3487, + 3011, 2721, 3479, + 2977, 2745, 3471, + 2927, 2777, 3459, + 2853, 2815, 3441, + 2727, 2861, 3417, + 2479, 2917, 3385, + 729, 2983, 3335, + 0, 3057, 3259, + 0, 3143, 3133, + 0, 3235, 2877, + 0, 3335, 0, + 0, 3441, 0, + 0, 3553, 0, + 0, 3671, 0, + 0, 3791, 0, + 0, 3913, 0, + 0, 4039, 0, + 3099, 2639, 3505, + 3099, 2639, 3505, + 3097, 2641, 3505, + 3097, 2641, 3505, + 3097, 2641, 3505, + 3095, 2643, 3505, + 3093, 2645, 3505, + 3091, 2647, 3503, + 3089, 2649, 3503, + 3085, 2653, 3501, + 3081, 2659, 3501, + 3075, 2665, 3499, + 3065, 2675, 3495, + 3053, 2685, 3493, + 3037, 2701, 3487, + 3013, 2721, 3481, + 2979, 2745, 3471, + 2931, 2777, 3459, + 2857, 2815, 3443, + 2733, 2861, 3419, + 2487, 2917, 3385, + 1043, 2983, 3335, + 0, 3057, 3261, + 0, 3141, 3133, + 0, 3235, 2881, + 0, 3335, 0, + 0, 3441, 0, + 0, 3553, 0, + 0, 3671, 0, + 0, 3791, 0, + 0, 3913, 0, + 0, 4039, 0, + 3101, 2639, 3507, + 3101, 2639, 3507, + 3101, 2639, 3507, + 3101, 2641, 3507, + 3099, 2641, 3507, + 3099, 2643, 3505, + 3097, 2645, 3505, + 3095, 2647, 3505, + 3093, 2649, 3503, + 3089, 2653, 3503, + 3085, 2659, 3501, + 3077, 2665, 3499, + 3069, 2673, 3497, + 3057, 2685, 3493, + 3041, 2701, 3489, + 3017, 2721, 3481, + 2985, 2745, 3473, + 2937, 2775, 3461, + 2863, 2815, 3443, + 2741, 2861, 3419, + 2501, 2917, 3387, + 1276, 2983, 3337, + 0, 3057, 3261, + 0, 3141, 3135, + 0, 3235, 2883, + 0, 3335, 699, + 0, 3441, 0, + 0, 3553, 0, + 0, 3669, 0, + 0, 3791, 0, + 0, 3913, 0, + 0, 4039, 0, + 3107, 2639, 3507, + 3105, 2639, 3507, + 3105, 2639, 3507, + 3105, 2639, 3507, + 3103, 2641, 3507, + 3103, 2641, 3507, + 3101, 2643, 3507, + 3099, 2645, 3505, + 3097, 2649, 3505, + 3093, 2653, 3503, + 3089, 2657, 3503, + 3083, 2665, 3501, + 3073, 2673, 3497, + 3061, 2685, 3495, + 3045, 2701, 3489, + 3023, 2719, 3483, + 2989, 2745, 3473, + 2943, 2775, 3461, + 2869, 2813, 3445, + 2751, 2861, 3421, + 2517, 2917, 3387, + 1471, 2983, 3339, + 0, 3057, 3263, + 0, 3141, 3139, + 0, 3235, 2889, + 0, 3335, 1073, + 0, 3441, 0, + 0, 3553, 0, + 0, 3669, 0, + 0, 3791, 0, + 0, 3913, 0, + 0, 4039, 0, + 3111, 2637, 3509, + 3111, 2637, 3509, + 3111, 2639, 3509, + 3111, 2639, 3509, + 3109, 2639, 3509, + 3109, 2641, 3509, + 3107, 2643, 3509, + 3105, 2645, 3507, + 3103, 2647, 3507, + 3099, 2651, 3505, + 3095, 2657, 3505, + 3089, 2663, 3503, + 3079, 2673, 3499, + 3069, 2685, 3495, + 3051, 2699, 3491, + 3029, 2719, 3485, + 2997, 2743, 3475, + 2951, 2775, 3463, + 2879, 2813, 3447, + 2763, 2861, 3423, + 2537, 2917, 3389, + 1645, 2981, 3341, + 0, 3057, 3267, + 0, 3141, 3143, + 0, 3235, 2895, + 0, 3335, 1327, + 0, 3441, 0, + 0, 3553, 0, + 0, 3669, 0, + 0, 3791, 0, + 0, 3913, 0, + 0, 4039, 0, + 3119, 2637, 3511, + 3119, 2637, 3511, + 3119, 2637, 3511, + 3119, 2637, 3511, + 3117, 2639, 3511, + 3117, 2641, 3511, + 3115, 2641, 3511, + 3113, 2643, 3509, + 3111, 2647, 3509, + 3107, 2651, 3507, + 3103, 2655, 3507, + 3097, 2663, 3505, + 3087, 2671, 3501, + 3077, 2683, 3499, + 3061, 2699, 3493, + 3039, 2717, 3487, + 3007, 2743, 3477, + 2961, 2773, 3465, + 2893, 2813, 3449, + 2779, 2859, 3425, + 2563, 2915, 3393, + 1806, 2981, 3345, + 0, 3057, 3271, + 0, 3141, 3147, + 0, 3233, 2903, + 0, 3335, 1533, + 0, 3441, 0, + 0, 3553, 0, + 0, 3669, 0, + 0, 3789, 0, + 0, 3913, 0, + 0, 4039, 0, + 3129, 2635, 3515, + 3129, 2635, 3515, + 3129, 2635, 3515, + 3129, 2637, 3515, + 3127, 2637, 3513, + 3127, 2639, 3513, + 3125, 2641, 3513, + 3123, 2643, 3513, + 3121, 2645, 3511, + 3117, 2649, 3511, + 3113, 2655, 3509, + 3107, 2661, 3507, + 3099, 2671, 3505, + 3087, 2681, 3501, + 3071, 2697, 3497, + 3051, 2717, 3489, + 3019, 2741, 3481, + 2975, 2773, 3469, + 2909, 2811, 3453, + 2799, 2859, 3429, + 2597, 2915, 3397, + 1958, 2981, 3349, + 0, 3057, 3275, + 0, 3141, 3153, + 0, 3233, 2913, + 0, 3333, 1714, + 0, 3441, 0, + 0, 3553, 0, + 0, 3669, 0, + 0, 3789, 0, + 0, 3913, 0, + 0, 4039, 0, + 3143, 2633, 3519, + 3143, 2633, 3519, + 3141, 2633, 3519, + 3141, 2635, 3517, + 3141, 2635, 3517, + 3139, 2637, 3517, + 3139, 2639, 3517, + 3137, 2641, 3517, + 3133, 2643, 3515, + 3131, 2647, 3515, + 3127, 2653, 3513, + 3121, 2659, 3511, + 3113, 2669, 3509, + 3101, 2681, 3505, + 3087, 2695, 3501, + 3065, 2715, 3493, + 3037, 2741, 3485, + 2993, 2771, 3473, + 2929, 2811, 3457, + 2827, 2857, 3433, + 2637, 2913, 3401, + 2105, 2979, 3353, + 0, 3055, 3281, + 0, 3139, 3161, + 0, 3233, 2927, + 0, 3333, 1879, + 0, 3441, 0, + 0, 3553, 0, + 0, 3669, 0, + 0, 3789, 0, + 0, 3913, 0, + 0, 4037, 0, + 3159, 2631, 3523, + 3159, 2631, 3523, + 3159, 2631, 3523, + 3159, 2631, 3523, + 3157, 2633, 3523, + 3157, 2635, 3523, + 3155, 2635, 3521, + 3153, 2637, 3521, + 3151, 2641, 3521, + 3149, 2645, 3519, + 3143, 2651, 3517, + 3139, 2657, 3517, + 3131, 2665, 3513, + 3121, 2677, 3511, + 3105, 2693, 3505, + 3085, 2713, 3499, + 3057, 2737, 3491, + 3017, 2769, 3479, + 2955, 2809, 3463, + 2859, 2855, 3439, + 2687, 2913, 3407, + 2249, 2979, 3361, + 0, 3055, 3289, + 0, 3139, 3173, + 0, 3233, 2945, + 0, 3333, 2034, + 0, 3439, 0, + 0, 3553, 0, + 0, 3669, 0, + 0, 3789, 0, + 0, 3913, 0, + 0, 4037, 0, + 3181, 2627, 3529, + 3181, 2627, 3529, + 3181, 2627, 3529, + 3179, 2629, 3529, + 3179, 2629, 3529, + 3179, 2631, 3529, + 3177, 2633, 3529, + 3175, 2635, 3527, + 3173, 2637, 3527, + 3171, 2641, 3527, + 3167, 2647, 3525, + 3161, 2653, 3523, + 3153, 2663, 3521, + 3143, 2675, 3517, + 3129, 2689, 3513, + 3111, 2709, 3505, + 3085, 2735, 3497, + 3047, 2767, 3485, + 2989, 2807, 3469, + 2901, 2853, 3447, + 2745, 2911, 3417, + 2389, 2977, 3371, + 0, 3053, 3301, + 0, 3137, 3187, + 0, 3231, 2969, + 0, 3333, 2183, + 0, 3439, 0, + 0, 3551, 0, + 0, 3669, 0, + 0, 3789, 0, + 0, 3913, 0, + 0, 4037, 0, + 3209, 2621, 3539, + 3207, 2623, 3539, + 3207, 2623, 3539, + 3207, 2623, 3539, + 3207, 2625, 3537, + 3205, 2625, 3537, + 3205, 2627, 3537, + 3203, 2629, 3537, + 3201, 2633, 3535, + 3199, 2637, 3535, + 3195, 2643, 3533, + 3189, 2649, 3531, + 3183, 2659, 3529, + 3173, 2671, 3525, + 3161, 2685, 3521, + 3143, 2705, 3515, + 3117, 2731, 3507, + 3083, 2763, 3495, + 3031, 2803, 3479, + 2949, 2851, 3459, + 2813, 2909, 3427, + 2527, 2975, 3383, + 0, 3051, 3315, + 0, 3137, 3205, + 0, 3229, 2997, + 0, 3331, 2327, + 0, 3439, 0, + 0, 3551, 0, + 0, 3669, 0, + 0, 3789, 0, + 0, 3913, 0, + 0, 4037, 0, + 3243, 2615, 3549, + 3243, 2615, 3549, + 3241, 2617, 3549, + 3241, 2617, 3549, + 3241, 2617, 3549, + 3239, 2619, 3549, + 3239, 2621, 3549, + 3237, 2623, 3547, + 3235, 2627, 3547, + 3233, 2631, 3547, + 3229, 2635, 3545, + 3225, 2643, 3543, + 3219, 2653, 3541, + 3209, 2665, 3537, + 3199, 2681, 3533, + 3181, 2701, 3527, + 3159, 2727, 3519, + 3127, 2759, 3507, + 3079, 2799, 3493, + 3009, 2847, 3471, + 2891, 2905, 3441, + 2663, 2971, 3399, + 1725, 3049, 3333, + 0, 3135, 3229, + 0, 3229, 3035, + 0, 3329, 2467, + 0, 3437, 0, + 0, 3551, 0, + 0, 3667, 0, + 0, 3789, 0, + 0, 3911, 0, + 0, 4037, 0, + 3285, 2607, 3565, + 3285, 2607, 3565, + 3283, 2607, 3565, + 3283, 2609, 3565, + 3283, 2609, 3565, + 3283, 2611, 3563, + 3281, 2613, 3563, + 3279, 2615, 3563, + 3279, 2617, 3563, + 3275, 2621, 3561, + 3273, 2627, 3559, + 3269, 2635, 3559, + 3263, 2645, 3555, + 3255, 2657, 3553, + 3245, 2673, 3549, + 3229, 2693, 3543, + 3209, 2719, 3535, + 3181, 2753, 3525, + 3139, 2793, 3509, + 3077, 2841, 3489, + 2977, 2899, 3461, + 2797, 2967, 3419, + 2323, 3045, 3357, + 0, 3131, 3257, + 0, 3225, 3079, + 0, 3327, 2607, + 0, 3435, 0, + 0, 3549, 0, + 0, 3667, 0, + 0, 3787, 0, + 0, 3911, 0, + 0, 4037, 0, + 3335, 2595, 3583, + 3335, 2595, 3583, + 3335, 2595, 3583, + 3335, 2597, 3583, + 3333, 2597, 3583, + 3333, 2599, 3583, + 3333, 2601, 3583, + 3331, 2603, 3581, + 3329, 2605, 3581, + 3327, 2611, 3581, + 3325, 2615, 3579, + 3321, 2623, 3577, + 3315, 2633, 3575, + 3309, 2645, 3573, + 3299, 2661, 3567, + 3287, 2683, 3563, + 3269, 2709, 3555, + 3243, 2743, 3545, + 3207, 2785, 3531, + 3155, 2835, 3511, + 3073, 2893, 3485, + 2933, 2963, 3445, + 2633, 3041, 3387, + 0, 3127, 3295, + 0, 3223, 3131, + 0, 3325, 2743, + 0, 3433, 0, + 0, 3547, 0, + 0, 3665, 0, + 0, 3787, 0, + 0, 3911, 0, + 0, 4037, 0, + 3395, 2577, 3607, + 3395, 2577, 3607, + 3395, 2579, 3607, + 3395, 2579, 3607, + 3393, 2581, 3607, + 3393, 2581, 3607, + 3393, 2583, 3607, + 3391, 2587, 3607, + 3391, 2589, 3605, + 3389, 2593, 3605, + 3385, 2599, 3603, + 3383, 2607, 3601, + 3379, 2617, 3599, + 3373, 2631, 3597, + 3363, 2647, 3593, + 3353, 2669, 3587, + 3337, 2697, 3581, + 3315, 2731, 3571, + 3285, 2773, 3559, + 3241, 2825, 3539, + 3175, 2885, 3515, + 3067, 2955, 3477, + 2863, 3035, 3423, + 2235, 3123, 3339, + 0, 3219, 3195, + 0, 3323, 2879, + 0, 3431, 0, + 0, 3545, 0, + 0, 3665, 0, + 0, 3785, 0, + 0, 3909, 0, + 0, 4035, 0, + 3465, 2555, 3639, + 3465, 2555, 3639, + 3465, 2555, 3639, + 3465, 2557, 3639, + 3463, 2557, 3637, + 3463, 2559, 3637, + 3463, 2561, 3637, + 3461, 2563, 3637, + 3461, 2567, 3637, + 3459, 2571, 3635, + 3457, 2577, 3635, + 3455, 2585, 3633, + 3451, 2597, 3631, + 3445, 2609, 3629, + 3439, 2627, 3625, + 3429, 2651, 3619, + 3415, 2679, 3613, + 3397, 2715, 3605, + 3373, 2759, 3591, + 3335, 2811, 3575, + 3283, 2873, 3551, + 3199, 2945, 3517, + 3057, 3025, 3469, + 2753, 3115, 3393, + 0, 3213, 3267, + 0, 3317, 3013, + 0, 3427, 479, + 0, 3543, 0, + 0, 3661, 0, + 0, 3783, 0, + 0, 3909, 0, + 0, 4035, 0, + 3543, 2521, 3677, + 3543, 2521, 3677, + 3543, 2521, 3677, + 3543, 2523, 3675, + 3543, 2525, 3675, + 3543, 2525, 3675, + 3541, 2527, 3675, + 3541, 2531, 3675, + 3541, 2535, 3675, + 3539, 2539, 3673, + 3537, 2545, 3673, + 3535, 2555, 3671, + 3531, 2565, 3669, + 3527, 2581, 3667, + 3521, 2599, 3663, + 3513, 2623, 3659, + 3503, 2653, 3653, + 3487, 2691, 3645, + 3467, 2737, 3633, + 3439, 2793, 3619, + 3395, 2857, 3597, + 3333, 2931, 3567, + 3231, 3015, 3523, + 3047, 3107, 3455, + 2543, 3205, 3349, + 0, 3311, 3147, + 0, 3423, 2533, + 0, 3539, 0, + 0, 3659, 0, + 0, 3781, 0, + 0, 3907, 0, + 0, 4033, 0, + 3631, 2471, 3723, + 3631, 2473, 3723, + 3631, 2473, 3723, + 3631, 2475, 3723, + 3631, 2475, 3721, + 3631, 2477, 3721, + 3631, 2479, 3721, + 3629, 2483, 3721, + 3629, 2487, 3721, + 3627, 2493, 3719, + 3627, 2499, 3719, + 3625, 2509, 3717, + 3621, 2521, 3717, + 3619, 2537, 3713, + 3613, 2559, 3711, + 3607, 2585, 3707, + 3599, 2617, 3701, + 3587, 2659, 3695, + 3569, 2707, 3685, + 3547, 2767, 3671, + 3513, 2835, 3651, + 3465, 2911, 3625, + 3393, 2999, 3585, + 3271, 3093, 3529, + 3031, 3195, 3439, + 1838, 3303, 3281, + 0, 3417, 2915, + 0, 3535, 0, + 0, 3655, 0, + 0, 3779, 0, + 0, 3905, 0, + 0, 4031, 0, + 3727, 2397, 3777, + 3727, 2397, 3777, + 3727, 2399, 3777, + 3727, 2399, 3777, + 3727, 2401, 3777, + 3727, 2403, 3777, + 3727, 2407, 3777, + 3725, 2411, 3777, + 3725, 2415, 3775, + 3725, 2421, 3775, + 3723, 2429, 3775, + 3721, 2441, 3773, + 3719, 2455, 3773, + 3717, 2475, 3771, + 3713, 2497, 3767, + 3707, 2527, 3763, + 3701, 2565, 3759, + 3691, 2611, 3753, + 3679, 2665, 3743, + 3659, 2729, 3731, + 3635, 2803, 3715, + 3599, 2885, 3691, + 3545, 2977, 3659, + 3461, 3075, 3611, + 3319, 3181, 3537, + 3009, 3293, 3415, + 0, 3409, 3173, + 0, 3527, 1904, + 0, 3651, 0, + 0, 3775, 0, + 0, 3901, 0, + 0, 4029, 0, + 3831, 2273, 3843, + 3831, 2273, 3843, + 3831, 2275, 3843, + 3831, 2277, 3843, + 3831, 2279, 3841, + 3831, 2281, 3841, + 3829, 2285, 3841, + 3829, 2289, 3841, + 3829, 2297, 3841, + 3829, 2305, 3841, + 3827, 2315, 3839, + 3827, 2329, 3839, + 3825, 2349, 3837, + 3823, 2371, 3835, + 3819, 2401, 3833, + 3815, 2437, 3831, + 3809, 2483, 3827, + 3801, 2537, 3821, + 3791, 2601, 3813, + 3777, 2673, 3803, + 3759, 2755, 3789, + 3731, 2847, 3769, + 3691, 2945, 3741, + 3633, 3051, 3701, + 3539, 3161, 3641, + 3375, 3277, 3547, + 2979, 3397, 3381, + 0, 3519, 2969, + 0, 3643, 0, + 0, 3769, 0, + 0, 3897, 0, + 0, 4027, 0, + 3939, 2026, 3917, + 3939, 2027, 3917, + 3939, 2029, 3917, + 3939, 2032, 3917, + 3939, 2035, 3917, + 3939, 2040, 3917, + 3939, 2046, 3915, + 3939, 2055, 3915, + 3939, 2065, 3915, + 3937, 2079, 3915, + 3937, 2097, 3915, + 3937, 2119, 3913, + 3935, 2149, 3913, + 3933, 2185, 3911, + 3931, 2229, 3909, + 3927, 2281, 3907, + 3923, 2343, 3903, + 3917, 2415, 3899, + 3909, 2497, 3891, + 3899, 2587, 3883, + 3883, 2683, 3871, + 3863, 2789, 3855, + 3833, 2899, 3833, + 3791, 3015, 3799, + 3729, 3133, 3753, + 3627, 3255, 3681, + 3441, 3379, 3561, + 2935, 3507, 3331, + 0, 3633, 2333, + 0, 3763, 0, + 0, 3893, 0, + 0, 4023, 0, + 4055, 463, 3999, + 4055, 508, 3999, + 4053, 561, 3999, + 4053, 623, 3999, + 4053, 696, 3999, + 4053, 777, 3999, + 4053, 867, 3999, + 4053, 965, 3999, + 4053, 1070, 3999, + 4053, 1181, 3999, + 4051, 1296, 3999, + 4051, 1415, 3997, + 4051, 1537, 3997, + 4049, 1662, 3995, + 4047, 1788, 3993, + 4045, 1916, 3991, + 4041, 2045, 3989, + 4037, 2175, 3985, + 4031, 2305, 3979, + 4023, 2435, 3973, + 4011, 2567, 3963, + 3995, 2697, 3949, + 3973, 2829, 3931, + 3943, 2961, 3905, + 3899, 3093, 3867, + 3831, 3225, 3813, + 3723, 3357, 3727, + 3517, 3489, 3579, + 2867, 3621, 3253, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 4095, 0, 4091, + 4095, 0, 4091, + 4095, 0, 4091, + 4095, 0, 4091, + 4095, 0, 4091, + 4095, 0, 4091, + 4095, 0, 4091, + 4095, 0, 4091, + 4095, 0, 4091, + 4095, 0, 4091, + 4095, 0, 4091, + 4095, 0, 4089, + 4095, 0, 4089, + 4095, 0, 4089, + 4095, 0, 4087, + 4095, 0, 4085, + 4095, 0, 4083, + 4095, 947, 4079, + 4095, 1757, 4075, + 4095, 2097, 4069, + 4095, 2339, 4061, + 4095, 2539, 4051, + 4095, 2717, 4037, + 4089, 2879, 4015, + 4057, 3033, 3987, + 4011, 3181, 3945, + 3941, 3325, 3883, + 3825, 3465, 3783, + 3603, 3603, 3603, + 2759, 3739, 3123, + 0, 3875, 0, + 0, 4009, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 1417, 4095, + 4095, 2167, 4095, + 4095, 2499, 4095, + 4095, 2739, 4095, + 4095, 2937, 4095, + 4095, 3115, 4077, + 4095, 3277, 4033, + 4055, 3431, 3963, + 3933, 3577, 3849, + 3697, 3721, 3631, + 2557, 3861, 2857, + 0, 3999, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 1729, 4095, + 4095, 2441, 4095, + 4095, 2769, 4095, + 4095, 3007, 4095, + 4095, 3203, 4095, + 4095, 3379, 4095, + 4095, 3541, 4051, + 4047, 3695, 3923, + 3797, 3843, 3669, + 1924, 3985, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2347, 4095, + 4095, 2805, 4095, + 4095, 3085, 4095, + 4095, 3301, 4095, + 4095, 3489, 4095, + 4095, 3657, 4095, + 4095, 3815, 4009, + 3905, 3967, 3713, + 3221, 2773, 3635, + 3221, 2773, 3635, + 3221, 2773, 3635, + 3221, 2773, 3635, + 3221, 2775, 3635, + 3219, 2775, 3635, + 3219, 2777, 3635, + 3217, 2779, 3635, + 3215, 2781, 3633, + 3213, 2783, 3633, + 3209, 2787, 3631, + 3203, 2793, 3629, + 3197, 2799, 3627, + 3187, 2807, 3625, + 3175, 2819, 3621, + 3159, 2835, 3617, + 3135, 2853, 3611, + 3101, 2879, 3601, + 3051, 2909, 3589, + 2973, 2947, 3571, + 2845, 2995, 3547, + 2585, 3051, 3515, + 0, 3115, 3465, + 0, 3191, 3387, + 0, 3275, 3261, + 0, 3367, 3003, + 0, 3467, 0, + 0, 3573, 0, + 0, 3685, 0, + 0, 3803, 0, + 0, 3923, 0, + 0, 4045, 0, + 3223, 2773, 3635, + 3223, 2773, 3635, + 3221, 2773, 3635, + 3221, 2773, 3635, + 3221, 2775, 3635, + 3219, 2775, 3635, + 3219, 2777, 3635, + 3217, 2777, 3635, + 3215, 2781, 3633, + 3213, 2783, 3633, + 3209, 2787, 3631, + 3203, 2791, 3631, + 3197, 2799, 3629, + 3189, 2807, 3625, + 3175, 2819, 3621, + 3159, 2835, 3617, + 3135, 2853, 3611, + 3101, 2879, 3601, + 3051, 2909, 3589, + 2975, 2947, 3571, + 2847, 2995, 3549, + 2587, 3051, 3515, + 0, 3115, 3465, + 0, 3191, 3389, + 0, 3275, 3261, + 0, 3367, 3003, + 0, 3467, 0, + 0, 3573, 0, + 0, 3685, 0, + 0, 3803, 0, + 0, 3923, 0, + 0, 4045, 0, + 3223, 2773, 3635, + 3223, 2773, 3635, + 3223, 2773, 3635, + 3221, 2773, 3635, + 3221, 2775, 3635, + 3221, 2775, 3635, + 3219, 2777, 3635, + 3217, 2777, 3635, + 3215, 2781, 3633, + 3213, 2783, 3633, + 3209, 2787, 3631, + 3205, 2791, 3631, + 3197, 2799, 3629, + 3189, 2807, 3625, + 3177, 2819, 3621, + 3159, 2835, 3617, + 3135, 2853, 3611, + 3101, 2879, 3601, + 3051, 2909, 3589, + 2975, 2947, 3573, + 2847, 2995, 3549, + 2587, 3051, 3515, + 0, 3115, 3465, + 0, 3191, 3389, + 0, 3275, 3261, + 0, 3367, 3003, + 0, 3467, 0, + 0, 3573, 0, + 0, 3685, 0, + 0, 3803, 0, + 0, 3923, 0, + 0, 4045, 0, + 3223, 2773, 3635, + 3223, 2773, 3635, + 3223, 2773, 3635, + 3223, 2773, 3635, + 3221, 2775, 3635, + 3221, 2775, 3635, + 3219, 2777, 3635, + 3219, 2777, 3635, + 3217, 2781, 3633, + 3213, 2783, 3633, + 3209, 2787, 3631, + 3205, 2791, 3631, + 3199, 2799, 3629, + 3189, 2807, 3625, + 3177, 2819, 3623, + 3161, 2835, 3617, + 3137, 2853, 3611, + 3103, 2879, 3601, + 3053, 2909, 3589, + 2977, 2947, 3573, + 2849, 2995, 3549, + 2591, 3051, 3515, + 0, 3115, 3465, + 0, 3191, 3389, + 0, 3275, 3261, + 0, 3367, 3005, + 0, 3467, 0, + 0, 3573, 0, + 0, 3685, 0, + 0, 3803, 0, + 0, 3923, 0, + 0, 4045, 0, + 3225, 2773, 3637, + 3223, 2773, 3637, + 3223, 2773, 3635, + 3223, 2773, 3635, + 3223, 2773, 3635, + 3221, 2775, 3635, + 3221, 2777, 3635, + 3219, 2777, 3635, + 3217, 2779, 3633, + 3215, 2783, 3633, + 3211, 2787, 3633, + 3205, 2791, 3631, + 3199, 2799, 3629, + 3191, 2807, 3625, + 3177, 2819, 3623, + 3161, 2833, 3617, + 3137, 2853, 3611, + 3103, 2877, 3601, + 3053, 2909, 3589, + 2977, 2947, 3573, + 2851, 2995, 3549, + 2593, 3051, 3515, + 0, 3115, 3465, + 0, 3191, 3389, + 0, 3275, 3261, + 0, 3367, 3005, + 0, 3467, 0, + 0, 3573, 0, + 0, 3685, 0, + 0, 3803, 0, + 0, 3923, 0, + 0, 4045, 0, + 3225, 2771, 3637, + 3225, 2773, 3637, + 3225, 2773, 3637, + 3225, 2773, 3637, + 3223, 2773, 3635, + 3223, 2775, 3635, + 3221, 2775, 3635, + 3221, 2777, 3635, + 3219, 2779, 3635, + 3215, 2783, 3633, + 3211, 2787, 3633, + 3207, 2791, 3631, + 3201, 2799, 3629, + 3191, 2807, 3627, + 3179, 2819, 3623, + 3163, 2833, 3617, + 3139, 2853, 3611, + 3105, 2877, 3603, + 3055, 2909, 3589, + 2979, 2947, 3573, + 2853, 2995, 3549, + 2597, 3049, 3515, + 0, 3115, 3465, + 0, 3191, 3389, + 0, 3275, 3263, + 0, 3367, 3007, + 0, 3467, 0, + 0, 3573, 0, + 0, 3685, 0, + 0, 3803, 0, + 0, 3923, 0, + 0, 4045, 0, + 3227, 2771, 3637, + 3227, 2773, 3637, + 3225, 2773, 3637, + 3225, 2773, 3637, + 3225, 2773, 3637, + 3225, 2775, 3637, + 3223, 2775, 3635, + 3221, 2777, 3635, + 3219, 2779, 3635, + 3217, 2783, 3633, + 3213, 2787, 3633, + 3209, 2791, 3631, + 3201, 2799, 3629, + 3193, 2807, 3627, + 3181, 2819, 3623, + 3163, 2833, 3619, + 3141, 2853, 3611, + 3107, 2877, 3603, + 3057, 2909, 3591, + 2981, 2947, 3573, + 2855, 2993, 3549, + 2603, 3049, 3515, + 240, 3115, 3467, + 0, 3191, 3391, + 0, 3275, 3263, + 0, 3367, 3007, + 0, 3467, 0, + 0, 3573, 0, + 0, 3685, 0, + 0, 3803, 0, + 0, 3923, 0, + 0, 4045, 0, + 3229, 2771, 3637, + 3229, 2771, 3637, + 3227, 2773, 3637, + 3227, 2773, 3637, + 3227, 2773, 3637, + 3225, 2775, 3637, + 3225, 2775, 3637, + 3223, 2777, 3635, + 3221, 2779, 3635, + 3219, 2783, 3635, + 3215, 2787, 3633, + 3211, 2791, 3631, + 3203, 2797, 3629, + 3195, 2807, 3627, + 3183, 2819, 3623, + 3165, 2833, 3619, + 3143, 2853, 3611, + 3109, 2877, 3603, + 3059, 2909, 3591, + 2985, 2947, 3573, + 2861, 2993, 3551, + 2611, 3049, 3517, + 861, 3115, 3467, + 0, 3191, 3391, + 0, 3275, 3265, + 0, 3367, 3009, + 0, 3467, 0, + 0, 3573, 0, + 0, 3685, 0, + 0, 3803, 0, + 0, 3923, 0, + 0, 4045, 0, + 3231, 2771, 3639, + 3231, 2771, 3637, + 3231, 2771, 3637, + 3229, 2773, 3637, + 3229, 2773, 3637, + 3229, 2773, 3637, + 3227, 2775, 3637, + 3225, 2777, 3637, + 3223, 2779, 3635, + 3221, 2781, 3635, + 3217, 2785, 3633, + 3213, 2791, 3633, + 3207, 2797, 3631, + 3197, 2807, 3627, + 3185, 2819, 3625, + 3169, 2833, 3619, + 3145, 2853, 3613, + 3113, 2877, 3603, + 3063, 2909, 3591, + 2989, 2947, 3575, + 2865, 2993, 3551, + 2619, 3049, 3517, + 1175, 3115, 3467, + 0, 3189, 3393, + 0, 3275, 3267, + 0, 3367, 3013, + 0, 3467, 0, + 0, 3573, 0, + 0, 3685, 0, + 0, 3803, 0, + 0, 3923, 0, + 0, 4045, 0, + 3235, 2771, 3639, + 3233, 2771, 3639, + 3233, 2771, 3639, + 3233, 2771, 3639, + 3233, 2773, 3639, + 3231, 2773, 3639, + 3231, 2775, 3637, + 3229, 2777, 3637, + 3227, 2779, 3637, + 3225, 2781, 3635, + 3221, 2785, 3635, + 3217, 2791, 3633, + 3209, 2797, 3631, + 3201, 2807, 3629, + 3189, 2817, 3625, + 3173, 2833, 3621, + 3149, 2853, 3613, + 3117, 2877, 3605, + 3069, 2907, 3593, + 2995, 2947, 3575, + 2873, 2993, 3553, + 2633, 3049, 3519, + 1408, 3115, 3469, + 0, 3189, 3393, + 0, 3273, 3269, + 0, 3367, 3015, + 0, 3467, 831, + 0, 3573, 0, + 0, 3685, 0, + 0, 3803, 0, + 0, 3923, 0, + 0, 4045, 0, + 3239, 2771, 3641, + 3239, 2771, 3641, + 3237, 2771, 3639, + 3237, 2771, 3639, + 3237, 2771, 3639, + 3237, 2773, 3639, + 3235, 2775, 3639, + 3233, 2775, 3639, + 3231, 2777, 3637, + 3229, 2781, 3637, + 3225, 2785, 3637, + 3221, 2789, 3635, + 3215, 2797, 3633, + 3205, 2805, 3629, + 3193, 2817, 3627, + 3177, 2833, 3621, + 3155, 2851, 3615, + 3123, 2877, 3607, + 3075, 2907, 3593, + 3001, 2947, 3577, + 2883, 2993, 3553, + 2649, 3049, 3519, + 1603, 3115, 3471, + 0, 3189, 3395, + 0, 3273, 3271, + 0, 3367, 3021, + 0, 3467, 1205, + 0, 3573, 0, + 0, 3685, 0, + 0, 3803, 0, + 0, 3923, 0, + 0, 4045, 0, + 3245, 2769, 3641, + 3245, 2769, 3641, + 3243, 2769, 3641, + 3243, 2771, 3641, + 3243, 2771, 3641, + 3241, 2773, 3641, + 3241, 2773, 3641, + 3239, 2775, 3641, + 3237, 2777, 3639, + 3235, 2781, 3639, + 3231, 2783, 3637, + 3227, 2789, 3637, + 3221, 2795, 3635, + 3211, 2805, 3631, + 3201, 2817, 3627, + 3185, 2831, 3623, + 3161, 2851, 3617, + 3129, 2875, 3607, + 3083, 2907, 3595, + 3011, 2945, 3579, + 2895, 2993, 3555, + 2669, 3049, 3523, + 1777, 3115, 3473, + 0, 3189, 3399, + 0, 3273, 3275, + 0, 3367, 3027, + 0, 3467, 1459, + 0, 3573, 0, + 0, 3685, 0, + 0, 3801, 0, + 0, 3923, 0, + 0, 4045, 0, + 3251, 2769, 3643, + 3251, 2769, 3643, + 3251, 2769, 3643, + 3251, 2769, 3643, + 3251, 2771, 3643, + 3249, 2771, 3643, + 3249, 2773, 3643, + 3247, 2773, 3643, + 3245, 2777, 3641, + 3243, 2779, 3641, + 3239, 2783, 3639, + 3235, 2789, 3639, + 3229, 2795, 3637, + 3221, 2803, 3633, + 3209, 2815, 3631, + 3193, 2831, 3625, + 3171, 2851, 3619, + 3139, 2875, 3611, + 3093, 2907, 3597, + 3025, 2945, 3581, + 2911, 2991, 3557, + 2695, 3047, 3525, + 1938, 3113, 3477, + 0, 3189, 3403, + 0, 3273, 3279, + 0, 3365, 3035, + 0, 3467, 1665, + 0, 3573, 0, + 0, 3685, 0, + 0, 3801, 0, + 0, 3923, 0, + 0, 4045, 0, + 3261, 2767, 3647, + 3261, 2767, 3647, + 3261, 2767, 3647, + 3261, 2767, 3647, + 3261, 2769, 3647, + 3259, 2769, 3645, + 3259, 2771, 3645, + 3257, 2773, 3645, + 3255, 2775, 3645, + 3253, 2777, 3643, + 3249, 2781, 3643, + 3245, 2787, 3641, + 3239, 2793, 3639, + 3231, 2803, 3637, + 3219, 2815, 3633, + 3205, 2829, 3629, + 3183, 2849, 3621, + 3151, 2873, 3613, + 3107, 2905, 3601, + 3041, 2943, 3585, + 2933, 2991, 3561, + 2729, 3047, 3529, + 2091, 3113, 3481, + 0, 3189, 3407, + 0, 3273, 3285, + 0, 3365, 3045, + 0, 3465, 1846, + 0, 3573, 0, + 0, 3685, 0, + 0, 3801, 0, + 0, 3921, 0, + 0, 4045, 0, + 3275, 2765, 3651, + 3275, 2765, 3651, + 3275, 2765, 3651, + 3273, 2765, 3651, + 3273, 2767, 3649, + 3273, 2767, 3649, + 3271, 2769, 3649, + 3271, 2771, 3649, + 3269, 2773, 3649, + 3267, 2775, 3647, + 3263, 2779, 3647, + 3259, 2785, 3645, + 3253, 2791, 3643, + 3245, 2801, 3641, + 3233, 2813, 3637, + 3219, 2827, 3633, + 3197, 2847, 3625, + 3169, 2873, 3617, + 3125, 2903, 3605, + 3061, 2943, 3589, + 2959, 2989, 3565, + 2769, 3047, 3533, + 2237, 3111, 3485, + 0, 3187, 3413, + 0, 3271, 3293, + 0, 3365, 3059, + 0, 3465, 2011, + 0, 3573, 0, + 0, 3685, 0, + 0, 3801, 0, + 0, 3921, 0, + 0, 4045, 0, + 3291, 2763, 3655, + 3291, 2763, 3655, + 3291, 2763, 3655, + 3291, 2763, 3655, + 3291, 2763, 3655, + 3289, 2765, 3655, + 3289, 2767, 3655, + 3287, 2767, 3653, + 3285, 2771, 3653, + 3283, 2773, 3653, + 3281, 2777, 3651, + 3275, 2783, 3651, + 3271, 2789, 3649, + 3263, 2799, 3645, + 3253, 2809, 3643, + 3237, 2825, 3637, + 3217, 2845, 3631, + 3189, 2871, 3623, + 3149, 2901, 3611, + 3089, 2941, 3595, + 2991, 2989, 3571, + 2819, 3045, 3539, + 2381, 3111, 3493, + 0, 3187, 3421, + 0, 3271, 3305, + 0, 3365, 3077, + 0, 3465, 2167, + 0, 3571, 0, + 0, 3685, 0, + 0, 3801, 0, + 0, 3921, 0, + 0, 4045, 0, + 3313, 2759, 3663, + 3313, 2759, 3661, + 3313, 2759, 3661, + 3313, 2759, 3661, + 3311, 2761, 3661, + 3311, 2761, 3661, + 3311, 2763, 3661, + 3309, 2765, 3661, + 3307, 2767, 3659, + 3305, 2769, 3659, + 3303, 2773, 3659, + 3299, 2779, 3657, + 3293, 2785, 3655, + 3285, 2795, 3653, + 3275, 2807, 3649, + 3261, 2823, 3645, + 3243, 2841, 3639, + 3217, 2867, 3629, + 3179, 2899, 3619, + 3121, 2939, 3603, + 3033, 2985, 3579, + 2877, 3043, 3549, + 2521, 3109, 3503, + 0, 3185, 3433, + 0, 3269, 3319, + 0, 3363, 3101, + 0, 3465, 2315, + 0, 3571, 0, + 0, 3683, 0, + 0, 3801, 0, + 0, 3921, 0, + 0, 4045, 0, + 3341, 2753, 3671, + 3341, 2753, 3671, + 3341, 2755, 3671, + 3339, 2755, 3671, + 3339, 2755, 3671, + 3339, 2757, 3671, + 3337, 2757, 3669, + 3337, 2759, 3669, + 3335, 2761, 3669, + 3333, 2765, 3667, + 3331, 2769, 3667, + 3327, 2775, 3665, + 3321, 2781, 3663, + 3315, 2791, 3661, + 3305, 2803, 3657, + 3293, 2817, 3653, + 3275, 2837, 3647, + 3249, 2863, 3639, + 3215, 2895, 3627, + 3163, 2935, 3613, + 3081, 2983, 3591, + 2945, 3041, 3559, + 2659, 3107, 3515, + 0, 3183, 3447, + 0, 3269, 3337, + 0, 3363, 3131, + 0, 3463, 2459, + 0, 3571, 0, + 0, 3683, 0, + 0, 3801, 0, + 0, 3921, 0, + 0, 4045, 0, + 3375, 2747, 3683, + 3375, 2747, 3683, + 3375, 2747, 3681, + 3373, 2749, 3681, + 3373, 2749, 3681, + 3373, 2751, 3681, + 3373, 2751, 3681, + 3371, 2753, 3681, + 3369, 2755, 3681, + 3367, 2759, 3679, + 3365, 2763, 3679, + 3361, 2767, 3677, + 3357, 2775, 3675, + 3351, 2785, 3673, + 3341, 2797, 3669, + 3331, 2813, 3665, + 3313, 2833, 3659, + 3291, 2859, 3651, + 3259, 2891, 3641, + 3213, 2931, 3625, + 3141, 2979, 3603, + 3023, 3037, 3573, + 2795, 3103, 3531, + 1857, 3181, 3465, + 0, 3267, 3361, + 0, 3361, 3167, + 0, 3461, 2601, + 0, 3569, 0, + 0, 3683, 0, + 0, 3799, 0, + 0, 3921, 0, + 0, 4043, 0, + 3417, 2739, 3697, + 3417, 2739, 3697, + 3417, 2739, 3697, + 3415, 2739, 3697, + 3415, 2741, 3697, + 3415, 2741, 3697, + 3415, 2743, 3695, + 3413, 2745, 3695, + 3413, 2747, 3695, + 3411, 2749, 3695, + 3407, 2753, 3693, + 3405, 2759, 3691, + 3401, 2767, 3691, + 3395, 2777, 3687, + 3387, 2789, 3685, + 3377, 2805, 3681, + 3361, 2825, 3675, + 3341, 2851, 3667, + 3313, 2885, 3657, + 3271, 2925, 3641, + 3209, 2973, 3621, + 3109, 3033, 3593, + 2929, 3099, 3551, + 2455, 3177, 3489, + 0, 3263, 3389, + 0, 3359, 3211, + 0, 3459, 2739, + 0, 3569, 0, + 0, 3681, 0, + 0, 3799, 0, + 0, 3919, 0, + 0, 4043, 0, + 3467, 2727, 3715, + 3467, 2727, 3715, + 3467, 2727, 3715, + 3467, 2727, 3715, + 3467, 2729, 3715, + 3465, 2729, 3715, + 3465, 2731, 3715, + 3465, 2733, 3715, + 3463, 2735, 3713, + 3461, 2737, 3713, + 3459, 2743, 3713, + 3457, 2747, 3711, + 3453, 2755, 3709, + 3447, 2765, 3707, + 3441, 2777, 3705, + 3431, 2795, 3701, + 3419, 2815, 3695, + 3401, 2841, 3687, + 3375, 2875, 3677, + 3339, 2917, 3663, + 3287, 2967, 3643, + 3205, 3025, 3617, + 3065, 3095, 3577, + 2765, 3173, 3519, + 0, 3259, 3427, + 0, 3355, 3265, + 0, 3457, 2875, + 0, 3567, 0, + 0, 3679, 0, + 0, 3797, 0, + 0, 3919, 0, + 0, 4043, 0, + 3527, 2709, 3741, + 3527, 2709, 3741, + 3527, 2711, 3739, + 3527, 2711, 3739, + 3527, 2711, 3739, + 3527, 2713, 3739, + 3525, 2713, 3739, + 3525, 2715, 3739, + 3523, 2719, 3739, + 3523, 2721, 3737, + 3521, 2727, 3737, + 3519, 2731, 3735, + 3515, 2739, 3735, + 3511, 2749, 3731, + 3505, 2763, 3729, + 3497, 2779, 3725, + 3485, 2801, 3719, + 3469, 2829, 3713, + 3447, 2863, 3703, + 3417, 2905, 3691, + 3373, 2957, 3671, + 3307, 3017, 3647, + 3199, 3087, 3609, + 2997, 3167, 3555, + 2367, 3255, 3471, + 0, 3351, 3327, + 0, 3455, 3011, + 0, 3563, 0, + 0, 3677, 0, + 0, 3797, 0, + 0, 3917, 0, + 0, 4041, 0, + 3597, 2685, 3771, + 3597, 2687, 3771, + 3597, 2687, 3771, + 3597, 2687, 3771, + 3597, 2689, 3771, + 3595, 2689, 3771, + 3595, 2691, 3769, + 3595, 2693, 3769, + 3593, 2695, 3769, + 3593, 2699, 3769, + 3591, 2703, 3767, + 3589, 2709, 3767, + 3587, 2717, 3765, + 3583, 2729, 3763, + 3577, 2741, 3761, + 3571, 2759, 3757, + 3561, 2783, 3751, + 3547, 2811, 3745, + 3529, 2847, 3737, + 3505, 2891, 3725, + 3469, 2943, 3707, + 3415, 3005, 3683, + 3331, 3077, 3649, + 3191, 3157, 3601, + 2885, 3247, 3525, + 0, 3345, 3399, + 0, 3449, 3145, + 0, 3559, 611, + 0, 3675, 0, + 0, 3795, 0, + 0, 3917, 0, + 0, 4041, 0, + 3675, 2653, 3809, + 3675, 2653, 3809, + 3675, 2653, 3809, + 3675, 2655, 3809, + 3675, 2655, 3809, + 3675, 2657, 3807, + 3675, 2657, 3807, + 3675, 2659, 3807, + 3673, 2663, 3807, + 3673, 2667, 3807, + 3671, 2671, 3805, + 3669, 2677, 3805, + 3667, 2687, 3803, + 3663, 2697, 3801, + 3659, 2713, 3799, + 3653, 2731, 3795, + 3645, 2755, 3791, + 3635, 2785, 3785, + 3621, 2823, 3777, + 3599, 2869, 3765, + 3571, 2925, 3751, + 3529, 2989, 3729, + 3465, 3063, 3699, + 3363, 3147, 3655, + 3179, 3239, 3589, + 2675, 3337, 3481, + 0, 3443, 3281, + 0, 3555, 2665, + 0, 3671, 0, + 0, 3791, 0, + 0, 3913, 0, + 0, 4039, 0, + 3763, 2603, 3855, + 3763, 2605, 3855, + 3763, 2605, 3855, + 3763, 2605, 3855, + 3763, 2607, 3855, + 3763, 2607, 3855, + 3763, 2609, 3853, + 3763, 2611, 3853, + 3761, 2615, 3853, + 3761, 2619, 3853, + 3759, 2625, 3853, + 3759, 2631, 3851, + 3757, 2641, 3849, + 3753, 2653, 3849, + 3751, 2671, 3847, + 3745, 2691, 3843, + 3739, 2717, 3839, + 3731, 2751, 3833, + 3719, 2791, 3827, + 3701, 2839, 3817, + 3679, 2899, 3803, + 3645, 2967, 3783, + 3597, 3043, 3757, + 3525, 3131, 3719, + 3403, 3225, 3661, + 3163, 3327, 3571, + 1971, 3435, 3413, + 0, 3549, 3047, + 0, 3667, 0, + 0, 3787, 0, + 0, 3911, 0, + 0, 4037, 0, + 3859, 2529, 3909, + 3859, 2529, 3909, + 3859, 2531, 3909, + 3859, 2531, 3909, + 3859, 2533, 3909, + 3859, 2533, 3909, + 3859, 2535, 3909, + 3859, 2539, 3909, + 3859, 2543, 3909, + 3857, 2547, 3909, + 3857, 2553, 3907, + 3855, 2561, 3907, + 3853, 2573, 3905, + 3851, 2587, 3905, + 3849, 2607, 3903, + 3845, 2629, 3899, + 3839, 2659, 3897, + 3833, 2697, 3891, + 3823, 2743, 3885, + 3811, 2797, 3875, + 3793, 2861, 3863, + 3767, 2935, 3847, + 3731, 3017, 3825, + 3677, 3109, 3791, + 3593, 3207, 3743, + 3451, 3313, 3669, + 3141, 3425, 3547, + 0, 3541, 3305, + 0, 3659, 2036, + 0, 3783, 0, + 0, 3907, 0, + 0, 4033, 0, + 3963, 2405, 3975, + 3963, 2405, 3975, + 3963, 2407, 3975, + 3963, 2407, 3975, + 3963, 2409, 3975, + 3963, 2411, 3975, + 3963, 2413, 3973, + 3961, 2417, 3973, + 3961, 2423, 3973, + 3961, 2429, 3973, + 3961, 2437, 3973, + 3959, 2447, 3971, + 3959, 2461, 3971, + 3957, 2481, 3969, + 3955, 2503, 3967, + 3951, 2533, 3965, + 3947, 2571, 3963, + 3941, 2615, 3959, + 3935, 2669, 3953, + 3923, 2733, 3945, + 3909, 2805, 3935, + 3891, 2887, 3921, + 3863, 2979, 3901, + 3823, 3077, 3873, + 3765, 3183, 3833, + 3671, 3293, 3773, + 3507, 3409, 3679, + 3111, 3529, 3513, + 0, 3651, 3101, + 0, 3775, 0, + 0, 3901, 0, + 0, 4029, 0, + 4073, 2157, 4049, + 4073, 2157, 4049, + 4071, 2159, 4049, + 4071, 2161, 4049, + 4071, 2163, 4049, + 4071, 2167, 4049, + 4071, 2173, 4049, + 4071, 2179, 4049, + 4071, 2187, 4047, + 4071, 2197, 4047, + 4071, 2211, 4047, + 4069, 2229, 4047, + 4069, 2251, 4045, + 4067, 2281, 4045, + 4065, 2317, 4043, + 4063, 2361, 4041, + 4059, 2413, 4039, + 4055, 2475, 4035, + 4049, 2547, 4031, + 4041, 2629, 4025, + 4031, 2719, 4015, + 4015, 2815, 4003, + 3995, 2921, 3987, + 3967, 3031, 3965, + 3923, 3147, 3931, + 3861, 3265, 3885, + 3759, 3387, 3813, + 3573, 3511, 3693, + 3067, 3639, 3463, + 0, 3765, 2465, + 0, 3895, 0, + 0, 4025, 0, + 4095, 559, 4095, + 4095, 596, 4095, + 4095, 640, 4095, + 4095, 693, 4095, + 4095, 756, 4095, + 4095, 828, 4095, + 4095, 909, 4095, + 4095, 999, 4095, + 4095, 1097, 4095, + 4095, 1202, 4095, + 4095, 1313, 4095, + 4095, 1428, 4095, + 4095, 1547, 4095, + 4095, 1669, 4095, + 4095, 1794, 4095, + 4095, 1920, 4095, + 4095, 2049, 4095, + 4095, 2177, 4095, + 4095, 2307, 4095, + 4095, 2437, 4095, + 4095, 2567, 4095, + 4095, 2699, 4095, + 4095, 2831, 4081, + 4095, 2961, 4063, + 4075, 3093, 4037, + 4031, 3225, 4001, + 3963, 3357, 3945, + 3855, 3489, 3859, + 3649, 3621, 3711, + 3001, 3753, 3385, + 0, 3885, 0, + 0, 4017, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 1079, 4095, + 4095, 1889, 4095, + 4095, 2229, 4095, + 4095, 2471, 4095, + 4095, 2671, 4095, + 4095, 2849, 4095, + 4095, 3011, 4095, + 4095, 3165, 4095, + 4095, 3313, 4077, + 4073, 3457, 4015, + 3957, 3597, 3915, + 3735, 3735, 3735, + 2891, 3871, 3255, + 0, 4007, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 1549, 4095, + 4095, 2299, 4095, + 4095, 2631, 4095, + 4095, 2871, 4095, + 4095, 3069, 4095, + 4095, 3247, 4095, + 4095, 3409, 4095, + 4095, 3563, 4095, + 4067, 3709, 3981, + 3829, 3853, 3765, + 2689, 3993, 2989, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 1862, 4095, + 4095, 2573, 4095, + 4095, 2901, 4095, + 4095, 3139, 4095, + 4095, 3337, 4095, + 4095, 3511, 4095, + 4095, 3673, 4095, + 4095, 3827, 4057, + 3929, 3975, 3801, + 3355, 2905, 3767, + 3353, 2905, 3767, + 3353, 2905, 3767, + 3353, 2905, 3767, + 3353, 2905, 3767, + 3353, 2907, 3767, + 3351, 2907, 3767, + 3351, 2909, 3767, + 3349, 2911, 3767, + 3347, 2913, 3765, + 3345, 2915, 3765, + 3341, 2919, 3763, + 3335, 2925, 3763, + 3329, 2931, 3761, + 3319, 2939, 3757, + 3307, 2951, 3753, + 3291, 2967, 3749, + 3267, 2985, 3743, + 3233, 3011, 3733, + 3183, 3041, 3721, + 3105, 3079, 3703, + 2977, 3127, 3681, + 2715, 3183, 3647, + 0, 3247, 3597, + 0, 3323, 3521, + 0, 3407, 3393, + 0, 3499, 3135, + 0, 3599, 0, + 0, 3705, 0, + 0, 3817, 0, + 0, 3935, 0, + 0, 4055, 0, + 3355, 2905, 3767, + 3355, 2905, 3767, + 3353, 2905, 3767, + 3353, 2905, 3767, + 3353, 2905, 3767, + 3353, 2907, 3767, + 3351, 2907, 3767, + 3351, 2909, 3767, + 3349, 2911, 3767, + 3347, 2913, 3765, + 3345, 2915, 3765, + 3341, 2919, 3763, + 3335, 2925, 3763, + 3329, 2931, 3761, + 3321, 2939, 3757, + 3307, 2951, 3753, + 3291, 2967, 3749, + 3267, 2985, 3743, + 3233, 3011, 3733, + 3183, 3041, 3721, + 3105, 3079, 3703, + 2977, 3127, 3681, + 2717, 3183, 3647, + 0, 3247, 3597, + 0, 3323, 3521, + 0, 3407, 3393, + 0, 3499, 3135, + 0, 3599, 0, + 0, 3705, 0, + 0, 3817, 0, + 0, 3935, 0, + 0, 4055, 0, + 3355, 2905, 3767, + 3355, 2905, 3767, + 3355, 2905, 3767, + 3353, 2905, 3767, + 3353, 2905, 3767, + 3353, 2907, 3767, + 3351, 2907, 3767, + 3351, 2909, 3767, + 3349, 2911, 3767, + 3347, 2913, 3765, + 3345, 2915, 3765, + 3341, 2919, 3763, + 3337, 2925, 3763, + 3329, 2931, 3761, + 3321, 2939, 3757, + 3309, 2951, 3753, + 3291, 2967, 3749, + 3267, 2985, 3743, + 3233, 3011, 3733, + 3183, 3041, 3721, + 3107, 3079, 3705, + 2979, 3127, 3681, + 2719, 3183, 3647, + 0, 3247, 3597, + 0, 3323, 3521, + 0, 3407, 3393, + 0, 3499, 3135, + 0, 3599, 0, + 0, 3705, 0, + 0, 3817, 0, + 0, 3935, 0, + 0, 4055, 0, + 3355, 2905, 3767, + 3355, 2905, 3767, + 3355, 2905, 3767, + 3355, 2905, 3767, + 3353, 2905, 3767, + 3353, 2907, 3767, + 3353, 2907, 3767, + 3351, 2909, 3767, + 3349, 2911, 3767, + 3347, 2913, 3765, + 3345, 2915, 3765, + 3341, 2919, 3763, + 3337, 2925, 3763, + 3329, 2931, 3761, + 3321, 2939, 3757, + 3309, 2951, 3753, + 3291, 2967, 3749, + 3267, 2985, 3743, + 3233, 3011, 3733, + 3183, 3041, 3721, + 3107, 3079, 3705, + 2979, 3127, 3681, + 2721, 3183, 3647, + 0, 3247, 3597, + 0, 3323, 3521, + 0, 3407, 3393, + 0, 3499, 3135, + 0, 3599, 0, + 0, 3705, 0, + 0, 3817, 0, + 0, 3935, 0, + 0, 4055, 0, + 3355, 2905, 3769, + 3355, 2905, 3769, + 3355, 2905, 3769, + 3355, 2905, 3767, + 3355, 2905, 3767, + 3353, 2907, 3767, + 3353, 2907, 3767, + 3351, 2909, 3767, + 3351, 2909, 3767, + 3349, 2913, 3765, + 3345, 2915, 3765, + 3343, 2919, 3763, + 3337, 2923, 3763, + 3331, 2931, 3761, + 3321, 2939, 3757, + 3309, 2951, 3755, + 3293, 2967, 3749, + 3269, 2985, 3743, + 3235, 3011, 3733, + 3185, 3041, 3721, + 3109, 3079, 3705, + 2981, 3127, 3681, + 2723, 3183, 3647, + 0, 3247, 3597, + 0, 3323, 3521, + 0, 3407, 3393, + 0, 3499, 3137, + 0, 3599, 0, + 0, 3705, 0, + 0, 3817, 0, + 0, 3935, 0, + 0, 4055, 0, + 3357, 2903, 3769, + 3357, 2905, 3769, + 3355, 2905, 3769, + 3355, 2905, 3769, + 3355, 2905, 3767, + 3355, 2907, 3767, + 3353, 2907, 3767, + 3353, 2909, 3767, + 3351, 2909, 3767, + 3349, 2913, 3767, + 3347, 2915, 3765, + 3343, 2919, 3765, + 3337, 2923, 3763, + 3331, 2931, 3761, + 3323, 2939, 3757, + 3311, 2951, 3755, + 3293, 2967, 3749, + 3269, 2985, 3743, + 3235, 3011, 3733, + 3185, 3041, 3721, + 3109, 3079, 3705, + 2983, 3127, 3681, + 2725, 3183, 3647, + 0, 3247, 3597, + 0, 3323, 3521, + 0, 3407, 3393, + 0, 3499, 3137, + 0, 3599, 0, + 0, 3705, 0, + 0, 3817, 0, + 0, 3935, 0, + 0, 4055, 0, + 3357, 2903, 3769, + 3357, 2905, 3769, + 3357, 2905, 3769, + 3357, 2905, 3769, + 3357, 2905, 3769, + 3355, 2905, 3769, + 3355, 2907, 3767, + 3353, 2909, 3767, + 3353, 2909, 3767, + 3351, 2911, 3767, + 3347, 2915, 3765, + 3343, 2919, 3765, + 3339, 2923, 3763, + 3333, 2931, 3761, + 3323, 2939, 3759, + 3311, 2951, 3755, + 3295, 2965, 3749, + 3271, 2985, 3743, + 3237, 3009, 3735, + 3187, 3041, 3721, + 3111, 3079, 3705, + 2985, 3127, 3681, + 2729, 3183, 3647, + 0, 3247, 3597, + 0, 3323, 3521, + 0, 3407, 3395, + 0, 3499, 3139, + 0, 3599, 0, + 0, 3705, 0, + 0, 3817, 0, + 0, 3935, 0, + 0, 4055, 0, + 3359, 2903, 3769, + 3359, 2903, 3769, + 3359, 2905, 3769, + 3359, 2905, 3769, + 3357, 2905, 3769, + 3357, 2905, 3769, + 3357, 2907, 3769, + 3355, 2907, 3767, + 3353, 2909, 3767, + 3351, 2911, 3767, + 3349, 2915, 3765, + 3345, 2919, 3765, + 3341, 2923, 3763, + 3333, 2931, 3761, + 3325, 2939, 3759, + 3313, 2951, 3755, + 3295, 2965, 3751, + 3273, 2985, 3743, + 3239, 3009, 3735, + 3189, 3041, 3723, + 3113, 3079, 3705, + 2987, 3127, 3681, + 2735, 3181, 3647, + 372, 3247, 3599, + 0, 3323, 3523, + 0, 3407, 3395, + 0, 3499, 3139, + 0, 3599, 0, + 0, 3705, 0, + 0, 3817, 0, + 0, 3935, 0, + 0, 4055, 0, + 3361, 2903, 3769, + 3361, 2903, 3769, + 3361, 2903, 3769, + 3359, 2905, 3769, + 3359, 2905, 3769, + 3359, 2905, 3769, + 3359, 2907, 3769, + 3357, 2907, 3769, + 3355, 2909, 3767, + 3353, 2911, 3767, + 3351, 2915, 3767, + 3347, 2919, 3765, + 3343, 2923, 3763, + 3335, 2931, 3761, + 3327, 2939, 3759, + 3315, 2951, 3755, + 3297, 2965, 3751, + 3275, 2985, 3745, + 3241, 3009, 3735, + 3193, 3041, 3723, + 3117, 3079, 3705, + 2993, 3125, 3683, + 2743, 3181, 3649, + 994, 3247, 3599, + 0, 3323, 3523, + 0, 3407, 3397, + 0, 3499, 3141, + 0, 3599, 0, + 0, 3705, 0, + 0, 3817, 0, + 0, 3935, 0, + 0, 4055, 0, + 3363, 2903, 3771, + 3363, 2903, 3771, + 3363, 2903, 3771, + 3363, 2903, 3769, + 3361, 2905, 3769, + 3361, 2905, 3769, + 3361, 2907, 3769, + 3359, 2907, 3769, + 3357, 2909, 3769, + 3357, 2911, 3767, + 3353, 2915, 3767, + 3349, 2917, 3767, + 3345, 2923, 3765, + 3339, 2929, 3763, + 3329, 2939, 3759, + 3317, 2951, 3757, + 3301, 2965, 3751, + 3277, 2985, 3745, + 3245, 3009, 3735, + 3195, 3041, 3723, + 3121, 3079, 3707, + 2997, 3125, 3683, + 2753, 3181, 3649, + 1308, 3247, 3599, + 0, 3323, 3525, + 0, 3407, 3399, + 0, 3499, 3145, + 0, 3599, 0, + 0, 3705, 0, + 0, 3817, 0, + 0, 3935, 0, + 0, 4055, 0, + 3367, 2903, 3771, + 3367, 2903, 3771, + 3367, 2903, 3771, + 3365, 2903, 3771, + 3365, 2903, 3771, + 3365, 2905, 3771, + 3363, 2905, 3771, + 3363, 2907, 3769, + 3361, 2909, 3769, + 3359, 2911, 3769, + 3357, 2913, 3769, + 3353, 2917, 3767, + 3349, 2923, 3765, + 3341, 2929, 3763, + 3333, 2939, 3761, + 3321, 2949, 3757, + 3305, 2965, 3753, + 3281, 2985, 3745, + 3249, 3009, 3737, + 3201, 3041, 3725, + 3127, 3079, 3707, + 3005, 3125, 3685, + 2765, 3181, 3651, + 1540, 3247, 3601, + 0, 3321, 3525, + 0, 3407, 3401, + 0, 3499, 3147, + 0, 3599, 963, + 0, 3705, 0, + 0, 3817, 0, + 0, 3935, 0, + 0, 4055, 0, + 3371, 2901, 3773, + 3371, 2903, 3773, + 3371, 2903, 3773, + 3371, 2903, 3773, + 3369, 2903, 3771, + 3369, 2905, 3771, + 3369, 2905, 3771, + 3367, 2907, 3771, + 3365, 2907, 3771, + 3363, 2911, 3771, + 3361, 2913, 3769, + 3357, 2917, 3769, + 3353, 2921, 3767, + 3347, 2929, 3765, + 3337, 2937, 3763, + 3325, 2949, 3759, + 3309, 2965, 3753, + 3287, 2983, 3747, + 3255, 3009, 3739, + 3207, 3039, 3725, + 3135, 3079, 3709, + 3015, 3125, 3685, + 2781, 3181, 3653, + 1735, 3247, 3603, + 0, 3321, 3527, + 0, 3405, 3403, + 0, 3499, 3153, + 0, 3599, 1337, + 0, 3705, 0, + 0, 3817, 0, + 0, 3935, 0, + 0, 4055, 0, + 3377, 2901, 3773, + 3377, 2901, 3773, + 3377, 2901, 3773, + 3375, 2903, 3773, + 3375, 2903, 3773, + 3375, 2903, 3773, + 3375, 2905, 3773, + 3373, 2905, 3773, + 3371, 2907, 3773, + 3369, 2909, 3771, + 3367, 2913, 3771, + 3363, 2917, 3769, + 3359, 2921, 3769, + 3353, 2927, 3767, + 3345, 2937, 3763, + 3333, 2949, 3761, + 3317, 2963, 3755, + 3293, 2983, 3749, + 3261, 3007, 3739, + 3215, 3039, 3727, + 3143, 3077, 3711, + 3027, 3125, 3687, + 2801, 3181, 3655, + 1909, 3247, 3605, + 0, 3321, 3531, + 0, 3405, 3407, + 0, 3499, 3159, + 0, 3599, 1591, + 0, 3705, 0, + 0, 3817, 0, + 0, 3935, 0, + 0, 4055, 0, + 3385, 2901, 3777, + 3385, 2901, 3775, + 3383, 2901, 3775, + 3383, 2901, 3775, + 3383, 2901, 3775, + 3383, 2903, 3775, + 3381, 2903, 3775, + 3381, 2905, 3775, + 3379, 2905, 3775, + 3377, 2909, 3773, + 3375, 2911, 3773, + 3371, 2915, 3771, + 3367, 2921, 3771, + 3361, 2927, 3769, + 3353, 2935, 3765, + 3341, 2947, 3763, + 3325, 2963, 3757, + 3303, 2983, 3751, + 3271, 3007, 3743, + 3225, 3039, 3731, + 3157, 3077, 3713, + 3043, 3123, 3691, + 2827, 3181, 3657, + 2071, 3245, 3609, + 0, 3321, 3535, + 0, 3405, 3411, + 0, 3499, 3167, + 0, 3599, 1797, + 0, 3705, 0, + 0, 3817, 0, + 0, 3933, 0, + 0, 4055, 0, + 3395, 2899, 3779, + 3393, 2899, 3779, + 3393, 2899, 3779, + 3393, 2899, 3779, + 3393, 2901, 3779, + 3393, 2901, 3779, + 3391, 2901, 3779, + 3391, 2903, 3777, + 3389, 2905, 3777, + 3387, 2907, 3777, + 3385, 2909, 3775, + 3381, 2913, 3775, + 3377, 2919, 3773, + 3371, 2925, 3771, + 3363, 2935, 3769, + 3351, 2947, 3765, + 3337, 2961, 3761, + 3315, 2981, 3755, + 3285, 3005, 3745, + 3239, 3037, 3733, + 3173, 3075, 3717, + 3065, 3123, 3693, + 2861, 3179, 3661, + 2223, 3245, 3613, + 0, 3321, 3539, + 0, 3405, 3417, + 0, 3497, 3177, + 0, 3599, 1978, + 0, 3705, 0, + 0, 3817, 0, + 0, 3933, 0, + 0, 4055, 0, + 3407, 2897, 3783, + 3407, 2897, 3783, + 3407, 2897, 3783, + 3407, 2897, 3783, + 3407, 2899, 3783, + 3405, 2899, 3783, + 3405, 2899, 3781, + 3403, 2901, 3781, + 3403, 2903, 3781, + 3401, 2905, 3781, + 3399, 2907, 3779, + 3395, 2911, 3779, + 3391, 2917, 3777, + 3385, 2923, 3775, + 3377, 2933, 3773, + 3365, 2945, 3769, + 3351, 2959, 3765, + 3331, 2979, 3757, + 3301, 3005, 3749, + 3257, 3035, 3737, + 3193, 3075, 3721, + 3091, 3121, 3699, + 2901, 3179, 3665, + 2369, 3245, 3617, + 0, 3319, 3545, + 0, 3405, 3425, + 0, 3497, 3191, + 0, 3597, 2143, + 0, 3705, 0, + 0, 3817, 0, + 0, 3933, 0, + 0, 4053, 0, + 3423, 2893, 3787, + 3423, 2895, 3787, + 3423, 2895, 3787, + 3423, 2895, 3787, + 3423, 2895, 3787, + 3423, 2897, 3787, + 3421, 2897, 3787, + 3421, 2899, 3787, + 3419, 2899, 3787, + 3417, 2903, 3785, + 3415, 2905, 3785, + 3413, 2909, 3783, + 3409, 2915, 3783, + 3403, 2921, 3781, + 3395, 2931, 3777, + 3385, 2943, 3775, + 3369, 2957, 3769, + 3349, 2977, 3763, + 3321, 3003, 3755, + 3281, 3033, 3743, + 3221, 3073, 3727, + 3123, 3121, 3705, + 2951, 3177, 3671, + 2513, 3243, 3625, + 0, 3319, 3553, + 0, 3403, 3437, + 0, 3497, 3209, + 0, 3597, 2299, + 0, 3705, 0, + 0, 3817, 0, + 0, 3933, 0, + 0, 4053, 0, + 3445, 2891, 3795, + 3445, 2891, 3795, + 3445, 2891, 3795, + 3445, 2891, 3795, + 3445, 2891, 3793, + 3443, 2893, 3793, + 3443, 2893, 3793, + 3443, 2895, 3793, + 3441, 2897, 3793, + 3439, 2899, 3793, + 3437, 2901, 3791, + 3435, 2905, 3791, + 3431, 2911, 3789, + 3425, 2917, 3787, + 3417, 2927, 3785, + 3407, 2939, 3781, + 3395, 2955, 3777, + 3375, 2975, 3771, + 3349, 2999, 3761, + 3311, 3031, 3751, + 3253, 3071, 3735, + 3165, 3119, 3713, + 3009, 3175, 3681, + 2653, 3241, 3635, + 0, 3317, 3565, + 0, 3403, 3451, + 0, 3495, 3233, + 0, 3597, 2447, + 0, 3703, 0, + 0, 3817, 0, + 0, 3933, 0, + 0, 4053, 0, + 3473, 2885, 3803, + 3473, 2885, 3803, + 3473, 2887, 3803, + 3473, 2887, 3803, + 3471, 2887, 3803, + 3471, 2887, 3803, + 3471, 2889, 3803, + 3469, 2889, 3801, + 3469, 2891, 3801, + 3467, 2893, 3801, + 3465, 2897, 3801, + 3463, 2901, 3799, + 3459, 2907, 3797, + 3453, 2913, 3795, + 3447, 2923, 3793, + 3437, 2935, 3789, + 3425, 2951, 3785, + 3407, 2971, 3779, + 3383, 2995, 3771, + 3347, 3027, 3759, + 3295, 3067, 3745, + 3213, 3115, 3723, + 3077, 3173, 3691, + 2791, 3239, 3647, + 0, 3315, 3579, + 0, 3401, 3469, + 0, 3495, 3263, + 0, 3595, 2591, + 0, 3703, 0, + 0, 3815, 0, + 0, 3933, 0, + 0, 4053, 0, + 3507, 2879, 3815, + 3507, 2879, 3815, + 3507, 2879, 3815, + 3507, 2879, 3815, + 3507, 2881, 3813, + 3505, 2881, 3813, + 3505, 2883, 3813, + 3505, 2883, 3813, + 3503, 2885, 3813, + 3501, 2887, 3813, + 3499, 2891, 3811, + 3497, 2895, 3811, + 3493, 2901, 3809, + 3489, 2907, 3807, + 3483, 2917, 3805, + 3475, 2929, 3801, + 3463, 2945, 3797, + 3447, 2965, 3791, + 3423, 2991, 3783, + 3391, 3023, 3773, + 3345, 3063, 3757, + 3273, 3111, 3735, + 3155, 3169, 3707, + 2927, 3235, 3663, + 1989, 3313, 3597, + 0, 3399, 3493, + 0, 3493, 3299, + 0, 3593, 2733, + 0, 3701, 0, + 0, 3815, 0, + 0, 3931, 0, + 0, 4053, 0, + 3549, 2871, 3829, + 3549, 2871, 3829, + 3549, 2871, 3829, + 3549, 2871, 3829, + 3549, 2871, 3829, + 3547, 2873, 3829, + 3547, 2873, 3829, + 3547, 2875, 3827, + 3545, 2877, 3827, + 3545, 2879, 3827, + 3543, 2881, 3827, + 3541, 2887, 3825, + 3537, 2891, 3825, + 3533, 2899, 3823, + 3527, 2909, 3819, + 3519, 2921, 3817, + 3509, 2937, 3813, + 3493, 2957, 3807, + 3473, 2983, 3799, + 3445, 3017, 3789, + 3403, 3057, 3773, + 3341, 3105, 3753, + 3241, 3165, 3725, + 3061, 3231, 3683, + 2587, 3309, 3621, + 0, 3395, 3521, + 0, 3491, 3343, + 0, 3593, 2871, + 0, 3701, 0, + 0, 3813, 0, + 0, 3931, 0, + 0, 4051, 0, + 3599, 2857, 3849, + 3599, 2859, 3847, + 3599, 2859, 3847, + 3599, 2859, 3847, + 3599, 2859, 3847, + 3599, 2861, 3847, + 3599, 2861, 3847, + 3597, 2863, 3847, + 3597, 2865, 3847, + 3595, 2867, 3847, + 3593, 2871, 3845, + 3591, 2875, 3845, + 3589, 2879, 3843, + 3585, 2887, 3841, + 3579, 2897, 3839, + 3573, 2909, 3837, + 3563, 2927, 3833, + 3551, 2947, 3827, + 3533, 2975, 3819, + 3507, 3007, 3809, + 3471, 3049, 3795, + 3419, 3099, 3775, + 3337, 3157, 3749, + 3197, 3227, 3709, + 2897, 3305, 3651, + 0, 3391, 3559, + 0, 3487, 3397, + 0, 3589, 3007, + 0, 3699, 0, + 0, 3811, 0, + 0, 3929, 0, + 0, 4051, 0, + 3659, 2841, 3873, + 3659, 2841, 3873, + 3659, 2841, 3873, + 3659, 2843, 3873, + 3659, 2843, 3871, + 3659, 2843, 3871, + 3659, 2845, 3871, + 3657, 2847, 3871, + 3657, 2847, 3871, + 3655, 2851, 3871, + 3655, 2853, 3869, + 3653, 2859, 3869, + 3651, 2865, 3867, + 3647, 2871, 3867, + 3643, 2881, 3865, + 3637, 2895, 3861, + 3629, 2911, 3857, + 3617, 2933, 3853, + 3601, 2961, 3845, + 3579, 2995, 3835, + 3549, 3037, 3823, + 3505, 3089, 3805, + 3439, 3149, 3779, + 3331, 3219, 3741, + 3129, 3299, 3687, + 2499, 3387, 3603, + 0, 3483, 3459, + 0, 3587, 3143, + 0, 3695, 0, + 0, 3809, 0, + 0, 3929, 0, + 0, 4049, 0, + 3729, 2817, 3903, + 3729, 2819, 3903, + 3729, 2819, 3903, + 3729, 2819, 3903, + 3729, 2819, 3903, + 3729, 2821, 3903, + 3727, 2821, 3903, + 3727, 2823, 3901, + 3727, 2825, 3901, + 3725, 2827, 3901, + 3725, 2831, 3901, + 3723, 2835, 3899, + 3721, 2841, 3899, + 3719, 2849, 3897, + 3715, 2861, 3895, + 3709, 2875, 3893, + 3703, 2891, 3889, + 3693, 2915, 3883, + 3679, 2943, 3877, + 3661, 2979, 3869, + 3637, 3023, 3857, + 3601, 3075, 3839, + 3547, 3137, 3815, + 3463, 3209, 3781, + 3323, 3291, 3733, + 3017, 3379, 3657, + 0, 3477, 3531, + 0, 3581, 3279, + 0, 3693, 744, + 0, 3807, 0, + 0, 3927, 0, + 0, 4049, 0, + 3809, 2785, 3941, + 3809, 2785, 3941, + 3807, 2785, 3941, + 3807, 2785, 3941, + 3807, 2787, 3941, + 3807, 2787, 3941, + 3807, 2789, 3941, + 3807, 2789, 3939, + 3807, 2791, 3939, + 3805, 2795, 3939, + 3805, 2799, 3939, + 3803, 2803, 3937, + 3801, 2811, 3937, + 3799, 2819, 3935, + 3795, 2831, 3933, + 3791, 2845, 3931, + 3785, 2863, 3927, + 3777, 2887, 3923, + 3767, 2919, 3917, + 3753, 2955, 3909, + 3731, 3001, 3897, + 3703, 3057, 3883, + 3661, 3121, 3861, + 3597, 3195, 3831, + 3495, 3279, 3787, + 3311, 3371, 3721, + 2807, 3469, 3613, + 0, 3575, 3413, + 0, 3687, 2797, + 0, 3803, 0, + 0, 3923, 0, + 0, 4047, 0, + 3897, 2735, 3987, + 3895, 2735, 3987, + 3895, 2737, 3987, + 3895, 2737, 3987, + 3895, 2737, 3987, + 3895, 2739, 3987, + 3895, 2739, 3987, + 3895, 2741, 3987, + 3895, 2743, 3985, + 3893, 2747, 3985, + 3893, 2751, 3985, + 3891, 2757, 3985, + 3891, 2765, 3983, + 3889, 2773, 3983, + 3885, 2787, 3981, + 3883, 2803, 3979, + 3877, 2823, 3975, + 3871, 2849, 3971, + 3863, 2883, 3965, + 3851, 2923, 3959, + 3833, 2973, 3949, + 3811, 3031, 3935, + 3777, 3099, 3915, + 3729, 3177, 3889, + 3657, 3263, 3851, + 3535, 3357, 3793, + 3295, 3459, 3703, + 2103, 3567, 3545, + 0, 3681, 3179, + 0, 3799, 0, + 0, 3919, 0, + 0, 4043, 0, + 3993, 2661, 4041, + 3991, 2661, 4041, + 3991, 2661, 4041, + 3991, 2663, 4041, + 3991, 2663, 4041, + 3991, 2665, 4041, + 3991, 2665, 4041, + 3991, 2667, 4041, + 3991, 2671, 4041, + 3991, 2675, 4041, + 3989, 2679, 4041, + 3989, 2685, 4039, + 3987, 2695, 4039, + 3985, 2705, 4037, + 3983, 2719, 4037, + 3981, 2739, 4035, + 3977, 2763, 4031, + 3971, 2793, 4029, + 3965, 2829, 4023, + 3955, 2875, 4017, + 3943, 2929, 4009, + 3925, 2993, 3997, + 3899, 3067, 3979, + 3863, 3149, 3957, + 3809, 3241, 3923, + 3725, 3339, 3875, + 3583, 3445, 3801, + 3273, 3557, 3679, + 0, 3673, 3437, + 0, 3791, 2169, + 0, 3915, 0, + 0, 4039, 0, + 4095, 2537, 4095, + 4095, 2537, 4095, + 4095, 2537, 4095, + 4095, 2539, 4095, + 4095, 2539, 4095, + 4095, 2541, 4095, + 4095, 2543, 4095, + 4095, 2545, 4095, + 4095, 2549, 4095, + 4093, 2555, 4095, + 4093, 2561, 4095, + 4093, 2569, 4095, + 4091, 2579, 4095, + 4091, 2595, 4095, + 4089, 2613, 4095, + 4087, 2635, 4095, + 4083, 2665, 4095, + 4079, 2703, 4095, + 4073, 2747, 4091, + 4067, 2801, 4085, + 4055, 2865, 4077, + 4041, 2937, 4067, + 4023, 3019, 4053, + 3995, 3111, 4033, + 3955, 3209, 4005, + 3897, 3315, 3965, + 3803, 3425, 3907, + 3639, 3541, 3811, + 3243, 3661, 3645, + 0, 3783, 3235, + 0, 3907, 0, + 0, 4033, 0, + 4095, 2287, 4095, + 4095, 2289, 4095, + 4095, 2289, 4095, + 4095, 2291, 4095, + 4095, 2293, 4095, + 4095, 2295, 4095, + 4095, 2299, 4095, + 4095, 2305, 4095, + 4095, 2311, 4095, + 4095, 2319, 4095, + 4095, 2329, 4095, + 4095, 2343, 4095, + 4095, 2361, 4095, + 4095, 2383, 4095, + 4095, 2413, 4095, + 4095, 2449, 4095, + 4095, 2493, 4095, + 4095, 2545, 4095, + 4095, 2607, 4095, + 4095, 2679, 4095, + 4095, 2761, 4095, + 4095, 2851, 4095, + 4095, 2949, 4095, + 4095, 3053, 4095, + 4095, 3163, 4095, + 4057, 3279, 4065, + 3993, 3397, 4017, + 3891, 3519, 3945, + 3707, 3643, 3825, + 3199, 3771, 3595, + 0, 3899, 2597, + 0, 4027, 0, + 4095, 662, 4095, + 4095, 691, 4095, + 4095, 728, 4095, + 4095, 772, 4095, + 4095, 825, 4095, + 4095, 888, 4095, + 4095, 960, 4095, + 4095, 1041, 4095, + 4095, 1131, 4095, + 4095, 1229, 4095, + 4095, 1334, 4095, + 4095, 1445, 4095, + 4095, 1560, 4095, + 4095, 1679, 4095, + 4095, 1802, 4095, + 4095, 1926, 4095, + 4095, 2053, 4095, + 4095, 2181, 4095, + 4095, 2309, 4095, + 4095, 2439, 4095, + 4095, 2569, 4095, + 4095, 2699, 4095, + 4095, 2831, 4095, + 4095, 2963, 4095, + 4095, 3093, 4095, + 4095, 3225, 4095, + 4095, 3357, 4095, + 4095, 3489, 4077, + 3987, 3621, 3991, + 3783, 3753, 3843, + 3133, 3885, 3517, + 0, 4017, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 1211, 4095, + 4095, 2021, 4095, + 4095, 2361, 4095, + 4095, 2603, 4095, + 4095, 2803, 4095, + 4095, 2981, 4095, + 4095, 3143, 4095, + 4095, 3297, 4095, + 4095, 3445, 4095, + 4095, 3589, 4095, + 4089, 3729, 4047, + 3867, 3867, 3867, + 3023, 4003, 3387, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 1681, 4095, + 4095, 2431, 4095, + 4095, 2763, 4095, + 4095, 3003, 4095, + 4095, 3203, 4095, + 4095, 3379, 4095, + 4095, 3541, 4095, + 4095, 3695, 4095, + 4095, 3841, 4095, + 3961, 3985, 3897, + 3487, 3037, 3899, + 3487, 3037, 3899, + 3485, 3037, 3899, + 3485, 3037, 3899, + 3485, 3037, 3899, + 3485, 3037, 3899, + 3485, 3039, 3899, + 3483, 3039, 3899, + 3483, 3041, 3899, + 3481, 3043, 3899, + 3479, 3045, 3897, + 3475, 3047, 3897, + 3473, 3051, 3895, + 3467, 3057, 3895, + 3461, 3063, 3893, + 3451, 3071, 3889, + 3439, 3083, 3885, + 3423, 3099, 3881, + 3399, 3117, 3875, + 3365, 3143, 3865, + 3315, 3173, 3853, + 3237, 3211, 3835, + 3109, 3259, 3813, + 2847, 3315, 3779, + 0, 3379, 3729, + 0, 3455, 3653, + 0, 3539, 3525, + 0, 3631, 3267, + 0, 3731, 0, + 0, 3837, 0, + 0, 3951, 0, + 0, 4067, 0, + 3487, 3037, 3899, + 3487, 3037, 3899, + 3485, 3037, 3899, + 3485, 3037, 3899, + 3485, 3037, 3899, + 3485, 3037, 3899, + 3485, 3039, 3899, + 3483, 3039, 3899, + 3483, 3041, 3899, + 3481, 3043, 3899, + 3479, 3045, 3897, + 3477, 3047, 3897, + 3473, 3051, 3895, + 3467, 3057, 3895, + 3461, 3063, 3893, + 3451, 3071, 3889, + 3439, 3083, 3885, + 3423, 3099, 3881, + 3399, 3117, 3875, + 3365, 3143, 3865, + 3315, 3173, 3853, + 3237, 3211, 3835, + 3109, 3259, 3813, + 2849, 3315, 3779, + 0, 3379, 3729, + 0, 3455, 3653, + 0, 3539, 3525, + 0, 3631, 3267, + 0, 3731, 0, + 0, 3837, 0, + 0, 3951, 0, + 0, 4067, 0, + 3487, 3037, 3899, + 3487, 3037, 3899, + 3487, 3037, 3899, + 3485, 3037, 3899, + 3485, 3037, 3899, + 3485, 3037, 3899, + 3485, 3039, 3899, + 3483, 3039, 3899, + 3483, 3041, 3899, + 3481, 3043, 3899, + 3479, 3045, 3897, + 3477, 3047, 3897, + 3473, 3051, 3895, + 3467, 3057, 3895, + 3461, 3063, 3893, + 3453, 3071, 3889, + 3439, 3083, 3885, + 3423, 3099, 3881, + 3399, 3117, 3875, + 3365, 3143, 3865, + 3315, 3173, 3853, + 3239, 3211, 3837, + 3109, 3259, 3813, + 2849, 3315, 3779, + 0, 3379, 3729, + 0, 3455, 3653, + 0, 3539, 3525, + 0, 3631, 3267, + 0, 3731, 0, + 0, 3837, 0, + 0, 3951, 0, + 0, 4067, 0, + 3487, 3037, 3901, + 3487, 3037, 3899, + 3487, 3037, 3899, + 3487, 3037, 3899, + 3485, 3037, 3899, + 3485, 3037, 3899, + 3485, 3039, 3899, + 3485, 3039, 3899, + 3483, 3041, 3899, + 3481, 3043, 3899, + 3479, 3045, 3897, + 3477, 3047, 3897, + 3473, 3051, 3895, + 3469, 3057, 3895, + 3461, 3063, 3893, + 3453, 3071, 3889, + 3441, 3083, 3885, + 3423, 3099, 3881, + 3399, 3117, 3875, + 3365, 3143, 3865, + 3315, 3173, 3853, + 3239, 3211, 3837, + 3111, 3259, 3813, + 2851, 3315, 3779, + 0, 3379, 3729, + 0, 3455, 3653, + 0, 3539, 3525, + 0, 3631, 3267, + 0, 3731, 0, + 0, 3837, 0, + 0, 3951, 0, + 0, 4067, 0, + 3487, 3037, 3901, + 3487, 3037, 3901, + 3487, 3037, 3901, + 3487, 3037, 3899, + 3487, 3037, 3899, + 3485, 3037, 3899, + 3485, 3039, 3899, + 3485, 3039, 3899, + 3483, 3041, 3899, + 3481, 3043, 3899, + 3479, 3045, 3897, + 3477, 3047, 3897, + 3473, 3051, 3895, + 3469, 3057, 3895, + 3463, 3063, 3893, + 3453, 3071, 3889, + 3441, 3083, 3887, + 3423, 3099, 3881, + 3399, 3117, 3875, + 3365, 3143, 3865, + 3315, 3173, 3853, + 3239, 3211, 3837, + 3111, 3259, 3813, + 2853, 3315, 3779, + 0, 3379, 3729, + 0, 3455, 3653, + 0, 3539, 3525, + 0, 3631, 3267, + 0, 3731, 0, + 0, 3837, 0, + 0, 3951, 0, + 0, 4067, 0, + 3487, 3037, 3901, + 3487, 3037, 3901, + 3487, 3037, 3901, + 3487, 3037, 3901, + 3487, 3037, 3901, + 3487, 3037, 3899, + 3485, 3039, 3899, + 3485, 3039, 3899, + 3483, 3041, 3899, + 3483, 3043, 3899, + 3481, 3045, 3899, + 3477, 3047, 3897, + 3475, 3051, 3897, + 3469, 3057, 3895, + 3463, 3063, 3893, + 3453, 3071, 3889, + 3441, 3083, 3887, + 3425, 3099, 3881, + 3401, 3117, 3875, + 3367, 3143, 3865, + 3317, 3173, 3853, + 3241, 3211, 3837, + 3113, 3259, 3813, + 2855, 3315, 3779, + 0, 3379, 3729, + 0, 3455, 3653, + 0, 3539, 3525, + 0, 3631, 3269, + 0, 3731, 0, + 0, 3837, 0, + 0, 3951, 0, + 0, 4067, 0, + 3489, 3035, 3901, + 3489, 3037, 3901, + 3489, 3037, 3901, + 3489, 3037, 3901, + 3487, 3037, 3901, + 3487, 3037, 3901, + 3487, 3039, 3899, + 3485, 3039, 3899, + 3485, 3041, 3899, + 3483, 3041, 3899, + 3481, 3045, 3899, + 3479, 3047, 3897, + 3475, 3051, 3897, + 3471, 3057, 3895, + 3463, 3063, 3893, + 3455, 3071, 3891, + 3443, 3083, 3887, + 3425, 3099, 3881, + 3401, 3117, 3875, + 3367, 3143, 3867, + 3317, 3173, 3853, + 3241, 3211, 3837, + 3115, 3259, 3813, + 2857, 3315, 3779, + 0, 3379, 3729, + 0, 3455, 3653, + 0, 3539, 3527, + 0, 3631, 3269, + 0, 3731, 0, + 0, 3837, 0, + 0, 3949, 0, + 0, 4067, 0, + 3489, 3035, 3901, + 3489, 3035, 3901, + 3489, 3037, 3901, + 3489, 3037, 3901, + 3489, 3037, 3901, + 3489, 3037, 3901, + 3487, 3039, 3901, + 3487, 3039, 3899, + 3485, 3041, 3899, + 3485, 3041, 3899, + 3483, 3045, 3899, + 3479, 3047, 3897, + 3477, 3051, 3897, + 3471, 3055, 3895, + 3465, 3063, 3893, + 3455, 3071, 3891, + 3443, 3083, 3887, + 3427, 3099, 3881, + 3403, 3117, 3875, + 3369, 3143, 3867, + 3319, 3173, 3855, + 3243, 3211, 3837, + 3117, 3259, 3813, + 2861, 3315, 3779, + 0, 3379, 3729, + 0, 3455, 3653, + 0, 3539, 3527, + 0, 3631, 3271, + 0, 3731, 0, + 0, 3837, 0, + 0, 3949, 0, + 0, 4067, 0, + 3491, 3035, 3901, + 3491, 3035, 3901, + 3491, 3035, 3901, + 3491, 3037, 3901, + 3491, 3037, 3901, + 3489, 3037, 3901, + 3489, 3037, 3901, + 3489, 3039, 3901, + 3487, 3041, 3899, + 3485, 3041, 3899, + 3483, 3043, 3899, + 3481, 3047, 3899, + 3477, 3051, 3897, + 3473, 3055, 3895, + 3467, 3063, 3893, + 3457, 3071, 3891, + 3445, 3083, 3887, + 3427, 3097, 3883, + 3405, 3117, 3875, + 3371, 3141, 3867, + 3321, 3173, 3855, + 3245, 3211, 3837, + 3121, 3259, 3813, + 2867, 3315, 3779, + 504, 3379, 3731, + 0, 3455, 3655, + 0, 3539, 3527, + 0, 3631, 3271, + 0, 3731, 0, + 0, 3837, 0, + 0, 3949, 0, + 0, 4067, 0, + 3493, 3035, 3901, + 3493, 3035, 3901, + 3493, 3035, 3901, + 3493, 3037, 3901, + 3493, 3037, 3901, + 3491, 3037, 3901, + 3491, 3037, 3901, + 3491, 3039, 3901, + 3489, 3039, 3901, + 3487, 3041, 3901, + 3485, 3043, 3899, + 3483, 3047, 3899, + 3479, 3051, 3897, + 3475, 3055, 3895, + 3469, 3063, 3893, + 3459, 3071, 3891, + 3447, 3083, 3887, + 3431, 3097, 3883, + 3407, 3117, 3877, + 3373, 3141, 3867, + 3325, 3173, 3855, + 3249, 3211, 3839, + 3125, 3259, 3815, + 2875, 3313, 3781, + 1125, 3379, 3731, + 0, 3455, 3655, + 0, 3539, 3529, + 0, 3631, 3273, + 0, 3731, 0, + 0, 3837, 0, + 0, 3949, 0, + 0, 4067, 0, + 3495, 3035, 3903, + 3495, 3035, 3903, + 3495, 3035, 3903, + 3495, 3035, 3903, + 3495, 3037, 3903, + 3495, 3037, 3901, + 3493, 3037, 3901, + 3493, 3039, 3901, + 3491, 3039, 3901, + 3491, 3041, 3901, + 3489, 3043, 3901, + 3485, 3047, 3899, + 3481, 3051, 3899, + 3477, 3055, 3897, + 3471, 3061, 3895, + 3461, 3071, 3893, + 3449, 3083, 3889, + 3433, 3097, 3883, + 3409, 3117, 3877, + 3377, 3141, 3869, + 3327, 3173, 3855, + 3253, 3211, 3839, + 3129, 3257, 3815, + 2885, 3313, 3781, + 1440, 3379, 3733, + 0, 3455, 3657, + 0, 3539, 3531, + 0, 3631, 3277, + 0, 3731, 0, + 0, 3837, 0, + 0, 3949, 0, + 0, 4067, 0, + 3499, 3035, 3903, + 3499, 3035, 3903, + 3499, 3035, 3903, + 3499, 3035, 3903, + 3497, 3035, 3903, + 3497, 3037, 3903, + 3497, 3037, 3903, + 3495, 3037, 3903, + 3495, 3039, 3903, + 3493, 3041, 3901, + 3491, 3043, 3901, + 3489, 3045, 3901, + 3485, 3049, 3899, + 3481, 3055, 3897, + 3475, 3061, 3895, + 3465, 3071, 3893, + 3453, 3081, 3889, + 3437, 3097, 3885, + 3413, 3117, 3877, + 3381, 3141, 3869, + 3333, 3173, 3857, + 3259, 3211, 3839, + 3137, 3257, 3817, + 2897, 3313, 3783, + 1672, 3379, 3733, + 0, 3455, 3657, + 0, 3539, 3533, + 0, 3631, 3281, + 0, 3731, 1095, + 0, 3837, 0, + 0, 3949, 0, + 0, 4067, 0, + 3503, 3033, 3905, + 3503, 3035, 3905, + 3503, 3035, 3905, + 3503, 3035, 3905, + 3503, 3035, 3905, + 3501, 3035, 3905, + 3501, 3037, 3903, + 3501, 3037, 3903, + 3499, 3039, 3903, + 3497, 3041, 3903, + 3495, 3043, 3903, + 3493, 3045, 3901, + 3489, 3049, 3901, + 3485, 3055, 3899, + 3479, 3061, 3897, + 3471, 3069, 3895, + 3459, 3081, 3891, + 3441, 3097, 3885, + 3419, 3115, 3879, + 3387, 3141, 3871, + 3339, 3171, 3859, + 3267, 3211, 3841, + 3147, 3257, 3817, + 2913, 3313, 3785, + 1867, 3379, 3735, + 0, 3453, 3661, + 0, 3537, 3535, + 0, 3631, 3285, + 0, 3731, 1469, + 0, 3837, 0, + 0, 3949, 0, + 0, 4067, 0, + 3509, 3033, 3907, + 3509, 3033, 3907, + 3509, 3033, 3905, + 3509, 3033, 3905, + 3507, 3035, 3905, + 3507, 3035, 3905, + 3507, 3035, 3905, + 3507, 3037, 3905, + 3505, 3037, 3905, + 3503, 3039, 3905, + 3501, 3041, 3903, + 3499, 3045, 3903, + 3495, 3049, 3901, + 3491, 3053, 3901, + 3485, 3061, 3899, + 3477, 3069, 3895, + 3465, 3081, 3893, + 3449, 3095, 3887, + 3425, 3115, 3881, + 3393, 3139, 3873, + 3347, 3171, 3859, + 3275, 3209, 3843, + 3159, 3257, 3819, + 2933, 3313, 3787, + 2041, 3379, 3737, + 0, 3453, 3663, + 0, 3537, 3539, + 0, 3631, 3291, + 0, 3731, 1724, + 0, 3837, 0, + 0, 3949, 0, + 0, 4067, 0, + 3517, 3033, 3909, + 3517, 3033, 3909, + 3517, 3033, 3909, + 3515, 3033, 3909, + 3515, 3033, 3907, + 3515, 3033, 3907, + 3515, 3035, 3907, + 3513, 3035, 3907, + 3513, 3037, 3907, + 3511, 3039, 3907, + 3509, 3041, 3905, + 3507, 3043, 3905, + 3503, 3047, 3905, + 3499, 3053, 3903, + 3493, 3059, 3901, + 3485, 3067, 3897, + 3473, 3079, 3895, + 3457, 3095, 3889, + 3435, 3115, 3883, + 3403, 3139, 3875, + 3357, 3171, 3863, + 3289, 3209, 3845, + 3175, 3257, 3823, + 2959, 3313, 3789, + 2203, 3377, 3741, + 0, 3453, 3667, + 0, 3537, 3543, + 0, 3631, 3299, + 0, 3731, 1929, + 0, 3837, 0, + 0, 3949, 0, + 0, 4067, 0, + 3527, 3031, 3911, + 3527, 3031, 3911, + 3527, 3031, 3911, + 3525, 3031, 3911, + 3525, 3031, 3911, + 3525, 3033, 3911, + 3525, 3033, 3911, + 3523, 3033, 3911, + 3523, 3035, 3909, + 3521, 3037, 3909, + 3519, 3039, 3909, + 3517, 3041, 3907, + 3513, 3045, 3907, + 3509, 3051, 3905, + 3503, 3057, 3903, + 3495, 3067, 3901, + 3483, 3079, 3897, + 3469, 3093, 3893, + 3447, 3113, 3887, + 3417, 3137, 3877, + 3371, 3169, 3865, + 3305, 3207, 3849, + 3197, 3255, 3825, + 2993, 3311, 3793, + 2355, 3377, 3745, + 0, 3453, 3671, + 0, 3537, 3549, + 0, 3629, 3311, + 0, 3731, 2109, + 0, 3837, 0, + 0, 3949, 0, + 0, 4065, 0, + 3539, 3029, 3915, + 3539, 3029, 3915, + 3539, 3029, 3915, + 3539, 3029, 3915, + 3539, 3029, 3915, + 3539, 3031, 3915, + 3537, 3031, 3915, + 3537, 3031, 3913, + 3535, 3033, 3913, + 3535, 3035, 3913, + 3533, 3037, 3913, + 3531, 3039, 3911, + 3527, 3043, 3911, + 3523, 3049, 3909, + 3517, 3055, 3907, + 3509, 3065, 3905, + 3499, 3077, 3901, + 3483, 3091, 3897, + 3463, 3111, 3891, + 3433, 3137, 3881, + 3389, 3167, 3869, + 3325, 3207, 3853, + 3223, 3253, 3831, + 3033, 3311, 3797, + 2501, 3377, 3751, + 0, 3451, 3677, + 0, 3537, 3559, + 0, 3629, 3325, + 0, 3729, 2275, + 0, 3837, 0, + 0, 3949, 0, + 0, 4065, 0, + 3557, 3025, 3919, + 3557, 3027, 3919, + 3555, 3027, 3919, + 3555, 3027, 3919, + 3555, 3027, 3919, + 3555, 3027, 3919, + 3555, 3029, 3919, + 3553, 3029, 3919, + 3553, 3031, 3919, + 3551, 3033, 3919, + 3549, 3035, 3917, + 3547, 3037, 3917, + 3545, 3041, 3915, + 3541, 3047, 3915, + 3535, 3053, 3913, + 3527, 3063, 3909, + 3517, 3075, 3907, + 3501, 3089, 3901, + 3483, 3109, 3895, + 3453, 3135, 3887, + 3413, 3165, 3875, + 3353, 3205, 3859, + 3255, 3253, 3837, + 3083, 3309, 3805, + 2645, 3375, 3757, + 0, 3451, 3685, + 0, 3535, 3569, + 0, 3629, 3343, + 0, 3729, 2431, + 0, 3837, 0, + 0, 3949, 0, + 0, 4065, 0, + 3577, 3023, 3927, + 3577, 3023, 3927, + 3577, 3023, 3927, + 3577, 3023, 3927, + 3577, 3023, 3927, + 3577, 3023, 3927, + 3577, 3025, 3925, + 3575, 3025, 3925, + 3575, 3027, 3925, + 3573, 3029, 3925, + 3571, 3031, 3925, + 3569, 3033, 3923, + 3567, 3037, 3923, + 3563, 3043, 3921, + 3557, 3049, 3919, + 3549, 3059, 3917, + 3539, 3071, 3913, + 3527, 3087, 3909, + 3507, 3107, 3903, + 3481, 3131, 3893, + 3443, 3163, 3883, + 3385, 3203, 3867, + 3297, 3251, 3845, + 3141, 3307, 3813, + 2785, 3373, 3767, + 0, 3449, 3697, + 0, 3535, 3583, + 0, 3627, 3365, + 0, 3729, 2579, + 0, 3835, 0, + 0, 3949, 0, + 0, 4065, 0, + 3605, 3017, 3935, + 3605, 3017, 3935, + 3605, 3017, 3935, + 3605, 3019, 3935, + 3605, 3019, 3935, + 3603, 3019, 3935, + 3603, 3019, 3935, + 3603, 3021, 3935, + 3601, 3023, 3933, + 3601, 3023, 3933, + 3599, 3027, 3933, + 3597, 3029, 3933, + 3595, 3033, 3931, + 3591, 3039, 3929, + 3585, 3045, 3927, + 3579, 3055, 3925, + 3569, 3067, 3923, + 3557, 3083, 3917, + 3539, 3103, 3911, + 3515, 3127, 3903, + 3479, 3159, 3891, + 3427, 3199, 3877, + 3347, 3247, 3855, + 3209, 3305, 3823, + 2923, 3371, 3779, + 0, 3447, 3711, + 0, 3533, 3601, + 0, 3627, 3395, + 0, 3727, 2723, + 0, 3835, 0, + 0, 3947, 0, + 0, 4065, 0, + 3639, 3011, 3947, + 3639, 3011, 3947, + 3639, 3011, 3947, + 3639, 3011, 3947, + 3639, 3013, 3947, + 3639, 3013, 3947, + 3637, 3013, 3945, + 3637, 3015, 3945, + 3637, 3015, 3945, + 3635, 3017, 3945, + 3633, 3019, 3945, + 3631, 3023, 3943, + 3629, 3027, 3943, + 3625, 3033, 3941, + 3621, 3039, 3939, + 3615, 3049, 3937, + 3607, 3061, 3933, + 3595, 3077, 3929, + 3579, 3097, 3923, + 3555, 3123, 3915, + 3523, 3155, 3905, + 3477, 3195, 3889, + 3405, 3243, 3869, + 3287, 3301, 3839, + 3059, 3369, 3795, + 2121, 3445, 3729, + 0, 3531, 3625, + 0, 3625, 3431, + 0, 3727, 2865, + 0, 3833, 0, + 0, 3947, 0, + 0, 4065, 0, + 3681, 3003, 3961, + 3681, 3003, 3961, + 3681, 3003, 3961, + 3681, 3003, 3961, + 3681, 3003, 3961, + 3681, 3003, 3961, + 3679, 3005, 3961, + 3679, 3005, 3961, + 3679, 3007, 3961, + 3677, 3009, 3959, + 3677, 3011, 3959, + 3675, 3015, 3959, + 3673, 3019, 3957, + 3669, 3023, 3957, + 3665, 3031, 3955, + 3659, 3041, 3953, + 3651, 3053, 3949, + 3641, 3069, 3945, + 3625, 3089, 3939, + 3605, 3115, 3931, + 3577, 3149, 3921, + 3535, 3189, 3905, + 3473, 3237, 3885, + 3373, 3297, 3857, + 3195, 3365, 3815, + 2719, 3441, 3753, + 0, 3527, 3655, + 0, 3623, 3475, + 0, 3725, 3003, + 0, 3833, 0, + 0, 3945, 0, + 0, 4063, 0, + 3731, 2989, 3981, + 3731, 2991, 3981, + 3731, 2991, 3981, + 3731, 2991, 3981, + 3731, 2991, 3979, + 3731, 2991, 3979, + 3731, 2993, 3979, + 3731, 2993, 3979, + 3729, 2995, 3979, + 3729, 2997, 3979, + 3727, 2999, 3979, + 3725, 3003, 3977, + 3723, 3007, 3977, + 3721, 3013, 3975, + 3717, 3019, 3973, + 3713, 3029, 3971, + 3705, 3041, 3969, + 3695, 3059, 3965, + 3683, 3079, 3959, + 3665, 3107, 3951, + 3639, 3139, 3941, + 3603, 3181, 3927, + 3551, 3231, 3907, + 3469, 3289, 3881, + 3329, 3359, 3841, + 3029, 3437, 3783, + 0, 3523, 3691, + 0, 3619, 3529, + 0, 3721, 3139, + 0, 3831, 0, + 0, 3945, 0, + 0, 4061, 0, + 3791, 2973, 4005, + 3791, 2973, 4005, + 3791, 2973, 4005, + 3791, 2973, 4005, + 3791, 2975, 4005, + 3791, 2975, 4005, + 3791, 2975, 4003, + 3791, 2977, 4003, + 3789, 2979, 4003, + 3789, 2981, 4003, + 3787, 2983, 4003, + 3787, 2985, 4001, + 3785, 2991, 4001, + 3783, 2997, 3999, + 3779, 3003, 3999, + 3775, 3013, 3997, + 3769, 3027, 3993, + 3761, 3043, 3989, + 3749, 3065, 3985, + 3733, 3093, 3977, + 3713, 3127, 3967, + 3681, 3169, 3955, + 3637, 3221, 3937, + 3571, 3281, 3911, + 3463, 3351, 3873, + 3261, 3431, 3819, + 2631, 3519, 3735, + 0, 3615, 3591, + 0, 3719, 3275, + 0, 3827, 0, + 0, 3943, 0, + 0, 4061, 0, + 3861, 2949, 4035, + 3861, 2949, 4035, + 3861, 2951, 4035, + 3861, 2951, 4035, + 3861, 2951, 4035, + 3861, 2951, 4035, + 3861, 2953, 4035, + 3861, 2953, 4035, + 3859, 2955, 4035, + 3859, 2957, 4033, + 3859, 2959, 4033, + 3857, 2963, 4033, + 3855, 2967, 4031, + 3853, 2973, 4031, + 3851, 2981, 4029, + 3847, 2993, 4027, + 3841, 3007, 4025, + 3835, 3023, 4021, + 3825, 3047, 4017, + 3811, 3075, 4009, + 3793, 3111, 4001, + 3769, 3155, 3989, + 3733, 3207, 3971, + 3679, 3269, 3947, + 3595, 3341, 3915, + 3455, 3423, 3865, + 3149, 3511, 3789, + 0, 3609, 3663, + 0, 3713, 3411, + 0, 3825, 876, + 0, 3939, 0, + 0, 4059, 0, + 3941, 2917, 4073, + 3941, 2917, 4073, + 3941, 2917, 4073, + 3941, 2917, 4073, + 3939, 2917, 4073, + 3939, 2919, 4073, + 3939, 2919, 4073, + 3939, 2921, 4073, + 3939, 2921, 4071, + 3939, 2925, 4071, + 3937, 2927, 4071, + 3937, 2931, 4071, + 3935, 2935, 4069, + 3933, 2943, 4069, + 3931, 2951, 4067, + 3927, 2963, 4065, + 3923, 2977, 4063, + 3917, 2995, 4059, + 3909, 3019, 4055, + 3899, 3051, 4049, + 3885, 3087, 4041, + 3863, 3133, 4031, + 3835, 3189, 4015, + 3793, 3253, 3993, + 3729, 3327, 3963, + 3627, 3411, 3919, + 3443, 3503, 3853, + 2939, 3601, 3745, + 0, 3707, 3545, + 0, 3819, 2929, + 0, 3935, 0, + 0, 4055, 0, + 4029, 2867, 4095, + 4029, 2867, 4095, + 4029, 2867, 4095, + 4029, 2869, 4095, + 4027, 2869, 4095, + 4027, 2869, 4095, + 4027, 2871, 4095, + 4027, 2871, 4095, + 4027, 2873, 4095, + 4027, 2877, 4095, + 4025, 2879, 4095, + 4025, 2883, 4095, + 4025, 2889, 4095, + 4023, 2897, 4095, + 4021, 2905, 4095, + 4019, 2919, 4095, + 4015, 2935, 4095, + 4009, 2955, 4095, + 4003, 2981, 4095, + 3995, 3015, 4095, + 3983, 3055, 4091, + 3965, 3105, 4081, + 3943, 3163, 4067, + 3909, 3231, 4047, + 3861, 3309, 4021, + 3789, 3395, 3983, + 3667, 3489, 3925, + 3427, 3591, 3835, + 2235, 3699, 3677, + 0, 3813, 3313, + 0, 3931, 0, + 0, 4051, 0, + 4095, 2793, 4095, + 4095, 2793, 4095, + 4095, 2793, 4095, + 4095, 2793, 4095, + 4095, 2795, 4095, + 4095, 2795, 4095, + 4095, 2797, 4095, + 4095, 2797, 4095, + 4095, 2799, 4095, + 4095, 2803, 4095, + 4095, 2807, 4095, + 4095, 2811, 4095, + 4095, 2817, 4095, + 4095, 2827, 4095, + 4095, 2837, 4095, + 4095, 2851, 4095, + 4095, 2871, 4095, + 4095, 2895, 4095, + 4095, 2925, 4095, + 4095, 2961, 4095, + 4087, 3007, 4095, + 4075, 3061, 4095, + 4057, 3125, 4095, + 4031, 3199, 4095, + 3995, 3281, 4089, + 3941, 3373, 4055, + 3857, 3471, 4007, + 3715, 3577, 3933, + 3407, 3689, 3811, + 0, 3805, 3569, + 0, 3925, 2301, + 0, 4047, 0, + 4095, 2667, 4095, + 4095, 2669, 4095, + 4095, 2669, 4095, + 4095, 2669, 4095, + 4095, 2671, 4095, + 4095, 2671, 4095, + 4095, 2673, 4095, + 4095, 2675, 4095, + 4095, 2677, 4095, + 4095, 2681, 4095, + 4095, 2687, 4095, + 4095, 2693, 4095, + 4095, 2701, 4095, + 4095, 2711, 4095, + 4095, 2727, 4095, + 4095, 2745, 4095, + 4095, 2767, 4095, + 4095, 2797, 4095, + 4095, 2835, 4095, + 4095, 2879, 4095, + 4095, 2933, 4095, + 4095, 2997, 4095, + 4095, 3069, 4095, + 4095, 3151, 4095, + 4095, 3243, 4095, + 4087, 3341, 4095, + 4029, 3447, 4095, + 3935, 3557, 4039, + 3771, 3673, 3945, + 3375, 3793, 3777, + 0, 3915, 3367, + 0, 4039, 0, + 4095, 2419, 4095, + 4095, 2421, 4095, + 4095, 2421, 4095, + 4095, 2421, 4095, + 4095, 2423, 4095, + 4095, 2425, 4095, + 4095, 2429, 4095, + 4095, 2431, 4095, + 4095, 2437, 4095, + 4095, 2443, 4095, + 4095, 2451, 4095, + 4095, 2461, 4095, + 4095, 2475, 4095, + 4095, 2493, 4095, + 4095, 2515, 4095, + 4095, 2545, 4095, + 4095, 2581, 4095, + 4095, 2625, 4095, + 4095, 2677, 4095, + 4095, 2739, 4095, + 4095, 2811, 4095, + 4095, 2893, 4095, + 4095, 2983, 4095, + 4095, 3081, 4095, + 4095, 3185, 4095, + 4095, 3295, 4095, + 4095, 3411, 4095, + 4095, 3529, 4095, + 4023, 3651, 4077, + 3839, 3777, 3959, + 3331, 3903, 3727, + 0, 4031, 2729, + 4095, 771, 4095, + 4095, 795, 4095, + 4095, 824, 4095, + 4095, 860, 4095, + 4095, 904, 4095, + 4095, 957, 4095, + 4095, 1020, 4095, + 4095, 1092, 4095, + 4095, 1173, 4095, + 4095, 1263, 4095, + 4095, 1361, 4095, + 4095, 1466, 4095, + 4095, 1577, 4095, + 4095, 1692, 4095, + 4095, 1811, 4095, + 4095, 1934, 4095, + 4095, 2059, 4095, + 4095, 2185, 4095, + 4095, 2313, 4095, + 4095, 2441, 4095, + 4095, 2571, 4095, + 4095, 2701, 4095, + 4095, 2831, 4095, + 4095, 2963, 4095, + 4095, 3095, 4095, + 4095, 3225, 4095, + 4095, 3357, 4095, + 4095, 3489, 4095, + 4095, 3621, 4095, + 4095, 3753, 4095, + 3915, 3885, 3977, + 3265, 4017, 3649, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 1343, 4095, + 4095, 2153, 4095, + 4095, 2493, 4095, + 4095, 2735, 4095, + 4095, 2935, 4095, + 4095, 3113, 4095, + 4095, 3275, 4095, + 4095, 3429, 4095, + 4095, 3577, 4095, + 4095, 3721, 4095, + 4095, 3861, 4095, + 3999, 3999, 3999 +] + } +} diff --git a/Gems/Atom/Feature/Common/Assets/ColorGrading/TestData/Nuke/test-grade_inv-Log2-48nits_32_LUT.azasset b/Gems/Atom/Feature/Common/Assets/ColorGrading/TestData/Nuke/test-grade_inv-Log2-48nits_32_LUT.azasset new file mode 100644 index 0000000000..a91e9d0c1a --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/ColorGrading/TestData/Nuke/test-grade_inv-Log2-48nits_32_LUT.azasset @@ -0,0 +1,32780 @@ +{ + "Type": "JsonSerialization", + "Version": 1, + "ClassName": "LookupTableAsset", + "ClassData": { + "Name": "LookupTable", + "Intervals": [ + 0, 33, 66, 99, 132, 165, 198, 231, 264, 297, 330, 363, 396, 429, 462, 495, 528, 561, 594, 627, 660, 693, 726, 759, 792, 825, 858, 891, 924, 957, 990, 1023], + "Values": [ + 0, 0, 0, + 0, 0, 0, + 0, 15, 0, + 0, 104, 0, + 0, 201, 0, + 0, 305, 0, + 0, 415, 0, + 0, 530, 0, + 0, 649, 0, + 0, 771, 0, + 0, 895, 0, + 0, 1022, 0, + 0, 1149, 0, + 0, 1278, 0, + 0, 1408, 0, + 0, 1538, 0, + 0, 1668, 0, + 0, 1799, 0, + 0, 1931, 0, + 0, 2062, 0, + 0, 2194, 0, + 0, 2326, 0, + 0, 2457, 0, + 0, 2589, 0, + 0, 2721, 0, + 0, 2853, 0, + 0, 2985, 0, + 0, 3117, 0, + 0, 3249, 0, + 0, 3381, 0, + 0, 3514, 0, + 0, 3646, 0, + 130, 0, 20, + 28, 0, 0, + 0, 33, 0, + 0, 119, 0, + 0, 213, 0, + 0, 315, 0, + 0, 423, 0, + 0, 536, 0, + 0, 654, 0, + 0, 775, 0, + 0, 898, 0, + 0, 1024, 0, + 0, 1151, 0, + 0, 1279, 0, + 0, 1408, 0, + 0, 1538, 0, + 0, 1669, 0, + 0, 1800, 0, + 0, 1931, 0, + 0, 2062, 0, + 0, 2194, 0, + 0, 2326, 0, + 0, 2458, 0, + 0, 2589, 0, + 0, 2721, 0, + 0, 2853, 0, + 0, 2985, 0, + 0, 3117, 0, + 0, 3249, 0, + 0, 3381, 0, + 0, 3514, 0, + 0, 3646, 0, + 342, 0, 170, + 280, 0, 102, + 183, 56, 0, + 7, 139, 0, + 0, 229, 0, + 0, 328, 0, + 0, 433, 0, + 0, 544, 0, + 0, 660, 0, + 0, 779, 0, + 0, 902, 0, + 0, 1026, 0, + 0, 1153, 0, + 0, 1281, 0, + 0, 1410, 0, + 0, 1539, 0, + 0, 1670, 0, + 0, 1800, 0, + 0, 1931, 0, + 0, 2063, 0, + 0, 2194, 0, + 0, 2326, 0, + 0, 2458, 0, + 0, 2589, 0, + 0, 2721, 0, + 0, 2853, 0, + 0, 2985, 0, + 0, 3117, 0, + 0, 3249, 0, + 0, 3381, 0, + 0, 3514, 0, + 0, 3646, 0, + 526, 0, 315, + 486, 18, 266, + 426, 86, 192, + 331, 163, 68, + 163, 250, 0, + 0, 344, 0, + 0, 446, 0, + 0, 555, 0, + 0, 668, 0, + 0, 785, 0, + 0, 906, 0, + 0, 1030, 0, + 0, 1156, 0, + 0, 1283, 0, + 0, 1411, 0, + 0, 1540, 0, + 0, 1670, 0, + 0, 1801, 0, + 0, 1932, 0, + 0, 2063, 0, + 0, 2194, 0, + 0, 2326, 0, + 0, 2458, 0, + 0, 2590, 0, + 0, 2722, 0, + 0, 2853, 0, + 0, 2985, 0, + 0, 3117, 0, + 0, 3249, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 693, 8, 457, + 666, 60, 422, + 626, 123, 370, + 568, 195, 290, + 475, 276, 155, + 312, 366, 0, + 0, 463, 0, + 0, 568, 0, + 0, 678, 0, + 0, 794, 0, + 0, 913, 0, + 0, 1035, 0, + 0, 1159, 0, + 0, 1285, 0, + 0, 1413, 0, + 0, 1542, 0, + 0, 1672, 0, + 0, 1802, 0, + 0, 1932, 0, + 0, 2064, 0, + 0, 2195, 0, + 0, 2326, 0, + 0, 2458, 0, + 0, 2590, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2985, 0, + 0, 3117, 0, + 0, 3249, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 850, 65, 596, + 831, 112, 570, + 804, 168, 534, + 765, 233, 479, + 707, 308, 395, + 616, 393, 250, + 457, 485, 0, + 82, 585, 0, + 0, 692, 0, + 0, 804, 0, + 0, 921, 0, + 0, 1041, 0, + 0, 1164, 0, + 0, 1289, 0, + 0, 1416, 0, + 0, 1544, 0, + 0, 1673, 0, + 0, 1803, 0, + 0, 1933, 0, + 0, 2064, 0, + 0, 2195, 0, + 0, 2327, 0, + 0, 2458, 0, + 0, 2590, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 999, 131, 733, + 986, 172, 714, + 967, 222, 688, + 940, 280, 650, + 901, 348, 594, + 844, 426, 505, + 755, 513, 352, + 598, 608, 3, + 235, 710, 0, + 0, 818, 0, + 0, 932, 0, + 0, 1049, 0, + 0, 1170, 0, + 0, 1294, 0, + 0, 1420, 0, + 0, 1547, 0, + 0, 1675, 0, + 0, 1805, 0, + 0, 1935, 0, + 0, 2065, 0, + 0, 2196, 0, + 0, 2327, 0, + 0, 2459, 0, + 0, 2590, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1144, 207, 869, + 1134, 242, 855, + 1121, 285, 836, + 1102, 336, 809, + 1075, 397, 770, + 1037, 468, 712, + 980, 547, 621, + 892, 636, 461, + 737, 732, 82, + 382, 836, 0, + 0, 946, 0, + 0, 1060, 0, + 0, 1179, 0, + 0, 1300, 0, + 0, 1424, 0, + 0, 1550, 0, + 0, 1678, 0, + 0, 1807, 0, + 0, 1936, 0, + 0, 2066, 0, + 0, 2197, 0, + 0, 2328, 0, + 0, 2459, 0, + 0, 2591, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1286, 293, 1004, + 1278, 322, 994, + 1268, 358, 980, + 1255, 402, 960, + 1236, 455, 932, + 1210, 518, 893, + 1172, 590, 833, + 1115, 671, 740, + 1027, 761, 574, + 874, 859, 170, + 525, 964, 0, + 0, 1074, 0, + 0, 1190, 0, + 0, 1309, 0, + 0, 1431, 0, + 0, 1555, 0, + 0, 1682, 0, + 0, 1809, 0, + 0, 1938, 0, + 0, 2068, 0, + 0, 2198, 0, + 0, 2329, 0, + 0, 2460, 0, + 0, 2591, 0, + 0, 2723, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1424, 386, 1138, + 1419, 410, 1131, + 1412, 440, 1120, + 1402, 477, 1106, + 1389, 523, 1086, + 1370, 577, 1058, + 1343, 641, 1018, + 1306, 714, 958, + 1250, 797, 862, + 1162, 888, 692, + 1010, 987, 267, + 665, 1093, 0, + 0, 1204, 0, + 0, 1320, 0, + 0, 1439, 0, + 0, 1562, 0, + 0, 1687, 0, + 0, 1813, 0, + 0, 1941, 0, + 0, 2070, 0, + 0, 2200, 0, + 0, 2330, 0, + 0, 2461, 0, + 0, 2592, 0, + 0, 2723, 0, + 0, 2855, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1562, 487, 1272, + 1558, 506, 1266, + 1552, 531, 1258, + 1545, 561, 1248, + 1535, 599, 1234, + 1522, 646, 1213, + 1503, 701, 1185, + 1477, 766, 1144, + 1439, 840, 1084, + 1383, 924, 987, + 1296, 1016, 813, + 1145, 1116, 370, + 802, 1222, 0, + 0, 1334, 0, + 0, 1450, 0, + 0, 1570, 0, + 0, 1693, 0, + 0, 1818, 0, + 0, 1945, 0, + 0, 2073, 0, + 0, 2202, 0, + 0, 2331, 0, + 0, 2462, 0, + 0, 2593, 0, + 0, 2724, 0, + 0, 2855, 0, + 0, 2987, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1697, 595, 1405, + 1695, 610, 1401, + 1691, 629, 1395, + 1685, 654, 1387, + 1678, 685, 1377, + 1668, 724, 1362, + 1655, 771, 1342, + 1636, 827, 1314, + 1610, 893, 1273, + 1572, 968, 1211, + 1517, 1053, 1113, + 1430, 1145, 937, + 1279, 1246, 479, + 939, 1352, 0, + 0, 1465, 0, + 0, 1581, 0, + 0, 1701, 0, + 0, 1824, 0, + 0, 1950, 0, + 0, 2076, 0, + 0, 2204, 0, + 0, 2334, 0, + 0, 2463, 0, + 0, 2594, 0, + 0, 2725, 0, + 0, 2856, 0, + 0, 2987, 0, + 0, 3119, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1832, 707, 1538, + 1830, 719, 1535, + 1827, 735, 1531, + 1823, 755, 1525, + 1818, 780, 1517, + 1811, 811, 1507, + 1801, 851, 1492, + 1788, 898, 1472, + 1769, 955, 1443, + 1743, 1021, 1402, + 1705, 1097, 1340, + 1650, 1182, 1241, + 1563, 1275, 1062, + 1412, 1376, 594, + 1074, 1483, 0, + 0, 1596, 0, + 0, 1712, 0, + 0, 1833, 0, + 0, 1956, 0, + 0, 2081, 0, + 0, 2208, 0, + 0, 2336, 0, + 0, 2466, 0, + 0, 2595, 0, + 0, 2726, 0, + 0, 2857, 0, + 0, 2988, 0, + 0, 3119, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3514, 0, + 0, 3646, 0, + 1966, 824, 1671, + 1965, 834, 1668, + 1963, 846, 1665, + 1960, 861, 1661, + 1956, 881, 1655, + 1951, 907, 1647, + 1943, 939, 1637, + 1934, 978, 1622, + 1920, 1026, 1602, + 1902, 1084, 1573, + 1875, 1150, 1531, + 1838, 1227, 1469, + 1782, 1312, 1370, + 1696, 1406, 1190, + 1545, 1507, 712, + 1209, 1614, 0, + 0, 1727, 0, + 0, 1844, 0, + 0, 1964, 0, + 0, 2088, 0, + 0, 2213, 0, + 0, 2340, 0, + 0, 2468, 0, + 0, 2597, 0, + 0, 2727, 0, + 0, 2858, 0, + 0, 2989, 0, + 0, 3120, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3646, 0, + 2100, 945, 1803, + 2099, 952, 1802, + 2097, 961, 1799, + 2095, 973, 1796, + 2092, 989, 1792, + 2088, 1009, 1786, + 2083, 1035, 1778, + 2076, 1067, 1768, + 2066, 1107, 1753, + 2053, 1156, 1732, + 2034, 1213, 1703, + 2008, 1280, 1662, + 1970, 1357, 1599, + 1915, 1442, 1499, + 1828, 1536, 1318, + 1678, 1638, 834, + 1342, 1745, 0, + 0, 1858, 0, + 0, 1976, 0, + 0, 2096, 0, + 0, 2220, 0, + 0, 2345, 0, + 0, 2472, 0, + 0, 2600, 0, + 0, 2730, 0, + 0, 2859, 0, + 0, 2990, 0, + 0, 3121, 0, + 0, 3252, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3647, 0, + 2233, 1068, 1936, + 2232, 1074, 1935, + 2231, 1081, 1933, + 2230, 1090, 1930, + 2227, 1102, 1927, + 2225, 1118, 1923, + 2221, 1139, 1917, + 2215, 1164, 1909, + 2208, 1197, 1899, + 2198, 1237, 1884, + 2185, 1286, 1863, + 2166, 1343, 1834, + 2140, 1411, 1793, + 2103, 1488, 1730, + 2047, 1573, 1629, + 1961, 1668, 1447, + 1811, 1769, 958, + 1476, 1877, 0, + 0, 1990, 0, + 0, 2107, 0, + 0, 2228, 0, + 0, 2351, 0, + 0, 2477, 0, + 0, 2604, 0, + 0, 2732, 0, + 0, 2862, 0, + 0, 2991, 0, + 0, 3122, 0, + 0, 3253, 0, + 0, 3384, 0, + 0, 3515, 0, + 0, 3647, 0, + 2366, 1194, 2068, + 2366, 1198, 2067, + 2365, 1203, 2066, + 2364, 1210, 2064, + 2362, 1220, 2062, + 2360, 1232, 2059, + 2357, 1248, 2054, + 2353, 1268, 2049, + 2348, 1294, 2041, + 2340, 1327, 2030, + 2331, 1367, 2015, + 2317, 1416, 1995, + 2299, 1474, 1966, + 2273, 1542, 1924, + 2235, 1619, 1861, + 2180, 1705, 1760, + 2093, 1799, 1577, + 1944, 1901, 1084, + 1609, 2009, 0, + 0, 2122, 0, + 0, 2239, 0, + 0, 2360, 0, + 0, 2483, 0, + 0, 2609, 0, + 0, 2736, 0, + 0, 2864, 0, + 0, 2994, 0, + 0, 3124, 0, + 0, 3254, 0, + 0, 3385, 0, + 0, 3516, 0, + 0, 3648, 0, + 2499, 1321, 2200, + 2499, 1324, 2200, + 2498, 1328, 2199, + 2497, 1333, 2197, + 2496, 1340, 2196, + 2494, 1350, 2193, + 2492, 1362, 2190, + 2489, 1378, 2186, + 2485, 1399, 2180, + 2480, 1425, 2172, + 2473, 1458, 2161, + 2463, 1498, 2147, + 2450, 1547, 2126, + 2431, 1605, 2097, + 2405, 1673, 2055, + 2367, 1750, 1992, + 2312, 1836, 1891, + 2226, 1931, 1708, + 2076, 2032, 1211, + 1742, 2140, 0, + 0, 2254, 0, + 0, 2371, 0, + 0, 2492, 0, + 0, 2615, 0, + 0, 2741, 0, + 0, 2868, 0, + 0, 2996, 0, + 0, 3126, 0, + 0, 3256, 0, + 0, 3386, 0, + 0, 3517, 0, + 0, 3648, 0, + 2632, 1449, 2333, + 2631, 1451, 2332, + 2631, 1454, 2331, + 2630, 1458, 2330, + 2629, 1464, 2329, + 2628, 1471, 2327, + 2626, 1481, 2325, + 2624, 1493, 2322, + 2621, 1509, 2318, + 2617, 1530, 2312, + 2612, 1556, 2304, + 2605, 1589, 2293, + 2595, 1629, 2278, + 2582, 1678, 2258, + 2563, 1736, 2229, + 2537, 1804, 2187, + 2500, 1881, 2123, + 2444, 1968, 2023, + 2358, 2062, 1839, + 2208, 2164, 1340, + 1874, 2272, 0, + 0, 2385, 0, + 0, 2503, 0, + 0, 2624, 0, + 0, 2747, 0, + 0, 2873, 0, + 0, 3000, 0, + 0, 3128, 0, + 0, 3258, 0, + 0, 3388, 0, + 0, 3518, 0, + 0, 3649, 0, + 2764, 1578, 2465, + 2764, 1580, 2465, + 2763, 1582, 2464, + 2763, 1585, 2463, + 2762, 1589, 2462, + 2761, 1595, 2461, + 2760, 1602, 2459, + 2759, 1612, 2457, + 2756, 1624, 2454, + 2753, 1640, 2449, + 2750, 1661, 2444, + 2744, 1687, 2436, + 2737, 1720, 2425, + 2727, 1760, 2410, + 2714, 1809, 2389, + 2695, 1868, 2360, + 2669, 1936, 2318, + 2632, 2013, 2255, + 2577, 2099, 2154, + 2490, 2194, 1970, + 2341, 2296, 1469, + 2007, 2404, 0, + 0, 2517, 0, + 0, 2635, 0, + 0, 2756, 0, + 0, 2879, 0, + 0, 3005, 0, + 0, 3132, 0, + 0, 3260, 0, + 0, 3390, 0, + 0, 3520, 0, + 0, 3650, 0, + 2896, 1708, 2597, + 2896, 1709, 2597, + 2896, 1711, 2596, + 2896, 1713, 2596, + 2895, 1716, 2595, + 2894, 1721, 2594, + 2893, 1726, 2593, + 2892, 1733, 2591, + 2891, 1743, 2589, + 2889, 1755, 2586, + 2886, 1771, 2581, + 2882, 1792, 2575, + 2876, 1818, 2568, + 2869, 1851, 2557, + 2859, 1892, 2542, + 2846, 1941, 2521, + 2828, 1999, 2492, + 2801, 2067, 2450, + 2764, 2145, 2387, + 2709, 2231, 2286, + 2622, 2326, 2101, + 2473, 2428, 1599, + 2139, 2536, 0, + 0, 2649, 0, + 0, 2767, 0, + 0, 2888, 0, + 0, 3011, 0, + 0, 3137, 0, + 0, 3264, 0, + 0, 3393, 0, + 0, 3522, 0, + 0, 3652, 0, + 3029, 1838, 2729, + 3029, 1839, 2729, + 3028, 1841, 2729, + 3028, 1842, 2728, + 3028, 1845, 2728, + 3027, 1848, 2727, + 3027, 1852, 2726, + 3026, 1858, 2725, + 3024, 1865, 2723, + 3023, 1874, 2721, + 3021, 1887, 2717, + 3018, 1903, 2713, + 3014, 1924, 2707, + 3009, 1950, 2699, + 3001, 1983, 2689, + 2992, 2024, 2674, + 2978, 2073, 2653, + 2960, 2131, 2624, + 2934, 2199, 2582, + 2896, 2277, 2519, + 2841, 2363, 2418, + 2755, 2458, 2233, + 2605, 2560, 1730, + 2272, 2668, 0, + 0, 2781, 0, + 0, 2899, 0, + 0, 3020, 0, + 0, 3143, 0, + 0, 3269, 0, + 0, 3396, 0, + 0, 3525, 0, + 0, 3654, 0, + 3161, 1969, 2861, + 3161, 1970, 2861, + 3161, 1971, 2861, + 3160, 1972, 2861, + 3160, 1974, 2860, + 3160, 1976, 2860, + 3159, 1980, 2859, + 3159, 1984, 2858, + 3158, 1989, 2857, + 3157, 1996, 2855, + 3155, 2006, 2853, + 3153, 2018, 2849, + 3150, 2035, 2845, + 3146, 2055, 2839, + 3141, 2082, 2831, + 3134, 2115, 2821, + 3124, 2155, 2806, + 3110, 2205, 2785, + 3092, 2263, 2756, + 3066, 2331, 2714, + 3028, 2409, 2651, + 2973, 2495, 2549, + 2887, 2590, 2365, + 2737, 2692, 1861, + 2404, 2800, 0, + 0, 2913, 0, + 0, 3031, 0, + 0, 3152, 0, + 0, 3276, 0, + 0, 3401, 0, + 0, 3528, 0, + 0, 3657, 0, + 3293, 2100, 2994, + 3293, 2101, 2993, + 3293, 2102, 2993, + 3293, 2103, 2993, + 3293, 2104, 2993, + 3292, 2106, 2992, + 3292, 2108, 2992, + 3291, 2111, 2991, + 3291, 2115, 2990, + 3290, 2121, 2989, + 3289, 2128, 2987, + 3287, 2138, 2985, + 3285, 2150, 2981, + 3282, 2166, 2977, + 3278, 2187, 2971, + 3273, 2213, 2963, + 3266, 2246, 2953, + 3256, 2287, 2938, + 3242, 2336, 2917, + 3224, 2395, 2888, + 3198, 2463, 2846, + 3161, 2541, 2783, + 3105, 2627, 2681, + 3019, 2722, 2497, + 2870, 2824, 1992, + 2536, 2932, 0, + 0, 3046, 0, + 0, 3163, 0, + 0, 3284, 0, + 0, 3408, 0, + 0, 3533, 0, + 0, 3660, 0, + 3425, 2232, 3126, + 3425, 2232, 3126, + 3425, 2233, 3125, + 3425, 2233, 3125, + 3425, 2234, 3125, + 3425, 2236, 3125, + 3424, 2238, 3124, + 3424, 2240, 3124, + 3424, 2243, 3123, + 3423, 2247, 3122, + 3422, 2253, 3121, + 3421, 2260, 3119, + 3419, 2270, 3117, + 3417, 2282, 3113, + 3414, 2298, 3109, + 3410, 2319, 3103, + 3405, 2345, 3095, + 3398, 2378, 3085, + 3388, 2419, 3070, + 3375, 2468, 3049, + 3356, 2527, 3020, + 3330, 2595, 2978, + 3293, 2673, 2915, + 3237, 2759, 2813, + 3151, 2854, 2629, + 3002, 2956, 2124, + 2668, 3064, 0, + 0, 3178, 0, + 0, 3295, 0, + 0, 3416, 0, + 0, 3540, 0, + 0, 3665, 0, + 3557, 2363, 3258, + 3557, 2364, 3258, + 3557, 2364, 3258, + 3557, 2365, 3258, + 3557, 2365, 3257, + 3557, 2366, 3257, + 3557, 2368, 3257, + 3557, 2370, 3256, + 3556, 2372, 3256, + 3556, 2375, 3255, + 3555, 2379, 3254, + 3554, 2385, 3253, + 3553, 2392, 3251, + 3551, 2402, 3249, + 3549, 2414, 3245, + 3546, 2430, 3241, + 3542, 2451, 3235, + 3537, 2477, 3227, + 3530, 2510, 3217, + 3520, 2551, 3202, + 3507, 2600, 3181, + 3488, 2659, 3152, + 3462, 2727, 3110, + 3425, 2805, 3047, + 3369, 2891, 2945, + 3283, 2986, 2760, + 3134, 3088, 2255, + 2800, 3196, 0, + 0, 3310, 0, + 0, 3427, 0, + 0, 3548, 0, + 0, 3672, 0, + 3690, 2495, 3390, + 3690, 2495, 3390, + 3690, 2496, 3390, + 3689, 2496, 3390, + 3689, 2497, 3390, + 3689, 2497, 3389, + 3689, 2498, 3389, + 3689, 2500, 3389, + 3689, 2501, 3388, + 3688, 2504, 3388, + 3688, 2507, 3387, + 3687, 2511, 3386, + 3686, 2517, 3385, + 3685, 2524, 3383, + 3683, 2534, 3381, + 3681, 2546, 3378, + 3678, 2562, 3373, + 3674, 2583, 3367, + 3669, 2609, 3360, + 3662, 2642, 3349, + 3652, 2683, 3334, + 3639, 2732, 3313, + 3620, 2791, 3284, + 3594, 2859, 3242, + 3557, 2937, 3179, + 3502, 3023, 3077, + 3415, 3118, 2892, + 3266, 3220, 2387, + 2933, 3328, 0, + 0, 3442, 0, + 0, 3559, 0, + 0, 3680, 0, + 3822, 2627, 3522, + 3822, 2627, 3522, + 3822, 2627, 3522, + 3822, 2628, 3522, + 3822, 2628, 3522, + 3822, 2629, 3522, + 3821, 2629, 3521, + 3821, 2630, 3521, + 3821, 2632, 3521, + 3821, 2633, 3521, + 3820, 2636, 3520, + 3820, 2639, 3519, + 3819, 2643, 3518, + 3818, 2649, 3517, + 3817, 2656, 3515, + 3816, 2666, 3513, + 3813, 2678, 3510, + 3810, 2694, 3505, + 3807, 2715, 3499, + 3801, 2741, 3492, + 3794, 2774, 3481, + 3784, 2815, 3466, + 3771, 2864, 3445, + 3752, 2923, 3416, + 3726, 2991, 3374, + 3689, 3069, 3311, + 3634, 3155, 3209, + 3547, 3250, 3024, + 3398, 3352, 2519, + 3065, 3460, 0, + 0, 3574, 0, + 0, 3691, 0, + 3954, 2759, 3654, + 3954, 2759, 3654, + 3954, 2759, 3654, + 3954, 2759, 3654, + 3954, 2760, 3654, + 3954, 2760, 3654, + 3954, 2761, 3654, + 3953, 2761, 3654, + 3953, 2762, 3653, + 3953, 2764, 3653, + 3953, 2765, 3653, + 3952, 2768, 3652, + 3952, 2771, 3651, + 3951, 2775, 3650, + 3950, 2781, 3649, + 3949, 2788, 3647, + 3948, 2798, 3645, + 3945, 2810, 3642, + 3943, 2826, 3637, + 3939, 2847, 3632, + 3933, 2873, 3624, + 3926, 2906, 3613, + 3916, 2947, 3598, + 3903, 2996, 3577, + 3884, 3055, 3548, + 3858, 3123, 3506, + 3821, 3201, 3443, + 3766, 3287, 3341, + 3679, 3382, 3156, + 3530, 3484, 2651, + 3197, 3592, 0, + 0, 3706, 0, + 4086, 2891, 3786, + 4086, 2891, 3786, + 4086, 2891, 3786, + 4086, 2891, 3786, + 4086, 2891, 3786, + 4086, 2892, 3786, + 4086, 2892, 3786, + 4086, 2893, 3786, + 4086, 2893, 3786, + 4085, 2894, 3785, + 4085, 2896, 3785, + 4085, 2897, 3785, + 4085, 2900, 3784, + 4084, 2903, 3783, + 4083, 2907, 3782, + 4083, 2913, 3781, + 4081, 2920, 3779, + 4080, 2930, 3777, + 4078, 2942, 3774, + 4075, 2958, 3769, + 4071, 2979, 3764, + 4065, 3005, 3756, + 4058, 3038, 3745, + 4049, 3079, 3730, + 4035, 3128, 3709, + 4017, 3187, 3680, + 3991, 3255, 3638, + 3953, 3333, 3575, + 3898, 3419, 3473, + 3812, 3514, 3289, + 3662, 3616, 2783, + 3329, 3725, 0, + 4095, 3023, 3918, + 4095, 3023, 3918, + 4095, 3023, 3918, + 4095, 3023, 3918, + 4095, 3023, 3918, + 4095, 3023, 3918, + 4095, 3024, 3918, + 4095, 3024, 3918, + 4095, 3025, 3918, + 4095, 3025, 3918, + 4095, 3026, 3917, + 4095, 3028, 3917, + 4095, 3030, 3917, + 4095, 3032, 3916, + 4095, 3035, 3915, + 4095, 3039, 3915, + 4095, 3045, 3913, + 4095, 3052, 3911, + 4095, 3062, 3909, + 4095, 3074, 3906, + 4095, 3090, 3902, + 4095, 3111, 3896, + 4095, 3137, 3888, + 4095, 3170, 3877, + 4095, 3211, 3862, + 4095, 3261, 3842, + 4095, 3319, 3812, + 4095, 3387, 3770, + 4085, 3465, 3707, + 4030, 3551, 3605, + 3944, 3646, 3421, + 3794, 3748, 2915, + 4095, 3155, 4050, + 4095, 3155, 4050, + 4095, 3155, 4050, + 4095, 3155, 4050, + 4095, 3155, 4050, + 4095, 3155, 4050, + 4095, 3155, 4050, + 4095, 3156, 4050, + 4095, 3156, 4050, + 4095, 3157, 4050, + 4095, 3157, 4050, + 4095, 3158, 4050, + 4095, 3160, 4049, + 4095, 3162, 4049, + 4095, 3164, 4048, + 4095, 3167, 4048, + 4095, 3171, 4047, + 4095, 3177, 4045, + 4095, 3184, 4044, + 4095, 3194, 4041, + 4095, 3206, 4038, + 4095, 3222, 4034, + 4095, 3243, 4028, + 4095, 3270, 4020, + 4095, 3303, 4009, + 4095, 3343, 3994, + 4095, 3393, 3974, + 4095, 3451, 3944, + 4095, 3519, 3902, + 4095, 3597, 3839, + 4095, 3684, 3738, + 4076, 3778, 3553, + 0, 0, 0, + 0, 0, 0, + 0, 49, 0, + 0, 132, 0, + 0, 224, 0, + 0, 324, 0, + 0, 430, 0, + 0, 542, 0, + 0, 658, 0, + 0, 778, 0, + 0, 901, 0, + 0, 1025, 0, + 0, 1152, 0, + 0, 1280, 0, + 0, 1409, 0, + 0, 1539, 0, + 0, 1669, 0, + 0, 1800, 0, + 0, 1931, 0, + 0, 2063, 0, + 0, 2194, 0, + 0, 2326, 0, + 0, 2458, 0, + 0, 2589, 0, + 0, 2721, 0, + 0, 2853, 0, + 0, 2985, 0, + 0, 3117, 0, + 0, 3249, 0, + 0, 3381, 0, + 0, 3514, 0, + 0, 3646, 0, + 104, 0, 80, + 0, 0, 0, + 0, 66, 0, + 0, 147, 0, + 0, 236, 0, + 0, 333, 0, + 0, 438, 0, + 0, 548, 0, + 0, 662, 0, + 0, 781, 0, + 0, 903, 0, + 0, 1028, 0, + 0, 1154, 0, + 0, 1281, 0, + 0, 1410, 0, + 0, 1540, 0, + 0, 1670, 0, + 0, 1800, 0, + 0, 1931, 0, + 0, 2063, 0, + 0, 2194, 0, + 0, 2326, 0, + 0, 2458, 0, + 0, 2590, 0, + 0, 2721, 0, + 0, 2853, 0, + 0, 2985, 0, + 0, 3117, 0, + 0, 3249, 0, + 0, 3381, 0, + 0, 3514, 0, + 0, 3646, 0, + 326, 0, 214, + 262, 20, 152, + 160, 88, 54, + 0, 165, 0, + 0, 251, 0, + 0, 346, 0, + 0, 447, 0, + 0, 555, 0, + 0, 668, 0, + 0, 786, 0, + 0, 907, 0, + 0, 1030, 0, + 0, 1156, 0, + 0, 1283, 0, + 0, 1411, 0, + 0, 1540, 0, + 0, 1670, 0, + 0, 1801, 0, + 0, 1932, 0, + 0, 2063, 0, + 0, 2194, 0, + 0, 2326, 0, + 0, 2458, 0, + 0, 2590, 0, + 0, 2722, 0, + 0, 2853, 0, + 0, 2985, 0, + 0, 3117, 0, + 0, 3249, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 515, 0, 347, + 474, 52, 302, + 413, 116, 234, + 315, 188, 122, + 139, 271, 0, + 0, 361, 0, + 0, 460, 0, + 0, 565, 0, + 0, 676, 0, + 0, 792, 0, + 0, 911, 0, + 0, 1034, 0, + 0, 1158, 0, + 0, 1285, 0, + 0, 1413, 0, + 0, 1542, 0, + 0, 1671, 0, + 0, 1802, 0, + 0, 1932, 0, + 0, 2063, 0, + 0, 2195, 0, + 0, 2326, 0, + 0, 2458, 0, + 0, 2590, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2985, 0, + 0, 3117, 0, + 0, 3249, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 686, 42, 481, + 658, 92, 447, + 618, 150, 399, + 558, 218, 324, + 463, 295, 200, + 295, 382, 0, + 0, 477, 0, + 0, 579, 0, + 0, 687, 0, + 0, 800, 0, + 0, 918, 0, + 0, 1039, 0, + 0, 1162, 0, + 0, 1288, 0, + 0, 1415, 0, + 0, 1543, 0, + 0, 1673, 0, + 0, 1802, 0, + 0, 1933, 0, + 0, 2064, 0, + 0, 2195, 0, + 0, 2327, 0, + 0, 2458, 0, + 0, 2590, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 844, 96, 614, + 825, 140, 589, + 798, 192, 554, + 758, 255, 502, + 700, 327, 422, + 607, 408, 287, + 444, 498, 4, + 53, 596, 0, + 0, 700, 0, + 0, 811, 0, + 0, 926, 0, + 0, 1045, 0, + 0, 1167, 0, + 0, 1291, 0, + 0, 1418, 0, + 0, 1545, 0, + 0, 1674, 0, + 0, 1804, 0, + 0, 1934, 0, + 0, 2065, 0, + 0, 2196, 0, + 0, 2327, 0, + 0, 2458, 0, + 0, 2590, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 996, 158, 746, + 982, 197, 728, + 963, 244, 702, + 936, 300, 666, + 897, 365, 611, + 839, 440, 527, + 748, 525, 382, + 589, 617, 65, + 214, 718, 0, + 0, 824, 0, + 0, 936, 0, + 0, 1053, 0, + 0, 1173, 0, + 0, 1296, 0, + 0, 1421, 0, + 0, 1548, 0, + 0, 1676, 0, + 0, 1805, 0, + 0, 1935, 0, + 0, 2065, 0, + 0, 2196, 0, + 0, 2327, 0, + 0, 2459, 0, + 0, 2590, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1141, 230, 879, + 1131, 263, 865, + 1118, 304, 846, + 1099, 354, 820, + 1072, 412, 782, + 1034, 481, 726, + 976, 558, 638, + 887, 645, 484, + 730, 740, 135, + 367, 842, 0, + 0, 950, 0, + 0, 1064, 0, + 0, 1181, 0, + 0, 1302, 0, + 0, 1426, 0, + 0, 1552, 0, + 0, 1679, 0, + 0, 1807, 0, + 0, 1937, 0, + 0, 2067, 0, + 0, 2197, 0, + 0, 2328, 0, + 0, 2459, 0, + 0, 2591, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1284, 312, 1011, + 1276, 340, 1001, + 1266, 374, 987, + 1253, 417, 968, + 1234, 468, 941, + 1207, 529, 902, + 1169, 600, 844, + 1112, 679, 753, + 1024, 768, 593, + 869, 865, 214, + 514, 968, 0, + 0, 1078, 0, + 0, 1192, 0, + 0, 1311, 0, + 0, 1432, 0, + 0, 1557, 0, + 0, 1683, 0, + 0, 1810, 0, + 0, 1939, 0, + 0, 2068, 0, + 0, 2198, 0, + 0, 2329, 0, + 0, 2460, 0, + 0, 2591, 0, + 0, 2723, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1423, 402, 1144, + 1418, 425, 1136, + 1410, 454, 1126, + 1401, 490, 1112, + 1387, 534, 1092, + 1368, 587, 1064, + 1342, 650, 1025, + 1304, 722, 966, + 1247, 803, 872, + 1159, 893, 706, + 1006, 991, 302, + 657, 1096, 0, + 0, 1206, 0, + 0, 1322, 0, + 0, 1441, 0, + 0, 1563, 0, + 0, 1687, 0, + 0, 1814, 0, + 0, 1941, 0, + 0, 2070, 0, + 0, 2200, 0, + 0, 2330, 0, + 0, 2461, 0, + 0, 2592, 0, + 0, 2723, 0, + 0, 2855, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1561, 500, 1276, + 1557, 518, 1270, + 1551, 542, 1263, + 1544, 572, 1252, + 1534, 609, 1238, + 1521, 655, 1218, + 1502, 709, 1190, + 1476, 773, 1150, + 1438, 846, 1090, + 1382, 929, 994, + 1294, 1020, 824, + 1142, 1119, 399, + 797, 1225, 0, + 0, 1336, 0, + 0, 1452, 0, + 0, 1571, 0, + 0, 1694, 0, + 0, 1819, 0, + 0, 1945, 0, + 0, 2073, 0, + 0, 2202, 0, + 0, 2332, 0, + 0, 2462, 0, + 0, 2593, 0, + 0, 2724, 0, + 0, 2855, 0, + 0, 2987, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1697, 605, 1408, + 1694, 619, 1404, + 1690, 639, 1398, + 1684, 663, 1391, + 1677, 694, 1380, + 1667, 732, 1366, + 1654, 778, 1346, + 1635, 833, 1317, + 1609, 898, 1277, + 1571, 973, 1216, + 1515, 1056, 1119, + 1428, 1148, 945, + 1277, 1248, 502, + 935, 1354, 0, + 0, 1466, 0, + 0, 1582, 0, + 0, 1702, 0, + 0, 1825, 0, + 0, 1950, 0, + 0, 2077, 0, + 0, 2205, 0, + 0, 2334, 0, + 0, 2464, 0, + 0, 2594, 0, + 0, 2725, 0, + 0, 2856, 0, + 0, 2987, 0, + 0, 3119, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1832, 715, 1540, + 1830, 727, 1537, + 1827, 742, 1533, + 1823, 761, 1527, + 1817, 786, 1519, + 1810, 818, 1509, + 1800, 856, 1494, + 1787, 903, 1474, + 1768, 959, 1446, + 1742, 1025, 1405, + 1704, 1100, 1343, + 1649, 1185, 1245, + 1562, 1277, 1069, + 1411, 1378, 612, + 1071, 1484, 0, + 0, 1597, 0, + 0, 1713, 0, + 0, 1833, 0, + 0, 1956, 0, + 0, 2082, 0, + 0, 2208, 0, + 0, 2337, 0, + 0, 2466, 0, + 0, 2596, 0, + 0, 2726, 0, + 0, 2857, 0, + 0, 2988, 0, + 0, 3119, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3514, 0, + 0, 3646, 0, + 1966, 830, 1672, + 1964, 840, 1670, + 1962, 851, 1667, + 1959, 867, 1663, + 1955, 887, 1657, + 1950, 912, 1649, + 1943, 943, 1639, + 1933, 983, 1624, + 1920, 1030, 1604, + 1901, 1087, 1575, + 1875, 1153, 1534, + 1837, 1229, 1472, + 1782, 1314, 1373, + 1695, 1407, 1194, + 1544, 1508, 726, + 1206, 1615, 0, + 0, 1728, 0, + 0, 1845, 0, + 0, 1965, 0, + 0, 2088, 0, + 0, 2213, 0, + 0, 2340, 0, + 0, 2468, 0, + 0, 2598, 0, + 0, 2728, 0, + 0, 2858, 0, + 0, 2989, 0, + 0, 3120, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3646, 0, + 2100, 950, 1805, + 2099, 957, 1803, + 2097, 966, 1801, + 2095, 978, 1797, + 2092, 993, 1793, + 2088, 1013, 1787, + 2083, 1039, 1780, + 2075, 1071, 1769, + 2066, 1110, 1754, + 2052, 1159, 1734, + 2034, 1216, 1705, + 2007, 1282, 1663, + 1970, 1359, 1601, + 1914, 1444, 1502, + 1828, 1538, 1322, + 1678, 1639, 844, + 1341, 1746, 0, + 0, 1859, 0, + 0, 1976, 0, + 0, 2097, 0, + 0, 2220, 0, + 0, 2345, 0, + 0, 2472, 0, + 0, 2600, 0, + 0, 2730, 0, + 0, 2860, 0, + 0, 2990, 0, + 0, 3121, 0, + 0, 3252, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3647, 0, + 2233, 1072, 1937, + 2232, 1077, 1935, + 2231, 1084, 1934, + 2229, 1093, 1931, + 2227, 1106, 1928, + 2224, 1121, 1924, + 2220, 1142, 1918, + 2215, 1167, 1910, + 2208, 1200, 1900, + 2198, 1239, 1885, + 2185, 1288, 1864, + 2166, 1345, 1836, + 2140, 1412, 1794, + 2103, 1489, 1731, + 2047, 1575, 1631, + 1960, 1669, 1450, + 1810, 1770, 966, + 1475, 1878, 0, + 0, 1990, 0, + 0, 2108, 0, + 0, 2228, 0, + 0, 2352, 0, + 0, 2477, 0, + 0, 2604, 0, + 0, 2732, 0, + 0, 2862, 0, + 0, 2992, 0, + 0, 3122, 0, + 0, 3253, 0, + 0, 3384, 0, + 0, 3515, 0, + 0, 3647, 0, + 2366, 1196, 2069, + 2365, 1200, 2068, + 2365, 1206, 2067, + 2363, 1213, 2065, + 2362, 1222, 2063, + 2360, 1234, 2059, + 2357, 1250, 2055, + 2353, 1271, 2049, + 2347, 1297, 2041, + 2340, 1329, 2031, + 2330, 1369, 2016, + 2317, 1418, 1995, + 2298, 1475, 1966, + 2272, 1543, 1925, + 2235, 1620, 1862, + 2180, 1706, 1762, + 2093, 1800, 1579, + 1943, 1901, 1090, + 1608, 2009, 0, + 0, 2122, 0, + 0, 2239, 0, + 0, 2360, 0, + 0, 2483, 0, + 0, 2609, 0, + 0, 2736, 0, + 0, 2864, 0, + 0, 2994, 0, + 0, 3124, 0, + 0, 3254, 0, + 0, 3385, 0, + 0, 3516, 0, + 0, 3648, 0, + 2499, 1323, 2201, + 2498, 1326, 2200, + 2498, 1330, 2199, + 2497, 1335, 2198, + 2496, 1342, 2196, + 2494, 1352, 2194, + 2492, 1364, 2191, + 2489, 1380, 2186, + 2485, 1400, 2181, + 2480, 1426, 2173, + 2473, 1459, 2162, + 2463, 1499, 2147, + 2449, 1548, 2127, + 2431, 1606, 2098, + 2405, 1674, 2056, + 2367, 1751, 1993, + 2312, 1837, 1892, + 2225, 1931, 1709, + 2076, 2033, 1216, + 1741, 2141, 0, + 0, 2254, 0, + 0, 2371, 0, + 0, 2492, 0, + 0, 2615, 0, + 0, 2741, 0, + 0, 2868, 0, + 0, 2996, 0, + 0, 3126, 0, + 0, 3256, 0, + 0, 3386, 0, + 0, 3517, 0, + 0, 3648, 0, + 2631, 1450, 2333, + 2631, 1453, 2333, + 2631, 1456, 2332, + 2630, 1460, 2331, + 2629, 1465, 2330, + 2628, 1473, 2328, + 2626, 1482, 2325, + 2624, 1494, 2322, + 2621, 1510, 2318, + 2617, 1531, 2312, + 2612, 1557, 2304, + 2605, 1590, 2294, + 2595, 1630, 2279, + 2582, 1679, 2258, + 2563, 1737, 2229, + 2537, 1805, 2187, + 2500, 1882, 2124, + 2444, 1968, 2023, + 2358, 2063, 1840, + 2208, 2164, 1343, + 1874, 2272, 0, + 0, 2386, 0, + 0, 2503, 0, + 0, 2624, 0, + 0, 2747, 0, + 0, 2873, 0, + 0, 3000, 0, + 0, 3128, 0, + 0, 3258, 0, + 0, 3388, 0, + 0, 3518, 0, + 0, 3649, 0, + 2764, 1579, 2465, + 2764, 1581, 2465, + 2763, 1583, 2464, + 2763, 1586, 2464, + 2762, 1590, 2463, + 2761, 1596, 2461, + 2760, 1603, 2460, + 2758, 1613, 2457, + 2756, 1625, 2454, + 2753, 1641, 2450, + 2749, 1662, 2444, + 2744, 1688, 2436, + 2737, 1721, 2425, + 2727, 1761, 2410, + 2714, 1810, 2390, + 2695, 1868, 2361, + 2669, 1936, 2319, + 2632, 2013, 2256, + 2576, 2100, 2155, + 2490, 2194, 1971, + 2341, 2296, 1472, + 2006, 2404, 0, + 0, 2518, 0, + 0, 2635, 0, + 0, 2756, 0, + 0, 2879, 0, + 0, 3005, 0, + 0, 3132, 0, + 0, 3261, 0, + 0, 3390, 0, + 0, 3520, 0, + 0, 3650, 0, + 2896, 1709, 2597, + 2896, 1710, 2597, + 2896, 1712, 2597, + 2895, 1714, 2596, + 2895, 1717, 2595, + 2894, 1721, 2594, + 2893, 1727, 2593, + 2892, 1734, 2591, + 2891, 1744, 2589, + 2888, 1756, 2586, + 2886, 1772, 2581, + 2882, 1793, 2576, + 2876, 1819, 2568, + 2869, 1852, 2557, + 2859, 1892, 2542, + 2846, 1942, 2522, + 2827, 2000, 2492, + 2801, 2068, 2450, + 2764, 2145, 2387, + 2709, 2232, 2286, + 2622, 2326, 2102, + 2473, 2428, 1601, + 2139, 2536, 0, + 0, 2650, 0, + 0, 2767, 0, + 0, 2888, 0, + 0, 3011, 0, + 0, 3137, 0, + 0, 3264, 0, + 0, 3393, 0, + 0, 3522, 0, + 0, 3652, 0, + 3029, 1839, 2729, + 3029, 1840, 2729, + 3028, 1841, 2729, + 3028, 1843, 2729, + 3028, 1845, 2728, + 3027, 1849, 2727, + 3026, 1853, 2726, + 3026, 1858, 2725, + 3024, 1865, 2723, + 3023, 1875, 2721, + 3021, 1887, 2718, + 3018, 1904, 2713, + 3014, 1924, 2708, + 3009, 1950, 2700, + 3001, 1983, 2689, + 2992, 2024, 2674, + 2978, 2073, 2653, + 2960, 2132, 2624, + 2934, 2199, 2582, + 2896, 2277, 2519, + 2841, 2363, 2418, + 2754, 2458, 2234, + 2605, 2560, 1732, + 2271, 2668, 0, + 0, 2781, 0, + 0, 2899, 0, + 0, 3020, 0, + 0, 3144, 0, + 0, 3269, 0, + 0, 3396, 0, + 0, 3525, 0, + 0, 3654, 0, + 3161, 1970, 2862, + 3161, 1970, 2861, + 3161, 1971, 2861, + 3160, 1973, 2861, + 3160, 1975, 2860, + 3160, 1977, 2860, + 3159, 1980, 2859, + 3159, 1984, 2858, + 3158, 1990, 2857, + 3157, 1997, 2855, + 3155, 2006, 2853, + 3153, 2019, 2850, + 3150, 2035, 2845, + 3146, 2056, 2839, + 3141, 2082, 2832, + 3133, 2115, 2821, + 3124, 2156, 2806, + 3110, 2205, 2785, + 3092, 2263, 2756, + 3066, 2331, 2714, + 3028, 2409, 2651, + 2973, 2495, 2550, + 2887, 2590, 2365, + 2737, 2692, 1862, + 2404, 2800, 0, + 0, 2914, 0, + 0, 3031, 0, + 0, 3152, 0, + 0, 3276, 0, + 0, 3401, 0, + 0, 3528, 0, + 0, 3657, 0, + 3293, 2101, 2994, + 3293, 2101, 2994, + 3293, 2102, 2993, + 3293, 2103, 2993, + 3293, 2104, 2993, + 3292, 2106, 2992, + 3292, 2109, 2992, + 3291, 2112, 2991, + 3291, 2116, 2990, + 3290, 2121, 2989, + 3289, 2129, 2987, + 3287, 2138, 2985, + 3285, 2151, 2982, + 3282, 2167, 2977, + 3278, 2187, 2971, + 3273, 2214, 2963, + 3266, 2247, 2953, + 3256, 2287, 2938, + 3242, 2337, 2917, + 3224, 2395, 2888, + 3198, 2463, 2846, + 3160, 2541, 2783, + 3105, 2627, 2681, + 3019, 2722, 2497, + 2870, 2824, 1993, + 2536, 2932, 0, + 0, 3046, 0, + 0, 3163, 0, + 0, 3284, 0, + 0, 3408, 0, + 0, 3533, 0, + 0, 3660, 0, + 3425, 2232, 3126, + 3425, 2232, 3126, + 3425, 2233, 3126, + 3425, 2234, 3125, + 3425, 2235, 3125, + 3425, 2236, 3125, + 3424, 2238, 3124, + 3424, 2240, 3124, + 3424, 2243, 3123, + 3423, 2248, 3122, + 3422, 2253, 3121, + 3421, 2260, 3119, + 3419, 2270, 3117, + 3417, 2282, 3114, + 3414, 2299, 3109, + 3410, 2319, 3103, + 3405, 2346, 3095, + 3398, 2379, 3085, + 3388, 2419, 3070, + 3375, 2469, 3049, + 3356, 2527, 3020, + 3330, 2595, 2978, + 3293, 2673, 2915, + 3237, 2759, 2813, + 3151, 2854, 2629, + 3002, 2956, 2124, + 2668, 3064, 0, + 0, 3178, 0, + 0, 3295, 0, + 0, 3416, 0, + 0, 3540, 0, + 0, 3665, 0, + 3557, 2364, 3258, + 3557, 2364, 3258, + 3557, 2364, 3258, + 3557, 2365, 3258, + 3557, 2366, 3257, + 3557, 2367, 3257, + 3557, 2368, 3257, + 3557, 2370, 3256, + 3556, 2372, 3256, + 3556, 2375, 3255, + 3555, 2379, 3254, + 3554, 2385, 3253, + 3553, 2392, 3251, + 3551, 2402, 3249, + 3549, 2414, 3246, + 3546, 2430, 3241, + 3542, 2451, 3235, + 3537, 2477, 3228, + 3530, 2510, 3217, + 3520, 2551, 3202, + 3507, 2600, 3181, + 3488, 2659, 3152, + 3462, 2727, 3110, + 3425, 2805, 3047, + 3369, 2891, 2945, + 3283, 2986, 2761, + 3134, 3088, 2256, + 2800, 3196, 0, + 0, 3310, 0, + 0, 3427, 0, + 0, 3548, 0, + 0, 3672, 0, + 3690, 2495, 3390, + 3690, 2495, 3390, + 3690, 2496, 3390, + 3689, 2496, 3390, + 3689, 2497, 3390, + 3689, 2497, 3389, + 3689, 2498, 3389, + 3689, 2500, 3389, + 3689, 2502, 3389, + 3688, 2504, 3388, + 3688, 2507, 3387, + 3687, 2511, 3386, + 3686, 2517, 3385, + 3685, 2524, 3383, + 3683, 2534, 3381, + 3681, 2546, 3378, + 3678, 2562, 3373, + 3674, 2583, 3367, + 3669, 2609, 3360, + 3662, 2642, 3349, + 3652, 2683, 3334, + 3639, 2732, 3313, + 3620, 2791, 3284, + 3594, 2859, 3242, + 3557, 2937, 3179, + 3502, 3023, 3077, + 3415, 3118, 2893, + 3266, 3220, 2387, + 2933, 3328, 0, + 0, 3442, 0, + 0, 3559, 0, + 0, 3680, 0, + 3822, 2627, 3522, + 3822, 2627, 3522, + 3822, 2627, 3522, + 3822, 2628, 3522, + 3822, 2628, 3522, + 3821, 2629, 3522, + 3821, 2629, 3522, + 3821, 2630, 3521, + 3821, 2632, 3521, + 3821, 2634, 3521, + 3820, 2636, 3520, + 3820, 2639, 3519, + 3819, 2643, 3518, + 3818, 2649, 3517, + 3817, 2656, 3515, + 3815, 2666, 3513, + 3813, 2678, 3510, + 3810, 2694, 3505, + 3807, 2715, 3500, + 3801, 2741, 3492, + 3794, 2774, 3481, + 3784, 2815, 3466, + 3771, 2864, 3445, + 3752, 2923, 3416, + 3726, 2991, 3374, + 3689, 3069, 3311, + 3634, 3155, 3209, + 3547, 3250, 3025, + 3398, 3352, 2519, + 3065, 3460, 0, + 0, 3574, 0, + 0, 3691, 0, + 3954, 2759, 3654, + 3954, 2759, 3654, + 3954, 2759, 3654, + 3954, 2759, 3654, + 3954, 2760, 3654, + 3954, 2760, 3654, + 3954, 2761, 3654, + 3953, 2761, 3654, + 3953, 2762, 3653, + 3953, 2764, 3653, + 3953, 2766, 3653, + 3952, 2768, 3652, + 3952, 2771, 3651, + 3951, 2775, 3650, + 3950, 2781, 3649, + 3949, 2788, 3647, + 3948, 2798, 3645, + 3945, 2810, 3642, + 3943, 2826, 3637, + 3939, 2847, 3632, + 3933, 2873, 3624, + 3926, 2906, 3613, + 3916, 2947, 3598, + 3903, 2996, 3577, + 3884, 3055, 3548, + 3858, 3123, 3506, + 3821, 3201, 3443, + 3766, 3287, 3341, + 3679, 3382, 3157, + 3530, 3484, 2651, + 3197, 3592, 0, + 0, 3706, 0, + 4086, 2891, 3786, + 4086, 2891, 3786, + 4086, 2891, 3786, + 4086, 2891, 3786, + 4086, 2891, 3786, + 4086, 2892, 3786, + 4086, 2892, 3786, + 4086, 2893, 3786, + 4086, 2893, 3786, + 4085, 2894, 3785, + 4085, 2896, 3785, + 4085, 2898, 3785, + 4085, 2900, 3784, + 4084, 2903, 3783, + 4083, 2907, 3782, + 4083, 2913, 3781, + 4081, 2920, 3779, + 4080, 2930, 3777, + 4078, 2942, 3774, + 4075, 2958, 3769, + 4071, 2979, 3764, + 4065, 3005, 3756, + 4058, 3038, 3745, + 4049, 3079, 3730, + 4035, 3129, 3709, + 4017, 3187, 3680, + 3991, 3255, 3638, + 3953, 3333, 3575, + 3898, 3419, 3473, + 3811, 3514, 3289, + 3662, 3616, 2783, + 3329, 3725, 0, + 4095, 3023, 3918, + 4095, 3023, 3918, + 4095, 3023, 3918, + 4095, 3023, 3918, + 4095, 3023, 3918, + 4095, 3023, 3918, + 4095, 3024, 3918, + 4095, 3024, 3918, + 4095, 3025, 3918, + 4095, 3025, 3918, + 4095, 3026, 3918, + 4095, 3028, 3917, + 4095, 3030, 3917, + 4095, 3032, 3916, + 4095, 3035, 3916, + 4095, 3039, 3915, + 4095, 3045, 3913, + 4095, 3052, 3911, + 4095, 3062, 3909, + 4095, 3074, 3906, + 4095, 3090, 3902, + 4095, 3111, 3896, + 4095, 3137, 3888, + 4095, 3171, 3877, + 4095, 3211, 3862, + 4095, 3261, 3842, + 4095, 3319, 3812, + 4095, 3387, 3770, + 4085, 3465, 3707, + 4030, 3551, 3605, + 3944, 3646, 3421, + 3794, 3748, 2915, + 4095, 3155, 4050, + 4095, 3155, 4050, + 4095, 3155, 4050, + 4095, 3155, 4050, + 4095, 3155, 4050, + 4095, 3155, 4050, + 4095, 3155, 4050, + 4095, 3156, 4050, + 4095, 3156, 4050, + 4095, 3157, 4050, + 4095, 3158, 4050, + 4095, 3159, 4050, + 4095, 3160, 4049, + 4095, 3162, 4049, + 4095, 3164, 4048, + 4095, 3167, 4048, + 4095, 3171, 4047, + 4095, 3177, 4045, + 4095, 3184, 4044, + 4095, 3194, 4041, + 4095, 3206, 4038, + 4095, 3222, 4034, + 4095, 3243, 4028, + 4095, 3270, 4020, + 4095, 3303, 4009, + 4095, 3343, 3994, + 4095, 3393, 3974, + 4095, 3451, 3944, + 4095, 3519, 3902, + 4095, 3597, 3839, + 4095, 3684, 3738, + 4076, 3778, 3553, + 0, 0, 36, + 0, 24, 0, + 0, 91, 0, + 0, 168, 0, + 0, 254, 0, + 0, 348, 0, + 0, 449, 0, + 0, 557, 0, + 0, 669, 0, + 0, 787, 0, + 0, 907, 0, + 0, 1031, 0, + 0, 1156, 0, + 0, 1283, 0, + 0, 1411, 0, + 0, 1541, 0, + 0, 1671, 0, + 0, 1801, 0, + 0, 1932, 0, + 0, 2063, 0, + 0, 2195, 0, + 0, 2326, 0, + 0, 2458, 0, + 0, 2590, 0, + 0, 2722, 0, + 0, 2853, 0, + 0, 2985, 0, + 0, 3117, 0, + 0, 3249, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 67, 0, 149, + 0, 42, 77, + 0, 107, 0, + 0, 181, 0, + 0, 264, 0, + 0, 356, 0, + 0, 456, 0, + 0, 562, 0, + 0, 674, 0, + 0, 790, 0, + 0, 910, 0, + 0, 1033, 0, + 0, 1158, 0, + 0, 1284, 0, + 0, 1412, 0, + 0, 1541, 0, + 0, 1671, 0, + 0, 1801, 0, + 0, 1932, 0, + 0, 2063, 0, + 0, 2195, 0, + 0, 2326, 0, + 0, 2458, 0, + 0, 2590, 0, + 0, 2722, 0, + 0, 2853, 0, + 0, 2985, 0, + 0, 3117, 0, + 0, 3249, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 303, 13, 267, + 236, 65, 212, + 127, 127, 127, + 0, 198, 0, + 0, 279, 0, + 0, 368, 0, + 0, 465, 0, + 0, 570, 0, + 0, 680, 0, + 0, 795, 0, + 0, 913, 0, + 0, 1035, 0, + 0, 1160, 0, + 0, 1286, 0, + 0, 1413, 0, + 0, 1542, 0, + 0, 1672, 0, + 0, 1802, 0, + 0, 1933, 0, + 0, 2064, 0, + 0, 2195, 0, + 0, 2326, 0, + 0, 2458, 0, + 0, 2590, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2985, 0, + 0, 3117, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 500, 45, 387, + 458, 94, 346, + 394, 152, 284, + 292, 220, 186, + 105, 297, 8, + 0, 383, 0, + 0, 478, 0, + 0, 579, 0, + 0, 687, 0, + 0, 801, 0, + 0, 918, 0, + 0, 1039, 0, + 0, 1162, 0, + 0, 1288, 0, + 0, 1415, 0, + 0, 1543, 0, + 0, 1673, 0, + 0, 1803, 0, + 0, 1933, 0, + 0, 2064, 0, + 0, 2195, 0, + 0, 2327, 0, + 0, 2458, 0, + 0, 2590, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 676, 85, 511, + 647, 130, 480, + 606, 184, 434, + 545, 248, 366, + 447, 321, 254, + 271, 403, 43, + 0, 494, 0, + 0, 592, 0, + 0, 697, 0, + 0, 808, 0, + 0, 924, 0, + 0, 1044, 0, + 0, 1166, 0, + 0, 1291, 0, + 0, 1417, 0, + 0, 1545, 0, + 0, 1674, 0, + 0, 1803, 0, + 0, 1934, 0, + 0, 2064, 0, + 0, 2196, 0, + 0, 2327, 0, + 0, 2458, 0, + 0, 2590, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 837, 134, 636, + 818, 175, 613, + 790, 224, 579, + 750, 282, 531, + 690, 350, 456, + 596, 428, 332, + 427, 514, 85, + 12, 609, 0, + 0, 711, 0, + 0, 819, 0, + 0, 932, 0, + 0, 1050, 0, + 0, 1171, 0, + 0, 1294, 0, + 0, 1420, 0, + 0, 1547, 0, + 0, 1675, 0, + 0, 1805, 0, + 0, 1935, 0, + 0, 2065, 0, + 0, 2196, 0, + 0, 2327, 0, + 0, 2459, 0, + 0, 2590, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 991, 192, 763, + 977, 228, 746, + 957, 272, 721, + 930, 325, 686, + 891, 387, 634, + 832, 459, 554, + 740, 540, 419, + 577, 630, 136, + 186, 728, 0, + 0, 832, 0, + 0, 943, 0, + 0, 1058, 0, + 0, 1177, 0, + 0, 1299, 0, + 0, 1423, 0, + 0, 1550, 0, + 0, 1677, 0, + 0, 1806, 0, + 0, 1936, 0, + 0, 2066, 0, + 0, 2197, 0, + 0, 2328, 0, + 0, 2459, 0, + 0, 2591, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1138, 259, 892, + 1128, 290, 878, + 1114, 329, 860, + 1095, 376, 834, + 1068, 432, 798, + 1029, 497, 743, + 971, 572, 659, + 880, 657, 514, + 721, 749, 197, + 347, 850, 0, + 0, 956, 0, + 0, 1068, 0, + 0, 1185, 0, + 0, 1305, 0, + 0, 1428, 0, + 0, 1553, 0, + 0, 1680, 0, + 0, 1808, 0, + 0, 1937, 0, + 0, 2067, 0, + 0, 2198, 0, + 0, 2328, 0, + 0, 2460, 0, + 0, 2591, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1281, 336, 1021, + 1274, 362, 1011, + 1264, 395, 997, + 1250, 436, 978, + 1231, 486, 952, + 1204, 544, 914, + 1166, 613, 858, + 1109, 690, 770, + 1019, 777, 616, + 862, 872, 267, + 499, 974, 0, + 0, 1082, 0, + 0, 1196, 0, + 0, 1314, 0, + 0, 1435, 0, + 0, 1558, 0, + 0, 1684, 0, + 0, 1811, 0, + 0, 1939, 0, + 0, 2069, 0, + 0, 2199, 0, + 0, 2329, 0, + 0, 2460, 0, + 0, 2591, 0, + 0, 2723, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1421, 422, 1151, + 1416, 444, 1143, + 1408, 472, 1133, + 1398, 506, 1119, + 1385, 549, 1100, + 1366, 601, 1073, + 1339, 661, 1034, + 1301, 732, 976, + 1245, 811, 885, + 1156, 900, 725, + 1001, 997, 346, + 646, 1100, 0, + 0, 1210, 0, + 0, 1324, 0, + 0, 1443, 0, + 0, 1565, 0, + 0, 1689, 0, + 0, 1815, 0, + 0, 1942, 0, + 0, 2071, 0, + 0, 2200, 0, + 0, 2330, 0, + 0, 2461, 0, + 0, 2592, 0, + 0, 2723, 0, + 0, 2855, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1559, 516, 1281, + 1555, 534, 1276, + 1550, 557, 1268, + 1543, 586, 1258, + 1533, 622, 1244, + 1519, 666, 1224, + 1500, 719, 1197, + 1474, 782, 1157, + 1436, 854, 1098, + 1380, 935, 1004, + 1291, 1025, 838, + 1138, 1123, 434, + 789, 1228, 0, + 0, 1339, 0, + 0, 1454, 0, + 0, 1573, 0, + 0, 1695, 0, + 0, 1820, 0, + 0, 1946, 0, + 0, 2074, 0, + 0, 2202, 0, + 0, 2332, 0, + 0, 2462, 0, + 0, 2593, 0, + 0, 2724, 0, + 0, 2855, 0, + 0, 2987, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1696, 617, 1412, + 1693, 632, 1408, + 1689, 651, 1402, + 1683, 674, 1395, + 1676, 704, 1384, + 1666, 741, 1370, + 1653, 787, 1350, + 1634, 841, 1322, + 1608, 905, 1282, + 1570, 978, 1222, + 1514, 1061, 1126, + 1426, 1152, 956, + 1274, 1251, 531, + 929, 1357, 0, + 0, 1468, 0, + 0, 1584, 0, + 0, 1703, 0, + 0, 1826, 0, + 0, 1951, 0, + 0, 2077, 0, + 0, 2205, 0, + 0, 2334, 0, + 0, 2464, 0, + 0, 2594, 0, + 0, 2725, 0, + 0, 2856, 0, + 0, 2987, 0, + 0, 3119, 0, + 0, 3251, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1831, 725, 1543, + 1829, 737, 1540, + 1826, 752, 1536, + 1822, 771, 1530, + 1817, 795, 1523, + 1809, 826, 1512, + 1800, 864, 1498, + 1786, 910, 1478, + 1767, 965, 1449, + 1741, 1030, 1409, + 1703, 1105, 1348, + 1648, 1188, 1251, + 1560, 1280, 1077, + 1409, 1380, 634, + 1067, 1486, 0, + 0, 1598, 0, + 0, 1714, 0, + 0, 1834, 0, + 0, 1957, 0, + 0, 2082, 0, + 0, 2209, 0, + 0, 2337, 0, + 0, 2466, 0, + 0, 2596, 0, + 0, 2726, 0, + 0, 2857, 0, + 0, 2988, 0, + 0, 3119, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3514, 0, + 0, 3646, 0, + 1965, 838, 1675, + 1964, 847, 1672, + 1962, 859, 1669, + 1959, 874, 1665, + 1955, 894, 1659, + 1949, 918, 1652, + 1942, 950, 1641, + 1932, 988, 1626, + 1919, 1035, 1606, + 1900, 1092, 1578, + 1874, 1157, 1537, + 1837, 1232, 1475, + 1781, 1317, 1377, + 1694, 1409, 1201, + 1543, 1510, 744, + 1203, 1617, 0, + 0, 1729, 0, + 0, 1845, 0, + 0, 1966, 0, + 0, 2089, 0, + 0, 2214, 0, + 0, 2341, 0, + 0, 2469, 0, + 0, 2598, 0, + 0, 2728, 0, + 0, 2858, 0, + 0, 2989, 0, + 0, 3120, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3646, 0, + 2099, 956, 1806, + 2098, 963, 1805, + 2097, 972, 1802, + 2094, 983, 1799, + 2091, 999, 1795, + 2087, 1019, 1789, + 2082, 1044, 1781, + 2075, 1076, 1771, + 2065, 1115, 1756, + 2052, 1162, 1736, + 2033, 1219, 1707, + 2007, 1285, 1666, + 1969, 1361, 1604, + 1914, 1446, 1505, + 1827, 1539, 1326, + 1676, 1640, 858, + 1338, 1747, 0, + 0, 1860, 0, + 0, 1977, 0, + 0, 2097, 0, + 0, 2220, 0, + 0, 2345, 0, + 0, 2472, 0, + 0, 2601, 0, + 0, 2730, 0, + 0, 2860, 0, + 0, 2990, 0, + 0, 3121, 0, + 0, 3252, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3647, 0, + 2233, 1076, 1938, + 2232, 1082, 1937, + 2231, 1089, 1935, + 2229, 1098, 1933, + 2227, 1110, 1929, + 2224, 1125, 1925, + 2220, 1146, 1919, + 2215, 1171, 1912, + 2208, 1203, 1901, + 2198, 1243, 1886, + 2184, 1291, 1866, + 2166, 1348, 1837, + 2140, 1415, 1796, + 2102, 1491, 1733, + 2047, 1576, 1634, + 1960, 1670, 1454, + 1810, 1771, 976, + 1473, 1878, 0, + 0, 1991, 0, + 0, 2108, 0, + 0, 2229, 0, + 0, 2352, 0, + 0, 2477, 0, + 0, 2604, 0, + 0, 2732, 0, + 0, 2862, 0, + 0, 2992, 0, + 0, 3122, 0, + 0, 3253, 0, + 0, 3384, 0, + 0, 3516, 0, + 0, 3647, 0, + 2366, 1200, 2070, + 2365, 1204, 2069, + 2364, 1209, 2068, + 2363, 1216, 2066, + 2361, 1226, 2063, + 2359, 1238, 2060, + 2356, 1253, 2056, + 2352, 1274, 2050, + 2347, 1299, 2042, + 2340, 1332, 2032, + 2330, 1371, 2017, + 2317, 1420, 1997, + 2298, 1477, 1968, + 2272, 1544, 1926, + 2235, 1621, 1863, + 2179, 1707, 1763, + 2092, 1801, 1582, + 1943, 1902, 1098, + 1607, 2010, 0, + 0, 2123, 0, + 0, 2240, 0, + 0, 2360, 0, + 0, 2484, 0, + 0, 2609, 0, + 0, 2736, 0, + 0, 2864, 0, + 0, 2994, 0, + 0, 3124, 0, + 0, 3254, 0, + 0, 3385, 0, + 0, 3516, 0, + 0, 3648, 0, + 2499, 1325, 2202, + 2498, 1328, 2201, + 2498, 1332, 2200, + 2497, 1338, 2199, + 2495, 1345, 2197, + 2494, 1354, 2195, + 2492, 1367, 2191, + 2489, 1382, 2187, + 2485, 1403, 2181, + 2480, 1429, 2174, + 2472, 1461, 2163, + 2463, 1501, 2148, + 2449, 1550, 2128, + 2431, 1608, 2099, + 2404, 1675, 2057, + 2367, 1752, 1994, + 2312, 1838, 1894, + 2225, 1932, 1711, + 2075, 2033, 1222, + 1740, 2141, 0, + 0, 2254, 0, + 0, 2371, 0, + 0, 2492, 0, + 0, 2616, 0, + 0, 2741, 0, + 0, 2868, 0, + 0, 2996, 0, + 0, 3126, 0, + 0, 3256, 0, + 0, 3386, 0, + 0, 3517, 0, + 0, 3648, 0, + 2631, 1452, 2334, + 2631, 1455, 2333, + 2630, 1458, 2332, + 2630, 1462, 2331, + 2629, 1467, 2330, + 2628, 1474, 2328, + 2626, 1484, 2326, + 2624, 1496, 2323, + 2621, 1512, 2319, + 2617, 1533, 2313, + 2612, 1559, 2305, + 2605, 1591, 2294, + 2595, 1631, 2279, + 2581, 1680, 2259, + 2563, 1738, 2230, + 2537, 1806, 2188, + 2499, 1883, 2125, + 2444, 1969, 2024, + 2357, 2063, 1842, + 2208, 2165, 1348, + 1873, 2273, 0, + 0, 2386, 0, + 0, 2503, 0, + 0, 2624, 0, + 0, 2748, 0, + 0, 2873, 0, + 0, 3000, 0, + 0, 3129, 0, + 0, 3258, 0, + 0, 3388, 0, + 0, 3518, 0, + 0, 3649, 0, + 2764, 1581, 2466, + 2764, 1582, 2465, + 2763, 1585, 2465, + 2763, 1588, 2464, + 2762, 1592, 2463, + 2761, 1597, 2462, + 2760, 1605, 2460, + 2758, 1614, 2458, + 2756, 1626, 2454, + 2753, 1642, 2450, + 2749, 1663, 2444, + 2744, 1689, 2436, + 2737, 1722, 2426, + 2727, 1762, 2411, + 2714, 1811, 2390, + 2695, 1869, 2361, + 2669, 1937, 2319, + 2632, 2014, 2256, + 2576, 2100, 2155, + 2490, 2195, 1972, + 2340, 2297, 1475, + 2006, 2405, 0, + 0, 2518, 0, + 0, 2635, 0, + 0, 2756, 0, + 0, 2880, 0, + 0, 3005, 0, + 0, 3132, 0, + 0, 3261, 0, + 0, 3390, 0, + 0, 3520, 0, + 0, 3650, 0, + 2896, 1710, 2598, + 2896, 1711, 2597, + 2896, 1713, 2597, + 2895, 1715, 2596, + 2895, 1718, 2596, + 2894, 1723, 2595, + 2893, 1728, 2593, + 2892, 1735, 2592, + 2891, 1745, 2589, + 2888, 1757, 2586, + 2885, 1773, 2582, + 2882, 1794, 2576, + 2876, 1820, 2568, + 2869, 1853, 2557, + 2859, 1893, 2542, + 2846, 1942, 2522, + 2827, 2001, 2493, + 2801, 2068, 2451, + 2764, 2146, 2388, + 2709, 2232, 2287, + 2622, 2326, 2103, + 2473, 2428, 1604, + 2139, 2536, 0, + 0, 2650, 0, + 0, 2767, 0, + 0, 2888, 0, + 0, 3012, 0, + 0, 3137, 0, + 0, 3264, 0, + 0, 3393, 0, + 0, 3522, 0, + 0, 3652, 0, + 3029, 1840, 2730, + 3028, 1841, 2729, + 3028, 1842, 2729, + 3028, 1844, 2729, + 3028, 1846, 2728, + 3027, 1849, 2727, + 3026, 1854, 2726, + 3026, 1859, 2725, + 3024, 1866, 2723, + 3023, 1876, 2721, + 3021, 1888, 2718, + 3018, 1904, 2714, + 3014, 1925, 2708, + 3008, 1951, 2700, + 3001, 1984, 2689, + 2992, 2025, 2674, + 2978, 2074, 2654, + 2960, 2132, 2625, + 2933, 2200, 2582, + 2896, 2277, 2519, + 2841, 2364, 2418, + 2754, 2458, 2234, + 2605, 2560, 1733, + 2271, 2668, 0, + 0, 2782, 0, + 0, 2899, 0, + 0, 3020, 0, + 0, 3144, 0, + 0, 3269, 0, + 0, 3396, 0, + 0, 3525, 0, + 0, 3654, 0, + 3161, 1970, 2862, + 3161, 1971, 2862, + 3161, 1972, 2861, + 3160, 1973, 2861, + 3160, 1975, 2861, + 3160, 1978, 2860, + 3159, 1981, 2859, + 3159, 1985, 2858, + 3158, 1990, 2857, + 3156, 1998, 2855, + 3155, 2007, 2853, + 3153, 2020, 2850, + 3150, 2036, 2845, + 3146, 2056, 2840, + 3141, 2083, 2832, + 3133, 2115, 2821, + 3124, 2156, 2806, + 3110, 2205, 2785, + 3092, 2264, 2756, + 3066, 2332, 2714, + 3028, 2409, 2651, + 2973, 2495, 2550, + 2887, 2590, 2366, + 2737, 2692, 1864, + 2403, 2800, 0, + 0, 2914, 0, + 0, 3031, 0, + 0, 3152, 0, + 0, 3276, 0, + 0, 3401, 0, + 0, 3528, 0, + 0, 3657, 0, + 3293, 2101, 2994, + 3293, 2102, 2994, + 3293, 2103, 2993, + 3293, 2104, 2993, + 3293, 2105, 2993, + 3292, 2107, 2993, + 3292, 2109, 2992, + 3291, 2112, 2991, + 3291, 2116, 2990, + 3290, 2122, 2989, + 3289, 2129, 2987, + 3287, 2139, 2985, + 3285, 2151, 2982, + 3282, 2167, 2977, + 3278, 2188, 2972, + 3273, 2214, 2964, + 3266, 2247, 2953, + 3256, 2288, 2938, + 3242, 2337, 2917, + 3224, 2395, 2888, + 3198, 2463, 2846, + 3160, 2541, 2783, + 3105, 2627, 2682, + 3019, 2722, 2497, + 2869, 2824, 1994, + 2536, 2932, 0, + 0, 3046, 0, + 0, 3163, 0, + 0, 3284, 0, + 0, 3408, 0, + 0, 3533, 0, + 0, 3660, 0, + 3425, 2232, 3126, + 3425, 2233, 3126, + 3425, 2233, 3126, + 3425, 2234, 3125, + 3425, 2235, 3125, + 3425, 2236, 3125, + 3424, 2238, 3125, + 3424, 2241, 3124, + 3424, 2244, 3123, + 3423, 2248, 3122, + 3422, 2253, 3121, + 3421, 2261, 3119, + 3419, 2270, 3117, + 3417, 2283, 3114, + 3414, 2299, 3109, + 3410, 2320, 3103, + 3405, 2346, 3096, + 3398, 2379, 3085, + 3388, 2420, 3070, + 3375, 2469, 3049, + 3356, 2527, 3020, + 3330, 2595, 2978, + 3293, 2673, 2915, + 3237, 2759, 2814, + 3151, 2854, 2629, + 3002, 2956, 2125, + 2668, 3064, 0, + 0, 3178, 0, + 0, 3295, 0, + 0, 3416, 0, + 0, 3540, 0, + 0, 3665, 0, + 3557, 2364, 3258, + 3557, 2364, 3258, + 3557, 2365, 3258, + 3557, 2365, 3258, + 3557, 2366, 3257, + 3557, 2367, 3257, + 3557, 2368, 3257, + 3557, 2370, 3257, + 3556, 2372, 3256, + 3556, 2375, 3255, + 3555, 2380, 3254, + 3554, 2385, 3253, + 3553, 2392, 3251, + 3551, 2402, 3249, + 3549, 2414, 3246, + 3546, 2431, 3241, + 3542, 2451, 3235, + 3537, 2478, 3228, + 3530, 2511, 3217, + 3520, 2551, 3202, + 3507, 2601, 3181, + 3488, 2659, 3152, + 3462, 2727, 3110, + 3425, 2805, 3047, + 3369, 2891, 2945, + 3283, 2986, 2761, + 3134, 3088, 2256, + 2800, 3196, 0, + 0, 3310, 0, + 0, 3427, 0, + 0, 3548, 0, + 0, 3672, 0, + 3690, 2495, 3390, + 3690, 2496, 3390, + 3690, 2496, 3390, + 3689, 2496, 3390, + 3689, 2497, 3390, + 3689, 2498, 3389, + 3689, 2499, 3389, + 3689, 2500, 3389, + 3689, 2502, 3389, + 3688, 2504, 3388, + 3688, 2507, 3387, + 3687, 2511, 3386, + 3686, 2517, 3385, + 3685, 2524, 3383, + 3683, 2534, 3381, + 3681, 2546, 3378, + 3678, 2562, 3373, + 3674, 2583, 3368, + 3669, 2610, 3360, + 3662, 2643, 3349, + 3652, 2683, 3334, + 3639, 2733, 3313, + 3620, 2791, 3284, + 3594, 2859, 3242, + 3557, 2937, 3179, + 3502, 3023, 3077, + 3415, 3118, 2893, + 3266, 3220, 2388, + 2932, 3328, 0, + 0, 3442, 0, + 0, 3559, 0, + 0, 3680, 0, + 3822, 2627, 3522, + 3822, 2627, 3522, + 3822, 2628, 3522, + 3822, 2628, 3522, + 3822, 2628, 3522, + 3821, 2629, 3522, + 3821, 2630, 3522, + 3821, 2631, 3521, + 3821, 2632, 3521, + 3821, 2634, 3521, + 3820, 2636, 3520, + 3820, 2639, 3519, + 3819, 2643, 3518, + 3818, 2649, 3517, + 3817, 2656, 3515, + 3815, 2666, 3513, + 3813, 2678, 3510, + 3810, 2694, 3505, + 3807, 2715, 3500, + 3801, 2742, 3492, + 3794, 2775, 3481, + 3784, 2815, 3466, + 3771, 2865, 3445, + 3752, 2923, 3416, + 3726, 2991, 3374, + 3689, 3069, 3311, + 3634, 3155, 3209, + 3547, 3250, 3025, + 3398, 3352, 2520, + 3065, 3460, 0, + 0, 3574, 0, + 0, 3691, 0, + 3954, 2759, 3654, + 3954, 2759, 3654, + 3954, 2759, 3654, + 3954, 2759, 3654, + 3954, 2760, 3654, + 3954, 2760, 3654, + 3954, 2761, 3654, + 3953, 2762, 3654, + 3953, 2763, 3653, + 3953, 2764, 3653, + 3953, 2766, 3653, + 3952, 2768, 3652, + 3952, 2771, 3651, + 3951, 2775, 3650, + 3950, 2781, 3649, + 3949, 2788, 3647, + 3948, 2798, 3645, + 3945, 2810, 3642, + 3943, 2826, 3637, + 3939, 2847, 3632, + 3933, 2873, 3624, + 3926, 2907, 3613, + 3916, 2947, 3598, + 3903, 2997, 3577, + 3884, 3055, 3548, + 3858, 3123, 3506, + 3821, 3201, 3443, + 3766, 3287, 3341, + 3679, 3382, 3157, + 3530, 3484, 2651, + 3197, 3592, 0, + 0, 3706, 0, + 4086, 2891, 3786, + 4086, 2891, 3786, + 4086, 2891, 3786, + 4086, 2891, 3786, + 4086, 2891, 3786, + 4086, 2892, 3786, + 4086, 2892, 3786, + 4086, 2893, 3786, + 4086, 2894, 3786, + 4085, 2895, 3785, + 4085, 2896, 3785, + 4085, 2898, 3785, + 4085, 2900, 3784, + 4084, 2903, 3783, + 4083, 2907, 3782, + 4083, 2913, 3781, + 4081, 2920, 3779, + 4080, 2930, 3777, + 4078, 2942, 3774, + 4075, 2958, 3770, + 4071, 2979, 3764, + 4065, 3005, 3756, + 4058, 3039, 3745, + 4049, 3079, 3730, + 4035, 3129, 3709, + 4017, 3187, 3680, + 3991, 3255, 3638, + 3953, 3333, 3575, + 3898, 3419, 3473, + 3811, 3514, 3289, + 3662, 3616, 2783, + 3329, 3725, 0, + 4095, 3023, 3918, + 4095, 3023, 3918, + 4095, 3023, 3918, + 4095, 3023, 3918, + 4095, 3023, 3918, + 4095, 3023, 3918, + 4095, 3024, 3918, + 4095, 3024, 3918, + 4095, 3025, 3918, + 4095, 3026, 3918, + 4095, 3027, 3918, + 4095, 3028, 3917, + 4095, 3030, 3917, + 4095, 3032, 3916, + 4095, 3035, 3916, + 4095, 3039, 3915, + 4095, 3045, 3913, + 4095, 3052, 3911, + 4095, 3062, 3909, + 4095, 3074, 3906, + 4095, 3090, 3902, + 4095, 3111, 3896, + 4095, 3138, 3888, + 4095, 3171, 3877, + 4095, 3211, 3862, + 4095, 3261, 3842, + 4095, 3319, 3812, + 4095, 3387, 3770, + 4085, 3465, 3707, + 4030, 3551, 3606, + 3944, 3646, 3421, + 3794, 3748, 2915, + 4095, 3155, 4050, + 4095, 3155, 4050, + 4095, 3155, 4050, + 4095, 3155, 4050, + 4095, 3155, 4050, + 4095, 3155, 4050, + 4095, 3156, 4050, + 4095, 3156, 4050, + 4095, 3156, 4050, + 4095, 3157, 4050, + 4095, 3158, 4050, + 4095, 3159, 4050, + 4095, 3160, 4049, + 4095, 3162, 4049, + 4095, 3164, 4048, + 4095, 3167, 4048, + 4095, 3171, 4047, + 4095, 3177, 4045, + 4095, 3184, 4044, + 4095, 3194, 4041, + 4095, 3206, 4038, + 4095, 3222, 4034, + 4095, 3243, 4028, + 4095, 3270, 4020, + 4095, 3303, 4009, + 4095, 3343, 3994, + 4095, 3393, 3974, + 4095, 3451, 3944, + 4095, 3519, 3902, + 4095, 3597, 3839, + 4095, 3684, 3738, + 4076, 3778, 3553, + 0, 33, 135, + 0, 83, 61, + 0, 142, 0, + 0, 211, 0, + 0, 290, 0, + 0, 377, 0, + 0, 473, 0, + 0, 576, 0, + 0, 684, 0, + 0, 798, 0, + 0, 916, 0, + 0, 1037, 0, + 0, 1161, 0, + 0, 1287, 0, + 0, 1414, 0, + 0, 1543, 0, + 0, 1672, 0, + 0, 1802, 0, + 0, 1933, 0, + 0, 2064, 0, + 0, 2195, 0, + 0, 2327, 0, + 0, 2458, 0, + 0, 2590, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 11, 50, 228, + 0, 99, 168, + 0, 156, 74, + 0, 223, 0, + 0, 300, 0, + 0, 386, 0, + 0, 480, 0, + 0, 581, 0, + 0, 689, 0, + 0, 802, 0, + 0, 919, 0, + 0, 1039, 0, + 0, 1163, 0, + 0, 1288, 0, + 0, 1415, 0, + 0, 1543, 0, + 0, 1673, 0, + 0, 1803, 0, + 0, 1933, 0, + 0, 2064, 0, + 0, 2195, 0, + 0, 2327, 0, + 0, 2458, 0, + 0, 2590, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 271, 73, 329, + 199, 119, 281, + 79, 174, 209, + 0, 239, 91, + 0, 313, 0, + 0, 397, 0, + 0, 489, 0, + 0, 588, 0, + 0, 694, 0, + 0, 806, 0, + 0, 922, 0, + 0, 1042, 0, + 0, 1165, 0, + 0, 1290, 0, + 0, 1416, 0, + 0, 1544, 0, + 0, 1673, 0, + 0, 1803, 0, + 0, 1934, 0, + 0, 2064, 0, + 0, 2195, 0, + 0, 2327, 0, + 0, 2458, 0, + 0, 2590, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 480, 102, 436, + 435, 145, 399, + 368, 197, 344, + 259, 259, 259, + 54, 330, 113, + 0, 411, 0, + 0, 500, 0, + 0, 597, 0, + 0, 702, 0, + 0, 812, 0, + 0, 927, 0, + 0, 1045, 0, + 0, 1167, 0, + 0, 1292, 0, + 0, 1418, 0, + 0, 1546, 0, + 0, 1674, 0, + 0, 1804, 0, + 0, 1934, 0, + 0, 2065, 0, + 0, 2196, 0, + 0, 2327, 0, + 0, 2458, 0, + 0, 2590, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 662, 137, 548, + 632, 177, 519, + 590, 226, 478, + 526, 284, 416, + 424, 352, 318, + 237, 429, 140, + 0, 515, 0, + 0, 610, 0, + 0, 711, 0, + 0, 819, 0, + 0, 933, 0, + 0, 1050, 0, + 0, 1171, 0, + 0, 1294, 0, + 0, 1420, 0, + 0, 1547, 0, + 0, 1675, 0, + 0, 1805, 0, + 0, 1935, 0, + 0, 2065, 0, + 0, 2196, 0, + 0, 2327, 0, + 0, 2459, 0, + 0, 2590, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 828, 181, 665, + 808, 217, 643, + 779, 262, 612, + 738, 316, 566, + 677, 380, 498, + 579, 453, 386, + 403, 535, 175, + 0, 626, 0, + 0, 724, 0, + 0, 830, 0, + 0, 941, 0, + 0, 1056, 0, + 0, 1176, 0, + 0, 1298, 0, + 0, 1423, 0, + 0, 1549, 0, + 0, 1677, 0, + 0, 1806, 0, + 0, 1936, 0, + 0, 2066, 0, + 0, 2197, 0, + 0, 2328, 0, + 0, 2459, 0, + 0, 2590, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 984, 233, 785, + 970, 266, 768, + 950, 307, 745, + 922, 356, 712, + 882, 414, 663, + 822, 482, 588, + 728, 560, 464, + 559, 646, 217, + 144, 741, 0, + 0, 843, 0, + 0, 951, 0, + 0, 1064, 0, + 0, 1182, 0, + 0, 1303, 0, + 0, 1426, 0, + 0, 1552, 0, + 0, 1679, 0, + 0, 1807, 0, + 0, 1937, 0, + 0, 2067, 0, + 0, 2197, 0, + 0, 2328, 0, + 0, 2459, 0, + 0, 2591, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1133, 295, 908, + 1123, 324, 895, + 1109, 360, 878, + 1089, 404, 853, + 1062, 457, 818, + 1023, 519, 766, + 964, 591, 686, + 872, 672, 551, + 709, 762, 268, + 318, 860, 0, + 0, 964, 0, + 0, 1075, 0, + 0, 1190, 0, + 0, 1309, 0, + 0, 1431, 0, + 0, 1555, 0, + 0, 1682, 0, + 0, 1809, 0, + 0, 1938, 0, + 0, 2068, 0, + 0, 2198, 0, + 0, 2329, 0, + 0, 2460, 0, + 0, 2591, 0, + 0, 2723, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1277, 366, 1033, + 1270, 391, 1024, + 1260, 422, 1010, + 1246, 461, 992, + 1227, 508, 967, + 1200, 564, 930, + 1161, 629, 876, + 1103, 705, 791, + 1013, 789, 646, + 853, 882, 329, + 479, 982, 0, + 0, 1088, 0, + 0, 1201, 0, + 0, 1317, 0, + 0, 1437, 0, + 0, 1560, 0, + 0, 1685, 0, + 0, 1812, 0, + 0, 1940, 0, + 0, 2069, 0, + 0, 2199, 0, + 0, 2330, 0, + 0, 2460, 0, + 0, 2592, 0, + 0, 2723, 0, + 0, 2855, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1418, 447, 1160, + 1413, 468, 1153, + 1406, 494, 1143, + 1396, 528, 1129, + 1382, 568, 1111, + 1363, 618, 1084, + 1336, 677, 1046, + 1298, 745, 990, + 1241, 822, 902, + 1151, 909, 748, + 994, 1004, 399, + 631, 1106, 0, + 0, 1214, 0, + 0, 1328, 0, + 0, 1446, 0, + 0, 1567, 0, + 0, 1690, 0, + 0, 1816, 0, + 0, 1943, 0, + 0, 2072, 0, + 0, 2201, 0, + 0, 2331, 0, + 0, 2461, 0, + 0, 2592, 0, + 0, 2724, 0, + 0, 2855, 0, + 0, 2987, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1557, 537, 1288, + 1553, 554, 1283, + 1548, 576, 1275, + 1540, 604, 1265, + 1531, 639, 1251, + 1517, 681, 1232, + 1498, 733, 1205, + 1471, 793, 1166, + 1433, 864, 1108, + 1377, 944, 1017, + 1288, 1032, 857, + 1133, 1129, 478, + 778, 1232, 0, + 0, 1342, 0, + 0, 1456, 0, + 0, 1575, 0, + 0, 1697, 0, + 0, 1821, 0, + 0, 1947, 0, + 0, 2074, 0, + 0, 2203, 0, + 0, 2332, 0, + 0, 2463, 0, + 0, 2593, 0, + 0, 2724, 0, + 0, 2855, 0, + 0, 2987, 0, + 0, 3119, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1694, 634, 1417, + 1691, 648, 1413, + 1687, 666, 1408, + 1682, 689, 1400, + 1675, 718, 1390, + 1665, 754, 1376, + 1651, 798, 1356, + 1632, 851, 1329, + 1606, 914, 1289, + 1568, 986, 1230, + 1512, 1067, 1136, + 1424, 1157, 970, + 1270, 1255, 567, + 921, 1360, 0, + 0, 1471, 0, + 0, 1586, 0, + 0, 1705, 0, + 0, 1827, 0, + 0, 1952, 0, + 0, 2078, 0, + 0, 2206, 0, + 0, 2334, 0, + 0, 2464, 0, + 0, 2594, 0, + 0, 2725, 0, + 0, 2856, 0, + 0, 2987, 0, + 0, 3119, 0, + 0, 3251, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1830, 738, 1547, + 1828, 750, 1544, + 1825, 764, 1540, + 1821, 783, 1534, + 1815, 806, 1527, + 1808, 836, 1516, + 1798, 873, 1502, + 1785, 919, 1482, + 1766, 973, 1454, + 1740, 1037, 1414, + 1702, 1110, 1354, + 1646, 1193, 1258, + 1558, 1284, 1088, + 1406, 1383, 663, + 1061, 1489, 0, + 0, 1600, 0, + 0, 1716, 0, + 0, 1836, 0, + 0, 1958, 0, + 0, 2083, 0, + 0, 2209, 0, + 0, 2337, 0, + 0, 2466, 0, + 0, 2596, 0, + 0, 2726, 0, + 0, 2857, 0, + 0, 2988, 0, + 0, 3119, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3514, 0, + 0, 3646, 0, + 1965, 849, 1678, + 1963, 857, 1675, + 1961, 869, 1672, + 1958, 884, 1668, + 1954, 903, 1662, + 1949, 927, 1655, + 1941, 958, 1644, + 1932, 996, 1630, + 1918, 1042, 1610, + 1899, 1097, 1582, + 1873, 1162, 1541, + 1835, 1237, 1480, + 1780, 1320, 1383, + 1692, 1412, 1209, + 1541, 1512, 766, + 1199, 1618, 0, + 0, 1730, 0, + 0, 1847, 0, + 0, 1966, 0, + 0, 2089, 0, + 0, 2214, 0, + 0, 2341, 0, + 0, 2469, 0, + 0, 2598, 0, + 0, 2728, 0, + 0, 2858, 0, + 0, 2989, 0, + 0, 3120, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3646, 0, + 2099, 964, 1809, + 2098, 970, 1807, + 2096, 979, 1804, + 2094, 991, 1801, + 2091, 1006, 1797, + 2087, 1026, 1791, + 2082, 1051, 1784, + 2074, 1082, 1773, + 2065, 1120, 1759, + 2051, 1167, 1738, + 2032, 1224, 1710, + 2006, 1289, 1669, + 1969, 1364, 1607, + 1913, 1449, 1509, + 1826, 1542, 1333, + 1675, 1642, 876, + 1335, 1749, 0, + 0, 1861, 0, + 0, 1978, 0, + 0, 2098, 0, + 0, 2221, 0, + 0, 2346, 0, + 0, 2473, 0, + 0, 2601, 0, + 0, 2730, 0, + 0, 2860, 0, + 0, 2990, 0, + 0, 3121, 0, + 0, 3252, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3647, 0, + 2232, 1083, 1940, + 2231, 1088, 1938, + 2230, 1095, 1937, + 2229, 1104, 1934, + 2226, 1116, 1931, + 2224, 1131, 1927, + 2220, 1151, 1921, + 2214, 1176, 1913, + 2207, 1208, 1903, + 2197, 1247, 1888, + 2184, 1294, 1868, + 2165, 1351, 1839, + 2139, 1417, 1798, + 2101, 1493, 1736, + 2046, 1578, 1637, + 1959, 1671, 1459, + 1809, 1772, 990, + 1470, 1879, 0, + 0, 1992, 0, + 0, 2109, 0, + 0, 2229, 0, + 0, 2352, 0, + 0, 2478, 0, + 0, 2604, 0, + 0, 2733, 0, + 0, 2862, 0, + 0, 2992, 0, + 0, 3122, 0, + 0, 3253, 0, + 0, 3384, 0, + 0, 3516, 0, + 0, 3647, 0, + 2366, 1204, 2071, + 2365, 1208, 2070, + 2364, 1214, 2069, + 2363, 1221, 2067, + 2361, 1230, 2065, + 2359, 1242, 2062, + 2356, 1258, 2057, + 2352, 1278, 2052, + 2347, 1303, 2044, + 2340, 1335, 2033, + 2330, 1375, 2018, + 2316, 1423, 1998, + 2298, 1480, 1969, + 2272, 1547, 1928, + 2234, 1623, 1865, + 2179, 1708, 1766, + 2092, 1802, 1586, + 1942, 1903, 1108, + 1605, 2010, 0, + 0, 2123, 0, + 0, 2240, 0, + 0, 2361, 0, + 0, 2484, 0, + 0, 2609, 0, + 0, 2736, 0, + 0, 2865, 0, + 0, 2994, 0, + 0, 3124, 0, + 0, 3254, 0, + 0, 3385, 0, + 0, 3516, 0, + 0, 3648, 0, + 2498, 1329, 2203, + 2498, 1332, 2202, + 2497, 1336, 2201, + 2496, 1341, 2200, + 2495, 1348, 2198, + 2494, 1358, 2196, + 2491, 1370, 2192, + 2488, 1385, 2188, + 2485, 1406, 2182, + 2479, 1431, 2175, + 2472, 1464, 2164, + 2462, 1504, 2149, + 2449, 1552, 2129, + 2430, 1609, 2100, + 2404, 1677, 2058, + 2367, 1753, 1995, + 2311, 1839, 1896, + 2225, 1933, 1714, + 2075, 2034, 1230, + 1739, 2142, 0, + 0, 2255, 0, + 0, 2372, 0, + 0, 2492, 0, + 0, 2616, 0, + 0, 2741, 0, + 0, 2868, 0, + 0, 2997, 0, + 0, 3126, 0, + 0, 3256, 0, + 0, 3386, 0, + 0, 3517, 0, + 0, 3648, 0, + 2631, 1455, 2334, + 2631, 1457, 2334, + 2630, 1460, 2333, + 2630, 1464, 2332, + 2629, 1470, 2331, + 2628, 1477, 2329, + 2626, 1486, 2327, + 2624, 1499, 2324, + 2621, 1514, 2319, + 2617, 1535, 2313, + 2612, 1561, 2306, + 2604, 1593, 2295, + 2595, 1633, 2280, + 2581, 1682, 2260, + 2563, 1740, 2231, + 2537, 1807, 2189, + 2499, 1884, 2126, + 2444, 1970, 2026, + 2357, 2064, 1844, + 2207, 2165, 1354, + 1872, 2273, 0, + 0, 2386, 0, + 0, 2504, 0, + 0, 2624, 0, + 0, 2748, 0, + 0, 2873, 0, + 0, 3000, 0, + 0, 3129, 0, + 0, 3258, 0, + 0, 3388, 0, + 0, 3518, 0, + 0, 3649, 0, + 2764, 1583, 2466, + 2763, 1584, 2466, + 2763, 1587, 2465, + 2763, 1590, 2464, + 2762, 1594, 2464, + 2761, 1599, 2462, + 2760, 1607, 2460, + 2758, 1616, 2458, + 2756, 1628, 2455, + 2753, 1644, 2451, + 2749, 1665, 2445, + 2744, 1691, 2437, + 2737, 1723, 2426, + 2727, 1764, 2411, + 2714, 1812, 2391, + 2695, 1870, 2362, + 2669, 1938, 2320, + 2631, 2015, 2257, + 2576, 2101, 2156, + 2490, 2195, 1974, + 2340, 2297, 1480, + 2005, 2405, 0, + 0, 2518, 0, + 0, 2635, 0, + 0, 2756, 0, + 0, 2880, 0, + 0, 3005, 0, + 0, 3132, 0, + 0, 3261, 0, + 0, 3390, 0, + 0, 3520, 0, + 0, 3650, 0, + 2896, 1711, 2598, + 2896, 1713, 2598, + 2896, 1714, 2597, + 2895, 1717, 2597, + 2895, 1720, 2596, + 2894, 1724, 2595, + 2893, 1730, 2594, + 2892, 1737, 2592, + 2890, 1746, 2590, + 2888, 1759, 2586, + 2885, 1775, 2582, + 2881, 1795, 2576, + 2876, 1821, 2568, + 2869, 1854, 2558, + 2859, 1894, 2543, + 2846, 1943, 2522, + 2827, 2001, 2493, + 2801, 2069, 2451, + 2764, 2146, 2388, + 2708, 2232, 2288, + 2622, 2327, 2104, + 2472, 2429, 1608, + 2138, 2537, 0, + 0, 2650, 0, + 0, 2767, 0, + 0, 2888, 0, + 0, 3012, 0, + 0, 3137, 0, + 0, 3264, 0, + 0, 3393, 0, + 0, 3522, 0, + 0, 3652, 0, + 3029, 1841, 2730, + 3028, 1842, 2730, + 3028, 1843, 2729, + 3028, 1845, 2729, + 3028, 1847, 2728, + 3027, 1851, 2728, + 3026, 1855, 2727, + 3025, 1860, 2725, + 3024, 1867, 2724, + 3023, 1877, 2721, + 3020, 1889, 2718, + 3018, 1905, 2714, + 3014, 1926, 2708, + 3008, 1952, 2700, + 3001, 1985, 2689, + 2991, 2025, 2675, + 2978, 2074, 2654, + 2959, 2133, 2625, + 2933, 2200, 2583, + 2896, 2278, 2520, + 2841, 2364, 2419, + 2754, 2459, 2235, + 2605, 2560, 1736, + 2271, 2668, 0, + 0, 2782, 0, + 0, 2899, 0, + 0, 3020, 0, + 0, 3144, 0, + 0, 3269, 0, + 0, 3396, 0, + 0, 3525, 0, + 0, 3654, 0, + 3161, 1971, 2862, + 3161, 1972, 2862, + 3161, 1973, 2862, + 3160, 1974, 2861, + 3160, 1976, 2861, + 3160, 1978, 2860, + 3159, 1981, 2860, + 3159, 1986, 2859, + 3158, 1991, 2857, + 3156, 1998, 2856, + 3155, 2008, 2853, + 3153, 2020, 2850, + 3150, 2036, 2846, + 3146, 2057, 2840, + 3141, 2083, 2832, + 3133, 2116, 2821, + 3124, 2157, 2806, + 3110, 2206, 2786, + 3092, 2264, 2757, + 3066, 2332, 2715, + 3028, 2409, 2651, + 2973, 2496, 2550, + 2886, 2590, 2366, + 2737, 2692, 1866, + 2403, 2800, 0, + 0, 2914, 0, + 0, 3031, 0, + 0, 3152, 0, + 0, 3276, 0, + 0, 3401, 0, + 0, 3528, 0, + 0, 3657, 0, + 3293, 2102, 2994, + 3293, 2102, 2994, + 3293, 2103, 2994, + 3293, 2104, 2993, + 3292, 2105, 2993, + 3292, 2107, 2993, + 3292, 2110, 2992, + 3291, 2113, 2991, + 3291, 2117, 2990, + 3290, 2122, 2989, + 3289, 2130, 2987, + 3287, 2139, 2985, + 3285, 2152, 2982, + 3282, 2168, 2978, + 3278, 2188, 2972, + 3273, 2215, 2964, + 3266, 2248, 2953, + 3256, 2288, 2938, + 3242, 2337, 2918, + 3224, 2396, 2888, + 3198, 2464, 2846, + 3160, 2541, 2783, + 3105, 2628, 2682, + 3019, 2722, 2498, + 2869, 2824, 1996, + 2536, 2932, 0, + 0, 3046, 0, + 0, 3163, 0, + 0, 3284, 0, + 0, 3408, 0, + 0, 3533, 0, + 0, 3660, 0, + 3425, 2233, 3126, + 3425, 2233, 3126, + 3425, 2234, 3126, + 3425, 2235, 3126, + 3425, 2236, 3125, + 3425, 2237, 3125, + 3424, 2239, 3125, + 3424, 2241, 3124, + 3423, 2244, 3123, + 3423, 2248, 3122, + 3422, 2254, 3121, + 3421, 2261, 3119, + 3419, 2271, 3117, + 3417, 2283, 3114, + 3414, 2299, 3109, + 3410, 2320, 3104, + 3405, 2346, 3096, + 3398, 2379, 3085, + 3388, 2420, 3070, + 3375, 2469, 3049, + 3356, 2527, 3020, + 3330, 2595, 2978, + 3293, 2673, 2915, + 3237, 2759, 2814, + 3151, 2854, 2629, + 3002, 2956, 2126, + 2668, 3064, 0, + 0, 3178, 0, + 0, 3295, 0, + 0, 3416, 0, + 0, 3540, 0, + 0, 3665, 0, + 3557, 2364, 3258, + 3557, 2365, 3258, + 3557, 2365, 3258, + 3557, 2365, 3258, + 3557, 2366, 3258, + 3557, 2367, 3257, + 3557, 2369, 3257, + 3556, 2370, 3257, + 3556, 2373, 3256, + 3556, 2376, 3255, + 3555, 2380, 3254, + 3554, 2386, 3253, + 3553, 2393, 3251, + 3551, 2402, 3249, + 3549, 2415, 3246, + 3546, 2431, 3241, + 3542, 2452, 3236, + 3537, 2478, 3228, + 3530, 2511, 3217, + 3520, 2552, 3202, + 3507, 2601, 3181, + 3488, 2659, 3152, + 3462, 2727, 3110, + 3425, 2805, 3047, + 3369, 2891, 2946, + 3283, 2986, 2761, + 3134, 3088, 2257, + 2800, 3196, 0, + 0, 3310, 0, + 0, 3427, 0, + 0, 3548, 0, + 0, 3672, 0, + 3690, 2496, 3390, + 3690, 2496, 3390, + 3690, 2496, 3390, + 3689, 2497, 3390, + 3689, 2497, 3390, + 3689, 2498, 3390, + 3689, 2499, 3389, + 3689, 2500, 3389, + 3689, 2502, 3389, + 3688, 2504, 3388, + 3688, 2508, 3387, + 3687, 2512, 3386, + 3686, 2517, 3385, + 3685, 2525, 3383, + 3683, 2534, 3381, + 3681, 2547, 3378, + 3678, 2563, 3373, + 3674, 2583, 3368, + 3669, 2610, 3360, + 3662, 2643, 3349, + 3652, 2683, 3334, + 3639, 2733, 3313, + 3620, 2791, 3284, + 3594, 2859, 3242, + 3557, 2937, 3179, + 3501, 3023, 3078, + 3415, 3118, 2893, + 3266, 3220, 2389, + 2932, 3328, 0, + 0, 3442, 0, + 0, 3559, 0, + 0, 3680, 0, + 3822, 2627, 3522, + 3822, 2628, 3522, + 3822, 2628, 3522, + 3822, 2628, 3522, + 3822, 2628, 3522, + 3821, 2629, 3522, + 3821, 2630, 3522, + 3821, 2631, 3521, + 3821, 2632, 3521, + 3821, 2634, 3521, + 3820, 2636, 3520, + 3820, 2639, 3519, + 3819, 2644, 3518, + 3818, 2649, 3517, + 3817, 2656, 3515, + 3815, 2666, 3513, + 3813, 2678, 3510, + 3810, 2695, 3505, + 3806, 2715, 3500, + 3801, 2742, 3492, + 3794, 2775, 3481, + 3784, 2815, 3466, + 3771, 2865, 3445, + 3752, 2923, 3416, + 3726, 2991, 3374, + 3689, 3069, 3311, + 3634, 3155, 3210, + 3547, 3250, 3025, + 3398, 3352, 2520, + 3065, 3460, 0, + 0, 3574, 0, + 0, 3691, 0, + 3954, 2759, 3654, + 3954, 2759, 3654, + 3954, 2759, 3654, + 3954, 2760, 3654, + 3954, 2760, 3654, + 3954, 2760, 3654, + 3954, 2761, 3654, + 3953, 2762, 3654, + 3953, 2763, 3653, + 3953, 2764, 3653, + 3953, 2766, 3653, + 3952, 2768, 3652, + 3952, 2771, 3651, + 3951, 2775, 3650, + 3950, 2781, 3649, + 3949, 2788, 3647, + 3948, 2798, 3645, + 3945, 2810, 3642, + 3943, 2826, 3637, + 3939, 2847, 3632, + 3933, 2874, 3624, + 3926, 2907, 3613, + 3916, 2947, 3598, + 3903, 2997, 3577, + 3884, 3055, 3548, + 3858, 3123, 3506, + 3821, 3201, 3443, + 3766, 3287, 3342, + 3679, 3382, 3157, + 3530, 3484, 2652, + 3197, 3593, 0, + 0, 3706, 0, + 4086, 2891, 3786, + 4086, 2891, 3786, + 4086, 2891, 3786, + 4086, 2891, 3786, + 4086, 2892, 3786, + 4086, 2892, 3786, + 4086, 2892, 3786, + 4086, 2893, 3786, + 4086, 2894, 3786, + 4085, 2895, 3785, + 4085, 2896, 3785, + 4085, 2898, 3785, + 4085, 2900, 3784, + 4084, 2903, 3783, + 4083, 2907, 3782, + 4082, 2913, 3781, + 4081, 2920, 3779, + 4080, 2930, 3777, + 4078, 2942, 3774, + 4075, 2958, 3770, + 4071, 2979, 3764, + 4065, 3006, 3756, + 4058, 3039, 3745, + 4048, 3079, 3730, + 4035, 3129, 3710, + 4017, 3187, 3680, + 3990, 3255, 3638, + 3953, 3333, 3575, + 3898, 3419, 3474, + 3811, 3514, 3289, + 3662, 3616, 2783, + 3329, 3725, 0, + 4095, 3023, 3918, + 4095, 3023, 3918, + 4095, 3023, 3918, + 4095, 3023, 3918, + 4095, 3023, 3918, + 4095, 3024, 3918, + 4095, 3024, 3918, + 4095, 3024, 3918, + 4095, 3025, 3918, + 4095, 3026, 3918, + 4095, 3027, 3918, + 4095, 3028, 3917, + 4095, 3030, 3917, + 4095, 3032, 3916, + 4095, 3035, 3916, + 4095, 3039, 3915, + 4095, 3045, 3913, + 4095, 3052, 3911, + 4095, 3062, 3909, + 4095, 3074, 3906, + 4095, 3090, 3902, + 4095, 3111, 3896, + 4095, 3138, 3888, + 4095, 3171, 3877, + 4095, 3211, 3862, + 4095, 3261, 3842, + 4095, 3319, 3812, + 4095, 3387, 3770, + 4085, 3465, 3707, + 4030, 3552, 3606, + 3944, 3646, 3421, + 3794, 3748, 2915, + 4095, 3155, 4050, + 4095, 3155, 4050, + 4095, 3155, 4050, + 4095, 3155, 4050, + 4095, 3155, 4050, + 4095, 3155, 4050, + 4095, 3156, 4050, + 4095, 3156, 4050, + 4095, 3156, 4050, + 4095, 3157, 4050, + 4095, 3158, 4050, + 4095, 3159, 4050, + 4095, 3160, 4049, + 4095, 3162, 4049, + 4095, 3164, 4048, + 4095, 3167, 4048, + 4095, 3171, 4047, + 4095, 3177, 4045, + 4095, 3184, 4044, + 4095, 3194, 4041, + 4095, 3206, 4038, + 4095, 3222, 4034, + 4095, 3243, 4028, + 4095, 3270, 4020, + 4095, 3303, 4009, + 4095, 3343, 3994, + 4095, 3393, 3974, + 4095, 3451, 3944, + 4095, 3519, 3902, + 4095, 3597, 3839, + 4095, 3684, 3738, + 4076, 3778, 3553, + 0, 108, 241, + 0, 151, 183, + 0, 203, 91, + 0, 264, 0, + 0, 334, 0, + 0, 414, 0, + 0, 503, 0, + 0, 600, 0, + 0, 704, 0, + 0, 813, 0, + 0, 928, 0, + 0, 1046, 0, + 0, 1168, 0, + 0, 1292, 0, + 0, 1418, 0, + 0, 1546, 0, + 0, 1674, 0, + 0, 1804, 0, + 0, 1934, 0, + 0, 2065, 0, + 0, 2196, 0, + 0, 2327, 0, + 0, 2459, 0, + 0, 2590, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 0, 123, 316, + 0, 165, 267, + 0, 215, 193, + 0, 274, 69, + 0, 343, 0, + 0, 422, 0, + 0, 509, 0, + 0, 605, 0, + 0, 708, 0, + 0, 816, 0, + 0, 930, 0, + 0, 1048, 0, + 0, 1170, 0, + 0, 1293, 0, + 0, 1419, 0, + 0, 1546, 0, + 0, 1675, 0, + 0, 1804, 0, + 0, 1934, 0, + 0, 2065, 0, + 0, 2196, 0, + 0, 2327, 0, + 0, 2459, 0, + 0, 2590, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 225, 143, 400, + 144, 182, 360, + 6, 231, 300, + 0, 288, 206, + 0, 355, 37, + 0, 432, 0, + 0, 518, 0, + 0, 612, 0, + 0, 713, 0, + 0, 821, 0, + 0, 934, 0, + 0, 1051, 0, + 0, 1171, 0, + 0, 1295, 0, + 0, 1420, 0, + 0, 1547, 0, + 0, 1676, 0, + 0, 1805, 0, + 0, 1935, 0, + 0, 2065, 0, + 0, 2196, 0, + 0, 2327, 0, + 0, 2459, 0, + 0, 2590, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 451, 167, 493, + 403, 205, 461, + 331, 251, 413, + 211, 306, 341, + 0, 371, 223, + 0, 445, 0, + 0, 529, 0, + 0, 621, 0, + 0, 720, 0, + 0, 826, 0, + 0, 938, 0, + 0, 1054, 0, + 0, 1174, 0, + 0, 1297, 0, + 0, 1422, 0, + 0, 1548, 0, + 0, 1676, 0, + 0, 1805, 0, + 0, 1935, 0, + 0, 2066, 0, + 0, 2196, 0, + 0, 2328, 0, + 0, 2459, 0, + 0, 2590, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 643, 198, 593, + 612, 234, 568, + 567, 277, 531, + 500, 329, 476, + 391, 391, 391, + 186, 462, 245, + 0, 543, 0, + 0, 632, 0, + 0, 730, 0, + 0, 834, 0, + 0, 944, 0, + 0, 1059, 0, + 0, 1178, 0, + 0, 1299, 0, + 0, 1424, 0, + 0, 1550, 0, + 0, 1678, 0, + 0, 1806, 0, + 0, 1936, 0, + 0, 2066, 0, + 0, 2197, 0, + 0, 2328, 0, + 0, 2459, 0, + 0, 2591, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 815, 237, 700, + 794, 269, 680, + 765, 310, 651, + 722, 358, 610, + 658, 417, 548, + 556, 484, 450, + 369, 561, 272, + 0, 647, 0, + 0, 742, 0, + 0, 844, 0, + 0, 952, 0, + 0, 1065, 0, + 0, 1182, 0, + 0, 1303, 0, + 0, 1426, 0, + 0, 1552, 0, + 0, 1679, 0, + 0, 1808, 0, + 0, 1937, 0, + 0, 2067, 0, + 0, 2197, 0, + 0, 2328, 0, + 0, 2459, 0, + 0, 2591, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 974, 283, 813, + 960, 313, 797, + 940, 350, 775, + 911, 395, 744, + 870, 448, 699, + 809, 512, 630, + 711, 585, 518, + 535, 667, 307, + 81, 758, 0, + 0, 856, 0, + 0, 962, 0, + 0, 1073, 0, + 0, 1188, 0, + 0, 1308, 0, + 0, 1430, 0, + 0, 1555, 0, + 0, 1681, 0, + 0, 1809, 0, + 0, 1938, 0, + 0, 2068, 0, + 0, 2198, 0, + 0, 2329, 0, + 0, 2460, 0, + 0, 2591, 0, + 0, 2723, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1126, 339, 929, + 1116, 365, 917, + 1102, 398, 900, + 1082, 439, 877, + 1054, 488, 844, + 1014, 546, 795, + 954, 614, 720, + 860, 692, 596, + 691, 778, 349, + 276, 873, 0, + 0, 975, 0, + 0, 1083, 0, + 0, 1196, 0, + 0, 1314, 0, + 0, 1435, 0, + 0, 1558, 0, + 0, 1684, 0, + 0, 1811, 0, + 0, 1939, 0, + 0, 2069, 0, + 0, 2199, 0, + 0, 2329, 0, + 0, 2460, 0, + 0, 2591, 0, + 0, 2723, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1272, 404, 1049, + 1265, 427, 1040, + 1255, 456, 1027, + 1241, 492, 1010, + 1221, 536, 985, + 1194, 589, 950, + 1155, 651, 898, + 1096, 723, 818, + 1004, 804, 683, + 841, 894, 400, + 450, 992, 0, + 0, 1096, 0, + 0, 1207, 0, + 0, 1322, 0, + 0, 1441, 0, + 0, 1563, 0, + 0, 1688, 0, + 0, 1814, 0, + 0, 1942, 0, + 0, 2070, 0, + 0, 2200, 0, + 0, 2330, 0, + 0, 2461, 0, + 0, 2592, 0, + 0, 2723, 0, + 0, 2855, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1415, 479, 1172, + 1409, 499, 1165, + 1402, 523, 1156, + 1392, 554, 1143, + 1378, 593, 1124, + 1359, 640, 1099, + 1332, 696, 1062, + 1293, 762, 1008, + 1235, 837, 923, + 1145, 921, 778, + 985, 1014, 461, + 611, 1114, 0, + 0, 1221, 0, + 0, 1333, 0, + 0, 1449, 0, + 0, 1569, 0, + 0, 1692, 0, + 0, 1817, 0, + 0, 1944, 0, + 0, 2072, 0, + 0, 2202, 0, + 0, 2331, 0, + 0, 2462, 0, + 0, 2593, 0, + 0, 2724, 0, + 0, 2855, 0, + 0, 2987, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1555, 563, 1298, + 1551, 579, 1292, + 1545, 600, 1285, + 1538, 627, 1275, + 1528, 660, 1262, + 1514, 701, 1243, + 1495, 750, 1216, + 1468, 809, 1178, + 1430, 877, 1122, + 1373, 955, 1034, + 1283, 1041, 880, + 1127, 1136, 531, + 763, 1238, 0, + 0, 1347, 0, + 0, 1460, 0, + 0, 1578, 0, + 0, 1699, 0, + 0, 1822, 0, + 0, 1948, 0, + 0, 2075, 0, + 0, 2204, 0, + 0, 2333, 0, + 0, 2463, 0, + 0, 2593, 0, + 0, 2724, 0, + 0, 2856, 0, + 0, 2987, 0, + 0, 3119, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1692, 656, 1424, + 1689, 669, 1420, + 1685, 686, 1415, + 1680, 708, 1408, + 1673, 736, 1397, + 1663, 771, 1384, + 1649, 813, 1364, + 1630, 865, 1337, + 1604, 926, 1298, + 1565, 996, 1240, + 1509, 1076, 1149, + 1420, 1164, 989, + 1265, 1261, 610, + 910, 1365, 0, + 0, 1474, 0, + 0, 1589, 0, + 0, 1707, 0, + 0, 1829, 0, + 0, 1953, 0, + 0, 2079, 0, + 0, 2206, 0, + 0, 2335, 0, + 0, 2464, 0, + 0, 2595, 0, + 0, 2725, 0, + 0, 2856, 0, + 0, 2988, 0, + 0, 3119, 0, + 0, 3251, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1828, 756, 1553, + 1826, 766, 1550, + 1823, 780, 1545, + 1819, 798, 1540, + 1814, 821, 1532, + 1807, 850, 1522, + 1797, 886, 1508, + 1783, 930, 1488, + 1764, 983, 1461, + 1738, 1046, 1421, + 1700, 1118, 1362, + 1644, 1199, 1268, + 1556, 1289, 1103, + 1402, 1387, 699, + 1053, 1492, 0, + 0, 1603, 0, + 0, 1718, 0, + 0, 1837, 0, + 0, 1959, 0, + 0, 2084, 0, + 0, 2210, 0, + 0, 2338, 0, + 0, 2467, 0, + 0, 2596, 0, + 0, 2726, 0, + 0, 2857, 0, + 0, 2988, 0, + 0, 3120, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3514, 0, + 0, 3646, 0, + 1964, 862, 1682, + 1962, 871, 1679, + 1960, 882, 1676, + 1957, 896, 1672, + 1953, 915, 1667, + 1948, 938, 1659, + 1940, 968, 1649, + 1930, 1006, 1634, + 1917, 1051, 1614, + 1898, 1105, 1586, + 1872, 1169, 1546, + 1834, 1243, 1486, + 1778, 1325, 1391, + 1690, 1416, 1220, + 1538, 1515, 795, + 1193, 1621, 0, + 0, 1732, 0, + 0, 1848, 0, + 0, 1968, 0, + 0, 2090, 0, + 0, 2215, 0, + 0, 2341, 0, + 0, 2469, 0, + 0, 2598, 0, + 0, 2728, 0, + 0, 2858, 0, + 0, 2989, 0, + 0, 3120, 0, + 0, 3252, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3646, 0, + 2098, 974, 1812, + 2097, 981, 1810, + 2095, 989, 1808, + 2093, 1001, 1804, + 2090, 1016, 1800, + 2086, 1035, 1795, + 2081, 1059, 1787, + 2074, 1090, 1776, + 2064, 1128, 1762, + 2050, 1174, 1742, + 2032, 1230, 1714, + 2005, 1294, 1673, + 1968, 1369, 1612, + 1912, 1452, 1515, + 1824, 1545, 1341, + 1673, 1644, 898, + 1331, 1751, 0, + 0, 1862, 0, + 0, 1979, 0, + 0, 2099, 0, + 0, 2221, 0, + 0, 2346, 0, + 0, 2473, 0, + 0, 2601, 0, + 0, 2730, 0, + 0, 2860, 0, + 0, 2990, 0, + 0, 3121, 0, + 0, 3252, 0, + 0, 3384, 0, + 0, 3515, 0, + 0, 3647, 0, + 2232, 1091, 1942, + 2231, 1096, 1941, + 2230, 1103, 1939, + 2228, 1111, 1937, + 2226, 1123, 1933, + 2223, 1138, 1929, + 2219, 1158, 1924, + 2214, 1183, 1916, + 2206, 1214, 1905, + 2197, 1253, 1891, + 2183, 1300, 1870, + 2165, 1356, 1842, + 2138, 1421, 1801, + 2101, 1497, 1739, + 2045, 1581, 1641, + 1958, 1674, 1465, + 1807, 1774, 1008, + 1467, 1881, 0, + 0, 1993, 0, + 0, 2110, 0, + 0, 2230, 0, + 0, 2353, 0, + 0, 2478, 0, + 0, 2605, 0, + 0, 2733, 0, + 0, 2862, 0, + 0, 2992, 0, + 0, 3122, 0, + 0, 3253, 0, + 0, 3384, 0, + 0, 3516, 0, + 0, 3647, 0, + 2365, 1211, 2073, + 2364, 1215, 2072, + 2364, 1220, 2071, + 2362, 1227, 2069, + 2361, 1236, 2066, + 2359, 1248, 2063, + 2356, 1263, 2059, + 2352, 1283, 2053, + 2346, 1308, 2046, + 2339, 1340, 2035, + 2329, 1379, 2020, + 2316, 1427, 2000, + 2297, 1483, 1971, + 2271, 1550, 1930, + 2234, 1625, 1868, + 2178, 1710, 1769, + 2091, 1804, 1591, + 1941, 1904, 1122, + 1603, 2011, 0, + 0, 2124, 0, + 0, 2241, 0, + 0, 2361, 0, + 0, 2484, 0, + 0, 2610, 0, + 0, 2737, 0, + 0, 2865, 0, + 0, 2994, 0, + 0, 3124, 0, + 0, 3254, 0, + 0, 3385, 0, + 0, 3516, 0, + 0, 3648, 0, + 2498, 1334, 2204, + 2498, 1337, 2203, + 2497, 1341, 2202, + 2496, 1346, 2201, + 2495, 1353, 2199, + 2493, 1362, 2197, + 2491, 1374, 2194, + 2488, 1390, 2189, + 2484, 1410, 2184, + 2479, 1435, 2176, + 2472, 1467, 2165, + 2462, 1507, 2150, + 2449, 1555, 2130, + 2430, 1612, 2101, + 2404, 1679, 2060, + 2366, 1755, 1997, + 2311, 1840, 1898, + 2224, 1934, 1718, + 2074, 2035, 1241, + 1737, 2142, 0, + 0, 2255, 0, + 0, 2372, 0, + 0, 2493, 0, + 0, 2616, 0, + 0, 2741, 0, + 0, 2868, 0, + 0, 2997, 0, + 0, 3126, 0, + 0, 3256, 0, + 0, 3386, 0, + 0, 3517, 0, + 0, 3648, 0, + 2631, 1459, 2335, + 2631, 1461, 2335, + 2630, 1464, 2334, + 2629, 1468, 2333, + 2628, 1473, 2332, + 2627, 1480, 2330, + 2626, 1490, 2328, + 2624, 1502, 2324, + 2621, 1518, 2320, + 2617, 1538, 2314, + 2611, 1564, 2307, + 2604, 1596, 2296, + 2594, 1636, 2281, + 2581, 1684, 2261, + 2562, 1742, 2232, + 2536, 1809, 2190, + 2499, 1885, 2128, + 2443, 1971, 2028, + 2357, 2065, 1846, + 2207, 2166, 1362, + 1871, 2274, 0, + 0, 2387, 0, + 0, 2504, 0, + 0, 2625, 0, + 0, 2748, 0, + 0, 2873, 0, + 0, 3000, 0, + 0, 3129, 0, + 0, 3258, 0, + 0, 3388, 0, + 0, 3518, 0, + 0, 3649, 0, + 2764, 1585, 2467, + 2763, 1587, 2466, + 2763, 1589, 2466, + 2762, 1593, 2465, + 2762, 1597, 2464, + 2761, 1602, 2463, + 2760, 1609, 2461, + 2758, 1618, 2459, + 2756, 1631, 2456, + 2753, 1647, 2451, + 2749, 1667, 2446, + 2744, 1693, 2438, + 2737, 1725, 2427, + 2727, 1765, 2412, + 2713, 1814, 2392, + 2695, 1872, 2363, + 2669, 1939, 2321, + 2631, 2016, 2258, + 2576, 2102, 2158, + 2489, 2196, 1976, + 2340, 2297, 1486, + 2004, 2405, 0, + 0, 2518, 0, + 0, 2636, 0, + 0, 2756, 0, + 0, 2880, 0, + 0, 3005, 0, + 0, 3132, 0, + 0, 3261, 0, + 0, 3390, 0, + 0, 3520, 0, + 0, 3650, 0, + 2896, 1713, 2599, + 2896, 1715, 2598, + 2896, 1717, 2598, + 2895, 1719, 2597, + 2895, 1722, 2597, + 2894, 1726, 2596, + 2893, 1731, 2594, + 2892, 1739, 2593, + 2890, 1748, 2590, + 2888, 1760, 2587, + 2885, 1776, 2583, + 2881, 1797, 2577, + 2876, 1823, 2569, + 2869, 1855, 2558, + 2859, 1896, 2544, + 2846, 1944, 2523, + 2827, 2002, 2494, + 2801, 2070, 2452, + 2764, 2147, 2389, + 2708, 2233, 2289, + 2622, 2327, 2106, + 2472, 2429, 1612, + 2137, 2537, 0, + 0, 2650, 0, + 0, 2767, 0, + 0, 2888, 0, + 0, 3012, 0, + 0, 3137, 0, + 0, 3264, 0, + 0, 3393, 0, + 0, 3522, 0, + 0, 3652, 0, + 3028, 1843, 2730, + 3028, 1844, 2730, + 3028, 1845, 2730, + 3028, 1847, 2729, + 3027, 1849, 2729, + 3027, 1852, 2728, + 3026, 1856, 2727, + 3025, 1862, 2726, + 3024, 1869, 2724, + 3023, 1878, 2722, + 3020, 1891, 2719, + 3017, 1907, 2714, + 3014, 1927, 2708, + 3008, 1953, 2701, + 3001, 1986, 2690, + 2991, 2026, 2675, + 2978, 2075, 2654, + 2959, 2133, 2625, + 2933, 2201, 2583, + 2896, 2278, 2520, + 2840, 2364, 2420, + 2754, 2459, 2236, + 2605, 2561, 1740, + 2270, 2669, 0, + 0, 2782, 0, + 0, 2899, 0, + 0, 3020, 0, + 0, 3144, 0, + 0, 3269, 0, + 0, 3396, 0, + 0, 3525, 0, + 0, 3654, 0, + 3161, 1972, 2862, + 3161, 1973, 2862, + 3160, 1974, 2862, + 3160, 1975, 2862, + 3160, 1977, 2861, + 3160, 1980, 2861, + 3159, 1983, 2860, + 3158, 1987, 2859, + 3158, 1992, 2858, + 3156, 1999, 2856, + 3155, 2009, 2853, + 3153, 2021, 2850, + 3150, 2037, 2846, + 3146, 2058, 2840, + 3140, 2084, 2832, + 3133, 2117, 2821, + 3124, 2157, 2807, + 3110, 2206, 2786, + 3092, 2265, 2757, + 3065, 2333, 2715, + 3028, 2410, 2652, + 2973, 2496, 2551, + 2886, 2591, 2367, + 2737, 2692, 1868, + 2403, 2801, 0, + 0, 2914, 0, + 0, 3031, 0, + 0, 3152, 0, + 0, 3276, 0, + 0, 3401, 0, + 0, 3528, 0, + 0, 3657, 0, + 3293, 2103, 2994, + 3293, 2103, 2994, + 3293, 2104, 2994, + 3293, 2105, 2994, + 3292, 2106, 2993, + 3292, 2108, 2993, + 3292, 2110, 2992, + 3291, 2114, 2992, + 3291, 2118, 2991, + 3290, 2123, 2989, + 3289, 2130, 2988, + 3287, 2140, 2985, + 3285, 2152, 2982, + 3282, 2168, 2978, + 3278, 2189, 2972, + 3273, 2215, 2964, + 3265, 2248, 2953, + 3256, 2289, 2938, + 3242, 2338, 2918, + 3224, 2396, 2889, + 3198, 2464, 2847, + 3160, 2541, 2784, + 3105, 2628, 2682, + 3019, 2722, 2498, + 2869, 2824, 1998, + 2535, 2932, 0, + 0, 3046, 0, + 0, 3163, 0, + 0, 3284, 0, + 0, 3408, 0, + 0, 3533, 0, + 0, 3660, 0, + 3425, 2234, 3126, + 3425, 2234, 3126, + 3425, 2235, 3126, + 3425, 2235, 3126, + 3425, 2236, 3126, + 3425, 2238, 3125, + 3424, 2239, 3125, + 3424, 2242, 3124, + 3423, 2245, 3124, + 3423, 2249, 3123, + 3422, 2255, 3121, + 3421, 2262, 3119, + 3419, 2271, 3117, + 3417, 2284, 3114, + 3414, 2300, 3110, + 3410, 2320, 3104, + 3405, 2347, 3096, + 3398, 2380, 3085, + 3388, 2420, 3070, + 3374, 2469, 3050, + 3356, 2528, 3021, + 3330, 2596, 2978, + 3292, 2673, 2915, + 3237, 2760, 2814, + 3151, 2854, 2630, + 3001, 2956, 2128, + 2668, 3064, 0, + 0, 3178, 0, + 0, 3295, 0, + 0, 3416, 0, + 0, 3540, 0, + 0, 3665, 0, + 3557, 2365, 3258, + 3557, 2365, 3258, + 3557, 2365, 3258, + 3557, 2366, 3258, + 3557, 2367, 3258, + 3557, 2368, 3257, + 3557, 2369, 3257, + 3556, 2371, 3257, + 3556, 2373, 3256, + 3556, 2376, 3255, + 3555, 2380, 3254, + 3554, 2386, 3253, + 3553, 2393, 3251, + 3551, 2403, 3249, + 3549, 2415, 3246, + 3546, 2431, 3242, + 3542, 2452, 3236, + 3537, 2478, 3228, + 3530, 2511, 3217, + 3520, 2552, 3202, + 3507, 2601, 3182, + 3488, 2660, 3152, + 3462, 2728, 3110, + 3425, 2805, 3047, + 3369, 2892, 2946, + 3283, 2986, 2761, + 3134, 3088, 2258, + 2800, 3196, 0, + 0, 3310, 0, + 0, 3427, 0, + 0, 3548, 0, + 0, 3672, 0, + 3690, 2496, 3390, + 3690, 2496, 3390, + 3689, 2497, 3390, + 3689, 2497, 3390, + 3689, 2498, 3390, + 3689, 2498, 3390, + 3689, 2499, 3389, + 3689, 2501, 3389, + 3689, 2502, 3389, + 3688, 2505, 3388, + 3688, 2508, 3387, + 3687, 2512, 3386, + 3686, 2518, 3385, + 3685, 2525, 3383, + 3683, 2534, 3381, + 3681, 2547, 3378, + 3678, 2563, 3374, + 3674, 2584, 3368, + 3669, 2610, 3360, + 3662, 2643, 3349, + 3652, 2684, 3334, + 3639, 2733, 3314, + 3620, 2791, 3284, + 3594, 2859, 3242, + 3557, 2937, 3179, + 3501, 3023, 3078, + 3415, 3118, 2893, + 3266, 3220, 2389, + 2932, 3328, 0, + 0, 3442, 0, + 0, 3559, 0, + 0, 3680, 0, + 3822, 2628, 3522, + 3822, 2628, 3522, + 3822, 2628, 3522, + 3822, 2628, 3522, + 3822, 2629, 3522, + 3821, 2629, 3522, + 3821, 2630, 3522, + 3821, 2631, 3521, + 3821, 2632, 3521, + 3821, 2634, 3521, + 3820, 2637, 3520, + 3820, 2640, 3519, + 3819, 2644, 3518, + 3818, 2649, 3517, + 3817, 2657, 3515, + 3815, 2666, 3513, + 3813, 2679, 3510, + 3810, 2695, 3506, + 3806, 2716, 3500, + 3801, 2742, 3492, + 3794, 2775, 3481, + 3784, 2816, 3466, + 3771, 2865, 3446, + 3752, 2923, 3416, + 3726, 2991, 3374, + 3689, 3069, 3311, + 3634, 3155, 3210, + 3547, 3250, 3025, + 3398, 3352, 2521, + 3064, 3460, 0, + 0, 3574, 0, + 0, 3691, 0, + 3954, 2759, 3654, + 3954, 2759, 3654, + 3954, 2760, 3654, + 3954, 2760, 3654, + 3954, 2760, 3654, + 3954, 2761, 3654, + 3954, 2761, 3654, + 3953, 2762, 3654, + 3953, 2763, 3653, + 3953, 2764, 3653, + 3953, 2766, 3653, + 3952, 2768, 3652, + 3952, 2772, 3651, + 3951, 2776, 3650, + 3950, 2781, 3649, + 3949, 2788, 3647, + 3948, 2798, 3645, + 3945, 2811, 3642, + 3943, 2827, 3638, + 3939, 2847, 3632, + 3933, 2874, 3624, + 3926, 2907, 3613, + 3916, 2947, 3598, + 3903, 2997, 3578, + 3884, 3055, 3548, + 3858, 3123, 3506, + 3821, 3201, 3443, + 3766, 3287, 3342, + 3679, 3382, 3157, + 3530, 3484, 2652, + 3197, 3593, 0, + 0, 3706, 0, + 4086, 2891, 3786, + 4086, 2891, 3786, + 4086, 2891, 3786, + 4086, 2891, 3786, + 4086, 2892, 3786, + 4086, 2892, 3786, + 4086, 2892, 3786, + 4086, 2893, 3786, + 4086, 2894, 3786, + 4085, 2895, 3786, + 4085, 2896, 3785, + 4085, 2898, 3785, + 4085, 2900, 3784, + 4084, 2903, 3784, + 4083, 2908, 3783, + 4082, 2913, 3781, + 4081, 2920, 3779, + 4080, 2930, 3777, + 4078, 2942, 3774, + 4075, 2959, 3770, + 4071, 2979, 3764, + 4065, 3006, 3756, + 4058, 3039, 3745, + 4048, 3079, 3730, + 4035, 3129, 3710, + 4017, 3187, 3680, + 3990, 3255, 3638, + 3953, 3333, 3575, + 3898, 3420, 3474, + 3811, 3514, 3289, + 3662, 3616, 2784, + 3329, 3725, 0, + 4095, 3023, 3918, + 4095, 3023, 3918, + 4095, 3023, 3918, + 4095, 3023, 3918, + 4095, 3023, 3918, + 4095, 3024, 3918, + 4095, 3024, 3918, + 4095, 3024, 3918, + 4095, 3025, 3918, + 4095, 3026, 3918, + 4095, 3027, 3918, + 4095, 3028, 3917, + 4095, 3030, 3917, + 4095, 3032, 3916, + 4095, 3035, 3916, + 4095, 3040, 3915, + 4095, 3045, 3913, + 4095, 3052, 3912, + 4095, 3062, 3909, + 4095, 3074, 3906, + 4095, 3091, 3902, + 4095, 3111, 3896, + 4095, 3138, 3888, + 4095, 3171, 3877, + 4095, 3211, 3862, + 4095, 3261, 3842, + 4095, 3319, 3812, + 4095, 3387, 3770, + 4085, 3465, 3707, + 4030, 3552, 3606, + 3944, 3646, 3421, + 3794, 3748, 2916, + 4095, 3155, 4051, + 4095, 3155, 4050, + 4095, 3155, 4050, + 4095, 3155, 4050, + 4095, 3155, 4050, + 4095, 3155, 4050, + 4095, 3156, 4050, + 4095, 3156, 4050, + 4095, 3156, 4050, + 4095, 3157, 4050, + 4095, 3158, 4050, + 4095, 3159, 4050, + 4095, 3160, 4049, + 4095, 3162, 4049, + 4095, 3164, 4048, + 4095, 3167, 4048, + 4095, 3172, 4047, + 4095, 3177, 4045, + 4095, 3184, 4044, + 4095, 3194, 4041, + 4095, 3206, 4038, + 4095, 3223, 4034, + 4095, 3243, 4028, + 4095, 3270, 4020, + 4095, 3303, 4009, + 4095, 3343, 3994, + 4095, 3393, 3974, + 4095, 3451, 3945, + 4095, 3519, 3902, + 4095, 3597, 3839, + 4095, 3684, 3738, + 4076, 3778, 3553, + 0, 193, 352, + 0, 229, 307, + 0, 273, 239, + 0, 326, 129, + 0, 388, 0, + 0, 459, 0, + 0, 540, 0, + 0, 630, 0, + 0, 728, 0, + 0, 833, 0, + 0, 943, 0, + 0, 1058, 0, + 0, 1177, 0, + 0, 1299, 0, + 0, 1423, 0, + 0, 1550, 0, + 0, 1677, 0, + 0, 1806, 0, + 0, 1936, 0, + 0, 2066, 0, + 0, 2197, 0, + 0, 2328, 0, + 0, 2459, 0, + 0, 2591, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 0, 205, 412, + 0, 240, 373, + 0, 283, 315, + 0, 335, 223, + 0, 396, 62, + 0, 466, 0, + 0, 546, 0, + 0, 635, 0, + 0, 732, 0, + 0, 836, 0, + 0, 945, 0, + 0, 1060, 0, + 0, 1178, 0, + 0, 1300, 0, + 0, 1424, 0, + 0, 1550, 0, + 0, 1678, 0, + 0, 1807, 0, + 0, 1936, 0, + 0, 2066, 0, + 0, 2197, 0, + 0, 2328, 0, + 0, 2459, 0, + 0, 2591, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 154, 222, 481, + 58, 255, 448, + 0, 297, 399, + 0, 347, 325, + 0, 407, 201, + 0, 476, 0, + 0, 554, 0, + 0, 641, 0, + 0, 737, 0, + 0, 840, 0, + 0, 949, 0, + 0, 1062, 0, + 0, 1180, 0, + 0, 1302, 0, + 0, 1425, 0, + 0, 1551, 0, + 0, 1679, 0, + 0, 1807, 0, + 0, 1936, 0, + 0, 2066, 0, + 0, 2197, 0, + 0, 2328, 0, + 0, 2459, 0, + 0, 2591, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 409, 242, 560, + 357, 275, 532, + 276, 315, 492, + 138, 363, 433, + 0, 420, 338, + 0, 488, 170, + 0, 564, 0, + 0, 650, 0, + 0, 744, 0, + 0, 845, 0, + 0, 953, 0, + 0, 1066, 0, + 0, 1183, 0, + 0, 1304, 0, + 0, 1427, 0, + 0, 1552, 0, + 0, 1679, 0, + 0, 1808, 0, + 0, 1937, 0, + 0, 2067, 0, + 0, 2197, 0, + 0, 2328, 0, + 0, 2459, 0, + 0, 2591, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 616, 269, 648, + 583, 299, 625, + 535, 337, 593, + 463, 383, 546, + 343, 438, 474, + 109, 503, 355, + 0, 577, 124, + 0, 661, 0, + 0, 753, 0, + 0, 852, 0, + 0, 958, 0, + 0, 1070, 0, + 0, 1186, 0, + 0, 1306, 0, + 0, 1429, 0, + 0, 1554, 0, + 0, 1681, 0, + 0, 1809, 0, + 0, 1938, 0, + 0, 2067, 0, + 0, 2198, 0, + 0, 2328, 0, + 0, 2460, 0, + 0, 2591, 0, + 0, 2723, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 796, 302, 744, + 775, 330, 726, + 744, 366, 700, + 700, 409, 663, + 632, 461, 608, + 523, 523, 523, + 318, 594, 377, + 0, 675, 54, + 0, 764, 0, + 0, 862, 0, + 0, 966, 0, + 0, 1076, 0, + 0, 1191, 0, + 0, 1310, 0, + 0, 1432, 0, + 0, 1556, 0, + 0, 1682, 0, + 0, 1810, 0, + 0, 1938, 0, + 0, 2068, 0, + 0, 2198, 0, + 0, 2329, 0, + 0, 2460, 0, + 0, 2591, 0, + 0, 2723, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 962, 343, 847, + 947, 369, 832, + 926, 401, 812, + 897, 442, 784, + 854, 490, 742, + 790, 549, 680, + 688, 616, 582, + 501, 693, 404, + 0, 780, 0, + 0, 874, 0, + 0, 976, 0, + 0, 1084, 0, + 0, 1197, 0, + 0, 1314, 0, + 0, 1435, 0, + 0, 1559, 0, + 0, 1684, 0, + 0, 1811, 0, + 0, 1940, 0, + 0, 2069, 0, + 0, 2199, 0, + 0, 2329, 0, + 0, 2460, 0, + 0, 2591, 0, + 0, 2723, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1117, 392, 956, + 1107, 415, 945, + 1092, 445, 929, + 1072, 482, 907, + 1043, 527, 876, + 1002, 581, 831, + 941, 644, 762, + 843, 717, 650, + 667, 799, 439, + 213, 890, 0, + 0, 988, 0, + 0, 1094, 0, + 0, 1205, 0, + 0, 1320, 0, + 0, 1440, 0, + 0, 1562, 0, + 0, 1687, 0, + 0, 1813, 0, + 0, 1941, 0, + 0, 2070, 0, + 0, 2200, 0, + 0, 2330, 0, + 0, 2461, 0, + 0, 2592, 0, + 0, 2723, 0, + 0, 2855, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1266, 450, 1070, + 1258, 471, 1061, + 1248, 497, 1049, + 1234, 530, 1032, + 1214, 571, 1009, + 1186, 620, 976, + 1146, 678, 927, + 1086, 746, 852, + 992, 824, 728, + 824, 910, 481, + 408, 1005, 0, + 0, 1107, 0, + 0, 1215, 0, + 0, 1328, 0, + 0, 1446, 0, + 0, 1567, 0, + 0, 1690, 0, + 0, 1816, 0, + 0, 1943, 0, + 0, 2072, 0, + 0, 2201, 0, + 0, 2331, 0, + 0, 2461, 0, + 0, 2592, 0, + 0, 2724, 0, + 0, 2855, 0, + 0, 2987, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1410, 519, 1188, + 1405, 536, 1182, + 1397, 559, 1172, + 1387, 588, 1160, + 1373, 624, 1142, + 1353, 668, 1117, + 1326, 721, 1082, + 1287, 783, 1030, + 1228, 855, 950, + 1136, 936, 815, + 973, 1026, 532, + 582, 1124, 0, + 0, 1229, 0, + 0, 1339, 0, + 0, 1454, 0, + 0, 1573, 0, + 0, 1695, 0, + 0, 1820, 0, + 0, 1946, 0, + 0, 2074, 0, + 0, 2202, 0, + 0, 2332, 0, + 0, 2462, 0, + 0, 2593, 0, + 0, 2724, 0, + 0, 2855, 0, + 0, 2987, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1551, 596, 1310, + 1547, 611, 1305, + 1542, 631, 1297, + 1534, 655, 1288, + 1524, 687, 1275, + 1510, 725, 1256, + 1491, 772, 1231, + 1464, 828, 1194, + 1425, 894, 1140, + 1367, 969, 1055, + 1277, 1053, 910, + 1117, 1146, 593, + 743, 1246, 0, + 0, 1353, 0, + 0, 1465, 0, + 0, 1581, 0, + 0, 1702, 0, + 0, 1824, 0, + 0, 1950, 0, + 0, 2076, 0, + 0, 2205, 0, + 0, 2334, 0, + 0, 2463, 0, + 0, 2594, 0, + 0, 2725, 0, + 0, 2856, 0, + 0, 2987, 0, + 0, 3119, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1690, 683, 1434, + 1687, 695, 1430, + 1683, 711, 1424, + 1677, 732, 1417, + 1670, 759, 1407, + 1660, 792, 1394, + 1646, 833, 1375, + 1627, 882, 1348, + 1600, 941, 1310, + 1562, 1009, 1254, + 1505, 1087, 1166, + 1415, 1173, 1013, + 1259, 1268, 663, + 895, 1370, 0, + 0, 1479, 0, + 0, 1592, 0, + 0, 1710, 0, + 0, 1831, 0, + 0, 1954, 0, + 0, 2080, 0, + 0, 2207, 0, + 0, 2336, 0, + 0, 2465, 0, + 0, 2595, 0, + 0, 2726, 0, + 0, 2856, 0, + 0, 2988, 0, + 0, 3119, 0, + 0, 3251, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1826, 777, 1560, + 1824, 788, 1557, + 1821, 801, 1552, + 1817, 818, 1547, + 1812, 840, 1540, + 1805, 868, 1530, + 1795, 903, 1516, + 1781, 945, 1496, + 1762, 997, 1469, + 1736, 1058, 1430, + 1697, 1128, 1372, + 1641, 1208, 1281, + 1552, 1296, 1121, + 1397, 1393, 742, + 1042, 1497, 0, + 0, 1606, 0, + 0, 1721, 0, + 0, 1839, 0, + 0, 1961, 0, + 0, 2085, 0, + 0, 2211, 0, + 0, 2338, 0, + 0, 2467, 0, + 0, 2597, 0, + 0, 2727, 0, + 0, 2857, 0, + 0, 2988, 0, + 0, 3120, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3514, 0, + 0, 3646, 0, + 1962, 880, 1687, + 1961, 888, 1685, + 1958, 898, 1682, + 1955, 912, 1678, + 1951, 930, 1672, + 1946, 953, 1664, + 1939, 982, 1654, + 1929, 1018, 1640, + 1915, 1062, 1620, + 1897, 1116, 1593, + 1870, 1178, 1553, + 1832, 1250, 1494, + 1776, 1331, 1400, + 1688, 1422, 1235, + 1534, 1520, 831, + 1185, 1624, 0, + 0, 1735, 0, + 0, 1850, 0, + 0, 1969, 0, + 0, 2091, 0, + 0, 2216, 0, + 0, 2342, 0, + 0, 2470, 0, + 0, 2599, 0, + 0, 2728, 0, + 0, 2859, 0, + 0, 2989, 0, + 0, 3120, 0, + 0, 3252, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3647, 0, + 2097, 988, 1815, + 2096, 994, 1814, + 2094, 1003, 1811, + 2092, 1014, 1808, + 2089, 1028, 1804, + 2085, 1047, 1799, + 2080, 1071, 1791, + 2072, 1100, 1781, + 2063, 1138, 1766, + 2049, 1183, 1746, + 2030, 1237, 1719, + 2004, 1301, 1678, + 1966, 1375, 1618, + 1910, 1457, 1523, + 1822, 1548, 1352, + 1670, 1647, 927, + 1325, 1753, 0, + 0, 1864, 0, + 0, 1980, 0, + 0, 2100, 0, + 0, 2222, 0, + 0, 2347, 0, + 0, 2474, 0, + 0, 2601, 0, + 0, 2730, 0, + 0, 2860, 0, + 0, 2990, 0, + 0, 3121, 0, + 0, 3252, 0, + 0, 3384, 0, + 0, 3515, 0, + 0, 3647, 0, + 2231, 1101, 1945, + 2230, 1106, 1944, + 2229, 1113, 1942, + 2227, 1122, 1940, + 2225, 1133, 1936, + 2222, 1148, 1932, + 2218, 1167, 1927, + 2213, 1191, 1919, + 2206, 1222, 1908, + 2196, 1260, 1894, + 2182, 1306, 1874, + 2164, 1362, 1846, + 2137, 1427, 1805, + 2100, 1501, 1744, + 2044, 1585, 1647, + 1956, 1677, 1473, + 1805, 1776, 1031, + 1463, 1883, 0, + 0, 1994, 0, + 0, 2111, 0, + 0, 2231, 0, + 0, 2353, 0, + 0, 2478, 0, + 0, 2605, 0, + 0, 2733, 0, + 0, 2862, 0, + 0, 2992, 0, + 0, 3122, 0, + 0, 3253, 0, + 0, 3384, 0, + 0, 3516, 0, + 0, 3647, 0, + 2364, 1219, 2075, + 2364, 1223, 2074, + 2363, 1228, 2073, + 2362, 1235, 2071, + 2360, 1244, 2069, + 2358, 1255, 2066, + 2355, 1270, 2061, + 2351, 1290, 2056, + 2346, 1315, 2048, + 2339, 1346, 2037, + 2329, 1385, 2023, + 2315, 1432, 2003, + 2297, 1488, 1974, + 2270, 1553, 1933, + 2233, 1629, 1871, + 2177, 1713, 1773, + 2090, 1806, 1597, + 1939, 1906, 1140, + 1599, 2013, 0, + 0, 2125, 0, + 0, 2242, 0, + 0, 2362, 0, + 0, 2485, 0, + 0, 2610, 0, + 0, 2737, 0, + 0, 2865, 0, + 0, 2994, 0, + 0, 3124, 0, + 0, 3254, 0, + 0, 3385, 0, + 0, 3516, 0, + 0, 3648, 0, + 2498, 1340, 2206, + 2497, 1343, 2205, + 2497, 1347, 2204, + 2496, 1352, 2203, + 2494, 1359, 2201, + 2493, 1368, 2199, + 2491, 1380, 2195, + 2488, 1395, 2191, + 2484, 1415, 2185, + 2478, 1440, 2178, + 2471, 1472, 2167, + 2461, 1511, 2152, + 2448, 1559, 2132, + 2429, 1615, 2103, + 2403, 1682, 2062, + 2366, 1757, 2000, + 2310, 1842, 1901, + 2223, 1936, 1723, + 2073, 2036, 1254, + 1735, 2144, 0, + 0, 2256, 0, + 0, 2373, 0, + 0, 2493, 0, + 0, 2616, 0, + 0, 2742, 0, + 0, 2869, 0, + 0, 2997, 0, + 0, 3126, 0, + 0, 3256, 0, + 0, 3386, 0, + 0, 3517, 0, + 0, 3648, 0, + 2631, 1463, 2337, + 2630, 1466, 2336, + 2630, 1469, 2335, + 2629, 1473, 2334, + 2628, 1478, 2333, + 2627, 1485, 2331, + 2625, 1494, 2329, + 2623, 1506, 2326, + 2620, 1522, 2322, + 2616, 1542, 2316, + 2611, 1567, 2308, + 2604, 1599, 2297, + 2594, 1639, 2283, + 2581, 1687, 2262, + 2562, 1744, 2233, + 2536, 1811, 2192, + 2498, 1887, 2130, + 2443, 1972, 2030, + 2356, 2066, 1850, + 2206, 2167, 1373, + 1869, 2275, 0, + 0, 2387, 0, + 0, 2504, 0, + 0, 2625, 0, + 0, 2748, 0, + 0, 2874, 0, + 0, 3001, 0, + 0, 3129, 0, + 0, 3258, 0, + 0, 3388, 0, + 0, 3518, 0, + 0, 3649, 0, + 2763, 1589, 2468, + 2763, 1591, 2467, + 2763, 1593, 2467, + 2762, 1596, 2466, + 2761, 1600, 2465, + 2761, 1605, 2464, + 2759, 1613, 2462, + 2758, 1622, 2460, + 2756, 1634, 2457, + 2753, 1650, 2452, + 2749, 1670, 2447, + 2743, 1696, 2439, + 2736, 1728, 2428, + 2727, 1768, 2413, + 2713, 1816, 2393, + 2694, 1874, 2364, + 2668, 1941, 2322, + 2631, 2017, 2260, + 2575, 2103, 2160, + 2489, 2197, 1978, + 2339, 2298, 1494, + 2003, 2406, 0, + 0, 2519, 0, + 0, 2636, 0, + 0, 2757, 0, + 0, 2880, 0, + 0, 3005, 0, + 0, 3132, 0, + 0, 3261, 0, + 0, 3390, 0, + 0, 3520, 0, + 0, 3650, 0, + 2896, 1716, 2599, + 2896, 1717, 2599, + 2895, 1719, 2599, + 2895, 1722, 2598, + 2894, 1725, 2597, + 2894, 1729, 2596, + 2893, 1734, 2595, + 2892, 1741, 2593, + 2890, 1751, 2591, + 2888, 1763, 2588, + 2885, 1779, 2583, + 2881, 1799, 2578, + 2876, 1825, 2570, + 2869, 1857, 2559, + 2859, 1897, 2544, + 2845, 1946, 2524, + 2827, 2004, 2495, + 2801, 2071, 2453, + 2763, 2148, 2390, + 2708, 2234, 2290, + 2621, 2328, 2108, + 2472, 2430, 1618, + 2136, 2537, 0, + 0, 2650, 0, + 0, 2768, 0, + 0, 2888, 0, + 0, 3012, 0, + 0, 3137, 0, + 0, 3264, 0, + 0, 3393, 0, + 0, 3522, 0, + 0, 3652, 0, + 3028, 1845, 2731, + 3028, 1846, 2731, + 3028, 1847, 2730, + 3028, 1849, 2730, + 3027, 1851, 2729, + 3027, 1854, 2729, + 3026, 1858, 2728, + 3025, 1864, 2726, + 3024, 1871, 2725, + 3022, 1880, 2722, + 3020, 1892, 2719, + 3017, 1908, 2715, + 3013, 1929, 2709, + 3008, 1955, 2701, + 3001, 1987, 2690, + 2991, 2028, 2676, + 2978, 2076, 2655, + 2959, 2134, 2626, + 2933, 2202, 2584, + 2896, 2279, 2521, + 2840, 2365, 2421, + 2754, 2459, 2238, + 2604, 2561, 1744, + 2269, 2669, 0, + 0, 2782, 0, + 0, 2900, 0, + 0, 3020, 0, + 0, 3144, 0, + 0, 3269, 0, + 0, 3396, 0, + 0, 3525, 0, + 0, 3654, 0, + 3161, 1974, 2863, + 3161, 1975, 2862, + 3160, 1976, 2862, + 3160, 1977, 2862, + 3160, 1979, 2862, + 3160, 1981, 2861, + 3159, 1984, 2860, + 3158, 1988, 2859, + 3157, 1994, 2858, + 3156, 2001, 2856, + 3155, 2010, 2854, + 3152, 2023, 2851, + 3150, 2039, 2846, + 3146, 2059, 2841, + 3140, 2085, 2833, + 3133, 2118, 2822, + 3123, 2158, 2807, + 3110, 2207, 2787, + 3091, 2266, 2758, + 3065, 2333, 2716, + 3028, 2410, 2653, + 2973, 2497, 2552, + 2886, 2591, 2368, + 2737, 2693, 1872, + 2402, 2801, 0, + 0, 2914, 0, + 0, 3031, 0, + 0, 3152, 0, + 0, 3276, 0, + 0, 3401, 0, + 0, 3528, 0, + 0, 3657, 0, + 3293, 2104, 2994, + 3293, 2104, 2994, + 3293, 2105, 2994, + 3293, 2106, 2994, + 3292, 2107, 2994, + 3292, 2109, 2993, + 3292, 2112, 2993, + 3291, 2115, 2992, + 3291, 2119, 2991, + 3290, 2124, 2990, + 3288, 2132, 2988, + 3287, 2141, 2986, + 3285, 2153, 2982, + 3282, 2169, 2978, + 3278, 2190, 2972, + 3273, 2216, 2964, + 3265, 2249, 2954, + 3256, 2290, 2939, + 3242, 2339, 2918, + 3224, 2397, 2889, + 3198, 2465, 2847, + 3160, 2542, 2784, + 3105, 2628, 2683, + 3018, 2723, 2499, + 2869, 2825, 2000, + 2535, 2933, 0, + 0, 3046, 0, + 0, 3163, 0, + 0, 3284, 0, + 0, 3408, 0, + 0, 3533, 0, + 0, 3661, 0, + 3425, 2234, 3126, + 3425, 2235, 3126, + 3425, 2235, 3126, + 3425, 2236, 3126, + 3425, 2237, 3126, + 3425, 2238, 3125, + 3424, 2240, 3125, + 3424, 2243, 3124, + 3423, 2246, 3124, + 3423, 2250, 3123, + 3422, 2255, 3121, + 3421, 2263, 3120, + 3419, 2272, 3117, + 3417, 2284, 3114, + 3414, 2301, 3110, + 3410, 2321, 3104, + 3405, 2347, 3096, + 3398, 2380, 3085, + 3388, 2421, 3071, + 3374, 2470, 3050, + 3356, 2528, 3021, + 3330, 2596, 2979, + 3292, 2674, 2916, + 3237, 2760, 2815, + 3151, 2855, 2631, + 3001, 2956, 2130, + 2667, 3065, 0, + 0, 3178, 0, + 0, 3295, 0, + 0, 3416, 0, + 0, 3540, 0, + 0, 3665, 0, + 3557, 2365, 3258, + 3557, 2366, 3258, + 3557, 2366, 3258, + 3557, 2367, 3258, + 3557, 2367, 3258, + 3557, 2368, 3258, + 3557, 2370, 3257, + 3556, 2371, 3257, + 3556, 2374, 3256, + 3556, 2377, 3256, + 3555, 2381, 3255, + 3554, 2387, 3253, + 3553, 2394, 3252, + 3551, 2403, 3249, + 3549, 2416, 3246, + 3546, 2432, 3242, + 3542, 2453, 3236, + 3537, 2479, 3228, + 3530, 2512, 3217, + 3520, 2552, 3202, + 3507, 2602, 3182, + 3488, 2660, 3153, + 3462, 2728, 3111, + 3425, 2805, 3047, + 3369, 2892, 2946, + 3283, 2986, 2762, + 3134, 3088, 2260, + 2800, 3197, 0, + 0, 3310, 0, + 0, 3427, 0, + 0, 3548, 0, + 0, 3672, 0, + 3690, 2497, 3390, + 3690, 2497, 3390, + 3689, 2497, 3390, + 3689, 2498, 3390, + 3689, 2498, 3390, + 3689, 2499, 3390, + 3689, 2500, 3390, + 3689, 2501, 3389, + 3689, 2503, 3389, + 3688, 2505, 3388, + 3688, 2508, 3388, + 3687, 2513, 3387, + 3686, 2518, 3385, + 3685, 2525, 3384, + 3683, 2535, 3381, + 3681, 2547, 3378, + 3678, 2563, 3374, + 3674, 2584, 3368, + 3669, 2610, 3360, + 3662, 2643, 3349, + 3652, 2684, 3334, + 3639, 2733, 3314, + 3620, 2792, 3285, + 3594, 2860, 3242, + 3557, 2937, 3179, + 3501, 3024, 3078, + 3415, 3118, 2894, + 3266, 3220, 2391, + 2932, 3329, 0, + 0, 3442, 0, + 0, 3559, 0, + 0, 3680, 0, + 3822, 2628, 3522, + 3822, 2628, 3522, + 3822, 2628, 3522, + 3822, 2629, 3522, + 3822, 2629, 3522, + 3821, 2630, 3522, + 3821, 2630, 3522, + 3821, 2631, 3522, + 3821, 2633, 3521, + 3821, 2635, 3521, + 3820, 2637, 3520, + 3820, 2640, 3520, + 3819, 2644, 3519, + 3818, 2650, 3517, + 3817, 2657, 3515, + 3815, 2667, 3513, + 3813, 2679, 3510, + 3810, 2695, 3506, + 3806, 2716, 3500, + 3801, 2742, 3492, + 3794, 2775, 3481, + 3784, 2816, 3466, + 3771, 2865, 3446, + 3752, 2924, 3416, + 3726, 2992, 3374, + 3689, 3069, 3311, + 3634, 3156, 3210, + 3547, 3250, 3025, + 3398, 3352, 2521, + 3064, 3461, 0, + 0, 3574, 0, + 0, 3692, 0, + 3954, 2760, 3654, + 3954, 2760, 3654, + 3954, 2760, 3654, + 3954, 2760, 3654, + 3954, 2760, 3654, + 3954, 2761, 3654, + 3954, 2761, 3654, + 3953, 2762, 3654, + 3953, 2763, 3654, + 3953, 2764, 3653, + 3953, 2766, 3653, + 3952, 2769, 3652, + 3952, 2772, 3652, + 3951, 2776, 3651, + 3950, 2781, 3649, + 3949, 2789, 3647, + 3948, 2798, 3645, + 3945, 2811, 3642, + 3942, 2827, 3638, + 3939, 2848, 3632, + 3933, 2874, 3624, + 3926, 2907, 3613, + 3916, 2948, 3598, + 3903, 2997, 3578, + 3884, 3055, 3548, + 3858, 3123, 3506, + 3821, 3201, 3443, + 3766, 3288, 3342, + 3679, 3382, 3157, + 3530, 3484, 2653, + 3197, 3593, 0, + 0, 3706, 0, + 4086, 2891, 3786, + 4086, 2891, 3786, + 4086, 2892, 3786, + 4086, 2892, 3786, + 4086, 2892, 3786, + 4086, 2892, 3786, + 4086, 2893, 3786, + 4086, 2893, 3786, + 4086, 2894, 3786, + 4085, 2895, 3786, + 4085, 2896, 3785, + 4085, 2898, 3785, + 4085, 2900, 3784, + 4084, 2904, 3784, + 4083, 2908, 3783, + 4082, 2913, 3781, + 4081, 2921, 3780, + 4080, 2930, 3777, + 4078, 2943, 3774, + 4075, 2959, 3770, + 4071, 2980, 3764, + 4065, 3006, 3756, + 4058, 3039, 3745, + 4048, 3080, 3730, + 4035, 3129, 3710, + 4017, 3187, 3680, + 3990, 3255, 3638, + 3953, 3333, 3575, + 3898, 3420, 3474, + 3811, 3514, 3289, + 3662, 3616, 2784, + 3329, 3725, 0, + 4095, 3023, 3918, + 4095, 3023, 3918, + 4095, 3023, 3918, + 4095, 3023, 3918, + 4095, 3024, 3918, + 4095, 3024, 3918, + 4095, 3024, 3918, + 4095, 3025, 3918, + 4095, 3025, 3918, + 4095, 3026, 3918, + 4095, 3027, 3918, + 4095, 3028, 3917, + 4095, 3030, 3917, + 4095, 3032, 3916, + 4095, 3036, 3916, + 4095, 3040, 3915, + 4095, 3045, 3913, + 4095, 3052, 3912, + 4095, 3062, 3909, + 4095, 3075, 3906, + 4095, 3091, 3902, + 4095, 3111, 3896, + 4095, 3138, 3888, + 4095, 3171, 3877, + 4095, 3212, 3862, + 4095, 3261, 3842, + 4095, 3319, 3813, + 4095, 3387, 3770, + 4085, 3465, 3707, + 4030, 3552, 3606, + 3944, 3646, 3421, + 3794, 3748, 2916, + 4095, 3155, 4051, + 4095, 3155, 4051, + 4095, 3155, 4051, + 4095, 3155, 4050, + 4095, 3155, 4050, + 4095, 3156, 4050, + 4095, 3156, 4050, + 4095, 3156, 4050, + 4095, 3157, 4050, + 4095, 3157, 4050, + 4095, 3158, 4050, + 4095, 3159, 4050, + 4095, 3160, 4049, + 4095, 3162, 4049, + 4095, 3164, 4048, + 4095, 3167, 4048, + 4095, 3172, 4047, + 4095, 3177, 4045, + 4095, 3184, 4044, + 4095, 3194, 4041, + 4095, 3206, 4038, + 4095, 3223, 4034, + 4095, 3243, 4028, + 4095, 3270, 4020, + 4095, 3303, 4009, + 4095, 3344, 3994, + 4095, 3393, 3974, + 4095, 3451, 3945, + 4095, 3520, 3902, + 4095, 3597, 3839, + 4095, 3684, 3738, + 4076, 3778, 3553, + 0, 286, 468, + 0, 316, 433, + 0, 352, 383, + 0, 397, 305, + 0, 450, 175, + 0, 514, 0, + 0, 586, 0, + 0, 668, 0, + 0, 759, 0, + 0, 857, 0, + 0, 962, 0, + 0, 1073, 0, + 0, 1189, 0, + 0, 1308, 0, + 0, 1430, 0, + 0, 1555, 0, + 0, 1681, 0, + 0, 1809, 0, + 0, 1938, 0, + 0, 2068, 0, + 0, 2198, 0, + 0, 2329, 0, + 0, 2460, 0, + 0, 2591, 0, + 0, 2723, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 0, 296, 515, + 0, 325, 484, + 0, 361, 439, + 0, 405, 371, + 0, 458, 261, + 0, 520, 54, + 0, 592, 0, + 0, 673, 0, + 0, 762, 0, + 0, 860, 0, + 0, 965, 0, + 0, 1075, 0, + 0, 1190, 0, + 0, 1309, 0, + 0, 1431, 0, + 0, 1556, 0, + 0, 1682, 0, + 0, 1810, 0, + 0, 1938, 0, + 0, 2068, 0, + 0, 2198, 0, + 0, 2329, 0, + 0, 2460, 0, + 0, 2591, 0, + 0, 2723, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 38, 310, 571, + 0, 338, 544, + 0, 372, 505, + 0, 415, 447, + 0, 467, 355, + 0, 528, 195, + 0, 599, 0, + 0, 678, 0, + 0, 767, 0, + 0, 864, 0, + 0, 968, 0, + 0, 1077, 0, + 0, 1192, 0, + 0, 1311, 0, + 0, 1432, 0, + 0, 1556, 0, + 0, 1682, 0, + 0, 1810, 0, + 0, 1939, 0, + 0, 2068, 0, + 0, 2198, 0, + 0, 2329, 0, + 0, 2460, 0, + 0, 2591, 0, + 0, 2723, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 347, 327, 637, + 286, 354, 613, + 190, 387, 580, + 17, 429, 531, + 0, 479, 457, + 0, 539, 333, + 0, 608, 87, + 0, 686, 0, + 0, 774, 0, + 0, 869, 0, + 0, 972, 0, + 0, 1081, 0, + 0, 1194, 0, + 0, 1312, 0, + 0, 1434, 0, + 0, 1558, 0, + 0, 1683, 0, + 0, 1811, 0, + 0, 1939, 0, + 0, 2069, 0, + 0, 2199, 0, + 0, 2329, 0, + 0, 2460, 0, + 0, 2591, 0, + 0, 2723, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 577, 349, 712, + 541, 375, 692, + 489, 407, 664, + 408, 447, 624, + 270, 495, 565, + 0, 553, 470, + 0, 620, 302, + 0, 696, 0, + 0, 782, 0, + 0, 876, 0, + 0, 977, 0, + 0, 1085, 0, + 0, 1198, 0, + 0, 1315, 0, + 0, 1436, 0, + 0, 1559, 0, + 0, 1684, 0, + 0, 1812, 0, + 0, 1940, 0, + 0, 2069, 0, + 0, 2199, 0, + 0, 2329, 0, + 0, 2460, 0, + 0, 2591, 0, + 0, 2723, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 771, 377, 796, + 748, 401, 780, + 715, 431, 757, + 668, 469, 725, + 595, 515, 678, + 475, 571, 606, + 241, 635, 487, + 0, 709, 256, + 0, 793, 0, + 0, 885, 0, + 0, 984, 0, + 0, 1091, 0, + 0, 1202, 0, + 0, 1318, 0, + 0, 1438, 0, + 0, 1561, 0, + 0, 1686, 0, + 0, 1813, 0, + 0, 1941, 0, + 0, 2070, 0, + 0, 2199, 0, + 0, 2330, 0, + 0, 2461, 0, + 0, 2592, 0, + 0, 2723, 0, + 0, 2855, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 944, 411, 889, + 928, 434, 876, + 907, 462, 858, + 876, 498, 832, + 832, 541, 795, + 764, 594, 740, + 655, 655, 655, + 450, 726, 509, + 0, 807, 186, + 0, 896, 0, + 0, 994, 0, + 0, 1098, 0, + 0, 1208, 0, + 0, 1323, 0, + 0, 1442, 0, + 0, 1564, 0, + 0, 1688, 0, + 0, 1814, 0, + 0, 1942, 0, + 0, 2071, 0, + 0, 2200, 0, + 0, 2330, 0, + 0, 2461, 0, + 0, 2592, 0, + 0, 2723, 0, + 0, 2855, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1105, 454, 990, + 1094, 475, 979, + 1079, 501, 965, + 1058, 533, 944, + 1029, 574, 916, + 986, 623, 874, + 922, 681, 813, + 820, 748, 714, + 633, 825, 536, + 113, 912, 73, + 0, 1006, 0, + 0, 1108, 0, + 0, 1216, 0, + 0, 1329, 0, + 0, 1446, 0, + 0, 1567, 0, + 0, 1691, 0, + 0, 1816, 0, + 0, 1943, 0, + 0, 2072, 0, + 0, 2201, 0, + 0, 2331, 0, + 0, 2461, 0, + 0, 2592, 0, + 0, 2724, 0, + 0, 2855, 0, + 0, 2987, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1257, 506, 1097, + 1249, 524, 1088, + 1239, 547, 1077, + 1224, 577, 1061, + 1204, 614, 1039, + 1175, 659, 1008, + 1134, 713, 963, + 1073, 776, 894, + 975, 849, 783, + 799, 931, 571, + 345, 1022, 0, + 0, 1121, 0, + 0, 1226, 0, + 0, 1337, 0, + 0, 1452, 0, + 0, 1572, 0, + 0, 1694, 0, + 0, 1819, 0, + 0, 1945, 0, + 0, 2073, 0, + 0, 2202, 0, + 0, 2332, 0, + 0, 2462, 0, + 0, 2593, 0, + 0, 2724, 0, + 0, 2855, 0, + 0, 2987, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1404, 566, 1209, + 1398, 582, 1202, + 1390, 603, 1193, + 1380, 629, 1181, + 1366, 662, 1165, + 1346, 703, 1141, + 1318, 752, 1108, + 1278, 811, 1059, + 1218, 878, 984, + 1124, 956, 860, + 956, 1042, 613, + 540, 1137, 0, + 0, 1239, 0, + 0, 1347, 0, + 0, 1461, 0, + 0, 1578, 0, + 0, 1699, 0, + 0, 1823, 0, + 0, 1948, 0, + 0, 2075, 0, + 0, 2204, 0, + 0, 2333, 0, + 0, 2463, 0, + 0, 2593, 0, + 0, 2724, 0, + 0, 2856, 0, + 0, 2987, 0, + 0, 3119, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1546, 637, 1325, + 1542, 651, 1320, + 1537, 668, 1314, + 1529, 691, 1304, + 1519, 720, 1292, + 1505, 756, 1274, + 1486, 800, 1249, + 1458, 853, 1214, + 1419, 915, 1162, + 1360, 987, 1082, + 1268, 1068, 947, + 1105, 1158, 665, + 714, 1256, 0, + 0, 1361, 0, + 0, 1471, 0, + 0, 1586, 0, + 0, 1705, 0, + 0, 1827, 0, + 0, 1952, 0, + 0, 2078, 0, + 0, 2206, 0, + 0, 2335, 0, + 0, 2464, 0, + 0, 2594, 0, + 0, 2725, 0, + 0, 2856, 0, + 0, 2987, 0, + 0, 3119, 0, + 0, 3251, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1686, 717, 1446, + 1683, 728, 1442, + 1679, 743, 1437, + 1674, 763, 1430, + 1666, 787, 1420, + 1656, 819, 1407, + 1642, 857, 1388, + 1623, 904, 1363, + 1596, 960, 1326, + 1557, 1026, 1272, + 1500, 1101, 1187, + 1409, 1185, 1042, + 1250, 1278, 725, + 875, 1378, 0, + 0, 1485, 0, + 0, 1597, 0, + 0, 1713, 0, + 0, 1834, 0, + 0, 1957, 0, + 0, 2082, 0, + 0, 2209, 0, + 0, 2337, 0, + 0, 2466, 0, + 0, 2596, 0, + 0, 2726, 0, + 0, 2857, 0, + 0, 2988, 0, + 0, 3119, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3514, 0, + 0, 3646, 0, + 1824, 805, 1569, + 1822, 815, 1566, + 1819, 827, 1562, + 1815, 843, 1556, + 1809, 864, 1549, + 1802, 891, 1539, + 1792, 924, 1526, + 1778, 965, 1507, + 1759, 1014, 1480, + 1732, 1073, 1442, + 1694, 1141, 1386, + 1637, 1219, 1298, + 1547, 1305, 1145, + 1391, 1400, 795, + 1028, 1502, 0, + 0, 1611, 0, + 0, 1724, 0, + 0, 1842, 0, + 0, 1963, 0, + 0, 2087, 0, + 0, 2212, 0, + 0, 2339, 0, + 0, 2468, 0, + 0, 2597, 0, + 0, 2727, 0, + 0, 2858, 0, + 0, 2989, 0, + 0, 3120, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3646, 0, + 1960, 902, 1694, + 1959, 910, 1692, + 1956, 920, 1689, + 1953, 933, 1685, + 1949, 950, 1679, + 1944, 972, 1672, + 1937, 1000, 1662, + 1927, 1035, 1648, + 1913, 1077, 1628, + 1894, 1129, 1601, + 1868, 1190, 1562, + 1830, 1260, 1505, + 1773, 1340, 1413, + 1684, 1428, 1253, + 1530, 1525, 875, + 1174, 1629, 0, + 0, 1738, 0, + 0, 1853, 0, + 0, 1971, 0, + 0, 2093, 0, + 0, 2217, 0, + 0, 2343, 0, + 0, 2471, 0, + 0, 2599, 0, + 0, 2729, 0, + 0, 2859, 0, + 0, 2989, 0, + 0, 3120, 0, + 0, 3252, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3647, 0, + 2095, 1005, 1821, + 2094, 1012, 1819, + 2093, 1020, 1817, + 2090, 1030, 1814, + 2087, 1044, 1810, + 2084, 1062, 1804, + 2078, 1085, 1797, + 2071, 1114, 1786, + 2061, 1150, 1772, + 2047, 1195, 1753, + 2029, 1248, 1725, + 2002, 1310, 1685, + 1964, 1382, 1626, + 1908, 1464, 1533, + 1820, 1554, 1367, + 1667, 1652, 963, + 1317, 1756, 0, + 0, 1867, 0, + 0, 1982, 0, + 0, 2101, 0, + 0, 2223, 0, + 0, 2348, 0, + 0, 2474, 0, + 0, 2602, 0, + 0, 2731, 0, + 0, 2860, 0, + 0, 2991, 0, + 0, 3121, 0, + 0, 3252, 0, + 0, 3384, 0, + 0, 3515, 0, + 0, 3647, 0, + 2230, 1115, 1949, + 2229, 1120, 1948, + 2228, 1126, 1946, + 2226, 1135, 1944, + 2224, 1146, 1941, + 2221, 1160, 1936, + 2217, 1179, 1931, + 2212, 1203, 1923, + 2205, 1233, 1913, + 2195, 1270, 1898, + 2181, 1315, 1879, + 2162, 1369, 1851, + 2136, 1433, 1810, + 2098, 1507, 1750, + 2042, 1589, 1655, + 1955, 1681, 1484, + 1802, 1780, 1059, + 1457, 1885, 0, + 0, 1996, 0, + 0, 2112, 0, + 0, 2232, 0, + 0, 2354, 0, + 0, 2479, 0, + 0, 2606, 0, + 0, 2734, 0, + 0, 2862, 0, + 0, 2992, 0, + 0, 3123, 0, + 0, 3253, 0, + 0, 3384, 0, + 0, 3516, 0, + 0, 3647, 0, + 2364, 1229, 2078, + 2363, 1233, 2077, + 2362, 1238, 2076, + 2361, 1245, 2074, + 2359, 1254, 2072, + 2357, 1265, 2069, + 2354, 1280, 2064, + 2350, 1299, 2059, + 2345, 1323, 2051, + 2338, 1354, 2041, + 2328, 1392, 2026, + 2314, 1438, 2006, + 2296, 1494, 1978, + 2269, 1559, 1937, + 2232, 1633, 1876, + 2176, 1717, 1779, + 2089, 1809, 1606, + 1937, 1908, 1163, + 1595, 2015, 0, + 0, 2127, 0, + 0, 2243, 0, + 0, 2363, 0, + 0, 2486, 0, + 0, 2611, 0, + 0, 2737, 0, + 0, 2865, 0, + 0, 2994, 0, + 0, 3124, 0, + 0, 3254, 0, + 0, 3385, 0, + 0, 3516, 0, + 0, 3648, 0, + 2497, 1348, 2208, + 2497, 1351, 2207, + 2496, 1355, 2206, + 2495, 1360, 2205, + 2494, 1367, 2203, + 2492, 1376, 2201, + 2490, 1387, 2198, + 2487, 1402, 2193, + 2483, 1422, 2188, + 2478, 1447, 2180, + 2471, 1478, 2169, + 2461, 1517, 2155, + 2447, 1564, 2135, + 2429, 1620, 2106, + 2402, 1686, 2065, + 2365, 1761, 2004, + 2309, 1845, 1906, + 2222, 1938, 1729, + 2071, 2038, 1272, + 1731, 2145, 0, + 0, 2257, 0, + 0, 2374, 0, + 0, 2494, 0, + 0, 2617, 0, + 0, 2742, 0, + 0, 2869, 0, + 0, 2997, 0, + 0, 3126, 0, + 0, 3256, 0, + 0, 3386, 0, + 0, 3517, 0, + 0, 3648, 0, + 2630, 1470, 2338, + 2630, 1472, 2338, + 2629, 1475, 2337, + 2629, 1479, 2336, + 2628, 1484, 2335, + 2627, 1491, 2333, + 2625, 1500, 2331, + 2623, 1512, 2327, + 2620, 1527, 2323, + 2616, 1547, 2317, + 2611, 1572, 2310, + 2603, 1604, 2299, + 2594, 1643, 2284, + 2580, 1691, 2264, + 2561, 1748, 2236, + 2535, 1814, 2194, + 2498, 1890, 2132, + 2442, 1974, 2033, + 2355, 2068, 1855, + 2205, 2168, 1386, + 1867, 2276, 0, + 0, 2388, 0, + 0, 2505, 0, + 0, 2625, 0, + 0, 2749, 0, + 0, 2874, 0, + 0, 3001, 0, + 0, 3129, 0, + 0, 3258, 0, + 0, 3388, 0, + 0, 3518, 0, + 0, 3649, 0, + 2763, 1594, 2469, + 2763, 1595, 2469, + 2762, 1598, 2468, + 2762, 1601, 2467, + 2761, 1605, 2466, + 2760, 1610, 2465, + 2759, 1617, 2463, + 2757, 1626, 2461, + 2755, 1638, 2458, + 2752, 1654, 2454, + 2748, 1674, 2448, + 2743, 1699, 2440, + 2736, 1731, 2429, + 2726, 1771, 2415, + 2713, 1819, 2394, + 2694, 1876, 2366, + 2668, 1943, 2324, + 2630, 2019, 2262, + 2575, 2104, 2162, + 2488, 2198, 1982, + 2338, 2299, 1505, + 2001, 2407, 0, + 0, 2519, 0, + 0, 2637, 0, + 0, 2757, 0, + 0, 2880, 0, + 0, 3006, 0, + 0, 3133, 0, + 0, 3261, 0, + 0, 3390, 0, + 0, 3520, 0, + 0, 3650, 0, + 2896, 1720, 2600, + 2895, 1721, 2600, + 2895, 1723, 2600, + 2895, 1725, 2599, + 2894, 1728, 2598, + 2894, 1732, 2597, + 2893, 1738, 2596, + 2891, 1745, 2594, + 2890, 1754, 2592, + 2888, 1766, 2589, + 2885, 1782, 2584, + 2881, 1802, 2579, + 2876, 1828, 2571, + 2868, 1860, 2560, + 2859, 1900, 2545, + 2845, 1948, 2525, + 2827, 2006, 2496, + 2800, 2073, 2454, + 2763, 2149, 2392, + 2708, 2235, 2292, + 2621, 2329, 2111, + 2471, 2430, 1626, + 2135, 2538, 0, + 0, 2651, 0, + 0, 2768, 0, + 0, 2889, 0, + 0, 3012, 0, + 0, 3138, 0, + 0, 3265, 0, + 0, 3393, 0, + 0, 3522, 0, + 0, 3652, 0, + 3028, 1847, 2732, + 3028, 1848, 2731, + 3028, 1850, 2731, + 3027, 1851, 2731, + 3027, 1854, 2730, + 3027, 1857, 2729, + 3026, 1861, 2728, + 3025, 1866, 2727, + 3024, 1873, 2725, + 3022, 1883, 2723, + 3020, 1895, 2720, + 3017, 1911, 2716, + 3013, 1931, 2710, + 3008, 1957, 2702, + 3001, 1989, 2691, + 2991, 2030, 2676, + 2978, 2078, 2656, + 2959, 2136, 2627, + 2933, 2203, 2585, + 2895, 2280, 2522, + 2840, 2366, 2422, + 2753, 2460, 2240, + 2604, 2562, 1750, + 2268, 2670, 0, + 0, 2783, 0, + 0, 2900, 0, + 0, 3021, 0, + 0, 3144, 0, + 0, 3269, 0, + 0, 3397, 0, + 0, 3525, 0, + 0, 3654, 0, + 3160, 1976, 2863, + 3160, 1977, 2863, + 3160, 1978, 2863, + 3160, 1979, 2862, + 3160, 1981, 2862, + 3159, 1983, 2862, + 3159, 1986, 2861, + 3158, 1990, 2860, + 3157, 1996, 2858, + 3156, 2003, 2857, + 3154, 2012, 2854, + 3152, 2025, 2851, + 3149, 2040, 2847, + 3146, 2061, 2841, + 3140, 2087, 2833, + 3133, 2120, 2822, + 3123, 2160, 2808, + 3110, 2209, 2787, + 3091, 2267, 2758, + 3065, 2334, 2716, + 3028, 2411, 2653, + 2972, 2497, 2553, + 2886, 2592, 2370, + 2736, 2693, 1876, + 2401, 2801, 0, + 0, 2914, 0, + 0, 3032, 0, + 0, 3152, 0, + 0, 3276, 0, + 0, 3401, 0, + 0, 3529, 0, + 0, 3657, 0, + 3293, 2105, 2995, + 3293, 2106, 2995, + 3293, 2107, 2995, + 3292, 2108, 2994, + 3292, 2109, 2994, + 3292, 2111, 2994, + 3292, 2113, 2993, + 3291, 2116, 2992, + 3290, 2120, 2991, + 3290, 2126, 2990, + 3288, 2133, 2988, + 3287, 2142, 2986, + 3285, 2155, 2983, + 3282, 2171, 2978, + 3278, 2191, 2973, + 3272, 2217, 2965, + 3265, 2250, 2954, + 3256, 2291, 2939, + 3242, 2339, 2919, + 3224, 2398, 2890, + 3197, 2465, 2848, + 3160, 2542, 2785, + 3105, 2629, 2684, + 3018, 2723, 2500, + 2869, 2825, 2004, + 2534, 2933, 0, + 0, 3046, 0, + 0, 3164, 0, + 0, 3284, 0, + 0, 3408, 0, + 0, 3533, 0, + 0, 3661, 0, + 3425, 2236, 3127, + 3425, 2236, 3127, + 3425, 2237, 3126, + 3425, 2237, 3126, + 3425, 2238, 3126, + 3424, 2240, 3126, + 3424, 2241, 3125, + 3424, 2244, 3125, + 3423, 2247, 3124, + 3423, 2251, 3123, + 3422, 2256, 3122, + 3421, 2264, 3120, + 3419, 2273, 3118, + 3417, 2286, 3114, + 3414, 2302, 3110, + 3410, 2322, 3104, + 3405, 2348, 3096, + 3397, 2381, 3086, + 3388, 2422, 3071, + 3374, 2471, 3050, + 3356, 2529, 3021, + 3330, 2597, 2979, + 3292, 2674, 2916, + 3237, 2760, 2815, + 3150, 2855, 2631, + 3001, 2957, 2132, + 2667, 3065, 0, + 0, 3178, 0, + 0, 3296, 0, + 0, 3416, 0, + 0, 3540, 0, + 0, 3665, 0, + 3557, 2366, 3259, + 3557, 2367, 3258, + 3557, 2367, 3258, + 3557, 2367, 3258, + 3557, 2368, 3258, + 3557, 2369, 3258, + 3557, 2371, 3258, + 3556, 2372, 3257, + 3556, 2375, 3257, + 3555, 2378, 3256, + 3555, 2382, 3255, + 3554, 2387, 3254, + 3553, 2395, 3252, + 3551, 2404, 3249, + 3549, 2417, 3246, + 3546, 2433, 3242, + 3542, 2453, 3236, + 3537, 2480, 3228, + 3530, 2512, 3217, + 3520, 2553, 3203, + 3506, 2602, 3182, + 3488, 2660, 3153, + 3462, 2728, 3111, + 3424, 2806, 3048, + 3369, 2892, 2947, + 3283, 2987, 2763, + 3133, 3089, 2262, + 2799, 3197, 0, + 0, 3310, 0, + 0, 3428, 0, + 0, 3548, 0, + 0, 3672, 0, + 3689, 2497, 3390, + 3689, 2497, 3390, + 3689, 2498, 3390, + 3689, 2498, 3390, + 3689, 2499, 3390, + 3689, 2499, 3390, + 3689, 2500, 3390, + 3689, 2502, 3389, + 3688, 2504, 3389, + 3688, 2506, 3388, + 3688, 2509, 3388, + 3687, 2513, 3387, + 3686, 2519, 3385, + 3685, 2526, 3384, + 3683, 2535, 3381, + 3681, 2548, 3378, + 3678, 2564, 3374, + 3674, 2585, 3368, + 3669, 2611, 3360, + 3662, 2644, 3349, + 3652, 2684, 3334, + 3639, 2734, 3314, + 3620, 2792, 3285, + 3594, 2860, 3243, + 3557, 2937, 3179, + 3501, 3024, 3078, + 3415, 3119, 2894, + 3266, 3220, 2392, + 2932, 3329, 0, + 0, 3442, 0, + 0, 3560, 0, + 0, 3680, 0, + 3822, 2628, 3522, + 3822, 2629, 3522, + 3822, 2629, 3522, + 3822, 2629, 3522, + 3821, 2630, 3522, + 3821, 2630, 3522, + 3821, 2631, 3522, + 3821, 2632, 3522, + 3821, 2633, 3521, + 3821, 2635, 3521, + 3820, 2637, 3520, + 3820, 2641, 3520, + 3819, 2645, 3519, + 3818, 2650, 3517, + 3817, 2657, 3516, + 3815, 2667, 3513, + 3813, 2679, 3510, + 3810, 2696, 3506, + 3806, 2716, 3500, + 3801, 2743, 3492, + 3794, 2775, 3481, + 3784, 2816, 3466, + 3771, 2865, 3446, + 3752, 2924, 3417, + 3726, 2992, 3375, + 3689, 3069, 3311, + 3633, 3156, 3210, + 3547, 3250, 3026, + 3398, 3352, 2523, + 3064, 3461, 0, + 0, 3574, 0, + 0, 3692, 0, + 3954, 2760, 3654, + 3954, 2760, 3654, + 3954, 2760, 3654, + 3954, 2760, 3654, + 3954, 2761, 3654, + 3954, 2761, 3654, + 3954, 2762, 3654, + 3953, 2763, 3654, + 3953, 2764, 3654, + 3953, 2765, 3653, + 3953, 2767, 3653, + 3952, 2769, 3652, + 3952, 2772, 3652, + 3951, 2776, 3651, + 3950, 2782, 3649, + 3949, 2789, 3648, + 3948, 2799, 3645, + 3945, 2811, 3642, + 3942, 2827, 3638, + 3939, 2848, 3632, + 3933, 2874, 3624, + 3926, 2907, 3613, + 3916, 2948, 3598, + 3903, 2997, 3578, + 3884, 3056, 3549, + 3858, 3124, 3506, + 3821, 3201, 3443, + 3766, 3288, 3342, + 3679, 3382, 3157, + 3530, 3484, 2654, + 3196, 3593, 0, + 0, 3706, 0, + 4086, 2892, 3786, + 4086, 2892, 3786, + 4086, 2892, 3786, + 4086, 2892, 3786, + 4086, 2892, 3786, + 4086, 2893, 3786, + 4086, 2893, 3786, + 4086, 2894, 3786, + 4086, 2894, 3786, + 4085, 2895, 3786, + 4085, 2897, 3785, + 4085, 2898, 3785, + 4085, 2901, 3784, + 4084, 2904, 3784, + 4083, 2908, 3783, + 4082, 2914, 3781, + 4081, 2921, 3780, + 4080, 2930, 3777, + 4077, 2943, 3774, + 4075, 2959, 3770, + 4071, 2980, 3764, + 4065, 3006, 3756, + 4058, 3039, 3745, + 4048, 3080, 3730, + 4035, 3129, 3710, + 4017, 3188, 3681, + 3990, 3256, 3638, + 3953, 3333, 3575, + 3898, 3420, 3474, + 3811, 3514, 3289, + 3662, 3616, 2785, + 3329, 3725, 0, + 4095, 3023, 3919, + 4095, 3023, 3918, + 4095, 3023, 3918, + 4095, 3024, 3918, + 4095, 3024, 3918, + 4095, 3024, 3918, + 4095, 3024, 3918, + 4095, 3025, 3918, + 4095, 3025, 3918, + 4095, 3026, 3918, + 4095, 3027, 3918, + 4095, 3028, 3917, + 4095, 3030, 3917, + 4095, 3033, 3916, + 4095, 3036, 3916, + 4095, 3040, 3915, + 4095, 3045, 3913, + 4095, 3053, 3912, + 4095, 3062, 3909, + 4095, 3075, 3906, + 4095, 3091, 3902, + 4095, 3112, 3896, + 4095, 3138, 3888, + 4095, 3171, 3877, + 4095, 3212, 3862, + 4095, 3261, 3842, + 4095, 3319, 3813, + 4095, 3388, 3770, + 4085, 3465, 3707, + 4030, 3552, 3606, + 3944, 3646, 3421, + 3794, 3748, 2916, + 4095, 3155, 4051, + 4095, 3155, 4051, + 4095, 3155, 4051, + 4095, 3155, 4051, + 4095, 3156, 4050, + 4095, 3156, 4050, + 4095, 3156, 4050, + 4095, 3156, 4050, + 4095, 3157, 4050, + 4095, 3157, 4050, + 4095, 3158, 4050, + 4095, 3159, 4050, + 4095, 3160, 4049, + 4095, 3162, 4049, + 4095, 3164, 4048, + 4095, 3168, 4048, + 4095, 3172, 4047, + 4095, 3177, 4045, + 4095, 3185, 4044, + 4095, 3194, 4041, + 4095, 3207, 4038, + 4095, 3223, 4034, + 4095, 3244, 4028, + 4095, 3270, 4020, + 4095, 3303, 4009, + 4095, 3344, 3994, + 4095, 3393, 3974, + 4095, 3451, 3945, + 4095, 3520, 3902, + 4095, 3597, 3839, + 4095, 3684, 3738, + 4076, 3778, 3553, + 0, 387, 587, + 0, 410, 561, + 0, 440, 523, + 0, 477, 468, + 0, 523, 381, + 0, 577, 231, + 0, 641, 0, + 0, 714, 0, + 0, 797, 0, + 0, 888, 0, + 0, 987, 0, + 0, 1093, 0, + 0, 1204, 0, + 0, 1320, 0, + 0, 1439, 0, + 0, 1562, 0, + 0, 1687, 0, + 0, 1813, 0, + 0, 1941, 0, + 0, 2070, 0, + 0, 2200, 0, + 0, 2330, 0, + 0, 2461, 0, + 0, 2592, 0, + 0, 2723, 0, + 0, 2855, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 0, 395, 624, + 0, 418, 600, + 0, 448, 565, + 0, 484, 515, + 0, 529, 437, + 0, 583, 307, + 0, 646, 42, + 0, 718, 0, + 0, 800, 0, + 0, 891, 0, + 0, 989, 0, + 0, 1094, 0, + 0, 1205, 0, + 0, 1321, 0, + 0, 1440, 0, + 0, 1562, 0, + 0, 1687, 0, + 0, 1813, 0, + 0, 1941, 0, + 0, 2070, 0, + 0, 2200, 0, + 0, 2330, 0, + 0, 2461, 0, + 0, 2592, 0, + 0, 2723, 0, + 0, 2855, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 0, 406, 669, + 0, 428, 647, + 0, 457, 616, + 0, 493, 571, + 0, 537, 503, + 0, 590, 393, + 0, 652, 186, + 0, 724, 0, + 0, 805, 0, + 0, 894, 0, + 0, 992, 0, + 0, 1097, 0, + 0, 1207, 0, + 0, 1322, 0, + 0, 1441, 0, + 0, 1563, 0, + 0, 1688, 0, + 0, 1814, 0, + 0, 1942, 0, + 0, 2070, 0, + 0, 2200, 0, + 0, 2330, 0, + 0, 2461, 0, + 0, 2592, 0, + 0, 2723, 0, + 0, 2855, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 247, 420, 722, + 170, 442, 703, + 41, 470, 676, + 0, 505, 637, + 0, 547, 579, + 0, 599, 487, + 0, 660, 327, + 0, 731, 0, + 0, 811, 0, + 0, 899, 0, + 0, 996, 0, + 0, 1100, 0, + 0, 1210, 0, + 0, 1324, 0, + 0, 1443, 0, + 0, 1564, 0, + 0, 1688, 0, + 0, 1815, 0, + 0, 1942, 0, + 0, 2071, 0, + 0, 2200, 0, + 0, 2330, 0, + 0, 2461, 0, + 0, 2592, 0, + 0, 2723, 0, + 0, 2855, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 519, 438, 786, + 479, 459, 769, + 418, 486, 745, + 322, 520, 712, + 149, 561, 663, + 0, 611, 589, + 0, 671, 465, + 0, 740, 219, + 0, 818, 0, + 0, 906, 0, + 0, 1001, 0, + 0, 1104, 0, + 0, 1213, 0, + 0, 1327, 0, + 0, 1445, 0, + 0, 1566, 0, + 0, 1690, 0, + 0, 1815, 0, + 0, 1943, 0, + 0, 2071, 0, + 0, 2201, 0, + 0, 2331, 0, + 0, 2461, 0, + 0, 2592, 0, + 0, 2723, 0, + 0, 2855, 0, + 0, 2987, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 734, 461, 858, + 709, 481, 844, + 673, 507, 824, + 621, 539, 797, + 540, 579, 756, + 402, 627, 697, + 110, 685, 602, + 0, 752, 434, + 0, 828, 18, + 0, 914, 0, + 0, 1008, 0, + 0, 1109, 0, + 0, 1217, 0, + 0, 1330, 0, + 0, 1447, 0, + 0, 1568, 0, + 0, 1691, 0, + 0, 1817, 0, + 0, 1944, 0, + 0, 2072, 0, + 0, 2201, 0, + 0, 2331, 0, + 0, 2462, 0, + 0, 2592, 0, + 0, 2724, 0, + 0, 2855, 0, + 0, 2987, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 919, 490, 940, + 903, 509, 929, + 880, 533, 912, + 847, 563, 889, + 800, 601, 857, + 727, 647, 810, + 607, 703, 738, + 373, 767, 619, + 0, 842, 388, + 0, 925, 0, + 0, 1017, 0, + 0, 1116, 0, + 0, 1223, 0, + 0, 1334, 0, + 0, 1451, 0, + 0, 1570, 0, + 0, 1693, 0, + 0, 1818, 0, + 0, 1945, 0, + 0, 2073, 0, + 0, 2202, 0, + 0, 2332, 0, + 0, 2462, 0, + 0, 2593, 0, + 0, 2724, 0, + 0, 2855, 0, + 0, 2987, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1087, 526, 1031, + 1076, 544, 1021, + 1061, 566, 1008, + 1039, 594, 990, + 1008, 630, 964, + 964, 673, 927, + 896, 726, 872, + 787, 787, 787, + 582, 859, 641, + 0, 939, 318, + 0, 1029, 0, + 0, 1126, 0, + 0, 1230, 0, + 0, 1340, 0, + 0, 1455, 0, + 0, 1574, 0, + 0, 1696, 0, + 0, 1820, 0, + 0, 1946, 0, + 0, 2074, 0, + 0, 2203, 0, + 0, 2332, 0, + 0, 2462, 0, + 0, 2593, 0, + 0, 2724, 0, + 0, 2855, 0, + 0, 2987, 0, + 0, 3119, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1245, 570, 1130, + 1237, 586, 1122, + 1226, 607, 1111, + 1211, 633, 1097, + 1190, 665, 1076, + 1161, 706, 1048, + 1118, 755, 1006, + 1055, 813, 945, + 952, 880, 846, + 765, 958, 669, + 245, 1044, 205, + 0, 1138, 0, + 0, 1240, 0, + 0, 1348, 0, + 0, 1461, 0, + 0, 1578, 0, + 0, 1699, 0, + 0, 1823, 0, + 0, 1948, 0, + 0, 2075, 0, + 0, 2204, 0, + 0, 2333, 0, + 0, 2463, 0, + 0, 2594, 0, + 0, 2724, 0, + 0, 2856, 0, + 0, 2987, 0, + 0, 3119, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1395, 623, 1235, + 1389, 638, 1229, + 1381, 656, 1220, + 1371, 679, 1209, + 1356, 709, 1193, + 1336, 746, 1171, + 1308, 791, 1140, + 1267, 845, 1095, + 1205, 908, 1026, + 1107, 981, 915, + 932, 1063, 703, + 477, 1154, 0, + 0, 1253, 0, + 0, 1358, 0, + 0, 1469, 0, + 0, 1585, 0, + 0, 1704, 0, + 0, 1826, 0, + 0, 1951, 0, + 0, 2077, 0, + 0, 2205, 0, + 0, 2334, 0, + 0, 2464, 0, + 0, 2594, 0, + 0, 2725, 0, + 0, 2856, 0, + 0, 2987, 0, + 0, 3119, 0, + 0, 3251, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1540, 686, 1346, + 1536, 698, 1341, + 1530, 715, 1334, + 1522, 735, 1326, + 1512, 762, 1313, + 1498, 794, 1297, + 1478, 835, 1273, + 1450, 884, 1240, + 1410, 943, 1191, + 1351, 1011, 1116, + 1256, 1088, 993, + 1088, 1174, 745, + 672, 1269, 0, + 0, 1371, 0, + 0, 1479, 0, + 0, 1593, 0, + 0, 1710, 0, + 0, 1831, 0, + 0, 1955, 0, + 0, 2080, 0, + 0, 2207, 0, + 0, 2336, 0, + 0, 2465, 0, + 0, 2595, 0, + 0, 2726, 0, + 0, 2857, 0, + 0, 2988, 0, + 0, 3119, 0, + 0, 3251, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1681, 758, 1461, + 1678, 769, 1458, + 1674, 783, 1453, + 1669, 801, 1446, + 1661, 823, 1436, + 1651, 852, 1424, + 1637, 888, 1406, + 1618, 932, 1381, + 1590, 985, 1346, + 1551, 1047, 1295, + 1492, 1119, 1215, + 1400, 1200, 1079, + 1237, 1290, 797, + 846, 1388, 0, + 0, 1493, 0, + 0, 1603, 0, + 0, 1718, 0, + 0, 1837, 0, + 0, 1959, 0, + 0, 2084, 0, + 0, 2210, 0, + 0, 2338, 0, + 0, 2467, 0, + 0, 2596, 0, + 0, 2726, 0, + 0, 2857, 0, + 0, 2988, 0, + 0, 3120, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3514, 0, + 0, 3646, 0, + 1820, 840, 1581, + 1818, 849, 1578, + 1815, 860, 1574, + 1811, 875, 1569, + 1806, 895, 1562, + 1798, 920, 1552, + 1788, 951, 1539, + 1774, 989, 1521, + 1755, 1036, 1495, + 1728, 1092, 1458, + 1689, 1158, 1404, + 1632, 1233, 1319, + 1541, 1317, 1174, + 1382, 1410, 857, + 1007, 1510, 0, + 0, 1617, 0, + 0, 1729, 0, + 0, 1846, 0, + 0, 1966, 0, + 0, 2089, 0, + 0, 2214, 0, + 0, 2341, 0, + 0, 2469, 0, + 0, 2598, 0, + 0, 2728, 0, + 0, 2858, 0, + 0, 2989, 0, + 0, 3120, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3646, 0, + 1958, 930, 1703, + 1956, 937, 1701, + 1954, 947, 1698, + 1951, 959, 1694, + 1947, 976, 1689, + 1941, 996, 1681, + 1934, 1023, 1671, + 1924, 1056, 1658, + 1910, 1097, 1639, + 1891, 1146, 1613, + 1865, 1205, 1575, + 1826, 1273, 1518, + 1769, 1351, 1430, + 1679, 1437, 1277, + 1523, 1532, 927, + 1160, 1635, 0, + 0, 1743, 0, + 0, 1856, 0, + 0, 1974, 0, + 0, 2095, 0, + 0, 2219, 0, + 0, 2344, 0, + 0, 2471, 0, + 0, 2600, 0, + 0, 2729, 0, + 0, 2859, 0, + 0, 2990, 0, + 0, 3121, 0, + 0, 3252, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3647, 0, + 2094, 1028, 1828, + 2092, 1034, 1826, + 2091, 1042, 1824, + 2088, 1052, 1821, + 2086, 1065, 1817, + 2082, 1082, 1811, + 2076, 1104, 1804, + 2069, 1132, 1794, + 2059, 1167, 1780, + 2045, 1210, 1761, + 2026, 1261, 1733, + 2000, 1322, 1695, + 1962, 1392, 1637, + 1905, 1472, 1545, + 1816, 1561, 1385, + 1662, 1657, 1007, + 1307, 1761, 0, + 0, 1870, 0, + 0, 1985, 0, + 0, 2103, 0, + 0, 2225, 0, + 0, 2349, 0, + 0, 2475, 0, + 0, 2603, 0, + 0, 2731, 0, + 0, 2861, 0, + 0, 2991, 0, + 0, 3122, 0, + 0, 3253, 0, + 0, 3384, 0, + 0, 3515, 0, + 0, 3647, 0, + 2228, 1133, 1954, + 2228, 1138, 1953, + 2226, 1144, 1951, + 2225, 1152, 1949, + 2223, 1163, 1946, + 2220, 1176, 1942, + 2216, 1194, 1936, + 2210, 1217, 1929, + 2203, 1246, 1918, + 2193, 1282, 1904, + 2180, 1327, 1885, + 2161, 1380, 1857, + 2134, 1442, 1817, + 2096, 1514, 1758, + 2040, 1596, 1665, + 1952, 1686, 1499, + 1799, 1784, 1095, + 1449, 1888, 0, + 0, 1999, 0, + 0, 2114, 0, + 0, 2233, 0, + 0, 2356, 0, + 0, 2480, 0, + 0, 2606, 0, + 0, 2734, 0, + 0, 2863, 0, + 0, 2992, 0, + 0, 3123, 0, + 0, 3253, 0, + 0, 3384, 0, + 0, 3516, 0, + 0, 3647, 0, + 2363, 1243, 2082, + 2362, 1247, 2081, + 2361, 1252, 2080, + 2360, 1258, 2078, + 2358, 1267, 2076, + 2356, 1278, 2073, + 2353, 1292, 2068, + 2349, 1311, 2063, + 2344, 1335, 2055, + 2337, 1365, 2045, + 2327, 1402, 2031, + 2313, 1447, 2011, + 2294, 1502, 1983, + 2268, 1565, 1942, + 2230, 1639, 1882, + 2174, 1721, 1787, + 2087, 1813, 1617, + 1934, 1912, 1191, + 1589, 2017, 0, + 0, 2129, 0, + 0, 2244, 0, + 0, 2364, 0, + 0, 2486, 0, + 0, 2611, 0, + 0, 2738, 0, + 0, 2866, 0, + 0, 2995, 0, + 0, 3124, 0, + 0, 3255, 0, + 0, 3385, 0, + 0, 3516, 0, + 0, 3648, 0, + 2496, 1359, 2211, + 2496, 1362, 2210, + 2495, 1365, 2209, + 2494, 1370, 2208, + 2493, 1377, 2206, + 2491, 1386, 2204, + 2489, 1397, 2201, + 2486, 1412, 2196, + 2482, 1431, 2191, + 2477, 1455, 2183, + 2470, 1486, 2173, + 2460, 1524, 2158, + 2446, 1570, 2138, + 2428, 1626, 2110, + 2402, 1691, 2069, + 2364, 1765, 2008, + 2308, 1849, 1911, + 2221, 1941, 1738, + 2069, 2041, 1295, + 1727, 2147, 0, + 0, 2259, 0, + 0, 2375, 0, + 0, 2495, 0, + 0, 2618, 0, + 0, 2743, 0, + 0, 2869, 0, + 0, 2997, 0, + 0, 3126, 0, + 0, 3256, 0, + 0, 3387, 0, + 0, 3517, 0, + 0, 3648, 0, + 2630, 1478, 2340, + 2629, 1480, 2340, + 2629, 1483, 2339, + 2628, 1487, 2338, + 2627, 1492, 2337, + 2626, 1499, 2335, + 2624, 1508, 2333, + 2622, 1519, 2330, + 2619, 1535, 2326, + 2615, 1554, 2320, + 2610, 1579, 2312, + 2603, 1610, 2302, + 2593, 1649, 2287, + 2579, 1696, 2267, + 2561, 1752, 2238, + 2535, 1818, 2197, + 2497, 1893, 2136, + 2441, 1977, 2038, + 2354, 2070, 1861, + 2203, 2170, 1404, + 1864, 2277, 0, + 0, 2389, 0, + 0, 2506, 0, + 0, 2626, 0, + 0, 2749, 0, + 0, 2874, 0, + 0, 3001, 0, + 0, 3129, 0, + 0, 3258, 0, + 0, 3388, 0, + 0, 3519, 0, + 0, 3649, 0, + 2763, 1600, 2471, + 2762, 1602, 2470, + 2762, 1604, 2470, + 2761, 1607, 2469, + 2761, 1611, 2468, + 2760, 1616, 2467, + 2759, 1623, 2465, + 2757, 1632, 2463, + 2755, 1644, 2460, + 2752, 1659, 2455, + 2748, 1679, 2450, + 2743, 1704, 2442, + 2735, 1736, 2431, + 2726, 1775, 2417, + 2712, 1823, 2396, + 2694, 1880, 2368, + 2667, 1946, 2326, + 2630, 2022, 2264, + 2574, 2107, 2165, + 2487, 2200, 1987, + 2337, 2301, 1518, + 1999, 2408, 0, + 0, 2520, 0, + 0, 2637, 0, + 0, 2758, 0, + 0, 2881, 0, + 0, 3006, 0, + 0, 3133, 0, + 0, 3261, 0, + 0, 3390, 0, + 0, 3520, 0, + 0, 3651, 0, + 2895, 1725, 2601, + 2895, 1726, 2601, + 2895, 1728, 2601, + 2894, 1730, 2600, + 2894, 1733, 2599, + 2893, 1737, 2599, + 2892, 1742, 2597, + 2891, 1749, 2595, + 2890, 1758, 2593, + 2887, 1770, 2590, + 2884, 1786, 2586, + 2881, 1806, 2580, + 2875, 1832, 2572, + 2868, 1864, 2561, + 2858, 1903, 2547, + 2845, 1951, 2526, + 2826, 2008, 2498, + 2800, 2075, 2456, + 2763, 2151, 2394, + 2707, 2237, 2294, + 2620, 2330, 2114, + 2470, 2431, 1637, + 2133, 2539, 0, + 0, 2652, 0, + 0, 2769, 0, + 0, 2889, 0, + 0, 3012, 0, + 0, 3138, 0, + 0, 3265, 0, + 0, 3393, 0, + 0, 3522, 0, + 0, 3652, 0, + 3028, 1851, 2733, + 3028, 1852, 2732, + 3027, 1853, 2732, + 3027, 1855, 2732, + 3027, 1857, 2731, + 3026, 1860, 2730, + 3026, 1864, 2729, + 3025, 1870, 2728, + 3024, 1877, 2726, + 3022, 1886, 2724, + 3020, 1898, 2721, + 3017, 1914, 2717, + 3013, 1934, 2711, + 3008, 1960, 2703, + 3000, 1992, 2692, + 2991, 2032, 2677, + 2977, 2080, 2657, + 2959, 2138, 2628, + 2933, 2205, 2586, + 2895, 2282, 2524, + 2840, 2367, 2424, + 2753, 2461, 2243, + 2603, 2562, 1758, + 2267, 2670, 0, + 0, 2783, 0, + 0, 2900, 0, + 0, 3021, 0, + 0, 3144, 0, + 0, 3270, 0, + 0, 3397, 0, + 0, 3525, 0, + 0, 3654, 0, + 3160, 1979, 2864, + 3160, 1979, 2864, + 3160, 1980, 2863, + 3160, 1982, 2863, + 3160, 1983, 2863, + 3159, 1986, 2862, + 3159, 1989, 2861, + 3158, 1993, 2861, + 3157, 1998, 2859, + 3156, 2005, 2857, + 3154, 2015, 2855, + 3152, 2027, 2852, + 3149, 2043, 2848, + 3145, 2063, 2842, + 3140, 2089, 2834, + 3133, 2122, 2823, + 3123, 2162, 2809, + 3110, 2210, 2788, + 3091, 2268, 2759, + 3065, 2335, 2717, + 3028, 2412, 2654, + 2972, 2498, 2554, + 2886, 2592, 2372, + 2736, 2694, 1882, + 2401, 2802, 0, + 0, 2915, 0, + 0, 3032, 0, + 0, 3153, 0, + 0, 3276, 0, + 0, 3402, 0, + 0, 3529, 0, + 0, 3657, 0, + 3293, 2107, 2995, + 3293, 2108, 2995, + 3292, 2109, 2995, + 3292, 2110, 2995, + 3292, 2111, 2995, + 3292, 2113, 2994, + 3291, 2115, 2994, + 3291, 2118, 2993, + 3290, 2122, 2992, + 3289, 2128, 2991, + 3288, 2135, 2989, + 3287, 2144, 2986, + 3284, 2157, 2983, + 3282, 2173, 2979, + 3278, 2193, 2973, + 3272, 2219, 2965, + 3265, 2252, 2955, + 3255, 2292, 2940, + 3242, 2341, 2919, + 3223, 2399, 2890, + 3197, 2466, 2848, + 3160, 2543, 2785, + 3104, 2629, 2685, + 3018, 2724, 2502, + 2868, 2825, 2008, + 2534, 2933, 0, + 0, 3046, 0, + 0, 3164, 0, + 0, 3285, 0, + 0, 3408, 0, + 0, 3534, 0, + 0, 3661, 0, + 3425, 2237, 3127, + 3425, 2238, 3127, + 3425, 2238, 3127, + 3425, 2239, 3127, + 3425, 2240, 3126, + 3424, 2241, 3126, + 3424, 2243, 3126, + 3424, 2245, 3125, + 3423, 2248, 3124, + 3423, 2252, 3123, + 3422, 2258, 3122, + 3420, 2265, 3120, + 3419, 2275, 3118, + 3417, 2287, 3115, + 3414, 2303, 3111, + 3410, 2323, 3105, + 3405, 2350, 3097, + 3397, 2382, 3086, + 3388, 2423, 3071, + 3374, 2472, 3051, + 3356, 2530, 3022, + 3330, 2597, 2980, + 3292, 2675, 2917, + 3237, 2761, 2816, + 3150, 2855, 2633, + 3001, 2957, 2136, + 2666, 3065, 0, + 0, 3178, 0, + 0, 3296, 0, + 0, 3417, 0, + 0, 3540, 0, + 0, 3666, 0, + 3557, 2367, 3259, + 3557, 2368, 3259, + 3557, 2368, 3259, + 3557, 2369, 3259, + 3557, 2369, 3258, + 3557, 2370, 3258, + 3557, 2372, 3258, + 3556, 2373, 3257, + 3556, 2376, 3257, + 3555, 2379, 3256, + 3555, 2383, 3255, + 3554, 2389, 3254, + 3553, 2396, 3252, + 3551, 2405, 3250, + 3549, 2418, 3247, + 3546, 2434, 3242, + 3542, 2454, 3236, + 3537, 2480, 3229, + 3530, 2513, 3218, + 3520, 2554, 3203, + 3506, 2603, 3182, + 3488, 2661, 3153, + 3462, 2729, 3111, + 3424, 2806, 3048, + 3369, 2892, 2947, + 3283, 2987, 2763, + 3133, 3089, 2264, + 2799, 3197, 0, + 0, 3310, 0, + 0, 3428, 0, + 0, 3548, 0, + 0, 3672, 0, + 3689, 2498, 3391, + 3689, 2498, 3391, + 3689, 2499, 3391, + 3689, 2499, 3390, + 3689, 2500, 3390, + 3689, 2500, 3390, + 3689, 2501, 3390, + 3689, 2503, 3390, + 3688, 2504, 3389, + 3688, 2507, 3389, + 3688, 2510, 3388, + 3687, 2514, 3387, + 3686, 2520, 3386, + 3685, 2527, 3384, + 3683, 2536, 3382, + 3681, 2549, 3378, + 3678, 2565, 3374, + 3674, 2585, 3368, + 3669, 2612, 3360, + 3662, 2644, 3350, + 3652, 2685, 3335, + 3639, 2734, 3314, + 3620, 2792, 3285, + 3594, 2860, 3243, + 3557, 2938, 3180, + 3501, 3024, 3079, + 3415, 3119, 2895, + 3265, 3221, 2394, + 2932, 3329, 0, + 0, 3442, 0, + 0, 3560, 0, + 0, 3681, 0, + 3822, 2629, 3523, + 3822, 2629, 3523, + 3822, 2630, 3523, + 3822, 2630, 3522, + 3821, 2630, 3522, + 3821, 2631, 3522, + 3821, 2632, 3522, + 3821, 2633, 3522, + 3821, 2634, 3522, + 3821, 2636, 3521, + 3820, 2638, 3521, + 3820, 2641, 3520, + 3819, 2645, 3519, + 3818, 2651, 3518, + 3817, 2658, 3516, + 3815, 2668, 3513, + 3813, 2680, 3510, + 3810, 2696, 3506, + 3806, 2717, 3500, + 3801, 2743, 3492, + 3794, 2776, 3481, + 3784, 2817, 3467, + 3771, 2866, 3446, + 3752, 2924, 3417, + 3726, 2992, 3375, + 3689, 3069, 3312, + 3633, 3156, 3210, + 3547, 3251, 3026, + 3398, 3353, 2524, + 3064, 3461, 0, + 0, 3574, 0, + 0, 3692, 0, + 3954, 2760, 3655, + 3954, 2761, 3655, + 3954, 2761, 3654, + 3954, 2761, 3654, + 3954, 2761, 3654, + 3954, 2762, 3654, + 3953, 2762, 3654, + 3953, 2763, 3654, + 3953, 2764, 3654, + 3953, 2765, 3653, + 3953, 2767, 3653, + 3952, 2769, 3652, + 3952, 2773, 3652, + 3951, 2777, 3651, + 3950, 2782, 3649, + 3949, 2790, 3648, + 3947, 2799, 3645, + 3945, 2812, 3642, + 3942, 2828, 3638, + 3939, 2848, 3632, + 3933, 2875, 3624, + 3926, 2908, 3613, + 3916, 2948, 3598, + 3903, 2997, 3578, + 3884, 3056, 3549, + 3858, 3124, 3507, + 3821, 3201, 3443, + 3766, 3288, 3342, + 3679, 3383, 3158, + 3530, 3485, 2655, + 3196, 3593, 0, + 0, 3706, 0, + 4086, 2892, 3787, + 4086, 2892, 3787, + 4086, 2892, 3787, + 4086, 2892, 3786, + 4086, 2893, 3786, + 4086, 2893, 3786, + 4086, 2893, 3786, + 4086, 2894, 3786, + 4086, 2895, 3786, + 4085, 2896, 3786, + 4085, 2897, 3785, + 4085, 2899, 3785, + 4084, 2901, 3784, + 4084, 2904, 3784, + 4083, 2908, 3783, + 4082, 2914, 3781, + 4081, 2921, 3780, + 4080, 2931, 3777, + 4077, 2943, 3774, + 4075, 2959, 3770, + 4071, 2980, 3764, + 4065, 3006, 3756, + 4058, 3039, 3745, + 4048, 3080, 3730, + 4035, 3129, 3710, + 4016, 3188, 3681, + 3990, 3256, 3639, + 3953, 3333, 3575, + 3898, 3420, 3474, + 3811, 3515, 3289, + 3662, 3617, 2786, + 3329, 3725, 0, + 4095, 3024, 3919, + 4095, 3024, 3919, + 4095, 3024, 3919, + 4095, 3024, 3919, + 4095, 3024, 3918, + 4095, 3024, 3918, + 4095, 3025, 3918, + 4095, 3025, 3918, + 4095, 3026, 3918, + 4095, 3026, 3918, + 4095, 3027, 3918, + 4095, 3029, 3917, + 4095, 3030, 3917, + 4095, 3033, 3916, + 4095, 3036, 3916, + 4095, 3040, 3915, + 4095, 3046, 3913, + 4095, 3053, 3912, + 4095, 3062, 3909, + 4095, 3075, 3906, + 4095, 3091, 3902, + 4095, 3112, 3896, + 4095, 3138, 3888, + 4095, 3171, 3877, + 4095, 3212, 3862, + 4095, 3261, 3842, + 4095, 3320, 3813, + 4095, 3388, 3771, + 4085, 3465, 3707, + 4030, 3552, 3606, + 3943, 3647, 3421, + 3794, 3749, 2917, + 4095, 3155, 4051, + 4095, 3155, 4051, + 4095, 3155, 4051, + 4095, 3156, 4051, + 4095, 3156, 4051, + 4095, 3156, 4051, + 4095, 3156, 4050, + 4095, 3156, 4050, + 4095, 3157, 4050, + 4095, 3157, 4050, + 4095, 3158, 4050, + 4095, 3159, 4050, + 4095, 3161, 4049, + 4095, 3162, 4049, + 4095, 3165, 4048, + 4095, 3168, 4048, + 4095, 3172, 4047, + 4095, 3177, 4045, + 4095, 3185, 4044, + 4095, 3194, 4041, + 4095, 3207, 4038, + 4095, 3223, 4034, + 4095, 3244, 4028, + 4095, 3270, 4020, + 4095, 3303, 4009, + 4095, 3344, 3994, + 4095, 3393, 3974, + 4095, 3452, 3945, + 4095, 3520, 3903, + 4095, 3597, 3839, + 4095, 3684, 3738, + 4076, 3779, 3553, + 0, 494, 709, + 0, 513, 690, + 0, 537, 662, + 0, 567, 621, + 0, 604, 561, + 0, 650, 466, + 0, 705, 295, + 0, 770, 0, + 0, 843, 0, + 0, 927, 0, + 0, 1018, 0, + 0, 1118, 0, + 0, 1223, 0, + 0, 1335, 0, + 0, 1451, 0, + 0, 1571, 0, + 0, 1693, 0, + 0, 1818, 0, + 0, 1945, 0, + 0, 2073, 0, + 0, 2202, 0, + 0, 2332, 0, + 0, 2462, 0, + 0, 2593, 0, + 0, 2724, 0, + 0, 2855, 0, + 0, 2987, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 0, 500, 738, + 0, 519, 719, + 0, 543, 693, + 0, 572, 655, + 0, 610, 600, + 0, 655, 513, + 0, 709, 363, + 0, 773, 25, + 0, 846, 0, + 0, 929, 0, + 0, 1020, 0, + 0, 1119, 0, + 0, 1225, 0, + 0, 1336, 0, + 0, 1452, 0, + 0, 1571, 0, + 0, 1694, 0, + 0, 1819, 0, + 0, 1945, 0, + 0, 2073, 0, + 0, 2202, 0, + 0, 2332, 0, + 0, 2462, 0, + 0, 2593, 0, + 0, 2724, 0, + 0, 2855, 0, + 0, 2987, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 0, 509, 773, + 0, 527, 756, + 0, 550, 732, + 0, 580, 697, + 0, 616, 647, + 0, 661, 569, + 0, 715, 440, + 0, 778, 174, + 0, 850, 0, + 0, 932, 0, + 0, 1023, 0, + 0, 1121, 0, + 0, 1227, 0, + 0, 1337, 0, + 0, 1453, 0, + 0, 1572, 0, + 0, 1694, 0, + 0, 1819, 0, + 0, 1946, 0, + 0, 2073, 0, + 0, 2202, 0, + 0, 2332, 0, + 0, 2462, 0, + 0, 2593, 0, + 0, 2724, 0, + 0, 2855, 0, + 0, 2987, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 66, 520, 816, + 0, 538, 801, + 0, 561, 779, + 0, 589, 748, + 0, 625, 703, + 0, 669, 635, + 0, 722, 525, + 0, 784, 318, + 0, 856, 0, + 0, 937, 0, + 0, 1027, 0, + 0, 1124, 0, + 0, 1229, 0, + 0, 1339, 0, + 0, 1454, 0, + 0, 1573, 0, + 0, 1695, 0, + 0, 1820, 0, + 0, 1946, 0, + 0, 2074, 0, + 0, 2202, 0, + 0, 2332, 0, + 0, 2462, 0, + 0, 2593, 0, + 0, 2724, 0, + 0, 2855, 0, + 0, 2987, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 429, 534, 868, + 379, 552, 854, + 302, 574, 835, + 173, 602, 808, + 0, 637, 769, + 0, 680, 711, + 0, 731, 620, + 0, 792, 459, + 0, 863, 78, + 0, 943, 0, + 0, 1031, 0, + 0, 1128, 0, + 0, 1232, 0, + 0, 1342, 0, + 0, 1456, 0, + 0, 1575, 0, + 0, 1696, 0, + 0, 1821, 0, + 0, 1947, 0, + 0, 2074, 0, + 0, 2203, 0, + 0, 2332, 0, + 0, 2463, 0, + 0, 2593, 0, + 0, 2724, 0, + 0, 2855, 0, + 0, 2987, 0, + 0, 3119, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 680, 553, 930, + 652, 570, 918, + 611, 591, 901, + 550, 618, 878, + 454, 652, 844, + 281, 693, 796, + 0, 743, 721, + 0, 803, 597, + 0, 872, 351, + 0, 950, 0, + 0, 1038, 0, + 0, 1133, 0, + 0, 1236, 0, + 0, 1345, 0, + 0, 1459, 0, + 0, 1577, 0, + 0, 1698, 0, + 0, 1822, 0, + 0, 1948, 0, + 0, 2075, 0, + 0, 2203, 0, + 0, 2333, 0, + 0, 2463, 0, + 0, 2593, 0, + 0, 2724, 0, + 0, 2856, 0, + 0, 2987, 0, + 0, 3119, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 884, 577, 1001, + 866, 593, 990, + 841, 613, 976, + 806, 639, 956, + 753, 671, 929, + 672, 711, 889, + 534, 759, 829, + 243, 817, 734, + 0, 884, 566, + 0, 960, 150, + 0, 1046, 0, + 0, 1140, 0, + 0, 1241, 0, + 0, 1349, 0, + 0, 1462, 0, + 0, 1579, 0, + 0, 1700, 0, + 0, 1823, 0, + 0, 1949, 0, + 0, 2076, 0, + 0, 2204, 0, + 0, 2333, 0, + 0, 2463, 0, + 0, 2594, 0, + 0, 2725, 0, + 0, 2856, 0, + 0, 2987, 0, + 0, 3119, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1063, 607, 1081, + 1051, 622, 1072, + 1035, 641, 1061, + 1012, 665, 1044, + 979, 696, 1022, + 932, 733, 989, + 859, 780, 942, + 739, 835, 870, + 505, 899, 751, + 0, 974, 520, + 0, 1057, 0, + 0, 1149, 0, + 0, 1249, 0, + 0, 1355, 0, + 0, 1466, 0, + 0, 1583, 0, + 0, 1702, 0, + 0, 1825, 0, + 0, 1950, 0, + 0, 2077, 0, + 0, 2205, 0, + 0, 2334, 0, + 0, 2464, 0, + 0, 2594, 0, + 0, 2725, 0, + 0, 2856, 0, + 0, 2987, 0, + 0, 3119, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1228, 644, 1170, + 1219, 658, 1163, + 1208, 676, 1153, + 1193, 698, 1140, + 1171, 727, 1122, + 1140, 762, 1096, + 1096, 805, 1059, + 1029, 858, 1005, + 919, 919, 919, + 715, 991, 773, + 63, 1071, 450, + 0, 1161, 0, + 0, 1258, 0, + 0, 1362, 0, + 0, 1472, 0, + 0, 1587, 0, + 0, 1706, 0, + 0, 1828, 0, + 0, 1952, 0, + 0, 2078, 0, + 0, 2206, 0, + 0, 2335, 0, + 0, 2464, 0, + 0, 2594, 0, + 0, 2725, 0, + 0, 2856, 0, + 0, 2987, 0, + 0, 3119, 0, + 0, 3251, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1383, 690, 1267, + 1377, 702, 1262, + 1369, 718, 1254, + 1358, 739, 1243, + 1343, 765, 1229, + 1322, 798, 1208, + 1293, 838, 1180, + 1250, 887, 1139, + 1187, 945, 1077, + 1084, 1013, 978, + 897, 1090, 801, + 377, 1176, 337, + 0, 1270, 0, + 0, 1372, 0, + 0, 1480, 0, + 0, 1593, 0, + 0, 1711, 0, + 0, 1831, 0, + 0, 1955, 0, + 0, 2080, 0, + 0, 2208, 0, + 0, 2336, 0, + 0, 2465, 0, + 0, 2595, 0, + 0, 2726, 0, + 0, 2857, 0, + 0, 2988, 0, + 0, 3119, 0, + 0, 3251, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1531, 745, 1371, + 1527, 756, 1367, + 1521, 770, 1361, + 1513, 788, 1352, + 1503, 812, 1341, + 1488, 841, 1325, + 1468, 878, 1303, + 1440, 923, 1272, + 1399, 977, 1227, + 1337, 1040, 1158, + 1239, 1113, 1047, + 1064, 1195, 835, + 609, 1286, 120, + 0, 1385, 0, + 0, 1490, 0, + 0, 1601, 0, + 0, 1717, 0, + 0, 1836, 0, + 0, 1958, 0, + 0, 2083, 0, + 0, 2210, 0, + 0, 2337, 0, + 0, 2466, 0, + 0, 2596, 0, + 0, 2726, 0, + 0, 2857, 0, + 0, 2988, 0, + 0, 3119, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3514, 0, + 0, 3646, 0, + 1675, 809, 1481, + 1672, 818, 1478, + 1668, 831, 1473, + 1662, 847, 1466, + 1655, 867, 1458, + 1644, 894, 1445, + 1630, 927, 1429, + 1610, 967, 1405, + 1582, 1016, 1372, + 1542, 1075, 1323, + 1483, 1143, 1249, + 1388, 1220, 1125, + 1220, 1307, 878, + 804, 1401, 0, + 0, 1503, 0, + 0, 1611, 0, + 0, 1725, 0, + 0, 1842, 0, + 0, 1963, 0, + 0, 2087, 0, + 0, 2212, 0, + 0, 2340, 0, + 0, 2468, 0, + 0, 2597, 0, + 0, 2727, 0, + 0, 2858, 0, + 0, 2989, 0, + 0, 3120, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3646, 0, + 1816, 882, 1596, + 1813, 890, 1593, + 1810, 901, 1590, + 1806, 915, 1585, + 1801, 933, 1578, + 1793, 955, 1569, + 1783, 984, 1556, + 1769, 1020, 1538, + 1750, 1064, 1514, + 1722, 1117, 1478, + 1683, 1179, 1427, + 1625, 1251, 1347, + 1532, 1333, 1212, + 1369, 1422, 929, + 978, 1520, 0, + 0, 1625, 0, + 0, 1735, 0, + 0, 1850, 0, + 0, 1969, 0, + 0, 2092, 0, + 0, 2216, 0, + 0, 2342, 0, + 0, 2470, 0, + 0, 2599, 0, + 0, 2728, 0, + 0, 2859, 0, + 0, 2989, 0, + 0, 3120, 0, + 0, 3252, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3647, 0, + 1954, 965, 1715, + 1952, 972, 1713, + 1950, 981, 1710, + 1947, 992, 1706, + 1943, 1007, 1701, + 1938, 1027, 1694, + 1930, 1052, 1684, + 1920, 1083, 1671, + 1906, 1121, 1653, + 1887, 1168, 1627, + 1860, 1224, 1590, + 1821, 1290, 1536, + 1764, 1365, 1452, + 1673, 1449, 1307, + 1514, 1542, 989, + 1139, 1642, 0, + 0, 1749, 0, + 0, 1861, 0, + 0, 1978, 0, + 0, 2098, 0, + 0, 2221, 0, + 0, 2346, 0, + 0, 2473, 0, + 0, 2601, 0, + 0, 2730, 0, + 0, 2860, 0, + 0, 2990, 0, + 0, 3121, 0, + 0, 3252, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3647, 0, + 2091, 1056, 1837, + 2090, 1062, 1835, + 2088, 1069, 1833, + 2086, 1079, 1830, + 2083, 1091, 1826, + 2079, 1108, 1821, + 2073, 1129, 1813, + 2066, 1155, 1803, + 2056, 1188, 1790, + 2042, 1229, 1771, + 2023, 1278, 1745, + 1997, 1337, 1707, + 1958, 1405, 1650, + 1901, 1483, 1562, + 1812, 1570, 1409, + 1655, 1664, 1059, + 1292, 1767, 0, + 0, 1875, 0, + 0, 1988, 0, + 0, 2106, 0, + 0, 2227, 0, + 0, 2351, 0, + 0, 2476, 0, + 0, 2604, 0, + 0, 2732, 0, + 0, 2861, 0, + 0, 2991, 0, + 0, 3122, 0, + 0, 3253, 0, + 0, 3384, 0, + 0, 3515, 0, + 0, 3647, 0, + 2227, 1156, 1961, + 2226, 1160, 1960, + 2224, 1166, 1958, + 2223, 1174, 1956, + 2221, 1184, 1953, + 2218, 1197, 1949, + 2214, 1214, 1943, + 2208, 1236, 1936, + 2201, 1264, 1926, + 2191, 1299, 1912, + 2177, 1342, 1893, + 2158, 1393, 1866, + 2132, 1454, 1827, + 2094, 1524, 1769, + 2037, 1604, 1678, + 1948, 1693, 1517, + 1794, 1789, 1139, + 1439, 1893, 0, + 0, 2002, 0, + 0, 2117, 0, + 0, 2235, 0, + 0, 2357, 0, + 0, 2481, 0, + 0, 2607, 0, + 0, 2735, 0, + 0, 2863, 0, + 0, 2993, 0, + 0, 3123, 0, + 0, 3254, 0, + 0, 3385, 0, + 0, 3516, 0, + 0, 3647, 0, + 2361, 1261, 2087, + 2361, 1265, 2086, + 2360, 1270, 2085, + 2358, 1276, 2083, + 2357, 1284, 2081, + 2355, 1295, 2078, + 2352, 1309, 2074, + 2348, 1327, 2068, + 2342, 1349, 2061, + 2335, 1378, 2050, + 2325, 1415, 2036, + 2312, 1459, 2017, + 2293, 1512, 1989, + 2266, 1574, 1949, + 2228, 1646, 1890, + 2172, 1728, 1797, + 2084, 1818, 1631, + 1931, 1916, 1227, + 1581, 2021, 0, + 0, 2131, 0, + 0, 2246, 0, + 0, 2365, 0, + 0, 2488, 0, + 0, 2612, 0, + 0, 2738, 0, + 0, 2866, 0, + 0, 2995, 0, + 0, 3125, 0, + 0, 3255, 0, + 0, 3386, 0, + 0, 3517, 0, + 0, 3648, 0, + 2495, 1373, 2215, + 2495, 1376, 2214, + 2494, 1379, 2213, + 2493, 1384, 2212, + 2492, 1391, 2210, + 2490, 1399, 2208, + 2488, 1410, 2205, + 2485, 1424, 2201, + 2481, 1443, 2195, + 2476, 1467, 2187, + 2469, 1497, 2177, + 2459, 1534, 2163, + 2445, 1579, 2143, + 2427, 1634, 2115, + 2400, 1698, 2074, + 2362, 1771, 2014, + 2306, 1854, 1919, + 2219, 1945, 1749, + 2066, 2044, 1323, + 1721, 2149, 0, + 0, 2261, 0, + 0, 2376, 0, + 0, 2496, 0, + 0, 2619, 0, + 0, 2743, 0, + 0, 2870, 0, + 0, 2998, 0, + 0, 3127, 0, + 0, 3256, 0, + 0, 3387, 0, + 0, 3517, 0, + 0, 3649, 0, + 2629, 1489, 2343, + 2628, 1491, 2343, + 2628, 1494, 2342, + 2627, 1497, 2341, + 2626, 1503, 2340, + 2625, 1509, 2338, + 2623, 1518, 2336, + 2621, 1529, 2333, + 2618, 1544, 2329, + 2614, 1563, 2323, + 2609, 1588, 2315, + 2602, 1618, 2305, + 2592, 1656, 2290, + 2579, 1703, 2270, + 2560, 1758, 2242, + 2534, 1823, 2201, + 2496, 1897, 2140, + 2440, 1981, 2043, + 2353, 2073, 1870, + 2201, 2173, 1427, + 1859, 2279, 0, + 0, 2391, 0, + 0, 2507, 0, + 0, 2627, 0, + 0, 2750, 0, + 0, 2875, 0, + 0, 3001, 0, + 0, 3129, 0, + 0, 3258, 0, + 0, 3388, 0, + 0, 3519, 0, + 0, 3649, 0, + 2762, 1608, 2473, + 2762, 1610, 2473, + 2761, 1612, 2472, + 2761, 1615, 2471, + 2760, 1619, 2470, + 2759, 1624, 2469, + 2758, 1631, 2467, + 2756, 1640, 2465, + 2754, 1652, 2462, + 2751, 1667, 2458, + 2747, 1686, 2452, + 2742, 1711, 2444, + 2735, 1742, 2434, + 2725, 1781, 2419, + 2712, 1828, 2399, + 2693, 1884, 2370, + 2667, 1950, 2329, + 2629, 2025, 2268, + 2573, 2109, 2170, + 2486, 2202, 1993, + 2335, 2302, 1536, + 1996, 2409, 0, + 0, 2521, 0, + 0, 2638, 0, + 0, 2758, 0, + 0, 2881, 0, + 0, 3006, 0, + 0, 3133, 0, + 0, 3261, 0, + 0, 3390, 0, + 0, 3520, 0, + 0, 3651, 0, + 2895, 1731, 2603, + 2895, 1732, 2603, + 2894, 1734, 2602, + 2894, 1736, 2602, + 2893, 1739, 2601, + 2893, 1743, 2600, + 2892, 1748, 2599, + 2891, 1755, 2597, + 2889, 1764, 2595, + 2887, 1776, 2592, + 2884, 1791, 2587, + 2880, 1811, 2582, + 2875, 1836, 2574, + 2868, 1868, 2563, + 2858, 1907, 2549, + 2844, 1955, 2528, + 2826, 2012, 2500, + 2800, 2078, 2458, + 2762, 2154, 2396, + 2706, 2239, 2298, + 2619, 2332, 2119, + 2469, 2433, 1651, + 2131, 2540, 0, + 0, 2652, 0, + 0, 2769, 0, + 0, 2890, 0, + 0, 3013, 0, + 0, 3138, 0, + 0, 3265, 0, + 0, 3393, 0, + 0, 3522, 0, + 0, 3652, 0, + 3028, 1856, 2734, + 3027, 1857, 2734, + 3027, 1858, 2733, + 3027, 1860, 2733, + 3027, 1862, 2732, + 3026, 1865, 2732, + 3025, 1869, 2731, + 3024, 1874, 2729, + 3023, 1881, 2728, + 3022, 1890, 2725, + 3019, 1902, 2722, + 3017, 1918, 2718, + 3013, 1938, 2712, + 3007, 1964, 2704, + 3000, 1996, 2694, + 2990, 2035, 2679, + 2977, 2083, 2658, + 2958, 2140, 2630, + 2932, 2207, 2588, + 2895, 2283, 2526, + 2839, 2369, 2426, + 2752, 2462, 2246, + 2602, 2563, 1769, + 2265, 2671, 0, + 0, 2784, 0, + 0, 2901, 0, + 0, 3021, 0, + 0, 3144, 0, + 0, 3270, 0, + 0, 3397, 0, + 0, 3525, 0, + 0, 3654, 0, + 3160, 1982, 2865, + 3160, 1983, 2865, + 3160, 1984, 2864, + 3160, 1985, 2864, + 3159, 1987, 2864, + 3159, 1989, 2863, + 3158, 1992, 2862, + 3158, 1996, 2861, + 3157, 2002, 2860, + 3156, 2009, 2858, + 3154, 2018, 2856, + 3152, 2030, 2853, + 3149, 2046, 2849, + 3145, 2066, 2843, + 3140, 2092, 2835, + 3133, 2124, 2824, + 3123, 2164, 2810, + 3109, 2212, 2789, + 3091, 2270, 2760, + 3065, 2337, 2719, + 3027, 2414, 2656, + 2972, 2499, 2556, + 2885, 2593, 2375, + 2735, 2695, 1890, + 2399, 2802, 0, + 0, 2915, 0, + 0, 3032, 0, + 0, 3153, 0, + 0, 3276, 0, + 0, 3402, 0, + 0, 3529, 0, + 0, 3657, 0, + 3292, 2110, 2996, + 3292, 2111, 2996, + 3292, 2111, 2996, + 3292, 2112, 2996, + 3292, 2114, 2995, + 3292, 2116, 2995, + 3291, 2118, 2994, + 3291, 2121, 2994, + 3290, 2125, 2993, + 3289, 2130, 2991, + 3288, 2138, 2990, + 3286, 2147, 2987, + 3284, 2159, 2984, + 3281, 2175, 2980, + 3277, 2195, 2974, + 3272, 2221, 2966, + 3265, 2254, 2955, + 3255, 2294, 2941, + 3242, 2342, 2920, + 3223, 2400, 2891, + 3197, 2467, 2849, + 3160, 2544, 2787, + 3104, 2630, 2686, + 3018, 2724, 2504, + 2868, 2826, 2015, + 2533, 2934, 0, + 0, 3047, 0, + 0, 3164, 0, + 0, 3285, 0, + 0, 3408, 0, + 0, 3534, 0, + 0, 3661, 0, + 3425, 2239, 3128, + 3425, 2240, 3127, + 3425, 2240, 3127, + 3425, 2241, 3127, + 3424, 2242, 3127, + 3424, 2243, 3127, + 3424, 2245, 3126, + 3424, 2247, 3126, + 3423, 2250, 3125, + 3422, 2254, 3124, + 3421, 2260, 3123, + 3420, 2267, 3121, + 3419, 2276, 3119, + 3417, 2289, 3115, + 3414, 2305, 3111, + 3410, 2325, 3105, + 3404, 2351, 3097, + 3397, 2384, 3087, + 3387, 2424, 3072, + 3374, 2473, 3051, + 3355, 2531, 3022, + 3329, 2598, 2980, + 3292, 2675, 2918, + 3237, 2761, 2817, + 3150, 2856, 2634, + 3000, 2957, 2141, + 2666, 3065, 0, + 0, 3178, 0, + 0, 3296, 0, + 0, 3417, 0, + 0, 3540, 0, + 0, 3666, 0, + 3557, 2369, 3259, + 3557, 2369, 3259, + 3557, 2370, 3259, + 3557, 2370, 3259, + 3557, 2371, 3259, + 3557, 2372, 3259, + 3556, 2373, 3258, + 3556, 2375, 3258, + 3556, 2377, 3257, + 3555, 2380, 3257, + 3555, 2385, 3256, + 3554, 2390, 3254, + 3553, 2397, 3252, + 3551, 2407, 3250, + 3549, 2419, 3247, + 3546, 2435, 3243, + 3542, 2456, 3237, + 3537, 2482, 3229, + 3529, 2514, 3218, + 3520, 2555, 3203, + 3506, 2604, 3183, + 3488, 2662, 3154, + 3462, 2729, 3112, + 3424, 2807, 3049, + 3369, 2893, 2948, + 3282, 2987, 2765, + 3133, 3089, 2268, + 2799, 3197, 0, + 0, 3310, 0, + 0, 3428, 0, + 0, 3549, 0, + 0, 3672, 0, + 3689, 2499, 3391, + 3689, 2499, 3391, + 3689, 2500, 3391, + 3689, 2500, 3391, + 3689, 2501, 3391, + 3689, 2501, 3390, + 3689, 2502, 3390, + 3689, 2504, 3390, + 3688, 2506, 3390, + 3688, 2508, 3389, + 3687, 2511, 3388, + 3687, 2515, 3387, + 3686, 2521, 3386, + 3685, 2528, 3384, + 3683, 2537, 3382, + 3681, 2550, 3379, + 3678, 2566, 3374, + 3674, 2586, 3369, + 3669, 2613, 3361, + 3662, 2645, 3350, + 3652, 2686, 3335, + 3639, 2735, 3314, + 3620, 2793, 3285, + 3594, 2861, 3243, + 3556, 2938, 3180, + 3501, 3024, 3079, + 3415, 3119, 2896, + 3265, 3221, 2397, + 2931, 3329, 0, + 0, 3442, 0, + 0, 3560, 0, + 0, 3681, 0, + 3822, 2630, 3523, + 3822, 2630, 3523, + 3821, 2630, 3523, + 3821, 2631, 3523, + 3821, 2631, 3523, + 3821, 2632, 3522, + 3821, 2632, 3522, + 3821, 2633, 3522, + 3821, 2635, 3522, + 3821, 2637, 3521, + 3820, 2639, 3521, + 3820, 2642, 3520, + 3819, 2646, 3519, + 3818, 2652, 3518, + 3817, 2659, 3516, + 3815, 2668, 3514, + 3813, 2681, 3510, + 3810, 2697, 3506, + 3806, 2717, 3500, + 3801, 2744, 3492, + 3794, 2777, 3482, + 3784, 2817, 3467, + 3771, 2866, 3446, + 3752, 2925, 3417, + 3726, 2992, 3375, + 3689, 3070, 3312, + 3633, 3156, 3211, + 3547, 3251, 3027, + 3398, 3353, 2526, + 3064, 3461, 0, + 0, 3574, 0, + 0, 3692, 0, + 3954, 2761, 3655, + 3954, 2761, 3655, + 3954, 2761, 3655, + 3954, 2762, 3655, + 3954, 2762, 3655, + 3954, 2762, 3654, + 3953, 2763, 3654, + 3953, 2764, 3654, + 3953, 2765, 3654, + 3953, 2766, 3654, + 3953, 2768, 3653, + 3952, 2770, 3653, + 3952, 2773, 3652, + 3951, 2777, 3651, + 3950, 2783, 3650, + 3949, 2790, 3648, + 3947, 2800, 3645, + 3945, 2812, 3642, + 3942, 2828, 3638, + 3938, 2849, 3632, + 3933, 2875, 3624, + 3926, 2908, 3614, + 3916, 2949, 3599, + 3903, 2998, 3578, + 3884, 3056, 3549, + 3858, 3124, 3507, + 3821, 3202, 3444, + 3766, 3288, 3343, + 3679, 3383, 3158, + 3530, 3485, 2656, + 3196, 3593, 0, + 0, 3706, 0, + 4086, 2892, 3787, + 4086, 2893, 3787, + 4086, 2893, 3787, + 4086, 2893, 3787, + 4086, 2893, 3787, + 4086, 2893, 3786, + 4086, 2894, 3786, + 4086, 2894, 3786, + 4085, 2895, 3786, + 4085, 2896, 3786, + 4085, 2897, 3786, + 4085, 2899, 3785, + 4084, 2902, 3785, + 4084, 2905, 3784, + 4083, 2909, 3783, + 4082, 2914, 3782, + 4081, 2922, 3780, + 4080, 2931, 3777, + 4077, 2944, 3774, + 4075, 2960, 3770, + 4071, 2980, 3764, + 4065, 3007, 3756, + 4058, 3040, 3745, + 4048, 3080, 3731, + 4035, 3130, 3710, + 4016, 3188, 3681, + 3990, 3256, 3639, + 3953, 3333, 3575, + 3898, 3420, 3474, + 3811, 3515, 3290, + 3662, 3617, 2787, + 3328, 3725, 0, + 4095, 3024, 3919, + 4095, 3024, 3919, + 4095, 3024, 3919, + 4095, 3024, 3919, + 4095, 3024, 3919, + 4095, 3025, 3919, + 4095, 3025, 3918, + 4095, 3025, 3918, + 4095, 3026, 3918, + 4095, 3027, 3918, + 4095, 3028, 3918, + 4095, 3029, 3918, + 4095, 3031, 3917, + 4095, 3033, 3917, + 4095, 3036, 3916, + 4095, 3040, 3915, + 4095, 3046, 3914, + 4095, 3053, 3912, + 4095, 3063, 3909, + 4095, 3075, 3906, + 4095, 3091, 3902, + 4095, 3112, 3896, + 4095, 3138, 3888, + 4095, 3171, 3877, + 4095, 3212, 3863, + 4095, 3261, 3842, + 4095, 3320, 3813, + 4095, 3388, 3771, + 4085, 3465, 3707, + 4030, 3552, 3606, + 3943, 3647, 3422, + 3794, 3749, 2918, + 4095, 3156, 4051, + 4095, 3156, 4051, + 4095, 3156, 4051, + 4095, 3156, 4051, + 4095, 3156, 4051, + 4095, 3156, 4051, + 4095, 3156, 4051, + 4095, 3157, 4050, + 4095, 3157, 4050, + 4095, 3158, 4050, + 4095, 3158, 4050, + 4095, 3159, 4050, + 4095, 3161, 4050, + 4095, 3163, 4049, + 4095, 3165, 4049, + 4095, 3168, 4048, + 4095, 3172, 4047, + 4095, 3178, 4046, + 4095, 3185, 4044, + 4095, 3195, 4041, + 4095, 3207, 4038, + 4095, 3223, 4034, + 4095, 3244, 4028, + 4095, 3270, 4020, + 4095, 3303, 4009, + 4095, 3344, 3995, + 4095, 3393, 3974, + 4095, 3452, 3945, + 4095, 3520, 3903, + 4095, 3597, 3839, + 4095, 3684, 3738, + 4076, 3779, 3553, + 0, 606, 834, + 0, 621, 819, + 0, 640, 798, + 0, 664, 769, + 0, 695, 726, + 0, 733, 662, + 0, 779, 559, + 0, 834, 370, + 0, 899, 0, + 0, 973, 0, + 0, 1057, 0, + 0, 1149, 0, + 0, 1248, 0, + 0, 1355, 0, + 0, 1466, 0, + 0, 1583, 0, + 0, 1702, 0, + 0, 1825, 0, + 0, 1950, 0, + 0, 2077, 0, + 0, 2205, 0, + 0, 2334, 0, + 0, 2464, 0, + 0, 2594, 0, + 0, 2725, 0, + 0, 2856, 0, + 0, 2987, 0, + 0, 3119, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 0, 611, 856, + 0, 626, 842, + 0, 645, 822, + 0, 669, 794, + 0, 699, 753, + 0, 737, 693, + 0, 782, 598, + 0, 837, 427, + 0, 902, 2, + 0, 976, 0, + 0, 1059, 0, + 0, 1150, 0, + 0, 1250, 0, + 0, 1356, 0, + 0, 1467, 0, + 0, 1583, 0, + 0, 1703, 0, + 0, 1825, 0, + 0, 1950, 0, + 0, 2077, 0, + 0, 2205, 0, + 0, 2334, 0, + 0, 2464, 0, + 0, 2594, 0, + 0, 2725, 0, + 0, 2856, 0, + 0, 2987, 0, + 0, 3119, 0, + 0, 3251, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 0, 618, 883, + 0, 632, 870, + 0, 651, 851, + 0, 675, 825, + 0, 705, 788, + 0, 742, 732, + 0, 787, 645, + 0, 841, 495, + 0, 905, 157, + 0, 979, 0, + 0, 1061, 0, + 0, 1152, 0, + 0, 1251, 0, + 0, 1357, 0, + 0, 1468, 0, + 0, 1584, 0, + 0, 1703, 0, + 0, 1826, 0, + 0, 1951, 0, + 0, 2077, 0, + 0, 2205, 0, + 0, 2334, 0, + 0, 2464, 0, + 0, 2594, 0, + 0, 2725, 0, + 0, 2856, 0, + 0, 2987, 0, + 0, 3119, 0, + 0, 3251, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 0, 627, 918, + 0, 641, 905, + 0, 659, 888, + 0, 682, 864, + 0, 712, 829, + 0, 748, 779, + 0, 793, 702, + 0, 847, 572, + 0, 910, 306, + 0, 983, 0, + 0, 1064, 0, + 0, 1155, 0, + 0, 1253, 0, + 0, 1359, 0, + 0, 1469, 0, + 0, 1585, 0, + 0, 1704, 0, + 0, 1827, 0, + 0, 1951, 0, + 0, 2078, 0, + 0, 2205, 0, + 0, 2334, 0, + 0, 2464, 0, + 0, 2594, 0, + 0, 2725, 0, + 0, 2856, 0, + 0, 2987, 0, + 0, 3119, 0, + 0, 3251, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 271, 638, 960, + 198, 652, 948, + 78, 670, 933, + 0, 693, 911, + 0, 721, 880, + 0, 757, 835, + 0, 801, 768, + 0, 854, 657, + 0, 916, 450, + 0, 988, 0, + 0, 1069, 0, + 0, 1159, 0, + 0, 1256, 0, + 0, 1361, 0, + 0, 1471, 0, + 0, 1586, 0, + 0, 1705, 0, + 0, 1827, 0, + 0, 1952, 0, + 0, 2078, 0, + 0, 2206, 0, + 0, 2335, 0, + 0, 2464, 0, + 0, 2594, 0, + 0, 2725, 0, + 0, 2856, 0, + 0, 2987, 0, + 0, 3119, 0, + 0, 3251, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 595, 653, 1011, + 561, 667, 1000, + 511, 684, 986, + 434, 706, 967, + 305, 734, 940, + 43, 769, 901, + 0, 812, 843, + 0, 863, 752, + 0, 924, 591, + 0, 995, 210, + 0, 1075, 0, + 0, 1164, 0, + 0, 1260, 0, + 0, 1364, 0, + 0, 1474, 0, + 0, 1588, 0, + 0, 1707, 0, + 0, 1829, 0, + 0, 1953, 0, + 0, 2079, 0, + 0, 2206, 0, + 0, 2335, 0, + 0, 2464, 0, + 0, 2595, 0, + 0, 2725, 0, + 0, 2856, 0, + 0, 2988, 0, + 0, 3119, 0, + 0, 3251, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 832, 672, 1071, + 812, 685, 1062, + 784, 702, 1050, + 743, 723, 1033, + 682, 750, 1010, + 586, 784, 976, + 413, 825, 928, + 0, 875, 853, + 0, 935, 729, + 0, 1004, 483, + 0, 1082, 0, + 0, 1170, 0, + 0, 1265, 0, + 0, 1368, 0, + 0, 1477, 0, + 0, 1591, 0, + 0, 1709, 0, + 0, 1830, 0, + 0, 1954, 0, + 0, 2080, 0, + 0, 2207, 0, + 0, 2335, 0, + 0, 2465, 0, + 0, 2595, 0, + 0, 2725, 0, + 0, 2856, 0, + 0, 2988, 0, + 0, 3119, 0, + 0, 3251, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1029, 697, 1140, + 1016, 709, 1133, + 998, 725, 1122, + 973, 745, 1108, + 938, 771, 1089, + 885, 803, 1061, + 804, 843, 1021, + 666, 891, 961, + 375, 949, 866, + 0, 1016, 698, + 0, 1093, 282, + 0, 1178, 0, + 0, 1272, 0, + 0, 1374, 0, + 0, 1481, 0, + 0, 1594, 0, + 0, 1711, 0, + 0, 1832, 0, + 0, 1955, 0, + 0, 2081, 0, + 0, 2208, 0, + 0, 2336, 0, + 0, 2465, 0, + 0, 2595, 0, + 0, 2726, 0, + 0, 2857, 0, + 0, 2988, 0, + 0, 3119, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3514, 0, + 0, 3646, 0, + 1204, 728, 1220, + 1195, 739, 1213, + 1183, 754, 1205, + 1167, 773, 1193, + 1144, 797, 1176, + 1111, 828, 1154, + 1064, 866, 1121, + 991, 912, 1074, + 872, 967, 1002, + 637, 1032, 883, + 0, 1106, 652, + 0, 1189, 0, + 0, 1281, 0, + 0, 1381, 0, + 0, 1487, 0, + 0, 1599, 0, + 0, 1715, 0, + 0, 1835, 0, + 0, 1957, 0, + 0, 2082, 0, + 0, 2209, 0, + 0, 2337, 0, + 0, 2466, 0, + 0, 2596, 0, + 0, 2726, 0, + 0, 2857, 0, + 0, 2988, 0, + 0, 3119, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3514, 0, + 0, 3646, 0, + 1366, 766, 1308, + 1360, 777, 1302, + 1352, 790, 1295, + 1340, 808, 1286, + 1325, 830, 1272, + 1303, 859, 1254, + 1272, 894, 1228, + 1228, 938, 1191, + 1161, 990, 1137, + 1052, 1052, 1052, + 847, 1123, 905, + 195, 1203, 583, + 0, 1293, 0, + 0, 1390, 0, + 0, 1494, 0, + 0, 1604, 0, + 0, 1719, 0, + 0, 1838, 0, + 0, 1960, 0, + 0, 2084, 0, + 0, 2210, 0, + 0, 2338, 0, + 0, 2467, 0, + 0, 2596, 0, + 0, 2727, 0, + 0, 2857, 0, + 0, 2988, 0, + 0, 3120, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3514, 0, + 0, 3646, 0, + 1519, 813, 1404, + 1515, 822, 1399, + 1509, 834, 1394, + 1501, 850, 1386, + 1490, 871, 1375, + 1475, 897, 1361, + 1454, 930, 1341, + 1425, 970, 1312, + 1383, 1019, 1271, + 1319, 1077, 1209, + 1216, 1145, 1110, + 1029, 1222, 933, + 509, 1308, 469, + 0, 1402, 0, + 0, 1504, 0, + 0, 1612, 0, + 0, 1725, 0, + 0, 1843, 0, + 0, 1963, 0, + 0, 2087, 0, + 0, 2213, 0, + 0, 2340, 0, + 0, 2468, 0, + 0, 2597, 0, + 0, 2727, 0, + 0, 2858, 0, + 0, 2989, 0, + 0, 3120, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3646, 0, + 1666, 868, 1507, + 1663, 877, 1504, + 1659, 888, 1499, + 1653, 902, 1493, + 1645, 920, 1484, + 1635, 944, 1473, + 1620, 973, 1457, + 1600, 1010, 1435, + 1572, 1055, 1404, + 1531, 1109, 1359, + 1469, 1172, 1290, + 1372, 1245, 1179, + 1196, 1327, 967, + 741, 1418, 252, + 0, 1517, 0, + 0, 1622, 0, + 0, 1733, 0, + 0, 1849, 0, + 0, 1968, 0, + 0, 2091, 0, + 0, 2215, 0, + 0, 2342, 0, + 0, 2470, 0, + 0, 2598, 0, + 0, 2728, 0, + 0, 2858, 0, + 0, 2989, 0, + 0, 3120, 0, + 0, 3252, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3647, 0, + 1809, 933, 1616, + 1807, 941, 1613, + 1804, 950, 1610, + 1800, 963, 1605, + 1794, 979, 1599, + 1787, 999, 1590, + 1776, 1026, 1578, + 1762, 1059, 1561, + 1742, 1099, 1537, + 1715, 1148, 1504, + 1675, 1207, 1455, + 1615, 1275, 1381, + 1520, 1352, 1257, + 1352, 1439, 1010, + 936, 1533, 0, + 0, 1635, 0, + 0, 1743, 0, + 0, 1857, 0, + 0, 1974, 0, + 0, 2095, 0, + 0, 2219, 0, + 0, 2344, 0, + 0, 2472, 0, + 0, 2600, 0, + 0, 2729, 0, + 0, 2859, 0, + 0, 2990, 0, + 0, 3121, 0, + 0, 3252, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3647, 0, + 1949, 1008, 1730, + 1948, 1014, 1728, + 1946, 1022, 1725, + 1943, 1033, 1722, + 1938, 1047, 1717, + 1933, 1065, 1710, + 1925, 1088, 1701, + 1915, 1116, 1688, + 1901, 1152, 1670, + 1882, 1196, 1646, + 1855, 1249, 1610, + 1815, 1312, 1559, + 1757, 1383, 1479, + 1664, 1465, 1344, + 1501, 1555, 1061, + 1110, 1652, 0, + 0, 1757, 0, + 0, 1867, 0, + 0, 1983, 0, + 0, 2102, 0, + 0, 2224, 0, + 0, 2348, 0, + 0, 2474, 0, + 0, 2602, 0, + 0, 2731, 0, + 0, 2860, 0, + 0, 2991, 0, + 0, 3121, 0, + 0, 3252, 0, + 0, 3384, 0, + 0, 3515, 0, + 0, 3647, 0, + 2087, 1092, 1849, + 2086, 1097, 1847, + 2085, 1104, 1845, + 2082, 1113, 1842, + 2079, 1124, 1838, + 2075, 1140, 1833, + 2070, 1159, 1826, + 2062, 1184, 1816, + 2052, 1215, 1803, + 2039, 1254, 1785, + 2019, 1300, 1759, + 1992, 1357, 1722, + 1954, 1422, 1668, + 1896, 1497, 1584, + 1805, 1581, 1439, + 1646, 1674, 1121, + 1271, 1774, 0, + 0, 1881, 0, + 0, 1993, 0, + 0, 2110, 0, + 0, 2230, 0, + 0, 2353, 0, + 0, 2478, 0, + 0, 2605, 0, + 0, 2733, 0, + 0, 2862, 0, + 0, 2992, 0, + 0, 3122, 0, + 0, 3253, 0, + 0, 3384, 0, + 0, 3516, 0, + 0, 3647, 0, + 2224, 1184, 1970, + 2223, 1189, 1969, + 2222, 1194, 1967, + 2220, 1201, 1965, + 2218, 1211, 1962, + 2215, 1224, 1958, + 2211, 1240, 1953, + 2206, 1261, 1945, + 2198, 1287, 1936, + 2188, 1320, 1922, + 2175, 1361, 1903, + 2156, 1410, 1877, + 2129, 1469, 1839, + 2090, 1537, 1782, + 2033, 1615, 1694, + 1944, 1702, 1541, + 1787, 1797, 1191, + 1424, 1899, 0, + 0, 2007, 0, + 0, 2121, 0, + 0, 2238, 0, + 0, 2359, 0, + 0, 2483, 0, + 0, 2608, 0, + 0, 2736, 0, + 0, 2864, 0, + 0, 2993, 0, + 0, 3123, 0, + 0, 3254, 0, + 0, 3385, 0, + 0, 3516, 0, + 0, 3648, 0, + 2359, 1284, 2094, + 2359, 1288, 2093, + 2358, 1292, 2092, + 2357, 1298, 2090, + 2355, 1306, 2088, + 2353, 1316, 2085, + 2350, 1329, 2081, + 2346, 1346, 2075, + 2340, 1368, 2068, + 2333, 1396, 2058, + 2323, 1431, 2044, + 2309, 1474, 2025, + 2291, 1525, 1998, + 2264, 1586, 1959, + 2226, 1656, 1901, + 2169, 1736, 1810, + 2080, 1825, 1649, + 1926, 1921, 1271, + 1571, 2025, 0, + 0, 2135, 0, + 0, 2249, 0, + 0, 2368, 0, + 0, 2489, 0, + 0, 2613, 0, + 0, 2739, 0, + 0, 2867, 0, + 0, 2995, 0, + 0, 3125, 0, + 0, 3255, 0, + 0, 3386, 0, + 0, 3517, 0, + 0, 3648, 0, + 2494, 1391, 2220, + 2493, 1393, 2219, + 2493, 1397, 2218, + 2492, 1402, 2217, + 2491, 1408, 2215, + 2489, 1416, 2213, + 2487, 1427, 2210, + 2484, 1441, 2206, + 2480, 1459, 2200, + 2474, 1482, 2193, + 2467, 1511, 2183, + 2457, 1547, 2168, + 2444, 1591, 2149, + 2425, 1644, 2121, + 2398, 1706, 2082, + 2361, 1779, 2022, + 2304, 1860, 1929, + 2216, 1950, 1763, + 2063, 2048, 1359, + 1714, 2153, 0, + 0, 2263, 0, + 0, 2378, 0, + 0, 2498, 0, + 0, 2620, 0, + 0, 2744, 0, + 0, 2871, 0, + 0, 2998, 0, + 0, 3127, 0, + 0, 3257, 0, + 0, 3387, 0, + 0, 3518, 0, + 0, 3649, 0, + 2628, 1503, 2347, + 2627, 1505, 2347, + 2627, 1508, 2346, + 2626, 1511, 2345, + 2625, 1516, 2344, + 2624, 1523, 2342, + 2622, 1531, 2340, + 2620, 1542, 2337, + 2617, 1557, 2333, + 2613, 1575, 2327, + 2608, 1599, 2319, + 2601, 1629, 2309, + 2591, 1666, 2295, + 2577, 1711, 2275, + 2559, 1766, 2247, + 2532, 1830, 2207, + 2495, 1903, 2146, + 2438, 1986, 2051, + 2351, 2077, 1881, + 2199, 2176, 1456, + 1853, 2281, 0, + 0, 2393, 0, + 0, 2509, 0, + 0, 2628, 0, + 0, 2751, 0, + 0, 2875, 0, + 0, 3002, 0, + 0, 3130, 0, + 0, 3259, 0, + 0, 3388, 0, + 0, 3519, 0, + 0, 3650, 0, + 2761, 1619, 2476, + 2761, 1621, 2476, + 2760, 1623, 2475, + 2760, 1626, 2474, + 2759, 1630, 2473, + 2758, 1635, 2472, + 2757, 1641, 2470, + 2756, 1650, 2468, + 2753, 1661, 2465, + 2750, 1676, 2461, + 2747, 1695, 2455, + 2741, 1720, 2447, + 2734, 1750, 2437, + 2724, 1788, 2422, + 2711, 1835, 2402, + 2692, 1890, 2374, + 2666, 1955, 2333, + 2628, 2029, 2272, + 2572, 2113, 2176, + 2485, 2205, 2002, + 2333, 2305, 1559, + 1991, 2411, 0, + 0, 2523, 0, + 0, 2639, 0, + 0, 2759, 0, + 0, 2882, 0, + 0, 3007, 0, + 0, 3134, 0, + 0, 3262, 0, + 0, 3391, 0, + 0, 3520, 0, + 0, 3651, 0, + 2894, 1739, 2605, + 2894, 1740, 2605, + 2894, 1742, 2605, + 2893, 1744, 2604, + 2893, 1747, 2603, + 2892, 1751, 2602, + 2891, 1756, 2601, + 2890, 1763, 2599, + 2888, 1772, 2597, + 2886, 1784, 2594, + 2883, 1799, 2590, + 2879, 1818, 2584, + 2874, 1843, 2576, + 2867, 1874, 2566, + 2857, 1913, 2551, + 2844, 1960, 2531, + 2825, 2016, 2502, + 2799, 2082, 2461, + 2761, 2157, 2400, + 2705, 2241, 2302, + 2618, 2334, 2125, + 2468, 2434, 1668, + 2128, 2541, 0, + 0, 2653, 0, + 0, 2770, 0, + 0, 2890, 0, + 0, 3013, 0, + 0, 3138, 0, + 0, 3265, 0, + 0, 3393, 0, + 0, 3522, 0, + 0, 3652, 0, + 3027, 1862, 2735, + 3027, 1863, 2735, + 3027, 1864, 2735, + 3026, 1866, 2735, + 3026, 1868, 2734, + 3026, 1871, 2733, + 3025, 1875, 2732, + 3024, 1880, 2731, + 3023, 1887, 2729, + 3021, 1896, 2727, + 3019, 1908, 2724, + 3016, 1924, 2720, + 3012, 1943, 2714, + 3007, 1969, 2706, + 3000, 2000, 2695, + 2990, 2039, 2681, + 2976, 2087, 2660, + 2958, 2144, 2632, + 2932, 2210, 2590, + 2894, 2286, 2528, + 2838, 2371, 2430, + 2752, 2464, 2251, + 2601, 2565, 1783, + 2263, 2672, 0, + 0, 2784, 0, + 0, 2901, 0, + 0, 3022, 0, + 0, 3145, 0, + 0, 3270, 0, + 0, 3397, 0, + 0, 3525, 0, + 0, 3654, 0, + 3160, 1987, 2866, + 3160, 1988, 2866, + 3159, 1989, 2866, + 3159, 1990, 2865, + 3159, 1992, 2865, + 3159, 1994, 2864, + 3158, 1997, 2864, + 3157, 2001, 2863, + 3157, 2006, 2861, + 3155, 2013, 2860, + 3154, 2023, 2857, + 3152, 2035, 2854, + 3149, 2050, 2850, + 3145, 2070, 2844, + 3139, 2096, 2836, + 3132, 2128, 2826, + 3122, 2167, 2811, + 3109, 2215, 2791, + 3090, 2272, 2762, + 3064, 2339, 2720, + 3027, 2415, 2658, + 2971, 2501, 2558, + 2884, 2594, 2378, + 2734, 2696, 1901, + 2397, 2803, 0, + 0, 2916, 0, + 0, 3033, 0, + 0, 3153, 0, + 0, 3277, 0, + 0, 3402, 0, + 0, 3529, 0, + 0, 3657, 0, + 3292, 2114, 2997, + 3292, 2114, 2997, + 3292, 2115, 2997, + 3292, 2116, 2997, + 3292, 2117, 2996, + 3291, 2119, 2996, + 3291, 2121, 2995, + 3291, 2124, 2995, + 3290, 2128, 2994, + 3289, 2134, 2992, + 3288, 2141, 2990, + 3286, 2150, 2988, + 3284, 2162, 2985, + 3281, 2178, 2981, + 3277, 2198, 2975, + 3272, 2224, 2967, + 3265, 2256, 2956, + 3255, 2296, 2942, + 3241, 2344, 2921, + 3223, 2402, 2892, + 3197, 2469, 2851, + 3159, 2546, 2788, + 3104, 2631, 2688, + 3017, 2725, 2507, + 2867, 2827, 2023, + 2531, 2934, 0, + 0, 3047, 0, + 0, 3164, 0, + 0, 3285, 0, + 0, 3408, 0, + 0, 3534, 0, + 0, 3661, 0, + 3425, 2242, 3128, + 3425, 2242, 3128, + 3425, 2243, 3128, + 3424, 2244, 3128, + 3424, 2245, 3128, + 3424, 2246, 3127, + 3424, 2248, 3127, + 3423, 2250, 3126, + 3423, 2253, 3126, + 3422, 2257, 3125, + 3421, 2262, 3123, + 3420, 2270, 3122, + 3418, 2279, 3119, + 3416, 2291, 3116, + 3413, 2307, 3112, + 3410, 2327, 3106, + 3404, 2353, 3098, + 3397, 2386, 3087, + 3387, 2426, 3073, + 3374, 2474, 3052, + 3355, 2532, 3023, + 3329, 2600, 2981, + 3292, 2676, 2919, + 3236, 2762, 2818, + 3150, 2856, 2636, + 3000, 2958, 2147, + 2665, 3066, 0, + 0, 3179, 0, + 0, 3296, 0, + 0, 3417, 0, + 0, 3540, 0, + 0, 3666, 0, + 3557, 2371, 3260, + 3557, 2371, 3260, + 3557, 2372, 3260, + 3557, 2372, 3259, + 3557, 2373, 3259, + 3557, 2374, 3259, + 3556, 2375, 3259, + 3556, 2377, 3258, + 3556, 2379, 3258, + 3555, 2382, 3257, + 3554, 2387, 3256, + 3554, 2392, 3255, + 3552, 2399, 3253, + 3551, 2409, 3251, + 3549, 2421, 3247, + 3546, 2437, 3243, + 3542, 2457, 3237, + 3537, 2483, 3230, + 3529, 2516, 3219, + 3520, 2556, 3204, + 3506, 2605, 3183, + 3488, 2663, 3154, + 3461, 2730, 3113, + 3424, 2807, 3050, + 3369, 2894, 2949, + 3282, 2988, 2766, + 3133, 3090, 2273, + 2798, 3197, 0, + 0, 3311, 0, + 0, 3428, 0, + 0, 3549, 0, + 0, 3672, 0, + 3689, 2501, 3391, + 3689, 2501, 3391, + 3689, 2501, 3391, + 3689, 2502, 3391, + 3689, 2502, 3391, + 3689, 2503, 3391, + 3689, 2504, 3391, + 3689, 2505, 3390, + 3688, 2507, 3390, + 3688, 2509, 3389, + 3687, 2513, 3389, + 3687, 2517, 3388, + 3686, 2522, 3386, + 3685, 2529, 3385, + 3683, 2539, 3382, + 3681, 2551, 3379, + 3678, 2567, 3375, + 3674, 2588, 3369, + 3669, 2614, 3361, + 3662, 2646, 3350, + 3652, 2687, 3336, + 3638, 2736, 3315, + 3620, 2794, 3286, + 3594, 2862, 3244, + 3556, 2939, 3181, + 3501, 3025, 3080, + 3414, 3119, 2897, + 3265, 3221, 2400, + 2931, 3329, 0, + 0, 3442, 0, + 0, 3560, 0, + 0, 3681, 0, + 3821, 2631, 3523, + 3821, 2631, 3523, + 3821, 2632, 3523, + 3821, 2632, 3523, + 3821, 2632, 3523, + 3821, 2633, 3523, + 3821, 2634, 3523, + 3821, 2635, 3522, + 3821, 2636, 3522, + 3820, 2638, 3522, + 3820, 2640, 3521, + 3820, 2643, 3520, + 3819, 2647, 3519, + 3818, 2653, 3518, + 3817, 2660, 3516, + 3815, 2669, 3514, + 3813, 2682, 3511, + 3810, 2698, 3506, + 3806, 2718, 3501, + 3801, 2745, 3493, + 3794, 2777, 3482, + 3784, 2818, 3467, + 3771, 2867, 3447, + 3752, 2925, 3418, + 3726, 2993, 3375, + 3689, 3070, 3312, + 3633, 3157, 3211, + 3547, 3251, 3028, + 3397, 3353, 2529, + 3063, 3461, 0, + 0, 3574, 0, + 0, 3692, 0, + 3954, 2762, 3655, + 3954, 2762, 3655, + 3954, 2762, 3655, + 3954, 2762, 3655, + 3954, 2763, 3655, + 3953, 2763, 3655, + 3953, 2764, 3655, + 3953, 2765, 3654, + 3953, 2766, 3654, + 3953, 2767, 3654, + 3953, 2769, 3653, + 3952, 2771, 3653, + 3952, 2774, 3652, + 3951, 2778, 3651, + 3950, 2784, 3650, + 3949, 2791, 3648, + 3947, 2800, 3646, + 3945, 2813, 3643, + 3942, 2829, 3638, + 3938, 2850, 3632, + 3933, 2876, 3625, + 3926, 2909, 3614, + 3916, 2949, 3599, + 3903, 2998, 3578, + 3884, 3057, 3549, + 3858, 3125, 3507, + 3821, 3202, 3444, + 3765, 3288, 3343, + 3679, 3383, 3159, + 3530, 3485, 2658, + 3196, 3593, 0, + 0, 3706, 0, + 4086, 2893, 3787, + 4086, 2893, 3787, + 4086, 2893, 3787, + 4086, 2893, 3787, + 4086, 2894, 3787, + 4086, 2894, 3787, + 4086, 2894, 3787, + 4086, 2895, 3786, + 4085, 2896, 3786, + 4085, 2897, 3786, + 4085, 2898, 3786, + 4085, 2900, 3785, + 4084, 2902, 3785, + 4084, 2905, 3784, + 4083, 2909, 3783, + 4082, 2915, 3782, + 4081, 2922, 3780, + 4080, 2932, 3778, + 4077, 2944, 3774, + 4074, 2960, 3770, + 4071, 2981, 3764, + 4065, 3007, 3756, + 4058, 3040, 3746, + 4048, 3081, 3731, + 4035, 3130, 3710, + 4016, 3188, 3681, + 3990, 3256, 3639, + 3953, 3334, 3576, + 3898, 3420, 3475, + 3811, 3515, 3290, + 3662, 3617, 2788, + 3328, 3725, 0, + 4095, 3024, 3919, + 4095, 3025, 3919, + 4095, 3025, 3919, + 4095, 3025, 3919, + 4095, 3025, 3919, + 4095, 3025, 3919, + 4095, 3025, 3919, + 4095, 3026, 3918, + 4095, 3026, 3918, + 4095, 3027, 3918, + 4095, 3028, 3918, + 4095, 3030, 3918, + 4095, 3031, 3917, + 4095, 3034, 3917, + 4095, 3037, 3916, + 4095, 3041, 3915, + 4095, 3046, 3914, + 4095, 3054, 3912, + 4095, 3063, 3910, + 4095, 3076, 3906, + 4095, 3092, 3902, + 4095, 3113, 3896, + 4095, 3139, 3888, + 4095, 3172, 3878, + 4095, 3212, 3863, + 4095, 3262, 3842, + 4095, 3320, 3813, + 4095, 3388, 3771, + 4085, 3466, 3708, + 4030, 3552, 3606, + 3943, 3647, 3422, + 3794, 3749, 2919, + 4095, 3156, 4051, + 4095, 3156, 4051, + 4095, 3156, 4051, + 4095, 3156, 4051, + 4095, 3156, 4051, + 4095, 3157, 4051, + 4095, 3157, 4051, + 4095, 3157, 4051, + 4095, 3158, 4050, + 4095, 3158, 4050, + 4095, 3159, 4050, + 4095, 3160, 4050, + 4095, 3161, 4050, + 4095, 3163, 4049, + 4095, 3165, 4049, + 4095, 3168, 4048, + 4095, 3173, 4047, + 4095, 3178, 4046, + 4095, 3185, 4044, + 4095, 3195, 4041, + 4095, 3207, 4038, + 4095, 3224, 4034, + 4095, 3244, 4028, + 4095, 3271, 4020, + 4095, 3304, 4009, + 4095, 3344, 3995, + 4095, 3393, 3974, + 4095, 3452, 3945, + 4095, 3520, 3903, + 4095, 3597, 3839, + 4095, 3684, 3738, + 4076, 3779, 3554, + 0, 723, 961, + 0, 734, 949, + 0, 749, 934, + 0, 769, 912, + 0, 793, 881, + 0, 824, 837, + 0, 862, 769, + 0, 908, 660, + 0, 964, 453, + 0, 1029, 0, + 0, 1104, 0, + 0, 1187, 0, + 0, 1280, 0, + 0, 1380, 0, + 0, 1486, 0, + 0, 1598, 0, + 0, 1714, 0, + 0, 1834, 0, + 0, 1957, 0, + 0, 2082, 0, + 0, 2209, 0, + 0, 2337, 0, + 0, 2466, 0, + 0, 2596, 0, + 0, 2726, 0, + 0, 2857, 0, + 0, 2988, 0, + 0, 3119, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3514, 0, + 0, 3646, 0, + 0, 727, 977, + 0, 738, 966, + 0, 753, 951, + 0, 772, 930, + 0, 796, 901, + 0, 827, 858, + 0, 865, 794, + 0, 911, 691, + 0, 966, 502, + 0, 1031, 0, + 0, 1105, 0, + 0, 1189, 0, + 0, 1281, 0, + 0, 1380, 0, + 0, 1487, 0, + 0, 1598, 0, + 0, 1715, 0, + 0, 1835, 0, + 0, 1957, 0, + 0, 2082, 0, + 0, 2209, 0, + 0, 2337, 0, + 0, 2466, 0, + 0, 2596, 0, + 0, 2726, 0, + 0, 2857, 0, + 0, 2988, 0, + 0, 3119, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3514, 0, + 0, 3646, 0, + 0, 732, 998, + 0, 743, 988, + 0, 758, 974, + 0, 777, 954, + 0, 801, 926, + 0, 831, 886, + 0, 869, 825, + 0, 915, 730, + 0, 969, 560, + 0, 1034, 134, + 0, 1108, 0, + 0, 1191, 0, + 0, 1282, 0, + 0, 1382, 0, + 0, 1488, 0, + 0, 1599, 0, + 0, 1715, 0, + 0, 1835, 0, + 0, 1958, 0, + 0, 2082, 0, + 0, 2209, 0, + 0, 2337, 0, + 0, 2466, 0, + 0, 2596, 0, + 0, 2726, 0, + 0, 2857, 0, + 0, 2988, 0, + 0, 3119, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3514, 0, + 0, 3646, 0, + 0, 739, 1025, + 0, 750, 1015, + 0, 764, 1002, + 0, 783, 983, + 0, 807, 957, + 0, 837, 920, + 0, 874, 864, + 0, 919, 777, + 0, 973, 627, + 0, 1037, 289, + 0, 1111, 0, + 0, 1193, 0, + 0, 1284, 0, + 0, 1383, 0, + 0, 1489, 0, + 0, 1600, 0, + 0, 1716, 0, + 0, 1836, 0, + 0, 1958, 0, + 0, 2083, 0, + 0, 2209, 0, + 0, 2337, 0, + 0, 2466, 0, + 0, 2596, 0, + 0, 2726, 0, + 0, 2857, 0, + 0, 2988, 0, + 0, 3119, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3514, 0, + 0, 3646, 0, + 0, 748, 1059, + 0, 759, 1050, + 0, 773, 1037, + 0, 791, 1020, + 0, 815, 996, + 0, 844, 962, + 0, 880, 911, + 0, 925, 834, + 0, 979, 704, + 0, 1042, 438, + 0, 1115, 0, + 0, 1197, 0, + 0, 1287, 0, + 0, 1386, 0, + 0, 1491, 0, + 0, 1602, 0, + 0, 1717, 0, + 0, 1836, 0, + 0, 1959, 0, + 0, 2083, 0, + 0, 2210, 0, + 0, 2338, 0, + 0, 2466, 0, + 0, 2596, 0, + 0, 2726, 0, + 0, 2857, 0, + 0, 2988, 0, + 0, 3119, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3514, 0, + 0, 3646, 0, + 450, 760, 1100, + 403, 770, 1092, + 330, 784, 1080, + 210, 802, 1065, + 0, 825, 1043, + 0, 853, 1012, + 0, 889, 967, + 0, 933, 900, + 0, 986, 790, + 0, 1048, 582, + 0, 1120, 0, + 0, 1201, 0, + 0, 1291, 0, + 0, 1388, 0, + 0, 1493, 0, + 0, 1603, 0, + 0, 1718, 0, + 0, 1837, 0, + 0, 1960, 0, + 0, 2084, 0, + 0, 2210, 0, + 0, 2338, 0, + 0, 2467, 0, + 0, 2596, 0, + 0, 2726, 0, + 0, 2857, 0, + 0, 2988, 0, + 0, 3120, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3514, 0, + 0, 3646, 0, + 751, 775, 1150, + 727, 785, 1143, + 693, 799, 1132, + 643, 816, 1119, + 566, 838, 1099, + 437, 866, 1072, + 175, 901, 1033, + 0, 944, 975, + 0, 995, 884, + 0, 1056, 723, + 0, 1127, 342, + 0, 1207, 0, + 0, 1296, 0, + 0, 1392, 0, + 0, 1496, 0, + 0, 1606, 0, + 0, 1720, 0, + 0, 1839, 0, + 0, 1961, 0, + 0, 2085, 0, + 0, 2211, 0, + 0, 2338, 0, + 0, 2467, 0, + 0, 2597, 0, + 0, 2727, 0, + 0, 2857, 0, + 0, 2988, 0, + 0, 3120, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3514, 0, + 0, 3646, 0, + 978, 795, 1209, + 964, 805, 1203, + 944, 817, 1194, + 916, 834, 1182, + 875, 855, 1165, + 814, 882, 1142, + 718, 916, 1108, + 545, 957, 1060, + 108, 1008, 985, + 0, 1067, 862, + 0, 1136, 615, + 0, 1215, 0, + 0, 1302, 0, + 0, 1397, 0, + 0, 1500, 0, + 0, 1609, 0, + 0, 1723, 0, + 0, 1841, 0, + 0, 1962, 0, + 0, 2086, 0, + 0, 2212, 0, + 0, 2339, 0, + 0, 2468, 0, + 0, 2597, 0, + 0, 2727, 0, + 0, 2858, 0, + 0, 2988, 0, + 0, 3120, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3646, 0, + 1170, 820, 1278, + 1161, 829, 1273, + 1148, 841, 1265, + 1130, 857, 1255, + 1105, 877, 1240, + 1070, 903, 1221, + 1017, 935, 1193, + 936, 975, 1153, + 798, 1023, 1093, + 507, 1081, 998, + 0, 1148, 830, + 0, 1225, 414, + 0, 1310, 0, + 0, 1404, 0, + 0, 1506, 0, + 0, 1613, 0, + 0, 1726, 0, + 0, 1843, 0, + 0, 1964, 0, + 0, 2087, 0, + 0, 2213, 0, + 0, 2340, 0, + 0, 2468, 0, + 0, 2597, 0, + 0, 2727, 0, + 0, 2858, 0, + 0, 2989, 0, + 0, 3120, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3646, 0, + 1343, 851, 1356, + 1336, 860, 1352, + 1327, 871, 1345, + 1316, 886, 1337, + 1299, 905, 1325, + 1276, 929, 1308, + 1244, 960, 1286, + 1196, 998, 1253, + 1123, 1044, 1206, + 1004, 1099, 1134, + 769, 1164, 1015, + 0, 1238, 784, + 0, 1321, 0, + 0, 1413, 0, + 0, 1513, 0, + 0, 1619, 0, + 0, 1731, 0, + 0, 1847, 0, + 0, 1967, 0, + 0, 2089, 0, + 0, 2214, 0, + 0, 2341, 0, + 0, 2469, 0, + 0, 2598, 0, + 0, 2728, 0, + 0, 2858, 0, + 0, 2989, 0, + 0, 3120, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3646, 0, + 1502, 890, 1444, + 1498, 898, 1440, + 1492, 909, 1434, + 1484, 922, 1427, + 1472, 940, 1418, + 1457, 962, 1404, + 1435, 991, 1386, + 1405, 1026, 1360, + 1360, 1070, 1323, + 1293, 1122, 1269, + 1184, 1184, 1184, + 979, 1255, 1037, + 327, 1335, 715, + 0, 1425, 0, + 0, 1522, 0, + 0, 1626, 0, + 0, 1736, 0, + 0, 1851, 0, + 0, 1970, 0, + 0, 2092, 0, + 0, 2216, 0, + 0, 2343, 0, + 0, 2470, 0, + 0, 2599, 0, + 0, 2728, 0, + 0, 2859, 0, + 0, 2989, 0, + 0, 3120, 0, + 0, 3252, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3647, 0, + 1654, 938, 1539, + 1651, 945, 1536, + 1647, 954, 1532, + 1641, 967, 1526, + 1633, 982, 1518, + 1622, 1003, 1507, + 1607, 1029, 1493, + 1586, 1062, 1473, + 1557, 1102, 1444, + 1515, 1151, 1403, + 1451, 1209, 1341, + 1349, 1277, 1243, + 1161, 1354, 1065, + 641, 1440, 601, + 0, 1534, 0, + 0, 1636, 0, + 0, 1744, 0, + 0, 1857, 0, + 0, 1975, 0, + 0, 2096, 0, + 0, 2219, 0, + 0, 2345, 0, + 0, 2472, 0, + 0, 2600, 0, + 0, 2729, 0, + 0, 2859, 0, + 0, 2990, 0, + 0, 3121, 0, + 0, 3252, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3647, 0, + 1801, 994, 1642, + 1798, 1000, 1639, + 1795, 1009, 1636, + 1791, 1020, 1631, + 1785, 1034, 1625, + 1778, 1052, 1617, + 1767, 1076, 1605, + 1752, 1105, 1589, + 1732, 1142, 1567, + 1704, 1187, 1536, + 1663, 1241, 1491, + 1601, 1304, 1423, + 1504, 1377, 1311, + 1328, 1459, 1099, + 874, 1550, 384, + 0, 1649, 0, + 0, 1754, 0, + 0, 1865, 0, + 0, 1981, 0, + 0, 2100, 0, + 0, 2223, 0, + 0, 2347, 0, + 0, 2474, 0, + 0, 2602, 0, + 0, 2731, 0, + 0, 2860, 0, + 0, 2990, 0, + 0, 3121, 0, + 0, 3252, 0, + 0, 3384, 0, + 0, 3515, 0, + 0, 3647, 0, + 1943, 1060, 1750, + 1941, 1066, 1748, + 1939, 1073, 1746, + 1936, 1082, 1742, + 1932, 1095, 1737, + 1926, 1111, 1731, + 1919, 1132, 1722, + 1908, 1158, 1710, + 1894, 1191, 1693, + 1874, 1231, 1670, + 1847, 1281, 1636, + 1807, 1339, 1587, + 1747, 1407, 1513, + 1652, 1484, 1389, + 1484, 1571, 1142, + 1068, 1665, 0, + 0, 1767, 0, + 0, 1876, 0, + 0, 1989, 0, + 0, 2106, 0, + 0, 2227, 0, + 0, 2351, 0, + 0, 2477, 0, + 0, 2604, 0, + 0, 2732, 0, + 0, 2861, 0, + 0, 2991, 0, + 0, 3122, 0, + 0, 3253, 0, + 0, 3384, 0, + 0, 3515, 0, + 0, 3647, 0, + 2083, 1136, 1864, + 2082, 1140, 1862, + 2080, 1146, 1860, + 2078, 1155, 1858, + 2075, 1165, 1854, + 2071, 1179, 1849, + 2065, 1197, 1842, + 2058, 1220, 1833, + 2047, 1249, 1820, + 2033, 1284, 1802, + 2014, 1328, 1778, + 1987, 1381, 1743, + 1947, 1444, 1691, + 1889, 1516, 1611, + 1796, 1597, 1476, + 1633, 1687, 1193, + 1242, 1784, 0, + 0, 1889, 0, + 0, 1999, 0, + 0, 2115, 0, + 0, 2234, 0, + 0, 2356, 0, + 0, 2480, 0, + 0, 2606, 0, + 0, 2734, 0, + 0, 2863, 0, + 0, 2993, 0, + 0, 3123, 0, + 0, 3253, 0, + 0, 3385, 0, + 0, 3516, 0, + 0, 3647, 0, + 2221, 1220, 1982, + 2220, 1224, 1981, + 2218, 1229, 1979, + 2217, 1236, 1977, + 2214, 1245, 1974, + 2211, 1257, 1970, + 2207, 1272, 1965, + 2202, 1291, 1958, + 2195, 1316, 1948, + 2185, 1347, 1935, + 2171, 1386, 1917, + 2151, 1433, 1891, + 2124, 1489, 1854, + 2086, 1554, 1800, + 2028, 1629, 1716, + 1937, 1713, 1571, + 1778, 1806, 1253, + 1403, 1906, 0, + 0, 2013, 0, + 0, 2125, 0, + 0, 2242, 0, + 0, 2362, 0, + 0, 2485, 0, + 0, 2610, 0, + 0, 2737, 0, + 0, 2865, 0, + 0, 2994, 0, + 0, 3124, 0, + 0, 3254, 0, + 0, 3385, 0, + 0, 3516, 0, + 0, 3648, 0, + 2357, 1313, 2103, + 2356, 1316, 2102, + 2355, 1321, 2101, + 2354, 1326, 2099, + 2352, 1334, 2097, + 2350, 1343, 2094, + 2347, 1356, 2090, + 2343, 1372, 2085, + 2338, 1393, 2078, + 2330, 1419, 2068, + 2320, 1452, 2054, + 2307, 1493, 2035, + 2288, 1543, 2009, + 2261, 1601, 1971, + 2222, 1669, 1915, + 2165, 1747, 1826, + 2076, 1834, 1673, + 1919, 1929, 1323, + 1556, 2031, 0, + 0, 2139, 0, + 0, 2253, 0, + 0, 2370, 0, + 0, 2491, 0, + 0, 2615, 0, + 0, 2741, 0, + 0, 2868, 0, + 0, 2996, 0, + 0, 3126, 0, + 0, 3256, 0, + 0, 3386, 0, + 0, 3517, 0, + 0, 3648, 0, + 2492, 1414, 2227, + 2491, 1416, 2226, + 2491, 1420, 2225, + 2490, 1424, 2224, + 2489, 1430, 2222, + 2487, 1438, 2220, + 2485, 1448, 2217, + 2482, 1461, 2213, + 2478, 1479, 2208, + 2472, 1501, 2200, + 2465, 1528, 2190, + 2455, 1563, 2176, + 2442, 1606, 2157, + 2423, 1657, 2130, + 2396, 1718, 2091, + 2358, 1788, 2033, + 2301, 1868, 1942, + 2213, 1957, 1782, + 2058, 2053, 1403, + 1703, 2157, 0, + 0, 2267, 0, + 0, 2381, 0, + 0, 2500, 0, + 0, 2621, 0, + 0, 2745, 0, + 0, 2871, 0, + 0, 2999, 0, + 0, 3128, 0, + 0, 3257, 0, + 0, 3387, 0, + 0, 3518, 0, + 0, 3649, 0, + 2626, 1521, 2353, + 2626, 1523, 2352, + 2625, 1526, 2351, + 2625, 1529, 2350, + 2624, 1534, 2349, + 2623, 1540, 2347, + 2621, 1548, 2345, + 2619, 1559, 2342, + 2616, 1573, 2338, + 2612, 1591, 2332, + 2607, 1614, 2325, + 2599, 1643, 2315, + 2589, 1679, 2301, + 2576, 1723, 2281, + 2557, 1776, 2253, + 2531, 1839, 2214, + 2493, 1911, 2154, + 2436, 1992, 2061, + 2348, 2082, 1895, + 2195, 2180, 1491, + 1846, 2285, 0, + 0, 2395, 0, + 0, 2511, 0, + 0, 2630, 0, + 0, 2752, 0, + 0, 2876, 0, + 0, 3003, 0, + 0, 3130, 0, + 0, 3259, 0, + 0, 3389, 0, + 0, 3519, 0, + 0, 3650, 0, + 2760, 1633, 2480, + 2760, 1635, 2479, + 2759, 1637, 2479, + 2759, 1640, 2478, + 2758, 1643, 2477, + 2757, 1648, 2476, + 2756, 1655, 2474, + 2755, 1663, 2472, + 2752, 1674, 2469, + 2749, 1689, 2465, + 2745, 1707, 2459, + 2740, 1731, 2451, + 2733, 1761, 2441, + 2723, 1798, 2427, + 2710, 1843, 2407, + 2691, 1898, 2379, + 2664, 1962, 2339, + 2627, 2035, 2278, + 2571, 2118, 2183, + 2483, 2209, 2013, + 2331, 2308, 1588, + 1986, 2414, 0, + 0, 2525, 0, + 0, 2641, 0, + 0, 2760, 0, + 0, 2883, 0, + 0, 3007, 0, + 0, 3134, 0, + 0, 3262, 0, + 0, 3391, 0, + 0, 3521, 0, + 0, 3651, 0, + 2893, 1750, 2608, + 2893, 1751, 2608, + 2893, 1753, 2608, + 2893, 1755, 2607, + 2892, 1758, 2606, + 2891, 1762, 2605, + 2891, 1767, 2604, + 2889, 1773, 2602, + 2888, 1782, 2600, + 2886, 1793, 2597, + 2883, 1808, 2593, + 2879, 1827, 2587, + 2873, 1852, 2579, + 2866, 1882, 2569, + 2856, 1920, 2554, + 2843, 1967, 2534, + 2824, 2022, 2506, + 2798, 2087, 2465, + 2760, 2161, 2404, + 2704, 2245, 2308, + 2617, 2337, 2134, + 2465, 2437, 1691, + 2123, 2543, 0, + 0, 2655, 0, + 0, 2771, 0, + 0, 2891, 0, + 0, 3014, 0, + 0, 3139, 0, + 0, 3266, 0, + 0, 3394, 0, + 0, 3523, 0, + 0, 3652, 0, + 3026, 1870, 2738, + 3026, 1871, 2737, + 3026, 1873, 2737, + 3026, 1874, 2737, + 3025, 1876, 2736, + 3025, 1879, 2735, + 3024, 1883, 2735, + 3023, 1888, 2733, + 3022, 1895, 2732, + 3021, 1904, 2729, + 3018, 1916, 2726, + 3015, 1931, 2722, + 3012, 1950, 2716, + 3006, 1975, 2708, + 2999, 2006, 2698, + 2989, 2045, 2683, + 2976, 2092, 2663, + 2957, 2148, 2635, + 2931, 2214, 2593, + 2893, 2289, 2532, + 2838, 2373, 2434, + 2750, 2466, 2258, + 2600, 2567, 1800, + 2260, 2673, 0, + 0, 2786, 0, + 0, 2902, 0, + 0, 3022, 0, + 0, 3145, 0, + 0, 3270, 0, + 0, 3397, 0, + 0, 3525, 0, + 0, 3655, 0, + 3159, 1993, 2868, + 3159, 1994, 2868, + 3159, 1995, 2867, + 3159, 1996, 2867, + 3159, 1998, 2867, + 3158, 2000, 2866, + 3158, 2003, 2865, + 3157, 2007, 2864, + 3156, 2012, 2863, + 3155, 2019, 2861, + 3153, 2028, 2859, + 3151, 2040, 2856, + 3148, 2056, 2852, + 3144, 2075, 2846, + 3139, 2101, 2838, + 3132, 2132, 2827, + 3122, 2172, 2813, + 3109, 2219, 2793, + 3090, 2276, 2764, + 3064, 2342, 2723, + 3026, 2418, 2661, + 2971, 2503, 2562, + 2884, 2596, 2383, + 2733, 2697, 1915, + 2395, 2804, 0, + 0, 2917, 0, + 0, 3033, 0, + 0, 3154, 0, + 0, 3277, 0, + 0, 3402, 0, + 0, 3529, 0, + 0, 3657, 0, + 3292, 2119, 2998, + 3292, 2119, 2998, + 3292, 2120, 2998, + 3292, 2121, 2998, + 3291, 2122, 2997, + 3291, 2124, 2997, + 3291, 2126, 2997, + 3290, 2129, 2996, + 3290, 2133, 2995, + 3289, 2138, 2994, + 3287, 2145, 2992, + 3286, 2155, 2989, + 3284, 2167, 2986, + 3281, 2182, 2982, + 3277, 2202, 2976, + 3272, 2228, 2968, + 3264, 2260, 2958, + 3255, 2299, 2943, + 3241, 2347, 2923, + 3222, 2405, 2894, + 3196, 2471, 2852, + 3159, 2548, 2790, + 3103, 2633, 2691, + 3017, 2727, 2510, + 2866, 2828, 2033, + 2530, 2935, 0, + 0, 3048, 0, + 0, 3165, 0, + 0, 3285, 0, + 0, 3409, 0, + 0, 3534, 0, + 0, 3661, 0, + 3424, 2246, 3129, + 3424, 2246, 3129, + 3424, 2246, 3129, + 3424, 2247, 3129, + 3424, 2248, 3129, + 3424, 2249, 3128, + 3424, 2251, 3128, + 3423, 2253, 3127, + 3423, 2257, 3127, + 3422, 2261, 3126, + 3421, 2266, 3124, + 3420, 2273, 3123, + 3418, 2282, 3120, + 3416, 2294, 3117, + 3413, 2310, 3113, + 3409, 2330, 3107, + 3404, 2356, 3099, + 3397, 2388, 3088, + 3387, 2428, 3074, + 3374, 2477, 3053, + 3355, 2534, 3024, + 3329, 2601, 2983, + 3291, 2678, 2920, + 3236, 2763, 2820, + 3149, 2857, 2639, + 2999, 2959, 2155, + 2663, 3066, 0, + 0, 3179, 0, + 0, 3297, 0, + 0, 3417, 0, + 0, 3540, 0, + 0, 3666, 0, + 3557, 2374, 3260, + 3557, 2374, 3260, + 3557, 2374, 3260, + 3557, 2375, 3260, + 3556, 2376, 3260, + 3556, 2377, 3260, + 3556, 2378, 3259, + 3556, 2380, 3259, + 3555, 2382, 3259, + 3555, 2385, 3258, + 3554, 2389, 3257, + 3553, 2395, 3255, + 3552, 2402, 3254, + 3551, 2411, 3251, + 3548, 2423, 3248, + 3546, 2439, 3244, + 3542, 2459, 3238, + 3536, 2485, 3230, + 3529, 2518, 3220, + 3519, 2558, 3205, + 3506, 2607, 3184, + 3487, 2664, 3155, + 3461, 2732, 3114, + 3424, 2808, 3051, + 3368, 2894, 2950, + 3282, 2989, 2768, + 3132, 3090, 2279, + 2797, 3198, 0, + 0, 3311, 0, + 0, 3428, 0, + 0, 3549, 0, + 0, 3672, 0, + 3689, 2503, 3392, + 3689, 2503, 3392, + 3689, 2503, 3392, + 3689, 2504, 3392, + 3689, 2504, 3392, + 3689, 2505, 3391, + 3689, 2506, 3391, + 3688, 2507, 3391, + 3688, 2509, 3390, + 3688, 2511, 3390, + 3687, 2515, 3389, + 3687, 2519, 3388, + 3686, 2524, 3387, + 3684, 2531, 3385, + 3683, 2541, 3383, + 3681, 2553, 3380, + 3678, 2569, 3375, + 3674, 2589, 3369, + 3669, 2615, 3362, + 3661, 2648, 3351, + 3652, 2688, 3336, + 3638, 2737, 3316, + 3620, 2795, 3287, + 3594, 2863, 3245, + 3556, 2940, 3182, + 3501, 3026, 3081, + 3414, 3120, 2898, + 3265, 3222, 2405, + 2930, 3330, 0, + 0, 3443, 0, + 0, 3560, 0, + 0, 3681, 0, + 3821, 2633, 3524, + 3821, 2633, 3523, + 3821, 2633, 3523, + 3821, 2633, 3523, + 3821, 2634, 3523, + 3821, 2634, 3523, + 3821, 2635, 3523, + 3821, 2636, 3523, + 3821, 2637, 3522, + 3820, 2639, 3522, + 3820, 2642, 3521, + 3819, 2645, 3521, + 3819, 2649, 3520, + 3818, 2654, 3518, + 3817, 2661, 3517, + 3815, 2671, 3514, + 3813, 2683, 3511, + 3810, 2699, 3507, + 3806, 2720, 3501, + 3801, 2746, 3493, + 3794, 2779, 3482, + 3784, 2819, 3468, + 3770, 2868, 3447, + 3752, 2926, 3418, + 3726, 2994, 3376, + 3688, 3071, 3313, + 3633, 3157, 3212, + 3547, 3252, 3029, + 3397, 3353, 2532, + 3063, 3461, 0, + 0, 3575, 0, + 0, 3692, 0, + 3954, 2763, 3655, + 3954, 2763, 3655, + 3954, 2763, 3655, + 3954, 2764, 3655, + 3953, 2764, 3655, + 3953, 2764, 3655, + 3953, 2765, 3655, + 3953, 2766, 3655, + 3953, 2767, 3654, + 3953, 2768, 3654, + 3953, 2770, 3654, + 3952, 2772, 3653, + 3952, 2775, 3652, + 3951, 2779, 3651, + 3950, 2785, 3650, + 3949, 2792, 3648, + 3947, 2802, 3646, + 3945, 2814, 3643, + 3942, 2830, 3639, + 3938, 2851, 3633, + 3933, 2877, 3625, + 3926, 2910, 3614, + 3916, 2950, 3599, + 3903, 2999, 3579, + 3884, 3057, 3550, + 3858, 3125, 3508, + 3821, 3202, 3444, + 3765, 3289, 3344, + 3679, 3383, 3160, + 3529, 3485, 2661, + 3195, 3593, 0, + 0, 3706, 0, + 4086, 2894, 3787, + 4086, 2894, 3787, + 4086, 2894, 3787, + 4086, 2894, 3787, + 4086, 2895, 3787, + 4086, 2895, 3787, + 4086, 2895, 3787, + 4085, 2896, 3787, + 4085, 2897, 3786, + 4085, 2898, 3786, + 4085, 2899, 3786, + 4085, 2901, 3786, + 4084, 2903, 3785, + 4084, 2906, 3784, + 4083, 2910, 3783, + 4082, 2916, 3782, + 4081, 2923, 3780, + 4079, 2933, 3778, + 4077, 2945, 3775, + 4074, 2961, 3770, + 4071, 2982, 3765, + 4065, 3008, 3757, + 4058, 3041, 3746, + 4048, 3081, 3731, + 4035, 3130, 3710, + 4016, 3189, 3681, + 3990, 3257, 3639, + 3953, 3334, 3576, + 3898, 3420, 3475, + 3811, 3515, 3291, + 3662, 3617, 2790, + 3328, 3725, 0, + 4095, 3025, 3919, + 4095, 3025, 3919, + 4095, 3025, 3919, + 4095, 3025, 3919, + 4095, 3026, 3919, + 4095, 3026, 3919, + 4095, 3026, 3919, + 4095, 3027, 3919, + 4095, 3027, 3919, + 4095, 3028, 3918, + 4095, 3029, 3918, + 4095, 3030, 3918, + 4095, 3032, 3917, + 4095, 3034, 3917, + 4095, 3037, 3916, + 4095, 3042, 3915, + 4095, 3047, 3914, + 4095, 3054, 3912, + 4095, 3064, 3910, + 4095, 3076, 3906, + 4095, 3092, 3902, + 4095, 3113, 3896, + 4095, 3139, 3888, + 4095, 3172, 3878, + 4095, 3213, 3863, + 4095, 3262, 3842, + 4095, 3320, 3813, + 4095, 3388, 3771, + 4085, 3466, 3708, + 4030, 3552, 3607, + 3943, 3647, 3422, + 3794, 3749, 2920, + 4095, 3156, 4051, + 4095, 3157, 4051, + 4095, 3157, 4051, + 4095, 3157, 4051, + 4095, 3157, 4051, + 4095, 3157, 4051, + 4095, 3157, 4051, + 4095, 3158, 4051, + 4095, 3158, 4051, + 4095, 3159, 4050, + 4095, 3159, 4050, + 4095, 3160, 4050, + 4095, 3162, 4050, + 4095, 3163, 4049, + 4095, 3166, 4049, + 4095, 3169, 4048, + 4095, 3173, 4047, + 4095, 3179, 4046, + 4095, 3186, 4044, + 4095, 3195, 4042, + 4095, 3208, 4038, + 4095, 3224, 4034, + 4095, 3245, 4028, + 4095, 3271, 4020, + 4095, 3304, 4010, + 4095, 3345, 3995, + 4095, 3394, 3974, + 4095, 3452, 3945, + 4095, 3520, 3903, + 4095, 3598, 3840, + 4095, 3684, 3738, + 4075, 3779, 3554, + 0, 843, 1089, + 0, 852, 1080, + 0, 864, 1068, + 0, 879, 1052, + 0, 898, 1030, + 0, 923, 998, + 0, 954, 952, + 0, 992, 882, + 0, 1039, 767, + 0, 1094, 545, + 0, 1160, 0, + 0, 1234, 0, + 0, 1318, 0, + 0, 1411, 0, + 0, 1511, 0, + 0, 1617, 0, + 0, 1729, 0, + 0, 1846, 0, + 0, 1966, 0, + 0, 2089, 0, + 0, 2214, 0, + 0, 2341, 0, + 0, 2469, 0, + 0, 2598, 0, + 0, 2728, 0, + 0, 2858, 0, + 0, 2989, 0, + 0, 3120, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3646, 0, + 0, 846, 1101, + 0, 855, 1093, + 0, 867, 1082, + 0, 881, 1066, + 0, 901, 1044, + 0, 925, 1013, + 0, 956, 969, + 0, 994, 901, + 0, 1041, 792, + 0, 1096, 585, + 0, 1161, 0, + 0, 1236, 0, + 0, 1319, 0, + 0, 1412, 0, + 0, 1512, 0, + 0, 1618, 0, + 0, 1730, 0, + 0, 1846, 0, + 0, 1966, 0, + 0, 2089, 0, + 0, 2214, 0, + 0, 2341, 0, + 0, 2469, 0, + 0, 2598, 0, + 0, 2728, 0, + 0, 2858, 0, + 0, 2989, 0, + 0, 3120, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3646, 0, + 0, 850, 1117, + 0, 859, 1109, + 0, 870, 1098, + 0, 885, 1083, + 0, 904, 1063, + 0, 928, 1033, + 0, 959, 990, + 0, 997, 926, + 0, 1043, 823, + 0, 1098, 634, + 0, 1163, 101, + 0, 1237, 0, + 0, 1321, 0, + 0, 1413, 0, + 0, 1513, 0, + 0, 1619, 0, + 0, 1730, 0, + 0, 1847, 0, + 0, 1967, 0, + 0, 2089, 0, + 0, 2214, 0, + 0, 2341, 0, + 0, 2469, 0, + 0, 2598, 0, + 0, 2728, 0, + 0, 2858, 0, + 0, 2989, 0, + 0, 3120, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3646, 0, + 0, 856, 1138, + 0, 864, 1130, + 0, 875, 1120, + 0, 890, 1106, + 0, 909, 1086, + 0, 933, 1058, + 0, 963, 1018, + 0, 1001, 957, + 0, 1047, 862, + 0, 1101, 692, + 0, 1166, 266, + 0, 1240, 0, + 0, 1323, 0, + 0, 1414, 0, + 0, 1514, 0, + 0, 1620, 0, + 0, 1731, 0, + 0, 1847, 0, + 0, 1967, 0, + 0, 2090, 0, + 0, 2215, 0, + 0, 2341, 0, + 0, 2469, 0, + 0, 2598, 0, + 0, 2728, 0, + 0, 2858, 0, + 0, 2989, 0, + 0, 3120, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3646, 0, + 0, 863, 1164, + 0, 871, 1157, + 0, 882, 1147, + 0, 897, 1134, + 0, 915, 1115, + 0, 939, 1089, + 0, 969, 1052, + 0, 1006, 996, + 0, 1051, 909, + 0, 1106, 759, + 0, 1169, 421, + 0, 1243, 0, + 0, 1325, 0, + 0, 1417, 0, + 0, 1515, 0, + 0, 1621, 0, + 0, 1732, 0, + 0, 1848, 0, + 0, 1968, 0, + 0, 2090, 0, + 0, 2215, 0, + 0, 2341, 0, + 0, 2469, 0, + 0, 2598, 0, + 0, 2728, 0, + 0, 2858, 0, + 0, 2989, 0, + 0, 3120, 0, + 0, 3252, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3646, 0, + 133, 872, 1198, + 32, 880, 1191, + 0, 891, 1182, + 0, 905, 1169, + 0, 923, 1152, + 0, 947, 1128, + 0, 976, 1094, + 0, 1013, 1043, + 0, 1057, 966, + 0, 1111, 836, + 0, 1174, 570, + 0, 1247, 0, + 0, 1329, 0, + 0, 1419, 0, + 0, 1518, 0, + 0, 1623, 0, + 0, 1734, 0, + 0, 1849, 0, + 0, 1968, 0, + 0, 2091, 0, + 0, 2215, 0, + 0, 2342, 0, + 0, 2470, 0, + 0, 2599, 0, + 0, 2728, 0, + 0, 2858, 0, + 0, 2989, 0, + 0, 3120, 0, + 0, 3252, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3647, 0, + 615, 884, 1238, + 582, 892, 1232, + 535, 902, 1224, + 462, 916, 1213, + 342, 934, 1197, + 107, 957, 1175, + 0, 986, 1144, + 0, 1021, 1100, + 0, 1065, 1032, + 0, 1118, 922, + 0, 1180, 714, + 0, 1252, 39, + 0, 1333, 0, + 0, 1423, 0, + 0, 1521, 0, + 0, 1625, 0, + 0, 1735, 0, + 0, 1851, 0, + 0, 1970, 0, + 0, 2092, 0, + 0, 2216, 0, + 0, 2342, 0, + 0, 2470, 0, + 0, 2599, 0, + 0, 2728, 0, + 0, 2859, 0, + 0, 2989, 0, + 0, 3120, 0, + 0, 3252, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3647, 0, + 901, 899, 1288, + 883, 907, 1282, + 859, 917, 1275, + 825, 931, 1265, + 775, 948, 1251, + 698, 970, 1231, + 569, 998, 1204, + 307, 1033, 1165, + 0, 1076, 1107, + 0, 1127, 1016, + 0, 1188, 855, + 0, 1259, 474, + 0, 1339, 0, + 0, 1428, 0, + 0, 1524, 0, + 0, 1628, 0, + 0, 1738, 0, + 0, 1852, 0, + 0, 1971, 0, + 0, 2093, 0, + 0, 2217, 0, + 0, 2343, 0, + 0, 2470, 0, + 0, 2599, 0, + 0, 2729, 0, + 0, 2859, 0, + 0, 2989, 0, + 0, 3120, 0, + 0, 3252, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3647, 0, + 1121, 919, 1346, + 1110, 927, 1341, + 1096, 937, 1335, + 1076, 949, 1326, + 1048, 966, 1314, + 1007, 987, 1297, + 947, 1014, 1274, + 850, 1048, 1241, + 677, 1089, 1192, + 240, 1140, 1117, + 0, 1199, 994, + 0, 1268, 747, + 0, 1347, 0, + 0, 1434, 0, + 0, 1530, 0, + 0, 1632, 0, + 0, 1741, 0, + 0, 1855, 0, + 0, 1973, 0, + 0, 2094, 0, + 0, 2218, 0, + 0, 2344, 0, + 0, 2471, 0, + 0, 2600, 0, + 0, 2729, 0, + 0, 2859, 0, + 0, 2990, 0, + 0, 3121, 0, + 0, 3252, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3647, 0, + 1309, 945, 1414, + 1302, 952, 1410, + 1293, 961, 1405, + 1280, 973, 1397, + 1262, 989, 1387, + 1237, 1009, 1372, + 1202, 1035, 1353, + 1149, 1067, 1325, + 1068, 1107, 1285, + 930, 1156, 1225, + 639, 1213, 1130, + 0, 1280, 962, + 0, 1357, 546, + 0, 1442, 0, + 0, 1536, 0, + 0, 1638, 0, + 0, 1745, 0, + 0, 1858, 0, + 0, 1976, 0, + 0, 2096, 0, + 0, 2220, 0, + 0, 2345, 0, + 0, 2472, 0, + 0, 2600, 0, + 0, 2729, 0, + 0, 2859, 0, + 0, 2990, 0, + 0, 3121, 0, + 0, 3252, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3647, 0, + 1479, 977, 1492, + 1475, 983, 1488, + 1468, 992, 1484, + 1460, 1003, 1477, + 1448, 1018, 1469, + 1431, 1037, 1457, + 1408, 1061, 1441, + 1376, 1092, 1418, + 1328, 1130, 1385, + 1255, 1176, 1338, + 1136, 1231, 1266, + 901, 1296, 1148, + 0, 1370, 916, + 0, 1453, 0, + 0, 1545, 0, + 0, 1645, 0, + 0, 1751, 0, + 0, 1863, 0, + 0, 1979, 0, + 0, 2099, 0, + 0, 2221, 0, + 0, 2346, 0, + 0, 2473, 0, + 0, 2601, 0, + 0, 2730, 0, + 0, 2860, 0, + 0, 2990, 0, + 0, 3121, 0, + 0, 3252, 0, + 0, 3384, 0, + 0, 3515, 0, + 0, 3647, 0, + 1638, 1016, 1579, + 1635, 1022, 1576, + 1630, 1030, 1572, + 1624, 1041, 1567, + 1616, 1054, 1559, + 1604, 1072, 1550, + 1589, 1094, 1537, + 1567, 1123, 1518, + 1537, 1158, 1492, + 1492, 1202, 1455, + 1425, 1254, 1401, + 1316, 1316, 1316, + 1111, 1387, 1169, + 459, 1468, 847, + 0, 1557, 0, + 0, 1654, 0, + 0, 1758, 0, + 0, 1869, 0, + 0, 1983, 0, + 0, 2102, 0, + 0, 2224, 0, + 0, 2348, 0, + 0, 2475, 0, + 0, 2602, 0, + 0, 2731, 0, + 0, 2861, 0, + 0, 2991, 0, + 0, 3121, 0, + 0, 3252, 0, + 0, 3384, 0, + 0, 3515, 0, + 0, 3647, 0, + 1789, 1064, 1673, + 1786, 1070, 1671, + 1783, 1077, 1668, + 1779, 1086, 1664, + 1773, 1099, 1658, + 1765, 1115, 1650, + 1754, 1135, 1640, + 1739, 1161, 1625, + 1719, 1194, 1605, + 1689, 1234, 1576, + 1647, 1283, 1535, + 1583, 1341, 1473, + 1481, 1409, 1375, + 1293, 1486, 1197, + 773, 1572, 733, + 0, 1667, 0, + 0, 1768, 0, + 0, 1876, 0, + 0, 1989, 0, + 0, 2107, 0, + 0, 2228, 0, + 0, 2351, 0, + 0, 2477, 0, + 0, 2604, 0, + 0, 2732, 0, + 0, 2861, 0, + 0, 2991, 0, + 0, 3122, 0, + 0, 3253, 0, + 0, 3384, 0, + 0, 3515, 0, + 0, 3647, 0, + 1934, 1121, 1775, + 1933, 1126, 1774, + 1930, 1133, 1771, + 1927, 1141, 1768, + 1923, 1152, 1763, + 1917, 1166, 1757, + 1910, 1184, 1749, + 1899, 1208, 1737, + 1885, 1237, 1721, + 1864, 1274, 1700, + 1836, 1319, 1668, + 1795, 1373, 1623, + 1734, 1436, 1555, + 1636, 1509, 1443, + 1460, 1592, 1231, + 1006, 1682, 516, + 0, 1781, 0, + 0, 1886, 0, + 0, 1997, 0, + 0, 2113, 0, + 0, 2232, 0, + 0, 2355, 0, + 0, 2479, 0, + 0, 2606, 0, + 0, 2734, 0, + 0, 2863, 0, + 0, 2992, 0, + 0, 3123, 0, + 0, 3253, 0, + 0, 3384, 0, + 0, 3516, 0, + 0, 3647, 0, + 2076, 1188, 1884, + 2075, 1192, 1882, + 2074, 1198, 1880, + 2071, 1205, 1878, + 2068, 1214, 1874, + 2064, 1227, 1869, + 2058, 1243, 1863, + 2051, 1264, 1854, + 2041, 1290, 1842, + 2026, 1323, 1825, + 2007, 1363, 1802, + 1979, 1413, 1768, + 1939, 1471, 1720, + 1879, 1539, 1645, + 1784, 1616, 1521, + 1616, 1703, 1274, + 1200, 1798, 0, + 0, 1899, 0, + 0, 2008, 0, + 0, 2121, 0, + 0, 2239, 0, + 0, 2359, 0, + 0, 2483, 0, + 0, 2609, 0, + 0, 2736, 0, + 0, 2864, 0, + 0, 2993, 0, + 0, 3123, 0, + 0, 3254, 0, + 0, 3385, 0, + 0, 3516, 0, + 0, 3648, 0, + 2216, 1264, 1997, + 2215, 1268, 1996, + 2214, 1272, 1995, + 2212, 1279, 1992, + 2210, 1287, 1990, + 2207, 1297, 1986, + 2203, 1311, 1981, + 2197, 1329, 1974, + 2190, 1352, 1965, + 2179, 1381, 1952, + 2165, 1417, 1935, + 2146, 1461, 1910, + 2119, 1513, 1875, + 2079, 1576, 1823, + 2021, 1648, 1743, + 1928, 1729, 1608, + 1765, 1819, 1325, + 1374, 1916, 0, + 0, 2021, 0, + 0, 2132, 0, + 0, 2247, 0, + 0, 2366, 0, + 0, 2488, 0, + 0, 2612, 0, + 0, 2739, 0, + 0, 2866, 0, + 0, 2995, 0, + 0, 3125, 0, + 0, 3255, 0, + 0, 3386, 0, + 0, 3517, 0, + 0, 3648, 0, + 2353, 1349, 2115, + 2353, 1352, 2114, + 2352, 1356, 2113, + 2350, 1361, 2111, + 2349, 1368, 2109, + 2347, 1377, 2106, + 2344, 1389, 2102, + 2340, 1404, 2097, + 2334, 1423, 2090, + 2327, 1448, 2080, + 2317, 1479, 2067, + 2303, 1518, 2049, + 2284, 1565, 2023, + 2257, 1621, 1987, + 2218, 1686, 1932, + 2160, 1761, 1848, + 2069, 1846, 1703, + 1910, 1938, 1386, + 1535, 2039, 0, + 0, 2145, 0, + 0, 2257, 0, + 0, 2374, 0, + 0, 2494, 0, + 0, 2617, 0, + 0, 2742, 0, + 0, 2869, 0, + 0, 2997, 0, + 0, 3126, 0, + 0, 3256, 0, + 0, 3386, 0, + 0, 3517, 0, + 0, 3648, 0, + 2489, 1443, 2236, + 2489, 1445, 2235, + 2488, 1449, 2234, + 2487, 1453, 2233, + 2486, 1458, 2231, + 2484, 1466, 2229, + 2482, 1475, 2226, + 2479, 1488, 2222, + 2475, 1504, 2217, + 2470, 1525, 2210, + 2462, 1551, 2200, + 2452, 1584, 2186, + 2439, 1625, 2167, + 2420, 1675, 2141, + 2393, 1733, 2103, + 2355, 1802, 2047, + 2297, 1879, 1958, + 2208, 1966, 1805, + 2051, 2061, 1456, + 1688, 2163, 0, + 0, 2271, 0, + 0, 2385, 0, + 0, 2502, 0, + 0, 2623, 0, + 0, 2747, 0, + 0, 2873, 0, + 0, 3000, 0, + 0, 3128, 0, + 0, 3258, 0, + 0, 3388, 0, + 0, 3518, 0, + 0, 3649, 0, + 2624, 1544, 2359, + 2624, 1546, 2359, + 2624, 1549, 2358, + 2623, 1552, 2357, + 2622, 1556, 2356, + 2621, 1562, 2354, + 2619, 1570, 2352, + 2617, 1580, 2349, + 2614, 1593, 2345, + 2610, 1611, 2340, + 2605, 1633, 2332, + 2597, 1661, 2322, + 2587, 1695, 2308, + 2574, 1738, 2289, + 2555, 1789, 2262, + 2528, 1850, 2223, + 2490, 1921, 2165, + 2433, 2000, 2074, + 2345, 2089, 1914, + 2190, 2186, 1535, + 1835, 2289, 0, + 0, 2399, 0, + 0, 2513, 0, + 0, 2632, 0, + 0, 2753, 0, + 0, 2877, 0, + 0, 3004, 0, + 0, 3131, 0, + 0, 3260, 0, + 0, 3389, 0, + 0, 3519, 0, + 0, 3650, 0, + 2759, 1651, 2485, + 2758, 1653, 2485, + 2758, 1655, 2484, + 2758, 1658, 2483, + 2757, 1661, 2482, + 2756, 1666, 2481, + 2755, 1672, 2480, + 2753, 1680, 2477, + 2751, 1691, 2474, + 2748, 1705, 2470, + 2744, 1723, 2465, + 2739, 1746, 2457, + 2731, 1775, 2447, + 2721, 1811, 2433, + 2708, 1855, 2413, + 2689, 1908, 2385, + 2663, 1971, 2346, + 2625, 2043, 2287, + 2568, 2124, 2193, + 2480, 2214, 2027, + 2327, 2312, 1623, + 1978, 2417, 0, + 0, 2527, 0, + 0, 2643, 0, + 0, 2762, 0, + 0, 2884, 0, + 0, 3008, 0, + 0, 3135, 0, + 0, 3262, 0, + 0, 3391, 0, + 0, 3521, 0, + 0, 3651, 0, + 2892, 1764, 2612, + 2892, 1765, 2612, + 2892, 1767, 2612, + 2892, 1769, 2611, + 2891, 1772, 2610, + 2890, 1775, 2609, + 2889, 1780, 2608, + 2888, 1787, 2606, + 2887, 1795, 2604, + 2884, 1806, 2601, + 2882, 1821, 2597, + 2878, 1839, 2591, + 2872, 1863, 2584, + 2865, 1893, 2573, + 2855, 1930, 2559, + 2842, 1976, 2539, + 2823, 2030, 2511, + 2797, 2094, 2471, + 2759, 2167, 2411, + 2703, 2250, 2315, + 2615, 2341, 2145, + 2463, 2440, 1720, + 2118, 2546, 0, + 0, 2657, 0, + 0, 2773, 0, + 0, 2892, 0, + 0, 3015, 0, + 0, 3140, 0, + 0, 3266, 0, + 0, 3394, 0, + 0, 3523, 0, + 0, 3653, 0, + 3026, 1881, 2741, + 3026, 1882, 2740, + 3025, 1883, 2740, + 3025, 1885, 2740, + 3025, 1887, 2739, + 3024, 1890, 2738, + 3024, 1894, 2737, + 3023, 1899, 2736, + 3021, 1905, 2734, + 3020, 1914, 2732, + 3018, 1926, 2729, + 3015, 1940, 2725, + 3011, 1960, 2719, + 3005, 1984, 2712, + 2998, 2015, 2701, + 2988, 2053, 2687, + 2975, 2099, 2667, + 2956, 2154, 2638, + 2930, 2219, 2598, + 2892, 2294, 2537, + 2836, 2377, 2440, + 2749, 2469, 2266, + 2598, 2569, 1823, + 2256, 2675, 0, + 0, 2787, 0, + 0, 2903, 0, + 0, 3023, 0, + 0, 3146, 0, + 0, 3271, 0, + 0, 3398, 0, + 0, 3526, 0, + 0, 3655, 0, + 3159, 2002, 2870, + 3159, 2002, 2870, + 3158, 2003, 2870, + 3158, 2005, 2869, + 3158, 2006, 2869, + 3158, 2008, 2868, + 3157, 2011, 2868, + 3156, 2015, 2867, + 3156, 2020, 2865, + 3154, 2027, 2864, + 3153, 2036, 2861, + 3151, 2048, 2858, + 3148, 2063, 2854, + 3144, 2082, 2848, + 3138, 2107, 2840, + 3131, 2139, 2830, + 3121, 2177, 2815, + 3108, 2224, 2795, + 3089, 2280, 2767, + 3063, 2346, 2726, + 3025, 2421, 2664, + 2970, 2506, 2566, + 2883, 2598, 2390, + 2732, 2699, 1933, + 2392, 2805, 0, + 0, 2918, 0, + 0, 3034, 0, + 0, 3154, 0, + 0, 3277, 0, + 0, 3403, 0, + 0, 3529, 0, + 0, 3658, 0, + 3291, 2125, 3000, + 3291, 2125, 3000, + 3291, 2126, 3000, + 3291, 2127, 2999, + 3291, 2128, 2999, + 3291, 2130, 2999, + 3290, 2132, 2998, + 3290, 2135, 2997, + 3289, 2139, 2996, + 3288, 2145, 2995, + 3287, 2151, 2993, + 3285, 2161, 2991, + 3283, 2172, 2988, + 3280, 2188, 2984, + 3276, 2208, 2978, + 3271, 2233, 2970, + 3264, 2264, 2960, + 3254, 2304, 2945, + 3241, 2351, 2925, + 3222, 2408, 2896, + 3196, 2474, 2855, + 3158, 2550, 2793, + 3103, 2635, 2694, + 3016, 2728, 2515, + 2865, 2829, 2047, + 2527, 2936, 0, + 0, 3049, 0, + 0, 3166, 0, + 0, 3286, 0, + 0, 3409, 0, + 0, 3534, 0, + 0, 3661, 0, + 3424, 2250, 3130, + 3424, 2251, 3130, + 3424, 2251, 3130, + 3424, 2252, 3130, + 3424, 2253, 3130, + 3423, 2254, 3130, + 3423, 2256, 3129, + 3423, 2258, 3129, + 3422, 2261, 3128, + 3422, 2265, 3127, + 3421, 2271, 3126, + 3420, 2278, 3124, + 3418, 2287, 3122, + 3416, 2299, 3118, + 3413, 2314, 3114, + 3409, 2334, 3108, + 3404, 2360, 3101, + 3396, 2392, 3090, + 3387, 2431, 3075, + 3373, 2479, 3055, + 3355, 2537, 3026, + 3328, 2603, 2984, + 3291, 2680, 2922, + 3235, 2765, 2823, + 3149, 2859, 2643, + 2999, 2960, 2165, + 2662, 3067, 0, + 0, 3180, 0, + 0, 3297, 0, + 0, 3418, 0, + 0, 3541, 0, + 0, 3666, 0, + 3557, 2377, 3261, + 3557, 2378, 3261, + 3556, 2378, 3261, + 3556, 2379, 3261, + 3556, 2379, 3261, + 3556, 2380, 3261, + 3556, 2382, 3260, + 3556, 2383, 3260, + 3555, 2386, 3259, + 3555, 2389, 3259, + 3554, 2393, 3258, + 3553, 2398, 3256, + 3552, 2405, 3255, + 3550, 2414, 3252, + 3548, 2427, 3249, + 3545, 2442, 3245, + 3541, 2462, 3239, + 3536, 2488, 3231, + 3529, 2520, 3221, + 3519, 2560, 3206, + 3506, 2609, 3185, + 3487, 2666, 3157, + 3461, 2733, 3115, + 3423, 2810, 3052, + 3368, 2896, 2952, + 3281, 2989, 2771, + 3131, 3091, 2287, + 2795, 3198, 0, + 0, 3311, 0, + 0, 3429, 0, + 0, 3549, 0, + 0, 3673, 0, + 3689, 2506, 3393, + 3689, 2506, 3393, + 3689, 2506, 3392, + 3689, 2506, 3392, + 3689, 2507, 3392, + 3689, 2508, 3392, + 3688, 2509, 3392, + 3688, 2510, 3392, + 3688, 2512, 3391, + 3688, 2514, 3391, + 3687, 2517, 3390, + 3686, 2521, 3389, + 3686, 2527, 3388, + 3684, 2534, 3386, + 3683, 2543, 3383, + 3681, 2555, 3380, + 3678, 2571, 3376, + 3674, 2592, 3370, + 3668, 2617, 3362, + 3661, 2650, 3352, + 3651, 2690, 3337, + 3638, 2739, 3316, + 3619, 2796, 3287, + 3593, 2864, 3246, + 3556, 2941, 3183, + 3500, 3026, 3083, + 3414, 3121, 2900, + 3264, 3222, 2411, + 2929, 3330, 0, + 0, 3443, 0, + 0, 3560, 0, + 0, 3681, 0, + 3821, 2635, 3524, + 3821, 2635, 3524, + 3821, 2635, 3524, + 3821, 2635, 3524, + 3821, 2636, 3524, + 3821, 2636, 3524, + 3821, 2637, 3523, + 3821, 2638, 3523, + 3821, 2639, 3523, + 3820, 2641, 3523, + 3820, 2644, 3522, + 3819, 2647, 3521, + 3819, 2651, 3520, + 3818, 2656, 3519, + 3817, 2663, 3517, + 3815, 2673, 3515, + 3813, 2685, 3512, + 3810, 2701, 3507, + 3806, 2721, 3502, + 3801, 2747, 3494, + 3794, 2780, 3483, + 3784, 2820, 3468, + 3770, 2869, 3448, + 3752, 2927, 3419, + 3726, 2995, 3377, + 3688, 3072, 3314, + 3633, 3158, 3213, + 3546, 3252, 3030, + 3397, 3354, 2537, + 3062, 3462, 0, + 0, 3575, 0, + 0, 3692, 0, + 3953, 2765, 3656, + 3953, 2765, 3656, + 3953, 2765, 3656, + 3953, 2765, 3656, + 3953, 2765, 3655, + 3953, 2766, 3655, + 3953, 2766, 3655, + 3953, 2767, 3655, + 3953, 2768, 3655, + 3953, 2770, 3655, + 3952, 2771, 3654, + 3952, 2774, 3654, + 3952, 2777, 3653, + 3951, 2781, 3652, + 3950, 2786, 3651, + 3949, 2793, 3649, + 3947, 2803, 3646, + 3945, 2815, 3643, + 3942, 2831, 3639, + 3938, 2852, 3633, + 3933, 2878, 3625, + 3926, 2911, 3615, + 3916, 2951, 3600, + 3903, 3000, 3579, + 3884, 3058, 3550, + 3858, 3126, 3508, + 3821, 3203, 3445, + 3765, 3289, 3344, + 3679, 3384, 3161, + 3529, 3485, 2664, + 3195, 3593, 0, + 0, 3707, 0, + 4086, 2895, 3787, + 4086, 2895, 3787, + 4086, 2895, 3787, + 4086, 2896, 3787, + 4086, 2896, 3787, + 4086, 2896, 3787, + 4086, 2896, 3787, + 4085, 2897, 3787, + 4085, 2898, 3787, + 4085, 2899, 3787, + 4085, 2900, 3786, + 4085, 2902, 3786, + 4084, 2904, 3785, + 4084, 2907, 3785, + 4083, 2911, 3784, + 4082, 2917, 3782, + 4081, 2924, 3780, + 4079, 2934, 3778, + 4077, 2946, 3775, + 4074, 2962, 3771, + 4070, 2983, 3765, + 4065, 3009, 3757, + 4058, 3042, 3746, + 4048, 3082, 3731, + 4035, 3131, 3711, + 4016, 3189, 3682, + 3990, 3257, 3640, + 3953, 3334, 3577, + 3897, 3421, 3476, + 3811, 3515, 3292, + 3662, 3617, 2793, + 3327, 3725, 0, + 4095, 3026, 3919, + 4095, 3026, 3919, + 4095, 3026, 3919, + 4095, 3026, 3919, + 4095, 3026, 3919, + 4095, 3027, 3919, + 4095, 3027, 3919, + 4095, 3027, 3919, + 4095, 3028, 3919, + 4095, 3029, 3919, + 4095, 3030, 3918, + 4095, 3031, 3918, + 4095, 3033, 3918, + 4095, 3035, 3917, + 4095, 3038, 3916, + 4095, 3042, 3915, + 4095, 3048, 3914, + 4095, 3055, 3912, + 4095, 3065, 3910, + 4095, 3077, 3907, + 4095, 3093, 3902, + 4095, 3114, 3897, + 4095, 3140, 3889, + 4095, 3173, 3878, + 4095, 3213, 3863, + 4095, 3263, 3843, + 4095, 3321, 3813, + 4095, 3389, 3771, + 4085, 3466, 3708, + 4030, 3552, 3607, + 3943, 3647, 3423, + 3794, 3749, 2922, + 4095, 3157, 4051, + 4095, 3157, 4051, + 4095, 3157, 4051, + 4095, 3157, 4051, + 4095, 3157, 4051, + 4095, 3158, 4051, + 4095, 3158, 4051, + 4095, 3158, 4051, + 4095, 3159, 4051, + 4095, 3159, 4051, + 4095, 3160, 4050, + 4095, 3161, 4050, + 4095, 3162, 4050, + 4095, 3164, 4049, + 4095, 3166, 4049, + 4095, 3170, 4048, + 4095, 3174, 4047, + 4095, 3179, 4046, + 4095, 3186, 4044, + 4095, 3196, 4042, + 4095, 3208, 4039, + 4095, 3224, 4034, + 4095, 3245, 4028, + 4095, 3271, 4021, + 4095, 3304, 4010, + 4095, 3345, 3995, + 4095, 3394, 3974, + 4095, 3453, 3945, + 4095, 3520, 3903, + 4095, 3598, 3840, + 4095, 3684, 3739, + 4075, 3779, 3555, + 0, 966, 1218, + 0, 973, 1211, + 0, 982, 1202, + 0, 994, 1191, + 0, 1009, 1174, + 0, 1028, 1151, + 0, 1053, 1119, + 0, 1084, 1071, + 0, 1122, 999, + 0, 1169, 879, + 0, 1225, 645, + 0, 1291, 0, + 0, 1366, 0, + 0, 1450, 0, + 0, 1542, 0, + 0, 1643, 0, + 0, 1749, 0, + 0, 1861, 0, + 0, 1978, 0, + 0, 2098, 0, + 0, 2221, 0, + 0, 2346, 0, + 0, 2473, 0, + 0, 2601, 0, + 0, 2730, 0, + 0, 2860, 0, + 0, 2990, 0, + 0, 3121, 0, + 0, 3252, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3647, 0, + 0, 969, 1227, + 0, 975, 1221, + 0, 984, 1212, + 0, 996, 1201, + 0, 1011, 1185, + 0, 1030, 1162, + 0, 1055, 1130, + 0, 1086, 1084, + 0, 1124, 1014, + 0, 1171, 899, + 0, 1226, 677, + 0, 1292, 0, + 0, 1367, 0, + 0, 1451, 0, + 0, 1543, 0, + 0, 1643, 0, + 0, 1750, 0, + 0, 1862, 0, + 0, 1978, 0, + 0, 2098, 0, + 0, 2221, 0, + 0, 2346, 0, + 0, 2473, 0, + 0, 2601, 0, + 0, 2730, 0, + 0, 2860, 0, + 0, 2990, 0, + 0, 3121, 0, + 0, 3252, 0, + 0, 3384, 0, + 0, 3515, 0, + 0, 3647, 0, + 0, 972, 1239, + 0, 978, 1233, + 0, 987, 1225, + 0, 999, 1214, + 0, 1014, 1198, + 0, 1033, 1176, + 0, 1057, 1146, + 0, 1088, 1101, + 0, 1126, 1033, + 0, 1173, 924, + 0, 1228, 717, + 0, 1293, 53, + 0, 1368, 0, + 0, 1452, 0, + 0, 1544, 0, + 0, 1644, 0, + 0, 1750, 0, + 0, 1862, 0, + 0, 1978, 0, + 0, 2098, 0, + 0, 2221, 0, + 0, 2346, 0, + 0, 2473, 0, + 0, 2601, 0, + 0, 2730, 0, + 0, 2860, 0, + 0, 2990, 0, + 0, 3121, 0, + 0, 3252, 0, + 0, 3384, 0, + 0, 3515, 0, + 0, 3647, 0, + 0, 976, 1255, + 0, 982, 1249, + 0, 991, 1241, + 0, 1002, 1230, + 0, 1017, 1215, + 0, 1036, 1195, + 0, 1061, 1165, + 0, 1091, 1122, + 0, 1129, 1058, + 0, 1175, 955, + 0, 1231, 766, + 0, 1295, 233, + 0, 1370, 0, + 0, 1453, 0, + 0, 1545, 0, + 0, 1645, 0, + 0, 1751, 0, + 0, 1863, 0, + 0, 1979, 0, + 0, 2099, 0, + 0, 2221, 0, + 0, 2346, 0, + 0, 2473, 0, + 0, 2601, 0, + 0, 2730, 0, + 0, 2860, 0, + 0, 2990, 0, + 0, 3121, 0, + 0, 3252, 0, + 0, 3384, 0, + 0, 3515, 0, + 0, 3647, 0, + 0, 981, 1276, + 0, 988, 1270, + 0, 996, 1263, + 0, 1008, 1252, + 0, 1022, 1238, + 0, 1041, 1218, + 0, 1065, 1190, + 0, 1095, 1150, + 0, 1133, 1090, + 0, 1179, 994, + 0, 1234, 824, + 0, 1298, 398, + 0, 1372, 0, + 0, 1455, 0, + 0, 1547, 0, + 0, 1646, 0, + 0, 1752, 0, + 0, 1863, 0, + 0, 1979, 0, + 0, 2099, 0, + 0, 2222, 0, + 0, 2347, 0, + 0, 2473, 0, + 0, 2601, 0, + 0, 2730, 0, + 0, 2860, 0, + 0, 2990, 0, + 0, 3121, 0, + 0, 3252, 0, + 0, 3384, 0, + 0, 3515, 0, + 0, 3647, 0, + 0, 988, 1302, + 0, 995, 1297, + 0, 1003, 1289, + 0, 1014, 1280, + 0, 1029, 1266, + 0, 1047, 1247, + 0, 1071, 1221, + 0, 1101, 1184, + 0, 1138, 1128, + 0, 1183, 1041, + 0, 1238, 891, + 0, 1301, 553, + 0, 1375, 0, + 0, 1457, 0, + 0, 1549, 0, + 0, 1648, 0, + 0, 1753, 0, + 0, 1864, 0, + 0, 1980, 0, + 0, 2100, 0, + 0, 2222, 0, + 0, 2347, 0, + 0, 2474, 0, + 0, 2601, 0, + 0, 2730, 0, + 0, 2860, 0, + 0, 2990, 0, + 0, 3121, 0, + 0, 3252, 0, + 0, 3384, 0, + 0, 3515, 0, + 0, 3647, 0, + 329, 998, 1335, + 265, 1004, 1330, + 164, 1012, 1323, + 0, 1023, 1314, + 0, 1037, 1301, + 0, 1055, 1284, + 0, 1079, 1260, + 0, 1108, 1226, + 0, 1145, 1175, + 0, 1189, 1098, + 0, 1243, 968, + 0, 1306, 702, + 0, 1379, 0, + 0, 1461, 0, + 0, 1551, 0, + 0, 1650, 0, + 0, 1755, 0, + 0, 1866, 0, + 0, 1981, 0, + 0, 2101, 0, + 0, 2223, 0, + 0, 2347, 0, + 0, 2474, 0, + 0, 2602, 0, + 0, 2731, 0, + 0, 2860, 0, + 0, 2991, 0, + 0, 3121, 0, + 0, 3252, 0, + 0, 3384, 0, + 0, 3515, 0, + 0, 3647, 0, + 770, 1010, 1375, + 747, 1016, 1370, + 715, 1024, 1364, + 667, 1035, 1356, + 594, 1048, 1345, + 474, 1066, 1329, + 239, 1089, 1307, + 0, 1118, 1276, + 0, 1154, 1232, + 0, 1197, 1164, + 0, 1250, 1054, + 0, 1312, 846, + 0, 1384, 171, + 0, 1465, 0, + 0, 1555, 0, + 0, 1653, 0, + 0, 1757, 0, + 0, 1868, 0, + 0, 1983, 0, + 0, 2102, 0, + 0, 2224, 0, + 0, 2348, 0, + 0, 2474, 0, + 0, 2602, 0, + 0, 2731, 0, + 0, 2860, 0, + 0, 2991, 0, + 0, 3121, 0, + 0, 3252, 0, + 0, 3384, 0, + 0, 3515, 0, + 0, 3647, 0, + 1045, 1025, 1424, + 1033, 1031, 1420, + 1016, 1039, 1414, + 992, 1049, 1407, + 957, 1063, 1397, + 907, 1080, 1383, + 830, 1102, 1364, + 702, 1130, 1336, + 440, 1165, 1297, + 0, 1208, 1239, + 0, 1260, 1148, + 0, 1321, 987, + 0, 1391, 606, + 0, 1471, 0, + 0, 1560, 0, + 0, 1657, 0, + 0, 1760, 0, + 0, 1870, 0, + 0, 1985, 0, + 0, 2103, 0, + 0, 2225, 0, + 0, 2349, 0, + 0, 2475, 0, + 0, 2603, 0, + 0, 2731, 0, + 0, 2861, 0, + 0, 2991, 0, + 0, 3122, 0, + 0, 3253, 0, + 0, 3384, 0, + 0, 3515, 0, + 0, 3647, 0, + 1261, 1046, 1482, + 1253, 1051, 1478, + 1242, 1059, 1473, + 1228, 1069, 1467, + 1208, 1082, 1458, + 1180, 1098, 1446, + 1139, 1119, 1429, + 1079, 1146, 1406, + 982, 1180, 1373, + 810, 1222, 1324, + 372, 1272, 1249, + 0, 1331, 1126, + 0, 1400, 879, + 0, 1479, 0, + 0, 1566, 0, + 0, 1662, 0, + 0, 1764, 0, + 0, 1873, 0, + 0, 1987, 0, + 0, 2105, 0, + 0, 2226, 0, + 0, 2350, 0, + 0, 2476, 0, + 0, 2603, 0, + 0, 2732, 0, + 0, 2861, 0, + 0, 2991, 0, + 0, 3122, 0, + 0, 3253, 0, + 0, 3384, 0, + 0, 3515, 0, + 0, 3647, 0, + 1446, 1072, 1550, + 1441, 1077, 1546, + 1434, 1084, 1542, + 1425, 1093, 1537, + 1412, 1105, 1529, + 1394, 1121, 1519, + 1370, 1141, 1505, + 1334, 1167, 1485, + 1282, 1199, 1457, + 1200, 1239, 1417, + 1063, 1288, 1357, + 771, 1345, 1263, + 0, 1412, 1094, + 0, 1489, 678, + 0, 1575, 0, + 0, 1668, 0, + 0, 1770, 0, + 0, 1877, 0, + 0, 1990, 0, + 0, 2108, 0, + 0, 2228, 0, + 0, 2352, 0, + 0, 2477, 0, + 0, 2604, 0, + 0, 2732, 0, + 0, 2862, 0, + 0, 2992, 0, + 0, 3122, 0, + 0, 3253, 0, + 0, 3384, 0, + 0, 3515, 0, + 0, 3647, 0, + 1615, 1104, 1627, + 1611, 1109, 1624, + 1607, 1115, 1621, + 1600, 1124, 1616, + 1592, 1135, 1609, + 1580, 1150, 1601, + 1563, 1169, 1589, + 1540, 1193, 1573, + 1508, 1224, 1550, + 1460, 1262, 1518, + 1388, 1308, 1470, + 1268, 1363, 1398, + 1033, 1428, 1280, + 0, 1502, 1048, + 0, 1585, 57, + 0, 1677, 0, + 0, 1777, 0, + 0, 1883, 0, + 0, 1995, 0, + 0, 2111, 0, + 0, 2231, 0, + 0, 2354, 0, + 0, 2479, 0, + 0, 2605, 0, + 0, 2733, 0, + 0, 2862, 0, + 0, 2992, 0, + 0, 3122, 0, + 0, 3253, 0, + 0, 3384, 0, + 0, 3516, 0, + 0, 3647, 0, + 1772, 1144, 1713, + 1770, 1148, 1711, + 1767, 1154, 1708, + 1762, 1162, 1704, + 1756, 1173, 1699, + 1748, 1186, 1692, + 1737, 1204, 1682, + 1721, 1226, 1669, + 1699, 1255, 1650, + 1669, 1290, 1624, + 1624, 1334, 1588, + 1557, 1386, 1533, + 1448, 1448, 1448, + 1243, 1519, 1301, + 591, 1600, 979, + 0, 1689, 0, + 0, 1786, 0, + 0, 1891, 0, + 0, 2001, 0, + 0, 2116, 0, + 0, 2234, 0, + 0, 2356, 0, + 0, 2481, 0, + 0, 2607, 0, + 0, 2734, 0, + 0, 2863, 0, + 0, 2993, 0, + 0, 3123, 0, + 0, 3254, 0, + 0, 3385, 0, + 0, 3516, 0, + 0, 3647, 0, + 1923, 1192, 1807, + 1921, 1196, 1805, + 1919, 1202, 1803, + 1915, 1209, 1800, + 1911, 1218, 1796, + 1905, 1231, 1790, + 1897, 1247, 1782, + 1886, 1267, 1772, + 1871, 1293, 1757, + 1851, 1326, 1737, + 1821, 1366, 1708, + 1779, 1415, 1667, + 1715, 1473, 1605, + 1613, 1541, 1507, + 1426, 1618, 1329, + 905, 1704, 865, + 0, 1799, 0, + 0, 1900, 0, + 0, 2008, 0, + 0, 2122, 0, + 0, 2239, 0, + 0, 2360, 0, + 0, 2483, 0, + 0, 2609, 0, + 0, 2736, 0, + 0, 2864, 0, + 0, 2994, 0, + 0, 3124, 0, + 0, 3254, 0, + 0, 3385, 0, + 0, 3516, 0, + 0, 3648, 0, + 2068, 1250, 1909, + 2067, 1253, 1908, + 2065, 1258, 1906, + 2063, 1265, 1903, + 2059, 1273, 1900, + 2055, 1284, 1895, + 2049, 1298, 1889, + 2042, 1317, 1881, + 2031, 1340, 1869, + 2017, 1370, 1854, + 1997, 1406, 1832, + 1968, 1451, 1801, + 1927, 1505, 1755, + 1866, 1569, 1687, + 1768, 1641, 1575, + 1592, 1724, 1364, + 1138, 1815, 648, + 0, 1913, 0, + 0, 2018, 0, + 0, 2129, 0, + 0, 2245, 0, + 0, 2364, 0, + 0, 2487, 0, + 0, 2612, 0, + 0, 2738, 0, + 0, 2866, 0, + 0, 2995, 0, + 0, 3124, 0, + 0, 3255, 0, + 0, 3385, 0, + 0, 3516, 0, + 0, 3648, 0, + 2210, 1317, 2017, + 2209, 1320, 2016, + 2207, 1324, 2014, + 2206, 1330, 2012, + 2203, 1337, 2010, + 2200, 1347, 2006, + 2196, 1359, 2001, + 2191, 1375, 1995, + 2183, 1396, 1986, + 2173, 1422, 1974, + 2158, 1455, 1957, + 2139, 1496, 1934, + 2111, 1545, 1900, + 2071, 1603, 1852, + 2011, 1671, 1777, + 1916, 1749, 1653, + 1748, 1835, 1406, + 1333, 1930, 0, + 0, 2032, 0, + 0, 2140, 0, + 0, 2253, 0, + 0, 2371, 0, + 0, 2492, 0, + 0, 2615, 0, + 0, 2741, 0, + 0, 2868, 0, + 0, 2996, 0, + 0, 3126, 0, + 0, 3256, 0, + 0, 3386, 0, + 0, 3517, 0, + 0, 3648, 0, + 2349, 1394, 2130, + 2348, 1396, 2129, + 2347, 1400, 2128, + 2346, 1404, 2127, + 2344, 1411, 2125, + 2342, 1419, 2122, + 2339, 1429, 2118, + 2335, 1443, 2113, + 2329, 1461, 2106, + 2322, 1484, 2097, + 2312, 1513, 2084, + 2298, 1549, 2067, + 2278, 1593, 2042, + 2251, 1646, 2007, + 2211, 1708, 1955, + 2153, 1780, 1875, + 2061, 1861, 1740, + 1898, 1951, 1457, + 1507, 2049, 0, + 0, 2153, 0, + 0, 2264, 0, + 0, 2379, 0, + 0, 2498, 0, + 0, 2620, 0, + 0, 2744, 0, + 0, 2871, 0, + 0, 2998, 0, + 0, 3127, 0, + 0, 3257, 0, + 0, 3387, 0, + 0, 3518, 0, + 0, 3649, 0, + 2486, 1479, 2248, + 2485, 1482, 2247, + 2485, 1484, 2246, + 2484, 1488, 2245, + 2483, 1493, 2243, + 2481, 1500, 2241, + 2479, 1509, 2238, + 2476, 1521, 2234, + 2472, 1536, 2229, + 2466, 1555, 2222, + 2459, 1580, 2213, + 2449, 1611, 2199, + 2435, 1650, 2181, + 2416, 1697, 2155, + 2389, 1753, 2119, + 2350, 1818, 2064, + 2292, 1893, 1980, + 2201, 1978, 1835, + 2042, 2070, 1518, + 1668, 2171, 0, + 0, 2277, 0, + 0, 2389, 0, + 0, 2506, 0, + 0, 2626, 0, + 0, 2749, 0, + 0, 2874, 0, + 0, 3001, 0, + 0, 3129, 0, + 0, 3258, 0, + 0, 3388, 0, + 0, 3519, 0, + 0, 3649, 0, + 2622, 1573, 2368, + 2621, 1575, 2368, + 2621, 1578, 2367, + 2620, 1581, 2366, + 2619, 1585, 2365, + 2618, 1590, 2363, + 2616, 1598, 2361, + 2614, 1607, 2358, + 2611, 1620, 2354, + 2607, 1636, 2349, + 2602, 1657, 2342, + 2595, 1683, 2332, + 2585, 1716, 2318, + 2571, 1757, 2299, + 2552, 1807, 2273, + 2525, 1865, 2235, + 2487, 1934, 2179, + 2430, 2011, 2091, + 2340, 2098, 1937, + 2183, 2193, 1588, + 1820, 2295, 0, + 0, 2403, 0, + 0, 2517, 0, + 0, 2634, 0, + 0, 2755, 0, + 0, 2879, 0, + 0, 3005, 0, + 0, 3132, 0, + 0, 3260, 0, + 0, 3390, 0, + 0, 3520, 0, + 0, 3650, 0, + 2757, 1675, 2492, + 2756, 1676, 2491, + 2756, 1678, 2491, + 2756, 1681, 2490, + 2755, 1684, 2489, + 2754, 1688, 2488, + 2753, 1694, 2486, + 2751, 1702, 2484, + 2749, 1712, 2481, + 2746, 1726, 2477, + 2742, 1743, 2472, + 2737, 1765, 2464, + 2729, 1793, 2454, + 2719, 1827, 2440, + 2706, 1870, 2421, + 2687, 1922, 2394, + 2660, 1982, 2355, + 2622, 2053, 2297, + 2566, 2132, 2206, + 2477, 2221, 2046, + 2322, 2318, 1667, + 1967, 2421, 0, + 0, 2531, 0, + 0, 2645, 0, + 0, 2764, 0, + 0, 2885, 0, + 0, 3010, 0, + 0, 3136, 0, + 0, 3263, 0, + 0, 3392, 0, + 0, 3521, 0, + 0, 3651, 0, + 2891, 1782, 2617, + 2891, 1784, 2617, + 2890, 1785, 2617, + 2890, 1787, 2616, + 2890, 1790, 2615, + 2889, 1793, 2615, + 2888, 1798, 2613, + 2887, 1804, 2612, + 2885, 1812, 2609, + 2883, 1823, 2606, + 2880, 1837, 2602, + 2876, 1855, 2597, + 2871, 1878, 2589, + 2863, 1907, 2579, + 2854, 1943, 2565, + 2840, 1987, 2545, + 2821, 2040, 2518, + 2795, 2103, 2478, + 2757, 2175, 2419, + 2701, 2256, 2325, + 2612, 2346, 2159, + 2459, 2444, 1755, + 2110, 2549, 0, + 0, 2659, 0, + 0, 2775, 0, + 0, 2894, 0, + 0, 3016, 0, + 0, 3140, 0, + 0, 3267, 0, + 0, 3395, 0, + 0, 3523, 0, + 0, 3653, 0, + 3025, 1895, 2745, + 3024, 1896, 2744, + 3024, 1897, 2744, + 3024, 1899, 2744, + 3024, 1901, 2743, + 3023, 1904, 2742, + 3022, 1908, 2741, + 3022, 1912, 2740, + 3020, 1919, 2738, + 3019, 1927, 2736, + 3017, 1938, 2733, + 3014, 1953, 2729, + 3010, 1971, 2723, + 3004, 1995, 2716, + 2997, 2025, 2705, + 2987, 2062, 2691, + 2974, 2108, 2671, + 2955, 2162, 2643, + 2929, 2226, 2603, + 2891, 2299, 2543, + 2835, 2382, 2447, + 2747, 2473, 2277, + 2595, 2572, 1852, + 2250, 2678, 0, + 0, 2789, 0, + 0, 2905, 0, + 0, 3024, 0, + 0, 3147, 0, + 0, 3272, 0, + 0, 3398, 0, + 0, 3526, 0, + 0, 3655, 0, + 3158, 2013, 2873, + 3158, 2013, 2873, + 3158, 2014, 2872, + 3157, 2015, 2872, + 3157, 2017, 2872, + 3157, 2019, 2871, + 3156, 2022, 2871, + 3156, 2026, 2870, + 3155, 2031, 2868, + 3154, 2038, 2867, + 3152, 2046, 2864, + 3150, 2058, 2861, + 3147, 2073, 2857, + 3143, 2092, 2851, + 3138, 2116, 2844, + 3130, 2147, 2833, + 3120, 2185, 2819, + 3107, 2231, 2799, + 3088, 2286, 2770, + 3062, 2351, 2730, + 3024, 2426, 2669, + 2968, 2509, 2572, + 2881, 2601, 2398, + 2730, 2701, 1955, + 2388, 2807, 0, + 0, 2919, 0, + 0, 3035, 0, + 0, 3155, 0, + 0, 3278, 0, + 0, 3403, 0, + 0, 3530, 0, + 0, 3658, 0, + 3291, 2133, 3002, + 3291, 2134, 3002, + 3291, 2135, 3002, + 3291, 2135, 3002, + 3290, 2137, 3001, + 3290, 2138, 3001, + 3290, 2141, 3000, + 3289, 2143, 3000, + 3288, 2147, 2999, + 3288, 2153, 2997, + 3286, 2159, 2996, + 3285, 2168, 2993, + 3283, 2180, 2990, + 3280, 2195, 2986, + 3276, 2215, 2980, + 3270, 2239, 2973, + 3263, 2271, 2962, + 3253, 2309, 2947, + 3240, 2356, 2927, + 3221, 2412, 2899, + 3195, 2478, 2858, + 3157, 2553, 2796, + 3102, 2638, 2698, + 3015, 2730, 2522, + 2864, 2831, 2065, + 2524, 2938, 0, + 0, 3050, 0, + 0, 3166, 0, + 0, 3287, 0, + 0, 3410, 0, + 0, 3535, 0, + 0, 3662, 0, + 3424, 2257, 3132, + 3424, 2257, 3132, + 3423, 2258, 3132, + 3423, 2258, 3132, + 3423, 2259, 3132, + 3423, 2261, 3131, + 3423, 2262, 3131, + 3422, 2264, 3130, + 3422, 2267, 3130, + 3421, 2271, 3129, + 3420, 2277, 3127, + 3419, 2284, 3126, + 3417, 2293, 3123, + 3415, 2304, 3120, + 3412, 2320, 3116, + 3408, 2340, 3110, + 3403, 2365, 3102, + 3396, 2397, 3092, + 3386, 2436, 3077, + 3373, 2483, 3057, + 3354, 2540, 3028, + 3328, 2606, 2987, + 3290, 2682, 2925, + 3235, 2767, 2826, + 3148, 2860, 2647, + 2997, 2961, 2179, + 2659, 3068, 0, + 0, 3181, 0, + 0, 3298, 0, + 0, 3418, 0, + 0, 3541, 0, + 0, 3666, 0, + 3556, 2382, 3263, + 3556, 2382, 3263, + 3556, 2383, 3262, + 3556, 2383, 3262, + 3556, 2384, 3262, + 3556, 2385, 3262, + 3556, 2386, 3262, + 3555, 2388, 3261, + 3555, 2390, 3261, + 3554, 2393, 3260, + 3554, 2397, 3259, + 3553, 2403, 3258, + 3552, 2410, 3256, + 3550, 2419, 3254, + 3548, 2431, 3250, + 3545, 2446, 3246, + 3541, 2466, 3240, + 3536, 2492, 3233, + 3529, 2524, 3222, + 3519, 2564, 3207, + 3505, 2612, 3187, + 3487, 2669, 3158, + 3461, 2736, 3117, + 3423, 2812, 3054, + 3368, 2897, 2955, + 3281, 2991, 2775, + 3131, 3092, 2297, + 2794, 3199, 0, + 0, 3312, 0, + 0, 3429, 0, + 0, 3550, 0, + 0, 3673, 0, + 3689, 2509, 3394, + 3689, 2509, 3393, + 3689, 2510, 3393, + 3689, 2510, 3393, + 3688, 2511, 3393, + 3688, 2511, 3393, + 3688, 2512, 3393, + 3688, 2514, 3392, + 3688, 2515, 3392, + 3687, 2518, 3392, + 3687, 2521, 3391, + 3686, 2525, 3390, + 3685, 2530, 3389, + 3684, 2537, 3387, + 3682, 2546, 3384, + 3680, 2559, 3381, + 3677, 2574, 3377, + 3673, 2595, 3371, + 3668, 2620, 3363, + 3661, 2653, 3353, + 3651, 2692, 3338, + 3638, 2741, 3318, + 3619, 2798, 3289, + 3593, 2865, 3247, + 3556, 2942, 3184, + 3500, 3028, 3084, + 3413, 3122, 2903, + 3264, 3223, 2419, + 2928, 3331, 0, + 0, 3443, 0, + 0, 3561, 0, + 0, 3681, 0, + 3821, 2637, 3525, + 3821, 2638, 3525, + 3821, 2638, 3525, + 3821, 2638, 3525, + 3821, 2639, 3524, + 3821, 2639, 3524, + 3821, 2640, 3524, + 3821, 2641, 3524, + 3820, 2642, 3524, + 3820, 2644, 3523, + 3820, 2646, 3523, + 3819, 2649, 3522, + 3818, 2653, 3521, + 3818, 2659, 3520, + 3816, 2666, 3518, + 3815, 2675, 3516, + 3813, 2687, 3512, + 3810, 2703, 3508, + 3806, 2724, 3502, + 3801, 2750, 3494, + 3793, 2782, 3484, + 3784, 2822, 3469, + 3770, 2871, 3448, + 3752, 2929, 3420, + 3725, 2996, 3378, + 3688, 3073, 3315, + 3633, 3159, 3215, + 3546, 3253, 3032, + 3396, 3354, 2543, + 3061, 3462, 0, + 0, 3575, 0, + 0, 3692, 0, + 3953, 2767, 3656, + 3953, 2767, 3656, + 3953, 2767, 3656, + 3953, 2767, 3656, + 3953, 2768, 3656, + 3953, 2768, 3656, + 3953, 2769, 3656, + 3953, 2769, 3656, + 3953, 2770, 3655, + 3953, 2772, 3655, + 3952, 2773, 3655, + 3952, 2776, 3654, + 3951, 2779, 3653, + 3951, 2783, 3652, + 3950, 2788, 3651, + 3949, 2795, 3649, + 3947, 2805, 3647, + 3945, 2817, 3644, + 3942, 2833, 3639, + 3938, 2854, 3634, + 3933, 2880, 3626, + 3926, 2912, 3615, + 3916, 2952, 3600, + 3902, 3001, 3580, + 3884, 3059, 3551, + 3858, 3127, 3509, + 3820, 3204, 3446, + 3765, 3290, 3345, + 3678, 3384, 3162, + 3529, 3486, 2669, + 3194, 3594, 0, + 0, 3707, 0, + 4086, 2897, 3788, + 4086, 2897, 3788, + 4086, 2897, 3788, + 4086, 2897, 3788, + 4086, 2897, 3788, + 4085, 2898, 3788, + 4085, 2898, 3787, + 4085, 2899, 3787, + 4085, 2899, 3787, + 4085, 2900, 3787, + 4085, 2902, 3787, + 4085, 2903, 3786, + 4084, 2906, 3786, + 4084, 2909, 3785, + 4083, 2913, 3784, + 4082, 2918, 3783, + 4081, 2926, 3781, + 4079, 2935, 3779, + 4077, 2947, 3775, + 4074, 2963, 3771, + 4070, 2984, 3765, + 4065, 3010, 3757, + 4058, 3043, 3747, + 4048, 3083, 3732, + 4035, 3132, 3711, + 4016, 3190, 3682, + 3990, 3258, 3640, + 3953, 3335, 3577, + 3897, 3421, 3476, + 3811, 3516, 3293, + 3661, 3617, 2796, + 3327, 3725, 0, + 4095, 3027, 3919, + 4095, 3027, 3919, + 4095, 3027, 3919, + 4095, 3027, 3919, + 4095, 3028, 3919, + 4095, 3028, 3919, + 4095, 3028, 3919, + 4095, 3029, 3919, + 4095, 3029, 3919, + 4095, 3030, 3919, + 4095, 3031, 3919, + 4095, 3032, 3918, + 4095, 3034, 3918, + 4095, 3036, 3917, + 4095, 3039, 3917, + 4095, 3044, 3916, + 4095, 3049, 3914, + 4095, 3056, 3913, + 4095, 3066, 3910, + 4095, 3078, 3907, + 4095, 3094, 3903, + 4095, 3115, 3897, + 4095, 3141, 3889, + 4095, 3174, 3878, + 4095, 3214, 3863, + 4095, 3263, 3843, + 4095, 3321, 3814, + 4095, 3389, 3772, + 4085, 3467, 3709, + 4030, 3553, 3608, + 3943, 3647, 3424, + 3794, 3749, 2925, + 4095, 3158, 4051, + 4095, 3158, 4051, + 4095, 3158, 4051, + 4095, 3158, 4051, + 4095, 3158, 4051, + 4095, 3159, 4051, + 4095, 3159, 4051, + 4095, 3159, 4051, + 4095, 3160, 4051, + 4095, 3160, 4051, + 4095, 3161, 4051, + 4095, 3162, 4050, + 4095, 3163, 4050, + 4095, 3165, 4050, + 4095, 3167, 4049, + 4095, 3170, 4048, + 4095, 3175, 4047, + 4095, 3180, 4046, + 4095, 3187, 4044, + 4095, 3197, 4042, + 4095, 3209, 4039, + 4095, 3225, 4035, + 4095, 3246, 4029, + 4095, 3272, 4021, + 4095, 3305, 4010, + 4095, 3346, 3995, + 4095, 3395, 3975, + 4095, 3453, 3946, + 4095, 3521, 3903, + 4095, 3598, 3840, + 4095, 3685, 3739, + 4075, 3779, 3555, + 0, 1092, 1347, + 0, 1097, 1342, + 0, 1104, 1336, + 0, 1112, 1327, + 0, 1124, 1315, + 0, 1139, 1298, + 0, 1159, 1275, + 0, 1183, 1242, + 0, 1215, 1193, + 0, 1253, 1119, + 0, 1300, 996, + 0, 1356, 751, + 0, 1422, 0, + 0, 1497, 0, + 0, 1581, 0, + 0, 1674, 0, + 0, 1774, 0, + 0, 1881, 0, + 0, 1993, 0, + 0, 2110, 0, + 0, 2230, 0, + 0, 2353, 0, + 0, 2478, 0, + 0, 2605, 0, + 0, 2733, 0, + 0, 2862, 0, + 0, 2992, 0, + 0, 3122, 0, + 0, 3253, 0, + 0, 3384, 0, + 0, 3516, 0, + 0, 3647, 0, + 0, 1093, 1354, + 0, 1098, 1350, + 0, 1105, 1343, + 0, 1114, 1335, + 0, 1126, 1323, + 0, 1141, 1306, + 0, 1160, 1283, + 0, 1185, 1251, + 0, 1216, 1203, + 0, 1254, 1131, + 0, 1301, 1011, + 0, 1357, 777, + 0, 1423, 0, + 0, 1498, 0, + 0, 1582, 0, + 0, 1674, 0, + 0, 1775, 0, + 0, 1881, 0, + 0, 1993, 0, + 0, 2110, 0, + 0, 2230, 0, + 0, 2353, 0, + 0, 2478, 0, + 0, 2605, 0, + 0, 2733, 0, + 0, 2862, 0, + 0, 2992, 0, + 0, 3122, 0, + 0, 3253, 0, + 0, 3384, 0, + 0, 3516, 0, + 0, 3647, 0, + 0, 1096, 1364, + 0, 1101, 1359, + 0, 1107, 1353, + 0, 1116, 1344, + 0, 1128, 1333, + 0, 1143, 1317, + 0, 1162, 1294, + 0, 1187, 1262, + 0, 1218, 1216, + 0, 1256, 1146, + 0, 1303, 1031, + 0, 1359, 809, + 0, 1424, 0, + 0, 1499, 0, + 0, 1583, 0, + 0, 1675, 0, + 0, 1775, 0, + 0, 1882, 0, + 0, 1994, 0, + 0, 2110, 0, + 0, 2230, 0, + 0, 2353, 0, + 0, 2478, 0, + 0, 2605, 0, + 0, 2733, 0, + 0, 2862, 0, + 0, 2992, 0, + 0, 3122, 0, + 0, 3253, 0, + 0, 3384, 0, + 0, 3516, 0, + 0, 3647, 0, + 0, 1099, 1376, + 0, 1104, 1371, + 0, 1110, 1365, + 0, 1119, 1357, + 0, 1131, 1346, + 0, 1146, 1330, + 0, 1165, 1308, + 0, 1189, 1278, + 0, 1220, 1233, + 0, 1258, 1165, + 0, 1305, 1056, + 0, 1360, 850, + 0, 1425, 185, + 0, 1500, 0, + 0, 1584, 0, + 0, 1676, 0, + 0, 1776, 0, + 0, 1882, 0, + 0, 1994, 0, + 0, 2110, 0, + 0, 2230, 0, + 0, 2353, 0, + 0, 2478, 0, + 0, 2605, 0, + 0, 2733, 0, + 0, 2862, 0, + 0, 2992, 0, + 0, 3122, 0, + 0, 3253, 0, + 0, 3384, 0, + 0, 3516, 0, + 0, 3647, 0, + 0, 1103, 1392, + 0, 1108, 1387, + 0, 1114, 1381, + 0, 1123, 1373, + 0, 1135, 1363, + 0, 1149, 1348, + 0, 1168, 1327, + 0, 1193, 1297, + 0, 1223, 1255, + 0, 1261, 1190, + 0, 1307, 1087, + 0, 1363, 898, + 0, 1427, 365, + 0, 1502, 0, + 0, 1585, 0, + 0, 1677, 0, + 0, 1777, 0, + 0, 1883, 0, + 0, 1995, 0, + 0, 2111, 0, + 0, 2231, 0, + 0, 2354, 0, + 0, 2479, 0, + 0, 2605, 0, + 0, 2733, 0, + 0, 2862, 0, + 0, 2992, 0, + 0, 3122, 0, + 0, 3253, 0, + 0, 3384, 0, + 0, 3516, 0, + 0, 3647, 0, + 0, 1108, 1412, + 0, 1113, 1408, + 0, 1120, 1402, + 0, 1128, 1395, + 0, 1140, 1384, + 0, 1154, 1370, + 0, 1173, 1350, + 0, 1197, 1322, + 0, 1227, 1282, + 0, 1265, 1222, + 0, 1311, 1126, + 0, 1366, 956, + 0, 1430, 530, + 0, 1504, 0, + 0, 1587, 0, + 0, 1679, 0, + 0, 1778, 0, + 0, 1884, 0, + 0, 1995, 0, + 0, 2112, 0, + 0, 2231, 0, + 0, 2354, 0, + 0, 2479, 0, + 0, 2605, 0, + 0, 2733, 0, + 0, 2862, 0, + 0, 2992, 0, + 0, 3122, 0, + 0, 3253, 0, + 0, 3384, 0, + 0, 3516, 0, + 0, 3647, 0, + 0, 1115, 1438, + 0, 1120, 1434, + 0, 1127, 1429, + 0, 1135, 1421, + 0, 1146, 1412, + 0, 1161, 1398, + 0, 1179, 1380, + 0, 1203, 1353, + 0, 1233, 1316, + 0, 1270, 1260, + 0, 1315, 1173, + 0, 1370, 1023, + 0, 1434, 686, + 0, 1507, 0, + 0, 1590, 0, + 0, 1681, 0, + 0, 1780, 0, + 0, 1885, 0, + 0, 1996, 0, + 0, 2112, 0, + 0, 2232, 0, + 0, 2354, 0, + 0, 2479, 0, + 0, 2606, 0, + 0, 2734, 0, + 0, 2862, 0, + 0, 2992, 0, + 0, 3123, 0, + 0, 3253, 0, + 0, 3384, 0, + 0, 3516, 0, + 0, 3647, 0, + 503, 1125, 1470, + 461, 1130, 1467, + 397, 1136, 1462, + 296, 1144, 1455, + 111, 1155, 1446, + 0, 1169, 1433, + 0, 1188, 1416, + 0, 1211, 1392, + 0, 1240, 1358, + 0, 1277, 1307, + 0, 1322, 1230, + 0, 1375, 1100, + 0, 1438, 834, + 0, 1511, 0, + 0, 1593, 0, + 0, 1683, 0, + 0, 1782, 0, + 0, 1887, 0, + 0, 1998, 0, + 0, 2113, 0, + 0, 2233, 0, + 0, 2355, 0, + 0, 2480, 0, + 0, 2606, 0, + 0, 2734, 0, + 0, 2863, 0, + 0, 2992, 0, + 0, 3123, 0, + 0, 3253, 0, + 0, 3384, 0, + 0, 3516, 0, + 0, 3647, 0, + 919, 1137, 1510, + 902, 1142, 1507, + 879, 1148, 1502, + 847, 1156, 1496, + 799, 1167, 1488, + 726, 1180, 1477, + 606, 1198, 1461, + 371, 1221, 1439, + 0, 1250, 1409, + 0, 1286, 1364, + 0, 1330, 1296, + 0, 1382, 1186, + 0, 1444, 978, + 0, 1516, 303, + 0, 1597, 0, + 0, 1687, 0, + 0, 1785, 0, + 0, 1889, 0, + 0, 2000, 0, + 0, 2115, 0, + 0, 2234, 0, + 0, 2356, 0, + 0, 2480, 0, + 0, 2606, 0, + 0, 2734, 0, + 0, 2863, 0, + 0, 2993, 0, + 0, 3123, 0, + 0, 3253, 0, + 0, 3385, 0, + 0, 3516, 0, + 0, 3647, 0, + 1186, 1153, 1559, + 1177, 1158, 1556, + 1165, 1164, 1552, + 1148, 1171, 1546, + 1124, 1182, 1539, + 1090, 1195, 1529, + 1039, 1212, 1515, + 962, 1234, 1496, + 834, 1262, 1468, + 572, 1297, 1429, + 0, 1340, 1371, + 0, 1392, 1280, + 0, 1453, 1119, + 0, 1523, 738, + 0, 1603, 0, + 0, 1692, 0, + 0, 1789, 0, + 0, 1892, 0, + 0, 2002, 0, + 0, 2117, 0, + 0, 2235, 0, + 0, 2357, 0, + 0, 2481, 0, + 0, 2607, 0, + 0, 2735, 0, + 0, 2863, 0, + 0, 2993, 0, + 0, 3123, 0, + 0, 3254, 0, + 0, 3385, 0, + 0, 3516, 0, + 0, 3647, 0, + 1398, 1174, 1617, + 1393, 1178, 1614, + 1385, 1184, 1610, + 1375, 1191, 1606, + 1360, 1201, 1599, + 1340, 1214, 1590, + 1312, 1230, 1578, + 1271, 1251, 1561, + 1211, 1278, 1538, + 1114, 1312, 1505, + 942, 1354, 1456, + 504, 1404, 1382, + 0, 1463, 1258, + 0, 1532, 1012, + 0, 1611, 0, + 0, 1698, 0, + 0, 1794, 0, + 0, 1896, 0, + 0, 2005, 0, + 0, 2119, 0, + 0, 2237, 0, + 0, 2358, 0, + 0, 2482, 0, + 0, 2608, 0, + 0, 2735, 0, + 0, 2864, 0, + 0, 2993, 0, + 0, 3123, 0, + 0, 3254, 0, + 0, 3385, 0, + 0, 3516, 0, + 0, 3647, 0, + 1582, 1200, 1684, + 1579, 1204, 1682, + 1573, 1209, 1679, + 1567, 1216, 1674, + 1557, 1225, 1669, + 1544, 1237, 1661, + 1527, 1253, 1651, + 1502, 1273, 1637, + 1466, 1299, 1617, + 1414, 1331, 1589, + 1332, 1371, 1549, + 1195, 1420, 1489, + 903, 1477, 1395, + 0, 1544, 1226, + 0, 1621, 810, + 0, 1707, 0, + 0, 1801, 0, + 0, 1902, 0, + 0, 2010, 0, + 0, 2123, 0, + 0, 2240, 0, + 0, 2360, 0, + 0, 2484, 0, + 0, 2609, 0, + 0, 2736, 0, + 0, 2864, 0, + 0, 2994, 0, + 0, 3124, 0, + 0, 3254, 0, + 0, 3385, 0, + 0, 3516, 0, + 0, 3648, 0, + 1750, 1232, 1761, + 1747, 1236, 1759, + 1744, 1241, 1756, + 1739, 1248, 1753, + 1732, 1256, 1748, + 1724, 1268, 1742, + 1712, 1282, 1733, + 1695, 1301, 1721, + 1672, 1326, 1705, + 1640, 1356, 1682, + 1592, 1394, 1650, + 1520, 1440, 1602, + 1400, 1495, 1530, + 1165, 1560, 1412, + 102, 1634, 1180, + 0, 1718, 189, + 0, 1809, 0, + 0, 1909, 0, + 0, 2015, 0, + 0, 2127, 0, + 0, 2243, 0, + 0, 2363, 0, + 0, 2486, 0, + 0, 2611, 0, + 0, 2737, 0, + 0, 2865, 0, + 0, 2994, 0, + 0, 3124, 0, + 0, 3254, 0, + 0, 3385, 0, + 0, 3516, 0, + 0, 3648, 0, + 1906, 1272, 1846, + 1905, 1276, 1845, + 1902, 1280, 1843, + 1899, 1286, 1840, + 1894, 1294, 1836, + 1888, 1305, 1831, + 1880, 1319, 1824, + 1869, 1336, 1814, + 1853, 1359, 1801, + 1831, 1387, 1782, + 1801, 1422, 1757, + 1756, 1466, 1720, + 1689, 1518, 1665, + 1580, 1580, 1580, + 1375, 1651, 1434, + 723, 1732, 1111, + 0, 1821, 0, + 0, 1918, 0, + 0, 2023, 0, + 0, 2133, 0, + 0, 2248, 0, + 0, 2366, 0, + 0, 2488, 0, + 0, 2613, 0, + 0, 2739, 0, + 0, 2866, 0, + 0, 2995, 0, + 0, 3125, 0, + 0, 3255, 0, + 0, 3386, 0, + 0, 3517, 0, + 0, 3648, 0, + 2056, 1321, 1941, + 2055, 1324, 1939, + 2053, 1328, 1938, + 2051, 1334, 1935, + 2047, 1341, 1932, + 2043, 1350, 1928, + 2037, 1363, 1922, + 2029, 1379, 1914, + 2018, 1399, 1904, + 2003, 1425, 1889, + 1983, 1458, 1869, + 1953, 1498, 1840, + 1911, 1547, 1799, + 1847, 1605, 1737, + 1745, 1673, 1639, + 1558, 1750, 1461, + 1037, 1836, 997, + 0, 1931, 0, + 0, 2032, 0, + 0, 2140, 0, + 0, 2254, 0, + 0, 2371, 0, + 0, 2492, 0, + 0, 2615, 0, + 0, 2741, 0, + 0, 2868, 0, + 0, 2996, 0, + 0, 3126, 0, + 0, 3256, 0, + 0, 3386, 0, + 0, 3517, 0, + 0, 3648, 0, + 2201, 1379, 2042, + 2200, 1382, 2041, + 2199, 1386, 2040, + 2197, 1390, 2038, + 2195, 1397, 2035, + 2191, 1405, 2032, + 2187, 1416, 2027, + 2182, 1430, 2021, + 2174, 1449, 2013, + 2163, 1472, 2001, + 2149, 1502, 1986, + 2129, 1538, 1964, + 2100, 1583, 1933, + 2059, 1637, 1887, + 1998, 1701, 1819, + 1900, 1774, 1707, + 1724, 1856, 1496, + 1270, 1947, 780, + 0, 2045, 0, + 0, 2151, 0, + 0, 2262, 0, + 0, 2377, 0, + 0, 2497, 0, + 0, 2619, 0, + 0, 2744, 0, + 0, 2870, 0, + 0, 2998, 0, + 0, 3127, 0, + 0, 3256, 0, + 0, 3387, 0, + 0, 3518, 0, + 0, 3649, 0, + 2342, 1447, 2150, + 2342, 1449, 2149, + 2341, 1452, 2148, + 2339, 1456, 2146, + 2338, 1462, 2145, + 2335, 1469, 2142, + 2332, 1479, 2138, + 2328, 1491, 2133, + 2323, 1507, 2127, + 2315, 1528, 2118, + 2305, 1554, 2106, + 2290, 1587, 2089, + 2271, 1628, 2066, + 2243, 1677, 2032, + 2203, 1735, 1984, + 2143, 1803, 1909, + 2049, 1881, 1785, + 1880, 1967, 1538, + 1465, 2062, 3, + 0, 2164, 0, + 0, 2272, 0, + 0, 2385, 0, + 0, 2503, 0, + 0, 2624, 0, + 0, 2747, 0, + 0, 2873, 0, + 0, 3000, 0, + 0, 3128, 0, + 0, 3258, 0, + 0, 3388, 0, + 0, 3518, 0, + 0, 3649, 0, + 2481, 1524, 2263, + 2481, 1526, 2262, + 2480, 1528, 2261, + 2479, 1532, 2260, + 2478, 1537, 2259, + 2476, 1543, 2257, + 2474, 1551, 2254, + 2471, 1561, 2250, + 2467, 1575, 2245, + 2461, 1593, 2238, + 2454, 1616, 2229, + 2444, 1645, 2216, + 2430, 1681, 2199, + 2410, 1725, 2174, + 2383, 1778, 2139, + 2344, 1840, 2087, + 2285, 1912, 2007, + 2193, 1993, 1872, + 2030, 2083, 1589, + 1639, 2181, 0, + 0, 2285, 0, + 0, 2396, 0, + 0, 2511, 0, + 0, 2630, 0, + 0, 2752, 0, + 0, 2876, 0, + 0, 3003, 0, + 0, 3130, 0, + 0, 3259, 0, + 0, 3389, 0, + 0, 3519, 0, + 0, 3650, 0, + 2618, 1610, 2380, + 2618, 1611, 2380, + 2617, 1614, 2379, + 2617, 1617, 2378, + 2616, 1620, 2377, + 2615, 1626, 2375, + 2613, 1632, 2373, + 2611, 1641, 2370, + 2608, 1653, 2367, + 2604, 1668, 2361, + 2598, 1687, 2354, + 2591, 1712, 2345, + 2581, 1743, 2331, + 2567, 1782, 2313, + 2548, 1829, 2287, + 2521, 1885, 2251, + 2482, 1950, 2197, + 2424, 2026, 2112, + 2333, 2110, 1967, + 2174, 2202, 1650, + 1800, 2303, 0, + 0, 2409, 0, + 0, 2522, 0, + 0, 2638, 0, + 0, 2758, 0, + 0, 2881, 0, + 0, 3006, 0, + 0, 3133, 0, + 0, 3261, 0, + 0, 3390, 0, + 0, 3520, 0, + 0, 3651, 0, + 2754, 1704, 2501, + 2754, 1705, 2500, + 2754, 1707, 2500, + 2753, 1710, 2499, + 2752, 1713, 2498, + 2751, 1717, 2497, + 2750, 1723, 2496, + 2749, 1730, 2493, + 2746, 1739, 2490, + 2743, 1752, 2486, + 2739, 1768, 2481, + 2734, 1789, 2474, + 2727, 1815, 2464, + 2717, 1849, 2450, + 2703, 1889, 2432, + 2684, 1939, 2405, + 2657, 1997, 2367, + 2619, 2066, 2311, + 2562, 2143, 2223, + 2472, 2230, 2069, + 2315, 2325, 1720, + 1952, 2427, 0, + 0, 2535, 0, + 0, 2649, 0, + 0, 2767, 0, + 0, 2888, 0, + 0, 3011, 0, + 0, 3137, 0, + 0, 3264, 0, + 0, 3392, 0, + 0, 3522, 0, + 0, 3652, 0, + 2889, 1806, 2624, + 2889, 1807, 2624, + 2889, 1808, 2624, + 2888, 1810, 2623, + 2888, 1813, 2622, + 2887, 1816, 2621, + 2886, 1821, 2620, + 2885, 1826, 2619, + 2883, 1834, 2616, + 2881, 1844, 2613, + 2878, 1858, 2609, + 2874, 1875, 2604, + 2869, 1897, 2596, + 2861, 1925, 2586, + 2852, 1959, 2572, + 2838, 2002, 2553, + 2819, 2054, 2526, + 2792, 2114, 2487, + 2754, 2185, 2429, + 2698, 2265, 2338, + 2609, 2353, 2178, + 2454, 2450, 1799, + 2099, 2553, 0, + 0, 2663, 0, + 0, 2777, 0, + 0, 2896, 0, + 0, 3018, 0, + 0, 3142, 0, + 0, 3268, 0, + 0, 3395, 0, + 0, 3524, 0, + 0, 3653, 0, + 3023, 1914, 2750, + 3023, 1915, 2749, + 3023, 1916, 2749, + 3023, 1917, 2749, + 3022, 1919, 2748, + 3022, 1922, 2748, + 3021, 1925, 2747, + 3020, 1930, 2745, + 3019, 1936, 2744, + 3017, 1944, 2741, + 3015, 1955, 2738, + 3012, 1969, 2734, + 3008, 1987, 2729, + 3003, 2010, 2721, + 2996, 2039, 2711, + 2986, 2075, 2697, + 2972, 2119, 2677, + 2953, 2172, 2650, + 2927, 2235, 2610, + 2889, 2307, 2551, + 2833, 2388, 2457, + 2744, 2478, 2291, + 2591, 2576, 1888, + 2242, 2681, 0, + 0, 2792, 0, + 0, 2907, 0, + 0, 3026, 0, + 0, 3148, 0, + 0, 3273, 0, + 0, 3399, 0, + 0, 3527, 0, + 0, 3655, 0, + 3157, 2027, 2877, + 3157, 2028, 2877, + 3157, 2028, 2876, + 3156, 2030, 2876, + 3156, 2031, 2876, + 3156, 2033, 2875, + 3155, 2036, 2874, + 3155, 2040, 2874, + 3154, 2045, 2872, + 3152, 2051, 2871, + 3151, 2059, 2868, + 3149, 2071, 2865, + 3146, 2085, 2861, + 3142, 2104, 2855, + 3136, 2127, 2848, + 3129, 2157, 2837, + 3119, 2194, 2823, + 3106, 2240, 2803, + 3087, 2294, 2775, + 3061, 2358, 2735, + 3023, 2431, 2675, + 2967, 2514, 2579, + 2879, 2605, 2409, + 2727, 2704, 1984, + 2382, 2810, 0, + 0, 2921, 0, + 0, 3037, 0, + 0, 3157, 0, + 0, 3279, 0, + 0, 3404, 0, + 0, 3530, 0, + 0, 3658, 0, + 3290, 2144, 3005, + 3290, 2145, 3005, + 3290, 2145, 3005, + 3290, 2146, 3005, + 3290, 2148, 3004, + 3289, 2149, 3004, + 3289, 2151, 3003, + 3288, 2154, 3003, + 3288, 2158, 3002, + 3287, 2163, 3000, + 3286, 2170, 2999, + 3284, 2178, 2996, + 3282, 2190, 2993, + 3279, 2205, 2989, + 3275, 2224, 2983, + 3270, 2248, 2976, + 3262, 2279, 2965, + 3253, 2317, 2951, + 3239, 2363, 2931, + 3220, 2418, 2902, + 3194, 2483, 2862, + 3156, 2558, 2801, + 3101, 2641, 2704, + 3013, 2733, 2530, + 2862, 2833, 2087, + 2520, 2939, 0, + 0, 3051, 0, + 0, 3168, 0, + 0, 3287, 0, + 0, 3410, 0, + 0, 3535, 0, + 0, 3662, 0, + 3423, 2265, 3134, + 3423, 2265, 3134, + 3423, 2266, 3134, + 3423, 2267, 3134, + 3423, 2268, 3134, + 3422, 2269, 3133, + 3422, 2270, 3133, + 3422, 2273, 3132, + 3421, 2276, 3132, + 3421, 2279, 3131, + 3420, 2285, 3130, + 3418, 2291, 3128, + 3417, 2300, 3125, + 3415, 2312, 3122, + 3412, 2327, 3118, + 3408, 2347, 3112, + 3403, 2371, 3105, + 3395, 2403, 3094, + 3386, 2441, 3080, + 3372, 2488, 3059, + 3353, 2545, 3031, + 3327, 2610, 2990, + 3290, 2685, 2928, + 3234, 2770, 2830, + 3147, 2863, 2654, + 2996, 2963, 2197, + 2656, 3070, 0, + 0, 3182, 0, + 0, 3298, 0, + 0, 3419, 0, + 0, 3542, 0, + 0, 3667, 0, + 3556, 2388, 3264, + 3556, 2389, 3264, + 3556, 2389, 3264, + 3556, 2390, 3264, + 3555, 2390, 3264, + 3555, 2391, 3264, + 3555, 2393, 3263, + 3555, 2394, 3263, + 3554, 2397, 3262, + 3554, 2400, 3262, + 3553, 2403, 3261, + 3552, 2409, 3259, + 3551, 2416, 3258, + 3550, 2425, 3255, + 3547, 2437, 3252, + 3544, 2452, 3248, + 3541, 2472, 3242, + 3535, 2497, 3234, + 3528, 2529, 3224, + 3518, 2568, 3209, + 3505, 2615, 3189, + 3486, 2672, 3160, + 3460, 2738, 3119, + 3422, 2814, 3057, + 3367, 2899, 2958, + 3280, 2992, 2780, + 3130, 3093, 2311, + 2791, 3200, 0, + 0, 3313, 0, + 0, 3430, 0, + 0, 3550, 0, + 0, 3673, 0, + 3688, 2514, 3395, + 3688, 2514, 3395, + 3688, 2515, 3395, + 3688, 2515, 3395, + 3688, 2515, 3394, + 3688, 2516, 3394, + 3688, 2517, 3394, + 3688, 2518, 3394, + 3687, 2520, 3393, + 3687, 2522, 3393, + 3686, 2525, 3392, + 3686, 2529, 3391, + 3685, 2535, 3390, + 3684, 2542, 3388, + 3682, 2551, 3386, + 3680, 2563, 3383, + 3677, 2579, 3378, + 3673, 2599, 3373, + 3668, 2624, 3365, + 3661, 2656, 3354, + 3651, 2696, 3339, + 3637, 2744, 3319, + 3619, 2801, 3290, + 3593, 2868, 3249, + 3555, 2944, 3186, + 3500, 3029, 3087, + 3413, 3123, 2907, + 3263, 3224, 2429, + 2926, 3331, 0, + 0, 3444, 0, + 0, 3561, 0, + 0, 3682, 0, + 3821, 2641, 3526, + 3821, 2641, 3526, + 3821, 2641, 3526, + 3821, 2642, 3526, + 3821, 2642, 3525, + 3821, 2643, 3525, + 3820, 2643, 3525, + 3820, 2644, 3525, + 3820, 2646, 3525, + 3820, 2647, 3524, + 3819, 2650, 3524, + 3819, 2653, 3523, + 3818, 2657, 3522, + 3817, 2662, 3521, + 3816, 2669, 3519, + 3815, 2679, 3517, + 3812, 2691, 3513, + 3809, 2706, 3509, + 3806, 2727, 3503, + 3800, 2752, 3495, + 3793, 2785, 3485, + 3783, 2825, 3470, + 3770, 2873, 3450, + 3751, 2930, 3421, + 3725, 2998, 3379, + 3688, 3074, 3316, + 3632, 3160, 3216, + 3546, 3254, 3035, + 3396, 3355, 2551, + 3060, 3463, 0, + 0, 3576, 0, + 0, 3693, 0, + 3953, 2769, 3657, + 3953, 2770, 3657, + 3953, 2770, 3657, + 3953, 2770, 3657, + 3953, 2770, 3657, + 3953, 2771, 3657, + 3953, 2771, 3656, + 3953, 2772, 3656, + 3953, 2773, 3656, + 3952, 2774, 3656, + 3952, 2776, 3655, + 3952, 2778, 3655, + 3951, 2781, 3654, + 3951, 2785, 3653, + 3950, 2791, 3652, + 3948, 2798, 3650, + 3947, 2807, 3648, + 3945, 2820, 3644, + 3942, 2835, 3640, + 3938, 2856, 3634, + 3933, 2882, 3627, + 3925, 2914, 3616, + 3916, 2954, 3601, + 3902, 3003, 3581, + 3884, 3061, 3552, + 3858, 3128, 3510, + 3820, 3205, 3447, + 3765, 3291, 3347, + 3678, 3385, 3165, + 3528, 3486, 2675, + 3193, 3594, 0, + 0, 3707, 0, + 4085, 2899, 3788, + 4085, 2899, 3788, + 4085, 2899, 3788, + 4085, 2899, 3788, + 4085, 2899, 3788, + 4085, 2900, 3788, + 4085, 2900, 3788, + 4085, 2901, 3788, + 4085, 2901, 3788, + 4085, 2902, 3787, + 4085, 2904, 3787, + 4084, 2905, 3787, + 4084, 2908, 3786, + 4084, 2911, 3785, + 4083, 2915, 3784, + 4082, 2920, 3783, + 4081, 2928, 3781, + 4079, 2937, 3779, + 4077, 2949, 3776, + 4074, 2965, 3772, + 4070, 2986, 3766, + 4065, 3012, 3758, + 4058, 3044, 3747, + 4048, 3084, 3732, + 4035, 3133, 3712, + 4016, 3191, 3683, + 3990, 3259, 3641, + 3952, 3336, 3578, + 3897, 3422, 3477, + 3811, 3516, 3295, + 3661, 3618, 2801, + 3326, 3726, 0, + 4095, 3029, 3920, + 4095, 3029, 3920, + 4095, 3029, 3920, + 4095, 3029, 3920, + 4095, 3029, 3920, + 4095, 3029, 3920, + 4095, 3030, 3920, + 4095, 3030, 3920, + 4095, 3031, 3919, + 4095, 3031, 3919, + 4095, 3032, 3919, + 4095, 3034, 3919, + 4095, 3035, 3918, + 4095, 3038, 3918, + 4095, 3041, 3917, + 4095, 3045, 3916, + 4095, 3050, 3915, + 4095, 3058, 3913, + 4095, 3067, 3911, + 4095, 3079, 3907, + 4095, 3095, 3903, + 4095, 3116, 3897, + 4095, 3142, 3889, + 4095, 3175, 3879, + 4095, 3215, 3864, + 4095, 3264, 3843, + 4095, 3322, 3814, + 4095, 3390, 3772, + 4085, 3467, 3709, + 4029, 3553, 3609, + 3943, 3648, 3425, + 3793, 3750, 2928, + 4095, 3159, 4052, + 4095, 3159, 4052, + 4095, 3159, 4052, + 4095, 3159, 4052, + 4095, 3160, 4052, + 4095, 3160, 4051, + 4095, 3160, 4051, + 4095, 3160, 4051, + 4095, 3161, 4051, + 4095, 3161, 4051, + 4095, 3162, 4051, + 4095, 3163, 4051, + 4095, 3164, 4050, + 4095, 3166, 4050, + 4095, 3168, 4049, + 4095, 3171, 4049, + 4095, 3176, 4048, + 4095, 3181, 4046, + 4095, 3188, 4045, + 4095, 3198, 4042, + 4095, 3210, 4039, + 4095, 3226, 4035, + 4095, 3247, 4029, + 4095, 3273, 4021, + 4095, 3306, 4010, + 4095, 3346, 3996, + 4095, 3395, 3975, + 4095, 3454, 3946, + 4095, 3521, 3904, + 4095, 3599, 3841, + 4095, 3685, 3740, + 4075, 3780, 3556, + 0, 1218, 1478, + 0, 1222, 1474, + 0, 1228, 1469, + 0, 1234, 1463, + 0, 1243, 1454, + 0, 1255, 1441, + 0, 1270, 1424, + 0, 1290, 1401, + 0, 1314, 1367, + 0, 1346, 1318, + 0, 1384, 1242, + 0, 1431, 1116, + 0, 1488, 863, + 0, 1553, 0, + 0, 1629, 0, + 0, 1713, 0, + 0, 1806, 0, + 0, 1906, 0, + 0, 2013, 0, + 0, 2125, 0, + 0, 2242, 0, + 0, 2362, 0, + 0, 2485, 0, + 0, 2610, 0, + 0, 2737, 0, + 0, 2865, 0, + 0, 2994, 0, + 0, 3124, 0, + 0, 3254, 0, + 0, 3385, 0, + 0, 3516, 0, + 0, 3648, 0, + 0, 1220, 1483, + 0, 1224, 1479, + 0, 1229, 1475, + 0, 1236, 1468, + 0, 1245, 1459, + 0, 1256, 1447, + 0, 1271, 1430, + 0, 1291, 1407, + 0, 1316, 1374, + 0, 1347, 1325, + 0, 1385, 1251, + 0, 1432, 1128, + 0, 1488, 883, + 0, 1554, 0, + 0, 1629, 0, + 0, 1713, 0, + 0, 1806, 0, + 0, 1906, 0, + 0, 2013, 0, + 0, 2125, 0, + 0, 2242, 0, + 0, 2362, 0, + 0, 2485, 0, + 0, 2610, 0, + 0, 2737, 0, + 0, 2865, 0, + 0, 2994, 0, + 0, 3124, 0, + 0, 3254, 0, + 0, 3385, 0, + 0, 3516, 0, + 0, 3648, 0, + 0, 1222, 1490, + 0, 1225, 1486, + 0, 1231, 1482, + 0, 1237, 1475, + 0, 1246, 1467, + 0, 1258, 1455, + 0, 1273, 1438, + 0, 1292, 1415, + 0, 1317, 1383, + 0, 1348, 1335, + 0, 1387, 1263, + 0, 1433, 1143, + 0, 1489, 909, + 0, 1555, 0, + 0, 1630, 0, + 0, 1714, 0, + 0, 1807, 0, + 0, 1907, 0, + 0, 2013, 0, + 0, 2125, 0, + 0, 2242, 0, + 0, 2362, 0, + 0, 2485, 0, + 0, 2610, 0, + 0, 2737, 0, + 0, 2865, 0, + 0, 2994, 0, + 0, 3124, 0, + 0, 3254, 0, + 0, 3385, 0, + 0, 3516, 0, + 0, 3648, 0, + 0, 1224, 1499, + 0, 1228, 1496, + 0, 1233, 1491, + 0, 1240, 1485, + 0, 1248, 1476, + 0, 1260, 1465, + 0, 1275, 1449, + 0, 1294, 1426, + 0, 1319, 1395, + 0, 1350, 1348, + 0, 1388, 1278, + 0, 1435, 1163, + 0, 1491, 942, + 0, 1556, 111, + 0, 1631, 0, + 0, 1715, 0, + 0, 1807, 0, + 0, 1907, 0, + 0, 2014, 0, + 0, 2126, 0, + 0, 2242, 0, + 0, 2362, 0, + 0, 2485, 0, + 0, 2610, 0, + 0, 2737, 0, + 0, 2865, 0, + 0, 2994, 0, + 0, 3124, 0, + 0, 3254, 0, + 0, 3385, 0, + 0, 3516, 0, + 0, 3648, 0, + 0, 1227, 1511, + 0, 1231, 1508, + 0, 1236, 1503, + 0, 1243, 1497, + 0, 1251, 1489, + 0, 1263, 1478, + 0, 1278, 1462, + 0, 1297, 1441, + 0, 1321, 1410, + 0, 1352, 1365, + 0, 1390, 1298, + 0, 1437, 1188, + 0, 1492, 982, + 0, 1557, 317, + 0, 1632, 0, + 0, 1716, 0, + 0, 1808, 0, + 0, 1908, 0, + 0, 2014, 0, + 0, 2126, 0, + 0, 2243, 0, + 0, 2363, 0, + 0, 2485, 0, + 0, 2610, 0, + 0, 2737, 0, + 0, 2865, 0, + 0, 2994, 0, + 0, 3124, 0, + 0, 3254, 0, + 0, 3385, 0, + 0, 3516, 0, + 0, 3648, 0, + 0, 1231, 1527, + 0, 1235, 1524, + 0, 1240, 1519, + 0, 1247, 1514, + 0, 1255, 1506, + 0, 1267, 1495, + 0, 1281, 1480, + 0, 1300, 1459, + 0, 1325, 1429, + 0, 1355, 1387, + 0, 1393, 1322, + 0, 1439, 1219, + 0, 1495, 1030, + 0, 1559, 497, + 0, 1634, 0, + 0, 1717, 0, + 0, 1809, 0, + 0, 1909, 0, + 0, 2015, 0, + 0, 2127, 0, + 0, 2243, 0, + 0, 2363, 0, + 0, 2486, 0, + 0, 2611, 0, + 0, 2737, 0, + 0, 2865, 0, + 0, 2994, 0, + 0, 3124, 0, + 0, 3254, 0, + 0, 3385, 0, + 0, 3516, 0, + 0, 3648, 0, + 0, 1237, 1547, + 0, 1240, 1544, + 0, 1245, 1540, + 0, 1252, 1534, + 0, 1260, 1527, + 0, 1272, 1516, + 0, 1286, 1502, + 0, 1305, 1482, + 0, 1329, 1454, + 0, 1360, 1414, + 0, 1397, 1354, + 0, 1443, 1258, + 0, 1498, 1088, + 0, 1562, 662, + 0, 1636, 0, + 0, 1719, 0, + 0, 1811, 0, + 0, 1910, 0, + 0, 2016, 0, + 0, 2128, 0, + 0, 2244, 0, + 0, 2363, 0, + 0, 2486, 0, + 0, 2611, 0, + 0, 2737, 0, + 0, 2865, 0, + 0, 2994, 0, + 0, 3124, 0, + 0, 3255, 0, + 0, 3385, 0, + 0, 3516, 0, + 0, 3648, 0, + 0, 1244, 1573, + 0, 1248, 1570, + 0, 1252, 1566, + 0, 1259, 1561, + 0, 1267, 1554, + 0, 1278, 1544, + 0, 1293, 1530, + 0, 1311, 1512, + 0, 1335, 1486, + 0, 1365, 1448, + 0, 1402, 1392, + 0, 1448, 1306, + 0, 1502, 1155, + 0, 1566, 818, + 0, 1639, 0, + 0, 1722, 0, + 0, 1813, 0, + 0, 1912, 0, + 0, 2017, 0, + 0, 2129, 0, + 0, 2244, 0, + 0, 2364, 0, + 0, 2486, 0, + 0, 2611, 0, + 0, 2738, 0, + 0, 2866, 0, + 0, 2995, 0, + 0, 3124, 0, + 0, 3255, 0, + 0, 3385, 0, + 0, 3516, 0, + 0, 3648, 0, + 664, 1253, 1605, + 635, 1257, 1602, + 593, 1262, 1599, + 530, 1268, 1594, + 428, 1276, 1587, + 243, 1287, 1578, + 0, 1301, 1566, + 0, 1320, 1548, + 0, 1343, 1524, + 0, 1372, 1490, + 0, 1409, 1440, + 0, 1454, 1362, + 0, 1507, 1232, + 0, 1570, 966, + 0, 1643, 0, + 0, 1725, 0, + 0, 1816, 0, + 0, 1914, 0, + 0, 2019, 0, + 0, 2130, 0, + 0, 2245, 0, + 0, 2365, 0, + 0, 2487, 0, + 0, 2612, 0, + 0, 2738, 0, + 0, 2866, 0, + 0, 2995, 0, + 0, 3124, 0, + 0, 3255, 0, + 0, 3385, 0, + 0, 3517, 0, + 0, 3648, 0, + 1063, 1266, 1645, + 1051, 1269, 1642, + 1034, 1274, 1639, + 1011, 1280, 1635, + 979, 1288, 1628, + 931, 1299, 1620, + 858, 1313, 1609, + 738, 1330, 1593, + 503, 1353, 1571, + 0, 1382, 1541, + 0, 1418, 1496, + 0, 1462, 1428, + 0, 1514, 1318, + 0, 1577, 1110, + 0, 1648, 435, + 0, 1729, 0, + 0, 1819, 0, + 0, 1917, 0, + 0, 2021, 0, + 0, 2132, 0, + 0, 2247, 0, + 0, 2366, 0, + 0, 2488, 0, + 0, 2612, 0, + 0, 2739, 0, + 0, 2866, 0, + 0, 2995, 0, + 0, 3125, 0, + 0, 3255, 0, + 0, 3386, 0, + 0, 3517, 0, + 0, 3648, 0, + 1325, 1282, 1693, + 1318, 1285, 1691, + 1309, 1290, 1688, + 1297, 1296, 1684, + 1280, 1303, 1678, + 1256, 1314, 1671, + 1222, 1327, 1661, + 1172, 1344, 1647, + 1095, 1366, 1628, + 966, 1394, 1601, + 704, 1429, 1562, + 0, 1472, 1503, + 0, 1524, 1412, + 0, 1585, 1251, + 0, 1655, 870, + 0, 1735, 0, + 0, 1824, 0, + 0, 1921, 0, + 0, 2024, 0, + 0, 2134, 0, + 0, 2249, 0, + 0, 2367, 0, + 0, 2489, 0, + 0, 2613, 0, + 0, 2739, 0, + 0, 2867, 0, + 0, 2995, 0, + 0, 3125, 0, + 0, 3255, 0, + 0, 3386, 0, + 0, 3517, 0, + 0, 3648, 0, + 1535, 1302, 1751, + 1530, 1306, 1749, + 1525, 1310, 1746, + 1517, 1316, 1742, + 1507, 1323, 1738, + 1492, 1333, 1731, + 1472, 1346, 1722, + 1444, 1362, 1710, + 1404, 1384, 1693, + 1343, 1411, 1670, + 1246, 1444, 1637, + 1074, 1486, 1588, + 636, 1536, 1514, + 0, 1595, 1390, + 0, 1664, 1144, + 0, 1743, 0, + 0, 1830, 0, + 0, 1926, 0, + 0, 2029, 0, + 0, 2137, 0, + 0, 2251, 0, + 0, 2369, 0, + 0, 2490, 0, + 0, 2614, 0, + 0, 2740, 0, + 0, 2867, 0, + 0, 2996, 0, + 0, 3125, 0, + 0, 3255, 0, + 0, 3386, 0, + 0, 3517, 0, + 0, 3648, 0, + 1717, 1329, 1818, + 1714, 1332, 1816, + 1711, 1336, 1814, + 1706, 1341, 1811, + 1699, 1348, 1806, + 1689, 1357, 1801, + 1676, 1370, 1793, + 1659, 1385, 1783, + 1634, 1406, 1769, + 1598, 1431, 1749, + 1546, 1464, 1721, + 1465, 1503, 1681, + 1327, 1552, 1621, + 1035, 1609, 1527, + 0, 1676, 1358, + 0, 1753, 942, + 0, 1839, 0, + 0, 1933, 0, + 0, 2034, 0, + 0, 2142, 0, + 0, 2255, 0, + 0, 2372, 0, + 0, 2492, 0, + 0, 2616, 0, + 0, 2741, 0, + 0, 2868, 0, + 0, 2997, 0, + 0, 3126, 0, + 0, 3256, 0, + 0, 3386, 0, + 0, 3517, 0, + 0, 3648, 0, + 1884, 1361, 1894, + 1882, 1364, 1893, + 1879, 1368, 1891, + 1876, 1373, 1888, + 1871, 1380, 1885, + 1865, 1388, 1880, + 1856, 1400, 1874, + 1844, 1414, 1865, + 1827, 1433, 1853, + 1805, 1458, 1837, + 1772, 1488, 1814, + 1724, 1526, 1782, + 1652, 1572, 1734, + 1532, 1627, 1662, + 1297, 1692, 1544, + 234, 1766, 1313, + 0, 1850, 322, + 0, 1942, 0, + 0, 2041, 0, + 0, 2147, 0, + 0, 2259, 0, + 0, 2375, 0, + 0, 2495, 0, + 0, 2618, 0, + 0, 2743, 0, + 0, 2869, 0, + 0, 2997, 0, + 0, 3126, 0, + 0, 3256, 0, + 0, 3387, 0, + 0, 3517, 0, + 0, 3648, 0, + 2040, 1402, 1980, + 2038, 1405, 1979, + 2037, 1408, 1977, + 2034, 1413, 1975, + 2031, 1419, 1972, + 2026, 1427, 1968, + 2020, 1437, 1963, + 2012, 1451, 1956, + 2001, 1468, 1946, + 1985, 1491, 1933, + 1964, 1519, 1914, + 1933, 1555, 1889, + 1888, 1598, 1852, + 1821, 1650, 1797, + 1712, 1712, 1712, + 1507, 1783, 1566, + 855, 1864, 1243, + 0, 1953, 0, + 0, 2051, 0, + 0, 2155, 0, + 0, 2265, 0, + 0, 2380, 0, + 0, 2499, 0, + 0, 2620, 0, + 0, 2745, 0, + 0, 2871, 0, + 0, 2999, 0, + 0, 3127, 0, + 0, 3257, 0, + 0, 3387, 0, + 0, 3518, 0, + 0, 3649, 0, + 2189, 1451, 2074, + 2188, 1453, 2073, + 2187, 1456, 2071, + 2185, 1461, 2070, + 2183, 1466, 2067, + 2180, 1473, 2064, + 2175, 1483, 2060, + 2169, 1495, 2054, + 2161, 1511, 2046, + 2151, 1531, 2036, + 2136, 1557, 2021, + 2115, 1590, 2001, + 2085, 1630, 1972, + 2043, 1679, 1931, + 1979, 1737, 1869, + 1877, 1805, 1771, + 1690, 1882, 1593, + 1170, 1968, 1129, + 0, 2063, 0, + 0, 2165, 0, + 0, 2273, 0, + 0, 2386, 0, + 0, 2503, 0, + 0, 2624, 0, + 0, 2747, 0, + 0, 2873, 0, + 0, 3000, 0, + 0, 3128, 0, + 0, 3258, 0, + 0, 3388, 0, + 0, 3518, 0, + 0, 3649, 0, + 2334, 1509, 2175, + 2333, 1511, 2174, + 2332, 1514, 2173, + 2331, 1518, 2172, + 2329, 1522, 2170, + 2327, 1529, 2167, + 2324, 1537, 2164, + 2319, 1548, 2159, + 2314, 1562, 2153, + 2306, 1581, 2145, + 2295, 1604, 2134, + 2281, 1634, 2118, + 2261, 1671, 2096, + 2232, 1716, 2065, + 2191, 1769, 2019, + 2130, 1833, 1951, + 2032, 1906, 1839, + 1856, 1988, 1628, + 1402, 2079, 912, + 0, 2177, 0, + 0, 2283, 0, + 0, 2394, 0, + 0, 2509, 0, + 0, 2629, 0, + 0, 2751, 0, + 0, 2876, 0, + 0, 3002, 0, + 0, 3130, 0, + 0, 3259, 0, + 0, 3389, 0, + 0, 3519, 0, + 0, 3650, 0, + 2475, 1577, 2283, + 2474, 1579, 2282, + 2474, 1581, 2281, + 2473, 1584, 2280, + 2472, 1588, 2279, + 2470, 1594, 2277, + 2468, 1601, 2274, + 2464, 1611, 2270, + 2460, 1623, 2266, + 2455, 1639, 2259, + 2447, 1660, 2250, + 2437, 1686, 2238, + 2423, 1719, 2221, + 2403, 1760, 2198, + 2375, 1809, 2165, + 2335, 1867, 2116, + 2275, 1935, 2041, + 2181, 2013, 1917, + 2012, 2099, 1670, + 1597, 2194, 135, + 0, 2296, 0, + 0, 2404, 0, + 0, 2517, 0, + 0, 2635, 0, + 0, 2756, 0, + 0, 2879, 0, + 0, 3005, 0, + 0, 3132, 0, + 0, 3260, 0, + 0, 3390, 0, + 0, 3520, 0, + 0, 3650, 0, + 2614, 1654, 2395, + 2613, 1656, 2395, + 2613, 1658, 2394, + 2612, 1660, 2393, + 2611, 1664, 2392, + 2610, 1669, 2391, + 2608, 1675, 2389, + 2606, 1683, 2386, + 2603, 1694, 2382, + 2599, 1707, 2377, + 2593, 1725, 2370, + 2586, 1748, 2361, + 2576, 1777, 2348, + 2562, 1813, 2331, + 2542, 1857, 2306, + 2515, 1910, 2271, + 2476, 1972, 2219, + 2417, 2044, 2139, + 2325, 2125, 2004, + 2162, 2215, 1721, + 1771, 2313, 0, + 0, 2417, 0, + 0, 2528, 0, + 0, 2643, 0, + 0, 2762, 0, + 0, 2884, 0, + 0, 3009, 0, + 0, 3135, 0, + 0, 3263, 0, + 0, 3391, 0, + 0, 3521, 0, + 0, 3651, 0, + 2751, 1741, 2513, + 2750, 1742, 2512, + 2750, 1744, 2512, + 2750, 1746, 2511, + 2749, 1749, 2510, + 2748, 1753, 2509, + 2747, 1758, 2507, + 2745, 1764, 2505, + 2743, 1773, 2502, + 2740, 1785, 2499, + 2736, 1800, 2493, + 2730, 1819, 2486, + 2723, 1844, 2477, + 2713, 1875, 2464, + 2699, 1914, 2445, + 2680, 1961, 2420, + 2653, 2017, 2383, + 2614, 2083, 2329, + 2556, 2158, 2244, + 2466, 2242, 2099, + 2306, 2335, 1782, + 1932, 2435, 0, + 0, 2542, 0, + 0, 2654, 0, + 0, 2770, 0, + 0, 2890, 0, + 0, 3013, 0, + 0, 3138, 0, + 0, 3265, 0, + 0, 3393, 0, + 0, 3522, 0, + 0, 3652, 0, + 2887, 1835, 2633, + 2886, 1836, 2633, + 2886, 1838, 2633, + 2886, 1839, 2632, + 2885, 1842, 2631, + 2884, 1845, 2630, + 2884, 1849, 2629, + 2882, 1855, 2628, + 2881, 1862, 2625, + 2878, 1872, 2623, + 2875, 1884, 2619, + 2871, 1900, 2613, + 2866, 1921, 2606, + 2859, 1948, 2596, + 2849, 1981, 2582, + 2835, 2021, 2564, + 2816, 2071, 2537, + 2789, 2130, 2499, + 2751, 2198, 2443, + 2694, 2275, 2355, + 2604, 2362, 2201, + 2447, 2457, 1852, + 2084, 2559, 0, + 0, 2668, 0, + 0, 2781, 0, + 0, 2899, 0, + 0, 3020, 0, + 0, 3143, 0, + 0, 3269, 0, + 0, 3396, 0, + 0, 3525, 0, + 0, 3654, 0, + 3021, 1937, 2757, + 3021, 1938, 2756, + 3021, 1939, 2756, + 3021, 1940, 2756, + 3020, 1942, 2755, + 3020, 1945, 2754, + 3019, 1948, 2754, + 3018, 1953, 2752, + 3017, 1959, 2751, + 3015, 1966, 2748, + 3013, 1977, 2745, + 3010, 1990, 2741, + 3006, 2007, 2736, + 3001, 2029, 2728, + 2994, 2057, 2718, + 2984, 2092, 2705, + 2970, 2134, 2685, + 2951, 2186, 2658, + 2924, 2247, 2619, + 2886, 2317, 2561, + 2830, 2397, 2470, + 2741, 2485, 2310, + 2586, 2582, 1931, + 2231, 2685, 0, + 0, 2795, 0, + 0, 2910, 0, + 0, 3028, 0, + 0, 3150, 0, + 0, 3274, 0, + 0, 3400, 0, + 0, 3527, 0, + 0, 3656, 0, + 3155, 2045, 2882, + 3155, 2046, 2882, + 3155, 2047, 2882, + 3155, 2048, 2881, + 3155, 2049, 2881, + 3154, 2051, 2880, + 3154, 2054, 2880, + 3153, 2057, 2879, + 3152, 2062, 2877, + 3151, 2068, 2876, + 3149, 2077, 2874, + 3147, 2087, 2870, + 3144, 2101, 2866, + 3140, 2119, 2861, + 3135, 2142, 2853, + 3128, 2171, 2843, + 3118, 2207, 2829, + 3104, 2251, 2809, + 3085, 2304, 2782, + 3059, 2367, 2742, + 3021, 2439, 2683, + 2965, 2520, 2589, + 2877, 2610, 2423, + 2723, 2708, 2020, + 2374, 2813, 0, + 0, 2924, 0, + 0, 3039, 0, + 0, 3158, 0, + 0, 3280, 0, + 0, 3405, 0, + 0, 3531, 0, + 0, 3659, 0, + 3289, 2158, 3009, + 3289, 2159, 3009, + 3289, 2160, 3009, + 3289, 2160, 3009, + 3288, 2162, 3008, + 3288, 2163, 3008, + 3288, 2165, 3007, + 3287, 2168, 3007, + 3287, 2172, 3006, + 3286, 2177, 3004, + 3285, 2183, 3003, + 3283, 2192, 3000, + 3281, 2203, 2997, + 3278, 2217, 2993, + 3274, 2236, 2988, + 3269, 2259, 2980, + 3261, 2289, 2969, + 3251, 2326, 2955, + 3238, 2372, 2935, + 3219, 2426, 2907, + 3193, 2490, 2867, + 3155, 2563, 2807, + 3099, 2646, 2711, + 3011, 2737, 2541, + 2859, 2836, 2116, + 2514, 2942, 0, + 0, 3053, 0, + 0, 3169, 0, + 0, 3289, 0, + 0, 3411, 0, + 0, 3536, 0, + 0, 3662, 0, + 3422, 2276, 3137, + 3422, 2276, 3137, + 3422, 2277, 3137, + 3422, 2278, 3137, + 3422, 2278, 3137, + 3422, 2280, 3136, + 3421, 2281, 3136, + 3421, 2283, 3135, + 3420, 2286, 3135, + 3420, 2290, 3134, + 3419, 2295, 3133, + 3418, 2302, 3131, + 3416, 2310, 3128, + 3414, 2322, 3125, + 3411, 2337, 3121, + 3407, 2356, 3115, + 3402, 2380, 3108, + 3394, 2411, 3097, + 3385, 2449, 3083, + 3371, 2495, 3063, + 3352, 2551, 3035, + 3326, 2615, 2994, + 3289, 2690, 2933, + 3233, 2773, 2836, + 3145, 2866, 2662, + 2994, 2965, 2219, + 2652, 3072, 0, + 0, 3183, 0, + 0, 3300, 0, + 0, 3420, 0, + 0, 3542, 0, + 0, 3667, 0, + 3555, 2397, 3267, + 3555, 2397, 3266, + 3555, 2398, 3266, + 3555, 2398, 3266, + 3555, 2399, 3266, + 3555, 2400, 3266, + 3555, 2401, 3266, + 3554, 2403, 3265, + 3554, 2405, 3265, + 3553, 2408, 3264, + 3553, 2412, 3263, + 3552, 2417, 3262, + 3551, 2423, 3260, + 3549, 2432, 3258, + 3547, 2444, 3254, + 3544, 2459, 3250, + 3540, 2479, 3245, + 3535, 2504, 3237, + 3527, 2535, 3226, + 3518, 2573, 3212, + 3504, 2621, 3191, + 3485, 2677, 3163, + 3459, 2742, 3122, + 3422, 2818, 3060, + 3366, 2902, 2962, + 3279, 2995, 2786, + 3128, 3095, 2329, + 2788, 3202, 0, + 0, 3314, 0, + 0, 3431, 0, + 0, 3551, 0, + 0, 3674, 0, + 3688, 2520, 3396, + 3688, 2521, 3396, + 3688, 2521, 3396, + 3688, 2521, 3396, + 3688, 2522, 3396, + 3688, 2522, 3396, + 3687, 2523, 3396, + 3687, 2525, 3395, + 3687, 2526, 3395, + 3687, 2529, 3394, + 3686, 2532, 3394, + 3685, 2536, 3393, + 3684, 2541, 3391, + 3683, 2548, 3390, + 3682, 2557, 3387, + 3679, 2569, 3384, + 3677, 2584, 3380, + 3673, 2604, 3374, + 3667, 2629, 3366, + 3660, 2661, 3356, + 3650, 2700, 3341, + 3637, 2748, 3321, + 3618, 2804, 3292, + 3592, 2871, 3251, + 3555, 2946, 3189, + 3499, 3031, 3090, + 3412, 3125, 2912, + 3262, 3225, 2443, + 2923, 3332, 0, + 0, 3445, 0, + 0, 3562, 0, + 0, 3682, 0, + 3820, 2646, 3527, + 3820, 2646, 3527, + 3820, 2646, 3527, + 3820, 2647, 3527, + 3820, 2647, 3527, + 3820, 2648, 3527, + 3820, 2648, 3526, + 3820, 2649, 3526, + 3820, 2651, 3526, + 3819, 2652, 3525, + 3819, 2654, 3525, + 3819, 2658, 3524, + 3818, 2662, 3523, + 3817, 2667, 3522, + 3816, 2674, 3520, + 3814, 2683, 3518, + 3812, 2695, 3515, + 3809, 2711, 3510, + 3805, 2731, 3505, + 3800, 2756, 3497, + 3793, 2788, 3486, + 3783, 2828, 3471, + 3769, 2876, 3451, + 3751, 2933, 3422, + 3725, 3000, 3381, + 3687, 3076, 3318, + 3632, 3161, 3219, + 3545, 3255, 3039, + 3395, 3356, 2562, + 3058, 3463, 0, + 0, 3576, 0, + 0, 3693, 0, + 3953, 2773, 3658, + 3953, 2773, 3658, + 3953, 2773, 3658, + 3953, 2774, 3658, + 3953, 2774, 3658, + 3953, 2774, 3658, + 3953, 2775, 3657, + 3953, 2776, 3657, + 3952, 2777, 3657, + 3952, 2778, 3657, + 3952, 2780, 3656, + 3952, 2782, 3656, + 3951, 2785, 3655, + 3950, 2789, 3654, + 3949, 2794, 3653, + 3948, 2801, 3651, + 3947, 2811, 3649, + 3944, 2823, 3645, + 3942, 2839, 3641, + 3938, 2859, 3635, + 3932, 2885, 3628, + 3925, 2917, 3617, + 3915, 2957, 3602, + 3902, 3005, 3582, + 3883, 3063, 3553, + 3857, 3130, 3511, + 3820, 3206, 3449, + 3764, 3292, 3349, + 3678, 3386, 3167, + 3528, 3487, 2683, + 3192, 3595, 0, + 0, 3708, 0, + 4085, 2901, 3789, + 4085, 2902, 3789, + 4085, 2902, 3789, + 4085, 2902, 3789, + 4085, 2902, 3789, + 4085, 2902, 3789, + 4085, 2903, 3789, + 4085, 2903, 3789, + 4085, 2904, 3788, + 4085, 2905, 3788, + 4085, 2906, 3788, + 4084, 2908, 3787, + 4084, 2910, 3787, + 4083, 2913, 3786, + 4083, 2918, 3785, + 4082, 2923, 3784, + 4081, 2930, 3782, + 4079, 2939, 3780, + 4077, 2952, 3777, + 4074, 2968, 3772, + 4070, 2988, 3767, + 4065, 3014, 3759, + 4058, 3046, 3748, + 4048, 3086, 3733, + 4034, 3135, 3713, + 4016, 3193, 3684, + 3990, 3260, 3642, + 3952, 3337, 3579, + 3897, 3423, 3479, + 3810, 3517, 3297, + 3660, 3618, 2807, + 3325, 3726, 0, + 4095, 3031, 3920, + 4095, 3031, 3920, + 4095, 3031, 3920, + 4095, 3031, 3920, + 4095, 3031, 3920, + 4095, 3031, 3920, + 4095, 3032, 3920, + 4095, 3032, 3920, + 4095, 3033, 3920, + 4095, 3033, 3920, + 4095, 3034, 3920, + 4095, 3036, 3919, + 4095, 3037, 3919, + 4095, 3040, 3918, + 4095, 3043, 3918, + 4095, 3047, 3917, + 4095, 3052, 3915, + 4095, 3060, 3914, + 4095, 3069, 3911, + 4095, 3081, 3908, + 4095, 3097, 3904, + 4095, 3118, 3898, + 4095, 3144, 3890, + 4095, 3176, 3879, + 4095, 3217, 3864, + 4095, 3265, 3844, + 4095, 3323, 3815, + 4095, 3391, 3773, + 4085, 3468, 3710, + 4029, 3554, 3610, + 3943, 3648, 3427, + 3793, 3750, 2933, + 4095, 3161, 4052, + 4095, 3161, 4052, + 4095, 3161, 4052, + 4095, 3161, 4052, + 4095, 3161, 4052, + 4095, 3161, 4052, + 4095, 3161, 4052, + 4095, 3162, 4052, + 4095, 3162, 4052, + 4095, 3163, 4052, + 4095, 3163, 4051, + 4095, 3164, 4051, + 4095, 3166, 4051, + 4095, 3168, 4050, + 4095, 3170, 4050, + 4095, 3173, 4049, + 4095, 3177, 4048, + 4095, 3183, 4047, + 4095, 3190, 4045, + 4095, 3199, 4043, + 4095, 3212, 4040, + 4095, 3228, 4035, + 4095, 3248, 4029, + 4095, 3274, 4022, + 4095, 3307, 4011, + 4095, 3347, 3996, + 4095, 3396, 3975, + 4095, 3454, 3946, + 4095, 3522, 3904, + 4095, 3599, 3841, + 4095, 3685, 3741, + 4075, 3780, 3557, + 0, 1347, 1608, + 0, 1350, 1606, + 0, 1354, 1602, + 0, 1359, 1597, + 0, 1365, 1590, + 0, 1374, 1581, + 0, 1386, 1569, + 0, 1401, 1552, + 0, 1421, 1528, + 0, 1446, 1494, + 0, 1477, 1444, + 0, 1516, 1367, + 0, 1563, 1239, + 0, 1619, 979, + 0, 1685, 0, + 0, 1760, 0, + 0, 1845, 0, + 0, 1938, 0, + 0, 2038, 0, + 0, 2145, 0, + 0, 2257, 0, + 0, 2374, 0, + 0, 2494, 0, + 0, 2617, 0, + 0, 2742, 0, + 0, 2869, 0, + 0, 2997, 0, + 0, 3126, 0, + 0, 3256, 0, + 0, 3386, 0, + 0, 3517, 0, + 0, 3648, 0, + 0, 1348, 1612, + 0, 1351, 1610, + 0, 1354, 1606, + 0, 1360, 1601, + 0, 1366, 1595, + 0, 1375, 1586, + 0, 1387, 1573, + 0, 1402, 1557, + 0, 1422, 1533, + 0, 1447, 1499, + 0, 1478, 1450, + 0, 1516, 1374, + 0, 1564, 1248, + 0, 1620, 995, + 0, 1685, 0, + 0, 1761, 0, + 0, 1845, 0, + 0, 1938, 0, + 0, 2038, 0, + 0, 2145, 0, + 0, 2257, 0, + 0, 2374, 0, + 0, 2494, 0, + 0, 2617, 0, + 0, 2742, 0, + 0, 2869, 0, + 0, 2997, 0, + 0, 3126, 0, + 0, 3256, 0, + 0, 3386, 0, + 0, 3517, 0, + 0, 3648, 0, + 0, 1349, 1618, + 0, 1352, 1615, + 0, 1356, 1611, + 0, 1361, 1607, + 0, 1368, 1600, + 0, 1377, 1591, + 0, 1388, 1579, + 0, 1403, 1563, + 0, 1423, 1539, + 0, 1448, 1506, + 0, 1479, 1457, + 0, 1517, 1383, + 0, 1564, 1260, + 0, 1620, 1015, + 0, 1686, 0, + 0, 1761, 0, + 0, 1845, 0, + 0, 1938, 0, + 0, 2038, 0, + 0, 2145, 0, + 0, 2257, 0, + 0, 2374, 0, + 0, 2494, 0, + 0, 2617, 0, + 0, 2742, 0, + 0, 2869, 0, + 0, 2997, 0, + 0, 3126, 0, + 0, 3256, 0, + 0, 3386, 0, + 0, 3517, 0, + 0, 3648, 0, + 0, 1351, 1625, + 0, 1354, 1622, + 0, 1358, 1619, + 0, 1363, 1614, + 0, 1369, 1607, + 0, 1378, 1599, + 0, 1390, 1587, + 0, 1405, 1570, + 0, 1424, 1548, + 0, 1449, 1515, + 0, 1480, 1467, + 0, 1519, 1395, + 0, 1565, 1275, + 0, 1621, 1041, + 0, 1687, 0, + 0, 1762, 0, + 0, 1846, 0, + 0, 1939, 0, + 0, 2039, 0, + 0, 2145, 0, + 0, 2258, 0, + 0, 2374, 0, + 0, 2494, 0, + 0, 2617, 0, + 0, 2742, 0, + 0, 2869, 0, + 0, 2997, 0, + 0, 3126, 0, + 0, 3256, 0, + 0, 3386, 0, + 0, 3517, 0, + 0, 3648, 0, + 0, 1353, 1634, + 0, 1356, 1631, + 0, 1360, 1628, + 0, 1365, 1623, + 0, 1372, 1617, + 0, 1381, 1608, + 0, 1392, 1597, + 0, 1407, 1581, + 0, 1426, 1558, + 0, 1451, 1527, + 0, 1482, 1480, + 0, 1520, 1410, + 0, 1567, 1295, + 0, 1623, 1074, + 0, 1688, 244, + 0, 1763, 0, + 0, 1847, 0, + 0, 1939, 0, + 0, 2039, 0, + 0, 2146, 0, + 0, 2258, 0, + 0, 2374, 0, + 0, 2494, 0, + 0, 2617, 0, + 0, 2742, 0, + 0, 2869, 0, + 0, 2997, 0, + 0, 3126, 0, + 0, 3256, 0, + 0, 3386, 0, + 0, 3517, 0, + 0, 3648, 0, + 0, 1356, 1646, + 0, 1359, 1643, + 0, 1363, 1640, + 0, 1368, 1636, + 0, 1375, 1629, + 0, 1383, 1621, + 0, 1395, 1610, + 0, 1410, 1594, + 0, 1429, 1573, + 0, 1453, 1542, + 0, 1484, 1497, + 0, 1522, 1430, + 0, 1569, 1320, + 0, 1624, 1114, + 0, 1690, 449, + 0, 1764, 0, + 0, 1848, 0, + 0, 1940, 0, + 0, 2040, 0, + 0, 2146, 0, + 0, 2258, 0, + 0, 2375, 0, + 0, 2495, 0, + 0, 2617, 0, + 0, 2742, 0, + 0, 2869, 0, + 0, 2997, 0, + 0, 3126, 0, + 0, 3256, 0, + 0, 3387, 0, + 0, 3517, 0, + 0, 3648, 0, + 0, 1360, 1662, + 0, 1363, 1659, + 0, 1367, 1656, + 0, 1372, 1652, + 0, 1379, 1646, + 0, 1387, 1638, + 0, 1399, 1627, + 0, 1414, 1612, + 0, 1433, 1591, + 0, 1457, 1561, + 0, 1487, 1519, + 0, 1525, 1455, + 0, 1572, 1351, + 0, 1627, 1162, + 0, 1692, 629, + 0, 1766, 0, + 0, 1849, 0, + 0, 1941, 0, + 0, 2041, 0, + 0, 2147, 0, + 0, 2259, 0, + 0, 2375, 0, + 0, 2495, 0, + 0, 2618, 0, + 0, 2743, 0, + 0, 2869, 0, + 0, 2997, 0, + 0, 3126, 0, + 0, 3256, 0, + 0, 3387, 0, + 0, 3517, 0, + 0, 3648, 0, + 0, 1366, 1682, + 0, 1369, 1679, + 0, 1373, 1676, + 0, 1377, 1672, + 0, 1384, 1666, + 0, 1393, 1659, + 0, 1404, 1648, + 0, 1418, 1634, + 0, 1437, 1614, + 0, 1461, 1586, + 0, 1492, 1546, + 0, 1529, 1486, + 0, 1575, 1390, + 0, 1630, 1220, + 0, 1694, 795, + 0, 1768, 0, + 0, 1851, 0, + 0, 1943, 0, + 0, 2042, 0, + 0, 2148, 0, + 0, 2260, 0, + 0, 2376, 0, + 0, 2495, 0, + 0, 2618, 0, + 0, 2743, 0, + 0, 2870, 0, + 0, 2998, 0, + 0, 3127, 0, + 0, 3256, 0, + 0, 3387, 0, + 0, 3517, 0, + 0, 3649, 0, + 0, 1373, 1707, + 0, 1376, 1705, + 0, 1380, 1702, + 0, 1385, 1698, + 0, 1391, 1693, + 0, 1399, 1686, + 0, 1411, 1676, + 0, 1425, 1662, + 0, 1444, 1644, + 0, 1467, 1618, + 0, 1497, 1580, + 0, 1534, 1525, + 0, 1580, 1438, + 0, 1634, 1287, + 0, 1698, 950, + 0, 1771, 0, + 0, 1854, 0, + 0, 1945, 0, + 0, 2044, 0, + 0, 2149, 0, + 0, 2261, 0, + 0, 2377, 0, + 0, 2496, 0, + 0, 2619, 0, + 0, 2743, 0, + 0, 2870, 0, + 0, 2998, 0, + 0, 3127, 0, + 0, 3256, 0, + 0, 3387, 0, + 0, 3517, 0, + 0, 3649, 0, + 817, 1383, 1739, + 796, 1385, 1737, + 767, 1389, 1734, + 725, 1394, 1731, + 662, 1400, 1726, + 560, 1408, 1719, + 375, 1419, 1710, + 0, 1433, 1698, + 0, 1452, 1680, + 0, 1475, 1656, + 0, 1504, 1622, + 0, 1541, 1572, + 0, 1586, 1494, + 0, 1639, 1364, + 0, 1702, 1098, + 0, 1775, 0, + 0, 1857, 0, + 0, 1948, 0, + 0, 2046, 0, + 0, 2151, 0, + 0, 2262, 0, + 0, 2378, 0, + 0, 2497, 0, + 0, 2619, 0, + 0, 2744, 0, + 0, 2870, 0, + 0, 2998, 0, + 0, 3127, 0, + 0, 3257, 0, + 0, 3387, 0, + 0, 3518, 0, + 0, 3649, 0, + 1204, 1395, 1779, + 1195, 1398, 1777, + 1183, 1401, 1775, + 1166, 1406, 1771, + 1143, 1412, 1767, + 1111, 1420, 1761, + 1063, 1431, 1752, + 990, 1445, 1741, + 870, 1462, 1725, + 635, 1485, 1704, + 0, 1514, 1673, + 0, 1550, 1628, + 0, 1594, 1560, + 0, 1646, 1450, + 0, 1709, 1243, + 0, 1780, 567, + 0, 1861, 0, + 0, 1951, 0, + 0, 2049, 0, + 0, 2154, 0, + 0, 2264, 0, + 0, 2379, 0, + 0, 2498, 0, + 0, 2620, 0, + 0, 2744, 0, + 0, 2871, 0, + 0, 2998, 0, + 0, 3127, 0, + 0, 3257, 0, + 0, 3387, 0, + 0, 3518, 0, + 0, 3649, 0, + 1462, 1411, 1827, + 1457, 1414, 1825, + 1450, 1417, 1823, + 1441, 1422, 1820, + 1429, 1428, 1816, + 1412, 1436, 1811, + 1388, 1446, 1803, + 1354, 1459, 1793, + 1304, 1476, 1779, + 1227, 1498, 1760, + 1098, 1526, 1733, + 836, 1561, 1694, + 0, 1604, 1636, + 0, 1656, 1544, + 0, 1717, 1383, + 0, 1787, 1003, + 0, 1867, 0, + 0, 1956, 0, + 0, 2053, 0, + 0, 2157, 0, + 0, 2266, 0, + 0, 2381, 0, + 0, 2499, 0, + 0, 2621, 0, + 0, 2745, 0, + 0, 2871, 0, + 0, 2999, 0, + 0, 3128, 0, + 0, 3257, 0, + 0, 3387, 0, + 0, 3518, 0, + 0, 3649, 0, + 1670, 1432, 1884, + 1667, 1435, 1883, + 1663, 1438, 1881, + 1657, 1442, 1878, + 1649, 1448, 1875, + 1639, 1455, 1870, + 1624, 1465, 1863, + 1604, 1478, 1854, + 1576, 1494, 1842, + 1536, 1516, 1826, + 1475, 1543, 1802, + 1378, 1576, 1769, + 1206, 1618, 1720, + 769, 1668, 1646, + 0, 1728, 1522, + 0, 1797, 1276, + 0, 1875, 0, + 0, 1962, 0, + 0, 2058, 0, + 0, 2161, 0, + 0, 2270, 0, + 0, 2383, 0, + 0, 2501, 0, + 0, 2623, 0, + 0, 2746, 0, + 0, 2872, 0, + 0, 3000, 0, + 0, 3128, 0, + 0, 3257, 0, + 0, 3387, 0, + 0, 3518, 0, + 0, 3649, 0, + 1851, 1458, 1951, + 1849, 1461, 1950, + 1847, 1464, 1948, + 1843, 1468, 1946, + 1838, 1473, 1943, + 1831, 1480, 1939, + 1821, 1490, 1933, + 1809, 1502, 1925, + 1791, 1517, 1915, + 1766, 1538, 1901, + 1730, 1563, 1881, + 1678, 1596, 1853, + 1597, 1636, 1813, + 1459, 1684, 1753, + 1167, 1741, 1659, + 0, 1809, 1491, + 0, 1885, 1074, + 0, 1971, 0, + 0, 2065, 0, + 0, 2166, 0, + 0, 2274, 0, + 0, 2387, 0, + 0, 2504, 0, + 0, 2625, 0, + 0, 2748, 0, + 0, 2873, 0, + 0, 3000, 0, + 0, 3129, 0, + 0, 3258, 0, + 0, 3388, 0, + 0, 3518, 0, + 0, 3649, 0, + 2017, 1491, 2027, + 2016, 1494, 2026, + 2014, 1496, 2025, + 2011, 1500, 2023, + 2008, 1505, 2020, + 2003, 1512, 2017, + 1997, 1520, 2012, + 1988, 1532, 2006, + 1976, 1547, 1997, + 1960, 1566, 1985, + 1937, 1590, 1969, + 1904, 1620, 1946, + 1856, 1658, 1914, + 1784, 1704, 1867, + 1664, 1759, 1794, + 1430, 1824, 1676, + 367, 1898, 1445, + 0, 1982, 454, + 0, 2074, 0, + 0, 2173, 0, + 0, 2279, 0, + 0, 2391, 0, + 0, 2507, 0, + 0, 2627, 0, + 0, 2750, 0, + 0, 2875, 0, + 0, 3002, 0, + 0, 3130, 0, + 0, 3259, 0, + 0, 3388, 0, + 0, 3519, 0, + 0, 3649, 0, + 2173, 1532, 2113, + 2172, 1534, 2112, + 2171, 1537, 2111, + 2169, 1540, 2109, + 2166, 1545, 2107, + 2163, 1551, 2104, + 2158, 1559, 2100, + 2152, 1569, 2095, + 2144, 1583, 2088, + 2133, 1600, 2078, + 2117, 1623, 2065, + 2096, 1651, 2047, + 2065, 1687, 2021, + 2021, 1730, 1984, + 1953, 1782, 1929, + 1844, 1844, 1844, + 1639, 1915, 1698, + 988, 1996, 1375, + 0, 2085, 0, + 0, 2183, 0, + 0, 2287, 0, + 0, 2397, 0, + 0, 2512, 0, + 0, 2631, 0, + 0, 2753, 0, + 0, 2877, 0, + 0, 3003, 0, + 0, 3131, 0, + 0, 3259, 0, + 0, 3389, 0, + 0, 3519, 0, + 0, 3650, 0, + 2322, 1581, 2206, + 2321, 1583, 2206, + 2320, 1585, 2205, + 2319, 1588, 2204, + 2317, 1593, 2202, + 2315, 1598, 2199, + 2312, 1605, 2196, + 2307, 1615, 2192, + 2301, 1627, 2186, + 2293, 1643, 2179, + 2283, 1663, 2168, + 2268, 1690, 2153, + 2247, 1722, 2133, + 2218, 1763, 2105, + 2175, 1811, 2063, + 2111, 1870, 2001, + 2009, 1937, 1903, + 1822, 2014, 1725, + 1302, 2100, 1261, + 0, 2195, 0, + 0, 2297, 0, + 0, 2405, 0, + 0, 2518, 0, + 0, 2635, 0, + 0, 2756, 0, + 0, 2880, 0, + 0, 3005, 0, + 0, 3132, 0, + 0, 3261, 0, + 0, 3390, 0, + 0, 3520, 0, + 0, 3650, 0, + 2466, 1640, 2308, + 2466, 1641, 2307, + 2465, 1643, 2306, + 2464, 1646, 2305, + 2463, 1650, 2304, + 2461, 1655, 2302, + 2459, 1661, 2299, + 2456, 1669, 2296, + 2451, 1680, 2292, + 2446, 1694, 2285, + 2438, 1713, 2277, + 2427, 1736, 2266, + 2413, 1766, 2250, + 2393, 1803, 2228, + 2364, 1848, 2197, + 2323, 1902, 2152, + 2262, 1965, 2083, + 2164, 2038, 1971, + 1988, 2120, 1760, + 1534, 2211, 1044, + 0, 2309, 0, + 0, 2415, 0, + 0, 2526, 0, + 0, 2641, 0, + 0, 2761, 0, + 0, 2883, 0, + 0, 3008, 0, + 0, 3134, 0, + 0, 3262, 0, + 0, 3391, 0, + 0, 3521, 0, + 0, 3651, 0, + 2607, 1708, 2415, + 2607, 1709, 2415, + 2607, 1711, 2414, + 2606, 1713, 2413, + 2605, 1716, 2412, + 2604, 1721, 2411, + 2602, 1726, 2409, + 2600, 1733, 2406, + 2597, 1743, 2402, + 2592, 1755, 2398, + 2587, 1771, 2391, + 2579, 1792, 2382, + 2569, 1818, 2370, + 2555, 1851, 2353, + 2535, 1892, 2330, + 2507, 1941, 2297, + 2467, 1999, 2248, + 2407, 2067, 2173, + 2313, 2145, 2049, + 2144, 2231, 1802, + 1729, 2326, 267, + 0, 2428, 0, + 0, 2536, 0, + 0, 2649, 0, + 0, 2767, 0, + 0, 2888, 0, + 0, 3011, 0, + 0, 3137, 0, + 0, 3264, 0, + 0, 3393, 0, + 0, 3522, 0, + 0, 3652, 0, + 2746, 1785, 2528, + 2746, 1786, 2528, + 2745, 1788, 2527, + 2745, 1790, 2526, + 2744, 1793, 2526, + 2743, 1796, 2524, + 2742, 1801, 2523, + 2740, 1807, 2521, + 2738, 1815, 2518, + 2735, 1826, 2514, + 2731, 1839, 2509, + 2726, 1857, 2502, + 2718, 1880, 2493, + 2708, 1909, 2480, + 2694, 1945, 2463, + 2674, 1989, 2438, + 2647, 2042, 2403, + 2608, 2104, 2351, + 2549, 2176, 2271, + 2457, 2257, 2136, + 2294, 2347, 1853, + 1903, 2445, 0, + 0, 2549, 0, + 0, 2660, 0, + 0, 2775, 0, + 0, 2894, 0, + 0, 3016, 0, + 0, 3141, 0, + 0, 3267, 0, + 0, 3395, 0, + 0, 3523, 0, + 0, 3653, 0, + 2883, 1872, 2645, + 2883, 1873, 2645, + 2883, 1874, 2644, + 2882, 1876, 2644, + 2882, 1878, 2643, + 2881, 1881, 2642, + 2880, 1885, 2641, + 2879, 1890, 2640, + 2877, 1897, 2637, + 2875, 1905, 2635, + 2872, 1917, 2631, + 2868, 1932, 2625, + 2862, 1952, 2618, + 2855, 1976, 2609, + 2845, 2008, 2596, + 2831, 2046, 2577, + 2812, 2093, 2552, + 2785, 2149, 2515, + 2746, 2215, 2461, + 2688, 2290, 2376, + 2598, 2374, 2231, + 2438, 2467, 1914, + 2064, 2567, 0, + 0, 2674, 0, + 0, 2786, 0, + 0, 2902, 0, + 0, 3022, 0, + 0, 3145, 0, + 0, 3271, 0, + 0, 3397, 0, + 0, 3525, 0, + 0, 3655, 0, + 3019, 1967, 2766, + 3019, 1967, 2765, + 3018, 1968, 2765, + 3018, 1970, 2765, + 3018, 1971, 2764, + 3017, 1974, 2763, + 3017, 1977, 2763, + 3016, 1981, 2761, + 3014, 1987, 2760, + 3013, 1994, 2758, + 3011, 2004, 2755, + 3008, 2016, 2751, + 3004, 2032, 2745, + 2998, 2053, 2738, + 2991, 2080, 2728, + 2981, 2113, 2715, + 2967, 2154, 2696, + 2948, 2203, 2669, + 2921, 2262, 2631, + 2883, 2330, 2575, + 2826, 2408, 2487, + 2736, 2494, 2334, + 2580, 2589, 1984, + 2216, 2691, 0, + 0, 2800, 0, + 0, 2913, 0, + 0, 3031, 0, + 0, 3152, 0, + 0, 3275, 0, + 0, 3401, 0, + 0, 3528, 0, + 0, 3657, 0, + 3154, 2069, 2889, + 3153, 2069, 2889, + 3153, 2070, 2888, + 3153, 2071, 2888, + 3153, 2072, 2888, + 3152, 2074, 2887, + 3152, 2077, 2887, + 3151, 2080, 2886, + 3150, 2085, 2884, + 3149, 2091, 2883, + 3147, 2098, 2881, + 3145, 2109, 2878, + 3142, 2122, 2873, + 3138, 2139, 2868, + 3133, 2161, 2861, + 3126, 2189, 2850, + 3116, 2224, 2837, + 3102, 2266, 2817, + 3083, 2318, 2790, + 3057, 2379, 2751, + 3018, 2449, 2693, + 2962, 2529, 2602, + 2873, 2617, 2442, + 2718, 2714, 2063, + 2363, 2818, 0, + 0, 2927, 0, + 0, 3042, 0, + 0, 3160, 0, + 0, 3282, 0, + 0, 3406, 0, + 0, 3532, 0, + 0, 3659, 0, + 3288, 2177, 3014, + 3288, 2177, 3014, + 3287, 2178, 3014, + 3287, 2179, 3014, + 3287, 2180, 3013, + 3287, 2181, 3013, + 3286, 2183, 3012, + 3286, 2186, 3012, + 3285, 2190, 3011, + 3284, 2194, 3010, + 3283, 2200, 3008, + 3281, 2209, 3006, + 3279, 2219, 3003, + 3276, 2233, 2998, + 3272, 2251, 2993, + 3267, 2274, 2985, + 3260, 2303, 2975, + 3250, 2339, 2961, + 3236, 2383, 2941, + 3217, 2437, 2914, + 3191, 2499, 2874, + 3153, 2571, 2815, + 3097, 2652, 2721, + 3009, 2743, 2556, + 2855, 2840, 2152, + 2506, 2945, 0, + 0, 3056, 0, + 0, 3171, 0, + 0, 3290, 0, + 0, 3412, 0, + 0, 3537, 0, + 0, 3663, 0, + 3421, 2290, 3141, + 3421, 2291, 3141, + 3421, 2291, 3141, + 3421, 2292, 3141, + 3421, 2293, 3141, + 3421, 2294, 3140, + 3420, 2295, 3140, + 3420, 2297, 3139, + 3419, 2300, 3139, + 3419, 2304, 3138, + 3418, 2309, 3136, + 3417, 2315, 3135, + 3415, 2324, 3132, + 3413, 2335, 3129, + 3410, 2349, 3125, + 3406, 2368, 3120, + 3401, 2392, 3112, + 3393, 2421, 3102, + 3384, 2459, 3087, + 3370, 2504, 3067, + 3351, 2558, 3039, + 3325, 2622, 2999, + 3287, 2696, 2939, + 3231, 2778, 2844, + 3143, 2869, 2673, + 2991, 2968, 2248, + 2646, 3074, 0, + 0, 3185, 0, + 0, 3301, 0, + 0, 3421, 0, + 0, 3543, 0, + 0, 3668, 0, + 3554, 2408, 3269, + 3554, 2408, 3269, + 3554, 2408, 3269, + 3554, 2409, 3269, + 3554, 2410, 3269, + 3554, 2411, 3269, + 3554, 2412, 3268, + 3553, 2413, 3268, + 3553, 2416, 3268, + 3553, 2418, 3267, + 3552, 2422, 3266, + 3551, 2427, 3265, + 3550, 2434, 3263, + 3548, 2443, 3261, + 3546, 2454, 3257, + 3543, 2469, 3253, + 3539, 2488, 3248, + 3534, 2512, 3240, + 3527, 2543, 3229, + 3517, 2581, 3215, + 3503, 2627, 3195, + 3485, 2683, 3167, + 3458, 2747, 3126, + 3421, 2822, 3065, + 3365, 2905, 2968, + 3277, 2998, 2794, + 3126, 3097, 2352, + 2784, 3204, 0, + 0, 3315, 0, + 0, 3432, 0, + 0, 3552, 0, + 0, 3674, 0, + 3687, 2529, 3399, + 3687, 2529, 3399, + 3687, 2529, 3399, + 3687, 2530, 3398, + 3687, 2530, 3398, + 3687, 2531, 3398, + 3687, 2532, 3398, + 3687, 2533, 3398, + 3686, 2535, 3397, + 3686, 2537, 3397, + 3685, 2540, 3396, + 3685, 2544, 3395, + 3684, 2549, 3394, + 3683, 2556, 3392, + 3681, 2565, 3390, + 3679, 2576, 3387, + 3676, 2591, 3382, + 3672, 2611, 3377, + 3667, 2636, 3369, + 3660, 2667, 3358, + 3650, 2706, 3344, + 3636, 2753, 3324, + 3618, 2809, 3295, + 3591, 2874, 3254, + 3554, 2950, 3192, + 3498, 3034, 3094, + 3411, 3127, 2918, + 3260, 3227, 2461, + 2920, 3334, 0, + 0, 3446, 0, + 0, 3563, 0, + 0, 3683, 0, + 3820, 2652, 3529, + 3820, 2652, 3529, + 3820, 2653, 3528, + 3820, 2653, 3528, + 3820, 2653, 3528, + 3820, 2654, 3528, + 3820, 2655, 3528, + 3820, 2656, 3528, + 3819, 2657, 3528, + 3819, 2658, 3527, + 3819, 2661, 3527, + 3818, 2664, 3526, + 3817, 2668, 3525, + 3817, 2673, 3524, + 3815, 2680, 3522, + 3814, 2689, 3519, + 3812, 2701, 3516, + 3809, 2716, 3512, + 3805, 2736, 3506, + 3799, 2761, 3499, + 3792, 2793, 3488, + 3782, 2832, 3473, + 3769, 2880, 3453, + 3750, 2936, 3424, + 3724, 3003, 3383, + 3687, 3078, 3321, + 3631, 3163, 3222, + 3544, 3257, 3044, + 3394, 3357, 2575, + 3056, 3465, 0, + 0, 3577, 0, + 0, 3694, 0, + 3953, 2778, 3659, + 3953, 2778, 3659, + 3953, 2778, 3659, + 3953, 2778, 3659, + 3952, 2779, 3659, + 3952, 2779, 3659, + 3952, 2780, 3659, + 3952, 2780, 3658, + 3952, 2781, 3658, + 3952, 2783, 3658, + 3952, 2784, 3658, + 3951, 2787, 3657, + 3951, 2790, 3656, + 3950, 2794, 3655, + 3949, 2799, 3654, + 3948, 2806, 3652, + 3946, 2815, 3650, + 3944, 2827, 3647, + 3941, 2843, 3642, + 3937, 2863, 3637, + 3932, 2888, 3629, + 3925, 2920, 3618, + 3915, 2960, 3604, + 3902, 3008, 3583, + 3883, 3065, 3554, + 3857, 3132, 3513, + 3819, 3208, 3450, + 3764, 3293, 3351, + 3677, 3387, 3171, + 3527, 3488, 2694, + 3190, 3596, 0, + 0, 3708, 0, + 4085, 2905, 3790, + 4085, 2905, 3790, + 4085, 2905, 3790, + 4085, 2905, 3790, + 4085, 2906, 3790, + 4085, 2906, 3790, + 4085, 2906, 3790, + 4085, 2907, 3789, + 4085, 2908, 3789, + 4084, 2909, 3789, + 4084, 2910, 3789, + 4084, 2912, 3788, + 4084, 2914, 3788, + 4083, 2917, 3787, + 4082, 2921, 3786, + 4082, 2926, 3785, + 4080, 2933, 3783, + 4079, 2943, 3781, + 4077, 2955, 3778, + 4074, 2971, 3773, + 4070, 2991, 3768, + 4064, 3017, 3760, + 4057, 3049, 3749, + 4047, 3089, 3734, + 4034, 3137, 3714, + 4015, 3195, 3685, + 3989, 3262, 3643, + 3952, 3338, 3581, + 3896, 3424, 3481, + 3810, 3518, 3299, + 3660, 3619, 2815, + 3324, 3727, 0, + 4095, 3033, 3921, + 4095, 3034, 3921, + 4095, 3034, 3921, + 4095, 3034, 3921, + 4095, 3034, 3921, + 4095, 3034, 3921, + 4095, 3034, 3921, + 4095, 3035, 3921, + 4095, 3035, 3921, + 4095, 3036, 3920, + 4095, 3037, 3920, + 4095, 3038, 3920, + 4095, 3040, 3920, + 4095, 3042, 3919, + 4095, 3046, 3918, + 4095, 3050, 3917, + 4095, 3055, 3916, + 4095, 3062, 3914, + 4095, 3072, 3912, + 4095, 3084, 3909, + 4095, 3100, 3904, + 4095, 3120, 3899, + 4095, 3146, 3891, + 4095, 3178, 3880, + 4095, 3218, 3865, + 4095, 3267, 3845, + 4095, 3325, 3816, + 4095, 3392, 3774, + 4084, 3469, 3711, + 4029, 3555, 3611, + 3942, 3649, 3429, + 3793, 3751, 2939, + 4095, 3163, 4053, + 4095, 3163, 4052, + 4095, 3163, 4052, + 4095, 3163, 4052, + 4095, 3163, 4052, + 4095, 3163, 4052, + 4095, 3164, 4052, + 4095, 3164, 4052, + 4095, 3164, 4052, + 4095, 3165, 4052, + 4095, 3166, 4052, + 4095, 3167, 4052, + 4095, 3168, 4051, + 4095, 3170, 4051, + 4095, 3172, 4050, + 4095, 3175, 4050, + 4095, 3179, 4049, + 4095, 3185, 4047, + 4095, 3192, 4046, + 4095, 3201, 4043, + 4095, 3213, 4040, + 4095, 3229, 4036, + 4095, 3250, 4030, + 4095, 3276, 4022, + 4095, 3308, 4011, + 4095, 3349, 3997, + 4095, 3397, 3976, + 4095, 3455, 3947, + 4095, 3523, 3905, + 4095, 3600, 3842, + 4095, 3686, 3742, + 4075, 3780, 3559, + 0, 1476, 1739, + 0, 1478, 1737, + 0, 1481, 1735, + 0, 1485, 1731, + 0, 1490, 1726, + 0, 1497, 1719, + 0, 1506, 1710, + 0, 1518, 1698, + 0, 1533, 1681, + 0, 1552, 1657, + 0, 1577, 1622, + 0, 1609, 1572, + 0, 1647, 1494, + 0, 1695, 1365, + 0, 1751, 1099, + 0, 1817, 0, + 0, 1892, 0, + 0, 1976, 0, + 0, 2069, 0, + 0, 2170, 0, + 0, 2277, 0, + 0, 2389, 0, + 0, 2506, 0, + 0, 2626, 0, + 0, 2749, 0, + 0, 2874, 0, + 0, 3001, 0, + 0, 3129, 0, + 0, 3258, 0, + 0, 3388, 0, + 0, 3518, 0, + 0, 3649, 0, + 0, 1477, 1742, + 0, 1479, 1740, + 0, 1482, 1738, + 0, 1486, 1734, + 0, 1491, 1729, + 0, 1498, 1723, + 0, 1507, 1713, + 0, 1518, 1701, + 0, 1533, 1684, + 0, 1553, 1660, + 0, 1578, 1626, + 0, 1609, 1576, + 0, 1648, 1500, + 0, 1695, 1371, + 0, 1751, 1111, + 0, 1817, 0, + 0, 1892, 0, + 0, 1977, 0, + 0, 2070, 0, + 0, 2170, 0, + 0, 2277, 0, + 0, 2389, 0, + 0, 2506, 0, + 0, 2626, 0, + 0, 2749, 0, + 0, 2874, 0, + 0, 3001, 0, + 0, 3129, 0, + 0, 3258, 0, + 0, 3388, 0, + 0, 3519, 0, + 0, 3649, 0, + 0, 1478, 1746, + 0, 1480, 1744, + 0, 1483, 1742, + 0, 1487, 1738, + 0, 1492, 1733, + 0, 1499, 1727, + 0, 1507, 1718, + 0, 1519, 1706, + 0, 1534, 1689, + 0, 1554, 1665, + 0, 1579, 1631, + 0, 1610, 1582, + 0, 1649, 1506, + 0, 1696, 1380, + 0, 1752, 1127, + 0, 1818, 0, + 0, 1893, 0, + 0, 1977, 0, + 0, 2070, 0, + 0, 2170, 0, + 0, 2277, 0, + 0, 2389, 0, + 0, 2506, 0, + 0, 2626, 0, + 0, 2749, 0, + 0, 2874, 0, + 0, 3001, 0, + 0, 3129, 0, + 0, 3258, 0, + 0, 3388, 0, + 0, 3519, 0, + 0, 3649, 0, + 0, 1479, 1752, + 0, 1481, 1750, + 0, 1484, 1747, + 0, 1488, 1744, + 0, 1493, 1739, + 0, 1500, 1732, + 0, 1509, 1723, + 0, 1520, 1711, + 0, 1535, 1695, + 0, 1555, 1671, + 0, 1580, 1638, + 0, 1611, 1590, + 0, 1650, 1515, + 0, 1696, 1392, + 0, 1753, 1147, + 0, 1818, 0, + 0, 1893, 0, + 0, 1978, 0, + 0, 2070, 0, + 0, 2171, 0, + 0, 2277, 0, + 0, 2389, 0, + 0, 2506, 0, + 0, 2626, 0, + 0, 2749, 0, + 0, 2874, 0, + 0, 3001, 0, + 0, 3129, 0, + 0, 3258, 0, + 0, 3388, 0, + 0, 3519, 0, + 0, 3649, 0, + 0, 1481, 1759, + 0, 1483, 1757, + 0, 1486, 1754, + 0, 1490, 1751, + 0, 1495, 1746, + 0, 1502, 1740, + 0, 1510, 1731, + 0, 1522, 1719, + 0, 1537, 1703, + 0, 1556, 1680, + 0, 1581, 1647, + 0, 1612, 1600, + 0, 1651, 1527, + 0, 1698, 1407, + 0, 1754, 1173, + 0, 1819, 122, + 0, 1894, 0, + 0, 1978, 0, + 0, 2071, 0, + 0, 2171, 0, + 0, 2278, 0, + 0, 2390, 0, + 0, 2506, 0, + 0, 2626, 0, + 0, 2749, 0, + 0, 2874, 0, + 0, 3001, 0, + 0, 3129, 0, + 0, 3258, 0, + 0, 3388, 0, + 0, 3519, 0, + 0, 3649, 0, + 0, 1483, 1768, + 0, 1485, 1766, + 0, 1488, 1763, + 0, 1492, 1760, + 0, 1497, 1755, + 0, 1504, 1749, + 0, 1513, 1741, + 0, 1524, 1729, + 0, 1539, 1713, + 0, 1558, 1691, + 0, 1583, 1659, + 0, 1614, 1612, + 0, 1652, 1542, + 0, 1699, 1427, + 0, 1755, 1206, + 0, 1820, 376, + 0, 1895, 0, + 0, 1979, 0, + 0, 2071, 0, + 0, 2171, 0, + 0, 2278, 0, + 0, 2390, 0, + 0, 2506, 0, + 0, 2626, 0, + 0, 2749, 0, + 0, 2874, 0, + 0, 3001, 0, + 0, 3129, 0, + 0, 3258, 0, + 0, 3388, 0, + 0, 3519, 0, + 0, 3649, 0, + 0, 1486, 1780, + 0, 1488, 1778, + 0, 1491, 1776, + 0, 1495, 1772, + 0, 1500, 1768, + 0, 1507, 1762, + 0, 1516, 1753, + 0, 1527, 1742, + 0, 1542, 1726, + 0, 1561, 1705, + 0, 1586, 1674, + 0, 1616, 1629, + 0, 1655, 1562, + 0, 1701, 1452, + 0, 1757, 1246, + 0, 1822, 581, + 0, 1896, 0, + 0, 1980, 0, + 0, 2072, 0, + 0, 2172, 0, + 0, 2279, 0, + 0, 2390, 0, + 0, 2507, 0, + 0, 2627, 0, + 0, 2750, 0, + 0, 2875, 0, + 0, 3001, 0, + 0, 3129, 0, + 0, 3258, 0, + 0, 3388, 0, + 0, 3519, 0, + 0, 3649, 0, + 0, 1490, 1795, + 0, 1493, 1794, + 0, 1495, 1791, + 0, 1499, 1788, + 0, 1504, 1784, + 0, 1511, 1778, + 0, 1519, 1770, + 0, 1531, 1759, + 0, 1546, 1744, + 0, 1565, 1723, + 0, 1589, 1694, + 0, 1620, 1651, + 0, 1657, 1587, + 0, 1704, 1484, + 0, 1759, 1294, + 0, 1824, 762, + 0, 1898, 0, + 0, 1981, 0, + 0, 2073, 0, + 0, 2173, 0, + 0, 2279, 0, + 0, 2391, 0, + 0, 2507, 0, + 0, 2627, 0, + 0, 2750, 0, + 0, 2875, 0, + 0, 3001, 0, + 0, 3129, 0, + 0, 3259, 0, + 0, 3388, 0, + 0, 3519, 0, + 0, 3649, 0, + 0, 1496, 1815, + 0, 1498, 1814, + 0, 1501, 1811, + 0, 1505, 1808, + 0, 1510, 1804, + 0, 1516, 1799, + 0, 1525, 1791, + 0, 1536, 1781, + 0, 1551, 1766, + 0, 1569, 1746, + 0, 1593, 1718, + 0, 1624, 1678, + 0, 1661, 1618, + 0, 1707, 1522, + 0, 1762, 1352, + 0, 1826, 927, + 0, 1900, 0, + 0, 1983, 0, + 0, 2075, 0, + 0, 2174, 0, + 0, 2280, 0, + 0, 2392, 0, + 0, 2508, 0, + 0, 2628, 0, + 0, 2750, 0, + 0, 2875, 0, + 0, 3002, 0, + 0, 3130, 0, + 0, 3259, 0, + 0, 3388, 0, + 0, 3519, 0, + 0, 3649, 0, + 0, 1503, 1841, + 0, 1505, 1839, + 0, 1508, 1837, + 0, 1512, 1834, + 0, 1517, 1830, + 0, 1523, 1825, + 0, 1532, 1818, + 0, 1543, 1808, + 0, 1557, 1795, + 0, 1576, 1776, + 0, 1599, 1750, + 0, 1629, 1712, + 0, 1666, 1657, + 0, 1712, 1570, + 0, 1766, 1419, + 0, 1830, 1082, + 0, 1903, 0, + 0, 1986, 0, + 0, 2077, 0, + 0, 2176, 0, + 0, 2282, 0, + 0, 2393, 0, + 0, 2509, 0, + 0, 2628, 0, + 0, 2751, 0, + 0, 2875, 0, + 0, 3002, 0, + 0, 3130, 0, + 0, 3259, 0, + 0, 3388, 0, + 0, 3519, 0, + 0, 3650, 0, + 964, 1513, 1873, + 949, 1515, 1871, + 928, 1518, 1869, + 899, 1521, 1867, + 857, 1526, 1863, + 794, 1532, 1858, + 692, 1541, 1851, + 507, 1551, 1842, + 0, 1566, 1830, + 0, 1584, 1813, + 0, 1607, 1788, + 0, 1637, 1754, + 0, 1673, 1704, + 0, 1718, 1626, + 0, 1771, 1496, + 0, 1835, 1231, + 0, 1907, 0, + 0, 1989, 0, + 0, 2080, 0, + 0, 2178, 0, + 0, 2283, 0, + 0, 2394, 0, + 0, 2510, 0, + 0, 2629, 0, + 0, 2751, 0, + 0, 2876, 0, + 0, 3002, 0, + 0, 3130, 0, + 0, 3259, 0, + 0, 3389, 0, + 0, 3519, 0, + 0, 3650, 0, + 1342, 1525, 1912, + 1336, 1527, 1911, + 1327, 1530, 1909, + 1315, 1533, 1907, + 1299, 1538, 1903, + 1276, 1544, 1899, + 1243, 1552, 1893, + 1195, 1563, 1884, + 1123, 1577, 1873, + 1003, 1595, 1857, + 767, 1617, 1836, + 0, 1646, 1805, + 0, 1682, 1760, + 0, 1726, 1692, + 0, 1779, 1582, + 0, 1841, 1375, + 0, 1912, 699, + 0, 1994, 0, + 0, 2083, 0, + 0, 2181, 0, + 0, 2286, 0, + 0, 2396, 0, + 0, 2511, 0, + 0, 2630, 0, + 0, 2752, 0, + 0, 2877, 0, + 0, 3003, 0, + 0, 3130, 0, + 0, 3259, 0, + 0, 3389, 0, + 0, 3519, 0, + 0, 3650, 0, + 1598, 1542, 1960, + 1594, 1543, 1959, + 1589, 1546, 1957, + 1582, 1549, 1955, + 1573, 1554, 1952, + 1561, 1560, 1948, + 1544, 1568, 1943, + 1520, 1578, 1935, + 1486, 1591, 1925, + 1436, 1608, 1911, + 1359, 1631, 1892, + 1230, 1659, 1865, + 968, 1693, 1826, + 0, 1736, 1768, + 0, 1788, 1676, + 0, 1849, 1516, + 0, 1919, 1135, + 0, 1999, 0, + 0, 2088, 0, + 0, 2185, 0, + 0, 2289, 0, + 0, 2398, 0, + 0, 2513, 0, + 0, 2632, 0, + 0, 2753, 0, + 0, 2877, 0, + 0, 3003, 0, + 0, 3131, 0, + 0, 3260, 0, + 0, 3389, 0, + 0, 3519, 0, + 0, 3650, 0, + 1804, 1562, 2017, + 1802, 1564, 2016, + 1799, 1567, 2015, + 1795, 1570, 2013, + 1789, 1574, 2010, + 1781, 1580, 2007, + 1771, 1587, 2002, + 1756, 1597, 1995, + 1737, 1610, 1987, + 1708, 1626, 1974, + 1668, 1648, 1958, + 1607, 1675, 1934, + 1511, 1708, 1901, + 1338, 1750, 1852, + 901, 1800, 1778, + 0, 1860, 1654, + 0, 1929, 1408, + 0, 2007, 0, + 0, 2095, 0, + 0, 2190, 0, + 0, 2293, 0, + 0, 2402, 0, + 0, 2515, 0, + 0, 2633, 0, + 0, 2755, 0, + 0, 2878, 0, + 0, 3004, 0, + 0, 3132, 0, + 0, 3260, 0, + 0, 3389, 0, + 0, 3520, 0, + 0, 3650, 0, + 1985, 1589, 2084, + 1983, 1591, 2083, + 1981, 1593, 2082, + 1979, 1596, 2080, + 1975, 1600, 2078, + 1970, 1605, 2075, + 1963, 1612, 2071, + 1953, 1622, 2065, + 1941, 1634, 2058, + 1923, 1650, 2047, + 1898, 1670, 2033, + 1862, 1695, 2013, + 1810, 1728, 1985, + 1729, 1768, 1945, + 1591, 1816, 1886, + 1299, 1874, 1791, + 0, 1941, 1623, + 0, 2017, 1207, + 0, 2103, 0, + 0, 2197, 0, + 0, 2298, 0, + 0, 2406, 0, + 0, 2519, 0, + 0, 2636, 0, + 0, 2757, 0, + 0, 2880, 0, + 0, 3005, 0, + 0, 3132, 0, + 0, 3261, 0, + 0, 3390, 0, + 0, 3520, 0, + 0, 3650, 0, + 2150, 1622, 2160, + 2149, 1623, 2159, + 2148, 1626, 2158, + 2146, 1628, 2157, + 2143, 1632, 2155, + 2140, 1637, 2152, + 2135, 1644, 2149, + 2129, 1653, 2144, + 2120, 1664, 2138, + 2108, 1679, 2129, + 2092, 1698, 2117, + 2069, 1722, 2101, + 2036, 1752, 2078, + 1989, 1790, 2046, + 1916, 1836, 1999, + 1796, 1892, 1927, + 1562, 1956, 1808, + 499, 2030, 1577, + 0, 2114, 586, + 0, 2206, 0, + 0, 2305, 0, + 0, 2412, 0, + 0, 2523, 0, + 0, 2639, 0, + 0, 2759, 0, + 0, 2882, 0, + 0, 3007, 0, + 0, 3134, 0, + 0, 3262, 0, + 0, 3391, 0, + 0, 3520, 0, + 0, 3651, 0, + 2306, 1663, 2246, + 2305, 1664, 2245, + 2304, 1666, 2244, + 2303, 1669, 2243, + 2301, 1672, 2241, + 2298, 1677, 2239, + 2295, 1683, 2236, + 2291, 1691, 2232, + 2284, 1701, 2227, + 2276, 1715, 2220, + 2265, 1732, 2210, + 2249, 1755, 2197, + 2228, 1783, 2179, + 2197, 1819, 2153, + 2153, 1862, 2116, + 2085, 1915, 2061, + 1976, 1976, 1976, + 1771, 2047, 1830, + 1120, 2128, 1507, + 0, 2217, 0, + 0, 2315, 0, + 0, 2419, 0, + 0, 2529, 0, + 0, 2644, 0, + 0, 2763, 0, + 0, 2885, 0, + 0, 3009, 0, + 0, 3135, 0, + 0, 3263, 0, + 0, 3392, 0, + 0, 3521, 0, + 0, 3651, 0, + 2455, 1712, 2339, + 2454, 1713, 2339, + 2453, 1715, 2338, + 2452, 1717, 2337, + 2451, 1721, 2336, + 2449, 1725, 2334, + 2447, 1730, 2332, + 2444, 1737, 2328, + 2439, 1747, 2324, + 2434, 1759, 2318, + 2426, 1775, 2311, + 2415, 1796, 2300, + 2400, 1822, 2285, + 2379, 1854, 2265, + 2350, 1895, 2237, + 2307, 1944, 2195, + 2243, 2002, 2134, + 2141, 2069, 2035, + 1954, 2146, 1857, + 1434, 2233, 1394, + 0, 2327, 0, + 0, 2429, 0, + 0, 2537, 0, + 0, 2650, 0, + 0, 2767, 0, + 0, 2888, 0, + 0, 3012, 0, + 0, 3137, 0, + 0, 3264, 0, + 0, 3393, 0, + 0, 3522, 0, + 0, 3652, 0, + 2599, 1771, 2440, + 2598, 1772, 2440, + 2598, 1773, 2439, + 2597, 1775, 2438, + 2596, 1778, 2437, + 2595, 1782, 2436, + 2593, 1787, 2434, + 2591, 1793, 2432, + 2588, 1801, 2428, + 2584, 1812, 2424, + 2578, 1827, 2418, + 2570, 1845, 2409, + 2560, 1868, 2398, + 2545, 1898, 2382, + 2525, 1935, 2360, + 2496, 1980, 2329, + 2455, 2034, 2284, + 2394, 2097, 2215, + 2296, 2170, 2104, + 2120, 2252, 1892, + 1666, 2343, 1176, + 0, 2441, 0, + 0, 2547, 0, + 0, 2658, 0, + 0, 2773, 0, + 0, 2893, 0, + 0, 3015, 0, + 0, 3140, 0, + 0, 3266, 0, + 0, 3394, 0, + 0, 3523, 0, + 0, 3653, 0, + 2740, 1839, 2548, + 2740, 1840, 2547, + 2739, 1841, 2547, + 2739, 1843, 2546, + 2738, 1845, 2545, + 2737, 1848, 2544, + 2736, 1853, 2543, + 2734, 1858, 2541, + 2732, 1865, 2538, + 2729, 1875, 2535, + 2725, 1887, 2530, + 2719, 1903, 2523, + 2711, 1924, 2514, + 2701, 1950, 2502, + 2687, 1983, 2486, + 2667, 2024, 2462, + 2639, 2073, 2429, + 2599, 2132, 2380, + 2539, 2199, 2305, + 2445, 2277, 2181, + 2277, 2363, 1934, + 1861, 2458, 400, + 0, 2560, 0, + 0, 2668, 0, + 0, 2781, 0, + 0, 2899, 0, + 0, 3020, 0, + 0, 3144, 0, + 0, 3269, 0, + 0, 3396, 0, + 0, 3525, 0, + 0, 3654, 0, + 2878, 1917, 2660, + 2878, 1917, 2660, + 2878, 1919, 2660, + 2878, 1920, 2659, + 2877, 1922, 2659, + 2876, 1925, 2658, + 2875, 1928, 2657, + 2874, 1933, 2655, + 2872, 1939, 2653, + 2870, 1947, 2650, + 2867, 1958, 2646, + 2863, 1972, 2641, + 2858, 1989, 2635, + 2850, 2012, 2625, + 2840, 2041, 2613, + 2826, 2077, 2595, + 2807, 2121, 2570, + 2779, 2174, 2535, + 2740, 2236, 2483, + 2681, 2308, 2403, + 2589, 2389, 2268, + 2426, 2479, 1986, + 2035, 2577, 0, + 0, 2682, 0, + 0, 2792, 0, + 0, 2907, 0, + 0, 3026, 0, + 0, 3148, 0, + 0, 3273, 0, + 0, 3399, 0, + 0, 3527, 0, + 0, 3656, 0, + 3015, 2003, 2777, + 3015, 2004, 2777, + 3015, 2005, 2777, + 3015, 2006, 2776, + 3014, 2008, 2776, + 3014, 2010, 2775, + 3013, 2013, 2774, + 3012, 2017, 2773, + 3011, 2022, 2772, + 3009, 2029, 2770, + 3007, 2038, 2767, + 3004, 2049, 2763, + 3000, 2064, 2758, + 2995, 2084, 2751, + 2987, 2108, 2741, + 2977, 2140, 2728, + 2963, 2178, 2709, + 2944, 2225, 2684, + 2917, 2281, 2647, + 2878, 2347, 2593, + 2821, 2422, 2508, + 2730, 2506, 2363, + 2570, 2599, 2046, + 2196, 2699, 0, + 0, 2806, 0, + 0, 2918, 0, + 0, 3034, 0, + 0, 3155, 0, + 0, 3278, 0, + 0, 3403, 0, + 0, 3529, 0, + 0, 3658, 0, + 3151, 2098, 2898, + 3151, 2099, 2898, + 3151, 2099, 2897, + 3150, 2100, 2897, + 3150, 2102, 2897, + 3150, 2104, 2896, + 3149, 2106, 2896, + 3149, 2109, 2895, + 3148, 2113, 2893, + 3147, 2119, 2892, + 3145, 2126, 2890, + 3143, 2136, 2887, + 3140, 2148, 2883, + 3136, 2164, 2877, + 3130, 2185, 2870, + 3123, 2212, 2860, + 3113, 2245, 2847, + 3099, 2286, 2828, + 3080, 2335, 2801, + 3053, 2394, 2763, + 3015, 2462, 2707, + 2958, 2540, 2619, + 2868, 2626, 2466, + 2712, 2721, 2116, + 2349, 2823, 0, + 0, 2932, 0, + 0, 3045, 0, + 0, 3163, 0, + 0, 3284, 0, + 0, 3407, 0, + 0, 3533, 0, + 0, 3660, 0, + 3286, 2200, 3021, + 3286, 2201, 3021, + 3286, 2201, 3021, + 3285, 2202, 3021, + 3285, 2203, 3020, + 3285, 2205, 3020, + 3284, 2206, 3019, + 3284, 2209, 3019, + 3283, 2212, 3018, + 3282, 2217, 3016, + 3281, 2223, 3015, + 3280, 2231, 3013, + 3277, 2241, 3010, + 3274, 2254, 3006, + 3270, 2271, 3000, + 3265, 2293, 2993, + 3258, 2321, 2983, + 3248, 2356, 2969, + 3234, 2398, 2949, + 3215, 2450, 2922, + 3189, 2511, 2883, + 3151, 2581, 2825, + 3094, 2661, 2734, + 3005, 2749, 2574, + 2850, 2846, 2196, + 2495, 2950, 0, + 0, 3059, 0, + 0, 3174, 0, + 0, 3292, 0, + 0, 3414, 0, + 0, 3538, 0, + 0, 3664, 0, + 3420, 2309, 3146, + 3420, 2309, 3146, + 3420, 2309, 3146, + 3420, 2310, 3146, + 3419, 2311, 3146, + 3419, 2312, 3145, + 3419, 2313, 3145, + 3418, 2315, 3145, + 3418, 2318, 3144, + 3417, 2322, 3143, + 3416, 2326, 3142, + 3415, 2333, 3140, + 3414, 2341, 3138, + 3411, 2351, 3135, + 3408, 2365, 3131, + 3404, 2383, 3125, + 3399, 2406, 3117, + 3392, 2435, 3107, + 3382, 2471, 3093, + 3368, 2516, 3074, + 3350, 2569, 3046, + 3323, 2631, 3006, + 3285, 2703, 2947, + 3229, 2785, 2853, + 3141, 2875, 2688, + 2988, 2973, 2284, + 2638, 3077, 0, + 0, 3188, 0, + 0, 3303, 0, + 0, 3422, 0, + 0, 3544, 0, + 0, 3669, 0, + 3553, 2422, 3273, + 3553, 2422, 3273, + 3553, 2423, 3273, + 3553, 2423, 3273, + 3553, 2424, 3273, + 3553, 2425, 3273, + 3553, 2426, 3272, + 3552, 2427, 3272, + 3552, 2430, 3271, + 3552, 2432, 3271, + 3551, 2436, 3270, + 3550, 2441, 3269, + 3549, 2447, 3267, + 3547, 2456, 3265, + 3545, 2467, 3261, + 3542, 2481, 3257, + 3538, 2500, 3252, + 3533, 2524, 3244, + 3525, 2554, 3234, + 3516, 2591, 3219, + 3502, 2636, 3200, + 3483, 2690, 3172, + 3457, 2754, 3131, + 3419, 2828, 3071, + 3363, 2910, 2976, + 3275, 3002, 2805, + 3123, 3100, 2380, + 2778, 3206, 0, + 0, 3317, 0, + 0, 3433, 0, + 0, 3553, 0, + 0, 3675, 0, + 3687, 2540, 3402, + 3687, 2540, 3402, + 3686, 2540, 3401, + 3686, 2541, 3401, + 3686, 2541, 3401, + 3686, 2542, 3401, + 3686, 2543, 3401, + 3686, 2544, 3401, + 3686, 2545, 3400, + 3685, 2548, 3400, + 3685, 2550, 3399, + 3684, 2554, 3398, + 3683, 2559, 3397, + 3682, 2566, 3395, + 3680, 2575, 3393, + 3678, 2586, 3390, + 3675, 2601, 3385, + 3671, 2620, 3380, + 3666, 2644, 3372, + 3659, 2675, 3362, + 3649, 2713, 3347, + 3635, 2759, 3327, + 3617, 2815, 3299, + 3590, 2880, 3258, + 3553, 2954, 3197, + 3497, 3038, 3100, + 3410, 3130, 2926, + 3258, 3229, 2484, + 2916, 3336, 0, + 0, 3448, 0, + 0, 3564, 0, + 0, 3684, 0, + 3819, 2661, 3531, + 3819, 2661, 3531, + 3819, 2661, 3531, + 3819, 2661, 3531, + 3819, 2662, 3531, + 3819, 2662, 3530, + 3819, 2663, 3530, + 3819, 2664, 3530, + 3819, 2665, 3530, + 3818, 2667, 3529, + 3818, 2669, 3529, + 3818, 2672, 3528, + 3817, 2676, 3527, + 3816, 2681, 3526, + 3815, 2688, 3524, + 3813, 2697, 3522, + 3811, 2708, 3519, + 3808, 2723, 3514, + 3804, 2743, 3509, + 3799, 2768, 3501, + 3792, 2799, 3490, + 3782, 2838, 3476, + 3768, 2885, 3456, + 3750, 2941, 3427, + 3723, 3007, 3386, + 3686, 3082, 3325, + 3630, 3166, 3227, + 3543, 3259, 3050, + 3392, 3359, 2593, + 3052, 3466, 0, + 0, 3578, 0, + 0, 3695, 0, + 3952, 2784, 3661, + 3952, 2784, 3661, + 3952, 2785, 3661, + 3952, 2785, 3661, + 3952, 2785, 3661, + 3952, 2785, 3660, + 3952, 2786, 3660, + 3952, 2787, 3660, + 3952, 2788, 3660, + 3951, 2789, 3660, + 3951, 2791, 3659, + 3951, 2793, 3659, + 3950, 2796, 3658, + 3950, 2800, 3657, + 3949, 2805, 3656, + 3947, 2812, 3654, + 3946, 2821, 3652, + 3944, 2833, 3648, + 3941, 2848, 3644, + 3937, 2868, 3638, + 3932, 2893, 3631, + 3924, 2925, 3620, + 3915, 2964, 3605, + 3901, 3012, 3585, + 3882, 3068, 3556, + 3856, 3135, 3515, + 3819, 3211, 3453, + 3763, 3295, 3354, + 3676, 3389, 3176, + 3526, 3489, 2707, + 3188, 3597, 0, + 0, 3709, 0, + 4085, 2910, 3791, + 4085, 2910, 3791, + 4085, 2910, 3791, + 4085, 2910, 3791, + 4085, 2911, 3791, + 4085, 2911, 3791, + 4085, 2911, 3791, + 4084, 2912, 3791, + 4084, 2912, 3791, + 4084, 2913, 3790, + 4084, 2915, 3790, + 4084, 2916, 3790, + 4083, 2919, 3789, + 4083, 2922, 3788, + 4082, 2926, 3787, + 4081, 2931, 3786, + 4080, 2938, 3784, + 4078, 2947, 3782, + 4076, 2959, 3779, + 4073, 2975, 3775, + 4069, 2995, 3769, + 4064, 3020, 3761, + 4057, 3052, 3750, + 4047, 3092, 3736, + 4034, 3140, 3715, + 4015, 3197, 3686, + 3989, 3264, 3645, + 3951, 3340, 3583, + 3896, 3425, 3483, + 3809, 3519, 3303, + 3659, 3620, 2826, + 3322, 3728, 0, + 4095, 3037, 3922, + 4095, 3037, 3922, + 4095, 3037, 3922, + 4095, 3037, 3922, + 4095, 3038, 3922, + 4095, 3038, 3922, + 4095, 3038, 3922, + 4095, 3039, 3922, + 4095, 3039, 3922, + 4095, 3040, 3921, + 4095, 3041, 3921, + 4095, 3042, 3921, + 4095, 3044, 3920, + 4095, 3046, 3920, + 4095, 3049, 3919, + 4095, 3053, 3918, + 4095, 3059, 3917, + 4095, 3066, 3915, + 4095, 3075, 3913, + 4095, 3087, 3910, + 4095, 3103, 3905, + 4095, 3123, 3900, + 4095, 3149, 3892, + 4095, 3181, 3881, + 4095, 3221, 3866, + 4095, 3269, 3846, + 4095, 3327, 3817, + 4095, 3394, 3775, + 4084, 3470, 3713, + 4029, 3556, 3613, + 3942, 3650, 3432, + 3792, 3751, 2947, + 4095, 3166, 4053, + 4095, 3166, 4053, + 4095, 3166, 4053, + 4095, 3166, 4053, + 4095, 3166, 4053, + 4095, 3166, 4053, + 4095, 3166, 4053, + 4095, 3167, 4053, + 4095, 3167, 4053, + 4095, 3168, 4053, + 4095, 3168, 4053, + 4095, 3169, 4052, + 4095, 3171, 4052, + 4095, 3172, 4052, + 4095, 3175, 4051, + 4095, 3178, 4050, + 4095, 3182, 4049, + 4095, 3187, 4048, + 4095, 3194, 4046, + 4095, 3204, 4044, + 4095, 3216, 4041, + 4095, 3232, 4037, + 4095, 3252, 4031, + 4095, 3278, 4023, + 4095, 3310, 4012, + 4095, 3350, 3997, + 4095, 3399, 3977, + 4095, 3457, 3948, + 4095, 3524, 3906, + 4095, 3601, 3843, + 4095, 3687, 3743, + 4074, 3781, 3561, + 0, 1606, 1871, + 0, 1607, 1869, + 0, 1610, 1867, + 0, 1612, 1864, + 0, 1616, 1861, + 0, 1622, 1856, + 0, 1628, 1849, + 0, 1637, 1840, + 0, 1649, 1827, + 0, 1664, 1810, + 0, 1684, 1786, + 0, 1709, 1751, + 0, 1740, 1701, + 0, 1779, 1623, + 0, 1826, 1491, + 0, 1883, 1222, + 0, 1949, 0, + 0, 2024, 0, + 0, 2108, 0, + 0, 2201, 0, + 0, 2302, 0, + 0, 2409, 0, + 0, 2521, 0, + 0, 2638, 0, + 0, 2758, 0, + 0, 2881, 0, + 0, 3006, 0, + 0, 3133, 0, + 0, 3261, 0, + 0, 3390, 0, + 0, 3520, 0, + 0, 3651, 0, + 0, 1606, 1873, + 0, 1608, 1871, + 0, 1610, 1869, + 0, 1613, 1867, + 0, 1617, 1863, + 0, 1622, 1858, + 0, 1629, 1851, + 0, 1638, 1842, + 0, 1650, 1830, + 0, 1665, 1813, + 0, 1684, 1789, + 0, 1709, 1754, + 0, 1741, 1704, + 0, 1779, 1626, + 0, 1827, 1497, + 0, 1883, 1231, + 0, 1949, 0, + 0, 2024, 0, + 0, 2109, 0, + 0, 2202, 0, + 0, 2302, 0, + 0, 2409, 0, + 0, 2521, 0, + 0, 2638, 0, + 0, 2758, 0, + 0, 2881, 0, + 0, 3006, 0, + 0, 3133, 0, + 0, 3261, 0, + 0, 3390, 0, + 0, 3520, 0, + 0, 3651, 0, + 0, 1607, 1876, + 0, 1609, 1874, + 0, 1611, 1872, + 0, 1614, 1870, + 0, 1618, 1866, + 0, 1623, 1861, + 0, 1630, 1855, + 0, 1639, 1846, + 0, 1650, 1833, + 0, 1666, 1816, + 0, 1685, 1792, + 0, 1710, 1758, + 0, 1741, 1708, + 0, 1780, 1632, + 0, 1827, 1503, + 0, 1883, 1243, + 0, 1949, 0, + 0, 2024, 0, + 0, 2109, 0, + 0, 2202, 0, + 0, 2302, 0, + 0, 2409, 0, + 0, 2521, 0, + 0, 2638, 0, + 0, 2758, 0, + 0, 2881, 0, + 0, 3006, 0, + 0, 3133, 0, + 0, 3261, 0, + 0, 3390, 0, + 0, 3520, 0, + 0, 3651, 0, + 0, 1608, 1880, + 0, 1610, 1878, + 0, 1612, 1876, + 0, 1615, 1874, + 0, 1619, 1870, + 0, 1624, 1865, + 0, 1631, 1859, + 0, 1640, 1850, + 0, 1651, 1838, + 0, 1666, 1821, + 0, 1686, 1797, + 0, 1711, 1763, + 0, 1742, 1714, + 0, 1781, 1638, + 0, 1828, 1512, + 0, 1884, 1259, + 0, 1950, 0, + 0, 2025, 0, + 0, 2109, 0, + 0, 2202, 0, + 0, 2302, 0, + 0, 2409, 0, + 0, 2521, 0, + 0, 2638, 0, + 0, 2758, 0, + 0, 2881, 0, + 0, 3006, 0, + 0, 3133, 0, + 0, 3261, 0, + 0, 3390, 0, + 0, 3520, 0, + 0, 3651, 0, + 0, 1609, 1885, + 0, 1611, 1884, + 0, 1613, 1882, + 0, 1616, 1879, + 0, 1620, 1876, + 0, 1625, 1871, + 0, 1632, 1864, + 0, 1641, 1855, + 0, 1652, 1843, + 0, 1668, 1827, + 0, 1687, 1803, + 0, 1712, 1770, + 0, 1743, 1722, + 0, 1782, 1647, + 0, 1829, 1524, + 0, 1885, 1280, + 0, 1950, 0, + 0, 2025, 0, + 0, 2110, 0, + 0, 2202, 0, + 0, 2303, 0, + 0, 2409, 0, + 0, 2522, 0, + 0, 2638, 0, + 0, 2758, 0, + 0, 2881, 0, + 0, 3006, 0, + 0, 3133, 0, + 0, 3261, 0, + 0, 3390, 0, + 0, 3520, 0, + 0, 3651, 0, + 0, 1611, 1892, + 0, 1613, 1891, + 0, 1615, 1889, + 0, 1618, 1886, + 0, 1622, 1883, + 0, 1627, 1878, + 0, 1634, 1872, + 0, 1642, 1863, + 0, 1654, 1851, + 0, 1669, 1835, + 0, 1689, 1812, + 0, 1713, 1779, + 0, 1744, 1732, + 0, 1783, 1659, + 0, 1830, 1540, + 0, 1886, 1305, + 0, 1951, 254, + 0, 2026, 0, + 0, 2110, 0, + 0, 2203, 0, + 0, 2303, 0, + 0, 2410, 0, + 0, 2522, 0, + 0, 2638, 0, + 0, 2758, 0, + 0, 2881, 0, + 0, 3006, 0, + 0, 3133, 0, + 0, 3261, 0, + 0, 3390, 0, + 0, 3520, 0, + 0, 3651, 0, + 0, 1614, 1901, + 0, 1615, 1900, + 0, 1617, 1898, + 0, 1620, 1896, + 0, 1624, 1892, + 0, 1629, 1887, + 0, 1636, 1881, + 0, 1645, 1873, + 0, 1656, 1861, + 0, 1671, 1845, + 0, 1691, 1823, + 0, 1715, 1791, + 0, 1746, 1745, + 0, 1784, 1674, + 0, 1831, 1559, + 0, 1887, 1338, + 0, 1952, 508, + 0, 2027, 0, + 0, 2111, 0, + 0, 2203, 0, + 0, 2304, 0, + 0, 2410, 0, + 0, 2522, 0, + 0, 2639, 0, + 0, 2759, 0, + 0, 2881, 0, + 0, 3007, 0, + 0, 3133, 0, + 0, 3261, 0, + 0, 3390, 0, + 0, 3520, 0, + 0, 3651, 0, + 0, 1617, 1913, + 0, 1618, 1912, + 0, 1620, 1910, + 0, 1623, 1908, + 0, 1627, 1904, + 0, 1632, 1900, + 0, 1639, 1894, + 0, 1648, 1885, + 0, 1659, 1874, + 0, 1674, 1859, + 0, 1693, 1837, + 0, 1718, 1806, + 0, 1748, 1761, + 0, 1787, 1694, + 0, 1833, 1584, + 0, 1889, 1378, + 0, 1954, 713, + 0, 2028, 0, + 0, 2112, 0, + 0, 2204, 0, + 0, 2304, 0, + 0, 2411, 0, + 0, 2522, 0, + 0, 2639, 0, + 0, 2759, 0, + 0, 2882, 0, + 0, 3007, 0, + 0, 3133, 0, + 0, 3261, 0, + 0, 3391, 0, + 0, 3520, 0, + 0, 3651, 0, + 0, 1621, 1929, + 0, 1622, 1928, + 0, 1625, 1926, + 0, 1627, 1923, + 0, 1631, 1920, + 0, 1636, 1916, + 0, 1643, 1910, + 0, 1652, 1902, + 0, 1663, 1891, + 0, 1678, 1876, + 0, 1697, 1855, + 0, 1721, 1826, + 0, 1752, 1783, + 0, 1790, 1719, + 0, 1836, 1616, + 0, 1891, 1426, + 0, 1956, 894, + 0, 2030, 0, + 0, 2113, 0, + 0, 2206, 0, + 0, 2305, 0, + 0, 2411, 0, + 0, 2523, 0, + 0, 2639, 0, + 0, 2759, 0, + 0, 2882, 0, + 0, 3007, 0, + 0, 3134, 0, + 0, 3262, 0, + 0, 3391, 0, + 0, 3520, 0, + 0, 3651, 0, + 0, 1626, 1949, + 0, 1628, 1948, + 0, 1630, 1946, + 0, 1633, 1944, + 0, 1637, 1940, + 0, 1642, 1936, + 0, 1648, 1931, + 0, 1657, 1923, + 0, 1668, 1913, + 0, 1683, 1898, + 0, 1701, 1878, + 0, 1726, 1851, + 0, 1756, 1810, + 0, 1793, 1750, + 0, 1839, 1655, + 0, 1894, 1484, + 0, 1958, 1059, + 0, 2032, 0, + 0, 2115, 0, + 0, 2207, 0, + 0, 2306, 0, + 0, 2412, 0, + 0, 2524, 0, + 0, 2640, 0, + 0, 2760, 0, + 0, 2882, 0, + 0, 3007, 0, + 0, 3134, 0, + 0, 3262, 0, + 0, 3391, 0, + 0, 3520, 0, + 0, 3651, 0, + 0, 1634, 1974, + 0, 1635, 1973, + 0, 1637, 1971, + 0, 1640, 1969, + 0, 1644, 1966, + 0, 1649, 1962, + 0, 1655, 1957, + 0, 1664, 1950, + 0, 1675, 1940, + 0, 1689, 1927, + 0, 1708, 1908, + 0, 1731, 1882, + 0, 1761, 1844, + 0, 1798, 1789, + 0, 1844, 1702, + 0, 1898, 1552, + 0, 1962, 1214, + 0, 2035, 0, + 0, 2118, 0, + 0, 2209, 0, + 0, 2308, 0, + 0, 2414, 0, + 0, 2525, 0, + 0, 2641, 0, + 0, 2760, 0, + 0, 2883, 0, + 0, 3008, 0, + 0, 3134, 0, + 0, 3262, 0, + 0, 3391, 0, + 0, 3521, 0, + 0, 3651, 0, + 1107, 1643, 2006, + 1096, 1645, 2005, + 1081, 1647, 2003, + 1061, 1650, 2001, + 1031, 1653, 1999, + 989, 1658, 1995, + 926, 1664, 1990, + 824, 1673, 1983, + 639, 1684, 1974, + 132, 1698, 1962, + 0, 1716, 1945, + 0, 1739, 1921, + 0, 1769, 1886, + 0, 1805, 1836, + 0, 1850, 1758, + 0, 1904, 1628, + 0, 1967, 1363, + 0, 2039, 0, + 0, 2121, 0, + 0, 2212, 0, + 0, 2310, 0, + 0, 2415, 0, + 0, 2526, 0, + 0, 2642, 0, + 0, 2761, 0, + 0, 2883, 0, + 0, 3008, 0, + 0, 3134, 0, + 0, 3262, 0, + 0, 3391, 0, + 0, 3521, 0, + 0, 3651, 0, + 1479, 1656, 2045, + 1474, 1657, 2044, + 1468, 1659, 2043, + 1459, 1662, 2041, + 1447, 1666, 2039, + 1431, 1670, 2035, + 1408, 1676, 2031, + 1375, 1684, 2025, + 1327, 1695, 2016, + 1255, 1709, 2005, + 1135, 1727, 1989, + 899, 1749, 1968, + 0, 1778, 1937, + 0, 1814, 1892, + 0, 1858, 1824, + 0, 1911, 1714, + 0, 1973, 1507, + 0, 2045, 831, + 0, 2126, 0, + 0, 2215, 0, + 0, 2313, 0, + 0, 2418, 0, + 0, 2528, 0, + 0, 2643, 0, + 0, 2762, 0, + 0, 2884, 0, + 0, 3009, 0, + 0, 3135, 0, + 0, 3263, 0, + 0, 3391, 0, + 0, 3521, 0, + 0, 3651, 0, + 1732, 1672, 2093, + 1730, 1674, 2092, + 1726, 1676, 2091, + 1721, 1678, 2089, + 1715, 1681, 2087, + 1706, 1686, 2084, + 1693, 1692, 2080, + 1676, 1700, 2075, + 1652, 1710, 2067, + 1618, 1723, 2057, + 1568, 1741, 2043, + 1491, 1763, 2024, + 1362, 1791, 1997, + 1100, 1826, 1958, + 0, 1868, 1900, + 0, 1920, 1808, + 0, 1981, 1648, + 0, 2052, 1267, + 0, 2132, 0, + 0, 2220, 0, + 0, 2317, 0, + 0, 2421, 0, + 0, 2530, 0, + 0, 2645, 0, + 0, 2764, 0, + 0, 2885, 0, + 0, 3009, 0, + 0, 3136, 0, + 0, 3263, 0, + 0, 3392, 0, + 0, 3521, 0, + 0, 3651, 0, + 1938, 1693, 2150, + 1936, 1694, 2150, + 1934, 1696, 2148, + 1931, 1699, 2147, + 1927, 1702, 2145, + 1921, 1706, 2142, + 1913, 1712, 2139, + 1903, 1719, 2134, + 1889, 1729, 2127, + 1869, 1742, 2119, + 1840, 1759, 2106, + 1800, 1780, 2090, + 1739, 1807, 2066, + 1643, 1841, 2033, + 1470, 1882, 1984, + 1033, 1932, 1910, + 0, 1992, 1786, + 0, 2061, 1540, + 0, 2139, 54, + 0, 2227, 0, + 0, 2322, 0, + 0, 2425, 0, + 0, 2534, 0, + 0, 2648, 0, + 0, 2766, 0, + 0, 2887, 0, + 0, 3011, 0, + 0, 3136, 0, + 0, 3264, 0, + 0, 3392, 0, + 0, 3522, 0, + 0, 3652, 0, + 2118, 1720, 2217, + 2117, 1721, 2216, + 2116, 1723, 2215, + 2113, 1725, 2214, + 2111, 1728, 2212, + 2107, 1732, 2210, + 2102, 1737, 2207, + 2095, 1744, 2203, + 2086, 1754, 2197, + 2073, 1766, 2190, + 2055, 1782, 2179, + 2030, 1802, 2165, + 1994, 1828, 2145, + 1942, 1860, 2118, + 1861, 1900, 2077, + 1723, 1948, 2018, + 1431, 2006, 1923, + 0, 2073, 1755, + 0, 2149, 1339, + 0, 2235, 0, + 0, 2329, 0, + 0, 2430, 0, + 0, 2538, 0, + 0, 2651, 0, + 0, 2768, 0, + 0, 2889, 0, + 0, 3012, 0, + 0, 3138, 0, + 0, 3265, 0, + 0, 3393, 0, + 0, 3522, 0, + 0, 3652, 0, + 2283, 1753, 2293, + 2282, 1754, 2292, + 2281, 1756, 2292, + 2280, 1758, 2290, + 2278, 1761, 2289, + 2275, 1764, 2287, + 2272, 1769, 2285, + 2267, 1776, 2281, + 2261, 1785, 2276, + 2252, 1796, 2270, + 2240, 1811, 2261, + 2224, 1830, 2249, + 2201, 1854, 2233, + 2168, 1884, 2210, + 2121, 1922, 2178, + 2048, 1968, 2131, + 1928, 2024, 2059, + 1694, 2088, 1940, + 631, 2163, 1709, + 0, 2246, 718, + 0, 2338, 0, + 0, 2437, 0, + 0, 2544, 0, + 0, 2655, 0, + 0, 2772, 0, + 0, 2891, 0, + 0, 3014, 0, + 0, 3139, 0, + 0, 3266, 0, + 0, 3394, 0, + 0, 3523, 0, + 0, 3653, 0, + 2439, 1794, 2378, + 2438, 1795, 2378, + 2437, 1796, 2377, + 2436, 1798, 2376, + 2435, 1801, 2375, + 2433, 1804, 2373, + 2430, 1809, 2371, + 2427, 1815, 2368, + 2423, 1823, 2364, + 2417, 1833, 2359, + 2408, 1847, 2352, + 2397, 1864, 2342, + 2382, 1887, 2329, + 2360, 1915, 2311, + 2329, 1951, 2285, + 2285, 1994, 2248, + 2217, 2047, 2193, + 2108, 2108, 2108, + 1903, 2180, 1962, + 1252, 2260, 1639, + 0, 2350, 0, + 0, 2447, 0, + 0, 2551, 0, + 0, 2661, 0, + 0, 2776, 0, + 0, 2895, 0, + 0, 3017, 0, + 0, 3141, 0, + 0, 3267, 0, + 0, 3395, 0, + 0, 3524, 0, + 0, 3653, 0, + 2587, 1843, 2472, + 2587, 1844, 2471, + 2586, 1845, 2471, + 2585, 1847, 2470, + 2584, 1850, 2469, + 2583, 1853, 2468, + 2581, 1857, 2466, + 2579, 1862, 2464, + 2576, 1869, 2460, + 2571, 1879, 2456, + 2566, 1891, 2451, + 2558, 1907, 2443, + 2547, 1928, 2432, + 2532, 1954, 2418, + 2511, 1986, 2397, + 2482, 2027, 2369, + 2439, 2076, 2327, + 2375, 2134, 2266, + 2273, 2201, 2167, + 2086, 2279, 1990, + 1566, 2365, 1526, + 0, 2459, 0, + 0, 2561, 0, + 0, 2669, 0, + 0, 2782, 0, + 0, 2899, 0, + 0, 3020, 0, + 0, 3144, 0, + 0, 3269, 0, + 0, 3396, 0, + 0, 3525, 0, + 0, 3654, 0, + 2731, 1902, 2573, + 2731, 1903, 2572, + 2731, 1904, 2572, + 2730, 1906, 2571, + 2729, 1908, 2570, + 2728, 1910, 2569, + 2727, 1914, 2568, + 2725, 1919, 2566, + 2723, 1925, 2564, + 2720, 1933, 2560, + 2716, 1944, 2556, + 2710, 1959, 2550, + 2702, 1977, 2541, + 2692, 2000, 2530, + 2677, 2030, 2514, + 2657, 2067, 2492, + 2629, 2112, 2461, + 2588, 2166, 2416, + 2526, 2229, 2347, + 2428, 2302, 2236, + 2252, 2384, 2024, + 1798, 2475, 1309, + 0, 2574, 0, + 0, 2679, 0, + 0, 2790, 0, + 0, 2906, 0, + 0, 3025, 0, + 0, 3147, 0, + 0, 3272, 0, + 0, 3398, 0, + 0, 3526, 0, + 0, 3655, 0, + 2872, 1970, 2680, + 2872, 1971, 2680, + 2872, 1972, 2679, + 2871, 1973, 2679, + 2871, 1975, 2678, + 2870, 1977, 2677, + 2869, 1981, 2676, + 2868, 1985, 2675, + 2866, 1990, 2673, + 2864, 1998, 2670, + 2861, 2007, 2667, + 2857, 2019, 2662, + 2851, 2036, 2655, + 2843, 2056, 2646, + 2833, 2083, 2634, + 2819, 2115, 2618, + 2799, 2156, 2594, + 2771, 2205, 2561, + 2731, 2264, 2512, + 2672, 2332, 2437, + 2577, 2409, 2314, + 2409, 2495, 2066, + 1993, 2590, 532, + 0, 2692, 0, + 0, 2800, 0, + 0, 2914, 0, + 0, 3031, 0, + 0, 3152, 0, + 0, 3276, 0, + 0, 3401, 0, + 0, 3528, 0, + 0, 3657, 0, + 3011, 2048, 2793, + 3011, 2049, 2792, + 3010, 2050, 2792, + 3010, 2051, 2792, + 3010, 2052, 2791, + 3009, 2054, 2791, + 3008, 2057, 2790, + 3007, 2060, 2789, + 3006, 2065, 2787, + 3005, 2071, 2785, + 3002, 2079, 2782, + 2999, 2090, 2779, + 2995, 2104, 2774, + 2990, 2122, 2767, + 2982, 2144, 2757, + 2972, 2173, 2745, + 2958, 2209, 2727, + 2939, 2253, 2702, + 2911, 2306, 2667, + 2872, 2368, 2616, + 2813, 2440, 2536, + 2721, 2521, 2400, + 2558, 2611, 2118, + 2167, 2709, 0, + 0, 2814, 0, + 0, 2924, 0, + 0, 3039, 0, + 0, 3158, 0, + 0, 3280, 0, + 0, 3405, 0, + 0, 3531, 0, + 0, 3659, 0, + 3148, 2135, 2910, + 3147, 2135, 2909, + 3147, 2136, 2909, + 3147, 2137, 2909, + 3147, 2138, 2909, + 3146, 2140, 2908, + 3146, 2142, 2907, + 3145, 2145, 2907, + 3144, 2149, 2905, + 3143, 2154, 2904, + 3141, 2161, 2902, + 3139, 2170, 2899, + 3136, 2181, 2895, + 3132, 2196, 2890, + 3127, 2216, 2883, + 3119, 2241, 2873, + 3109, 2272, 2860, + 3095, 2310, 2842, + 3076, 2357, 2816, + 3049, 2413, 2779, + 3010, 2479, 2725, + 2953, 2554, 2640, + 2862, 2638, 2495, + 2703, 2731, 2178, + 2328, 2831, 0, + 0, 2938, 0, + 0, 3050, 0, + 0, 3167, 0, + 0, 3287, 0, + 0, 3410, 0, + 0, 3535, 0, + 0, 3662, 0, + 3283, 2230, 3030, + 3283, 2230, 3030, + 3283, 2231, 3030, + 3283, 2232, 3030, + 3283, 2233, 3029, + 3282, 2234, 3029, + 3282, 2236, 3028, + 3281, 2238, 3028, + 3281, 2241, 3027, + 3280, 2245, 3026, + 3279, 2251, 3024, + 3277, 2258, 3022, + 3275, 2268, 3019, + 3272, 2280, 3015, + 3268, 2297, 3010, + 3262, 2317, 3002, + 3255, 2344, 2992, + 3245, 2377, 2979, + 3231, 2418, 2960, + 3212, 2467, 2933, + 3186, 2526, 2896, + 3147, 2594, 2839, + 3090, 2672, 2751, + 3000, 2758, 2598, + 2844, 2853, 2248, + 2481, 2955, 0, + 0, 3064, 0, + 0, 3177, 0, + 0, 3295, 0, + 0, 3416, 0, + 0, 3540, 0, + 0, 3665, 0, + 3418, 2332, 3153, + 3418, 2332, 3153, + 3418, 2333, 3153, + 3418, 2333, 3153, + 3417, 2334, 3153, + 3417, 2335, 3152, + 3417, 2337, 3152, + 3417, 2339, 3151, + 3416, 2341, 3151, + 3415, 2344, 3150, + 3414, 2349, 3149, + 3413, 2355, 3147, + 3412, 2363, 3145, + 3409, 2373, 3142, + 3406, 2386, 3138, + 3403, 2403, 3132, + 3397, 2425, 3125, + 3390, 2453, 3115, + 3380, 2488, 3101, + 3366, 2531, 3082, + 3347, 2582, 3054, + 3321, 2643, 3016, + 3283, 2713, 2958, + 3226, 2793, 2866, + 3137, 2882, 2706, + 2983, 2978, 2328, + 2627, 3082, 0, + 0, 3191, 0, + 0, 3306, 0, + 0, 3424, 0, + 0, 3546, 0, + 0, 3670, 0, + 3552, 2440, 3279, + 3552, 2441, 3278, + 3552, 2441, 3278, + 3552, 2441, 3278, + 3552, 2442, 3278, + 3551, 2443, 3278, + 3551, 2444, 3278, + 3551, 2446, 3277, + 3551, 2448, 3277, + 3550, 2450, 3276, + 3549, 2454, 3275, + 3549, 2458, 3274, + 3547, 2465, 3272, + 3546, 2473, 3270, + 3543, 2484, 3267, + 3541, 2497, 3263, + 3537, 2515, 3257, + 3531, 2538, 3250, + 3524, 2567, 3239, + 3514, 2603, 3225, + 3500, 2648, 3206, + 3482, 2701, 3178, + 3455, 2763, 3138, + 3417, 2835, 3079, + 3361, 2917, 2986, + 3273, 3007, 2820, + 3120, 3105, 2416, + 2770, 3209, 0, + 0, 3320, 0, + 0, 3435, 0, + 0, 3554, 0, + 0, 3676, 0, + 3685, 2554, 3406, + 3685, 2554, 3405, + 3685, 2554, 3405, + 3685, 2555, 3405, + 3685, 2555, 3405, + 3685, 2556, 3405, + 3685, 2557, 3405, + 3685, 2558, 3405, + 3684, 2560, 3404, + 3684, 2562, 3404, + 3684, 2564, 3403, + 3683, 2568, 3402, + 3682, 2573, 3401, + 3681, 2579, 3399, + 3679, 2588, 3397, + 3677, 2599, 3394, + 3674, 2613, 3389, + 3670, 2632, 3384, + 3665, 2656, 3376, + 3658, 2686, 3366, + 3648, 2723, 3351, + 3634, 2768, 3332, + 3615, 2823, 3304, + 3589, 2886, 3263, + 3551, 2960, 3203, + 3495, 3042, 3108, + 3408, 3134, 2938, + 3255, 3233, 2512, + 2910, 3338, 0, + 0, 3449, 0, + 0, 3565, 0, + 0, 3685, 0, + 3819, 2672, 3534, + 3819, 2672, 3534, + 3819, 2672, 3534, + 3819, 2672, 3534, + 3818, 2673, 3533, + 3818, 2673, 3533, + 3818, 2674, 3533, + 3818, 2675, 3533, + 3818, 2676, 3533, + 3818, 2678, 3532, + 3817, 2680, 3532, + 3817, 2683, 3531, + 3816, 2686, 3530, + 3815, 2691, 3529, + 3814, 2698, 3527, + 3812, 2707, 3525, + 3810, 2718, 3522, + 3807, 2733, 3517, + 3803, 2752, 3512, + 3798, 2776, 3504, + 3791, 2807, 3494, + 3781, 2845, 3479, + 3767, 2891, 3459, + 3749, 2947, 3431, + 3722, 3012, 3390, + 3685, 3086, 3329, + 3629, 3170, 3232, + 3542, 3262, 3059, + 3390, 3362, 2616, + 3048, 3468, 0, + 0, 3580, 0, + 0, 3696, 0, + 3952, 2793, 3663, + 3952, 2793, 3663, + 3952, 2793, 3663, + 3951, 2793, 3663, + 3951, 2793, 3663, + 3951, 2794, 3663, + 3951, 2794, 3663, + 3951, 2795, 3662, + 3951, 2796, 3662, + 3951, 2797, 3662, + 3951, 2799, 3661, + 3950, 2801, 3661, + 3950, 2804, 3660, + 3949, 2808, 3659, + 3948, 2813, 3658, + 3947, 2820, 3656, + 3945, 2829, 3654, + 3943, 2840, 3651, + 3940, 2856, 3646, + 3936, 2875, 3641, + 3931, 2900, 3633, + 3924, 2931, 3622, + 3914, 2970, 3608, + 3900, 3017, 3588, + 3882, 3073, 3559, + 3856, 3139, 3518, + 3818, 3214, 3457, + 3762, 3298, 3359, + 3675, 3391, 3182, + 3524, 3491, 2725, + 3184, 3598, 0, + 0, 3710, 0, + 4084, 2916, 3793, + 4084, 2916, 3793, + 4084, 2916, 3793, + 4084, 2917, 3793, + 4084, 2917, 3793, + 4084, 2917, 3793, + 4084, 2918, 3793, + 4084, 2918, 3792, + 4084, 2919, 3792, + 4084, 2920, 3792, + 4083, 2921, 3792, + 4083, 2923, 3791, + 4083, 2925, 3791, + 4082, 2928, 3790, + 4082, 2932, 3789, + 4081, 2937, 3788, + 4080, 2944, 3786, + 4078, 2953, 3784, + 4076, 2965, 3781, + 4073, 2980, 3776, + 4069, 3000, 3771, + 4064, 3025, 3763, + 4056, 3057, 3752, + 4047, 3096, 3738, + 4033, 3144, 3717, + 4015, 3201, 3689, + 3988, 3267, 3647, + 3951, 3343, 3585, + 3895, 3428, 3486, + 3808, 3521, 3308, + 3658, 3622, 2839, + 3320, 3729, 0, + 4095, 3042, 3923, + 4095, 3042, 3923, + 4095, 3042, 3923, + 4095, 3042, 3923, + 4095, 3042, 3923, + 4095, 3043, 3923, + 4095, 3043, 3923, + 4095, 3043, 3923, + 4095, 3044, 3923, + 4095, 3045, 3923, + 4095, 3046, 3922, + 4095, 3047, 3922, + 4095, 3049, 3922, + 4095, 3051, 3921, + 4095, 3054, 3920, + 4095, 3058, 3919, + 4095, 3063, 3918, + 4095, 3070, 3916, + 4095, 3079, 3914, + 4095, 3091, 3911, + 4095, 3107, 3907, + 4095, 3127, 3901, + 4095, 3152, 3893, + 4095, 3184, 3882, + 4095, 3224, 3868, + 4095, 3272, 3847, + 4095, 3329, 3819, + 4095, 3396, 3777, + 4084, 3472, 3715, + 4028, 3558, 3615, + 3941, 3651, 3435, + 3791, 3752, 2958, + 4095, 3169, 4054, + 4095, 3169, 4054, + 4095, 3169, 4054, + 4095, 3169, 4054, + 4095, 3169, 4054, + 4095, 3170, 4054, + 4095, 3170, 4054, + 4095, 3170, 4054, + 4095, 3171, 4054, + 4095, 3171, 4054, + 4095, 3172, 4054, + 4095, 3173, 4053, + 4095, 3174, 4053, + 4095, 3176, 4053, + 4095, 3178, 4052, + 4095, 3181, 4051, + 4095, 3185, 4050, + 4095, 3191, 4049, + 4095, 3198, 4047, + 4095, 3207, 4045, + 4095, 3219, 4042, + 4095, 3235, 4037, + 4095, 3255, 4032, + 4095, 3281, 4024, + 4095, 3313, 4013, + 4095, 3353, 3998, + 4095, 3401, 3978, + 4095, 3459, 3949, + 4095, 3526, 3907, + 4095, 3602, 3845, + 4095, 3688, 3745, + 4074, 3782, 3564, + 0, 1736, 2002, + 0, 1737, 2001, + 0, 1739, 2000, + 0, 1741, 1998, + 0, 1744, 1995, + 0, 1748, 1991, + 0, 1753, 1986, + 0, 1760, 1979, + 0, 1769, 1970, + 0, 1781, 1958, + 0, 1796, 1940, + 0, 1816, 1916, + 0, 1841, 1881, + 0, 1872, 1830, + 0, 1911, 1752, + 0, 1958, 1620, + 0, 2015, 1347, + 0, 2080, 0, + 0, 2156, 0, + 0, 2240, 0, + 0, 2333, 0, + 0, 2434, 0, + 0, 2541, 0, + 0, 2653, 0, + 0, 2770, 0, + 0, 2890, 0, + 0, 3013, 0, + 0, 3138, 0, + 0, 3265, 0, + 0, 3393, 0, + 0, 3522, 0, + 0, 3652, 0, + 0, 1737, 2004, + 0, 1738, 2003, + 0, 1739, 2001, + 0, 1742, 1999, + 0, 1745, 1997, + 0, 1749, 1993, + 0, 1754, 1988, + 0, 1761, 1981, + 0, 1769, 1972, + 0, 1781, 1960, + 0, 1796, 1942, + 0, 1816, 1918, + 0, 1841, 1883, + 0, 1872, 1833, + 0, 1911, 1755, + 0, 1958, 1624, + 0, 2015, 1354, + 0, 2081, 0, + 0, 2156, 0, + 0, 2241, 0, + 0, 2333, 0, + 0, 2434, 0, + 0, 2541, 0, + 0, 2653, 0, + 0, 2770, 0, + 0, 2890, 0, + 0, 3013, 0, + 0, 3138, 0, + 0, 3265, 0, + 0, 3393, 0, + 0, 3522, 0, + 0, 3652, 0, + 0, 1737, 2006, + 0, 1738, 2005, + 0, 1740, 2004, + 0, 1742, 2002, + 0, 1745, 1999, + 0, 1749, 1995, + 0, 1754, 1990, + 0, 1761, 1984, + 0, 1770, 1974, + 0, 1782, 1962, + 0, 1797, 1945, + 0, 1817, 1921, + 0, 1841, 1886, + 0, 1873, 1836, + 0, 1912, 1759, + 0, 1959, 1629, + 0, 2015, 1363, + 0, 2081, 0, + 0, 2156, 0, + 0, 2241, 0, + 0, 2334, 0, + 0, 2434, 0, + 0, 2541, 0, + 0, 2653, 0, + 0, 2770, 0, + 0, 2890, 0, + 0, 3013, 0, + 0, 3138, 0, + 0, 3265, 0, + 0, 3393, 0, + 0, 3522, 0, + 0, 3652, 0, + 0, 1738, 2009, + 0, 1739, 2008, + 0, 1741, 2007, + 0, 1743, 2005, + 0, 1746, 2002, + 0, 1750, 1998, + 0, 1755, 1993, + 0, 1762, 1987, + 0, 1771, 1978, + 0, 1782, 1965, + 0, 1798, 1948, + 0, 1817, 1924, + 0, 1842, 1890, + 0, 1873, 1840, + 0, 1912, 1764, + 0, 1959, 1636, + 0, 2015, 1375, + 0, 2081, 0, + 0, 2157, 0, + 0, 2241, 0, + 0, 2334, 0, + 0, 2434, 0, + 0, 2541, 0, + 0, 2653, 0, + 0, 2770, 0, + 0, 2890, 0, + 0, 3013, 0, + 0, 3138, 0, + 0, 3265, 0, + 0, 3393, 0, + 0, 3522, 0, + 0, 3652, 0, + 0, 1739, 2013, + 0, 1740, 2012, + 0, 1742, 2011, + 0, 1744, 2009, + 0, 1747, 2006, + 0, 1751, 2002, + 0, 1756, 1997, + 0, 1763, 1991, + 0, 1772, 1982, + 0, 1783, 1970, + 0, 1798, 1953, + 0, 1818, 1929, + 0, 1843, 1895, + 0, 1874, 1846, + 0, 1913, 1771, + 0, 1960, 1645, + 0, 2016, 1391, + 0, 2082, 0, + 0, 2157, 0, + 0, 2241, 0, + 0, 2334, 0, + 0, 2434, 0, + 0, 2541, 0, + 0, 2653, 0, + 0, 2770, 0, + 0, 2890, 0, + 0, 3013, 0, + 0, 3138, 0, + 0, 3265, 0, + 0, 3393, 0, + 0, 3522, 0, + 0, 3652, 0, + 0, 1740, 2018, + 0, 1741, 2017, + 0, 1743, 2016, + 0, 1745, 2014, + 0, 1748, 2011, + 0, 1752, 2008, + 0, 1757, 2003, + 0, 1764, 1996, + 0, 1773, 1988, + 0, 1785, 1975, + 0, 1800, 1959, + 0, 1819, 1935, + 0, 1844, 1902, + 0, 1875, 1854, + 0, 1914, 1779, + 0, 1961, 1656, + 0, 2017, 1412, + 0, 2082, 13, + 0, 2157, 0, + 0, 2242, 0, + 0, 2334, 0, + 0, 2435, 0, + 0, 2541, 0, + 0, 2654, 0, + 0, 2770, 0, + 0, 2890, 0, + 0, 3013, 0, + 0, 3138, 0, + 0, 3265, 0, + 0, 3393, 0, + 0, 3522, 0, + 0, 3652, 0, + 0, 1742, 2025, + 0, 1743, 2024, + 0, 1745, 2023, + 0, 1747, 2021, + 0, 1750, 2018, + 0, 1754, 2015, + 0, 1759, 2010, + 0, 1766, 2004, + 0, 1775, 1995, + 0, 1786, 1983, + 0, 1801, 1967, + 0, 1821, 1944, + 0, 1845, 1911, + 0, 1876, 1864, + 0, 1915, 1791, + 0, 1962, 1672, + 0, 2018, 1438, + 0, 2083, 386, + 0, 2158, 0, + 0, 2242, 0, + 0, 2335, 0, + 0, 2435, 0, + 0, 2542, 0, + 0, 2654, 0, + 0, 2770, 0, + 0, 2890, 0, + 0, 3013, 0, + 0, 3139, 0, + 0, 3265, 0, + 0, 3393, 0, + 0, 3523, 0, + 0, 3652, 0, + 0, 1744, 2035, + 0, 1746, 2033, + 0, 1747, 2032, + 0, 1749, 2030, + 0, 1752, 2028, + 0, 1756, 2024, + 0, 1761, 2020, + 0, 1768, 2013, + 0, 1777, 2005, + 0, 1788, 1993, + 0, 1803, 1977, + 0, 1823, 1955, + 0, 1847, 1923, + 0, 1878, 1877, + 0, 1917, 1806, + 0, 1963, 1691, + 0, 2019, 1470, + 0, 2084, 640, + 0, 2159, 0, + 0, 2243, 0, + 0, 2336, 0, + 0, 2436, 0, + 0, 2542, 0, + 0, 2654, 0, + 0, 2771, 0, + 0, 2891, 0, + 0, 3014, 0, + 0, 3139, 0, + 0, 3265, 0, + 0, 3393, 0, + 0, 3523, 0, + 0, 3652, 0, + 0, 1748, 2046, + 0, 1749, 2045, + 0, 1750, 2044, + 0, 1753, 2042, + 0, 1755, 2040, + 0, 1759, 2036, + 0, 1764, 2032, + 0, 1771, 2026, + 0, 1780, 2018, + 0, 1791, 2006, + 0, 1806, 1991, + 0, 1825, 1969, + 0, 1850, 1938, + 0, 1881, 1893, + 0, 1919, 1826, + 0, 1965, 1716, + 0, 2021, 1510, + 0, 2086, 846, + 0, 2160, 0, + 0, 2244, 0, + 0, 2336, 0, + 0, 2436, 0, + 0, 2543, 0, + 0, 2655, 0, + 0, 2771, 0, + 0, 2891, 0, + 0, 3014, 0, + 0, 3139, 0, + 0, 3266, 0, + 0, 3394, 0, + 0, 3523, 0, + 0, 3652, 0, + 0, 1752, 2062, + 0, 1753, 2061, + 0, 1755, 2060, + 0, 1757, 2058, + 0, 1760, 2055, + 0, 1763, 2052, + 0, 1768, 2048, + 0, 1775, 2042, + 0, 1784, 2034, + 0, 1795, 2023, + 0, 1810, 2008, + 0, 1829, 1987, + 0, 1853, 1958, + 0, 1884, 1915, + 0, 1922, 1851, + 0, 1968, 1748, + 0, 2023, 1559, + 0, 2088, 1026, + 0, 2162, 0, + 0, 2246, 0, + 0, 2338, 0, + 0, 2437, 0, + 0, 2543, 0, + 0, 2655, 0, + 0, 2771, 0, + 0, 2891, 0, + 0, 3014, 0, + 0, 3139, 0, + 0, 3266, 0, + 0, 3394, 0, + 0, 3523, 0, + 0, 3652, 0, + 0, 1757, 2082, + 0, 1759, 2081, + 0, 1760, 2080, + 0, 1762, 2078, + 0, 1765, 2076, + 0, 1769, 2073, + 0, 1774, 2068, + 0, 1780, 2063, + 0, 1789, 2055, + 0, 1800, 2045, + 0, 1815, 2030, + 0, 1834, 2011, + 0, 1858, 1983, + 0, 1888, 1942, + 0, 1925, 1882, + 0, 1971, 1787, + 0, 2026, 1616, + 0, 2090, 1191, + 0, 2164, 0, + 0, 2247, 0, + 0, 2339, 0, + 0, 2438, 0, + 0, 2544, 0, + 0, 2656, 0, + 0, 2772, 0, + 0, 2892, 0, + 0, 3014, 0, + 0, 3139, 0, + 0, 3266, 0, + 0, 3394, 0, + 0, 3523, 0, + 0, 3653, 0, + 30, 1765, 2107, + 0, 1766, 2106, + 0, 1767, 2105, + 0, 1770, 2103, + 0, 1772, 2101, + 0, 1776, 2098, + 0, 1781, 2094, + 0, 1787, 2089, + 0, 1796, 2082, + 0, 1807, 2072, + 0, 1821, 2059, + 0, 1840, 2040, + 0, 1864, 2014, + 0, 1893, 1976, + 0, 1931, 1921, + 0, 1976, 1834, + 0, 2030, 1684, + 0, 2094, 1346, + 0, 2167, 0, + 0, 2250, 0, + 0, 2341, 0, + 0, 2440, 0, + 0, 2546, 0, + 0, 2657, 0, + 0, 2773, 0, + 0, 2892, 0, + 0, 3015, 0, + 0, 3140, 0, + 0, 3266, 0, + 0, 3394, 0, + 0, 3523, 0, + 0, 3653, 0, + 1247, 1774, 2139, + 1239, 1775, 2138, + 1228, 1777, 2137, + 1213, 1779, 2136, + 1193, 1782, 2133, + 1163, 1785, 2131, + 1121, 1790, 2127, + 1058, 1796, 2122, + 956, 1805, 2116, + 771, 1816, 2106, + 265, 1830, 2094, + 0, 1848, 2077, + 0, 1871, 2053, + 0, 1901, 2018, + 0, 1937, 1968, + 0, 1982, 1890, + 0, 2036, 1760, + 0, 2099, 1495, + 0, 2171, 0, + 0, 2253, 0, + 0, 2344, 0, + 0, 2442, 0, + 0, 2547, 0, + 0, 2658, 0, + 0, 2774, 0, + 0, 2893, 0, + 0, 3015, 0, + 0, 3140, 0, + 0, 3267, 0, + 0, 3394, 0, + 0, 3523, 0, + 0, 3653, 0, + 1614, 1787, 2178, + 1611, 1788, 2178, + 1606, 1790, 2177, + 1600, 1792, 2175, + 1591, 1794, 2173, + 1579, 1798, 2171, + 1563, 1802, 2167, + 1540, 1808, 2163, + 1507, 1817, 2157, + 1459, 1827, 2149, + 1387, 1841, 2137, + 1267, 1859, 2122, + 1031, 1881, 2100, + 0, 1910, 2069, + 0, 1946, 2024, + 0, 1990, 1956, + 0, 2043, 1846, + 0, 2105, 1639, + 0, 2177, 963, + 0, 2258, 0, + 0, 2348, 0, + 0, 2445, 0, + 0, 2550, 0, + 0, 2660, 0, + 0, 2775, 0, + 0, 2894, 0, + 0, 3016, 0, + 0, 3141, 0, + 0, 3267, 0, + 0, 3395, 0, + 0, 3523, 0, + 0, 3653, 0, + 1867, 1803, 2226, + 1865, 1804, 2225, + 1862, 1806, 2224, + 1858, 1808, 2223, + 1853, 1810, 2222, + 1847, 1814, 2219, + 1838, 1818, 2216, + 1825, 1824, 2212, + 1808, 1832, 2207, + 1784, 1842, 2199, + 1750, 1855, 2189, + 1700, 1873, 2175, + 1623, 1895, 2156, + 1494, 1923, 2129, + 1232, 1958, 2090, + 0, 2000, 2032, + 0, 2052, 1940, + 0, 2113, 1780, + 0, 2184, 1399, + 0, 2264, 0, + 0, 2352, 0, + 0, 2449, 0, + 0, 2553, 0, + 0, 2663, 0, + 0, 2777, 0, + 0, 2896, 0, + 0, 3017, 0, + 0, 3142, 0, + 0, 3268, 0, + 0, 3395, 0, + 0, 3524, 0, + 0, 3653, 0, + 2071, 1824, 2283, + 2070, 1825, 2282, + 2068, 1827, 2282, + 2066, 1828, 2281, + 2063, 1831, 2279, + 2059, 1834, 2277, + 2053, 1838, 2274, + 2046, 1844, 2271, + 2035, 1851, 2266, + 2021, 1861, 2260, + 2001, 1874, 2251, + 1973, 1891, 2239, + 1932, 1912, 2222, + 1871, 1939, 2198, + 1775, 1973, 2165, + 1602, 2014, 2117, + 1165, 2064, 2042, + 0, 2124, 1918, + 0, 2193, 1672, + 0, 2271, 186, + 0, 2359, 0, + 0, 2454, 0, + 0, 2557, 0, + 0, 2666, 0, + 0, 2780, 0, + 0, 2898, 0, + 0, 3019, 0, + 0, 3143, 0, + 0, 3268, 0, + 0, 3396, 0, + 0, 3524, 0, + 0, 3654, 0, + 2251, 1851, 2350, + 2250, 1852, 2349, + 2249, 1853, 2348, + 2248, 1855, 2347, + 2246, 1857, 2346, + 2243, 1860, 2344, + 2239, 1864, 2342, + 2234, 1869, 2339, + 2227, 1877, 2335, + 2218, 1886, 2329, + 2205, 1898, 2322, + 2187, 1914, 2311, + 2162, 1934, 2297, + 2127, 1960, 2277, + 2074, 1992, 2250, + 1993, 2032, 2210, + 1855, 2080, 2150, + 1563, 2138, 2055, + 0, 2205, 1887, + 0, 2281, 1471, + 0, 2367, 0, + 0, 2461, 0, + 0, 2562, 0, + 0, 2670, 0, + 0, 2783, 0, + 0, 2900, 0, + 0, 3021, 0, + 0, 3144, 0, + 0, 3270, 0, + 0, 3397, 0, + 0, 3525, 0, + 0, 3654, 0, + 2416, 1884, 2425, + 2415, 1885, 2425, + 2415, 1886, 2424, + 2413, 1888, 2424, + 2412, 1890, 2423, + 2410, 1893, 2421, + 2408, 1896, 2419, + 2404, 1901, 2417, + 2399, 1908, 2413, + 2393, 1917, 2408, + 2384, 1928, 2402, + 2372, 1943, 2393, + 2356, 1962, 2382, + 2333, 1986, 2365, + 2300, 2017, 2342, + 2253, 2054, 2310, + 2180, 2101, 2263, + 2060, 2156, 2191, + 1826, 2220, 2072, + 763, 2295, 1841, + 0, 2378, 850, + 0, 2470, 0, + 0, 2570, 0, + 0, 2676, 0, + 0, 2787, 0, + 0, 2904, 0, + 0, 3023, 0, + 0, 3146, 0, + 0, 3271, 0, + 0, 3398, 0, + 0, 3526, 0, + 0, 3655, 0, + 2571, 1925, 2511, + 2571, 1926, 2510, + 2570, 1927, 2510, + 2569, 1928, 2509, + 2568, 1930, 2508, + 2567, 1933, 2507, + 2565, 1936, 2505, + 2563, 1941, 2503, + 2559, 1947, 2500, + 2555, 1955, 2496, + 2549, 1965, 2491, + 2540, 1979, 2484, + 2529, 1997, 2474, + 2514, 2019, 2461, + 2492, 2048, 2443, + 2461, 2083, 2417, + 2417, 2126, 2380, + 2350, 2179, 2326, + 2240, 2240, 2240, + 2036, 2312, 2094, + 1384, 2392, 1771, + 0, 2482, 0, + 0, 2579, 0, + 0, 2683, 0, + 0, 2793, 0, + 0, 2908, 0, + 0, 3027, 0, + 0, 3149, 0, + 0, 3273, 0, + 0, 3399, 0, + 0, 3527, 0, + 0, 3656, 0, + 2720, 1975, 2604, + 2719, 1975, 2604, + 2719, 1976, 2603, + 2718, 1978, 2603, + 2718, 1979, 2602, + 2717, 1982, 2601, + 2715, 1985, 2600, + 2713, 1989, 2598, + 2711, 1994, 2596, + 2708, 2002, 2593, + 2704, 2011, 2588, + 2698, 2023, 2583, + 2690, 2039, 2575, + 2679, 2060, 2564, + 2664, 2086, 2550, + 2643, 2119, 2529, + 2614, 2159, 2501, + 2571, 2208, 2460, + 2508, 2266, 2398, + 2405, 2333, 2299, + 2218, 2411, 2122, + 1698, 2497, 1658, + 0, 2591, 0, + 0, 2693, 0, + 0, 2801, 0, + 0, 2914, 0, + 0, 3032, 0, + 0, 3152, 0, + 0, 3276, 0, + 0, 3401, 0, + 0, 3529, 0, + 0, 3657, 0, + 2864, 2033, 2705, + 2863, 2034, 2705, + 2863, 2035, 2704, + 2863, 2036, 2704, + 2862, 2038, 2703, + 2861, 2040, 2703, + 2860, 2042, 2702, + 2859, 2046, 2700, + 2857, 2051, 2698, + 2855, 2057, 2696, + 2852, 2066, 2692, + 2848, 2076, 2688, + 2842, 2091, 2682, + 2834, 2109, 2673, + 2824, 2133, 2662, + 2809, 2162, 2646, + 2789, 2199, 2624, + 2761, 2244, 2593, + 2720, 2298, 2548, + 2658, 2361, 2479, + 2560, 2434, 2368, + 2385, 2516, 2156, + 1930, 2607, 1441, + 0, 2706, 0, + 0, 2811, 0, + 0, 2922, 0, + 0, 3038, 0, + 0, 3157, 0, + 0, 3279, 0, + 0, 3404, 0, + 0, 3531, 0, + 0, 3658, 0, + 3004, 2102, 2812, + 3004, 2102, 2812, + 3004, 2103, 2812, + 3004, 2104, 2811, + 3003, 2105, 2811, + 3003, 2107, 2810, + 3002, 2110, 2810, + 3001, 2113, 2808, + 3000, 2117, 2807, + 2998, 2122, 2805, + 2996, 2130, 2802, + 2993, 2139, 2799, + 2989, 2152, 2794, + 2983, 2168, 2787, + 2976, 2188, 2779, + 2965, 2215, 2766, + 2951, 2248, 2750, + 2931, 2288, 2726, + 2903, 2337, 2693, + 2863, 2396, 2644, + 2804, 2464, 2570, + 2709, 2541, 2446, + 2541, 2628, 2199, + 2125, 2722, 664, + 0, 2824, 0, + 0, 2932, 0, + 0, 3046, 0, + 0, 3163, 0, + 0, 3284, 0, + 0, 3408, 0, + 0, 3533, 0, + 0, 3660, 0, + 3143, 2180, 2925, + 3143, 2180, 2925, + 3143, 2181, 2924, + 3142, 2182, 2924, + 3142, 2183, 2924, + 3142, 2184, 2923, + 3141, 2186, 2923, + 3141, 2189, 2922, + 3140, 2192, 2921, + 3138, 2197, 2919, + 3137, 2203, 2917, + 3134, 2211, 2914, + 3131, 2222, 2911, + 3127, 2236, 2906, + 3122, 2254, 2899, + 3114, 2276, 2890, + 3104, 2305, 2877, + 3090, 2341, 2859, + 3071, 2385, 2835, + 3043, 2438, 2799, + 3004, 2500, 2748, + 2945, 2572, 2668, + 2853, 2653, 2532, + 2690, 2743, 2250, + 2299, 2841, 0, + 0, 2946, 0, + 0, 3056, 0, + 0, 3171, 0, + 0, 3290, 0, + 0, 3412, 0, + 0, 3537, 0, + 0, 3663, 0, + 3280, 2267, 3042, + 3280, 2267, 3042, + 3280, 2267, 3041, + 3279, 2268, 3041, + 3279, 2269, 3041, + 3279, 2270, 3041, + 3278, 2272, 3040, + 3278, 2274, 3039, + 3277, 2277, 3039, + 3276, 2281, 3037, + 3275, 2286, 3036, + 3273, 2293, 3034, + 3271, 2302, 3031, + 3268, 2313, 3027, + 3264, 2328, 3022, + 3259, 2348, 3015, + 3251, 2373, 3005, + 3241, 2404, 2992, + 3227, 2442, 2974, + 3208, 2489, 2948, + 3181, 2545, 2911, + 3142, 2611, 2857, + 3085, 2686, 2773, + 2994, 2770, 2628, + 2835, 2863, 2310, + 2460, 2963, 0, + 0, 3070, 0, + 0, 3182, 0, + 0, 3299, 0, + 0, 3419, 0, + 0, 3542, 0, + 0, 3667, 0, + 3415, 2362, 3162, + 3415, 2362, 3162, + 3415, 2362, 3162, + 3415, 2363, 3162, + 3415, 2364, 3162, + 3415, 2365, 3161, + 3414, 2366, 3161, + 3414, 2368, 3160, + 3414, 2370, 3160, + 3413, 2373, 3159, + 3412, 2377, 3158, + 3411, 2383, 3156, + 3409, 2390, 3154, + 3407, 2400, 3151, + 3404, 2412, 3147, + 3400, 2429, 3142, + 3394, 2449, 3134, + 3387, 2476, 3124, + 3377, 2509, 3111, + 3363, 2550, 3092, + 3344, 2599, 3066, + 3318, 2658, 3028, + 3279, 2726, 2971, + 3222, 2804, 2883, + 3132, 2891, 2730, + 2976, 2985, 2380, + 2613, 3088, 0, + 0, 3196, 0, + 0, 3309, 0, + 0, 3427, 0, + 0, 3548, 0, + 0, 3672, 0, + 3550, 2464, 3285, + 3550, 2464, 3285, + 3550, 2464, 3285, + 3550, 2465, 3285, + 3550, 2465, 3285, + 3550, 2466, 3285, + 3549, 2467, 3284, + 3549, 2469, 3284, + 3549, 2471, 3284, + 3548, 2473, 3283, + 3548, 2477, 3282, + 3547, 2481, 3281, + 3545, 2487, 3279, + 3544, 2495, 3277, + 3542, 2505, 3274, + 3539, 2518, 3270, + 3535, 2535, 3264, + 3529, 2557, 3257, + 3522, 2585, 3247, + 3512, 2620, 3233, + 3498, 2663, 3214, + 3479, 2714, 3187, + 3453, 2775, 3148, + 3415, 2845, 3090, + 3358, 2925, 2999, + 3269, 3014, 2838, + 3115, 3110, 2460, + 2760, 3214, 0, + 0, 3323, 0, + 0, 3438, 0, + 0, 3556, 0, + 0, 3678, 0, + 3684, 2572, 3411, + 3684, 2572, 3411, + 3684, 2573, 3411, + 3684, 2573, 3410, + 3684, 2574, 3410, + 3684, 2574, 3410, + 3684, 2575, 3410, + 3683, 2576, 3410, + 3683, 2578, 3409, + 3683, 2580, 3409, + 3682, 2582, 3408, + 3682, 2586, 3407, + 3681, 2591, 3406, + 3679, 2597, 3404, + 3678, 2605, 3402, + 3676, 2616, 3399, + 3673, 2630, 3395, + 3669, 2647, 3389, + 3663, 2670, 3382, + 3656, 2699, 3371, + 3646, 2736, 3357, + 3633, 2780, 3338, + 3614, 2833, 3310, + 3587, 2895, 3270, + 3549, 2967, 3211, + 3493, 3049, 3118, + 3405, 3139, 2952, + 3252, 3237, 2548, + 2902, 3342, 0, + 0, 3452, 0, + 0, 3567, 0, + 0, 3686, 0, + 3818, 2686, 3538, + 3818, 2686, 3538, + 3818, 2686, 3538, + 3818, 2686, 3537, + 3817, 2687, 3537, + 3817, 2687, 3537, + 3817, 2688, 3537, + 3817, 2689, 3537, + 3817, 2690, 3537, + 3817, 2692, 3536, + 3816, 2694, 3536, + 3816, 2696, 3535, + 3815, 2700, 3534, + 3814, 2705, 3533, + 3813, 2711, 3531, + 3811, 2720, 3529, + 3809, 2731, 3526, + 3806, 2745, 3522, + 3802, 2764, 3516, + 3797, 2788, 3508, + 3790, 2818, 3498, + 3780, 2855, 3484, + 3766, 2900, 3464, + 3748, 2955, 3436, + 3721, 3018, 3395, + 3683, 3092, 3335, + 3627, 3174, 3240, + 3540, 3266, 3070, + 3387, 3365, 2644, + 3042, 3470, 0, + 0, 3582, 0, + 0, 3697, 0, + 3951, 2804, 3666, + 3951, 2804, 3666, + 3951, 2804, 3666, + 3951, 2804, 3666, + 3951, 2804, 3666, + 3951, 2805, 3666, + 3951, 2805, 3665, + 3950, 2806, 3665, + 3950, 2807, 3665, + 3950, 2808, 3665, + 3950, 2810, 3664, + 3949, 2812, 3664, + 3949, 2815, 3663, + 3948, 2818, 3662, + 3947, 2823, 3661, + 3946, 2830, 3659, + 3944, 2839, 3657, + 3942, 2850, 3654, + 3939, 2865, 3650, + 3935, 2884, 3644, + 3930, 2909, 3636, + 3923, 2939, 3626, + 3913, 2977, 3611, + 3900, 3024, 3591, + 3881, 3079, 3563, + 3855, 3144, 3522, + 3817, 3218, 3461, + 3761, 3302, 3364, + 3674, 3394, 3191, + 3522, 3494, 2748, + 3180, 3600, 0, + 0, 3712, 0, + 4084, 2925, 3795, + 4084, 2925, 3795, + 4084, 2925, 3795, + 4084, 2925, 3795, + 4084, 2925, 3795, + 4084, 2926, 3795, + 4083, 2926, 3795, + 4083, 2926, 3795, + 4083, 2927, 3794, + 4083, 2928, 3794, + 4083, 2929, 3794, + 4083, 2931, 3794, + 4082, 2933, 3793, + 4082, 2936, 3792, + 4081, 2940, 3791, + 4080, 2945, 3790, + 4079, 2952, 3788, + 4077, 2961, 3786, + 4075, 2972, 3783, + 4072, 2988, 3779, + 4068, 3007, 3773, + 4063, 3032, 3765, + 4056, 3063, 3755, + 4046, 3102, 3740, + 4033, 3149, 3720, + 4014, 3205, 3691, + 3988, 3271, 3650, + 3950, 3346, 3589, + 3894, 3430, 3491, + 3807, 3523, 3314, + 3656, 3623, 2857, + 3317, 3730, 0, + 4095, 3048, 3925, + 4095, 3048, 3925, + 4095, 3048, 3925, + 4095, 3049, 3925, + 4095, 3049, 3925, + 4095, 3049, 3925, + 4095, 3049, 3925, + 4095, 3050, 3925, + 4095, 3050, 3924, + 4095, 3051, 3924, + 4095, 3052, 3924, + 4095, 3053, 3924, + 4095, 3055, 3923, + 4095, 3057, 3923, + 4095, 3060, 3922, + 4095, 3064, 3921, + 4095, 3069, 3920, + 4095, 3076, 3918, + 4095, 3085, 3916, + 4095, 3097, 3913, + 4095, 3112, 3908, + 4095, 3132, 3903, + 4095, 3157, 3895, + 4095, 3189, 3884, + 4095, 3228, 3870, + 4095, 3276, 3849, + 4095, 3333, 3821, + 4095, 3399, 3779, + 4083, 3475, 3717, + 4027, 3560, 3619, + 3940, 3653, 3440, + 3790, 3754, 2972, + 4095, 3174, 4055, + 4095, 3174, 4055, + 4095, 3174, 4055, + 4095, 3174, 4055, + 4095, 3174, 4055, + 4095, 3174, 4055, + 4095, 3175, 4055, + 4095, 3175, 4055, + 4095, 3175, 4055, + 4095, 3176, 4055, + 4095, 3177, 4055, + 4095, 3178, 4055, + 4095, 3179, 4054, + 4095, 3181, 4054, + 4095, 3183, 4053, + 4095, 3186, 4053, + 4095, 3190, 4052, + 4095, 3195, 4050, + 4095, 3202, 4049, + 4095, 3211, 4046, + 4095, 3223, 4043, + 4095, 3239, 4039, + 4095, 3259, 4033, + 4095, 3285, 4025, + 4095, 3317, 4015, + 4095, 3356, 4000, + 4095, 3404, 3979, + 4095, 3461, 3951, + 4095, 3528, 3909, + 4095, 3604, 3847, + 4095, 3690, 3747, + 4073, 3783, 3567, + 0, 1867, 2134, + 0, 1868, 2133, + 0, 1869, 2132, + 0, 1871, 2130, + 0, 1873, 2128, + 0, 1876, 2126, + 0, 1880, 2122, + 0, 1885, 2117, + 0, 1892, 2110, + 0, 1901, 2101, + 0, 1913, 2088, + 0, 1928, 2071, + 0, 1948, 2047, + 0, 1973, 2012, + 0, 2004, 1961, + 0, 2043, 1882, + 0, 2090, 1749, + 0, 2146, 1473, + 0, 2212, 0, + 0, 2288, 0, + 0, 2372, 0, + 0, 2465, 0, + 0, 2566, 0, + 0, 2673, 0, + 0, 2785, 0, + 0, 2902, 0, + 0, 3022, 0, + 0, 3145, 0, + 0, 3270, 0, + 0, 3397, 0, + 0, 3525, 0, + 0, 3654, 0, + 0, 1867, 2135, + 0, 1868, 2134, + 0, 1869, 2133, + 0, 1871, 2132, + 0, 1873, 2130, + 0, 1876, 2127, + 0, 1880, 2123, + 0, 1885, 2118, + 0, 1892, 2112, + 0, 1901, 2102, + 0, 1913, 2090, + 0, 1928, 2072, + 0, 1948, 2048, + 0, 1973, 2013, + 0, 2004, 1962, + 0, 2043, 1884, + 0, 2090, 1752, + 0, 2147, 1479, + 0, 2213, 0, + 0, 2288, 0, + 0, 2372, 0, + 0, 2465, 0, + 0, 2566, 0, + 0, 2673, 0, + 0, 2785, 0, + 0, 2902, 0, + 0, 3022, 0, + 0, 3145, 0, + 0, 3270, 0, + 0, 3397, 0, + 0, 3525, 0, + 0, 3654, 0, + 0, 1868, 2137, + 0, 1869, 2136, + 0, 1870, 2135, + 0, 1872, 2133, + 0, 1874, 2131, + 0, 1877, 2129, + 0, 1881, 2125, + 0, 1886, 2120, + 0, 1893, 2113, + 0, 1902, 2104, + 0, 1913, 2092, + 0, 1929, 2074, + 0, 1948, 2050, + 0, 1973, 2016, + 0, 2004, 1965, + 0, 2043, 1887, + 0, 2091, 1756, + 0, 2147, 1486, + 0, 2213, 0, + 0, 2288, 0, + 0, 2373, 0, + 0, 2466, 0, + 0, 2566, 0, + 0, 2673, 0, + 0, 2785, 0, + 0, 2902, 0, + 0, 3022, 0, + 0, 3145, 0, + 0, 3270, 0, + 0, 3397, 0, + 0, 3525, 0, + 0, 3655, 0, + 0, 1868, 2139, + 0, 1869, 2138, + 0, 1870, 2137, + 0, 1872, 2136, + 0, 1874, 2134, + 0, 1877, 2131, + 0, 1881, 2127, + 0, 1886, 2122, + 0, 1893, 2116, + 0, 1902, 2107, + 0, 1914, 2094, + 0, 1929, 2077, + 0, 1949, 2053, + 0, 1974, 2019, + 0, 2005, 1968, + 0, 2044, 1891, + 0, 2091, 1761, + 0, 2147, 1495, + 0, 2213, 0, + 0, 2288, 0, + 0, 2373, 0, + 0, 2466, 0, + 0, 2566, 0, + 0, 2673, 0, + 0, 2785, 0, + 0, 2902, 0, + 0, 3022, 0, + 0, 3145, 0, + 0, 3270, 0, + 0, 3397, 0, + 0, 3525, 0, + 0, 3655, 0, + 0, 1869, 2142, + 0, 1870, 2141, + 0, 1871, 2140, + 0, 1873, 2139, + 0, 1875, 2137, + 0, 1878, 2134, + 0, 1882, 2130, + 0, 1887, 2125, + 0, 1894, 2119, + 0, 1903, 2110, + 0, 1915, 2097, + 0, 1930, 2080, + 0, 1949, 2056, + 0, 1974, 2022, + 0, 2005, 1973, + 0, 2044, 1896, + 0, 2091, 1768, + 0, 2148, 1508, + 0, 2213, 0, + 0, 2289, 0, + 0, 2373, 0, + 0, 2466, 0, + 0, 2566, 0, + 0, 2673, 0, + 0, 2785, 0, + 0, 2902, 0, + 0, 3022, 0, + 0, 3145, 0, + 0, 3270, 0, + 0, 3397, 0, + 0, 3525, 0, + 0, 3655, 0, + 0, 1870, 2146, + 0, 1871, 2145, + 0, 1872, 2144, + 0, 1874, 2143, + 0, 1876, 2141, + 0, 1879, 2138, + 0, 1883, 2134, + 0, 1888, 2130, + 0, 1895, 2123, + 0, 1904, 2114, + 0, 1915, 2102, + 0, 1931, 2085, + 0, 1950, 2061, + 0, 1975, 2028, + 0, 2006, 1978, + 0, 2045, 1903, + 0, 2092, 1777, + 0, 2148, 1523, + 0, 2214, 0, + 0, 2289, 0, + 0, 2373, 0, + 0, 2466, 0, + 0, 2567, 0, + 0, 2673, 0, + 0, 2786, 0, + 0, 2902, 0, + 0, 3022, 0, + 0, 3145, 0, + 0, 3270, 0, + 0, 3397, 0, + 0, 3525, 0, + 0, 3655, 0, + 0, 1871, 2151, + 0, 1872, 2151, + 0, 1874, 2149, + 0, 1875, 2148, + 0, 1877, 2146, + 0, 1880, 2143, + 0, 1884, 2140, + 0, 1889, 2135, + 0, 1896, 2129, + 0, 1905, 2120, + 0, 1917, 2108, + 0, 1932, 2091, + 0, 1951, 2068, + 0, 1976, 2034, + 0, 2007, 1986, + 0, 2046, 1912, + 0, 2093, 1788, + 0, 2149, 1544, + 0, 2214, 145, + 0, 2290, 0, + 0, 2374, 0, + 0, 2467, 0, + 0, 2567, 0, + 0, 2674, 0, + 0, 2786, 0, + 0, 2902, 0, + 0, 3022, 0, + 0, 3145, 0, + 0, 3271, 0, + 0, 3397, 0, + 0, 3525, 0, + 0, 3655, 0, + 0, 1873, 2158, + 0, 1874, 2157, + 0, 1875, 2156, + 0, 1877, 2155, + 0, 1879, 2153, + 0, 1882, 2150, + 0, 1886, 2147, + 0, 1891, 2142, + 0, 1898, 2136, + 0, 1907, 2127, + 0, 1918, 2115, + 0, 1933, 2099, + 0, 1953, 2076, + 0, 1977, 2043, + 0, 2009, 1996, + 0, 2047, 1923, + 0, 2094, 1804, + 0, 2150, 1570, + 0, 2215, 518, + 0, 2290, 0, + 0, 2374, 0, + 0, 2467, 0, + 0, 2567, 0, + 0, 2674, 0, + 0, 2786, 0, + 0, 2902, 0, + 0, 3023, 0, + 0, 3146, 0, + 0, 3271, 0, + 0, 3397, 0, + 0, 3526, 0, + 0, 3655, 0, + 0, 1876, 2167, + 0, 1876, 2167, + 0, 1878, 2166, + 0, 1879, 2164, + 0, 1882, 2162, + 0, 1884, 2160, + 0, 1888, 2156, + 0, 1893, 2152, + 0, 1900, 2145, + 0, 1909, 2137, + 0, 1920, 2125, + 0, 1935, 2109, + 0, 1955, 2087, + 0, 1979, 2055, + 0, 2010, 2009, + 0, 2049, 1938, + 0, 2095, 1823, + 0, 2151, 1602, + 0, 2216, 772, + 0, 2291, 0, + 0, 2375, 0, + 0, 2468, 0, + 0, 2568, 0, + 0, 2674, 0, + 0, 2786, 0, + 0, 2903, 0, + 0, 3023, 0, + 0, 3146, 0, + 0, 3271, 0, + 0, 3398, 0, + 0, 3526, 0, + 0, 3655, 0, + 0, 1879, 2179, + 0, 1880, 2179, + 0, 1881, 2178, + 0, 1883, 2176, + 0, 1885, 2174, + 0, 1888, 2172, + 0, 1891, 2168, + 0, 1896, 2164, + 0, 1903, 2158, + 0, 1912, 2150, + 0, 1923, 2138, + 0, 1938, 2123, + 0, 1957, 2101, + 0, 1982, 2070, + 0, 2013, 2026, + 0, 2051, 1958, + 0, 2097, 1848, + 0, 2153, 1642, + 0, 2218, 978, + 0, 2293, 0, + 0, 2376, 0, + 0, 2469, 0, + 0, 2568, 0, + 0, 2675, 0, + 0, 2787, 0, + 0, 2903, 0, + 0, 3023, 0, + 0, 3146, 0, + 0, 3271, 0, + 0, 3398, 0, + 0, 3526, 0, + 0, 3655, 0, + 0, 1883, 2195, + 0, 1884, 2194, + 0, 1885, 2193, + 0, 1887, 2192, + 0, 1889, 2190, + 0, 1892, 2188, + 0, 1895, 2184, + 0, 1900, 2180, + 0, 1907, 2174, + 0, 1916, 2166, + 0, 1927, 2155, + 0, 1942, 2140, + 0, 1961, 2119, + 0, 1985, 2090, + 0, 2016, 2047, + 0, 2054, 1983, + 0, 2100, 1880, + 0, 2155, 1691, + 0, 2220, 1158, + 0, 2294, 0, + 0, 2378, 0, + 0, 2470, 0, + 0, 2569, 0, + 0, 2676, 0, + 0, 2787, 0, + 0, 2904, 0, + 0, 3023, 0, + 0, 3146, 0, + 0, 3271, 0, + 0, 3398, 0, + 0, 3526, 0, + 0, 3655, 0, + 0, 1889, 2215, + 0, 1889, 2214, + 0, 1891, 2213, + 0, 1892, 2212, + 0, 1894, 2210, + 0, 1897, 2208, + 0, 1901, 2205, + 0, 1906, 2200, + 0, 1912, 2195, + 0, 1921, 2187, + 0, 1932, 2177, + 0, 1947, 2163, + 0, 1966, 2143, + 0, 1990, 2115, + 0, 2020, 2074, + 0, 2058, 2014, + 0, 2103, 1919, + 0, 2158, 1748, + 0, 2223, 1323, + 0, 2296, 0, + 0, 2380, 0, + 0, 2471, 0, + 0, 2571, 0, + 0, 2677, 0, + 0, 2788, 0, + 0, 2904, 0, + 0, 3024, 0, + 0, 3146, 0, + 0, 3271, 0, + 0, 3398, 0, + 0, 3526, 0, + 0, 3655, 0, + 241, 1896, 2240, + 162, 1897, 2239, + 31, 1898, 2238, + 0, 1900, 2237, + 0, 1902, 2236, + 0, 1904, 2233, + 0, 1908, 2230, + 0, 1913, 2227, + 0, 1919, 2221, + 0, 1928, 2214, + 0, 1939, 2204, + 0, 1953, 2191, + 0, 1972, 2172, + 0, 1996, 2146, + 0, 2026, 2108, + 0, 2063, 2053, + 0, 2108, 1966, + 0, 2162, 1816, + 0, 2226, 1478, + 0, 2299, 0, + 0, 2382, 0, + 0, 2473, 0, + 0, 2572, 0, + 0, 2678, 0, + 0, 2789, 0, + 0, 2905, 0, + 0, 3024, 0, + 0, 3147, 0, + 0, 3272, 0, + 0, 3398, 0, + 0, 3526, 0, + 0, 3655, 0, + 1385, 1906, 2272, + 1379, 1906, 2271, + 1371, 1908, 2270, + 1360, 1909, 2269, + 1345, 1911, 2268, + 1325, 1914, 2266, + 1296, 1917, 2263, + 1253, 1922, 2259, + 1190, 1929, 2254, + 1089, 1937, 2248, + 903, 1948, 2239, + 397, 1962, 2226, + 0, 1980, 2209, + 0, 2003, 2185, + 0, 2033, 2150, + 0, 2069, 2100, + 0, 2114, 2023, + 0, 2168, 1893, + 0, 2231, 1627, + 0, 2303, 0, + 0, 2385, 0, + 0, 2476, 0, + 0, 2574, 0, + 0, 2680, 0, + 0, 2790, 0, + 0, 2906, 0, + 0, 3025, 0, + 0, 3148, 0, + 0, 3272, 0, + 0, 3399, 0, + 0, 3526, 0, + 0, 3655, 0, + 1749, 1918, 2311, + 1747, 1919, 2310, + 1743, 1920, 2310, + 1738, 1922, 2309, + 1732, 1924, 2307, + 1723, 1926, 2305, + 1711, 1930, 2303, + 1695, 1934, 2300, + 1672, 1941, 2295, + 1639, 1949, 2289, + 1592, 1959, 2281, + 1519, 1973, 2269, + 1399, 1991, 2254, + 1164, 2014, 2232, + 83, 2042, 2201, + 0, 2078, 2156, + 0, 2122, 2088, + 0, 2175, 1978, + 0, 2237, 1771, + 0, 2309, 1096, + 0, 2390, 0, + 0, 2480, 0, + 0, 2577, 0, + 0, 2682, 0, + 0, 2792, 0, + 0, 2907, 0, + 0, 3026, 0, + 0, 3148, 0, + 0, 3273, 0, + 0, 3399, 0, + 0, 3527, 0, + 0, 3656, 0, + 2000, 1935, 2359, + 1999, 1935, 2358, + 1997, 1936, 2358, + 1994, 1938, 2357, + 1990, 1940, 2355, + 1985, 1942, 2354, + 1979, 1946, 2351, + 1970, 1950, 2348, + 1957, 1956, 2344, + 1940, 1964, 2339, + 1916, 1974, 2331, + 1882, 1988, 2321, + 1832, 2005, 2307, + 1755, 2027, 2288, + 1626, 2055, 2261, + 1364, 2090, 2222, + 0, 2133, 2164, + 0, 2184, 2073, + 0, 2245, 1912, + 0, 2316, 1531, + 0, 2396, 0, + 0, 2484, 0, + 0, 2581, 0, + 0, 2685, 0, + 0, 2795, 0, + 0, 2909, 0, + 0, 3028, 0, + 0, 3149, 0, + 0, 3274, 0, + 0, 3400, 0, + 0, 3527, 0, + 0, 3656, 0, + 2205, 1955, 2416, + 2204, 1956, 2415, + 2202, 1957, 2415, + 2201, 1959, 2414, + 2198, 1960, 2413, + 2195, 1963, 2411, + 2191, 1966, 2409, + 2185, 1970, 2407, + 2178, 1976, 2403, + 2167, 1984, 2398, + 2153, 1993, 2392, + 2133, 2006, 2383, + 2105, 2023, 2371, + 2064, 2044, 2354, + 2003, 2071, 2331, + 1907, 2105, 2297, + 1734, 2146, 2249, + 1297, 2196, 2174, + 0, 2256, 2050, + 0, 2325, 1804, + 0, 2403, 318, + 0, 2491, 0, + 0, 2586, 0, + 0, 2689, 0, + 0, 2798, 0, + 0, 2912, 0, + 0, 3030, 0, + 0, 3151, 0, + 0, 3275, 0, + 0, 3401, 0, + 0, 3528, 0, + 0, 3656, 0, + 2384, 1982, 2482, + 2383, 1983, 2482, + 2382, 1984, 2481, + 2381, 1985, 2480, + 2380, 1987, 2479, + 2378, 1989, 2478, + 2375, 1992, 2476, + 2371, 1996, 2474, + 2366, 2002, 2471, + 2359, 2009, 2467, + 2350, 2018, 2461, + 2337, 2030, 2454, + 2319, 2046, 2443, + 2294, 2066, 2429, + 2259, 2092, 2410, + 2206, 2124, 2382, + 2125, 2164, 2342, + 1987, 2212, 2282, + 1696, 2270, 2187, + 0, 2337, 2019, + 0, 2414, 1603, + 0, 2499, 0, + 0, 2593, 0, + 0, 2694, 0, + 0, 2802, 0, + 0, 2915, 0, + 0, 3032, 0, + 0, 3153, 0, + 0, 3276, 0, + 0, 3402, 0, + 0, 3529, 0, + 0, 3657, 0, + 2549, 2015, 2558, + 2548, 2016, 2558, + 2547, 2017, 2557, + 2547, 2018, 2557, + 2546, 2020, 2556, + 2544, 2022, 2555, + 2542, 2025, 2553, + 2540, 2029, 2551, + 2536, 2034, 2549, + 2531, 2040, 2545, + 2525, 2049, 2541, + 2516, 2060, 2534, + 2504, 2075, 2526, + 2488, 2094, 2514, + 2465, 2118, 2497, + 2432, 2149, 2475, + 2385, 2187, 2442, + 2312, 2233, 2395, + 2192, 2288, 2323, + 1958, 2352, 2204, + 895, 2427, 1973, + 0, 2510, 982, + 0, 2602, 0, + 0, 2702, 0, + 0, 2808, 0, + 0, 2919, 0, + 0, 3036, 0, + 0, 3156, 0, + 0, 3278, 0, + 0, 3403, 0, + 0, 3530, 0, + 0, 3658, 0, + 2703, 2056, 2643, + 2703, 2057, 2643, + 2703, 2058, 2642, + 2702, 2059, 2642, + 2701, 2060, 2641, + 2700, 2062, 2640, + 2699, 2065, 2639, + 2697, 2068, 2637, + 2695, 2073, 2635, + 2691, 2079, 2632, + 2687, 2087, 2629, + 2681, 2097, 2623, + 2673, 2111, 2616, + 2661, 2129, 2607, + 2646, 2151, 2593, + 2624, 2180, 2575, + 2593, 2215, 2549, + 2549, 2259, 2512, + 2482, 2311, 2458, + 2373, 2373, 2373, + 2168, 2444, 2226, + 1516, 2524, 1903, + 0, 2614, 0, + 0, 2711, 0, + 0, 2815, 0, + 0, 2925, 0, + 0, 3040, 0, + 0, 3159, 0, + 0, 3281, 0, + 0, 3405, 0, + 0, 3531, 0, + 0, 3659, 0, + 2852, 2106, 2736, + 2852, 2107, 2736, + 2851, 2107, 2736, + 2851, 2108, 2735, + 2850, 2110, 2735, + 2850, 2111, 2734, + 2849, 2114, 2733, + 2847, 2117, 2732, + 2846, 2121, 2730, + 2843, 2126, 2728, + 2840, 2134, 2725, + 2836, 2143, 2720, + 2830, 2155, 2715, + 2822, 2171, 2707, + 2811, 2192, 2696, + 2796, 2218, 2682, + 2775, 2251, 2662, + 2746, 2291, 2633, + 2703, 2340, 2592, + 2640, 2398, 2530, + 2537, 2466, 2431, + 2350, 2543, 2254, + 1830, 2629, 1790, + 0, 2723, 0, + 0, 2825, 0, + 0, 2933, 0, + 0, 3046, 0, + 0, 3164, 0, + 0, 3284, 0, + 0, 3408, 0, + 0, 3533, 0, + 0, 3661, 0, + 2996, 2165, 2837, + 2996, 2165, 2837, + 2995, 2166, 2837, + 2995, 2167, 2836, + 2995, 2168, 2836, + 2994, 2170, 2835, + 2994, 2172, 2835, + 2993, 2174, 2834, + 2991, 2178, 2832, + 2990, 2183, 2830, + 2987, 2189, 2828, + 2984, 2198, 2825, + 2980, 2209, 2820, + 2974, 2223, 2814, + 2966, 2241, 2805, + 2956, 2265, 2794, + 2941, 2294, 2778, + 2921, 2331, 2756, + 2893, 2376, 2725, + 2852, 2430, 2680, + 2790, 2493, 2611, + 2693, 2566, 2500, + 2517, 2648, 2288, + 2062, 2739, 1573, + 0, 2838, 0, + 0, 2943, 0, + 0, 3054, 0, + 0, 3170, 0, + 0, 3289, 0, + 0, 3412, 0, + 0, 3536, 0, + 0, 3663, 0, + 3137, 2233, 2944, + 3136, 2234, 2944, + 3136, 2234, 2944, + 3136, 2235, 2944, + 3136, 2236, 2944, + 3135, 2238, 2943, + 3135, 2239, 2942, + 3134, 2242, 2942, + 3133, 2245, 2941, + 3132, 2249, 2939, + 3130, 2254, 2937, + 3128, 2262, 2934, + 3125, 2271, 2931, + 3121, 2284, 2926, + 3115, 2300, 2920, + 3108, 2320, 2911, + 3097, 2347, 2899, + 3083, 2380, 2882, + 3063, 2420, 2858, + 3036, 2469, 2825, + 2996, 2528, 2776, + 2936, 2596, 2702, + 2841, 2673, 2578, + 2673, 2760, 2331, + 2257, 2854, 796, + 0, 2956, 0, + 0, 3064, 0, + 0, 3178, 0, + 0, 3295, 0, + 0, 3416, 0, + 0, 3540, 0, + 0, 3665, 0, + 3275, 2311, 3057, + 3275, 2312, 3057, + 3275, 2312, 3057, + 3275, 2313, 3057, + 3275, 2314, 3056, + 3274, 2315, 3056, + 3274, 2316, 3055, + 3273, 2318, 3055, + 3273, 2321, 3054, + 3272, 2324, 3053, + 3270, 2329, 3051, + 3269, 2335, 3049, + 3267, 2343, 3046, + 3263, 2354, 3043, + 3259, 2368, 3038, + 3254, 2386, 3031, + 3246, 2409, 3022, + 3236, 2437, 3009, + 3222, 2473, 2991, + 3203, 2517, 2967, + 3175, 2570, 2931, + 3136, 2633, 2880, + 3078, 2704, 2800, + 2985, 2786, 2665, + 2822, 2875, 2382, + 2431, 2973, 0, + 0, 3078, 0, + 0, 3188, 0, + 0, 3303, 0, + 0, 3422, 0, + 0, 3545, 0, + 0, 3669, 0, + 3412, 2398, 3174, + 3412, 2399, 3174, + 3412, 2399, 3174, + 3412, 2400, 3174, + 3411, 2400, 3173, + 3411, 2401, 3173, + 3411, 2402, 3173, + 3411, 2404, 3172, + 3410, 2406, 3172, + 3409, 2409, 3171, + 3408, 2413, 3170, + 3407, 2418, 3168, + 3406, 2425, 3166, + 3403, 2434, 3163, + 3400, 2445, 3159, + 3396, 2461, 3154, + 3391, 2480, 3147, + 3383, 2505, 3137, + 3373, 2536, 3124, + 3360, 2574, 3106, + 3340, 2621, 3080, + 3313, 2677, 3043, + 3275, 2743, 2989, + 3217, 2818, 2905, + 3126, 2902, 2760, + 2967, 2995, 2442, + 2592, 3095, 0, + 0, 3202, 0, + 0, 3314, 0, + 0, 3431, 0, + 0, 3551, 0, + 0, 3674, 0, + 3547, 2493, 3294, + 3547, 2494, 3294, + 3547, 2494, 3294, + 3547, 2494, 3294, + 3547, 2495, 3294, + 3547, 2496, 3294, + 3547, 2497, 3293, + 3547, 2498, 3293, + 3546, 2500, 3293, + 3546, 2502, 3292, + 3545, 2505, 3291, + 3544, 2510, 3290, + 3543, 2515, 3288, + 3541, 2522, 3286, + 3539, 2532, 3283, + 3536, 2545, 3279, + 3532, 2561, 3274, + 3527, 2582, 3266, + 3519, 2608, 3257, + 3509, 2641, 3243, + 3496, 2682, 3224, + 3476, 2731, 3198, + 3450, 2790, 3160, + 3411, 2858, 3103, + 3354, 2936, 3015, + 3265, 3023, 2862, + 3108, 3118, 2512, + 2745, 3220, 0, + 0, 3328, 0, + 0, 3442, 0, + 0, 3559, 0, + 0, 3680, 0, + 3682, 2596, 3418, + 3682, 2596, 3417, + 3682, 2596, 3417, + 3682, 2597, 3417, + 3682, 2597, 3417, + 3682, 2598, 3417, + 3682, 2598, 3417, + 3681, 2599, 3417, + 3681, 2601, 3416, + 3681, 2603, 3416, + 3680, 2605, 3415, + 3680, 2609, 3414, + 3679, 2613, 3413, + 3677, 2619, 3411, + 3676, 2627, 3409, + 3674, 2637, 3406, + 3671, 2650, 3402, + 3667, 2667, 3396, + 3661, 2689, 3389, + 3654, 2717, 3379, + 3644, 2752, 3365, + 3630, 2795, 3346, + 3612, 2846, 3319, + 3585, 2907, 3280, + 3547, 2977, 3222, + 3490, 3057, 3131, + 3401, 3146, 2970, + 3247, 3242, 2592, + 2892, 3346, 0, + 0, 3456, 0, + 0, 3570, 0, + 0, 3689, 0, + 3816, 2704, 3543, + 3816, 2704, 3543, + 3816, 2705, 3543, + 3816, 2705, 3543, + 3816, 2705, 3543, + 3816, 2706, 3542, + 3816, 2706, 3542, + 3816, 2707, 3542, + 3815, 2708, 3542, + 3815, 2710, 3541, + 3815, 2712, 3541, + 3814, 2714, 3540, + 3814, 2718, 3539, + 3813, 2723, 3538, + 3811, 2729, 3536, + 3810, 2737, 3534, + 3808, 2748, 3531, + 3805, 2762, 3527, + 3801, 2780, 3521, + 3795, 2803, 3514, + 3788, 2832, 3504, + 3778, 2868, 3489, + 3765, 2912, 3470, + 3746, 2965, 3442, + 3719, 3027, 3403, + 3681, 3099, 3343, + 3625, 3181, 3250, + 3537, 3271, 3084, + 3384, 3369, 2680, + 3034, 3474, 0, + 0, 3584, 0, + 0, 3699, 0, + 3950, 2818, 3670, + 3950, 2818, 3670, + 3950, 2818, 3670, + 3950, 2818, 3670, + 3950, 2819, 3670, + 3950, 2819, 3669, + 3949, 2819, 3669, + 3949, 2820, 3669, + 3949, 2821, 3669, + 3949, 2822, 3669, + 3949, 2824, 3668, + 3948, 2826, 3668, + 3948, 2829, 3667, + 3947, 2832, 3666, + 3946, 2837, 3665, + 3945, 2844, 3663, + 3943, 2852, 3661, + 3941, 2863, 3658, + 3938, 2878, 3654, + 3934, 2896, 3648, + 3929, 2920, 3640, + 3922, 2950, 3630, + 3912, 2987, 3616, + 3898, 3032, 3596, + 3880, 3087, 3568, + 3853, 3151, 3528, + 3815, 3224, 3467, + 3759, 3307, 3372, + 3672, 3398, 3202, + 3520, 3497, 2776, + 3174, 3602, 0, + 0, 3714, 0, + 4083, 2936, 3798, + 4083, 2936, 3798, + 4083, 2936, 3798, + 4083, 2936, 3798, + 4083, 2936, 3798, + 4083, 2936, 3798, + 4083, 2937, 3798, + 4083, 2937, 3798, + 4082, 2938, 3797, + 4082, 2939, 3797, + 4082, 2940, 3797, + 4082, 2942, 3796, + 4081, 2944, 3796, + 4081, 2947, 3795, + 4080, 2951, 3794, + 4079, 2956, 3793, + 4078, 2962, 3791, + 4077, 2971, 3789, + 4074, 2982, 3786, + 4071, 2997, 3782, + 4068, 3016, 3776, + 4062, 3041, 3768, + 4055, 3071, 3758, + 4045, 3109, 3743, + 4032, 3156, 3723, + 4013, 3211, 3695, + 3987, 3276, 3654, + 3949, 3350, 3593, + 3893, 3434, 3496, + 3806, 3526, 3323, + 3654, 3626, 2880, + 3312, 3732, 0, + 4095, 3057, 3927, + 4095, 3057, 3927, + 4095, 3057, 3927, + 4095, 3057, 3927, + 4095, 3057, 3927, + 4095, 3057, 3927, + 4095, 3058, 3927, + 4095, 3058, 3927, + 4095, 3059, 3927, + 4095, 3059, 3927, + 4095, 3060, 3926, + 4095, 3061, 3926, + 4095, 3063, 3926, + 4095, 3065, 3925, + 4095, 3068, 3924, + 4095, 3072, 3923, + 4095, 3077, 3922, + 4095, 3084, 3920, + 4095, 3093, 3918, + 4095, 3105, 3915, + 4095, 3120, 3911, + 4095, 3139, 3905, + 4095, 3164, 3897, + 4095, 3195, 3887, + 4095, 3234, 3872, + 4095, 3281, 3852, + 4095, 3337, 3823, + 4095, 3403, 3782, + 4082, 3478, 3721, + 4026, 3562, 3623, + 3939, 3655, 3446, + 3788, 3755, 2989, + 4095, 3180, 4057, + 4095, 3180, 4057, + 4095, 3180, 4057, + 4095, 3181, 4057, + 4095, 3181, 4057, + 4095, 3181, 4057, + 4095, 3181, 4057, + 4095, 3181, 4057, + 4095, 3182, 4057, + 4095, 3182, 4057, + 4095, 3183, 4056, + 4095, 3184, 4056, + 4095, 3185, 4056, + 4095, 3187, 4055, + 4095, 3189, 4055, + 4095, 3192, 4054, + 4095, 3196, 4053, + 4095, 3201, 4052, + 4095, 3208, 4050, + 4095, 3217, 4048, + 4095, 3229, 4045, + 4095, 3245, 4040, + 4095, 3264, 4035, + 4095, 3290, 4027, + 4095, 3321, 4016, + 4095, 3360, 4002, + 4095, 3408, 3981, + 4095, 3465, 3953, + 4095, 3531, 3911, + 4095, 3607, 3849, + 4095, 3692, 3751, + 4073, 3785, 3572, + 0, 1998, 2266, + 0, 1999, 2265, + 0, 2000, 2264, + 0, 2001, 2263, + 0, 2003, 2262, + 0, 2005, 2260, + 0, 2008, 2257, + 0, 2012, 2253, + 0, 2017, 2248, + 0, 2024, 2241, + 0, 2033, 2232, + 0, 2045, 2219, + 0, 2060, 2202, + 0, 2079, 2177, + 0, 2104, 2143, + 0, 2136, 2091, + 0, 2175, 2012, + 0, 2222, 1879, + 0, 2278, 1601, + 0, 2344, 0, + 0, 2420, 0, + 0, 2504, 0, + 0, 2597, 0, + 0, 2698, 0, + 0, 2805, 0, + 0, 2917, 0, + 0, 3034, 0, + 0, 3154, 0, + 0, 3277, 0, + 0, 3402, 0, + 0, 3529, 0, + 0, 3657, 0, + 0, 1998, 2267, + 0, 1999, 2266, + 0, 2000, 2265, + 0, 2001, 2264, + 0, 2003, 2263, + 0, 2005, 2260, + 0, 2008, 2258, + 0, 2012, 2254, + 0, 2017, 2249, + 0, 2024, 2242, + 0, 2033, 2233, + 0, 2045, 2220, + 0, 2060, 2203, + 0, 2080, 2179, + 0, 2105, 2144, + 0, 2136, 2093, + 0, 2175, 2014, + 0, 2222, 1881, + 0, 2279, 1606, + 0, 2344, 0, + 0, 2420, 0, + 0, 2504, 0, + 0, 2597, 0, + 0, 2698, 0, + 0, 2805, 0, + 0, 2917, 0, + 0, 3034, 0, + 0, 3154, 0, + 0, 3277, 0, + 0, 3402, 0, + 0, 3529, 0, + 0, 3657, 0, + 0, 1999, 2268, + 0, 1999, 2267, + 0, 2000, 2266, + 0, 2002, 2265, + 0, 2003, 2264, + 0, 2005, 2262, + 0, 2008, 2259, + 0, 2012, 2255, + 0, 2017, 2250, + 0, 2024, 2244, + 0, 2033, 2234, + 0, 2045, 2222, + 0, 2060, 2204, + 0, 2080, 2180, + 0, 2105, 2145, + 0, 2136, 2095, + 0, 2175, 2016, + 0, 2222, 1884, + 0, 2279, 1611, + 0, 2345, 0, + 0, 2420, 0, + 0, 2505, 0, + 0, 2598, 0, + 0, 2698, 0, + 0, 2805, 0, + 0, 2917, 0, + 0, 3034, 0, + 0, 3154, 0, + 0, 3277, 0, + 0, 3402, 0, + 0, 3529, 0, + 0, 3657, 0, + 0, 1999, 2270, + 0, 2000, 2269, + 0, 2001, 2268, + 0, 2002, 2267, + 0, 2004, 2265, + 0, 2006, 2263, + 0, 2009, 2261, + 0, 2013, 2257, + 0, 2018, 2252, + 0, 2025, 2245, + 0, 2034, 2236, + 0, 2045, 2224, + 0, 2061, 2206, + 0, 2080, 2182, + 0, 2105, 2148, + 0, 2137, 2097, + 0, 2175, 2019, + 0, 2223, 1888, + 0, 2279, 1618, + 0, 2345, 0, + 0, 2420, 0, + 0, 2505, 0, + 0, 2598, 0, + 0, 2698, 0, + 0, 2805, 0, + 0, 2917, 0, + 0, 3034, 0, + 0, 3154, 0, + 0, 3277, 0, + 0, 3402, 0, + 0, 3529, 0, + 0, 3657, 0, + 0, 2000, 2272, + 0, 2000, 2271, + 0, 2001, 2270, + 0, 2003, 2269, + 0, 2004, 2268, + 0, 2006, 2266, + 0, 2009, 2263, + 0, 2013, 2259, + 0, 2018, 2254, + 0, 2025, 2248, + 0, 2034, 2239, + 0, 2046, 2226, + 0, 2061, 2209, + 0, 2081, 2185, + 0, 2106, 2151, + 0, 2137, 2100, + 0, 2176, 2023, + 0, 2223, 1893, + 0, 2279, 1627, + 0, 2345, 0, + 0, 2420, 0, + 0, 2505, 0, + 0, 2598, 0, + 0, 2698, 0, + 0, 2805, 0, + 0, 2917, 0, + 0, 3034, 0, + 0, 3154, 0, + 0, 3277, 0, + 0, 3402, 0, + 0, 3529, 0, + 0, 3657, 0, + 0, 2000, 2275, + 0, 2001, 2274, + 0, 2002, 2273, + 0, 2003, 2272, + 0, 2005, 2271, + 0, 2007, 2269, + 0, 2010, 2266, + 0, 2014, 2262, + 0, 2019, 2258, + 0, 2026, 2251, + 0, 2035, 2242, + 0, 2047, 2230, + 0, 2062, 2212, + 0, 2081, 2189, + 0, 2106, 2155, + 0, 2138, 2105, + 0, 2176, 2028, + 0, 2223, 1900, + 0, 2280, 1640, + 0, 2345, 0, + 0, 2421, 0, + 0, 2505, 0, + 0, 2598, 0, + 0, 2698, 0, + 0, 2805, 0, + 0, 2917, 0, + 0, 3034, 0, + 0, 3154, 0, + 0, 3277, 0, + 0, 3403, 0, + 0, 3529, 0, + 0, 3658, 0, + 0, 2001, 2279, + 0, 2002, 2278, + 0, 2003, 2277, + 0, 2004, 2276, + 0, 2006, 2275, + 0, 2008, 2273, + 0, 2011, 2270, + 0, 2015, 2267, + 0, 2020, 2262, + 0, 2027, 2255, + 0, 2036, 2246, + 0, 2048, 2234, + 0, 2063, 2217, + 0, 2082, 2193, + 0, 2107, 2160, + 0, 2138, 2110, + 0, 2177, 2035, + 0, 2224, 1909, + 0, 2280, 1655, + 0, 2346, 0, + 0, 2421, 0, + 0, 2505, 0, + 0, 2598, 0, + 0, 2699, 0, + 0, 2805, 0, + 0, 2918, 0, + 0, 3034, 0, + 0, 3154, 0, + 0, 3277, 0, + 0, 3403, 0, + 0, 3529, 0, + 0, 3658, 0, + 0, 2003, 2284, + 0, 2003, 2283, + 0, 2004, 2283, + 0, 2006, 2282, + 0, 2007, 2280, + 0, 2009, 2278, + 0, 2012, 2275, + 0, 2016, 2272, + 0, 2021, 2267, + 0, 2028, 2261, + 0, 2037, 2252, + 0, 2049, 2240, + 0, 2064, 2223, + 0, 2083, 2200, + 0, 2108, 2166, + 0, 2139, 2118, + 0, 2178, 2044, + 0, 2225, 1921, + 0, 2281, 1676, + 0, 2347, 277, + 0, 2422, 0, + 0, 2506, 0, + 0, 2599, 0, + 0, 2699, 0, + 0, 2806, 0, + 0, 2918, 0, + 0, 3034, 0, + 0, 3155, 0, + 0, 3278, 0, + 0, 3403, 0, + 0, 3529, 0, + 0, 3658, 0, + 0, 2005, 2291, + 0, 2005, 2290, + 0, 2006, 2290, + 0, 2007, 2288, + 0, 2009, 2287, + 0, 2011, 2285, + 0, 2014, 2283, + 0, 2018, 2279, + 0, 2023, 2274, + 0, 2030, 2268, + 0, 2039, 2259, + 0, 2050, 2247, + 0, 2065, 2231, + 0, 2085, 2208, + 0, 2110, 2175, + 0, 2141, 2128, + 0, 2179, 2055, + 0, 2226, 1936, + 0, 2282, 1702, + 0, 2347, 650, + 0, 2422, 0, + 0, 2507, 0, + 0, 2599, 0, + 0, 2699, 0, + 0, 2806, 0, + 0, 2918, 0, + 0, 3035, 0, + 0, 3155, 0, + 0, 3278, 0, + 0, 3403, 0, + 0, 3530, 0, + 0, 3658, 0, + 0, 2007, 2300, + 0, 2008, 2299, + 0, 2009, 2299, + 0, 2010, 2298, + 0, 2011, 2296, + 0, 2014, 2294, + 0, 2017, 2292, + 0, 2020, 2288, + 0, 2025, 2284, + 0, 2032, 2277, + 0, 2041, 2269, + 0, 2053, 2257, + 0, 2068, 2241, + 0, 2087, 2219, + 0, 2111, 2187, + 0, 2142, 2141, + 0, 2181, 2071, + 0, 2227, 1955, + 0, 2283, 1734, + 0, 2349, 904, + 0, 2423, 0, + 0, 2507, 0, + 0, 2600, 0, + 0, 2700, 0, + 0, 2806, 0, + 0, 2918, 0, + 0, 3035, 0, + 0, 3155, 0, + 0, 3278, 0, + 0, 3403, 0, + 0, 3530, 0, + 0, 3658, 0, + 0, 2010, 2312, + 0, 2011, 2311, + 0, 2012, 2311, + 0, 2013, 2310, + 0, 2015, 2308, + 0, 2017, 2306, + 0, 2020, 2304, + 0, 2023, 2301, + 0, 2029, 2296, + 0, 2035, 2290, + 0, 2044, 2282, + 0, 2055, 2270, + 0, 2070, 2255, + 0, 2090, 2233, + 0, 2114, 2202, + 0, 2145, 2158, + 0, 2183, 2090, + 0, 2229, 1980, + 0, 2285, 1774, + 0, 2350, 1110, + 0, 2425, 0, + 0, 2508, 0, + 0, 2601, 0, + 0, 2700, 0, + 0, 2807, 0, + 0, 2919, 0, + 0, 3035, 0, + 0, 3155, 0, + 0, 3278, 0, + 0, 3403, 0, + 0, 3530, 0, + 0, 3658, 0, + 0, 2014, 2327, + 0, 2015, 2327, + 0, 2016, 2326, + 0, 2017, 2325, + 0, 2019, 2324, + 0, 2021, 2322, + 0, 2024, 2320, + 0, 2028, 2316, + 0, 2033, 2312, + 0, 2039, 2306, + 0, 2048, 2298, + 0, 2059, 2287, + 0, 2074, 2272, + 0, 2093, 2251, + 0, 2117, 2222, + 0, 2148, 2179, + 0, 2186, 2115, + 0, 2232, 2012, + 0, 2287, 1823, + 0, 2352, 1290, + 0, 2426, 0, + 0, 2510, 0, + 0, 2602, 0, + 0, 2701, 0, + 0, 2808, 0, + 0, 2919, 0, + 0, 3036, 0, + 0, 3155, 0, + 0, 3278, 0, + 0, 3403, 0, + 0, 3530, 0, + 0, 3658, 0, + 0, 2020, 2347, + 0, 2021, 2347, + 0, 2022, 2346, + 0, 2023, 2345, + 0, 2024, 2344, + 0, 2026, 2342, + 0, 2029, 2340, + 0, 2033, 2337, + 0, 2038, 2333, + 0, 2044, 2327, + 0, 2053, 2319, + 0, 2064, 2309, + 0, 2079, 2295, + 0, 2098, 2275, + 0, 2122, 2247, + 0, 2152, 2206, + 0, 2190, 2146, + 0, 2235, 2051, + 0, 2290, 1881, + 0, 2355, 1455, + 0, 2429, 0, + 0, 2512, 0, + 0, 2603, 0, + 0, 2703, 0, + 0, 2809, 0, + 0, 2920, 0, + 0, 3036, 0, + 0, 3156, 0, + 0, 3279, 0, + 0, 3403, 0, + 0, 3530, 0, + 0, 3658, 0, + 423, 2027, 2373, + 373, 2028, 2372, + 295, 2029, 2371, + 163, 2030, 2370, + 0, 2032, 2369, + 0, 2034, 2368, + 0, 2036, 2365, + 0, 2040, 2363, + 0, 2045, 2359, + 0, 2051, 2353, + 0, 2060, 2346, + 0, 2071, 2336, + 0, 2085, 2323, + 0, 2104, 2304, + 0, 2128, 2278, + 0, 2158, 2241, + 0, 2195, 2185, + 0, 2240, 2098, + 0, 2294, 1948, + 0, 2358, 1610, + 0, 2432, 0, + 0, 2514, 0, + 0, 2605, 0, + 0, 2704, 0, + 0, 2810, 0, + 0, 2921, 0, + 0, 3037, 0, + 0, 3157, 0, + 0, 3279, 0, + 0, 3404, 0, + 0, 3530, 0, + 0, 3658, 0, + 1521, 2037, 2404, + 1517, 2038, 2404, + 1511, 2039, 2403, + 1503, 2040, 2402, + 1492, 2041, 2401, + 1477, 2043, 2400, + 1457, 2046, 2398, + 1428, 2050, 2395, + 1385, 2054, 2391, + 1322, 2061, 2386, + 1221, 2069, 2380, + 1036, 2080, 2371, + 529, 2094, 2358, + 0, 2112, 2341, + 0, 2135, 2317, + 0, 2165, 2283, + 0, 2201, 2232, + 0, 2246, 2155, + 0, 2300, 2025, + 0, 2363, 1759, + 0, 2436, 0, + 0, 2518, 0, + 0, 2608, 0, + 0, 2707, 0, + 0, 2812, 0, + 0, 2923, 0, + 0, 3038, 0, + 0, 3157, 0, + 0, 3280, 0, + 0, 3404, 0, + 0, 3531, 0, + 0, 3659, 0, + 1883, 2050, 2444, + 1881, 2050, 2443, + 1879, 2051, 2443, + 1875, 2052, 2442, + 1870, 2054, 2441, + 1864, 2056, 2439, + 1855, 2058, 2437, + 1843, 2062, 2435, + 1827, 2066, 2432, + 1804, 2073, 2427, + 1771, 2081, 2421, + 1724, 2091, 2413, + 1651, 2105, 2401, + 1531, 2123, 2386, + 1296, 2146, 2364, + 216, 2174, 2333, + 0, 2210, 2288, + 0, 2254, 2221, + 0, 2307, 2111, + 0, 2369, 1903, + 0, 2441, 1228, + 0, 2522, 0, + 0, 2612, 0, + 0, 2709, 0, + 0, 2814, 0, + 0, 2924, 0, + 0, 3039, 0, + 0, 3158, 0, + 0, 3280, 0, + 0, 3405, 0, + 0, 3531, 0, + 0, 3659, 0, + 2133, 2066, 2491, + 2132, 2067, 2491, + 2131, 2067, 2490, + 2129, 2068, 2490, + 2126, 2070, 2489, + 2122, 2072, 2487, + 2118, 2074, 2486, + 2111, 2078, 2484, + 2102, 2082, 2481, + 2089, 2088, 2476, + 2072, 2096, 2471, + 2048, 2106, 2464, + 2014, 2120, 2453, + 1964, 2137, 2440, + 1887, 2159, 2420, + 1758, 2187, 2393, + 1496, 2222, 2354, + 0, 2265, 2296, + 0, 2316, 2205, + 0, 2377, 2044, + 0, 2448, 1663, + 0, 2528, 0, + 0, 2617, 0, + 0, 2713, 0, + 0, 2817, 0, + 0, 2927, 0, + 0, 3041, 0, + 0, 3160, 0, + 0, 3282, 0, + 0, 3406, 0, + 0, 3532, 0, + 0, 3659, 0, + 2337, 2087, 2548, + 2337, 2088, 2548, + 2336, 2088, 2547, + 2334, 2089, 2547, + 2333, 2091, 2546, + 2330, 2093, 2545, + 2327, 2095, 2543, + 2323, 2098, 2541, + 2317, 2103, 2539, + 2310, 2108, 2535, + 2299, 2116, 2530, + 2285, 2126, 2524, + 2265, 2138, 2515, + 2237, 2155, 2503, + 2196, 2176, 2486, + 2135, 2203, 2463, + 2039, 2237, 2429, + 1866, 2278, 2381, + 1429, 2329, 2306, + 0, 2388, 2182, + 0, 2457, 1936, + 0, 2536, 450, + 0, 2623, 0, + 0, 2718, 0, + 0, 2821, 0, + 0, 2930, 0, + 0, 3044, 0, + 0, 3162, 0, + 0, 3283, 0, + 0, 3407, 0, + 0, 3533, 0, + 0, 3660, 0, + 2517, 2114, 2614, + 2516, 2114, 2614, + 2515, 2115, 2614, + 2515, 2116, 2613, + 2513, 2117, 2612, + 2512, 2119, 2612, + 2510, 2121, 2610, + 2507, 2124, 2609, + 2503, 2128, 2606, + 2498, 2134, 2603, + 2491, 2141, 2599, + 2482, 2150, 2593, + 2469, 2162, 2586, + 2451, 2178, 2576, + 2426, 2198, 2561, + 2391, 2224, 2542, + 2338, 2256, 2514, + 2257, 2296, 2474, + 2119, 2344, 2414, + 1828, 2402, 2319, + 0, 2469, 2151, + 0, 2546, 1735, + 0, 2631, 0, + 0, 2725, 0, + 0, 2827, 0, + 0, 2934, 0, + 0, 3047, 0, + 0, 3164, 0, + 0, 3285, 0, + 0, 3408, 0, + 0, 3534, 0, + 0, 3661, 0, + 2681, 2147, 2690, + 2681, 2147, 2690, + 2680, 2148, 2690, + 2680, 2149, 2689, + 2679, 2150, 2689, + 2678, 2152, 2688, + 2676, 2154, 2687, + 2674, 2157, 2685, + 2672, 2161, 2683, + 2668, 2166, 2681, + 2663, 2172, 2677, + 2657, 2181, 2673, + 2648, 2192, 2666, + 2636, 2207, 2658, + 2620, 2226, 2646, + 2597, 2250, 2629, + 2565, 2281, 2607, + 2517, 2319, 2574, + 2444, 2365, 2527, + 2325, 2420, 2455, + 2090, 2485, 2336, + 1027, 2559, 2105, + 0, 2642, 1114, + 0, 2734, 0, + 0, 2834, 0, + 0, 2940, 0, + 0, 3052, 0, + 0, 3168, 0, + 0, 3288, 0, + 0, 3410, 0, + 0, 3535, 0, + 0, 3662, 0, + 2836, 2188, 2775, + 2836, 2189, 2775, + 2835, 2189, 2775, + 2835, 2190, 2774, + 2834, 2191, 2774, + 2833, 2193, 2773, + 2832, 2194, 2772, + 2831, 2197, 2771, + 2829, 2201, 2770, + 2827, 2205, 2767, + 2823, 2211, 2765, + 2819, 2219, 2761, + 2813, 2230, 2755, + 2805, 2243, 2748, + 2793, 2261, 2739, + 2778, 2283, 2725, + 2756, 2312, 2707, + 2726, 2347, 2681, + 2681, 2391, 2644, + 2614, 2443, 2590, + 2505, 2505, 2505, + 2300, 2576, 2358, + 1648, 2656, 2036, + 0, 2746, 0, + 0, 2843, 0, + 0, 2947, 0, + 0, 3057, 0, + 0, 3172, 0, + 0, 3291, 0, + 0, 3413, 0, + 0, 3537, 0, + 0, 3664, 0, + 2984, 2238, 2869, + 2984, 2238, 2868, + 2984, 2239, 2868, + 2983, 2239, 2868, + 2983, 2240, 2868, + 2983, 2242, 2867, + 2982, 2244, 2866, + 2981, 2246, 2865, + 2979, 2249, 2864, + 2978, 2253, 2862, + 2975, 2259, 2860, + 2972, 2266, 2857, + 2968, 2275, 2853, + 2962, 2287, 2847, + 2954, 2303, 2839, + 2943, 2324, 2828, + 2928, 2350, 2814, + 2907, 2383, 2794, + 2878, 2423, 2765, + 2836, 2472, 2724, + 2772, 2530, 2662, + 2669, 2598, 2563, + 2482, 2675, 2386, + 1962, 2761, 1922, + 0, 2855, 0, + 0, 2957, 0, + 0, 3065, 0, + 0, 3178, 0, + 0, 3296, 0, + 0, 3417, 0, + 0, 3540, 0, + 0, 3666, 0, + 3128, 2297, 2969, + 3128, 2297, 2969, + 3128, 2298, 2969, + 3128, 2298, 2969, + 3127, 2299, 2969, + 3127, 2300, 2968, + 3126, 2302, 2968, + 3126, 2304, 2967, + 3125, 2307, 2966, + 3123, 2310, 2964, + 3122, 2315, 2962, + 3119, 2321, 2960, + 3116, 2330, 2957, + 3112, 2341, 2952, + 3106, 2355, 2946, + 3099, 2373, 2938, + 3088, 2397, 2926, + 3073, 2426, 2910, + 3053, 2463, 2888, + 3025, 2508, 2857, + 2984, 2562, 2812, + 2922, 2625, 2744, + 2825, 2698, 2632, + 2649, 2780, 2420, + 2195, 2871, 1705, + 0, 2970, 0, + 0, 3075, 0, + 0, 3186, 0, + 0, 3302, 0, + 0, 3421, 0, + 0, 3544, 0, + 0, 3668, 0, + 3269, 2365, 3077, + 3269, 2366, 3077, + 3269, 2366, 3076, + 3268, 2367, 3076, + 3268, 2367, 3076, + 3268, 2368, 3076, + 3268, 2370, 3075, + 3267, 2371, 3075, + 3266, 2374, 3074, + 3265, 2377, 3073, + 3264, 2381, 3071, + 3262, 2387, 3069, + 3260, 2394, 3067, + 3257, 2403, 3063, + 3253, 2416, 3058, + 3247, 2432, 3052, + 3240, 2453, 3043, + 3229, 2479, 3031, + 3215, 2512, 3014, + 3195, 2552, 2990, + 3168, 2601, 2957, + 3128, 2660, 2908, + 3068, 2728, 2834, + 2973, 2805, 2710, + 2805, 2892, 2463, + 2389, 2986, 928, + 0, 3088, 0, + 0, 3197, 0, + 0, 3310, 0, + 0, 3427, 0, + 0, 3548, 0, + 0, 3672, 0, + 3407, 2443, 3189, + 3407, 2444, 3189, + 3407, 2444, 3189, + 3407, 2444, 3189, + 3407, 2445, 3189, + 3407, 2446, 3188, + 3406, 2447, 3188, + 3406, 2448, 3188, + 3405, 2450, 3187, + 3405, 2453, 3186, + 3404, 2457, 3185, + 3403, 2461, 3183, + 3401, 2467, 3181, + 3399, 2475, 3179, + 3396, 2486, 3175, + 3392, 2500, 3170, + 3386, 2518, 3163, + 3379, 2541, 3154, + 3368, 2570, 3141, + 3354, 2605, 3123, + 3335, 2649, 3099, + 3308, 2702, 3064, + 3268, 2765, 3012, + 3210, 2836, 2932, + 3117, 2918, 2797, + 2954, 3008, 2514, + 2563, 3105, 0, + 0, 3210, 0, + 0, 3320, 0, + 0, 3436, 0, + 0, 3555, 0, + 0, 3677, 0, + 3544, 2530, 3306, + 3544, 2530, 3306, + 3544, 2531, 3306, + 3544, 2531, 3306, + 3544, 2532, 3306, + 3544, 2532, 3305, + 3543, 2533, 3305, + 3543, 2534, 3305, + 3543, 2536, 3304, + 3542, 2538, 3304, + 3541, 2541, 3303, + 3541, 2545, 3302, + 3539, 2550, 3300, + 3538, 2557, 3298, + 3535, 2566, 3295, + 3532, 2578, 3291, + 3528, 2593, 3286, + 3523, 2612, 3279, + 3516, 2637, 3269, + 3505, 2668, 3256, + 3492, 2707, 3238, + 3472, 2754, 3212, + 3445, 2810, 3175, + 3407, 2875, 3121, + 3349, 2950, 3037, + 3258, 3034, 2892, + 3099, 3127, 2574, + 2724, 3227, 0, + 0, 3334, 0, + 0, 3446, 0, + 0, 3563, 0, + 0, 3683, 0, + 3680, 2625, 3427, + 3680, 2626, 3426, + 3680, 2626, 3426, + 3679, 2626, 3426, + 3679, 2626, 3426, + 3679, 2627, 3426, + 3679, 2628, 3426, + 3679, 2629, 3426, + 3679, 2630, 3425, + 3678, 2632, 3425, + 3678, 2634, 3424, + 3677, 2637, 3423, + 3676, 2642, 3422, + 3675, 2647, 3420, + 3673, 2655, 3418, + 3671, 2664, 3415, + 3668, 2677, 3411, + 3664, 2693, 3406, + 3659, 2714, 3399, + 3651, 2740, 3389, + 3641, 2773, 3375, + 3628, 2814, 3356, + 3609, 2863, 3330, + 3582, 2922, 3292, + 3543, 2990, 3236, + 3486, 3068, 3147, + 3397, 3155, 2994, + 3240, 3250, 2644, + 2877, 3352, 0, + 0, 3460, 0, + 0, 3574, 0, + 0, 3691, 0, + 3814, 2728, 3550, + 3814, 2728, 3550, + 3814, 2728, 3550, + 3814, 2728, 3550, + 3814, 2729, 3549, + 3814, 2729, 3549, + 3814, 2730, 3549, + 3814, 2730, 3549, + 3814, 2732, 3549, + 3813, 2733, 3548, + 3813, 2735, 3548, + 3812, 2737, 3547, + 3812, 2741, 3546, + 3811, 2745, 3545, + 3810, 2751, 3543, + 3808, 2759, 3541, + 3806, 2769, 3538, + 3803, 2782, 3534, + 3799, 2800, 3528, + 3793, 2822, 3521, + 3786, 2849, 3511, + 3776, 2884, 3497, + 3763, 2927, 3478, + 3744, 2978, 3451, + 3717, 3039, 3412, + 3679, 3109, 3354, + 3622, 3189, 3263, + 3534, 3278, 3102, + 3379, 3374, 2724, + 3024, 3478, 0, + 0, 3588, 0, + 0, 3702, 0, + 3948, 2836, 3675, + 3948, 2836, 3675, + 3948, 2836, 3675, + 3948, 2837, 3675, + 3948, 2837, 3675, + 3948, 2837, 3675, + 3948, 2838, 3675, + 3948, 2838, 3674, + 3948, 2839, 3674, + 3948, 2840, 3674, + 3947, 2842, 3673, + 3947, 2844, 3673, + 3946, 2847, 3672, + 3946, 2850, 3671, + 3945, 2855, 3670, + 3944, 2861, 3668, + 3942, 2869, 3666, + 3940, 2880, 3663, + 3937, 2894, 3659, + 3933, 2912, 3653, + 3928, 2935, 3646, + 3920, 2964, 3636, + 3910, 3000, 3622, + 3897, 3044, 3602, + 3878, 3097, 3574, + 3852, 3160, 3535, + 3814, 3232, 3475, + 3757, 3313, 3382, + 3669, 3403, 3216, + 3516, 3501, 2812, + 3167, 3606, 0, + 0, 3716, 0, + 4082, 2950, 3802, + 4082, 2950, 3802, + 4082, 2950, 3802, + 4082, 2950, 3802, + 4082, 2950, 3802, + 4082, 2951, 3802, + 4082, 2951, 3802, + 4082, 2952, 3801, + 4081, 2952, 3801, + 4081, 2953, 3801, + 4081, 2954, 3801, + 4081, 2956, 3800, + 4080, 2958, 3800, + 4080, 2961, 3799, + 4079, 2964, 3798, + 4078, 2969, 3797, + 4077, 2976, 3795, + 4075, 2984, 3793, + 4073, 2995, 3790, + 4070, 3010, 3786, + 4066, 3028, 3780, + 4061, 3052, 3772, + 4054, 3082, 3762, + 4044, 3119, 3748, + 4030, 3164, 3728, + 4012, 3219, 3700, + 3985, 3283, 3660, + 3948, 3356, 3599, + 3892, 3439, 3504, + 3804, 3530, 3334, + 3652, 3629, 2909, + 3307, 3735, 0, + 4095, 3068, 3930, + 4095, 3068, 3930, + 4095, 3068, 3930, + 4095, 3068, 3930, + 4095, 3068, 3930, + 4095, 3068, 3930, + 4095, 3069, 3930, + 4095, 3069, 3930, + 4095, 3069, 3930, + 4095, 3070, 3929, + 4095, 3071, 3929, + 4095, 3072, 3929, + 4095, 3074, 3929, + 4095, 3076, 3928, + 4095, 3079, 3927, + 4095, 3083, 3926, + 4095, 3088, 3925, + 4095, 3094, 3923, + 4095, 3103, 3921, + 4095, 3114, 3918, + 4095, 3129, 3914, + 4095, 3148, 3908, + 4095, 3173, 3900, + 4095, 3203, 3890, + 4095, 3241, 3875, + 4095, 3288, 3855, + 4095, 3343, 3827, + 4095, 3408, 3786, + 4081, 3482, 3725, + 4025, 3566, 3629, + 3938, 3658, 3455, + 3786, 3758, 3012, + 4095, 3189, 4059, + 4095, 3189, 4059, + 4095, 3189, 4059, + 4095, 3189, 4059, + 4095, 3189, 4059, + 4095, 3189, 4059, + 4095, 3189, 4059, + 4095, 3190, 4059, + 4095, 3190, 4059, + 4095, 3191, 4059, + 4095, 3191, 4059, + 4095, 3192, 4058, + 4095, 3193, 4058, + 4095, 3195, 4058, + 4095, 3197, 4057, + 4095, 3200, 4056, + 4095, 3204, 4055, + 4095, 3209, 4054, + 4095, 3216, 4052, + 4095, 3225, 4050, + 4095, 3237, 4047, + 4095, 3252, 4043, + 4095, 3271, 4037, + 4095, 3296, 4029, + 4095, 3327, 4019, + 4095, 3366, 4004, + 4095, 3413, 3984, + 4095, 3469, 3956, + 4095, 3535, 3914, + 4095, 3610, 3853, + 4095, 3694, 3755, + 4071, 3787, 3579, + 0, 2129, 2398, + 0, 2130, 2397, + 0, 2131, 2396, + 0, 2132, 2396, + 0, 2133, 2394, + 0, 2135, 2393, + 0, 2137, 2391, + 0, 2140, 2388, + 0, 2144, 2384, + 0, 2149, 2379, + 0, 2156, 2373, + 0, 2165, 2363, + 0, 2176, 2351, + 0, 2192, 2333, + 0, 2211, 2309, + 0, 2236, 2274, + 0, 2268, 2222, + 0, 2307, 2143, + 0, 2354, 2009, + 0, 2410, 1731, + 0, 2476, 0, + 0, 2552, 0, + 0, 2636, 0, + 0, 2729, 0, + 0, 2830, 0, + 0, 2937, 0, + 0, 3049, 0, + 0, 3166, 0, + 0, 3286, 0, + 0, 3409, 0, + 0, 3535, 0, + 0, 3661, 0, + 0, 2130, 2398, + 0, 2130, 2398, + 0, 2131, 2397, + 0, 2132, 2396, + 0, 2133, 2395, + 0, 2135, 2394, + 0, 2137, 2392, + 0, 2140, 2389, + 0, 2144, 2385, + 0, 2149, 2380, + 0, 2156, 2373, + 0, 2165, 2364, + 0, 2177, 2352, + 0, 2192, 2334, + 0, 2212, 2310, + 0, 2237, 2275, + 0, 2268, 2223, + 0, 2307, 2144, + 0, 2354, 2011, + 0, 2411, 1734, + 0, 2476, 0, + 0, 2552, 0, + 0, 2636, 0, + 0, 2729, 0, + 0, 2830, 0, + 0, 2937, 0, + 0, 3049, 0, + 0, 3166, 0, + 0, 3286, 0, + 0, 3409, 0, + 0, 3535, 0, + 0, 3661, 0, + 0, 2130, 2399, + 0, 2130, 2399, + 0, 2131, 2398, + 0, 2132, 2397, + 0, 2133, 2396, + 0, 2135, 2395, + 0, 2137, 2393, + 0, 2140, 2390, + 0, 2144, 2386, + 0, 2149, 2381, + 0, 2156, 2374, + 0, 2165, 2365, + 0, 2177, 2353, + 0, 2192, 2335, + 0, 2212, 2311, + 0, 2237, 2276, + 0, 2268, 2225, + 0, 2307, 2146, + 0, 2354, 2013, + 0, 2411, 1738, + 0, 2477, 0, + 0, 2552, 0, + 0, 2637, 0, + 0, 2730, 0, + 0, 2830, 0, + 0, 2937, 0, + 0, 3049, 0, + 0, 3166, 0, + 0, 3286, 0, + 0, 3409, 0, + 0, 3535, 0, + 0, 3661, 0, + 0, 2130, 2400, + 0, 2131, 2400, + 0, 2131, 2399, + 0, 2132, 2399, + 0, 2134, 2397, + 0, 2135, 2396, + 0, 2138, 2394, + 0, 2140, 2391, + 0, 2144, 2387, + 0, 2150, 2382, + 0, 2156, 2376, + 0, 2165, 2367, + 0, 2177, 2354, + 0, 2192, 2337, + 0, 2212, 2312, + 0, 2237, 2278, + 0, 2268, 2227, + 0, 2307, 2148, + 0, 2354, 2016, + 0, 2411, 1743, + 0, 2477, 0, + 0, 2552, 0, + 0, 2637, 0, + 0, 2730, 0, + 0, 2830, 0, + 0, 2937, 0, + 0, 3049, 0, + 0, 3166, 0, + 0, 3286, 0, + 0, 3409, 0, + 0, 3535, 0, + 0, 3661, 0, + 0, 2131, 2402, + 0, 2131, 2402, + 0, 2132, 2401, + 0, 2133, 2400, + 0, 2134, 2399, + 0, 2136, 2398, + 0, 2138, 2396, + 0, 2141, 2393, + 0, 2145, 2389, + 0, 2150, 2384, + 0, 2157, 2377, + 0, 2166, 2368, + 0, 2177, 2356, + 0, 2193, 2339, + 0, 2212, 2314, + 0, 2237, 2280, + 0, 2269, 2229, + 0, 2307, 2151, + 0, 2355, 2020, + 0, 2411, 1750, + 0, 2477, 0, + 0, 2552, 0, + 0, 2637, 0, + 0, 2730, 0, + 0, 2830, 0, + 0, 2937, 0, + 0, 3049, 0, + 0, 3166, 0, + 0, 3286, 0, + 0, 3409, 0, + 0, 3535, 0, + 0, 3661, 0, + 0, 2131, 2404, + 0, 2132, 2404, + 0, 2132, 2403, + 0, 2133, 2402, + 0, 2135, 2401, + 0, 2136, 2400, + 0, 2139, 2398, + 0, 2141, 2395, + 0, 2145, 2391, + 0, 2151, 2387, + 0, 2157, 2380, + 0, 2166, 2371, + 0, 2178, 2358, + 0, 2193, 2341, + 0, 2213, 2317, + 0, 2238, 2283, + 0, 2269, 2232, + 0, 2308, 2155, + 0, 2355, 2025, + 0, 2411, 1760, + 0, 2477, 0, + 0, 2553, 0, + 0, 2637, 0, + 0, 2730, 0, + 0, 2830, 0, + 0, 2937, 0, + 0, 3049, 0, + 0, 3166, 0, + 0, 3286, 0, + 0, 3409, 0, + 0, 3535, 0, + 0, 3661, 0, + 0, 2132, 2407, + 0, 2133, 2407, + 0, 2133, 2406, + 0, 2134, 2405, + 0, 2135, 2404, + 0, 2137, 2403, + 0, 2139, 2401, + 0, 2142, 2398, + 0, 2146, 2395, + 0, 2151, 2390, + 0, 2158, 2383, + 0, 2167, 2374, + 0, 2179, 2362, + 0, 2194, 2345, + 0, 2213, 2321, + 0, 2238, 2287, + 0, 2270, 2237, + 0, 2308, 2160, + 0, 2356, 2032, + 0, 2412, 1772, + 0, 2478, 0, + 0, 2553, 0, + 0, 2637, 0, + 0, 2730, 0, + 0, 2830, 0, + 0, 2937, 0, + 0, 3050, 0, + 0, 3166, 0, + 0, 3286, 0, + 0, 3409, 0, + 0, 3535, 0, + 0, 3661, 0, + 0, 2133, 2411, + 0, 2134, 2411, + 0, 2134, 2410, + 0, 2135, 2409, + 0, 2136, 2408, + 0, 2138, 2407, + 0, 2140, 2405, + 0, 2143, 2402, + 0, 2147, 2399, + 0, 2152, 2394, + 0, 2159, 2387, + 0, 2168, 2378, + 0, 2180, 2366, + 0, 2195, 2349, + 0, 2214, 2325, + 0, 2239, 2292, + 0, 2270, 2242, + 0, 2309, 2167, + 0, 2356, 2041, + 0, 2412, 1788, + 0, 2478, 0, + 0, 2553, 0, + 0, 2638, 0, + 0, 2730, 0, + 0, 2831, 0, + 0, 2937, 0, + 0, 3050, 0, + 0, 3166, 0, + 0, 3287, 0, + 0, 3410, 0, + 0, 3535, 0, + 0, 3662, 0, + 0, 2134, 2417, + 0, 2135, 2416, + 0, 2136, 2416, + 0, 2136, 2415, + 0, 2138, 2414, + 0, 2139, 2412, + 0, 2142, 2410, + 0, 2144, 2408, + 0, 2148, 2404, + 0, 2154, 2399, + 0, 2160, 2393, + 0, 2169, 2384, + 0, 2181, 2372, + 0, 2196, 2355, + 0, 2215, 2332, + 0, 2240, 2299, + 0, 2271, 2250, + 0, 2310, 2176, + 0, 2357, 2053, + 0, 2413, 1808, + 0, 2479, 410, + 0, 2554, 0, + 0, 2638, 0, + 0, 2731, 0, + 0, 2831, 0, + 0, 2938, 0, + 0, 3050, 0, + 0, 3166, 0, + 0, 3287, 0, + 0, 3410, 0, + 0, 3535, 0, + 0, 3662, 0, + 0, 2136, 2424, + 0, 2137, 2423, + 0, 2137, 2422, + 0, 2138, 2422, + 0, 2140, 2421, + 0, 2141, 2419, + 0, 2143, 2417, + 0, 2146, 2415, + 0, 2150, 2411, + 0, 2155, 2406, + 0, 2162, 2400, + 0, 2171, 2391, + 0, 2182, 2379, + 0, 2198, 2363, + 0, 2217, 2340, + 0, 2242, 2308, + 0, 2273, 2260, + 0, 2311, 2187, + 0, 2358, 2068, + 0, 2414, 1834, + 0, 2479, 782, + 0, 2554, 0, + 0, 2639, 0, + 0, 2731, 0, + 0, 2831, 0, + 0, 2938, 0, + 0, 3050, 0, + 0, 3167, 0, + 0, 3287, 0, + 0, 3410, 0, + 0, 3535, 0, + 0, 3662, 0, + 0, 2139, 2433, + 0, 2139, 2432, + 0, 2140, 2432, + 0, 2141, 2431, + 0, 2142, 2430, + 0, 2144, 2428, + 0, 2146, 2426, + 0, 2149, 2424, + 0, 2152, 2420, + 0, 2158, 2416, + 0, 2164, 2410, + 0, 2173, 2401, + 0, 2185, 2389, + 0, 2200, 2373, + 0, 2219, 2351, + 0, 2244, 2319, + 0, 2274, 2273, + 0, 2313, 2203, + 0, 2360, 2088, + 0, 2415, 1866, + 0, 2481, 1036, + 0, 2555, 0, + 0, 2639, 0, + 0, 2732, 0, + 0, 2832, 0, + 0, 2938, 0, + 0, 3050, 0, + 0, 3167, 0, + 0, 3287, 0, + 0, 3410, 0, + 0, 3535, 0, + 0, 3662, 0, + 0, 2142, 2444, + 0, 2142, 2444, + 0, 2143, 2443, + 0, 2144, 2443, + 0, 2145, 2442, + 0, 2147, 2440, + 0, 2149, 2438, + 0, 2152, 2436, + 0, 2156, 2433, + 0, 2161, 2428, + 0, 2167, 2422, + 0, 2176, 2414, + 0, 2188, 2402, + 0, 2202, 2387, + 0, 2222, 2365, + 0, 2246, 2334, + 0, 2277, 2290, + 0, 2315, 2222, + 0, 2362, 2113, + 0, 2417, 1906, + 0, 2482, 1242, + 0, 2557, 0, + 0, 2640, 0, + 0, 2733, 0, + 0, 2833, 0, + 0, 2939, 0, + 0, 3051, 0, + 0, 3167, 0, + 0, 3287, 0, + 0, 3410, 0, + 0, 3535, 0, + 0, 3662, 0, + 0, 2146, 2460, + 0, 2146, 2460, + 0, 2147, 2459, + 0, 2148, 2458, + 0, 2149, 2457, + 0, 2151, 2456, + 0, 2153, 2454, + 0, 2156, 2452, + 0, 2160, 2448, + 0, 2165, 2444, + 0, 2171, 2438, + 0, 2180, 2430, + 0, 2191, 2419, + 0, 2206, 2404, + 0, 2225, 2383, + 0, 2249, 2354, + 0, 2280, 2311, + 0, 2318, 2247, + 0, 2364, 2144, + 0, 2419, 1955, + 0, 2484, 1422, + 0, 2558, 0, + 0, 2642, 0, + 0, 2734, 0, + 0, 2834, 0, + 0, 2940, 0, + 0, 3051, 0, + 0, 3168, 0, + 0, 3288, 0, + 0, 3410, 0, + 0, 3535, 0, + 0, 3662, 0, + 0, 2152, 2480, + 0, 2152, 2479, + 0, 2153, 2479, + 0, 2154, 2478, + 0, 2155, 2477, + 0, 2156, 2476, + 0, 2159, 2474, + 0, 2161, 2472, + 0, 2165, 2469, + 0, 2170, 2465, + 0, 2177, 2459, + 0, 2185, 2451, + 0, 2196, 2441, + 0, 2211, 2427, + 0, 2230, 2407, + 0, 2254, 2379, + 0, 2284, 2339, + 0, 2322, 2278, + 0, 2368, 2183, + 0, 2422, 2013, + 0, 2487, 1587, + 0, 2561, 0, + 0, 2644, 0, + 0, 2735, 0, + 0, 2835, 0, + 0, 2941, 0, + 0, 3052, 0, + 0, 3168, 0, + 0, 3288, 0, + 0, 3411, 0, + 0, 3536, 0, + 0, 3662, 0, + 590, 2159, 2505, + 556, 2159, 2505, + 505, 2160, 2504, + 427, 2161, 2503, + 295, 2162, 2503, + 26, 2164, 2501, + 0, 2166, 2500, + 0, 2169, 2498, + 0, 2172, 2495, + 0, 2177, 2491, + 0, 2184, 2485, + 0, 2192, 2478, + 0, 2203, 2468, + 0, 2218, 2455, + 0, 2236, 2436, + 0, 2260, 2410, + 0, 2290, 2373, + 0, 2327, 2317, + 0, 2372, 2230, + 0, 2427, 2080, + 0, 2490, 1742, + 0, 2564, 0, + 0, 2646, 0, + 0, 2737, 0, + 0, 2836, 0, + 0, 2942, 0, + 0, 3053, 0, + 0, 3169, 0, + 0, 3289, 0, + 0, 3411, 0, + 0, 3536, 0, + 0, 3662, 0, + 1656, 2169, 2537, + 1653, 2169, 2536, + 1649, 2170, 2536, + 1643, 2171, 2535, + 1635, 2172, 2534, + 1624, 2173, 2533, + 1610, 2175, 2532, + 1589, 2178, 2530, + 1560, 2182, 2527, + 1518, 2186, 2523, + 1454, 2193, 2518, + 1353, 2201, 2512, + 1168, 2212, 2503, + 661, 2226, 2490, + 0, 2244, 2473, + 0, 2268, 2449, + 0, 2297, 2415, + 0, 2334, 2364, + 0, 2378, 2287, + 0, 2432, 2157, + 0, 2495, 1891, + 0, 2568, 0, + 0, 2650, 0, + 0, 2740, 0, + 0, 2839, 0, + 0, 2944, 0, + 0, 3055, 0, + 0, 3170, 0, + 0, 3289, 0, + 0, 3412, 0, + 0, 3536, 0, + 0, 3663, 0, + 2017, 2181, 2576, + 2015, 2182, 2576, + 2013, 2182, 2575, + 2011, 2183, 2575, + 2007, 2184, 2574, + 2002, 2186, 2573, + 1996, 2188, 2571, + 1987, 2190, 2570, + 1975, 2194, 2567, + 1959, 2199, 2564, + 1936, 2205, 2559, + 1903, 2213, 2553, + 1856, 2223, 2545, + 1783, 2237, 2533, + 1663, 2255, 2518, + 1428, 2278, 2496, + 348, 2307, 2465, + 0, 2342, 2420, + 0, 2386, 2353, + 0, 2439, 2243, + 0, 2501, 2035, + 0, 2573, 1360, + 0, 2654, 0, + 0, 2744, 0, + 0, 2842, 0, + 0, 2946, 0, + 0, 3056, 0, + 0, 3172, 0, + 0, 3291, 0, + 0, 3413, 0, + 0, 3537, 0, + 0, 3663, 0, + 2266, 2198, 2624, + 2266, 2198, 2623, + 2264, 2199, 2623, + 2263, 2200, 2622, + 2261, 2201, 2622, + 2258, 2202, 2621, + 2255, 2204, 2620, + 2250, 2206, 2618, + 2243, 2210, 2616, + 2234, 2214, 2613, + 2222, 2220, 2609, + 2204, 2228, 2603, + 2180, 2238, 2596, + 2146, 2252, 2586, + 2096, 2269, 2572, + 2019, 2291, 2552, + 1890, 2319, 2525, + 1628, 2354, 2486, + 0, 2397, 2428, + 0, 2448, 2337, + 0, 2509, 2176, + 0, 2580, 1795, + 0, 2660, 0, + 0, 2749, 0, + 0, 2845, 0, + 0, 2949, 0, + 0, 3059, 0, + 0, 3173, 0, + 0, 3292, 0, + 0, 3414, 0, + 0, 3538, 0, + 0, 3664, 0, + 2470, 2219, 2680, + 2469, 2219, 2680, + 2469, 2220, 2680, + 2468, 2220, 2679, + 2466, 2221, 2679, + 2465, 2223, 2678, + 2462, 2225, 2677, + 2459, 2227, 2675, + 2455, 2230, 2673, + 2450, 2235, 2671, + 2442, 2240, 2667, + 2431, 2248, 2662, + 2417, 2258, 2656, + 2397, 2270, 2647, + 2369, 2287, 2635, + 2328, 2308, 2618, + 2267, 2335, 2595, + 2171, 2369, 2561, + 1998, 2410, 2513, + 1561, 2461, 2438, + 0, 2520, 2315, + 0, 2589, 2068, + 0, 2668, 582, + 0, 2755, 0, + 0, 2851, 0, + 0, 2953, 0, + 0, 3062, 0, + 0, 3176, 0, + 0, 3294, 0, + 0, 3415, 0, + 0, 3539, 0, + 0, 3665, 0, + 2649, 2245, 2747, + 2649, 2246, 2746, + 2648, 2246, 2746, + 2648, 2247, 2746, + 2647, 2248, 2745, + 2646, 2249, 2745, + 2644, 2251, 2744, + 2642, 2253, 2742, + 2639, 2256, 2741, + 2635, 2260, 2738, + 2630, 2266, 2735, + 2623, 2273, 2731, + 2614, 2282, 2726, + 2601, 2294, 2718, + 2583, 2310, 2708, + 2558, 2330, 2693, + 2523, 2356, 2674, + 2470, 2388, 2646, + 2389, 2428, 2606, + 2251, 2476, 2546, + 1960, 2534, 2451, + 0, 2601, 2283, + 0, 2678, 1867, + 0, 2763, 0, + 0, 2857, 0, + 0, 2959, 0, + 0, 3066, 0, + 0, 3179, 0, + 0, 3296, 0, + 0, 3417, 0, + 0, 3540, 0, + 0, 3666, 0, + 2813, 2279, 2823, + 2813, 2279, 2822, + 2813, 2280, 2822, + 2812, 2280, 2822, + 2812, 2281, 2821, + 2811, 2282, 2821, + 2810, 2284, 2820, + 2808, 2286, 2819, + 2806, 2289, 2817, + 2804, 2293, 2816, + 2800, 2298, 2813, + 2796, 2304, 2809, + 2789, 2313, 2805, + 2780, 2324, 2798, + 2769, 2339, 2790, + 2752, 2358, 2778, + 2729, 2382, 2762, + 2697, 2413, 2739, + 2649, 2451, 2706, + 2576, 2497, 2659, + 2457, 2552, 2587, + 2222, 2617, 2468, + 1159, 2691, 2237, + 0, 2774, 1246, + 0, 2866, 0, + 0, 2966, 0, + 0, 3072, 0, + 0, 3184, 0, + 0, 3300, 0, + 0, 3420, 0, + 0, 3542, 0, + 0, 3667, 0, + 2968, 2320, 2907, + 2968, 2320, 2907, + 2968, 2321, 2907, + 2967, 2321, 2907, + 2967, 2322, 2906, + 2966, 2323, 2906, + 2966, 2325, 2905, + 2965, 2327, 2904, + 2963, 2329, 2903, + 2961, 2333, 2902, + 2959, 2337, 2900, + 2956, 2343, 2897, + 2951, 2351, 2893, + 2945, 2362, 2888, + 2937, 2375, 2880, + 2925, 2393, 2871, + 2910, 2415, 2857, + 2888, 2444, 2839, + 2858, 2479, 2813, + 2813, 2523, 2776, + 2746, 2575, 2722, + 2637, 2637, 2637, + 2432, 2708, 2490, + 1780, 2789, 2168, + 0, 2878, 0, + 0, 2975, 0, + 0, 3079, 0, + 0, 3190, 0, + 0, 3304, 0, + 0, 3423, 0, + 0, 3545, 0, + 0, 3669, 0, + 3116, 2370, 3001, + 3116, 2370, 3001, + 3116, 2370, 3001, + 3116, 2371, 3000, + 3116, 2372, 3000, + 3115, 2373, 3000, + 3115, 2374, 2999, + 3114, 2376, 2998, + 3113, 2378, 2997, + 3112, 2381, 2996, + 3110, 2385, 2994, + 3107, 2391, 2992, + 3104, 2398, 2989, + 3100, 2407, 2985, + 3094, 2420, 2979, + 3086, 2436, 2971, + 3075, 2456, 2961, + 3060, 2482, 2946, + 3039, 2515, 2926, + 3010, 2555, 2897, + 2968, 2604, 2856, + 2904, 2662, 2794, + 2802, 2730, 2696, + 2614, 2807, 2518, + 2094, 2893, 2054, + 0, 2987, 0, + 0, 3089, 0, + 0, 3197, 0, + 0, 3310, 0, + 0, 3428, 0, + 0, 3549, 0, + 0, 3672, 0, + 3260, 2429, 3102, + 3260, 2429, 3102, + 3260, 2429, 3101, + 3260, 2430, 3101, + 3260, 2430, 3101, + 3259, 2431, 3101, + 3259, 2432, 3100, + 3258, 2434, 3100, + 3258, 2436, 3099, + 3257, 2439, 3098, + 3255, 2442, 3096, + 3254, 2447, 3095, + 3251, 2453, 3092, + 3248, 2462, 3089, + 3244, 2473, 3084, + 3238, 2487, 3078, + 3231, 2505, 3070, + 3220, 2529, 3058, + 3206, 2558, 3042, + 3185, 2595, 3021, + 3157, 2640, 2989, + 3116, 2694, 2944, + 3054, 2757, 2876, + 2957, 2830, 2764, + 2781, 2913, 2552, + 2327, 3003, 1837, + 0, 3102, 0, + 0, 3207, 0, + 0, 3318, 0, + 0, 3434, 0, + 0, 3553, 0, + 0, 3676, 0, + 3401, 2497, 3209, + 3401, 2497, 3209, + 3401, 2498, 3209, + 3401, 2498, 3208, + 3401, 2499, 3208, + 3400, 2499, 3208, + 3400, 2500, 3208, + 3400, 2502, 3207, + 3399, 2503, 3207, + 3398, 2506, 3206, + 3397, 2509, 3205, + 3396, 2513, 3203, + 3394, 2519, 3201, + 3392, 2526, 3199, + 3389, 2535, 3195, + 3385, 2548, 3190, + 3379, 2564, 3184, + 3372, 2585, 3175, + 3361, 2611, 3163, + 3347, 2644, 3146, + 3328, 2684, 3123, + 3300, 2734, 3089, + 3260, 2792, 3040, + 3200, 2860, 2966, + 3105, 2937, 2842, + 2937, 3024, 2595, + 2521, 3118, 1060, + 0, 3220, 0, + 0, 3329, 0, + 0, 3442, 0, + 0, 3560, 0, + 0, 3680, 0, + 3539, 2575, 3321, + 3539, 2575, 3321, + 3539, 2576, 3321, + 3539, 2576, 3321, + 3539, 2576, 3321, + 3539, 2577, 3321, + 3539, 2578, 3320, + 3538, 2579, 3320, + 3538, 2581, 3320, + 3537, 2582, 3319, + 3537, 2585, 3318, + 3536, 2589, 3317, + 3535, 2593, 3315, + 3533, 2599, 3313, + 3531, 2608, 3311, + 3528, 2618, 3307, + 3524, 2632, 3302, + 3518, 2650, 3295, + 3511, 2673, 3286, + 3500, 2702, 3273, + 3486, 2738, 3255, + 3467, 2782, 3231, + 3440, 2834, 3196, + 3400, 2897, 3144, + 3342, 2969, 3064, + 3249, 3050, 2929, + 3086, 3140, 2646, + 2695, 3237, 0, + 0, 3342, 0, + 0, 3452, 0, + 0, 3568, 0, + 0, 3687, 0, + 3676, 2662, 3438, + 3676, 2662, 3438, + 3676, 2663, 3438, + 3676, 2663, 3438, + 3676, 2663, 3438, + 3676, 2664, 3438, + 3676, 2664, 3438, + 3675, 2665, 3437, + 3675, 2667, 3437, + 3675, 2668, 3436, + 3674, 2670, 3436, + 3674, 2673, 3435, + 3673, 2677, 3434, + 3671, 2682, 3432, + 3670, 2689, 3430, + 3668, 2698, 3427, + 3665, 2710, 3423, + 3661, 2725, 3418, + 3655, 2744, 3411, + 3648, 2769, 3401, + 3638, 2800, 3388, + 3624, 2839, 3370, + 3605, 2886, 3344, + 3578, 2942, 3308, + 3539, 3007, 3253, + 3481, 3082, 3169, + 3390, 3167, 3024, + 3231, 3259, 2706, + 2856, 3359, 0, + 0, 3466, 0, + 0, 3578, 0, + 0, 3695, 0, + 3812, 2757, 3559, + 3812, 2757, 3559, + 3812, 2758, 3559, + 3812, 2758, 3558, + 3812, 2758, 3558, + 3811, 2759, 3558, + 3811, 2759, 3558, + 3811, 2760, 3558, + 3811, 2761, 3558, + 3811, 2762, 3557, + 3810, 2764, 3557, + 3810, 2766, 3556, + 3809, 2770, 3555, + 3808, 2774, 3554, + 3807, 2779, 3552, + 3805, 2787, 3550, + 3803, 2796, 3547, + 3800, 2809, 3543, + 3796, 2825, 3538, + 3791, 2846, 3531, + 3783, 2872, 3521, + 3773, 2905, 3507, + 3760, 2946, 3488, + 3741, 2996, 3462, + 3714, 3054, 3424, + 3675, 3122, 3368, + 3618, 3200, 3279, + 3529, 3287, 3126, + 3372, 3382, 2777, + 3009, 3484, 0, + 0, 3592, 0, + 0, 3706, 0, + 3946, 2860, 3682, + 3946, 2860, 3682, + 3946, 2860, 3682, + 3946, 2860, 3682, + 3946, 2860, 3682, + 3946, 2861, 3682, + 3946, 2861, 3681, + 3946, 2862, 3681, + 3946, 2863, 3681, + 3946, 2864, 3681, + 3945, 2865, 3680, + 3945, 2867, 3680, + 3944, 2869, 3679, + 3944, 2873, 3678, + 3943, 2877, 3677, + 3942, 2883, 3675, + 3940, 2891, 3673, + 3938, 2901, 3670, + 3935, 2914, 3666, + 3931, 2932, 3661, + 3926, 2954, 3653, + 3918, 2981, 3643, + 3908, 3016, 3629, + 3895, 3059, 3610, + 3876, 3110, 3583, + 3849, 3171, 3544, + 3811, 3242, 3486, + 3754, 3321, 3395, + 3666, 3410, 3235, + 3511, 3507, 2856, + 3156, 3610, 0, + 0, 3720, 0, + 4080, 2968, 3807, + 4080, 2968, 3807, + 4080, 2968, 3807, + 4080, 2969, 3807, + 4080, 2969, 3807, + 4080, 2969, 3807, + 4080, 2969, 3807, + 4080, 2970, 3807, + 4080, 2970, 3806, + 4080, 2971, 3806, + 4080, 2972, 3806, + 4079, 2974, 3806, + 4079, 2976, 3805, + 4078, 2979, 3804, + 4078, 2982, 3803, + 4077, 2987, 3802, + 4076, 2993, 3800, + 4074, 3001, 3798, + 4072, 3012, 3795, + 4069, 3026, 3791, + 4065, 3044, 3786, + 4060, 3067, 3778, + 4052, 3096, 3768, + 4042, 3132, 3754, + 4029, 3176, 3734, + 4010, 3229, 3706, + 3984, 3292, 3667, + 3946, 3364, 3608, + 3889, 3445, 3514, + 3801, 3535, 3348, + 3648, 3633, 2944, + 3299, 3738, 0, + 4095, 3082, 3934, + 4095, 3082, 3934, + 4095, 3082, 3934, + 4095, 3082, 3934, + 4095, 3082, 3934, + 4095, 3082, 3934, + 4095, 3083, 3934, + 4095, 3083, 3934, + 4095, 3084, 3934, + 4095, 3084, 3933, + 4095, 3085, 3933, + 4095, 3086, 3933, + 4095, 3088, 3932, + 4095, 3090, 3932, + 4095, 3093, 3931, + 4095, 3096, 3930, + 4095, 3101, 3929, + 4095, 3108, 3927, + 4095, 3116, 3925, + 4095, 3127, 3922, + 4095, 3142, 3918, + 4095, 3160, 3912, + 4095, 3184, 3905, + 4095, 3214, 3894, + 4095, 3251, 3880, + 4095, 3297, 3860, + 4095, 3351, 3832, + 4095, 3415, 3792, + 4080, 3488, 3732, + 4024, 3571, 3636, + 3936, 3662, 3466, + 3784, 3761, 3041, + 4095, 3200, 4062, + 4095, 3200, 4062, + 4095, 3200, 4062, + 4095, 3200, 4062, + 4095, 3200, 4062, + 4095, 3200, 4062, + 4095, 3200, 4062, + 4095, 3201, 4062, + 4095, 3201, 4062, + 4095, 3202, 4062, + 4095, 3202, 4062, + 4095, 3203, 4061, + 4095, 3204, 4061, + 4095, 3206, 4061, + 4095, 3208, 4060, + 4095, 3211, 4059, + 4095, 3215, 4058, + 4095, 3220, 4057, + 4095, 3226, 4055, + 4095, 3235, 4053, + 4095, 3247, 4050, + 4095, 3261, 4046, + 4095, 3280, 4040, + 4095, 3305, 4032, + 4095, 3335, 4022, + 4095, 3374, 4008, + 4095, 3420, 3988, + 4095, 3475, 3959, + 4095, 3540, 3918, + 4095, 3614, 3858, + 4095, 3698, 3761, + 4070, 3790, 3587, + 0, 2261, 2529, + 0, 2261, 2529, + 0, 2262, 2529, + 0, 2263, 2528, + 0, 2264, 2527, + 0, 2265, 2526, + 0, 2267, 2524, + 0, 2269, 2522, + 0, 2272, 2520, + 0, 2276, 2516, + 0, 2281, 2511, + 0, 2288, 2504, + 0, 2297, 2495, + 0, 2308, 2482, + 0, 2324, 2465, + 0, 2343, 2440, + 0, 2368, 2405, + 0, 2400, 2354, + 0, 2439, 2274, + 0, 2486, 2140, + 0, 2542, 1860, + 0, 2608, 0, + 0, 2684, 0, + 0, 2768, 0, + 0, 2861, 0, + 0, 2962, 0, + 0, 3069, 0, + 0, 3181, 0, + 0, 3298, 0, + 0, 3418, 0, + 0, 3541, 0, + 0, 3667, 0, + 0, 2261, 2530, + 0, 2262, 2530, + 0, 2262, 2529, + 0, 2263, 2529, + 0, 2264, 2528, + 0, 2265, 2527, + 0, 2267, 2525, + 0, 2269, 2523, + 0, 2272, 2520, + 0, 2276, 2517, + 0, 2281, 2512, + 0, 2288, 2505, + 0, 2297, 2495, + 0, 2309, 2483, + 0, 2324, 2465, + 0, 2343, 2441, + 0, 2368, 2406, + 0, 2400, 2354, + 0, 2439, 2275, + 0, 2486, 2141, + 0, 2543, 1863, + 0, 2608, 0, + 0, 2684, 0, + 0, 2769, 0, + 0, 2862, 0, + 0, 2962, 0, + 0, 3069, 0, + 0, 3181, 0, + 0, 3298, 0, + 0, 3418, 0, + 0, 3541, 0, + 0, 3667, 0, + 0, 2261, 2531, + 0, 2262, 2530, + 0, 2262, 2530, + 0, 2263, 2529, + 0, 2264, 2528, + 0, 2265, 2527, + 0, 2267, 2526, + 0, 2269, 2524, + 0, 2272, 2521, + 0, 2276, 2517, + 0, 2281, 2512, + 0, 2288, 2505, + 0, 2297, 2496, + 0, 2309, 2484, + 0, 2324, 2466, + 0, 2344, 2442, + 0, 2369, 2407, + 0, 2400, 2355, + 0, 2439, 2276, + 0, 2486, 2143, + 0, 2543, 1866, + 0, 2609, 0, + 0, 2684, 0, + 0, 2769, 0, + 0, 2862, 0, + 0, 2962, 0, + 0, 3069, 0, + 0, 3181, 0, + 0, 3298, 0, + 0, 3418, 0, + 0, 3541, 0, + 0, 3667, 0, + 0, 2262, 2532, + 0, 2262, 2531, + 0, 2263, 2531, + 0, 2263, 2530, + 0, 2264, 2529, + 0, 2265, 2528, + 0, 2267, 2527, + 0, 2269, 2525, + 0, 2272, 2522, + 0, 2276, 2518, + 0, 2281, 2513, + 0, 2288, 2506, + 0, 2297, 2497, + 0, 2309, 2485, + 0, 2324, 2467, + 0, 2344, 2443, + 0, 2369, 2408, + 0, 2400, 2357, + 0, 2439, 2278, + 0, 2486, 2145, + 0, 2543, 1870, + 0, 2609, 0, + 0, 2684, 0, + 0, 2769, 0, + 0, 2862, 0, + 0, 2962, 0, + 0, 3069, 0, + 0, 3181, 0, + 0, 3298, 0, + 0, 3418, 0, + 0, 3541, 0, + 0, 3667, 0, + 0, 2262, 2533, + 0, 2262, 2533, + 0, 2263, 2532, + 0, 2264, 2531, + 0, 2264, 2531, + 0, 2266, 2529, + 0, 2267, 2528, + 0, 2270, 2526, + 0, 2273, 2523, + 0, 2276, 2520, + 0, 2282, 2515, + 0, 2288, 2508, + 0, 2297, 2499, + 0, 2309, 2486, + 0, 2324, 2469, + 0, 2344, 2444, + 0, 2369, 2410, + 0, 2400, 2359, + 0, 2439, 2280, + 0, 2487, 2148, + 0, 2543, 1875, + 0, 2609, 0, + 0, 2684, 0, + 0, 2769, 0, + 0, 2862, 0, + 0, 2962, 0, + 0, 3069, 0, + 0, 3181, 0, + 0, 3298, 0, + 0, 3418, 0, + 0, 3541, 0, + 0, 3667, 0, + 0, 2262, 2535, + 0, 2263, 2534, + 0, 2263, 2534, + 0, 2264, 2533, + 0, 2265, 2532, + 0, 2266, 2531, + 0, 2268, 2530, + 0, 2270, 2528, + 0, 2273, 2525, + 0, 2277, 2521, + 0, 2282, 2516, + 0, 2289, 2510, + 0, 2298, 2500, + 0, 2310, 2488, + 0, 2325, 2471, + 0, 2344, 2446, + 0, 2369, 2412, + 0, 2401, 2361, + 0, 2440, 2283, + 0, 2487, 2152, + 0, 2543, 1882, + 0, 2609, 0, + 0, 2684, 0, + 0, 2769, 0, + 0, 2862, 0, + 0, 2962, 0, + 0, 3069, 0, + 0, 3181, 0, + 0, 3298, 0, + 0, 3418, 0, + 0, 3541, 0, + 0, 3667, 0, + 0, 2263, 2537, + 0, 2263, 2537, + 0, 2264, 2536, + 0, 2265, 2535, + 0, 2265, 2535, + 0, 2267, 2533, + 0, 2268, 2532, + 0, 2271, 2530, + 0, 2274, 2527, + 0, 2277, 2524, + 0, 2283, 2519, + 0, 2289, 2512, + 0, 2298, 2503, + 0, 2310, 2490, + 0, 2325, 2473, + 0, 2345, 2449, + 0, 2370, 2415, + 0, 2401, 2364, + 0, 2440, 2287, + 0, 2487, 2157, + 0, 2543, 1892, + 0, 2609, 0, + 0, 2685, 0, + 0, 2769, 0, + 0, 2862, 0, + 0, 2962, 0, + 0, 3069, 0, + 0, 3182, 0, + 0, 3298, 0, + 0, 3418, 0, + 0, 3542, 0, + 0, 3667, 0, + 0, 2264, 2540, + 0, 2264, 2539, + 0, 2265, 2539, + 0, 2265, 2538, + 0, 2266, 2538, + 0, 2267, 2536, + 0, 2269, 2535, + 0, 2271, 2533, + 0, 2274, 2530, + 0, 2278, 2527, + 0, 2283, 2522, + 0, 2290, 2515, + 0, 2299, 2506, + 0, 2311, 2494, + 0, 2326, 2477, + 0, 2346, 2453, + 0, 2370, 2419, + 0, 2402, 2369, + 0, 2440, 2292, + 0, 2488, 2164, + 0, 2544, 1904, + 0, 2610, 0, + 0, 2685, 0, + 0, 2769, 0, + 0, 2862, 0, + 0, 2963, 0, + 0, 3069, 0, + 0, 3182, 0, + 0, 3298, 0, + 0, 3419, 0, + 0, 3542, 0, + 0, 3667, 0, + 0, 2265, 2544, + 0, 2265, 2543, + 0, 2266, 2543, + 0, 2266, 2542, + 0, 2267, 2542, + 0, 2268, 2540, + 0, 2270, 2539, + 0, 2272, 2537, + 0, 2275, 2534, + 0, 2279, 2531, + 0, 2284, 2526, + 0, 2291, 2519, + 0, 2300, 2510, + 0, 2312, 2498, + 0, 2327, 2481, + 0, 2346, 2458, + 0, 2371, 2424, + 0, 2402, 2375, + 0, 2441, 2299, + 0, 2488, 2173, + 0, 2544, 1920, + 0, 2610, 0, + 0, 2685, 0, + 0, 2770, 0, + 0, 2862, 0, + 0, 2963, 0, + 0, 3070, 0, + 0, 3182, 0, + 0, 3298, 0, + 0, 3419, 0, + 0, 3542, 0, + 0, 3667, 0, + 0, 2266, 2549, + 0, 2266, 2549, + 0, 2267, 2548, + 0, 2268, 2548, + 0, 2269, 2547, + 0, 2270, 2546, + 0, 2271, 2544, + 0, 2274, 2542, + 0, 2277, 2540, + 0, 2280, 2536, + 0, 2286, 2531, + 0, 2292, 2525, + 0, 2301, 2516, + 0, 2313, 2504, + 0, 2328, 2487, + 0, 2348, 2464, + 0, 2372, 2431, + 0, 2403, 2382, + 0, 2442, 2308, + 0, 2489, 2185, + 0, 2545, 1940, + 0, 2611, 542, + 0, 2686, 0, + 0, 2770, 0, + 0, 2863, 0, + 0, 2963, 0, + 0, 3070, 0, + 0, 3182, 0, + 0, 3299, 0, + 0, 3419, 0, + 0, 3542, 0, + 0, 3667, 0, + 0, 2268, 2556, + 0, 2268, 2556, + 0, 2269, 2555, + 0, 2269, 2555, + 0, 2270, 2554, + 0, 2272, 2553, + 0, 2273, 2551, + 0, 2275, 2549, + 0, 2278, 2547, + 0, 2282, 2543, + 0, 2287, 2538, + 0, 2294, 2532, + 0, 2303, 2523, + 0, 2315, 2512, + 0, 2330, 2495, + 0, 2349, 2472, + 0, 2374, 2440, + 0, 2405, 2392, + 0, 2443, 2320, + 0, 2490, 2200, + 0, 2546, 1966, + 0, 2612, 914, + 0, 2687, 0, + 0, 2771, 0, + 0, 2863, 0, + 0, 2963, 0, + 0, 3070, 0, + 0, 3182, 0, + 0, 3299, 0, + 0, 3419, 0, + 0, 3542, 0, + 0, 3667, 0, + 0, 2270, 2565, + 0, 2271, 2565, + 0, 2271, 2564, + 0, 2272, 2564, + 0, 2273, 2563, + 0, 2274, 2562, + 0, 2276, 2560, + 0, 2278, 2559, + 0, 2281, 2556, + 0, 2285, 2553, + 0, 2290, 2548, + 0, 2296, 2542, + 0, 2305, 2533, + 0, 2317, 2522, + 0, 2332, 2505, + 0, 2351, 2483, + 0, 2376, 2451, + 0, 2407, 2405, + 0, 2445, 2335, + 0, 2492, 2220, + 0, 2547, 1998, + 0, 2613, 1168, + 0, 2688, 0, + 0, 2772, 0, + 0, 2864, 0, + 0, 2964, 0, + 0, 3071, 0, + 0, 3183, 0, + 0, 3299, 0, + 0, 3419, 0, + 0, 3542, 0, + 0, 3667, 0, + 0, 2273, 2577, + 0, 2274, 2577, + 0, 2274, 2576, + 0, 2275, 2576, + 0, 2276, 2575, + 0, 2277, 2574, + 0, 2279, 2572, + 0, 2281, 2571, + 0, 2284, 2568, + 0, 2288, 2565, + 0, 2293, 2560, + 0, 2299, 2554, + 0, 2308, 2546, + 0, 2320, 2535, + 0, 2335, 2519, + 0, 2354, 2497, + 0, 2378, 2467, + 0, 2409, 2422, + 0, 2447, 2354, + 0, 2494, 2245, + 0, 2549, 2038, + 0, 2614, 1374, + 0, 2689, 0, + 0, 2773, 0, + 0, 2865, 0, + 0, 2965, 0, + 0, 3071, 0, + 0, 3183, 0, + 0, 3299, 0, + 0, 3419, 0, + 0, 3542, 0, + 0, 3667, 0, + 0, 2278, 2592, + 0, 2278, 2592, + 0, 2279, 2592, + 0, 2279, 2591, + 0, 2280, 2590, + 0, 2281, 2589, + 0, 2283, 2588, + 0, 2285, 2586, + 0, 2288, 2584, + 0, 2292, 2581, + 0, 2297, 2576, + 0, 2303, 2570, + 0, 2312, 2562, + 0, 2323, 2551, + 0, 2338, 2536, + 0, 2357, 2516, + 0, 2382, 2486, + 0, 2412, 2443, + 0, 2450, 2379, + 0, 2496, 2276, + 0, 2551, 2087, + 0, 2616, 1554, + 0, 2690, 0, + 0, 2774, 0, + 0, 2866, 0, + 0, 2966, 0, + 0, 3072, 0, + 0, 3184, 0, + 0, 3300, 0, + 0, 3420, 0, + 0, 3542, 0, + 0, 3667, 0, + 0, 2283, 2612, + 0, 2284, 2612, + 0, 2284, 2611, + 0, 2285, 2611, + 0, 2286, 2610, + 0, 2287, 2609, + 0, 2289, 2608, + 0, 2291, 2606, + 0, 2293, 2604, + 0, 2297, 2601, + 0, 2302, 2597, + 0, 2309, 2591, + 0, 2317, 2584, + 0, 2329, 2573, + 0, 2343, 2559, + 0, 2362, 2539, + 0, 2386, 2511, + 0, 2416, 2471, + 0, 2454, 2410, + 0, 2500, 2315, + 0, 2555, 2145, + 0, 2619, 1719, + 0, 2693, 0, + 0, 2776, 0, + 0, 2868, 0, + 0, 2967, 0, + 0, 3073, 0, + 0, 3184, 0, + 0, 3300, 0, + 0, 3420, 0, + 0, 3543, 0, + 0, 3668, 0, + 746, 2291, 2637, + 722, 2291, 2637, + 688, 2292, 2637, + 637, 2292, 2636, + 559, 2293, 2636, + 428, 2294, 2635, + 158, 2296, 2633, + 0, 2298, 2632, + 0, 2301, 2630, + 0, 2304, 2627, + 0, 2309, 2623, + 0, 2316, 2618, + 0, 2324, 2610, + 0, 2335, 2601, + 0, 2350, 2587, + 0, 2368, 2568, + 0, 2392, 2542, + 0, 2422, 2505, + 0, 2459, 2449, + 0, 2504, 2362, + 0, 2559, 2212, + 0, 2622, 1874, + 0, 2696, 0, + 0, 2778, 0, + 0, 2870, 0, + 0, 2969, 0, + 0, 3074, 0, + 0, 3185, 0, + 0, 3301, 0, + 0, 3421, 0, + 0, 3543, 0, + 0, 3668, 0, + 1791, 2300, 2669, + 1789, 2301, 2669, + 1785, 2301, 2668, + 1781, 2302, 2668, + 1775, 2303, 2667, + 1767, 2304, 2667, + 1757, 2305, 2665, + 1742, 2307, 2664, + 1721, 2310, 2662, + 1692, 2314, 2659, + 1650, 2319, 2656, + 1586, 2325, 2651, + 1485, 2333, 2644, + 1300, 2344, 2635, + 793, 2358, 2622, + 0, 2376, 2605, + 0, 2400, 2581, + 0, 2429, 2547, + 0, 2466, 2496, + 0, 2510, 2419, + 0, 2564, 2289, + 0, 2627, 2023, + 0, 2700, 0, + 0, 2782, 0, + 0, 2872, 0, + 0, 2971, 0, + 0, 3076, 0, + 0, 3187, 0, + 0, 3302, 0, + 0, 3422, 0, + 0, 3544, 0, + 0, 3668, 0, + 2150, 2313, 2708, + 2149, 2313, 2708, + 2147, 2314, 2708, + 2145, 2314, 2707, + 2143, 2315, 2707, + 2139, 2316, 2706, + 2135, 2318, 2705, + 2128, 2320, 2704, + 2119, 2323, 2702, + 2108, 2326, 2699, + 2091, 2331, 2696, + 2068, 2337, 2691, + 2036, 2345, 2685, + 1988, 2356, 2677, + 1915, 2369, 2666, + 1795, 2387, 2650, + 1560, 2410, 2628, + 480, 2439, 2597, + 0, 2474, 2553, + 0, 2518, 2485, + 0, 2571, 2375, + 0, 2633, 2167, + 0, 2705, 1492, + 0, 2786, 0, + 0, 2876, 0, + 0, 2974, 0, + 0, 3078, 0, + 0, 3189, 0, + 0, 3304, 0, + 0, 3423, 0, + 0, 3545, 0, + 0, 3669, 0, + 2399, 2329, 2756, + 2398, 2330, 2756, + 2398, 2330, 2755, + 2396, 2331, 2755, + 2395, 2332, 2754, + 2393, 2333, 2754, + 2390, 2334, 2753, + 2387, 2336, 2752, + 2382, 2339, 2750, + 2375, 2342, 2748, + 2366, 2346, 2745, + 2354, 2352, 2741, + 2337, 2360, 2735, + 2313, 2370, 2728, + 2278, 2384, 2718, + 2228, 2401, 2704, + 2151, 2423, 2684, + 2023, 2451, 2657, + 1760, 2486, 2618, + 0, 2529, 2560, + 0, 2581, 2469, + 0, 2642, 2308, + 0, 2712, 1927, + 0, 2792, 0, + 0, 2881, 0, + 0, 2978, 0, + 0, 3081, 0, + 0, 3191, 0, + 0, 3306, 0, + 0, 3424, 0, + 0, 3546, 0, + 0, 3670, 0, + 2602, 2350, 2813, + 2602, 2351, 2812, + 2602, 2351, 2812, + 2601, 2352, 2812, + 2600, 2353, 2811, + 2599, 2354, 2811, + 2597, 2355, 2810, + 2595, 2357, 2809, + 2591, 2359, 2807, + 2587, 2362, 2805, + 2582, 2367, 2803, + 2574, 2372, 2799, + 2563, 2380, 2794, + 2549, 2390, 2788, + 2529, 2402, 2779, + 2501, 2419, 2767, + 2460, 2440, 2750, + 2400, 2467, 2727, + 2303, 2501, 2694, + 2131, 2543, 2645, + 1693, 2593, 2570, + 0, 2652, 2447, + 0, 2721, 2200, + 0, 2800, 714, + 0, 2887, 0, + 0, 2983, 0, + 0, 3085, 0, + 0, 3194, 0, + 0, 3308, 0, + 0, 3426, 0, + 0, 3547, 0, + 0, 3671, 0, + 2781, 2377, 2879, + 2781, 2377, 2879, + 2781, 2378, 2879, + 2780, 2378, 2878, + 2780, 2379, 2878, + 2779, 2380, 2877, + 2778, 2381, 2877, + 2776, 2383, 2876, + 2774, 2385, 2874, + 2771, 2388, 2873, + 2767, 2392, 2870, + 2762, 2398, 2867, + 2755, 2405, 2863, + 2746, 2414, 2858, + 2733, 2426, 2850, + 2715, 2442, 2840, + 2691, 2462, 2826, + 2655, 2488, 2806, + 2602, 2520, 2778, + 2521, 2560, 2738, + 2384, 2609, 2678, + 2092, 2666, 2584, + 0, 2733, 2415, + 0, 2810, 1999, + 0, 2895, 0, + 0, 2989, 0, + 0, 3091, 0, + 0, 3198, 0, + 0, 3311, 0, + 0, 3429, 0, + 0, 3549, 0, + 0, 3673, 0, + 2946, 2411, 2955, + 2945, 2411, 2955, + 2945, 2411, 2954, + 2945, 2412, 2954, + 2944, 2412, 2954, + 2944, 2413, 2953, + 2943, 2414, 2953, + 2942, 2416, 2952, + 2940, 2418, 2951, + 2939, 2421, 2950, + 2936, 2425, 2948, + 2932, 2430, 2945, + 2928, 2436, 2942, + 2921, 2445, 2937, + 2913, 2456, 2930, + 2901, 2471, 2922, + 2884, 2490, 2910, + 2861, 2514, 2894, + 2829, 2545, 2871, + 2781, 2583, 2838, + 2709, 2629, 2791, + 2589, 2684, 2719, + 2354, 2749, 2601, + 1291, 2823, 2369, + 0, 2906, 1378, + 0, 2998, 0, + 0, 3098, 0, + 0, 3204, 0, + 0, 3316, 0, + 0, 3432, 0, + 0, 3552, 0, + 0, 3675, 0, + 3100, 2452, 3040, + 3100, 2452, 3040, + 3100, 2452, 3039, + 3100, 2453, 3039, + 3099, 2453, 3039, + 3099, 2454, 3039, + 3098, 2455, 3038, + 3098, 2457, 3037, + 3097, 2459, 3037, + 3095, 2461, 3035, + 3093, 2465, 3034, + 3091, 2469, 3032, + 3088, 2475, 3029, + 3083, 2483, 3025, + 3077, 2494, 3020, + 3069, 2507, 3013, + 3058, 2525, 3003, + 3042, 2547, 2990, + 3020, 2576, 2971, + 2990, 2611, 2945, + 2945, 2655, 2909, + 2878, 2707, 2854, + 2769, 2769, 2769, + 2564, 2840, 2622, + 1912, 2921, 2300, + 0, 3010, 0, + 0, 3107, 0, + 0, 3212, 0, + 0, 3322, 0, + 0, 3437, 0, + 0, 3555, 0, + 0, 3677, 0, + 3249, 2501, 3133, + 3248, 2502, 3133, + 3248, 2502, 3133, + 3248, 2502, 3133, + 3248, 2503, 3132, + 3248, 2504, 3132, + 3247, 2505, 3132, + 3247, 2506, 3131, + 3246, 2508, 3130, + 3245, 2510, 3129, + 3244, 2513, 3128, + 3242, 2517, 3126, + 3239, 2523, 3124, + 3236, 2530, 3121, + 3232, 2539, 3117, + 3226, 2552, 3111, + 3218, 2568, 3103, + 3207, 2588, 3093, + 3192, 2614, 3078, + 3172, 2647, 3058, + 3142, 2687, 3029, + 3100, 2736, 2988, + 3036, 2794, 2926, + 2934, 2862, 2828, + 2746, 2939, 2650, + 2226, 3025, 2186, + 0, 3120, 0, + 0, 3221, 0, + 0, 3329, 0, + 0, 3443, 0, + 0, 3560, 0, + 0, 3681, 0, + 3392, 2560, 3234, + 3392, 2561, 3234, + 3392, 2561, 3234, + 3392, 2561, 3233, + 3392, 2562, 3233, + 3392, 2562, 3233, + 3391, 2563, 3233, + 3391, 2564, 3232, + 3391, 2566, 3232, + 3390, 2568, 3231, + 3389, 2571, 3230, + 3388, 2574, 3229, + 3386, 2579, 3227, + 3383, 2586, 3224, + 3380, 2594, 3221, + 3376, 2605, 3216, + 3370, 2619, 3210, + 3363, 2637, 3202, + 3352, 2661, 3190, + 3338, 2691, 3175, + 3317, 2727, 3153, + 3289, 2772, 3121, + 3248, 2826, 3076, + 3187, 2890, 3008, + 3089, 2962, 2896, + 2913, 3045, 2685, + 2459, 3135, 1969, + 0, 3234, 0, + 0, 3339, 0, + 0, 3450, 0, + 0, 3566, 0, + 0, 3685, 0, + 3533, 2629, 3341, + 3533, 2629, 3341, + 3533, 2629, 3341, + 3533, 2630, 3341, + 3533, 2630, 3341, + 3533, 2631, 3340, + 3532, 2631, 3340, + 3532, 2632, 3340, + 3532, 2634, 3339, + 3531, 2636, 3339, + 3530, 2638, 3338, + 3530, 2641, 3337, + 3528, 2645, 3335, + 3527, 2651, 3333, + 3524, 2658, 3331, + 3521, 2668, 3327, + 3517, 2680, 3322, + 3512, 2696, 3316, + 3504, 2717, 3307, + 3494, 2743, 3295, + 3479, 2776, 3278, + 3460, 2817, 3255, + 3432, 2866, 3221, + 3392, 2924, 3173, + 3332, 2992, 3098, + 3237, 3069, 2974, + 3069, 3156, 2727, + 2654, 3251, 1192, + 0, 3353, 0, + 0, 3461, 0, + 0, 3574, 0, + 0, 3692, 0, + 3672, 2707, 3453, + 3672, 2707, 3453, + 3671, 2707, 3453, + 3671, 2708, 3453, + 3671, 2708, 3453, + 3671, 2709, 3453, + 3671, 2709, 3453, + 3671, 2710, 3453, + 3671, 2711, 3452, + 3670, 2713, 3452, + 3670, 2715, 3451, + 3669, 2717, 3450, + 3668, 2721, 3449, + 3667, 2725, 3448, + 3665, 2732, 3446, + 3663, 2740, 3443, + 3660, 2750, 3439, + 3656, 2764, 3434, + 3650, 2782, 3427, + 3643, 2805, 3418, + 3633, 2834, 3405, + 3619, 2870, 3388, + 3599, 2914, 3363, + 3572, 2967, 3328, + 3532, 3029, 3276, + 3474, 3101, 3196, + 3382, 3182, 3061, + 3218, 3272, 2778, + 2827, 3370, 0, + 0, 3474, 0, + 0, 3585, 0, + 0, 3700, 0, + 3808, 2794, 3570, + 3808, 2794, 3570, + 3808, 2794, 3570, + 3808, 2795, 3570, + 3808, 2795, 3570, + 3808, 2795, 3570, + 3808, 2796, 3570, + 3808, 2796, 3570, + 3808, 2797, 3569, + 3807, 2799, 3569, + 3807, 2800, 3569, + 3806, 2803, 3568, + 3806, 2805, 3567, + 3805, 2809, 3566, + 3804, 2814, 3564, + 3802, 2821, 3562, + 3800, 2830, 3559, + 3797, 2842, 3555, + 3793, 2857, 3550, + 3787, 2876, 3543, + 3780, 2901, 3533, + 3770, 2932, 3520, + 3756, 2971, 3502, + 3737, 3018, 3476, + 3710, 3074, 3440, + 3671, 3139, 3385, + 3613, 3214, 3301, + 3522, 3299, 3156, + 3363, 3391, 2839, + 2989, 3492, 0, + 0, 3598, 0, + 0, 3710, 0, + 3944, 2889, 3691, + 3944, 2889, 3691, + 3944, 2890, 3691, + 3944, 2890, 3691, + 3944, 2890, 3691, + 3944, 2890, 3691, + 3944, 2891, 3690, + 3943, 2891, 3690, + 3943, 2892, 3690, + 3943, 2893, 3690, + 3943, 2894, 3689, + 3942, 2896, 3689, + 3942, 2898, 3688, + 3941, 2902, 3687, + 3940, 2906, 3686, + 3939, 2911, 3684, + 3937, 2919, 3682, + 3935, 2928, 3679, + 3932, 2941, 3675, + 3928, 2957, 3670, + 3923, 2978, 3663, + 3916, 3004, 3653, + 3906, 3037, 3639, + 3892, 3078, 3620, + 3873, 3128, 3594, + 3846, 3186, 3556, + 3808, 3255, 3500, + 3750, 3332, 3412, + 3661, 3419, 3258, + 3504, 3514, 2909, + 3141, 3616, 0, + 0, 3724, 0, + 4079, 2992, 3814, + 4079, 2992, 3814, + 4078, 2992, 3814, + 4078, 2992, 3814, + 4078, 2992, 3814, + 4078, 2992, 3814, + 4078, 2993, 3814, + 4078, 2993, 3813, + 4078, 2994, 3813, + 4078, 2995, 3813, + 4078, 2996, 3813, + 4077, 2997, 3812, + 4077, 2999, 3812, + 4077, 3002, 3811, + 4076, 3005, 3810, + 4075, 3009, 3809, + 4074, 3015, 3807, + 4072, 3023, 3805, + 4070, 3033, 3802, + 4067, 3047, 3798, + 4063, 3064, 3793, + 4058, 3086, 3785, + 4050, 3114, 3775, + 4040, 3148, 3761, + 4027, 3191, 3742, + 4008, 3242, 3715, + 3981, 3303, 3676, + 3943, 3374, 3618, + 3886, 3453, 3527, + 3798, 3542, 3367, + 3643, 3639, 2988, + 3288, 3742, 0, + 4095, 3100, 3939, + 4095, 3100, 3939, + 4095, 3100, 3939, + 4095, 3101, 3939, + 4095, 3101, 3939, + 4095, 3101, 3939, + 4095, 3101, 3939, + 4095, 3101, 3939, + 4095, 3102, 3939, + 4095, 3103, 3939, + 4095, 3103, 3938, + 4095, 3105, 3938, + 4095, 3106, 3938, + 4095, 3108, 3937, + 4095, 3111, 3936, + 4095, 3114, 3936, + 4095, 3119, 3934, + 4095, 3125, 3933, + 4095, 3133, 3930, + 4095, 3144, 3927, + 4095, 3158, 3923, + 4095, 3176, 3918, + 4095, 3199, 3910, + 4095, 3228, 3900, + 4095, 3264, 3886, + 4095, 3308, 3866, + 4095, 3361, 3839, + 4095, 3424, 3799, + 4078, 3496, 3740, + 4021, 3577, 3646, + 3933, 3667, 3480, + 3780, 3765, 3076, + 4095, 3214, 4066, + 4095, 3214, 4066, + 4095, 3214, 4066, + 4095, 3214, 4066, + 4095, 3214, 4066, + 4095, 3214, 4066, + 4095, 3215, 4066, + 4095, 3215, 4066, + 4095, 3215, 4066, + 4095, 3216, 4066, + 4095, 3216, 4066, + 4095, 3217, 4065, + 4095, 3218, 4065, + 4095, 3220, 4065, + 4095, 3222, 4064, + 4095, 3225, 4063, + 4095, 3229, 4062, + 4095, 3233, 4061, + 4095, 3240, 4059, + 4095, 3248, 4057, + 4095, 3259, 4054, + 4095, 3274, 4050, + 4095, 3292, 4044, + 4095, 3316, 4037, + 4095, 3346, 4026, + 4095, 3383, 4012, + 4095, 3429, 3992, + 4095, 3483, 3964, + 4095, 3547, 3924, + 4095, 3620, 3864, + 4095, 3703, 3768, + 4068, 3794, 3598, + 0, 2393, 2661, + 0, 2393, 2661, + 0, 2393, 2661, + 0, 2394, 2660, + 0, 2395, 2660, + 0, 2396, 2659, + 0, 2397, 2658, + 0, 2399, 2656, + 0, 2401, 2654, + 0, 2404, 2651, + 0, 2408, 2648, + 0, 2413, 2643, + 0, 2420, 2636, + 0, 2429, 2627, + 0, 2440, 2614, + 0, 2456, 2596, + 0, 2475, 2572, + 0, 2500, 2537, + 0, 2532, 2485, + 0, 2571, 2406, + 0, 2618, 2271, + 0, 2674, 1991, + 0, 2740, 0, + 0, 2816, 0, + 0, 2901, 0, + 0, 2994, 0, + 0, 3094, 0, + 0, 3201, 0, + 0, 3313, 0, + 0, 3430, 0, + 0, 3550, 0, + 0, 3673, 0, + 0, 2393, 2662, + 0, 2393, 2662, + 0, 2394, 2661, + 0, 2394, 2661, + 0, 2395, 2660, + 0, 2396, 2659, + 0, 2397, 2658, + 0, 2399, 2657, + 0, 2401, 2655, + 0, 2404, 2652, + 0, 2408, 2648, + 0, 2413, 2643, + 0, 2420, 2636, + 0, 2429, 2627, + 0, 2441, 2614, + 0, 2456, 2597, + 0, 2475, 2572, + 0, 2500, 2537, + 0, 2532, 2486, + 0, 2571, 2406, + 0, 2618, 2272, + 0, 2675, 1992, + 0, 2740, 0, + 0, 2816, 0, + 0, 2901, 0, + 0, 2994, 0, + 0, 3094, 0, + 0, 3201, 0, + 0, 3313, 0, + 0, 3430, 0, + 0, 3550, 0, + 0, 3673, 0, + 0, 2393, 2662, + 0, 2393, 2662, + 0, 2394, 2662, + 0, 2394, 2661, + 0, 2395, 2661, + 0, 2396, 2660, + 0, 2397, 2659, + 0, 2399, 2657, + 0, 2401, 2655, + 0, 2404, 2652, + 0, 2408, 2649, + 0, 2413, 2644, + 0, 2420, 2637, + 0, 2429, 2628, + 0, 2441, 2615, + 0, 2456, 2597, + 0, 2476, 2573, + 0, 2501, 2538, + 0, 2532, 2487, + 0, 2571, 2407, + 0, 2618, 2273, + 0, 2675, 1995, + 0, 2741, 0, + 0, 2816, 0, + 0, 2901, 0, + 0, 2994, 0, + 0, 3094, 0, + 0, 3201, 0, + 0, 3313, 0, + 0, 3430, 0, + 0, 3550, 0, + 0, 3673, 0, + 0, 2393, 2663, + 0, 2393, 2663, + 0, 2394, 2662, + 0, 2394, 2662, + 0, 2395, 2661, + 0, 2396, 2661, + 0, 2397, 2659, + 0, 2399, 2658, + 0, 2401, 2656, + 0, 2404, 2653, + 0, 2408, 2649, + 0, 2413, 2644, + 0, 2420, 2638, + 0, 2429, 2628, + 0, 2441, 2616, + 0, 2456, 2598, + 0, 2476, 2574, + 0, 2501, 2539, + 0, 2532, 2488, + 0, 2571, 2408, + 0, 2618, 2275, + 0, 2675, 1998, + 0, 2741, 0, + 0, 2816, 0, + 0, 2901, 0, + 0, 2994, 0, + 0, 3094, 0, + 0, 3201, 0, + 0, 3313, 0, + 0, 3430, 0, + 0, 3550, 0, + 0, 3674, 0, + 0, 2393, 2664, + 0, 2394, 2664, + 0, 2394, 2663, + 0, 2395, 2663, + 0, 2395, 2662, + 0, 2396, 2661, + 0, 2398, 2660, + 0, 2399, 2659, + 0, 2401, 2657, + 0, 2404, 2654, + 0, 2408, 2650, + 0, 2413, 2645, + 0, 2420, 2639, + 0, 2429, 2629, + 0, 2441, 2617, + 0, 2456, 2599, + 0, 2476, 2575, + 0, 2501, 2540, + 0, 2532, 2489, + 0, 2571, 2410, + 0, 2618, 2277, + 0, 2675, 2002, + 0, 2741, 0, + 0, 2816, 0, + 0, 2901, 0, + 0, 2994, 0, + 0, 3094, 0, + 0, 3201, 0, + 0, 3313, 0, + 0, 3430, 0, + 0, 3550, 0, + 0, 3674, 0, + 0, 2394, 2665, + 0, 2394, 2665, + 0, 2394, 2665, + 0, 2395, 2664, + 0, 2396, 2664, + 0, 2397, 2663, + 0, 2398, 2662, + 0, 2399, 2660, + 0, 2402, 2658, + 0, 2405, 2655, + 0, 2409, 2652, + 0, 2414, 2647, + 0, 2421, 2640, + 0, 2430, 2631, + 0, 2441, 2618, + 0, 2457, 2601, + 0, 2476, 2576, + 0, 2501, 2542, + 0, 2533, 2491, + 0, 2571, 2412, + 0, 2619, 2280, + 0, 2675, 2007, + 0, 2741, 0, + 0, 2816, 0, + 0, 2901, 0, + 0, 2994, 0, + 0, 3094, 0, + 0, 3201, 0, + 0, 3314, 0, + 0, 3430, 0, + 0, 3551, 0, + 0, 3674, 0, + 0, 2394, 2667, + 0, 2394, 2667, + 0, 2395, 2666, + 0, 2395, 2666, + 0, 2396, 2665, + 0, 2397, 2664, + 0, 2398, 2663, + 0, 2400, 2662, + 0, 2402, 2660, + 0, 2405, 2657, + 0, 2409, 2653, + 0, 2414, 2648, + 0, 2421, 2642, + 0, 2430, 2633, + 0, 2442, 2620, + 0, 2457, 2603, + 0, 2477, 2579, + 0, 2501, 2544, + 0, 2533, 2493, + 0, 2572, 2415, + 0, 2619, 2284, + 0, 2675, 2014, + 0, 2741, 0, + 0, 2816, 0, + 0, 2901, 0, + 0, 2994, 0, + 0, 3094, 0, + 0, 3201, 0, + 0, 3314, 0, + 0, 3430, 0, + 0, 3551, 0, + 0, 3674, 0, + 0, 2395, 2669, + 0, 2395, 2669, + 0, 2395, 2669, + 0, 2396, 2668, + 0, 2397, 2668, + 0, 2398, 2667, + 0, 2399, 2666, + 0, 2400, 2664, + 0, 2403, 2662, + 0, 2406, 2659, + 0, 2410, 2656, + 0, 2415, 2651, + 0, 2422, 2644, + 0, 2430, 2635, + 0, 2442, 2623, + 0, 2457, 2605, + 0, 2477, 2581, + 0, 2502, 2547, + 0, 2533, 2497, + 0, 2572, 2419, + 0, 2619, 2289, + 0, 2676, 2024, + 0, 2741, 0, + 0, 2817, 0, + 0, 2901, 0, + 0, 2994, 0, + 0, 3095, 0, + 0, 3201, 0, + 0, 3314, 0, + 0, 3430, 0, + 0, 3551, 0, + 0, 3674, 0, + 0, 2395, 2672, + 0, 2396, 2672, + 0, 2396, 2672, + 0, 2397, 2671, + 0, 2397, 2670, + 0, 2398, 2670, + 0, 2400, 2669, + 0, 2401, 2667, + 0, 2403, 2665, + 0, 2406, 2662, + 0, 2410, 2659, + 0, 2415, 2654, + 0, 2422, 2647, + 0, 2431, 2638, + 0, 2443, 2626, + 0, 2458, 2609, + 0, 2478, 2585, + 0, 2503, 2551, + 0, 2534, 2501, + 0, 2573, 2424, + 0, 2620, 2296, + 0, 2676, 2036, + 0, 2742, 0, + 0, 2817, 0, + 0, 2901, 0, + 0, 2994, 0, + 0, 3095, 0, + 0, 3202, 0, + 0, 3314, 0, + 0, 3430, 0, + 0, 3551, 0, + 0, 3674, 0, + 0, 2397, 2676, + 0, 2397, 2676, + 0, 2397, 2676, + 0, 2398, 2675, + 0, 2398, 2674, + 0, 2399, 2674, + 0, 2401, 2673, + 0, 2402, 2671, + 0, 2404, 2669, + 0, 2407, 2666, + 0, 2411, 2663, + 0, 2416, 2658, + 0, 2423, 2651, + 0, 2432, 2642, + 0, 2444, 2630, + 0, 2459, 2613, + 0, 2478, 2590, + 0, 2503, 2556, + 0, 2535, 2507, + 0, 2573, 2431, + 0, 2620, 2305, + 0, 2677, 2052, + 0, 2742, 0, + 0, 2817, 0, + 0, 2902, 0, + 0, 2995, 0, + 0, 3095, 0, + 0, 3202, 0, + 0, 3314, 0, + 0, 3431, 0, + 0, 3551, 0, + 0, 3674, 0, + 0, 2398, 2681, + 0, 2398, 2681, + 0, 2399, 2681, + 0, 2399, 2680, + 0, 2400, 2680, + 0, 2401, 2679, + 0, 2402, 2678, + 0, 2404, 2676, + 0, 2406, 2674, + 0, 2409, 2672, + 0, 2413, 2668, + 0, 2418, 2663, + 0, 2424, 2657, + 0, 2433, 2648, + 0, 2445, 2636, + 0, 2460, 2619, + 0, 2480, 2596, + 0, 2504, 2563, + 0, 2536, 2514, + 0, 2574, 2440, + 0, 2621, 2317, + 0, 2677, 2072, + 0, 2743, 674, + 0, 2818, 0, + 0, 2902, 0, + 0, 2995, 0, + 0, 3095, 0, + 0, 3202, 0, + 0, 3314, 0, + 0, 3431, 0, + 0, 3551, 0, + 0, 3674, 0, + 0, 2400, 2688, + 0, 2400, 2688, + 0, 2400, 2688, + 0, 2401, 2687, + 0, 2402, 2687, + 0, 2402, 2686, + 0, 2404, 2685, + 0, 2405, 2683, + 0, 2408, 2681, + 0, 2410, 2679, + 0, 2414, 2675, + 0, 2419, 2671, + 0, 2426, 2664, + 0, 2435, 2656, + 0, 2447, 2644, + 0, 2462, 2627, + 0, 2481, 2604, + 0, 2506, 2572, + 0, 2537, 2524, + 0, 2575, 2452, + 0, 2622, 2332, + 0, 2678, 2098, + 0, 2744, 1046, + 0, 2819, 0, + 0, 2903, 0, + 0, 2995, 0, + 0, 3096, 0, + 0, 3202, 0, + 0, 3314, 0, + 0, 3431, 0, + 0, 3551, 0, + 0, 3674, 0, + 0, 2402, 2697, + 0, 2402, 2697, + 0, 2403, 2697, + 0, 2403, 2696, + 0, 2404, 2696, + 0, 2405, 2695, + 0, 2406, 2694, + 0, 2408, 2693, + 0, 2410, 2691, + 0, 2413, 2688, + 0, 2417, 2685, + 0, 2422, 2680, + 0, 2428, 2674, + 0, 2437, 2665, + 0, 2449, 2654, + 0, 2464, 2638, + 0, 2483, 2615, + 0, 2508, 2583, + 0, 2539, 2537, + 0, 2577, 2467, + 0, 2624, 2352, + 0, 2680, 2130, + 0, 2745, 1300, + 0, 2820, 0, + 0, 2904, 0, + 0, 2996, 0, + 0, 3096, 0, + 0, 3203, 0, + 0, 3315, 0, + 0, 3431, 0, + 0, 3551, 0, + 0, 3674, 0, + 0, 2405, 2709, + 0, 2406, 2709, + 0, 2406, 2709, + 0, 2406, 2708, + 0, 2407, 2708, + 0, 2408, 2707, + 0, 2409, 2706, + 0, 2411, 2705, + 0, 2413, 2703, + 0, 2416, 2700, + 0, 2420, 2697, + 0, 2425, 2692, + 0, 2431, 2686, + 0, 2440, 2678, + 0, 2452, 2667, + 0, 2467, 2651, + 0, 2486, 2629, + 0, 2510, 2599, + 0, 2541, 2554, + 0, 2579, 2486, + 0, 2626, 2377, + 0, 2681, 2170, + 0, 2746, 1506, + 0, 2821, 0, + 0, 2905, 0, + 0, 2997, 0, + 0, 3097, 0, + 0, 3203, 0, + 0, 3315, 0, + 0, 3431, 0, + 0, 3551, 0, + 0, 3674, 0, + 0, 2410, 2725, + 0, 2410, 2724, + 0, 2410, 2724, + 0, 2411, 2724, + 0, 2411, 2723, + 0, 2412, 2722, + 0, 2413, 2721, + 0, 2415, 2720, + 0, 2417, 2718, + 0, 2420, 2716, + 0, 2424, 2713, + 0, 2429, 2708, + 0, 2435, 2702, + 0, 2444, 2694, + 0, 2456, 2684, + 0, 2470, 2669, + 0, 2489, 2648, + 0, 2514, 2618, + 0, 2544, 2575, + 0, 2582, 2511, + 0, 2628, 2408, + 0, 2684, 2219, + 0, 2748, 1686, + 0, 2823, 0, + 0, 2906, 0, + 0, 2998, 0, + 0, 3098, 0, + 0, 3204, 0, + 0, 3316, 0, + 0, 3432, 0, + 0, 3552, 0, + 0, 3675, 0, + 0, 2415, 2744, + 0, 2415, 2744, + 0, 2416, 2744, + 0, 2416, 2744, + 0, 2417, 2743, + 0, 2418, 2742, + 0, 2419, 2741, + 0, 2421, 2740, + 0, 2423, 2738, + 0, 2426, 2736, + 0, 2429, 2733, + 0, 2434, 2729, + 0, 2441, 2723, + 0, 2449, 2716, + 0, 2461, 2705, + 0, 2475, 2691, + 0, 2494, 2671, + 0, 2518, 2643, + 0, 2548, 2603, + 0, 2586, 2543, + 0, 2632, 2447, + 0, 2687, 2277, + 0, 2751, 1851, + 0, 2825, 0, + 0, 2908, 0, + 0, 3000, 0, + 0, 3099, 0, + 0, 3205, 0, + 0, 3316, 0, + 0, 3432, 0, + 0, 3552, 0, + 0, 3675, 0, + 896, 2423, 2770, + 879, 2423, 2769, + 854, 2423, 2769, + 820, 2424, 2769, + 769, 2424, 2768, + 691, 2425, 2768, + 560, 2426, 2767, + 290, 2428, 2766, + 0, 2430, 2764, + 0, 2433, 2762, + 0, 2436, 2759, + 0, 2441, 2755, + 0, 2448, 2750, + 0, 2456, 2742, + 0, 2467, 2733, + 0, 2482, 2719, + 0, 2500, 2701, + 0, 2524, 2674, + 0, 2554, 2637, + 0, 2591, 2581, + 0, 2636, 2494, + 0, 2691, 2344, + 0, 2755, 2007, + 0, 2828, 0, + 0, 2910, 0, + 0, 3002, 0, + 0, 3101, 0, + 0, 3206, 0, + 0, 3317, 0, + 0, 3433, 0, + 0, 3553, 0, + 0, 3675, 0, + 1925, 2432, 2801, + 1923, 2432, 2801, + 1921, 2433, 2801, + 1917, 2433, 2801, + 1913, 2434, 2800, + 1907, 2435, 2799, + 1899, 2436, 2799, + 1889, 2438, 2798, + 1874, 2440, 2796, + 1853, 2442, 2794, + 1824, 2446, 2791, + 1782, 2451, 2788, + 1718, 2457, 2783, + 1617, 2465, 2776, + 1432, 2476, 2767, + 925, 2490, 2754, + 0, 2508, 2737, + 0, 2532, 2713, + 0, 2561, 2679, + 0, 2598, 2628, + 0, 2642, 2551, + 0, 2696, 2421, + 0, 2759, 2155, + 0, 2832, 0, + 0, 2914, 0, + 0, 3004, 0, + 0, 3103, 0, + 0, 3208, 0, + 0, 3319, 0, + 0, 3434, 0, + 0, 3554, 0, + 0, 3676, 0, + 2283, 2445, 2841, + 2282, 2445, 2840, + 2281, 2445, 2840, + 2279, 2446, 2840, + 2278, 2447, 2839, + 2275, 2447, 2839, + 2271, 2449, 2838, + 2267, 2450, 2837, + 2260, 2452, 2836, + 2252, 2455, 2834, + 2240, 2458, 2831, + 2223, 2463, 2828, + 2200, 2469, 2823, + 2168, 2477, 2817, + 2120, 2488, 2809, + 2047, 2501, 2798, + 1927, 2519, 2782, + 1692, 2542, 2760, + 612, 2571, 2729, + 0, 2607, 2685, + 0, 2650, 2617, + 0, 2703, 2507, + 0, 2765, 2299, + 0, 2837, 1624, + 0, 2918, 0, + 0, 3008, 0, + 0, 3106, 0, + 0, 3210, 0, + 0, 3321, 0, + 0, 3436, 0, + 0, 3555, 0, + 0, 3677, 0, + 2532, 2461, 2888, + 2531, 2462, 2888, + 2531, 2462, 2888, + 2530, 2462, 2887, + 2529, 2463, 2887, + 2527, 2464, 2887, + 2525, 2465, 2886, + 2522, 2466, 2885, + 2519, 2468, 2884, + 2514, 2471, 2882, + 2507, 2474, 2880, + 2498, 2479, 2877, + 2486, 2484, 2873, + 2469, 2492, 2867, + 2445, 2503, 2860, + 2411, 2516, 2850, + 2360, 2533, 2836, + 2283, 2555, 2817, + 2155, 2583, 2789, + 1893, 2618, 2750, + 0, 2661, 2692, + 0, 2713, 2601, + 0, 2774, 2440, + 0, 2844, 2059, + 0, 2924, 0, + 0, 3013, 0, + 0, 3110, 0, + 0, 3213, 0, + 0, 3323, 0, + 0, 3438, 0, + 0, 3556, 0, + 0, 3678, 0, + 2735, 2482, 2945, + 2735, 2483, 2945, + 2734, 2483, 2945, + 2734, 2483, 2944, + 2733, 2484, 2944, + 2732, 2485, 2944, + 2731, 2486, 2943, + 2729, 2487, 2942, + 2727, 2489, 2941, + 2724, 2491, 2940, + 2719, 2495, 2938, + 2714, 2499, 2935, + 2706, 2504, 2931, + 2696, 2512, 2927, + 2681, 2522, 2920, + 2661, 2535, 2911, + 2633, 2551, 2899, + 2592, 2572, 2882, + 2532, 2599, 2859, + 2435, 2633, 2826, + 2263, 2675, 2777, + 1825, 2725, 2702, + 0, 2784, 2579, + 0, 2853, 2332, + 0, 2932, 847, + 0, 3019, 0, + 0, 3115, 0, + 0, 3217, 0, + 0, 3326, 0, + 0, 3440, 0, + 0, 3558, 0, + 0, 3679, 0, + 2914, 2509, 3011, + 2913, 2509, 3011, + 2913, 2510, 3011, + 2913, 2510, 3011, + 2912, 2510, 3010, + 2912, 2511, 3010, + 2911, 2512, 3009, + 2910, 2513, 3009, + 2908, 2515, 3008, + 2906, 2517, 3007, + 2903, 2521, 3005, + 2900, 2525, 3003, + 2894, 2530, 3000, + 2888, 2537, 2995, + 2878, 2546, 2990, + 2865, 2558, 2982, + 2848, 2574, 2972, + 2823, 2594, 2958, + 2787, 2620, 2938, + 2735, 2652, 2910, + 2653, 2692, 2870, + 2516, 2741, 2810, + 2224, 2798, 2716, + 0, 2865, 2547, + 0, 2942, 2131, + 0, 3028, 0, + 0, 3122, 0, + 0, 3223, 0, + 0, 3331, 0, + 0, 3443, 0, + 0, 3561, 0, + 0, 3681, 0, + 3078, 2542, 3087, + 3078, 2543, 3087, + 3077, 2543, 3087, + 3077, 2543, 3087, + 3077, 2544, 3086, + 3076, 2544, 3086, + 3076, 2545, 3086, + 3075, 2547, 3085, + 3074, 2548, 3084, + 3073, 2550, 3083, + 3071, 2553, 3082, + 3068, 2557, 3080, + 3064, 2562, 3077, + 3060, 2569, 3074, + 3053, 2577, 3069, + 3045, 2589, 3063, + 3033, 2603, 3054, + 3016, 2622, 3042, + 2993, 2647, 3026, + 2961, 2677, 3003, + 2913, 2715, 2971, + 2841, 2761, 2923, + 2721, 2816, 2851, + 2486, 2881, 2733, + 1423, 2955, 2501, + 0, 3039, 1510, + 0, 3130, 0, + 0, 3230, 0, + 0, 3336, 0, + 0, 3448, 0, + 0, 3564, 0, + 0, 3684, 0, + 3232, 2584, 3172, + 3232, 2584, 3172, + 3232, 2584, 3172, + 3232, 2584, 3172, + 3232, 2585, 3171, + 3232, 2585, 3171, + 3231, 2586, 3171, + 3231, 2587, 3170, + 3230, 2589, 3170, + 3229, 2591, 3169, + 3227, 2593, 3167, + 3226, 2597, 3166, + 3223, 2601, 3164, + 3220, 2607, 3161, + 3215, 2615, 3157, + 3209, 2626, 3152, + 3201, 2639, 3145, + 3190, 2657, 3135, + 3174, 2680, 3122, + 3152, 2708, 3103, + 3122, 2743, 3078, + 3077, 2787, 3041, + 3010, 2839, 2986, + 2901, 2901, 2901, + 2696, 2972, 2754, + 2044, 3053, 2432, + 0, 3142, 0, + 0, 3239, 0, + 0, 3344, 0, + 0, 3454, 0, + 0, 3569, 0, + 0, 3687, 0, + 3381, 2633, 3265, + 3381, 2634, 3265, + 3381, 2634, 3265, + 3380, 2634, 3265, + 3380, 2634, 3265, + 3380, 2635, 3265, + 3380, 2636, 3264, + 3379, 2637, 3264, + 3379, 2638, 3263, + 3378, 2640, 3263, + 3377, 2642, 3262, + 3376, 2645, 3260, + 3374, 2649, 3259, + 3372, 2655, 3256, + 3368, 2662, 3253, + 3364, 2671, 3249, + 3358, 2684, 3243, + 3350, 2700, 3235, + 3339, 2720, 3225, + 3324, 2746, 3210, + 3304, 2779, 3190, + 3274, 2819, 3161, + 3232, 2868, 3120, + 3168, 2926, 3058, + 3066, 2994, 2960, + 2879, 3071, 2782, + 2358, 3157, 2318, + 0, 3252, 0, + 0, 3353, 0, + 0, 3461, 0, + 0, 3575, 0, + 0, 3692, 0, + 3525, 2692, 3366, + 3525, 2693, 3366, + 3524, 2693, 3366, + 3524, 2693, 3366, + 3524, 2693, 3366, + 3524, 2694, 3365, + 3524, 2695, 3365, + 3524, 2695, 3365, + 3523, 2697, 3364, + 3523, 2698, 3364, + 3522, 2700, 3363, + 3521, 2703, 3362, + 3520, 2707, 3361, + 3518, 2711, 3359, + 3516, 2718, 3356, + 3512, 2726, 3353, + 3508, 2737, 3348, + 3503, 2751, 3342, + 3495, 2770, 3334, + 3484, 2793, 3322, + 3470, 2823, 3307, + 3450, 2859, 3285, + 3421, 2904, 3254, + 3380, 2958, 3208, + 3319, 3022, 3140, + 3221, 3095, 3028, + 3045, 3177, 2817, + 2591, 3268, 2101, + 0, 3366, 0, + 0, 3471, 0, + 0, 3582, 0, + 0, 3698, 0, + 3665, 2761, 3473, + 3665, 2761, 3473, + 3665, 2761, 3473, + 3665, 2762, 3473, + 3665, 2762, 3473, + 3665, 2762, 3473, + 3665, 2763, 3472, + 3665, 2764, 3472, + 3664, 2765, 3472, + 3664, 2766, 3471, + 3663, 2768, 3471, + 3663, 2770, 3470, + 3662, 2773, 3469, + 3660, 2777, 3467, + 3659, 2783, 3465, + 3656, 2790, 3463, + 3653, 2800, 3459, + 3649, 2812, 3454, + 3644, 2828, 3448, + 3636, 2849, 3439, + 3626, 2875, 3427, + 3611, 2908, 3410, + 3592, 2949, 3387, + 3564, 2998, 3353, + 3524, 3056, 3305, + 3464, 3124, 3230, + 3370, 3202, 3106, + 3201, 3288, 2859, + 2786, 3383, 1324, + 0, 3485, 0, + 0, 3593, 0, + 0, 3706, 0, + 3804, 2839, 3586, + 3804, 2839, 3586, + 3804, 2839, 3586, + 3804, 2840, 3585, + 3803, 2840, 3585, + 3803, 2840, 3585, + 3803, 2841, 3585, + 3803, 2841, 3585, + 3803, 2842, 3585, + 3803, 2843, 3584, + 3802, 2845, 3584, + 3802, 2847, 3583, + 3801, 2849, 3582, + 3800, 2853, 3581, + 3799, 2858, 3580, + 3797, 2864, 3578, + 3795, 2872, 3575, + 3792, 2882, 3571, + 3788, 2896, 3566, + 3782, 2914, 3559, + 3775, 2937, 3550, + 3765, 2966, 3537, + 3751, 3002, 3520, + 3731, 3046, 3495, + 3704, 3099, 3460, + 3665, 3161, 3408, + 3606, 3233, 3328, + 3514, 3314, 3193, + 3351, 3404, 2910, + 2960, 3502, 0, + 0, 3606, 0, + 0, 3717, 0, + 3940, 2926, 3703, + 3940, 2926, 3702, + 3940, 2926, 3702, + 3940, 2926, 3702, + 3940, 2927, 3702, + 3940, 2927, 3702, + 3940, 2927, 3702, + 3940, 2928, 3702, + 3940, 2929, 3702, + 3940, 2930, 3702, + 3939, 2931, 3701, + 3939, 2932, 3701, + 3938, 2935, 3700, + 3938, 2938, 3699, + 3937, 2941, 3698, + 3936, 2947, 3696, + 3934, 2953, 3694, + 3932, 2962, 3691, + 3929, 2974, 3687, + 3925, 2989, 3682, + 3919, 3008, 3675, + 3912, 3033, 3666, + 3902, 3064, 3652, + 3888, 3103, 3634, + 3869, 3150, 3608, + 3842, 3206, 3572, + 3803, 3271, 3517, + 3745, 3347, 3433, + 3654, 3431, 3288, + 3495, 3523, 2971, + 3121, 3624, 0, + 0, 3730, 0, + 4076, 3021, 3823, + 4076, 3021, 3823, + 4076, 3021, 3823, + 4076, 3022, 3823, + 4076, 3022, 3823, + 4076, 3022, 3823, + 4076, 3022, 3823, + 4076, 3023, 3822, + 4076, 3023, 3822, + 4075, 3024, 3822, + 4075, 3025, 3822, + 4075, 3026, 3821, + 4075, 3028, 3821, + 4074, 3031, 3820, + 4073, 3034, 3819, + 4072, 3038, 3818, + 4071, 3043, 3817, + 4070, 3051, 3814, + 4067, 3060, 3811, + 4064, 3073, 3807, + 4060, 3089, 3802, + 4055, 3110, 3795, + 4048, 3136, 3785, + 4038, 3170, 3771, + 4024, 3210, 3753, + 4005, 3260, 3726, + 3978, 3318, 3688, + 3940, 3387, 3632, + 3883, 3464, 3544, + 3793, 3551, 3390, + 3636, 3646, 3041, + 3273, 3748, 0, + 4095, 3124, 3946, + 4095, 3124, 3946, + 4095, 3124, 3946, + 4095, 3124, 3946, + 4095, 3124, 3946, + 4095, 3124, 3946, + 4095, 3125, 3946, + 4095, 3125, 3946, + 4095, 3125, 3946, + 4095, 3126, 3945, + 4095, 3127, 3945, + 4095, 3128, 3945, + 4095, 3129, 3945, + 4095, 3131, 3944, + 4095, 3134, 3943, + 4095, 3137, 3942, + 4095, 3142, 3941, + 4095, 3147, 3940, + 4095, 3155, 3937, + 4095, 3165, 3934, + 4095, 3179, 3930, + 4095, 3196, 3925, + 4095, 3218, 3917, + 4095, 3246, 3907, + 4095, 3280, 3893, + 4095, 3323, 3874, + 4095, 3375, 3847, + 4095, 3435, 3808, + 4075, 3506, 3750, + 4019, 3586, 3659, + 3930, 3674, 3499, + 3775, 3771, 3120, + 4095, 3232, 4071, + 4095, 3232, 4071, + 4095, 3232, 4071, + 4095, 3232, 4071, + 4095, 3233, 4071, + 4095, 3233, 4071, + 4095, 3233, 4071, + 4095, 3233, 4071, + 4095, 3234, 4071, + 4095, 3234, 4071, + 4095, 3235, 4071, + 4095, 3236, 4070, + 4095, 3237, 4070, + 4095, 3238, 4070, + 4095, 3240, 4069, + 4095, 3243, 4069, + 4095, 3246, 4068, + 4095, 3251, 4066, + 4095, 3257, 4065, + 4095, 3265, 4062, + 4095, 3276, 4059, + 4095, 3290, 4055, + 4095, 3308, 4050, + 4095, 3331, 4042, + 4095, 3360, 4032, + 4095, 3396, 4018, + 4095, 3440, 3998, + 4095, 3493, 3971, + 4095, 3556, 3931, + 4095, 3628, 3872, + 4095, 3709, 3778, + 4065, 3799, 3612, + 0, 2525, 2793, + 0, 2525, 2793, + 0, 2525, 2793, + 0, 2525, 2793, + 0, 2526, 2792, + 0, 2527, 2792, + 0, 2528, 2791, + 0, 2529, 2790, + 0, 2531, 2788, + 0, 2533, 2786, + 0, 2536, 2783, + 0, 2540, 2779, + 0, 2545, 2774, + 0, 2552, 2768, + 0, 2561, 2758, + 0, 2572, 2746, + 0, 2588, 2728, + 0, 2607, 2704, + 0, 2632, 2668, + 0, 2664, 2617, + 0, 2703, 2537, + 0, 2750, 2402, + 0, 2807, 2121, + 0, 2873, 0, + 0, 2948, 0, + 0, 3033, 0, + 0, 3126, 0, + 0, 3226, 0, + 0, 3333, 0, + 0, 3445, 0, + 0, 3562, 0, + 0, 3683, 0, + 0, 2525, 2794, + 0, 2525, 2794, + 0, 2525, 2793, + 0, 2526, 2793, + 0, 2526, 2792, + 0, 2527, 2792, + 0, 2528, 2791, + 0, 2529, 2790, + 0, 2531, 2788, + 0, 2533, 2786, + 0, 2536, 2783, + 0, 2540, 2780, + 0, 2545, 2775, + 0, 2552, 2768, + 0, 2561, 2759, + 0, 2573, 2746, + 0, 2588, 2728, + 0, 2607, 2704, + 0, 2632, 2669, + 0, 2664, 2617, + 0, 2703, 2538, + 0, 2750, 2403, + 0, 2807, 2123, + 0, 2873, 0, + 0, 2948, 0, + 0, 3033, 0, + 0, 3126, 0, + 0, 3226, 0, + 0, 3333, 0, + 0, 3446, 0, + 0, 3562, 0, + 0, 3683, 0, + 0, 2525, 2794, + 0, 2525, 2794, + 0, 2525, 2794, + 0, 2526, 2793, + 0, 2526, 2793, + 0, 2527, 2792, + 0, 2528, 2791, + 0, 2529, 2790, + 0, 2531, 2789, + 0, 2533, 2787, + 0, 2536, 2784, + 0, 2540, 2780, + 0, 2545, 2775, + 0, 2552, 2768, + 0, 2561, 2759, + 0, 2573, 2746, + 0, 2588, 2729, + 0, 2608, 2704, + 0, 2633, 2669, + 0, 2664, 2618, + 0, 2703, 2538, + 0, 2750, 2404, + 0, 2807, 2124, + 0, 2873, 0, + 0, 2948, 0, + 0, 3033, 0, + 0, 3126, 0, + 0, 3226, 0, + 0, 3333, 0, + 0, 3446, 0, + 0, 3562, 0, + 0, 3683, 0, + 0, 2525, 2795, + 0, 2525, 2794, + 0, 2525, 2794, + 0, 2526, 2794, + 0, 2526, 2793, + 0, 2527, 2793, + 0, 2528, 2792, + 0, 2529, 2791, + 0, 2531, 2789, + 0, 2533, 2787, + 0, 2536, 2784, + 0, 2540, 2781, + 0, 2545, 2776, + 0, 2552, 2769, + 0, 2561, 2760, + 0, 2573, 2747, + 0, 2588, 2730, + 0, 2608, 2705, + 0, 2633, 2670, + 0, 2664, 2619, + 0, 2703, 2539, + 0, 2750, 2405, + 0, 2807, 2127, + 0, 2873, 0, + 0, 2948, 0, + 0, 3033, 0, + 0, 3126, 0, + 0, 3226, 0, + 0, 3333, 0, + 0, 3446, 0, + 0, 3562, 0, + 0, 3683, 0, + 0, 2525, 2795, + 0, 2525, 2795, + 0, 2526, 2795, + 0, 2526, 2795, + 0, 2526, 2794, + 0, 2527, 2793, + 0, 2528, 2793, + 0, 2529, 2791, + 0, 2531, 2790, + 0, 2533, 2788, + 0, 2536, 2785, + 0, 2540, 2781, + 0, 2545, 2776, + 0, 2552, 2770, + 0, 2561, 2760, + 0, 2573, 2748, + 0, 2588, 2730, + 0, 2608, 2706, + 0, 2633, 2671, + 0, 2664, 2620, + 0, 2703, 2540, + 0, 2750, 2407, + 0, 2807, 2130, + 0, 2873, 0, + 0, 2948, 0, + 0, 3033, 0, + 0, 3126, 0, + 0, 3226, 0, + 0, 3333, 0, + 0, 3446, 0, + 0, 3562, 0, + 0, 3683, 0, + 0, 2525, 2796, + 0, 2526, 2796, + 0, 2526, 2796, + 0, 2526, 2795, + 0, 2527, 2795, + 0, 2527, 2794, + 0, 2528, 2794, + 0, 2530, 2792, + 0, 2531, 2791, + 0, 2533, 2789, + 0, 2536, 2786, + 0, 2540, 2782, + 0, 2546, 2777, + 0, 2552, 2771, + 0, 2561, 2761, + 0, 2573, 2749, + 0, 2588, 2731, + 0, 2608, 2707, + 0, 2633, 2672, + 0, 2664, 2621, + 0, 2703, 2542, + 0, 2751, 2409, + 0, 2807, 2134, + 0, 2873, 0, + 0, 2948, 0, + 0, 3033, 0, + 0, 3126, 0, + 0, 3226, 0, + 0, 3333, 0, + 0, 3446, 0, + 0, 3562, 0, + 0, 3683, 0, + 0, 2526, 2798, + 0, 2526, 2797, + 0, 2526, 2797, + 0, 2527, 2797, + 0, 2527, 2796, + 0, 2528, 2796, + 0, 2529, 2795, + 0, 2530, 2794, + 0, 2532, 2792, + 0, 2534, 2790, + 0, 2537, 2787, + 0, 2541, 2784, + 0, 2546, 2779, + 0, 2553, 2772, + 0, 2562, 2763, + 0, 2573, 2750, + 0, 2589, 2733, + 0, 2608, 2709, + 0, 2633, 2674, + 0, 2665, 2623, + 0, 2703, 2544, + 0, 2751, 2412, + 0, 2807, 2139, + 0, 2873, 0, + 0, 2948, 0, + 0, 3033, 0, + 0, 3126, 0, + 0, 3226, 0, + 0, 3333, 0, + 0, 3446, 0, + 0, 3562, 0, + 0, 3683, 0, + 0, 2526, 2799, + 0, 2526, 2799, + 0, 2527, 2799, + 0, 2527, 2798, + 0, 2527, 2798, + 0, 2528, 2797, + 0, 2529, 2797, + 0, 2530, 2795, + 0, 2532, 2794, + 0, 2534, 2792, + 0, 2537, 2789, + 0, 2541, 2785, + 0, 2546, 2780, + 0, 2553, 2774, + 0, 2562, 2765, + 0, 2574, 2752, + 0, 2589, 2735, + 0, 2609, 2711, + 0, 2634, 2676, + 0, 2665, 2625, + 0, 2704, 2547, + 0, 2751, 2416, + 0, 2807, 2146, + 0, 2873, 0, + 0, 2949, 0, + 0, 3033, 0, + 0, 3126, 0, + 0, 3226, 0, + 0, 3333, 0, + 0, 3446, 0, + 0, 3562, 0, + 0, 3683, 0, + 0, 2527, 2801, + 0, 2527, 2801, + 0, 2527, 2801, + 0, 2528, 2801, + 0, 2528, 2800, + 0, 2529, 2800, + 0, 2530, 2799, + 0, 2531, 2798, + 0, 2533, 2796, + 0, 2535, 2794, + 0, 2538, 2791, + 0, 2542, 2788, + 0, 2547, 2783, + 0, 2554, 2776, + 0, 2563, 2767, + 0, 2574, 2755, + 0, 2590, 2737, + 0, 2609, 2713, + 0, 2634, 2679, + 0, 2665, 2629, + 0, 2704, 2551, + 0, 2751, 2421, + 0, 2808, 2156, + 0, 2873, 0, + 0, 2949, 0, + 0, 3033, 0, + 0, 3126, 0, + 0, 3227, 0, + 0, 3333, 0, + 0, 3446, 0, + 0, 3562, 0, + 0, 3683, 0, + 0, 2527, 2804, + 0, 2528, 2804, + 0, 2528, 2804, + 0, 2528, 2804, + 0, 2529, 2803, + 0, 2529, 2803, + 0, 2530, 2802, + 0, 2532, 2801, + 0, 2533, 2799, + 0, 2536, 2797, + 0, 2538, 2794, + 0, 2542, 2791, + 0, 2548, 2786, + 0, 2554, 2779, + 0, 2563, 2770, + 0, 2575, 2758, + 0, 2590, 2741, + 0, 2610, 2717, + 0, 2635, 2683, + 0, 2666, 2633, + 0, 2705, 2556, + 0, 2752, 2428, + 0, 2808, 2168, + 0, 2874, 0, + 0, 2949, 0, + 0, 3034, 0, + 0, 3126, 0, + 0, 3227, 0, + 0, 3334, 0, + 0, 3446, 0, + 0, 3563, 0, + 0, 3683, 0, + 0, 2528, 2808, + 0, 2529, 2808, + 0, 2529, 2808, + 0, 2529, 2808, + 0, 2530, 2807, + 0, 2531, 2807, + 0, 2531, 2806, + 0, 2533, 2805, + 0, 2534, 2803, + 0, 2537, 2801, + 0, 2539, 2799, + 0, 2543, 2795, + 0, 2549, 2790, + 0, 2555, 2783, + 0, 2564, 2775, + 0, 2576, 2762, + 0, 2591, 2745, + 0, 2611, 2722, + 0, 2635, 2688, + 0, 2667, 2639, + 0, 2705, 2563, + 0, 2752, 2437, + 0, 2809, 2184, + 0, 2874, 0, + 0, 2949, 0, + 0, 3034, 0, + 0, 3127, 0, + 0, 3227, 0, + 0, 3334, 0, + 0, 3446, 0, + 0, 3563, 0, + 0, 3683, 0, + 0, 2530, 2814, + 0, 2530, 2813, + 0, 2530, 2813, + 0, 2531, 2813, + 0, 2531, 2812, + 0, 2532, 2812, + 0, 2533, 2811, + 0, 2534, 2810, + 0, 2536, 2808, + 0, 2538, 2806, + 0, 2541, 2804, + 0, 2545, 2800, + 0, 2550, 2795, + 0, 2557, 2789, + 0, 2565, 2780, + 0, 2577, 2768, + 0, 2592, 2751, + 0, 2612, 2728, + 0, 2636, 2695, + 0, 2668, 2646, + 0, 2706, 2572, + 0, 2753, 2449, + 0, 2809, 2204, + 0, 2875, 806, + 0, 2950, 0, + 0, 3034, 0, + 0, 3127, 0, + 0, 3227, 0, + 0, 3334, 0, + 0, 3446, 0, + 0, 3563, 0, + 0, 3683, 0, + 0, 2532, 2821, + 0, 2532, 2820, + 0, 2532, 2820, + 0, 2532, 2820, + 0, 2533, 2819, + 0, 2534, 2819, + 0, 2535, 2818, + 0, 2536, 2817, + 0, 2537, 2815, + 0, 2540, 2814, + 0, 2543, 2811, + 0, 2546, 2807, + 0, 2552, 2803, + 0, 2558, 2796, + 0, 2567, 2788, + 0, 2579, 2776, + 0, 2594, 2759, + 0, 2613, 2736, + 0, 2638, 2704, + 0, 2669, 2656, + 0, 2708, 2584, + 0, 2754, 2464, + 0, 2810, 2230, + 0, 2876, 1179, + 0, 2951, 0, + 0, 3035, 0, + 0, 3128, 0, + 0, 3228, 0, + 0, 3334, 0, + 0, 3446, 0, + 0, 3563, 0, + 0, 3683, 0, + 0, 2534, 2830, + 0, 2534, 2829, + 0, 2534, 2829, + 0, 2535, 2829, + 0, 2535, 2828, + 0, 2536, 2828, + 0, 2537, 2827, + 0, 2538, 2826, + 0, 2540, 2825, + 0, 2542, 2823, + 0, 2545, 2820, + 0, 2549, 2817, + 0, 2554, 2812, + 0, 2561, 2806, + 0, 2569, 2797, + 0, 2581, 2786, + 0, 2596, 2770, + 0, 2615, 2747, + 0, 2640, 2716, + 0, 2671, 2669, + 0, 2709, 2599, + 0, 2756, 2484, + 0, 2812, 2263, + 0, 2877, 1432, + 0, 2952, 0, + 0, 3036, 0, + 0, 3128, 0, + 0, 3228, 0, + 0, 3335, 0, + 0, 3447, 0, + 0, 3563, 0, + 0, 3683, 0, + 0, 2537, 2842, + 0, 2537, 2841, + 0, 2538, 2841, + 0, 2538, 2841, + 0, 2539, 2840, + 0, 2539, 2840, + 0, 2540, 2839, + 0, 2541, 2838, + 0, 2543, 2837, + 0, 2545, 2835, + 0, 2548, 2832, + 0, 2552, 2829, + 0, 2557, 2824, + 0, 2564, 2818, + 0, 2572, 2810, + 0, 2584, 2799, + 0, 2599, 2783, + 0, 2618, 2761, + 0, 2642, 2731, + 0, 2673, 2686, + 0, 2711, 2618, + 0, 2758, 2509, + 0, 2813, 2303, + 0, 2878, 1638, + 0, 2953, 0, + 0, 3037, 0, + 0, 3129, 0, + 0, 3229, 0, + 0, 3335, 0, + 0, 3447, 0, + 0, 3564, 0, + 0, 3684, 0, + 0, 2541, 2857, + 0, 2542, 2857, + 0, 2542, 2857, + 0, 2542, 2856, + 0, 2543, 2856, + 0, 2543, 2855, + 0, 2544, 2854, + 0, 2546, 2854, + 0, 2547, 2852, + 0, 2549, 2850, + 0, 2552, 2848, + 0, 2556, 2845, + 0, 2561, 2840, + 0, 2568, 2835, + 0, 2576, 2827, + 0, 2588, 2816, + 0, 2602, 2801, + 0, 2621, 2780, + 0, 2646, 2750, + 0, 2676, 2708, + 0, 2714, 2643, + 0, 2760, 2540, + 0, 2816, 2351, + 0, 2880, 1818, + 0, 2955, 0, + 0, 3038, 0, + 0, 3130, 0, + 0, 3230, 0, + 0, 3336, 0, + 0, 3448, 0, + 0, 3564, 0, + 0, 3684, 0, + 0, 2547, 2877, + 0, 2547, 2877, + 0, 2547, 2876, + 0, 2548, 2876, + 0, 2548, 2876, + 0, 2549, 2875, + 0, 2550, 2874, + 0, 2551, 2873, + 0, 2553, 2872, + 0, 2555, 2870, + 0, 2558, 2868, + 0, 2561, 2865, + 0, 2566, 2861, + 0, 2573, 2855, + 0, 2581, 2848, + 0, 2593, 2837, + 0, 2607, 2823, + 0, 2626, 2803, + 0, 2650, 2775, + 0, 2680, 2735, + 0, 2718, 2675, + 0, 2764, 2579, + 0, 2819, 2409, + 0, 2883, 1983, + 0, 2957, 0, + 0, 3040, 0, + 0, 3132, 0, + 0, 3231, 0, + 0, 3337, 0, + 0, 3449, 0, + 0, 3565, 0, + 0, 3684, 0, + 1040, 2554, 2902, + 1028, 2555, 2902, + 1011, 2555, 2902, + 986, 2555, 2901, + 952, 2556, 2901, + 901, 2556, 2900, + 823, 2557, 2900, + 692, 2558, 2899, + 422, 2560, 2898, + 0, 2562, 2896, + 0, 2565, 2894, + 0, 2569, 2891, + 0, 2573, 2887, + 0, 2580, 2882, + 0, 2588, 2875, + 0, 2599, 2865, + 0, 2614, 2851, + 0, 2632, 2833, + 0, 2656, 2806, + 0, 2686, 2769, + 0, 2723, 2713, + 0, 2768, 2627, + 0, 2823, 2476, + 0, 2887, 2139, + 0, 2960, 0, + 0, 3043, 0, + 0, 3134, 0, + 0, 3233, 0, + 0, 3338, 0, + 0, 3450, 0, + 0, 3565, 0, + 0, 3685, 0, + 2058, 2564, 2934, + 2057, 2564, 2933, + 2055, 2565, 2933, + 2053, 2565, 2933, + 2050, 2565, 2933, + 2045, 2566, 2932, + 2039, 2567, 2932, + 2032, 2568, 2931, + 2021, 2570, 2930, + 2006, 2572, 2928, + 1985, 2574, 2926, + 1956, 2578, 2923, + 1914, 2583, 2920, + 1850, 2589, 2915, + 1749, 2597, 2908, + 1564, 2608, 2899, + 1057, 2622, 2887, + 0, 2641, 2869, + 0, 2664, 2845, + 0, 2693, 2811, + 0, 2730, 2761, + 0, 2775, 2683, + 0, 2828, 2553, + 0, 2891, 2287, + 0, 2964, 0, + 0, 3046, 0, + 0, 3137, 0, + 0, 3235, 0, + 0, 3340, 0, + 0, 3451, 0, + 0, 3566, 0, + 0, 3686, 0, + 2415, 2577, 2973, + 2415, 2577, 2973, + 2414, 2577, 2972, + 2413, 2578, 2972, + 2412, 2578, 2972, + 2410, 2579, 2971, + 2407, 2580, 2971, + 2404, 2581, 2970, + 2399, 2582, 2969, + 2392, 2584, 2968, + 2384, 2587, 2966, + 2372, 2590, 2963, + 2355, 2595, 2960, + 2332, 2601, 2956, + 2300, 2609, 2949, + 2252, 2620, 2941, + 2179, 2633, 2930, + 2059, 2651, 2914, + 1824, 2674, 2892, + 744, 2703, 2862, + 0, 2739, 2817, + 0, 2783, 2749, + 0, 2835, 2639, + 0, 2898, 2431, + 0, 2969, 1756, + 0, 3050, 0, + 0, 3140, 0, + 0, 3238, 0, + 0, 3342, 0, + 0, 3453, 0, + 0, 3568, 0, + 0, 3687, 0, + 2664, 2593, 3020, + 2664, 2593, 3020, + 2663, 2594, 3020, + 2663, 2594, 3020, + 2662, 2594, 3020, + 2661, 2595, 3019, + 2659, 2596, 3019, + 2657, 2597, 3018, + 2654, 2598, 3017, + 2651, 2600, 3016, + 2646, 2603, 3014, + 2639, 2606, 3012, + 2630, 2611, 3009, + 2618, 2617, 3005, + 2601, 2624, 2999, + 2577, 2635, 2992, + 2543, 2648, 2982, + 2493, 2665, 2968, + 2416, 2687, 2949, + 2287, 2715, 2922, + 2025, 2750, 2883, + 0, 2793, 2824, + 0, 2845, 2733, + 0, 2906, 2572, + 0, 2976, 2191, + 0, 3056, 0, + 0, 3145, 0, + 0, 3242, 0, + 0, 3345, 0, + 0, 3455, 0, + 0, 3570, 0, + 0, 3688, 0, + 2867, 2614, 3077, + 2867, 2614, 3077, + 2867, 2615, 3077, + 2866, 2615, 3077, + 2866, 2615, 3076, + 2865, 2616, 3076, + 2864, 2617, 3076, + 2863, 2618, 3075, + 2861, 2619, 3074, + 2859, 2621, 3073, + 2856, 2623, 3072, + 2851, 2627, 3070, + 2846, 2631, 3067, + 2838, 2637, 3063, + 2828, 2644, 3059, + 2813, 2654, 3052, + 2793, 2667, 3043, + 2765, 2683, 3031, + 2724, 2705, 3014, + 2664, 2731, 2991, + 2567, 2765, 2958, + 2395, 2807, 2909, + 1957, 2857, 2835, + 0, 2916, 2711, + 0, 2985, 2465, + 0, 3064, 979, + 0, 3151, 0, + 0, 3247, 0, + 0, 3350, 0, + 0, 3458, 0, + 0, 3572, 0, + 0, 3690, 0, + 3046, 2641, 3143, + 3046, 2641, 3143, + 3046, 2641, 3143, + 3045, 2642, 3143, + 3045, 2642, 3143, + 3044, 2643, 3142, + 3044, 2643, 3142, + 3043, 2644, 3142, + 3042, 2646, 3141, + 3040, 2647, 3140, + 3038, 2650, 3139, + 3035, 2653, 3137, + 3032, 2657, 3135, + 3027, 2662, 3132, + 3020, 2669, 3127, + 3010, 2678, 3122, + 2997, 2691, 3114, + 2980, 2706, 3104, + 2955, 2727, 3090, + 2919, 2752, 3070, + 2867, 2785, 3042, + 2786, 2824, 3002, + 2648, 2873, 2942, + 2356, 2930, 2848, + 0, 2997, 2679, + 0, 3074, 2263, + 0, 3160, 0, + 0, 3254, 0, + 0, 3355, 0, + 0, 3463, 0, + 0, 3576, 0, + 0, 3693, 0, + 3210, 2674, 3219, + 3210, 2674, 3219, + 3210, 2675, 3219, + 3210, 2675, 3219, + 3209, 2675, 3219, + 3209, 2676, 3218, + 3209, 2677, 3218, + 3208, 2677, 3218, + 3207, 2679, 3217, + 3206, 2680, 3216, + 3205, 2682, 3215, + 3203, 2685, 3214, + 3200, 2689, 3212, + 3197, 2694, 3209, + 3192, 2701, 3206, + 3185, 2709, 3201, + 3177, 2721, 3195, + 3165, 2735, 3186, + 3148, 2754, 3174, + 3126, 2779, 3158, + 3093, 2809, 3135, + 3045, 2847, 3103, + 2973, 2893, 3055, + 2853, 2948, 2983, + 2618, 3013, 2865, + 1555, 3087, 2634, + 0, 3171, 1643, + 0, 3263, 0, + 0, 3362, 0, + 0, 3468, 0, + 0, 3580, 0, + 0, 3696, 0, + 3365, 2716, 3304, + 3365, 2716, 3304, + 3364, 2716, 3304, + 3364, 2716, 3304, + 3364, 2716, 3304, + 3364, 2717, 3303, + 3364, 2718, 3303, + 3363, 2718, 3303, + 3363, 2719, 3302, + 3362, 2721, 3302, + 3361, 2723, 3301, + 3359, 2725, 3300, + 3358, 2729, 3298, + 3355, 2734, 3296, + 3352, 2740, 3293, + 3347, 2748, 3289, + 3341, 2758, 3284, + 3333, 2772, 3277, + 3322, 2789, 3267, + 3306, 2812, 3254, + 3285, 2840, 3235, + 3254, 2876, 3210, + 3209, 2919, 3173, + 3142, 2971, 3118, + 3033, 3033, 3033, + 2828, 3104, 2887, + 2176, 3185, 2564, + 0, 3274, 0, + 0, 3372, 0, + 0, 3476, 0, + 0, 3586, 0, + 0, 3701, 0, + 3513, 2765, 3397, + 3513, 2765, 3397, + 3513, 2766, 3397, + 3513, 2766, 3397, + 3513, 2766, 3397, + 3512, 2767, 3397, + 3512, 2767, 3397, + 3512, 2768, 3396, + 3511, 2769, 3396, + 3511, 2770, 3395, + 3510, 2772, 3395, + 3509, 2774, 3394, + 3508, 2777, 3392, + 3506, 2781, 3391, + 3504, 2787, 3388, + 3500, 2794, 3385, + 3496, 2804, 3381, + 3490, 2816, 3375, + 3482, 2832, 3367, + 3471, 2852, 3357, + 3457, 2878, 3342, + 3436, 2911, 3322, + 3406, 2951, 3293, + 3364, 3000, 3252, + 3300, 3058, 3190, + 3198, 3126, 3092, + 3011, 3203, 2914, + 2491, 3289, 2450, + 0, 3384, 0, + 0, 3486, 0, + 0, 3594, 0, + 0, 3707, 0, + 3657, 2824, 3498, + 3657, 2824, 3498, + 3657, 2825, 3498, + 3657, 2825, 3498, + 3656, 2825, 3498, + 3656, 2825, 3498, + 3656, 2826, 3497, + 3656, 2827, 3497, + 3656, 2827, 3497, + 3655, 2829, 3497, + 3655, 2830, 3496, + 3654, 2832, 3495, + 3653, 2835, 3494, + 3652, 2839, 3493, + 3650, 2843, 3491, + 3648, 2850, 3488, + 3645, 2858, 3485, + 3640, 2869, 3480, + 3635, 2883, 3474, + 3627, 2902, 3466, + 3616, 2925, 3454, + 3602, 2955, 3439, + 3582, 2992, 3417, + 3553, 3036, 3386, + 3512, 3090, 3340, + 3451, 3154, 3272, + 3353, 3227, 3160, + 3177, 3309, 2949, + 2723, 3400, 2233, + 0, 3498, 0, + 0, 3604, 0, + 0, 3715, 0, + 3797, 2893, 3605, + 3797, 2893, 3605, + 3797, 2893, 3605, + 3797, 2893, 3605, + 3797, 2894, 3605, + 3797, 2894, 3605, + 3797, 2894, 3605, + 3797, 2895, 3605, + 3797, 2896, 3604, + 3796, 2897, 3604, + 3796, 2898, 3604, + 3795, 2900, 3603, + 3795, 2902, 3602, + 3794, 2905, 3601, + 3792, 2909, 3600, + 3791, 2915, 3598, + 3788, 2922, 3595, + 3785, 2932, 3591, + 3781, 2944, 3587, + 3776, 2960, 3580, + 3768, 2981, 3571, + 3758, 3007, 3559, + 3744, 3040, 3542, + 3724, 3081, 3519, + 3696, 3130, 3486, + 3656, 3188, 3437, + 3596, 3256, 3362, + 3502, 3334, 3238, + 3333, 3420, 2991, + 2918, 3515, 1456, + 0, 3617, 0, + 0, 3725, 0, + 3936, 2971, 3718, + 3936, 2971, 3718, + 3936, 2971, 3718, + 3936, 2971, 3718, + 3936, 2972, 3718, + 3936, 2972, 3717, + 3935, 2972, 3717, + 3935, 2973, 3717, + 3935, 2973, 3717, + 3935, 2974, 3717, + 3935, 2975, 3716, + 3934, 2977, 3716, + 3934, 2979, 3715, + 3933, 2981, 3714, + 3932, 2985, 3713, + 3931, 2990, 3712, + 3929, 2996, 3710, + 3927, 3004, 3707, + 3924, 3015, 3703, + 3920, 3028, 3698, + 3914, 3046, 3691, + 3907, 3069, 3682, + 3897, 3098, 3669, + 3883, 3134, 3652, + 3863, 3178, 3627, + 3836, 3231, 3592, + 3797, 3293, 3540, + 3738, 3365, 3460, + 3646, 3446, 3325, + 3483, 3536, 3042, + 3092, 3634, 0, + 0, 3738, 0, + 4073, 3058, 3835, + 4073, 3058, 3835, + 4072, 3058, 3835, + 4072, 3058, 3835, + 4072, 3059, 3834, + 4072, 3059, 3834, + 4072, 3059, 3834, + 4072, 3059, 3834, + 4072, 3060, 3834, + 4072, 3061, 3834, + 4072, 3062, 3834, + 4071, 3063, 3833, + 4071, 3064, 3833, + 4071, 3067, 3832, + 4070, 3070, 3831, + 4069, 3073, 3830, + 4068, 3079, 3828, + 4066, 3085, 3826, + 4064, 3094, 3823, + 4061, 3106, 3820, + 4057, 3121, 3814, + 4051, 3140, 3807, + 4044, 3165, 3798, + 4034, 3196, 3784, + 4020, 3235, 3766, + 4001, 3282, 3741, + 3974, 3338, 3704, + 3935, 3404, 3650, + 3877, 3479, 3565, + 3787, 3563, 3420, + 3627, 3656, 3103, + 3253, 3756, 0, + 4095, 3153, 3955, + 4095, 3153, 3955, + 4095, 3153, 3955, + 4095, 3154, 3955, + 4095, 3154, 3955, + 4095, 3154, 3955, + 4095, 3154, 3955, + 4095, 3154, 3955, + 4095, 3155, 3955, + 4095, 3155, 3954, + 4095, 3156, 3954, + 4095, 3157, 3954, + 4095, 3159, 3954, + 4095, 3160, 3953, + 4095, 3163, 3952, + 4095, 3166, 3951, + 4095, 3170, 3950, + 4095, 3176, 3949, + 4095, 3183, 3946, + 4095, 3192, 3943, + 4095, 3205, 3940, + 4095, 3221, 3934, + 4095, 3242, 3927, + 4095, 3269, 3917, + 4095, 3302, 3903, + 4095, 3342, 3885, + 4095, 3392, 3858, + 4095, 3451, 3820, + 4072, 3519, 3764, + 4015, 3596, 3676, + 3925, 3683, 3522, + 3768, 3778, 3173, + 4095, 3256, 4078, + 4095, 3256, 4078, + 4095, 3256, 4078, + 4095, 3256, 4078, + 4095, 3256, 4078, + 4095, 3256, 4078, + 4095, 3256, 4078, + 4095, 3257, 4078, + 4095, 3257, 4078, + 4095, 3257, 4078, + 4095, 3258, 4078, + 4095, 3259, 4077, + 4095, 3260, 4077, + 4095, 3261, 4077, + 4095, 3263, 4076, + 4095, 3266, 4075, + 4095, 3269, 4075, + 4095, 3274, 4073, + 4095, 3280, 4072, + 4095, 3287, 4069, + 4095, 3297, 4066, + 4095, 3311, 4062, + 4095, 3328, 4057, + 4095, 3350, 4049, + 4095, 3378, 4039, + 4095, 3413, 4025, + 4095, 3455, 4006, + 4095, 3507, 3979, + 4095, 3567, 3940, + 4095, 3638, 3882, + 4095, 3718, 3791, + 4062, 3806, 3631, + 0, 2656, 2925, + 0, 2657, 2925, + 0, 2657, 2925, + 0, 2657, 2925, + 0, 2658, 2924, + 0, 2658, 2924, + 0, 2659, 2923, + 0, 2660, 2923, + 0, 2661, 2921, + 0, 2663, 2920, + 0, 2665, 2918, + 0, 2668, 2915, + 0, 2672, 2911, + 0, 2677, 2906, + 0, 2684, 2899, + 0, 2693, 2890, + 0, 2705, 2878, + 0, 2720, 2860, + 0, 2739, 2835, + 0, 2764, 2800, + 0, 2796, 2749, + 0, 2835, 2669, + 0, 2882, 2534, + 0, 2939, 2253, + 0, 3005, 0, + 0, 3080, 0, + 0, 3165, 0, + 0, 3258, 0, + 0, 3358, 0, + 0, 3465, 0, + 0, 3578, 0, + 0, 3694, 0, + 0, 2657, 2926, + 0, 2657, 2926, + 0, 2657, 2925, + 0, 2657, 2925, + 0, 2658, 2925, + 0, 2658, 2924, + 0, 2659, 2924, + 0, 2660, 2923, + 0, 2661, 2922, + 0, 2663, 2920, + 0, 2665, 2918, + 0, 2668, 2915, + 0, 2672, 2912, + 0, 2677, 2907, + 0, 2684, 2900, + 0, 2693, 2890, + 0, 2705, 2878, + 0, 2720, 2860, + 0, 2739, 2836, + 0, 2765, 2801, + 0, 2796, 2749, + 0, 2835, 2669, + 0, 2882, 2535, + 0, 2939, 2254, + 0, 3005, 0, + 0, 3080, 0, + 0, 3165, 0, + 0, 3258, 0, + 0, 3358, 0, + 0, 3465, 0, + 0, 3578, 0, + 0, 3694, 0, + 0, 2657, 2926, + 0, 2657, 2926, + 0, 2657, 2926, + 0, 2657, 2925, + 0, 2658, 2925, + 0, 2658, 2925, + 0, 2659, 2924, + 0, 2660, 2923, + 0, 2661, 2922, + 0, 2663, 2920, + 0, 2665, 2918, + 0, 2668, 2916, + 0, 2672, 2912, + 0, 2677, 2907, + 0, 2684, 2900, + 0, 2693, 2891, + 0, 2705, 2878, + 0, 2720, 2861, + 0, 2740, 2836, + 0, 2765, 2801, + 0, 2796, 2749, + 0, 2835, 2670, + 0, 2882, 2535, + 0, 2939, 2255, + 0, 3005, 0, + 0, 3080, 0, + 0, 3165, 0, + 0, 3258, 0, + 0, 3358, 0, + 0, 3465, 0, + 0, 3578, 0, + 0, 3694, 0, + 0, 2657, 2926, + 0, 2657, 2926, + 0, 2657, 2926, + 0, 2657, 2926, + 0, 2658, 2925, + 0, 2658, 2925, + 0, 2659, 2924, + 0, 2660, 2923, + 0, 2661, 2922, + 0, 2663, 2921, + 0, 2665, 2919, + 0, 2668, 2916, + 0, 2672, 2912, + 0, 2677, 2907, + 0, 2684, 2900, + 0, 2693, 2891, + 0, 2705, 2879, + 0, 2720, 2861, + 0, 2740, 2836, + 0, 2765, 2801, + 0, 2796, 2750, + 0, 2835, 2670, + 0, 2882, 2536, + 0, 2939, 2257, + 0, 3005, 0, + 0, 3080, 0, + 0, 3165, 0, + 0, 3258, 0, + 0, 3358, 0, + 0, 3465, 0, + 0, 3578, 0, + 0, 3694, 0, + 0, 2657, 2927, + 0, 2657, 2927, + 0, 2657, 2927, + 0, 2657, 2926, + 0, 2658, 2926, + 0, 2658, 2925, + 0, 2659, 2925, + 0, 2660, 2924, + 0, 2661, 2923, + 0, 2663, 2921, + 0, 2665, 2919, + 0, 2668, 2917, + 0, 2672, 2913, + 0, 2677, 2908, + 0, 2684, 2901, + 0, 2693, 2892, + 0, 2705, 2879, + 0, 2720, 2862, + 0, 2740, 2837, + 0, 2765, 2802, + 0, 2796, 2751, + 0, 2835, 2671, + 0, 2882, 2537, + 0, 2939, 2259, + 0, 3005, 0, + 0, 3080, 0, + 0, 3165, 0, + 0, 3258, 0, + 0, 3358, 0, + 0, 3465, 0, + 0, 3578, 0, + 0, 3694, 0, + 0, 2657, 2928, + 0, 2657, 2927, + 0, 2657, 2927, + 0, 2658, 2927, + 0, 2658, 2927, + 0, 2659, 2926, + 0, 2659, 2926, + 0, 2660, 2925, + 0, 2661, 2924, + 0, 2663, 2922, + 0, 2665, 2920, + 0, 2668, 2917, + 0, 2672, 2914, + 0, 2677, 2909, + 0, 2684, 2902, + 0, 2693, 2893, + 0, 2705, 2880, + 0, 2720, 2862, + 0, 2740, 2838, + 0, 2765, 2803, + 0, 2796, 2752, + 0, 2835, 2673, + 0, 2882, 2539, + 0, 2939, 2262, + 0, 3005, 0, + 0, 3080, 0, + 0, 3165, 0, + 0, 3258, 0, + 0, 3358, 0, + 0, 3465, 0, + 0, 3578, 0, + 0, 3694, 0, + 0, 2657, 2929, + 0, 2657, 2928, + 0, 2658, 2928, + 0, 2658, 2928, + 0, 2658, 2928, + 0, 2659, 2927, + 0, 2660, 2926, + 0, 2660, 2926, + 0, 2662, 2925, + 0, 2663, 2923, + 0, 2666, 2921, + 0, 2669, 2918, + 0, 2672, 2915, + 0, 2678, 2910, + 0, 2684, 2903, + 0, 2693, 2894, + 0, 2705, 2881, + 0, 2720, 2864, + 0, 2740, 2839, + 0, 2765, 2804, + 0, 2796, 2753, + 0, 2835, 2674, + 0, 2883, 2541, + 0, 2939, 2266, + 0, 3005, 0, + 0, 3080, 0, + 0, 3165, 0, + 0, 3258, 0, + 0, 3358, 0, + 0, 3465, 0, + 0, 3578, 0, + 0, 3694, 0, + 0, 2658, 2930, + 0, 2658, 2930, + 0, 2658, 2929, + 0, 2658, 2929, + 0, 2659, 2929, + 0, 2659, 2928, + 0, 2660, 2928, + 0, 2661, 2927, + 0, 2662, 2926, + 0, 2664, 2924, + 0, 2666, 2922, + 0, 2669, 2919, + 0, 2673, 2916, + 0, 2678, 2911, + 0, 2685, 2904, + 0, 2694, 2895, + 0, 2706, 2882, + 0, 2721, 2865, + 0, 2740, 2841, + 0, 2765, 2806, + 0, 2797, 2755, + 0, 2836, 2676, + 0, 2883, 2544, + 0, 2939, 2271, + 0, 3005, 0, + 0, 3080, 0, + 0, 3165, 0, + 0, 3258, 0, + 0, 3358, 0, + 0, 3465, 0, + 0, 3578, 0, + 0, 3694, 0, + 0, 2658, 2931, + 0, 2658, 2931, + 0, 2658, 2931, + 0, 2659, 2931, + 0, 2659, 2931, + 0, 2660, 2930, + 0, 2660, 2929, + 0, 2661, 2929, + 0, 2662, 2927, + 0, 2664, 2926, + 0, 2666, 2924, + 0, 2669, 2921, + 0, 2673, 2918, + 0, 2678, 2913, + 0, 2685, 2906, + 0, 2694, 2897, + 0, 2706, 2884, + 0, 2721, 2867, + 0, 2741, 2843, + 0, 2766, 2808, + 0, 2797, 2757, + 0, 2836, 2679, + 0, 2883, 2548, + 0, 2939, 2279, + 0, 3005, 0, + 0, 3081, 0, + 0, 3165, 0, + 0, 3258, 0, + 0, 3359, 0, + 0, 3465, 0, + 0, 3578, 0, + 0, 3694, 0, + 0, 2659, 2934, + 0, 2659, 2934, + 0, 2659, 2933, + 0, 2659, 2933, + 0, 2660, 2933, + 0, 2660, 2932, + 0, 2661, 2932, + 0, 2662, 2931, + 0, 2663, 2930, + 0, 2665, 2928, + 0, 2667, 2926, + 0, 2670, 2924, + 0, 2674, 2920, + 0, 2679, 2915, + 0, 2686, 2908, + 0, 2695, 2899, + 0, 2706, 2887, + 0, 2722, 2870, + 0, 2741, 2845, + 0, 2766, 2811, + 0, 2797, 2761, + 0, 2836, 2683, + 0, 2883, 2553, + 0, 2940, 2288, + 0, 3006, 0, + 0, 3081, 0, + 0, 3165, 0, + 0, 3258, 0, + 0, 3359, 0, + 0, 3466, 0, + 0, 3578, 0, + 0, 3695, 0, + 0, 2659, 2937, + 0, 2659, 2937, + 0, 2660, 2936, + 0, 2660, 2936, + 0, 2660, 2936, + 0, 2661, 2935, + 0, 2662, 2935, + 0, 2663, 2934, + 0, 2664, 2933, + 0, 2665, 2931, + 0, 2668, 2929, + 0, 2671, 2927, + 0, 2674, 2923, + 0, 2680, 2918, + 0, 2686, 2911, + 0, 2695, 2902, + 0, 2707, 2890, + 0, 2722, 2873, + 0, 2742, 2849, + 0, 2767, 2815, + 0, 2798, 2765, + 0, 2837, 2688, + 0, 2884, 2560, + 0, 2940, 2300, + 0, 3006, 0, + 0, 3081, 0, + 0, 3166, 0, + 0, 3258, 0, + 0, 3359, 0, + 0, 3466, 0, + 0, 3578, 0, + 0, 3695, 0, + 0, 2660, 2941, + 0, 2660, 2941, + 0, 2661, 2940, + 0, 2661, 2940, + 0, 2661, 2940, + 0, 2662, 2939, + 0, 2663, 2939, + 0, 2664, 2938, + 0, 2665, 2937, + 0, 2666, 2935, + 0, 2669, 2933, + 0, 2672, 2931, + 0, 2675, 2927, + 0, 2681, 2922, + 0, 2687, 2916, + 0, 2696, 2907, + 0, 2708, 2894, + 0, 2723, 2877, + 0, 2743, 2854, + 0, 2768, 2820, + 0, 2799, 2771, + 0, 2837, 2695, + 0, 2885, 2569, + 0, 2941, 2316, + 0, 3006, 0, + 0, 3082, 0, + 0, 3166, 0, + 0, 3259, 0, + 0, 3359, 0, + 0, 3466, 0, + 0, 3578, 0, + 0, 3695, 0, + 0, 2662, 2946, + 0, 2662, 2946, + 0, 2662, 2946, + 0, 2662, 2945, + 0, 2663, 2945, + 0, 2663, 2945, + 0, 2664, 2944, + 0, 2665, 2943, + 0, 2666, 2942, + 0, 2668, 2941, + 0, 2670, 2939, + 0, 2673, 2936, + 0, 2677, 2932, + 0, 2682, 2928, + 0, 2689, 2921, + 0, 2698, 2912, + 0, 2709, 2900, + 0, 2724, 2883, + 0, 2744, 2860, + 0, 2769, 2827, + 0, 2800, 2778, + 0, 2838, 2704, + 0, 2885, 2581, + 0, 2941, 2336, + 0, 3007, 938, + 0, 3082, 0, + 0, 3166, 0, + 0, 3259, 0, + 0, 3359, 0, + 0, 3466, 0, + 0, 3578, 0, + 0, 3695, 0, + 0, 2663, 2953, + 0, 2664, 2953, + 0, 2664, 2952, + 0, 2664, 2952, + 0, 2665, 2952, + 0, 2665, 2951, + 0, 2666, 2951, + 0, 2667, 2950, + 0, 2668, 2949, + 0, 2670, 2948, + 0, 2672, 2946, + 0, 2675, 2943, + 0, 2679, 2940, + 0, 2684, 2935, + 0, 2690, 2928, + 0, 2699, 2920, + 0, 2711, 2908, + 0, 2726, 2891, + 0, 2745, 2868, + 0, 2770, 2836, + 0, 2801, 2788, + 0, 2840, 2716, + 0, 2886, 2596, + 0, 2942, 2362, + 0, 3008, 1311, + 0, 3083, 0, + 0, 3167, 0, + 0, 3260, 0, + 0, 3360, 0, + 0, 3466, 0, + 0, 3579, 0, + 0, 3695, 0, + 0, 2666, 2962, + 0, 2666, 2962, + 0, 2666, 2962, + 0, 2667, 2961, + 0, 2667, 2961, + 0, 2667, 2961, + 0, 2668, 2960, + 0, 2669, 2959, + 0, 2670, 2958, + 0, 2672, 2957, + 0, 2674, 2955, + 0, 2677, 2952, + 0, 2681, 2949, + 0, 2686, 2944, + 0, 2693, 2938, + 0, 2701, 2929, + 0, 2713, 2918, + 0, 2728, 2902, + 0, 2747, 2879, + 0, 2772, 2848, + 0, 2803, 2801, + 0, 2841, 2731, + 0, 2888, 2616, + 0, 2944, 2395, + 0, 3009, 1565, + 0, 3084, 0, + 0, 3168, 0, + 0, 3260, 0, + 0, 3360, 0, + 0, 3467, 0, + 0, 3579, 0, + 0, 3695, 0, + 0, 2669, 2974, + 0, 2669, 2974, + 0, 2669, 2973, + 0, 2670, 2973, + 0, 2670, 2973, + 0, 2671, 2972, + 0, 2671, 2972, + 0, 2672, 2971, + 0, 2673, 2970, + 0, 2675, 2969, + 0, 2677, 2967, + 0, 2680, 2964, + 0, 2684, 2961, + 0, 2689, 2957, + 0, 2696, 2950, + 0, 2704, 2942, + 0, 2716, 2931, + 0, 2731, 2915, + 0, 2750, 2894, + 0, 2774, 2863, + 0, 2805, 2818, + 0, 2843, 2751, + 0, 2890, 2641, + 0, 2945, 2435, + 0, 3010, 1770, + 0, 3085, 0, + 0, 3169, 0, + 0, 3261, 0, + 0, 3361, 0, + 0, 3467, 0, + 0, 3579, 0, + 0, 3696, 0, + 0, 2673, 2989, + 0, 2673, 2989, + 0, 2674, 2989, + 0, 2674, 2989, + 0, 2674, 2988, + 0, 2675, 2988, + 0, 2676, 2987, + 0, 2676, 2987, + 0, 2678, 2986, + 0, 2679, 2984, + 0, 2681, 2982, + 0, 2684, 2980, + 0, 2688, 2977, + 0, 2693, 2973, + 0, 2700, 2967, + 0, 2708, 2959, + 0, 2720, 2948, + 0, 2735, 2933, + 0, 2754, 2912, + 0, 2778, 2882, + 0, 2808, 2840, + 0, 2846, 2775, + 0, 2893, 2672, + 0, 2948, 2483, + 0, 3013, 1950, + 0, 3087, 0, + 0, 3170, 0, + 0, 3262, 0, + 0, 3362, 0, + 0, 3468, 0, + 0, 3580, 0, + 0, 3696, 0, + 0, 2679, 3009, + 0, 2679, 3009, + 0, 2679, 3009, + 0, 2680, 3008, + 0, 2680, 3008, + 0, 2680, 3008, + 0, 2681, 3007, + 0, 2682, 3007, + 0, 2683, 3006, + 0, 2685, 3004, + 0, 2687, 3003, + 0, 2690, 3000, + 0, 2693, 2997, + 0, 2698, 2993, + 0, 2705, 2987, + 0, 2714, 2980, + 0, 2725, 2969, + 0, 2739, 2955, + 0, 2758, 2935, + 0, 2782, 2907, + 0, 2813, 2867, + 0, 2850, 2807, + 0, 2896, 2711, + 0, 2951, 2541, + 0, 3015, 2115, + 0, 3089, 0, + 0, 3172, 0, + 0, 3264, 0, + 0, 3363, 0, + 0, 3469, 0, + 0, 3581, 0, + 0, 3697, 0, + 1182, 2686, 3034, + 1173, 2686, 3034, + 1160, 2687, 3034, + 1143, 2687, 3034, + 1119, 2687, 3033, + 1084, 2688, 3033, + 1033, 2688, 3033, + 955, 2689, 3032, + 824, 2691, 3031, + 554, 2692, 3030, + 0, 2694, 3028, + 0, 2697, 3026, + 0, 2701, 3023, + 0, 2706, 3019, + 0, 2712, 3014, + 0, 2720, 3007, + 0, 2731, 2997, + 0, 2746, 2983, + 0, 2764, 2965, + 0, 2788, 2939, + 0, 2818, 2901, + 0, 2855, 2846, + 0, 2901, 2759, + 0, 2955, 2608, + 0, 3019, 2271, + 0, 3092, 0, + 0, 3175, 0, + 0, 3266, 0, + 0, 3365, 0, + 0, 3470, 0, + 0, 3582, 0, + 0, 3697, 0, + 2191, 2696, 3066, + 2190, 2696, 3066, + 2189, 2696, 3066, + 2187, 2697, 3065, + 2185, 2697, 3065, + 2182, 2698, 3065, + 2177, 2698, 3064, + 2172, 2699, 3064, + 2164, 2700, 3063, + 2153, 2702, 3062, + 2138, 2704, 3060, + 2117, 2706, 3058, + 2088, 2710, 3055, + 2046, 2715, 3052, + 1983, 2721, 3047, + 1881, 2729, 3040, + 1696, 2740, 3031, + 1189, 2754, 3019, + 0, 2773, 3001, + 0, 2796, 2977, + 0, 2825, 2943, + 0, 2862, 2893, + 0, 2907, 2815, + 0, 2960, 2685, + 0, 3023, 2419, + 0, 3096, 0, + 0, 3178, 0, + 0, 3269, 0, + 0, 3367, 0, + 0, 3472, 0, + 0, 3583, 0, + 0, 3699, 0, + 2548, 2709, 3105, + 2548, 2709, 3105, + 2547, 2709, 3105, + 2546, 2709, 3105, + 2545, 2710, 3104, + 2544, 2710, 3104, + 2542, 2711, 3104, + 2539, 2712, 3103, + 2536, 2713, 3102, + 2531, 2714, 3101, + 2524, 2716, 3100, + 2516, 2719, 3098, + 2504, 2722, 3095, + 2487, 2727, 3092, + 2464, 2733, 3088, + 2432, 2741, 3082, + 2384, 2752, 3073, + 2311, 2766, 3062, + 2191, 2783, 3046, + 1956, 2806, 3025, + 876, 2835, 2994, + 0, 2871, 2949, + 0, 2915, 2881, + 0, 2967, 2771, + 0, 3030, 2564, + 0, 3101, 1888, + 0, 3182, 0, + 0, 3272, 0, + 0, 3370, 0, + 0, 3474, 0, + 0, 3585, 0, + 0, 3700, 0, + 2796, 2725, 3153, + 2796, 2725, 3152, + 2796, 2725, 3152, + 2795, 2726, 3152, + 2795, 2726, 3152, + 2794, 2726, 3152, + 2793, 2727, 3151, + 2791, 2728, 3151, + 2789, 2729, 3150, + 2787, 2730, 3149, + 2783, 2732, 3148, + 2778, 2735, 3146, + 2771, 2738, 3144, + 2762, 2743, 3141, + 2750, 2749, 3137, + 2733, 2756, 3131, + 2709, 2767, 3124, + 2675, 2780, 3114, + 2625, 2797, 3100, + 2548, 2819, 3081, + 2419, 2847, 3054, + 2157, 2882, 3015, + 0, 2925, 2957, + 0, 2977, 2865, + 0, 3038, 2704, + 0, 3108, 2323, + 0, 3188, 0, + 0, 3277, 0, + 0, 3374, 0, + 0, 3478, 0, + 0, 3587, 0, + 0, 3702, 0, + 2999, 2746, 3209, + 2999, 2746, 3209, + 2999, 2746, 3209, + 2999, 2747, 3209, + 2998, 2747, 3209, + 2998, 2747, 3209, + 2997, 2748, 3208, + 2996, 2749, 3208, + 2995, 2750, 3207, + 2993, 2751, 3206, + 2991, 2753, 3205, + 2988, 2755, 3204, + 2984, 2759, 3202, + 2978, 2763, 3199, + 2970, 2769, 3196, + 2960, 2776, 3191, + 2945, 2786, 3184, + 2925, 2799, 3175, + 2897, 2815, 3163, + 2857, 2837, 3147, + 2796, 2864, 3123, + 2699, 2897, 3090, + 2527, 2939, 3041, + 2089, 2989, 2967, + 0, 3048, 2843, + 0, 3118, 2597, + 0, 3196, 1111, + 0, 3283, 0, + 0, 3379, 0, + 0, 3482, 0, + 0, 3590, 0, + 0, 3704, 0, + 3178, 2773, 3276, + 3178, 2773, 3275, + 3178, 2773, 3275, + 3178, 2773, 3275, + 3177, 2774, 3275, + 3177, 2774, 3275, + 3177, 2775, 3275, + 3176, 2775, 3274, + 3175, 2776, 3274, + 3174, 2778, 3273, + 3172, 2779, 3272, + 3170, 2782, 3271, + 3167, 2785, 3269, + 3164, 2789, 3267, + 3159, 2794, 3264, + 3152, 2801, 3260, + 3142, 2811, 3254, + 3130, 2823, 3246, + 3112, 2838, 3236, + 3087, 2859, 3222, + 3051, 2884, 3202, + 2999, 2917, 3174, + 2918, 2956, 3134, + 2780, 3005, 3074, + 2488, 3062, 2980, + 0, 3130, 2811, + 0, 3206, 2395, + 0, 3292, 0, + 0, 3386, 0, + 0, 3487, 0, + 0, 3595, 0, + 0, 3708, 0, + 3342, 2806, 3351, + 3342, 2806, 3351, + 3342, 2807, 3351, + 3342, 2807, 3351, + 3342, 2807, 3351, + 3341, 2807, 3351, + 3341, 2808, 3350, + 3341, 2809, 3350, + 3340, 2810, 3350, + 3339, 2811, 3349, + 3338, 2812, 3348, + 3337, 2814, 3347, + 3335, 2817, 3346, + 3332, 2821, 3344, + 3329, 2826, 3341, + 3324, 2833, 3338, + 3318, 2841, 3333, + 3309, 2853, 3327, + 3297, 2867, 3318, + 3281, 2886, 3306, + 3258, 2911, 3290, + 3225, 2941, 3267, + 3177, 2979, 3235, + 3105, 3025, 3187, + 2985, 3080, 3115, + 2750, 3145, 2997, + 1687, 3219, 2766, + 0, 3303, 1775, + 0, 3395, 0, + 0, 3494, 0, + 0, 3600, 0, + 0, 3712, 0, + 3497, 2847, 3436, + 3497, 2848, 3436, + 3497, 2848, 3436, + 3497, 2848, 3436, + 3496, 2848, 3436, + 3496, 2849, 3436, + 3496, 2849, 3436, + 3496, 2850, 3435, + 3495, 2850, 3435, + 3495, 2852, 3434, + 3494, 2853, 3434, + 3493, 2855, 3433, + 3492, 2858, 3432, + 3490, 2861, 3430, + 3487, 2866, 3428, + 3484, 2872, 3425, + 3479, 2880, 3421, + 3473, 2890, 3416, + 3465, 2904, 3409, + 3454, 2921, 3399, + 3438, 2944, 3386, + 3417, 2972, 3368, + 3386, 3008, 3342, + 3341, 3051, 3305, + 3274, 3103, 3250, + 3165, 3165, 3165, + 2960, 3236, 3019, + 2308, 3317, 2696, + 0, 3406, 0, + 0, 3504, 0, + 0, 3608, 0, + 0, 3718, 0, + 3645, 2897, 3529, + 3645, 2897, 3529, + 3645, 2898, 3529, + 3645, 2898, 3529, + 3645, 2898, 3529, + 3645, 2898, 3529, + 3644, 2899, 3529, + 3644, 2899, 3529, + 3644, 2900, 3528, + 3644, 2901, 3528, + 3643, 2902, 3527, + 3642, 2904, 3527, + 3641, 2906, 3526, + 3640, 2909, 3524, + 3638, 2914, 3523, + 3636, 2919, 3520, + 3633, 2926, 3517, + 3628, 2936, 3513, + 3622, 2948, 3507, + 3614, 2964, 3500, + 3604, 2984, 3489, + 3589, 3011, 3474, + 3568, 3043, 3454, + 3539, 3084, 3426, + 3496, 3132, 3384, + 3432, 3191, 3322, + 3330, 3258, 3224, + 3143, 3335, 3046, + 2623, 3421, 2582, + 0, 3516, 0, + 0, 3618, 0, + 0, 3726, 0, + 3789, 2956, 3630, + 3789, 2956, 3630, + 3789, 2957, 3630, + 3789, 2957, 3630, + 3789, 2957, 3630, + 3789, 2957, 3630, + 3788, 2958, 3630, + 3788, 2958, 3630, + 3788, 2959, 3629, + 3788, 2960, 3629, + 3787, 2961, 3629, + 3787, 2962, 3628, + 3786, 2964, 3627, + 3785, 2967, 3626, + 3784, 2971, 3625, + 3782, 2976, 3623, + 3780, 2982, 3620, + 3777, 2990, 3617, + 3772, 3001, 3613, + 3767, 3015, 3606, + 3759, 3034, 3598, + 3748, 3057, 3587, + 3734, 3087, 3571, + 3714, 3124, 3549, + 3685, 3169, 3518, + 3644, 3222, 3473, + 3583, 3286, 3404, + 3485, 3359, 3292, + 3309, 3441, 3081, + 2855, 3532, 2365, + 0, 3630, 0, + 0, 3736, 0, + 3929, 3025, 3737, + 3929, 3025, 3737, + 3929, 3025, 3737, + 3929, 3025, 3737, + 3929, 3026, 3737, + 3929, 3026, 3737, + 3929, 3026, 3737, + 3929, 3026, 3737, + 3929, 3027, 3737, + 3929, 3028, 3736, + 3928, 3029, 3736, + 3928, 3030, 3736, + 3927, 3032, 3735, + 3927, 3034, 3734, + 3926, 3037, 3733, + 3925, 3042, 3732, + 3923, 3047, 3730, + 3921, 3054, 3727, + 3918, 3064, 3723, + 3913, 3076, 3719, + 3908, 3092, 3712, + 3900, 3113, 3703, + 3890, 3139, 3691, + 3876, 3172, 3674, + 3856, 3213, 3651, + 3828, 3262, 3618, + 3788, 3320, 3569, + 3728, 3388, 3494, + 3634, 3466, 3370, + 3465, 3552, 3123, + 3050, 3647, 1588, + 0, 3749, 0, + 4068, 3103, 3850, + 4068, 3103, 3850, + 4068, 3103, 3850, + 4068, 3103, 3850, + 4068, 3104, 3850, + 4068, 3104, 3850, + 4068, 3104, 3850, + 4068, 3104, 3849, + 4067, 3105, 3849, + 4067, 3105, 3849, + 4067, 3106, 3849, + 4067, 3107, 3849, + 4066, 3109, 3848, + 4066, 3111, 3847, + 4065, 3114, 3847, + 4064, 3117, 3845, + 4063, 3122, 3844, + 4061, 3128, 3842, + 4059, 3136, 3839, + 4056, 3147, 3835, + 4052, 3160, 3830, + 4046, 3178, 3823, + 4039, 3201, 3814, + 4029, 3230, 3801, + 4015, 3266, 3784, + 3995, 3310, 3759, + 3968, 3363, 3724, + 3929, 3425, 3672, + 3870, 3497, 3592, + 3778, 3578, 3457, + 3615, 3668, 3174, + 3224, 3766, 0, + 4095, 3190, 3967, + 4095, 3190, 3967, + 4095, 3190, 3967, + 4095, 3190, 3967, + 4095, 3191, 3967, + 4095, 3191, 3967, + 4095, 3191, 3967, + 4095, 3191, 3966, + 4095, 3192, 3966, + 4095, 3192, 3966, + 4095, 3193, 3966, + 4095, 3194, 3966, + 4095, 3195, 3965, + 4095, 3197, 3965, + 4095, 3199, 3964, + 4095, 3202, 3963, + 4095, 3206, 3962, + 4095, 3211, 3961, + 4095, 3217, 3958, + 4095, 3226, 3956, + 4095, 3238, 3952, + 4095, 3253, 3946, + 4095, 3273, 3939, + 4095, 3297, 3930, + 4095, 3328, 3917, + 4095, 3367, 3898, + 4095, 3414, 3873, + 4095, 3470, 3836, + 4067, 3536, 3782, + 4009, 3611, 3697, + 3919, 3695, 3552, + 3759, 3788, 3235, + 4095, 3285, 4087, + 4095, 3285, 4087, + 4095, 3286, 4087, + 4095, 3286, 4087, + 4095, 3286, 4087, + 4095, 3286, 4087, + 4095, 3286, 4087, + 4095, 3286, 4087, + 4095, 3287, 4087, + 4095, 3287, 4087, + 4095, 3288, 4087, + 4095, 3288, 4086, + 4095, 3289, 4086, + 4095, 3291, 4086, + 4095, 3292, 4085, + 4095, 3295, 4084, + 4095, 3298, 4084, + 4095, 3302, 4082, + 4095, 3308, 4081, + 4095, 3315, 4079, + 4095, 3325, 4076, + 4095, 3337, 4072, + 4095, 3353, 4066, + 4095, 3374, 4059, + 4095, 3401, 4049, + 4095, 3434, 4036, + 4095, 3475, 4017, + 4095, 3524, 3990, + 4095, 3583, 3952, + 4095, 3651, 3896, + 4095, 3729, 3808, + 4057, 3815, 3655, + 0, 2788, 3057, + 0, 2789, 3057, + 0, 2789, 3057, + 0, 2789, 3057, + 0, 2789, 3057, + 0, 2790, 3056, + 0, 2790, 3056, + 0, 2791, 3055, + 0, 2792, 3054, + 0, 2793, 3053, + 0, 2795, 3052, + 0, 2797, 3050, + 0, 2800, 3047, + 0, 2804, 3043, + 0, 2809, 3038, + 0, 2816, 3031, + 0, 2825, 3022, + 0, 2837, 3009, + 0, 2852, 2992, + 0, 2872, 2967, + 0, 2897, 2932, + 0, 2928, 2880, + 0, 2967, 2801, + 0, 3014, 2666, + 0, 3071, 2384, + 0, 3137, 0, + 0, 3212, 0, + 0, 3297, 0, + 0, 3390, 0, + 0, 3490, 0, + 0, 3597, 0, + 0, 3710, 0, + 0, 2788, 3058, + 0, 2789, 3058, + 0, 2789, 3057, + 0, 2789, 3057, + 0, 2789, 3057, + 0, 2790, 3057, + 0, 2790, 3056, + 0, 2791, 3055, + 0, 2792, 3055, + 0, 2793, 3053, + 0, 2795, 3052, + 0, 2797, 3050, + 0, 2800, 3047, + 0, 2804, 3043, + 0, 2809, 3038, + 0, 2816, 3032, + 0, 2825, 3022, + 0, 2837, 3010, + 0, 2852, 2992, + 0, 2872, 2967, + 0, 2897, 2932, + 0, 2928, 2881, + 0, 2967, 2801, + 0, 3014, 2666, + 0, 3071, 2385, + 0, 3137, 0, + 0, 3212, 0, + 0, 3297, 0, + 0, 3390, 0, + 0, 3490, 0, + 0, 3597, 0, + 0, 3710, 0, + 0, 2788, 3058, + 0, 2789, 3058, + 0, 2789, 3058, + 0, 2789, 3057, + 0, 2789, 3057, + 0, 2790, 3057, + 0, 2790, 3056, + 0, 2791, 3056, + 0, 2792, 3055, + 0, 2793, 3054, + 0, 2795, 3052, + 0, 2797, 3050, + 0, 2800, 3047, + 0, 2804, 3044, + 0, 2809, 3039, + 0, 2816, 3032, + 0, 2825, 3023, + 0, 2837, 3010, + 0, 2852, 2992, + 0, 2872, 2968, + 0, 2897, 2933, + 0, 2928, 2881, + 0, 2967, 2801, + 0, 3014, 2667, + 0, 3071, 2386, + 0, 3137, 0, + 0, 3212, 0, + 0, 3297, 0, + 0, 3390, 0, + 0, 3490, 0, + 0, 3597, 0, + 0, 3710, 0, + 0, 2789, 3058, + 0, 2789, 3058, + 0, 2789, 3058, + 0, 2789, 3058, + 0, 2789, 3057, + 0, 2790, 3057, + 0, 2790, 3057, + 0, 2791, 3056, + 0, 2792, 3055, + 0, 2793, 3054, + 0, 2795, 3052, + 0, 2797, 3050, + 0, 2800, 3048, + 0, 2804, 3044, + 0, 2809, 3039, + 0, 2816, 3032, + 0, 2825, 3023, + 0, 2837, 3010, + 0, 2852, 2993, + 0, 2872, 2968, + 0, 2897, 2933, + 0, 2928, 2881, + 0, 2967, 2802, + 0, 3014, 2667, + 0, 3071, 2387, + 0, 3137, 0, + 0, 3212, 0, + 0, 3297, 0, + 0, 3390, 0, + 0, 3490, 0, + 0, 3597, 0, + 0, 3710, 0, + 0, 2789, 3059, + 0, 2789, 3058, + 0, 2789, 3058, + 0, 2789, 3058, + 0, 2789, 3058, + 0, 2790, 3058, + 0, 2790, 3057, + 0, 2791, 3056, + 0, 2792, 3056, + 0, 2793, 3054, + 0, 2795, 3053, + 0, 2797, 3051, + 0, 2800, 3048, + 0, 2804, 3044, + 0, 2809, 3039, + 0, 2816, 3033, + 0, 2825, 3023, + 0, 2837, 3011, + 0, 2852, 2993, + 0, 2872, 2969, + 0, 2897, 2934, + 0, 2928, 2882, + 0, 2967, 2802, + 0, 3014, 2668, + 0, 3071, 2389, + 0, 3137, 0, + 0, 3212, 0, + 0, 3297, 0, + 0, 3390, 0, + 0, 3490, 0, + 0, 3597, 0, + 0, 3710, 0, + 0, 2789, 3059, + 0, 2789, 3059, + 0, 2789, 3059, + 0, 2789, 3059, + 0, 2790, 3058, + 0, 2790, 3058, + 0, 2791, 3058, + 0, 2791, 3057, + 0, 2792, 3056, + 0, 2793, 3055, + 0, 2795, 3053, + 0, 2797, 3051, + 0, 2800, 3049, + 0, 2804, 3045, + 0, 2809, 3040, + 0, 2816, 3033, + 0, 2825, 3024, + 0, 2837, 3011, + 0, 2852, 2994, + 0, 2872, 2969, + 0, 2897, 2934, + 0, 2928, 2883, + 0, 2967, 2803, + 0, 3014, 2670, + 0, 3071, 2391, + 0, 3137, 0, + 0, 3212, 0, + 0, 3297, 0, + 0, 3390, 0, + 0, 3490, 0, + 0, 3597, 0, + 0, 3710, 0, + 0, 2789, 3060, + 0, 2789, 3060, + 0, 2789, 3060, + 0, 2789, 3059, + 0, 2790, 3059, + 0, 2790, 3059, + 0, 2791, 3058, + 0, 2791, 3058, + 0, 2792, 3057, + 0, 2794, 3056, + 0, 2795, 3054, + 0, 2797, 3052, + 0, 2800, 3049, + 0, 2804, 3046, + 0, 2810, 3041, + 0, 2816, 3034, + 0, 2825, 3025, + 0, 2837, 3012, + 0, 2852, 2995, + 0, 2872, 2970, + 0, 2897, 2935, + 0, 2928, 2884, + 0, 2967, 2805, + 0, 3015, 2671, + 0, 3071, 2394, + 0, 3137, 0, + 0, 3212, 0, + 0, 3297, 0, + 0, 3390, 0, + 0, 3490, 0, + 0, 3597, 0, + 0, 3710, 0, + 0, 2789, 3061, + 0, 2789, 3061, + 0, 2789, 3061, + 0, 2790, 3060, + 0, 2790, 3060, + 0, 2790, 3060, + 0, 2791, 3059, + 0, 2792, 3059, + 0, 2793, 3058, + 0, 2794, 3057, + 0, 2795, 3055, + 0, 2798, 3053, + 0, 2801, 3050, + 0, 2805, 3047, + 0, 2810, 3042, + 0, 2817, 3035, + 0, 2826, 3026, + 0, 2837, 3013, + 0, 2853, 2996, + 0, 2872, 2971, + 0, 2897, 2936, + 0, 2929, 2885, + 0, 2967, 2806, + 0, 3015, 2673, + 0, 3071, 2398, + 0, 3137, 0, + 0, 3212, 0, + 0, 3297, 0, + 0, 3390, 0, + 0, 3491, 0, + 0, 3597, 0, + 0, 3710, 0, + 0, 2790, 3062, + 0, 2790, 3062, + 0, 2790, 3062, + 0, 2790, 3062, + 0, 2790, 3061, + 0, 2791, 3061, + 0, 2791, 3060, + 0, 2792, 3060, + 0, 2793, 3059, + 0, 2794, 3058, + 0, 2796, 3056, + 0, 2798, 3054, + 0, 2801, 3052, + 0, 2805, 3048, + 0, 2810, 3043, + 0, 2817, 3036, + 0, 2826, 3027, + 0, 2838, 3014, + 0, 2853, 2997, + 0, 2872, 2973, + 0, 2897, 2938, + 0, 2929, 2887, + 0, 2968, 2809, + 0, 3015, 2676, + 0, 3071, 2404, + 0, 3137, 0, + 0, 3213, 0, + 0, 3297, 0, + 0, 3390, 0, + 0, 3491, 0, + 0, 3598, 0, + 0, 3710, 0, + 0, 2790, 3064, + 0, 2790, 3064, + 0, 2790, 3063, + 0, 2790, 3063, + 0, 2791, 3063, + 0, 2791, 3063, + 0, 2792, 3062, + 0, 2792, 3062, + 0, 2793, 3061, + 0, 2795, 3060, + 0, 2796, 3058, + 0, 2798, 3056, + 0, 2801, 3053, + 0, 2805, 3050, + 0, 2810, 3045, + 0, 2817, 3038, + 0, 2826, 3029, + 0, 2838, 3016, + 0, 2853, 2999, + 0, 2873, 2975, + 0, 2898, 2940, + 0, 2929, 2890, + 0, 2968, 2811, + 0, 3015, 2680, + 0, 3072, 2411, + 0, 3137, 0, + 0, 3213, 0, + 0, 3297, 0, + 0, 3390, 0, + 0, 3491, 0, + 0, 3598, 0, + 0, 3710, 0, + 0, 2791, 3066, + 0, 2791, 3066, + 0, 2791, 3066, + 0, 2791, 3065, + 0, 2791, 3065, + 0, 2792, 3065, + 0, 2792, 3064, + 0, 2793, 3064, + 0, 2794, 3063, + 0, 2795, 3062, + 0, 2797, 3060, + 0, 2799, 3058, + 0, 2802, 3056, + 0, 2806, 3052, + 0, 2811, 3047, + 0, 2818, 3040, + 0, 2827, 3031, + 0, 2838, 3019, + 0, 2854, 3002, + 0, 2873, 2978, + 0, 2898, 2943, + 0, 2930, 2893, + 0, 2968, 2815, + 0, 3016, 2685, + 0, 3072, 2420, + 0, 3138, 0, + 0, 3213, 0, + 0, 3297, 0, + 0, 3390, 0, + 0, 3491, 0, + 0, 3598, 0, + 0, 3710, 0, + 0, 2791, 3069, + 0, 2791, 3069, + 0, 2792, 3069, + 0, 2792, 3068, + 0, 2792, 3068, + 0, 2792, 3068, + 0, 2793, 3067, + 0, 2794, 3067, + 0, 2795, 3066, + 0, 2796, 3065, + 0, 2798, 3063, + 0, 2800, 3061, + 0, 2803, 3059, + 0, 2807, 3055, + 0, 2812, 3050, + 0, 2819, 3043, + 0, 2827, 3034, + 0, 2839, 3022, + 0, 2854, 3005, + 0, 2874, 2981, + 0, 2899, 2947, + 0, 2930, 2897, + 0, 2969, 2821, + 0, 3016, 2692, + 0, 3072, 2432, + 0, 3138, 0, + 0, 3213, 0, + 0, 3298, 0, + 0, 3391, 0, + 0, 3491, 0, + 0, 3598, 0, + 0, 3710, 0, + 0, 2792, 3073, + 0, 2792, 3073, + 0, 2793, 3073, + 0, 2793, 3072, + 0, 2793, 3072, + 0, 2793, 3072, + 0, 2794, 3071, + 0, 2795, 3071, + 0, 2796, 3070, + 0, 2797, 3069, + 0, 2799, 3067, + 0, 2801, 3065, + 0, 2804, 3063, + 0, 2808, 3059, + 0, 2813, 3054, + 0, 2819, 3048, + 0, 2828, 3039, + 0, 2840, 3026, + 0, 2855, 3010, + 0, 2875, 2986, + 0, 2900, 2952, + 0, 2931, 2903, + 0, 2970, 2827, + 0, 3017, 2701, + 0, 3073, 2448, + 0, 3138, 0, + 0, 3214, 0, + 0, 3298, 0, + 0, 3391, 0, + 0, 3491, 0, + 0, 3598, 0, + 0, 3710, 0, + 0, 2794, 3078, + 0, 2794, 3078, + 0, 2794, 3078, + 0, 2794, 3078, + 0, 2794, 3077, + 0, 2795, 3077, + 0, 2795, 3077, + 0, 2796, 3076, + 0, 2797, 3075, + 0, 2798, 3074, + 0, 2800, 3073, + 0, 2802, 3071, + 0, 2805, 3068, + 0, 2809, 3064, + 0, 2814, 3060, + 0, 2821, 3053, + 0, 2830, 3044, + 0, 2841, 3032, + 0, 2856, 3016, + 0, 2876, 2992, + 0, 2901, 2959, + 0, 2932, 2911, + 0, 2970, 2836, + 0, 3017, 2713, + 0, 3074, 2468, + 0, 3139, 1070, + 0, 3214, 0, + 0, 3298, 0, + 0, 3391, 0, + 0, 3491, 0, + 0, 3598, 0, + 0, 3710, 0, + 0, 2795, 3085, + 0, 2796, 3085, + 0, 2796, 3085, + 0, 2796, 3085, + 0, 2796, 3084, + 0, 2797, 3084, + 0, 2797, 3084, + 0, 2798, 3083, + 0, 2799, 3082, + 0, 2800, 3081, + 0, 2802, 3080, + 0, 2804, 3078, + 0, 2807, 3075, + 0, 2811, 3072, + 0, 2816, 3067, + 0, 2822, 3060, + 0, 2831, 3052, + 0, 2843, 3040, + 0, 2858, 3023, + 0, 2877, 3001, + 0, 2902, 2968, + 0, 2933, 2920, + 0, 2972, 2848, + 0, 3019, 2728, + 0, 3075, 2494, + 0, 3140, 1443, + 0, 3215, 0, + 0, 3299, 0, + 0, 3392, 0, + 0, 3492, 0, + 0, 3599, 0, + 0, 3711, 0, + 0, 2798, 3094, + 0, 2798, 3094, + 0, 2798, 3094, + 0, 2798, 3094, + 0, 2799, 3093, + 0, 2799, 3093, + 0, 2800, 3093, + 0, 2800, 3092, + 0, 2801, 3091, + 0, 2802, 3090, + 0, 2804, 3089, + 0, 2806, 3087, + 0, 2809, 3084, + 0, 2813, 3081, + 0, 2818, 3076, + 0, 2825, 3070, + 0, 2834, 3062, + 0, 2845, 3050, + 0, 2860, 3034, + 0, 2879, 3011, + 0, 2904, 2980, + 0, 2935, 2933, + 0, 2973, 2863, + 0, 3020, 2748, + 0, 3076, 2527, + 0, 3141, 1697, + 0, 3216, 0, + 0, 3300, 0, + 0, 3392, 0, + 0, 3492, 0, + 0, 3599, 0, + 0, 3711, 0, + 0, 2801, 3106, + 0, 2801, 3106, + 0, 2801, 3106, + 0, 2802, 3106, + 0, 2802, 3105, + 0, 2802, 3105, + 0, 2803, 3105, + 0, 2803, 3104, + 0, 2804, 3103, + 0, 2806, 3102, + 0, 2807, 3101, + 0, 2809, 3099, + 0, 2812, 3096, + 0, 2816, 3093, + 0, 2821, 3089, + 0, 2828, 3083, + 0, 2837, 3074, + 0, 2848, 3063, + 0, 2863, 3047, + 0, 2882, 3026, + 0, 2907, 2995, + 0, 2937, 2950, + 0, 2976, 2883, + 0, 3022, 2773, + 0, 3078, 2567, + 0, 3143, 1902, + 0, 3217, 0, + 0, 3301, 0, + 0, 3393, 0, + 0, 3493, 0, + 0, 3599, 0, + 0, 3711, 0, + 0, 2805, 3121, + 0, 2805, 3121, + 0, 2806, 3121, + 0, 2806, 3121, + 0, 2806, 3121, + 0, 2806, 3120, + 0, 2807, 3120, + 0, 2808, 3119, + 0, 2809, 3119, + 0, 2810, 3118, + 0, 2811, 3116, + 0, 2814, 3115, + 0, 2816, 3112, + 0, 2820, 3109, + 0, 2825, 3105, + 0, 2832, 3099, + 0, 2840, 3091, + 0, 2852, 3080, + 0, 2867, 3065, + 0, 2886, 3044, + 0, 2910, 3014, + 0, 2940, 2972, + 0, 2978, 2908, + 0, 3025, 2805, + 0, 3080, 2615, + 0, 3145, 2083, + 0, 3219, 0, + 0, 3302, 0, + 0, 3394, 0, + 0, 3494, 0, + 0, 3600, 0, + 0, 3712, 0, + 0, 2811, 3141, + 0, 2811, 3141, + 0, 2811, 3141, + 0, 2811, 3141, + 0, 2812, 3141, + 0, 2812, 3140, + 0, 2813, 3140, + 0, 2813, 3139, + 0, 2814, 3139, + 0, 2815, 3138, + 0, 2817, 3136, + 0, 2819, 3135, + 0, 2822, 3132, + 0, 2826, 3129, + 0, 2831, 3125, + 0, 2837, 3120, + 0, 2846, 3112, + 0, 2857, 3101, + 0, 2872, 3087, + 0, 2890, 3067, + 0, 2914, 3039, + 0, 2945, 2999, + 0, 2982, 2939, + 0, 3028, 2843, + 0, 3083, 2673, + 0, 3147, 2248, + 0, 3221, 0, + 0, 3304, 0, + 0, 3396, 0, + 0, 3495, 0, + 0, 3601, 0, + 0, 3713, 0, + 1321, 2818, 3166, + 1314, 2818, 3166, + 1305, 2819, 3166, + 1292, 2819, 3166, + 1275, 2819, 3166, + 1251, 2819, 3165, + 1216, 2820, 3165, + 1165, 2821, 3165, + 1087, 2821, 3164, + 956, 2823, 3163, + 686, 2824, 3162, + 0, 2826, 3160, + 0, 2829, 3158, + 0, 2833, 3155, + 0, 2838, 3151, + 0, 2844, 3146, + 0, 2853, 3139, + 0, 2864, 3129, + 0, 2878, 3115, + 0, 2897, 3097, + 0, 2920, 3071, + 0, 2950, 3033, + 0, 2987, 2978, + 0, 3033, 2891, + 0, 3087, 2740, + 0, 3151, 2403, + 0, 3224, 0, + 0, 3307, 0, + 0, 3398, 0, + 0, 3497, 0, + 0, 3603, 0, + 0, 3714, 0, + 2324, 2828, 3198, + 2323, 2828, 3198, + 2322, 2828, 3198, + 2321, 2828, 3198, + 2319, 2829, 3197, + 2317, 2829, 3197, + 2314, 2830, 3197, + 2309, 2830, 3196, + 2304, 2831, 3196, + 2296, 2832, 3195, + 2285, 2834, 3194, + 2270, 2836, 3192, + 2249, 2839, 3190, + 2220, 2842, 3188, + 2178, 2847, 3184, + 2115, 2853, 3179, + 2013, 2862, 3172, + 1828, 2872, 3163, + 1321, 2887, 3151, + 0, 2905, 3134, + 0, 2928, 3109, + 0, 2957, 3075, + 0, 2994, 3025, + 0, 3039, 2947, + 0, 3092, 2817, + 0, 3156, 2552, + 0, 3228, 0, + 0, 3310, 0, + 0, 3401, 0, + 0, 3499, 0, + 0, 3604, 0, + 0, 3715, 0, + 2680, 2841, 3237, + 2680, 2841, 3237, + 2680, 2841, 3237, + 2679, 2841, 3237, + 2678, 2841, 3237, + 2677, 2842, 3236, + 2676, 2842, 3236, + 2674, 2843, 3236, + 2671, 2844, 3235, + 2668, 2845, 3234, + 2663, 2846, 3233, + 2657, 2848, 3232, + 2648, 2851, 3230, + 2636, 2854, 3228, + 2620, 2859, 3224, + 2597, 2865, 3220, + 2564, 2873, 3214, + 2516, 2884, 3205, + 2444, 2898, 3194, + 2324, 2915, 3178, + 2088, 2938, 3157, + 1008, 2967, 3126, + 0, 3003, 3081, + 0, 3047, 3013, + 0, 3100, 2903, + 0, 3162, 2696, + 0, 3233, 2020, + 0, 3315, 0, + 0, 3404, 0, + 0, 3502, 0, + 0, 3607, 0, + 0, 3717, 0, + 2929, 2857, 3285, + 2929, 2857, 3285, + 2928, 2857, 3285, + 2928, 2858, 3284, + 2927, 2858, 3284, + 2927, 2858, 3284, + 2926, 2859, 3284, + 2925, 2859, 3283, + 2923, 2860, 3283, + 2921, 2861, 3282, + 2919, 2863, 3281, + 2915, 2864, 3280, + 2910, 2867, 3278, + 2903, 2870, 3276, + 2894, 2875, 3273, + 2882, 2881, 3269, + 2865, 2889, 3264, + 2841, 2899, 3256, + 2807, 2912, 3246, + 2757, 2929, 3232, + 2680, 2952, 3213, + 2551, 2980, 3186, + 2289, 3014, 3147, + 0, 3057, 3089, + 0, 3109, 2997, + 0, 3170, 2837, + 0, 3240, 2456, + 0, 3320, 0, + 0, 3409, 0, + 0, 3506, 0, + 0, 3610, 0, + 0, 3719, 0, + 3132, 2878, 3341, + 3132, 2878, 3341, + 3131, 2878, 3341, + 3131, 2879, 3341, + 3131, 2879, 3341, + 3130, 2879, 3341, + 3130, 2880, 3341, + 3129, 2880, 3340, + 3128, 2881, 3340, + 3127, 2882, 3339, + 3125, 2883, 3338, + 3123, 2885, 3337, + 3120, 2888, 3336, + 3116, 2891, 3334, + 3110, 2895, 3331, + 3102, 2901, 3328, + 3092, 2908, 3323, + 3077, 2918, 3316, + 3057, 2931, 3307, + 3029, 2947, 3295, + 2989, 2969, 3279, + 2928, 2996, 3255, + 2832, 3029, 3222, + 2659, 3071, 3173, + 2222, 3121, 3099, + 0, 3181, 2975, + 0, 3250, 2729, + 0, 3328, 1243, + 0, 3415, 0, + 0, 3511, 0, + 0, 3614, 0, + 0, 3723, 0, + 3310, 2905, 3408, + 3310, 2905, 3408, + 3310, 2905, 3408, + 3310, 2905, 3407, + 3310, 2906, 3407, + 3309, 2906, 3407, + 3309, 2906, 3407, + 3309, 2907, 3407, + 3308, 2907, 3406, + 3307, 2908, 3406, + 3306, 2910, 3405, + 3304, 2911, 3404, + 3302, 2914, 3403, + 3300, 2917, 3401, + 3296, 2921, 3399, + 3291, 2926, 3396, + 3284, 2933, 3392, + 3274, 2943, 3386, + 3262, 2955, 3378, + 3244, 2970, 3368, + 3219, 2991, 3354, + 3183, 3016, 3334, + 3131, 3049, 3306, + 3050, 3089, 3266, + 2912, 3137, 3207, + 2620, 3195, 3112, + 0, 3262, 2944, + 0, 3338, 2528, + 0, 3424, 0, + 0, 3518, 0, + 0, 3619, 0, + 0, 3727, 0, + 3474, 2938, 3483, + 3474, 2938, 3483, + 3474, 2939, 3483, + 3474, 2939, 3483, + 3474, 2939, 3483, + 3474, 2939, 3483, + 3474, 2940, 3483, + 3473, 2940, 3483, + 3473, 2941, 3482, + 3472, 2942, 3482, + 3471, 2943, 3481, + 3470, 2944, 3480, + 3469, 2947, 3479, + 3467, 2949, 3478, + 3464, 2953, 3476, + 3461, 2958, 3473, + 3456, 2965, 3470, + 3450, 2973, 3465, + 3441, 2985, 3459, + 3429, 3000, 3450, + 3413, 3019, 3438, + 3390, 3043, 3422, + 3357, 3073, 3399, + 3310, 3111, 3367, + 3237, 3157, 3320, + 3117, 3213, 3248, + 2883, 3277, 3129, + 1820, 3351, 2898, + 0, 3435, 1907, + 0, 3527, 0, + 0, 3626, 0, + 0, 3732, 0, + 3629, 2980, 3568, + 3629, 2980, 3568, + 3629, 2980, 3568, + 3629, 2980, 3568, + 3629, 2980, 3568, + 3629, 2980, 3568, + 3628, 2981, 3568, + 3628, 2981, 3568, + 3628, 2982, 3567, + 3627, 2983, 3567, + 3627, 2984, 3566, + 3626, 2985, 3566, + 3625, 2987, 3565, + 3624, 2990, 3564, + 3622, 2993, 3562, + 3619, 2998, 3560, + 3616, 3004, 3557, + 3612, 3012, 3553, + 3605, 3022, 3548, + 3597, 3036, 3541, + 3586, 3053, 3531, + 3570, 3076, 3518, + 3549, 3104, 3500, + 3518, 3140, 3474, + 3474, 3183, 3437, + 3406, 3235, 3382, + 3297, 3297, 3297, + 3092, 3368, 3151, + 2441, 3449, 2828, + 0, 3538, 0, + 0, 3636, 0, + 0, 3740, 0, + 3777, 3029, 3662, + 3777, 3029, 3662, + 3777, 3030, 3662, + 3777, 3030, 3661, + 3777, 3030, 3661, + 3777, 3030, 3661, + 3777, 3030, 3661, + 3777, 3031, 3661, + 3776, 3031, 3661, + 3776, 3032, 3660, + 3776, 3033, 3660, + 3775, 3034, 3660, + 3774, 3036, 3659, + 3773, 3038, 3658, + 3772, 3042, 3657, + 3770, 3046, 3655, + 3768, 3051, 3652, + 3765, 3058, 3649, + 3760, 3068, 3645, + 3754, 3080, 3639, + 3747, 3096, 3632, + 3736, 3117, 3621, + 3721, 3143, 3606, + 3700, 3175, 3586, + 3671, 3216, 3558, + 3628, 3265, 3516, + 3564, 3323, 3455, + 3462, 3390, 3356, + 3275, 3467, 3178, + 2755, 3554, 2715, + 0, 3648, 0, + 0, 3750, 0, + 3921, 3088, 3762, + 3921, 3088, 3762, + 3921, 3089, 3762, + 3921, 3089, 3762, + 3921, 3089, 3762, + 3921, 3089, 3762, + 3921, 3089, 3762, + 3921, 3090, 3762, + 3920, 3090, 3762, + 3920, 3091, 3761, + 3920, 3092, 3761, + 3919, 3093, 3761, + 3919, 3094, 3760, + 3918, 3096, 3759, + 3917, 3099, 3758, + 3916, 3103, 3757, + 3914, 3108, 3755, + 3912, 3114, 3753, + 3909, 3122, 3749, + 3905, 3133, 3745, + 3899, 3148, 3738, + 3891, 3166, 3730, + 3881, 3189, 3719, + 3866, 3219, 3703, + 3846, 3256, 3681, + 3817, 3301, 3650, + 3776, 3355, 3605, + 3715, 3418, 3536, + 3617, 3491, 3424, + 3441, 3573, 3213, + 2987, 3664, 2497, + 0, 3762, 0, + 4062, 3157, 3869, + 4062, 3157, 3869, + 4062, 3157, 3869, + 4062, 3157, 3869, + 4062, 3157, 3869, + 4061, 3158, 3869, + 4061, 3158, 3869, + 4061, 3158, 3869, + 4061, 3159, 3869, + 4061, 3159, 3869, + 4061, 3160, 3869, + 4060, 3161, 3868, + 4060, 3162, 3868, + 4060, 3164, 3867, + 4059, 3166, 3866, + 4058, 3169, 3865, + 4057, 3174, 3864, + 4055, 3179, 3862, + 4053, 3186, 3859, + 4050, 3196, 3856, + 4045, 3208, 3851, + 4040, 3224, 3844, + 4032, 3245, 3835, + 4022, 3271, 3823, + 4008, 3304, 3806, + 3988, 3345, 3783, + 3960, 3394, 3750, + 3920, 3452, 3701, + 3860, 3520, 3626, + 3766, 3598, 3502, + 3598, 3684, 3255, + 3182, 3779, 1720, + 4095, 3235, 3982, + 4095, 3235, 3982, + 4095, 3235, 3982, + 4095, 3235, 3982, + 4095, 3235, 3982, + 4095, 3236, 3982, + 4095, 3236, 3982, + 4095, 3236, 3982, + 4095, 3236, 3982, + 4095, 3237, 3981, + 4095, 3238, 3981, + 4095, 3238, 3981, + 4095, 3239, 3981, + 4095, 3241, 3980, + 4095, 3243, 3979, + 4095, 3246, 3979, + 4095, 3249, 3978, + 4095, 3254, 3976, + 4095, 3260, 3974, + 4095, 3268, 3971, + 4095, 3279, 3967, + 4095, 3293, 3962, + 4095, 3310, 3956, + 4095, 3333, 3946, + 4095, 3362, 3934, + 4095, 3398, 3916, + 4095, 3442, 3891, + 4095, 3495, 3856, + 4061, 3557, 3804, + 4002, 3629, 3724, + 3910, 3710, 3589, + 3747, 3800, 3306, + 4095, 3322, 4095, + 4095, 3322, 4095, + 4095, 3322, 4095, + 4095, 3322, 4095, + 4095, 3322, 4095, + 4095, 3323, 4095, + 4095, 3323, 4095, + 4095, 3323, 4095, + 4095, 3323, 4095, + 4095, 3324, 4095, + 4095, 3324, 4095, + 4095, 3325, 4095, + 4095, 3326, 4095, + 4095, 3327, 4095, + 4095, 3329, 4095, + 4095, 3331, 4095, + 4095, 3334, 4095, + 4095, 3338, 4094, + 4095, 3343, 4093, + 4095, 3350, 4090, + 4095, 3358, 4088, + 4095, 3370, 4084, + 4095, 3385, 4079, + 4095, 3405, 4071, + 4095, 3429, 4062, + 4095, 3461, 4049, + 4095, 3499, 4030, + 4095, 3546, 4005, + 4095, 3602, 3968, + 4095, 3668, 3914, + 4095, 3743, 3829, + 4051, 3827, 3684, + 0, 2920, 3190, + 0, 2920, 3189, + 0, 2921, 3189, + 0, 2921, 3189, + 0, 2921, 3189, + 0, 2921, 3189, + 0, 2922, 3188, + 0, 2922, 3188, + 0, 2923, 3187, + 0, 2924, 3186, + 0, 2925, 3185, + 0, 2927, 3184, + 0, 2929, 3182, + 0, 2932, 3179, + 0, 2936, 3175, + 0, 2941, 3170, + 0, 2948, 3163, + 0, 2957, 3154, + 0, 2969, 3141, + 0, 2984, 3124, + 0, 3004, 3099, + 0, 3029, 3064, + 0, 3060, 3012, + 0, 3099, 2932, + 0, 3146, 2798, + 0, 3203, 2515, + 0, 3269, 0, + 0, 3344, 0, + 0, 3429, 0, + 0, 3522, 0, + 0, 3622, 0, + 0, 3729, 0, + 0, 2920, 3190, + 0, 2920, 3190, + 0, 2921, 3189, + 0, 2921, 3189, + 0, 2921, 3189, + 0, 2921, 3189, + 0, 2922, 3189, + 0, 2922, 3188, + 0, 2923, 3187, + 0, 2924, 3187, + 0, 2925, 3185, + 0, 2927, 3184, + 0, 2929, 3182, + 0, 2932, 3179, + 0, 2936, 3175, + 0, 2941, 3170, + 0, 2948, 3163, + 0, 2957, 3154, + 0, 2969, 3142, + 0, 2984, 3124, + 0, 3004, 3099, + 0, 3029, 3064, + 0, 3060, 3013, + 0, 3099, 2933, + 0, 3146, 2798, + 0, 3203, 2516, + 0, 3269, 0, + 0, 3344, 0, + 0, 3429, 0, + 0, 3522, 0, + 0, 3622, 0, + 0, 3729, 0, + 0, 2920, 3190, + 0, 2921, 3190, + 0, 2921, 3190, + 0, 2921, 3189, + 0, 2921, 3189, + 0, 2921, 3189, + 0, 2922, 3189, + 0, 2922, 3188, + 0, 2923, 3188, + 0, 2924, 3187, + 0, 2925, 3186, + 0, 2927, 3184, + 0, 2929, 3182, + 0, 2932, 3179, + 0, 2936, 3176, + 0, 2941, 3170, + 0, 2948, 3164, + 0, 2957, 3154, + 0, 2969, 3142, + 0, 2984, 3124, + 0, 3004, 3100, + 0, 3029, 3064, + 0, 3060, 3013, + 0, 3099, 2933, + 0, 3146, 2798, + 0, 3203, 2517, + 0, 3269, 0, + 0, 3344, 0, + 0, 3429, 0, + 0, 3522, 0, + 0, 3622, 0, + 0, 3729, 0, + 0, 2920, 3190, + 0, 2921, 3190, + 0, 2921, 3190, + 0, 2921, 3190, + 0, 2921, 3190, + 0, 2921, 3189, + 0, 2922, 3189, + 0, 2922, 3188, + 0, 2923, 3188, + 0, 2924, 3187, + 0, 2925, 3186, + 0, 2927, 3184, + 0, 2929, 3182, + 0, 2932, 3179, + 0, 2936, 3176, + 0, 2941, 3171, + 0, 2948, 3164, + 0, 2957, 3155, + 0, 2969, 3142, + 0, 2984, 3124, + 0, 3004, 3100, + 0, 3029, 3065, + 0, 3060, 3013, + 0, 3099, 2933, + 0, 3146, 2799, + 0, 3203, 2518, + 0, 3269, 0, + 0, 3344, 0, + 0, 3429, 0, + 0, 3522, 0, + 0, 3622, 0, + 0, 3729, 0, + 0, 2921, 3190, + 0, 2921, 3190, + 0, 2921, 3190, + 0, 2921, 3190, + 0, 2921, 3190, + 0, 2921, 3190, + 0, 2922, 3189, + 0, 2922, 3189, + 0, 2923, 3188, + 0, 2924, 3187, + 0, 2925, 3186, + 0, 2927, 3185, + 0, 2929, 3183, + 0, 2932, 3180, + 0, 2936, 3176, + 0, 2941, 3171, + 0, 2948, 3164, + 0, 2957, 3155, + 0, 2969, 3142, + 0, 2984, 3125, + 0, 3004, 3100, + 0, 3029, 3065, + 0, 3060, 3014, + 0, 3099, 2934, + 0, 3146, 2799, + 0, 3203, 2519, + 0, 3269, 0, + 0, 3344, 0, + 0, 3429, 0, + 0, 3522, 0, + 0, 3622, 0, + 0, 3729, 0, + 0, 2921, 3191, + 0, 2921, 3191, + 0, 2921, 3191, + 0, 2921, 3190, + 0, 2921, 3190, + 0, 2922, 3190, + 0, 2922, 3190, + 0, 2922, 3189, + 0, 2923, 3188, + 0, 2924, 3188, + 0, 2925, 3187, + 0, 2927, 3185, + 0, 2929, 3183, + 0, 2932, 3180, + 0, 2936, 3176, + 0, 2941, 3171, + 0, 2948, 3165, + 0, 2957, 3155, + 0, 2969, 3143, + 0, 2984, 3125, + 0, 3004, 3101, + 0, 3029, 3066, + 0, 3060, 3014, + 0, 3099, 2935, + 0, 3146, 2800, + 0, 3203, 2521, + 0, 3269, 0, + 0, 3344, 0, + 0, 3429, 0, + 0, 3522, 0, + 0, 3622, 0, + 0, 3729, 0, + 0, 2921, 3191, + 0, 2921, 3191, + 0, 2921, 3191, + 0, 2921, 3191, + 0, 2921, 3191, + 0, 2922, 3190, + 0, 2922, 3190, + 0, 2923, 3190, + 0, 2923, 3189, + 0, 2924, 3188, + 0, 2925, 3187, + 0, 2927, 3186, + 0, 2929, 3183, + 0, 2932, 3181, + 0, 2936, 3177, + 0, 2941, 3172, + 0, 2948, 3165, + 0, 2957, 3156, + 0, 2969, 3143, + 0, 2984, 3126, + 0, 3004, 3101, + 0, 3029, 3066, + 0, 3060, 3015, + 0, 3099, 2936, + 0, 3147, 2802, + 0, 3203, 2523, + 0, 3269, 0, + 0, 3344, 0, + 0, 3429, 0, + 0, 3522, 0, + 0, 3623, 0, + 0, 3729, 0, + 0, 2921, 3192, + 0, 2921, 3192, + 0, 2921, 3192, + 0, 2921, 3192, + 0, 2922, 3191, + 0, 2922, 3191, + 0, 2922, 3191, + 0, 2923, 3190, + 0, 2923, 3190, + 0, 2924, 3189, + 0, 2926, 3188, + 0, 2927, 3186, + 0, 2930, 3184, + 0, 2933, 3181, + 0, 2936, 3178, + 0, 2942, 3173, + 0, 2948, 3166, + 0, 2957, 3157, + 0, 2969, 3144, + 0, 2984, 3127, + 0, 3004, 3102, + 0, 3029, 3067, + 0, 3061, 3016, + 0, 3099, 2937, + 0, 3147, 2803, + 0, 3203, 2526, + 0, 3269, 0, + 0, 3344, 0, + 0, 3429, 0, + 0, 3522, 0, + 0, 3623, 0, + 0, 3730, 0, + 0, 2921, 3193, + 0, 2921, 3193, + 0, 2921, 3193, + 0, 2922, 3193, + 0, 2922, 3192, + 0, 2922, 3192, + 0, 2922, 3192, + 0, 2923, 3191, + 0, 2924, 3191, + 0, 2925, 3190, + 0, 2926, 3189, + 0, 2928, 3187, + 0, 2930, 3185, + 0, 2933, 3182, + 0, 2937, 3179, + 0, 2942, 3174, + 0, 2949, 3167, + 0, 2958, 3158, + 0, 2969, 3145, + 0, 2985, 3128, + 0, 3004, 3103, + 0, 3029, 3069, + 0, 3061, 3017, + 0, 3100, 2938, + 0, 3147, 2806, + 0, 3203, 2530, + 0, 3269, 0, + 0, 3345, 0, + 0, 3429, 0, + 0, 3522, 0, + 0, 3623, 0, + 0, 3730, 0, + 0, 2922, 3194, + 0, 2922, 3194, + 0, 2922, 3194, + 0, 2922, 3194, + 0, 2922, 3194, + 0, 2922, 3193, + 0, 2923, 3193, + 0, 2923, 3193, + 0, 2924, 3192, + 0, 2925, 3191, + 0, 2926, 3190, + 0, 2928, 3188, + 0, 2930, 3186, + 0, 2933, 3184, + 0, 2937, 3180, + 0, 2942, 3175, + 0, 2949, 3168, + 0, 2958, 3159, + 0, 2970, 3147, + 0, 2985, 3129, + 0, 3005, 3105, + 0, 3030, 3070, + 0, 3061, 3019, + 0, 3100, 2941, + 0, 3147, 2808, + 0, 3203, 2536, + 0, 3269, 0, + 0, 3345, 0, + 0, 3429, 0, + 0, 3522, 0, + 0, 3623, 0, + 0, 3730, 0, + 0, 2922, 3196, + 0, 2922, 3196, + 0, 2922, 3196, + 0, 2922, 3196, + 0, 2923, 3195, + 0, 2923, 3195, + 0, 2923, 3195, + 0, 2924, 3194, + 0, 2924, 3194, + 0, 2925, 3193, + 0, 2927, 3192, + 0, 2928, 3190, + 0, 2931, 3188, + 0, 2933, 3185, + 0, 2937, 3182, + 0, 2943, 3177, + 0, 2949, 3170, + 0, 2958, 3161, + 0, 2970, 3148, + 0, 2985, 3131, + 0, 3005, 3107, + 0, 3030, 3072, + 0, 3061, 3022, + 0, 3100, 2944, + 0, 3147, 2812, + 0, 3204, 2543, + 0, 3269, 0, + 0, 3345, 0, + 0, 3429, 0, + 0, 3522, 0, + 0, 3623, 0, + 0, 3730, 0, + 0, 2923, 3198, + 0, 2923, 3198, + 0, 2923, 3198, + 0, 2923, 3198, + 0, 2923, 3198, + 0, 2923, 3197, + 0, 2924, 3197, + 0, 2924, 3197, + 0, 2925, 3196, + 0, 2926, 3195, + 0, 2927, 3194, + 0, 2929, 3192, + 0, 2931, 3190, + 0, 2934, 3188, + 0, 2938, 3184, + 0, 2943, 3179, + 0, 2950, 3172, + 0, 2959, 3163, + 0, 2971, 3151, + 0, 2986, 3134, + 0, 3005, 3110, + 0, 3030, 3075, + 0, 3062, 3025, + 0, 3100, 2947, + 0, 3148, 2818, + 0, 3204, 2552, + 0, 3270, 0, + 0, 3345, 0, + 0, 3430, 0, + 0, 3522, 0, + 0, 3623, 0, + 0, 3730, 0, + 0, 2923, 3201, + 0, 2923, 3201, + 0, 2924, 3201, + 0, 2924, 3201, + 0, 2924, 3201, + 0, 2924, 3200, + 0, 2925, 3200, + 0, 2925, 3200, + 0, 2926, 3199, + 0, 2927, 3198, + 0, 2928, 3197, + 0, 2930, 3195, + 0, 2932, 3193, + 0, 2935, 3191, + 0, 2939, 3187, + 0, 2944, 3182, + 0, 2951, 3176, + 0, 2960, 3167, + 0, 2971, 3154, + 0, 2986, 3137, + 0, 3006, 3113, + 0, 3031, 3079, + 0, 3062, 3029, + 0, 3101, 2953, + 0, 3148, 2824, + 0, 3204, 2564, + 0, 3270, 0, + 0, 3345, 0, + 0, 3430, 0, + 0, 3523, 0, + 0, 3623, 0, + 0, 3730, 0, + 0, 2924, 3205, + 0, 2924, 3205, + 0, 2925, 3205, + 0, 2925, 3205, + 0, 2925, 3205, + 0, 2925, 3204, + 0, 2926, 3204, + 0, 2926, 3203, + 0, 2927, 3203, + 0, 2928, 3202, + 0, 2929, 3201, + 0, 2931, 3199, + 0, 2933, 3197, + 0, 2936, 3195, + 0, 2940, 3191, + 0, 2945, 3186, + 0, 2952, 3180, + 0, 2961, 3171, + 0, 2972, 3159, + 0, 2987, 3142, + 0, 3007, 3118, + 0, 3032, 3084, + 0, 3063, 3035, + 0, 3102, 2959, + 0, 3149, 2833, + 0, 3205, 2580, + 0, 3271, 0, + 0, 3346, 0, + 0, 3430, 0, + 0, 3523, 0, + 0, 3623, 0, + 0, 3730, 0, + 0, 2926, 3210, + 0, 2926, 3210, + 0, 2926, 3210, + 0, 2926, 3210, + 0, 2926, 3210, + 0, 2927, 3210, + 0, 2927, 3209, + 0, 2927, 3209, + 0, 2928, 3208, + 0, 2929, 3207, + 0, 2930, 3206, + 0, 2932, 3205, + 0, 2934, 3203, + 0, 2937, 3200, + 0, 2941, 3197, + 0, 2946, 3192, + 0, 2953, 3185, + 0, 2962, 3176, + 0, 2973, 3164, + 0, 2989, 3148, + 0, 3008, 3124, + 0, 3033, 3091, + 0, 3064, 3043, + 0, 3103, 2968, + 0, 3150, 2845, + 0, 3206, 2601, + 0, 3271, 1202, + 0, 3346, 0, + 0, 3431, 0, + 0, 3523, 0, + 0, 3624, 0, + 0, 3730, 0, + 0, 2927, 3217, + 0, 2928, 3217, + 0, 2928, 3217, + 0, 2928, 3217, + 0, 2928, 3217, + 0, 2928, 3216, + 0, 2929, 3216, + 0, 2929, 3216, + 0, 2930, 3215, + 0, 2931, 3214, + 0, 2932, 3213, + 0, 2934, 3212, + 0, 2936, 3210, + 0, 2939, 3207, + 0, 2943, 3204, + 0, 2948, 3199, + 0, 2955, 3193, + 0, 2963, 3184, + 0, 2975, 3172, + 0, 2990, 3156, + 0, 3010, 3133, + 0, 3034, 3100, + 0, 3065, 3053, + 0, 3104, 2980, + 0, 3151, 2860, + 0, 3207, 2626, + 0, 3272, 1575, + 0, 3347, 0, + 0, 3431, 0, + 0, 3524, 0, + 0, 3624, 0, + 0, 3731, 0, + 0, 2930, 3226, + 0, 2930, 3226, + 0, 2930, 3226, + 0, 2930, 3226, + 0, 2930, 3226, + 0, 2931, 3226, + 0, 2931, 3225, + 0, 2932, 3225, + 0, 2932, 3224, + 0, 2933, 3223, + 0, 2934, 3222, + 0, 2936, 3221, + 0, 2938, 3219, + 0, 2941, 3216, + 0, 2945, 3213, + 0, 2950, 3208, + 0, 2957, 3202, + 0, 2966, 3194, + 0, 2977, 3182, + 0, 2992, 3166, + 0, 3012, 3144, + 0, 3036, 3112, + 0, 3067, 3066, + 0, 3105, 2995, + 0, 3152, 2880, + 0, 3208, 2659, + 0, 3273, 1829, + 0, 3348, 0, + 0, 3432, 0, + 0, 3524, 0, + 0, 3624, 0, + 0, 3731, 0, + 0, 2933, 3238, + 0, 2933, 3238, + 0, 2933, 3238, + 0, 2933, 3238, + 0, 2934, 3238, + 0, 2934, 3237, + 0, 2934, 3237, + 0, 2935, 3237, + 0, 2936, 3236, + 0, 2936, 3235, + 0, 2938, 3234, + 0, 2939, 3233, + 0, 2941, 3231, + 0, 2944, 3229, + 0, 2948, 3225, + 0, 2953, 3221, + 0, 2960, 3215, + 0, 2969, 3206, + 0, 2980, 3195, + 0, 2995, 3179, + 0, 3014, 3158, + 0, 3039, 3127, + 0, 3069, 3082, + 0, 3108, 3015, + 0, 3154, 2905, + 0, 3210, 2699, + 0, 3275, 2034, + 0, 3349, 0, + 0, 3433, 0, + 0, 3525, 0, + 0, 3625, 0, + 0, 3732, 0, + 0, 2937, 3254, + 0, 2937, 3253, + 0, 2938, 3253, + 0, 2938, 3253, + 0, 2938, 3253, + 0, 2938, 3253, + 0, 2939, 3252, + 0, 2939, 3252, + 0, 2940, 3252, + 0, 2941, 3251, + 0, 2942, 3250, + 0, 2943, 3248, + 0, 2946, 3247, + 0, 2948, 3244, + 0, 2952, 3241, + 0, 2957, 3237, + 0, 2964, 3231, + 0, 2973, 3223, + 0, 2984, 3212, + 0, 2999, 3197, + 0, 3018, 3176, + 0, 3042, 3147, + 0, 3073, 3104, + 0, 3110, 3040, + 0, 3157, 2937, + 0, 3212, 2747, + 0, 3277, 2215, + 0, 3351, 0, + 0, 3434, 0, + 0, 3526, 0, + 0, 3626, 0, + 0, 3732, 0, + 0, 2943, 3273, + 0, 2943, 3273, + 0, 2943, 3273, + 0, 2943, 3273, + 0, 2944, 3273, + 0, 2944, 3273, + 0, 2944, 3272, + 0, 2945, 3272, + 0, 2945, 3271, + 0, 2946, 3271, + 0, 2947, 3270, + 0, 2949, 3268, + 0, 2951, 3267, + 0, 2954, 3264, + 0, 2958, 3261, + 0, 2963, 3257, + 0, 2969, 3252, + 0, 2978, 3244, + 0, 2989, 3234, + 0, 3004, 3219, + 0, 3022, 3199, + 0, 3046, 3171, + 0, 3077, 3131, + 0, 3114, 3071, + 0, 3160, 2976, + 0, 3215, 2805, + 0, 3279, 2380, + 0, 3353, 0, + 0, 3436, 0, + 0, 3528, 0, + 0, 3627, 0, + 0, 3733, 0, + 1458, 2950, 3298, + 1453, 2950, 3298, + 1446, 2951, 3298, + 1437, 2951, 3298, + 1424, 2951, 3298, + 1407, 2951, 3298, + 1383, 2952, 3298, + 1348, 2952, 3297, + 1297, 2953, 3297, + 1219, 2954, 3296, + 1088, 2955, 3295, + 818, 2956, 3294, + 0, 2958, 3292, + 0, 2961, 3290, + 0, 2965, 3287, + 0, 2970, 3283, + 0, 2976, 3278, + 0, 2985, 3271, + 0, 2996, 3261, + 0, 3010, 3248, + 0, 3029, 3229, + 0, 3052, 3203, + 0, 3082, 3165, + 0, 3119, 3110, + 0, 3165, 3023, + 0, 3219, 2873, + 0, 3283, 2535, + 0, 3356, 0, + 0, 3439, 0, + 0, 3530, 0, + 0, 3629, 0, + 0, 3735, 0, + 2457, 2960, 3330, + 2456, 2960, 3330, + 2456, 2960, 3330, + 2455, 2960, 3330, + 2453, 2961, 3330, + 2451, 2961, 3330, + 2449, 2961, 3329, + 2446, 2962, 3329, + 2442, 2962, 3328, + 2436, 2963, 3328, + 2428, 2964, 3327, + 2417, 2966, 3326, + 2402, 2968, 3324, + 2382, 2971, 3322, + 2352, 2974, 3320, + 2310, 2979, 3316, + 2247, 2985, 3311, + 2145, 2994, 3304, + 1960, 3004, 3295, + 1453, 3019, 3283, + 0, 3037, 3266, + 0, 3060, 3242, + 0, 3090, 3207, + 0, 3126, 3157, + 0, 3171, 3079, + 0, 3225, 2949, + 0, 3288, 2684, + 0, 3360, 0, + 0, 3442, 0, + 0, 3533, 0, + 0, 3631, 0, + 0, 3736, 0, + 2813, 2973, 3369, + 2813, 2973, 3369, + 2812, 2973, 3369, + 2812, 2973, 3369, + 2811, 2973, 3369, + 2810, 2974, 3369, + 2809, 2974, 3369, + 2808, 2974, 3368, + 2806, 2975, 3368, + 2803, 2976, 3367, + 2800, 2977, 3366, + 2795, 2978, 3365, + 2789, 2980, 3364, + 2780, 2983, 3362, + 2768, 2987, 3360, + 2752, 2991, 3356, + 2729, 2997, 3352, + 2696, 3005, 3346, + 2648, 3016, 3337, + 2576, 3030, 3326, + 2456, 3048, 3310, + 2220, 3070, 3289, + 1140, 3099, 3258, + 0, 3135, 3213, + 0, 3179, 3145, + 0, 3232, 3035, + 0, 3294, 2828, + 0, 3366, 2152, + 0, 3447, 0, + 0, 3536, 0, + 0, 3634, 0, + 0, 3739, 0, + 3061, 2989, 3417, + 3061, 2989, 3417, + 3061, 2989, 3417, + 3060, 2989, 3417, + 3060, 2990, 3417, + 3060, 2990, 3416, + 3059, 2990, 3416, + 3058, 2991, 3416, + 3057, 2991, 3415, + 3055, 2992, 3415, + 3053, 2993, 3414, + 3051, 2995, 3413, + 3047, 2997, 3412, + 3042, 2999, 3410, + 3036, 3002, 3408, + 3027, 3007, 3405, + 3014, 3013, 3401, + 2997, 3021, 3396, + 2973, 3031, 3388, + 2939, 3044, 3378, + 2889, 3062, 3364, + 2812, 3084, 3345, + 2683, 3112, 3318, + 2421, 3147, 3279, + 0, 3189, 3221, + 0, 3241, 3129, + 0, 3302, 2969, + 0, 3373, 2588, + 0, 3452, 0, + 0, 3541, 0, + 0, 3638, 0, + 0, 3742, 0, + 3264, 3010, 3474, + 3264, 3010, 3474, + 3264, 3010, 3473, + 3263, 3010, 3473, + 3263, 3011, 3473, + 3263, 3011, 3473, + 3263, 3011, 3473, + 3262, 3012, 3473, + 3261, 3012, 3472, + 3260, 3013, 3472, + 3259, 3014, 3471, + 3257, 3015, 3470, + 3255, 3017, 3469, + 3252, 3020, 3468, + 3248, 3023, 3466, + 3242, 3027, 3463, + 3234, 3033, 3460, + 3224, 3040, 3455, + 3210, 3050, 3448, + 3190, 3063, 3440, + 3161, 3080, 3427, + 3121, 3101, 3411, + 3060, 3128, 3387, + 2964, 3162, 3354, + 2791, 3203, 3305, + 2354, 3253, 3231, + 0, 3313, 3107, + 0, 3382, 2861, + 0, 3460, 1375, + 0, 3548, 0, + 0, 3643, 0, + 0, 3746, 0, + 3442, 3037, 3540, + 3442, 3037, 3540, + 3442, 3037, 3540, + 3442, 3037, 3540, + 3442, 3037, 3540, + 3442, 3038, 3539, + 3442, 3038, 3539, + 3441, 3038, 3539, + 3441, 3039, 3539, + 3440, 3040, 3538, + 3439, 3041, 3538, + 3438, 3042, 3537, + 3437, 3044, 3536, + 3434, 3046, 3535, + 3432, 3049, 3533, + 3428, 3053, 3531, + 3423, 3058, 3528, + 3416, 3065, 3524, + 3407, 3075, 3518, + 3394, 3087, 3511, + 3376, 3103, 3500, + 3351, 3123, 3486, + 3315, 3149, 3466, + 3263, 3181, 3438, + 3182, 3221, 3398, + 3044, 3269, 3339, + 2752, 3327, 3244, + 0, 3394, 3076, + 0, 3470, 2660, + 0, 3556, 0, + 0, 3650, 0, + 0, 3751, 0, + 3606, 3070, 3616, + 3606, 3070, 3616, + 3606, 3071, 3616, + 3606, 3071, 3615, + 3606, 3071, 3615, + 3606, 3071, 3615, + 3606, 3071, 3615, + 3606, 3072, 3615, + 3605, 3072, 3615, + 3605, 3073, 3614, + 3604, 3074, 3614, + 3603, 3075, 3613, + 3602, 3077, 3613, + 3601, 3079, 3611, + 3599, 3082, 3610, + 3596, 3085, 3608, + 3593, 3090, 3605, + 3588, 3097, 3602, + 3582, 3106, 3597, + 3573, 3117, 3591, + 3561, 3132, 3582, + 3545, 3151, 3570, + 3522, 3175, 3554, + 3489, 3205, 3531, + 3442, 3243, 3499, + 3369, 3289, 3452, + 3249, 3345, 3380, + 3015, 3409, 3261, + 1952, 3483, 3030, + 0, 3567, 2039, + 0, 3659, 0, + 0, 3758, 0, + 3761, 3112, 3700, + 3761, 3112, 3700, + 3761, 3112, 3700, + 3761, 3112, 3700, + 3761, 3112, 3700, + 3761, 3112, 3700, + 3761, 3112, 3700, + 3760, 3113, 3700, + 3760, 3113, 3700, + 3760, 3114, 3699, + 3759, 3115, 3699, + 3759, 3116, 3699, + 3758, 3117, 3698, + 3757, 3119, 3697, + 3756, 3122, 3696, + 3754, 3125, 3694, + 3751, 3130, 3692, + 3748, 3136, 3689, + 3744, 3144, 3685, + 3738, 3154, 3680, + 3729, 3168, 3673, + 3718, 3185, 3663, + 3702, 3208, 3650, + 3681, 3236, 3632, + 3650, 3272, 3606, + 3606, 3315, 3569, + 3538, 3368, 3514, + 3429, 3429, 3429, + 3224, 3501, 3283, + 2573, 3581, 2960, + 0, 3671, 0, + 0, 3768, 0, + 3909, 3161, 3794, + 3909, 3161, 3794, + 3909, 3162, 3794, + 3909, 3162, 3794, + 3909, 3162, 3794, + 3909, 3162, 3794, + 3909, 3162, 3793, + 3909, 3162, 3793, + 3909, 3163, 3793, + 3908, 3163, 3793, + 3908, 3164, 3793, + 3908, 3165, 3792, + 3907, 3166, 3792, + 3906, 3168, 3791, + 3905, 3171, 3790, + 3904, 3174, 3789, + 3902, 3178, 3787, + 3900, 3183, 3785, + 3897, 3190, 3781, + 3892, 3200, 3777, + 3887, 3212, 3771, + 3879, 3228, 3764, + 3868, 3249, 3753, + 3853, 3275, 3739, + 3832, 3307, 3718, + 3803, 3348, 3690, + 3760, 3397, 3648, + 3696, 3455, 3587, + 3594, 3522, 3488, + 3407, 3599, 3311, + 2887, 3686, 2847, + 0, 3780, 0, + 4053, 3220, 3894, + 4053, 3221, 3894, + 4053, 3221, 3894, + 4053, 3221, 3894, + 4053, 3221, 3894, + 4053, 3221, 3894, + 4053, 3221, 3894, + 4053, 3221, 3894, + 4053, 3222, 3894, + 4052, 3222, 3894, + 4052, 3223, 3894, + 4052, 3224, 3893, + 4052, 3225, 3893, + 4051, 3226, 3892, + 4050, 3229, 3891, + 4049, 3231, 3890, + 4048, 3235, 3889, + 4046, 3240, 3887, + 4044, 3246, 3885, + 4041, 3254, 3881, + 4037, 3265, 3877, + 4031, 3280, 3871, + 4023, 3298, 3862, + 4013, 3321, 3851, + 3998, 3351, 3835, + 3978, 3388, 3813, + 3950, 3433, 3782, + 3908, 3487, 3737, + 3847, 3550, 3668, + 3749, 3623, 3557, + 3573, 3705, 3345, + 3119, 3796, 2630, + 4095, 3289, 4002, + 4095, 3289, 4002, + 4095, 3289, 4002, + 4095, 3289, 4002, + 4095, 3289, 4001, + 4095, 3290, 4001, + 4095, 3290, 4001, + 4095, 3290, 4001, + 4095, 3290, 4001, + 4095, 3291, 4001, + 4095, 3291, 4001, + 4095, 3292, 4001, + 4095, 3293, 4000, + 4095, 3294, 4000, + 4095, 3296, 3999, + 4095, 3298, 3998, + 4095, 3302, 3997, + 4095, 3306, 3996, + 4095, 3311, 3994, + 4095, 3318, 3991, + 4095, 3328, 3988, + 4095, 3340, 3983, + 4095, 3357, 3976, + 4095, 3377, 3967, + 4095, 3403, 3955, + 4095, 3436, 3939, + 4095, 3477, 3915, + 4092, 3526, 3882, + 4052, 3585, 3833, + 3993, 3653, 3758, + 3898, 3730, 3634, + 3730, 3816, 3387, + 4095, 3367, 4095, + 4095, 3367, 4095, + 4095, 3367, 4095, + 4095, 3367, 4095, + 4095, 3367, 4095, + 4095, 3368, 4095, + 4095, 3368, 4095, + 4095, 3368, 4095, + 4095, 3368, 4095, + 4095, 3369, 4095, + 4095, 3369, 4095, + 4095, 3370, 4095, + 4095, 3370, 4095, + 4095, 3372, 4095, + 4095, 3373, 4095, + 4095, 3375, 4095, + 4095, 3378, 4095, + 4095, 3381, 4095, + 4095, 3386, 4095, + 4095, 3392, 4095, + 4095, 3400, 4095, + 4095, 3411, 4095, + 4095, 3425, 4094, + 4095, 3442, 4088, + 4095, 3465, 4078, + 4095, 3494, 4066, + 4095, 3530, 4048, + 4095, 3574, 4023, + 4095, 3627, 3988, + 4095, 3689, 3936, + 4095, 3761, 3857, + 4042, 3842, 3721, + 0, 3052, 3322, + 0, 3052, 3322, + 0, 3053, 3321, + 0, 3053, 3321, + 0, 3053, 3321, + 0, 3053, 3321, + 0, 3053, 3321, + 0, 3054, 3320, + 0, 3054, 3320, + 0, 3055, 3319, + 0, 3056, 3318, + 0, 3057, 3317, + 0, 3059, 3316, + 0, 3061, 3314, + 0, 3064, 3311, + 0, 3068, 3307, + 0, 3073, 3302, + 0, 3080, 3295, + 0, 3089, 3286, + 0, 3101, 3273, + 0, 3116, 3256, + 0, 3136, 3231, + 0, 3161, 3196, + 0, 3192, 3144, + 0, 3231, 3064, + 0, 3278, 2929, + 0, 3335, 2647, + 0, 3401, 0, + 0, 3476, 0, + 0, 3561, 0, + 0, 3654, 0, + 0, 3755, 0, + 0, 3052, 3322, + 0, 3052, 3322, + 0, 3053, 3322, + 0, 3053, 3321, + 0, 3053, 3321, + 0, 3053, 3321, + 0, 3053, 3321, + 0, 3054, 3320, + 0, 3054, 3320, + 0, 3055, 3319, + 0, 3056, 3319, + 0, 3057, 3317, + 0, 3059, 3316, + 0, 3061, 3314, + 0, 3064, 3311, + 0, 3068, 3307, + 0, 3073, 3302, + 0, 3080, 3295, + 0, 3089, 3286, + 0, 3101, 3273, + 0, 3116, 3256, + 0, 3136, 3231, + 0, 3161, 3196, + 0, 3192, 3144, + 0, 3231, 3065, + 0, 3278, 2930, + 0, 3335, 2648, + 0, 3401, 0, + 0, 3476, 0, + 0, 3561, 0, + 0, 3654, 0, + 0, 3755, 0, + 0, 3052, 3322, + 0, 3052, 3322, + 0, 3053, 3322, + 0, 3053, 3322, + 0, 3053, 3321, + 0, 3053, 3321, + 0, 3053, 3321, + 0, 3054, 3321, + 0, 3054, 3320, + 0, 3055, 3319, + 0, 3056, 3319, + 0, 3057, 3318, + 0, 3059, 3316, + 0, 3061, 3314, + 0, 3064, 3311, + 0, 3068, 3307, + 0, 3073, 3302, + 0, 3080, 3296, + 0, 3089, 3286, + 0, 3101, 3274, + 0, 3116, 3256, + 0, 3136, 3231, + 0, 3161, 3196, + 0, 3192, 3145, + 0, 3231, 3065, + 0, 3278, 2930, + 0, 3335, 2648, + 0, 3401, 0, + 0, 3476, 0, + 0, 3561, 0, + 0, 3654, 0, + 0, 3755, 0, + 0, 3052, 3322, + 0, 3053, 3322, + 0, 3053, 3322, + 0, 3053, 3322, + 0, 3053, 3322, + 0, 3053, 3321, + 0, 3053, 3321, + 0, 3054, 3321, + 0, 3054, 3320, + 0, 3055, 3320, + 0, 3056, 3319, + 0, 3057, 3318, + 0, 3059, 3316, + 0, 3061, 3314, + 0, 3064, 3311, + 0, 3068, 3308, + 0, 3073, 3303, + 0, 3080, 3296, + 0, 3089, 3286, + 0, 3101, 3274, + 0, 3116, 3256, + 0, 3136, 3232, + 0, 3161, 3197, + 0, 3192, 3145, + 0, 3231, 3065, + 0, 3278, 2930, + 0, 3335, 2649, + 0, 3401, 0, + 0, 3476, 0, + 0, 3561, 0, + 0, 3654, 0, + 0, 3755, 0, + 0, 3053, 3322, + 0, 3053, 3322, + 0, 3053, 3322, + 0, 3053, 3322, + 0, 3053, 3322, + 0, 3053, 3322, + 0, 3053, 3321, + 0, 3054, 3321, + 0, 3054, 3321, + 0, 3055, 3320, + 0, 3056, 3319, + 0, 3057, 3318, + 0, 3059, 3316, + 0, 3061, 3314, + 0, 3064, 3312, + 0, 3068, 3308, + 0, 3073, 3303, + 0, 3080, 3296, + 0, 3089, 3287, + 0, 3101, 3274, + 0, 3116, 3256, + 0, 3136, 3232, + 0, 3161, 3197, + 0, 3192, 3145, + 0, 3231, 3065, + 0, 3278, 2931, + 0, 3335, 2650, + 0, 3401, 0, + 0, 3476, 0, + 0, 3561, 0, + 0, 3654, 0, + 0, 3755, 0, + 0, 3053, 3323, + 0, 3053, 3322, + 0, 3053, 3322, + 0, 3053, 3322, + 0, 3053, 3322, + 0, 3053, 3322, + 0, 3054, 3322, + 0, 3054, 3321, + 0, 3054, 3321, + 0, 3055, 3320, + 0, 3056, 3319, + 0, 3057, 3318, + 0, 3059, 3317, + 0, 3061, 3315, + 0, 3064, 3312, + 0, 3068, 3308, + 0, 3073, 3303, + 0, 3080, 3296, + 0, 3089, 3287, + 0, 3101, 3274, + 0, 3116, 3257, + 0, 3136, 3232, + 0, 3161, 3197, + 0, 3192, 3146, + 0, 3231, 3066, + 0, 3279, 2932, + 0, 3335, 2651, + 0, 3401, 0, + 0, 3476, 0, + 0, 3561, 0, + 0, 3654, 0, + 0, 3755, 0, + 0, 3053, 3323, + 0, 3053, 3323, + 0, 3053, 3323, + 0, 3053, 3323, + 0, 3053, 3323, + 0, 3053, 3322, + 0, 3054, 3322, + 0, 3054, 3322, + 0, 3055, 3321, + 0, 3055, 3321, + 0, 3056, 3320, + 0, 3057, 3319, + 0, 3059, 3317, + 0, 3061, 3315, + 0, 3064, 3312, + 0, 3068, 3309, + 0, 3073, 3304, + 0, 3080, 3297, + 0, 3089, 3287, + 0, 3101, 3275, + 0, 3116, 3257, + 0, 3136, 3233, + 0, 3161, 3198, + 0, 3192, 3146, + 0, 3231, 3067, + 0, 3279, 2932, + 0, 3335, 2653, + 0, 3401, 0, + 0, 3476, 0, + 0, 3561, 0, + 0, 3654, 0, + 0, 3755, 0, + 0, 3053, 3323, + 0, 3053, 3323, + 0, 3053, 3323, + 0, 3053, 3323, + 0, 3053, 3323, + 0, 3053, 3323, + 0, 3054, 3323, + 0, 3054, 3322, + 0, 3055, 3322, + 0, 3055, 3321, + 0, 3056, 3320, + 0, 3058, 3319, + 0, 3059, 3318, + 0, 3061, 3316, + 0, 3064, 3313, + 0, 3068, 3309, + 0, 3074, 3304, + 0, 3080, 3297, + 0, 3089, 3288, + 0, 3101, 3275, + 0, 3116, 3258, + 0, 3136, 3233, + 0, 3161, 3198, + 0, 3192, 3147, + 0, 3231, 3068, + 0, 3279, 2934, + 0, 3335, 2655, + 0, 3401, 0, + 0, 3476, 0, + 0, 3561, 0, + 0, 3654, 0, + 0, 3755, 0, + 0, 3053, 3324, + 0, 3053, 3324, + 0, 3053, 3324, + 0, 3053, 3324, + 0, 3053, 3324, + 0, 3054, 3324, + 0, 3054, 3323, + 0, 3054, 3323, + 0, 3055, 3322, + 0, 3056, 3322, + 0, 3057, 3321, + 0, 3058, 3320, + 0, 3059, 3318, + 0, 3062, 3316, + 0, 3065, 3314, + 0, 3069, 3310, + 0, 3074, 3305, + 0, 3081, 3298, + 0, 3090, 3289, + 0, 3101, 3276, + 0, 3117, 3259, + 0, 3136, 3234, + 0, 3161, 3199, + 0, 3193, 3148, + 0, 3231, 3069, + 0, 3279, 2935, + 0, 3335, 2658, + 0, 3401, 0, + 0, 3477, 0, + 0, 3561, 0, + 0, 3654, 0, + 0, 3755, 0, + 0, 3053, 3325, + 0, 3053, 3325, + 0, 3053, 3325, + 0, 3054, 3325, + 0, 3054, 3325, + 0, 3054, 3325, + 0, 3054, 3324, + 0, 3055, 3324, + 0, 3055, 3323, + 0, 3056, 3323, + 0, 3057, 3322, + 0, 3058, 3321, + 0, 3060, 3319, + 0, 3062, 3317, + 0, 3065, 3314, + 0, 3069, 3311, + 0, 3074, 3306, + 0, 3081, 3299, + 0, 3090, 3290, + 0, 3102, 3277, + 0, 3117, 3260, + 0, 3136, 3235, + 0, 3161, 3201, + 0, 3193, 3149, + 0, 3232, 3071, + 0, 3279, 2938, + 0, 3335, 2662, + 0, 3401, 0, + 0, 3477, 0, + 0, 3561, 0, + 0, 3654, 0, + 0, 3755, 0, + 0, 3054, 3326, + 0, 3054, 3326, + 0, 3054, 3326, + 0, 3054, 3326, + 0, 3054, 3326, + 0, 3054, 3326, + 0, 3055, 3326, + 0, 3055, 3325, + 0, 3055, 3325, + 0, 3056, 3324, + 0, 3057, 3323, + 0, 3058, 3322, + 0, 3060, 3321, + 0, 3062, 3319, + 0, 3065, 3316, + 0, 3069, 3312, + 0, 3074, 3307, + 0, 3081, 3300, + 0, 3090, 3291, + 0, 3102, 3279, + 0, 3117, 3261, + 0, 3137, 3237, + 0, 3162, 3202, + 0, 3193, 3151, + 0, 3232, 3073, + 0, 3279, 2941, + 0, 3335, 2668, + 0, 3401, 0, + 0, 3477, 0, + 0, 3561, 0, + 0, 3654, 0, + 0, 3755, 0, + 0, 3054, 3328, + 0, 3054, 3328, + 0, 3054, 3328, + 0, 3054, 3328, + 0, 3054, 3328, + 0, 3055, 3327, + 0, 3055, 3327, + 0, 3055, 3327, + 0, 3056, 3326, + 0, 3057, 3326, + 0, 3057, 3325, + 0, 3059, 3324, + 0, 3060, 3322, + 0, 3063, 3320, + 0, 3066, 3318, + 0, 3069, 3314, + 0, 3075, 3309, + 0, 3081, 3302, + 0, 3090, 3293, + 0, 3102, 3281, + 0, 3117, 3263, + 0, 3137, 3239, + 0, 3162, 3204, + 0, 3193, 3154, + 0, 3232, 3076, + 0, 3279, 2944, + 0, 3336, 2675, + 0, 3402, 0, + 0, 3477, 0, + 0, 3561, 0, + 0, 3654, 0, + 0, 3755, 0, + 0, 3055, 3330, + 0, 3055, 3330, + 0, 3055, 3330, + 0, 3055, 3330, + 0, 3055, 3330, + 0, 3055, 3330, + 0, 3056, 3329, + 0, 3056, 3329, + 0, 3056, 3329, + 0, 3057, 3328, + 0, 3058, 3327, + 0, 3059, 3326, + 0, 3061, 3325, + 0, 3063, 3323, + 0, 3066, 3320, + 0, 3070, 3316, + 0, 3075, 3311, + 0, 3082, 3305, + 0, 3091, 3295, + 0, 3103, 3283, + 0, 3118, 3266, + 0, 3137, 3242, + 0, 3162, 3207, + 0, 3194, 3157, + 0, 3233, 3080, + 0, 3280, 2950, + 0, 3336, 2684, + 0, 3402, 0, + 0, 3477, 0, + 0, 3562, 0, + 0, 3655, 0, + 0, 3755, 0, + 0, 3055, 3333, + 0, 3055, 3333, + 0, 3055, 3333, + 0, 3056, 3333, + 0, 3056, 3333, + 0, 3056, 3333, + 0, 3056, 3332, + 0, 3057, 3332, + 0, 3057, 3332, + 0, 3058, 3331, + 0, 3059, 3330, + 0, 3060, 3329, + 0, 3062, 3328, + 0, 3064, 3326, + 0, 3067, 3323, + 0, 3071, 3319, + 0, 3076, 3314, + 0, 3083, 3308, + 0, 3092, 3299, + 0, 3103, 3286, + 0, 3119, 3269, + 0, 3138, 3245, + 0, 3163, 3211, + 0, 3194, 3161, + 0, 3233, 3085, + 0, 3280, 2957, + 0, 3336, 2696, + 0, 3402, 0, + 0, 3477, 0, + 0, 3562, 0, + 0, 3655, 0, + 0, 3755, 0, + 0, 3056, 3337, + 0, 3056, 3337, + 0, 3056, 3337, + 0, 3057, 3337, + 0, 3057, 3337, + 0, 3057, 3337, + 0, 3057, 3336, + 0, 3058, 3336, + 0, 3058, 3336, + 0, 3059, 3335, + 0, 3060, 3334, + 0, 3061, 3333, + 0, 3063, 3332, + 0, 3065, 3330, + 0, 3068, 3327, + 0, 3072, 3323, + 0, 3077, 3318, + 0, 3084, 3312, + 0, 3093, 3303, + 0, 3104, 3291, + 0, 3119, 3274, + 0, 3139, 3250, + 0, 3164, 3216, + 0, 3195, 3167, + 0, 3234, 3092, + 0, 3281, 2966, + 0, 3337, 2712, + 0, 3403, 0, + 0, 3478, 0, + 0, 3562, 0, + 0, 3655, 0, + 0, 3755, 0, + 0, 3058, 3342, + 0, 3058, 3342, + 0, 3058, 3342, + 0, 3058, 3342, + 0, 3058, 3342, + 0, 3058, 3342, + 0, 3059, 3342, + 0, 3059, 3341, + 0, 3060, 3341, + 0, 3060, 3340, + 0, 3061, 3339, + 0, 3062, 3338, + 0, 3064, 3337, + 0, 3066, 3335, + 0, 3069, 3332, + 0, 3073, 3329, + 0, 3078, 3324, + 0, 3085, 3317, + 0, 3094, 3309, + 0, 3106, 3296, + 0, 3121, 3280, + 0, 3140, 3256, + 0, 3165, 3223, + 0, 3196, 3175, + 0, 3235, 3100, + 0, 3282, 2977, + 0, 3338, 2733, + 0, 3403, 1334, + 0, 3478, 0, + 0, 3563, 0, + 0, 3655, 0, + 0, 3756, 0, + 0, 3059, 3349, + 0, 3060, 3349, + 0, 3060, 3349, + 0, 3060, 3349, + 0, 3060, 3349, + 0, 3060, 3349, + 0, 3060, 3349, + 0, 3061, 3348, + 0, 3061, 3348, + 0, 3062, 3347, + 0, 3063, 3346, + 0, 3064, 3345, + 0, 3066, 3344, + 0, 3068, 3342, + 0, 3071, 3339, + 0, 3075, 3336, + 0, 3080, 3331, + 0, 3087, 3325, + 0, 3096, 3316, + 0, 3107, 3304, + 0, 3122, 3288, + 0, 3142, 3265, + 0, 3166, 3232, + 0, 3197, 3185, + 0, 3236, 3112, + 0, 3283, 2993, + 0, 3339, 2758, + 0, 3404, 1707, + 0, 3479, 0, + 0, 3563, 0, + 0, 3656, 0, + 0, 3756, 0, + 0, 3062, 3358, + 0, 3062, 3358, + 0, 3062, 3358, + 0, 3062, 3358, + 0, 3062, 3358, + 0, 3063, 3358, + 0, 3063, 3358, + 0, 3063, 3357, + 0, 3064, 3357, + 0, 3064, 3356, + 0, 3065, 3355, + 0, 3067, 3354, + 0, 3068, 3353, + 0, 3070, 3351, + 0, 3073, 3349, + 0, 3077, 3345, + 0, 3082, 3341, + 0, 3089, 3334, + 0, 3098, 3326, + 0, 3109, 3314, + 0, 3124, 3298, + 0, 3144, 3276, + 0, 3168, 3244, + 0, 3199, 3198, + 0, 3238, 3127, + 0, 3284, 3012, + 0, 3340, 2791, + 0, 3405, 1961, + 0, 3480, 0, + 0, 3564, 0, + 0, 3657, 0, + 0, 3757, 0, + 0, 3065, 3370, + 0, 3065, 3370, + 0, 3065, 3370, + 0, 3065, 3370, + 0, 3066, 3370, + 0, 3066, 3370, + 0, 3066, 3369, + 0, 3066, 3369, + 0, 3067, 3369, + 0, 3068, 3368, + 0, 3069, 3367, + 0, 3070, 3366, + 0, 3071, 3365, + 0, 3074, 3363, + 0, 3076, 3361, + 0, 3080, 3357, + 0, 3085, 3353, + 0, 3092, 3347, + 0, 3101, 3338, + 0, 3112, 3327, + 0, 3127, 3312, + 0, 3146, 3290, + 0, 3171, 3259, + 0, 3202, 3214, + 0, 3240, 3147, + 0, 3286, 3037, + 0, 3342, 2831, + 0, 3407, 2166, + 0, 3481, 0, + 0, 3565, 0, + 0, 3657, 0, + 0, 3757, 0, + 0, 3069, 3386, + 0, 3069, 3386, + 0, 3070, 3386, + 0, 3070, 3385, + 0, 3070, 3385, + 0, 3070, 3385, + 0, 3070, 3385, + 0, 3071, 3385, + 0, 3071, 3384, + 0, 3072, 3384, + 0, 3073, 3383, + 0, 3074, 3382, + 0, 3076, 3381, + 0, 3078, 3379, + 0, 3081, 3376, + 0, 3084, 3373, + 0, 3089, 3369, + 0, 3096, 3363, + 0, 3105, 3355, + 0, 3116, 3344, + 0, 3131, 3329, + 0, 3150, 3308, + 0, 3174, 3279, + 0, 3205, 3236, + 0, 3243, 3172, + 0, 3289, 3069, + 0, 3344, 2880, + 0, 3409, 2347, + 0, 3483, 0, + 0, 3567, 0, + 0, 3659, 0, + 0, 3758, 0, + 0, 3075, 3405, + 0, 3075, 3405, + 0, 3075, 3405, + 0, 3075, 3405, + 0, 3075, 3405, + 0, 3076, 3405, + 0, 3076, 3405, + 0, 3076, 3404, + 0, 3077, 3404, + 0, 3077, 3404, + 0, 3078, 3403, + 0, 3080, 3402, + 0, 3081, 3401, + 0, 3083, 3399, + 0, 3086, 3397, + 0, 3090, 3393, + 0, 3095, 3389, + 0, 3101, 3384, + 0, 3110, 3376, + 0, 3121, 3366, + 0, 3136, 3351, + 0, 3155, 3332, + 0, 3179, 3304, + 0, 3209, 3263, + 0, 3246, 3203, + 0, 3292, 3108, + 0, 3347, 2937, + 0, 3411, 2512, + 0, 3485, 0, + 0, 3568, 0, + 0, 3660, 0, + 0, 3759, 0, + 1593, 3082, 3431, + 1590, 3082, 3431, + 1585, 3083, 3431, + 1578, 3083, 3430, + 1569, 3083, 3430, + 1556, 3083, 3430, + 1539, 3083, 3430, + 1515, 3084, 3430, + 1480, 3084, 3429, + 1429, 3085, 3429, + 1351, 3086, 3428, + 1220, 3087, 3427, + 950, 3088, 3426, + 0, 3090, 3424, + 0, 3093, 3422, + 0, 3097, 3419, + 0, 3102, 3415, + 0, 3108, 3410, + 0, 3117, 3403, + 0, 3128, 3393, + 0, 3142, 3380, + 0, 3161, 3361, + 0, 3184, 3335, + 0, 3214, 3297, + 0, 3252, 3242, + 0, 3297, 3155, + 0, 3351, 3005, + 0, 3415, 2667, + 0, 3488, 0, + 0, 3571, 0, + 0, 3662, 0, + 0, 3761, 0, + 2589, 3092, 3462, + 2589, 3092, 3462, + 2588, 3092, 3462, + 2588, 3092, 3462, + 2587, 3092, 3462, + 2585, 3093, 3462, + 2584, 3093, 3462, + 2581, 3093, 3461, + 2578, 3094, 3461, + 2574, 3094, 3461, + 2568, 3095, 3460, + 2560, 3096, 3459, + 2549, 3098, 3458, + 2534, 3100, 3456, + 2514, 3103, 3454, + 2484, 3106, 3452, + 2442, 3111, 3448, + 2379, 3117, 3443, + 2277, 3126, 3436, + 2092, 3137, 3427, + 1586, 3151, 3415, + 0, 3169, 3398, + 0, 3192, 3374, + 0, 3222, 3339, + 0, 3258, 3289, + 0, 3303, 3211, + 0, 3357, 3081, + 0, 3420, 2816, + 0, 3492, 0, + 0, 3574, 0, + 0, 3665, 0, + 0, 3763, 0, + 2945, 3105, 3501, + 2945, 3105, 3501, + 2945, 3105, 3501, + 2944, 3105, 3501, + 2944, 3105, 3501, + 2943, 3105, 3501, + 2942, 3106, 3501, + 2941, 3106, 3501, + 2940, 3106, 3500, + 2938, 3107, 3500, + 2935, 3108, 3499, + 2932, 3109, 3499, + 2927, 3110, 3497, + 2921, 3112, 3496, + 2912, 3115, 3494, + 2900, 3119, 3492, + 2884, 3123, 3488, + 2861, 3129, 3484, + 2828, 3137, 3478, + 2780, 3148, 3470, + 2708, 3162, 3458, + 2588, 3180, 3443, + 2352, 3202, 3421, + 1272, 3231, 3390, + 0, 3267, 3345, + 0, 3311, 3277, + 0, 3364, 3167, + 0, 3426, 2960, + 0, 3498, 2284, + 0, 3579, 0, + 0, 3669, 0, + 0, 3766, 0, + 3193, 3121, 3549, + 3193, 3121, 3549, + 3193, 3121, 3549, + 3193, 3121, 3549, + 3192, 3122, 3549, + 3192, 3122, 3549, + 3192, 3122, 3548, + 3191, 3122, 3548, + 3190, 3123, 3548, + 3189, 3123, 3548, + 3188, 3124, 3547, + 3186, 3125, 3546, + 3183, 3127, 3545, + 3179, 3129, 3544, + 3174, 3131, 3543, + 3168, 3135, 3540, + 3159, 3139, 3537, + 3146, 3145, 3533, + 3129, 3153, 3528, + 3105, 3163, 3520, + 3071, 3176, 3510, + 3021, 3194, 3496, + 2944, 3216, 3477, + 2815, 3244, 3450, + 2553, 3279, 3411, + 0, 3321, 3353, + 0, 3373, 3261, + 0, 3434, 3101, + 0, 3505, 2720, + 0, 3585, 0, + 0, 3673, 0, + 0, 3770, 0, + 3396, 3142, 3606, + 3396, 3142, 3606, + 3396, 3142, 3606, + 3396, 3142, 3606, + 3396, 3143, 3605, + 3395, 3143, 3605, + 3395, 3143, 3605, + 3395, 3143, 3605, + 3394, 3144, 3605, + 3393, 3144, 3604, + 3392, 3145, 3604, + 3391, 3146, 3603, + 3389, 3148, 3603, + 3387, 3149, 3601, + 3384, 3152, 3600, + 3380, 3155, 3598, + 3374, 3159, 3595, + 3367, 3165, 3592, + 3356, 3172, 3587, + 3342, 3182, 3581, + 3322, 3195, 3572, + 3294, 3212, 3560, + 3253, 3233, 3543, + 3192, 3260, 3519, + 3096, 3294, 3486, + 2923, 3335, 3437, + 2486, 3385, 3363, + 0, 3445, 3239, + 0, 3514, 2993, + 0, 3592, 1507, + 0, 3680, 0, + 0, 3775, 0, + 3575, 3169, 3672, + 3575, 3169, 3672, + 3574, 3169, 3672, + 3574, 3169, 3672, + 3574, 3169, 3672, + 3574, 3169, 3672, + 3574, 3170, 3672, + 3574, 3170, 3671, + 3573, 3170, 3671, + 3573, 3171, 3671, + 3572, 3172, 3670, + 3571, 3173, 3670, + 3570, 3174, 3669, + 3569, 3176, 3668, + 3567, 3178, 3667, + 3564, 3181, 3665, + 3560, 3185, 3663, + 3555, 3190, 3660, + 3548, 3198, 3656, + 3539, 3207, 3650, + 3526, 3219, 3643, + 3508, 3235, 3632, + 3483, 3255, 3618, + 3448, 3281, 3598, + 3395, 3313, 3571, + 3314, 3353, 3531, + 3176, 3401, 3471, + 2884, 3459, 3376, + 0, 3526, 3208, + 0, 3602, 2792, + 0, 3688, 0, + 0, 3782, 0, + 3739, 3202, 3748, + 3739, 3202, 3748, + 3739, 3203, 3748, + 3738, 3203, 3748, + 3738, 3203, 3748, + 3738, 3203, 3747, + 3738, 3203, 3747, + 3738, 3203, 3747, + 3738, 3204, 3747, + 3737, 3204, 3747, + 3737, 3205, 3746, + 3736, 3206, 3746, + 3736, 3207, 3745, + 3734, 3209, 3745, + 3733, 3211, 3744, + 3731, 3214, 3742, + 3728, 3217, 3740, + 3725, 3222, 3738, + 3720, 3229, 3734, + 3714, 3238, 3729, + 3705, 3249, 3723, + 3693, 3264, 3714, + 3677, 3283, 3703, + 3654, 3307, 3686, + 3621, 3338, 3663, + 3574, 3375, 3631, + 3501, 3422, 3584, + 3381, 3477, 3512, + 3147, 3541, 3393, + 2084, 3616, 3162, + 0, 3699, 2171, + 0, 3791, 0, + 3893, 3244, 3833, + 3893, 3244, 3833, + 3893, 3244, 3833, + 3893, 3244, 3832, + 3893, 3244, 3832, + 3893, 3244, 3832, + 3893, 3244, 3832, + 3893, 3244, 3832, + 3893, 3245, 3832, + 3892, 3245, 3832, + 3892, 3246, 3832, + 3892, 3247, 3831, + 3891, 3248, 3831, + 3890, 3249, 3830, + 3889, 3251, 3829, + 3888, 3254, 3828, + 3886, 3257, 3826, + 3884, 3262, 3824, + 3880, 3268, 3821, + 3876, 3276, 3817, + 3870, 3286, 3812, + 3861, 3300, 3805, + 3850, 3318, 3795, + 3835, 3340, 3782, + 3813, 3368, 3764, + 3782, 3404, 3738, + 3738, 3447, 3701, + 3670, 3500, 3646, + 3561, 3561, 3561, + 3357, 3633, 3415, + 2705, 3713, 3092, + 0, 3803, 0, + 4041, 3293, 3926, + 4041, 3293, 3926, + 4041, 3294, 3926, + 4041, 3294, 3926, + 4041, 3294, 3926, + 4041, 3294, 3926, + 4041, 3294, 3926, + 4041, 3294, 3926, + 4041, 3295, 3925, + 4041, 3295, 3925, + 4041, 3296, 3925, + 4040, 3296, 3925, + 4040, 3297, 3924, + 4039, 3299, 3924, + 4039, 3300, 3923, + 4038, 3303, 3922, + 4036, 3306, 3921, + 4034, 3310, 3919, + 4032, 3315, 3917, + 4029, 3322, 3914, + 4025, 3332, 3909, + 4019, 3344, 3904, + 4011, 3360, 3896, + 4000, 3381, 3885, + 3985, 3407, 3871, + 3964, 3440, 3850, + 3935, 3480, 3822, + 3892, 3529, 3781, + 3829, 3587, 3719, + 3726, 3654, 3620, + 3539, 3732, 3443, + 3019, 3818, 2979, + 4095, 3353, 4027, + 4095, 3353, 4027, + 4095, 3353, 4027, + 4095, 3353, 4027, + 4095, 3353, 4026, + 4095, 3353, 4026, + 4095, 3353, 4026, + 4095, 3353, 4026, + 4095, 3354, 4026, + 4095, 3354, 4026, + 4095, 3354, 4026, + 4095, 3355, 4026, + 4095, 3356, 4025, + 4095, 3357, 4025, + 4095, 3359, 4024, + 4095, 3361, 4024, + 4095, 3363, 4023, + 4095, 3367, 4021, + 4095, 3372, 4019, + 4095, 3378, 4017, + 4095, 3387, 4013, + 4095, 3397, 4009, + 4095, 3412, 4003, + 4095, 3430, 3994, + 4095, 3454, 3983, + 4095, 3483, 3967, + 4095, 3520, 3945, + 4082, 3565, 3914, + 4041, 3619, 3869, + 3979, 3682, 3800, + 3881, 3755, 3689, + 3706, 3837, 3477, + 4095, 3421, 4095, + 4095, 3421, 4095, + 4095, 3421, 4095, + 4095, 3421, 4095, + 4095, 3421, 4095, + 4095, 3421, 4095, + 4095, 3422, 4095, + 4095, 3422, 4095, + 4095, 3422, 4095, + 4095, 3422, 4095, + 4095, 3423, 4095, + 4095, 3423, 4095, + 4095, 3424, 4095, + 4095, 3425, 4095, + 4095, 3426, 4095, + 4095, 3428, 4095, + 4095, 3431, 4095, + 4095, 3434, 4095, + 4095, 3438, 4095, + 4095, 3443, 4095, + 4095, 3451, 4095, + 4095, 3460, 4095, + 4095, 3473, 4095, + 4095, 3489, 4095, + 4095, 3509, 4095, + 4095, 3536, 4087, + 4095, 3568, 4071, + 4095, 3609, 4047, + 4095, 3658, 4014, + 4095, 3717, 3965, + 4095, 3785, 3891, + 4030, 3862, 3767, + 0, 3184, 3454, + 0, 3184, 3454, + 0, 3185, 3454, + 0, 3185, 3453, + 0, 3185, 3453, + 0, 3185, 3453, + 0, 3185, 3453, + 0, 3185, 3453, + 0, 3186, 3452, + 0, 3186, 3452, + 0, 3187, 3451, + 0, 3188, 3450, + 0, 3189, 3449, + 0, 3191, 3448, + 0, 3193, 3446, + 0, 3196, 3443, + 0, 3200, 3439, + 0, 3205, 3434, + 0, 3212, 3427, + 0, 3221, 3418, + 0, 3233, 3405, + 0, 3248, 3388, + 0, 3268, 3363, + 0, 3293, 3328, + 0, 3324, 3276, + 0, 3363, 3196, + 0, 3410, 3061, + 0, 3467, 2779, + 0, 3533, 0, + 0, 3608, 0, + 0, 3693, 0, + 0, 3786, 0, + 0, 3184, 3454, + 0, 3184, 3454, + 0, 3185, 3454, + 0, 3185, 3454, + 0, 3185, 3453, + 0, 3185, 3453, + 0, 3185, 3453, + 0, 3185, 3453, + 0, 3186, 3452, + 0, 3186, 3452, + 0, 3187, 3451, + 0, 3188, 3451, + 0, 3189, 3449, + 0, 3191, 3448, + 0, 3193, 3446, + 0, 3196, 3443, + 0, 3200, 3439, + 0, 3205, 3434, + 0, 3212, 3427, + 0, 3221, 3418, + 0, 3233, 3405, + 0, 3248, 3388, + 0, 3268, 3363, + 0, 3293, 3328, + 0, 3324, 3276, + 0, 3363, 3196, + 0, 3410, 3061, + 0, 3467, 2779, + 0, 3533, 0, + 0, 3608, 0, + 0, 3693, 0, + 0, 3786, 0, + 0, 3184, 3454, + 0, 3184, 3454, + 0, 3185, 3454, + 0, 3185, 3454, + 0, 3185, 3454, + 0, 3185, 3453, + 0, 3185, 3453, + 0, 3185, 3453, + 0, 3186, 3453, + 0, 3186, 3452, + 0, 3187, 3451, + 0, 3188, 3451, + 0, 3189, 3449, + 0, 3191, 3448, + 0, 3193, 3446, + 0, 3196, 3443, + 0, 3200, 3439, + 0, 3205, 3434, + 0, 3212, 3428, + 0, 3221, 3418, + 0, 3233, 3406, + 0, 3248, 3388, + 0, 3268, 3363, + 0, 3293, 3328, + 0, 3324, 3277, + 0, 3363, 3197, + 0, 3411, 3062, + 0, 3467, 2780, + 0, 3533, 0, + 0, 3608, 0, + 0, 3693, 0, + 0, 3786, 0, + 0, 3184, 3454, + 0, 3185, 3454, + 0, 3185, 3454, + 0, 3185, 3454, + 0, 3185, 3454, + 0, 3185, 3454, + 0, 3185, 3453, + 0, 3185, 3453, + 0, 3186, 3453, + 0, 3186, 3452, + 0, 3187, 3452, + 0, 3188, 3451, + 0, 3189, 3450, + 0, 3191, 3448, + 0, 3193, 3446, + 0, 3196, 3443, + 0, 3200, 3440, + 0, 3205, 3434, + 0, 3212, 3428, + 0, 3221, 3418, + 0, 3233, 3406, + 0, 3248, 3388, + 0, 3268, 3364, + 0, 3293, 3328, + 0, 3324, 3277, + 0, 3363, 3197, + 0, 3411, 3062, + 0, 3467, 2780, + 0, 3533, 0, + 0, 3608, 0, + 0, 3693, 0, + 0, 3786, 0, + 0, 3184, 3454, + 0, 3185, 3454, + 0, 3185, 3454, + 0, 3185, 3454, + 0, 3185, 3454, + 0, 3185, 3454, + 0, 3185, 3453, + 0, 3186, 3453, + 0, 3186, 3453, + 0, 3186, 3452, + 0, 3187, 3452, + 0, 3188, 3451, + 0, 3189, 3450, + 0, 3191, 3448, + 0, 3193, 3446, + 0, 3196, 3443, + 0, 3200, 3440, + 0, 3205, 3435, + 0, 3212, 3428, + 0, 3221, 3419, + 0, 3233, 3406, + 0, 3248, 3388, + 0, 3268, 3364, + 0, 3293, 3329, + 0, 3324, 3277, + 0, 3363, 3197, + 0, 3411, 3062, + 0, 3467, 2781, + 0, 3533, 0, + 0, 3608, 0, + 0, 3693, 0, + 0, 3786, 0, + 0, 3185, 3454, + 0, 3185, 3454, + 0, 3185, 3454, + 0, 3185, 3454, + 0, 3185, 3454, + 0, 3185, 3454, + 0, 3185, 3454, + 0, 3186, 3453, + 0, 3186, 3453, + 0, 3186, 3453, + 0, 3187, 3452, + 0, 3188, 3451, + 0, 3189, 3450, + 0, 3191, 3448, + 0, 3193, 3446, + 0, 3196, 3444, + 0, 3200, 3440, + 0, 3205, 3435, + 0, 3212, 3428, + 0, 3221, 3419, + 0, 3233, 3406, + 0, 3248, 3389, + 0, 3268, 3364, + 0, 3293, 3329, + 0, 3324, 3277, + 0, 3363, 3198, + 0, 3411, 3063, + 0, 3467, 2782, + 0, 3533, 0, + 0, 3608, 0, + 0, 3693, 0, + 0, 3786, 0, + 0, 3185, 3455, + 0, 3185, 3455, + 0, 3185, 3455, + 0, 3185, 3454, + 0, 3185, 3454, + 0, 3185, 3454, + 0, 3185, 3454, + 0, 3186, 3454, + 0, 3186, 3453, + 0, 3187, 3453, + 0, 3187, 3452, + 0, 3188, 3451, + 0, 3189, 3450, + 0, 3191, 3449, + 0, 3193, 3447, + 0, 3196, 3444, + 0, 3200, 3440, + 0, 3205, 3435, + 0, 3212, 3428, + 0, 3221, 3419, + 0, 3233, 3406, + 0, 3248, 3389, + 0, 3268, 3364, + 0, 3293, 3329, + 0, 3324, 3278, + 0, 3363, 3198, + 0, 3411, 3064, + 0, 3467, 2783, + 0, 3533, 0, + 0, 3609, 0, + 0, 3693, 0, + 0, 3786, 0, + 0, 3185, 3455, + 0, 3185, 3455, + 0, 3185, 3455, + 0, 3185, 3455, + 0, 3185, 3455, + 0, 3185, 3455, + 0, 3185, 3454, + 0, 3186, 3454, + 0, 3186, 3454, + 0, 3187, 3453, + 0, 3187, 3453, + 0, 3188, 3452, + 0, 3190, 3451, + 0, 3191, 3449, + 0, 3193, 3447, + 0, 3196, 3444, + 0, 3200, 3441, + 0, 3205, 3436, + 0, 3212, 3429, + 0, 3221, 3420, + 0, 3233, 3407, + 0, 3248, 3389, + 0, 3268, 3365, + 0, 3293, 3330, + 0, 3324, 3278, + 0, 3363, 3199, + 0, 3411, 3065, + 0, 3467, 2785, + 0, 3533, 0, + 0, 3609, 0, + 0, 3693, 0, + 0, 3786, 0, + 0, 3185, 3456, + 0, 3185, 3456, + 0, 3185, 3455, + 0, 3185, 3455, + 0, 3185, 3455, + 0, 3185, 3455, + 0, 3186, 3455, + 0, 3186, 3455, + 0, 3186, 3454, + 0, 3187, 3454, + 0, 3187, 3453, + 0, 3188, 3452, + 0, 3190, 3451, + 0, 3191, 3450, + 0, 3194, 3448, + 0, 3197, 3445, + 0, 3200, 3441, + 0, 3206, 3436, + 0, 3212, 3429, + 0, 3221, 3420, + 0, 3233, 3407, + 0, 3248, 3390, + 0, 3268, 3365, + 0, 3293, 3331, + 0, 3325, 3279, + 0, 3363, 3200, + 0, 3411, 3066, + 0, 3467, 2787, + 0, 3533, 0, + 0, 3609, 0, + 0, 3693, 0, + 0, 3786, 0, + 0, 3185, 3456, + 0, 3185, 3456, + 0, 3185, 3456, + 0, 3185, 3456, + 0, 3185, 3456, + 0, 3186, 3456, + 0, 3186, 3456, + 0, 3186, 3455, + 0, 3186, 3455, + 0, 3187, 3455, + 0, 3188, 3454, + 0, 3189, 3453, + 0, 3190, 3452, + 0, 3192, 3450, + 0, 3194, 3448, + 0, 3197, 3446, + 0, 3201, 3442, + 0, 3206, 3437, + 0, 3213, 3430, + 0, 3222, 3421, + 0, 3233, 3408, + 0, 3249, 3391, + 0, 3268, 3366, + 0, 3293, 3331, + 0, 3325, 3280, + 0, 3364, 3201, + 0, 3411, 3067, + 0, 3467, 2790, + 0, 3533, 0, + 0, 3609, 0, + 0, 3693, 0, + 0, 3786, 0, + 0, 3185, 3457, + 0, 3185, 3457, + 0, 3185, 3457, + 0, 3185, 3457, + 0, 3186, 3457, + 0, 3186, 3457, + 0, 3186, 3457, + 0, 3186, 3456, + 0, 3187, 3456, + 0, 3187, 3456, + 0, 3188, 3455, + 0, 3189, 3454, + 0, 3190, 3453, + 0, 3192, 3451, + 0, 3194, 3449, + 0, 3197, 3447, + 0, 3201, 3443, + 0, 3206, 3438, + 0, 3213, 3431, + 0, 3222, 3422, + 0, 3234, 3409, + 0, 3249, 3392, + 0, 3268, 3368, + 0, 3293, 3333, + 0, 3325, 3282, + 0, 3364, 3203, + 0, 3411, 3070, + 0, 3467, 2794, + 0, 3533, 0, + 0, 3609, 0, + 0, 3693, 0, + 0, 3786, 0, + 0, 3186, 3459, + 0, 3186, 3458, + 0, 3186, 3458, + 0, 3186, 3458, + 0, 3186, 3458, + 0, 3186, 3458, + 0, 3186, 3458, + 0, 3187, 3458, + 0, 3187, 3457, + 0, 3188, 3457, + 0, 3188, 3456, + 0, 3189, 3455, + 0, 3190, 3454, + 0, 3192, 3453, + 0, 3194, 3451, + 0, 3197, 3448, + 0, 3201, 3444, + 0, 3206, 3439, + 0, 3213, 3432, + 0, 3222, 3423, + 0, 3234, 3411, + 0, 3249, 3393, + 0, 3269, 3369, + 0, 3294, 3334, + 0, 3325, 3283, + 0, 3364, 3205, + 0, 3411, 3073, + 0, 3468, 2800, + 0, 3533, 0, + 0, 3609, 0, + 0, 3693, 0, + 0, 3786, 0, + 0, 3186, 3460, + 0, 3186, 3460, + 0, 3186, 3460, + 0, 3186, 3460, + 0, 3186, 3460, + 0, 3187, 3460, + 0, 3187, 3460, + 0, 3187, 3459, + 0, 3187, 3459, + 0, 3188, 3458, + 0, 3189, 3458, + 0, 3190, 3457, + 0, 3191, 3456, + 0, 3193, 3454, + 0, 3195, 3452, + 0, 3198, 3450, + 0, 3202, 3446, + 0, 3207, 3441, + 0, 3214, 3434, + 0, 3223, 3425, + 0, 3234, 3413, + 0, 3250, 3395, + 0, 3269, 3371, + 0, 3294, 3337, + 0, 3325, 3286, + 0, 3364, 3208, + 0, 3411, 3077, + 0, 3468, 2807, + 0, 3534, 0, + 0, 3609, 0, + 0, 3694, 0, + 0, 3787, 0, + 0, 3187, 3462, + 0, 3187, 3462, + 0, 3187, 3462, + 0, 3187, 3462, + 0, 3187, 3462, + 0, 3187, 3462, + 0, 3187, 3462, + 0, 3188, 3462, + 0, 3188, 3461, + 0, 3189, 3461, + 0, 3189, 3460, + 0, 3190, 3459, + 0, 3191, 3458, + 0, 3193, 3457, + 0, 3195, 3455, + 0, 3198, 3452, + 0, 3202, 3448, + 0, 3207, 3443, + 0, 3214, 3437, + 0, 3223, 3428, + 0, 3235, 3415, + 0, 3250, 3398, + 0, 3270, 3374, + 0, 3295, 3339, + 0, 3326, 3289, + 0, 3365, 3212, + 0, 3412, 3082, + 0, 3468, 2816, + 0, 3534, 0, + 0, 3609, 0, + 0, 3694, 0, + 0, 3787, 0, + 0, 3187, 3465, + 0, 3187, 3465, + 0, 3187, 3465, + 0, 3188, 3465, + 0, 3188, 3465, + 0, 3188, 3465, + 0, 3188, 3465, + 0, 3188, 3465, + 0, 3189, 3464, + 0, 3189, 3464, + 0, 3190, 3463, + 0, 3191, 3462, + 0, 3192, 3461, + 0, 3194, 3460, + 0, 3196, 3458, + 0, 3199, 3455, + 0, 3203, 3451, + 0, 3208, 3446, + 0, 3215, 3440, + 0, 3224, 3431, + 0, 3235, 3418, + 0, 3251, 3401, + 0, 3270, 3377, + 0, 3295, 3343, + 0, 3326, 3293, + 0, 3365, 3217, + 0, 3412, 3089, + 0, 3469, 2829, + 0, 3534, 0, + 0, 3610, 0, + 0, 3694, 0, + 0, 3787, 0, + 0, 3188, 3469, + 0, 3188, 3469, + 0, 3188, 3469, + 0, 3189, 3469, + 0, 3189, 3469, + 0, 3189, 3469, + 0, 3189, 3469, + 0, 3189, 3468, + 0, 3190, 3468, + 0, 3190, 3468, + 0, 3191, 3467, + 0, 3192, 3466, + 0, 3193, 3465, + 0, 3195, 3464, + 0, 3197, 3462, + 0, 3200, 3459, + 0, 3204, 3455, + 0, 3209, 3451, + 0, 3216, 3444, + 0, 3225, 3435, + 0, 3236, 3423, + 0, 3252, 3406, + 0, 3271, 3382, + 0, 3296, 3349, + 0, 3327, 3299, + 0, 3366, 3224, + 0, 3413, 3098, + 0, 3469, 2844, + 0, 3535, 106, + 0, 3610, 0, + 0, 3694, 0, + 0, 3787, 0, + 0, 3190, 3475, + 0, 3190, 3475, + 0, 3190, 3474, + 0, 3190, 3474, + 0, 3190, 3474, + 0, 3190, 3474, + 0, 3190, 3474, + 0, 3191, 3474, + 0, 3191, 3473, + 0, 3192, 3473, + 0, 3192, 3472, + 0, 3193, 3471, + 0, 3195, 3470, + 0, 3196, 3469, + 0, 3198, 3467, + 0, 3201, 3464, + 0, 3205, 3461, + 0, 3210, 3456, + 0, 3217, 3449, + 0, 3226, 3441, + 0, 3238, 3429, + 0, 3253, 3412, + 0, 3272, 3389, + 0, 3297, 3355, + 0, 3328, 3307, + 0, 3367, 3233, + 0, 3414, 3109, + 0, 3470, 2865, + 0, 3535, 1466, + 0, 3611, 0, + 0, 3695, 0, + 0, 3788, 0, + 0, 3192, 3481, + 0, 3192, 3481, + 0, 3192, 3481, + 0, 3192, 3481, + 0, 3192, 3481, + 0, 3192, 3481, + 0, 3192, 3481, + 0, 3193, 3481, + 0, 3193, 3480, + 0, 3193, 3480, + 0, 3194, 3479, + 0, 3195, 3478, + 0, 3196, 3477, + 0, 3198, 3476, + 0, 3200, 3474, + 0, 3203, 3471, + 0, 3207, 3468, + 0, 3212, 3463, + 0, 3219, 3457, + 0, 3228, 3448, + 0, 3239, 3436, + 0, 3254, 3420, + 0, 3274, 3397, + 0, 3298, 3364, + 0, 3329, 3317, + 0, 3368, 3244, + 0, 3415, 3125, + 0, 3471, 2891, + 0, 3536, 1839, + 0, 3611, 0, + 0, 3695, 0, + 0, 3788, 0, + 0, 3194, 3491, + 0, 3194, 3491, + 0, 3194, 3490, + 0, 3194, 3490, + 0, 3194, 3490, + 0, 3194, 3490, + 0, 3195, 3490, + 0, 3195, 3490, + 0, 3195, 3489, + 0, 3196, 3489, + 0, 3197, 3488, + 0, 3197, 3488, + 0, 3199, 3487, + 0, 3200, 3485, + 0, 3202, 3483, + 0, 3205, 3481, + 0, 3209, 3477, + 0, 3214, 3473, + 0, 3221, 3466, + 0, 3230, 3458, + 0, 3241, 3446, + 0, 3256, 3430, + 0, 3276, 3408, + 0, 3300, 3376, + 0, 3331, 3330, + 0, 3370, 3259, + 0, 3416, 3144, + 0, 3472, 2923, + 0, 3537, 2093, + 0, 3612, 0, + 0, 3696, 0, + 0, 3789, 0, + 0, 3197, 3502, + 0, 3197, 3502, + 0, 3197, 3502, + 0, 3197, 3502, + 0, 3197, 3502, + 0, 3198, 3502, + 0, 3198, 3502, + 0, 3198, 3502, + 0, 3199, 3501, + 0, 3199, 3501, + 0, 3200, 3500, + 0, 3201, 3500, + 0, 3202, 3498, + 0, 3203, 3497, + 0, 3206, 3495, + 0, 3209, 3493, + 0, 3212, 3489, + 0, 3217, 3485, + 0, 3224, 3479, + 0, 3233, 3471, + 0, 3244, 3459, + 0, 3259, 3444, + 0, 3278, 3422, + 0, 3303, 3391, + 0, 3334, 3347, + 0, 3372, 3279, + 0, 3418, 3169, + 0, 3474, 2963, + 0, 3539, 2299, + 0, 3613, 0, + 0, 3697, 0, + 0, 3790, 0, + 0, 3201, 3518, + 0, 3201, 3518, + 0, 3202, 3518, + 0, 3202, 3518, + 0, 3202, 3518, + 0, 3202, 3517, + 0, 3202, 3517, + 0, 3202, 3517, + 0, 3203, 3517, + 0, 3203, 3516, + 0, 3204, 3516, + 0, 3205, 3515, + 0, 3206, 3514, + 0, 3208, 3513, + 0, 3210, 3511, + 0, 3213, 3508, + 0, 3216, 3505, + 0, 3221, 3501, + 0, 3228, 3495, + 0, 3237, 3487, + 0, 3248, 3476, + 0, 3263, 3461, + 0, 3282, 3440, + 0, 3306, 3411, + 0, 3337, 3368, + 0, 3375, 3304, + 0, 3421, 3201, + 0, 3476, 3012, + 0, 3541, 2479, + 0, 3615, 0, + 0, 3699, 0, + 0, 3791, 0, + 0, 3207, 3538, + 0, 3207, 3538, + 0, 3207, 3537, + 0, 3207, 3537, + 0, 3207, 3537, + 0, 3207, 3537, + 0, 3208, 3537, + 0, 3208, 3537, + 0, 3208, 3537, + 0, 3209, 3536, + 0, 3210, 3536, + 0, 3210, 3535, + 0, 3212, 3534, + 0, 3213, 3533, + 0, 3215, 3531, + 0, 3218, 3529, + 0, 3222, 3526, + 0, 3227, 3521, + 0, 3233, 3516, + 0, 3242, 3508, + 0, 3253, 3498, + 0, 3268, 3483, + 0, 3287, 3464, + 0, 3311, 3436, + 0, 3341, 3395, + 0, 3379, 3335, + 0, 3424, 3240, + 0, 3479, 3069, + 0, 3544, 2644, + 0, 3617, 0, + 0, 3701, 0, + 0, 3792, 0, + 1728, 3214, 3563, + 1725, 3214, 3563, + 1722, 3215, 3563, + 1717, 3215, 3563, + 1710, 3215, 3563, + 1701, 3215, 3562, + 1688, 3215, 3562, + 1671, 3215, 3562, + 1647, 3216, 3562, + 1612, 3216, 3561, + 1562, 3217, 3561, + 1483, 3218, 3560, + 1352, 3219, 3559, + 1082, 3220, 3558, + 0, 3223, 3557, + 0, 3225, 3554, + 0, 3229, 3551, + 0, 3234, 3548, + 0, 3240, 3542, + 0, 3249, 3535, + 0, 3260, 3525, + 0, 3274, 3512, + 0, 3293, 3493, + 0, 3317, 3467, + 0, 3346, 3429, + 0, 3384, 3374, + 0, 3429, 3287, + 0, 3483, 3137, + 0, 3547, 2799, + 0, 3620, 0, + 0, 3703, 0, + 0, 3794, 0, + 2722, 3224, 3594, + 2721, 3224, 3594, + 2721, 3224, 3594, + 2720, 3224, 3594, + 2720, 3224, 3594, + 2719, 3225, 3594, + 2717, 3225, 3594, + 2716, 3225, 3594, + 2713, 3225, 3593, + 2710, 3226, 3593, + 2706, 3227, 3593, + 2700, 3227, 3592, + 2692, 3229, 3591, + 2681, 3230, 3590, + 2666, 3232, 3589, + 2646, 3235, 3587, + 2617, 3238, 3584, + 2574, 3243, 3580, + 2511, 3250, 3575, + 2410, 3258, 3569, + 2224, 3269, 3559, + 1718, 3283, 3547, + 0, 3301, 3530, + 0, 3324, 3506, + 0, 3354, 3471, + 0, 3390, 3421, + 0, 3435, 3343, + 0, 3489, 3214, + 0, 3552, 2948, + 0, 3624, 0, + 0, 3706, 0, + 0, 3797, 0, + 3077, 3237, 3634, + 3077, 3237, 3634, + 3077, 3237, 3633, + 3077, 3237, 3633, + 3076, 3237, 3633, + 3076, 3237, 3633, + 3075, 3237, 3633, + 3075, 3238, 3633, + 3073, 3238, 3633, + 3072, 3239, 3632, + 3070, 3239, 3632, + 3068, 3240, 3631, + 3064, 3241, 3631, + 3059, 3243, 3630, + 3053, 3245, 3628, + 3044, 3247, 3626, + 3032, 3251, 3624, + 3016, 3255, 3621, + 2993, 3262, 3616, + 2960, 3270, 3610, + 2913, 3280, 3602, + 2840, 3294, 3590, + 2720, 3312, 3575, + 2485, 3335, 3553, + 1404, 3363, 3522, + 0, 3399, 3477, + 0, 3443, 3409, + 0, 3496, 3299, + 0, 3558, 3092, + 0, 3630, 2417, + 0, 3711, 0, + 0, 3801, 0, + 3325, 3253, 3681, + 3325, 3253, 3681, + 3325, 3253, 3681, + 3325, 3253, 3681, + 3325, 3254, 3681, + 3325, 3254, 3681, + 3324, 3254, 3681, + 3324, 3254, 3681, + 3323, 3254, 3680, + 3322, 3255, 3680, + 3321, 3255, 3680, + 3320, 3256, 3679, + 3318, 3257, 3678, + 3315, 3259, 3678, + 3311, 3261, 3676, + 3306, 3263, 3675, + 3300, 3267, 3672, + 3291, 3271, 3669, + 3278, 3277, 3665, + 3261, 3285, 3660, + 3237, 3295, 3652, + 3203, 3308, 3642, + 3153, 3326, 3628, + 3076, 3348, 3609, + 2947, 3376, 3582, + 2685, 3411, 3543, + 0, 3454, 3485, + 0, 3505, 3394, + 0, 3566, 3233, + 0, 3637, 2852, + 0, 3717, 0, + 0, 3805, 0, + 3528, 3274, 3738, + 3528, 3274, 3738, + 3528, 3274, 3738, + 3528, 3274, 3738, + 3528, 3275, 3738, + 3528, 3275, 3738, + 3527, 3275, 3737, + 3527, 3275, 3737, + 3527, 3275, 3737, + 3526, 3276, 3737, + 3525, 3276, 3737, + 3525, 3277, 3736, + 3523, 3278, 3735, + 3522, 3280, 3735, + 3519, 3281, 3734, + 3516, 3284, 3732, + 3512, 3287, 3730, + 3506, 3291, 3728, + 3499, 3297, 3724, + 3488, 3305, 3719, + 3474, 3314, 3713, + 3454, 3327, 3704, + 3426, 3344, 3692, + 3385, 3365, 3675, + 3324, 3392, 3652, + 3228, 3426, 3618, + 3055, 3467, 3570, + 2618, 3517, 3495, + 0, 3577, 3371, + 0, 3646, 3125, + 0, 3724, 1639, + 0, 3812, 0, + 3707, 3301, 3804, + 3707, 3301, 3804, + 3707, 3301, 3804, + 3707, 3301, 3804, + 3707, 3301, 3804, + 3706, 3301, 3804, + 3706, 3302, 3804, + 3706, 3302, 3804, + 3706, 3302, 3803, + 3705, 3303, 3803, + 3705, 3303, 3803, + 3704, 3304, 3803, + 3703, 3305, 3802, + 3702, 3306, 3801, + 3701, 3308, 3800, + 3699, 3310, 3799, + 3696, 3313, 3797, + 3692, 3317, 3795, + 3687, 3323, 3792, + 3680, 3330, 3788, + 3671, 3339, 3782, + 3658, 3351, 3775, + 3640, 3367, 3764, + 3615, 3387, 3750, + 3580, 3413, 3730, + 3527, 3445, 3703, + 3446, 3485, 3663, + 3308, 3533, 3603, + 3017, 3591, 3508, + 0, 3658, 3340, + 0, 3734, 2924, + 0, 3820, 0, + 3871, 3334, 3880, + 3871, 3334, 3880, + 3871, 3335, 3880, + 3871, 3335, 3880, + 3871, 3335, 3880, + 3871, 3335, 3880, + 3870, 3335, 3880, + 3870, 3335, 3879, + 3870, 3335, 3879, + 3870, 3336, 3879, + 3869, 3336, 3879, + 3869, 3337, 3879, + 3868, 3338, 3878, + 3868, 3339, 3878, + 3867, 3341, 3877, + 3865, 3343, 3876, + 3863, 3346, 3874, + 3861, 3349, 3872, + 3857, 3354, 3870, + 3852, 3361, 3866, + 3846, 3370, 3862, + 3837, 3381, 3855, + 3825, 3396, 3846, + 3809, 3415, 3835, + 3786, 3439, 3818, + 3753, 3470, 3796, + 3706, 3507, 3763, + 3633, 3554, 3716, + 3513, 3609, 3644, + 3279, 3673, 3525, + 2216, 3748, 3294, + 0, 3831, 2303, + 4025, 3376, 3965, + 4025, 3376, 3965, + 4025, 3376, 3965, + 4025, 3376, 3965, + 4025, 3376, 3965, + 4025, 3376, 3965, + 4025, 3376, 3964, + 4025, 3376, 3964, + 4025, 3377, 3964, + 4025, 3377, 3964, + 4024, 3377, 3964, + 4024, 3378, 3964, + 4024, 3379, 3963, + 4023, 3380, 3963, + 4022, 3381, 3962, + 4021, 3383, 3961, + 4020, 3386, 3960, + 4018, 3389, 3958, + 4016, 3394, 3956, + 4012, 3400, 3953, + 4008, 3408, 3950, + 4002, 3418, 3944, + 3993, 3432, 3937, + 3982, 3450, 3928, + 3967, 3472, 3914, + 3945, 3501, 3896, + 3914, 3536, 3870, + 3870, 3579, 3833, + 3803, 3632, 3779, + 3693, 3693, 3693, + 3489, 3765, 3547, + 2837, 3845, 3224, + 4095, 3425, 4058, + 4095, 3426, 4058, + 4095, 3426, 4058, + 4095, 3426, 4058, + 4095, 3426, 4058, + 4095, 3426, 4058, + 4095, 3426, 4058, + 4095, 3426, 4058, + 4095, 3426, 4058, + 4095, 3427, 4057, + 4095, 3427, 4057, + 4095, 3428, 4057, + 4095, 3428, 4057, + 4095, 3429, 4056, + 4095, 3431, 4056, + 4095, 3432, 4055, + 4095, 3435, 4054, + 4095, 3438, 4053, + 4095, 3442, 4051, + 4095, 3447, 4049, + 4095, 3455, 4046, + 4095, 3464, 4041, + 4095, 3476, 4036, + 4095, 3492, 4028, + 4095, 3513, 4017, + 4095, 3539, 4003, + 4095, 3572, 3982, + 4067, 3612, 3954, + 4024, 3661, 3913, + 3961, 3719, 3851, + 3858, 3787, 3752, + 3671, 3864, 3575, + 4095, 3485, 4095, + 4095, 3485, 4095, + 4095, 3485, 4095, + 4095, 3485, 4095, + 4095, 3485, 4095, + 4095, 3485, 4095, + 4095, 3485, 4095, + 4095, 3485, 4095, + 4095, 3485, 4095, + 4095, 3486, 4095, + 4095, 3486, 4095, + 4095, 3486, 4095, + 4095, 3487, 4095, + 4095, 3488, 4095, + 4095, 3489, 4095, + 4095, 3491, 4095, + 4095, 3493, 4095, + 4095, 3495, 4095, + 4095, 3499, 4095, + 4095, 3504, 4095, + 4095, 3510, 4095, + 4095, 3519, 4095, + 4095, 3530, 4095, + 4095, 3544, 4095, + 4095, 3562, 4095, + 4095, 3586, 4095, + 4095, 3615, 4095, + 4095, 3652, 4077, + 4095, 3697, 4046, + 4095, 3751, 4001, + 4095, 3814, 3932, + 4014, 3887, 3821, + 0, 3316, 3586, + 0, 3316, 3586, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3317, 3585, + 0, 3317, 3585, + 0, 3317, 3585, + 0, 3317, 3585, + 0, 3318, 3584, + 0, 3318, 3584, + 0, 3319, 3583, + 0, 3320, 3582, + 0, 3321, 3581, + 0, 3323, 3580, + 0, 3325, 3578, + 0, 3328, 3575, + 0, 3332, 3571, + 0, 3337, 3566, + 0, 3344, 3559, + 0, 3353, 3550, + 0, 3365, 3537, + 0, 3380, 3520, + 0, 3400, 3495, + 0, 3425, 3460, + 0, 3456, 3408, + 0, 3495, 3328, + 0, 3543, 3193, + 0, 3599, 2911, + 0, 3665, 0, + 0, 3740, 0, + 0, 3825, 0, + 0, 3316, 3586, + 0, 3316, 3586, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3317, 3585, + 0, 3317, 3585, + 0, 3317, 3585, + 0, 3317, 3585, + 0, 3318, 3585, + 0, 3318, 3584, + 0, 3319, 3583, + 0, 3320, 3583, + 0, 3321, 3581, + 0, 3323, 3580, + 0, 3325, 3578, + 0, 3328, 3575, + 0, 3332, 3571, + 0, 3337, 3566, + 0, 3344, 3559, + 0, 3353, 3550, + 0, 3365, 3537, + 0, 3380, 3520, + 0, 3400, 3495, + 0, 3425, 3460, + 0, 3456, 3408, + 0, 3495, 3328, + 0, 3543, 3193, + 0, 3599, 2911, + 0, 3665, 0, + 0, 3741, 0, + 0, 3825, 0, + 0, 3316, 3586, + 0, 3316, 3586, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3317, 3585, + 0, 3317, 3585, + 0, 3318, 3585, + 0, 3318, 3585, + 0, 3318, 3584, + 0, 3319, 3583, + 0, 3320, 3583, + 0, 3321, 3581, + 0, 3323, 3580, + 0, 3325, 3578, + 0, 3328, 3575, + 0, 3332, 3571, + 0, 3337, 3566, + 0, 3344, 3560, + 0, 3353, 3550, + 0, 3365, 3538, + 0, 3380, 3520, + 0, 3400, 3495, + 0, 3425, 3460, + 0, 3456, 3408, + 0, 3495, 3329, + 0, 3543, 3194, + 0, 3599, 2911, + 0, 3665, 0, + 0, 3741, 0, + 0, 3825, 0, + 0, 3316, 3586, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3317, 3585, + 0, 3317, 3585, + 0, 3318, 3585, + 0, 3318, 3585, + 0, 3318, 3584, + 0, 3319, 3584, + 0, 3320, 3583, + 0, 3321, 3582, + 0, 3323, 3580, + 0, 3325, 3578, + 0, 3328, 3575, + 0, 3332, 3571, + 0, 3337, 3566, + 0, 3344, 3560, + 0, 3353, 3550, + 0, 3365, 3538, + 0, 3380, 3520, + 0, 3400, 3495, + 0, 3425, 3460, + 0, 3456, 3409, + 0, 3495, 3329, + 0, 3543, 3194, + 0, 3599, 2912, + 0, 3665, 0, + 0, 3741, 0, + 0, 3825, 0, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3317, 3585, + 0, 3318, 3585, + 0, 3318, 3585, + 0, 3318, 3584, + 0, 3319, 3584, + 0, 3320, 3583, + 0, 3321, 3582, + 0, 3323, 3580, + 0, 3325, 3578, + 0, 3328, 3575, + 0, 3332, 3572, + 0, 3337, 3567, + 0, 3344, 3560, + 0, 3353, 3551, + 0, 3365, 3538, + 0, 3380, 3520, + 0, 3400, 3496, + 0, 3425, 3460, + 0, 3456, 3409, + 0, 3495, 3329, + 0, 3543, 3194, + 0, 3599, 2912, + 0, 3665, 0, + 0, 3741, 0, + 0, 3825, 0, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3318, 3585, + 0, 3318, 3585, + 0, 3319, 3584, + 0, 3319, 3584, + 0, 3320, 3583, + 0, 3321, 3582, + 0, 3323, 3580, + 0, 3325, 3578, + 0, 3328, 3576, + 0, 3332, 3572, + 0, 3337, 3567, + 0, 3344, 3560, + 0, 3353, 3551, + 0, 3365, 3538, + 0, 3380, 3520, + 0, 3400, 3496, + 0, 3425, 3461, + 0, 3456, 3409, + 0, 3495, 3329, + 0, 3543, 3194, + 0, 3599, 2913, + 0, 3665, 0, + 0, 3741, 0, + 0, 3825, 0, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3318, 3586, + 0, 3318, 3585, + 0, 3319, 3585, + 0, 3319, 3584, + 0, 3320, 3583, + 0, 3321, 3582, + 0, 3323, 3581, + 0, 3325, 3579, + 0, 3328, 3576, + 0, 3332, 3572, + 0, 3337, 3567, + 0, 3344, 3560, + 0, 3353, 3551, + 0, 3365, 3538, + 0, 3380, 3521, + 0, 3400, 3496, + 0, 3425, 3461, + 0, 3456, 3409, + 0, 3495, 3330, + 0, 3543, 3195, + 0, 3599, 2914, + 0, 3665, 0, + 0, 3741, 0, + 0, 3825, 0, + 0, 3317, 3587, + 0, 3317, 3587, + 0, 3317, 3587, + 0, 3317, 3587, + 0, 3317, 3587, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3318, 3586, + 0, 3318, 3585, + 0, 3319, 3585, + 0, 3319, 3584, + 0, 3320, 3584, + 0, 3322, 3582, + 0, 3323, 3581, + 0, 3325, 3579, + 0, 3328, 3576, + 0, 3332, 3572, + 0, 3338, 3567, + 0, 3344, 3561, + 0, 3353, 3551, + 0, 3365, 3539, + 0, 3380, 3521, + 0, 3400, 3496, + 0, 3425, 3461, + 0, 3456, 3410, + 0, 3495, 3330, + 0, 3543, 3196, + 0, 3599, 2915, + 0, 3665, 0, + 0, 3741, 0, + 0, 3825, 0, + 0, 3317, 3587, + 0, 3317, 3587, + 0, 3317, 3587, + 0, 3317, 3587, + 0, 3317, 3587, + 0, 3317, 3587, + 0, 3317, 3587, + 0, 3318, 3587, + 0, 3318, 3586, + 0, 3318, 3586, + 0, 3319, 3585, + 0, 3319, 3585, + 0, 3320, 3584, + 0, 3322, 3583, + 0, 3323, 3581, + 0, 3326, 3579, + 0, 3328, 3576, + 0, 3332, 3573, + 0, 3338, 3568, + 0, 3344, 3561, + 0, 3353, 3552, + 0, 3365, 3539, + 0, 3380, 3521, + 0, 3400, 3497, + 0, 3425, 3462, + 0, 3457, 3410, + 0, 3495, 3331, + 0, 3543, 3197, + 0, 3599, 2917, + 0, 3665, 0, + 0, 3741, 0, + 0, 3825, 0, + 0, 3317, 3588, + 0, 3317, 3588, + 0, 3317, 3588, + 0, 3317, 3588, + 0, 3317, 3587, + 0, 3317, 3587, + 0, 3317, 3587, + 0, 3318, 3587, + 0, 3318, 3587, + 0, 3318, 3586, + 0, 3319, 3586, + 0, 3320, 3585, + 0, 3321, 3584, + 0, 3322, 3583, + 0, 3323, 3582, + 0, 3326, 3580, + 0, 3329, 3577, + 0, 3333, 3573, + 0, 3338, 3568, + 0, 3345, 3561, + 0, 3354, 3552, + 0, 3365, 3540, + 0, 3381, 3522, + 0, 3400, 3498, + 0, 3425, 3463, + 0, 3457, 3411, + 0, 3496, 3332, + 0, 3543, 3198, + 0, 3599, 2919, + 0, 3665, 0, + 0, 3741, 0, + 0, 3825, 0, + 0, 3317, 3588, + 0, 3317, 3588, + 0, 3317, 3588, + 0, 3317, 3588, + 0, 3317, 3588, + 0, 3317, 3588, + 0, 3318, 3588, + 0, 3318, 3588, + 0, 3318, 3587, + 0, 3319, 3587, + 0, 3319, 3587, + 0, 3320, 3586, + 0, 3321, 3585, + 0, 3322, 3584, + 0, 3324, 3583, + 0, 3326, 3580, + 0, 3329, 3578, + 0, 3333, 3574, + 0, 3338, 3569, + 0, 3345, 3562, + 0, 3354, 3553, + 0, 3365, 3540, + 0, 3381, 3523, + 0, 3400, 3498, + 0, 3425, 3464, + 0, 3457, 3412, + 0, 3496, 3333, + 0, 3543, 3200, + 0, 3599, 2922, + 0, 3665, 0, + 0, 3741, 0, + 0, 3825, 0, + 0, 3317, 3589, + 0, 3317, 3589, + 0, 3317, 3589, + 0, 3317, 3589, + 0, 3318, 3589, + 0, 3318, 3589, + 0, 3318, 3589, + 0, 3318, 3589, + 0, 3318, 3588, + 0, 3319, 3588, + 0, 3319, 3588, + 0, 3320, 3587, + 0, 3321, 3586, + 0, 3322, 3585, + 0, 3324, 3583, + 0, 3326, 3581, + 0, 3329, 3579, + 0, 3333, 3575, + 0, 3338, 3570, + 0, 3345, 3563, + 0, 3354, 3554, + 0, 3366, 3541, + 0, 3381, 3524, + 0, 3401, 3500, + 0, 3426, 3465, + 0, 3457, 3414, + 0, 3496, 3335, + 0, 3543, 3202, + 0, 3600, 2927, + 0, 3665, 0, + 0, 3741, 0, + 0, 3825, 0, + 0, 3318, 3591, + 0, 3318, 3591, + 0, 3318, 3591, + 0, 3318, 3590, + 0, 3318, 3590, + 0, 3318, 3590, + 0, 3318, 3590, + 0, 3318, 3590, + 0, 3319, 3590, + 0, 3319, 3589, + 0, 3320, 3589, + 0, 3320, 3588, + 0, 3321, 3587, + 0, 3323, 3586, + 0, 3324, 3585, + 0, 3326, 3583, + 0, 3329, 3580, + 0, 3333, 3576, + 0, 3338, 3571, + 0, 3345, 3565, + 0, 3354, 3555, + 0, 3366, 3543, + 0, 3381, 3525, + 0, 3401, 3501, + 0, 3426, 3466, + 0, 3457, 3415, + 0, 3496, 3337, + 0, 3543, 3205, + 0, 3600, 2932, + 0, 3666, 0, + 0, 3741, 0, + 0, 3826, 0, + 0, 3318, 3592, + 0, 3318, 3592, + 0, 3318, 3592, + 0, 3318, 3592, + 0, 3318, 3592, + 0, 3318, 3592, + 0, 3319, 3592, + 0, 3319, 3592, + 0, 3319, 3591, + 0, 3320, 3591, + 0, 3320, 3591, + 0, 3321, 3590, + 0, 3322, 3589, + 0, 3323, 3588, + 0, 3325, 3586, + 0, 3327, 3584, + 0, 3330, 3582, + 0, 3334, 3578, + 0, 3339, 3573, + 0, 3346, 3566, + 0, 3355, 3557, + 0, 3366, 3545, + 0, 3382, 3527, + 0, 3401, 3503, + 0, 3426, 3469, + 0, 3458, 3418, + 0, 3496, 3340, + 0, 3544, 3209, + 0, 3600, 2939, + 0, 3666, 0, + 0, 3741, 0, + 0, 3826, 0, + 0, 3319, 3595, + 0, 3319, 3595, + 0, 3319, 3594, + 0, 3319, 3594, + 0, 3319, 3594, + 0, 3319, 3594, + 0, 3319, 3594, + 0, 3319, 3594, + 0, 3320, 3594, + 0, 3320, 3593, + 0, 3321, 3593, + 0, 3321, 3592, + 0, 3322, 3591, + 0, 3324, 3590, + 0, 3325, 3589, + 0, 3327, 3587, + 0, 3330, 3584, + 0, 3334, 3580, + 0, 3339, 3575, + 0, 3346, 3569, + 0, 3355, 3560, + 0, 3367, 3547, + 0, 3382, 3530, + 0, 3402, 3506, + 0, 3427, 3472, + 0, 3458, 3421, + 0, 3497, 3344, + 0, 3544, 3214, + 0, 3600, 2948, + 0, 3666, 0, + 0, 3741, 0, + 0, 3826, 0, + 0, 3319, 3598, + 0, 3319, 3597, + 0, 3320, 3597, + 0, 3320, 3597, + 0, 3320, 3597, + 0, 3320, 3597, + 0, 3320, 3597, + 0, 3320, 3597, + 0, 3320, 3597, + 0, 3321, 3596, + 0, 3321, 3596, + 0, 3322, 3595, + 0, 3323, 3594, + 0, 3324, 3593, + 0, 3326, 3592, + 0, 3328, 3590, + 0, 3331, 3587, + 0, 3335, 3583, + 0, 3340, 3579, + 0, 3347, 3572, + 0, 3356, 3563, + 0, 3368, 3550, + 0, 3383, 3533, + 0, 3402, 3510, + 0, 3427, 3475, + 0, 3459, 3426, + 0, 3497, 3349, + 0, 3544, 3221, + 0, 3601, 2961, + 0, 3666, 0, + 0, 3742, 0, + 0, 3826, 0, + 0, 3320, 3601, + 0, 3320, 3601, + 0, 3321, 3601, + 0, 3321, 3601, + 0, 3321, 3601, + 0, 3321, 3601, + 0, 3321, 3601, + 0, 3321, 3601, + 0, 3321, 3601, + 0, 3322, 3600, + 0, 3322, 3600, + 0, 3323, 3599, + 0, 3324, 3598, + 0, 3325, 3597, + 0, 3327, 3596, + 0, 3329, 3594, + 0, 3332, 3591, + 0, 3336, 3587, + 0, 3341, 3583, + 0, 3348, 3576, + 0, 3357, 3567, + 0, 3368, 3555, + 0, 3384, 3538, + 0, 3403, 3514, + 0, 3428, 3481, + 0, 3459, 3431, + 0, 3498, 3356, + 0, 3545, 3230, + 0, 3601, 2976, + 0, 3667, 238, + 0, 3742, 0, + 0, 3826, 0, + 0, 3322, 3607, + 0, 3322, 3607, + 0, 3322, 3607, + 0, 3322, 3607, + 0, 3322, 3606, + 0, 3322, 3606, + 0, 3322, 3606, + 0, 3323, 3606, + 0, 3323, 3606, + 0, 3323, 3605, + 0, 3324, 3605, + 0, 3324, 3604, + 0, 3325, 3604, + 0, 3327, 3603, + 0, 3328, 3601, + 0, 3330, 3599, + 0, 3333, 3596, + 0, 3337, 3593, + 0, 3342, 3588, + 0, 3349, 3582, + 0, 3358, 3573, + 0, 3370, 3561, + 0, 3385, 3544, + 0, 3404, 3521, + 0, 3429, 3487, + 0, 3460, 3439, + 0, 3499, 3365, + 0, 3546, 3241, + 0, 3602, 2997, + 0, 3668, 1599, + 0, 3743, 0, + 0, 3827, 0, + 0, 3324, 3614, + 0, 3324, 3614, + 0, 3324, 3614, + 0, 3324, 3613, + 0, 3324, 3613, + 0, 3324, 3613, + 0, 3324, 3613, + 0, 3324, 3613, + 0, 3325, 3613, + 0, 3325, 3612, + 0, 3326, 3612, + 0, 3326, 3611, + 0, 3327, 3611, + 0, 3328, 3609, + 0, 3330, 3608, + 0, 3332, 3606, + 0, 3335, 3603, + 0, 3339, 3600, + 0, 3344, 3595, + 0, 3351, 3589, + 0, 3360, 3580, + 0, 3371, 3568, + 0, 3386, 3552, + 0, 3406, 3529, + 0, 3431, 3496, + 0, 3462, 3449, + 0, 3500, 3376, + 0, 3547, 3257, + 0, 3603, 3023, + 0, 3668, 1971, + 0, 3743, 0, + 0, 3827, 0, + 0, 3326, 3623, + 0, 3326, 3623, + 0, 3326, 3623, + 0, 3326, 3623, + 0, 3326, 3622, + 0, 3326, 3622, + 0, 3327, 3622, + 0, 3327, 3622, + 0, 3327, 3622, + 0, 3327, 3621, + 0, 3328, 3621, + 0, 3329, 3620, + 0, 3330, 3620, + 0, 3331, 3619, + 0, 3332, 3617, + 0, 3335, 3615, + 0, 3337, 3613, + 0, 3341, 3609, + 0, 3346, 3605, + 0, 3353, 3598, + 0, 3362, 3590, + 0, 3374, 3578, + 0, 3388, 3562, + 0, 3408, 3540, + 0, 3432, 3508, + 0, 3463, 3462, + 0, 3502, 3392, + 0, 3548, 3276, + 0, 3604, 3055, + 0, 3669, 2225, + 0, 3744, 0, + 0, 3828, 0, + 0, 3329, 3635, + 0, 3329, 3635, + 0, 3329, 3634, + 0, 3329, 3634, + 0, 3329, 3634, + 0, 3330, 3634, + 0, 3330, 3634, + 0, 3330, 3634, + 0, 3330, 3634, + 0, 3331, 3633, + 0, 3331, 3633, + 0, 3332, 3632, + 0, 3333, 3632, + 0, 3334, 3631, + 0, 3336, 3629, + 0, 3338, 3627, + 0, 3341, 3625, + 0, 3344, 3622, + 0, 3349, 3617, + 0, 3356, 3611, + 0, 3365, 3603, + 0, 3376, 3591, + 0, 3391, 3576, + 0, 3410, 3554, + 0, 3435, 3523, + 0, 3466, 3479, + 0, 3504, 3411, + 0, 3550, 3301, + 0, 3606, 3095, + 0, 3671, 2431, + 0, 3746, 0, + 0, 3829, 0, + 0, 3333, 3650, + 0, 3333, 3650, + 0, 3334, 3650, + 0, 3334, 3650, + 0, 3334, 3650, + 0, 3334, 3650, + 0, 3334, 3649, + 0, 3334, 3649, + 0, 3334, 3649, + 0, 3335, 3649, + 0, 3335, 3648, + 0, 3336, 3648, + 0, 3337, 3647, + 0, 3338, 3646, + 0, 3340, 3645, + 0, 3342, 3643, + 0, 3345, 3641, + 0, 3349, 3637, + 0, 3354, 3633, + 0, 3360, 3627, + 0, 3369, 3619, + 0, 3380, 3608, + 0, 3395, 3593, + 0, 3414, 3572, + 0, 3438, 3543, + 0, 3469, 3500, + 0, 3507, 3436, + 0, 3553, 3333, + 0, 3608, 3144, + 0, 3673, 2611, + 0, 3747, 0, + 0, 3831, 0, + 0, 3339, 3670, + 0, 3339, 3670, + 0, 3339, 3670, + 0, 3339, 3670, + 0, 3339, 3670, + 0, 3339, 3669, + 0, 3340, 3669, + 0, 3340, 3669, + 0, 3340, 3669, + 0, 3340, 3669, + 0, 3341, 3668, + 0, 3342, 3668, + 0, 3343, 3667, + 0, 3344, 3666, + 0, 3345, 3665, + 0, 3347, 3663, + 0, 3350, 3661, + 0, 3354, 3658, + 0, 3359, 3654, + 0, 3365, 3648, + 0, 3374, 3640, + 0, 3385, 3630, + 0, 3400, 3616, + 0, 3419, 3596, + 0, 3443, 3568, + 0, 3473, 3527, + 0, 3511, 3467, + 0, 3556, 3372, + 0, 3611, 3202, + 0, 3676, 2776, + 0, 3750, 0, + 0, 3833, 0, + 1862, 3346, 3695, + 1860, 3347, 3695, + 1858, 3347, 3695, + 1854, 3347, 3695, + 1849, 3347, 3695, + 1842, 3347, 3695, + 1833, 3347, 3695, + 1821, 3347, 3694, + 1803, 3347, 3694, + 1779, 3348, 3694, + 1744, 3348, 3693, + 1694, 3349, 3693, + 1616, 3350, 3692, + 1484, 3351, 3691, + 1214, 3353, 3690, + 0, 3355, 3689, + 0, 3357, 3686, + 0, 3361, 3684, + 0, 3366, 3680, + 0, 3372, 3674, + 0, 3381, 3667, + 0, 3392, 3657, + 0, 3406, 3644, + 0, 3425, 3625, + 0, 3449, 3599, + 0, 3479, 3562, + 0, 3516, 3506, + 0, 3561, 3419, + 0, 3615, 3269, + 0, 3679, 2931, + 0, 3753, 0, + 0, 3835, 0, + 2854, 3356, 3727, + 2854, 3356, 3727, + 2853, 3356, 3726, + 2853, 3356, 3726, + 2853, 3356, 3726, + 2852, 3357, 3726, + 2851, 3357, 3726, + 2849, 3357, 3726, + 2848, 3357, 3726, + 2845, 3358, 3726, + 2842, 3358, 3725, + 2838, 3359, 3725, + 2832, 3360, 3724, + 2824, 3361, 3723, + 2813, 3362, 3722, + 2798, 3364, 3721, + 2778, 3367, 3719, + 2749, 3371, 3716, + 2706, 3375, 3712, + 2643, 3382, 3707, + 2542, 3390, 3701, + 2357, 3401, 3692, + 1850, 3415, 3679, + 0, 3433, 3662, + 0, 3456, 3638, + 0, 3486, 3604, + 0, 3522, 3553, + 0, 3567, 3476, + 0, 3621, 3346, + 0, 3684, 3080, + 0, 3757, 0, + 0, 3838, 0, + 3210, 3369, 3766, + 3209, 3369, 3766, + 3209, 3369, 3766, + 3209, 3369, 3766, + 3209, 3369, 3766, + 3209, 3369, 3765, + 3208, 3369, 3765, + 3207, 3370, 3765, + 3207, 3370, 3765, + 3206, 3370, 3765, + 3204, 3371, 3764, + 3202, 3371, 3764, + 3200, 3372, 3763, + 3196, 3373, 3763, + 3191, 3375, 3762, + 3185, 3377, 3760, + 3176, 3379, 3758, + 3164, 3383, 3756, + 3148, 3387, 3753, + 3125, 3394, 3748, + 3092, 3402, 3742, + 3045, 3412, 3734, + 2972, 3426, 3722, + 2852, 3444, 3707, + 2617, 3467, 3685, + 1537, 3495, 3654, + 0, 3531, 3609, + 0, 3575, 3542, + 0, 3628, 3431, + 0, 3690, 3224, + 0, 3762, 2549, + 0, 3843, 0, + 3457, 3385, 3813, + 3457, 3385, 3813, + 3457, 3385, 3813, + 3457, 3385, 3813, + 3457, 3385, 3813, + 3457, 3386, 3813, + 3457, 3386, 3813, + 3456, 3386, 3813, + 3456, 3386, 3813, + 3455, 3387, 3812, + 3454, 3387, 3812, + 3453, 3388, 3812, + 3452, 3388, 3811, + 3450, 3389, 3811, + 3447, 3391, 3810, + 3443, 3393, 3808, + 3439, 3395, 3807, + 3432, 3399, 3805, + 3423, 3403, 3802, + 3410, 3409, 3797, + 3393, 3417, 3792, + 3369, 3427, 3785, + 3335, 3441, 3774, + 3285, 3458, 3761, + 3208, 3480, 3741, + 3079, 3508, 3714, + 2817, 3543, 3675, + 0, 3586, 3617, + 0, 3637, 3526, + 0, 3698, 3365, + 0, 3769, 2984, + 0, 3849, 0, + 3660, 3406, 3870, + 3660, 3406, 3870, + 3660, 3406, 3870, + 3660, 3406, 3870, + 3660, 3407, 3870, + 3660, 3407, 3870, + 3660, 3407, 3870, + 3660, 3407, 3870, + 3659, 3407, 3869, + 3659, 3408, 3869, + 3658, 3408, 3869, + 3658, 3409, 3869, + 3657, 3409, 3868, + 3655, 3410, 3868, + 3654, 3412, 3867, + 3651, 3414, 3866, + 3648, 3416, 3864, + 3644, 3419, 3862, + 3638, 3424, 3860, + 3631, 3429, 3856, + 3620, 3437, 3851, + 3606, 3446, 3845, + 3586, 3459, 3836, + 3558, 3476, 3824, + 3517, 3497, 3807, + 3456, 3524, 3784, + 3360, 3558, 3750, + 3187, 3599, 3702, + 2750, 3650, 3627, + 0, 3709, 3503, + 0, 3778, 3257, + 0, 3856, 1771, + 3839, 3433, 3936, + 3839, 3433, 3936, + 3839, 3433, 3936, + 3839, 3433, 3936, + 3839, 3433, 3936, + 3839, 3433, 3936, + 3838, 3433, 3936, + 3838, 3434, 3936, + 3838, 3434, 3936, + 3838, 3434, 3936, + 3838, 3435, 3935, + 3837, 3435, 3935, + 3836, 3436, 3935, + 3836, 3437, 3934, + 3834, 3438, 3933, + 3833, 3440, 3932, + 3831, 3442, 3931, + 3828, 3445, 3930, + 3824, 3449, 3927, + 3819, 3455, 3924, + 3812, 3462, 3920, + 3803, 3471, 3914, + 3790, 3483, 3907, + 3772, 3499, 3897, + 3747, 3519, 3882, + 3712, 3545, 3863, + 3659, 3577, 3835, + 3578, 3617, 3795, + 3440, 3665, 3735, + 3149, 3723, 3640, + 0, 3790, 3472, + 0, 3867, 3056, + 4003, 3467, 4012, + 4003, 3467, 4012, + 4003, 3467, 4012, + 4003, 3467, 4012, + 4003, 3467, 4012, + 4003, 3467, 4012, + 4003, 3467, 4012, + 4002, 3467, 4012, + 4002, 3467, 4012, + 4002, 3468, 4011, + 4002, 3468, 4011, + 4002, 3468, 4011, + 4001, 3469, 4011, + 4001, 3470, 4010, + 4000, 3471, 4010, + 3999, 3473, 4009, + 3997, 3475, 4008, + 3995, 3478, 4006, + 3993, 3482, 4004, + 3989, 3487, 4002, + 3984, 3493, 3998, + 3978, 3502, 3994, + 3969, 3513, 3987, + 3957, 3528, 3979, + 3941, 3547, 3967, + 3918, 3571, 3950, + 3886, 3602, 3928, + 3838, 3640, 3895, + 3765, 3686, 3848, + 3646, 3741, 3776, + 3411, 3806, 3657, + 2348, 3880, 3426, + 4095, 3508, 4095, + 4095, 3508, 4095, + 4095, 3508, 4095, + 4095, 3508, 4095, + 4095, 3508, 4095, + 4095, 3508, 4095, + 4095, 3508, 4095, + 4095, 3508, 4095, + 4095, 3508, 4095, + 4095, 3509, 4095, + 4095, 3509, 4095, + 4095, 3509, 4095, + 4095, 3510, 4095, + 4095, 3511, 4095, + 4095, 3512, 4095, + 4095, 3513, 4094, + 4095, 3515, 4093, + 4095, 3518, 4092, + 4095, 3522, 4091, + 4095, 3526, 4088, + 4095, 3532, 4086, + 4095, 3540, 4082, + 4095, 3551, 4076, + 4095, 3564, 4069, + 4095, 3582, 4060, + 4095, 3604, 4046, + 4077, 3633, 4028, + 4046, 3668, 4002, + 4002, 3712, 3965, + 3935, 3764, 3911, + 3826, 3826, 3826, + 3621, 3897, 3679, + 4095, 3558, 4095, + 4095, 3558, 4095, + 4095, 3558, 4095, + 4095, 3558, 4095, + 4095, 3558, 4095, + 4095, 3558, 4095, + 4095, 3558, 4095, + 4095, 3558, 4095, + 4095, 3558, 4095, + 4095, 3558, 4095, + 4095, 3559, 4095, + 4095, 3559, 4095, + 4095, 3560, 4095, + 4095, 3560, 4095, + 4095, 3561, 4095, + 4095, 3563, 4095, + 4095, 3564, 4095, + 4095, 3567, 4095, + 4095, 3570, 4095, + 4095, 3574, 4095, + 4095, 3580, 4095, + 4095, 3587, 4095, + 4095, 3596, 4095, + 4095, 3608, 4095, + 4095, 3624, 4095, + 4095, 3645, 4095, + 4095, 3671, 4095, + 4095, 3704, 4095, + 4095, 3744, 4086, + 4095, 3793, 4045, + 4093, 3851, 3983, + 3990, 3919, 3884, + 0, 3448, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3717, + 0, 3449, 3717, + 0, 3449, 3717, + 0, 3450, 3717, + 0, 3450, 3717, + 0, 3450, 3716, + 0, 3451, 3715, + 0, 3452, 3715, + 0, 3453, 3713, + 0, 3455, 3712, + 0, 3457, 3710, + 0, 3460, 3707, + 0, 3464, 3703, + 0, 3469, 3698, + 0, 3476, 3691, + 0, 3485, 3682, + 0, 3497, 3669, + 0, 3512, 3652, + 0, 3532, 3627, + 0, 3557, 3592, + 0, 3588, 3540, + 0, 3627, 3460, + 0, 3675, 3325, + 0, 3731, 3043, + 0, 3797, 0, + 0, 3873, 0, + 0, 3448, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3717, + 0, 3449, 3717, + 0, 3450, 3717, + 0, 3450, 3717, + 0, 3451, 3716, + 0, 3451, 3715, + 0, 3452, 3715, + 0, 3453, 3713, + 0, 3455, 3712, + 0, 3457, 3710, + 0, 3460, 3707, + 0, 3464, 3703, + 0, 3469, 3698, + 0, 3476, 3692, + 0, 3485, 3682, + 0, 3497, 3670, + 0, 3512, 3652, + 0, 3532, 3627, + 0, 3557, 3592, + 0, 3588, 3540, + 0, 3627, 3460, + 0, 3675, 3325, + 0, 3731, 3043, + 0, 3797, 0, + 0, 3873, 0, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3717, + 0, 3449, 3717, + 0, 3450, 3717, + 0, 3450, 3717, + 0, 3451, 3716, + 0, 3451, 3716, + 0, 3452, 3715, + 0, 3453, 3714, + 0, 3455, 3712, + 0, 3457, 3710, + 0, 3460, 3707, + 0, 3464, 3703, + 0, 3469, 3698, + 0, 3476, 3692, + 0, 3485, 3682, + 0, 3497, 3670, + 0, 3512, 3652, + 0, 3532, 3627, + 0, 3557, 3592, + 0, 3588, 3540, + 0, 3627, 3461, + 0, 3675, 3326, + 0, 3731, 3043, + 0, 3797, 0, + 0, 3873, 0, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3717, + 0, 3450, 3717, + 0, 3450, 3717, + 0, 3451, 3716, + 0, 3451, 3716, + 0, 3452, 3715, + 0, 3453, 3714, + 0, 3455, 3712, + 0, 3457, 3710, + 0, 3460, 3707, + 0, 3464, 3703, + 0, 3469, 3698, + 0, 3476, 3692, + 0, 3485, 3682, + 0, 3497, 3670, + 0, 3512, 3652, + 0, 3532, 3627, + 0, 3557, 3592, + 0, 3588, 3541, + 0, 3627, 3461, + 0, 3675, 3326, + 0, 3731, 3043, + 0, 3797, 0, + 0, 3873, 0, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3717, + 0, 3450, 3717, + 0, 3450, 3717, + 0, 3451, 3716, + 0, 3451, 3716, + 0, 3452, 3715, + 0, 3453, 3714, + 0, 3455, 3712, + 0, 3457, 3710, + 0, 3460, 3707, + 0, 3464, 3704, + 0, 3469, 3699, + 0, 3476, 3692, + 0, 3485, 3682, + 0, 3497, 3670, + 0, 3512, 3652, + 0, 3532, 3628, + 0, 3557, 3592, + 0, 3588, 3541, + 0, 3627, 3461, + 0, 3675, 3326, + 0, 3731, 3044, + 0, 3797, 0, + 0, 3873, 0, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3450, 3717, + 0, 3450, 3717, + 0, 3451, 3716, + 0, 3451, 3716, + 0, 3452, 3715, + 0, 3453, 3714, + 0, 3455, 3712, + 0, 3457, 3710, + 0, 3460, 3707, + 0, 3464, 3704, + 0, 3469, 3699, + 0, 3476, 3692, + 0, 3485, 3683, + 0, 3497, 3670, + 0, 3512, 3652, + 0, 3532, 3628, + 0, 3557, 3593, + 0, 3588, 3541, + 0, 3627, 3461, + 0, 3675, 3326, + 0, 3731, 3044, + 0, 3797, 0, + 0, 3873, 0, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3450, 3717, + 0, 3450, 3717, + 0, 3451, 3717, + 0, 3451, 3716, + 0, 3452, 3715, + 0, 3454, 3714, + 0, 3455, 3712, + 0, 3457, 3710, + 0, 3460, 3708, + 0, 3464, 3704, + 0, 3469, 3699, + 0, 3476, 3692, + 0, 3485, 3683, + 0, 3497, 3670, + 0, 3512, 3653, + 0, 3532, 3628, + 0, 3557, 3593, + 0, 3588, 3541, + 0, 3627, 3461, + 0, 3675, 3327, + 0, 3731, 3045, + 0, 3797, 0, + 0, 3873, 0, + 0, 3449, 3719, + 0, 3449, 3719, + 0, 3449, 3719, + 0, 3449, 3719, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3450, 3718, + 0, 3450, 3717, + 0, 3451, 3717, + 0, 3451, 3716, + 0, 3452, 3715, + 0, 3454, 3714, + 0, 3455, 3713, + 0, 3457, 3711, + 0, 3460, 3708, + 0, 3464, 3704, + 0, 3470, 3699, + 0, 3476, 3692, + 0, 3485, 3683, + 0, 3497, 3670, + 0, 3512, 3653, + 0, 3532, 3628, + 0, 3557, 3593, + 0, 3589, 3541, + 0, 3627, 3462, + 0, 3675, 3327, + 0, 3731, 3046, + 0, 3797, 0, + 0, 3873, 0, + 0, 3449, 3719, + 0, 3449, 3719, + 0, 3449, 3719, + 0, 3449, 3719, + 0, 3449, 3719, + 0, 3449, 3719, + 0, 3449, 3719, + 0, 3449, 3718, + 0, 3450, 3718, + 0, 3450, 3718, + 0, 3450, 3718, + 0, 3451, 3717, + 0, 3451, 3716, + 0, 3452, 3716, + 0, 3454, 3714, + 0, 3455, 3713, + 0, 3458, 3711, + 0, 3460, 3708, + 0, 3464, 3704, + 0, 3470, 3699, + 0, 3476, 3693, + 0, 3485, 3683, + 0, 3497, 3671, + 0, 3512, 3653, + 0, 3532, 3629, + 0, 3557, 3593, + 0, 3589, 3542, + 0, 3627, 3462, + 0, 3675, 3328, + 0, 3731, 3047, + 0, 3797, 0, + 0, 3873, 0, + 0, 3449, 3719, + 0, 3449, 3719, + 0, 3449, 3719, + 0, 3449, 3719, + 0, 3449, 3719, + 0, 3449, 3719, + 0, 3449, 3719, + 0, 3449, 3719, + 0, 3450, 3719, + 0, 3450, 3718, + 0, 3450, 3718, + 0, 3451, 3718, + 0, 3452, 3717, + 0, 3452, 3716, + 0, 3454, 3715, + 0, 3455, 3713, + 0, 3458, 3711, + 0, 3461, 3709, + 0, 3465, 3705, + 0, 3470, 3700, + 0, 3477, 3693, + 0, 3486, 3684, + 0, 3497, 3671, + 0, 3513, 3654, + 0, 3532, 3629, + 0, 3557, 3594, + 0, 3589, 3542, + 0, 3628, 3463, + 0, 3675, 3329, + 0, 3731, 3049, + 0, 3797, 0, + 0, 3873, 0, + 0, 3449, 3720, + 0, 3449, 3720, + 0, 3449, 3720, + 0, 3449, 3720, + 0, 3449, 3720, + 0, 3449, 3720, + 0, 3449, 3719, + 0, 3450, 3719, + 0, 3450, 3719, + 0, 3450, 3719, + 0, 3450, 3719, + 0, 3451, 3718, + 0, 3452, 3717, + 0, 3453, 3717, + 0, 3454, 3715, + 0, 3456, 3714, + 0, 3458, 3712, + 0, 3461, 3709, + 0, 3465, 3705, + 0, 3470, 3700, + 0, 3477, 3694, + 0, 3486, 3684, + 0, 3497, 3672, + 0, 3513, 3654, + 0, 3532, 3630, + 0, 3557, 3595, + 0, 3589, 3543, + 0, 3628, 3464, + 0, 3675, 3330, + 0, 3731, 3051, + 0, 3797, 0, + 0, 3873, 0, + 0, 3449, 3721, + 0, 3449, 3721, + 0, 3449, 3720, + 0, 3449, 3720, + 0, 3449, 3720, + 0, 3449, 3720, + 0, 3450, 3720, + 0, 3450, 3720, + 0, 3450, 3720, + 0, 3450, 3720, + 0, 3451, 3719, + 0, 3451, 3719, + 0, 3452, 3718, + 0, 3453, 3717, + 0, 3454, 3716, + 0, 3456, 3715, + 0, 3458, 3713, + 0, 3461, 3710, + 0, 3465, 3706, + 0, 3470, 3701, + 0, 3477, 3694, + 0, 3486, 3685, + 0, 3498, 3672, + 0, 3513, 3655, + 0, 3532, 3631, + 0, 3557, 3596, + 0, 3589, 3544, + 0, 3628, 3465, + 0, 3675, 3332, + 0, 3731, 3055, + 0, 3797, 0, + 0, 3873, 0, + 0, 3449, 3721, + 0, 3449, 3721, + 0, 3449, 3721, + 0, 3450, 3721, + 0, 3450, 3721, + 0, 3450, 3721, + 0, 3450, 3721, + 0, 3450, 3721, + 0, 3450, 3721, + 0, 3450, 3721, + 0, 3451, 3720, + 0, 3451, 3720, + 0, 3452, 3719, + 0, 3453, 3718, + 0, 3454, 3717, + 0, 3456, 3716, + 0, 3458, 3714, + 0, 3461, 3711, + 0, 3465, 3707, + 0, 3470, 3702, + 0, 3477, 3695, + 0, 3486, 3686, + 0, 3498, 3674, + 0, 3513, 3656, + 0, 3533, 3632, + 0, 3558, 3597, + 0, 3589, 3546, + 0, 3628, 3467, + 0, 3675, 3334, + 0, 3732, 3059, + 0, 3798, 0, + 0, 3873, 0, + 0, 3450, 3723, + 0, 3450, 3723, + 0, 3450, 3723, + 0, 3450, 3723, + 0, 3450, 3723, + 0, 3450, 3723, + 0, 3450, 3722, + 0, 3450, 3722, + 0, 3451, 3722, + 0, 3451, 3722, + 0, 3451, 3721, + 0, 3452, 3721, + 0, 3452, 3720, + 0, 3453, 3719, + 0, 3455, 3718, + 0, 3456, 3717, + 0, 3458, 3715, + 0, 3461, 3712, + 0, 3465, 3708, + 0, 3471, 3703, + 0, 3477, 3697, + 0, 3486, 3687, + 0, 3498, 3675, + 0, 3513, 3658, + 0, 3533, 3633, + 0, 3558, 3599, + 0, 3589, 3548, + 0, 3628, 3469, + 0, 3675, 3337, + 0, 3732, 3064, + 0, 3798, 0, + 0, 3873, 0, + 0, 3450, 3724, + 0, 3450, 3724, + 0, 3450, 3724, + 0, 3450, 3724, + 0, 3450, 3724, + 0, 3450, 3724, + 0, 3451, 3724, + 0, 3451, 3724, + 0, 3451, 3724, + 0, 3451, 3723, + 0, 3452, 3723, + 0, 3452, 3723, + 0, 3453, 3722, + 0, 3454, 3721, + 0, 3455, 3720, + 0, 3457, 3719, + 0, 3459, 3717, + 0, 3462, 3714, + 0, 3466, 3710, + 0, 3471, 3705, + 0, 3478, 3698, + 0, 3487, 3689, + 0, 3498, 3677, + 0, 3514, 3659, + 0, 3533, 3635, + 0, 3558, 3601, + 0, 3590, 3550, + 0, 3628, 3472, + 0, 3676, 3341, + 0, 3732, 3071, + 0, 3798, 0, + 0, 3873, 0, + 0, 3451, 3727, + 0, 3451, 3727, + 0, 3451, 3727, + 0, 3451, 3727, + 0, 3451, 3727, + 0, 3451, 3726, + 0, 3451, 3726, + 0, 3451, 3726, + 0, 3452, 3726, + 0, 3452, 3726, + 0, 3452, 3725, + 0, 3453, 3725, + 0, 3453, 3724, + 0, 3454, 3723, + 0, 3456, 3722, + 0, 3457, 3721, + 0, 3459, 3719, + 0, 3462, 3716, + 0, 3466, 3712, + 0, 3471, 3708, + 0, 3478, 3701, + 0, 3487, 3692, + 0, 3499, 3679, + 0, 3514, 3662, + 0, 3534, 3638, + 0, 3559, 3604, + 0, 3590, 3553, + 0, 3629, 3476, + 0, 3676, 3346, + 0, 3732, 3081, + 0, 3798, 0, + 0, 3873, 0, + 0, 3451, 3730, + 0, 3452, 3730, + 0, 3452, 3730, + 0, 3452, 3730, + 0, 3452, 3729, + 0, 3452, 3729, + 0, 3452, 3729, + 0, 3452, 3729, + 0, 3452, 3729, + 0, 3453, 3729, + 0, 3453, 3728, + 0, 3453, 3728, + 0, 3454, 3727, + 0, 3455, 3726, + 0, 3456, 3725, + 0, 3458, 3724, + 0, 3460, 3722, + 0, 3463, 3719, + 0, 3467, 3716, + 0, 3472, 3711, + 0, 3479, 3704, + 0, 3488, 3695, + 0, 3500, 3683, + 0, 3515, 3666, + 0, 3534, 3642, + 0, 3559, 3608, + 0, 3591, 3558, + 0, 3629, 3481, + 0, 3676, 3353, + 0, 3733, 3093, + 0, 3798, 0, + 0, 3874, 0, + 0, 3453, 3734, + 0, 3453, 3734, + 0, 3453, 3734, + 0, 3453, 3734, + 0, 3453, 3733, + 0, 3453, 3733, + 0, 3453, 3733, + 0, 3453, 3733, + 0, 3453, 3733, + 0, 3454, 3733, + 0, 3454, 3732, + 0, 3454, 3732, + 0, 3455, 3731, + 0, 3456, 3730, + 0, 3457, 3729, + 0, 3459, 3728, + 0, 3461, 3726, + 0, 3464, 3723, + 0, 3468, 3720, + 0, 3473, 3715, + 0, 3480, 3708, + 0, 3489, 3699, + 0, 3501, 3687, + 0, 3516, 3670, + 0, 3535, 3646, + 0, 3560, 3613, + 0, 3591, 3563, + 0, 3630, 3488, + 0, 3677, 3362, + 0, 3733, 3109, + 0, 3799, 370, + 0, 3874, 0, + 0, 3454, 3739, + 0, 3454, 3739, + 0, 3454, 3739, + 0, 3454, 3739, + 0, 3454, 3739, + 0, 3454, 3739, + 0, 3454, 3738, + 0, 3454, 3738, + 0, 3455, 3738, + 0, 3455, 3738, + 0, 3455, 3738, + 0, 3456, 3737, + 0, 3457, 3737, + 0, 3457, 3736, + 0, 3459, 3735, + 0, 3460, 3733, + 0, 3463, 3731, + 0, 3465, 3729, + 0, 3469, 3725, + 0, 3474, 3720, + 0, 3481, 3714, + 0, 3490, 3705, + 0, 3502, 3693, + 0, 3517, 3676, + 0, 3536, 3653, + 0, 3561, 3620, + 0, 3592, 3571, + 0, 3631, 3497, + 0, 3678, 3374, + 0, 3734, 3129, + 0, 3800, 1731, + 0, 3875, 0, + 0, 3456, 3746, + 0, 3456, 3746, + 0, 3456, 3746, + 0, 3456, 3746, + 0, 3456, 3746, + 0, 3456, 3745, + 0, 3456, 3745, + 0, 3456, 3745, + 0, 3456, 3745, + 0, 3457, 3745, + 0, 3457, 3744, + 0, 3458, 3744, + 0, 3458, 3743, + 0, 3459, 3743, + 0, 3460, 3742, + 0, 3462, 3740, + 0, 3464, 3738, + 0, 3467, 3736, + 0, 3471, 3732, + 0, 3476, 3727, + 0, 3483, 3721, + 0, 3492, 3712, + 0, 3503, 3700, + 0, 3518, 3684, + 0, 3538, 3661, + 0, 3563, 3629, + 0, 3594, 3581, + 0, 3632, 3508, + 0, 3679, 3389, + 0, 3735, 3155, + 0, 3800, 2103, + 0, 3875, 0, + 0, 3458, 3755, + 0, 3458, 3755, + 0, 3458, 3755, + 0, 3458, 3755, + 0, 3458, 3755, + 0, 3458, 3755, + 0, 3458, 3754, + 0, 3459, 3754, + 0, 3459, 3754, + 0, 3459, 3754, + 0, 3460, 3754, + 0, 3460, 3753, + 0, 3461, 3753, + 0, 3462, 3752, + 0, 3463, 3751, + 0, 3465, 3749, + 0, 3467, 3747, + 0, 3470, 3745, + 0, 3473, 3741, + 0, 3479, 3737, + 0, 3485, 3731, + 0, 3494, 3722, + 0, 3506, 3710, + 0, 3521, 3694, + 0, 3540, 3672, + 0, 3565, 3640, + 0, 3595, 3594, + 0, 3634, 3524, + 0, 3681, 3409, + 0, 3736, 3187, + 0, 3802, 2357, + 0, 3876, 0, + 0, 3461, 3767, + 0, 3461, 3767, + 0, 3461, 3767, + 0, 3461, 3767, + 0, 3461, 3767, + 0, 3462, 3766, + 0, 3462, 3766, + 0, 3462, 3766, + 0, 3462, 3766, + 0, 3462, 3766, + 0, 3463, 3765, + 0, 3463, 3765, + 0, 3464, 3764, + 0, 3465, 3764, + 0, 3466, 3763, + 0, 3468, 3761, + 0, 3470, 3759, + 0, 3473, 3757, + 0, 3477, 3754, + 0, 3482, 3749, + 0, 3488, 3743, + 0, 3497, 3735, + 0, 3508, 3723, + 0, 3523, 3708, + 0, 3543, 3686, + 0, 3567, 3655, + 0, 3598, 3611, + 0, 3636, 3543, + 0, 3682, 3434, + 0, 3738, 3227, + 0, 3803, 2563, + 0, 3878, 0, + 0, 3466, 3782, + 0, 3466, 3782, + 0, 3466, 3782, + 0, 3466, 3782, + 0, 3466, 3782, + 0, 3466, 3782, + 0, 3466, 3782, + 0, 3466, 3782, + 0, 3466, 3781, + 0, 3467, 3781, + 0, 3467, 3781, + 0, 3467, 3780, + 0, 3468, 3780, + 0, 3469, 3779, + 0, 3470, 3778, + 0, 3472, 3777, + 0, 3474, 3775, + 0, 3477, 3773, + 0, 3481, 3769, + 0, 3486, 3765, + 0, 3492, 3759, + 0, 3501, 3751, + 0, 3512, 3740, + 0, 3527, 3725, + 0, 3546, 3704, + 0, 3570, 3675, + 0, 3601, 3632, + 0, 3639, 3568, + 0, 3685, 3465, + 0, 3740, 3276, + 0, 3805, 2743, + 0, 3879, 0, + 0, 3471, 3802, + 0, 3471, 3802, + 0, 3471, 3802, + 0, 3471, 3802, + 0, 3471, 3802, + 0, 3471, 3802, + 0, 3472, 3802, + 0, 3472, 3801, + 0, 3472, 3801, + 0, 3472, 3801, + 0, 3473, 3801, + 0, 3473, 3800, + 0, 3474, 3800, + 0, 3475, 3799, + 0, 3476, 3798, + 0, 3477, 3797, + 0, 3480, 3795, + 0, 3482, 3793, + 0, 3486, 3790, + 0, 3491, 3786, + 0, 3498, 3780, + 0, 3506, 3772, + 0, 3517, 3762, + 0, 3532, 3748, + 0, 3551, 3728, + 0, 3575, 3700, + 0, 3605, 3660, + 0, 3643, 3599, + 0, 3689, 3504, + 0, 3743, 3334, + 0, 3808, 2908, + 0, 3882, 0, + 1996, 3479, 3827, + 1994, 3479, 3827, + 1992, 3479, 3827, + 1990, 3479, 3827, + 1986, 3479, 3827, + 1981, 3479, 3827, + 1974, 3479, 3827, + 1965, 3479, 3827, + 1953, 3479, 3826, + 1935, 3480, 3826, + 1911, 3480, 3826, + 1877, 3480, 3826, + 1826, 3481, 3825, + 1748, 3482, 3824, + 1616, 3483, 3824, + 1346, 3485, 3822, + 0, 3487, 3821, + 0, 3490, 3819, + 0, 3493, 3816, + 0, 3498, 3812, + 0, 3505, 3806, + 0, 3513, 3799, + 0, 3524, 3789, + 0, 3538, 3776, + 0, 3557, 3757, + 0, 3581, 3731, + 0, 3611, 3694, + 0, 3648, 3638, + 0, 3693, 3551, + 0, 3748, 3401, + 0, 3811, 3063, + 0, 3885, 0, + 2986, 3488, 3859, + 2986, 3488, 3859, + 2986, 3488, 3859, + 2986, 3488, 3859, + 2985, 3488, 3859, + 2985, 3489, 3858, + 2984, 3489, 3858, + 2983, 3489, 3858, + 2982, 3489, 3858, + 2980, 3489, 3858, + 2977, 3490, 3858, + 2974, 3490, 3857, + 2970, 3491, 3857, + 2964, 3492, 3856, + 2956, 3493, 3855, + 2945, 3494, 3854, + 2931, 3496, 3853, + 2910, 3499, 3851, + 2881, 3503, 3848, + 2839, 3507, 3844, + 2775, 3514, 3839, + 2674, 3522, 3833, + 2489, 3533, 3824, + 1982, 3547, 3811, + 0, 3565, 3794, + 0, 3589, 3770, + 0, 3618, 3736, + 0, 3655, 3685, + 0, 3699, 3608, + 0, 3753, 3478, + 0, 3816, 3212, + 0, 3889, 0, + 3342, 3501, 3898, + 3342, 3501, 3898, + 3342, 3501, 3898, + 3341, 3501, 3898, + 3341, 3501, 3898, + 3341, 3501, 3898, + 3341, 3501, 3898, + 3340, 3501, 3897, + 3340, 3502, 3897, + 3339, 3502, 3897, + 3338, 3502, 3897, + 3336, 3503, 3897, + 3334, 3503, 3896, + 3332, 3504, 3896, + 3328, 3505, 3895, + 3323, 3507, 3894, + 3317, 3509, 3892, + 3308, 3511, 3891, + 3296, 3515, 3888, + 3280, 3520, 3885, + 3257, 3526, 3880, + 3224, 3534, 3874, + 3177, 3544, 3866, + 3104, 3558, 3854, + 2984, 3576, 3839, + 2749, 3599, 3817, + 1669, 3628, 3786, + 0, 3663, 3741, + 0, 3707, 3674, + 0, 3760, 3564, + 0, 3822, 3356, + 0, 3894, 2681, + 3590, 3517, 3945, + 3590, 3517, 3945, + 3590, 3517, 3945, + 3589, 3517, 3945, + 3589, 3518, 3945, + 3589, 3518, 3945, + 3589, 3518, 3945, + 3589, 3518, 3945, + 3588, 3518, 3945, + 3588, 3518, 3945, + 3587, 3519, 3945, + 3586, 3519, 3944, + 3585, 3520, 3944, + 3584, 3520, 3943, + 3582, 3522, 3943, + 3579, 3523, 3942, + 3576, 3525, 3941, + 3571, 3527, 3939, + 3564, 3531, 3937, + 3555, 3535, 3934, + 3543, 3541, 3930, + 3525, 3549, 3924, + 3501, 3559, 3917, + 3467, 3573, 3907, + 3417, 3590, 3893, + 3340, 3612, 3873, + 3211, 3640, 3846, + 2949, 3675, 3807, + 0, 3718, 3749, + 0, 3769, 3658, + 0, 3830, 3497, + 0, 3901, 3116, + 3792, 3538, 4002, + 3792, 3538, 4002, + 3792, 3538, 4002, + 3792, 3539, 4002, + 3792, 3539, 4002, + 3792, 3539, 4002, + 3792, 3539, 4002, + 3792, 3539, 4002, + 3792, 3539, 4002, + 3791, 3539, 4002, + 3791, 3540, 4001, + 3790, 3540, 4001, + 3790, 3541, 4001, + 3789, 3541, 4000, + 3787, 3542, 4000, + 3786, 3544, 3999, + 3783, 3546, 3998, + 3780, 3548, 3996, + 3776, 3551, 3994, + 3770, 3556, 3992, + 3763, 3561, 3988, + 3752, 3569, 3983, + 3738, 3579, 3977, + 3718, 3591, 3968, + 3690, 3608, 3956, + 3649, 3629, 3939, + 3588, 3656, 3916, + 3492, 3690, 3882, + 3319, 3731, 3834, + 2882, 3782, 3759, + 0, 3841, 3636, + 0, 3910, 3389, + 3971, 3565, 4068, + 3971, 3565, 4068, + 3971, 3565, 4068, + 3971, 3565, 4068, + 3971, 3565, 4068, + 3971, 3565, 4068, + 3971, 3565, 4068, + 3971, 3566, 4068, + 3970, 3566, 4068, + 3970, 3566, 4068, + 3970, 3566, 4068, + 3970, 3567, 4067, + 3969, 3567, 4067, + 3968, 3568, 4067, + 3968, 3569, 4066, + 3966, 3570, 4066, + 3965, 3572, 4065, + 3963, 3574, 4063, + 3960, 3577, 4062, + 3956, 3581, 4059, + 3951, 3587, 4056, + 3944, 3594, 4052, + 3935, 3603, 4047, + 3922, 3615, 4039, + 3904, 3631, 4029, + 3879, 3651, 4014, + 3844, 3677, 3995, + 3791, 3709, 3967, + 3710, 3749, 3927, + 3572, 3797, 3867, + 3281, 3855, 3772, + 0, 3922, 3604, + 4095, 3599, 4095, + 4095, 3599, 4095, + 4095, 3599, 4095, + 4095, 3599, 4095, + 4095, 3599, 4095, + 4095, 3599, 4095, + 4095, 3599, 4095, + 4095, 3599, 4095, + 4095, 3599, 4095, + 4095, 3599, 4095, + 4095, 3600, 4095, + 4095, 3600, 4095, + 4095, 3601, 4095, + 4095, 3601, 4095, + 4095, 3602, 4095, + 4095, 3603, 4095, + 4095, 3605, 4095, + 4095, 3607, 4095, + 4095, 3610, 4095, + 4095, 3614, 4095, + 4095, 3619, 4095, + 4095, 3625, 4095, + 4095, 3634, 4095, + 4095, 3645, 4095, + 4090, 3660, 4095, + 4073, 3679, 4095, + 4050, 3703, 4083, + 4018, 3734, 4060, + 3970, 3772, 4027, + 3897, 3818, 3980, + 3778, 3873, 3908, + 3543, 3938, 3789, + 4095, 3640, 4095, + 4095, 3640, 4095, + 4095, 3640, 4095, + 4095, 3640, 4095, + 4095, 3640, 4095, + 4095, 3640, 4095, + 4095, 3640, 4095, + 4095, 3640, 4095, + 4095, 3640, 4095, + 4095, 3641, 4095, + 4095, 3641, 4095, + 4095, 3641, 4095, + 4095, 3642, 4095, + 4095, 3642, 4095, + 4095, 3643, 4095, + 4095, 3644, 4095, + 4095, 3646, 4095, + 4095, 3648, 4095, + 4095, 3650, 4095, + 4095, 3654, 4095, + 4095, 3658, 4095, + 4095, 3664, 4095, + 4095, 3672, 4095, + 4095, 3683, 4095, + 4095, 3696, 4095, + 4095, 3714, 4095, + 4095, 3736, 4095, + 4095, 3765, 4095, + 4095, 3800, 4095, + 4095, 3844, 4095, + 4067, 3896, 4043, + 3958, 3958, 3958 +] + } +} diff --git a/Gems/Atom/Feature/Common/Assets/ColorGrading/TestData/Photoshop/inv-Log2-48nits/Test_3DL_32_LUT.azasset b/Gems/Atom/Feature/Common/Assets/ColorGrading/TestData/Photoshop/inv-Log2-48nits/Test_3DL_32_LUT.azasset new file mode 100644 index 0000000000..b643955084 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/ColorGrading/TestData/Photoshop/inv-Log2-48nits/Test_3DL_32_LUT.azasset @@ -0,0 +1,4922 @@ +{ + "Type": "JsonSerialization", + "Version": 1, + "ClassName": "LookupTableAsset", + "ClassData": { + "Name": "LookupTable", + "Intervals": [0, 64, 128, 192, 256, 320, 384, 448, 512, 575, 639, 703, 767, 831, 895, 959, 1023], + "Values": [128, 193, 337, +96, 193, 353, +145, 241, 418, +177, 273, 514, +225, 273, 562, +337, 337, 707, +385, 385, 803, +450, 450, 883, +562, 514, 996, +594, 578, 1108, +691, 658, 1220, +739, 723, 1317, +803, 787, 1429, +915, 867, 1574, +980, 915, 1638, +1028, 996, 1766, +1092, 1044, 1847, +257, 353, 401, +289, 353, 434, +305, 369, 514, +273, 385, 594, +321, 385, 642, +353, 466, 771, +434, 482, 835, +498, 562, 964, +562, 594, 1060, +642, 658, 1140, +691, 723, 1253, +755, 787, 1349, +851, 835, 1477, +899, 899, 1574, +947, 964, 1670, +1044, 1044, 1783, +1124, 1076, 1863, +337, 530, 482, +385, 546, 530, +401, 562, 594, +401, 562, 691, +434, 594, 771, +450, 642, 867, +482, 642, 931, +562, 674, 1028, +610, 739, 1108, +658, 771, 1204, +739, 819, 1317, +851, 899, 1445, +867, 915, 1510, +947, 980, 1590, +1012, 1044, 1718, +1060, 1076, 1815, +1140, 1140, 1927, +466, 771, 642, +482, 771, 691, +482, 771, 755, +514, 787, 803, +514, 803, 915, +578, 803, 964, +626, 851, 1044, +658, 867, 1124, +707, 899, 1220, +771, 931, 1301, +787, 947, 1381, +883, 1012, 1477, +931, 1044, 1590, +1012, 1108, 1686, +1044, 1140, 1766, +1140, 1204, 1879, +1188, 1253, 1991, +691, 1012, 755, +674, 1012, 803, +674, 980, 883, +658, 980, 947, +658, 1012, 980, +642, 1012, 1092, +707, 1012, 1156, +755, 1060, 1269, +771, 1060, 1317, +835, 1108, 1397, +931, 1156, 1510, +947, 1156, 1574, +980, 1188, 1654, +1076, 1237, 1783, +1140, 1285, 1863, +1188, 1301, 1911, +1237, 1349, 2023, +851, 1220, 899, +803, 1204, 931, +835, 1204, 996, +819, 1204, 1060, +835, 1204, 1124, +867, 1204, 1156, +883, 1220, 1253, +899, 1237, 1349, +931, 1253, 1429, +996, 1269, 1510, +996, 1317, 1590, +1060, 1349, 1670, +1124, 1349, 1750, +1156, 1397, 1847, +1253, 1429, 1943, +1285, 1461, 2039, +1333, 1477, 2104, +980, 1413, 1012, +980, 1429, 1060, +980, 1413, 1108, +980, 1413, 1172, +996, 1397, 1237, +1012, 1429, 1333, +1044, 1429, 1365, +1076, 1445, 1445, +1044, 1445, 1526, +1124, 1477, 1622, +1140, 1493, 1702, +1156, 1493, 1750, +1188, 1558, 1863, +1285, 1558, 1943, +1349, 1590, 2023, +1381, 1622, 2104, +1461, 1654, 2216, +1156, 1606, 1124, +1140, 1622, 1172, +1140, 1606, 1253, +1172, 1622, 1317, +1188, 1622, 1381, +1172, 1638, 1445, +1188, 1638, 1510, +1220, 1638, 1542, +1237, 1638, 1606, +1301, 1654, 1718, +1333, 1670, 1799, +1365, 1702, 1879, +1397, 1734, 1975, +1429, 1734, 2039, +1477, 1766, 2104, +1526, 1815, 2216, +1558, 1831, 2296, +1317, 1815, 1285, +1285, 1831, 1317, +1301, 1831, 1365, +1317, 1815, 1397, +1333, 1799, 1445, +1349, 1831, 1542, +1381, 1831, 1622, +1381, 1815, 1654, +1413, 1863, 1734, +1461, 1863, 1799, +1477, 1863, 1895, +1510, 1895, 1991, +1542, 1895, 2023, +1638, 1943, 2136, +1670, 1927, 2184, +1670, 1943, 2264, +1734, 1991, 2377, +1542, 2007, 1381, +1510, 2023, 1381, +1526, 2023, 1445, +1542, 2023, 1526, +1542, 2007, 1590, +1574, 2023, 1654, +1558, 2023, 1686, +1606, 2039, 1766, +1606, 2023, 1815, +1654, 2056, 1863, +1686, 2072, 1943, +1718, 2088, 2072, +1734, 2104, 2168, +1766, 2120, 2248, +1847, 2136, 2296, +1927, 2152, 2361, +1975, 2184, 2457, +1734, 2232, 1493, +1766, 2248, 1510, +1734, 2232, 1526, +1766, 2248, 1590, +1766, 2232, 1686, +1815, 2232, 1766, +1799, 2232, 1815, +1847, 2264, 1927, +1831, 2264, 1927, +1879, 2280, 2007, +1895, 2280, 2072, +1911, 2280, 2136, +1959, 2312, 2232, +1975, 2329, 2345, +2023, 2361, 2425, +2072, 2329, 2441, +2104, 2361, 2537, +1975, 2457, 1654, +1943, 2457, 1638, +1959, 2457, 1670, +1975, 2441, 1734, +1991, 2441, 1799, +2007, 2441, 1895, +2023, 2441, 1943, +2023, 2441, 1991, +2023, 2441, 2072, +2072, 2473, 2168, +2104, 2473, 2200, +2120, 2473, 2264, +2184, 2489, 2296, +2216, 2505, 2377, +2200, 2521, 2537, +2248, 2553, 2634, +2264, 2537, 2682, +2152, 2650, 1734, +2168, 2634, 1783, +2120, 2650, 1815, +2136, 2650, 1879, +2168, 2650, 1959, +2200, 2650, 2023, +2216, 2650, 2088, +2200, 2666, 2120, +2248, 2682, 2200, +2232, 2682, 2264, +2248, 2682, 2329, +2280, 2682, 2377, +2312, 2698, 2457, +2345, 2714, 2537, +2361, 2714, 2602, +2393, 2730, 2714, +2425, 2762, 2810, +2312, 2858, 1895, +2329, 2858, 1895, +2329, 2875, 1959, +2296, 2858, 1991, +2329, 2875, 2056, +2345, 2858, 2120, +2377, 2875, 2184, +2377, 2875, 2296, +2393, 2891, 2329, +2409, 2875, 2361, +2473, 2875, 2441, +2441, 2875, 2489, +2489, 2891, 2553, +2521, 2907, 2618, +2537, 2907, 2698, +2585, 2923, 2778, +2618, 2955, 2907, +2553, 3067, 2023, +2537, 3067, 2056, +2489, 3067, 2088, +2521, 3067, 2120, +2537, 3051, 2184, +2537, 3051, 2280, +2585, 3067, 2312, +2602, 3051, 2377, +2602, 3083, 2425, +2602, 3067, 2505, +2618, 3083, 2553, +2634, 3083, 2618, +2666, 3083, 2666, +2698, 3083, 2714, +2730, 3115, 2794, +2746, 3115, 2907, +2778, 3131, 2987, +2714, 3276, 2184, +2714, 3276, 2216, +2682, 3292, 2232, +2698, 3292, 2280, +2698, 3292, 2296, +2746, 3276, 2393, +2730, 3292, 2457, +2762, 3292, 2521, +2762, 3276, 2585, +2778, 3260, 2634, +2746, 3260, 2698, +2810, 3276, 2746, +2842, 3292, 2842, +2826, 3292, 2858, +2858, 3292, 2907, +2875, 3308, 3003, +2923, 3324, 3067, +2891, 3501, 2345, +2891, 3485, 2377, +2875, 3485, 2361, +2842, 3501, 2377, +2858, 3485, 2425, +2907, 3501, 2521, +2907, 3485, 2602, +2939, 3485, 2650, +2939, 3469, 2698, +2955, 3501, 2762, +2955, 3485, 2810, +3035, 3485, 2891, +3019, 3501, 2971, +3067, 3517, 3051, +3067, 3517, 3115, +3115, 3533, 3164, +3099, 3549, 3244, +273, 225, 353, +273, 241, 385, +225, 273, 450, +257, 257, 514, +305, 321, 626, +369, 353, 707, +434, 434, 819, +498, 482, 915, +562, 562, 1028, +594, 594, 1124, +723, 658, 1220, +755, 723, 1333, +819, 819, 1445, +899, 883, 1590, +980, 915, 1638, +1060, 1012, 1750, +1108, 1060, 1863, +337, 353, 401, +337, 369, 450, +321, 401, 546, +337, 401, 594, +369, 434, 707, +418, 466, 771, +466, 514, 867, +546, 578, 996, +578, 626, 1076, +691, 674, 1156, +723, 739, 1269, +755, 803, 1365, +867, 851, 1493, +931, 915, 1558, +996, 980, 1670, +1060, 1044, 1783, +1124, 1076, 1863, +434, 546, 482, +418, 562, 546, +466, 594, 626, +466, 594, 707, +466, 642, 819, +482, 642, 867, +514, 674, 964, +578, 707, 1028, +626, 755, 1140, +707, 787, 1220, +755, 835, 1333, +835, 883, 1429, +915, 931, 1510, +947, 996, 1606, +1028, 1060, 1734, +1076, 1076, 1799, +1140, 1140, 1927, +562, 771, 594, +530, 787, 707, +546, 803, 771, +578, 803, 803, +578, 803, 867, +594, 819, 980, +642, 867, 1076, +658, 883, 1140, +739, 915, 1237, +771, 931, 1301, +787, 980, 1413, +883, 1012, 1493, +947, 1060, 1574, +996, 1108, 1670, +1060, 1140, 1783, +1140, 1204, 1879, +1220, 1237, 1991, +723, 996, 755, +691, 996, 819, +707, 996, 883, +674, 1012, 964, +707, 1012, 996, +723, 1028, 1092, +723, 1044, 1172, +787, 1060, 1253, +819, 1092, 1317, +851, 1124, 1413, +931, 1156, 1510, +964, 1172, 1590, +1012, 1172, 1654, +1076, 1237, 1783, +1140, 1285, 1863, +1220, 1333, 1943, +1285, 1349, 2039, +851, 1220, 867, +835, 1220, 931, +835, 1220, 996, +835, 1220, 1076, +851, 1204, 1140, +867, 1204, 1156, +883, 1220, 1253, +915, 1253, 1381, +980, 1269, 1445, +996, 1285, 1510, +1012, 1317, 1606, +1108, 1349, 1686, +1124, 1365, 1750, +1156, 1381, 1847, +1237, 1413, 1927, +1285, 1445, 2039, +1349, 1493, 2104, +1028, 1413, 996, +996, 1413, 1044, +1012, 1413, 1140, +1028, 1413, 1188, +1044, 1413, 1253, +1012, 1413, 1333, +1060, 1429, 1333, +1076, 1445, 1445, +1060, 1477, 1542, +1108, 1477, 1606, +1140, 1493, 1702, +1172, 1510, 1783, +1220, 1542, 1863, +1285, 1558, 1959, +1349, 1606, 2023, +1413, 1622, 2120, +1477, 1670, 2232, +1188, 1606, 1156, +1140, 1622, 1172, +1156, 1606, 1220, +1156, 1606, 1317, +1172, 1606, 1381, +1188, 1622, 1461, +1220, 1622, 1510, +1237, 1654, 1558, +1253, 1654, 1622, +1285, 1686, 1734, +1333, 1670, 1799, +1381, 1718, 1895, +1397, 1718, 1959, +1429, 1734, 2039, +1477, 1766, 2104, +1526, 1815, 2200, +1558, 1831, 2296, +1333, 1815, 1253, +1349, 1815, 1301, +1317, 1831, 1349, +1333, 1815, 1397, +1365, 1815, 1493, +1365, 1831, 1558, +1365, 1815, 1590, +1397, 1847, 1686, +1429, 1847, 1718, +1461, 1863, 1799, +1477, 1879, 1911, +1493, 1895, 2007, +1574, 1927, 2039, +1670, 1927, 2136, +1686, 1927, 2200, +1670, 1943, 2264, +1718, 1991, 2377, +1558, 2023, 1365, +1542, 2023, 1381, +1542, 2023, 1445, +1558, 2023, 1510, +1574, 2023, 1606, +1574, 2023, 1654, +1622, 2023, 1702, +1606, 2039, 1766, +1622, 2056, 1831, +1654, 2056, 1863, +1686, 2056, 1943, +1718, 2088, 2056, +1718, 2088, 2152, +1766, 2136, 2248, +1879, 2120, 2264, +1927, 2152, 2361, +1975, 2184, 2473, +1799, 2232, 1477, +1783, 2232, 1510, +1766, 2232, 1558, +1783, 2232, 1622, +1799, 2216, 1670, +1815, 2232, 1766, +1815, 2248, 1815, +1847, 2264, 1895, +1879, 2280, 1975, +1879, 2296, 2023, +1911, 2296, 2088, +1911, 2280, 2136, +2007, 2312, 2248, +1975, 2329, 2345, +2056, 2345, 2393, +2072, 2345, 2457, +2120, 2361, 2553, +2007, 2457, 1654, +1991, 2473, 1654, +1959, 2457, 1670, +1975, 2441, 1734, +1991, 2441, 1799, +2007, 2441, 1863, +2039, 2457, 1959, +2072, 2473, 2039, +2039, 2457, 2088, +2072, 2473, 2168, +2120, 2489, 2216, +2120, 2457, 2264, +2168, 2505, 2361, +2200, 2505, 2441, +2216, 2537, 2553, +2232, 2537, 2618, +2248, 2537, 2682, +2168, 2666, 1750, +2168, 2650, 1799, +2120, 2650, 1815, +2168, 2666, 1879, +2168, 2650, 1959, +2184, 2650, 2023, +2216, 2650, 2056, +2216, 2666, 2136, +2216, 2650, 2184, +2248, 2666, 2248, +2248, 2682, 2345, +2280, 2682, 2377, +2312, 2698, 2457, +2329, 2698, 2521, +2377, 2730, 2618, +2393, 2746, 2714, +2425, 2762, 2794, +2345, 2842, 1895, +2329, 2858, 1895, +2296, 2858, 1943, +2312, 2875, 1959, +2329, 2875, 2056, +2345, 2858, 2120, +2377, 2875, 2200, +2393, 2875, 2264, +2425, 2875, 2329, +2409, 2875, 2361, +2473, 2875, 2441, +2489, 2875, 2505, +2505, 2891, 2553, +2505, 2875, 2602, +2553, 2907, 2698, +2585, 2923, 2778, +2602, 2955, 2891, +2537, 3067, 2023, +2569, 3067, 2056, +2505, 3067, 2056, +2521, 3067, 2120, +2537, 3067, 2184, +2569, 3083, 2264, +2585, 3067, 2329, +2585, 3051, 2377, +2602, 3083, 2425, +2602, 3067, 2521, +2634, 3083, 2602, +2618, 3067, 2618, +2666, 3083, 2666, +2698, 3099, 2714, +2730, 3115, 2794, +2778, 3131, 2891, +2778, 3131, 2987, +2714, 3276, 2184, +2746, 3308, 2216, +2698, 3308, 2232, +2714, 3308, 2312, +2714, 3308, 2296, +2730, 3292, 2361, +2730, 3292, 2457, +2778, 3276, 2553, +2778, 3276, 2585, +2778, 3260, 2634, +2762, 3276, 2698, +2794, 3260, 2730, +2826, 3292, 2826, +2810, 3276, 2858, +2842, 3292, 2923, +2875, 3308, 3003, +2939, 3340, 3083, +2891, 3485, 2345, +2875, 3485, 2329, +2875, 3485, 2377, +2842, 3501, 2377, +2891, 3517, 2457, +2907, 3501, 2521, +2907, 3485, 2569, +2907, 3485, 2666, +2939, 3485, 2714, +2971, 3485, 2778, +3019, 3501, 2826, +3035, 3485, 2891, +3035, 3517, 2971, +3051, 3517, 3051, +3083, 3533, 3131, +3099, 3517, 3164, +3148, 3533, 3212, +385, 257, 369, +353, 289, 401, +369, 305, 482, +401, 337, 594, +401, 337, 642, +434, 401, 771, +482, 466, 835, +562, 530, 947, +578, 578, 1060, +674, 626, 1124, +723, 707, 1253, +803, 755, 1349, +883, 835, 1477, +915, 883, 1558, +1044, 947, 1670, +1076, 1012, 1766, +1108, 1060, 1863, +498, 369, 385, +450, 401, 498, +434, 434, 578, +401, 466, 626, +450, 498, 723, +514, 514, 803, +562, 594, 931, +578, 610, 996, +642, 642, 1076, +691, 707, 1188, +755, 771, 1285, +835, 835, 1413, +867, 867, 1477, +964, 915, 1574, +996, 996, 1670, +1108, 1060, 1815, +1140, 1108, 1895, +562, 594, 514, +562, 610, 578, +530, 610, 674, +514, 642, 739, +514, 626, 803, +562, 674, 883, +610, 707, 980, +658, 755, 1076, +674, 771, 1156, +755, 819, 1237, +819, 883, 1365, +851, 915, 1445, +931, 964, 1542, +980, 1012, 1622, +1076, 1076, 1766, +1076, 1092, 1799, +1172, 1172, 1959, +658, 787, 610, +642, 803, 658, +610, 803, 755, +626, 819, 819, +642, 835, 915, +674, 851, 980, +707, 883, 1092, +723, 899, 1172, +771, 947, 1269, +771, 964, 1349, +851, 996, 1445, +915, 1044, 1493, +996, 1092, 1606, +1012, 1108, 1686, +1092, 1172, 1783, +1140, 1220, 1895, +1253, 1269, 1959, +771, 1012, 755, +771, 1012, 803, +723, 1012, 899, +739, 1028, 964, +755, 1028, 1012, +771, 1044, 1108, +787, 1060, 1204, +819, 1092, 1285, +851, 1092, 1333, +915, 1140, 1429, +931, 1156, 1510, +996, 1172, 1590, +1044, 1220, 1702, +1108, 1253, 1783, +1172, 1301, 1847, +1253, 1317, 1959, +1285, 1365, 2023, +883, 1204, 835, +915, 1220, 931, +867, 1220, 1012, +883, 1220, 1060, +899, 1220, 1156, +931, 1220, 1188, +947, 1237, 1285, +947, 1253, 1365, +980, 1269, 1445, +1012, 1285, 1526, +1060, 1333, 1622, +1092, 1333, 1670, +1140, 1381, 1766, +1220, 1397, 1863, +1269, 1445, 1959, +1317, 1477, 2039, +1381, 1477, 2120, +1060, 1413, 996, +1044, 1413, 1028, +1028, 1429, 1124, +1044, 1429, 1172, +1060, 1429, 1269, +1076, 1445, 1333, +1108, 1445, 1365, +1076, 1445, 1445, +1092, 1461, 1542, +1124, 1493, 1622, +1220, 1526, 1734, +1204, 1542, 1799, +1237, 1558, 1879, +1317, 1574, 1943, +1365, 1606, 2039, +1413, 1622, 2120, +1477, 1654, 2200, +1188, 1606, 1108, +1204, 1606, 1188, +1172, 1622, 1253, +1188, 1622, 1301, +1237, 1622, 1397, +1220, 1638, 1429, +1253, 1654, 1526, +1285, 1654, 1574, +1285, 1654, 1622, +1317, 1670, 1734, +1349, 1702, 1815, +1381, 1718, 1895, +1429, 1718, 1959, +1445, 1750, 2023, +1493, 1783, 2120, +1574, 1815, 2216, +1622, 1847, 2312, +1365, 1815, 1253, +1365, 1815, 1285, +1333, 1815, 1365, +1365, 1815, 1397, +1397, 1831, 1477, +1397, 1815, 1558, +1413, 1831, 1622, +1413, 1863, 1702, +1461, 1863, 1750, +1477, 1879, 1815, +1493, 1879, 1911, +1542, 1879, 1975, +1606, 1911, 2039, +1670, 1927, 2136, +1686, 1927, 2200, +1686, 1975, 2280, +1766, 2007, 2361, +1558, 2023, 1365, +1574, 2007, 1381, +1542, 2039, 1461, +1558, 2023, 1510, +1590, 2039, 1590, +1606, 2023, 1654, +1638, 2056, 1718, +1638, 2039, 1766, +1670, 2056, 1847, +1702, 2056, 1879, +1702, 2088, 1991, +1766, 2088, 2072, +1783, 2104, 2152, +1847, 2136, 2216, +1879, 2120, 2264, +1911, 2136, 2345, +1975, 2184, 2473, +1799, 2248, 1477, +1783, 2232, 1477, +1799, 2264, 1558, +1799, 2248, 1638, +1799, 2216, 1670, +1831, 2232, 1750, +1831, 2216, 1799, +1863, 2264, 1895, +1895, 2280, 1943, +1911, 2280, 2023, +1959, 2296, 2072, +1975, 2296, 2120, +2007, 2329, 2248, +2039, 2329, 2329, +2056, 2345, 2393, +2088, 2361, 2473, +2120, 2377, 2553, +2007, 2457, 1654, +2023, 2457, 1622, +1975, 2457, 1638, +2007, 2457, 1718, +2007, 2441, 1799, +2039, 2425, 1879, +2039, 2457, 1927, +2072, 2457, 2039, +2039, 2457, 2088, +2072, 2473, 2136, +2104, 2473, 2200, +2168, 2489, 2232, +2152, 2489, 2345, +2200, 2521, 2441, +2216, 2521, 2537, +2248, 2553, 2634, +2264, 2553, 2698, +2168, 2666, 1750, +2152, 2666, 1783, +2152, 2666, 1815, +2168, 2650, 1863, +2200, 2682, 1943, +2216, 2666, 2007, +2216, 2650, 2056, +2264, 2682, 2152, +2248, 2682, 2216, +2264, 2682, 2264, +2296, 2682, 2345, +2280, 2682, 2377, +2312, 2698, 2457, +2329, 2698, 2521, +2377, 2730, 2618, +2393, 2746, 2730, +2425, 2762, 2794, +2345, 2875, 1911, +2345, 2875, 1911, +2345, 2891, 1943, +2345, 2875, 1991, +2345, 2875, 2039, +2345, 2875, 2120, +2409, 2875, 2232, +2409, 2891, 2280, +2425, 2875, 2329, +2457, 2891, 2377, +2489, 2891, 2441, +2505, 2891, 2521, +2521, 2875, 2537, +2569, 2907, 2634, +2553, 2907, 2698, +2618, 2907, 2778, +2618, 2955, 2907, +2553, 3067, 2039, +2569, 3067, 2056, +2537, 3067, 2072, +2521, 3067, 2120, +2553, 3083, 2200, +2553, 3067, 2248, +2585, 3067, 2312, +2618, 3083, 2409, +2634, 3067, 2457, +2634, 3099, 2505, +2634, 3083, 2585, +2666, 3083, 2634, +2666, 3099, 2682, +2730, 3115, 2746, +2746, 3131, 2810, +2778, 3131, 2891, +2778, 3131, 2971, +2746, 3308, 2200, +2730, 3292, 2200, +2682, 3292, 2216, +2714, 3308, 2296, +2746, 3308, 2345, +2762, 3292, 2393, +2778, 3276, 2457, +2746, 3276, 2521, +2762, 3276, 2569, +2778, 3260, 2634, +2794, 3276, 2714, +2794, 3276, 2746, +2842, 3292, 2794, +2875, 3292, 2875, +2858, 3292, 2907, +2891, 3308, 2987, +2923, 3340, 3099, +2891, 3485, 2345, +2891, 3485, 2345, +2939, 3501, 2361, +2875, 3485, 2409, +2858, 3485, 2425, +2907, 3501, 2489, +2907, 3485, 2569, +2923, 3485, 2634, +2955, 3501, 2714, +2987, 3485, 2746, +3019, 3501, 2842, +3051, 3517, 2923, +3067, 3501, 2971, +3051, 3517, 3051, +3099, 3533, 3131, +3131, 3533, 3180, +3164, 3549, 3228, +594, 321, 466, +530, 369, 498, +498, 401, 562, +530, 418, 658, +562, 450, 707, +546, 482, 787, +594, 562, 915, +642, 594, 996, +707, 626, 1076, +755, 707, 1204, +787, 755, 1285, +851, 803, 1397, +899, 867, 1493, +1012, 915, 1574, +1060, 980, 1670, +1108, 1060, 1815, +1188, 1108, 1895, +658, 450, 466, +610, 450, 546, +546, 482, 594, +578, 514, 674, +562, 562, 771, +594, 594, 867, +594, 610, 931, +642, 642, 1028, +707, 723, 1124, +739, 739, 1204, +803, 803, 1317, +899, 883, 1445, +931, 899, 1510, +996, 947, 1606, +1060, 1012, 1702, +1092, 1076, 1783, +1188, 1140, 1927, +658, 626, 514, +674, 626, 562, +642, 642, 723, +658, 658, 787, +626, 691, 851, +610, 723, 947, +658, 739, 996, +707, 787, 1092, +739, 803, 1172, +803, 867, 1301, +867, 883, 1381, +883, 915, 1445, +947, 980, 1542, +1028, 1028, 1654, +1092, 1092, 1750, +1156, 1124, 1863, +1204, 1188, 1943, +755, 835, 642, +755, 819, 674, +739, 819, 755, +739, 851, 867, +723, 867, 931, +755, 899, 1044, +787, 915, 1108, +819, 947, 1204, +819, 964, 1269, +851, 996, 1349, +899, 1012, 1413, +964, 1076, 1526, +1028, 1092, 1622, +1076, 1140, 1718, +1156, 1188, 1815, +1220, 1237, 1927, +1253, 1269, 1975, +835, 1028, 739, +835, 1012, 787, +819, 1028, 867, +803, 1044, 996, +835, 1060, 1060, +851, 1076, 1156, +883, 1092, 1188, +883, 1108, 1269, +931, 1124, 1381, +964, 1140, 1461, +980, 1172, 1526, +1028, 1204, 1622, +1092, 1253, 1702, +1140, 1285, 1799, +1220, 1301, 1863, +1285, 1349, 1975, +1349, 1397, 2072, +980, 1220, 867, +964, 1220, 915, +964, 1237, 996, +931, 1220, 1076, +947, 1220, 1156, +980, 1237, 1204, +996, 1253, 1301, +1028, 1269, 1381, +1060, 1285, 1461, +1044, 1317, 1558, +1092, 1349, 1622, +1140, 1349, 1686, +1188, 1381, 1783, +1253, 1429, 1863, +1301, 1461, 1959, +1381, 1493, 2056, +1429, 1526, 2120, +1124, 1429, 980, +1108, 1429, 1028, +1124, 1429, 1108, +1108, 1445, 1204, +1124, 1461, 1301, +1124, 1445, 1349, +1108, 1445, 1365, +1156, 1477, 1493, +1172, 1493, 1558, +1188, 1493, 1654, +1204, 1526, 1734, +1220, 1558, 1815, +1269, 1558, 1895, +1365, 1590, 1959, +1397, 1606, 2039, +1445, 1638, 2104, +1510, 1686, 2216, +1237, 1638, 1124, +1269, 1622, 1188, +1285, 1638, 1220, +1253, 1638, 1301, +1285, 1622, 1381, +1269, 1638, 1445, +1285, 1654, 1542, +1349, 1670, 1558, +1349, 1670, 1622, +1365, 1686, 1750, +1397, 1718, 1847, +1413, 1718, 1911, +1461, 1750, 1991, +1461, 1766, 2039, +1558, 1815, 2152, +1574, 1815, 2232, +1638, 1863, 2345, +1413, 1831, 1220, +1429, 1831, 1285, +1445, 1831, 1349, +1397, 1831, 1397, +1429, 1831, 1477, +1445, 1847, 1574, +1429, 1847, 1638, +1477, 1863, 1718, +1493, 1863, 1750, +1526, 1895, 1831, +1542, 1895, 1895, +1574, 1911, 1975, +1654, 1927, 2072, +1686, 1943, 2152, +1718, 1959, 2232, +1766, 1991, 2329, +1783, 1991, 2361, +1622, 2039, 1349, +1638, 2039, 1413, +1654, 2056, 1461, +1606, 2039, 1542, +1638, 2039, 1574, +1654, 2056, 1670, +1670, 2039, 1718, +1686, 2039, 1783, +1702, 2072, 1863, +1718, 2072, 1911, +1750, 2088, 1975, +1750, 2088, 2072, +1831, 2136, 2152, +1831, 2120, 2200, +1895, 2136, 2280, +1959, 2136, 2361, +1991, 2200, 2473, +1847, 2248, 1477, +1847, 2248, 1493, +1831, 2248, 1526, +1815, 2248, 1606, +1831, 2248, 1670, +1863, 2264, 1783, +1879, 2264, 1847, +1911, 2264, 1879, +1927, 2280, 1959, +1927, 2296, 2023, +1975, 2312, 2072, +1991, 2312, 2152, +2007, 2329, 2248, +2056, 2361, 2345, +2056, 2345, 2393, +2136, 2361, 2489, +2136, 2345, 2537, +2023, 2457, 1590, +2072, 2457, 1638, +2039, 2441, 1654, +2007, 2441, 1734, +2056, 2457, 1815, +2056, 2441, 1863, +2104, 2473, 1959, +2072, 2457, 2007, +2104, 2473, 2072, +2120, 2473, 2152, +2152, 2473, 2216, +2168, 2505, 2280, +2184, 2505, 2345, +2184, 2521, 2473, +2216, 2537, 2553, +2264, 2553, 2602, +2329, 2553, 2682, +2200, 2650, 1750, +2232, 2666, 1799, +2216, 2666, 1815, +2184, 2666, 1847, +2216, 2682, 1959, +2232, 2682, 2023, +2264, 2650, 2072, +2280, 2682, 2152, +2280, 2666, 2216, +2280, 2698, 2280, +2296, 2682, 2345, +2345, 2698, 2393, +2361, 2714, 2473, +2409, 2714, 2521, +2425, 2714, 2585, +2409, 2762, 2730, +2441, 2762, 2810, +2393, 2891, 1927, +2393, 2891, 1927, +2393, 2891, 1959, +2361, 2891, 2007, +2377, 2875, 2072, +2409, 2875, 2152, +2425, 2875, 2216, +2441, 2875, 2312, +2473, 2891, 2361, +2489, 2875, 2377, +2473, 2875, 2441, +2505, 2891, 2521, +2553, 2907, 2569, +2553, 2891, 2618, +2585, 2907, 2698, +2634, 2923, 2794, +2634, 2939, 2891, +2553, 3083, 2039, +2569, 3083, 2039, +2585, 3083, 2120, +2553, 3083, 2104, +2553, 3083, 2168, +2569, 3067, 2248, +2585, 3051, 2280, +2618, 3035, 2377, +2634, 3083, 2473, +2634, 3083, 2505, +2650, 3067, 2569, +2682, 3099, 2650, +2730, 3099, 2698, +2714, 3115, 2730, +2762, 3131, 2810, +2794, 3148, 2891, +2794, 3148, 2987, +2778, 3292, 2200, +2746, 3308, 2200, +2762, 3292, 2248, +2730, 3308, 2280, +2746, 3292, 2296, +2762, 3276, 2361, +2778, 3292, 2457, +2794, 3276, 2521, +2810, 3276, 2585, +2778, 3260, 2634, +2826, 3292, 2698, +2826, 3292, 2730, +2842, 3276, 2794, +2875, 3292, 2875, +2907, 3308, 2923, +2955, 3324, 3003, +2939, 3340, 3083, +2955, 3501, 2329, +2891, 3485, 2345, +2923, 3517, 2329, +2939, 3501, 2393, +2907, 3501, 2457, +2923, 3517, 2505, +2923, 3517, 2602, +2955, 3501, 2666, +2987, 3485, 2730, +3019, 3485, 2762, +3051, 3485, 2826, +3051, 3517, 2923, +3067, 3501, 2971, +3099, 3517, 3051, +3083, 3533, 3131, +3115, 3533, 3180, +3164, 3549, 3228, +771, 418, 498, +739, 450, 562, +674, 498, 642, +658, 530, 707, +707, 562, 819, +691, 578, 883, +674, 626, 964, +739, 658, 1028, +755, 707, 1124, +819, 755, 1237, +867, 819, 1333, +931, 867, 1429, +980, 899, 1510, +1076, 964, 1606, +1108, 1028, 1718, +1140, 1060, 1799, +1204, 1124, 1927, +851, 530, 530, +819, 546, 610, +723, 594, 691, +691, 610, 755, +707, 626, 835, +723, 626, 931, +755, 691, 980, +755, 723, 1060, +803, 771, 1172, +867, 819, 1269, +915, 867, 1381, +964, 899, 1461, +1012, 947, 1526, +1044, 996, 1638, +1124, 1060, 1734, +1156, 1092, 1831, +1253, 1188, 1959, +915, 674, 498, +883, 691, 562, +819, 691, 755, +739, 739, 835, +755, 755, 899, +771, 771, 980, +771, 803, 1044, +803, 835, 1140, +851, 867, 1220, +883, 899, 1317, +899, 931, 1413, +980, 980, 1493, +1028, 1044, 1606, +1092, 1076, 1686, +1140, 1108, 1766, +1188, 1172, 1879, +1285, 1220, 1991, +899, 883, 658, +899, 867, 707, +915, 883, 787, +883, 899, 947, +867, 931, 996, +835, 931, 1076, +835, 947, 1124, +867, 980, 1237, +883, 996, 1317, +947, 1044, 1397, +964, 1044, 1461, +1028, 1108, 1574, +1076, 1140, 1638, +1124, 1172, 1734, +1188, 1220, 1847, +1269, 1253, 1911, +1317, 1301, 2007, +964, 1044, 771, +947, 1060, 851, +964, 1044, 899, +947, 1076, 1012, +931, 1076, 1076, +931, 1108, 1156, +947, 1124, 1237, +996, 1156, 1333, +980, 1172, 1397, +1028, 1156, 1445, +1076, 1204, 1558, +1108, 1237, 1638, +1140, 1253, 1718, +1204, 1301, 1799, +1285, 1333, 1879, +1301, 1349, 1959, +1365, 1413, 2088, +1076, 1253, 883, +1060, 1253, 947, +1092, 1253, 996, +1076, 1269, 1092, +1044, 1269, 1172, +1092, 1285, 1269, +1060, 1285, 1349, +1108, 1317, 1429, +1092, 1317, 1493, +1140, 1349, 1558, +1156, 1365, 1622, +1172, 1397, 1702, +1237, 1413, 1799, +1317, 1445, 1895, +1349, 1477, 1975, +1397, 1510, 2088, +1477, 1558, 2136, +1220, 1445, 1012, +1204, 1445, 1028, +1188, 1461, 1124, +1188, 1445, 1204, +1156, 1445, 1269, +1156, 1477, 1381, +1172, 1477, 1397, +1204, 1493, 1510, +1220, 1493, 1574, +1253, 1526, 1654, +1237, 1542, 1750, +1301, 1558, 1847, +1349, 1574, 1847, +1413, 1622, 1975, +1445, 1654, 2056, +1510, 1670, 2152, +1542, 1686, 2232, +1333, 1654, 1092, +1349, 1638, 1156, +1333, 1654, 1204, +1349, 1654, 1301, +1317, 1654, 1381, +1333, 1654, 1477, +1365, 1686, 1542, +1381, 1670, 1574, +1413, 1686, 1686, +1429, 1702, 1750, +1461, 1734, 1879, +1461, 1750, 1911, +1493, 1766, 1991, +1526, 1799, 2072, +1558, 1815, 2168, +1622, 1847, 2232, +1686, 1895, 2312, +1461, 1847, 1220, +1493, 1847, 1269, +1510, 1847, 1333, +1493, 1847, 1397, +1461, 1847, 1461, +1526, 1863, 1574, +1510, 1863, 1638, +1526, 1879, 1702, +1558, 1879, 1750, +1590, 1895, 1783, +1574, 1911, 1927, +1606, 1927, 2007, +1686, 1927, 2072, +1718, 1927, 2152, +1718, 1975, 2232, +1783, 2007, 2312, +1815, 2023, 2393, +1670, 2039, 1333, +1686, 2056, 1381, +1670, 2056, 1445, +1670, 2056, 1493, +1686, 2072, 1574, +1702, 2056, 1686, +1734, 2072, 1766, +1718, 2072, 1815, +1750, 2088, 1879, +1799, 2104, 1943, +1831, 2104, 1975, +1815, 2136, 2088, +1863, 2136, 2152, +1927, 2136, 2232, +1943, 2136, 2296, +2007, 2184, 2409, +2023, 2232, 2505, +1895, 2280, 1461, +1879, 2280, 1493, +1895, 2264, 1558, +1895, 2280, 1622, +1895, 2280, 1702, +1911, 2280, 1815, +1927, 2264, 1863, +1975, 2296, 1911, +1943, 2296, 1975, +1975, 2296, 2039, +2007, 2312, 2088, +2039, 2329, 2168, +2088, 2361, 2296, +2088, 2345, 2345, +2104, 2361, 2409, +2136, 2361, 2489, +2184, 2393, 2585, +2088, 2473, 1622, +2088, 2489, 1622, +2088, 2473, 1654, +2104, 2473, 1718, +2072, 2473, 1799, +2072, 2457, 1895, +2136, 2473, 1991, +2136, 2489, 2039, +2136, 2473, 2088, +2152, 2489, 2136, +2184, 2505, 2216, +2216, 2521, 2264, +2248, 2521, 2329, +2264, 2537, 2473, +2296, 2537, 2505, +2312, 2537, 2585, +2329, 2569, 2698, +2264, 2682, 1750, +2264, 2682, 1783, +2248, 2666, 1799, +2248, 2698, 1879, +2216, 2682, 1927, +2264, 2666, 2023, +2280, 2682, 2088, +2312, 2682, 2152, +2280, 2682, 2216, +2312, 2682, 2280, +2345, 2698, 2377, +2377, 2698, 2409, +2377, 2714, 2489, +2409, 2730, 2569, +2441, 2746, 2650, +2473, 2778, 2762, +2473, 2762, 2778, +2409, 2891, 1911, +2393, 2891, 1927, +2425, 2891, 1927, +2425, 2891, 1991, +2409, 2907, 2072, +2473, 2891, 2136, +2473, 2891, 2232, +2489, 2891, 2296, +2505, 2891, 2361, +2537, 2875, 2393, +2521, 2891, 2457, +2521, 2875, 2505, +2585, 2891, 2569, +2569, 2907, 2634, +2618, 2939, 2730, +2634, 2939, 2810, +2634, 2939, 2891, +2602, 3067, 2007, +2618, 3099, 2056, +2602, 3067, 2072, +2585, 3083, 2120, +2602, 3083, 2216, +2618, 3083, 2280, +2650, 3083, 2312, +2650, 3067, 2361, +2666, 3067, 2473, +2682, 3099, 2521, +2682, 3083, 2569, +2698, 3115, 2666, +2730, 3115, 2714, +2762, 3115, 2746, +2778, 3115, 2810, +2842, 3148, 2923, +2794, 3148, 3003, +2746, 3292, 2168, +2778, 3292, 2216, +2778, 3292, 2216, +2762, 3292, 2264, +2762, 3308, 2312, +2762, 3292, 2361, +2778, 3276, 2425, +2794, 3260, 2489, +2794, 3260, 2569, +2826, 3276, 2650, +2858, 3308, 2682, +2842, 3276, 2762, +2875, 3292, 2842, +2891, 3308, 2891, +2939, 3324, 2939, +2955, 3324, 3019, +2987, 3340, 3083, +2907, 3501, 2329, +2923, 3501, 2329, +2939, 3501, 2361, +2987, 3517, 2409, +2923, 3517, 2473, +2955, 3517, 2537, +2955, 3501, 2585, +3003, 3501, 2634, +3035, 3501, 2746, +3035, 3501, 2778, +3067, 3501, 2842, +3099, 3517, 2923, +3067, 3517, 2987, +3083, 3517, 3051, +3131, 3533, 3131, +3131, 3533, 3180, +3164, 3549, 3228, +996, 514, 562, +947, 546, 626, +819, 578, 723, +803, 626, 771, +803, 642, 851, +819, 674, 947, +819, 707, 1012, +867, 739, 1108, +883, 787, 1188, +947, 819, 1301, +964, 851, 1365, +1012, 899, 1461, +1076, 947, 1542, +1124, 1028, 1654, +1156, 1060, 1734, +1220, 1124, 1863, +1285, 1188, 1959, +1028, 594, 562, +996, 610, 658, +899, 674, 787, +835, 723, 851, +835, 723, 883, +851, 739, 980, +851, 755, 1044, +883, 803, 1140, +883, 835, 1220, +947, 883, 1317, +980, 899, 1397, +1060, 964, 1493, +1076, 1012, 1590, +1108, 1060, 1670, +1172, 1108, 1783, +1253, 1172, 1879, +1317, 1220, 2007, +1092, 723, 514, +1028, 739, 658, +980, 755, 803, +883, 803, 883, +899, 851, 964, +915, 851, 1044, +931, 867, 1140, +931, 899, 1188, +947, 915, 1269, +964, 947, 1349, +1012, 980, 1413, +1044, 1044, 1526, +1092, 1076, 1622, +1140, 1124, 1734, +1204, 1172, 1815, +1269, 1220, 1927, +1349, 1253, 1975, +1076, 899, 642, +1108, 899, 707, +1108, 899, 771, +1028, 931, 980, +931, 947, 1028, +964, 980, 1140, +947, 996, 1204, +964, 1028, 1269, +996, 1044, 1333, +1044, 1076, 1413, +1076, 1108, 1510, +1108, 1124, 1574, +1156, 1172, 1686, +1220, 1204, 1766, +1269, 1269, 1847, +1349, 1301, 1959, +1365, 1333, 2023, +1092, 1092, 787, +1108, 1124, 851, +1108, 1124, 931, +1108, 1092, 964, +1092, 1140, 1156, +1060, 1140, 1172, +1044, 1172, 1269, +1044, 1156, 1317, +1076, 1204, 1413, +1108, 1237, 1493, +1140, 1253, 1574, +1188, 1285, 1670, +1269, 1301, 1734, +1285, 1349, 1831, +1349, 1365, 1927, +1381, 1381, 2007, +1429, 1461, 2104, +1220, 1285, 915, +1204, 1285, 964, +1204, 1301, 1060, +1188, 1285, 1124, +1172, 1301, 1220, +1172, 1333, 1317, +1156, 1333, 1381, +1172, 1333, 1445, +1188, 1365, 1477, +1220, 1397, 1606, +1204, 1397, 1654, +1253, 1413, 1734, +1301, 1445, 1831, +1333, 1477, 1927, +1365, 1493, 2007, +1461, 1542, 2056, +1526, 1590, 2184, +1285, 1477, 1044, +1301, 1477, 1076, +1253, 1477, 1108, +1269, 1477, 1204, +1285, 1477, 1301, +1237, 1493, 1349, +1253, 1510, 1445, +1269, 1526, 1558, +1301, 1542, 1622, +1269, 1542, 1670, +1381, 1574, 1750, +1397, 1590, 1831, +1445, 1622, 1911, +1477, 1654, 2007, +1510, 1670, 2088, +1558, 1702, 2184, +1622, 1734, 2232, +1429, 1686, 1140, +1461, 1670, 1172, +1445, 1686, 1237, +1429, 1686, 1317, +1429, 1686, 1397, +1413, 1702, 1493, +1413, 1702, 1574, +1445, 1702, 1622, +1477, 1718, 1718, +1526, 1750, 1783, +1542, 1750, 1831, +1542, 1766, 1927, +1574, 1799, 1991, +1622, 1815, 2088, +1638, 1831, 2168, +1702, 1863, 2232, +1750, 1879, 2312, +1558, 1863, 1237, +1558, 1879, 1285, +1574, 1879, 1349, +1542, 1863, 1381, +1574, 1863, 1477, +1558, 1895, 1590, +1590, 1879, 1654, +1606, 1895, 1718, +1638, 1911, 1750, +1638, 1911, 1847, +1654, 1927, 1943, +1686, 1927, 2023, +1750, 1943, 2104, +1766, 1991, 2200, +1799, 1991, 2232, +1847, 2023, 2345, +1895, 2039, 2393, +1750, 2088, 1397, +1750, 2088, 1381, +1734, 2088, 1413, +1750, 2072, 1493, +1750, 2072, 1558, +1750, 2088, 1654, +1783, 2072, 1766, +1783, 2088, 1799, +1799, 2088, 1863, +1847, 2104, 1927, +1879, 2120, 1975, +1847, 2136, 2104, +1911, 2136, 2168, +1975, 2152, 2264, +2023, 2184, 2345, +2023, 2216, 2441, +2056, 2232, 2521, +1959, 2312, 1510, +1943, 2296, 1493, +1959, 2296, 1558, +1991, 2296, 1622, +1959, 2296, 1702, +1959, 2280, 1783, +1991, 2280, 1863, +2023, 2296, 1943, +2023, 2329, 2007, +2039, 2329, 2072, +2072, 2345, 2120, +2104, 2345, 2200, +2104, 2329, 2280, +2104, 2361, 2361, +2120, 2361, 2425, +2136, 2377, 2505, +2264, 2393, 2602, +2136, 2473, 1638, +2088, 2473, 1622, +2136, 2489, 1638, +2120, 2489, 1702, +2120, 2473, 1783, +2152, 2489, 1895, +2152, 2473, 1975, +2168, 2489, 2039, +2184, 2473, 2104, +2200, 2505, 2152, +2232, 2505, 2232, +2264, 2521, 2264, +2296, 2521, 2345, +2312, 2537, 2457, +2329, 2537, 2521, +2361, 2553, 2602, +2393, 2585, 2682, +2264, 2682, 1750, +2264, 2682, 1750, +2296, 2682, 1831, +2296, 2666, 1863, +2296, 2682, 1943, +2280, 2682, 2007, +2312, 2682, 2072, +2377, 2714, 2200, +2361, 2698, 2248, +2377, 2698, 2312, +2361, 2714, 2345, +2393, 2714, 2425, +2457, 2746, 2457, +2473, 2746, 2553, +2473, 2746, 2650, +2521, 2762, 2730, +2537, 2778, 2810, +2457, 2891, 1879, +2457, 2907, 1895, +2505, 2907, 1927, +2521, 2907, 1991, +2521, 2891, 2072, +2489, 2907, 2120, +2521, 2891, 2200, +2537, 2891, 2296, +2569, 2891, 2345, +2553, 2891, 2409, +2569, 2907, 2473, +2602, 2907, 2553, +2618, 2923, 2602, +2618, 2923, 2666, +2650, 2923, 2730, +2698, 2955, 2794, +2714, 2971, 2939, +2650, 3083, 2023, +2650, 3083, 2039, +2650, 3083, 2056, +2682, 3099, 2136, +2666, 3099, 2216, +2634, 3099, 2264, +2666, 3099, 2345, +2682, 3099, 2393, +2698, 3083, 2457, +2730, 3099, 2537, +2714, 3115, 2602, +2746, 3115, 2682, +2778, 3115, 2714, +2794, 3148, 2778, +2826, 3148, 2842, +2826, 3148, 2907, +2875, 3180, 3035, +2826, 3292, 2184, +2794, 3308, 2184, +2778, 3292, 2200, +2794, 3276, 2232, +2810, 3276, 2296, +2762, 3276, 2329, +2826, 3292, 2441, +2842, 3292, 2537, +2842, 3276, 2585, +2858, 3292, 2650, +2875, 3292, 2714, +2907, 3292, 2778, +2907, 3308, 2826, +2939, 3324, 2907, +2955, 3308, 2939, +3003, 3340, 3035, +3003, 3356, 3099, +2939, 3517, 2312, +3019, 3517, 2361, +2971, 3517, 2345, +3035, 3517, 2393, +2971, 3517, 2441, +3003, 3517, 2521, +3003, 3501, 2618, +3035, 3501, 2682, +3051, 3501, 2746, +3083, 3501, 2778, +3115, 3517, 2875, +3099, 3517, 2939, +3131, 3533, 3019, +3148, 3517, 3067, +3164, 3549, 3131, +3180, 3549, 3164, +3212, 3549, 3228, +1188, 594, 578, +1124, 642, 674, +1044, 691, 803, +947, 739, 851, +931, 755, 931, +980, 787, 1012, +996, 819, 1092, +1028, 851, 1204, +1044, 867, 1253, +1028, 899, 1349, +1044, 931, 1413, +1108, 996, 1510, +1156, 1044, 1622, +1188, 1060, 1686, +1253, 1124, 1799, +1317, 1188, 1911, +1349, 1220, 1959, +1220, 691, 610, +1204, 691, 691, +1092, 739, 819, +996, 787, 899, +996, 819, 964, +996, 835, 1060, +1028, 883, 1124, +1028, 883, 1204, +1060, 915, 1269, +1060, 947, 1365, +1108, 1012, 1461, +1140, 1028, 1542, +1172, 1060, 1638, +1204, 1108, 1702, +1285, 1156, 1831, +1333, 1204, 1943, +1381, 1237, 1975, +1285, 771, 578, +1237, 803, 739, +1172, 835, 851, +1092, 867, 964, +1044, 899, 1012, +1044, 915, 1076, +1028, 931, 1156, +1076, 947, 1237, +1060, 1012, 1333, +1076, 1044, 1397, +1124, 1076, 1493, +1140, 1092, 1558, +1204, 1140, 1670, +1253, 1172, 1766, +1285, 1220, 1847, +1381, 1253, 1927, +1381, 1285, 2023, +1285, 931, 626, +1301, 931, 674, +1237, 947, 867, +1172, 996, 1044, +1092, 1028, 1076, +1108, 1060, 1156, +1108, 1060, 1237, +1140, 1076, 1301, +1108, 1108, 1381, +1140, 1140, 1461, +1140, 1156, 1542, +1220, 1188, 1638, +1253, 1237, 1734, +1301, 1269, 1815, +1349, 1301, 1895, +1397, 1333, 1959, +1461, 1381, 2072, +1269, 1124, 771, +1285, 1124, 819, +1253, 1124, 883, +1285, 1108, 964, +1220, 1140, 1172, +1172, 1188, 1237, +1188, 1204, 1301, +1172, 1220, 1397, +1172, 1237, 1461, +1220, 1269, 1558, +1237, 1285, 1622, +1253, 1317, 1686, +1333, 1333, 1783, +1365, 1349, 1863, +1413, 1413, 1959, +1461, 1445, 2056, +1526, 1493, 2120, +1301, 1333, 980, +1301, 1333, 980, +1317, 1333, 1028, +1317, 1317, 1108, +1333, 1317, 1188, +1301, 1333, 1317, +1285, 1365, 1381, +1269, 1381, 1461, +1237, 1397, 1526, +1253, 1429, 1606, +1317, 1429, 1686, +1349, 1445, 1766, +1397, 1493, 1863, +1429, 1510, 1943, +1493, 1542, 2023, +1542, 1590, 2120, +1622, 1638, 2200, +1397, 1526, 1076, +1429, 1510, 1108, +1413, 1526, 1156, +1397, 1526, 1253, +1397, 1526, 1333, +1381, 1542, 1413, +1365, 1542, 1493, +1349, 1558, 1558, +1365, 1558, 1622, +1397, 1574, 1686, +1445, 1606, 1766, +1477, 1622, 1879, +1493, 1638, 1943, +1542, 1670, 2039, +1574, 1686, 2120, +1654, 1734, 2184, +1686, 1750, 2264, +1574, 1718, 1204, +1558, 1702, 1220, +1558, 1718, 1253, +1526, 1718, 1333, +1542, 1718, 1413, +1558, 1718, 1510, +1542, 1718, 1590, +1558, 1750, 1654, +1558, 1750, 1734, +1558, 1734, 1783, +1574, 1766, 1863, +1622, 1815, 1975, +1638, 1815, 2023, +1670, 1831, 2120, +1734, 1879, 2200, +1783, 1879, 2264, +1815, 1895, 2345, +1686, 1895, 1285, +1670, 1895, 1285, +1670, 1879, 1333, +1654, 1895, 1397, +1670, 1895, 1493, +1670, 1911, 1558, +1670, 1911, 1686, +1686, 1911, 1734, +1734, 1927, 1799, +1734, 1927, 1879, +1766, 1943, 1959, +1815, 1975, 2023, +1815, 1975, 2088, +1847, 2007, 2168, +1863, 2039, 2264, +1911, 2039, 2345, +1943, 2056, 2425, +1847, 2088, 1349, +1863, 2104, 1397, +1831, 2104, 1413, +1847, 2088, 1493, +1847, 2104, 1574, +1863, 2104, 1670, +1847, 2104, 1783, +1911, 2120, 1831, +1879, 2136, 1895, +1927, 2136, 1943, +1959, 2120, 2023, +1975, 2120, 2088, +2023, 2152, 2184, +2023, 2184, 2296, +2056, 2216, 2393, +2072, 2232, 2441, +2120, 2280, 2537, +2039, 2312, 1493, +2039, 2312, 1526, +2007, 2296, 1542, +2023, 2329, 1622, +2056, 2312, 1702, +2056, 2329, 1783, +2023, 2329, 1863, +2088, 2329, 1975, +2072, 2329, 1991, +2104, 2345, 2104, +2136, 2345, 2136, +2136, 2329, 2168, +2136, 2377, 2312, +2152, 2377, 2377, +2184, 2393, 2457, +2232, 2393, 2537, +2280, 2409, 2634, +2216, 2505, 1606, +2200, 2489, 1606, +2200, 2505, 1670, +2216, 2505, 1734, +2200, 2505, 1783, +2232, 2521, 1895, +2200, 2505, 1943, +2232, 2505, 2072, +2264, 2505, 2120, +2264, 2521, 2184, +2296, 2537, 2264, +2329, 2537, 2312, +2345, 2537, 2377, +2312, 2537, 2457, +2361, 2569, 2553, +2393, 2585, 2634, +2425, 2602, 2714, +2345, 2698, 1718, +2345, 2714, 1766, +2361, 2714, 1815, +2345, 2698, 1879, +2377, 2714, 1943, +2393, 2714, 2007, +2377, 2714, 2104, +2393, 2714, 2184, +2409, 2714, 2232, +2441, 2714, 2312, +2425, 2730, 2377, +2473, 2746, 2441, +2505, 2762, 2473, +2521, 2762, 2569, +2537, 2762, 2666, +2521, 2778, 2746, +2569, 2810, 2842, +2521, 2907, 1879, +2489, 2891, 1895, +2537, 2907, 1943, +2521, 2891, 1959, +2537, 2891, 2023, +2553, 2891, 2120, +2537, 2907, 2216, +2553, 2907, 2280, +2585, 2907, 2329, +2602, 2907, 2425, +2618, 2907, 2489, +2634, 2923, 2537, +2666, 2939, 2618, +2698, 2939, 2666, +2730, 2955, 2746, +2714, 2971, 2842, +2746, 2955, 2907, +2682, 3099, 2023, +2682, 3099, 2023, +2682, 3115, 2056, +2682, 3099, 2104, +2714, 3115, 2184, +2698, 3099, 2248, +2714, 3131, 2296, +2714, 3099, 2409, +2746, 3099, 2473, +2778, 3099, 2553, +2778, 3131, 2634, +2794, 3131, 2698, +2810, 3148, 2746, +2826, 3131, 2778, +2842, 3131, 2842, +2907, 3180, 2939, +2939, 3180, 3003, +2810, 3276, 2136, +2826, 3292, 2152, +2858, 3292, 2232, +2842, 3292, 2264, +2842, 3292, 2248, +2858, 3292, 2361, +2842, 3308, 2457, +2858, 3308, 2521, +2907, 3324, 2602, +2907, 3308, 2666, +2939, 3308, 2698, +2955, 3340, 2794, +2955, 3324, 2858, +2987, 3324, 2923, +3003, 3356, 2987, +3019, 3356, 3051, +3067, 3388, 3148, +3051, 3517, 2329, +3051, 3517, 2361, +3051, 3517, 2361, +3083, 3517, 2393, +3035, 3517, 2425, +3003, 3517, 2489, +3035, 3517, 2569, +3083, 3517, 2666, +3099, 3501, 2762, +3131, 3517, 2810, +3131, 3533, 2891, +3148, 3533, 2955, +3131, 3533, 3003, +3164, 3533, 3067, +3196, 3549, 3131, +3244, 3565, 3180, +3212, 3565, 3244, +1365, 707, 658, +1349, 739, 739, +1237, 787, 883, +1140, 835, 980, +1108, 883, 1028, +1108, 867, 1092, +1124, 899, 1172, +1172, 947, 1269, +1156, 980, 1349, +1204, 996, 1397, +1188, 1044, 1493, +1220, 1060, 1574, +1269, 1092, 1654, +1317, 1156, 1783, +1349, 1204, 1847, +1397, 1237, 1927, +1461, 1285, 2039, +1381, 771, 658, +1397, 771, 739, +1301, 835, 899, +1188, 867, 980, +1140, 899, 1044, +1124, 915, 1108, +1124, 931, 1188, +1156, 980, 1285, +1172, 1012, 1349, +1220, 1044, 1445, +1204, 1076, 1526, +1269, 1092, 1606, +1285, 1140, 1702, +1317, 1188, 1766, +1381, 1237, 1847, +1445, 1285, 1959, +1445, 1301, 2007, +1445, 851, 642, +1413, 867, 755, +1365, 883, 899, +1237, 947, 1028, +1156, 1012, 1092, +1172, 1012, 1156, +1188, 1044, 1237, +1188, 1060, 1301, +1220, 1076, 1381, +1220, 1076, 1477, +1220, 1124, 1542, +1269, 1156, 1622, +1301, 1188, 1718, +1397, 1253, 1815, +1413, 1269, 1895, +1461, 1317, 1975, +1526, 1365, 2088, +1493, 996, 658, +1493, 980, 723, +1413, 1028, 915, +1349, 1060, 1060, +1253, 1092, 1156, +1237, 1108, 1204, +1204, 1124, 1269, +1253, 1140, 1365, +1253, 1172, 1429, +1253, 1188, 1493, +1269, 1237, 1590, +1333, 1269, 1670, +1365, 1301, 1766, +1397, 1317, 1831, +1429, 1333, 1927, +1510, 1397, 2056, +1510, 1413, 2104, +1461, 1140, 755, +1461, 1156, 819, +1510, 1140, 883, +1445, 1188, 1108, +1381, 1204, 1220, +1301, 1253, 1285, +1301, 1269, 1365, +1317, 1285, 1445, +1333, 1301, 1493, +1349, 1333, 1590, +1365, 1333, 1638, +1397, 1365, 1734, +1397, 1381, 1815, +1445, 1413, 1911, +1477, 1445, 1991, +1574, 1493, 2056, +1622, 1526, 2152, +1493, 1365, 931, +1461, 1349, 964, +1510, 1365, 1028, +1510, 1365, 1108, +1510, 1349, 1172, +1429, 1397, 1397, +1397, 1397, 1429, +1397, 1429, 1493, +1333, 1461, 1574, +1413, 1461, 1638, +1461, 1493, 1766, +1477, 1510, 1831, +1510, 1510, 1879, +1542, 1542, 1943, +1590, 1590, 2039, +1638, 1622, 2136, +1686, 1654, 2248, +1526, 1526, 1076, +1542, 1558, 1172, +1477, 1542, 1156, +1493, 1542, 1220, +1526, 1558, 1301, +1574, 1558, 1397, +1510, 1574, 1526, +1526, 1590, 1574, +1526, 1622, 1686, +1542, 1638, 1750, +1526, 1638, 1815, +1574, 1670, 1895, +1606, 1702, 1991, +1654, 1718, 2039, +1686, 1734, 2120, +1734, 1766, 2232, +1766, 1783, 2312, +1686, 1750, 1204, +1670, 1750, 1237, +1654, 1734, 1285, +1670, 1734, 1349, +1654, 1734, 1397, +1670, 1750, 1510, +1670, 1766, 1590, +1638, 1766, 1670, +1654, 1799, 1766, +1638, 1815, 1815, +1670, 1815, 1895, +1702, 1847, 1991, +1750, 1863, 2039, +1766, 1863, 2104, +1815, 1895, 2200, +1863, 1911, 2280, +1911, 1943, 2377, +1815, 1927, 1285, +1799, 1911, 1301, +1799, 1927, 1365, +1766, 1927, 1429, +1799, 1927, 1477, +1815, 1927, 1574, +1815, 1927, 1670, +1799, 1927, 1750, +1847, 1959, 1815, +1799, 1943, 1879, +1847, 1975, 1975, +1847, 2007, 2056, +1863, 1991, 2120, +1911, 2023, 2200, +1959, 2056, 2296, +1991, 2072, 2377, +2023, 2088, 2425, +1959, 2120, 1397, +1943, 2120, 1429, +1943, 2136, 1461, +1959, 2120, 1526, +1943, 2120, 1574, +1927, 2136, 1670, +1943, 2136, 1734, +1943, 2136, 1847, +1991, 2120, 1911, +2007, 2136, 1959, +2023, 2152, 2056, +2072, 2184, 2152, +2088, 2184, 2216, +2120, 2232, 2296, +2104, 2248, 2393, +2120, 2248, 2457, +2168, 2280, 2553, +2136, 2329, 1526, +2152, 2345, 1542, +2136, 2345, 1606, +2120, 2345, 1654, +2136, 2345, 1718, +2120, 2345, 1783, +2168, 2361, 1863, +2152, 2345, 1975, +2168, 2345, 2039, +2152, 2345, 2088, +2200, 2361, 2152, +2200, 2377, 2232, +2232, 2377, 2312, +2232, 2393, 2377, +2296, 2409, 2473, +2329, 2425, 2553, +2329, 2441, 2634, +2296, 2505, 1590, +2264, 2521, 1622, +2296, 2537, 1686, +2264, 2505, 1718, +2280, 2537, 1799, +2280, 2521, 1879, +2329, 2521, 1991, +2296, 2521, 2072, +2345, 2537, 2152, +2329, 2553, 2216, +2345, 2537, 2280, +2393, 2553, 2296, +2425, 2569, 2377, +2377, 2553, 2489, +2425, 2602, 2585, +2473, 2618, 2650, +2489, 2618, 2746, +2441, 2714, 1750, +2441, 2730, 1799, +2425, 2730, 1815, +2409, 2730, 1847, +2409, 2730, 1911, +2441, 2746, 1991, +2457, 2714, 2104, +2473, 2746, 2184, +2473, 2746, 2280, +2505, 2746, 2345, +2505, 2762, 2425, +2537, 2778, 2473, +2569, 2762, 2505, +2553, 2778, 2569, +2569, 2794, 2714, +2569, 2794, 2762, +2634, 2794, 2842, +2553, 2907, 1879, +2602, 2923, 1895, +2602, 2923, 1895, +2602, 2923, 1975, +2602, 2907, 2056, +2618, 2907, 2120, +2618, 2923, 2200, +2602, 2907, 2312, +2634, 2907, 2345, +2666, 2923, 2409, +2698, 2939, 2505, +2666, 2923, 2553, +2714, 2939, 2634, +2746, 2955, 2682, +2778, 2955, 2762, +2746, 2971, 2858, +2794, 2987, 2939, +2746, 3115, 2007, +2714, 3115, 2023, +2746, 3131, 2056, +2762, 3131, 2120, +2778, 3115, 2184, +2778, 3099, 2264, +2746, 3131, 2312, +2778, 3131, 2377, +2794, 3131, 2489, +2842, 3131, 2585, +2842, 3148, 2618, +2858, 3131, 2682, +2858, 3148, 2762, +2891, 3164, 2810, +2907, 3164, 2875, +2955, 3164, 2923, +2955, 3196, 3051, +2875, 3324, 2152, +2858, 3324, 2152, +2875, 3308, 2200, +2875, 3308, 2232, +2923, 3324, 2296, +2875, 3308, 2345, +2875, 3324, 2409, +2907, 3340, 2537, +2939, 3324, 2618, +2955, 3308, 2682, +2987, 3308, 2730, +2971, 3324, 2778, +3019, 3340, 2891, +2987, 3340, 2923, +3051, 3356, 2987, +3099, 3388, 3099, +3099, 3372, 3148, +3083, 3533, 2312, +3083, 3533, 2361, +3083, 3533, 2361, +3115, 3549, 2409, +3083, 3517, 2409, +3115, 3533, 2521, +3131, 3533, 2585, +3131, 3549, 2698, +3131, 3533, 2762, +3180, 3549, 2810, +3196, 3533, 2875, +3212, 3549, 2987, +3196, 3549, 3003, +3212, 3549, 3067, +3228, 3533, 3131, +3244, 3565, 3196, +3276, 3565, 3276, +1558, 771, 691, +1542, 803, 771, +1445, 867, 947, +1349, 931, 1060, +1253, 964, 1108, +1269, 996, 1156, +1253, 1012, 1237, +1253, 1028, 1301, +1285, 1044, 1381, +1301, 1076, 1461, +1333, 1092, 1542, +1349, 1140, 1638, +1381, 1188, 1734, +1445, 1220, 1815, +1461, 1269, 1879, +1510, 1285, 1959, +1542, 1349, 2088, +1574, 835, 691, +1574, 851, 803, +1477, 883, 915, +1365, 964, 1028, +1285, 1028, 1124, +1269, 1028, 1188, +1269, 1044, 1237, +1285, 1060, 1333, +1301, 1092, 1397, +1317, 1092, 1477, +1349, 1140, 1542, +1397, 1172, 1670, +1413, 1220, 1766, +1429, 1269, 1815, +1493, 1285, 1895, +1510, 1317, 1991, +1574, 1365, 2072, +1606, 931, 707, +1590, 931, 803, +1558, 964, 931, +1429, 1012, 1060, +1333, 1076, 1172, +1301, 1076, 1188, +1285, 1092, 1253, +1333, 1124, 1365, +1317, 1124, 1429, +1365, 1156, 1510, +1381, 1204, 1606, +1397, 1237, 1702, +1397, 1253, 1734, +1461, 1301, 1847, +1510, 1333, 1943, +1542, 1397, 2023, +1574, 1413, 2104, +1670, 1028, 674, +1606, 1060, 819, +1590, 1060, 964, +1510, 1076, 1076, +1397, 1156, 1220, +1349, 1188, 1269, +1333, 1204, 1349, +1365, 1220, 1429, +1397, 1220, 1493, +1413, 1253, 1542, +1429, 1269, 1638, +1429, 1317, 1718, +1461, 1349, 1799, +1510, 1365, 1879, +1558, 1413, 1975, +1606, 1445, 2088, +1654, 1493, 2136, +1702, 1204, 755, +1718, 1204, 819, +1702, 1204, 915, +1622, 1220, 1124, +1542, 1253, 1220, +1445, 1301, 1333, +1445, 1317, 1413, +1445, 1349, 1477, +1461, 1333, 1542, +1461, 1365, 1606, +1477, 1413, 1702, +1461, 1413, 1766, +1526, 1461, 1863, +1542, 1461, 1943, +1622, 1526, 2023, +1670, 1558, 2120, +1686, 1590, 2184, +1670, 1397, 931, +1686, 1381, 947, +1686, 1397, 1028, +1718, 1365, 1076, +1654, 1397, 1285, +1590, 1429, 1413, +1493, 1461, 1461, +1510, 1461, 1526, +1510, 1477, 1606, +1526, 1493, 1702, +1558, 1526, 1766, +1558, 1558, 1847, +1590, 1590, 1927, +1638, 1622, 2023, +1686, 1638, 2104, +1718, 1654, 2168, +1750, 1702, 2232, +1686, 1574, 1044, +1702, 1558, 1092, +1702, 1574, 1172, +1702, 1590, 1220, +1750, 1590, 1301, +1750, 1574, 1397, +1670, 1606, 1558, +1638, 1638, 1638, +1638, 1654, 1702, +1638, 1686, 1783, +1638, 1702, 1831, +1654, 1702, 1895, +1686, 1718, 1959, +1750, 1750, 2072, +1799, 1783, 2168, +1815, 1799, 2248, +1879, 1847, 2329, +1799, 1766, 1204, +1766, 1766, 1253, +1783, 1783, 1285, +1766, 1799, 1381, +1750, 1783, 1429, +1766, 1783, 1526, +1783, 1799, 1590, +1766, 1799, 1734, +1750, 1831, 1815, +1766, 1847, 1847, +1783, 1863, 1927, +1799, 1895, 2007, +1831, 1879, 2072, +1863, 1895, 2152, +1927, 1927, 2248, +1943, 1943, 2329, +1991, 1991, 2377, +1927, 1927, 1285, +1927, 1927, 1317, +1911, 1927, 1381, +1927, 1959, 1461, +1927, 1943, 1526, +1911, 1943, 1590, +1943, 1959, 1654, +1927, 1975, 1750, +1911, 1991, 1847, +1895, 1975, 1895, +1911, 2023, 2007, +1943, 2039, 2072, +1975, 2056, 2152, +2007, 2072, 2232, +2039, 2072, 2280, +2072, 2088, 2361, +2120, 2136, 2457, +2072, 2120, 1397, +2088, 2120, 1429, +2088, 2136, 1493, +2088, 2136, 1526, +2072, 2136, 1590, +2088, 2136, 1670, +2072, 2136, 1734, +2056, 2152, 1831, +2072, 2152, 1927, +2120, 2168, 1991, +2104, 2200, 2088, +2152, 2216, 2168, +2136, 2216, 2232, +2168, 2248, 2312, +2184, 2280, 2409, +2216, 2296, 2473, +2248, 2312, 2537, +2248, 2361, 1542, +2232, 2345, 1558, +2232, 2361, 1606, +2216, 2345, 1654, +2216, 2345, 1718, +2216, 2345, 1750, +2216, 2361, 1847, +2216, 2361, 1959, +2216, 2361, 2056, +2248, 2361, 2120, +2248, 2377, 2168, +2264, 2393, 2264, +2329, 2393, 2345, +2345, 2425, 2441, +2361, 2425, 2505, +2361, 2457, 2585, +2393, 2473, 2666, +2409, 2537, 1654, +2377, 2521, 1654, +2393, 2537, 1702, +2377, 2537, 1734, +2377, 2537, 1799, +2393, 2553, 1895, +2377, 2553, 1991, +2377, 2537, 2072, +2377, 2553, 2120, +2425, 2553, 2216, +2409, 2553, 2280, +2457, 2585, 2345, +2473, 2585, 2441, +2505, 2602, 2505, +2489, 2618, 2585, +2521, 2618, 2666, +2569, 2650, 2762, +2505, 2746, 1799, +2505, 2746, 1783, +2489, 2746, 1815, +2505, 2746, 1879, +2505, 2746, 1943, +2521, 2762, 1991, +2537, 2746, 2104, +2537, 2762, 2184, +2553, 2762, 2280, +2553, 2762, 2377, +2553, 2778, 2441, +2569, 2762, 2473, +2618, 2778, 2521, +2650, 2778, 2553, +2618, 2810, 2698, +2666, 2794, 2794, +2682, 2810, 2875, +2666, 2939, 1895, +2682, 2939, 1895, +2682, 2955, 1943, +2682, 2939, 1991, +2682, 2939, 2023, +2666, 2939, 2088, +2698, 2923, 2216, +2714, 2939, 2312, +2714, 2939, 2393, +2730, 2955, 2457, +2746, 2939, 2521, +2730, 2955, 2585, +2778, 2971, 2666, +2794, 2955, 2698, +2826, 2971, 2778, +2810, 2987, 2891, +2842, 3003, 2955, +2826, 3164, 2023, +2794, 3131, 2039, +2794, 3148, 2039, +2794, 3164, 2120, +2810, 3148, 2168, +2826, 3148, 2280, +2875, 3164, 2329, +2875, 3148, 2409, +2842, 3131, 2489, +2875, 3148, 2569, +2875, 3148, 2666, +2923, 3164, 2714, +2939, 3180, 2762, +2939, 3180, 2826, +3003, 3196, 2891, +3003, 3180, 2955, +2987, 3196, 3051, +2923, 3340, 2136, +2971, 3340, 2184, +2955, 3340, 2216, +2923, 3324, 2232, +2907, 3324, 2296, +2955, 3340, 2345, +2971, 3324, 2441, +2971, 3340, 2521, +2987, 3340, 2618, +3003, 3340, 2682, +3067, 3340, 2762, +3019, 3324, 2794, +3067, 3340, 2891, +3067, 3356, 2971, +3115, 3388, 3035, +3131, 3372, 3051, +3164, 3388, 3148, +3131, 3533, 2296, +3148, 3565, 2361, +3148, 3565, 2345, +3164, 3549, 2425, +3164, 3565, 2457, +3148, 3549, 2489, +3164, 3549, 2585, +3148, 3565, 2650, +3164, 3565, 2746, +3212, 3549, 2810, +3244, 3549, 2891, +3244, 3533, 2971, +3244, 3549, 3019, +3276, 3565, 3099, +3260, 3565, 3180, +3308, 3581, 3228, +3340, 3597, 3308, +1734, 883, 755, +1734, 867, 819, +1670, 931, 964, +1510, 996, 1076, +1429, 1028, 1140, +1381, 1060, 1204, +1397, 1108, 1301, +1413, 1124, 1365, +1429, 1140, 1461, +1429, 1156, 1542, +1477, 1188, 1622, +1510, 1237, 1702, +1542, 1253, 1766, +1542, 1301, 1831, +1558, 1333, 1927, +1622, 1381, 2039, +1654, 1397, 2120, +1734, 915, 755, +1750, 915, 819, +1654, 947, 980, +1558, 1012, 1076, +1477, 1076, 1204, +1413, 1124, 1253, +1413, 1140, 1317, +1429, 1140, 1397, +1445, 1172, 1461, +1461, 1188, 1574, +1510, 1220, 1606, +1510, 1253, 1686, +1542, 1269, 1766, +1542, 1333, 1863, +1590, 1365, 1975, +1622, 1397, 2056, +1686, 1429, 2136, +1750, 1012, 771, +1734, 1028, 883, +1718, 1028, 980, +1622, 1076, 1108, +1542, 1124, 1220, +1429, 1172, 1269, +1445, 1204, 1349, +1477, 1220, 1445, +1477, 1237, 1493, +1493, 1237, 1558, +1526, 1285, 1654, +1558, 1301, 1734, +1574, 1333, 1815, +1590, 1381, 1911, +1638, 1413, 2007, +1654, 1445, 2072, +1702, 1493, 2152, +1879, 1092, 739, +1799, 1124, 883, +1783, 1140, 1012, +1718, 1172, 1156, +1606, 1220, 1253, +1510, 1237, 1317, +1510, 1269, 1365, +1510, 1301, 1461, +1542, 1317, 1542, +1542, 1333, 1606, +1574, 1349, 1686, +1606, 1397, 1799, +1590, 1413, 1863, +1590, 1445, 1943, +1654, 1477, 2007, +1702, 1526, 2120, +1750, 1542, 2200, +1863, 1220, 771, +1895, 1237, 835, +1831, 1237, 964, +1783, 1269, 1140, +1718, 1301, 1285, +1606, 1349, 1397, +1558, 1381, 1429, +1558, 1397, 1526, +1590, 1429, 1622, +1606, 1461, 1686, +1622, 1461, 1750, +1654, 1477, 1847, +1654, 1526, 1895, +1686, 1542, 1975, +1734, 1574, 2072, +1750, 1622, 2184, +1799, 1654, 2232, +1863, 1413, 899, +1895, 1413, 931, +1879, 1413, 1028, +1879, 1397, 1124, +1815, 1429, 1317, +1734, 1477, 1461, +1670, 1510, 1526, +1654, 1542, 1574, +1670, 1558, 1670, +1670, 1574, 1750, +1686, 1574, 1815, +1702, 1622, 1895, +1718, 1654, 1991, +1734, 1654, 2039, +1766, 1670, 2104, +1847, 1734, 2232, +1911, 1734, 2312, +1879, 1606, 1028, +1895, 1606, 1092, +1895, 1622, 1156, +1943, 1638, 1237, +1927, 1606, 1301, +1911, 1622, 1477, +1831, 1654, 1590, +1734, 1686, 1638, +1766, 1702, 1750, +1766, 1718, 1783, +1799, 1750, 1895, +1799, 1766, 1975, +1831, 1783, 2056, +1879, 1799, 2120, +1911, 1831, 2200, +1959, 1847, 2296, +1959, 1863, 2329, +1959, 1815, 1220, +1943, 1815, 1237, +1927, 1815, 1269, +1927, 1815, 1365, +1927, 1815, 1445, +2007, 1815, 1493, +2023, 1831, 1590, +1943, 1847, 1783, +1879, 1863, 1815, +1911, 1879, 1895, +1911, 1895, 1959, +1911, 1911, 2023, +1943, 1927, 2072, +1975, 1943, 2168, +2023, 1959, 2248, +2023, 2007, 2329, +2104, 2023, 2441, +2056, 1991, 1365, +2039, 1975, 1381, +2039, 1975, 1413, +2039, 1991, 1445, +2023, 1991, 1526, +2007, 1991, 1590, +2039, 2007, 1702, +2039, 2007, 1783, +2023, 2023, 1911, +2023, 2039, 1975, +2007, 2056, 1991, +2056, 2072, 2104, +2072, 2072, 2152, +2104, 2088, 2232, +2168, 2136, 2345, +2216, 2168, 2441, +2232, 2168, 2505, +2248, 2184, 1461, +2248, 2184, 1445, +2216, 2184, 1510, +2216, 2184, 1558, +2200, 2184, 1622, +2200, 2168, 1702, +2200, 2184, 1799, +2232, 2200, 1895, +2232, 2232, 1959, +2216, 2232, 2039, +2216, 2248, 2120, +2216, 2264, 2200, +2232, 2280, 2264, +2264, 2280, 2345, +2264, 2312, 2425, +2280, 2312, 2489, +2312, 2312, 2553, +2329, 2377, 1574, +2329, 2377, 1574, +2312, 2361, 1606, +2329, 2361, 1686, +2329, 2361, 1718, +2312, 2377, 1783, +2312, 2361, 1863, +2329, 2393, 1991, +2329, 2377, 2039, +2361, 2393, 2152, +2377, 2393, 2216, +2361, 2409, 2312, +2393, 2425, 2393, +2393, 2441, 2457, +2409, 2473, 2553, +2425, 2489, 2634, +2457, 2489, 2666, +2457, 2553, 1638, +2457, 2553, 1670, +2489, 2553, 1718, +2457, 2537, 1750, +2473, 2569, 1847, +2441, 2553, 1895, +2457, 2553, 1991, +2505, 2585, 2072, +2473, 2553, 2104, +2489, 2585, 2248, +2505, 2585, 2312, +2505, 2602, 2361, +2537, 2618, 2473, +2553, 2618, 2537, +2553, 2634, 2618, +2602, 2666, 2714, +2602, 2682, 2794, +2618, 2778, 1799, +2634, 2762, 1831, +2618, 2762, 1847, +2618, 2794, 1911, +2618, 2778, 1959, +2602, 2778, 1991, +2618, 2762, 2072, +2602, 2778, 2184, +2602, 2762, 2248, +2618, 2778, 2377, +2666, 2794, 2409, +2666, 2810, 2489, +2682, 2794, 2521, +2730, 2794, 2618, +2730, 2810, 2698, +2762, 2826, 2778, +2778, 2826, 2842, +2762, 2955, 1895, +2762, 2939, 1895, +2778, 2971, 1943, +2730, 2939, 1975, +2778, 2955, 2056, +2762, 2971, 2136, +2746, 2971, 2184, +2810, 2971, 2296, +2794, 2971, 2361, +2810, 2971, 2473, +2810, 2955, 2537, +2794, 2971, 2618, +2826, 2971, 2682, +2858, 2971, 2730, +2907, 3003, 2778, +2875, 3019, 2923, +2939, 3051, 2987, +2907, 3148, 2039, +2923, 3180, 2056, +2907, 3164, 2088, +2891, 3164, 2104, +2891, 3164, 2184, +2891, 3164, 2264, +2939, 3180, 2312, +2923, 3148, 2393, +2939, 3164, 2505, +2939, 3180, 2618, +2955, 3164, 2666, +2987, 3180, 2714, +2987, 3196, 2794, +3003, 3196, 2858, +3019, 3180, 2891, +3051, 3196, 2971, +3019, 3196, 3051, +3019, 3340, 2168, +3019, 3340, 2168, +3035, 3340, 2200, +3003, 3356, 2232, +3035, 3356, 2312, +3035, 3356, 2345, +3035, 3356, 2441, +3051, 3340, 2505, +3051, 3372, 2650, +3051, 3356, 2714, +3099, 3372, 2762, +3131, 3404, 2875, +3148, 3388, 2939, +3148, 3388, 2971, +3164, 3388, 3035, +3196, 3404, 3099, +3228, 3404, 3164, +3212, 3565, 2345, +3212, 3565, 2345, +3212, 3565, 2345, +3244, 3581, 2425, +3228, 3565, 2441, +3244, 3565, 2521, +3228, 3581, 2585, +3276, 3565, 2682, +3228, 3565, 2730, +3228, 3549, 2794, +3260, 3565, 2875, +3276, 3549, 2971, +3308, 3565, 3051, +3324, 3581, 3115, +3308, 3581, 3180, +3356, 3581, 3228, +3404, 3613, 3292, +1927, 964, 803, +1911, 964, 899, +1847, 1012, 1028, +1766, 1092, 1172, +1654, 1140, 1269, +1574, 1204, 1333, +1574, 1220, 1365, +1558, 1220, 1429, +1574, 1253, 1510, +1606, 1269, 1622, +1606, 1285, 1654, +1638, 1301, 1766, +1670, 1349, 1831, +1702, 1365, 1911, +1686, 1413, 1991, +1766, 1461, 2088, +1783, 1510, 2184, +1959, 1012, 835, +1943, 1012, 899, +1863, 1060, 1028, +1783, 1108, 1172, +1702, 1172, 1253, +1590, 1220, 1317, +1558, 1220, 1349, +1590, 1253, 1461, +1590, 1253, 1510, +1590, 1285, 1590, +1638, 1317, 1686, +1638, 1333, 1766, +1686, 1365, 1847, +1686, 1381, 1927, +1734, 1445, 2007, +1766, 1461, 2088, +1799, 1510, 2200, +1927, 1076, 819, +1911, 1076, 899, +1911, 1092, 1012, +1799, 1140, 1140, +1750, 1220, 1301, +1638, 1253, 1365, +1606, 1301, 1413, +1606, 1301, 1493, +1622, 1333, 1542, +1654, 1349, 1654, +1638, 1349, 1718, +1686, 1381, 1799, +1702, 1413, 1895, +1734, 1429, 1943, +1734, 1493, 2039, +1799, 1526, 2136, +1831, 1574, 2216, +1991, 1156, 803, +1943, 1204, 915, +1927, 1188, 1044, +1879, 1204, 1140, +1799, 1253, 1285, +1702, 1317, 1397, +1638, 1365, 1445, +1638, 1381, 1542, +1654, 1381, 1606, +1670, 1413, 1686, +1686, 1429, 1750, +1702, 1445, 1831, +1750, 1477, 1895, +1766, 1526, 1991, +1783, 1558, 2072, +1847, 1606, 2184, +1847, 1606, 2200, +2088, 1285, 819, +2072, 1285, 883, +1975, 1333, 1092, +1959, 1333, 1220, +1879, 1365, 1349, +1766, 1413, 1461, +1686, 1445, 1510, +1702, 1477, 1590, +1702, 1477, 1622, +1750, 1510, 1718, +1750, 1542, 1799, +1783, 1558, 1879, +1799, 1590, 1959, +1815, 1622, 2056, +1815, 1638, 2088, +1895, 1670, 2200, +1943, 1702, 2280, +2056, 1461, 915, +2088, 1461, 947, +2088, 1461, 1028, +2039, 1477, 1188, +1991, 1493, 1365, +1927, 1526, 1510, +1847, 1574, 1590, +1799, 1622, 1638, +1799, 1638, 1734, +1831, 1638, 1783, +1831, 1654, 1847, +1847, 1654, 1911, +1879, 1686, 2023, +1879, 1734, 2104, +1943, 1750, 2168, +2007, 1783, 2248, +2007, 1799, 2329, +2072, 1654, 1028, +2088, 1638, 1060, +2104, 1638, 1108, +2136, 1638, 1188, +2104, 1638, 1285, +2072, 1670, 1510, +1991, 1702, 1638, +1911, 1734, 1734, +1879, 1766, 1766, +1911, 1783, 1863, +1943, 1799, 1927, +1975, 1815, 1991, +1959, 1847, 2088, +1975, 1847, 2152, +2007, 1863, 2232, +2056, 1895, 2312, +2104, 1927, 2377, +2136, 1847, 1172, +2136, 1847, 1188, +2152, 1847, 1269, +2136, 1831, 1317, +2168, 1847, 1413, +2200, 1815, 1461, +2136, 1847, 1654, +2120, 1879, 1766, +2023, 1911, 1815, +2039, 1911, 1895, +2039, 1927, 1959, +2088, 1975, 2088, +2072, 1991, 2136, +2088, 2023, 2248, +2152, 2007, 2280, +2200, 2039, 2377, +2216, 2072, 2441, +2216, 2007, 1301, +2184, 2023, 1365, +2200, 2007, 1381, +2200, 2039, 1461, +2184, 2039, 1510, +2200, 2023, 1590, +2232, 2039, 1686, +2296, 2023, 1734, +2184, 2056, 1911, +2184, 2072, 1975, +2168, 2072, 2039, +2152, 2120, 2136, +2200, 2152, 2216, +2232, 2152, 2296, +2264, 2184, 2393, +2312, 2200, 2473, +2312, 2232, 2553, +2345, 2216, 1461, +2361, 2216, 1510, +2345, 2216, 1526, +2329, 2216, 1590, +2329, 2232, 1654, +2312, 2232, 1750, +2312, 2248, 1847, +2345, 2248, 1895, +2361, 2264, 1959, +2329, 2264, 2104, +2329, 2296, 2184, +2296, 2296, 2216, +2312, 2312, 2312, +2329, 2312, 2377, +2345, 2312, 2441, +2361, 2345, 2505, +2425, 2361, 2634, +2505, 2393, 1606, +2489, 2377, 1590, +2489, 2377, 1622, +2473, 2393, 1686, +2457, 2377, 1734, +2457, 2393, 1831, +2473, 2393, 1895, +2473, 2409, 2007, +2489, 2409, 2072, +2473, 2425, 2152, +2473, 2441, 2232, +2473, 2457, 2296, +2473, 2489, 2393, +2505, 2489, 2473, +2489, 2505, 2521, +2505, 2505, 2602, +2553, 2537, 2698, +2585, 2569, 1686, +2585, 2569, 1686, +2585, 2585, 1750, +2585, 2585, 1783, +2569, 2585, 1847, +2618, 2618, 1959, +2569, 2585, 2007, +2569, 2602, 2072, +2602, 2618, 2152, +2602, 2634, 2264, +2585, 2618, 2329, +2618, 2634, 2409, +2634, 2666, 2505, +2650, 2666, 2569, +2650, 2666, 2634, +2666, 2714, 2730, +2666, 2698, 2778, +2746, 2778, 1831, +2698, 2778, 1815, +2714, 2810, 1879, +2714, 2794, 1927, +2730, 2794, 1975, +2698, 2794, 2023, +2730, 2794, 2088, +2698, 2794, 2168, +2698, 2810, 2248, +2746, 2810, 2361, +2762, 2810, 2457, +2762, 2794, 2505, +2778, 2810, 2553, +2794, 2826, 2666, +2842, 2858, 2762, +2842, 2842, 2810, +2842, 2858, 2891, +2858, 2971, 1943, +2875, 2971, 1943, +2842, 2955, 1959, +2858, 2987, 2007, +2875, 2971, 2072, +2858, 2971, 2120, +2842, 2971, 2216, +2826, 2987, 2280, +2858, 2987, 2361, +2858, 2987, 2441, +2875, 2987, 2553, +2907, 3003, 2634, +2891, 3003, 2682, +2939, 3003, 2698, +2971, 3019, 2794, +2939, 3035, 2907, +3003, 3067, 3019, +2971, 3180, 2039, +3003, 3180, 2072, +3019, 3196, 2136, +2987, 3180, 2152, +2987, 3196, 2216, +3003, 3180, 2280, +2987, 3180, 2329, +3019, 3196, 2409, +3051, 3196, 2489, +3035, 3180, 2602, +3019, 3196, 2682, +3051, 3196, 2746, +3051, 3180, 2794, +3051, 3196, 2875, +3099, 3196, 2891, +3115, 3196, 2955, +3148, 3228, 3067, +3099, 3372, 2184, +3115, 3356, 2200, +3131, 3388, 2216, +3115, 3372, 2280, +3099, 3372, 2296, +3115, 3388, 2345, +3115, 3388, 2441, +3164, 3404, 2537, +3180, 3404, 2634, +3148, 3388, 2714, +3148, 3388, 2778, +3180, 3404, 2858, +3196, 3388, 2923, +3244, 3404, 3003, +3260, 3404, 3083, +3276, 3404, 3115, +3324, 3421, 3196, +3292, 3565, 2312, +3308, 3581, 2329, +3276, 3565, 2345, +3292, 3581, 2409, +3276, 3581, 2425, +3308, 3581, 2505, +3292, 3581, 2569, +3308, 3581, 2666, +3292, 3581, 2730, +3308, 3581, 2826, +3324, 3581, 2891, +3356, 3581, 2971, +3372, 3597, 3083, +3372, 3581, 3148, +3404, 3613, 3212, +3421, 3613, 3276, +3437, 3613, 3308, +2120, 1060, 867, +2104, 1060, 931, +2056, 1092, 1044, +1943, 1140, 1188, +1831, 1204, 1285, +1750, 1269, 1381, +1718, 1301, 1445, +1702, 1317, 1510, +1734, 1349, 1606, +1750, 1365, 1670, +1750, 1381, 1734, +1766, 1381, 1799, +1815, 1429, 1879, +1831, 1477, 1975, +1879, 1493, 2072, +1911, 1558, 2168, +1927, 1590, 2264, +2088, 1108, 867, +2072, 1092, 947, +2072, 1140, 1076, +1975, 1172, 1188, +1895, 1237, 1301, +1783, 1285, 1413, +1718, 1349, 1445, +1734, 1349, 1542, +1750, 1365, 1622, +1734, 1381, 1686, +1766, 1397, 1766, +1783, 1429, 1815, +1815, 1445, 1927, +1847, 1493, 1991, +1895, 1510, 2088, +1911, 1558, 2184, +1959, 1590, 2248, +2136, 1188, 899, +2120, 1204, 1012, +2104, 1188, 1076, +2023, 1237, 1237, +1927, 1269, 1333, +1831, 1333, 1461, +1750, 1381, 1477, +1766, 1397, 1558, +1750, 1397, 1606, +1783, 1445, 1686, +1799, 1445, 1766, +1815, 1477, 1831, +1847, 1510, 1943, +1879, 1542, 2007, +1895, 1558, 2120, +1959, 1590, 2184, +1991, 1622, 2248, +2168, 1253, 915, +2120, 1253, 996, +2120, 1269, 1108, +2072, 1269, 1188, +1975, 1349, 1381, +1895, 1397, 1477, +1815, 1445, 1526, +1799, 1461, 1590, +1815, 1477, 1654, +1799, 1493, 1718, +1847, 1526, 1815, +1847, 1542, 1879, +1895, 1590, 2007, +1895, 1606, 2056, +1943, 1622, 2104, +1959, 1654, 2200, +2023, 1702, 2312, +2280, 1333, 835, +2232, 1365, 947, +2168, 1381, 1108, +2152, 1397, 1204, +2088, 1445, 1381, +1991, 1461, 1477, +1911, 1542, 1590, +1847, 1558, 1638, +1895, 1590, 1718, +1879, 1606, 1799, +1895, 1622, 1831, +1911, 1622, 1911, +1927, 1654, 1975, +1991, 1670, 2072, +2023, 1702, 2200, +2039, 1750, 2232, +2088, 1783, 2329, +2329, 1493, 931, +2312, 1493, 980, +2296, 1493, 1076, +2184, 1542, 1285, +2200, 1542, 1381, +2120, 1606, 1526, +2023, 1638, 1638, +1943, 1670, 1686, +1943, 1686, 1766, +1959, 1718, 1831, +1975, 1718, 1895, +1991, 1718, 1975, +2072, 1766, 2056, +2088, 1799, 2136, +2072, 1815, 2200, +2072, 1831, 2280, +2120, 1879, 2377, +2329, 1686, 1076, +2345, 1686, 1076, +2361, 1702, 1140, +2377, 1686, 1237, +2312, 1702, 1397, +2264, 1702, 1526, +2168, 1750, 1670, +2120, 1799, 1766, +2072, 1831, 1831, +2056, 1831, 1895, +2104, 1863, 1959, +2104, 1863, 2023, +2136, 1879, 2104, +2136, 1911, 2184, +2152, 1959, 2280, +2184, 1959, 2345, +2232, 1991, 2441, +2345, 1863, 1156, +2312, 1863, 1204, +2345, 1879, 1253, +2345, 1863, 1301, +2377, 1863, 1397, +2377, 1879, 1493, +2312, 1895, 1686, +2280, 1927, 1815, +2184, 1959, 1895, +2152, 1975, 1927, +2184, 1991, 2007, +2216, 2007, 2088, +2248, 2023, 2168, +2216, 2039, 2232, +2264, 2072, 2329, +2312, 2104, 2425, +2361, 2136, 2521, +2393, 2039, 1301, +2393, 2039, 1333, +2409, 2039, 1365, +2409, 2039, 1445, +2441, 2039, 1477, +2425, 2039, 1558, +2473, 2039, 1670, +2425, 2072, 1847, +2361, 2120, 1975, +2312, 2136, 2007, +2329, 2152, 2104, +2345, 2168, 2168, +2361, 2184, 2248, +2329, 2200, 2296, +2393, 2232, 2393, +2393, 2232, 2489, +2425, 2280, 2553, +2489, 2264, 1510, +2489, 2264, 1510, +2489, 2280, 1558, +2505, 2264, 1606, +2457, 2280, 1670, +2473, 2280, 1734, +2457, 2264, 1783, +2521, 2280, 1863, +2553, 2248, 1943, +2425, 2296, 2152, +2425, 2296, 2184, +2425, 2312, 2248, +2473, 2345, 2345, +2457, 2361, 2409, +2489, 2377, 2489, +2505, 2377, 2553, +2537, 2409, 2650, +2634, 2441, 1606, +2618, 2425, 1622, +2602, 2425, 1670, +2602, 2441, 1718, +2618, 2457, 1799, +2569, 2441, 1863, +2569, 2457, 1927, +2585, 2473, 2039, +2585, 2457, 2104, +2618, 2457, 2136, +2569, 2473, 2280, +2585, 2489, 2361, +2569, 2505, 2425, +2569, 2521, 2505, +2602, 2521, 2569, +2634, 2569, 2650, +2666, 2569, 2746, +2698, 2602, 1702, +2714, 2618, 1750, +2746, 2618, 1799, +2714, 2618, 1847, +2730, 2634, 1911, +2714, 2634, 1975, +2698, 2634, 2039, +2714, 2618, 2088, +2714, 2650, 2200, +2746, 2666, 2312, +2730, 2682, 2377, +2714, 2682, 2441, +2714, 2698, 2505, +2714, 2714, 2618, +2714, 2698, 2682, +2730, 2730, 2762, +2746, 2746, 2842, +2842, 2810, 1847, +2842, 2810, 1879, +2858, 2794, 1911, +2875, 2810, 1911, +2858, 2810, 1975, +2842, 2810, 2039, +2842, 2794, 2120, +2826, 2794, 2184, +2858, 2810, 2296, +2858, 2826, 2329, +2858, 2842, 2441, +2858, 2842, 2537, +2875, 2842, 2602, +2875, 2858, 2682, +2907, 2875, 2762, +2907, 2891, 2826, +2907, 2907, 2907, +2971, 3003, 1943, +2971, 2971, 1959, +2987, 2987, 2007, +2939, 2987, 2023, +2971, 2987, 2104, +2955, 2987, 2152, +2939, 3003, 2232, +2987, 3003, 2312, +2955, 3003, 2361, +2987, 3003, 2473, +3003, 3019, 2585, +2987, 3035, 2682, +3019, 3035, 2714, +3019, 3051, 2762, +3035, 3051, 2858, +3067, 3067, 2971, +3051, 3083, 3035, +3115, 3212, 2104, +3115, 3212, 2088, +3115, 3212, 2136, +3083, 3196, 2184, +3083, 3212, 2216, +3083, 3212, 2280, +3099, 3196, 2312, +3083, 3212, 2409, +3099, 3196, 2473, +3067, 3196, 2569, +3099, 3212, 2666, +3115, 3212, 2746, +3148, 3228, 2826, +3131, 3228, 2875, +3164, 3228, 2923, +3196, 3244, 3003, +3212, 3260, 3115, +3228, 3404, 2216, +3244, 3404, 2232, +3212, 3404, 2264, +3228, 3404, 2296, +3212, 3404, 2345, +3196, 3404, 2377, +3212, 3388, 2441, +3212, 3404, 2521, +3228, 3404, 2618, +3228, 3388, 2714, +3324, 3421, 2810, +3292, 3421, 2907, +3292, 3404, 2955, +3340, 3421, 3051, +3324, 3437, 3115, +3372, 3453, 3164, +3388, 3437, 3196, +3388, 3581, 2361, +3421, 3613, 2377, +3404, 3597, 2409, +3388, 3597, 2441, +3388, 3597, 2473, +3372, 3597, 2505, +3356, 3597, 2553, +3388, 3613, 2666, +3388, 3629, 2746, +3372, 3613, 2826, +3421, 3581, 2891, +3421, 3613, 2971, +3453, 3581, 3099, +3469, 3613, 3148, +3469, 3597, 3212, +3485, 3613, 3260, +3517, 3629, 3308, +2296, 1156, 915, +2296, 1156, 1012, +2264, 1172, 1140, +2168, 1237, 1237, +2072, 1301, 1381, +1975, 1333, 1445, +1879, 1397, 1542, +1895, 1429, 1558, +1879, 1445, 1654, +1911, 1461, 1718, +1927, 1493, 1815, +1927, 1510, 1879, +1959, 1526, 1959, +1975, 1558, 2039, +2056, 1574, 2120, +2088, 1622, 2216, +2120, 1654, 2312, +2296, 1172, 931, +2296, 1188, 1012, +2280, 1188, 1124, +2184, 1253, 1285, +2072, 1301, 1381, +1991, 1365, 1445, +1911, 1413, 1526, +1895, 1445, 1574, +1911, 1461, 1654, +1911, 1493, 1750, +1943, 1510, 1831, +1943, 1526, 1911, +1959, 1574, 1991, +2007, 1574, 2039, +2056, 1606, 2104, +2072, 1622, 2216, +2120, 1670, 2280, +2312, 1253, 947, +2329, 1237, 996, +2329, 1253, 1124, +2232, 1285, 1237, +2136, 1365, 1381, +2023, 1413, 1493, +1927, 1461, 1574, +1943, 1510, 1638, +1927, 1526, 1702, +1943, 1526, 1750, +1975, 1574, 1863, +1975, 1574, 1895, +1991, 1590, 1991, +2023, 1606, 2072, +2072, 1622, 2152, +2104, 1670, 2232, +2136, 1702, 2361, +2361, 1317, 947, +2329, 1333, 1060, +2329, 1349, 1140, +2296, 1349, 1269, +2184, 1429, 1413, +2120, 1477, 1542, +2007, 1542, 1622, +1959, 1558, 1638, +1959, 1574, 1718, +1959, 1590, 1783, +1975, 1606, 1847, +1975, 1622, 1927, +2056, 1638, 2023, +2072, 1686, 2104, +2120, 1702, 2200, +2136, 1734, 2248, +2184, 1750, 2345, +2473, 1397, 915, +2425, 1445, 1060, +2361, 1445, 1172, +2345, 1445, 1285, +2296, 1477, 1397, +2200, 1542, 1510, +2088, 1590, 1622, +2023, 1654, 1702, +2023, 1654, 1750, +2039, 1654, 1815, +2056, 1686, 1911, +2088, 1702, 1991, +2120, 1750, 2056, +2152, 1766, 2136, +2152, 1783, 2200, +2200, 1815, 2296, +2168, 1847, 2377, +2537, 1558, 947, +2505, 1526, 996, +2489, 1558, 1140, +2409, 1606, 1349, +2377, 1606, 1445, +2296, 1622, 1574, +2232, 1686, 1670, +2152, 1734, 1766, +2104, 1766, 1799, +2136, 1766, 1879, +2136, 1799, 1943, +2136, 1815, 2007, +2168, 1815, 2088, +2184, 1847, 2168, +2216, 1863, 2232, +2312, 1911, 2377, +2280, 1943, 2425, +2553, 1718, 1012, +2521, 1702, 1060, +2569, 1702, 1140, +2521, 1718, 1237, +2441, 1734, 1429, +2441, 1766, 1590, +2377, 1799, 1670, +2264, 1847, 1815, +2184, 1895, 1847, +2216, 1911, 1943, +2216, 1927, 2007, +2232, 1943, 2088, +2248, 1943, 2152, +2296, 1959, 2264, +2312, 1975, 2280, +2329, 2007, 2361, +2361, 2072, 2473, +2585, 1911, 1156, +2585, 1911, 1188, +2618, 1911, 1237, +2585, 1895, 1317, +2585, 1879, 1381, +2569, 1927, 1590, +2537, 1927, 1718, +2441, 1975, 1847, +2345, 2007, 1943, +2345, 2039, 2007, +2329, 2056, 2072, +2345, 2056, 2136, +2377, 2104, 2232, +2425, 2120, 2296, +2409, 2136, 2393, +2425, 2168, 2473, +2489, 2200, 2553, +2618, 2088, 1285, +2618, 2104, 1317, +2602, 2104, 1381, +2634, 2072, 1413, +2618, 2104, 1510, +2666, 2088, 1606, +2666, 2104, 1702, +2602, 2120, 1863, +2537, 2152, 2023, +2441, 2200, 2088, +2457, 2216, 2136, +2473, 2216, 2232, +2473, 2232, 2296, +2489, 2248, 2361, +2473, 2248, 2441, +2505, 2296, 2537, +2553, 2296, 2602, +2650, 2280, 1445, +2666, 2280, 1477, +2634, 2264, 1526, +2634, 2264, 1558, +2634, 2280, 1622, +2650, 2280, 1686, +2650, 2296, 1783, +2746, 2264, 1863, +2682, 2280, 2023, +2602, 2312, 2184, +2585, 2361, 2216, +2602, 2361, 2264, +2585, 2377, 2393, +2618, 2393, 2489, +2602, 2425, 2537, +2618, 2425, 2602, +2634, 2473, 2698, +2714, 2473, 1622, +2714, 2473, 1654, +2698, 2473, 1670, +2730, 2473, 1718, +2730, 2489, 1783, +2698, 2473, 1831, +2698, 2457, 1911, +2714, 2489, 1991, +2762, 2473, 2056, +2794, 2473, 2136, +2746, 2505, 2329, +2666, 2537, 2393, +2698, 2553, 2457, +2698, 2553, 2537, +2714, 2585, 2618, +2746, 2618, 2714, +2762, 2602, 2762, +2842, 2666, 1783, +2842, 2666, 1783, +2826, 2650, 1799, +2858, 2666, 1879, +2858, 2666, 1943, +2826, 2666, 1959, +2842, 2682, 2072, +2826, 2698, 2168, +2794, 2682, 2216, +2826, 2682, 2296, +2842, 2682, 2361, +2826, 2714, 2489, +2826, 2730, 2569, +2810, 2730, 2634, +2858, 2746, 2682, +2875, 2746, 2746, +2875, 2762, 2826, +2971, 2810, 1879, +2971, 2826, 1895, +2955, 2810, 1911, +2971, 2826, 1927, +2971, 2810, 2007, +2971, 2826, 2088, +2971, 2842, 2152, +2955, 2842, 2248, +2955, 2875, 2329, +2971, 2858, 2393, +3003, 2875, 2489, +2971, 2875, 2553, +2971, 2891, 2666, +2971, 2907, 2730, +2955, 2907, 2794, +2987, 2939, 2891, +2987, 2939, 2955, +3083, 3035, 1991, +3067, 3003, 1975, +3067, 3035, 2023, +3067, 3035, 2072, +3083, 3019, 2120, +3067, 3019, 2184, +3083, 3019, 2280, +3099, 3035, 2329, +3083, 3035, 2377, +3099, 3051, 2489, +3067, 3051, 2569, +3067, 3067, 2650, +3115, 3083, 2746, +3131, 3083, 2810, +3131, 3099, 2891, +3164, 3115, 2971, +3164, 3131, 3035, +3180, 3196, 2072, +3180, 3196, 2104, +3180, 3196, 2136, +3180, 3212, 2168, +3196, 3196, 2232, +3180, 3228, 2280, +3164, 3196, 2329, +3180, 3212, 2409, +3180, 3212, 2505, +3196, 3244, 2585, +3180, 3212, 2666, +3228, 3228, 2746, +3212, 3244, 2858, +3228, 3244, 2923, +3276, 3260, 2971, +3260, 3276, 3083, +3276, 3324, 3180, +3340, 3421, 2232, +3324, 3404, 2264, +3340, 3421, 2296, +3324, 3421, 2329, +3372, 3437, 2377, +3340, 3421, 2393, +3340, 3421, 2473, +3356, 3421, 2569, +3356, 3437, 2650, +3372, 3437, 2698, +3372, 3453, 2778, +3372, 3453, 2875, +3388, 3453, 2971, +3421, 3469, 3099, +3437, 3453, 3131, +3453, 3469, 3180, +3453, 3469, 3244, +3485, 3597, 2393, +3517, 3629, 2409, +3501, 3613, 2409, +3485, 3613, 2473, +3469, 3613, 2489, +3469, 3613, 2537, +3501, 3645, 2602, +3501, 3629, 2682, +3485, 3645, 2746, +3485, 3629, 2842, +3517, 3629, 2907, +3517, 3613, 3003, +3485, 3629, 3099, +3533, 3645, 3196, +3533, 3629, 3244, +3549, 3661, 3308, +3597, 3661, 3356, +2505, 1253, 996, +2537, 1253, 1060, +2473, 1253, 1140, +2377, 1317, 1317, +2296, 1365, 1413, +2184, 1445, 1526, +2104, 1493, 1622, +2039, 1542, 1670, +2072, 1574, 1718, +2039, 1558, 1750, +2056, 1574, 1847, +2104, 1606, 1943, +2120, 1638, 2039, +2152, 1654, 2104, +2184, 1670, 2168, +2232, 1702, 2264, +2232, 1734, 2345, +2521, 1269, 980, +2505, 1301, 1076, +2505, 1285, 1156, +2393, 1333, 1301, +2312, 1381, 1429, +2200, 1461, 1542, +2120, 1510, 1638, +2056, 1574, 1654, +2072, 1574, 1718, +2104, 1590, 1799, +2104, 1606, 1863, +2136, 1622, 1959, +2152, 1654, 2056, +2168, 1686, 2104, +2200, 1702, 2200, +2232, 1734, 2248, +2264, 1750, 2329, +2521, 1333, 1012, +2521, 1349, 1108, +2505, 1349, 1188, +2457, 1381, 1317, +2377, 1429, 1429, +2264, 1477, 1526, +2136, 1542, 1606, +2088, 1606, 1686, +2056, 1606, 1734, +2120, 1638, 1831, +2136, 1638, 1895, +2136, 1638, 1959, +2168, 1670, 2072, +2200, 1702, 2104, +2232, 1718, 2184, +2248, 1766, 2312, +2264, 1783, 2361, +2537, 1397, 1028, +2537, 1413, 1092, +2521, 1413, 1172, +2521, 1429, 1317, +2425, 1493, 1445, +2296, 1542, 1574, +2232, 1590, 1670, +2152, 1638, 1734, +2136, 1670, 1783, +2168, 1686, 1879, +2184, 1718, 1943, +2184, 1718, 2007, +2232, 1750, 2088, +2216, 1750, 2152, +2232, 1783, 2232, +2280, 1815, 2329, +2345, 1815, 2377, +2634, 1477, 1012, +2585, 1510, 1092, +2553, 1542, 1220, +2569, 1526, 1349, +2489, 1558, 1461, +2393, 1622, 1606, +2312, 1654, 1686, +2232, 1702, 1766, +2200, 1750, 1815, +2200, 1766, 1895, +2216, 1766, 1959, +2216, 1783, 2023, +2248, 1815, 2088, +2280, 1831, 2168, +2296, 1863, 2248, +2361, 1879, 2345, +2409, 1911, 2441, +2698, 1590, 980, +2682, 1590, 1028, +2650, 1638, 1188, +2569, 1654, 1317, +2585, 1654, 1461, +2489, 1686, 1590, +2409, 1734, 1718, +2312, 1799, 1799, +2248, 1847, 1847, +2280, 1863, 1927, +2264, 1863, 1975, +2329, 1895, 2072, +2345, 1895, 2136, +2377, 1911, 2248, +2393, 1943, 2312, +2425, 1959, 2345, +2425, 1975, 2441, +2794, 1734, 1044, +2778, 1718, 1092, +2778, 1734, 1172, +2730, 1766, 1285, +2650, 1799, 1477, +2618, 1799, 1606, +2569, 1847, 1734, +2505, 1895, 1847, +2393, 1943, 1927, +2393, 1975, 1975, +2361, 1975, 2023, +2409, 1991, 2104, +2409, 2007, 2184, +2457, 2039, 2280, +2457, 2072, 2361, +2489, 2088, 2441, +2553, 2136, 2569, +2778, 1911, 1140, +2794, 1927, 1188, +2794, 1911, 1237, +2826, 1943, 1333, +2826, 1959, 1429, +2714, 1991, 1654, +2730, 1991, 1766, +2634, 2039, 1879, +2537, 2072, 1959, +2473, 2120, 2039, +2473, 2136, 2104, +2505, 2152, 2184, +2505, 2168, 2248, +2553, 2200, 2361, +2569, 2184, 2409, +2602, 2200, 2489, +2585, 2200, 2553, +2810, 2136, 1317, +2810, 2152, 1349, +2810, 2120, 1365, +2810, 2136, 1429, +2842, 2120, 1493, +2842, 2120, 1590, +2778, 2152, 1799, +2746, 2152, 1895, +2682, 2184, 2056, +2602, 2248, 2152, +2553, 2248, 2184, +2553, 2264, 2248, +2602, 2280, 2345, +2634, 2296, 2425, +2666, 2312, 2489, +2682, 2345, 2553, +2666, 2361, 2666, +2826, 2280, 1429, +2826, 2296, 1477, +2858, 2296, 1526, +2842, 2296, 1574, +2858, 2296, 1606, +2907, 2296, 1686, +2891, 2312, 1783, +2923, 2312, 1879, +2842, 2312, 2072, +2778, 2361, 2200, +2698, 2409, 2280, +2714, 2441, 2361, +2682, 2425, 2409, +2730, 2441, 2489, +2746, 2441, 2553, +2730, 2489, 2650, +2746, 2489, 2714, +2875, 2505, 1622, +2891, 2489, 1622, +2891, 2505, 1654, +2875, 2505, 1718, +2907, 2489, 1750, +2891, 2489, 1847, +2907, 2489, 1943, +2923, 2505, 1975, +2955, 2489, 2039, +2939, 2505, 2232, +2842, 2537, 2377, +2794, 2569, 2425, +2810, 2602, 2505, +2810, 2602, 2602, +2858, 2634, 2698, +2842, 2666, 2746, +2858, 2666, 2810, +2939, 2682, 1799, +2939, 2682, 1799, +2923, 2682, 1815, +2939, 2698, 1895, +2923, 2698, 1927, +2955, 2698, 1991, +2939, 2698, 2056, +2971, 2714, 2136, +2971, 2714, 2200, +3003, 2714, 2296, +3083, 2682, 2361, +2971, 2730, 2553, +2923, 2746, 2569, +2955, 2746, 2650, +2923, 2778, 2730, +2971, 2794, 2810, +3019, 2826, 2907, +3083, 2842, 1911, +3099, 2875, 1927, +3083, 2858, 1943, +3115, 2858, 1991, +3115, 2875, 2072, +3099, 2875, 2120, +3083, 2875, 2216, +3083, 2891, 2280, +3083, 2907, 2329, +3067, 2907, 2409, +3067, 2891, 2457, +3099, 2907, 2569, +3099, 2891, 2698, +3083, 2939, 2794, +3035, 2955, 2810, +3067, 2955, 2891, +3115, 2987, 2987, +3228, 3051, 2023, +3228, 3051, 2023, +3228, 3067, 2088, +3212, 3051, 2120, +3212, 3067, 2184, +3180, 3051, 2232, +3212, 3067, 2312, +3212, 3067, 2345, +3196, 3083, 2441, +3212, 3067, 2505, +3212, 3099, 2618, +3244, 3115, 2698, +3228, 3115, 2762, +3228, 3131, 2875, +3212, 3131, 2939, +3180, 3131, 2987, +3212, 3148, 3067, +3308, 3244, 2136, +3292, 3228, 2152, +3292, 3244, 2168, +3324, 3228, 2232, +3276, 3244, 2248, +3292, 3228, 2329, +3292, 3228, 2345, +3292, 3260, 2457, +3308, 3244, 2521, +3308, 3260, 2634, +3308, 3244, 2682, +3308, 3260, 2762, +3308, 3292, 2842, +3324, 3292, 2939, +3372, 3324, 3035, +3340, 3308, 3099, +3372, 3308, 3164, +3469, 3437, 2280, +3485, 3437, 2280, +3469, 3437, 2312, +3469, 3437, 2345, +3485, 3469, 2425, +3469, 3469, 2425, +3485, 3453, 2521, +3469, 3453, 2585, +3453, 3453, 2634, +3485, 3469, 2762, +3485, 3485, 2810, +3485, 3469, 2891, +3501, 3469, 2987, +3469, 3469, 3067, +3517, 3501, 3180, +3501, 3501, 3212, +3533, 3501, 3324, +3597, 3629, 2409, +3549, 3629, 2425, +3581, 3613, 2425, +3581, 3613, 2457, +3597, 3645, 2489, +3565, 3629, 2521, +3549, 3629, 2585, +3581, 3629, 2698, +3581, 3645, 2746, +3565, 3645, 2842, +3581, 3645, 2875, +3565, 3645, 2971, +3581, 3661, 3083, +3597, 3677, 3228, +3613, 3661, 3292, +3677, 3677, 3324, +3677, 3694, 3356, +2682, 1333, 1028, +2666, 1333, 1108, +2666, 1349, 1188, +2602, 1413, 1333, +2505, 1445, 1461, +2441, 1510, 1574, +2329, 1590, 1702, +2264, 1638, 1766, +2216, 1638, 1783, +2232, 1654, 1831, +2264, 1686, 1943, +2280, 1718, 2023, +2280, 1718, 2056, +2312, 1750, 2184, +2329, 1766, 2232, +2377, 1799, 2329, +2409, 1815, 2409, +2682, 1365, 1044, +2698, 1365, 1092, +2714, 1381, 1220, +2634, 1429, 1349, +2521, 1493, 1493, +2441, 1526, 1590, +2361, 1574, 1686, +2264, 1638, 1766, +2264, 1686, 1799, +2264, 1686, 1863, +2264, 1702, 1927, +2280, 1734, 2007, +2312, 1750, 2120, +2312, 1766, 2168, +2361, 1783, 2248, +2409, 1815, 2312, +2457, 1847, 2441, +2698, 1429, 1076, +2698, 1397, 1108, +2714, 1413, 1220, +2682, 1461, 1365, +2569, 1526, 1493, +2473, 1558, 1590, +2377, 1622, 1686, +2312, 1670, 1783, +2280, 1718, 1831, +2248, 1718, 1879, +2296, 1734, 1943, +2296, 1750, 2023, +2329, 1783, 2088, +2361, 1799, 2168, +2361, 1831, 2248, +2425, 1831, 2329, +2457, 1879, 2441, +2730, 1493, 1092, +2746, 1493, 1156, +2746, 1493, 1237, +2698, 1510, 1333, +2634, 1574, 1493, +2553, 1622, 1590, +2457, 1686, 1718, +2345, 1702, 1783, +2296, 1766, 1831, +2329, 1766, 1863, +2329, 1799, 1975, +2329, 1799, 2007, +2361, 1831, 2136, +2393, 1831, 2200, +2425, 1879, 2264, +2457, 1895, 2377, +2489, 1927, 2409, +2842, 1558, 1044, +2730, 1574, 1156, +2746, 1606, 1269, +2730, 1606, 1365, +2698, 1622, 1477, +2569, 1670, 1606, +2521, 1734, 1718, +2425, 1766, 1799, +2361, 1815, 1863, +2345, 1847, 1927, +2393, 1879, 2023, +2425, 1895, 2104, +2441, 1879, 2168, +2457, 1927, 2216, +2441, 1927, 2280, +2505, 1959, 2377, +2521, 1991, 2473, +2907, 1638, 1012, +2891, 1670, 1140, +2826, 1718, 1269, +2778, 1702, 1349, +2794, 1718, 1510, +2730, 1766, 1638, +2634, 1799, 1766, +2553, 1879, 1847, +2489, 1895, 1927, +2473, 1959, 1991, +2441, 1959, 2039, +2473, 1959, 2104, +2473, 1975, 2200, +2521, 2023, 2280, +2553, 2039, 2361, +2553, 2072, 2457, +2602, 2104, 2537, +2987, 1766, 1044, +2955, 1783, 1108, +2939, 1799, 1204, +2875, 1831, 1365, +2842, 1863, 1493, +2826, 1863, 1638, +2746, 1911, 1783, +2634, 1943, 1879, +2585, 2007, 1975, +2521, 2056, 2007, +2553, 2072, 2088, +2553, 2088, 2152, +2602, 2120, 2248, +2602, 2136, 2329, +2618, 2168, 2409, +2602, 2152, 2489, +2682, 2168, 2553, +3019, 1991, 1204, +3003, 1975, 1237, +3003, 1991, 1269, +3019, 1991, 1365, +2955, 2007, 1526, +2891, 2039, 1670, +2923, 2056, 1815, +2810, 2088, 1943, +2730, 2136, 2039, +2634, 2168, 2120, +2618, 2200, 2168, +2602, 2200, 2232, +2666, 2216, 2312, +2682, 2232, 2393, +2682, 2232, 2441, +2698, 2264, 2537, +2730, 2280, 2618, +3003, 2136, 1285, +2987, 2136, 1301, +3035, 2136, 1349, +3067, 2136, 1429, +3051, 2104, 1493, +3035, 2152, 1638, +2939, 2168, 1831, +2955, 2168, 1959, +2875, 2216, 2088, +2746, 2264, 2200, +2714, 2312, 2200, +2714, 2329, 2280, +2746, 2345, 2361, +2746, 2361, 2473, +2794, 2377, 2521, +2762, 2377, 2602, +2794, 2409, 2698, +3051, 2345, 1461, +3035, 2345, 1477, +3067, 2345, 1526, +3067, 2345, 1558, +3051, 2345, 1606, +3051, 2329, 1686, +3067, 2312, 1783, +3019, 2345, 1991, +3003, 2345, 2072, +2939, 2393, 2216, +2858, 2457, 2345, +2810, 2457, 2361, +2826, 2489, 2457, +2842, 2505, 2537, +2858, 2521, 2618, +2891, 2521, 2682, +2907, 2569, 2778, +3083, 2553, 1622, +3067, 2537, 1638, +3051, 2521, 1622, +3067, 2521, 1686, +3083, 2537, 1766, +3099, 2537, 1831, +3115, 2537, 1927, +3180, 2537, 1991, +3148, 2521, 2056, +3083, 2553, 2264, +3035, 2602, 2441, +2955, 2634, 2473, +2955, 2650, 2505, +2939, 2666, 2602, +2955, 2666, 2714, +2971, 2682, 2730, +2987, 2698, 2875, +3148, 2714, 1783, +3131, 2714, 1799, +3131, 2714, 1831, +3115, 2714, 1863, +3099, 2714, 1911, +3131, 2714, 1959, +3131, 2714, 2023, +3148, 2714, 2088, +3212, 2714, 2200, +3212, 2698, 2248, +3164, 2730, 2457, +3115, 2762, 2569, +3067, 2794, 2618, +3067, 2810, 2698, +3099, 2826, 2778, +3099, 2826, 2842, +3099, 2858, 2923, +3212, 2891, 1911, +3180, 2907, 1943, +3212, 2907, 1975, +3164, 2907, 1991, +3196, 2907, 2072, +3196, 2923, 2136, +3180, 2907, 2200, +3180, 2907, 2248, +3228, 2907, 2296, +3212, 2907, 2361, +3276, 2923, 2473, +3276, 2907, 2537, +3228, 2939, 2698, +3180, 2987, 2778, +3196, 2987, 2891, +3164, 3019, 2955, +3212, 3035, 3051, +3356, 3099, 2056, +3324, 3083, 2072, +3340, 3099, 2104, +3356, 3115, 2152, +3340, 3115, 2216, +3340, 3099, 2280, +3340, 3099, 2296, +3340, 3131, 2425, +3324, 3115, 2473, +3292, 3115, 2553, +3292, 3131, 2634, +3292, 3115, 2682, +3324, 3115, 2762, +3292, 3115, 2875, +3292, 3148, 2955, +3292, 3196, 3035, +3308, 3180, 3083, +3421, 3276, 2152, +3421, 3276, 2184, +3453, 3260, 2216, +3437, 3276, 2248, +3404, 3276, 2312, +3437, 3292, 2361, +3421, 3292, 2425, +3404, 3292, 2489, +3453, 3308, 2585, +3437, 3324, 2682, +3453, 3308, 2778, +3453, 3324, 2810, +3453, 3308, 2891, +3453, 3324, 2971, +3485, 3340, 3083, +3485, 3372, 3164, +3453, 3356, 3228, +3597, 3469, 2329, +3581, 3469, 2329, +3597, 3485, 2377, +3581, 3469, 2393, +3581, 3485, 2425, +3581, 3485, 2473, +3549, 3469, 2521, +3565, 3469, 2618, +3565, 3453, 2682, +3581, 3469, 2746, +3597, 3469, 2826, +3597, 3501, 2907, +3613, 3501, 3019, +3581, 3517, 3067, +3597, 3517, 3180, +3613, 3517, 3244, +3629, 3549, 3340, +3677, 3661, 2425, +3677, 3661, 2457, +3677, 3661, 2441, +3694, 3645, 2473, +3694, 3645, 2505, +3677, 3645, 2537, +3694, 3677, 2634, +3710, 3677, 2730, +3677, 3661, 2778, +3710, 3677, 2907, +3694, 3677, 2923, +3710, 3677, 3019, +3710, 3694, 3115, +3726, 3694, 3212, +3694, 3694, 3308, +3758, 3726, 3404, +3806, 3758, 3517, +2923, 1445, 1108, +2907, 1429, 1156, +2907, 1445, 1285, +2842, 1477, 1381, +2730, 1526, 1510, +2634, 1590, 1606, +2553, 1638, 1718, +2441, 1686, 1799, +2409, 1766, 1847, +2409, 1783, 1911, +2441, 1783, 1975, +2473, 1799, 2056, +2473, 1815, 2120, +2489, 1847, 2216, +2521, 1863, 2280, +2553, 1895, 2361, +2553, 1927, 2441, +2923, 1429, 1076, +2923, 1445, 1156, +2907, 1445, 1237, +2842, 1461, 1349, +2778, 1526, 1493, +2650, 1606, 1622, +2585, 1654, 1718, +2489, 1718, 1783, +2409, 1766, 1831, +2425, 1783, 1911, +2425, 1815, 1991, +2457, 1815, 2072, +2489, 1831, 2152, +2489, 1847, 2216, +2537, 1879, 2329, +2553, 1895, 2361, +2569, 1943, 2441, +2939, 1477, 1108, +2923, 1477, 1188, +2907, 1477, 1269, +2875, 1493, 1365, +2794, 1574, 1526, +2714, 1622, 1638, +2602, 1702, 1734, +2521, 1750, 1815, +2441, 1799, 1863, +2409, 1815, 1927, +2489, 1831, 2023, +2489, 1847, 2104, +2489, 1879, 2168, +2537, 1879, 2216, +2537, 1911, 2296, +2569, 1943, 2393, +2602, 1959, 2473, +2955, 1558, 1156, +2939, 1558, 1204, +2923, 1558, 1285, +2923, 1574, 1397, +2858, 1638, 1526, +2778, 1670, 1622, +2666, 1734, 1766, +2602, 1783, 1831, +2537, 1847, 1927, +2505, 1863, 1959, +2521, 1879, 2007, +2537, 1911, 2088, +2505, 1911, 2136, +2553, 1927, 2264, +2553, 1943, 2296, +2634, 2007, 2425, +2650, 2039, 2521, +2987, 1654, 1172, +2987, 1654, 1204, +2971, 1654, 1253, +2971, 1670, 1381, +2907, 1702, 1526, +2826, 1750, 1686, +2762, 1799, 1750, +2682, 1863, 1879, +2553, 1895, 1943, +2537, 1911, 1975, +2553, 1943, 2072, +2569, 1975, 2136, +2569, 2007, 2232, +2618, 2023, 2312, +2618, 2039, 2393, +2666, 2056, 2473, +2666, 2088, 2553, +3099, 1702, 1092, +3035, 1766, 1220, +3003, 1783, 1333, +2987, 1783, 1413, +2971, 1783, 1526, +2907, 1815, 1670, +2826, 1863, 1783, +2762, 1959, 1927, +2682, 2007, 1991, +2618, 2039, 2023, +2634, 2056, 2104, +2650, 2072, 2184, +2650, 2088, 2248, +2666, 2088, 2312, +2682, 2120, 2393, +2714, 2136, 2505, +2746, 2152, 2569, +3228, 1847, 1124, +3164, 1847, 1156, +3180, 1879, 1269, +3083, 1927, 1445, +3067, 1927, 1590, +3051, 1927, 1702, +2939, 1975, 1831, +2875, 2039, 1959, +2778, 2088, 2056, +2714, 2136, 2120, +2682, 2152, 2152, +2666, 2152, 2200, +2746, 2184, 2345, +2730, 2168, 2361, +2762, 2200, 2473, +2778, 2232, 2569, +2794, 2248, 2618, +3260, 2007, 1172, +3244, 2007, 1204, +3228, 2007, 1285, +3196, 2007, 1365, +3115, 2056, 1590, +3083, 2039, 1686, +3099, 2072, 1815, +2987, 2104, 1959, +2923, 2168, 2088, +2826, 2200, 2168, +2778, 2264, 2232, +2810, 2264, 2264, +2778, 2264, 2361, +2794, 2296, 2441, +2810, 2312, 2553, +2842, 2345, 2602, +2858, 2345, 2698, +3244, 2168, 1285, +3228, 2168, 1317, +3260, 2168, 1349, +3228, 2152, 1429, +3244, 2168, 1542, +3212, 2200, 1702, +3131, 2232, 1879, +3099, 2232, 2007, +3051, 2280, 2152, +2955, 2345, 2248, +2858, 2377, 2296, +2842, 2377, 2312, +2858, 2393, 2409, +2891, 2409, 2521, +2891, 2425, 2553, +2923, 2457, 2682, +2939, 2473, 2730, +3228, 2377, 1461, +3244, 2393, 1510, +3228, 2377, 1493, +3276, 2361, 1526, +3276, 2361, 1606, +3292, 2361, 1686, +3276, 2361, 1815, +3196, 2409, 2023, +3196, 2425, 2168, +3099, 2473, 2312, +2987, 2489, 2377, +2939, 2537, 2425, +2955, 2553, 2505, +2971, 2553, 2585, +2971, 2585, 2666, +3003, 2585, 2730, +3019, 2618, 2826, +3260, 2569, 1590, +3260, 2569, 1622, +3260, 2569, 1654, +3244, 2569, 1718, +3260, 2569, 1766, +3308, 2537, 1799, +3292, 2537, 1895, +3324, 2553, 1975, +3260, 2569, 2152, +3244, 2585, 2345, +3164, 2634, 2441, +3131, 2666, 2537, +3067, 2698, 2585, +3099, 2698, 2650, +3099, 2714, 2730, +3115, 2714, 2794, +3115, 2730, 2875, +3292, 2746, 1766, +3324, 2746, 1783, +3324, 2746, 1815, +3308, 2746, 1879, +3308, 2746, 1911, +3324, 2730, 1927, +3324, 2746, 2039, +3356, 2746, 2104, +3404, 2746, 2184, +3388, 2762, 2312, +3356, 2762, 2457, +3292, 2810, 2618, +3196, 2842, 2682, +3196, 2842, 2714, +3180, 2858, 2794, +3228, 2891, 2907, +3228, 2907, 2955, +3372, 2939, 1927, +3388, 2939, 1927, +3372, 2939, 1959, +3372, 2939, 2023, +3388, 2955, 2072, +3372, 2955, 2120, +3356, 2923, 2200, +3388, 2939, 2248, +3404, 2955, 2312, +3404, 2939, 2377, +3469, 2939, 2457, +3404, 2971, 2682, +3372, 3003, 2778, +3324, 3035, 2826, +3324, 3051, 2907, +3372, 3083, 3003, +3340, 3067, 3051, +3404, 3115, 2072, +3404, 3115, 2072, +3404, 3115, 2104, +3404, 3115, 2136, +3404, 3131, 2216, +3421, 3131, 2280, +3404, 3115, 2296, +3388, 3115, 2361, +3404, 3115, 2425, +3404, 3131, 2537, +3437, 3131, 2618, +3453, 3131, 2682, +3517, 3131, 2714, +3421, 3180, 2955, +3404, 3212, 3003, +3437, 3212, 3067, +3437, 3228, 3148, +3565, 3308, 2216, +3597, 3324, 2232, +3581, 3308, 2248, +3565, 3308, 2280, +3565, 3324, 2345, +3565, 3324, 2393, +3581, 3324, 2457, +3581, 3324, 2521, +3549, 3324, 2618, +3533, 3324, 2666, +3565, 3340, 2762, +3581, 3356, 2842, +3581, 3356, 2891, +3613, 3356, 3003, +3597, 3372, 3148, +3597, 3404, 3228, +3581, 3421, 3276, +3694, 3485, 2329, +3694, 3485, 2361, +3694, 3485, 2361, +3694, 3501, 2409, +3710, 3501, 2489, +3710, 3501, 2489, +3710, 3501, 2553, +3694, 3501, 2650, +3677, 3517, 2714, +3694, 3517, 2778, +3677, 3517, 2875, +3710, 3517, 2955, +3694, 3533, 3019, +3710, 3533, 3131, +3710, 3549, 3196, +3694, 3549, 3260, +3710, 3581, 3356, +3838, 3694, 2473, +3806, 3677, 2457, +3822, 3677, 2505, +3822, 3694, 2553, +3806, 3694, 2569, +3790, 3677, 2602, +3790, 3694, 2666, +3806, 3677, 2730, +3790, 3694, 2842, +3790, 3710, 2907, +3838, 3742, 3003, +3854, 3774, 3131, +3854, 3758, 3196, +3854, 3790, 3340, +3822, 3774, 3388, +3838, 3790, 3533, +3854, 3806, 3645, +3115, 1526, 1172, +3099, 1526, 1253, +3099, 1542, 1285, +3067, 1542, 1413, +2971, 1590, 1542, +2891, 1670, 1670, +2794, 1750, 1783, +2730, 1799, 1847, +2650, 1831, 1943, +2618, 1879, 1991, +2602, 1879, 2039, +2618, 1879, 2104, +2634, 1911, 2184, +2650, 1959, 2280, +2666, 1991, 2361, +2698, 1991, 2441, +2746, 2056, 2553, +3099, 1558, 1172, +3115, 1542, 1204, +3099, 1542, 1285, +3083, 1574, 1445, +2971, 1622, 1558, +2891, 1670, 1670, +2826, 1766, 1783, +2746, 1815, 1863, +2634, 1863, 1959, +2618, 1879, 1959, +2585, 1879, 2023, +2602, 1911, 2120, +2634, 1911, 2184, +2666, 1959, 2280, +2698, 2007, 2393, +2730, 2023, 2473, +2730, 2039, 2553, +3131, 1590, 1172, +3148, 1590, 1220, +3115, 1574, 1301, +3067, 1590, 1413, +3019, 1654, 1574, +2955, 1718, 1686, +2842, 1783, 1799, +2746, 1815, 1879, +2650, 1879, 1943, +2618, 1911, 1975, +2650, 1927, 2056, +2666, 1959, 2136, +2682, 1991, 2248, +2666, 1991, 2312, +2714, 2023, 2409, +2730, 2056, 2489, +2762, 2072, 2569, +3131, 1638, 1172, +3115, 1638, 1253, +3131, 1654, 1317, +3115, 1622, 1413, +3035, 1670, 1542, +2987, 1734, 1654, +2875, 1815, 1799, +2810, 1863, 1895, +2730, 1943, 1975, +2682, 1975, 2007, +2682, 1991, 2072, +2698, 2007, 2152, +2682, 2023, 2216, +2730, 2056, 2345, +2762, 2088, 2409, +2794, 2088, 2473, +2810, 2088, 2537, +3148, 1718, 1237, +3180, 1750, 1301, +3164, 1750, 1349, +3180, 1750, 1477, +3180, 1750, 1574, +3051, 1831, 1702, +2987, 1895, 1863, +2875, 1943, 1927, +2778, 1991, 1991, +2714, 2072, 2072, +2730, 2072, 2152, +2730, 2072, 2200, +2762, 2104, 2296, +2794, 2104, 2361, +2794, 2120, 2441, +2810, 2120, 2505, +2826, 2152, 2585, +3324, 1799, 1204, +3276, 1831, 1285, +3228, 1831, 1365, +3228, 1847, 1477, +3212, 1847, 1590, +3148, 1879, 1734, +3083, 1943, 1831, +2955, 2023, 1975, +2907, 2056, 2072, +2794, 2120, 2136, +2762, 2120, 2152, +2810, 2136, 2248, +2794, 2152, 2312, +2826, 2152, 2377, +2842, 2200, 2473, +2842, 2200, 2537, +2891, 2232, 2634, +3404, 1895, 1188, +3372, 1895, 1204, +3324, 1943, 1349, +3228, 1991, 1526, +3228, 1991, 1654, +3212, 1991, 1734, +3148, 2023, 1847, +3067, 2072, 1991, +2987, 2136, 2088, +2891, 2200, 2184, +2842, 2216, 2216, +2858, 2232, 2296, +2858, 2248, 2361, +2858, 2248, 2425, +2907, 2280, 2553, +2907, 2296, 2618, +2907, 2329, 2666, +3437, 2056, 1204, +3421, 2039, 1253, +3388, 2056, 1317, +3372, 2056, 1397, +3276, 2120, 1638, +3260, 2120, 1766, +3244, 2136, 1911, +3164, 2184, 2039, +3067, 2232, 2152, +3019, 2296, 2232, +2907, 2312, 2280, +2923, 2345, 2329, +2923, 2361, 2393, +2939, 2361, 2489, +2955, 2377, 2553, +2955, 2409, 2618, +3003, 2441, 2746, +3404, 2200, 1301, +3469, 2216, 1365, +3453, 2216, 1397, +3437, 2200, 1461, +3421, 2232, 1574, +3340, 2248, 1734, +3292, 2280, 1927, +3308, 2296, 2056, +3228, 2312, 2136, +3099, 2377, 2280, +3019, 2425, 2345, +2987, 2473, 2409, +3003, 2457, 2489, +3035, 2505, 2569, +3035, 2521, 2634, +3051, 2537, 2746, +3051, 2537, 2778, +3437, 2393, 1445, +3469, 2409, 1461, +3469, 2409, 1493, +3485, 2409, 1574, +3469, 2393, 1622, +3469, 2409, 1750, +3437, 2409, 1895, +3388, 2457, 2088, +3340, 2457, 2200, +3292, 2521, 2345, +3164, 2553, 2457, +3083, 2585, 2473, +3099, 2602, 2521, +3099, 2618, 2602, +3115, 2634, 2714, +3164, 2650, 2762, +3164, 2650, 2891, +3469, 2585, 1590, +3469, 2585, 1606, +3453, 2585, 1654, +3485, 2569, 1686, +3469, 2569, 1750, +3533, 2569, 1847, +3549, 2553, 1927, +3501, 2569, 2007, +3421, 2602, 2216, +3437, 2602, 2345, +3340, 2666, 2489, +3260, 2714, 2585, +3212, 2746, 2634, +3212, 2762, 2698, +3228, 2762, 2762, +3244, 2794, 2858, +3260, 2778, 2907, +3485, 2778, 1750, +3485, 2778, 1799, +3469, 2762, 1815, +3469, 2778, 1847, +3485, 2762, 1895, +3533, 2778, 1959, +3517, 2746, 1991, +3565, 2762, 2088, +3565, 2746, 2168, +3549, 2778, 2345, +3517, 2794, 2505, +3421, 2810, 2634, +3356, 2875, 2714, +3308, 2907, 2762, +3324, 2923, 2875, +3324, 2939, 2939, +3356, 2939, 3019, +3533, 2971, 1895, +3533, 3003, 1943, +3549, 2987, 1927, +3533, 2971, 1991, +3581, 2987, 2039, +3581, 2955, 2088, +3549, 2987, 2184, +3565, 2987, 2264, +3613, 2971, 2329, +3645, 2971, 2361, +3645, 2987, 2505, +3581, 3019, 2730, +3533, 3035, 2810, +3404, 3067, 2875, +3404, 3051, 2923, +3404, 3067, 2971, +3437, 3083, 3083, +3581, 3164, 2056, +3565, 3148, 2072, +3565, 3164, 2120, +3581, 3131, 2136, +3549, 3148, 2216, +3581, 3148, 2248, +3581, 3164, 2329, +3597, 3164, 2377, +3597, 3180, 2457, +3613, 3164, 2521, +3645, 3164, 2602, +3661, 3164, 2698, +3645, 3180, 2858, +3597, 3228, 3003, +3549, 3260, 3051, +3549, 3260, 3115, +3565, 3276, 3196, +3710, 3356, 2248, +3694, 3340, 2280, +3694, 3340, 2280, +3694, 3372, 2361, +3710, 3372, 2393, +3694, 3372, 2425, +3677, 3372, 2489, +3694, 3356, 2537, +3694, 3372, 2618, +3694, 3388, 2682, +3694, 3372, 2794, +3742, 3388, 2826, +3758, 3388, 2907, +3790, 3372, 3003, +3710, 3404, 3196, +3677, 3437, 3244, +3710, 3437, 3308, +3854, 3533, 2409, +3854, 3533, 2409, +3806, 3517, 2393, +3854, 3533, 2473, +3806, 3549, 2505, +3822, 3533, 2537, +3822, 3549, 2602, +3806, 3533, 2666, +3822, 3533, 2730, +3790, 3533, 2810, +3806, 3549, 2858, +3790, 3549, 2955, +3790, 3581, 3051, +3806, 3581, 3148, +3822, 3581, 3212, +3822, 3597, 3324, +3806, 3597, 3388, +3983, 3758, 2553, +3983, 3774, 2602, +3950, 3758, 2618, +3967, 3774, 2634, +3967, 3774, 2698, +3950, 3774, 2762, +3934, 3758, 2746, +3950, 3758, 2891, +3934, 3758, 2955, +3918, 3774, 3019, +3950, 3774, 3131, +3934, 3790, 3196, +3950, 3806, 3340, +3934, 3790, 3404, +3950, 3854, 3613, +3918, 3854, 3661, +3902, 3870, 3806] + } +} \ No newline at end of file diff --git a/Gems/Atom/Feature/Common/Assets/ColorGrading/TestData/Photoshop/inv-Log2-48nits/test_clt_32_LUT.azasset b/Gems/Atom/Feature/Common/Assets/ColorGrading/TestData/Photoshop/inv-Log2-48nits/test_clt_32_LUT.azasset new file mode 100644 index 0000000000..92f5a49363 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/ColorGrading/TestData/Photoshop/inv-Log2-48nits/test_clt_32_LUT.azasset @@ -0,0 +1,32777 @@ +{ + "Type": "JsonSerialization", + "Version": 1, + "ClassName": "LookupTableAsset", + "ClassData": { + "Name": "LookupTable", + "Intervals": [0, 33, 66, 99, 132, 165, 198, 231, 264, 297, 330, 363, 396, 429, 462, 495, 528, 561, 594, 627, 660, 693, 726, 759, 792, 825, 858, 891, 924, 957, 990, 1023], + "Values": [0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 28, +0, 0, 152, +0, 0, 280, +0, 0, 408, +0, 0, 537, +0, 0, 667, +0, 0, 797, +0, 0, 928, +0, 0, 1084, +0, 0, 1291, +0, 0, 1472, +0, 0, 1634, +361, 0, 1771, +1145, 0, 1881, +1561, 0, 2006, +1561, 0, 2154, +432, 987, 2341, +1228, 621, 2470, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 54, +0, 0, 173, +0, 0, 295, +0, 0, 419, +0, 0, 545, +0, 0, 673, +0, 0, 802, +0, 0, 932, +0, 0, 1087, +0, 0, 1293, +0, 0, 1473, +0, 0, 1635, +370, 0, 1772, +1144, 0, 1882, +1559, 0, 2006, +1558, 0, 2154, +428, 992, 2341, +1232, 621, 2470, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 87, +0, 0, 198, +0, 0, 315, +0, 0, 434, +0, 0, 557, +0, 0, 682, +0, 0, 809, +0, 0, 937, +0, 0, 1091, +0, 0, 1295, +0, 0, 1474, +0, 0, 1635, +381, 0, 1773, +1143, 0, 1883, +1556, 0, 2007, +1554, 0, 2155, +423, 998, 2341, +1238, 621, 2470, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 31, +0, 0, 127, +0, 0, 230, +0, 0, 340, +0, 0, 454, +0, 0, 572, +0, 0, 693, +0, 0, 817, +0, 0, 943, +0, 0, 1095, +0, 0, 1298, +0, 0, 1476, +0, 0, 1636, +395, 0, 1774, +1142, 0, 1883, +1552, 0, 2008, +1548, 0, 2156, +416, 1005, 2342, +1246, 621, 2470, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 31, +0, 0, 176, +0, 0, 270, +0, 0, 371, +0, 0, 478, +0, 0, 591, +0, 0, 708, +0, 0, 828, +0, 0, 952, +0, 0, 1101, +0, 0, 1302, +0, 0, 1479, +0, 0, 1637, +414, 0, 1775, +1140, 0, 1884, +1547, 0, 2010, +1540, 58, 2158, +407, 1015, 2342, +1257, 621, 2470, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 31, +0, 7, 176, +0, 63, 318, +0, 63, 410, +0, 63, 509, +0, 63, 615, +0, 63, 727, +0, 63, 843, +0, 63, 963, +0, 103, 1109, +0, 30, 1307, +0, 30, 1482, +0, 3, 1639, +438, 0, 1777, +1137, 0, 1886, +1539, 0, 2011, +1530, 197, 2160, +394, 1028, 2343, +1270, 621, 2470, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +0, 4, 0, +0, 23, 0, +0, 47, 0, +0, 77, 31, +0, 114, 176, +0, 159, 318, +0, 214, 457, +0, 214, 548, +0, 214, 646, +0, 214, 751, +0, 214, 862, +0, 214, 977, +0, 243, 1120, +0, 163, 1314, +0, 163, 1487, +0, 142, 1641, +468, 0, 1779, +1134, 0, 1888, +1530, 32, 2014, +1515, 333, 2163, +376, 1045, 2344, +1287, 621, 2470, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +0, 144, 0, +0, 157, 0, +0, 175, 0, +0, 198, 31, +0, 227, 176, +0, 262, 318, +0, 306, 457, +0, 359, 595, +0, 359, 684, +0, 359, 782, +0, 359, 886, +0, 359, 996, +0, 380, 1134, +0, 295, 1323, +0, 295, 1494, +0, 280, 1644, +506, 122, 1783, +1129, 0, 1891, +1516, 164, 2017, +1495, 469, 2167, +352, 1066, 2345, +1309, 621, 2470, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +0, 281, 0, +0, 291, 0, +0, 304, 0, +0, 322, 31, +0, 344, 176, +0, 371, 318, +0, 406, 457, +0, 449, 595, +0, 501, 730, +0, 501, 819, +0, 501, 916, +0, 501, 1020, +0, 516, 1151, +0, 426, 1335, +0, 426, 1502, +0, 415, 1648, +552, 265, 1787, +1123, 111, 1894, +1498, 296, 2021, +1467, 603, 2172, +317, 1093, 2347, +1348, 639, 2470, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +0, 417, 0, +0, 424, 0, +0, 434, 0, +0, 447, 31, +0, 464, 176, +0, 486, 318, +0, 513, 457, +0, 547, 595, +0, 589, 730, +0, 640, 865, +0, 640, 954, +0, 640, 1050, +0, 651, 1174, +0, 570, 1350, +0, 559, 1512, +0, 550, 1653, +556, 441, 1791, +1115, 244, 1898, +1471, 428, 2027, +1426, 737, 2178, +265, 1128, 2349, +1396, 662, 2470, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +0, 552, 0, +0, 557, 0, +0, 565, 0, +0, 575, 31, +0, 587, 176, +0, 604, 318, +0, 625, 457, +0, 652, 595, +0, 686, 730, +0, 727, 865, +0, 777, 1000, +0, 777, 1088, +0, 786, 1203, +0, 726, 1370, +0, 691, 1526, +0, 685, 1662, +556, 606, 1796, +1132, 422, 1904, +1434, 560, 2035, +1365, 871, 2187, +186, 1169, 2352, +1454, 691, 2470, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +0, 686, 0, +0, 690, 0, +0, 696, 0, +0, 703, 31, +0, 713, 176, +0, 726, 318, +0, 742, 457, +0, 763, 595, +0, 789, 730, +0, 823, 865, +0, 864, 1000, +0, 913, 1133, +0, 920, 1239, +0, 876, 1395, +0, 823, 1544, +0, 818, 1675, +556, 761, 1803, +1160, 593, 1912, +1378, 692, 2045, +1267, 1004, 2199, +0, 1212, 2357, +1520, 728, 2470, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +0, 857, 100, +0, 857, 131, +0, 861, 202, +0, 866, 282, +0, 873, 371, +0, 882, 468, +0, 894, 573, +0, 909, 683, +0, 928, 797, +0, 953, 916, +0, 984, 1038, +0, 1023, 1162, +0, 1061, 1287, +0, 1030, 1430, +0, 984, 1569, +0, 971, 1697, +566, 941, 1817, +1178, 799, 1926, +1302, 849, 2057, +1119, 1137, 2212, +0, 1255, 2365, +1585, 801, 2470, +1738, 957, 2513, +1738, 957, 2513, +1738, 957, 2513, +1738, 957, 2513, +1738, 957, 2513, +1738, 957, 2513, +1738, 957, 2513, +1738, 957, 2513, +1738, 957, 2513, +1738, 957, 2513, +0, 1184, 1027, +0, 1184, 1031, +0, 1184, 1036, +0, 1184, 1043, +0, 1184, 1052, +0, 1184, 1064, +0, 1184, 1080, +0, 1184, 1099, +0, 1184, 1125, +0, 1190, 1168, +0, 1209, 1242, +0, 1232, 1325, +0, 1257, 1416, +0, 1237, 1493, +0, 1209, 1617, +0, 1222, 1740, +636, 1187, 1854, +1040, 1131, 1961, +1243, 1131, 2080, +1031, 1271, 2224, +472, 1312, 2372, +1588, 1032, 2472, +1765, 1144, 2512, +1765, 1144, 2512, +1765, 1144, 2512, +1765, 1144, 2512, +1765, 1144, 2512, +1765, 1144, 2512, +1765, 1144, 2512, +1765, 1144, 2512, +1765, 1144, 2512, +1765, 1144, 2512, +0, 1421, 1377, +0, 1421, 1379, +0, 1421, 1382, +0, 1421, 1385, +0, 1421, 1389, +0, 1421, 1395, +0, 1421, 1402, +0, 1421, 1412, +0, 1421, 1425, +0, 1421, 1442, +0, 1421, 1463, +0, 1421, 1491, +0, 1432, 1546, +0, 1418, 1604, +0, 1399, 1673, +0, 1412, 1786, +636, 1404, 1895, +1048, 1353, 1999, +1151, 1350, 2110, +878, 1405, 2240, +666, 1388, 2378, +1601, 1209, 2473, +1799, 1314, 2510, +1799, 1314, 2510, +1799, 1314, 2510, +1799, 1314, 2510, +1799, 1314, 2510, +1799, 1314, 2510, +1799, 1314, 2510, +1799, 1314, 2510, +1799, 1314, 2510, +1799, 1314, 2510, +901, 1580, 1648, +901, 1579, 1649, +901, 1579, 1650, +901, 1579, 1652, +901, 1578, 1655, +901, 1577, 1658, +901, 1576, 1662, +901, 1574, 1668, +901, 1572, 1675, +901, 1569, 1685, +901, 1567, 1698, +901, 1567, 1714, +886, 1567, 1736, +886, 1577, 1788, +886, 1569, 1838, +890, 1552, 1888, +807, 1557, 1969, +921, 1536, 2067, +942, 1537, 2170, +810, 1524, 2268, +1125, 1501, 2382, +1680, 1435, 2473, +1845, 1472, 2509, +1845, 1472, 2509, +1845, 1472, 2509, +1845, 1472, 2509, +1845, 1472, 2509, +1845, 1472, 2509, +1845, 1472, 2509, +1845, 1472, 2509, +1845, 1472, 2509, +1845, 1472, 2509, +1449, 1705, 1856, +1448, 1705, 1856, +1447, 1705, 1857, +1446, 1705, 1859, +1444, 1705, 1860, +1441, 1705, 1862, +1438, 1705, 1865, +1433, 1705, 1868, +1427, 1705, 1873, +1426, 1703, 1880, +1426, 1700, 1888, +1426, 1696, 1899, +1423, 1691, 1913, +1400, 1685, 1931, +1400, 1696, 1976, +1370, 1702, 2022, +1371, 1685, 2062, +1192, 1672, 2128, +1127, 1678, 2221, +1173, 1647, 2295, +1519, 1631, 2386, +1775, 1634, 2475, +1894, 1629, 2511, +1894, 1629, 2511, +1894, 1629, 2511, +1894, 1629, 2511, +1894, 1629, 2511, +1894, 1629, 2511, +1894, 1629, 2511, +1894, 1629, 2511, +1894, 1629, 2511, +1894, 1629, 2511, +1785, 1818, 1978, +1786, 1818, 1978, +1786, 1818, 1979, +1786, 1818, 1980, +1786, 1818, 1981, +1787, 1818, 1982, +1788, 1818, 1983, +1789, 1818, 1986, +1790, 1818, 1988, +1792, 1818, 1992, +1788, 1818, 1998, +1781, 1818, 2007, +1772, 1818, 2018, +1752, 1824, 2037, +1733, 1818, 2052, +1727, 1802, 2080, +1685, 1816, 2123, +1705, 1809, 2166, +1657, 1793, 2234, +1664, 1793, 2304, +1754, 1797, 2389, +1874, 1790, 2475, +1964, 1800, 2514, +1964, 1800, 2514, +1964, 1800, 2514, +1964, 1800, 2514, +1964, 1800, 2514, +1964, 1800, 2514, +1964, 1800, 2514, +1964, 1800, 2514, +1964, 1800, 2514, +1964, 1800, 2514, +1958, 1958, 2028, +1957, 1958, 2029, +1957, 1958, 2029, +1957, 1958, 2030, +1956, 1958, 2031, +1956, 1958, 2031, +1956, 1958, 2033, +1955, 1958, 2035, +1954, 1958, 2037, +1953, 1958, 2041, +1951, 1958, 2045, +1948, 1958, 2051, +1946, 1958, 2058, +1941, 1962, 2068, +1935, 1968, 2081, +1927, 1969, 2115, +1913, 1965, 2153, +1905, 1963, 2189, +1920, 1969, 2243, +1881, 1969, 2320, +1929, 1954, 2391, +2032, 1964, 2481, +2093, 1969, 2517, +2093, 1969, 2517, +2093, 1969, 2517, +2093, 1969, 2517, +2093, 1969, 2517, +2093, 1969, 2517, +2093, 1969, 2517, +2093, 1969, 2517, +2093, 1969, 2517, +2093, 1969, 2517, +2119, 2119, 2068, +2119, 2119, 2068, +2119, 2119, 2068, +2119, 2120, 2069, +2119, 2120, 2069, +2119, 2120, 2071, +2119, 2120, 2072, +2119, 2121, 2073, +2119, 2122, 2076, +2119, 2122, 2079, +2119, 2124, 2083, +2119, 2125, 2088, +2119, 2127, 2095, +2119, 2127, 2101, +2119, 2127, 2110, +2115, 2131, 2133, +2108, 2133, 2164, +2103, 2131, 2206, +2110, 2135, 2256, +2119, 2135, 2316, +2148, 2131, 2395, +2212, 2147, 2485, +2261, 2159, 2524, +2261, 2159, 2524, +2261, 2159, 2524, +2261, 2159, 2524, +2261, 2159, 2524, +2261, 2159, 2524, +2261, 2159, 2524, +2261, 2159, 2524, +2261, 2159, 2524, +2261, 2159, 2524, +2370, 2355, 2124, +2370, 2355, 2124, +2370, 2355, 2124, +2370, 2355, 2125, +2369, 2356, 2125, +2369, 2356, 2126, +2369, 2356, 2126, +2369, 2356, 2127, +2369, 2357, 2129, +2368, 2357, 2131, +2367, 2358, 2133, +2368, 2359, 2137, +2369, 2360, 2143, +2370, 2358, 2146, +2369, 2356, 2148, +2368, 2358, 2163, +2370, 2358, 2193, +2369, 2358, 2226, +2372, 2355, 2273, +2383, 2356, 2337, +2410, 2367, 2405, +2467, 2385, 2498, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2681, 2655, 1963, +2681, 2655, 1963, +2681, 2655, 1963, +2681, 2655, 1963, +2681, 2654, 1964, +2681, 2654, 1965, +2681, 2654, 1966, +2681, 2654, 1968, +2681, 2654, 1967, +2681, 2654, 1965, +2680, 2653, 1964, +2680, 2653, 1961, +2679, 2652, 1961, +2678, 2653, 1968, +2677, 2654, 1989, +2676, 2653, 2013, +2675, 2649, 2032, +2677, 2655, 2124, +2681, 2656, 2208, +2687, 2661, 2306, +2695, 2667, 2410, +2715, 2678, 2527, +2722, 2684, 2575, +2722, 2684, 2575, +2722, 2684, 2575, +2722, 2684, 2575, +2722, 2684, 2575, +2722, 2684, 2575, +2722, 2684, 2575, +2722, 2684, 2575, +2722, 2684, 2575, +2722, 2684, 2575, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2771, 2455, +2709, 2773, 2484, +2714, 2773, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2771, 2455, +2709, 2773, 2484, +2714, 2773, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2771, 2455, +2709, 2773, 2484, +2714, 2773, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2771, 2455, +2709, 2773, 2484, +2714, 2773, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2771, 2455, +2709, 2773, 2484, +2714, 2773, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2771, 2455, +2709, 2773, 2484, +2714, 2773, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2771, 2455, +2709, 2773, 2484, +2714, 2773, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2771, 2455, +2709, 2773, 2484, +2714, 2773, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2771, 2455, +2709, 2773, 2484, +2714, 2773, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2771, 2455, +2709, 2773, 2484, +2714, 2773, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 28, +0, 0, 152, +0, 0, 280, +0, 0, 408, +0, 0, 537, +0, 0, 667, +0, 0, 797, +0, 0, 928, +0, 0, 1088, +0, 0, 1293, +0, 0, 1473, +0, 0, 1634, +398, 0, 1772, +1148, 0, 1882, +1561, 0, 2006, +1560, 0, 2154, +428, 987, 2341, +1231, 619, 2470, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 36, +0, 0, 159, +0, 0, 285, +0, 0, 412, +0, 0, 540, +0, 0, 669, +0, 0, 799, +0, 0, 930, +0, 0, 1089, +0, 0, 1294, +0, 0, 1474, +0, 0, 1635, +378, 0, 1771, +1147, 0, 1882, +1561, 0, 2006, +1559, 0, 2154, +428, 992, 2341, +1235, 621, 2470, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 71, +0, 0, 186, +0, 0, 305, +0, 0, 427, +0, 0, 551, +0, 0, 678, +0, 0, 805, +0, 0, 935, +0, 0, 1092, +0, 0, 1296, +0, 0, 1475, +0, 0, 1635, +389, 0, 1772, +1146, 0, 1883, +1558, 0, 2007, +1555, 0, 2155, +423, 998, 2341, +1241, 621, 2470, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 13, +0, 0, 112, +0, 0, 219, +0, 0, 330, +0, 0, 446, +0, 0, 566, +0, 0, 689, +0, 0, 814, +0, 0, 941, +0, 0, 1097, +0, 0, 1299, +0, 0, 1477, +0, 0, 1636, +403, 0, 1773, +1145, 0, 1884, +1554, 0, 2008, +1549, 0, 2156, +416, 1005, 2342, +1249, 621, 2470, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 13, +0, 0, 163, +0, 0, 259, +0, 0, 363, +0, 0, 472, +0, 0, 586, +0, 0, 704, +0, 0, 825, +0, 0, 949, +0, 0, 1103, +0, 0, 1303, +0, 0, 1480, +0, 0, 1637, +422, 0, 1775, +1143, 0, 1884, +1548, 0, 2010, +1541, 50, 2158, +407, 1015, 2342, +1259, 621, 2470, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 13, +0, 0, 163, +0, 38, 309, +0, 38, 402, +0, 38, 503, +0, 38, 610, +0, 38, 723, +0, 38, 840, +0, 38, 961, +0, 102, 1111, +0, 30, 1308, +0, 30, 1483, +0, 0, 1639, +445, 0, 1776, +1140, 0, 1886, +1541, 0, 2011, +1531, 190, 2160, +394, 1028, 2343, +1272, 621, 2470, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +0, 4, 0, +0, 0, 0, +0, 20, 0, +0, 52, 13, +0, 91, 163, +0, 139, 309, +0, 195, 450, +0, 195, 542, +0, 195, 641, +0, 195, 748, +0, 195, 859, +0, 195, 975, +0, 242, 1121, +0, 163, 1315, +0, 163, 1488, +0, 135, 1641, +475, 0, 1779, +1137, 0, 1888, +1532, 32, 2014, +1516, 329, 2163, +376, 1045, 2344, +1289, 621, 2470, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +0, 144, 0, +0, 137, 0, +0, 155, 0, +0, 179, 13, +0, 209, 163, +0, 246, 309, +0, 291, 450, +0, 346, 589, +0, 346, 680, +0, 346, 778, +0, 346, 883, +0, 346, 994, +0, 380, 1135, +0, 295, 1324, +0, 295, 1494, +0, 274, 1644, +512, 108, 1782, +1133, 0, 1891, +1518, 164, 2017, +1496, 465, 2167, +352, 1066, 2345, +1311, 621, 2470, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +0, 281, 0, +0, 276, 0, +0, 289, 0, +0, 307, 13, +0, 330, 163, +0, 359, 309, +0, 394, 450, +0, 438, 589, +0, 491, 727, +0, 491, 816, +0, 491, 914, +0, 491, 1018, +0, 516, 1153, +0, 426, 1336, +0, 426, 1502, +0, 412, 1648, +557, 254, 1787, +1126, 111, 1894, +1500, 296, 2021, +1468, 601, 2172, +317, 1093, 2347, +1350, 639, 2470, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +0, 417, 0, +0, 413, 0, +0, 423, 0, +0, 437, 13, +0, 454, 163, +0, 476, 309, +0, 504, 450, +0, 539, 589, +0, 581, 727, +0, 633, 862, +0, 633, 952, +0, 633, 1049, +0, 651, 1176, +0, 570, 1351, +0, 559, 1513, +0, 547, 1653, +561, 434, 1790, +1118, 244, 1898, +1474, 428, 2027, +1427, 736, 2178, +265, 1128, 2349, +1398, 662, 2470, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +0, 552, 0, +0, 549, 0, +0, 557, 0, +0, 566, 13, +0, 579, 163, +0, 596, 309, +0, 618, 450, +0, 645, 589, +0, 679, 727, +0, 721, 862, +0, 772, 997, +0, 772, 1086, +0, 785, 1204, +0, 726, 1371, +0, 691, 1527, +0, 682, 1662, +561, 601, 1796, +1135, 422, 1904, +1436, 560, 2035, +1366, 869, 2187, +186, 1169, 2352, +1455, 691, 2470, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +0, 686, 0, +0, 684, 0, +0, 690, 0, +0, 697, 13, +0, 707, 163, +0, 720, 309, +0, 736, 450, +0, 758, 589, +0, 784, 727, +0, 818, 862, +0, 859, 997, +0, 909, 1132, +0, 919, 1240, +0, 876, 1396, +0, 823, 1545, +0, 817, 1675, +561, 758, 1802, +1163, 593, 1912, +1381, 692, 2045, +1269, 1003, 2199, +0, 1212, 2357, +1522, 728, 2470, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +0, 854, 85, +0, 854, 130, +0, 858, 201, +0, 863, 282, +0, 870, 371, +0, 879, 468, +0, 891, 572, +0, 906, 682, +0, 925, 797, +0, 950, 916, +0, 981, 1038, +0, 1020, 1162, +0, 1060, 1288, +0, 1029, 1430, +0, 983, 1570, +0, 969, 1697, +572, 942, 1817, +1182, 800, 1926, +1302, 849, 2057, +1120, 1137, 2212, +0, 1254, 2365, +1585, 800, 2470, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +0, 1183, 1025, +0, 1183, 1031, +0, 1183, 1036, +0, 1183, 1043, +0, 1183, 1052, +0, 1183, 1064, +0, 1183, 1080, +0, 1183, 1099, +0, 1183, 1125, +0, 1188, 1168, +0, 1207, 1242, +0, 1231, 1325, +0, 1257, 1417, +0, 1236, 1493, +0, 1208, 1617, +0, 1221, 1741, +640, 1187, 1855, +1045, 1132, 1961, +1243, 1131, 2080, +1031, 1271, 2225, +498, 1311, 2371, +1589, 1031, 2471, +1765, 1143, 2512, +1765, 1143, 2512, +1765, 1143, 2512, +1765, 1143, 2512, +1765, 1143, 2512, +1765, 1143, 2512, +1765, 1143, 2512, +1765, 1143, 2512, +1765, 1143, 2512, +1765, 1143, 2512, +0, 1421, 1376, +0, 1421, 1379, +0, 1421, 1382, +0, 1421, 1385, +0, 1421, 1389, +0, 1421, 1395, +0, 1421, 1402, +0, 1421, 1412, +0, 1421, 1425, +0, 1421, 1442, +0, 1421, 1463, +0, 1421, 1491, +0, 1431, 1546, +0, 1417, 1605, +0, 1399, 1673, +0, 1411, 1786, +640, 1405, 1896, +1052, 1353, 1999, +1151, 1350, 2110, +878, 1405, 2240, +684, 1387, 2378, +1602, 1208, 2473, +1799, 1313, 2510, +1799, 1313, 2510, +1799, 1313, 2510, +1799, 1313, 2510, +1799, 1313, 2510, +1799, 1313, 2510, +1799, 1313, 2510, +1799, 1313, 2510, +1799, 1313, 2510, +1799, 1313, 2510, +913, 1579, 1648, +912, 1579, 1649, +912, 1579, 1651, +912, 1579, 1653, +912, 1578, 1655, +912, 1577, 1658, +912, 1576, 1662, +912, 1574, 1668, +912, 1572, 1675, +912, 1569, 1685, +912, 1567, 1698, +912, 1567, 1714, +892, 1567, 1736, +891, 1577, 1788, +891, 1569, 1838, +896, 1552, 1889, +818, 1557, 1970, +929, 1536, 2067, +946, 1537, 2170, +810, 1524, 2268, +1128, 1500, 2382, +1680, 1435, 2473, +1845, 1471, 2509, +1845, 1471, 2509, +1845, 1471, 2509, +1845, 1471, 2509, +1845, 1471, 2509, +1845, 1471, 2509, +1845, 1471, 2509, +1845, 1471, 2509, +1845, 1471, 2509, +1845, 1471, 2509, +1450, 1705, 1856, +1449, 1705, 1856, +1448, 1705, 1857, +1446, 1705, 1859, +1444, 1705, 1860, +1442, 1705, 1862, +1439, 1705, 1865, +1434, 1705, 1868, +1427, 1705, 1873, +1427, 1703, 1880, +1427, 1700, 1888, +1427, 1696, 1899, +1424, 1691, 1913, +1401, 1685, 1931, +1401, 1696, 1976, +1370, 1701, 2022, +1372, 1685, 2062, +1195, 1672, 2128, +1129, 1678, 2221, +1176, 1647, 2295, +1520, 1631, 2386, +1776, 1634, 2475, +1894, 1629, 2511, +1894, 1629, 2511, +1894, 1629, 2511, +1894, 1629, 2511, +1894, 1629, 2511, +1894, 1629, 2511, +1894, 1629, 2511, +1894, 1629, 2511, +1894, 1629, 2511, +1894, 1629, 2511, +1786, 1817, 1978, +1786, 1817, 1978, +1786, 1817, 1979, +1786, 1817, 1980, +1787, 1817, 1981, +1787, 1817, 1982, +1788, 1817, 1983, +1789, 1817, 1986, +1790, 1817, 1988, +1793, 1817, 1992, +1789, 1817, 1998, +1782, 1817, 2007, +1772, 1818, 2018, +1753, 1824, 2036, +1733, 1818, 2052, +1727, 1803, 2080, +1686, 1816, 2123, +1706, 1808, 2166, +1658, 1793, 2234, +1664, 1793, 2304, +1754, 1797, 2389, +1874, 1790, 2475, +1964, 1800, 2514, +1964, 1800, 2514, +1964, 1800, 2514, +1964, 1800, 2514, +1964, 1800, 2514, +1964, 1800, 2514, +1964, 1800, 2514, +1964, 1800, 2514, +1964, 1800, 2514, +1964, 1800, 2514, +1958, 1958, 2028, +1958, 1958, 2029, +1957, 1958, 2029, +1957, 1958, 2030, +1957, 1958, 2031, +1956, 1958, 2031, +1956, 1958, 2033, +1955, 1958, 2035, +1954, 1958, 2037, +1953, 1958, 2041, +1951, 1958, 2045, +1948, 1958, 2051, +1946, 1958, 2058, +1941, 1962, 2068, +1936, 1968, 2081, +1927, 1969, 2115, +1913, 1965, 2153, +1905, 1963, 2189, +1920, 1969, 2243, +1881, 1968, 2320, +1929, 1954, 2392, +2033, 1964, 2481, +2094, 1969, 2517, +2094, 1969, 2517, +2094, 1969, 2517, +2094, 1969, 2517, +2094, 1969, 2517, +2094, 1969, 2517, +2094, 1969, 2517, +2094, 1969, 2517, +2094, 1969, 2517, +2094, 1969, 2517, +2120, 2119, 2068, +2120, 2119, 2068, +2120, 2119, 2068, +2120, 2120, 2069, +2120, 2120, 2069, +2120, 2120, 2070, +2120, 2120, 2072, +2120, 2121, 2073, +2120, 2122, 2076, +2120, 2122, 2079, +2120, 2124, 2083, +2120, 2125, 2088, +2119, 2127, 2095, +2119, 2127, 2101, +2119, 2127, 2110, +2115, 2131, 2133, +2109, 2133, 2164, +2103, 2131, 2206, +2111, 2135, 2256, +2119, 2135, 2316, +2148, 2131, 2395, +2212, 2147, 2485, +2261, 2159, 2524, +2261, 2159, 2524, +2261, 2159, 2524, +2261, 2159, 2524, +2261, 2159, 2524, +2261, 2159, 2524, +2261, 2159, 2524, +2261, 2159, 2524, +2261, 2159, 2524, +2261, 2159, 2524, +2370, 2355, 2124, +2370, 2355, 2124, +2370, 2355, 2124, +2370, 2355, 2125, +2370, 2356, 2125, +2369, 2356, 2126, +2369, 2356, 2126, +2369, 2356, 2127, +2369, 2357, 2129, +2368, 2357, 2131, +2367, 2358, 2133, +2368, 2359, 2137, +2369, 2360, 2143, +2370, 2358, 2146, +2369, 2356, 2148, +2368, 2358, 2163, +2370, 2358, 2193, +2369, 2358, 2226, +2372, 2355, 2273, +2383, 2356, 2337, +2410, 2367, 2405, +2467, 2385, 2498, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2681, 2655, 1963, +2681, 2655, 1963, +2681, 2655, 1963, +2681, 2655, 1964, +2681, 2655, 1965, +2681, 2654, 1965, +2681, 2654, 1966, +2681, 2654, 1968, +2681, 2654, 1967, +2681, 2654, 1966, +2680, 2653, 1964, +2680, 2653, 1962, +2679, 2652, 1962, +2678, 2653, 1969, +2677, 2654, 1990, +2676, 2653, 2014, +2675, 2650, 2033, +2677, 2655, 2124, +2681, 2656, 2208, +2687, 2661, 2306, +2695, 2667, 2410, +2715, 2678, 2527, +2722, 2684, 2575, +2722, 2684, 2575, +2722, 2684, 2575, +2722, 2684, 2575, +2722, 2684, 2575, +2722, 2684, 2575, +2722, 2684, 2575, +2722, 2684, 2575, +2722, 2684, 2575, +2722, 2684, 2575, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2771, 2455, +2709, 2773, 2484, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2771, 2455, +2709, 2773, 2484, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2771, 2455, +2709, 2773, 2484, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2771, 2455, +2709, 2773, 2484, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2771, 2455, +2709, 2773, 2484, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2771, 2455, +2709, 2773, 2484, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2771, 2455, +2709, 2773, 2484, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2771, 2455, +2709, 2773, 2484, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2771, 2455, +2709, 2773, 2484, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2771, 2455, +2709, 2773, 2484, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 28, +0, 0, 152, +0, 0, 280, +0, 0, 408, +0, 0, 537, +0, 0, 667, +0, 0, 797, +0, 0, 928, +0, 0, 1088, +0, 0, 1296, +0, 0, 1475, +0, 0, 1634, +445, 0, 1772, +1152, 0, 1882, +1561, 0, 2006, +1559, 0, 2155, +423, 987, 2341, +1234, 615, 2470, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 36, +0, 0, 159, +0, 0, 285, +0, 0, 412, +0, 0, 540, +0, 0, 669, +0, 0, 799, +0, 0, 930, +0, 0, 1089, +0, 0, 1297, +0, 0, 1475, +0, 0, 1635, +426, 0, 1772, +1151, 0, 1882, +1561, 0, 2007, +1558, 0, 2155, +423, 992, 2341, +1238, 618, 2470, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 48, +0, 0, 168, +0, 0, 291, +0, 0, 417, +0, 0, 544, +0, 0, 672, +0, 0, 801, +0, 0, 931, +0, 0, 1090, +0, 0, 1298, +0, 0, 1476, +0, 0, 1635, +400, 0, 1772, +1150, 0, 1883, +1560, 0, 2007, +1556, 0, 2155, +423, 998, 2341, +1244, 621, 2470, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 92, +0, 0, 203, +0, 0, 318, +0, 0, 437, +0, 0, 559, +0, 0, 683, +0, 0, 810, +0, 0, 938, +0, 0, 1094, +0, 0, 1300, +0, 0, 1478, +0, 0, 1636, +414, 0, 1773, +1149, 0, 1884, +1556, 0, 2008, +1550, 0, 2156, +416, 1005, 2342, +1252, 621, 2470, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 145, +0, 0, 245, +0, 0, 351, +0, 0, 462, +0, 0, 579, +0, 0, 699, +0, 0, 821, +0, 0, 946, +0, 0, 1101, +0, 0, 1304, +0, 0, 1481, +0, 0, 1637, +432, 0, 1774, +1147, 0, 1885, +1551, 0, 2010, +1543, 38, 2158, +407, 1015, 2342, +1262, 621, 2470, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 145, +0, 1, 295, +0, 1, 391, +0, 1, 494, +0, 1, 604, +0, 1, 718, +0, 1, 836, +0, 1, 958, +0, 70, 1109, +0, 30, 1310, +0, 30, 1484, +0, 0, 1639, +455, 0, 1776, +1144, 0, 1886, +1544, 0, 2012, +1532, 182, 2160, +394, 1028, 2343, +1275, 621, 2470, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +0, 4, 0, +0, 0, 0, +0, 0, 0, +0, 16, 0, +0, 58, 145, +0, 109, 295, +0, 170, 441, +0, 170, 534, +0, 170, 635, +0, 170, 742, +0, 170, 855, +0, 170, 973, +0, 218, 1119, +0, 163, 1316, +0, 163, 1489, +0, 126, 1641, +484, 0, 1778, +1141, 0, 1888, +1534, 32, 2014, +1518, 322, 2163, +376, 1045, 2344, +1292, 621, 2470, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +0, 144, 0, +0, 137, 0, +0, 127, 0, +0, 152, 0, +0, 184, 145, +0, 223, 295, +0, 271, 441, +0, 327, 582, +0, 327, 674, +0, 327, 773, +0, 327, 879, +0, 327, 991, +0, 363, 1133, +0, 295, 1325, +0, 295, 1495, +0, 267, 1644, +520, 87, 1782, +1137, 0, 1891, +1521, 164, 2017, +1498, 461, 2167, +352, 1066, 2345, +1314, 621, 2470, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +0, 281, 0, +0, 276, 0, +0, 269, 0, +0, 287, 0, +0, 311, 145, +0, 341, 295, +0, 378, 441, +0, 423, 582, +0, 478, 721, +0, 478, 812, +0, 478, 910, +0, 478, 1016, +0, 503, 1151, +0, 426, 1337, +0, 426, 1503, +0, 406, 1648, +565, 239, 1786, +1131, 111, 1894, +1503, 296, 2022, +1470, 597, 2172, +317, 1093, 2347, +1353, 639, 2470, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +0, 417, 0, +0, 413, 0, +0, 408, 0, +0, 422, 0, +0, 439, 145, +0, 462, 295, +0, 491, 441, +0, 527, 582, +0, 570, 721, +0, 623, 859, +0, 623, 948, +0, 623, 1046, +0, 642, 1174, +0, 570, 1352, +0, 559, 1514, +0, 544, 1653, +569, 424, 1790, +1123, 244, 1899, +1477, 428, 2027, +1429, 733, 2178, +265, 1128, 2349, +1400, 662, 2470, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +0, 552, 0, +0, 549, 0, +0, 545, 0, +0, 555, 0, +0, 568, 145, +0, 586, 295, +0, 608, 441, +0, 636, 582, +0, 670, 721, +0, 713, 859, +0, 765, 995, +0, 765, 1084, +0, 778, 1202, +0, 726, 1372, +0, 691, 1528, +0, 680, 1662, +569, 594, 1795, +1139, 422, 1905, +1440, 560, 2035, +1368, 868, 2187, +186, 1169, 2352, +1457, 691, 2470, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +0, 686, 0, +0, 684, 0, +0, 681, 0, +0, 689, 0, +0, 699, 145, +0, 712, 295, +0, 729, 441, +0, 750, 582, +0, 777, 721, +0, 811, 859, +0, 854, 995, +0, 904, 1130, +0, 914, 1238, +0, 876, 1397, +0, 823, 1546, +0, 815, 1675, +569, 753, 1802, +1167, 593, 1913, +1385, 692, 2045, +1272, 1002, 2199, +0, 1212, 2357, +1524, 728, 2470, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +0, 854, 85, +0, 854, 130, +0, 852, 185, +0, 857, 268, +0, 864, 360, +0, 873, 459, +0, 885, 565, +0, 901, 676, +0, 920, 793, +0, 946, 912, +0, 977, 1035, +0, 1016, 1160, +0, 1056, 1287, +0, 1029, 1432, +0, 983, 1571, +0, 967, 1697, +579, 939, 1816, +1186, 800, 1926, +1306, 849, 2057, +1123, 1137, 2212, +0, 1254, 2365, +1587, 800, 2470, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +0, 1181, 1022, +0, 1181, 1028, +0, 1181, 1036, +0, 1181, 1043, +0, 1181, 1052, +0, 1181, 1064, +0, 1181, 1080, +0, 1181, 1099, +0, 1181, 1125, +0, 1186, 1168, +0, 1205, 1242, +0, 1229, 1325, +0, 1255, 1417, +0, 1235, 1494, +0, 1207, 1618, +0, 1219, 1741, +647, 1188, 1855, +1051, 1133, 1961, +1243, 1131, 2080, +1031, 1271, 2225, +532, 1310, 2371, +1590, 1030, 2471, +1766, 1141, 2512, +1766, 1141, 2512, +1766, 1141, 2512, +1766, 1141, 2512, +1766, 1141, 2512, +1766, 1141, 2512, +1766, 1141, 2512, +1766, 1141, 2512, +1766, 1141, 2512, +1766, 1141, 2512, +0, 1420, 1375, +0, 1420, 1378, +0, 1420, 1382, +0, 1420, 1385, +0, 1420, 1389, +0, 1420, 1395, +0, 1420, 1402, +0, 1420, 1412, +0, 1420, 1425, +0, 1420, 1442, +0, 1420, 1463, +0, 1420, 1491, +0, 1430, 1546, +0, 1417, 1606, +0, 1398, 1674, +0, 1410, 1786, +647, 1405, 1896, +1059, 1354, 2000, +1151, 1350, 2109, +878, 1405, 2240, +706, 1386, 2378, +1603, 1208, 2473, +1800, 1311, 2510, +1800, 1311, 2510, +1800, 1311, 2510, +1800, 1311, 2510, +1800, 1311, 2510, +1800, 1311, 2510, +1800, 1311, 2510, +1800, 1311, 2510, +1800, 1311, 2510, +1800, 1311, 2510, +929, 1579, 1649, +928, 1579, 1650, +926, 1579, 1651, +926, 1579, 1653, +926, 1578, 1655, +926, 1577, 1658, +926, 1576, 1663, +926, 1574, 1668, +926, 1572, 1676, +926, 1569, 1685, +926, 1567, 1698, +926, 1567, 1715, +906, 1567, 1736, +898, 1576, 1787, +898, 1569, 1837, +906, 1552, 1889, +833, 1557, 1970, +939, 1536, 2067, +950, 1537, 2170, +810, 1524, 2268, +1132, 1500, 2382, +1680, 1435, 2473, +1845, 1471, 2509, +1845, 1471, 2509, +1845, 1471, 2509, +1845, 1471, 2509, +1845, 1471, 2509, +1845, 1471, 2509, +1845, 1471, 2509, +1845, 1471, 2509, +1845, 1471, 2509, +1845, 1471, 2509, +1452, 1705, 1855, +1450, 1705, 1856, +1449, 1705, 1857, +1448, 1705, 1859, +1446, 1705, 1860, +1443, 1705, 1862, +1440, 1705, 1865, +1435, 1705, 1868, +1429, 1705, 1873, +1428, 1703, 1880, +1428, 1700, 1888, +1428, 1696, 1899, +1425, 1691, 1913, +1402, 1685, 1931, +1402, 1696, 1977, +1371, 1701, 2021, +1374, 1685, 2062, +1200, 1672, 2128, +1132, 1678, 2221, +1180, 1647, 2295, +1520, 1631, 2386, +1776, 1634, 2475, +1894, 1628, 2511, +1894, 1628, 2511, +1894, 1628, 2511, +1894, 1628, 2511, +1894, 1628, 2511, +1894, 1628, 2511, +1894, 1628, 2511, +1894, 1628, 2511, +1894, 1628, 2511, +1894, 1628, 2511, +1787, 1817, 1978, +1787, 1817, 1978, +1786, 1817, 1979, +1786, 1817, 1980, +1787, 1817, 1981, +1787, 1817, 1982, +1788, 1817, 1983, +1789, 1817, 1986, +1791, 1817, 1988, +1793, 1817, 1992, +1789, 1817, 1998, +1782, 1817, 2007, +1772, 1818, 2018, +1753, 1823, 2036, +1734, 1818, 2052, +1728, 1803, 2080, +1687, 1816, 2123, +1706, 1808, 2166, +1658, 1793, 2234, +1666, 1793, 2304, +1755, 1797, 2389, +1874, 1790, 2475, +1965, 1800, 2514, +1965, 1800, 2514, +1965, 1800, 2514, +1965, 1800, 2514, +1965, 1800, 2514, +1965, 1800, 2514, +1965, 1800, 2514, +1965, 1800, 2514, +1965, 1800, 2514, +1965, 1800, 2514, +1958, 1958, 2029, +1958, 1958, 2029, +1958, 1958, 2029, +1958, 1958, 2030, +1957, 1958, 2031, +1957, 1958, 2032, +1956, 1958, 2033, +1955, 1958, 2035, +1955, 1958, 2037, +1953, 1958, 2041, +1951, 1958, 2045, +1949, 1958, 2051, +1946, 1958, 2058, +1941, 1962, 2068, +1936, 1968, 2081, +1927, 1969, 2114, +1914, 1966, 2153, +1905, 1963, 2189, +1920, 1969, 2243, +1882, 1968, 2320, +1930, 1954, 2392, +2034, 1964, 2481, +2094, 1969, 2517, +2094, 1969, 2517, +2094, 1969, 2517, +2094, 1969, 2517, +2094, 1969, 2517, +2094, 1969, 2517, +2094, 1969, 2517, +2094, 1969, 2517, +2094, 1969, 2517, +2094, 1969, 2517, +2120, 2119, 2068, +2120, 2119, 2068, +2120, 2119, 2068, +2120, 2120, 2069, +2120, 2120, 2069, +2120, 2120, 2070, +2120, 2120, 2071, +2120, 2121, 2073, +2120, 2122, 2076, +2120, 2122, 2079, +2120, 2124, 2083, +2120, 2125, 2088, +2119, 2127, 2095, +2119, 2127, 2101, +2119, 2127, 2110, +2116, 2131, 2132, +2109, 2133, 2164, +2103, 2131, 2206, +2111, 2135, 2256, +2120, 2135, 2316, +2148, 2131, 2395, +2212, 2147, 2485, +2261, 2159, 2524, +2261, 2159, 2524, +2261, 2159, 2524, +2261, 2159, 2524, +2261, 2159, 2524, +2261, 2159, 2524, +2261, 2159, 2524, +2261, 2159, 2524, +2261, 2159, 2524, +2261, 2159, 2524, +2370, 2355, 2124, +2370, 2355, 2124, +2370, 2355, 2124, +2370, 2355, 2125, +2370, 2355, 2125, +2370, 2356, 2126, +2369, 2356, 2126, +2369, 2356, 2127, +2369, 2357, 2129, +2368, 2357, 2131, +2367, 2358, 2133, +2368, 2359, 2137, +2369, 2360, 2143, +2370, 2358, 2146, +2369, 2356, 2148, +2368, 2358, 2163, +2370, 2358, 2193, +2369, 2358, 2226, +2372, 2355, 2273, +2384, 2356, 2337, +2410, 2367, 2405, +2467, 2385, 2498, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2681, 2655, 1963, +2681, 2655, 1963, +2681, 2655, 1964, +2681, 2655, 1965, +2681, 2655, 1965, +2681, 2655, 1966, +2681, 2654, 1967, +2681, 2654, 1969, +2681, 2654, 1968, +2681, 2654, 1966, +2680, 2653, 1965, +2680, 2653, 1962, +2679, 2652, 1963, +2678, 2653, 1970, +2677, 2655, 1992, +2676, 2653, 2015, +2675, 2650, 2035, +2677, 2655, 2124, +2681, 2656, 2208, +2687, 2661, 2306, +2695, 2666, 2409, +2715, 2678, 2527, +2722, 2684, 2575, +2722, 2684, 2575, +2722, 2684, 2575, +2722, 2684, 2575, +2722, 2684, 2575, +2722, 2684, 2575, +2722, 2684, 2575, +2722, 2684, 2575, +2722, 2684, 2575, +2722, 2684, 2575, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2771, 2455, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2771, 2455, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2771, 2455, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2771, 2455, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2771, 2455, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2771, 2455, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2771, 2455, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2771, 2455, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2771, 2455, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2771, 2455, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 28, +0, 0, 152, +0, 0, 280, +0, 0, 408, +0, 0, 537, +0, 0, 667, +0, 0, 797, +0, 0, 928, +0, 0, 1088, +0, 0, 1300, +0, 0, 1478, +0, 0, 1634, +499, 0, 1773, +1157, 0, 1883, +1561, 0, 2007, +1557, 0, 2156, +416, 987, 2341, +1238, 611, 2470, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 36, +0, 0, 159, +0, 0, 285, +0, 0, 412, +0, 0, 540, +0, 0, 669, +0, 0, 799, +0, 0, 930, +0, 0, 1089, +0, 0, 1301, +0, 0, 1478, +0, 0, 1635, +483, 0, 1773, +1157, 0, 1883, +1561, 0, 2007, +1556, 0, 2156, +416, 992, 2341, +1243, 614, 2470, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 48, +0, 0, 168, +0, 0, 291, +0, 0, 417, +0, 0, 544, +0, 0, 672, +0, 0, 801, +0, 0, 931, +0, 0, 1090, +0, 0, 1302, +0, 0, 1479, +0, 0, 1635, +460, 0, 1772, +1156, 0, 1884, +1560, 0, 2008, +1554, 0, 2156, +416, 998, 2341, +1249, 617, 2470, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 63, +0, 0, 180, +0, 0, 300, +0, 0, 424, +0, 0, 549, +0, 0, 676, +0, 0, 804, +0, 0, 933, +0, 0, 1091, +0, 0, 1302, +0, 0, 1480, +0, 0, 1636, +427, 0, 1772, +1154, 0, 1884, +1560, 0, 2009, +1552, 0, 2156, +416, 1005, 2342, +1256, 621, 2470, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 120, +0, 0, 224, +0, 0, 335, +0, 0, 450, +0, 0, 569, +0, 0, 691, +0, 0, 816, +0, 0, 942, +0, 0, 1097, +0, 0, 1306, +0, 0, 1482, +0, 0, 1637, +445, 0, 1774, +1153, 0, 1885, +1554, 0, 2010, +1544, 22, 2158, +407, 1015, 2342, +1266, 621, 2470, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 120, +0, 0, 277, +0, 0, 376, +0, 0, 483, +0, 0, 594, +0, 0, 711, +0, 0, 831, +0, 0, 954, +0, 23, 1106, +0, 30, 1311, +0, 30, 1486, +0, 0, 1639, +467, 0, 1775, +1150, 0, 1887, +1547, 0, 2012, +1534, 170, 2160, +394, 1028, 2343, +1279, 621, 2470, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +0, 4, 0, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 11, 120, +0, 67, 277, +0, 133, 427, +0, 133, 523, +0, 133, 627, +0, 133, 736, +0, 133, 850, +0, 133, 968, +0, 186, 1116, +0, 163, 1318, +0, 163, 1490, +0, 112, 1641, +496, 0, 1778, +1147, 0, 1888, +1538, 32, 2014, +1520, 314, 2163, +376, 1045, 2344, +1296, 621, 2470, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +0, 144, 0, +0, 137, 0, +0, 127, 0, +0, 114, 0, +0, 148, 120, +0, 190, 277, +0, 241, 427, +0, 302, 573, +0, 302, 666, +0, 302, 767, +0, 302, 875, +0, 302, 987, +0, 339, 1130, +0, 295, 1327, +0, 295, 1496, +0, 258, 1644, +531, 58, 1781, +1142, 0, 1891, +1524, 164, 2018, +1500, 455, 2167, +352, 1066, 2345, +1318, 621, 2470, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +0, 281, 0, +0, 276, 0, +0, 269, 0, +0, 259, 0, +0, 284, 120, +0, 316, 277, +0, 355, 427, +0, 403, 573, +0, 459, 714, +0, 459, 806, +0, 459, 906, +0, 459, 1012, +0, 486, 1148, +0, 426, 1339, +0, 426, 1504, +0, 399, 1648, +574, 219, 1786, +1136, 111, 1894, +1506, 296, 2022, +1472, 593, 2172, +317, 1093, 2347, +1356, 639, 2470, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +0, 417, 0, +0, 413, 0, +0, 408, 0, +0, 401, 0, +0, 419, 120, +0, 443, 277, +0, 473, 427, +0, 510, 573, +0, 556, 714, +0, 610, 854, +0, 610, 944, +0, 610, 1043, +0, 629, 1171, +0, 570, 1354, +0, 559, 1515, +0, 539, 1653, +578, 410, 1789, +1128, 244, 1899, +1481, 428, 2028, +1431, 730, 2178, +265, 1128, 2349, +1403, 662, 2470, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +0, 552, 0, +0, 549, 0, +0, 545, 0, +0, 540, 0, +0, 553, 120, +0, 571, 277, +0, 594, 427, +0, 623, 573, +0, 658, 714, +0, 702, 854, +0, 755, 991, +0, 755, 1080, +0, 769, 1200, +0, 726, 1374, +0, 691, 1529, +0, 676, 1662, +578, 585, 1795, +1145, 422, 1905, +1444, 560, 2035, +1371, 865, 2187, +186, 1169, 2352, +1460, 691, 2470, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +0, 686, 0, +0, 684, 0, +0, 681, 0, +0, 677, 0, +0, 688, 120, +0, 701, 277, +0, 718, 427, +0, 740, 573, +0, 768, 714, +0, 803, 854, +0, 845, 991, +0, 897, 1127, +0, 907, 1236, +0, 876, 1399, +0, 823, 1547, +0, 812, 1675, +578, 746, 1801, +1172, 593, 1913, +1390, 692, 2045, +1275, 1000, 2199, +0, 1212, 2357, +1526, 728, 2470, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +0, 854, 85, +0, 854, 130, +0, 852, 185, +0, 850, 248, +0, 857, 344, +0, 866, 446, +0, 878, 555, +0, 894, 669, +0, 914, 787, +0, 939, 908, +0, 971, 1032, +0, 1011, 1157, +0, 1051, 1285, +0, 1029, 1433, +0, 983, 1572, +27, 965, 1697, +589, 934, 1816, +1190, 800, 1926, +1312, 849, 2057, +1127, 1135, 2212, +0, 1254, 2365, +1589, 800, 2470, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +0, 1178, 1018, +0, 1178, 1024, +0, 1178, 1032, +0, 1178, 1043, +0, 1178, 1052, +0, 1178, 1064, +0, 1178, 1080, +0, 1178, 1099, +0, 1178, 1125, +0, 1184, 1168, +0, 1203, 1242, +0, 1227, 1325, +0, 1253, 1417, +21, 1234, 1496, +21, 1206, 1619, +81, 1217, 1742, +655, 1189, 1855, +1060, 1135, 1962, +1243, 1131, 2080, +1031, 1271, 2225, +573, 1308, 2371, +1592, 1028, 2471, +1767, 1138, 2512, +1767, 1138, 2512, +1767, 1138, 2512, +1767, 1138, 2512, +1767, 1138, 2512, +1767, 1138, 2512, +1767, 1138, 2512, +1767, 1138, 2512, +1767, 1138, 2512, +1767, 1138, 2512, +0, 1418, 1374, +0, 1418, 1376, +0, 1418, 1380, +0, 1418, 1385, +0, 1418, 1389, +0, 1418, 1395, +0, 1418, 1402, +0, 1418, 1412, +0, 1418, 1425, +0, 1418, 1442, +0, 1418, 1463, +0, 1418, 1491, +0, 1429, 1546, +21, 1416, 1607, +21, 1397, 1675, +81, 1409, 1787, +655, 1406, 1896, +1067, 1355, 2000, +1151, 1350, 2109, +878, 1405, 2240, +735, 1384, 2378, +1605, 1206, 2473, +1801, 1309, 2510, +1801, 1309, 2510, +1801, 1309, 2510, +1801, 1309, 2510, +1801, 1309, 2510, +1801, 1309, 2510, +1801, 1309, 2510, +1801, 1309, 2510, +1801, 1309, 2510, +1801, 1309, 2510, +949, 1577, 1650, +947, 1578, 1651, +946, 1578, 1652, +943, 1579, 1653, +943, 1578, 1656, +943, 1577, 1659, +943, 1576, 1663, +943, 1574, 1669, +943, 1572, 1676, +943, 1569, 1686, +943, 1567, 1699, +943, 1567, 1715, +924, 1567, 1737, +908, 1576, 1787, +908, 1568, 1837, +917, 1552, 1889, +852, 1557, 1971, +951, 1536, 2066, +957, 1537, 2170, +810, 1525, 2268, +1138, 1499, 2382, +1680, 1435, 2473, +1845, 1470, 2509, +1845, 1470, 2509, +1845, 1470, 2509, +1845, 1470, 2509, +1845, 1470, 2509, +1845, 1470, 2509, +1845, 1470, 2509, +1845, 1470, 2509, +1845, 1470, 2509, +1845, 1470, 2509, +1454, 1705, 1855, +1453, 1705, 1856, +1451, 1705, 1857, +1449, 1705, 1859, +1447, 1705, 1860, +1444, 1705, 1862, +1441, 1705, 1865, +1436, 1705, 1868, +1430, 1705, 1873, +1430, 1703, 1880, +1430, 1700, 1888, +1430, 1696, 1899, +1426, 1691, 1913, +1403, 1685, 1931, +1403, 1696, 1977, +1372, 1701, 2021, +1375, 1686, 2063, +1206, 1672, 2128, +1137, 1678, 2221, +1185, 1647, 2295, +1521, 1632, 2386, +1778, 1634, 2475, +1894, 1628, 2511, +1894, 1628, 2511, +1894, 1628, 2511, +1894, 1628, 2511, +1894, 1628, 2511, +1894, 1628, 2511, +1894, 1628, 2511, +1894, 1628, 2511, +1894, 1628, 2511, +1894, 1628, 2511, +1788, 1817, 1978, +1788, 1817, 1978, +1787, 1817, 1979, +1787, 1817, 1980, +1787, 1817, 1981, +1788, 1817, 1982, +1789, 1817, 1983, +1790, 1817, 1986, +1791, 1817, 1988, +1793, 1817, 1992, +1789, 1817, 1998, +1782, 1817, 2007, +1773, 1818, 2018, +1754, 1823, 2036, +1735, 1818, 2051, +1730, 1803, 2080, +1689, 1816, 2124, +1707, 1808, 2166, +1658, 1793, 2234, +1668, 1793, 2304, +1756, 1797, 2389, +1874, 1789, 2475, +1965, 1800, 2514, +1965, 1800, 2514, +1965, 1800, 2514, +1965, 1800, 2514, +1965, 1800, 2514, +1965, 1800, 2514, +1965, 1800, 2514, +1965, 1800, 2514, +1965, 1800, 2514, +1965, 1800, 2514, +1959, 1958, 2029, +1959, 1958, 2029, +1958, 1958, 2030, +1958, 1958, 2030, +1958, 1958, 2031, +1957, 1958, 2032, +1957, 1958, 2033, +1956, 1958, 2035, +1955, 1958, 2037, +1954, 1958, 2041, +1952, 1958, 2045, +1950, 1958, 2051, +1946, 1958, 2058, +1942, 1962, 2068, +1936, 1967, 2081, +1928, 1969, 2114, +1915, 1966, 2154, +1905, 1962, 2189, +1920, 1968, 2243, +1883, 1968, 2320, +1930, 1954, 2392, +2035, 1964, 2481, +2095, 1968, 2516, +2095, 1968, 2516, +2095, 1968, 2516, +2095, 1968, 2516, +2095, 1968, 2516, +2095, 1968, 2516, +2095, 1968, 2516, +2095, 1968, 2516, +2095, 1968, 2516, +2095, 1968, 2516, +2120, 2120, 2068, +2120, 2120, 2068, +2120, 2120, 2068, +2120, 2120, 2069, +2120, 2120, 2069, +2120, 2120, 2070, +2120, 2120, 2071, +2120, 2121, 2073, +2120, 2122, 2075, +2120, 2122, 2078, +2120, 2124, 2082, +2120, 2125, 2088, +2119, 2127, 2095, +2119, 2127, 2101, +2119, 2127, 2110, +2116, 2131, 2132, +2110, 2133, 2165, +2104, 2131, 2206, +2111, 2134, 2256, +2120, 2135, 2316, +2148, 2131, 2395, +2212, 2147, 2485, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2370, 2355, 2124, +2370, 2355, 2124, +2370, 2355, 2124, +2370, 2355, 2125, +2370, 2355, 2125, +2370, 2356, 2126, +2369, 2356, 2126, +2369, 2356, 2127, +2369, 2357, 2129, +2368, 2357, 2131, +2368, 2358, 2133, +2368, 2359, 2137, +2369, 2360, 2143, +2370, 2358, 2146, +2369, 2356, 2148, +2369, 2358, 2163, +2371, 2358, 2193, +2369, 2358, 2226, +2372, 2355, 2273, +2384, 2357, 2337, +2410, 2367, 2405, +2467, 2385, 2498, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2681, 2655, 1963, +2681, 2655, 1963, +2681, 2655, 1964, +2681, 2655, 1965, +2681, 2655, 1966, +2681, 2655, 1967, +2681, 2655, 1968, +2681, 2655, 1969, +2681, 2654, 1968, +2681, 2654, 1967, +2680, 2654, 1965, +2680, 2653, 1963, +2679, 2653, 1963, +2678, 2654, 1973, +2677, 2655, 1994, +2676, 2653, 2016, +2675, 2650, 2036, +2677, 2655, 2123, +2681, 2656, 2208, +2687, 2661, 2306, +2695, 2666, 2409, +2715, 2678, 2527, +2723, 2684, 2575, +2723, 2684, 2575, +2723, 2684, 2575, +2723, 2684, 2575, +2723, 2684, 2575, +2723, 2684, 2575, +2723, 2684, 2575, +2723, 2684, 2575, +2723, 2684, 2575, +2723, 2684, 2575, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2456, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2456, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2456, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2456, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2456, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2456, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2456, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2456, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2456, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2456, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +58, 0, 0, +58, 0, 0, +58, 0, 0, +58, 0, 0, +58, 0, 28, +58, 0, 152, +58, 0, 280, +58, 0, 408, +58, 0, 537, +58, 0, 667, +58, 0, 797, +58, 0, 928, +0, 0, 1088, +0, 0, 1305, +0, 0, 1481, +28, 0, 1634, +564, 0, 1774, +1165, 0, 1884, +1561, 0, 2007, +1555, 0, 2157, +407, 987, 2341, +1245, 605, 2470, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +41, 0, 0, +50, 0, 0, +50, 0, 0, +50, 0, 0, +50, 0, 36, +50, 0, 159, +50, 0, 285, +50, 0, 412, +50, 0, 540, +50, 0, 669, +50, 0, 799, +50, 0, 930, +0, 0, 1089, +0, 0, 1306, +0, 0, 1482, +36, 0, 1635, +550, 0, 1774, +1164, 0, 1884, +1561, 0, 2008, +1554, 0, 2157, +407, 992, 2341, +1249, 608, 2470, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +17, 0, 0, +26, 0, 0, +38, 0, 0, +38, 0, 0, +38, 0, 48, +38, 0, 168, +38, 0, 291, +38, 0, 417, +38, 0, 544, +38, 0, 672, +38, 0, 801, +38, 0, 931, +0, 0, 1090, +0, 0, 1307, +0, 0, 1482, +48, 0, 1635, +530, 0, 1773, +1163, 0, 1884, +1560, 0, 2008, +1552, 0, 2157, +407, 998, 2341, +1254, 611, 2470, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +0, 0, 0, +0, 0, 0, +6, 0, 0, +22, 0, 0, +22, 0, 63, +22, 0, 180, +22, 0, 300, +22, 0, 424, +22, 0, 549, +22, 0, 676, +22, 0, 804, +22, 0, 933, +0, 0, 1091, +0, 0, 1308, +0, 0, 1483, +63, 0, 1636, +502, 0, 1773, +1162, 0, 1885, +1560, 0, 2009, +1550, 0, 2158, +407, 1005, 2342, +1262, 615, 2470, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 83, +0, 0, 195, +0, 0, 312, +0, 0, 433, +0, 0, 556, +0, 0, 681, +0, 0, 808, +0, 0, 936, +0, 0, 1093, +0, 0, 1309, +0, 0, 1484, +83, 0, 1637, +462, 0, 1772, +1160, 0, 1885, +1559, 0, 2010, +1547, 0, 2158, +407, 1015, 2342, +1272, 621, 2470, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 83, +0, 0, 251, +0, 0, 356, +0, 0, 467, +0, 0, 582, +0, 0, 701, +0, 0, 823, +0, 0, 948, +0, 0, 1102, +0, 30, 1314, +0, 30, 1487, +83, 0, 1639, +483, 0, 1774, +1157, 0, 1887, +1552, 0, 2012, +1536, 154, 2160, +394, 1028, 2343, +1285, 621, 2470, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +0, 4, 0, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 83, +0, 3, 251, +0, 78, 409, +0, 78, 509, +0, 78, 615, +0, 78, 727, +0, 78, 843, +0, 78, 963, +0, 137, 1112, +0, 163, 1321, +0, 163, 1492, +83, 94, 1641, +511, 0, 1777, +1154, 0, 1889, +1542, 32, 2015, +1522, 302, 2163, +376, 1045, 2344, +1302, 621, 2470, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +0, 144, 0, +0, 137, 0, +0, 127, 0, +0, 114, 0, +0, 96, 83, +0, 143, 251, +0, 199, 409, +0, 265, 559, +0, 265, 655, +0, 265, 759, +0, 265, 868, +0, 265, 982, +0, 305, 1126, +0, 295, 1330, +0, 295, 1498, +83, 244, 1644, +545, 15, 1780, +1150, 0, 1891, +1529, 164, 2018, +1502, 446, 2167, +352, 1066, 2345, +1323, 621, 2470, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +0, 281, 0, +0, 276, 0, +0, 269, 0, +0, 259, 0, +0, 246, 83, +0, 280, 251, +0, 322, 409, +0, 373, 559, +0, 434, 705, +0, 434, 798, +0, 434, 899, +0, 434, 1007, +0, 462, 1144, +0, 426, 1341, +0, 426, 1506, +83, 390, 1648, +587, 190, 1784, +1144, 111, 1895, +1511, 296, 2022, +1474, 586, 2172, +317, 1093, 2347, +1361, 639, 2470, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +0, 417, 0, +0, 413, 0, +0, 408, 0, +0, 401, 0, +0, 391, 83, +0, 416, 251, +0, 448, 409, +0, 487, 559, +0, 535, 705, +0, 591, 846, +0, 591, 938, +0, 591, 1038, +0, 611, 1167, +0, 570, 1357, +0, 559, 1517, +83, 531, 1653, +591, 391, 1789, +1136, 244, 1899, +1486, 428, 2028, +1434, 725, 2178, +265, 1128, 2349, +1407, 662, 2470, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +0, 552, 0, +0, 549, 0, +0, 545, 0, +0, 540, 0, +0, 533, 83, +0, 551, 251, +0, 575, 409, +0, 605, 559, +0, 642, 705, +0, 688, 846, +0, 742, 985, +0, 742, 1076, +0, 756, 1197, +0, 726, 1376, +0, 691, 1531, +83, 670, 1662, +591, 572, 1794, +1152, 422, 1905, +1450, 560, 2036, +1374, 862, 2187, +186, 1169, 2352, +1464, 691, 2470, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +0, 686, 0, +0, 684, 0, +0, 681, 0, +0, 677, 0, +0, 672, 83, +0, 686, 251, +0, 703, 409, +0, 726, 559, +0, 755, 705, +0, 791, 846, +0, 835, 985, +0, 887, 1123, +0, 898, 1233, +0, 876, 1401, +0, 823, 1548, +83, 808, 1675, +591, 737, 1800, +1179, 593, 1913, +1396, 692, 2046, +1279, 997, 2199, +0, 1212, 2357, +1529, 728, 2470, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +0, 854, 85, +0, 854, 130, +0, 852, 185, +0, 850, 248, +0, 846, 322, +0, 855, 429, +0, 868, 541, +0, 884, 658, +0, 904, 778, +0, 930, 901, +0, 963, 1027, +0, 1003, 1154, +69, 1044, 1282, +0, 1029, 1435, +0, 983, 1573, +141, 963, 1697, +601, 928, 1815, +1197, 800, 1927, +1320, 849, 2058, +1133, 1133, 2212, +0, 1254, 2365, +1592, 800, 2470, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +136, 1175, 1014, +107, 1175, 1020, +65, 1175, 1028, +1, 1175, 1038, +0, 1175, 1052, +0, 1175, 1064, +0, 1175, 1080, +0, 1175, 1099, +0, 1175, 1125, +0, 1180, 1168, +0, 1200, 1242, +0, 1224, 1325, +21, 1250, 1417, +153, 1233, 1497, +153, 1204, 1620, +214, 1214, 1743, +666, 1191, 1855, +1071, 1137, 1962, +1243, 1131, 2080, +1031, 1271, 2226, +622, 1305, 2371, +1594, 1025, 2471, +1769, 1134, 2512, +1769, 1134, 2512, +1769, 1134, 2512, +1769, 1134, 2512, +1769, 1134, 2512, +1769, 1134, 2512, +1769, 1134, 2512, +1769, 1134, 2512, +1769, 1134, 2512, +1769, 1134, 2512, +136, 1416, 1371, +107, 1416, 1374, +65, 1416, 1378, +1, 1416, 1383, +0, 1416, 1389, +0, 1416, 1395, +0, 1416, 1402, +0, 1416, 1412, +0, 1416, 1425, +0, 1416, 1442, +0, 1416, 1463, +0, 1416, 1491, +21, 1427, 1546, +153, 1415, 1608, +153, 1396, 1676, +214, 1407, 1788, +666, 1407, 1897, +1078, 1356, 2001, +1151, 1350, 2109, +878, 1405, 2241, +770, 1382, 2378, +1607, 1205, 2473, +1802, 1306, 2510, +1802, 1306, 2510, +1802, 1306, 2510, +1802, 1306, 2510, +1802, 1306, 2510, +1802, 1306, 2510, +1802, 1306, 2510, +1802, 1306, 2510, +1802, 1306, 2510, +1802, 1306, 2510, +973, 1576, 1651, +973, 1576, 1652, +971, 1577, 1653, +969, 1577, 1654, +966, 1578, 1656, +966, 1577, 1659, +966, 1576, 1664, +966, 1574, 1669, +966, 1572, 1677, +966, 1569, 1686, +966, 1567, 1699, +966, 1567, 1716, +948, 1567, 1737, +920, 1575, 1786, +920, 1568, 1836, +932, 1552, 1890, +876, 1557, 1972, +968, 1536, 2066, +965, 1537, 2170, +810, 1526, 2268, +1145, 1498, 2382, +1680, 1435, 2473, +1844, 1469, 2509, +1844, 1469, 2509, +1844, 1469, 2509, +1844, 1469, 2509, +1844, 1469, 2509, +1844, 1469, 2509, +1844, 1469, 2509, +1844, 1469, 2509, +1844, 1469, 2509, +1844, 1469, 2509, +1457, 1704, 1855, +1456, 1704, 1856, +1454, 1705, 1857, +1452, 1705, 1858, +1449, 1705, 1860, +1446, 1705, 1862, +1443, 1705, 1865, +1438, 1705, 1868, +1432, 1705, 1873, +1431, 1703, 1880, +1431, 1700, 1888, +1431, 1696, 1899, +1428, 1691, 1913, +1405, 1685, 1932, +1405, 1696, 1977, +1373, 1700, 2021, +1378, 1686, 2063, +1214, 1672, 2128, +1142, 1679, 2221, +1192, 1647, 2295, +1522, 1633, 2386, +1779, 1634, 2475, +1895, 1627, 2511, +1895, 1627, 2511, +1895, 1627, 2511, +1895, 1627, 2511, +1895, 1627, 2511, +1895, 1627, 2511, +1895, 1627, 2511, +1895, 1627, 2511, +1895, 1627, 2511, +1895, 1627, 2511, +1790, 1816, 1977, +1790, 1816, 1978, +1789, 1816, 1978, +1789, 1816, 1979, +1788, 1816, 1981, +1788, 1816, 1982, +1789, 1816, 1983, +1790, 1816, 1986, +1792, 1816, 1988, +1793, 1816, 1992, +1790, 1816, 1998, +1783, 1816, 2007, +1773, 1817, 2018, +1755, 1823, 2036, +1736, 1817, 2051, +1731, 1804, 2079, +1691, 1816, 2124, +1708, 1807, 2166, +1659, 1793, 2234, +1670, 1794, 2305, +1757, 1797, 2389, +1873, 1789, 2475, +1966, 1800, 2514, +1966, 1800, 2514, +1966, 1800, 2514, +1966, 1800, 2514, +1966, 1800, 2514, +1966, 1800, 2514, +1966, 1800, 2514, +1966, 1800, 2514, +1966, 1800, 2514, +1966, 1800, 2514, +1960, 1958, 2029, +1960, 1958, 2029, +1959, 1958, 2030, +1959, 1958, 2030, +1958, 1958, 2031, +1958, 1958, 2032, +1957, 1958, 2034, +1956, 1958, 2035, +1956, 1958, 2038, +1954, 1958, 2041, +1952, 1958, 2046, +1950, 1958, 2051, +1947, 1958, 2059, +1942, 1961, 2068, +1936, 1967, 2081, +1928, 1969, 2113, +1916, 1966, 2154, +1905, 1962, 2189, +1920, 1968, 2242, +1884, 1968, 2319, +1930, 1954, 2392, +2036, 1964, 2481, +2096, 1968, 2516, +2096, 1968, 2516, +2096, 1968, 2516, +2096, 1968, 2516, +2096, 1968, 2516, +2096, 1968, 2516, +2096, 1968, 2516, +2096, 1968, 2516, +2096, 1968, 2516, +2096, 1968, 2516, +2120, 2120, 2068, +2120, 2120, 2068, +2120, 2120, 2069, +2120, 2120, 2069, +2121, 2120, 2069, +2121, 2120, 2070, +2121, 2120, 2071, +2121, 2121, 2073, +2121, 2122, 2075, +2121, 2122, 2078, +2121, 2124, 2082, +2121, 2125, 2087, +2120, 2127, 2094, +2119, 2127, 2101, +2119, 2127, 2110, +2116, 2131, 2132, +2110, 2134, 2165, +2104, 2130, 2206, +2111, 2134, 2256, +2120, 2134, 2316, +2148, 2131, 2395, +2213, 2146, 2485, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2370, 2355, 2124, +2370, 2355, 2124, +2370, 2355, 2124, +2370, 2355, 2125, +2370, 2355, 2125, +2370, 2355, 2126, +2370, 2356, 2126, +2369, 2356, 2127, +2369, 2356, 2129, +2369, 2357, 2131, +2368, 2357, 2133, +2368, 2359, 2137, +2369, 2360, 2143, +2370, 2358, 2146, +2369, 2356, 2148, +2369, 2358, 2162, +2371, 2358, 2193, +2370, 2358, 2226, +2372, 2356, 2273, +2384, 2357, 2337, +2410, 2367, 2406, +2466, 2384, 2498, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2681, 2655, 1963, +2681, 2655, 1963, +2681, 2655, 1964, +2681, 2655, 1965, +2681, 2655, 1967, +2681, 2655, 1968, +2681, 2655, 1969, +2681, 2655, 1970, +2681, 2655, 1969, +2681, 2654, 1968, +2680, 2654, 1966, +2680, 2653, 1964, +2679, 2653, 1964, +2678, 2654, 1975, +2677, 2655, 1997, +2676, 2654, 2018, +2675, 2650, 2038, +2677, 2655, 2123, +2681, 2656, 2208, +2687, 2661, 2306, +2695, 2666, 2409, +2715, 2678, 2527, +2723, 2684, 2575, +2723, 2684, 2575, +2723, 2684, 2575, +2723, 2684, 2575, +2723, 2684, 2575, +2723, 2684, 2575, +2723, 2684, 2575, +2723, 2684, 2575, +2723, 2684, 2575, +2723, 2684, 2575, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2456, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2456, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2456, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2456, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2456, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2456, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2456, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2456, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2456, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2456, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +197, 0, 0, +197, 0, 0, +197, 0, 0, +197, 0, 0, +197, 0, 28, +197, 0, 152, +197, 0, 280, +197, 0, 408, +197, 0, 537, +197, 0, 667, +197, 0, 797, +197, 0, 928, +71, 0, 1088, +0, 0, 1312, +0, 0, 1486, +152, 0, 1634, +638, 0, 1775, +1174, 0, 1884, +1561, 0, 2008, +1552, 0, 2159, +394, 987, 2341, +1252, 597, 2470, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +184, 0, 0, +190, 0, 0, +190, 0, 0, +190, 0, 0, +190, 0, 36, +190, 0, 159, +190, 0, 285, +190, 0, 412, +190, 0, 540, +190, 0, 669, +190, 0, 799, +190, 0, 930, +46, 0, 1089, +0, 0, 1313, +0, 0, 1486, +159, 0, 1635, +626, 0, 1775, +1173, 0, 1885, +1561, 0, 2008, +1551, 0, 2159, +394, 992, 2341, +1257, 599, 2470, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +167, 0, 0, +173, 0, 0, +182, 0, 0, +182, 0, 0, +182, 0, 48, +182, 0, 168, +182, 0, 291, +182, 0, 417, +182, 0, 544, +182, 0, 672, +182, 0, 801, +182, 0, 931, +35, 0, 1090, +0, 0, 1313, +0, 0, 1487, +168, 0, 1635, +609, 0, 1775, +1172, 0, 1885, +1560, 0, 2009, +1549, 0, 2159, +394, 998, 2341, +1262, 603, 2470, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +142, 0, 0, +149, 0, 0, +158, 0, 0, +170, 0, 0, +170, 0, 63, +170, 0, 180, +170, 0, 300, +170, 0, 424, +170, 0, 549, +170, 0, 676, +170, 0, 804, +170, 0, 933, +19, 0, 1091, +0, 0, 1315, +0, 0, 1487, +180, 0, 1636, +586, 0, 1774, +1171, 0, 1886, +1560, 0, 2010, +1547, 0, 2159, +394, 1005, 2342, +1270, 608, 2470, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +107, 0, 0, +115, 0, 0, +125, 0, 0, +138, 0, 0, +154, 0, 83, +154, 0, 195, +154, 0, 312, +154, 0, 433, +154, 0, 556, +154, 0, 681, +154, 0, 808, +154, 0, 936, +0, 0, 1093, +0, 0, 1316, +0, 0, 1489, +195, 0, 1637, +552, 0, 1774, +1169, 0, 1886, +1559, 0, 2011, +1544, 57, 2160, +394, 1015, 2342, +1279, 613, 2470, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +56, 0, 0, +65, 0, 0, +76, 0, 0, +90, 0, 0, +108, 0, 83, +132, 0, 215, +132, 0, 327, +132, 0, 444, +132, 0, 564, +132, 0, 688, +132, 0, 813, +132, 0, 940, +0, 0, 1096, +0, 30, 1317, +0, 30, 1490, +215, 0, 1639, +504, 0, 1773, +1167, 0, 1887, +1558, 0, 2012, +1540, 132, 2160, +394, 1028, 2343, +1292, 621, 2470, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +56, 4, 0, +65, 0, 0, +76, 0, 0, +90, 0, 0, +108, 0, 83, +132, 0, 215, +132, 0, 383, +132, 0, 488, +132, 0, 599, +132, 0, 714, +132, 0, 833, +132, 0, 955, +0, 64, 1107, +0, 163, 1324, +0, 163, 1494, +215, 68, 1641, +530, 0, 1776, +1164, 0, 1889, +1548, 32, 2015, +1525, 286, 2163, +376, 1045, 2344, +1308, 621, 2470, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +56, 144, 0, +65, 137, 0, +76, 127, 0, +90, 114, 0, +108, 96, 83, +132, 70, 215, +132, 135, 383, +132, 210, 541, +132, 210, 641, +132, 210, 747, +132, 210, 859, +132, 210, 975, +0, 255, 1121, +0, 295, 1333, +0, 295, 1500, +215, 226, 1644, +563, 0, 1779, +1159, 0, 1892, +1536, 164, 2018, +1506, 434, 2167, +352, 1066, 2345, +1329, 621, 2470, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +56, 281, 0, +65, 276, 0, +76, 269, 0, +90, 259, 0, +108, 246, 83, +132, 227, 215, +132, 275, 383, +132, 331, 541, +132, 397, 691, +132, 397, 787, +132, 397, 891, +132, 397, 1000, +0, 427, 1139, +0, 426, 1344, +0, 426, 1508, +215, 376, 1648, +604, 147, 1783, +1154, 111, 1895, +1518, 296, 2022, +1478, 578, 2172, +317, 1093, 2347, +1367, 639, 2470, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +56, 417, 0, +65, 413, 0, +76, 408, 0, +90, 401, 0, +108, 391, 83, +132, 378, 215, +132, 412, 383, +132, 455, 541, +132, 505, 691, +132, 566, 837, +132, 566, 930, +132, 566, 1032, +0, 587, 1163, +0, 570, 1359, +0, 559, 1519, +215, 522, 1653, +607, 365, 1787, +1146, 244, 1900, +1493, 428, 2028, +1438, 719, 2178, +265, 1128, 2349, +1413, 662, 2470, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +56, 552, 0, +65, 549, 0, +76, 545, 0, +90, 540, 0, +108, 533, 83, +132, 523, 215, +132, 548, 383, +132, 580, 541, +132, 619, 691, +132, 667, 837, +132, 723, 978, +132, 723, 1071, +0, 738, 1192, +0, 726, 1379, +0, 691, 1532, +215, 663, 1662, +607, 554, 1792, +1162, 422, 1905, +1457, 560, 2036, +1379, 857, 2187, +186, 1169, 2352, +1468, 691, 2470, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +56, 686, 0, +65, 684, 0, +76, 681, 0, +90, 677, 0, +108, 672, 83, +132, 665, 215, +132, 684, 383, +132, 708, 541, +132, 737, 691, +132, 774, 837, +132, 820, 978, +132, 874, 1118, +0, 885, 1229, +0, 876, 1403, +0, 823, 1550, +215, 803, 1675, +607, 725, 1799, +1188, 593, 1913, +1404, 692, 2046, +1285, 994, 2199, +0, 1212, 2357, +1533, 728, 2470, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +63, 854, 85, +31, 854, 130, +43, 852, 185, +58, 850, 248, +78, 846, 322, +103, 841, 404, +103, 854, 522, +103, 870, 643, +103, 892, 767, +103, 918, 893, +103, 952, 1020, +103, 993, 1149, +185, 1035, 1278, +0, 1029, 1438, +0, 983, 1575, +259, 959, 1697, +617, 920, 1814, +1206, 800, 1927, +1329, 849, 2058, +1141, 1131, 2212, +0, 1254, 2365, +1596, 800, 2470, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +289, 1170, 1007, +268, 1170, 1013, +239, 1170, 1021, +196, 1170, 1032, +132, 1170, 1046, +30, 1170, 1064, +30, 1170, 1080, +30, 1170, 1099, +30, 1170, 1125, +30, 1176, 1168, +30, 1195, 1242, +30, 1220, 1325, +125, 1246, 1417, +285, 1231, 1499, +285, 1202, 1622, +345, 1210, 1744, +680, 1193, 1856, +1086, 1139, 1963, +1243, 1131, 2080, +1031, 1271, 2226, +681, 1302, 2370, +1597, 1022, 2471, +1771, 1129, 2512, +1771, 1129, 2512, +1771, 1129, 2512, +1771, 1129, 2512, +1771, 1129, 2512, +1771, 1129, 2512, +1771, 1129, 2512, +1771, 1129, 2512, +1771, 1129, 2512, +1771, 1129, 2512, +289, 1413, 1368, +268, 1413, 1371, +239, 1413, 1375, +196, 1413, 1380, +132, 1413, 1386, +30, 1413, 1395, +30, 1413, 1402, +30, 1413, 1412, +30, 1413, 1425, +30, 1413, 1442, +30, 1413, 1463, +30, 1413, 1491, +125, 1424, 1546, +285, 1414, 1610, +285, 1395, 1677, +345, 1404, 1789, +680, 1408, 1897, +1092, 1358, 2001, +1151, 1350, 2109, +878, 1405, 2241, +813, 1379, 2377, +1609, 1202, 2473, +1804, 1303, 2510, +1804, 1303, 2510, +1804, 1303, 2510, +1804, 1303, 2510, +1804, 1303, 2510, +1804, 1303, 2510, +1804, 1303, 2510, +1804, 1303, 2510, +1804, 1303, 2510, +1804, 1303, 2510, +1005, 1574, 1653, +1004, 1574, 1654, +1003, 1575, 1655, +1001, 1575, 1656, +998, 1576, 1658, +995, 1577, 1660, +995, 1576, 1664, +995, 1574, 1670, +995, 1572, 1678, +995, 1569, 1687, +995, 1567, 1700, +995, 1567, 1716, +977, 1567, 1738, +937, 1574, 1785, +937, 1567, 1835, +952, 1552, 1890, +906, 1557, 1973, +989, 1536, 2066, +976, 1537, 2170, +810, 1527, 2268, +1155, 1497, 2382, +1680, 1435, 2473, +1844, 1468, 2509, +1844, 1468, 2509, +1844, 1468, 2509, +1844, 1468, 2509, +1844, 1468, 2509, +1844, 1468, 2509, +1844, 1468, 2509, +1844, 1468, 2509, +1844, 1468, 2509, +1844, 1468, 2509, +1461, 1703, 1854, +1459, 1704, 1855, +1458, 1704, 1856, +1456, 1704, 1858, +1453, 1705, 1859, +1449, 1705, 1862, +1446, 1705, 1865, +1441, 1705, 1868, +1435, 1705, 1873, +1434, 1703, 1880, +1434, 1700, 1888, +1434, 1696, 1899, +1431, 1691, 1913, +1408, 1685, 1932, +1408, 1696, 1977, +1375, 1699, 2021, +1380, 1687, 2064, +1224, 1672, 2127, +1149, 1680, 2221, +1200, 1647, 2295, +1523, 1633, 2386, +1781, 1634, 2475, +1896, 1626, 2511, +1896, 1626, 2511, +1896, 1626, 2511, +1896, 1626, 2511, +1896, 1626, 2511, +1896, 1626, 2511, +1896, 1626, 2511, +1896, 1626, 2511, +1896, 1626, 2511, +1896, 1626, 2511, +1793, 1816, 1977, +1792, 1816, 1977, +1792, 1816, 1978, +1791, 1816, 1979, +1790, 1816, 1980, +1789, 1816, 1982, +1790, 1816, 1983, +1791, 1816, 1986, +1792, 1816, 1988, +1794, 1816, 1992, +1790, 1816, 1998, +1783, 1816, 2007, +1774, 1817, 2018, +1756, 1822, 2035, +1737, 1817, 2051, +1733, 1804, 2079, +1694, 1816, 2124, +1710, 1807, 2166, +1660, 1793, 2234, +1673, 1795, 2305, +1759, 1797, 2389, +1873, 1788, 2475, +1968, 1800, 2514, +1968, 1800, 2514, +1968, 1800, 2514, +1968, 1800, 2514, +1968, 1800, 2514, +1968, 1800, 2514, +1968, 1800, 2514, +1968, 1800, 2514, +1968, 1800, 2514, +1968, 1800, 2514, +1961, 1958, 2029, +1961, 1958, 2030, +1961, 1958, 2030, +1960, 1958, 2031, +1959, 1958, 2031, +1959, 1958, 2032, +1958, 1958, 2034, +1958, 1958, 2036, +1956, 1958, 2038, +1955, 1958, 2042, +1953, 1958, 2046, +1951, 1958, 2052, +1948, 1958, 2059, +1943, 1961, 2068, +1937, 1966, 2081, +1930, 1968, 2112, +1918, 1966, 2154, +1905, 1962, 2189, +1920, 1968, 2242, +1885, 1967, 2319, +1930, 1954, 2392, +2038, 1964, 2481, +2097, 1968, 2516, +2097, 1968, 2516, +2097, 1968, 2516, +2097, 1968, 2516, +2097, 1968, 2516, +2097, 1968, 2516, +2097, 1968, 2516, +2097, 1968, 2516, +2097, 1968, 2516, +2097, 1968, 2516, +2120, 2120, 2069, +2120, 2120, 2069, +2121, 2120, 2069, +2121, 2120, 2069, +2121, 2120, 2069, +2121, 2120, 2069, +2121, 2120, 2071, +2121, 2121, 2073, +2121, 2122, 2075, +2121, 2122, 2078, +2121, 2124, 2082, +2121, 2125, 2087, +2120, 2127, 2094, +2119, 2127, 2101, +2119, 2127, 2110, +2117, 2131, 2132, +2111, 2134, 2166, +2105, 2130, 2206, +2111, 2134, 2255, +2121, 2134, 2316, +2148, 2131, 2396, +2213, 2146, 2485, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2370, 2355, 2124, +2370, 2355, 2124, +2370, 2355, 2124, +2370, 2355, 2125, +2370, 2355, 2125, +2370, 2355, 2126, +2370, 2355, 2126, +2370, 2356, 2127, +2369, 2356, 2129, +2369, 2357, 2131, +2368, 2357, 2133, +2369, 2358, 2137, +2369, 2359, 2143, +2370, 2358, 2146, +2369, 2356, 2148, +2369, 2358, 2162, +2371, 2358, 2193, +2370, 2358, 2226, +2373, 2356, 2273, +2385, 2357, 2337, +2411, 2367, 2406, +2466, 2384, 2498, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2681, 2655, 1963, +2681, 2655, 1963, +2681, 2655, 1964, +2681, 2655, 1965, +2681, 2655, 1967, +2681, 2655, 1969, +2681, 2655, 1970, +2681, 2655, 1971, +2681, 2655, 1970, +2681, 2655, 1969, +2680, 2654, 1968, +2680, 2654, 1965, +2679, 2653, 1966, +2679, 2654, 1979, +2677, 2655, 2000, +2676, 2654, 2020, +2675, 2650, 2041, +2677, 2655, 2122, +2681, 2656, 2208, +2688, 2661, 2306, +2695, 2666, 2408, +2715, 2678, 2527, +2723, 2684, 2575, +2723, 2684, 2575, +2723, 2684, 2575, +2723, 2684, 2575, +2723, 2684, 2575, +2723, 2684, 2575, +2723, 2684, 2575, +2723, 2684, 2575, +2723, 2684, 2575, +2723, 2684, 2575, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2457, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2784, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2457, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2784, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2457, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2784, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2457, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2784, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2457, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2784, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2457, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2784, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2457, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2784, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2457, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2784, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2457, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2784, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2457, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2784, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +333, 0, 0, +333, 0, 0, +333, 0, 0, +333, 0, 0, +333, 0, 28, +333, 0, 152, +333, 0, 280, +333, 0, 408, +333, 0, 537, +333, 0, 667, +333, 0, 797, +333, 0, 928, +244, 0, 1088, +0, 0, 1321, +0, 0, 1492, +280, 0, 1634, +721, 0, 1777, +1186, 0, 1886, +1561, 0, 2009, +1548, 0, 2161, +376, 987, 2341, +1263, 586, 2469, +1736, 0, 2503, +1736, 0, 2503, +1736, 0, 2503, +1736, 0, 2503, +1736, 0, 2503, +1736, 0, 2503, +1736, 0, 2503, +1736, 0, 2503, +1736, 0, 2503, +1736, 0, 2503, +324, 0, 0, +329, 0, 0, +329, 0, 0, +329, 0, 0, +329, 0, 36, +329, 0, 159, +329, 0, 285, +329, 0, 412, +329, 0, 540, +329, 0, 669, +329, 0, 799, +329, 0, 930, +227, 0, 1089, +0, 0, 1322, +0, 0, 1493, +285, 0, 1635, +711, 0, 1776, +1185, 0, 1886, +1561, 0, 2009, +1547, 0, 2161, +376, 992, 2341, +1267, 588, 2469, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +311, 0, 0, +316, 0, 0, +322, 0, 0, +322, 0, 0, +322, 0, 48, +322, 0, 168, +322, 0, 291, +322, 0, 417, +322, 0, 544, +322, 0, 672, +322, 0, 801, +322, 0, 931, +219, 0, 1090, +0, 0, 1323, +0, 0, 1493, +291, 0, 1635, +697, 0, 1776, +1184, 0, 1886, +1560, 0, 2010, +1545, 22, 2161, +376, 998, 2341, +1272, 592, 2469, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +294, 0, 0, +299, 0, 0, +305, 0, 0, +314, 0, 0, +314, 0, 63, +314, 0, 180, +314, 0, 300, +314, 0, 424, +314, 0, 549, +314, 0, 676, +314, 0, 804, +314, 0, 933, +209, 0, 1091, +0, 0, 1323, +0, 0, 1494, +300, 0, 1636, +678, 0, 1776, +1183, 0, 1887, +1560, 0, 2011, +1543, 69, 2161, +376, 1005, 2342, +1280, 596, 2469, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +269, 0, 0, +274, 0, 0, +281, 0, 0, +290, 0, 0, +302, 0, 83, +302, 0, 195, +302, 0, 312, +302, 0, 433, +302, 0, 556, +302, 0, 681, +302, 0, 808, +302, 0, 936, +194, 0, 1093, +0, 0, 1325, +0, 0, 1495, +312, 0, 1637, +651, 0, 1776, +1181, 0, 1887, +1559, 0, 2012, +1540, 124, 2162, +376, 1015, 2342, +1289, 603, 2469, +1734, 0, 2504, +1734, 0, 2504, +1734, 0, 2504, +1734, 0, 2504, +1734, 0, 2504, +1734, 0, 2504, +1734, 0, 2504, +1734, 0, 2504, +1734, 0, 2504, +1734, 0, 2504, +234, 0, 0, +239, 0, 0, +247, 0, 0, +257, 0, 0, +270, 0, 83, +286, 0, 215, +286, 0, 327, +286, 0, 444, +286, 0, 564, +286, 0, 688, +286, 0, 813, +286, 0, 940, +173, 0, 1096, +0, 30, 1326, +0, 30, 1496, +327, 0, 1639, +613, 0, 1775, +1179, 0, 1888, +1558, 0, 2013, +1535, 189, 2162, +376, 1028, 2343, +1301, 611, 2469, +1733, 30, 2504, +1733, 30, 2504, +1733, 30, 2504, +1733, 30, 2504, +1733, 30, 2504, +1733, 30, 2504, +1733, 30, 2504, +1733, 30, 2504, +1733, 30, 2504, +1733, 30, 2504, +182, 4, 0, +188, 0, 0, +197, 0, 0, +208, 0, 0, +222, 0, 83, +241, 0, 215, +264, 0, 347, +264, 0, 459, +264, 0, 576, +264, 0, 697, +264, 0, 820, +264, 0, 946, +145, 0, 1100, +0, 163, 1329, +0, 163, 1497, +347, 32, 1641, +555, 0, 1774, +1176, 0, 1890, +1557, 32, 2015, +1530, 264, 2163, +376, 1045, 2344, +1318, 621, 2469, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +182, 144, 0, +188, 137, 0, +197, 127, 0, +208, 114, 0, +222, 96, 83, +241, 70, 215, +264, 34, 347, +264, 126, 516, +264, 126, 620, +264, 126, 731, +264, 126, 846, +264, 126, 966, +145, 179, 1114, +0, 295, 1337, +0, 295, 1503, +347, 201, 1644, +586, 0, 1777, +1172, 0, 1892, +1544, 164, 2019, +1510, 418, 2167, +352, 1066, 2345, +1338, 621, 2469, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +182, 281, 0, +188, 276, 0, +197, 269, 0, +208, 259, 0, +222, 246, 83, +241, 227, 215, +264, 202, 347, +264, 267, 516, +264, 342, 673, +264, 342, 773, +264, 342, 879, +264, 342, 991, +145, 376, 1133, +0, 426, 1349, +0, 426, 1511, +347, 358, 1648, +625, 84, 1782, +1166, 111, 1896, +1526, 296, 2023, +1483, 566, 2172, +317, 1093, 2347, +1375, 639, 2469, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +182, 417, 0, +188, 413, 0, +197, 408, 0, +208, 401, 0, +222, 391, 83, +241, 378, 215, +264, 360, 347, +264, 407, 516, +264, 463, 673, +264, 529, 824, +264, 529, 920, +264, 529, 1023, +145, 552, 1156, +0, 570, 1364, +0, 559, 1522, +347, 509, 1653, +628, 326, 1786, +1159, 244, 1900, +1502, 428, 2029, +1443, 710, 2178, +265, 1128, 2349, +1420, 662, 2469, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +182, 552, 0, +188, 549, 0, +197, 545, 0, +208, 540, 0, +222, 533, 83, +241, 523, 215, +264, 510, 347, +264, 544, 516, +264, 586, 673, +264, 637, 824, +264, 698, 969, +264, 698, 1063, +145, 714, 1186, +0, 726, 1383, +0, 691, 1535, +347, 654, 1662, +628, 529, 1791, +1174, 422, 1906, +1467, 560, 2036, +1385, 851, 2187, +186, 1169, 2352, +1475, 691, 2469, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +182, 686, 0, +188, 684, 0, +197, 681, 0, +208, 677, 0, +222, 672, 83, +241, 665, 215, +264, 655, 347, +264, 681, 516, +264, 712, 673, +264, 752, 824, +264, 799, 969, +264, 856, 1111, +145, 867, 1223, +0, 876, 1407, +0, 823, 1553, +347, 796, 1675, +628, 708, 1798, +1200, 593, 1914, +1415, 692, 2046, +1292, 989, 2199, +0, 1212, 2357, +1539, 728, 2469, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +187, 854, 85, +163, 854, 130, +172, 852, 185, +183, 850, 248, +198, 846, 322, +218, 841, 404, +243, 835, 496, +243, 852, 623, +243, 874, 752, +243, 902, 881, +243, 936, 1011, +243, 979, 1142, +304, 1023, 1273, +0, 1029, 1441, +0, 983, 1578, +380, 954, 1697, +638, 909, 1812, +1217, 800, 1928, +1343, 849, 2058, +1151, 1127, 2212, +0, 1254, 2365, +1600, 800, 2469, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +436, 1164, 998, +421, 1164, 1004, +400, 1164, 1013, +371, 1164, 1024, +328, 1164, 1038, +265, 1164, 1056, +163, 1164, 1080, +163, 1164, 1099, +163, 1164, 1125, +163, 1170, 1168, +163, 1189, 1242, +163, 1214, 1325, +235, 1241, 1417, +417, 1228, 1503, +417, 1199, 1624, +478, 1204, 1746, +698, 1196, 1857, +1104, 1142, 1964, +1243, 1131, 2079, +1031, 1271, 2226, +750, 1297, 2370, +1600, 1018, 2470, +1773, 1121, 2512, +1773, 1121, 2512, +1773, 1121, 2512, +1773, 1121, 2512, +1773, 1121, 2512, +1773, 1121, 2512, +1773, 1121, 2512, +1773, 1121, 2512, +1773, 1121, 2512, +1773, 1121, 2512, +436, 1410, 1364, +421, 1410, 1367, +400, 1410, 1371, +371, 1410, 1376, +328, 1410, 1382, +265, 1410, 1391, +163, 1410, 1402, +163, 1410, 1412, +163, 1410, 1425, +163, 1410, 1442, +163, 1410, 1463, +163, 1410, 1491, +235, 1421, 1546, +417, 1412, 1612, +417, 1393, 1679, +478, 1400, 1791, +698, 1410, 1897, +1111, 1360, 2002, +1151, 1350, 2108, +878, 1405, 2242, +865, 1375, 2377, +1613, 1200, 2472, +1806, 1298, 2510, +1806, 1298, 2510, +1806, 1298, 2510, +1806, 1298, 2510, +1806, 1298, 2510, +1806, 1298, 2510, +1806, 1298, 2510, +1806, 1298, 2510, +1806, 1298, 2510, +1806, 1298, 2510, +1044, 1572, 1655, +1043, 1572, 1656, +1042, 1572, 1657, +1040, 1573, 1658, +1038, 1573, 1660, +1034, 1574, 1662, +1030, 1576, 1666, +1030, 1574, 1671, +1030, 1572, 1679, +1030, 1569, 1688, +1030, 1567, 1701, +1030, 1567, 1717, +1014, 1567, 1739, +958, 1573, 1783, +958, 1565, 1833, +977, 1552, 1891, +944, 1557, 1974, +1016, 1536, 2066, +990, 1537, 2170, +810, 1528, 2268, +1168, 1496, 2382, +1680, 1435, 2473, +1843, 1466, 2509, +1843, 1466, 2509, +1843, 1466, 2509, +1843, 1466, 2509, +1843, 1466, 2509, +1843, 1466, 2509, +1843, 1466, 2509, +1843, 1466, 2509, +1843, 1466, 2509, +1843, 1466, 2509, +1466, 1702, 1854, +1464, 1703, 1855, +1463, 1703, 1855, +1461, 1703, 1857, +1458, 1704, 1859, +1454, 1705, 1862, +1449, 1705, 1865, +1444, 1705, 1868, +1438, 1705, 1873, +1438, 1703, 1880, +1438, 1700, 1888, +1438, 1696, 1899, +1434, 1691, 1913, +1412, 1685, 1932, +1412, 1696, 1978, +1377, 1698, 2020, +1384, 1688, 2065, +1238, 1672, 2127, +1159, 1681, 2221, +1212, 1647, 2296, +1524, 1635, 2386, +1783, 1634, 2474, +1897, 1625, 2511, +1897, 1625, 2511, +1897, 1625, 2511, +1897, 1625, 2511, +1897, 1625, 2511, +1897, 1625, 2511, +1897, 1625, 2511, +1897, 1625, 2511, +1897, 1625, 2511, +1897, 1625, 2511, +1796, 1815, 1977, +1795, 1815, 1977, +1795, 1815, 1978, +1794, 1815, 1978, +1793, 1815, 1980, +1792, 1815, 1981, +1790, 1815, 1983, +1792, 1815, 1986, +1793, 1815, 1988, +1795, 1815, 1992, +1791, 1815, 1998, +1784, 1815, 2007, +1775, 1816, 2018, +1758, 1821, 2035, +1739, 1816, 2051, +1736, 1805, 2078, +1698, 1816, 2124, +1712, 1806, 2166, +1661, 1793, 2234, +1677, 1795, 2305, +1762, 1797, 2390, +1872, 1787, 2475, +1969, 1800, 2514, +1969, 1800, 2514, +1969, 1800, 2514, +1969, 1800, 2514, +1969, 1800, 2514, +1969, 1800, 2514, +1969, 1800, 2514, +1969, 1800, 2514, +1969, 1800, 2514, +1969, 1800, 2514, +1963, 1958, 2030, +1962, 1958, 2030, +1962, 1958, 2031, +1962, 1958, 2031, +1961, 1958, 2032, +1960, 1958, 2033, +1959, 1958, 2034, +1958, 1958, 2036, +1958, 1958, 2039, +1956, 1958, 2042, +1955, 1958, 2047, +1952, 1958, 2052, +1949, 1958, 2059, +1943, 1961, 2068, +1937, 1966, 2081, +1930, 1968, 2111, +1921, 1967, 2155, +1905, 1961, 2189, +1920, 1967, 2241, +1887, 1967, 2319, +1931, 1954, 2392, +2040, 1964, 2481, +2099, 1967, 2516, +2099, 1967, 2516, +2099, 1967, 2516, +2099, 1967, 2516, +2099, 1967, 2516, +2099, 1967, 2516, +2099, 1967, 2516, +2099, 1967, 2516, +2099, 1967, 2516, +2099, 1967, 2516, +2121, 2120, 2069, +2121, 2120, 2069, +2121, 2120, 2069, +2121, 2120, 2069, +2121, 2120, 2070, +2122, 2120, 2070, +2122, 2120, 2070, +2122, 2121, 2072, +2122, 2122, 2074, +2122, 2122, 2078, +2122, 2124, 2082, +2122, 2125, 2087, +2121, 2127, 2094, +2119, 2127, 2101, +2119, 2127, 2110, +2118, 2131, 2131, +2112, 2134, 2166, +2105, 2129, 2205, +2112, 2134, 2255, +2122, 2134, 2316, +2148, 2132, 2396, +2214, 2146, 2485, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2370, 2355, 2124, +2370, 2355, 2124, +2370, 2355, 2124, +2370, 2355, 2125, +2370, 2355, 2125, +2370, 2355, 2126, +2371, 2355, 2126, +2370, 2356, 2127, +2370, 2356, 2129, +2369, 2357, 2131, +2369, 2357, 2133, +2369, 2358, 2137, +2370, 2359, 2143, +2370, 2358, 2146, +2369, 2356, 2148, +2369, 2358, 2162, +2372, 2358, 2193, +2371, 2358, 2226, +2374, 2356, 2273, +2386, 2358, 2337, +2411, 2367, 2406, +2465, 2384, 2499, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2681, 2655, 1963, +2681, 2655, 1963, +2681, 2655, 1964, +2681, 2655, 1965, +2681, 2655, 1967, +2681, 2655, 1969, +2681, 2656, 1972, +2681, 2656, 1973, +2681, 2655, 1972, +2681, 2655, 1971, +2680, 2655, 1969, +2680, 2654, 1967, +2679, 2654, 1967, +2679, 2655, 1983, +2677, 2656, 2005, +2677, 2654, 2023, +2675, 2651, 2045, +2677, 2655, 2122, +2681, 2656, 2208, +2688, 2660, 2305, +2695, 2666, 2408, +2715, 2678, 2527, +2723, 2684, 2576, +2723, 2684, 2576, +2723, 2684, 2576, +2723, 2684, 2576, +2723, 2684, 2576, +2723, 2684, 2576, +2723, 2684, 2576, +2723, 2684, 2576, +2723, 2684, 2576, +2723, 2684, 2576, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2458, +2710, 2773, 2482, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2722, 2784, 2693, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2458, +2710, 2773, 2482, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2722, 2784, 2693, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2458, +2710, 2773, 2482, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2722, 2784, 2693, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2458, +2710, 2773, 2482, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2722, 2784, 2693, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2458, +2710, 2773, 2482, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2722, 2784, 2693, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2458, +2710, 2773, 2482, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2722, 2784, 2693, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2458, +2710, 2773, 2482, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2722, 2784, 2693, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2458, +2710, 2773, 2482, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2722, 2784, 2693, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2458, +2710, 2773, 2482, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2722, 2784, 2693, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2458, +2710, 2773, 2482, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2722, 2784, 2693, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +469, 0, 0, +469, 0, 0, +469, 0, 0, +469, 0, 0, +469, 0, 28, +469, 0, 152, +469, 0, 280, +469, 0, 408, +469, 0, 537, +469, 0, 667, +469, 0, 797, +469, 0, 928, +404, 0, 1088, +100, 0, 1333, +100, 0, 1501, +408, 0, 1634, +813, 0, 1779, +1202, 0, 1887, +1561, 0, 2010, +1542, 61, 2164, +352, 987, 2341, +1276, 570, 2469, +1737, 0, 2503, +1737, 0, 2503, +1737, 0, 2503, +1737, 0, 2503, +1737, 0, 2503, +1737, 0, 2503, +1737, 0, 2503, +1737, 0, 2503, +1737, 0, 2503, +1737, 0, 2503, +462, 0, 0, +465, 0, 0, +465, 0, 0, +465, 0, 0, +465, 0, 36, +465, 0, 159, +465, 0, 285, +465, 0, 412, +465, 0, 540, +465, 0, 669, +465, 0, 799, +465, 0, 930, +393, 0, 1089, +76, 0, 1333, +76, 0, 1501, +412, 0, 1635, +805, 0, 1779, +1201, 0, 1887, +1561, 0, 2011, +1541, 86, 2164, +352, 992, 2341, +1280, 573, 2469, +1736, 0, 2503, +1736, 0, 2503, +1736, 0, 2503, +1736, 0, 2503, +1736, 0, 2503, +1736, 0, 2503, +1736, 0, 2503, +1736, 0, 2503, +1736, 0, 2503, +1736, 0, 2503, +453, 0, 0, +456, 0, 0, +461, 0, 0, +461, 0, 0, +461, 0, 48, +461, 0, 168, +461, 0, 291, +461, 0, 417, +461, 0, 544, +461, 0, 672, +461, 0, 801, +461, 0, 931, +387, 0, 1090, +43, 0, 1334, +43, 0, 1501, +417, 0, 1635, +793, 0, 1778, +1200, 0, 1888, +1560, 0, 2011, +1539, 116, 2164, +352, 998, 2341, +1285, 577, 2469, +1736, 0, 2503, +1736, 0, 2503, +1736, 0, 2503, +1736, 0, 2503, +1736, 0, 2503, +1736, 0, 2503, +1736, 0, 2503, +1736, 0, 2503, +1736, 0, 2503, +1736, 0, 2503, +440, 0, 0, +444, 0, 0, +448, 0, 0, +455, 0, 0, +455, 0, 63, +455, 0, 180, +455, 0, 300, +455, 0, 424, +455, 0, 549, +455, 0, 676, +455, 0, 804, +455, 0, 933, +380, 0, 1091, +0, 0, 1335, +0, 0, 1502, +424, 0, 1636, +778, 0, 1778, +1199, 0, 1889, +1560, 0, 2012, +1537, 154, 2164, +352, 1005, 2342, +1292, 582, 2469, +1736, 0, 2504, +1736, 0, 2504, +1736, 0, 2504, +1736, 0, 2504, +1736, 0, 2504, +1736, 0, 2504, +1736, 0, 2504, +1736, 0, 2504, +1736, 0, 2504, +1736, 0, 2504, +422, 0, 0, +426, 0, 0, +431, 0, 0, +437, 0, 0, +446, 0, 83, +446, 0, 195, +446, 0, 312, +446, 0, 433, +446, 0, 556, +446, 0, 681, +446, 0, 808, +446, 0, 936, +370, 0, 1093, +0, 0, 1336, +0, 0, 1503, +433, 0, 1637, +757, 0, 1778, +1197, 0, 1889, +1559, 0, 2013, +1534, 201, 2165, +352, 1015, 2342, +1302, 588, 2469, +1735, 0, 2504, +1735, 0, 2504, +1735, 0, 2504, +1735, 0, 2504, +1735, 0, 2504, +1735, 0, 2504, +1735, 0, 2504, +1735, 0, 2504, +1735, 0, 2504, +1735, 0, 2504, +397, 0, 0, +401, 0, 0, +406, 0, 0, +413, 0, 0, +422, 0, 83, +434, 0, 215, +434, 0, 327, +434, 0, 444, +434, 0, 564, +434, 0, 688, +434, 0, 813, +434, 0, 940, +356, 0, 1096, +0, 30, 1338, +0, 30, 1504, +444, 0, 1639, +726, 0, 1777, +1195, 0, 1890, +1558, 0, 2015, +1530, 256, 2165, +352, 1028, 2343, +1314, 596, 2469, +1735, 30, 2504, +1735, 30, 2504, +1735, 30, 2504, +1735, 30, 2504, +1735, 30, 2504, +1735, 30, 2504, +1735, 30, 2504, +1735, 30, 2504, +1735, 30, 2504, +1735, 30, 2504, +362, 4, 0, +366, 0, 0, +371, 0, 0, +379, 0, 0, +389, 0, 83, +402, 0, 215, +418, 0, 347, +418, 0, 459, +418, 0, 576, +418, 0, 697, +418, 0, 820, +418, 0, 946, +337, 0, 1100, +0, 163, 1340, +0, 163, 1505, +459, 32, 1641, +682, 0, 1776, +1192, 0, 1891, +1557, 32, 2017, +1524, 322, 2166, +352, 1045, 2344, +1329, 607, 2469, +1734, 163, 2504, +1734, 163, 2504, +1734, 163, 2504, +1734, 163, 2504, +1734, 163, 2504, +1734, 163, 2504, +1734, 163, 2504, +1734, 163, 2504, +1734, 163, 2504, +1734, 163, 2504, +309, 144, 0, +314, 137, 0, +320, 127, 0, +329, 114, 0, +340, 96, 83, +354, 70, 215, +373, 34, 347, +396, 0, 479, +396, 0, 591, +396, 0, 708, +396, 0, 829, +396, 0, 952, +310, 52, 1105, +0, 295, 1343, +0, 295, 1507, +479, 164, 1644, +615, 0, 1775, +1188, 0, 1893, +1555, 164, 2019, +1516, 396, 2167, +352, 1066, 2345, +1349, 621, 2469, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +309, 281, 0, +314, 276, 0, +320, 269, 0, +329, 259, 0, +340, 246, 83, +354, 227, 215, +373, 202, 347, +396, 166, 479, +396, 257, 648, +396, 257, 752, +396, 257, 863, +396, 257, 978, +310, 298, 1124, +0, 426, 1354, +0, 426, 1515, +479, 333, 1648, +652, 0, 1779, +1183, 111, 1897, +1538, 296, 2024, +1489, 550, 2172, +317, 1093, 2347, +1385, 639, 2469, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +309, 417, 0, +314, 413, 0, +320, 408, 0, +329, 401, 0, +340, 391, 83, +354, 378, 215, +373, 360, 347, +396, 334, 479, +396, 399, 648, +396, 474, 805, +396, 474, 905, +396, 474, 1011, +310, 500, 1148, +0, 570, 1369, +0, 559, 1526, +479, 490, 1653, +655, 270, 1784, +1176, 244, 1901, +1514, 428, 2029, +1450, 699, 2178, +265, 1128, 2349, +1430, 662, 2469, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +309, 552, 0, +314, 549, 0, +320, 545, 0, +329, 540, 0, +340, 533, 83, +354, 523, 215, +373, 510, 347, +396, 492, 479, +396, 539, 648, +396, 595, 805, +396, 661, 955, +396, 661, 1052, +310, 678, 1178, +0, 726, 1388, +0, 691, 1539, +479, 640, 1662, +655, 494, 1789, +1191, 422, 1907, +1480, 560, 2037, +1393, 842, 2187, +186, 1169, 2352, +1483, 691, 2469, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +309, 686, 0, +314, 684, 0, +320, 681, 0, +329, 677, 0, +340, 672, 83, +354, 665, 215, +373, 655, 347, +396, 643, 479, +396, 677, 648, +396, 719, 805, +396, 770, 955, +396, 830, 1101, +310, 842, 1216, +0, 876, 1412, +0, 823, 1557, +479, 786, 1675, +655, 684, 1796, +1216, 593, 1915, +1430, 692, 2047, +1302, 983, 2199, +0, 1212, 2357, +1546, 728, 2469, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +313, 854, 85, +295, 854, 130, +302, 852, 185, +310, 850, 248, +322, 846, 322, +336, 841, 404, +356, 835, 496, +380, 826, 594, +380, 849, 730, +380, 878, 865, +380, 915, 1000, +380, 960, 1133, +426, 1005, 1267, +0, 1029, 1446, +0, 983, 1581, +504, 947, 1697, +664, 894, 1810, +1232, 800, 1928, +1359, 849, 2059, +1164, 1123, 2212, +0, 1254, 2365, +1607, 800, 2469, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +579, 1156, 985, +568, 1156, 992, +553, 1156, 1001, +532, 1156, 1012, +503, 1156, 1027, +461, 1156, 1045, +397, 1156, 1069, +295, 1156, 1099, +295, 1156, 1125, +295, 1161, 1168, +295, 1181, 1242, +295, 1207, 1325, +350, 1233, 1417, +549, 1224, 1507, +549, 1195, 1627, +610, 1196, 1748, +721, 1200, 1858, +1128, 1147, 1966, +1243, 1131, 2078, +1031, 1271, 2227, +827, 1290, 2369, +1605, 1012, 2470, +1776, 1112, 2512, +1776, 1112, 2512, +1776, 1112, 2512, +1776, 1112, 2512, +1776, 1112, 2512, +1776, 1112, 2512, +1776, 1112, 2512, +1776, 1112, 2512, +1776, 1112, 2512, +1776, 1112, 2512, +579, 1405, 1359, +568, 1405, 1361, +553, 1405, 1365, +532, 1405, 1370, +503, 1405, 1377, +461, 1405, 1386, +397, 1405, 1397, +295, 1405, 1412, +295, 1405, 1425, +295, 1405, 1442, +295, 1405, 1463, +295, 1405, 1491, +350, 1416, 1546, +549, 1410, 1615, +549, 1390, 1682, +610, 1395, 1793, +721, 1413, 1898, +1134, 1362, 2004, +1151, 1350, 2108, +878, 1405, 2243, +927, 1369, 2376, +1617, 1196, 2472, +1809, 1292, 2510, +1809, 1292, 2510, +1809, 1292, 2510, +1809, 1292, 2510, +1809, 1292, 2510, +1809, 1292, 2510, +1809, 1292, 2510, +1809, 1292, 2510, +1809, 1292, 2510, +1809, 1292, 2510, +1091, 1568, 1658, +1091, 1569, 1659, +1089, 1569, 1660, +1088, 1569, 1661, +1086, 1570, 1663, +1083, 1571, 1665, +1079, 1572, 1668, +1074, 1574, 1673, +1074, 1572, 1680, +1074, 1569, 1690, +1074, 1567, 1702, +1074, 1567, 1718, +1060, 1567, 1740, +984, 1571, 1781, +984, 1563, 1832, +1008, 1552, 1891, +990, 1557, 1977, +1050, 1536, 2065, +1008, 1537, 2170, +810, 1530, 2268, +1184, 1494, 2382, +1680, 1435, 2473, +1842, 1464, 2509, +1842, 1464, 2509, +1842, 1464, 2509, +1842, 1464, 2509, +1842, 1464, 2509, +1842, 1464, 2509, +1842, 1464, 2509, +1842, 1464, 2509, +1842, 1464, 2509, +1842, 1464, 2509, +1472, 1701, 1853, +1471, 1701, 1854, +1469, 1702, 1855, +1467, 1702, 1856, +1464, 1703, 1858, +1461, 1703, 1861, +1456, 1704, 1864, +1449, 1705, 1868, +1443, 1705, 1873, +1442, 1703, 1880, +1442, 1700, 1888, +1442, 1696, 1899, +1439, 1691, 1913, +1417, 1685, 1933, +1417, 1696, 1979, +1379, 1697, 2020, +1390, 1690, 2066, +1256, 1672, 2126, +1172, 1682, 2221, +1227, 1647, 2296, +1526, 1636, 2386, +1786, 1634, 2474, +1899, 1624, 2511, +1899, 1624, 2511, +1899, 1624, 2511, +1899, 1624, 2511, +1899, 1624, 2511, +1899, 1624, 2511, +1899, 1624, 2511, +1899, 1624, 2511, +1899, 1624, 2511, +1899, 1624, 2511, +1800, 1814, 1976, +1800, 1814, 1976, +1799, 1814, 1977, +1799, 1814, 1978, +1797, 1814, 1979, +1796, 1814, 1981, +1795, 1814, 1983, +1793, 1814, 1986, +1794, 1814, 1988, +1796, 1814, 1992, +1792, 1814, 1998, +1785, 1814, 2007, +1776, 1815, 2018, +1760, 1821, 2034, +1741, 1815, 2050, +1739, 1806, 2078, +1704, 1816, 2125, +1714, 1805, 2166, +1662, 1793, 2234, +1683, 1796, 2305, +1765, 1797, 2390, +1871, 1786, 2475, +1971, 1800, 2514, +1971, 1800, 2514, +1971, 1800, 2514, +1971, 1800, 2514, +1971, 1800, 2514, +1971, 1800, 2514, +1971, 1800, 2514, +1971, 1800, 2514, +1971, 1800, 2514, +1971, 1800, 2514, +1965, 1958, 2031, +1965, 1958, 2031, +1964, 1958, 2031, +1964, 1958, 2032, +1963, 1958, 2032, +1962, 1958, 2034, +1961, 1958, 2035, +1960, 1958, 2037, +1959, 1958, 2039, +1958, 1958, 2042, +1956, 1958, 2047, +1953, 1958, 2053, +1951, 1958, 2060, +1944, 1960, 2068, +1938, 1965, 2081, +1932, 1967, 2110, +1924, 1968, 2156, +1905, 1961, 2189, +1920, 1966, 2240, +1890, 1966, 2318, +1932, 1954, 2393, +2043, 1964, 2481, +2101, 1966, 2516, +2101, 1966, 2516, +2101, 1966, 2516, +2101, 1966, 2516, +2101, 1966, 2516, +2101, 1966, 2516, +2101, 1966, 2516, +2101, 1966, 2516, +2101, 1966, 2516, +2101, 1966, 2516, +2121, 2121, 2069, +2121, 2121, 2070, +2121, 2121, 2070, +2122, 2121, 2070, +2122, 2121, 2070, +2122, 2121, 2071, +2122, 2121, 2071, +2123, 2121, 2071, +2123, 2122, 2074, +2123, 2122, 2077, +2123, 2124, 2081, +2123, 2125, 2086, +2122, 2127, 2093, +2119, 2127, 2101, +2119, 2127, 2110, +2119, 2131, 2131, +2114, 2135, 2167, +2107, 2129, 2205, +2112, 2133, 2255, +2123, 2133, 2316, +2148, 2132, 2397, +2215, 2145, 2485, +2260, 2159, 2523, +2260, 2159, 2523, +2260, 2159, 2523, +2260, 2159, 2523, +2260, 2159, 2523, +2260, 2159, 2523, +2260, 2159, 2523, +2260, 2159, 2523, +2260, 2159, 2523, +2260, 2159, 2523, +2370, 2355, 2124, +2370, 2355, 2124, +2370, 2355, 2124, +2370, 2355, 2125, +2370, 2355, 2125, +2370, 2355, 2126, +2371, 2355, 2126, +2371, 2355, 2127, +2371, 2356, 2129, +2370, 2356, 2131, +2369, 2357, 2133, +2369, 2358, 2137, +2370, 2359, 2143, +2370, 2358, 2146, +2369, 2356, 2148, +2369, 2358, 2161, +2372, 2358, 2193, +2371, 2358, 2227, +2375, 2356, 2273, +2387, 2359, 2337, +2411, 2367, 2406, +2465, 2384, 2499, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2681, 2655, 1963, +2681, 2655, 1963, +2681, 2655, 1964, +2681, 2655, 1965, +2681, 2655, 1967, +2681, 2655, 1969, +2681, 2656, 1972, +2681, 2656, 1975, +2681, 2656, 1974, +2681, 2656, 1973, +2680, 2655, 1971, +2680, 2655, 1969, +2679, 2654, 1969, +2679, 2655, 1990, +2678, 2657, 2010, +2677, 2655, 2027, +2675, 2651, 2050, +2677, 2656, 2121, +2681, 2656, 2208, +2688, 2660, 2305, +2695, 2665, 2407, +2715, 2678, 2527, +2723, 2684, 2576, +2723, 2684, 2576, +2723, 2684, 2576, +2723, 2684, 2576, +2723, 2684, 2576, +2723, 2684, 2576, +2723, 2684, 2576, +2723, 2684, 2576, +2723, 2684, 2576, +2723, 2684, 2576, +2713, 2771, 2431, +2713, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2460, +2711, 2773, 2482, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2722, 2784, 2693, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2771, 2431, +2713, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2460, +2711, 2773, 2482, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2722, 2784, 2693, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2771, 2431, +2713, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2460, +2711, 2773, 2482, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2722, 2784, 2693, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2771, 2431, +2713, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2460, +2711, 2773, 2482, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2722, 2784, 2693, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2771, 2431, +2713, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2460, +2711, 2773, 2482, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2722, 2784, 2693, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2771, 2431, +2713, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2460, +2711, 2773, 2482, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2722, 2784, 2693, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2771, 2431, +2713, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2460, +2711, 2773, 2482, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2722, 2784, 2693, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2771, 2431, +2713, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2460, +2711, 2773, 2482, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2722, 2784, 2693, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2771, 2431, +2713, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2460, +2711, 2773, 2482, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2722, 2784, 2693, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2771, 2431, +2713, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2460, +2711, 2773, 2482, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2722, 2784, 2693, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +603, 0, 0, +603, 0, 0, +603, 0, 0, +603, 0, 0, +603, 0, 28, +603, 0, 152, +603, 0, 280, +603, 0, 408, +603, 0, 537, +603, 0, 667, +603, 0, 797, +603, 0, 928, +556, 0, 1088, +249, 0, 1348, +249, 0, 1511, +537, 0, 1634, +912, 0, 1782, +1222, 0, 1890, +1561, 0, 2012, +1535, 174, 2167, +317, 987, 2341, +1325, 528, 2469, +1738, 0, 2504, +1738, 0, 2504, +1738, 0, 2504, +1738, 0, 2504, +1738, 0, 2504, +1738, 0, 2504, +1738, 0, 2504, +1738, 0, 2504, +1738, 0, 2504, +1738, 0, 2504, +598, 0, 0, +601, 0, 0, +601, 0, 0, +601, 0, 0, +601, 0, 36, +601, 0, 159, +601, 0, 285, +601, 0, 412, +601, 0, 540, +601, 0, 669, +601, 0, 799, +601, 0, 930, +548, 0, 1089, +232, 0, 1349, +232, 0, 1511, +540, 0, 1635, +906, 0, 1782, +1221, 0, 1890, +1561, 0, 2013, +1534, 193, 2167, +317, 992, 2341, +1328, 531, 2469, +1738, 0, 2504, +1738, 0, 2504, +1738, 0, 2504, +1738, 0, 2504, +1738, 0, 2504, +1738, 0, 2504, +1738, 0, 2504, +1738, 0, 2504, +1738, 0, 2504, +1738, 0, 2504, +591, 0, 0, +594, 0, 0, +597, 0, 0, +597, 0, 0, +597, 0, 48, +597, 0, 168, +597, 0, 291, +597, 0, 417, +597, 0, 544, +597, 0, 672, +597, 0, 801, +597, 0, 931, +544, 0, 1090, +208, 0, 1349, +208, 0, 1512, +544, 0, 1635, +897, 0, 1781, +1221, 0, 1891, +1560, 0, 2013, +1532, 217, 2168, +317, 998, 2341, +1333, 535, 2469, +1738, 0, 2504, +1738, 0, 2504, +1738, 0, 2504, +1738, 0, 2504, +1738, 0, 2504, +1738, 0, 2504, +1738, 0, 2504, +1738, 0, 2504, +1738, 0, 2504, +1738, 0, 2504, +582, 0, 0, +585, 0, 0, +588, 0, 0, +593, 0, 0, +593, 0, 63, +593, 0, 180, +593, 0, 300, +593, 0, 424, +593, 0, 549, +593, 0, 676, +593, 0, 804, +593, 0, 933, +539, 0, 1091, +175, 0, 1351, +175, 0, 1512, +549, 0, 1636, +884, 0, 1781, +1220, 0, 1891, +1560, 0, 2014, +1530, 248, 2168, +317, 1005, 2342, +1339, 540, 2469, +1737, 0, 2504, +1737, 0, 2504, +1737, 0, 2504, +1737, 0, 2504, +1737, 0, 2504, +1737, 0, 2504, +1737, 0, 2504, +1737, 0, 2504, +1737, 0, 2504, +1737, 0, 2504, +569, 0, 0, +572, 0, 0, +575, 0, 0, +580, 0, 0, +586, 0, 83, +586, 0, 195, +586, 0, 312, +586, 0, 433, +586, 0, 556, +586, 0, 681, +586, 0, 808, +586, 0, 936, +532, 0, 1093, +125, 0, 1352, +125, 0, 1513, +556, 0, 1637, +867, 0, 1781, +1218, 0, 1891, +1559, 0, 2015, +1526, 286, 2168, +317, 1015, 2342, +1348, 547, 2469, +1737, 0, 2504, +1737, 0, 2504, +1737, 0, 2504, +1737, 0, 2504, +1737, 0, 2504, +1737, 0, 2504, +1737, 0, 2504, +1737, 0, 2504, +1737, 0, 2504, +1737, 0, 2504, +551, 0, 0, +554, 0, 0, +558, 0, 0, +563, 0, 0, +569, 0, 83, +578, 0, 215, +578, 0, 327, +578, 0, 444, +578, 0, 564, +578, 0, 688, +578, 0, 813, +578, 0, 940, +522, 0, 1096, +50, 30, 1353, +50, 30, 1514, +564, 0, 1639, +844, 0, 1780, +1216, 0, 1893, +1558, 0, 2017, +1522, 333, 2169, +317, 1028, 2343, +1359, 556, 2469, +1736, 30, 2504, +1736, 30, 2504, +1736, 30, 2504, +1736, 30, 2504, +1736, 30, 2504, +1736, 30, 2504, +1736, 30, 2504, +1736, 30, 2504, +1736, 30, 2504, +1736, 30, 2504, +526, 4, 0, +529, 0, 0, +533, 0, 0, +538, 0, 0, +545, 0, 83, +554, 0, 215, +566, 0, 347, +566, 0, 459, +566, 0, 576, +566, 0, 697, +566, 0, 820, +566, 0, 946, +509, 0, 1100, +0, 163, 1355, +0, 163, 1516, +576, 32, 1641, +810, 0, 1779, +1213, 0, 1894, +1557, 32, 2019, +1516, 388, 2170, +317, 1045, 2344, +1373, 568, 2469, +1735, 163, 2505, +1735, 163, 2505, +1735, 163, 2505, +1735, 163, 2505, +1735, 163, 2505, +1735, 163, 2505, +1735, 163, 2505, +1735, 163, 2505, +1735, 163, 2505, +1735, 163, 2505, +490, 144, 0, +494, 137, 0, +498, 127, 0, +504, 114, 0, +511, 96, 83, +521, 70, 215, +534, 34, 347, +550, 0, 479, +550, 0, 591, +550, 0, 708, +550, 0, 829, +550, 0, 952, +491, 52, 1105, +0, 295, 1358, +0, 295, 1518, +591, 164, 1644, +761, 0, 1778, +1209, 0, 1896, +1555, 164, 2021, +1508, 454, 2170, +317, 1066, 2345, +1391, 584, 2469, +1734, 295, 2505, +1734, 295, 2505, +1734, 295, 2505, +1734, 295, 2505, +1734, 295, 2505, +1734, 295, 2505, +1734, 295, 2505, +1734, 295, 2505, +1734, 295, 2505, +1734, 295, 2505, +438, 281, 0, +441, 276, 0, +446, 269, 0, +452, 259, 0, +461, 246, 83, +472, 227, 215, +486, 202, 347, +505, 166, 479, +528, 111, 611, +528, 111, 723, +528, 111, 840, +528, 111, 961, +465, 167, 1111, +0, 426, 1362, +0, 426, 1520, +611, 296, 1648, +685, 0, 1777, +1204, 111, 1898, +1552, 296, 2024, +1498, 528, 2172, +317, 1093, 2347, +1405, 655, 2469, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +438, 417, 0, +441, 413, 0, +446, 408, 0, +452, 401, 0, +461, 391, 83, +472, 378, 215, +486, 360, 347, +505, 334, 479, +528, 298, 611, +528, 390, 780, +528, 390, 884, +528, 390, 995, +465, 420, 1136, +0, 570, 1376, +0, 559, 1531, +611, 465, 1653, +688, 180, 1781, +1197, 244, 1902, +1529, 428, 2030, +1459, 683, 2178, +265, 1128, 2349, +1448, 678, 2469, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +438, 552, 0, +441, 549, 0, +446, 545, 0, +452, 540, 0, +461, 533, 83, +472, 523, 215, +486, 510, 347, +505, 492, 479, +528, 466, 611, +528, 532, 780, +528, 606, 937, +528, 606, 1037, +465, 626, 1167, +0, 726, 1395, +0, 691, 1544, +611, 622, 1662, +688, 441, 1786, +1211, 422, 1908, +1496, 560, 2038, +1403, 831, 2187, +186, 1169, 2352, +1499, 706, 2469, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +438, 686, 0, +441, 684, 0, +446, 681, 0, +452, 677, 0, +461, 672, 83, +472, 665, 215, +486, 655, 347, +505, 643, 479, +528, 624, 611, +528, 671, 780, +528, 728, 937, +528, 793, 1088, +465, 806, 1206, +0, 876, 1419, +0, 823, 1561, +611, 773, 1675, +688, 651, 1793, +1235, 593, 1916, +1448, 692, 2048, +1314, 975, 2199, +0, 1212, 2357, +1560, 742, 2469, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +441, 854, 85, +427, 854, 130, +432, 852, 185, +438, 850, 248, +447, 846, 322, +458, 841, 404, +473, 835, 496, +492, 826, 594, +516, 814, 700, +516, 845, 843, +516, 884, 983, +516, 932, 1121, +551, 980, 1257, +0, 1029, 1452, +0, 983, 1586, +630, 938, 1697, +697, 873, 1807, +1251, 800, 1930, +1381, 849, 2060, +1181, 1116, 2212, +0, 1254, 2365, +1619, 811, 2469, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +719, 1144, 968, +711, 1144, 975, +700, 1144, 984, +685, 1144, 996, +664, 1144, 1011, +635, 1144, 1030, +592, 1144, 1055, +529, 1144, 1086, +426, 1144, 1125, +426, 1150, 1168, +426, 1170, 1242, +426, 1196, 1325, +469, 1224, 1417, +681, 1219, 1512, +681, 1190, 1631, +741, 1186, 1751, +750, 1205, 1859, +1158, 1153, 1968, +1243, 1131, 2078, +1031, 1271, 2228, +914, 1282, 2369, +1608, 1020, 2470, +1781, 1099, 2512, +1781, 1099, 2512, +1781, 1099, 2512, +1781, 1099, 2512, +1781, 1099, 2512, +1781, 1099, 2512, +1781, 1099, 2512, +1781, 1099, 2512, +1781, 1099, 2512, +1781, 1099, 2512, +719, 1398, 1351, +711, 1398, 1354, +700, 1398, 1358, +685, 1398, 1363, +664, 1398, 1370, +635, 1398, 1379, +592, 1398, 1390, +529, 1398, 1406, +426, 1398, 1425, +426, 1398, 1442, +426, 1398, 1463, +426, 1398, 1491, +469, 1409, 1546, +681, 1406, 1619, +681, 1387, 1686, +741, 1388, 1796, +750, 1416, 1900, +1164, 1366, 2006, +1151, 1350, 2107, +878, 1405, 2243, +998, 1362, 2375, +1620, 1201, 2472, +1813, 1283, 2510, +1813, 1283, 2510, +1813, 1283, 2510, +1813, 1283, 2510, +1813, 1283, 2510, +1813, 1283, 2510, +1813, 1283, 2510, +1813, 1283, 2510, +1813, 1283, 2510, +1813, 1283, 2510, +1148, 1563, 1662, +1147, 1564, 1663, +1146, 1564, 1663, +1145, 1565, 1665, +1143, 1565, 1667, +1140, 1566, 1669, +1137, 1568, 1672, +1133, 1569, 1676, +1126, 1572, 1682, +1126, 1569, 1691, +1126, 1567, 1704, +1126, 1567, 1720, +1114, 1567, 1742, +1017, 1569, 1778, +1017, 1561, 1829, +1046, 1552, 1893, +1045, 1557, 1979, +1092, 1536, 2064, +1032, 1537, 2170, +810, 1533, 2268, +1205, 1491, 2382, +1680, 1432, 2474, +1841, 1461, 2509, +1841, 1461, 2509, +1841, 1461, 2509, +1841, 1461, 2509, +1841, 1461, 2509, +1841, 1461, 2509, +1841, 1461, 2509, +1841, 1461, 2509, +1841, 1461, 2509, +1841, 1461, 2509, +1481, 1699, 1851, +1480, 1700, 1852, +1478, 1700, 1853, +1476, 1700, 1855, +1473, 1701, 1857, +1470, 1702, 1859, +1465, 1703, 1863, +1458, 1704, 1867, +1449, 1705, 1873, +1448, 1703, 1880, +1448, 1700, 1888, +1448, 1696, 1899, +1445, 1691, 1913, +1423, 1685, 1934, +1423, 1696, 1979, +1383, 1695, 2019, +1396, 1691, 2067, +1278, 1672, 2126, +1188, 1684, 2221, +1246, 1647, 2296, +1529, 1638, 2386, +1793, 1636, 2474, +1901, 1622, 2511, +1901, 1622, 2511, +1901, 1622, 2511, +1901, 1622, 2511, +1901, 1622, 2511, +1901, 1622, 2511, +1901, 1622, 2511, +1901, 1622, 2511, +1901, 1622, 2511, +1901, 1622, 2511, +1805, 1813, 1975, +1805, 1813, 1975, +1805, 1813, 1976, +1804, 1813, 1977, +1803, 1813, 1978, +1802, 1813, 1979, +1800, 1813, 1982, +1798, 1813, 1984, +1796, 1813, 1988, +1797, 1813, 1992, +1793, 1813, 1998, +1787, 1813, 2007, +1777, 1813, 2018, +1763, 1819, 2033, +1745, 1813, 2049, +1744, 1807, 2077, +1710, 1816, 2126, +1718, 1804, 2166, +1664, 1793, 2234, +1690, 1798, 2306, +1770, 1797, 2390, +1871, 1786, 2475, +1974, 1800, 2514, +1974, 1800, 2514, +1974, 1800, 2514, +1974, 1800, 2514, +1974, 1800, 2514, +1974, 1800, 2514, +1974, 1800, 2514, +1974, 1800, 2514, +1974, 1800, 2514, +1974, 1800, 2514, +1968, 1958, 2031, +1968, 1958, 2031, +1967, 1958, 2032, +1967, 1958, 2032, +1966, 1958, 2033, +1965, 1958, 2034, +1964, 1958, 2036, +1963, 1958, 2038, +1961, 1958, 2040, +1960, 1958, 2043, +1958, 1958, 2048, +1955, 1958, 2054, +1953, 1958, 2061, +1945, 1959, 2068, +1939, 1964, 2081, +1934, 1966, 2107, +1928, 1969, 2157, +1905, 1959, 2189, +1920, 1965, 2239, +1893, 1965, 2317, +1933, 1954, 2393, +2043, 1964, 2481, +2104, 1965, 2515, +2104, 1965, 2515, +2104, 1965, 2515, +2104, 1965, 2515, +2104, 1965, 2515, +2104, 1965, 2515, +2104, 1965, 2515, +2104, 1965, 2515, +2104, 1965, 2515, +2104, 1965, 2515, +2122, 2122, 2070, +2122, 2122, 2070, +2122, 2122, 2071, +2122, 2122, 2071, +2122, 2122, 2071, +2123, 2122, 2071, +2123, 2122, 2072, +2124, 2122, 2072, +2124, 2122, 2073, +2124, 2122, 2076, +2124, 2124, 2080, +2124, 2125, 2086, +2124, 2127, 2093, +2119, 2127, 2101, +2119, 2127, 2110, +2120, 2131, 2130, +2116, 2135, 2169, +2108, 2128, 2204, +2113, 2132, 2254, +2124, 2133, 2316, +2148, 2133, 2397, +2216, 2146, 2485, +2260, 2159, 2522, +2260, 2159, 2522, +2260, 2159, 2522, +2260, 2159, 2522, +2260, 2159, 2522, +2260, 2159, 2522, +2260, 2159, 2522, +2260, 2159, 2522, +2260, 2159, 2522, +2260, 2159, 2522, +2370, 2355, 2124, +2370, 2355, 2124, +2370, 2355, 2124, +2370, 2355, 2125, +2370, 2355, 2125, +2370, 2355, 2126, +2371, 2355, 2126, +2371, 2355, 2127, +2371, 2355, 2129, +2371, 2356, 2131, +2370, 2357, 2133, +2370, 2357, 2137, +2371, 2358, 2143, +2370, 2358, 2146, +2369, 2356, 2148, +2370, 2358, 2161, +2373, 2358, 2193, +2372, 2358, 2227, +2376, 2357, 2273, +2388, 2360, 2337, +2411, 2367, 2406, +2465, 2385, 2499, +2496, 2392, 2532, +2496, 2392, 2532, +2496, 2392, 2532, +2496, 2392, 2532, +2496, 2392, 2532, +2496, 2392, 2532, +2496, 2392, 2532, +2496, 2392, 2532, +2496, 2392, 2532, +2496, 2392, 2532, +2680, 2654, 1962, +2680, 2655, 1962, +2681, 2655, 1963, +2681, 2655, 1964, +2681, 2655, 1966, +2681, 2655, 1968, +2681, 2656, 1970, +2681, 2656, 1974, +2681, 2656, 1972, +2681, 2655, 1970, +2680, 2655, 1969, +2680, 2654, 1966, +2679, 2654, 1967, +2679, 2655, 1987, +2677, 2657, 2008, +2677, 2656, 2029, +2675, 2652, 2050, +2677, 2656, 2121, +2681, 2656, 2208, +2688, 2660, 2306, +2695, 2665, 2407, +2715, 2678, 2527, +2724, 2684, 2577, +2724, 2684, 2577, +2724, 2684, 2577, +2724, 2684, 2577, +2724, 2684, 2577, +2724, 2684, 2577, +2724, 2684, 2577, +2724, 2684, 2577, +2724, 2684, 2577, +2724, 2684, 2577, +2713, 2771, 2430, +2713, 2771, 2430, +2713, 2771, 2430, +2714, 2771, 2430, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2432, +2715, 2770, 2435, +2716, 2769, 2439, +2714, 2769, 2444, +2711, 2772, 2462, +2711, 2773, 2481, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2723, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2771, 2430, +2713, 2771, 2430, +2713, 2771, 2430, +2714, 2771, 2430, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2432, +2715, 2770, 2435, +2716, 2769, 2439, +2714, 2769, 2444, +2711, 2772, 2462, +2711, 2773, 2481, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2723, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2771, 2430, +2713, 2771, 2430, +2713, 2771, 2430, +2714, 2771, 2430, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2432, +2715, 2770, 2435, +2716, 2769, 2439, +2714, 2769, 2444, +2711, 2772, 2462, +2711, 2773, 2481, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2723, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2771, 2430, +2713, 2771, 2430, +2713, 2771, 2430, +2714, 2771, 2430, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2432, +2715, 2770, 2435, +2716, 2769, 2439, +2714, 2769, 2444, +2711, 2772, 2462, +2711, 2773, 2481, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2723, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2771, 2430, +2713, 2771, 2430, +2713, 2771, 2430, +2714, 2771, 2430, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2432, +2715, 2770, 2435, +2716, 2769, 2439, +2714, 2769, 2444, +2711, 2772, 2462, +2711, 2773, 2481, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2723, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2771, 2430, +2713, 2771, 2430, +2713, 2771, 2430, +2714, 2771, 2430, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2432, +2715, 2770, 2435, +2716, 2769, 2439, +2714, 2769, 2444, +2711, 2772, 2462, +2711, 2773, 2481, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2723, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2771, 2430, +2713, 2771, 2430, +2713, 2771, 2430, +2714, 2771, 2430, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2432, +2715, 2770, 2435, +2716, 2769, 2439, +2714, 2769, 2444, +2711, 2772, 2462, +2711, 2773, 2481, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2723, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2771, 2430, +2713, 2771, 2430, +2713, 2771, 2430, +2714, 2771, 2430, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2432, +2715, 2770, 2435, +2716, 2769, 2439, +2714, 2769, 2444, +2711, 2772, 2462, +2711, 2773, 2481, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2723, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2771, 2430, +2713, 2771, 2430, +2713, 2771, 2430, +2714, 2771, 2430, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2432, +2715, 2770, 2435, +2716, 2769, 2439, +2714, 2769, 2444, +2711, 2772, 2462, +2711, 2773, 2481, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2723, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2771, 2430, +2713, 2771, 2430, +2713, 2771, 2430, +2714, 2771, 2430, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2432, +2715, 2770, 2435, +2716, 2769, 2439, +2714, 2769, 2444, +2711, 2772, 2462, +2711, 2773, 2481, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2723, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +737, 0, 0, +737, 0, 0, +737, 0, 0, +737, 0, 0, +737, 0, 28, +737, 0, 152, +737, 0, 280, +737, 0, 408, +737, 0, 537, +737, 0, 667, +737, 0, 797, +737, 0, 928, +703, 0, 1088, +438, 0, 1361, +394, 0, 1525, +667, 0, 1634, +977, 0, 1782, +1248, 0, 1893, +1561, 0, 2015, +1525, 291, 2172, +265, 987, 2341, +1385, 462, 2468, +1740, 0, 2504, +1740, 0, 2504, +1740, 0, 2504, +1740, 0, 2504, +1740, 0, 2504, +1740, 0, 2504, +1740, 0, 2504, +1740, 0, 2504, +1740, 0, 2504, +1740, 0, 2504, +734, 0, 0, +736, 0, 0, +736, 0, 0, +736, 0, 0, +736, 0, 36, +736, 0, 159, +736, 0, 285, +736, 0, 412, +736, 0, 540, +736, 0, 669, +736, 0, 799, +736, 0, 930, +697, 0, 1089, +427, 0, 1361, +381, 0, 1525, +669, 0, 1635, +971, 0, 1782, +1248, 0, 1893, +1561, 0, 2015, +1524, 306, 2173, +265, 992, 2341, +1388, 465, 2468, +1740, 0, 2504, +1740, 0, 2504, +1740, 0, 2504, +1740, 0, 2504, +1740, 0, 2504, +1740, 0, 2504, +1740, 0, 2504, +1740, 0, 2504, +1740, 0, 2504, +1740, 0, 2504, +729, 0, 0, +730, 0, 0, +733, 0, 0, +733, 0, 0, +733, 0, 48, +733, 0, 168, +733, 0, 291, +733, 0, 417, +733, 0, 544, +733, 0, 672, +733, 0, 801, +733, 0, 931, +694, 0, 1090, +412, 0, 1362, +365, 0, 1526, +672, 0, 1635, +963, 0, 1782, +1247, 0, 1894, +1560, 0, 2016, +1522, 325, 2173, +265, 998, 2341, +1392, 470, 2468, +1740, 0, 2504, +1740, 0, 2504, +1740, 0, 2504, +1740, 0, 2504, +1740, 0, 2504, +1740, 0, 2504, +1740, 0, 2504, +1740, 0, 2504, +1740, 0, 2504, +1740, 0, 2504, +722, 0, 0, +723, 0, 0, +726, 0, 0, +730, 0, 0, +730, 0, 63, +730, 0, 180, +730, 0, 300, +730, 0, 424, +730, 0, 549, +730, 0, 676, +730, 0, 804, +730, 0, 933, +690, 0, 1091, +391, 0, 1363, +341, 0, 1526, +676, 0, 1636, +953, 0, 1781, +1245, 0, 1894, +1560, 0, 2017, +1519, 349, 2173, +265, 1005, 2342, +1398, 476, 2468, +1739, 0, 2504, +1739, 0, 2504, +1739, 0, 2504, +1739, 0, 2504, +1739, 0, 2504, +1739, 0, 2504, +1739, 0, 2504, +1739, 0, 2504, +1739, 0, 2504, +1739, 0, 2504, +712, 0, 0, +714, 0, 0, +717, 0, 0, +720, 0, 0, +725, 0, 83, +725, 0, 195, +725, 0, 312, +725, 0, 433, +725, 0, 556, +725, 0, 681, +725, 0, 808, +725, 0, 936, +685, 0, 1093, +361, 0, 1364, +307, 0, 1527, +681, 0, 1637, +939, 0, 1781, +1244, 0, 1895, +1559, 0, 2018, +1516, 380, 2173, +265, 1015, 2342, +1405, 484, 2468, +1739, 0, 2505, +1739, 0, 2505, +1739, 0, 2505, +1739, 0, 2505, +1739, 0, 2505, +1739, 0, 2505, +1739, 0, 2505, +1739, 0, 2505, +1739, 0, 2505, +1739, 0, 2505, +699, 0, 0, +701, 0, 0, +704, 0, 0, +708, 0, 0, +712, 0, 83, +719, 0, 215, +719, 0, 327, +719, 0, 444, +719, 0, 564, +719, 0, 688, +719, 0, 813, +719, 0, 940, +678, 0, 1096, +317, 30, 1365, +258, 30, 1528, +688, 0, 1639, +918, 0, 1780, +1242, 0, 1896, +1558, 0, 2019, +1512, 419, 2174, +265, 1028, 2343, +1415, 494, 2468, +1738, 30, 2505, +1738, 30, 2505, +1738, 30, 2505, +1738, 30, 2505, +1738, 30, 2505, +1738, 30, 2505, +1738, 30, 2505, +1738, 30, 2505, +1738, 30, 2505, +1738, 30, 2505, +681, 4, 0, +683, 0, 0, +686, 0, 0, +690, 0, 0, +695, 0, 83, +702, 0, 215, +710, 0, 347, +710, 0, 459, +710, 0, 576, +710, 0, 697, +710, 0, 820, +710, 0, 946, +669, 0, 1100, +251, 163, 1367, +182, 163, 1530, +697, 32, 1641, +890, 0, 1779, +1239, 0, 1897, +1557, 32, 2021, +1506, 465, 2175, +265, 1045, 2344, +1427, 508, 2468, +1737, 163, 2505, +1737, 163, 2505, +1737, 163, 2505, +1737, 163, 2505, +1737, 163, 2505, +1737, 163, 2505, +1737, 163, 2505, +1737, 163, 2505, +1737, 163, 2505, +1737, 163, 2505, +656, 144, 0, +658, 137, 0, +661, 127, 0, +665, 114, 0, +670, 96, 83, +678, 70, 215, +686, 34, 347, +699, 0, 479, +699, 0, 591, +699, 0, 708, +699, 0, 829, +699, 0, 952, +656, 52, 1105, +145, 295, 1370, +56, 295, 1531, +708, 164, 1644, +849, 0, 1778, +1236, 0, 1899, +1555, 164, 2023, +1498, 521, 2175, +265, 1066, 2345, +1443, 526, 2468, +1736, 295, 2505, +1736, 295, 2505, +1736, 295, 2505, +1736, 295, 2505, +1736, 295, 2505, +1736, 295, 2505, +1736, 295, 2505, +1736, 295, 2505, +1736, 295, 2505, +1736, 295, 2505, +620, 281, 0, +623, 276, 0, +626, 269, 0, +630, 259, 0, +636, 246, 83, +643, 227, 215, +653, 202, 347, +666, 166, 479, +683, 111, 611, +683, 111, 723, +683, 111, 840, +683, 111, 961, +639, 167, 1111, +0, 426, 1374, +0, 426, 1534, +723, 296, 1648, +788, 0, 1777, +1231, 111, 1901, +1552, 296, 2027, +1487, 586, 2177, +265, 1093, 2347, +1456, 606, 2469, +1735, 426, 2506, +1735, 426, 2506, +1735, 426, 2506, +1735, 426, 2506, +1735, 426, 2506, +1735, 426, 2506, +1735, 426, 2506, +1735, 426, 2506, +1735, 426, 2506, +1735, 426, 2506, +567, 417, 0, +570, 413, 0, +573, 408, 0, +578, 401, 0, +585, 391, 83, +593, 378, 215, +604, 360, 347, +618, 334, 479, +637, 298, 611, +660, 244, 743, +660, 244, 856, +660, 244, 973, +614, 286, 1119, +0, 536, 1379, +0, 559, 1537, +743, 428, 1653, +797, 104, 1780, +1224, 244, 1904, +1549, 428, 2031, +1472, 660, 2178, +265, 1128, 2349, +1472, 699, 2469, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +567, 552, 0, +570, 549, 0, +573, 545, 0, +578, 540, 0, +585, 533, 83, +593, 523, 215, +604, 510, 347, +618, 492, 479, +637, 466, 611, +660, 430, 743, +660, 521, 912, +660, 521, 1017, +614, 545, 1152, +0, 703, 1397, +0, 691, 1550, +743, 597, 1662, +797, 399, 1786, +1238, 422, 1910, +1518, 560, 2039, +1417, 815, 2187, +186, 1169, 2352, +1521, 727, 2469, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +567, 686, 0, +570, 684, 0, +573, 681, 0, +578, 677, 0, +585, 672, 83, +593, 665, 215, +604, 655, 347, +618, 643, 479, +637, 624, 611, +660, 599, 743, +660, 664, 912, +660, 739, 1070, +614, 754, 1192, +0, 860, 1421, +0, 823, 1568, +743, 755, 1675, +797, 625, 1792, +1261, 593, 1918, +1472, 692, 2049, +1331, 963, 2199, +0, 1212, 2357, +1579, 761, 2469, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +569, 854, 85, +559, 854, 130, +563, 852, 185, +568, 850, 248, +574, 846, 322, +583, 841, 404, +594, 835, 496, +608, 826, 594, +627, 814, 700, +651, 797, 811, +651, 841, 960, +651, 893, 1104, +678, 945, 1245, +0, 1017, 1454, +0, 983, 1592, +758, 925, 1697, +804, 857, 1807, +1275, 800, 1931, +1408, 849, 2061, +1203, 1108, 2212, +0, 1254, 2365, +1635, 828, 2469, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +834, 1134, 954, +827, 1134, 961, +819, 1134, 970, +808, 1134, 982, +792, 1134, 998, +770, 1134, 1018, +739, 1134, 1043, +693, 1134, 1075, +625, 1134, 1115, +570, 1131, 1163, +570, 1152, 1237, +570, 1179, 1321, +601, 1208, 1413, +800, 1208, 1514, +767, 1185, 1636, +863, 1174, 1754, +863, 1195, 1861, +1192, 1157, 1970, +1257, 1131, 2078, +1043, 1269, 2229, +975, 1275, 2368, +1616, 1030, 2470, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +857, 1389, 1341, +851, 1389, 1344, +843, 1389, 1348, +832, 1389, 1353, +817, 1389, 1360, +797, 1389, 1369, +767, 1389, 1381, +725, 1389, 1397, +661, 1389, 1417, +559, 1389, 1442, +559, 1389, 1463, +559, 1389, 1491, +591, 1400, 1546, +794, 1400, 1623, +813, 1382, 1691, +874, 1379, 1799, +874, 1408, 1902, +1201, 1371, 2008, +1151, 1350, 2106, +878, 1405, 2245, +1078, 1352, 2375, +1623, 1208, 2472, +1819, 1270, 2510, +1819, 1270, 2510, +1819, 1270, 2510, +1819, 1270, 2510, +1819, 1270, 2510, +1819, 1270, 2510, +1819, 1270, 2510, +1819, 1270, 2510, +1819, 1270, 2510, +1819, 1270, 2510, +1214, 1557, 1667, +1213, 1557, 1668, +1212, 1558, 1669, +1211, 1558, 1670, +1209, 1559, 1672, +1207, 1560, 1674, +1205, 1561, 1677, +1201, 1563, 1681, +1195, 1565, 1686, +1188, 1569, 1694, +1188, 1567, 1706, +1188, 1567, 1722, +1177, 1567, 1744, +1072, 1567, 1776, +1057, 1558, 1825, +1094, 1552, 1894, +1094, 1557, 1981, +1142, 1536, 2063, +1061, 1537, 2170, +810, 1536, 2268, +1232, 1487, 2382, +1680, 1427, 2474, +1839, 1457, 2509, +1839, 1457, 2509, +1839, 1457, 2509, +1839, 1457, 2509, +1839, 1457, 2509, +1839, 1457, 2509, +1839, 1457, 2509, +1839, 1457, 2509, +1839, 1457, 2509, +1839, 1457, 2509, +1512, 1695, 1855, +1511, 1695, 1855, +1510, 1695, 1856, +1508, 1696, 1858, +1505, 1696, 1860, +1502, 1697, 1862, +1497, 1698, 1866, +1491, 1699, 1870, +1482, 1701, 1876, +1478, 1703, 1881, +1478, 1700, 1889, +1478, 1696, 1900, +1475, 1691, 1914, +1446, 1684, 1934, +1440, 1693, 1977, +1405, 1695, 2020, +1418, 1691, 2069, +1312, 1672, 2125, +1209, 1684, 2221, +1248, 1649, 2296, +1541, 1636, 2386, +1794, 1633, 2475, +1900, 1619, 2511, +1900, 1619, 2511, +1900, 1619, 2511, +1900, 1619, 2511, +1900, 1619, 2511, +1900, 1619, 2511, +1900, 1619, 2511, +1900, 1619, 2511, +1900, 1619, 2511, +1900, 1619, 2511, +1813, 1811, 1973, +1812, 1811, 1974, +1812, 1811, 1975, +1811, 1811, 1976, +1810, 1811, 1977, +1809, 1811, 1978, +1808, 1811, 1981, +1806, 1811, 1983, +1803, 1811, 1987, +1799, 1811, 1992, +1795, 1811, 1998, +1789, 1811, 2007, +1779, 1812, 2018, +1767, 1817, 2033, +1749, 1812, 2048, +1751, 1809, 2076, +1717, 1818, 2125, +1722, 1802, 2166, +1667, 1793, 2234, +1699, 1800, 2306, +1776, 1797, 2391, +1871, 1786, 2475, +1978, 1800, 2515, +1978, 1800, 2515, +1978, 1800, 2515, +1978, 1800, 2515, +1978, 1800, 2515, +1978, 1800, 2515, +1978, 1800, 2515, +1978, 1800, 2515, +1978, 1800, 2515, +1978, 1800, 2515, +1972, 1958, 2032, +1972, 1958, 2033, +1971, 1958, 2033, +1971, 1958, 2034, +1970, 1958, 2034, +1969, 1958, 2036, +1968, 1958, 2037, +1967, 1958, 2039, +1965, 1958, 2041, +1962, 1958, 2045, +1961, 1958, 2049, +1958, 1958, 2055, +1955, 1958, 2062, +1947, 1958, 2069, +1940, 1963, 2081, +1937, 1965, 2105, +1931, 1968, 2155, +1905, 1958, 2189, +1920, 1964, 2238, +1898, 1964, 2316, +1934, 1954, 2393, +2043, 1964, 2481, +2108, 1964, 2515, +2108, 1964, 2515, +2108, 1964, 2515, +2108, 1964, 2515, +2108, 1964, 2515, +2108, 1964, 2515, +2108, 1964, 2515, +2108, 1964, 2515, +2108, 1964, 2515, +2108, 1964, 2515, +2123, 2122, 2071, +2123, 2122, 2071, +2123, 2122, 2071, +2123, 2122, 2072, +2124, 2122, 2072, +2124, 2122, 2072, +2124, 2122, 2073, +2125, 2122, 2073, +2125, 2122, 2074, +2126, 2122, 2075, +2126, 2124, 2079, +2126, 2125, 2085, +2125, 2127, 2092, +2119, 2127, 2101, +2119, 2127, 2110, +2122, 2131, 2129, +2118, 2135, 2168, +2110, 2127, 2203, +2114, 2132, 2254, +2126, 2132, 2316, +2148, 2134, 2399, +2218, 2147, 2485, +2259, 2159, 2522, +2259, 2159, 2522, +2259, 2159, 2522, +2259, 2159, 2522, +2259, 2159, 2522, +2259, 2159, 2522, +2259, 2159, 2522, +2259, 2159, 2522, +2259, 2159, 2522, +2259, 2159, 2522, +2370, 2355, 2124, +2370, 2355, 2124, +2370, 2355, 2124, +2370, 2355, 2125, +2370, 2355, 2125, +2370, 2355, 2126, +2371, 2355, 2126, +2371, 2355, 2127, +2371, 2355, 2129, +2372, 2355, 2131, +2371, 2356, 2133, +2372, 2357, 2137, +2372, 2358, 2143, +2371, 2358, 2146, +2369, 2356, 2148, +2370, 2358, 2160, +2373, 2358, 2193, +2373, 2358, 2228, +2377, 2357, 2273, +2391, 2362, 2337, +2412, 2367, 2407, +2466, 2386, 2499, +2496, 2392, 2532, +2496, 2392, 2532, +2496, 2392, 2532, +2496, 2392, 2532, +2496, 2392, 2532, +2496, 2392, 2532, +2496, 2392, 2532, +2496, 2392, 2532, +2496, 2392, 2532, +2496, 2392, 2532, +2680, 2654, 1961, +2680, 2654, 1961, +2680, 2654, 1962, +2680, 2654, 1963, +2680, 2655, 1965, +2680, 2655, 1966, +2681, 2655, 1969, +2681, 2656, 1973, +2681, 2655, 1970, +2680, 2654, 1966, +2680, 2654, 1965, +2679, 2653, 1962, +2679, 2653, 1963, +2678, 2655, 1982, +2677, 2657, 2003, +2678, 2657, 2033, +2676, 2653, 2053, +2678, 2656, 2122, +2681, 2656, 2208, +2688, 2660, 2306, +2695, 2665, 2407, +2715, 2678, 2527, +2724, 2684, 2577, +2724, 2684, 2577, +2724, 2684, 2577, +2724, 2684, 2577, +2724, 2684, 2577, +2724, 2684, 2577, +2724, 2684, 2577, +2724, 2684, 2577, +2724, 2684, 2577, +2724, 2684, 2577, +2713, 2770, 2430, +2713, 2770, 2430, +2713, 2770, 2430, +2713, 2770, 2430, +2713, 2770, 2430, +2714, 2770, 2430, +2714, 2770, 2430, +2714, 2770, 2431, +2715, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2432, +2715, 2770, 2435, +2716, 2769, 2439, +2714, 2769, 2444, +2711, 2772, 2462, +2712, 2773, 2481, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2723, 2785, 2695, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2770, 2430, +2713, 2770, 2430, +2713, 2770, 2430, +2713, 2770, 2430, +2713, 2770, 2430, +2714, 2770, 2430, +2714, 2770, 2430, +2714, 2770, 2431, +2715, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2432, +2715, 2770, 2435, +2716, 2769, 2439, +2714, 2769, 2444, +2711, 2772, 2462, +2712, 2773, 2481, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2723, 2785, 2695, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2770, 2430, +2713, 2770, 2430, +2713, 2770, 2430, +2713, 2770, 2430, +2713, 2770, 2430, +2714, 2770, 2430, +2714, 2770, 2430, +2714, 2770, 2431, +2715, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2432, +2715, 2770, 2435, +2716, 2769, 2439, +2714, 2769, 2444, +2711, 2772, 2462, +2712, 2773, 2481, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2723, 2785, 2695, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2770, 2430, +2713, 2770, 2430, +2713, 2770, 2430, +2713, 2770, 2430, +2713, 2770, 2430, +2714, 2770, 2430, +2714, 2770, 2430, +2714, 2770, 2431, +2715, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2432, +2715, 2770, 2435, +2716, 2769, 2439, +2714, 2769, 2444, +2711, 2772, 2462, +2712, 2773, 2481, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2723, 2785, 2695, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2770, 2430, +2713, 2770, 2430, +2713, 2770, 2430, +2713, 2770, 2430, +2713, 2770, 2430, +2714, 2770, 2430, +2714, 2770, 2430, +2714, 2770, 2431, +2715, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2432, +2715, 2770, 2435, +2716, 2769, 2439, +2714, 2769, 2444, +2711, 2772, 2462, +2712, 2773, 2481, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2723, 2785, 2695, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2770, 2430, +2713, 2770, 2430, +2713, 2770, 2430, +2713, 2770, 2430, +2713, 2770, 2430, +2714, 2770, 2430, +2714, 2770, 2430, +2714, 2770, 2431, +2715, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2432, +2715, 2770, 2435, +2716, 2769, 2439, +2714, 2769, 2444, +2711, 2772, 2462, +2712, 2773, 2481, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2723, 2785, 2695, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2770, 2430, +2713, 2770, 2430, +2713, 2770, 2430, +2713, 2770, 2430, +2713, 2770, 2430, +2714, 2770, 2430, +2714, 2770, 2430, +2714, 2770, 2431, +2715, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2432, +2715, 2770, 2435, +2716, 2769, 2439, +2714, 2769, 2444, +2711, 2772, 2462, +2712, 2773, 2481, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2723, 2785, 2695, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2770, 2430, +2713, 2770, 2430, +2713, 2770, 2430, +2713, 2770, 2430, +2713, 2770, 2430, +2714, 2770, 2430, +2714, 2770, 2430, +2714, 2770, 2431, +2715, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2432, +2715, 2770, 2435, +2716, 2769, 2439, +2714, 2769, 2444, +2711, 2772, 2462, +2712, 2773, 2481, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2723, 2785, 2695, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2770, 2430, +2713, 2770, 2430, +2713, 2770, 2430, +2713, 2770, 2430, +2713, 2770, 2430, +2714, 2770, 2430, +2714, 2770, 2430, +2714, 2770, 2431, +2715, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2432, +2715, 2770, 2435, +2716, 2769, 2439, +2714, 2769, 2444, +2711, 2772, 2462, +2712, 2773, 2481, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2723, 2785, 2695, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2770, 2430, +2713, 2770, 2430, +2713, 2770, 2430, +2713, 2770, 2430, +2713, 2770, 2430, +2714, 2770, 2430, +2714, 2770, 2430, +2714, 2770, 2431, +2715, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2432, +2715, 2770, 2435, +2716, 2769, 2439, +2714, 2769, 2444, +2711, 2772, 2462, +2712, 2773, 2481, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2723, 2785, 2695, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +871, 0, 0, +871, 0, 0, +871, 0, 0, +871, 0, 0, +871, 0, 28, +871, 0, 152, +871, 0, 280, +871, 0, 408, +871, 0, 537, +871, 0, 667, +871, 0, 797, +871, 0, 928, +845, 0, 1088, +668, 0, 1361, +535, 0, 1543, +769, 0, 1643, +1048, 0, 1782, +1313, 0, 1897, +1561, 0, 2018, +1511, 412, 2179, +186, 987, 2341, +1454, 356, 2467, +1743, 0, 2505, +1743, 0, 2505, +1743, 0, 2505, +1743, 0, 2505, +1743, 0, 2505, +1743, 0, 2505, +1743, 0, 2505, +1743, 0, 2505, +1743, 0, 2505, +1743, 0, 2505, +868, 0, 0, +869, 0, 0, +869, 0, 0, +869, 0, 0, +869, 0, 36, +869, 0, 159, +869, 0, 285, +869, 0, 412, +869, 0, 540, +869, 0, 669, +869, 0, 799, +869, 0, 930, +841, 0, 1089, +662, 0, 1361, +526, 0, 1543, +770, 0, 1643, +1043, 0, 1782, +1313, 0, 1897, +1561, 0, 2018, +1510, 423, 2179, +186, 992, 2341, +1457, 360, 2467, +1743, 0, 2505, +1743, 0, 2505, +1743, 0, 2505, +1743, 0, 2505, +1743, 0, 2505, +1743, 0, 2505, +1743, 0, 2505, +1743, 0, 2505, +1743, 0, 2505, +1743, 0, 2505, +864, 0, 0, +866, 0, 0, +868, 0, 0, +868, 0, 0, +868, 0, 48, +868, 0, 168, +868, 0, 291, +868, 0, 417, +868, 0, 544, +868, 0, 672, +868, 0, 801, +868, 0, 931, +839, 0, 1090, +653, 0, 1362, +513, 0, 1544, +773, 0, 1644, +1036, 0, 1782, +1312, 0, 1897, +1560, 0, 2019, +1508, 438, 2179, +186, 998, 2341, +1461, 366, 2467, +1743, 0, 2505, +1743, 0, 2505, +1743, 0, 2505, +1743, 0, 2505, +1743, 0, 2505, +1743, 0, 2505, +1743, 0, 2505, +1743, 0, 2505, +1743, 0, 2505, +1743, 0, 2505, +859, 0, 0, +861, 0, 0, +862, 0, 0, +865, 0, 0, +865, 0, 63, +865, 0, 180, +865, 0, 300, +865, 0, 424, +865, 0, 549, +865, 0, 676, +865, 0, 804, +865, 0, 933, +836, 0, 1091, +640, 0, 1363, +496, 0, 1544, +776, 0, 1645, +1027, 0, 1781, +1311, 0, 1898, +1560, 0, 2020, +1505, 457, 2180, +186, 1005, 2342, +1465, 373, 2467, +1742, 0, 2505, +1742, 0, 2505, +1742, 0, 2505, +1742, 0, 2505, +1742, 0, 2505, +1742, 0, 2505, +1742, 0, 2505, +1742, 0, 2505, +1742, 0, 2505, +1742, 0, 2505, +852, 0, 0, +854, 0, 0, +856, 0, 0, +858, 0, 0, +862, 0, 83, +862, 0, 195, +862, 0, 312, +862, 0, 433, +862, 0, 556, +862, 0, 681, +862, 0, 808, +862, 0, 936, +833, 0, 1093, +623, 0, 1364, +473, 0, 1545, +780, 0, 1646, +1015, 0, 1781, +1310, 0, 1899, +1559, 0, 2021, +1502, 482, 2180, +186, 1015, 2342, +1472, 383, 2467, +1742, 0, 2505, +1742, 0, 2505, +1742, 0, 2505, +1742, 0, 2505, +1742, 0, 2505, +1742, 0, 2505, +1742, 0, 2505, +1742, 0, 2505, +1742, 0, 2505, +1742, 0, 2505, +843, 0, 0, +844, 0, 0, +846, 0, 0, +849, 0, 0, +852, 0, 83, +857, 0, 215, +857, 0, 327, +857, 0, 444, +857, 0, 564, +857, 0, 688, +857, 0, 813, +857, 0, 940, +827, 0, 1096, +599, 30, 1365, +439, 30, 1546, +785, 0, 1648, +998, 0, 1780, +1308, 0, 1900, +1558, 0, 2022, +1497, 512, 2180, +186, 1028, 2343, +1480, 397, 2467, +1741, 30, 2505, +1741, 30, 2505, +1741, 30, 2505, +1741, 30, 2505, +1741, 30, 2505, +1741, 30, 2505, +1741, 30, 2505, +1741, 30, 2505, +1741, 30, 2505, +1741, 30, 2505, +830, 4, 0, +831, 0, 0, +833, 0, 0, +836, 0, 0, +839, 0, 83, +844, 0, 215, +851, 0, 347, +851, 0, 459, +851, 0, 576, +851, 0, 697, +851, 0, 820, +851, 0, 946, +821, 0, 1100, +565, 163, 1367, +390, 163, 1547, +793, 32, 1650, +974, 0, 1779, +1306, 0, 1901, +1557, 32, 2024, +1491, 551, 2181, +186, 1045, 2344, +1491, 413, 2467, +1740, 163, 2506, +1740, 163, 2506, +1740, 163, 2506, +1740, 163, 2506, +1740, 163, 2506, +1740, 163, 2506, +1740, 163, 2506, +1740, 163, 2506, +1740, 163, 2506, +1740, 163, 2506, +812, 144, 0, +813, 137, 0, +815, 127, 0, +818, 114, 0, +822, 96, 83, +827, 70, 215, +834, 34, 347, +842, 0, 479, +842, 0, 591, +842, 0, 708, +842, 0, 829, +842, 0, 952, +812, 52, 1105, +515, 295, 1370, +314, 295, 1549, +802, 164, 1653, +940, 0, 1778, +1302, 0, 1903, +1555, 164, 2027, +1483, 597, 2182, +186, 1066, 2345, +1505, 435, 2467, +1739, 295, 2506, +1739, 295, 2506, +1739, 295, 2506, +1739, 295, 2506, +1739, 295, 2506, +1739, 295, 2506, +1739, 295, 2506, +1739, 295, 2506, +1739, 295, 2506, +1739, 295, 2506, +787, 281, 0, +788, 276, 0, +790, 269, 0, +793, 259, 0, +797, 246, 83, +803, 227, 215, +809, 202, 347, +819, 166, 479, +831, 111, 611, +831, 111, 723, +831, 111, 840, +831, 111, 961, +799, 167, 1111, +438, 426, 1374, +188, 426, 1552, +814, 296, 1657, +891, 0, 1777, +1298, 111, 1905, +1552, 296, 2030, +1472, 653, 2183, +186, 1093, 2347, +1516, 532, 2467, +1738, 426, 2507, +1738, 426, 2507, +1738, 426, 2507, +1738, 426, 2507, +1738, 426, 2507, +1738, 426, 2507, +1738, 426, 2507, +1738, 426, 2507, +1738, 426, 2507, +1738, 426, 2507, +750, 417, 0, +752, 413, 0, +755, 408, 0, +758, 401, 0, +762, 391, 83, +768, 378, 215, +775, 360, 347, +785, 334, 479, +798, 298, 611, +815, 244, 743, +815, 244, 856, +815, 244, 973, +782, 286, 1119, +345, 536, 1379, +0, 559, 1555, +831, 428, 1662, +899, 104, 1780, +1292, 244, 1908, +1549, 428, 2034, +1456, 718, 2185, +186, 1128, 2349, +1530, 640, 2468, +1736, 559, 2508, +1736, 559, 2508, +1736, 559, 2508, +1736, 559, 2508, +1736, 559, 2508, +1736, 559, 2508, +1736, 559, 2508, +1736, 559, 2508, +1736, 559, 2508, +1736, 559, 2508, +697, 552, 0, +699, 549, 0, +702, 545, 0, +705, 540, 0, +710, 533, 83, +717, 523, 215, +725, 510, 347, +736, 492, 479, +750, 466, 611, +769, 430, 743, +792, 376, 875, +792, 376, 988, +758, 407, 1131, +280, 611, 1385, +0, 691, 1559, +799, 583, 1666, +916, 342, 1786, +1257, 324, 1907, +1545, 560, 2040, +1434, 792, 2187, +186, 1169, 2352, +1547, 752, 2469, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +697, 686, 0, +699, 684, 0, +702, 681, 0, +705, 677, 0, +710, 672, 83, +717, 665, 215, +725, 655, 347, +736, 643, 479, +750, 624, 611, +769, 599, 743, +792, 562, 875, +792, 654, 1044, +758, 672, 1172, +280, 796, 1409, +0, 823, 1576, +799, 745, 1680, +916, 591, 1792, +1279, 529, 1915, +1502, 692, 2050, +1352, 947, 2199, +0, 1212, 2357, +1603, 785, 2469, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +699, 854, 85, +691, 854, 130, +694, 852, 185, +698, 850, 248, +702, 846, 322, +709, 841, 404, +717, 835, 496, +728, 826, 594, +743, 814, 700, +762, 797, 811, +786, 774, 927, +786, 834, 1081, +805, 893, 1228, +403, 973, 1443, +0, 983, 1599, +812, 918, 1701, +921, 837, 1807, +1293, 760, 1928, +1442, 849, 2062, +1230, 1096, 2212, +0, 1254, 2365, +1657, 848, 2469, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +910, 1134, 954, +905, 1134, 961, +898, 1134, 970, +889, 1134, 982, +875, 1134, 998, +857, 1134, 1018, +832, 1134, 1043, +795, 1134, 1075, +741, 1134, 1115, +699, 1131, 1163, +726, 1120, 1220, +726, 1149, 1307, +748, 1179, 1402, +901, 1179, 1504, +767, 1185, 1644, +906, 1170, 1757, +968, 1186, 1861, +1214, 1140, 1967, +1304, 1131, 2079, +1082, 1261, 2229, +975, 1275, 2368, +1638, 1044, 2470, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +993, 1376, 1327, +989, 1376, 1330, +983, 1376, 1334, +975, 1376, 1340, +964, 1376, 1347, +949, 1376, 1356, +928, 1376, 1368, +899, 1376, 1385, +857, 1376, 1405, +793, 1376, 1431, +691, 1376, 1463, +691, 1376, 1491, +715, 1388, 1546, +877, 1388, 1623, +945, 1376, 1697, +997, 1370, 1804, +1006, 1396, 1906, +1223, 1377, 2010, +1151, 1350, 2105, +878, 1405, 2247, +1167, 1339, 2373, +1626, 1218, 2473, +1826, 1254, 2510, +1826, 1254, 2510, +1826, 1254, 2510, +1826, 1254, 2510, +1826, 1254, 2510, +1826, 1254, 2510, +1826, 1254, 2510, +1826, 1254, 2510, +1826, 1254, 2510, +1826, 1254, 2510, +1284, 1548, 1666, +1284, 1549, 1666, +1283, 1549, 1667, +1282, 1550, 1668, +1281, 1550, 1670, +1279, 1551, 1673, +1276, 1553, 1675, +1273, 1555, 1680, +1269, 1557, 1685, +1263, 1560, 1692, +1239, 1562, 1707, +1239, 1562, 1723, +1229, 1562, 1745, +1136, 1562, 1777, +1127, 1554, 1826, +1162, 1550, 1897, +1168, 1552, 1984, +1181, 1539, 2065, +1075, 1537, 2169, +810, 1538, 2270, +1285, 1479, 2381, +1681, 1429, 2475, +1842, 1448, 2509, +1842, 1448, 2509, +1842, 1448, 2509, +1842, 1448, 2509, +1842, 1448, 2509, +1842, 1448, 2509, +1842, 1448, 2509, +1842, 1448, 2509, +1842, 1448, 2509, +1842, 1448, 2509, +1553, 1689, 1859, +1552, 1689, 1860, +1551, 1689, 1861, +1549, 1690, 1862, +1547, 1690, 1864, +1544, 1691, 1867, +1539, 1692, 1870, +1534, 1693, 1874, +1526, 1695, 1880, +1522, 1697, 1885, +1517, 1700, 1891, +1517, 1696, 1902, +1515, 1691, 1916, +1488, 1684, 1935, +1461, 1690, 1974, +1430, 1693, 2019, +1446, 1691, 2070, +1360, 1672, 2128, +1236, 1684, 2221, +1248, 1653, 2296, +1559, 1632, 2386, +1794, 1630, 2475, +1898, 1615, 2511, +1898, 1615, 2511, +1898, 1615, 2511, +1898, 1615, 2511, +1898, 1615, 2511, +1898, 1615, 2511, +1898, 1615, 2511, +1898, 1615, 2511, +1898, 1615, 2511, +1898, 1615, 2511, +1821, 1809, 1972, +1820, 1809, 1972, +1820, 1809, 1973, +1819, 1809, 1974, +1818, 1809, 1975, +1817, 1809, 1977, +1816, 1809, 1979, +1813, 1809, 1982, +1811, 1809, 1986, +1807, 1809, 1990, +1800, 1811, 1998, +1793, 1811, 2007, +1784, 1811, 2018, +1772, 1817, 2033, +1754, 1811, 2049, +1756, 1809, 2076, +1721, 1816, 2124, +1728, 1804, 2168, +1675, 1795, 2234, +1712, 1800, 2308, +1779, 1799, 2391, +1880, 1789, 2475, +1982, 1798, 2515, +1982, 1798, 2515, +1982, 1798, 2515, +1982, 1798, 2515, +1982, 1798, 2515, +1982, 1798, 2515, +1982, 1798, 2515, +1982, 1798, 2515, +1982, 1798, 2515, +1982, 1798, 2515, +1977, 1958, 2034, +1977, 1958, 2034, +1976, 1958, 2035, +1976, 1958, 2035, +1975, 1958, 2036, +1974, 1958, 2037, +1973, 1958, 2038, +1972, 1958, 2040, +1970, 1958, 2043, +1968, 1958, 2046, +1964, 1958, 2050, +1962, 1958, 2056, +1959, 1958, 2063, +1950, 1958, 2070, +1942, 1961, 2081, +1940, 1963, 2103, +1935, 1966, 2152, +1912, 1959, 2190, +1920, 1962, 2236, +1904, 1962, 2314, +1936, 1954, 2394, +2043, 1964, 2481, +2112, 1962, 2514, +2112, 1962, 2514, +2112, 1962, 2514, +2112, 1962, 2514, +2112, 1962, 2514, +2112, 1962, 2514, +2112, 1962, 2514, +2112, 1962, 2514, +2112, 1962, 2514, +2112, 1962, 2514, +2124, 2124, 2073, +2124, 2124, 2073, +2124, 2124, 2073, +2125, 2124, 2073, +2125, 2124, 2073, +2125, 2124, 2074, +2125, 2124, 2074, +2126, 2124, 2075, +2126, 2124, 2076, +2127, 2124, 2076, +2129, 2124, 2078, +2129, 2125, 2083, +2128, 2127, 2090, +2122, 2127, 2100, +2119, 2127, 2110, +2123, 2131, 2129, +2120, 2135, 2167, +2113, 2128, 2205, +2115, 2130, 2253, +2128, 2131, 2316, +2148, 2135, 2400, +2220, 2148, 2485, +2258, 2159, 2521, +2258, 2159, 2521, +2258, 2159, 2521, +2258, 2159, 2521, +2258, 2159, 2521, +2258, 2159, 2521, +2258, 2159, 2521, +2258, 2159, 2521, +2258, 2159, 2521, +2258, 2159, 2521, +2370, 2355, 2124, +2370, 2355, 2124, +2370, 2355, 2124, +2370, 2355, 2125, +2370, 2355, 2125, +2370, 2355, 2126, +2371, 2355, 2126, +2371, 2355, 2127, +2371, 2355, 2129, +2372, 2355, 2131, +2372, 2355, 2133, +2373, 2356, 2137, +2374, 2357, 2143, +2372, 2357, 2146, +2369, 2356, 2148, +2370, 2358, 2159, +2374, 2358, 2192, +2374, 2358, 2228, +2379, 2358, 2273, +2393, 2364, 2337, +2413, 2367, 2408, +2467, 2387, 2498, +2496, 2393, 2533, +2496, 2393, 2533, +2496, 2393, 2533, +2496, 2393, 2533, +2496, 2393, 2533, +2496, 2393, 2533, +2496, 2393, 2533, +2496, 2393, 2533, +2496, 2393, 2533, +2496, 2393, 2533, +2680, 2654, 1959, +2680, 2654, 1959, +2680, 2654, 1960, +2680, 2654, 1961, +2680, 2654, 1963, +2680, 2655, 1965, +2680, 2655, 1968, +2680, 2655, 1971, +2680, 2655, 1969, +2680, 2654, 1965, +2679, 2653, 1959, +2679, 2652, 1957, +2678, 2652, 1958, +2678, 2654, 1977, +2677, 2657, 1996, +2678, 2657, 2031, +2677, 2654, 2057, +2678, 2657, 2122, +2682, 2656, 2208, +2688, 2660, 2307, +2695, 2665, 2407, +2715, 2678, 2527, +2725, 2684, 2578, +2725, 2684, 2578, +2725, 2684, 2578, +2725, 2684, 2578, +2725, 2684, 2578, +2725, 2684, 2578, +2725, 2684, 2578, +2725, 2684, 2578, +2725, 2684, 2578, +2725, 2684, 2578, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2430, +2713, 2770, 2430, +2714, 2770, 2430, +2714, 2770, 2430, +2715, 2770, 2430, +2715, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2432, +2716, 2770, 2435, +2716, 2769, 2439, +2714, 2770, 2444, +2711, 2772, 2462, +2712, 2773, 2483, +2714, 2775, 2522, +2712, 2773, 2553, +2717, 2777, 2616, +2724, 2786, 2697, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2430, +2713, 2770, 2430, +2714, 2770, 2430, +2714, 2770, 2430, +2715, 2770, 2430, +2715, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2432, +2716, 2770, 2435, +2716, 2769, 2439, +2714, 2770, 2444, +2711, 2772, 2462, +2712, 2773, 2483, +2714, 2775, 2522, +2712, 2773, 2553, +2717, 2777, 2616, +2724, 2786, 2697, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2430, +2713, 2770, 2430, +2714, 2770, 2430, +2714, 2770, 2430, +2715, 2770, 2430, +2715, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2432, +2716, 2770, 2435, +2716, 2769, 2439, +2714, 2770, 2444, +2711, 2772, 2462, +2712, 2773, 2483, +2714, 2775, 2522, +2712, 2773, 2553, +2717, 2777, 2616, +2724, 2786, 2697, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2430, +2713, 2770, 2430, +2714, 2770, 2430, +2714, 2770, 2430, +2715, 2770, 2430, +2715, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2432, +2716, 2770, 2435, +2716, 2769, 2439, +2714, 2770, 2444, +2711, 2772, 2462, +2712, 2773, 2483, +2714, 2775, 2522, +2712, 2773, 2553, +2717, 2777, 2616, +2724, 2786, 2697, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2430, +2713, 2770, 2430, +2714, 2770, 2430, +2714, 2770, 2430, +2715, 2770, 2430, +2715, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2432, +2716, 2770, 2435, +2716, 2769, 2439, +2714, 2770, 2444, +2711, 2772, 2462, +2712, 2773, 2483, +2714, 2775, 2522, +2712, 2773, 2553, +2717, 2777, 2616, +2724, 2786, 2697, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2430, +2713, 2770, 2430, +2714, 2770, 2430, +2714, 2770, 2430, +2715, 2770, 2430, +2715, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2432, +2716, 2770, 2435, +2716, 2769, 2439, +2714, 2770, 2444, +2711, 2772, 2462, +2712, 2773, 2483, +2714, 2775, 2522, +2712, 2773, 2553, +2717, 2777, 2616, +2724, 2786, 2697, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2430, +2713, 2770, 2430, +2714, 2770, 2430, +2714, 2770, 2430, +2715, 2770, 2430, +2715, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2432, +2716, 2770, 2435, +2716, 2769, 2439, +2714, 2770, 2444, +2711, 2772, 2462, +2712, 2773, 2483, +2714, 2775, 2522, +2712, 2773, 2553, +2717, 2777, 2616, +2724, 2786, 2697, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2430, +2713, 2770, 2430, +2714, 2770, 2430, +2714, 2770, 2430, +2715, 2770, 2430, +2715, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2432, +2716, 2770, 2435, +2716, 2769, 2439, +2714, 2770, 2444, +2711, 2772, 2462, +2712, 2773, 2483, +2714, 2775, 2522, +2712, 2773, 2553, +2717, 2777, 2616, +2724, 2786, 2697, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2430, +2713, 2770, 2430, +2714, 2770, 2430, +2714, 2770, 2430, +2715, 2770, 2430, +2715, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2432, +2716, 2770, 2435, +2716, 2769, 2439, +2714, 2770, 2444, +2711, 2772, 2462, +2712, 2773, 2483, +2714, 2775, 2522, +2712, 2773, 2553, +2717, 2777, 2616, +2724, 2786, 2697, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2430, +2713, 2770, 2430, +2714, 2770, 2430, +2714, 2770, 2430, +2715, 2770, 2430, +2715, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2432, +2716, 2770, 2435, +2716, 2769, 2439, +2714, 2770, 2444, +2711, 2772, 2462, +2712, 2773, 2483, +2714, 2775, 2522, +2712, 2773, 2553, +2717, 2777, 2616, +2724, 2786, 2697, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +1004, 0, 0, +1004, 0, 0, +1004, 0, 0, +1004, 0, 0, +1004, 0, 28, +1004, 0, 152, +1004, 0, 280, +1004, 0, 408, +1004, 0, 537, +1004, 0, 667, +1004, 0, 797, +1004, 0, 928, +985, 0, 1088, +862, 0, 1361, +674, 0, 1566, +856, 0, 1661, +1128, 0, 1782, +1394, 0, 1902, +1561, 0, 2022, +1491, 535, 2188, +220, 987, 2343, +1533, 158, 2465, +1747, 0, 2505, +1747, 0, 2505, +1747, 0, 2505, +1747, 0, 2505, +1747, 0, 2505, +1747, 0, 2505, +1747, 0, 2505, +1747, 0, 2505, +1747, 0, 2505, +1747, 0, 2505, +1002, 0, 0, +1003, 0, 0, +1003, 0, 0, +1003, 0, 0, +1003, 0, 36, +1003, 0, 159, +1003, 0, 285, +1003, 0, 412, +1003, 0, 540, +1003, 0, 669, +1003, 0, 799, +1003, 0, 930, +982, 0, 1089, +858, 0, 1361, +667, 0, 1566, +858, 0, 1662, +1124, 0, 1782, +1393, 0, 1903, +1561, 0, 2022, +1490, 544, 2188, +220, 992, 2343, +1536, 164, 2465, +1747, 0, 2505, +1747, 0, 2505, +1747, 0, 2505, +1747, 0, 2505, +1747, 0, 2505, +1747, 0, 2505, +1747, 0, 2505, +1747, 0, 2505, +1747, 0, 2505, +1747, 0, 2505, +999, 0, 0, +1000, 0, 0, +1002, 0, 0, +1002, 0, 0, +1002, 0, 48, +1002, 0, 168, +1002, 0, 291, +1002, 0, 417, +1002, 0, 544, +1002, 0, 672, +1002, 0, 801, +1002, 0, 931, +981, 0, 1090, +852, 0, 1362, +658, 0, 1567, +860, 0, 1662, +1118, 0, 1782, +1393, 0, 1903, +1560, 0, 2023, +1488, 556, 2188, +220, 998, 2343, +1539, 173, 2465, +1747, 0, 2505, +1747, 0, 2505, +1747, 0, 2505, +1747, 0, 2505, +1747, 0, 2505, +1747, 0, 2505, +1747, 0, 2505, +1747, 0, 2505, +1747, 0, 2505, +1747, 0, 2505, +996, 0, 0, +996, 0, 0, +998, 0, 0, +1000, 0, 0, +1000, 0, 63, +1000, 0, 180, +1000, 0, 300, +1000, 0, 424, +1000, 0, 549, +1000, 0, 676, +1000, 0, 804, +1000, 0, 933, +979, 0, 1091, +844, 0, 1363, +645, 0, 1567, +862, 0, 1663, +1110, 0, 1781, +1392, 0, 1903, +1560, 0, 2024, +1486, 570, 2188, +220, 1005, 2344, +1543, 185, 2465, +1746, 0, 2505, +1746, 0, 2505, +1746, 0, 2505, +1746, 0, 2505, +1746, 0, 2505, +1746, 0, 2505, +1746, 0, 2505, +1746, 0, 2505, +1746, 0, 2505, +1746, 0, 2505, +990, 0, 0, +991, 0, 0, +993, 0, 0, +995, 0, 0, +997, 0, 83, +997, 0, 195, +997, 0, 312, +997, 0, 433, +997, 0, 556, +997, 0, 681, +997, 0, 808, +997, 0, 936, +976, 0, 1093, +833, 0, 1364, +629, 0, 1568, +866, 0, 1664, +1100, 0, 1781, +1391, 0, 1904, +1559, 0, 2025, +1482, 590, 2189, +220, 1015, 2344, +1548, 200, 2465, +1746, 0, 2506, +1746, 0, 2506, +1746, 0, 2506, +1746, 0, 2506, +1746, 0, 2506, +1746, 0, 2506, +1746, 0, 2506, +1746, 0, 2506, +1746, 0, 2506, +1746, 0, 2506, +983, 0, 0, +985, 0, 0, +986, 0, 0, +988, 0, 0, +991, 0, 83, +994, 0, 215, +994, 0, 327, +994, 0, 444, +994, 0, 564, +994, 0, 688, +994, 0, 813, +994, 0, 940, +973, 0, 1096, +819, 30, 1365, +605, 30, 1569, +871, 0, 1666, +1086, 0, 1780, +1390, 0, 1905, +1558, 0, 2026, +1477, 614, 2189, +220, 1028, 2345, +1555, 219, 2465, +1745, 30, 2506, +1745, 30, 2506, +1745, 30, 2506, +1745, 30, 2506, +1745, 30, 2506, +1745, 30, 2506, +1745, 30, 2506, +1745, 30, 2506, +1745, 30, 2506, +1745, 30, 2506, +974, 4, 0, +975, 0, 0, +977, 0, 0, +979, 0, 0, +981, 0, 83, +985, 0, 215, +989, 0, 347, +989, 0, 459, +989, 0, 576, +989, 0, 697, +989, 0, 820, +989, 0, 946, +968, 0, 1100, +798, 163, 1367, +571, 163, 1570, +876, 32, 1668, +1067, 0, 1779, +1388, 0, 1906, +1557, 32, 2028, +1471, 645, 2190, +220, 1045, 2346, +1564, 244, 2465, +1744, 163, 2506, +1744, 163, 2506, +1744, 163, 2506, +1744, 163, 2506, +1744, 163, 2506, +1744, 163, 2506, +1744, 163, 2506, +1744, 163, 2506, +1744, 163, 2506, +1744, 163, 2506, +961, 144, 0, +962, 137, 0, +963, 127, 0, +966, 114, 0, +968, 96, 83, +972, 70, 215, +977, 34, 347, +983, 0, 479, +983, 0, 591, +983, 0, 708, +983, 0, 829, +983, 0, 952, +961, 52, 1105, +769, 295, 1370, +522, 295, 1572, +884, 164, 1671, +1039, 0, 1778, +1385, 0, 1908, +1555, 164, 2031, +1462, 683, 2191, +220, 1066, 2347, +1576, 275, 2465, +1743, 295, 2507, +1743, 295, 2507, +1743, 295, 2507, +1743, 295, 2507, +1743, 295, 2507, +1743, 295, 2507, +1743, 295, 2507, +1743, 295, 2507, +1743, 295, 2507, +1743, 295, 2507, +943, 281, 0, +944, 276, 0, +946, 269, 0, +948, 259, 0, +951, 246, 83, +955, 227, 215, +959, 202, 347, +966, 166, 479, +975, 111, 611, +975, 111, 723, +975, 111, 840, +975, 111, 961, +952, 167, 1111, +726, 426, 1374, +446, 426, 1574, +895, 296, 1674, +1000, 0, 1777, +1382, 111, 1910, +1552, 296, 2034, +1450, 729, 2192, +220, 1093, 2349, +1586, 407, 2466, +1741, 426, 2508, +1741, 426, 2508, +1741, 426, 2508, +1741, 426, 2508, +1741, 426, 2508, +1741, 426, 2508, +1741, 426, 2508, +1741, 426, 2508, +1741, 426, 2508, +1741, 426, 2508, +917, 417, 0, +919, 413, 0, +920, 408, 0, +923, 401, 0, +926, 391, 83, +930, 378, 215, +935, 360, 347, +942, 334, 479, +951, 298, 611, +963, 244, 743, +963, 244, 856, +963, 244, 973, +940, 286, 1119, +679, 536, 1379, +320, 559, 1577, +908, 428, 1679, +1006, 104, 1780, +1377, 244, 1913, +1549, 428, 2038, +1434, 785, 2194, +220, 1128, 2351, +1598, 544, 2467, +1739, 559, 2508, +1739, 559, 2508, +1739, 559, 2508, +1739, 559, 2508, +1739, 559, 2508, +1739, 559, 2508, +1739, 559, 2508, +1739, 559, 2508, +1739, 559, 2508, +1739, 559, 2508, +881, 552, 0, +883, 549, 0, +884, 545, 0, +887, 540, 0, +890, 533, 83, +894, 523, 215, +900, 510, 347, +908, 492, 479, +917, 466, 611, +930, 430, 743, +947, 376, 875, +947, 376, 988, +923, 407, 1131, +649, 611, 1385, +67, 691, 1581, +882, 583, 1684, +1020, 342, 1786, +1348, 324, 1912, +1545, 560, 2044, +1411, 850, 2196, +220, 1169, 2354, +1613, 680, 2468, +1736, 691, 2509, +1736, 691, 2509, +1736, 691, 2509, +1736, 691, 2509, +1736, 691, 2509, +1736, 691, 2509, +1736, 691, 2509, +1736, 691, 2509, +1736, 691, 2509, +1736, 691, 2509, +828, 686, 0, +829, 684, 0, +831, 681, 0, +834, 677, 0, +838, 672, 83, +842, 665, 215, +849, 655, 347, +857, 643, 479, +868, 624, 611, +883, 599, 743, +901, 562, 875, +925, 508, 1007, +899, 532, 1145, +605, 694, 1393, +0, 823, 1587, +799, 745, 1688, +1039, 540, 1792, +1299, 403, 1909, +1539, 692, 2052, +1379, 925, 2199, +0, 1212, 2357, +1633, 815, 2469, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +829, 854, 85, +823, 854, 130, +825, 852, 185, +828, 850, 248, +832, 846, 322, +837, 841, 404, +843, 835, 496, +852, 826, 594, +863, 814, 700, +877, 797, 811, +896, 774, 927, +920, 741, 1047, +934, 812, 1203, +669, 906, 1428, +0, 983, 1610, +812, 918, 1709, +1043, 809, 1807, +1313, 689, 1923, +1484, 849, 2064, +1265, 1080, 2212, +0, 1254, 2365, +1683, 875, 2469, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +996, 1134, 954, +992, 1134, 961, +986, 1134, 970, +979, 1134, 982, +968, 1134, 998, +953, 1134, 1018, +932, 1134, 1043, +903, 1134, 1075, +861, 1134, 1115, +829, 1131, 1163, +850, 1120, 1220, +876, 1105, 1286, +892, 1138, 1385, +1008, 1138, 1491, +767, 1185, 1653, +906, 1170, 1765, +1078, 1173, 1861, +1237, 1110, 1962, +1360, 1131, 2081, +1129, 1250, 2229, +975, 1275, 2368, +1666, 1061, 2470, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1129, 1359, 1308, +1126, 1359, 1311, +1121, 1359, 1315, +1115, 1359, 1321, +1107, 1359, 1328, +1097, 1359, 1338, +1082, 1359, 1351, +1061, 1359, 1367, +1032, 1359, 1389, +989, 1359, 1416, +926, 1359, 1449, +823, 1359, 1491, +841, 1371, 1546, +969, 1371, 1623, +1077, 1367, 1705, +1117, 1361, 1811, +1138, 1380, 1911, +1246, 1386, 2012, +1151, 1350, 2103, +878, 1405, 2249, +1204, 1332, 2374, +1631, 1230, 2474, +1835, 1230, 2510, +1835, 1230, 2510, +1835, 1230, 2510, +1835, 1230, 2510, +1835, 1230, 2510, +1835, 1230, 2510, +1835, 1230, 2510, +1835, 1230, 2510, +1835, 1230, 2510, +1835, 1230, 2510, +1361, 1536, 1656, +1360, 1537, 1657, +1360, 1537, 1658, +1359, 1538, 1659, +1358, 1539, 1661, +1356, 1540, 1663, +1354, 1541, 1667, +1351, 1543, 1671, +1347, 1545, 1676, +1342, 1549, 1684, +1323, 1550, 1699, +1283, 1550, 1723, +1274, 1550, 1745, +1190, 1550, 1777, +1220, 1548, 1833, +1249, 1544, 1903, +1265, 1540, 1988, +1206, 1545, 2067, +1075, 1537, 2167, +810, 1538, 2272, +1313, 1474, 2382, +1686, 1437, 2475, +1851, 1433, 2509, +1851, 1433, 2509, +1851, 1433, 2509, +1851, 1433, 2509, +1851, 1433, 2509, +1851, 1433, 2509, +1851, 1433, 2509, +1851, 1433, 2509, +1851, 1433, 2509, +1851, 1433, 2509, +1603, 1680, 1865, +1602, 1680, 1865, +1600, 1680, 1867, +1599, 1681, 1868, +1597, 1681, 1870, +1594, 1682, 1872, +1590, 1683, 1876, +1585, 1684, 1880, +1578, 1686, 1886, +1575, 1689, 1891, +1571, 1692, 1897, +1565, 1696, 1905, +1563, 1691, 1919, +1538, 1684, 1938, +1489, 1686, 1969, +1460, 1689, 2014, +1482, 1691, 2072, +1418, 1672, 2133, +1270, 1684, 2221, +1248, 1657, 2296, +1563, 1627, 2386, +1794, 1625, 2476, +1896, 1610, 2511, +1896, 1610, 2511, +1896, 1610, 2511, +1896, 1610, 2511, +1896, 1610, 2511, +1896, 1610, 2511, +1896, 1610, 2511, +1896, 1610, 2511, +1896, 1610, 2511, +1896, 1610, 2511, +1830, 1805, 1969, +1830, 1805, 1970, +1829, 1805, 1971, +1829, 1805, 1972, +1828, 1805, 1973, +1827, 1805, 1974, +1825, 1805, 1977, +1823, 1805, 1979, +1821, 1805, 1983, +1817, 1805, 1988, +1810, 1807, 1996, +1800, 1811, 2007, +1791, 1811, 2018, +1779, 1817, 2033, +1762, 1811, 2051, +1763, 1809, 2078, +1725, 1813, 2122, +1736, 1807, 2171, +1689, 1798, 2234, +1727, 1800, 2309, +1778, 1800, 2391, +1894, 1792, 2475, +1986, 1795, 2515, +1986, 1795, 2515, +1986, 1795, 2515, +1986, 1795, 2515, +1986, 1795, 2515, +1986, 1795, 2515, +1986, 1795, 2515, +1986, 1795, 2515, +1986, 1795, 2515, +1986, 1795, 2515, +1983, 1958, 2036, +1983, 1958, 2036, +1983, 1958, 2037, +1983, 1958, 2037, +1982, 1958, 2038, +1981, 1958, 2039, +1980, 1958, 2040, +1979, 1958, 2042, +1977, 1958, 2045, +1974, 1958, 2048, +1971, 1958, 2052, +1966, 1958, 2058, +1963, 1958, 2065, +1955, 1958, 2072, +1945, 1959, 2081, +1942, 1961, 2103, +1940, 1963, 2147, +1922, 1962, 2193, +1920, 1960, 2233, +1912, 1960, 2312, +1943, 1954, 2394, +2043, 1964, 2481, +2119, 1960, 2514, +2119, 1960, 2514, +2119, 1960, 2514, +2119, 1960, 2514, +2119, 1960, 2514, +2119, 1960, 2514, +2119, 1960, 2514, +2119, 1960, 2514, +2119, 1960, 2514, +2119, 1960, 2514, +2126, 2125, 2075, +2126, 2125, 2075, +2126, 2125, 2075, +2126, 2125, 2075, +2126, 2125, 2075, +2127, 2125, 2076, +2127, 2125, 2076, +2127, 2125, 2076, +2128, 2125, 2077, +2129, 2125, 2078, +2130, 2125, 2080, +2132, 2125, 2082, +2131, 2127, 2089, +2125, 2127, 2098, +2119, 2127, 2110, +2123, 2131, 2129, +2124, 2135, 2165, +2118, 2130, 2208, +2117, 2129, 2251, +2132, 2129, 2316, +2154, 2135, 2400, +2222, 2149, 2485, +2257, 2159, 2521, +2257, 2159, 2521, +2257, 2159, 2521, +2257, 2159, 2521, +2257, 2159, 2521, +2257, 2159, 2521, +2257, 2159, 2521, +2257, 2159, 2521, +2257, 2159, 2521, +2257, 2159, 2521, +2371, 2355, 2125, +2371, 2355, 2125, +2371, 2355, 2125, +2371, 2355, 2126, +2372, 2355, 2126, +2372, 2355, 2127, +2372, 2355, 2127, +2372, 2355, 2128, +2372, 2355, 2130, +2373, 2355, 2132, +2374, 2355, 2134, +2374, 2355, 2136, +2375, 2356, 2142, +2373, 2356, 2145, +2371, 2355, 2148, +2372, 2357, 2159, +2375, 2358, 2191, +2375, 2358, 2229, +2381, 2358, 2273, +2396, 2366, 2336, +2413, 2367, 2408, +2468, 2388, 2498, +2497, 2394, 2532, +2497, 2394, 2532, +2497, 2394, 2532, +2497, 2394, 2532, +2497, 2394, 2532, +2497, 2394, 2532, +2497, 2394, 2532, +2497, 2394, 2532, +2497, 2394, 2532, +2497, 2394, 2532, +2679, 2653, 1956, +2679, 2653, 1957, +2679, 2653, 1958, +2679, 2654, 1959, +2679, 2654, 1961, +2680, 2654, 1962, +2680, 2654, 1965, +2680, 2655, 1969, +2680, 2654, 1966, +2679, 2653, 1962, +2679, 2652, 1957, +2678, 2651, 1950, +2678, 2650, 1950, +2677, 2652, 1970, +2676, 2657, 1988, +2678, 2657, 2023, +2679, 2655, 2063, +2679, 2657, 2122, +2682, 2656, 2208, +2688, 2660, 2308, +2695, 2665, 2407, +2715, 2678, 2527, +2726, 2684, 2578, +2726, 2684, 2578, +2726, 2684, 2578, +2726, 2684, 2578, +2726, 2684, 2578, +2726, 2684, 2578, +2726, 2684, 2578, +2726, 2684, 2578, +2726, 2684, 2578, +2726, 2684, 2578, +2712, 2770, 2428, +2712, 2770, 2429, +2712, 2770, 2429, +2712, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2714, 2770, 2429, +2714, 2770, 2430, +2715, 2770, 2430, +2716, 2770, 2431, +2717, 2770, 2431, +2717, 2770, 2432, +2716, 2770, 2435, +2716, 2769, 2439, +2714, 2770, 2444, +2711, 2772, 2462, +2713, 2774, 2488, +2714, 2775, 2522, +2712, 2773, 2553, +2717, 2777, 2617, +2724, 2787, 2699, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2712, 2770, 2428, +2712, 2770, 2429, +2712, 2770, 2429, +2712, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2714, 2770, 2429, +2714, 2770, 2430, +2715, 2770, 2430, +2716, 2770, 2431, +2717, 2770, 2431, +2717, 2770, 2432, +2716, 2770, 2435, +2716, 2769, 2439, +2714, 2770, 2444, +2711, 2772, 2462, +2713, 2774, 2488, +2714, 2775, 2522, +2712, 2773, 2553, +2717, 2777, 2617, +2724, 2787, 2699, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2712, 2770, 2428, +2712, 2770, 2429, +2712, 2770, 2429, +2712, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2714, 2770, 2429, +2714, 2770, 2430, +2715, 2770, 2430, +2716, 2770, 2431, +2717, 2770, 2431, +2717, 2770, 2432, +2716, 2770, 2435, +2716, 2769, 2439, +2714, 2770, 2444, +2711, 2772, 2462, +2713, 2774, 2488, +2714, 2775, 2522, +2712, 2773, 2553, +2717, 2777, 2617, +2724, 2787, 2699, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2712, 2770, 2428, +2712, 2770, 2429, +2712, 2770, 2429, +2712, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2714, 2770, 2429, +2714, 2770, 2430, +2715, 2770, 2430, +2716, 2770, 2431, +2717, 2770, 2431, +2717, 2770, 2432, +2716, 2770, 2435, +2716, 2769, 2439, +2714, 2770, 2444, +2711, 2772, 2462, +2713, 2774, 2488, +2714, 2775, 2522, +2712, 2773, 2553, +2717, 2777, 2617, +2724, 2787, 2699, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2712, 2770, 2428, +2712, 2770, 2429, +2712, 2770, 2429, +2712, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2714, 2770, 2429, +2714, 2770, 2430, +2715, 2770, 2430, +2716, 2770, 2431, +2717, 2770, 2431, +2717, 2770, 2432, +2716, 2770, 2435, +2716, 2769, 2439, +2714, 2770, 2444, +2711, 2772, 2462, +2713, 2774, 2488, +2714, 2775, 2522, +2712, 2773, 2553, +2717, 2777, 2617, +2724, 2787, 2699, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2712, 2770, 2428, +2712, 2770, 2429, +2712, 2770, 2429, +2712, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2714, 2770, 2429, +2714, 2770, 2430, +2715, 2770, 2430, +2716, 2770, 2431, +2717, 2770, 2431, +2717, 2770, 2432, +2716, 2770, 2435, +2716, 2769, 2439, +2714, 2770, 2444, +2711, 2772, 2462, +2713, 2774, 2488, +2714, 2775, 2522, +2712, 2773, 2553, +2717, 2777, 2617, +2724, 2787, 2699, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2712, 2770, 2428, +2712, 2770, 2429, +2712, 2770, 2429, +2712, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2714, 2770, 2429, +2714, 2770, 2430, +2715, 2770, 2430, +2716, 2770, 2431, +2717, 2770, 2431, +2717, 2770, 2432, +2716, 2770, 2435, +2716, 2769, 2439, +2714, 2770, 2444, +2711, 2772, 2462, +2713, 2774, 2488, +2714, 2775, 2522, +2712, 2773, 2553, +2717, 2777, 2617, +2724, 2787, 2699, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2712, 2770, 2428, +2712, 2770, 2429, +2712, 2770, 2429, +2712, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2714, 2770, 2429, +2714, 2770, 2430, +2715, 2770, 2430, +2716, 2770, 2431, +2717, 2770, 2431, +2717, 2770, 2432, +2716, 2770, 2435, +2716, 2769, 2439, +2714, 2770, 2444, +2711, 2772, 2462, +2713, 2774, 2488, +2714, 2775, 2522, +2712, 2773, 2553, +2717, 2777, 2617, +2724, 2787, 2699, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2712, 2770, 2428, +2712, 2770, 2429, +2712, 2770, 2429, +2712, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2714, 2770, 2429, +2714, 2770, 2430, +2715, 2770, 2430, +2716, 2770, 2431, +2717, 2770, 2431, +2717, 2770, 2432, +2716, 2770, 2435, +2716, 2769, 2439, +2714, 2770, 2444, +2711, 2772, 2462, +2713, 2774, 2488, +2714, 2775, 2522, +2712, 2773, 2553, +2717, 2777, 2617, +2724, 2787, 2699, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2712, 2770, 2428, +2712, 2770, 2429, +2712, 2770, 2429, +2712, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2714, 2770, 2429, +2714, 2770, 2430, +2715, 2770, 2430, +2716, 2770, 2431, +2717, 2770, 2431, +2717, 2770, 2432, +2716, 2770, 2435, +2716, 2769, 2439, +2714, 2770, 2444, +2711, 2772, 2462, +2713, 2774, 2488, +2714, 2775, 2522, +2712, 2773, 2553, +2717, 2777, 2617, +2724, 2787, 2699, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +1146, 0, 0, +1146, 0, 0, +1146, 0, 0, +1146, 0, 46, +1146, 0, 140, +1146, 0, 240, +1146, 0, 347, +1146, 0, 460, +1146, 0, 576, +1146, 0, 697, +1146, 0, 820, +1146, 0, 946, +1143, 0, 1084, +1060, 0, 1359, +918, 0, 1574, +981, 0, 1683, +1223, 0, 1785, +1476, 0, 1909, +1569, 0, 2028, +1478, 645, 2197, +391, 989, 2347, +1611, 0, 2464, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1146, 0, 0, +1146, 0, 0, +1146, 0, 27, +1146, 0, 101, +1146, 0, 185, +1146, 0, 277, +1146, 0, 376, +1146, 0, 482, +1146, 0, 594, +1146, 0, 710, +1146, 0, 830, +1146, 0, 953, +1142, 0, 1089, +1059, 0, 1361, +917, 0, 1576, +981, 0, 1683, +1223, 0, 1786, +1476, 0, 1910, +1569, 0, 2029, +1477, 656, 2197, +395, 992, 2347, +1611, 0, 2464, +1757, 0, 2506, +1757, 0, 2506, +1757, 0, 2506, +1757, 0, 2506, +1757, 0, 2506, +1757, 0, 2506, +1757, 0, 2506, +1757, 0, 2506, +1757, 0, 2506, +1757, 0, 2506, +1143, 0, 0, +1143, 0, 0, +1144, 0, 38, +1144, 0, 111, +1144, 0, 193, +1144, 0, 284, +1144, 0, 382, +1144, 0, 487, +1144, 0, 598, +1144, 0, 713, +1144, 0, 833, +1144, 0, 955, +1141, 0, 1090, +1055, 0, 1362, +911, 0, 1576, +982, 0, 1684, +1219, 0, 1785, +1475, 0, 1911, +1568, 0, 2029, +1475, 665, 2197, +395, 998, 2347, +1614, 0, 2464, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1141, 0, 0, +1141, 0, 0, +1142, 0, 38, +1143, 0, 124, +1143, 0, 204, +1143, 0, 293, +1143, 0, 389, +1143, 0, 493, +1143, 0, 602, +1143, 0, 717, +1143, 0, 835, +1143, 0, 957, +1140, 0, 1091, +1050, 0, 1363, +904, 0, 1577, +984, 0, 1685, +1213, 0, 1785, +1474, 0, 1911, +1568, 0, 2030, +1472, 676, 2198, +395, 1005, 2348, +1617, 0, 2464, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1137, 0, 0, +1137, 0, 0, +1138, 0, 38, +1139, 0, 124, +1141, 0, 219, +1141, 0, 305, +1141, 0, 399, +1141, 0, 501, +1141, 0, 608, +1141, 0, 722, +1141, 0, 839, +1141, 0, 960, +1138, 0, 1093, +1043, 0, 1364, +895, 0, 1577, +987, 0, 1686, +1205, 0, 1784, +1474, 0, 1912, +1567, 0, 2031, +1469, 692, 2198, +395, 1015, 2348, +1622, 0, 2464, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1132, 0, 0, +1132, 0, 0, +1133, 0, 38, +1134, 0, 124, +1136, 0, 219, +1139, 0, 320, +1139, 0, 411, +1139, 0, 511, +1139, 0, 616, +1139, 0, 728, +1139, 0, 844, +1139, 0, 963, +1136, 0, 1096, +1034, 0, 1365, +882, 0, 1578, +990, 0, 1687, +1194, 0, 1784, +1472, 0, 1913, +1566, 0, 2032, +1464, 711, 2199, +395, 1028, 2349, +1628, 0, 2464, +1755, 0, 2507, +1755, 0, 2507, +1755, 0, 2507, +1755, 0, 2507, +1755, 0, 2507, +1755, 0, 2507, +1755, 0, 2507, +1755, 0, 2507, +1755, 0, 2507, +1755, 0, 2507, +1125, 13, 0, +1125, 0, 0, +1126, 0, 38, +1128, 0, 124, +1129, 0, 219, +1132, 0, 320, +1135, 0, 428, +1135, 0, 524, +1135, 0, 627, +1135, 0, 736, +1135, 0, 850, +1135, 0, 968, +1132, 0, 1100, +1021, 107, 1367, +864, 107, 1579, +995, 0, 1690, +1178, 0, 1783, +1471, 0, 1914, +1565, 97, 2034, +1457, 736, 2199, +395, 1045, 2350, +1636, 0, 2464, +1754, 107, 2507, +1754, 107, 2507, +1754, 107, 2507, +1754, 107, 2507, +1754, 107, 2507, +1754, 107, 2507, +1754, 107, 2507, +1754, 107, 2507, +1754, 107, 2507, +1754, 107, 2507, +1116, 150, 0, +1116, 137, 0, +1117, 127, 38, +1118, 114, 124, +1120, 96, 219, +1123, 70, 320, +1126, 34, 428, +1131, 0, 541, +1131, 0, 640, +1131, 0, 747, +1131, 0, 858, +1131, 0, 975, +1128, 0, 1105, +1003, 254, 1370, +839, 254, 1581, +1001, 137, 1692, +1157, 0, 1782, +1469, 17, 1915, +1563, 213, 2037, +1448, 768, 2200, +395, 1066, 2351, +1646, 21, 2464, +1753, 254, 2507, +1753, 254, 2507, +1753, 254, 2507, +1753, 254, 2507, +1753, 254, 2507, +1753, 254, 2507, +1753, 254, 2507, +1753, 254, 2507, +1753, 254, 2507, +1753, 254, 2507, +1103, 286, 0, +1103, 276, 0, +1104, 269, 38, +1106, 259, 124, +1108, 246, 219, +1110, 227, 320, +1114, 202, 428, +1118, 166, 541, +1125, 111, 658, +1125, 111, 760, +1125, 111, 869, +1125, 111, 983, +1121, 111, 1111, +979, 396, 1374, +803, 396, 1584, +1009, 276, 1696, +1127, 0, 1781, +1466, 140, 1918, +1560, 333, 2040, +1436, 807, 2201, +395, 1093, 2353, +1654, 232, 2464, +1751, 396, 2508, +1751, 396, 2508, +1751, 396, 2508, +1751, 396, 2508, +1751, 396, 2508, +1751, 396, 2508, +1751, 396, 2508, +1751, 396, 2508, +1751, 396, 2508, +1751, 396, 2508, +1085, 420, 0, +1085, 413, 0, +1086, 408, 38, +1088, 401, 124, +1090, 391, 219, +1093, 378, 320, +1097, 360, 428, +1102, 334, 541, +1108, 298, 658, +1116, 244, 779, +1116, 244, 884, +1116, 244, 995, +1113, 244, 1119, +952, 513, 1379, +749, 536, 1587, +1019, 413, 1700, +1132, 186, 1784, +1462, 265, 1920, +1557, 456, 2044, +1419, 854, 2202, +395, 1128, 2355, +1664, 421, 2465, +1749, 536, 2509, +1749, 536, 2509, +1749, 536, 2509, +1749, 536, 2509, +1749, 536, 2509, +1749, 536, 2509, +1749, 536, 2509, +1749, 536, 2509, +1749, 536, 2509, +1749, 536, 2509, +1061, 554, 0, +1061, 549, 0, +1062, 545, 38, +1064, 540, 124, +1066, 533, 219, +1069, 523, 320, +1073, 510, 428, +1078, 492, 541, +1085, 466, 658, +1093, 430, 779, +1105, 376, 902, +1105, 376, 1009, +1102, 376, 1131, +936, 591, 1385, +666, 674, 1590, +999, 572, 1705, +1142, 392, 1789, +1438, 342, 1919, +1553, 581, 2050, +1395, 910, 2205, +395, 1169, 2358, +1678, 592, 2466, +1746, 674, 2510, +1746, 674, 2510, +1746, 674, 2510, +1746, 674, 2510, +1746, 674, 2510, +1746, 674, 2510, +1746, 674, 2510, +1746, 674, 2510, +1746, 674, 2510, +1746, 674, 2510, +1025, 688, 0, +1025, 684, 0, +1027, 681, 38, +1028, 677, 124, +1031, 672, 219, +1034, 665, 320, +1038, 655, 428, +1044, 643, 541, +1051, 624, 658, +1061, 599, 779, +1073, 562, 902, +1089, 508, 1028, +1086, 508, 1145, +913, 678, 1393, +525, 811, 1596, +936, 738, 1709, +1157, 573, 1796, +1399, 418, 1917, +1547, 709, 2058, +1361, 976, 2207, +221, 1212, 2361, +1695, 752, 2468, +1742, 811, 2511, +1742, 811, 2511, +1742, 811, 2511, +1742, 811, 2511, +1742, 811, 2511, +1742, 811, 2511, +1742, 811, 2511, +1742, 811, 2511, +1742, 811, 2511, +1742, 811, 2511, +998, 854, 247, +999, 854, 274, +1000, 852, 314, +1002, 850, 363, +1005, 846, 421, +1008, 841, 488, +1013, 835, 565, +1018, 826, 651, +1026, 814, 746, +1036, 797, 847, +1050, 774, 955, +1067, 741, 1069, +1082, 701, 1186, +907, 818, 1417, +458, 939, 1611, +854, 914, 1719, +1166, 781, 1811, +1344, 583, 1918, +1532, 855, 2069, +1306, 1062, 2213, +0, 1254, 2365, +1713, 908, 2469, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1120, 1134, 981, +1120, 1134, 987, +1116, 1134, 996, +1110, 1134, 1007, +1102, 1134, 1022, +1091, 1134, 1041, +1076, 1134, 1065, +1055, 1134, 1096, +1025, 1134, 1133, +1003, 1131, 1180, +1017, 1120, 1235, +1036, 1105, 1300, +1052, 1087, 1374, +1136, 1087, 1482, +920, 1158, 1655, +941, 1167, 1774, +1193, 1161, 1864, +1274, 1071, 1958, +1421, 1134, 2085, +1184, 1237, 2230, +980, 1275, 2368, +1697, 1083, 2471, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1244, 1351, 1313, +1244, 1351, 1315, +1241, 1351, 1320, +1236, 1351, 1325, +1230, 1351, 1332, +1222, 1351, 1342, +1211, 1351, 1355, +1195, 1351, 1371, +1174, 1351, 1392, +1143, 1351, 1419, +1099, 1351, 1452, +1031, 1351, 1493, +1008, 1345, 1543, +1101, 1345, 1620, +1200, 1345, 1706, +1180, 1356, 1819, +1250, 1368, 1917, +1282, 1376, 2010, +1214, 1352, 2106, +941, 1399, 2251, +1206, 1332, 2375, +1655, 1246, 2474, +1839, 1219, 2510, +1839, 1219, 2510, +1839, 1219, 2510, +1839, 1219, 2510, +1839, 1219, 2510, +1839, 1219, 2510, +1839, 1219, 2510, +1839, 1219, 2510, +1839, 1219, 2510, +1839, 1219, 2510, +1442, 1522, 1648, +1441, 1522, 1649, +1440, 1523, 1650, +1440, 1523, 1651, +1439, 1524, 1653, +1437, 1525, 1655, +1436, 1526, 1658, +1433, 1528, 1663, +1430, 1531, 1668, +1426, 1534, 1676, +1410, 1536, 1691, +1377, 1536, 1716, +1335, 1537, 1749, +1263, 1537, 1781, +1301, 1537, 1839, +1339, 1536, 1910, +1357, 1528, 1994, +1241, 1551, 2071, +1105, 1537, 2167, +883, 1536, 2275, +1324, 1476, 2384, +1692, 1446, 2476, +1866, 1416, 2509, +1866, 1416, 2509, +1866, 1416, 2509, +1866, 1416, 2509, +1866, 1416, 2509, +1866, 1416, 2509, +1866, 1416, 2509, +1866, 1416, 2509, +1866, 1416, 2509, +1866, 1416, 2509, +1656, 1669, 1872, +1656, 1669, 1873, +1655, 1669, 1874, +1654, 1670, 1875, +1652, 1671, 1877, +1650, 1671, 1879, +1646, 1672, 1883, +1642, 1674, 1887, +1636, 1675, 1893, +1633, 1678, 1897, +1629, 1681, 1903, +1624, 1685, 1911, +1616, 1691, 1922, +1595, 1684, 1941, +1542, 1684, 1969, +1504, 1684, 2010, +1525, 1691, 2073, +1483, 1671, 2138, +1324, 1684, 2221, +1259, 1662, 2297, +1564, 1621, 2385, +1796, 1617, 2477, +1894, 1605, 2510, +1894, 1605, 2510, +1894, 1605, 2510, +1894, 1605, 2510, +1894, 1605, 2510, +1894, 1605, 2510, +1894, 1605, 2510, +1894, 1605, 2510, +1894, 1605, 2510, +1894, 1605, 2510, +1843, 1802, 1967, +1843, 1802, 1968, +1843, 1802, 1969, +1842, 1802, 1969, +1841, 1802, 1971, +1840, 1802, 1972, +1839, 1802, 1974, +1837, 1802, 1977, +1834, 1802, 1981, +1831, 1802, 1986, +1824, 1804, 1994, +1814, 1807, 2005, +1802, 1811, 2018, +1790, 1817, 2033, +1773, 1811, 2052, +1772, 1809, 2081, +1734, 1809, 2120, +1747, 1811, 2175, +1708, 1801, 2234, +1744, 1800, 2309, +1774, 1800, 2391, +1911, 1796, 2475, +1992, 1790, 2515, +1992, 1790, 2515, +1992, 1790, 2515, +1992, 1790, 2515, +1992, 1790, 2515, +1992, 1790, 2515, +1992, 1790, 2515, +1992, 1790, 2515, +1992, 1790, 2515, +1992, 1790, 2515, +1992, 1958, 2037, +1992, 1958, 2037, +1992, 1958, 2037, +1991, 1958, 2038, +1991, 1958, 2038, +1990, 1958, 2040, +1989, 1958, 2041, +1988, 1958, 2043, +1986, 1958, 2045, +1983, 1958, 2049, +1980, 1958, 2053, +1976, 1958, 2059, +1970, 1958, 2067, +1962, 1958, 2074, +1950, 1958, 2082, +1946, 1958, 2104, +1947, 1962, 2142, +1936, 1964, 2196, +1923, 1957, 2231, +1922, 1958, 2310, +1954, 1955, 2394, +2043, 1964, 2481, +2127, 1958, 2514, +2127, 1958, 2514, +2127, 1958, 2514, +2127, 1958, 2514, +2127, 1958, 2514, +2127, 1958, 2514, +2127, 1958, 2514, +2127, 1958, 2514, +2127, 1958, 2514, +2127, 1958, 2514, +2128, 2127, 2076, +2128, 2127, 2077, +2129, 2127, 2077, +2129, 2127, 2077, +2129, 2127, 2077, +2129, 2127, 2078, +2130, 2127, 2078, +2130, 2127, 2079, +2131, 2127, 2080, +2132, 2127, 2080, +2133, 2127, 2082, +2135, 2127, 2084, +2135, 2127, 2087, +2129, 2127, 2097, +2122, 2127, 2109, +2124, 2131, 2129, +2128, 2135, 2163, +2124, 2132, 2210, +2119, 2127, 2251, +2135, 2128, 2316, +2164, 2135, 2400, +2226, 2151, 2485, +2257, 2159, 2520, +2257, 2159, 2520, +2257, 2159, 2520, +2257, 2159, 2520, +2257, 2159, 2520, +2257, 2159, 2520, +2257, 2159, 2520, +2257, 2159, 2520, +2257, 2159, 2520, +2257, 2159, 2520, +2374, 2355, 2126, +2374, 2355, 2127, +2374, 2355, 2127, +2374, 2355, 2127, +2374, 2355, 2127, +2374, 2355, 2128, +2374, 2355, 2129, +2375, 2355, 2130, +2375, 2355, 2131, +2375, 2355, 2133, +2376, 2355, 2135, +2377, 2355, 2138, +2376, 2355, 2140, +2375, 2355, 2143, +2372, 2354, 2147, +2374, 2356, 2159, +2375, 2358, 2191, +2375, 2357, 2230, +2381, 2358, 2275, +2398, 2368, 2335, +2415, 2368, 2409, +2469, 2388, 2498, +2498, 2395, 2532, +2498, 2395, 2532, +2498, 2395, 2532, +2498, 2395, 2532, +2498, 2395, 2532, +2498, 2395, 2532, +2498, 2395, 2532, +2498, 2395, 2532, +2498, 2395, 2532, +2498, 2395, 2532, +2679, 2653, 1955, +2679, 2653, 1955, +2679, 2653, 1956, +2679, 2653, 1957, +2679, 2653, 1958, +2679, 2654, 1961, +2679, 2654, 1963, +2679, 2654, 1967, +2679, 2654, 1964, +2679, 2653, 1961, +2678, 2652, 1955, +2678, 2650, 1948, +2677, 2648, 1939, +2677, 2650, 1960, +2676, 2655, 1976, +2677, 2657, 2013, +2680, 2657, 2068, +2679, 2658, 2122, +2683, 2657, 2209, +2688, 2661, 2310, +2695, 2666, 2408, +2715, 2679, 2527, +2727, 2684, 2579, +2727, 2684, 2579, +2727, 2684, 2579, +2727, 2684, 2579, +2727, 2684, 2579, +2727, 2684, 2579, +2727, 2684, 2579, +2727, 2684, 2579, +2727, 2684, 2579, +2727, 2684, 2579, +2712, 2769, 2427, +2712, 2769, 2427, +2712, 2769, 2427, +2712, 2769, 2428, +2712, 2769, 2428, +2712, 2769, 2428, +2713, 2769, 2428, +2713, 2769, 2428, +2714, 2769, 2429, +2714, 2769, 2429, +2715, 2769, 2430, +2717, 2769, 2431, +2718, 2770, 2433, +2717, 2770, 2436, +2716, 2770, 2440, +2714, 2770, 2444, +2712, 2772, 2461, +2714, 2774, 2492, +2714, 2775, 2523, +2712, 2774, 2554, +2717, 2778, 2620, +2725, 2789, 2702, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2712, 2769, 2427, +2712, 2769, 2427, +2712, 2769, 2427, +2712, 2769, 2428, +2712, 2769, 2428, +2712, 2769, 2428, +2713, 2769, 2428, +2713, 2769, 2428, +2714, 2769, 2429, +2714, 2769, 2429, +2715, 2769, 2430, +2717, 2769, 2431, +2718, 2770, 2433, +2717, 2770, 2436, +2716, 2770, 2440, +2714, 2770, 2444, +2712, 2772, 2461, +2714, 2774, 2492, +2714, 2775, 2523, +2712, 2774, 2554, +2717, 2778, 2620, +2725, 2789, 2702, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2712, 2769, 2427, +2712, 2769, 2427, +2712, 2769, 2427, +2712, 2769, 2428, +2712, 2769, 2428, +2712, 2769, 2428, +2713, 2769, 2428, +2713, 2769, 2428, +2714, 2769, 2429, +2714, 2769, 2429, +2715, 2769, 2430, +2717, 2769, 2431, +2718, 2770, 2433, +2717, 2770, 2436, +2716, 2770, 2440, +2714, 2770, 2444, +2712, 2772, 2461, +2714, 2774, 2492, +2714, 2775, 2523, +2712, 2774, 2554, +2717, 2778, 2620, +2725, 2789, 2702, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2712, 2769, 2427, +2712, 2769, 2427, +2712, 2769, 2427, +2712, 2769, 2428, +2712, 2769, 2428, +2712, 2769, 2428, +2713, 2769, 2428, +2713, 2769, 2428, +2714, 2769, 2429, +2714, 2769, 2429, +2715, 2769, 2430, +2717, 2769, 2431, +2718, 2770, 2433, +2717, 2770, 2436, +2716, 2770, 2440, +2714, 2770, 2444, +2712, 2772, 2461, +2714, 2774, 2492, +2714, 2775, 2523, +2712, 2774, 2554, +2717, 2778, 2620, +2725, 2789, 2702, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2712, 2769, 2427, +2712, 2769, 2427, +2712, 2769, 2427, +2712, 2769, 2428, +2712, 2769, 2428, +2712, 2769, 2428, +2713, 2769, 2428, +2713, 2769, 2428, +2714, 2769, 2429, +2714, 2769, 2429, +2715, 2769, 2430, +2717, 2769, 2431, +2718, 2770, 2433, +2717, 2770, 2436, +2716, 2770, 2440, +2714, 2770, 2444, +2712, 2772, 2461, +2714, 2774, 2492, +2714, 2775, 2523, +2712, 2774, 2554, +2717, 2778, 2620, +2725, 2789, 2702, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2712, 2769, 2427, +2712, 2769, 2427, +2712, 2769, 2427, +2712, 2769, 2428, +2712, 2769, 2428, +2712, 2769, 2428, +2713, 2769, 2428, +2713, 2769, 2428, +2714, 2769, 2429, +2714, 2769, 2429, +2715, 2769, 2430, +2717, 2769, 2431, +2718, 2770, 2433, +2717, 2770, 2436, +2716, 2770, 2440, +2714, 2770, 2444, +2712, 2772, 2461, +2714, 2774, 2492, +2714, 2775, 2523, +2712, 2774, 2554, +2717, 2778, 2620, +2725, 2789, 2702, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2712, 2769, 2427, +2712, 2769, 2427, +2712, 2769, 2427, +2712, 2769, 2428, +2712, 2769, 2428, +2712, 2769, 2428, +2713, 2769, 2428, +2713, 2769, 2428, +2714, 2769, 2429, +2714, 2769, 2429, +2715, 2769, 2430, +2717, 2769, 2431, +2718, 2770, 2433, +2717, 2770, 2436, +2716, 2770, 2440, +2714, 2770, 2444, +2712, 2772, 2461, +2714, 2774, 2492, +2714, 2775, 2523, +2712, 2774, 2554, +2717, 2778, 2620, +2725, 2789, 2702, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2712, 2769, 2427, +2712, 2769, 2427, +2712, 2769, 2427, +2712, 2769, 2428, +2712, 2769, 2428, +2712, 2769, 2428, +2713, 2769, 2428, +2713, 2769, 2428, +2714, 2769, 2429, +2714, 2769, 2429, +2715, 2769, 2430, +2717, 2769, 2431, +2718, 2770, 2433, +2717, 2770, 2436, +2716, 2770, 2440, +2714, 2770, 2444, +2712, 2772, 2461, +2714, 2774, 2492, +2714, 2775, 2523, +2712, 2774, 2554, +2717, 2778, 2620, +2725, 2789, 2702, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2712, 2769, 2427, +2712, 2769, 2427, +2712, 2769, 2427, +2712, 2769, 2428, +2712, 2769, 2428, +2712, 2769, 2428, +2713, 2769, 2428, +2713, 2769, 2428, +2714, 2769, 2429, +2714, 2769, 2429, +2715, 2769, 2430, +2717, 2769, 2431, +2718, 2770, 2433, +2717, 2770, 2436, +2716, 2770, 2440, +2714, 2770, 2444, +2712, 2772, 2461, +2714, 2774, 2492, +2714, 2775, 2523, +2712, 2774, 2554, +2717, 2778, 2620, +2725, 2789, 2702, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2712, 2769, 2427, +2712, 2769, 2427, +2712, 2769, 2427, +2712, 2769, 2428, +2712, 2769, 2428, +2712, 2769, 2428, +2713, 2769, 2428, +2713, 2769, 2428, +2714, 2769, 2429, +2714, 2769, 2429, +2715, 2769, 2430, +2717, 2769, 2431, +2718, 2770, 2433, +2717, 2770, 2436, +2716, 2770, 2440, +2714, 2770, 2444, +2712, 2772, 2461, +2714, 2774, 2492, +2714, 2775, 2523, +2712, 2774, 2554, +2717, 2778, 2620, +2725, 2789, 2702, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +1314, 0, 0, +1314, 0, 0, +1315, 0, 0, +1316, 0, 18, +1317, 0, 98, +1319, 0, 188, +1321, 0, 285, +1324, 0, 389, +1328, 0, 499, +1331, 0, 624, +1331, 0, 765, +1331, 0, 904, +1329, 0, 1054, +1312, 0, 1291, +1236, 0, 1533, +1269, 0, 1690, +1323, 0, 1781, +1534, 0, 1909, +1607, 0, 2039, +1502, 645, 2197, +677, 1023, 2352, +1658, 0, 2466, +1776, 0, 2506, +1776, 0, 2506, +1776, 0, 2506, +1776, 0, 2506, +1776, 0, 2506, +1776, 0, 2506, +1776, 0, 2506, +1776, 0, 2506, +1776, 0, 2506, +1776, 0, 2506, +1314, 0, 0, +1314, 0, 0, +1315, 0, 17, +1315, 0, 78, +1316, 0, 150, +1318, 0, 230, +1321, 0, 319, +1324, 0, 417, +1328, 0, 521, +1331, 0, 640, +1331, 0, 777, +1331, 0, 914, +1329, 0, 1059, +1311, 0, 1294, +1235, 0, 1535, +1268, 0, 1691, +1323, 0, 1782, +1533, 0, 1910, +1607, 0, 2039, +1501, 656, 2197, +679, 1026, 2352, +1659, 0, 2466, +1776, 0, 2506, +1776, 0, 2506, +1776, 0, 2506, +1776, 0, 2506, +1776, 0, 2506, +1776, 0, 2506, +1776, 0, 2506, +1776, 0, 2506, +1776, 0, 2506, +1776, 0, 2506, +1314, 0, 0, +1314, 0, 17, +1314, 0, 97, +1315, 0, 149, +1316, 0, 211, +1318, 0, 282, +1320, 0, 363, +1323, 0, 452, +1327, 0, 549, +1330, 0, 662, +1330, 0, 794, +1330, 0, 926, +1328, 0, 1068, +1311, 0, 1298, +1235, 0, 1537, +1267, 0, 1692, +1323, 0, 1783, +1532, 0, 1911, +1606, 0, 2040, +1500, 671, 2198, +682, 1030, 2352, +1660, 0, 2466, +1777, 0, 2506, +1777, 0, 2506, +1777, 0, 2506, +1777, 0, 2506, +1777, 0, 2506, +1777, 0, 2506, +1777, 0, 2506, +1777, 0, 2506, +1777, 0, 2506, +1777, 0, 2506, +1314, 0, 18, +1314, 0, 78, +1314, 0, 149, +1314, 0, 229, +1315, 0, 281, +1316, 0, 343, +1319, 0, 414, +1322, 0, 494, +1326, 0, 584, +1329, 0, 689, +1329, 0, 814, +1329, 0, 941, +1327, 0, 1079, +1310, 0, 1302, +1233, 0, 1540, +1266, 0, 1693, +1323, 0, 1784, +1531, 0, 1912, +1605, 0, 2041, +1498, 690, 2198, +686, 1035, 2353, +1661, 0, 2466, +1778, 0, 2506, +1778, 0, 2506, +1778, 0, 2506, +1778, 0, 2506, +1778, 0, 2506, +1778, 0, 2506, +1778, 0, 2506, +1778, 0, 2506, +1778, 0, 2506, +1778, 0, 2506, +1314, 0, 98, +1314, 0, 150, +1314, 0, 211, +1314, 0, 281, +1314, 0, 361, +1315, 0, 413, +1318, 0, 475, +1321, 0, 546, +1325, 0, 627, +1328, 0, 723, +1328, 0, 840, +1328, 0, 961, +1326, 0, 1094, +1309, 0, 1309, +1232, 0, 1544, +1265, 0, 1695, +1323, 0, 1787, +1529, 0, 1914, +1603, 0, 2042, +1497, 714, 2199, +691, 1042, 2353, +1662, 0, 2466, +1779, 0, 2506, +1779, 0, 2506, +1779, 0, 2506, +1779, 0, 2506, +1779, 0, 2506, +1779, 0, 2506, +1779, 0, 2506, +1779, 0, 2506, +1779, 0, 2506, +1779, 0, 2506, +1314, 0, 188, +1314, 0, 230, +1314, 0, 282, +1314, 0, 343, +1314, 0, 413, +1314, 0, 493, +1316, 0, 545, +1319, 0, 607, +1323, 0, 678, +1326, 0, 766, +1326, 0, 873, +1326, 0, 986, +1324, 0, 1113, +1307, 0, 1317, +1230, 0, 1549, +1263, 0, 1697, +1323, 30, 1790, +1527, 0, 1916, +1602, 132, 2043, +1495, 745, 2200, +698, 1051, 2354, +1663, 0, 2466, +1781, 0, 2506, +1781, 0, 2506, +1781, 0, 2506, +1781, 0, 2506, +1781, 0, 2506, +1781, 0, 2506, +1781, 0, 2506, +1781, 0, 2506, +1781, 0, 2506, +1781, 0, 2506, +1314, 121, 285, +1314, 106, 319, +1314, 85, 363, +1314, 56, 414, +1314, 13, 475, +1314, 0, 545, +1314, 0, 625, +1317, 0, 677, +1321, 0, 739, +1324, 0, 816, +1324, 0, 914, +1324, 0, 1018, +1322, 0, 1138, +1304, 0, 1329, +1227, 0, 1556, +1261, 0, 1700, +1323, 163, 1794, +1524, 32, 1919, +1599, 264, 2045, +1491, 783, 2201, +706, 1063, 2354, +1666, 32, 2466, +1784, 0, 2506, +1784, 0, 2506, +1784, 0, 2506, +1784, 0, 2506, +1784, 0, 2506, +1784, 0, 2506, +1784, 0, 2506, +1784, 0, 2506, +1784, 0, 2506, +1784, 0, 2506, +1314, 264, 389, +1314, 253, 417, +1314, 238, 452, +1314, 217, 494, +1314, 188, 546, +1314, 146, 607, +1314, 82, 677, +1314, 0, 757, +1318, 0, 809, +1321, 0, 876, +1321, 0, 963, +1321, 0, 1058, +1319, 0, 1168, +1302, 0, 1343, +1223, 0, 1565, +1257, 0, 1704, +1323, 295, 1799, +1520, 164, 1923, +1596, 396, 2047, +1487, 830, 2203, +718, 1079, 2355, +1668, 164, 2466, +1787, 0, 2506, +1787, 0, 2506, +1787, 0, 2506, +1787, 0, 2506, +1787, 0, 2506, +1787, 0, 2506, +1787, 0, 2506, +1787, 0, 2506, +1787, 0, 2506, +1787, 0, 2506, +1314, 404, 499, +1314, 396, 521, +1314, 385, 549, +1314, 370, 584, +1314, 349, 627, +1314, 320, 678, +1314, 277, 739, +1314, 214, 809, +1314, 111, 889, +1317, 111, 946, +1317, 111, 1021, +1317, 111, 1106, +1315, 111, 1206, +1297, 111, 1362, +1218, 111, 1576, +1252, 111, 1709, +1323, 426, 1806, +1515, 296, 1928, +1592, 528, 2051, +1482, 885, 2205, +733, 1099, 2357, +1667, 296, 2465, +1791, 111, 2506, +1791, 111, 2506, +1791, 111, 2506, +1791, 111, 2506, +1791, 111, 2506, +1791, 111, 2506, +1791, 111, 2506, +1791, 111, 2506, +1791, 111, 2506, +1791, 111, 2506, +1310, 530, 574, +1310, 524, 592, +1310, 516, 616, +1310, 505, 646, +1310, 490, 684, +1310, 468, 730, +1310, 438, 784, +1310, 394, 848, +1310, 328, 922, +1311, 244, 1001, +1311, 244, 1068, +1311, 244, 1145, +1310, 244, 1238, +1292, 244, 1379, +1207, 285, 1587, +1251, 265, 1716, +1322, 514, 1811, +1510, 413, 1934, +1587, 643, 2055, +1471, 941, 2208, +745, 1128, 2358, +1669, 442, 2465, +1794, 285, 2506, +1794, 285, 2506, +1794, 285, 2506, +1794, 285, 2506, +1794, 285, 2506, +1794, 285, 2506, +1794, 285, 2506, +1794, 285, 2506, +1794, 285, 2506, +1794, 285, 2506, +1294, 639, 574, +1294, 634, 592, +1294, 627, 616, +1294, 619, 646, +1294, 607, 684, +1294, 591, 730, +1294, 568, 784, +1294, 535, 848, +1294, 488, 922, +1297, 430, 1001, +1304, 376, 1080, +1304, 376, 1155, +1302, 376, 1246, +1284, 376, 1385, +1178, 503, 1590, +1239, 473, 1720, +1329, 626, 1816, +1488, 470, 1933, +1583, 729, 2060, +1450, 988, 2209, +745, 1169, 2362, +1682, 607, 2467, +1792, 503, 2507, +1792, 503, 2507, +1792, 503, 2507, +1792, 503, 2507, +1792, 503, 2507, +1792, 503, 2507, +1792, 503, 2507, +1792, 503, 2507, +1792, 503, 2507, +1792, 503, 2507, +1274, 753, 574, +1274, 749, 592, +1274, 744, 616, +1274, 737, 646, +1274, 728, 684, +1274, 716, 730, +1274, 698, 784, +1274, 674, 848, +1274, 640, 922, +1276, 599, 1001, +1284, 562, 1080, +1294, 508, 1169, +1292, 508, 1257, +1273, 508, 1393, +1137, 691, 1596, +1203, 671, 1723, +1338, 742, 1822, +1453, 529, 1930, +1577, 824, 2068, +1421, 1044, 2212, +672, 1212, 2365, +1699, 762, 2468, +1788, 691, 2509, +1788, 691, 2509, +1788, 691, 2509, +1788, 691, 2509, +1788, 691, 2509, +1788, 691, 2509, +1788, 691, 2509, +1788, 691, 2509, +1788, 691, 2509, +1788, 691, 2509, +1258, 900, 682, +1259, 900, 693, +1259, 896, 712, +1259, 891, 736, +1259, 885, 767, +1259, 876, 806, +1259, 864, 852, +1259, 847, 908, +1259, 824, 973, +1261, 797, 1044, +1269, 774, 1117, +1280, 741, 1199, +1289, 701, 1290, +1270, 701, 1417, +1120, 852, 1611, +1159, 869, 1734, +1344, 895, 1836, +1405, 663, 1931, +1563, 942, 2078, +1372, 1118, 2218, +602, 1254, 2368, +1718, 915, 2470, +1784, 871, 2510, +1784, 871, 2510, +1784, 871, 2510, +1784, 871, 2510, +1784, 871, 2510, +1784, 871, 2510, +1784, 871, 2510, +1784, 871, 2510, +1784, 871, 2510, +1784, 871, 2510, +1314, 1134, 1183, +1314, 1134, 1187, +1315, 1134, 1191, +1316, 1134, 1197, +1317, 1134, 1206, +1319, 1134, 1216, +1321, 1134, 1230, +1324, 1134, 1248, +1328, 1134, 1271, +1333, 1131, 1302, +1340, 1120, 1345, +1349, 1105, 1396, +1358, 1087, 1457, +1341, 1087, 1528, +1216, 1158, 1687, +1159, 1142, 1780, +1317, 1176, 1886, +1360, 1041, 1962, +1486, 1159, 2104, +1228, 1237, 2234, +1015, 1275, 2368, +1721, 1100, 2471, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1399, 1351, 1421, +1399, 1351, 1423, +1400, 1351, 1426, +1400, 1351, 1429, +1401, 1351, 1434, +1403, 1351, 1441, +1405, 1351, 1449, +1407, 1351, 1460, +1410, 1351, 1475, +1407, 1351, 1495, +1382, 1351, 1523, +1347, 1351, 1559, +1336, 1345, 1602, +1319, 1345, 1655, +1383, 1345, 1736, +1321, 1339, 1825, +1361, 1378, 1936, +1367, 1360, 2014, +1313, 1367, 2124, +1014, 1399, 2255, +1228, 1332, 2375, +1681, 1258, 2475, +1839, 1219, 2510, +1839, 1219, 2510, +1839, 1219, 2510, +1839, 1219, 2510, +1839, 1219, 2510, +1839, 1219, 2510, +1839, 1219, 2510, +1839, 1219, 2510, +1839, 1219, 2510, +1839, 1219, 2510, +1514, 1522, 1673, +1514, 1522, 1673, +1513, 1522, 1674, +1512, 1522, 1674, +1510, 1522, 1676, +1508, 1522, 1677, +1505, 1522, 1679, +1501, 1522, 1682, +1495, 1522, 1685, +1489, 1523, 1691, +1475, 1525, 1706, +1447, 1525, 1730, +1412, 1526, 1762, +1397, 1537, 1811, +1426, 1537, 1865, +1415, 1525, 1919, +1395, 1535, 2005, +1299, 1551, 2087, +1205, 1526, 2170, +1197, 1525, 2279, +1402, 1488, 2382, +1717, 1446, 2476, +1900, 1416, 2509, +1900, 1416, 2509, +1900, 1416, 2509, +1900, 1416, 2509, +1900, 1416, 2509, +1900, 1416, 2509, +1900, 1416, 2509, +1900, 1416, 2509, +1900, 1416, 2509, +1900, 1416, 2509, +1678, 1669, 1879, +1678, 1669, 1879, +1678, 1669, 1880, +1678, 1669, 1882, +1678, 1669, 1884, +1678, 1669, 1886, +1678, 1669, 1889, +1678, 1669, 1894, +1678, 1669, 1900, +1674, 1670, 1903, +1671, 1673, 1909, +1667, 1678, 1917, +1659, 1683, 1928, +1644, 1684, 1948, +1597, 1684, 1976, +1591, 1683, 2015, +1577, 1683, 2072, +1536, 1664, 2140, +1423, 1683, 2226, +1349, 1660, 2299, +1619, 1615, 2384, +1819, 1607, 2477, +1912, 1605, 2509, +1912, 1605, 2509, +1912, 1605, 2509, +1912, 1605, 2509, +1912, 1605, 2509, +1912, 1605, 2509, +1912, 1605, 2509, +1912, 1605, 2509, +1912, 1605, 2509, +1912, 1605, 2509, +1848, 1802, 1967, +1848, 1802, 1968, +1849, 1802, 1969, +1849, 1803, 1970, +1849, 1803, 1972, +1850, 1804, 1973, +1851, 1805, 1976, +1851, 1806, 1980, +1853, 1807, 1984, +1853, 1808, 1990, +1846, 1810, 1998, +1837, 1813, 2009, +1825, 1817, 2022, +1820, 1817, 2033, +1804, 1811, 2052, +1785, 1809, 2084, +1764, 1804, 2118, +1767, 1811, 2177, +1736, 1801, 2237, +1751, 1800, 2307, +1774, 1800, 2391, +1919, 1797, 2474, +2000, 1784, 2514, +2000, 1784, 2514, +2000, 1784, 2514, +2000, 1784, 2514, +2000, 1784, 2514, +2000, 1784, 2514, +2000, 1784, 2514, +2000, 1784, 2514, +2000, 1784, 2514, +2000, 1784, 2514, +1992, 1958, 2037, +1992, 1958, 2037, +1992, 1958, 2037, +1992, 1958, 2037, +1992, 1958, 2037, +1992, 1958, 2038, +1992, 1958, 2038, +1992, 1958, 2039, +1992, 1958, 2040, +1991, 1958, 2042, +1988, 1958, 2046, +1983, 1958, 2052, +1978, 1958, 2060, +1974, 1962, 2077, +1963, 1962, 2086, +1955, 1958, 2110, +1955, 1962, 2141, +1953, 1964, 2193, +1941, 1953, 2231, +1931, 1953, 2310, +1966, 1959, 2394, +2048, 1966, 2481, +2129, 1963, 2515, +2129, 1963, 2515, +2129, 1963, 2515, +2129, 1963, 2515, +2129, 1963, 2515, +2129, 1963, 2515, +2129, 1963, 2515, +2129, 1963, 2515, +2129, 1963, 2515, +2129, 1963, 2515, +2134, 2127, 2070, +2134, 2127, 2070, +2134, 2127, 2071, +2135, 2127, 2071, +2135, 2127, 2073, +2135, 2127, 2074, +2135, 2127, 2076, +2136, 2127, 2078, +2137, 2127, 2081, +2137, 2127, 2084, +2139, 2127, 2085, +2140, 2127, 2087, +2141, 2127, 2091, +2135, 2127, 2100, +2127, 2127, 2112, +2129, 2128, 2129, +2136, 2135, 2161, +2130, 2135, 2208, +2125, 2127, 2253, +2141, 2131, 2316, +2170, 2132, 2397, +2230, 2150, 2485, +2266, 2159, 2520, +2266, 2159, 2520, +2266, 2159, 2520, +2266, 2159, 2520, +2266, 2159, 2520, +2266, 2159, 2520, +2266, 2159, 2520, +2266, 2159, 2520, +2266, 2159, 2520, +2266, 2159, 2520, +2377, 2355, 2126, +2377, 2355, 2127, +2377, 2355, 2127, +2377, 2355, 2127, +2377, 2355, 2127, +2378, 2355, 2127, +2378, 2355, 2128, +2378, 2355, 2128, +2378, 2355, 2129, +2379, 2355, 2130, +2380, 2355, 2133, +2380, 2355, 2135, +2380, 2355, 2137, +2378, 2357, 2143, +2376, 2356, 2147, +2376, 2354, 2159, +2375, 2358, 2194, +2375, 2357, 2230, +2381, 2357, 2273, +2399, 2366, 2335, +2418, 2368, 2408, +2472, 2387, 2495, +2499, 2395, 2533, +2499, 2395, 2533, +2499, 2395, 2533, +2499, 2395, 2533, +2499, 2395, 2533, +2499, 2395, 2533, +2499, 2395, 2533, +2499, 2395, 2533, +2499, 2395, 2533, +2499, 2395, 2533, +2680, 2655, 1964, +2680, 2655, 1964, +2680, 2655, 1964, +2680, 2655, 1964, +2680, 2655, 1964, +2680, 2655, 1964, +2680, 2655, 1964, +2680, 2655, 1964, +2679, 2655, 1968, +2679, 2655, 1970, +2679, 2654, 1965, +2678, 2652, 1958, +2677, 2650, 1949, +2677, 2648, 1945, +2675, 2653, 1962, +2676, 2656, 2011, +2680, 2657, 2064, +2681, 2657, 2122, +2684, 2657, 2213, +2688, 2662, 2314, +2696, 2667, 2413, +2716, 2679, 2527, +2727, 2684, 2578, +2727, 2684, 2578, +2727, 2684, 2578, +2727, 2684, 2578, +2727, 2684, 2578, +2727, 2684, 2578, +2727, 2684, 2578, +2727, 2684, 2578, +2727, 2684, 2578, +2727, 2684, 2578, +2713, 2769, 2427, +2713, 2769, 2427, +2713, 2769, 2427, +2713, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2429, +2714, 2769, 2429, +2715, 2769, 2430, +2717, 2769, 2431, +2718, 2770, 2433, +2719, 2772, 2443, +2718, 2772, 2447, +2715, 2770, 2444, +2712, 2771, 2455, +2714, 2774, 2492, +2716, 2775, 2523, +2714, 2775, 2560, +2719, 2781, 2625, +2725, 2789, 2703, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2713, 2769, 2427, +2713, 2769, 2427, +2713, 2769, 2427, +2713, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2429, +2714, 2769, 2429, +2715, 2769, 2430, +2717, 2769, 2431, +2718, 2770, 2433, +2719, 2772, 2443, +2718, 2772, 2447, +2715, 2770, 2444, +2712, 2771, 2455, +2714, 2774, 2492, +2716, 2775, 2523, +2714, 2775, 2560, +2719, 2781, 2625, +2725, 2789, 2703, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2713, 2769, 2427, +2713, 2769, 2427, +2713, 2769, 2427, +2713, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2429, +2714, 2769, 2429, +2715, 2769, 2430, +2717, 2769, 2431, +2718, 2770, 2433, +2719, 2772, 2443, +2718, 2772, 2447, +2715, 2770, 2444, +2712, 2771, 2455, +2714, 2774, 2492, +2716, 2775, 2523, +2714, 2775, 2560, +2719, 2781, 2625, +2725, 2789, 2703, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2713, 2769, 2427, +2713, 2769, 2427, +2713, 2769, 2427, +2713, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2429, +2714, 2769, 2429, +2715, 2769, 2430, +2717, 2769, 2431, +2718, 2770, 2433, +2719, 2772, 2443, +2718, 2772, 2447, +2715, 2770, 2444, +2712, 2771, 2455, +2714, 2774, 2492, +2716, 2775, 2523, +2714, 2775, 2560, +2719, 2781, 2625, +2725, 2789, 2703, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2713, 2769, 2427, +2713, 2769, 2427, +2713, 2769, 2427, +2713, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2429, +2714, 2769, 2429, +2715, 2769, 2430, +2717, 2769, 2431, +2718, 2770, 2433, +2719, 2772, 2443, +2718, 2772, 2447, +2715, 2770, 2444, +2712, 2771, 2455, +2714, 2774, 2492, +2716, 2775, 2523, +2714, 2775, 2560, +2719, 2781, 2625, +2725, 2789, 2703, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2713, 2769, 2427, +2713, 2769, 2427, +2713, 2769, 2427, +2713, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2429, +2714, 2769, 2429, +2715, 2769, 2430, +2717, 2769, 2431, +2718, 2770, 2433, +2719, 2772, 2443, +2718, 2772, 2447, +2715, 2770, 2444, +2712, 2771, 2455, +2714, 2774, 2492, +2716, 2775, 2523, +2714, 2775, 2560, +2719, 2781, 2625, +2725, 2789, 2703, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2713, 2769, 2427, +2713, 2769, 2427, +2713, 2769, 2427, +2713, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2429, +2714, 2769, 2429, +2715, 2769, 2430, +2717, 2769, 2431, +2718, 2770, 2433, +2719, 2772, 2443, +2718, 2772, 2447, +2715, 2770, 2444, +2712, 2771, 2455, +2714, 2774, 2492, +2716, 2775, 2523, +2714, 2775, 2560, +2719, 2781, 2625, +2725, 2789, 2703, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2713, 2769, 2427, +2713, 2769, 2427, +2713, 2769, 2427, +2713, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2429, +2714, 2769, 2429, +2715, 2769, 2430, +2717, 2769, 2431, +2718, 2770, 2433, +2719, 2772, 2443, +2718, 2772, 2447, +2715, 2770, 2444, +2712, 2771, 2455, +2714, 2774, 2492, +2716, 2775, 2523, +2714, 2775, 2560, +2719, 2781, 2625, +2725, 2789, 2703, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2713, 2769, 2427, +2713, 2769, 2427, +2713, 2769, 2427, +2713, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2429, +2714, 2769, 2429, +2715, 2769, 2430, +2717, 2769, 2431, +2718, 2770, 2433, +2719, 2772, 2443, +2718, 2772, 2447, +2715, 2770, 2444, +2712, 2771, 2455, +2714, 2774, 2492, +2716, 2775, 2523, +2714, 2775, 2560, +2719, 2781, 2625, +2725, 2789, 2703, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2713, 2769, 2427, +2713, 2769, 2427, +2713, 2769, 2427, +2713, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2429, +2714, 2769, 2429, +2715, 2769, 2430, +2717, 2769, 2431, +2718, 2770, 2433, +2719, 2772, 2443, +2718, 2772, 2447, +2715, 2770, 2444, +2712, 2771, 2455, +2714, 2774, 2492, +2716, 2775, 2523, +2714, 2775, 2560, +2719, 2781, 2625, +2725, 2789, 2703, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +1471, 0, 0, +1471, 0, 0, +1472, 0, 0, +1472, 0, 18, +1473, 0, 98, +1475, 0, 188, +1476, 0, 285, +1478, 0, 389, +1481, 0, 499, +1485, 0, 614, +1490, 0, 733, +1496, 0, 855, +1498, 0, 1011, +1486, 0, 1266, +1470, 0, 1472, +1490, 0, 1659, +1524, 0, 1789, +1589, 0, 1904, +1654, 0, 2053, +1531, 645, 2197, +923, 1046, 2356, +1710, 0, 2469, +1801, 0, 2506, +1801, 0, 2506, +1801, 0, 2506, +1801, 0, 2506, +1801, 0, 2506, +1801, 0, 2506, +1801, 0, 2506, +1801, 0, 2506, +1801, 0, 2506, +1801, 0, 2506, +1471, 0, 0, +1471, 0, 0, +1471, 0, 17, +1472, 0, 78, +1473, 0, 150, +1474, 0, 230, +1476, 0, 319, +1478, 0, 417, +1481, 0, 521, +1485, 0, 631, +1489, 0, 746, +1496, 0, 865, +1497, 0, 1017, +1486, 0, 1269, +1469, 0, 1474, +1489, 0, 1660, +1524, 0, 1790, +1589, 0, 1905, +1653, 0, 2053, +1531, 656, 2197, +924, 1049, 2356, +1710, 0, 2469, +1801, 0, 2506, +1801, 0, 2506, +1801, 0, 2506, +1801, 0, 2506, +1801, 0, 2506, +1801, 0, 2506, +1801, 0, 2506, +1801, 0, 2506, +1801, 0, 2506, +1801, 0, 2506, +1471, 0, 0, +1471, 0, 17, +1471, 0, 97, +1472, 0, 149, +1472, 0, 211, +1474, 0, 282, +1475, 0, 363, +1477, 0, 452, +1480, 0, 549, +1484, 0, 653, +1489, 0, 763, +1496, 0, 878, +1497, 0, 1026, +1485, 0, 1273, +1469, 0, 1476, +1489, 0, 1661, +1524, 0, 1791, +1588, 0, 1905, +1652, 0, 2054, +1530, 671, 2198, +926, 1053, 2357, +1711, 0, 2469, +1802, 0, 2506, +1802, 0, 2506, +1802, 0, 2506, +1802, 0, 2506, +1802, 0, 2506, +1802, 0, 2506, +1802, 0, 2506, +1802, 0, 2506, +1802, 0, 2506, +1802, 0, 2506, +1471, 0, 18, +1471, 0, 78, +1471, 0, 149, +1471, 0, 229, +1472, 0, 281, +1473, 0, 343, +1475, 0, 414, +1477, 0, 494, +1480, 0, 584, +1483, 0, 681, +1488, 0, 785, +1495, 0, 895, +1496, 0, 1039, +1485, 0, 1278, +1468, 0, 1480, +1488, 0, 1662, +1524, 0, 1793, +1587, 0, 1907, +1651, 0, 2054, +1529, 690, 2198, +928, 1058, 2357, +1712, 0, 2469, +1803, 0, 2506, +1803, 0, 2506, +1803, 0, 2506, +1803, 0, 2506, +1803, 0, 2506, +1803, 0, 2506, +1803, 0, 2506, +1803, 0, 2506, +1803, 0, 2506, +1803, 0, 2506, +1471, 0, 98, +1471, 0, 150, +1471, 0, 211, +1471, 0, 281, +1471, 0, 361, +1472, 0, 413, +1474, 0, 475, +1476, 0, 546, +1479, 0, 627, +1482, 0, 716, +1487, 0, 813, +1494, 0, 917, +1495, 0, 1055, +1484, 0, 1285, +1467, 0, 1484, +1487, 0, 1664, +1524, 0, 1795, +1585, 0, 1908, +1650, 0, 2055, +1527, 714, 2199, +931, 1065, 2357, +1713, 0, 2469, +1804, 0, 2506, +1804, 0, 2506, +1804, 0, 2506, +1804, 0, 2506, +1804, 0, 2506, +1804, 0, 2506, +1804, 0, 2506, +1804, 0, 2506, +1804, 0, 2506, +1804, 0, 2506, +1471, 0, 188, +1471, 0, 230, +1471, 0, 282, +1471, 0, 343, +1471, 0, 413, +1471, 0, 493, +1472, 0, 545, +1475, 0, 607, +1478, 0, 678, +1481, 0, 759, +1486, 0, 848, +1493, 0, 946, +1494, 0, 1075, +1482, 0, 1294, +1466, 0, 1490, +1486, 0, 1667, +1524, 30, 1798, +1584, 0, 1911, +1648, 132, 2057, +1525, 745, 2200, +935, 1074, 2358, +1715, 0, 2469, +1806, 0, 2506, +1806, 0, 2506, +1806, 0, 2506, +1806, 0, 2506, +1806, 0, 2506, +1806, 0, 2506, +1806, 0, 2506, +1806, 0, 2506, +1806, 0, 2506, +1806, 0, 2506, +1471, 121, 285, +1471, 106, 319, +1471, 85, 363, +1471, 56, 414, +1471, 13, 475, +1471, 0, 545, +1471, 0, 625, +1473, 0, 677, +1476, 0, 739, +1480, 0, 810, +1485, 0, 891, +1491, 0, 980, +1493, 0, 1102, +1481, 0, 1306, +1464, 0, 1497, +1485, 0, 1670, +1524, 163, 1802, +1581, 32, 1914, +1646, 264, 2058, +1522, 783, 2201, +940, 1085, 2358, +1716, 32, 2469, +1809, 0, 2506, +1809, 0, 2506, +1809, 0, 2506, +1809, 0, 2506, +1809, 0, 2506, +1809, 0, 2506, +1809, 0, 2506, +1809, 0, 2506, +1809, 0, 2506, +1809, 0, 2506, +1471, 264, 389, +1471, 253, 417, +1471, 238, 452, +1471, 217, 494, +1471, 188, 546, +1471, 146, 607, +1471, 82, 677, +1471, 0, 757, +1474, 0, 809, +1478, 0, 871, +1483, 0, 942, +1489, 0, 1023, +1491, 0, 1135, +1479, 0, 1321, +1462, 0, 1507, +1482, 0, 1674, +1524, 295, 1807, +1578, 164, 1918, +1644, 396, 2061, +1518, 830, 2203, +947, 1100, 2359, +1719, 164, 2469, +1812, 0, 2506, +1812, 0, 2506, +1812, 0, 2506, +1812, 0, 2506, +1812, 0, 2506, +1812, 0, 2506, +1812, 0, 2506, +1812, 0, 2506, +1812, 0, 2506, +1812, 0, 2506, +1471, 404, 499, +1471, 396, 521, +1471, 385, 549, +1471, 370, 584, +1471, 349, 627, +1471, 320, 678, +1471, 277, 739, +1471, 214, 809, +1471, 111, 889, +1475, 111, 942, +1480, 111, 1003, +1486, 111, 1075, +1488, 111, 1176, +1476, 111, 1340, +1459, 111, 1520, +1480, 111, 1680, +1524, 426, 1814, +1573, 296, 1923, +1640, 528, 2064, +1513, 885, 2205, +956, 1119, 2361, +1717, 296, 2469, +1816, 111, 2506, +1816, 111, 2506, +1816, 111, 2506, +1816, 111, 2506, +1816, 111, 2506, +1816, 111, 2506, +1816, 111, 2506, +1816, 111, 2506, +1816, 111, 2506, +1816, 111, 2506, +1471, 542, 614, +1471, 536, 631, +1471, 528, 653, +1471, 517, 681, +1471, 502, 716, +1471, 482, 759, +1471, 452, 810, +1471, 410, 871, +1471, 346, 942, +1471, 244, 1021, +1476, 244, 1074, +1483, 244, 1135, +1484, 244, 1225, +1472, 244, 1369, +1455, 244, 1537, +1476, 244, 1687, +1520, 502, 1820, +1567, 428, 1930, +1634, 660, 2068, +1506, 950, 2208, +968, 1143, 2362, +1715, 428, 2469, +1821, 244, 2506, +1821, 244, 2506, +1821, 244, 2506, +1821, 244, 2506, +1821, 244, 2506, +1821, 244, 2506, +1821, 244, 2506, +1821, 244, 2506, +1821, 244, 2506, +1821, 244, 2506, +1471, 678, 733, +1471, 674, 746, +1471, 668, 763, +1471, 660, 785, +1471, 649, 813, +1471, 634, 848, +1471, 613, 891, +1471, 584, 942, +1471, 542, 1003, +1471, 478, 1074, +1471, 376, 1153, +1478, 376, 1206, +1479, 376, 1283, +1467, 376, 1412, +1450, 376, 1559, +1471, 376, 1701, +1516, 581, 1827, +1566, 591, 1940, +1627, 792, 2074, +1496, 1025, 2212, +983, 1174, 2364, +1712, 560, 2468, +1828, 376, 2506, +1828, 376, 2506, +1828, 376, 2506, +1828, 376, 2506, +1828, 376, 2506, +1828, 376, 2506, +1828, 376, 2506, +1828, 376, 2506, +1828, 376, 2506, +1828, 376, 2506, +1471, 814, 855, +1471, 811, 865, +1471, 806, 878, +1471, 800, 895, +1471, 792, 917, +1471, 782, 946, +1471, 767, 980, +1471, 746, 1023, +1471, 717, 1075, +1471, 674, 1135, +1471, 611, 1206, +1471, 508, 1285, +1472, 508, 1352, +1460, 508, 1465, +1443, 508, 1587, +1464, 508, 1721, +1509, 670, 1836, +1566, 751, 1952, +1617, 925, 2081, +1483, 1109, 2218, +935, 1212, 2368, +1708, 692, 2467, +1838, 508, 2506, +1838, 508, 2506, +1838, 508, 2506, +1838, 508, 2506, +1838, 508, 2506, +1838, 508, 2506, +1838, 508, 2506, +1838, 508, 2506, +1838, 508, 2506, +1838, 508, 2506, +1467, 954, 955, +1467, 954, 960, +1467, 951, 971, +1467, 947, 985, +1467, 941, 1004, +1467, 933, 1027, +1467, 923, 1056, +1467, 908, 1092, +1467, 888, 1137, +1467, 859, 1191, +1467, 818, 1254, +1467, 755, 1326, +1471, 701, 1400, +1458, 701, 1503, +1441, 701, 1611, +1446, 742, 1738, +1508, 833, 1851, +1542, 872, 1959, +1602, 1037, 2091, +1448, 1185, 2224, +886, 1254, 2372, +1718, 855, 2468, +1839, 727, 2507, +1839, 727, 2507, +1839, 727, 2507, +1839, 727, 2507, +1839, 727, 2507, +1839, 727, 2507, +1839, 727, 2507, +1839, 727, 2507, +1839, 727, 2507, +1839, 727, 2507, +1503, 1167, 1293, +1503, 1167, 1296, +1504, 1167, 1299, +1504, 1167, 1304, +1505, 1167, 1311, +1506, 1167, 1319, +1508, 1167, 1330, +1510, 1167, 1344, +1512, 1167, 1363, +1514, 1162, 1390, +1514, 1141, 1432, +1514, 1111, 1482, +1517, 1087, 1536, +1506, 1087, 1597, +1491, 1087, 1687, +1446, 1077, 1783, +1489, 1144, 1900, +1509, 1144, 1988, +1532, 1221, 2116, +1329, 1289, 2240, +1151, 1275, 2372, +1721, 1061, 2469, +1839, 1003, 2508, +1839, 1003, 2508, +1839, 1003, 2508, +1839, 1003, 2508, +1839, 1003, 2508, +1839, 1003, 2508, +1839, 1003, 2508, +1839, 1003, 2508, +1839, 1003, 2508, +1839, 1003, 2508, +1547, 1351, 1534, +1547, 1351, 1536, +1547, 1351, 1538, +1548, 1351, 1541, +1549, 1351, 1545, +1550, 1351, 1550, +1551, 1351, 1556, +1553, 1351, 1565, +1555, 1351, 1577, +1558, 1351, 1592, +1563, 1351, 1611, +1569, 1351, 1636, +1573, 1345, 1671, +1563, 1345, 1717, +1550, 1345, 1771, +1498, 1335, 1850, +1489, 1358, 1942, +1476, 1376, 2036, +1418, 1388, 2147, +1096, 1399, 2261, +1290, 1332, 2375, +1730, 1258, 2473, +1839, 1219, 2510, +1839, 1219, 2510, +1839, 1219, 2510, +1839, 1219, 2510, +1839, 1219, 2510, +1839, 1219, 2510, +1839, 1219, 2510, +1839, 1219, 2510, +1839, 1219, 2510, +1839, 1219, 2510, +1626, 1522, 1733, +1625, 1522, 1734, +1625, 1522, 1734, +1623, 1522, 1735, +1622, 1522, 1736, +1621, 1522, 1737, +1618, 1522, 1739, +1615, 1522, 1742, +1611, 1522, 1745, +1605, 1522, 1749, +1605, 1522, 1760, +1609, 1522, 1778, +1596, 1523, 1805, +1587, 1534, 1850, +1574, 1537, 1894, +1558, 1522, 1941, +1509, 1521, 2012, +1413, 1563, 2107, +1330, 1535, 2187, +1296, 1523, 2285, +1459, 1491, 2382, +1767, 1446, 2474, +1910, 1416, 2509, +1910, 1416, 2509, +1910, 1416, 2509, +1910, 1416, 2509, +1910, 1416, 2509, +1910, 1416, 2509, +1910, 1416, 2509, +1910, 1416, 2509, +1910, 1416, 2509, +1910, 1416, 2509, +1737, 1669, 1898, +1737, 1669, 1899, +1737, 1669, 1900, +1737, 1669, 1901, +1737, 1669, 1903, +1737, 1669, 1905, +1737, 1669, 1908, +1737, 1669, 1913, +1737, 1669, 1918, +1732, 1669, 1922, +1727, 1669, 1925, +1719, 1669, 1930, +1711, 1672, 1940, +1697, 1674, 1960, +1687, 1684, 2003, +1675, 1681, 2036, +1638, 1672, 2080, +1565, 1674, 2153, +1492, 1672, 2229, +1526, 1649, 2305, +1680, 1621, 2385, +1871, 1607, 2473, +1954, 1605, 2509, +1954, 1605, 2509, +1954, 1605, 2509, +1954, 1605, 2509, +1954, 1605, 2509, +1954, 1605, 2509, +1954, 1605, 2509, +1954, 1605, 2509, +1954, 1605, 2509, +1954, 1605, 2509, +1862, 1802, 1972, +1862, 1802, 1973, +1862, 1802, 1973, +1862, 1803, 1975, +1862, 1803, 1976, +1863, 1804, 1978, +1864, 1805, 1981, +1865, 1806, 1984, +1866, 1807, 1989, +1868, 1809, 1995, +1868, 1809, 2004, +1868, 1809, 2014, +1861, 1811, 2027, +1856, 1811, 2038, +1842, 1811, 2056, +1824, 1809, 2088, +1829, 1804, 2122, +1805, 1804, 2175, +1793, 1801, 2242, +1782, 1800, 2309, +1820, 1797, 2390, +1940, 1796, 2477, +2014, 1783, 2512, +2014, 1783, 2512, +2014, 1783, 2512, +2014, 1783, 2512, +2014, 1783, 2512, +2014, 1783, 2512, +2014, 1783, 2512, +2014, 1783, 2512, +2014, 1783, 2512, +2014, 1783, 2512, +1992, 1958, 2037, +1992, 1958, 2037, +1992, 1958, 2037, +1992, 1958, 2037, +1992, 1958, 2037, +1992, 1958, 2038, +1992, 1958, 2038, +1992, 1958, 2039, +1992, 1958, 2040, +1992, 1958, 2041, +1992, 1958, 2042, +1992, 1958, 2044, +1989, 1958, 2051, +1984, 1962, 2068, +1979, 1968, 2090, +1970, 1962, 2115, +1966, 1962, 2148, +1966, 1964, 2190, +1964, 1947, 2231, +1943, 1947, 2310, +1978, 1965, 2395, +2061, 1971, 2481, +2133, 1968, 2516, +2133, 1968, 2516, +2133, 1968, 2516, +2133, 1968, 2516, +2133, 1968, 2516, +2133, 1968, 2516, +2133, 1968, 2516, +2133, 1968, 2516, +2133, 1968, 2516, +2133, 1968, 2516, +2142, 2127, 2061, +2142, 2127, 2061, +2142, 2127, 2062, +2142, 2127, 2063, +2142, 2127, 2064, +2143, 2127, 2065, +2143, 2127, 2067, +2143, 2127, 2069, +2144, 2127, 2072, +2145, 2127, 2076, +2146, 2127, 2082, +2148, 2127, 2089, +2148, 2127, 2095, +2143, 2127, 2104, +2135, 2127, 2116, +2137, 2127, 2132, +2144, 2131, 2161, +2141, 2135, 2204, +2133, 2127, 2256, +2149, 2134, 2316, +2174, 2130, 2395, +2237, 2146, 2485, +2277, 2159, 2520, +2277, 2159, 2520, +2277, 2159, 2520, +2277, 2159, 2520, +2277, 2159, 2520, +2277, 2159, 2520, +2277, 2159, 2520, +2277, 2159, 2520, +2277, 2159, 2520, +2277, 2159, 2520, +2379, 2355, 2126, +2380, 2355, 2127, +2380, 2355, 2127, +2380, 2355, 2127, +2380, 2355, 2127, +2380, 2355, 2127, +2380, 2355, 2128, +2381, 2355, 2128, +2381, 2355, 2129, +2381, 2355, 2130, +2382, 2355, 2131, +2382, 2355, 2133, +2382, 2355, 2135, +2381, 2357, 2141, +2379, 2358, 2148, +2379, 2355, 2161, +2378, 2357, 2192, +2376, 2358, 2230, +2382, 2354, 2270, +2402, 2364, 2335, +2420, 2368, 2405, +2473, 2383, 2495, +2499, 2394, 2533, +2499, 2394, 2533, +2499, 2394, 2533, +2499, 2394, 2533, +2499, 2394, 2533, +2499, 2394, 2533, +2499, 2394, 2533, +2499, 2394, 2533, +2499, 2394, 2533, +2499, 2394, 2533, +2681, 2657, 1947, +2681, 2657, 1947, +2681, 2657, 1947, +2681, 2657, 1947, +2681, 2657, 1947, +2681, 2657, 1947, +2681, 2657, 1947, +2681, 2657, 1947, +2681, 2656, 1951, +2680, 2656, 1956, +2680, 2656, 1963, +2679, 2655, 1973, +2679, 2654, 1971, +2678, 2651, 1967, +2678, 2651, 1962, +2678, 2655, 2011, +2679, 2657, 2064, +2682, 2657, 2129, +2684, 2657, 2213, +2688, 2661, 2311, +2699, 2668, 2415, +2717, 2681, 2528, +2726, 2683, 2577, +2726, 2683, 2577, +2726, 2683, 2577, +2726, 2683, 2577, +2726, 2683, 2577, +2726, 2683, 2577, +2726, 2683, 2577, +2726, 2683, 2577, +2726, 2683, 2577, +2726, 2683, 2577, +2715, 2769, 2427, +2716, 2769, 2427, +2716, 2769, 2427, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2429, +2716, 2769, 2429, +2717, 2769, 2430, +2717, 2769, 2431, +2718, 2770, 2433, +2719, 2772, 2443, +2720, 2775, 2457, +2716, 2772, 2452, +2713, 2770, 2455, +2714, 2773, 2485, +2718, 2774, 2523, +2717, 2777, 2567, +2721, 2782, 2627, +2725, 2788, 2702, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2715, 2769, 2427, +2716, 2769, 2427, +2716, 2769, 2427, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2429, +2716, 2769, 2429, +2717, 2769, 2430, +2717, 2769, 2431, +2718, 2770, 2433, +2719, 2772, 2443, +2720, 2775, 2457, +2716, 2772, 2452, +2713, 2770, 2455, +2714, 2773, 2485, +2718, 2774, 2523, +2717, 2777, 2567, +2721, 2782, 2627, +2725, 2788, 2702, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2715, 2769, 2427, +2716, 2769, 2427, +2716, 2769, 2427, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2429, +2716, 2769, 2429, +2717, 2769, 2430, +2717, 2769, 2431, +2718, 2770, 2433, +2719, 2772, 2443, +2720, 2775, 2457, +2716, 2772, 2452, +2713, 2770, 2455, +2714, 2773, 2485, +2718, 2774, 2523, +2717, 2777, 2567, +2721, 2782, 2627, +2725, 2788, 2702, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2715, 2769, 2427, +2716, 2769, 2427, +2716, 2769, 2427, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2429, +2716, 2769, 2429, +2717, 2769, 2430, +2717, 2769, 2431, +2718, 2770, 2433, +2719, 2772, 2443, +2720, 2775, 2457, +2716, 2772, 2452, +2713, 2770, 2455, +2714, 2773, 2485, +2718, 2774, 2523, +2717, 2777, 2567, +2721, 2782, 2627, +2725, 2788, 2702, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2715, 2769, 2427, +2716, 2769, 2427, +2716, 2769, 2427, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2429, +2716, 2769, 2429, +2717, 2769, 2430, +2717, 2769, 2431, +2718, 2770, 2433, +2719, 2772, 2443, +2720, 2775, 2457, +2716, 2772, 2452, +2713, 2770, 2455, +2714, 2773, 2485, +2718, 2774, 2523, +2717, 2777, 2567, +2721, 2782, 2627, +2725, 2788, 2702, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2715, 2769, 2427, +2716, 2769, 2427, +2716, 2769, 2427, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2429, +2716, 2769, 2429, +2717, 2769, 2430, +2717, 2769, 2431, +2718, 2770, 2433, +2719, 2772, 2443, +2720, 2775, 2457, +2716, 2772, 2452, +2713, 2770, 2455, +2714, 2773, 2485, +2718, 2774, 2523, +2717, 2777, 2567, +2721, 2782, 2627, +2725, 2788, 2702, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2715, 2769, 2427, +2716, 2769, 2427, +2716, 2769, 2427, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2429, +2716, 2769, 2429, +2717, 2769, 2430, +2717, 2769, 2431, +2718, 2770, 2433, +2719, 2772, 2443, +2720, 2775, 2457, +2716, 2772, 2452, +2713, 2770, 2455, +2714, 2773, 2485, +2718, 2774, 2523, +2717, 2777, 2567, +2721, 2782, 2627, +2725, 2788, 2702, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2715, 2769, 2427, +2716, 2769, 2427, +2716, 2769, 2427, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2429, +2716, 2769, 2429, +2717, 2769, 2430, +2717, 2769, 2431, +2718, 2770, 2433, +2719, 2772, 2443, +2720, 2775, 2457, +2716, 2772, 2452, +2713, 2770, 2455, +2714, 2773, 2485, +2718, 2774, 2523, +2717, 2777, 2567, +2721, 2782, 2627, +2725, 2788, 2702, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2715, 2769, 2427, +2716, 2769, 2427, +2716, 2769, 2427, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2429, +2716, 2769, 2429, +2717, 2769, 2430, +2717, 2769, 2431, +2718, 2770, 2433, +2719, 2772, 2443, +2720, 2775, 2457, +2716, 2772, 2452, +2713, 2770, 2455, +2714, 2773, 2485, +2718, 2774, 2523, +2717, 2777, 2567, +2721, 2782, 2627, +2725, 2788, 2702, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2715, 2769, 2427, +2716, 2769, 2427, +2716, 2769, 2427, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2429, +2716, 2769, 2429, +2717, 2769, 2430, +2717, 2769, 2431, +2718, 2770, 2433, +2719, 2772, 2443, +2720, 2775, 2457, +2716, 2772, 2452, +2713, 2770, 2455, +2714, 2773, 2485, +2718, 2774, 2523, +2717, 2777, 2567, +2721, 2782, 2627, +2725, 2788, 2702, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +1677, 0, 708, +1676, 0, 722, +1676, 0, 740, +1675, 0, 763, +1674, 0, 792, +1672, 0, 829, +1670, 0, 873, +1667, 0, 927, +1663, 0, 989, +1658, 0, 1062, +1657, 0, 1123, +1662, 0, 1179, +1666, 0, 1250, +1649, 0, 1372, +1636, 0, 1533, +1634, 0, 1672, +1671, 0, 1828, +1667, 0, 1929, +1689, 355, 2079, +1608, 810, 2211, +1232, 994, 2359, +1771, 0, 2470, +1854, 0, 2508, +1854, 0, 2508, +1854, 0, 2508, +1854, 0, 2508, +1854, 0, 2508, +1854, 0, 2508, +1854, 0, 2508, +1854, 0, 2508, +1854, 0, 2508, +1854, 0, 2508, +1676, 0, 726, +1676, 0, 735, +1675, 0, 753, +1674, 0, 775, +1673, 0, 804, +1672, 0, 839, +1669, 0, 883, +1667, 0, 935, +1663, 0, 997, +1658, 0, 1068, +1657, 0, 1129, +1662, 0, 1184, +1666, 0, 1253, +1649, 0, 1375, +1636, 0, 1535, +1635, 0, 1673, +1670, 0, 1829, +1666, 0, 1930, +1689, 372, 2079, +1607, 814, 2211, +1238, 995, 2359, +1771, 0, 2470, +1855, 0, 2508, +1855, 0, 2508, +1855, 0, 2508, +1855, 0, 2508, +1855, 0, 2508, +1855, 0, 2508, +1855, 0, 2508, +1855, 0, 2508, +1855, 0, 2508, +1855, 0, 2508, +1676, 0, 749, +1675, 0, 758, +1675, 0, 770, +1674, 0, 791, +1673, 0, 819, +1672, 0, 853, +1669, 0, 895, +1666, 0, 946, +1663, 0, 1007, +1657, 0, 1077, +1657, 0, 1136, +1661, 0, 1191, +1665, 0, 1259, +1649, 0, 1378, +1636, 0, 1537, +1635, 0, 1674, +1669, 0, 1829, +1665, 0, 1930, +1688, 394, 2080, +1606, 821, 2211, +1245, 996, 2359, +1771, 0, 2470, +1855, 0, 2508, +1855, 0, 2508, +1855, 0, 2508, +1855, 0, 2508, +1855, 0, 2508, +1855, 0, 2508, +1855, 0, 2508, +1855, 0, 2508, +1855, 0, 2508, +1855, 0, 2508, +1675, 0, 777, +1674, 0, 786, +1674, 0, 797, +1674, 0, 812, +1673, 0, 838, +1671, 0, 871, +1669, 0, 912, +1666, 0, 961, +1662, 0, 1020, +1657, 0, 1088, +1656, 0, 1146, +1661, 0, 1199, +1665, 0, 1266, +1649, 0, 1383, +1636, 0, 1541, +1636, 0, 1676, +1668, 0, 1830, +1663, 0, 1932, +1687, 422, 2080, +1605, 829, 2212, +1255, 998, 2359, +1772, 0, 2470, +1855, 0, 2508, +1855, 0, 2508, +1855, 0, 2508, +1855, 0, 2508, +1855, 0, 2508, +1855, 0, 2508, +1855, 0, 2508, +1855, 0, 2508, +1855, 0, 2508, +1855, 0, 2508, +1674, 0, 814, +1673, 0, 822, +1673, 0, 832, +1673, 0, 845, +1672, 0, 863, +1671, 0, 894, +1668, 0, 933, +1666, 0, 980, +1662, 0, 1036, +1656, 0, 1102, +1655, 0, 1159, +1660, 0, 1210, +1664, 0, 1276, +1649, 0, 1390, +1636, 0, 1545, +1637, 0, 1679, +1667, 0, 1831, +1662, 0, 1934, +1686, 457, 2081, +1603, 840, 2212, +1268, 1001, 2360, +1772, 0, 2470, +1856, 0, 2508, +1856, 0, 2508, +1856, 0, 2508, +1856, 0, 2508, +1856, 0, 2508, +1856, 0, 2508, +1856, 0, 2508, +1856, 0, 2508, +1856, 0, 2508, +1856, 0, 2508, +1672, 0, 858, +1672, 0, 865, +1672, 0, 874, +1671, 0, 887, +1671, 0, 903, +1670, 0, 923, +1667, 0, 960, +1664, 0, 1004, +1661, 0, 1058, +1655, 0, 1121, +1655, 0, 1175, +1659, 0, 1225, +1663, 0, 1289, +1649, 0, 1398, +1636, 0, 1551, +1639, 0, 1683, +1666, 0, 1832, +1659, 132, 1936, +1684, 500, 2083, +1600, 854, 2213, +1285, 1004, 2360, +1773, 0, 2470, +1857, 0, 2508, +1857, 0, 2508, +1857, 0, 2508, +1857, 0, 2508, +1857, 0, 2508, +1857, 0, 2508, +1857, 0, 2508, +1857, 0, 2508, +1857, 0, 2508, +1857, 0, 2508, +1670, 32, 911, +1669, 32, 917, +1669, 32, 926, +1669, 32, 937, +1668, 32, 951, +1667, 32, 970, +1667, 32, 993, +1663, 32, 1035, +1660, 32, 1085, +1654, 32, 1144, +1654, 32, 1196, +1658, 32, 1244, +1662, 0, 1305, +1649, 0, 1410, +1636, 0, 1560, +1641, 32, 1688, +1663, 32, 1833, +1656, 264, 1939, +1682, 551, 2084, +1596, 873, 2214, +1306, 1009, 2361, +1773, 0, 2470, +1859, 32, 2508, +1859, 32, 2508, +1859, 32, 2508, +1859, 32, 2508, +1859, 32, 2508, +1859, 32, 2508, +1859, 32, 2508, +1859, 32, 2508, +1859, 32, 2508, +1859, 32, 2508, +1667, 164, 973, +1667, 164, 979, +1666, 164, 986, +1666, 164, 996, +1666, 164, 1009, +1664, 164, 1025, +1663, 164, 1046, +1662, 164, 1073, +1658, 164, 1119, +1653, 164, 1174, +1652, 164, 1223, +1657, 164, 1268, +1661, 137, 1326, +1649, 0, 1424, +1636, 0, 1570, +1644, 164, 1695, +1661, 164, 1835, +1652, 396, 1943, +1680, 612, 2086, +1591, 896, 2215, +1333, 1014, 2362, +1774, 0, 2470, +1861, 164, 2508, +1861, 164, 2508, +1861, 164, 2508, +1861, 164, 2508, +1861, 164, 2508, +1861, 164, 2508, +1861, 164, 2508, +1861, 164, 2508, +1861, 164, 2508, +1861, 164, 2508, +1663, 296, 1045, +1663, 296, 1050, +1663, 296, 1056, +1662, 296, 1065, +1662, 296, 1075, +1661, 296, 1090, +1660, 296, 1108, +1658, 296, 1131, +1656, 296, 1161, +1651, 296, 1212, +1650, 296, 1257, +1655, 296, 1299, +1659, 276, 1353, +1649, 111, 1443, +1636, 111, 1584, +1648, 296, 1704, +1657, 296, 1838, +1646, 528, 1948, +1676, 683, 2089, +1585, 926, 2217, +1367, 1022, 2363, +1772, 0, 2470, +1863, 296, 2508, +1863, 296, 2508, +1863, 296, 2508, +1863, 296, 2508, +1863, 296, 2508, +1863, 296, 2508, +1863, 296, 2508, +1863, 296, 2508, +1863, 296, 2508, +1863, 296, 2508, +1658, 428, 1127, +1658, 428, 1131, +1657, 428, 1136, +1657, 428, 1143, +1656, 428, 1152, +1655, 428, 1164, +1654, 428, 1180, +1653, 428, 1200, +1651, 428, 1225, +1648, 428, 1257, +1648, 428, 1298, +1653, 428, 1336, +1657, 413, 1387, +1648, 265, 1468, +1636, 244, 1601, +1653, 428, 1715, +1661, 428, 1846, +1638, 660, 1955, +1671, 762, 2093, +1576, 963, 2219, +1408, 1032, 2365, +1768, 91, 2470, +1866, 428, 2508, +1866, 428, 2508, +1866, 428, 2508, +1866, 428, 2508, +1866, 428, 2508, +1866, 428, 2508, +1866, 428, 2508, +1866, 428, 2508, +1866, 428, 2508, +1866, 428, 2508, +1655, 583, 1188, +1655, 583, 1191, +1654, 583, 1196, +1654, 583, 1202, +1654, 583, 1210, +1653, 583, 1221, +1651, 583, 1234, +1650, 583, 1252, +1648, 583, 1275, +1646, 583, 1304, +1644, 536, 1348, +1649, 536, 1383, +1653, 524, 1429, +1645, 413, 1503, +1633, 376, 1622, +1654, 536, 1730, +1662, 536, 1854, +1635, 766, 1962, +1664, 863, 2099, +1566, 1025, 2222, +1432, 1062, 2367, +1764, 309, 2470, +1872, 536, 2508, +1872, 536, 2508, +1872, 536, 2508, +1872, 536, 2508, +1872, 536, 2508, +1872, 536, 2508, +1872, 536, 2508, +1872, 536, 2508, +1872, 536, 2508, +1872, 536, 2508, +1655, 745, 1237, +1655, 745, 1240, +1654, 745, 1244, +1654, 745, 1249, +1654, 745, 1257, +1653, 745, 1266, +1651, 745, 1279, +1650, 745, 1295, +1648, 745, 1315, +1646, 745, 1342, +1644, 713, 1383, +1644, 633, 1439, +1648, 624, 1479, +1640, 536, 1547, +1628, 508, 1646, +1649, 633, 1749, +1657, 633, 1863, +1635, 881, 1973, +1655, 979, 2105, +1554, 1109, 2228, +1415, 1110, 2370, +1760, 519, 2469, +1880, 633, 2508, +1880, 633, 2508, +1880, 633, 2508, +1880, 633, 2508, +1880, 633, 2508, +1880, 633, 2508, +1880, 633, 2508, +1880, 633, 2508, +1880, 633, 2508, +1880, 633, 2508, +1655, 918, 1304, +1656, 918, 1306, +1655, 918, 1310, +1655, 918, 1314, +1654, 918, 1320, +1654, 918, 1329, +1653, 918, 1340, +1651, 918, 1354, +1649, 918, 1372, +1647, 918, 1395, +1645, 897, 1432, +1645, 845, 1482, +1643, 779, 1541, +1635, 719, 1601, +1623, 701, 1686, +1641, 772, 1775, +1650, 779, 1877, +1631, 1007, 1989, +1643, 1092, 2115, +1533, 1205, 2236, +1384, 1170, 2375, +1758, 725, 2468, +1889, 758, 2508, +1889, 758, 2508, +1889, 758, 2508, +1889, 758, 2508, +1889, 758, 2508, +1889, 758, 2508, +1889, 758, 2508, +1889, 758, 2508, +1889, 758, 2508, +1889, 758, 2508, +1647, 1170, 1441, +1648, 1170, 1443, +1648, 1170, 1445, +1648, 1170, 1448, +1649, 1170, 1452, +1650, 1170, 1457, +1651, 1170, 1463, +1653, 1170, 1472, +1654, 1170, 1484, +1655, 1170, 1500, +1654, 1157, 1529, +1654, 1129, 1570, +1651, 1095, 1619, +1635, 1095, 1678, +1623, 1087, 1751, +1615, 1062, 1817, +1632, 1090, 1907, +1595, 1178, 2016, +1626, 1217, 2123, +1463, 1323, 2255, +1427, 1258, 2375, +1780, 1002, 2468, +1884, 986, 2506, +1884, 986, 2506, +1884, 986, 2506, +1884, 986, 2506, +1884, 986, 2506, +1884, 986, 2506, +1884, 986, 2506, +1884, 986, 2506, +1884, 986, 2506, +1884, 986, 2506, +1671, 1358, 1617, +1671, 1358, 1618, +1672, 1358, 1619, +1672, 1358, 1621, +1672, 1358, 1624, +1673, 1358, 1628, +1674, 1358, 1632, +1676, 1358, 1638, +1678, 1358, 1646, +1680, 1358, 1657, +1683, 1358, 1672, +1687, 1358, 1694, +1687, 1345, 1729, +1672, 1345, 1775, +1659, 1345, 1825, +1644, 1322, 1879, +1625, 1320, 1950, +1565, 1390, 2060, +1550, 1377, 2150, +1313, 1430, 2275, +1491, 1332, 2378, +1794, 1220, 2471, +1883, 1202, 2507, +1883, 1202, 2507, +1883, 1202, 2507, +1883, 1202, 2507, +1883, 1202, 2507, +1883, 1202, 2507, +1883, 1202, 2507, +1883, 1202, 2507, +1883, 1202, 2507, +1883, 1202, 2507, +1720, 1522, 1779, +1720, 1522, 1780, +1719, 1522, 1781, +1718, 1522, 1782, +1717, 1522, 1783, +1716, 1522, 1785, +1714, 1522, 1787, +1712, 1522, 1790, +1708, 1522, 1795, +1704, 1522, 1800, +1703, 1522, 1811, +1707, 1522, 1827, +1711, 1522, 1847, +1703, 1522, 1873, +1693, 1522, 1912, +1668, 1522, 1965, +1628, 1506, 2021, +1607, 1566, 2121, +1540, 1536, 2191, +1494, 1506, 2283, +1572, 1474, 2382, +1813, 1446, 2473, +1923, 1435, 2511, +1923, 1435, 2511, +1923, 1435, 2511, +1923, 1435, 2511, +1923, 1435, 2511, +1923, 1435, 2511, +1923, 1435, 2511, +1923, 1435, 2511, +1923, 1435, 2511, +1923, 1435, 2511, +1810, 1655, 1910, +1809, 1655, 1911, +1809, 1655, 1911, +1808, 1655, 1912, +1807, 1656, 1913, +1806, 1657, 1915, +1805, 1658, 1918, +1802, 1659, 1921, +1800, 1661, 1925, +1796, 1662, 1930, +1791, 1662, 1934, +1784, 1662, 1939, +1776, 1662, 1948, +1775, 1662, 1972, +1766, 1670, 2011, +1745, 1681, 2051, +1732, 1662, 2087, +1680, 1676, 2155, +1604, 1655, 2226, +1644, 1643, 2305, +1738, 1626, 2385, +1900, 1611, 2473, +1984, 1617, 2510, +1984, 1617, 2510, +1984, 1617, 2510, +1984, 1617, 2510, +1984, 1617, 2510, +1984, 1617, 2510, +1984, 1617, 2510, +1984, 1617, 2510, +1984, 1617, 2510, +1984, 1617, 2510, +1907, 1800, 1983, +1907, 1800, 1984, +1907, 1800, 1984, +1907, 1800, 1985, +1907, 1800, 1986, +1907, 1800, 1987, +1907, 1800, 1989, +1907, 1800, 1991, +1907, 1800, 1994, +1907, 1800, 1997, +1906, 1801, 2005, +1906, 1801, 2015, +1905, 1801, 2029, +1901, 1801, 2043, +1890, 1801, 2062, +1872, 1801, 2086, +1874, 1807, 2128, +1850, 1801, 2174, +1847, 1800, 2243, +1818, 1792, 2312, +1871, 1797, 2387, +1976, 1799, 2480, +2034, 1783, 2511, +2034, 1783, 2511, +2034, 1783, 2511, +2034, 1783, 2511, +2034, 1783, 2511, +2034, 1783, 2511, +2034, 1783, 2511, +2034, 1783, 2511, +2034, 1783, 2511, +2034, 1783, 2511, +2034, 1958, 2033, +2033, 1958, 2033, +2033, 1958, 2034, +2032, 1958, 2034, +2031, 1959, 2036, +2031, 1959, 2037, +2029, 1960, 2039, +2027, 1961, 2041, +2025, 1961, 2044, +2021, 1963, 2049, +2020, 1963, 2052, +2020, 1963, 2054, +2020, 1963, 2059, +2020, 1959, 2069, +2016, 1962, 2088, +2004, 1969, 2111, +1998, 1964, 2152, +1993, 1963, 2193, +1987, 1952, 2238, +1975, 1952, 2313, +2009, 1966, 2398, +2073, 1966, 2481, +2135, 1969, 2517, +2135, 1969, 2517, +2135, 1969, 2517, +2135, 1969, 2517, +2135, 1969, 2517, +2135, 1969, 2517, +2135, 1969, 2517, +2135, 1969, 2517, +2135, 1969, 2517, +2135, 1969, 2517, +2163, 2131, 2063, +2163, 2131, 2063, +2163, 2131, 2064, +2163, 2131, 2065, +2163, 2131, 2065, +2163, 2131, 2066, +2163, 2131, 2068, +2163, 2131, 2069, +2163, 2131, 2072, +2163, 2131, 2075, +2164, 2131, 2080, +2165, 2131, 2087, +2166, 2131, 2096, +2164, 2131, 2105, +2157, 2131, 2117, +2148, 2127, 2128, +2154, 2127, 2154, +2155, 2131, 2206, +2143, 2127, 2260, +2159, 2135, 2315, +2188, 2134, 2395, +2251, 2149, 2486, +2283, 2159, 2520, +2283, 2159, 2520, +2283, 2159, 2520, +2283, 2159, 2520, +2283, 2159, 2520, +2283, 2159, 2520, +2283, 2159, 2520, +2283, 2159, 2520, +2283, 2159, 2520, +2283, 2159, 2520, +2386, 2355, 2123, +2386, 2355, 2123, +2386, 2356, 2123, +2387, 2356, 2123, +2387, 2356, 2124, +2387, 2356, 2124, +2387, 2356, 2125, +2387, 2357, 2126, +2388, 2357, 2127, +2388, 2357, 2129, +2389, 2358, 2131, +2389, 2358, 2133, +2389, 2357, 2135, +2386, 2356, 2141, +2384, 2356, 2148, +2382, 2356, 2170, +2388, 2357, 2191, +2386, 2356, 2226, +2394, 2358, 2272, +2409, 2366, 2337, +2431, 2373, 2403, +2476, 2384, 2495, +2508, 2398, 2531, +2508, 2398, 2531, +2508, 2398, 2531, +2508, 2398, 2531, +2508, 2398, 2531, +2508, 2398, 2531, +2508, 2398, 2531, +2508, 2398, 2531, +2508, 2398, 2531, +2508, 2398, 2531, +2684, 2656, 1957, +2684, 2656, 1957, +2684, 2656, 1956, +2684, 2656, 1956, +2684, 2656, 1956, +2684, 2656, 1956, +2684, 2656, 1955, +2684, 2656, 1954, +2684, 2656, 1955, +2684, 2656, 1956, +2684, 2656, 1961, +2683, 2656, 1971, +2683, 2655, 1982, +2682, 2655, 1994, +2682, 2655, 1993, +2681, 2656, 2011, +2682, 2656, 2069, +2683, 2657, 2133, +2686, 2657, 2216, +2691, 2663, 2315, +2700, 2669, 2417, +2719, 2681, 2533, +2726, 2683, 2576, +2726, 2683, 2576, +2726, 2683, 2576, +2726, 2683, 2576, +2726, 2683, 2576, +2726, 2683, 2576, +2726, 2683, 2576, +2726, 2683, 2576, +2726, 2683, 2576, +2726, 2683, 2576, +2718, 2771, 2437, +2718, 2771, 2437, +2718, 2771, 2437, +2718, 2771, 2436, +2718, 2771, 2436, +2718, 2771, 2435, +2718, 2771, 2435, +2717, 2770, 2434, +2717, 2770, 2432, +2717, 2770, 2430, +2717, 2769, 2430, +2718, 2769, 2431, +2718, 2770, 2433, +2719, 2771, 2443, +2720, 2774, 2457, +2721, 2773, 2466, +2716, 2771, 2466, +2717, 2774, 2492, +2718, 2776, 2528, +2718, 2777, 2569, +2722, 2782, 2624, +2727, 2788, 2703, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2718, 2771, 2437, +2718, 2771, 2437, +2718, 2771, 2437, +2718, 2771, 2436, +2718, 2771, 2436, +2718, 2771, 2435, +2718, 2771, 2435, +2717, 2770, 2434, +2717, 2770, 2432, +2717, 2770, 2430, +2717, 2769, 2430, +2718, 2769, 2431, +2718, 2770, 2433, +2719, 2771, 2443, +2720, 2774, 2457, +2721, 2773, 2466, +2716, 2771, 2466, +2717, 2774, 2492, +2718, 2776, 2528, +2718, 2777, 2569, +2722, 2782, 2624, +2727, 2788, 2703, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2718, 2771, 2437, +2718, 2771, 2437, +2718, 2771, 2437, +2718, 2771, 2436, +2718, 2771, 2436, +2718, 2771, 2435, +2718, 2771, 2435, +2717, 2770, 2434, +2717, 2770, 2432, +2717, 2770, 2430, +2717, 2769, 2430, +2718, 2769, 2431, +2718, 2770, 2433, +2719, 2771, 2443, +2720, 2774, 2457, +2721, 2773, 2466, +2716, 2771, 2466, +2717, 2774, 2492, +2718, 2776, 2528, +2718, 2777, 2569, +2722, 2782, 2624, +2727, 2788, 2703, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2718, 2771, 2437, +2718, 2771, 2437, +2718, 2771, 2437, +2718, 2771, 2436, +2718, 2771, 2436, +2718, 2771, 2435, +2718, 2771, 2435, +2717, 2770, 2434, +2717, 2770, 2432, +2717, 2770, 2430, +2717, 2769, 2430, +2718, 2769, 2431, +2718, 2770, 2433, +2719, 2771, 2443, +2720, 2774, 2457, +2721, 2773, 2466, +2716, 2771, 2466, +2717, 2774, 2492, +2718, 2776, 2528, +2718, 2777, 2569, +2722, 2782, 2624, +2727, 2788, 2703, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2718, 2771, 2437, +2718, 2771, 2437, +2718, 2771, 2437, +2718, 2771, 2436, +2718, 2771, 2436, +2718, 2771, 2435, +2718, 2771, 2435, +2717, 2770, 2434, +2717, 2770, 2432, +2717, 2770, 2430, +2717, 2769, 2430, +2718, 2769, 2431, +2718, 2770, 2433, +2719, 2771, 2443, +2720, 2774, 2457, +2721, 2773, 2466, +2716, 2771, 2466, +2717, 2774, 2492, +2718, 2776, 2528, +2718, 2777, 2569, +2722, 2782, 2624, +2727, 2788, 2703, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2718, 2771, 2437, +2718, 2771, 2437, +2718, 2771, 2437, +2718, 2771, 2436, +2718, 2771, 2436, +2718, 2771, 2435, +2718, 2771, 2435, +2717, 2770, 2434, +2717, 2770, 2432, +2717, 2770, 2430, +2717, 2769, 2430, +2718, 2769, 2431, +2718, 2770, 2433, +2719, 2771, 2443, +2720, 2774, 2457, +2721, 2773, 2466, +2716, 2771, 2466, +2717, 2774, 2492, +2718, 2776, 2528, +2718, 2777, 2569, +2722, 2782, 2624, +2727, 2788, 2703, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2718, 2771, 2437, +2718, 2771, 2437, +2718, 2771, 2437, +2718, 2771, 2436, +2718, 2771, 2436, +2718, 2771, 2435, +2718, 2771, 2435, +2717, 2770, 2434, +2717, 2770, 2432, +2717, 2770, 2430, +2717, 2769, 2430, +2718, 2769, 2431, +2718, 2770, 2433, +2719, 2771, 2443, +2720, 2774, 2457, +2721, 2773, 2466, +2716, 2771, 2466, +2717, 2774, 2492, +2718, 2776, 2528, +2718, 2777, 2569, +2722, 2782, 2624, +2727, 2788, 2703, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2718, 2771, 2437, +2718, 2771, 2437, +2718, 2771, 2437, +2718, 2771, 2436, +2718, 2771, 2436, +2718, 2771, 2435, +2718, 2771, 2435, +2717, 2770, 2434, +2717, 2770, 2432, +2717, 2770, 2430, +2717, 2769, 2430, +2718, 2769, 2431, +2718, 2770, 2433, +2719, 2771, 2443, +2720, 2774, 2457, +2721, 2773, 2466, +2716, 2771, 2466, +2717, 2774, 2492, +2718, 2776, 2528, +2718, 2777, 2569, +2722, 2782, 2624, +2727, 2788, 2703, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2718, 2771, 2437, +2718, 2771, 2437, +2718, 2771, 2437, +2718, 2771, 2436, +2718, 2771, 2436, +2718, 2771, 2435, +2718, 2771, 2435, +2717, 2770, 2434, +2717, 2770, 2432, +2717, 2770, 2430, +2717, 2769, 2430, +2718, 2769, 2431, +2718, 2770, 2433, +2719, 2771, 2443, +2720, 2774, 2457, +2721, 2773, 2466, +2716, 2771, 2466, +2717, 2774, 2492, +2718, 2776, 2528, +2718, 2777, 2569, +2722, 2782, 2624, +2727, 2788, 2703, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2718, 2771, 2437, +2718, 2771, 2437, +2718, 2771, 2437, +2718, 2771, 2436, +2718, 2771, 2436, +2718, 2771, 2435, +2718, 2771, 2435, +2717, 2770, 2434, +2717, 2770, 2432, +2717, 2770, 2430, +2717, 2769, 2430, +2718, 2769, 2431, +2718, 2770, 2433, +2719, 2771, 2443, +2720, 2774, 2457, +2721, 2773, 2466, +2716, 2771, 2466, +2717, 2774, 2492, +2718, 2776, 2528, +2718, 2777, 2569, +2722, 2782, 2624, +2727, 2788, 2703, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +1824, 0, 1212, +1824, 0, 1217, +1825, 0, 1223, +1825, 0, 1231, +1826, 0, 1242, +1827, 0, 1255, +1829, 0, 1273, +1831, 0, 1296, +1833, 0, 1325, +1830, 0, 1360, +1825, 0, 1405, +1819, 0, 1458, +1810, 0, 1521, +1804, 0, 1576, +1787, 0, 1659, +1777, 0, 1755, +1770, 0, 1865, +1790, 0, 1986, +1740, 750, 2108, +1692, 916, 2230, +1561, 947, 2370, +1845, 0, 2469, +1920, 0, 2511, +1920, 0, 2511, +1920, 0, 2511, +1920, 0, 2511, +1920, 0, 2511, +1920, 0, 2511, +1920, 0, 2511, +1920, 0, 2511, +1920, 0, 2511, +1920, 0, 2511, +1824, 0, 1216, +1824, 0, 1219, +1825, 0, 1225, +1825, 0, 1233, +1826, 0, 1243, +1827, 0, 1257, +1829, 0, 1275, +1831, 0, 1298, +1833, 0, 1326, +1830, 0, 1362, +1825, 0, 1406, +1819, 0, 1459, +1810, 0, 1523, +1804, 0, 1578, +1787, 0, 1661, +1777, 0, 1756, +1770, 0, 1866, +1790, 32, 1986, +1740, 754, 2108, +1692, 922, 2231, +1561, 949, 2370, +1845, 0, 2470, +1920, 0, 2510, +1920, 0, 2510, +1920, 0, 2510, +1920, 0, 2510, +1920, 0, 2510, +1920, 0, 2510, +1920, 0, 2510, +1920, 0, 2510, +1920, 0, 2510, +1920, 0, 2510, +1825, 0, 1221, +1825, 0, 1224, +1825, 0, 1228, +1825, 0, 1235, +1826, 0, 1246, +1827, 0, 1260, +1829, 0, 1277, +1831, 0, 1300, +1833, 0, 1328, +1830, 0, 1364, +1825, 0, 1408, +1819, 0, 1461, +1810, 0, 1524, +1804, 0, 1580, +1787, 0, 1663, +1777, 0, 1758, +1770, 44, 1866, +1789, 88, 1987, +1740, 759, 2109, +1692, 931, 2231, +1562, 952, 2370, +1845, 0, 2470, +1920, 0, 2510, +1920, 0, 2510, +1920, 0, 2510, +1920, 0, 2510, +1920, 0, 2510, +1920, 0, 2510, +1920, 0, 2510, +1920, 0, 2510, +1920, 0, 2510, +1920, 0, 2510, +1825, 0, 1228, +1825, 0, 1231, +1825, 0, 1234, +1825, 0, 1239, +1826, 0, 1249, +1827, 0, 1263, +1829, 0, 1280, +1831, 0, 1302, +1833, 0, 1331, +1830, 0, 1366, +1825, 0, 1410, +1819, 0, 1463, +1810, 0, 1526, +1804, 0, 1584, +1787, 0, 1666, +1777, 0, 1760, +1769, 102, 1867, +1788, 153, 1988, +1739, 765, 2110, +1692, 942, 2232, +1563, 957, 2370, +1845, 0, 2470, +1920, 44, 2510, +1920, 44, 2510, +1920, 44, 2510, +1920, 44, 2510, +1920, 44, 2510, +1920, 44, 2510, +1920, 44, 2510, +1920, 44, 2510, +1920, 44, 2510, +1920, 44, 2510, +1826, 0, 1238, +1826, 0, 1240, +1826, 0, 1243, +1826, 0, 1248, +1826, 0, 1254, +1827, 0, 1267, +1829, 0, 1284, +1831, 0, 1306, +1833, 0, 1335, +1830, 0, 1370, +1825, 0, 1413, +1819, 0, 1465, +1810, 0, 1528, +1804, 0, 1588, +1787, 0, 1669, +1777, 83, 1763, +1769, 170, 1868, +1787, 229, 1990, +1739, 774, 2111, +1692, 956, 2233, +1563, 962, 2370, +1845, 0, 2470, +1921, 103, 2510, +1921, 103, 2510, +1921, 103, 2510, +1921, 103, 2510, +1921, 103, 2510, +1921, 103, 2510, +1921, 103, 2510, +1921, 103, 2510, +1921, 103, 2510, +1921, 103, 2510, +1827, 0, 1250, +1827, 0, 1252, +1827, 0, 1255, +1827, 0, 1260, +1827, 1, 1265, +1827, 30, 1273, +1829, 30, 1290, +1831, 30, 1312, +1833, 30, 1339, +1830, 30, 1375, +1825, 30, 1417, +1819, 30, 1469, +1810, 64, 1531, +1804, 132, 1593, +1787, 132, 1674, +1777, 215, 1767, +1768, 247, 1870, +1785, 313, 1991, +1738, 785, 2113, +1692, 974, 2235, +1564, 970, 2370, +1845, 0, 2470, +1921, 171, 2510, +1921, 171, 2510, +1921, 171, 2510, +1921, 171, 2510, +1921, 171, 2510, +1921, 171, 2510, +1921, 171, 2510, +1921, 171, 2510, +1921, 171, 2510, +1921, 171, 2510, +1829, 58, 1265, +1829, 66, 1267, +1829, 77, 1270, +1829, 91, 1275, +1829, 109, 1280, +1829, 133, 1288, +1829, 163, 1297, +1831, 163, 1318, +1833, 163, 1346, +1830, 163, 1380, +1825, 163, 1423, +1819, 163, 1474, +1810, 188, 1536, +1804, 264, 1601, +1787, 264, 1680, +1777, 347, 1772, +1767, 334, 1872, +1783, 406, 1994, +1737, 799, 2115, +1692, 998, 2237, +1565, 979, 2370, +1845, 32, 2471, +1922, 248, 2510, +1922, 248, 2510, +1922, 248, 2510, +1922, 248, 2510, +1922, 248, 2510, +1922, 248, 2510, +1922, 248, 2510, +1922, 248, 2510, +1922, 248, 2510, +1922, 248, 2510, +1831, 183, 1285, +1831, 190, 1287, +1831, 198, 1290, +1831, 209, 1294, +1831, 223, 1299, +1831, 242, 1306, +1831, 265, 1315, +1831, 295, 1328, +1833, 295, 1354, +1830, 295, 1388, +1825, 295, 1430, +1819, 295, 1480, +1810, 314, 1541, +1804, 396, 1611, +1787, 396, 1688, +1777, 479, 1778, +1766, 428, 1875, +1779, 506, 1998, +1736, 818, 2119, +1692, 1027, 2240, +1567, 992, 2369, +1845, 164, 2471, +1922, 335, 2510, +1922, 335, 2510, +1922, 335, 2510, +1922, 335, 2510, +1922, 335, 2510, +1922, 335, 2510, +1922, 335, 2510, +1922, 335, 2510, +1922, 335, 2510, +1922, 335, 2510, +1833, 310, 1310, +1833, 315, 1312, +1833, 322, 1315, +1833, 330, 1319, +1833, 341, 1324, +1833, 355, 1331, +1833, 373, 1339, +1833, 397, 1351, +1833, 426, 1365, +1830, 426, 1398, +1825, 426, 1439, +1819, 426, 1489, +1810, 441, 1548, +1804, 528, 1623, +1787, 528, 1699, +1777, 611, 1787, +1765, 530, 1878, +1775, 613, 2002, +1734, 841, 2123, +1692, 1064, 2244, +1569, 1008, 2369, +1844, 330, 2472, +1924, 429, 2510, +1924, 429, 2510, +1924, 429, 2510, +1924, 429, 2510, +1924, 429, 2510, +1924, 429, 2510, +1924, 429, 2510, +1924, 429, 2510, +1924, 429, 2510, +1924, 429, 2510, +1830, 439, 1356, +1830, 443, 1358, +1830, 447, 1361, +1830, 454, 1364, +1830, 462, 1369, +1830, 473, 1375, +1830, 487, 1383, +1830, 506, 1393, +1830, 529, 1407, +1828, 531, 1428, +1824, 531, 1466, +1817, 531, 1513, +1809, 543, 1570, +1803, 601, 1641, +1787, 591, 1713, +1780, 686, 1796, +1768, 615, 1886, +1769, 725, 2008, +1730, 897, 2126, +1685, 1092, 2246, +1595, 1019, 2371, +1840, 422, 2472, +1926, 531, 2509, +1926, 531, 2509, +1926, 531, 2509, +1926, 531, 2509, +1926, 531, 2509, +1926, 531, 2509, +1926, 531, 2509, +1926, 531, 2509, +1926, 531, 2509, +1926, 531, 2509, +1825, 568, 1412, +1825, 571, 1414, +1825, 575, 1417, +1825, 579, 1420, +1825, 586, 1424, +1825, 594, 1429, +1825, 605, 1436, +1825, 619, 1445, +1825, 638, 1457, +1824, 640, 1476, +1821, 640, 1501, +1814, 640, 1545, +1806, 648, 1598, +1800, 695, 1664, +1787, 658, 1731, +1782, 751, 1810, +1774, 707, 1896, +1763, 805, 2012, +1724, 965, 2131, +1675, 1127, 2249, +1629, 1033, 2373, +1836, 515, 2472, +1930, 640, 2509, +1930, 640, 2509, +1930, 640, 2509, +1930, 640, 2509, +1930, 640, 2509, +1930, 640, 2509, +1930, 640, 2509, +1930, 640, 2509, +1930, 640, 2509, +1930, 640, 2509, +1819, 699, 1479, +1819, 701, 1480, +1819, 703, 1482, +1819, 707, 1485, +1819, 712, 1488, +1819, 718, 1493, +1819, 727, 1499, +1819, 737, 1507, +1819, 752, 1518, +1817, 753, 1534, +1814, 753, 1556, +1811, 753, 1584, +1803, 760, 1633, +1797, 797, 1695, +1787, 733, 1754, +1782, 813, 1830, +1781, 806, 1910, +1756, 887, 2016, +1716, 1042, 2138, +1662, 1169, 2253, +1634, 1062, 2374, +1829, 616, 2472, +1935, 753, 2509, +1935, 753, 2509, +1935, 753, 2509, +1935, 753, 2509, +1935, 753, 2509, +1935, 753, 2509, +1935, 753, 2509, +1935, 753, 2509, +1935, 753, 2509, +1935, 753, 2509, +1811, 848, 1553, +1811, 848, 1554, +1811, 851, 1556, +1811, 853, 1558, +1811, 857, 1561, +1811, 861, 1565, +1811, 867, 1570, +1811, 875, 1577, +1811, 886, 1586, +1809, 887, 1600, +1807, 887, 1619, +1804, 887, 1644, +1799, 892, 1675, +1793, 920, 1732, +1785, 861, 1784, +1781, 901, 1853, +1789, 932, 1929, +1748, 990, 2023, +1706, 1137, 2147, +1648, 1218, 2257, +1620, 1108, 2375, +1824, 746, 2471, +1942, 876, 2509, +1942, 876, 2509, +1942, 876, 2509, +1942, 876, 2509, +1942, 876, 2509, +1942, 876, 2509, +1942, 876, 2509, +1942, 876, 2509, +1942, 876, 2509, +1942, 876, 2509, +1820, 1109, 1630, +1820, 1109, 1631, +1819, 1109, 1633, +1819, 1109, 1635, +1818, 1109, 1637, +1817, 1109, 1641, +1815, 1109, 1645, +1813, 1109, 1651, +1810, 1109, 1659, +1810, 1109, 1670, +1808, 1109, 1686, +1805, 1109, 1707, +1800, 1112, 1734, +1793, 1134, 1775, +1785, 1098, 1823, +1767, 1090, 1881, +1785, 1153, 1970, +1749, 1166, 2045, +1704, 1267, 2165, +1646, 1289, 2266, +1638, 1188, 2377, +1843, 976, 2471, +1948, 1035, 2509, +1948, 1035, 2509, +1948, 1035, 2509, +1948, 1035, 2509, +1948, 1035, 2509, +1948, 1035, 2509, +1948, 1035, 2509, +1948, 1035, 2509, +1948, 1035, 2509, +1948, 1035, 2509, +1812, 1336, 1724, +1812, 1336, 1725, +1811, 1336, 1727, +1811, 1336, 1728, +1810, 1336, 1730, +1809, 1336, 1733, +1807, 1336, 1736, +1805, 1336, 1741, +1802, 1336, 1748, +1804, 1336, 1756, +1806, 1336, 1767, +1810, 1336, 1781, +1808, 1338, 1803, +1801, 1351, 1839, +1785, 1351, 1887, +1762, 1338, 1936, +1760, 1342, 2007, +1728, 1366, 2073, +1683, 1382, 2175, +1573, 1418, 2288, +1713, 1264, 2379, +1872, 1202, 2471, +1942, 1211, 2508, +1942, 1211, 2508, +1942, 1211, 2508, +1942, 1211, 2508, +1942, 1211, 2508, +1942, 1211, 2508, +1942, 1211, 2508, +1942, 1211, 2508, +1942, 1211, 2508, +1942, 1211, 2508, +1832, 1511, 1838, +1832, 1511, 1839, +1832, 1511, 1839, +1832, 1511, 1840, +1832, 1511, 1841, +1832, 1511, 1843, +1832, 1511, 1845, +1832, 1511, 1848, +1832, 1511, 1852, +1829, 1511, 1857, +1829, 1511, 1865, +1832, 1511, 1876, +1834, 1511, 1891, +1824, 1511, 1912, +1810, 1511, 1951, +1783, 1522, 2002, +1774, 1495, 2052, +1746, 1515, 2117, +1708, 1501, 2192, +1652, 1522, 2297, +1779, 1436, 2383, +1898, 1422, 2472, +1969, 1408, 2508, +1969, 1408, 2508, +1969, 1408, 2508, +1969, 1408, 2508, +1969, 1408, 2508, +1969, 1408, 2508, +1969, 1408, 2508, +1969, 1408, 2508, +1969, 1408, 2508, +1969, 1408, 2508, +1888, 1654, 1938, +1888, 1654, 1938, +1888, 1654, 1939, +1888, 1654, 1940, +1888, 1654, 1940, +1888, 1654, 1942, +1888, 1654, 1943, +1888, 1654, 1946, +1888, 1654, 1949, +1885, 1654, 1953, +1881, 1654, 1958, +1875, 1654, 1965, +1868, 1655, 1975, +1863, 1662, 1991, +1855, 1662, 2017, +1843, 1654, 2055, +1817, 1654, 2107, +1794, 1657, 2159, +1766, 1662, 2229, +1800, 1621, 2303, +1843, 1605, 2385, +1921, 1624, 2474, +2007, 1630, 2511, +2007, 1630, 2511, +2007, 1630, 2511, +2007, 1630, 2511, +2007, 1630, 2511, +2007, 1630, 2511, +2007, 1630, 2511, +2007, 1630, 2511, +2007, 1630, 2511, +2007, 1630, 2511, +1977, 1783, 1983, +1977, 1783, 1984, +1977, 1783, 1984, +1977, 1783, 1985, +1977, 1783, 1986, +1978, 1783, 1987, +1978, 1783, 1989, +1979, 1783, 1991, +1980, 1783, 1994, +1980, 1783, 1997, +1977, 1785, 2004, +1973, 1788, 2012, +1966, 1792, 2023, +1959, 1786, 2037, +1958, 1786, 2064, +1950, 1793, 2093, +1929, 1801, 2129, +1939, 1792, 2174, +1905, 1778, 2235, +1877, 1792, 2311, +1920, 1800, 2389, +2007, 1802, 2476, +2064, 1798, 2511, +2064, 1798, 2511, +2064, 1798, 2511, +2064, 1798, 2511, +2064, 1798, 2511, +2064, 1798, 2511, +2064, 1798, 2511, +2064, 1798, 2511, +2064, 1798, 2511, +2064, 1798, 2511, +2083, 1958, 2032, +2082, 1958, 2032, +2082, 1958, 2032, +2082, 1958, 2033, +2082, 1958, 2034, +2082, 1958, 2035, +2081, 1958, 2036, +2081, 1958, 2038, +2080, 1958, 2041, +2077, 1959, 2045, +2073, 1961, 2051, +2067, 1963, 2058, +2061, 1965, 2068, +2056, 1964, 2080, +2056, 1959, 2093, +2052, 1959, 2114, +2036, 1961, 2142, +2031, 1968, 2199, +2019, 1953, 2244, +2017, 1958, 2317, +2046, 1962, 2395, +2106, 1970, 2483, +2149, 1969, 2517, +2149, 1969, 2517, +2149, 1969, 2517, +2149, 1969, 2517, +2149, 1969, 2517, +2149, 1969, 2517, +2149, 1969, 2517, +2149, 1969, 2517, +2149, 1969, 2517, +2149, 1969, 2517, +2191, 2132, 2068, +2191, 2132, 2068, +2191, 2132, 2069, +2190, 2132, 2069, +2190, 2132, 2070, +2190, 2131, 2071, +2189, 2131, 2072, +2188, 2130, 2074, +2187, 2130, 2076, +2187, 2129, 2079, +2187, 2129, 2083, +2187, 2129, 2088, +2187, 2129, 2096, +2184, 2129, 2105, +2180, 2129, 2117, +2180, 2128, 2131, +2170, 2124, 2154, +2176, 2127, 2200, +2167, 2133, 2262, +2179, 2135, 2315, +2208, 2135, 2395, +2271, 2155, 2484, +2291, 2159, 2521, +2291, 2159, 2521, +2291, 2159, 2521, +2291, 2159, 2521, +2291, 2159, 2521, +2291, 2159, 2521, +2291, 2159, 2521, +2291, 2159, 2521, +2291, 2159, 2521, +2291, 2159, 2521, +2407, 2360, 2121, +2407, 2360, 2121, +2407, 2360, 2121, +2407, 2360, 2121, +2407, 2360, 2121, +2407, 2359, 2122, +2407, 2359, 2122, +2407, 2359, 2123, +2407, 2358, 2123, +2408, 2359, 2125, +2408, 2360, 2128, +2409, 2360, 2131, +2409, 2360, 2135, +2408, 2362, 2141, +2405, 2359, 2147, +2402, 2358, 2164, +2395, 2358, 2193, +2399, 2361, 2228, +2408, 2365, 2275, +2419, 2368, 2338, +2446, 2373, 2402, +2486, 2387, 2498, +2516, 2398, 2529, +2516, 2398, 2529, +2516, 2398, 2529, +2516, 2398, 2529, +2516, 2398, 2529, +2516, 2398, 2529, +2516, 2398, 2529, +2516, 2398, 2529, +2516, 2398, 2529, +2516, 2398, 2529, +2687, 2656, 1984, +2687, 2656, 1984, +2687, 2656, 1984, +2687, 2656, 1984, +2687, 2656, 1984, +2687, 2656, 1984, +2687, 2656, 1984, +2687, 2656, 1984, +2688, 2656, 1989, +2688, 2656, 1991, +2688, 2656, 1992, +2689, 2656, 1995, +2690, 2656, 1999, +2690, 2657, 2008, +2688, 2657, 2023, +2688, 2657, 2054, +2688, 2658, 2083, +2688, 2659, 2149, +2689, 2659, 2227, +2696, 2667, 2323, +2703, 2668, 2417, +2722, 2681, 2534, +2728, 2686, 2580, +2728, 2686, 2580, +2728, 2686, 2580, +2728, 2686, 2580, +2728, 2686, 2580, +2728, 2686, 2580, +2728, 2686, 2580, +2728, 2686, 2580, +2728, 2686, 2580, +2728, 2686, 2580, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2772, 2447, +2721, 2772, 2444, +2721, 2771, 2441, +2720, 2770, 2438, +2721, 2771, 2443, +2722, 2773, 2457, +2723, 2774, 2473, +2723, 2774, 2481, +2717, 2775, 2500, +2720, 2779, 2531, +2720, 2778, 2569, +2726, 2782, 2625, +2731, 2788, 2703, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2772, 2447, +2721, 2772, 2444, +2721, 2771, 2441, +2720, 2770, 2438, +2721, 2771, 2443, +2722, 2773, 2457, +2723, 2774, 2473, +2723, 2774, 2481, +2717, 2775, 2500, +2720, 2779, 2531, +2720, 2778, 2569, +2726, 2782, 2625, +2731, 2788, 2703, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2772, 2447, +2721, 2772, 2444, +2721, 2771, 2441, +2720, 2770, 2438, +2721, 2771, 2443, +2722, 2773, 2457, +2723, 2774, 2473, +2723, 2774, 2481, +2717, 2775, 2500, +2720, 2779, 2531, +2720, 2778, 2569, +2726, 2782, 2625, +2731, 2788, 2703, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2772, 2447, +2721, 2772, 2444, +2721, 2771, 2441, +2720, 2770, 2438, +2721, 2771, 2443, +2722, 2773, 2457, +2723, 2774, 2473, +2723, 2774, 2481, +2717, 2775, 2500, +2720, 2779, 2531, +2720, 2778, 2569, +2726, 2782, 2625, +2731, 2788, 2703, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2772, 2447, +2721, 2772, 2444, +2721, 2771, 2441, +2720, 2770, 2438, +2721, 2771, 2443, +2722, 2773, 2457, +2723, 2774, 2473, +2723, 2774, 2481, +2717, 2775, 2500, +2720, 2779, 2531, +2720, 2778, 2569, +2726, 2782, 2625, +2731, 2788, 2703, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2772, 2447, +2721, 2772, 2444, +2721, 2771, 2441, +2720, 2770, 2438, +2721, 2771, 2443, +2722, 2773, 2457, +2723, 2774, 2473, +2723, 2774, 2481, +2717, 2775, 2500, +2720, 2779, 2531, +2720, 2778, 2569, +2726, 2782, 2625, +2731, 2788, 2703, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2772, 2447, +2721, 2772, 2444, +2721, 2771, 2441, +2720, 2770, 2438, +2721, 2771, 2443, +2722, 2773, 2457, +2723, 2774, 2473, +2723, 2774, 2481, +2717, 2775, 2500, +2720, 2779, 2531, +2720, 2778, 2569, +2726, 2782, 2625, +2731, 2788, 2703, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2772, 2447, +2721, 2772, 2444, +2721, 2771, 2441, +2720, 2770, 2438, +2721, 2771, 2443, +2722, 2773, 2457, +2723, 2774, 2473, +2723, 2774, 2481, +2717, 2775, 2500, +2720, 2779, 2531, +2720, 2778, 2569, +2726, 2782, 2625, +2731, 2788, 2703, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2772, 2447, +2721, 2772, 2444, +2721, 2771, 2441, +2720, 2770, 2438, +2721, 2771, 2443, +2722, 2773, 2457, +2723, 2774, 2473, +2723, 2774, 2481, +2717, 2775, 2500, +2720, 2779, 2531, +2720, 2778, 2569, +2726, 2782, 2625, +2731, 2788, 2703, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2772, 2447, +2721, 2772, 2444, +2721, 2771, 2441, +2720, 2770, 2438, +2721, 2771, 2443, +2722, 2773, 2457, +2723, 2774, 2473, +2723, 2774, 2481, +2717, 2775, 2500, +2720, 2779, 2531, +2720, 2778, 2569, +2726, 2782, 2625, +2731, 2788, 2703, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +1906, 311, 1618, +1906, 316, 1619, +1906, 322, 1620, +1906, 330, 1621, +1905, 342, 1623, +1905, 356, 1626, +1905, 374, 1630, +1904, 398, 1634, +1903, 427, 1640, +1901, 464, 1648, +1904, 471, 1670, +1909, 471, 1700, +1914, 464, 1736, +1910, 152, 1775, +1903, 63, 1817, +1900, 481, 1880, +1885, 481, 1958, +1866, 624, 2053, +1837, 927, 2156, +1786, 933, 2261, +1818, 679, 2380, +1933, 0, 2471, +1989, 487, 2513, +1989, 487, 2513, +1989, 487, 2513, +1989, 487, 2513, +1989, 487, 2513, +1989, 487, 2513, +1989, 487, 2513, +1989, 487, 2513, +1989, 487, 2513, +1989, 487, 2513, +1906, 330, 1619, +1907, 325, 1621, +1906, 332, 1622, +1906, 340, 1623, +1906, 351, 1625, +1905, 365, 1628, +1905, 383, 1631, +1904, 406, 1636, +1903, 435, 1642, +1901, 471, 1650, +1904, 478, 1672, +1910, 478, 1702, +1915, 478, 1736, +1910, 179, 1776, +1903, 95, 1817, +1900, 491, 1880, +1885, 491, 1958, +1866, 631, 2054, +1837, 928, 2156, +1786, 935, 2261, +1818, 681, 2380, +1933, 0, 2471, +1989, 491, 2513, +1989, 491, 2513, +1989, 491, 2513, +1989, 491, 2513, +1989, 491, 2513, +1989, 491, 2513, +1989, 491, 2513, +1989, 491, 2513, +1989, 491, 2513, +1989, 491, 2513, +1906, 354, 1621, +1907, 350, 1622, +1907, 344, 1624, +1907, 352, 1625, +1906, 362, 1627, +1906, 376, 1630, +1905, 393, 1633, +1904, 416, 1638, +1903, 444, 1644, +1902, 480, 1652, +1905, 486, 1674, +1910, 486, 1704, +1915, 486, 1738, +1910, 212, 1777, +1904, 135, 1818, +1900, 504, 1881, +1885, 504, 1959, +1866, 640, 2054, +1837, 930, 2156, +1787, 936, 2261, +1819, 684, 2380, +1933, 0, 2471, +1990, 495, 2513, +1990, 495, 2513, +1990, 495, 2513, +1990, 495, 2513, +1990, 495, 2513, +1990, 495, 2513, +1990, 495, 2513, +1990, 495, 2513, +1990, 495, 2513, +1990, 495, 2513, +1906, 384, 1623, +1907, 381, 1624, +1907, 375, 1626, +1907, 367, 1628, +1907, 377, 1630, +1906, 391, 1633, +1905, 408, 1636, +1905, 430, 1641, +1904, 457, 1647, +1902, 491, 1655, +1905, 498, 1676, +1911, 498, 1706, +1915, 498, 1740, +1910, 253, 1778, +1904, 183, 1819, +1900, 520, 1882, +1885, 520, 1960, +1866, 653, 2055, +1838, 932, 2156, +1787, 939, 2261, +1819, 688, 2381, +1933, 0, 2471, +1990, 501, 2513, +1990, 501, 2513, +1990, 501, 2513, +1990, 501, 2513, +1990, 501, 2513, +1990, 501, 2513, +1990, 501, 2513, +1990, 501, 2513, +1990, 501, 2513, +1990, 501, 2513, +1906, 422, 1625, +1907, 419, 1626, +1907, 413, 1628, +1907, 406, 1631, +1908, 397, 1634, +1907, 409, 1636, +1906, 426, 1640, +1905, 447, 1644, +1904, 473, 1650, +1903, 507, 1658, +1906, 513, 1680, +1911, 513, 1709, +1916, 513, 1743, +1911, 303, 1780, +1904, 241, 1821, +1899, 542, 1884, +1886, 542, 1962, +1866, 669, 2056, +1838, 935, 2156, +1788, 941, 2261, +1820, 693, 2381, +1933, 0, 2471, +1991, 508, 2513, +1991, 508, 2513, +1991, 508, 2513, +1991, 508, 2513, +1991, 508, 2513, +1991, 508, 2513, +1991, 508, 2513, +1991, 508, 2513, +1991, 508, 2513, +1991, 508, 2513, +1906, 468, 1629, +1907, 465, 1630, +1907, 460, 1632, +1907, 454, 1634, +1908, 445, 1637, +1908, 434, 1641, +1907, 449, 1645, +1906, 469, 1649, +1905, 495, 1655, +1904, 526, 1663, +1907, 533, 1684, +1912, 533, 1713, +1917, 533, 1747, +1911, 362, 1783, +1905, 308, 1823, +1899, 569, 1886, +1886, 569, 1964, +1866, 690, 2057, +1839, 939, 2157, +1789, 945, 2262, +1821, 700, 2381, +1933, 10, 2471, +1993, 518, 2513, +1993, 518, 2513, +1993, 518, 2513, +1993, 518, 2513, +1993, 518, 2513, +1993, 518, 2513, +1993, 518, 2513, +1993, 518, 2513, +1993, 518, 2513, +1993, 518, 2513, +1906, 523, 1633, +1907, 520, 1635, +1907, 516, 1636, +1907, 511, 1639, +1908, 503, 1642, +1908, 493, 1646, +1908, 479, 1651, +1908, 498, 1656, +1907, 521, 1662, +1905, 551, 1669, +1908, 557, 1690, +1913, 557, 1719, +1918, 557, 1753, +1912, 430, 1786, +1905, 384, 1826, +1898, 602, 1888, +1887, 602, 1966, +1866, 716, 2059, +1839, 944, 2157, +1791, 950, 2262, +1823, 708, 2381, +1933, 84, 2470, +1994, 531, 2513, +1994, 531, 2513, +1994, 531, 2513, +1994, 531, 2513, +1994, 531, 2513, +1994, 531, 2513, +1994, 531, 2513, +1994, 531, 2513, +1994, 531, 2513, +1994, 531, 2513, +1906, 588, 1640, +1907, 585, 1641, +1907, 582, 1643, +1907, 577, 1645, +1908, 570, 1648, +1908, 562, 1652, +1908, 550, 1657, +1909, 533, 1664, +1908, 555, 1670, +1907, 583, 1678, +1910, 588, 1698, +1915, 588, 1727, +1920, 588, 1759, +1913, 508, 1790, +1906, 470, 1830, +1897, 644, 1892, +1888, 644, 1970, +1866, 749, 2061, +1840, 951, 2157, +1793, 957, 2263, +1825, 720, 2382, +1933, 167, 2470, +1996, 548, 2512, +1996, 548, 2512, +1996, 548, 2512, +1996, 548, 2512, +1996, 548, 2512, +1996, 548, 2512, +1996, 548, 2512, +1996, 548, 2512, +1996, 548, 2512, +1996, 548, 2512, +1906, 662, 1647, +1907, 660, 1649, +1907, 657, 1650, +1907, 653, 1653, +1908, 647, 1655, +1908, 640, 1659, +1908, 629, 1665, +1909, 615, 1672, +1911, 596, 1681, +1909, 622, 1689, +1912, 627, 1708, +1917, 627, 1736, +1922, 627, 1769, +1913, 595, 1796, +1907, 563, 1835, +1896, 695, 1896, +1889, 695, 1975, +1866, 789, 2064, +1841, 960, 2158, +1796, 966, 2263, +1827, 735, 2383, +1933, 330, 2471, +1999, 569, 2512, +1999, 569, 2512, +1999, 569, 2512, +1999, 569, 2512, +1999, 569, 2512, +1999, 569, 2512, +1999, 569, 2512, +1999, 569, 2512, +1999, 569, 2512, +1999, 569, 2512, +1906, 745, 1658, +1907, 743, 1659, +1907, 741, 1661, +1907, 737, 1663, +1908, 733, 1666, +1908, 727, 1670, +1908, 718, 1675, +1909, 707, 1682, +1911, 691, 1691, +1912, 669, 1703, +1915, 674, 1722, +1920, 674, 1749, +1925, 674, 1780, +1915, 674, 1805, +1909, 665, 1842, +1894, 754, 1903, +1887, 754, 1980, +1866, 838, 2069, +1843, 972, 2159, +1800, 977, 2264, +1831, 754, 2384, +1933, 489, 2472, +2002, 596, 2512, +2002, 596, 2512, +2002, 596, 2512, +2002, 596, 2512, +2002, 596, 2512, +2002, 596, 2512, +2002, 596, 2512, +2002, 596, 2512, +2002, 596, 2512, +2002, 596, 2512, +1910, 819, 1677, +1910, 817, 1678, +1910, 815, 1680, +1911, 812, 1682, +1911, 809, 1685, +1911, 803, 1689, +1912, 796, 1693, +1913, 787, 1700, +1914, 773, 1708, +1915, 755, 1720, +1915, 772, 1732, +1921, 772, 1758, +1925, 772, 1789, +1916, 772, 1813, +1909, 792, 1855, +1894, 863, 1914, +1887, 875, 1990, +1865, 911, 2073, +1841, 1000, 2165, +1800, 1040, 2269, +1833, 798, 2384, +1931, 640, 2472, +2004, 683, 2511, +2004, 683, 2511, +2004, 683, 2511, +2004, 683, 2511, +2004, 683, 2511, +2004, 683, 2511, +2004, 683, 2511, +2004, 683, 2511, +2004, 683, 2511, +2004, 683, 2511, +1915, 898, 1703, +1915, 897, 1704, +1915, 895, 1705, +1915, 893, 1707, +1916, 890, 1710, +1916, 885, 1713, +1917, 879, 1718, +1918, 871, 1724, +1919, 860, 1732, +1920, 845, 1743, +1921, 860, 1755, +1921, 885, 1769, +1925, 885, 1799, +1916, 885, 1823, +1909, 925, 1873, +1894, 979, 1929, +1887, 1007, 2002, +1862, 997, 2078, +1838, 1037, 2174, +1800, 1121, 2277, +1843, 837, 2383, +1928, 785, 2473, +2007, 787, 2510, +2007, 787, 2510, +2007, 787, 2510, +2007, 787, 2510, +2007, 787, 2510, +2007, 787, 2510, +2007, 787, 2510, +2007, 787, 2510, +2007, 787, 2510, +2007, 787, 2510, +1922, 997, 1735, +1922, 998, 1736, +1922, 997, 1737, +1922, 995, 1739, +1923, 993, 1741, +1923, 989, 1745, +1924, 984, 1749, +1925, 978, 1755, +1926, 969, 1763, +1927, 958, 1772, +1927, 969, 1783, +1927, 989, 1797, +1926, 1011, 1816, +1917, 1011, 1839, +1910, 1049, 1891, +1895, 1094, 1949, +1888, 1137, 2019, +1859, 1095, 2086, +1833, 1102, 2184, +1802, 1203, 2287, +1856, 905, 2383, +1926, 942, 2474, +2010, 902, 2509, +2010, 902, 2509, +2010, 902, 2509, +2010, 902, 2509, +2010, 902, 2509, +2010, 902, 2509, +2010, 902, 2509, +2010, 902, 2509, +2010, 902, 2509, +2010, 902, 2509, +1931, 1121, 1774, +1931, 1122, 1775, +1931, 1123, 1776, +1932, 1124, 1778, +1932, 1126, 1780, +1932, 1129, 1783, +1933, 1132, 1787, +1934, 1137, 1793, +1935, 1143, 1800, +1936, 1145, 1809, +1936, 1152, 1819, +1936, 1166, 1832, +1935, 1181, 1849, +1921, 1181, 1881, +1914, 1207, 1928, +1905, 1197, 1974, +1898, 1248, 2038, +1870, 1219, 2099, +1827, 1224, 2189, +1814, 1266, 2289, +1856, 1137, 2381, +1933, 1139, 2475, +2017, 1048, 2509, +2017, 1048, 2509, +2017, 1048, 2509, +2017, 1048, 2509, +2017, 1048, 2509, +2017, 1048, 2509, +2017, 1048, 2509, +2017, 1048, 2509, +2017, 1048, 2509, +2017, 1048, 2509, +1943, 1312, 1836, +1943, 1312, 1837, +1943, 1313, 1838, +1943, 1314, 1839, +1944, 1315, 1841, +1944, 1317, 1844, +1945, 1319, 1847, +1945, 1322, 1852, +1946, 1326, 1858, +1948, 1331, 1866, +1945, 1332, 1875, +1940, 1332, 1886, +1936, 1339, 1902, +1923, 1339, 1930, +1915, 1358, 1965, +1906, 1343, 2006, +1889, 1364, 2062, +1872, 1381, 2136, +1826, 1367, 2210, +1822, 1339, 2296, +1868, 1258, 2382, +1955, 1262, 2478, +2027, 1191, 2509, +2027, 1191, 2509, +2027, 1191, 2509, +2027, 1191, 2509, +2027, 1191, 2509, +2027, 1191, 2509, +2027, 1191, 2509, +2027, 1191, 2509, +2027, 1191, 2509, +2027, 1191, 2509, +1969, 1458, 1884, +1969, 1458, 1884, +1968, 1458, 1885, +1968, 1458, 1887, +1968, 1458, 1888, +1968, 1458, 1890, +1967, 1458, 1892, +1966, 1458, 1896, +1965, 1458, 1900, +1964, 1458, 1906, +1962, 1458, 1913, +1957, 1458, 1924, +1950, 1459, 1938, +1941, 1472, 1960, +1934, 1487, 1991, +1937, 1461, 2031, +1908, 1472, 2078, +1899, 1508, 2159, +1871, 1507, 2226, +1869, 1459, 2304, +1906, 1424, 2382, +1989, 1433, 2480, +2031, 1414, 2509, +2031, 1414, 2509, +2031, 1414, 2509, +2031, 1414, 2509, +2031, 1414, 2509, +2031, 1414, 2509, +2031, 1414, 2509, +2031, 1414, 2509, +2031, 1414, 2509, +2031, 1414, 2509, +1995, 1625, 1959, +1995, 1625, 1960, +1995, 1625, 1961, +1995, 1626, 1962, +1995, 1626, 1963, +1994, 1627, 1965, +1994, 1628, 1968, +1993, 1630, 1972, +1992, 1632, 1976, +1991, 1632, 1982, +1990, 1632, 1987, +1990, 1632, 1993, +1990, 1632, 2002, +1989, 1633, 2018, +1978, 1635, 2038, +1968, 1630, 2070, +1945, 1650, 2122, +1941, 1635, 2175, +1926, 1623, 2233, +1921, 1624, 2309, +1947, 1613, 2388, +2014, 1610, 2474, +2061, 1608, 2512, +2061, 1608, 2512, +2061, 1608, 2512, +2061, 1608, 2512, +2061, 1608, 2512, +2061, 1608, 2512, +2061, 1608, 2512, +2061, 1608, 2512, +2061, 1608, 2512, +2061, 1608, 2512, +2048, 1766, 1996, +2048, 1766, 1996, +2048, 1766, 1996, +2048, 1766, 1997, +2048, 1766, 1998, +2048, 1766, 1999, +2048, 1766, 2000, +2048, 1766, 2002, +2048, 1766, 2006, +2048, 1766, 2009, +2048, 1766, 2014, +2048, 1766, 2020, +2048, 1767, 2029, +2044, 1773, 2043, +2040, 1782, 2061, +2029, 1792, 2098, +2027, 1783, 2138, +1997, 1783, 2185, +1996, 1799, 2243, +1996, 1791, 2315, +2012, 1789, 2391, +2075, 1804, 2478, +2111, 1808, 2513, +2111, 1808, 2513, +2111, 1808, 2513, +2111, 1808, 2513, +2111, 1808, 2513, +2111, 1808, 2513, +2111, 1808, 2513, +2111, 1808, 2513, +2111, 1808, 2513, +2111, 1808, 2513, +2118, 1947, 2038, +2118, 1947, 2038, +2118, 1947, 2039, +2118, 1947, 2039, +2118, 1948, 2040, +2119, 1948, 2041, +2119, 1948, 2042, +2120, 1949, 2044, +2120, 1950, 2047, +2121, 1951, 2050, +2120, 1952, 2054, +2119, 1952, 2060, +2117, 1952, 2068, +2111, 1952, 2078, +2102, 1952, 2094, +2100, 1957, 2116, +2094, 1953, 2146, +2078, 1951, 2186, +2073, 1951, 2247, +2076, 1958, 2318, +2097, 1963, 2398, +2161, 1972, 2478, +2191, 1974, 2517, +2191, 1974, 2517, +2191, 1974, 2517, +2191, 1974, 2517, +2191, 1974, 2517, +2191, 1974, 2517, +2191, 1974, 2517, +2191, 1974, 2517, +2191, 1974, 2517, +2191, 1974, 2517, +2223, 2127, 2077, +2223, 2127, 2077, +2223, 2127, 2077, +2223, 2128, 2078, +2223, 2128, 2078, +2223, 2128, 2078, +2223, 2128, 2079, +2223, 2129, 2080, +2223, 2130, 2082, +2223, 2131, 2084, +2221, 2130, 2088, +2219, 2128, 2093, +2216, 2127, 2099, +2213, 2127, 2109, +2210, 2127, 2121, +2206, 2127, 2136, +2216, 2126, 2162, +2212, 2127, 2204, +2215, 2139, 2260, +2222, 2139, 2318, +2237, 2143, 2401, +2282, 2159, 2486, +2316, 2166, 2524, +2316, 2166, 2524, +2316, 2166, 2524, +2316, 2166, 2524, +2316, 2166, 2524, +2316, 2166, 2524, +2316, 2166, 2524, +2316, 2166, 2524, +2316, 2166, 2524, +2316, 2166, 2524, +2426, 2364, 2124, +2426, 2364, 2124, +2426, 2364, 2124, +2426, 2364, 2125, +2426, 2364, 2125, +2426, 2364, 2126, +2426, 2364, 2126, +2426, 2364, 2127, +2426, 2364, 2129, +2426, 2364, 2131, +2426, 2364, 2132, +2426, 2363, 2135, +2427, 2362, 2138, +2429, 2364, 2138, +2428, 2365, 2146, +2427, 2363, 2161, +2428, 2366, 2187, +2427, 2369, 2230, +2430, 2369, 2278, +2430, 2368, 2333, +2463, 2376, 2405, +2502, 2392, 2495, +2540, 2403, 2525, +2540, 2403, 2525, +2540, 2403, 2525, +2540, 2403, 2525, +2540, 2403, 2525, +2540, 2403, 2525, +2540, 2403, 2525, +2540, 2403, 2525, +2540, 2403, 2525, +2540, 2403, 2525, +2694, 2658, 1982, +2694, 2658, 1982, +2694, 2658, 1982, +2694, 2658, 1981, +2694, 2658, 1981, +2694, 2658, 1979, +2693, 2657, 1979, +2693, 2657, 1977, +2693, 2657, 1978, +2693, 2657, 1979, +2693, 2658, 1988, +2694, 2659, 2001, +2694, 2660, 2015, +2696, 2660, 2021, +2695, 2657, 2016, +2695, 2660, 2055, +2697, 2662, 2117, +2697, 2663, 2170, +2697, 2666, 2245, +2701, 2667, 2320, +2711, 2672, 2426, +2725, 2685, 2539, +2731, 2689, 2588, +2731, 2689, 2588, +2731, 2689, 2588, +2731, 2689, 2588, +2731, 2689, 2588, +2731, 2689, 2588, +2731, 2689, 2588, +2731, 2689, 2588, +2731, 2689, 2588, +2731, 2689, 2588, +2727, 2773, 2456, +2727, 2773, 2456, +2727, 2773, 2456, +2727, 2774, 2457, +2727, 2774, 2457, +2727, 2774, 2457, +2727, 2774, 2458, +2728, 2774, 2459, +2728, 2775, 2460, +2728, 2775, 2461, +2728, 2775, 2461, +2728, 2775, 2461, +2728, 2775, 2461, +2729, 2773, 2461, +2729, 2774, 2466, +2728, 2776, 2478, +2729, 2777, 2494, +2725, 2779, 2509, +2723, 2779, 2533, +2725, 2779, 2571, +2728, 2783, 2631, +2735, 2789, 2705, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2727, 2773, 2456, +2727, 2773, 2456, +2727, 2773, 2456, +2727, 2774, 2457, +2727, 2774, 2457, +2727, 2774, 2457, +2727, 2774, 2458, +2728, 2774, 2459, +2728, 2775, 2460, +2728, 2775, 2461, +2728, 2775, 2461, +2728, 2775, 2461, +2728, 2775, 2461, +2729, 2773, 2461, +2729, 2774, 2466, +2728, 2776, 2478, +2729, 2777, 2494, +2725, 2779, 2509, +2723, 2779, 2533, +2725, 2779, 2571, +2728, 2783, 2631, +2735, 2789, 2705, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2727, 2773, 2456, +2727, 2773, 2456, +2727, 2773, 2456, +2727, 2774, 2457, +2727, 2774, 2457, +2727, 2774, 2457, +2727, 2774, 2458, +2728, 2774, 2459, +2728, 2775, 2460, +2728, 2775, 2461, +2728, 2775, 2461, +2728, 2775, 2461, +2728, 2775, 2461, +2729, 2773, 2461, +2729, 2774, 2466, +2728, 2776, 2478, +2729, 2777, 2494, +2725, 2779, 2509, +2723, 2779, 2533, +2725, 2779, 2571, +2728, 2783, 2631, +2735, 2789, 2705, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2727, 2773, 2456, +2727, 2773, 2456, +2727, 2773, 2456, +2727, 2774, 2457, +2727, 2774, 2457, +2727, 2774, 2457, +2727, 2774, 2458, +2728, 2774, 2459, +2728, 2775, 2460, +2728, 2775, 2461, +2728, 2775, 2461, +2728, 2775, 2461, +2728, 2775, 2461, +2729, 2773, 2461, +2729, 2774, 2466, +2728, 2776, 2478, +2729, 2777, 2494, +2725, 2779, 2509, +2723, 2779, 2533, +2725, 2779, 2571, +2728, 2783, 2631, +2735, 2789, 2705, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2727, 2773, 2456, +2727, 2773, 2456, +2727, 2773, 2456, +2727, 2774, 2457, +2727, 2774, 2457, +2727, 2774, 2457, +2727, 2774, 2458, +2728, 2774, 2459, +2728, 2775, 2460, +2728, 2775, 2461, +2728, 2775, 2461, +2728, 2775, 2461, +2728, 2775, 2461, +2729, 2773, 2461, +2729, 2774, 2466, +2728, 2776, 2478, +2729, 2777, 2494, +2725, 2779, 2509, +2723, 2779, 2533, +2725, 2779, 2571, +2728, 2783, 2631, +2735, 2789, 2705, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2727, 2773, 2456, +2727, 2773, 2456, +2727, 2773, 2456, +2727, 2774, 2457, +2727, 2774, 2457, +2727, 2774, 2457, +2727, 2774, 2458, +2728, 2774, 2459, +2728, 2775, 2460, +2728, 2775, 2461, +2728, 2775, 2461, +2728, 2775, 2461, +2728, 2775, 2461, +2729, 2773, 2461, +2729, 2774, 2466, +2728, 2776, 2478, +2729, 2777, 2494, +2725, 2779, 2509, +2723, 2779, 2533, +2725, 2779, 2571, +2728, 2783, 2631, +2735, 2789, 2705, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2727, 2773, 2456, +2727, 2773, 2456, +2727, 2773, 2456, +2727, 2774, 2457, +2727, 2774, 2457, +2727, 2774, 2457, +2727, 2774, 2458, +2728, 2774, 2459, +2728, 2775, 2460, +2728, 2775, 2461, +2728, 2775, 2461, +2728, 2775, 2461, +2728, 2775, 2461, +2729, 2773, 2461, +2729, 2774, 2466, +2728, 2776, 2478, +2729, 2777, 2494, +2725, 2779, 2509, +2723, 2779, 2533, +2725, 2779, 2571, +2728, 2783, 2631, +2735, 2789, 2705, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2727, 2773, 2456, +2727, 2773, 2456, +2727, 2773, 2456, +2727, 2774, 2457, +2727, 2774, 2457, +2727, 2774, 2457, +2727, 2774, 2458, +2728, 2774, 2459, +2728, 2775, 2460, +2728, 2775, 2461, +2728, 2775, 2461, +2728, 2775, 2461, +2728, 2775, 2461, +2729, 2773, 2461, +2729, 2774, 2466, +2728, 2776, 2478, +2729, 2777, 2494, +2725, 2779, 2509, +2723, 2779, 2533, +2725, 2779, 2571, +2728, 2783, 2631, +2735, 2789, 2705, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2727, 2773, 2456, +2727, 2773, 2456, +2727, 2773, 2456, +2727, 2774, 2457, +2727, 2774, 2457, +2727, 2774, 2457, +2727, 2774, 2458, +2728, 2774, 2459, +2728, 2775, 2460, +2728, 2775, 2461, +2728, 2775, 2461, +2728, 2775, 2461, +2728, 2775, 2461, +2729, 2773, 2461, +2729, 2774, 2466, +2728, 2776, 2478, +2729, 2777, 2494, +2725, 2779, 2509, +2723, 2779, 2533, +2725, 2779, 2571, +2728, 2783, 2631, +2735, 2789, 2705, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2727, 2773, 2456, +2727, 2773, 2456, +2727, 2773, 2456, +2727, 2774, 2457, +2727, 2774, 2457, +2727, 2774, 2457, +2727, 2774, 2458, +2728, 2774, 2459, +2728, 2775, 2460, +2728, 2775, 2461, +2728, 2775, 2461, +2728, 2775, 2461, +2728, 2775, 2461, +2729, 2773, 2461, +2729, 2774, 2466, +2728, 2776, 2478, +2729, 2777, 2494, +2725, 2779, 2509, +2723, 2779, 2533, +2725, 2779, 2571, +2728, 2783, 2631, +2735, 2789, 2705, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2036, 810, 1881, +2036, 808, 1882, +2036, 806, 1882, +2036, 803, 1883, +2037, 799, 1884, +2037, 794, 1886, +2037, 787, 1887, +2038, 777, 1890, +2039, 763, 1894, +2040, 745, 1898, +2042, 718, 1904, +2043, 681, 1912, +2044, 657, 1923, +2037, 657, 1946, +2028, 657, 1974, +2025, 726, 2020, +2019, 820, 2081, +1994, 874, 2146, +1993, 810, 2228, +2002, 0, 2298, +2010, 0, 2382, +2069, 0, 2474, +2108, 0, 2510, +2108, 0, 2510, +2108, 0, 2510, +2108, 0, 2510, +2108, 0, 2510, +2108, 0, 2510, +2108, 0, 2510, +2108, 0, 2510, +2108, 0, 2510, +2108, 0, 2510, +2036, 813, 1881, +2036, 813, 1882, +2036, 811, 1883, +2036, 808, 1884, +2037, 804, 1884, +2037, 799, 1886, +2037, 791, 1888, +2038, 782, 1891, +2039, 769, 1894, +2040, 750, 1898, +2042, 724, 1905, +2043, 687, 1912, +2044, 666, 1924, +2037, 666, 1946, +2028, 666, 1974, +2024, 730, 2021, +2019, 824, 2081, +1994, 876, 2146, +1994, 812, 2228, +2002, 0, 2298, +2010, 0, 2382, +2069, 0, 2474, +2108, 0, 2510, +2108, 0, 2510, +2108, 0, 2510, +2108, 0, 2510, +2108, 0, 2510, +2108, 0, 2510, +2108, 0, 2510, +2108, 0, 2510, +2108, 0, 2510, +2108, 0, 2510, +2037, 817, 1881, +2036, 817, 1882, +2036, 817, 1883, +2036, 814, 1884, +2037, 810, 1885, +2037, 805, 1887, +2037, 798, 1888, +2038, 789, 1891, +2039, 776, 1894, +2040, 757, 1899, +2042, 732, 1905, +2043, 695, 1913, +2044, 675, 1924, +2037, 678, 1946, +2028, 678, 1974, +2024, 735, 2021, +2019, 831, 2081, +1994, 877, 2146, +1994, 814, 2228, +2002, 0, 2298, +2010, 0, 2382, +2069, 0, 2474, +2108, 0, 2510, +2108, 0, 2510, +2108, 0, 2510, +2108, 0, 2510, +2108, 0, 2510, +2108, 0, 2510, +2108, 0, 2510, +2108, 0, 2510, +2108, 0, 2510, +2108, 0, 2510, +2037, 823, 1882, +2037, 823, 1883, +2037, 823, 1884, +2036, 823, 1885, +2037, 819, 1886, +2037, 814, 1887, +2037, 807, 1889, +2038, 797, 1892, +2039, 785, 1895, +2040, 767, 1900, +2042, 742, 1906, +2043, 706, 1914, +2044, 686, 1925, +2038, 693, 1947, +2028, 693, 1975, +2024, 742, 2022, +2020, 839, 2082, +1995, 880, 2146, +1995, 817, 2228, +2003, 0, 2298, +2010, 0, 2382, +2069, 0, 2474, +2107, 0, 2510, +2107, 0, 2510, +2107, 0, 2510, +2107, 0, 2510, +2107, 0, 2510, +2107, 0, 2510, +2107, 0, 2510, +2107, 0, 2510, +2107, 0, 2510, +2107, 0, 2510, +2037, 830, 1882, +2037, 830, 1883, +2037, 830, 1884, +2037, 830, 1885, +2037, 830, 1887, +2037, 825, 1888, +2037, 818, 1891, +2038, 809, 1893, +2039, 797, 1897, +2040, 779, 1901, +2042, 755, 1907, +2043, 721, 1915, +2044, 701, 1926, +2038, 713, 1948, +2029, 713, 1976, +2024, 751, 2023, +2020, 850, 2082, +1995, 883, 2147, +1996, 821, 2228, +2004, 0, 2298, +2011, 0, 2383, +2069, 0, 2474, +2107, 61, 2510, +2107, 61, 2510, +2107, 61, 2510, +2107, 61, 2510, +2107, 61, 2510, +2107, 61, 2510, +2107, 61, 2510, +2107, 61, 2510, +2107, 61, 2510, +2107, 61, 2510, +2038, 840, 1883, +2038, 840, 1884, +2038, 840, 1884, +2037, 840, 1886, +2037, 840, 1887, +2037, 840, 1890, +2037, 833, 1892, +2038, 825, 1894, +2039, 813, 1898, +2040, 796, 1902, +2042, 772, 1908, +2043, 739, 1916, +2044, 721, 1927, +2038, 737, 1950, +2029, 737, 1977, +2023, 762, 2025, +2021, 864, 2083, +1996, 888, 2147, +1997, 826, 2228, +2005, 48, 2298, +2011, 0, 2383, +2069, 10, 2474, +2105, 179, 2510, +2105, 179, 2510, +2105, 179, 2510, +2105, 179, 2510, +2105, 179, 2510, +2105, 179, 2510, +2105, 179, 2510, +2105, 179, 2510, +2105, 179, 2510, +2105, 179, 2510, +2039, 853, 1883, +2039, 853, 1884, +2039, 853, 1885, +2038, 853, 1887, +2038, 853, 1888, +2038, 853, 1891, +2037, 853, 1894, +2038, 844, 1896, +2039, 833, 1900, +2040, 817, 1904, +2042, 794, 1910, +2043, 763, 1918, +2044, 745, 1929, +2039, 769, 1951, +2029, 769, 1979, +2023, 777, 2027, +2022, 882, 2084, +1997, 894, 2148, +1998, 832, 2227, +2006, 147, 2298, +2011, 89, 2384, +2069, 84, 2473, +2104, 299, 2510, +2104, 299, 2510, +2104, 299, 2510, +2104, 299, 2510, +2104, 299, 2510, +2104, 299, 2510, +2104, 299, 2510, +2104, 299, 2510, +2104, 299, 2510, +2104, 299, 2510, +2040, 869, 1884, +2040, 869, 1885, +2040, 869, 1886, +2040, 869, 1887, +2039, 869, 1889, +2039, 869, 1891, +2039, 869, 1894, +2038, 869, 1899, +2039, 858, 1902, +2040, 843, 1907, +2042, 822, 1913, +2043, 792, 1920, +2044, 776, 1932, +2039, 807, 1954, +2030, 807, 1981, +2022, 797, 2029, +2023, 905, 2085, +1998, 901, 2149, +2000, 841, 2227, +2007, 253, 2298, +2012, 208, 2384, +2069, 167, 2473, +2103, 423, 2510, +2103, 423, 2510, +2103, 423, 2510, +2103, 423, 2510, +2103, 423, 2510, +2103, 423, 2510, +2103, 423, 2510, +2103, 423, 2510, +2103, 423, 2510, +2103, 423, 2510, +2042, 890, 1885, +2042, 890, 1886, +2042, 890, 1887, +2041, 890, 1888, +2041, 890, 1890, +2041, 890, 1893, +2040, 890, 1896, +2040, 890, 1900, +2039, 890, 1905, +2040, 876, 1910, +2042, 857, 1916, +2043, 829, 1924, +2044, 814, 1935, +2040, 854, 1957, +2031, 854, 1984, +2021, 822, 2032, +2025, 934, 2086, +2000, 911, 2150, +2003, 852, 2226, +2009, 364, 2298, +2013, 329, 2385, +2069, 258, 2473, +2101, 548, 2511, +2101, 548, 2511, +2101, 548, 2511, +2101, 548, 2511, +2101, 548, 2511, +2101, 548, 2511, +2101, 548, 2511, +2101, 548, 2511, +2101, 548, 2511, +2101, 548, 2511, +2044, 917, 1887, +2044, 917, 1887, +2044, 917, 1889, +2043, 917, 1890, +2043, 917, 1892, +2043, 917, 1894, +2042, 917, 1897, +2042, 917, 1901, +2041, 917, 1907, +2040, 917, 1914, +2042, 899, 1920, +2043, 874, 1928, +2044, 861, 1939, +2041, 906, 1961, +2032, 910, 1988, +2020, 853, 2037, +2024, 959, 2090, +2002, 924, 2152, +2007, 867, 2226, +2011, 480, 2298, +2014, 453, 2386, +2069, 358, 2472, +2098, 675, 2511, +2098, 675, 2511, +2098, 675, 2511, +2098, 675, 2511, +2098, 675, 2511, +2098, 675, 2511, +2098, 675, 2511, +2098, 675, 2511, +2098, 675, 2511, +2098, 675, 2511, +2047, 951, 1889, +2047, 951, 1890, +2047, 951, 1891, +2047, 951, 1892, +2046, 951, 1894, +2046, 951, 1896, +2045, 951, 1899, +2045, 951, 1903, +2044, 951, 1909, +2043, 951, 1916, +2042, 951, 1926, +2043, 928, 1933, +2044, 916, 1944, +2041, 956, 1966, +2033, 976, 1993, +2021, 913, 2042, +2022, 990, 2095, +2006, 968, 2154, +2012, 886, 2225, +2014, 599, 2298, +2016, 579, 2387, +2069, 463, 2472, +2094, 803, 2512, +2094, 803, 2512, +2094, 803, 2512, +2094, 803, 2512, +2094, 803, 2512, +2094, 803, 2512, +2094, 803, 2512, +2094, 803, 2512, +2094, 803, 2512, +2094, 803, 2512, +2051, 992, 1892, +2051, 992, 1892, +2051, 992, 1894, +2050, 992, 1895, +2050, 992, 1897, +2050, 992, 1899, +2049, 992, 1902, +2049, 992, 1906, +2048, 992, 1912, +2047, 992, 1919, +2045, 992, 1928, +2043, 992, 1941, +2044, 981, 1951, +2041, 1016, 1973, +2035, 1052, 1999, +2023, 999, 2048, +2020, 1028, 2102, +2010, 1027, 2157, +2018, 910, 2223, +2019, 722, 2298, +2019, 682, 2389, +2069, 575, 2471, +2089, 933, 2513, +2089, 933, 2513, +2089, 933, 2513, +2089, 933, 2513, +2089, 933, 2513, +2089, 933, 2513, +2089, 933, 2513, +2089, 933, 2513, +2089, 933, 2513, +2089, 933, 2513, +2055, 1051, 1898, +2055, 1052, 1899, +2055, 1052, 1900, +2055, 1052, 1902, +2054, 1052, 1903, +2054, 1052, 1905, +2054, 1052, 1909, +2053, 1052, 1913, +2052, 1052, 1918, +2051, 1052, 1925, +2050, 1052, 1935, +2048, 1052, 1947, +2047, 1053, 1963, +2043, 1083, 1983, +2038, 1120, 2010, +2027, 1089, 2055, +2019, 1074, 2110, +2016, 1091, 2162, +2024, 958, 2224, +2023, 859, 2299, +2024, 795, 2391, +2069, 729, 2471, +2085, 1046, 2513, +2085, 1046, 2513, +2085, 1046, 2513, +2085, 1046, 2513, +2085, 1046, 2513, +2085, 1046, 2513, +2085, 1046, 2513, +2085, 1046, 2513, +2085, 1046, 2513, +2085, 1046, 2513, +2065, 1109, 1913, +2065, 1110, 1913, +2065, 1112, 1915, +2065, 1113, 1916, +2064, 1115, 1918, +2063, 1118, 1921, +2063, 1121, 1924, +2061, 1126, 1929, +2060, 1132, 1936, +2058, 1137, 1943, +2057, 1137, 1952, +2055, 1137, 1964, +2053, 1137, 1979, +2053, 1164, 1999, +2049, 1195, 2025, +2041, 1167, 2059, +2028, 1112, 2110, +2027, 1145, 2168, +2024, 1061, 2228, +2023, 1050, 2301, +2024, 973, 2387, +2069, 983, 2473, +2092, 1159, 2513, +2092, 1159, 2513, +2092, 1159, 2513, +2092, 1159, 2513, +2092, 1159, 2513, +2092, 1159, 2513, +2092, 1159, 2513, +2092, 1159, 2513, +2092, 1159, 2513, +2092, 1159, 2513, +2079, 1177, 1931, +2078, 1178, 1932, +2078, 1179, 1933, +2078, 1180, 1934, +2077, 1182, 1936, +2077, 1184, 1939, +2076, 1187, 1942, +2075, 1191, 1947, +2073, 1196, 1953, +2071, 1204, 1961, +2068, 1213, 1971, +2065, 1225, 1985, +2062, 1230, 2000, +2062, 1252, 2020, +2062, 1280, 2044, +2056, 1256, 2073, +2047, 1209, 2114, +2037, 1182, 2169, +2024, 1169, 2235, +2023, 1221, 2303, +2029, 1152, 2384, +2060, 1207, 2475, +2100, 1275, 2513, +2100, 1275, 2513, +2100, 1275, 2513, +2100, 1275, 2513, +2100, 1275, 2513, +2100, 1275, 2513, +2100, 1275, 2513, +2100, 1275, 2513, +2100, 1275, 2513, +2100, 1275, 2513, +2099, 1357, 1955, +2099, 1357, 1955, +2099, 1357, 1955, +2099, 1357, 1956, +2098, 1357, 1957, +2098, 1357, 1958, +2097, 1357, 1960, +2096, 1357, 1962, +2094, 1357, 1965, +2093, 1357, 1969, +2090, 1361, 1977, +2086, 1370, 1990, +2083, 1381, 2008, +2080, 1396, 2034, +2079, 1416, 2059, +2078, 1420, 2093, +2067, 1399, 2124, +2059, 1381, 2174, +2045, 1359, 2234, +2030, 1417, 2304, +2051, 1393, 2388, +2070, 1417, 2476, +2115, 1452, 2513, +2115, 1452, 2513, +2115, 1452, 2513, +2115, 1452, 2513, +2115, 1452, 2513, +2115, 1452, 2513, +2115, 1452, 2513, +2115, 1452, 2513, +2115, 1452, 2513, +2115, 1452, 2513, +2118, 1561, 1978, +2118, 1561, 1978, +2118, 1561, 1979, +2118, 1561, 1980, +2119, 1561, 1982, +2119, 1561, 1984, +2119, 1561, 1986, +2120, 1561, 1990, +2120, 1561, 1994, +2119, 1561, 1998, +2116, 1561, 2003, +2113, 1561, 2009, +2109, 1560, 2018, +2103, 1553, 2032, +2099, 1566, 2064, +2098, 1570, 2096, +2095, 1587, 2145, +2080, 1579, 2177, +2077, 1562, 2236, +2046, 1604, 2305, +2071, 1614, 2389, +2114, 1600, 2477, +2143, 1637, 2513, +2143, 1637, 2513, +2143, 1637, 2513, +2143, 1637, 2513, +2143, 1637, 2513, +2143, 1637, 2513, +2143, 1637, 2513, +2143, 1637, 2513, +2143, 1637, 2513, +2143, 1637, 2513, +2134, 1765, 2000, +2134, 1765, 2001, +2134, 1766, 2001, +2134, 1766, 2002, +2134, 1767, 2003, +2134, 1767, 2004, +2134, 1768, 2005, +2134, 1769, 2007, +2134, 1771, 2010, +2134, 1772, 2014, +2135, 1773, 2021, +2137, 1773, 2031, +2138, 1773, 2045, +2138, 1767, 2062, +2131, 1758, 2076, +2129, 1756, 2098, +2124, 1756, 2137, +2121, 1783, 2193, +2113, 1774, 2243, +2086, 1783, 2307, +2096, 1787, 2390, +2148, 1816, 2480, +2194, 1817, 2514, +2194, 1817, 2514, +2194, 1817, 2514, +2194, 1817, 2514, +2194, 1817, 2514, +2194, 1817, 2514, +2194, 1817, 2514, +2194, 1817, 2514, +2194, 1817, 2514, +2194, 1817, 2514, +2181, 1956, 2056, +2181, 1956, 2057, +2181, 1956, 2057, +2182, 1956, 2057, +2182, 1955, 2057, +2182, 1955, 2057, +2182, 1955, 2058, +2183, 1954, 2058, +2183, 1953, 2059, +2184, 1951, 2060, +2185, 1950, 2062, +2187, 1947, 2063, +2188, 1945, 2068, +2188, 1950, 2081, +2188, 1955, 2098, +2191, 1957, 2124, +2187, 1958, 2158, +2166, 1958, 2197, +2157, 1958, 2256, +2157, 1958, 2315, +2170, 1965, 2391, +2214, 1983, 2481, +2243, 1992, 2520, +2243, 1992, 2520, +2243, 1992, 2520, +2243, 1992, 2520, +2243, 1992, 2520, +2243, 1992, 2520, +2243, 1992, 2520, +2243, 1992, 2520, +2243, 1992, 2520, +2243, 1992, 2520, +2280, 2135, 2094, +2279, 2135, 2094, +2279, 2135, 2094, +2279, 2135, 2093, +2279, 2135, 2093, +2279, 2135, 2093, +2278, 2135, 2093, +2278, 2135, 2092, +2278, 2135, 2091, +2277, 2135, 2090, +2276, 2135, 2089, +2275, 2135, 2087, +2273, 2135, 2088, +2271, 2132, 2104, +2268, 2128, 2124, +2265, 2127, 2141, +2261, 2127, 2163, +2267, 2131, 2204, +2267, 2143, 2274, +2279, 2151, 2326, +2302, 2151, 2402, +2336, 2169, 2486, +2365, 2174, 2524, +2365, 2174, 2524, +2365, 2174, 2524, +2365, 2174, 2524, +2365, 2174, 2524, +2365, 2174, 2524, +2365, 2174, 2524, +2365, 2174, 2524, +2365, 2174, 2524, +2365, 2174, 2524, +2461, 2367, 2129, +2461, 2367, 2129, +2461, 2367, 2129, +2460, 2367, 2129, +2460, 2367, 2129, +2460, 2367, 2129, +2460, 2367, 2129, +2459, 2367, 2129, +2458, 2367, 2129, +2457, 2367, 2129, +2456, 2367, 2129, +2456, 2367, 2131, +2456, 2368, 2135, +2457, 2370, 2144, +2458, 2370, 2155, +2459, 2368, 2173, +2458, 2367, 2191, +2459, 2372, 2228, +2457, 2374, 2273, +2469, 2375, 2338, +2498, 2390, 2405, +2539, 2403, 2489, +2561, 2413, 2521, +2561, 2413, 2521, +2561, 2413, 2521, +2561, 2413, 2521, +2561, 2413, 2521, +2561, 2413, 2521, +2561, 2413, 2521, +2561, 2413, 2521, +2561, 2413, 2521, +2561, 2413, 2521, +2709, 2666, 2040, +2709, 2666, 2040, +2709, 2665, 2040, +2709, 2665, 2040, +2709, 2665, 2040, +2709, 2665, 2040, +2709, 2665, 2040, +2710, 2664, 2040, +2710, 2664, 2039, +2710, 2664, 2038, +2710, 2664, 2037, +2710, 2663, 2035, +2710, 2663, 2036, +2709, 2665, 2056, +2708, 2668, 2074, +2708, 2667, 2090, +2708, 2666, 2122, +2710, 2669, 2190, +2713, 2675, 2273, +2712, 2672, 2336, +2722, 2681, 2446, +2732, 2688, 2548, +2743, 2699, 2604, +2743, 2699, 2604, +2743, 2699, 2604, +2743, 2699, 2604, +2743, 2699, 2604, +2743, 2699, 2604, +2743, 2699, 2604, +2743, 2699, 2604, +2743, 2699, 2604, +2743, 2699, 2604, +2736, 2777, 2472, +2736, 2777, 2472, +2736, 2777, 2472, +2736, 2777, 2473, +2736, 2778, 2473, +2736, 2778, 2473, +2736, 2778, 2473, +2736, 2778, 2474, +2736, 2778, 2475, +2736, 2778, 2475, +2736, 2779, 2476, +2736, 2779, 2478, +2736, 2779, 2480, +2736, 2779, 2480, +2736, 2779, 2480, +2737, 2778, 2487, +2736, 2777, 2497, +2732, 2777, 2512, +2731, 2783, 2550, +2734, 2783, 2585, +2737, 2787, 2644, +2741, 2798, 2718, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2736, 2777, 2472, +2736, 2777, 2472, +2736, 2777, 2472, +2736, 2777, 2473, +2736, 2778, 2473, +2736, 2778, 2473, +2736, 2778, 2473, +2736, 2778, 2474, +2736, 2778, 2475, +2736, 2778, 2475, +2736, 2779, 2476, +2736, 2779, 2478, +2736, 2779, 2480, +2736, 2779, 2480, +2736, 2779, 2480, +2737, 2778, 2487, +2736, 2777, 2497, +2732, 2777, 2512, +2731, 2783, 2550, +2734, 2783, 2585, +2737, 2787, 2644, +2741, 2798, 2718, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2736, 2777, 2472, +2736, 2777, 2472, +2736, 2777, 2472, +2736, 2777, 2473, +2736, 2778, 2473, +2736, 2778, 2473, +2736, 2778, 2473, +2736, 2778, 2474, +2736, 2778, 2475, +2736, 2778, 2475, +2736, 2779, 2476, +2736, 2779, 2478, +2736, 2779, 2480, +2736, 2779, 2480, +2736, 2779, 2480, +2737, 2778, 2487, +2736, 2777, 2497, +2732, 2777, 2512, +2731, 2783, 2550, +2734, 2783, 2585, +2737, 2787, 2644, +2741, 2798, 2718, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2736, 2777, 2472, +2736, 2777, 2472, +2736, 2777, 2472, +2736, 2777, 2473, +2736, 2778, 2473, +2736, 2778, 2473, +2736, 2778, 2473, +2736, 2778, 2474, +2736, 2778, 2475, +2736, 2778, 2475, +2736, 2779, 2476, +2736, 2779, 2478, +2736, 2779, 2480, +2736, 2779, 2480, +2736, 2779, 2480, +2737, 2778, 2487, +2736, 2777, 2497, +2732, 2777, 2512, +2731, 2783, 2550, +2734, 2783, 2585, +2737, 2787, 2644, +2741, 2798, 2718, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2736, 2777, 2472, +2736, 2777, 2472, +2736, 2777, 2472, +2736, 2777, 2473, +2736, 2778, 2473, +2736, 2778, 2473, +2736, 2778, 2473, +2736, 2778, 2474, +2736, 2778, 2475, +2736, 2778, 2475, +2736, 2779, 2476, +2736, 2779, 2478, +2736, 2779, 2480, +2736, 2779, 2480, +2736, 2779, 2480, +2737, 2778, 2487, +2736, 2777, 2497, +2732, 2777, 2512, +2731, 2783, 2550, +2734, 2783, 2585, +2737, 2787, 2644, +2741, 2798, 2718, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2736, 2777, 2472, +2736, 2777, 2472, +2736, 2777, 2472, +2736, 2777, 2473, +2736, 2778, 2473, +2736, 2778, 2473, +2736, 2778, 2473, +2736, 2778, 2474, +2736, 2778, 2475, +2736, 2778, 2475, +2736, 2779, 2476, +2736, 2779, 2478, +2736, 2779, 2480, +2736, 2779, 2480, +2736, 2779, 2480, +2737, 2778, 2487, +2736, 2777, 2497, +2732, 2777, 2512, +2731, 2783, 2550, +2734, 2783, 2585, +2737, 2787, 2644, +2741, 2798, 2718, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2736, 2777, 2472, +2736, 2777, 2472, +2736, 2777, 2472, +2736, 2777, 2473, +2736, 2778, 2473, +2736, 2778, 2473, +2736, 2778, 2473, +2736, 2778, 2474, +2736, 2778, 2475, +2736, 2778, 2475, +2736, 2779, 2476, +2736, 2779, 2478, +2736, 2779, 2480, +2736, 2779, 2480, +2736, 2779, 2480, +2737, 2778, 2487, +2736, 2777, 2497, +2732, 2777, 2512, +2731, 2783, 2550, +2734, 2783, 2585, +2737, 2787, 2644, +2741, 2798, 2718, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2736, 2777, 2472, +2736, 2777, 2472, +2736, 2777, 2472, +2736, 2777, 2473, +2736, 2778, 2473, +2736, 2778, 2473, +2736, 2778, 2473, +2736, 2778, 2474, +2736, 2778, 2475, +2736, 2778, 2475, +2736, 2779, 2476, +2736, 2779, 2478, +2736, 2779, 2480, +2736, 2779, 2480, +2736, 2779, 2480, +2737, 2778, 2487, +2736, 2777, 2497, +2732, 2777, 2512, +2731, 2783, 2550, +2734, 2783, 2585, +2737, 2787, 2644, +2741, 2798, 2718, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2736, 2777, 2472, +2736, 2777, 2472, +2736, 2777, 2472, +2736, 2777, 2473, +2736, 2778, 2473, +2736, 2778, 2473, +2736, 2778, 2473, +2736, 2778, 2474, +2736, 2778, 2475, +2736, 2778, 2475, +2736, 2779, 2476, +2736, 2779, 2478, +2736, 2779, 2480, +2736, 2779, 2480, +2736, 2779, 2480, +2737, 2778, 2487, +2736, 2777, 2497, +2732, 2777, 2512, +2731, 2783, 2550, +2734, 2783, 2585, +2737, 2787, 2644, +2741, 2798, 2718, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2736, 2777, 2472, +2736, 2777, 2472, +2736, 2777, 2472, +2736, 2777, 2473, +2736, 2778, 2473, +2736, 2778, 2473, +2736, 2778, 2473, +2736, 2778, 2474, +2736, 2778, 2475, +2736, 2778, 2475, +2736, 2779, 2476, +2736, 2779, 2478, +2736, 2779, 2480, +2736, 2779, 2480, +2736, 2779, 2480, +2737, 2778, 2487, +2736, 2777, 2497, +2732, 2777, 2512, +2731, 2783, 2550, +2734, 2783, 2585, +2737, 2787, 2644, +2741, 2798, 2718, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2203, 0, 1962, +2203, 0, 1963, +2203, 0, 1963, +2203, 0, 1964, +2202, 0, 1966, +2202, 0, 1967, +2202, 0, 1969, +2202, 0, 1972, +2201, 0, 1976, +2200, 0, 1981, +2199, 0, 1988, +2198, 0, 1996, +2196, 0, 2008, +2194, 0, 2027, +2190, 0, 2051, +2189, 0, 2090, +2187, 0, 2135, +2178, 0, 2178, +2160, 0, 2231, +2145, 0, 2305, +2169, 0, 2389, +2195, 0, 2474, +2191, 934, 2513, +2191, 934, 2513, +2191, 934, 2513, +2191, 934, 2513, +2191, 934, 2513, +2191, 934, 2513, +2191, 934, 2513, +2191, 934, 2513, +2191, 934, 2513, +2191, 934, 2513, +2203, 0, 1962, +2203, 0, 1963, +2203, 0, 1963, +2203, 0, 1965, +2202, 0, 1966, +2202, 0, 1967, +2202, 0, 1969, +2202, 0, 1972, +2201, 0, 1976, +2200, 0, 1981, +2199, 0, 1988, +2198, 0, 1997, +2196, 0, 2008, +2194, 0, 2027, +2190, 0, 2051, +2189, 0, 2090, +2187, 0, 2135, +2178, 0, 2178, +2160, 0, 2231, +2145, 0, 2305, +2169, 0, 2389, +2195, 0, 2474, +2191, 935, 2513, +2191, 935, 2513, +2191, 935, 2513, +2191, 935, 2513, +2191, 935, 2513, +2191, 935, 2513, +2191, 935, 2513, +2191, 935, 2513, +2191, 935, 2513, +2191, 935, 2513, +2203, 0, 1962, +2203, 0, 1963, +2203, 0, 1964, +2203, 0, 1965, +2202, 0, 1966, +2202, 0, 1968, +2202, 0, 1970, +2202, 0, 1973, +2201, 0, 1976, +2200, 0, 1981, +2199, 0, 1988, +2198, 0, 1997, +2196, 0, 2008, +2194, 0, 2026, +2190, 0, 2051, +2189, 0, 2090, +2187, 0, 2135, +2178, 0, 2178, +2161, 0, 2231, +2146, 0, 2305, +2169, 0, 2389, +2195, 0, 2474, +2191, 937, 2513, +2191, 937, 2513, +2191, 937, 2513, +2191, 937, 2513, +2191, 937, 2513, +2191, 937, 2513, +2191, 937, 2513, +2191, 937, 2513, +2191, 937, 2513, +2191, 937, 2513, +2203, 0, 1963, +2203, 0, 1963, +2203, 0, 1964, +2203, 0, 1965, +2202, 0, 1966, +2202, 0, 1968, +2202, 0, 1970, +2202, 0, 1973, +2201, 0, 1977, +2200, 0, 1982, +2199, 0, 1988, +2198, 0, 1997, +2196, 0, 2008, +2194, 0, 2026, +2190, 0, 2050, +2189, 0, 2090, +2187, 0, 2135, +2178, 0, 2178, +2161, 0, 2232, +2146, 0, 2305, +2169, 0, 2389, +2195, 0, 2474, +2192, 939, 2513, +2192, 939, 2513, +2192, 939, 2513, +2192, 939, 2513, +2192, 939, 2513, +2192, 939, 2513, +2192, 939, 2513, +2192, 939, 2513, +2192, 939, 2513, +2192, 939, 2513, +2202, 0, 1963, +2202, 0, 1963, +2202, 0, 1964, +2202, 0, 1965, +2202, 0, 1966, +2202, 0, 1968, +2202, 0, 1970, +2202, 0, 1973, +2201, 0, 1977, +2200, 0, 1982, +2199, 0, 1989, +2198, 0, 1997, +2196, 0, 2009, +2194, 0, 2026, +2190, 0, 2050, +2188, 0, 2090, +2187, 0, 2136, +2178, 0, 2178, +2161, 0, 2232, +2147, 0, 2305, +2169, 0, 2389, +2195, 0, 2474, +2192, 942, 2513, +2192, 942, 2513, +2192, 942, 2513, +2192, 942, 2513, +2192, 942, 2513, +2192, 942, 2513, +2192, 942, 2513, +2192, 942, 2513, +2192, 942, 2513, +2192, 942, 2513, +2202, 0, 1963, +2202, 0, 1964, +2202, 0, 1965, +2202, 0, 1966, +2202, 0, 1967, +2202, 0, 1969, +2202, 0, 1970, +2202, 0, 1973, +2201, 0, 1977, +2200, 0, 1982, +2199, 0, 1989, +2198, 0, 1998, +2196, 0, 2009, +2194, 0, 2026, +2190, 0, 2050, +2188, 0, 2090, +2187, 0, 2136, +2178, 0, 2178, +2162, 0, 2232, +2148, 0, 2305, +2169, 0, 2389, +2195, 74, 2474, +2193, 946, 2513, +2193, 946, 2513, +2193, 946, 2513, +2193, 946, 2513, +2193, 946, 2513, +2193, 946, 2513, +2193, 946, 2513, +2193, 946, 2513, +2193, 946, 2513, +2193, 946, 2513, +2202, 0, 1964, +2202, 0, 1965, +2202, 0, 1965, +2202, 0, 1966, +2202, 0, 1968, +2202, 0, 1969, +2202, 0, 1971, +2202, 0, 1974, +2201, 0, 1978, +2200, 0, 1983, +2199, 0, 1989, +2198, 0, 1998, +2196, 0, 2010, +2194, 0, 2025, +2190, 0, 2049, +2188, 0, 2090, +2187, 0, 2137, +2178, 0, 2178, +2162, 0, 2232, +2149, 0, 2305, +2168, 0, 2389, +2196, 195, 2474, +2194, 951, 2513, +2194, 951, 2513, +2194, 951, 2513, +2194, 951, 2513, +2194, 951, 2513, +2194, 951, 2513, +2194, 951, 2513, +2194, 951, 2513, +2194, 951, 2513, +2194, 951, 2513, +2202, 0, 1965, +2202, 0, 1965, +2202, 0, 1966, +2202, 0, 1967, +2202, 0, 1968, +2202, 0, 1970, +2202, 0, 1972, +2202, 0, 1975, +2201, 0, 1979, +2200, 0, 1984, +2199, 0, 1990, +2198, 0, 1999, +2196, 0, 2010, +2194, 0, 2024, +2190, 0, 2049, +2188, 0, 2090, +2187, 0, 2138, +2178, 0, 2178, +2163, 0, 2233, +2150, 0, 2306, +2168, 0, 2388, +2196, 319, 2474, +2195, 957, 2513, +2195, 957, 2513, +2195, 957, 2513, +2195, 957, 2513, +2195, 957, 2513, +2195, 957, 2513, +2195, 957, 2513, +2195, 957, 2513, +2195, 957, 2513, +2195, 957, 2513, +2201, 0, 1966, +2201, 0, 1966, +2201, 0, 1967, +2201, 0, 1968, +2201, 0, 1969, +2201, 0, 1971, +2201, 0, 1973, +2201, 0, 1976, +2201, 0, 1979, +2200, 0, 1984, +2199, 0, 1991, +2198, 0, 2000, +2196, 0, 2011, +2194, 0, 2024, +2190, 0, 2048, +2187, 0, 2090, +2187, 0, 2140, +2178, 0, 2178, +2165, 0, 2233, +2152, 111, 2306, +2167, 0, 2388, +2195, 419, 2475, +2197, 966, 2513, +2197, 966, 2513, +2197, 966, 2513, +2197, 966, 2513, +2197, 966, 2513, +2197, 966, 2513, +2197, 966, 2513, +2197, 966, 2513, +2197, 966, 2513, +2197, 966, 2513, +2200, 0, 1967, +2200, 0, 1968, +2200, 0, 1968, +2200, 0, 1969, +2200, 0, 1970, +2200, 0, 1972, +2200, 0, 1974, +2200, 0, 1977, +2200, 0, 1981, +2200, 0, 1986, +2199, 0, 1993, +2198, 0, 2001, +2196, 0, 2012, +2194, 0, 2023, +2190, 0, 2047, +2186, 0, 2090, +2186, 0, 2140, +2178, 0, 2178, +2166, 0, 2234, +2155, 244, 2307, +2166, 0, 2388, +2195, 523, 2475, +2199, 978, 2513, +2199, 978, 2513, +2199, 978, 2513, +2199, 978, 2513, +2199, 978, 2513, +2199, 978, 2513, +2199, 978, 2513, +2199, 978, 2513, +2199, 978, 2513, +2199, 978, 2513, +2199, 0, 1969, +2199, 0, 1969, +2199, 0, 1970, +2199, 0, 1971, +2199, 0, 1972, +2199, 0, 1974, +2199, 0, 1976, +2199, 0, 1979, +2199, 0, 1983, +2199, 0, 1988, +2199, 0, 1994, +2198, 0, 2003, +2196, 0, 2014, +2194, 0, 2025, +2190, 0, 2045, +2186, 0, 2089, +2185, 0, 2140, +2178, 0, 2180, +2169, 0, 2235, +2158, 376, 2308, +2165, 61, 2387, +2194, 633, 2476, +2202, 993, 2513, +2202, 993, 2513, +2202, 993, 2513, +2202, 993, 2513, +2202, 993, 2513, +2202, 993, 2513, +2202, 993, 2513, +2202, 993, 2513, +2202, 993, 2513, +2202, 993, 2513, +2198, 0, 1971, +2198, 0, 1972, +2198, 0, 1972, +2198, 0, 1973, +2198, 0, 1974, +2198, 0, 1976, +2198, 0, 1978, +2198, 0, 1981, +2198, 0, 1985, +2198, 0, 1990, +2198, 0, 1996, +2198, 0, 2005, +2196, 0, 2016, +2194, 0, 2027, +2190, 0, 2043, +2186, 0, 2087, +2183, 0, 2140, +2178, 0, 2183, +2172, 0, 2236, +2163, 508, 2309, +2167, 263, 2387, +2192, 748, 2476, +2206, 1012, 2513, +2206, 1012, 2513, +2206, 1012, 2513, +2206, 1012, 2513, +2206, 1012, 2513, +2206, 1012, 2513, +2206, 1012, 2513, +2206, 1012, 2513, +2206, 1012, 2513, +2206, 1012, 2513, +2197, 0, 1974, +2197, 0, 1974, +2197, 0, 1975, +2197, 0, 1976, +2197, 0, 1977, +2197, 0, 1979, +2197, 0, 1981, +2197, 0, 1984, +2197, 0, 1988, +2197, 0, 1993, +2197, 0, 1999, +2197, 0, 2008, +2196, 0, 2019, +2194, 0, 2030, +2190, 0, 2044, +2186, 0, 2085, +2183, 0, 2139, +2179, 0, 2186, +2175, 0, 2237, +2168, 643, 2310, +2170, 532, 2388, +2192, 890, 2477, +2211, 1054, 2513, +2211, 1054, 2513, +2211, 1054, 2513, +2211, 1054, 2513, +2211, 1054, 2513, +2211, 1054, 2513, +2211, 1054, 2513, +2211, 1054, 2513, +2211, 1054, 2513, +2211, 1054, 2513, +2200, 621, 1974, +2200, 621, 1974, +2200, 621, 1976, +2200, 621, 1977, +2200, 621, 1978, +2200, 621, 1980, +2201, 621, 1983, +2201, 621, 1986, +2202, 621, 1991, +2202, 621, 1997, +2202, 621, 2003, +2202, 621, 2012, +2202, 617, 2022, +2196, 529, 2033, +2193, 529, 2047, +2189, 621, 2082, +2185, 627, 2133, +2182, 413, 2189, +2177, 708, 2240, +2170, 828, 2310, +2173, 948, 2390, +2196, 1121, 2478, +2216, 1189, 2513, +2216, 1189, 2513, +2216, 1189, 2513, +2216, 1189, 2513, +2216, 1189, 2513, +2216, 1189, 2513, +2216, 1189, 2513, +2216, 1189, 2513, +2216, 1189, 2513, +2216, 1189, 2513, +2203, 974, 1974, +2203, 974, 1974, +2203, 974, 1976, +2203, 974, 1977, +2203, 974, 1978, +2204, 974, 1980, +2204, 974, 1983, +2204, 974, 1986, +2205, 974, 1991, +2206, 974, 1997, +2207, 974, 2005, +2208, 974, 2016, +2208, 973, 2027, +2203, 934, 2038, +2196, 877, 2052, +2192, 934, 2084, +2188, 977, 2129, +2185, 874, 2183, +2181, 1059, 2243, +2174, 996, 2310, +2175, 1202, 2391, +2206, 1271, 2478, +2222, 1322, 2513, +2222, 1322, 2513, +2222, 1322, 2513, +2222, 1322, 2513, +2222, 1322, 2513, +2222, 1322, 2513, +2222, 1322, 2513, +2222, 1322, 2513, +2222, 1322, 2513, +2222, 1322, 2513, +2208, 1278, 1984, +2208, 1279, 1985, +2208, 1279, 1986, +2208, 1281, 1986, +2209, 1282, 1987, +2209, 1284, 1988, +2209, 1286, 1990, +2209, 1289, 1992, +2210, 1294, 1995, +2211, 1299, 1998, +2212, 1302, 2005, +2213, 1302, 2016, +2214, 1300, 2030, +2212, 1282, 2047, +2206, 1256, 2063, +2201, 1278, 2090, +2194, 1321, 2134, +2193, 1308, 2182, +2182, 1327, 2241, +2178, 1331, 2310, +2182, 1416, 2391, +2214, 1452, 2477, +2228, 1489, 2513, +2228, 1489, 2513, +2228, 1489, 2513, +2228, 1489, 2513, +2228, 1489, 2513, +2228, 1489, 2513, +2228, 1489, 2513, +2228, 1489, 2513, +2228, 1489, 2513, +2228, 1489, 2513, +2220, 1531, 2004, +2220, 1531, 2004, +2220, 1531, 2004, +2220, 1532, 2005, +2220, 1533, 2006, +2220, 1534, 2007, +2220, 1535, 2008, +2220, 1537, 2010, +2220, 1540, 2013, +2221, 1543, 2017, +2222, 1547, 2021, +2223, 1553, 2027, +2224, 1559, 2037, +2222, 1557, 2051, +2218, 1543, 2073, +2214, 1535, 2102, +2208, 1550, 2140, +2199, 1572, 2190, +2195, 1558, 2240, +2192, 1577, 2310, +2192, 1604, 2393, +2223, 1653, 2476, +2238, 1676, 2514, +2238, 1676, 2514, +2238, 1676, 2514, +2238, 1676, 2514, +2238, 1676, 2514, +2238, 1676, 2514, +2238, 1676, 2514, +2238, 1676, 2514, +2238, 1676, 2514, +2238, 1676, 2514, +2241, 1755, 2023, +2241, 1755, 2023, +2241, 1755, 2024, +2241, 1755, 2024, +2241, 1755, 2025, +2241, 1755, 2025, +2241, 1755, 2026, +2241, 1755, 2028, +2241, 1755, 2029, +2241, 1755, 2031, +2241, 1758, 2036, +2241, 1761, 2042, +2240, 1765, 2049, +2240, 1765, 2063, +2238, 1765, 2080, +2237, 1764, 2104, +2229, 1762, 2147, +2223, 1755, 2193, +2223, 1765, 2244, +2223, 1774, 2315, +2215, 1795, 2391, +2250, 1824, 2482, +2262, 1849, 2517, +2262, 1849, 2517, +2262, 1849, 2517, +2262, 1849, 2517, +2262, 1849, 2517, +2262, 1849, 2517, +2262, 1849, 2517, +2262, 1849, 2517, +2262, 1849, 2517, +2262, 1849, 2517, +2268, 1946, 2048, +2268, 1946, 2049, +2269, 1946, 2049, +2269, 1946, 2050, +2269, 1946, 2051, +2269, 1946, 2051, +2270, 1946, 2053, +2270, 1946, 2054, +2270, 1946, 2057, +2271, 1946, 2060, +2272, 1946, 2064, +2273, 1946, 2070, +2274, 1945, 2077, +2274, 1945, 2087, +2274, 1945, 2099, +2271, 1951, 2124, +2268, 1961, 2158, +2265, 1963, 2203, +2273, 1968, 2256, +2261, 1969, 2321, +2271, 1965, 2394, +2310, 1995, 2482, +2335, 2014, 2520, +2335, 2014, 2520, +2335, 2014, 2520, +2335, 2014, 2520, +2335, 2014, 2520, +2335, 2014, 2520, +2335, 2014, 2520, +2335, 2014, 2520, +2335, 2014, 2520, +2335, 2014, 2520, +2351, 2143, 2087, +2351, 2143, 2087, +2351, 2143, 2087, +2351, 2143, 2088, +2351, 2143, 2088, +2351, 2143, 2089, +2351, 2143, 2091, +2351, 2143, 2092, +2351, 2143, 2094, +2351, 2143, 2097, +2351, 2143, 2101, +2351, 2143, 2106, +2351, 2143, 2112, +2351, 2143, 2115, +2351, 2143, 2119, +2351, 2143, 2141, +2349, 2146, 2174, +2346, 2147, 2214, +2351, 2143, 2263, +2356, 2159, 2326, +2362, 2167, 2401, +2402, 2189, 2492, +2434, 2202, 2530, +2434, 2202, 2530, +2434, 2202, 2530, +2434, 2202, 2530, +2434, 2202, 2530, +2434, 2202, 2530, +2434, 2202, 2530, +2434, 2202, 2530, +2434, 2202, 2530, +2434, 2202, 2530, +2515, 2384, 2126, +2514, 2384, 2127, +2514, 2384, 2127, +2514, 2384, 2127, +2514, 2383, 2127, +2514, 2383, 2127, +2514, 2383, 2128, +2514, 2383, 2128, +2514, 2382, 2129, +2513, 2382, 2130, +2513, 2381, 2131, +2513, 2381, 2133, +2514, 2382, 2135, +2515, 2384, 2141, +2515, 2385, 2150, +2515, 2388, 2172, +2515, 2388, 2195, +2520, 2388, 2230, +2523, 2391, 2279, +2523, 2395, 2342, +2548, 2407, 2404, +2582, 2421, 2483, +2607, 2433, 2514, +2607, 2433, 2514, +2607, 2433, 2514, +2607, 2433, 2514, +2607, 2433, 2514, +2607, 2433, 2514, +2607, 2433, 2514, +2607, 2433, 2514, +2607, 2433, 2514, +2607, 2433, 2514, +2731, 2680, 2128, +2731, 2680, 2129, +2731, 2680, 2129, +2731, 2680, 2130, +2731, 2680, 2131, +2731, 2681, 2132, +2731, 2681, 2133, +2731, 2681, 2135, +2731, 2681, 2136, +2730, 2681, 2137, +2730, 2681, 2138, +2729, 2680, 2140, +2728, 2679, 2142, +2728, 2679, 2150, +2730, 2679, 2164, +2731, 2678, 2176, +2730, 2679, 2195, +2730, 2680, 2243, +2735, 2682, 2308, +2735, 2687, 2382, +2739, 2689, 2468, +2750, 2708, 2581, +2756, 2707, 2625, +2756, 2707, 2625, +2756, 2707, 2625, +2756, 2707, 2625, +2756, 2707, 2625, +2756, 2707, 2625, +2756, 2707, 2625, +2756, 2707, 2625, +2756, 2707, 2625, +2756, 2707, 2625, +2755, 2784, 2495, +2755, 2784, 2495, +2755, 2784, 2495, +2755, 2784, 2496, +2755, 2784, 2496, +2755, 2784, 2496, +2755, 2784, 2497, +2755, 2784, 2498, +2755, 2785, 2499, +2755, 2785, 2501, +2755, 2786, 2503, +2755, 2786, 2506, +2755, 2787, 2509, +2755, 2787, 2512, +2755, 2787, 2515, +2754, 2787, 2520, +2753, 2788, 2528, +2753, 2787, 2543, +2751, 2785, 2569, +2749, 2789, 2602, +2753, 2795, 2660, +2755, 2801, 2726, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2755, 2784, 2495, +2755, 2784, 2495, +2755, 2784, 2495, +2755, 2784, 2496, +2755, 2784, 2496, +2755, 2784, 2496, +2755, 2784, 2497, +2755, 2784, 2498, +2755, 2785, 2499, +2755, 2785, 2501, +2755, 2786, 2503, +2755, 2786, 2506, +2755, 2787, 2509, +2755, 2787, 2512, +2755, 2787, 2515, +2754, 2787, 2520, +2753, 2788, 2528, +2753, 2787, 2543, +2751, 2785, 2569, +2749, 2789, 2602, +2753, 2795, 2660, +2755, 2801, 2726, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2755, 2784, 2495, +2755, 2784, 2495, +2755, 2784, 2495, +2755, 2784, 2496, +2755, 2784, 2496, +2755, 2784, 2496, +2755, 2784, 2497, +2755, 2784, 2498, +2755, 2785, 2499, +2755, 2785, 2501, +2755, 2786, 2503, +2755, 2786, 2506, +2755, 2787, 2509, +2755, 2787, 2512, +2755, 2787, 2515, +2754, 2787, 2520, +2753, 2788, 2528, +2753, 2787, 2543, +2751, 2785, 2569, +2749, 2789, 2602, +2753, 2795, 2660, +2755, 2801, 2726, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2755, 2784, 2495, +2755, 2784, 2495, +2755, 2784, 2495, +2755, 2784, 2496, +2755, 2784, 2496, +2755, 2784, 2496, +2755, 2784, 2497, +2755, 2784, 2498, +2755, 2785, 2499, +2755, 2785, 2501, +2755, 2786, 2503, +2755, 2786, 2506, +2755, 2787, 2509, +2755, 2787, 2512, +2755, 2787, 2515, +2754, 2787, 2520, +2753, 2788, 2528, +2753, 2787, 2543, +2751, 2785, 2569, +2749, 2789, 2602, +2753, 2795, 2660, +2755, 2801, 2726, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2755, 2784, 2495, +2755, 2784, 2495, +2755, 2784, 2495, +2755, 2784, 2496, +2755, 2784, 2496, +2755, 2784, 2496, +2755, 2784, 2497, +2755, 2784, 2498, +2755, 2785, 2499, +2755, 2785, 2501, +2755, 2786, 2503, +2755, 2786, 2506, +2755, 2787, 2509, +2755, 2787, 2512, +2755, 2787, 2515, +2754, 2787, 2520, +2753, 2788, 2528, +2753, 2787, 2543, +2751, 2785, 2569, +2749, 2789, 2602, +2753, 2795, 2660, +2755, 2801, 2726, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2755, 2784, 2495, +2755, 2784, 2495, +2755, 2784, 2495, +2755, 2784, 2496, +2755, 2784, 2496, +2755, 2784, 2496, +2755, 2784, 2497, +2755, 2784, 2498, +2755, 2785, 2499, +2755, 2785, 2501, +2755, 2786, 2503, +2755, 2786, 2506, +2755, 2787, 2509, +2755, 2787, 2512, +2755, 2787, 2515, +2754, 2787, 2520, +2753, 2788, 2528, +2753, 2787, 2543, +2751, 2785, 2569, +2749, 2789, 2602, +2753, 2795, 2660, +2755, 2801, 2726, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2755, 2784, 2495, +2755, 2784, 2495, +2755, 2784, 2495, +2755, 2784, 2496, +2755, 2784, 2496, +2755, 2784, 2496, +2755, 2784, 2497, +2755, 2784, 2498, +2755, 2785, 2499, +2755, 2785, 2501, +2755, 2786, 2503, +2755, 2786, 2506, +2755, 2787, 2509, +2755, 2787, 2512, +2755, 2787, 2515, +2754, 2787, 2520, +2753, 2788, 2528, +2753, 2787, 2543, +2751, 2785, 2569, +2749, 2789, 2602, +2753, 2795, 2660, +2755, 2801, 2726, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2755, 2784, 2495, +2755, 2784, 2495, +2755, 2784, 2495, +2755, 2784, 2496, +2755, 2784, 2496, +2755, 2784, 2496, +2755, 2784, 2497, +2755, 2784, 2498, +2755, 2785, 2499, +2755, 2785, 2501, +2755, 2786, 2503, +2755, 2786, 2506, +2755, 2787, 2509, +2755, 2787, 2512, +2755, 2787, 2515, +2754, 2787, 2520, +2753, 2788, 2528, +2753, 2787, 2543, +2751, 2785, 2569, +2749, 2789, 2602, +2753, 2795, 2660, +2755, 2801, 2726, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2755, 2784, 2495, +2755, 2784, 2495, +2755, 2784, 2495, +2755, 2784, 2496, +2755, 2784, 2496, +2755, 2784, 2496, +2755, 2784, 2497, +2755, 2784, 2498, +2755, 2785, 2499, +2755, 2785, 2501, +2755, 2786, 2503, +2755, 2786, 2506, +2755, 2787, 2509, +2755, 2787, 2512, +2755, 2787, 2515, +2754, 2787, 2520, +2753, 2788, 2528, +2753, 2787, 2543, +2751, 2785, 2569, +2749, 2789, 2602, +2753, 2795, 2660, +2755, 2801, 2726, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2755, 2784, 2495, +2755, 2784, 2495, +2755, 2784, 2495, +2755, 2784, 2496, +2755, 2784, 2496, +2755, 2784, 2496, +2755, 2784, 2497, +2755, 2784, 2498, +2755, 2785, 2499, +2755, 2785, 2501, +2755, 2786, 2503, +2755, 2786, 2506, +2755, 2787, 2509, +2755, 2787, 2512, +2755, 2787, 2515, +2754, 2787, 2520, +2753, 2788, 2528, +2753, 2787, 2543, +2751, 2785, 2569, +2749, 2789, 2602, +2753, 2795, 2660, +2755, 2801, 2726, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2331, 0, 2000, +2331, 0, 2000, +2331, 0, 2001, +2331, 0, 2001, +2331, 0, 2002, +2331, 0, 2003, +2331, 0, 2005, +2331, 0, 2007, +2331, 0, 2010, +2331, 0, 2013, +2331, 0, 2018, +2331, 0, 2024, +2330, 0, 2034, +2326, 0, 2051, +2322, 0, 2072, +2321, 0, 2094, +2320, 0, 2138, +2314, 0, 2186, +2319, 0, 2244, +2315, 0, 2315, +2317, 0, 2391, +2334, 913, 2480, +2348, 1255, 2518, +2348, 1255, 2518, +2348, 1255, 2518, +2348, 1255, 2518, +2348, 1255, 2518, +2348, 1255, 2518, +2348, 1255, 2518, +2348, 1255, 2518, +2348, 1255, 2518, +2348, 1255, 2518, +2331, 0, 2000, +2331, 0, 2000, +2331, 0, 2001, +2331, 0, 2001, +2331, 0, 2002, +2331, 0, 2003, +2331, 0, 2005, +2331, 0, 2007, +2331, 0, 2010, +2331, 0, 2013, +2331, 0, 2018, +2331, 0, 2024, +2330, 0, 2034, +2326, 0, 2051, +2322, 0, 2072, +2321, 0, 2094, +2320, 0, 2138, +2315, 0, 2186, +2319, 0, 2245, +2315, 0, 2315, +2317, 0, 2392, +2334, 917, 2480, +2348, 1256, 2518, +2348, 1256, 2518, +2348, 1256, 2518, +2348, 1256, 2518, +2348, 1256, 2518, +2348, 1256, 2518, +2348, 1256, 2518, +2348, 1256, 2518, +2348, 1256, 2518, +2348, 1256, 2518, +2331, 0, 2000, +2331, 0, 2000, +2331, 0, 2001, +2331, 0, 2001, +2331, 0, 2002, +2331, 0, 2003, +2331, 0, 2005, +2331, 0, 2007, +2331, 0, 2010, +2331, 0, 2013, +2331, 0, 2018, +2330, 0, 2024, +2329, 0, 2034, +2326, 0, 2051, +2322, 0, 2072, +2321, 0, 2095, +2320, 0, 2138, +2315, 0, 2186, +2319, 0, 2245, +2315, 0, 2315, +2317, 0, 2392, +2334, 922, 2479, +2348, 1258, 2518, +2348, 1258, 2518, +2348, 1258, 2518, +2348, 1258, 2518, +2348, 1258, 2518, +2348, 1258, 2518, +2348, 1258, 2518, +2348, 1258, 2518, +2348, 1258, 2518, +2348, 1258, 2518, +2331, 0, 2000, +2331, 0, 2000, +2331, 0, 2001, +2331, 0, 2001, +2331, 0, 2002, +2331, 0, 2003, +2331, 0, 2005, +2331, 0, 2007, +2331, 0, 2010, +2331, 0, 2013, +2331, 0, 2018, +2330, 0, 2024, +2329, 0, 2034, +2326, 0, 2052, +2322, 0, 2072, +2321, 0, 2095, +2321, 0, 2138, +2315, 0, 2186, +2319, 0, 2245, +2315, 0, 2315, +2317, 0, 2392, +2334, 929, 2479, +2348, 1260, 2518, +2348, 1260, 2518, +2348, 1260, 2518, +2348, 1260, 2518, +2348, 1260, 2518, +2348, 1260, 2518, +2348, 1260, 2518, +2348, 1260, 2518, +2348, 1260, 2518, +2348, 1260, 2518, +2331, 0, 2000, +2331, 0, 2000, +2331, 0, 2001, +2331, 0, 2001, +2331, 0, 2002, +2331, 0, 2003, +2331, 0, 2005, +2331, 0, 2007, +2331, 0, 2010, +2331, 0, 2013, +2331, 0, 2018, +2330, 0, 2024, +2329, 0, 2034, +2326, 0, 2052, +2322, 0, 2072, +2321, 0, 2095, +2321, 0, 2138, +2315, 0, 2186, +2319, 0, 2245, +2315, 0, 2315, +2317, 0, 2392, +2334, 938, 2479, +2349, 1263, 2518, +2349, 1263, 2518, +2349, 1263, 2518, +2349, 1263, 2518, +2349, 1263, 2518, +2349, 1263, 2518, +2349, 1263, 2518, +2349, 1263, 2518, +2349, 1263, 2518, +2349, 1263, 2518, +2331, 0, 2000, +2331, 0, 2000, +2331, 0, 2001, +2331, 0, 2001, +2330, 0, 2002, +2330, 0, 2003, +2330, 0, 2005, +2330, 0, 2007, +2330, 0, 2010, +2330, 0, 2013, +2330, 0, 2018, +2330, 0, 2024, +2329, 0, 2034, +2326, 0, 2052, +2322, 0, 2073, +2321, 0, 2095, +2322, 0, 2138, +2315, 0, 2186, +2318, 0, 2245, +2315, 30, 2315, +2317, 0, 2392, +2334, 949, 2479, +2349, 1267, 2518, +2349, 1267, 2518, +2349, 1267, 2518, +2349, 1267, 2518, +2349, 1267, 2518, +2349, 1267, 2518, +2349, 1267, 2518, +2349, 1267, 2518, +2349, 1267, 2518, +2349, 1267, 2518, +2331, 0, 2000, +2330, 0, 2000, +2330, 0, 2001, +2330, 0, 2001, +2330, 0, 2002, +2330, 0, 2003, +2330, 0, 2005, +2330, 0, 2007, +2330, 0, 2010, +2330, 0, 2013, +2330, 0, 2018, +2329, 0, 2024, +2328, 0, 2034, +2327, 0, 2053, +2323, 0, 2073, +2321, 0, 2096, +2322, 0, 2139, +2315, 0, 2186, +2318, 0, 2245, +2315, 163, 2315, +2317, 32, 2392, +2334, 964, 2478, +2350, 1272, 2518, +2350, 1272, 2518, +2350, 1272, 2518, +2350, 1272, 2518, +2350, 1272, 2518, +2350, 1272, 2518, +2350, 1272, 2518, +2350, 1272, 2518, +2350, 1272, 2518, +2350, 1272, 2518, +2330, 0, 2000, +2330, 0, 2000, +2330, 0, 2001, +2330, 0, 2001, +2330, 0, 2002, +2330, 0, 2003, +2329, 0, 2005, +2329, 0, 2007, +2329, 0, 2010, +2329, 0, 2013, +2329, 0, 2018, +2328, 0, 2024, +2327, 0, 2034, +2327, 0, 2053, +2323, 0, 2073, +2321, 0, 2096, +2323, 0, 2139, +2316, 0, 2186, +2318, 0, 2246, +2315, 295, 2315, +2317, 164, 2393, +2334, 983, 2478, +2351, 1279, 2518, +2351, 1279, 2518, +2351, 1279, 2518, +2351, 1279, 2518, +2351, 1279, 2518, +2351, 1279, 2518, +2351, 1279, 2518, +2351, 1279, 2518, +2351, 1279, 2518, +2351, 1279, 2518, +2330, 0, 2000, +2330, 0, 2000, +2330, 0, 2001, +2330, 0, 2001, +2329, 0, 2002, +2329, 0, 2003, +2329, 0, 2005, +2329, 0, 2007, +2328, 0, 2010, +2328, 0, 2013, +2328, 0, 2018, +2328, 0, 2024, +2327, 0, 2034, +2327, 0, 2054, +2323, 0, 2074, +2321, 0, 2097, +2325, 0, 2140, +2316, 0, 2186, +2317, 111, 2246, +2315, 426, 2315, +2317, 296, 2393, +2334, 993, 2478, +2352, 1288, 2518, +2352, 1288, 2518, +2352, 1288, 2518, +2352, 1288, 2518, +2352, 1288, 2518, +2352, 1288, 2518, +2352, 1288, 2518, +2352, 1288, 2518, +2352, 1288, 2518, +2352, 1288, 2518, +2329, 0, 2000, +2329, 0, 2000, +2329, 0, 2001, +2329, 0, 2001, +2329, 0, 2002, +2329, 0, 2003, +2328, 0, 2005, +2328, 0, 2007, +2328, 0, 2010, +2327, 0, 2013, +2327, 0, 2018, +2326, 0, 2024, +2325, 0, 2034, +2327, 0, 2055, +2324, 0, 2075, +2321, 0, 2098, +2325, 0, 2141, +2317, 0, 2186, +2317, 244, 2247, +2315, 559, 2315, +2317, 428, 2393, +2335, 1003, 2479, +2354, 1300, 2518, +2354, 1300, 2518, +2354, 1300, 2518, +2354, 1300, 2518, +2354, 1300, 2518, +2354, 1300, 2518, +2354, 1300, 2518, +2354, 1300, 2518, +2354, 1300, 2518, +2354, 1300, 2518, +2328, 0, 2000, +2328, 0, 2000, +2328, 0, 2001, +2328, 0, 2001, +2328, 0, 2002, +2328, 0, 2003, +2328, 0, 2005, +2327, 0, 2007, +2327, 0, 2010, +2326, 0, 2013, +2325, 0, 2018, +2325, 0, 2024, +2324, 0, 2034, +2326, 0, 2055, +2325, 61, 2077, +2322, 0, 2099, +2325, 0, 2142, +2319, 0, 2187, +2316, 376, 2248, +2315, 691, 2315, +2317, 560, 2394, +2337, 1018, 2479, +2356, 1315, 2518, +2356, 1315, 2518, +2356, 1315, 2518, +2356, 1315, 2518, +2356, 1315, 2518, +2356, 1315, 2518, +2356, 1315, 2518, +2356, 1315, 2518, +2356, 1315, 2518, +2356, 1315, 2518, +2328, 0, 2000, +2328, 0, 2000, +2328, 0, 2001, +2328, 0, 2001, +2328, 0, 2002, +2327, 0, 2003, +2327, 0, 2005, +2327, 0, 2007, +2326, 0, 2010, +2326, 0, 2013, +2325, 0, 2018, +2325, 0, 2027, +2324, 0, 2036, +2326, 0, 2057, +2327, 111, 2081, +2323, 0, 2103, +2324, 0, 2142, +2322, 0, 2190, +2315, 426, 2247, +2315, 741, 2315, +2319, 692, 2394, +2338, 1091, 2481, +2357, 1322, 2518, +2357, 1322, 2518, +2357, 1322, 2518, +2357, 1322, 2518, +2357, 1322, 2518, +2357, 1322, 2518, +2357, 1322, 2518, +2357, 1322, 2518, +2357, 1322, 2518, +2357, 1322, 2518, +2328, 0, 2000, +2328, 0, 2001, +2328, 0, 2001, +2328, 0, 2002, +2328, 0, 2003, +2328, 0, 2004, +2328, 0, 2006, +2327, 0, 2008, +2327, 0, 2011, +2326, 0, 2014, +2326, 0, 2019, +2325, 0, 2028, +2325, 0, 2040, +2327, 44, 2061, +2328, 216, 2085, +2326, 0, 2109, +2323, 0, 2139, +2324, 123, 2193, +2314, 517, 2247, +2316, 765, 2314, +2321, 843, 2393, +2340, 1204, 2482, +2357, 1332, 2518, +2357, 1332, 2518, +2357, 1332, 2518, +2357, 1332, 2518, +2357, 1332, 2518, +2357, 1332, 2518, +2357, 1332, 2518, +2357, 1332, 2518, +2357, 1332, 2518, +2357, 1332, 2518, +2332, 614, 2005, +2332, 614, 2005, +2332, 614, 2006, +2332, 614, 2007, +2332, 614, 2008, +2332, 614, 2009, +2331, 614, 2011, +2331, 614, 2014, +2331, 614, 2017, +2330, 614, 2021, +2329, 614, 2026, +2329, 614, 2035, +2329, 614, 2047, +2329, 614, 2057, +2330, 670, 2082, +2328, 727, 2109, +2321, 757, 2137, +2324, 709, 2196, +2318, 901, 2249, +2318, 868, 2316, +2319, 1072, 2391, +2342, 1300, 2483, +2357, 1409, 2519, +2357, 1409, 2519, +2357, 1409, 2519, +2357, 1409, 2519, +2357, 1409, 2519, +2357, 1409, 2519, +2357, 1409, 2519, +2357, 1409, 2519, +2357, 1409, 2519, +2357, 1409, 2519, +2336, 924, 2012, +2336, 924, 2013, +2336, 924, 2013, +2336, 924, 2014, +2335, 924, 2015, +2335, 924, 2017, +2335, 924, 2019, +2335, 924, 2021, +2335, 924, 2024, +2334, 924, 2029, +2333, 924, 2035, +2333, 924, 2042, +2333, 924, 2052, +2333, 924, 2063, +2333, 971, 2080, +2330, 1020, 2108, +2324, 1065, 2141, +2325, 1052, 2197, +2321, 1173, 2253, +2319, 1077, 2317, +2317, 1227, 2391, +2345, 1377, 2483, +2359, 1509, 2521, +2359, 1509, 2521, +2359, 1509, 2521, +2359, 1509, 2521, +2359, 1509, 2521, +2359, 1509, 2521, +2359, 1509, 2521, +2359, 1509, 2521, +2359, 1509, 2521, +2359, 1509, 2521, +2339, 1291, 2020, +2339, 1291, 2020, +2339, 1290, 2020, +2339, 1289, 2020, +2339, 1288, 2021, +2339, 1286, 2022, +2338, 1283, 2023, +2338, 1280, 2024, +2338, 1276, 2026, +2337, 1270, 2028, +2336, 1267, 2033, +2336, 1267, 2040, +2336, 1269, 2048, +2336, 1288, 2065, +2336, 1315, 2084, +2334, 1351, 2116, +2331, 1343, 2151, +2330, 1343, 2198, +2326, 1378, 2257, +2319, 1407, 2317, +2328, 1414, 2394, +2350, 1546, 2482, +2368, 1608, 2518, +2368, 1608, 2518, +2368, 1608, 2518, +2368, 1608, 2518, +2368, 1608, 2518, +2368, 1608, 2518, +2368, 1608, 2518, +2368, 1608, 2518, +2368, 1608, 2518, +2368, 1608, 2518, +2349, 1557, 2025, +2349, 1557, 2025, +2349, 1557, 2025, +2349, 1557, 2026, +2348, 1557, 2026, +2348, 1557, 2027, +2348, 1557, 2028, +2348, 1557, 2029, +2347, 1557, 2031, +2347, 1554, 2033, +2346, 1550, 2036, +2345, 1548, 2041, +2344, 1548, 2050, +2344, 1550, 2067, +2343, 1557, 2089, +2339, 1571, 2115, +2337, 1566, 2150, +2337, 1567, 2198, +2334, 1596, 2255, +2334, 1620, 2319, +2342, 1646, 2396, +2365, 1717, 2481, +2382, 1733, 2518, +2382, 1733, 2518, +2382, 1733, 2518, +2382, 1733, 2518, +2382, 1733, 2518, +2382, 1733, 2518, +2382, 1733, 2518, +2382, 1733, 2518, +2382, 1733, 2518, +2382, 1733, 2518, +2364, 1776, 2032, +2364, 1776, 2033, +2364, 1776, 2033, +2364, 1777, 2034, +2364, 1778, 2035, +2364, 1779, 2037, +2363, 1781, 2038, +2363, 1783, 2041, +2363, 1786, 2044, +2362, 1790, 2049, +2361, 1791, 2052, +2360, 1789, 2057, +2359, 1784, 2065, +2361, 1784, 2074, +2360, 1788, 2094, +2357, 1783, 2117, +2358, 1792, 2156, +2361, 1806, 2207, +2354, 1805, 2259, +2356, 1809, 2322, +2365, 1822, 2394, +2383, 1874, 2484, +2403, 1889, 2522, +2403, 1889, 2522, +2403, 1889, 2522, +2403, 1889, 2522, +2403, 1889, 2522, +2403, 1889, 2522, +2403, 1889, 2522, +2403, 1889, 2522, +2403, 1889, 2522, +2403, 1889, 2522, +2391, 1976, 2073, +2391, 1976, 2073, +2391, 1976, 2073, +2391, 1976, 2073, +2391, 1976, 2073, +2391, 1976, 2074, +2391, 1976, 2074, +2391, 1976, 2075, +2391, 1976, 2076, +2391, 1976, 2077, +2391, 1976, 2078, +2391, 1976, 2080, +2392, 1977, 2084, +2394, 1981, 2093, +2395, 1984, 2105, +2395, 1984, 2134, +2392, 1984, 2163, +2391, 1984, 2207, +2387, 1995, 2266, +2396, 1995, 2324, +2406, 2017, 2405, +2425, 2038, 2488, +2448, 2060, 2526, +2448, 2060, 2526, +2448, 2060, 2526, +2448, 2060, 2526, +2448, 2060, 2526, +2448, 2060, 2526, +2448, 2060, 2526, +2448, 2060, 2526, +2448, 2060, 2526, +2448, 2060, 2526, +2463, 2177, 2109, +2463, 2177, 2109, +2463, 2177, 2110, +2463, 2177, 2110, +2463, 2177, 2110, +2463, 2177, 2111, +2463, 2178, 2112, +2463, 2178, 2113, +2463, 2179, 2114, +2463, 2180, 2116, +2463, 2181, 2119, +2462, 2182, 2121, +2460, 2183, 2124, +2459, 2181, 2126, +2458, 2177, 2134, +2459, 2184, 2157, +2463, 2186, 2183, +2461, 2184, 2220, +2460, 2188, 2268, +2468, 2189, 2340, +2476, 2191, 2406, +2508, 2230, 2493, +2527, 2237, 2533, +2527, 2237, 2533, +2527, 2237, 2533, +2527, 2237, 2533, +2527, 2237, 2533, +2527, 2237, 2533, +2527, 2237, 2533, +2527, 2237, 2533, +2527, 2237, 2533, +2527, 2237, 2533, +2598, 2410, 2071, +2598, 2410, 2071, +2599, 2411, 2071, +2599, 2411, 2071, +2599, 2411, 2071, +2600, 2412, 2070, +2600, 2412, 2070, +2602, 2413, 2069, +2603, 2414, 2069, +2604, 2416, 2068, +2606, 2418, 2066, +2607, 2419, 2068, +2607, 2420, 2073, +2607, 2420, 2079, +2607, 2420, 2088, +2607, 2420, 2112, +2607, 2422, 2147, +2606, 2422, 2181, +2609, 2420, 2243, +2615, 2426, 2302, +2628, 2437, 2380, +2656, 2458, 2462, +2676, 2468, 2496, +2676, 2468, 2496, +2676, 2468, 2496, +2676, 2468, 2496, +2676, 2468, 2496, +2676, 2468, 2496, +2676, 2468, 2496, +2676, 2468, 2496, +2676, 2468, 2496, +2676, 2468, 2496, +2763, 2702, 2255, +2763, 2702, 2255, +2763, 2702, 2255, +2762, 2701, 2255, +2762, 2701, 2255, +2762, 2701, 2255, +2762, 2701, 2255, +2762, 2701, 2255, +2762, 2701, 2255, +2763, 2701, 2256, +2763, 2701, 2257, +2764, 2701, 2260, +2765, 2701, 2267, +2765, 2701, 2274, +2763, 2702, 2284, +2762, 2704, 2300, +2763, 2706, 2316, +2764, 2703, 2348, +2764, 2703, 2388, +2768, 2710, 2455, +2769, 2717, 2538, +2774, 2727, 2626, +2777, 2731, 2667, +2777, 2731, 2667, +2777, 2731, 2667, +2777, 2731, 2667, +2777, 2731, 2667, +2777, 2731, 2667, +2777, 2731, 2667, +2777, 2731, 2667, +2777, 2731, 2667, +2777, 2731, 2667, +2781, 2797, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2549, +2781, 2798, 2550, +2781, 2799, 2550, +2781, 2799, 2551, +2781, 2800, 2553, +2782, 2800, 2555, +2782, 2801, 2558, +2781, 2801, 2560, +2780, 2800, 2559, +2782, 2800, 2561, +2781, 2802, 2573, +2781, 2801, 2584, +2780, 2801, 2606, +2777, 2799, 2640, +2775, 2801, 2677, +2779, 2810, 2744, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2797, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2549, +2781, 2798, 2550, +2781, 2799, 2550, +2781, 2799, 2551, +2781, 2800, 2553, +2782, 2800, 2555, +2782, 2801, 2558, +2781, 2801, 2560, +2780, 2800, 2559, +2782, 2800, 2561, +2781, 2802, 2573, +2781, 2801, 2584, +2780, 2801, 2606, +2777, 2799, 2640, +2775, 2801, 2677, +2779, 2810, 2744, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2797, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2549, +2781, 2798, 2550, +2781, 2799, 2550, +2781, 2799, 2551, +2781, 2800, 2553, +2782, 2800, 2555, +2782, 2801, 2558, +2781, 2801, 2560, +2780, 2800, 2559, +2782, 2800, 2561, +2781, 2802, 2573, +2781, 2801, 2584, +2780, 2801, 2606, +2777, 2799, 2640, +2775, 2801, 2677, +2779, 2810, 2744, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2797, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2549, +2781, 2798, 2550, +2781, 2799, 2550, +2781, 2799, 2551, +2781, 2800, 2553, +2782, 2800, 2555, +2782, 2801, 2558, +2781, 2801, 2560, +2780, 2800, 2559, +2782, 2800, 2561, +2781, 2802, 2573, +2781, 2801, 2584, +2780, 2801, 2606, +2777, 2799, 2640, +2775, 2801, 2677, +2779, 2810, 2744, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2797, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2549, +2781, 2798, 2550, +2781, 2799, 2550, +2781, 2799, 2551, +2781, 2800, 2553, +2782, 2800, 2555, +2782, 2801, 2558, +2781, 2801, 2560, +2780, 2800, 2559, +2782, 2800, 2561, +2781, 2802, 2573, +2781, 2801, 2584, +2780, 2801, 2606, +2777, 2799, 2640, +2775, 2801, 2677, +2779, 2810, 2744, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2797, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2549, +2781, 2798, 2550, +2781, 2799, 2550, +2781, 2799, 2551, +2781, 2800, 2553, +2782, 2800, 2555, +2782, 2801, 2558, +2781, 2801, 2560, +2780, 2800, 2559, +2782, 2800, 2561, +2781, 2802, 2573, +2781, 2801, 2584, +2780, 2801, 2606, +2777, 2799, 2640, +2775, 2801, 2677, +2779, 2810, 2744, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2797, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2549, +2781, 2798, 2550, +2781, 2799, 2550, +2781, 2799, 2551, +2781, 2800, 2553, +2782, 2800, 2555, +2782, 2801, 2558, +2781, 2801, 2560, +2780, 2800, 2559, +2782, 2800, 2561, +2781, 2802, 2573, +2781, 2801, 2584, +2780, 2801, 2606, +2777, 2799, 2640, +2775, 2801, 2677, +2779, 2810, 2744, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2797, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2549, +2781, 2798, 2550, +2781, 2799, 2550, +2781, 2799, 2551, +2781, 2800, 2553, +2782, 2800, 2555, +2782, 2801, 2558, +2781, 2801, 2560, +2780, 2800, 2559, +2782, 2800, 2561, +2781, 2802, 2573, +2781, 2801, 2584, +2780, 2801, 2606, +2777, 2799, 2640, +2775, 2801, 2677, +2779, 2810, 2744, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2797, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2549, +2781, 2798, 2550, +2781, 2799, 2550, +2781, 2799, 2551, +2781, 2800, 2553, +2782, 2800, 2555, +2782, 2801, 2558, +2781, 2801, 2560, +2780, 2800, 2559, +2782, 2800, 2561, +2781, 2802, 2573, +2781, 2801, 2584, +2780, 2801, 2606, +2777, 2799, 2640, +2775, 2801, 2677, +2779, 2810, 2744, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2797, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2549, +2781, 2798, 2550, +2781, 2799, 2550, +2781, 2799, 2551, +2781, 2800, 2553, +2782, 2800, 2555, +2782, 2801, 2558, +2781, 2801, 2560, +2780, 2800, 2559, +2782, 2800, 2561, +2781, 2802, 2573, +2781, 2801, 2584, +2780, 2801, 2606, +2777, 2799, 2640, +2775, 2801, 2677, +2779, 2810, 2744, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2481, 974, 2044, +2481, 973, 2044, +2481, 971, 2044, +2481, 969, 2045, +2480, 967, 2045, +2480, 963, 2046, +2480, 958, 2047, +2480, 951, 2048, +2480, 951, 2051, +2480, 951, 2054, +2480, 951, 2058, +2480, 951, 2063, +2480, 955, 2072, +2479, 992, 2087, +2477, 1037, 2103, +2476, 1071, 2127, +2475, 1132, 2163, +2475, 1219, 2209, +2476, 1370, 2267, +2478, 1392, 2329, +2488, 1469, 2402, +2504, 1610, 2488, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2481, 977, 2044, +2481, 977, 2044, +2481, 976, 2044, +2480, 974, 2045, +2480, 971, 2045, +2480, 968, 2046, +2480, 963, 2047, +2480, 956, 2048, +2480, 955, 2051, +2480, 955, 2054, +2480, 955, 2058, +2480, 955, 2063, +2480, 960, 2072, +2479, 996, 2087, +2477, 1041, 2103, +2476, 1074, 2127, +2476, 1133, 2163, +2475, 1220, 2209, +2476, 1373, 2267, +2478, 1394, 2329, +2488, 1469, 2402, +2504, 1611, 2488, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2481, 982, 2044, +2481, 982, 2044, +2480, 982, 2044, +2480, 980, 2045, +2480, 977, 2045, +2480, 974, 2046, +2480, 969, 2047, +2480, 962, 2048, +2480, 962, 2051, +2480, 962, 2054, +2480, 962, 2058, +2480, 962, 2063, +2480, 966, 2072, +2479, 1002, 2087, +2477, 1046, 2103, +2476, 1079, 2127, +2476, 1136, 2162, +2475, 1221, 2209, +2476, 1377, 2267, +2478, 1397, 2329, +2488, 1469, 2402, +2504, 1611, 2488, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2481, 988, 2044, +2480, 988, 2044, +2480, 988, 2044, +2480, 988, 2045, +2480, 985, 2045, +2480, 981, 2046, +2480, 977, 2047, +2480, 970, 2048, +2480, 970, 2051, +2480, 970, 2054, +2480, 970, 2058, +2480, 970, 2063, +2480, 974, 2072, +2479, 1010, 2087, +2477, 1053, 2103, +2476, 1085, 2127, +2476, 1138, 2162, +2475, 1222, 2209, +2476, 1382, 2267, +2478, 1400, 2329, +2488, 1469, 2402, +2504, 1612, 2488, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2480, 996, 2044, +2480, 996, 2044, +2480, 996, 2044, +2480, 996, 2045, +2480, 996, 2045, +2480, 992, 2046, +2480, 987, 2047, +2480, 981, 2048, +2480, 981, 2051, +2480, 981, 2054, +2480, 981, 2058, +2480, 981, 2063, +2480, 985, 2072, +2479, 1020, 2087, +2477, 1062, 2103, +2476, 1094, 2127, +2476, 1142, 2162, +2476, 1223, 2208, +2476, 1388, 2268, +2478, 1404, 2329, +2488, 1469, 2402, +2504, 1614, 2487, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2480, 1006, 2044, +2480, 1006, 2044, +2480, 1006, 2044, +2480, 1006, 2045, +2480, 1006, 2045, +2480, 1006, 2046, +2480, 1001, 2047, +2479, 995, 2048, +2479, 995, 2051, +2479, 995, 2054, +2479, 995, 2058, +2479, 995, 2063, +2479, 999, 2072, +2479, 1032, 2087, +2477, 1074, 2103, +2476, 1105, 2127, +2476, 1147, 2162, +2476, 1225, 2208, +2476, 1397, 2268, +2478, 1409, 2329, +2488, 1469, 2401, +2503, 1615, 2487, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2480, 1019, 2044, +2480, 1019, 2044, +2480, 1019, 2044, +2480, 1019, 2045, +2480, 1019, 2045, +2480, 1019, 2046, +2479, 1019, 2047, +2479, 1013, 2048, +2479, 1013, 2051, +2479, 1013, 2054, +2479, 1013, 2058, +2479, 1013, 2063, +2479, 1017, 2072, +2479, 1049, 2087, +2477, 1089, 2103, +2475, 1119, 2127, +2476, 1154, 2161, +2476, 1228, 2208, +2477, 1408, 2268, +2477, 1417, 2329, +2488, 1469, 2401, +2503, 1618, 2486, +2518, 1697, 2526, +2518, 1697, 2526, +2518, 1697, 2526, +2518, 1697, 2526, +2518, 1697, 2526, +2518, 1697, 2526, +2518, 1697, 2526, +2518, 1697, 2526, +2518, 1697, 2526, +2518, 1697, 2526, +2480, 1036, 2044, +2480, 1036, 2044, +2480, 1036, 2044, +2480, 1036, 2045, +2480, 1036, 2045, +2479, 1036, 2046, +2479, 1036, 2047, +2479, 1036, 2048, +2479, 1036, 2051, +2479, 1036, 2054, +2479, 1036, 2058, +2479, 1036, 2063, +2479, 1039, 2072, +2478, 1070, 2087, +2476, 1108, 2103, +2475, 1137, 2127, +2477, 1162, 2161, +2476, 1232, 2207, +2477, 1423, 2268, +2477, 1426, 2329, +2488, 1469, 2401, +2503, 1621, 2486, +2518, 1697, 2526, +2518, 1697, 2526, +2518, 1697, 2526, +2518, 1697, 2526, +2518, 1697, 2526, +2518, 1697, 2526, +2518, 1697, 2526, +2518, 1697, 2526, +2518, 1697, 2526, +2518, 1697, 2526, +2480, 1071, 2044, +2480, 1071, 2044, +2480, 1071, 2044, +2480, 1071, 2045, +2480, 1071, 2045, +2479, 1071, 2046, +2479, 1071, 2047, +2479, 1071, 2048, +2479, 1044, 2051, +2479, 1044, 2054, +2479, 1044, 2058, +2479, 1044, 2063, +2479, 1048, 2072, +2479, 1085, 2087, +2477, 1122, 2103, +2476, 1149, 2126, +2478, 1179, 2161, +2476, 1241, 2208, +2477, 1424, 2268, +2478, 1436, 2329, +2488, 1480, 2401, +2504, 1627, 2485, +2519, 1702, 2526, +2519, 1702, 2526, +2519, 1702, 2526, +2519, 1702, 2526, +2519, 1702, 2526, +2519, 1702, 2526, +2519, 1702, 2526, +2519, 1702, 2526, +2519, 1702, 2526, +2519, 1702, 2526, +2480, 1115, 2044, +2480, 1115, 2044, +2480, 1115, 2044, +2480, 1115, 2045, +2480, 1115, 2045, +2479, 1115, 2046, +2479, 1115, 2047, +2479, 1115, 2048, +2479, 1091, 2051, +2479, 1054, 2054, +2479, 1054, 2058, +2479, 1054, 2063, +2479, 1058, 2072, +2479, 1099, 2087, +2478, 1138, 2103, +2476, 1165, 2125, +2478, 1193, 2160, +2477, 1254, 2209, +2477, 1424, 2266, +2479, 1448, 2329, +2488, 1495, 2401, +2504, 1635, 2485, +2521, 1708, 2526, +2521, 1708, 2526, +2521, 1708, 2526, +2521, 1708, 2526, +2521, 1708, 2526, +2521, 1708, 2526, +2521, 1708, 2526, +2521, 1708, 2526, +2521, 1708, 2526, +2521, 1708, 2526, +2480, 1169, 2044, +2480, 1169, 2044, +2480, 1169, 2044, +2480, 1169, 2045, +2480, 1169, 2045, +2479, 1169, 2046, +2479, 1169, 2047, +2479, 1169, 2048, +2479, 1147, 2051, +2479, 1114, 2054, +2479, 1067, 2058, +2479, 1067, 2063, +2479, 1070, 2072, +2479, 1111, 2087, +2479, 1159, 2103, +2478, 1185, 2125, +2480, 1212, 2159, +2478, 1278, 2209, +2477, 1424, 2264, +2480, 1464, 2329, +2488, 1514, 2402, +2505, 1646, 2485, +2523, 1718, 2525, +2523, 1718, 2525, +2523, 1718, 2525, +2523, 1718, 2525, +2523, 1718, 2525, +2523, 1718, 2525, +2523, 1718, 2525, +2523, 1718, 2525, +2523, 1718, 2525, +2523, 1718, 2525, +2480, 1231, 2044, +2480, 1231, 2044, +2480, 1231, 2044, +2480, 1231, 2045, +2480, 1231, 2045, +2479, 1231, 2046, +2479, 1231, 2047, +2479, 1231, 2048, +2479, 1212, 2051, +2479, 1184, 2054, +2479, 1144, 2058, +2479, 1083, 2063, +2479, 1087, 2072, +2479, 1126, 2087, +2481, 1186, 2103, +2479, 1210, 2125, +2481, 1236, 2158, +2479, 1308, 2209, +2477, 1424, 2262, +2481, 1485, 2329, +2488, 1542, 2402, +2507, 1660, 2485, +2526, 1729, 2524, +2526, 1729, 2524, +2526, 1729, 2524, +2526, 1729, 2524, +2526, 1729, 2524, +2526, 1729, 2524, +2526, 1729, 2524, +2526, 1729, 2524, +2526, 1729, 2524, +2526, 1729, 2524, +2480, 1299, 2045, +2480, 1299, 2045, +2480, 1299, 2045, +2480, 1299, 2046, +2480, 1299, 2046, +2480, 1299, 2047, +2480, 1299, 2048, +2479, 1299, 2049, +2479, 1283, 2051, +2479, 1259, 2054, +2479, 1225, 2059, +2479, 1174, 2064, +2479, 1114, 2072, +2480, 1151, 2087, +2481, 1213, 2103, +2481, 1244, 2125, +2483, 1268, 2156, +2481, 1346, 2209, +2477, 1430, 2260, +2483, 1511, 2329, +2489, 1583, 2403, +2509, 1680, 2486, +2529, 1745, 2524, +2529, 1745, 2524, +2529, 1745, 2524, +2529, 1745, 2524, +2529, 1745, 2524, +2529, 1745, 2524, +2529, 1745, 2524, +2529, 1745, 2524, +2529, 1745, 2524, +2529, 1745, 2524, +2482, 1385, 2049, +2482, 1385, 2049, +2482, 1384, 2049, +2482, 1384, 2050, +2482, 1382, 2050, +2482, 1381, 2051, +2482, 1379, 2052, +2481, 1376, 2053, +2482, 1366, 2055, +2482, 1349, 2058, +2482, 1321, 2063, +2482, 1281, 2068, +2482, 1235, 2076, +2482, 1263, 2087, +2484, 1312, 2103, +2484, 1330, 2127, +2485, 1346, 2157, +2483, 1386, 2211, +2480, 1472, 2262, +2483, 1568, 2328, +2492, 1634, 2404, +2509, 1714, 2486, +2531, 1767, 2524, +2531, 1767, 2524, +2531, 1767, 2524, +2531, 1767, 2524, +2531, 1767, 2524, +2531, 1767, 2524, +2531, 1767, 2524, +2531, 1767, 2524, +2531, 1767, 2524, +2531, 1767, 2524, +2484, 1508, 2049, +2484, 1507, 2049, +2484, 1507, 2049, +2484, 1506, 2050, +2484, 1506, 2050, +2484, 1504, 2051, +2483, 1503, 2052, +2483, 1501, 2053, +2483, 1493, 2055, +2484, 1482, 2058, +2485, 1467, 2063, +2485, 1445, 2068, +2485, 1416, 2076, +2486, 1436, 2087, +2488, 1470, 2103, +2487, 1479, 2127, +2487, 1478, 2157, +2484, 1484, 2208, +2487, 1547, 2268, +2485, 1642, 2328, +2495, 1671, 2406, +2509, 1751, 2486, +2531, 1801, 2522, +2531, 1801, 2522, +2531, 1801, 2522, +2531, 1801, 2522, +2531, 1801, 2522, +2531, 1801, 2522, +2531, 1801, 2522, +2531, 1801, 2522, +2531, 1801, 2522, +2531, 1801, 2522, +2490, 1632, 2052, +2490, 1632, 2052, +2490, 1632, 2053, +2490, 1632, 2054, +2490, 1632, 2054, +2490, 1632, 2056, +2490, 1632, 2057, +2490, 1632, 2060, +2490, 1628, 2062, +2491, 1623, 2066, +2491, 1613, 2070, +2492, 1598, 2075, +2493, 1580, 2082, +2492, 1580, 2091, +2493, 1600, 2105, +2492, 1613, 2131, +2491, 1631, 2162, +2489, 1632, 2206, +2493, 1658, 2265, +2493, 1730, 2328, +2499, 1742, 2404, +2518, 1813, 2489, +2537, 1864, 2526, +2537, 1864, 2526, +2537, 1864, 2526, +2537, 1864, 2526, +2537, 1864, 2526, +2537, 1864, 2526, +2537, 1864, 2526, +2537, 1864, 2526, +2537, 1864, 2526, +2537, 1864, 2526, +2502, 1784, 2071, +2502, 1784, 2071, +2502, 1784, 2071, +2502, 1784, 2072, +2502, 1784, 2073, +2502, 1784, 2073, +2502, 1784, 2075, +2502, 1784, 2077, +2502, 1779, 2078, +2502, 1774, 2081, +2503, 1769, 2085, +2503, 1762, 2090, +2504, 1754, 2098, +2504, 1757, 2107, +2503, 1757, 2115, +2502, 1754, 2140, +2499, 1757, 2175, +2500, 1778, 2215, +2501, 1806, 2266, +2500, 1817, 2326, +2509, 1832, 2402, +2528, 1891, 2490, +2547, 1940, 2532, +2547, 1940, 2532, +2547, 1940, 2532, +2547, 1940, 2532, +2547, 1940, 2532, +2547, 1940, 2532, +2547, 1940, 2532, +2547, 1940, 2532, +2547, 1940, 2532, +2547, 1940, 2532, +2516, 1927, 2075, +2516, 1928, 2075, +2516, 1928, 2075, +2516, 1928, 2076, +2516, 1928, 2076, +2517, 1929, 2077, +2517, 1929, 2078, +2517, 1930, 2079, +2517, 1930, 2081, +2516, 1930, 2084, +2516, 1924, 2087, +2515, 1913, 2090, +2514, 1901, 2096, +2516, 1900, 2105, +2517, 1912, 2120, +2515, 1910, 2143, +2514, 1921, 2180, +2513, 1918, 2218, +2516, 1938, 2272, +2518, 1938, 2333, +2528, 1977, 2406, +2552, 2008, 2491, +2567, 2036, 2526, +2567, 2036, 2526, +2567, 2036, 2526, +2567, 2036, 2526, +2567, 2036, 2526, +2567, 2036, 2526, +2567, 2036, 2526, +2567, 2036, 2526, +2567, 2036, 2526, +2567, 2036, 2526, +2547, 2073, 2093, +2547, 2073, 2093, +2547, 2073, 2093, +2546, 2073, 2093, +2546, 2073, 2094, +2546, 2073, 2094, +2545, 2073, 2095, +2545, 2073, 2096, +2545, 2073, 2098, +2545, 2073, 2100, +2545, 2073, 2102, +2545, 2073, 2106, +2545, 2073, 2111, +2545, 2075, 2119, +2543, 2075, 2127, +2543, 2078, 2149, +2543, 2075, 2180, +2546, 2089, 2222, +2546, 2091, 2274, +2551, 2098, 2337, +2558, 2115, 2411, +2588, 2155, 2491, +2598, 2168, 2529, +2598, 2168, 2529, +2598, 2168, 2529, +2598, 2168, 2529, +2598, 2168, 2529, +2598, 2168, 2529, +2598, 2168, 2529, +2598, 2168, 2529, +2598, 2168, 2529, +2598, 2168, 2529, +2602, 2259, 2099, +2602, 2258, 2099, +2602, 2258, 2099, +2602, 2258, 2099, +2602, 2258, 2099, +2601, 2258, 2099, +2600, 2258, 2099, +2600, 2257, 2099, +2600, 2257, 2101, +2600, 2257, 2104, +2600, 2257, 2108, +2600, 2257, 2113, +2600, 2257, 2120, +2603, 2257, 2132, +2606, 2257, 2144, +2606, 2263, 2161, +2611, 2270, 2190, +2606, 2266, 2226, +2612, 2277, 2289, +2615, 2277, 2347, +2621, 2290, 2414, +2651, 2318, 2497, +2668, 2333, 2527, +2668, 2333, 2527, +2668, 2333, 2527, +2668, 2333, 2527, +2668, 2333, 2527, +2668, 2333, 2527, +2668, 2333, 2527, +2668, 2333, 2527, +2668, 2333, 2527, +2668, 2333, 2527, +2722, 2488, 1839, +2722, 2488, 1839, +2722, 2488, 1841, +2722, 2488, 1843, +2723, 2488, 1845, +2723, 2489, 1848, +2724, 2489, 1852, +2724, 2489, 1858, +2724, 2489, 1862, +2724, 2489, 1867, +2724, 2488, 1873, +2723, 2488, 1876, +2723, 2488, 1878, +2722, 2488, 1891, +2722, 2486, 1913, +2722, 2485, 1956, +2723, 2487, 2015, +2723, 2486, 2070, +2727, 2489, 2159, +2732, 2495, 2242, +2745, 2509, 2352, +2763, 2528, 2453, +2772, 2539, 2499, +2772, 2539, 2499, +2772, 2539, 2499, +2772, 2539, 2499, +2772, 2539, 2499, +2772, 2539, 2499, +2772, 2539, 2499, +2772, 2539, 2499, +2772, 2539, 2499, +2772, 2539, 2499, +2811, 2738, 2425, +2811, 2738, 2425, +2811, 2738, 2426, +2811, 2738, 2426, +2811, 2738, 2426, +2811, 2738, 2426, +2811, 2738, 2427, +2811, 2738, 2427, +2811, 2739, 2428, +2811, 2739, 2430, +2811, 2739, 2431, +2811, 2740, 2434, +2811, 2740, 2437, +2811, 2740, 2440, +2810, 2740, 2444, +2810, 2740, 2448, +2811, 2742, 2464, +2810, 2743, 2483, +2810, 2745, 2522, +2810, 2748, 2564, +2811, 2752, 2623, +2810, 2762, 2701, +2813, 2763, 2731, +2813, 2763, 2731, +2813, 2763, 2731, +2813, 2763, 2731, +2813, 2763, 2731, +2813, 2763, 2731, +2813, 2763, 2731, +2813, 2763, 2731, +2813, 2763, 2731, +2813, 2763, 2731, +2820, 2813, 2591, +2820, 2813, 2591, +2820, 2813, 2591, +2820, 2813, 2591, +2820, 2813, 2590, +2820, 2813, 2590, +2820, 2813, 2589, +2820, 2812, 2589, +2820, 2813, 2590, +2820, 2813, 2591, +2820, 2813, 2592, +2820, 2813, 2593, +2820, 2814, 2596, +2819, 2814, 2598, +2818, 2813, 2599, +2820, 2813, 2604, +2822, 2813, 2612, +2820, 2813, 2623, +2820, 2815, 2643, +2818, 2815, 2670, +2818, 2817, 2713, +2813, 2819, 2768, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2820, 2813, 2591, +2820, 2813, 2591, +2820, 2813, 2591, +2820, 2813, 2591, +2820, 2813, 2590, +2820, 2813, 2590, +2820, 2813, 2589, +2820, 2812, 2589, +2820, 2813, 2590, +2820, 2813, 2591, +2820, 2813, 2592, +2820, 2813, 2593, +2820, 2814, 2596, +2819, 2814, 2598, +2818, 2813, 2599, +2820, 2813, 2604, +2822, 2813, 2612, +2820, 2813, 2623, +2820, 2815, 2643, +2818, 2815, 2670, +2818, 2817, 2713, +2813, 2819, 2768, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2820, 2813, 2591, +2820, 2813, 2591, +2820, 2813, 2591, +2820, 2813, 2591, +2820, 2813, 2590, +2820, 2813, 2590, +2820, 2813, 2589, +2820, 2812, 2589, +2820, 2813, 2590, +2820, 2813, 2591, +2820, 2813, 2592, +2820, 2813, 2593, +2820, 2814, 2596, +2819, 2814, 2598, +2818, 2813, 2599, +2820, 2813, 2604, +2822, 2813, 2612, +2820, 2813, 2623, +2820, 2815, 2643, +2818, 2815, 2670, +2818, 2817, 2713, +2813, 2819, 2768, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2820, 2813, 2591, +2820, 2813, 2591, +2820, 2813, 2591, +2820, 2813, 2591, +2820, 2813, 2590, +2820, 2813, 2590, +2820, 2813, 2589, +2820, 2812, 2589, +2820, 2813, 2590, +2820, 2813, 2591, +2820, 2813, 2592, +2820, 2813, 2593, +2820, 2814, 2596, +2819, 2814, 2598, +2818, 2813, 2599, +2820, 2813, 2604, +2822, 2813, 2612, +2820, 2813, 2623, +2820, 2815, 2643, +2818, 2815, 2670, +2818, 2817, 2713, +2813, 2819, 2768, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2820, 2813, 2591, +2820, 2813, 2591, +2820, 2813, 2591, +2820, 2813, 2591, +2820, 2813, 2590, +2820, 2813, 2590, +2820, 2813, 2589, +2820, 2812, 2589, +2820, 2813, 2590, +2820, 2813, 2591, +2820, 2813, 2592, +2820, 2813, 2593, +2820, 2814, 2596, +2819, 2814, 2598, +2818, 2813, 2599, +2820, 2813, 2604, +2822, 2813, 2612, +2820, 2813, 2623, +2820, 2815, 2643, +2818, 2815, 2670, +2818, 2817, 2713, +2813, 2819, 2768, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2820, 2813, 2591, +2820, 2813, 2591, +2820, 2813, 2591, +2820, 2813, 2591, +2820, 2813, 2590, +2820, 2813, 2590, +2820, 2813, 2589, +2820, 2812, 2589, +2820, 2813, 2590, +2820, 2813, 2591, +2820, 2813, 2592, +2820, 2813, 2593, +2820, 2814, 2596, +2819, 2814, 2598, +2818, 2813, 2599, +2820, 2813, 2604, +2822, 2813, 2612, +2820, 2813, 2623, +2820, 2815, 2643, +2818, 2815, 2670, +2818, 2817, 2713, +2813, 2819, 2768, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2820, 2813, 2591, +2820, 2813, 2591, +2820, 2813, 2591, +2820, 2813, 2591, +2820, 2813, 2590, +2820, 2813, 2590, +2820, 2813, 2589, +2820, 2812, 2589, +2820, 2813, 2590, +2820, 2813, 2591, +2820, 2813, 2592, +2820, 2813, 2593, +2820, 2814, 2596, +2819, 2814, 2598, +2818, 2813, 2599, +2820, 2813, 2604, +2822, 2813, 2612, +2820, 2813, 2623, +2820, 2815, 2643, +2818, 2815, 2670, +2818, 2817, 2713, +2813, 2819, 2768, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2820, 2813, 2591, +2820, 2813, 2591, +2820, 2813, 2591, +2820, 2813, 2591, +2820, 2813, 2590, +2820, 2813, 2590, +2820, 2813, 2589, +2820, 2812, 2589, +2820, 2813, 2590, +2820, 2813, 2591, +2820, 2813, 2592, +2820, 2813, 2593, +2820, 2814, 2596, +2819, 2814, 2598, +2818, 2813, 2599, +2820, 2813, 2604, +2822, 2813, 2612, +2820, 2813, 2623, +2820, 2815, 2643, +2818, 2815, 2670, +2818, 2817, 2713, +2813, 2819, 2768, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2820, 2813, 2591, +2820, 2813, 2591, +2820, 2813, 2591, +2820, 2813, 2591, +2820, 2813, 2590, +2820, 2813, 2590, +2820, 2813, 2589, +2820, 2812, 2589, +2820, 2813, 2590, +2820, 2813, 2591, +2820, 2813, 2592, +2820, 2813, 2593, +2820, 2814, 2596, +2819, 2814, 2598, +2818, 2813, 2599, +2820, 2813, 2604, +2822, 2813, 2612, +2820, 2813, 2623, +2820, 2815, 2643, +2818, 2815, 2670, +2818, 2817, 2713, +2813, 2819, 2768, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2820, 2813, 2591, +2820, 2813, 2591, +2820, 2813, 2591, +2820, 2813, 2591, +2820, 2813, 2590, +2820, 2813, 2590, +2820, 2813, 2589, +2820, 2812, 2589, +2820, 2813, 2590, +2820, 2813, 2591, +2820, 2813, 2592, +2820, 2813, 2593, +2820, 2814, 2596, +2819, 2814, 2598, +2818, 2813, 2599, +2820, 2813, 2604, +2822, 2813, 2612, +2820, 2813, 2623, +2820, 2815, 2643, +2818, 2815, 2670, +2818, 2817, 2713, +2813, 2819, 2768, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2554, 1623, 2059, +2554, 1623, 2059, +2554, 1623, 2060, +2554, 1623, 2060, +2554, 1623, 2061, +2554, 1623, 2063, +2554, 1623, 2065, +2554, 1623, 2067, +2554, 1623, 2070, +2554, 1623, 2074, +2554, 1623, 2080, +2554, 1623, 2087, +2554, 1621, 2096, +2554, 1621, 2102, +2554, 1621, 2110, +2555, 1588, 2133, +2556, 1555, 2169, +2555, 1608, 2217, +2557, 1691, 2269, +2563, 1692, 2342, +2564, 1761, 2409, +2587, 1838, 2491, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1625, 2059, +2554, 1624, 2059, +2554, 1624, 2060, +2554, 1624, 2060, +2554, 1624, 2061, +2554, 1624, 2063, +2554, 1624, 2064, +2554, 1624, 2067, +2554, 1624, 2070, +2554, 1624, 2074, +2554, 1624, 2080, +2554, 1624, 2087, +2554, 1621, 2096, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1590, 2134, +2556, 1556, 2169, +2555, 1609, 2217, +2557, 1691, 2269, +2563, 1692, 2342, +2564, 1762, 2409, +2587, 1839, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1627, 2059, +2554, 1626, 2059, +2554, 1625, 2060, +2554, 1625, 2060, +2554, 1625, 2061, +2554, 1625, 2063, +2554, 1625, 2064, +2554, 1625, 2067, +2554, 1625, 2070, +2554, 1625, 2074, +2554, 1625, 2079, +2554, 1625, 2086, +2554, 1622, 2096, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1592, 2134, +2556, 1559, 2169, +2555, 1610, 2217, +2557, 1691, 2269, +2564, 1693, 2342, +2564, 1764, 2409, +2587, 1840, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1630, 2060, +2554, 1629, 2060, +2554, 1627, 2060, +2554, 1625, 2060, +2554, 1625, 2061, +2554, 1625, 2062, +2554, 1625, 2064, +2554, 1625, 2066, +2554, 1625, 2070, +2554, 1625, 2074, +2554, 1625, 2079, +2554, 1625, 2086, +2554, 1623, 2095, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1595, 2134, +2556, 1562, 2169, +2555, 1611, 2217, +2557, 1691, 2270, +2564, 1694, 2342, +2564, 1765, 2409, +2587, 1842, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1633, 2060, +2554, 1632, 2060, +2554, 1631, 2060, +2554, 1629, 2060, +2554, 1626, 2061, +2554, 1626, 2062, +2554, 1626, 2064, +2554, 1626, 2066, +2554, 1626, 2069, +2554, 1626, 2073, +2554, 1626, 2079, +2554, 1626, 2086, +2554, 1625, 2095, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1599, 2135, +2556, 1567, 2169, +2555, 1613, 2217, +2557, 1692, 2270, +2564, 1695, 2342, +2565, 1768, 2409, +2587, 1844, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1638, 2061, +2554, 1638, 2061, +2554, 1636, 2061, +2554, 1634, 2061, +2554, 1631, 2061, +2554, 1628, 2062, +2554, 1628, 2063, +2554, 1628, 2066, +2554, 1628, 2069, +2554, 1628, 2073, +2554, 1628, 2079, +2554, 1628, 2086, +2554, 1626, 2095, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1605, 2135, +2556, 1572, 2169, +2555, 1616, 2217, +2557, 1693, 2270, +2564, 1696, 2342, +2565, 1771, 2409, +2587, 1847, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2555, 1645, 2062, +2555, 1644, 2062, +2555, 1643, 2062, +2555, 1641, 2062, +2555, 1638, 2062, +2555, 1635, 2063, +2555, 1631, 2063, +2555, 1631, 2066, +2555, 1631, 2069, +2555, 1631, 2073, +2555, 1631, 2078, +2555, 1631, 2085, +2555, 1628, 2094, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1612, 2136, +2556, 1580, 2169, +2554, 1619, 2217, +2558, 1694, 2270, +2564, 1698, 2342, +2565, 1775, 2409, +2587, 1852, 2492, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2555, 1654, 2063, +2555, 1653, 2063, +2555, 1651, 2063, +2555, 1650, 2063, +2555, 1647, 2063, +2555, 1644, 2064, +2555, 1640, 2064, +2555, 1633, 2065, +2555, 1633, 2068, +2555, 1633, 2072, +2555, 1633, 2078, +2555, 1633, 2085, +2555, 1631, 2094, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1621, 2137, +2557, 1590, 2169, +2554, 1624, 2217, +2558, 1695, 2270, +2564, 1701, 2342, +2565, 1781, 2409, +2588, 1857, 2493, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2556, 1665, 2064, +2556, 1664, 2065, +2556, 1663, 2065, +2556, 1661, 2065, +2556, 1659, 2065, +2556, 1655, 2066, +2556, 1651, 2066, +2556, 1646, 2066, +2556, 1638, 2067, +2556, 1638, 2071, +2556, 1638, 2077, +2556, 1638, 2084, +2556, 1636, 2093, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1633, 2138, +2557, 1603, 2169, +2554, 1630, 2217, +2558, 1697, 2271, +2564, 1704, 2342, +2565, 1788, 2409, +2588, 1860, 2493, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2556, 1680, 2066, +2556, 1679, 2067, +2556, 1678, 2067, +2556, 1676, 2067, +2556, 1674, 2067, +2556, 1671, 2068, +2556, 1667, 2068, +2556, 1661, 2069, +2556, 1653, 2069, +2556, 1643, 2070, +2556, 1643, 2076, +2556, 1643, 2083, +2556, 1641, 2092, +2554, 1624, 2101, +2554, 1621, 2110, +2557, 1649, 2140, +2557, 1620, 2170, +2554, 1638, 2217, +2558, 1699, 2271, +2565, 1709, 2342, +2566, 1798, 2409, +2589, 1863, 2493, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2558, 1699, 2069, +2558, 1698, 2069, +2558, 1697, 2070, +2558, 1695, 2070, +2558, 1693, 2070, +2558, 1690, 2070, +2558, 1686, 2071, +2558, 1681, 2071, +2558, 1674, 2072, +2558, 1663, 2073, +2558, 1650, 2074, +2558, 1650, 2082, +2557, 1648, 2091, +2555, 1631, 2100, +2554, 1621, 2110, +2557, 1657, 2141, +2558, 1642, 2173, +2554, 1658, 2217, +2559, 1702, 2273, +2565, 1715, 2342, +2566, 1810, 2409, +2589, 1868, 2493, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2559, 1723, 2073, +2559, 1723, 2073, +2559, 1722, 2073, +2559, 1720, 2073, +2559, 1718, 2074, +2559, 1715, 2074, +2559, 1711, 2074, +2559, 1706, 2075, +2559, 1699, 2076, +2559, 1690, 2077, +2559, 1677, 2078, +2559, 1659, 2080, +2558, 1657, 2089, +2556, 1641, 2098, +2554, 1621, 2110, +2557, 1657, 2141, +2558, 1669, 2176, +2555, 1684, 2217, +2560, 1706, 2274, +2566, 1723, 2342, +2567, 1816, 2409, +2591, 1873, 2493, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2560, 1754, 2078, +2560, 1754, 2078, +2560, 1753, 2078, +2560, 1752, 2079, +2560, 1750, 2079, +2560, 1747, 2079, +2560, 1744, 2080, +2560, 1739, 2080, +2560, 1732, 2081, +2560, 1724, 2082, +2560, 1712, 2083, +2560, 1695, 2085, +2560, 1674, 2088, +2558, 1658, 2097, +2555, 1635, 2110, +2557, 1661, 2141, +2559, 1703, 2179, +2556, 1716, 2217, +2560, 1716, 2275, +2566, 1739, 2342, +2568, 1818, 2408, +2592, 1880, 2493, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2562, 1761, 2078, +2562, 1761, 2078, +2562, 1761, 2079, +2562, 1762, 2080, +2562, 1763, 2080, +2562, 1765, 2082, +2562, 1766, 2084, +2562, 1769, 2086, +2562, 1772, 2089, +2563, 1771, 2091, +2563, 1760, 2093, +2563, 1745, 2094, +2562, 1727, 2097, +2561, 1712, 2103, +2558, 1692, 2116, +2556, 1693, 2138, +2560, 1738, 2181, +2560, 1744, 2217, +2561, 1744, 2275, +2566, 1785, 2340, +2571, 1835, 2406, +2592, 1893, 2492, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2563, 1769, 2078, +2563, 1769, 2078, +2563, 1770, 2079, +2563, 1771, 2080, +2563, 1772, 2080, +2563, 1773, 2082, +2564, 1775, 2084, +2564, 1777, 2086, +2564, 1780, 2089, +2564, 1784, 2093, +2565, 1789, 2098, +2565, 1796, 2105, +2566, 1789, 2110, +2564, 1776, 2116, +2563, 1758, 2124, +2559, 1753, 2143, +2558, 1773, 2177, +2563, 1787, 2220, +2563, 1779, 2275, +2566, 1840, 2337, +2576, 1860, 2406, +2591, 1925, 2491, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2566, 1822, 2077, +2566, 1822, 2078, +2566, 1822, 2078, +2566, 1822, 2078, +2566, 1822, 2079, +2566, 1822, 2079, +2566, 1822, 2080, +2566, 1822, 2081, +2566, 1822, 2083, +2566, 1822, 2085, +2567, 1824, 2089, +2568, 1831, 2096, +2568, 1839, 2106, +2570, 1844, 2121, +2568, 1834, 2131, +2568, 1813, 2145, +2564, 1813, 2176, +2565, 1838, 2221, +2568, 1838, 2272, +2573, 1888, 2337, +2580, 1896, 2406, +2599, 1967, 2492, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2573, 1894, 2080, +2573, 1894, 2081, +2573, 1895, 2081, +2573, 1896, 2081, +2573, 1897, 2082, +2574, 1898, 2082, +2574, 1900, 2083, +2575, 1903, 2084, +2575, 1906, 2086, +2575, 1906, 2088, +2575, 1906, 2090, +2575, 1906, 2094, +2575, 1906, 2099, +2575, 1907, 2109, +2576, 1913, 2129, +2577, 1915, 2152, +2578, 1893, 2171, +2576, 1899, 2221, +2578, 1919, 2273, +2580, 1949, 2338, +2587, 1961, 2408, +2611, 2008, 2495, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2588, 1996, 2083, +2588, 1997, 2083, +2588, 1997, 2084, +2588, 1997, 2085, +2588, 1997, 2086, +2588, 1998, 2087, +2588, 1998, 2088, +2588, 1999, 2091, +2588, 2000, 2093, +2588, 2001, 2098, +2588, 2005, 2100, +2589, 2012, 2104, +2591, 2018, 2108, +2588, 2010, 2114, +2588, 2009, 2126, +2589, 2014, 2149, +2590, 2016, 2184, +2591, 2003, 2214, +2591, 2019, 2275, +2595, 2044, 2342, +2604, 2072, 2411, +2625, 2108, 2494, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2625, 2149, 2111, +2624, 2149, 2111, +2624, 2149, 2111, +2624, 2149, 2111, +2624, 2148, 2111, +2624, 2148, 2111, +2623, 2147, 2111, +2623, 2146, 2111, +2622, 2145, 2111, +2621, 2143, 2111, +2620, 2141, 2111, +2618, 2137, 2111, +2617, 2136, 2114, +2617, 2144, 2126, +2617, 2155, 2141, +2619, 2157, 2164, +2623, 2160, 2195, +2624, 2165, 2231, +2619, 2165, 2275, +2633, 2187, 2352, +2638, 2190, 2417, +2660, 2223, 2503, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2670, 2315, 2112, +2671, 2315, 2112, +2671, 2315, 2112, +2671, 2315, 2111, +2671, 2316, 2111, +2672, 2316, 2111, +2672, 2316, 2111, +2673, 2317, 2110, +2674, 2318, 2109, +2675, 2319, 2108, +2677, 2321, 2107, +2680, 2323, 2105, +2682, 2325, 2106, +2681, 2325, 2118, +2680, 2325, 2133, +2678, 2328, 2149, +2677, 2328, 2176, +2677, 2325, 2215, +2687, 2335, 2275, +2689, 2335, 2316, +2695, 2346, 2391, +2724, 2369, 2462, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2775, 2531, 1744, +2775, 2531, 1745, +2775, 2531, 1747, +2775, 2531, 1750, +2776, 2532, 1753, +2776, 2532, 1758, +2776, 2533, 1764, +2776, 2533, 1772, +2777, 2534, 1782, +2778, 2535, 1796, +2778, 2536, 1813, +2778, 2537, 1825, +2777, 2535, 1833, +2776, 2530, 1839, +2776, 2528, 1859, +2778, 2535, 1929, +2779, 2534, 1991, +2780, 2535, 2071, +2782, 2538, 2158, +2784, 2536, 2248, +2791, 2552, 2360, +2803, 2569, 2485, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2826, 2762, 2506, +2826, 2762, 2506, +2826, 2762, 2505, +2826, 2762, 2505, +2826, 2762, 2505, +2826, 2762, 2505, +2826, 2761, 2505, +2826, 2761, 2505, +2826, 2761, 2505, +2826, 2761, 2506, +2826, 2761, 2507, +2826, 2761, 2509, +2826, 2761, 2510, +2826, 2760, 2508, +2826, 2760, 2508, +2826, 2762, 2520, +2826, 2764, 2535, +2826, 2763, 2548, +2826, 2763, 2571, +2826, 2767, 2613, +2826, 2769, 2662, +2826, 2779, 2732, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2554, 1623, 2059, +2554, 1623, 2059, +2554, 1623, 2060, +2554, 1623, 2060, +2554, 1623, 2061, +2554, 1623, 2063, +2554, 1623, 2065, +2554, 1623, 2067, +2554, 1623, 2070, +2554, 1623, 2074, +2554, 1623, 2080, +2554, 1623, 2087, +2554, 1621, 2096, +2554, 1621, 2102, +2554, 1621, 2110, +2555, 1588, 2133, +2556, 1555, 2169, +2555, 1608, 2217, +2557, 1691, 2269, +2563, 1692, 2342, +2564, 1761, 2409, +2587, 1838, 2491, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1625, 2059, +2554, 1624, 2059, +2554, 1624, 2060, +2554, 1624, 2060, +2554, 1624, 2061, +2554, 1624, 2063, +2554, 1624, 2064, +2554, 1624, 2067, +2554, 1624, 2070, +2554, 1624, 2074, +2554, 1624, 2080, +2554, 1624, 2087, +2554, 1621, 2096, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1590, 2134, +2556, 1556, 2169, +2555, 1609, 2217, +2557, 1691, 2269, +2563, 1692, 2342, +2564, 1762, 2409, +2587, 1839, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1627, 2059, +2554, 1626, 2059, +2554, 1625, 2060, +2554, 1625, 2060, +2554, 1625, 2061, +2554, 1625, 2063, +2554, 1625, 2064, +2554, 1625, 2067, +2554, 1625, 2070, +2554, 1625, 2074, +2554, 1625, 2079, +2554, 1625, 2086, +2554, 1622, 2096, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1592, 2134, +2556, 1559, 2169, +2555, 1610, 2217, +2557, 1691, 2269, +2564, 1693, 2342, +2564, 1764, 2409, +2587, 1840, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1630, 2060, +2554, 1629, 2060, +2554, 1627, 2060, +2554, 1625, 2060, +2554, 1625, 2061, +2554, 1625, 2062, +2554, 1625, 2064, +2554, 1625, 2066, +2554, 1625, 2070, +2554, 1625, 2074, +2554, 1625, 2079, +2554, 1625, 2086, +2554, 1623, 2095, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1595, 2134, +2556, 1562, 2169, +2555, 1611, 2217, +2557, 1691, 2270, +2564, 1694, 2342, +2564, 1765, 2409, +2587, 1842, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1633, 2060, +2554, 1632, 2060, +2554, 1631, 2060, +2554, 1629, 2060, +2554, 1626, 2061, +2554, 1626, 2062, +2554, 1626, 2064, +2554, 1626, 2066, +2554, 1626, 2069, +2554, 1626, 2073, +2554, 1626, 2079, +2554, 1626, 2086, +2554, 1625, 2095, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1599, 2135, +2556, 1567, 2169, +2555, 1613, 2217, +2557, 1692, 2270, +2564, 1695, 2342, +2565, 1768, 2409, +2587, 1844, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1638, 2061, +2554, 1638, 2061, +2554, 1636, 2061, +2554, 1634, 2061, +2554, 1631, 2061, +2554, 1628, 2062, +2554, 1628, 2063, +2554, 1628, 2066, +2554, 1628, 2069, +2554, 1628, 2073, +2554, 1628, 2079, +2554, 1628, 2086, +2554, 1626, 2095, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1605, 2135, +2556, 1572, 2169, +2555, 1616, 2217, +2557, 1693, 2270, +2564, 1696, 2342, +2565, 1771, 2409, +2587, 1847, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2555, 1645, 2062, +2555, 1644, 2062, +2555, 1643, 2062, +2555, 1641, 2062, +2555, 1638, 2062, +2555, 1635, 2063, +2555, 1631, 2063, +2555, 1631, 2066, +2555, 1631, 2069, +2555, 1631, 2073, +2555, 1631, 2078, +2555, 1631, 2085, +2555, 1628, 2094, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1612, 2136, +2556, 1580, 2169, +2554, 1619, 2217, +2558, 1694, 2270, +2564, 1698, 2342, +2565, 1775, 2409, +2587, 1852, 2492, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2555, 1654, 2063, +2555, 1653, 2063, +2555, 1651, 2063, +2555, 1650, 2063, +2555, 1647, 2063, +2555, 1644, 2064, +2555, 1640, 2064, +2555, 1633, 2065, +2555, 1633, 2068, +2555, 1633, 2072, +2555, 1633, 2078, +2555, 1633, 2085, +2555, 1631, 2094, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1621, 2137, +2557, 1590, 2169, +2554, 1624, 2217, +2558, 1695, 2270, +2564, 1701, 2342, +2565, 1781, 2409, +2588, 1857, 2493, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2556, 1665, 2064, +2556, 1664, 2065, +2556, 1663, 2065, +2556, 1661, 2065, +2556, 1659, 2065, +2556, 1655, 2066, +2556, 1651, 2066, +2556, 1646, 2066, +2556, 1638, 2067, +2556, 1638, 2071, +2556, 1638, 2077, +2556, 1638, 2084, +2556, 1636, 2093, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1633, 2138, +2557, 1603, 2169, +2554, 1630, 2217, +2558, 1697, 2271, +2564, 1704, 2342, +2565, 1788, 2409, +2588, 1860, 2493, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2556, 1680, 2066, +2556, 1679, 2067, +2556, 1678, 2067, +2556, 1676, 2067, +2556, 1674, 2067, +2556, 1671, 2068, +2556, 1667, 2068, +2556, 1661, 2069, +2556, 1653, 2069, +2556, 1643, 2070, +2556, 1643, 2076, +2556, 1643, 2083, +2556, 1641, 2092, +2554, 1624, 2101, +2554, 1621, 2110, +2557, 1649, 2140, +2557, 1620, 2170, +2554, 1638, 2217, +2558, 1699, 2271, +2565, 1709, 2342, +2566, 1798, 2409, +2589, 1863, 2493, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2558, 1699, 2069, +2558, 1698, 2069, +2558, 1697, 2070, +2558, 1695, 2070, +2558, 1693, 2070, +2558, 1690, 2070, +2558, 1686, 2071, +2558, 1681, 2071, +2558, 1674, 2072, +2558, 1663, 2073, +2558, 1650, 2074, +2558, 1650, 2082, +2557, 1648, 2091, +2555, 1631, 2100, +2554, 1621, 2110, +2557, 1657, 2141, +2558, 1642, 2173, +2554, 1658, 2217, +2559, 1702, 2273, +2565, 1715, 2342, +2566, 1810, 2409, +2589, 1868, 2493, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2559, 1723, 2073, +2559, 1723, 2073, +2559, 1722, 2073, +2559, 1720, 2073, +2559, 1718, 2074, +2559, 1715, 2074, +2559, 1711, 2074, +2559, 1706, 2075, +2559, 1699, 2076, +2559, 1690, 2077, +2559, 1677, 2078, +2559, 1659, 2080, +2558, 1657, 2089, +2556, 1641, 2098, +2554, 1621, 2110, +2557, 1657, 2141, +2558, 1669, 2176, +2555, 1684, 2217, +2560, 1706, 2274, +2566, 1723, 2342, +2567, 1816, 2409, +2591, 1873, 2493, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2560, 1754, 2078, +2560, 1754, 2078, +2560, 1753, 2078, +2560, 1752, 2079, +2560, 1750, 2079, +2560, 1747, 2079, +2560, 1744, 2080, +2560, 1739, 2080, +2560, 1732, 2081, +2560, 1724, 2082, +2560, 1712, 2083, +2560, 1695, 2085, +2560, 1674, 2088, +2558, 1658, 2097, +2555, 1635, 2110, +2557, 1661, 2141, +2559, 1703, 2179, +2556, 1716, 2217, +2560, 1716, 2275, +2566, 1739, 2342, +2568, 1818, 2408, +2592, 1880, 2493, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2562, 1761, 2078, +2562, 1761, 2078, +2562, 1761, 2079, +2562, 1762, 2080, +2562, 1763, 2080, +2562, 1765, 2082, +2562, 1766, 2084, +2562, 1769, 2086, +2562, 1772, 2089, +2563, 1771, 2091, +2563, 1760, 2093, +2563, 1745, 2094, +2562, 1727, 2097, +2561, 1712, 2103, +2558, 1692, 2116, +2556, 1693, 2138, +2560, 1738, 2181, +2560, 1744, 2217, +2561, 1744, 2275, +2566, 1785, 2340, +2571, 1835, 2406, +2592, 1893, 2492, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2563, 1769, 2078, +2563, 1769, 2078, +2563, 1770, 2079, +2563, 1771, 2080, +2563, 1772, 2080, +2563, 1773, 2082, +2564, 1775, 2084, +2564, 1777, 2086, +2564, 1780, 2089, +2564, 1784, 2093, +2565, 1789, 2098, +2565, 1796, 2105, +2566, 1789, 2110, +2564, 1776, 2116, +2563, 1758, 2124, +2559, 1753, 2143, +2558, 1773, 2177, +2563, 1787, 2220, +2563, 1779, 2275, +2566, 1840, 2337, +2576, 1860, 2406, +2591, 1925, 2491, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2566, 1822, 2077, +2566, 1822, 2078, +2566, 1822, 2078, +2566, 1822, 2078, +2566, 1822, 2079, +2566, 1822, 2079, +2566, 1822, 2080, +2566, 1822, 2081, +2566, 1822, 2083, +2566, 1822, 2085, +2567, 1824, 2089, +2568, 1831, 2096, +2568, 1839, 2106, +2570, 1844, 2121, +2568, 1834, 2131, +2568, 1813, 2145, +2564, 1813, 2176, +2565, 1838, 2221, +2568, 1838, 2272, +2573, 1888, 2337, +2580, 1896, 2406, +2599, 1967, 2492, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2573, 1894, 2080, +2573, 1894, 2081, +2573, 1895, 2081, +2573, 1896, 2081, +2573, 1897, 2082, +2574, 1898, 2082, +2574, 1900, 2083, +2575, 1903, 2084, +2575, 1906, 2086, +2575, 1906, 2088, +2575, 1906, 2090, +2575, 1906, 2094, +2575, 1906, 2099, +2575, 1907, 2109, +2576, 1913, 2129, +2577, 1915, 2152, +2578, 1893, 2171, +2576, 1899, 2221, +2578, 1919, 2273, +2580, 1949, 2338, +2587, 1961, 2408, +2611, 2008, 2495, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2588, 1996, 2083, +2588, 1997, 2083, +2588, 1997, 2084, +2588, 1997, 2085, +2588, 1997, 2086, +2588, 1998, 2087, +2588, 1998, 2088, +2588, 1999, 2091, +2588, 2000, 2093, +2588, 2001, 2098, +2588, 2005, 2100, +2589, 2012, 2104, +2591, 2018, 2108, +2588, 2010, 2114, +2588, 2009, 2126, +2589, 2014, 2149, +2590, 2016, 2184, +2591, 2003, 2214, +2591, 2019, 2275, +2595, 2044, 2342, +2604, 2072, 2411, +2625, 2108, 2494, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2625, 2149, 2111, +2624, 2149, 2111, +2624, 2149, 2111, +2624, 2149, 2111, +2624, 2148, 2111, +2624, 2148, 2111, +2623, 2147, 2111, +2623, 2146, 2111, +2622, 2145, 2111, +2621, 2143, 2111, +2620, 2141, 2111, +2618, 2137, 2111, +2617, 2136, 2114, +2617, 2144, 2126, +2617, 2155, 2141, +2619, 2157, 2164, +2623, 2160, 2195, +2624, 2165, 2231, +2619, 2165, 2275, +2633, 2187, 2352, +2638, 2190, 2417, +2660, 2223, 2503, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2670, 2315, 2112, +2671, 2315, 2112, +2671, 2315, 2112, +2671, 2315, 2111, +2671, 2316, 2111, +2672, 2316, 2111, +2672, 2316, 2111, +2673, 2317, 2110, +2674, 2318, 2109, +2675, 2319, 2108, +2677, 2321, 2107, +2680, 2323, 2105, +2682, 2325, 2106, +2681, 2325, 2118, +2680, 2325, 2133, +2678, 2328, 2149, +2677, 2328, 2176, +2677, 2325, 2215, +2687, 2335, 2275, +2689, 2335, 2316, +2695, 2346, 2391, +2724, 2369, 2462, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2775, 2531, 1744, +2775, 2531, 1745, +2775, 2531, 1747, +2775, 2531, 1750, +2776, 2532, 1753, +2776, 2532, 1758, +2776, 2533, 1764, +2776, 2533, 1772, +2777, 2534, 1782, +2778, 2535, 1796, +2778, 2536, 1813, +2778, 2537, 1825, +2777, 2535, 1833, +2776, 2530, 1839, +2776, 2528, 1859, +2778, 2535, 1929, +2779, 2534, 1991, +2780, 2535, 2071, +2782, 2538, 2158, +2784, 2536, 2248, +2791, 2552, 2360, +2803, 2569, 2485, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2826, 2762, 2506, +2826, 2762, 2506, +2826, 2762, 2505, +2826, 2762, 2505, +2826, 2762, 2505, +2826, 2762, 2505, +2826, 2761, 2505, +2826, 2761, 2505, +2826, 2761, 2505, +2826, 2761, 2506, +2826, 2761, 2507, +2826, 2761, 2509, +2826, 2761, 2510, +2826, 2760, 2508, +2826, 2760, 2508, +2826, 2762, 2520, +2826, 2764, 2535, +2826, 2763, 2548, +2826, 2763, 2571, +2826, 2767, 2613, +2826, 2769, 2662, +2826, 2779, 2732, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2554, 1623, 2059, +2554, 1623, 2059, +2554, 1623, 2060, +2554, 1623, 2060, +2554, 1623, 2061, +2554, 1623, 2063, +2554, 1623, 2065, +2554, 1623, 2067, +2554, 1623, 2070, +2554, 1623, 2074, +2554, 1623, 2080, +2554, 1623, 2087, +2554, 1621, 2096, +2554, 1621, 2102, +2554, 1621, 2110, +2555, 1588, 2133, +2556, 1555, 2169, +2555, 1608, 2217, +2557, 1691, 2269, +2563, 1692, 2342, +2564, 1761, 2409, +2587, 1838, 2491, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1625, 2059, +2554, 1624, 2059, +2554, 1624, 2060, +2554, 1624, 2060, +2554, 1624, 2061, +2554, 1624, 2063, +2554, 1624, 2064, +2554, 1624, 2067, +2554, 1624, 2070, +2554, 1624, 2074, +2554, 1624, 2080, +2554, 1624, 2087, +2554, 1621, 2096, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1590, 2134, +2556, 1556, 2169, +2555, 1609, 2217, +2557, 1691, 2269, +2563, 1692, 2342, +2564, 1762, 2409, +2587, 1839, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1627, 2059, +2554, 1626, 2059, +2554, 1625, 2060, +2554, 1625, 2060, +2554, 1625, 2061, +2554, 1625, 2063, +2554, 1625, 2064, +2554, 1625, 2067, +2554, 1625, 2070, +2554, 1625, 2074, +2554, 1625, 2079, +2554, 1625, 2086, +2554, 1622, 2096, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1592, 2134, +2556, 1559, 2169, +2555, 1610, 2217, +2557, 1691, 2269, +2564, 1693, 2342, +2564, 1764, 2409, +2587, 1840, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1630, 2060, +2554, 1629, 2060, +2554, 1627, 2060, +2554, 1625, 2060, +2554, 1625, 2061, +2554, 1625, 2062, +2554, 1625, 2064, +2554, 1625, 2066, +2554, 1625, 2070, +2554, 1625, 2074, +2554, 1625, 2079, +2554, 1625, 2086, +2554, 1623, 2095, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1595, 2134, +2556, 1562, 2169, +2555, 1611, 2217, +2557, 1691, 2270, +2564, 1694, 2342, +2564, 1765, 2409, +2587, 1842, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1633, 2060, +2554, 1632, 2060, +2554, 1631, 2060, +2554, 1629, 2060, +2554, 1626, 2061, +2554, 1626, 2062, +2554, 1626, 2064, +2554, 1626, 2066, +2554, 1626, 2069, +2554, 1626, 2073, +2554, 1626, 2079, +2554, 1626, 2086, +2554, 1625, 2095, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1599, 2135, +2556, 1567, 2169, +2555, 1613, 2217, +2557, 1692, 2270, +2564, 1695, 2342, +2565, 1768, 2409, +2587, 1844, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1638, 2061, +2554, 1638, 2061, +2554, 1636, 2061, +2554, 1634, 2061, +2554, 1631, 2061, +2554, 1628, 2062, +2554, 1628, 2063, +2554, 1628, 2066, +2554, 1628, 2069, +2554, 1628, 2073, +2554, 1628, 2079, +2554, 1628, 2086, +2554, 1626, 2095, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1605, 2135, +2556, 1572, 2169, +2555, 1616, 2217, +2557, 1693, 2270, +2564, 1696, 2342, +2565, 1771, 2409, +2587, 1847, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2555, 1645, 2062, +2555, 1644, 2062, +2555, 1643, 2062, +2555, 1641, 2062, +2555, 1638, 2062, +2555, 1635, 2063, +2555, 1631, 2063, +2555, 1631, 2066, +2555, 1631, 2069, +2555, 1631, 2073, +2555, 1631, 2078, +2555, 1631, 2085, +2555, 1628, 2094, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1612, 2136, +2556, 1580, 2169, +2554, 1619, 2217, +2558, 1694, 2270, +2564, 1698, 2342, +2565, 1775, 2409, +2587, 1852, 2492, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2555, 1654, 2063, +2555, 1653, 2063, +2555, 1651, 2063, +2555, 1650, 2063, +2555, 1647, 2063, +2555, 1644, 2064, +2555, 1640, 2064, +2555, 1633, 2065, +2555, 1633, 2068, +2555, 1633, 2072, +2555, 1633, 2078, +2555, 1633, 2085, +2555, 1631, 2094, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1621, 2137, +2557, 1590, 2169, +2554, 1624, 2217, +2558, 1695, 2270, +2564, 1701, 2342, +2565, 1781, 2409, +2588, 1857, 2493, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2556, 1665, 2064, +2556, 1664, 2065, +2556, 1663, 2065, +2556, 1661, 2065, +2556, 1659, 2065, +2556, 1655, 2066, +2556, 1651, 2066, +2556, 1646, 2066, +2556, 1638, 2067, +2556, 1638, 2071, +2556, 1638, 2077, +2556, 1638, 2084, +2556, 1636, 2093, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1633, 2138, +2557, 1603, 2169, +2554, 1630, 2217, +2558, 1697, 2271, +2564, 1704, 2342, +2565, 1788, 2409, +2588, 1860, 2493, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2556, 1680, 2066, +2556, 1679, 2067, +2556, 1678, 2067, +2556, 1676, 2067, +2556, 1674, 2067, +2556, 1671, 2068, +2556, 1667, 2068, +2556, 1661, 2069, +2556, 1653, 2069, +2556, 1643, 2070, +2556, 1643, 2076, +2556, 1643, 2083, +2556, 1641, 2092, +2554, 1624, 2101, +2554, 1621, 2110, +2557, 1649, 2140, +2557, 1620, 2170, +2554, 1638, 2217, +2558, 1699, 2271, +2565, 1709, 2342, +2566, 1798, 2409, +2589, 1863, 2493, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2558, 1699, 2069, +2558, 1698, 2069, +2558, 1697, 2070, +2558, 1695, 2070, +2558, 1693, 2070, +2558, 1690, 2070, +2558, 1686, 2071, +2558, 1681, 2071, +2558, 1674, 2072, +2558, 1663, 2073, +2558, 1650, 2074, +2558, 1650, 2082, +2557, 1648, 2091, +2555, 1631, 2100, +2554, 1621, 2110, +2557, 1657, 2141, +2558, 1642, 2173, +2554, 1658, 2217, +2559, 1702, 2273, +2565, 1715, 2342, +2566, 1810, 2409, +2589, 1868, 2493, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2559, 1723, 2073, +2559, 1723, 2073, +2559, 1722, 2073, +2559, 1720, 2073, +2559, 1718, 2074, +2559, 1715, 2074, +2559, 1711, 2074, +2559, 1706, 2075, +2559, 1699, 2076, +2559, 1690, 2077, +2559, 1677, 2078, +2559, 1659, 2080, +2558, 1657, 2089, +2556, 1641, 2098, +2554, 1621, 2110, +2557, 1657, 2141, +2558, 1669, 2176, +2555, 1684, 2217, +2560, 1706, 2274, +2566, 1723, 2342, +2567, 1816, 2409, +2591, 1873, 2493, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2560, 1754, 2078, +2560, 1754, 2078, +2560, 1753, 2078, +2560, 1752, 2079, +2560, 1750, 2079, +2560, 1747, 2079, +2560, 1744, 2080, +2560, 1739, 2080, +2560, 1732, 2081, +2560, 1724, 2082, +2560, 1712, 2083, +2560, 1695, 2085, +2560, 1674, 2088, +2558, 1658, 2097, +2555, 1635, 2110, +2557, 1661, 2141, +2559, 1703, 2179, +2556, 1716, 2217, +2560, 1716, 2275, +2566, 1739, 2342, +2568, 1818, 2408, +2592, 1880, 2493, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2562, 1761, 2078, +2562, 1761, 2078, +2562, 1761, 2079, +2562, 1762, 2080, +2562, 1763, 2080, +2562, 1765, 2082, +2562, 1766, 2084, +2562, 1769, 2086, +2562, 1772, 2089, +2563, 1771, 2091, +2563, 1760, 2093, +2563, 1745, 2094, +2562, 1727, 2097, +2561, 1712, 2103, +2558, 1692, 2116, +2556, 1693, 2138, +2560, 1738, 2181, +2560, 1744, 2217, +2561, 1744, 2275, +2566, 1785, 2340, +2571, 1835, 2406, +2592, 1893, 2492, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2563, 1769, 2078, +2563, 1769, 2078, +2563, 1770, 2079, +2563, 1771, 2080, +2563, 1772, 2080, +2563, 1773, 2082, +2564, 1775, 2084, +2564, 1777, 2086, +2564, 1780, 2089, +2564, 1784, 2093, +2565, 1789, 2098, +2565, 1796, 2105, +2566, 1789, 2110, +2564, 1776, 2116, +2563, 1758, 2124, +2559, 1753, 2143, +2558, 1773, 2177, +2563, 1787, 2220, +2563, 1779, 2275, +2566, 1840, 2337, +2576, 1860, 2406, +2591, 1925, 2491, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2566, 1822, 2077, +2566, 1822, 2078, +2566, 1822, 2078, +2566, 1822, 2078, +2566, 1822, 2079, +2566, 1822, 2079, +2566, 1822, 2080, +2566, 1822, 2081, +2566, 1822, 2083, +2566, 1822, 2085, +2567, 1824, 2089, +2568, 1831, 2096, +2568, 1839, 2106, +2570, 1844, 2121, +2568, 1834, 2131, +2568, 1813, 2145, +2564, 1813, 2176, +2565, 1838, 2221, +2568, 1838, 2272, +2573, 1888, 2337, +2580, 1896, 2406, +2599, 1967, 2492, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2573, 1894, 2080, +2573, 1894, 2081, +2573, 1895, 2081, +2573, 1896, 2081, +2573, 1897, 2082, +2574, 1898, 2082, +2574, 1900, 2083, +2575, 1903, 2084, +2575, 1906, 2086, +2575, 1906, 2088, +2575, 1906, 2090, +2575, 1906, 2094, +2575, 1906, 2099, +2575, 1907, 2109, +2576, 1913, 2129, +2577, 1915, 2152, +2578, 1893, 2171, +2576, 1899, 2221, +2578, 1919, 2273, +2580, 1949, 2338, +2587, 1961, 2408, +2611, 2008, 2495, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2588, 1996, 2083, +2588, 1997, 2083, +2588, 1997, 2084, +2588, 1997, 2085, +2588, 1997, 2086, +2588, 1998, 2087, +2588, 1998, 2088, +2588, 1999, 2091, +2588, 2000, 2093, +2588, 2001, 2098, +2588, 2005, 2100, +2589, 2012, 2104, +2591, 2018, 2108, +2588, 2010, 2114, +2588, 2009, 2126, +2589, 2014, 2149, +2590, 2016, 2184, +2591, 2003, 2214, +2591, 2019, 2275, +2595, 2044, 2342, +2604, 2072, 2411, +2625, 2108, 2494, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2625, 2149, 2111, +2624, 2149, 2111, +2624, 2149, 2111, +2624, 2149, 2111, +2624, 2148, 2111, +2624, 2148, 2111, +2623, 2147, 2111, +2623, 2146, 2111, +2622, 2145, 2111, +2621, 2143, 2111, +2620, 2141, 2111, +2618, 2137, 2111, +2617, 2136, 2114, +2617, 2144, 2126, +2617, 2155, 2141, +2619, 2157, 2164, +2623, 2160, 2195, +2624, 2165, 2231, +2619, 2165, 2275, +2633, 2187, 2352, +2638, 2190, 2417, +2660, 2223, 2503, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2670, 2315, 2112, +2671, 2315, 2112, +2671, 2315, 2112, +2671, 2315, 2111, +2671, 2316, 2111, +2672, 2316, 2111, +2672, 2316, 2111, +2673, 2317, 2110, +2674, 2318, 2109, +2675, 2319, 2108, +2677, 2321, 2107, +2680, 2323, 2105, +2682, 2325, 2106, +2681, 2325, 2118, +2680, 2325, 2133, +2678, 2328, 2149, +2677, 2328, 2176, +2677, 2325, 2215, +2687, 2335, 2275, +2689, 2335, 2316, +2695, 2346, 2391, +2724, 2369, 2462, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2775, 2531, 1744, +2775, 2531, 1745, +2775, 2531, 1747, +2775, 2531, 1750, +2776, 2532, 1753, +2776, 2532, 1758, +2776, 2533, 1764, +2776, 2533, 1772, +2777, 2534, 1782, +2778, 2535, 1796, +2778, 2536, 1813, +2778, 2537, 1825, +2777, 2535, 1833, +2776, 2530, 1839, +2776, 2528, 1859, +2778, 2535, 1929, +2779, 2534, 1991, +2780, 2535, 2071, +2782, 2538, 2158, +2784, 2536, 2248, +2791, 2552, 2360, +2803, 2569, 2485, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2826, 2762, 2506, +2826, 2762, 2506, +2826, 2762, 2505, +2826, 2762, 2505, +2826, 2762, 2505, +2826, 2762, 2505, +2826, 2761, 2505, +2826, 2761, 2505, +2826, 2761, 2505, +2826, 2761, 2506, +2826, 2761, 2507, +2826, 2761, 2509, +2826, 2761, 2510, +2826, 2760, 2508, +2826, 2760, 2508, +2826, 2762, 2520, +2826, 2764, 2535, +2826, 2763, 2548, +2826, 2763, 2571, +2826, 2767, 2613, +2826, 2769, 2662, +2826, 2779, 2732, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2554, 1623, 2059, +2554, 1623, 2059, +2554, 1623, 2060, +2554, 1623, 2060, +2554, 1623, 2061, +2554, 1623, 2063, +2554, 1623, 2065, +2554, 1623, 2067, +2554, 1623, 2070, +2554, 1623, 2074, +2554, 1623, 2080, +2554, 1623, 2087, +2554, 1621, 2096, +2554, 1621, 2102, +2554, 1621, 2110, +2555, 1588, 2133, +2556, 1555, 2169, +2555, 1608, 2217, +2557, 1691, 2269, +2563, 1692, 2342, +2564, 1761, 2409, +2587, 1838, 2491, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1625, 2059, +2554, 1624, 2059, +2554, 1624, 2060, +2554, 1624, 2060, +2554, 1624, 2061, +2554, 1624, 2063, +2554, 1624, 2064, +2554, 1624, 2067, +2554, 1624, 2070, +2554, 1624, 2074, +2554, 1624, 2080, +2554, 1624, 2087, +2554, 1621, 2096, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1590, 2134, +2556, 1556, 2169, +2555, 1609, 2217, +2557, 1691, 2269, +2563, 1692, 2342, +2564, 1762, 2409, +2587, 1839, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1627, 2059, +2554, 1626, 2059, +2554, 1625, 2060, +2554, 1625, 2060, +2554, 1625, 2061, +2554, 1625, 2063, +2554, 1625, 2064, +2554, 1625, 2067, +2554, 1625, 2070, +2554, 1625, 2074, +2554, 1625, 2079, +2554, 1625, 2086, +2554, 1622, 2096, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1592, 2134, +2556, 1559, 2169, +2555, 1610, 2217, +2557, 1691, 2269, +2564, 1693, 2342, +2564, 1764, 2409, +2587, 1840, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1630, 2060, +2554, 1629, 2060, +2554, 1627, 2060, +2554, 1625, 2060, +2554, 1625, 2061, +2554, 1625, 2062, +2554, 1625, 2064, +2554, 1625, 2066, +2554, 1625, 2070, +2554, 1625, 2074, +2554, 1625, 2079, +2554, 1625, 2086, +2554, 1623, 2095, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1595, 2134, +2556, 1562, 2169, +2555, 1611, 2217, +2557, 1691, 2270, +2564, 1694, 2342, +2564, 1765, 2409, +2587, 1842, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1633, 2060, +2554, 1632, 2060, +2554, 1631, 2060, +2554, 1629, 2060, +2554, 1626, 2061, +2554, 1626, 2062, +2554, 1626, 2064, +2554, 1626, 2066, +2554, 1626, 2069, +2554, 1626, 2073, +2554, 1626, 2079, +2554, 1626, 2086, +2554, 1625, 2095, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1599, 2135, +2556, 1567, 2169, +2555, 1613, 2217, +2557, 1692, 2270, +2564, 1695, 2342, +2565, 1768, 2409, +2587, 1844, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1638, 2061, +2554, 1638, 2061, +2554, 1636, 2061, +2554, 1634, 2061, +2554, 1631, 2061, +2554, 1628, 2062, +2554, 1628, 2063, +2554, 1628, 2066, +2554, 1628, 2069, +2554, 1628, 2073, +2554, 1628, 2079, +2554, 1628, 2086, +2554, 1626, 2095, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1605, 2135, +2556, 1572, 2169, +2555, 1616, 2217, +2557, 1693, 2270, +2564, 1696, 2342, +2565, 1771, 2409, +2587, 1847, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2555, 1645, 2062, +2555, 1644, 2062, +2555, 1643, 2062, +2555, 1641, 2062, +2555, 1638, 2062, +2555, 1635, 2063, +2555, 1631, 2063, +2555, 1631, 2066, +2555, 1631, 2069, +2555, 1631, 2073, +2555, 1631, 2078, +2555, 1631, 2085, +2555, 1628, 2094, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1612, 2136, +2556, 1580, 2169, +2554, 1619, 2217, +2558, 1694, 2270, +2564, 1698, 2342, +2565, 1775, 2409, +2587, 1852, 2492, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2555, 1654, 2063, +2555, 1653, 2063, +2555, 1651, 2063, +2555, 1650, 2063, +2555, 1647, 2063, +2555, 1644, 2064, +2555, 1640, 2064, +2555, 1633, 2065, +2555, 1633, 2068, +2555, 1633, 2072, +2555, 1633, 2078, +2555, 1633, 2085, +2555, 1631, 2094, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1621, 2137, +2557, 1590, 2169, +2554, 1624, 2217, +2558, 1695, 2270, +2564, 1701, 2342, +2565, 1781, 2409, +2588, 1857, 2493, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2556, 1665, 2064, +2556, 1664, 2065, +2556, 1663, 2065, +2556, 1661, 2065, +2556, 1659, 2065, +2556, 1655, 2066, +2556, 1651, 2066, +2556, 1646, 2066, +2556, 1638, 2067, +2556, 1638, 2071, +2556, 1638, 2077, +2556, 1638, 2084, +2556, 1636, 2093, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1633, 2138, +2557, 1603, 2169, +2554, 1630, 2217, +2558, 1697, 2271, +2564, 1704, 2342, +2565, 1788, 2409, +2588, 1860, 2493, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2556, 1680, 2066, +2556, 1679, 2067, +2556, 1678, 2067, +2556, 1676, 2067, +2556, 1674, 2067, +2556, 1671, 2068, +2556, 1667, 2068, +2556, 1661, 2069, +2556, 1653, 2069, +2556, 1643, 2070, +2556, 1643, 2076, +2556, 1643, 2083, +2556, 1641, 2092, +2554, 1624, 2101, +2554, 1621, 2110, +2557, 1649, 2140, +2557, 1620, 2170, +2554, 1638, 2217, +2558, 1699, 2271, +2565, 1709, 2342, +2566, 1798, 2409, +2589, 1863, 2493, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2558, 1699, 2069, +2558, 1698, 2069, +2558, 1697, 2070, +2558, 1695, 2070, +2558, 1693, 2070, +2558, 1690, 2070, +2558, 1686, 2071, +2558, 1681, 2071, +2558, 1674, 2072, +2558, 1663, 2073, +2558, 1650, 2074, +2558, 1650, 2082, +2557, 1648, 2091, +2555, 1631, 2100, +2554, 1621, 2110, +2557, 1657, 2141, +2558, 1642, 2173, +2554, 1658, 2217, +2559, 1702, 2273, +2565, 1715, 2342, +2566, 1810, 2409, +2589, 1868, 2493, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2559, 1723, 2073, +2559, 1723, 2073, +2559, 1722, 2073, +2559, 1720, 2073, +2559, 1718, 2074, +2559, 1715, 2074, +2559, 1711, 2074, +2559, 1706, 2075, +2559, 1699, 2076, +2559, 1690, 2077, +2559, 1677, 2078, +2559, 1659, 2080, +2558, 1657, 2089, +2556, 1641, 2098, +2554, 1621, 2110, +2557, 1657, 2141, +2558, 1669, 2176, +2555, 1684, 2217, +2560, 1706, 2274, +2566, 1723, 2342, +2567, 1816, 2409, +2591, 1873, 2493, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2560, 1754, 2078, +2560, 1754, 2078, +2560, 1753, 2078, +2560, 1752, 2079, +2560, 1750, 2079, +2560, 1747, 2079, +2560, 1744, 2080, +2560, 1739, 2080, +2560, 1732, 2081, +2560, 1724, 2082, +2560, 1712, 2083, +2560, 1695, 2085, +2560, 1674, 2088, +2558, 1658, 2097, +2555, 1635, 2110, +2557, 1661, 2141, +2559, 1703, 2179, +2556, 1716, 2217, +2560, 1716, 2275, +2566, 1739, 2342, +2568, 1818, 2408, +2592, 1880, 2493, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2562, 1761, 2078, +2562, 1761, 2078, +2562, 1761, 2079, +2562, 1762, 2080, +2562, 1763, 2080, +2562, 1765, 2082, +2562, 1766, 2084, +2562, 1769, 2086, +2562, 1772, 2089, +2563, 1771, 2091, +2563, 1760, 2093, +2563, 1745, 2094, +2562, 1727, 2097, +2561, 1712, 2103, +2558, 1692, 2116, +2556, 1693, 2138, +2560, 1738, 2181, +2560, 1744, 2217, +2561, 1744, 2275, +2566, 1785, 2340, +2571, 1835, 2406, +2592, 1893, 2492, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2563, 1769, 2078, +2563, 1769, 2078, +2563, 1770, 2079, +2563, 1771, 2080, +2563, 1772, 2080, +2563, 1773, 2082, +2564, 1775, 2084, +2564, 1777, 2086, +2564, 1780, 2089, +2564, 1784, 2093, +2565, 1789, 2098, +2565, 1796, 2105, +2566, 1789, 2110, +2564, 1776, 2116, +2563, 1758, 2124, +2559, 1753, 2143, +2558, 1773, 2177, +2563, 1787, 2220, +2563, 1779, 2275, +2566, 1840, 2337, +2576, 1860, 2406, +2591, 1925, 2491, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2566, 1822, 2077, +2566, 1822, 2078, +2566, 1822, 2078, +2566, 1822, 2078, +2566, 1822, 2079, +2566, 1822, 2079, +2566, 1822, 2080, +2566, 1822, 2081, +2566, 1822, 2083, +2566, 1822, 2085, +2567, 1824, 2089, +2568, 1831, 2096, +2568, 1839, 2106, +2570, 1844, 2121, +2568, 1834, 2131, +2568, 1813, 2145, +2564, 1813, 2176, +2565, 1838, 2221, +2568, 1838, 2272, +2573, 1888, 2337, +2580, 1896, 2406, +2599, 1967, 2492, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2573, 1894, 2080, +2573, 1894, 2081, +2573, 1895, 2081, +2573, 1896, 2081, +2573, 1897, 2082, +2574, 1898, 2082, +2574, 1900, 2083, +2575, 1903, 2084, +2575, 1906, 2086, +2575, 1906, 2088, +2575, 1906, 2090, +2575, 1906, 2094, +2575, 1906, 2099, +2575, 1907, 2109, +2576, 1913, 2129, +2577, 1915, 2152, +2578, 1893, 2171, +2576, 1899, 2221, +2578, 1919, 2273, +2580, 1949, 2338, +2587, 1961, 2408, +2611, 2008, 2495, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2588, 1996, 2083, +2588, 1997, 2083, +2588, 1997, 2084, +2588, 1997, 2085, +2588, 1997, 2086, +2588, 1998, 2087, +2588, 1998, 2088, +2588, 1999, 2091, +2588, 2000, 2093, +2588, 2001, 2098, +2588, 2005, 2100, +2589, 2012, 2104, +2591, 2018, 2108, +2588, 2010, 2114, +2588, 2009, 2126, +2589, 2014, 2149, +2590, 2016, 2184, +2591, 2003, 2214, +2591, 2019, 2275, +2595, 2044, 2342, +2604, 2072, 2411, +2625, 2108, 2494, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2625, 2149, 2111, +2624, 2149, 2111, +2624, 2149, 2111, +2624, 2149, 2111, +2624, 2148, 2111, +2624, 2148, 2111, +2623, 2147, 2111, +2623, 2146, 2111, +2622, 2145, 2111, +2621, 2143, 2111, +2620, 2141, 2111, +2618, 2137, 2111, +2617, 2136, 2114, +2617, 2144, 2126, +2617, 2155, 2141, +2619, 2157, 2164, +2623, 2160, 2195, +2624, 2165, 2231, +2619, 2165, 2275, +2633, 2187, 2352, +2638, 2190, 2417, +2660, 2223, 2503, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2670, 2315, 2112, +2671, 2315, 2112, +2671, 2315, 2112, +2671, 2315, 2111, +2671, 2316, 2111, +2672, 2316, 2111, +2672, 2316, 2111, +2673, 2317, 2110, +2674, 2318, 2109, +2675, 2319, 2108, +2677, 2321, 2107, +2680, 2323, 2105, +2682, 2325, 2106, +2681, 2325, 2118, +2680, 2325, 2133, +2678, 2328, 2149, +2677, 2328, 2176, +2677, 2325, 2215, +2687, 2335, 2275, +2689, 2335, 2316, +2695, 2346, 2391, +2724, 2369, 2462, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2775, 2531, 1744, +2775, 2531, 1745, +2775, 2531, 1747, +2775, 2531, 1750, +2776, 2532, 1753, +2776, 2532, 1758, +2776, 2533, 1764, +2776, 2533, 1772, +2777, 2534, 1782, +2778, 2535, 1796, +2778, 2536, 1813, +2778, 2537, 1825, +2777, 2535, 1833, +2776, 2530, 1839, +2776, 2528, 1859, +2778, 2535, 1929, +2779, 2534, 1991, +2780, 2535, 2071, +2782, 2538, 2158, +2784, 2536, 2248, +2791, 2552, 2360, +2803, 2569, 2485, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2826, 2762, 2506, +2826, 2762, 2506, +2826, 2762, 2505, +2826, 2762, 2505, +2826, 2762, 2505, +2826, 2762, 2505, +2826, 2761, 2505, +2826, 2761, 2505, +2826, 2761, 2505, +2826, 2761, 2506, +2826, 2761, 2507, +2826, 2761, 2509, +2826, 2761, 2510, +2826, 2760, 2508, +2826, 2760, 2508, +2826, 2762, 2520, +2826, 2764, 2535, +2826, 2763, 2548, +2826, 2763, 2571, +2826, 2767, 2613, +2826, 2769, 2662, +2826, 2779, 2732, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2554, 1623, 2059, +2554, 1623, 2059, +2554, 1623, 2060, +2554, 1623, 2060, +2554, 1623, 2061, +2554, 1623, 2063, +2554, 1623, 2065, +2554, 1623, 2067, +2554, 1623, 2070, +2554, 1623, 2074, +2554, 1623, 2080, +2554, 1623, 2087, +2554, 1621, 2096, +2554, 1621, 2102, +2554, 1621, 2110, +2555, 1588, 2133, +2556, 1555, 2169, +2555, 1608, 2217, +2557, 1691, 2269, +2563, 1692, 2342, +2564, 1761, 2409, +2587, 1838, 2491, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1625, 2059, +2554, 1624, 2059, +2554, 1624, 2060, +2554, 1624, 2060, +2554, 1624, 2061, +2554, 1624, 2063, +2554, 1624, 2064, +2554, 1624, 2067, +2554, 1624, 2070, +2554, 1624, 2074, +2554, 1624, 2080, +2554, 1624, 2087, +2554, 1621, 2096, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1590, 2134, +2556, 1556, 2169, +2555, 1609, 2217, +2557, 1691, 2269, +2563, 1692, 2342, +2564, 1762, 2409, +2587, 1839, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1627, 2059, +2554, 1626, 2059, +2554, 1625, 2060, +2554, 1625, 2060, +2554, 1625, 2061, +2554, 1625, 2063, +2554, 1625, 2064, +2554, 1625, 2067, +2554, 1625, 2070, +2554, 1625, 2074, +2554, 1625, 2079, +2554, 1625, 2086, +2554, 1622, 2096, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1592, 2134, +2556, 1559, 2169, +2555, 1610, 2217, +2557, 1691, 2269, +2564, 1693, 2342, +2564, 1764, 2409, +2587, 1840, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1630, 2060, +2554, 1629, 2060, +2554, 1627, 2060, +2554, 1625, 2060, +2554, 1625, 2061, +2554, 1625, 2062, +2554, 1625, 2064, +2554, 1625, 2066, +2554, 1625, 2070, +2554, 1625, 2074, +2554, 1625, 2079, +2554, 1625, 2086, +2554, 1623, 2095, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1595, 2134, +2556, 1562, 2169, +2555, 1611, 2217, +2557, 1691, 2270, +2564, 1694, 2342, +2564, 1765, 2409, +2587, 1842, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1633, 2060, +2554, 1632, 2060, +2554, 1631, 2060, +2554, 1629, 2060, +2554, 1626, 2061, +2554, 1626, 2062, +2554, 1626, 2064, +2554, 1626, 2066, +2554, 1626, 2069, +2554, 1626, 2073, +2554, 1626, 2079, +2554, 1626, 2086, +2554, 1625, 2095, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1599, 2135, +2556, 1567, 2169, +2555, 1613, 2217, +2557, 1692, 2270, +2564, 1695, 2342, +2565, 1768, 2409, +2587, 1844, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1638, 2061, +2554, 1638, 2061, +2554, 1636, 2061, +2554, 1634, 2061, +2554, 1631, 2061, +2554, 1628, 2062, +2554, 1628, 2063, +2554, 1628, 2066, +2554, 1628, 2069, +2554, 1628, 2073, +2554, 1628, 2079, +2554, 1628, 2086, +2554, 1626, 2095, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1605, 2135, +2556, 1572, 2169, +2555, 1616, 2217, +2557, 1693, 2270, +2564, 1696, 2342, +2565, 1771, 2409, +2587, 1847, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2555, 1645, 2062, +2555, 1644, 2062, +2555, 1643, 2062, +2555, 1641, 2062, +2555, 1638, 2062, +2555, 1635, 2063, +2555, 1631, 2063, +2555, 1631, 2066, +2555, 1631, 2069, +2555, 1631, 2073, +2555, 1631, 2078, +2555, 1631, 2085, +2555, 1628, 2094, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1612, 2136, +2556, 1580, 2169, +2554, 1619, 2217, +2558, 1694, 2270, +2564, 1698, 2342, +2565, 1775, 2409, +2587, 1852, 2492, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2555, 1654, 2063, +2555, 1653, 2063, +2555, 1651, 2063, +2555, 1650, 2063, +2555, 1647, 2063, +2555, 1644, 2064, +2555, 1640, 2064, +2555, 1633, 2065, +2555, 1633, 2068, +2555, 1633, 2072, +2555, 1633, 2078, +2555, 1633, 2085, +2555, 1631, 2094, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1621, 2137, +2557, 1590, 2169, +2554, 1624, 2217, +2558, 1695, 2270, +2564, 1701, 2342, +2565, 1781, 2409, +2588, 1857, 2493, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2556, 1665, 2064, +2556, 1664, 2065, +2556, 1663, 2065, +2556, 1661, 2065, +2556, 1659, 2065, +2556, 1655, 2066, +2556, 1651, 2066, +2556, 1646, 2066, +2556, 1638, 2067, +2556, 1638, 2071, +2556, 1638, 2077, +2556, 1638, 2084, +2556, 1636, 2093, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1633, 2138, +2557, 1603, 2169, +2554, 1630, 2217, +2558, 1697, 2271, +2564, 1704, 2342, +2565, 1788, 2409, +2588, 1860, 2493, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2556, 1680, 2066, +2556, 1679, 2067, +2556, 1678, 2067, +2556, 1676, 2067, +2556, 1674, 2067, +2556, 1671, 2068, +2556, 1667, 2068, +2556, 1661, 2069, +2556, 1653, 2069, +2556, 1643, 2070, +2556, 1643, 2076, +2556, 1643, 2083, +2556, 1641, 2092, +2554, 1624, 2101, +2554, 1621, 2110, +2557, 1649, 2140, +2557, 1620, 2170, +2554, 1638, 2217, +2558, 1699, 2271, +2565, 1709, 2342, +2566, 1798, 2409, +2589, 1863, 2493, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2558, 1699, 2069, +2558, 1698, 2069, +2558, 1697, 2070, +2558, 1695, 2070, +2558, 1693, 2070, +2558, 1690, 2070, +2558, 1686, 2071, +2558, 1681, 2071, +2558, 1674, 2072, +2558, 1663, 2073, +2558, 1650, 2074, +2558, 1650, 2082, +2557, 1648, 2091, +2555, 1631, 2100, +2554, 1621, 2110, +2557, 1657, 2141, +2558, 1642, 2173, +2554, 1658, 2217, +2559, 1702, 2273, +2565, 1715, 2342, +2566, 1810, 2409, +2589, 1868, 2493, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2559, 1723, 2073, +2559, 1723, 2073, +2559, 1722, 2073, +2559, 1720, 2073, +2559, 1718, 2074, +2559, 1715, 2074, +2559, 1711, 2074, +2559, 1706, 2075, +2559, 1699, 2076, +2559, 1690, 2077, +2559, 1677, 2078, +2559, 1659, 2080, +2558, 1657, 2089, +2556, 1641, 2098, +2554, 1621, 2110, +2557, 1657, 2141, +2558, 1669, 2176, +2555, 1684, 2217, +2560, 1706, 2274, +2566, 1723, 2342, +2567, 1816, 2409, +2591, 1873, 2493, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2560, 1754, 2078, +2560, 1754, 2078, +2560, 1753, 2078, +2560, 1752, 2079, +2560, 1750, 2079, +2560, 1747, 2079, +2560, 1744, 2080, +2560, 1739, 2080, +2560, 1732, 2081, +2560, 1724, 2082, +2560, 1712, 2083, +2560, 1695, 2085, +2560, 1674, 2088, +2558, 1658, 2097, +2555, 1635, 2110, +2557, 1661, 2141, +2559, 1703, 2179, +2556, 1716, 2217, +2560, 1716, 2275, +2566, 1739, 2342, +2568, 1818, 2408, +2592, 1880, 2493, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2562, 1761, 2078, +2562, 1761, 2078, +2562, 1761, 2079, +2562, 1762, 2080, +2562, 1763, 2080, +2562, 1765, 2082, +2562, 1766, 2084, +2562, 1769, 2086, +2562, 1772, 2089, +2563, 1771, 2091, +2563, 1760, 2093, +2563, 1745, 2094, +2562, 1727, 2097, +2561, 1712, 2103, +2558, 1692, 2116, +2556, 1693, 2138, +2560, 1738, 2181, +2560, 1744, 2217, +2561, 1744, 2275, +2566, 1785, 2340, +2571, 1835, 2406, +2592, 1893, 2492, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2563, 1769, 2078, +2563, 1769, 2078, +2563, 1770, 2079, +2563, 1771, 2080, +2563, 1772, 2080, +2563, 1773, 2082, +2564, 1775, 2084, +2564, 1777, 2086, +2564, 1780, 2089, +2564, 1784, 2093, +2565, 1789, 2098, +2565, 1796, 2105, +2566, 1789, 2110, +2564, 1776, 2116, +2563, 1758, 2124, +2559, 1753, 2143, +2558, 1773, 2177, +2563, 1787, 2220, +2563, 1779, 2275, +2566, 1840, 2337, +2576, 1860, 2406, +2591, 1925, 2491, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2566, 1822, 2077, +2566, 1822, 2078, +2566, 1822, 2078, +2566, 1822, 2078, +2566, 1822, 2079, +2566, 1822, 2079, +2566, 1822, 2080, +2566, 1822, 2081, +2566, 1822, 2083, +2566, 1822, 2085, +2567, 1824, 2089, +2568, 1831, 2096, +2568, 1839, 2106, +2570, 1844, 2121, +2568, 1834, 2131, +2568, 1813, 2145, +2564, 1813, 2176, +2565, 1838, 2221, +2568, 1838, 2272, +2573, 1888, 2337, +2580, 1896, 2406, +2599, 1967, 2492, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2573, 1894, 2080, +2573, 1894, 2081, +2573, 1895, 2081, +2573, 1896, 2081, +2573, 1897, 2082, +2574, 1898, 2082, +2574, 1900, 2083, +2575, 1903, 2084, +2575, 1906, 2086, +2575, 1906, 2088, +2575, 1906, 2090, +2575, 1906, 2094, +2575, 1906, 2099, +2575, 1907, 2109, +2576, 1913, 2129, +2577, 1915, 2152, +2578, 1893, 2171, +2576, 1899, 2221, +2578, 1919, 2273, +2580, 1949, 2338, +2587, 1961, 2408, +2611, 2008, 2495, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2588, 1996, 2083, +2588, 1997, 2083, +2588, 1997, 2084, +2588, 1997, 2085, +2588, 1997, 2086, +2588, 1998, 2087, +2588, 1998, 2088, +2588, 1999, 2091, +2588, 2000, 2093, +2588, 2001, 2098, +2588, 2005, 2100, +2589, 2012, 2104, +2591, 2018, 2108, +2588, 2010, 2114, +2588, 2009, 2126, +2589, 2014, 2149, +2590, 2016, 2184, +2591, 2003, 2214, +2591, 2019, 2275, +2595, 2044, 2342, +2604, 2072, 2411, +2625, 2108, 2494, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2625, 2149, 2111, +2624, 2149, 2111, +2624, 2149, 2111, +2624, 2149, 2111, +2624, 2148, 2111, +2624, 2148, 2111, +2623, 2147, 2111, +2623, 2146, 2111, +2622, 2145, 2111, +2621, 2143, 2111, +2620, 2141, 2111, +2618, 2137, 2111, +2617, 2136, 2114, +2617, 2144, 2126, +2617, 2155, 2141, +2619, 2157, 2164, +2623, 2160, 2195, +2624, 2165, 2231, +2619, 2165, 2275, +2633, 2187, 2352, +2638, 2190, 2417, +2660, 2223, 2503, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2670, 2315, 2112, +2671, 2315, 2112, +2671, 2315, 2112, +2671, 2315, 2111, +2671, 2316, 2111, +2672, 2316, 2111, +2672, 2316, 2111, +2673, 2317, 2110, +2674, 2318, 2109, +2675, 2319, 2108, +2677, 2321, 2107, +2680, 2323, 2105, +2682, 2325, 2106, +2681, 2325, 2118, +2680, 2325, 2133, +2678, 2328, 2149, +2677, 2328, 2176, +2677, 2325, 2215, +2687, 2335, 2275, +2689, 2335, 2316, +2695, 2346, 2391, +2724, 2369, 2462, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2775, 2531, 1744, +2775, 2531, 1745, +2775, 2531, 1747, +2775, 2531, 1750, +2776, 2532, 1753, +2776, 2532, 1758, +2776, 2533, 1764, +2776, 2533, 1772, +2777, 2534, 1782, +2778, 2535, 1796, +2778, 2536, 1813, +2778, 2537, 1825, +2777, 2535, 1833, +2776, 2530, 1839, +2776, 2528, 1859, +2778, 2535, 1929, +2779, 2534, 1991, +2780, 2535, 2071, +2782, 2538, 2158, +2784, 2536, 2248, +2791, 2552, 2360, +2803, 2569, 2485, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2826, 2762, 2506, +2826, 2762, 2506, +2826, 2762, 2505, +2826, 2762, 2505, +2826, 2762, 2505, +2826, 2762, 2505, +2826, 2761, 2505, +2826, 2761, 2505, +2826, 2761, 2505, +2826, 2761, 2506, +2826, 2761, 2507, +2826, 2761, 2509, +2826, 2761, 2510, +2826, 2760, 2508, +2826, 2760, 2508, +2826, 2762, 2520, +2826, 2764, 2535, +2826, 2763, 2548, +2826, 2763, 2571, +2826, 2767, 2613, +2826, 2769, 2662, +2826, 2779, 2732, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2554, 1623, 2059, +2554, 1623, 2059, +2554, 1623, 2060, +2554, 1623, 2060, +2554, 1623, 2061, +2554, 1623, 2063, +2554, 1623, 2065, +2554, 1623, 2067, +2554, 1623, 2070, +2554, 1623, 2074, +2554, 1623, 2080, +2554, 1623, 2087, +2554, 1621, 2096, +2554, 1621, 2102, +2554, 1621, 2110, +2555, 1588, 2133, +2556, 1555, 2169, +2555, 1608, 2217, +2557, 1691, 2269, +2563, 1692, 2342, +2564, 1761, 2409, +2587, 1838, 2491, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1625, 2059, +2554, 1624, 2059, +2554, 1624, 2060, +2554, 1624, 2060, +2554, 1624, 2061, +2554, 1624, 2063, +2554, 1624, 2064, +2554, 1624, 2067, +2554, 1624, 2070, +2554, 1624, 2074, +2554, 1624, 2080, +2554, 1624, 2087, +2554, 1621, 2096, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1590, 2134, +2556, 1556, 2169, +2555, 1609, 2217, +2557, 1691, 2269, +2563, 1692, 2342, +2564, 1762, 2409, +2587, 1839, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1627, 2059, +2554, 1626, 2059, +2554, 1625, 2060, +2554, 1625, 2060, +2554, 1625, 2061, +2554, 1625, 2063, +2554, 1625, 2064, +2554, 1625, 2067, +2554, 1625, 2070, +2554, 1625, 2074, +2554, 1625, 2079, +2554, 1625, 2086, +2554, 1622, 2096, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1592, 2134, +2556, 1559, 2169, +2555, 1610, 2217, +2557, 1691, 2269, +2564, 1693, 2342, +2564, 1764, 2409, +2587, 1840, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1630, 2060, +2554, 1629, 2060, +2554, 1627, 2060, +2554, 1625, 2060, +2554, 1625, 2061, +2554, 1625, 2062, +2554, 1625, 2064, +2554, 1625, 2066, +2554, 1625, 2070, +2554, 1625, 2074, +2554, 1625, 2079, +2554, 1625, 2086, +2554, 1623, 2095, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1595, 2134, +2556, 1562, 2169, +2555, 1611, 2217, +2557, 1691, 2270, +2564, 1694, 2342, +2564, 1765, 2409, +2587, 1842, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1633, 2060, +2554, 1632, 2060, +2554, 1631, 2060, +2554, 1629, 2060, +2554, 1626, 2061, +2554, 1626, 2062, +2554, 1626, 2064, +2554, 1626, 2066, +2554, 1626, 2069, +2554, 1626, 2073, +2554, 1626, 2079, +2554, 1626, 2086, +2554, 1625, 2095, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1599, 2135, +2556, 1567, 2169, +2555, 1613, 2217, +2557, 1692, 2270, +2564, 1695, 2342, +2565, 1768, 2409, +2587, 1844, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1638, 2061, +2554, 1638, 2061, +2554, 1636, 2061, +2554, 1634, 2061, +2554, 1631, 2061, +2554, 1628, 2062, +2554, 1628, 2063, +2554, 1628, 2066, +2554, 1628, 2069, +2554, 1628, 2073, +2554, 1628, 2079, +2554, 1628, 2086, +2554, 1626, 2095, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1605, 2135, +2556, 1572, 2169, +2555, 1616, 2217, +2557, 1693, 2270, +2564, 1696, 2342, +2565, 1771, 2409, +2587, 1847, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2555, 1645, 2062, +2555, 1644, 2062, +2555, 1643, 2062, +2555, 1641, 2062, +2555, 1638, 2062, +2555, 1635, 2063, +2555, 1631, 2063, +2555, 1631, 2066, +2555, 1631, 2069, +2555, 1631, 2073, +2555, 1631, 2078, +2555, 1631, 2085, +2555, 1628, 2094, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1612, 2136, +2556, 1580, 2169, +2554, 1619, 2217, +2558, 1694, 2270, +2564, 1698, 2342, +2565, 1775, 2409, +2587, 1852, 2492, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2555, 1654, 2063, +2555, 1653, 2063, +2555, 1651, 2063, +2555, 1650, 2063, +2555, 1647, 2063, +2555, 1644, 2064, +2555, 1640, 2064, +2555, 1633, 2065, +2555, 1633, 2068, +2555, 1633, 2072, +2555, 1633, 2078, +2555, 1633, 2085, +2555, 1631, 2094, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1621, 2137, +2557, 1590, 2169, +2554, 1624, 2217, +2558, 1695, 2270, +2564, 1701, 2342, +2565, 1781, 2409, +2588, 1857, 2493, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2556, 1665, 2064, +2556, 1664, 2065, +2556, 1663, 2065, +2556, 1661, 2065, +2556, 1659, 2065, +2556, 1655, 2066, +2556, 1651, 2066, +2556, 1646, 2066, +2556, 1638, 2067, +2556, 1638, 2071, +2556, 1638, 2077, +2556, 1638, 2084, +2556, 1636, 2093, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1633, 2138, +2557, 1603, 2169, +2554, 1630, 2217, +2558, 1697, 2271, +2564, 1704, 2342, +2565, 1788, 2409, +2588, 1860, 2493, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2556, 1680, 2066, +2556, 1679, 2067, +2556, 1678, 2067, +2556, 1676, 2067, +2556, 1674, 2067, +2556, 1671, 2068, +2556, 1667, 2068, +2556, 1661, 2069, +2556, 1653, 2069, +2556, 1643, 2070, +2556, 1643, 2076, +2556, 1643, 2083, +2556, 1641, 2092, +2554, 1624, 2101, +2554, 1621, 2110, +2557, 1649, 2140, +2557, 1620, 2170, +2554, 1638, 2217, +2558, 1699, 2271, +2565, 1709, 2342, +2566, 1798, 2409, +2589, 1863, 2493, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2558, 1699, 2069, +2558, 1698, 2069, +2558, 1697, 2070, +2558, 1695, 2070, +2558, 1693, 2070, +2558, 1690, 2070, +2558, 1686, 2071, +2558, 1681, 2071, +2558, 1674, 2072, +2558, 1663, 2073, +2558, 1650, 2074, +2558, 1650, 2082, +2557, 1648, 2091, +2555, 1631, 2100, +2554, 1621, 2110, +2557, 1657, 2141, +2558, 1642, 2173, +2554, 1658, 2217, +2559, 1702, 2273, +2565, 1715, 2342, +2566, 1810, 2409, +2589, 1868, 2493, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2559, 1723, 2073, +2559, 1723, 2073, +2559, 1722, 2073, +2559, 1720, 2073, +2559, 1718, 2074, +2559, 1715, 2074, +2559, 1711, 2074, +2559, 1706, 2075, +2559, 1699, 2076, +2559, 1690, 2077, +2559, 1677, 2078, +2559, 1659, 2080, +2558, 1657, 2089, +2556, 1641, 2098, +2554, 1621, 2110, +2557, 1657, 2141, +2558, 1669, 2176, +2555, 1684, 2217, +2560, 1706, 2274, +2566, 1723, 2342, +2567, 1816, 2409, +2591, 1873, 2493, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2560, 1754, 2078, +2560, 1754, 2078, +2560, 1753, 2078, +2560, 1752, 2079, +2560, 1750, 2079, +2560, 1747, 2079, +2560, 1744, 2080, +2560, 1739, 2080, +2560, 1732, 2081, +2560, 1724, 2082, +2560, 1712, 2083, +2560, 1695, 2085, +2560, 1674, 2088, +2558, 1658, 2097, +2555, 1635, 2110, +2557, 1661, 2141, +2559, 1703, 2179, +2556, 1716, 2217, +2560, 1716, 2275, +2566, 1739, 2342, +2568, 1818, 2408, +2592, 1880, 2493, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2562, 1761, 2078, +2562, 1761, 2078, +2562, 1761, 2079, +2562, 1762, 2080, +2562, 1763, 2080, +2562, 1765, 2082, +2562, 1766, 2084, +2562, 1769, 2086, +2562, 1772, 2089, +2563, 1771, 2091, +2563, 1760, 2093, +2563, 1745, 2094, +2562, 1727, 2097, +2561, 1712, 2103, +2558, 1692, 2116, +2556, 1693, 2138, +2560, 1738, 2181, +2560, 1744, 2217, +2561, 1744, 2275, +2566, 1785, 2340, +2571, 1835, 2406, +2592, 1893, 2492, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2563, 1769, 2078, +2563, 1769, 2078, +2563, 1770, 2079, +2563, 1771, 2080, +2563, 1772, 2080, +2563, 1773, 2082, +2564, 1775, 2084, +2564, 1777, 2086, +2564, 1780, 2089, +2564, 1784, 2093, +2565, 1789, 2098, +2565, 1796, 2105, +2566, 1789, 2110, +2564, 1776, 2116, +2563, 1758, 2124, +2559, 1753, 2143, +2558, 1773, 2177, +2563, 1787, 2220, +2563, 1779, 2275, +2566, 1840, 2337, +2576, 1860, 2406, +2591, 1925, 2491, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2566, 1822, 2077, +2566, 1822, 2078, +2566, 1822, 2078, +2566, 1822, 2078, +2566, 1822, 2079, +2566, 1822, 2079, +2566, 1822, 2080, +2566, 1822, 2081, +2566, 1822, 2083, +2566, 1822, 2085, +2567, 1824, 2089, +2568, 1831, 2096, +2568, 1839, 2106, +2570, 1844, 2121, +2568, 1834, 2131, +2568, 1813, 2145, +2564, 1813, 2176, +2565, 1838, 2221, +2568, 1838, 2272, +2573, 1888, 2337, +2580, 1896, 2406, +2599, 1967, 2492, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2573, 1894, 2080, +2573, 1894, 2081, +2573, 1895, 2081, +2573, 1896, 2081, +2573, 1897, 2082, +2574, 1898, 2082, +2574, 1900, 2083, +2575, 1903, 2084, +2575, 1906, 2086, +2575, 1906, 2088, +2575, 1906, 2090, +2575, 1906, 2094, +2575, 1906, 2099, +2575, 1907, 2109, +2576, 1913, 2129, +2577, 1915, 2152, +2578, 1893, 2171, +2576, 1899, 2221, +2578, 1919, 2273, +2580, 1949, 2338, +2587, 1961, 2408, +2611, 2008, 2495, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2588, 1996, 2083, +2588, 1997, 2083, +2588, 1997, 2084, +2588, 1997, 2085, +2588, 1997, 2086, +2588, 1998, 2087, +2588, 1998, 2088, +2588, 1999, 2091, +2588, 2000, 2093, +2588, 2001, 2098, +2588, 2005, 2100, +2589, 2012, 2104, +2591, 2018, 2108, +2588, 2010, 2114, +2588, 2009, 2126, +2589, 2014, 2149, +2590, 2016, 2184, +2591, 2003, 2214, +2591, 2019, 2275, +2595, 2044, 2342, +2604, 2072, 2411, +2625, 2108, 2494, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2625, 2149, 2111, +2624, 2149, 2111, +2624, 2149, 2111, +2624, 2149, 2111, +2624, 2148, 2111, +2624, 2148, 2111, +2623, 2147, 2111, +2623, 2146, 2111, +2622, 2145, 2111, +2621, 2143, 2111, +2620, 2141, 2111, +2618, 2137, 2111, +2617, 2136, 2114, +2617, 2144, 2126, +2617, 2155, 2141, +2619, 2157, 2164, +2623, 2160, 2195, +2624, 2165, 2231, +2619, 2165, 2275, +2633, 2187, 2352, +2638, 2190, 2417, +2660, 2223, 2503, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2670, 2315, 2112, +2671, 2315, 2112, +2671, 2315, 2112, +2671, 2315, 2111, +2671, 2316, 2111, +2672, 2316, 2111, +2672, 2316, 2111, +2673, 2317, 2110, +2674, 2318, 2109, +2675, 2319, 2108, +2677, 2321, 2107, +2680, 2323, 2105, +2682, 2325, 2106, +2681, 2325, 2118, +2680, 2325, 2133, +2678, 2328, 2149, +2677, 2328, 2176, +2677, 2325, 2215, +2687, 2335, 2275, +2689, 2335, 2316, +2695, 2346, 2391, +2724, 2369, 2462, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2775, 2531, 1744, +2775, 2531, 1745, +2775, 2531, 1747, +2775, 2531, 1750, +2776, 2532, 1753, +2776, 2532, 1758, +2776, 2533, 1764, +2776, 2533, 1772, +2777, 2534, 1782, +2778, 2535, 1796, +2778, 2536, 1813, +2778, 2537, 1825, +2777, 2535, 1833, +2776, 2530, 1839, +2776, 2528, 1859, +2778, 2535, 1929, +2779, 2534, 1991, +2780, 2535, 2071, +2782, 2538, 2158, +2784, 2536, 2248, +2791, 2552, 2360, +2803, 2569, 2485, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2826, 2762, 2506, +2826, 2762, 2506, +2826, 2762, 2505, +2826, 2762, 2505, +2826, 2762, 2505, +2826, 2762, 2505, +2826, 2761, 2505, +2826, 2761, 2505, +2826, 2761, 2505, +2826, 2761, 2506, +2826, 2761, 2507, +2826, 2761, 2509, +2826, 2761, 2510, +2826, 2760, 2508, +2826, 2760, 2508, +2826, 2762, 2520, +2826, 2764, 2535, +2826, 2763, 2548, +2826, 2763, 2571, +2826, 2767, 2613, +2826, 2769, 2662, +2826, 2779, 2732, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2554, 1623, 2059, +2554, 1623, 2059, +2554, 1623, 2060, +2554, 1623, 2060, +2554, 1623, 2061, +2554, 1623, 2063, +2554, 1623, 2065, +2554, 1623, 2067, +2554, 1623, 2070, +2554, 1623, 2074, +2554, 1623, 2080, +2554, 1623, 2087, +2554, 1621, 2096, +2554, 1621, 2102, +2554, 1621, 2110, +2555, 1588, 2133, +2556, 1555, 2169, +2555, 1608, 2217, +2557, 1691, 2269, +2563, 1692, 2342, +2564, 1761, 2409, +2587, 1838, 2491, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1625, 2059, +2554, 1624, 2059, +2554, 1624, 2060, +2554, 1624, 2060, +2554, 1624, 2061, +2554, 1624, 2063, +2554, 1624, 2064, +2554, 1624, 2067, +2554, 1624, 2070, +2554, 1624, 2074, +2554, 1624, 2080, +2554, 1624, 2087, +2554, 1621, 2096, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1590, 2134, +2556, 1556, 2169, +2555, 1609, 2217, +2557, 1691, 2269, +2563, 1692, 2342, +2564, 1762, 2409, +2587, 1839, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1627, 2059, +2554, 1626, 2059, +2554, 1625, 2060, +2554, 1625, 2060, +2554, 1625, 2061, +2554, 1625, 2063, +2554, 1625, 2064, +2554, 1625, 2067, +2554, 1625, 2070, +2554, 1625, 2074, +2554, 1625, 2079, +2554, 1625, 2086, +2554, 1622, 2096, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1592, 2134, +2556, 1559, 2169, +2555, 1610, 2217, +2557, 1691, 2269, +2564, 1693, 2342, +2564, 1764, 2409, +2587, 1840, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1630, 2060, +2554, 1629, 2060, +2554, 1627, 2060, +2554, 1625, 2060, +2554, 1625, 2061, +2554, 1625, 2062, +2554, 1625, 2064, +2554, 1625, 2066, +2554, 1625, 2070, +2554, 1625, 2074, +2554, 1625, 2079, +2554, 1625, 2086, +2554, 1623, 2095, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1595, 2134, +2556, 1562, 2169, +2555, 1611, 2217, +2557, 1691, 2270, +2564, 1694, 2342, +2564, 1765, 2409, +2587, 1842, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1633, 2060, +2554, 1632, 2060, +2554, 1631, 2060, +2554, 1629, 2060, +2554, 1626, 2061, +2554, 1626, 2062, +2554, 1626, 2064, +2554, 1626, 2066, +2554, 1626, 2069, +2554, 1626, 2073, +2554, 1626, 2079, +2554, 1626, 2086, +2554, 1625, 2095, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1599, 2135, +2556, 1567, 2169, +2555, 1613, 2217, +2557, 1692, 2270, +2564, 1695, 2342, +2565, 1768, 2409, +2587, 1844, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1638, 2061, +2554, 1638, 2061, +2554, 1636, 2061, +2554, 1634, 2061, +2554, 1631, 2061, +2554, 1628, 2062, +2554, 1628, 2063, +2554, 1628, 2066, +2554, 1628, 2069, +2554, 1628, 2073, +2554, 1628, 2079, +2554, 1628, 2086, +2554, 1626, 2095, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1605, 2135, +2556, 1572, 2169, +2555, 1616, 2217, +2557, 1693, 2270, +2564, 1696, 2342, +2565, 1771, 2409, +2587, 1847, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2555, 1645, 2062, +2555, 1644, 2062, +2555, 1643, 2062, +2555, 1641, 2062, +2555, 1638, 2062, +2555, 1635, 2063, +2555, 1631, 2063, +2555, 1631, 2066, +2555, 1631, 2069, +2555, 1631, 2073, +2555, 1631, 2078, +2555, 1631, 2085, +2555, 1628, 2094, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1612, 2136, +2556, 1580, 2169, +2554, 1619, 2217, +2558, 1694, 2270, +2564, 1698, 2342, +2565, 1775, 2409, +2587, 1852, 2492, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2555, 1654, 2063, +2555, 1653, 2063, +2555, 1651, 2063, +2555, 1650, 2063, +2555, 1647, 2063, +2555, 1644, 2064, +2555, 1640, 2064, +2555, 1633, 2065, +2555, 1633, 2068, +2555, 1633, 2072, +2555, 1633, 2078, +2555, 1633, 2085, +2555, 1631, 2094, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1621, 2137, +2557, 1590, 2169, +2554, 1624, 2217, +2558, 1695, 2270, +2564, 1701, 2342, +2565, 1781, 2409, +2588, 1857, 2493, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2556, 1665, 2064, +2556, 1664, 2065, +2556, 1663, 2065, +2556, 1661, 2065, +2556, 1659, 2065, +2556, 1655, 2066, +2556, 1651, 2066, +2556, 1646, 2066, +2556, 1638, 2067, +2556, 1638, 2071, +2556, 1638, 2077, +2556, 1638, 2084, +2556, 1636, 2093, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1633, 2138, +2557, 1603, 2169, +2554, 1630, 2217, +2558, 1697, 2271, +2564, 1704, 2342, +2565, 1788, 2409, +2588, 1860, 2493, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2556, 1680, 2066, +2556, 1679, 2067, +2556, 1678, 2067, +2556, 1676, 2067, +2556, 1674, 2067, +2556, 1671, 2068, +2556, 1667, 2068, +2556, 1661, 2069, +2556, 1653, 2069, +2556, 1643, 2070, +2556, 1643, 2076, +2556, 1643, 2083, +2556, 1641, 2092, +2554, 1624, 2101, +2554, 1621, 2110, +2557, 1649, 2140, +2557, 1620, 2170, +2554, 1638, 2217, +2558, 1699, 2271, +2565, 1709, 2342, +2566, 1798, 2409, +2589, 1863, 2493, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2558, 1699, 2069, +2558, 1698, 2069, +2558, 1697, 2070, +2558, 1695, 2070, +2558, 1693, 2070, +2558, 1690, 2070, +2558, 1686, 2071, +2558, 1681, 2071, +2558, 1674, 2072, +2558, 1663, 2073, +2558, 1650, 2074, +2558, 1650, 2082, +2557, 1648, 2091, +2555, 1631, 2100, +2554, 1621, 2110, +2557, 1657, 2141, +2558, 1642, 2173, +2554, 1658, 2217, +2559, 1702, 2273, +2565, 1715, 2342, +2566, 1810, 2409, +2589, 1868, 2493, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2559, 1723, 2073, +2559, 1723, 2073, +2559, 1722, 2073, +2559, 1720, 2073, +2559, 1718, 2074, +2559, 1715, 2074, +2559, 1711, 2074, +2559, 1706, 2075, +2559, 1699, 2076, +2559, 1690, 2077, +2559, 1677, 2078, +2559, 1659, 2080, +2558, 1657, 2089, +2556, 1641, 2098, +2554, 1621, 2110, +2557, 1657, 2141, +2558, 1669, 2176, +2555, 1684, 2217, +2560, 1706, 2274, +2566, 1723, 2342, +2567, 1816, 2409, +2591, 1873, 2493, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2560, 1754, 2078, +2560, 1754, 2078, +2560, 1753, 2078, +2560, 1752, 2079, +2560, 1750, 2079, +2560, 1747, 2079, +2560, 1744, 2080, +2560, 1739, 2080, +2560, 1732, 2081, +2560, 1724, 2082, +2560, 1712, 2083, +2560, 1695, 2085, +2560, 1674, 2088, +2558, 1658, 2097, +2555, 1635, 2110, +2557, 1661, 2141, +2559, 1703, 2179, +2556, 1716, 2217, +2560, 1716, 2275, +2566, 1739, 2342, +2568, 1818, 2408, +2592, 1880, 2493, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2562, 1761, 2078, +2562, 1761, 2078, +2562, 1761, 2079, +2562, 1762, 2080, +2562, 1763, 2080, +2562, 1765, 2082, +2562, 1766, 2084, +2562, 1769, 2086, +2562, 1772, 2089, +2563, 1771, 2091, +2563, 1760, 2093, +2563, 1745, 2094, +2562, 1727, 2097, +2561, 1712, 2103, +2558, 1692, 2116, +2556, 1693, 2138, +2560, 1738, 2181, +2560, 1744, 2217, +2561, 1744, 2275, +2566, 1785, 2340, +2571, 1835, 2406, +2592, 1893, 2492, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2563, 1769, 2078, +2563, 1769, 2078, +2563, 1770, 2079, +2563, 1771, 2080, +2563, 1772, 2080, +2563, 1773, 2082, +2564, 1775, 2084, +2564, 1777, 2086, +2564, 1780, 2089, +2564, 1784, 2093, +2565, 1789, 2098, +2565, 1796, 2105, +2566, 1789, 2110, +2564, 1776, 2116, +2563, 1758, 2124, +2559, 1753, 2143, +2558, 1773, 2177, +2563, 1787, 2220, +2563, 1779, 2275, +2566, 1840, 2337, +2576, 1860, 2406, +2591, 1925, 2491, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2566, 1822, 2077, +2566, 1822, 2078, +2566, 1822, 2078, +2566, 1822, 2078, +2566, 1822, 2079, +2566, 1822, 2079, +2566, 1822, 2080, +2566, 1822, 2081, +2566, 1822, 2083, +2566, 1822, 2085, +2567, 1824, 2089, +2568, 1831, 2096, +2568, 1839, 2106, +2570, 1844, 2121, +2568, 1834, 2131, +2568, 1813, 2145, +2564, 1813, 2176, +2565, 1838, 2221, +2568, 1838, 2272, +2573, 1888, 2337, +2580, 1896, 2406, +2599, 1967, 2492, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2573, 1894, 2080, +2573, 1894, 2081, +2573, 1895, 2081, +2573, 1896, 2081, +2573, 1897, 2082, +2574, 1898, 2082, +2574, 1900, 2083, +2575, 1903, 2084, +2575, 1906, 2086, +2575, 1906, 2088, +2575, 1906, 2090, +2575, 1906, 2094, +2575, 1906, 2099, +2575, 1907, 2109, +2576, 1913, 2129, +2577, 1915, 2152, +2578, 1893, 2171, +2576, 1899, 2221, +2578, 1919, 2273, +2580, 1949, 2338, +2587, 1961, 2408, +2611, 2008, 2495, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2588, 1996, 2083, +2588, 1997, 2083, +2588, 1997, 2084, +2588, 1997, 2085, +2588, 1997, 2086, +2588, 1998, 2087, +2588, 1998, 2088, +2588, 1999, 2091, +2588, 2000, 2093, +2588, 2001, 2098, +2588, 2005, 2100, +2589, 2012, 2104, +2591, 2018, 2108, +2588, 2010, 2114, +2588, 2009, 2126, +2589, 2014, 2149, +2590, 2016, 2184, +2591, 2003, 2214, +2591, 2019, 2275, +2595, 2044, 2342, +2604, 2072, 2411, +2625, 2108, 2494, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2625, 2149, 2111, +2624, 2149, 2111, +2624, 2149, 2111, +2624, 2149, 2111, +2624, 2148, 2111, +2624, 2148, 2111, +2623, 2147, 2111, +2623, 2146, 2111, +2622, 2145, 2111, +2621, 2143, 2111, +2620, 2141, 2111, +2618, 2137, 2111, +2617, 2136, 2114, +2617, 2144, 2126, +2617, 2155, 2141, +2619, 2157, 2164, +2623, 2160, 2195, +2624, 2165, 2231, +2619, 2165, 2275, +2633, 2187, 2352, +2638, 2190, 2417, +2660, 2223, 2503, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2670, 2315, 2112, +2671, 2315, 2112, +2671, 2315, 2112, +2671, 2315, 2111, +2671, 2316, 2111, +2672, 2316, 2111, +2672, 2316, 2111, +2673, 2317, 2110, +2674, 2318, 2109, +2675, 2319, 2108, +2677, 2321, 2107, +2680, 2323, 2105, +2682, 2325, 2106, +2681, 2325, 2118, +2680, 2325, 2133, +2678, 2328, 2149, +2677, 2328, 2176, +2677, 2325, 2215, +2687, 2335, 2275, +2689, 2335, 2316, +2695, 2346, 2391, +2724, 2369, 2462, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2775, 2531, 1744, +2775, 2531, 1745, +2775, 2531, 1747, +2775, 2531, 1750, +2776, 2532, 1753, +2776, 2532, 1758, +2776, 2533, 1764, +2776, 2533, 1772, +2777, 2534, 1782, +2778, 2535, 1796, +2778, 2536, 1813, +2778, 2537, 1825, +2777, 2535, 1833, +2776, 2530, 1839, +2776, 2528, 1859, +2778, 2535, 1929, +2779, 2534, 1991, +2780, 2535, 2071, +2782, 2538, 2158, +2784, 2536, 2248, +2791, 2552, 2360, +2803, 2569, 2485, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2826, 2762, 2506, +2826, 2762, 2506, +2826, 2762, 2505, +2826, 2762, 2505, +2826, 2762, 2505, +2826, 2762, 2505, +2826, 2761, 2505, +2826, 2761, 2505, +2826, 2761, 2505, +2826, 2761, 2506, +2826, 2761, 2507, +2826, 2761, 2509, +2826, 2761, 2510, +2826, 2760, 2508, +2826, 2760, 2508, +2826, 2762, 2520, +2826, 2764, 2535, +2826, 2763, 2548, +2826, 2763, 2571, +2826, 2767, 2613, +2826, 2769, 2662, +2826, 2779, 2732, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2554, 1623, 2059, +2554, 1623, 2059, +2554, 1623, 2060, +2554, 1623, 2060, +2554, 1623, 2061, +2554, 1623, 2063, +2554, 1623, 2065, +2554, 1623, 2067, +2554, 1623, 2070, +2554, 1623, 2074, +2554, 1623, 2080, +2554, 1623, 2087, +2554, 1621, 2096, +2554, 1621, 2102, +2554, 1621, 2110, +2555, 1588, 2133, +2556, 1555, 2169, +2555, 1608, 2217, +2557, 1691, 2269, +2563, 1692, 2342, +2564, 1761, 2409, +2587, 1838, 2491, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1625, 2059, +2554, 1624, 2059, +2554, 1624, 2060, +2554, 1624, 2060, +2554, 1624, 2061, +2554, 1624, 2063, +2554, 1624, 2064, +2554, 1624, 2067, +2554, 1624, 2070, +2554, 1624, 2074, +2554, 1624, 2080, +2554, 1624, 2087, +2554, 1621, 2096, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1590, 2134, +2556, 1556, 2169, +2555, 1609, 2217, +2557, 1691, 2269, +2563, 1692, 2342, +2564, 1762, 2409, +2587, 1839, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1627, 2059, +2554, 1626, 2059, +2554, 1625, 2060, +2554, 1625, 2060, +2554, 1625, 2061, +2554, 1625, 2063, +2554, 1625, 2064, +2554, 1625, 2067, +2554, 1625, 2070, +2554, 1625, 2074, +2554, 1625, 2079, +2554, 1625, 2086, +2554, 1622, 2096, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1592, 2134, +2556, 1559, 2169, +2555, 1610, 2217, +2557, 1691, 2269, +2564, 1693, 2342, +2564, 1764, 2409, +2587, 1840, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1630, 2060, +2554, 1629, 2060, +2554, 1627, 2060, +2554, 1625, 2060, +2554, 1625, 2061, +2554, 1625, 2062, +2554, 1625, 2064, +2554, 1625, 2066, +2554, 1625, 2070, +2554, 1625, 2074, +2554, 1625, 2079, +2554, 1625, 2086, +2554, 1623, 2095, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1595, 2134, +2556, 1562, 2169, +2555, 1611, 2217, +2557, 1691, 2270, +2564, 1694, 2342, +2564, 1765, 2409, +2587, 1842, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1633, 2060, +2554, 1632, 2060, +2554, 1631, 2060, +2554, 1629, 2060, +2554, 1626, 2061, +2554, 1626, 2062, +2554, 1626, 2064, +2554, 1626, 2066, +2554, 1626, 2069, +2554, 1626, 2073, +2554, 1626, 2079, +2554, 1626, 2086, +2554, 1625, 2095, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1599, 2135, +2556, 1567, 2169, +2555, 1613, 2217, +2557, 1692, 2270, +2564, 1695, 2342, +2565, 1768, 2409, +2587, 1844, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1638, 2061, +2554, 1638, 2061, +2554, 1636, 2061, +2554, 1634, 2061, +2554, 1631, 2061, +2554, 1628, 2062, +2554, 1628, 2063, +2554, 1628, 2066, +2554, 1628, 2069, +2554, 1628, 2073, +2554, 1628, 2079, +2554, 1628, 2086, +2554, 1626, 2095, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1605, 2135, +2556, 1572, 2169, +2555, 1616, 2217, +2557, 1693, 2270, +2564, 1696, 2342, +2565, 1771, 2409, +2587, 1847, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2555, 1645, 2062, +2555, 1644, 2062, +2555, 1643, 2062, +2555, 1641, 2062, +2555, 1638, 2062, +2555, 1635, 2063, +2555, 1631, 2063, +2555, 1631, 2066, +2555, 1631, 2069, +2555, 1631, 2073, +2555, 1631, 2078, +2555, 1631, 2085, +2555, 1628, 2094, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1612, 2136, +2556, 1580, 2169, +2554, 1619, 2217, +2558, 1694, 2270, +2564, 1698, 2342, +2565, 1775, 2409, +2587, 1852, 2492, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2555, 1654, 2063, +2555, 1653, 2063, +2555, 1651, 2063, +2555, 1650, 2063, +2555, 1647, 2063, +2555, 1644, 2064, +2555, 1640, 2064, +2555, 1633, 2065, +2555, 1633, 2068, +2555, 1633, 2072, +2555, 1633, 2078, +2555, 1633, 2085, +2555, 1631, 2094, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1621, 2137, +2557, 1590, 2169, +2554, 1624, 2217, +2558, 1695, 2270, +2564, 1701, 2342, +2565, 1781, 2409, +2588, 1857, 2493, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2556, 1665, 2064, +2556, 1664, 2065, +2556, 1663, 2065, +2556, 1661, 2065, +2556, 1659, 2065, +2556, 1655, 2066, +2556, 1651, 2066, +2556, 1646, 2066, +2556, 1638, 2067, +2556, 1638, 2071, +2556, 1638, 2077, +2556, 1638, 2084, +2556, 1636, 2093, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1633, 2138, +2557, 1603, 2169, +2554, 1630, 2217, +2558, 1697, 2271, +2564, 1704, 2342, +2565, 1788, 2409, +2588, 1860, 2493, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2556, 1680, 2066, +2556, 1679, 2067, +2556, 1678, 2067, +2556, 1676, 2067, +2556, 1674, 2067, +2556, 1671, 2068, +2556, 1667, 2068, +2556, 1661, 2069, +2556, 1653, 2069, +2556, 1643, 2070, +2556, 1643, 2076, +2556, 1643, 2083, +2556, 1641, 2092, +2554, 1624, 2101, +2554, 1621, 2110, +2557, 1649, 2140, +2557, 1620, 2170, +2554, 1638, 2217, +2558, 1699, 2271, +2565, 1709, 2342, +2566, 1798, 2409, +2589, 1863, 2493, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2558, 1699, 2069, +2558, 1698, 2069, +2558, 1697, 2070, +2558, 1695, 2070, +2558, 1693, 2070, +2558, 1690, 2070, +2558, 1686, 2071, +2558, 1681, 2071, +2558, 1674, 2072, +2558, 1663, 2073, +2558, 1650, 2074, +2558, 1650, 2082, +2557, 1648, 2091, +2555, 1631, 2100, +2554, 1621, 2110, +2557, 1657, 2141, +2558, 1642, 2173, +2554, 1658, 2217, +2559, 1702, 2273, +2565, 1715, 2342, +2566, 1810, 2409, +2589, 1868, 2493, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2559, 1723, 2073, +2559, 1723, 2073, +2559, 1722, 2073, +2559, 1720, 2073, +2559, 1718, 2074, +2559, 1715, 2074, +2559, 1711, 2074, +2559, 1706, 2075, +2559, 1699, 2076, +2559, 1690, 2077, +2559, 1677, 2078, +2559, 1659, 2080, +2558, 1657, 2089, +2556, 1641, 2098, +2554, 1621, 2110, +2557, 1657, 2141, +2558, 1669, 2176, +2555, 1684, 2217, +2560, 1706, 2274, +2566, 1723, 2342, +2567, 1816, 2409, +2591, 1873, 2493, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2560, 1754, 2078, +2560, 1754, 2078, +2560, 1753, 2078, +2560, 1752, 2079, +2560, 1750, 2079, +2560, 1747, 2079, +2560, 1744, 2080, +2560, 1739, 2080, +2560, 1732, 2081, +2560, 1724, 2082, +2560, 1712, 2083, +2560, 1695, 2085, +2560, 1674, 2088, +2558, 1658, 2097, +2555, 1635, 2110, +2557, 1661, 2141, +2559, 1703, 2179, +2556, 1716, 2217, +2560, 1716, 2275, +2566, 1739, 2342, +2568, 1818, 2408, +2592, 1880, 2493, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2562, 1761, 2078, +2562, 1761, 2078, +2562, 1761, 2079, +2562, 1762, 2080, +2562, 1763, 2080, +2562, 1765, 2082, +2562, 1766, 2084, +2562, 1769, 2086, +2562, 1772, 2089, +2563, 1771, 2091, +2563, 1760, 2093, +2563, 1745, 2094, +2562, 1727, 2097, +2561, 1712, 2103, +2558, 1692, 2116, +2556, 1693, 2138, +2560, 1738, 2181, +2560, 1744, 2217, +2561, 1744, 2275, +2566, 1785, 2340, +2571, 1835, 2406, +2592, 1893, 2492, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2563, 1769, 2078, +2563, 1769, 2078, +2563, 1770, 2079, +2563, 1771, 2080, +2563, 1772, 2080, +2563, 1773, 2082, +2564, 1775, 2084, +2564, 1777, 2086, +2564, 1780, 2089, +2564, 1784, 2093, +2565, 1789, 2098, +2565, 1796, 2105, +2566, 1789, 2110, +2564, 1776, 2116, +2563, 1758, 2124, +2559, 1753, 2143, +2558, 1773, 2177, +2563, 1787, 2220, +2563, 1779, 2275, +2566, 1840, 2337, +2576, 1860, 2406, +2591, 1925, 2491, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2566, 1822, 2077, +2566, 1822, 2078, +2566, 1822, 2078, +2566, 1822, 2078, +2566, 1822, 2079, +2566, 1822, 2079, +2566, 1822, 2080, +2566, 1822, 2081, +2566, 1822, 2083, +2566, 1822, 2085, +2567, 1824, 2089, +2568, 1831, 2096, +2568, 1839, 2106, +2570, 1844, 2121, +2568, 1834, 2131, +2568, 1813, 2145, +2564, 1813, 2176, +2565, 1838, 2221, +2568, 1838, 2272, +2573, 1888, 2337, +2580, 1896, 2406, +2599, 1967, 2492, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2573, 1894, 2080, +2573, 1894, 2081, +2573, 1895, 2081, +2573, 1896, 2081, +2573, 1897, 2082, +2574, 1898, 2082, +2574, 1900, 2083, +2575, 1903, 2084, +2575, 1906, 2086, +2575, 1906, 2088, +2575, 1906, 2090, +2575, 1906, 2094, +2575, 1906, 2099, +2575, 1907, 2109, +2576, 1913, 2129, +2577, 1915, 2152, +2578, 1893, 2171, +2576, 1899, 2221, +2578, 1919, 2273, +2580, 1949, 2338, +2587, 1961, 2408, +2611, 2008, 2495, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2588, 1996, 2083, +2588, 1997, 2083, +2588, 1997, 2084, +2588, 1997, 2085, +2588, 1997, 2086, +2588, 1998, 2087, +2588, 1998, 2088, +2588, 1999, 2091, +2588, 2000, 2093, +2588, 2001, 2098, +2588, 2005, 2100, +2589, 2012, 2104, +2591, 2018, 2108, +2588, 2010, 2114, +2588, 2009, 2126, +2589, 2014, 2149, +2590, 2016, 2184, +2591, 2003, 2214, +2591, 2019, 2275, +2595, 2044, 2342, +2604, 2072, 2411, +2625, 2108, 2494, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2625, 2149, 2111, +2624, 2149, 2111, +2624, 2149, 2111, +2624, 2149, 2111, +2624, 2148, 2111, +2624, 2148, 2111, +2623, 2147, 2111, +2623, 2146, 2111, +2622, 2145, 2111, +2621, 2143, 2111, +2620, 2141, 2111, +2618, 2137, 2111, +2617, 2136, 2114, +2617, 2144, 2126, +2617, 2155, 2141, +2619, 2157, 2164, +2623, 2160, 2195, +2624, 2165, 2231, +2619, 2165, 2275, +2633, 2187, 2352, +2638, 2190, 2417, +2660, 2223, 2503, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2670, 2315, 2112, +2671, 2315, 2112, +2671, 2315, 2112, +2671, 2315, 2111, +2671, 2316, 2111, +2672, 2316, 2111, +2672, 2316, 2111, +2673, 2317, 2110, +2674, 2318, 2109, +2675, 2319, 2108, +2677, 2321, 2107, +2680, 2323, 2105, +2682, 2325, 2106, +2681, 2325, 2118, +2680, 2325, 2133, +2678, 2328, 2149, +2677, 2328, 2176, +2677, 2325, 2215, +2687, 2335, 2275, +2689, 2335, 2316, +2695, 2346, 2391, +2724, 2369, 2462, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2775, 2531, 1744, +2775, 2531, 1745, +2775, 2531, 1747, +2775, 2531, 1750, +2776, 2532, 1753, +2776, 2532, 1758, +2776, 2533, 1764, +2776, 2533, 1772, +2777, 2534, 1782, +2778, 2535, 1796, +2778, 2536, 1813, +2778, 2537, 1825, +2777, 2535, 1833, +2776, 2530, 1839, +2776, 2528, 1859, +2778, 2535, 1929, +2779, 2534, 1991, +2780, 2535, 2071, +2782, 2538, 2158, +2784, 2536, 2248, +2791, 2552, 2360, +2803, 2569, 2485, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2826, 2762, 2506, +2826, 2762, 2506, +2826, 2762, 2505, +2826, 2762, 2505, +2826, 2762, 2505, +2826, 2762, 2505, +2826, 2761, 2505, +2826, 2761, 2505, +2826, 2761, 2505, +2826, 2761, 2506, +2826, 2761, 2507, +2826, 2761, 2509, +2826, 2761, 2510, +2826, 2760, 2508, +2826, 2760, 2508, +2826, 2762, 2520, +2826, 2764, 2535, +2826, 2763, 2548, +2826, 2763, 2571, +2826, 2767, 2613, +2826, 2769, 2662, +2826, 2779, 2732, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2554, 1623, 2059, +2554, 1623, 2059, +2554, 1623, 2060, +2554, 1623, 2060, +2554, 1623, 2061, +2554, 1623, 2063, +2554, 1623, 2065, +2554, 1623, 2067, +2554, 1623, 2070, +2554, 1623, 2074, +2554, 1623, 2080, +2554, 1623, 2087, +2554, 1621, 2096, +2554, 1621, 2102, +2554, 1621, 2110, +2555, 1588, 2133, +2556, 1555, 2169, +2555, 1608, 2217, +2557, 1691, 2269, +2563, 1692, 2342, +2564, 1761, 2409, +2587, 1838, 2491, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1625, 2059, +2554, 1624, 2059, +2554, 1624, 2060, +2554, 1624, 2060, +2554, 1624, 2061, +2554, 1624, 2063, +2554, 1624, 2064, +2554, 1624, 2067, +2554, 1624, 2070, +2554, 1624, 2074, +2554, 1624, 2080, +2554, 1624, 2087, +2554, 1621, 2096, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1590, 2134, +2556, 1556, 2169, +2555, 1609, 2217, +2557, 1691, 2269, +2563, 1692, 2342, +2564, 1762, 2409, +2587, 1839, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1627, 2059, +2554, 1626, 2059, +2554, 1625, 2060, +2554, 1625, 2060, +2554, 1625, 2061, +2554, 1625, 2063, +2554, 1625, 2064, +2554, 1625, 2067, +2554, 1625, 2070, +2554, 1625, 2074, +2554, 1625, 2079, +2554, 1625, 2086, +2554, 1622, 2096, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1592, 2134, +2556, 1559, 2169, +2555, 1610, 2217, +2557, 1691, 2269, +2564, 1693, 2342, +2564, 1764, 2409, +2587, 1840, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1630, 2060, +2554, 1629, 2060, +2554, 1627, 2060, +2554, 1625, 2060, +2554, 1625, 2061, +2554, 1625, 2062, +2554, 1625, 2064, +2554, 1625, 2066, +2554, 1625, 2070, +2554, 1625, 2074, +2554, 1625, 2079, +2554, 1625, 2086, +2554, 1623, 2095, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1595, 2134, +2556, 1562, 2169, +2555, 1611, 2217, +2557, 1691, 2270, +2564, 1694, 2342, +2564, 1765, 2409, +2587, 1842, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1633, 2060, +2554, 1632, 2060, +2554, 1631, 2060, +2554, 1629, 2060, +2554, 1626, 2061, +2554, 1626, 2062, +2554, 1626, 2064, +2554, 1626, 2066, +2554, 1626, 2069, +2554, 1626, 2073, +2554, 1626, 2079, +2554, 1626, 2086, +2554, 1625, 2095, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1599, 2135, +2556, 1567, 2169, +2555, 1613, 2217, +2557, 1692, 2270, +2564, 1695, 2342, +2565, 1768, 2409, +2587, 1844, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1638, 2061, +2554, 1638, 2061, +2554, 1636, 2061, +2554, 1634, 2061, +2554, 1631, 2061, +2554, 1628, 2062, +2554, 1628, 2063, +2554, 1628, 2066, +2554, 1628, 2069, +2554, 1628, 2073, +2554, 1628, 2079, +2554, 1628, 2086, +2554, 1626, 2095, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1605, 2135, +2556, 1572, 2169, +2555, 1616, 2217, +2557, 1693, 2270, +2564, 1696, 2342, +2565, 1771, 2409, +2587, 1847, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2555, 1645, 2062, +2555, 1644, 2062, +2555, 1643, 2062, +2555, 1641, 2062, +2555, 1638, 2062, +2555, 1635, 2063, +2555, 1631, 2063, +2555, 1631, 2066, +2555, 1631, 2069, +2555, 1631, 2073, +2555, 1631, 2078, +2555, 1631, 2085, +2555, 1628, 2094, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1612, 2136, +2556, 1580, 2169, +2554, 1619, 2217, +2558, 1694, 2270, +2564, 1698, 2342, +2565, 1775, 2409, +2587, 1852, 2492, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2555, 1654, 2063, +2555, 1653, 2063, +2555, 1651, 2063, +2555, 1650, 2063, +2555, 1647, 2063, +2555, 1644, 2064, +2555, 1640, 2064, +2555, 1633, 2065, +2555, 1633, 2068, +2555, 1633, 2072, +2555, 1633, 2078, +2555, 1633, 2085, +2555, 1631, 2094, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1621, 2137, +2557, 1590, 2169, +2554, 1624, 2217, +2558, 1695, 2270, +2564, 1701, 2342, +2565, 1781, 2409, +2588, 1857, 2493, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2556, 1665, 2064, +2556, 1664, 2065, +2556, 1663, 2065, +2556, 1661, 2065, +2556, 1659, 2065, +2556, 1655, 2066, +2556, 1651, 2066, +2556, 1646, 2066, +2556, 1638, 2067, +2556, 1638, 2071, +2556, 1638, 2077, +2556, 1638, 2084, +2556, 1636, 2093, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1633, 2138, +2557, 1603, 2169, +2554, 1630, 2217, +2558, 1697, 2271, +2564, 1704, 2342, +2565, 1788, 2409, +2588, 1860, 2493, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2556, 1680, 2066, +2556, 1679, 2067, +2556, 1678, 2067, +2556, 1676, 2067, +2556, 1674, 2067, +2556, 1671, 2068, +2556, 1667, 2068, +2556, 1661, 2069, +2556, 1653, 2069, +2556, 1643, 2070, +2556, 1643, 2076, +2556, 1643, 2083, +2556, 1641, 2092, +2554, 1624, 2101, +2554, 1621, 2110, +2557, 1649, 2140, +2557, 1620, 2170, +2554, 1638, 2217, +2558, 1699, 2271, +2565, 1709, 2342, +2566, 1798, 2409, +2589, 1863, 2493, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2558, 1699, 2069, +2558, 1698, 2069, +2558, 1697, 2070, +2558, 1695, 2070, +2558, 1693, 2070, +2558, 1690, 2070, +2558, 1686, 2071, +2558, 1681, 2071, +2558, 1674, 2072, +2558, 1663, 2073, +2558, 1650, 2074, +2558, 1650, 2082, +2557, 1648, 2091, +2555, 1631, 2100, +2554, 1621, 2110, +2557, 1657, 2141, +2558, 1642, 2173, +2554, 1658, 2217, +2559, 1702, 2273, +2565, 1715, 2342, +2566, 1810, 2409, +2589, 1868, 2493, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2559, 1723, 2073, +2559, 1723, 2073, +2559, 1722, 2073, +2559, 1720, 2073, +2559, 1718, 2074, +2559, 1715, 2074, +2559, 1711, 2074, +2559, 1706, 2075, +2559, 1699, 2076, +2559, 1690, 2077, +2559, 1677, 2078, +2559, 1659, 2080, +2558, 1657, 2089, +2556, 1641, 2098, +2554, 1621, 2110, +2557, 1657, 2141, +2558, 1669, 2176, +2555, 1684, 2217, +2560, 1706, 2274, +2566, 1723, 2342, +2567, 1816, 2409, +2591, 1873, 2493, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2560, 1754, 2078, +2560, 1754, 2078, +2560, 1753, 2078, +2560, 1752, 2079, +2560, 1750, 2079, +2560, 1747, 2079, +2560, 1744, 2080, +2560, 1739, 2080, +2560, 1732, 2081, +2560, 1724, 2082, +2560, 1712, 2083, +2560, 1695, 2085, +2560, 1674, 2088, +2558, 1658, 2097, +2555, 1635, 2110, +2557, 1661, 2141, +2559, 1703, 2179, +2556, 1716, 2217, +2560, 1716, 2275, +2566, 1739, 2342, +2568, 1818, 2408, +2592, 1880, 2493, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2562, 1761, 2078, +2562, 1761, 2078, +2562, 1761, 2079, +2562, 1762, 2080, +2562, 1763, 2080, +2562, 1765, 2082, +2562, 1766, 2084, +2562, 1769, 2086, +2562, 1772, 2089, +2563, 1771, 2091, +2563, 1760, 2093, +2563, 1745, 2094, +2562, 1727, 2097, +2561, 1712, 2103, +2558, 1692, 2116, +2556, 1693, 2138, +2560, 1738, 2181, +2560, 1744, 2217, +2561, 1744, 2275, +2566, 1785, 2340, +2571, 1835, 2406, +2592, 1893, 2492, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2563, 1769, 2078, +2563, 1769, 2078, +2563, 1770, 2079, +2563, 1771, 2080, +2563, 1772, 2080, +2563, 1773, 2082, +2564, 1775, 2084, +2564, 1777, 2086, +2564, 1780, 2089, +2564, 1784, 2093, +2565, 1789, 2098, +2565, 1796, 2105, +2566, 1789, 2110, +2564, 1776, 2116, +2563, 1758, 2124, +2559, 1753, 2143, +2558, 1773, 2177, +2563, 1787, 2220, +2563, 1779, 2275, +2566, 1840, 2337, +2576, 1860, 2406, +2591, 1925, 2491, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2566, 1822, 2077, +2566, 1822, 2078, +2566, 1822, 2078, +2566, 1822, 2078, +2566, 1822, 2079, +2566, 1822, 2079, +2566, 1822, 2080, +2566, 1822, 2081, +2566, 1822, 2083, +2566, 1822, 2085, +2567, 1824, 2089, +2568, 1831, 2096, +2568, 1839, 2106, +2570, 1844, 2121, +2568, 1834, 2131, +2568, 1813, 2145, +2564, 1813, 2176, +2565, 1838, 2221, +2568, 1838, 2272, +2573, 1888, 2337, +2580, 1896, 2406, +2599, 1967, 2492, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2573, 1894, 2080, +2573, 1894, 2081, +2573, 1895, 2081, +2573, 1896, 2081, +2573, 1897, 2082, +2574, 1898, 2082, +2574, 1900, 2083, +2575, 1903, 2084, +2575, 1906, 2086, +2575, 1906, 2088, +2575, 1906, 2090, +2575, 1906, 2094, +2575, 1906, 2099, +2575, 1907, 2109, +2576, 1913, 2129, +2577, 1915, 2152, +2578, 1893, 2171, +2576, 1899, 2221, +2578, 1919, 2273, +2580, 1949, 2338, +2587, 1961, 2408, +2611, 2008, 2495, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2588, 1996, 2083, +2588, 1997, 2083, +2588, 1997, 2084, +2588, 1997, 2085, +2588, 1997, 2086, +2588, 1998, 2087, +2588, 1998, 2088, +2588, 1999, 2091, +2588, 2000, 2093, +2588, 2001, 2098, +2588, 2005, 2100, +2589, 2012, 2104, +2591, 2018, 2108, +2588, 2010, 2114, +2588, 2009, 2126, +2589, 2014, 2149, +2590, 2016, 2184, +2591, 2003, 2214, +2591, 2019, 2275, +2595, 2044, 2342, +2604, 2072, 2411, +2625, 2108, 2494, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2625, 2149, 2111, +2624, 2149, 2111, +2624, 2149, 2111, +2624, 2149, 2111, +2624, 2148, 2111, +2624, 2148, 2111, +2623, 2147, 2111, +2623, 2146, 2111, +2622, 2145, 2111, +2621, 2143, 2111, +2620, 2141, 2111, +2618, 2137, 2111, +2617, 2136, 2114, +2617, 2144, 2126, +2617, 2155, 2141, +2619, 2157, 2164, +2623, 2160, 2195, +2624, 2165, 2231, +2619, 2165, 2275, +2633, 2187, 2352, +2638, 2190, 2417, +2660, 2223, 2503, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2670, 2315, 2112, +2671, 2315, 2112, +2671, 2315, 2112, +2671, 2315, 2111, +2671, 2316, 2111, +2672, 2316, 2111, +2672, 2316, 2111, +2673, 2317, 2110, +2674, 2318, 2109, +2675, 2319, 2108, +2677, 2321, 2107, +2680, 2323, 2105, +2682, 2325, 2106, +2681, 2325, 2118, +2680, 2325, 2133, +2678, 2328, 2149, +2677, 2328, 2176, +2677, 2325, 2215, +2687, 2335, 2275, +2689, 2335, 2316, +2695, 2346, 2391, +2724, 2369, 2462, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2775, 2531, 1744, +2775, 2531, 1745, +2775, 2531, 1747, +2775, 2531, 1750, +2776, 2532, 1753, +2776, 2532, 1758, +2776, 2533, 1764, +2776, 2533, 1772, +2777, 2534, 1782, +2778, 2535, 1796, +2778, 2536, 1813, +2778, 2537, 1825, +2777, 2535, 1833, +2776, 2530, 1839, +2776, 2528, 1859, +2778, 2535, 1929, +2779, 2534, 1991, +2780, 2535, 2071, +2782, 2538, 2158, +2784, 2536, 2248, +2791, 2552, 2360, +2803, 2569, 2485, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2826, 2762, 2506, +2826, 2762, 2506, +2826, 2762, 2505, +2826, 2762, 2505, +2826, 2762, 2505, +2826, 2762, 2505, +2826, 2761, 2505, +2826, 2761, 2505, +2826, 2761, 2505, +2826, 2761, 2506, +2826, 2761, 2507, +2826, 2761, 2509, +2826, 2761, 2510, +2826, 2760, 2508, +2826, 2760, 2508, +2826, 2762, 2520, +2826, 2764, 2535, +2826, 2763, 2548, +2826, 2763, 2571, +2826, 2767, 2613, +2826, 2769, 2662, +2826, 2779, 2732, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2554, 1623, 2059, +2554, 1623, 2059, +2554, 1623, 2060, +2554, 1623, 2060, +2554, 1623, 2061, +2554, 1623, 2063, +2554, 1623, 2065, +2554, 1623, 2067, +2554, 1623, 2070, +2554, 1623, 2074, +2554, 1623, 2080, +2554, 1623, 2087, +2554, 1621, 2096, +2554, 1621, 2102, +2554, 1621, 2110, +2555, 1588, 2133, +2556, 1555, 2169, +2555, 1608, 2217, +2557, 1691, 2269, +2563, 1692, 2342, +2564, 1761, 2409, +2587, 1838, 2491, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1625, 2059, +2554, 1624, 2059, +2554, 1624, 2060, +2554, 1624, 2060, +2554, 1624, 2061, +2554, 1624, 2063, +2554, 1624, 2064, +2554, 1624, 2067, +2554, 1624, 2070, +2554, 1624, 2074, +2554, 1624, 2080, +2554, 1624, 2087, +2554, 1621, 2096, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1590, 2134, +2556, 1556, 2169, +2555, 1609, 2217, +2557, 1691, 2269, +2563, 1692, 2342, +2564, 1762, 2409, +2587, 1839, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1627, 2059, +2554, 1626, 2059, +2554, 1625, 2060, +2554, 1625, 2060, +2554, 1625, 2061, +2554, 1625, 2063, +2554, 1625, 2064, +2554, 1625, 2067, +2554, 1625, 2070, +2554, 1625, 2074, +2554, 1625, 2079, +2554, 1625, 2086, +2554, 1622, 2096, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1592, 2134, +2556, 1559, 2169, +2555, 1610, 2217, +2557, 1691, 2269, +2564, 1693, 2342, +2564, 1764, 2409, +2587, 1840, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1630, 2060, +2554, 1629, 2060, +2554, 1627, 2060, +2554, 1625, 2060, +2554, 1625, 2061, +2554, 1625, 2062, +2554, 1625, 2064, +2554, 1625, 2066, +2554, 1625, 2070, +2554, 1625, 2074, +2554, 1625, 2079, +2554, 1625, 2086, +2554, 1623, 2095, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1595, 2134, +2556, 1562, 2169, +2555, 1611, 2217, +2557, 1691, 2270, +2564, 1694, 2342, +2564, 1765, 2409, +2587, 1842, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1633, 2060, +2554, 1632, 2060, +2554, 1631, 2060, +2554, 1629, 2060, +2554, 1626, 2061, +2554, 1626, 2062, +2554, 1626, 2064, +2554, 1626, 2066, +2554, 1626, 2069, +2554, 1626, 2073, +2554, 1626, 2079, +2554, 1626, 2086, +2554, 1625, 2095, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1599, 2135, +2556, 1567, 2169, +2555, 1613, 2217, +2557, 1692, 2270, +2564, 1695, 2342, +2565, 1768, 2409, +2587, 1844, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1638, 2061, +2554, 1638, 2061, +2554, 1636, 2061, +2554, 1634, 2061, +2554, 1631, 2061, +2554, 1628, 2062, +2554, 1628, 2063, +2554, 1628, 2066, +2554, 1628, 2069, +2554, 1628, 2073, +2554, 1628, 2079, +2554, 1628, 2086, +2554, 1626, 2095, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1605, 2135, +2556, 1572, 2169, +2555, 1616, 2217, +2557, 1693, 2270, +2564, 1696, 2342, +2565, 1771, 2409, +2587, 1847, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2555, 1645, 2062, +2555, 1644, 2062, +2555, 1643, 2062, +2555, 1641, 2062, +2555, 1638, 2062, +2555, 1635, 2063, +2555, 1631, 2063, +2555, 1631, 2066, +2555, 1631, 2069, +2555, 1631, 2073, +2555, 1631, 2078, +2555, 1631, 2085, +2555, 1628, 2094, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1612, 2136, +2556, 1580, 2169, +2554, 1619, 2217, +2558, 1694, 2270, +2564, 1698, 2342, +2565, 1775, 2409, +2587, 1852, 2492, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2555, 1654, 2063, +2555, 1653, 2063, +2555, 1651, 2063, +2555, 1650, 2063, +2555, 1647, 2063, +2555, 1644, 2064, +2555, 1640, 2064, +2555, 1633, 2065, +2555, 1633, 2068, +2555, 1633, 2072, +2555, 1633, 2078, +2555, 1633, 2085, +2555, 1631, 2094, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1621, 2137, +2557, 1590, 2169, +2554, 1624, 2217, +2558, 1695, 2270, +2564, 1701, 2342, +2565, 1781, 2409, +2588, 1857, 2493, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2556, 1665, 2064, +2556, 1664, 2065, +2556, 1663, 2065, +2556, 1661, 2065, +2556, 1659, 2065, +2556, 1655, 2066, +2556, 1651, 2066, +2556, 1646, 2066, +2556, 1638, 2067, +2556, 1638, 2071, +2556, 1638, 2077, +2556, 1638, 2084, +2556, 1636, 2093, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1633, 2138, +2557, 1603, 2169, +2554, 1630, 2217, +2558, 1697, 2271, +2564, 1704, 2342, +2565, 1788, 2409, +2588, 1860, 2493, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2556, 1680, 2066, +2556, 1679, 2067, +2556, 1678, 2067, +2556, 1676, 2067, +2556, 1674, 2067, +2556, 1671, 2068, +2556, 1667, 2068, +2556, 1661, 2069, +2556, 1653, 2069, +2556, 1643, 2070, +2556, 1643, 2076, +2556, 1643, 2083, +2556, 1641, 2092, +2554, 1624, 2101, +2554, 1621, 2110, +2557, 1649, 2140, +2557, 1620, 2170, +2554, 1638, 2217, +2558, 1699, 2271, +2565, 1709, 2342, +2566, 1798, 2409, +2589, 1863, 2493, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2558, 1699, 2069, +2558, 1698, 2069, +2558, 1697, 2070, +2558, 1695, 2070, +2558, 1693, 2070, +2558, 1690, 2070, +2558, 1686, 2071, +2558, 1681, 2071, +2558, 1674, 2072, +2558, 1663, 2073, +2558, 1650, 2074, +2558, 1650, 2082, +2557, 1648, 2091, +2555, 1631, 2100, +2554, 1621, 2110, +2557, 1657, 2141, +2558, 1642, 2173, +2554, 1658, 2217, +2559, 1702, 2273, +2565, 1715, 2342, +2566, 1810, 2409, +2589, 1868, 2493, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2559, 1723, 2073, +2559, 1723, 2073, +2559, 1722, 2073, +2559, 1720, 2073, +2559, 1718, 2074, +2559, 1715, 2074, +2559, 1711, 2074, +2559, 1706, 2075, +2559, 1699, 2076, +2559, 1690, 2077, +2559, 1677, 2078, +2559, 1659, 2080, +2558, 1657, 2089, +2556, 1641, 2098, +2554, 1621, 2110, +2557, 1657, 2141, +2558, 1669, 2176, +2555, 1684, 2217, +2560, 1706, 2274, +2566, 1723, 2342, +2567, 1816, 2409, +2591, 1873, 2493, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2560, 1754, 2078, +2560, 1754, 2078, +2560, 1753, 2078, +2560, 1752, 2079, +2560, 1750, 2079, +2560, 1747, 2079, +2560, 1744, 2080, +2560, 1739, 2080, +2560, 1732, 2081, +2560, 1724, 2082, +2560, 1712, 2083, +2560, 1695, 2085, +2560, 1674, 2088, +2558, 1658, 2097, +2555, 1635, 2110, +2557, 1661, 2141, +2559, 1703, 2179, +2556, 1716, 2217, +2560, 1716, 2275, +2566, 1739, 2342, +2568, 1818, 2408, +2592, 1880, 2493, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2562, 1761, 2078, +2562, 1761, 2078, +2562, 1761, 2079, +2562, 1762, 2080, +2562, 1763, 2080, +2562, 1765, 2082, +2562, 1766, 2084, +2562, 1769, 2086, +2562, 1772, 2089, +2563, 1771, 2091, +2563, 1760, 2093, +2563, 1745, 2094, +2562, 1727, 2097, +2561, 1712, 2103, +2558, 1692, 2116, +2556, 1693, 2138, +2560, 1738, 2181, +2560, 1744, 2217, +2561, 1744, 2275, +2566, 1785, 2340, +2571, 1835, 2406, +2592, 1893, 2492, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2563, 1769, 2078, +2563, 1769, 2078, +2563, 1770, 2079, +2563, 1771, 2080, +2563, 1772, 2080, +2563, 1773, 2082, +2564, 1775, 2084, +2564, 1777, 2086, +2564, 1780, 2089, +2564, 1784, 2093, +2565, 1789, 2098, +2565, 1796, 2105, +2566, 1789, 2110, +2564, 1776, 2116, +2563, 1758, 2124, +2559, 1753, 2143, +2558, 1773, 2177, +2563, 1787, 2220, +2563, 1779, 2275, +2566, 1840, 2337, +2576, 1860, 2406, +2591, 1925, 2491, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2566, 1822, 2077, +2566, 1822, 2078, +2566, 1822, 2078, +2566, 1822, 2078, +2566, 1822, 2079, +2566, 1822, 2079, +2566, 1822, 2080, +2566, 1822, 2081, +2566, 1822, 2083, +2566, 1822, 2085, +2567, 1824, 2089, +2568, 1831, 2096, +2568, 1839, 2106, +2570, 1844, 2121, +2568, 1834, 2131, +2568, 1813, 2145, +2564, 1813, 2176, +2565, 1838, 2221, +2568, 1838, 2272, +2573, 1888, 2337, +2580, 1896, 2406, +2599, 1967, 2492, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2573, 1894, 2080, +2573, 1894, 2081, +2573, 1895, 2081, +2573, 1896, 2081, +2573, 1897, 2082, +2574, 1898, 2082, +2574, 1900, 2083, +2575, 1903, 2084, +2575, 1906, 2086, +2575, 1906, 2088, +2575, 1906, 2090, +2575, 1906, 2094, +2575, 1906, 2099, +2575, 1907, 2109, +2576, 1913, 2129, +2577, 1915, 2152, +2578, 1893, 2171, +2576, 1899, 2221, +2578, 1919, 2273, +2580, 1949, 2338, +2587, 1961, 2408, +2611, 2008, 2495, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2588, 1996, 2083, +2588, 1997, 2083, +2588, 1997, 2084, +2588, 1997, 2085, +2588, 1997, 2086, +2588, 1998, 2087, +2588, 1998, 2088, +2588, 1999, 2091, +2588, 2000, 2093, +2588, 2001, 2098, +2588, 2005, 2100, +2589, 2012, 2104, +2591, 2018, 2108, +2588, 2010, 2114, +2588, 2009, 2126, +2589, 2014, 2149, +2590, 2016, 2184, +2591, 2003, 2214, +2591, 2019, 2275, +2595, 2044, 2342, +2604, 2072, 2411, +2625, 2108, 2494, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2625, 2149, 2111, +2624, 2149, 2111, +2624, 2149, 2111, +2624, 2149, 2111, +2624, 2148, 2111, +2624, 2148, 2111, +2623, 2147, 2111, +2623, 2146, 2111, +2622, 2145, 2111, +2621, 2143, 2111, +2620, 2141, 2111, +2618, 2137, 2111, +2617, 2136, 2114, +2617, 2144, 2126, +2617, 2155, 2141, +2619, 2157, 2164, +2623, 2160, 2195, +2624, 2165, 2231, +2619, 2165, 2275, +2633, 2187, 2352, +2638, 2190, 2417, +2660, 2223, 2503, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2670, 2315, 2112, +2671, 2315, 2112, +2671, 2315, 2112, +2671, 2315, 2111, +2671, 2316, 2111, +2672, 2316, 2111, +2672, 2316, 2111, +2673, 2317, 2110, +2674, 2318, 2109, +2675, 2319, 2108, +2677, 2321, 2107, +2680, 2323, 2105, +2682, 2325, 2106, +2681, 2325, 2118, +2680, 2325, 2133, +2678, 2328, 2149, +2677, 2328, 2176, +2677, 2325, 2215, +2687, 2335, 2275, +2689, 2335, 2316, +2695, 2346, 2391, +2724, 2369, 2462, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2775, 2531, 1744, +2775, 2531, 1745, +2775, 2531, 1747, +2775, 2531, 1750, +2776, 2532, 1753, +2776, 2532, 1758, +2776, 2533, 1764, +2776, 2533, 1772, +2777, 2534, 1782, +2778, 2535, 1796, +2778, 2536, 1813, +2778, 2537, 1825, +2777, 2535, 1833, +2776, 2530, 1839, +2776, 2528, 1859, +2778, 2535, 1929, +2779, 2534, 1991, +2780, 2535, 2071, +2782, 2538, 2158, +2784, 2536, 2248, +2791, 2552, 2360, +2803, 2569, 2485, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2826, 2762, 2506, +2826, 2762, 2506, +2826, 2762, 2505, +2826, 2762, 2505, +2826, 2762, 2505, +2826, 2762, 2505, +2826, 2761, 2505, +2826, 2761, 2505, +2826, 2761, 2505, +2826, 2761, 2506, +2826, 2761, 2507, +2826, 2761, 2509, +2826, 2761, 2510, +2826, 2760, 2508, +2826, 2760, 2508, +2826, 2762, 2520, +2826, 2764, 2535, +2826, 2763, 2548, +2826, 2763, 2571, +2826, 2767, 2613, +2826, 2769, 2662, +2826, 2779, 2732, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819] + } +} \ No newline at end of file diff --git a/Gems/Atom/Feature/Common/Assets/ColorGrading/TestData/Photoshop/inv-Log2-48nits/test_hue-sat_32_LUT.azasset b/Gems/Atom/Feature/Common/Assets/ColorGrading/TestData/Photoshop/inv-Log2-48nits/test_hue-sat_32_LUT.azasset new file mode 100644 index 0000000000..82fbee2eee --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/ColorGrading/TestData/Photoshop/inv-Log2-48nits/test_hue-sat_32_LUT.azasset @@ -0,0 +1,32777 @@ +{ + "Type": "JsonSerialization", + "Version": 1, + "ClassName": "LookupTableAsset", + "ClassData": { + "Name": "LookupTable", + "Intervals": [0, 33, 66, 99, 132, 165, 198, 231, 264, 297, 330, 363, 396, 429, 462, 495, 528, 561, 594, 627, 660, 693, 726, 759, 792, 825, 858, 891, 924, 957, 990, 1023], + "Values": [0, 0, 0, +97, 163, 0, +201, 318, 0, +312, 466, 0, +427, 609, 0, +545, 750, 0, +667, 888, 0, +792, 1025, 0, +918, 1160, 0, +1046, 1295, 0, +1174, 1429, 0, +1304, 1563, 0, +1434, 1696, 0, +1565, 1828, 0, +1696, 1961, 0, +1827, 2094, 0, +1959, 2226, 0, +2090, 2358, 0, +2222, 2491, 0, +2354, 2623, 0, +2486, 2755, 0, +2618, 2887, 0, +2750, 3019, 0, +2882, 3152, 0, +3014, 3284, 0, +3146, 3416, 0, +3278, 3548, 0, +3410, 3680, 0, +3542, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3939, 4095, 0, +163, 0, 97, +163, 42, 0, +318, 300, 0, +419, 466, 0, +512, 609, 0, +613, 750, 0, +719, 888, 0, +832, 1025, 0, +949, 1160, 0, +1069, 1295, 0, +1192, 1429, 0, +1318, 1563, 0, +1444, 1696, 0, +1572, 1828, 0, +1702, 1961, 0, +1831, 2094, 0, +1962, 2226, 0, +2093, 2358, 0, +2224, 2491, 0, +2355, 2623, 0, +2487, 2755, 0, +2619, 2887, 0, +2750, 3019, 0, +2883, 3152, 0, +3014, 3284, 0, +3146, 3416, 0, +3278, 3548, 0, +3410, 3680, 0, +3542, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3939, 4095, 0, +318, 0, 201, +318, 0, 13, +318, 93, 0, +466, 388, 0, +606, 609, 0, +689, 750, 0, +781, 888, 0, +881, 1025, 0, +987, 1160, 0, +1099, 1295, 0, +1215, 1429, 0, +1335, 1563, 0, +1457, 1696, 0, +1582, 1828, 0, +1709, 1961, 0, +1837, 2094, 0, +1966, 2226, 0, +2096, 2358, 0, +2226, 2491, 0, +2357, 2623, 0, +2488, 2755, 0, +2620, 2887, 0, +2751, 3019, 0, +2883, 3152, 0, +3014, 3284, 0, +3147, 3416, 0, +3279, 3548, 0, +3410, 3680, 0, +3543, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3939, 4095, 0, +466, 0, 312, +466, 0, 171, +466, 0, 0, +466, 154, 0, +609, 485, 0, +750, 723, 0, +852, 888, 0, +939, 1025, 0, +1033, 1160, 0, +1135, 1295, 0, +1244, 1429, 0, +1357, 1563, 0, +1475, 1696, 0, +1596, 1828, 0, +1719, 1961, 0, +1845, 2094, 0, +1972, 2226, 0, +2100, 2358, 0, +2230, 2491, 0, +2359, 2623, 0, +2490, 2755, 0, +2621, 2887, 0, +2752, 3019, 0, +2884, 3152, 0, +3015, 3284, 0, +3147, 3416, 0, +3279, 3548, 0, +3411, 3680, 0, +3543, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3939, 4095, 0, +609, 0, 427, +609, 0, 322, +609, 0, 127, +609, 0, 0, +609, 224, 0, +750, 587, 0, +888, 838, 0, +1006, 1025, 0, +1089, 1160, 0, +1181, 1295, 0, +1280, 1429, 0, +1385, 1563, 0, +1496, 1696, 0, +1612, 1828, 0, +1732, 1961, 0, +1855, 2094, 0, +1979, 2226, 0, +2106, 2358, 0, +2234, 2491, 0, +2363, 2623, 0, +2493, 2755, 0, +2623, 2887, 0, +2754, 3019, 0, +2885, 3152, 0, +3016, 3284, 0, +3147, 3416, 0, +3279, 3548, 0, +3411, 3680, 0, +3543, 3812, 0, +3675, 3944, 0, +3807, 4076, 0, +3939, 4095, 0, +750, 0, 545, +750, 0, 467, +750, 0, 334, +750, 0, 59, +750, 0, 0, +750, 304, 0, +888, 697, 0, +1025, 957, 0, +1154, 1160, 0, +1234, 1295, 0, +1323, 1429, 0, +1421, 1563, 0, +1524, 1696, 0, +1634, 1828, 0, +1749, 1961, 0, +1867, 2094, 0, +1989, 2226, 0, +2113, 2358, 0, +2239, 2491, 0, +2367, 2623, 0, +2496, 2755, 0, +2625, 2887, 0, +2755, 3019, 0, +2886, 3152, 0, +3017, 3284, 0, +3148, 3416, 0, +3280, 3548, 0, +3411, 3680, 0, +3543, 3812, 0, +3675, 3944, 0, +3807, 4076, 0, +3939, 4095, 0, +888, 0, 667, +888, 0, 608, +888, 0, 515, +888, 0, 350, +888, 0, 0, +888, 0, 0, +888, 392, 0, +1025, 811, 0, +1160, 1079, 0, +1295, 1292, 0, +1376, 1429, 0, +1463, 1563, 0, +1559, 1696, 0, +1661, 1828, 0, +1770, 1961, 0, +1884, 2094, 0, +2002, 2226, 0, +2123, 2358, 0, +2247, 2491, 0, +2372, 2623, 0, +2500, 2755, 0, +2628, 2887, 0, +2758, 3019, 0, +2888, 3152, 0, +3018, 3284, 0, +3149, 3416, 0, +3280, 3548, 0, +3412, 3680, 0, +3544, 3812, 0, +3675, 3944, 0, +3807, 4076, 0, +3939, 4095, 0, +1025, 0, 792, +1025, 0, 748, +1025, 0, 681, +1025, 0, 573, +1025, 0, 371, +1025, 0, 0, +1025, 0, 0, +1025, 488, 0, +1160, 929, 0, +1295, 1204, 0, +1429, 1419, 0, +1515, 1563, 0, +1601, 1696, 0, +1696, 1828, 0, +1797, 1961, 0, +1905, 2094, 0, +2018, 2226, 0, +2136, 2358, 0, +2256, 2491, 0, +2380, 2623, 0, +2505, 2755, 0, +2633, 2887, 0, +2761, 3019, 0, +2890, 3152, 0, +3020, 3284, 0, +3151, 3416, 0, +3281, 3548, 0, +3413, 3680, 0, +3544, 3812, 0, +3676, 3944, 0, +3808, 4076, 0, +3939, 4095, 0, +1160, 0, 918, +1160, 0, 885, +1160, 0, 836, +1160, 0, 762, +1160, 0, 640, +1160, 0, 397, +1160, 0, 0, +1160, 0, 0, +1160, 592, 0, +1295, 1051, 0, +1429, 1330, 0, +1563, 1548, 0, +1653, 1696, 0, +1738, 1828, 0, +1831, 1961, 0, +1932, 2094, 0, +2039, 2226, 0, +2152, 2358, 0, +2269, 2491, 0, +2390, 2623, 0, +2513, 2755, 0, +2638, 2887, 0, +2765, 3019, 0, +2893, 3152, 0, +3022, 3284, 0, +3152, 3416, 0, +3283, 3548, 0, +3414, 3680, 0, +3545, 3812, 0, +3676, 3944, 0, +3808, 4076, 0, +3940, 4095, 0, +1295, 0, 1046, +1295, 0, 1021, +1295, 0, 985, +1295, 0, 934, +1295, 0, 853, +1295, 0, 717, +1295, 0, 431, +1295, 0, 0, +1295, 0, 0, +1295, 702, 0, +1429, 1174, 0, +1563, 1458, 0, +1696, 1677, 0, +1789, 1828, 0, +1873, 1961, 0, +1966, 2094, 0, +2066, 2226, 0, +2173, 2358, 0, +2285, 2491, 0, +2402, 2623, 0, +2523, 2755, 0, +2646, 2887, 0, +2771, 3019, 0, +2898, 3152, 0, +3025, 3284, 0, +3155, 3416, 0, +3285, 3548, 0, +3415, 3680, 0, +3546, 3812, 0, +3677, 3944, 0, +3808, 4076, 0, +3940, 4095, 0, +1429, 0, 1174, +1429, 0, 1156, +1429, 0, 1130, +1429, 0, 1092, +1429, 0, 1037, +1429, 0, 951, +1429, 0, 803, +1429, 0, 471, +1429, 0, 0, +1429, 0, 0, +1429, 816, 0, +1563, 1301, 0, +1696, 1587, 0, +1828, 1807, 0, +1923, 1961, 0, +2007, 2094, 0, +2100, 2226, 0, +2200, 2358, 0, +2306, 2491, 0, +2419, 2623, 0, +2535, 2755, 0, +2655, 2887, 0, +2778, 3019, 0, +2903, 3152, 0, +3030, 3284, 0, +3158, 3416, 0, +3287, 3548, 0, +3417, 3680, 0, +3547, 3812, 0, +3678, 3944, 0, +3809, 4076, 0, +3941, 4095, 0, +1563, 0, 1304, +1563, 0, 1290, +1563, 0, 1271, +1563, 0, 1244, +1563, 0, 1205, +1563, 0, 1148, +1563, 0, 1057, +1563, 0, 897, +1563, 0, 523, +1563, 0, 0, +1563, 0, 0, +1563, 934, 0, +1696, 1427, 0, +1828, 1716, 0, +1961, 1938, 0, +2058, 2094, 0, +2141, 2226, 0, +2233, 2358, 0, +2333, 2491, 0, +2440, 2623, 0, +2552, 2755, 0, +2668, 2887, 0, +2788, 3019, 0, +2911, 3152, 0, +3035, 3284, 0, +3162, 3416, 0, +3290, 3548, 0, +3419, 3680, 0, +3549, 3812, 0, +3679, 3944, 0, +3810, 4076, 0, +3941, 4095, 0, +1696, 0, 1434, +1696, 0, 1424, +1696, 0, 1410, +1696, 0, 1390, +1696, 0, 1362, +1696, 0, 1322, +1696, 0, 1262, +1696, 0, 1167, +1696, 0, 998, +1696, 0, 580, +1696, 0, 0, +1696, 0, 0, +1696, 1056, 0, +1828, 1557, 0, +1961, 1847, 0, +2094, 2069, 0, +2191, 2226, 0, +2275, 2358, 0, +2367, 2491, 0, +2466, 2623, 0, +2573, 2755, 0, +2684, 2887, 0, +2800, 3019, 0, +2920, 3152, 0, +3043, 3284, 0, +3168, 3416, 0, +3294, 3548, 0, +3422, 3680, 0, +3552, 3812, 0, +3681, 3944, 0, +3812, 4076, 0, +3942, 4095, 0, +1828, 0, 1565, +1828, 0, 1557, +1828, 0, 1547, +1828, 0, 1532, +1828, 0, 1512, +1828, 0, 1484, +1828, 0, 1442, +1828, 0, 1381, +1828, 0, 1283, +1828, 0, 1106, +1828, 0, 650, +1828, 0, 0, +1828, 0, 0, +1828, 1180, 0, +1961, 1686, 0, +2094, 1977, 0, +2226, 2200, 0, +2325, 2358, 0, +2408, 2491, 0, +2500, 2623, 0, +2599, 2755, 0, +2705, 2887, 0, +2816, 3019, 0, +2933, 3152, 0, +3052, 3284, 0, +3175, 3416, 0, +3300, 3548, 0, +3427, 3680, 0, +3554, 3812, 0, +3683, 3944, 0, +3813, 4076, 0, +3944, 4095, 0, +1961, 0, 1696, +1961, 0, 1690, +1961, 0, 1682, +1961, 0, 1672, +1961, 0, 1657, +1961, 0, 1636, +1961, 0, 1607, +1961, 0, 1565, +1961, 0, 1503, +1961, 0, 1402, +1961, 0, 1220, +1961, 0, 726, +1961, 0, 0, +1961, 0, 0, +1961, 1306, 0, +2094, 1816, 0, +2226, 2108, 0, +2358, 2332, 0, +2458, 2491, 0, +2541, 2623, 0, +2632, 2755, 0, +2732, 2887, 0, +2837, 3019, 0, +2949, 3152, 0, +3065, 3284, 0, +3184, 3416, 0, +3307, 3548, 0, +3432, 3680, 0, +3559, 3812, 0, +3687, 3944, 0, +3816, 4076, 0, +3946, 4095, 0, +2094, 0, 1827, +2094, 0, 1823, +2094, 0, 1817, +2094, 0, 1809, +2094, 0, 1798, +2094, 0, 1783, +2094, 0, 1763, +2094, 0, 1733, +2094, 0, 1691, +2094, 0, 1626, +2094, 0, 1524, +2094, 0, 1336, +2094, 0, 814, +2094, 0, 0, +2094, 0, 0, +2094, 1433, 0, +2226, 1946, 0, +2358, 2239, 0, +2491, 2463, 0, +2590, 2623, 0, +2673, 2755, 0, +2765, 2887, 0, +2864, 3019, 0, +2970, 3152, 0, +3081, 3284, 0, +3197, 3416, 0, +3317, 3548, 0, +3440, 3680, 0, +3564, 3812, 0, +3691, 3944, 0, +3819, 4076, 0, +3948, 4095, 0, +2226, 0, 1959, +2226, 0, 1956, +2226, 0, 1951, +2226, 0, 1945, +2226, 0, 1937, +2226, 0, 1926, +2226, 0, 1911, +2226, 0, 1890, +2226, 0, 1860, +2226, 0, 1817, +2226, 0, 1753, +2226, 0, 1648, +2226, 0, 1457, +2226, 0, 907, +2226, 0, 0, +2226, 0, 0, +2226, 1562, 0, +2358, 2078, 0, +2491, 2371, 0, +2623, 2595, 0, +2723, 2755, 0, +2806, 2887, 0, +2897, 3019, 0, +2996, 3152, 0, +3102, 3284, 0, +3213, 3416, 0, +3329, 3548, 0, +3449, 3680, 0, +3572, 3812, 0, +3696, 3944, 0, +3823, 4076, 0, +3951, 4095, 0, +2358, 0, 2090, +2358, 0, 2088, +2358, 0, 2085, +2358, 0, 2080, +2358, 0, 2074, +2358, 0, 2066, +2358, 0, 2055, +2358, 0, 2040, +2358, 0, 2019, +2358, 0, 1989, +2358, 0, 1946, +2358, 0, 1880, +2358, 0, 1775, +2358, 0, 1580, +2358, 0, 1009, +2358, 0, 0, +2358, 0, 0, +2358, 1692, 0, +2491, 2209, 0, +2623, 2503, 0, +2755, 2727, 0, +2856, 2887, 0, +2938, 3019, 0, +3030, 3152, 0, +3128, 3284, 0, +3234, 3416, 0, +3346, 3548, 0, +3462, 3680, 0, +3581, 3812, 0, +3704, 3944, 0, +3828, 4076, 0, +3955, 4095, 0, +2491, 0, 2222, +2491, 0, 2220, +2491, 0, 2218, +2491, 0, 2215, +2491, 0, 2210, +2491, 0, 2204, +2491, 0, 2196, +2491, 0, 2185, +2491, 0, 2170, +2491, 0, 2149, +2491, 0, 2119, +2491, 0, 2075, +2491, 0, 2009, +2491, 0, 1903, +2491, 0, 1706, +2491, 0, 1120, +2491, 0, 0, +2491, 0, 0, +2491, 1822, 0, +2623, 2340, 0, +2755, 2635, 0, +2887, 2859, 0, +2988, 3019, 0, +3071, 3152, 0, +3162, 3284, 0, +3261, 3416, 0, +3367, 3548, 0, +3478, 3680, 0, +3594, 3812, 0, +3713, 3944, 0, +3836, 4076, 0, +3961, 4095, 0, +2623, 0, 2354, +2623, 0, 2352, +2623, 0, 2351, +2623, 0, 2348, +2623, 0, 2345, +2623, 0, 2341, +2623, 0, 2335, +2623, 0, 2327, +2623, 0, 2315, +2623, 0, 2300, +2623, 0, 2278, +2623, 0, 2248, +2623, 0, 2205, +2623, 0, 2138, +2623, 0, 2032, +2623, 0, 1833, +2623, 0, 1232, +2623, 0, 0, +2623, 0, 0, +2623, 1952, 0, +2755, 2473, 0, +2887, 2767, 0, +3019, 2991, 0, +3120, 3152, 0, +3203, 3284, 0, +3294, 3416, 0, +3393, 3548, 0, +3499, 3680, 0, +3610, 3812, 0, +3726, 3944, 0, +3846, 4076, 0, +3968, 4095, 0, +2755, 0, 2486, +2755, 0, 2485, +2755, 0, 2484, +2755, 0, 2482, +2755, 0, 2479, +2755, 0, 2476, +2755, 0, 2472, +2755, 0, 2466, +2755, 0, 2457, +2755, 0, 2446, +2755, 0, 2431, +2755, 0, 2409, +2755, 0, 2379, +2755, 0, 2335, +2755, 0, 2269, +2755, 0, 2162, +2755, 0, 1962, +2755, 0, 1353, +2755, 0, 0, +2755, 0, 0, +2755, 2083, 0, +2887, 2604, 0, +3019, 2898, 0, +3152, 3123, 0, +3252, 3284, 0, +3335, 3416, 0, +3426, 3548, 0, +3525, 3680, 0, +3631, 3812, 0, +3742, 3944, 0, +3858, 4076, 0, +3978, 4095, 0, +2887, 0, 2618, +2887, 0, 2617, +2887, 0, 2616, +2887, 0, 2615, +2887, 0, 2613, +2887, 0, 2611, +2887, 0, 2607, +2887, 0, 2603, +2887, 0, 2597, +2887, 0, 2589, +2887, 0, 2577, +2887, 0, 2562, +2887, 0, 2541, +2887, 0, 2510, +2887, 0, 2466, +2887, 0, 2400, +2887, 0, 2292, +2887, 0, 2091, +2887, 0, 1472, +2887, 0, 0, +2887, 0, 0, +2887, 2215, 0, +3019, 2735, 0, +3152, 3031, 0, +3284, 3254, 0, +3385, 3416, 0, +3467, 3548, 0, +3558, 3680, 0, +3657, 3812, 0, +3763, 3944, 0, +3874, 4076, 0, +3990, 4095, 0, +3019, 0, 2750, +3019, 0, 2749, +3019, 0, 2748, +3019, 0, 2747, +3019, 0, 2746, +3019, 0, 2744, +3019, 0, 2742, +3019, 0, 2738, +3019, 0, 2734, +3019, 0, 2728, +3019, 0, 2720, +3019, 0, 2708, +3019, 0, 2693, +3019, 0, 2672, +3019, 0, 2641, +3019, 0, 2597, +3019, 0, 2530, +3019, 0, 2422, +3019, 0, 2220, +3019, 0, 1594, +3019, 0, 0, +3019, 0, 0, +3019, 2346, 0, +3152, 2868, 0, +3284, 3162, 0, +3416, 3387, 0, +3516, 3548, 0, +3599, 3680, 0, +3691, 3812, 0, +3790, 3944, 0, +3895, 4076, 0, +4007, 4095, 0, +3152, 0, 2882, +3152, 0, 2881, +3152, 0, 2881, +3152, 0, 2880, +3152, 0, 2879, +3152, 0, 2878, +3152, 0, 2876, +3152, 0, 2873, +3152, 0, 2870, +3152, 0, 2866, +3152, 0, 2860, +3152, 0, 2851, +3152, 0, 2840, +3152, 0, 2825, +3152, 0, 2803, +3152, 0, 2773, +3152, 0, 2729, +3152, 0, 2662, +3152, 0, 2554, +3152, 0, 2352, +3152, 0, 1720, +3152, 0, 0, +3152, 0, 0, +3152, 2478, 0, +3284, 2999, 0, +3416, 3294, 0, +3548, 3519, 0, +3649, 3680, 0, +3732, 3812, 0, +3823, 3944, 0, +3922, 4076, 0, +4027, 4095, 0, +3284, 0, 3014, +3284, 0, 3014, +3284, 0, 3013, +3284, 0, 3012, +3284, 0, 3012, +3284, 0, 3011, +3284, 0, 3009, +3284, 0, 3008, +3284, 0, 3005, +3284, 0, 3002, +3284, 0, 2997, +3284, 0, 2991, +3284, 0, 2983, +3284, 0, 2972, +3284, 0, 2956, +3284, 0, 2935, +3284, 0, 2904, +3284, 0, 2860, +3284, 0, 2793, +3284, 0, 2684, +3284, 0, 2481, +3284, 0, 1844, +3284, 0, 0, +3284, 0, 0, +3284, 2609, 0, +3416, 3132, 0, +3548, 3426, 0, +3680, 3651, 0, +3781, 3812, 0, +3864, 3944, 0, +3955, 4076, 0, +4054, 4095, 0, +3416, 0, 3146, +3416, 0, 3146, +3416, 0, 3145, +3416, 0, 3145, +3416, 0, 3144, +3416, 0, 3144, +3416, 0, 3143, +3416, 0, 3141, +3416, 0, 3139, +3416, 0, 3137, +3416, 0, 3134, +3416, 0, 3129, +3416, 0, 3123, +3416, 0, 3115, +3416, 0, 3104, +3416, 0, 3088, +3416, 0, 3067, +3416, 0, 3036, +3416, 0, 2992, +3416, 0, 2925, +3416, 0, 2816, +3416, 0, 2613, +3416, 0, 1977, +3416, 0, 0, +3416, 0, 0, +3416, 2741, 0, +3548, 3264, 0, +3680, 3558, 0, +3812, 3783, 0, +3913, 3944, 0, +3996, 4076, 0, +4087, 4095, 0, +3548, 0, 3278, +3548, 0, 3278, +3548, 0, 3278, +3548, 0, 3277, +3548, 0, 3277, +3548, 0, 3276, +3548, 0, 3276, +3548, 0, 3275, +3548, 0, 3273, +3548, 0, 3271, +3548, 0, 3269, +3548, 0, 3266, +3548, 0, 3261, +3548, 0, 3255, +3548, 0, 3247, +3548, 0, 3236, +3548, 0, 3220, +3548, 0, 3198, +3548, 0, 3168, +3548, 0, 3124, +3548, 0, 3056, +3548, 0, 2948, +3548, 0, 2745, +3548, 0, 2104, +3548, 0, 0, +3548, 0, 0, +3548, 2873, 0, +3680, 3396, 0, +3812, 3691, 0, +3944, 3915, 0, +4045, 4076, 0, +4095, 4095, 0, +3680, 0, 3410, +3680, 0, 3410, +3680, 0, 3410, +3680, 0, 3410, +3680, 0, 3409, +3680, 0, 3409, +3680, 0, 3408, +3680, 0, 3408, +3680, 0, 3406, +3680, 0, 3405, +3680, 0, 3403, +3680, 0, 3401, +3680, 0, 3398, +3680, 0, 3393, +3680, 0, 3387, +3680, 0, 3379, +3680, 0, 3367, +3680, 0, 3352, +3680, 0, 3330, +3680, 0, 3300, +3680, 0, 3255, +3680, 0, 3188, +3680, 0, 3080, +3680, 0, 2876, +3680, 0, 2237, +3680, 0, 0, +3680, 0, 0, +3680, 3005, 0, +3812, 3528, 0, +3944, 3822, 0, +4076, 4047, 0, +4095, 4095, 0, +3812, 0, 3542, +3812, 0, 3542, +3812, 0, 3542, +3812, 0, 3542, +3812, 0, 3541, +3812, 0, 3541, +3812, 0, 3541, +3812, 0, 3540, +3812, 0, 3540, +3812, 0, 3538, +3812, 0, 3537, +3812, 0, 3535, +3812, 0, 3533, +3812, 0, 3530, +3812, 0, 3525, +3812, 0, 3519, +3812, 0, 3511, +3812, 0, 3499, +3812, 0, 3484, +3812, 0, 3462, +3812, 0, 3432, +3812, 0, 3387, +3812, 0, 3320, +3812, 0, 3211, +3812, 0, 3008, +3812, 0, 2367, +3812, 0, 0, +3812, 0, 0, +3812, 3137, 0, +3944, 3660, 0, +4076, 3954, 0, +4095, 4095, 0, +3944, 0, 3674, +3944, 0, 3674, +3944, 0, 3674, +3944, 0, 3674, +3944, 0, 3674, +3944, 0, 3674, +3944, 0, 3673, +3944, 0, 3673, +3944, 0, 3672, +3944, 0, 3671, +3944, 0, 3670, +3944, 0, 3669, +3944, 0, 3667, +3944, 0, 3665, +3944, 0, 3661, +3944, 0, 3657, +3944, 0, 3651, +3944, 0, 3643, +3944, 0, 3631, +3944, 0, 3616, +3944, 0, 3594, +3944, 0, 3564, +3944, 0, 3520, +3944, 0, 3452, +3944, 0, 3344, +3944, 0, 3140, +3944, 0, 2497, +3944, 0, 0, +3944, 0, 0, +3944, 3269, 0, +4076, 3791, 0, +4095, 4087, 0, +4076, 0, 3806, +4076, 0, 3806, +4076, 0, 3806, +4076, 0, 3806, +4076, 0, 3806, +4076, 0, 3806, +4076, 0, 3805, +4076, 0, 3805, +4076, 0, 3805, +4076, 0, 3804, +4076, 0, 3803, +4076, 0, 3803, +4076, 0, 3801, +4076, 0, 3799, +4076, 0, 3797, +4076, 0, 3793, +4076, 0, 3789, +4076, 0, 3783, +4076, 0, 3774, +4076, 0, 3763, +4076, 0, 3748, +4076, 0, 3726, +4076, 0, 3696, +4076, 0, 3651, +4076, 0, 3584, +4076, 0, 3475, +4076, 0, 3271, +4076, 0, 2626, +4076, 0, 0, +4076, 0, 0, +4076, 3401, 0, +4095, 3924, 0, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3938, +4095, 0, 3938, +4095, 0, 3938, +4095, 0, 3938, +4095, 0, 3938, +4095, 0, 3938, +4095, 0, 3937, +4095, 0, 3937, +4095, 0, 3937, +4095, 0, 3936, +4095, 0, 3935, +4095, 0, 3933, +4095, 0, 3932, +4095, 0, 3929, +4095, 0, 3926, +4095, 0, 3921, +4095, 0, 3915, +4095, 0, 3907, +4095, 0, 3896, +4095, 0, 3880, +4095, 0, 3859, +4095, 0, 3828, +4095, 0, 3784, +4095, 0, 3716, +4095, 0, 3608, +4095, 0, 3404, +4095, 0, 2761, +4095, 0, 0, +4095, 0, 0, +4095, 3533, 0, +0, 97, 163, +0, 163, 42, +13, 318, 0, +171, 466, 0, +322, 609, 0, +467, 750, 0, +608, 888, 0, +748, 1025, 0, +885, 1160, 0, +1021, 1295, 0, +1156, 1429, 0, +1290, 1563, 0, +1424, 1696, 0, +1557, 1828, 0, +1690, 1961, 0, +1823, 2094, 0, +1956, 2226, 0, +2088, 2358, 0, +2220, 2491, 0, +2352, 2623, 0, +2485, 2755, 0, +2617, 2887, 0, +2749, 3019, 0, +2881, 3152, 0, +3014, 3284, 0, +3146, 3416, 0, +3278, 3548, 0, +3410, 3680, 0, +3542, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3939, 4095, 0, +42, 0, 163, +131, 131, 131, +229, 295, 86, +333, 450, 15, +444, 598, 0, +559, 741, 0, +678, 882, 0, +800, 1020, 0, +924, 1157, 0, +1050, 1292, 0, +1178, 1427, 0, +1307, 1561, 0, +1436, 1695, 0, +1566, 1828, 0, +1697, 1961, 0, +1828, 2093, 0, +1959, 2226, 0, +2091, 2358, 0, +2223, 2491, 0, +2354, 2623, 0, +2486, 2755, 0, +2618, 2887, 0, +2750, 3019, 0, +2882, 3152, 0, +3014, 3283, 0, +3146, 3416, 0, +3278, 3548, 0, +3410, 3680, 0, +3542, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3939, 4095, 0, +300, 0, 318, +295, 86, 229, +295, 174, 86, +450, 432, 15, +551, 598, 0, +644, 741, 0, +745, 882, 0, +852, 1020, 0, +964, 1157, 0, +1081, 1292, 0, +1201, 1427, 0, +1325, 1561, 0, +1450, 1695, 0, +1576, 1828, 0, +1705, 1961, 0, +1834, 2093, 0, +1963, 2226, 0, +2094, 2358, 0, +2225, 2491, 0, +2356, 2623, 0, +2488, 2755, 0, +2619, 2887, 0, +2751, 3019, 0, +2883, 3152, 0, +3014, 3283, 0, +3146, 3416, 0, +3278, 3548, 0, +3410, 3680, 0, +3543, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3939, 4095, 0, +466, 0, 419, +450, 15, 333, +450, 15, 145, +450, 225, 15, +598, 520, 0, +738, 741, 0, +822, 882, 0, +914, 1020, 0, +1013, 1157, 0, +1119, 1292, 0, +1231, 1427, 0, +1347, 1561, 0, +1467, 1695, 0, +1590, 1828, 0, +1715, 1961, 0, +1841, 2093, 0, +1969, 2226, 0, +2098, 2358, 0, +2228, 2491, 0, +2358, 2623, 0, +2489, 2755, 0, +2620, 2887, 0, +2752, 3019, 0, +2883, 3152, 0, +3015, 3283, 0, +3147, 3416, 0, +3279, 3548, 0, +3411, 3680, 0, +3543, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3939, 4095, 0, +609, 0, 512, +598, 0, 444, +598, 0, 303, +598, 0, 0, +598, 286, 0, +741, 616, 0, +882, 855, 0, +985, 1020, 0, +1071, 1157, 0, +1166, 1292, 0, +1267, 1427, 0, +1376, 1561, 0, +1489, 1695, 0, +1607, 1828, 0, +1728, 1961, 0, +1851, 2093, 0, +1977, 2226, 0, +2104, 2358, 0, +2233, 2491, 0, +2362, 2623, 0, +2492, 2755, 0, +2622, 2887, 0, +2753, 3019, 0, +2885, 3152, 0, +3016, 3283, 0, +3147, 3416, 0, +3279, 3548, 0, +3411, 3680, 0, +3543, 3812, 0, +3675, 3944, 0, +3807, 4076, 0, +3939, 4095, 0, +750, 0, 613, +741, 0, 559, +741, 0, 453, +741, 0, 258, +741, 0, 0, +741, 356, 0, +882, 719, 0, +1020, 970, 0, +1139, 1157, 0, +1221, 1292, 0, +1313, 1427, 0, +1412, 1561, 0, +1517, 1695, 0, +1629, 1828, 0, +1745, 1961, 0, +1864, 2093, 0, +1987, 2226, 0, +2111, 2358, 0, +2238, 2491, 0, +2366, 2623, 0, +2495, 2755, 0, +2625, 2887, 0, +2755, 3019, 0, +2886, 3152, 0, +3017, 3283, 0, +3148, 3416, 0, +3280, 3548, 0, +3411, 3680, 0, +3543, 3812, 0, +3675, 3944, 0, +3807, 4076, 0, +3939, 4095, 0, +888, 0, 719, +882, 0, 678, +882, 0, 599, +882, 0, 466, +882, 0, 190, +882, 0, 0, +882, 436, 0, +1020, 829, 0, +1157, 1089, 0, +1286, 1292, 0, +1366, 1427, 0, +1456, 1561, 0, +1552, 1695, 0, +1656, 1828, 0, +1766, 1961, 0, +1881, 2093, 0, +1999, 2226, 0, +2121, 2358, 0, +2245, 2491, 0, +2372, 2623, 0, +2499, 2755, 0, +2628, 2887, 0, +2757, 3019, 0, +2888, 3152, 0, +3018, 3283, 0, +3149, 3416, 0, +3280, 3548, 0, +3412, 3680, 0, +3544, 3812, 0, +3675, 3944, 0, +3807, 4076, 0, +3939, 4095, 0, +1025, 0, 832, +1020, 0, 800, +1020, 0, 740, +1020, 0, 647, +1020, 0, 482, +1020, 0, 81, +1020, 0, 0, +1020, 524, 0, +1157, 943, 0, +1292, 1211, 0, +1427, 1424, 0, +1508, 1561, 0, +1596, 1695, 0, +1691, 1828, 0, +1793, 1961, 0, +1902, 2093, 0, +2016, 2226, 0, +2134, 2358, 0, +2255, 2491, 0, +2379, 2623, 0, +2505, 2755, 0, +2632, 2887, 0, +2760, 3019, 0, +2890, 3152, 0, +3020, 3283, 0, +3151, 3416, 0, +3281, 3548, 0, +3413, 3680, 0, +3544, 3812, 0, +3676, 3944, 0, +3807, 4076, 0, +3939, 4095, 0, +1160, 0, 949, +1157, 0, 924, +1157, 0, 879, +1157, 0, 813, +1157, 0, 705, +1157, 0, 503, +1157, 0, 0, +1157, 0, 0, +1157, 620, 0, +1292, 1062, 0, +1427, 1336, 0, +1561, 1552, 0, +1647, 1695, 0, +1733, 1828, 0, +1828, 1961, 0, +1929, 2093, 0, +2037, 2226, 0, +2150, 2358, 0, +2268, 2491, 0, +2388, 2623, 0, +2512, 2755, 0, +2638, 2887, 0, +2765, 3019, 0, +2893, 3152, 0, +3022, 3283, 0, +3152, 3416, 0, +3283, 3548, 0, +3414, 3680, 0, +3545, 3812, 0, +3676, 3944, 0, +3808, 4076, 0, +3940, 4095, 0, +1295, 0, 1069, +1292, 0, 1050, +1292, 0, 1017, +1292, 0, 968, +1292, 0, 894, +1292, 0, 772, +1292, 0, 529, +1292, 0, 0, +1292, 0, 0, +1292, 724, 0, +1427, 1182, 0, +1561, 1463, 0, +1695, 1680, 0, +1785, 1828, 0, +1870, 1961, 0, +1963, 2093, 0, +2064, 2226, 0, +2171, 2358, 0, +2284, 2491, 0, +2401, 2623, 0, +2522, 2755, 0, +2645, 2887, 0, +2770, 3019, 0, +2897, 3152, 0, +3025, 3283, 0, +3154, 3416, 0, +3284, 3548, 0, +3415, 3680, 0, +3546, 3812, 0, +3677, 3944, 0, +3808, 4076, 0, +3940, 4095, 0, +1429, 0, 1192, +1427, 0, 1178, +1427, 0, 1153, +1427, 0, 1118, +1427, 0, 1065, +1427, 0, 985, +1427, 0, 849, +1427, 0, 562, +1427, 0, 0, +1427, 0, 0, +1427, 833, 0, +1561, 1307, 0, +1695, 1590, 0, +1828, 1810, 0, +1920, 1961, 0, +2005, 2093, 0, +2098, 2226, 0, +2199, 2358, 0, +2305, 2491, 0, +2417, 2623, 0, +2535, 2755, 0, +2655, 2887, 0, +2777, 3019, 0, +2903, 3152, 0, +3029, 3283, 0, +3158, 3416, 0, +3287, 3548, 0, +3417, 3680, 0, +3547, 3812, 0, +3678, 3944, 0, +3809, 4076, 0, +3941, 4095, 0, +1563, 0, 1318, +1561, 0, 1307, +1561, 0, 1288, +1561, 0, 1262, +1561, 0, 1225, +1561, 0, 1170, +1561, 0, 1084, +1561, 0, 935, +1561, 0, 605, +1561, 0, 0, +1561, 0, 0, +1561, 948, 0, +1695, 1432, 0, +1828, 1719, 0, +1961, 1940, 0, +2056, 2093, 0, +2140, 2226, 0, +2232, 2358, 0, +2332, 2491, 0, +2439, 2623, 0, +2551, 2755, 0, +2667, 2887, 0, +2787, 3019, 0, +2910, 3152, 0, +3035, 3283, 0, +3162, 3416, 0, +3290, 3548, 0, +3419, 3680, 0, +3549, 3812, 0, +3679, 3944, 0, +3810, 4076, 0, +3941, 4095, 0, +1696, 0, 1444, +1695, 0, 1436, +1695, 0, 1422, +1695, 0, 1403, +1695, 0, 1376, +1695, 0, 1337, +1695, 0, 1279, +1695, 0, 1188, +1695, 0, 1029, +1695, 0, 653, +1695, 0, 0, +1695, 0, 0, +1695, 1066, 0, +1828, 1560, 0, +1961, 1849, 0, +2093, 2070, 0, +2190, 2226, 0, +2273, 2358, 0, +2366, 2491, 0, +2465, 2623, 0, +2572, 2755, 0, +2684, 2887, 0, +2800, 3019, 0, +2920, 3152, 0, +3042, 3283, 0, +3168, 3416, 0, +3294, 3548, 0, +3422, 3680, 0, +3551, 3812, 0, +3681, 3944, 0, +3811, 4076, 0, +3942, 4095, 0, +1828, 0, 1572, +1828, 0, 1566, +1828, 0, 1556, +1828, 0, 1542, +1828, 0, 1522, +1828, 0, 1494, +1828, 0, 1454, +1828, 0, 1394, +1828, 0, 1300, +1828, 0, 1131, +1828, 0, 713, +1828, 0, 0, +1828, 0, 0, +1828, 1188, 0, +1961, 1689, 0, +2093, 1979, 0, +2226, 2201, 0, +2324, 2358, 0, +2407, 2491, 0, +2499, 2623, 0, +2598, 2755, 0, +2705, 2887, 0, +2816, 3019, 0, +2932, 3152, 0, +3052, 3283, 0, +3175, 3416, 0, +3300, 3548, 0, +3426, 3680, 0, +3554, 3812, 0, +3683, 3944, 0, +3813, 4076, 0, +3944, 4095, 0, +1961, 0, 1702, +1961, 0, 1697, +1961, 0, 1689, +1961, 0, 1679, +1961, 0, 1664, +1961, 0, 1644, +1961, 0, 1615, +1961, 0, 1574, +1961, 0, 1513, +1961, 0, 1415, +1961, 0, 1238, +1961, 0, 780, +1961, 0, 0, +1961, 0, 0, +1961, 1312, 0, +2093, 1818, 0, +2226, 2109, 0, +2358, 2332, 0, +2457, 2491, 0, +2540, 2623, 0, +2632, 2755, 0, +2731, 2887, 0, +2837, 3019, 0, +2949, 3152, 0, +3065, 3283, 0, +3184, 3416, 0, +3307, 3548, 0, +3432, 3680, 0, +3559, 3812, 0, +3687, 3944, 0, +3816, 4076, 0, +3946, 4095, 0, +2094, 0, 1831, +2093, 0, 1828, +2093, 0, 1822, +2093, 0, 1814, +2093, 0, 1804, +2093, 0, 1789, +2093, 0, 1768, +2093, 0, 1739, +2093, 0, 1698, +2093, 0, 1635, +2093, 0, 1534, +2093, 0, 1351, +2093, 0, 859, +2093, 0, 0, +2093, 0, 0, +2093, 1438, 0, +2226, 1948, 0, +2358, 2240, 0, +2491, 2464, 0, +2590, 2623, 0, +2673, 2755, 0, +2764, 2887, 0, +2863, 3019, 0, +2970, 3152, 0, +3081, 3283, 0, +3197, 3416, 0, +3317, 3548, 0, +3439, 3680, 0, +3564, 3812, 0, +3691, 3944, 0, +3819, 4076, 0, +3948, 4095, 0, +2226, 0, 1962, +2226, 0, 1959, +2226, 0, 1955, +2226, 0, 1949, +2226, 0, 1941, +2226, 0, 1930, +2226, 0, 1915, +2226, 0, 1894, +2226, 0, 1865, +2226, 0, 1823, +2226, 0, 1759, +2226, 0, 1656, +2226, 0, 1469, +2226, 0, 944, +2226, 0, 0, +2226, 0, 0, +2226, 1565, 0, +2358, 2079, 0, +2491, 2372, 0, +2623, 2595, 0, +2723, 2755, 0, +2805, 2887, 0, +2897, 3019, 0, +2996, 3152, 0, +3102, 3283, 0, +3213, 3416, 0, +3329, 3548, 0, +3449, 3680, 0, +3572, 3812, 0, +3696, 3944, 0, +3823, 4076, 0, +3951, 4095, 0, +2358, 0, 2093, +2358, 0, 2091, +2358, 0, 2087, +2358, 0, 2083, +2358, 0, 2077, +2358, 0, 2069, +2358, 0, 2058, +2358, 0, 2043, +2358, 0, 2022, +2358, 0, 1993, +2358, 0, 1950, +2358, 0, 1885, +2358, 0, 1781, +2358, 0, 1589, +2358, 0, 1039, +2358, 0, 0, +2358, 0, 0, +2358, 1694, 0, +2491, 2210, 0, +2623, 2503, 0, +2755, 2727, 0, +2855, 2887, 0, +2938, 3019, 0, +3029, 3152, 0, +3128, 3283, 0, +3234, 3416, 0, +3346, 3548, 0, +3462, 3680, 0, +3581, 3812, 0, +3704, 3944, 0, +3828, 4076, 0, +3955, 4095, 0, +2491, 0, 2224, +2491, 0, 2223, +2491, 0, 2220, +2491, 0, 2217, +2491, 0, 2212, +2491, 0, 2206, +2491, 0, 2199, +2491, 0, 2187, +2491, 0, 2172, +2491, 0, 2151, +2491, 0, 2121, +2491, 0, 2078, +2491, 0, 2013, +2491, 0, 1907, +2491, 0, 1713, +2491, 0, 1143, +2491, 0, 0, +2491, 0, 0, +2491, 1824, 0, +2623, 2341, 0, +2755, 2635, 0, +2887, 2859, 0, +2987, 3019, 0, +3070, 3152, 0, +3162, 3283, 0, +3261, 3416, 0, +3367, 3548, 0, +3478, 3680, 0, +3594, 3812, 0, +3713, 3944, 0, +3836, 4076, 0, +3961, 4095, 0, +2623, 0, 2355, +2623, 0, 2354, +2623, 0, 2352, +2623, 0, 2350, +2623, 0, 2347, +2623, 0, 2342, +2623, 0, 2336, +2623, 0, 2328, +2623, 0, 2317, +2623, 0, 2302, +2623, 0, 2281, +2623, 0, 2250, +2623, 0, 2207, +2623, 0, 2141, +2623, 0, 2035, +2623, 0, 1838, +2623, 0, 1251, +2623, 0, 0, +2623, 0, 0, +2623, 1954, 0, +2755, 2473, 0, +2887, 2767, 0, +3019, 2991, 0, +3120, 3152, 0, +3203, 3283, 0, +3294, 3416, 0, +3393, 3548, 0, +3499, 3680, 0, +3610, 3812, 0, +3726, 3944, 0, +3845, 4076, 0, +3968, 4095, 0, +2755, 0, 2487, +2755, 0, 2486, +2755, 0, 2485, +2755, 0, 2483, +2755, 0, 2481, +2755, 0, 2477, +2755, 0, 2473, +2755, 0, 2467, +2755, 0, 2459, +2755, 0, 2448, +2755, 0, 2432, +2755, 0, 2411, +2755, 0, 2381, +2755, 0, 2337, +2755, 0, 2271, +2755, 0, 2164, +2755, 0, 1966, +2755, 0, 1367, +2755, 0, 0, +2755, 0, 0, +2755, 2084, 0, +2887, 2604, 0, +3019, 2898, 0, +3152, 3123, 0, +3252, 3283, 0, +3335, 3416, 0, +3426, 3548, 0, +3525, 3680, 0, +3631, 3812, 0, +3742, 3944, 0, +3858, 4076, 0, +3978, 4095, 0, +2887, 0, 2619, +2887, 0, 2618, +2887, 0, 2617, +2887, 0, 2616, +2887, 0, 2614, +2887, 0, 2612, +2887, 0, 2608, +2887, 0, 2604, +2887, 0, 2598, +2887, 0, 2589, +2887, 0, 2578, +2887, 0, 2563, +2887, 0, 2542, +2887, 0, 2511, +2887, 0, 2467, +2887, 0, 2401, +2887, 0, 2294, +2887, 0, 2094, +2887, 0, 1483, +2887, 0, 0, +2887, 0, 0, +2887, 2215, 0, +3019, 2735, 0, +3152, 3031, 0, +3283, 3254, 0, +3385, 3416, 0, +3467, 3548, 0, +3558, 3680, 0, +3657, 3812, 0, +3763, 3944, 0, +3874, 4076, 0, +3990, 4095, 0, +3019, 0, 2750, +3019, 0, 2750, +3019, 0, 2749, +3019, 0, 2748, +3019, 0, 2747, +3019, 0, 2745, +3019, 0, 2742, +3019, 0, 2739, +3019, 0, 2735, +3019, 0, 2729, +3019, 0, 2720, +3019, 0, 2709, +3019, 0, 2694, +3019, 0, 2672, +3019, 0, 2642, +3019, 0, 2598, +3019, 0, 2531, +3019, 0, 2424, +3019, 0, 2222, +3019, 0, 1602, +3019, 0, 0, +3019, 0, 0, +3019, 2346, 0, +3152, 2868, 0, +3283, 3162, 0, +3416, 3387, 0, +3516, 3548, 0, +3599, 3680, 0, +3691, 3812, 0, +3790, 3944, 0, +3895, 4076, 0, +4006, 4095, 0, +3152, 0, 2883, +3152, 0, 2882, +3152, 0, 2881, +3152, 0, 2881, +3152, 0, 2880, +3152, 0, 2878, +3152, 0, 2877, +3152, 0, 2874, +3152, 0, 2871, +3152, 0, 2866, +3152, 0, 2860, +3152, 0, 2852, +3152, 0, 2841, +3152, 0, 2825, +3152, 0, 2804, +3152, 0, 2773, +3152, 0, 2729, +3152, 0, 2663, +3152, 0, 2555, +3152, 0, 2353, +3152, 0, 1726, +3152, 0, 0, +3152, 0, 0, +3152, 2478, 0, +3283, 2999, 0, +3416, 3294, 0, +3548, 3519, 0, +3649, 3680, 0, +3731, 3812, 0, +3823, 3944, 0, +3922, 4076, 0, +4027, 4095, 0, +3284, 0, 3014, +3283, 0, 3014, +3283, 0, 3014, +3283, 0, 3013, +3283, 0, 3012, +3283, 0, 3011, +3283, 0, 3010, +3283, 0, 3008, +3283, 0, 3005, +3283, 0, 3002, +3283, 0, 2998, +3283, 0, 2992, +3283, 0, 2983, +3283, 0, 2972, +3283, 0, 2957, +3283, 0, 2935, +3283, 0, 2905, +3283, 0, 2860, +3283, 0, 2793, +3283, 0, 2685, +3283, 0, 2482, +3283, 0, 1849, +3283, 0, 0, +3283, 0, 0, +3283, 2609, 0, +3416, 3132, 0, +3548, 3426, 0, +3680, 3651, 0, +3781, 3812, 0, +3864, 3944, 0, +3955, 4076, 0, +4054, 4095, 0, +3416, 0, 3146, +3416, 0, 3146, +3416, 0, 3146, +3416, 0, 3145, +3416, 0, 3145, +3416, 0, 3144, +3416, 0, 3143, +3416, 0, 3141, +3416, 0, 3140, +3416, 0, 3137, +3416, 0, 3134, +3416, 0, 3129, +3416, 0, 3123, +3416, 0, 3115, +3416, 0, 3104, +3416, 0, 3088, +3416, 0, 3067, +3416, 0, 3036, +3416, 0, 2992, +3416, 0, 2925, +3416, 0, 2817, +3416, 0, 2614, +3416, 0, 1981, +3416, 0, 0, +3416, 0, 0, +3416, 2741, 0, +3548, 3264, 0, +3680, 3558, 0, +3812, 3783, 0, +3913, 3944, 0, +3996, 4076, 0, +4087, 4095, 0, +3548, 0, 3278, +3548, 0, 3278, +3548, 0, 3278, +3548, 0, 3278, +3548, 0, 3277, +3548, 0, 3277, +3548, 0, 3276, +3548, 0, 3275, +3548, 0, 3273, +3548, 0, 3272, +3548, 0, 3269, +3548, 0, 3266, +3548, 0, 3261, +3548, 0, 3255, +3548, 0, 3247, +3548, 0, 3236, +3548, 0, 3220, +3548, 0, 3199, +3548, 0, 3168, +3548, 0, 3124, +3548, 0, 3057, +3548, 0, 2948, +3548, 0, 2745, +3548, 0, 2107, +3548, 0, 0, +3548, 0, 0, +3548, 2873, 0, +3680, 3396, 0, +3812, 3691, 0, +3944, 3915, 0, +4045, 4076, 0, +4095, 4095, 0, +3680, 0, 3410, +3680, 0, 3410, +3680, 0, 3410, +3680, 0, 3410, +3680, 0, 3409, +3680, 0, 3409, +3680, 0, 3408, +3680, 0, 3408, +3680, 0, 3407, +3680, 0, 3405, +3680, 0, 3403, +3680, 0, 3401, +3680, 0, 3398, +3680, 0, 3393, +3680, 0, 3387, +3680, 0, 3379, +3680, 0, 3368, +3680, 0, 3352, +3680, 0, 3331, +3680, 0, 3300, +3680, 0, 3256, +3680, 0, 3188, +3680, 0, 3080, +3680, 0, 2877, +3680, 0, 2239, +3680, 0, 0, +3680, 0, 0, +3680, 3005, 0, +3812, 3528, 0, +3944, 3822, 0, +4076, 4047, 0, +4095, 4095, 0, +3812, 0, 3542, +3812, 0, 3542, +3812, 0, 3542, +3812, 0, 3542, +3812, 0, 3542, +3812, 0, 3541, +3812, 0, 3541, +3812, 0, 3540, +3812, 0, 3540, +3812, 0, 3538, +3812, 0, 3537, +3812, 0, 3536, +3812, 0, 3533, +3812, 0, 3530, +3812, 0, 3525, +3812, 0, 3519, +3812, 0, 3511, +3812, 0, 3499, +3812, 0, 3484, +3812, 0, 3462, +3812, 0, 3432, +3812, 0, 3388, +3812, 0, 3321, +3812, 0, 3212, +3812, 0, 3009, +3812, 0, 2369, +3812, 0, 0, +3812, 0, 0, +3812, 3137, 0, +3944, 3660, 0, +4076, 3954, 0, +4095, 4095, 0, +3944, 0, 3674, +3944, 0, 3674, +3944, 0, 3674, +3944, 0, 3674, +3944, 0, 3674, +3944, 0, 3674, +3944, 0, 3673, +3944, 0, 3673, +3944, 0, 3672, +3944, 0, 3671, +3944, 0, 3671, +3944, 0, 3669, +3944, 0, 3667, +3944, 0, 3665, +3944, 0, 3662, +3944, 0, 3657, +3944, 0, 3651, +3944, 0, 3643, +3944, 0, 3632, +3944, 0, 3616, +3944, 0, 3595, +3944, 0, 3564, +3944, 0, 3520, +3944, 0, 3452, +3944, 0, 3344, +3944, 0, 3140, +3944, 0, 2498, +3944, 0, 0, +3944, 0, 0, +3944, 3269, 0, +4076, 3792, 0, +4095, 4087, 0, +4076, 0, 3806, +4076, 0, 3806, +4076, 0, 3806, +4076, 0, 3806, +4076, 0, 3806, +4076, 0, 3806, +4076, 0, 3805, +4076, 0, 3805, +4076, 0, 3805, +4076, 0, 3804, +4076, 0, 3803, +4076, 0, 3803, +4076, 0, 3801, +4076, 0, 3799, +4076, 0, 3797, +4076, 0, 3793, +4076, 0, 3789, +4076, 0, 3783, +4076, 0, 3775, +4076, 0, 3763, +4076, 0, 3748, +4076, 0, 3726, +4076, 0, 3696, +4076, 0, 3651, +4076, 0, 3584, +4076, 0, 3475, +4076, 0, 3272, +4076, 0, 2627, +4076, 0, 0, +4076, 0, 0, +4076, 3401, 0, +4095, 3924, 0, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3938, +4095, 0, 3938, +4095, 0, 3938, +4095, 0, 3938, +4095, 0, 3938, +4095, 0, 3937, +4095, 0, 3937, +4095, 0, 3937, +4095, 0, 3936, +4095, 0, 3935, +4095, 0, 3933, +4095, 0, 3932, +4095, 0, 3929, +4095, 0, 3926, +4095, 0, 3921, +4095, 0, 3915, +4095, 0, 3907, +4095, 0, 3896, +4095, 0, 3880, +4095, 0, 3859, +4095, 0, 3828, +4095, 0, 3784, +4095, 0, 3717, +4095, 0, 3608, +4095, 0, 3404, +4095, 0, 2762, +4095, 0, 0, +4095, 0, 0, +4095, 3533, 0, +0, 201, 318, +0, 318, 300, +0, 318, 93, +0, 466, 0, +127, 609, 0, +334, 750, 0, +515, 888, 0, +681, 1025, 0, +836, 1160, 0, +985, 1295, 0, +1130, 1429, 0, +1271, 1563, 0, +1410, 1696, 0, +1547, 1828, 0, +1682, 1961, 0, +1817, 2094, 0, +1951, 2226, 0, +2085, 2358, 0, +2218, 2491, 0, +2351, 2623, 0, +2484, 2755, 0, +2616, 2887, 0, +2748, 3019, 0, +2881, 3152, 0, +3013, 3284, 0, +3145, 3416, 0, +3278, 3548, 0, +3410, 3680, 0, +3542, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3938, 4095, 0, +0, 13, 318, +86, 229, 295, +86, 295, 174, +145, 450, 15, +303, 598, 0, +453, 741, 0, +599, 882, 0, +740, 1020, 0, +879, 1157, 0, +1017, 1292, 0, +1153, 1427, 0, +1288, 1561, 0, +1422, 1695, 0, +1556, 1828, 0, +1689, 1961, 0, +1822, 2093, 0, +1955, 2226, 0, +2087, 2358, 0, +2220, 2491, 0, +2352, 2623, 0, +2485, 2755, 0, +2617, 2887, 0, +2749, 3019, 0, +2881, 3152, 0, +3014, 3283, 0, +3146, 3416, 0, +3278, 3548, 0, +3410, 3680, 0, +3542, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3939, 4095, 0, +93, 0, 318, +174, 86, 295, +264, 264, 264, +361, 427, 218, +466, 582, 148, +576, 730, 34, +691, 873, 0, +810, 1014, 0, +932, 1152, 0, +1056, 1289, 0, +1182, 1424, 0, +1310, 1559, 0, +1439, 1693, 0, +1568, 1827, 0, +1699, 1960, 0, +1829, 2093, 0, +1960, 2225, 0, +2091, 2358, 0, +2223, 2490, 0, +2355, 2623, 0, +2486, 2755, 0, +2618, 2887, 0, +2750, 3019, 0, +2882, 3152, 0, +3014, 3283, 0, +3146, 3416, 0, +3278, 3548, 0, +3410, 3680, 0, +3542, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3939, 4095, 0, +388, 0, 466, +432, 15, 450, +427, 218, 361, +427, 306, 218, +582, 564, 148, +683, 730, 34, +776, 873, 0, +877, 1014, 0, +984, 1152, 0, +1096, 1289, 0, +1213, 1424, 0, +1333, 1559, 0, +1456, 1693, 0, +1582, 1827, 0, +1708, 1960, 0, +1837, 2093, 0, +1966, 2225, 0, +2096, 2358, 0, +2226, 2490, 0, +2357, 2623, 0, +2488, 2755, 0, +2620, 2887, 0, +2751, 3019, 0, +2883, 3152, 0, +3014, 3283, 0, +3147, 3416, 0, +3279, 3548, 0, +3410, 3680, 0, +3543, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3939, 4095, 0, +609, 0, 606, +598, 0, 551, +582, 148, 466, +582, 148, 277, +582, 357, 148, +730, 652, 34, +870, 873, 0, +954, 1014, 0, +1045, 1152, 0, +1145, 1289, 0, +1251, 1424, 0, +1363, 1559, 0, +1479, 1693, 0, +1599, 1827, 0, +1722, 1960, 0, +1847, 2093, 0, +1973, 2225, 0, +2101, 2358, 0, +2230, 2490, 0, +2360, 2623, 0, +2491, 2755, 0, +2621, 2887, 0, +2752, 3019, 0, +2884, 3152, 0, +3015, 3283, 0, +3147, 3416, 0, +3279, 3548, 0, +3411, 3680, 0, +3543, 3812, 0, +3675, 3944, 0, +3807, 4076, 0, +3939, 4095, 0, +750, 0, 689, +741, 0, 644, +730, 34, 576, +730, 34, 435, +730, 34, 132, +730, 418, 34, +873, 749, 0, +1014, 987, 0, +1117, 1152, 0, +1203, 1289, 0, +1298, 1424, 0, +1400, 1559, 0, +1508, 1693, 0, +1621, 1827, 0, +1739, 1960, 0, +1860, 2093, 0, +1983, 2225, 0, +2109, 2358, 0, +2236, 2490, 0, +2364, 2623, 0, +2494, 2755, 0, +2624, 2887, 0, +2754, 3019, 0, +2885, 3152, 0, +3016, 3283, 0, +3148, 3416, 0, +3280, 3548, 0, +3411, 3680, 0, +3543, 3812, 0, +3675, 3944, 0, +3807, 4076, 0, +3939, 4095, 0, +888, 0, 781, +882, 0, 745, +873, 0, 691, +873, 0, 585, +873, 0, 390, +873, 0, 0, +873, 488, 0, +1014, 852, 0, +1152, 1102, 0, +1271, 1289, 0, +1353, 1424, 0, +1445, 1559, 0, +1544, 1693, 0, +1650, 1827, 0, +1761, 1960, 0, +1877, 2093, 0, +1996, 2225, 0, +2119, 2358, 0, +2243, 2490, 0, +2370, 2623, 0, +2498, 2755, 0, +2627, 2887, 0, +2757, 3019, 0, +2887, 3152, 0, +3018, 3283, 0, +3149, 3416, 0, +3280, 3548, 0, +3412, 3680, 0, +3543, 3812, 0, +3675, 3944, 0, +3807, 4076, 0, +3939, 4095, 0, +1025, 0, 881, +1020, 0, 852, +1014, 0, 810, +1014, 0, 731, +1014, 0, 598, +1014, 0, 323, +1014, 0, 0, +1014, 568, 0, +1152, 960, 0, +1289, 1221, 0, +1418, 1424, 0, +1499, 1559, 0, +1588, 1693, 0, +1684, 1827, 0, +1789, 1960, 0, +1898, 2093, 0, +2013, 2225, 0, +2132, 2358, 0, +2253, 2490, 0, +2378, 2623, 0, +2504, 2755, 0, +2631, 2887, 0, +2760, 3019, 0, +2890, 3152, 0, +3019, 3283, 0, +3150, 3416, 0, +3281, 3548, 0, +3413, 3680, 0, +3544, 3812, 0, +3676, 3944, 0, +3807, 4076, 0, +3939, 4095, 0, +1160, 0, 987, +1157, 0, 964, +1152, 0, 932, +1152, 0, 873, +1152, 0, 779, +1152, 0, 614, +1152, 0, 214, +1152, 0, 0, +1152, 656, 0, +1289, 1075, 0, +1424, 1343, 0, +1559, 1556, 0, +1640, 1693, 0, +1727, 1827, 0, +1823, 1960, 0, +1926, 2093, 0, +2034, 2225, 0, +2148, 2358, 0, +2266, 2490, 0, +2387, 2623, 0, +2511, 2755, 0, +2637, 2887, 0, +2764, 3019, 0, +2893, 3152, 0, +3022, 3283, 0, +3152, 3416, 0, +3282, 3548, 0, +3414, 3680, 0, +3545, 3812, 0, +3676, 3944, 0, +3808, 4076, 0, +3940, 4095, 0, +1295, 0, 1099, +1292, 0, 1081, +1289, 0, 1056, +1289, 0, 1012, +1289, 0, 945, +1289, 0, 837, +1289, 0, 635, +1289, 0, 9, +1289, 0, 0, +1289, 753, 0, +1424, 1193, 0, +1559, 1468, 0, +1693, 1683, 0, +1779, 1827, 0, +1865, 1960, 0, +1960, 2093, 0, +2061, 2225, 0, +2169, 2358, 0, +2283, 2490, 0, +2400, 2623, 0, +2521, 2755, 0, +2644, 2887, 0, +2770, 3019, 0, +2897, 3152, 0, +3025, 3283, 0, +3154, 3416, 0, +3284, 3548, 0, +3415, 3680, 0, +3546, 3812, 0, +3677, 3944, 0, +3808, 4076, 0, +3940, 4095, 0, +1429, 0, 1215, +1427, 0, 1201, +1424, 0, 1182, +1424, 0, 1149, +1424, 0, 1101, +1424, 0, 1027, +1424, 0, 904, +1424, 0, 662, +1424, 0, 0, +1424, 0, 0, +1424, 856, 0, +1559, 1315, 0, +1693, 1594, 0, +1827, 1812, 0, +1917, 1960, 0, +2002, 2093, 0, +2095, 2225, 0, +2196, 2358, 0, +2304, 2490, 0, +2416, 2623, 0, +2533, 2755, 0, +2654, 2887, 0, +2777, 3019, 0, +2903, 3152, 0, +3029, 3283, 0, +3157, 3416, 0, +3287, 3548, 0, +3417, 3680, 0, +3547, 3812, 0, +3678, 3944, 0, +3809, 4076, 0, +3941, 4095, 0, +1563, 0, 1335, +1561, 0, 1325, +1559, 0, 1310, +1559, 0, 1285, +1559, 0, 1250, +1559, 0, 1198, +1559, 0, 1118, +1559, 0, 981, +1559, 0, 696, +1559, 0, 0, +1559, 0, 0, +1559, 966, 0, +1693, 1439, 0, +1827, 1722, 0, +1960, 1941, 0, +2053, 2093, 0, +2137, 2225, 0, +2230, 2358, 0, +2331, 2490, 0, +2437, 2623, 0, +2550, 2755, 0, +2667, 2887, 0, +2787, 3019, 0, +2910, 3152, 0, +3035, 3283, 0, +3162, 3416, 0, +3290, 3548, 0, +3419, 3680, 0, +3549, 3812, 0, +3679, 3944, 0, +3810, 4076, 0, +3941, 4095, 0, +1696, 0, 1457, +1695, 0, 1450, +1693, 0, 1439, +1693, 0, 1420, +1693, 0, 1394, +1693, 0, 1357, +1693, 0, 1302, +1693, 0, 1216, +1693, 0, 1067, +1693, 0, 736, +1693, 0, 0, +1693, 0, 0, +1693, 1080, 0, +1827, 1565, 0, +1960, 1851, 0, +2093, 2071, 0, +2188, 2225, 0, +2271, 2358, 0, +2364, 2490, 0, +2464, 2623, 0, +2571, 2755, 0, +2683, 2887, 0, +2799, 3019, 0, +2919, 3152, 0, +3042, 3283, 0, +3167, 3416, 0, +3294, 3548, 0, +3422, 3680, 0, +3551, 3812, 0, +3681, 3944, 0, +3811, 4076, 0, +3942, 4095, 0, +1828, 0, 1582, +1828, 0, 1576, +1827, 0, 1568, +1827, 0, 1554, +1827, 0, 1535, +1827, 0, 1508, +1827, 0, 1469, +1827, 0, 1412, +1827, 0, 1321, +1827, 0, 1161, +1827, 0, 786, +1827, 0, 0, +1827, 0, 0, +1827, 1198, 0, +1960, 1692, 0, +2093, 1981, 0, +2225, 2202, 0, +2322, 2358, 0, +2406, 2490, 0, +2498, 2623, 0, +2598, 2755, 0, +2704, 2887, 0, +2816, 3019, 0, +2932, 3152, 0, +3052, 3283, 0, +3175, 3416, 0, +3300, 3548, 0, +3426, 3680, 0, +3554, 3812, 0, +3683, 3944, 0, +3813, 4076, 0, +3944, 4095, 0, +1961, 0, 1709, +1961, 0, 1705, +1960, 0, 1699, +1960, 0, 1688, +1960, 0, 1674, +1960, 0, 1654, +1960, 0, 1626, +1960, 0, 1586, +1960, 0, 1526, +1960, 0, 1431, +1960, 0, 1263, +1960, 0, 844, +1960, 0, 0, +1960, 0, 0, +1960, 1320, 0, +2093, 1821, 0, +2225, 2111, 0, +2358, 2333, 0, +2456, 2490, 0, +2539, 2623, 0, +2631, 2755, 0, +2731, 2887, 0, +2836, 3019, 0, +2948, 3152, 0, +3064, 3283, 0, +3184, 3416, 0, +3307, 3548, 0, +3432, 3680, 0, +3559, 3812, 0, +3687, 3944, 0, +3816, 4076, 0, +3945, 4095, 0, +2094, 0, 1837, +2093, 0, 1834, +2093, 0, 1829, +2093, 0, 1821, +2093, 0, 1811, +2093, 0, 1796, +2093, 0, 1776, +2093, 0, 1748, +2093, 0, 1706, +2093, 0, 1645, +2093, 0, 1547, +2093, 0, 1370, +2093, 0, 913, +2093, 0, 0, +2093, 0, 0, +2093, 1444, 0, +2225, 1950, 0, +2358, 2241, 0, +2490, 2464, 0, +2589, 2623, 0, +2672, 2755, 0, +2764, 2887, 0, +2863, 3019, 0, +2969, 3152, 0, +3081, 3283, 0, +3197, 3416, 0, +3317, 3548, 0, +3439, 3680, 0, +3564, 3812, 0, +3691, 3944, 0, +3819, 4076, 0, +3948, 4095, 0, +2226, 0, 1966, +2226, 0, 1963, +2225, 0, 1960, +2225, 0, 1954, +2225, 0, 1946, +2225, 0, 1936, +2225, 0, 1921, +2225, 0, 1900, +2225, 0, 1871, +2225, 0, 1829, +2225, 0, 1767, +2225, 0, 1666, +2225, 0, 1484, +2225, 0, 990, +2225, 0, 0, +2225, 0, 0, +2225, 1570, 0, +2358, 2080, 0, +2490, 2373, 0, +2623, 2596, 0, +2722, 2755, 0, +2805, 2887, 0, +2896, 3019, 0, +2996, 3152, 0, +3101, 3283, 0, +3213, 3416, 0, +3329, 3548, 0, +3449, 3680, 0, +3572, 3812, 0, +3696, 3944, 0, +3823, 4076, 0, +3951, 4095, 0, +2358, 0, 2096, +2358, 0, 2094, +2358, 0, 2091, +2358, 0, 2087, +2358, 0, 2081, +2358, 0, 2073, +2358, 0, 2062, +2358, 0, 2047, +2358, 0, 2027, +2358, 0, 1997, +2358, 0, 1955, +2358, 0, 1891, +2358, 0, 1788, +2358, 0, 1600, +2358, 0, 1076, +2358, 0, 0, +2358, 0, 0, +2358, 1698, 0, +2490, 2211, 0, +2623, 2504, 0, +2755, 2728, 0, +2855, 2887, 0, +2938, 3019, 0, +3029, 3152, 0, +3128, 3283, 0, +3234, 3416, 0, +3346, 3548, 0, +3462, 3680, 0, +3581, 3812, 0, +3704, 3944, 0, +3828, 4076, 0, +3955, 4095, 0, +2491, 0, 2226, +2491, 0, 2225, +2490, 0, 2223, +2490, 0, 2220, +2490, 0, 2215, +2490, 0, 2209, +2490, 0, 2202, +2490, 0, 2190, +2490, 0, 2175, +2490, 0, 2154, +2490, 0, 2125, +2490, 0, 2082, +2490, 0, 2017, +2490, 0, 1913, +2490, 0, 1722, +2490, 0, 1173, +2490, 0, 0, +2490, 0, 0, +2490, 1826, 0, +2623, 2342, 0, +2755, 2636, 0, +2887, 2859, 0, +2987, 3019, 0, +3070, 3152, 0, +3161, 3283, 0, +3260, 3416, 0, +3366, 3548, 0, +3478, 3680, 0, +3594, 3812, 0, +3713, 3944, 0, +3836, 4076, 0, +3961, 4095, 0, +2623, 0, 2357, +2623, 0, 2356, +2623, 0, 2355, +2623, 0, 2352, +2623, 0, 2349, +2623, 0, 2345, +2623, 0, 2338, +2623, 0, 2331, +2623, 0, 2320, +2623, 0, 2304, +2623, 0, 2283, +2623, 0, 2253, +2623, 0, 2210, +2623, 0, 2144, +2623, 0, 2039, +2623, 0, 1845, +2623, 0, 1275, +2623, 0, 0, +2623, 0, 0, +2623, 1956, 0, +2755, 2474, 0, +2887, 2767, 0, +3019, 2991, 0, +3120, 3152, 0, +3202, 3283, 0, +3294, 3416, 0, +3393, 3548, 0, +3499, 3680, 0, +3610, 3812, 0, +3726, 3944, 0, +3845, 4076, 0, +3968, 4095, 0, +2755, 0, 2488, +2755, 0, 2488, +2755, 0, 2486, +2755, 0, 2485, +2755, 0, 2482, +2755, 0, 2479, +2755, 0, 2475, +2755, 0, 2469, +2755, 0, 2460, +2755, 0, 2449, +2755, 0, 2434, +2755, 0, 2413, +2755, 0, 2383, +2755, 0, 2339, +2755, 0, 2274, +2755, 0, 2167, +2755, 0, 1971, +2755, 0, 1386, +2755, 0, 0, +2755, 0, 0, +2755, 2086, 0, +2887, 2605, 0, +3019, 2898, 0, +3152, 3123, 0, +3252, 3283, 0, +3335, 3416, 0, +3426, 3548, 0, +3525, 3680, 0, +3631, 3812, 0, +3742, 3944, 0, +3858, 4076, 0, +3978, 4095, 0, +2887, 0, 2620, +2887, 0, 2619, +2887, 0, 2618, +2887, 0, 2617, +2887, 0, 2615, +2887, 0, 2613, +2887, 0, 2609, +2887, 0, 2605, +2887, 0, 2599, +2887, 0, 2591, +2887, 0, 2580, +2887, 0, 2564, +2887, 0, 2543, +2887, 0, 2513, +2887, 0, 2469, +2887, 0, 2403, +2887, 0, 2296, +2887, 0, 2098, +2887, 0, 1497, +2887, 0, 0, +2887, 0, 0, +2887, 2217, 0, +3019, 2736, 0, +3152, 3031, 0, +3283, 3255, 0, +3384, 3416, 0, +3467, 3548, 0, +3558, 3680, 0, +3657, 3812, 0, +3763, 3944, 0, +3874, 4076, 0, +3990, 4095, 0, +3019, 0, 2751, +3019, 0, 2751, +3019, 0, 2750, +3019, 0, 2749, +3019, 0, 2747, +3019, 0, 2746, +3019, 0, 2743, +3019, 0, 2740, +3019, 0, 2735, +3019, 0, 2729, +3019, 0, 2721, +3019, 0, 2710, +3019, 0, 2695, +3019, 0, 2673, +3019, 0, 2643, +3019, 0, 2599, +3019, 0, 2533, +3019, 0, 2426, +3019, 0, 2225, +3019, 0, 1613, +3019, 0, 0, +3019, 0, 0, +3019, 2347, 0, +3152, 2869, 0, +3283, 3163, 0, +3416, 3387, 0, +3516, 3548, 0, +3599, 3680, 0, +3690, 3812, 0, +3790, 3944, 0, +3895, 4076, 0, +4006, 4095, 0, +3152, 0, 2883, +3152, 0, 2883, +3152, 0, 2882, +3152, 0, 2881, +3152, 0, 2880, +3152, 0, 2879, +3152, 0, 2877, +3152, 0, 2875, +3152, 0, 2871, +3152, 0, 2867, +3152, 0, 2861, +3152, 0, 2853, +3152, 0, 2842, +3152, 0, 2826, +3152, 0, 2805, +3152, 0, 2774, +3152, 0, 2730, +3152, 0, 2664, +3152, 0, 2556, +3152, 0, 2355, +3152, 0, 1735, +3152, 0, 0, +3152, 0, 0, +3152, 2479, 0, +3283, 2999, 0, +3416, 3294, 0, +3548, 3519, 0, +3649, 3680, 0, +3731, 3812, 0, +3823, 3944, 0, +3921, 4076, 0, +4027, 4095, 0, +3284, 0, 3014, +3283, 0, 3014, +3283, 0, 3014, +3283, 0, 3013, +3283, 0, 3013, +3283, 0, 3011, +3283, 0, 3010, +3283, 0, 3008, +3283, 0, 3006, +3283, 0, 3002, +3283, 0, 2998, +3283, 0, 2992, +3283, 0, 2984, +3283, 0, 2973, +3283, 0, 2957, +3283, 0, 2936, +3283, 0, 2905, +3283, 0, 2861, +3283, 0, 2794, +3283, 0, 2686, +3283, 0, 2484, +3283, 0, 1856, +3283, 0, 0, +3283, 0, 0, +3283, 2610, 0, +3416, 3132, 0, +3548, 3427, 0, +3680, 3651, 0, +3781, 3812, 0, +3863, 3944, 0, +3955, 4076, 0, +4054, 4095, 0, +3416, 0, 3147, +3416, 0, 3146, +3416, 0, 3146, +3416, 0, 3146, +3416, 0, 3145, +3416, 0, 3144, +3416, 0, 3143, +3416, 0, 3142, +3416, 0, 3140, +3416, 0, 3138, +3416, 0, 3134, +3416, 0, 3130, +3416, 0, 3124, +3416, 0, 3115, +3416, 0, 3104, +3416, 0, 3089, +3416, 0, 3067, +3416, 0, 3037, +3416, 0, 2992, +3416, 0, 2926, +3416, 0, 2817, +3416, 0, 2615, +3416, 0, 1986, +3416, 0, 0, +3416, 0, 0, +3416, 2742, 0, +3548, 3264, 0, +3680, 3559, 0, +3812, 3783, 0, +3913, 3944, 0, +3996, 4076, 0, +4087, 4095, 0, +3548, 0, 3279, +3548, 0, 3278, +3548, 0, 3278, +3548, 0, 3278, +3548, 0, 3277, +3548, 0, 3277, +3548, 0, 3276, +3548, 0, 3275, +3548, 0, 3274, +3548, 0, 3272, +3548, 0, 3269, +3548, 0, 3266, +3548, 0, 3261, +3548, 0, 3256, +3548, 0, 3247, +3548, 0, 3236, +3548, 0, 3221, +3548, 0, 3199, +3548, 0, 3168, +3548, 0, 3124, +3548, 0, 3057, +3548, 0, 2949, +3548, 0, 2746, +3548, 0, 2111, +3548, 0, 0, +3548, 0, 0, +3548, 2873, 0, +3680, 3396, 0, +3812, 3691, 0, +3944, 3915, 0, +4045, 4076, 0, +4095, 4095, 0, +3680, 0, 3410, +3680, 0, 3410, +3680, 0, 3410, +3680, 0, 3410, +3680, 0, 3410, +3680, 0, 3409, +3680, 0, 3409, +3680, 0, 3408, +3680, 0, 3407, +3680, 0, 3405, +3680, 0, 3404, +3680, 0, 3401, +3680, 0, 3398, +3680, 0, 3393, +3680, 0, 3387, +3680, 0, 3379, +3680, 0, 3368, +3680, 0, 3353, +3680, 0, 3331, +3680, 0, 3300, +3680, 0, 3256, +3680, 0, 3189, +3680, 0, 3081, +3680, 0, 2877, +3680, 0, 2242, +3680, 0, 0, +3680, 0, 0, +3680, 3005, 0, +3812, 3528, 0, +3944, 3822, 0, +4076, 4047, 0, +4095, 4095, 0, +3812, 0, 3543, +3812, 0, 3543, +3812, 0, 3542, +3812, 0, 3542, +3812, 0, 3542, +3812, 0, 3541, +3812, 0, 3541, +3812, 0, 3541, +3812, 0, 3540, +3812, 0, 3539, +3812, 0, 3537, +3812, 0, 3536, +3812, 0, 3533, +3812, 0, 3530, +3812, 0, 3525, +3812, 0, 3519, +3812, 0, 3511, +3812, 0, 3500, +3812, 0, 3484, +3812, 0, 3463, +3812, 0, 3432, +3812, 0, 3388, +3812, 0, 3321, +3812, 0, 3212, +3812, 0, 3009, +3812, 0, 2371, +3812, 0, 0, +3812, 0, 0, +3812, 3137, 0, +3944, 3660, 0, +4076, 3954, 0, +4095, 4095, 0, +3944, 0, 3674, +3944, 0, 3674, +3944, 0, 3674, +3944, 0, 3674, +3944, 0, 3674, +3944, 0, 3674, +3944, 0, 3673, +3944, 0, 3673, +3944, 0, 3673, +3944, 0, 3672, +3944, 0, 3671, +3944, 0, 3669, +3944, 0, 3668, +3944, 0, 3665, +3944, 0, 3662, +3944, 0, 3657, +3944, 0, 3651, +3944, 0, 3643, +3944, 0, 3632, +3944, 0, 3616, +3944, 0, 3595, +3944, 0, 3564, +3944, 0, 3520, +3944, 0, 3453, +3944, 0, 3344, +3944, 0, 3140, +3944, 0, 2500, +3944, 0, 0, +3944, 0, 0, +3944, 3269, 0, +4076, 3792, 0, +4095, 4087, 0, +4076, 0, 3806, +4076, 0, 3806, +4076, 0, 3806, +4076, 0, 3806, +4076, 0, 3806, +4076, 0, 3806, +4076, 0, 3805, +4076, 0, 3805, +4076, 0, 3805, +4076, 0, 3804, +4076, 0, 3803, +4076, 0, 3803, +4076, 0, 3801, +4076, 0, 3799, +4076, 0, 3797, +4076, 0, 3793, +4076, 0, 3789, +4076, 0, 3783, +4076, 0, 3775, +4076, 0, 3763, +4076, 0, 3748, +4076, 0, 3726, +4076, 0, 3696, +4076, 0, 3651, +4076, 0, 3585, +4076, 0, 3476, +4076, 0, 3272, +4076, 0, 2628, +4076, 0, 0, +4076, 0, 0, +4076, 3401, 0, +4095, 3924, 0, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3938, +4095, 0, 3938, +4095, 0, 3938, +4095, 0, 3938, +4095, 0, 3937, +4095, 0, 3937, +4095, 0, 3937, +4095, 0, 3936, +4095, 0, 3935, +4095, 0, 3933, +4095, 0, 3932, +4095, 0, 3929, +4095, 0, 3926, +4095, 0, 3921, +4095, 0, 3915, +4095, 0, 3907, +4095, 0, 3896, +4095, 0, 3880, +4095, 0, 3859, +4095, 0, 3828, +4095, 0, 3784, +4095, 0, 3717, +4095, 0, 3608, +4095, 0, 3404, +4095, 0, 2762, +4095, 0, 0, +4095, 0, 0, +4095, 3533, 0, +0, 312, 466, +0, 419, 466, +0, 466, 388, +0, 466, 154, +0, 609, 0, +59, 750, 0, +350, 888, 0, +573, 1025, 0, +762, 1160, 0, +934, 1295, 0, +1092, 1429, 0, +1244, 1563, 0, +1390, 1696, 0, +1532, 1828, 0, +1672, 1961, 0, +1809, 2094, 0, +1945, 2226, 0, +2080, 2358, 0, +2215, 2491, 0, +2348, 2623, 0, +2482, 2755, 0, +2615, 2887, 0, +2747, 3019, 0, +2880, 3152, 0, +3012, 3284, 0, +3145, 3416, 0, +3277, 3548, 0, +3410, 3680, 0, +3542, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3938, 4095, 0, +0, 171, 466, +15, 333, 450, +15, 450, 432, +15, 450, 225, +0, 598, 0, +258, 741, 0, +466, 882, 0, +647, 1020, 0, +813, 1157, 0, +968, 1292, 0, +1118, 1427, 0, +1262, 1561, 0, +1403, 1695, 0, +1542, 1828, 0, +1679, 1961, 0, +1814, 2093, 0, +1949, 2226, 0, +2083, 2358, 0, +2217, 2491, 0, +2350, 2623, 0, +2483, 2755, 0, +2616, 2887, 0, +2748, 3019, 0, +2881, 3152, 0, +3013, 3283, 0, +3145, 3416, 0, +3278, 3548, 0, +3410, 3680, 0, +3542, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3938, 4095, 0, +0, 0, 466, +15, 145, 450, +218, 361, 427, +218, 427, 306, +277, 582, 148, +435, 730, 34, +585, 873, 0, +731, 1014, 0, +873, 1152, 0, +1012, 1289, 0, +1149, 1424, 0, +1285, 1559, 0, +1420, 1693, 0, +1554, 1827, 0, +1688, 1960, 0, +1821, 2093, 0, +1954, 2225, 0, +2087, 2358, 0, +2220, 2490, 0, +2352, 2623, 0, +2485, 2755, 0, +2617, 2887, 0, +2749, 3019, 0, +2881, 3152, 0, +3013, 3283, 0, +3146, 3416, 0, +3278, 3548, 0, +3410, 3680, 0, +3542, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3939, 4095, 0, +154, 0, 466, +225, 15, 450, +306, 218, 427, +396, 396, 396, +494, 560, 350, +598, 714, 280, +708, 862, 166, +823, 1005, 0, +942, 1146, 0, +1064, 1284, 0, +1188, 1421, 0, +1315, 1557, 0, +1442, 1691, 0, +1571, 1825, 0, +1700, 1959, 0, +1830, 2092, 0, +1961, 2225, 0, +2092, 2357, 0, +2223, 2490, 0, +2355, 2622, 0, +2487, 2755, 0, +2619, 2887, 0, +2750, 3019, 0, +2882, 3151, 0, +3014, 3283, 0, +3146, 3416, 0, +3278, 3548, 0, +3410, 3680, 0, +3542, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3939, 4095, 0, +485, 0, 609, +520, 0, 598, +564, 148, 582, +560, 350, 494, +560, 438, 350, +714, 696, 280, +815, 862, 166, +908, 1005, 0, +1009, 1146, 0, +1116, 1284, 0, +1228, 1421, 0, +1345, 1557, 0, +1465, 1691, 0, +1588, 1825, 0, +1714, 1959, 0, +1841, 2092, 0, +1969, 2225, 0, +2098, 2357, 0, +2228, 2490, 0, +2358, 2622, 0, +2489, 2755, 0, +2620, 2887, 0, +2751, 3019, 0, +2883, 3151, 0, +3015, 3283, 0, +3147, 3416, 0, +3279, 3548, 0, +3411, 3680, 0, +3543, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3939, 4095, 0, +723, 0, 750, +741, 0, 738, +730, 34, 683, +714, 280, 598, +714, 280, 409, +714, 490, 280, +862, 784, 166, +1002, 1005, 0, +1086, 1146, 0, +1177, 1284, 0, +1277, 1421, 0, +1384, 1557, 0, +1495, 1691, 0, +1611, 1825, 0, +1731, 1959, 0, +1854, 2092, 0, +1979, 2225, 0, +2105, 2357, 0, +2234, 2490, 0, +2362, 2622, 0, +2492, 2755, 0, +2623, 2887, 0, +2753, 3019, 0, +2885, 3151, 0, +3016, 3283, 0, +3147, 3416, 0, +3279, 3548, 0, +3411, 3680, 0, +3543, 3812, 0, +3675, 3944, 0, +3807, 4076, 0, +3939, 4095, 0, +888, 0, 852, +882, 0, 822, +873, 0, 776, +862, 166, 708, +862, 166, 567, +862, 166, 264, +862, 550, 166, +1005, 881, 0, +1146, 1119, 0, +1249, 1284, 0, +1335, 1421, 0, +1430, 1557, 0, +1532, 1691, 0, +1640, 1825, 0, +1754, 1959, 0, +1871, 2092, 0, +1992, 2225, 0, +2115, 2357, 0, +2241, 2490, 0, +2368, 2622, 0, +2497, 2755, 0, +2626, 2887, 0, +2756, 3019, 0, +2886, 3151, 0, +3017, 3283, 0, +3148, 3416, 0, +3280, 3548, 0, +3412, 3680, 0, +3543, 3812, 0, +3675, 3944, 0, +3807, 4076, 0, +3939, 4095, 0, +1025, 0, 939, +1020, 0, 914, +1014, 0, 877, +1005, 0, 823, +1005, 0, 717, +1005, 0, 523, +1005, 0, 0, +1005, 620, 0, +1146, 983, 0, +1284, 1235, 0, +1403, 1421, 0, +1486, 1557, 0, +1577, 1691, 0, +1676, 1825, 0, +1781, 1959, 0, +1893, 2092, 0, +2009, 2225, 0, +2128, 2357, 0, +2251, 2490, 0, +2375, 2622, 0, +2502, 2755, 0, +2630, 2887, 0, +2759, 3019, 0, +2889, 3151, 0, +3019, 3283, 0, +3150, 3416, 0, +3281, 3548, 0, +3412, 3680, 0, +3544, 3812, 0, +3676, 3944, 0, +3807, 4076, 0, +3939, 4095, 0, +1160, 0, 1033, +1157, 0, 1013, +1152, 0, 984, +1146, 0, 942, +1146, 0, 863, +1146, 0, 730, +1146, 0, 455, +1146, 0, 0, +1146, 700, 0, +1284, 1093, 0, +1421, 1353, 0, +1551, 1557, 0, +1631, 1691, 0, +1720, 1825, 0, +1817, 1959, 0, +1920, 2092, 0, +2030, 2225, 0, +2145, 2357, 0, +2264, 2490, 0, +2385, 2622, 0, +2510, 2755, 0, +2636, 2887, 0, +2763, 3019, 0, +2892, 3151, 0, +3021, 3283, 0, +3151, 3416, 0, +3282, 3548, 0, +3413, 3680, 0, +3545, 3812, 0, +3676, 3944, 0, +3808, 4076, 0, +3940, 4095, 0, +1295, 0, 1135, +1292, 0, 1119, +1289, 0, 1096, +1284, 0, 1064, +1284, 0, 1005, +1284, 0, 911, +1284, 0, 746, +1284, 0, 346, +1284, 0, 0, +1284, 788, 0, +1421, 1207, 0, +1557, 1476, 0, +1691, 1688, 0, +1772, 1825, 0, +1860, 1959, 0, +1955, 2092, 0, +2058, 2225, 0, +2166, 2357, 0, +2280, 2490, 0, +2398, 2622, 0, +2520, 2755, 0, +2643, 2887, 0, +2769, 3019, 0, +2896, 3151, 0, +3025, 3283, 0, +3154, 3416, 0, +3284, 3548, 0, +3415, 3680, 0, +3545, 3812, 0, +3677, 3944, 0, +3808, 4076, 0, +3940, 4095, 0, +1429, 0, 1244, +1427, 0, 1231, +1424, 0, 1213, +1421, 0, 1188, +1421, 0, 1144, +1421, 0, 1077, +1421, 0, 969, +1421, 0, 767, +1421, 0, 141, +1421, 0, 0, +1421, 885, 0, +1557, 1326, 0, +1691, 1600, 0, +1825, 1816, 0, +1911, 1959, 0, +1997, 2092, 0, +2092, 2225, 0, +2193, 2357, 0, +2302, 2490, 0, +2414, 2622, 0, +2532, 2755, 0, +2653, 2887, 0, +2776, 3019, 0, +2902, 3151, 0, +3029, 3283, 0, +3157, 3416, 0, +3286, 3548, 0, +3416, 3680, 0, +3547, 3812, 0, +3678, 3944, 0, +3809, 4076, 0, +3941, 4095, 0, +1563, 0, 1357, +1561, 0, 1347, +1559, 0, 1333, +1557, 0, 1315, +1557, 0, 1281, +1557, 0, 1233, +1557, 0, 1159, +1557, 0, 1037, +1557, 0, 794, +1557, 0, 0, +1557, 0, 0, +1557, 988, 0, +1691, 1447, 0, +1825, 1727, 0, +1959, 1944, 0, +2049, 2092, 0, +2134, 2225, 0, +2228, 2357, 0, +2329, 2490, 0, +2436, 2622, 0, +2549, 2755, 0, +2666, 2887, 0, +2786, 3019, 0, +2909, 3151, 0, +3034, 3283, 0, +3161, 3416, 0, +3290, 3548, 0, +3419, 3680, 0, +3549, 3812, 0, +3679, 3944, 0, +3810, 4076, 0, +3941, 4095, 0, +1696, 0, 1475, +1695, 0, 1467, +1693, 0, 1456, +1691, 0, 1442, +1691, 0, 1417, +1691, 0, 1382, +1691, 0, 1330, +1691, 0, 1249, +1691, 0, 1113, +1691, 0, 827, +1691, 0, 0, +1691, 0, 0, +1691, 1098, 0, +1825, 1571, 0, +1959, 1854, 0, +2092, 2073, 0, +2185, 2225, 0, +2269, 2357, 0, +2362, 2490, 0, +2463, 2622, 0, +2570, 2755, 0, +2682, 2887, 0, +2798, 3019, 0, +2919, 3151, 0, +3042, 3283, 0, +3167, 3416, 0, +3294, 3548, 0, +3422, 3680, 0, +3551, 3812, 0, +3681, 3944, 0, +3811, 4076, 0, +3942, 4095, 0, +1828, 0, 1596, +1828, 0, 1590, +1827, 0, 1582, +1825, 0, 1571, +1825, 0, 1552, +1825, 0, 1526, +1825, 0, 1489, +1825, 0, 1434, +1825, 0, 1348, +1825, 0, 1199, +1825, 0, 869, +1825, 0, 0, +1825, 0, 0, +1825, 1212, 0, +1959, 1697, 0, +2092, 1983, 0, +2225, 2203, 0, +2320, 2357, 0, +2404, 2490, 0, +2496, 2622, 0, +2596, 2755, 0, +2703, 2887, 0, +2815, 3019, 0, +2932, 3151, 0, +3051, 3283, 0, +3174, 3416, 0, +3299, 3548, 0, +3426, 3680, 0, +3554, 3812, 0, +3683, 3944, 0, +3813, 4076, 0, +3944, 4095, 0, +1961, 0, 1719, +1961, 0, 1715, +1960, 0, 1708, +1959, 0, 1700, +1959, 0, 1686, +1959, 0, 1667, +1959, 0, 1640, +1959, 0, 1601, +1959, 0, 1544, +1959, 0, 1453, +1959, 0, 1294, +1959, 0, 917, +1959, 0, 0, +1959, 0, 0, +1959, 1331, 0, +2092, 1824, 0, +2225, 2112, 0, +2357, 2334, 0, +2454, 2490, 0, +2538, 2622, 0, +2630, 2755, 0, +2730, 2887, 0, +2836, 3019, 0, +2948, 3151, 0, +3064, 3283, 0, +3184, 3416, 0, +3307, 3548, 0, +3432, 3680, 0, +3558, 3812, 0, +3686, 3944, 0, +3815, 4076, 0, +3945, 4095, 0, +2094, 0, 1845, +2093, 0, 1841, +2093, 0, 1837, +2092, 0, 1830, +2092, 0, 1820, +2092, 0, 1806, +2092, 0, 1786, +2092, 0, 1758, +2092, 0, 1718, +2092, 0, 1658, +2092, 0, 1564, +2092, 0, 1394, +2092, 0, 977, +2092, 0, 0, +2092, 0, 0, +2092, 1452, 0, +2225, 1953, 0, +2357, 2243, 0, +2490, 2465, 0, +2588, 2622, 0, +2671, 2755, 0, +2763, 2887, 0, +2863, 3019, 0, +2969, 3151, 0, +3080, 3283, 0, +3196, 3416, 0, +3316, 3548, 0, +3439, 3680, 0, +3564, 3812, 0, +3691, 3944, 0, +3818, 4076, 0, +3948, 4095, 0, +2226, 0, 1972, +2226, 0, 1969, +2225, 0, 1966, +2225, 0, 1961, +2225, 0, 1953, +2225, 0, 1943, +2225, 0, 1928, +2225, 0, 1908, +2225, 0, 1880, +2225, 0, 1839, +2225, 0, 1777, +2225, 0, 1679, +2225, 0, 1503, +2225, 0, 1044, +2225, 0, 0, +2225, 0, 0, +2225, 1576, 0, +2357, 2082, 0, +2490, 2374, 0, +2622, 2596, 0, +2721, 2755, 0, +2804, 2887, 0, +2896, 3019, 0, +2995, 3151, 0, +3101, 3283, 0, +3213, 3416, 0, +3329, 3548, 0, +3449, 3680, 0, +3571, 3812, 0, +3696, 3944, 0, +3823, 4076, 0, +3951, 4095, 0, +2358, 0, 2100, +2358, 0, 2098, +2358, 0, 2096, +2357, 0, 2092, +2357, 0, 2086, +2357, 0, 2078, +2357, 0, 2068, +2357, 0, 2053, +2357, 0, 2032, +2357, 0, 2004, +2357, 0, 1962, +2357, 0, 1899, +2357, 0, 1798, +2357, 0, 1615, +2357, 0, 1122, +2357, 0, 0, +2357, 0, 0, +2357, 1702, 0, +2490, 2213, 0, +2622, 2505, 0, +2755, 2728, 0, +2854, 2887, 0, +2937, 3019, 0, +3029, 3151, 0, +3128, 3283, 0, +3234, 3416, 0, +3345, 3548, 0, +3461, 3680, 0, +3581, 3812, 0, +3703, 3944, 0, +3828, 4076, 0, +3955, 4095, 0, +2491, 0, 2230, +2491, 0, 2228, +2490, 0, 2226, +2490, 0, 2223, +2490, 0, 2219, +2490, 0, 2213, +2490, 0, 2206, +2490, 0, 2195, +2490, 0, 2180, +2490, 0, 2159, +2490, 0, 2129, +2490, 0, 2087, +2490, 0, 2023, +2490, 0, 1920, +2490, 0, 1733, +2490, 0, 1210, +2490, 0, 0, +2490, 0, 0, +2490, 1830, 0, +2622, 2343, 0, +2755, 2636, 0, +2887, 2860, 0, +2987, 3019, 0, +3070, 3151, 0, +3161, 3283, 0, +3260, 3416, 0, +3366, 3548, 0, +3478, 3680, 0, +3594, 3812, 0, +3713, 3944, 0, +3836, 4076, 0, +3961, 4095, 0, +2623, 0, 2359, +2623, 0, 2358, +2623, 0, 2357, +2622, 0, 2355, +2622, 0, 2352, +2622, 0, 2347, +2622, 0, 2341, +2622, 0, 2334, +2622, 0, 2323, +2622, 0, 2308, +2622, 0, 2287, +2622, 0, 2256, +2622, 0, 2214, +2622, 0, 2149, +2622, 0, 2045, +2622, 0, 1853, +2622, 0, 1304, +2622, 0, 0, +2622, 0, 0, +2622, 1958, 0, +2755, 2475, 0, +2887, 2768, 0, +3019, 2991, 0, +3119, 3151, 0, +3202, 3283, 0, +3293, 3416, 0, +3393, 3548, 0, +3499, 3680, 0, +3610, 3812, 0, +3726, 3944, 0, +3845, 4076, 0, +3968, 4095, 0, +2755, 0, 2490, +2755, 0, 2489, +2755, 0, 2488, +2755, 0, 2487, +2755, 0, 2484, +2755, 0, 2481, +2755, 0, 2477, +2755, 0, 2471, +2755, 0, 2463, +2755, 0, 2452, +2755, 0, 2436, +2755, 0, 2415, +2755, 0, 2386, +2755, 0, 2342, +2755, 0, 2277, +2755, 0, 2172, +2755, 0, 1977, +2755, 0, 1409, +2755, 0, 0, +2755, 0, 0, +2755, 2088, 0, +2887, 2605, 0, +3019, 2899, 0, +3151, 3123, 0, +3252, 3283, 0, +3335, 3416, 0, +3426, 3548, 0, +3525, 3680, 0, +3631, 3812, 0, +3742, 3944, 0, +3858, 4076, 0, +3978, 4095, 0, +2887, 0, 2621, +2887, 0, 2620, +2887, 0, 2620, +2887, 0, 2619, +2887, 0, 2617, +2887, 0, 2614, +2887, 0, 2611, +2887, 0, 2607, +2887, 0, 2601, +2887, 0, 2592, +2887, 0, 2581, +2887, 0, 2566, +2887, 0, 2545, +2887, 0, 2515, +2887, 0, 2471, +2887, 0, 2406, +2887, 0, 2299, +2887, 0, 2103, +2887, 0, 1516, +2887, 0, 0, +2887, 0, 0, +2887, 2218, 0, +3019, 2736, 0, +3151, 3031, 0, +3283, 3255, 0, +3384, 3416, 0, +3467, 3548, 0, +3558, 3680, 0, +3657, 3812, 0, +3763, 3944, 0, +3874, 4076, 0, +3990, 4095, 0, +3019, 0, 2752, +3019, 0, 2752, +3019, 0, 2751, +3019, 0, 2750, +3019, 0, 2749, +3019, 0, 2747, +3019, 0, 2745, +3019, 0, 2741, +3019, 0, 2737, +3019, 0, 2731, +3019, 0, 2723, +3019, 0, 2712, +3019, 0, 2696, +3019, 0, 2675, +3019, 0, 2645, +3019, 0, 2601, +3019, 0, 2535, +3019, 0, 2428, +3019, 0, 2229, +3019, 0, 1628, +3019, 0, 0, +3019, 0, 0, +3019, 2348, 0, +3151, 2869, 0, +3283, 3163, 0, +3416, 3387, 0, +3516, 3548, 0, +3599, 3680, 0, +3690, 3812, 0, +3790, 3944, 0, +3895, 4076, 0, +4006, 4095, 0, +3152, 0, 2884, +3152, 0, 2883, +3152, 0, 2883, +3151, 0, 2882, +3151, 0, 2881, +3151, 0, 2880, +3151, 0, 2878, +3151, 0, 2876, +3151, 0, 2872, +3151, 0, 2868, +3151, 0, 2862, +3151, 0, 2854, +3151, 0, 2842, +3151, 0, 2827, +3151, 0, 2806, +3151, 0, 2775, +3151, 0, 2732, +3151, 0, 2665, +3151, 0, 2558, +3151, 0, 2358, +3151, 0, 1746, +3151, 0, 0, +3151, 0, 0, +3151, 2480, 0, +3283, 2999, 0, +3416, 3294, 0, +3548, 3519, 0, +3649, 3680, 0, +3731, 3812, 0, +3822, 3944, 0, +3921, 4076, 0, +4027, 4095, 0, +3284, 0, 3015, +3283, 0, 3015, +3283, 0, 3014, +3283, 0, 3014, +3283, 0, 3013, +3283, 0, 3012, +3283, 0, 3011, +3283, 0, 3009, +3283, 0, 3007, +3283, 0, 3003, +3283, 0, 2999, +3283, 0, 2993, +3283, 0, 2985, +3283, 0, 2973, +3283, 0, 2958, +3283, 0, 2936, +3283, 0, 2906, +3283, 0, 2862, +3283, 0, 2795, +3283, 0, 2688, +3283, 0, 2486, +3283, 0, 1864, +3283, 0, 0, +3283, 0, 0, +3283, 2611, 0, +3416, 3132, 0, +3548, 3427, 0, +3680, 3651, 0, +3781, 3812, 0, +3863, 3944, 0, +3955, 4076, 0, +4054, 4095, 0, +3416, 0, 3147, +3416, 0, 3147, +3416, 0, 3147, +3416, 0, 3146, +3416, 0, 3146, +3416, 0, 3145, +3416, 0, 3144, +3416, 0, 3142, +3416, 0, 3141, +3416, 0, 3138, +3416, 0, 3135, +3416, 0, 3130, +3416, 0, 3124, +3416, 0, 3116, +3416, 0, 3105, +3416, 0, 3089, +3416, 0, 3068, +3416, 0, 3038, +3416, 0, 2993, +3416, 0, 2927, +3416, 0, 2818, +3416, 0, 2617, +3416, 0, 1992, +3416, 0, 0, +3416, 0, 0, +3416, 2742, 0, +3548, 3264, 0, +3680, 3559, 0, +3812, 3783, 0, +3913, 3944, 0, +3995, 4076, 0, +4087, 4095, 0, +3548, 0, 3279, +3548, 0, 3279, +3548, 0, 3279, +3548, 0, 3278, +3548, 0, 3278, +3548, 0, 3277, +3548, 0, 3277, +3548, 0, 3275, +3548, 0, 3274, +3548, 0, 3272, +3548, 0, 3270, +3548, 0, 3267, +3548, 0, 3262, +3548, 0, 3256, +3548, 0, 3248, +3548, 0, 3237, +3548, 0, 3221, +3548, 0, 3200, +3548, 0, 3169, +3548, 0, 3125, +3548, 0, 3058, +3548, 0, 2950, +3548, 0, 2747, +3548, 0, 2115, +3548, 0, 0, +3548, 0, 0, +3548, 2874, 0, +3680, 3396, 0, +3812, 3691, 0, +3944, 3915, 0, +4045, 4076, 0, +4095, 4095, 0, +3680, 0, 3411, +3680, 0, 3411, +3680, 0, 3410, +3680, 0, 3410, +3680, 0, 3410, +3680, 0, 3410, +3680, 0, 3409, +3680, 0, 3408, +3680, 0, 3407, +3680, 0, 3406, +3680, 0, 3404, +3680, 0, 3401, +3680, 0, 3398, +3680, 0, 3394, +3680, 0, 3388, +3680, 0, 3379, +3680, 0, 3368, +3680, 0, 3353, +3680, 0, 3331, +3680, 0, 3301, +3680, 0, 3256, +3680, 0, 3189, +3680, 0, 3081, +3680, 0, 2878, +3680, 0, 2246, +3680, 0, 0, +3680, 0, 0, +3680, 3006, 0, +3812, 3528, 0, +3944, 3823, 0, +4076, 4047, 0, +4095, 4095, 0, +3812, 0, 3543, +3812, 0, 3543, +3812, 0, 3543, +3812, 0, 3542, +3812, 0, 3542, +3812, 0, 3542, +3812, 0, 3541, +3812, 0, 3541, +3812, 0, 3540, +3812, 0, 3539, +3812, 0, 3538, +3812, 0, 3536, +3812, 0, 3533, +3812, 0, 3530, +3812, 0, 3526, +3812, 0, 3520, +3812, 0, 3511, +3812, 0, 3500, +3812, 0, 3485, +3812, 0, 3463, +3812, 0, 3432, +3812, 0, 3388, +3812, 0, 3321, +3812, 0, 3213, +3812, 0, 3010, +3812, 0, 2374, +3812, 0, 0, +3812, 0, 0, +3812, 3138, 0, +3944, 3660, 0, +4076, 3954, 0, +4095, 4095, 0, +3944, 0, 3674, +3944, 0, 3674, +3944, 0, 3674, +3944, 0, 3674, +3944, 0, 3674, +3944, 0, 3674, +3944, 0, 3674, +3944, 0, 3673, +3944, 0, 3673, +3944, 0, 3672, +3944, 0, 3671, +3944, 0, 3669, +3944, 0, 3668, +3944, 0, 3665, +3944, 0, 3662, +3944, 0, 3657, +3944, 0, 3651, +3944, 0, 3643, +3944, 0, 3632, +3944, 0, 3616, +3944, 0, 3595, +3944, 0, 3564, +3944, 0, 3520, +3944, 0, 3453, +3944, 0, 3344, +3944, 0, 3141, +3944, 0, 2502, +3944, 0, 0, +3944, 0, 0, +3944, 3269, 0, +4076, 3792, 0, +4095, 4087, 0, +4076, 0, 3806, +4076, 0, 3806, +4076, 0, 3806, +4076, 0, 3806, +4076, 0, 3806, +4076, 0, 3806, +4076, 0, 3806, +4076, 0, 3805, +4076, 0, 3805, +4076, 0, 3805, +4076, 0, 3804, +4076, 0, 3803, +4076, 0, 3801, +4076, 0, 3799, +4076, 0, 3797, +4076, 0, 3794, +4076, 0, 3789, +4076, 0, 3783, +4076, 0, 3775, +4076, 0, 3764, +4076, 0, 3748, +4076, 0, 3727, +4076, 0, 3696, +4076, 0, 3652, +4076, 0, 3585, +4076, 0, 3476, +4076, 0, 3272, +4076, 0, 2630, +4076, 0, 0, +4076, 0, 0, +4076, 3401, 0, +4095, 3924, 0, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3938, +4095, 0, 3938, +4095, 0, 3938, +4095, 0, 3938, +4095, 0, 3937, +4095, 0, 3937, +4095, 0, 3936, +4095, 0, 3935, +4095, 0, 3933, +4095, 0, 3932, +4095, 0, 3929, +4095, 0, 3926, +4095, 0, 3921, +4095, 0, 3915, +4095, 0, 3907, +4095, 0, 3896, +4095, 0, 3880, +4095, 0, 3859, +4095, 0, 3828, +4095, 0, 3784, +4095, 0, 3717, +4095, 0, 3608, +4095, 0, 3405, +4095, 0, 2764, +4095, 0, 0, +4095, 0, 0, +4095, 3534, 0, +0, 427, 609, +0, 512, 609, +0, 606, 609, +0, 609, 485, +0, 609, 224, +0, 750, 0, +0, 888, 0, +371, 1025, 0, +640, 1160, 0, +853, 1295, 0, +1037, 1429, 0, +1205, 1563, 0, +1362, 1696, 0, +1512, 1828, 0, +1657, 1961, 0, +1798, 2094, 0, +1937, 2226, 0, +2074, 2358, 0, +2210, 2491, 0, +2345, 2623, 0, +2479, 2755, 0, +2613, 2887, 0, +2746, 3019, 0, +2879, 3152, 0, +3012, 3284, 0, +3144, 3416, 0, +3277, 3548, 0, +3409, 3680, 0, +3541, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3938, 4095, 0, +0, 322, 609, +0, 444, 598, +0, 551, 598, +0, 598, 520, +0, 598, 286, +0, 741, 0, +190, 882, 0, +482, 1020, 0, +705, 1157, 0, +894, 1292, 0, +1065, 1427, 0, +1225, 1561, 0, +1376, 1695, 0, +1522, 1828, 0, +1664, 1961, 0, +1804, 2093, 0, +1941, 2226, 0, +2077, 2358, 0, +2212, 2491, 0, +2347, 2623, 0, +2481, 2755, 0, +2614, 2887, 0, +2747, 3019, 0, +2880, 3152, 0, +3012, 3283, 0, +3145, 3416, 0, +3277, 3548, 0, +3409, 3680, 0, +3542, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3938, 4095, 0, +0, 127, 609, +0, 303, 598, +148, 466, 582, +148, 582, 564, +148, 582, 357, +132, 730, 34, +390, 873, 0, +598, 1014, 0, +779, 1152, 0, +945, 1289, 0, +1101, 1424, 0, +1250, 1559, 0, +1394, 1693, 0, +1535, 1827, 0, +1674, 1960, 0, +1811, 2093, 0, +1946, 2225, 0, +2081, 2358, 0, +2215, 2490, 0, +2349, 2623, 0, +2482, 2755, 0, +2615, 2887, 0, +2747, 3019, 0, +2880, 3152, 0, +3013, 3283, 0, +3145, 3416, 0, +3277, 3548, 0, +3410, 3680, 0, +3542, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3938, 4095, 0, +0, 0, 609, +0, 0, 598, +148, 277, 582, +350, 494, 560, +350, 560, 438, +409, 714, 280, +567, 862, 166, +717, 1005, 0, +863, 1146, 0, +1005, 1284, 0, +1144, 1421, 0, +1281, 1557, 0, +1417, 1691, 0, +1552, 1825, 0, +1686, 1959, 0, +1820, 2092, 0, +1953, 2225, 0, +2086, 2357, 0, +2219, 2490, 0, +2352, 2622, 0, +2484, 2755, 0, +2617, 2887, 0, +2749, 3019, 0, +2881, 3151, 0, +3013, 3283, 0, +3146, 3416, 0, +3278, 3548, 0, +3410, 3680, 0, +3542, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3939, 4095, 0, +224, 0, 609, +286, 0, 598, +357, 148, 582, +438, 350, 560, +528, 528, 528, +625, 691, 482, +730, 846, 412, +840, 994, 298, +955, 1137, 80, +1074, 1278, 0, +1196, 1416, 0, +1320, 1553, 0, +1446, 1689, 0, +1574, 1823, 0, +1703, 1958, 0, +1832, 2091, 0, +1963, 2224, 0, +2093, 2357, 0, +2224, 2489, 0, +2356, 2622, 0, +2487, 2755, 0, +2619, 2887, 0, +2750, 3019, 0, +2883, 3151, 0, +3014, 3283, 0, +3146, 3416, 0, +3278, 3548, 0, +3410, 3680, 0, +3543, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3939, 4095, 0, +587, 0, 750, +616, 0, 741, +652, 34, 730, +696, 280, 714, +691, 482, 625, +691, 570, 482, +846, 828, 412, +947, 994, 298, +1040, 1137, 80, +1141, 1278, 0, +1248, 1416, 0, +1360, 1553, 0, +1477, 1689, 0, +1598, 1823, 0, +1721, 1958, 0, +1846, 2091, 0, +1973, 2224, 0, +2101, 2357, 0, +2230, 2489, 0, +2360, 2622, 0, +2490, 2755, 0, +2621, 2887, 0, +2752, 3019, 0, +2884, 3151, 0, +3015, 3283, 0, +3147, 3416, 0, +3279, 3548, 0, +3411, 3680, 0, +3543, 3812, 0, +3674, 3944, 0, +3807, 4076, 0, +3939, 4095, 0, +838, 0, 888, +855, 0, 882, +873, 0, 870, +862, 166, 815, +846, 412, 730, +846, 412, 541, +846, 622, 412, +994, 917, 298, +1134, 1137, 80, +1218, 1278, 0, +1310, 1416, 0, +1409, 1553, 0, +1515, 1689, 0, +1627, 1823, 0, +1743, 1958, 0, +1863, 2091, 0, +1986, 2224, 0, +2111, 2357, 0, +2238, 2489, 0, +2366, 2622, 0, +2495, 2755, 0, +2625, 2887, 0, +2755, 3019, 0, +2886, 3151, 0, +3016, 3283, 0, +3148, 3416, 0, +3280, 3548, 0, +3411, 3680, 0, +3543, 3812, 0, +3675, 3944, 0, +3807, 4076, 0, +3939, 4095, 0, +1025, 0, 1006, +1020, 0, 985, +1014, 0, 954, +1005, 0, 908, +994, 298, 840, +994, 298, 699, +994, 298, 397, +994, 682, 298, +1137, 1013, 80, +1278, 1251, 0, +1381, 1416, 0, +1467, 1553, 0, +1562, 1689, 0, +1664, 1823, 0, +1772, 1958, 0, +1885, 2091, 0, +2003, 2224, 0, +2124, 2357, 0, +2247, 2489, 0, +2373, 2622, 0, +2501, 2755, 0, +2629, 2887, 0, +2758, 3019, 0, +2888, 3151, 0, +3018, 3283, 0, +3149, 3416, 0, +3280, 3548, 0, +3412, 3680, 0, +3544, 3812, 0, +3675, 3944, 0, +3807, 4076, 0, +3939, 4095, 0, +1160, 0, 1089, +1157, 0, 1071, +1152, 0, 1045, +1146, 0, 1009, +1137, 80, 955, +1137, 80, 850, +1137, 80, 655, +1137, 80, 81, +1137, 753, 80, +1278, 1116, 0, +1416, 1367, 0, +1535, 1553, 0, +1617, 1689, 0, +1709, 1823, 0, +1808, 1958, 0, +1913, 2091, 0, +2025, 2224, 0, +2141, 2357, 0, +2260, 2489, 0, +2383, 2622, 0, +2508, 2755, 0, +2635, 2887, 0, +2762, 3019, 0, +2891, 3151, 0, +3021, 3283, 0, +3151, 3416, 0, +3282, 3548, 0, +3413, 3680, 0, +3544, 3812, 0, +3676, 3944, 0, +3808, 4076, 0, +3940, 4095, 0, +1295, 0, 1181, +1292, 0, 1166, +1289, 0, 1145, +1284, 0, 1116, +1278, 0, 1074, +1278, 0, 995, +1278, 0, 862, +1278, 0, 587, +1278, 0, 0, +1278, 832, 0, +1416, 1225, 0, +1553, 1486, 0, +1683, 1689, 0, +1763, 1823, 0, +1852, 1958, 0, +1949, 2091, 0, +2053, 2224, 0, +2162, 2357, 0, +2277, 2489, 0, +2396, 2622, 0, +2517, 2755, 0, +2642, 2887, 0, +2768, 3019, 0, +2895, 3151, 0, +3024, 3283, 0, +3154, 3416, 0, +3284, 3548, 0, +3414, 3680, 0, +3545, 3812, 0, +3677, 3944, 0, +3808, 4076, 0, +3940, 4095, 0, +1429, 0, 1280, +1427, 0, 1267, +1424, 0, 1251, +1421, 0, 1228, +1416, 0, 1196, +1416, 0, 1137, +1416, 0, 1043, +1416, 0, 878, +1416, 0, 478, +1416, 0, 0, +1416, 920, 0, +1553, 1340, 0, +1689, 1608, 0, +1823, 1821, 0, +1905, 1958, 0, +1992, 2091, 0, +2087, 2224, 0, +2190, 2357, 0, +2298, 2489, 0, +2412, 2622, 0, +2530, 2755, 0, +2651, 2887, 0, +2775, 3019, 0, +2901, 3151, 0, +3028, 3283, 0, +3157, 3416, 0, +3286, 3548, 0, +3416, 3680, 0, +3547, 3812, 0, +3678, 3944, 0, +3809, 4076, 0, +3941, 4095, 0, +1563, 0, 1385, +1561, 0, 1376, +1559, 0, 1363, +1557, 0, 1345, +1553, 0, 1320, +1553, 0, 1276, +1553, 0, 1209, +1553, 0, 1102, +1553, 0, 900, +1553, 0, 275, +1553, 0, 0, +1553, 1017, 0, +1689, 1457, 0, +1823, 1732, 0, +1958, 1948, 0, +2044, 2091, 0, +2130, 2224, 0, +2224, 2357, 0, +2326, 2489, 0, +2434, 2622, 0, +2547, 2755, 0, +2664, 2887, 0, +2785, 3019, 0, +2908, 3151, 0, +3034, 3283, 0, +3161, 3416, 0, +3289, 3548, 0, +3419, 3680, 0, +3549, 3812, 0, +3679, 3944, 0, +3810, 4076, 0, +3941, 4095, 0, +1696, 0, 1496, +1695, 0, 1489, +1693, 0, 1479, +1691, 0, 1465, +1689, 0, 1446, +1689, 0, 1413, +1689, 0, 1365, +1689, 0, 1291, +1689, 0, 1169, +1689, 0, 926, +1689, 0, 0, +1689, 0, 0, +1689, 1120, 0, +1823, 1579, 0, +1958, 1859, 0, +2091, 2076, 0, +2181, 2224, 0, +2266, 2357, 0, +2360, 2489, 0, +2460, 2622, 0, +2568, 2755, 0, +2681, 2887, 0, +2797, 3019, 0, +2918, 3151, 0, +3041, 3283, 0, +3166, 3416, 0, +3293, 3548, 0, +3422, 3680, 0, +3551, 3812, 0, +3681, 3944, 0, +3811, 4076, 0, +3942, 4095, 0, +1828, 0, 1612, +1828, 0, 1607, +1827, 0, 1599, +1825, 0, 1588, +1823, 0, 1574, +1823, 0, 1549, +1823, 0, 1514, +1823, 0, 1462, +1823, 0, 1382, +1823, 0, 1245, +1823, 0, 960, +1823, 0, 0, +1823, 0, 0, +1823, 1230, 0, +1958, 1703, 0, +2091, 1986, 0, +2224, 2206, 0, +2317, 2357, 0, +2401, 2489, 0, +2494, 2622, 0, +2595, 2755, 0, +2702, 2887, 0, +2814, 3019, 0, +2931, 3151, 0, +3051, 3283, 0, +3174, 3416, 0, +3299, 3548, 0, +3426, 3680, 0, +3554, 3812, 0, +3683, 3944, 0, +3813, 4076, 0, +3944, 4095, 0, +1961, 0, 1732, +1961, 0, 1728, +1960, 0, 1722, +1959, 0, 1714, +1958, 0, 1703, +1958, 0, 1684, +1958, 0, 1658, +1958, 0, 1621, +1958, 0, 1566, +1958, 0, 1480, +1958, 0, 1332, +1958, 0, 1000, +1958, 0, 0, +1958, 0, 0, +1958, 1344, 0, +2091, 1829, 0, +2224, 2115, 0, +2357, 2335, 0, +2452, 2489, 0, +2536, 2622, 0, +2628, 2755, 0, +2728, 2887, 0, +2835, 3019, 0, +2947, 3151, 0, +3063, 3283, 0, +3184, 3416, 0, +3307, 3548, 0, +3431, 3680, 0, +3558, 3812, 0, +3686, 3944, 0, +3815, 4076, 0, +3945, 4095, 0, +2094, 0, 1855, +2093, 0, 1851, +2093, 0, 1847, +2092, 0, 1841, +2091, 0, 1832, +2091, 0, 1819, +2091, 0, 1799, +2091, 0, 1772, +2091, 0, 1733, +2091, 0, 1676, +2091, 0, 1585, +2091, 0, 1425, +2091, 0, 1050, +2091, 0, 0, +2091, 0, 0, +2091, 1463, 0, +2224, 1956, 0, +2357, 2245, 0, +2489, 2466, 0, +2586, 2622, 0, +2670, 2755, 0, +2762, 2887, 0, +2862, 3019, 0, +2968, 3151, 0, +3080, 3283, 0, +3196, 3416, 0, +3316, 3548, 0, +3439, 3680, 0, +3564, 3812, 0, +3691, 3944, 0, +3818, 4076, 0, +3948, 4095, 0, +2226, 0, 1979, +2226, 0, 1977, +2225, 0, 1973, +2225, 0, 1969, +2224, 0, 1963, +2224, 0, 1952, +2224, 0, 1938, +2224, 0, 1918, +2224, 0, 1891, +2224, 0, 1850, +2224, 0, 1790, +2224, 0, 1695, +2224, 0, 1527, +2224, 0, 1108, +2224, 0, 0, +2224, 0, 0, +2224, 1584, 0, +2357, 2085, 0, +2489, 2375, 0, +2622, 2597, 0, +2720, 2755, 0, +2803, 2887, 0, +2895, 3019, 0, +2995, 3151, 0, +3101, 3283, 0, +3212, 3416, 0, +3329, 3548, 0, +3448, 3680, 0, +3571, 3812, 0, +3696, 3944, 0, +3823, 4076, 0, +3951, 4095, 0, +2358, 0, 2106, +2358, 0, 2104, +2358, 0, 2101, +2357, 0, 2098, +2357, 0, 2093, +2357, 0, 2086, +2357, 0, 2075, +2357, 0, 2060, +2357, 0, 2040, +2357, 0, 2012, +2357, 0, 1970, +2357, 0, 1909, +2357, 0, 1811, +2357, 0, 1634, +2357, 0, 1176, +2357, 0, 0, +2357, 0, 0, +2357, 1708, 0, +2489, 2215, 0, +2622, 2506, 0, +2755, 2729, 0, +2853, 2887, 0, +2936, 3019, 0, +3028, 3151, 0, +3127, 3283, 0, +3233, 3416, 0, +3345, 3548, 0, +3461, 3680, 0, +3581, 3812, 0, +3703, 3944, 0, +3828, 4076, 0, +3955, 4095, 0, +2491, 0, 2234, +2491, 0, 2233, +2490, 0, 2230, +2490, 0, 2228, +2489, 0, 2224, +2489, 0, 2219, +2489, 0, 2211, +2489, 0, 2200, +2489, 0, 2185, +2489, 0, 2165, +2489, 0, 2136, +2489, 0, 2094, +2489, 0, 2031, +2489, 0, 1930, +2489, 0, 1748, +2489, 0, 1255, +2489, 0, 0, +2489, 0, 0, +2489, 1834, 0, +2622, 2344, 0, +2755, 2637, 0, +2887, 2860, 0, +2986, 3019, 0, +3069, 3151, 0, +3160, 3283, 0, +3260, 3416, 0, +3366, 3548, 0, +3478, 3680, 0, +3594, 3812, 0, +3713, 3944, 0, +3836, 4076, 0, +3961, 4095, 0, +2623, 0, 2363, +2623, 0, 2362, +2623, 0, 2360, +2622, 0, 2358, +2622, 0, 2356, +2622, 0, 2351, +2622, 0, 2346, +2622, 0, 2337, +2622, 0, 2327, +2622, 0, 2312, +2622, 0, 2291, +2622, 0, 2261, +2622, 0, 2219, +2622, 0, 2155, +2622, 0, 2052, +2622, 0, 1865, +2622, 0, 1342, +2622, 0, 0, +2622, 0, 0, +2622, 1962, 0, +2755, 2476, 0, +2887, 2768, 0, +3019, 2992, 0, +3119, 3151, 0, +3201, 3283, 0, +3293, 3416, 0, +3392, 3548, 0, +3498, 3680, 0, +3610, 3812, 0, +3726, 3944, 0, +3845, 4076, 0, +3968, 4095, 0, +2755, 0, 2493, +2755, 0, 2492, +2755, 0, 2491, +2755, 0, 2489, +2755, 0, 2487, +2755, 0, 2484, +2755, 0, 2480, +2755, 0, 2474, +2755, 0, 2466, +2755, 0, 2455, +2755, 0, 2440, +2755, 0, 2419, +2755, 0, 2389, +2755, 0, 2346, +2755, 0, 2281, +2755, 0, 2177, +2755, 0, 1986, +2755, 0, 1439, +2755, 0, 0, +2755, 0, 0, +2755, 2091, 0, +2887, 2606, 0, +3019, 2899, 0, +3151, 3123, 0, +3251, 3283, 0, +3334, 3416, 0, +3426, 3548, 0, +3525, 3680, 0, +3631, 3812, 0, +3742, 3944, 0, +3858, 4076, 0, +3977, 4095, 0, +2887, 0, 2623, +2887, 0, 2622, +2887, 0, 2621, +2887, 0, 2620, +2887, 0, 2619, +2887, 0, 2617, +2887, 0, 2613, +2887, 0, 2609, +2887, 0, 2603, +2887, 0, 2595, +2887, 0, 2584, +2887, 0, 2569, +2887, 0, 2548, +2887, 0, 2517, +2887, 0, 2474, +2887, 0, 2409, +2887, 0, 2304, +2887, 0, 2110, +2887, 0, 1540, +2887, 0, 0, +2887, 0, 0, +2887, 2220, 0, +3019, 2737, 0, +3151, 3031, 0, +3283, 3255, 0, +3384, 3416, 0, +3467, 3548, 0, +3558, 3680, 0, +3657, 3812, 0, +3763, 3944, 0, +3874, 4076, 0, +3990, 4095, 0, +3019, 0, 2754, +3019, 0, 2753, +3019, 0, 2752, +3019, 0, 2751, +3019, 0, 2750, +3019, 0, 2749, +3019, 0, 2746, +3019, 0, 2743, +3019, 0, 2738, +3019, 0, 2732, +3019, 0, 2724, +3019, 0, 2713, +3019, 0, 2698, +3019, 0, 2677, +3019, 0, 2647, +3019, 0, 2603, +3019, 0, 2537, +3019, 0, 2431, +3019, 0, 2234, +3019, 0, 1646, +3019, 0, 0, +3019, 0, 0, +3019, 2350, 0, +3151, 2869, 0, +3283, 3163, 0, +3416, 3387, 0, +3516, 3548, 0, +3599, 3680, 0, +3690, 3812, 0, +3789, 3944, 0, +3895, 4076, 0, +4006, 4095, 0, +3152, 0, 2885, +3152, 0, 2885, +3152, 0, 2884, +3151, 0, 2883, +3151, 0, 2883, +3151, 0, 2881, +3151, 0, 2879, +3151, 0, 2877, +3151, 0, 2873, +3151, 0, 2869, +3151, 0, 2863, +3151, 0, 2855, +3151, 0, 2844, +3151, 0, 2829, +3151, 0, 2807, +3151, 0, 2777, +3151, 0, 2733, +3151, 0, 2667, +3151, 0, 2560, +3151, 0, 2362, +3151, 0, 1760, +3151, 0, 0, +3151, 0, 0, +3151, 2481, 0, +3283, 3000, 0, +3416, 3295, 0, +3548, 3519, 0, +3648, 3680, 0, +3731, 3812, 0, +3822, 3944, 0, +3921, 4076, 0, +4027, 4095, 0, +3284, 0, 3016, +3283, 0, 3016, +3283, 0, 3015, +3283, 0, 3015, +3283, 0, 3014, +3283, 0, 3013, +3283, 0, 3012, +3283, 0, 3010, +3283, 0, 3008, +3283, 0, 3004, +3283, 0, 3000, +3283, 0, 2994, +3283, 0, 2986, +3283, 0, 2974, +3283, 0, 2959, +3283, 0, 2938, +3283, 0, 2907, +3283, 0, 2863, +3283, 0, 2797, +3283, 0, 2690, +3283, 0, 2489, +3283, 0, 1875, +3283, 0, 0, +3283, 0, 0, +3283, 2612, 0, +3416, 3132, 0, +3548, 3427, 0, +3680, 3651, 0, +3781, 3812, 0, +3863, 3944, 0, +3955, 4076, 0, +4054, 4095, 0, +3416, 0, 3147, +3416, 0, 3147, +3416, 0, 3147, +3416, 0, 3147, +3416, 0, 3146, +3416, 0, 3145, +3416, 0, 3144, +3416, 0, 3143, +3416, 0, 3141, +3416, 0, 3139, +3416, 0, 3135, +3416, 0, 3131, +3416, 0, 3125, +3416, 0, 3117, +3416, 0, 3106, +3416, 0, 3090, +3416, 0, 3069, +3416, 0, 3038, +3416, 0, 2994, +3416, 0, 2928, +3416, 0, 2820, +3416, 0, 2619, +3416, 0, 2000, +3416, 0, 0, +3416, 0, 0, +3416, 2743, 0, +3548, 3264, 0, +3680, 3559, 0, +3812, 3783, 0, +3913, 3944, 0, +3995, 4076, 0, +4087, 4095, 0, +3548, 0, 3279, +3548, 0, 3279, +3548, 0, 3279, +3548, 0, 3279, +3548, 0, 3278, +3548, 0, 3278, +3548, 0, 3277, +3548, 0, 3276, +3548, 0, 3275, +3548, 0, 3273, +3548, 0, 3270, +3548, 0, 3267, +3548, 0, 3262, +3548, 0, 3256, +3548, 0, 3248, +3548, 0, 3237, +3548, 0, 3222, +3548, 0, 3200, +3548, 0, 3170, +3548, 0, 3125, +3548, 0, 3059, +3548, 0, 2951, +3548, 0, 2749, +3548, 0, 2122, +3548, 0, 0, +3548, 0, 0, +3548, 2874, 0, +3680, 3396, 0, +3812, 3691, 0, +3944, 3915, 0, +4045, 4076, 0, +4095, 4095, 0, +3680, 0, 3411, +3680, 0, 3411, +3680, 0, 3411, +3680, 0, 3411, +3680, 0, 3410, +3680, 0, 3410, +3680, 0, 3409, +3680, 0, 3409, +3680, 0, 3408, +3680, 0, 3406, +3680, 0, 3404, +3680, 0, 3402, +3680, 0, 3399, +3680, 0, 3394, +3680, 0, 3388, +3680, 0, 3380, +3680, 0, 3369, +3680, 0, 3353, +3680, 0, 3332, +3680, 0, 3301, +3680, 0, 3257, +3680, 0, 3190, +3680, 0, 3082, +3680, 0, 2879, +3680, 0, 2251, +3680, 0, 0, +3680, 0, 0, +3680, 3006, 0, +3812, 3528, 0, +3944, 3823, 0, +4076, 4047, 0, +4095, 4095, 0, +3812, 0, 3543, +3812, 0, 3543, +3812, 0, 3543, +3812, 0, 3543, +3812, 0, 3543, +3812, 0, 3542, +3812, 0, 3542, +3812, 0, 3541, +3812, 0, 3540, +3812, 0, 3539, +3812, 0, 3538, +3812, 0, 3536, +3812, 0, 3534, +3812, 0, 3530, +3812, 0, 3526, +3812, 0, 3520, +3812, 0, 3511, +3812, 0, 3500, +3812, 0, 3485, +3812, 0, 3463, +3812, 0, 3433, +3812, 0, 3388, +3812, 0, 3322, +3812, 0, 3213, +3812, 0, 3011, +3812, 0, 2377, +3812, 0, 0, +3812, 0, 0, +3812, 3138, 0, +3944, 3660, 0, +4076, 3955, 0, +4095, 4095, 0, +3944, 0, 3675, +3944, 0, 3675, +3944, 0, 3675, +3944, 0, 3674, +3944, 0, 3674, +3944, 0, 3674, +3944, 0, 3674, +3944, 0, 3673, +3944, 0, 3673, +3944, 0, 3672, +3944, 0, 3671, +3944, 0, 3670, +3944, 0, 3668, +3944, 0, 3665, +3944, 0, 3662, +3944, 0, 3658, +3944, 0, 3652, +3944, 0, 3643, +3944, 0, 3632, +3944, 0, 3617, +3944, 0, 3595, +3944, 0, 3564, +3944, 0, 3520, +3944, 0, 3453, +3944, 0, 3345, +3944, 0, 3142, +3944, 0, 2505, +3944, 0, 0, +3944, 0, 0, +3944, 3270, 0, +4076, 3792, 0, +4095, 4087, 0, +4076, 0, 3807, +4076, 0, 3807, +4076, 0, 3807, +4076, 0, 3806, +4076, 0, 3806, +4076, 0, 3806, +4076, 0, 3806, +4076, 0, 3805, +4076, 0, 3805, +4076, 0, 3805, +4076, 0, 3804, +4076, 0, 3803, +4076, 0, 3801, +4076, 0, 3800, +4076, 0, 3797, +4076, 0, 3794, +4076, 0, 3790, +4076, 0, 3783, +4076, 0, 3775, +4076, 0, 3764, +4076, 0, 3748, +4076, 0, 3727, +4076, 0, 3696, +4076, 0, 3652, +4076, 0, 3585, +4076, 0, 3476, +4076, 0, 3273, +4076, 0, 2632, +4076, 0, 0, +4076, 0, 0, +4076, 3401, 0, +4095, 3924, 0, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3938, +4095, 0, 3938, +4095, 0, 3938, +4095, 0, 3938, +4095, 0, 3937, +4095, 0, 3937, +4095, 0, 3936, +4095, 0, 3935, +4095, 0, 3934, +4095, 0, 3932, +4095, 0, 3929, +4095, 0, 3926, +4095, 0, 3921, +4095, 0, 3915, +4095, 0, 3907, +4095, 0, 3896, +4095, 0, 3880, +4095, 0, 3859, +4095, 0, 3828, +4095, 0, 3784, +4095, 0, 3717, +4095, 0, 3608, +4095, 0, 3405, +4095, 0, 2765, +4095, 0, 0, +4095, 0, 0, +4095, 3534, 0, +0, 545, 750, +0, 613, 750, +0, 689, 750, +0, 750, 723, +0, 750, 587, +0, 750, 304, +0, 888, 0, +0, 1025, 0, +397, 1160, 0, +717, 1295, 0, +951, 1429, 0, +1148, 1563, 0, +1322, 1696, 0, +1484, 1828, 0, +1636, 1961, 0, +1783, 2094, 0, +1926, 2226, 0, +2066, 2358, 0, +2204, 2491, 0, +2341, 2623, 0, +2476, 2755, 0, +2611, 2887, 0, +2744, 3019, 0, +2878, 3152, 0, +3011, 3284, 0, +3144, 3416, 0, +3276, 3548, 0, +3409, 3680, 0, +3541, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3938, 4095, 0, +0, 467, 750, +0, 559, 741, +0, 644, 741, +0, 738, 741, +0, 741, 616, +0, 741, 356, +0, 882, 0, +81, 1020, 0, +503, 1157, 0, +772, 1292, 0, +985, 1427, 0, +1170, 1561, 0, +1337, 1695, 0, +1494, 1828, 0, +1644, 1961, 0, +1789, 2093, 0, +1930, 2226, 0, +2069, 2358, 0, +2206, 2491, 0, +2342, 2623, 0, +2477, 2755, 0, +2612, 2887, 0, +2745, 3019, 0, +2878, 3152, 0, +3011, 3283, 0, +3144, 3416, 0, +3277, 3548, 0, +3409, 3680, 0, +3541, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3938, 4095, 0, +0, 334, 750, +0, 453, 741, +34, 576, 730, +34, 683, 730, +34, 730, 652, +34, 730, 418, +0, 873, 0, +323, 1014, 0, +614, 1152, 0, +837, 1289, 0, +1027, 1424, 0, +1198, 1559, 0, +1357, 1693, 0, +1508, 1827, 0, +1654, 1960, 0, +1796, 2093, 0, +1936, 2225, 0, +2073, 2358, 0, +2209, 2490, 0, +2345, 2623, 0, +2479, 2755, 0, +2613, 2887, 0, +2746, 3019, 0, +2879, 3152, 0, +3011, 3283, 0, +3144, 3416, 0, +3277, 3548, 0, +3409, 3680, 0, +3541, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3938, 4095, 0, +0, 59, 750, +0, 258, 741, +34, 435, 730, +280, 598, 714, +280, 714, 696, +280, 714, 490, +264, 862, 166, +523, 1005, 0, +730, 1146, 0, +911, 1284, 0, +1077, 1421, 0, +1233, 1557, 0, +1382, 1691, 0, +1526, 1825, 0, +1667, 1959, 0, +1806, 2092, 0, +1943, 2225, 0, +2078, 2357, 0, +2213, 2490, 0, +2347, 2622, 0, +2481, 2755, 0, +2614, 2887, 0, +2747, 3019, 0, +2880, 3151, 0, +3012, 3283, 0, +3145, 3416, 0, +3277, 3548, 0, +3410, 3680, 0, +3542, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3938, 4095, 0, +0, 0, 750, +0, 0, 741, +34, 132, 730, +280, 409, 714, +482, 625, 691, +482, 691, 570, +541, 846, 412, +699, 994, 298, +850, 1137, 80, +995, 1278, 0, +1137, 1416, 0, +1276, 1553, 0, +1413, 1689, 0, +1549, 1823, 0, +1684, 1958, 0, +1819, 2091, 0, +1952, 2224, 0, +2086, 2357, 0, +2219, 2489, 0, +2351, 2622, 0, +2484, 2755, 0, +2617, 2887, 0, +2749, 3019, 0, +2881, 3151, 0, +3013, 3283, 0, +3145, 3416, 0, +3278, 3548, 0, +3410, 3680, 0, +3542, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3938, 4095, 0, +304, 0, 750, +356, 0, 741, +418, 34, 730, +490, 280, 714, +570, 482, 691, +660, 660, 660, +758, 824, 614, +862, 978, 544, +972, 1126, 430, +1087, 1270, 212, +1206, 1410, 0, +1328, 1549, 0, +1452, 1685, 0, +1579, 1821, 0, +1706, 1956, 0, +1835, 2089, 0, +1965, 2223, 0, +2095, 2356, 0, +2226, 2489, 0, +2356, 2621, 0, +2488, 2754, 0, +2619, 2887, 0, +2751, 3019, 0, +2883, 3151, 0, +3014, 3283, 0, +3146, 3416, 0, +3278, 3548, 0, +3410, 3680, 0, +3543, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3939, 4095, 0, +697, 0, 888, +719, 0, 882, +749, 0, 873, +784, 166, 862, +828, 412, 846, +824, 614, 758, +824, 702, 614, +978, 960, 544, +1079, 1126, 430, +1172, 1270, 212, +1273, 1410, 0, +1380, 1549, 0, +1492, 1685, 0, +1609, 1821, 0, +1730, 1956, 0, +1853, 2089, 0, +1978, 2223, 0, +2105, 2356, 0, +2233, 2489, 0, +2362, 2621, 0, +2492, 2754, 0, +2623, 2887, 0, +2753, 3019, 0, +2885, 3151, 0, +3016, 3283, 0, +3147, 3416, 0, +3279, 3548, 0, +3411, 3680, 0, +3543, 3812, 0, +3675, 3944, 0, +3807, 4076, 0, +3939, 4095, 0, +957, 0, 1025, +970, 0, 1020, +987, 0, 1014, +1005, 0, 1002, +994, 298, 947, +978, 544, 862, +978, 544, 673, +978, 754, 544, +1126, 1049, 430, +1266, 1270, 212, +1350, 1410, 0, +1442, 1549, 0, +1541, 1685, 0, +1648, 1821, 0, +1759, 1956, 0, +1875, 2089, 0, +1995, 2223, 0, +2118, 2356, 0, +2243, 2489, 0, +2370, 2621, 0, +2498, 2754, 0, +2627, 2887, 0, +2756, 3019, 0, +2887, 3151, 0, +3018, 3283, 0, +3149, 3416, 0, +3280, 3548, 0, +3412, 3680, 0, +3543, 3812, 0, +3675, 3944, 0, +3807, 4076, 0, +3939, 4095, 0, +1160, 0, 1154, +1157, 0, 1139, +1152, 0, 1117, +1146, 0, 1086, +1137, 80, 1040, +1126, 430, 972, +1126, 430, 831, +1126, 430, 529, +1126, 814, 430, +1270, 1145, 212, +1410, 1383, 0, +1513, 1549, 0, +1599, 1685, 0, +1694, 1821, 0, +1796, 1956, 0, +1904, 2089, 0, +2018, 2223, 0, +2135, 2356, 0, +2256, 2489, 0, +2380, 2621, 0, +2505, 2754, 0, +2632, 2887, 0, +2761, 3019, 0, +2890, 3151, 0, +3020, 3283, 0, +3151, 3416, 0, +3281, 3548, 0, +3413, 3680, 0, +3544, 3812, 0, +3676, 3944, 0, +3808, 4076, 0, +3939, 4095, 0, +1295, 0, 1234, +1292, 0, 1221, +1289, 0, 1203, +1284, 0, 1177, +1278, 0, 1141, +1270, 212, 1087, +1270, 212, 982, +1270, 212, 787, +1270, 212, 214, +1270, 884, 212, +1410, 1248, 0, +1549, 1499, 0, +1667, 1685, 0, +1750, 1821, 0, +1841, 1956, 0, +1940, 2089, 0, +2046, 2223, 0, +2157, 2356, 0, +2273, 2489, 0, +2393, 2621, 0, +2515, 2754, 0, +2640, 2887, 0, +2766, 3019, 0, +2895, 3151, 0, +3023, 3283, 0, +3153, 3416, 0, +3283, 3548, 0, +3414, 3680, 0, +3545, 3812, 0, +3676, 3944, 0, +3808, 4076, 0, +3940, 4095, 0, +1429, 0, 1323, +1427, 0, 1313, +1424, 0, 1298, +1421, 0, 1277, +1416, 0, 1248, +1410, 0, 1206, +1410, 0, 1127, +1410, 0, 994, +1410, 0, 719, +1410, 47, 0, +1410, 964, 0, +1549, 1358, 0, +1685, 1618, 0, +1815, 1821, 0, +1895, 1956, 0, +1984, 2089, 0, +2081, 2223, 0, +2185, 2356, 0, +2294, 2489, 0, +2409, 2621, 0, +2528, 2754, 0, +2650, 2887, 0, +2774, 3019, 0, +2900, 3151, 0, +3027, 3283, 0, +3156, 3416, 0, +3286, 3548, 0, +3416, 3680, 0, +3547, 3812, 0, +3677, 3944, 0, +3809, 4076, 0, +3941, 4095, 0, +1563, 0, 1421, +1561, 0, 1412, +1559, 0, 1400, +1557, 0, 1384, +1553, 0, 1360, +1549, 0, 1328, +1549, 0, 1269, +1549, 0, 1176, +1549, 0, 1011, +1549, 0, 611, +1549, 0, 0, +1549, 1053, 0, +1685, 1471, 0, +1821, 1740, 0, +1956, 1953, 0, +2037, 2089, 0, +2124, 2223, 0, +2219, 2356, 0, +2322, 2489, 0, +2431, 2621, 0, +2545, 2754, 0, +2662, 2887, 0, +2784, 3019, 0, +2907, 3151, 0, +3033, 3283, 0, +3160, 3416, 0, +3289, 3548, 0, +3418, 3680, 0, +3548, 3812, 0, +3679, 3944, 0, +3810, 4076, 0, +3941, 4095, 0, +1696, 0, 1524, +1695, 0, 1517, +1693, 0, 1508, +1691, 0, 1495, +1689, 0, 1477, +1685, 0, 1452, +1685, 0, 1408, +1685, 0, 1341, +1685, 0, 1233, +1685, 0, 1031, +1685, 0, 406, +1685, 0, 0, +1685, 1149, 0, +1821, 1590, 0, +1956, 1865, 0, +2089, 2080, 0, +2176, 2223, 0, +2262, 2356, 0, +2356, 2489, 0, +2458, 2621, 0, +2566, 2754, 0, +2679, 2887, 0, +2796, 3019, 0, +2917, 3151, 0, +3040, 3283, 0, +3166, 3416, 0, +3293, 3548, 0, +3421, 3680, 0, +3551, 3812, 0, +3681, 3944, 0, +3811, 4076, 0, +3942, 4095, 0, +1828, 0, 1634, +1828, 0, 1629, +1827, 0, 1621, +1825, 0, 1611, +1823, 0, 1598, +1821, 0, 1579, +1821, 0, 1545, +1821, 0, 1497, +1821, 0, 1423, +1821, 0, 1301, +1821, 0, 1059, +1821, 0, 0, +1821, 0, 0, +1821, 1253, 0, +1956, 1711, 0, +2089, 1991, 0, +2223, 2208, 0, +2313, 2356, 0, +2398, 2489, 0, +2492, 2621, 0, +2593, 2754, 0, +2700, 2887, 0, +2813, 3019, 0, +2930, 3151, 0, +3050, 3283, 0, +3173, 3416, 0, +3299, 3548, 0, +3426, 3680, 0, +3554, 3812, 0, +3683, 3944, 0, +3813, 4076, 0, +3944, 4095, 0, +1961, 0, 1749, +1961, 0, 1745, +1960, 0, 1739, +1959, 0, 1731, +1958, 0, 1721, +1956, 0, 1706, +1956, 0, 1681, +1956, 0, 1646, +1956, 0, 1594, +1956, 0, 1514, +1956, 0, 1378, +1956, 0, 1091, +1956, 0, 0, +1956, 0, 0, +1956, 1362, 0, +2089, 1835, 0, +2223, 2118, 0, +2356, 2338, 0, +2449, 2489, 0, +2533, 2621, 0, +2627, 2754, 0, +2727, 2887, 0, +2834, 3019, 0, +2946, 3151, 0, +3062, 3283, 0, +3183, 3416, 0, +3306, 3548, 0, +3431, 3680, 0, +3558, 3812, 0, +3686, 3944, 0, +3815, 4076, 0, +3945, 4095, 0, +2094, 0, 1867, +2093, 0, 1864, +2093, 0, 1860, +2092, 0, 1854, +2091, 0, 1846, +2089, 0, 1835, +2089, 0, 1816, +2089, 0, 1790, +2089, 0, 1753, +2089, 0, 1698, +2089, 0, 1612, +2089, 0, 1463, +2089, 0, 1133, +2089, 0, 0, +2089, 0, 0, +2089, 1476, 0, +2223, 1961, 0, +2356, 2247, 0, +2489, 2468, 0, +2584, 2621, 0, +2668, 2754, 0, +2761, 2887, 0, +2860, 3019, 0, +2967, 3151, 0, +3079, 3283, 0, +3196, 3416, 0, +3316, 3548, 0, +3438, 3680, 0, +3564, 3812, 0, +3690, 3944, 0, +3818, 4076, 0, +3948, 4095, 0, +2226, 0, 1989, +2226, 0, 1987, +2225, 0, 1983, +2225, 0, 1979, +2224, 0, 1973, +2223, 0, 1965, +2223, 0, 1951, +2223, 0, 1931, +2223, 0, 1904, +2223, 0, 1865, +2223, 0, 1808, +2223, 0, 1717, +2223, 0, 1557, +2223, 0, 1181, +2223, 0, 0, +2223, 0, 0, +2223, 1595, 0, +2356, 2088, 0, +2489, 2377, 0, +2621, 2598, 0, +2718, 2754, 0, +2802, 2887, 0, +2894, 3019, 0, +2994, 3151, 0, +3100, 3283, 0, +3212, 3416, 0, +3328, 3548, 0, +3448, 3680, 0, +3571, 3812, 0, +3696, 3944, 0, +3822, 4076, 0, +3951, 4095, 0, +2358, 0, 2113, +2358, 0, 2111, +2358, 0, 2109, +2357, 0, 2105, +2357, 0, 2101, +2356, 0, 2095, +2356, 0, 2084, +2356, 0, 2070, +2356, 0, 2050, +2356, 0, 2022, +2356, 0, 1982, +2356, 0, 1922, +2356, 0, 1828, +2356, 0, 1659, +2356, 0, 1240, +2356, 0, 0, +2356, 0, 0, +2356, 1716, 0, +2489, 2218, 0, +2621, 2507, 0, +2754, 2730, 0, +2852, 2887, 0, +2935, 3019, 0, +3027, 3151, 0, +3127, 3283, 0, +3233, 3416, 0, +3344, 3548, 0, +3461, 3680, 0, +3581, 3812, 0, +3703, 3944, 0, +3828, 4076, 0, +3955, 4095, 0, +2491, 0, 2239, +2491, 0, 2238, +2490, 0, 2236, +2490, 0, 2234, +2489, 0, 2230, +2489, 0, 2226, +2489, 0, 2218, +2489, 0, 2207, +2489, 0, 2193, +2489, 0, 2172, +2489, 0, 2144, +2489, 0, 2103, +2489, 0, 2041, +2489, 0, 1943, +2489, 0, 1767, +2489, 0, 1310, +2489, 0, 0, +2489, 0, 0, +2489, 1840, 0, +2621, 2346, 0, +2754, 2638, 0, +2887, 2861, 0, +2985, 3019, 0, +3068, 3151, 0, +3160, 3283, 0, +3259, 3416, 0, +3365, 3548, 0, +3477, 3680, 0, +3593, 3812, 0, +3713, 3944, 0, +3835, 4076, 0, +3961, 4095, 0, +2623, 0, 2367, +2623, 0, 2366, +2623, 0, 2364, +2622, 0, 2362, +2622, 0, 2360, +2621, 0, 2356, +2621, 0, 2351, +2621, 0, 2343, +2621, 0, 2332, +2621, 0, 2317, +2621, 0, 2297, +2621, 0, 2268, +2621, 0, 2226, +2621, 0, 2163, +2621, 0, 2062, +2621, 0, 1880, +2621, 0, 1387, +2621, 0, 0, +2621, 0, 0, +2621, 1966, 0, +2754, 2477, 0, +2887, 2769, 0, +3019, 2992, 0, +3118, 3151, 0, +3201, 3283, 0, +3293, 3416, 0, +3392, 3548, 0, +3498, 3680, 0, +3609, 3812, 0, +3725, 3944, 0, +3845, 4076, 0, +3968, 4095, 0, +2755, 0, 2496, +2755, 0, 2495, +2755, 0, 2494, +2755, 0, 2492, +2755, 0, 2490, +2754, 0, 2488, +2754, 0, 2484, +2754, 0, 2478, +2754, 0, 2470, +2754, 0, 2459, +2754, 0, 2444, +2754, 0, 2423, +2754, 0, 2394, +2754, 0, 2351, +2754, 0, 2287, +2754, 0, 2185, +2754, 0, 1997, +2754, 0, 1476, +2754, 0, 0, +2754, 0, 0, +2754, 2094, 0, +2887, 2607, 0, +3019, 2900, 0, +3151, 3124, 0, +3251, 3283, 0, +3334, 3416, 0, +3425, 3548, 0, +3525, 3680, 0, +3630, 3812, 0, +3742, 3944, 0, +3858, 4076, 0, +3977, 4095, 0, +2887, 0, 2625, +2887, 0, 2625, +2887, 0, 2624, +2887, 0, 2623, +2887, 0, 2621, +2887, 0, 2619, +2887, 0, 2616, +2887, 0, 2612, +2887, 0, 2606, +2887, 0, 2598, +2887, 0, 2587, +2887, 0, 2572, +2887, 0, 2551, +2887, 0, 2521, +2887, 0, 2478, +2887, 0, 2413, +2887, 0, 2310, +2887, 0, 2118, +2887, 0, 1569, +2887, 0, 0, +2887, 0, 0, +2887, 2223, 0, +3019, 2738, 0, +3151, 3032, 0, +3283, 3255, 0, +3384, 3416, 0, +3466, 3548, 0, +3558, 3680, 0, +3657, 3812, 0, +3763, 3944, 0, +3874, 4076, 0, +3990, 4095, 0, +3019, 0, 2755, +3019, 0, 2755, +3019, 0, 2754, +3019, 0, 2753, +3019, 0, 2752, +3019, 0, 2751, +3019, 0, 2748, +3019, 0, 2745, +3019, 0, 2741, +3019, 0, 2735, +3019, 0, 2727, +3019, 0, 2716, +3019, 0, 2701, +3019, 0, 2679, +3019, 0, 2649, +3019, 0, 2606, +3019, 0, 2541, +3019, 0, 2435, +3019, 0, 2241, +3019, 0, 1670, +3019, 0, 0, +3019, 0, 0, +3019, 2352, 0, +3151, 2870, 0, +3283, 3163, 0, +3416, 3387, 0, +3516, 3548, 0, +3599, 3680, 0, +3690, 3812, 0, +3789, 3944, 0, +3895, 4076, 0, +4006, 4095, 0, +3152, 0, 2886, +3152, 0, 2886, +3152, 0, 2885, +3151, 0, 2885, +3151, 0, 2884, +3151, 0, 2883, +3151, 0, 2881, +3151, 0, 2879, +3151, 0, 2875, +3151, 0, 2871, +3151, 0, 2865, +3151, 0, 2857, +3151, 0, 2845, +3151, 0, 2830, +3151, 0, 2809, +3151, 0, 2779, +3151, 0, 2735, +3151, 0, 2670, +3151, 0, 2564, +3151, 0, 2367, +3151, 0, 1779, +3151, 0, 0, +3151, 0, 0, +3151, 2482, 0, +3283, 3000, 0, +3416, 3295, 0, +3548, 3519, 0, +3648, 3680, 0, +3731, 3812, 0, +3822, 3944, 0, +3921, 4076, 0, +4027, 4095, 0, +3284, 0, 3017, +3283, 0, 3017, +3283, 0, 3016, +3283, 0, 3016, +3283, 0, 3015, +3283, 0, 3014, +3283, 0, 3013, +3283, 0, 3011, +3283, 0, 3009, +3283, 0, 3005, +3283, 0, 3001, +3283, 0, 2995, +3283, 0, 2987, +3283, 0, 2976, +3283, 0, 2960, +3283, 0, 2939, +3283, 0, 2909, +3283, 0, 2865, +3283, 0, 2799, +3283, 0, 2692, +3283, 0, 2493, +3283, 0, 1890, +3283, 0, 0, +3283, 0, 0, +3283, 2613, 0, +3416, 3133, 0, +3548, 3427, 0, +3680, 3651, 0, +3781, 3812, 0, +3863, 3944, 0, +3954, 4076, 0, +4054, 4095, 0, +3416, 0, 3148, +3416, 0, 3148, +3416, 0, 3148, +3416, 0, 3147, +3416, 0, 3147, +3416, 0, 3146, +3416, 0, 3145, +3416, 0, 3144, +3416, 0, 3142, +3416, 0, 3140, +3416, 0, 3136, +3416, 0, 3132, +3416, 0, 3126, +3416, 0, 3118, +3416, 0, 3106, +3416, 0, 3091, +3416, 0, 3070, +3416, 0, 3039, +3416, 0, 2996, +3416, 0, 2929, +3416, 0, 2822, +3416, 0, 2621, +3416, 0, 2011, +3416, 0, 0, +3416, 0, 0, +3416, 2744, 0, +3548, 3265, 0, +3680, 3559, 0, +3812, 3783, 0, +3913, 3944, 0, +3995, 4076, 0, +4087, 4095, 0, +3548, 0, 3280, +3548, 0, 3280, +3548, 0, 3280, +3548, 0, 3279, +3548, 0, 3279, +3548, 0, 3278, +3548, 0, 3278, +3548, 0, 3277, +3548, 0, 3275, +3548, 0, 3273, +3548, 0, 3271, +3548, 0, 3268, +3548, 0, 3263, +3548, 0, 3257, +3548, 0, 3249, +3548, 0, 3238, +3548, 0, 3222, +3548, 0, 3201, +3548, 0, 3171, +3548, 0, 3126, +3548, 0, 3060, +3548, 0, 2952, +3548, 0, 2751, +3548, 0, 2130, +3548, 0, 0, +3548, 0, 0, +3548, 2875, 0, +3680, 3396, 0, +3812, 3691, 0, +3944, 3915, 0, +4045, 4076, 0, +4095, 4095, 0, +3680, 0, 3411, +3680, 0, 3411, +3680, 0, 3411, +3680, 0, 3411, +3680, 0, 3411, +3680, 0, 3410, +3680, 0, 3410, +3680, 0, 3409, +3680, 0, 3408, +3680, 0, 3407, +3680, 0, 3405, +3680, 0, 3402, +3680, 0, 3399, +3680, 0, 3395, +3680, 0, 3388, +3680, 0, 3380, +3680, 0, 3369, +3680, 0, 3354, +3680, 0, 3332, +3680, 0, 3302, +3680, 0, 3258, +3680, 0, 3191, +3680, 0, 3083, +3680, 0, 2881, +3680, 0, 2257, +3680, 0, 0, +3680, 0, 0, +3680, 3006, 0, +3812, 3528, 0, +3944, 3823, 0, +4076, 4047, 0, +4095, 4095, 0, +3812, 0, 3543, +3812, 0, 3543, +3812, 0, 3543, +3812, 0, 3543, +3812, 0, 3543, +3812, 0, 3543, +3812, 0, 3542, +3812, 0, 3541, +3812, 0, 3541, +3812, 0, 3540, +3812, 0, 3538, +3812, 0, 3537, +3812, 0, 3534, +3812, 0, 3531, +3812, 0, 3526, +3812, 0, 3520, +3812, 0, 3512, +3812, 0, 3501, +3812, 0, 3485, +3812, 0, 3464, +3812, 0, 3433, +3812, 0, 3389, +3812, 0, 3322, +3812, 0, 3214, +3812, 0, 3012, +3812, 0, 2382, +3812, 0, 0, +3812, 0, 0, +3812, 3138, 0, +3944, 3660, 0, +4076, 3955, 0, +4095, 4095, 0, +3944, 0, 3675, +3944, 0, 3675, +3944, 0, 3675, +3944, 0, 3675, +3944, 0, 3674, +3944, 0, 3674, +3944, 0, 3674, +3944, 0, 3674, +3944, 0, 3673, +3944, 0, 3672, +3944, 0, 3671, +3944, 0, 3670, +3944, 0, 3668, +3944, 0, 3666, +3944, 0, 3662, +3944, 0, 3658, +3944, 0, 3652, +3944, 0, 3644, +3944, 0, 3632, +3944, 0, 3617, +3944, 0, 3595, +3944, 0, 3565, +3944, 0, 3521, +3944, 0, 3454, +3944, 0, 3346, +3944, 0, 3143, +3944, 0, 2508, +3944, 0, 0, +3944, 0, 0, +3944, 3270, 0, +4076, 3792, 0, +4095, 4087, 0, +4076, 0, 3807, +4076, 0, 3807, +4076, 0, 3807, +4076, 0, 3807, +4076, 0, 3807, +4076, 0, 3806, +4076, 0, 3806, +4076, 0, 3806, +4076, 0, 3805, +4076, 0, 3805, +4076, 0, 3804, +4076, 0, 3803, +4076, 0, 3802, +4076, 0, 3800, +4076, 0, 3797, +4076, 0, 3794, +4076, 0, 3790, +4076, 0, 3784, +4076, 0, 3775, +4076, 0, 3764, +4076, 0, 3749, +4076, 0, 3727, +4076, 0, 3696, +4076, 0, 3652, +4076, 0, 3585, +4076, 0, 3477, +4076, 0, 3273, +4076, 0, 2635, +4076, 0, 0, +4076, 0, 0, +4076, 3402, 0, +4095, 3925, 0, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3938, +4095, 0, 3938, +4095, 0, 3938, +4095, 0, 3937, +4095, 0, 3937, +4095, 0, 3936, +4095, 0, 3935, +4095, 0, 3934, +4095, 0, 3932, +4095, 0, 3929, +4095, 0, 3926, +4095, 0, 3922, +4095, 0, 3916, +4095, 0, 3908, +4095, 0, 3896, +4095, 0, 3881, +4095, 0, 3859, +4095, 0, 3829, +4095, 0, 3784, +4095, 0, 3717, +4095, 0, 3609, +4095, 0, 3405, +4095, 0, 2767, +4095, 0, 0, +4095, 0, 0, +4095, 3534, 0, +0, 667, 888, +0, 719, 888, +0, 781, 888, +0, 852, 888, +0, 888, 838, +0, 888, 697, +0, 888, 392, +0, 1025, 0, +0, 1160, 0, +431, 1295, 0, +803, 1429, 0, +1057, 1563, 0, +1262, 1696, 0, +1442, 1828, 0, +1607, 1961, 0, +1763, 2094, 0, +1911, 2226, 0, +2055, 2358, 0, +2196, 2491, 0, +2335, 2623, 0, +2472, 2755, 0, +2607, 2887, 0, +2742, 3019, 0, +2876, 3152, 0, +3009, 3284, 0, +3143, 3416, 0, +3276, 3548, 0, +3408, 3680, 0, +3541, 3812, 0, +3673, 3944, 0, +3805, 4076, 0, +3938, 4095, 0, +0, 608, 888, +0, 678, 882, +0, 745, 882, +0, 822, 882, +0, 882, 855, +0, 882, 719, +0, 882, 436, +0, 1020, 0, +0, 1157, 0, +529, 1292, 0, +849, 1427, 0, +1084, 1561, 0, +1279, 1695, 0, +1454, 1828, 0, +1615, 1961, 0, +1768, 2093, 0, +1915, 2226, 0, +2058, 2358, 0, +2199, 2491, 0, +2336, 2623, 0, +2473, 2755, 0, +2608, 2887, 0, +2742, 3019, 0, +2877, 3152, 0, +3010, 3283, 0, +3143, 3416, 0, +3276, 3548, 0, +3408, 3680, 0, +3541, 3812, 0, +3673, 3944, 0, +3805, 4076, 0, +3938, 4095, 0, +0, 515, 888, +0, 599, 882, +0, 691, 873, +0, 776, 873, +0, 870, 873, +0, 873, 749, +0, 873, 488, +0, 1014, 0, +214, 1152, 0, +635, 1289, 0, +904, 1424, 0, +1118, 1559, 0, +1302, 1693, 0, +1469, 1827, 0, +1626, 1960, 0, +1776, 2093, 0, +1921, 2225, 0, +2062, 2358, 0, +2202, 2490, 0, +2338, 2623, 0, +2475, 2755, 0, +2609, 2887, 0, +2743, 3019, 0, +2877, 3152, 0, +3010, 3283, 0, +3143, 3416, 0, +3276, 3548, 0, +3409, 3680, 0, +3541, 3812, 0, +3673, 3944, 0, +3805, 4076, 0, +3938, 4095, 0, +0, 350, 888, +0, 466, 882, +0, 585, 873, +166, 708, 862, +166, 815, 862, +166, 862, 784, +166, 862, 550, +0, 1005, 0, +455, 1146, 0, +746, 1284, 0, +969, 1421, 0, +1159, 1557, 0, +1330, 1691, 0, +1489, 1825, 0, +1640, 1959, 0, +1786, 2092, 0, +1928, 2225, 0, +2068, 2357, 0, +2206, 2490, 0, +2341, 2622, 0, +2477, 2755, 0, +2611, 2887, 0, +2745, 3019, 0, +2878, 3151, 0, +3011, 3283, 0, +3144, 3416, 0, +3277, 3548, 0, +3409, 3680, 0, +3541, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3938, 4095, 0, +0, 0, 888, +0, 190, 882, +0, 390, 873, +166, 567, 862, +412, 730, 846, +412, 846, 828, +412, 846, 622, +397, 994, 298, +655, 1137, 80, +862, 1278, 0, +1043, 1416, 0, +1209, 1553, 0, +1365, 1689, 0, +1514, 1823, 0, +1658, 1958, 0, +1799, 2091, 0, +1938, 2224, 0, +2075, 2357, 0, +2211, 2489, 0, +2346, 2622, 0, +2480, 2755, 0, +2613, 2887, 0, +2746, 3019, 0, +2879, 3151, 0, +3012, 3283, 0, +3144, 3416, 0, +3277, 3548, 0, +3409, 3680, 0, +3542, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3938, 4095, 0, +0, 0, 888, +0, 0, 882, +0, 0, 873, +166, 264, 862, +412, 541, 846, +614, 758, 824, +614, 824, 702, +673, 978, 544, +831, 1126, 430, +982, 1270, 212, +1127, 1410, 0, +1269, 1549, 0, +1408, 1685, 0, +1545, 1821, 0, +1681, 1956, 0, +1816, 2089, 0, +1951, 2223, 0, +2084, 2356, 0, +2218, 2489, 0, +2351, 2621, 0, +2484, 2754, 0, +2616, 2887, 0, +2748, 3019, 0, +2881, 3151, 0, +3013, 3283, 0, +3145, 3416, 0, +3278, 3548, 0, +3410, 3680, 0, +3542, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3938, 4095, 0, +392, 0, 888, +436, 0, 882, +488, 0, 873, +550, 166, 862, +622, 412, 846, +702, 614, 824, +792, 792, 792, +890, 956, 746, +994, 1110, 676, +1104, 1258, 562, +1219, 1402, 344, +1338, 1543, 0, +1460, 1681, 0, +1585, 1817, 0, +1711, 1953, 0, +1838, 2087, 0, +1967, 2221, 0, +2096, 2355, 0, +2227, 2488, 0, +2357, 2621, 0, +2489, 2754, 0, +2620, 2886, 0, +2751, 3018, 0, +2883, 3151, 0, +3015, 3283, 0, +3147, 3415, 0, +3279, 3548, 0, +3411, 3680, 0, +3543, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3939, 4095, 0, +811, 0, 1025, +829, 0, 1020, +852, 0, 1014, +881, 0, 1005, +917, 298, 994, +960, 544, 978, +956, 746, 890, +956, 834, 746, +1110, 1092, 676, +1211, 1258, 562, +1304, 1402, 344, +1405, 1543, 0, +1512, 1681, 0, +1625, 1817, 0, +1742, 1953, 0, +1862, 2087, 0, +1985, 2221, 0, +2110, 2355, 0, +2237, 2488, 0, +2365, 2621, 0, +2494, 2754, 0, +2624, 2886, 0, +2754, 3018, 0, +2885, 3151, 0, +3016, 3283, 0, +3148, 3415, 0, +3280, 3548, 0, +3411, 3680, 0, +3543, 3812, 0, +3675, 3944, 0, +3807, 4076, 0, +3939, 4095, 0, +1079, 0, 1160, +1089, 0, 1157, +1102, 0, 1152, +1119, 0, 1146, +1137, 80, 1134, +1126, 430, 1079, +1110, 676, 994, +1110, 676, 805, +1110, 886, 676, +1258, 1181, 562, +1398, 1402, 344, +1482, 1543, 0, +1574, 1681, 0, +1673, 1817, 0, +1779, 1953, 0, +1891, 2087, 0, +2008, 2221, 0, +2127, 2355, 0, +2250, 2488, 0, +2375, 2621, 0, +2502, 2754, 0, +2630, 2886, 0, +2759, 3018, 0, +2889, 3151, 0, +3019, 3283, 0, +3150, 3415, 0, +3281, 3548, 0, +3412, 3680, 0, +3544, 3812, 0, +3676, 3944, 0, +3807, 4076, 0, +3939, 4095, 0, +1292, 0, 1295, +1292, 0, 1286, +1289, 0, 1271, +1284, 0, 1249, +1278, 0, 1218, +1270, 212, 1172, +1258, 562, 1104, +1258, 562, 963, +1258, 562, 661, +1258, 946, 562, +1402, 1277, 344, +1543, 1516, 0, +1645, 1681, 0, +1732, 1817, 0, +1826, 1953, 0, +1928, 2087, 0, +2036, 2221, 0, +2150, 2355, 0, +2267, 2488, 0, +2388, 2621, 0, +2512, 2754, 0, +2637, 2886, 0, +2764, 3018, 0, +2893, 3151, 0, +3022, 3283, 0, +3152, 3415, 0, +3283, 3548, 0, +3414, 3680, 0, +3545, 3812, 0, +3676, 3944, 0, +3808, 4076, 0, +3940, 4095, 0, +1429, 0, 1376, +1427, 0, 1366, +1424, 0, 1353, +1421, 0, 1335, +1416, 0, 1310, +1410, 0, 1273, +1402, 344, 1219, +1402, 344, 1114, +1402, 344, 919, +1402, 344, 345, +1402, 1017, 344, +1543, 1381, 0, +1681, 1631, 0, +1799, 1817, 0, +1882, 1953, 0, +1973, 2087, 0, +2072, 2221, 0, +2178, 2355, 0, +2289, 2488, 0, +2405, 2621, 0, +2525, 2754, 0, +2647, 2886, 0, +2772, 3018, 0, +2898, 3151, 0, +3026, 3283, 0, +3155, 3415, 0, +3285, 3548, 0, +3415, 3680, 0, +3546, 3812, 0, +3677, 3944, 0, +3808, 4076, 0, +3940, 4095, 0, +1563, 0, 1463, +1561, 0, 1456, +1559, 0, 1445, +1557, 0, 1430, +1553, 0, 1409, +1549, 0, 1380, +1543, 0, 1338, +1543, 0, 1259, +1543, 0, 1127, +1543, 0, 852, +1543, 172, 0, +1543, 1096, 0, +1681, 1489, 0, +1817, 1750, 0, +1947, 1953, 0, +2027, 2087, 0, +2116, 2221, 0, +2213, 2355, 0, +2317, 2488, 0, +2427, 2621, 0, +2541, 2754, 0, +2660, 2886, 0, +2782, 3018, 0, +2906, 3151, 0, +3032, 3283, 0, +3160, 3415, 0, +3288, 3548, 0, +3418, 3680, 0, +3548, 3812, 0, +3679, 3944, 0, +3810, 4076, 0, +3941, 4095, 0, +1696, 0, 1559, +1695, 0, 1552, +1693, 0, 1544, +1691, 0, 1532, +1689, 0, 1515, +1685, 0, 1492, +1681, 0, 1460, +1681, 0, 1401, +1681, 0, 1308, +1681, 0, 1142, +1681, 0, 742, +1681, 0, 0, +1681, 1184, 0, +1817, 1604, 0, +1953, 1872, 0, +2087, 2085, 0, +2169, 2221, 0, +2256, 2355, 0, +2352, 2488, 0, +2454, 2621, 0, +2563, 2754, 0, +2677, 2886, 0, +2794, 3018, 0, +2916, 3151, 0, +3039, 3283, 0, +3165, 3415, 0, +3292, 3548, 0, +3421, 3680, 0, +3550, 3812, 0, +3680, 3944, 0, +3811, 4076, 0, +3942, 4095, 0, +1828, 0, 1661, +1828, 0, 1656, +1827, 0, 1650, +1825, 0, 1640, +1823, 0, 1627, +1821, 0, 1609, +1817, 0, 1585, +1817, 0, 1540, +1817, 0, 1474, +1817, 0, 1366, +1817, 0, 1164, +1817, 0, 536, +1817, 0, 0, +1817, 1281, 0, +1953, 1722, 0, +2087, 1996, 0, +2221, 2212, 0, +2308, 2355, 0, +2394, 2488, 0, +2488, 2621, 0, +2590, 2754, 0, +2698, 2886, 0, +2811, 3018, 0, +2928, 3151, 0, +3049, 3283, 0, +3173, 3415, 0, +3298, 3548, 0, +3425, 3680, 0, +3553, 3812, 0, +3683, 3944, 0, +3812, 4076, 0, +3943, 4095, 0, +1961, 0, 1770, +1961, 0, 1766, +1960, 0, 1761, +1959, 0, 1754, +1958, 0, 1743, +1956, 0, 1730, +1953, 0, 1711, +1953, 0, 1678, +1953, 0, 1629, +1953, 0, 1555, +1953, 0, 1433, +1953, 0, 1190, +1953, 0, 0, +1953, 0, 0, +1953, 1385, 0, +2087, 1843, 0, +2221, 2123, 0, +2355, 2340, 0, +2445, 2488, 0, +2530, 2621, 0, +2624, 2754, 0, +2725, 2886, 0, +2832, 3018, 0, +2945, 3151, 0, +3062, 3283, 0, +3182, 3415, 0, +3305, 3548, 0, +3431, 3680, 0, +3558, 3812, 0, +3686, 3944, 0, +3815, 4076, 0, +3945, 4095, 0, +2094, 0, 1884, +2093, 0, 1881, +2093, 0, 1877, +2092, 0, 1871, +2091, 0, 1863, +2089, 0, 1853, +2087, 0, 1838, +2087, 0, 1813, +2087, 0, 1778, +2087, 0, 1726, +2087, 0, 1646, +2087, 0, 1509, +2087, 0, 1224, +2087, 0, 0, +2087, 0, 0, +2087, 1494, 0, +2221, 1967, 0, +2355, 2251, 0, +2488, 2470, 0, +2581, 2621, 0, +2666, 2754, 0, +2759, 2886, 0, +2859, 3018, 0, +2966, 3151, 0, +3078, 3283, 0, +3195, 3415, 0, +3315, 3548, 0, +3438, 3680, 0, +3563, 3812, 0, +3690, 3944, 0, +3818, 4076, 0, +3947, 4095, 0, +2226, 0, 2002, +2226, 0, 1999, +2225, 0, 1996, +2225, 0, 1992, +2224, 0, 1986, +2223, 0, 1978, +2221, 0, 1967, +2221, 0, 1948, +2221, 0, 1922, +2221, 0, 1885, +2221, 0, 1830, +2221, 0, 1744, +2221, 0, 1596, +2221, 0, 1264, +2221, 0, 0, +2221, 0, 0, +2221, 1608, 0, +2355, 2093, 0, +2488, 2379, 0, +2621, 2600, 0, +2716, 2754, 0, +2800, 2886, 0, +2892, 3018, 0, +2993, 3151, 0, +3099, 3283, 0, +3211, 3415, 0, +3328, 3548, 0, +3448, 3680, 0, +3571, 3812, 0, +3696, 3944, 0, +3822, 4076, 0, +3951, 4095, 0, +2358, 0, 2123, +2358, 0, 2121, +2358, 0, 2119, +2357, 0, 2115, +2357, 0, 2111, +2356, 0, 2105, +2355, 0, 2096, +2355, 0, 2083, +2355, 0, 2063, +2355, 0, 2037, +2355, 0, 1998, +2355, 0, 1940, +2355, 0, 1849, +2355, 0, 1689, +2355, 0, 1313, +2355, 0, 0, +2355, 0, 0, +2355, 1727, 0, +2488, 2221, 0, +2621, 2509, 0, +2754, 2731, 0, +2850, 2886, 0, +2934, 3018, 0, +3026, 3151, 0, +3126, 3283, 0, +3232, 3415, 0, +3344, 3548, 0, +3460, 3680, 0, +3580, 3812, 0, +3703, 3944, 0, +3828, 4076, 0, +3955, 4095, 0, +2491, 0, 2247, +2491, 0, 2245, +2490, 0, 2243, +2490, 0, 2241, +2489, 0, 2238, +2489, 0, 2233, +2488, 0, 2227, +2488, 0, 2217, +2488, 0, 2202, +2488, 0, 2183, +2488, 0, 2155, +2488, 0, 2115, +2488, 0, 2055, +2488, 0, 1960, +2488, 0, 1791, +2488, 0, 1373, +2488, 0, 0, +2488, 0, 0, +2488, 1848, 0, +2621, 2349, 0, +2754, 2640, 0, +2886, 2862, 0, +2984, 3018, 0, +3067, 3151, 0, +3159, 3283, 0, +3259, 3415, 0, +3365, 3548, 0, +3477, 3680, 0, +3593, 3812, 0, +3713, 3944, 0, +3835, 4076, 0, +3961, 4095, 0, +2623, 0, 2372, +2623, 0, 2372, +2623, 0, 2370, +2622, 0, 2368, +2622, 0, 2366, +2621, 0, 2362, +2621, 0, 2357, +2621, 0, 2350, +2621, 0, 2339, +2621, 0, 2325, +2621, 0, 2304, +2621, 0, 2276, +2621, 0, 2235, +2621, 0, 2173, +2621, 0, 2075, +2621, 0, 1899, +2621, 0, 1441, +2621, 0, 0, +2621, 0, 0, +2621, 1972, 0, +2754, 2479, 0, +2886, 2770, 0, +3018, 2992, 0, +3117, 3151, 0, +3200, 3283, 0, +3292, 3415, 0, +3392, 3548, 0, +3497, 3680, 0, +3609, 3812, 0, +3725, 3944, 0, +3845, 4076, 0, +3968, 4095, 0, +2755, 0, 2500, +2755, 0, 2499, +2755, 0, 2498, +2755, 0, 2497, +2755, 0, 2495, +2754, 0, 2492, +2754, 0, 2489, +2754, 0, 2483, +2754, 0, 2475, +2754, 0, 2464, +2754, 0, 2450, +2754, 0, 2429, +2754, 0, 2400, +2754, 0, 2358, +2754, 0, 2295, +2754, 0, 2195, +2754, 0, 2012, +2754, 0, 1521, +2754, 0, 0, +2754, 0, 0, +2754, 2099, 0, +2886, 2609, 0, +3018, 2901, 0, +3151, 3124, 0, +3250, 3283, 0, +3333, 3415, 0, +3425, 3548, 0, +3524, 3680, 0, +3630, 3812, 0, +3741, 3944, 0, +3858, 4076, 0, +3977, 4095, 0, +2887, 0, 2628, +2887, 0, 2628, +2887, 0, 2627, +2887, 0, 2626, +2887, 0, 2625, +2887, 0, 2623, +2886, 0, 2620, +2886, 0, 2616, +2886, 0, 2610, +2886, 0, 2602, +2886, 0, 2591, +2886, 0, 2576, +2886, 0, 2555, +2886, 0, 2526, +2886, 0, 2483, +2886, 0, 2419, +2886, 0, 2317, +2886, 0, 2129, +2886, 0, 1606, +2886, 0, 0, +2886, 0, 0, +2886, 2226, 0, +3018, 2739, 0, +3151, 3032, 0, +3283, 3256, 0, +3383, 3415, 0, +3466, 3548, 0, +3557, 3680, 0, +3657, 3812, 0, +3762, 3944, 0, +3874, 4076, 0, +3990, 4095, 0, +3019, 0, 2758, +3019, 0, 2757, +3019, 0, 2757, +3019, 0, 2756, +3019, 0, 2755, +3019, 0, 2753, +3018, 0, 2751, +3018, 0, 2748, +3018, 0, 2744, +3018, 0, 2738, +3018, 0, 2730, +3018, 0, 2719, +3018, 0, 2703, +3018, 0, 2683, +3018, 0, 2653, +3018, 0, 2610, +3018, 0, 2545, +3018, 0, 2441, +3018, 0, 2249, +3018, 0, 1700, +3018, 0, 0, +3018, 0, 0, +3018, 2354, 0, +3151, 2871, 0, +3283, 3164, 0, +3415, 3387, 0, +3515, 3548, 0, +3598, 3680, 0, +3690, 3812, 0, +3789, 3944, 0, +3895, 4076, 0, +4006, 4095, 0, +3152, 0, 2888, +3152, 0, 2888, +3152, 0, 2887, +3151, 0, 2886, +3151, 0, 2886, +3151, 0, 2885, +3151, 0, 2883, +3151, 0, 2881, +3151, 0, 2877, +3151, 0, 2873, +3151, 0, 2867, +3151, 0, 2859, +3151, 0, 2848, +3151, 0, 2833, +3151, 0, 2812, +3151, 0, 2782, +3151, 0, 2738, +3151, 0, 2673, +3151, 0, 2568, +3151, 0, 2373, +3151, 0, 1802, +3151, 0, 0, +3151, 0, 0, +3151, 2484, 0, +3283, 3001, 0, +3415, 3295, 0, +3548, 3519, 0, +3648, 3680, 0, +3731, 3812, 0, +3822, 3944, 0, +3921, 4076, 0, +4027, 4095, 0, +3284, 0, 3018, +3283, 0, 3018, +3283, 0, 3018, +3283, 0, 3017, +3283, 0, 3016, +3283, 0, 3016, +3283, 0, 3015, +3283, 0, 3013, +3283, 0, 3010, +3283, 0, 3007, +3283, 0, 3003, +3283, 0, 2997, +3283, 0, 2988, +3283, 0, 2977, +3283, 0, 2962, +3283, 0, 2941, +3283, 0, 2911, +3283, 0, 2867, +3283, 0, 2801, +3283, 0, 2695, +3283, 0, 2498, +3283, 0, 1908, +3283, 0, 0, +3283, 0, 0, +3283, 2614, 0, +3415, 3133, 0, +3548, 3427, 0, +3680, 3651, 0, +3781, 3812, 0, +3863, 3944, 0, +3954, 4076, 0, +4054, 4095, 0, +3416, 0, 3149, +3416, 0, 3149, +3416, 0, 3149, +3416, 0, 3148, +3416, 0, 3148, +3416, 0, 3147, +3415, 0, 3147, +3415, 0, 3145, +3415, 0, 3144, +3415, 0, 3141, +3415, 0, 3138, +3415, 0, 3133, +3415, 0, 3127, +3415, 0, 3119, +3415, 0, 3108, +3415, 0, 3093, +3415, 0, 3071, +3415, 0, 3041, +3415, 0, 2997, +3415, 0, 2931, +3415, 0, 2824, +3415, 0, 2625, +3415, 0, 2026, +3415, 0, 0, +3415, 0, 0, +3415, 2745, 0, +3548, 3265, 0, +3680, 3559, 0, +3812, 3783, 0, +3913, 3944, 0, +3995, 4076, 0, +4087, 4095, 0, +3548, 0, 3280, +3548, 0, 3280, +3548, 0, 3280, +3548, 0, 3280, +3548, 0, 3280, +3548, 0, 3279, +3548, 0, 3279, +3548, 0, 3278, +3548, 0, 3276, +3548, 0, 3274, +3548, 0, 3272, +3548, 0, 3269, +3548, 0, 3264, +3548, 0, 3258, +3548, 0, 3250, +3548, 0, 3239, +3548, 0, 3223, +3548, 0, 3202, +3548, 0, 3172, +3548, 0, 3128, +3548, 0, 3061, +3548, 0, 2954, +3548, 0, 2754, +3548, 0, 2141, +3548, 0, 0, +3548, 0, 0, +3548, 2876, 0, +3680, 3396, 0, +3812, 3691, 0, +3944, 3915, 0, +4045, 4076, 0, +4095, 4095, 0, +3680, 0, 3412, +3680, 0, 3412, +3680, 0, 3412, +3680, 0, 3412, +3680, 0, 3411, +3680, 0, 3411, +3680, 0, 3411, +3680, 0, 3410, +3680, 0, 3409, +3680, 0, 3407, +3680, 0, 3406, +3680, 0, 3403, +3680, 0, 3400, +3680, 0, 3395, +3680, 0, 3389, +3680, 0, 3381, +3680, 0, 3370, +3680, 0, 3354, +3680, 0, 3333, +3680, 0, 3303, +3680, 0, 3258, +3680, 0, 3192, +3680, 0, 3084, +3680, 0, 2883, +3680, 0, 2266, +3680, 0, 0, +3680, 0, 0, +3680, 3007, 0, +3812, 3528, 0, +3944, 3823, 0, +4076, 4047, 0, +4095, 4095, 0, +3812, 0, 3544, +3812, 0, 3544, +3812, 0, 3543, +3812, 0, 3543, +3812, 0, 3543, +3812, 0, 3543, +3812, 0, 3543, +3812, 0, 3542, +3812, 0, 3541, +3812, 0, 3540, +3812, 0, 3539, +3812, 0, 3537, +3812, 0, 3534, +3812, 0, 3531, +3812, 0, 3527, +3812, 0, 3521, +3812, 0, 3513, +3812, 0, 3501, +3812, 0, 3486, +3812, 0, 3464, +3812, 0, 3434, +3812, 0, 3390, +3812, 0, 3323, +3812, 0, 3215, +3812, 0, 3014, +3812, 0, 2389, +3812, 0, 0, +3812, 0, 0, +3812, 3139, 0, +3944, 3660, 0, +4076, 3955, 0, +4095, 4095, 0, +3944, 0, 3675, +3944, 0, 3675, +3944, 0, 3675, +3944, 0, 3675, +3944, 0, 3675, +3944, 0, 3675, +3944, 0, 3674, +3944, 0, 3674, +3944, 0, 3673, +3944, 0, 3673, +3944, 0, 3672, +3944, 0, 3670, +3944, 0, 3668, +3944, 0, 3666, +3944, 0, 3663, +3944, 0, 3658, +3944, 0, 3652, +3944, 0, 3644, +3944, 0, 3633, +3944, 0, 3617, +3944, 0, 3596, +3944, 0, 3565, +3944, 0, 3521, +3944, 0, 3454, +3944, 0, 3346, +3944, 0, 3144, +3944, 0, 2513, +3944, 0, 0, +3944, 0, 0, +3944, 3270, 0, +4076, 3792, 0, +4095, 4087, 0, +4076, 0, 3807, +4076, 0, 3807, +4076, 0, 3807, +4076, 0, 3807, +4076, 0, 3807, +4076, 0, 3807, +4076, 0, 3806, +4076, 0, 3806, +4076, 0, 3805, +4076, 0, 3805, +4076, 0, 3804, +4076, 0, 3803, +4076, 0, 3802, +4076, 0, 3800, +4076, 0, 3798, +4076, 0, 3794, +4076, 0, 3790, +4076, 0, 3784, +4076, 0, 3776, +4076, 0, 3764, +4076, 0, 3749, +4076, 0, 3727, +4076, 0, 3697, +4076, 0, 3653, +4076, 0, 3586, +4076, 0, 3477, +4076, 0, 3274, +4076, 0, 2639, +4076, 0, 0, +4076, 0, 0, +4076, 3402, 0, +4095, 3925, 0, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3938, +4095, 0, 3938, +4095, 0, 3938, +4095, 0, 3937, +4095, 0, 3937, +4095, 0, 3935, +4095, 0, 3934, +4095, 0, 3932, +4095, 0, 3930, +4095, 0, 3927, +4095, 0, 3922, +4095, 0, 3916, +4095, 0, 3908, +4095, 0, 3896, +4095, 0, 3881, +4095, 0, 3859, +4095, 0, 3829, +4095, 0, 3784, +4095, 0, 3718, +4095, 0, 3609, +4095, 0, 3406, +4095, 0, 2770, +4095, 0, 0, +4095, 0, 0, +4095, 3534, 0, +0, 792, 1025, +0, 832, 1025, +0, 881, 1025, +0, 939, 1025, +0, 1006, 1025, +0, 1025, 957, +0, 1025, 811, +0, 1025, 488, +0, 1160, 0, +0, 1295, 0, +471, 1429, 0, +897, 1563, 0, +1167, 1696, 0, +1381, 1828, 0, +1565, 1961, 0, +1733, 2094, 0, +1890, 2226, 0, +2040, 2358, 0, +2185, 2491, 0, +2327, 2623, 0, +2466, 2755, 0, +2603, 2887, 0, +2738, 3019, 0, +2873, 3152, 0, +3008, 3284, 0, +3141, 3416, 0, +3275, 3548, 0, +3408, 3680, 0, +3540, 3812, 0, +3673, 3944, 0, +3805, 4076, 0, +3938, 4095, 0, +0, 748, 1025, +0, 800, 1020, +0, 852, 1020, +0, 914, 1020, +0, 985, 1020, +0, 1020, 970, +0, 1020, 829, +0, 1020, 524, +0, 1157, 0, +0, 1292, 0, +562, 1427, 0, +935, 1561, 0, +1188, 1695, 0, +1394, 1828, 0, +1574, 1961, 0, +1739, 2093, 0, +1894, 2226, 0, +2043, 2358, 0, +2187, 2491, 0, +2328, 2623, 0, +2467, 2755, 0, +2604, 2887, 0, +2739, 3019, 0, +2874, 3152, 0, +3008, 3283, 0, +3141, 3416, 0, +3275, 3548, 0, +3408, 3680, 0, +3540, 3812, 0, +3673, 3944, 0, +3805, 4076, 0, +3938, 4095, 0, +0, 681, 1025, +0, 740, 1020, +0, 810, 1014, +0, 877, 1014, +0, 954, 1014, +0, 1014, 987, +0, 1014, 852, +0, 1014, 568, +0, 1152, 0, +9, 1289, 0, +662, 1424, 0, +981, 1559, 0, +1216, 1693, 0, +1412, 1827, 0, +1586, 1960, 0, +1748, 2093, 0, +1900, 2225, 0, +2047, 2358, 0, +2190, 2490, 0, +2331, 2623, 0, +2469, 2755, 0, +2605, 2887, 0, +2740, 3019, 0, +2875, 3152, 0, +3008, 3283, 0, +3142, 3416, 0, +3275, 3548, 0, +3408, 3680, 0, +3541, 3812, 0, +3673, 3944, 0, +3805, 4076, 0, +3938, 4095, 0, +0, 573, 1025, +0, 647, 1020, +0, 731, 1014, +0, 823, 1005, +0, 908, 1005, +0, 1002, 1005, +0, 1005, 881, +0, 1005, 620, +0, 1146, 0, +346, 1284, 0, +767, 1421, 0, +1037, 1557, 0, +1249, 1691, 0, +1434, 1825, 0, +1601, 1959, 0, +1758, 2092, 0, +1908, 2225, 0, +2053, 2357, 0, +2195, 2490, 0, +2334, 2622, 0, +2471, 2755, 0, +2607, 2887, 0, +2741, 3019, 0, +2876, 3151, 0, +3009, 3283, 0, +3142, 3416, 0, +3275, 3548, 0, +3408, 3680, 0, +3541, 3812, 0, +3673, 3944, 0, +3805, 4076, 0, +3938, 4095, 0, +0, 371, 1025, +0, 482, 1020, +0, 598, 1014, +0, 717, 1005, +298, 840, 994, +298, 947, 994, +298, 994, 917, +298, 994, 682, +81, 1137, 80, +587, 1278, 0, +878, 1416, 0, +1102, 1553, 0, +1291, 1689, 0, +1462, 1823, 0, +1621, 1958, 0, +1772, 2091, 0, +1918, 2224, 0, +2060, 2357, 0, +2200, 2489, 0, +2337, 2622, 0, +2474, 2755, 0, +2609, 2887, 0, +2743, 3019, 0, +2877, 3151, 0, +3010, 3283, 0, +3143, 3416, 0, +3276, 3548, 0, +3409, 3680, 0, +3541, 3812, 0, +3673, 3944, 0, +3805, 4076, 0, +3938, 4095, 0, +0, 0, 1025, +0, 81, 1020, +0, 323, 1014, +0, 523, 1005, +298, 699, 994, +544, 862, 978, +544, 978, 960, +544, 978, 754, +529, 1126, 430, +787, 1270, 212, +994, 1410, 0, +1176, 1549, 0, +1341, 1685, 0, +1497, 1821, 0, +1646, 1956, 0, +1790, 2089, 0, +1931, 2223, 0, +2070, 2356, 0, +2207, 2489, 0, +2343, 2621, 0, +2478, 2754, 0, +2612, 2887, 0, +2745, 3019, 0, +2879, 3151, 0, +3011, 3283, 0, +3144, 3416, 0, +3277, 3548, 0, +3409, 3680, 0, +3541, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3938, 4095, 0, +0, 0, 1025, +0, 0, 1020, +0, 0, 1014, +0, 0, 1005, +298, 397, 994, +544, 673, 978, +746, 890, 956, +746, 956, 834, +805, 1110, 676, +963, 1258, 562, +1114, 1402, 344, +1259, 1543, 0, +1401, 1681, 0, +1540, 1817, 0, +1678, 1953, 0, +1813, 2087, 0, +1948, 2221, 0, +2083, 2355, 0, +2217, 2488, 0, +2350, 2621, 0, +2483, 2754, 0, +2616, 2886, 0, +2748, 3018, 0, +2881, 3151, 0, +3013, 3283, 0, +3145, 3415, 0, +3278, 3548, 0, +3410, 3680, 0, +3542, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3938, 4095, 0, +488, 0, 1025, +524, 0, 1020, +568, 0, 1014, +620, 0, 1005, +682, 298, 994, +754, 544, 978, +834, 746, 956, +924, 924, 924, +1021, 1088, 878, +1126, 1242, 809, +1236, 1390, 695, +1351, 1534, 476, +1470, 1674, 0, +1592, 1813, 0, +1716, 1950, 0, +1843, 2085, 0, +1970, 2220, 0, +2099, 2353, 0, +2229, 2487, 0, +2359, 2620, 0, +2490, 2753, 0, +2621, 2886, 0, +2752, 3018, 0, +2883, 3151, 0, +3015, 3283, 0, +3147, 3415, 0, +3279, 3548, 0, +3411, 3680, 0, +3543, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3939, 4095, 0, +929, 0, 1160, +943, 0, 1157, +960, 0, 1152, +983, 0, 1146, +1013, 80, 1137, +1049, 430, 1126, +1092, 676, 1110, +1088, 878, 1021, +1088, 967, 878, +1242, 1225, 809, +1343, 1390, 695, +1437, 1534, 476, +1537, 1674, 0, +1644, 1813, 0, +1757, 1950, 0, +1873, 2085, 0, +1994, 2220, 0, +2117, 2353, 0, +2242, 2487, 0, +2369, 2620, 0, +2497, 2753, 0, +2626, 2886, 0, +2756, 3018, 0, +2887, 3151, 0, +3017, 3283, 0, +3149, 3415, 0, +3280, 3548, 0, +3412, 3680, 0, +3543, 3812, 0, +3675, 3944, 0, +3807, 4076, 0, +3939, 4095, 0, +1204, 0, 1295, +1211, 0, 1292, +1221, 0, 1289, +1235, 0, 1284, +1251, 0, 1278, +1270, 212, 1266, +1258, 562, 1211, +1242, 809, 1126, +1242, 809, 938, +1242, 1018, 809, +1390, 1313, 695, +1531, 1534, 476, +1614, 1674, 0, +1706, 1813, 0, +1806, 1950, 0, +1912, 2085, 0, +2023, 2220, 0, +2140, 2353, 0, +2260, 2487, 0, +2382, 2620, 0, +2507, 2753, 0, +2634, 2886, 0, +2762, 3018, 0, +2891, 3151, 0, +3021, 3283, 0, +3151, 3415, 0, +3282, 3548, 0, +3413, 3680, 0, +3544, 3812, 0, +3676, 3944, 0, +3808, 4076, 0, +3940, 4095, 0, +1419, 0, 1429, +1424, 0, 1427, +1424, 0, 1418, +1421, 0, 1403, +1416, 0, 1381, +1410, 0, 1350, +1402, 344, 1304, +1390, 695, 1236, +1390, 695, 1095, +1390, 695, 793, +1390, 1078, 695, +1534, 1409, 476, +1674, 1648, 0, +1777, 1813, 0, +1864, 1950, 0, +1958, 2085, 0, +2060, 2220, 0, +2168, 2353, 0, +2282, 2487, 0, +2399, 2620, 0, +2521, 2753, 0, +2644, 2886, 0, +2769, 3018, 0, +2896, 3151, 0, +3025, 3283, 0, +3154, 3415, 0, +3284, 3548, 0, +3415, 3680, 0, +3546, 3812, 0, +3677, 3944, 0, +3808, 4076, 0, +3940, 4095, 0, +1563, 0, 1515, +1561, 0, 1508, +1559, 0, 1499, +1557, 0, 1486, +1553, 0, 1467, +1549, 0, 1442, +1543, 0, 1405, +1534, 476, 1351, +1534, 476, 1246, +1534, 476, 1051, +1534, 476, 479, +1534, 1149, 476, +1674, 1512, 0, +1813, 1763, 0, +1931, 1950, 0, +2014, 2085, 0, +2105, 2220, 0, +2204, 2353, 0, +2310, 2487, 0, +2421, 2620, 0, +2537, 2753, 0, +2657, 2886, 0, +2779, 3018, 0, +2904, 3151, 0, +3031, 3283, 0, +3158, 3415, 0, +3287, 3548, 0, +3417, 3680, 0, +3548, 3812, 0, +3678, 3944, 0, +3809, 4076, 0, +3941, 4095, 0, +1696, 0, 1601, +1695, 0, 1596, +1693, 0, 1588, +1691, 0, 1577, +1689, 0, 1562, +1685, 0, 1541, +1681, 0, 1512, +1674, 0, 1470, +1674, 0, 1391, +1674, 0, 1258, +1674, 0, 983, +1674, 313, 0, +1674, 1228, 0, +1813, 1622, 0, +1950, 1882, 0, +2079, 2085, 0, +2159, 2220, 0, +2248, 2353, 0, +2345, 2487, 0, +2449, 2620, 0, +2559, 2753, 0, +2673, 2886, 0, +2792, 3018, 0, +2914, 3151, 0, +3038, 3283, 0, +3164, 3415, 0, +3292, 3548, 0, +3420, 3680, 0, +3550, 3812, 0, +3680, 3944, 0, +3810, 4076, 0, +3942, 4095, 0, +1828, 0, 1696, +1828, 0, 1691, +1827, 0, 1684, +1825, 0, 1676, +1823, 0, 1664, +1821, 0, 1648, +1817, 0, 1625, +1813, 0, 1592, +1813, 0, 1533, +1813, 0, 1440, +1813, 0, 1275, +1813, 0, 874, +1813, 0, 0, +1813, 1317, 0, +1950, 1736, 0, +2085, 2004, 0, +2220, 2217, 0, +2301, 2353, 0, +2388, 2487, 0, +2483, 2620, 0, +2586, 2753, 0, +2695, 2886, 0, +2808, 3018, 0, +2927, 3151, 0, +3047, 3283, 0, +3171, 3415, 0, +3297, 3548, 0, +3425, 3680, 0, +3553, 3812, 0, +3682, 3944, 0, +3812, 4076, 0, +3943, 4095, 0, +1961, 0, 1797, +1961, 0, 1793, +1960, 0, 1789, +1959, 0, 1781, +1958, 0, 1772, +1956, 0, 1759, +1953, 0, 1742, +1950, 0, 1716, +1950, 0, 1672, +1950, 0, 1606, +1950, 0, 1498, +1950, 0, 1295, +1950, 0, 670, +1950, 0, 0, +1950, 1413, 0, +2085, 1854, 0, +2220, 2128, 0, +2353, 2344, 0, +2440, 2487, 0, +2526, 2620, 0, +2620, 2753, 0, +2722, 2886, 0, +2830, 3018, 0, +2943, 3151, 0, +3060, 3283, 0, +3181, 3415, 0, +3305, 3548, 0, +3430, 3680, 0, +3557, 3812, 0, +3686, 3944, 0, +3815, 4076, 0, +3945, 4095, 0, +2094, 0, 1905, +2093, 0, 1902, +2093, 0, 1898, +2092, 0, 1893, +2091, 0, 1885, +2089, 0, 1875, +2087, 0, 1862, +2085, 0, 1843, +2085, 0, 1810, +2085, 0, 1761, +2085, 0, 1687, +2085, 0, 1565, +2085, 0, 1322, +2085, 0, 10, +2085, 0, 0, +2085, 1517, 0, +2220, 1975, 0, +2353, 2255, 0, +2487, 2473, 0, +2577, 2620, 0, +2662, 2753, 0, +2756, 2886, 0, +2857, 3018, 0, +2964, 3151, 0, +3077, 3283, 0, +3194, 3415, 0, +3314, 3548, 0, +3437, 3680, 0, +3563, 3812, 0, +3690, 3944, 0, +3818, 4076, 0, +3947, 4095, 0, +2226, 0, 2018, +2226, 0, 2016, +2225, 0, 2013, +2225, 0, 2009, +2224, 0, 2003, +2223, 0, 1995, +2221, 0, 1985, +2220, 0, 1970, +2220, 0, 1946, +2220, 0, 1910, +2220, 0, 1858, +2220, 0, 1778, +2220, 0, 1642, +2220, 0, 1355, +2220, 0, 0, +2220, 0, 0, +2220, 1626, 0, +2353, 2099, 0, +2487, 2383, 0, +2620, 2602, 0, +2713, 2753, 0, +2798, 2886, 0, +2890, 3018, 0, +2991, 3151, 0, +3098, 3283, 0, +3210, 3415, 0, +3327, 3548, 0, +3447, 3680, 0, +3570, 3812, 0, +3695, 3944, 0, +3822, 4076, 0, +3950, 4095, 0, +2358, 0, 2136, +2358, 0, 2134, +2358, 0, 2132, +2357, 0, 2128, +2357, 0, 2124, +2356, 0, 2118, +2355, 0, 2110, +2353, 0, 2099, +2353, 0, 2081, +2353, 0, 2054, +2353, 0, 2017, +2353, 0, 1962, +2353, 0, 1876, +2353, 0, 1727, +2353, 0, 1396, +2353, 0, 0, +2353, 0, 0, +2353, 1740, 0, +2487, 2226, 0, +2620, 2511, 0, +2753, 2732, 0, +2848, 2886, 0, +2932, 3018, 0, +3025, 3151, 0, +3125, 3283, 0, +3231, 3415, 0, +3343, 3548, 0, +3460, 3680, 0, +3580, 3812, 0, +3703, 3944, 0, +3828, 4076, 0, +3955, 4095, 0, +2491, 0, 2256, +2491, 0, 2255, +2490, 0, 2253, +2490, 0, 2251, +2489, 0, 2247, +2489, 0, 2243, +2488, 0, 2237, +2487, 0, 2229, +2487, 0, 2215, +2487, 0, 2196, +2487, 0, 2169, +2487, 0, 2130, +2487, 0, 2072, +2487, 0, 1981, +2487, 0, 1822, +2487, 0, 1446, +2487, 0, 0, +2487, 0, 0, +2487, 1859, 0, +2620, 2352, 0, +2753, 2641, 0, +2886, 2863, 0, +2982, 3018, 0, +3066, 3151, 0, +3158, 3283, 0, +3258, 3415, 0, +3364, 3548, 0, +3476, 3680, 0, +3593, 3812, 0, +3712, 3944, 0, +3835, 4076, 0, +3960, 4095, 0, +2623, 0, 2380, +2623, 0, 2379, +2623, 0, 2378, +2622, 0, 2375, +2622, 0, 2373, +2621, 0, 2370, +2621, 0, 2365, +2620, 0, 2359, +2620, 0, 2348, +2620, 0, 2334, +2620, 0, 2314, +2620, 0, 2287, +2620, 0, 2247, +2620, 0, 2187, +2620, 0, 2092, +2620, 0, 1923, +2620, 0, 1505, +2620, 0, 0, +2620, 0, 0, +2620, 1981, 0, +2753, 2482, 0, +2886, 2772, 0, +3018, 2993, 0, +3116, 3151, 0, +3199, 3283, 0, +3291, 3415, 0, +3391, 3548, 0, +3497, 3680, 0, +3609, 3812, 0, +3725, 3944, 0, +3845, 4076, 0, +3968, 4095, 0, +2755, 0, 2505, +2755, 0, 2505, +2755, 0, 2504, +2755, 0, 2502, +2755, 0, 2501, +2754, 0, 2498, +2754, 0, 2494, +2753, 0, 2490, +2753, 0, 2482, +2753, 0, 2471, +2753, 0, 2457, +2753, 0, 2437, +2753, 0, 2408, +2753, 0, 2367, +2753, 0, 2305, +2753, 0, 2208, +2753, 0, 2031, +2753, 0, 1575, +2753, 0, 0, +2753, 0, 0, +2753, 2105, 0, +2886, 2611, 0, +3018, 2902, 0, +3151, 3125, 0, +3249, 3283, 0, +3333, 3415, 0, +3424, 3548, 0, +3524, 3680, 0, +3630, 3812, 0, +3741, 3944, 0, +3857, 4076, 0, +3977, 4095, 0, +2887, 0, 2633, +2887, 0, 2632, +2887, 0, 2631, +2887, 0, 2630, +2887, 0, 2629, +2887, 0, 2627, +2886, 0, 2624, +2886, 0, 2621, +2886, 0, 2615, +2886, 0, 2607, +2886, 0, 2596, +2886, 0, 2581, +2886, 0, 2561, +2886, 0, 2532, +2886, 0, 2490, +2886, 0, 2427, +2886, 0, 2327, +2886, 0, 2144, +2886, 0, 1651, +2886, 0, 0, +2886, 0, 0, +2886, 2231, 0, +3018, 2740, 0, +3151, 3033, 0, +3283, 3256, 0, +3382, 3415, 0, +3466, 3548, 0, +3557, 3680, 0, +3656, 3812, 0, +3762, 3944, 0, +3873, 4076, 0, +3990, 4095, 0, +3019, 0, 2761, +3019, 0, 2760, +3019, 0, 2760, +3019, 0, 2759, +3019, 0, 2758, +3019, 0, 2756, +3018, 0, 2754, +3018, 0, 2752, +3018, 0, 2747, +3018, 0, 2742, +3018, 0, 2734, +3018, 0, 2723, +3018, 0, 2708, +3018, 0, 2687, +3018, 0, 2658, +3018, 0, 2615, +3018, 0, 2551, +3018, 0, 2449, +3018, 0, 2261, +3018, 0, 1737, +3018, 0, 0, +3018, 0, 0, +3018, 2358, 0, +3151, 2872, 0, +3283, 3164, 0, +3415, 3388, 0, +3515, 3548, 0, +3598, 3680, 0, +3690, 3812, 0, +3789, 3944, 0, +3895, 4076, 0, +4006, 4095, 0, +3152, 0, 2890, +3152, 0, 2890, +3152, 0, 2890, +3151, 0, 2889, +3151, 0, 2888, +3151, 0, 2887, +3151, 0, 2885, +3151, 0, 2883, +3151, 0, 2880, +3151, 0, 2876, +3151, 0, 2870, +3151, 0, 2862, +3151, 0, 2851, +3151, 0, 2836, +3151, 0, 2815, +3151, 0, 2785, +3151, 0, 2742, +3151, 0, 2678, +3151, 0, 2573, +3151, 0, 2382, +3151, 0, 1832, +3151, 0, 0, +3151, 0, 0, +3151, 2487, 0, +3283, 3002, 0, +3415, 3296, 0, +3548, 3520, 0, +3648, 3680, 0, +3730, 3812, 0, +3822, 3944, 0, +3921, 4076, 0, +4027, 4095, 0, +3284, 0, 3020, +3283, 0, 3020, +3283, 0, 3019, +3283, 0, 3019, +3283, 0, 3018, +3283, 0, 3018, +3283, 0, 3016, +3283, 0, 3015, +3283, 0, 3013, +3283, 0, 3009, +3283, 0, 3005, +3283, 0, 2999, +3283, 0, 2991, +3283, 0, 2980, +3283, 0, 2965, +3283, 0, 2943, +3283, 0, 2914, +3283, 0, 2870, +3283, 0, 2805, +3283, 0, 2700, +3283, 0, 2504, +3283, 0, 1932, +3283, 0, 0, +3283, 0, 0, +3283, 2616, 0, +3415, 3134, 0, +3548, 3428, 0, +3680, 3652, 0, +3780, 3812, 0, +3863, 3944, 0, +3954, 4076, 0, +4053, 4095, 0, +3416, 0, 3151, +3416, 0, 3151, +3416, 0, 3150, +3416, 0, 3150, +3416, 0, 3149, +3416, 0, 3149, +3415, 0, 3148, +3415, 0, 3147, +3415, 0, 3145, +3415, 0, 3143, +3415, 0, 3139, +3415, 0, 3135, +3415, 0, 3129, +3415, 0, 3121, +3415, 0, 3110, +3415, 0, 3094, +3415, 0, 3073, +3415, 0, 3043, +3415, 0, 2999, +3415, 0, 2934, +3415, 0, 2827, +3415, 0, 2630, +3415, 0, 2044, +3415, 0, 0, +3415, 0, 0, +3415, 2746, 0, +3548, 3265, 0, +3680, 3559, 0, +3812, 3784, 0, +3912, 3944, 0, +3995, 4076, 0, +4087, 4095, 0, +3548, 0, 3281, +3548, 0, 3281, +3548, 0, 3281, +3548, 0, 3281, +3548, 0, 3280, +3548, 0, 3280, +3548, 0, 3280, +3548, 0, 3279, +3548, 0, 3277, +3548, 0, 3276, +3548, 0, 3273, +3548, 0, 3270, +3548, 0, 3265, +3548, 0, 3259, +3548, 0, 3251, +3548, 0, 3240, +3548, 0, 3225, +3548, 0, 3203, +3548, 0, 3173, +3548, 0, 3129, +3548, 0, 3063, +3548, 0, 2956, +3548, 0, 2758, +3548, 0, 2156, +3548, 0, 0, +3548, 0, 0, +3548, 2877, 0, +3680, 3397, 0, +3812, 3691, 0, +3944, 3915, 0, +4045, 4076, 0, +4095, 4095, 0, +3680, 0, 3413, +3680, 0, 3413, +3680, 0, 3413, +3680, 0, 3412, +3680, 0, 3412, +3680, 0, 3412, +3680, 0, 3411, +3680, 0, 3411, +3680, 0, 3410, +3680, 0, 3408, +3680, 0, 3406, +3680, 0, 3404, +3680, 0, 3401, +3680, 0, 3396, +3680, 0, 3390, +3680, 0, 3382, +3680, 0, 3371, +3680, 0, 3356, +3680, 0, 3334, +3680, 0, 3304, +3680, 0, 3260, +3680, 0, 3193, +3680, 0, 3086, +3680, 0, 2886, +3680, 0, 2277, +3680, 0, 0, +3680, 0, 0, +3680, 3008, 0, +3812, 3529, 0, +3944, 3823, 0, +4076, 4047, 0, +4095, 4095, 0, +3812, 0, 3544, +3812, 0, 3544, +3812, 0, 3544, +3812, 0, 3544, +3812, 0, 3544, +3812, 0, 3543, +3812, 0, 3543, +3812, 0, 3543, +3812, 0, 3542, +3812, 0, 3541, +3812, 0, 3540, +3812, 0, 3538, +3812, 0, 3535, +3812, 0, 3532, +3812, 0, 3528, +3812, 0, 3521, +3812, 0, 3513, +3812, 0, 3502, +3812, 0, 3487, +3812, 0, 3465, +3812, 0, 3435, +3812, 0, 3391, +3812, 0, 3324, +3812, 0, 3216, +3812, 0, 3016, +3812, 0, 2397, +3812, 0, 0, +3812, 0, 0, +3812, 3139, 0, +3944, 3660, 0, +4076, 3955, 0, +4095, 4095, 0, +3944, 0, 3676, +3944, 0, 3676, +3944, 0, 3676, +3944, 0, 3676, +3944, 0, 3675, +3944, 0, 3675, +3944, 0, 3675, +3944, 0, 3674, +3944, 0, 3674, +3944, 0, 3673, +3944, 0, 3672, +3944, 0, 3671, +3944, 0, 3669, +3944, 0, 3666, +3944, 0, 3663, +3944, 0, 3659, +3944, 0, 3653, +3944, 0, 3645, +3944, 0, 3633, +3944, 0, 3618, +3944, 0, 3596, +3944, 0, 3566, +3944, 0, 3522, +3944, 0, 3455, +3944, 0, 3347, +3944, 0, 3145, +3944, 0, 2520, +3944, 0, 0, +3944, 0, 0, +3944, 3271, 0, +4076, 3792, 0, +4095, 4087, 0, +4076, 0, 3808, +4076, 0, 3807, +4076, 0, 3807, +4076, 0, 3807, +4076, 0, 3807, +4076, 0, 3807, +4076, 0, 3807, +4076, 0, 3806, +4076, 0, 3806, +4076, 0, 3805, +4076, 0, 3805, +4076, 0, 3804, +4076, 0, 3802, +4076, 0, 3801, +4076, 0, 3798, +4076, 0, 3795, +4076, 0, 3790, +4076, 0, 3784, +4076, 0, 3776, +4076, 0, 3765, +4076, 0, 3749, +4076, 0, 3728, +4076, 0, 3697, +4076, 0, 3653, +4076, 0, 3586, +4076, 0, 3478, +4076, 0, 3276, +4076, 0, 2644, +4076, 0, 0, +4076, 0, 0, +4076, 3402, 0, +4095, 3925, 0, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3938, +4095, 0, 3938, +4095, 0, 3937, +4095, 0, 3937, +4095, 0, 3936, +4095, 0, 3934, +4095, 0, 3932, +4095, 0, 3930, +4095, 0, 3927, +4095, 0, 3922, +4095, 0, 3916, +4095, 0, 3908, +4095, 0, 3897, +4095, 0, 3881, +4095, 0, 3860, +4095, 0, 3829, +4095, 0, 3785, +4095, 0, 3718, +4095, 0, 3610, +4095, 0, 3407, +4095, 0, 2773, +4095, 0, 0, +4095, 0, 0, +4095, 3534, 0, +0, 918, 1160, +0, 949, 1160, +0, 987, 1160, +0, 1033, 1160, +0, 1089, 1160, +0, 1154, 1160, +0, 1160, 1079, +0, 1160, 929, +0, 1160, 592, +0, 1295, 0, +0, 1429, 0, +523, 1563, 0, +998, 1696, 0, +1283, 1828, 0, +1503, 1961, 0, +1691, 2094, 0, +1860, 2226, 0, +2019, 2358, 0, +2170, 2491, 0, +2315, 2623, 0, +2457, 2755, 0, +2597, 2887, 0, +2734, 3019, 0, +2870, 3152, 0, +3005, 3284, 0, +3139, 3416, 0, +3273, 3548, 0, +3406, 3680, 0, +3540, 3812, 0, +3672, 3944, 0, +3805, 4076, 0, +3937, 4095, 0, +0, 885, 1160, +0, 924, 1157, +0, 964, 1157, +0, 1013, 1157, +0, 1071, 1157, +0, 1139, 1157, +0, 1157, 1089, +0, 1157, 943, +0, 1157, 620, +0, 1292, 0, +0, 1427, 0, +605, 1561, 0, +1029, 1695, 0, +1300, 1828, 0, +1513, 1961, 0, +1698, 2093, 0, +1865, 2226, 0, +2022, 2358, 0, +2172, 2491, 0, +2317, 2623, 0, +2459, 2755, 0, +2598, 2887, 0, +2735, 3019, 0, +2871, 3152, 0, +3005, 3283, 0, +3140, 3416, 0, +3273, 3548, 0, +3407, 3680, 0, +3540, 3812, 0, +3672, 3944, 0, +3805, 4076, 0, +3937, 4095, 0, +0, 836, 1160, +0, 879, 1157, +0, 932, 1152, +0, 984, 1152, +0, 1045, 1152, +0, 1117, 1152, +0, 1152, 1102, +0, 1152, 960, +0, 1152, 656, +0, 1289, 0, +0, 1424, 0, +696, 1559, 0, +1067, 1693, 0, +1321, 1827, 0, +1526, 1960, 0, +1706, 2093, 0, +1871, 2225, 0, +2027, 2358, 0, +2175, 2490, 0, +2320, 2623, 0, +2460, 2755, 0, +2599, 2887, 0, +2735, 3019, 0, +2871, 3152, 0, +3006, 3283, 0, +3140, 3416, 0, +3274, 3548, 0, +3407, 3680, 0, +3540, 3812, 0, +3673, 3944, 0, +3805, 4076, 0, +3937, 4095, 0, +0, 762, 1160, +0, 813, 1157, +0, 873, 1152, +0, 942, 1146, +0, 1009, 1146, +0, 1086, 1146, +0, 1146, 1119, +0, 1146, 983, +0, 1146, 700, +0, 1284, 0, +141, 1421, 0, +794, 1557, 0, +1113, 1691, 0, +1348, 1825, 0, +1544, 1959, 0, +1718, 2092, 0, +1880, 2225, 0, +2032, 2357, 0, +2180, 2490, 0, +2323, 2622, 0, +2463, 2755, 0, +2601, 2887, 0, +2737, 3019, 0, +2872, 3151, 0, +3007, 3283, 0, +3141, 3416, 0, +3274, 3548, 0, +3407, 3680, 0, +3540, 3812, 0, +3673, 3944, 0, +3805, 4076, 0, +3938, 4095, 0, +0, 640, 1160, +0, 705, 1157, +0, 779, 1152, +0, 863, 1146, +80, 955, 1137, +80, 1040, 1137, +80, 1134, 1137, +80, 1137, 1013, +80, 1137, 753, +0, 1278, 0, +478, 1416, 0, +900, 1553, 0, +1169, 1689, 0, +1382, 1823, 0, +1566, 1958, 0, +1733, 2091, 0, +1891, 2224, 0, +2040, 2357, 0, +2185, 2489, 0, +2327, 2622, 0, +2466, 2755, 0, +2603, 2887, 0, +2738, 3019, 0, +2873, 3151, 0, +3008, 3283, 0, +3141, 3416, 0, +3275, 3548, 0, +3408, 3680, 0, +3540, 3812, 0, +3673, 3944, 0, +3805, 4076, 0, +3938, 4095, 0, +0, 397, 1160, +0, 503, 1157, +0, 614, 1152, +0, 730, 1146, +80, 850, 1137, +430, 972, 1126, +430, 1079, 1126, +430, 1126, 1049, +430, 1126, 814, +214, 1270, 212, +719, 1410, 0, +1011, 1549, 0, +1233, 1685, 0, +1423, 1821, 0, +1594, 1956, 0, +1753, 2089, 0, +1904, 2223, 0, +2050, 2356, 0, +2193, 2489, 0, +2332, 2621, 0, +2470, 2754, 0, +2606, 2887, 0, +2741, 3019, 0, +2875, 3151, 0, +3009, 3283, 0, +3142, 3416, 0, +3275, 3548, 0, +3408, 3680, 0, +3541, 3812, 0, +3673, 3944, 0, +3805, 4076, 0, +3938, 4095, 0, +0, 0, 1160, +0, 0, 1157, +0, 214, 1152, +0, 455, 1146, +80, 655, 1137, +430, 831, 1126, +676, 994, 1110, +676, 1110, 1092, +676, 1110, 886, +661, 1258, 562, +919, 1402, 344, +1127, 1543, 0, +1308, 1681, 0, +1474, 1817, 0, +1629, 1953, 0, +1778, 2087, 0, +1922, 2221, 0, +2063, 2355, 0, +2202, 2488, 0, +2339, 2621, 0, +2475, 2754, 0, +2610, 2886, 0, +2744, 3018, 0, +2877, 3151, 0, +3010, 3283, 0, +3144, 3415, 0, +3276, 3548, 0, +3409, 3680, 0, +3541, 3812, 0, +3673, 3944, 0, +3805, 4076, 0, +3938, 4095, 0, +0, 0, 1160, +0, 0, 1157, +0, 0, 1152, +0, 0, 1146, +80, 81, 1137, +430, 529, 1126, +676, 805, 1110, +878, 1021, 1088, +878, 1088, 967, +938, 1242, 809, +1095, 1390, 695, +1246, 1534, 476, +1391, 1674, 0, +1533, 1813, 0, +1672, 1950, 0, +1810, 2085, 0, +1946, 2220, 0, +2081, 2353, 0, +2215, 2487, 0, +2348, 2620, 0, +2482, 2753, 0, +2615, 2886, 0, +2747, 3018, 0, +2880, 3151, 0, +3013, 3283, 0, +3145, 3415, 0, +3277, 3548, 0, +3410, 3680, 0, +3542, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3938, 4095, 0, +592, 0, 1160, +620, 0, 1157, +656, 0, 1152, +700, 0, 1146, +753, 80, 1137, +814, 430, 1126, +886, 676, 1110, +967, 878, 1088, +1056, 1056, 1056, +1154, 1220, 1010, +1258, 1374, 940, +1368, 1523, 826, +1483, 1666, 608, +1602, 1807, 0, +1724, 1945, 0, +1849, 2082, 0, +1975, 2217, 0, +2102, 2352, 0, +2231, 2486, 0, +2361, 2619, 0, +2491, 2752, 0, +2622, 2885, 0, +2752, 3018, 0, +2884, 3151, 0, +3015, 3283, 0, +3147, 3415, 0, +3279, 3548, 0, +3411, 3680, 0, +3543, 3812, 0, +3675, 3944, 0, +3807, 4076, 0, +3939, 4095, 0, +1051, 0, 1295, +1062, 0, 1292, +1075, 0, 1289, +1093, 0, 1284, +1116, 0, 1278, +1145, 212, 1270, +1181, 562, 1258, +1225, 809, 1242, +1220, 1010, 1154, +1220, 1099, 1010, +1374, 1357, 940, +1476, 1523, 826, +1569, 1666, 608, +1669, 1807, 0, +1776, 1945, 0, +1889, 2082, 0, +2006, 2217, 0, +2126, 2352, 0, +2249, 2486, 0, +2374, 2619, 0, +2501, 2752, 0, +2629, 2885, 0, +2758, 3018, 0, +2888, 3151, 0, +3018, 3283, 0, +3150, 3415, 0, +3281, 3548, 0, +3412, 3680, 0, +3544, 3812, 0, +3675, 3944, 0, +3807, 4076, 0, +3939, 4095, 0, +1330, 0, 1429, +1336, 0, 1427, +1343, 0, 1424, +1353, 0, 1421, +1367, 0, 1416, +1383, 0, 1410, +1402, 344, 1398, +1390, 695, 1343, +1374, 940, 1258, +1374, 940, 1069, +1374, 1150, 940, +1523, 1445, 826, +1663, 1666, 608, +1746, 1807, 0, +1838, 1945, 0, +1938, 2082, 0, +2044, 2217, 0, +2155, 2352, 0, +2272, 2486, 0, +2392, 2619, 0, +2514, 2752, 0, +2639, 2885, 0, +2766, 3018, 0, +2894, 3151, 0, +3023, 3283, 0, +3153, 3415, 0, +3283, 3548, 0, +3414, 3680, 0, +3545, 3812, 0, +3676, 3944, 0, +3808, 4076, 0, +3940, 4095, 0, +1548, 0, 1563, +1552, 0, 1561, +1556, 0, 1559, +1557, 0, 1551, +1553, 0, 1535, +1549, 0, 1513, +1543, 0, 1482, +1534, 476, 1437, +1523, 826, 1368, +1523, 826, 1228, +1523, 826, 926, +1523, 1211, 826, +1666, 1541, 608, +1807, 1780, 0, +1909, 1945, 0, +1996, 2082, 0, +2090, 2217, 0, +2192, 2352, 0, +2301, 2486, 0, +2414, 2619, 0, +2532, 2752, 0, +2652, 2885, 0, +2776, 3018, 0, +2902, 3151, 0, +3029, 3283, 0, +3157, 3415, 0, +3286, 3548, 0, +3416, 3680, 0, +3547, 3812, 0, +3678, 3944, 0, +3809, 4076, 0, +3941, 4095, 0, +1696, 0, 1653, +1695, 0, 1647, +1693, 0, 1640, +1691, 0, 1631, +1689, 0, 1617, +1685, 0, 1599, +1681, 0, 1574, +1674, 0, 1537, +1666, 608, 1483, +1666, 608, 1378, +1666, 608, 1183, +1666, 609, 608, +1666, 1281, 608, +1807, 1644, 0, +1945, 1895, 0, +2063, 2082, 0, +2146, 2217, 0, +2237, 2352, 0, +2336, 2486, 0, +2442, 2619, 0, +2553, 2752, 0, +2669, 2885, 0, +2789, 3018, 0, +2911, 3151, 0, +3036, 3283, 0, +3163, 3415, 0, +3291, 3548, 0, +3420, 3680, 0, +3549, 3812, 0, +3680, 3944, 0, +3810, 4076, 0, +3941, 4095, 0, +1828, 0, 1738, +1828, 0, 1733, +1827, 0, 1727, +1825, 0, 1720, +1823, 0, 1709, +1821, 0, 1694, +1817, 0, 1673, +1813, 0, 1644, +1807, 0, 1602, +1807, 0, 1523, +1807, 0, 1391, +1807, 0, 1115, +1807, 438, 0, +1807, 1360, 0, +1945, 1754, 0, +2082, 2014, 0, +2211, 2217, 0, +2291, 2352, 0, +2380, 2486, 0, +2477, 2619, 0, +2581, 2752, 0, +2691, 2885, 0, +2805, 3018, 0, +2924, 3151, 0, +3046, 3283, 0, +3170, 3415, 0, +3296, 3548, 0, +3424, 3680, 0, +3552, 3812, 0, +3682, 3944, 0, +3812, 4076, 0, +3943, 4095, 0, +1961, 0, 1831, +1961, 0, 1828, +1960, 0, 1823, +1959, 0, 1817, +1958, 0, 1808, +1956, 0, 1796, +1953, 0, 1779, +1950, 0, 1757, +1945, 0, 1724, +1945, 0, 1665, +1945, 0, 1572, +1945, 0, 1407, +1945, 0, 1007, +1945, 37, 0, +1945, 1449, 0, +2082, 1868, 0, +2217, 2136, 0, +2352, 2349, 0, +2433, 2486, 0, +2520, 2619, 0, +2616, 2752, 0, +2718, 2885, 0, +2827, 3018, 0, +2941, 3151, 0, +3059, 3283, 0, +3180, 3415, 0, +3303, 3548, 0, +3429, 3680, 0, +3557, 3812, 0, +3685, 3944, 0, +3814, 4076, 0, +3945, 4095, 0, +2094, 0, 1932, +2093, 0, 1929, +2093, 0, 1926, +2092, 0, 1920, +2091, 0, 1913, +2089, 0, 1904, +2087, 0, 1891, +2085, 0, 1873, +2082, 0, 1849, +2082, 0, 1804, +2082, 0, 1738, +2082, 0, 1630, +2082, 0, 1428, +2082, 0, 800, +2082, 0, 0, +2082, 1545, 0, +2217, 1986, 0, +2352, 2261, 0, +2486, 2476, 0, +2572, 2619, 0, +2658, 2752, 0, +2752, 2885, 0, +2854, 3018, 0, +2962, 3151, 0, +3075, 3283, 0, +3192, 3415, 0, +3313, 3548, 0, +3437, 3680, 0, +3562, 3812, 0, +3689, 3944, 0, +3818, 4076, 0, +3947, 4095, 0, +2226, 0, 2039, +2226, 0, 2037, +2225, 0, 2034, +2225, 0, 2030, +2224, 0, 2025, +2223, 0, 2018, +2221, 0, 2008, +2220, 0, 1994, +2217, 0, 1975, +2217, 0, 1941, +2217, 0, 1894, +2217, 0, 1819, +2217, 0, 1697, +2217, 0, 1454, +2217, 0, 140, +2217, 0, 0, +2217, 1649, 0, +2352, 2107, 0, +2486, 2387, 0, +2619, 2604, 0, +2710, 2752, 0, +2795, 2885, 0, +2888, 3018, 0, +2989, 3151, 0, +3096, 3283, 0, +3209, 3415, 0, +3326, 3548, 0, +3446, 3680, 0, +3570, 3812, 0, +3695, 3944, 0, +3822, 4076, 0, +3950, 4095, 0, +2358, 0, 2152, +2358, 0, 2150, +2358, 0, 2148, +2357, 0, 2145, +2357, 0, 2141, +2356, 0, 2135, +2355, 0, 2127, +2353, 0, 2117, +2352, 0, 2102, +2352, 0, 2078, +2352, 0, 2042, +2352, 0, 1990, +2352, 0, 1910, +2352, 0, 1773, +2352, 0, 1487, +2352, 0, 0, +2352, 0, 0, +2352, 1758, 0, +2486, 2232, 0, +2619, 2515, 0, +2752, 2734, 0, +2845, 2885, 0, +2930, 3018, 0, +3023, 3151, 0, +3123, 3283, 0, +3230, 3415, 0, +3342, 3548, 0, +3459, 3680, 0, +3579, 3812, 0, +3702, 3944, 0, +3827, 4076, 0, +3954, 4095, 0, +2491, 0, 2269, +2491, 0, 2268, +2490, 0, 2266, +2490, 0, 2264, +2489, 0, 2260, +2489, 0, 2256, +2488, 0, 2250, +2487, 0, 2242, +2486, 0, 2231, +2486, 0, 2213, +2486, 0, 2187, +2486, 0, 2149, +2486, 0, 2094, +2486, 0, 2008, +2486, 0, 1859, +2486, 0, 1529, +2486, 0, 0, +2486, 0, 0, +2486, 1873, 0, +2619, 2357, 0, +2752, 2644, 0, +2885, 2864, 0, +2980, 3018, 0, +3064, 3151, 0, +3157, 3283, 0, +3257, 3415, 0, +3363, 3548, 0, +3475, 3680, 0, +3592, 3812, 0, +3712, 3944, 0, +3835, 4076, 0, +3960, 4095, 0, +2623, 0, 2390, +2623, 0, 2388, +2623, 0, 2387, +2622, 0, 2385, +2622, 0, 2383, +2621, 0, 2380, +2621, 0, 2375, +2620, 0, 2369, +2619, 0, 2361, +2619, 0, 2347, +2619, 0, 2328, +2619, 0, 2301, +2619, 0, 2262, +2619, 0, 2204, +2619, 0, 2113, +2619, 0, 1954, +2619, 0, 1578, +2619, 0, 0, +2619, 0, 0, +2619, 1991, 0, +2752, 2485, 0, +2885, 2773, 0, +3018, 2995, 0, +3115, 3151, 0, +3198, 3283, 0, +3290, 3415, 0, +3390, 3548, 0, +3496, 3680, 0, +3608, 3812, 0, +3725, 3944, 0, +3845, 4076, 0, +3967, 4095, 0, +2755, 0, 2513, +2755, 0, 2512, +2755, 0, 2511, +2755, 0, 2510, +2755, 0, 2508, +2754, 0, 2505, +2754, 0, 2502, +2753, 0, 2497, +2752, 0, 2491, +2752, 0, 2481, +2752, 0, 2467, +2752, 0, 2447, +2752, 0, 2419, +2752, 0, 2379, +2752, 0, 2319, +2752, 0, 2224, +2752, 0, 2056, +2752, 0, 1638, +2752, 0, 0, +2752, 0, 0, +2752, 2113, 0, +2885, 2613, 0, +3018, 2903, 0, +3151, 3126, 0, +3248, 3283, 0, +3331, 3415, 0, +3423, 3548, 0, +3523, 3680, 0, +3629, 3812, 0, +3741, 3944, 0, +3857, 4076, 0, +3977, 4095, 0, +2887, 0, 2638, +2887, 0, 2638, +2887, 0, 2637, +2887, 0, 2636, +2887, 0, 2635, +2887, 0, 2632, +2886, 0, 2630, +2886, 0, 2626, +2885, 0, 2622, +2885, 0, 2614, +2885, 0, 2603, +2885, 0, 2589, +2885, 0, 2569, +2885, 0, 2540, +2885, 0, 2499, +2885, 0, 2438, +2885, 0, 2340, +2885, 0, 2163, +2885, 0, 1706, +2885, 0, 0, +2885, 0, 0, +2885, 2237, 0, +3018, 2742, 0, +3151, 3034, 0, +3283, 3257, 0, +3381, 3415, 0, +3465, 3548, 0, +3556, 3680, 0, +3656, 3812, 0, +3762, 3944, 0, +3873, 4076, 0, +3989, 4095, 0, +3019, 0, 2765, +3019, 0, 2765, +3019, 0, 2764, +3019, 0, 2763, +3019, 0, 2762, +3019, 0, 2761, +3018, 0, 2759, +3018, 0, 2756, +3018, 0, 2752, +3018, 0, 2747, +3018, 0, 2739, +3018, 0, 2728, +3018, 0, 2714, +3018, 0, 2693, +3018, 0, 2664, +3018, 0, 2622, +3018, 0, 2559, +3018, 0, 2459, +3018, 0, 2276, +3018, 0, 1782, +3018, 0, 0, +3018, 0, 0, +3018, 2362, 0, +3151, 2873, 0, +3283, 3165, 0, +3415, 3388, 0, +3514, 3548, 0, +3597, 3680, 0, +3689, 3812, 0, +3788, 3944, 0, +3894, 4076, 0, +4006, 4095, 0, +3152, 0, 2893, +3152, 0, 2893, +3152, 0, 2893, +3151, 0, 2892, +3151, 0, 2891, +3151, 0, 2890, +3151, 0, 2889, +3151, 0, 2887, +3151, 0, 2884, +3151, 0, 2880, +3151, 0, 2874, +3151, 0, 2866, +3151, 0, 2855, +3151, 0, 2840, +3151, 0, 2819, +3151, 0, 2790, +3151, 0, 2747, +3151, 0, 2684, +3151, 0, 2581, +3151, 0, 2394, +3151, 0, 1869, +3151, 0, 0, +3151, 0, 0, +3151, 2490, 0, +3283, 3003, 0, +3415, 3296, 0, +3548, 3520, 0, +3647, 3680, 0, +3730, 3812, 0, +3822, 3944, 0, +3921, 4076, 0, +4027, 4095, 0, +3284, 0, 3022, +3283, 0, 3022, +3283, 0, 3022, +3283, 0, 3021, +3283, 0, 3021, +3283, 0, 3020, +3283, 0, 3019, +3283, 0, 3017, +3283, 0, 3015, +3283, 0, 3012, +3283, 0, 3008, +3283, 0, 3002, +3283, 0, 2994, +3283, 0, 2983, +3283, 0, 2968, +3283, 0, 2947, +3283, 0, 2917, +3283, 0, 2874, +3283, 0, 2809, +3283, 0, 2705, +3283, 0, 2513, +3283, 0, 1962, +3283, 0, 0, +3283, 0, 0, +3283, 2619, 0, +3415, 3135, 0, +3548, 3428, 0, +3680, 3652, 0, +3780, 3812, 0, +3863, 3944, 0, +3954, 4076, 0, +4053, 4095, 0, +3416, 0, 3152, +3416, 0, 3152, +3416, 0, 3152, +3416, 0, 3151, +3416, 0, 3151, +3416, 0, 3151, +3415, 0, 3150, +3415, 0, 3149, +3415, 0, 3147, +3415, 0, 3145, +3415, 0, 3141, +3415, 0, 3137, +3415, 0, 3131, +3415, 0, 3123, +3415, 0, 3112, +3415, 0, 3097, +3415, 0, 3076, +3415, 0, 3046, +3415, 0, 3002, +3415, 0, 2937, +3415, 0, 2832, +3415, 0, 2637, +3415, 0, 2068, +3415, 0, 0, +3415, 0, 0, +3415, 2748, 0, +3548, 3266, 0, +3680, 3560, 0, +3812, 3784, 0, +3912, 3944, 0, +3995, 4076, 0, +4086, 4095, 0, +3548, 0, 3283, +3548, 0, 3283, +3548, 0, 3282, +3548, 0, 3282, +3548, 0, 3282, +3548, 0, 3281, +3548, 0, 3281, +3548, 0, 3280, +3548, 0, 3279, +3548, 0, 3277, +3548, 0, 3275, +3548, 0, 3271, +3548, 0, 3267, +3548, 0, 3261, +3548, 0, 3253, +3548, 0, 3242, +3548, 0, 3226, +3548, 0, 3205, +3548, 0, 3175, +3548, 0, 3132, +3548, 0, 3066, +3548, 0, 2960, +3548, 0, 2763, +3548, 0, 2174, +3548, 0, 0, +3548, 0, 0, +3548, 2878, 0, +3680, 3397, 0, +3812, 3691, 0, +3944, 3915, 0, +4044, 4076, 0, +4095, 4095, 0, +3680, 0, 3414, +3680, 0, 3414, +3680, 0, 3414, +3680, 0, 3413, +3680, 0, 3413, +3680, 0, 3413, +3680, 0, 3412, +3680, 0, 3412, +3680, 0, 3411, +3680, 0, 3409, +3680, 0, 3408, +3680, 0, 3405, +3680, 0, 3402, +3680, 0, 3397, +3680, 0, 3392, +3680, 0, 3383, +3680, 0, 3372, +3680, 0, 3357, +3680, 0, 3336, +3680, 0, 3305, +3680, 0, 3261, +3680, 0, 3195, +3680, 0, 3089, +3680, 0, 2890, +3680, 0, 2291, +3680, 0, 0, +3680, 0, 0, +3680, 3009, 0, +3812, 3529, 0, +3944, 3823, 0, +4076, 4047, 0, +4095, 4095, 0, +3812, 0, 3545, +3812, 0, 3545, +3812, 0, 3545, +3812, 0, 3545, +3812, 0, 3544, +3812, 0, 3544, +3812, 0, 3544, +3812, 0, 3543, +3812, 0, 3543, +3812, 0, 3542, +3812, 0, 3540, +3812, 0, 3538, +3812, 0, 3536, +3812, 0, 3533, +3812, 0, 3528, +3812, 0, 3522, +3812, 0, 3514, +3812, 0, 3503, +3812, 0, 3488, +3812, 0, 3466, +3812, 0, 3436, +3812, 0, 3392, +3812, 0, 3326, +3812, 0, 3218, +3812, 0, 3019, +3812, 0, 2408, +3812, 0, 0, +3812, 0, 0, +3812, 3140, 0, +3944, 3661, 0, +4076, 3955, 0, +4095, 4095, 0, +3944, 0, 3676, +3944, 0, 3676, +3944, 0, 3676, +3944, 0, 3676, +3944, 0, 3676, +3944, 0, 3676, +3944, 0, 3676, +3944, 0, 3675, +3944, 0, 3675, +3944, 0, 3674, +3944, 0, 3673, +3944, 0, 3671, +3944, 0, 3670, +3944, 0, 3667, +3944, 0, 3664, +3944, 0, 3659, +3944, 0, 3653, +3944, 0, 3645, +3944, 0, 3634, +3944, 0, 3619, +3944, 0, 3597, +3944, 0, 3567, +3944, 0, 3523, +3944, 0, 3456, +3944, 0, 3349, +3944, 0, 3147, +3944, 0, 2528, +3944, 0, 0, +3944, 0, 0, +3944, 3271, 0, +4076, 3792, 0, +4095, 4087, 0, +4076, 0, 3808, +4076, 0, 3808, +4076, 0, 3808, +4076, 0, 3808, +4076, 0, 3808, +4076, 0, 3808, +4076, 0, 3807, +4076, 0, 3807, +4076, 0, 3807, +4076, 0, 3806, +4076, 0, 3805, +4076, 0, 3804, +4076, 0, 3803, +4076, 0, 3801, +4076, 0, 3798, +4076, 0, 3795, +4076, 0, 3791, +4076, 0, 3785, +4076, 0, 3777, +4076, 0, 3765, +4076, 0, 3750, +4076, 0, 3728, +4076, 0, 3698, +4076, 0, 3654, +4076, 0, 3587, +4076, 0, 3479, +4076, 0, 3277, +4076, 0, 2650, +4076, 0, 0, +4076, 0, 0, +4076, 3403, 0, +4095, 3925, 0, +4095, 0, 3940, +4095, 0, 3940, +4095, 0, 3940, +4095, 0, 3940, +4095, 0, 3940, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3938, +4095, 0, 3938, +4095, 0, 3937, +4095, 0, 3936, +4095, 0, 3935, +4095, 0, 3933, +4095, 0, 3930, +4095, 0, 3927, +4095, 0, 3923, +4095, 0, 3917, +4095, 0, 3908, +4095, 0, 3897, +4095, 0, 3881, +4095, 0, 3860, +4095, 0, 3830, +4095, 0, 3786, +4095, 0, 3719, +4095, 0, 3611, +4095, 0, 3408, +4095, 0, 2778, +4095, 0, 0, +4095, 0, 0, +4095, 3534, 0, +0, 1046, 1295, +0, 1069, 1295, +0, 1099, 1295, +0, 1135, 1295, +0, 1181, 1295, +0, 1234, 1295, +0, 1295, 1292, +0, 1295, 1204, +0, 1295, 1051, +0, 1295, 702, +0, 1429, 0, +0, 1563, 0, +580, 1696, 0, +1106, 1828, 0, +1402, 1961, 0, +1626, 2094, 0, +1817, 2226, 0, +1989, 2358, 0, +2149, 2491, 0, +2300, 2623, 0, +2446, 2755, 0, +2589, 2887, 0, +2728, 3019, 0, +2866, 3152, 0, +3002, 3284, 0, +3137, 3416, 0, +3271, 3548, 0, +3405, 3680, 0, +3538, 3812, 0, +3671, 3944, 0, +3804, 4076, 0, +3937, 4095, 0, +0, 1021, 1295, +0, 1050, 1292, +0, 1081, 1292, +0, 1119, 1292, +0, 1166, 1292, +0, 1221, 1292, +0, 1286, 1292, +0, 1292, 1211, +0, 1292, 1062, +0, 1292, 724, +0, 1427, 0, +0, 1561, 0, +653, 1695, 0, +1131, 1828, 0, +1415, 1961, 0, +1635, 2093, 0, +1823, 2226, 0, +1993, 2358, 0, +2151, 2491, 0, +2302, 2623, 0, +2448, 2755, 0, +2589, 2887, 0, +2729, 3019, 0, +2866, 3152, 0, +3002, 3283, 0, +3137, 3416, 0, +3272, 3548, 0, +3405, 3680, 0, +3538, 3812, 0, +3671, 3944, 0, +3804, 4076, 0, +3937, 4095, 0, +0, 985, 1295, +0, 1017, 1292, +0, 1056, 1289, +0, 1096, 1289, +0, 1145, 1289, +0, 1203, 1289, +0, 1271, 1289, +0, 1289, 1221, +0, 1289, 1075, +0, 1289, 753, +0, 1424, 0, +0, 1559, 0, +736, 1693, 0, +1161, 1827, 0, +1431, 1960, 0, +1645, 2093, 0, +1829, 2225, 0, +1997, 2358, 0, +2154, 2490, 0, +2304, 2623, 0, +2449, 2755, 0, +2591, 2887, 0, +2729, 3019, 0, +2867, 3152, 0, +3002, 3283, 0, +3138, 3416, 0, +3272, 3548, 0, +3405, 3680, 0, +3539, 3812, 0, +3672, 3944, 0, +3804, 4076, 0, +3937, 4095, 0, +0, 934, 1295, +0, 968, 1292, +0, 1012, 1289, +0, 1064, 1284, +0, 1116, 1284, +0, 1177, 1284, +0, 1249, 1284, +0, 1284, 1235, +0, 1284, 1093, +0, 1284, 788, +0, 1421, 0, +0, 1557, 0, +827, 1691, 0, +1199, 1825, 0, +1453, 1959, 0, +1658, 2092, 0, +1839, 2225, 0, +2004, 2357, 0, +2159, 2490, 0, +2308, 2622, 0, +2452, 2755, 0, +2592, 2887, 0, +2731, 3019, 0, +2868, 3151, 0, +3003, 3283, 0, +3138, 3416, 0, +3272, 3548, 0, +3406, 3680, 0, +3539, 3812, 0, +3672, 3944, 0, +3805, 4076, 0, +3937, 4095, 0, +0, 853, 1295, +0, 894, 1292, +0, 945, 1289, +0, 1005, 1284, +0, 1074, 1278, +0, 1141, 1278, +0, 1218, 1278, +0, 1278, 1251, +0, 1278, 1116, +0, 1278, 832, +0, 1416, 0, +275, 1553, 0, +926, 1689, 0, +1245, 1823, 0, +1480, 1958, 0, +1676, 2091, 0, +1850, 2224, 0, +2012, 2357, 0, +2165, 2489, 0, +2312, 2622, 0, +2455, 2755, 0, +2595, 2887, 0, +2732, 3019, 0, +2869, 3151, 0, +3004, 3283, 0, +3139, 3416, 0, +3273, 3548, 0, +3406, 3680, 0, +3539, 3812, 0, +3672, 3944, 0, +3805, 4076, 0, +3937, 4095, 0, +0, 717, 1295, +0, 772, 1292, +0, 837, 1289, +0, 911, 1284, +0, 995, 1278, +212, 1087, 1270, +212, 1172, 1270, +212, 1266, 1270, +212, 1270, 1145, +212, 1270, 884, +0, 1410, 47, +611, 1549, 0, +1031, 1685, 0, +1301, 1821, 0, +1514, 1956, 0, +1698, 2089, 0, +1865, 2223, 0, +2022, 2356, 0, +2172, 2489, 0, +2317, 2621, 0, +2459, 2754, 0, +2598, 2887, 0, +2735, 3019, 0, +2871, 3151, 0, +3005, 3283, 0, +3140, 3416, 0, +3273, 3548, 0, +3407, 3680, 0, +3540, 3812, 0, +3672, 3944, 0, +3805, 4076, 0, +3937, 4095, 0, +0, 431, 1295, +0, 529, 1292, +0, 635, 1289, +0, 746, 1284, +0, 862, 1278, +212, 982, 1270, +562, 1104, 1258, +562, 1211, 1258, +562, 1258, 1181, +562, 1258, 946, +345, 1402, 344, +852, 1543, 0, +1142, 1681, 0, +1366, 1817, 0, +1555, 1953, 0, +1726, 2087, 0, +1885, 2221, 0, +2037, 2355, 0, +2183, 2488, 0, +2325, 2621, 0, +2464, 2754, 0, +2602, 2886, 0, +2738, 3018, 0, +2873, 3151, 0, +3007, 3283, 0, +3141, 3415, 0, +3274, 3548, 0, +3407, 3680, 0, +3540, 3812, 0, +3673, 3944, 0, +3805, 4076, 0, +3938, 4095, 0, +0, 0, 1295, +0, 0, 1292, +0, 9, 1289, +0, 346, 1284, +0, 587, 1278, +212, 787, 1270, +562, 963, 1258, +809, 1126, 1242, +809, 1242, 1225, +809, 1242, 1018, +793, 1390, 695, +1051, 1534, 476, +1258, 1674, 0, +1440, 1813, 0, +1606, 1950, 0, +1761, 2085, 0, +1910, 2220, 0, +2054, 2353, 0, +2196, 2487, 0, +2334, 2620, 0, +2471, 2753, 0, +2607, 2886, 0, +2742, 3018, 0, +2876, 3151, 0, +3009, 3283, 0, +3143, 3415, 0, +3276, 3548, 0, +3408, 3680, 0, +3541, 3812, 0, +3673, 3944, 0, +3805, 4076, 0, +3938, 4095, 0, +0, 0, 1295, +0, 0, 1292, +0, 0, 1289, +0, 0, 1284, +0, 0, 1278, +212, 214, 1270, +562, 661, 1258, +809, 938, 1242, +1010, 1154, 1220, +1010, 1220, 1099, +1069, 1374, 940, +1228, 1523, 826, +1378, 1666, 608, +1523, 1807, 0, +1665, 1945, 0, +1804, 2082, 0, +1942, 2217, 0, +2078, 2352, 0, +2213, 2486, 0, +2347, 2619, 0, +2481, 2752, 0, +2614, 2885, 0, +2747, 3018, 0, +2880, 3151, 0, +3012, 3283, 0, +3145, 3415, 0, +3277, 3548, 0, +3409, 3680, 0, +3542, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3938, 4095, 0, +702, 0, 1295, +724, 0, 1292, +753, 0, 1289, +788, 0, 1284, +832, 0, 1278, +884, 212, 1270, +946, 562, 1258, +1018, 809, 1242, +1099, 1010, 1220, +1188, 1188, 1188, +1286, 1352, 1142, +1390, 1507, 1073, +1500, 1654, 959, +1615, 1798, 740, +1734, 1939, 0, +1856, 2077, 0, +1981, 2214, 0, +2107, 2349, 0, +2235, 2484, 0, +2363, 2618, 0, +2493, 2751, 0, +2623, 2885, 0, +2754, 3017, 0, +2885, 3150, 0, +3016, 3282, 0, +3147, 3415, 0, +3279, 3547, 0, +3411, 3680, 0, +3543, 3812, 0, +3675, 3944, 0, +3807, 4076, 0, +3939, 4095, 0, +1174, 0, 1429, +1182, 0, 1427, +1193, 0, 1424, +1207, 0, 1421, +1225, 0, 1416, +1248, 0, 1410, +1277, 344, 1402, +1313, 695, 1390, +1357, 940, 1374, +1352, 1142, 1286, +1352, 1231, 1142, +1507, 1489, 1073, +1608, 1654, 959, +1701, 1798, 740, +1801, 1939, 0, +1908, 2077, 0, +2021, 2214, 0, +2138, 2349, 0, +2258, 2484, 0, +2381, 2618, 0, +2506, 2751, 0, +2633, 2885, 0, +2761, 3017, 0, +2891, 3150, 0, +3020, 3282, 0, +3151, 3415, 0, +3282, 3547, 0, +3413, 3680, 0, +3544, 3812, 0, +3676, 3944, 0, +3808, 4076, 0, +3940, 4095, 0, +1458, 0, 1563, +1463, 0, 1561, +1468, 0, 1559, +1476, 0, 1557, +1486, 0, 1553, +1499, 0, 1549, +1516, 0, 1543, +1534, 476, 1531, +1523, 826, 1476, +1507, 1073, 1390, +1507, 1073, 1202, +1507, 1282, 1073, +1654, 1577, 959, +1795, 1798, 740, +1878, 1939, 0, +1970, 2077, 0, +2070, 2214, 0, +2176, 2349, 0, +2288, 2484, 0, +2404, 2618, 0, +2524, 2751, 0, +2647, 2885, 0, +2771, 3017, 0, +2898, 3150, 0, +3026, 3282, 0, +3155, 3415, 0, +3285, 3547, 0, +3415, 3680, 0, +3546, 3812, 0, +3677, 3944, 0, +3808, 4076, 0, +3940, 4095, 0, +1677, 0, 1696, +1680, 0, 1695, +1683, 0, 1693, +1688, 0, 1691, +1689, 0, 1683, +1685, 0, 1667, +1681, 0, 1645, +1674, 0, 1614, +1666, 608, 1569, +1654, 959, 1500, +1654, 959, 1360, +1654, 959, 1056, +1654, 1343, 959, +1798, 1673, 740, +1939, 1912, 0, +2041, 2077, 0, +2128, 2214, 0, +2223, 2349, 0, +2325, 2484, 0, +2432, 2618, 0, +2546, 2751, 0, +2664, 2885, 0, +2784, 3017, 0, +2908, 3150, 0, +3033, 3282, 0, +3161, 3415, 0, +3289, 3547, 0, +3418, 3680, 0, +3548, 3812, 0, +3679, 3944, 0, +3810, 4076, 0, +3941, 4095, 0, +1828, 0, 1789, +1828, 0, 1785, +1827, 0, 1779, +1825, 0, 1772, +1823, 0, 1763, +1821, 0, 1750, +1817, 0, 1732, +1813, 0, 1706, +1807, 0, 1669, +1798, 740, 1615, +1798, 740, 1510, +1798, 740, 1315, +1798, 740, 742, +1798, 1413, 740, +1939, 1776, 0, +2077, 2027, 0, +2195, 2214, 0, +2278, 2349, 0, +2369, 2484, 0, +2469, 2618, 0, +2574, 2751, 0, +2685, 2885, 0, +2801, 3017, 0, +2921, 3150, 0, +3043, 3282, 0, +3168, 3415, 0, +3295, 3547, 0, +3423, 3680, 0, +3552, 3812, 0, +3681, 3944, 0, +3812, 4076, 0, +3943, 4095, 0, +1961, 0, 1873, +1961, 0, 1870, +1960, 0, 1865, +1959, 0, 1860, +1958, 0, 1852, +1956, 0, 1841, +1953, 0, 1826, +1950, 0, 1806, +1945, 0, 1776, +1939, 0, 1734, +1939, 0, 1655, +1939, 0, 1523, +1939, 0, 1248, +1939, 573, 0, +1939, 1492, 0, +2077, 1886, 0, +2214, 2146, 0, +2343, 2349, 0, +2423, 2484, 0, +2512, 2618, 0, +2609, 2751, 0, +2713, 2885, 0, +2823, 3017, 0, +2938, 3150, 0, +3056, 3282, 0, +3178, 3415, 0, +3302, 3547, 0, +3428, 3680, 0, +3556, 3812, 0, +3685, 3944, 0, +3814, 4076, 0, +3944, 4095, 0, +2094, 0, 1966, +2093, 0, 1963, +2093, 0, 1960, +2092, 0, 1955, +2091, 0, 1949, +2089, 0, 1940, +2087, 0, 1928, +2085, 0, 1912, +2082, 0, 1889, +2077, 0, 1856, +2077, 0, 1797, +2077, 0, 1704, +2077, 0, 1539, +2077, 0, 1138, +2077, 173, 0, +2077, 1581, 0, +2214, 2000, 0, +2349, 2268, 0, +2484, 2481, 0, +2565, 2618, 0, +2652, 2751, 0, +2748, 2885, 0, +2850, 3017, 0, +2959, 3150, 0, +3073, 3282, 0, +3191, 3415, 0, +3312, 3547, 0, +3436, 3680, 0, +3562, 3812, 0, +3689, 3944, 0, +3817, 4076, 0, +3947, 4095, 0, +2226, 0, 2066, +2226, 0, 2064, +2225, 0, 2061, +2225, 0, 2058, +2224, 0, 2053, +2223, 0, 2046, +2221, 0, 2036, +2220, 0, 2023, +2217, 0, 2006, +2214, 0, 1981, +2214, 0, 1936, +2214, 0, 1870, +2214, 0, 1762, +2214, 0, 1560, +2214, 0, 932, +2214, 0, 0, +2214, 1677, 0, +2349, 2118, 0, +2484, 2393, 0, +2618, 2608, 0, +2704, 2751, 0, +2790, 2885, 0, +2885, 3017, 0, +2986, 3150, 0, +3094, 3282, 0, +3207, 3415, 0, +3325, 3547, 0, +3445, 3680, 0, +3569, 3812, 0, +3694, 3944, 0, +3821, 4076, 0, +3950, 4095, 0, +2358, 0, 2173, +2358, 0, 2171, +2358, 0, 2169, +2357, 0, 2166, +2357, 0, 2162, +2356, 0, 2157, +2355, 0, 2150, +2353, 0, 2140, +2352, 0, 2126, +2349, 0, 2107, +2349, 0, 2074, +2349, 0, 2025, +2349, 0, 1951, +2349, 0, 1829, +2349, 0, 1586, +2349, 0, 275, +2349, 0, 0, +2349, 1781, 0, +2484, 2240, 0, +2618, 2519, 0, +2751, 2737, 0, +2842, 2885, 0, +2927, 3017, 0, +3020, 3150, 0, +3121, 3282, 0, +3228, 3415, 0, +3341, 3547, 0, +3458, 3680, 0, +3579, 3812, 0, +3702, 3944, 0, +3827, 4076, 0, +3954, 4095, 0, +2491, 0, 2285, +2491, 0, 2284, +2490, 0, 2283, +2490, 0, 2280, +2489, 0, 2277, +2489, 0, 2273, +2488, 0, 2267, +2487, 0, 2260, +2486, 0, 2249, +2484, 0, 2235, +2484, 0, 2210, +2484, 0, 2174, +2484, 0, 2122, +2484, 0, 2042, +2484, 0, 1906, +2484, 0, 1620, +2484, 0, 0, +2484, 0, 0, +2484, 1891, 0, +2618, 2363, 0, +2751, 2647, 0, +2885, 2866, 0, +2977, 3017, 0, +3062, 3150, 0, +3155, 3282, 0, +3255, 3415, 0, +3362, 3547, 0, +3475, 3680, 0, +3591, 3812, 0, +3711, 3944, 0, +3834, 4076, 0, +3960, 4095, 0, +2623, 0, 2402, +2623, 0, 2401, +2623, 0, 2400, +2622, 0, 2398, +2622, 0, 2396, +2621, 0, 2393, +2621, 0, 2388, +2620, 0, 2382, +2619, 0, 2374, +2618, 0, 2363, +2618, 0, 2345, +2618, 0, 2319, +2618, 0, 2281, +2618, 0, 2226, +2618, 0, 2140, +2618, 0, 1991, +2618, 0, 1661, +2618, 0, 0, +2618, 0, 0, +2618, 2005, 0, +2751, 2490, 0, +2885, 2776, 0, +3017, 2996, 0, +3112, 3150, 0, +3196, 3282, 0, +3289, 3415, 0, +3389, 3547, 0, +3495, 3680, 0, +3607, 3812, 0, +3724, 3944, 0, +3844, 4076, 0, +3967, 4095, 0, +2755, 0, 2523, +2755, 0, 2522, +2755, 0, 2521, +2755, 0, 2520, +2755, 0, 2517, +2754, 0, 2515, +2754, 0, 2512, +2753, 0, 2507, +2752, 0, 2501, +2751, 0, 2493, +2751, 0, 2479, +2751, 0, 2460, +2751, 0, 2433, +2751, 0, 2394, +2751, 0, 2336, +2751, 0, 2245, +2751, 0, 2086, +2751, 0, 1711, +2751, 0, 0, +2751, 0, 0, +2751, 2123, 0, +2885, 2617, 0, +3017, 2905, 0, +3150, 3127, 0, +3247, 3282, 0, +3330, 3415, 0, +3422, 3547, 0, +3522, 3680, 0, +3629, 3812, 0, +3740, 3944, 0, +3856, 4076, 0, +3977, 4095, 0, +2887, 0, 2646, +2887, 0, 2645, +2887, 0, 2644, +2887, 0, 2643, +2887, 0, 2642, +2887, 0, 2640, +2886, 0, 2637, +2886, 0, 2634, +2885, 0, 2629, +2885, 0, 2623, +2885, 0, 2613, +2885, 0, 2599, +2885, 0, 2579, +2885, 0, 2551, +2885, 0, 2511, +2885, 0, 2451, +2885, 0, 2356, +2885, 0, 2188, +2885, 0, 1769, +2885, 0, 0, +2885, 0, 0, +2885, 2245, 0, +3017, 2745, 0, +3150, 3036, 0, +3282, 3257, 0, +3380, 3415, 0, +3464, 3547, 0, +3556, 3680, 0, +3655, 3812, 0, +3761, 3944, 0, +3873, 4076, 0, +3989, 4095, 0, +3019, 0, 2771, +3019, 0, 2770, +3019, 0, 2770, +3019, 0, 2769, +3019, 0, 2768, +3019, 0, 2766, +3018, 0, 2764, +3018, 0, 2762, +3018, 0, 2758, +3017, 0, 2754, +3017, 0, 2746, +3017, 0, 2735, +3017, 0, 2721, +3017, 0, 2701, +3017, 0, 2672, +3017, 0, 2631, +3017, 0, 2570, +3017, 0, 2471, +3017, 0, 2294, +3017, 0, 1837, +3017, 0, 0, +3017, 0, 0, +3017, 2369, 0, +3150, 2875, 0, +3282, 3166, 0, +3415, 3389, 0, +3513, 3547, 0, +3597, 3680, 0, +3689, 3812, 0, +3788, 3944, 0, +3894, 4076, 0, +4005, 4095, 0, +3152, 0, 2898, +3152, 0, 2897, +3152, 0, 2897, +3151, 0, 2896, +3151, 0, 2895, +3151, 0, 2895, +3151, 0, 2893, +3151, 0, 2891, +3151, 0, 2888, +3150, 0, 2885, +3150, 0, 2879, +3150, 0, 2871, +3150, 0, 2860, +3150, 0, 2846, +3150, 0, 2825, +3150, 0, 2796, +3150, 0, 2754, +3150, 0, 2691, +3150, 0, 2591, +3150, 0, 2408, +3150, 0, 1915, +3150, 0, 0, +3150, 0, 0, +3150, 2495, 0, +3282, 3005, 0, +3415, 3297, 0, +3547, 3520, 0, +3646, 3680, 0, +3729, 3812, 0, +3821, 3944, 0, +3921, 4076, 0, +4026, 4095, 0, +3284, 0, 3025, +3283, 0, 3025, +3283, 0, 3025, +3283, 0, 3025, +3283, 0, 3024, +3283, 0, 3023, +3283, 0, 3022, +3283, 0, 3021, +3283, 0, 3018, +3282, 0, 3016, +3282, 0, 3012, +3282, 0, 3006, +3282, 0, 2998, +3282, 0, 2987, +3282, 0, 2972, +3282, 0, 2951, +3282, 0, 2922, +3282, 0, 2879, +3282, 0, 2815, +3282, 0, 2713, +3282, 0, 2524, +3282, 0, 1999, +3282, 0, 0, +3282, 0, 0, +3282, 2622, 0, +3415, 3136, 0, +3547, 3429, 0, +3680, 3652, 0, +3779, 3812, 0, +3862, 3944, 0, +3953, 4076, 0, +4053, 4095, 0, +3416, 0, 3155, +3416, 0, 3154, +3416, 0, 3154, +3416, 0, 3154, +3416, 0, 3154, +3416, 0, 3153, +3415, 0, 3152, +3415, 0, 3151, +3415, 0, 3150, +3415, 0, 3147, +3415, 0, 3144, +3415, 0, 3140, +3415, 0, 3134, +3415, 0, 3126, +3415, 0, 3115, +3415, 0, 3100, +3415, 0, 3079, +3415, 0, 3049, +3415, 0, 3006, +3415, 0, 2942, +3415, 0, 2837, +3415, 0, 2646, +3415, 0, 2098, +3415, 0, 0, +3415, 0, 0, +3415, 2751, 0, +3547, 3267, 0, +3680, 3560, 0, +3812, 3784, 0, +3912, 3944, 0, +3995, 4076, 0, +4086, 4095, 0, +3548, 0, 3285, +3548, 0, 3284, +3548, 0, 3284, +3548, 0, 3284, +3548, 0, 3284, +3548, 0, 3283, +3548, 0, 3283, +3548, 0, 3282, +3548, 0, 3281, +3547, 0, 3279, +3547, 0, 3277, +3547, 0, 3274, +3547, 0, 3269, +3547, 0, 3263, +3547, 0, 3255, +3547, 0, 3244, +3547, 0, 3229, +3547, 0, 3208, +3547, 0, 3178, +3547, 0, 3135, +3547, 0, 3069, +3547, 0, 2964, +3547, 0, 2770, +3547, 0, 2198, +3547, 0, 0, +3547, 0, 0, +3547, 2880, 0, +3680, 3398, 0, +3812, 3692, 0, +3944, 3916, 0, +4044, 4076, 0, +4095, 4095, 0, +3680, 0, 3415, +3680, 0, 3415, +3680, 0, 3415, +3680, 0, 3415, +3680, 0, 3414, +3680, 0, 3414, +3680, 0, 3414, +3680, 0, 3413, +3680, 0, 3412, +3680, 0, 3411, +3680, 0, 3409, +3680, 0, 3407, +3680, 0, 3404, +3680, 0, 3399, +3680, 0, 3393, +3680, 0, 3385, +3680, 0, 3374, +3680, 0, 3359, +3680, 0, 3337, +3680, 0, 3307, +3680, 0, 3264, +3680, 0, 3198, +3680, 0, 3092, +3680, 0, 2895, +3680, 0, 2310, +3680, 0, 0, +3680, 0, 0, +3680, 3011, 0, +3812, 3530, 0, +3944, 3824, 0, +4076, 4047, 0, +4095, 4095, 0, +3812, 0, 3546, +3812, 0, 3546, +3812, 0, 3546, +3812, 0, 3545, +3812, 0, 3545, +3812, 0, 3545, +3812, 0, 3545, +3812, 0, 3544, +3812, 0, 3544, +3812, 0, 3543, +3812, 0, 3541, +3812, 0, 3540, +3812, 0, 3537, +3812, 0, 3534, +3812, 0, 3530, +3812, 0, 3523, +3812, 0, 3515, +3812, 0, 3504, +3812, 0, 3489, +3812, 0, 3468, +3812, 0, 3437, +3812, 0, 3394, +3812, 0, 3328, +3812, 0, 3221, +3812, 0, 3023, +3812, 0, 2422, +3812, 0, 0, +3812, 0, 0, +3812, 3141, 0, +3944, 3661, 0, +4076, 3955, 0, +4095, 4095, 0, +3944, 0, 3677, +3944, 0, 3677, +3944, 0, 3677, +3944, 0, 3677, +3944, 0, 3677, +3944, 0, 3676, +3944, 0, 3676, +3944, 0, 3676, +3944, 0, 3675, +3944, 0, 3675, +3944, 0, 3674, +3944, 0, 3673, +3944, 0, 3671, +3944, 0, 3668, +3944, 0, 3665, +3944, 0, 3661, +3944, 0, 3654, +3944, 0, 3646, +3944, 0, 3635, +3944, 0, 3620, +3944, 0, 3598, +3944, 0, 3568, +3944, 0, 3524, +3944, 0, 3458, +3944, 0, 3351, +3944, 0, 3151, +3944, 0, 2539, +3944, 0, 0, +3944, 0, 0, +3944, 3272, 0, +4076, 3793, 0, +4095, 4088, 0, +4076, 0, 3808, +4076, 0, 3808, +4076, 0, 3808, +4076, 0, 3808, +4076, 0, 3808, +4076, 0, 3808, +4076, 0, 3808, +4076, 0, 3808, +4076, 0, 3807, +4076, 0, 3807, +4076, 0, 3806, +4076, 0, 3805, +4076, 0, 3803, +4076, 0, 3802, +4076, 0, 3799, +4076, 0, 3796, +4076, 0, 3791, +4076, 0, 3785, +4076, 0, 3777, +4076, 0, 3766, +4076, 0, 3751, +4076, 0, 3729, +4076, 0, 3699, +4076, 0, 3655, +4076, 0, 3588, +4076, 0, 3480, +4076, 0, 3279, +4076, 0, 2659, +4076, 0, 0, +4076, 0, 0, +4076, 3403, 0, +4095, 3925, 0, +4095, 0, 3940, +4095, 0, 3940, +4095, 0, 3940, +4095, 0, 3940, +4095, 0, 3940, +4095, 0, 3940, +4095, 0, 3940, +4095, 0, 3940, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3938, +4095, 0, 3937, +4095, 0, 3937, +4095, 0, 3935, +4095, 0, 3933, +4095, 0, 3931, +4095, 0, 3927, +4095, 0, 3923, +4095, 0, 3917, +4095, 0, 3909, +4095, 0, 3898, +4095, 0, 3882, +4095, 0, 3861, +4095, 0, 3830, +4095, 0, 3786, +4095, 0, 3720, +4095, 0, 3612, +4095, 0, 3410, +4095, 0, 2785, +4095, 0, 0, +4095, 0, 0, +4095, 3535, 0, +0, 1174, 1429, +0, 1192, 1429, +0, 1215, 1429, +0, 1244, 1429, +0, 1280, 1429, +0, 1323, 1429, +0, 1376, 1429, +0, 1429, 1419, +0, 1429, 1330, +0, 1429, 1174, +0, 1429, 816, +0, 1563, 0, +0, 1696, 0, +650, 1828, 0, +1220, 1961, 0, +1524, 2094, 0, +1753, 2226, 0, +1946, 2358, 0, +2119, 2491, 0, +2278, 2623, 0, +2431, 2755, 0, +2577, 2887, 0, +2720, 3019, 0, +2860, 3152, 0, +2997, 3284, 0, +3134, 3416, 0, +3269, 3548, 0, +3403, 3680, 0, +3537, 3812, 0, +3670, 3944, 0, +3803, 4076, 0, +3937, 4095, 0, +0, 1156, 1429, +0, 1178, 1427, +0, 1201, 1427, +0, 1231, 1427, +0, 1267, 1427, +0, 1313, 1427, +0, 1366, 1427, +0, 1427, 1424, +0, 1427, 1336, +0, 1427, 1182, +0, 1427, 833, +0, 1561, 0, +0, 1695, 0, +713, 1828, 0, +1238, 1961, 0, +1534, 2093, 0, +1759, 2226, 0, +1950, 2358, 0, +2121, 2491, 0, +2281, 2623, 0, +2432, 2755, 0, +2578, 2887, 0, +2720, 3019, 0, +2860, 3152, 0, +2998, 3283, 0, +3134, 3416, 0, +3269, 3548, 0, +3403, 3680, 0, +3537, 3812, 0, +3671, 3944, 0, +3803, 4076, 0, +3937, 4095, 0, +0, 1130, 1429, +0, 1153, 1427, +0, 1182, 1424, +0, 1213, 1424, +0, 1251, 1424, +0, 1298, 1424, +0, 1353, 1424, +0, 1418, 1424, +0, 1424, 1343, +0, 1424, 1193, +0, 1424, 856, +0, 1559, 0, +0, 1693, 0, +786, 1827, 0, +1263, 1960, 0, +1547, 2093, 0, +1767, 2225, 0, +1955, 2358, 0, +2125, 2490, 0, +2283, 2623, 0, +2434, 2755, 0, +2580, 2887, 0, +2721, 3019, 0, +2861, 3152, 0, +2998, 3283, 0, +3134, 3416, 0, +3269, 3548, 0, +3404, 3680, 0, +3537, 3812, 0, +3671, 3944, 0, +3803, 4076, 0, +3937, 4095, 0, +0, 1092, 1429, +0, 1118, 1427, +0, 1149, 1424, +0, 1188, 1421, +0, 1228, 1421, +0, 1277, 1421, +0, 1335, 1421, +0, 1403, 1421, +0, 1421, 1353, +0, 1421, 1207, +0, 1421, 885, +0, 1557, 0, +0, 1691, 0, +869, 1825, 0, +1294, 1959, 0, +1564, 2092, 0, +1777, 2225, 0, +1962, 2357, 0, +2129, 2490, 0, +2287, 2622, 0, +2436, 2755, 0, +2581, 2887, 0, +2723, 3019, 0, +2862, 3151, 0, +2999, 3283, 0, +3135, 3416, 0, +3270, 3548, 0, +3404, 3680, 0, +3538, 3812, 0, +3671, 3944, 0, +3804, 4076, 0, +3937, 4095, 0, +0, 1037, 1429, +0, 1065, 1427, +0, 1101, 1424, +0, 1144, 1421, +0, 1196, 1416, +0, 1248, 1416, +0, 1310, 1416, +0, 1381, 1416, +0, 1416, 1367, +0, 1416, 1225, +0, 1416, 920, +0, 1553, 0, +0, 1689, 0, +960, 1823, 0, +1332, 1958, 0, +1585, 2091, 0, +1790, 2224, 0, +1970, 2357, 0, +2136, 2489, 0, +2291, 2622, 0, +2440, 2755, 0, +2584, 2887, 0, +2724, 3019, 0, +2863, 3151, 0, +3000, 3283, 0, +3135, 3416, 0, +3270, 3548, 0, +3404, 3680, 0, +3538, 3812, 0, +3671, 3944, 0, +3804, 4076, 0, +3937, 4095, 0, +0, 951, 1429, +0, 985, 1427, +0, 1027, 1424, +0, 1077, 1421, +0, 1137, 1416, +0, 1206, 1410, +0, 1273, 1410, +0, 1350, 1410, +0, 1410, 1383, +0, 1410, 1248, +0, 1410, 964, +0, 1549, 0, +406, 1685, 0, +1059, 1821, 0, +1378, 1956, 0, +1612, 2089, 0, +1808, 2223, 0, +1982, 2356, 0, +2144, 2489, 0, +2297, 2621, 0, +2444, 2754, 0, +2587, 2887, 0, +2727, 3019, 0, +2865, 3151, 0, +3001, 3283, 0, +3136, 3416, 0, +3271, 3548, 0, +3405, 3680, 0, +3538, 3812, 0, +3671, 3944, 0, +3804, 4076, 0, +3937, 4095, 0, +0, 803, 1429, +0, 849, 1427, +0, 904, 1424, +0, 969, 1421, +0, 1043, 1416, +0, 1127, 1410, +344, 1219, 1402, +344, 1304, 1402, +344, 1398, 1402, +344, 1402, 1277, +344, 1402, 1017, +0, 1543, 172, +742, 1681, 0, +1164, 1817, 0, +1433, 1953, 0, +1646, 2087, 0, +1830, 2221, 0, +1998, 2355, 0, +2155, 2488, 0, +2304, 2621, 0, +2450, 2754, 0, +2591, 2886, 0, +2730, 3018, 0, +2867, 3151, 0, +3003, 3283, 0, +3138, 3415, 0, +3272, 3548, 0, +3406, 3680, 0, +3539, 3812, 0, +3672, 3944, 0, +3804, 4076, 0, +3937, 4095, 0, +0, 471, 1429, +0, 562, 1427, +0, 662, 1424, +0, 767, 1421, +0, 878, 1416, +0, 994, 1410, +344, 1114, 1402, +695, 1236, 1390, +695, 1343, 1390, +695, 1390, 1313, +695, 1390, 1078, +479, 1534, 476, +983, 1674, 0, +1275, 1813, 0, +1498, 1950, 0, +1687, 2085, 0, +1858, 2220, 0, +2017, 2353, 0, +2169, 2487, 0, +2314, 2620, 0, +2457, 2753, 0, +2596, 2886, 0, +2734, 3018, 0, +2870, 3151, 0, +3005, 3283, 0, +3139, 3415, 0, +3273, 3548, 0, +3406, 3680, 0, +3540, 3812, 0, +3672, 3944, 0, +3805, 4076, 0, +3937, 4095, 0, +0, 0, 1429, +0, 0, 1427, +0, 0, 1424, +0, 141, 1421, +0, 478, 1416, +0, 719, 1410, +344, 919, 1402, +695, 1095, 1390, +940, 1258, 1374, +940, 1374, 1357, +940, 1374, 1150, +926, 1523, 826, +1183, 1666, 608, +1391, 1807, 0, +1572, 1945, 0, +1738, 2082, 0, +1894, 2217, 0, +2042, 2352, 0, +2187, 2486, 0, +2328, 2619, 0, +2467, 2752, 0, +2603, 2885, 0, +2739, 3018, 0, +2874, 3151, 0, +3008, 3283, 0, +3141, 3415, 0, +3275, 3548, 0, +3408, 3680, 0, +3540, 3812, 0, +3673, 3944, 0, +3805, 4076, 0, +3938, 4095, 0, +0, 0, 1429, +0, 0, 1427, +0, 0, 1424, +0, 0, 1421, +0, 0, 1416, +47, 0, 1410, +344, 345, 1402, +695, 793, 1390, +940, 1069, 1374, +1142, 1286, 1352, +1142, 1352, 1231, +1202, 1507, 1073, +1360, 1654, 959, +1510, 1798, 740, +1655, 1939, 0, +1797, 2077, 0, +1936, 2214, 0, +2074, 2349, 0, +2210, 2484, 0, +2345, 2618, 0, +2479, 2751, 0, +2613, 2885, 0, +2746, 3017, 0, +2879, 3150, 0, +3012, 3282, 0, +3144, 3415, 0, +3277, 3547, 0, +3409, 3680, 0, +3541, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3938, 4095, 0, +816, 0, 1429, +833, 0, 1427, +856, 0, 1424, +885, 0, 1421, +920, 0, 1416, +964, 0, 1410, +1017, 344, 1402, +1078, 695, 1390, +1150, 940, 1374, +1231, 1142, 1352, +1320, 1320, 1320, +1418, 1484, 1274, +1522, 1638, 1205, +1633, 1787, 1090, +1748, 1930, 872, +1866, 2071, 79, +1988, 2209, 0, +2113, 2346, 0, +2239, 2481, 0, +2367, 2616, 0, +2495, 2750, 0, +2625, 2883, 0, +2755, 3016, 0, +2886, 3150, 0, +3017, 3282, 0, +3148, 3414, 0, +3280, 3547, 0, +3411, 3679, 0, +3543, 3812, 0, +3675, 3944, 0, +3807, 4076, 0, +3939, 4095, 0, +1301, 0, 1563, +1307, 0, 1561, +1315, 0, 1559, +1326, 0, 1557, +1340, 0, 1553, +1358, 0, 1549, +1381, 0, 1543, +1409, 476, 1534, +1445, 826, 1523, +1489, 1073, 1507, +1484, 1274, 1418, +1484, 1363, 1274, +1638, 1621, 1205, +1740, 1787, 1090, +1833, 1930, 872, +1934, 2071, 79, +2041, 2209, 0, +2153, 2346, 0, +2270, 2481, 0, +2390, 2616, 0, +2514, 2750, 0, +2639, 2883, 0, +2765, 3016, 0, +2894, 3150, 0, +3023, 3282, 0, +3152, 3414, 0, +3283, 3547, 0, +3414, 3679, 0, +3545, 3812, 0, +3676, 3944, 0, +3808, 4076, 0, +3940, 4095, 0, +1587, 0, 1696, +1590, 0, 1695, +1594, 0, 1693, +1600, 0, 1691, +1608, 0, 1689, +1618, 0, 1685, +1631, 0, 1681, +1648, 0, 1674, +1666, 608, 1663, +1654, 959, 1608, +1638, 1205, 1522, +1638, 1205, 1333, +1638, 1414, 1205, +1787, 1709, 1090, +1927, 1930, 872, +2010, 2071, 79, +2102, 2209, 0, +2202, 2346, 0, +2308, 2481, 0, +2420, 2616, 0, +2536, 2750, 0, +2656, 2883, 0, +2778, 3016, 0, +2904, 3150, 0, +3030, 3282, 0, +3158, 3414, 0, +3287, 3547, 0, +3417, 3679, 0, +3547, 3812, 0, +3678, 3944, 0, +3809, 4076, 0, +3941, 4095, 0, +1807, 0, 1828, +1810, 0, 1828, +1812, 0, 1827, +1816, 0, 1825, +1821, 0, 1823, +1821, 0, 1815, +1817, 0, 1799, +1813, 0, 1777, +1807, 0, 1746, +1798, 740, 1701, +1787, 1090, 1633, +1787, 1090, 1491, +1787, 1090, 1189, +1787, 1475, 1090, +1930, 1805, 872, +2071, 2044, 79, +2174, 2209, 0, +2260, 2346, 0, +2355, 2481, 0, +2456, 2616, 0, +2565, 2750, 0, +2678, 2883, 0, +2796, 3016, 0, +2917, 3150, 0, +3040, 3282, 0, +3165, 3414, 0, +3293, 3547, 0, +3421, 3679, 0, +3551, 3812, 0, +3680, 3944, 0, +3811, 4076, 0, +3942, 4095, 0, +1961, 0, 1923, +1961, 0, 1920, +1960, 0, 1917, +1959, 0, 1911, +1958, 0, 1905, +1956, 0, 1895, +1953, 0, 1882, +1950, 0, 1864, +1945, 0, 1838, +1939, 0, 1801, +1930, 872, 1748, +1930, 872, 1642, +1930, 872, 1447, +1930, 872, 873, +1930, 1545, 872, +2071, 1908, 79, +2209, 2159, 0, +2328, 2346, 0, +2410, 2481, 0, +2501, 2616, 0, +2601, 2750, 0, +2706, 2883, 0, +2817, 3016, 0, +2933, 3150, 0, +3053, 3282, 0, +3175, 3414, 0, +3300, 3547, 0, +3427, 3679, 0, +3555, 3812, 0, +3684, 3944, 0, +3813, 4076, 0, +3944, 4095, 0, +2094, 0, 2007, +2093, 0, 2005, +2093, 0, 2002, +2092, 0, 1997, +2091, 0, 1992, +2089, 0, 1984, +2087, 0, 1973, +2085, 0, 1958, +2082, 0, 1938, +2077, 0, 1908, +2071, 79, 1866, +2071, 79, 1787, +2071, 79, 1655, +2071, 79, 1379, +2071, 706, 79, +2071, 1625, 79, +2209, 2018, 0, +2346, 2278, 0, +2475, 2481, 0, +2555, 2616, 0, +2645, 2750, 0, +2741, 2883, 0, +2845, 3016, 0, +2955, 3150, 0, +3070, 3282, 0, +3188, 3414, 0, +3310, 3547, 0, +3434, 3679, 0, +3561, 3812, 0, +3688, 3944, 0, +3816, 4076, 0, +3946, 4095, 0, +2226, 0, 2100, +2226, 0, 2098, +2225, 0, 2095, +2225, 0, 2092, +2224, 0, 2087, +2223, 0, 2081, +2221, 0, 2072, +2220, 0, 2060, +2217, 0, 2044, +2214, 0, 2021, +2209, 0, 1988, +2209, 0, 1929, +2209, 0, 1836, +2209, 0, 1671, +2209, 0, 1270, +2209, 303, 0, +2209, 1713, 0, +2346, 2132, 0, +2481, 2401, 0, +2616, 2613, 0, +2697, 2750, 0, +2784, 2883, 0, +2880, 3016, 0, +2982, 3150, 0, +3091, 3282, 0, +3205, 3414, 0, +3323, 3547, 0, +3444, 3679, 0, +3568, 3812, 0, +3694, 3944, 0, +3821, 4076, 0, +3950, 4095, 0, +2358, 0, 2200, +2358, 0, 2199, +2358, 0, 2196, +2357, 0, 2193, +2357, 0, 2190, +2356, 0, 2185, +2355, 0, 2178, +2353, 0, 2168, +2352, 0, 2155, +2349, 0, 2138, +2346, 0, 2113, +2346, 0, 2069, +2346, 0, 2002, +2346, 0, 1894, +2346, 0, 1692, +2346, 0, 1064, +2346, 0, 0, +2346, 1809, 0, +2481, 2251, 0, +2616, 2525, 0, +2750, 2741, 0, +2836, 2883, 0, +2922, 3016, 0, +3017, 3150, 0, +3118, 3282, 0, +3226, 3414, 0, +3339, 3547, 0, +3457, 3679, 0, +3577, 3812, 0, +3701, 3944, 0, +3826, 4076, 0, +3954, 4095, 0, +2491, 0, 2306, +2491, 0, 2305, +2490, 0, 2304, +2490, 0, 2302, +2489, 0, 2298, +2489, 0, 2294, +2488, 0, 2289, +2487, 0, 2282, +2486, 0, 2272, +2484, 0, 2258, +2481, 0, 2239, +2481, 0, 2206, +2481, 0, 2158, +2481, 0, 2084, +2481, 0, 1961, +2481, 0, 1719, +2481, 0, 415, +2481, 0, 0, +2481, 1913, 0, +2616, 2372, 0, +2750, 2651, 0, +2883, 2869, 0, +2974, 3016, 0, +3059, 3150, 0, +3152, 3282, 0, +3253, 3414, 0, +3361, 3547, 0, +3473, 3679, 0, +3590, 3812, 0, +3711, 3944, 0, +3834, 4076, 0, +3959, 4095, 0, +2623, 0, 2419, +2623, 0, 2417, +2623, 0, 2416, +2622, 0, 2414, +2622, 0, 2412, +2621, 0, 2409, +2621, 0, 2405, +2620, 0, 2399, +2619, 0, 2392, +2618, 0, 2381, +2616, 0, 2367, +2616, 0, 2342, +2616, 0, 2306, +2616, 0, 2255, +2616, 0, 2174, +2616, 0, 2038, +2616, 0, 1752, +2616, 0, 0, +2616, 0, 0, +2616, 2022, 0, +2750, 2496, 0, +2883, 2779, 0, +3016, 2998, 0, +3110, 3150, 0, +3194, 3282, 0, +3287, 3414, 0, +3387, 3547, 0, +3494, 3679, 0, +3606, 3812, 0, +3723, 3944, 0, +3843, 4076, 0, +3967, 4095, 0, +2755, 0, 2535, +2755, 0, 2535, +2755, 0, 2533, +2755, 0, 2532, +2755, 0, 2530, +2754, 0, 2528, +2754, 0, 2525, +2753, 0, 2521, +2752, 0, 2514, +2751, 0, 2506, +2750, 0, 2495, +2750, 0, 2477, +2750, 0, 2451, +2750, 0, 2414, +2750, 0, 2359, +2750, 0, 2273, +2750, 0, 2124, +2750, 0, 1794, +2750, 0, 0, +2750, 0, 0, +2750, 2137, 0, +2883, 2621, 0, +3016, 2907, 0, +3150, 3128, 0, +3244, 3282, 0, +3329, 3414, 0, +3421, 3547, 0, +3521, 3679, 0, +3628, 3812, 0, +3740, 3944, 0, +3856, 4076, 0, +3976, 4095, 0, +2887, 0, 2655, +2887, 0, 2655, +2887, 0, 2654, +2887, 0, 2653, +2887, 0, 2651, +2887, 0, 2650, +2886, 0, 2647, +2886, 0, 2644, +2885, 0, 2639, +2885, 0, 2633, +2883, 0, 2625, +2883, 0, 2611, +2883, 0, 2592, +2883, 0, 2565, +2883, 0, 2526, +2883, 0, 2469, +2883, 0, 2378, +2883, 0, 2218, +2883, 0, 1843, +2883, 0, 0, +2883, 0, 0, +2883, 2255, 0, +3016, 2749, 0, +3150, 3038, 0, +3282, 3259, 0, +3379, 3414, 0, +3462, 3547, 0, +3554, 3679, 0, +3654, 3812, 0, +3761, 3944, 0, +3872, 4076, 0, +3989, 4095, 0, +3019, 0, 2778, +3019, 0, 2777, +3019, 0, 2777, +3019, 0, 2776, +3019, 0, 2775, +3019, 0, 2774, +3018, 0, 2772, +3018, 0, 2769, +3018, 0, 2766, +3017, 0, 2761, +3016, 0, 2755, +3016, 0, 2745, +3016, 0, 2731, +3016, 0, 2711, +3016, 0, 2683, +3016, 0, 2643, +3016, 0, 2583, +3016, 0, 2488, +3016, 0, 2319, +3016, 0, 1900, +3016, 0, 0, +3016, 0, 0, +3016, 2377, 0, +3150, 2878, 0, +3282, 3168, 0, +3414, 3390, 0, +3512, 3547, 0, +3596, 3679, 0, +3688, 3812, 0, +3787, 3944, 0, +3893, 4076, 0, +4005, 4095, 0, +3152, 0, 2903, +3152, 0, 2903, +3152, 0, 2903, +3151, 0, 2902, +3151, 0, 2901, +3151, 0, 2900, +3151, 0, 2898, +3151, 0, 2896, +3151, 0, 2894, +3150, 0, 2891, +3150, 0, 2886, +3150, 0, 2878, +3150, 0, 2868, +3150, 0, 2853, +3150, 0, 2833, +3150, 0, 2804, +3150, 0, 2763, +3150, 0, 2702, +3150, 0, 2604, +3150, 0, 2427, +3150, 0, 1969, +3150, 0, 0, +3150, 0, 0, +3150, 2501, 0, +3282, 3006, 0, +3414, 3298, 0, +3547, 3521, 0, +3646, 3679, 0, +3729, 3812, 0, +3820, 3944, 0, +3920, 4076, 0, +4026, 4095, 0, +3284, 0, 3030, +3283, 0, 3029, +3283, 0, 3029, +3283, 0, 3029, +3283, 0, 3028, +3283, 0, 3027, +3283, 0, 3026, +3283, 0, 3025, +3283, 0, 3023, +3282, 0, 3020, +3282, 0, 3017, +3282, 0, 3011, +3282, 0, 3003, +3282, 0, 2992, +3282, 0, 2977, +3282, 0, 2957, +3282, 0, 2928, +3282, 0, 2886, +3282, 0, 2823, +3282, 0, 2723, +3282, 0, 2539, +3282, 0, 2045, +3282, 0, 0, +3282, 0, 0, +3282, 2627, 0, +3414, 3137, 0, +3547, 3429, 0, +3679, 3653, 0, +3778, 3812, 0, +3862, 3944, 0, +3953, 4076, 0, +4053, 4095, 0, +3416, 0, 3158, +3416, 0, 3158, +3416, 0, 3157, +3416, 0, 3157, +3416, 0, 3157, +3416, 0, 3156, +3415, 0, 3155, +3415, 0, 3154, +3415, 0, 3153, +3415, 0, 3151, +3414, 0, 3148, +3414, 0, 3144, +3414, 0, 3138, +3414, 0, 3130, +3414, 0, 3119, +3414, 0, 3104, +3414, 0, 3083, +3414, 0, 3054, +3414, 0, 3011, +3414, 0, 2947, +3414, 0, 2845, +3414, 0, 2657, +3414, 0, 2135, +3414, 0, 0, +3414, 0, 0, +3414, 2754, 0, +3547, 3268, 0, +3679, 3561, 0, +3812, 3784, 0, +3911, 3944, 0, +3994, 4076, 0, +4086, 4095, 0, +3548, 0, 3287, +3548, 0, 3287, +3548, 0, 3287, +3548, 0, 3286, +3548, 0, 3286, +3548, 0, 3286, +3548, 0, 3285, +3548, 0, 3284, +3548, 0, 3283, +3547, 0, 3282, +3547, 0, 3280, +3547, 0, 3277, +3547, 0, 3272, +3547, 0, 3266, +3547, 0, 3258, +3547, 0, 3247, +3547, 0, 3232, +3547, 0, 3211, +3547, 0, 3181, +3547, 0, 3138, +3547, 0, 3074, +3547, 0, 2970, +3547, 0, 2778, +3547, 0, 2228, +3547, 0, 0, +3547, 0, 0, +3547, 2883, 0, +3679, 3399, 0, +3812, 3692, 0, +3944, 3916, 0, +4044, 4076, 0, +4095, 4095, 0, +3680, 0, 3417, +3680, 0, 3417, +3680, 0, 3417, +3680, 0, 3416, +3680, 0, 3416, +3680, 0, 3416, +3680, 0, 3415, +3680, 0, 3415, +3680, 0, 3414, +3680, 0, 3413, +3679, 0, 3411, +3679, 0, 3409, +3679, 0, 3406, +3679, 0, 3401, +3679, 0, 3395, +3679, 0, 3387, +3679, 0, 3376, +3679, 0, 3361, +3679, 0, 3340, +3679, 0, 3310, +3679, 0, 3267, +3679, 0, 3201, +3679, 0, 3096, +3679, 0, 2901, +3679, 0, 2333, +3679, 0, 0, +3679, 0, 0, +3679, 3013, 0, +3812, 3530, 0, +3944, 3824, 0, +4076, 4048, 0, +4095, 4095, 0, +3812, 0, 3547, +3812, 0, 3547, +3812, 0, 3547, +3812, 0, 3547, +3812, 0, 3547, +3812, 0, 3547, +3812, 0, 3546, +3812, 0, 3546, +3812, 0, 3545, +3812, 0, 3544, +3812, 0, 3543, +3812, 0, 3541, +3812, 0, 3539, +3812, 0, 3536, +3812, 0, 3531, +3812, 0, 3525, +3812, 0, 3517, +3812, 0, 3506, +3812, 0, 3491, +3812, 0, 3469, +3812, 0, 3439, +3812, 0, 3396, +3812, 0, 3330, +3812, 0, 3224, +3812, 0, 3027, +3812, 0, 2441, +3812, 0, 0, +3812, 0, 0, +3812, 3143, 0, +3944, 3661, 0, +4076, 3955, 0, +4095, 4095, 0, +3944, 0, 3678, +3944, 0, 3678, +3944, 0, 3678, +3944, 0, 3678, +3944, 0, 3678, +3944, 0, 3677, +3944, 0, 3677, +3944, 0, 3677, +3944, 0, 3676, +3944, 0, 3676, +3944, 0, 3675, +3944, 0, 3674, +3944, 0, 3672, +3944, 0, 3669, +3944, 0, 3666, +3944, 0, 3662, +3944, 0, 3656, +3944, 0, 3648, +3944, 0, 3636, +3944, 0, 3621, +3944, 0, 3600, +3944, 0, 3569, +3944, 0, 3526, +3944, 0, 3459, +3944, 0, 3353, +3944, 0, 3154, +3944, 0, 2553, +3944, 0, 0, +3944, 0, 0, +3944, 3273, 0, +4076, 3793, 0, +4095, 4088, 0, +4076, 0, 3809, +4076, 0, 3809, +4076, 0, 3809, +4076, 0, 3809, +4076, 0, 3809, +4076, 0, 3809, +4076, 0, 3808, +4076, 0, 3808, +4076, 0, 3808, +4076, 0, 3808, +4076, 0, 3807, +4076, 0, 3806, +4076, 0, 3804, +4076, 0, 3803, +4076, 0, 3800, +4076, 0, 3797, +4076, 0, 3793, +4076, 0, 3787, +4076, 0, 3778, +4076, 0, 3767, +4076, 0, 3752, +4076, 0, 3730, +4076, 0, 3700, +4076, 0, 3656, +4076, 0, 3590, +4076, 0, 3482, +4076, 0, 3282, +4076, 0, 2670, +4076, 0, 0, +4076, 0, 0, +4076, 3404, 0, +4095, 3925, 0, +4095, 0, 3941, +4095, 0, 3941, +4095, 0, 3941, +4095, 0, 3941, +4095, 0, 3941, +4095, 0, 3941, +4095, 0, 3940, +4095, 0, 3940, +4095, 0, 3940, +4095, 0, 3940, +4095, 0, 3939, +4095, 0, 3938, +4095, 0, 3937, +4095, 0, 3936, +4095, 0, 3934, +4095, 0, 3932, +4095, 0, 3928, +4095, 0, 3924, +4095, 0, 3918, +4095, 0, 3910, +4095, 0, 3898, +4095, 0, 3883, +4095, 0, 3862, +4095, 0, 3831, +4095, 0, 3787, +4095, 0, 3721, +4095, 0, 3613, +4095, 0, 3412, +4095, 0, 2793, +4095, 0, 0, +4095, 0, 0, +4095, 3536, 0, +0, 1304, 1563, +0, 1318, 1563, +0, 1335, 1563, +0, 1357, 1563, +0, 1385, 1563, +0, 1421, 1563, +0, 1463, 1563, +0, 1515, 1563, +0, 1563, 1548, +0, 1563, 1458, +0, 1563, 1301, +0, 1563, 934, +0, 1696, 0, +0, 1828, 0, +726, 1961, 0, +1336, 2094, 0, +1648, 2226, 0, +1880, 2358, 0, +2075, 2491, 0, +2248, 2623, 0, +2409, 2755, 0, +2562, 2887, 0, +2708, 3019, 0, +2851, 3152, 0, +2991, 3284, 0, +3129, 3416, 0, +3266, 3548, 0, +3401, 3680, 0, +3535, 3812, 0, +3669, 3944, 0, +3803, 4076, 0, +3936, 4095, 0, +0, 1290, 1563, +0, 1307, 1561, +0, 1325, 1561, +0, 1347, 1561, +0, 1376, 1561, +0, 1412, 1561, +0, 1456, 1561, +0, 1508, 1561, +0, 1561, 1552, +0, 1561, 1463, +0, 1561, 1307, +0, 1561, 948, +0, 1695, 0, +0, 1828, 0, +780, 1961, 0, +1351, 2093, 0, +1656, 2226, 0, +1885, 2358, 0, +2078, 2491, 0, +2250, 2623, 0, +2411, 2755, 0, +2563, 2887, 0, +2709, 3019, 0, +2852, 3152, 0, +2992, 3283, 0, +3129, 3416, 0, +3266, 3548, 0, +3401, 3680, 0, +3536, 3812, 0, +3669, 3944, 0, +3803, 4076, 0, +3936, 4095, 0, +0, 1271, 1563, +0, 1288, 1561, +0, 1310, 1559, +0, 1333, 1559, +0, 1363, 1559, +0, 1400, 1559, +0, 1445, 1559, +0, 1499, 1559, +0, 1559, 1556, +0, 1559, 1468, +0, 1559, 1315, +0, 1559, 966, +0, 1693, 0, +0, 1827, 0, +844, 1960, 0, +1370, 2093, 0, +1666, 2225, 0, +1891, 2358, 0, +2082, 2490, 0, +2253, 2623, 0, +2413, 2755, 0, +2564, 2887, 0, +2710, 3019, 0, +2853, 3152, 0, +2992, 3283, 0, +3130, 3416, 0, +3266, 3548, 0, +3401, 3680, 0, +3536, 3812, 0, +3669, 3944, 0, +3803, 4076, 0, +3936, 4095, 0, +0, 1244, 1563, +0, 1262, 1561, +0, 1285, 1559, +0, 1315, 1557, +0, 1345, 1557, +0, 1384, 1557, +0, 1430, 1557, +0, 1486, 1557, +0, 1551, 1557, +0, 1557, 1476, +0, 1557, 1326, +0, 1557, 988, +0, 1691, 0, +0, 1825, 0, +917, 1959, 0, +1394, 2092, 0, +1679, 2225, 0, +1899, 2357, 0, +2087, 2490, 0, +2256, 2622, 0, +2415, 2755, 0, +2566, 2887, 0, +2712, 3019, 0, +2854, 3151, 0, +2993, 3283, 0, +3130, 3416, 0, +3267, 3548, 0, +3401, 3680, 0, +3536, 3812, 0, +3669, 3944, 0, +3803, 4076, 0, +3936, 4095, 0, +0, 1205, 1563, +0, 1225, 1561, +0, 1250, 1559, +0, 1281, 1557, +0, 1320, 1553, +0, 1360, 1553, +0, 1409, 1553, +0, 1467, 1553, +0, 1535, 1553, +0, 1553, 1486, +0, 1553, 1340, +0, 1553, 1017, +0, 1689, 0, +0, 1823, 0, +1000, 1958, 0, +1425, 2091, 0, +1695, 2224, 0, +1909, 2357, 0, +2094, 2489, 0, +2261, 2622, 0, +2419, 2755, 0, +2569, 2887, 0, +2713, 3019, 0, +2855, 3151, 0, +2994, 3283, 0, +3131, 3416, 0, +3267, 3548, 0, +3402, 3680, 0, +3536, 3812, 0, +3670, 3944, 0, +3803, 4076, 0, +3936, 4095, 0, +0, 1148, 1563, +0, 1170, 1561, +0, 1198, 1559, +0, 1233, 1557, +0, 1276, 1553, +0, 1328, 1549, +0, 1380, 1549, +0, 1442, 1549, +0, 1513, 1549, +0, 1549, 1499, +0, 1549, 1358, +0, 1549, 1053, +0, 1685, 0, +0, 1821, 0, +1091, 1956, 0, +1463, 2089, 0, +1717, 2223, 0, +1922, 2356, 0, +2103, 2489, 0, +2268, 2621, 0, +2423, 2754, 0, +2572, 2887, 0, +2716, 3019, 0, +2857, 3151, 0, +2995, 3283, 0, +3132, 3416, 0, +3268, 3548, 0, +3402, 3680, 0, +3537, 3812, 0, +3670, 3944, 0, +3803, 4076, 0, +3936, 4095, 0, +0, 1057, 1563, +0, 1084, 1561, +0, 1118, 1559, +0, 1159, 1557, +0, 1209, 1553, +0, 1269, 1549, +0, 1338, 1543, +0, 1405, 1543, +0, 1482, 1543, +0, 1543, 1516, +0, 1543, 1381, +0, 1543, 1096, +0, 1681, 0, +536, 1817, 0, +1190, 1953, 0, +1509, 2087, 0, +1744, 2221, 0, +1940, 2355, 0, +2115, 2488, 0, +2276, 2621, 0, +2429, 2754, 0, +2576, 2886, 0, +2719, 3018, 0, +2859, 3151, 0, +2997, 3283, 0, +3133, 3415, 0, +3269, 3548, 0, +3403, 3680, 0, +3537, 3812, 0, +3670, 3944, 0, +3803, 4076, 0, +3937, 4095, 0, +0, 897, 1563, +0, 935, 1561, +0, 981, 1559, +0, 1037, 1557, +0, 1102, 1553, +0, 1176, 1549, +0, 1259, 1543, +476, 1351, 1534, +476, 1437, 1534, +476, 1531, 1534, +476, 1534, 1409, +476, 1534, 1149, +0, 1674, 313, +874, 1813, 0, +1295, 1950, 0, +1565, 2085, 0, +1778, 2220, 0, +1962, 2353, 0, +2130, 2487, 0, +2287, 2620, 0, +2437, 2753, 0, +2581, 2886, 0, +2723, 3018, 0, +2862, 3151, 0, +2999, 3283, 0, +3135, 3415, 0, +3270, 3548, 0, +3404, 3680, 0, +3538, 3812, 0, +3671, 3944, 0, +3804, 4076, 0, +3937, 4095, 0, +0, 523, 1563, +0, 605, 1561, +0, 696, 1559, +0, 794, 1557, +0, 900, 1553, +0, 1011, 1549, +0, 1127, 1543, +476, 1246, 1534, +826, 1368, 1523, +826, 1476, 1523, +826, 1523, 1445, +826, 1523, 1211, +608, 1666, 609, +1115, 1807, 0, +1407, 1945, 0, +1630, 2082, 0, +1819, 2217, 0, +1990, 2352, 0, +2149, 2486, 0, +2301, 2619, 0, +2447, 2752, 0, +2589, 2885, 0, +2728, 3018, 0, +2866, 3151, 0, +3002, 3283, 0, +3137, 3415, 0, +3271, 3548, 0, +3405, 3680, 0, +3538, 3812, 0, +3671, 3944, 0, +3804, 4076, 0, +3937, 4095, 0, +0, 0, 1563, +0, 0, 1561, +0, 0, 1559, +0, 0, 1557, +0, 275, 1553, +0, 611, 1549, +0, 852, 1543, +476, 1051, 1534, +826, 1228, 1523, +1073, 1390, 1507, +1073, 1507, 1489, +1073, 1507, 1282, +1056, 1654, 959, +1315, 1798, 740, +1523, 1939, 0, +1704, 2077, 0, +1870, 2214, 0, +2025, 2349, 0, +2174, 2484, 0, +2319, 2618, 0, +2460, 2751, 0, +2599, 2885, 0, +2735, 3017, 0, +2871, 3150, 0, +3006, 3282, 0, +3140, 3415, 0, +3274, 3547, 0, +3407, 3680, 0, +3540, 3812, 0, +3673, 3944, 0, +3805, 4076, 0, +3937, 4095, 0, +0, 0, 1563, +0, 0, 1561, +0, 0, 1559, +0, 0, 1557, +0, 0, 1553, +0, 0, 1549, +172, 0, 1543, +476, 479, 1534, +826, 926, 1523, +1073, 1202, 1507, +1274, 1418, 1484, +1274, 1484, 1363, +1333, 1638, 1205, +1491, 1787, 1090, +1642, 1930, 872, +1787, 2071, 79, +1929, 2209, 0, +2069, 2346, 0, +2206, 2481, 0, +2342, 2616, 0, +2477, 2750, 0, +2611, 2883, 0, +2745, 3016, 0, +2878, 3150, 0, +3011, 3282, 0, +3144, 3414, 0, +3277, 3547, 0, +3409, 3679, 0, +3541, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3938, 4095, 0, +934, 0, 1563, +948, 0, 1561, +966, 0, 1559, +988, 0, 1557, +1017, 0, 1553, +1053, 0, 1549, +1096, 0, 1543, +1149, 476, 1534, +1211, 826, 1523, +1282, 1073, 1507, +1363, 1274, 1484, +1453, 1453, 1453, +1550, 1616, 1407, +1654, 1771, 1337, +1765, 1919, 1223, +1880, 2062, 1005, +1998, 2203, 217, +2120, 2341, 0, +2245, 2478, 0, +2371, 2613, 0, +2499, 2748, 0, +2628, 2882, 0, +2757, 3015, 0, +2887, 3149, 0, +3018, 3281, 0, +3149, 3414, 0, +3280, 3547, 0, +3412, 3679, 0, +3544, 3812, 0, +3675, 3944, 0, +3807, 4076, 0, +3939, 4095, 0, +1427, 0, 1696, +1432, 0, 1695, +1439, 0, 1693, +1447, 0, 1691, +1457, 0, 1689, +1471, 0, 1685, +1489, 0, 1681, +1512, 0, 1674, +1541, 608, 1666, +1577, 959, 1654, +1621, 1205, 1638, +1616, 1407, 1550, +1616, 1495, 1407, +1771, 1754, 1337, +1872, 1919, 1223, +1965, 2062, 1005, +2066, 2203, 217, +2173, 2341, 0, +2285, 2478, 0, +2402, 2613, 0, +2522, 2748, 0, +2645, 2882, 0, +2770, 3015, 0, +2898, 3149, 0, +3025, 3281, 0, +3155, 3414, 0, +3285, 3547, 0, +3415, 3679, 0, +3546, 3812, 0, +3677, 3944, 0, +3808, 4076, 0, +3940, 4095, 0, +1716, 0, 1828, +1719, 0, 1828, +1722, 0, 1827, +1727, 0, 1825, +1732, 0, 1823, +1740, 0, 1821, +1750, 0, 1817, +1763, 0, 1813, +1780, 0, 1807, +1798, 740, 1795, +1787, 1090, 1740, +1771, 1337, 1654, +1771, 1337, 1466, +1771, 1546, 1337, +1919, 1841, 1223, +2059, 2062, 1005, +2142, 2203, 217, +2234, 2341, 0, +2334, 2478, 0, +2440, 2613, 0, +2552, 2748, 0, +2668, 2882, 0, +2788, 3015, 0, +2911, 3149, 0, +3035, 3281, 0, +3162, 3414, 0, +3290, 3547, 0, +3419, 3679, 0, +3549, 3812, 0, +3679, 3944, 0, +3810, 4076, 0, +3941, 4095, 0, +1938, 0, 1961, +1940, 0, 1961, +1941, 0, 1960, +1944, 0, 1959, +1948, 0, 1958, +1953, 0, 1956, +1953, 0, 1947, +1950, 0, 1931, +1945, 0, 1909, +1939, 0, 1878, +1930, 872, 1833, +1919, 1223, 1765, +1919, 1223, 1624, +1919, 1223, 1321, +1919, 1607, 1223, +2062, 1937, 1005, +2203, 2176, 217, +2305, 2341, 0, +2392, 2478, 0, +2487, 2613, 0, +2589, 2748, 0, +2697, 2882, 0, +2810, 3015, 0, +2928, 3149, 0, +3049, 3281, 0, +3172, 3414, 0, +3298, 3547, 0, +3425, 3679, 0, +3553, 3812, 0, +3683, 3944, 0, +3812, 4076, 0, +3943, 4095, 0, +2094, 0, 2058, +2093, 0, 2056, +2093, 0, 2053, +2092, 0, 2049, +2091, 0, 2044, +2089, 0, 2037, +2087, 0, 2027, +2085, 0, 2014, +2082, 0, 1996, +2077, 0, 1970, +2071, 79, 1934, +2062, 1005, 1880, +2062, 1005, 1774, +2062, 1005, 1579, +2062, 1005, 1006, +2062, 1677, 1005, +2203, 2041, 217, +2341, 2291, 0, +2460, 2478, 0, +2542, 2613, 0, +2634, 2748, 0, +2733, 2882, 0, +2838, 3015, 0, +2950, 3149, 0, +3065, 3281, 0, +3185, 3414, 0, +3307, 3547, 0, +3432, 3679, 0, +3559, 3812, 0, +3687, 3944, 0, +3816, 4076, 0, +3946, 4095, 0, +2226, 0, 2141, +2226, 0, 2140, +2225, 0, 2137, +2225, 0, 2134, +2224, 0, 2130, +2223, 0, 2124, +2221, 0, 2116, +2220, 0, 2105, +2217, 0, 2090, +2214, 0, 2070, +2209, 0, 2041, +2203, 217, 1998, +2203, 217, 1920, +2203, 217, 1787, +2203, 217, 1512, +2203, 838, 217, +2203, 1757, 217, +2341, 2150, 0, +2478, 2411, 0, +2607, 2613, 0, +2687, 2748, 0, +2777, 2882, 0, +2873, 3015, 0, +2977, 3149, 0, +3087, 3281, 0, +3202, 3414, 0, +3320, 3547, 0, +3442, 3679, 0, +3566, 3812, 0, +3692, 3944, 0, +3820, 4076, 0, +3949, 4095, 0, +2358, 0, 2233, +2358, 0, 2232, +2358, 0, 2230, +2357, 0, 2228, +2357, 0, 2224, +2356, 0, 2219, +2355, 0, 2213, +2353, 0, 2204, +2352, 0, 2192, +2349, 0, 2176, +2346, 0, 2153, +2341, 0, 2120, +2341, 0, 2061, +2341, 0, 1968, +2341, 0, 1803, +2341, 0, 1403, +2341, 437, 0, +2341, 1845, 0, +2478, 2264, 0, +2613, 2533, 0, +2748, 2745, 0, +2829, 2882, 0, +2916, 3015, 0, +3012, 3149, 0, +3114, 3281, 0, +3223, 3414, 0, +3337, 3547, 0, +3455, 3679, 0, +3576, 3812, 0, +3700, 3944, 0, +3826, 4076, 0, +3953, 4095, 0, +2491, 0, 2333, +2491, 0, 2332, +2490, 0, 2331, +2490, 0, 2329, +2489, 0, 2326, +2489, 0, 2322, +2488, 0, 2317, +2487, 0, 2310, +2486, 0, 2301, +2484, 0, 2288, +2481, 0, 2270, +2478, 0, 2245, +2478, 0, 2201, +2478, 0, 2134, +2478, 0, 2026, +2478, 0, 1824, +2478, 0, 1199, +2478, 0, 0, +2478, 1941, 0, +2613, 2382, 0, +2748, 2657, 0, +2882, 2873, 0, +2968, 3015, 0, +3055, 3149, 0, +3149, 3281, 0, +3250, 3414, 0, +3358, 3547, 0, +3472, 3679, 0, +3589, 3812, 0, +3710, 3944, 0, +3833, 4076, 0, +3959, 4095, 0, +2623, 0, 2440, +2623, 0, 2439, +2623, 0, 2437, +2622, 0, 2436, +2622, 0, 2434, +2621, 0, 2431, +2621, 0, 2427, +2620, 0, 2421, +2619, 0, 2414, +2618, 0, 2404, +2616, 0, 2390, +2613, 0, 2371, +2613, 0, 2338, +2613, 0, 2290, +2613, 0, 2216, +2613, 0, 2093, +2613, 0, 1851, +2613, 0, 547, +2613, 0, 0, +2613, 2045, 0, +2748, 2504, 0, +2882, 2784, 0, +3015, 3001, 0, +3106, 3149, 0, +3191, 3281, 0, +3284, 3414, 0, +3385, 3547, 0, +3493, 3679, 0, +3605, 3812, 0, +3722, 3944, 0, +3843, 4076, 0, +3966, 4095, 0, +2755, 0, 2552, +2755, 0, 2551, +2755, 0, 2550, +2755, 0, 2549, +2755, 0, 2547, +2754, 0, 2545, +2754, 0, 2541, +2753, 0, 2537, +2752, 0, 2532, +2751, 0, 2524, +2750, 0, 2514, +2748, 0, 2499, +2748, 0, 2474, +2748, 0, 2439, +2748, 0, 2387, +2748, 0, 2306, +2748, 0, 2170, +2748, 0, 1885, +2748, 0, 0, +2748, 0, 0, +2748, 2155, 0, +2882, 2628, 0, +3015, 2911, 0, +3149, 3131, 0, +3242, 3281, 0, +3326, 3414, 0, +3419, 3547, 0, +3520, 3679, 0, +3626, 3812, 0, +3739, 3944, 0, +3855, 4076, 0, +3976, 4095, 0, +2887, 0, 2668, +2887, 0, 2667, +2887, 0, 2667, +2887, 0, 2666, +2887, 0, 2664, +2887, 0, 2662, +2886, 0, 2660, +2886, 0, 2657, +2885, 0, 2652, +2885, 0, 2647, +2883, 0, 2639, +2882, 0, 2628, +2882, 0, 2609, +2882, 0, 2583, +2882, 0, 2546, +2882, 0, 2491, +2882, 0, 2405, +2882, 0, 2256, +2882, 0, 1925, +2882, 0, 0, +2882, 0, 0, +2882, 2269, 0, +3015, 2753, 0, +3149, 3040, 0, +3281, 3260, 0, +3376, 3414, 0, +3461, 3547, 0, +3553, 3679, 0, +3653, 3812, 0, +3760, 3944, 0, +3872, 4076, 0, +3988, 4095, 0, +3019, 0, 2788, +3019, 0, 2787, +3019, 0, 2787, +3019, 0, 2786, +3019, 0, 2785, +3019, 0, 2784, +3018, 0, 2782, +3018, 0, 2779, +3018, 0, 2776, +3017, 0, 2771, +3016, 0, 2765, +3015, 0, 2757, +3015, 0, 2743, +3015, 0, 2724, +3015, 0, 2697, +3015, 0, 2658, +3015, 0, 2600, +3015, 0, 2510, +3015, 0, 2350, +3015, 0, 1974, +3015, 0, 0, +3015, 0, 0, +3015, 2387, 0, +3149, 2881, 0, +3281, 3169, 0, +3414, 3391, 0, +3511, 3547, 0, +3595, 3679, 0, +3687, 3812, 0, +3786, 3944, 0, +3892, 4076, 0, +4005, 4095, 0, +3152, 0, 2911, +3152, 0, 2910, +3152, 0, 2910, +3151, 0, 2909, +3151, 0, 2908, +3151, 0, 2907, +3151, 0, 2906, +3151, 0, 2904, +3151, 0, 2902, +3150, 0, 2898, +3150, 0, 2894, +3149, 0, 2887, +3149, 0, 2877, +3149, 0, 2863, +3149, 0, 2843, +3149, 0, 2815, +3149, 0, 2775, +3149, 0, 2715, +3149, 0, 2620, +3149, 0, 2452, +3149, 0, 2033, +3149, 0, 0, +3149, 0, 0, +3149, 2509, 0, +3281, 3009, 0, +3414, 3299, 0, +3547, 3522, 0, +3644, 3679, 0, +3728, 3812, 0, +3820, 3944, 0, +3919, 4076, 0, +4026, 4095, 0, +3284, 0, 3035, +3283, 0, 3035, +3283, 0, 3035, +3283, 0, 3034, +3283, 0, 3034, +3283, 0, 3033, +3283, 0, 3032, +3283, 0, 3031, +3283, 0, 3029, +3282, 0, 3026, +3282, 0, 3023, +3281, 0, 3018, +3281, 0, 3010, +3281, 0, 2999, +3281, 0, 2985, +3281, 0, 2965, +3281, 0, 2936, +3281, 0, 2895, +3281, 0, 2833, +3281, 0, 2735, +3281, 0, 2558, +3281, 0, 2100, +3281, 0, 0, +3281, 0, 0, +3281, 2633, 0, +3414, 3139, 0, +3547, 3430, 0, +3679, 3653, 0, +3777, 3812, 0, +3861, 3944, 0, +3953, 4076, 0, +4052, 4095, 0, +3416, 0, 3162, +3416, 0, 3162, +3416, 0, 3162, +3416, 0, 3161, +3416, 0, 3161, +3416, 0, 3160, +3415, 0, 3160, +3415, 0, 3158, +3415, 0, 3157, +3415, 0, 3155, +3414, 0, 3152, +3414, 0, 3149, +3414, 0, 3143, +3414, 0, 3135, +3414, 0, 3125, +3414, 0, 3110, +3414, 0, 3089, +3414, 0, 3060, +3414, 0, 3018, +3414, 0, 2956, +3414, 0, 2855, +3414, 0, 2672, +3414, 0, 2180, +3414, 0, 0, +3414, 0, 0, +3414, 2759, 0, +3547, 3269, 0, +3679, 3562, 0, +3812, 3785, 0, +3910, 3944, 0, +3994, 4076, 0, +4085, 4095, 0, +3548, 0, 3290, +3548, 0, 3290, +3548, 0, 3290, +3548, 0, 3290, +3548, 0, 3289, +3548, 0, 3289, +3548, 0, 3288, +3548, 0, 3287, +3548, 0, 3286, +3547, 0, 3285, +3547, 0, 3283, +3547, 0, 3280, +3547, 0, 3276, +3547, 0, 3270, +3547, 0, 3262, +3547, 0, 3251, +3547, 0, 3236, +3547, 0, 3216, +3547, 0, 3186, +3547, 0, 3144, +3547, 0, 3080, +3547, 0, 2977, +3547, 0, 2790, +3547, 0, 2265, +3547, 0, 0, +3547, 0, 0, +3547, 2886, 0, +3679, 3400, 0, +3812, 3693, 0, +3944, 3916, 0, +4043, 4076, 0, +4095, 4095, 0, +3680, 0, 3419, +3680, 0, 3419, +3680, 0, 3419, +3680, 0, 3419, +3680, 0, 3419, +3680, 0, 3418, +3680, 0, 3418, +3680, 0, 3417, +3680, 0, 3416, +3680, 0, 3415, +3679, 0, 3414, +3679, 0, 3412, +3679, 0, 3409, +3679, 0, 3404, +3679, 0, 3398, +3679, 0, 3390, +3679, 0, 3379, +3679, 0, 3364, +3679, 0, 3343, +3679, 0, 3314, +3679, 0, 3271, +3679, 0, 3206, +3679, 0, 3102, +3679, 0, 2910, +3679, 0, 2363, +3679, 0, 0, +3679, 0, 0, +3679, 3015, 0, +3812, 3531, 0, +3944, 3824, 0, +4076, 4048, 0, +4095, 4095, 0, +3812, 0, 3549, +3812, 0, 3549, +3812, 0, 3549, +3812, 0, 3549, +3812, 0, 3549, +3812, 0, 3548, +3812, 0, 3548, +3812, 0, 3548, +3812, 0, 3547, +3812, 0, 3546, +3812, 0, 3545, +3812, 0, 3544, +3812, 0, 3541, +3812, 0, 3538, +3812, 0, 3533, +3812, 0, 3528, +3812, 0, 3520, +3812, 0, 3508, +3812, 0, 3493, +3812, 0, 3472, +3812, 0, 3442, +3812, 0, 3399, +3812, 0, 3333, +3812, 0, 3228, +3812, 0, 3034, +3812, 0, 2465, +3812, 0, 0, +3812, 0, 0, +3812, 3145, 0, +3944, 3662, 0, +4076, 3956, 0, +4095, 4095, 0, +3944, 0, 3679, +3944, 0, 3679, +3944, 0, 3679, +3944, 0, 3679, +3944, 0, 3679, +3944, 0, 3679, +3944, 0, 3679, +3944, 0, 3678, +3944, 0, 3678, +3944, 0, 3677, +3944, 0, 3676, +3944, 0, 3675, +3944, 0, 3673, +3944, 0, 3671, +3944, 0, 3668, +3944, 0, 3663, +3944, 0, 3657, +3944, 0, 3649, +3944, 0, 3638, +3944, 0, 3623, +3944, 0, 3602, +3944, 0, 3571, +3944, 0, 3528, +3944, 0, 3462, +3944, 0, 3356, +3944, 0, 3159, +3944, 0, 2572, +3944, 0, 0, +3944, 0, 0, +3944, 3275, 0, +4076, 3793, 0, +4095, 4088, 0, +4076, 0, 3810, +4076, 0, 3810, +4076, 0, 3810, +4076, 0, 3810, +4076, 0, 3810, +4076, 0, 3810, +4076, 0, 3810, +4076, 0, 3809, +4076, 0, 3809, +4076, 0, 3808, +4076, 0, 3808, +4076, 0, 3807, +4076, 0, 3805, +4076, 0, 3804, +4076, 0, 3801, +4076, 0, 3798, +4076, 0, 3794, +4076, 0, 3787, +4076, 0, 3780, +4076, 0, 3768, +4076, 0, 3753, +4076, 0, 3732, +4076, 0, 3701, +4076, 0, 3658, +4076, 0, 3592, +4076, 0, 3485, +4076, 0, 3286, +4076, 0, 2684, +4076, 0, 0, +4076, 0, 0, +4076, 3405, 0, +4095, 3926, 0, +4095, 0, 3941, +4095, 0, 3941, +4095, 0, 3941, +4095, 0, 3941, +4095, 0, 3941, +4095, 0, 3941, +4095, 0, 3941, +4095, 0, 3941, +4095, 0, 3941, +4095, 0, 3940, +4095, 0, 3940, +4095, 0, 3939, +4095, 0, 3938, +4095, 0, 3937, +4095, 0, 3935, +4095, 0, 3932, +4095, 0, 3929, +4095, 0, 3925, +4095, 0, 3919, +4095, 0, 3910, +4095, 0, 3899, +4095, 0, 3884, +4095, 0, 3863, +4095, 0, 3832, +4095, 0, 3788, +4095, 0, 3722, +4095, 0, 3615, +4095, 0, 3415, +4095, 0, 2804, +4095, 0, 0, +4095, 0, 0, +4095, 3537, 0, +0, 1434, 1696, +0, 1444, 1696, +0, 1457, 1696, +0, 1475, 1696, +0, 1496, 1696, +0, 1524, 1696, +0, 1559, 1696, +0, 1601, 1696, +0, 1653, 1696, +0, 1696, 1677, +0, 1696, 1587, +0, 1696, 1427, +0, 1696, 1056, +0, 1828, 0, +0, 1961, 0, +814, 2094, 0, +1457, 2226, 0, +1775, 2358, 0, +2009, 2491, 0, +2205, 2623, 0, +2379, 2755, 0, +2541, 2887, 0, +2693, 3019, 0, +2840, 3152, 0, +2983, 3284, 0, +3123, 3416, 0, +3261, 3548, 0, +3398, 3680, 0, +3533, 3812, 0, +3667, 3944, 0, +3801, 4076, 0, +3935, 4095, 0, +0, 1424, 1696, +0, 1436, 1695, +0, 1450, 1695, +0, 1467, 1695, +0, 1489, 1695, +0, 1517, 1695, +0, 1552, 1695, +0, 1596, 1695, +0, 1647, 1695, +0, 1695, 1680, +0, 1695, 1590, +0, 1695, 1432, +0, 1695, 1066, +0, 1828, 0, +0, 1961, 0, +859, 2093, 0, +1469, 2226, 0, +1781, 2358, 0, +2013, 2491, 0, +2207, 2623, 0, +2381, 2755, 0, +2542, 2887, 0, +2694, 3019, 0, +2841, 3152, 0, +2983, 3283, 0, +3123, 3416, 0, +3261, 3548, 0, +3398, 3680, 0, +3533, 3812, 0, +3667, 3944, 0, +3801, 4076, 0, +3935, 4095, 0, +0, 1410, 1696, +0, 1422, 1695, +0, 1439, 1693, +0, 1456, 1693, +0, 1479, 1693, +0, 1508, 1693, +0, 1544, 1693, +0, 1588, 1693, +0, 1640, 1693, +0, 1693, 1683, +0, 1693, 1594, +0, 1693, 1439, +0, 1693, 1080, +0, 1827, 0, +0, 1960, 0, +913, 2093, 0, +1484, 2225, 0, +1788, 2358, 0, +2017, 2490, 0, +2210, 2623, 0, +2383, 2755, 0, +2543, 2887, 0, +2695, 3019, 0, +2842, 3152, 0, +2984, 3283, 0, +3124, 3416, 0, +3261, 3548, 0, +3398, 3680, 0, +3533, 3812, 0, +3668, 3944, 0, +3801, 4076, 0, +3935, 4095, 0, +0, 1390, 1696, +0, 1403, 1695, +0, 1420, 1693, +0, 1442, 1691, +0, 1465, 1691, +0, 1495, 1691, +0, 1532, 1691, +0, 1577, 1691, +0, 1631, 1691, +0, 1691, 1688, +0, 1691, 1600, +0, 1691, 1447, +0, 1691, 1098, +0, 1825, 0, +0, 1959, 0, +977, 2092, 0, +1503, 2225, 0, +1798, 2357, 0, +2023, 2490, 0, +2214, 2622, 0, +2386, 2755, 0, +2545, 2887, 0, +2696, 3019, 0, +2842, 3151, 0, +2985, 3283, 0, +3124, 3416, 0, +3262, 3548, 0, +3398, 3680, 0, +3533, 3812, 0, +3668, 3944, 0, +3801, 4076, 0, +3935, 4095, 0, +0, 1362, 1696, +0, 1376, 1695, +0, 1394, 1693, +0, 1417, 1691, +0, 1446, 1689, +0, 1477, 1689, +0, 1515, 1689, +0, 1562, 1689, +0, 1617, 1689, +0, 1683, 1689, +0, 1689, 1608, +0, 1689, 1457, +0, 1689, 1120, +0, 1823, 0, +0, 1958, 0, +1050, 2091, 0, +1527, 2224, 0, +1811, 2357, 0, +2031, 2489, 0, +2219, 2622, 0, +2389, 2755, 0, +2548, 2887, 0, +2698, 3019, 0, +2844, 3151, 0, +2986, 3283, 0, +3125, 3416, 0, +3262, 3548, 0, +3399, 3680, 0, +3534, 3812, 0, +3668, 3944, 0, +3801, 4076, 0, +3935, 4095, 0, +0, 1322, 1696, +0, 1337, 1695, +0, 1357, 1693, +0, 1382, 1691, +0, 1413, 1689, +0, 1452, 1685, +0, 1492, 1685, +0, 1541, 1685, +0, 1599, 1685, +0, 1667, 1685, +0, 1685, 1618, +0, 1685, 1471, +0, 1685, 1149, +0, 1821, 0, +0, 1956, 0, +1133, 2089, 0, +1557, 2223, 0, +1828, 2356, 0, +2041, 2489, 0, +2226, 2621, 0, +2394, 2754, 0, +2551, 2887, 0, +2701, 3019, 0, +2845, 3151, 0, +2987, 3283, 0, +3126, 3416, 0, +3263, 3548, 0, +3399, 3680, 0, +3534, 3812, 0, +3668, 3944, 0, +3802, 4076, 0, +3935, 4095, 0, +0, 1262, 1696, +0, 1279, 1695, +0, 1302, 1693, +0, 1330, 1691, +0, 1365, 1689, +0, 1408, 1685, +0, 1460, 1681, +0, 1512, 1681, +0, 1574, 1681, +0, 1645, 1681, +0, 1681, 1631, +0, 1681, 1489, +0, 1681, 1184, +0, 1817, 0, +0, 1953, 0, +1224, 2087, 0, +1596, 2221, 0, +1849, 2355, 0, +2055, 2488, 0, +2235, 2621, 0, +2400, 2754, 0, +2555, 2886, 0, +2703, 3018, 0, +2848, 3151, 0, +2988, 3283, 0, +3127, 3415, 0, +3264, 3548, 0, +3400, 3680, 0, +3534, 3812, 0, +3668, 3944, 0, +3802, 4076, 0, +3935, 4095, 0, +0, 1167, 1696, +0, 1188, 1695, +0, 1216, 1693, +0, 1249, 1691, +0, 1291, 1689, +0, 1341, 1685, +0, 1401, 1681, +0, 1470, 1674, +0, 1537, 1674, +0, 1614, 1674, +0, 1674, 1648, +0, 1674, 1512, +0, 1674, 1228, +0, 1813, 0, +670, 1950, 0, +1322, 2085, 0, +1642, 2220, 0, +1876, 2353, 0, +2072, 2487, 0, +2247, 2620, 0, +2408, 2753, 0, +2561, 2886, 0, +2708, 3018, 0, +2851, 3151, 0, +2991, 3283, 0, +3129, 3415, 0, +3265, 3548, 0, +3401, 3680, 0, +3535, 3812, 0, +3669, 3944, 0, +3802, 4076, 0, +3936, 4095, 0, +0, 998, 1696, +0, 1029, 1695, +0, 1067, 1693, +0, 1113, 1691, +0, 1169, 1689, +0, 1233, 1685, +0, 1308, 1681, +0, 1391, 1674, +608, 1483, 1666, +608, 1569, 1666, +608, 1663, 1666, +608, 1666, 1541, +608, 1666, 1281, +0, 1807, 438, +1007, 1945, 0, +1428, 2082, 0, +1697, 2217, 0, +1910, 2352, 0, +2094, 2486, 0, +2262, 2619, 0, +2419, 2752, 0, +2569, 2885, 0, +2714, 3018, 0, +2855, 3151, 0, +2994, 3283, 0, +3131, 3415, 0, +3267, 3548, 0, +3402, 3680, 0, +3536, 3812, 0, +3670, 3944, 0, +3803, 4076, 0, +3936, 4095, 0, +0, 580, 1696, +0, 653, 1695, +0, 736, 1693, +0, 827, 1691, +0, 926, 1689, +0, 1031, 1685, +0, 1142, 1681, +0, 1258, 1674, +608, 1378, 1666, +959, 1500, 1654, +959, 1608, 1654, +959, 1654, 1577, +959, 1654, 1343, +742, 1798, 740, +1248, 1939, 0, +1539, 2077, 0, +1762, 2214, 0, +1951, 2349, 0, +2122, 2484, 0, +2281, 2618, 0, +2433, 2751, 0, +2579, 2885, 0, +2721, 3017, 0, +2860, 3150, 0, +2998, 3282, 0, +3134, 3415, 0, +3269, 3547, 0, +3404, 3680, 0, +3537, 3812, 0, +3671, 3944, 0, +3803, 4076, 0, +3937, 4095, 0, +0, 0, 1696, +0, 0, 1695, +0, 0, 1693, +0, 0, 1691, +0, 0, 1689, +0, 406, 1685, +0, 742, 1681, +0, 983, 1674, +608, 1183, 1666, +959, 1360, 1654, +1205, 1522, 1638, +1205, 1638, 1621, +1205, 1638, 1414, +1189, 1787, 1090, +1447, 1930, 872, +1655, 2071, 79, +1836, 2209, 0, +2002, 2346, 0, +2158, 2481, 0, +2306, 2616, 0, +2451, 2750, 0, +2592, 2883, 0, +2731, 3016, 0, +2868, 3150, 0, +3003, 3282, 0, +3138, 3414, 0, +3272, 3547, 0, +3406, 3679, 0, +3539, 3812, 0, +3672, 3944, 0, +3804, 4076, 0, +3937, 4095, 0, +0, 0, 1696, +0, 0, 1695, +0, 0, 1693, +0, 0, 1691, +0, 0, 1689, +0, 0, 1685, +0, 0, 1681, +313, 0, 1674, +609, 608, 1666, +959, 1056, 1654, +1205, 1333, 1638, +1407, 1550, 1616, +1407, 1616, 1495, +1466, 1771, 1337, +1624, 1919, 1223, +1774, 2062, 1005, +1920, 2203, 217, +2061, 2341, 0, +2201, 2478, 0, +2338, 2613, 0, +2474, 2748, 0, +2609, 2882, 0, +2743, 3015, 0, +2877, 3149, 0, +3010, 3281, 0, +3143, 3414, 0, +3276, 3547, 0, +3409, 3679, 0, +3541, 3812, 0, +3673, 3944, 0, +3805, 4076, 0, +3938, 4095, 0, +1056, 0, 1696, +1066, 0, 1695, +1080, 0, 1693, +1098, 0, 1691, +1120, 0, 1689, +1149, 0, 1685, +1184, 0, 1681, +1228, 0, 1674, +1281, 608, 1666, +1343, 959, 1654, +1414, 1205, 1638, +1495, 1407, 1616, +1585, 1585, 1585, +1682, 1748, 1539, +1787, 1903, 1469, +1897, 2051, 1355, +2012, 2194, 1136, +2131, 2335, 345, +2253, 2473, 0, +2377, 2610, 0, +2503, 2746, 0, +2631, 2880, 0, +2759, 3014, 0, +2889, 3148, 0, +3019, 3280, 0, +3150, 3414, 0, +3281, 3546, 0, +3413, 3679, 0, +3544, 3811, 0, +3676, 3944, 0, +3807, 4076, 0, +3939, 4095, 0, +1557, 0, 1828, +1560, 0, 1828, +1565, 0, 1827, +1571, 0, 1825, +1579, 0, 1823, +1590, 0, 1821, +1604, 0, 1817, +1622, 0, 1813, +1644, 0, 1807, +1673, 740, 1798, +1709, 1090, 1787, +1754, 1337, 1771, +1748, 1539, 1682, +1748, 1627, 1539, +1903, 1885, 1469, +2004, 2051, 1355, +2097, 2194, 1136, +2198, 2335, 345, +2305, 2473, 0, +2417, 2610, 0, +2534, 2746, 0, +2654, 2880, 0, +2777, 3014, 0, +2903, 3148, 0, +3029, 3280, 0, +3158, 3414, 0, +3287, 3546, 0, +3417, 3679, 0, +3547, 3811, 0, +3678, 3944, 0, +3809, 4076, 0, +3941, 4095, 0, +1847, 0, 1961, +1849, 0, 1961, +1851, 0, 1960, +1854, 0, 1959, +1859, 0, 1958, +1865, 0, 1956, +1872, 0, 1953, +1882, 0, 1950, +1895, 0, 1945, +1912, 0, 1939, +1930, 872, 1927, +1919, 1223, 1872, +1903, 1469, 1787, +1903, 1469, 1598, +1903, 1678, 1469, +2051, 1973, 1355, +2191, 2194, 1136, +2274, 2335, 345, +2366, 2473, 0, +2466, 2610, 0, +2572, 2746, 0, +2684, 2880, 0, +2800, 3014, 0, +2920, 3148, 0, +3043, 3280, 0, +3168, 3414, 0, +3294, 3546, 0, +3422, 3679, 0, +3552, 3811, 0, +3681, 3944, 0, +3812, 4076, 0, +3942, 4095, 0, +2069, 0, 2094, +2070, 0, 2093, +2071, 0, 2093, +2073, 0, 2092, +2076, 0, 2091, +2080, 0, 2089, +2085, 0, 2087, +2085, 0, 2079, +2082, 0, 2063, +2077, 0, 2041, +2071, 79, 2010, +2062, 1005, 1965, +2051, 1355, 1897, +2051, 1355, 1756, +2051, 1355, 1453, +2051, 1739, 1355, +2194, 2069, 1136, +2335, 2308, 345, +2438, 2473, 0, +2524, 2610, 0, +2619, 2746, 0, +2721, 2880, 0, +2829, 3014, 0, +2942, 3148, 0, +3060, 3280, 0, +3181, 3414, 0, +3304, 3546, 0, +3430, 3679, 0, +3557, 3811, 0, +3685, 3944, 0, +3814, 4076, 0, +3945, 4095, 0, +2226, 0, 2191, +2226, 0, 2190, +2225, 0, 2188, +2225, 0, 2185, +2224, 0, 2181, +2223, 0, 2176, +2221, 0, 2169, +2220, 0, 2159, +2217, 0, 2146, +2214, 0, 2128, +2209, 0, 2102, +2203, 217, 2066, +2194, 1136, 2012, +2194, 1136, 1906, +2194, 1136, 1711, +2194, 1136, 1137, +2194, 1809, 1136, +2335, 2173, 345, +2473, 2423, 0, +2592, 2610, 0, +2674, 2746, 0, +2766, 2880, 0, +2865, 3014, 0, +2970, 3148, 0, +3082, 3280, 0, +3198, 3414, 0, +3317, 3546, 0, +3440, 3679, 0, +3564, 3811, 0, +3691, 3944, 0, +3819, 4076, 0, +3948, 4095, 0, +2358, 0, 2275, +2358, 0, 2273, +2358, 0, 2271, +2357, 0, 2269, +2357, 0, 2266, +2356, 0, 2262, +2355, 0, 2256, +2353, 0, 2248, +2352, 0, 2237, +2349, 0, 2223, +2346, 0, 2202, +2341, 0, 2173, +2335, 345, 2131, +2335, 345, 2052, +2335, 345, 1919, +2335, 345, 1644, +2335, 970, 345, +2335, 1889, 345, +2473, 2282, 0, +2610, 2543, 0, +2740, 2746, 0, +2820, 2880, 0, +2908, 3014, 0, +3005, 3148, 0, +3109, 3280, 0, +3219, 3414, 0, +3334, 3546, 0, +3453, 3679, 0, +3574, 3811, 0, +3699, 3944, 0, +3824, 4076, 0, +3952, 4095, 0, +2491, 0, 2367, +2491, 0, 2366, +2490, 0, 2364, +2490, 0, 2362, +2489, 0, 2360, +2489, 0, 2356, +2488, 0, 2352, +2487, 0, 2345, +2486, 0, 2336, +2484, 0, 2325, +2481, 0, 2308, +2478, 0, 2285, +2473, 0, 2253, +2473, 0, 2194, +2473, 0, 2100, +2473, 0, 1935, +2473, 0, 1535, +2473, 557, 0, +2473, 1977, 0, +2610, 2396, 0, +2746, 2665, 0, +2880, 2877, 0, +2961, 3014, 0, +3049, 3148, 0, +3144, 3280, 0, +3247, 3414, 0, +3355, 3546, 0, +3469, 3679, 0, +3587, 3811, 0, +3708, 3944, 0, +3832, 4076, 0, +3958, 4095, 0, +2623, 0, 2466, +2623, 0, 2465, +2623, 0, 2464, +2622, 0, 2463, +2622, 0, 2460, +2621, 0, 2458, +2621, 0, 2454, +2620, 0, 2449, +2619, 0, 2442, +2618, 0, 2432, +2616, 0, 2420, +2613, 0, 2402, +2610, 0, 2377, +2610, 0, 2333, +2610, 0, 2266, +2610, 0, 2158, +2610, 0, 1956, +2610, 0, 1330, +2610, 0, 0, +2610, 2073, 0, +2746, 2515, 0, +2880, 2789, 0, +3014, 3004, 0, +3100, 3148, 0, +3186, 3280, 0, +3281, 3414, 0, +3382, 3546, 0, +3490, 3679, 0, +3604, 3811, 0, +3721, 3944, 0, +3841, 4076, 0, +3965, 4095, 0, +2755, 0, 2573, +2755, 0, 2572, +2755, 0, 2571, +2755, 0, 2570, +2755, 0, 2568, +2754, 0, 2566, +2754, 0, 2563, +2753, 0, 2559, +2752, 0, 2553, +2751, 0, 2546, +2750, 0, 2536, +2748, 0, 2522, +2746, 0, 2503, +2746, 0, 2470, +2746, 0, 2422, +2746, 0, 2348, +2746, 0, 2226, +2746, 0, 1983, +2746, 0, 678, +2746, 0, 0, +2746, 2177, 0, +2880, 2636, 0, +3014, 2915, 0, +3148, 3133, 0, +3238, 3280, 0, +3323, 3414, 0, +3416, 3546, 0, +3517, 3679, 0, +3625, 3811, 0, +3737, 3944, 0, +3854, 4076, 0, +3975, 4095, 0, +2887, 0, 2684, +2887, 0, 2684, +2887, 0, 2683, +2887, 0, 2682, +2887, 0, 2681, +2887, 0, 2679, +2886, 0, 2677, +2886, 0, 2673, +2885, 0, 2669, +2885, 0, 2664, +2883, 0, 2656, +2882, 0, 2645, +2880, 0, 2631, +2880, 0, 2606, +2880, 0, 2571, +2880, 0, 2519, +2880, 0, 2439, +2880, 0, 2302, +2880, 0, 2016, +2880, 0, 0, +2880, 0, 0, +2880, 2287, 0, +3014, 2759, 0, +3148, 3043, 0, +3280, 3262, 0, +3374, 3414, 0, +3458, 3546, 0, +3551, 3679, 0, +3652, 3811, 0, +3758, 3944, 0, +3871, 4076, 0, +3988, 4095, 0, +3019, 0, 2800, +3019, 0, 2800, +3019, 0, 2799, +3019, 0, 2798, +3019, 0, 2797, +3019, 0, 2796, +3018, 0, 2794, +3018, 0, 2792, +3018, 0, 2789, +3017, 0, 2784, +3016, 0, 2778, +3015, 0, 2770, +3014, 0, 2759, +3014, 0, 2741, +3014, 0, 2715, +3014, 0, 2678, +3014, 0, 2623, +3014, 0, 2536, +3014, 0, 2388, +3014, 0, 2056, +3014, 0, 0, +3014, 0, 0, +3014, 2401, 0, +3148, 2886, 0, +3280, 3172, 0, +3414, 3393, 0, +3509, 3546, 0, +3593, 3679, 0, +3685, 3811, 0, +3785, 3944, 0, +3891, 4076, 0, +4004, 4095, 0, +3152, 0, 2920, +3152, 0, 2920, +3152, 0, 2919, +3151, 0, 2919, +3151, 0, 2918, +3151, 0, 2917, +3151, 0, 2916, +3151, 0, 2914, +3151, 0, 2911, +3150, 0, 2908, +3150, 0, 2904, +3149, 0, 2898, +3148, 0, 2889, +3148, 0, 2875, +3148, 0, 2856, +3148, 0, 2829, +3148, 0, 2790, +3148, 0, 2733, +3148, 0, 2642, +3148, 0, 2482, +3148, 0, 2106, +3148, 0, 0, +3148, 0, 0, +3148, 2520, 0, +3280, 3013, 0, +3414, 3301, 0, +3546, 3523, 0, +3643, 3679, 0, +3727, 3811, 0, +3819, 3944, 0, +3918, 4076, 0, +4025, 4095, 0, +3284, 0, 3043, +3283, 0, 3042, +3283, 0, 3042, +3283, 0, 3042, +3283, 0, 3041, +3283, 0, 3040, +3283, 0, 3039, +3283, 0, 3038, +3283, 0, 3036, +3282, 0, 3033, +3282, 0, 3030, +3281, 0, 3025, +3280, 0, 3019, +3280, 0, 3009, +3280, 0, 2995, +3280, 0, 2975, +3280, 0, 2947, +3280, 0, 2907, +3280, 0, 2847, +3280, 0, 2752, +3280, 0, 2583, +3280, 0, 2164, +3280, 0, 0, +3280, 0, 0, +3280, 2641, 0, +3414, 3142, 0, +3546, 3432, 0, +3679, 3654, 0, +3777, 3811, 0, +3860, 3944, 0, +3952, 4076, 0, +4051, 4095, 0, +3416, 0, 3168, +3416, 0, 3168, +3416, 0, 3167, +3416, 0, 3167, +3416, 0, 3166, +3416, 0, 3166, +3415, 0, 3165, +3415, 0, 3164, +3415, 0, 3163, +3415, 0, 3161, +3414, 0, 3158, +3414, 0, 3155, +3414, 0, 3150, +3414, 0, 3142, +3414, 0, 3132, +3414, 0, 3117, +3414, 0, 3097, +3414, 0, 3069, +3414, 0, 3027, +3414, 0, 2966, +3414, 0, 2867, +3414, 0, 2691, +3414, 0, 2234, +3414, 0, 0, +3414, 0, 0, +3414, 2765, 0, +3546, 3271, 0, +3679, 3563, 0, +3811, 3785, 0, +3910, 3944, 0, +3993, 4076, 0, +4085, 4095, 0, +3548, 0, 3294, +3548, 0, 3294, +3548, 0, 3294, +3548, 0, 3294, +3548, 0, 3293, +3548, 0, 3293, +3548, 0, 3292, +3548, 0, 3292, +3548, 0, 3291, +3547, 0, 3289, +3547, 0, 3287, +3547, 0, 3285, +3546, 0, 3281, +3546, 0, 3275, +3546, 0, 3268, +3546, 0, 3257, +3546, 0, 3242, +3546, 0, 3221, +3546, 0, 3192, +3546, 0, 3151, +3546, 0, 3087, +3546, 0, 2987, +3546, 0, 2804, +3546, 0, 2311, +3546, 0, 0, +3546, 0, 0, +3546, 2891, 0, +3679, 3401, 0, +3811, 3694, 0, +3944, 3917, 0, +4043, 4076, 0, +4095, 4095, 0, +3680, 0, 3422, +3680, 0, 3422, +3680, 0, 3422, +3680, 0, 3422, +3680, 0, 3422, +3680, 0, 3421, +3680, 0, 3421, +3680, 0, 3420, +3680, 0, 3420, +3680, 0, 3418, +3679, 0, 3417, +3679, 0, 3415, +3679, 0, 3413, +3679, 0, 3408, +3679, 0, 3402, +3679, 0, 3394, +3679, 0, 3384, +3679, 0, 3368, +3679, 0, 3348, +3679, 0, 3318, +3679, 0, 3276, +3679, 0, 3212, +3679, 0, 3110, +3679, 0, 2922, +3679, 0, 2400, +3679, 0, 0, +3679, 0, 0, +3679, 3018, 0, +3811, 3532, 0, +3944, 3825, 0, +4076, 4048, 0, +4095, 4095, 0, +3812, 0, 3552, +3812, 0, 3551, +3812, 0, 3551, +3812, 0, 3551, +3812, 0, 3551, +3812, 0, 3551, +3812, 0, 3550, +3812, 0, 3550, +3812, 0, 3549, +3812, 0, 3548, +3812, 0, 3547, +3812, 0, 3546, +3811, 0, 3544, +3811, 0, 3541, +3811, 0, 3536, +3811, 0, 3530, +3811, 0, 3522, +3811, 0, 3511, +3811, 0, 3496, +3811, 0, 3475, +3811, 0, 3446, +3811, 0, 3403, +3811, 0, 3338, +3811, 0, 3234, +3811, 0, 3043, +3811, 0, 2494, +3811, 0, 0, +3811, 0, 0, +3811, 3147, 0, +3944, 3663, 0, +4076, 3956, 0, +4095, 4095, 0, +3944, 0, 3681, +3944, 0, 3681, +3944, 0, 3681, +3944, 0, 3681, +3944, 0, 3681, +3944, 0, 3681, +3944, 0, 3680, +3944, 0, 3680, +3944, 0, 3680, +3944, 0, 3679, +3944, 0, 3678, +3944, 0, 3677, +3944, 0, 3676, +3944, 0, 3673, +3944, 0, 3670, +3944, 0, 3666, +3944, 0, 3659, +3944, 0, 3651, +3944, 0, 3640, +3944, 0, 3625, +3944, 0, 3604, +3944, 0, 3574, +3944, 0, 3531, +3944, 0, 3466, +3944, 0, 3361, +3944, 0, 3166, +3944, 0, 2596, +3944, 0, 0, +3944, 0, 0, +3944, 3277, 0, +4076, 3794, 0, +4095, 4088, 0, +4076, 0, 3812, +4076, 0, 3811, +4076, 0, 3811, +4076, 0, 3811, +4076, 0, 3811, +4076, 0, 3811, +4076, 0, 3811, +4076, 0, 3810, +4076, 0, 3810, +4076, 0, 3810, +4076, 0, 3809, +4076, 0, 3808, +4076, 0, 3807, +4076, 0, 3805, +4076, 0, 3803, +4076, 0, 3800, +4076, 0, 3795, +4076, 0, 3789, +4076, 0, 3781, +4076, 0, 3770, +4076, 0, 3755, +4076, 0, 3734, +4076, 0, 3703, +4076, 0, 3660, +4076, 0, 3594, +4076, 0, 3488, +4076, 0, 3291, +4076, 0, 2703, +4076, 0, 0, +4076, 0, 0, +4076, 3407, 0, +4095, 3926, 0, +4095, 0, 3942, +4095, 0, 3942, +4095, 0, 3942, +4095, 0, 3942, +4095, 0, 3942, +4095, 0, 3942, +4095, 0, 3942, +4095, 0, 3942, +4095, 0, 3941, +4095, 0, 3941, +4095, 0, 3941, +4095, 0, 3940, +4095, 0, 3939, +4095, 0, 3938, +4095, 0, 3936, +4095, 0, 3934, +4095, 0, 3930, +4095, 0, 3926, +4095, 0, 3920, +4095, 0, 3912, +4095, 0, 3901, +4095, 0, 3885, +4095, 0, 3864, +4095, 0, 3834, +4095, 0, 3790, +4095, 0, 3724, +4095, 0, 3617, +4095, 0, 3419, +4095, 0, 2818, +4095, 0, 0, +4095, 0, 0, +4095, 3538, 0, +0, 1565, 1828, +0, 1572, 1828, +0, 1582, 1828, +0, 1596, 1828, +0, 1612, 1828, +0, 1634, 1828, +0, 1661, 1828, +0, 1696, 1828, +0, 1738, 1828, +0, 1789, 1828, +0, 1828, 1807, +0, 1828, 1716, +0, 1828, 1557, +0, 1828, 1180, +0, 1961, 0, +0, 2094, 0, +907, 2226, 0, +1580, 2358, 0, +1903, 2491, 0, +2138, 2623, 0, +2335, 2755, 0, +2510, 2887, 0, +2672, 3019, 0, +2825, 3152, 0, +2972, 3284, 0, +3115, 3416, 0, +3255, 3548, 0, +3393, 3680, 0, +3530, 3812, 0, +3665, 3944, 0, +3799, 4076, 0, +3933, 4095, 0, +0, 1557, 1828, +0, 1566, 1828, +0, 1576, 1828, +0, 1590, 1828, +0, 1607, 1828, +0, 1629, 1828, +0, 1656, 1828, +0, 1691, 1828, +0, 1733, 1828, +0, 1785, 1828, +0, 1828, 1810, +0, 1828, 1719, +0, 1828, 1560, +0, 1828, 1188, +0, 1961, 0, +0, 2093, 0, +944, 2226, 0, +1589, 2358, 0, +1907, 2491, 0, +2141, 2623, 0, +2337, 2755, 0, +2511, 2887, 0, +2672, 3019, 0, +2825, 3152, 0, +2972, 3283, 0, +3115, 3416, 0, +3255, 3548, 0, +3393, 3680, 0, +3530, 3812, 0, +3665, 3944, 0, +3799, 4076, 0, +3933, 4095, 0, +0, 1547, 1828, +0, 1556, 1828, +0, 1568, 1827, +0, 1582, 1827, +0, 1599, 1827, +0, 1621, 1827, +0, 1650, 1827, +0, 1684, 1827, +0, 1727, 1827, +0, 1779, 1827, +0, 1827, 1812, +0, 1827, 1722, +0, 1827, 1565, +0, 1827, 1198, +0, 1960, 0, +0, 2093, 0, +990, 2225, 0, +1600, 2358, 0, +1913, 2490, 0, +2144, 2623, 0, +2339, 2755, 0, +2513, 2887, 0, +2673, 3019, 0, +2826, 3152, 0, +2973, 3283, 0, +3115, 3416, 0, +3256, 3548, 0, +3393, 3680, 0, +3530, 3812, 0, +3665, 3944, 0, +3799, 4076, 0, +3933, 4095, 0, +0, 1532, 1828, +0, 1542, 1828, +0, 1554, 1827, +0, 1571, 1825, +0, 1588, 1825, +0, 1611, 1825, +0, 1640, 1825, +0, 1676, 1825, +0, 1720, 1825, +0, 1772, 1825, +0, 1825, 1816, +0, 1825, 1727, +0, 1825, 1571, +0, 1825, 1212, +0, 1959, 0, +0, 2092, 0, +1044, 2225, 0, +1615, 2357, 0, +1920, 2490, 0, +2149, 2622, 0, +2342, 2755, 0, +2515, 2887, 0, +2675, 3019, 0, +2827, 3151, 0, +2973, 3283, 0, +3116, 3416, 0, +3256, 3548, 0, +3394, 3680, 0, +3530, 3812, 0, +3665, 3944, 0, +3799, 4076, 0, +3933, 4095, 0, +0, 1512, 1828, +0, 1522, 1828, +0, 1535, 1827, +0, 1552, 1825, +0, 1574, 1823, +0, 1598, 1823, +0, 1627, 1823, +0, 1664, 1823, +0, 1709, 1823, +0, 1763, 1823, +0, 1823, 1821, +0, 1823, 1732, +0, 1823, 1579, +0, 1823, 1230, +0, 1958, 0, +0, 2091, 0, +1108, 2224, 0, +1634, 2357, 0, +1930, 2489, 0, +2155, 2622, 0, +2346, 2755, 0, +2517, 2887, 0, +2677, 3019, 0, +2829, 3151, 0, +2974, 3283, 0, +3117, 3416, 0, +3256, 3548, 0, +3394, 3680, 0, +3530, 3812, 0, +3665, 3944, 0, +3800, 4076, 0, +3934, 4095, 0, +0, 1484, 1828, +0, 1494, 1828, +0, 1508, 1827, +0, 1526, 1825, +0, 1549, 1823, +0, 1579, 1821, +0, 1609, 1821, +0, 1648, 1821, +0, 1694, 1821, +0, 1750, 1821, +0, 1815, 1821, +0, 1821, 1740, +0, 1821, 1590, +0, 1821, 1253, +0, 1956, 0, +0, 2089, 0, +1181, 2223, 0, +1659, 2356, 0, +1943, 2489, 0, +2163, 2621, 0, +2351, 2754, 0, +2521, 2887, 0, +2679, 3019, 0, +2830, 3151, 0, +2976, 3283, 0, +3118, 3416, 0, +3257, 3548, 0, +3395, 3680, 0, +3531, 3812, 0, +3666, 3944, 0, +3800, 4076, 0, +3934, 4095, 0, +0, 1442, 1828, +0, 1454, 1828, +0, 1469, 1827, +0, 1489, 1825, +0, 1514, 1823, +0, 1545, 1821, +0, 1585, 1817, +0, 1625, 1817, +0, 1673, 1817, +0, 1732, 1817, +0, 1799, 1817, +0, 1817, 1750, +0, 1817, 1604, +0, 1817, 1281, +0, 1953, 0, +0, 2087, 0, +1264, 2221, 0, +1689, 2355, 0, +1960, 2488, 0, +2173, 2621, 0, +2358, 2754, 0, +2526, 2886, 0, +2683, 3018, 0, +2833, 3151, 0, +2977, 3283, 0, +3119, 3415, 0, +3258, 3548, 0, +3395, 3680, 0, +3531, 3812, 0, +3666, 3944, 0, +3800, 4076, 0, +3934, 4095, 0, +0, 1381, 1828, +0, 1394, 1828, +0, 1412, 1827, +0, 1434, 1825, +0, 1462, 1823, +0, 1497, 1821, +0, 1540, 1817, +0, 1592, 1813, +0, 1644, 1813, +0, 1706, 1813, +0, 1777, 1813, +0, 1813, 1763, +0, 1813, 1622, +0, 1813, 1317, +0, 1950, 0, +10, 2085, 0, +1355, 2220, 0, +1727, 2353, 0, +1981, 2487, 0, +2187, 2620, 0, +2367, 2753, 0, +2532, 2886, 0, +2687, 3018, 0, +2836, 3151, 0, +2980, 3283, 0, +3121, 3415, 0, +3259, 3548, 0, +3396, 3680, 0, +3532, 3812, 0, +3666, 3944, 0, +3801, 4076, 0, +3934, 4095, 0, +0, 1283, 1828, +0, 1300, 1828, +0, 1321, 1827, +0, 1348, 1825, +0, 1382, 1823, +0, 1423, 1821, +0, 1474, 1817, +0, 1533, 1813, +0, 1602, 1807, +0, 1669, 1807, +0, 1746, 1807, +0, 1807, 1780, +0, 1807, 1644, +0, 1807, 1360, +0, 1945, 37, +800, 2082, 0, +1454, 2217, 0, +1773, 2352, 0, +2008, 2486, 0, +2204, 2619, 0, +2379, 2752, 0, +2540, 2885, 0, +2693, 3018, 0, +2840, 3151, 0, +2983, 3283, 0, +3123, 3415, 0, +3261, 3548, 0, +3397, 3680, 0, +3533, 3812, 0, +3667, 3944, 0, +3801, 4076, 0, +3935, 4095, 0, +0, 1106, 1828, +0, 1131, 1828, +0, 1161, 1827, +0, 1199, 1825, +0, 1245, 1823, +0, 1301, 1821, +0, 1366, 1817, +0, 1440, 1813, +0, 1523, 1807, +740, 1615, 1798, +740, 1701, 1798, +740, 1795, 1798, +740, 1798, 1673, +740, 1798, 1413, +0, 1939, 573, +1138, 2077, 0, +1560, 2214, 0, +1829, 2349, 0, +2042, 2484, 0, +2226, 2618, 0, +2394, 2751, 0, +2551, 2885, 0, +2701, 3017, 0, +2846, 3150, 0, +2987, 3282, 0, +3126, 3415, 0, +3263, 3547, 0, +3399, 3680, 0, +3534, 3812, 0, +3668, 3944, 0, +3802, 4076, 0, +3935, 4095, 0, +0, 650, 1828, +0, 713, 1828, +0, 786, 1827, +0, 869, 1825, +0, 960, 1823, +0, 1059, 1821, +0, 1164, 1817, +0, 1275, 1813, +0, 1391, 1807, +740, 1510, 1798, +1090, 1633, 1787, +1090, 1740, 1787, +1090, 1787, 1709, +1090, 1787, 1475, +873, 1930, 872, +1379, 2071, 79, +1671, 2209, 0, +1894, 2346, 0, +2084, 2481, 0, +2255, 2616, 0, +2414, 2750, 0, +2565, 2883, 0, +2711, 3016, 0, +2853, 3150, 0, +2992, 3282, 0, +3130, 3414, 0, +3266, 3547, 0, +3401, 3679, 0, +3536, 3812, 0, +3669, 3944, 0, +3803, 4076, 0, +3936, 4095, 0, +0, 0, 1828, +0, 0, 1828, +0, 0, 1827, +0, 0, 1825, +0, 0, 1823, +0, 0, 1821, +0, 536, 1817, +0, 874, 1813, +0, 1115, 1807, +740, 1315, 1798, +1090, 1491, 1787, +1337, 1654, 1771, +1337, 1771, 1754, +1337, 1771, 1546, +1321, 1919, 1223, +1579, 2062, 1005, +1787, 2203, 217, +1968, 2341, 0, +2134, 2478, 0, +2290, 2613, 0, +2439, 2748, 0, +2583, 2882, 0, +2724, 3015, 0, +2863, 3149, 0, +2999, 3281, 0, +3135, 3414, 0, +3270, 3547, 0, +3404, 3679, 0, +3538, 3812, 0, +3671, 3944, 0, +3804, 4076, 0, +3937, 4095, 0, +0, 0, 1828, +0, 0, 1828, +0, 0, 1827, +0, 0, 1825, +0, 0, 1823, +0, 0, 1821, +0, 0, 1817, +0, 0, 1813, +438, 0, 1807, +740, 742, 1798, +1090, 1189, 1787, +1337, 1466, 1771, +1539, 1682, 1748, +1539, 1748, 1627, +1598, 1903, 1469, +1756, 2051, 1355, +1906, 2194, 1136, +2052, 2335, 345, +2194, 2473, 0, +2333, 2610, 0, +2470, 2746, 0, +2606, 2880, 0, +2741, 3014, 0, +2875, 3148, 0, +3009, 3280, 0, +3142, 3414, 0, +3275, 3546, 0, +3408, 3679, 0, +3541, 3811, 0, +3673, 3944, 0, +3805, 4076, 0, +3938, 4095, 0, +1180, 0, 1828, +1188, 0, 1828, +1198, 0, 1827, +1212, 0, 1825, +1230, 0, 1823, +1253, 0, 1821, +1281, 0, 1817, +1317, 0, 1813, +1360, 0, 1807, +1413, 740, 1798, +1475, 1090, 1787, +1546, 1337, 1771, +1627, 1539, 1748, +1717, 1717, 1717, +1814, 1880, 1671, +1919, 2035, 1601, +2029, 2183, 1487, +2144, 2326, 1269, +2263, 2467, 477, +2385, 2605, 0, +2509, 2742, 0, +2636, 2878, 0, +2763, 3012, 0, +2892, 3146, 0, +3021, 3280, 0, +3151, 3413, 0, +3282, 3546, 0, +3413, 3678, 0, +3545, 3811, 0, +3676, 3943, 0, +3808, 4076, 0, +3940, 4095, 0, +1686, 0, 1961, +1689, 0, 1961, +1692, 0, 1960, +1697, 0, 1959, +1703, 0, 1958, +1711, 0, 1956, +1722, 0, 1953, +1736, 0, 1950, +1754, 0, 1945, +1776, 0, 1939, +1805, 872, 1930, +1841, 1223, 1919, +1885, 1469, 1903, +1880, 1671, 1814, +1880, 1759, 1671, +2035, 2017, 1601, +2136, 2183, 1487, +2229, 2326, 1269, +2330, 2467, 477, +2437, 2605, 0, +2550, 2742, 0, +2666, 2878, 0, +2786, 3012, 0, +2910, 3146, 0, +3034, 3280, 0, +3162, 3413, 0, +3290, 3546, 0, +3419, 3678, 0, +3549, 3811, 0, +3679, 3943, 0, +3810, 4076, 0, +3941, 4095, 0, +1977, 0, 2094, +1979, 0, 2093, +1981, 0, 2093, +1983, 0, 2092, +1986, 0, 2091, +1991, 0, 2089, +1996, 0, 2087, +2004, 0, 2085, +2014, 0, 2082, +2027, 0, 2077, +2044, 79, 2071, +2062, 1005, 2059, +2051, 1355, 2004, +2035, 1601, 1919, +2035, 1601, 1730, +2035, 1811, 1601, +2183, 2105, 1487, +2323, 2326, 1269, +2407, 2467, 477, +2498, 2605, 0, +2598, 2742, 0, +2704, 2878, 0, +2816, 3012, 0, +2932, 3146, 0, +3052, 3280, 0, +3175, 3413, 0, +3300, 3546, 0, +3426, 3678, 0, +3554, 3811, 0, +3683, 3943, 0, +3813, 4076, 0, +3944, 4095, 0, +2200, 0, 2226, +2201, 0, 2226, +2202, 0, 2225, +2203, 0, 2225, +2206, 0, 2224, +2208, 0, 2223, +2212, 0, 2221, +2217, 0, 2220, +2217, 0, 2211, +2214, 0, 2195, +2209, 0, 2174, +2203, 217, 2142, +2194, 1136, 2097, +2183, 1487, 2029, +2183, 1487, 1888, +2183, 1487, 1585, +2183, 1871, 1487, +2326, 2202, 1269, +2467, 2440, 477, +2570, 2605, 0, +2656, 2742, 0, +2751, 2878, 0, +2853, 3012, 0, +2961, 3146, 0, +3074, 3280, 0, +3192, 3413, 0, +3313, 3546, 0, +3436, 3678, 0, +3562, 3811, 0, +3689, 3943, 0, +3817, 4076, 0, +3947, 4095, 0, +2358, 0, 2325, +2358, 0, 2324, +2358, 0, 2322, +2357, 0, 2320, +2357, 0, 2317, +2356, 0, 2313, +2355, 0, 2308, +2353, 0, 2301, +2352, 0, 2291, +2349, 0, 2278, +2346, 0, 2260, +2341, 0, 2234, +2335, 345, 2198, +2326, 1269, 2144, +2326, 1269, 2038, +2326, 1269, 1843, +2326, 1269, 1270, +2326, 1941, 1269, +2467, 2305, 477, +2605, 2556, 0, +2724, 2742, 0, +2807, 2878, 0, +2898, 3012, 0, +2997, 3146, 0, +3102, 3280, 0, +3214, 3413, 0, +3330, 3546, 0, +3449, 3678, 0, +3572, 3811, 0, +3697, 3943, 0, +3823, 4076, 0, +3951, 4095, 0, +2491, 0, 2408, +2491, 0, 2407, +2490, 0, 2406, +2490, 0, 2404, +2489, 0, 2401, +2489, 0, 2398, +2488, 0, 2394, +2487, 0, 2388, +2486, 0, 2380, +2484, 0, 2369, +2481, 0, 2355, +2478, 0, 2334, +2473, 0, 2305, +2467, 477, 2263, +2467, 477, 2184, +2467, 477, 2051, +2467, 477, 1776, +2467, 1099, 477, +2467, 2021, 477, +2605, 2414, 0, +2742, 2675, 0, +2872, 2878, 0, +2952, 3012, 0, +3041, 3146, 0, +3138, 3280, 0, +3242, 3413, 0, +3351, 3546, 0, +3466, 3678, 0, +3585, 3811, 0, +3706, 3943, 0, +3830, 4076, 0, +3957, 4095, 0, +2623, 0, 2500, +2623, 0, 2499, +2623, 0, 2498, +2622, 0, 2496, +2622, 0, 2494, +2621, 0, 2492, +2621, 0, 2488, +2620, 0, 2483, +2619, 0, 2477, +2618, 0, 2469, +2616, 0, 2456, +2613, 0, 2440, +2610, 0, 2417, +2605, 0, 2385, +2605, 0, 2326, +2605, 0, 2233, +2605, 0, 2067, +2605, 0, 1667, +2605, 705, 0, +2605, 2109, 0, +2742, 2529, 0, +2878, 2797, 0, +3012, 3009, 0, +3093, 3146, 0, +3180, 3280, 0, +3276, 3413, 0, +3379, 3546, 0, +3488, 3678, 0, +3601, 3811, 0, +3719, 3943, 0, +3840, 4076, 0, +3964, 4095, 0, +2755, 0, 2599, +2755, 0, 2598, +2755, 0, 2598, +2755, 0, 2596, +2755, 0, 2595, +2754, 0, 2593, +2754, 0, 2590, +2753, 0, 2586, +2752, 0, 2581, +2751, 0, 2574, +2750, 0, 2565, +2748, 0, 2552, +2746, 0, 2534, +2742, 0, 2509, +2742, 0, 2465, +2742, 0, 2398, +2742, 0, 2291, +2742, 0, 2089, +2742, 0, 1463, +2742, 0, 0, +2742, 2206, 0, +2878, 2647, 0, +3012, 2921, 0, +3146, 3137, 0, +3233, 3280, 0, +3319, 3413, 0, +3413, 3546, 0, +3515, 3678, 0, +3622, 3811, 0, +3736, 3943, 0, +3853, 4076, 0, +3974, 4095, 0, +2887, 0, 2705, +2887, 0, 2705, +2887, 0, 2704, +2887, 0, 2703, +2887, 0, 2702, +2887, 0, 2700, +2886, 0, 2698, +2886, 0, 2695, +2885, 0, 2691, +2885, 0, 2685, +2883, 0, 2678, +2882, 0, 2668, +2880, 0, 2654, +2878, 0, 2636, +2878, 0, 2602, +2878, 0, 2554, +2878, 0, 2480, +2878, 0, 2358, +2878, 0, 2115, +2878, 0, 817, +2878, 0, 0, +2878, 2309, 0, +3012, 2767, 0, +3146, 3047, 0, +3280, 3265, 0, +3370, 3413, 0, +3455, 3546, 0, +3548, 3678, 0, +3650, 3811, 0, +3757, 3943, 0, +3869, 4076, 0, +3986, 4095, 0, +3019, 0, 2816, +3019, 0, 2816, +3019, 0, 2816, +3019, 0, 2815, +3019, 0, 2814, +3019, 0, 2813, +3018, 0, 2811, +3018, 0, 2808, +3018, 0, 2805, +3017, 0, 2801, +3016, 0, 2796, +3015, 0, 2788, +3014, 0, 2777, +3012, 0, 2763, +3012, 0, 2738, +3012, 0, 2703, +3012, 0, 2651, +3012, 0, 2570, +3012, 0, 2434, +3012, 0, 2148, +3012, 0, 0, +3012, 0, 0, +3012, 2419, 0, +3146, 2892, 0, +3280, 3175, 0, +3413, 3395, 0, +3506, 3546, 0, +3590, 3678, 0, +3683, 3811, 0, +3784, 3943, 0, +3890, 4076, 0, +4003, 4095, 0, +3152, 0, 2933, +3152, 0, 2932, +3152, 0, 2932, +3151, 0, 2932, +3151, 0, 2931, +3151, 0, 2930, +3151, 0, 2928, +3151, 0, 2927, +3151, 0, 2924, +3150, 0, 2921, +3150, 0, 2917, +3149, 0, 2911, +3148, 0, 2903, +3146, 0, 2892, +3146, 0, 2873, +3146, 0, 2847, +3146, 0, 2810, +3146, 0, 2755, +3146, 0, 2669, +3146, 0, 2521, +3146, 0, 2189, +3146, 0, 0, +3146, 0, 0, +3146, 2533, 0, +3280, 3017, 0, +3413, 3304, 0, +3546, 3525, 0, +3641, 3678, 0, +3725, 3811, 0, +3817, 3943, 0, +3917, 4076, 0, +4024, 4095, 0, +3284, 0, 3052, +3283, 0, 3052, +3283, 0, 3052, +3283, 0, 3051, +3283, 0, 3051, +3283, 0, 3050, +3283, 0, 3049, +3283, 0, 3047, +3283, 0, 3046, +3282, 0, 3043, +3282, 0, 3040, +3281, 0, 3035, +3280, 0, 3029, +3280, 0, 3021, +3280, 0, 3007, +3280, 0, 2988, +3280, 0, 2961, +3280, 0, 2922, +3280, 0, 2865, +3280, 0, 2773, +3280, 0, 2613, +3280, 0, 2237, +3280, 0, 0, +3280, 0, 0, +3280, 2651, 0, +3413, 3145, 0, +3546, 3434, 0, +3678, 3655, 0, +3775, 3811, 0, +3859, 3943, 0, +3950, 4076, 0, +4051, 4095, 0, +3416, 0, 3175, +3416, 0, 3175, +3416, 0, 3175, +3416, 0, 3174, +3416, 0, 3174, +3416, 0, 3173, +3415, 0, 3173, +3415, 0, 3171, +3415, 0, 3170, +3415, 0, 3168, +3414, 0, 3165, +3414, 0, 3162, +3414, 0, 3158, +3413, 0, 3151, +3413, 0, 3141, +3413, 0, 3127, +3413, 0, 3107, +3413, 0, 3079, +3413, 0, 3039, +3413, 0, 2979, +3413, 0, 2884, +3413, 0, 2715, +3413, 0, 2298, +3413, 0, 0, +3413, 0, 0, +3413, 2773, 0, +3546, 3274, 0, +3678, 3564, 0, +3811, 3786, 0, +3909, 3943, 0, +3992, 4076, 0, +4084, 4095, 0, +3548, 0, 3300, +3548, 0, 3300, +3548, 0, 3300, +3548, 0, 3299, +3548, 0, 3299, +3548, 0, 3299, +3548, 0, 3298, +3548, 0, 3297, +3548, 0, 3296, +3547, 0, 3295, +3547, 0, 3293, +3547, 0, 3290, +3546, 0, 3287, +3546, 0, 3282, +3546, 0, 3275, +3546, 0, 3264, +3546, 0, 3249, +3546, 0, 3229, +3546, 0, 3201, +3546, 0, 3160, +3546, 0, 3098, +3546, 0, 3000, +3546, 0, 2824, +3546, 0, 2365, +3546, 0, 0, +3546, 0, 0, +3546, 2897, 0, +3678, 3403, 0, +3811, 3695, 0, +3943, 3917, 0, +4042, 4076, 0, +4095, 4095, 0, +3680, 0, 3427, +3680, 0, 3426, +3680, 0, 3426, +3680, 0, 3426, +3680, 0, 3426, +3680, 0, 3426, +3680, 0, 3425, +3680, 0, 3425, +3680, 0, 3424, +3680, 0, 3423, +3679, 0, 3421, +3679, 0, 3419, +3679, 0, 3417, +3678, 0, 3413, +3678, 0, 3407, +3678, 0, 3400, +3678, 0, 3389, +3678, 0, 3374, +3678, 0, 3354, +3678, 0, 3325, +3678, 0, 3282, +3678, 0, 3220, +3678, 0, 3119, +3678, 0, 2936, +3678, 0, 2445, +3678, 0, 0, +3678, 0, 0, +3678, 3023, 0, +3811, 3534, 0, +3943, 3826, 0, +4076, 4049, 0, +4095, 4095, 0, +3812, 0, 3554, +3812, 0, 3554, +3812, 0, 3554, +3812, 0, 3554, +3812, 0, 3554, +3812, 0, 3554, +3812, 0, 3553, +3812, 0, 3553, +3812, 0, 3552, +3812, 0, 3552, +3812, 0, 3551, +3812, 0, 3549, +3811, 0, 3547, +3811, 0, 3545, +3811, 0, 3540, +3811, 0, 3534, +3811, 0, 3526, +3811, 0, 3516, +3811, 0, 3501, +3811, 0, 3480, +3811, 0, 3450, +3811, 0, 3408, +3811, 0, 3344, +3811, 0, 3241, +3811, 0, 3054, +3811, 0, 2531, +3811, 0, 0, +3811, 0, 0, +3811, 3151, 0, +3943, 3664, 0, +4076, 3957, 0, +4095, 4095, 0, +3944, 0, 3683, +3944, 0, 3683, +3944, 0, 3683, +3944, 0, 3683, +3944, 0, 3683, +3944, 0, 3683, +3944, 0, 3683, +3944, 0, 3682, +3944, 0, 3682, +3944, 0, 3681, +3944, 0, 3680, +3944, 0, 3679, +3944, 0, 3678, +3943, 0, 3676, +3943, 0, 3673, +3943, 0, 3668, +3943, 0, 3662, +3943, 0, 3655, +3943, 0, 3644, +3943, 0, 3628, +3943, 0, 3607, +3943, 0, 3578, +3943, 0, 3535, +3943, 0, 3470, +3943, 0, 3366, +3943, 0, 3175, +3943, 0, 2625, +3943, 0, 0, +3943, 0, 0, +3943, 3279, 0, +4076, 3795, 0, +4095, 4089, 0, +4076, 0, 3813, +4076, 0, 3813, +4076, 0, 3813, +4076, 0, 3813, +4076, 0, 3813, +4076, 0, 3813, +4076, 0, 3812, +4076, 0, 3812, +4076, 0, 3812, +4076, 0, 3812, +4076, 0, 3811, +4076, 0, 3810, +4076, 0, 3809, +4076, 0, 3808, +4076, 0, 3805, +4076, 0, 3802, +4076, 0, 3798, +4076, 0, 3792, +4076, 0, 3784, +4076, 0, 3773, +4076, 0, 3757, +4076, 0, 3736, +4076, 0, 3706, +4076, 0, 3663, +4076, 0, 3597, +4076, 0, 3492, +4076, 0, 3297, +4076, 0, 2726, +4076, 0, 0, +4076, 0, 0, +4076, 3409, 0, +4095, 3927, 0, +4095, 0, 3944, +4095, 0, 3944, +4095, 0, 3944, +4095, 0, 3944, +4095, 0, 3944, +4095, 0, 3944, +4095, 0, 3943, +4095, 0, 3943, +4095, 0, 3943, +4095, 0, 3943, +4095, 0, 3942, +4095, 0, 3941, +4095, 0, 3941, +4095, 0, 3940, +4095, 0, 3938, +4095, 0, 3935, +4095, 0, 3932, +4095, 0, 3927, +4095, 0, 3922, +4095, 0, 3913, +4095, 0, 3903, +4095, 0, 3887, +4095, 0, 3866, +4095, 0, 3836, +4095, 0, 3792, +4095, 0, 3727, +4095, 0, 3621, +4095, 0, 3424, +4095, 0, 2837, +4095, 0, 0, +4095, 0, 0, +4095, 3539, 0, +0, 1696, 1961, +0, 1702, 1961, +0, 1709, 1961, +0, 1719, 1961, +0, 1732, 1961, +0, 1749, 1961, +0, 1770, 1961, +0, 1797, 1961, +0, 1831, 1961, +0, 1873, 1961, +0, 1923, 1961, +0, 1961, 1938, +0, 1961, 1847, +0, 1961, 1686, +0, 1961, 1306, +0, 2094, 0, +0, 2226, 0, +1009, 2358, 0, +1706, 2491, 0, +2032, 2623, 0, +2269, 2755, 0, +2466, 2887, 0, +2641, 3019, 0, +2803, 3152, 0, +2956, 3284, 0, +3104, 3416, 0, +3247, 3548, 0, +3387, 3680, 0, +3525, 3812, 0, +3661, 3944, 0, +3797, 4076, 0, +3932, 4095, 0, +0, 1690, 1961, +0, 1697, 1961, +0, 1705, 1961, +0, 1715, 1961, +0, 1728, 1961, +0, 1745, 1961, +0, 1766, 1961, +0, 1793, 1961, +0, 1828, 1961, +0, 1870, 1961, +0, 1920, 1961, +0, 1961, 1940, +0, 1961, 1849, +0, 1961, 1689, +0, 1961, 1312, +0, 2093, 0, +0, 2226, 0, +1039, 2358, 0, +1713, 2491, 0, +2035, 2623, 0, +2271, 2755, 0, +2467, 2887, 0, +2642, 3019, 0, +2804, 3152, 0, +2957, 3283, 0, +3104, 3416, 0, +3247, 3548, 0, +3387, 3680, 0, +3525, 3812, 0, +3662, 3944, 0, +3797, 4076, 0, +3932, 4095, 0, +0, 1682, 1961, +0, 1689, 1961, +0, 1699, 1960, +0, 1708, 1960, +0, 1722, 1960, +0, 1739, 1960, +0, 1761, 1960, +0, 1789, 1960, +0, 1823, 1960, +0, 1865, 1960, +0, 1917, 1960, +0, 1960, 1941, +0, 1960, 1851, +0, 1960, 1692, +0, 1960, 1320, +0, 2093, 0, +0, 2225, 0, +1076, 2358, 0, +1722, 2490, 0, +2039, 2623, 0, +2274, 2755, 0, +2469, 2887, 0, +2643, 3019, 0, +2805, 3152, 0, +2957, 3283, 0, +3104, 3416, 0, +3247, 3548, 0, +3387, 3680, 0, +3525, 3812, 0, +3662, 3944, 0, +3797, 4076, 0, +3932, 4095, 0, +0, 1672, 1961, +0, 1679, 1961, +0, 1688, 1960, +0, 1700, 1959, +0, 1714, 1959, +0, 1731, 1959, +0, 1754, 1959, +0, 1781, 1959, +0, 1817, 1959, +0, 1860, 1959, +0, 1911, 1959, +0, 1959, 1944, +0, 1959, 1854, +0, 1959, 1697, +0, 1959, 1331, +0, 2092, 0, +0, 2225, 0, +1122, 2357, 0, +1733, 2490, 0, +2045, 2622, 0, +2277, 2755, 0, +2471, 2887, 0, +2645, 3019, 0, +2806, 3151, 0, +2958, 3283, 0, +3105, 3416, 0, +3248, 3548, 0, +3388, 3680, 0, +3526, 3812, 0, +3662, 3944, 0, +3797, 4076, 0, +3932, 4095, 0, +0, 1657, 1961, +0, 1664, 1961, +0, 1674, 1960, +0, 1686, 1959, +0, 1703, 1958, +0, 1721, 1958, +0, 1743, 1958, +0, 1772, 1958, +0, 1808, 1958, +0, 1852, 1958, +0, 1905, 1958, +0, 1958, 1948, +0, 1958, 1859, +0, 1958, 1703, +0, 1958, 1344, +0, 2091, 0, +0, 2224, 0, +1176, 2357, 0, +1748, 2489, 0, +2052, 2622, 0, +2281, 2755, 0, +2474, 2887, 0, +2647, 3019, 0, +2807, 3151, 0, +2959, 3283, 0, +3106, 3416, 0, +3248, 3548, 0, +3388, 3680, 0, +3526, 3812, 0, +3662, 3944, 0, +3797, 4076, 0, +3932, 4095, 0, +0, 1636, 1961, +0, 1644, 1961, +0, 1654, 1960, +0, 1667, 1959, +0, 1684, 1958, +0, 1706, 1956, +0, 1730, 1956, +0, 1759, 1956, +0, 1796, 1956, +0, 1841, 1956, +0, 1895, 1956, +0, 1956, 1953, +0, 1956, 1865, +0, 1956, 1711, +0, 1956, 1362, +0, 2089, 0, +0, 2223, 0, +1240, 2356, 0, +1767, 2489, 0, +2062, 2621, 0, +2287, 2754, 0, +2478, 2887, 0, +2649, 3019, 0, +2809, 3151, 0, +2960, 3283, 0, +3106, 3416, 0, +3249, 3548, 0, +3388, 3680, 0, +3526, 3812, 0, +3662, 3944, 0, +3797, 4076, 0, +3932, 4095, 0, +0, 1607, 1961, +0, 1615, 1961, +0, 1626, 1960, +0, 1640, 1959, +0, 1658, 1958, +0, 1681, 1956, +0, 1711, 1953, +0, 1742, 1953, +0, 1779, 1953, +0, 1826, 1953, +0, 1882, 1953, +0, 1947, 1953, +0, 1953, 1872, +0, 1953, 1722, +0, 1953, 1385, +0, 2087, 0, +0, 2221, 0, +1313, 2355, 0, +1791, 2488, 0, +2075, 2621, 0, +2295, 2754, 0, +2483, 2886, 0, +2653, 3018, 0, +2812, 3151, 0, +2962, 3283, 0, +3108, 3415, 0, +3250, 3548, 0, +3389, 3680, 0, +3527, 3812, 0, +3663, 3944, 0, +3798, 4076, 0, +3932, 4095, 0, +0, 1565, 1961, +0, 1574, 1961, +0, 1586, 1960, +0, 1601, 1959, +0, 1621, 1958, +0, 1646, 1956, +0, 1678, 1953, +0, 1716, 1950, +0, 1757, 1950, +0, 1806, 1950, +0, 1864, 1950, +0, 1931, 1950, +0, 1950, 1882, +0, 1950, 1736, +0, 1950, 1413, +0, 2085, 0, +0, 2220, 0, +1396, 2353, 0, +1822, 2487, 0, +2092, 2620, 0, +2305, 2753, 0, +2490, 2886, 0, +2658, 3018, 0, +2815, 3151, 0, +2965, 3283, 0, +3110, 3415, 0, +3251, 3548, 0, +3390, 3680, 0, +3528, 3812, 0, +3663, 3944, 0, +3798, 4076, 0, +3932, 4095, 0, +0, 1503, 1961, +0, 1513, 1961, +0, 1526, 1960, +0, 1544, 1959, +0, 1566, 1958, +0, 1594, 1956, +0, 1629, 1953, +0, 1672, 1950, +0, 1724, 1945, +0, 1776, 1945, +0, 1838, 1945, +0, 1909, 1945, +0, 1945, 1895, +0, 1945, 1754, +0, 1945, 1449, +0, 2082, 0, +140, 2217, 0, +1487, 2352, 0, +1859, 2486, 0, +2113, 2619, 0, +2319, 2752, 0, +2499, 2885, 0, +2664, 3018, 0, +2819, 3151, 0, +2968, 3283, 0, +3112, 3415, 0, +3253, 3548, 0, +3392, 3680, 0, +3528, 3812, 0, +3664, 3944, 0, +3798, 4076, 0, +3933, 4095, 0, +0, 1402, 1961, +0, 1415, 1961, +0, 1431, 1960, +0, 1453, 1959, +0, 1480, 1958, +0, 1514, 1956, +0, 1555, 1953, +0, 1606, 1950, +0, 1665, 1945, +0, 1734, 1939, +0, 1801, 1939, +0, 1878, 1939, +0, 1939, 1912, +0, 1939, 1776, +0, 1939, 1492, +0, 2077, 173, +932, 2214, 0, +1586, 2349, 0, +1906, 2484, 0, +2140, 2618, 0, +2336, 2751, 0, +2511, 2885, 0, +2672, 3017, 0, +2825, 3150, 0, +2972, 3282, 0, +3115, 3415, 0, +3255, 3547, 0, +3393, 3680, 0, +3530, 3812, 0, +3665, 3944, 0, +3799, 4076, 0, +3933, 4095, 0, +0, 1220, 1961, +0, 1238, 1961, +0, 1263, 1960, +0, 1294, 1959, +0, 1332, 1958, +0, 1378, 1956, +0, 1433, 1953, +0, 1498, 1950, +0, 1572, 1945, +0, 1655, 1939, +872, 1748, 1930, +872, 1833, 1930, +872, 1927, 1930, +872, 1930, 1805, +872, 1930, 1545, +79, 2071, 706, +1270, 2209, 0, +1692, 2346, 0, +1961, 2481, 0, +2174, 2616, 0, +2359, 2750, 0, +2526, 2883, 0, +2683, 3016, 0, +2833, 3150, 0, +2977, 3282, 0, +3119, 3414, 0, +3258, 3547, 0, +3395, 3679, 0, +3531, 3812, 0, +3666, 3944, 0, +3800, 4076, 0, +3934, 4095, 0, +0, 726, 1961, +0, 780, 1961, +0, 844, 1960, +0, 917, 1959, +0, 1000, 1958, +0, 1091, 1956, +0, 1190, 1953, +0, 1295, 1950, +0, 1407, 1945, +0, 1523, 1939, +872, 1642, 1930, +1223, 1765, 1919, +1223, 1872, 1919, +1223, 1919, 1841, +1223, 1919, 1607, +1006, 2062, 1005, +1512, 2203, 217, +1803, 2341, 0, +2026, 2478, 0, +2216, 2613, 0, +2387, 2748, 0, +2546, 2882, 0, +2697, 3015, 0, +2843, 3149, 0, +2985, 3281, 0, +3125, 3414, 0, +3262, 3547, 0, +3398, 3679, 0, +3533, 3812, 0, +3668, 3944, 0, +3801, 4076, 0, +3935, 4095, 0, +0, 0, 1961, +0, 0, 1961, +0, 0, 1960, +0, 0, 1959, +0, 0, 1958, +0, 0, 1956, +0, 0, 1953, +0, 670, 1950, +0, 1007, 1945, +0, 1248, 1939, +872, 1447, 1930, +1223, 1624, 1919, +1469, 1787, 1903, +1469, 1903, 1885, +1469, 1903, 1678, +1453, 2051, 1355, +1711, 2194, 1136, +1919, 2335, 345, +2100, 2473, 0, +2266, 2610, 0, +2422, 2746, 0, +2571, 2880, 0, +2715, 3014, 0, +2856, 3148, 0, +2995, 3280, 0, +3132, 3414, 0, +3268, 3546, 0, +3402, 3679, 0, +3536, 3811, 0, +3670, 3944, 0, +3803, 4076, 0, +3936, 4095, 0, +0, 0, 1961, +0, 0, 1961, +0, 0, 1960, +0, 0, 1959, +0, 0, 1958, +0, 0, 1956, +0, 0, 1953, +0, 0, 1950, +37, 0, 1945, +573, 0, 1939, +872, 873, 1930, +1223, 1321, 1919, +1469, 1598, 1903, +1671, 1814, 1880, +1671, 1880, 1759, +1730, 2035, 1601, +1888, 2183, 1487, +2038, 2326, 1269, +2184, 2467, 477, +2326, 2605, 0, +2465, 2742, 0, +2602, 2878, 0, +2738, 3012, 0, +2873, 3146, 0, +3007, 3280, 0, +3141, 3413, 0, +3275, 3546, 0, +3407, 3678, 0, +3540, 3811, 0, +3673, 3943, 0, +3805, 4076, 0, +3938, 4095, 0, +1306, 0, 1961, +1312, 0, 1961, +1320, 0, 1960, +1331, 0, 1959, +1344, 0, 1958, +1362, 0, 1956, +1385, 0, 1953, +1413, 0, 1950, +1449, 0, 1945, +1492, 0, 1939, +1545, 872, 1930, +1607, 1223, 1919, +1678, 1469, 1903, +1759, 1671, 1880, +1849, 1849, 1849, +1946, 2013, 1803, +2051, 2167, 1733, +2161, 2315, 1619, +2276, 2459, 1401, +2395, 2599, 611, +2517, 2738, 0, +2641, 2874, 0, +2767, 3010, 0, +2895, 3144, 0, +3024, 3278, 0, +3154, 3412, 0, +3284, 3545, 0, +3414, 3678, 0, +3545, 3810, 0, +3677, 3943, 0, +3808, 4075, 0, +3940, 4095, 0, +1816, 0, 2094, +1818, 0, 2093, +1821, 0, 2093, +1824, 0, 2092, +1829, 0, 2091, +1835, 0, 2089, +1843, 0, 2087, +1854, 0, 2085, +1868, 0, 2082, +1886, 0, 2077, +1908, 79, 2071, +1937, 1005, 2062, +1973, 1355, 2051, +2017, 1601, 2035, +2013, 1803, 1946, +2013, 1891, 1803, +2167, 2149, 1733, +2268, 2315, 1619, +2362, 2459, 1401, +2462, 2599, 611, +2569, 2738, 0, +2681, 2874, 0, +2798, 3010, 0, +2919, 3144, 0, +3041, 3278, 0, +3167, 3412, 0, +3294, 3545, 0, +3422, 3678, 0, +3551, 3810, 0, +3681, 3943, 0, +3811, 4075, 0, +3942, 4095, 0, +2108, 0, 2226, +2109, 0, 2226, +2111, 0, 2225, +2112, 0, 2225, +2115, 0, 2224, +2118, 0, 2223, +2123, 0, 2221, +2128, 0, 2220, +2136, 0, 2217, +2146, 0, 2214, +2159, 0, 2209, +2176, 217, 2203, +2194, 1136, 2191, +2183, 1487, 2136, +2167, 1733, 2051, +2167, 1733, 1862, +2167, 1943, 1733, +2315, 2237, 1619, +2455, 2459, 1401, +2538, 2599, 611, +2631, 2738, 0, +2730, 2874, 0, +2836, 3010, 0, +2948, 3144, 0, +3064, 3278, 0, +3184, 3412, 0, +3307, 3545, 0, +3432, 3678, 0, +3559, 3810, 0, +3687, 3943, 0, +3816, 4075, 0, +3945, 4095, 0, +2332, 0, 2358, +2332, 0, 2358, +2333, 0, 2358, +2334, 0, 2357, +2335, 0, 2357, +2338, 0, 2356, +2340, 0, 2355, +2344, 0, 2353, +2349, 0, 2352, +2349, 0, 2343, +2346, 0, 2328, +2341, 0, 2305, +2335, 345, 2274, +2326, 1269, 2229, +2315, 1619, 2161, +2315, 1619, 2020, +2315, 1619, 1718, +2315, 2003, 1619, +2459, 2334, 1401, +2599, 2572, 611, +2702, 2738, 0, +2788, 2874, 0, +2883, 3010, 0, +2985, 3144, 0, +3093, 3278, 0, +3206, 3412, 0, +3324, 3545, 0, +3445, 3678, 0, +3569, 3810, 0, +3694, 3943, 0, +3821, 4075, 0, +3950, 4095, 0, +2491, 0, 2458, +2491, 0, 2457, +2490, 0, 2456, +2490, 0, 2454, +2489, 0, 2452, +2489, 0, 2449, +2488, 0, 2445, +2487, 0, 2440, +2486, 0, 2433, +2484, 0, 2423, +2481, 0, 2410, +2478, 0, 2392, +2473, 0, 2366, +2467, 477, 2330, +2459, 1401, 2276, +2459, 1401, 2171, +2459, 1401, 1976, +2459, 1401, 1403, +2459, 2073, 1401, +2599, 2437, 611, +2738, 2688, 0, +2856, 2874, 0, +2939, 3010, 0, +3030, 3144, 0, +3129, 3278, 0, +3234, 3412, 0, +3346, 3545, 0, +3462, 3678, 0, +3582, 3810, 0, +3704, 3943, 0, +3829, 4075, 0, +3955, 4095, 0, +2623, 0, 2541, +2623, 0, 2540, +2623, 0, 2539, +2622, 0, 2538, +2622, 0, 2536, +2621, 0, 2533, +2621, 0, 2530, +2620, 0, 2526, +2619, 0, 2520, +2618, 0, 2512, +2616, 0, 2501, +2613, 0, 2487, +2610, 0, 2466, +2605, 0, 2437, +2599, 611, 2395, +2599, 611, 2316, +2599, 611, 2183, +2599, 611, 1908, +2599, 1236, 611, +2599, 2153, 611, +2738, 2547, 0, +2874, 2807, 0, +3004, 3010, 0, +3084, 3144, 0, +3173, 3278, 0, +3270, 3412, 0, +3374, 3545, 0, +3483, 3678, 0, +3598, 3810, 0, +3717, 3943, 0, +3838, 4075, 0, +3963, 4095, 0, +2755, 0, 2632, +2755, 0, 2632, +2755, 0, 2631, +2755, 0, 2630, +2755, 0, 2628, +2754, 0, 2627, +2754, 0, 2624, +2753, 0, 2620, +2752, 0, 2616, +2751, 0, 2609, +2750, 0, 2601, +2748, 0, 2589, +2746, 0, 2572, +2742, 0, 2550, +2738, 0, 2517, +2738, 0, 2458, +2738, 0, 2365, +2738, 0, 2200, +2738, 0, 1799, +2738, 817, 0, +2738, 2241, 0, +2874, 2661, 0, +3010, 2928, 0, +3144, 3141, 0, +3225, 3278, 0, +3313, 3412, 0, +3408, 3545, 0, +3511, 3678, 0, +3620, 3810, 0, +3733, 3943, 0, +3851, 4075, 0, +3972, 4095, 0, +2887, 0, 2732, +2887, 0, 2731, +2887, 0, 2731, +2887, 0, 2730, +2887, 0, 2728, +2887, 0, 2727, +2886, 0, 2725, +2886, 0, 2722, +2885, 0, 2718, +2885, 0, 2713, +2883, 0, 2706, +2882, 0, 2697, +2880, 0, 2684, +2878, 0, 2666, +2874, 0, 2641, +2874, 0, 2597, +2874, 0, 2530, +2874, 0, 2423, +2874, 0, 2220, +2874, 0, 1596, +2874, 0, 0, +2874, 2338, 0, +3010, 2778, 0, +3144, 3053, 0, +3278, 3269, 0, +3365, 3412, 0, +3451, 3545, 0, +3545, 3678, 0, +3647, 3810, 0, +3755, 3943, 0, +3868, 4075, 0, +3985, 4095, 0, +3019, 0, 2837, +3019, 0, 2837, +3019, 0, 2836, +3019, 0, 2836, +3019, 0, 2835, +3019, 0, 2834, +3018, 0, 2832, +3018, 0, 2830, +3018, 0, 2827, +3017, 0, 2823, +3016, 0, 2817, +3015, 0, 2810, +3014, 0, 2800, +3012, 0, 2786, +3010, 0, 2767, +3010, 0, 2734, +3010, 0, 2686, +3010, 0, 2612, +3010, 0, 2489, +3010, 0, 2247, +3010, 0, 922, +3010, 0, 0, +3010, 2441, 0, +3144, 2901, 0, +3278, 3180, 0, +3412, 3397, 0, +3502, 3545, 0, +3587, 3678, 0, +3680, 3810, 0, +3781, 3943, 0, +3889, 4075, 0, +4002, 4095, 0, +3152, 0, 2949, +3152, 0, 2949, +3152, 0, 2948, +3151, 0, 2948, +3151, 0, 2947, +3151, 0, 2946, +3151, 0, 2945, +3151, 0, 2943, +3151, 0, 2941, +3150, 0, 2938, +3150, 0, 2933, +3149, 0, 2928, +3148, 0, 2920, +3146, 0, 2910, +3144, 0, 2895, +3144, 0, 2870, +3144, 0, 2835, +3144, 0, 2783, +3144, 0, 2703, +3144, 0, 2566, +3144, 0, 2280, +3144, 0, 0, +3144, 0, 0, +3144, 2551, 0, +3278, 3023, 0, +3412, 3307, 0, +3545, 3526, 0, +3638, 3678, 0, +3722, 3810, 0, +3815, 3943, 0, +3916, 4075, 0, +4023, 4095, 0, +3284, 0, 3065, +3283, 0, 3065, +3283, 0, 3064, +3283, 0, 3064, +3283, 0, 3063, +3283, 0, 3062, +3283, 0, 3062, +3283, 0, 3060, +3283, 0, 3059, +3282, 0, 3056, +3282, 0, 3053, +3281, 0, 3049, +3280, 0, 3043, +3280, 0, 3034, +3278, 0, 3024, +3278, 0, 3005, +3278, 0, 2979, +3278, 0, 2942, +3278, 0, 2886, +3278, 0, 2800, +3278, 0, 2651, +3278, 0, 2320, +3278, 0, 0, +3278, 0, 0, +3278, 2665, 0, +3412, 3150, 0, +3545, 3436, 0, +3678, 3657, 0, +3773, 3810, 0, +3857, 3943, 0, +3949, 4075, 0, +4049, 4095, 0, +3416, 0, 3184, +3416, 0, 3184, +3416, 0, 3184, +3416, 0, 3184, +3416, 0, 3184, +3416, 0, 3183, +3415, 0, 3182, +3415, 0, 3181, +3415, 0, 3180, +3415, 0, 3178, +3414, 0, 3175, +3414, 0, 3172, +3414, 0, 3168, +3413, 0, 3162, +3412, 0, 3154, +3412, 0, 3140, +3412, 0, 3120, +3412, 0, 3093, +3412, 0, 3055, +3412, 0, 2997, +3412, 0, 2906, +3412, 0, 2746, +3412, 0, 2371, +3412, 0, 0, +3412, 0, 0, +3412, 2784, 0, +3545, 3278, 0, +3678, 3566, 0, +3810, 3787, 0, +3907, 3943, 0, +3991, 4075, 0, +4083, 4095, 0, +3548, 0, 3307, +3548, 0, 3307, +3548, 0, 3307, +3548, 0, 3307, +3548, 0, 3307, +3548, 0, 3306, +3548, 0, 3305, +3548, 0, 3305, +3548, 0, 3303, +3547, 0, 3302, +3547, 0, 3300, +3547, 0, 3298, +3546, 0, 3294, +3546, 0, 3290, +3545, 0, 3284, +3545, 0, 3273, +3545, 0, 3259, +3545, 0, 3239, +3545, 0, 3211, +3545, 0, 3171, +3545, 0, 3111, +3545, 0, 3016, +3545, 0, 2848, +3545, 0, 2429, +3545, 0, 0, +3545, 0, 0, +3545, 2905, 0, +3678, 3406, 0, +3810, 3696, 0, +3943, 3918, 0, +4041, 4075, 0, +4095, 4095, 0, +3680, 0, 3432, +3680, 0, 3432, +3680, 0, 3432, +3680, 0, 3432, +3680, 0, 3431, +3680, 0, 3431, +3680, 0, 3431, +3680, 0, 3430, +3680, 0, 3429, +3680, 0, 3428, +3679, 0, 3427, +3679, 0, 3425, +3679, 0, 3422, +3678, 0, 3419, +3678, 0, 3414, +3678, 0, 3407, +3678, 0, 3396, +3678, 0, 3381, +3678, 0, 3361, +3678, 0, 3333, +3678, 0, 3291, +3678, 0, 3230, +3678, 0, 3132, +3678, 0, 2955, +3678, 0, 2499, +3678, 0, 0, +3678, 0, 0, +3678, 3029, 0, +3810, 3536, 0, +3943, 3827, 0, +4075, 4049, 0, +4095, 4095, 0, +3812, 0, 3559, +3812, 0, 3559, +3812, 0, 3559, +3812, 0, 3558, +3812, 0, 3558, +3812, 0, 3558, +3812, 0, 3558, +3812, 0, 3557, +3812, 0, 3557, +3812, 0, 3556, +3812, 0, 3555, +3812, 0, 3553, +3811, 0, 3552, +3811, 0, 3549, +3810, 0, 3545, +3810, 0, 3540, +3810, 0, 3532, +3810, 0, 3521, +3810, 0, 3506, +3810, 0, 3486, +3810, 0, 3457, +3810, 0, 3415, +3810, 0, 3352, +3810, 0, 3251, +3810, 0, 3069, +3810, 0, 2576, +3810, 0, 0, +3810, 0, 0, +3810, 3155, 0, +3943, 3665, 0, +4075, 3958, 0, +4095, 4095, 0, +3944, 0, 3687, +3944, 0, 3687, +3944, 0, 3687, +3944, 0, 3686, +3944, 0, 3686, +3944, 0, 3686, +3944, 0, 3686, +3944, 0, 3686, +3944, 0, 3685, +3944, 0, 3685, +3944, 0, 3684, +3944, 0, 3683, +3944, 0, 3681, +3943, 0, 3679, +3943, 0, 3677, +3943, 0, 3672, +3943, 0, 3666, +3943, 0, 3659, +3943, 0, 3648, +3943, 0, 3632, +3943, 0, 3612, +3943, 0, 3583, +3943, 0, 3540, +3943, 0, 3476, +3943, 0, 3374, +3943, 0, 3186, +3943, 0, 2662, +3943, 0, 0, +3943, 0, 0, +3943, 3283, 0, +4075, 3796, 0, +4095, 4089, 0, +4076, 0, 3816, +4076, 0, 3816, +4076, 0, 3816, +4076, 0, 3815, +4076, 0, 3815, +4076, 0, 3815, +4076, 0, 3815, +4076, 0, 3815, +4076, 0, 3814, +4076, 0, 3814, +4076, 0, 3813, +4076, 0, 3812, +4076, 0, 3812, +4076, 0, 3810, +4075, 0, 3808, +4075, 0, 3805, +4075, 0, 3801, +4075, 0, 3795, +4075, 0, 3787, +4075, 0, 3776, +4075, 0, 3760, +4075, 0, 3739, +4075, 0, 3710, +4075, 0, 3667, +4075, 0, 3602, +4075, 0, 3498, +4075, 0, 3306, +4075, 0, 2756, +4075, 0, 0, +4075, 0, 0, +4075, 3411, 0, +4095, 3927, 0, +4095, 0, 3946, +4095, 0, 3946, +4095, 0, 3945, +4095, 0, 3945, +4095, 0, 3945, +4095, 0, 3945, +4095, 0, 3945, +4095, 0, 3945, +4095, 0, 3945, +4095, 0, 3944, +4095, 0, 3944, +4095, 0, 3943, +4095, 0, 3942, +4095, 0, 3941, +4095, 0, 3940, +4095, 0, 3937, +4095, 0, 3934, +4095, 0, 3930, +4095, 0, 3924, +4095, 0, 3916, +4095, 0, 3905, +4095, 0, 3889, +4095, 0, 3868, +4095, 0, 3838, +4095, 0, 3795, +4095, 0, 3730, +4095, 0, 3625, +4095, 0, 3430, +4095, 0, 2861, +4095, 0, 0, +4095, 0, 0, +4095, 3541, 0, +0, 1827, 2094, +0, 1831, 2094, +0, 1837, 2094, +0, 1845, 2094, +0, 1855, 2094, +0, 1867, 2094, +0, 1884, 2094, +0, 1905, 2094, +0, 1932, 2094, +0, 1966, 2094, +0, 2007, 2094, +0, 2058, 2094, +0, 2094, 2069, +0, 2094, 1977, +0, 2094, 1816, +0, 2094, 1433, +0, 2226, 0, +0, 2358, 0, +1120, 2491, 0, +1833, 2623, 0, +2162, 2755, 0, +2400, 2887, 0, +2597, 3019, 0, +2773, 3152, 0, +2935, 3284, 0, +3088, 3416, 0, +3236, 3548, 0, +3379, 3680, 0, +3519, 3812, 0, +3657, 3944, 0, +3793, 4076, 0, +3929, 4095, 0, +0, 1823, 2094, +0, 1828, 2093, +0, 1834, 2093, +0, 1841, 2093, +0, 1851, 2093, +0, 1864, 2093, +0, 1881, 2093, +0, 1902, 2093, +0, 1929, 2093, +0, 1963, 2093, +0, 2005, 2093, +0, 2056, 2093, +0, 2093, 2070, +0, 2093, 1979, +0, 2093, 1818, +0, 2093, 1438, +0, 2226, 0, +0, 2358, 0, +1143, 2491, 0, +1838, 2623, 0, +2164, 2755, 0, +2401, 2887, 0, +2598, 3019, 0, +2773, 3152, 0, +2935, 3283, 0, +3088, 3416, 0, +3236, 3548, 0, +3379, 3680, 0, +3519, 3812, 0, +3657, 3944, 0, +3793, 4076, 0, +3929, 4095, 0, +0, 1817, 2094, +0, 1822, 2093, +0, 1829, 2093, +0, 1837, 2093, +0, 1847, 2093, +0, 1860, 2093, +0, 1877, 2093, +0, 1898, 2093, +0, 1926, 2093, +0, 1960, 2093, +0, 2002, 2093, +0, 2053, 2093, +0, 2093, 2071, +0, 2093, 1981, +0, 2093, 1821, +0, 2093, 1444, +0, 2225, 0, +0, 2358, 0, +1173, 2490, 0, +1845, 2623, 0, +2167, 2755, 0, +2403, 2887, 0, +2599, 3019, 0, +2774, 3152, 0, +2936, 3283, 0, +3089, 3416, 0, +3236, 3548, 0, +3379, 3680, 0, +3519, 3812, 0, +3657, 3944, 0, +3793, 4076, 0, +3929, 4095, 0, +0, 1809, 2094, +0, 1814, 2093, +0, 1821, 2093, +0, 1830, 2092, +0, 1841, 2092, +0, 1854, 2092, +0, 1871, 2092, +0, 1893, 2092, +0, 1920, 2092, +0, 1955, 2092, +0, 1997, 2092, +0, 2049, 2092, +0, 2092, 2073, +0, 2092, 1983, +0, 2092, 1824, +0, 2092, 1452, +0, 2225, 0, +0, 2357, 0, +1210, 2490, 0, +1853, 2622, 0, +2172, 2755, 0, +2406, 2887, 0, +2601, 3019, 0, +2775, 3151, 0, +2936, 3283, 0, +3089, 3416, 0, +3237, 3548, 0, +3379, 3680, 0, +3520, 3812, 0, +3657, 3944, 0, +3794, 4076, 0, +3929, 4095, 0, +0, 1798, 2094, +0, 1804, 2093, +0, 1811, 2093, +0, 1820, 2092, +0, 1832, 2091, +0, 1846, 2091, +0, 1863, 2091, +0, 1885, 2091, +0, 1913, 2091, +0, 1949, 2091, +0, 1992, 2091, +0, 2044, 2091, +0, 2091, 2076, +0, 2091, 1986, +0, 2091, 1829, +0, 2091, 1463, +0, 2224, 0, +0, 2357, 0, +1255, 2489, 0, +1865, 2622, 0, +2177, 2755, 0, +2409, 2887, 0, +2603, 3019, 0, +2777, 3151, 0, +2938, 3283, 0, +3090, 3416, 0, +3237, 3548, 0, +3380, 3680, 0, +3520, 3812, 0, +3658, 3944, 0, +3794, 4076, 0, +3929, 4095, 0, +0, 1783, 2094, +0, 1789, 2093, +0, 1796, 2093, +0, 1806, 2092, +0, 1819, 2091, +0, 1835, 2089, +0, 1853, 2089, +0, 1875, 2089, +0, 1904, 2089, +0, 1940, 2089, +0, 1984, 2089, +0, 2037, 2089, +0, 2089, 2080, +0, 2089, 1991, +0, 2089, 1835, +0, 2089, 1476, +0, 2223, 0, +0, 2356, 0, +1310, 2489, 0, +1880, 2621, 0, +2185, 2754, 0, +2413, 2887, 0, +2606, 3019, 0, +2779, 3151, 0, +2939, 3283, 0, +3091, 3416, 0, +3238, 3548, 0, +3380, 3680, 0, +3520, 3812, 0, +3658, 3944, 0, +3794, 4076, 0, +3929, 4095, 0, +0, 1763, 2094, +0, 1768, 2093, +0, 1776, 2093, +0, 1786, 2092, +0, 1799, 2091, +0, 1816, 2089, +0, 1838, 2087, +0, 1862, 2087, +0, 1891, 2087, +0, 1928, 2087, +0, 1973, 2087, +0, 2027, 2087, +0, 2087, 2085, +0, 2087, 1996, +0, 2087, 1843, +0, 2087, 1494, +0, 2221, 0, +0, 2355, 0, +1373, 2488, 0, +1899, 2621, 0, +2195, 2754, 0, +2419, 2886, 0, +2610, 3018, 0, +2782, 3151, 0, +2941, 3283, 0, +3093, 3415, 0, +3239, 3548, 0, +3381, 3680, 0, +3521, 3812, 0, +3658, 3944, 0, +3794, 4076, 0, +3930, 4095, 0, +0, 1733, 2094, +0, 1739, 2093, +0, 1748, 2093, +0, 1758, 2092, +0, 1772, 2091, +0, 1790, 2089, +0, 1813, 2087, +0, 1843, 2085, +0, 1873, 2085, +0, 1912, 2085, +0, 1958, 2085, +0, 2014, 2085, +0, 2079, 2085, +0, 2085, 2004, +0, 2085, 1854, +0, 2085, 1517, +0, 2220, 0, +0, 2353, 0, +1446, 2487, 0, +1923, 2620, 0, +2208, 2753, 0, +2427, 2886, 0, +2615, 3018, 0, +2785, 3151, 0, +2943, 3283, 0, +3094, 3415, 0, +3240, 3548, 0, +3382, 3680, 0, +3521, 3812, 0, +3659, 3944, 0, +3795, 4076, 0, +3930, 4095, 0, +0, 1691, 2094, +0, 1698, 2093, +0, 1706, 2093, +0, 1718, 2092, +0, 1733, 2091, +0, 1753, 2089, +0, 1778, 2087, +0, 1810, 2085, +0, 1849, 2082, +0, 1889, 2082, +0, 1938, 2082, +0, 1996, 2082, +0, 2063, 2082, +0, 2082, 2014, +0, 2082, 1868, +0, 2082, 1545, +0, 2217, 0, +0, 2352, 0, +1529, 2486, 0, +1954, 2619, 0, +2224, 2752, 0, +2438, 2885, 0, +2622, 3018, 0, +2790, 3151, 0, +2947, 3283, 0, +3097, 3415, 0, +3242, 3548, 0, +3383, 3680, 0, +3522, 3812, 0, +3659, 3944, 0, +3795, 4076, 0, +3930, 4095, 0, +0, 1626, 2094, +0, 1635, 2093, +0, 1645, 2093, +0, 1658, 2092, +0, 1676, 2091, +0, 1698, 2089, +0, 1726, 2087, +0, 1761, 2085, +0, 1804, 2082, +0, 1856, 2077, +0, 1908, 2077, +0, 1970, 2077, +0, 2041, 2077, +0, 2077, 2027, +0, 2077, 1886, +0, 2077, 1581, +0, 2214, 0, +275, 2349, 0, +1620, 2484, 0, +1991, 2618, 0, +2245, 2751, 0, +2451, 2885, 0, +2631, 3017, 0, +2796, 3150, 0, +2951, 3282, 0, +3100, 3415, 0, +3244, 3547, 0, +3385, 3680, 0, +3523, 3812, 0, +3661, 3944, 0, +3796, 4076, 0, +3931, 4095, 0, +0, 1524, 2094, +0, 1534, 2093, +0, 1547, 2093, +0, 1564, 2092, +0, 1585, 2091, +0, 1612, 2089, +0, 1646, 2087, +0, 1687, 2085, +0, 1738, 2082, +0, 1797, 2077, +79, 1866, 2071, +79, 1934, 2071, +79, 2010, 2071, +79, 2071, 2044, +79, 2071, 1908, +79, 2071, 1625, +0, 2209, 303, +1064, 2346, 0, +1719, 2481, 0, +2038, 2616, 0, +2273, 2750, 0, +2469, 2883, 0, +2643, 3016, 0, +2804, 3150, 0, +2957, 3282, 0, +3104, 3414, 0, +3247, 3547, 0, +3387, 3679, 0, +3525, 3812, 0, +3662, 3944, 0, +3797, 4076, 0, +3932, 4095, 0, +0, 1336, 2094, +0, 1351, 2093, +0, 1370, 2093, +0, 1394, 2092, +0, 1425, 2091, +0, 1463, 2089, +0, 1509, 2087, +0, 1565, 2085, +0, 1630, 2082, +0, 1704, 2077, +79, 1787, 2071, +1005, 1880, 2062, +1005, 1965, 2062, +1005, 2059, 2062, +1005, 2062, 1937, +1005, 2062, 1677, +217, 2203, 838, +1403, 2341, 0, +1824, 2478, 0, +2093, 2613, 0, +2306, 2748, 0, +2491, 2882, 0, +2658, 3015, 0, +2815, 3149, 0, +2965, 3281, 0, +3110, 3414, 0, +3251, 3547, 0, +3390, 3679, 0, +3528, 3812, 0, +3663, 3944, 0, +3798, 4076, 0, +3932, 4095, 0, +0, 814, 2094, +0, 859, 2093, +0, 913, 2093, +0, 977, 2092, +0, 1050, 2091, +0, 1133, 2089, +0, 1224, 2087, +0, 1322, 2085, +0, 1428, 2082, +0, 1539, 2077, +79, 1655, 2071, +1005, 1774, 2062, +1355, 1897, 2051, +1355, 2004, 2051, +1355, 2051, 1973, +1355, 2051, 1739, +1137, 2194, 1136, +1644, 2335, 345, +1935, 2473, 0, +2158, 2610, 0, +2348, 2746, 0, +2519, 2880, 0, +2678, 3014, 0, +2829, 3148, 0, +2975, 3280, 0, +3117, 3414, 0, +3257, 3546, 0, +3394, 3679, 0, +3530, 3811, 0, +3666, 3944, 0, +3800, 4076, 0, +3934, 4095, 0, +0, 0, 2094, +0, 0, 2093, +0, 0, 2093, +0, 0, 2092, +0, 0, 2091, +0, 0, 2089, +0, 0, 2087, +0, 10, 2085, +0, 800, 2082, +0, 1138, 2077, +79, 1379, 2071, +1005, 1579, 2062, +1355, 1756, 2051, +1601, 1919, 2035, +1601, 2035, 2017, +1601, 2035, 1811, +1585, 2183, 1487, +1843, 2326, 1269, +2051, 2467, 477, +2233, 2605, 0, +2398, 2742, 0, +2554, 2878, 0, +2703, 3012, 0, +2847, 3146, 0, +2988, 3280, 0, +3127, 3413, 0, +3264, 3546, 0, +3400, 3678, 0, +3534, 3811, 0, +3668, 3943, 0, +3802, 4076, 0, +3935, 4095, 0, +0, 0, 2094, +0, 0, 2093, +0, 0, 2093, +0, 0, 2092, +0, 0, 2091, +0, 0, 2089, +0, 0, 2087, +0, 0, 2085, +0, 0, 2082, +173, 0, 2077, +706, 79, 2071, +1005, 1006, 2062, +1355, 1453, 2051, +1601, 1730, 2035, +1803, 1946, 2013, +1803, 2013, 1891, +1862, 2167, 1733, +2020, 2315, 1619, +2171, 2459, 1401, +2316, 2599, 611, +2458, 2738, 0, +2597, 2874, 0, +2734, 3010, 0, +2870, 3144, 0, +3005, 3278, 0, +3140, 3412, 0, +3273, 3545, 0, +3407, 3678, 0, +3540, 3810, 0, +3672, 3943, 0, +3805, 4075, 0, +3937, 4095, 0, +1433, 0, 2094, +1438, 0, 2093, +1444, 0, 2093, +1452, 0, 2092, +1463, 0, 2091, +1476, 0, 2089, +1494, 0, 2087, +1517, 0, 2085, +1545, 0, 2082, +1581, 0, 2077, +1625, 79, 2071, +1677, 1005, 2062, +1739, 1355, 2051, +1811, 1601, 2035, +1891, 1803, 2013, +1981, 1981, 1981, +2078, 2145, 1935, +2183, 2299, 1865, +2293, 2447, 1751, +2408, 2591, 1533, +2527, 2731, 738, +2649, 2870, 0, +2773, 3006, 0, +2900, 3142, 0, +3027, 3276, 0, +3156, 3410, 0, +3285, 3544, 0, +3416, 3677, 0, +3547, 3810, 0, +3677, 3943, 0, +3809, 4075, 0, +3940, 4095, 0, +1946, 0, 2226, +1948, 0, 2226, +1950, 0, 2225, +1953, 0, 2225, +1956, 0, 2224, +1961, 0, 2223, +1967, 0, 2221, +1975, 0, 2220, +1986, 0, 2217, +2000, 0, 2214, +2018, 0, 2209, +2041, 217, 2203, +2069, 1136, 2194, +2105, 1487, 2183, +2149, 1733, 2167, +2145, 1935, 2078, +2145, 2023, 1935, +2299, 2281, 1865, +2401, 2447, 1751, +2493, 2591, 1533, +2594, 2731, 738, +2701, 2870, 0, +2813, 3006, 0, +2931, 3142, 0, +3050, 3276, 0, +3174, 3410, 0, +3299, 3544, 0, +3426, 3677, 0, +3554, 3810, 0, +3683, 3943, 0, +3813, 4075, 0, +3944, 4095, 0, +2239, 0, 2358, +2240, 0, 2358, +2241, 0, 2358, +2243, 0, 2357, +2245, 0, 2357, +2247, 0, 2356, +2251, 0, 2355, +2255, 0, 2353, +2261, 0, 2352, +2268, 0, 2349, +2278, 0, 2346, +2291, 0, 2341, +2308, 345, 2335, +2326, 1269, 2323, +2315, 1619, 2268, +2299, 1865, 2183, +2299, 1865, 1994, +2299, 2075, 1865, +2447, 2370, 1751, +2587, 2591, 1533, +2671, 2731, 738, +2763, 2870, 0, +2862, 3006, 0, +2969, 3142, 0, +3080, 3276, 0, +3196, 3410, 0, +3316, 3544, 0, +3439, 3677, 0, +3564, 3810, 0, +3691, 3943, 0, +3818, 4075, 0, +3948, 4095, 0, +2463, 0, 2491, +2464, 0, 2491, +2464, 0, 2490, +2465, 0, 2490, +2466, 0, 2489, +2468, 0, 2489, +2470, 0, 2488, +2473, 0, 2487, +2476, 0, 2486, +2481, 0, 2484, +2481, 0, 2475, +2478, 0, 2460, +2473, 0, 2438, +2467, 477, 2407, +2459, 1401, 2362, +2447, 1751, 2293, +2447, 1751, 2152, +2447, 1751, 1850, +2447, 2135, 1751, +2591, 2466, 1533, +2731, 2705, 738, +2834, 2870, 0, +2920, 3006, 0, +3015, 3142, 0, +3117, 3276, 0, +3225, 3410, 0, +3339, 3544, 0, +3456, 3677, 0, +3577, 3810, 0, +3701, 3943, 0, +3826, 4075, 0, +3953, 4095, 0, +2623, 0, 2590, +2623, 0, 2590, +2623, 0, 2589, +2622, 0, 2588, +2622, 0, 2586, +2621, 0, 2584, +2621, 0, 2581, +2620, 0, 2577, +2619, 0, 2572, +2618, 0, 2565, +2616, 0, 2555, +2613, 0, 2542, +2610, 0, 2524, +2605, 0, 2498, +2599, 611, 2462, +2591, 1533, 2408, +2591, 1533, 2303, +2591, 1533, 2108, +2591, 1533, 1533, +2591, 2206, 1533, +2731, 2570, 738, +2870, 2820, 0, +2988, 3006, 0, +3071, 3142, 0, +3162, 3276, 0, +3261, 3410, 0, +3367, 3544, 0, +3478, 3677, 0, +3594, 3810, 0, +3713, 3943, 0, +3836, 4075, 0, +3961, 4095, 0, +2755, 0, 2673, +2755, 0, 2673, +2755, 0, 2672, +2755, 0, 2671, +2755, 0, 2670, +2754, 0, 2668, +2754, 0, 2666, +2753, 0, 2662, +2752, 0, 2658, +2751, 0, 2652, +2750, 0, 2645, +2748, 0, 2634, +2746, 0, 2619, +2742, 0, 2598, +2738, 0, 2569, +2731, 738, 2527, +2731, 738, 2448, +2731, 738, 2315, +2731, 738, 2040, +2731, 1362, 738, +2731, 2285, 738, +2870, 2678, 0, +3006, 2939, 0, +3136, 3142, 0, +3216, 3276, 0, +3305, 3410, 0, +3402, 3544, 0, +3506, 3677, 0, +3616, 3810, 0, +3730, 3943, 0, +3849, 4075, 0, +3971, 4095, 0, +2887, 0, 2765, +2887, 0, 2764, +2887, 0, 2764, +2887, 0, 2763, +2887, 0, 2762, +2887, 0, 2761, +2886, 0, 2759, +2886, 0, 2756, +2885, 0, 2752, +2885, 0, 2748, +2883, 0, 2741, +2882, 0, 2733, +2880, 0, 2721, +2878, 0, 2704, +2874, 0, 2681, +2870, 0, 2649, +2870, 0, 2590, +2870, 0, 2497, +2870, 0, 2332, +2870, 0, 1932, +2870, 963, 0, +2870, 2374, 0, +3006, 2792, 0, +3142, 3061, 0, +3276, 3273, 0, +3358, 3410, 0, +3445, 3544, 0, +3540, 3677, 0, +3643, 3810, 0, +3752, 3943, 0, +3865, 4075, 0, +3983, 4095, 0, +3019, 0, 2864, +3019, 0, 2863, +3019, 0, 2863, +3019, 0, 2863, +3019, 0, 2862, +3019, 0, 2860, +3018, 0, 2859, +3018, 0, 2857, +3018, 0, 2854, +3017, 0, 2850, +3016, 0, 2845, +3015, 0, 2838, +3014, 0, 2829, +3012, 0, 2816, +3010, 0, 2798, +3006, 0, 2773, +3006, 0, 2729, +3006, 0, 2662, +3006, 0, 2554, +3006, 0, 2352, +3006, 0, 1723, +3006, 0, 0, +3006, 2470, 0, +3142, 2911, 0, +3276, 3185, 0, +3410, 3401, 0, +3497, 3544, 0, +3583, 3677, 0, +3677, 3810, 0, +3779, 3943, 0, +3887, 4075, 0, +4000, 4095, 0, +3152, 0, 2970, +3152, 0, 2970, +3152, 0, 2969, +3151, 0, 2969, +3151, 0, 2968, +3151, 0, 2967, +3151, 0, 2966, +3151, 0, 2964, +3151, 0, 2962, +3150, 0, 2959, +3150, 0, 2955, +3149, 0, 2950, +3148, 0, 2942, +3146, 0, 2932, +3144, 0, 2919, +3142, 0, 2900, +3142, 0, 2867, +3142, 0, 2818, +3142, 0, 2744, +3142, 0, 2622, +3142, 0, 2379, +3142, 0, 1068, +3142, 0, 0, +3142, 2573, 0, +3276, 3032, 0, +3410, 3311, 0, +3544, 3529, 0, +3634, 3677, 0, +3719, 3810, 0, +3813, 3943, 0, +3913, 4075, 0, +4021, 4095, 0, +3284, 0, 3081, +3283, 0, 3081, +3283, 0, 3081, +3283, 0, 3080, +3283, 0, 3080, +3283, 0, 3079, +3283, 0, 3078, +3283, 0, 3077, +3283, 0, 3075, +3282, 0, 3073, +3282, 0, 3070, +3281, 0, 3065, +3280, 0, 3060, +3280, 0, 3052, +3278, 0, 3041, +3276, 0, 3027, +3276, 0, 3002, +3276, 0, 2967, +3276, 0, 2915, +3276, 0, 2834, +3276, 0, 2698, +3276, 0, 2411, +3276, 0, 0, +3276, 0, 0, +3276, 2683, 0, +3410, 3156, 0, +3544, 3440, 0, +3677, 3659, 0, +3770, 3810, 0, +3854, 3943, 0, +3947, 4075, 0, +4048, 4095, 0, +3416, 0, 3197, +3416, 0, 3197, +3416, 0, 3197, +3416, 0, 3196, +3416, 0, 3196, +3416, 0, 3196, +3415, 0, 3195, +3415, 0, 3194, +3415, 0, 3192, +3415, 0, 3191, +3414, 0, 3188, +3414, 0, 3185, +3414, 0, 3181, +3413, 0, 3175, +3412, 0, 3167, +3410, 0, 3156, +3410, 0, 3137, +3410, 0, 3111, +3410, 0, 3074, +3410, 0, 3019, +3410, 0, 2933, +3410, 0, 2784, +3410, 0, 2453, +3410, 0, 0, +3410, 0, 0, +3410, 2797, 0, +3544, 3282, 0, +3677, 3568, 0, +3810, 3789, 0, +3905, 3943, 0, +3989, 4075, 0, +4082, 4095, 0, +3548, 0, 3317, +3548, 0, 3317, +3548, 0, 3317, +3548, 0, 3316, +3548, 0, 3316, +3548, 0, 3316, +3548, 0, 3315, +3548, 0, 3314, +3548, 0, 3313, +3547, 0, 3312, +3547, 0, 3310, +3547, 0, 3307, +3546, 0, 3304, +3546, 0, 3300, +3545, 0, 3294, +3544, 0, 3285, +3544, 0, 3272, +3544, 0, 3253, +3544, 0, 3225, +3544, 0, 3186, +3544, 0, 3129, +3544, 0, 3038, +3544, 0, 2879, +3544, 0, 2502, +3544, 0, 0, +3544, 0, 0, +3544, 2916, 0, +3677, 3410, 0, +3810, 3698, 0, +3943, 3920, 0, +4039, 4075, 0, +4095, 4095, 0, +3680, 0, 3440, +3680, 0, 3439, +3680, 0, 3439, +3680, 0, 3439, +3680, 0, 3439, +3680, 0, 3438, +3680, 0, 3438, +3680, 0, 3437, +3680, 0, 3437, +3680, 0, 3436, +3679, 0, 3434, +3679, 0, 3432, +3679, 0, 3430, +3678, 0, 3426, +3678, 0, 3422, +3677, 0, 3416, +3677, 0, 3405, +3677, 0, 3391, +3677, 0, 3371, +3677, 0, 3344, +3677, 0, 3303, +3677, 0, 3243, +3677, 0, 3149, +3677, 0, 2980, +3677, 0, 2562, +3677, 0, 0, +3677, 0, 0, +3677, 3037, 0, +3810, 3538, 0, +3943, 3828, 0, +4075, 4050, 0, +4095, 4095, 0, +3812, 0, 3564, +3812, 0, 3564, +3812, 0, 3564, +3812, 0, 3564, +3812, 0, 3564, +3812, 0, 3564, +3812, 0, 3563, +3812, 0, 3563, +3812, 0, 3562, +3812, 0, 3562, +3812, 0, 3561, +3812, 0, 3559, +3811, 0, 3557, +3811, 0, 3554, +3810, 0, 3551, +3810, 0, 3547, +3810, 0, 3539, +3810, 0, 3528, +3810, 0, 3514, +3810, 0, 3493, +3810, 0, 3465, +3810, 0, 3424, +3810, 0, 3362, +3810, 0, 3264, +3810, 0, 3088, +3810, 0, 2631, +3810, 0, 0, +3810, 0, 0, +3810, 3161, 0, +3943, 3667, 0, +4075, 3959, 0, +4095, 4095, 0, +3944, 0, 3691, +3944, 0, 3691, +3944, 0, 3691, +3944, 0, 3691, +3944, 0, 3691, +3944, 0, 3690, +3944, 0, 3690, +3944, 0, 3690, +3944, 0, 3689, +3944, 0, 3689, +3944, 0, 3688, +3944, 0, 3687, +3944, 0, 3685, +3943, 0, 3683, +3943, 0, 3681, +3943, 0, 3677, +3943, 0, 3672, +3943, 0, 3664, +3943, 0, 3653, +3943, 0, 3638, +3943, 0, 3618, +3943, 0, 3589, +3943, 0, 3547, +3943, 0, 3484, +3943, 0, 3384, +3943, 0, 3201, +3943, 0, 2708, +3943, 0, 0, +3943, 0, 0, +3943, 3287, 0, +4075, 3797, 0, +4095, 4090, 0, +4076, 0, 3819, +4076, 0, 3819, +4076, 0, 3819, +4076, 0, 3818, +4076, 0, 3818, +4076, 0, 3818, +4076, 0, 3818, +4076, 0, 3818, +4076, 0, 3818, +4076, 0, 3817, +4076, 0, 3816, +4076, 0, 3816, +4076, 0, 3814, +4076, 0, 3813, +4075, 0, 3811, +4075, 0, 3809, +4075, 0, 3804, +4075, 0, 3798, +4075, 0, 3790, +4075, 0, 3780, +4075, 0, 3765, +4075, 0, 3744, +4075, 0, 3714, +4075, 0, 3672, +4075, 0, 3608, +4075, 0, 3505, +4075, 0, 3318, +4075, 0, 2793, +4075, 0, 0, +4075, 0, 0, +4075, 3415, 0, +4095, 3929, 0, +4095, 0, 3948, +4095, 0, 3948, +4095, 0, 3948, +4095, 0, 3948, +4095, 0, 3948, +4095, 0, 3948, +4095, 0, 3947, +4095, 0, 3947, +4095, 0, 3947, +4095, 0, 3947, +4095, 0, 3946, +4095, 0, 3946, +4095, 0, 3945, +4095, 0, 3944, +4095, 0, 3942, +4095, 0, 3940, +4095, 0, 3937, +4095, 0, 3933, +4095, 0, 3927, +4095, 0, 3919, +4095, 0, 3908, +4095, 0, 3893, +4095, 0, 3872, +4095, 0, 3842, +4095, 0, 3799, +4095, 0, 3735, +4095, 0, 3630, +4095, 0, 3439, +4095, 0, 2890, +4095, 0, 0, +4095, 0, 0, +4095, 3544, 0, +0, 1959, 2226, +0, 1962, 2226, +0, 1966, 2226, +0, 1972, 2226, +0, 1979, 2226, +0, 1989, 2226, +0, 2002, 2226, +0, 2018, 2226, +0, 2039, 2226, +0, 2066, 2226, +0, 2100, 2226, +0, 2141, 2226, +0, 2191, 2226, +0, 2226, 2200, +0, 2226, 2108, +0, 2226, 1946, +0, 2226, 1562, +0, 2358, 0, +0, 2491, 0, +1232, 2623, 0, +1962, 2755, 0, +2292, 2887, 0, +2530, 3019, 0, +2729, 3152, 0, +2904, 3284, 0, +3067, 3416, 0, +3220, 3548, 0, +3367, 3680, 0, +3511, 3812, 0, +3651, 3944, 0, +3789, 4076, 0, +3926, 4095, 0, +0, 1956, 2226, +0, 1959, 2226, +0, 1963, 2226, +0, 1969, 2226, +0, 1977, 2226, +0, 1987, 2226, +0, 1999, 2226, +0, 2016, 2226, +0, 2037, 2226, +0, 2064, 2226, +0, 2098, 2226, +0, 2140, 2226, +0, 2190, 2226, +0, 2226, 2201, +0, 2226, 2109, +0, 2226, 1948, +0, 2226, 1565, +0, 2358, 0, +0, 2491, 0, +1251, 2623, 0, +1966, 2755, 0, +2294, 2887, 0, +2531, 3019, 0, +2729, 3152, 0, +2905, 3283, 0, +3067, 3416, 0, +3220, 3548, 0, +3368, 3680, 0, +3511, 3812, 0, +3651, 3944, 0, +3789, 4076, 0, +3926, 4095, 0, +0, 1951, 2226, +0, 1955, 2226, +0, 1960, 2225, +0, 1966, 2225, +0, 1973, 2225, +0, 1983, 2225, +0, 1996, 2225, +0, 2013, 2225, +0, 2034, 2225, +0, 2061, 2225, +0, 2095, 2225, +0, 2137, 2225, +0, 2188, 2225, +0, 2225, 2202, +0, 2225, 2111, +0, 2225, 1950, +0, 2225, 1570, +0, 2358, 0, +0, 2490, 0, +1275, 2623, 0, +1971, 2755, 0, +2296, 2887, 0, +2533, 3019, 0, +2730, 3152, 0, +2905, 3283, 0, +3067, 3416, 0, +3221, 3548, 0, +3368, 3680, 0, +3511, 3812, 0, +3651, 3944, 0, +3789, 4076, 0, +3926, 4095, 0, +0, 1945, 2226, +0, 1949, 2226, +0, 1954, 2225, +0, 1961, 2225, +0, 1969, 2225, +0, 1979, 2225, +0, 1992, 2225, +0, 2009, 2225, +0, 2030, 2225, +0, 2058, 2225, +0, 2092, 2225, +0, 2134, 2225, +0, 2185, 2225, +0, 2225, 2203, +0, 2225, 2112, +0, 2225, 1953, +0, 2225, 1576, +0, 2357, 0, +0, 2490, 0, +1304, 2622, 0, +1977, 2755, 0, +2299, 2887, 0, +2535, 3019, 0, +2732, 3151, 0, +2906, 3283, 0, +3068, 3416, 0, +3221, 3548, 0, +3368, 3680, 0, +3511, 3812, 0, +3651, 3944, 0, +3789, 4076, 0, +3926, 4095, 0, +0, 1937, 2226, +0, 1941, 2226, +0, 1946, 2225, +0, 1953, 2225, +0, 1963, 2224, +0, 1973, 2224, +0, 1986, 2224, +0, 2003, 2224, +0, 2025, 2224, +0, 2053, 2224, +0, 2087, 2224, +0, 2130, 2224, +0, 2181, 2224, +0, 2224, 2206, +0, 2224, 2115, +0, 2224, 1956, +0, 2224, 1584, +0, 2357, 0, +0, 2489, 0, +1342, 2622, 0, +1986, 2755, 0, +2304, 2887, 0, +2537, 3019, 0, +2733, 3151, 0, +2907, 3283, 0, +3069, 3416, 0, +3222, 3548, 0, +3369, 3680, 0, +3511, 3812, 0, +3652, 3944, 0, +3790, 4076, 0, +3926, 4095, 0, +0, 1926, 2226, +0, 1930, 2226, +0, 1936, 2225, +0, 1943, 2225, +0, 1952, 2224, +0, 1965, 2223, +0, 1978, 2223, +0, 1995, 2223, +0, 2018, 2223, +0, 2046, 2223, +0, 2081, 2223, +0, 2124, 2223, +0, 2176, 2223, +0, 2223, 2208, +0, 2223, 2118, +0, 2223, 1961, +0, 2223, 1595, +0, 2356, 0, +0, 2489, 0, +1387, 2621, 0, +1997, 2754, 0, +2310, 2887, 0, +2541, 3019, 0, +2735, 3151, 0, +2909, 3283, 0, +3070, 3416, 0, +3222, 3548, 0, +3369, 3680, 0, +3512, 3812, 0, +3652, 3944, 0, +3790, 4076, 0, +3926, 4095, 0, +0, 1911, 2226, +0, 1915, 2226, +0, 1921, 2225, +0, 1928, 2225, +0, 1938, 2224, +0, 1951, 2223, +0, 1967, 2221, +0, 1985, 2221, +0, 2008, 2221, +0, 2036, 2221, +0, 2072, 2221, +0, 2116, 2221, +0, 2169, 2221, +0, 2221, 2212, +0, 2221, 2123, +0, 2221, 1967, +0, 2221, 1608, +0, 2355, 0, +0, 2488, 0, +1441, 2621, 0, +2012, 2754, 0, +2317, 2886, 0, +2545, 3018, 0, +2738, 3151, 0, +2911, 3283, 0, +3071, 3415, 0, +3223, 3548, 0, +3370, 3680, 0, +3513, 3812, 0, +3652, 3944, 0, +3790, 4076, 0, +3927, 4095, 0, +0, 1890, 2226, +0, 1894, 2226, +0, 1900, 2225, +0, 1908, 2225, +0, 1918, 2224, +0, 1931, 2223, +0, 1948, 2221, +0, 1970, 2220, +0, 1994, 2220, +0, 2023, 2220, +0, 2060, 2220, +0, 2105, 2220, +0, 2159, 2220, +0, 2220, 2217, +0, 2220, 2128, +0, 2220, 1975, +0, 2220, 1626, +0, 2353, 0, +0, 2487, 0, +1505, 2620, 0, +2031, 2753, 0, +2327, 2886, 0, +2551, 3018, 0, +2742, 3151, 0, +2914, 3283, 0, +3073, 3415, 0, +3225, 3548, 0, +3371, 3680, 0, +3513, 3812, 0, +3653, 3944, 0, +3790, 4076, 0, +3927, 4095, 0, +0, 1860, 2226, +0, 1865, 2226, +0, 1871, 2225, +0, 1880, 2225, +0, 1891, 2224, +0, 1904, 2223, +0, 1922, 2221, +0, 1946, 2220, +0, 1975, 2217, +0, 2006, 2217, +0, 2044, 2217, +0, 2090, 2217, +0, 2146, 2217, +0, 2211, 2217, +0, 2217, 2136, +0, 2217, 1986, +0, 2217, 1649, +0, 2352, 0, +0, 2486, 0, +1578, 2619, 0, +2056, 2752, 0, +2340, 2885, 0, +2559, 3018, 0, +2747, 3151, 0, +2917, 3283, 0, +3076, 3415, 0, +3226, 3548, 0, +3372, 3680, 0, +3514, 3812, 0, +3653, 3944, 0, +3791, 4076, 0, +3927, 4095, 0, +0, 1817, 2226, +0, 1823, 2226, +0, 1829, 2225, +0, 1839, 2225, +0, 1850, 2224, +0, 1865, 2223, +0, 1885, 2221, +0, 1910, 2220, +0, 1942, 2217, +0, 1981, 2214, +0, 2021, 2214, +0, 2070, 2214, +0, 2128, 2214, +0, 2195, 2214, +0, 2214, 2146, +0, 2214, 2000, +0, 2214, 1677, +0, 2349, 0, +0, 2484, 0, +1661, 2618, 0, +2086, 2751, 0, +2356, 2885, 0, +2570, 3017, 0, +2754, 3150, 0, +2922, 3282, 0, +3079, 3415, 0, +3229, 3547, 0, +3374, 3680, 0, +3515, 3812, 0, +3654, 3944, 0, +3791, 4076, 0, +3927, 4095, 0, +0, 1753, 2226, +0, 1759, 2226, +0, 1767, 2225, +0, 1777, 2225, +0, 1790, 2224, +0, 1808, 2223, +0, 1830, 2221, +0, 1858, 2220, +0, 1894, 2217, +0, 1936, 2214, +0, 1988, 2209, +0, 2041, 2209, +0, 2102, 2209, +0, 2174, 2209, +0, 2209, 2159, +0, 2209, 2018, +0, 2209, 1713, +0, 2346, 0, +415, 2481, 0, +1752, 2616, 0, +2124, 2750, 0, +2378, 2883, 0, +2583, 3016, 0, +2763, 3150, 0, +2928, 3282, 0, +3083, 3414, 0, +3232, 3547, 0, +3376, 3679, 0, +3517, 3812, 0, +3656, 3944, 0, +3793, 4076, 0, +3928, 4095, 0, +0, 1648, 2226, +0, 1656, 2226, +0, 1666, 2225, +0, 1679, 2225, +0, 1695, 2224, +0, 1717, 2223, +0, 1744, 2221, +0, 1778, 2220, +0, 1819, 2217, +0, 1870, 2214, +0, 1929, 2209, +217, 1998, 2203, +217, 2066, 2203, +217, 2142, 2203, +217, 2203, 2176, +217, 2203, 2041, +217, 2203, 1757, +0, 2341, 437, +1199, 2478, 0, +1851, 2613, 0, +2170, 2748, 0, +2405, 2882, 0, +2600, 3015, 0, +2775, 3149, 0, +2936, 3281, 0, +3089, 3414, 0, +3236, 3547, 0, +3379, 3679, 0, +3520, 3812, 0, +3657, 3944, 0, +3794, 4076, 0, +3929, 4095, 0, +0, 1457, 2226, +0, 1469, 2226, +0, 1484, 2225, +0, 1503, 2225, +0, 1527, 2224, +0, 1557, 2223, +0, 1596, 2221, +0, 1642, 2220, +0, 1697, 2217, +0, 1762, 2214, +0, 1836, 2209, +217, 1920, 2203, +1136, 2012, 2194, +1136, 2097, 2194, +1136, 2191, 2194, +1136, 2194, 2069, +1136, 2194, 1809, +345, 2335, 970, +1535, 2473, 0, +1956, 2610, 0, +2226, 2746, 0, +2439, 2880, 0, +2623, 3014, 0, +2790, 3148, 0, +2947, 3280, 0, +3097, 3414, 0, +3242, 3546, 0, +3384, 3679, 0, +3522, 3811, 0, +3659, 3944, 0, +3795, 4076, 0, +3930, 4095, 0, +0, 907, 2226, +0, 944, 2226, +0, 990, 2225, +0, 1044, 2225, +0, 1108, 2224, +0, 1181, 2223, +0, 1264, 2221, +0, 1355, 2220, +0, 1454, 2217, +0, 1560, 2214, +0, 1671, 2209, +217, 1787, 2203, +1136, 1906, 2194, +1487, 2029, 2183, +1487, 2136, 2183, +1487, 2183, 2105, +1487, 2183, 1871, +1270, 2326, 1269, +1776, 2467, 477, +2067, 2605, 0, +2291, 2742, 0, +2480, 2878, 0, +2651, 3012, 0, +2810, 3146, 0, +2961, 3280, 0, +3107, 3413, 0, +3249, 3546, 0, +3389, 3678, 0, +3526, 3811, 0, +3662, 3943, 0, +3798, 4076, 0, +3932, 4095, 0, +0, 0, 2226, +0, 0, 2226, +0, 0, 2225, +0, 0, 2225, +0, 0, 2224, +0, 0, 2223, +0, 0, 2221, +0, 0, 2220, +0, 140, 2217, +0, 932, 2214, +0, 1270, 2209, +217, 1512, 2203, +1136, 1711, 2194, +1487, 1888, 2183, +1733, 2051, 2167, +1733, 2167, 2149, +1733, 2167, 1943, +1718, 2315, 1619, +1976, 2459, 1401, +2183, 2599, 611, +2365, 2738, 0, +2530, 2874, 0, +2686, 3010, 0, +2835, 3144, 0, +2979, 3278, 0, +3120, 3412, 0, +3259, 3545, 0, +3396, 3678, 0, +3532, 3810, 0, +3666, 3943, 0, +3801, 4075, 0, +3934, 4095, 0, +0, 0, 2226, +0, 0, 2226, +0, 0, 2225, +0, 0, 2225, +0, 0, 2224, +0, 0, 2223, +0, 0, 2221, +0, 0, 2220, +0, 0, 2217, +0, 0, 2214, +303, 0, 2209, +838, 217, 2203, +1136, 1137, 2194, +1487, 1585, 2183, +1733, 1862, 2167, +1935, 2078, 2145, +1935, 2145, 2023, +1994, 2299, 1865, +2152, 2447, 1751, +2303, 2591, 1533, +2448, 2731, 738, +2590, 2870, 0, +2729, 3006, 0, +2867, 3142, 0, +3002, 3276, 0, +3137, 3410, 0, +3272, 3544, 0, +3405, 3677, 0, +3539, 3810, 0, +3672, 3943, 0, +3804, 4075, 0, +3937, 4095, 0, +1562, 0, 2226, +1565, 0, 2226, +1570, 0, 2225, +1576, 0, 2225, +1584, 0, 2224, +1595, 0, 2223, +1608, 0, 2221, +1626, 0, 2220, +1649, 0, 2217, +1677, 0, 2214, +1713, 0, 2209, +1757, 217, 2203, +1809, 1136, 2194, +1871, 1487, 2183, +1943, 1733, 2167, +2023, 1935, 2145, +2113, 2113, 2113, +2210, 2277, 2067, +2315, 2431, 1997, +2425, 2579, 1883, +2540, 2723, 1664, +2659, 2863, 870, +2781, 3002, 0, +2906, 3138, 0, +3031, 3274, 0, +3159, 3408, 0, +3288, 3543, 0, +3418, 3676, 0, +3548, 3809, 0, +3679, 3942, 0, +3810, 4075, 0, +3941, 4095, 0, +2078, 0, 2358, +2079, 0, 2358, +2080, 0, 2358, +2082, 0, 2357, +2085, 0, 2357, +2088, 0, 2356, +2093, 0, 2355, +2099, 0, 2353, +2107, 0, 2352, +2118, 0, 2349, +2132, 0, 2346, +2150, 0, 2341, +2173, 345, 2335, +2202, 1269, 2326, +2237, 1619, 2315, +2281, 1865, 2299, +2277, 2067, 2210, +2277, 2155, 2067, +2431, 2414, 1997, +2533, 2579, 1883, +2626, 2723, 1664, +2726, 2863, 870, +2833, 3002, 0, +2946, 3138, 0, +3062, 3274, 0, +3183, 3408, 0, +3306, 3543, 0, +3431, 3676, 0, +3558, 3809, 0, +3686, 3942, 0, +3815, 4075, 0, +3945, 4095, 0, +2371, 0, 2491, +2372, 0, 2491, +2373, 0, 2490, +2374, 0, 2490, +2375, 0, 2489, +2377, 0, 2489, +2379, 0, 2488, +2383, 0, 2487, +2387, 0, 2486, +2393, 0, 2484, +2401, 0, 2481, +2411, 0, 2478, +2423, 0, 2473, +2440, 477, 2467, +2459, 1401, 2455, +2447, 1751, 2401, +2431, 1997, 2315, +2431, 1997, 2126, +2431, 2207, 1997, +2579, 2502, 1883, +2719, 2723, 1664, +2803, 2863, 870, +2895, 3002, 0, +2995, 3138, 0, +3100, 3274, 0, +3212, 3408, 0, +3329, 3543, 0, +3448, 3676, 0, +3571, 3809, 0, +3696, 3942, 0, +3823, 4075, 0, +3951, 4095, 0, +2595, 0, 2623, +2595, 0, 2623, +2596, 0, 2623, +2596, 0, 2622, +2597, 0, 2622, +2598, 0, 2621, +2600, 0, 2621, +2602, 0, 2620, +2604, 0, 2619, +2608, 0, 2618, +2613, 0, 2616, +2613, 0, 2607, +2610, 0, 2592, +2605, 0, 2570, +2599, 611, 2538, +2591, 1533, 2493, +2579, 1883, 2425, +2579, 1883, 2284, +2579, 1883, 1981, +2579, 2267, 1883, +2723, 2598, 1664, +2863, 2837, 870, +2966, 3002, 0, +3053, 3138, 0, +3147, 3274, 0, +3249, 3408, 0, +3357, 3543, 0, +3471, 3676, 0, +3588, 3809, 0, +3709, 3942, 0, +3833, 4075, 0, +3959, 4095, 0, +2755, 0, 2723, +2755, 0, 2723, +2755, 0, 2722, +2755, 0, 2721, +2755, 0, 2720, +2754, 0, 2718, +2754, 0, 2716, +2753, 0, 2713, +2752, 0, 2710, +2751, 0, 2704, +2750, 0, 2697, +2748, 0, 2687, +2746, 0, 2674, +2742, 0, 2656, +2738, 0, 2631, +2731, 738, 2594, +2723, 1664, 2540, +2723, 1664, 2435, +2723, 1664, 2240, +2723, 1664, 1667, +2723, 2338, 1664, +2863, 2701, 870, +3002, 2952, 0, +3120, 3138, 0, +3203, 3274, 0, +3294, 3408, 0, +3393, 3543, 0, +3499, 3676, 0, +3610, 3809, 0, +3726, 3942, 0, +3846, 4075, 0, +3968, 4095, 0, +2887, 0, 2806, +2887, 0, 2805, +2887, 0, 2805, +2887, 0, 2804, +2887, 0, 2803, +2887, 0, 2802, +2886, 0, 2800, +2886, 0, 2798, +2885, 0, 2795, +2885, 0, 2790, +2883, 0, 2784, +2882, 0, 2777, +2880, 0, 2766, +2878, 0, 2751, +2874, 0, 2730, +2870, 0, 2701, +2863, 870, 2659, +2863, 870, 2580, +2863, 870, 2447, +2863, 870, 2173, +2863, 1498, 870, +2863, 2417, 870, +3002, 2810, 0, +3138, 3071, 0, +3268, 3274, 0, +3348, 3408, 0, +3437, 3543, 0, +3534, 3676, 0, +3638, 3809, 0, +3748, 3942, 0, +3862, 4075, 0, +3981, 4095, 0, +3019, 0, 2897, +3019, 0, 2897, +3019, 0, 2896, +3019, 0, 2896, +3019, 0, 2895, +3019, 0, 2894, +3018, 0, 2892, +3018, 0, 2890, +3018, 0, 2888, +3017, 0, 2885, +3016, 0, 2880, +3015, 0, 2873, +3014, 0, 2865, +3012, 0, 2853, +3010, 0, 2836, +3006, 0, 2813, +3002, 0, 2781, +3002, 0, 2722, +3002, 0, 2628, +3002, 0, 2463, +3002, 0, 2062, +3002, 1109, 0, +3002, 2505, 0, +3138, 2925, 0, +3274, 3193, 0, +3408, 3406, 0, +3490, 3543, 0, +3577, 3676, 0, +3672, 3809, 0, +3775, 3942, 0, +3884, 4075, 0, +3998, 4095, 0, +3152, 0, 2996, +3152, 0, 2996, +3152, 0, 2996, +3151, 0, 2995, +3151, 0, 2995, +3151, 0, 2994, +3151, 0, 2993, +3151, 0, 2991, +3151, 0, 2989, +3150, 0, 2986, +3150, 0, 2982, +3149, 0, 2977, +3148, 0, 2970, +3146, 0, 2961, +3144, 0, 2948, +3142, 0, 2931, +3138, 0, 2906, +3138, 0, 2861, +3138, 0, 2795, +3138, 0, 2687, +3138, 0, 2484, +3138, 0, 1857, +3138, 0, 0, +3138, 2602, 0, +3274, 3042, 0, +3408, 3317, 0, +3543, 3533, 0, +3629, 3676, 0, +3715, 3809, 0, +3809, 3942, 0, +3911, 4075, 0, +4019, 4095, 0, +3284, 0, 3102, +3283, 0, 3102, +3283, 0, 3101, +3283, 0, 3101, +3283, 0, 3101, +3283, 0, 3100, +3283, 0, 3099, +3283, 0, 3098, +3283, 0, 3096, +3282, 0, 3094, +3282, 0, 3091, +3281, 0, 3087, +3280, 0, 3082, +3280, 0, 3074, +3278, 0, 3064, +3276, 0, 3050, +3274, 0, 3031, +3274, 0, 2998, +3274, 0, 2950, +3274, 0, 2876, +3274, 0, 2753, +3274, 0, 2510, +3274, 0, 1202, +3274, 0, 0, +3274, 2706, 0, +3408, 3164, 0, +3543, 3444, 0, +3676, 3662, 0, +3766, 3809, 0, +3851, 3942, 0, +3945, 4075, 0, +4046, 4095, 0, +3416, 0, 3213, +3416, 0, 3213, +3416, 0, 3213, +3416, 0, 3213, +3416, 0, 3212, +3416, 0, 3212, +3415, 0, 3211, +3415, 0, 3210, +3415, 0, 3209, +3415, 0, 3207, +3414, 0, 3205, +3414, 0, 3202, +3414, 0, 3198, +3413, 0, 3192, +3412, 0, 3184, +3410, 0, 3174, +3408, 0, 3159, +3408, 0, 3134, +3408, 0, 3099, +3408, 0, 3047, +3408, 0, 2966, +3408, 0, 2830, +3408, 0, 2545, +3408, 0, 0, +3408, 0, 0, +3408, 2815, 0, +3543, 3288, 0, +3676, 3572, 0, +3809, 3791, 0, +3902, 3942, 0, +3986, 4075, 0, +4080, 4095, 0, +3548, 0, 3329, +3548, 0, 3329, +3548, 0, 3329, +3548, 0, 3329, +3548, 0, 3329, +3548, 0, 3328, +3548, 0, 3328, +3548, 0, 3327, +3548, 0, 3326, +3547, 0, 3325, +3547, 0, 3323, +3547, 0, 3320, +3546, 0, 3317, +3546, 0, 3313, +3545, 0, 3307, +3544, 0, 3299, +3543, 0, 3288, +3543, 0, 3270, +3543, 0, 3243, +3543, 0, 3206, +3543, 0, 3151, +3543, 0, 3065, +3543, 0, 2917, +3543, 0, 2585, +3543, 0, 0, +3543, 0, 0, +3543, 2929, 0, +3676, 3414, 0, +3809, 3700, 0, +3942, 3921, 0, +4037, 4075, 0, +4095, 4095, 0, +3680, 0, 3449, +3680, 0, 3449, +3680, 0, 3449, +3680, 0, 3449, +3680, 0, 3448, +3680, 0, 3448, +3680, 0, 3448, +3680, 0, 3447, +3680, 0, 3446, +3680, 0, 3445, +3679, 0, 3444, +3679, 0, 3442, +3679, 0, 3440, +3678, 0, 3436, +3678, 0, 3432, +3677, 0, 3426, +3676, 0, 3418, +3676, 0, 3404, +3676, 0, 3385, +3676, 0, 3358, +3676, 0, 3319, +3676, 0, 3261, +3676, 0, 3170, +3676, 0, 3010, +3676, 0, 2636, +3676, 0, 0, +3676, 0, 0, +3676, 3048, 0, +3809, 3542, 0, +3942, 3830, 0, +4075, 4051, 0, +4095, 4095, 0, +3812, 0, 3572, +3812, 0, 3572, +3812, 0, 3572, +3812, 0, 3571, +3812, 0, 3571, +3812, 0, 3571, +3812, 0, 3571, +3812, 0, 3570, +3812, 0, 3570, +3812, 0, 3569, +3812, 0, 3568, +3812, 0, 3566, +3811, 0, 3564, +3811, 0, 3562, +3810, 0, 3559, +3810, 0, 3554, +3809, 0, 3548, +3809, 0, 3537, +3809, 0, 3523, +3809, 0, 3503, +3809, 0, 3475, +3809, 0, 3435, +3809, 0, 3376, +3809, 0, 3281, +3809, 0, 3112, +3809, 0, 2694, +3809, 0, 0, +3809, 0, 0, +3809, 3169, 0, +3942, 3670, 0, +4075, 3960, 0, +4095, 4095, 0, +3944, 0, 3696, +3944, 0, 3696, +3944, 0, 3696, +3944, 0, 3696, +3944, 0, 3696, +3944, 0, 3696, +3944, 0, 3696, +3944, 0, 3695, +3944, 0, 3695, +3944, 0, 3694, +3944, 0, 3694, +3944, 0, 3692, +3944, 0, 3691, +3943, 0, 3689, +3943, 0, 3687, +3943, 0, 3683, +3942, 0, 3679, +3942, 0, 3671, +3942, 0, 3660, +3942, 0, 3646, +3942, 0, 3626, +3942, 0, 3597, +3942, 0, 3556, +3942, 0, 3494, +3942, 0, 3396, +3942, 0, 3220, +3942, 0, 2762, +3942, 0, 0, +3942, 0, 0, +3942, 3293, 0, +4075, 3799, 0, +4095, 4091, 0, +4076, 0, 3823, +4076, 0, 3823, +4076, 0, 3823, +4076, 0, 3823, +4076, 0, 3823, +4076, 0, 3822, +4076, 0, 3822, +4076, 0, 3822, +4076, 0, 3822, +4076, 0, 3821, +4076, 0, 3821, +4076, 0, 3820, +4076, 0, 3819, +4076, 0, 3817, +4075, 0, 3816, +4075, 0, 3813, +4075, 0, 3810, +4075, 0, 3803, +4075, 0, 3796, +4075, 0, 3785, +4075, 0, 3770, +4075, 0, 3750, +4075, 0, 3721, +4075, 0, 3679, +4075, 0, 3616, +4075, 0, 3515, +4075, 0, 3333, +4075, 0, 2839, +4075, 0, 0, +4075, 0, 0, +4075, 3419, 0, +4095, 3930, 0, +4095, 0, 3951, +4095, 0, 3951, +4095, 0, 3951, +4095, 0, 3951, +4095, 0, 3951, +4095, 0, 3951, +4095, 0, 3951, +4095, 0, 3950, +4095, 0, 3950, +4095, 0, 3950, +4095, 0, 3950, +4095, 0, 3949, +4095, 0, 3948, +4095, 0, 3947, +4095, 0, 3945, +4095, 0, 3944, +4095, 0, 3941, +4095, 0, 3937, +4095, 0, 3931, +4095, 0, 3923, +4095, 0, 3912, +4095, 0, 3897, +4095, 0, 3876, +4095, 0, 3847, +4095, 0, 3804, +4095, 0, 3741, +4095, 0, 3638, +4095, 0, 3450, +4095, 0, 2927, +4095, 0, 0, +4095, 0, 0, +4095, 3547, 0, +0, 2090, 2358, +0, 2093, 2358, +0, 2096, 2358, +0, 2100, 2358, +0, 2106, 2358, +0, 2113, 2358, +0, 2123, 2358, +0, 2136, 2358, +0, 2152, 2358, +0, 2173, 2358, +0, 2200, 2358, +0, 2233, 2358, +0, 2275, 2358, +0, 2325, 2358, +0, 2358, 2332, +0, 2358, 2239, +0, 2358, 2078, +0, 2358, 1692, +0, 2491, 0, +0, 2623, 0, +1353, 2755, 0, +2091, 2887, 0, +2422, 3019, 0, +2662, 3152, 0, +2860, 3284, 0, +3036, 3416, 0, +3198, 3548, 0, +3352, 3680, 0, +3499, 3812, 0, +3643, 3944, 0, +3783, 4076, 0, +3921, 4095, 0, +0, 2088, 2358, +0, 2091, 2358, +0, 2094, 2358, +0, 2098, 2358, +0, 2104, 2358, +0, 2111, 2358, +0, 2121, 2358, +0, 2134, 2358, +0, 2150, 2358, +0, 2171, 2358, +0, 2199, 2358, +0, 2232, 2358, +0, 2273, 2358, +0, 2324, 2358, +0, 2358, 2332, +0, 2358, 2240, +0, 2358, 2079, +0, 2358, 1694, +0, 2491, 0, +0, 2623, 0, +1367, 2755, 0, +2094, 2887, 0, +2424, 3019, 0, +2663, 3152, 0, +2860, 3283, 0, +3036, 3416, 0, +3199, 3548, 0, +3352, 3680, 0, +3499, 3812, 0, +3643, 3944, 0, +3783, 4076, 0, +3921, 4095, 0, +0, 2085, 2358, +0, 2087, 2358, +0, 2091, 2358, +0, 2096, 2358, +0, 2101, 2358, +0, 2109, 2358, +0, 2119, 2358, +0, 2132, 2358, +0, 2148, 2358, +0, 2169, 2358, +0, 2196, 2358, +0, 2230, 2358, +0, 2271, 2358, +0, 2322, 2358, +0, 2358, 2333, +0, 2358, 2241, +0, 2358, 2080, +0, 2358, 1698, +0, 2490, 0, +0, 2623, 0, +1386, 2755, 0, +2098, 2887, 0, +2426, 3019, 0, +2664, 3152, 0, +2861, 3283, 0, +3037, 3416, 0, +3199, 3548, 0, +3353, 3680, 0, +3500, 3812, 0, +3643, 3944, 0, +3783, 4076, 0, +3921, 4095, 0, +0, 2080, 2358, +0, 2083, 2358, +0, 2087, 2358, +0, 2092, 2357, +0, 2098, 2357, +0, 2105, 2357, +0, 2115, 2357, +0, 2128, 2357, +0, 2145, 2357, +0, 2166, 2357, +0, 2193, 2357, +0, 2228, 2357, +0, 2269, 2357, +0, 2320, 2357, +0, 2357, 2334, +0, 2357, 2243, +0, 2357, 2082, +0, 2357, 1702, +0, 2490, 0, +0, 2622, 0, +1409, 2755, 0, +2103, 2887, 0, +2428, 3019, 0, +2665, 3151, 0, +2862, 3283, 0, +3038, 3416, 0, +3200, 3548, 0, +3353, 3680, 0, +3500, 3812, 0, +3643, 3944, 0, +3783, 4076, 0, +3921, 4095, 0, +0, 2074, 2358, +0, 2077, 2358, +0, 2081, 2358, +0, 2086, 2357, +0, 2093, 2357, +0, 2101, 2357, +0, 2111, 2357, +0, 2124, 2357, +0, 2141, 2357, +0, 2162, 2357, +0, 2190, 2357, +0, 2224, 2357, +0, 2266, 2357, +0, 2317, 2357, +0, 2357, 2335, +0, 2357, 2245, +0, 2357, 2085, +0, 2357, 1708, +0, 2489, 0, +0, 2622, 0, +1439, 2755, 0, +2110, 2887, 0, +2431, 3019, 0, +2667, 3151, 0, +2863, 3283, 0, +3038, 3416, 0, +3200, 3548, 0, +3353, 3680, 0, +3500, 3812, 0, +3643, 3944, 0, +3783, 4076, 0, +3921, 4095, 0, +0, 2066, 2358, +0, 2069, 2358, +0, 2073, 2358, +0, 2078, 2357, +0, 2086, 2357, +0, 2095, 2356, +0, 2105, 2356, +0, 2118, 2356, +0, 2135, 2356, +0, 2157, 2356, +0, 2185, 2356, +0, 2219, 2356, +0, 2262, 2356, +0, 2313, 2356, +0, 2356, 2338, +0, 2356, 2247, +0, 2356, 2088, +0, 2356, 1716, +0, 2489, 0, +0, 2621, 0, +1476, 2754, 0, +2118, 2887, 0, +2435, 3019, 0, +2670, 3151, 0, +2865, 3283, 0, +3039, 3416, 0, +3201, 3548, 0, +3354, 3680, 0, +3501, 3812, 0, +3644, 3944, 0, +3784, 4076, 0, +3922, 4095, 0, +0, 2055, 2358, +0, 2058, 2358, +0, 2062, 2358, +0, 2068, 2357, +0, 2075, 2357, +0, 2084, 2356, +0, 2096, 2355, +0, 2110, 2355, +0, 2127, 2355, +0, 2150, 2355, +0, 2178, 2355, +0, 2213, 2355, +0, 2256, 2355, +0, 2308, 2355, +0, 2355, 2340, +0, 2355, 2251, +0, 2355, 2093, +0, 2355, 1727, +0, 2488, 0, +0, 2621, 0, +1521, 2754, 0, +2129, 2886, 0, +2441, 3018, 0, +2673, 3151, 0, +2867, 3283, 0, +3041, 3415, 0, +3202, 3548, 0, +3354, 3680, 0, +3501, 3812, 0, +3644, 3944, 0, +3784, 4076, 0, +3922, 4095, 0, +0, 2040, 2358, +0, 2043, 2358, +0, 2047, 2358, +0, 2053, 2357, +0, 2060, 2357, +0, 2070, 2356, +0, 2083, 2355, +0, 2099, 2353, +0, 2117, 2353, +0, 2140, 2353, +0, 2168, 2353, +0, 2204, 2353, +0, 2248, 2353, +0, 2301, 2353, +0, 2353, 2344, +0, 2353, 2255, +0, 2353, 2099, +0, 2353, 1740, +0, 2487, 0, +0, 2620, 0, +1575, 2753, 0, +2144, 2886, 0, +2449, 3018, 0, +2678, 3151, 0, +2870, 3283, 0, +3043, 3415, 0, +3203, 3548, 0, +3356, 3680, 0, +3502, 3812, 0, +3645, 3944, 0, +3784, 4076, 0, +3922, 4095, 0, +0, 2019, 2358, +0, 2022, 2358, +0, 2027, 2358, +0, 2032, 2357, +0, 2040, 2357, +0, 2050, 2356, +0, 2063, 2355, +0, 2081, 2353, +0, 2102, 2352, +0, 2126, 2352, +0, 2155, 2352, +0, 2192, 2352, +0, 2237, 2352, +0, 2291, 2352, +0, 2352, 2349, +0, 2352, 2261, +0, 2352, 2107, +0, 2352, 1758, +0, 2486, 0, +0, 2619, 0, +1638, 2752, 0, +2163, 2885, 0, +2459, 3018, 0, +2684, 3151, 0, +2874, 3283, 0, +3046, 3415, 0, +3205, 3548, 0, +3357, 3680, 0, +3503, 3812, 0, +3645, 3944, 0, +3785, 4076, 0, +3923, 4095, 0, +0, 1989, 2358, +0, 1993, 2358, +0, 1997, 2358, +0, 2004, 2357, +0, 2012, 2357, +0, 2022, 2356, +0, 2037, 2355, +0, 2054, 2353, +0, 2078, 2352, +0, 2107, 2349, +0, 2138, 2349, +0, 2176, 2349, +0, 2223, 2349, +0, 2278, 2349, +0, 2343, 2349, +0, 2349, 2268, +0, 2349, 2118, +0, 2349, 1781, +0, 2484, 0, +0, 2618, 0, +1711, 2751, 0, +2188, 2885, 0, +2471, 3017, 0, +2691, 3150, 0, +2879, 3282, 0, +3049, 3415, 0, +3208, 3547, 0, +3359, 3680, 0, +3504, 3812, 0, +3646, 3944, 0, +3785, 4076, 0, +3923, 4095, 0, +0, 1946, 2358, +0, 1950, 2358, +0, 1955, 2358, +0, 1962, 2357, +0, 1970, 2357, +0, 1982, 2356, +0, 1998, 2355, +0, 2017, 2353, +0, 2042, 2352, +0, 2074, 2349, +0, 2113, 2346, +0, 2153, 2346, +0, 2202, 2346, +0, 2260, 2346, +0, 2328, 2346, +0, 2346, 2278, +0, 2346, 2132, +0, 2346, 1809, +0, 2481, 0, +0, 2616, 0, +1794, 2750, 0, +2218, 2883, 0, +2488, 3016, 0, +2702, 3150, 0, +2886, 3282, 0, +3054, 3414, 0, +3211, 3547, 0, +3361, 3679, 0, +3506, 3812, 0, +3648, 3944, 0, +3787, 4076, 0, +3924, 4095, 0, +0, 1880, 2358, +0, 1885, 2358, +0, 1891, 2358, +0, 1899, 2357, +0, 1909, 2357, +0, 1922, 2356, +0, 1940, 2355, +0, 1962, 2353, +0, 1990, 2352, +0, 2025, 2349, +0, 2069, 2346, +0, 2120, 2341, +0, 2173, 2341, +0, 2234, 2341, +0, 2305, 2341, +0, 2341, 2291, +0, 2341, 2150, +0, 2341, 1845, +0, 2478, 0, +547, 2613, 0, +1885, 2748, 0, +2256, 2882, 0, +2510, 3015, 0, +2715, 3149, 0, +2895, 3281, 0, +3060, 3414, 0, +3216, 3547, 0, +3364, 3679, 0, +3508, 3812, 0, +3649, 3944, 0, +3787, 4076, 0, +3925, 4095, 0, +0, 1775, 2358, +0, 1781, 2358, +0, 1788, 2358, +0, 1798, 2357, +0, 1811, 2357, +0, 1828, 2356, +0, 1849, 2355, +0, 1876, 2353, +0, 1910, 2352, +0, 1951, 2349, +0, 2002, 2346, +0, 2061, 2341, +345, 2131, 2335, +345, 2198, 2335, +345, 2274, 2335, +345, 2335, 2308, +345, 2335, 2173, +345, 2335, 1889, +0, 2473, 557, +1330, 2610, 0, +1983, 2746, 0, +2302, 2880, 0, +2536, 3014, 0, +2733, 3148, 0, +2907, 3280, 0, +3069, 3414, 0, +3221, 3546, 0, +3368, 3679, 0, +3511, 3811, 0, +3651, 3944, 0, +3789, 4076, 0, +3926, 4095, 0, +0, 1580, 2358, +0, 1589, 2358, +0, 1600, 2358, +0, 1615, 2357, +0, 1634, 2357, +0, 1659, 2356, +0, 1689, 2355, +0, 1727, 2353, +0, 1773, 2352, +0, 1829, 2349, +0, 1894, 2346, +0, 1968, 2341, +345, 2052, 2335, +1269, 2144, 2326, +1269, 2229, 2326, +1269, 2323, 2326, +1269, 2326, 2202, +1269, 2326, 1941, +477, 2467, 1099, +1667, 2605, 0, +2089, 2742, 0, +2358, 2878, 0, +2570, 3012, 0, +2755, 3146, 0, +2922, 3280, 0, +3079, 3413, 0, +3229, 3546, 0, +3374, 3678, 0, +3516, 3811, 0, +3655, 3943, 0, +3792, 4076, 0, +3927, 4095, 0, +0, 1009, 2358, +0, 1039, 2358, +0, 1076, 2358, +0, 1122, 2357, +0, 1176, 2357, +0, 1240, 2356, +0, 1313, 2355, +0, 1396, 2353, +0, 1487, 2352, +0, 1586, 2349, +0, 1692, 2346, +0, 1803, 2341, +345, 1919, 2335, +1269, 2038, 2326, +1619, 2161, 2315, +1619, 2268, 2315, +1619, 2315, 2237, +1619, 2315, 2003, +1403, 2459, 1401, +1908, 2599, 611, +2200, 2738, 0, +2423, 2874, 0, +2612, 3010, 0, +2783, 3144, 0, +2942, 3278, 0, +3093, 3412, 0, +3239, 3545, 0, +3381, 3678, 0, +3521, 3810, 0, +3659, 3943, 0, +3795, 4075, 0, +3930, 4095, 0, +0, 0, 2358, +0, 0, 2358, +0, 0, 2358, +0, 0, 2357, +0, 0, 2357, +0, 0, 2356, +0, 0, 2355, +0, 0, 2353, +0, 0, 2352, +0, 275, 2349, +0, 1064, 2346, +0, 1403, 2341, +345, 1644, 2335, +1269, 1843, 2326, +1619, 2020, 2315, +1865, 2183, 2299, +1865, 2299, 2281, +1865, 2299, 2075, +1850, 2447, 1751, +2108, 2591, 1533, +2315, 2731, 738, +2497, 2870, 0, +2662, 3006, 0, +2818, 3142, 0, +2967, 3276, 0, +3111, 3410, 0, +3253, 3544, 0, +3391, 3677, 0, +3528, 3810, 0, +3664, 3943, 0, +3798, 4075, 0, +3933, 4095, 0, +0, 0, 2358, +0, 0, 2358, +0, 0, 2358, +0, 0, 2357, +0, 0, 2357, +0, 0, 2356, +0, 0, 2355, +0, 0, 2353, +0, 0, 2352, +0, 0, 2349, +0, 0, 2346, +437, 0, 2341, +970, 345, 2335, +1269, 1270, 2326, +1619, 1718, 2315, +1865, 1994, 2299, +2067, 2210, 2277, +2067, 2277, 2155, +2126, 2431, 1997, +2284, 2579, 1883, +2435, 2723, 1664, +2580, 2863, 870, +2722, 3002, 0, +2861, 3138, 0, +2998, 3274, 0, +3134, 3408, 0, +3270, 3543, 0, +3404, 3676, 0, +3537, 3809, 0, +3671, 3942, 0, +3803, 4075, 0, +3937, 4095, 0, +1692, 0, 2358, +1694, 0, 2358, +1698, 0, 2358, +1702, 0, 2357, +1708, 0, 2357, +1716, 0, 2356, +1727, 0, 2355, +1740, 0, 2353, +1758, 0, 2352, +1781, 0, 2349, +1809, 0, 2346, +1845, 0, 2341, +1889, 345, 2335, +1941, 1269, 2326, +2003, 1619, 2315, +2075, 1865, 2299, +2155, 2067, 2277, +2245, 2245, 2245, +2343, 2409, 2199, +2447, 2563, 2129, +2557, 2711, 2015, +2672, 2855, 1796, +2791, 2995, 1006, +2913, 3134, 0, +3037, 3270, 0, +3164, 3406, 0, +3291, 3541, 0, +3420, 3675, 0, +3550, 3808, 0, +3680, 3941, 0, +3810, 4074, 0, +3942, 4095, 0, +2209, 0, 2491, +2210, 0, 2491, +2211, 0, 2490, +2213, 0, 2490, +2215, 0, 2489, +2218, 0, 2489, +2221, 0, 2488, +2226, 0, 2487, +2232, 0, 2486, +2240, 0, 2484, +2251, 0, 2481, +2264, 0, 2478, +2282, 0, 2473, +2305, 477, 2467, +2334, 1401, 2459, +2370, 1751, 2447, +2414, 1997, 2431, +2409, 2199, 2343, +2409, 2288, 2199, +2563, 2545, 2129, +2665, 2711, 2015, +2758, 2855, 1796, +2858, 2995, 1006, +2965, 3134, 0, +3078, 3270, 0, +3194, 3406, 0, +3315, 3541, 0, +3438, 3675, 0, +3563, 3808, 0, +3690, 3941, 0, +3818, 4074, 0, +3947, 4095, 0, +2503, 0, 2623, +2503, 0, 2623, +2504, 0, 2623, +2505, 0, 2622, +2506, 0, 2622, +2507, 0, 2621, +2509, 0, 2621, +2511, 0, 2620, +2515, 0, 2619, +2519, 0, 2618, +2525, 0, 2616, +2533, 0, 2613, +2543, 0, 2610, +2556, 0, 2605, +2572, 611, 2599, +2591, 1533, 2587, +2579, 1883, 2533, +2563, 2129, 2447, +2563, 2129, 2258, +2563, 2339, 2129, +2711, 2634, 2015, +2852, 2855, 1796, +2935, 2995, 1006, +3027, 3134, 0, +3126, 3270, 0, +3233, 3406, 0, +3344, 3541, 0, +3461, 3675, 0, +3581, 3808, 0, +3703, 3941, 0, +3828, 4074, 0, +3955, 4095, 0, +2727, 0, 2755, +2727, 0, 2755, +2728, 0, 2755, +2728, 0, 2755, +2729, 0, 2755, +2730, 0, 2754, +2731, 0, 2754, +2732, 0, 2753, +2734, 0, 2752, +2737, 0, 2751, +2741, 0, 2750, +2745, 0, 2748, +2746, 0, 2740, +2742, 0, 2724, +2738, 0, 2702, +2731, 738, 2671, +2723, 1664, 2626, +2711, 2015, 2557, +2711, 2015, 2416, +2711, 2015, 2114, +2711, 2400, 2015, +2855, 2730, 1796, +2995, 2968, 1006, +3098, 3134, 0, +3184, 3270, 0, +3279, 3406, 0, +3381, 3541, 0, +3490, 3675, 0, +3603, 3808, 0, +3720, 3941, 0, +3841, 4074, 0, +3965, 4095, 0, +2887, 0, 2856, +2887, 0, 2855, +2887, 0, 2855, +2887, 0, 2854, +2887, 0, 2853, +2887, 0, 2852, +2886, 0, 2850, +2886, 0, 2848, +2885, 0, 2845, +2885, 0, 2842, +2883, 0, 2836, +2882, 0, 2829, +2880, 0, 2820, +2878, 0, 2807, +2874, 0, 2788, +2870, 0, 2763, +2863, 870, 2726, +2855, 1796, 2672, +2855, 1796, 2567, +2855, 1796, 2372, +2855, 1796, 1797, +2855, 2470, 1796, +2995, 2833, 1006, +3134, 3084, 0, +3252, 3270, 0, +3335, 3406, 0, +3426, 3541, 0, +3525, 3675, 0, +3631, 3808, 0, +3742, 3941, 0, +3858, 4074, 0, +3978, 4095, 0, +3019, 0, 2938, +3019, 0, 2938, +3019, 0, 2938, +3019, 0, 2937, +3019, 0, 2936, +3019, 0, 2935, +3018, 0, 2934, +3018, 0, 2932, +3018, 0, 2930, +3017, 0, 2927, +3016, 0, 2922, +3015, 0, 2916, +3014, 0, 2908, +3012, 0, 2898, +3010, 0, 2883, +3006, 0, 2862, +3002, 0, 2833, +2995, 1006, 2791, +2995, 1006, 2712, +2995, 1006, 2579, +2995, 1006, 2303, +2995, 1635, 1006, +2995, 2549, 1006, +3134, 2943, 0, +3270, 3203, 0, +3400, 3406, 0, +3480, 3541, 0, +3569, 3675, 0, +3666, 3808, 0, +3770, 3941, 0, +3880, 4074, 0, +3994, 4095, 0, +3152, 0, 3030, +3152, 0, 3029, +3152, 0, 3029, +3151, 0, 3029, +3151, 0, 3028, +3151, 0, 3027, +3151, 0, 3026, +3151, 0, 3025, +3151, 0, 3023, +3150, 0, 3020, +3150, 0, 3017, +3149, 0, 3012, +3148, 0, 3005, +3146, 0, 2997, +3144, 0, 2985, +3142, 0, 2969, +3138, 0, 2946, +3134, 0, 2913, +3134, 0, 2854, +3134, 0, 2761, +3134, 0, 2596, +3134, 0, 2195, +3134, 1211, 0, +3134, 2638, 0, +3270, 3056, 0, +3406, 3325, 0, +3541, 3538, 0, +3622, 3675, 0, +3709, 3808, 0, +3805, 3941, 0, +3907, 4074, 0, +4016, 4095, 0, +3284, 0, 3128, +3283, 0, 3128, +3283, 0, 3128, +3283, 0, 3128, +3283, 0, 3127, +3283, 0, 3127, +3283, 0, 3126, +3283, 0, 3125, +3283, 0, 3123, +3282, 0, 3121, +3282, 0, 3118, +3281, 0, 3114, +3280, 0, 3109, +3280, 0, 3102, +3278, 0, 3093, +3276, 0, 3080, +3274, 0, 3062, +3270, 0, 3037, +3270, 0, 2993, +3270, 0, 2926, +3270, 0, 2818, +3270, 0, 2616, +3270, 0, 1990, +3270, 0, 0, +3270, 2734, 0, +3406, 3175, 0, +3541, 3450, 0, +3675, 3665, 0, +3761, 3808, 0, +3847, 3941, 0, +3941, 4074, 0, +4043, 4095, 0, +3416, 0, 3234, +3416, 0, 3234, +3416, 0, 3234, +3416, 0, 3234, +3416, 0, 3233, +3416, 0, 3233, +3415, 0, 3232, +3415, 0, 3231, +3415, 0, 3230, +3415, 0, 3228, +3414, 0, 3226, +3414, 0, 3223, +3414, 0, 3219, +3413, 0, 3214, +3412, 0, 3206, +3410, 0, 3196, +3408, 0, 3183, +3406, 0, 3164, +3406, 0, 3131, +3406, 0, 3082, +3406, 0, 3008, +3406, 0, 2886, +3406, 0, 2643, +3406, 0, 1325, +3406, 0, 0, +3406, 2838, 0, +3541, 3296, 0, +3675, 3576, 0, +3808, 3794, 0, +3898, 3941, 0, +3983, 4074, 0, +4077, 4095, 0, +3548, 0, 3346, +3548, 0, 3346, +3548, 0, 3346, +3548, 0, 3345, +3548, 0, 3345, +3548, 0, 3344, +3548, 0, 3344, +3548, 0, 3343, +3548, 0, 3342, +3547, 0, 3341, +3547, 0, 3339, +3547, 0, 3337, +3546, 0, 3334, +3546, 0, 3330, +3545, 0, 3324, +3544, 0, 3316, +3543, 0, 3306, +3541, 0, 3291, +3541, 0, 3267, +3541, 0, 3231, +3541, 0, 3179, +3541, 0, 3099, +3541, 0, 2963, +3541, 0, 2676, +3541, 0, 0, +3541, 0, 0, +3541, 2947, 0, +3675, 3420, 0, +3808, 3704, 0, +3941, 3923, 0, +4034, 4074, 0, +4095, 4095, 0, +3680, 0, 3462, +3680, 0, 3462, +3680, 0, 3462, +3680, 0, 3461, +3680, 0, 3461, +3680, 0, 3461, +3680, 0, 3460, +3680, 0, 3460, +3680, 0, 3459, +3680, 0, 3458, +3679, 0, 3457, +3679, 0, 3455, +3679, 0, 3453, +3678, 0, 3449, +3678, 0, 3445, +3677, 0, 3439, +3676, 0, 3431, +3675, 0, 3420, +3675, 0, 3402, +3675, 0, 3376, +3675, 0, 3338, +3675, 0, 3283, +3675, 0, 3197, +3675, 0, 3048, +3675, 0, 2718, +3675, 0, 0, +3675, 0, 0, +3675, 3061, 0, +3808, 3546, 0, +3941, 3832, 0, +4074, 4053, 0, +4095, 4095, 0, +3812, 0, 3581, +3812, 0, 3581, +3812, 0, 3581, +3812, 0, 3581, +3812, 0, 3581, +3812, 0, 3581, +3812, 0, 3580, +3812, 0, 3580, +3812, 0, 3579, +3812, 0, 3579, +3812, 0, 3577, +3812, 0, 3576, +3811, 0, 3574, +3811, 0, 3572, +3810, 0, 3569, +3810, 0, 3564, +3809, 0, 3558, +3808, 0, 3550, +3808, 0, 3536, +3808, 0, 3517, +3808, 0, 3490, +3808, 0, 3451, +3808, 0, 3393, +3808, 0, 3302, +3808, 0, 3143, +3808, 0, 2767, +3808, 0, 0, +3808, 0, 0, +3808, 3180, 0, +3941, 3674, 0, +4074, 3962, 0, +4095, 4095, 0, +3944, 0, 3704, +3944, 0, 3704, +3944, 0, 3704, +3944, 0, 3703, +3944, 0, 3703, +3944, 0, 3703, +3944, 0, 3703, +3944, 0, 3703, +3944, 0, 3702, +3944, 0, 3702, +3944, 0, 3701, +3944, 0, 3700, +3944, 0, 3699, +3943, 0, 3697, +3943, 0, 3694, +3943, 0, 3691, +3942, 0, 3686, +3941, 0, 3680, +3941, 0, 3669, +3941, 0, 3655, +3941, 0, 3635, +3941, 0, 3608, +3941, 0, 3568, +3941, 0, 3507, +3941, 0, 3413, +3941, 0, 3244, +3941, 0, 2826, +3941, 0, 0, +3941, 0, 0, +3941, 3302, 0, +4074, 3802, 0, +4095, 4092, 0, +4076, 0, 3828, +4076, 0, 3828, +4076, 0, 3828, +4076, 0, 3828, +4076, 0, 3828, +4076, 0, 3828, +4076, 0, 3828, +4076, 0, 3828, +4076, 0, 3827, +4076, 0, 3827, +4076, 0, 3826, +4076, 0, 3826, +4076, 0, 3824, +4076, 0, 3823, +4075, 0, 3821, +4075, 0, 3818, +4075, 0, 3815, +4074, 0, 3810, +4074, 0, 3803, +4074, 0, 3792, +4074, 0, 3777, +4074, 0, 3757, +4074, 0, 3729, +4074, 0, 3688, +4074, 0, 3626, +4074, 0, 3528, +4074, 0, 3351, +4074, 0, 2893, +4074, 0, 0, +4074, 0, 0, +4074, 3426, 0, +4095, 3932, 0, +4095, 0, 3955, +4095, 0, 3955, +4095, 0, 3955, +4095, 0, 3955, +4095, 0, 3955, +4095, 0, 3955, +4095, 0, 3955, +4095, 0, 3955, +4095, 0, 3954, +4095, 0, 3954, +4095, 0, 3954, +4095, 0, 3953, +4095, 0, 3952, +4095, 0, 3951, +4095, 0, 3950, +4095, 0, 3948, +4095, 0, 3945, +4095, 0, 3942, +4095, 0, 3936, +4095, 0, 3928, +4095, 0, 3917, +4095, 0, 3903, +4095, 0, 3882, +4095, 0, 3853, +4095, 0, 3811, +4095, 0, 3748, +4095, 0, 3648, +4095, 0, 3465, +4095, 0, 2973, +4095, 0, 0, +4095, 0, 0, +4095, 3552, 0, +0, 2222, 2491, +0, 2224, 2491, +0, 2226, 2491, +0, 2230, 2491, +0, 2234, 2491, +0, 2239, 2491, +0, 2247, 2491, +0, 2256, 2491, +0, 2269, 2491, +0, 2285, 2491, +0, 2306, 2491, +0, 2333, 2491, +0, 2367, 2491, +0, 2408, 2491, +0, 2458, 2491, +0, 2491, 2463, +0, 2491, 2371, +0, 2491, 2209, +0, 2491, 1822, +0, 2623, 0, +0, 2755, 0, +1472, 2887, 0, +2220, 3019, 0, +2554, 3152, 0, +2793, 3284, 0, +2992, 3416, 0, +3168, 3548, 0, +3330, 3680, 0, +3484, 3812, 0, +3631, 3944, 0, +3774, 4076, 0, +3915, 4095, 0, +0, 2220, 2491, +0, 2223, 2491, +0, 2225, 2491, +0, 2228, 2491, +0, 2233, 2491, +0, 2238, 2491, +0, 2245, 2491, +0, 2255, 2491, +0, 2268, 2491, +0, 2284, 2491, +0, 2305, 2491, +0, 2332, 2491, +0, 2366, 2491, +0, 2407, 2491, +0, 2457, 2491, +0, 2491, 2464, +0, 2491, 2372, +0, 2491, 2210, +0, 2491, 1824, +0, 2623, 0, +0, 2755, 0, +1483, 2887, 0, +2222, 3019, 0, +2555, 3152, 0, +2793, 3283, 0, +2992, 3416, 0, +3168, 3548, 0, +3331, 3680, 0, +3484, 3812, 0, +3632, 3944, 0, +3775, 4076, 0, +3915, 4095, 0, +0, 2218, 2491, +0, 2220, 2491, +0, 2223, 2490, +0, 2226, 2490, +0, 2230, 2490, +0, 2236, 2490, +0, 2243, 2490, +0, 2253, 2490, +0, 2266, 2490, +0, 2283, 2490, +0, 2304, 2490, +0, 2331, 2490, +0, 2364, 2490, +0, 2406, 2490, +0, 2456, 2490, +0, 2490, 2464, +0, 2490, 2373, +0, 2490, 2211, +0, 2490, 1826, +0, 2623, 0, +0, 2755, 0, +1497, 2887, 0, +2225, 3019, 0, +2556, 3152, 0, +2794, 3283, 0, +2992, 3416, 0, +3168, 3548, 0, +3331, 3680, 0, +3484, 3812, 0, +3632, 3944, 0, +3775, 4076, 0, +3915, 4095, 0, +0, 2215, 2491, +0, 2217, 2491, +0, 2220, 2490, +0, 2223, 2490, +0, 2228, 2490, +0, 2234, 2490, +0, 2241, 2490, +0, 2251, 2490, +0, 2264, 2490, +0, 2280, 2490, +0, 2302, 2490, +0, 2329, 2490, +0, 2362, 2490, +0, 2404, 2490, +0, 2454, 2490, +0, 2490, 2465, +0, 2490, 2374, +0, 2490, 2213, +0, 2490, 1830, +0, 2622, 0, +0, 2755, 0, +1516, 2887, 0, +2229, 3019, 0, +2558, 3151, 0, +2795, 3283, 0, +2993, 3416, 0, +3169, 3548, 0, +3331, 3680, 0, +3485, 3812, 0, +3632, 3944, 0, +3775, 4076, 0, +3915, 4095, 0, +0, 2210, 2491, +0, 2212, 2491, +0, 2215, 2490, +0, 2219, 2490, +0, 2224, 2489, +0, 2230, 2489, +0, 2238, 2489, +0, 2247, 2489, +0, 2260, 2489, +0, 2277, 2489, +0, 2298, 2489, +0, 2326, 2489, +0, 2360, 2489, +0, 2401, 2489, +0, 2452, 2489, +0, 2489, 2466, +0, 2489, 2375, +0, 2489, 2215, +0, 2489, 1834, +0, 2622, 0, +0, 2755, 0, +1540, 2887, 0, +2234, 3019, 0, +2560, 3151, 0, +2797, 3283, 0, +2994, 3416, 0, +3170, 3548, 0, +3332, 3680, 0, +3485, 3812, 0, +3632, 3944, 0, +3775, 4076, 0, +3915, 4095, 0, +0, 2204, 2491, +0, 2206, 2491, +0, 2209, 2490, +0, 2213, 2490, +0, 2219, 2489, +0, 2226, 2489, +0, 2233, 2489, +0, 2243, 2489, +0, 2256, 2489, +0, 2273, 2489, +0, 2294, 2489, +0, 2322, 2489, +0, 2356, 2489, +0, 2398, 2489, +0, 2449, 2489, +0, 2489, 2468, +0, 2489, 2377, +0, 2489, 2218, +0, 2489, 1840, +0, 2621, 0, +0, 2754, 0, +1569, 2887, 0, +2241, 3019, 0, +2564, 3151, 0, +2799, 3283, 0, +2996, 3416, 0, +3171, 3548, 0, +3332, 3680, 0, +3485, 3812, 0, +3632, 3944, 0, +3775, 4076, 0, +3916, 4095, 0, +0, 2196, 2491, +0, 2199, 2491, +0, 2202, 2490, +0, 2206, 2490, +0, 2211, 2489, +0, 2218, 2489, +0, 2227, 2488, +0, 2237, 2488, +0, 2250, 2488, +0, 2267, 2488, +0, 2289, 2488, +0, 2317, 2488, +0, 2352, 2488, +0, 2394, 2488, +0, 2445, 2488, +0, 2488, 2470, +0, 2488, 2379, +0, 2488, 2221, +0, 2488, 1848, +0, 2621, 0, +0, 2754, 0, +1606, 2886, 0, +2249, 3018, 0, +2568, 3151, 0, +2801, 3283, 0, +2997, 3415, 0, +3172, 3548, 0, +3333, 3680, 0, +3486, 3812, 0, +3633, 3944, 0, +3776, 4076, 0, +3916, 4095, 0, +0, 2185, 2491, +0, 2187, 2491, +0, 2190, 2490, +0, 2195, 2490, +0, 2200, 2489, +0, 2207, 2489, +0, 2217, 2488, +0, 2229, 2487, +0, 2242, 2487, +0, 2260, 2487, +0, 2282, 2487, +0, 2310, 2487, +0, 2345, 2487, +0, 2388, 2487, +0, 2440, 2487, +0, 2487, 2473, +0, 2487, 2383, +0, 2487, 2226, +0, 2487, 1859, +0, 2620, 0, +0, 2753, 0, +1651, 2886, 0, +2261, 3018, 0, +2573, 3151, 0, +2805, 3283, 0, +2999, 3415, 0, +3173, 3548, 0, +3334, 3680, 0, +3487, 3812, 0, +3633, 3944, 0, +3776, 4076, 0, +3916, 4095, 0, +0, 2170, 2491, +0, 2172, 2491, +0, 2175, 2490, +0, 2180, 2490, +0, 2185, 2489, +0, 2193, 2489, +0, 2202, 2488, +0, 2215, 2487, +0, 2231, 2486, +0, 2249, 2486, +0, 2272, 2486, +0, 2301, 2486, +0, 2336, 2486, +0, 2380, 2486, +0, 2433, 2486, +0, 2486, 2476, +0, 2486, 2387, +0, 2486, 2232, +0, 2486, 1873, +0, 2619, 0, +0, 2752, 0, +1706, 2885, 0, +2276, 3018, 0, +2581, 3151, 0, +2809, 3283, 0, +3002, 3415, 0, +3175, 3548, 0, +3336, 3680, 0, +3488, 3812, 0, +3634, 3944, 0, +3777, 4076, 0, +3917, 4095, 0, +0, 2149, 2491, +0, 2151, 2491, +0, 2154, 2490, +0, 2159, 2490, +0, 2165, 2489, +0, 2172, 2489, +0, 2183, 2488, +0, 2196, 2487, +0, 2213, 2486, +0, 2235, 2484, +0, 2258, 2484, +0, 2288, 2484, +0, 2325, 2484, +0, 2369, 2484, +0, 2423, 2484, +0, 2484, 2481, +0, 2484, 2393, +0, 2484, 2240, +0, 2484, 1891, +0, 2618, 0, +0, 2751, 0, +1769, 2885, 0, +2294, 3017, 0, +2591, 3150, 0, +2815, 3282, 0, +3006, 3415, 0, +3178, 3547, 0, +3337, 3680, 0, +3489, 3812, 0, +3635, 3944, 0, +3777, 4076, 0, +3917, 4095, 0, +0, 2119, 2491, +0, 2121, 2491, +0, 2125, 2490, +0, 2129, 2490, +0, 2136, 2489, +0, 2144, 2489, +0, 2155, 2488, +0, 2169, 2487, +0, 2187, 2486, +0, 2210, 2484, +0, 2239, 2481, +0, 2270, 2481, +0, 2308, 2481, +0, 2355, 2481, +0, 2410, 2481, +0, 2475, 2481, +0, 2481, 2401, +0, 2481, 2251, +0, 2481, 1913, +0, 2616, 0, +0, 2750, 0, +1843, 2883, 0, +2319, 3016, 0, +2604, 3150, 0, +2823, 3282, 0, +3011, 3414, 0, +3182, 3547, 0, +3340, 3679, 0, +3491, 3812, 0, +3636, 3944, 0, +3778, 4076, 0, +3918, 4095, 0, +0, 2075, 2491, +0, 2078, 2491, +0, 2082, 2490, +0, 2087, 2490, +0, 2094, 2489, +0, 2103, 2489, +0, 2115, 2488, +0, 2130, 2487, +0, 2149, 2486, +0, 2174, 2484, +0, 2206, 2481, +0, 2245, 2478, +0, 2285, 2478, +0, 2334, 2478, +0, 2392, 2478, +0, 2460, 2478, +0, 2478, 2411, +0, 2478, 2264, +0, 2478, 1941, +0, 2613, 0, +0, 2748, 0, +1925, 2882, 0, +2350, 3015, 0, +2620, 3149, 0, +2833, 3281, 0, +3018, 3414, 0, +3186, 3547, 0, +3343, 3679, 0, +3493, 3812, 0, +3638, 3944, 0, +3780, 4076, 0, +3919, 4095, 0, +0, 2009, 2491, +0, 2013, 2491, +0, 2017, 2490, +0, 2023, 2490, +0, 2031, 2489, +0, 2041, 2489, +0, 2055, 2488, +0, 2072, 2487, +0, 2094, 2486, +0, 2122, 2484, +0, 2158, 2481, +0, 2201, 2478, +0, 2253, 2473, +0, 2305, 2473, +0, 2366, 2473, +0, 2438, 2473, +0, 2473, 2423, +0, 2473, 2282, +0, 2473, 1977, +0, 2610, 0, +678, 2746, 0, +2016, 2880, 0, +2388, 3014, 0, +2642, 3148, 0, +2847, 3280, 0, +3027, 3414, 0, +3192, 3546, 0, +3348, 3679, 0, +3496, 3811, 0, +3640, 3944, 0, +3781, 4076, 0, +3920, 4095, 0, +0, 1903, 2491, +0, 1907, 2491, +0, 1913, 2490, +0, 1920, 2490, +0, 1930, 2489, +0, 1943, 2489, +0, 1960, 2488, +0, 1981, 2487, +0, 2008, 2486, +0, 2042, 2484, +0, 2084, 2481, +0, 2134, 2478, +0, 2194, 2473, +477, 2263, 2467, +477, 2330, 2467, +477, 2407, 2467, +477, 2467, 2440, +477, 2467, 2305, +477, 2467, 2021, +0, 2605, 705, +1463, 2742, 0, +2115, 2878, 0, +2434, 3012, 0, +2669, 3146, 0, +2865, 3280, 0, +3039, 3413, 0, +3201, 3546, 0, +3354, 3678, 0, +3501, 3811, 0, +3644, 3943, 0, +3784, 4076, 0, +3922, 4095, 0, +0, 1706, 2491, +0, 1713, 2491, +0, 1722, 2490, +0, 1733, 2490, +0, 1748, 2489, +0, 1767, 2489, +0, 1791, 2488, +0, 1822, 2487, +0, 1859, 2486, +0, 1906, 2484, +0, 1961, 2481, +0, 2026, 2478, +0, 2100, 2473, +477, 2184, 2467, +1401, 2276, 2459, +1401, 2362, 2459, +1401, 2455, 2459, +1401, 2459, 2334, +1401, 2459, 2073, +611, 2599, 1236, +1799, 2738, 0, +2220, 2874, 0, +2489, 3010, 0, +2703, 3144, 0, +2886, 3278, 0, +3055, 3412, 0, +3211, 3545, 0, +3361, 3678, 0, +3506, 3810, 0, +3648, 3943, 0, +3787, 4075, 0, +3924, 4095, 0, +0, 1120, 2491, +0, 1143, 2491, +0, 1173, 2490, +0, 1210, 2490, +0, 1255, 2489, +0, 1310, 2489, +0, 1373, 2488, +0, 1446, 2487, +0, 1529, 2486, +0, 1620, 2484, +0, 1719, 2481, +0, 1824, 2478, +0, 1935, 2473, +477, 2051, 2467, +1401, 2171, 2459, +1751, 2293, 2447, +1751, 2401, 2447, +1751, 2447, 2370, +1751, 2447, 2135, +1533, 2591, 1533, +2040, 2731, 738, +2332, 2870, 0, +2554, 3006, 0, +2744, 3142, 0, +2915, 3276, 0, +3074, 3410, 0, +3225, 3544, 0, +3371, 3677, 0, +3514, 3810, 0, +3653, 3943, 0, +3790, 4075, 0, +3927, 4095, 0, +0, 0, 2491, +0, 0, 2491, +0, 0, 2490, +0, 0, 2490, +0, 0, 2489, +0, 0, 2489, +0, 0, 2488, +0, 0, 2487, +0, 0, 2486, +0, 0, 2484, +0, 415, 2481, +0, 1199, 2478, +0, 1535, 2473, +477, 1776, 2467, +1401, 1976, 2459, +1751, 2152, 2447, +1997, 2315, 2431, +1997, 2431, 2414, +1997, 2431, 2207, +1981, 2579, 1883, +2240, 2723, 1664, +2447, 2863, 870, +2628, 3002, 0, +2795, 3138, 0, +2950, 3274, 0, +3099, 3408, 0, +3243, 3543, 0, +3385, 3676, 0, +3523, 3809, 0, +3660, 3942, 0, +3796, 4075, 0, +3931, 4095, 0, +0, 0, 2491, +0, 0, 2491, +0, 0, 2490, +0, 0, 2490, +0, 0, 2489, +0, 0, 2489, +0, 0, 2488, +0, 0, 2487, +0, 0, 2486, +0, 0, 2484, +0, 0, 2481, +0, 0, 2478, +557, 0, 2473, +1099, 477, 2467, +1401, 1403, 2459, +1751, 1850, 2447, +1997, 2126, 2431, +2199, 2343, 2409, +2199, 2409, 2288, +2258, 2563, 2129, +2416, 2711, 2015, +2567, 2855, 1796, +2712, 2995, 1006, +2854, 3134, 0, +2993, 3270, 0, +3131, 3406, 0, +3267, 3541, 0, +3402, 3675, 0, +3536, 3808, 0, +3669, 3941, 0, +3803, 4074, 0, +3936, 4095, 0, +1822, 0, 2491, +1824, 0, 2491, +1826, 0, 2490, +1830, 0, 2490, +1834, 0, 2489, +1840, 0, 2489, +1848, 0, 2488, +1859, 0, 2487, +1873, 0, 2486, +1891, 0, 2484, +1913, 0, 2481, +1941, 0, 2478, +1977, 0, 2473, +2021, 477, 2467, +2073, 1401, 2459, +2135, 1751, 2447, +2207, 1997, 2431, +2288, 2199, 2409, +2377, 2377, 2377, +2475, 2541, 2331, +2579, 2696, 2261, +2689, 2843, 2147, +2804, 2987, 1930, +2923, 3128, 1137, +3045, 3266, 0, +3170, 3402, 0, +3296, 3538, 0, +3423, 3673, 0, +3552, 3807, 0, +3682, 3940, 0, +3812, 4073, 0, +3943, 4095, 0, +2340, 0, 2623, +2341, 0, 2623, +2342, 0, 2623, +2343, 0, 2622, +2344, 0, 2622, +2346, 0, 2621, +2349, 0, 2621, +2352, 0, 2620, +2357, 0, 2619, +2363, 0, 2618, +2372, 0, 2616, +2382, 0, 2613, +2396, 0, 2610, +2414, 0, 2605, +2437, 611, 2599, +2466, 1533, 2591, +2502, 1883, 2579, +2545, 2129, 2563, +2541, 2331, 2475, +2541, 2420, 2331, +2696, 2678, 2261, +2797, 2843, 2147, +2890, 2987, 1930, +2991, 3128, 1137, +3097, 3266, 0, +3210, 3402, 0, +3326, 3538, 0, +3447, 3673, 0, +3570, 3807, 0, +3695, 3940, 0, +3822, 4073, 0, +3950, 4095, 0, +2635, 0, 2755, +2635, 0, 2755, +2636, 0, 2755, +2636, 0, 2755, +2637, 0, 2755, +2638, 0, 2754, +2640, 0, 2754, +2641, 0, 2753, +2644, 0, 2752, +2647, 0, 2751, +2651, 0, 2750, +2657, 0, 2748, +2665, 0, 2746, +2675, 0, 2742, +2688, 0, 2738, +2705, 738, 2731, +2723, 1664, 2719, +2711, 2015, 2665, +2696, 2261, 2579, +2696, 2261, 2391, +2696, 2471, 2261, +2843, 2766, 2147, +2984, 2987, 1930, +3067, 3128, 1137, +3159, 3266, 0, +3259, 3402, 0, +3365, 3538, 0, +3477, 3673, 0, +3593, 3807, 0, +3713, 3940, 0, +3835, 4073, 0, +3961, 4095, 0, +2859, 0, 2887, +2859, 0, 2887, +2859, 0, 2887, +2860, 0, 2887, +2860, 0, 2887, +2861, 0, 2887, +2862, 0, 2886, +2863, 0, 2886, +2864, 0, 2885, +2866, 0, 2885, +2869, 0, 2883, +2873, 0, 2882, +2877, 0, 2880, +2878, 0, 2872, +2874, 0, 2856, +2870, 0, 2834, +2863, 870, 2803, +2855, 1796, 2758, +2843, 2147, 2689, +2843, 2147, 2549, +2843, 2147, 2246, +2843, 2532, 2147, +2987, 2862, 1930, +3128, 3101, 1137, +3230, 3266, 0, +3317, 3402, 0, +3411, 3538, 0, +3513, 3673, 0, +3622, 3807, 0, +3735, 3940, 0, +3852, 4073, 0, +3974, 4095, 0, +3019, 0, 2988, +3019, 0, 2987, +3019, 0, 2987, +3019, 0, 2987, +3019, 0, 2986, +3019, 0, 2985, +3018, 0, 2984, +3018, 0, 2982, +3018, 0, 2980, +3017, 0, 2977, +3016, 0, 2974, +3015, 0, 2968, +3014, 0, 2961, +3012, 0, 2952, +3010, 0, 2939, +3006, 0, 2920, +3002, 0, 2895, +2995, 1006, 2858, +2987, 1930, 2804, +2987, 1930, 2699, +2987, 1930, 2503, +2987, 1930, 1930, +2987, 2602, 1930, +3128, 2965, 1137, +3266, 3216, 0, +3384, 3402, 0, +3467, 3538, 0, +3558, 3673, 0, +3657, 3807, 0, +3763, 3940, 0, +3874, 4073, 0, +3990, 4095, 0, +3152, 0, 3071, +3152, 0, 3070, +3152, 0, 3070, +3151, 0, 3070, +3151, 0, 3069, +3151, 0, 3068, +3151, 0, 3067, +3151, 0, 3066, +3151, 0, 3064, +3150, 0, 3062, +3150, 0, 3059, +3149, 0, 3055, +3148, 0, 3049, +3146, 0, 3041, +3144, 0, 3030, +3142, 0, 3015, +3138, 0, 2995, +3134, 0, 2965, +3128, 1137, 2923, +3128, 1137, 2845, +3128, 1137, 2712, +3128, 1137, 2436, +3128, 1758, 1137, +3128, 2681, 1137, +3266, 3074, 0, +3402, 3335, 0, +3532, 3538, 0, +3612, 3673, 0, +3701, 3807, 0, +3798, 3940, 0, +3902, 4073, 0, +4012, 4095, 0, +3284, 0, 3162, +3283, 0, 3162, +3283, 0, 3161, +3283, 0, 3161, +3283, 0, 3160, +3283, 0, 3160, +3283, 0, 3159, +3283, 0, 3158, +3283, 0, 3157, +3282, 0, 3155, +3282, 0, 3152, +3281, 0, 3149, +3280, 0, 3144, +3280, 0, 3138, +3278, 0, 3129, +3276, 0, 3117, +3274, 0, 3100, +3270, 0, 3078, +3266, 0, 3045, +3266, 0, 2986, +3266, 0, 2893, +3266, 0, 2727, +3266, 0, 2327, +3266, 1375, 0, +3266, 2770, 0, +3402, 3189, 0, +3538, 3457, 0, +3673, 3670, 0, +3754, 3807, 0, +3841, 3940, 0, +3937, 4073, 0, +4039, 4095, 0, +3416, 0, 3261, +3416, 0, 3261, +3416, 0, 3260, +3416, 0, 3260, +3416, 0, 3260, +3416, 0, 3259, +3415, 0, 3259, +3415, 0, 3258, +3415, 0, 3257, +3415, 0, 3255, +3414, 0, 3253, +3414, 0, 3250, +3414, 0, 3247, +3413, 0, 3242, +3412, 0, 3234, +3410, 0, 3225, +3408, 0, 3212, +3406, 0, 3194, +3402, 0, 3170, +3402, 0, 3125, +3402, 0, 3059, +3402, 0, 2951, +3402, 0, 2749, +3402, 0, 2121, +3402, 0, 0, +3402, 2866, 0, +3538, 3307, 0, +3673, 3582, 0, +3807, 3797, 0, +3893, 3940, 0, +3979, 4073, 0, +4073, 4095, 0, +3548, 0, 3367, +3548, 0, 3367, +3548, 0, 3366, +3548, 0, 3366, +3548, 0, 3366, +3548, 0, 3365, +3548, 0, 3365, +3548, 0, 3364, +3548, 0, 3363, +3547, 0, 3362, +3547, 0, 3361, +3547, 0, 3358, +3546, 0, 3355, +3546, 0, 3351, +3545, 0, 3346, +3544, 0, 3339, +3543, 0, 3329, +3541, 0, 3315, +3538, 0, 3296, +3538, 0, 3263, +3538, 0, 3214, +3538, 0, 3140, +3538, 0, 3018, +3538, 0, 2775, +3538, 0, 1477, +3538, 0, 0, +3538, 2970, 0, +3673, 3429, 0, +3807, 3708, 0, +3940, 3926, 0, +4030, 4073, 0, +4095, 4095, 0, +3680, 0, 3478, +3680, 0, 3478, +3680, 0, 3478, +3680, 0, 3478, +3680, 0, 3478, +3680, 0, 3477, +3680, 0, 3477, +3680, 0, 3476, +3680, 0, 3475, +3680, 0, 3475, +3679, 0, 3473, +3679, 0, 3472, +3679, 0, 3469, +3678, 0, 3466, +3678, 0, 3462, +3677, 0, 3456, +3676, 0, 3448, +3675, 0, 3438, +3673, 0, 3423, +3673, 0, 3399, +3673, 0, 3363, +3673, 0, 3311, +3673, 0, 3231, +3673, 0, 3095, +3673, 0, 2809, +3673, 0, 0, +3673, 0, 0, +3673, 3079, 0, +3807, 3552, 0, +3940, 3836, 0, +4073, 4055, 0, +4095, 4095, 0, +3812, 0, 3594, +3812, 0, 3594, +3812, 0, 3594, +3812, 0, 3594, +3812, 0, 3594, +3812, 0, 3593, +3812, 0, 3593, +3812, 0, 3593, +3812, 0, 3592, +3812, 0, 3591, +3812, 0, 3590, +3812, 0, 3589, +3811, 0, 3587, +3811, 0, 3585, +3810, 0, 3582, +3810, 0, 3577, +3809, 0, 3571, +3808, 0, 3563, +3807, 0, 3552, +3807, 0, 3534, +3807, 0, 3508, +3807, 0, 3470, +3807, 0, 3415, +3807, 0, 3329, +3807, 0, 3181, +3807, 0, 2850, +3807, 0, 0, +3807, 0, 0, +3807, 3194, 0, +3940, 3678, 0, +4073, 3964, 0, +4095, 4095, 0, +3944, 0, 3713, +3944, 0, 3713, +3944, 0, 3713, +3944, 0, 3713, +3944, 0, 3713, +3944, 0, 3713, +3944, 0, 3713, +3944, 0, 3712, +3944, 0, 3712, +3944, 0, 3711, +3944, 0, 3711, +3944, 0, 3710, +3944, 0, 3708, +3943, 0, 3706, +3943, 0, 3704, +3943, 0, 3701, +3942, 0, 3696, +3941, 0, 3690, +3940, 0, 3682, +3940, 0, 3668, +3940, 0, 3649, +3940, 0, 3622, +3940, 0, 3583, +3940, 0, 3525, +3940, 0, 3434, +3940, 0, 3275, +3940, 0, 2899, +3940, 0, 0, +3940, 0, 0, +3940, 3312, 0, +4073, 3805, 0, +4095, 4094, 0, +4076, 0, 3836, +4076, 0, 3836, +4076, 0, 3836, +4076, 0, 3836, +4076, 0, 3836, +4076, 0, 3835, +4076, 0, 3835, +4076, 0, 3835, +4076, 0, 3835, +4076, 0, 3834, +4076, 0, 3834, +4076, 0, 3833, +4076, 0, 3832, +4076, 0, 3830, +4075, 0, 3829, +4075, 0, 3826, +4075, 0, 3823, +4074, 0, 3818, +4073, 0, 3812, +4073, 0, 3801, +4073, 0, 3787, +4073, 0, 3768, +4073, 0, 3740, +4073, 0, 3700, +4073, 0, 3640, +4073, 0, 3545, +4073, 0, 3376, +4073, 0, 2957, +4073, 0, 0, +4073, 0, 0, +4073, 3434, 0, +4095, 3935, 0, +4095, 0, 3961, +4095, 0, 3961, +4095, 0, 3961, +4095, 0, 3961, +4095, 0, 3961, +4095, 0, 3961, +4095, 0, 3961, +4095, 0, 3960, +4095, 0, 3960, +4095, 0, 3960, +4095, 0, 3959, +4095, 0, 3959, +4095, 0, 3958, +4095, 0, 3957, +4095, 0, 3955, +4095, 0, 3953, +4095, 0, 3951, +4095, 0, 3947, +4095, 0, 3943, +4095, 0, 3935, +4095, 0, 3924, +4095, 0, 3910, +4095, 0, 3890, +4095, 0, 3861, +4095, 0, 3820, +4095, 0, 3759, +4095, 0, 3661, +4095, 0, 3484, +4095, 0, 3027, +4095, 0, 0, +4095, 0, 0, +4095, 3558, 0, +0, 2354, 2623, +0, 2355, 2623, +0, 2357, 2623, +0, 2359, 2623, +0, 2363, 2623, +0, 2367, 2623, +0, 2372, 2623, +0, 2380, 2623, +0, 2390, 2623, +0, 2402, 2623, +0, 2419, 2623, +0, 2440, 2623, +0, 2466, 2623, +0, 2500, 2623, +0, 2541, 2623, +0, 2590, 2623, +0, 2623, 2595, +0, 2623, 2503, +0, 2623, 2340, +0, 2623, 1952, +0, 2755, 0, +0, 2887, 0, +1594, 3019, 0, +2352, 3152, 0, +2684, 3284, 0, +2925, 3416, 0, +3124, 3548, 0, +3300, 3680, 0, +3462, 3812, 0, +3616, 3944, 0, +3763, 4076, 0, +3907, 4095, 0, +0, 2352, 2623, +0, 2354, 2623, +0, 2356, 2623, +0, 2358, 2623, +0, 2362, 2623, +0, 2366, 2623, +0, 2372, 2623, +0, 2379, 2623, +0, 2388, 2623, +0, 2401, 2623, +0, 2417, 2623, +0, 2439, 2623, +0, 2465, 2623, +0, 2499, 2623, +0, 2540, 2623, +0, 2590, 2623, +0, 2623, 2595, +0, 2623, 2503, +0, 2623, 2341, +0, 2623, 1954, +0, 2755, 0, +0, 2887, 0, +1602, 3019, 0, +2353, 3152, 0, +2685, 3283, 0, +2925, 3416, 0, +3124, 3548, 0, +3300, 3680, 0, +3462, 3812, 0, +3616, 3944, 0, +3763, 4076, 0, +3907, 4095, 0, +0, 2351, 2623, +0, 2352, 2623, +0, 2355, 2623, +0, 2357, 2623, +0, 2360, 2623, +0, 2364, 2623, +0, 2370, 2623, +0, 2378, 2623, +0, 2387, 2623, +0, 2400, 2623, +0, 2416, 2623, +0, 2437, 2623, +0, 2464, 2623, +0, 2498, 2623, +0, 2539, 2623, +0, 2589, 2623, +0, 2623, 2596, +0, 2623, 2504, +0, 2623, 2342, +0, 2623, 1956, +0, 2755, 0, +0, 2887, 0, +1613, 3019, 0, +2355, 3152, 0, +2686, 3283, 0, +2926, 3416, 0, +3124, 3548, 0, +3300, 3680, 0, +3463, 3812, 0, +3616, 3944, 0, +3763, 4076, 0, +3907, 4095, 0, +0, 2348, 2623, +0, 2350, 2623, +0, 2352, 2623, +0, 2355, 2622, +0, 2358, 2622, +0, 2362, 2622, +0, 2368, 2622, +0, 2375, 2622, +0, 2385, 2622, +0, 2398, 2622, +0, 2414, 2622, +0, 2436, 2622, +0, 2463, 2622, +0, 2496, 2622, +0, 2538, 2622, +0, 2588, 2622, +0, 2622, 2596, +0, 2622, 2505, +0, 2622, 2343, +0, 2622, 1958, +0, 2755, 0, +0, 2887, 0, +1628, 3019, 0, +2358, 3151, 0, +2688, 3283, 0, +2927, 3416, 0, +3125, 3548, 0, +3301, 3680, 0, +3463, 3812, 0, +3616, 3944, 0, +3764, 4076, 0, +3907, 4095, 0, +0, 2345, 2623, +0, 2347, 2623, +0, 2349, 2623, +0, 2352, 2622, +0, 2356, 2622, +0, 2360, 2622, +0, 2366, 2622, +0, 2373, 2622, +0, 2383, 2622, +0, 2396, 2622, +0, 2412, 2622, +0, 2434, 2622, +0, 2460, 2622, +0, 2494, 2622, +0, 2536, 2622, +0, 2586, 2622, +0, 2622, 2597, +0, 2622, 2506, +0, 2622, 2344, +0, 2622, 1962, +0, 2755, 0, +0, 2887, 0, +1646, 3019, 0, +2362, 3151, 0, +2690, 3283, 0, +2928, 3416, 0, +3125, 3548, 0, +3301, 3680, 0, +3463, 3812, 0, +3617, 3944, 0, +3764, 4076, 0, +3907, 4095, 0, +0, 2341, 2623, +0, 2342, 2623, +0, 2345, 2623, +0, 2347, 2622, +0, 2351, 2622, +0, 2356, 2621, +0, 2362, 2621, +0, 2370, 2621, +0, 2380, 2621, +0, 2393, 2621, +0, 2409, 2621, +0, 2431, 2621, +0, 2458, 2621, +0, 2492, 2621, +0, 2533, 2621, +0, 2584, 2621, +0, 2621, 2598, +0, 2621, 2507, +0, 2621, 2346, +0, 2621, 1966, +0, 2754, 0, +0, 2887, 0, +1670, 3019, 0, +2367, 3151, 0, +2692, 3283, 0, +2929, 3416, 0, +3126, 3548, 0, +3302, 3680, 0, +3464, 3812, 0, +3617, 3944, 0, +3764, 4076, 0, +3908, 4095, 0, +0, 2335, 2623, +0, 2336, 2623, +0, 2338, 2623, +0, 2341, 2622, +0, 2346, 2622, +0, 2351, 2621, +0, 2357, 2621, +0, 2365, 2621, +0, 2375, 2621, +0, 2388, 2621, +0, 2405, 2621, +0, 2427, 2621, +0, 2454, 2621, +0, 2488, 2621, +0, 2530, 2621, +0, 2581, 2621, +0, 2621, 2600, +0, 2621, 2509, +0, 2621, 2349, +0, 2621, 1972, +0, 2754, 0, +0, 2886, 0, +1700, 3018, 0, +2373, 3151, 0, +2695, 3283, 0, +2931, 3415, 0, +3128, 3548, 0, +3303, 3680, 0, +3464, 3812, 0, +3617, 3944, 0, +3764, 4076, 0, +3908, 4095, 0, +0, 2327, 2623, +0, 2328, 2623, +0, 2331, 2623, +0, 2334, 2622, +0, 2337, 2622, +0, 2343, 2621, +0, 2350, 2621, +0, 2359, 2620, +0, 2369, 2620, +0, 2382, 2620, +0, 2399, 2620, +0, 2421, 2620, +0, 2449, 2620, +0, 2483, 2620, +0, 2526, 2620, +0, 2577, 2620, +0, 2620, 2602, +0, 2620, 2511, +0, 2620, 2352, +0, 2620, 1981, +0, 2753, 0, +0, 2886, 0, +1737, 3018, 0, +2382, 3151, 0, +2700, 3283, 0, +2934, 3415, 0, +3129, 3548, 0, +3304, 3680, 0, +3465, 3812, 0, +3618, 3944, 0, +3765, 4076, 0, +3908, 4095, 0, +0, 2315, 2623, +0, 2317, 2623, +0, 2320, 2623, +0, 2323, 2622, +0, 2327, 2622, +0, 2332, 2621, +0, 2339, 2621, +0, 2348, 2620, +0, 2361, 2619, +0, 2374, 2619, +0, 2392, 2619, +0, 2414, 2619, +0, 2442, 2619, +0, 2477, 2619, +0, 2520, 2619, +0, 2572, 2619, +0, 2619, 2604, +0, 2619, 2515, +0, 2619, 2357, +0, 2619, 1991, +0, 2752, 0, +0, 2885, 0, +1782, 3018, 0, +2394, 3151, 0, +2705, 3283, 0, +2937, 3415, 0, +3132, 3548, 0, +3305, 3680, 0, +3466, 3812, 0, +3619, 3944, 0, +3765, 4076, 0, +3908, 4095, 0, +0, 2300, 2623, +0, 2302, 2623, +0, 2304, 2623, +0, 2308, 2622, +0, 2312, 2622, +0, 2317, 2621, +0, 2325, 2621, +0, 2334, 2620, +0, 2347, 2619, +0, 2363, 2618, +0, 2381, 2618, +0, 2404, 2618, +0, 2432, 2618, +0, 2469, 2618, +0, 2512, 2618, +0, 2565, 2618, +0, 2618, 2608, +0, 2618, 2519, +0, 2618, 2363, +0, 2618, 2005, +0, 2751, 0, +0, 2885, 0, +1837, 3017, 0, +2408, 3150, 0, +2713, 3282, 0, +2942, 3415, 0, +3135, 3547, 0, +3307, 3680, 0, +3468, 3812, 0, +3620, 3944, 0, +3766, 4076, 0, +3909, 4095, 0, +0, 2278, 2623, +0, 2281, 2623, +0, 2283, 2623, +0, 2287, 2622, +0, 2291, 2622, +0, 2297, 2621, +0, 2304, 2621, +0, 2314, 2620, +0, 2328, 2619, +0, 2345, 2618, +0, 2367, 2616, +0, 2390, 2616, +0, 2420, 2616, +0, 2456, 2616, +0, 2501, 2616, +0, 2555, 2616, +0, 2616, 2613, +0, 2616, 2525, +0, 2616, 2372, +0, 2616, 2022, +0, 2750, 0, +0, 2883, 0, +1900, 3016, 0, +2427, 3150, 0, +2723, 3282, 0, +2947, 3414, 0, +3138, 3547, 0, +3310, 3679, 0, +3469, 3812, 0, +3621, 3944, 0, +3767, 4076, 0, +3910, 4095, 0, +0, 2248, 2623, +0, 2250, 2623, +0, 2253, 2623, +0, 2256, 2622, +0, 2261, 2622, +0, 2268, 2621, +0, 2276, 2621, +0, 2287, 2620, +0, 2301, 2619, +0, 2319, 2618, +0, 2342, 2616, +0, 2371, 2613, +0, 2402, 2613, +0, 2440, 2613, +0, 2487, 2613, +0, 2542, 2613, +0, 2607, 2613, +0, 2613, 2533, +0, 2613, 2382, +0, 2613, 2045, +0, 2748, 0, +0, 2882, 0, +1974, 3015, 0, +2452, 3149, 0, +2735, 3281, 0, +2956, 3414, 0, +3144, 3547, 0, +3314, 3679, 0, +3472, 3812, 0, +3623, 3944, 0, +3768, 4076, 0, +3910, 4095, 0, +0, 2205, 2623, +0, 2207, 2623, +0, 2210, 2623, +0, 2214, 2622, +0, 2219, 2622, +0, 2226, 2621, +0, 2235, 2621, +0, 2247, 2620, +0, 2262, 2619, +0, 2281, 2618, +0, 2306, 2616, +0, 2338, 2613, +0, 2377, 2610, +0, 2417, 2610, +0, 2466, 2610, +0, 2524, 2610, +0, 2592, 2610, +0, 2610, 2543, +0, 2610, 2396, +0, 2610, 2073, +0, 2746, 0, +0, 2880, 0, +2056, 3014, 0, +2482, 3148, 0, +2752, 3280, 0, +2966, 3414, 0, +3151, 3546, 0, +3318, 3679, 0, +3475, 3811, 0, +3625, 3944, 0, +3770, 4076, 0, +3912, 4095, 0, +0, 2138, 2623, +0, 2141, 2623, +0, 2144, 2623, +0, 2149, 2622, +0, 2155, 2622, +0, 2163, 2621, +0, 2173, 2621, +0, 2187, 2620, +0, 2204, 2619, +0, 2226, 2618, +0, 2255, 2616, +0, 2290, 2613, +0, 2333, 2610, +0, 2385, 2605, +0, 2437, 2605, +0, 2498, 2605, +0, 2570, 2605, +0, 2605, 2556, +0, 2605, 2414, +0, 2605, 2109, +0, 2742, 0, +817, 2878, 0, +2148, 3012, 0, +2521, 3146, 0, +2773, 3280, 0, +2979, 3413, 0, +3160, 3546, 0, +3325, 3678, 0, +3480, 3811, 0, +3628, 3943, 0, +3773, 4076, 0, +3913, 4095, 0, +0, 2032, 2623, +0, 2035, 2623, +0, 2039, 2623, +0, 2045, 2622, +0, 2052, 2622, +0, 2062, 2621, +0, 2075, 2621, +0, 2092, 2620, +0, 2113, 2619, +0, 2140, 2618, +0, 2174, 2616, +0, 2216, 2613, +0, 2266, 2610, +0, 2326, 2605, +611, 2395, 2599, +611, 2462, 2599, +611, 2538, 2599, +611, 2599, 2572, +611, 2599, 2437, +611, 2599, 2153, +0, 2738, 817, +1596, 2874, 0, +2247, 3010, 0, +2566, 3144, 0, +2800, 3278, 0, +2997, 3412, 0, +3171, 3545, 0, +3333, 3678, 0, +3486, 3810, 0, +3632, 3943, 0, +3776, 4075, 0, +3916, 4095, 0, +0, 1833, 2623, +0, 1838, 2623, +0, 1845, 2623, +0, 1853, 2622, +0, 1865, 2622, +0, 1880, 2621, +0, 1899, 2621, +0, 1923, 2620, +0, 1954, 2619, +0, 1991, 2618, +0, 2038, 2616, +0, 2093, 2613, +0, 2158, 2610, +0, 2233, 2605, +611, 2316, 2599, +1533, 2408, 2591, +1533, 2493, 2591, +1533, 2587, 2591, +1533, 2591, 2466, +1533, 2591, 2206, +738, 2731, 1362, +1932, 2870, 0, +2352, 3006, 0, +2622, 3142, 0, +2834, 3276, 0, +3019, 3410, 0, +3186, 3544, 0, +3344, 3677, 0, +3493, 3810, 0, +3638, 3943, 0, +3780, 4075, 0, +3919, 4095, 0, +0, 1232, 2623, +0, 1251, 2623, +0, 1275, 2623, +0, 1304, 2622, +0, 1342, 2622, +0, 1387, 2621, +0, 1441, 2621, +0, 1505, 2620, +0, 1578, 2619, +0, 1661, 2618, +0, 1752, 2616, +0, 1851, 2613, +0, 1956, 2610, +0, 2067, 2605, +611, 2183, 2599, +1533, 2303, 2591, +1883, 2425, 2579, +1883, 2533, 2579, +1883, 2579, 2502, +1883, 2579, 2267, +1667, 2723, 1664, +2173, 2863, 870, +2463, 3002, 0, +2687, 3138, 0, +2876, 3274, 0, +3047, 3408, 0, +3206, 3543, 0, +3358, 3676, 0, +3503, 3809, 0, +3646, 3942, 0, +3785, 4075, 0, +3923, 4095, 0, +0, 0, 2623, +0, 0, 2623, +0, 0, 2623, +0, 0, 2622, +0, 0, 2622, +0, 0, 2621, +0, 0, 2621, +0, 0, 2620, +0, 0, 2619, +0, 0, 2618, +0, 0, 2616, +0, 547, 2613, +0, 1330, 2610, +0, 1667, 2605, +611, 1908, 2599, +1533, 2108, 2591, +1883, 2284, 2579, +2129, 2447, 2563, +2129, 2563, 2545, +2129, 2563, 2339, +2114, 2711, 2015, +2372, 2855, 1796, +2579, 2995, 1006, +2761, 3134, 0, +2926, 3270, 0, +3082, 3406, 0, +3231, 3541, 0, +3376, 3675, 0, +3517, 3808, 0, +3655, 3941, 0, +3792, 4074, 0, +3928, 4095, 0, +0, 0, 2623, +0, 0, 2623, +0, 0, 2623, +0, 0, 2622, +0, 0, 2622, +0, 0, 2621, +0, 0, 2621, +0, 0, 2620, +0, 0, 2619, +0, 0, 2618, +0, 0, 2616, +0, 0, 2613, +0, 0, 2610, +705, 0, 2605, +1236, 611, 2599, +1533, 1533, 2591, +1883, 1981, 2579, +2129, 2258, 2563, +2331, 2475, 2541, +2331, 2541, 2420, +2391, 2696, 2261, +2549, 2843, 2147, +2699, 2987, 1930, +2845, 3128, 1137, +2986, 3266, 0, +3125, 3402, 0, +3263, 3538, 0, +3399, 3673, 0, +3534, 3807, 0, +3668, 3940, 0, +3801, 4073, 0, +3935, 4095, 0, +1952, 0, 2623, +1954, 0, 2623, +1956, 0, 2623, +1958, 0, 2622, +1962, 0, 2622, +1966, 0, 2621, +1972, 0, 2621, +1981, 0, 2620, +1991, 0, 2619, +2005, 0, 2618, +2022, 0, 2616, +2045, 0, 2613, +2073, 0, 2610, +2109, 0, 2605, +2153, 611, 2599, +2206, 1533, 2591, +2267, 1883, 2579, +2339, 2129, 2563, +2420, 2331, 2541, +2509, 2509, 2509, +2607, 2673, 2463, +2711, 2828, 2393, +2821, 2975, 2280, +2936, 3119, 2061, +3055, 3259, 1272, +3177, 3398, 0, +3302, 3535, 0, +3428, 3670, 0, +3556, 3805, 0, +3684, 3939, 0, +3814, 4072, 0, +3944, 4095, 0, +2473, 0, 2755, +2473, 0, 2755, +2474, 0, 2755, +2475, 0, 2755, +2476, 0, 2755, +2477, 0, 2754, +2479, 0, 2754, +2482, 0, 2753, +2485, 0, 2752, +2490, 0, 2751, +2496, 0, 2750, +2504, 0, 2748, +2515, 0, 2746, +2529, 0, 2742, +2547, 0, 2738, +2570, 738, 2731, +2598, 1664, 2723, +2634, 2015, 2711, +2678, 2261, 2696, +2673, 2463, 2607, +2673, 2552, 2463, +2828, 2810, 2393, +2929, 2975, 2280, +3022, 3119, 2061, +3122, 3259, 1272, +3230, 3398, 0, +3342, 3535, 0, +3459, 3670, 0, +3579, 3805, 0, +3702, 3939, 0, +3827, 4072, 0, +3954, 4095, 0, +2767, 0, 2887, +2767, 0, 2887, +2767, 0, 2887, +2768, 0, 2887, +2768, 0, 2887, +2769, 0, 2887, +2770, 0, 2886, +2772, 0, 2886, +2773, 0, 2885, +2776, 0, 2885, +2779, 0, 2883, +2784, 0, 2882, +2789, 0, 2880, +2797, 0, 2878, +2807, 0, 2874, +2820, 0, 2870, +2837, 870, 2863, +2855, 1796, 2852, +2843, 2147, 2797, +2828, 2393, 2711, +2828, 2393, 2522, +2828, 2603, 2393, +2975, 2898, 2280, +3116, 3119, 2061, +3199, 3259, 1272, +3291, 3398, 0, +3391, 3535, 0, +3497, 3670, 0, +3609, 3805, 0, +3725, 3939, 0, +3845, 4072, 0, +3968, 4095, 0, +2991, 0, 3019, +2991, 0, 3019, +2991, 0, 3019, +2991, 0, 3019, +2992, 0, 3019, +2992, 0, 3019, +2992, 0, 3018, +2993, 0, 3018, +2995, 0, 3018, +2996, 0, 3017, +2998, 0, 3016, +3001, 0, 3015, +3004, 0, 3014, +3009, 0, 3012, +3010, 0, 3004, +3006, 0, 2988, +3002, 0, 2966, +2995, 1006, 2935, +2987, 1930, 2890, +2975, 2280, 2821, +2975, 2280, 2680, +2975, 2280, 2377, +2975, 2664, 2280, +3119, 2995, 2061, +3259, 3233, 1272, +3362, 3398, 0, +3449, 3535, 0, +3543, 3670, 0, +3646, 3805, 0, +3754, 3939, 0, +3867, 4072, 0, +3984, 4095, 0, +3152, 0, 3120, +3152, 0, 3120, +3152, 0, 3120, +3151, 0, 3119, +3151, 0, 3119, +3151, 0, 3118, +3151, 0, 3117, +3151, 0, 3116, +3151, 0, 3115, +3150, 0, 3112, +3150, 0, 3110, +3149, 0, 3106, +3148, 0, 3100, +3146, 0, 3093, +3144, 0, 3084, +3142, 0, 3071, +3138, 0, 3053, +3134, 0, 3027, +3128, 1137, 2991, +3119, 2061, 2936, +3119, 2061, 2831, +3119, 2061, 2636, +3119, 2061, 2064, +3119, 2734, 2061, +3259, 3097, 1272, +3398, 3348, 0, +3516, 3535, 0, +3599, 3670, 0, +3690, 3805, 0, +3790, 3939, 0, +3895, 4072, 0, +4006, 4095, 0, +3284, 0, 3203, +3283, 0, 3203, +3283, 0, 3202, +3283, 0, 3202, +3283, 0, 3201, +3283, 0, 3201, +3283, 0, 3200, +3283, 0, 3199, +3283, 0, 3198, +3282, 0, 3196, +3282, 0, 3194, +3281, 0, 3191, +3280, 0, 3186, +3280, 0, 3180, +3278, 0, 3173, +3276, 0, 3162, +3274, 0, 3147, +3270, 0, 3126, +3266, 0, 3097, +3259, 1272, 3055, +3259, 1272, 2976, +3259, 1272, 2843, +3259, 1272, 2569, +3259, 1899, 1272, +3259, 2813, 1272, +3398, 3206, 0, +3535, 3467, 0, +3664, 3670, 0, +3744, 3805, 0, +3833, 3939, 0, +3930, 4072, 0, +4034, 4095, 0, +3416, 0, 3294, +3416, 0, 3294, +3416, 0, 3294, +3416, 0, 3293, +3416, 0, 3293, +3416, 0, 3293, +3415, 0, 3292, +3415, 0, 3291, +3415, 0, 3290, +3415, 0, 3289, +3414, 0, 3287, +3414, 0, 3284, +3414, 0, 3281, +3413, 0, 3276, +3412, 0, 3270, +3410, 0, 3261, +3408, 0, 3249, +3406, 0, 3233, +3402, 0, 3210, +3398, 0, 3177, +3398, 0, 3118, +3398, 0, 3025, +3398, 0, 2860, +3398, 0, 2458, +3398, 1484, 0, +3398, 2902, 0, +3535, 3321, 0, +3670, 3589, 0, +3805, 3802, 0, +3886, 3939, 0, +3973, 4072, 0, +4069, 4095, 0, +3548, 0, 3393, +3548, 0, 3393, +3548, 0, 3393, +3548, 0, 3393, +3548, 0, 3392, +3548, 0, 3392, +3548, 0, 3392, +3548, 0, 3391, +3548, 0, 3390, +3547, 0, 3389, +3547, 0, 3387, +3547, 0, 3385, +3546, 0, 3382, +3546, 0, 3379, +3545, 0, 3374, +3544, 0, 3367, +3543, 0, 3357, +3541, 0, 3344, +3538, 0, 3326, +3535, 0, 3302, +3535, 0, 3257, +3535, 0, 3190, +3535, 0, 3083, +3535, 0, 2881, +3535, 0, 2256, +3535, 0, 0, +3535, 2998, 0, +3670, 3439, 0, +3805, 3714, 0, +3939, 3929, 0, +4025, 4072, 0, +4095, 4095, 0, +3680, 0, 3499, +3680, 0, 3499, +3680, 0, 3499, +3680, 0, 3499, +3680, 0, 3498, +3680, 0, 3498, +3680, 0, 3497, +3680, 0, 3497, +3680, 0, 3496, +3680, 0, 3495, +3679, 0, 3494, +3679, 0, 3493, +3679, 0, 3490, +3678, 0, 3488, +3678, 0, 3483, +3677, 0, 3478, +3676, 0, 3471, +3675, 0, 3461, +3673, 0, 3447, +3670, 0, 3428, +3670, 0, 3395, +3670, 0, 3346, +3670, 0, 3273, +3670, 0, 3150, +3670, 0, 2908, +3670, 0, 1603, +3670, 0, 0, +3670, 3102, 0, +3805, 3561, 0, +3939, 3840, 0, +4072, 4058, 0, +4095, 4095, 0, +3812, 0, 3610, +3812, 0, 3610, +3812, 0, 3610, +3812, 0, 3610, +3812, 0, 3610, +3812, 0, 3609, +3812, 0, 3609, +3812, 0, 3609, +3812, 0, 3608, +3812, 0, 3607, +3812, 0, 3606, +3812, 0, 3605, +3811, 0, 3604, +3811, 0, 3601, +3810, 0, 3598, +3810, 0, 3594, +3809, 0, 3588, +3808, 0, 3581, +3807, 0, 3570, +3805, 0, 3556, +3805, 0, 3531, +3805, 0, 3495, +3805, 0, 3443, +3805, 0, 3363, +3805, 0, 3227, +3805, 0, 2941, +3805, 0, 0, +3805, 0, 0, +3805, 3211, 0, +3939, 3685, 0, +4072, 3968, 0, +4095, 4095, 0, +3944, 0, 3726, +3944, 0, 3726, +3944, 0, 3726, +3944, 0, 3726, +3944, 0, 3726, +3944, 0, 3725, +3944, 0, 3725, +3944, 0, 3725, +3944, 0, 3725, +3944, 0, 3724, +3944, 0, 3723, +3944, 0, 3722, +3944, 0, 3721, +3943, 0, 3719, +3943, 0, 3717, +3943, 0, 3713, +3942, 0, 3709, +3941, 0, 3703, +3940, 0, 3695, +3939, 0, 3684, +3939, 0, 3666, +3939, 0, 3640, +3939, 0, 3603, +3939, 0, 3547, +3939, 0, 3461, +3939, 0, 3313, +3939, 0, 2982, +3939, 0, 0, +3939, 0, 0, +3939, 3326, 0, +4072, 3810, 0, +4095, 4095, 0, +4076, 0, 3846, +4076, 0, 3845, +4076, 0, 3845, +4076, 0, 3845, +4076, 0, 3845, +4076, 0, 3845, +4076, 0, 3845, +4076, 0, 3845, +4076, 0, 3845, +4076, 0, 3844, +4076, 0, 3843, +4076, 0, 3843, +4076, 0, 3841, +4076, 0, 3840, +4075, 0, 3838, +4075, 0, 3836, +4075, 0, 3833, +4074, 0, 3828, +4073, 0, 3822, +4072, 0, 3814, +4072, 0, 3800, +4072, 0, 3781, +4072, 0, 3754, +4072, 0, 3715, +4072, 0, 3657, +4072, 0, 3566, +4072, 0, 3407, +4072, 0, 3031, +4072, 0, 0, +4072, 0, 0, +4072, 3444, 0, +4095, 3938, 0, +4095, 0, 3968, +4095, 0, 3968, +4095, 0, 3968, +4095, 0, 3968, +4095, 0, 3968, +4095, 0, 3968, +4095, 0, 3968, +4095, 0, 3968, +4095, 0, 3967, +4095, 0, 3967, +4095, 0, 3967, +4095, 0, 3966, +4095, 0, 3965, +4095, 0, 3964, +4095, 0, 3963, +4095, 0, 3961, +4095, 0, 3959, +4095, 0, 3955, +4095, 0, 3950, +4095, 0, 3944, +4095, 0, 3934, +4095, 0, 3920, +4095, 0, 3900, +4095, 0, 3872, +4095, 0, 3832, +4095, 0, 3772, +4095, 0, 3677, +4095, 0, 3509, +4095, 0, 3090, +4095, 0, 0, +4095, 0, 0, +4095, 3566, 0, +0, 2486, 2755, +0, 2487, 2755, +0, 2488, 2755, +0, 2490, 2755, +0, 2493, 2755, +0, 2496, 2755, +0, 2500, 2755, +0, 2505, 2755, +0, 2513, 2755, +0, 2523, 2755, +0, 2535, 2755, +0, 2552, 2755, +0, 2573, 2755, +0, 2599, 2755, +0, 2632, 2755, +0, 2673, 2755, +0, 2723, 2755, +0, 2755, 2727, +0, 2755, 2635, +0, 2755, 2473, +0, 2755, 2083, +0, 2887, 0, +0, 3019, 0, +1720, 3152, 0, +2481, 3284, 0, +2816, 3416, 0, +3056, 3548, 0, +3255, 3680, 0, +3432, 3812, 0, +3594, 3944, 0, +3748, 4076, 0, +3896, 4095, 0, +0, 2485, 2755, +0, 2486, 2755, +0, 2488, 2755, +0, 2489, 2755, +0, 2492, 2755, +0, 2495, 2755, +0, 2499, 2755, +0, 2505, 2755, +0, 2512, 2755, +0, 2522, 2755, +0, 2535, 2755, +0, 2551, 2755, +0, 2572, 2755, +0, 2598, 2755, +0, 2632, 2755, +0, 2673, 2755, +0, 2723, 2755, +0, 2755, 2727, +0, 2755, 2635, +0, 2755, 2473, +0, 2755, 2084, +0, 2887, 0, +0, 3019, 0, +1726, 3152, 0, +2482, 3283, 0, +2817, 3416, 0, +3057, 3548, 0, +3256, 3680, 0, +3432, 3812, 0, +3595, 3944, 0, +3748, 4076, 0, +3896, 4095, 0, +0, 2484, 2755, +0, 2485, 2755, +0, 2486, 2755, +0, 2488, 2755, +0, 2491, 2755, +0, 2494, 2755, +0, 2498, 2755, +0, 2504, 2755, +0, 2511, 2755, +0, 2521, 2755, +0, 2533, 2755, +0, 2550, 2755, +0, 2571, 2755, +0, 2598, 2755, +0, 2631, 2755, +0, 2672, 2755, +0, 2722, 2755, +0, 2755, 2728, +0, 2755, 2636, +0, 2755, 2474, +0, 2755, 2086, +0, 2887, 0, +0, 3019, 0, +1735, 3152, 0, +2484, 3283, 0, +2817, 3416, 0, +3057, 3548, 0, +3256, 3680, 0, +3432, 3812, 0, +3595, 3944, 0, +3748, 4076, 0, +3896, 4095, 0, +0, 2482, 2755, +0, 2483, 2755, +0, 2485, 2755, +0, 2487, 2755, +0, 2489, 2755, +0, 2492, 2755, +0, 2497, 2755, +0, 2502, 2755, +0, 2510, 2755, +0, 2520, 2755, +0, 2532, 2755, +0, 2549, 2755, +0, 2570, 2755, +0, 2596, 2755, +0, 2630, 2755, +0, 2671, 2755, +0, 2721, 2755, +0, 2755, 2728, +0, 2755, 2636, +0, 2755, 2475, +0, 2755, 2088, +0, 2887, 0, +0, 3019, 0, +1746, 3151, 0, +2486, 3283, 0, +2818, 3416, 0, +3058, 3548, 0, +3256, 3680, 0, +3432, 3812, 0, +3595, 3944, 0, +3748, 4076, 0, +3896, 4095, 0, +0, 2479, 2755, +0, 2481, 2755, +0, 2482, 2755, +0, 2484, 2755, +0, 2487, 2755, +0, 2490, 2755, +0, 2495, 2755, +0, 2501, 2755, +0, 2508, 2755, +0, 2517, 2755, +0, 2530, 2755, +0, 2547, 2755, +0, 2568, 2755, +0, 2595, 2755, +0, 2628, 2755, +0, 2670, 2755, +0, 2720, 2755, +0, 2755, 2729, +0, 2755, 2637, +0, 2755, 2476, +0, 2755, 2091, +0, 2887, 0, +0, 3019, 0, +1760, 3151, 0, +2489, 3283, 0, +2820, 3416, 0, +3059, 3548, 0, +3257, 3680, 0, +3433, 3812, 0, +3595, 3944, 0, +3748, 4076, 0, +3896, 4095, 0, +0, 2476, 2755, +0, 2477, 2755, +0, 2479, 2755, +0, 2481, 2755, +0, 2484, 2755, +0, 2488, 2754, +0, 2492, 2754, +0, 2498, 2754, +0, 2505, 2754, +0, 2515, 2754, +0, 2528, 2754, +0, 2545, 2754, +0, 2566, 2754, +0, 2593, 2754, +0, 2627, 2754, +0, 2668, 2754, +0, 2718, 2754, +0, 2754, 2730, +0, 2754, 2638, +0, 2754, 2477, +0, 2754, 2094, +0, 2887, 0, +0, 3019, 0, +1779, 3151, 0, +2493, 3283, 0, +2822, 3416, 0, +3060, 3548, 0, +3258, 3680, 0, +3433, 3812, 0, +3595, 3944, 0, +3749, 4076, 0, +3896, 4095, 0, +0, 2472, 2755, +0, 2473, 2755, +0, 2475, 2755, +0, 2477, 2755, +0, 2480, 2755, +0, 2484, 2754, +0, 2489, 2754, +0, 2494, 2754, +0, 2502, 2754, +0, 2512, 2754, +0, 2525, 2754, +0, 2541, 2754, +0, 2563, 2754, +0, 2590, 2754, +0, 2624, 2754, +0, 2666, 2754, +0, 2716, 2754, +0, 2754, 2731, +0, 2754, 2640, +0, 2754, 2479, +0, 2754, 2099, +0, 2886, 0, +0, 3018, 0, +1802, 3151, 0, +2498, 3283, 0, +2824, 3415, 0, +3061, 3548, 0, +3258, 3680, 0, +3434, 3812, 0, +3596, 3944, 0, +3749, 4076, 0, +3896, 4095, 0, +0, 2466, 2755, +0, 2467, 2755, +0, 2469, 2755, +0, 2471, 2755, +0, 2474, 2755, +0, 2478, 2754, +0, 2483, 2754, +0, 2490, 2753, +0, 2497, 2753, +0, 2507, 2753, +0, 2521, 2753, +0, 2537, 2753, +0, 2559, 2753, +0, 2586, 2753, +0, 2620, 2753, +0, 2662, 2753, +0, 2713, 2753, +0, 2753, 2732, +0, 2753, 2641, +0, 2753, 2482, +0, 2753, 2105, +0, 2886, 0, +0, 3018, 0, +1832, 3151, 0, +2504, 3283, 0, +2827, 3415, 0, +3063, 3548, 0, +3260, 3680, 0, +3435, 3812, 0, +3596, 3944, 0, +3749, 4076, 0, +3897, 4095, 0, +0, 2457, 2755, +0, 2459, 2755, +0, 2460, 2755, +0, 2463, 2755, +0, 2466, 2755, +0, 2470, 2754, +0, 2475, 2754, +0, 2482, 2753, +0, 2491, 2752, +0, 2501, 2752, +0, 2514, 2752, +0, 2532, 2752, +0, 2553, 2752, +0, 2581, 2752, +0, 2616, 2752, +0, 2658, 2752, +0, 2710, 2752, +0, 2752, 2734, +0, 2752, 2644, +0, 2752, 2485, +0, 2752, 2113, +0, 2885, 0, +0, 3018, 0, +1869, 3151, 0, +2513, 3283, 0, +2832, 3415, 0, +3066, 3548, 0, +3261, 3680, 0, +3436, 3812, 0, +3597, 3944, 0, +3750, 4076, 0, +3897, 4095, 0, +0, 2446, 2755, +0, 2448, 2755, +0, 2449, 2755, +0, 2452, 2755, +0, 2455, 2755, +0, 2459, 2754, +0, 2464, 2754, +0, 2471, 2753, +0, 2481, 2752, +0, 2493, 2751, +0, 2506, 2751, +0, 2524, 2751, +0, 2546, 2751, +0, 2574, 2751, +0, 2609, 2751, +0, 2652, 2751, +0, 2704, 2751, +0, 2751, 2737, +0, 2751, 2647, +0, 2751, 2490, +0, 2751, 2123, +0, 2885, 0, +0, 3017, 0, +1915, 3150, 0, +2524, 3282, 0, +2837, 3415, 0, +3069, 3547, 0, +3264, 3680, 0, +3437, 3812, 0, +3598, 3944, 0, +3751, 4076, 0, +3898, 4095, 0, +0, 2431, 2755, +0, 2432, 2755, +0, 2434, 2755, +0, 2436, 2755, +0, 2440, 2755, +0, 2444, 2754, +0, 2450, 2754, +0, 2457, 2753, +0, 2467, 2752, +0, 2479, 2751, +0, 2495, 2750, +0, 2514, 2750, +0, 2536, 2750, +0, 2565, 2750, +0, 2601, 2750, +0, 2645, 2750, +0, 2697, 2750, +0, 2750, 2741, +0, 2750, 2651, +0, 2750, 2496, +0, 2750, 2137, +0, 2883, 0, +0, 3016, 0, +1969, 3150, 0, +2539, 3282, 0, +2845, 3414, 0, +3074, 3547, 0, +3267, 3679, 0, +3439, 3812, 0, +3600, 3944, 0, +3752, 4076, 0, +3898, 4095, 0, +0, 2409, 2755, +0, 2411, 2755, +0, 2413, 2755, +0, 2415, 2755, +0, 2419, 2755, +0, 2423, 2754, +0, 2429, 2754, +0, 2437, 2753, +0, 2447, 2752, +0, 2460, 2751, +0, 2477, 2750, +0, 2499, 2748, +0, 2522, 2748, +0, 2552, 2748, +0, 2589, 2748, +0, 2634, 2748, +0, 2687, 2748, +0, 2748, 2745, +0, 2748, 2657, +0, 2748, 2504, +0, 2748, 2155, +0, 2882, 0, +0, 3015, 0, +2033, 3149, 0, +2558, 3281, 0, +2855, 3414, 0, +3080, 3547, 0, +3271, 3679, 0, +3442, 3812, 0, +3602, 3944, 0, +3753, 4076, 0, +3899, 4095, 0, +0, 2379, 2755, +0, 2381, 2755, +0, 2383, 2755, +0, 2386, 2755, +0, 2389, 2755, +0, 2394, 2754, +0, 2400, 2754, +0, 2408, 2753, +0, 2419, 2752, +0, 2433, 2751, +0, 2451, 2750, +0, 2474, 2748, +0, 2503, 2746, +0, 2534, 2746, +0, 2572, 2746, +0, 2619, 2746, +0, 2674, 2746, +0, 2740, 2746, +0, 2746, 2665, +0, 2746, 2515, +0, 2746, 2177, +0, 2880, 0, +0, 3014, 0, +2106, 3148, 0, +2583, 3280, 0, +2867, 3414, 0, +3087, 3546, 0, +3276, 3679, 0, +3446, 3811, 0, +3604, 3944, 0, +3755, 4076, 0, +3901, 4095, 0, +0, 2335, 2755, +0, 2337, 2755, +0, 2339, 2755, +0, 2342, 2755, +0, 2346, 2755, +0, 2351, 2754, +0, 2358, 2754, +0, 2367, 2753, +0, 2379, 2752, +0, 2394, 2751, +0, 2414, 2750, +0, 2439, 2748, +0, 2470, 2746, +0, 2509, 2742, +0, 2550, 2742, +0, 2598, 2742, +0, 2656, 2742, +0, 2724, 2742, +0, 2742, 2675, +0, 2742, 2529, +0, 2742, 2206, +0, 2878, 0, +0, 3012, 0, +2189, 3146, 0, +2613, 3280, 0, +2884, 3413, 0, +3098, 3546, 0, +3282, 3678, 0, +3450, 3811, 0, +3607, 3943, 0, +3757, 4076, 0, +3903, 4095, 0, +0, 2269, 2755, +0, 2271, 2755, +0, 2274, 2755, +0, 2277, 2755, +0, 2281, 2755, +0, 2287, 2754, +0, 2295, 2754, +0, 2305, 2753, +0, 2319, 2752, +0, 2336, 2751, +0, 2359, 2750, +0, 2387, 2748, +0, 2422, 2746, +0, 2465, 2742, +0, 2517, 2738, +0, 2569, 2738, +0, 2631, 2738, +0, 2702, 2738, +0, 2738, 2688, +0, 2738, 2547, +0, 2738, 2241, +0, 2874, 0, +922, 3010, 0, +2280, 3144, 0, +2651, 3278, 0, +2906, 3412, 0, +3111, 3545, 0, +3291, 3678, 0, +3457, 3810, 0, +3612, 3943, 0, +3760, 4075, 0, +3905, 4095, 0, +0, 2162, 2755, +0, 2164, 2755, +0, 2167, 2755, +0, 2172, 2755, +0, 2177, 2755, +0, 2185, 2754, +0, 2195, 2754, +0, 2208, 2753, +0, 2224, 2752, +0, 2245, 2751, +0, 2273, 2750, +0, 2306, 2748, +0, 2348, 2746, +0, 2398, 2742, +0, 2458, 2738, +738, 2527, 2731, +738, 2594, 2731, +738, 2671, 2731, +738, 2731, 2705, +738, 2731, 2570, +738, 2731, 2285, +0, 2870, 963, +1723, 3006, 0, +2379, 3142, 0, +2698, 3276, 0, +2933, 3410, 0, +3129, 3544, 0, +3303, 3677, 0, +3465, 3810, 0, +3618, 3943, 0, +3765, 4075, 0, +3908, 4095, 0, +0, 1962, 2755, +0, 1966, 2755, +0, 1971, 2755, +0, 1977, 2755, +0, 1986, 2755, +0, 1997, 2754, +0, 2012, 2754, +0, 2031, 2753, +0, 2056, 2752, +0, 2086, 2751, +0, 2124, 2750, +0, 2170, 2748, +0, 2226, 2746, +0, 2291, 2742, +0, 2365, 2738, +738, 2448, 2731, +1664, 2540, 2723, +1664, 2626, 2723, +1664, 2719, 2723, +1664, 2723, 2598, +1664, 2723, 2338, +870, 2863, 1498, +2062, 3002, 0, +2484, 3138, 0, +2753, 3274, 0, +2966, 3408, 0, +3151, 3543, 0, +3319, 3676, 0, +3475, 3809, 0, +3626, 3942, 0, +3770, 4075, 0, +3912, 4095, 0, +0, 1353, 2755, +0, 1367, 2755, +0, 1386, 2755, +0, 1409, 2755, +0, 1439, 2755, +0, 1476, 2754, +0, 1521, 2754, +0, 1575, 2753, +0, 1638, 2752, +0, 1711, 2751, +0, 1794, 2750, +0, 1885, 2748, +0, 1983, 2746, +0, 2089, 2742, +0, 2200, 2738, +738, 2315, 2731, +1664, 2435, 2723, +2015, 2557, 2711, +2015, 2665, 2711, +2015, 2711, 2634, +2015, 2711, 2400, +1797, 2855, 1796, +2303, 2995, 1006, +2596, 3134, 0, +2818, 3270, 0, +3008, 3406, 0, +3179, 3541, 0, +3338, 3675, 0, +3490, 3808, 0, +3635, 3941, 0, +3777, 4074, 0, +3917, 4095, 0, +0, 0, 2755, +0, 0, 2755, +0, 0, 2755, +0, 0, 2755, +0, 0, 2755, +0, 0, 2754, +0, 0, 2754, +0, 0, 2753, +0, 0, 2752, +0, 0, 2751, +0, 0, 2750, +0, 0, 2748, +0, 678, 2746, +0, 1463, 2742, +0, 1799, 2738, +738, 2040, 2731, +1664, 2240, 2723, +2015, 2416, 2711, +2261, 2579, 2696, +2261, 2696, 2678, +2261, 2696, 2471, +2246, 2843, 2147, +2503, 2987, 1930, +2712, 3128, 1137, +2893, 3266, 0, +3059, 3402, 0, +3214, 3538, 0, +3363, 3673, 0, +3508, 3807, 0, +3649, 3940, 0, +3787, 4073, 0, +3924, 4095, 0, +0, 0, 2755, +0, 0, 2755, +0, 0, 2755, +0, 0, 2755, +0, 0, 2755, +0, 0, 2754, +0, 0, 2754, +0, 0, 2753, +0, 0, 2752, +0, 0, 2751, +0, 0, 2750, +0, 0, 2748, +0, 0, 2746, +0, 0, 2742, +817, 0, 2738, +1362, 738, 2731, +1664, 1667, 2723, +2015, 2114, 2711, +2261, 2391, 2696, +2463, 2607, 2673, +2463, 2673, 2552, +2522, 2828, 2393, +2680, 2975, 2280, +2831, 3119, 2061, +2976, 3259, 1272, +3118, 3398, 0, +3257, 3535, 0, +3395, 3670, 0, +3531, 3805, 0, +3666, 3939, 0, +3800, 4072, 0, +3934, 4095, 0, +2083, 0, 2755, +2084, 0, 2755, +2086, 0, 2755, +2088, 0, 2755, +2091, 0, 2755, +2094, 0, 2754, +2099, 0, 2754, +2105, 0, 2753, +2113, 0, 2752, +2123, 0, 2751, +2137, 0, 2750, +2155, 0, 2748, +2177, 0, 2746, +2206, 0, 2742, +2241, 0, 2738, +2285, 738, 2731, +2338, 1664, 2723, +2400, 2015, 2711, +2471, 2261, 2696, +2552, 2463, 2673, +2642, 2642, 2642, +2739, 2805, 2596, +2843, 2959, 2526, +2954, 3108, 2412, +3069, 3251, 2194, +3187, 3392, 1406, +3309, 3530, 0, +3434, 3667, 0, +3560, 3802, 0, +3688, 3937, 0, +3816, 4071, 0, +3946, 4095, 0, +2604, 0, 2887, +2604, 0, 2887, +2605, 0, 2887, +2605, 0, 2887, +2606, 0, 2887, +2607, 0, 2887, +2609, 0, 2886, +2611, 0, 2886, +2613, 0, 2885, +2617, 0, 2885, +2621, 0, 2883, +2628, 0, 2882, +2636, 0, 2880, +2647, 0, 2878, +2661, 0, 2874, +2678, 0, 2870, +2701, 870, 2863, +2730, 1796, 2855, +2766, 2147, 2843, +2810, 2393, 2828, +2805, 2596, 2739, +2805, 2684, 2596, +2959, 2942, 2526, +3061, 3108, 2412, +3154, 3251, 2194, +3255, 3392, 1406, +3362, 3530, 0, +3474, 3667, 0, +3591, 3802, 0, +3711, 3937, 0, +3834, 4071, 0, +3960, 4095, 0, +2898, 0, 3019, +2898, 0, 3019, +2898, 0, 3019, +2899, 0, 3019, +2899, 0, 3019, +2900, 0, 3019, +2901, 0, 3018, +2902, 0, 3018, +2903, 0, 3018, +2905, 0, 3017, +2907, 0, 3016, +2911, 0, 3015, +2915, 0, 3014, +2921, 0, 3012, +2928, 0, 3010, +2939, 0, 3006, +2952, 0, 3002, +2968, 1006, 2995, +2987, 1930, 2984, +2975, 2280, 2929, +2959, 2526, 2843, +2959, 2526, 2654, +2959, 2735, 2526, +3108, 3031, 2412, +3248, 3251, 2194, +3331, 3392, 1406, +3423, 3530, 0, +3523, 3667, 0, +3629, 3802, 0, +3741, 3937, 0, +3857, 4071, 0, +3977, 4095, 0, +3123, 0, 3152, +3123, 0, 3152, +3123, 0, 3152, +3123, 0, 3151, +3123, 0, 3151, +3124, 0, 3151, +3124, 0, 3151, +3125, 0, 3151, +3126, 0, 3151, +3127, 0, 3150, +3128, 0, 3150, +3131, 0, 3149, +3133, 0, 3148, +3137, 0, 3146, +3141, 0, 3144, +3142, 0, 3136, +3138, 0, 3120, +3134, 0, 3098, +3128, 1137, 3067, +3119, 2061, 3022, +3108, 2412, 2954, +3108, 2412, 2813, +3108, 2412, 2511, +3108, 2796, 2412, +3251, 3126, 2194, +3392, 3365, 1406, +3495, 3530, 0, +3581, 3667, 0, +3676, 3802, 0, +3777, 3937, 0, +3886, 4071, 0, +3999, 4095, 0, +3284, 0, 3252, +3283, 0, 3252, +3283, 0, 3252, +3283, 0, 3252, +3283, 0, 3251, +3283, 0, 3251, +3283, 0, 3250, +3283, 0, 3249, +3283, 0, 3248, +3282, 0, 3247, +3282, 0, 3244, +3281, 0, 3242, +3280, 0, 3238, +3280, 0, 3233, +3278, 0, 3225, +3276, 0, 3216, +3274, 0, 3203, +3270, 0, 3184, +3266, 0, 3159, +3259, 1272, 3122, +3251, 2194, 3069, +3251, 2194, 2963, +3251, 2194, 2768, +3251, 2195, 2194, +3251, 2866, 2194, +3392, 3230, 1406, +3530, 3480, 0, +3648, 3667, 0, +3731, 3802, 0, +3822, 3937, 0, +3921, 4071, 0, +4027, 4095, 0, +3416, 0, 3335, +3416, 0, 3335, +3416, 0, 3335, +3416, 0, 3335, +3416, 0, 3334, +3416, 0, 3334, +3415, 0, 3333, +3415, 0, 3333, +3415, 0, 3331, +3415, 0, 3330, +3414, 0, 3329, +3414, 0, 3326, +3414, 0, 3323, +3413, 0, 3319, +3412, 0, 3313, +3410, 0, 3305, +3408, 0, 3294, +3406, 0, 3279, +3402, 0, 3259, +3398, 0, 3230, +3392, 1406, 3187, +3392, 1406, 3108, +3392, 1406, 2976, +3392, 1406, 2701, +3392, 2025, 1406, +3392, 2945, 1406, +3530, 3339, 0, +3667, 3599, 0, +3796, 3802, 0, +3876, 3937, 0, +3965, 4071, 0, +4062, 4095, 0, +3548, 0, 3426, +3548, 0, 3426, +3548, 0, 3426, +3548, 0, 3426, +3548, 0, 3426, +3548, 0, 3425, +3548, 0, 3425, +3548, 0, 3424, +3548, 0, 3423, +3547, 0, 3422, +3547, 0, 3421, +3547, 0, 3419, +3546, 0, 3416, +3546, 0, 3413, +3545, 0, 3408, +3544, 0, 3402, +3543, 0, 3393, +3541, 0, 3381, +3538, 0, 3365, +3535, 0, 3342, +3530, 0, 3309, +3530, 0, 3250, +3530, 0, 3157, +3530, 0, 2992, +3530, 0, 2593, +3530, 1621, 0, +3530, 3034, 0, +3667, 3453, 0, +3802, 3721, 0, +3937, 3934, 0, +4018, 4071, 0, +4095, 4095, 0, +3680, 0, 3525, +3680, 0, 3525, +3680, 0, 3525, +3680, 0, 3525, +3680, 0, 3525, +3680, 0, 3525, +3680, 0, 3524, +3680, 0, 3524, +3680, 0, 3523, +3680, 0, 3522, +3679, 0, 3521, +3679, 0, 3520, +3679, 0, 3517, +3678, 0, 3515, +3678, 0, 3511, +3677, 0, 3506, +3676, 0, 3499, +3675, 0, 3490, +3673, 0, 3477, +3670, 0, 3459, +3667, 0, 3434, +3667, 0, 3389, +3667, 0, 3323, +3667, 0, 3215, +3667, 0, 3014, +3667, 0, 2388, +3667, 0, 0, +3667, 3131, 0, +3802, 3571, 0, +3937, 3846, 0, +4071, 4061, 0, +4095, 4095, 0, +3812, 0, 3631, +3812, 0, 3631, +3812, 0, 3631, +3812, 0, 3631, +3812, 0, 3631, +3812, 0, 3630, +3812, 0, 3630, +3812, 0, 3630, +3812, 0, 3629, +3812, 0, 3629, +3812, 0, 3628, +3812, 0, 3626, +3811, 0, 3625, +3811, 0, 3622, +3810, 0, 3620, +3810, 0, 3616, +3809, 0, 3610, +3808, 0, 3603, +3807, 0, 3593, +3805, 0, 3579, +3802, 0, 3560, +3802, 0, 3527, +3802, 0, 3479, +3802, 0, 3405, +3802, 0, 3282, +3802, 0, 3040, +3802, 0, 1737, +3802, 0, 0, +3802, 3234, 0, +3937, 3692, 0, +4071, 3972, 0, +4095, 4095, 0, +3944, 0, 3742, +3944, 0, 3742, +3944, 0, 3742, +3944, 0, 3742, +3944, 0, 3742, +3944, 0, 3742, +3944, 0, 3741, +3944, 0, 3741, +3944, 0, 3741, +3944, 0, 3740, +3944, 0, 3740, +3944, 0, 3739, +3944, 0, 3737, +3943, 0, 3736, +3943, 0, 3733, +3943, 0, 3730, +3942, 0, 3726, +3941, 0, 3720, +3940, 0, 3713, +3939, 0, 3702, +3937, 0, 3688, +3937, 0, 3663, +3937, 0, 3628, +3937, 0, 3575, +3937, 0, 3495, +3937, 0, 3359, +3937, 0, 3073, +3937, 0, 0, +3937, 0, 0, +3937, 3344, 0, +4071, 3816, 0, +4095, 4095, 0, +4076, 0, 3858, +4076, 0, 3858, +4076, 0, 3858, +4076, 0, 3858, +4076, 0, 3858, +4076, 0, 3858, +4076, 0, 3858, +4076, 0, 3857, +4076, 0, 3857, +4076, 0, 3856, +4076, 0, 3856, +4076, 0, 3855, +4076, 0, 3854, +4076, 0, 3853, +4075, 0, 3851, +4075, 0, 3849, +4075, 0, 3846, +4074, 0, 3841, +4073, 0, 3835, +4072, 0, 3827, +4071, 0, 3816, +4071, 0, 3798, +4071, 0, 3772, +4071, 0, 3735, +4071, 0, 3679, +4071, 0, 3593, +4071, 0, 3445, +4071, 0, 3113, +4071, 0, 0, +4071, 0, 0, +4071, 3458, 0, +4095, 3943, 0, +4095, 0, 3978, +4095, 0, 3978, +4095, 0, 3978, +4095, 0, 3978, +4095, 0, 3977, +4095, 0, 3977, +4095, 0, 3977, +4095, 0, 3977, +4095, 0, 3977, +4095, 0, 3977, +4095, 0, 3976, +4095, 0, 3976, +4095, 0, 3975, +4095, 0, 3974, +4095, 0, 3972, +4095, 0, 3971, +4095, 0, 3968, +4095, 0, 3965, +4095, 0, 3961, +4095, 0, 3954, +4095, 0, 3946, +4095, 0, 3932, +4095, 0, 3913, +4095, 0, 3886, +4095, 0, 3847, +4095, 0, 3790, +4095, 0, 3699, +4095, 0, 3539, +4095, 0, 3164, +4095, 0, 0, +4095, 0, 0, +4095, 3576, 0, +0, 2618, 2887, +0, 2619, 2887, +0, 2620, 2887, +0, 2621, 2887, +0, 2623, 2887, +0, 2625, 2887, +0, 2628, 2887, +0, 2633, 2887, +0, 2638, 2887, +0, 2646, 2887, +0, 2655, 2887, +0, 2668, 2887, +0, 2684, 2887, +0, 2705, 2887, +0, 2732, 2887, +0, 2765, 2887, +0, 2806, 2887, +0, 2856, 2887, +0, 2887, 2859, +0, 2887, 2767, +0, 2887, 2604, +0, 2887, 2215, +0, 3019, 0, +0, 3152, 0, +1844, 3284, 0, +2613, 3416, 0, +2948, 3548, 0, +3188, 3680, 0, +3387, 3812, 0, +3564, 3944, 0, +3726, 4076, 0, +3880, 4095, 0, +0, 2617, 2887, +0, 2618, 2887, +0, 2619, 2887, +0, 2620, 2887, +0, 2622, 2887, +0, 2625, 2887, +0, 2628, 2887, +0, 2632, 2887, +0, 2638, 2887, +0, 2645, 2887, +0, 2655, 2887, +0, 2667, 2887, +0, 2684, 2887, +0, 2705, 2887, +0, 2731, 2887, +0, 2764, 2887, +0, 2805, 2887, +0, 2855, 2887, +0, 2887, 2859, +0, 2887, 2767, +0, 2887, 2604, +0, 2887, 2215, +0, 3019, 0, +0, 3152, 0, +1849, 3283, 0, +2614, 3416, 0, +2948, 3548, 0, +3188, 3680, 0, +3388, 3812, 0, +3564, 3944, 0, +3726, 4076, 0, +3880, 4095, 0, +0, 2616, 2887, +0, 2617, 2887, +0, 2618, 2887, +0, 2620, 2887, +0, 2621, 2887, +0, 2624, 2887, +0, 2627, 2887, +0, 2631, 2887, +0, 2637, 2887, +0, 2644, 2887, +0, 2654, 2887, +0, 2667, 2887, +0, 2683, 2887, +0, 2704, 2887, +0, 2731, 2887, +0, 2764, 2887, +0, 2805, 2887, +0, 2855, 2887, +0, 2887, 2859, +0, 2887, 2767, +0, 2887, 2605, +0, 2887, 2217, +0, 3019, 0, +0, 3152, 0, +1856, 3283, 0, +2615, 3416, 0, +2949, 3548, 0, +3189, 3680, 0, +3388, 3812, 0, +3564, 3944, 0, +3726, 4076, 0, +3880, 4095, 0, +0, 2615, 2887, +0, 2616, 2887, +0, 2617, 2887, +0, 2619, 2887, +0, 2620, 2887, +0, 2623, 2887, +0, 2626, 2887, +0, 2630, 2887, +0, 2636, 2887, +0, 2643, 2887, +0, 2653, 2887, +0, 2666, 2887, +0, 2682, 2887, +0, 2703, 2887, +0, 2730, 2887, +0, 2763, 2887, +0, 2804, 2887, +0, 2854, 2887, +0, 2887, 2860, +0, 2887, 2768, +0, 2887, 2605, +0, 2887, 2218, +0, 3019, 0, +0, 3151, 0, +1864, 3283, 0, +2617, 3416, 0, +2950, 3548, 0, +3189, 3680, 0, +3388, 3812, 0, +3564, 3944, 0, +3727, 4076, 0, +3880, 4095, 0, +0, 2613, 2887, +0, 2614, 2887, +0, 2615, 2887, +0, 2617, 2887, +0, 2619, 2887, +0, 2621, 2887, +0, 2625, 2887, +0, 2629, 2887, +0, 2635, 2887, +0, 2642, 2887, +0, 2651, 2887, +0, 2664, 2887, +0, 2681, 2887, +0, 2702, 2887, +0, 2728, 2887, +0, 2762, 2887, +0, 2803, 2887, +0, 2853, 2887, +0, 2887, 2860, +0, 2887, 2768, +0, 2887, 2606, +0, 2887, 2220, +0, 3019, 0, +0, 3151, 0, +1875, 3283, 0, +2619, 3416, 0, +2951, 3548, 0, +3190, 3680, 0, +3388, 3812, 0, +3564, 3944, 0, +3727, 4076, 0, +3880, 4095, 0, +0, 2611, 2887, +0, 2612, 2887, +0, 2613, 2887, +0, 2614, 2887, +0, 2617, 2887, +0, 2619, 2887, +0, 2623, 2887, +0, 2627, 2887, +0, 2632, 2887, +0, 2640, 2887, +0, 2650, 2887, +0, 2662, 2887, +0, 2679, 2887, +0, 2700, 2887, +0, 2727, 2887, +0, 2761, 2887, +0, 2802, 2887, +0, 2852, 2887, +0, 2887, 2861, +0, 2887, 2769, +0, 2887, 2607, +0, 2887, 2223, +0, 3019, 0, +0, 3151, 0, +1890, 3283, 0, +2621, 3416, 0, +2952, 3548, 0, +3191, 3680, 0, +3389, 3812, 0, +3565, 3944, 0, +3727, 4076, 0, +3881, 4095, 0, +0, 2607, 2887, +0, 2608, 2887, +0, 2609, 2887, +0, 2611, 2887, +0, 2613, 2887, +0, 2616, 2887, +0, 2620, 2886, +0, 2624, 2886, +0, 2630, 2886, +0, 2637, 2886, +0, 2647, 2886, +0, 2660, 2886, +0, 2677, 2886, +0, 2698, 2886, +0, 2725, 2886, +0, 2759, 2886, +0, 2800, 2886, +0, 2850, 2886, +0, 2886, 2862, +0, 2886, 2770, +0, 2886, 2609, +0, 2886, 2226, +0, 3018, 0, +0, 3151, 0, +1908, 3283, 0, +2625, 3415, 0, +2954, 3548, 0, +3192, 3680, 0, +3390, 3812, 0, +3565, 3944, 0, +3727, 4076, 0, +3881, 4095, 0, +0, 2603, 2887, +0, 2604, 2887, +0, 2605, 2887, +0, 2607, 2887, +0, 2609, 2887, +0, 2612, 2887, +0, 2616, 2886, +0, 2621, 2886, +0, 2626, 2886, +0, 2634, 2886, +0, 2644, 2886, +0, 2657, 2886, +0, 2673, 2886, +0, 2695, 2886, +0, 2722, 2886, +0, 2756, 2886, +0, 2798, 2886, +0, 2848, 2886, +0, 2886, 2863, +0, 2886, 2772, +0, 2886, 2611, +0, 2886, 2231, +0, 3018, 0, +0, 3151, 0, +1932, 3283, 0, +2630, 3415, 0, +2956, 3548, 0, +3193, 3680, 0, +3391, 3812, 0, +3566, 3944, 0, +3728, 4076, 0, +3881, 4095, 0, +0, 2597, 2887, +0, 2598, 2887, +0, 2599, 2887, +0, 2601, 2887, +0, 2603, 2887, +0, 2606, 2887, +0, 2610, 2886, +0, 2615, 2886, +0, 2622, 2885, +0, 2629, 2885, +0, 2639, 2885, +0, 2652, 2885, +0, 2669, 2885, +0, 2691, 2885, +0, 2718, 2885, +0, 2752, 2885, +0, 2795, 2885, +0, 2845, 2885, +0, 2885, 2864, +0, 2885, 2773, +0, 2885, 2613, +0, 2885, 2237, +0, 3018, 0, +0, 3151, 0, +1962, 3283, 0, +2637, 3415, 0, +2960, 3548, 0, +3195, 3680, 0, +3392, 3812, 0, +3567, 3944, 0, +3728, 4076, 0, +3881, 4095, 0, +0, 2589, 2887, +0, 2589, 2887, +0, 2591, 2887, +0, 2592, 2887, +0, 2595, 2887, +0, 2598, 2887, +0, 2602, 2886, +0, 2607, 2886, +0, 2614, 2885, +0, 2623, 2885, +0, 2633, 2885, +0, 2647, 2885, +0, 2664, 2885, +0, 2685, 2885, +0, 2713, 2885, +0, 2748, 2885, +0, 2790, 2885, +0, 2842, 2885, +0, 2885, 2866, +0, 2885, 2776, +0, 2885, 2617, +0, 2885, 2245, +0, 3017, 0, +0, 3150, 0, +1999, 3282, 0, +2646, 3415, 0, +2964, 3547, 0, +3198, 3680, 0, +3394, 3812, 0, +3568, 3944, 0, +3729, 4076, 0, +3882, 4095, 0, +0, 2577, 2887, +0, 2578, 2887, +0, 2580, 2887, +0, 2581, 2887, +0, 2584, 2887, +0, 2587, 2887, +0, 2591, 2886, +0, 2596, 2886, +0, 2603, 2885, +0, 2613, 2885, +0, 2625, 2883, +0, 2639, 2883, +0, 2656, 2883, +0, 2678, 2883, +0, 2706, 2883, +0, 2741, 2883, +0, 2784, 2883, +0, 2836, 2883, +0, 2883, 2869, +0, 2883, 2779, +0, 2883, 2621, +0, 2883, 2255, +0, 3016, 0, +0, 3150, 0, +2045, 3282, 0, +2657, 3414, 0, +2970, 3547, 0, +3201, 3679, 0, +3396, 3812, 0, +3569, 3944, 0, +3730, 4076, 0, +3883, 4095, 0, +0, 2562, 2887, +0, 2563, 2887, +0, 2564, 2887, +0, 2566, 2887, +0, 2569, 2887, +0, 2572, 2887, +0, 2576, 2886, +0, 2581, 2886, +0, 2589, 2885, +0, 2599, 2885, +0, 2611, 2883, +0, 2628, 2882, +0, 2645, 2882, +0, 2668, 2882, +0, 2697, 2882, +0, 2733, 2882, +0, 2777, 2882, +0, 2829, 2882, +0, 2882, 2873, +0, 2882, 2784, +0, 2882, 2628, +0, 2882, 2269, +0, 3015, 0, +0, 3149, 0, +2100, 3281, 0, +2672, 3414, 0, +2977, 3547, 0, +3206, 3679, 0, +3399, 3812, 0, +3571, 3944, 0, +3732, 4076, 0, +3884, 4095, 0, +0, 2541, 2887, +0, 2542, 2887, +0, 2543, 2887, +0, 2545, 2887, +0, 2548, 2887, +0, 2551, 2887, +0, 2555, 2886, +0, 2561, 2886, +0, 2569, 2885, +0, 2579, 2885, +0, 2592, 2883, +0, 2609, 2882, +0, 2631, 2880, +0, 2654, 2880, +0, 2684, 2880, +0, 2721, 2880, +0, 2766, 2880, +0, 2820, 2880, +0, 2880, 2877, +0, 2880, 2789, +0, 2880, 2636, +0, 2880, 2287, +0, 3014, 0, +0, 3148, 0, +2164, 3280, 0, +2691, 3414, 0, +2987, 3546, 0, +3212, 3679, 0, +3403, 3811, 0, +3574, 3944, 0, +3734, 4076, 0, +3885, 4095, 0, +0, 2510, 2887, +0, 2511, 2887, +0, 2513, 2887, +0, 2515, 2887, +0, 2517, 2887, +0, 2521, 2887, +0, 2526, 2886, +0, 2532, 2886, +0, 2540, 2885, +0, 2551, 2885, +0, 2565, 2883, +0, 2583, 2882, +0, 2606, 2880, +0, 2636, 2878, +0, 2666, 2878, +0, 2704, 2878, +0, 2751, 2878, +0, 2807, 2878, +0, 2872, 2878, +0, 2878, 2797, +0, 2878, 2647, +0, 2878, 2309, +0, 3012, 0, +0, 3146, 0, +2237, 3280, 0, +2715, 3413, 0, +3000, 3546, 0, +3220, 3678, 0, +3408, 3811, 0, +3578, 3943, 0, +3736, 4076, 0, +3887, 4095, 0, +0, 2466, 2887, +0, 2467, 2887, +0, 2469, 2887, +0, 2471, 2887, +0, 2474, 2887, +0, 2478, 2887, +0, 2483, 2886, +0, 2490, 2886, +0, 2499, 2885, +0, 2511, 2885, +0, 2526, 2883, +0, 2546, 2882, +0, 2571, 2880, +0, 2602, 2878, +0, 2641, 2874, +0, 2681, 2874, +0, 2730, 2874, +0, 2788, 2874, +0, 2856, 2874, +0, 2874, 2807, +0, 2874, 2661, +0, 2874, 2338, +0, 3010, 0, +0, 3144, 0, +2320, 3278, 0, +2746, 3412, 0, +3016, 3545, 0, +3230, 3678, 0, +3415, 3810, 0, +3583, 3943, 0, +3739, 4075, 0, +3889, 4095, 0, +0, 2400, 2887, +0, 2401, 2887, +0, 2403, 2887, +0, 2406, 2887, +0, 2409, 2887, +0, 2413, 2887, +0, 2419, 2886, +0, 2427, 2886, +0, 2438, 2885, +0, 2451, 2885, +0, 2469, 2883, +0, 2491, 2882, +0, 2519, 2880, +0, 2554, 2878, +0, 2597, 2874, +0, 2649, 2870, +0, 2701, 2870, +0, 2763, 2870, +0, 2834, 2870, +0, 2870, 2820, +0, 2870, 2678, +0, 2870, 2374, +0, 3006, 0, +1068, 3142, 0, +2411, 3276, 0, +2784, 3410, 0, +3038, 3544, 0, +3243, 3677, 0, +3424, 3810, 0, +3589, 3943, 0, +3744, 4075, 0, +3893, 4095, 0, +0, 2292, 2887, +0, 2294, 2887, +0, 2296, 2887, +0, 2299, 2887, +0, 2304, 2887, +0, 2310, 2887, +0, 2317, 2886, +0, 2327, 2886, +0, 2340, 2885, +0, 2356, 2885, +0, 2378, 2883, +0, 2405, 2882, +0, 2439, 2880, +0, 2480, 2878, +0, 2530, 2874, +0, 2590, 2870, +870, 2659, 2863, +870, 2726, 2863, +870, 2803, 2863, +870, 2863, 2837, +870, 2863, 2701, +870, 2863, 2417, +0, 3002, 1109, +1857, 3138, 0, +2510, 3274, 0, +2830, 3408, 0, +3065, 3543, 0, +3261, 3676, 0, +3435, 3809, 0, +3597, 3942, 0, +3750, 4075, 0, +3897, 4095, 0, +0, 2091, 2887, +0, 2094, 2887, +0, 2098, 2887, +0, 2103, 2887, +0, 2110, 2887, +0, 2118, 2887, +0, 2129, 2886, +0, 2144, 2886, +0, 2163, 2885, +0, 2188, 2885, +0, 2218, 2883, +0, 2256, 2882, +0, 2302, 2880, +0, 2358, 2878, +0, 2423, 2874, +0, 2497, 2870, +870, 2580, 2863, +1796, 2672, 2855, +1796, 2758, 2855, +1796, 2852, 2855, +1796, 2855, 2730, +1796, 2855, 2470, +1006, 2995, 1635, +2195, 3134, 0, +2616, 3270, 0, +2886, 3406, 0, +3099, 3541, 0, +3283, 3675, 0, +3451, 3808, 0, +3608, 3941, 0, +3757, 4074, 0, +3903, 4095, 0, +0, 1472, 2887, +0, 1483, 2887, +0, 1497, 2887, +0, 1516, 2887, +0, 1540, 2887, +0, 1569, 2887, +0, 1606, 2886, +0, 1651, 2886, +0, 1706, 2885, +0, 1769, 2885, +0, 1843, 2883, +0, 1925, 2882, +0, 2016, 2880, +0, 2115, 2878, +0, 2220, 2874, +0, 2332, 2870, +870, 2447, 2863, +1796, 2567, 2855, +2147, 2689, 2843, +2147, 2797, 2843, +2147, 2843, 2766, +2147, 2843, 2532, +1930, 2987, 1930, +2436, 3128, 1137, +2727, 3266, 0, +2951, 3402, 0, +3140, 3538, 0, +3311, 3673, 0, +3470, 3807, 0, +3622, 3940, 0, +3768, 4073, 0, +3910, 4095, 0, +0, 0, 2887, +0, 0, 2887, +0, 0, 2887, +0, 0, 2887, +0, 0, 2887, +0, 0, 2887, +0, 0, 2886, +0, 0, 2886, +0, 0, 2885, +0, 0, 2885, +0, 0, 2883, +0, 0, 2882, +0, 0, 2880, +0, 817, 2878, +0, 1596, 2874, +0, 1932, 2870, +870, 2173, 2863, +1796, 2372, 2855, +2147, 2549, 2843, +2393, 2711, 2828, +2393, 2828, 2810, +2393, 2828, 2603, +2377, 2975, 2280, +2636, 3119, 2061, +2843, 3259, 1272, +3025, 3398, 0, +3190, 3535, 0, +3346, 3670, 0, +3495, 3805, 0, +3640, 3939, 0, +3781, 4072, 0, +3920, 4095, 0, +0, 0, 2887, +0, 0, 2887, +0, 0, 2887, +0, 0, 2887, +0, 0, 2887, +0, 0, 2887, +0, 0, 2886, +0, 0, 2886, +0, 0, 2885, +0, 0, 2885, +0, 0, 2883, +0, 0, 2882, +0, 0, 2880, +0, 0, 2878, +0, 0, 2874, +963, 0, 2870, +1498, 870, 2863, +1796, 1797, 2855, +2147, 2246, 2843, +2393, 2522, 2828, +2596, 2739, 2805, +2596, 2805, 2684, +2654, 2959, 2526, +2813, 3108, 2412, +2963, 3251, 2194, +3108, 3392, 1406, +3250, 3530, 0, +3389, 3667, 0, +3527, 3802, 0, +3663, 3937, 0, +3798, 4071, 0, +3932, 4095, 0, +2215, 0, 2887, +2215, 0, 2887, +2217, 0, 2887, +2218, 0, 2887, +2220, 0, 2887, +2223, 0, 2887, +2226, 0, 2886, +2231, 0, 2886, +2237, 0, 2885, +2245, 0, 2885, +2255, 0, 2883, +2269, 0, 2882, +2287, 0, 2880, +2309, 0, 2878, +2338, 0, 2874, +2374, 0, 2870, +2417, 870, 2863, +2470, 1796, 2855, +2532, 2147, 2843, +2603, 2393, 2828, +2684, 2596, 2805, +2774, 2774, 2774, +2871, 2937, 2728, +2976, 3092, 2658, +3085, 3239, 2544, +3201, 3383, 2326, +3320, 3524, 1536, +3441, 3662, 0, +3566, 3799, 0, +3692, 3934, 0, +3820, 4069, 0, +3949, 4095, 0, +2735, 0, 3019, +2735, 0, 3019, +2736, 0, 3019, +2736, 0, 3019, +2737, 0, 3019, +2738, 0, 3019, +2739, 0, 3018, +2740, 0, 3018, +2742, 0, 3018, +2745, 0, 3017, +2749, 0, 3016, +2753, 0, 3015, +2759, 0, 3014, +2767, 0, 3012, +2778, 0, 3010, +2792, 0, 3006, +2810, 0, 3002, +2833, 1006, 2995, +2862, 1930, 2987, +2898, 2280, 2975, +2942, 2526, 2959, +2937, 2728, 2871, +2937, 2816, 2728, +3092, 3074, 2658, +3193, 3239, 2544, +3286, 3383, 2326, +3387, 3524, 1536, +3494, 3662, 0, +3606, 3799, 0, +3723, 3934, 0, +3843, 4069, 0, +3966, 4095, 0, +3031, 0, 3152, +3031, 0, 3152, +3031, 0, 3152, +3031, 0, 3151, +3031, 0, 3151, +3032, 0, 3151, +3032, 0, 3151, +3033, 0, 3151, +3034, 0, 3151, +3036, 0, 3150, +3038, 0, 3150, +3040, 0, 3149, +3043, 0, 3148, +3047, 0, 3146, +3053, 0, 3144, +3061, 0, 3142, +3071, 0, 3138, +3084, 0, 3134, +3101, 1137, 3128, +3119, 2061, 3116, +3108, 2412, 3061, +3092, 2658, 2976, +3092, 2658, 2787, +3092, 2867, 2658, +3239, 3162, 2544, +3380, 3383, 2326, +3463, 3524, 1536, +3555, 3662, 0, +3655, 3799, 0, +3761, 3934, 0, +3873, 4069, 0, +3989, 4095, 0, +3254, 0, 3284, +3254, 0, 3283, +3255, 0, 3283, +3255, 0, 3283, +3255, 0, 3283, +3255, 0, 3283, +3256, 0, 3283, +3256, 0, 3283, +3257, 0, 3283, +3257, 0, 3282, +3259, 0, 3282, +3260, 0, 3281, +3262, 0, 3280, +3265, 0, 3280, +3269, 0, 3278, +3273, 0, 3276, +3274, 0, 3268, +3270, 0, 3252, +3266, 0, 3230, +3259, 1272, 3199, +3251, 2194, 3154, +3239, 2544, 3085, +3239, 2544, 2945, +3239, 2544, 2642, +3239, 2928, 2544, +3383, 3258, 2326, +3524, 3497, 1536, +3626, 3662, 0, +3713, 3799, 0, +3808, 3934, 0, +3910, 4069, 0, +4018, 4095, 0, +3416, 0, 3385, +3416, 0, 3385, +3416, 0, 3384, +3416, 0, 3384, +3416, 0, 3384, +3416, 0, 3384, +3415, 0, 3383, +3415, 0, 3382, +3415, 0, 3381, +3415, 0, 3380, +3414, 0, 3379, +3414, 0, 3376, +3414, 0, 3374, +3413, 0, 3370, +3412, 0, 3365, +3410, 0, 3358, +3408, 0, 3348, +3406, 0, 3335, +3402, 0, 3317, +3398, 0, 3291, +3392, 1406, 3255, +3383, 2326, 3201, +3383, 2326, 3095, +3383, 2326, 2900, +3383, 2326, 2328, +3383, 2998, 2326, +3524, 3362, 1536, +3662, 3612, 0, +3781, 3799, 0, +3863, 3934, 0, +3954, 4069, 0, +4054, 4095, 0, +3548, 0, 3467, +3548, 0, 3467, +3548, 0, 3467, +3548, 0, 3467, +3548, 0, 3467, +3548, 0, 3466, +3548, 0, 3466, +3548, 0, 3466, +3548, 0, 3465, +3547, 0, 3464, +3547, 0, 3462, +3547, 0, 3461, +3546, 0, 3458, +3546, 0, 3455, +3545, 0, 3451, +3544, 0, 3445, +3543, 0, 3437, +3541, 0, 3426, +3538, 0, 3411, +3535, 0, 3391, +3530, 0, 3362, +3524, 1536, 3320, +3524, 1536, 3241, +3524, 1536, 3108, +3524, 1536, 2833, +3524, 2158, 1536, +3524, 3078, 1536, +3662, 3471, 0, +3799, 3731, 0, +3928, 3934, 0, +4008, 4069, 0, +4095, 4095, 0, +3680, 0, 3558, +3680, 0, 3558, +3680, 0, 3558, +3680, 0, 3558, +3680, 0, 3558, +3680, 0, 3558, +3680, 0, 3557, +3680, 0, 3557, +3680, 0, 3556, +3680, 0, 3556, +3679, 0, 3554, +3679, 0, 3553, +3679, 0, 3551, +3678, 0, 3548, +3678, 0, 3545, +3677, 0, 3540, +3676, 0, 3534, +3675, 0, 3525, +3673, 0, 3513, +3670, 0, 3497, +3667, 0, 3474, +3662, 0, 3441, +3662, 0, 3382, +3662, 0, 3289, +3662, 0, 3125, +3662, 0, 2724, +3662, 1753, 0, +3662, 3166, 0, +3799, 3585, 0, +3934, 3853, 0, +4069, 4066, 0, +4095, 4095, 0, +3812, 0, 3657, +3812, 0, 3657, +3812, 0, 3657, +3812, 0, 3657, +3812, 0, 3657, +3812, 0, 3657, +3812, 0, 3657, +3812, 0, 3656, +3812, 0, 3656, +3812, 0, 3655, +3812, 0, 3654, +3812, 0, 3653, +3811, 0, 3652, +3811, 0, 3650, +3810, 0, 3647, +3810, 0, 3643, +3809, 0, 3638, +3808, 0, 3631, +3807, 0, 3622, +3805, 0, 3609, +3802, 0, 3591, +3799, 0, 3566, +3799, 0, 3522, +3799, 0, 3455, +3799, 0, 3347, +3799, 0, 3145, +3799, 0, 2519, +3799, 0, 0, +3799, 3262, 0, +3934, 3703, 0, +4069, 3978, 0, +4095, 4095, 0, +3944, 0, 3763, +3944, 0, 3763, +3944, 0, 3763, +3944, 0, 3763, +3944, 0, 3763, +3944, 0, 3763, +3944, 0, 3762, +3944, 0, 3762, +3944, 0, 3762, +3944, 0, 3761, +3944, 0, 3761, +3944, 0, 3760, +3944, 0, 3758, +3943, 0, 3757, +3943, 0, 3755, +3943, 0, 3752, +3942, 0, 3748, +3941, 0, 3742, +3940, 0, 3735, +3939, 0, 3725, +3937, 0, 3711, +3934, 0, 3692, +3934, 0, 3659, +3934, 0, 3611, +3934, 0, 3537, +3934, 0, 3414, +3934, 0, 3172, +3934, 0, 1863, +3934, 0, 0, +3934, 3366, 0, +4069, 3824, 0, +4095, 4095, 0, +4076, 0, 3874, +4076, 0, 3874, +4076, 0, 3874, +4076, 0, 3874, +4076, 0, 3874, +4076, 0, 3874, +4076, 0, 3874, +4076, 0, 3873, +4076, 0, 3873, +4076, 0, 3873, +4076, 0, 3872, +4076, 0, 3872, +4076, 0, 3871, +4076, 0, 3869, +4075, 0, 3868, +4075, 0, 3865, +4075, 0, 3862, +4074, 0, 3858, +4073, 0, 3852, +4072, 0, 3845, +4071, 0, 3834, +4069, 0, 3820, +4069, 0, 3795, +4069, 0, 3760, +4069, 0, 3708, +4069, 0, 3627, +4069, 0, 3491, +4069, 0, 3205, +4069, 0, 0, +4069, 0, 0, +4069, 3475, 0, +4095, 3949, 0, +4095, 0, 3990, +4095, 0, 3990, +4095, 0, 3990, +4095, 0, 3990, +4095, 0, 3990, +4095, 0, 3990, +4095, 0, 3990, +4095, 0, 3990, +4095, 0, 3989, +4095, 0, 3989, +4095, 0, 3989, +4095, 0, 3988, +4095, 0, 3988, +4095, 0, 3986, +4095, 0, 3985, +4095, 0, 3983, +4095, 0, 3981, +4095, 0, 3978, +4095, 0, 3974, +4095, 0, 3968, +4095, 0, 3960, +4095, 0, 3949, +4095, 0, 3930, +4095, 0, 3904, +4095, 0, 3867, +4095, 0, 3812, +4095, 0, 3726, +4095, 0, 3577, +4095, 0, 3246, +4095, 0, 0, +4095, 0, 0, +4095, 3590, 0, +0, 2750, 3019, +0, 2750, 3019, +0, 2751, 3019, +0, 2752, 3019, +0, 2754, 3019, +0, 2755, 3019, +0, 2758, 3019, +0, 2761, 3019, +0, 2765, 3019, +0, 2771, 3019, +0, 2778, 3019, +0, 2788, 3019, +0, 2800, 3019, +0, 2816, 3019, +0, 2837, 3019, +0, 2864, 3019, +0, 2897, 3019, +0, 2938, 3019, +0, 2988, 3019, +0, 3019, 2991, +0, 3019, 2898, +0, 3019, 2735, +0, 3019, 2346, +0, 3152, 0, +0, 3284, 0, +1977, 3416, 0, +2745, 3548, 0, +3080, 3680, 0, +3320, 3812, 0, +3520, 3944, 0, +3696, 4076, 0, +3859, 4095, 0, +0, 2749, 3019, +0, 2750, 3019, +0, 2751, 3019, +0, 2752, 3019, +0, 2753, 3019, +0, 2755, 3019, +0, 2757, 3019, +0, 2760, 3019, +0, 2765, 3019, +0, 2770, 3019, +0, 2777, 3019, +0, 2787, 3019, +0, 2800, 3019, +0, 2816, 3019, +0, 2837, 3019, +0, 2863, 3019, +0, 2897, 3019, +0, 2938, 3019, +0, 2987, 3019, +0, 3019, 2991, +0, 3019, 2898, +0, 3019, 2735, +0, 3019, 2346, +0, 3152, 0, +0, 3283, 0, +1981, 3416, 0, +2745, 3548, 0, +3080, 3680, 0, +3321, 3812, 0, +3520, 3944, 0, +3696, 4076, 0, +3859, 4095, 0, +0, 2748, 3019, +0, 2749, 3019, +0, 2750, 3019, +0, 2751, 3019, +0, 2752, 3019, +0, 2754, 3019, +0, 2757, 3019, +0, 2760, 3019, +0, 2764, 3019, +0, 2770, 3019, +0, 2777, 3019, +0, 2787, 3019, +0, 2799, 3019, +0, 2816, 3019, +0, 2836, 3019, +0, 2863, 3019, +0, 2896, 3019, +0, 2938, 3019, +0, 2987, 3019, +0, 3019, 2991, +0, 3019, 2898, +0, 3019, 2736, +0, 3019, 2347, +0, 3152, 0, +0, 3283, 0, +1986, 3416, 0, +2746, 3548, 0, +3081, 3680, 0, +3321, 3812, 0, +3520, 3944, 0, +3696, 4076, 0, +3859, 4095, 0, +0, 2747, 3019, +0, 2748, 3019, +0, 2749, 3019, +0, 2750, 3019, +0, 2751, 3019, +0, 2753, 3019, +0, 2756, 3019, +0, 2759, 3019, +0, 2763, 3019, +0, 2769, 3019, +0, 2776, 3019, +0, 2786, 3019, +0, 2798, 3019, +0, 2815, 3019, +0, 2836, 3019, +0, 2863, 3019, +0, 2896, 3019, +0, 2937, 3019, +0, 2987, 3019, +0, 3019, 2991, +0, 3019, 2899, +0, 3019, 2736, +0, 3019, 2348, +0, 3151, 0, +0, 3283, 0, +1992, 3416, 0, +2747, 3548, 0, +3081, 3680, 0, +3321, 3812, 0, +3520, 3944, 0, +3696, 4076, 0, +3859, 4095, 0, +0, 2746, 3019, +0, 2747, 3019, +0, 2747, 3019, +0, 2749, 3019, +0, 2750, 3019, +0, 2752, 3019, +0, 2755, 3019, +0, 2758, 3019, +0, 2762, 3019, +0, 2768, 3019, +0, 2775, 3019, +0, 2785, 3019, +0, 2797, 3019, +0, 2814, 3019, +0, 2835, 3019, +0, 2862, 3019, +0, 2895, 3019, +0, 2936, 3019, +0, 2986, 3019, +0, 3019, 2992, +0, 3019, 2899, +0, 3019, 2737, +0, 3019, 2350, +0, 3151, 0, +0, 3283, 0, +2000, 3416, 0, +2749, 3548, 0, +3082, 3680, 0, +3322, 3812, 0, +3520, 3944, 0, +3696, 4076, 0, +3859, 4095, 0, +0, 2744, 3019, +0, 2745, 3019, +0, 2746, 3019, +0, 2747, 3019, +0, 2749, 3019, +0, 2751, 3019, +0, 2753, 3019, +0, 2756, 3019, +0, 2761, 3019, +0, 2766, 3019, +0, 2774, 3019, +0, 2784, 3019, +0, 2796, 3019, +0, 2813, 3019, +0, 2834, 3019, +0, 2860, 3019, +0, 2894, 3019, +0, 2935, 3019, +0, 2985, 3019, +0, 3019, 2992, +0, 3019, 2900, +0, 3019, 2738, +0, 3019, 2352, +0, 3151, 0, +0, 3283, 0, +2011, 3416, 0, +2751, 3548, 0, +3083, 3680, 0, +3322, 3812, 0, +3521, 3944, 0, +3696, 4076, 0, +3859, 4095, 0, +0, 2742, 3019, +0, 2742, 3019, +0, 2743, 3019, +0, 2745, 3019, +0, 2746, 3019, +0, 2748, 3019, +0, 2751, 3018, +0, 2754, 3018, +0, 2759, 3018, +0, 2764, 3018, +0, 2772, 3018, +0, 2782, 3018, +0, 2794, 3018, +0, 2811, 3018, +0, 2832, 3018, +0, 2859, 3018, +0, 2892, 3018, +0, 2934, 3018, +0, 2984, 3018, +0, 3018, 2992, +0, 3018, 2901, +0, 3018, 2739, +0, 3018, 2354, +0, 3151, 0, +0, 3283, 0, +2026, 3415, 0, +2754, 3548, 0, +3084, 3680, 0, +3323, 3812, 0, +3521, 3944, 0, +3697, 4076, 0, +3859, 4095, 0, +0, 2738, 3019, +0, 2739, 3019, +0, 2740, 3019, +0, 2741, 3019, +0, 2743, 3019, +0, 2745, 3019, +0, 2748, 3018, +0, 2752, 3018, +0, 2756, 3018, +0, 2762, 3018, +0, 2769, 3018, +0, 2779, 3018, +0, 2792, 3018, +0, 2808, 3018, +0, 2830, 3018, +0, 2857, 3018, +0, 2890, 3018, +0, 2932, 3018, +0, 2982, 3018, +0, 3018, 2993, +0, 3018, 2902, +0, 3018, 2740, +0, 3018, 2358, +0, 3151, 0, +0, 3283, 0, +2044, 3415, 0, +2758, 3548, 0, +3086, 3680, 0, +3324, 3812, 0, +3522, 3944, 0, +3697, 4076, 0, +3860, 4095, 0, +0, 2734, 3019, +0, 2735, 3019, +0, 2735, 3019, +0, 2737, 3019, +0, 2738, 3019, +0, 2741, 3019, +0, 2744, 3018, +0, 2747, 3018, +0, 2752, 3018, +0, 2758, 3018, +0, 2766, 3018, +0, 2776, 3018, +0, 2789, 3018, +0, 2805, 3018, +0, 2827, 3018, +0, 2854, 3018, +0, 2888, 3018, +0, 2930, 3018, +0, 2980, 3018, +0, 3018, 2995, +0, 3018, 2903, +0, 3018, 2742, +0, 3018, 2362, +0, 3151, 0, +0, 3283, 0, +2068, 3415, 0, +2763, 3548, 0, +3089, 3680, 0, +3326, 3812, 0, +3523, 3944, 0, +3698, 4076, 0, +3860, 4095, 0, +0, 2728, 3019, +0, 2729, 3019, +0, 2729, 3019, +0, 2731, 3019, +0, 2732, 3019, +0, 2735, 3019, +0, 2738, 3018, +0, 2742, 3018, +0, 2747, 3018, +0, 2754, 3017, +0, 2761, 3017, +0, 2771, 3017, +0, 2784, 3017, +0, 2801, 3017, +0, 2823, 3017, +0, 2850, 3017, +0, 2885, 3017, +0, 2927, 3017, +0, 2977, 3017, +0, 3017, 2996, +0, 3017, 2905, +0, 3017, 2745, +0, 3017, 2369, +0, 3150, 0, +0, 3282, 0, +2098, 3415, 0, +2770, 3547, 0, +3092, 3680, 0, +3328, 3812, 0, +3524, 3944, 0, +3699, 4076, 0, +3861, 4095, 0, +0, 2720, 3019, +0, 2720, 3019, +0, 2721, 3019, +0, 2723, 3019, +0, 2724, 3019, +0, 2727, 3019, +0, 2730, 3018, +0, 2734, 3018, +0, 2739, 3018, +0, 2746, 3017, +0, 2755, 3016, +0, 2765, 3016, +0, 2778, 3016, +0, 2796, 3016, +0, 2817, 3016, +0, 2845, 3016, +0, 2880, 3016, +0, 2922, 3016, +0, 2974, 3016, +0, 3016, 2998, +0, 3016, 2907, +0, 3016, 2749, +0, 3016, 2377, +0, 3150, 0, +0, 3282, 0, +2135, 3414, 0, +2778, 3547, 0, +3096, 3679, 0, +3330, 3812, 0, +3526, 3944, 0, +3700, 4076, 0, +3862, 4095, 0, +0, 2708, 3019, +0, 2709, 3019, +0, 2710, 3019, +0, 2712, 3019, +0, 2713, 3019, +0, 2716, 3019, +0, 2719, 3018, +0, 2723, 3018, +0, 2728, 3018, +0, 2735, 3017, +0, 2745, 3016, +0, 2757, 3015, +0, 2770, 3015, +0, 2788, 3015, +0, 2810, 3015, +0, 2838, 3015, +0, 2873, 3015, +0, 2916, 3015, +0, 2968, 3015, +0, 3015, 3001, +0, 3015, 2911, +0, 3015, 2753, +0, 3015, 2387, +0, 3149, 0, +0, 3281, 0, +2180, 3414, 0, +2790, 3547, 0, +3102, 3679, 0, +3333, 3812, 0, +3528, 3944, 0, +3701, 4076, 0, +3863, 4095, 0, +0, 2693, 3019, +0, 2694, 3019, +0, 2695, 3019, +0, 2696, 3019, +0, 2698, 3019, +0, 2701, 3019, +0, 2703, 3018, +0, 2708, 3018, +0, 2714, 3018, +0, 2721, 3017, +0, 2731, 3016, +0, 2743, 3015, +0, 2759, 3014, +0, 2777, 3014, +0, 2800, 3014, +0, 2829, 3014, +0, 2865, 3014, +0, 2908, 3014, +0, 2961, 3014, +0, 3014, 3004, +0, 3014, 2915, +0, 3014, 2759, +0, 3014, 2401, +0, 3148, 0, +0, 3280, 0, +2234, 3414, 0, +2804, 3546, 0, +3110, 3679, 0, +3338, 3811, 0, +3531, 3944, 0, +3703, 4076, 0, +3864, 4095, 0, +0, 2672, 3019, +0, 2672, 3019, +0, 2673, 3019, +0, 2675, 3019, +0, 2677, 3019, +0, 2679, 3019, +0, 2683, 3018, +0, 2687, 3018, +0, 2693, 3018, +0, 2701, 3017, +0, 2711, 3016, +0, 2724, 3015, +0, 2741, 3014, +0, 2763, 3012, +0, 2786, 3012, +0, 2816, 3012, +0, 2853, 3012, +0, 2898, 3012, +0, 2952, 3012, +0, 3012, 3009, +0, 3012, 2921, +0, 3012, 2767, +0, 3012, 2419, +0, 3146, 0, +0, 3280, 0, +2298, 3413, 0, +2824, 3546, 0, +3119, 3678, 0, +3344, 3811, 0, +3535, 3943, 0, +3706, 4076, 0, +3866, 4095, 0, +0, 2641, 3019, +0, 2642, 3019, +0, 2643, 3019, +0, 2645, 3019, +0, 2647, 3019, +0, 2649, 3019, +0, 2653, 3018, +0, 2658, 3018, +0, 2664, 3018, +0, 2672, 3017, +0, 2683, 3016, +0, 2697, 3015, +0, 2715, 3014, +0, 2738, 3012, +0, 2767, 3010, +0, 2798, 3010, +0, 2836, 3010, +0, 2883, 3010, +0, 2939, 3010, +0, 3004, 3010, +0, 3010, 2928, +0, 3010, 2778, +0, 3010, 2441, +0, 3144, 0, +0, 3278, 0, +2371, 3412, 0, +2848, 3545, 0, +3132, 3678, 0, +3352, 3810, 0, +3540, 3943, 0, +3710, 4075, 0, +3868, 4095, 0, +0, 2597, 3019, +0, 2598, 3019, +0, 2599, 3019, +0, 2601, 3019, +0, 2603, 3019, +0, 2606, 3019, +0, 2610, 3018, +0, 2615, 3018, +0, 2622, 3018, +0, 2631, 3017, +0, 2643, 3016, +0, 2658, 3015, +0, 2678, 3014, +0, 2703, 3012, +0, 2734, 3010, +0, 2773, 3006, +0, 2813, 3006, +0, 2862, 3006, +0, 2920, 3006, +0, 2988, 3006, +0, 3006, 2939, +0, 3006, 2792, +0, 3006, 2470, +0, 3142, 0, +0, 3276, 0, +2453, 3410, 0, +2879, 3544, 0, +3149, 3677, 0, +3362, 3810, 0, +3547, 3943, 0, +3714, 4075, 0, +3872, 4095, 0, +0, 2530, 3019, +0, 2531, 3019, +0, 2533, 3019, +0, 2535, 3019, +0, 2537, 3019, +0, 2541, 3019, +0, 2545, 3018, +0, 2551, 3018, +0, 2559, 3018, +0, 2570, 3017, +0, 2583, 3016, +0, 2600, 3015, +0, 2623, 3014, +0, 2651, 3012, +0, 2686, 3010, +0, 2729, 3006, +0, 2781, 3002, +0, 2833, 3002, +0, 2895, 3002, +0, 2966, 3002, +0, 3002, 2952, +0, 3002, 2810, +0, 3002, 2505, +0, 3138, 0, +1202, 3274, 0, +2545, 3408, 0, +2917, 3543, 0, +3170, 3676, 0, +3376, 3809, 0, +3556, 3942, 0, +3721, 4075, 0, +3876, 4095, 0, +0, 2422, 3019, +0, 2424, 3019, +0, 2426, 3019, +0, 2428, 3019, +0, 2431, 3019, +0, 2435, 3019, +0, 2441, 3018, +0, 2449, 3018, +0, 2459, 3018, +0, 2471, 3017, +0, 2488, 3016, +0, 2510, 3015, +0, 2536, 3014, +0, 2570, 3012, +0, 2612, 3010, +0, 2662, 3006, +0, 2722, 3002, +1006, 2791, 2995, +1006, 2858, 2995, +1006, 2935, 2995, +1006, 2995, 2968, +1006, 2995, 2833, +1006, 2995, 2549, +0, 3134, 1211, +1990, 3270, 0, +2643, 3406, 0, +2963, 3541, 0, +3197, 3675, 0, +3393, 3808, 0, +3568, 3941, 0, +3729, 4074, 0, +3882, 4095, 0, +0, 2220, 3019, +0, 2222, 3019, +0, 2225, 3019, +0, 2229, 3019, +0, 2234, 3019, +0, 2241, 3019, +0, 2249, 3018, +0, 2261, 3018, +0, 2276, 3018, +0, 2294, 3017, +0, 2319, 3016, +0, 2350, 3015, +0, 2388, 3014, +0, 2434, 3012, +0, 2489, 3010, +0, 2554, 3006, +0, 2628, 3002, +1006, 2712, 2995, +1930, 2804, 2987, +1930, 2890, 2987, +1930, 2984, 2987, +1930, 2987, 2862, +1930, 2987, 2602, +1137, 3128, 1758, +2327, 3266, 0, +2749, 3402, 0, +3018, 3538, 0, +3231, 3673, 0, +3415, 3807, 0, +3583, 3940, 0, +3740, 4073, 0, +3890, 4095, 0, +0, 1594, 3019, +0, 1602, 3019, +0, 1613, 3019, +0, 1628, 3019, +0, 1646, 3019, +0, 1670, 3019, +0, 1700, 3018, +0, 1737, 3018, +0, 1782, 3018, +0, 1837, 3017, +0, 1900, 3016, +0, 1974, 3015, +0, 2056, 3014, +0, 2148, 3012, +0, 2247, 3010, +0, 2352, 3006, +0, 2463, 3002, +1006, 2579, 2995, +1930, 2699, 2987, +2280, 2821, 2975, +2280, 2929, 2975, +2280, 2975, 2898, +2280, 2975, 2664, +2064, 3119, 2061, +2569, 3259, 1272, +2860, 3398, 0, +3083, 3535, 0, +3273, 3670, 0, +3443, 3805, 0, +3603, 3939, 0, +3754, 4072, 0, +3900, 4095, 0, +0, 0, 3019, +0, 0, 3019, +0, 0, 3019, +0, 0, 3019, +0, 0, 3019, +0, 0, 3019, +0, 0, 3018, +0, 0, 3018, +0, 0, 3018, +0, 0, 3017, +0, 0, 3016, +0, 0, 3015, +0, 0, 3014, +0, 0, 3012, +0, 922, 3010, +0, 1723, 3006, +0, 2062, 3002, +1006, 2303, 2995, +1930, 2503, 2987, +2280, 2680, 2975, +2526, 2843, 2959, +2526, 2959, 2942, +2526, 2959, 2735, +2511, 3108, 2412, +2768, 3251, 2194, +2976, 3392, 1406, +3157, 3530, 0, +3323, 3667, 0, +3479, 3802, 0, +3628, 3937, 0, +3772, 4071, 0, +3913, 4095, 0, +0, 0, 3019, +0, 0, 3019, +0, 0, 3019, +0, 0, 3019, +0, 0, 3019, +0, 0, 3019, +0, 0, 3018, +0, 0, 3018, +0, 0, 3018, +0, 0, 3017, +0, 0, 3016, +0, 0, 3015, +0, 0, 3014, +0, 0, 3012, +0, 0, 3010, +0, 0, 3006, +1109, 0, 3002, +1635, 1006, 2995, +1930, 1930, 2987, +2280, 2377, 2975, +2526, 2654, 2959, +2728, 2871, 2937, +2728, 2937, 2816, +2787, 3092, 2658, +2945, 3239, 2544, +3095, 3383, 2326, +3241, 3524, 1536, +3382, 3662, 0, +3522, 3799, 0, +3659, 3934, 0, +3795, 4069, 0, +3930, 4095, 0, +2346, 0, 3019, +2346, 0, 3019, +2347, 0, 3019, +2348, 0, 3019, +2350, 0, 3019, +2352, 0, 3019, +2354, 0, 3018, +2358, 0, 3018, +2362, 0, 3018, +2369, 0, 3017, +2377, 0, 3016, +2387, 0, 3015, +2401, 0, 3014, +2419, 0, 3012, +2441, 0, 3010, +2470, 0, 3006, +2505, 0, 3002, +2549, 1006, 2995, +2602, 1930, 2987, +2664, 2280, 2975, +2735, 2526, 2959, +2816, 2728, 2937, +2906, 2906, 2906, +3003, 3069, 2860, +3107, 3223, 2790, +3218, 3372, 2676, +3333, 3515, 2457, +3452, 3656, 1663, +3574, 3794, 0, +3698, 3931, 0, +3824, 4066, 0, +3952, 4095, 0, +2868, 0, 3152, +2868, 0, 3152, +2869, 0, 3152, +2869, 0, 3151, +2869, 0, 3151, +2870, 0, 3151, +2871, 0, 3151, +2872, 0, 3151, +2873, 0, 3151, +2875, 0, 3150, +2878, 0, 3150, +2881, 0, 3149, +2886, 0, 3148, +2892, 0, 3146, +2901, 0, 3144, +2911, 0, 3142, +2925, 0, 3138, +2943, 0, 3134, +2965, 1137, 3128, +2995, 2061, 3119, +3031, 2412, 3108, +3074, 2658, 3092, +3069, 2860, 3003, +3069, 2948, 2860, +3223, 3206, 2790, +3325, 3372, 2676, +3418, 3515, 2457, +3519, 3656, 1663, +3626, 3794, 0, +3738, 3931, 0, +3855, 4066, 0, +3976, 4095, 0, +3162, 0, 3284, +3162, 0, 3283, +3163, 0, 3283, +3163, 0, 3283, +3163, 0, 3283, +3163, 0, 3283, +3164, 0, 3283, +3164, 0, 3283, +3165, 0, 3283, +3166, 0, 3282, +3168, 0, 3282, +3169, 0, 3281, +3172, 0, 3280, +3175, 0, 3280, +3180, 0, 3278, +3185, 0, 3276, +3193, 0, 3274, +3203, 0, 3270, +3216, 0, 3266, +3233, 1272, 3259, +3251, 2194, 3248, +3239, 2544, 3193, +3223, 2790, 3107, +3223, 2790, 2918, +3223, 2999, 2790, +3372, 3294, 2676, +3512, 3515, 2457, +3595, 3656, 1663, +3687, 3794, 0, +3787, 3931, 0, +3893, 4066, 0, +4005, 4095, 0, +3387, 0, 3416, +3387, 0, 3416, +3387, 0, 3416, +3387, 0, 3416, +3387, 0, 3416, +3387, 0, 3416, +3387, 0, 3415, +3388, 0, 3415, +3388, 0, 3415, +3389, 0, 3415, +3390, 0, 3414, +3391, 0, 3414, +3393, 0, 3414, +3395, 0, 3413, +3397, 0, 3412, +3401, 0, 3410, +3406, 0, 3408, +3406, 0, 3400, +3402, 0, 3384, +3398, 0, 3362, +3392, 1406, 3331, +3383, 2326, 3286, +3372, 2676, 3218, +3372, 2676, 3077, +3372, 2676, 2774, +3372, 3060, 2676, +3515, 3391, 2457, +3656, 3629, 1663, +3759, 3794, 0, +3845, 3931, 0, +3940, 4066, 0, +4042, 4095, 0, +3548, 0, 3516, +3548, 0, 3516, +3548, 0, 3516, +3548, 0, 3516, +3548, 0, 3516, +3548, 0, 3516, +3548, 0, 3515, +3548, 0, 3515, +3548, 0, 3514, +3547, 0, 3513, +3547, 0, 3512, +3547, 0, 3511, +3546, 0, 3509, +3546, 0, 3506, +3545, 0, 3502, +3544, 0, 3497, +3543, 0, 3490, +3541, 0, 3480, +3538, 0, 3467, +3535, 0, 3449, +3530, 0, 3423, +3524, 1536, 3387, +3515, 2457, 3333, +3515, 2457, 3227, +3515, 2457, 3032, +3515, 2457, 2459, +3515, 3130, 2457, +3656, 3494, 1663, +3794, 3745, 0, +3913, 3931, 0, +3995, 4066, 0, +4087, 4095, 0, +3680, 0, 3599, +3680, 0, 3599, +3680, 0, 3599, +3680, 0, 3599, +3680, 0, 3599, +3680, 0, 3599, +3680, 0, 3598, +3680, 0, 3598, +3680, 0, 3597, +3680, 0, 3597, +3679, 0, 3596, +3679, 0, 3595, +3679, 0, 3593, +3678, 0, 3590, +3678, 0, 3587, +3677, 0, 3583, +3676, 0, 3577, +3675, 0, 3569, +3673, 0, 3558, +3670, 0, 3543, +3667, 0, 3523, +3662, 0, 3494, +3656, 1663, 3452, +3656, 1663, 3373, +3656, 1663, 3240, +3656, 1663, 2965, +3656, 2289, 1663, +3656, 3210, 1663, +3794, 3603, 0, +3931, 3863, 0, +4060, 4066, 0, +4095, 4095, 0, +3812, 0, 3691, +3812, 0, 3691, +3812, 0, 3690, +3812, 0, 3690, +3812, 0, 3690, +3812, 0, 3690, +3812, 0, 3690, +3812, 0, 3690, +3812, 0, 3689, +3812, 0, 3689, +3812, 0, 3688, +3812, 0, 3687, +3811, 0, 3685, +3811, 0, 3683, +3810, 0, 3680, +3810, 0, 3677, +3809, 0, 3672, +3808, 0, 3666, +3807, 0, 3657, +3805, 0, 3646, +3802, 0, 3629, +3799, 0, 3606, +3794, 0, 3574, +3794, 0, 3515, +3794, 0, 3421, +3794, 0, 3256, +3794, 0, 2856, +3794, 1884, 0, +3794, 3298, 0, +3931, 3717, 0, +4066, 3985, 0, +4095, 4095, 0, +3944, 0, 3790, +3944, 0, 3790, +3944, 0, 3790, +3944, 0, 3790, +3944, 0, 3789, +3944, 0, 3789, +3944, 0, 3789, +3944, 0, 3789, +3944, 0, 3788, +3944, 0, 3788, +3944, 0, 3787, +3944, 0, 3786, +3944, 0, 3785, +3943, 0, 3784, +3943, 0, 3781, +3943, 0, 3779, +3942, 0, 3775, +3941, 0, 3770, +3940, 0, 3763, +3939, 0, 3754, +3937, 0, 3741, +3934, 0, 3723, +3931, 0, 3698, +3931, 0, 3654, +3931, 0, 3587, +3931, 0, 3479, +3931, 0, 3277, +3931, 0, 2650, +3931, 0, 0, +3931, 3395, 0, +4066, 3835, 0, +4095, 4095, 0, +4076, 0, 3895, +4076, 0, 3895, +4076, 0, 3895, +4076, 0, 3895, +4076, 0, 3895, +4076, 0, 3895, +4076, 0, 3895, +4076, 0, 3895, +4076, 0, 3894, +4076, 0, 3894, +4076, 0, 3893, +4076, 0, 3892, +4076, 0, 3891, +4076, 0, 3890, +4075, 0, 3889, +4075, 0, 3887, +4075, 0, 3884, +4074, 0, 3880, +4073, 0, 3874, +4072, 0, 3867, +4071, 0, 3857, +4069, 0, 3843, +4066, 0, 3824, +4066, 0, 3791, +4066, 0, 3743, +4066, 0, 3669, +4066, 0, 3546, +4066, 0, 3303, +4066, 0, 1985, +4066, 0, 0, +4066, 3498, 0, +4095, 3957, 0, +4095, 0, 4007, +4095, 0, 4006, +4095, 0, 4006, +4095, 0, 4006, +4095, 0, 4006, +4095, 0, 4006, +4095, 0, 4006, +4095, 0, 4006, +4095, 0, 4006, +4095, 0, 4005, +4095, 0, 4005, +4095, 0, 4005, +4095, 0, 4004, +4095, 0, 4003, +4095, 0, 4002, +4095, 0, 4000, +4095, 0, 3998, +4095, 0, 3994, +4095, 0, 3990, +4095, 0, 3984, +4095, 0, 3977, +4095, 0, 3966, +4095, 0, 3952, +4095, 0, 3927, +4095, 0, 3892, +4095, 0, 3840, +4095, 0, 3759, +4095, 0, 3623, +4095, 0, 3337, +4095, 0, 0, +4095, 0, 0, +4095, 3608, 0, +0, 2882, 3152, +0, 2883, 3152, +0, 2883, 3152, +0, 2884, 3152, +0, 2885, 3152, +0, 2886, 3152, +0, 2888, 3152, +0, 2890, 3152, +0, 2893, 3152, +0, 2898, 3152, +0, 2903, 3152, +0, 2911, 3152, +0, 2920, 3152, +0, 2933, 3152, +0, 2949, 3152, +0, 2970, 3152, +0, 2996, 3152, +0, 3030, 3152, +0, 3071, 3152, +0, 3120, 3152, +0, 3152, 3123, +0, 3152, 3031, +0, 3152, 2868, +0, 3152, 2478, +0, 3284, 0, +0, 3416, 0, +2104, 3548, 0, +2876, 3680, 0, +3211, 3812, 0, +3452, 3944, 0, +3651, 4076, 0, +3828, 4095, 0, +0, 2881, 3152, +0, 2882, 3152, +0, 2883, 3152, +0, 2883, 3152, +0, 2885, 3152, +0, 2886, 3152, +0, 2888, 3152, +0, 2890, 3152, +0, 2893, 3152, +0, 2897, 3152, +0, 2903, 3152, +0, 2910, 3152, +0, 2920, 3152, +0, 2932, 3152, +0, 2949, 3152, +0, 2970, 3152, +0, 2996, 3152, +0, 3029, 3152, +0, 3070, 3152, +0, 3120, 3152, +0, 3152, 3123, +0, 3152, 3031, +0, 3152, 2868, +0, 3152, 2478, +0, 3283, 0, +0, 3416, 0, +2107, 3548, 0, +2877, 3680, 0, +3212, 3812, 0, +3452, 3944, 0, +3651, 4076, 0, +3828, 4095, 0, +0, 2881, 3152, +0, 2881, 3152, +0, 2882, 3152, +0, 2883, 3152, +0, 2884, 3152, +0, 2885, 3152, +0, 2887, 3152, +0, 2890, 3152, +0, 2893, 3152, +0, 2897, 3152, +0, 2903, 3152, +0, 2910, 3152, +0, 2919, 3152, +0, 2932, 3152, +0, 2948, 3152, +0, 2969, 3152, +0, 2996, 3152, +0, 3029, 3152, +0, 3070, 3152, +0, 3120, 3152, +0, 3152, 3123, +0, 3152, 3031, +0, 3152, 2869, +0, 3152, 2479, +0, 3283, 0, +0, 3416, 0, +2111, 3548, 0, +2877, 3680, 0, +3212, 3812, 0, +3453, 3944, 0, +3651, 4076, 0, +3828, 4095, 0, +0, 2880, 3152, +0, 2881, 3152, +0, 2881, 3152, +0, 2882, 3151, +0, 2883, 3151, +0, 2885, 3151, +0, 2886, 3151, +0, 2889, 3151, +0, 2892, 3151, +0, 2896, 3151, +0, 2902, 3151, +0, 2909, 3151, +0, 2919, 3151, +0, 2932, 3151, +0, 2948, 3151, +0, 2969, 3151, +0, 2995, 3151, +0, 3029, 3151, +0, 3070, 3151, +0, 3119, 3151, +0, 3151, 3123, +0, 3151, 3031, +0, 3151, 2869, +0, 3151, 2480, +0, 3283, 0, +0, 3416, 0, +2115, 3548, 0, +2878, 3680, 0, +3213, 3812, 0, +3453, 3944, 0, +3652, 4076, 0, +3828, 4095, 0, +0, 2879, 3152, +0, 2880, 3152, +0, 2880, 3152, +0, 2881, 3151, +0, 2883, 3151, +0, 2884, 3151, +0, 2886, 3151, +0, 2888, 3151, +0, 2891, 3151, +0, 2895, 3151, +0, 2901, 3151, +0, 2908, 3151, +0, 2918, 3151, +0, 2931, 3151, +0, 2947, 3151, +0, 2968, 3151, +0, 2995, 3151, +0, 3028, 3151, +0, 3069, 3151, +0, 3119, 3151, +0, 3151, 3123, +0, 3151, 3031, +0, 3151, 2869, +0, 3151, 2481, +0, 3283, 0, +0, 3416, 0, +2122, 3548, 0, +2879, 3680, 0, +3213, 3812, 0, +3453, 3944, 0, +3652, 4076, 0, +3828, 4095, 0, +0, 2878, 3152, +0, 2878, 3152, +0, 2879, 3152, +0, 2880, 3151, +0, 2881, 3151, +0, 2883, 3151, +0, 2885, 3151, +0, 2887, 3151, +0, 2890, 3151, +0, 2895, 3151, +0, 2900, 3151, +0, 2907, 3151, +0, 2917, 3151, +0, 2930, 3151, +0, 2946, 3151, +0, 2967, 3151, +0, 2994, 3151, +0, 3027, 3151, +0, 3068, 3151, +0, 3118, 3151, +0, 3151, 3124, +0, 3151, 3032, +0, 3151, 2870, +0, 3151, 2482, +0, 3283, 0, +0, 3416, 0, +2130, 3548, 0, +2881, 3680, 0, +3214, 3812, 0, +3454, 3944, 0, +3652, 4076, 0, +3829, 4095, 0, +0, 2876, 3152, +0, 2877, 3152, +0, 2877, 3152, +0, 2878, 3151, +0, 2879, 3151, +0, 2881, 3151, +0, 2883, 3151, +0, 2885, 3151, +0, 2889, 3151, +0, 2893, 3151, +0, 2898, 3151, +0, 2906, 3151, +0, 2916, 3151, +0, 2928, 3151, +0, 2945, 3151, +0, 2966, 3151, +0, 2993, 3151, +0, 3026, 3151, +0, 3067, 3151, +0, 3117, 3151, +0, 3151, 3124, +0, 3151, 3032, +0, 3151, 2871, +0, 3151, 2484, +0, 3283, 0, +0, 3415, 0, +2141, 3548, 0, +2883, 3680, 0, +3215, 3812, 0, +3454, 3944, 0, +3653, 4076, 0, +3829, 4095, 0, +0, 2873, 3152, +0, 2874, 3152, +0, 2875, 3152, +0, 2876, 3151, +0, 2877, 3151, +0, 2879, 3151, +0, 2881, 3151, +0, 2883, 3151, +0, 2887, 3151, +0, 2891, 3151, +0, 2896, 3151, +0, 2904, 3151, +0, 2914, 3151, +0, 2927, 3151, +0, 2943, 3151, +0, 2964, 3151, +0, 2991, 3151, +0, 3025, 3151, +0, 3066, 3151, +0, 3116, 3151, +0, 3151, 3125, +0, 3151, 3033, +0, 3151, 2872, +0, 3151, 2487, +0, 3283, 0, +0, 3415, 0, +2156, 3548, 0, +2886, 3680, 0, +3216, 3812, 0, +3455, 3944, 0, +3653, 4076, 0, +3829, 4095, 0, +0, 2870, 3152, +0, 2871, 3152, +0, 2871, 3152, +0, 2872, 3151, +0, 2873, 3151, +0, 2875, 3151, +0, 2877, 3151, +0, 2880, 3151, +0, 2884, 3151, +0, 2888, 3151, +0, 2894, 3151, +0, 2902, 3151, +0, 2911, 3151, +0, 2924, 3151, +0, 2941, 3151, +0, 2962, 3151, +0, 2989, 3151, +0, 3023, 3151, +0, 3064, 3151, +0, 3115, 3151, +0, 3151, 3126, +0, 3151, 3034, +0, 3151, 2873, +0, 3151, 2490, +0, 3283, 0, +0, 3415, 0, +2174, 3548, 0, +2890, 3680, 0, +3218, 3812, 0, +3456, 3944, 0, +3654, 4076, 0, +3830, 4095, 0, +0, 2866, 3152, +0, 2866, 3152, +0, 2867, 3152, +0, 2868, 3151, +0, 2869, 3151, +0, 2871, 3151, +0, 2873, 3151, +0, 2876, 3151, +0, 2880, 3151, +0, 2885, 3150, +0, 2891, 3150, +0, 2898, 3150, +0, 2908, 3150, +0, 2921, 3150, +0, 2938, 3150, +0, 2959, 3150, +0, 2986, 3150, +0, 3020, 3150, +0, 3062, 3150, +0, 3112, 3150, +0, 3150, 3127, +0, 3150, 3036, +0, 3150, 2875, +0, 3150, 2495, +0, 3282, 0, +0, 3415, 0, +2198, 3547, 0, +2895, 3680, 0, +3221, 3812, 0, +3458, 3944, 0, +3655, 4076, 0, +3830, 4095, 0, +0, 2860, 3152, +0, 2860, 3152, +0, 2861, 3152, +0, 2862, 3151, +0, 2863, 3151, +0, 2865, 3151, +0, 2867, 3151, +0, 2870, 3151, +0, 2874, 3151, +0, 2879, 3150, +0, 2886, 3150, +0, 2894, 3150, +0, 2904, 3150, +0, 2917, 3150, +0, 2933, 3150, +0, 2955, 3150, +0, 2982, 3150, +0, 3017, 3150, +0, 3059, 3150, +0, 3110, 3150, +0, 3150, 3128, +0, 3150, 3038, +0, 3150, 2878, +0, 3150, 2501, +0, 3282, 0, +0, 3414, 0, +2228, 3547, 0, +2901, 3679, 0, +3224, 3812, 0, +3459, 3944, 0, +3656, 4076, 0, +3831, 4095, 0, +0, 2851, 3152, +0, 2852, 3152, +0, 2853, 3152, +0, 2854, 3151, +0, 2855, 3151, +0, 2857, 3151, +0, 2859, 3151, +0, 2862, 3151, +0, 2866, 3151, +0, 2871, 3150, +0, 2878, 3150, +0, 2887, 3149, +0, 2898, 3149, +0, 2911, 3149, +0, 2928, 3149, +0, 2950, 3149, +0, 2977, 3149, +0, 3012, 3149, +0, 3055, 3149, +0, 3106, 3149, +0, 3149, 3131, +0, 3149, 3040, +0, 3149, 2881, +0, 3149, 2509, +0, 3281, 0, +0, 3414, 0, +2265, 3547, 0, +2910, 3679, 0, +3228, 3812, 0, +3462, 3944, 0, +3658, 4076, 0, +3832, 4095, 0, +0, 2840, 3152, +0, 2841, 3152, +0, 2842, 3152, +0, 2842, 3151, +0, 2844, 3151, +0, 2845, 3151, +0, 2848, 3151, +0, 2851, 3151, +0, 2855, 3151, +0, 2860, 3150, +0, 2868, 3150, +0, 2877, 3149, +0, 2889, 3148, +0, 2903, 3148, +0, 2920, 3148, +0, 2942, 3148, +0, 2970, 3148, +0, 3005, 3148, +0, 3049, 3148, +0, 3100, 3148, +0, 3148, 3133, +0, 3148, 3043, +0, 3148, 2886, +0, 3148, 2520, +0, 3280, 0, +0, 3414, 0, +2311, 3546, 0, +2922, 3679, 0, +3234, 3811, 0, +3466, 3944, 0, +3660, 4076, 0, +3834, 4095, 0, +0, 2825, 3152, +0, 2825, 3152, +0, 2826, 3152, +0, 2827, 3151, +0, 2829, 3151, +0, 2830, 3151, +0, 2833, 3151, +0, 2836, 3151, +0, 2840, 3151, +0, 2846, 3150, +0, 2853, 3150, +0, 2863, 3149, +0, 2875, 3148, +0, 2892, 3146, +0, 2910, 3146, +0, 2932, 3146, +0, 2961, 3146, +0, 2997, 3146, +0, 3041, 3146, +0, 3093, 3146, +0, 3146, 3137, +0, 3146, 3047, +0, 3146, 2892, +0, 3146, 2533, +0, 3280, 0, +0, 3413, 0, +2365, 3546, 0, +2936, 3678, 0, +3241, 3811, 0, +3470, 3943, 0, +3663, 4076, 0, +3836, 4095, 0, +0, 2803, 3152, +0, 2804, 3152, +0, 2805, 3152, +0, 2806, 3151, +0, 2807, 3151, +0, 2809, 3151, +0, 2812, 3151, +0, 2815, 3151, +0, 2819, 3151, +0, 2825, 3150, +0, 2833, 3150, +0, 2843, 3149, +0, 2856, 3148, +0, 2873, 3146, +0, 2895, 3144, +0, 2919, 3144, +0, 2948, 3144, +0, 2985, 3144, +0, 3030, 3144, +0, 3084, 3144, +0, 3144, 3141, +0, 3144, 3053, +0, 3144, 2901, +0, 3144, 2551, +0, 3278, 0, +0, 3412, 0, +2429, 3545, 0, +2955, 3678, 0, +3251, 3810, 0, +3476, 3943, 0, +3667, 4075, 0, +3838, 4095, 0, +0, 2773, 3152, +0, 2773, 3152, +0, 2774, 3152, +0, 2775, 3151, +0, 2777, 3151, +0, 2779, 3151, +0, 2782, 3151, +0, 2785, 3151, +0, 2790, 3151, +0, 2796, 3150, +0, 2804, 3150, +0, 2815, 3149, +0, 2829, 3148, +0, 2847, 3146, +0, 2870, 3144, +0, 2900, 3142, +0, 2931, 3142, +0, 2969, 3142, +0, 3015, 3142, +0, 3071, 3142, +0, 3136, 3142, +0, 3142, 3061, +0, 3142, 2911, +0, 3142, 2573, +0, 3276, 0, +0, 3410, 0, +2502, 3544, 0, +2980, 3677, 0, +3264, 3810, 0, +3484, 3943, 0, +3672, 4075, 0, +3842, 4095, 0, +0, 2729, 3152, +0, 2729, 3152, +0, 2730, 3152, +0, 2732, 3151, +0, 2733, 3151, +0, 2735, 3151, +0, 2738, 3151, +0, 2742, 3151, +0, 2747, 3151, +0, 2754, 3150, +0, 2763, 3150, +0, 2775, 3149, +0, 2790, 3148, +0, 2810, 3146, +0, 2835, 3144, +0, 2867, 3142, +0, 2906, 3138, +0, 2946, 3138, +0, 2995, 3138, +0, 3053, 3138, +0, 3120, 3138, +0, 3138, 3071, +0, 3138, 2925, +0, 3138, 2602, +0, 3274, 0, +0, 3408, 0, +2585, 3543, 0, +3010, 3676, 0, +3281, 3809, 0, +3494, 3942, 0, +3679, 4075, 0, +3847, 4095, 0, +0, 2662, 3152, +0, 2663, 3152, +0, 2664, 3152, +0, 2665, 3151, +0, 2667, 3151, +0, 2670, 3151, +0, 2673, 3151, +0, 2678, 3151, +0, 2684, 3151, +0, 2691, 3150, +0, 2702, 3150, +0, 2715, 3149, +0, 2733, 3148, +0, 2755, 3146, +0, 2783, 3144, +0, 2818, 3142, +0, 2861, 3138, +0, 2913, 3134, +0, 2965, 3134, +0, 3027, 3134, +0, 3098, 3134, +0, 3134, 3084, +0, 3134, 2943, +0, 3134, 2638, +0, 3270, 0, +1325, 3406, 0, +2676, 3541, 0, +3048, 3675, 0, +3302, 3808, 0, +3507, 3941, 0, +3688, 4074, 0, +3853, 4095, 0, +0, 2554, 3152, +0, 2555, 3152, +0, 2556, 3152, +0, 2558, 3151, +0, 2560, 3151, +0, 2564, 3151, +0, 2568, 3151, +0, 2573, 3151, +0, 2581, 3151, +0, 2591, 3150, +0, 2604, 3150, +0, 2620, 3149, +0, 2642, 3148, +0, 2669, 3146, +0, 2703, 3144, +0, 2744, 3142, +0, 2795, 3138, +0, 2854, 3134, +1137, 2923, 3128, +1137, 2991, 3128, +1137, 3067, 3128, +1137, 3128, 3101, +1137, 3128, 2965, +1137, 3128, 2681, +0, 3266, 1375, +2121, 3402, 0, +2775, 3538, 0, +3095, 3673, 0, +3329, 3807, 0, +3525, 3940, 0, +3700, 4073, 0, +3861, 4095, 0, +0, 2352, 3152, +0, 2353, 3152, +0, 2355, 3152, +0, 2358, 3151, +0, 2362, 3151, +0, 2367, 3151, +0, 2373, 3151, +0, 2382, 3151, +0, 2394, 3151, +0, 2408, 3150, +0, 2427, 3150, +0, 2452, 3149, +0, 2482, 3148, +0, 2521, 3146, +0, 2566, 3144, +0, 2622, 3142, +0, 2687, 3138, +0, 2761, 3134, +1137, 2845, 3128, +2061, 2936, 3119, +2061, 3022, 3119, +2061, 3116, 3119, +2061, 3119, 2995, +2061, 3119, 2734, +1272, 3259, 1899, +2458, 3398, 0, +2881, 3535, 0, +3150, 3670, 0, +3363, 3805, 0, +3547, 3939, 0, +3715, 4072, 0, +3872, 4095, 0, +0, 1720, 3152, +0, 1726, 3152, +0, 1735, 3152, +0, 1746, 3151, +0, 1760, 3151, +0, 1779, 3151, +0, 1802, 3151, +0, 1832, 3151, +0, 1869, 3151, +0, 1915, 3150, +0, 1969, 3150, +0, 2033, 3149, +0, 2106, 3148, +0, 2189, 3146, +0, 2280, 3144, +0, 2379, 3142, +0, 2484, 3138, +0, 2596, 3134, +1137, 2712, 3128, +2061, 2831, 3119, +2412, 2954, 3108, +2412, 3061, 3108, +2412, 3108, 3031, +2412, 3108, 2796, +2194, 3251, 2195, +2701, 3392, 1406, +2992, 3530, 0, +3215, 3667, 0, +3405, 3802, 0, +3575, 3937, 0, +3735, 4071, 0, +3886, 4095, 0, +0, 0, 3152, +0, 0, 3152, +0, 0, 3152, +0, 0, 3151, +0, 0, 3151, +0, 0, 3151, +0, 0, 3151, +0, 0, 3151, +0, 0, 3151, +0, 0, 3150, +0, 0, 3150, +0, 0, 3149, +0, 0, 3148, +0, 0, 3146, +0, 0, 3144, +0, 1068, 3142, +0, 1857, 3138, +0, 2195, 3134, +1137, 2436, 3128, +2061, 2636, 3119, +2412, 2813, 3108, +2658, 2976, 3092, +2658, 3092, 3074, +2658, 3092, 2867, +2642, 3239, 2544, +2900, 3383, 2326, +3108, 3524, 1536, +3289, 3662, 0, +3455, 3799, 0, +3611, 3934, 0, +3760, 4069, 0, +3904, 4095, 0, +0, 0, 3152, +0, 0, 3152, +0, 0, 3152, +0, 0, 3151, +0, 0, 3151, +0, 0, 3151, +0, 0, 3151, +0, 0, 3151, +0, 0, 3151, +0, 0, 3150, +0, 0, 3150, +0, 0, 3149, +0, 0, 3148, +0, 0, 3146, +0, 0, 3144, +0, 0, 3142, +0, 0, 3138, +1211, 0, 3134, +1758, 1137, 3128, +2061, 2064, 3119, +2412, 2511, 3108, +2658, 2787, 3092, +2860, 3003, 3069, +2860, 3069, 2948, +2918, 3223, 2790, +3077, 3372, 2676, +3227, 3515, 2457, +3373, 3656, 1663, +3515, 3794, 0, +3654, 3931, 0, +3791, 4066, 0, +3927, 4095, 0, +2478, 0, 3152, +2478, 0, 3152, +2479, 0, 3152, +2480, 0, 3151, +2481, 0, 3151, +2482, 0, 3151, +2484, 0, 3151, +2487, 0, 3151, +2490, 0, 3151, +2495, 0, 3150, +2501, 0, 3150, +2509, 0, 3149, +2520, 0, 3148, +2533, 0, 3146, +2551, 0, 3144, +2573, 0, 3142, +2602, 0, 3138, +2638, 0, 3134, +2681, 1137, 3128, +2734, 2061, 3119, +2796, 2412, 3108, +2867, 2658, 3092, +2948, 2860, 3069, +3038, 3038, 3038, +3135, 3201, 2992, +3239, 3356, 2922, +3350, 3504, 2808, +3465, 3648, 2590, +3584, 3788, 1799, +3706, 3926, 0, +3830, 4063, 0, +3956, 4095, 0, +2999, 0, 3284, +2999, 0, 3283, +2999, 0, 3283, +2999, 0, 3283, +3000, 0, 3283, +3000, 0, 3283, +3001, 0, 3283, +3002, 0, 3283, +3003, 0, 3283, +3005, 0, 3282, +3006, 0, 3282, +3009, 0, 3281, +3013, 0, 3280, +3017, 0, 3280, +3023, 0, 3278, +3032, 0, 3276, +3042, 0, 3274, +3056, 0, 3270, +3074, 0, 3266, +3097, 1272, 3259, +3126, 2194, 3251, +3162, 2544, 3239, +3206, 2790, 3223, +3201, 2992, 3135, +3201, 3080, 2992, +3356, 3338, 2922, +3457, 3504, 2808, +3550, 3648, 2590, +3651, 3788, 1799, +3758, 3926, 0, +3870, 4063, 0, +3987, 4095, 0, +3294, 0, 3416, +3294, 0, 3416, +3294, 0, 3416, +3294, 0, 3416, +3295, 0, 3416, +3295, 0, 3416, +3295, 0, 3415, +3296, 0, 3415, +3296, 0, 3415, +3297, 0, 3415, +3298, 0, 3414, +3299, 0, 3414, +3301, 0, 3414, +3304, 0, 3413, +3307, 0, 3412, +3311, 0, 3410, +3317, 0, 3408, +3325, 0, 3406, +3335, 0, 3402, +3348, 0, 3398, +3365, 1406, 3392, +3383, 2326, 3380, +3372, 2676, 3325, +3356, 2922, 3239, +3356, 2922, 3051, +3356, 3132, 2922, +3504, 3426, 2808, +3644, 3648, 2590, +3728, 3788, 1799, +3820, 3926, 0, +3919, 4063, 0, +4025, 4095, 0, +3519, 0, 3548, +3519, 0, 3548, +3519, 0, 3548, +3519, 0, 3548, +3519, 0, 3548, +3519, 0, 3548, +3519, 0, 3548, +3520, 0, 3548, +3520, 0, 3548, +3520, 0, 3547, +3521, 0, 3547, +3522, 0, 3547, +3523, 0, 3546, +3525, 0, 3546, +3526, 0, 3545, +3529, 0, 3544, +3533, 0, 3543, +3538, 0, 3541, +3538, 0, 3532, +3535, 0, 3516, +3530, 0, 3495, +3524, 1536, 3463, +3515, 2457, 3418, +3504, 2808, 3350, +3504, 2808, 3209, +3504, 2808, 2907, +3504, 3192, 2808, +3648, 3523, 2590, +3788, 3761, 1799, +3891, 3926, 0, +3977, 4063, 0, +4072, 4095, 0, +3680, 0, 3649, +3680, 0, 3649, +3680, 0, 3649, +3680, 0, 3649, +3680, 0, 3648, +3680, 0, 3648, +3680, 0, 3648, +3680, 0, 3648, +3680, 0, 3647, +3680, 0, 3646, +3679, 0, 3646, +3679, 0, 3644, +3679, 0, 3643, +3678, 0, 3641, +3678, 0, 3638, +3677, 0, 3634, +3676, 0, 3629, +3675, 0, 3622, +3673, 0, 3612, +3670, 0, 3599, +3667, 0, 3581, +3662, 0, 3555, +3656, 1663, 3519, +3648, 2590, 3465, +3648, 2590, 3360, +3648, 2590, 3165, +3648, 2590, 2592, +3648, 3262, 2590, +3788, 3626, 1799, +3926, 3877, 0, +4045, 4063, 0, +4095, 4095, 0, +3812, 0, 3732, +3812, 0, 3731, +3812, 0, 3731, +3812, 0, 3731, +3812, 0, 3731, +3812, 0, 3731, +3812, 0, 3731, +3812, 0, 3730, +3812, 0, 3730, +3812, 0, 3729, +3812, 0, 3729, +3812, 0, 3728, +3811, 0, 3727, +3811, 0, 3725, +3810, 0, 3722, +3810, 0, 3719, +3809, 0, 3715, +3808, 0, 3709, +3807, 0, 3701, +3805, 0, 3690, +3802, 0, 3676, +3799, 0, 3655, +3794, 0, 3626, +3788, 1799, 3584, +3788, 1799, 3505, +3788, 1799, 3372, +3788, 1799, 3097, +3788, 2422, 1799, +3788, 3342, 1799, +3926, 3735, 0, +4063, 3995, 0, +4095, 4095, 0, +3944, 0, 3823, +3944, 0, 3823, +3944, 0, 3823, +3944, 0, 3822, +3944, 0, 3822, +3944, 0, 3822, +3944, 0, 3822, +3944, 0, 3822, +3944, 0, 3822, +3944, 0, 3821, +3944, 0, 3820, +3944, 0, 3820, +3944, 0, 3819, +3943, 0, 3817, +3943, 0, 3815, +3943, 0, 3813, +3942, 0, 3809, +3941, 0, 3805, +3940, 0, 3798, +3939, 0, 3790, +3937, 0, 3777, +3934, 0, 3761, +3931, 0, 3738, +3926, 0, 3706, +3926, 0, 3647, +3926, 0, 3553, +3926, 0, 3388, +3926, 0, 2988, +3926, 2023, 0, +3926, 3430, 0, +4063, 3849, 0, +4095, 4095, 0, +4076, 0, 3922, +4076, 0, 3922, +4076, 0, 3921, +4076, 0, 3921, +4076, 0, 3921, +4076, 0, 3921, +4076, 0, 3921, +4076, 0, 3921, +4076, 0, 3921, +4076, 0, 3921, +4076, 0, 3920, +4076, 0, 3919, +4076, 0, 3918, +4076, 0, 3917, +4075, 0, 3916, +4075, 0, 3913, +4075, 0, 3911, +4074, 0, 3907, +4073, 0, 3902, +4072, 0, 3895, +4071, 0, 3886, +4069, 0, 3873, +4066, 0, 3855, +4063, 0, 3830, +4063, 0, 3786, +4063, 0, 3719, +4063, 0, 3611, +4063, 0, 3409, +4063, 0, 2781, +4063, 0, 0, +4063, 3527, 0, +4095, 3968, 0, +4095, 0, 4027, +4095, 0, 4027, +4095, 0, 4027, +4095, 0, 4027, +4095, 0, 4027, +4095, 0, 4027, +4095, 0, 4027, +4095, 0, 4027, +4095, 0, 4027, +4095, 0, 4026, +4095, 0, 4026, +4095, 0, 4026, +4095, 0, 4025, +4095, 0, 4024, +4095, 0, 4023, +4095, 0, 4021, +4095, 0, 4019, +4095, 0, 4016, +4095, 0, 4012, +4095, 0, 4006, +4095, 0, 3999, +4095, 0, 3989, +4095, 0, 3976, +4095, 0, 3956, +4095, 0, 3923, +4095, 0, 3875, +4095, 0, 3801, +4095, 0, 3679, +4095, 0, 3436, +4095, 0, 2137, +4095, 0, 0, +4095, 3630, 0, +0, 3014, 3284, +0, 3014, 3284, +0, 3014, 3284, +0, 3015, 3284, +0, 3016, 3284, +0, 3017, 3284, +0, 3018, 3284, +0, 3020, 3284, +0, 3022, 3284, +0, 3025, 3284, +0, 3030, 3284, +0, 3035, 3284, +0, 3043, 3284, +0, 3052, 3284, +0, 3065, 3284, +0, 3081, 3284, +0, 3102, 3284, +0, 3128, 3284, +0, 3162, 3284, +0, 3203, 3284, +0, 3252, 3284, +0, 3284, 3254, +0, 3284, 3162, +0, 3284, 2999, +0, 3284, 2609, +0, 3416, 0, +0, 3548, 0, +2237, 3680, 0, +3008, 3812, 0, +3344, 3944, 0, +3584, 4076, 0, +3784, 4095, 0, +0, 3014, 3284, +0, 3014, 3283, +0, 3014, 3283, +0, 3015, 3283, +0, 3016, 3283, +0, 3017, 3283, +0, 3018, 3283, +0, 3020, 3283, +0, 3022, 3283, +0, 3025, 3283, +0, 3029, 3283, +0, 3035, 3283, +0, 3042, 3283, +0, 3052, 3283, +0, 3065, 3283, +0, 3081, 3283, +0, 3102, 3283, +0, 3128, 3283, +0, 3162, 3283, +0, 3203, 3283, +0, 3252, 3283, +0, 3283, 3254, +0, 3283, 3162, +0, 3283, 2999, +0, 3283, 2609, +0, 3416, 0, +0, 3548, 0, +2239, 3680, 0, +3009, 3812, 0, +3344, 3944, 0, +3584, 4076, 0, +3784, 4095, 0, +0, 3013, 3284, +0, 3014, 3283, +0, 3014, 3283, +0, 3014, 3283, +0, 3015, 3283, +0, 3016, 3283, +0, 3018, 3283, +0, 3019, 3283, +0, 3022, 3283, +0, 3025, 3283, +0, 3029, 3283, +0, 3035, 3283, +0, 3042, 3283, +0, 3052, 3283, +0, 3064, 3283, +0, 3081, 3283, +0, 3101, 3283, +0, 3128, 3283, +0, 3161, 3283, +0, 3202, 3283, +0, 3252, 3283, +0, 3283, 3255, +0, 3283, 3163, +0, 3283, 2999, +0, 3283, 2610, +0, 3416, 0, +0, 3548, 0, +2242, 3680, 0, +3009, 3812, 0, +3344, 3944, 0, +3585, 4076, 0, +3784, 4095, 0, +0, 3012, 3284, +0, 3013, 3283, +0, 3013, 3283, +0, 3014, 3283, +0, 3015, 3283, +0, 3016, 3283, +0, 3017, 3283, +0, 3019, 3283, +0, 3021, 3283, +0, 3025, 3283, +0, 3029, 3283, +0, 3034, 3283, +0, 3042, 3283, +0, 3051, 3283, +0, 3064, 3283, +0, 3080, 3283, +0, 3101, 3283, +0, 3128, 3283, +0, 3161, 3283, +0, 3202, 3283, +0, 3252, 3283, +0, 3283, 3255, +0, 3283, 3163, +0, 3283, 2999, +0, 3283, 2611, +0, 3416, 0, +0, 3548, 0, +2246, 3680, 0, +3010, 3812, 0, +3344, 3944, 0, +3585, 4076, 0, +3784, 4095, 0, +0, 3012, 3284, +0, 3012, 3283, +0, 3013, 3283, +0, 3013, 3283, +0, 3014, 3283, +0, 3015, 3283, +0, 3016, 3283, +0, 3018, 3283, +0, 3021, 3283, +0, 3024, 3283, +0, 3028, 3283, +0, 3034, 3283, +0, 3041, 3283, +0, 3051, 3283, +0, 3063, 3283, +0, 3080, 3283, +0, 3101, 3283, +0, 3127, 3283, +0, 3160, 3283, +0, 3201, 3283, +0, 3251, 3283, +0, 3283, 3255, +0, 3283, 3163, +0, 3283, 3000, +0, 3283, 2612, +0, 3416, 0, +0, 3548, 0, +2251, 3680, 0, +3011, 3812, 0, +3345, 3944, 0, +3585, 4076, 0, +3784, 4095, 0, +0, 3011, 3284, +0, 3011, 3283, +0, 3011, 3283, +0, 3012, 3283, +0, 3013, 3283, +0, 3014, 3283, +0, 3016, 3283, +0, 3018, 3283, +0, 3020, 3283, +0, 3023, 3283, +0, 3027, 3283, +0, 3033, 3283, +0, 3040, 3283, +0, 3050, 3283, +0, 3062, 3283, +0, 3079, 3283, +0, 3100, 3283, +0, 3127, 3283, +0, 3160, 3283, +0, 3201, 3283, +0, 3251, 3283, +0, 3283, 3255, +0, 3283, 3163, +0, 3283, 3000, +0, 3283, 2613, +0, 3416, 0, +0, 3548, 0, +2257, 3680, 0, +3012, 3812, 0, +3346, 3944, 0, +3585, 4076, 0, +3784, 4095, 0, +0, 3009, 3284, +0, 3010, 3283, +0, 3010, 3283, +0, 3011, 3283, +0, 3012, 3283, +0, 3013, 3283, +0, 3015, 3283, +0, 3016, 3283, +0, 3019, 3283, +0, 3022, 3283, +0, 3026, 3283, +0, 3032, 3283, +0, 3039, 3283, +0, 3049, 3283, +0, 3062, 3283, +0, 3078, 3283, +0, 3099, 3283, +0, 3126, 3283, +0, 3159, 3283, +0, 3200, 3283, +0, 3250, 3283, +0, 3283, 3256, +0, 3283, 3164, +0, 3283, 3001, +0, 3283, 2614, +0, 3415, 0, +0, 3548, 0, +2266, 3680, 0, +3014, 3812, 0, +3346, 3944, 0, +3586, 4076, 0, +3784, 4095, 0, +0, 3008, 3284, +0, 3008, 3283, +0, 3008, 3283, +0, 3009, 3283, +0, 3010, 3283, +0, 3011, 3283, +0, 3013, 3283, +0, 3015, 3283, +0, 3017, 3283, +0, 3021, 3283, +0, 3025, 3283, +0, 3031, 3283, +0, 3038, 3283, +0, 3047, 3283, +0, 3060, 3283, +0, 3077, 3283, +0, 3098, 3283, +0, 3125, 3283, +0, 3158, 3283, +0, 3199, 3283, +0, 3249, 3283, +0, 3283, 3256, +0, 3283, 3164, +0, 3283, 3002, +0, 3283, 2616, +0, 3415, 0, +0, 3548, 0, +2277, 3680, 0, +3016, 3812, 0, +3347, 3944, 0, +3586, 4076, 0, +3785, 4095, 0, +0, 3005, 3284, +0, 3005, 3283, +0, 3006, 3283, +0, 3007, 3283, +0, 3008, 3283, +0, 3009, 3283, +0, 3010, 3283, +0, 3013, 3283, +0, 3015, 3283, +0, 3018, 3283, +0, 3023, 3283, +0, 3029, 3283, +0, 3036, 3283, +0, 3046, 3283, +0, 3059, 3283, +0, 3075, 3283, +0, 3096, 3283, +0, 3123, 3283, +0, 3157, 3283, +0, 3198, 3283, +0, 3248, 3283, +0, 3283, 3257, +0, 3283, 3165, +0, 3283, 3003, +0, 3283, 2619, +0, 3415, 0, +0, 3548, 0, +2291, 3680, 0, +3019, 3812, 0, +3349, 3944, 0, +3587, 4076, 0, +3786, 4095, 0, +0, 3002, 3284, +0, 3002, 3283, +0, 3002, 3283, +0, 3003, 3283, +0, 3004, 3283, +0, 3005, 3283, +0, 3007, 3283, +0, 3009, 3283, +0, 3012, 3283, +0, 3016, 3282, +0, 3020, 3282, +0, 3026, 3282, +0, 3033, 3282, +0, 3043, 3282, +0, 3056, 3282, +0, 3073, 3282, +0, 3094, 3282, +0, 3121, 3282, +0, 3155, 3282, +0, 3196, 3282, +0, 3247, 3282, +0, 3282, 3257, +0, 3282, 3166, +0, 3282, 3005, +0, 3282, 2622, +0, 3415, 0, +0, 3547, 0, +2310, 3680, 0, +3023, 3812, 0, +3351, 3944, 0, +3588, 4076, 0, +3786, 4095, 0, +0, 2997, 3284, +0, 2998, 3283, +0, 2998, 3283, +0, 2999, 3283, +0, 3000, 3283, +0, 3001, 3283, +0, 3003, 3283, +0, 3005, 3283, +0, 3008, 3283, +0, 3012, 3282, +0, 3017, 3282, +0, 3023, 3282, +0, 3030, 3282, +0, 3040, 3282, +0, 3053, 3282, +0, 3070, 3282, +0, 3091, 3282, +0, 3118, 3282, +0, 3152, 3282, +0, 3194, 3282, +0, 3244, 3282, +0, 3282, 3259, +0, 3282, 3168, +0, 3282, 3006, +0, 3282, 2627, +0, 3414, 0, +0, 3547, 0, +2333, 3679, 0, +3027, 3812, 0, +3353, 3944, 0, +3590, 4076, 0, +3787, 4095, 0, +0, 2991, 3284, +0, 2992, 3283, +0, 2992, 3283, +0, 2993, 3283, +0, 2994, 3283, +0, 2995, 3283, +0, 2997, 3283, +0, 2999, 3283, +0, 3002, 3283, +0, 3006, 3282, +0, 3011, 3282, +0, 3018, 3281, +0, 3025, 3281, +0, 3035, 3281, +0, 3049, 3281, +0, 3065, 3281, +0, 3087, 3281, +0, 3114, 3281, +0, 3149, 3281, +0, 3191, 3281, +0, 3242, 3281, +0, 3281, 3260, +0, 3281, 3169, +0, 3281, 3009, +0, 3281, 2633, +0, 3414, 0, +0, 3547, 0, +2363, 3679, 0, +3034, 3812, 0, +3356, 3944, 0, +3592, 4076, 0, +3788, 4095, 0, +0, 2983, 3284, +0, 2983, 3283, +0, 2984, 3283, +0, 2985, 3283, +0, 2986, 3283, +0, 2987, 3283, +0, 2988, 3283, +0, 2991, 3283, +0, 2994, 3283, +0, 2998, 3282, +0, 3003, 3282, +0, 3010, 3281, +0, 3019, 3280, +0, 3029, 3280, +0, 3043, 3280, +0, 3060, 3280, +0, 3082, 3280, +0, 3109, 3280, +0, 3144, 3280, +0, 3186, 3280, +0, 3238, 3280, +0, 3280, 3262, +0, 3280, 3172, +0, 3280, 3013, +0, 3280, 2641, +0, 3414, 0, +0, 3546, 0, +2400, 3679, 0, +3043, 3811, 0, +3361, 3944, 0, +3594, 4076, 0, +3790, 4095, 0, +0, 2972, 3284, +0, 2972, 3283, +0, 2973, 3283, +0, 2973, 3283, +0, 2974, 3283, +0, 2976, 3283, +0, 2977, 3283, +0, 2980, 3283, +0, 2983, 3283, +0, 2987, 3282, +0, 2992, 3282, +0, 2999, 3281, +0, 3009, 3280, +0, 3021, 3280, +0, 3034, 3280, +0, 3052, 3280, +0, 3074, 3280, +0, 3102, 3280, +0, 3138, 3280, +0, 3180, 3280, +0, 3233, 3280, +0, 3280, 3265, +0, 3280, 3175, +0, 3280, 3017, +0, 3280, 2651, +0, 3413, 0, +0, 3546, 0, +2445, 3678, 0, +3054, 3811, 0, +3366, 3943, 0, +3597, 4076, 0, +3792, 4095, 0, +0, 2956, 3284, +0, 2957, 3283, +0, 2957, 3283, +0, 2958, 3283, +0, 2959, 3283, +0, 2960, 3283, +0, 2962, 3283, +0, 2965, 3283, +0, 2968, 3283, +0, 2972, 3282, +0, 2977, 3282, +0, 2985, 3281, +0, 2995, 3280, +0, 3007, 3280, +0, 3024, 3278, +0, 3041, 3278, +0, 3064, 3278, +0, 3093, 3278, +0, 3129, 3278, +0, 3173, 3278, +0, 3225, 3278, +0, 3278, 3269, +0, 3278, 3180, +0, 3278, 3023, +0, 3278, 2665, +0, 3412, 0, +0, 3545, 0, +2499, 3678, 0, +3069, 3810, 0, +3374, 3943, 0, +3602, 4075, 0, +3795, 4095, 0, +0, 2935, 3284, +0, 2935, 3283, +0, 2936, 3283, +0, 2936, 3283, +0, 2938, 3283, +0, 2939, 3283, +0, 2941, 3283, +0, 2943, 3283, +0, 2947, 3283, +0, 2951, 3282, +0, 2957, 3282, +0, 2965, 3281, +0, 2975, 3280, +0, 2988, 3280, +0, 3005, 3278, +0, 3027, 3276, +0, 3050, 3276, +0, 3080, 3276, +0, 3117, 3276, +0, 3162, 3276, +0, 3216, 3276, +0, 3276, 3273, +0, 3276, 3185, +0, 3276, 3032, +0, 3276, 2683, +0, 3410, 0, +0, 3544, 0, +2562, 3677, 0, +3088, 3810, 0, +3384, 3943, 0, +3608, 4075, 0, +3799, 4095, 0, +0, 2904, 3284, +0, 2905, 3283, +0, 2905, 3283, +0, 2906, 3283, +0, 2907, 3283, +0, 2909, 3283, +0, 2911, 3283, +0, 2914, 3283, +0, 2917, 3283, +0, 2922, 3282, +0, 2928, 3282, +0, 2936, 3281, +0, 2947, 3280, +0, 2961, 3280, +0, 2979, 3278, +0, 3002, 3276, +0, 3031, 3274, +0, 3062, 3274, +0, 3100, 3274, +0, 3147, 3274, +0, 3203, 3274, +0, 3268, 3274, +0, 3274, 3193, +0, 3274, 3042, +0, 3274, 2706, +0, 3408, 0, +0, 3543, 0, +2636, 3676, 0, +3112, 3809, 0, +3396, 3942, 0, +3616, 4075, 0, +3804, 4095, 0, +0, 2860, 3284, +0, 2860, 3283, +0, 2861, 3283, +0, 2862, 3283, +0, 2863, 3283, +0, 2865, 3283, +0, 2867, 3283, +0, 2870, 3283, +0, 2874, 3283, +0, 2879, 3282, +0, 2886, 3282, +0, 2895, 3281, +0, 2907, 3280, +0, 2922, 3280, +0, 2942, 3278, +0, 2967, 3276, +0, 2998, 3274, +0, 3037, 3270, +0, 3078, 3270, +0, 3126, 3270, +0, 3184, 3270, +0, 3252, 3270, +0, 3270, 3203, +0, 3270, 3056, +0, 3270, 2734, +0, 3406, 0, +0, 3541, 0, +2718, 3675, 0, +3143, 3808, 0, +3413, 3941, 0, +3626, 4074, 0, +3811, 4095, 0, +0, 2793, 3284, +0, 2793, 3283, +0, 2794, 3283, +0, 2795, 3283, +0, 2797, 3283, +0, 2799, 3283, +0, 2801, 3283, +0, 2805, 3283, +0, 2809, 3283, +0, 2815, 3282, +0, 2823, 3282, +0, 2833, 3281, +0, 2847, 3280, +0, 2865, 3280, +0, 2886, 3278, +0, 2915, 3276, +0, 2950, 3274, +0, 2993, 3270, +0, 3045, 3266, +0, 3097, 3266, +0, 3159, 3266, +0, 3230, 3266, +0, 3266, 3216, +0, 3266, 3074, +0, 3266, 2770, +0, 3402, 0, +1477, 3538, 0, +2809, 3673, 0, +3181, 3807, 0, +3434, 3940, 0, +3640, 4073, 0, +3820, 4095, 0, +0, 2684, 3284, +0, 2685, 3283, +0, 2686, 3283, +0, 2688, 3283, +0, 2690, 3283, +0, 2692, 3283, +0, 2695, 3283, +0, 2700, 3283, +0, 2705, 3283, +0, 2713, 3282, +0, 2723, 3282, +0, 2735, 3281, +0, 2752, 3280, +0, 2773, 3280, +0, 2800, 3278, +0, 2834, 3276, +0, 2876, 3274, +0, 2926, 3270, +0, 2986, 3266, +1272, 3055, 3259, +1272, 3122, 3259, +1272, 3199, 3259, +1272, 3259, 3233, +1272, 3259, 3097, +1272, 3259, 2813, +0, 3398, 1484, +2256, 3535, 0, +2908, 3670, 0, +3227, 3805, 0, +3461, 3939, 0, +3657, 4072, 0, +3832, 4095, 0, +0, 2481, 3284, +0, 2482, 3283, +0, 2484, 3283, +0, 2486, 3283, +0, 2489, 3283, +0, 2493, 3283, +0, 2498, 3283, +0, 2504, 3283, +0, 2513, 3283, +0, 2524, 3282, +0, 2539, 3282, +0, 2558, 3281, +0, 2583, 3280, +0, 2613, 3280, +0, 2651, 3278, +0, 2698, 3276, +0, 2753, 3274, +0, 2818, 3270, +0, 2893, 3266, +1272, 2976, 3259, +2194, 3069, 3251, +2194, 3154, 3251, +2194, 3248, 3251, +2194, 3251, 3126, +2194, 3251, 2866, +1406, 3392, 2025, +2593, 3530, 0, +3014, 3667, 0, +3282, 3802, 0, +3495, 3937, 0, +3679, 4071, 0, +3847, 4095, 0, +0, 1844, 3284, +0, 1849, 3283, +0, 1856, 3283, +0, 1864, 3283, +0, 1875, 3283, +0, 1890, 3283, +0, 1908, 3283, +0, 1932, 3283, +0, 1962, 3283, +0, 1999, 3282, +0, 2045, 3282, +0, 2100, 3281, +0, 2164, 3280, +0, 2237, 3280, +0, 2320, 3278, +0, 2411, 3276, +0, 2510, 3274, +0, 2616, 3270, +0, 2727, 3266, +1272, 2843, 3259, +2194, 2963, 3251, +2544, 3085, 3239, +2544, 3193, 3239, +2544, 3239, 3162, +2544, 3239, 2928, +2328, 3383, 2326, +2833, 3524, 1536, +3125, 3662, 0, +3347, 3799, 0, +3537, 3934, 0, +3708, 4069, 0, +3867, 4095, 0, +0, 0, 3284, +0, 0, 3283, +0, 0, 3283, +0, 0, 3283, +0, 0, 3283, +0, 0, 3283, +0, 0, 3283, +0, 0, 3283, +0, 0, 3283, +0, 0, 3282, +0, 0, 3282, +0, 0, 3281, +0, 0, 3280, +0, 0, 3280, +0, 0, 3278, +0, 0, 3276, +0, 1202, 3274, +0, 1990, 3270, +0, 2327, 3266, +1272, 2569, 3259, +2194, 2768, 3251, +2544, 2945, 3239, +2790, 3107, 3223, +2790, 3223, 3206, +2790, 3223, 2999, +2774, 3372, 2676, +3032, 3515, 2457, +3240, 3656, 1663, +3421, 3794, 0, +3587, 3931, 0, +3743, 4066, 0, +3892, 4095, 0, +0, 0, 3284, +0, 0, 3283, +0, 0, 3283, +0, 0, 3283, +0, 0, 3283, +0, 0, 3283, +0, 0, 3283, +0, 0, 3283, +0, 0, 3283, +0, 0, 3282, +0, 0, 3282, +0, 0, 3281, +0, 0, 3280, +0, 0, 3280, +0, 0, 3278, +0, 0, 3276, +0, 0, 3274, +0, 0, 3270, +1375, 0, 3266, +1899, 1272, 3259, +2195, 2194, 3251, +2544, 2642, 3239, +2790, 2918, 3223, +2992, 3135, 3201, +2992, 3201, 3080, +3051, 3356, 2922, +3209, 3504, 2808, +3360, 3648, 2590, +3505, 3788, 1799, +3647, 3926, 0, +3786, 4063, 0, +3923, 4095, 0, +2609, 0, 3284, +2609, 0, 3283, +2610, 0, 3283, +2611, 0, 3283, +2612, 0, 3283, +2613, 0, 3283, +2614, 0, 3283, +2616, 0, 3283, +2619, 0, 3283, +2622, 0, 3282, +2627, 0, 3282, +2633, 0, 3281, +2641, 0, 3280, +2651, 0, 3280, +2665, 0, 3278, +2683, 0, 3276, +2706, 0, 3274, +2734, 0, 3270, +2770, 0, 3266, +2813, 1272, 3259, +2866, 2194, 3251, +2928, 2544, 3239, +2999, 2790, 3223, +3080, 2992, 3201, +3170, 3170, 3170, +3267, 3333, 3124, +3372, 3488, 3054, +3482, 3636, 2940, +3597, 3780, 2721, +3716, 3920, 1928, +3838, 4058, 0, +3962, 4095, 0, +3132, 0, 3416, +3132, 0, 3416, +3132, 0, 3416, +3132, 0, 3416, +3132, 0, 3416, +3133, 0, 3416, +3133, 0, 3415, +3134, 0, 3415, +3135, 0, 3415, +3136, 0, 3415, +3137, 0, 3414, +3139, 0, 3414, +3142, 0, 3414, +3145, 0, 3413, +3150, 0, 3412, +3156, 0, 3410, +3164, 0, 3408, +3175, 0, 3406, +3189, 0, 3402, +3206, 0, 3398, +3230, 1406, 3392, +3258, 2326, 3383, +3294, 2676, 3372, +3338, 2922, 3356, +3333, 3124, 3267, +3333, 3212, 3124, +3488, 3470, 3054, +3589, 3636, 2940, +3682, 3780, 2721, +3783, 3920, 1928, +3890, 4058, 0, +4002, 4095, 0, +3426, 0, 3548, +3426, 0, 3548, +3427, 0, 3548, +3427, 0, 3548, +3427, 0, 3548, +3427, 0, 3548, +3427, 0, 3548, +3428, 0, 3548, +3428, 0, 3548, +3429, 0, 3547, +3429, 0, 3547, +3430, 0, 3547, +3432, 0, 3546, +3434, 0, 3546, +3436, 0, 3545, +3440, 0, 3544, +3444, 0, 3543, +3450, 0, 3541, +3457, 0, 3538, +3467, 0, 3535, +3480, 0, 3530, +3497, 1536, 3524, +3515, 2457, 3512, +3504, 2808, 3457, +3488, 3054, 3372, +3488, 3054, 3183, +3488, 3264, 3054, +3636, 3558, 2940, +3776, 3780, 2721, +3860, 3920, 1928, +3952, 4058, 0, +4051, 4095, 0, +3651, 0, 3680, +3651, 0, 3680, +3651, 0, 3680, +3651, 0, 3680, +3651, 0, 3680, +3651, 0, 3680, +3651, 0, 3680, +3652, 0, 3680, +3652, 0, 3680, +3652, 0, 3680, +3653, 0, 3679, +3653, 0, 3679, +3654, 0, 3679, +3655, 0, 3678, +3657, 0, 3678, +3659, 0, 3677, +3662, 0, 3676, +3665, 0, 3675, +3670, 0, 3673, +3670, 0, 3664, +3667, 0, 3648, +3662, 0, 3626, +3656, 1663, 3595, +3648, 2590, 3550, +3636, 2940, 3482, +3636, 2940, 3341, +3636, 2940, 3038, +3636, 3324, 2940, +3780, 3655, 2721, +3920, 3893, 1928, +4023, 4058, 0, +4095, 4095, 0, +3812, 0, 3781, +3812, 0, 3781, +3812, 0, 3781, +3812, 0, 3781, +3812, 0, 3781, +3812, 0, 3781, +3812, 0, 3781, +3812, 0, 3780, +3812, 0, 3780, +3812, 0, 3779, +3812, 0, 3778, +3812, 0, 3777, +3811, 0, 3777, +3811, 0, 3775, +3810, 0, 3773, +3810, 0, 3770, +3809, 0, 3766, +3808, 0, 3761, +3807, 0, 3754, +3805, 0, 3744, +3802, 0, 3731, +3799, 0, 3713, +3794, 0, 3687, +3788, 1799, 3651, +3780, 2721, 3597, +3780, 2721, 3492, +3780, 2721, 3296, +3780, 2721, 2722, +3780, 3394, 2721, +3920, 3758, 1928, +4058, 4008, 0, +4095, 4095, 0, +3944, 0, 3864, +3944, 0, 3864, +3944, 0, 3863, +3944, 0, 3863, +3944, 0, 3863, +3944, 0, 3863, +3944, 0, 3863, +3944, 0, 3863, +3944, 0, 3863, +3944, 0, 3862, +3944, 0, 3862, +3944, 0, 3861, +3944, 0, 3860, +3943, 0, 3859, +3943, 0, 3857, +3943, 0, 3854, +3942, 0, 3851, +3941, 0, 3847, +3940, 0, 3841, +3939, 0, 3833, +3937, 0, 3822, +3934, 0, 3808, +3931, 0, 3787, +3926, 0, 3758, +3920, 1928, 3716, +3920, 1928, 3637, +3920, 1928, 3504, +3920, 1928, 3229, +3920, 2556, 1928, +3920, 3474, 1928, +4058, 3867, 0, +4095, 4095, 0, +4076, 0, 3955, +4076, 0, 3955, +4076, 0, 3955, +4076, 0, 3955, +4076, 0, 3955, +4076, 0, 3954, +4076, 0, 3954, +4076, 0, 3954, +4076, 0, 3954, +4076, 0, 3953, +4076, 0, 3953, +4076, 0, 3953, +4076, 0, 3952, +4076, 0, 3950, +4075, 0, 3949, +4075, 0, 3947, +4075, 0, 3945, +4074, 0, 3941, +4073, 0, 3937, +4072, 0, 3930, +4071, 0, 3921, +4069, 0, 3910, +4066, 0, 3893, +4063, 0, 3870, +4058, 0, 3838, +4058, 0, 3779, +4058, 0, 3685, +4058, 0, 3520, +4058, 0, 3119, +4058, 2157, 0, +4058, 3562, 0, +4095, 3982, 0, +4095, 0, 4054, +4095, 0, 4054, +4095, 0, 4054, +4095, 0, 4054, +4095, 0, 4054, +4095, 0, 4054, +4095, 0, 4054, +4095, 0, 4053, +4095, 0, 4053, +4095, 0, 4053, +4095, 0, 4053, +4095, 0, 4052, +4095, 0, 4051, +4095, 0, 4051, +4095, 0, 4049, +4095, 0, 4048, +4095, 0, 4046, +4095, 0, 4043, +4095, 0, 4039, +4095, 0, 4034, +4095, 0, 4027, +4095, 0, 4018, +4095, 0, 4005, +4095, 0, 3987, +4095, 0, 3962, +4095, 0, 3918, +4095, 0, 3851, +4095, 0, 3743, +4095, 0, 3541, +4095, 0, 2915, +4095, 0, 0, +4095, 3659, 0, +0, 3146, 3416, +0, 3146, 3416, +0, 3147, 3416, +0, 3147, 3416, +0, 3147, 3416, +0, 3148, 3416, +0, 3149, 3416, +0, 3151, 3416, +0, 3152, 3416, +0, 3155, 3416, +0, 3158, 3416, +0, 3162, 3416, +0, 3168, 3416, +0, 3175, 3416, +0, 3184, 3416, +0, 3197, 3416, +0, 3213, 3416, +0, 3234, 3416, +0, 3261, 3416, +0, 3294, 3416, +0, 3335, 3416, +0, 3385, 3416, +0, 3416, 3387, +0, 3416, 3294, +0, 3416, 3132, +0, 3416, 2741, +0, 3548, 0, +0, 3680, 0, +2367, 3812, 0, +3140, 3944, 0, +3475, 4076, 0, +3716, 4095, 0, +0, 3146, 3416, +0, 3146, 3416, +0, 3146, 3416, +0, 3147, 3416, +0, 3147, 3416, +0, 3148, 3416, +0, 3149, 3416, +0, 3151, 3416, +0, 3152, 3416, +0, 3154, 3416, +0, 3158, 3416, +0, 3162, 3416, +0, 3168, 3416, +0, 3175, 3416, +0, 3184, 3416, +0, 3197, 3416, +0, 3213, 3416, +0, 3234, 3416, +0, 3261, 3416, +0, 3294, 3416, +0, 3335, 3416, +0, 3385, 3416, +0, 3416, 3387, +0, 3416, 3294, +0, 3416, 3132, +0, 3416, 2741, +0, 3548, 0, +0, 3680, 0, +2369, 3812, 0, +3140, 3944, 0, +3475, 4076, 0, +3717, 4095, 0, +0, 3145, 3416, +0, 3146, 3416, +0, 3146, 3416, +0, 3147, 3416, +0, 3147, 3416, +0, 3148, 3416, +0, 3149, 3416, +0, 3150, 3416, +0, 3152, 3416, +0, 3154, 3416, +0, 3157, 3416, +0, 3162, 3416, +0, 3167, 3416, +0, 3175, 3416, +0, 3184, 3416, +0, 3197, 3416, +0, 3213, 3416, +0, 3234, 3416, +0, 3260, 3416, +0, 3294, 3416, +0, 3335, 3416, +0, 3384, 3416, +0, 3416, 3387, +0, 3416, 3294, +0, 3416, 3132, +0, 3416, 2742, +0, 3548, 0, +0, 3680, 0, +2371, 3812, 0, +3140, 3944, 0, +3476, 4076, 0, +3717, 4095, 0, +0, 3145, 3416, +0, 3145, 3416, +0, 3146, 3416, +0, 3146, 3416, +0, 3147, 3416, +0, 3147, 3416, +0, 3148, 3416, +0, 3150, 3416, +0, 3151, 3416, +0, 3154, 3416, +0, 3157, 3416, +0, 3161, 3416, +0, 3167, 3416, +0, 3174, 3416, +0, 3184, 3416, +0, 3196, 3416, +0, 3213, 3416, +0, 3234, 3416, +0, 3260, 3416, +0, 3293, 3416, +0, 3335, 3416, +0, 3384, 3416, +0, 3416, 3387, +0, 3416, 3294, +0, 3416, 3132, +0, 3416, 2742, +0, 3548, 0, +0, 3680, 0, +2374, 3812, 0, +3141, 3944, 0, +3476, 4076, 0, +3717, 4095, 0, +0, 3144, 3416, +0, 3145, 3416, +0, 3145, 3416, +0, 3146, 3416, +0, 3146, 3416, +0, 3147, 3416, +0, 3148, 3416, +0, 3149, 3416, +0, 3151, 3416, +0, 3154, 3416, +0, 3157, 3416, +0, 3161, 3416, +0, 3166, 3416, +0, 3174, 3416, +0, 3184, 3416, +0, 3196, 3416, +0, 3212, 3416, +0, 3233, 3416, +0, 3260, 3416, +0, 3293, 3416, +0, 3334, 3416, +0, 3384, 3416, +0, 3416, 3387, +0, 3416, 3295, +0, 3416, 3132, +0, 3416, 2743, +0, 3548, 0, +0, 3680, 0, +2377, 3812, 0, +3142, 3944, 0, +3476, 4076, 0, +3717, 4095, 0, +0, 3144, 3416, +0, 3144, 3416, +0, 3144, 3416, +0, 3145, 3416, +0, 3145, 3416, +0, 3146, 3416, +0, 3147, 3416, +0, 3149, 3416, +0, 3151, 3416, +0, 3153, 3416, +0, 3156, 3416, +0, 3160, 3416, +0, 3166, 3416, +0, 3173, 3416, +0, 3183, 3416, +0, 3196, 3416, +0, 3212, 3416, +0, 3233, 3416, +0, 3259, 3416, +0, 3293, 3416, +0, 3334, 3416, +0, 3384, 3416, +0, 3416, 3387, +0, 3416, 3295, +0, 3416, 3133, +0, 3416, 2744, +0, 3548, 0, +0, 3680, 0, +2382, 3812, 0, +3143, 3944, 0, +3477, 4076, 0, +3717, 4095, 0, +0, 3143, 3416, +0, 3143, 3416, +0, 3143, 3416, +0, 3144, 3416, +0, 3144, 3416, +0, 3145, 3416, +0, 3147, 3415, +0, 3148, 3415, +0, 3150, 3415, +0, 3152, 3415, +0, 3155, 3415, +0, 3160, 3415, +0, 3165, 3415, +0, 3173, 3415, +0, 3182, 3415, +0, 3195, 3415, +0, 3211, 3415, +0, 3232, 3415, +0, 3259, 3415, +0, 3292, 3415, +0, 3333, 3415, +0, 3383, 3415, +0, 3415, 3387, +0, 3415, 3295, +0, 3415, 3133, +0, 3415, 2745, +0, 3548, 0, +0, 3680, 0, +2389, 3812, 0, +3144, 3944, 0, +3477, 4076, 0, +3718, 4095, 0, +0, 3141, 3416, +0, 3141, 3416, +0, 3142, 3416, +0, 3142, 3416, +0, 3143, 3416, +0, 3144, 3416, +0, 3145, 3415, +0, 3147, 3415, +0, 3149, 3415, +0, 3151, 3415, +0, 3154, 3415, +0, 3158, 3415, +0, 3164, 3415, +0, 3171, 3415, +0, 3181, 3415, +0, 3194, 3415, +0, 3210, 3415, +0, 3231, 3415, +0, 3258, 3415, +0, 3291, 3415, +0, 3333, 3415, +0, 3382, 3415, +0, 3415, 3388, +0, 3415, 3296, +0, 3415, 3134, +0, 3415, 2746, +0, 3548, 0, +0, 3680, 0, +2397, 3812, 0, +3145, 3944, 0, +3478, 4076, 0, +3718, 4095, 0, +0, 3139, 3416, +0, 3140, 3416, +0, 3140, 3416, +0, 3141, 3416, +0, 3141, 3416, +0, 3142, 3416, +0, 3144, 3415, +0, 3145, 3415, +0, 3147, 3415, +0, 3150, 3415, +0, 3153, 3415, +0, 3157, 3415, +0, 3163, 3415, +0, 3170, 3415, +0, 3180, 3415, +0, 3192, 3415, +0, 3209, 3415, +0, 3230, 3415, +0, 3257, 3415, +0, 3290, 3415, +0, 3331, 3415, +0, 3381, 3415, +0, 3415, 3388, +0, 3415, 3296, +0, 3415, 3135, +0, 3415, 2748, +0, 3548, 0, +0, 3680, 0, +2408, 3812, 0, +3147, 3944, 0, +3479, 4076, 0, +3719, 4095, 0, +0, 3137, 3416, +0, 3137, 3416, +0, 3138, 3416, +0, 3138, 3416, +0, 3139, 3416, +0, 3140, 3416, +0, 3141, 3415, +0, 3143, 3415, +0, 3145, 3415, +0, 3147, 3415, +0, 3151, 3415, +0, 3155, 3415, +0, 3161, 3415, +0, 3168, 3415, +0, 3178, 3415, +0, 3191, 3415, +0, 3207, 3415, +0, 3228, 3415, +0, 3255, 3415, +0, 3289, 3415, +0, 3330, 3415, +0, 3380, 3415, +0, 3415, 3389, +0, 3415, 3297, +0, 3415, 3136, +0, 3415, 2751, +0, 3547, 0, +0, 3680, 0, +2422, 3812, 0, +3151, 3944, 0, +3480, 4076, 0, +3720, 4095, 0, +0, 3134, 3416, +0, 3134, 3416, +0, 3134, 3416, +0, 3135, 3416, +0, 3135, 3416, +0, 3136, 3416, +0, 3138, 3415, +0, 3139, 3415, +0, 3141, 3415, +0, 3144, 3415, +0, 3148, 3414, +0, 3152, 3414, +0, 3158, 3414, +0, 3165, 3414, +0, 3175, 3414, +0, 3188, 3414, +0, 3205, 3414, +0, 3226, 3414, +0, 3253, 3414, +0, 3287, 3414, +0, 3329, 3414, +0, 3379, 3414, +0, 3414, 3390, +0, 3414, 3298, +0, 3414, 3137, +0, 3414, 2754, +0, 3547, 0, +0, 3679, 0, +2441, 3812, 0, +3154, 3944, 0, +3482, 4076, 0, +3721, 4095, 0, +0, 3129, 3416, +0, 3129, 3416, +0, 3130, 3416, +0, 3130, 3416, +0, 3131, 3416, +0, 3132, 3416, +0, 3133, 3415, +0, 3135, 3415, +0, 3137, 3415, +0, 3140, 3415, +0, 3144, 3414, +0, 3149, 3414, +0, 3155, 3414, +0, 3162, 3414, +0, 3172, 3414, +0, 3185, 3414, +0, 3202, 3414, +0, 3223, 3414, +0, 3250, 3414, +0, 3284, 3414, +0, 3326, 3414, +0, 3376, 3414, +0, 3414, 3391, +0, 3414, 3299, +0, 3414, 3139, +0, 3414, 2759, +0, 3547, 0, +0, 3679, 0, +2465, 3812, 0, +3159, 3944, 0, +3485, 4076, 0, +3722, 4095, 0, +0, 3123, 3416, +0, 3123, 3416, +0, 3124, 3416, +0, 3124, 3416, +0, 3125, 3416, +0, 3126, 3416, +0, 3127, 3415, +0, 3129, 3415, +0, 3131, 3415, +0, 3134, 3415, +0, 3138, 3414, +0, 3143, 3414, +0, 3150, 3414, +0, 3158, 3414, +0, 3168, 3414, +0, 3181, 3414, +0, 3198, 3414, +0, 3219, 3414, +0, 3247, 3414, +0, 3281, 3414, +0, 3323, 3414, +0, 3374, 3414, +0, 3414, 3393, +0, 3414, 3301, +0, 3414, 3142, +0, 3414, 2765, +0, 3546, 0, +0, 3679, 0, +2494, 3811, 0, +3166, 3944, 0, +3488, 4076, 0, +3724, 4095, 0, +0, 3115, 3416, +0, 3115, 3416, +0, 3115, 3416, +0, 3116, 3416, +0, 3117, 3416, +0, 3118, 3416, +0, 3119, 3415, +0, 3121, 3415, +0, 3123, 3415, +0, 3126, 3415, +0, 3130, 3414, +0, 3135, 3414, +0, 3142, 3414, +0, 3151, 3413, +0, 3162, 3413, +0, 3175, 3413, +0, 3192, 3413, +0, 3214, 3413, +0, 3242, 3413, +0, 3276, 3413, +0, 3319, 3413, +0, 3370, 3413, +0, 3413, 3395, +0, 3413, 3304, +0, 3413, 3145, +0, 3413, 2773, +0, 3546, 0, +0, 3678, 0, +2531, 3811, 0, +3175, 3943, 0, +3492, 4076, 0, +3727, 4095, 0, +0, 3104, 3416, +0, 3104, 3416, +0, 3104, 3416, +0, 3105, 3416, +0, 3106, 3416, +0, 3106, 3416, +0, 3108, 3415, +0, 3110, 3415, +0, 3112, 3415, +0, 3115, 3415, +0, 3119, 3414, +0, 3125, 3414, +0, 3132, 3414, +0, 3141, 3413, +0, 3154, 3412, +0, 3167, 3412, +0, 3184, 3412, +0, 3206, 3412, +0, 3234, 3412, +0, 3270, 3412, +0, 3313, 3412, +0, 3365, 3412, +0, 3412, 3397, +0, 3412, 3307, +0, 3412, 3150, +0, 3412, 2784, +0, 3545, 0, +0, 3678, 0, +2576, 3810, 0, +3186, 3943, 0, +3498, 4075, 0, +3730, 4095, 0, +0, 3088, 3416, +0, 3088, 3416, +0, 3089, 3416, +0, 3089, 3416, +0, 3090, 3416, +0, 3091, 3416, +0, 3093, 3415, +0, 3094, 3415, +0, 3097, 3415, +0, 3100, 3415, +0, 3104, 3414, +0, 3110, 3414, +0, 3117, 3414, +0, 3127, 3413, +0, 3140, 3412, +0, 3156, 3410, +0, 3174, 3410, +0, 3196, 3410, +0, 3225, 3410, +0, 3261, 3410, +0, 3305, 3410, +0, 3358, 3410, +0, 3410, 3401, +0, 3410, 3311, +0, 3410, 3156, +0, 3410, 2797, +0, 3544, 0, +0, 3677, 0, +2631, 3810, 0, +3201, 3943, 0, +3505, 4075, 0, +3735, 4095, 0, +0, 3067, 3416, +0, 3067, 3416, +0, 3067, 3416, +0, 3068, 3416, +0, 3069, 3416, +0, 3070, 3416, +0, 3071, 3415, +0, 3073, 3415, +0, 3076, 3415, +0, 3079, 3415, +0, 3083, 3414, +0, 3089, 3414, +0, 3097, 3414, +0, 3107, 3413, +0, 3120, 3412, +0, 3137, 3410, +0, 3159, 3408, +0, 3183, 3408, +0, 3212, 3408, +0, 3249, 3408, +0, 3294, 3408, +0, 3348, 3408, +0, 3408, 3406, +0, 3408, 3317, +0, 3408, 3164, +0, 3408, 2815, +0, 3543, 0, +0, 3676, 0, +2694, 3809, 0, +3220, 3942, 0, +3515, 4075, 0, +3741, 4095, 0, +0, 3036, 3416, +0, 3036, 3416, +0, 3037, 3416, +0, 3038, 3416, +0, 3038, 3416, +0, 3039, 3416, +0, 3041, 3415, +0, 3043, 3415, +0, 3046, 3415, +0, 3049, 3415, +0, 3054, 3414, +0, 3060, 3414, +0, 3069, 3414, +0, 3079, 3413, +0, 3093, 3412, +0, 3111, 3410, +0, 3134, 3408, +0, 3164, 3406, +0, 3194, 3406, +0, 3233, 3406, +0, 3279, 3406, +0, 3335, 3406, +0, 3400, 3406, +0, 3406, 3325, +0, 3406, 3175, +0, 3406, 2838, +0, 3541, 0, +0, 3675, 0, +2767, 3808, 0, +3244, 3941, 0, +3528, 4074, 0, +3748, 4095, 0, +0, 2992, 3416, +0, 2992, 3416, +0, 2992, 3416, +0, 2993, 3416, +0, 2994, 3416, +0, 2996, 3416, +0, 2997, 3415, +0, 2999, 3415, +0, 3002, 3415, +0, 3006, 3415, +0, 3011, 3414, +0, 3018, 3414, +0, 3027, 3414, +0, 3039, 3413, +0, 3055, 3412, +0, 3074, 3410, +0, 3099, 3408, +0, 3131, 3406, +0, 3170, 3402, +0, 3210, 3402, +0, 3259, 3402, +0, 3317, 3402, +0, 3384, 3402, +0, 3402, 3335, +0, 3402, 3189, +0, 3402, 2866, +0, 3538, 0, +0, 3673, 0, +2850, 3807, 0, +3275, 3940, 0, +3545, 4073, 0, +3759, 4095, 0, +0, 2925, 3416, +0, 2925, 3416, +0, 2926, 3416, +0, 2927, 3416, +0, 2928, 3416, +0, 2929, 3416, +0, 2931, 3415, +0, 2934, 3415, +0, 2937, 3415, +0, 2942, 3415, +0, 2947, 3414, +0, 2956, 3414, +0, 2966, 3414, +0, 2979, 3413, +0, 2997, 3412, +0, 3019, 3410, +0, 3047, 3408, +0, 3082, 3406, +0, 3125, 3402, +0, 3177, 3398, +0, 3230, 3398, +0, 3291, 3398, +0, 3362, 3398, +0, 3398, 3348, +0, 3398, 3206, +0, 3398, 2902, +0, 3535, 0, +1603, 3670, 0, +2941, 3805, 0, +3313, 3939, 0, +3566, 4072, 0, +3772, 4095, 0, +0, 2816, 3416, +0, 2817, 3416, +0, 2817, 3416, +0, 2818, 3416, +0, 2820, 3416, +0, 2822, 3416, +0, 2824, 3415, +0, 2827, 3415, +0, 2832, 3415, +0, 2837, 3415, +0, 2845, 3414, +0, 2855, 3414, +0, 2867, 3414, +0, 2884, 3413, +0, 2906, 3412, +0, 2933, 3410, +0, 2966, 3408, +0, 3008, 3406, +0, 3059, 3402, +0, 3118, 3398, +1406, 3187, 3392, +1406, 3255, 3392, +1406, 3331, 3392, +1406, 3392, 3365, +1406, 3392, 3230, +1406, 3392, 2945, +0, 3530, 1621, +2388, 3667, 0, +3040, 3802, 0, +3359, 3937, 0, +3593, 4071, 0, +3790, 4095, 0, +0, 2613, 3416, +0, 2614, 3416, +0, 2615, 3416, +0, 2617, 3416, +0, 2619, 3416, +0, 2621, 3416, +0, 2625, 3415, +0, 2630, 3415, +0, 2637, 3415, +0, 2646, 3415, +0, 2657, 3414, +0, 2672, 3414, +0, 2691, 3414, +0, 2715, 3413, +0, 2746, 3412, +0, 2784, 3410, +0, 2830, 3408, +0, 2886, 3406, +0, 2951, 3402, +0, 3025, 3398, +1406, 3108, 3392, +2326, 3201, 3383, +2326, 3286, 3383, +2326, 3380, 3383, +2326, 3383, 3258, +2326, 3383, 2998, +1536, 3524, 2158, +2724, 3662, 0, +3145, 3799, 0, +3414, 3934, 0, +3627, 4069, 0, +3812, 4095, 0, +0, 1977, 3416, +0, 1981, 3416, +0, 1986, 3416, +0, 1992, 3416, +0, 2000, 3416, +0, 2011, 3416, +0, 2026, 3415, +0, 2044, 3415, +0, 2068, 3415, +0, 2098, 3415, +0, 2135, 3414, +0, 2180, 3414, +0, 2234, 3414, +0, 2298, 3413, +0, 2371, 3412, +0, 2453, 3410, +0, 2545, 3408, +0, 2643, 3406, +0, 2749, 3402, +0, 2860, 3398, +1406, 2976, 3392, +2326, 3095, 3383, +2676, 3218, 3372, +2676, 3325, 3372, +2676, 3372, 3294, +2676, 3372, 3060, +2459, 3515, 2457, +2965, 3656, 1663, +3256, 3794, 0, +3479, 3931, 0, +3669, 4066, 0, +3840, 4095, 0, +0, 0, 3416, +0, 0, 3416, +0, 0, 3416, +0, 0, 3416, +0, 0, 3416, +0, 0, 3416, +0, 0, 3415, +0, 0, 3415, +0, 0, 3415, +0, 0, 3415, +0, 0, 3414, +0, 0, 3414, +0, 0, 3414, +0, 0, 3413, +0, 0, 3412, +0, 0, 3410, +0, 0, 3408, +0, 1325, 3406, +0, 2121, 3402, +0, 2458, 3398, +1406, 2701, 3392, +2326, 2900, 3383, +2676, 3077, 3372, +2922, 3239, 3356, +2922, 3356, 3338, +2922, 3356, 3132, +2907, 3504, 2808, +3165, 3648, 2590, +3372, 3788, 1799, +3553, 3926, 0, +3719, 4063, 0, +3875, 4095, 0, +0, 0, 3416, +0, 0, 3416, +0, 0, 3416, +0, 0, 3416, +0, 0, 3416, +0, 0, 3416, +0, 0, 3415, +0, 0, 3415, +0, 0, 3415, +0, 0, 3415, +0, 0, 3414, +0, 0, 3414, +0, 0, 3414, +0, 0, 3413, +0, 0, 3412, +0, 0, 3410, +0, 0, 3408, +0, 0, 3406, +0, 0, 3402, +1484, 0, 3398, +2025, 1406, 3392, +2326, 2328, 3383, +2676, 2774, 3372, +2922, 3051, 3356, +3124, 3267, 3333, +3124, 3333, 3212, +3183, 3488, 3054, +3341, 3636, 2940, +3492, 3780, 2721, +3637, 3920, 1928, +3779, 4058, 0, +3918, 4095, 0, +2741, 0, 3416, +2741, 0, 3416, +2742, 0, 3416, +2742, 0, 3416, +2743, 0, 3416, +2744, 0, 3416, +2745, 0, 3415, +2746, 0, 3415, +2748, 0, 3415, +2751, 0, 3415, +2754, 0, 3414, +2759, 0, 3414, +2765, 0, 3414, +2773, 0, 3413, +2784, 0, 3412, +2797, 0, 3410, +2815, 0, 3408, +2838, 0, 3406, +2866, 0, 3402, +2902, 0, 3398, +2945, 1406, 3392, +2998, 2326, 3383, +3060, 2676, 3372, +3132, 2922, 3356, +3212, 3124, 3333, +3302, 3302, 3302, +3399, 3466, 3256, +3504, 3620, 3186, +3614, 3768, 3072, +3729, 3912, 2854, +3848, 4052, 2063, +3970, 4095, 0, +3264, 0, 3548, +3264, 0, 3548, +3264, 0, 3548, +3264, 0, 3548, +3264, 0, 3548, +3265, 0, 3548, +3265, 0, 3548, +3265, 0, 3548, +3266, 0, 3548, +3267, 0, 3547, +3268, 0, 3547, +3269, 0, 3547, +3271, 0, 3546, +3274, 0, 3546, +3278, 0, 3545, +3282, 0, 3544, +3288, 0, 3543, +3296, 0, 3541, +3307, 0, 3538, +3321, 0, 3535, +3339, 0, 3530, +3362, 1536, 3524, +3391, 2457, 3515, +3426, 2808, 3504, +3470, 3054, 3488, +3466, 3256, 3399, +3466, 3344, 3256, +3620, 3603, 3186, +3721, 3768, 3072, +3814, 3912, 2854, +3915, 4052, 2063, +4022, 4095, 0, +3558, 0, 3680, +3558, 0, 3680, +3559, 0, 3680, +3559, 0, 3680, +3559, 0, 3680, +3559, 0, 3680, +3559, 0, 3680, +3559, 0, 3680, +3560, 0, 3680, +3560, 0, 3680, +3561, 0, 3679, +3562, 0, 3679, +3563, 0, 3679, +3564, 0, 3678, +3566, 0, 3678, +3568, 0, 3677, +3572, 0, 3676, +3576, 0, 3675, +3582, 0, 3673, +3589, 0, 3670, +3599, 0, 3667, +3612, 0, 3662, +3629, 1663, 3656, +3648, 2590, 3644, +3636, 2940, 3589, +3620, 3186, 3504, +3620, 3186, 3315, +3620, 3396, 3186, +3768, 3691, 3072, +3908, 3912, 2854, +3992, 4052, 2063, +4084, 4095, 0, +3783, 0, 3812, +3783, 0, 3812, +3783, 0, 3812, +3783, 0, 3812, +3783, 0, 3812, +3783, 0, 3812, +3783, 0, 3812, +3784, 0, 3812, +3784, 0, 3812, +3784, 0, 3812, +3784, 0, 3812, +3785, 0, 3812, +3785, 0, 3811, +3786, 0, 3811, +3787, 0, 3810, +3789, 0, 3810, +3791, 0, 3809, +3794, 0, 3808, +3797, 0, 3807, +3802, 0, 3805, +3802, 0, 3796, +3799, 0, 3781, +3794, 0, 3759, +3788, 1799, 3728, +3780, 2721, 3682, +3768, 3072, 3614, +3768, 3072, 3473, +3768, 3072, 3171, +3768, 3456, 3072, +3912, 3787, 2854, +4052, 4025, 2063, +4095, 4095, 0, +3944, 0, 3913, +3944, 0, 3913, +3944, 0, 3913, +3944, 0, 3913, +3944, 0, 3913, +3944, 0, 3913, +3944, 0, 3913, +3944, 0, 3912, +3944, 0, 3912, +3944, 0, 3912, +3944, 0, 3911, +3944, 0, 3910, +3944, 0, 3910, +3943, 0, 3909, +3943, 0, 3907, +3943, 0, 3905, +3942, 0, 3902, +3941, 0, 3898, +3940, 0, 3893, +3939, 0, 3886, +3937, 0, 3876, +3934, 0, 3863, +3931, 0, 3845, +3926, 0, 3820, +3920, 1928, 3783, +3912, 2854, 3729, +3912, 2854, 3624, +3912, 2854, 3428, +3912, 2854, 2854, +3912, 3526, 2854, +4052, 3890, 2063, +4095, 4095, 0, +4076, 0, 3996, +4076, 0, 3996, +4076, 0, 3996, +4076, 0, 3995, +4076, 0, 3995, +4076, 0, 3995, +4076, 0, 3995, +4076, 0, 3995, +4076, 0, 3995, +4076, 0, 3995, +4076, 0, 3994, +4076, 0, 3994, +4076, 0, 3993, +4076, 0, 3992, +4075, 0, 3991, +4075, 0, 3989, +4075, 0, 3986, +4074, 0, 3983, +4073, 0, 3979, +4072, 0, 3973, +4071, 0, 3965, +4069, 0, 3954, +4066, 0, 3940, +4063, 0, 3919, +4058, 0, 3890, +4052, 2063, 3848, +4052, 2063, 3769, +4052, 2063, 3636, +4052, 2063, 3361, +4052, 2689, 2063, +4052, 3606, 2063, +4095, 4000, 0, +4095, 0, 4087, +4095, 0, 4087, +4095, 0, 4087, +4095, 0, 4087, +4095, 0, 4087, +4095, 0, 4087, +4095, 0, 4087, +4095, 0, 4087, +4095, 0, 4086, +4095, 0, 4086, +4095, 0, 4086, +4095, 0, 4085, +4095, 0, 4085, +4095, 0, 4084, +4095, 0, 4083, +4095, 0, 4082, +4095, 0, 4080, +4095, 0, 4077, +4095, 0, 4073, +4095, 0, 4069, +4095, 0, 4062, +4095, 0, 4054, +4095, 0, 4042, +4095, 0, 4025, +4095, 0, 4002, +4095, 0, 3970, +4095, 0, 3911, +4095, 0, 3818, +4095, 0, 3653, +4095, 0, 3253, +4095, 2266, 0, +4095, 3695, 0, +0, 3278, 3548, +0, 3278, 3548, +0, 3279, 3548, +0, 3279, 3548, +0, 3279, 3548, +0, 3280, 3548, +0, 3280, 3548, +0, 3281, 3548, +0, 3283, 3548, +0, 3285, 3548, +0, 3287, 3548, +0, 3290, 3548, +0, 3294, 3548, +0, 3300, 3548, +0, 3307, 3548, +0, 3317, 3548, +0, 3329, 3548, +0, 3346, 3548, +0, 3367, 3548, +0, 3393, 3548, +0, 3426, 3548, +0, 3467, 3548, +0, 3516, 3548, +0, 3548, 3519, +0, 3548, 3426, +0, 3548, 3264, +0, 3548, 2873, +0, 3680, 0, +0, 3812, 0, +2497, 3944, 0, +3271, 4076, 0, +3608, 4095, 0, +0, 3278, 3548, +0, 3278, 3548, +0, 3278, 3548, +0, 3279, 3548, +0, 3279, 3548, +0, 3280, 3548, +0, 3280, 3548, +0, 3281, 3548, +0, 3283, 3548, +0, 3284, 3548, +0, 3287, 3548, +0, 3290, 3548, +0, 3294, 3548, +0, 3300, 3548, +0, 3307, 3548, +0, 3317, 3548, +0, 3329, 3548, +0, 3346, 3548, +0, 3367, 3548, +0, 3393, 3548, +0, 3426, 3548, +0, 3467, 3548, +0, 3516, 3548, +0, 3548, 3519, +0, 3548, 3426, +0, 3548, 3264, +0, 3548, 2873, +0, 3680, 0, +0, 3812, 0, +2498, 3944, 0, +3272, 4076, 0, +3608, 4095, 0, +0, 3278, 3548, +0, 3278, 3548, +0, 3278, 3548, +0, 3279, 3548, +0, 3279, 3548, +0, 3280, 3548, +0, 3280, 3548, +0, 3281, 3548, +0, 3282, 3548, +0, 3284, 3548, +0, 3287, 3548, +0, 3290, 3548, +0, 3294, 3548, +0, 3300, 3548, +0, 3307, 3548, +0, 3317, 3548, +0, 3329, 3548, +0, 3346, 3548, +0, 3366, 3548, +0, 3393, 3548, +0, 3426, 3548, +0, 3467, 3548, +0, 3516, 3548, +0, 3548, 3519, +0, 3548, 3427, +0, 3548, 3264, +0, 3548, 2873, +0, 3680, 0, +0, 3812, 0, +2500, 3944, 0, +3272, 4076, 0, +3608, 4095, 0, +0, 3277, 3548, +0, 3278, 3548, +0, 3278, 3548, +0, 3278, 3548, +0, 3279, 3548, +0, 3279, 3548, +0, 3280, 3548, +0, 3281, 3548, +0, 3282, 3548, +0, 3284, 3548, +0, 3286, 3548, +0, 3290, 3548, +0, 3294, 3548, +0, 3299, 3548, +0, 3307, 3548, +0, 3316, 3548, +0, 3329, 3548, +0, 3345, 3548, +0, 3366, 3548, +0, 3393, 3548, +0, 3426, 3548, +0, 3467, 3548, +0, 3516, 3548, +0, 3548, 3519, +0, 3548, 3427, +0, 3548, 3264, +0, 3548, 2874, +0, 3680, 0, +0, 3812, 0, +2502, 3944, 0, +3272, 4076, 0, +3608, 4095, 0, +0, 3277, 3548, +0, 3277, 3548, +0, 3277, 3548, +0, 3278, 3548, +0, 3278, 3548, +0, 3279, 3548, +0, 3280, 3548, +0, 3280, 3548, +0, 3282, 3548, +0, 3284, 3548, +0, 3286, 3548, +0, 3289, 3548, +0, 3293, 3548, +0, 3299, 3548, +0, 3307, 3548, +0, 3316, 3548, +0, 3329, 3548, +0, 3345, 3548, +0, 3366, 3548, +0, 3392, 3548, +0, 3426, 3548, +0, 3467, 3548, +0, 3516, 3548, +0, 3548, 3519, +0, 3548, 3427, +0, 3548, 3264, +0, 3548, 2874, +0, 3680, 0, +0, 3812, 0, +2505, 3944, 0, +3273, 4076, 0, +3608, 4095, 0, +0, 3276, 3548, +0, 3277, 3548, +0, 3277, 3548, +0, 3277, 3548, +0, 3278, 3548, +0, 3278, 3548, +0, 3279, 3548, +0, 3280, 3548, +0, 3281, 3548, +0, 3283, 3548, +0, 3286, 3548, +0, 3289, 3548, +0, 3293, 3548, +0, 3299, 3548, +0, 3306, 3548, +0, 3316, 3548, +0, 3328, 3548, +0, 3344, 3548, +0, 3365, 3548, +0, 3392, 3548, +0, 3425, 3548, +0, 3466, 3548, +0, 3516, 3548, +0, 3548, 3519, +0, 3548, 3427, +0, 3548, 3265, +0, 3548, 2875, +0, 3680, 0, +0, 3812, 0, +2508, 3944, 0, +3273, 4076, 0, +3609, 4095, 0, +0, 3276, 3548, +0, 3276, 3548, +0, 3276, 3548, +0, 3277, 3548, +0, 3277, 3548, +0, 3278, 3548, +0, 3279, 3548, +0, 3280, 3548, +0, 3281, 3548, +0, 3283, 3548, +0, 3285, 3548, +0, 3288, 3548, +0, 3292, 3548, +0, 3298, 3548, +0, 3305, 3548, +0, 3315, 3548, +0, 3328, 3548, +0, 3344, 3548, +0, 3365, 3548, +0, 3392, 3548, +0, 3425, 3548, +0, 3466, 3548, +0, 3515, 3548, +0, 3548, 3519, +0, 3548, 3427, +0, 3548, 3265, +0, 3548, 2876, +0, 3680, 0, +0, 3812, 0, +2513, 3944, 0, +3274, 4076, 0, +3609, 4095, 0, +0, 3275, 3548, +0, 3275, 3548, +0, 3275, 3548, +0, 3275, 3548, +0, 3276, 3548, +0, 3277, 3548, +0, 3278, 3548, +0, 3279, 3548, +0, 3280, 3548, +0, 3282, 3548, +0, 3284, 3548, +0, 3287, 3548, +0, 3292, 3548, +0, 3297, 3548, +0, 3305, 3548, +0, 3314, 3548, +0, 3327, 3548, +0, 3343, 3548, +0, 3364, 3548, +0, 3391, 3548, +0, 3424, 3548, +0, 3466, 3548, +0, 3515, 3548, +0, 3548, 3520, +0, 3548, 3428, +0, 3548, 3265, +0, 3548, 2877, +0, 3680, 0, +0, 3812, 0, +2520, 3944, 0, +3276, 4076, 0, +3610, 4095, 0, +0, 3273, 3548, +0, 3273, 3548, +0, 3274, 3548, +0, 3274, 3548, +0, 3275, 3548, +0, 3275, 3548, +0, 3276, 3548, +0, 3277, 3548, +0, 3279, 3548, +0, 3281, 3548, +0, 3283, 3548, +0, 3286, 3548, +0, 3291, 3548, +0, 3296, 3548, +0, 3303, 3548, +0, 3313, 3548, +0, 3326, 3548, +0, 3342, 3548, +0, 3363, 3548, +0, 3390, 3548, +0, 3423, 3548, +0, 3465, 3548, +0, 3514, 3548, +0, 3548, 3520, +0, 3548, 3428, +0, 3548, 3266, +0, 3548, 2878, +0, 3680, 0, +0, 3812, 0, +2528, 3944, 0, +3277, 4076, 0, +3611, 4095, 0, +0, 3271, 3548, +0, 3272, 3548, +0, 3272, 3548, +0, 3272, 3548, +0, 3273, 3548, +0, 3273, 3548, +0, 3274, 3548, +0, 3276, 3548, +0, 3277, 3548, +0, 3279, 3547, +0, 3282, 3547, +0, 3285, 3547, +0, 3289, 3547, +0, 3295, 3547, +0, 3302, 3547, +0, 3312, 3547, +0, 3325, 3547, +0, 3341, 3547, +0, 3362, 3547, +0, 3389, 3547, +0, 3422, 3547, +0, 3464, 3547, +0, 3513, 3547, +0, 3547, 3520, +0, 3547, 3429, +0, 3547, 3267, +0, 3547, 2880, +0, 3680, 0, +0, 3812, 0, +2539, 3944, 0, +3279, 4076, 0, +3612, 4095, 0, +0, 3269, 3548, +0, 3269, 3548, +0, 3269, 3548, +0, 3270, 3548, +0, 3270, 3548, +0, 3271, 3548, +0, 3272, 3548, +0, 3273, 3548, +0, 3275, 3548, +0, 3277, 3547, +0, 3280, 3547, +0, 3283, 3547, +0, 3287, 3547, +0, 3293, 3547, +0, 3300, 3547, +0, 3310, 3547, +0, 3323, 3547, +0, 3339, 3547, +0, 3361, 3547, +0, 3387, 3547, +0, 3421, 3547, +0, 3462, 3547, +0, 3512, 3547, +0, 3547, 3521, +0, 3547, 3429, +0, 3547, 3268, +0, 3547, 2883, +0, 3679, 0, +0, 3812, 0, +2553, 3944, 0, +3282, 4076, 0, +3613, 4095, 0, +0, 3266, 3548, +0, 3266, 3548, +0, 3266, 3548, +0, 3267, 3548, +0, 3267, 3548, +0, 3268, 3548, +0, 3269, 3548, +0, 3270, 3548, +0, 3271, 3548, +0, 3274, 3547, +0, 3277, 3547, +0, 3280, 3547, +0, 3285, 3547, +0, 3290, 3547, +0, 3298, 3547, +0, 3307, 3547, +0, 3320, 3547, +0, 3337, 3547, +0, 3358, 3547, +0, 3385, 3547, +0, 3419, 3547, +0, 3461, 3547, +0, 3511, 3547, +0, 3547, 3522, +0, 3547, 3430, +0, 3547, 3269, +0, 3547, 2886, +0, 3679, 0, +0, 3812, 0, +2572, 3944, 0, +3286, 4076, 0, +3615, 4095, 0, +0, 3261, 3548, +0, 3261, 3548, +0, 3261, 3548, +0, 3262, 3548, +0, 3262, 3548, +0, 3263, 3548, +0, 3264, 3548, +0, 3265, 3548, +0, 3267, 3548, +0, 3269, 3547, +0, 3272, 3547, +0, 3276, 3547, +0, 3281, 3546, +0, 3287, 3546, +0, 3294, 3546, +0, 3304, 3546, +0, 3317, 3546, +0, 3334, 3546, +0, 3355, 3546, +0, 3382, 3546, +0, 3416, 3546, +0, 3458, 3546, +0, 3509, 3546, +0, 3546, 3523, +0, 3546, 3432, +0, 3546, 3271, +0, 3546, 2891, +0, 3679, 0, +0, 3811, 0, +2596, 3944, 0, +3291, 4076, 0, +3617, 4095, 0, +0, 3255, 3548, +0, 3255, 3548, +0, 3256, 3548, +0, 3256, 3548, +0, 3256, 3548, +0, 3257, 3548, +0, 3258, 3548, +0, 3259, 3548, +0, 3261, 3548, +0, 3263, 3547, +0, 3266, 3547, +0, 3270, 3547, +0, 3275, 3546, +0, 3282, 3546, +0, 3290, 3546, +0, 3300, 3546, +0, 3313, 3546, +0, 3330, 3546, +0, 3351, 3546, +0, 3379, 3546, +0, 3413, 3546, +0, 3455, 3546, +0, 3506, 3546, +0, 3546, 3525, +0, 3546, 3434, +0, 3546, 3274, +0, 3546, 2897, +0, 3678, 0, +0, 3811, 0, +2625, 3943, 0, +3297, 4076, 0, +3621, 4095, 0, +0, 3247, 3548, +0, 3247, 3548, +0, 3247, 3548, +0, 3248, 3548, +0, 3248, 3548, +0, 3249, 3548, +0, 3250, 3548, +0, 3251, 3548, +0, 3253, 3548, +0, 3255, 3547, +0, 3258, 3547, +0, 3262, 3547, +0, 3268, 3546, +0, 3275, 3546, +0, 3284, 3545, +0, 3294, 3545, +0, 3307, 3545, +0, 3324, 3545, +0, 3346, 3545, +0, 3374, 3545, +0, 3408, 3545, +0, 3451, 3545, +0, 3502, 3545, +0, 3545, 3526, +0, 3545, 3436, +0, 3545, 3278, +0, 3545, 2905, +0, 3678, 0, +0, 3810, 0, +2662, 3943, 0, +3306, 4075, 0, +3625, 4095, 0, +0, 3236, 3548, +0, 3236, 3548, +0, 3236, 3548, +0, 3237, 3548, +0, 3237, 3548, +0, 3238, 3548, +0, 3239, 3548, +0, 3240, 3548, +0, 3242, 3548, +0, 3244, 3547, +0, 3247, 3547, +0, 3251, 3547, +0, 3257, 3546, +0, 3264, 3546, +0, 3273, 3545, +0, 3285, 3544, +0, 3299, 3544, +0, 3316, 3544, +0, 3339, 3544, +0, 3367, 3544, +0, 3402, 3544, +0, 3445, 3544, +0, 3497, 3544, +0, 3544, 3529, +0, 3544, 3440, +0, 3544, 3282, +0, 3544, 2916, +0, 3677, 0, +0, 3810, 0, +2708, 3943, 0, +3318, 4075, 0, +3630, 4095, 0, +0, 3220, 3548, +0, 3220, 3548, +0, 3221, 3548, +0, 3221, 3548, +0, 3222, 3548, +0, 3222, 3548, +0, 3223, 3548, +0, 3225, 3548, +0, 3226, 3548, +0, 3229, 3547, +0, 3232, 3547, +0, 3236, 3547, +0, 3242, 3546, +0, 3249, 3546, +0, 3259, 3545, +0, 3272, 3544, +0, 3288, 3543, +0, 3306, 3543, +0, 3329, 3543, +0, 3357, 3543, +0, 3393, 3543, +0, 3437, 3543, +0, 3490, 3543, +0, 3543, 3533, +0, 3543, 3444, +0, 3543, 3288, +0, 3543, 2929, +0, 3676, 0, +0, 3809, 0, +2762, 3942, 0, +3333, 4075, 0, +3638, 4095, 0, +0, 3198, 3548, +0, 3199, 3548, +0, 3199, 3548, +0, 3200, 3548, +0, 3200, 3548, +0, 3201, 3548, +0, 3202, 3548, +0, 3203, 3548, +0, 3205, 3548, +0, 3208, 3547, +0, 3211, 3547, +0, 3216, 3547, +0, 3221, 3546, +0, 3229, 3546, +0, 3239, 3545, +0, 3253, 3544, +0, 3270, 3543, +0, 3291, 3541, +0, 3315, 3541, +0, 3344, 3541, +0, 3381, 3541, +0, 3426, 3541, +0, 3480, 3541, +0, 3541, 3538, +0, 3541, 3450, +0, 3541, 3296, +0, 3541, 2947, +0, 3675, 0, +0, 3808, 0, +2826, 3941, 0, +3351, 4074, 0, +3648, 4095, 0, +0, 3168, 3548, +0, 3168, 3548, +0, 3168, 3548, +0, 3169, 3548, +0, 3170, 3548, +0, 3171, 3548, +0, 3172, 3548, +0, 3173, 3548, +0, 3175, 3548, +0, 3178, 3547, +0, 3182, 3547, +0, 3186, 3547, +0, 3192, 3546, +0, 3201, 3546, +0, 3211, 3545, +0, 3225, 3544, +0, 3243, 3543, +0, 3267, 3541, +0, 3296, 3538, +0, 3326, 3538, +0, 3365, 3538, +0, 3411, 3538, +0, 3467, 3538, +0, 3532, 3538, +0, 3538, 3457, +0, 3538, 3307, +0, 3538, 2970, +0, 3673, 0, +0, 3807, 0, +2899, 3940, 0, +3376, 4073, 0, +3661, 4095, 0, +0, 3124, 3548, +0, 3124, 3548, +0, 3124, 3548, +0, 3125, 3548, +0, 3125, 3548, +0, 3126, 3548, +0, 3128, 3548, +0, 3129, 3548, +0, 3132, 3548, +0, 3135, 3547, +0, 3138, 3547, +0, 3144, 3547, +0, 3151, 3546, +0, 3160, 3546, +0, 3171, 3545, +0, 3186, 3544, +0, 3206, 3543, +0, 3231, 3541, +0, 3263, 3538, +0, 3302, 3535, +0, 3342, 3535, +0, 3391, 3535, +0, 3449, 3535, +0, 3516, 3535, +0, 3535, 3467, +0, 3535, 3321, +0, 3535, 2998, +0, 3670, 0, +0, 3805, 0, +2982, 3939, 0, +3407, 4072, 0, +3677, 4095, 0, +0, 3056, 3548, +0, 3057, 3548, +0, 3057, 3548, +0, 3058, 3548, +0, 3059, 3548, +0, 3060, 3548, +0, 3061, 3548, +0, 3063, 3548, +0, 3066, 3548, +0, 3069, 3547, +0, 3074, 3547, +0, 3080, 3547, +0, 3087, 3546, +0, 3098, 3546, +0, 3111, 3545, +0, 3129, 3544, +0, 3151, 3543, +0, 3179, 3541, +0, 3214, 3538, +0, 3257, 3535, +0, 3309, 3530, +0, 3362, 3530, +0, 3423, 3530, +0, 3495, 3530, +0, 3530, 3480, +0, 3530, 3339, +0, 3530, 3034, +0, 3667, 0, +1737, 3802, 0, +3073, 3937, 0, +3445, 4071, 0, +3699, 4095, 0, +0, 2948, 3548, +0, 2948, 3548, +0, 2949, 3548, +0, 2950, 3548, +0, 2951, 3548, +0, 2952, 3548, +0, 2954, 3548, +0, 2956, 3548, +0, 2960, 3548, +0, 2964, 3547, +0, 2970, 3547, +0, 2977, 3547, +0, 2987, 3546, +0, 3000, 3546, +0, 3016, 3545, +0, 3038, 3544, +0, 3065, 3543, +0, 3099, 3541, +0, 3140, 3538, +0, 3190, 3535, +0, 3250, 3530, +1536, 3320, 3524, +1536, 3387, 3524, +1536, 3463, 3524, +1536, 3524, 3497, +1536, 3524, 3362, +1536, 3524, 3078, +0, 3662, 1753, +2519, 3799, 0, +3172, 3934, 0, +3491, 4069, 0, +3726, 4095, 0, +0, 2745, 3548, +0, 2745, 3548, +0, 2746, 3548, +0, 2747, 3548, +0, 2749, 3548, +0, 2751, 3548, +0, 2754, 3548, +0, 2758, 3548, +0, 2763, 3548, +0, 2770, 3547, +0, 2778, 3547, +0, 2790, 3547, +0, 2804, 3546, +0, 2824, 3546, +0, 2848, 3545, +0, 2879, 3544, +0, 2917, 3543, +0, 2963, 3541, +0, 3018, 3538, +0, 3083, 3535, +0, 3157, 3530, +1536, 3241, 3524, +2457, 3333, 3515, +2457, 3418, 3515, +2457, 3512, 3515, +2457, 3515, 3391, +2457, 3515, 3130, +1663, 3656, 2289, +2856, 3794, 0, +3277, 3931, 0, +3546, 4066, 0, +3759, 4095, 0, +0, 2104, 3548, +0, 2107, 3548, +0, 2111, 3548, +0, 2115, 3548, +0, 2122, 3548, +0, 2130, 3548, +0, 2141, 3548, +0, 2156, 3548, +0, 2174, 3548, +0, 2198, 3547, +0, 2228, 3547, +0, 2265, 3547, +0, 2311, 3546, +0, 2365, 3546, +0, 2429, 3545, +0, 2502, 3544, +0, 2585, 3543, +0, 2676, 3541, +0, 2775, 3538, +0, 2881, 3535, +0, 2992, 3530, +1536, 3108, 3524, +2457, 3227, 3515, +2808, 3350, 3504, +2808, 3457, 3504, +2808, 3504, 3426, +2808, 3504, 3192, +2592, 3648, 2590, +3097, 3788, 1799, +3388, 3926, 0, +3611, 4063, 0, +3801, 4095, 0, +0, 0, 3548, +0, 0, 3548, +0, 0, 3548, +0, 0, 3548, +0, 0, 3548, +0, 0, 3548, +0, 0, 3548, +0, 0, 3548, +0, 0, 3548, +0, 0, 3547, +0, 0, 3547, +0, 0, 3547, +0, 0, 3546, +0, 0, 3546, +0, 0, 3545, +0, 0, 3544, +0, 0, 3543, +0, 0, 3541, +0, 1477, 3538, +0, 2256, 3535, +0, 2593, 3530, +1536, 2833, 3524, +2457, 3032, 3515, +2808, 3209, 3504, +3054, 3372, 3488, +3054, 3488, 3470, +3054, 3488, 3264, +3038, 3636, 2940, +3296, 3780, 2721, +3504, 3920, 1928, +3685, 4058, 0, +3851, 4095, 0, +0, 0, 3548, +0, 0, 3548, +0, 0, 3548, +0, 0, 3548, +0, 0, 3548, +0, 0, 3548, +0, 0, 3548, +0, 0, 3548, +0, 0, 3548, +0, 0, 3547, +0, 0, 3547, +0, 0, 3547, +0, 0, 3546, +0, 0, 3546, +0, 0, 3545, +0, 0, 3544, +0, 0, 3543, +0, 0, 3541, +0, 0, 3538, +0, 0, 3535, +1621, 0, 3530, +2158, 1536, 3524, +2457, 2459, 3515, +2808, 2907, 3504, +3054, 3183, 3488, +3256, 3399, 3466, +3256, 3466, 3344, +3315, 3620, 3186, +3473, 3768, 3072, +3624, 3912, 2854, +3769, 4052, 2063, +3911, 4095, 0, +2873, 0, 3548, +2873, 0, 3548, +2873, 0, 3548, +2874, 0, 3548, +2874, 0, 3548, +2875, 0, 3548, +2876, 0, 3548, +2877, 0, 3548, +2878, 0, 3548, +2880, 0, 3547, +2883, 0, 3547, +2886, 0, 3547, +2891, 0, 3546, +2897, 0, 3546, +2905, 0, 3545, +2916, 0, 3544, +2929, 0, 3543, +2947, 0, 3541, +2970, 0, 3538, +2998, 0, 3535, +3034, 0, 3530, +3078, 1536, 3524, +3130, 2457, 3515, +3192, 2808, 3504, +3264, 3054, 3488, +3344, 3256, 3466, +3434, 3434, 3434, +3531, 3598, 3388, +3636, 3752, 3318, +3746, 3900, 3204, +3861, 4044, 2986, +3980, 4095, 2192, +3396, 0, 3680, +3396, 0, 3680, +3396, 0, 3680, +3396, 0, 3680, +3396, 0, 3680, +3396, 0, 3680, +3396, 0, 3680, +3397, 0, 3680, +3397, 0, 3680, +3398, 0, 3680, +3399, 0, 3679, +3400, 0, 3679, +3401, 0, 3679, +3403, 0, 3678, +3406, 0, 3678, +3410, 0, 3677, +3414, 0, 3676, +3420, 0, 3675, +3429, 0, 3673, +3439, 0, 3670, +3453, 0, 3667, +3471, 0, 3662, +3494, 1663, 3656, +3523, 2590, 3648, +3558, 2940, 3636, +3603, 3186, 3620, +3598, 3388, 3531, +3598, 3477, 3388, +3752, 3735, 3318, +3853, 3900, 3204, +3947, 4044, 2986, +4047, 4095, 2192, +3691, 0, 3812, +3691, 0, 3812, +3691, 0, 3812, +3691, 0, 3812, +3691, 0, 3812, +3691, 0, 3812, +3691, 0, 3812, +3691, 0, 3812, +3691, 0, 3812, +3692, 0, 3812, +3692, 0, 3812, +3693, 0, 3812, +3694, 0, 3811, +3695, 0, 3811, +3696, 0, 3810, +3698, 0, 3810, +3700, 0, 3809, +3704, 0, 3808, +3708, 0, 3807, +3714, 0, 3805, +3721, 0, 3802, +3731, 0, 3799, +3745, 0, 3794, +3761, 1799, 3788, +3780, 2721, 3776, +3768, 3072, 3721, +3752, 3318, 3636, +3752, 3318, 3447, +3752, 3528, 3318, +3900, 3822, 3204, +4040, 4044, 2986, +4095, 4095, 2192, +3915, 0, 3944, +3915, 0, 3944, +3915, 0, 3944, +3915, 0, 3944, +3915, 0, 3944, +3915, 0, 3944, +3915, 0, 3944, +3915, 0, 3944, +3915, 0, 3944, +3916, 0, 3944, +3916, 0, 3944, +3916, 0, 3944, +3917, 0, 3944, +3917, 0, 3943, +3918, 0, 3943, +3920, 0, 3943, +3921, 0, 3942, +3923, 0, 3941, +3926, 0, 3940, +3929, 0, 3939, +3934, 0, 3937, +3934, 0, 3928, +3931, 0, 3913, +3926, 0, 3891, +3920, 1928, 3860, +3912, 2854, 3814, +3900, 3204, 3746, +3900, 3204, 3605, +3900, 3204, 3302, +3900, 3588, 3204, +4044, 3919, 2986, +4095, 4095, 2192, +4076, 0, 4045, +4076, 0, 4045, +4076, 0, 4045, +4076, 0, 4045, +4076, 0, 4045, +4076, 0, 4045, +4076, 0, 4045, +4076, 0, 4045, +4076, 0, 4044, +4076, 0, 4044, +4076, 0, 4044, +4076, 0, 4043, +4076, 0, 4043, +4076, 0, 4042, +4075, 0, 4041, +4075, 0, 4039, +4075, 0, 4037, +4074, 0, 4034, +4073, 0, 4030, +4072, 0, 4025, +4071, 0, 4018, +4069, 0, 4008, +4066, 0, 3995, +4063, 0, 3977, +4058, 0, 3952, +4052, 2063, 3915, +4044, 2986, 3861, +4044, 2986, 3755, +4044, 2986, 3561, +4044, 2986, 2987, +4044, 3659, 2986, +4095, 4023, 2192, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4087, +4095, 0, 4072, +4095, 0, 4051, +4095, 0, 4022, +4095, 2192, 3980, +4095, 2192, 3901, +4095, 2192, 3768, +4095, 2192, 3494, +4095, 2814, 2192, +4095, 3738, 2192, +0, 3410, 3680, +0, 3410, 3680, +0, 3410, 3680, +0, 3411, 3680, +0, 3411, 3680, +0, 3411, 3680, +0, 3412, 3680, +0, 3413, 3680, +0, 3414, 3680, +0, 3415, 3680, +0, 3417, 3680, +0, 3419, 3680, +0, 3422, 3680, +0, 3427, 3680, +0, 3432, 3680, +0, 3440, 3680, +0, 3449, 3680, +0, 3462, 3680, +0, 3478, 3680, +0, 3499, 3680, +0, 3525, 3680, +0, 3558, 3680, +0, 3599, 3680, +0, 3649, 3680, +0, 3680, 3651, +0, 3680, 3558, +0, 3680, 3396, +0, 3680, 3005, +0, 3812, 0, +0, 3944, 0, +2626, 4076, 0, +3404, 4095, 0, +0, 3410, 3680, +0, 3410, 3680, +0, 3410, 3680, +0, 3411, 3680, +0, 3411, 3680, +0, 3411, 3680, +0, 3412, 3680, +0, 3413, 3680, +0, 3414, 3680, +0, 3415, 3680, +0, 3417, 3680, +0, 3419, 3680, +0, 3422, 3680, +0, 3426, 3680, +0, 3432, 3680, +0, 3439, 3680, +0, 3449, 3680, +0, 3462, 3680, +0, 3478, 3680, +0, 3499, 3680, +0, 3525, 3680, +0, 3558, 3680, +0, 3599, 3680, +0, 3649, 3680, +0, 3680, 3651, +0, 3680, 3558, +0, 3680, 3396, +0, 3680, 3005, +0, 3812, 0, +0, 3944, 0, +2627, 4076, 0, +3404, 4095, 0, +0, 3410, 3680, +0, 3410, 3680, +0, 3410, 3680, +0, 3410, 3680, +0, 3411, 3680, +0, 3411, 3680, +0, 3412, 3680, +0, 3413, 3680, +0, 3414, 3680, +0, 3415, 3680, +0, 3417, 3680, +0, 3419, 3680, +0, 3422, 3680, +0, 3426, 3680, +0, 3432, 3680, +0, 3439, 3680, +0, 3449, 3680, +0, 3462, 3680, +0, 3478, 3680, +0, 3499, 3680, +0, 3525, 3680, +0, 3558, 3680, +0, 3599, 3680, +0, 3649, 3680, +0, 3680, 3651, +0, 3680, 3559, +0, 3680, 3396, +0, 3680, 3005, +0, 3812, 0, +0, 3944, 0, +2628, 4076, 0, +3404, 4095, 0, +0, 3410, 3680, +0, 3410, 3680, +0, 3410, 3680, +0, 3410, 3680, +0, 3411, 3680, +0, 3411, 3680, +0, 3412, 3680, +0, 3412, 3680, +0, 3413, 3680, +0, 3415, 3680, +0, 3416, 3680, +0, 3419, 3680, +0, 3422, 3680, +0, 3426, 3680, +0, 3432, 3680, +0, 3439, 3680, +0, 3449, 3680, +0, 3461, 3680, +0, 3478, 3680, +0, 3499, 3680, +0, 3525, 3680, +0, 3558, 3680, +0, 3599, 3680, +0, 3649, 3680, +0, 3680, 3651, +0, 3680, 3559, +0, 3680, 3396, +0, 3680, 3006, +0, 3812, 0, +0, 3944, 0, +2630, 4076, 0, +3405, 4095, 0, +0, 3409, 3680, +0, 3409, 3680, +0, 3410, 3680, +0, 3410, 3680, +0, 3410, 3680, +0, 3411, 3680, +0, 3411, 3680, +0, 3412, 3680, +0, 3413, 3680, +0, 3414, 3680, +0, 3416, 3680, +0, 3419, 3680, +0, 3422, 3680, +0, 3426, 3680, +0, 3431, 3680, +0, 3439, 3680, +0, 3448, 3680, +0, 3461, 3680, +0, 3478, 3680, +0, 3498, 3680, +0, 3525, 3680, +0, 3558, 3680, +0, 3599, 3680, +0, 3648, 3680, +0, 3680, 3651, +0, 3680, 3559, +0, 3680, 3396, +0, 3680, 3006, +0, 3812, 0, +0, 3944, 0, +2632, 4076, 0, +3405, 4095, 0, +0, 3409, 3680, +0, 3409, 3680, +0, 3409, 3680, +0, 3410, 3680, +0, 3410, 3680, +0, 3410, 3680, +0, 3411, 3680, +0, 3412, 3680, +0, 3413, 3680, +0, 3414, 3680, +0, 3416, 3680, +0, 3418, 3680, +0, 3421, 3680, +0, 3426, 3680, +0, 3431, 3680, +0, 3438, 3680, +0, 3448, 3680, +0, 3461, 3680, +0, 3477, 3680, +0, 3498, 3680, +0, 3525, 3680, +0, 3558, 3680, +0, 3599, 3680, +0, 3648, 3680, +0, 3680, 3651, +0, 3680, 3559, +0, 3680, 3396, +0, 3680, 3006, +0, 3812, 0, +0, 3944, 0, +2635, 4076, 0, +3405, 4095, 0, +0, 3408, 3680, +0, 3408, 3680, +0, 3409, 3680, +0, 3409, 3680, +0, 3409, 3680, +0, 3410, 3680, +0, 3411, 3680, +0, 3411, 3680, +0, 3412, 3680, +0, 3414, 3680, +0, 3415, 3680, +0, 3418, 3680, +0, 3421, 3680, +0, 3425, 3680, +0, 3431, 3680, +0, 3438, 3680, +0, 3448, 3680, +0, 3460, 3680, +0, 3477, 3680, +0, 3497, 3680, +0, 3524, 3680, +0, 3557, 3680, +0, 3598, 3680, +0, 3648, 3680, +0, 3680, 3651, +0, 3680, 3559, +0, 3680, 3396, +0, 3680, 3007, +0, 3812, 0, +0, 3944, 0, +2639, 4076, 0, +3406, 4095, 0, +0, 3408, 3680, +0, 3408, 3680, +0, 3408, 3680, +0, 3408, 3680, +0, 3409, 3680, +0, 3409, 3680, +0, 3410, 3680, +0, 3411, 3680, +0, 3412, 3680, +0, 3413, 3680, +0, 3415, 3680, +0, 3417, 3680, +0, 3420, 3680, +0, 3425, 3680, +0, 3430, 3680, +0, 3437, 3680, +0, 3447, 3680, +0, 3460, 3680, +0, 3476, 3680, +0, 3497, 3680, +0, 3524, 3680, +0, 3557, 3680, +0, 3598, 3680, +0, 3648, 3680, +0, 3680, 3652, +0, 3680, 3559, +0, 3680, 3397, +0, 3680, 3008, +0, 3812, 0, +0, 3944, 0, +2644, 4076, 0, +3407, 4095, 0, +0, 3406, 3680, +0, 3407, 3680, +0, 3407, 3680, +0, 3407, 3680, +0, 3408, 3680, +0, 3408, 3680, +0, 3409, 3680, +0, 3410, 3680, +0, 3411, 3680, +0, 3412, 3680, +0, 3414, 3680, +0, 3416, 3680, +0, 3420, 3680, +0, 3424, 3680, +0, 3429, 3680, +0, 3437, 3680, +0, 3446, 3680, +0, 3459, 3680, +0, 3475, 3680, +0, 3496, 3680, +0, 3523, 3680, +0, 3556, 3680, +0, 3597, 3680, +0, 3647, 3680, +0, 3680, 3652, +0, 3680, 3560, +0, 3680, 3397, +0, 3680, 3009, +0, 3812, 0, +0, 3944, 0, +2650, 4076, 0, +3408, 4095, 0, +0, 3405, 3680, +0, 3405, 3680, +0, 3405, 3680, +0, 3406, 3680, +0, 3406, 3680, +0, 3407, 3680, +0, 3407, 3680, +0, 3408, 3680, +0, 3409, 3680, +0, 3411, 3680, +0, 3413, 3680, +0, 3415, 3680, +0, 3418, 3680, +0, 3423, 3680, +0, 3428, 3680, +0, 3436, 3680, +0, 3445, 3680, +0, 3458, 3680, +0, 3475, 3680, +0, 3495, 3680, +0, 3522, 3680, +0, 3556, 3680, +0, 3597, 3680, +0, 3646, 3680, +0, 3680, 3652, +0, 3680, 3560, +0, 3680, 3398, +0, 3680, 3011, +0, 3812, 0, +0, 3944, 0, +2659, 4076, 0, +3410, 4095, 0, +0, 3403, 3680, +0, 3403, 3680, +0, 3404, 3680, +0, 3404, 3680, +0, 3404, 3680, +0, 3405, 3680, +0, 3406, 3680, +0, 3406, 3680, +0, 3408, 3680, +0, 3409, 3680, +0, 3411, 3679, +0, 3414, 3679, +0, 3417, 3679, +0, 3421, 3679, +0, 3427, 3679, +0, 3434, 3679, +0, 3444, 3679, +0, 3457, 3679, +0, 3473, 3679, +0, 3494, 3679, +0, 3521, 3679, +0, 3554, 3679, +0, 3596, 3679, +0, 3646, 3679, +0, 3679, 3653, +0, 3679, 3561, +0, 3679, 3399, +0, 3679, 3013, +0, 3812, 0, +0, 3944, 0, +2670, 4076, 0, +3412, 4095, 0, +0, 3401, 3680, +0, 3401, 3680, +0, 3401, 3680, +0, 3401, 3680, +0, 3402, 3680, +0, 3402, 3680, +0, 3403, 3680, +0, 3404, 3680, +0, 3405, 3680, +0, 3407, 3680, +0, 3409, 3679, +0, 3412, 3679, +0, 3415, 3679, +0, 3419, 3679, +0, 3425, 3679, +0, 3432, 3679, +0, 3442, 3679, +0, 3455, 3679, +0, 3472, 3679, +0, 3493, 3679, +0, 3520, 3679, +0, 3553, 3679, +0, 3595, 3679, +0, 3644, 3679, +0, 3679, 3653, +0, 3679, 3562, +0, 3679, 3400, +0, 3679, 3015, +0, 3812, 0, +0, 3944, 0, +2684, 4076, 0, +3415, 4095, 0, +0, 3398, 3680, +0, 3398, 3680, +0, 3398, 3680, +0, 3398, 3680, +0, 3399, 3680, +0, 3399, 3680, +0, 3400, 3680, +0, 3401, 3680, +0, 3402, 3680, +0, 3404, 3680, +0, 3406, 3679, +0, 3409, 3679, +0, 3413, 3679, +0, 3417, 3679, +0, 3422, 3679, +0, 3430, 3679, +0, 3440, 3679, +0, 3453, 3679, +0, 3469, 3679, +0, 3490, 3679, +0, 3517, 3679, +0, 3551, 3679, +0, 3593, 3679, +0, 3643, 3679, +0, 3679, 3654, +0, 3679, 3563, +0, 3679, 3401, +0, 3679, 3018, +0, 3811, 0, +0, 3944, 0, +2703, 4076, 0, +3419, 4095, 0, +0, 3393, 3680, +0, 3393, 3680, +0, 3393, 3680, +0, 3394, 3680, +0, 3394, 3680, +0, 3395, 3680, +0, 3395, 3680, +0, 3396, 3680, +0, 3397, 3680, +0, 3399, 3680, +0, 3401, 3679, +0, 3404, 3679, +0, 3408, 3679, +0, 3413, 3678, +0, 3419, 3678, +0, 3426, 3678, +0, 3436, 3678, +0, 3449, 3678, +0, 3466, 3678, +0, 3488, 3678, +0, 3515, 3678, +0, 3548, 3678, +0, 3590, 3678, +0, 3641, 3678, +0, 3678, 3655, +0, 3678, 3564, +0, 3678, 3403, +0, 3678, 3023, +0, 3811, 0, +0, 3943, 0, +2726, 4076, 0, +3424, 4095, 0, +0, 3387, 3680, +0, 3387, 3680, +0, 3387, 3680, +0, 3388, 3680, +0, 3388, 3680, +0, 3388, 3680, +0, 3389, 3680, +0, 3390, 3680, +0, 3392, 3680, +0, 3393, 3680, +0, 3395, 3679, +0, 3398, 3679, +0, 3402, 3679, +0, 3407, 3678, +0, 3414, 3678, +0, 3422, 3678, +0, 3432, 3678, +0, 3445, 3678, +0, 3462, 3678, +0, 3483, 3678, +0, 3511, 3678, +0, 3545, 3678, +0, 3587, 3678, +0, 3638, 3678, +0, 3678, 3657, +0, 3678, 3566, +0, 3678, 3406, +0, 3678, 3029, +0, 3810, 0, +0, 3943, 0, +2756, 4075, 0, +3430, 4095, 0, +0, 3379, 3680, +0, 3379, 3680, +0, 3379, 3680, +0, 3379, 3680, +0, 3380, 3680, +0, 3380, 3680, +0, 3381, 3680, +0, 3382, 3680, +0, 3383, 3680, +0, 3385, 3680, +0, 3387, 3679, +0, 3390, 3679, +0, 3394, 3679, +0, 3400, 3678, +0, 3407, 3678, +0, 3416, 3677, +0, 3426, 3677, +0, 3439, 3677, +0, 3456, 3677, +0, 3478, 3677, +0, 3506, 3677, +0, 3540, 3677, +0, 3583, 3677, +0, 3634, 3677, +0, 3677, 3659, +0, 3677, 3568, +0, 3677, 3410, +0, 3677, 3037, +0, 3810, 0, +0, 3943, 0, +2793, 4075, 0, +3439, 4095, 0, +0, 3367, 3680, +0, 3368, 3680, +0, 3368, 3680, +0, 3368, 3680, +0, 3369, 3680, +0, 3369, 3680, +0, 3370, 3680, +0, 3371, 3680, +0, 3372, 3680, +0, 3374, 3680, +0, 3376, 3679, +0, 3379, 3679, +0, 3384, 3679, +0, 3389, 3678, +0, 3396, 3678, +0, 3405, 3677, +0, 3418, 3676, +0, 3431, 3676, +0, 3448, 3676, +0, 3471, 3676, +0, 3499, 3676, +0, 3534, 3676, +0, 3577, 3676, +0, 3629, 3676, +0, 3676, 3662, +0, 3676, 3572, +0, 3676, 3414, +0, 3676, 3048, +0, 3809, 0, +0, 3942, 0, +2839, 4075, 0, +3450, 4095, 0, +0, 3352, 3680, +0, 3352, 3680, +0, 3353, 3680, +0, 3353, 3680, +0, 3353, 3680, +0, 3354, 3680, +0, 3354, 3680, +0, 3356, 3680, +0, 3357, 3680, +0, 3359, 3680, +0, 3361, 3679, +0, 3364, 3679, +0, 3368, 3679, +0, 3374, 3678, +0, 3381, 3678, +0, 3391, 3677, +0, 3404, 3676, +0, 3420, 3675, +0, 3438, 3675, +0, 3461, 3675, +0, 3490, 3675, +0, 3525, 3675, +0, 3569, 3675, +0, 3622, 3675, +0, 3675, 3665, +0, 3675, 3576, +0, 3675, 3420, +0, 3675, 3061, +0, 3808, 0, +0, 3941, 0, +2893, 4074, 0, +3465, 4095, 0, +0, 3330, 3680, +0, 3331, 3680, +0, 3331, 3680, +0, 3331, 3680, +0, 3332, 3680, +0, 3332, 3680, +0, 3333, 3680, +0, 3334, 3680, +0, 3336, 3680, +0, 3337, 3680, +0, 3340, 3679, +0, 3343, 3679, +0, 3348, 3679, +0, 3354, 3678, +0, 3361, 3678, +0, 3371, 3677, +0, 3385, 3676, +0, 3402, 3675, +0, 3423, 3673, +0, 3447, 3673, +0, 3477, 3673, +0, 3513, 3673, +0, 3558, 3673, +0, 3612, 3673, +0, 3673, 3670, +0, 3673, 3582, +0, 3673, 3429, +0, 3673, 3079, +0, 3807, 0, +0, 3940, 0, +2957, 4073, 0, +3484, 4095, 0, +0, 3300, 3680, +0, 3300, 3680, +0, 3300, 3680, +0, 3301, 3680, +0, 3301, 3680, +0, 3302, 3680, +0, 3303, 3680, +0, 3304, 3680, +0, 3305, 3680, +0, 3307, 3680, +0, 3310, 3679, +0, 3314, 3679, +0, 3318, 3679, +0, 3325, 3678, +0, 3333, 3678, +0, 3344, 3677, +0, 3358, 3676, +0, 3376, 3675, +0, 3399, 3673, +0, 3428, 3670, +0, 3459, 3670, +0, 3497, 3670, +0, 3543, 3670, +0, 3599, 3670, +0, 3664, 3670, +0, 3670, 3589, +0, 3670, 3439, +0, 3670, 3102, +0, 3805, 0, +0, 3939, 0, +3031, 4072, 0, +3509, 4095, 0, +0, 3255, 3680, +0, 3256, 3680, +0, 3256, 3680, +0, 3256, 3680, +0, 3257, 3680, +0, 3258, 3680, +0, 3258, 3680, +0, 3260, 3680, +0, 3261, 3680, +0, 3264, 3680, +0, 3267, 3679, +0, 3271, 3679, +0, 3276, 3679, +0, 3282, 3678, +0, 3291, 3678, +0, 3303, 3677, +0, 3319, 3676, +0, 3338, 3675, +0, 3363, 3673, +0, 3395, 3670, +0, 3434, 3667, +0, 3474, 3667, +0, 3523, 3667, +0, 3581, 3667, +0, 3648, 3667, +0, 3667, 3599, +0, 3667, 3453, +0, 3667, 3131, +0, 3802, 0, +0, 3937, 0, +3113, 4071, 0, +3539, 4095, 0, +0, 3188, 3680, +0, 3188, 3680, +0, 3189, 3680, +0, 3189, 3680, +0, 3190, 3680, +0, 3191, 3680, +0, 3192, 3680, +0, 3193, 3680, +0, 3195, 3680, +0, 3198, 3680, +0, 3201, 3679, +0, 3206, 3679, +0, 3212, 3679, +0, 3220, 3678, +0, 3230, 3678, +0, 3243, 3677, +0, 3261, 3676, +0, 3283, 3675, +0, 3311, 3673, +0, 3346, 3670, +0, 3389, 3667, +0, 3441, 3662, +0, 3494, 3662, +0, 3555, 3662, +0, 3626, 3662, +0, 3662, 3612, +0, 3662, 3471, +0, 3662, 3166, +0, 3799, 0, +1863, 3934, 0, +3205, 4069, 0, +3577, 4095, 0, +0, 3080, 3680, +0, 3080, 3680, +0, 3081, 3680, +0, 3081, 3680, +0, 3082, 3680, +0, 3083, 3680, +0, 3084, 3680, +0, 3086, 3680, +0, 3089, 3680, +0, 3092, 3680, +0, 3096, 3679, +0, 3102, 3679, +0, 3110, 3679, +0, 3119, 3678, +0, 3132, 3678, +0, 3149, 3677, +0, 3170, 3676, +0, 3197, 3675, +0, 3231, 3673, +0, 3273, 3670, +0, 3323, 3667, +0, 3382, 3662, +1663, 3452, 3656, +1663, 3519, 3656, +1663, 3595, 3656, +1663, 3656, 3629, +1663, 3656, 3494, +1663, 3656, 3210, +0, 3794, 1884, +2650, 3931, 0, +3303, 4066, 0, +3623, 4095, 0, +0, 2876, 3680, +0, 2877, 3680, +0, 2877, 3680, +0, 2878, 3680, +0, 2879, 3680, +0, 2881, 3680, +0, 2883, 3680, +0, 2886, 3680, +0, 2890, 3680, +0, 2895, 3680, +0, 2901, 3679, +0, 2910, 3679, +0, 2922, 3679, +0, 2936, 3678, +0, 2955, 3678, +0, 2980, 3677, +0, 3010, 3676, +0, 3048, 3675, +0, 3095, 3673, +0, 3150, 3670, +0, 3215, 3667, +0, 3289, 3662, +1663, 3373, 3656, +2590, 3465, 3648, +2590, 3550, 3648, +2590, 3644, 3648, +2590, 3648, 3523, +2590, 3648, 3262, +1799, 3788, 2422, +2988, 3926, 0, +3409, 4063, 0, +3679, 4095, 0, +0, 2237, 3680, +0, 2239, 3680, +0, 2242, 3680, +0, 2246, 3680, +0, 2251, 3680, +0, 2257, 3680, +0, 2266, 3680, +0, 2277, 3680, +0, 2291, 3680, +0, 2310, 3680, +0, 2333, 3679, +0, 2363, 3679, +0, 2400, 3679, +0, 2445, 3678, +0, 2499, 3678, +0, 2562, 3677, +0, 2636, 3676, +0, 2718, 3675, +0, 2809, 3673, +0, 2908, 3670, +0, 3014, 3667, +0, 3125, 3662, +1663, 3240, 3656, +2590, 3360, 3648, +2940, 3482, 3636, +2940, 3589, 3636, +2940, 3636, 3558, +2940, 3636, 3324, +2722, 3780, 2721, +3229, 3920, 1928, +3520, 4058, 0, +3743, 4095, 0, +0, 0, 3680, +0, 0, 3680, +0, 0, 3680, +0, 0, 3680, +0, 0, 3680, +0, 0, 3680, +0, 0, 3680, +0, 0, 3680, +0, 0, 3680, +0, 0, 3680, +0, 0, 3679, +0, 0, 3679, +0, 0, 3679, +0, 0, 3678, +0, 0, 3678, +0, 0, 3677, +0, 0, 3676, +0, 0, 3675, +0, 0, 3673, +0, 1603, 3670, +0, 2388, 3667, +0, 2724, 3662, +1663, 2965, 3656, +2590, 3165, 3648, +2940, 3341, 3636, +3186, 3504, 3620, +3186, 3620, 3603, +3186, 3620, 3396, +3171, 3768, 3072, +3428, 3912, 2854, +3636, 4052, 2063, +3818, 4095, 0, +0, 0, 3680, +0, 0, 3680, +0, 0, 3680, +0, 0, 3680, +0, 0, 3680, +0, 0, 3680, +0, 0, 3680, +0, 0, 3680, +0, 0, 3680, +0, 0, 3680, +0, 0, 3679, +0, 0, 3679, +0, 0, 3679, +0, 0, 3678, +0, 0, 3678, +0, 0, 3677, +0, 0, 3676, +0, 0, 3675, +0, 0, 3673, +0, 0, 3670, +0, 0, 3667, +1753, 0, 3662, +2289, 1663, 3656, +2590, 2592, 3648, +2940, 3038, 3636, +3186, 3315, 3620, +3388, 3531, 3598, +3388, 3598, 3477, +3447, 3752, 3318, +3605, 3900, 3204, +3755, 4044, 2986, +3901, 4095, 2192, +3005, 0, 3680, +3005, 0, 3680, +3005, 0, 3680, +3006, 0, 3680, +3006, 0, 3680, +3006, 0, 3680, +3007, 0, 3680, +3008, 0, 3680, +3009, 0, 3680, +3011, 0, 3680, +3013, 0, 3679, +3015, 0, 3679, +3018, 0, 3679, +3023, 0, 3678, +3029, 0, 3678, +3037, 0, 3677, +3048, 0, 3676, +3061, 0, 3675, +3079, 0, 3673, +3102, 0, 3670, +3131, 0, 3667, +3166, 0, 3662, +3210, 1663, 3656, +3262, 2590, 3648, +3324, 2940, 3636, +3396, 3186, 3620, +3477, 3388, 3598, +3566, 3566, 3566, +3664, 3730, 3520, +3768, 3884, 3450, +3878, 4032, 3336, +3993, 4095, 3118, +3528, 0, 3812, +3528, 0, 3812, +3528, 0, 3812, +3528, 0, 3812, +3528, 0, 3812, +3528, 0, 3812, +3528, 0, 3812, +3529, 0, 3812, +3529, 0, 3812, +3530, 0, 3812, +3530, 0, 3812, +3531, 0, 3812, +3532, 0, 3811, +3534, 0, 3811, +3536, 0, 3810, +3538, 0, 3810, +3542, 0, 3809, +3546, 0, 3808, +3552, 0, 3807, +3561, 0, 3805, +3571, 0, 3802, +3585, 0, 3799, +3603, 0, 3794, +3626, 1799, 3788, +3655, 2721, 3780, +3691, 3072, 3768, +3735, 3318, 3752, +3730, 3520, 3664, +3730, 3609, 3520, +3884, 3867, 3450, +3986, 4032, 3336, +4079, 4095, 3118, +3822, 0, 3944, +3822, 0, 3944, +3822, 0, 3944, +3823, 0, 3944, +3823, 0, 3944, +3823, 0, 3944, +3823, 0, 3944, +3823, 0, 3944, +3823, 0, 3944, +3824, 0, 3944, +3824, 0, 3944, +3824, 0, 3944, +3825, 0, 3944, +3826, 0, 3943, +3827, 0, 3943, +3828, 0, 3943, +3830, 0, 3942, +3832, 0, 3941, +3836, 0, 3940, +3840, 0, 3939, +3846, 0, 3937, +3853, 0, 3934, +3863, 0, 3931, +3877, 0, 3926, +3893, 1928, 3920, +3912, 2854, 3908, +3900, 3204, 3853, +3884, 3450, 3768, +3884, 3450, 3579, +3884, 3660, 3450, +4032, 3955, 3336, +4095, 4095, 3118, +4047, 0, 4076, +4047, 0, 4076, +4047, 0, 4076, +4047, 0, 4076, +4047, 0, 4076, +4047, 0, 4076, +4047, 0, 4076, +4047, 0, 4076, +4047, 0, 4076, +4047, 0, 4076, +4048, 0, 4076, +4048, 0, 4076, +4048, 0, 4076, +4049, 0, 4076, +4049, 0, 4075, +4050, 0, 4075, +4051, 0, 4075, +4053, 0, 4074, +4055, 0, 4073, +4058, 0, 4072, +4061, 0, 4071, +4066, 0, 4069, +4066, 0, 4060, +4063, 0, 4045, +4058, 0, 4023, +4052, 2063, 3992, +4044, 2986, 3947, +4032, 3336, 3878, +4032, 3336, 3737, +4032, 3336, 3435, +4032, 3720, 3336, +4095, 4051, 3118, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4084, +4095, 2192, 4047, +4095, 3118, 3993, +4095, 3118, 3888, +4095, 3118, 3693, +4095, 3118, 3121, +4095, 3791, 3118, +0, 3542, 3812, +0, 3542, 3812, +0, 3543, 3812, +0, 3543, 3812, +0, 3543, 3812, +0, 3543, 3812, +0, 3544, 3812, +0, 3544, 3812, +0, 3545, 3812, +0, 3546, 3812, +0, 3547, 3812, +0, 3549, 3812, +0, 3552, 3812, +0, 3554, 3812, +0, 3559, 3812, +0, 3564, 3812, +0, 3572, 3812, +0, 3581, 3812, +0, 3594, 3812, +0, 3610, 3812, +0, 3631, 3812, +0, 3657, 3812, +0, 3691, 3812, +0, 3732, 3812, +0, 3781, 3812, +0, 3812, 3783, +0, 3812, 3691, +0, 3812, 3528, +0, 3812, 3137, +0, 3944, 0, +0, 4076, 0, +2761, 4095, 0, +0, 3542, 3812, +0, 3542, 3812, +0, 3543, 3812, +0, 3543, 3812, +0, 3543, 3812, +0, 3543, 3812, +0, 3544, 3812, +0, 3544, 3812, +0, 3545, 3812, +0, 3546, 3812, +0, 3547, 3812, +0, 3549, 3812, +0, 3551, 3812, +0, 3554, 3812, +0, 3559, 3812, +0, 3564, 3812, +0, 3572, 3812, +0, 3581, 3812, +0, 3594, 3812, +0, 3610, 3812, +0, 3631, 3812, +0, 3657, 3812, +0, 3691, 3812, +0, 3731, 3812, +0, 3781, 3812, +0, 3812, 3783, +0, 3812, 3691, +0, 3812, 3528, +0, 3812, 3137, +0, 3944, 0, +0, 4076, 0, +2762, 4095, 0, +0, 3542, 3812, +0, 3542, 3812, +0, 3542, 3812, +0, 3543, 3812, +0, 3543, 3812, +0, 3543, 3812, +0, 3543, 3812, +0, 3544, 3812, +0, 3545, 3812, +0, 3546, 3812, +0, 3547, 3812, +0, 3549, 3812, +0, 3551, 3812, +0, 3554, 3812, +0, 3559, 3812, +0, 3564, 3812, +0, 3572, 3812, +0, 3581, 3812, +0, 3594, 3812, +0, 3610, 3812, +0, 3631, 3812, +0, 3657, 3812, +0, 3690, 3812, +0, 3731, 3812, +0, 3781, 3812, +0, 3812, 3783, +0, 3812, 3691, +0, 3812, 3528, +0, 3812, 3137, +0, 3944, 0, +0, 4076, 0, +2762, 4095, 0, +0, 3542, 3812, +0, 3542, 3812, +0, 3542, 3812, +0, 3542, 3812, +0, 3543, 3812, +0, 3543, 3812, +0, 3543, 3812, +0, 3544, 3812, +0, 3545, 3812, +0, 3545, 3812, +0, 3547, 3812, +0, 3549, 3812, +0, 3551, 3812, +0, 3554, 3812, +0, 3558, 3812, +0, 3564, 3812, +0, 3571, 3812, +0, 3581, 3812, +0, 3594, 3812, +0, 3610, 3812, +0, 3631, 3812, +0, 3657, 3812, +0, 3690, 3812, +0, 3731, 3812, +0, 3781, 3812, +0, 3812, 3783, +0, 3812, 3691, +0, 3812, 3528, +0, 3812, 3138, +0, 3944, 0, +0, 4076, 0, +2764, 4095, 0, +0, 3541, 3812, +0, 3542, 3812, +0, 3542, 3812, +0, 3542, 3812, +0, 3543, 3812, +0, 3543, 3812, +0, 3543, 3812, +0, 3544, 3812, +0, 3544, 3812, +0, 3545, 3812, +0, 3547, 3812, +0, 3549, 3812, +0, 3551, 3812, +0, 3554, 3812, +0, 3558, 3812, +0, 3564, 3812, +0, 3571, 3812, +0, 3581, 3812, +0, 3594, 3812, +0, 3610, 3812, +0, 3631, 3812, +0, 3657, 3812, +0, 3690, 3812, +0, 3731, 3812, +0, 3781, 3812, +0, 3812, 3783, +0, 3812, 3691, +0, 3812, 3528, +0, 3812, 3138, +0, 3944, 0, +0, 4076, 0, +2765, 4095, 0, +0, 3541, 3812, +0, 3541, 3812, +0, 3541, 3812, +0, 3542, 3812, +0, 3542, 3812, +0, 3543, 3812, +0, 3543, 3812, +0, 3543, 3812, +0, 3544, 3812, +0, 3545, 3812, +0, 3547, 3812, +0, 3548, 3812, +0, 3551, 3812, +0, 3554, 3812, +0, 3558, 3812, +0, 3564, 3812, +0, 3571, 3812, +0, 3581, 3812, +0, 3593, 3812, +0, 3609, 3812, +0, 3630, 3812, +0, 3657, 3812, +0, 3690, 3812, +0, 3731, 3812, +0, 3781, 3812, +0, 3812, 3783, +0, 3812, 3691, +0, 3812, 3528, +0, 3812, 3138, +0, 3944, 0, +0, 4076, 0, +2767, 4095, 0, +0, 3541, 3812, +0, 3541, 3812, +0, 3541, 3812, +0, 3541, 3812, +0, 3542, 3812, +0, 3542, 3812, +0, 3543, 3812, +0, 3543, 3812, +0, 3544, 3812, +0, 3545, 3812, +0, 3546, 3812, +0, 3548, 3812, +0, 3550, 3812, +0, 3553, 3812, +0, 3558, 3812, +0, 3563, 3812, +0, 3571, 3812, +0, 3580, 3812, +0, 3593, 3812, +0, 3609, 3812, +0, 3630, 3812, +0, 3657, 3812, +0, 3690, 3812, +0, 3731, 3812, +0, 3781, 3812, +0, 3812, 3783, +0, 3812, 3691, +0, 3812, 3528, +0, 3812, 3139, +0, 3944, 0, +0, 4076, 0, +2770, 4095, 0, +0, 3540, 3812, +0, 3540, 3812, +0, 3541, 3812, +0, 3541, 3812, +0, 3541, 3812, +0, 3541, 3812, +0, 3542, 3812, +0, 3543, 3812, +0, 3543, 3812, +0, 3544, 3812, +0, 3546, 3812, +0, 3548, 3812, +0, 3550, 3812, +0, 3553, 3812, +0, 3557, 3812, +0, 3563, 3812, +0, 3570, 3812, +0, 3580, 3812, +0, 3593, 3812, +0, 3609, 3812, +0, 3630, 3812, +0, 3656, 3812, +0, 3690, 3812, +0, 3730, 3812, +0, 3780, 3812, +0, 3812, 3784, +0, 3812, 3691, +0, 3812, 3529, +0, 3812, 3139, +0, 3944, 0, +0, 4076, 0, +2773, 4095, 0, +0, 3540, 3812, +0, 3540, 3812, +0, 3540, 3812, +0, 3540, 3812, +0, 3540, 3812, +0, 3541, 3812, +0, 3541, 3812, +0, 3542, 3812, +0, 3543, 3812, +0, 3544, 3812, +0, 3545, 3812, +0, 3547, 3812, +0, 3549, 3812, +0, 3552, 3812, +0, 3557, 3812, +0, 3562, 3812, +0, 3570, 3812, +0, 3579, 3812, +0, 3592, 3812, +0, 3608, 3812, +0, 3629, 3812, +0, 3656, 3812, +0, 3689, 3812, +0, 3730, 3812, +0, 3780, 3812, +0, 3812, 3784, +0, 3812, 3691, +0, 3812, 3529, +0, 3812, 3140, +0, 3944, 0, +0, 4076, 0, +2778, 4095, 0, +0, 3538, 3812, +0, 3538, 3812, +0, 3539, 3812, +0, 3539, 3812, +0, 3539, 3812, +0, 3540, 3812, +0, 3540, 3812, +0, 3541, 3812, +0, 3542, 3812, +0, 3543, 3812, +0, 3544, 3812, +0, 3546, 3812, +0, 3548, 3812, +0, 3552, 3812, +0, 3556, 3812, +0, 3562, 3812, +0, 3569, 3812, +0, 3579, 3812, +0, 3591, 3812, +0, 3607, 3812, +0, 3629, 3812, +0, 3655, 3812, +0, 3689, 3812, +0, 3729, 3812, +0, 3779, 3812, +0, 3812, 3784, +0, 3812, 3692, +0, 3812, 3530, +0, 3812, 3141, +0, 3944, 0, +0, 4076, 0, +2785, 4095, 0, +0, 3537, 3812, +0, 3537, 3812, +0, 3537, 3812, +0, 3538, 3812, +0, 3538, 3812, +0, 3538, 3812, +0, 3539, 3812, +0, 3540, 3812, +0, 3540, 3812, +0, 3541, 3812, +0, 3543, 3812, +0, 3545, 3812, +0, 3547, 3812, +0, 3551, 3812, +0, 3555, 3812, +0, 3561, 3812, +0, 3568, 3812, +0, 3577, 3812, +0, 3590, 3812, +0, 3606, 3812, +0, 3628, 3812, +0, 3654, 3812, +0, 3688, 3812, +0, 3729, 3812, +0, 3778, 3812, +0, 3812, 3784, +0, 3812, 3692, +0, 3812, 3530, +0, 3812, 3143, +0, 3944, 0, +0, 4076, 0, +2793, 4095, 0, +0, 3535, 3812, +0, 3536, 3812, +0, 3536, 3812, +0, 3536, 3812, +0, 3536, 3812, +0, 3537, 3812, +0, 3537, 3812, +0, 3538, 3812, +0, 3538, 3812, +0, 3540, 3812, +0, 3541, 3812, +0, 3544, 3812, +0, 3546, 3812, +0, 3549, 3812, +0, 3553, 3812, +0, 3559, 3812, +0, 3566, 3812, +0, 3576, 3812, +0, 3589, 3812, +0, 3605, 3812, +0, 3626, 3812, +0, 3653, 3812, +0, 3687, 3812, +0, 3728, 3812, +0, 3777, 3812, +0, 3812, 3785, +0, 3812, 3693, +0, 3812, 3531, +0, 3812, 3145, +0, 3944, 0, +0, 4076, 0, +2804, 4095, 0, +0, 3533, 3812, +0, 3533, 3812, +0, 3533, 3812, +0, 3533, 3812, +0, 3534, 3812, +0, 3534, 3812, +0, 3534, 3812, +0, 3535, 3812, +0, 3536, 3812, +0, 3537, 3812, +0, 3539, 3812, +0, 3541, 3812, +0, 3544, 3811, +0, 3547, 3811, +0, 3552, 3811, +0, 3557, 3811, +0, 3564, 3811, +0, 3574, 3811, +0, 3587, 3811, +0, 3604, 3811, +0, 3625, 3811, +0, 3652, 3811, +0, 3685, 3811, +0, 3727, 3811, +0, 3777, 3811, +0, 3811, 3785, +0, 3811, 3694, +0, 3811, 3532, +0, 3811, 3147, +0, 3944, 0, +0, 4076, 0, +2818, 4095, 0, +0, 3530, 3812, +0, 3530, 3812, +0, 3530, 3812, +0, 3530, 3812, +0, 3530, 3812, +0, 3531, 3812, +0, 3531, 3812, +0, 3532, 3812, +0, 3533, 3812, +0, 3534, 3812, +0, 3536, 3812, +0, 3538, 3812, +0, 3541, 3811, +0, 3545, 3811, +0, 3549, 3811, +0, 3554, 3811, +0, 3562, 3811, +0, 3572, 3811, +0, 3585, 3811, +0, 3601, 3811, +0, 3622, 3811, +0, 3650, 3811, +0, 3683, 3811, +0, 3725, 3811, +0, 3775, 3811, +0, 3811, 3786, +0, 3811, 3695, +0, 3811, 3534, +0, 3811, 3151, +0, 3943, 0, +0, 4076, 0, +2837, 4095, 0, +0, 3525, 3812, +0, 3525, 3812, +0, 3525, 3812, +0, 3526, 3812, +0, 3526, 3812, +0, 3526, 3812, +0, 3527, 3812, +0, 3528, 3812, +0, 3528, 3812, +0, 3530, 3812, +0, 3531, 3812, +0, 3533, 3812, +0, 3536, 3811, +0, 3540, 3811, +0, 3545, 3810, +0, 3551, 3810, +0, 3559, 3810, +0, 3569, 3810, +0, 3582, 3810, +0, 3598, 3810, +0, 3620, 3810, +0, 3647, 3810, +0, 3680, 3810, +0, 3722, 3810, +0, 3773, 3810, +0, 3810, 3787, +0, 3810, 3696, +0, 3810, 3536, +0, 3810, 3155, +0, 3943, 0, +0, 4075, 0, +2861, 4095, 0, +0, 3519, 3812, +0, 3519, 3812, +0, 3519, 3812, +0, 3520, 3812, +0, 3520, 3812, +0, 3520, 3812, +0, 3521, 3812, +0, 3521, 3812, +0, 3522, 3812, +0, 3523, 3812, +0, 3525, 3812, +0, 3528, 3812, +0, 3530, 3811, +0, 3534, 3811, +0, 3540, 3810, +0, 3547, 3810, +0, 3554, 3810, +0, 3564, 3810, +0, 3577, 3810, +0, 3594, 3810, +0, 3616, 3810, +0, 3643, 3810, +0, 3677, 3810, +0, 3719, 3810, +0, 3770, 3810, +0, 3810, 3789, +0, 3810, 3698, +0, 3810, 3538, +0, 3810, 3161, +0, 3943, 0, +0, 4075, 0, +2890, 4095, 0, +0, 3511, 3812, +0, 3511, 3812, +0, 3511, 3812, +0, 3511, 3812, +0, 3511, 3812, +0, 3512, 3812, +0, 3513, 3812, +0, 3513, 3812, +0, 3514, 3812, +0, 3515, 3812, +0, 3517, 3812, +0, 3520, 3812, +0, 3522, 3811, +0, 3526, 3811, +0, 3532, 3810, +0, 3539, 3810, +0, 3548, 3809, +0, 3558, 3809, +0, 3571, 3809, +0, 3588, 3809, +0, 3610, 3809, +0, 3638, 3809, +0, 3672, 3809, +0, 3715, 3809, +0, 3766, 3809, +0, 3809, 3791, +0, 3809, 3700, +0, 3809, 3542, +0, 3809, 3169, +0, 3942, 0, +0, 4075, 0, +2927, 4095, 0, +0, 3499, 3812, +0, 3499, 3812, +0, 3500, 3812, +0, 3500, 3812, +0, 3500, 3812, +0, 3501, 3812, +0, 3501, 3812, +0, 3502, 3812, +0, 3503, 3812, +0, 3504, 3812, +0, 3506, 3812, +0, 3508, 3812, +0, 3511, 3811, +0, 3516, 3811, +0, 3521, 3810, +0, 3528, 3810, +0, 3537, 3809, +0, 3550, 3808, +0, 3563, 3808, +0, 3581, 3808, +0, 3603, 3808, +0, 3631, 3808, +0, 3666, 3808, +0, 3709, 3808, +0, 3761, 3808, +0, 3808, 3794, +0, 3808, 3704, +0, 3808, 3546, +0, 3808, 3180, +0, 3941, 0, +0, 4074, 0, +2973, 4095, 0, +0, 3484, 3812, +0, 3484, 3812, +0, 3484, 3812, +0, 3485, 3812, +0, 3485, 3812, +0, 3485, 3812, +0, 3486, 3812, +0, 3487, 3812, +0, 3488, 3812, +0, 3489, 3812, +0, 3491, 3812, +0, 3493, 3812, +0, 3496, 3811, +0, 3501, 3811, +0, 3506, 3810, +0, 3514, 3810, +0, 3523, 3809, +0, 3536, 3808, +0, 3552, 3807, +0, 3570, 3807, +0, 3593, 3807, +0, 3622, 3807, +0, 3657, 3807, +0, 3701, 3807, +0, 3754, 3807, +0, 3807, 3797, +0, 3807, 3708, +0, 3807, 3552, +0, 3807, 3194, +0, 3940, 0, +0, 4073, 0, +3027, 4095, 0, +0, 3462, 3812, +0, 3462, 3812, +0, 3463, 3812, +0, 3463, 3812, +0, 3463, 3812, +0, 3464, 3812, +0, 3464, 3812, +0, 3465, 3812, +0, 3466, 3812, +0, 3468, 3812, +0, 3469, 3812, +0, 3472, 3812, +0, 3475, 3811, +0, 3480, 3811, +0, 3486, 3810, +0, 3493, 3810, +0, 3503, 3809, +0, 3517, 3808, +0, 3534, 3807, +0, 3556, 3805, +0, 3579, 3805, +0, 3609, 3805, +0, 3646, 3805, +0, 3690, 3805, +0, 3744, 3805, +0, 3805, 3802, +0, 3805, 3714, +0, 3805, 3561, +0, 3805, 3211, +0, 3939, 0, +0, 4072, 0, +3090, 4095, 0, +0, 3432, 3812, +0, 3432, 3812, +0, 3432, 3812, +0, 3432, 3812, +0, 3433, 3812, +0, 3433, 3812, +0, 3434, 3812, +0, 3435, 3812, +0, 3436, 3812, +0, 3437, 3812, +0, 3439, 3812, +0, 3442, 3812, +0, 3446, 3811, +0, 3450, 3811, +0, 3457, 3810, +0, 3465, 3810, +0, 3475, 3809, +0, 3490, 3808, +0, 3508, 3807, +0, 3531, 3805, +0, 3560, 3802, +0, 3591, 3802, +0, 3629, 3802, +0, 3676, 3802, +0, 3731, 3802, +0, 3796, 3802, +0, 3802, 3721, +0, 3802, 3571, +0, 3802, 3234, +0, 3937, 0, +0, 4071, 0, +3164, 4095, 0, +0, 3387, 3812, +0, 3388, 3812, +0, 3388, 3812, +0, 3388, 3812, +0, 3388, 3812, +0, 3389, 3812, +0, 3390, 3812, +0, 3391, 3812, +0, 3392, 3812, +0, 3394, 3812, +0, 3396, 3812, +0, 3399, 3812, +0, 3403, 3811, +0, 3408, 3811, +0, 3415, 3810, +0, 3424, 3810, +0, 3435, 3809, +0, 3451, 3808, +0, 3470, 3807, +0, 3495, 3805, +0, 3527, 3802, +0, 3566, 3799, +0, 3606, 3799, +0, 3655, 3799, +0, 3713, 3799, +0, 3781, 3799, +0, 3799, 3731, +0, 3799, 3585, +0, 3799, 3262, +0, 3934, 0, +0, 4069, 0, +3246, 4095, 0, +0, 3320, 3812, +0, 3321, 3812, +0, 3321, 3812, +0, 3321, 3812, +0, 3322, 3812, +0, 3322, 3812, +0, 3323, 3812, +0, 3324, 3812, +0, 3326, 3812, +0, 3328, 3812, +0, 3330, 3812, +0, 3333, 3812, +0, 3338, 3811, +0, 3344, 3811, +0, 3352, 3810, +0, 3362, 3810, +0, 3376, 3809, +0, 3393, 3808, +0, 3415, 3807, +0, 3443, 3805, +0, 3479, 3802, +0, 3522, 3799, +0, 3574, 3794, +0, 3626, 3794, +0, 3687, 3794, +0, 3759, 3794, +0, 3794, 3745, +0, 3794, 3603, +0, 3794, 3298, +0, 3931, 0, +1985, 4066, 0, +3337, 4095, 0, +0, 3211, 3812, +0, 3212, 3812, +0, 3212, 3812, +0, 3213, 3812, +0, 3213, 3812, +0, 3214, 3812, +0, 3215, 3812, +0, 3216, 3812, +0, 3218, 3812, +0, 3221, 3812, +0, 3224, 3812, +0, 3228, 3812, +0, 3234, 3811, +0, 3241, 3811, +0, 3251, 3810, +0, 3264, 3810, +0, 3281, 3809, +0, 3302, 3808, +0, 3329, 3807, +0, 3363, 3805, +0, 3405, 3802, +0, 3455, 3799, +0, 3515, 3794, +1799, 3584, 3788, +1799, 3651, 3788, +1799, 3728, 3788, +1799, 3788, 3761, +1799, 3788, 3626, +1799, 3788, 3342, +0, 3926, 2023, +2781, 4063, 0, +3436, 4095, 0, +0, 3008, 3812, +0, 3009, 3812, +0, 3009, 3812, +0, 3010, 3812, +0, 3011, 3812, +0, 3012, 3812, +0, 3014, 3812, +0, 3016, 3812, +0, 3019, 3812, +0, 3023, 3812, +0, 3027, 3812, +0, 3034, 3812, +0, 3043, 3811, +0, 3054, 3811, +0, 3069, 3810, +0, 3088, 3810, +0, 3112, 3809, +0, 3143, 3808, +0, 3181, 3807, +0, 3227, 3805, +0, 3282, 3802, +0, 3347, 3799, +0, 3421, 3794, +1799, 3505, 3788, +2721, 3597, 3780, +2721, 3682, 3780, +2721, 3776, 3780, +2721, 3780, 3655, +2721, 3780, 3394, +1928, 3920, 2556, +3119, 4058, 0, +3541, 4095, 0, +0, 2367, 3812, +0, 2369, 3812, +0, 2371, 3812, +0, 2374, 3812, +0, 2377, 3812, +0, 2382, 3812, +0, 2389, 3812, +0, 2397, 3812, +0, 2408, 3812, +0, 2422, 3812, +0, 2441, 3812, +0, 2465, 3812, +0, 2494, 3811, +0, 2531, 3811, +0, 2576, 3810, +0, 2631, 3810, +0, 2694, 3809, +0, 2767, 3808, +0, 2850, 3807, +0, 2941, 3805, +0, 3040, 3802, +0, 3145, 3799, +0, 3256, 3794, +1799, 3372, 3788, +2721, 3492, 3780, +3072, 3614, 3768, +3072, 3721, 3768, +3072, 3768, 3691, +3072, 3768, 3456, +2854, 3912, 2854, +3361, 4052, 2063, +3653, 4095, 0, +0, 0, 3812, +0, 0, 3812, +0, 0, 3812, +0, 0, 3812, +0, 0, 3812, +0, 0, 3812, +0, 0, 3812, +0, 0, 3812, +0, 0, 3812, +0, 0, 3812, +0, 0, 3812, +0, 0, 3812, +0, 0, 3811, +0, 0, 3811, +0, 0, 3810, +0, 0, 3810, +0, 0, 3809, +0, 0, 3808, +0, 0, 3807, +0, 0, 3805, +0, 1737, 3802, +0, 2519, 3799, +0, 2856, 3794, +1799, 3097, 3788, +2721, 3296, 3780, +3072, 3473, 3768, +3318, 3636, 3752, +3318, 3752, 3735, +3318, 3752, 3528, +3302, 3900, 3204, +3561, 4044, 2986, +3768, 4095, 2192, +0, 0, 3812, +0, 0, 3812, +0, 0, 3812, +0, 0, 3812, +0, 0, 3812, +0, 0, 3812, +0, 0, 3812, +0, 0, 3812, +0, 0, 3812, +0, 0, 3812, +0, 0, 3812, +0, 0, 3812, +0, 0, 3811, +0, 0, 3811, +0, 0, 3810, +0, 0, 3810, +0, 0, 3809, +0, 0, 3808, +0, 0, 3807, +0, 0, 3805, +0, 0, 3802, +0, 0, 3799, +1884, 0, 3794, +2422, 1799, 3788, +2721, 2722, 3780, +3072, 3171, 3768, +3318, 3447, 3752, +3520, 3664, 3730, +3520, 3730, 3609, +3579, 3884, 3450, +3737, 4032, 3336, +3888, 4095, 3118, +3137, 0, 3812, +3137, 0, 3812, +3137, 0, 3812, +3138, 0, 3812, +3138, 0, 3812, +3138, 0, 3812, +3139, 0, 3812, +3139, 0, 3812, +3140, 0, 3812, +3141, 0, 3812, +3143, 0, 3812, +3145, 0, 3812, +3147, 0, 3811, +3151, 0, 3811, +3155, 0, 3810, +3161, 0, 3810, +3169, 0, 3809, +3180, 0, 3808, +3194, 0, 3807, +3211, 0, 3805, +3234, 0, 3802, +3262, 0, 3799, +3298, 0, 3794, +3342, 1799, 3788, +3394, 2721, 3780, +3456, 3072, 3768, +3528, 3318, 3752, +3609, 3520, 3730, +3698, 3698, 3698, +3796, 3862, 3652, +3900, 4016, 3583, +4010, 4095, 3469, +3660, 0, 3944, +3660, 0, 3944, +3660, 0, 3944, +3660, 0, 3944, +3660, 0, 3944, +3660, 0, 3944, +3660, 0, 3944, +3660, 0, 3944, +3661, 0, 3944, +3661, 0, 3944, +3661, 0, 3944, +3662, 0, 3944, +3663, 0, 3944, +3664, 0, 3943, +3665, 0, 3943, +3667, 0, 3943, +3670, 0, 3942, +3674, 0, 3941, +3678, 0, 3940, +3685, 0, 3939, +3692, 0, 3937, +3703, 0, 3934, +3717, 0, 3931, +3735, 0, 3926, +3758, 1928, 3920, +3787, 2854, 3912, +3822, 3204, 3900, +3867, 3450, 3884, +3862, 3652, 3796, +3862, 3741, 3652, +4016, 3999, 3583, +4095, 4095, 3469, +3954, 0, 4076, +3954, 0, 4076, +3954, 0, 4076, +3954, 0, 4076, +3955, 0, 4076, +3955, 0, 4076, +3955, 0, 4076, +3955, 0, 4076, +3955, 0, 4076, +3955, 0, 4076, +3955, 0, 4076, +3956, 0, 4076, +3956, 0, 4076, +3957, 0, 4076, +3958, 0, 4075, +3959, 0, 4075, +3960, 0, 4075, +3962, 0, 4074, +3964, 0, 4073, +3968, 0, 4072, +3972, 0, 4071, +3978, 0, 4069, +3985, 0, 4066, +3995, 0, 4063, +4008, 0, 4058, +4025, 2063, 4052, +4044, 2986, 4040, +4032, 3336, 3986, +4016, 3583, 3900, +4016, 3583, 3711, +4016, 3792, 3583, +4095, 4087, 3469, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 2192, 4095, +4095, 3118, 4079, +4095, 3469, 4010, +4095, 3469, 3869, +4095, 3469, 3568, +4095, 3853, 3469, +0, 3674, 3944, +0, 3674, 3944, +0, 3674, 3944, +0, 3674, 3944, +0, 3675, 3944, +0, 3675, 3944, +0, 3675, 3944, +0, 3676, 3944, +0, 3676, 3944, +0, 3677, 3944, +0, 3678, 3944, +0, 3679, 3944, +0, 3681, 3944, +0, 3683, 3944, +0, 3687, 3944, +0, 3691, 3944, +0, 3696, 3944, +0, 3704, 3944, +0, 3713, 3944, +0, 3726, 3944, +0, 3742, 3944, +0, 3763, 3944, +0, 3790, 3944, +0, 3823, 3944, +0, 3864, 3944, +0, 3913, 3944, +0, 3944, 3915, +0, 3944, 3822, +0, 3944, 3660, +0, 3944, 3269, +0, 4076, 0, +0, 4095, 0, +0, 3674, 3944, +0, 3674, 3944, +0, 3674, 3944, +0, 3674, 3944, +0, 3675, 3944, +0, 3675, 3944, +0, 3675, 3944, +0, 3676, 3944, +0, 3676, 3944, +0, 3677, 3944, +0, 3678, 3944, +0, 3679, 3944, +0, 3681, 3944, +0, 3683, 3944, +0, 3687, 3944, +0, 3691, 3944, +0, 3696, 3944, +0, 3704, 3944, +0, 3713, 3944, +0, 3726, 3944, +0, 3742, 3944, +0, 3763, 3944, +0, 3790, 3944, +0, 3823, 3944, +0, 3864, 3944, +0, 3913, 3944, +0, 3944, 3915, +0, 3944, 3822, +0, 3944, 3660, +0, 3944, 3269, +0, 4076, 0, +0, 4095, 0, +0, 3674, 3944, +0, 3674, 3944, +0, 3674, 3944, +0, 3674, 3944, +0, 3675, 3944, +0, 3675, 3944, +0, 3675, 3944, +0, 3676, 3944, +0, 3676, 3944, +0, 3677, 3944, +0, 3678, 3944, +0, 3679, 3944, +0, 3681, 3944, +0, 3683, 3944, +0, 3687, 3944, +0, 3691, 3944, +0, 3696, 3944, +0, 3704, 3944, +0, 3713, 3944, +0, 3726, 3944, +0, 3742, 3944, +0, 3763, 3944, +0, 3790, 3944, +0, 3823, 3944, +0, 3863, 3944, +0, 3913, 3944, +0, 3944, 3915, +0, 3944, 3822, +0, 3944, 3660, +0, 3944, 3269, +0, 4076, 0, +0, 4095, 0, +0, 3674, 3944, +0, 3674, 3944, +0, 3674, 3944, +0, 3674, 3944, +0, 3674, 3944, +0, 3675, 3944, +0, 3675, 3944, +0, 3676, 3944, +0, 3676, 3944, +0, 3677, 3944, +0, 3678, 3944, +0, 3679, 3944, +0, 3681, 3944, +0, 3683, 3944, +0, 3686, 3944, +0, 3691, 3944, +0, 3696, 3944, +0, 3703, 3944, +0, 3713, 3944, +0, 3726, 3944, +0, 3742, 3944, +0, 3763, 3944, +0, 3790, 3944, +0, 3822, 3944, +0, 3863, 3944, +0, 3913, 3944, +0, 3944, 3915, +0, 3944, 3823, +0, 3944, 3660, +0, 3944, 3269, +0, 4076, 0, +0, 4095, 0, +0, 3674, 3944, +0, 3674, 3944, +0, 3674, 3944, +0, 3674, 3944, +0, 3674, 3944, +0, 3674, 3944, +0, 3675, 3944, +0, 3675, 3944, +0, 3676, 3944, +0, 3677, 3944, +0, 3678, 3944, +0, 3679, 3944, +0, 3681, 3944, +0, 3683, 3944, +0, 3686, 3944, +0, 3691, 3944, +0, 3696, 3944, +0, 3703, 3944, +0, 3713, 3944, +0, 3726, 3944, +0, 3742, 3944, +0, 3763, 3944, +0, 3789, 3944, +0, 3822, 3944, +0, 3863, 3944, +0, 3913, 3944, +0, 3944, 3915, +0, 3944, 3823, +0, 3944, 3660, +0, 3944, 3270, +0, 4076, 0, +0, 4095, 0, +0, 3674, 3944, +0, 3674, 3944, +0, 3674, 3944, +0, 3674, 3944, +0, 3674, 3944, +0, 3674, 3944, +0, 3675, 3944, +0, 3675, 3944, +0, 3676, 3944, +0, 3676, 3944, +0, 3677, 3944, +0, 3679, 3944, +0, 3681, 3944, +0, 3683, 3944, +0, 3686, 3944, +0, 3690, 3944, +0, 3696, 3944, +0, 3703, 3944, +0, 3713, 3944, +0, 3725, 3944, +0, 3742, 3944, +0, 3763, 3944, +0, 3789, 3944, +0, 3822, 3944, +0, 3863, 3944, +0, 3913, 3944, +0, 3944, 3915, +0, 3944, 3823, +0, 3944, 3660, +0, 3944, 3270, +0, 4076, 0, +0, 4095, 0, +0, 3673, 3944, +0, 3673, 3944, +0, 3673, 3944, +0, 3674, 3944, +0, 3674, 3944, +0, 3674, 3944, +0, 3674, 3944, +0, 3675, 3944, +0, 3676, 3944, +0, 3676, 3944, +0, 3677, 3944, +0, 3679, 3944, +0, 3680, 3944, +0, 3683, 3944, +0, 3686, 3944, +0, 3690, 3944, +0, 3696, 3944, +0, 3703, 3944, +0, 3713, 3944, +0, 3725, 3944, +0, 3741, 3944, +0, 3762, 3944, +0, 3789, 3944, +0, 3822, 3944, +0, 3863, 3944, +0, 3913, 3944, +0, 3944, 3915, +0, 3944, 3823, +0, 3944, 3660, +0, 3944, 3270, +0, 4076, 0, +0, 4095, 0, +0, 3673, 3944, +0, 3673, 3944, +0, 3673, 3944, +0, 3673, 3944, +0, 3673, 3944, +0, 3674, 3944, +0, 3674, 3944, +0, 3674, 3944, +0, 3675, 3944, +0, 3676, 3944, +0, 3677, 3944, +0, 3678, 3944, +0, 3680, 3944, +0, 3682, 3944, +0, 3686, 3944, +0, 3690, 3944, +0, 3695, 3944, +0, 3703, 3944, +0, 3712, 3944, +0, 3725, 3944, +0, 3741, 3944, +0, 3762, 3944, +0, 3789, 3944, +0, 3822, 3944, +0, 3863, 3944, +0, 3912, 3944, +0, 3944, 3915, +0, 3944, 3823, +0, 3944, 3660, +0, 3944, 3271, +0, 4076, 0, +0, 4095, 0, +0, 3672, 3944, +0, 3672, 3944, +0, 3673, 3944, +0, 3673, 3944, +0, 3673, 3944, +0, 3673, 3944, +0, 3673, 3944, +0, 3674, 3944, +0, 3675, 3944, +0, 3675, 3944, +0, 3676, 3944, +0, 3678, 3944, +0, 3680, 3944, +0, 3682, 3944, +0, 3685, 3944, +0, 3689, 3944, +0, 3695, 3944, +0, 3702, 3944, +0, 3712, 3944, +0, 3725, 3944, +0, 3741, 3944, +0, 3762, 3944, +0, 3788, 3944, +0, 3822, 3944, +0, 3863, 3944, +0, 3912, 3944, +0, 3944, 3915, +0, 3944, 3823, +0, 3944, 3661, +0, 3944, 3271, +0, 4076, 0, +0, 4095, 0, +0, 3671, 3944, +0, 3671, 3944, +0, 3672, 3944, +0, 3672, 3944, +0, 3672, 3944, +0, 3672, 3944, +0, 3673, 3944, +0, 3673, 3944, +0, 3674, 3944, +0, 3675, 3944, +0, 3676, 3944, +0, 3677, 3944, +0, 3679, 3944, +0, 3681, 3944, +0, 3685, 3944, +0, 3689, 3944, +0, 3694, 3944, +0, 3702, 3944, +0, 3711, 3944, +0, 3724, 3944, +0, 3740, 3944, +0, 3761, 3944, +0, 3788, 3944, +0, 3821, 3944, +0, 3862, 3944, +0, 3912, 3944, +0, 3944, 3916, +0, 3944, 3824, +0, 3944, 3661, +0, 3944, 3272, +0, 4076, 0, +0, 4095, 0, +0, 3670, 3944, +0, 3671, 3944, +0, 3671, 3944, +0, 3671, 3944, +0, 3671, 3944, +0, 3671, 3944, +0, 3672, 3944, +0, 3672, 3944, +0, 3673, 3944, +0, 3674, 3944, +0, 3675, 3944, +0, 3676, 3944, +0, 3678, 3944, +0, 3680, 3944, +0, 3684, 3944, +0, 3688, 3944, +0, 3694, 3944, +0, 3701, 3944, +0, 3711, 3944, +0, 3723, 3944, +0, 3740, 3944, +0, 3761, 3944, +0, 3787, 3944, +0, 3820, 3944, +0, 3862, 3944, +0, 3911, 3944, +0, 3944, 3916, +0, 3944, 3824, +0, 3944, 3661, +0, 3944, 3273, +0, 4076, 0, +0, 4095, 0, +0, 3669, 3944, +0, 3669, 3944, +0, 3669, 3944, +0, 3669, 3944, +0, 3670, 3944, +0, 3670, 3944, +0, 3670, 3944, +0, 3671, 3944, +0, 3671, 3944, +0, 3673, 3944, +0, 3674, 3944, +0, 3675, 3944, +0, 3677, 3944, +0, 3679, 3944, +0, 3683, 3944, +0, 3687, 3944, +0, 3692, 3944, +0, 3700, 3944, +0, 3710, 3944, +0, 3722, 3944, +0, 3739, 3944, +0, 3760, 3944, +0, 3786, 3944, +0, 3820, 3944, +0, 3861, 3944, +0, 3910, 3944, +0, 3944, 3916, +0, 3944, 3824, +0, 3944, 3662, +0, 3944, 3275, +0, 4076, 0, +0, 4095, 0, +0, 3667, 3944, +0, 3667, 3944, +0, 3668, 3944, +0, 3668, 3944, +0, 3668, 3944, +0, 3668, 3944, +0, 3668, 3944, +0, 3669, 3944, +0, 3670, 3944, +0, 3671, 3944, +0, 3672, 3944, +0, 3673, 3944, +0, 3676, 3944, +0, 3678, 3944, +0, 3681, 3944, +0, 3685, 3944, +0, 3691, 3944, +0, 3699, 3944, +0, 3708, 3944, +0, 3721, 3944, +0, 3737, 3944, +0, 3758, 3944, +0, 3785, 3944, +0, 3819, 3944, +0, 3860, 3944, +0, 3910, 3944, +0, 3944, 3917, +0, 3944, 3825, +0, 3944, 3663, +0, 3944, 3277, +0, 4076, 0, +0, 4095, 0, +0, 3665, 3944, +0, 3665, 3944, +0, 3665, 3944, +0, 3665, 3944, +0, 3665, 3944, +0, 3666, 3944, +0, 3666, 3944, +0, 3666, 3944, +0, 3667, 3944, +0, 3668, 3944, +0, 3669, 3944, +0, 3671, 3944, +0, 3673, 3944, +0, 3676, 3943, +0, 3679, 3943, +0, 3683, 3943, +0, 3689, 3943, +0, 3697, 3943, +0, 3706, 3943, +0, 3719, 3943, +0, 3736, 3943, +0, 3757, 3943, +0, 3784, 3943, +0, 3817, 3943, +0, 3859, 3943, +0, 3909, 3943, +0, 3943, 3917, +0, 3943, 3826, +0, 3943, 3664, +0, 3943, 3279, +0, 4076, 0, +0, 4095, 0, +0, 3661, 3944, +0, 3662, 3944, +0, 3662, 3944, +0, 3662, 3944, +0, 3662, 3944, +0, 3662, 3944, +0, 3663, 3944, +0, 3663, 3944, +0, 3664, 3944, +0, 3665, 3944, +0, 3666, 3944, +0, 3668, 3944, +0, 3670, 3944, +0, 3673, 3943, +0, 3677, 3943, +0, 3681, 3943, +0, 3687, 3943, +0, 3694, 3943, +0, 3704, 3943, +0, 3717, 3943, +0, 3733, 3943, +0, 3755, 3943, +0, 3781, 3943, +0, 3815, 3943, +0, 3857, 3943, +0, 3907, 3943, +0, 3943, 3918, +0, 3943, 3827, +0, 3943, 3665, +0, 3943, 3283, +0, 4075, 0, +0, 4095, 0, +0, 3657, 3944, +0, 3657, 3944, +0, 3657, 3944, +0, 3657, 3944, +0, 3658, 3944, +0, 3658, 3944, +0, 3658, 3944, +0, 3659, 3944, +0, 3659, 3944, +0, 3661, 3944, +0, 3662, 3944, +0, 3663, 3944, +0, 3666, 3944, +0, 3668, 3943, +0, 3672, 3943, +0, 3677, 3943, +0, 3683, 3943, +0, 3691, 3943, +0, 3701, 3943, +0, 3713, 3943, +0, 3730, 3943, +0, 3752, 3943, +0, 3779, 3943, +0, 3813, 3943, +0, 3854, 3943, +0, 3905, 3943, +0, 3943, 3920, +0, 3943, 3828, +0, 3943, 3667, +0, 3943, 3287, +0, 4075, 0, +0, 4095, 0, +0, 3651, 3944, +0, 3651, 3944, +0, 3651, 3944, +0, 3651, 3944, +0, 3652, 3944, +0, 3652, 3944, +0, 3652, 3944, +0, 3653, 3944, +0, 3653, 3944, +0, 3654, 3944, +0, 3656, 3944, +0, 3657, 3944, +0, 3659, 3944, +0, 3662, 3943, +0, 3666, 3943, +0, 3672, 3943, +0, 3679, 3942, +0, 3686, 3942, +0, 3696, 3942, +0, 3709, 3942, +0, 3726, 3942, +0, 3748, 3942, +0, 3775, 3942, +0, 3809, 3942, +0, 3851, 3942, +0, 3902, 3942, +0, 3942, 3921, +0, 3942, 3830, +0, 3942, 3670, +0, 3942, 3293, +0, 4075, 0, +0, 4095, 0, +0, 3643, 3944, +0, 3643, 3944, +0, 3643, 3944, +0, 3643, 3944, +0, 3643, 3944, +0, 3644, 3944, +0, 3644, 3944, +0, 3645, 3944, +0, 3645, 3944, +0, 3646, 3944, +0, 3648, 3944, +0, 3649, 3944, +0, 3651, 3944, +0, 3655, 3943, +0, 3659, 3943, +0, 3664, 3943, +0, 3671, 3942, +0, 3680, 3941, +0, 3690, 3941, +0, 3703, 3941, +0, 3720, 3941, +0, 3742, 3941, +0, 3770, 3941, +0, 3805, 3941, +0, 3847, 3941, +0, 3898, 3941, +0, 3941, 3923, +0, 3941, 3832, +0, 3941, 3674, +0, 3941, 3302, +0, 4074, 0, +0, 4095, 0, +0, 3631, 3944, +0, 3632, 3944, +0, 3632, 3944, +0, 3632, 3944, +0, 3632, 3944, +0, 3632, 3944, +0, 3633, 3944, +0, 3633, 3944, +0, 3634, 3944, +0, 3635, 3944, +0, 3636, 3944, +0, 3638, 3944, +0, 3640, 3944, +0, 3644, 3943, +0, 3648, 3943, +0, 3653, 3943, +0, 3660, 3942, +0, 3669, 3941, +0, 3682, 3940, +0, 3695, 3940, +0, 3713, 3940, +0, 3735, 3940, +0, 3763, 3940, +0, 3798, 3940, +0, 3841, 3940, +0, 3893, 3940, +0, 3940, 3926, +0, 3940, 3836, +0, 3940, 3678, +0, 3940, 3312, +0, 4073, 0, +0, 4095, 0, +0, 3616, 3944, +0, 3616, 3944, +0, 3616, 3944, +0, 3616, 3944, +0, 3617, 3944, +0, 3617, 3944, +0, 3617, 3944, +0, 3618, 3944, +0, 3619, 3944, +0, 3620, 3944, +0, 3621, 3944, +0, 3623, 3944, +0, 3625, 3944, +0, 3628, 3943, +0, 3632, 3943, +0, 3638, 3943, +0, 3646, 3942, +0, 3655, 3941, +0, 3668, 3940, +0, 3684, 3939, +0, 3702, 3939, +0, 3725, 3939, +0, 3754, 3939, +0, 3790, 3939, +0, 3833, 3939, +0, 3886, 3939, +0, 3939, 3929, +0, 3939, 3840, +0, 3939, 3685, +0, 3939, 3326, +0, 4072, 0, +0, 4095, 0, +0, 3594, 3944, +0, 3595, 3944, +0, 3595, 3944, +0, 3595, 3944, +0, 3595, 3944, +0, 3595, 3944, +0, 3596, 3944, +0, 3596, 3944, +0, 3597, 3944, +0, 3598, 3944, +0, 3600, 3944, +0, 3602, 3944, +0, 3604, 3944, +0, 3607, 3943, +0, 3612, 3943, +0, 3618, 3943, +0, 3626, 3942, +0, 3635, 3941, +0, 3649, 3940, +0, 3666, 3939, +0, 3688, 3937, +0, 3711, 3937, +0, 3741, 3937, +0, 3777, 3937, +0, 3822, 3937, +0, 3876, 3937, +0, 3937, 3934, +0, 3937, 3846, +0, 3937, 3692, +0, 3937, 3344, +0, 4071, 0, +0, 4095, 0, +0, 3564, 3944, +0, 3564, 3944, +0, 3564, 3944, +0, 3564, 3944, +0, 3564, 3944, +0, 3565, 3944, +0, 3565, 3944, +0, 3566, 3944, +0, 3567, 3944, +0, 3568, 3944, +0, 3569, 3944, +0, 3571, 3944, +0, 3574, 3944, +0, 3578, 3943, +0, 3583, 3943, +0, 3589, 3943, +0, 3597, 3942, +0, 3608, 3941, +0, 3622, 3940, +0, 3640, 3939, +0, 3663, 3937, +0, 3692, 3934, +0, 3723, 3934, +0, 3761, 3934, +0, 3808, 3934, +0, 3863, 3934, +0, 3928, 3934, +0, 3934, 3853, +0, 3934, 3703, +0, 3934, 3366, +0, 4069, 0, +0, 4095, 0, +0, 3520, 3944, +0, 3520, 3944, +0, 3520, 3944, +0, 3520, 3944, +0, 3520, 3944, +0, 3521, 3944, +0, 3521, 3944, +0, 3522, 3944, +0, 3523, 3944, +0, 3524, 3944, +0, 3526, 3944, +0, 3528, 3944, +0, 3531, 3944, +0, 3535, 3943, +0, 3540, 3943, +0, 3547, 3943, +0, 3556, 3942, +0, 3568, 3941, +0, 3583, 3940, +0, 3603, 3939, +0, 3628, 3937, +0, 3659, 3934, +0, 3698, 3931, +0, 3738, 3931, +0, 3787, 3931, +0, 3845, 3931, +0, 3913, 3931, +0, 3931, 3863, +0, 3931, 3717, +0, 3931, 3395, +0, 4066, 0, +0, 4095, 0, +0, 3452, 3944, +0, 3452, 3944, +0, 3453, 3944, +0, 3453, 3944, +0, 3453, 3944, +0, 3454, 3944, +0, 3454, 3944, +0, 3455, 3944, +0, 3456, 3944, +0, 3458, 3944, +0, 3459, 3944, +0, 3462, 3944, +0, 3466, 3944, +0, 3470, 3943, +0, 3476, 3943, +0, 3484, 3943, +0, 3494, 3942, +0, 3507, 3941, +0, 3525, 3940, +0, 3547, 3939, +0, 3575, 3937, +0, 3611, 3934, +0, 3654, 3931, +0, 3706, 3926, +0, 3758, 3926, +0, 3820, 3926, +0, 3891, 3926, +0, 3926, 3877, +0, 3926, 3735, +0, 3926, 3430, +0, 4063, 0, +2137, 4095, 0, +0, 3344, 3944, +0, 3344, 3944, +0, 3344, 3944, +0, 3344, 3944, +0, 3345, 3944, +0, 3346, 3944, +0, 3346, 3944, +0, 3347, 3944, +0, 3349, 3944, +0, 3351, 3944, +0, 3353, 3944, +0, 3356, 3944, +0, 3361, 3944, +0, 3366, 3943, +0, 3374, 3943, +0, 3384, 3943, +0, 3396, 3942, +0, 3413, 3941, +0, 3434, 3940, +0, 3461, 3939, +0, 3495, 3937, +0, 3537, 3934, +0, 3587, 3931, +0, 3647, 3926, +1928, 3716, 3920, +1928, 3783, 3920, +1928, 3860, 3920, +1928, 3920, 3893, +1928, 3920, 3758, +1928, 3920, 3474, +0, 4058, 2157, +2915, 4095, 0, +0, 3140, 3944, +0, 3140, 3944, +0, 3140, 3944, +0, 3141, 3944, +0, 3142, 3944, +0, 3143, 3944, +0, 3144, 3944, +0, 3145, 3944, +0, 3147, 3944, +0, 3151, 3944, +0, 3154, 3944, +0, 3159, 3944, +0, 3166, 3944, +0, 3175, 3943, +0, 3186, 3943, +0, 3201, 3943, +0, 3220, 3942, +0, 3244, 3941, +0, 3275, 3940, +0, 3313, 3939, +0, 3359, 3937, +0, 3414, 3934, +0, 3479, 3931, +0, 3553, 3926, +1928, 3637, 3920, +2854, 3729, 3912, +2854, 3814, 3912, +2854, 3908, 3912, +2854, 3912, 3787, +2854, 3912, 3526, +2063, 4052, 2689, +3253, 4095, 0, +0, 2497, 3944, +0, 2498, 3944, +0, 2500, 3944, +0, 2502, 3944, +0, 2505, 3944, +0, 2508, 3944, +0, 2513, 3944, +0, 2520, 3944, +0, 2528, 3944, +0, 2539, 3944, +0, 2553, 3944, +0, 2572, 3944, +0, 2596, 3944, +0, 2625, 3943, +0, 2662, 3943, +0, 2708, 3943, +0, 2762, 3942, +0, 2826, 3941, +0, 2899, 3940, +0, 2982, 3939, +0, 3073, 3937, +0, 3172, 3934, +0, 3277, 3931, +0, 3388, 3926, +1928, 3504, 3920, +2854, 3624, 3912, +3204, 3746, 3900, +3204, 3853, 3900, +3204, 3900, 3822, +3204, 3900, 3588, +2987, 4044, 2986, +3494, 4095, 2192, +0, 0, 3944, +0, 0, 3944, +0, 0, 3944, +0, 0, 3944, +0, 0, 3944, +0, 0, 3944, +0, 0, 3944, +0, 0, 3944, +0, 0, 3944, +0, 0, 3944, +0, 0, 3944, +0, 0, 3944, +0, 0, 3944, +0, 0, 3943, +0, 0, 3943, +0, 0, 3943, +0, 0, 3942, +0, 0, 3941, +0, 0, 3940, +0, 0, 3939, +0, 0, 3937, +0, 1863, 3934, +0, 2650, 3931, +0, 2988, 3926, +1928, 3229, 3920, +2854, 3428, 3912, +3204, 3605, 3900, +3450, 3768, 3884, +3450, 3884, 3867, +3450, 3884, 3660, +3435, 4032, 3336, +3693, 4095, 3118, +0, 0, 3944, +0, 0, 3944, +0, 0, 3944, +0, 0, 3944, +0, 0, 3944, +0, 0, 3944, +0, 0, 3944, +0, 0, 3944, +0, 0, 3944, +0, 0, 3944, +0, 0, 3944, +0, 0, 3944, +0, 0, 3944, +0, 0, 3943, +0, 0, 3943, +0, 0, 3943, +0, 0, 3942, +0, 0, 3941, +0, 0, 3940, +0, 0, 3939, +0, 0, 3937, +0, 0, 3934, +0, 0, 3931, +2023, 0, 3926, +2556, 1928, 3920, +2854, 2854, 3912, +3204, 3302, 3900, +3450, 3579, 3884, +3652, 3796, 3862, +3652, 3862, 3741, +3711, 4016, 3583, +3869, 4095, 3469, +3269, 0, 3944, +3269, 0, 3944, +3269, 0, 3944, +3269, 0, 3944, +3270, 0, 3944, +3270, 0, 3944, +3270, 0, 3944, +3271, 0, 3944, +3271, 0, 3944, +3272, 0, 3944, +3273, 0, 3944, +3275, 0, 3944, +3277, 0, 3944, +3279, 0, 3943, +3283, 0, 3943, +3287, 0, 3943, +3293, 0, 3942, +3302, 0, 3941, +3312, 0, 3940, +3326, 0, 3939, +3344, 0, 3937, +3366, 0, 3934, +3395, 0, 3931, +3430, 0, 3926, +3474, 1928, 3920, +3526, 2854, 3912, +3588, 3204, 3900, +3660, 3450, 3884, +3741, 3652, 3862, +3830, 3830, 3830, +3928, 3994, 3784, +4032, 4095, 3714, +3791, 0, 4076, +3792, 0, 4076, +3792, 0, 4076, +3792, 0, 4076, +3792, 0, 4076, +3792, 0, 4076, +3792, 0, 4076, +3792, 0, 4076, +3792, 0, 4076, +3793, 0, 4076, +3793, 0, 4076, +3793, 0, 4076, +3794, 0, 4076, +3795, 0, 4076, +3796, 0, 4075, +3797, 0, 4075, +3799, 0, 4075, +3802, 0, 4074, +3805, 0, 4073, +3810, 0, 4072, +3816, 0, 4071, +3824, 0, 4069, +3835, 0, 4066, +3849, 0, 4063, +3867, 0, 4058, +3890, 2063, 4052, +3919, 2986, 4044, +3955, 3336, 4032, +3999, 3583, 4016, +3994, 3784, 3928, +3994, 3873, 3784, +4095, 4095, 3714, +4087, 0, 4095, +4087, 0, 4095, +4087, 0, 4095, +4087, 0, 4095, +4087, 0, 4095, +4087, 0, 4095, +4087, 0, 4095, +4087, 0, 4095, +4087, 0, 4095, +4088, 0, 4095, +4088, 0, 4095, +4088, 0, 4095, +4088, 0, 4095, +4089, 0, 4095, +4089, 0, 4095, +4090, 0, 4095, +4091, 0, 4095, +4092, 0, 4095, +4094, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 2192, 4095, +4095, 3118, 4095, +4095, 3469, 4095, +4095, 3714, 4032, +4095, 3714, 3844, +4095, 3924, 3714, +0, 3806, 4076, +0, 3806, 4076, +0, 3806, 4076, +0, 3806, 4076, +0, 3807, 4076, +0, 3807, 4076, +0, 3807, 4076, +0, 3808, 4076, +0, 3808, 4076, +0, 3808, 4076, +0, 3809, 4076, +0, 3810, 4076, +0, 3812, 4076, +0, 3813, 4076, +0, 3816, 4076, +0, 3819, 4076, +0, 3823, 4076, +0, 3828, 4076, +0, 3836, 4076, +0, 3846, 4076, +0, 3858, 4076, +0, 3874, 4076, +0, 3895, 4076, +0, 3922, 4076, +0, 3955, 4076, +0, 3996, 4076, +0, 4045, 4076, +0, 4076, 4047, +0, 4076, 3954, +0, 4076, 3791, +0, 4076, 3401, +0, 4095, 0, +0, 3806, 4076, +0, 3806, 4076, +0, 3806, 4076, +0, 3806, 4076, +0, 3807, 4076, +0, 3807, 4076, +0, 3807, 4076, +0, 3807, 4076, +0, 3808, 4076, +0, 3808, 4076, +0, 3809, 4076, +0, 3810, 4076, +0, 3811, 4076, +0, 3813, 4076, +0, 3816, 4076, +0, 3819, 4076, +0, 3823, 4076, +0, 3828, 4076, +0, 3836, 4076, +0, 3845, 4076, +0, 3858, 4076, +0, 3874, 4076, +0, 3895, 4076, +0, 3922, 4076, +0, 3955, 4076, +0, 3996, 4076, +0, 4045, 4076, +0, 4076, 4047, +0, 4076, 3954, +0, 4076, 3792, +0, 4076, 3401, +0, 4095, 0, +0, 3806, 4076, +0, 3806, 4076, +0, 3806, 4076, +0, 3806, 4076, +0, 3807, 4076, +0, 3807, 4076, +0, 3807, 4076, +0, 3807, 4076, +0, 3808, 4076, +0, 3808, 4076, +0, 3809, 4076, +0, 3810, 4076, +0, 3811, 4076, +0, 3813, 4076, +0, 3816, 4076, +0, 3819, 4076, +0, 3823, 4076, +0, 3828, 4076, +0, 3836, 4076, +0, 3845, 4076, +0, 3858, 4076, +0, 3874, 4076, +0, 3895, 4076, +0, 3921, 4076, +0, 3955, 4076, +0, 3996, 4076, +0, 4045, 4076, +0, 4076, 4047, +0, 4076, 3954, +0, 4076, 3792, +0, 4076, 3401, +0, 4095, 0, +0, 3806, 4076, +0, 3806, 4076, +0, 3806, 4076, +0, 3806, 4076, +0, 3806, 4076, +0, 3807, 4076, +0, 3807, 4076, +0, 3807, 4076, +0, 3808, 4076, +0, 3808, 4076, +0, 3809, 4076, +0, 3810, 4076, +0, 3811, 4076, +0, 3813, 4076, +0, 3815, 4076, +0, 3818, 4076, +0, 3823, 4076, +0, 3828, 4076, +0, 3836, 4076, +0, 3845, 4076, +0, 3858, 4076, +0, 3874, 4076, +0, 3895, 4076, +0, 3921, 4076, +0, 3955, 4076, +0, 3995, 4076, +0, 4045, 4076, +0, 4076, 4047, +0, 4076, 3954, +0, 4076, 3792, +0, 4076, 3401, +0, 4095, 0, +0, 3806, 4076, +0, 3806, 4076, +0, 3806, 4076, +0, 3806, 4076, +0, 3806, 4076, +0, 3807, 4076, +0, 3807, 4076, +0, 3807, 4076, +0, 3808, 4076, +0, 3808, 4076, +0, 3809, 4076, +0, 3810, 4076, +0, 3811, 4076, +0, 3813, 4076, +0, 3815, 4076, +0, 3818, 4076, +0, 3823, 4076, +0, 3828, 4076, +0, 3836, 4076, +0, 3845, 4076, +0, 3858, 4076, +0, 3874, 4076, +0, 3895, 4076, +0, 3921, 4076, +0, 3955, 4076, +0, 3995, 4076, +0, 4045, 4076, +0, 4076, 4047, +0, 4076, 3955, +0, 4076, 3792, +0, 4076, 3401, +0, 4095, 0, +0, 3806, 4076, +0, 3806, 4076, +0, 3806, 4076, +0, 3806, 4076, +0, 3806, 4076, +0, 3806, 4076, +0, 3807, 4076, +0, 3807, 4076, +0, 3808, 4076, +0, 3808, 4076, +0, 3809, 4076, +0, 3810, 4076, +0, 3811, 4076, +0, 3813, 4076, +0, 3815, 4076, +0, 3818, 4076, +0, 3822, 4076, +0, 3828, 4076, +0, 3835, 4076, +0, 3845, 4076, +0, 3858, 4076, +0, 3874, 4076, +0, 3895, 4076, +0, 3921, 4076, +0, 3954, 4076, +0, 3995, 4076, +0, 4045, 4076, +0, 4076, 4047, +0, 4076, 3955, +0, 4076, 3792, +0, 4076, 3402, +0, 4095, 0, +0, 3805, 4076, +0, 3805, 4076, +0, 3805, 4076, +0, 3806, 4076, +0, 3806, 4076, +0, 3806, 4076, +0, 3806, 4076, +0, 3807, 4076, +0, 3807, 4076, +0, 3808, 4076, +0, 3808, 4076, +0, 3810, 4076, +0, 3811, 4076, +0, 3812, 4076, +0, 3815, 4076, +0, 3818, 4076, +0, 3822, 4076, +0, 3828, 4076, +0, 3835, 4076, +0, 3845, 4076, +0, 3858, 4076, +0, 3874, 4076, +0, 3895, 4076, +0, 3921, 4076, +0, 3954, 4076, +0, 3995, 4076, +0, 4045, 4076, +0, 4076, 4047, +0, 4076, 3955, +0, 4076, 3792, +0, 4076, 3402, +0, 4095, 0, +0, 3805, 4076, +0, 3805, 4076, +0, 3805, 4076, +0, 3805, 4076, +0, 3805, 4076, +0, 3806, 4076, +0, 3806, 4076, +0, 3806, 4076, +0, 3807, 4076, +0, 3808, 4076, +0, 3808, 4076, +0, 3809, 4076, +0, 3810, 4076, +0, 3812, 4076, +0, 3815, 4076, +0, 3818, 4076, +0, 3822, 4076, +0, 3828, 4076, +0, 3835, 4076, +0, 3845, 4076, +0, 3857, 4076, +0, 3873, 4076, +0, 3895, 4076, +0, 3921, 4076, +0, 3954, 4076, +0, 3995, 4076, +0, 4045, 4076, +0, 4076, 4047, +0, 4076, 3955, +0, 4076, 3792, +0, 4076, 3402, +0, 4095, 0, +0, 3805, 4076, +0, 3805, 4076, +0, 3805, 4076, +0, 3805, 4076, +0, 3805, 4076, +0, 3805, 4076, +0, 3805, 4076, +0, 3806, 4076, +0, 3807, 4076, +0, 3807, 4076, +0, 3808, 4076, +0, 3809, 4076, +0, 3810, 4076, +0, 3812, 4076, +0, 3814, 4076, +0, 3818, 4076, +0, 3822, 4076, +0, 3827, 4076, +0, 3835, 4076, +0, 3845, 4076, +0, 3857, 4076, +0, 3873, 4076, +0, 3894, 4076, +0, 3921, 4076, +0, 3954, 4076, +0, 3995, 4076, +0, 4044, 4076, +0, 4076, 4047, +0, 4076, 3955, +0, 4076, 3792, +0, 4076, 3403, +0, 4095, 0, +0, 3804, 4076, +0, 3804, 4076, +0, 3804, 4076, +0, 3805, 4076, +0, 3805, 4076, +0, 3805, 4076, +0, 3805, 4076, +0, 3805, 4076, +0, 3806, 4076, +0, 3807, 4076, +0, 3808, 4076, +0, 3808, 4076, +0, 3810, 4076, +0, 3812, 4076, +0, 3814, 4076, +0, 3817, 4076, +0, 3821, 4076, +0, 3827, 4076, +0, 3834, 4076, +0, 3844, 4076, +0, 3856, 4076, +0, 3873, 4076, +0, 3894, 4076, +0, 3921, 4076, +0, 3953, 4076, +0, 3995, 4076, +0, 4044, 4076, +0, 4076, 4047, +0, 4076, 3955, +0, 4076, 3793, +0, 4076, 3403, +0, 4095, 0, +0, 3803, 4076, +0, 3803, 4076, +0, 3803, 4076, +0, 3804, 4076, +0, 3804, 4076, +0, 3804, 4076, +0, 3804, 4076, +0, 3805, 4076, +0, 3805, 4076, +0, 3806, 4076, +0, 3807, 4076, +0, 3808, 4076, +0, 3809, 4076, +0, 3811, 4076, +0, 3813, 4076, +0, 3816, 4076, +0, 3821, 4076, +0, 3826, 4076, +0, 3834, 4076, +0, 3843, 4076, +0, 3856, 4076, +0, 3872, 4076, +0, 3893, 4076, +0, 3920, 4076, +0, 3953, 4076, +0, 3994, 4076, +0, 4044, 4076, +0, 4076, 4048, +0, 4076, 3955, +0, 4076, 3793, +0, 4076, 3404, +0, 4095, 0, +0, 3803, 4076, +0, 3803, 4076, +0, 3803, 4076, +0, 3803, 4076, +0, 3803, 4076, +0, 3803, 4076, +0, 3803, 4076, +0, 3804, 4076, +0, 3804, 4076, +0, 3805, 4076, +0, 3806, 4076, +0, 3807, 4076, +0, 3808, 4076, +0, 3810, 4076, +0, 3812, 4076, +0, 3816, 4076, +0, 3820, 4076, +0, 3826, 4076, +0, 3833, 4076, +0, 3843, 4076, +0, 3855, 4076, +0, 3872, 4076, +0, 3892, 4076, +0, 3919, 4076, +0, 3953, 4076, +0, 3994, 4076, +0, 4043, 4076, +0, 4076, 4048, +0, 4076, 3956, +0, 4076, 3793, +0, 4076, 3405, +0, 4095, 0, +0, 3801, 4076, +0, 3801, 4076, +0, 3801, 4076, +0, 3801, 4076, +0, 3801, 4076, +0, 3802, 4076, +0, 3802, 4076, +0, 3802, 4076, +0, 3803, 4076, +0, 3803, 4076, +0, 3804, 4076, +0, 3805, 4076, +0, 3807, 4076, +0, 3809, 4076, +0, 3812, 4076, +0, 3814, 4076, +0, 3819, 4076, +0, 3824, 4076, +0, 3832, 4076, +0, 3841, 4076, +0, 3854, 4076, +0, 3871, 4076, +0, 3891, 4076, +0, 3918, 4076, +0, 3952, 4076, +0, 3993, 4076, +0, 4043, 4076, +0, 4076, 4048, +0, 4076, 3956, +0, 4076, 3794, +0, 4076, 3407, +0, 4095, 0, +0, 3799, 4076, +0, 3799, 4076, +0, 3799, 4076, +0, 3799, 4076, +0, 3800, 4076, +0, 3800, 4076, +0, 3800, 4076, +0, 3801, 4076, +0, 3801, 4076, +0, 3802, 4076, +0, 3803, 4076, +0, 3804, 4076, +0, 3805, 4076, +0, 3808, 4076, +0, 3810, 4076, +0, 3813, 4076, +0, 3817, 4076, +0, 3823, 4076, +0, 3830, 4076, +0, 3840, 4076, +0, 3853, 4076, +0, 3869, 4076, +0, 3890, 4076, +0, 3917, 4076, +0, 3950, 4076, +0, 3992, 4076, +0, 4042, 4076, +0, 4076, 4049, +0, 4076, 3957, +0, 4076, 3795, +0, 4076, 3409, +0, 4095, 0, +0, 3797, 4076, +0, 3797, 4076, +0, 3797, 4076, +0, 3797, 4076, +0, 3797, 4076, +0, 3797, 4076, +0, 3798, 4076, +0, 3798, 4076, +0, 3798, 4076, +0, 3799, 4076, +0, 3800, 4076, +0, 3801, 4076, +0, 3803, 4076, +0, 3805, 4076, +0, 3808, 4075, +0, 3811, 4075, +0, 3816, 4075, +0, 3821, 4075, +0, 3829, 4075, +0, 3838, 4075, +0, 3851, 4075, +0, 3868, 4075, +0, 3889, 4075, +0, 3916, 4075, +0, 3949, 4075, +0, 3991, 4075, +0, 4041, 4075, +0, 4075, 4049, +0, 4075, 3958, +0, 4075, 3796, +0, 4075, 3411, +0, 4095, 0, +0, 3793, 4076, +0, 3793, 4076, +0, 3793, 4076, +0, 3794, 4076, +0, 3794, 4076, +0, 3794, 4076, +0, 3794, 4076, +0, 3795, 4076, +0, 3795, 4076, +0, 3796, 4076, +0, 3797, 4076, +0, 3798, 4076, +0, 3800, 4076, +0, 3802, 4076, +0, 3805, 4075, +0, 3809, 4075, +0, 3813, 4075, +0, 3818, 4075, +0, 3826, 4075, +0, 3836, 4075, +0, 3849, 4075, +0, 3865, 4075, +0, 3887, 4075, +0, 3913, 4075, +0, 3947, 4075, +0, 3989, 4075, +0, 4039, 4075, +0, 4075, 4050, +0, 4075, 3959, +0, 4075, 3797, +0, 4075, 3415, +0, 4095, 0, +0, 3789, 4076, +0, 3789, 4076, +0, 3789, 4076, +0, 3789, 4076, +0, 3790, 4076, +0, 3790, 4076, +0, 3790, 4076, +0, 3790, 4076, +0, 3791, 4076, +0, 3791, 4076, +0, 3793, 4076, +0, 3794, 4076, +0, 3795, 4076, +0, 3798, 4076, +0, 3801, 4075, +0, 3804, 4075, +0, 3810, 4075, +0, 3815, 4075, +0, 3823, 4075, +0, 3833, 4075, +0, 3846, 4075, +0, 3862, 4075, +0, 3884, 4075, +0, 3911, 4075, +0, 3945, 4075, +0, 3986, 4075, +0, 4037, 4075, +0, 4075, 4051, +0, 4075, 3960, +0, 4075, 3799, +0, 4075, 3419, +0, 4095, 0, +0, 3783, 4076, +0, 3783, 4076, +0, 3783, 4076, +0, 3783, 4076, +0, 3783, 4076, +0, 3784, 4076, +0, 3784, 4076, +0, 3784, 4076, +0, 3785, 4076, +0, 3785, 4076, +0, 3787, 4076, +0, 3787, 4076, +0, 3789, 4076, +0, 3792, 4076, +0, 3795, 4075, +0, 3798, 4075, +0, 3803, 4075, +0, 3810, 4074, +0, 3818, 4074, +0, 3828, 4074, +0, 3841, 4074, +0, 3858, 4074, +0, 3880, 4074, +0, 3907, 4074, +0, 3941, 4074, +0, 3983, 4074, +0, 4034, 4074, +0, 4074, 4053, +0, 4074, 3962, +0, 4074, 3802, +0, 4074, 3426, +0, 4095, 0, +0, 3774, 4076, +0, 3775, 4076, +0, 3775, 4076, +0, 3775, 4076, +0, 3775, 4076, +0, 3775, 4076, +0, 3776, 4076, +0, 3776, 4076, +0, 3777, 4076, +0, 3777, 4076, +0, 3778, 4076, +0, 3780, 4076, +0, 3781, 4076, +0, 3784, 4076, +0, 3787, 4075, +0, 3790, 4075, +0, 3796, 4075, +0, 3803, 4074, +0, 3812, 4073, +0, 3822, 4073, +0, 3835, 4073, +0, 3852, 4073, +0, 3874, 4073, +0, 3902, 4073, +0, 3937, 4073, +0, 3979, 4073, +0, 4030, 4073, +0, 4073, 4055, +0, 4073, 3964, +0, 4073, 3805, +0, 4073, 3434, +0, 4095, 0, +0, 3763, 4076, +0, 3763, 4076, +0, 3763, 4076, +0, 3764, 4076, +0, 3764, 4076, +0, 3764, 4076, +0, 3764, 4076, +0, 3765, 4076, +0, 3765, 4076, +0, 3766, 4076, +0, 3767, 4076, +0, 3768, 4076, +0, 3770, 4076, +0, 3773, 4076, +0, 3776, 4075, +0, 3780, 4075, +0, 3785, 4075, +0, 3792, 4074, +0, 3801, 4073, +0, 3814, 4072, +0, 3827, 4072, +0, 3845, 4072, +0, 3867, 4072, +0, 3895, 4072, +0, 3930, 4072, +0, 3973, 4072, +0, 4025, 4072, +0, 4072, 4058, +0, 4072, 3968, +0, 4072, 3810, +0, 4072, 3444, +0, 4095, 0, +0, 3748, 4076, +0, 3748, 4076, +0, 3748, 4076, +0, 3748, 4076, +0, 3748, 4076, +0, 3749, 4076, +0, 3749, 4076, +0, 3749, 4076, +0, 3750, 4076, +0, 3751, 4076, +0, 3752, 4076, +0, 3753, 4076, +0, 3755, 4076, +0, 3757, 4076, +0, 3760, 4075, +0, 3765, 4075, +0, 3770, 4075, +0, 3777, 4074, +0, 3787, 4073, +0, 3800, 4072, +0, 3816, 4071, +0, 3834, 4071, +0, 3857, 4071, +0, 3886, 4071, +0, 3921, 4071, +0, 3965, 4071, +0, 4018, 4071, +0, 4071, 4061, +0, 4071, 3972, +0, 4071, 3816, +0, 4071, 3458, +0, 4095, 0, +0, 3726, 4076, +0, 3726, 4076, +0, 3726, 4076, +0, 3727, 4076, +0, 3727, 4076, +0, 3727, 4076, +0, 3727, 4076, +0, 3728, 4076, +0, 3728, 4076, +0, 3729, 4076, +0, 3730, 4076, +0, 3732, 4076, +0, 3734, 4076, +0, 3736, 4076, +0, 3739, 4075, +0, 3744, 4075, +0, 3750, 4075, +0, 3757, 4074, +0, 3768, 4073, +0, 3781, 4072, +0, 3798, 4071, +0, 3820, 4069, +0, 3843, 4069, +0, 3873, 4069, +0, 3910, 4069, +0, 3954, 4069, +0, 4008, 4069, +0, 4069, 4066, +0, 4069, 3978, +0, 4069, 3824, +0, 4069, 3475, +0, 4095, 0, +0, 3696, 4076, +0, 3696, 4076, +0, 3696, 4076, +0, 3696, 4076, +0, 3696, 4076, +0, 3696, 4076, +0, 3697, 4076, +0, 3697, 4076, +0, 3698, 4076, +0, 3699, 4076, +0, 3700, 4076, +0, 3701, 4076, +0, 3703, 4076, +0, 3706, 4076, +0, 3710, 4075, +0, 3714, 4075, +0, 3721, 4075, +0, 3729, 4074, +0, 3740, 4073, +0, 3754, 4072, +0, 3772, 4071, +0, 3795, 4069, +0, 3824, 4066, +0, 3855, 4066, +0, 3893, 4066, +0, 3940, 4066, +0, 3995, 4066, +0, 4060, 4066, +0, 4066, 3985, +0, 4066, 3835, +0, 4066, 3498, +0, 4095, 0, +0, 3651, 4076, +0, 3651, 4076, +0, 3651, 4076, +0, 3652, 4076, +0, 3652, 4076, +0, 3652, 4076, +0, 3653, 4076, +0, 3653, 4076, +0, 3654, 4076, +0, 3655, 4076, +0, 3656, 4076, +0, 3658, 4076, +0, 3660, 4076, +0, 3663, 4076, +0, 3667, 4075, +0, 3672, 4075, +0, 3679, 4075, +0, 3688, 4074, +0, 3700, 4073, +0, 3715, 4072, +0, 3735, 4071, +0, 3760, 4069, +0, 3791, 4066, +0, 3830, 4063, +0, 3870, 4063, +0, 3919, 4063, +0, 3977, 4063, +0, 4045, 4063, +0, 4063, 3995, +0, 4063, 3849, +0, 4063, 3527, +0, 4095, 0, +0, 3584, 4076, +0, 3584, 4076, +0, 3585, 4076, +0, 3585, 4076, +0, 3585, 4076, +0, 3585, 4076, +0, 3586, 4076, +0, 3586, 4076, +0, 3587, 4076, +0, 3588, 4076, +0, 3590, 4076, +0, 3592, 4076, +0, 3594, 4076, +0, 3597, 4076, +0, 3602, 4075, +0, 3608, 4075, +0, 3616, 4075, +0, 3626, 4074, +0, 3640, 4073, +0, 3657, 4072, +0, 3679, 4071, +0, 3708, 4069, +0, 3743, 4066, +0, 3786, 4063, +0, 3838, 4058, +0, 3890, 4058, +0, 3952, 4058, +0, 4023, 4058, +0, 4058, 4008, +0, 4058, 3867, +0, 4058, 3562, +0, 4095, 0, +0, 3475, 4076, +0, 3475, 4076, +0, 3476, 4076, +0, 3476, 4076, +0, 3476, 4076, +0, 3477, 4076, +0, 3477, 4076, +0, 3478, 4076, +0, 3479, 4076, +0, 3480, 4076, +0, 3482, 4076, +0, 3485, 4076, +0, 3488, 4076, +0, 3492, 4076, +0, 3498, 4075, +0, 3505, 4075, +0, 3515, 4075, +0, 3528, 4074, +0, 3545, 4073, +0, 3566, 4072, +0, 3593, 4071, +0, 3627, 4069, +0, 3669, 4066, +0, 3719, 4063, +0, 3779, 4058, +2063, 3848, 4052, +2063, 3915, 4052, +2063, 3992, 4052, +2063, 4052, 4025, +2063, 4052, 3890, +2063, 4052, 3606, +0, 4095, 2266, +0, 3271, 4076, +0, 3272, 4076, +0, 3272, 4076, +0, 3272, 4076, +0, 3273, 4076, +0, 3273, 4076, +0, 3274, 4076, +0, 3276, 4076, +0, 3277, 4076, +0, 3279, 4076, +0, 3282, 4076, +0, 3286, 4076, +0, 3291, 4076, +0, 3297, 4076, +0, 3306, 4075, +0, 3318, 4075, +0, 3333, 4075, +0, 3351, 4074, +0, 3376, 4073, +0, 3407, 4072, +0, 3445, 4071, +0, 3491, 4069, +0, 3546, 4066, +0, 3611, 4063, +0, 3685, 4058, +2063, 3769, 4052, +2986, 3861, 4044, +2986, 3947, 4044, +2986, 4040, 4044, +2986, 4044, 3919, +2986, 4044, 3659, +2192, 4095, 2814, +0, 2626, 4076, +0, 2627, 4076, +0, 2628, 4076, +0, 2630, 4076, +0, 2632, 4076, +0, 2635, 4076, +0, 2639, 4076, +0, 2644, 4076, +0, 2650, 4076, +0, 2659, 4076, +0, 2670, 4076, +0, 2684, 4076, +0, 2703, 4076, +0, 2726, 4076, +0, 2756, 4075, +0, 2793, 4075, +0, 2839, 4075, +0, 2893, 4074, +0, 2957, 4073, +0, 3031, 4072, +0, 3113, 4071, +0, 3205, 4069, +0, 3303, 4066, +0, 3409, 4063, +0, 3520, 4058, +2063, 3636, 4052, +2986, 3755, 4044, +3336, 3878, 4032, +3336, 3986, 4032, +3336, 4032, 3955, +3336, 4032, 3720, +3121, 4095, 3118, +0, 0, 4076, +0, 0, 4076, +0, 0, 4076, +0, 0, 4076, +0, 0, 4076, +0, 0, 4076, +0, 0, 4076, +0, 0, 4076, +0, 0, 4076, +0, 0, 4076, +0, 0, 4076, +0, 0, 4076, +0, 0, 4076, +0, 0, 4076, +0, 0, 4075, +0, 0, 4075, +0, 0, 4075, +0, 0, 4074, +0, 0, 4073, +0, 0, 4072, +0, 0, 4071, +0, 0, 4069, +0, 1985, 4066, +0, 2781, 4063, +0, 3119, 4058, +2063, 3361, 4052, +2986, 3561, 4044, +3336, 3737, 4032, +3583, 3900, 4016, +3583, 4016, 3999, +3583, 4016, 3792, +3568, 4095, 3469, +0, 0, 4076, +0, 0, 4076, +0, 0, 4076, +0, 0, 4076, +0, 0, 4076, +0, 0, 4076, +0, 0, 4076, +0, 0, 4076, +0, 0, 4076, +0, 0, 4076, +0, 0, 4076, +0, 0, 4076, +0, 0, 4076, +0, 0, 4076, +0, 0, 4075, +0, 0, 4075, +0, 0, 4075, +0, 0, 4074, +0, 0, 4073, +0, 0, 4072, +0, 0, 4071, +0, 0, 4069, +0, 0, 4066, +0, 0, 4063, +2157, 0, 4058, +2689, 2063, 4052, +2986, 2987, 4044, +3336, 3435, 4032, +3583, 3711, 4016, +3784, 3928, 3994, +3784, 3994, 3873, +3844, 4095, 3714, +3401, 0, 4076, +3401, 0, 4076, +3401, 0, 4076, +3401, 0, 4076, +3401, 0, 4076, +3402, 0, 4076, +3402, 0, 4076, +3402, 0, 4076, +3403, 0, 4076, +3403, 0, 4076, +3404, 0, 4076, +3405, 0, 4076, +3407, 0, 4076, +3409, 0, 4076, +3411, 0, 4075, +3415, 0, 4075, +3419, 0, 4075, +3426, 0, 4074, +3434, 0, 4073, +3444, 0, 4072, +3458, 0, 4071, +3475, 0, 4069, +3498, 0, 4066, +3527, 0, 4063, +3562, 0, 4058, +3606, 2063, 4052, +3659, 2986, 4044, +3720, 3336, 4032, +3792, 3583, 4016, +3873, 3784, 3994, +3962, 3962, 3962, +4060, 4095, 3916, +3924, 0, 4095, +3924, 0, 4095, +3924, 0, 4095, +3924, 0, 4095, +3924, 0, 4095, +3925, 0, 4095, +3925, 0, 4095, +3925, 0, 4095, +3925, 0, 4095, +3925, 0, 4095, +3925, 0, 4095, +3926, 0, 4095, +3926, 0, 4095, +3927, 0, 4095, +3927, 0, 4095, +3929, 0, 4095, +3930, 0, 4095, +3932, 0, 4095, +3935, 0, 4095, +3938, 0, 4095, +3943, 0, 4095, +3949, 0, 4095, +3957, 0, 4095, +3968, 0, 4095, +3982, 0, 4095, +4000, 0, 4095, +4023, 2192, 4095, +4051, 3118, 4095, +4087, 3469, 4095, +4095, 3714, 4095, +4095, 3916, 4060, +4095, 4005, 3916, +0, 3939, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3940, 4095, +0, 3940, 4095, +0, 3941, 4095, +0, 3941, 4095, +0, 3942, 4095, +0, 3944, 4095, +0, 3946, 4095, +0, 3948, 4095, +0, 3951, 4095, +0, 3955, 4095, +0, 3961, 4095, +0, 3968, 4095, +0, 3978, 4095, +0, 3990, 4095, +0, 4007, 4095, +0, 4027, 4095, +0, 4054, 4095, +0, 4087, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4087, +0, 4095, 3924, +0, 4095, 3533, +0, 3939, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3940, 4095, +0, 3940, 4095, +0, 3941, 4095, +0, 3941, 4095, +0, 3942, 4095, +0, 3944, 4095, +0, 3946, 4095, +0, 3948, 4095, +0, 3951, 4095, +0, 3955, 4095, +0, 3961, 4095, +0, 3968, 4095, +0, 3978, 4095, +0, 3990, 4095, +0, 4006, 4095, +0, 4027, 4095, +0, 4054, 4095, +0, 4087, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4087, +0, 4095, 3924, +0, 4095, 3533, +0, 3938, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3940, 4095, +0, 3940, 4095, +0, 3941, 4095, +0, 3941, 4095, +0, 3942, 4095, +0, 3944, 4095, +0, 3945, 4095, +0, 3948, 4095, +0, 3951, 4095, +0, 3955, 4095, +0, 3961, 4095, +0, 3968, 4095, +0, 3978, 4095, +0, 3990, 4095, +0, 4006, 4095, +0, 4027, 4095, +0, 4054, 4095, +0, 4087, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4087, +0, 4095, 3924, +0, 4095, 3533, +0, 3938, 4095, +0, 3938, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3940, 4095, +0, 3940, 4095, +0, 3941, 4095, +0, 3941, 4095, +0, 3942, 4095, +0, 3944, 4095, +0, 3945, 4095, +0, 3948, 4095, +0, 3951, 4095, +0, 3955, 4095, +0, 3961, 4095, +0, 3968, 4095, +0, 3978, 4095, +0, 3990, 4095, +0, 4006, 4095, +0, 4027, 4095, +0, 4054, 4095, +0, 4087, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4087, +0, 4095, 3924, +0, 4095, 3534, +0, 3938, 4095, +0, 3938, 4095, +0, 3938, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3940, 4095, +0, 3940, 4095, +0, 3941, 4095, +0, 3941, 4095, +0, 3942, 4095, +0, 3944, 4095, +0, 3945, 4095, +0, 3948, 4095, +0, 3951, 4095, +0, 3955, 4095, +0, 3961, 4095, +0, 3968, 4095, +0, 3977, 4095, +0, 3990, 4095, +0, 4006, 4095, +0, 4027, 4095, +0, 4054, 4095, +0, 4087, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4087, +0, 4095, 3924, +0, 4095, 3534, +0, 3938, 4095, +0, 3938, 4095, +0, 3938, 4095, +0, 3938, 4095, +0, 3938, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3940, 4095, +0, 3941, 4095, +0, 3941, 4095, +0, 3942, 4095, +0, 3944, 4095, +0, 3945, 4095, +0, 3948, 4095, +0, 3951, 4095, +0, 3955, 4095, +0, 3961, 4095, +0, 3968, 4095, +0, 3977, 4095, +0, 3990, 4095, +0, 4006, 4095, +0, 4027, 4095, +0, 4054, 4095, +0, 4087, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4087, +0, 4095, 3925, +0, 4095, 3534, +0, 3938, 4095, +0, 3938, 4095, +0, 3938, 4095, +0, 3938, 4095, +0, 3938, 4095, +0, 3938, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3940, 4095, +0, 3940, 4095, +0, 3941, 4095, +0, 3942, 4095, +0, 3943, 4095, +0, 3945, 4095, +0, 3947, 4095, +0, 3951, 4095, +0, 3955, 4095, +0, 3961, 4095, +0, 3968, 4095, +0, 3977, 4095, +0, 3990, 4095, +0, 4006, 4095, +0, 4027, 4095, +0, 4054, 4095, +0, 4087, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4087, +0, 4095, 3925, +0, 4095, 3534, +0, 3938, 4095, +0, 3938, 4095, +0, 3938, 4095, +0, 3938, 4095, +0, 3938, 4095, +0, 3938, 4095, +0, 3938, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3940, 4095, +0, 3940, 4095, +0, 3941, 4095, +0, 3942, 4095, +0, 3943, 4095, +0, 3945, 4095, +0, 3947, 4095, +0, 3950, 4095, +0, 3955, 4095, +0, 3960, 4095, +0, 3968, 4095, +0, 3977, 4095, +0, 3990, 4095, +0, 4006, 4095, +0, 4027, 4095, +0, 4053, 4095, +0, 4087, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4087, +0, 4095, 3925, +0, 4095, 3534, +0, 3937, 4095, +0, 3937, 4095, +0, 3937, 4095, +0, 3938, 4095, +0, 3938, 4095, +0, 3938, 4095, +0, 3938, 4095, +0, 3938, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3940, 4095, +0, 3941, 4095, +0, 3941, 4095, +0, 3943, 4095, +0, 3945, 4095, +0, 3947, 4095, +0, 3950, 4095, +0, 3954, 4095, +0, 3960, 4095, +0, 3967, 4095, +0, 3977, 4095, +0, 3989, 4095, +0, 4006, 4095, +0, 4027, 4095, +0, 4053, 4095, +0, 4086, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4087, +0, 4095, 3925, +0, 4095, 3534, +0, 3937, 4095, +0, 3937, 4095, +0, 3937, 4095, +0, 3937, 4095, +0, 3937, 4095, +0, 3937, 4095, +0, 3938, 4095, +0, 3938, 4095, +0, 3938, 4095, +0, 3939, 4095, +0, 3940, 4095, +0, 3940, 4095, +0, 3941, 4095, +0, 3943, 4095, +0, 3944, 4095, +0, 3947, 4095, +0, 3950, 4095, +0, 3954, 4095, +0, 3960, 4095, +0, 3967, 4095, +0, 3977, 4095, +0, 3989, 4095, +0, 4005, 4095, +0, 4026, 4095, +0, 4053, 4095, +0, 4086, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4088, +0, 4095, 3925, +0, 4095, 3535, +0, 3937, 4095, +0, 3937, 4095, +0, 3937, 4095, +0, 3937, 4095, +0, 3937, 4095, +0, 3937, 4095, +0, 3937, 4095, +0, 3937, 4095, +0, 3938, 4095, +0, 3938, 4095, +0, 3939, 4095, +0, 3940, 4095, +0, 3941, 4095, +0, 3942, 4095, +0, 3944, 4095, +0, 3946, 4095, +0, 3950, 4095, +0, 3954, 4095, +0, 3959, 4095, +0, 3967, 4095, +0, 3976, 4095, +0, 3989, 4095, +0, 4005, 4095, +0, 4026, 4095, +0, 4053, 4095, +0, 4086, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4088, +0, 4095, 3925, +0, 4095, 3536, +0, 3936, 4095, +0, 3936, 4095, +0, 3936, 4095, +0, 3936, 4095, +0, 3936, 4095, +0, 3936, 4095, +0, 3937, 4095, +0, 3937, 4095, +0, 3937, 4095, +0, 3937, 4095, +0, 3938, 4095, +0, 3939, 4095, +0, 3940, 4095, +0, 3941, 4095, +0, 3943, 4095, +0, 3946, 4095, +0, 3949, 4095, +0, 3953, 4095, +0, 3959, 4095, +0, 3966, 4095, +0, 3976, 4095, +0, 3988, 4095, +0, 4005, 4095, +0, 4026, 4095, +0, 4052, 4095, +0, 4085, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4088, +0, 4095, 3926, +0, 4095, 3537, +0, 3935, 4095, +0, 3935, 4095, +0, 3935, 4095, +0, 3935, 4095, +0, 3935, 4095, +0, 3935, 4095, +0, 3935, 4095, +0, 3936, 4095, +0, 3936, 4095, +0, 3937, 4095, +0, 3937, 4095, +0, 3938, 4095, +0, 3939, 4095, +0, 3941, 4095, +0, 3942, 4095, +0, 3945, 4095, +0, 3948, 4095, +0, 3952, 4095, +0, 3958, 4095, +0, 3965, 4095, +0, 3975, 4095, +0, 3988, 4095, +0, 4004, 4095, +0, 4025, 4095, +0, 4051, 4095, +0, 4085, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4088, +0, 4095, 3926, +0, 4095, 3538, +0, 3933, 4095, +0, 3933, 4095, +0, 3933, 4095, +0, 3933, 4095, +0, 3934, 4095, +0, 3934, 4095, +0, 3934, 4095, +0, 3934, 4095, +0, 3935, 4095, +0, 3935, 4095, +0, 3936, 4095, +0, 3937, 4095, +0, 3938, 4095, +0, 3940, 4095, +0, 3941, 4095, +0, 3944, 4095, +0, 3947, 4095, +0, 3951, 4095, +0, 3957, 4095, +0, 3964, 4095, +0, 3974, 4095, +0, 3986, 4095, +0, 4003, 4095, +0, 4024, 4095, +0, 4051, 4095, +0, 4084, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4089, +0, 4095, 3927, +0, 4095, 3539, +0, 3932, 4095, +0, 3932, 4095, +0, 3932, 4095, +0, 3932, 4095, +0, 3932, 4095, +0, 3932, 4095, +0, 3932, 4095, +0, 3932, 4095, +0, 3933, 4095, +0, 3933, 4095, +0, 3934, 4095, +0, 3935, 4095, +0, 3936, 4095, +0, 3938, 4095, +0, 3940, 4095, +0, 3942, 4095, +0, 3945, 4095, +0, 3950, 4095, +0, 3955, 4095, +0, 3963, 4095, +0, 3972, 4095, +0, 3985, 4095, +0, 4002, 4095, +0, 4023, 4095, +0, 4049, 4095, +0, 4083, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4089, +0, 4095, 3927, +0, 4095, 3541, +0, 3929, 4095, +0, 3929, 4095, +0, 3929, 4095, +0, 3929, 4095, +0, 3929, 4095, +0, 3929, 4095, +0, 3930, 4095, +0, 3930, 4095, +0, 3930, 4095, +0, 3931, 4095, +0, 3932, 4095, +0, 3932, 4095, +0, 3934, 4095, +0, 3935, 4095, +0, 3937, 4095, +0, 3940, 4095, +0, 3944, 4095, +0, 3948, 4095, +0, 3953, 4095, +0, 3961, 4095, +0, 3971, 4095, +0, 3983, 4095, +0, 4000, 4095, +0, 4021, 4095, +0, 4048, 4095, +0, 4082, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4090, +0, 4095, 3929, +0, 4095, 3544, +0, 3926, 4095, +0, 3926, 4095, +0, 3926, 4095, +0, 3926, 4095, +0, 3926, 4095, +0, 3926, 4095, +0, 3927, 4095, +0, 3927, 4095, +0, 3927, 4095, +0, 3927, 4095, +0, 3928, 4095, +0, 3929, 4095, +0, 3930, 4095, +0, 3932, 4095, +0, 3934, 4095, +0, 3937, 4095, +0, 3941, 4095, +0, 3945, 4095, +0, 3951, 4095, +0, 3959, 4095, +0, 3968, 4095, +0, 3981, 4095, +0, 3998, 4095, +0, 4019, 4095, +0, 4046, 4095, +0, 4080, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4091, +0, 4095, 3930, +0, 4095, 3547, +0, 3921, 4095, +0, 3921, 4095, +0, 3921, 4095, +0, 3921, 4095, +0, 3921, 4095, +0, 3922, 4095, +0, 3922, 4095, +0, 3922, 4095, +0, 3923, 4095, +0, 3923, 4095, +0, 3924, 4095, +0, 3925, 4095, +0, 3926, 4095, +0, 3927, 4095, +0, 3930, 4095, +0, 3933, 4095, +0, 3937, 4095, +0, 3942, 4095, +0, 3947, 4095, +0, 3955, 4095, +0, 3965, 4095, +0, 3978, 4095, +0, 3994, 4095, +0, 4016, 4095, +0, 4043, 4095, +0, 4077, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4092, +0, 4095, 3932, +0, 4095, 3552, +0, 3915, 4095, +0, 3915, 4095, +0, 3915, 4095, +0, 3915, 4095, +0, 3915, 4095, +0, 3916, 4095, +0, 3916, 4095, +0, 3916, 4095, +0, 3917, 4095, +0, 3917, 4095, +0, 3918, 4095, +0, 3919, 4095, +0, 3920, 4095, +0, 3922, 4095, +0, 3924, 4095, +0, 3927, 4095, +0, 3931, 4095, +0, 3936, 4095, +0, 3943, 4095, +0, 3950, 4095, +0, 3961, 4095, +0, 3974, 4095, +0, 3990, 4095, +0, 4012, 4095, +0, 4039, 4095, +0, 4073, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4094, +0, 4095, 3935, +0, 4095, 3558, +0, 3907, 4095, +0, 3907, 4095, +0, 3907, 4095, +0, 3907, 4095, +0, 3907, 4095, +0, 3908, 4095, +0, 3908, 4095, +0, 3908, 4095, +0, 3908, 4095, +0, 3909, 4095, +0, 3910, 4095, +0, 3910, 4095, +0, 3912, 4095, +0, 3913, 4095, +0, 3916, 4095, +0, 3919, 4095, +0, 3923, 4095, +0, 3928, 4095, +0, 3935, 4095, +0, 3944, 4095, +0, 3954, 4095, +0, 3968, 4095, +0, 3984, 4095, +0, 4006, 4095, +0, 4034, 4095, +0, 4069, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 3938, +0, 4095, 3566, +0, 3896, 4095, +0, 3896, 4095, +0, 3896, 4095, +0, 3896, 4095, +0, 3896, 4095, +0, 3896, 4095, +0, 3896, 4095, +0, 3897, 4095, +0, 3897, 4095, +0, 3898, 4095, +0, 3898, 4095, +0, 3899, 4095, +0, 3901, 4095, +0, 3903, 4095, +0, 3905, 4095, +0, 3908, 4095, +0, 3912, 4095, +0, 3917, 4095, +0, 3924, 4095, +0, 3934, 4095, +0, 3946, 4095, +0, 3960, 4095, +0, 3977, 4095, +0, 3999, 4095, +0, 4027, 4095, +0, 4062, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 3943, +0, 4095, 3576, +0, 3880, 4095, +0, 3880, 4095, +0, 3880, 4095, +0, 3880, 4095, +0, 3880, 4095, +0, 3881, 4095, +0, 3881, 4095, +0, 3881, 4095, +0, 3881, 4095, +0, 3882, 4095, +0, 3883, 4095, +0, 3884, 4095, +0, 3885, 4095, +0, 3887, 4095, +0, 3889, 4095, +0, 3893, 4095, +0, 3897, 4095, +0, 3903, 4095, +0, 3910, 4095, +0, 3920, 4095, +0, 3932, 4095, +0, 3949, 4095, +0, 3966, 4095, +0, 3989, 4095, +0, 4018, 4095, +0, 4054, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 3949, +0, 4095, 3590, +0, 3859, 4095, +0, 3859, 4095, +0, 3859, 4095, +0, 3859, 4095, +0, 3859, 4095, +0, 3859, 4095, +0, 3859, 4095, +0, 3860, 4095, +0, 3860, 4095, +0, 3861, 4095, +0, 3862, 4095, +0, 3863, 4095, +0, 3864, 4095, +0, 3866, 4095, +0, 3868, 4095, +0, 3872, 4095, +0, 3876, 4095, +0, 3882, 4095, +0, 3890, 4095, +0, 3900, 4095, +0, 3913, 4095, +0, 3930, 4095, +0, 3952, 4095, +0, 3976, 4095, +0, 4005, 4095, +0, 4042, 4095, +0, 4087, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 3957, +0, 4095, 3608, +0, 3828, 4095, +0, 3828, 4095, +0, 3828, 4095, +0, 3828, 4095, +0, 3828, 4095, +0, 3829, 4095, +0, 3829, 4095, +0, 3829, 4095, +0, 3830, 4095, +0, 3830, 4095, +0, 3831, 4095, +0, 3832, 4095, +0, 3834, 4095, +0, 3836, 4095, +0, 3838, 4095, +0, 3842, 4095, +0, 3847, 4095, +0, 3853, 4095, +0, 3861, 4095, +0, 3872, 4095, +0, 3886, 4095, +0, 3904, 4095, +0, 3927, 4095, +0, 3956, 4095, +0, 3987, 4095, +0, 4025, 4095, +0, 4072, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 3968, +0, 4095, 3630, +0, 3784, 4095, +0, 3784, 4095, +0, 3784, 4095, +0, 3784, 4095, +0, 3784, 4095, +0, 3784, 4095, +0, 3784, 4095, +0, 3785, 4095, +0, 3786, 4095, +0, 3786, 4095, +0, 3787, 4095, +0, 3788, 4095, +0, 3790, 4095, +0, 3792, 4095, +0, 3795, 4095, +0, 3799, 4095, +0, 3804, 4095, +0, 3811, 4095, +0, 3820, 4095, +0, 3832, 4095, +0, 3847, 4095, +0, 3867, 4095, +0, 3892, 4095, +0, 3923, 4095, +0, 3962, 4095, +0, 4002, 4095, +0, 4051, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 3982, +0, 4095, 3659, +0, 3716, 4095, +0, 3717, 4095, +0, 3717, 4095, +0, 3717, 4095, +0, 3717, 4095, +0, 3717, 4095, +0, 3718, 4095, +0, 3718, 4095, +0, 3719, 4095, +0, 3720, 4095, +0, 3721, 4095, +0, 3722, 4095, +0, 3724, 4095, +0, 3727, 4095, +0, 3730, 4095, +0, 3735, 4095, +0, 3741, 4095, +0, 3748, 4095, +0, 3759, 4095, +0, 3772, 4095, +0, 3790, 4095, +0, 3812, 4095, +0, 3840, 4095, +0, 3875, 4095, +0, 3918, 4095, +0, 3970, 4095, +0, 4022, 4095, +0, 4084, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4000, +0, 4095, 3695, +0, 3608, 4095, +0, 3608, 4095, +0, 3608, 4095, +0, 3608, 4095, +0, 3608, 4095, +0, 3609, 4095, +0, 3609, 4095, +0, 3610, 4095, +0, 3611, 4095, +0, 3612, 4095, +0, 3613, 4095, +0, 3615, 4095, +0, 3617, 4095, +0, 3621, 4095, +0, 3625, 4095, +0, 3630, 4095, +0, 3638, 4095, +0, 3648, 4095, +0, 3661, 4095, +0, 3677, 4095, +0, 3699, 4095, +0, 3726, 4095, +0, 3759, 4095, +0, 3801, 4095, +0, 3851, 4095, +0, 3911, 4095, +2192, 3980, 4095, +2192, 4047, 4095, +2192, 4095, 4095, +2192, 4095, 4095, +2192, 4095, 4023, +2192, 4095, 3738, +0, 3404, 4095, +0, 3404, 4095, +0, 3404, 4095, +0, 3405, 4095, +0, 3405, 4095, +0, 3405, 4095, +0, 3406, 4095, +0, 3407, 4095, +0, 3408, 4095, +0, 3410, 4095, +0, 3412, 4095, +0, 3415, 4095, +0, 3419, 4095, +0, 3424, 4095, +0, 3430, 4095, +0, 3439, 4095, +0, 3450, 4095, +0, 3465, 4095, +0, 3484, 4095, +0, 3509, 4095, +0, 3539, 4095, +0, 3577, 4095, +0, 3623, 4095, +0, 3679, 4095, +0, 3743, 4095, +0, 3818, 4095, +2192, 3901, 4095, +3118, 3993, 4095, +3118, 4079, 4095, +3118, 4095, 4095, +3118, 4095, 4051, +3118, 4095, 3791, +0, 2761, 4095, +0, 2762, 4095, +0, 2762, 4095, +0, 2764, 4095, +0, 2765, 4095, +0, 2767, 4095, +0, 2770, 4095, +0, 2773, 4095, +0, 2778, 4095, +0, 2785, 4095, +0, 2793, 4095, +0, 2804, 4095, +0, 2818, 4095, +0, 2837, 4095, +0, 2861, 4095, +0, 2890, 4095, +0, 2927, 4095, +0, 2973, 4095, +0, 3027, 4095, +0, 3090, 4095, +0, 3164, 4095, +0, 3246, 4095, +0, 3337, 4095, +0, 3436, 4095, +0, 3541, 4095, +0, 3653, 4095, +2192, 3768, 4095, +3118, 3888, 4095, +3469, 4010, 4095, +3469, 4095, 4095, +3469, 4095, 4087, +3469, 4095, 3853, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 2137, 4095, +0, 2915, 4095, +0, 3253, 4095, +2192, 3494, 4095, +3118, 3693, 4095, +3469, 3869, 4095, +3714, 4032, 4095, +3714, 4095, 4095, +3714, 4095, 3924, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +2266, 0, 4095, +2814, 2192, 4095, +3118, 3121, 4095, +3469, 3568, 4095, +3714, 3844, 4095, +3916, 4060, 4095, +3916, 4095, 4005, +3533, 0, 4095, +3533, 0, 4095, +3533, 0, 4095, +3534, 0, 4095, +3534, 0, 4095, +3534, 0, 4095, +3534, 0, 4095, +3534, 0, 4095, +3534, 0, 4095, +3535, 0, 4095, +3536, 0, 4095, +3537, 0, 4095, +3538, 0, 4095, +3539, 0, 4095, +3541, 0, 4095, +3544, 0, 4095, +3547, 0, 4095, +3552, 0, 4095, +3558, 0, 4095, +3566, 0, 4095, +3576, 0, 4095, +3590, 0, 4095, +3608, 0, 4095, +3630, 0, 4095, +3659, 0, 4095, +3695, 0, 4095, +3738, 2192, 4095, +3791, 3118, 4095, +3853, 3469, 4095, +3924, 3714, 4095, +4005, 3916, 4095, +4095, 4095, 4095] + } +} \ No newline at end of file diff --git a/Gems/Atom/Feature/Common/Editor/Scripts/ColorGrading/.gitignore b/Gems/Atom/Feature/Common/Editor/Scripts/ColorGrading/.gitignore new file mode 100644 index 0000000000..268cdab0c7 --- /dev/null +++ b/Gems/Atom/Feature/Common/Editor/Scripts/ColorGrading/.gitignore @@ -0,0 +1 @@ +.tmp \ No newline at end of file diff --git a/Gems/Atom/Feature/Common/Editor/Scripts/ColorGrading/__init__.py b/Gems/Atom/Feature/Common/Editor/Scripts/ColorGrading/__init__.py new file mode 100644 index 0000000000..af73f82b8d --- /dev/null +++ b/Gems/Atom/Feature/Common/Editor/Scripts/ColorGrading/__init__.py @@ -0,0 +1,258 @@ +# coding:utf-8 +#!/usr/bin/python +# +# Copyright (c) Contributors to the Open 3D Engine Project. +# For complete copyright and license terms please see the LICENSE at the root of this distribution. +# +# SPDX-License-Identifier: Apache-2.0 OR MIT +# +# +"""O3DE/Atom Color Grading Python Package""" +# ------------------------------------------------------------------------- +import sys +import os +import site +import inspect +import logging as _logging +import pathlib +from pathlib import Path +import math + +# ------------------------------------------------------------------------- +__copyright__ = "Copyright 2021, Amazon" +__credits__ = ["Jonny Galloway", "Ben Black"] +__license__ = "EULA" +__version__ = "0.0.1" +__status__ = "Prototype" + +__all__ = ['from_3dl_to_azasset', + 'capture_displaymapperpassthrough', + 'exr_to_3dl_azasset', + 'initialize', + 'lut_compositor', + 'lut_helper', + 'env_bool', + 'makedirs', + 'initialize_logger' + 'inv_shaper_transform', + 'shaper_transform', + 'get_uv_coord', + 'clamp', + 'log2', + 'is_power_of_two'] +# ------------------------------------------------------------------------- + + +# ------------------------------------------------------------------------- +_MODULE_PATH = Path(os.path.abspath(__file__)) +site.addsitedir(_MODULE_PATH.parent.absolute()) + +_PACKAGENAME = 'ColorGrading' +_MODULEENAME = 'ColorGrading.init' + +# project cache log dir path +DCCSI_LOG_PATH = Path(_MODULE_PATH.parent.absolute(), '.tmp', 'logs') +# ------------------------------------------------------------------------- + + +# -- envar util ---------------------------------------------------------- +def env_bool(envar, default=False): + """cast a env bool to a python bool""" + envar_test = os.getenv(envar, default) + # check 'False', 'false', and '0' since all are non-empty + # env comes back as string and normally coerced to True. + if envar_test in ('True', 'true', '1'): + return True + elif envar_test in ('False', 'false', '0'): + return False + else: + return envar_test +# ------------------------------------------------------------------------- + + +# ------------------------------------------------------------------------- +# set these true if you want them set globally for debugging +DCCSI_GDEBUG = env_bool('DCCSI_GDEBUG', False) +DCCSI_DEV_MODE = env_bool('DCCSI_DEV_MODE', False) +DCCSI_GDEBUGGER = env_bool('DCCSI_GDEBUGGER', False) +DCCSI_LOGLEVEL = env_bool('DCCSI_LOGLEVEL', int(20)) +# ------------------------------------------------------------------------- + + +# ------------------------------------------------------------------------- +FRMT_LOG_LONG = "[%(name)s][%(levelname)s] >> %(message)s (%(asctime)s; %(filename)s:%(lineno)d)" + +def initialize_logger(name, + log_to_file=False, + default_log_level=_logging.NOTSET): + """Start a azpy logger""" + _logger = _logging.getLogger(name) + _logger.propagate = False + if not _logger.handlers: + + # default log level + _log_level = int(os.getenv('DCCSI_LOGLEVEL', default_log_level)) + + if DCCSI_GDEBUG: + _log_level = int(10) # force when debugging + + if _log_level: + ch = _logging.StreamHandler(sys.stdout) + ch.setLevel(_log_level) + formatter = _logging.Formatter(FRMT_LOG_LONG) + ch.setFormatter(formatter) + _logger.addHandler(ch) + _logger.setLevel(_log_level) + else: + _logger.addHandler(_logging.NullHandler()) + + _logger.debug('_log_level: {}'.format(_log_level)) + + # optionally add the log file handler (off by default) + if log_to_file: + _logger.info('DCCSI_LOG_PATH: {}'.format(DCCSI_LOG_PATH)) + try: + # exist_ok, isn't available in py2.7 pathlib + # because it doesn't exist for os.makedirs + # pathlib2 backport used instead (see above) + if sys.version_info.major >= 3: + DCCSI_LOG_PATH.mkdir(parents=True, exist_ok=True) + else: + makedirs(str(DCCSI_LOG_PATH.resolve())) # py2.7 + except FileExistsError: + # except FileExistsError: doesn't exist in py2.7 + _logger.debug("Folder is already there") + else: + _logger.debug("Folder was created") + + _log_filepath = Path(DCCSI_LOG_PATH, '{}.log'.format(name)) + try: + _log_filepath.touch(mode=0o666, exist_ok=True) + except FileExistsError: + _logger.debug("Log file is already there: {}".format(_log_filepath)) + else: + _logger.debug("Log file was created: {}".format(_log_filepath)) + + if _log_filepath.exists(): + file_formatter = _logging.Formatter(FRMT_LOG_LONG) + file_handler = _logging.FileHandler(str(_log_filepath)) + file_handler.setLevel(_logging.DEBUG) + file_handler.setFormatter(file_formatter) + _logger.addHandler(file_handler) + + return _logger +# ------------------------------------------------------------------------- + + +# ------------------------------------------------------------------------- +# _ROOT_LOGGER = _logging.getLogger() # only use this if debugging +# https://stackoverflow.com/questions/56733085/how-to-know-the-current-file-path-after-being-frozen-into-an-executable-using-cx/56748839 +#os.chdir(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))) +# ------------------------------------------------------------------------- +if DCCSI_GDEBUG: + DCCSI_LOGLEVEL = int(10) + +# set up logger with both console and file _logging +if DCCSI_GDEBUG: + _LOGGER = initialize_logger(_MODULEENAME, log_to_file=True) +else: + _LOGGER = initialize_logger(_MODULEENAME, log_to_file=False) + +_LOGGER.debug('Invoking __init__.py for {0}.'.format({_PACKAGENAME})) +# ------------------------------------------------------------------------- + + +# ------------------------------------------------------------------------- +def makedirs(folder, *args, **kwargs): + """a makedirs for py2.7 support""" + try: + return os.makedirs(folder, exist_ok=True, *args, **kwargs) + except TypeError: + # Unexpected arguments encountered + pass + try: + # Should work is TypeError was caused by exist_ok, eg., Py2 + return os.makedirs(folder, *args, **kwargs) + except OSError as e: + if e.errno != errno.EEXIST: + raise + + if os.path.isfile(folder): + # folder is a file, raise OSError just like os.makedirs() in Py3 + raise +# ------------------------------------------------------------------------- + + +# ------------------------------------------------------------------------- +class FileExistsError(Exception): + """Implements a stand-in Exception for py2.7""" + def __init__(self, message, errors): + + # Call the base class constructor with the parameters it needs + super(FileExistsError, self).__init__(message) + + # Now for your custom code... + self.errors = errors + +if sys.version_info.major < 3: + FileExistsError = FileExistsError +# ------------------------------------------------------------------------- + + +# ------------------------------------------------------------------------ +# commonly reused utilities +AZASSET_LUT = """\ +{ + "Type": "JsonSerialization", + "Version": 1, + "ClassName": "LookupTableAsset", + "ClassData": { + "Name": "LookupTable", + "Intervals": [%s], + "Values": [%s] + } +}""" + +FLOAT_EPSILON = sys.float_info.epsilon + +# pow(f, e) won't work if f is negative, or may cause inf / NAN. +def no_nan_pow(base, power): + return pow(max(abs(base), (FLOAT_EPSILON, FLOAT_EPSILON, FLOAT_EPSILON)), power) + +# Transform from high dynamic range to normalized +def inv_shaper_transform(bias, scale, v): + return pow(2.0, (v - bias) / scale) + +# Transform from normalized range to high dynamic range +def shaper_transform(bias, scale, v, clip_threshold=FLOAT_EPSILON): + if v > 0.0: + return math.log(v, 2.0) * scale + bias + + # this is probably not correct, clamps, avoids a math domain error + elif v <= 0.0: + _LOGGER.debug(f'Clipping a value: bias={bias}, scale={scale}, v={v}') + return math.log(clip_threshold, 2.0) * scale + bias + +def get_uv_coord(size, r, g, b): + u = g * size + r + v = b + return (u, v) + +def clamp(v): + return max(0.0, min(1.0, v)) + +def log2(x): + return (math.log10(x) / + math.log10(2)) + +def is_power_of_two(n): + return (math.ceil(log2(n)) == math.floor(log2(n))) +# ------------------------------------------------------------------------ + + +########################################################################### +# Main Code Block, runs this script as main (testing) +# ------------------------------------------------------------------------- +if __name__ == '__main__': + + del _LOGGER \ No newline at end of file diff --git a/Gems/Atom/Feature/Common/Editor/Scripts/ColorGrading/capture_displaymapperpassthrough.py b/Gems/Atom/Feature/Common/Editor/Scripts/ColorGrading/capture_displaymapperpassthrough.py new file mode 100644 index 0000000000..76cdd8450a --- /dev/null +++ b/Gems/Atom/Feature/Common/Editor/Scripts/ColorGrading/capture_displaymapperpassthrough.py @@ -0,0 +1,61 @@ +# coding:utf-8 +#!/usr/bin/python +# +# Copyright (c) Contributors to the Open 3D Engine Project. +# For complete copyright and license terms please see the LICENSE at the root of this distribution. +# +# SPDX-License-Identifier: Apache-2.0 OR MIT +# +# +"""Frame capture of the Displaymapper Passthrough (outputs .dds image)""" +# ------------------------------------------------------------------------ +import logging as _logging +from env_bool import env_bool + +# ------------------------------------------------------------------------ +_MODULENAME = 'ColorGrading.capture_displaymapperpassthrough' + +import ColorGrading.initialize +ColorGrading.initialize.start() + +_LOGGER = _logging.getLogger(_MODULENAME) +_LOGGER.debug('Initializing: {0}.'.format({_MODULENAME})) +# ------------------------------------------------------------------------ + + +# ------------------------------------------------------------------------ +import azlmbr.bus +import azlmbr.atom + +default_passtree = ["Root", + "MainPipeline_0", + "MainPipeline", + "PostProcessPass", + "LightAdaptation", + "DisplayMapperPass", + "DisplayMapperPassthrough"] + +default_path = "FrameCapture\DisplayMapperPassthrough.dds" + +# To Do: we should try to set display mapper to passthrough, +# then back after capture? + +# To Do: we can wrap this, to call from a PySide2 GUI + +def capture(command="CapturePassAttachment", + passtree=default_passtree, + pass_type="Output", + output_path=default_path): + azlmbr.atom.FrameCaptureRequestBus(azlmbr.bus.Broadcast, + command, + passtree, + pass_type, + output_path, 1) +# ------------------------------------------------------------------------ + + +########################################################################### +# Main Code Block, runs this script as main +# ------------------------------------------------------------------------- +if __name__ == '__main__': + capture() diff --git a/Gems/Atom/Feature/Common/Editor/Scripts/ColorGrading/exr_to_3dl_azasset.py b/Gems/Atom/Feature/Common/Editor/Scripts/ColorGrading/exr_to_3dl_azasset.py new file mode 100644 index 0000000000..9166ef5a44 --- /dev/null +++ b/Gems/Atom/Feature/Common/Editor/Scripts/ColorGrading/exr_to_3dl_azasset.py @@ -0,0 +1,120 @@ +# coding:utf-8 +#!/usr/bin/python +# +# Copyright (c) Contributors to the Open 3D Engine Project. +# For complete copyright and license terms please see the LICENSE at the root of this distribution. +# +# SPDX-License-Identifier: Apache-2.0 OR MIT +# +# +""" + input: a shaped .exr representing a LUT (for instance coming out of photoshop) + output: a inverse shaped LUT as .exr + ^ as a .3DL (normalized lut file type) + ^ as a .azasset (for o3de engine) +""" + +import sys +import os +import argparse +import math +import site +import pathlib +from pathlib import Path +import logging as _logging +import numpy as np + +# ------------------------------------------------------------------------ +_MODULENAME = 'ColorGrading.exr_to_3dl_azasset' + +import ColorGrading.initialize +ColorGrading.initialize.start() + +_LOGGER = _logging.getLogger(_MODULENAME) +_LOGGER.debug('Initializing: {0}.'.format({_MODULENAME})) + +try: + import OpenImageIO as oiio + pass +except ImportError as e: + _LOGGER.error(f"invalid import: {e}") + sys.exit(1) +# ------------------------------------------------------------------------ + + +# ------------------------------------------------------------------------ +from ColorGrading.from_3dl_to_azasset import write_azasset + +from ColorGrading import get_uv_coord + +def generate_lut_values(image_spec, image_buffer): + lut_size = image_spec.height + + lut_intervals = [] + lut_values = [] + + # First line contains the vertex intervals + dv = 1023.0 / float(lut_size-1) + for i in range(lut_size): + lut_intervals.append(np.uint16(dv * i)) + # Texels are in R G B per line with indices increasing first with blue, then green, and then red. + for r in range(lut_size): + for g in range(lut_size): + for b in range(lut_size): + uv = get_uv_coord(lut_size, r, g, b) + px = np.array(image_buffer.getpixel(uv[0], uv[1]), dtype='f') + px = np.clip(px, 0.0, 1.0) + px = np.uint16(px * 4095) + lut_values.append(px) + + return lut_intervals, lut_values + +# To Do: add some input file validation +# If the input file doesn't exist, you'll get a LUT with res of 0 x 0 and result in a math error +#Resolution is 0 x 0 +#writing C:\Depot\o3de-engine\Gems\AtomLyIntegration\CommonFeatures\Tools\ColorGrading\TestData\Nuke\HDR\Nuke_Post_grade_LUT.3dl... +#Traceback (most recent call last): + #File "..\..\Editor\Scripts\ColorGrading\exr_to_3dl_azasset.py", line 103, in + #dv = 1023.0 / float(lutSize) +# ZeroDivisionError: float division by zero + +def write_3DL(file_path, lut_size, lut_intervals, lut_values): + lut_file_path = f'{file_path}.3dl' + _LOGGER.info(f"Writing {lut_file_path}...") + lut_file = open(lut_file_path, 'w') + for i in range(lut_size): + lut_file.write(f"{lut_intervals[i]} ") + lut_file.write("\n") + for px in lut_values: + lut_file.write(f"{px[0]} {px[1]} {px[2]}\n") + lut_file.close() + + +########################################################################### +# Main Code Block, runs this script as main (testing) +# ------------------------------------------------------------------------- +if __name__ == '__main__': + """Run this file as main""" + + parser=argparse.ArgumentParser() + parser.add_argument('--i', type=str, required=True, help='input file') + parser.add_argument('--o', type=str, required=True, help='output file') + args=parser.parse_args() + + # Read input image + # image_buffer = oiio.ImageBuf("linear_lut.exr") + image_buffer=oiio.ImageBuf(args.i) + image_spec=image_buffer.spec() + _LOGGER.info(f"Resolution is, x: {image_buffer.spec().width} and y: {image_buffer.spec().height}") + + if image_spec.width != image_spec.height * image_spec.height: + _LOGGER.info(f"invalid input file dimensions. Expect lengthwise LUT with dimension W: s*s X H: s, where s is the size of the LUT") + sys.exit(1) + + lut_intervals, lut_values = generate_lut_values(image_spec, image_buffer) + + write_3DL(args.o, image_spec.height, lut_intervals, lut_values) + write_azasset(args.o, image_spec.height, lut_intervals, lut_values) + + # example from command line + # python % DCCSI_COLORGRADING_SCRIPTS %\lut_helper.py - -i C: \Depot\o3de\Gems\Atom\Feature\Common\Tools\ColorGrading\Resources\LUTs\linear_32_LUT.exr - -op pre - grading - -shaper Log2 - 48nits - -o C: \Depot\o3de\Gems\Atom\Feature\Common\Tools\ColorGrading\Resources\LUTs\base_Log2-48nits_32_LUT.exr diff --git a/Gems/Atom/Feature/Common/Editor/Scripts/ColorGrading/from_3dl_to_azasset.py b/Gems/Atom/Feature/Common/Editor/Scripts/ColorGrading/from_3dl_to_azasset.py new file mode 100644 index 0000000000..e61ca33710 --- /dev/null +++ b/Gems/Atom/Feature/Common/Editor/Scripts/ColorGrading/from_3dl_to_azasset.py @@ -0,0 +1,114 @@ +# coding:utf-8 +#!/usr/bin/python +# +# Copyright (c) Contributors to the Open 3D Engine Project. +# For complete copyright and license terms please see the LICENSE at the root of this distribution. +# +# SPDX-License-Identifier: Apache-2.0 OR MIT +# +# +"""Takes a 3dl file and encodes it into a .azasset file that can be read by the AssetProcessor""" +# ------------------------------------------------------------------------ +import json +import sys, getopt +import logging as _logging +# ------------------------------------------------------------------------ + + +# ------------------------------------------------------------------------ +_MODULENAME = 'ColorGrading.from_3dl_to_azasset' + +import ColorGrading.initialize +ColorGrading.initialize.start() + +_LOGGER = _logging.getLogger(_MODULENAME) +_LOGGER.debug('Initializing: {0}.'.format({_MODULENAME})) + +try: + import OpenImageIO as oiio + pass +except ImportError as e: + _LOGGER.error(f"invalid import: {e}") + sys.exit(1) +# ------------------------------------------------------------------------ + + +# ------------------------------------------------------------------------ +from ColorGrading import AZASSET_LUT + + +# ------------------------------------------------------------------------ +def find_first_line(alist): + for lno, line in enumerate(alist): + if line[0].isdigit(): # skip non-number metadata + return lno +# ------------------------------------------------------------------------ + + +# ------------------------------------------------------------------------ +def write_azasset(file_path, lut_intervals, lut_values, azasset_json=AZASSET_LUT): + values_str = '' + for idx, px in enumerate(lut_values): + values_str += f"{px[0]}, {px[1]}, {px[2]}" + if idx < (len(lut_values) - 1): + values_str += ",\n" + + intervals_str = ', '.join(map(str, lut_intervals)) + + azasset_json = azasset_json % (intervals_str, values_str) + + asset_file_path = f"{file_path}.azasset" + _LOGGER.info(f"Writting {asset_file_path}...") + asset_file = open(asset_file_path, 'w') + asset_file.write(azasset_json) +# ------------------------------------------------------------------------ + + +# ------------------------------------------------------------------------ +def convert_3dl_to_azasset(input_file, output_file): + lut_intervals = [] + lut_values = [] + with open(input_file) as lut_file: + alist = [line.rstrip().lstrip() for line in lut_file] + intervals_idx = find_first_line(alist) + + lut_intervals = alist[intervals_idx].split(" ") + + lut_values_range = range(intervals_idx + 1, len(alist)) + for ln in lut_values_range: + values = alist[ln].split(" ") + if values is None or len(values) < 3: + continue + lut_values.append(values) + + write_azasset(output_file, lut_intervals, lut_values) +# ------------------------------------------------------------------------ + + +########################################################################### +# Main Code Block, runs this script as main (testing) +# ------------------------------------------------------------------------- +if __name__ == '__main__': + """Run this file as main""" + input_file = '' + output_file = '' + try: + opts, args = getopt.getopt(sys.argv[1:],"hi:o:",["ifile=","ofile="]) + except getopt.GetoptError: + _LOGGER.info('test.py -i -o ') + sys.exit(2) + for opt, arg in opts: + _LOGGER.info(f"opt {opt} arg {arg}") + if opt == '-h': + _LOGGER.info('test.py -i -o ') + sys.exit() + elif opt in ("-i", "--ifile"): + input_file = arg + elif opt in ("-o", "--ofile"): + output_file = arg + _LOGGER.info(f'Input file is "{input_file}"') + _LOGGER.info(f'Output file is "{output_file}"') + if input_file == '' or output_file == '': + _LOGGER.info('test.py -i -o ') + else: + convert_3dl_to_azasset(input_file, output_file) diff --git a/Gems/Atom/Feature/Common/Editor/Scripts/ColorGrading/initialize.py b/Gems/Atom/Feature/Common/Editor/Scripts/ColorGrading/initialize.py new file mode 100644 index 0000000000..536c10ed05 --- /dev/null +++ b/Gems/Atom/Feature/Common/Editor/Scripts/ColorGrading/initialize.py @@ -0,0 +1,123 @@ +# coding:utf-8 +#!/usr/bin/python +# +# Copyright (c) Contributors to the Open 3D Engine Project. +# For complete copyright and license terms please see the LICENSE at the root of this distribution. +# +# SPDX-License-Identifier: Apache-2.0 OR MIT +# +# + +# standard imports +import sys +import os +import pathlib +import site +from pathlib import Path +import logging as _logging + +# local imports +from ColorGrading import env_bool +from ColorGrading import initialize_logger +from ColorGrading import DCCSI_GDEBUG +from ColorGrading import DCCSI_DEV_MODE +from ColorGrading import DCCSI_GDEBUGGER +from ColorGrading import DCCSI_LOGLEVEL +from ColorGrading import FRMT_LOG_LONG + +__all__ = ['start'] + +# ------------------------------------------------------------------------ +_PACKAGENAME = 'ColorGrading' +_MODULENAME = 'ColorGrading.initialize' + +if DCCSI_GDEBUG: + DCCSI_LOGLEVEL = int(10) + +# set up logger with both console and file _logging +if DCCSI_GDEBUG: + _LOGGER = initialize_logger(_PACKAGENAME, log_to_file=True, default_log_level=DCCSI_LOGLEVEL) +else: + _LOGGER = initialize_logger(_PACKAGENAME, log_to_file=False, default_log_level=DCCSI_LOGLEVEL) + +_LOGGER.debug('Initializing: {0}.'.format({_MODULENAME})) + +# connect to the debugger +if DCCSI_DEV_MODE: + APP_DATA_WING = Path('C:/Users/gallowj/AppData/Roaming/Wing Pro 7') + APP_DATA_WING.resolve() + site.addsitedir(pathlib.PureWindowsPath(APP_DATA_WING).as_posix()) + import wingdbstub as debugger + try: + debugger.Ensure() + _LOGGER.info("Wing debugger attached") + except Exception as e: + _LOGGER.debug('Can not attach Wing debugger (running in IDE already?)') +# ------------------------------------------------------------------------ + + +# ------------------------------------------------------------------------ +def start(): + """set up access to OpenImageIO, within o3de or without""" + # ------------------------------------------------------------------------ + try: + # running in o3de + import azlmbr + + _O3DE_DEV = Path(os.getenv('O3DE_DEV', Path(azlmbr.paths.engroot))) + os.environ['O3DE_DEV'] = pathlib.PureWindowsPath(_O3DE_DEV).as_posix() + _LOGGER.debug(_O3DE_DEV) + + _O3DE_BIN_PATH = Path(str(_O3DE_DEV),Path(azlmbr.paths.executableFolder)) + + _O3DE_BIN = Path(os.getenv('O3DE_BIN', _O3DE_BIN_PATH.resolve())) + os.environ['O3DE_BIN'] = pathlib.PureWindowsPath(_O3DE_BIN).as_posix() + + _LOGGER.debug(_O3DE_BIN) + + site.addsitedir(_O3DE_BIN) + + except Exception as e: + # running external, start this module from: + # "C:\Depot\o3de-engine\Gems\Atom\Feature\Common\Tools\ColorGrading\cmdline\CMD_ColorGradinTools.bat" + pass + + try: + _O3DE_DEV = Path(os.getenv('O3DE_DEV')) + _O3DE_DEV = _O3DE_DEV.resolve() + os.environ['O3DE_DEV'] = pathlib.PureWindowsPath(_O3DE_DEV).as_posix() + _LOGGER.debug(f'O3DE_DEV is: {_O3DE_DEV}') + except EnvironmentError as e: + _LOGGER.error('O3DE engineroot not set or found') + raise e + + try: + _TAG_LY_BUILD_PATH = os.getenv('TAG_LY_BUILD_PATH', 'build') + _DEFAULT_BIN_PATH = Path(str(_O3DE_DEV), _TAG_LY_BUILD_PATH, 'bin', 'profile') + _O3DE_BIN_PATH = Path(os.getenv('O3DE_BIN_PATH', _DEFAULT_BIN_PATH)) + _O3DE_BIN_PATH = _O3DE_BIN_PATH.resolve() + os.environ['O3DE_BIN_PATH'] = pathlib.PureWindowsPath(_O3DE_BIN_PATH).as_posix() + _LOGGER.debug(f'O3DE_BIN_PATH is: {_O3DE_BIN_PATH}') + site.addsitedir(pathlib.PureWindowsPath(_O3DE_BIN_PATH).as_posix()) + except EnvironmentError as e: + _LOGGER.error('O3DE bin folder not set or found') + raise e +# ------------------------------------------------------------------------ + + +# ------------------------------------------------------------------------ +try: + import OpenImageIO as OpenImageIO +except ImportError as e: + _LOGGER.error(f"invalid import: {e}") + sys.exit(1) +# ------------------------------------------------------------------------ + + +########################################################################### +# Main Code Block, runs this script as main (testing) +# ------------------------------------------------------------------------- +if __name__ == '__main__': + """Run this file as main""" + + start() \ No newline at end of file diff --git a/Gems/Atom/Feature/Common/Editor/Scripts/ColorGrading/lut_compositor.py b/Gems/Atom/Feature/Common/Editor/Scripts/ColorGrading/lut_compositor.py new file mode 100644 index 0000000000..74ba44dc27 --- /dev/null +++ b/Gems/Atom/Feature/Common/Editor/Scripts/ColorGrading/lut_compositor.py @@ -0,0 +1,110 @@ +# coding:utf-8 +#!/usr/bin/python +# +# Copyright (c) Contributors to the Open 3D Engine Project. +# For complete copyright and license terms please see the LICENSE at the root of this distribution. +# +# SPDX-License-Identifier: Apache-2.0 OR MIT +# +# +# lut_compositor.py + +import sys +import os +import site +import argparse +import math +import pathlib +from pathlib import Path +import logging as _logging +from env_bool import env_bool + +# ------------------------------------------------------------------------ +_MODULENAME = 'ColorGrading.lut_compositor' + +# set these true if you want them set globally for debugging +_DCCSI_GDEBUG = env_bool('DCCSI_GDEBUG', False) +_DCCSI_DEV_MODE = env_bool('DCCSI_DEV_MODE', False) +_DCCSI_GDEBUGGER = env_bool('DCCSI_GDEBUGGER', False) +_DCCSI_LOGLEVEL = env_bool('DCCSI_LOGLEVEL', int(20)) + +if _DCCSI_GDEBUG: + _DCCSI_LOGLEVEL = int(10) + +FRMT_LOG_LONG = "[%(name)s][%(levelname)s] >> %(message)s (%(asctime)s; %(filename)s:%(lineno)d)" +_logging.basicConfig(level=_DCCSI_LOGLEVEL, + format=FRMT_LOG_LONG, + datefmt='%m-%d %H:%M') +_LOGGER = _logging.getLogger(_MODULENAME) +_LOGGER.debug('Initializing: {0}.'.format({_MODULENAME})) + +import ColorGrading.initialize +ColorGrading.initialize.start() + +try: + import OpenImageIO as oiio + pass +except ImportError as e: + _LOGGER.error(f"invalid import: {e}") + sys.exit(1) +# ------------------------------------------------------------------------ + +operations = {"composite": 0, "extract": 1} +invalidOp = -1 + +parser = argparse.ArgumentParser() +parser.add_argument('--i', type=str, required=True, help='input file') +parser.add_argument('--l', type=str, required=False, help='LUT to composite with screenshot in \'composite\' mode') +parser.add_argument('--op', type=str, required=True, help='operation. Should be \'composite\' or \'extract\'') +parser.add_argument('--s', type=int, required=True, help='size of the LUT (i.e. 16)') +parser.add_argument('--o', type=str, required=True, help='output file') +args = parser.parse_args() + +op = operations.get(args.op, invalidOp) +if op == invalidOp: + print("invalid operation") + sys.exit(1) +elif op == 0: + if args.l is None: + print("no LUT file specified") + sys.exit() + +# read in the input image +inBuf = oiio.ImageBuf(args.i) +inSpec = inBuf.spec() +print("Input resolution is ", inBuf.spec().width, " x ", inBuf.spec().height) + +if op == 0: + outFileName = args.o + print("writing %s..." % (outFileName)) + lutBuf = oiio.ImageBuf(args.l) + lutSpec = lutBuf.spec() + print("Resolution is ", lutBuf.spec().width, " x ", lutBuf.spec().height) + if lutSpec.width != lutSpec.height*lutSpec.height: + print("invalid input file dimensions. Expect lengthwise LUT with dimension W: s*s X H: s, where s is the size of the LUT") + sys.exit(1) + lutSize = lutSpec.height + outSpec = oiio.ImageSpec(inSpec.width, inSpec.height, 3, oiio.TypeFloat) + outBuf = oiio.ImageBuf(outSpec) + outBuf.write(outFileName) + for y in range(outBuf.ybegin, outBuf.yend): + for x in range(outBuf.xbegin, outBuf.xend): + srcPx = inBuf.getpixel(x, y) + dstPx = (srcPx[0], srcPx[1], srcPx[2]) + if y < lutSpec.height and x < lutSpec.width: + lutPx = lutBuf.getpixel(x, y) + dstPx = (lutPx[0], lutPx[1], lutPx[2]) + outBuf.setpixel(x, y, dstPx) + outBuf.write(outFileName) +elif op == 1: + outFileName = args.o + print("writing %s..." % (outFileName)) + lutSize = args.s + lutSpec = oiio.ImageSpec(lutSize*lutSize, lutSize, 3, oiio.TypeFloat) + lutBuf = oiio.ImageBuf(lutSpec) + for y in range(lutBuf.ybegin, lutBuf.yend): + for x in range(lutBuf.xbegin, lutBuf.xend): + srcPx = inBuf.getpixel(x, y) + dstPx = (srcPx[0], srcPx[1], srcPx[2]) + lutBuf.setpixel(x, y, dstPx) + lutBuf.write(outFileName) \ No newline at end of file diff --git a/Gems/Atom/Feature/Common/Editor/Scripts/ColorGrading/lut_helper.py b/Gems/Atom/Feature/Common/Editor/Scripts/ColorGrading/lut_helper.py new file mode 100644 index 0000000000..459fe241fa --- /dev/null +++ b/Gems/Atom/Feature/Common/Editor/Scripts/ColorGrading/lut_helper.py @@ -0,0 +1,186 @@ +# coding:utf-8 +#!/usr/bin/python +# +# Copyright (c) Contributors to the Open 3D Engine Project. +# For complete copyright and license terms please see the LICENSE at the root of this distribution. +# +# SPDX-License-Identifier: Apache-2.0 OR MIT +# +# +# lut_helper.py + +import sys +import os +import argparse +import math +import site +import pathlib +from pathlib import Path +import logging as _logging +import numpy as np +from pathlib import Path + +# ------------------------------------------------------------------------ +_MODULENAME = 'ColorGrading.lut_helper' + +import ColorGrading.initialize +ColorGrading.initialize.start() + +_LOGGER = _logging.getLogger(_MODULENAME) +_LOGGER.debug('Initializing: {0}.'.format({_MODULENAME})) + +try: + import OpenImageIO as oiio + pass +except ImportError as e: + _LOGGER.error(f"invalid import: {e}") + sys.exit(1) +# ------------------------------------------------------------------------ + + +# ------------------------------------------------------------------------ +# Transform from high dynamic range to normalized +from ColorGrading import inv_shaper_transform + +# Transform from normalized range to high dynamic range +from ColorGrading import shaper_transform + +# utils +from ColorGrading import get_uv_coord +from ColorGrading import log2 +from ColorGrading import is_power_of_two + +shaper_presets = {"Log2-48nits": (-6.5, 6.5), + "Log2-1000nits": (-12.0, 10.0), + "Log2-2000nits": (-12.0, 11.0), + "Log2-4000nits": (-12.0, 12.0)} + +def transform_exr(image_buffer, out_image_buffer, op, out_path, write_exr): + # Set the destination image pixels by applying the shaperfunction + for y in range(out_image_buffer.ybegin, out_image_buffer.yend): + for x in range(out_image_buffer.xbegin, out_image_buffer.xend): + src_pixel = image_buffer.getpixel(x, y) + # _LOGGER.debug(f'src_pixel is: {src_pixel}') + if op == 0: + dst_pixel = (inv_shaper_transform(bias, scale, src_pixel[0]), + inv_shaper_transform(bias, scale, src_pixel[1]), + inv_shaper_transform(bias, scale, src_pixel[2])) + out_image_buffer.setpixel(x, y, dst_pixel) + elif op == 1: + dst_pixel = (shaper_transform(bias, scale, src_pixel[0]), + shaper_transform(bias, scale, src_pixel[1]), + shaper_transform(bias, scale, src_pixel[2])) + out_image_buffer.setpixel(x, y, dst_pixel) + else: + # Unspecified operation. Just write zeroes + out_image_buffer.setpixel(x, y, 0.0, 0.0, 0.0) + + if write_exr: + _LOGGER.info(f"writing {out_path}.exr ...") + out_image_buffer.write(out_path + '.exr', "float") + + return out_image_buffer + + +########################################################################### +# Main Code Block, runs this script as main (testing) +# ------------------------------------------------------------------------- +if __name__ == '__main__': + """Run this file as main""" + + operations = {"pre-grading": 0, "post-grading": 1} + + parser = argparse.ArgumentParser() + parser.add_argument('--i', type=str, required=True, help='input file') + parser.add_argument('--shaper', type=str, required=True, + help='shaper preset. Should be one of \'Log2-48nits\', \'Log2-1000nits\', \'Log2-2000nits\', \'Log2-4000nits\'') + parser.add_argument('--op', type=str, required=True, help='operation. Should be \'pre-grading\' or \'post-grading\'') + parser.add_argument('--o', type=str, required=True, help='output file') + parser.add_argument('-e', dest='writeExr', action='store_true', help='output lut as exr file (float)') + parser.add_argument('-l', dest='write3dl', action='store_true', help='output lut as .3dl file') + parser.add_argument('-a', dest='writeAsset', action='store_true', help='write out lut as O3dE .azasset file') + args = parser.parse_args() + + # Check for valid shaper type + invalid_shaper = (0, 0) + invalid_op = -1 + + shaper_limits = shaper_presets.get(args.shaper, invalid_shaper) + if shaper_limits == invalid_shaper: + _LOGGER.error("invalid shaper") + sys.exit(1) + op = operations.get(args.op, invalid_op) + if op == invalid_op: + _LOGGER.error("invalid operation") + sys.exit(1) + + # input validation + input_file = Path(args.i) + if input_file.is_file(): + # file exists + pass + else: + FILE_ERROR_MSG = f'File does not exist: {input_file}' + _LOGGER.error(FILE_ERROR_MSG) + #raise FileNotFoundError(FILE_ERROR_MSG) + sys.exit(1) + + # Read input image + #buf = oiio.ImageBuf("linear_lut.exr") + image_buffer = oiio.ImageBuf(args.i) + image_spec = image_buffer.spec() + + _LOGGER.info(f"Resolution is x:{image_spec.height}, y:{image_spec.width}") + + if image_spec.height < 16: + _LOGGER.info(f"invalid input file dimensions: x is {image_spec.height}. Expected LUT with height dimension >= 16 pixels") + sys.exit(1) + + if not is_power_of_two(image_buffer.spec().height): + _LOGGER.info(f"invalid input file dimensions: {buf.spec().height}. Expected LUT dimensions power of 2: 16, 32, or 64 height") + sys.exit(1) + + elif image_spec.width != image_spec.height * image_spec.height: + _LOGGER.info("invalid input file dimensions. Expect lengthwise LUT with dimension W: s*s X H: s, where s is the size of the LUT") + sys.exit(1) + + lut_size = image_spec.height + + middle_grey = 0.18 + lower_stops = shaper_limits[0] + upper_stops = shaper_limits[1] + + middle_grey = math.log(middle_grey, 2.0) + log_min = middle_grey + lower_stops + log_max = middle_grey + upper_stops + + scale = 1.0 / (log_max - log_min) + bias = -scale * log_min + + _LOGGER.info("Shaper: range in stops %.1f -> %.1f (linear: %.3f -> %.3f) logMin %.3f logMax %.3f scale %.3f bias %.3f\n" % + (lower_stops, upper_stops, middle_grey * math.pow(2.0, lower_stops), middle_grey * math.pow(2.0, upper_stops), + log_min, log_max, scale, bias)) + + buffer_name = Path(args.o).name + + # Create a writing image + out_image_spec = oiio.ImageSpec(image_buffer.spec().width, image_buffer.spec().height, 3, "float") + out_image_buffer = oiio.ImageBuf(out_image_spec) + + # write out the modified exr file + write_exr = False + if args.writeExr: + write_exr = True + out_image_buffer = transform_exr(image_buffer, out_image_buffer, op, args.o, write_exr) + + from ColorGrading.exr_to_3dl_azasset import generate_lut_values + lut_intervals, lut_values = generate_lut_values(image_spec, out_image_buffer) + + if args.write3dl: + from ColorGrading.exr_to_3dl_azasset import write_3DL + write_3DL(args.o, lut_size, lut_intervals, lut_values) + + if args.writeAsset: + from ColorGrading import AZASSET_LUT + from ColorGrading.from_3dl_to_azasset import write_azasset + write_azasset(args.o, lut_intervals, lut_values, AZASSET_LUT) diff --git a/Gems/Atom/Feature/Common/Editor/Scripts/bootstrap.py b/Gems/Atom/Feature/Common/Editor/Scripts/bootstrap.py new file mode 100644 index 0000000000..0070611592 --- /dev/null +++ b/Gems/Atom/Feature/Common/Editor/Scripts/bootstrap.py @@ -0,0 +1,60 @@ +# coding:utf-8 +#!/usr/bin/python +# +# Copyright (c) Contributors to the Open 3D Engine Project. +# For complete copyright and license terms please see the LICENSE at the root of this distribution. +# +# SPDX-License-Identifier: Apache-2.0 OR MIT +# +# +""" +Boostraps O3DE editor access to the python scripts within Atom.Feature.Commmon +Example: color grading related scripts +""" +# ------------------------------------------------------------------------ +# standard imports +import sys +import os +import inspect +import pathlib +import site +from pathlib import Path +import logging as _logging +# ------------------------------------------------------------------------ +_MODULENAME = 'Gems.Atom.Feature.Common.bootstrap' + +# print (inspect.getfile(inspect.currentframe()) # script filename (usually with path) +# script directory +_MODULE_PATH = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) +_MODULE_PATH = Path(_MODULE_PATH) +site.addsitedir(_MODULE_PATH.resolve()) + +from ColorGrading import env_bool +from ColorGrading import initialize_logger +from ColorGrading import DCCSI_GDEBUG +from ColorGrading import DCCSI_DEV_MODE +from ColorGrading import DCCSI_LOGLEVEL + +if DCCSI_GDEBUG: + DCCSI_LOGLEVEL = int(10) + +_LOGGER = initialize_logger(_MODULENAME, log_to_file=False, default_log_level=DCCSI_LOGLEVEL) +_LOGGER.info('Initializing: {0}.'.format({_MODULENAME})) +_LOGGER.info(f'site.addsitedir({_MODULE_PATH.resolve()})') + +# early connect to the debugger +if DCCSI_DEV_MODE: + APP_DATA_WING = Path('C:/Users/gallowj/AppData/Roaming/Wing Pro 7') + APP_DATA_WING.resolve() + site.addsitedir(pathlib.PureWindowsPath(APP_DATA_WING).as_posix()) + import wingdbstub as debugger + try: + debugger.Ensure() + _LOGGER.info("Wing debugger attached") + except Exception as e: + _LOGGER.debug('Can not attach Wing debugger (running in IDE already?)') + + +from ColorGrading.initialize import start +start() +# ------------------------------------------------------------------------ \ No newline at end of file diff --git a/Gems/Atom/Feature/Common/Tools/ColorGrading/.gitignore b/Gems/Atom/Feature/Common/Tools/ColorGrading/.gitignore new file mode 100644 index 0000000000..60fead7091 --- /dev/null +++ b/Gems/Atom/Feature/Common/Tools/ColorGrading/.gitignore @@ -0,0 +1 @@ +.solutions \ No newline at end of file diff --git a/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/LUTs/base_Log2-1000nits_16_LUT.exr b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/LUTs/base_Log2-1000nits_16_LUT.exr new file mode 100644 index 0000000000..744d53464e --- /dev/null +++ b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/LUTs/base_Log2-1000nits_16_LUT.exr @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6c9f3506348d675c15d65e6f4a5cf1b773144cf5c8a2227c1f985806e6afe4b1 +size 1042 diff --git a/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/LUTs/base_Log2-1000nits_32_LUT.exr b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/LUTs/base_Log2-1000nits_32_LUT.exr new file mode 100644 index 0000000000..588c73a0cd --- /dev/null +++ b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/LUTs/base_Log2-1000nits_32_LUT.exr @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a269460a16993fce1d1973bccf53bc7f88a66ba1bad7b444b258bcd7b26527f8 +size 3326 diff --git a/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/LUTs/base_Log2-1000nits_64_LUT.exr b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/LUTs/base_Log2-1000nits_64_LUT.exr new file mode 100644 index 0000000000..4a75163a96 --- /dev/null +++ b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/LUTs/base_Log2-1000nits_64_LUT.exr @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:767ebd1863954ac04c16a68ec90c31c1ed15dfda26239dd0f0159fa279100661 +size 18642 diff --git a/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/LUTs/base_Log2-2000nits_16_LUT.exr b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/LUTs/base_Log2-2000nits_16_LUT.exr new file mode 100644 index 0000000000..64be39f369 --- /dev/null +++ b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/LUTs/base_Log2-2000nits_16_LUT.exr @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:05e1fb5ea519499012cfe11b4fa245396e6ae49e476fe7a5951b20bf28a367b1 +size 1063 diff --git a/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/LUTs/base_Log2-2000nits_32_LUT.exr b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/LUTs/base_Log2-2000nits_32_LUT.exr new file mode 100644 index 0000000000..9e87af6e5e --- /dev/null +++ b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/LUTs/base_Log2-2000nits_32_LUT.exr @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:52386c8753b282e5ff428819e79a5ad1675ad86cdf75c8402ea1ab41e630ac98 +size 3328 diff --git a/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/LUTs/base_Log2-2000nits_64_LUT.exr b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/LUTs/base_Log2-2000nits_64_LUT.exr new file mode 100644 index 0000000000..00ad138501 --- /dev/null +++ b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/LUTs/base_Log2-2000nits_64_LUT.exr @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b6d7bc8a85561d37aaf3f5ed6547ce939759cd00db96874bc9e6107c3ee12e23 +size 18421 diff --git a/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/LUTs/base_Log2-4000nits_16_LUT.exr b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/LUTs/base_Log2-4000nits_16_LUT.exr new file mode 100644 index 0000000000..4e024dad46 --- /dev/null +++ b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/LUTs/base_Log2-4000nits_16_LUT.exr @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:937b4d3388f27947886f49cd935663142806bce38768b83c89b8765c03bbd67b +size 1047 diff --git a/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/LUTs/base_Log2-4000nits_32_LUT.exr b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/LUTs/base_Log2-4000nits_32_LUT.exr new file mode 100644 index 0000000000..39ab05ffcb --- /dev/null +++ b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/LUTs/base_Log2-4000nits_32_LUT.exr @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0ce932c419c11ed2366cd94e27547f65d11abcd604e5262583a36e661d4ad41b +size 3329 diff --git a/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/LUTs/base_Log2-4000nits_64_LUT.exr b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/LUTs/base_Log2-4000nits_64_LUT.exr new file mode 100644 index 0000000000..6c876fd065 --- /dev/null +++ b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/LUTs/base_Log2-4000nits_64_LUT.exr @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8786dc9bcf1afe914fafaac63659e3d0fcdefa453c5bee153fa915094c0df132 +size 18604 diff --git a/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/LUTs/base_Log2-48nits_16_LUT.exr b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/LUTs/base_Log2-48nits_16_LUT.exr new file mode 100644 index 0000000000..4ae30ddf60 --- /dev/null +++ b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/LUTs/base_Log2-48nits_16_LUT.exr @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:155b3ba516d77fcfc9a77a7e96acbf450759d87ee7f042730d1d75b0f2628902 +size 1038 diff --git a/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/LUTs/base_Log2-48nits_32_LUT.exr b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/LUTs/base_Log2-48nits_32_LUT.exr new file mode 100644 index 0000000000..44355677e5 --- /dev/null +++ b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/LUTs/base_Log2-48nits_32_LUT.exr @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ea718b119139cc8a55b944555ab0b0ad9d012a676c5e4c63bd338f26e8290a01 +size 3309 diff --git a/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/LUTs/base_Log2-48nits_64_LUT.exr b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/LUTs/base_Log2-48nits_64_LUT.exr new file mode 100644 index 0000000000..32a6600e64 --- /dev/null +++ b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/LUTs/base_Log2-48nits_64_LUT.exr @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:75340a9238177b5bd3b8f8a3d4864fc75a613ec29222ecf7c90bc5e3b4bc8416 +size 18349 diff --git a/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/LUTs/from_ACEScg_to_sRGB.icc b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/LUTs/from_ACEScg_to_sRGB.icc new file mode 100644 index 0000000000000000000000000000000000000000..ea10bec0b50b602ef9f107f425fb37966c1e2468 GIT binary patch literal 394128 zcmagFbyOQ$`0q_iT~2%IN+~UEfkG+n5+o$VT?io|Bm_c82!RlR;O@aSxCaX^308MM zb$3^)FX!CfyYBnPz3bg;J)iyEGSAHHwbz91oO<%6+Ec&)X`bAenI1+BYFSo;03)YFqpIVLDVDcO4HMFCDZ_pbl%H6uD4K)e-2Rbbva5 zg)#U)`*8Tr2V94z6QsjkI6hp5vtSWAARV~QVIBPiZ{Z8|F$)T`a1Ppn=OCTv|9XTj z_+Cf^B1!+>Tu0}BkClLFY4KmxqBRg5ou!Zd{Q07ghGfSh1MU04PU{8%`}~|94_+{c zaqb%;@2zoR4qecH=(=XuRo~jRW4LusmYes;I=vTeXGhq2ew(9(KU2%L$VEl5(c2ti z+5Ea4JCZo8zFn;Jx6~B9Cpq5j;~#$H3Rly*A8X0t%cj2`W4oC?(Z7HEj<8V8wZbOdE9UMbmX09f6Fqn zRIlXL#in-N(AKAi7khth8#I0ktY{Y*z4CGEFgf(q=VZspLk1vlC+#2!G}HO+KpEJz zOJw*E+}QQm(8Yc`b4%%2doT-7@Y()kNJq*;hZJs;w9b(iaaVB4DLL9K^po>#NhIU8 zD>9DhKj1c&xQIvwY)^q>lpX=;1VpH3dDb3Cjn}!HMvxtFao$VsLq2+iYdz2)lcE)F zgW!F|k6a+WyGo0lHv0Z4-{!Cr@=t}t4h&UQj@l?;jH-LqhVX6GZ!NX(zM8KVJcLc{ z!=qk^lS-AjEi#}k^oTw3M*U_pBFeYE-!v69(f~QELF+X2RkW(vJ1+vrDv zy^MQB_zV6ip$KDwc%S?iq8|Au6%P$ZO{OP-1?YxM8Bl|fXCuA5u*BR&fbX~+d8ux1 zaOd;Cx-P@V6hfUn2rCuwj@^XnqG|_wqIGeV-4mj!B*}J=WLoNHQ$gw~+h?6e-c)wo zs-7$?ms=hqU#-xy`097GV${OKk5`F1%0X!6H}U0^Bka`a2;QBs#!K(-}|rI+y~eqM1a zF;L2~_?<{^%8i8YuuT7gq#57eR8UF;sFwON^(!zTAT>SED~q-*W5{EaR+#w;u$%r@ z_FrzrbVbf;SI59bIUihf1NpfpobCqR&nt91#cAdONqJ4oY5d0@Mdno8^uI{a6o{#z0gUu70eb>n6HEf0FzqF4Xua$M zkz;gu==*T9KyPkYh&^K&e@D zU?_O-aO_+7BQ{JP2-UK0#83N9h2RqZ20aNmmSpGS8S0n}^&SmvNI`kQLVu<@d9LA5 z(l!F_aK_W_x@*GzPS0^W6&8?T?fN*ZKI5jVZrF>=7?;D`gIP!SpFu|n(?=|DfB5*Dcr^>VQ=E?4|54+ zhpNIJg;lYdxQXHYf%D-8{I-Ca@NPjCC4uKF^d)uhE=PSKtl%?5iP%#9vzX`T@CdTR z1IdWEAeF;Y1TL}?=p#W>Yy$)*_!ZX-z7q+Pr-Mo(mGM*`M&x|L0U$u=lyJivAe1J? zdtro=Nqam6QMyTLkBTVQWJkbl-YA;i(aO`J!#mpfx|pg)C7+8ERbJvhBPbN@5j@h1 z>h!t-T4&sDjdDIh3k@#-(SJW$so#+n|FUgO2 z4}U0mB%X!UO06V$P>wW8>JM?2cFWfK+Dl){y1^isNh}z|lyPEj`eeyU;#j~LQ4QjQ z3M6Voyi@s#t|RZXDq`%>xyq$6ZP@s-CE|nlru)`y^F*<|)+`nT-9ko~kx+22C-sI(kc&T7hBP73FVA3SF^tc9$b z^P3w?oXNEh*CQx$`Qd|jMQ$SxgsacJz`Kc6=lO-=P5PwxVXO|=27iHwEL|@NM%#mXIGxp}Z#3v*Jb4f&Z z`Ged!(i`c6JafOa7`wbO|G$N|@_te?A|~>w0UyF|=TFjsVU`8k19L+93wVryV0po0 z&?RPA;Tq;GMp7Z3b&P(kuqwEX=2m!}okZ0r)`xid3lzQ~^AuY}VrZ-13WbW}Mb=T= zcP44E;uV1{Usi-9ew0#+ddOihONux6 zT@^kr4)eDVtSFwL%6R@I`T+xB4@x++>!GbBL-gnD(o)^P=d7Mm0OJBvr!+aJlM!5c zoGGEdEB(W=pw*WhVLc0=m(hb2RP(Yt_CbHsG7YtrJ1p2(fu5>TFz6e>Gge2rG zDt(UnlW9{1!<3}lE$hPVOL$to2455BQ65TMEqPf!O$rfRsMtjw6n?DW`+X7kR%rc= zcxNg%P@TDDm4pBwC$+MI<{na0d7G{u{H|&T{VNMsg$kSs`ll+L5y{A{nhM$#h^zV# zG)v!Cy^Tqv?W}fXJ_y)f&1SKv_SFj3BY#45Z!nRPRsPA_V}w`!!P|3zU%dl|D=Tb( zg}tbXB%iPCyDDyhlNwAb?I9*rJ(U&EOC{GTf5C+XiYf|nZT9)9F;sE7ym~ukV{%Tl z5StMHrusDQL2PNweu9-Gz9xzoBWkEQPU;Z;uH8buDu}Q3_j|~P)izQdg}c^1^}iB^ zSMH;#LYtL-0r4Sgl?s|yaG`RF_J!rC{7A26E~_&PbYont!v!7>yjB;(K+x~hl`}5W z-qwu=p=qn??gwcCJZsE6zl@%&FgHWZv+ z^R@OQ#Hid%X#^cnd{rjEz4DxtcM#glcXduE^R%UPdFa9zyvZqOzxTYZ5_n@GrJi3q}Yf{la1Qs=&4y4gf)$j3`9AEQ4 z+_#{Y*86*29B`;_^wv{Z)qe)&ws0G~LA&bKHB^9GDxnP@AxBDfHTpt33fPTRaQ&P; zjqec28MaM88dZOf>) zSVL__0R-mhHb}tvpr>tInthN#Q#+t#!nCOw&^B?nsbPU8P1ihH2Cp{n^nBI*s5#6V z)n?H=2|Qo_sAVGvS#93J1)nTi(=r2bR4`gML+kPkTG_DQS+1?)2;a1>wzbHtWO|z) zN}GUbYev6}i*5UWT_(NL?uy$i4r!O;*NPn5$M8R*Oxr&ZZbgDR42jJVr5#ujm-nk9 zg}g63siT`b$F=LY=EvlG>-a@k6gtznpOO$V)d}?1VV~|~_)CLtcP9FOV14Usrs7#v ztuNf$Caqha|8KVK1Sp2#Z8VQFy`naimr?u8_9fosjn(Z0pY=6g+f|_0@;e>N!4HdF zI`9xc!Qzf;Xi1J<$8*@-jI2&;#Ew)zrwj>BvhLKNc=433CFqpc(Jl{+Lh8|#j7=7A z?Ha@JMJu~L<9(wJs7wieMaHVgg!2&(RH?*7K3g?N(&z0}JtPftA9pV&Bg1;T&B*6D zs&14YD0IAAiy-CZ#<*og<6 z?0ec-$S(jB0GA6@V^CCz4?Sv{>$D8qA9PZ_a$*GJh^Wj$&s7TcZAd%meU6!n{cZ8g2+{& zLw#~T-H>;x8rPTFC8~1QS6W?Fsq1U)V%3z}!07#M9rs6S!)~yLMOSrqg=axaZ1+>I zuXQhaY=HQx+dauXon^i~mqFi)^m_OCI^~0VIgqGqO>ZBxK10^01Di?}_W|M8lUn;S z5Dya8_nk&Qh^y{jg*qvV>Ia}(CEWffj4URrzYgmheYgJ{_Dhsc|94z{J{i9Kk^OAHB}ozax<8QB(ldmsmuD!nwI zMH9rI20mi`j)4y9VU9=l4}!7$D7Qf&Zdv5~U@5LlFg7@XH;Tv{yp6Bprw{26Hu1`a z^a)AfT|*9p&)nlf1R|EJ+n?mZnab;zyM#^U_DfvCr?UGiUH42Z?Z52iHAqu$bx-Sl ztEK^NwLMa|d0I9y)$hGhYFPvJ-WMxw4J7z%EEya)0rD+;F}MLN$_p7p_*P{f8Z3Ye zWEc)!g3hE8hql3{lV*mH@bLu9P#U6IZaOrHjE+4t^d1F}f`|8`=Ee2HXmo4L`e7Lc z8C^cyf_V^y8$OTa3wIBH#QqYz8QFr1jCea@i+jxfHA2Lr`I|>1_%WXKND*OIc=$k; z^XX~pfmG+S(^dmX&gZ5r2U=XBCvFeib1fbM4eocl((_=D3)t8GaB##UqA6l%k>{jR zG6eEoTKQ!tALv$kedvadplIFjeo$$C(J%u%m_reAM;~84)sQ)9MQxRzszPLU7nGu{*!whQ#z%%38CWa7>u`4F-A)ZQwlPi#^65Yuo zsLe4GlW0_pD0wmheK49ZsX&)Tkth2wONAkm=P~?9`Q$UqO+lqb7i$x7eQdFl!OWY{ z?@op@FGs&P9hiABw#jKoyKT(Z`RqvDSeonNe*D;JH;*pC_(u1n)@|ctfVRP5ywc-) z&Gh&!FO!O{i9O!Pl6Mn?R;lkKInmEL68Bf!Q7?u3ioJIo0qnZ!MvoXoqjVO$WsI^8- zNBe1UXtOA;HWFPTOxEV2e@8ZG+b{&d{c*Wt*DP~f?5LV$j7K^4%m$7ZIk{xy1MXo`AVdsthKI+81KrLF)7%7~O~0ev;5(Em()vPDlPTJGC?b)r?S-w0&(_|B4aU8i zS_!AdQl>26^U^m{7(}w9bt)41mzY0QfGmjdno^;bh`gsxqWID1smG{)qC%#ApaH^^ z>5b^hNbSTMN0-?f6VDypX0J~?b#$M-Ho4sK)RfhvyVH%)Ym;#<%ha`#Q?72RQ<{}- zqBgk(?cUzlqbUO1RDw0vJawyFwcEV*m8EJa-ZsU%wbelPf)CoeK7hPMQ`yGC%|#C;puw#J!#bR z41y(bnSO+LA>J^v2uX_BJhKxyE7~_>jWUaNn1Q1Tqlhz1)N7$agLJq!2hut;&0W};)($u7;*@-z8s(Iv`GvK7%?=sgNrVV!e)qX(R?tY|+q5Hb{`(jd_&KN*; zB)ynHK`te3pOHZ&@sgQ(n10;LnK{^StaRoX93XR;T?s!X)txm$fW+5ly%2*jH)mg>e&>CSK^u3UdZ!=qqDc5 znexWDMX-Hwc5?=>HreMn0NhNfnWMqGB*k-b#7=R=Tp1!MrhQJ0crKcqJBx%xKbm`r zY=}1a3zxY)@#9~Qv&Lhtt>@<1aT+%G7OLoqP0ErbB>L7vP9UH40p?i1R*IEL< z>u;|+=@Dmet#P+&wP8`ShZFYD&Q^1Ke`8+TYn#r)#U1fh4rZmDpN`I(N2x$Zo>*9Q zCz$@QyxP-r_^36kx81nJrn9foXt(XBe(Aw6`^{>%1E~&&)ZY#1j)w-C_M@Cu3_9-% zbh$*`lolWW6p!=6Gn*O66vAKZ?O1nC8C+ZVee9liCQ ze0AKf?LCS85wCXcO1%>-*mXK-ypFi~1g?HnWS3ckTPlJDO)~*I9(M%B<=v7iOD56)}gEiX;kf4-D`OW@1*Ekb8wGybl*+GA1+q?W&1z7d{;Z}U*S5WzP!)S z4L?9P@N;`U@MLeTyL6DI{|2yO@T9&kpm6B$p20(RIN$Qe4}A%DOz$%i2;5|wjE_bC ziD)})FVkhun_i2*Nv9p@NJ%E=9#v$FVjC@aIU+=wwN?H($QqlQiYq>A?W84g&v=Jb zWiQ+jj?t9|To_KLs_h+nTz1v|Z4YoIDv#SPa!acxS-o~IZ_rw90Ms?DJWBB>ZgxB} z=Na4rH}m(hX@!}t@%qtbV{*k?*}mLZ3-o9|V>AkU)*(N1+(+KI{@@RvKb_47EkH3{ z_6H(B@4BW9hroE1yWvK=944r=)K0^a71Y_ghdfWIaQK`1P)c*$D%d4Rb2=K$4efQ# zlJqiaU3KD`{AF(3L=U2&`>~WlOsL0(^m2r)CnSpj3G>Rxc>r4DJ(h3e^%Hor5aeO( z^SB7;mJPa5a?oWD_-g58$CthnKE*C&0)(5czCU~ z1ql9Kx&7#VM27OI`DWy`md$|D1Jlk;S$u9#zQ6-(FYrcO!jy? z(l}M;yaVZ5%XPgkGS25z0_DN$l4^XsLaQa$L1y73!56TXU?1nKFD2?2Gae!o8`Bm; z%Vn;9masngcKlQLaKbERF`_rw9U(^6rDj7tQS$U*urE3?vjJF#@y(Wb?Z@uTJp#Ca zy`MMeb{bb)aM0xu-lZ_kSs#Bv(d(E?U>2Qo*hXAbeBAB?F}9@3wvzb0G{r_v5|tsX z1*9A0tE>{qHsxx|Msi^V-r^$pZN&$R<$ku6$wy%*83j=1fvTe9)MC+VsV9oc(Z%$X z%zGGzpu$8e%+KI|Bna#)&XGt{+@o+#*aQ5P2x%~xpcPUA1;l#Mdg@w|R9s5lMD~>a z!bkY6kF&rS``w9mL>{KJCF;S#{TWFweD6_rr6@qj)X}uvKxP0bJ=H5B;915Uk7`cCyxfspNiH~Dr!ZH!WZg4P@a5?-MEW-gAtPf{_PVs7IrSZGNP z<_znzjDxZc&W-yEeuBMUo&arP_r~AzZ3{6?JOVl!QjtXTF$rCp%=1=;#-s?mtV6G) z5?hE_eg}O6}+1Wa8tJ`|NdoF1Z=(9{zY`=WC8CUl_S~T=W;}x@1et z7Nm!SD_#XZD;X2tgQZK?O4^}VDN-5@IVjDM9q=`jo|GL2+sKy2GC&BKXY3cBXjx=j z9I#s?LHt%Zi{yx(Dp!#j`KmQCW;43B_CZVA0o~oEzXcicKU&nAd)8k z_}G(D>wvnL+tOKjn~*01GphM4*#%}y*l;W&*g1q4dyf5rPPi4-kG!0y zA035gPNa#p!&?)pMLn>w#B(uF=!K-kF%KZ`lB~pm5YxCK*i=tpTnS9uqllY=%Q`;D zcOw68sE{Y3?p998e_-ww(c>j}ot)J8pG1Q+Rze)vCgEM84#h5ZMWU2?Af`NVKH!hA zFo{Q>=08e$!wBPMB$Jq{LxYn~vGRgbQ|#EfL3dJ=A&fwJ>dMd>nt3XnbCIf-st)@= zu})jbeM3%9!-qd0en_k2og@g;?(qxphtm&4ps=6QLj_qED4#2t{@;Nr{1-Xnv7$4I!T1Z+xk`eBko{PA?9-&z?hV-w|E3?(ClDiii(yr*rCKxPKeYr<_Z zk1@7zFj+=H5_WS|7V|92BcUlm9(X8B$Y# zVw?yLEvO56#3UEIVZLGT3$0l<>C=U>;0c;Z;V`>|+FAH11nW;%n1-&V7%EtyBjm4& zJPw}pMlsHLMx0l?4vQeJFWMdUgx@F8bv6On9jn?(Z4#vABtv!vmG*1RM`LQv#zs4=pOGpnqqllspTZXVsP-U_1zV zQyLVcVPHxdnK|@-O7F0|X}M+VS@QviGVkC9s(x7%+s=P?Src1BIb3!s1mfph_95f~ znNYqh)Qgl?>;xPfdi6i_2EH6r6lZ~ssJ<272G_SVme@nwl&vL|(D{m;rHkPGMV6&3 zBrEr6>1p)3Oue$BnC6sYWjQ$OgtKL@@!fHU%b~;w7g>#cD?E{FM$jUexDkQ6Nihd;cUX@PZG8VAPHt=H5i7GZDnIWsH2|60+ zUUfF;27O)CJTsKGvf7aOAz*Vgf+eIHSBqI6{Xx~G!NHWc^2^@P5oY-%Z`eps`E_sJ zaBRhPU`?-GMG$Cd+wY1Aa6!ZRNi3CnUz<$%9By2D z-2Z8qr*a8Z8>&zO0`k~Dl`W;(iJ-FqHZ|)#|BPyC)_LiSPS&jVT0e@dL3vyBJJeJG(>wKQ-h);& zfotL5>Y6*XT@c&y&C1o#lZsnPCLEKuPpL(m&%9BmhjLAQQzt;zC!y+QG4t}@^&4=W zvZwWQe4J!;eFvdk6jc9}ct-fV!HslYFw!6;pXE0-jQ9(}0 z7P_dhf;!F~X*?A`3yy94K+|P`ns(5#m|jhu^ff`KCN4dd5z>?uxHK@KsWUKwK2pEf zu+pO8GQ_oHaia-ztN`99 zhabsV*?0+2l(DDD82KtCy(t>)kZ9L*0uwDi)ciNLT?TEY<4%h^n;Y>@MHbC(2oIx{ zv{(}_34XM2NTU%OTbjseJXXs+KPdM?>)(`>Vfa=LN+)M+YqUQ&nSQb zxVH5v^);)hZCL<^IoNg};8D<}HV_RGw6-Y=&^xiODGks!VbGKSP*3PL4ST2uN1Js# zzjdEzhI-T5Ha9DQcj`|xe+5yix3!?a*GfOPG(x}%-}jvY4Sfj;oiTXe*EeY8Jna%`H(@yKoGhSuQOS*Oemnnn0I6mA;OxGCbOv#XHweP;dBozk2 z%WYQGLp!tdRL@`!)2?(|BUUA!?G_=866U+LC>uGg`#0J}_M*obb67IjBf+kX8R}7C zA4gy5d5Wu#I?}rbPmZkYg%DN?_V-2;n)o++l|(0AZSPs)sc>QMdlHx%(f1c=CQQhLksFJ&W(tKCNx_(|@jO!Q8H&vb6)aWtQ1NV38HQk3jT)UFG zrJl7d^zM`1OY1K5>;N*Vj`gs8M$4>v2EZ$emh~?4_06~JML-g>+j~o(-5KoO`>+eC zL4Akd&yo~<;fQzfzxve3H*qFIDDNU<@S^RcI^7e{=&QcyrKp7u?DW1@F*CsMF(|1WXakW7FAjVJr{tjrEq&Xw zHw=m((-|8F)zC|+o`c_D7n4*&=I}EKE<;>IhkWNy6EZP&>(CVxQffQA9KBqeKWvL0 z6#W^dVgjPmhto0dqr8UuuyWzr;p@27g1f^%aq@_JBfD`Q`L9P@@HGC?5r6zCp5aIg z!8n{c5bAtw+GHTu`TDf+0Mq%#w9!C{OX9@Tz?5tK(2>DqZufgm48j3N+fNLZd&ryc zgO5B7ZedLPyVO>yje(W$1JeT7!oauW#(|h;?{6m^L=IQQlSal6@o}V)cSw*-KDr0_OLAirhH4l4jEc~3(Us9s^rPsE(NT;b z3Nd;U^INDt`U5MB+%vWX`%GXwW`-j~IFA8wvwXrB18=}n4EZ^`O&=Q~EpTp#;OxFY ziSxtB+@T?t-@~hhe!AK8_78iz%R459^8qKCvBS4K*VToL?Dv9Ky%`DfPA3fBPuNB`8W;rQ`9gXkIsk=9hB9LN{~_7gM?)DYaiI?1AGzkL=*t`3>Gn^jax?&7 z(Bd@Of8F}Ni z5Vtg)@hedC0nE_H|+w@mb24c!4Yyzn|QI+85I~ zX@lwzMNMMSHqpSzD0FiaXi|aMEF?_!VC0d!$&;Apf~?7BSkH*#qj#N5XC98;bTXT{ zKYG>4eCFQhN2giMuQ3znTO+AsA+GECUBxn5)agOW6FK}_Dc+$}~E$#JWI3y}1VX^@VPGU@6 zhiyqyS$+I-J@Pybm8V15x7NE&Q9GAS&^dK?fHqBM!%^0EP8;T|ZX}6*-M*C`Q z(auqRS}eLr7^xLt)iq!p;_`c$#Hm=G>&r|nI(=#IzhC#;~mb_QN!`q zF4_H0CM;Y}sa8)!yRU2=oEQUmG~Auk^@ysCob>cmRx&43yrxS#CXajHDss{+2fiv; ztMT!9m%Brg2zr%;*J!~v)6Zyr_)ez=Yt0}<$zUxFN=<}m^I^Np(eqMV|QW{#lhqkuEss9(Z(jk&|EIaiI@0$ntw4!0NR z>&TpH)ucKJ#*msB=ZXOX?Gl$u-54#MxJns%uleo*m@| zQ>k8>;=!pY?^A`DQ@??y^2(;|e5SK+O^1WJGSSnG;KH=G(>HtrQm)M`g&az{K64cE zFmdUOA2cJLHIo245_fH;6?QB(bmkNsAv2nJ1-~NsFuNLo7av=Q0?fvon)ODSiEhmX zAd8|u&5DpeqBqQDqp(pht16YpRbFY_VU z&zW!^*PPUuCeWd*MKd?StJ14y*Ml#orq8+Bvs9M!p9`Za}0!$IAb9SkQY-qSAqB<8kp-vlA|xrokI3T|Gf=b zWS?QYgIJ;$ziX$m^kSsru9xMF>@#}ll>@ZB`uytG#99N9@(Ak2enmYEy68YwBMtcK zkf7PYBi8sp%R^VW$&)s*ldfrg`vLt&epr8ZO^c?`A%-XwM?I;SsW4#GXspdvlETh_eHd`1-H& zB+;h~b`^XLGucNjDrI=@KUWIyOE@5}*oe(IWLq@^k2bnoy9#V%!mVR^r60c50CcCC z88&TjE;&-x{M7+{)S|W4Hs0cFyS>$KE6bMmZnSX{w%_jA;% z@^f)?(yK9aL^?;;KCye^a=fn6rr+)F1~;p2_l=F^7AFBqnl2w*2Kdwb=}45vP|Fw7 z-=4{>Uk|r=f!ZFJ2)sVF_Zri^t2^S2=s;Mf*`X-llTPiyRv%s$?7&l>$6a?1>;uK9 z;tgX#m%4TLpLf{FMU|C1K*RM5s~kf3S*ZyQeB{?$hkHK$}h`>n>Sd!v%oM$WO0W}EHIV`X?+MKz^_oKKXpc}eZc7ps2 zwojgf&w-mJnxi`r2a>xGhRB_%Um+inzcTiLexlxFtp{SzC$b-V-oVu5mH=|G^!&YU ziMVYAxh|Es$-?JO*YJoUJx3t^ZLx*@H9~I5A-fFXU!`ko1Bl6`&urX?f64}}%}KO! zo)v&JQnAO9PTo>6Ws$w`vOqaHO`fWJc61%`AtkDA4Qe&zRPB0HT)^TYAbJgbCNmS= zA9OY0HYSd(C;o|z z+u|hX*M5Tdbi_-Fb0QCBMww4`^i}$Ir#u6BQQ>J3zys7*>9@Ts0;HLi9svPgvx42V zwAgI9n-_g)j@0D^U6@OC9;DyTb8yNFMC31Xlm<5DYaEgTzZ7uoYZ>6e^>)V@Wrba~ zUm2Ga-nP~hd*Wcz3W^VLy0M<3B6n7B{cZeL6s+>U7@$f|p=JkW$Bzf#nVI4`nju>n ziKo5e_;OFs)!Z-aYk^UGaS)qfE4WMxVLXf4NYMt>hzv;rCP=J@4`hCpe8d#7%4O}y zKfzXU2zX)eoO}+-V-pe#e52SG6C*%nA#O>Pz%L=HWVJUZ)F7qLYe}dqwcKMS^j4Yx zP{MIecXbzY3ew-WC3BuFGN?dFn+k$1-+mDSW<-C9YK&@ zfxAR#WbdHm0<+k8$a+C?+)r?s;2-%-5I)i*zSn1OWPF0e`%mPlL?iE|!c~bEy|xH_ zlLVfY!tCUg9%SLkE7WCUYOxI(ys`GQv@tPK9e$&NY_@+tUU)EMVNP-3(vx0ue3 zKF0H+W{BMQcm3{(v;qn#EXF2skl-BCDEx!76mN<)!(heHB4?CJd@9BVxlOWH>;hLx z_>zqt*o_`(90GQ|M-~?YFX=cIcLizM5GHp) z{i@8D_hSAOna5k=4RWyYgGA3Xn*;|kF+r0sNTJBCCt6b>F`UFcnxT-HbeR5}KbX|Y zDCGJlZ)IA9x+JHuhJyW*zp#yi)G5@E%s~5;na~ro<*9o(Km5O@Msc@O)}l?%AT{algbKv{ zjD1n-5cvl*>L(;Haf&V;Cgm>D2{5B{g4BoFn+y$)=7kY#m8(XlwOg0b|+?Ou5->V?4$G>Ihpvr7Il&)MHgSd~{x9gm35UqUksSLO%NCI3eF1E)hI1zQ;}f_(~tnah~A z1>LL-3~0eO)*pIJpx!fR}13d ze@g8OUL(&Hcove;MOkkOXR(MhJ%tJGXQEcIu;VmtPVtSjPrA2=Os*6iD;lOO7j_kI z_799WTg;($@%9(b1w0RHE!jX{9m+4E2ku}8mh>{Vvg9Rif))jxDLou?pJ7?bVXElE zrHw2mExhzv@QwiUvem(J{(s7x*#ye3vT*i2%9^sGkWjxpWg{W)$@XQpLs=w#u@3O$ z(2e3n|8b>{&LF=S3G!B*FRllVw8R$wh7gtV5;|-{`TLSN_}QXWrKZUE+=f9tGzVP?r13*SD>LY@;K|D4frhLDm45=?2enjLG3puqRUtv}K!d8%ps%!dRT^eS zz_Y3stc}!9)tgyG)K%5)!JGVzsu{t_6k2(iH+2MEUj82|y_1Ih%WnhKy&Ee`LA%Yr9Tf}pCnm0r-FC5p;scy$4~Y8BEZd*Qbals4V7Y8K;~jH=#??TqiQ7UBPj z4X8dxph-YA`oty?rzVp0kMLN{oZlh=yml4kZ~pdLg#U){Rka1wC1Lw(PgC!PMk<#F zbhB?NJ!yjAK&60gz}liz(oY3lQ=SdvF&dS>1Lp%9>h>|@^sYLepv5$8U09Gj;8tCJ z(CdJ$)mOd#9__5Yw!p6Hf4uZZfi*k4f&H6nn82EjuQekey(WX&9bk3MP^}08FMC~k z3Hnf>Rvv+e<^EP?B3@*wmCsP5)RT42=6M_Y0YrYzPisi=yArN!I7Vp{W~a3lP*a2Dt$hJ2S?R4; z0+N}Pt=|HE1r4?BpfMRAo3McCiNBkWfSHN)O;Etx#JZ+LkK==-O((q8b~iL{^NwnL z+sp-iuCH&N21QkUXwd_|Ej{0|u;*NHuw@o{BKKMA4*348<*i`|L0VMn7_vXvr0p-% zvjqJ%3g+)PNLvHeOxoV|7UwLsYd68$iI%l935SH=+UtnRBe%3)B3_DMb}S*4@J@GF zlVRc54jTC#cV$PCUq0tpM=QlNRMByX(iu|NG4Fqft?blf_}l zs=MTQPGa{GzlhMhZezd4A+6os6hHP+jY@7$kRfdm;e|H@dS?aJhT;88lvYs%I_6Q=;sFV)w^X_Q zasLlhcNNxF*M^I_?)uf;Xra`AmO{}GLPFey;4VQD;sOco?(Xh^5aI^Z-QC@Vx@^|J z*TLQ=_cadZHP7aFpZA#>&WfQ|WDYA)x{k7kIZx_A(J{1AmKUC$E^YOC5a%Z~QiEd2 z(%aN~G5*r8-lS;y@G9>Uw47mUpZ!te18~3`{mTI;VD7Xaz(}z{Kj|rgRPxy;Mr;$B`R=&>&h8WK68xfLr zaMp};kj}CiM$VJNnZ%J#N@TJd;SiXsn$u4x$PZYBTWV}1{$Q7-A{F84e#}Gb~$+ypq`~BcWcT-I0}|->10C&STz6 zE{-n2UQFy6b-@jYnn#&&3ZS*|hJvV*y2eFE?T)vxhkabcHC+V5_avB*M z?=+)+E*lw@}P{8!BHKo zzR+4e3vSH)EcZm*%=#ivMZU_|EkBNWnOZb91N}64`N{CiLFieKGuSZ6m1;4 zf!`|NDi-6<@}4QI30!WRf=XP-u}~xvD_9>D?WA2yli~!aI^LvsON>wEO7dK9o zLCEFUs5*%2*|Sy0iTSKqs)wXm%q6Pdr1<#l>b0c13}^KbvIAW(X5oxB$;Zr{F{aV6 zJ^vHxJf)+LrMs>edpULr0FxFeR=Jh*Rx1L4_d0A8Js`7YsA9?^xbCdd8C+F0qD+Mx zFZ-xG?fI%$s9FJ=UErZY!q?=2Rk?^wSz?t5xi0;s>IZ6Zsz`kh^(>j9_C+ftcy%sD zlE_yput!9f)Q_-_gaFMFTnhi3<_P{jUX})jZ{i{~bix777EK|ck-bebL|o1~s5wbY zWCAshh%e*)G=E7Rj4I_EC+#@$|2o%6GmcVPI(z8>%5WEkLa%If?HrC(J_CH{OHl0x z+I6m1#k&hzY*cd4XuU%9)8ln@i~1O3UHLt=(9^yoQauL66xyi2!F==VHAmn9+3}h< z1UciOrVR;6<7n=nwxp1?OHl8U2wF$9R4mZaFo6j-wME#aBCuA0?H63pKE^rli**Zd zCZ3PZ9FO20&_VE8&Ou!`VISL7mqsXMk#*I?nap_IDA6arPu1h(Jbp>l?&LClQPu1O z7(cJlIo;6TQGIuQrwmuyyY3v>tQG-6`|Z?vw~o$Rnt8xyEx$Af(3XZQO`!*}MxZ$l zW>+Y+t00A?P%Xx@wP=mD2-=&!O?wK~mqXPpgg0cK)43vY(?fM!WI(E?t_QU*89qG) zcq@t5&qG%yUeMcMfC=t;3g)5kqF#cH7Ub(Yu%Gze`cpVA&r1Iq_nd2EScJ!O+zl3Z zHQU<&ChTO14E}@!rd+en@x%l|WA1oz0;Vx@JT(E;xH)=n5!o`rK+ve_ zfBMTV&j)P`s{z}(Ul~Yl`1UP^N}!}kVYunuRyShY2r^dBGEzLQmRA@{zz<4djAtPa z3x%e+p11PUCTHkG&Jhz6)}495)DGvSkC~%24@W;_OM+`uR z%*j%Ni$nHgiQ$+-&Sa5+;JC*4$B^r^Q{8Gfu?Xxm=Ac|K4iQA zT-uB`t#r4l$C)r7Sap-Bz{9J;*>oB_9lal)5AiSBGw$L^%8wl9LS1s6jCaF!WJ$*F zz}{rgCKkg7(-;%>h^UnMiBROS$UzBrVh9BlFPylFI-hWI;u{(#Dw|x5zAU6o zT4Ml$xJe|YlP{T!#4h7iPfD;%u41wZdy4aQ$3#tD!TVj6bu%(n?EcrVK)A!)yfKd6 zZ2@n35{ zIp>aw_9|V_@=X>2u1n=Z<~v;tV-9=P0k~t@-CNyuDV)s?x``E4yX@VbDyDY&0g+1d zjzXYZ*|GgR@V4^lw%>bF%KsJ<_Rz{dXP&YES8o$l?UmH-jNfaSRrfn``@S;`*8^P+ z*fhPSt~@y2GM(VFI?#3%C9+QLsDuvMyzX-INIPQIeZy_o7SU_(;&imMufWmPuB-pO zy_bE?;6mHlV;zGZ4}%>p4&Arj?|4pn^^lvBa=7b&!1=%kdS9+{n{3hE=Pqky=PbxB z(ovTA9M|^IYkPJ9%H&6PW8A{z4Q71cqOnE0q|<5tpU zKV|bRE2!f2VaKe~g-dN-WM`zfAA#qo`5SGa1yAX7jvgr99{#}&Q(76&YoA*FfJ!`8 zU-_G$aX3|DgMQ$6rEU&9!RbT&El7>?gGLT$w#&8V#ekEpXItu>Zvv#P4;**7!P~yu zbAe_ZE=TtQzjekOF>^oHm0^Pc$-9%RhCTdyD2EPtobLVaKn?h4uW|ogu(*$Gc^&+q z@A=*~NKik=q6YGQV1fB@Pw_yB`6B4NLCZaOXzSp`-NUdsL%7`wT^K^$^v;1oge`}; zJWhC*4RZ~X%oYCy>_|Ssc>(y8s*b(j_9WwQxCD46D>rbyyFTZWcPL1a4<|7^G7I6@ zci`M&9BLLsQtAj}dhRIGLgsj0sld3uhPG6GaoYyf!nf5JoSfkGwR(q{2$#BN z_KOf-8#W$ABO4p-j+{ktnnDjt(3obLjTd^LWMV;;1AIq(o` z)<)m|5zApl8fZN!9-?A9$5LehR0*$24s<{hQGYSh?u;olvItkXvRwhKk zqj)6tbV^q+6}uSmBq2UL9jOyP4t#=wCk^;W(SX!_6dd|nx-G#8b3BuZsm69>MiF2(|wq|GJYUHV9sWm}!jl3tWAa{Q0%U4G+O z8u@v}sQrFQQst1{Dz8;ltw-m0wN+=>&ZEw%aX7My>Ra>Z@DZw_Hq|E3+pO-8b)$Dw zU5nK-JTgSs{1%@R@~`nD{$?1vd?R67gjKF1Av21Q5=2DDY@hD`Sr>PM&)ZV66yN0iJ9#gr-REhlJMxdOB7HwR z+0QD2=lRFal=&Te-9I{;3wjwaJLjtVmH=MvZ#Plk%)H-#nSnX^UtKx_zZ6V3(}RKw z2b>T=SBkP7j|JNlqZ~Ygb4q3%iwyo$GHzcRf-B|OT?-MG&9GbK3-VdkZt1(u8{Sst z%kf=WgZ10)f2-(^Uw_c9tT_LL!H<)o{NIEh5cmaLkD{^m1Ww0^Vq1eO<6x0VL2nu7 zL)Qckvi1e84~gZZ`0_&Cd8et)p_2k0c}*Bogd#x0Hzm%+j)Y6ay=cz}P?8zaEaG~y z1in9#m~s}1i#(qC12Pl^PTvo?Wg zXTNv#jqaaL{wGF%$+dBAk2#oYaC#PYmt^Sj3j0l7-W3#nkYd@$32&piRZt=veOd}; zMSSrWXZS~E2Tn=cqMSpj`M;yyhg-22wED=7I7zf8?JsS4^p{w>@WnCNbbPRPtYthr zV9xZK;y#~uaRKb-)GcxExdr4zx{$wvxRm}+kcoTD;0PaL?lN8^>_q*I$0WKUz2cQ( z82mhQwFC+CVumCgg05mJl4nC6vDPO~fX7)8DRhssthUq*p!=-HscQG1?44;8_w8)o zw0pq7xRZEouUFi8yt>z$zK-y`x>0LK|3>*&I+u~Aq3)bJvDbq3as%n9{z&eP`0YN; zJa1+_)rxnX^^-D#@4^8Rzwvvy@q`V6|9BD{M-a)+!aNY@1Y$HzxJ*bw?GXlwwj;g> zTSc$oCxrJBYGEePxpQ7Fel&-KTfnMcs_f!s3GJp z{b$17u$wWMg!YJr$PbBoqmW_O6KiO%g1?B@#LxmU;*8ike%HkB>HB>eB?Lw!wNxUF zFQN=2&0*G(XC-;Ds)(^kgX|>yucRLw9Bw4pnY$S)NS1K#V9?11o&=3enZsX;3Qw`+ zOOc|K5CIHPnNlb?2fvi~67_w^JMjbR>yV##6MC$-M9jisTW!U6@n*F|37%+C`dM<7 zjL6@R&Q7 z_Dl%l6X|MZdc2HSoq38GOJHRFWUawRW*ubp<7J+~t>-4&x~xRBn1Yp6`g*gYxAmQ60Tv*%yT&>f5wMCsDZi*5bpM9hGy7 z>#?7TSC%ZrD{|E(Tp~N;P03yI&Xj^u5Jf94EA67fgdfWmdr$Dn%VK;Fu_a}v{j%d5 z%eVVqkNaBA4_p-^DxV0lrGY9|1%o4PD}q8m;n<3%(EXuJ6_3Ieg)FGt9d;wAu+l#~ zKM+!x8vzQKSE-Ho=y$d9ePpWd#j5R5%X}VIc}7)uf3AwAZS!7MRYWVMLdu39kH++6 z(*LRU+$4vT&w&OFw3Jg|*E`YWQUtdNU9lQg!*1kp= zP#3+o=5Js{lv}N95HF&*HX#@t_On(RvMDsN_EpH4kRx@wLODS{>qudn15ei_h7AUo z>RQ4b{m;~$4%hiTtec8(^_x+@K4Q?^VjV6M`k8V9aZ9IY;aTo`&${TOQB z-C5%TJKiF%sX;L6oNIogHdTbx`lEHlyJ`(sa$acNHr(T^HFb%Ez_i_UH;LzyGV86# z)`^GfGbpLTt@Ss(PVw9t_EG<_YZ?-KESNhRjJ|gCca2N^j>bM}#QB>?|7lDQm_vg% zY6GrE4mJJ=td2O=v^NMA_NK`z=yPa)Q+9A^$n=2*L6p6x8dy+=wyB28uuBcujW&pw zDt%)T@ZXY}pBxp``f3LpPoZ`KdAuuuO)3juPe<3~#u)W4~&btddh&D~Zif?Yn?I)waO^tWv; zIwEhZje z@ac*TI2az%l^f6##_sA1+#OojbvZC6sg&sdIOXl02Jg=|u zu02|+ir&`q!8<NgpY-}}KI z5Z=+Z%D*k_VHd&ehHh>b{(s`!Zt7-rWdKi&ed@XZnk!w?z0D(}ht(YqzR_meeZmvf zP}s8-s;%bt#KQNMUFp#xGK#8u7bEZFDSL_NJ=vDMwV06fd%aJwB`KHs_Tdzg-+fH{ z`9%M|A;MkZi@vYKvwU6uLDCpk+8<0VW1s7a_d3g1GhjiDiaR$z z@}3o2I>7U;jtLy7_t_X7FmS@BkVYT)=sPPaYjBw_KeA=e()WJE?cPAZOWmJdD&V#5 zS1$qZR`;V<;&w(!=ry>{9+vbi2Kn?p?W1^{XqWZ1LF}8>_f2^=*3Rwsgw3p=^_Rja zCHDOf5UmA%12)J~}*0?bK>lz3DmS$D`^$= zUyOrv%$psJlHTxsMx#l;`#_`G1{MG|=&uaS|DUq}oAj3k4g%h&Bm=R)%_F)2xqEcK z-QYsd`OZ~?RPd4J)WI%DNu6l$o9CO#7egSJW2t(m7%nb+F?1g>ninG7hkTs9OUgmd z$=EJcVK%2?rGK$|lE#LCxZPsdFc1GSzhew7eTN$56E>i~S#*v?1mT^YeMz6-$b23}%+L(tj3^gPAw~S7G5p6$| z=Sna%4i&iK4NXJ&|8oqmPF*|n(+wc|Aaw_34sfL>jd?q5d;$N$7lg@88>KDMU=DOjJ_hlSzYp#q`S;G`5|&#yt5of ze!*~*b0}0gTwYE&85bn)^Kyz6$xnOL#EcHVb*VB24!?A%F$N4jaj7->jm&i=XmON=$9Ur`Sr24+jY#&%6JJ3ZwTI@GWR6N;%ECpX zM)>{QGx7z9Z&_#LVATBdfASpk+|*dP5i>LCxBM^Wq4>s_9d<0?>R31~P55oB67MX) zjh)25YKNVZ@MDK3)B=_eH*DKq0< zDi>0M;&#ZsI{!4ylYMdiWtuB{@BGI!dvuLUuQqWM<9b&9Y_!yE>5zEz9?-8RQEuVh z-@ZuB1pR7SFQ2{)t*soJ3rVaLjG;USOQmC_(3?eeW7lBc^ZqC{A(rIKQ1~F%X4)z0 zP%G2g75C6{Q=FCS(GQb0Dlr(Dc!M$pn~>nDl;W&~)yliLhl2U4x%hNmiOPboi3?M~ z2;H3JsuKtNf8e8nLSce#cx$YS=jpYLZrL?hYZauv$#SY-Nj)jV7kaP2Ph1?^du3b3`JY1Ep zL_+SDol_P<=MEK9KGrf# z9IgehPWUcv!J}0JVtudm6F)bOpSF~H3fITIUYTIyRK3#hX_mFo? z`y3y|U8Gxxzr$Ig+e?75x9Fe*DeI^%fVh>3(}{@u_&im#6J}hi3U|VdYg9o__;Hm= z;`C0hR4HBNDgmlruE&PIsGR``{ma$KZo1B4^>N_8mdl!DAiIWO4b~&P2B#?k=U0?y zZa}(9&9tjMb%h_aB0(fx$>zFh^dbpL zcN#5A9MJv7cqf?Yw_|<@hxA}vM4>yk+_x{9Nt|{TV!ivqS$Hf0ONC zSV(YX`51N*s+nc#H;%U_?A0$F?@ZXKpE};1u+_|RVi}McXXgy%Jx!v^*hrmb-1Td} zQM=I1wkuAH2GU#0wZ-nOjr+7$K^JPb>ehRFt_;)pKo*yN*VTA#DmtmV2i=~3UB3~w zId`p|0AHGwt%SrkQZEwuP-)C{OevY(>Uajx6 zJz6iv=!tGE$MK)xhIY_-xr(Fx{U){xXgN{2{&Fw{Z71L{E044pqVyfc8DxYPMA)?2NMN*fIn{HVrzKEO+~o* z-0P-p9E0=LWWZhLEH>T7Td_TLMu)$Xn{|f&sde}_xk-21G1o}buW_nTFVYj7CuP_5 zN1usr7HB}<0sg))Za&7Xs=>t-oWHG)L6(p`2cS8M2 z+&>j*i!3vIW`W8q9Zo{`f6yAg^(J3VVX9m{^KC$hkgYhRfirGR$?T znM^Xwbf}$_=zlrXPl^p|9W9MF4JfB$YKbA&IdGIwIB&juX%2^6=+lmt0SbT(%1U7-fC7yWNULqYrNZ669O0?cG<)PaG1v z>&E;K`~<~}ecE5>VWvplhxX`K{IJ{$-lz<*_y8JP@4E>#IFJX{d%Sau9^3<@Imw5%xrRHxlP+_r zcQFjFIdnh~#=Mao4b@y(_q)KBJ<7uP%zU!nt zvG`xjCVOCUXNiTqMTvQO`muZEv7&y5kClbY3CHu*5wt$1>$MIc-p=>xe*3;~dEan_ zf_44URF3xrd}vvX`t0_owGj3Vc)5KpB+z}Ng9_RN%Ij=%TkjFlHR0j~-r9Z6(FDHV z^Y&N-q^S419nurk_sllJ^Gbi&;VdYAz}fm0^ya{Ct4NsN;Mk%0u**Y12QI_ChNkwb z;J2m1eNx1H=~>HKgzfOQy$y)i;W!H^VsQAb`E|sP5v2JR_hsp~>o2(bW>{CPaL>-1 zoww7yCi7Zy6X;^jNB&2T%DnT8o8b5YMN|UBr^pbp*wdrL;1>a1T~^`c1$|oqAUuGb zseFyO5AUx|MtUFuYu-X1BNx@dz>~<6^)HS*93v#t^LDO3#Qb?{hLw1WK#dlHL5-l?Cpho}C6a$S- zdc%E+{*$_bo{BN0?~Gc3P03st5`eSLy5#RU-9dbcdJ$ir7fb3T5DKhtzX)#%o6-5i zs^X0Z9?8F?06I*bQTiIPhD^q^!SgWOC!^t&O{0&p z(boDV={S9B>vPgg`rhU%WE+OCaud0ZX`UZQS*8Kh zi$$-a_Ig_ueO_`tAkzn#%=V%9yhuGrsrDU6dqc$g*<_G#yZtU@UO^-MvDteN z)&65SXxI|}o4KnX)d8z>KYN4)2=f=Z3j>!FIJvzIlodt*GJ}GO(p)`)jKwZ4^Mn2s z-*qwtyO#(Zi-U7YH#?LBUnx}_>k2U|L))JV$u0YCzcgf|Jj@Q@|0~S3W5oYon03dY z0BCr8?T>)I$XO*Bfi_W3vVR6@qhF_N4swcpAiNSZLRYaV!Mo$daizgVR&!K-$U4sI z&^sY7dGUcSL(>H)zoTI*gfFS5!^8=`0&^Jt{3Z$K}aJo}=X%k&*&6u>ds zHs`G?Jerxyb_tE{%bV|<9{nb-!|7B6&R5cH9|7@o@3xA_@QZA6k6a&+UU@V!JZM3| zSfngCE8|+!jL?;m>?m1yy8ucnib`hPj$RQR6L%)sJLWuXd-O=0N7&1lAVyv=B-Vm? zDqvA;FFV2KMO-L1hPpTI2JbwXOE>4gB|M;~3m4%U7)wM9OcNtDL5Vuf_?GwrX&E0Q znGJ7`Hzm!0Sur;xee-k&ouz9TgT95iY4NN4@o6FPqCj); zLgw6H6raaD5&DJI$O?(rM?cK^9pxH*fE`1784<&o6LTwc9Va#pANZ2C_+9MdsS!aXiy$9F8Ip2{EtiX1)c=87j6?MQ;hx09 zJEypx39!avJThr{r8(~-CBIO?FZQ;~x-Qt_8=TT1$oF?mTq|4^=*ZtKYz~I76e7z| z7y7VhBHSZpO#(1-MdV1r`KT*lEs0jqZowmowK2ni3&hLg_V^Wu*>s){ReX;zNX1D& z@z*E}Nfq+}X+rXi^_^&!L}CBHpPH`ip2Vdlo#oQ7&dE!87MNwpNZuLrisWp57;0Ct zj{gtonEYN)j_^v^D%=P!N#vln4A~|opf?TKCCV{ddPBs^u{|xn#L;+c?Mm?jBBiuX z5<(W|U6Q=;YRMQ$VtZdr_DFi`dn&;@ImTbhd!PI)u!!{{B`BE8a89`wIw$6FDj}>P z>O|^fgn9VOG~3APP+(dWZAQ>U+TUnEKykWH4Bam+T^d{9Q=c&_E}!}-gG85j`Dauz zXyk_(x8rR|m65zHRKvCL`~4u3fF1nV8nHS-5M1xv^}z*&jmWchP)&?Bi+ z$Th>n)bGgE!=$wJ$ld`-8XdjA1D$pS^Rl5R9e_Js2~3w0E)WZ1(D`uYrw>(d>ZW{jpWq$3xm^V>$c67DcYeDGv7w zE6aHkQ4$i6>k%mr!spgSod}@kKBgJ`^m%)u2Yt=+;$rf>`|@P5NNQx>+qflOmic?) z#>v0(z3G9Z@A(Dv&!h$UMuvpAJ^yw53W8(7>i8TyJNp^jQ3lF>0e6sj8#oNm-ubARqiOiGO;Hx(CCdOCNCK*>Lm7eYFg6_$6EvM9A6-_z@qnG3cpu08Wt6Lp?GFE zC-`|WEFw6_vA8r66wqFLDQc^~Wy#X0JHGcyz_b#d=90wd={22_?&y2e*pjO;3@<_H zte8KPywXFlDdfIVzu0f2*M%5pu6#}*5t<{PR~QDpKXSWp0B+wmt7sm=*p^-tiQ?5q z6;x-jsEAGcX$xSNRKy1vAmPp9x6jI4c%4@M-DT2xuj+OR$Px1WAmih*= z!DTc*b$mqGM8Nzwefh3Hw-{)7Oi(CoMY%kf7dfM1P6#i2Q-w!pKxlMDT9`}l<%)^$ zr9s}6v%`&nt1Ayj@cb`VhDDnBwN#cz%6%IvPer-&wSbUe)OpTQTcO8!J+=X9`Fa zukhULyh=QAWx7M<2&q09RJDq-C9$O{)+5*X|8Y2s>RH5CRQF*A|8R37J(p5!w|rS^F&v z8(3bqBkV~)K^-hS#=oYH8~)x;TGt#A<9oU8WW-(HrBzelBIVYq&){O^ma1=Hm11eN z1LXaXygD07>E={Fg}rJ?ssSTP>K4?rqW~3FwF}Tsir&@Iu!(txYER%7Wj?6eO~^`p zUzbGuk%X_iP4-UsSAT@kCwN_-?)8PYy#AWEB|EBNj}IaKLqoK02wl}M>=zO{(D2=# z6n(PMCcuWau`w=iR%A+JZ=fk+Y2&RRc9_0tZt(U{Ns~?RcnG>FCmX zh+tC<#D=?w!m6A`XOvkfrLh7%SkTb;32T)@YJ%aKGa{R62@6xsG<_rnNQBMqr0#_9 z=2G%gL0kaaWA_HXrjjtG>-2he%)4)`PE3RER<@_rjP)w#t-8XMG!_Kk~v-YNE5MXT=|@EeK>?Y!fU zjI`~V;eREE#OKRyelXW6&l`^9yk)x+@=72);wsF1HWkQx56kFxV|UtGv)m zV-JYBDSk~4o%)#0?`ia|j+@bQ&c`WcwC9V@ooHU~245b{qZj1+J<6ju+Altm(3|e} zAtJc9dAj*0p?A{%Y}i=W9JdeJH~-g}ZlAPIyX=5Z$4+)hKs$zBc3tq0^nki8z*BAW zyG5Qc4ME*!q4%pHJzL=LvgV!`L{CvYns2 zcAKqx)H~a4uI_&CA-5Mw%U-(s_F;Ul3MA;2^)2#v-k#b=g^(Iw_H}ydYp(VEgzczs z><7aIB@6mX5EBK5`X8g_=Clv&MLTEu4e&9+Y2E`$Y;tn?;2d0`_}w4~Uzs2rln~N| zm_Z#ek`EvJLIQFlhxUIP~O3>SmCxc7C_-4|eA4FP*9_)iIu2c>Ff_aw~3_;=bh3cUa#Erb8Lw8a0vZkaK zXp8huQU=B)b+>dB>zR}%{e^>ww+|n}+loF82NBi_UJRELUh@|Yn}|JJ-{JS9F!sdA zX7Yb5%!miMhdF;Fk^*F$8p)wtp;wO#d!gcLMy`69V!KA(P#t0vvN_bg=*zNQ-piwx z4Y|3}44Ff~|BrD1D>ZLuz>O-K9Qp=q9e_(ApqX8VrIj9jEd$c$V0nH2@L|tI)!TSxk@7$K;auRq_RtC5%<_ zgOo(NnH)=b6Xz_C^zw@($dXGrlk9H$RPJ;4V&&k$!JZ`uw3xpi1LCQKknH83@_t4%F-_c{Rn+5krd59Ug z4WnA*`mDy$KPZdz%W?qPBGpaK!cJ#jc>9)IaOOFkW zujNc|KrKzKg49+b$L4rmC`}(jLBAI*9V>#b%ey>w4Y4o#x?(NzXy!5n5p_6Cq$oyP zq^wk&!OW4oSI)y+PkgU*#MURQRmS3QLZ-3`Ka2lRX~ehlVwDdG&fHz98H97}XR2*P zDod_%BVJ(2Ro)~}yivs_4KuE(^2yujpH+S21iF>H!I^K$k=Osv8fSqiTdsF8)0xTt zy1I>3jd=h>QovZD+hi|v?6&)V?e`UCAZpW;BG#k2PNiHOb;y(2eEK`)O z_QCBGd{L+2#`#I=emsr`P@lm+Q{*3j1tXO zWNO+T4H@N~vQU$O-k-EUBS(J_AJRO>)F0Z&wGXA+9lBEdFQnd*vp(n+I0A>%p|P_aXfv4_A|0J<(Fsr|v3tn=nK77uzKO>v!X<`2Xpl(|6`C^-=iUoY(psd;$B9z8n9Y zy-t6E;Kw?qze7+n>FQ?3j}tr8O^%-?wySF#KTm8`E1hx;7V59gjY^s3sLQ1hrbY<( zufI&Acf)l7wF`hbthynl3F2w$6a6T%FZq@JDJnW?t>HiPdNIdfk2WMcHTYuuL>z+{ z^GaxKXvD_ze;RbyZ@lw{`?v`1MZ*u=RnC3me|T5+l+kj!#b~wBgD``I)vj@rOq6O@ z|Ihy%lcvwsPHPRrTAH(k3aRaOA<5Qi-@6tK0CjeNGhJVGiNM)ydvxROha2_!#UN^} zN{{joRL#@pf(y&4^(P_q#W99Co-G9egDbQ?S83qF^0KWAeQkH-Af2S?$EJ3Ib5wdBx*4JswkI6*`&N=TaEqjN==iE_*`;hu>hj7YF|;w`*?@;#3CAvW^o$Fd>U#`5e!Je6}b>0kk&e z7i~_q0;<%9SG9%~P8<=n15-Qg+B>_2MaR6mcQWTVMD&QGrW{jxj|aCnb@cu5b#lHn zu$w&WdSGxr?k(Wx5E_-?<}C%ndVm{-L%|>1%|;^JO`wf36yP%G*QlAxdXMv?Zyk%l zUGm{$U4-d{Z69jT-#uvO=ATq0y% z_d*mCa=Ql#JL4(uje{gZg?*(UHq5?1%dHjmWFXdcKD==-(y0Rh7>aO6MqH6@wNF9D zNKYOeLVg?$wq1+jj?6q zu$$!W`(9zi^5%WJu|s2)mcEdof~h7ZY1I?S$8zN=Gdb)5UUFK|ImD+dhK? z?>=c~P8#b8wEaMy-}Cy2jEw1xIGje#>%D1{NIugCw$7%k=u=vCP-y+@4&9+B`eP4S zVE3iXZ*{{4r|oJ?!(K?=SQd)gpRqkB7#EarD;a~QXLky62wQSFOdGKE-hy|4Kip@APFYihm>K}D+RW9NnHNCnT%Jbed z{dQ)1*VRsdF8J)J(*w`?q}JyHZu-1$K)YJ|hBhvC?({v^sB}8!XWr!H@YOH9>G!eY ze%fZCeV*U*=C^iy|5YuaM}_{LE!S-G{EJ$xk0|^vwPqduO$`yawSS9D|Zuno$ z`s~*i5S8Ok{Sfdkx0{?5D9F1y^g2ywRRz%XN9d=D4=$5oxXOCxt}vgv=*ek2uvbhc*?pyXsXmo>p8Wi5`pDlqHL?h&3gr#Z=LwMB8Fl z#&6?rVw+iW7`(V8?BwW&aSdFjh>P_9c>2)A^kl)dzzX_ZVThkEW50;&O=XlN^if(E z9}+K+Rx{p-58+GW_lSRE!{VEgpy+(&=42-F8*?aS7?H_Zl3D{_&2mb!hbmc&G@~br zrAv>2pjdy?zkw0#V;L15K5YNY)u0G=c4of2gq@o?2CR+m3<&985uwmg{Nd$C4v^Qym z=W9`R(pAsBqBqIOkQDwguiSwzd@C=)z+1kn*Qu_P{6y-*U+QJ8-tx37w1c7NGjt%%Kfmym{+Orh^5o_|9#UxD}9h=7WF99HO-&)FsLJ~ zIJzf*l=e7A?&p>ciT&vlnBGs{O&!lz&v5esWZ>hsk~J9(%*CXHjPJ~UM0_Th^_t+2 z$z}WFEi%*CL%403O`PRe^GpMWhH=V#!?}uPr`|&SKSaItSDV@UhTBd%ZHKzMyU|j| zHAIMeh!7+p0Rjmj5P}7FcXxt^Koa5#REN5|d#CPlaz5+3&iUn9`!Cq*eV=FF_fTCjwEOLA=gVgGYe2qNl0cNdQ)>^<{M06&7v$WuC)}MJ)Q76ADLa@zbf;6&Jv1U z>Z%+(6_r??b1`76usU}mJu>EMZff8i9xrcNaBE~pUOdAoyddu-^Iz8Md^U^1Ov|rh z9}YQ`f0F$>Xl}vg@cHyz1>A_gX(-bk^8ftLC8SmWDf@++E4ru>fnDXy zfH~3jm3X>ml(_QbXc!)J#)f^&aKB#)YsA3$d-oi`|ZmbRqWd-f5 zma^>WPpc{XNtwFSPz>Yue`zQ;9FYKwhus~*-~04h3~y4X5k9;Owdo^&QChrNa#~P(1}78$vM0ayl9;*wG9{<68XA z)a8u=LVl99@n7OSk+f-}|F*bGO#(7S;Lvo6k`}FPo=+|3W;SDKRguEx>VTYxvgS!T zGweaj%s@vrq{S=nSLpc`K~NtvyQMuC$AGk44*n9dx^;R;YVfL7d&Z2Q?X4(AZlF_Z zEOQne-&(^I1{5`300e5ujhAesG+qY?H0PVv_%@H^H?e`g`a_!ZU~y+|^Gd%p&8wT^ zq3T*x^Hn&aVol2t#EoJ`OBITgzpmva`rqvRt*+Q3>E*4(xFWG<>s|bfq&;o+#N{G% zTN249PTF?DKU8qEeF-_7Z`Y2Yu(;pb%ctLgPp+O?ZFeBVZm)d4?FWh76h$oJ@2zk*V=l~ z#ced_thx#3@=eBo1O;uj)f8ZXar5$*L zyb#gRgIb##+BqE^n|Y}di5X8z@9e@&OA&Uy#ycf8bh#5K@qfB9h{Cw6u9KuV0ZFpJ zpT$Q>{K!aNgd~fyCdw)qr`(NnkbI}sMX0)W)7-8v)E_d=+e&10Ort& zu5G^Odjh(|AWZwht}EaxjdY2cPJ)x??V*k$9Jb9Z)ZR2zJ%V8 z(cH5QgHNsOiN~fSkM$UF4T)QNr{ZPt{k^V)fw;upSYopvvR6hD^YeQj`9pbk`j(Ox za((+iFY9|l+Y+{{e>ts*y|sUTz*^R!e!qaKP*{IN zz%OQ2cemGE!`bd0uQ@h$d(AT(@4oFlP1V%1#m7sg?1=%i_s#D)4P4oAzIO|#xY@op z7BanVVXxJXSIOyH1U+ARsE-2QS%~TDLGW|O`aU9uvPAvvsQc;M{!GkFaee<8?AoM1 z19NbD6LJPn_;vC0foy_Z9CkoYcq-ryd?ohqPYv!Mg-0J8#M#Wh>cMn>T@-&%PR2&M z3|=9>=KM4Gi^7SRA>B%O6uw-Fpc29yq+IGLHbPoJb6{ol4STLLj`t0DuD7wrbEDDP zciC&E`bYm#Z_kkp{Q*Ap{o?*XU%M{Ez!adUWn=&edQ{&s&<63Xo;C2!ud(d%pbPX> z(T~A=_?~?J;CVzy&Ti=jWM1ZWX%MO}4I}MEYf?1Qml#VDXlOTfC}I5&2UilmW~d#{ zj&mNmPS`0Zm(3?Uh?ypHC6-0!%UC3Pp0})=G{&`)sr`wOH)YrTuW_!(K9MmIcZZkQ zntwhHAEY>kFBryA8p2?MK^{<3^I(7n%+xeU@qn8eZGU}Rw0j0mdEwUS8$T$zb;rE7Kx@Vdr zhhF^ulr8sw>ku-Er%+KVlXzLAYh|B&HuOvz1^`mplZT6ZZ#0R9uY&f~z8KjE7FC)? z*bq(Wed_<39tvgK$Rp2R zL%ZbmwuR^#d907Lqd{);{kyqMVFyIluTo$@RaKuAb>MU5yA_Whzl-~oTcKMEqLdt% zYc5aO2Zv>~EB`~lG8T>QK!Q`-MuSniQc^}6(NmL>N6(>@DXMF>VhGdlW++Ge!#)pFM%H%}P(N+P?M5LhqNI{mN?q#}@7A zCSP%b^JqBGP_uS)81%jZKl%-_rsSr|)z77{O_c^k=1Ejm7&-fndIp@3iBN+OkhCXi zF>;64svbrDOtz|Dp~ezlXjY&T5_~ism_6}QO&I39&{dOL9If2AtN`#_geb=gPMI_4$rboJOWLAOqan;FxiyMq((wYpEZN70k|xp)-sg?=}_ zpSMH3$92lsKk9uhf5zC^v3gY+ttlxnKHFSPY( zZUGiF9oBC21=MZO1_Jq2RBaomqU@>m9(b^LNVfr^D;U+0{mi-VbhXgY>=4}~tUKeI zekNR;c2j>0ffC=;vye+u{?gYXElDAI6N;N~UjGEWNJKL%KsUv&H5|2>f1et#n4ws; zAqKlepfQwVOJhzOMzG)cj}5167K5pVCpdGot7g(gJXWAN?UFi{ubFU38_Ux?a@}MK z*RFAMRX^9#-1#H5+E$Ozfnn`4&mY}*-9B&U_IRDZN6}Gl6a#L7fq;HQun9e{H!g^tCvnX*C8CYc@Gyl!EgnB6dT}3sVd> zD`vJS7yF3stwX!mjnCAC<_xC7?Zj~mi`9ctzpjsqbTEyh_Oaw*>k1_u_2jTsPHzR_s% zL*yPYeuo~*I&azsv&&GLLSPrubfyY;srZ@6jBrf>nO-6uC27rzk>W&{`7mm3!b~$3 zRTY2E9F1Nr>@XLj3*x%W67-MQ5wigkDmY=jf;k)W#QYAsBW8}L2q!b z8yD&Cx*RYU7*@ObXg3>ZZqf1=hIaP>=~BaUj~6{BjP_oeI=&cVyfH1M#!;WdhCJg> zKz+?slbf%sl4D8+8p}LQYS36Q-1Gr#EGRPXfDGkLGgJL)vK!4s(6G!jvmSOZJHX*D=gVaX2KPV1o=kPWSOvSF=8x_QTK#G>r}K~T#j|Q z?P_hb?!~MVXssYjT+CPFPUk)2uZ%mK_m00bZu=j7oDG&u#$=asTBXt8`b!};{&7Dl zm6<#}c)ek!G|#Ti2Gf|=#@HO>S&{SDZj@`h#~1|FA;gS@py$LzjET@Ou{mR9=re+GQ<&4K36zQH zbY=o+3Uc~)0%1yVrdo$k z5AV#zOO_Oyzj&*~1Q@C^S-$&f%B!tMf$EZ8Yb0o>@Qt+xT$3MRy$wmqwHsUD2g>?5 z<_VpX@oOvsI+4C>tQy8iEgCbz=ZU9}J%me=tHx&__9YRqFpbcf-d{V()u<4*ep7)K*-uLCC6sMUVab7y-)hlnhl4^+ks z0s}mU!zfL@ppi&IKhRYkf^h}eE6@l}u$^+BUjz8Vs2zw5(T!dN!2R-6RbDwziW=uJ z4Yoit&9wp6r)hHL!{OQ^j*0M}+A~L0h$0>0$Ts9m-T0w;q*#CS-~r@YeS^byRIp*{ z{>!La2F5;{Xxd<~zlAO_{=N4N`nnOicMfKYv3SoBOt|s%?gTG%%XrIm&(AIUYL|KK zZmBDH;+@vknf4iQqVu=t5pb8}1%DH0VUJt*1n6;ZGQ$(B>zfG3hqUy6_Rsa>58C1F zpx)9ws9(_UL)+orunV#^kZ0-qFDKD{u!i z1N+Y7_?p-DFK}w@Ui*c(*V^d45U4{nr~MOjRrSm!Z@=eN=CT0j?rK5Kd{{}{+LUsH zQ{yz@O5~!ZBJL^V#pbVJ5L97na7ZcIudOdYjG5Vf&Ho!l(>Viw4;$RI9kT^DSK@^* z;Rd@yp{;mu4-jm`-|9VJdq1Dlx5`IC_|f;kD~cG?U++ODz8na4OC*s7H@aLRT^}?! zqx}y_4?14)Pn9+v%k{rJwC*T|ymzSWh&?$$w&Ab?`M9j^5STJw_Vpl(;x~NYKn^8g zINZUA3oaCQ)!=dpliD8QOogAT&){wr9W5NfuPS<;(N732y`8j}7*H`?@PRb1k{=}^ z>8kFskNXpA4umYk1Mhd0 zxhxLaFInUCA}B`E>i9HB)xG)Hw_v;OvSS;A;oaAd0)wM^<{lBy4y2QM=F!mU36g2F z>I_^%8tru^w(M4bZ`Ovql>r^uQ_|+qhjRN876c;m55=?v-Yn>jd>%wEn$JER^rkq8 z;T+5<84FwxGP7(xl@O9qzLoTVF}(tWS1|G_LojCRYbfw?WAAR9>G72OU{AJns{ShC{q%DrdQ8=D;j9I5eiMvRi}q)6aN%X zVYw&AX76L2v28Jau|cUR@g;0y+FSmOFvpCbNOPDb^Fr96@IBdUnE!+imls=g#AA}z zSEcosZ7WDwJx~@Iz*{j;71_*t(P4@F%AZ+35=D<8mXo8#1&aJy?vc3t8C-6MuseA^ zZ;@!FFoc(z(8wq9z9&tOJP{q5ObBa>zM3Lq-sZ!^FN3-Kk+h|Bml#{K3)MfSJ|oJ% zGv-TX0&#@^k`;_QC+N(EV>E)tIqOim*d;k8#K%}fZZO<0wmfe+^knRvyjyX9)MUI*Lvff5};0B!QbOh$QKPvTwX zxAJvK7*1zD4JI6jkfJPj|}M);8yBr3o= zril~&!nUQU5^6B$bi2ev^rm!b5(+gnosblbxSWo+?KMp4;Yqh)W9hBQNzkY1cT-kE zcc%_e`bHL}swl%F%Tn)CQG>hFHq)4$)--xRYUBB|Zu;>mYTC!3^~J1oKyYgAzVr^p z-|0Q+Uzh>OJsDd=;i7pN7ulh)yE1*koAyOP>Xf{K1@_ zCE>aTr)R}+chlczm2tH+P1euoDU|!!k^CcMXwI^j3DVmfxFCxdkt2@XLs*%kik-yW z$ax}L z8}E?!PY7AS%Y!mvd0+ERg|3Z!kD80gdXPf`e4Qr3$e0PRkb#Y!IP?s%u9?zRi8tnf^(}KSo?zJRA;ak(=S)|vik#ys?UeH z&0)xW}SQ#@wNh*0%hv5+HNy=v8f~;tFEbC3H*CtLmdzK;Gu+A^e)mn>CvWw^D6s zNm4>Gspf7N5|D_?LQFWUGN~5mT;pr4kMO|5-OSri1aZnJu zwf;yjJM>R|MhK0`ua`0whrFr(z<3=z(BRCR2uf*453LFeXvhh@MfYf^WNi;{YLKw_ zG|z@f)?+HI;Ts!EsjDpn(KSnIslXxi_gY6FLN!sF1?rOp)INt$de_y_ppNZF>a4K$ z4Z8YOh}f#z^-;)|rRDX5==BBWhB+8XPILnS`#dAIVH{s9e%!d7I47yPv6xgSDr~&% zKNdIG1Zpsq^2jdvyslt_5r2{Vl#{05Z2w?87N>cZhjQx6580Z zD(D*%-+~S{GS;=^g`@<3Y8hi}4*K5mAEPVipO$Zo4}r5=?U+9FHLVUzbpXDx$=6$p zv(eSYV&7#NRpW^7^$}9zFVN=x-A#eu^PRY+vwrPOZ=2mruN$bzr(h6%%+#Iu6K9_9t>^m2n)Q#!NY!Z{LI`}`n&TtYm9*CQJl55;mifHVdAGI$(iOg~ zkA24mx3(Pvxk)f>Mc{v1KDNE^W7i*PN5a-tEodKxt4o<3e<9ZwuIunYA#?Y1G@vD! z)g5oJGt!`)9=Jm(E}gmfu*9Iwn}mY+iLR~0t~g{Dmoy^S+GX_D@warnCa3X^N_JDI zQN@yQ>K@K-NelHwM7HEOEhXGh@?XF*_V@190mH0Q-5zwO(D80MUB{g476&>r?svBa zj)eT~J{hzs#JS^>_db1V$8T?>zN>SZcbs0_>EJ_AKJDZIa;5h>O}<}xwsoxlCA3}c z;(>oRZs|JZmsm4RvKjieoGM9zvx+xMt|89l1G~4Q)?~}OlhK@v$ZiWJBbCy#2s@aZ z(?h^bCOqqDz(0uR_uM4hiSzDVPMj1R>&1}<`GnqV|0G^-uZj%iF6w z;QE}XZV?On0;pHR?)2r*{Monr}xOg(*5cx5B3g2 zf0TUh{S8MKuIYmzT5=2f>X5IpfPJ^o^U{y@Z^9fF2lafwNH0wr*t0m7kj02H!XyP>Vtc_8aw+Sp6r z{JQ^dpR@h&ez@>h~!c5|U-yY#M{_uz}i3fLj0yIAc!@Y!Zhe3t+seumZEP#U~SxWM)X?-p2 z0sd%sB>e`)*Pw@hkj{$jL)CsSORz%^U|S2$%J#vrxy3ROA}*^yW^#9Ch1 z$W787u9N&PQdg9-e5?QJNU+@9zm!9f`;(_f#L45y%y8LIv3si-^?xk1osmNtj|ko7 zp`6II-4@%V|DCml! z!y}b2pS+JF*Wtn0@8qiy@tK?D6r?zuB?fX8N-^+02p4fU$K?<=;V?DyzZ+{JHG2BF}GYalGOb6k6b{Tnr1zbycF^u~}SY zIU+9owsI25PmLP2Lt#>2qX6`-Bzf-7822fkFl*fHL8fK0z1U{^O zK1u;Euh=r$0r4p59ew5(SQxFchYIpyRgo}p_JC>to|3sn^#;LD8&PjVqQoU?I%;cj zsk#dFDp8|0q1zJ{sb6An@nX$#%va%j%`t3Y?6`)ATQA7f2yuNe6ipp|BcG}n##cs% zYEBVm@)9(U2r=9$?KHxHHcN$l!7Xg>m{-vgX0F|EVMsP&wg!&#NyQoC7#;+m2R6~Sz z=A6`&z}m8oYL3IJ(@$xBA^54?+Pz3nN|%;~nxAw=TYxer?$RpIJW;jw7G_EOR^3cY zTigTPcC16JLt^~r$u--?UbnLk>EdB$GfwDa@UFBz-2;SB+^b)R zbWJ|5_eQ=;GV`$L1S0VxfXUgEw|GrrE&2 zZQyGRiMagetA;Avv*<+{flK`uPs4L*7~^UpT$;urHTkX{Hh;mm8(FQ<&T=mu3Dd$n zt_-AV%e>ZfZ_{4&rnUoh>wK!4F6)8-CvE=X4&V3Hvvkiu^UJICTfy5(7nOtyo{FT~oE?dW5 zYCpSd8+&0h7jGYXu3O|XX1b(<+Wf_2U7^iiyi|9|<}W^?U*lQa{ZJq5b-H7YzT4-o z<`(@cz`ptl!+u|E^=(5mFtUPckb%Udo`(0}%p!zwKO{ZB$jI@F$(>>BhElRRjCW!7 z89An9u+M2FCJt~S8j{~dg6sPMGwsWsg6^6EHY-0aP72{y8P8XBm^et@o~+xXn~vdv$-9r&nh zz9|Uwym*bN9{jj~YPtxyoO{7+=cmi&n%$s)}gMv&`dgW6Bfr3j`~f zXjzDymiXLq$kzOC`v5^L74a<5sG4|Ro4`yzxX`j1;+vOmLHg~<*=fo2 z`T8fvTBhZMf0uK zQNi(xtzS{6h1sXfrsYnLCXSjGJ3XE_Vw&glWa5x%r?bcs zVhVD}(@in8xGEKsriX5?hh~|#d2H!DVGj4icl~AV_eyQ;Fu(ThYV5G=@v+o?vTy(w zt4b^q-`nLZ%Ol{el0@rT(8WTNl?c}5yIO4%-<(@kgC8er-1-{okTE&768bXj=NJH1 zni@0~2|r}>7ni}$*!;z#2u#xMv70u3@%OPGNWAF6_zL7${N?dOsJ+6c;|NrlaOyY< z^(Ai8xEPI$4RBBGpW0&b5cS)Jpk9-M8w-Viw?lI?+CX4gLt-U(V)$gtGsx+YaZaP3 zQmzc$0xeTC1V+Kal}Qvj95PC_z29D@+J(7@c&GY~+>ex~6}I==3{4bRgWjawiKeMaU{C}Eb-bYvER zZd!imJV9%UJlIcMXwn`SCbG;k9L^FgX5{{Fq_yVS{q`iH`NF<%_ZR&~TfTaD_2<+i zc%}^`7M${dN!dLLV;q;hH2!5o5gYt8ciwV^9rt4fi+cDj`OYUMUM9*-| z!=BJTa_+*p8Hi4Q;naqc#}e>PM#rPe@KR&r;YavC#&?Ih2{@DQK{27-RB}K}_+Yy3 zP)7usH|{qPTg+kmJ`%r}2lfGczjkeH=ljY!o9mzW{_0v){1UWPV#<62q4jE#Za@J8 zi(_M9^g(fy7u-==$r^`$9Fhc2Ll|U()K5tMu!_V$?HTF8`JqnA`%&p=ks=Si3A0Q| zg#5(xjrxL?Vu7mpfGF%!mDKAOj;UsQjNz_m4!cS5aND-_6yB;m>b#ZUrR{cXCXDNr z9CIc5=y*pL5&Lzg4?iP*({DVaA$jYg4ys87dhLNp(pkeYhv)w54Gf3n{_%#U{cNP5 zvAhd{^lbRk(t(`X&|mQYiEU)(4WbI047CAhZO3 zrQ1FzognTxK>bME)9XpPPPFzp;TMzG{m0N!(%XTp2(f?pz$a)2dC%Y#$P{v~v;>$) z*)jwIcu_irzIr=SSILGwvDD~cH}@v$^(Q41g9_Y{j{#p4Ek~Bnfr@8`z3F+%gNL$7ffeHJlccZ;Nas>gOa-lO3Mr%l zSNwpasN9(K(f?6(eF}==SBDlRQkU0Xj9x|6HqMV=(nw99P!#P|GbczJkkL{_tE1bs z*7%>J_qNp%A_EV$7h!z@bse!Na*%gt5PUF5({&8GD|m%uD)?S-s>A|375uw98t^)V z*fZb9Ii$Cz#;cJrt#_U0CI+&%+5H-$qi>yCJL5xNyK4e-W&aG95T(4!o5=vu|JI^(togN5DXy%tx;do9 z?7!=N;y1GS_5Wd5?8gnakdML+HFm-kqG<3n0!$Nv=*Tyr}8NBuBZM^4$SB#k0)1UvPpHx7qiw98dDZ!jo}`p_-Bi;z?8zAjc8rU zKu#%&l5#osFXVjjjNEwmRk35=J#6MlD`)6POQpDLe?g8!oCk* zv+?op)#R*jlC8Sb8UgJ%m@p^1!O}XGx6# z#Ec!ufz+cJxa3#l0~z%xYLYnPl{la9GSfX3jgQUrN=?8`&lIJt!Hi|9(oE>8%GA3tcEDO=dLo@aN49v{}m{qB0L;aXBWjbC%xLi>1t7!d)KMl+ETj@$Y1t zql387Idk|S9Jd^9OidUmM=FR6t;(Gho6T69%Ze)tx|=&BKgOJAq&e-=3QZg z6b|IuGZi_9^6OX!(sB78*$K(_3y@(Z(dB}|@QJv&1@|M~^VOz>ZP{U=i<`+%np&4h3sL`z8<3*HcNnl@586O+)zUW?z2aR5QSg?iiwm4t#ojh8s zh!y)s7hjD1LOM|VDvm^4Q!+PBN7ztuNVp#FP!cR0#-U5d!mHTuqP_m;QRgCif1gpO zA}9Y;`O+dWxuSnd(M8Jjj{M@q)US=OVr;<9ss=5Ha>vMZAt%cBMWTY9l^>3*4BS~B66F=pUf#o9MGGo_$~{lrRk4~!Cx5Hh!E5xt zQvr)!M|x5rif$wRtkCd*#GRE>`8IE4nF;qtl~X3iT~ei%4dCu59m?+F&4b|bwS>to zb9oT)PjhW~hrfNzgYqxrtg^=yF;rk-Q-zL}nq#c^5>T1pSLsY261!Hi0&8rSN>fl# z{LISH;9~+yWk+yWbYs=>kmuZ4Rb9*?j;!ioXr#^myOTv{)2nmXiJ>{wC&S>38@4%r zcgVWxC*jM2a%&ccw*@-Ypd+H_f7c{)=F-mB@HwlflA2J?DoSyUh{GmV)$~OEQ)D6g~GaN0Z#?EIw1W~ zbbH-sP%ziM?o7~K&eOV&!A0TY^*$l(>?ieIj7b)%VP~j4^KpY~sDy!TV6vP;rZkkZ zP6wGAuCT>{jSVU`kIrsTv)cp64OaGJ8nxk4m_3!#@G?w5X{eLH(lna7QkbJ=&_Eo%U3FN)Ml7dnT7wVHw{Sy4Ildw1WWyzb zA>()>oFqtfZ#0tUCH-t#LV=2&G~uZ5xIaxvv;_jMrcv7KXl>J_fEsR8(*7#a;8q(m>APE3hV}-ani3#&+M7)w5Ri7V$s7DqyR~T(_`*niQ<+~`e_Hb#SWKs; zIT3NNnb>?8*<^ATZ3lZ!P)QlB}OC*KqgKX{}^}T)eZjjd(X{ zLEB7!u*jzkOJ>Klw23Khf@N(tsr2X%Z6Bx~xM$k!X#B{3+jr7laTc~S15Sh|xA)SO zVRPG`1oBv?I<^IE4Xy3)3oXs(Do1Tg6>J{1)zs6qE!RLDR8ZSK&^vE+pv)J5=NWJ?@jCC_HD4ndP;i+Vpr9H z_S?wD(zNz3C|cp_jzc!D$+iv#hMFnr7{lI4JKVVlKO<#JC!GLDgm<1HO5-hEt4P;v z^Zx+ZR?2+7eb+-u5ARsl2kMNd7|C*KA?LgVMFU4rB=NLc;qxSI0V4K!$yNGM zR=4CUT^ZWay&(|89PEY#eqx;LP7bOLdD}f2ygS6Pa|-~gpX@vasL)^Q+zUvtZ2=Ad zt|(u1QhZg?Yn>IqJ3aF{UxBG@`Yx*9*2a}xr=ibkW=M9zBg;c12?$H^R>@7&-h8O! z6Y5%aP4_YMlMGh_k2n3soQfrf(xHILy@NNK>#!`fvf$S(?7+0CDJ< zzH0gs=Bqvny_&hVd!KipLDdcSHrQVN)4hM#QUJw17gVX;DnOSkwfnL!wO83Q7s&1i z=@EdBHl66X2)R)!?{$DiR<7)=g)b_3(|ZSjEu7uA9vPDx+Xq7hX07fkN2jLG>pP3d z7a#0jfXz)R>&M_)64v)u;Y);{`>zs8W8V#|A{Ggj4$w(FzHlJhe>v~gK&QWLK{N1x z%#2z+xPh{c^Lh|MnTRkAlBr9=hXy04n6Tl&BC48wVo*lg%X&I^j#kFn&^O!jjIp|J zjn`6ROW!sxlu^>>?+sRu^_BY2hHv$a0T}(e`hNIkbw2Ayfo8P8`-{N`>i74*hN!EW z20&2vvY3H7SY1)mz!&)M{B?ud5bv{34yL038Iyx1G$!@S;3v$^6s*(x{# zoE#aLd@~}=rg7L6o-gB58p9;AD#~y6qk%S$GE>Mvmxsi}92oJqZ;Bjv?Rj5wZ}5=! z2Kmy#cpv6K+Moq6BEd@+1DCgsOCg|*4Fl3TaAM6G=}X9&@^?d?&=n<{hALtFg0`U- za9u82=7#u_6(K7|*{65N`ce19pJlJn&yzEUH)2jFl7?+Rcp~_47A{g4HLS$j$4(62 z$3GYBADK_6;%i1+i1yL3BMjm#p36uPDTBLkMCZROYT3wr|DwokBai*hadwYlxqVGm(}w zs@x5wPkA9vL3bq`mk(fs33~Z$tY`df#S-i{p|iprHx%2YVB@KR{fbKbJN_$$iI5tt zRNN;n=4C2p5c9d2N(a)ss5&KuR1&FDGD&wir<57~K+cTe0{5ln_rn?Pv&{bui{0(a zuZKI`&*(l6KlJ#b^cXqh6(T(`lHq-$M>jGFIMm@PpXbYHc9LU&4Rum^J?KGIf&3X{ zPnlI=?*}XPQE;I#1v3;XSV69x;tRYf%SGvqkfaYNg~--accmPam9j?p4jq`Zc62pn zbAq#N*mFI;W>k#L721vV;10%Cj9$b|2vDQH@YtBus_pnY(eG7Y0)h8d6+t+`o2tqu z9_6l7braj8j;buAxsg11lUt;vR$k-Av{cJ$-C`^?a;^IY{YCkA58u%}3J=emA)}(u z>sGHyamUBE6Rg}1=xXs-M*5ztzo68BmQ;_9&IZ%UKaBz*>=MCffnQFc>*xh&W1g34 z39LI?q$0pOGhV1_5VdLPs*6aWI8eO^6_6aN2B3E)7OF$hlcIa-B8)g5rdDIO#obWf zz-nVl)!%VY0YS3{cQt0G#tRSS@6nL)rs$&@0l|R>)f5t%xGYUS;YU=bvc`4N>Zq)B zy=-+-wzz(@x+yhoiH1()H}`tgf>95T>$1Voe6JmS^3m(wf-XPRb{~CfkSfl1VZ#g6 zIFL|tMZEx2Te(c_2`(=!Ri{E^MgD4o-*`S%{S!KwQ=vHuJC!v}69qS<*J!#Bb*Vzl zRU|hhRyzxIG^t*D1ob@OyOx5k6EU^v7&qYu?I7k%+_3gvEG1T`eT9800PE)AC^3Gz zgSZoXn$8b@EIL{ji0|YT>XHb5aZjqmt}fP#szTQY>kUX&zrSpeRrp4>>5zS(ePK#tDx9VP@7AH;9FGCp< zV)Sn4K+#k^6a7YL)E8pn;_~&q*r~BJ{b{T~5TJi$Ycb*)=HmSLd4|n6WptOp4ZoQ8 zK(oe0Ifm1$a?y=pZM-~&*EqP+Ov^OkZX$JoX24xGa#Zu)*(bsd9M|Fi`y4# zCw$aR?Ye&euj|TmaNx44E4p&f(Q=mV92in^P`?<0E%eaC{0Mmo`g|xP`<>nbJC>QJ z{|29%9%Xn5}Uv zqYzUQ%Q9AC{}u?1!`P^p660y?HNMn%4|gQ`nYQJB&f-QF&#_5uor~Alzgo4+eN&(I zlk0cQKHX7w`;o`GWDoA(blsSztb0gr=k=!jnjY!1wK+;(3Bc3`>u>nRRreXz0ZS{~ z4Rlaj=|V#bxTk1?;Wk8)PdBdetI4@y#6!hd0%I-=mq9Wb;Oo-p#y9ZW;(XHzL|*a> zlRNTI62-(qo=bRR%0baYJ*HmNlX$-A6gpf8F}*;~|$Yvx`33HAQnuKkO!z=jp$@e;ia8+&y>qunZYq zAvS-(Y46Gw2jfB?W5aGE4sfp~&RFLAt@0n^1<eaRCPENmX~&G)HcH9Pf#b^mW1@4=xWeW#{%SsJ zxZpZROEE5Tb5?9H;@p#@C}X9^aPLgxRnO<0PNr4fD_gFbs5XDWMN=JsUc1qB(^pWb zGOq-tmKB-tHh)30xd@zGaNm3a5}rpj|MWv;f44Y5*JnPo&}?t-o>}r??P*IbD!89G z!Ey)wF8Q@}IwC(Q#kv!@IMKrjLDnS9v9eIB;~!WvQF+40);83~xGz=%njE*#dKqnw z-EaL5vr51*>i_2~&^S+-SY=c?Pn}p{yyRSIaW>6!k!UZPV6K-G&8A}aInryU^Bz9E z)#fFhah>PP1h4ki7<0AviN+Z7HJ?Yd<2HZ6=c+&p4mhR!n57gnr37j@3Hn-CY@G(a zpFhuf3^JB8U=8;x&8oIGLU9?b))TM=X=kk;Van7)V{750l)f=9`1@qHF$O}E_am|Fb=;-#W$3lBU&i;LV`C2jI;E@I|MSg}O6!%N z_@S32xBckD{n@|aGvrwDL4;LNCe$I{D$9A*s9U3P;akx%6^s#siBT`7Q?Q5Cx5*c< z?==ks4NjuPVyEH*bTg1`gvGiMSRO&DM?*S^X#E?|G~#DN7NCM8Fxq*ONI#7Eo=E>p z(?9O97I)R`Han_e4Mh|T<4fYDKNi3Mxgv>0UbR?b+?opaiS(z&K?F( z)z-O(sMMcU=)qK)t2Oh0)px2C+_BD=C2g#K3QQm3moUIrW&dTbfSwyMr^FyuDSU)* zq)18S0Z}odps@RBU)4IsKFmzjGx|!*N%bJP9Gj(yA|&8^wYxBd+(~c?5|VVL)2}*pcekl~fBu`Z-o+JM0p~n> zKO@L}RpIEKzuIqvAL>bL%nGmUxl}e3(cZT^XDq5r)h*4B=~ssdCB8O5NW&Sfc~;2YiPyflcZ=Q(3_BC7W*84aD%_X-yZ?eBkz zvcdvY=U@uh%>ftq0-QXkh)2QyQzysmMPzFBL`NehYVJf-BQvzhu%*b~I(YD16j}E= z@FeP-Ugm!tz1uL?Z#!CHsP?Hwzco(tUV}Mm#Cx8@aGfgeWP}oTG zw4*F+p*i+Q0d~xsez*tw$!t1wA3m!#vgZWsN6m}QMQ%T#y?zGlubS@Cukf|CDY+{U z+v-^|BJxI4hG-0RwK=j2G#((JB7`Bc8>FWyFPZ;Pw7$ham>K_ew zPNb`1{Q1NVmCI6x`3=RS^FYEjB@d8N-P@8YV%cX$NG zC7LPiU&{pJhseaHl=QOF}XsFz6 zZN)TY?&-Q{+U-12*$91F-rc-2^w|8?^pxbVqWLLA#^mCs{6`FF=~C7u#(!m-=>AMf zxfgjo^O9m8K7kco;emO|(o`--4zgEQ&4W4Fc~u`1XR#kuTR{?zS5030Ax>j$3}8Ly zP3`O0-P{9pInivcynaLE74Fq~T?CT1z2QjsN*<`8JMi?1BFU1UA=R`_DgSR+x>8q|aoKrG$(`N2Uc|+x8E-SsL zcm;PPgOUB5wtdQz~1-+ENZyEeW7X;g(`?gLrQ(T{2D*TXt1KOv%naC%Ke5mRXPz^8Z(i zlor`0(fgF&a(^B%6`2lX1*hsV@br|l`I!XDv@~)Sm2fG|mK~UMOS&Y-1G8C5%$<*{ zlJ@4>;o;IRd4GK)3>8OWwocjLEOlCmC+7+p1mnE z8oDPtD)TBtnw^@30Da02E8RTgD~lS69uWNR4dWidH_ zFzp3fb4aXrSsgi}oDDKc73k$W!B zZ^NI`Zpwd3F!fF@*iO{8h7~YKBXyq(?Bq8UTMB1Wmln?`gwhV@78Ul;kr~ZJ6O${Y zdy7Kc*P|sx?aUJbLeYIzH|I^U2YZZpsyL0)LcdgemfJzyRI;7dPUo{;3PJ%bc#@jE-u|8nvZ;38X=M+fTb+aTiB0MrC10xmtK~vNX#q!F3E?al>U-v z!Su4}lG`A9*|rqFg!Hnw6ifV2NhCVmL@bFwGfnuC7<8TfU`Yms-5**qie5ml>=3y#EG0a*@-lVw7${@V2Sk6Y_Cs&|2yORNwXi_KIHa z9`vS)*WB00dzFWIoru9oIDZ9PP?^P7z?hZA{98~$Wu;(YBCfJU5CvgWS_Gxw289{+ z-Ku_HAX7`+&5%~$3@^y=C@%sa^c zYRRk=#K+n!)+PAYS`w=tcDJ^k9R!CQ; zsqsjx?HON_33au6t+@qXSWm89f!I;WsZB)smoBYUq6h^6wf~}{vj44HiXo<-uLEMC z(p7a;NjQn6?kvt%SX{pWPvoiV_u((H@4HFUHr8tT*brfv>HX>T7^kEv@w@;#;(P>c1zH^xkba3aV{;*dPQO8X*lf z$lYpQ;}qzO@|}$&n6QZ5XooxU);In{oXA?=v=iATr!_HA+O&C1MQFJATGJTDNARlY zHFi92U(yu4EVH$fio_-V)k#FU zY4c7Q@*6e1(}DVz64*5zJxpHN1;(h{{Xb;PFT#IaSy&1FYgaq=3w~DD=_Dy`SNAHM zUs8HUad^1BzC#+m%wFC>3wvP)cI1ZV8@oH&BMuIhc3g?v+kLWgc@(Ub(OD6*t>JR# zhuFGmOV^ILM#Y4#L_l`&K$jdCop0zW1K!O3)m0ZCl9Ao@E}=js@Ad$-rS^4af-gzt zb^n(bB-HjCg!=KbdtlISTxL%V>Js60Zvz^L|Jr*E{S6<`ogV6L@9h?b+;FhFp&>Fy zQa2&wsp)&SD3qyw)14PKu6JE`SJ=t6;hwD#uBL-M@~EKNwLSNv|E|dF^^Dz93hX7v zZ7fXcEr@%PJJg#Ch|CJ?y$BSid-N@c&vx_w>*If zq9G(Ciz*9om3UFriv$zr^t`zxl#5n}ITe^52Y z{hjehbqS!CPgC6jE=UUbCp5Oc zd!X9==WXTS_z0+C{9sDd;*!w8(P+PdQT5IkO|C+XidAG~s(a#k(=F=qxPPS2)h&R~ zRJi&!@TlZ~W_^5!=#U1Quu+hxktLkt^=a%N3wND%9JrBf(jJ3ASQ2eCSK-8u(cF zm(CS`T=0kPZTvT$M875BZ|-b83Y5mapsxV$WVPt~!QD)n{x&3t!8I&_yi6`L028a| zRs%TkihKW`1f50ws=;|b8-A-1`}ht2(3JSJx~6NizEIml?RY=40jLEB>>0SJEenkA z9?_l-;%*ANupr zgsg3b-7!7sorc(0lx&9~Gj4C%WW!~^@s#<7Uv3NY9^*9NQ6by74XEW`Hv;3~JiIY2 z{tb7%QJql6erJ3F@@Abk%>n(7`LD?fjAOhs5y3wgGfWCdMe=@A7vvS4s7vvVb=B(R z-egyUF4H^HrPLL8U$r@Pw|tKnSL^rswGSHfB?0?;Ecyq5_3aUc?Ln86AVYL;XPwJX z8}hQM!*DM2X8A?q_%KIFq|qzeH*W=miyYGW*)D@wT4HCUK`nP;|4YfSPI6nA?^$QW z-4GqM?f{Sk!&V632VZW@0QT`>tOM~N?slsqzJ{~bdL#ZFd$;vN0*2*3G&|u86E(C8 zw4c#nD)Mr=$^U#W^~eho+UwBBWs|?xTt|#a>V4Q`G@bQn(ICvL{Ql@mHq-niopa1X z0e4#VSf&T))LmuOW)?#Mc8 zJr%V&13xs|?IDXE3XFa)1rAAK&ZkO;46#*`$3y4imW!i?9>wJg&)HT0jtQ!4(SZAW zicR3oVg%YUfdAtjvnk?daeQqCcZ(6sb}s%7OKf|QaGa^PO!quF3U{|-oEU|gpLt3~ zqs$LII~{K=TfA`KiLI7D3@IFuXO;r16_3>zt2X`3H@E)Qxu5W&oL+Gvr;%tTvT)PZy_+s&xovLO4M z=#y#5_Q05;luK@NafBq+UK4v!blv{HIH^!+{{`44;5haJF7QE)EV5A@ z`DpvE57B)ubV-Nw{(rP~*`@@LngVQqz`i;UTYb>&svO&+klBhg_O0&x!h1U%b5W()khC%&r@{=&@() zz|eJ%Ah*Bxo(E;j!#34(`S3Pdu$PC$U`zLg=vcOXpTnv=+cV$r?!)%Ie(7y^yU^d@ z_7^wn3Wp10u8Sjw2V$wBrNfuvrU>2* z|A@=ue|N2n`@x^%S_Rm}TkJXrP;d{rq5-ctEc-6Ev!KE5b=)!5VGnWp7kcf<9_nGM zz0dQaHPrsl>!p6GV}|!%16v%vK3BW1I^=#c+NV2C_#abtIHw0->RX*5f%59N&fK8J zid^Tp;4@|T;khB#iiN|mq0b5&!?LiUyo19X;r#5A!#Caj0*z~CuBUD*%KEr zN+^wT6-RGO9d_xW?I}RlrI=%q1+LFAcF~=Y#j$=u{m6mXL4kQBF>W{i+z2nOiuYn9 zJ?<%Q(ntfqm+R|DKEC_JL}a4bEj=NqV_6%p2qG zFOvE&dPq*EZ&kZ;c!uA#=HTH#|K|+>!|8!jYZSwyLCY%ly2b@>ET87`4cT6@#w86s zQiyjAhaJj$=6V?RJSTNzX}BSaG!hk&nZX+oM*7NIM%p5u$)=5*jVex)j=YcFp1NRk zesrtk!sx-6_2Q<{_?T9aV3Zv@Pbe8Jjui=tM*CxL^Ls}Bj`QQ49(@qk%9|M;tA5!r z7O_IZXtYIYwSw~hV*K?J^S;M@F?6Me0e={ON@gaY%(J-*Kv455x(>Y4VkAugzqSgo zpCGkEJCWGLh@o51pu~5!EKmlt#=aA{8n)X$7V{ob4GA>vXD}M<@>CT9a35N|O+{qxi z(MCT9jxx2A{siAOmnThva4l3MK5>FI8hR+P$@&q*hQq$92E zIjF89sfG`p)H$`74}R8#&-y1((epHo1jF>p1SjD613s)eMEoFv`VH|xeSmNmnXOrf z4MnZcJVS0kwP|fo2--s@0lh-o^lm5$6QX|_dl7TNoq*hi^*07YG-3OUSHqx5t4+j^ z@T7Xv>mXXvTQecRT|8wz@4p(?X7TiG!M(S1`atlZ);Zpr@NzeR{0iT19rCz_zcV!L z_+7%vp{Qfu2#BHbV`~Z3LpP2hQ2eIdeKn}K#=)*OlNdmuf;1=m_fi|QTm2?dhqZE_7u1j1Q{EqGf9mFX&!Hvj;=T6MI&^iO z3?ifQv8sbesvPVqCDJOLE&fDirMkL_$geaO|Bra9sx12&mdW&+bK3P1GIa?FS2zU zV9<+q*MDJ@7pE)8jMidx0gdt7Eur1T8ejG>Z9VIb;+4?M7FR+!!|YF0P{vUXqB@E? zhjXFEj~Kx{P`fJWEVrrlGrEcUv+f+CgBM?40)5OgHzY!k{27f)L5ukDjaJ}$eqU1z zU=sgR(}&n-!BJ&ubgzJ?d=<4(pl*(fxFC4h{8xC1a7Rl(7+Q#E=?_g1%33~#fP}rR z$Aj_0>#g!2nea#J{XjK;QdW)z#$S-d)1dg_SwFi6_@&t@<@WXUGRQt{r>)zo-#QRy$@P4TO;+qf=C zWVsz5Vdc_|_47jiP9dfJ zsT-HVOxvoPkW!VV>>EnCE=9D>O5G$oQuij6FJGsCq@GNlQy7}IApK6(r!-84RR)yK z&+3!NrL1fN|C{t&j+%W#wma9rSSriStE0Bb?&fEcSn}Wk20mL}T6h@ym;71L4768z zK+zfG#PsxHG3;)-qhw{`qx7F81CX5=zNNvSqKxFyGYR7|6lI>k)(n>$`GaSCE?*M2 zEpu~uaqODR*z#{Nn=>g2@95o``3hN-UuK`e8Ocfa6fpI&^dJFMpOKCeTpbXlw+lNu zr>4IVl{C%G2oM)kRb@0w+Dke!C!~z!@iK|2k22n7p8fwThC5XSS%1kt zvn#V#q`zit%1+7{qrS>EXKG15vwvo#6FhPPv;C6#a*A>mV8}V=a>h`Rxzlq2h`8K< z+}E(`+>AU$;`dx<{sxFJ_hEhtcvarq{C5eL^ZeX*jpjT~!82fOUUwlF(35wfup&;E z_n`1`?1}t|Mcy%Aa#Sp;;eE~!i)Q$obCq>UGd}kZc47BWZVZRs{4}?QOR3Gvea@4X zcjbBUYYSz0WddW)guLg%)9G{bJwzu`%kmZCn<8ocJ;@l)QE)uv6dP0^O>JUqD7chX zPCHz%soSE zR6x&?I}7)|Eo<>BuhTqaG>ZS<7p+Ocn51n38*-ey(jN!@l8%t z)`XJn+yq%+iHMh&l2T&k`wOk5(*(zOv86%6W$aa@xx!bB?WGq*w`jbw8R7!+y|PeA zD6z4uIAsMsugsp(lT=jpGIbB;eEFu-Yv}#un6y-+zPupqjhmnEl7_+;mS2>fhTc+4 zkOd}QR_vFVAdeIz`8LRSMXp>1UaF{)kAi&45(v-C*=1g`-5%Z-WzWmM)29~76#mK6bLtdDjF}m`75A9yrCTaCv1UkU z6+HH0;misv`#tw=*q>Dcq9}~0>YnHYdRNs4u?O;c^&D{_qNaMc_%S@c8Z1eIRaIw5?m|`7eJLS{ z|Et!e5Fl?W>##nS{>nz|A@@{b0jAi>D@m&crB#b@GrOl(q48^)KU576JnLerCle_Z zi0UvBzxYRW9$ApTy80|7B}-p3k4l&K)Wp&7sh?^}>0#o6nv2Pv0z&PyBDQ`=poAyapA_7MRn?l1`>f|`b;uRg)3v?G zm6l1hSCH2<)Vf(HQ}4{W2(+%$5U?cA2lAQw!8cDxil%Or?HN{oPlZlAKgI@ zZknE4LPa!fWK1U4HF+|Uh_9L`%t-`VQzNqtzp?2b)|R9PO~b5x*y5(AtbRRN9VC5prsBIafw9>mS(HZ(E*HJ1M@c zlW7Y{hSpuQQX;VxNk2l^-HM~LagSQr^zNiHt-17P*mJD|$u!L4)+@=+F_YUSFfizV z=KnxVw!fQSg0gL6&38al+me>q;9dH^TY?~qRShj!iK{vtEf=5x&2g>kVC=f=Rx-S# zGNM(9C@jrry@t#!+|@P>MakXK7KY|z=C;u>JLRj|2C>`ICbeD1K9nqMpO-W!#J9t6 zX5QO&4t^`At-S?*i&fbEkf3AqcC031k|%VmAy(5uJ18U}<#tCuc|Td%ae>@QLUp{L z%q4E>_&|vy%<3FR$-qzRoJ}#~=5(&3{7Tx;8Augk;qB2tsom1<3q;$s?c0GK_Fe4} zz?a5|c1ir{!9Uyk6Lj6c_E(^DE&p}=34YbEyMqS#Q1z*!FY#-+XUA9AuA;A<$Km_) zXLJ@LAlZUWBXWJl!p_&o_tMW@t5JWa&g}|CbHs2rvF|0g+0}-5z-#EzV?8*$uKU=h zteox*Ne0HFuHQ)o$xFIkBxTT;-N$iKs%N+R9!go+{e-|G&**+k$R@t(SwP%C_}vpg z93rgh0g)Eq_x3PIFdV+?&seS_y=#B0$dTcmGDkueH13G0vnvZQMcve;2fXOH+4Tze zs7=t2;5_OifvLwc88xp!*cqTB7Lw0O1tW_4p??CwUf^2Xj- z@Qk#7dl3kAif6A3i52O3`%tR{;$8zPhZom-8aHUQ^uvC3hFbf$!d!L|xCdc*7 z!EoqP+{Kp|>g~R&qyrRtUwsms+|egX+Da>Aujnb}8@-;uRw4YDg=!N*!SGeP5ORTpW+|2IrB77aLI znT(>@lQ2Hjtf3^ll$2^*;H{!&&2Pv=!3pgQ2!cONdo*zcm#Y;ee&Ec~UWWc+J=VT} zB{P+}iLiSNif%U?mz=Ca!e7y|bOG?&G=c62{5@5y^Fgenbf~St7}q-WyO4=456!d? zKUc73c}V}zYt7-%IKwIpDs0U_u0|4euN$bT3U6!GXih}bH#Td|My{)QrQILZT5(aE z8#A$Nj@Ax##vywtr*5Q;zQ zw}GNX%k+~#^8}vyRiJWSqdp#tkPtU`kU5R@_AU<0(vIEI_R{b}CDg}^T<-o}7R8iFLU%@HnW;Ikn{n85+ntdin?69zbfrE&VE)Kq zeRBX}#7{5qe>Ad7kMuud->d&SkYrRE)&*TvdmA_*yL!D1ouOOW9fq;cJ4&75aacqB zD&yMlj;b%ljS-U-GmM~!S0(Aj?8vi)KE{{P2l61M=$O*%c2ikwS>{sHuejIpQ|6U` zRB4Ub8@M>N&My3XLCJkHO`PD7jt-M92sLAVy1aRcztPx zIW&S;UDkaO4Fw0Rxsh*jQ>}$j zp6>nsKhZuJU2m?i*!>7vKg$jO&HaAXl>vax`&LolzpeAESAwG&2ZsI#f!5Xx z1%<}D`G0YkS2<#+KI~`7@}a-NjfG2X^CO<*A#95y_hzeY-jVMz{cKrLAJg~PuExxk zh1jRXTuNivBVsKnckQ)t1_{}&0<00evY!Ri2)pe+fV%`Dhd1yeALrN$e8UTKYyv*x z`Z(6d&)@_)w#FZ0gB?Nf9jprLQ}4mC#n$KEuCb-ov)a?V!c^S3V5R_D7xCAFRQTh+bUzR5qY4QZDL zj#o~z-wP7f&vP6KzEDkautV-CzB^oDt4pstZiLy2{&mg@uPT`1o_E~-; zK2uTTyb$uXj66Iu^ii>3_+VIHfqIx6o|m_Mm>d2*dtkUb;;+o=;U|&i^e)%JD30us zYhBccbgL^enw#3_lEiFJIppey85Vzcor;YR{o{HPdrH_eGA9lo=o;~id&)mCLU4CU zJsrUU%DJCLxPZIdKOG8>7bmtlvONAdvCdKMInMp8_iT0TcRcZ`uns%7dJpUK-R1(; zK(7<;8`J}JcKFfTOP$aBYnl%YZwb&h>>maNHq}UmyMrE8t{;99{Hg4R>rm*LlI1RB z=$pa>mnM95-UHWYcvDWY>pypkRKm!?$e0Yu2r6o-yn2KX6(W5)k`;9_4KmUjjZJwm zawhtrq;KSN3{RXkx+Lb42t4W;D;1(giE(oUlF^E|c7DsK6|j+aYV;I<%9|J?)N#54 zVvp)xH;dxZ^(QOsK!USswfWA(p~hx+MtkGGykIF^F{cB1%b6XDQ_(IdBF`g8@|u-Ij~Tg|<(KlM44nSd%ob>Xap z>87Qb2f!8P&eX`nLdyrf5qjPFj#&vC9nn(Ew=M5bvOhzml`h;O4ls1d|{U5cH6H}4@IHrPTp_Vw_0L-X7XLpPPy<&KE z)FSl7VS2a`0~&rAnvNNDB?Kp9qg`!*71)ceH~znqkRyBi(vuoSN_{>h-5Gh}-HP)V z-Ri~0DM#_1ApC^U1`j-b!{~?O7<|as@naM`dra!~w`PxBJJJEA^gQd^2;JF(@3;tE z+LKV13(fEOR@wqX_wC5}1i!C}kjas~gC|7~(6cl;&K>km?bl=&W>EK*48$JQJ8&lK zm_d#%PVzCv!0kzY8Gj~*<2+0%&?21Gj0SGO?>E1RW#F4E@1$lmxQX9F|46 zG_)?Hp15g98T5$Av26|vB06o^{w~r~+hsov31VOG>q+XdvwRkjF54e?Pb5!rczI1H zA9v6_SCe^;dJk`MzvF+$#n{Z&1l2KYe9M`h3haiKf+jO|c}rczC2U43s&GkCLYp}= z26wJ=XKDo@p}SpRb~lDbu)~Sp`Z)9ulCVFV)KB`UT8_&hi&a^E;-B#?t0S$!KS_KO#!#8+6HGx9AMr`%rJXO-~56 z(?9D+f{4k74J!k;B&Ql!{$G>ThD(00l3yBk`~G08GE#j1U_==ke6}-$#(%w$6hK|p z-~r0KQXze zwTFde%xlZ0U18+66G>XekB;rQr%YDIFAR@)sndk?VEJ~X!opa}ZZAka>sR-KgzxUY z*dm~gZS36|r{qlUZH(#R0Q(k3z2`LcDI()JZ~GU9U*m4*=Y`3*u>P~5o?M0M&ycCy z5mi;tSMEpE*Psc!Jp%!OD|xU1X22m{#(>hF#2PNo(9B_tlt-#btXt*jom$qHa#N#_ zJ-Pg5#bfqT#k|7zY>wh(mYEY)c}7~rWz}HBDBjN6SG+V{f8A^5cm9g{TePeEw1y7y zEdGneOni+Xswn`A6R4DPQOUx2%FA%0kkBlKZWiiWc7kt;X182Q7!^TV zfz{v8`n2+z0py0X>$PCmRq6KH?}>IPt*#n8CRNt20Zo$Lsc(u$%QiPG1>ASk zWEl-#V*_QH#`u_7vOA64QNQGK8$UXy0bZ0}Wa^q^V z)2m*@DznwqVKMsbN7Zf7S8}FQ-;SQ1S)IDya4NGYb+h4rnZ{K4peysgw8LHCtV7a? zNlp5 zKT`AsCdmIyXZ*y`6c>XFk)iKqug6C zP3ej}6qH-)lV?agR*KB~0@+$B%ZGz^mUiYlKwhQ)7OYKxmHsXe$5$2)vHH!V;=fq~ zW?J!O)=NFDWG1`0A6^p1;kFNy6mk)bl#&}fSXE2uRzAG6xRftQELd4OCPZW(EL$Q% z$;Zl2V&7DCnOfo}`c?KJun~|uH(!~SW3THC7^Jm3m zMxgRs1&|r#=I7g35XGvBPwb>3b7d%pntQ9Vmw0t2I3CY zq^9byJvBXP$1%{Fn`sU=Kfh4w=jP|POT~zrwIR~m@Vm8CnGft;ZMjSdn_D|1`wk7O zE+DP4+N<+ObF4$vIiyYIglY@vrn;#59l5_}WzC8IaLq1#n|MJ;^yVQqN2>4~^Edl1^EE)OX;D zwDkIiczWNmhV2AW`-+BSBDFEMVSq%eZfJN%PAZRRJW9b9r8IJ=0eMRr^|WJIOB+AX z7s*LY2kAf4rZpuekBaX#85nxO@1}=L5HCQvjLR3@=LGV_! zXDR<{-p6H-4>iYgpA!32KR$v>KOxA`Hz7kj1oHUBy0T=P%C4)m3l zc>)^hS<6mAA8Ms?GwO+LOt}$t)i$DBfx0+UrVK^r=vOJF7Ax6Y&7PhH#^LDh@* zv`T19fw;AszLfj6^*;SR+t@ZES<0+!+nxM9xup%sXrjGqt6)Y^p>1lWmVB=5ENc!) z-1eEJARceuz+OR^*&fHPz|Uw$v7NZ7?J1nKNlV(BIJwvZ?I$>IG0CkRaJ1drIshlz zZLQ7l82hBwf8bvY_SWwR*FbsO0c3xdu`L;*kFKugwY|aARUK>JfmM_V+LPP? zw6*PhxRSj6?GNyTtlW;B1X}u$4is^(ba6*3X;sRRj{Bt7qT)KB@lEb>g<5aTR(K(MhF{scP&Si=_4+)v$X!AYr{jJt>JH?UWuTG^WYaI}L`a zt?Z406DwZz79!xK-MwST!-clq�++tNM1L&SZ`CC8BH7d-|l9P^q)ef%QpU+jkM` z5*PPROkxYc{oc4}eoTKH&d5#Z7vn?OZT)@tUv7T>4xx=v)BligBKfFl3Nf7aMYWfB zhk8ndC($V9Rpq2RMSBKCvIRSa&xBtz;5JKdEx*L)sSW!kfD82_6&5Q{}p{4xP~bZJRA6d-OT$o zxBx5T`VQ{Jeq<{L5lM}#t%G9R1jf}tCT?7E%3vlAP7fH=;a<>!2cO{iRHS+pVH`z1 z_zABibJRNsfh5boxY*~z7gfJwU%Th0*!#oh2A0NUSpPTR4G7Ua8=wK#sr&|-;}>^L z8@QY>y#+rwGvR$h=%6p?c6Iw;D)^3qKG*~4DajnXlPE2Cr=ACe<~FONUML!05|Q#j8<-S9nX5h)-R@$j_eB@E zsOt66L>EpS5dCvVtro@H(LYrW#l9LqXeIzAbsyCn0z7L~YDmDdjfI-pcva0C&H04t z3XA5w`y2h7b{BYSQJ^*)Y|eYGEr*=Qey&v{F3)(Uy$RhVM`>R}d(tlJ*1)K4eqIc( z5nFTy1W9;LH-zXFtkwNMX7j4`^N}C83-yOlboT%B$5DD#iheKZB6FWU5WSMIS&v31 zC-2keW2Vug_1zdLjjk`pAgNheY-HKUbZtT;d1Rv2FLJl*ixw8yYg1|qq6CH;T3d9& zV6^sU46A3K&Of%ktxuN|H`3IvI|;a0w_5iJ*kAcnza&1ne1bkA0a7f`qZ3{itkTzm zZsji3_kj^vJN0)V+tN!6D-)N=HX8m+Oig`kNPupUTs0IzKZ<@EFwj2XS_2(6kuNl; zVGno)u^o;H%Lj|%@{r|Ja}r;G!7Wn`^-tNvzGSMOrO(&&M9g&`=WSXpG? z#!~CP8?139RW}XK0eHnEV+gRnq{4`c2Nwnys}k1dc^I_`W7$yS9S}RiW?BJ;$pNO# zV7+v{=}+*_l#eD1#35O3B0xTiV5Zd&tUziy2D#0jWRfOoxED-+L$f$)vlq<9Hkt8o zUzXJ@g?BPfn5z-98Q0B!A=(&|%~ui6laCs=hk1@JH|`0G8C_*u9JX+Do^e~4%(2B7 z6CPj^8YONrbb?V8Il1?}@p9ya4yI{*RC_bibSPR;|I~zv!BksKgc!TxoXH+Hz7%Wv zFYZ#&I&(B|N&aDTYrIEJiuvF8Z3TccS*JV8kME!7dj5xtm-l||`*#D8 zDa*CnfMeX9+6YiivQ#?@w20NAc@LVzT%g?x8l#VCS>V5DI_;gP&q*4sK1xH)(mJBP zQnI!GLd4{D-J=w8wvYL$<#JyqT9bHtvaZuQw}=cpg~{AaqYS>gLYb4KIi zr|G%s^7HfBhBbKsXB&exy1*GV5t>(l&&w}re+%Lk7inh)|6ZWddW8IzdqhhLxtRG$ zYYm&3F~z0oZw5~a5p)y~0Dd>9MeEsy`OIf${$3yBfZt8`h7Wry@a41gdug?uj z7QN8F2(J=6G#rX(;(s#4L|=&{fQI?aa0M8^IA>e{ z+C=X)d~xd>FW5nsq64ea{zP|o-jwS%hm7e@YVHr zJ~lts-SyJA`1upP`MqECt9-V%|EH(;rZqL|&-wjZdrLp=Z?A+J<_BO)4;qdH9w@{a zz=30VPYs1ZPqI~pw%|BLli_}dkNmzt8?roYrQxrTY;n19X=sTs%P0%`nW{JH!yPIA z7(Ye0Sfr-ok#U@BCXdMaK%fteV(l{mrz?Q@? zMFGxHQ%p?YF^b->#G}$-Hca(kIyCwp9tcODYgb#~hIO8y+A9VxuhlO7{InOegJ$4+ zbDGx~9{7BygBXwa`BnZfrubt^KNR-yS`q?w7cEC#?CT=O%)N;=GZ88DXyHah`}lj6*G0T^njk#cs>xy1-STjN}B z3_6Q+E-?n2&9K}t!aNr1!i=dNm-;6dQ$7FeoNO%hbT(HS-*_*tyKai{>8eUMY5W$K z<(c05FDx1}ZwZ)GfHNZkr?~omiGj4NJ!XF3=M1npBM2c=nMpx$()H%*;GN>B=JAji z;h&Zxp+2cl%h6D7O1&i^YzJ?pr6TN`i~n;aygpfMc@eRS?Pr}5k;7VR-4(flxz$RE zyw3=;21M4=-K~2gr8IZz=}5EdvuJVeck)f0?xRkjDcwEENj0UpS6CxWC1>~O&Y4ta z@AdOcPLHI{T+`p46IyngH+cEgqslO#neVp3*<~(vW4QJ{_X$?5dBk0*KWTn+_H_S8%kLhOyH;D~dx%<$mT=F;`Y#rR zS4*|h(&Qako@(j!9xd*-uJesi;;pfM=sX{*&3`nTX1y0cP&C@s2Ex*}+vWyx(yDB` zf~HDRZ1AAJMG9M4aIe5-69t#@f7w!l4JpyK_7EcXgY8M^Hjc%$Q|?(kvmm}Rz~DM1N&;<1HKKsDh>v{(yYrq z1PRq~pYA6lYzoHH%`dh`oiHTQjvm=%ufHp;FB4X4&CFl;)+s+QCM4IjY`sJfmIRbo2Q4B}D z*E7`L&fh#k(Z`(Nv$xTFXO+7gZFfF#^TW&-+;(O;CU_8idJ!gXu>RB*%(cOLCq1we zhUTA$!tNY8eOwUE#8IgSIa?@wx*1f1U= zTYnaa=>J)K542JBGV2{!p_s%& z>3*}3OYL`k{y>r)N4<#1za0{fJE(An`YaRWbi8!;MtyXiIWvy-a8gg7N9Q@KPF+O* z>$IJGiwSmKKe++Z?EG*7jAa37| zgq`aq2xHL3~$ZJ5A@j z>Dd3wM?K%+PMa${YH>pIi?fNiVaq1>gSZbCrrUb_63c}%>+o*Y4X1bEN!FxOzW7RO z-AO(I*EqS;j5yH1YTJgG)Nr&KiTJ%CqOcf|(zqb=HPX8&M7j-?)e^&x#B6E1%TB|F zbac^<;+A#3CI#YDUH7nm;dghJAgl0gJrN1F2y1#L!eE5FUKMl?;Y%Md>HsmieVk3h)I7BYz`_RZyZnrJR+k8zWSdccc>A*8uDxPMIQ`huV%0J z4hmYs@cc+A(&#*%P#oIHXJ1ghX#L%PQTJ&x-T$B_YA?G*6XsQBcQ@kSRIcmH!{4fS zS|5iWsxX#b#$T(rmAB00bJVB15vNuk6zwK?)n@Tdk-7DMvwo+%nhrm5l@a}z6}Y7SM)I#>0YsAQk0)?%-*l{LvI5c_NG zk;Ki(;k9q#cP2O1mB!*ZQ|mpWA9Dih|B1@y6g4D)7@SuPUjP#Bfkr{ZB`&t{UHBGm zV-qB_iuWbq$>+9A*@oYG97+csx90X_gVU-&>VX$?Pw7Q zI+n&MdKA4iO;-$wlBYc{z6AOqTUK%!*eDAqX#pT)X{GZbkH~sTkr6vwOsJmlt+JP; zKf(^m7nXU32FZ_`o`K@#&dq?`#j6ga%ouyby8BaGV9uln? z^E2CUmotL1;xO|vin8Y*g&Fs<&57=cB{|^+#rp=VlKC!FHmuoceHK2B9%8@2T=^BoG+i2xq#oJ+?5GU&B>mTSuO~ZOEMn{ z7mG8qwhFJN&dXAX$=r?E6C@{DiP@pjm9($f1=4Gjq3lO#EySBSTV!DT+8m60J|;J( zQ|>^8<-AM>A`a!QPk#wNnG4R~#*1^6ikYzIxef&@HZJ#-;-8qAc`Gs_qKEQ=GEI=e zJZ{#?sH{9?76F`{*OsLM73K|Q{RFn;J$vGzGWECstGqa{b|p&u3O!F*AfX_aD2F94 z5@VF#rNRV#;r6uO;|~`Gq(NbK3#n-Xu|U_)ES6f-YJi z$3=094#-X5Hsub=16`f+0OgLZL3xBaQJthjQCqu;l+{V(=K0FUw20~#g*)hHOOF-O z8HWmv6k3?uvaS_PXU&#>Dhgx0lgNw8*!KjYqI=1WymQ6dIGM?qVhq=pd8)Xbw}uv0 z{DJq7QeCn=C6lzM1jBd7Un^%s?$Jbra+u7^PIK2v;kZZ~rrNxx;!nD#SRAuggvdu{;is&*7 z4W2e$)=o7h^eGHt^<#Q((xaLMj1WpyjW^>3DZPfmlo1MR@|nMIw`=q) zI`(MIGxh}ZK~TXPCo)^V$bfuc3Os_93^R+DQ!VggHx zYWHFHE5mBZxK%kBwY~TmiX*kJ@V8{g>vj-y;)1$FqEK+KuAT%-alNIHXLEMcFD2h+ z3F`eR8T23Z9O}U&Q++@61*Nn8RZ<4Y*|2~%lQ_HKG_4d*ZlKUNV?Q;N(aSK+4ej(# z=;#I;BM7y+;U1$LIltj2<0WEw<60&laYy5RW-a`5<7wu#1Wf(Dc!H^*es4U?lwZFk zKE!yb9vJ_9pr~GvFxbVcABHzIS2fH|tg1cQ5RND=CpRdO`9((?ZlkjE_>C*jysSNq z{+Q781C3(rE@@6kp4(& zXssbfuc4Q>97#Hb z+R~Dc)POwOl9u!fks_e zZIcl?i09fmiKhwtw(~?4{#4ry;wS94wl}1sm{;v{Nge1f?fb|Z(X-n@MP5EZunL|jYl={SUJPMOm| zM~OMb9i`~y?3j)b^awMk^EZs^OW(N#J26Suc^pfoF6fNJj*&AuS-7(#x6X3hC~;C} zJ$@11+^NO`ab2C4@Wohl=WF~|%wJtI325}wt__49^s4sPV6f#)`%AE|VGcFcbvduSZ)x{p#DU~{-G>nd)<`!B zNnkwfE=SFxyLESN))fPIU@htj1X!%uU3efsFX<`+{n6jjbs0Rlb5{2> z@T;c3yWOMi)*kQXLC#fd?zTo>D9-Bs3LPi__MC`m%;ENsW0{H{?y^5UKgun$sc z@1!`BsH1mFJWw#X7mzR^Mb;}wXySr;%ixQW-FoftIu^M1OQJucuWx2zF@0{|s>Ihx zl0GkllzOI*id;{b(WgMBk^b&0L)wVWJ_G6$;cDM)R1^N+zVGNo`04$d&|I8~kO7sceI-RcL%3M8}pnXqlb#QqZ4dH&OW zXB?NO>c18DkyFb7Fs1E$pFJ$gwZ9DCWTf>k z3BNJW+wT_9+P$?O7b$7|y}ty2u4nX*0>i3^{XaqbN^hvPfW8#gsN%tI@-C>dqXx3w zR6~%;j325m(Q&eO1AC!orRxX6p_fFQ0dY*FVETYP7Mt>H;A!l4?oIVgFQr58d7c#P^m*Vo3^T+hK{Ql1M9;6?fGpWI{c|iKbJ*V z8wdls$l7Ycz%u}`?6!Il(7mW#9R%8)e^*Thjpc->yTBJS7pl)k0p-6m6Cr!jc4_{E z7{%!t-)NX{p+*GV!GEvGg|c}!HTsy}6)CmJgFKR%(l3 z4{3L_U2zAJnze&*xzrl1HLjmh>Y8KZO06S)I;lf@Cmu|EswM_6wqI1EgQwd^)sUcP zcBh&U9B#UzE(}?q*`Xc{`PO6BObi`s8_=8x8*Oyg@Wb!aL~2YCH_ESS-bJ<*cWO5Q z1O*SYA;8nQQCdD|a@KNf6{s|0hIR<-Ejyt70Ddni(M^kjh*s!MLe`~z)`1|cDbI9J z$Sdx9U2e3R6RA4~<+IQ0v`{|lkbYuJ40D?P&zOJc7xn(J6k3Cx6Z z7=fbI%V4GCVSPF5HtCmkOJJ2FP`f%%?C{Y}3k-0a)GiBbGV`@(f}%AKwB+FZy&P?Q z$f9D2v-bV=^|9RO+eG<_g&f5vw` z4tQ0*QLhB$OBMPC@O1G^{RME7;IaO{s2Kiz{nw~6-oJ)FAX~Yf1`y;;veCeZCbGQ@ zlxPm~nL!@?oY87%hf?W$!!77Hn%rQ8jwZ1TcIZcHis4m^(8bT+61#!?S$848*Wu9V z0@gY7x+?$YjxJqmfTv}HZZzPBR;v3Pc&=}QeoK(1W0xKjT-9XLOG5ayf4jIn(Ul;*Z8?5K8!$ zQ4U_4dfu1`My1>`c7pHm4j6AmC36~$zaaCI4;nv1ma?uHKR`A!(@b+9<%}rP(ddoz zc$1$isf0Dngj`SZGfjoOp#n@Nqs5eJ!xFz+&eewbepj3;4AcCEol6ZX{SR204JZAd z=~fsL13LQ*hP=S6j*A9s5UH79cpL0pCo!%M*-$md2nd~1`qh{m>L}V{tPG>%cN))y zpU$BhUxi=KB%78+e_QK3nj%rw_s z32p@VikwuVzc0>7FrM`FcOs3Ez9#Epquj4vS7IFYZ|(;eKL_wTNv4f~z?Ma(@SxrG z2VCy`2~{RjTkz$w7Lzk1q3EvZL+JJbqbq1w&2-oIOTX2;-hW!>TQe!(NK1#gIdEJ3ZS#e|r`0I)cu;S7q-Ab!K(Wkn zJY=PEvBf{6Aoqer6e`WSYvF|&GR7^2uwFUCq7Hi@edluW7l=TWWwAzj%*t19HD zqR#p}bU1yDZBiK6#m`?Cc3YBWgNL6JxxCI1e8H&AJ^XL}Q(I)jnUo+~dgNs8OWSDV z1($w4A5fWGYu^C)$)?%^fdUrKo(!7DEVY+`xD2hG0y;+TvhzVq+EdGz7iy4f8Sy$i zh_du~O&W}Gk$e(u!IoFvJN0+0%e;T6Dy<;j`CVf!p3nW(9BYGLeS^t5;vZWRX`2(k ztcbGh4*a8})Rq&(D-5@OoHa5g#CM|LI8a`*!FvzIuM z0D9JbM>Wu!8RfVJyw6B?Tn4_T4}b;gtL?O?1Ddl9yCJJJPf8o2FK9pIierB0z2seS zCk?eiRl;uLeeNE3h3NrfZ(@tNhpap*lVcyU!w{n8#@Z2*E1m3XcX+1$b%szFO@L{;^ z)GBb9`awHCYL;eKLrm0|X0WsvGOo?coeRCGGsq{xHX8mAPKl2&@;Ei{Nv2ZzUx^3J zDP#g-wdEvEg1BONh?S{VtCkUwnGU>i{!ng@BMg_}D#&o>?yH3;)I;2H+oy^i8O41V@_jdvS5dA1*) zHpF*N!|R3y+*tT`Lod&y61ER-I9*6U41-T;2-U;#lV75=>gDaDQ8x9|Mt8`5wWw?n zgA2W>xZeh2J>TN|2Ae!;aQTBD&!TZphEBS>;a3gO-45V`hnmlvz$=HG zr=#%?h8~}i5_SyzJb5v$u$$Hy6G!Qu+Y%JV?p{_I5cjIPt3Vvz-P4otG-0Igh}bO= zqzdPW5O35lW*h2|<|h@2UZFci5Tm>FbJ71{PV0vg|HgC~lH(^~w-^`4$gsu6R!9VP z+yn)M<8Y?Sk!84h=E(3R_`T+jA%pk=OK4CxVS=S4V33eto#MZSAh#C!A_)(yH@%+| z584)c)e#l8P){oHxh>rzoV3<9de)nC+`h=&jTCK+AZvo_UP0%xctsK&Qkot?r!=c!kym3 zlodo_-$Hy9X?ovNbSg>EFH2OD-l&eopCU)8uEb6yI|ew>3n?4a^T44Lg}MkZM0usz z7$K&*X$r$o)DrE45IXg>787JoI;OoJ_-7JRcf`LWsY|Eu^G43du594Yr9 z1=Pgk7mp3OBf*?!|}Hms?Ma?r_32$E1(;g=&q(HCDYb@7!<);)U5&>V!?YhM7Xm$d$PhZ zSf6^Qg}h|%>%|2puoHUiK{ME8eJcWn*kgTo|DxpSeV6=X$p`uu`er4^_IvqMCTI0C zz4giZ{x+`hDX4D-qp~!lC4o^|>QlX+QCR9()WT4g=478|t|_C)YMCSD zcZDR@<;w589qey4`&jwO{k2Nkan7l_Ch{&$WjzQF=T2x?gMQ78Zm=Q-xC4#U1PgCY z)5^HXJa|)U42{>(92mWg_r3W>)Vvgr7H`nf6j6%?5R+nSJshFqPi(CXKg2)S`rg%e zMrd;jso+<%)deH@qwN!eApEcGk%0-RYuYmc2&um9CVy!vp?%y>%k#=FS9$Z?^Al8? zc#-+?_9`AR-(2V53G?5UF?qQK%kz79T?L5>cFKHZpmaw{f8k%LYJP9=SMI{pywVZo zEy1d?@uaH)PPvIZUvRrZh_4jxtK5UZ3MG|Kk#yl$RW4jF+ETqEe!GZVJrw&;WUh&Y z{w4Zea~(1&K2RGGHBX#WI|3q$wRI-|AH+}V6pPI$`m!e77b>OSKbl5 z&w>BRhK&Ms+n!DZ&Dv}wwbBypOn7nHm> zt-Z(-e?RTJ%Y*zv7F^tbIv~p|@l33gT`Res0G6*TCB>bVhnJ4Wy2~YHIH*W&E4u@E zEdN>#i;7L(Q0@dzN%yZ<4K$>4Du@7SdQ*itlAC_Ma&3el{X-=oJSSsbWkXn9#;(fS zp;u*Br3TG%*-dGSW`*pH^h56=`5$TA7M&a-TT*jXUMka%Kozu6YY~7Sg4Nr zl}#;L1GZ-u7qLJC*^Z*~Kx_7=;thZsIrED_kuP#K7nesa&AgdAoZ#ikoifl zv_CRyr=Yw2P!?7QuV-d;h_+O0%^DYt7lvn_5D(<+$)-pG)0?szC1aA7?1xf{U`tN2 zY%cF??nF6;-Ig1ezK?Mxw=#V^X<6=AMhkge-bMw4fXPe9oPxcRSCmTg8&AVH0I2D#jET9PH%lHMI0=sy6!CPT6|D%#D8t294@wtv zi9T9*Lb`=|vydx&MBY$nPRl2h7Jinw7+FQTWhTtABBDGR6;MlGDHW${0XkI`)<3o<<+f0eAsOpSV1 z_?#it7Z<)^@b#sI zl&ul%CcG~T7a4HZ%Vgpx%+sPm(^5 z-&3BKwli*hd3Tx=wz>Rj+SAx0<=&cr>!qEppIbIgUtK{hKSBRlBq~p3Jj&Z$KFA!(jH#H#s+E1O2x61O;}vBXMWysN5lprmlo{ z292#7Yk>|M0~3MEd`kPq<(Em5BycV8-Eu3w|WFWF=0)827e$vsuqd4Y|3`c zK~q*O4C6FL)Mj9js()(DxDB0swcl}{nl9Fz#9yuf)TIyx%7k@hVnv}x{Zv;ky`K2VL>=&qg@pGpwB6!GSzvrZ${I9x&4zMvwj+g~Kg%fdUhA`pem9SG#{Jak7p zYF(DB;~&(&>F+ytpdD$Aoe>z0Sl%hb?iVz5wqqZq{OG)b6L8sGlkl69y}JIy>sY(G zJPC&xC%fjJE72DR#hiIMye0&Y>7S95AVDKThO8I znh*QX#P0HTC1#<>%u!no@Ve^>Rdne;&GPd;Y#HG`+d%bW! zT>KdrK9r*EO~zM|S-pjXDJ0KcErCWn+dD|8Bb@EMM!1L%?EQ!E6PM68kqE#RcMrNs zyNV#jOA!1up_nqjK2H&1}(N9(M9&f0r^Ii`prlh%}r!$sWx1i?{ETG~??~=IH zCDFYBai5ic_6p;Na(#OH5(JsOz0ctx>FB;?@c+^PeZGmkVoo0)ffwBCt3!G+W!@sOSY+& zVqcMrsy}h3iDuPy9G&1)9l&+sud94<&+#*Rzk^}6FTLa7VB4qOf51CzuluHgJB>T~ z4oBe!Fnt7wPuHWqw&;B=w!Rn8mGwvax5Z4Z+SiYad0JZ0UmDwAi0>bT(etwVf5z?4 zo}}6p_cUWb1&VK!HK=$A0g@qAFMN$?m+Cy+1)x%WN%Tlb9@vKXjY}IijX)*~2jGZ* zS=R@$kaDKSfEu-!K007Wou$zS?xWO6hX;P4cTuORH>3a0pYcY&A}>{gF~>=p)Obu5 z@syf}86l8WYk>at4Am0g9($VVci(S>r%1R93_raK<3>n+ATw9?khfy$?29F{X}%+2xnisc{(TCv{)^ zT5+`cQhdMQj`~Z2JHJh{Dd8orLE{d`a9jy<_?6_@8bM+ti>_%-e8Tvp(IPg}+cd)n z2o0%uj5wEcP&*xYf_hN92iZjN)9yv~k%P1+kuON`S}4kgSfQR5neJGso)k%S%pZ6a z>F=28+Kr~$>g@ogW}6xWJk!&mmV?%}RjJM3iH#f7AHican>Aaaddf>QFi3GRQF!GtsVAQG)en!94+;lZc+T?lnc6p z@!8zxy5RUvoTEBS0*GCy%SgD&+M=t6?_u25^}vzze4Q0uLyOVfO`Mk$rTdjArDFBd z6P*;gep2EMa*BR2Vlk;#qYWQ$q-h4iyB!iuM|h<}pt%^a)tsgI5^-1aQoGUBWs{-> z0vPQqZ5lABX|h%a`lEJ^_66u&MVf9sc&G%W^NAuUb9H=(Pu^l(J>*5!1>K`)d&U+0 zM5w>)KmDngWm1ejF{Vj0uFr{$5?s&^!Pf9E>p#H^ym7;lI3I4HVP~8nx!d3qzm~Id*q639Zc8u%7 zLf<+*>Rc+BR!MUX>&_#l+vD7Md^#(<#IHry)!yTz@kJ?u^k7h4?yw`g!JhAPvUmdIOeZ$yrd$_?{RI^ zVWUrQxO32WJouQ?V%!$I!l^Z$3>H~EjOY*_o!(dyx~3mv918u=nPU7BHqx@rv?aW< z{*(z8A*>oTXVDk)WZ;Sdxp@!pdTyvW7Np3EGz-87GQ{Q<@MYNt^X;fi zX}b9%WP&)>G7EwgMq2hq|DKv`35>?2T($tC>v{VuROkYZ&QcC7PfoFPL!YwUEH%)Z z%&!((Od#XCrntI*D}&AsZZqWuZ5-TSN)7xqxYCpt z1hX1UhTv6tH`BA=C;gwy3qzW_=9|xiCbbNhiD8~D{k%SWOEuYiA^dT9l=(lGU9`w@ zBvPo{X^92w%>8Jo1}@2-Vz~;urZ{U|0BVyPtw+HgX_3}&uv4YqVFWnu)c`C&9Yj*Lzgr4whhn<##LKj%ntfz z8#6{t|HFojX`*?VuLe#Smi~x6AqxEp$Y{OwIG;mb)*(wam>0W1T4TiK{wq6g}*6_fgX^$Hi|A_GWWUQpi*3L8ogZ3c{m*Z3XufTl|3=#<+kXEihIAV; zV0a+PRvOsTooD+iD7`Jz_Bj~TD6+2!SzNou?h$gaa-p3TT3Z@tFAfVVeCuNJ{E_dp zzYf>uoO7&;NY9$<*c0(4gW-sb%#+V^hylLRZw@{HC4S;)1uhb~m`T7vfxyuNr1Kq) zXP`YP3C>-hpSl9Pn(@Hn9_tVMe9+p*C3PEG!yijZ9jI zIcb|i+=Y2zYjw4#DeUfuJltHnGkyqH=A;xP)U3?RO0`H%I1o0mDB% zCy`4=j(Pk>K0iV@JDvP}q}+WeW&6me+g=KIZ zB7o*HW<2tzrGgrUo@7lWq@eHEc4Agwgtl{tDcG6zi1^dkJo~Mfi@13X5TpVpcU%H> z;HNl!BfsNGPE|Mw|8#JE=ph1Z5F5OUP&Rlka3kUE&`y6c(S-r`y+N!UI_DEhygNMC zdpc>waJZ+P1Q{;y$Rm{vUpkvfx;rw%y_!60(geIJxgk*EM)( z@AK9%IJj?8)ff11Uv;5JBB#GBvj#y>J(0XbUROK#YtdxwDBB@zE2>4ZAVA5b9SKZ`jkl<4Zj2Ido8*Tu*=r1`esuwIfY z#So%!srSc&3dz&#!hnCsdmPjK_mV-5T;C#cwd1l+5cxmHXYUo10O$Ju`{$hj9$zRo zoMMj|)Ok+r**~Z!olo44QE`K_-ALHB_R~FFEW6FtIUO6-R#C^pvf6AVcd;MaS-IZ0 z#*R$66kp!8K$u4O+Ow5gK?3z1V=~FEXb06uIiY$*Or+QbbXZ@ihZ={JP+K)~;4_jI zYuaGfk{H@!&|68Dw09sYX!~`pU?)wk8v%IIZs`LeHq&?LHDP<{G{b@rCf#VD1YM_p zH{1&hW*ju0^8d!b8wGy-j1HsDSIl^6eDA|&&Nq2^3z;WOO0PU7(q!>$WoDROd5ls1 zZ8*}mpJK1?=-EZ7uO~IFq7>IhRkTwE>T{KIsaqRJnLgBujjhtXNw#K8>T>$@*8Jo* zjQ#BtMi_HR$0O=YW?83|@QJmeOMyMg;&$&v8d+oA_uy&lBR%9e1zX;`EM|oLthY4! zO!Be5`QY(nXEL%lN@fX&kis9UK?C{E-^hxZGRlh{%lAqPwOW|{;)s3^C@Fq8m&ufe9JPHTfe)v2LvcOWIHHSJ(< zYwEpr9q^4{X~$-Ok07EWGr}Us?syqa6AX493fm`m+bIqCBwX5gJ@}FEOxK2>=R#r^ zKJdG+x~nO0wb0UaJ|KXfROCNE;Ny#a9|+?!ik5W@^F>8_>&N-BqBG?!{EVW=f+zge zqT0;v)CI+gG+gRH$#=mIL1Eb~o{zAp;wO8z=y=s}`d*Q>+Jhn&FRXq?oF^vLlw%)= zwY46or;-`9_YhkpkUBv^xkOn%BQ8)fR-X~OSGuWTKJ=6n(jbBGr8x~Rz_+BMje(%Z zv?-0Qez~-LP4gm6Y2YSkgdmOIR2xoBYi)WGmYjC8d2?u1+V|#^kOtY3W<&55NqEi` z^;JnkPJ{ZQ1etTWyHFy_UEe%I(wa-D`XaIC_7}%UZsoqoJtg^&w=eykG&p~WBwYHs zAS;!h_E({t8z$oyZ)Z{D(@H?J3-Z{~`4pJEv(!o4E&pDI#~n@gDxZSpre~FRBHpE6 ztT+U3%$Q#>5HHUNsq}{BWymYdF}E{}RqLP!Gu~7wAgziuRbQh(ity?<@G?bmbsca_ zQC(kZADWTtR=PMkAUC0u2AP|iQfdT$&8;Y#4EmXCEAs=* z$$eR-0B*~hQT7-Roo$ya(Lu8>N@nU{*-s_@s`#8Gk}DlPIe}7QLuO7|+S1B1IgT`I z5h~}KEGpM6ca!XVhAI~<50`3kh4LZc?!3hrktx1;{fc|Z*8C-zkC}=2(5!6Q;r!a{ zK#F(%gY3t|^nwjJ8Tj7{;&QiO3s81%1%3g})WNiGEhNMtKPGqVS|r67^qUobp=K!a{N3TCiUMkZ;wq z3u5^LdQJh3|4dCRC{Io9VinvF{Lyq@xk7Nix=R@+Y%F=NY!Kn{|4}{_ug_u@E)v(u zMTNeS!;8@-f%u?!= z-4)wb8k_wgroEJxa}cU6t;(TCUn|w+j6_c@ZcBb>$ShVR-!tSCTR1bckm3)V+McYE zZQRh-#U)tYqT2D2cHV>Xppthf-GyPL2l?!r_oejI!-|Ea?Wqsa>PnvqL?UI`2H`Fj zhpSMO&MhvxCf>^?mM;~5V2H{?Bsodv%H`4n6pwPJ^cHDq`R6n+{&~gbG}kkx0whCV z&Q!=`k5JVWo$}+zWffQC^@+BM@9A^k0#^eKJt4F*AYC8tS(%tIG0wY^pAiO&sI1PY zh$U3oGX9CFE3akv7}Lv}7;eUl@>T{!Kdbx><6~cZ#S&&i`|lM%7Oi1&MH$<#5?}E+ zd1JA#au;WE{((vg=Xw^rQpIgZpIkMO$B|B}I+Joz2(FU<|B6v%(gzgk#^*P}cQh4+;VB(Wh6VYqIDMOVevEF*M4vwF{Wy9A<4eD^jth zwt&4wwyE|adrZu#TbSG?SW_3kiQxTLC*>~WEUdF}bu2{PI1fs{SHFk%E2+L7o+78@ z)MxP*lFI81d?n#U{rl8q_^^f*sZ#9uhNG#^G3*AQzzcn#A=!1y_|;G@_=Om6Xcu}U zerm7?h45buH-vWh;)eI4-x7T4{v~cSBkJA||3}d|M#r`GQM|mhja%Ec+q6lV#!hA? zW7|e-+s1^$jE$(adu!Wz=l!zRv(C5YtTSh3_Ot){x5$k2te2XWH7+2U)P}}j60Jc+R*ePib3W)V}C zu)bNzLW;*XzhX}lEN@xP?&q>vf;d3d+ZGAu2Se^D;3%Wjw%p`RqO`Y;X1HT{$fR82fpl5gN<9d|(kRqH>vX9PYLkU7 z#iPvHDrp&-CNGhm#q4gs+&&gNrAgF&9Q&-Mubq$6lvlQ^@To;F+dmN?9)9Zv;_@tQ z2a@C;|4h z^QLiqy@B-`y|r@|e2dl9IUBy#qZ8n>tht@L;T^h*op=OF@wBrExx4d_$J?LT z{IhEb>Tz8_R}@-Sxv?u3BPxmS8p8S)cy*7!jm(Md-j8!{&%RBna*aB=z&=_Xx=}&ZM43@-NoX9v219AojeZyrNx{&7=~k5wcxW z2W7m>pSGCflwoP9#9Ubx?I|HsrludmSIaKZvv4xmJ^CfAP4<>C5%aOT7ZPXVbgLnO zHdc3=hYSYpz6dcGM)eGXa#Txuw!uzxv3s!a6|F~mnh>MwYkKY@{;Nun%|~iWpUNUp zC57FxOf)R_tjvYkm~~M09&PZBC`!)FSw$bP*jPkAVKf_kky z0er4ISFVH9x54F~p!|k&ighr*YNG-QUs}FWQ4arF^j>ieA7=alWHM$ir8Ou7+WZuqe9^p@W-q2ajo3ds&@Q%HdW=qQ<;}l zkMVaIVd}922z`QjCZU6BQLi9;rzEQn5|5FE>L_9xDNW5J%_P>S1*B7iE_Eh}jK8l8 z1SsrsWe`B-QC~oEnX0)O>E_~ab78UgRgWUI>&329`t4Y@M8K>Z2%AmMB8dQ^=hxz``P zN)*z|MB4>Ey$u);58Z3Woa1PFA7ca9OEmvr9n1#JTHG22P_qvgPoJwfg}Xq#tpVWY zQZ8vcm1*RAnmoLf^hr}om_!<<=^*U$^v^`ca2y9cigO%L2gZarcB?5d=S}C-^|85{ zdFmSgoUFWeDlniux%Vh&Me~SWGU!9?pWeDSYbBxg99Ud>sP`AdyAY|_44sgBPZJ5% zXBB8tVa)UljU2uzMX7lJw8`9sBG>%tr7K^ zb4>dHO=tD#CZb<4lXdGbM;U&)BbW;M99{oJ>&Wu}0 zO496!Dt8z(TcdIuTFvq(u0x?Y5cSb4)?lN%HPC_+t5B-foHzZ=_lk2r#B7QmdXx~P>bnejJk2vexsQnhX z-?Cn}Jo1$`OBWm^Q>@X&M{_$@>Qpg4EppxK*njJ7`c<)CtG)E$fZpcQ&)ZfCHy{{PS$cqLf1hHAJ2`Xt)mbj;}JjgIdJd#woCa!gk|M z*cHJ)#^dnyJcKb4p1^r(WWv9B_^qV~9t&fvLui?sjS9qP#!BN^WFURJ@fFfQ^D~V> zEv8~kb5OyQDt%Kp%h{!`4u?6V`ke41&IWyBc#Y+zekj6QcT)c=a=hY+VMF9#=W7En zs-QLAkQa?;C^1-K_SDQbyo~u${?)iRcCcid@eCllKyKs%gL7HNF3{{Ow(&9Ozw~a? zm^fDIY|{?#x}+8p1nfviGR1o)dW5DL$VE}P$q5Y>d^25zs`$~S=dfwqo92IDcuu}~ zHS9k&z`Ps2kF~~p3QlJ(GRMN@jJ0M8VkG^LIRycx#hB|5UDP7ulF)wFbmOAXbFOK| z*`aRNWaEageO9_LIP8_~v5_C%txPpGMX@Ji|(a}FpanQXSkZA}a@--s)Z zKV=yX-X_Lbwt^kP^Oiu!cELdl8PdgbThgJExgtv|6vy$gSfS_G^DXCK6IfF%_hBcP z^DOUROvXCv2$+HHWnB!POOu#rA&D-ci4-Dn5lnF*2p7V0WzhP>R2`bEhnX&g0abI& zL)aH+}P+~Xb z46{_nKFQo;u>eSEb(Y7#;VC<;bAVk*bFCXe6A~s_{XyB1EmmIKa#6muJT6l>(%KpK zfS+W&4hHgkY$L(9xbtmWAOQ9cn-@gJ`fLk;d|>{xMM5_+$JyXeEMuvS169+b&Bove zSD#rPe8gop*9Omb={;+PEzEo;WR3ooWlG2oRf*+9=(%o#g&o!+#am?IDNQAoXAyCA zo2`o?w^c2-21I@+Ls{8Tbw%&3jnU!x2CFOjS&rWNE+!@OqiuHV(sZb8M{I@1KL-JP zlP=p>0BgdKEd#hp^1`M9TE%BL0?X~dhwkZ?*Fk%21J+qV zPYmJK6TwpTY%427+~Z}HhK5RiSnq}{Z(ePi685>yXgd);Sf#XyBednCZC#Pv;sV?K zsG|i4`|zlHxhVUJXnt0u-8W`&#uPg=rY5z@o)Wt|S!8dDH75$}TEL3Zpx#GsO-I zcs0Xn+Yq?K&9E&D9Ofq4#s*w-!)>zyH`;gE_66QG*lh5i8g-JbFqqw=vpGTn+Ud5> zp^KWE>?=cG)E~1)hgqu++0(-dJTWl2XO?Q7{c+^Pg4d48k*eIUj)PIO?A;D>^wtc8 zBQ;u{cEZsSb0lSz<6O+yq&1EQv0D;OI)}y9N*bN30Gq`NoqGWp!g^;Q;GO{Jj03Lp z_~%?;A@`fJ2>6-v!8S1FEII_aH z6%!rG@D(K$j)&oo3n|XA5u!YMT^Y0x!1 z=5)eq*P<9*yr1iE>?X0r6%$)83Unc39|}jg=zwK>mn#`S;g!0Y0Qb1nu2#S=PMxb2 zIGx?@Y6os$SzK;lDr-3SfIhMNGx)jwP1_imxwF3xf!eR#r70(2m$ZdfqP3F<}jho5%Zkh@M)w;P8+y{lXrTupLE*H{#V|a{a zp!bb?Gq1y=OvEHOGSF-iK0rrV{&IY<<7_kO$8gcMAEY{bkX?og#s75pp-vDg9k*e* z#F@@W@LXcP^Ag}CX}HTP`ZI~-QbZmgJ$A1M(~yt4<3os^5b=LO5tPw=M*`54@V=Zg za!OU-O}}ZB7yZk9GpRfK5k6j2UVpRqSZZhg!;?eQ`vY^mjI`MUekb}oI}#p$KuaFz zIX;rsJ#g#TF66(eOR^ov=_+AIG;*7&sIC-Qsoq=i8RgZxE++~-S93C@5EHBYDpp~y z>u+%{<4+h%7*c|tc^UZ`ag}8yK8@(MyhO7}$E{L$4@qU)1=&OPvekfQk&yb$dKdGwfCg|~@m)d7 zcW?8)M?3EZos!b0y5mna(tX`sUUItF{oup^-O)GZ_$T_6KH%{=gqdBRi0<=3I-$9(x6PYoF_*T}E@Rz(*kt7`JL7ocPcd5?az4TMGb`6O1 zogSh+gZoH-pc{@p$OzQcz?}@Oek&x8xkPUOl`}~O-`LB{^9EU&Z|U(z~R8Abcik}8j;-E9eM1<hBr#Vk55o0v-zkQpBYA#` zO2iUgr*bEB1Mip85{Kl+styD0@?|PjOez1XdUX_2a7n3u2J|82yL2|XEeg6+BJSU(R3~J^nmE7w#@gr2(P{3yM#BU zZmH@E_gQVH>NNLiZF0Mg>#il$*L##zzM1>6_EJ8K2d~N_BOH?Q&h@Ynk`J9dU}pT0 zu0x=$@uIFSz~p#$_rjPt2~)b`qu>c%-5(5>w>=1RxXD^8NmaiO=QuGiC{_T++*sgq3gVjg*9zZ|J%ti7MaT zJXR80ez3|c!IdM5$4YX_joG&)pDSup%iOA`+psCEU|V+w0FT8A-~9 z!_EMdPoQCwLm2u3G8IY=2sx(7d^^?TP z_*GqtPt5eL*?}3%Os(lh9mu>`8wvlGHNEyC^mdj{T_E^=mblIqw>ryQza5yC^`<^2 z_D}ZA`ZqBR*~c1AMuW4N4JA=qvYQ(`G_!0=o$eeu*AF?*&R91?!{BqtEC1=5MH{~47;^kt~ zsTMUibw)SX@|y zM_w$p7d=AEE&f>?3FDM(Db_*0mIRl~0#}u=OUQ9iB@HEgpp_*TO6LO?m3%IZ1FR^W zTv{KyxpYnG!|qZt>&gmZOfP$v^_L1NU!9#vI#&+KnL)@ZFU@JkG0R=K%Q5`&FS%(bd&P>pk;vs0 zp?Q3Gbp<`IALdkhA2H;6$NWpo) z>~e3R!$>L*5bBJS@-X3D-LCQk5kXEW*Ndk~znA|M+Z*my9F!zg?W+*RdzBokFvNe) zdrUi#VrFXTCSJ&~r`U^k0>3z*E!O|LF4O8%}j9#M>N(-0Od=w#bf@(L2C#JuyMT#}a zPispgfeG7dFG${q2I~$cZ0Eb`=m|rd8+BcY9M-zJCrLBt_4V_T3aOBKzvNA1zj}Uh zH!-HZF=Yn6uKsLFCT@8B&(zTvQNxl{FnV*t(bQJtvxc~|35f0naT*lf*wB>L3+ryM zr+tN*8*Zj=fn08QpH72}tb56vU=FK$%N%76uY1FsZWPupVm7OO*N3t~yL9#0>?tko z`U{>ZjMELXIGq)gh6padcw<93?^GVD;XZ#(*38Dm{L5+c8)1Tc&!kh8&@X;=SZHS(u4`H4?*z)d3YW9IE9sf0i;ZMq}*NKI^>7%wIlG;fT5LA=!*nh-+R*DOe| z;d+~E6Srbf&DumEW^wcN#6i^4=5I;!k+)iACovEYTXrP%!9Ta0O!@^M+Y*z!0k*q| zNZo1K*F>hSx9n}gP}iGYG!;_yy=hHu8oUSA^q0P*Ev5M&{dvQjWlJH&$)*aC%1Z-GvZIJvAkm8#MWHCHxJy}&ws^! z(E3F{W7f5;7LK9kv;l-g)aEvk@DKT2Ta$=R3U0e3dPcY;9U%_Hr%UIHn{g+k+r>Yy zm5fQD;M2U5rr?!r79q(E5EK^#qkS1%# zw@o1FW#8LQkp=Br+L9@OjhEUi)Fm}j+rCp@m)()>plOO$O7V1V?lox*<3Q#k>21c3 zH1GCF%$B5=?cS`|_>1jK_6X6d_I7re;CTCg9Dh%KegenMPU+ao^=C3W(A)>~^o~rP z5A}LS4^K+j+i{J*g4Embm!C@{b}r`MCv5E8Cs>F3+!-#AV4rs~1lKU1I!lG?F%vpv zLJWF&r&ZX53T|)5ZM2?kZ^NzeXccaWby>R|*QpC{|AYr9B0AO+7I&0&AP6s;eLHH2 zy4s?Sd!*C~Qs-iFY_X#=in2Uk+*wHZFT1q!3biR?WY;8GY)V&`4}EfCMHh#zkm$PF z7-vM&yY4Yw@r%31FsWQX_ZH?`wr@9xMP-7!#jIEK&h83!2yH^Qo~@>&bl>J|B=7J3 z#>pdo>zTm0L(uoE%L3aRqEd}oA9P^ zQcn=EHFsT43JI54(4!?UOgq~1hI})5lWZ9!B_T)_MBO58l_gN`2)D|*X>i^z*)`f1 z&I|cJ^aS=u`3}Y~X0+UoL7=PTD8?1qcF(Z?R?0KElvz%0m1~&KNqG5r)&?S2{(^-k zU=*WSy?CBtF?$}aNU@3SgLTLzBB1sivT2A|`%c+d#3}n6*%riQgI)$fW~lDT@=$@@ zhh;YO+_ryYU(t^m5b}+fp6UQO6w52?kmuv}6p`dk+@HKG`A>XL)=$NH0zSQ60VK{$ zDO2PS&nB7`dQxQkLd8q+Xi=SVE;&y?Q6BV=*1<{yrGmp&7Ezb5E-HJd6y|p21?p3} zT=|_AM8m08&~((Dssr><6MrA!v?aa}xVCDBRlkKutc*DqgN>#~%<*)ePd5{8gHdgza2`b`qh9 z{Xn~dIGhF29wUY`XKLe!ee`Qu9%&n`Nt;Q+QcJb9q#8=CR!Mq8mTL#eUZk_y7vy5n zxZXBUiQ`jm6DY~?p|=PW=XlZE4H`7FdauQ?HD=9d@ILu*jfW!Gu|#CYsXX1k=$NGYx>J~u z2{;`OQztp8tHdr9?bF$@?Scs1d)x+|LO&H(&RwWqj{D9o(I3GFu>AEvd=qnqo==!V zf2>a<1kU9WfTD<-#GAj9{VKVYXBGYgfl@=dlfTI40eGKtvfe>cs!i?Zs z47V^s-gd(W%q5P(I2(J2O*9_FHna8_A-MU>X+{bT%J|2~#Z}YC8k2DMXtRt3_$Abh zMkyXlf$5jVJaBqi24XHdZ|Wz-^g1u=SI4fj^y$N5FYC7JQvel;OL_~C)Okz)6Lg}L zahGdG7(9WJ^8XBOhdVCF8F*C8I}j+e{5;1P5ZWp>MI* znI2%gn7>WmF&T_+=6^6Q`XBRr>|FX(^A;?Yw$U7b)le}8Q}iL1pP@H;t;@&I7Cpvw z%wUbiSZRj0F|%|JjZ0!KDU*$nu{9q5JR3l0+hMc<4>tN4KZ7RKoHMNl-K$WWKye)< zA5B?cjK@FMKo;ihGu?w&vv-6S@I4zI|v66xfgu^dD#<4m(eqB2+yEezB%<|B&`J(ls*l8HV_ z|7xj07tm)|4Cu$S0MqG6t4nP<6xr>Pnbt?v1S!$d1Y@Gq~Ntj|?3zJLMSbgA&L=r0wULg2rO-792^Q>iv z)4a{rPDB>xgVl+6&9+&eAcI*>>wBbtIcWWbtYh4?O+enHf3&Sct*37`H$-H)=a|bQ zMD7{pln9`Eyty<&XOo!CktoA3^Q)*OsvgUNsOR11Eq>7oDci!2;WU+7I${sit+(6- zjINq*9Ruhti?Hqj!i)a1fa(QlHWEpv|kLcU4!ir4%)uJ>IG5u(XdDS3HG`0HQclI^>8Yu((VPn#;&jj zBNnk5?2(Am%x*gf!DBe=RD_QH+j2X6w;OG_8otSmundMTa6>Fl!;@{_tTQ7H8YI?3 z5g*lutoTTE58PTA#cQ8w9gIHIe9-zm`fJ^J+qxJ{mE9H;8(u!rCIU<^&a*WGItyZK zH-PY5r0o~*byk^uE2u7Grad5Td1|Ab8D~gNv^Rj^i5Yey_)-$!dGO(EjH3v?nMHS0z(LFuM+dx!VYW>S z{p{A*Mu$FfE3H35``q2O>0w*!DBIDnr-pAfT6l+AZ|jIi>UnQ_92wo-Zl4@Aqxrgh zZ`8SZf*lr}UJbD)$LuJtw<}{ll|tP=)N^0zqo(D}U4 z&Pu3&JHcs&KHw~K4#AeNw>vMvf>_?p|6nOhfqiSp`M$CC)gh+7QTBNuE$-j;O`((Q z{r0F(rx9RJ3CrwVWjBVSWnla3h+Q3v9E&1{wS+i=BG1-;bi_xMRljpIM|)N5a$Jr6 zT{7VK5>r@M;9MDdCa=MHEcQnB4JRJJ%nWko0%xVYaCQT;Qu>_NK`WEaJAZ@Z2|rzv zL4V_eU2Edd9{=1Y?ujVa6$joYob1AYG5jHy7<`sj=c<8h<2JjjkRp!3<$}oAgRZNP z@2sb;570BLm5#%~&-+3hJA$wD1vpj(Yx}$%`$FbB{&m1Y&KWh1+|c~qREIe%TIO=R z4qx1n?pzrDu*L2?6CrKDI0cc68kAESwW&hw{4eTPX_#wLw6tiAYky31{$5v1%&Q!- zOB|b!`P|h4SdpIOasnz+5w7RJg~@pLM4&XW*u4<=HU6!83&>j%>ka@}M6ccWxV6Gg zH!Ut)fOm`I^7#kc)p1{WN8KiHEH~194qU*&y9dDKY@YiO_%%xdQy4eMB=9(6p7a*{ zooQrk2XdClUXp_9Hal`sF`1Ue;(t_fa}ay=9a-Rr+b;q!Bf6`re-j~$B+4VQ0cvgHErJbH| zTqyOC`vm|_^X?0duBUbN^+wL4&+A_pc9V|lr-t;>P5tg5Gh^n!+`uUe@Bq}G#Hbx; z_It#5F!1DbK6Az33g2)hdJyWfmRT}b;5~=w7_^;Q$ow?;;p9fv@}VVO-mLH;zY`*u z)3{TX2D@uK*q#7CW$dYSBj%dUlpIHVGJVcgpy=kllrxw;)`{Y7+&bF{-emk&JA}E2 z7~}A#WRgJ6i3DHrL8l4>B%gO3MATDYE(`Ps<-B`a+*s;ycRgS>wWV)TbTn;pA2ni# z#_GEomPI?;za@lBU)G-x#HKU)F9$g3?tx|g8yVvU5Pr1`pMl2H!HkT7N4_%{R|gk* zKWB~{3_o>^xqeV`@&+?vu*>T?Ghy(K*GQ&nX#9zT=sL|Vxd5Ht`@K_*mTFctOu#JA z7|NKKv)ba^XV@|wFKspMy#9UsF~T8ZGe4SGWu~zb zJCQ)@LPrDi9JS8zE3Sp+=iCmsK@&J1M*pVWb_GWg=p{fl|3@0M=|liI)Dhr*Qh!@beWC;j|WOxC~sl_xV; z;r#}$P8MKb-ibjHT831-ARU&C>M0;??RnRHh!iE;P-!9c%dQvhBa`JfGewjw%F#&} z>KRqHD2`Uqo6p@zf1o|isAb&Ld60$761|*2WUVmZF=|$saWT?|J>1v|o59AKR)d$Y z%_cbz#93lq5Oa|u^31g5aqQ;b5k&3`OL!QA3$(O{ShzCFpWt=e=hmpea^7NVb-*cJ zr1if4C|<5@iQffYzb)=`KktJr$9IT7**4&FnZMaS%KIrl*nY_KTpg5pK!?mZ(!~lk z<5%0;whWKHt3AqGB|TPRU>3Ab$sNwx(&1@NXT9&F#2Yx1yY~o0+|#lJ?DxFWawFZ! zpRM>yzRj;!-Xm-f%vY6QtOAyLA2L&LRc(S53)lCCfv*ciy;jg^;Wf<`z!=eDO-J-I z5nMYV^0lZ*i;CDOdZ~4W6^fVY)`pH3`|B9NU1Et&AA}Pdbw305i@)j*1niV7)C>Ig zNRH{HXHH7+`Wt>=Ns(dP=>q8)4d6^Qy$EMt5f1$kjyZDL7)_RM7O6-=J*~=x>9sB8i@q0T@lH20jx+W7&Buwnm zU}q;ly1h_~6J*_w;LyZjJu#3AiQYYz<5ChcW#K?v;#rwGmYg(2J|$X{bX?Alnw}(( zKa5CEk}6h(?@YR{K!v_fo~Gyt(I)RvjtOo{1}VdWx|1bJNuVKFs_YE7ntWM#Ens58 zsVcIDny{m4ng*1xzVdJP<%D&W-&>~re_eesVQZ!}g4aorVyvjNhFRbRr4dSJW{pleSNc6AK0UU4SA1K>qzaV~mhrW! zh1-%Tui3|1pS7lTIqiH_PVFCZPu8`%9D+7`W&JYT$ZUAM5>3gjYuJWdoBgao3ZItq zZ{r5&tQ^0_9B@QVeB)b?B1h8{4&0pcph*#XBX?}mpP2029nB}BqjMq6Nl}5hiOn}6 z!*lCf7DYgEO)a6}^xQiwiD8Y|r}HZHmAzcqWqPOx3ksx zlq!7orF?ZUE&F-?2Ty;_$buc|xjEp%1xc+r_lwR*&g51Ve-QBUAf+zuguEwZkC?{% z!16n^ru>2mEV(EDTID#xw}OS0r8q)CMAZz;%7UD#64dyDq3T(P*#&>9@vxY}_0=~Z zib6om3Gk-E%$i!z-9kmpLtt^?_1awkK;h5Y->=F#3A1?bGS?v({aSxZ_d1XzO@xO zt1*qW?wmyQ(%LsUZ;)wl$o4Xrhwg*?^N+I6CNoyJ<2$klAGtrLrCx7R+D>?`-L zTPk^1_@^#5zASfBT~@-z3|E~op*zJ`_abq7;+Xn{iM`^=`kdsEf~xv2DKoj}8aAY~ zv;S>CrTQ|;8p>1MwAhBev@?|B4ZqSZkU|@`q#q;HH-@IS;r=%AGG<}9jZGO0%%;Z6 z8JAEW8ee6uLMoa@WfBneO-nN6@YbdynO|YLrnszQ&?`;EEDm&71Da#DtY{!{^p;f( zWX_=JbVDr{pdM_v&Ku#$&(GqiTALb!__X@9jhTWSl|hYzf)6E=n!?j#T3D_e)9?7;cAu1P7!PHFW@d5FH&8kf2Z)z`{R zr6A9>mZX{y_gmFz6XCyFFQy%bZ*CrBT(kUWzQ8zV`RQ3-GS@bLXM!}oEgP7BJ^6VQ zODhd;X=HO6p0#);(yNzvy#4W|FIth@bA?-58+hqC4_cq_Pi4GoTf+aH8qfw3bR>Rj zD;7pcZna(e|0#xan5dZVE8Qwy&v8njVjU|}nk?DHph;ztE?T_wUi>=B73rV&0`j)@ z#ql4A?d>NLP7#3Z$b?S(qIOB*80?ew(!`UPYwhyHc=Vn2p+qO@b^Ft#*{FXyMkaxg z2c%P}Ue+P$bm~5jj;C(3^h>u=Ra%D>LJOBGrKR*q?eC=*=@*;w+9xu~Yc99@FcIZV z?IPC7qBreY*1f#?_Rs9bEOo~QPC)vc4mfvQvbCd>+mz7Uae)^uc6W~C-4!nC+`$*{ zDm(FlSsYwvfgp($-f0w0V4yqS2@`3?uDQaO)MZ_JMPcNsE|5q`3hqi4&m_+2l8T9* zWQJZW!(Hw=FaChN-t|nf8S}L3uY~N$&(D<@(c3#mdRiXSI!6(o+0r|{6Yp7{bS@)d z^;0^-$g`AlIk%U~2h}~7 z@hhXhJBTSy<#vl$r;@Gl(7YVglt*5AP1i>s}-l|(nXL6(rD7+mhV4`U*ppcc6e4y$L!>BSzovaxs5u9y?TV|M zG74VtnLCEOUpaw$inLj|n9C&YQ10S(5WJMW+`sr(C6ad){A+(E55-KhKarn8 zzqKpmNDRdYk>_IPtCQqb?3M1P@^84BHnn0C9^1G;0V8a#`A1PgcwLTEoFjG>dwyG! zDET4Ez2v#sCMBMHDTAi0q!3e~%CppelTuWpsH*svs!g;&F;NAkJrW*MWzkXmy(&5V zIoDrxn*m_gtN&s2vnHz-GB+_&)O(mh`hImd^8)pkn#Ni|8B}L@s?aRz3RW}8q3&Vb zB3@BD*s}<))i>Et!ct`|vcVxz)*x#=T8PYX5S41wG*hVZ0ZQ4Mp_+!q^!!ns!fcRU zSMf0Kn!Hur*v{Gmsz*3{MT2@iep3lueFlHGpj0g+BH!15JfF0=zT|B!jo!dQmZ+CHJ)dZjnzccM9fzjI_)u| zQj<+TMF(j*=uNcEnsfA@)Qy_^jH4bZ*eiyJd{Fa~VJ3xWr!#&Llhr!-8RvMl7Jl40 zPTdJ#=NzHF0BicM%a1z z6D=5C)p1>0guu1{wEf5(^>Mmk$gfpbbvseIvThv=O)0vgE5WSIkJh;{cXDRyeq+-z zXXuyWR;KOMhv00<^?E8kIB~7M6n{zbQ|}OVMrklW8@o}$sl^3!AP#6RTzfIPHLOsF8L3|X81<&CjZh^f&*Mr zb%o&Lu1UHC@LJbsT@|?0V$-=GM|DedpCMlqUHUapU1x_r7A9`pr_Y8TZ}8Gv;D4&k z`Y#Aud97hN5?6fQ5Q$n=5M)R|4dzZU=+L~ZsfI_GdFcm@3ozD{cB2Q1Q(+e~pd5d`p`c>jT=6#r?_|awnc7%AP*)w@B@iW-Z&A;(bmeMjC-@)v$Y$c3gSS-5<2j~NqBLoWVo+X&jM4M^6 z3%KigVY~&n?0Rmz2r#-H8{Y!g*=CrQ0I%tjOyQtH)izUR9H9H8Ne`ahcHi^_eAeTi z&xEAca?D4d$0~tl6!b%BzPSX}Q#9YKgP+d3VSbJHC;N_N3Zf`;yyXCLUmD8-MP5%C zXGui)C*HSoqMpa!w_HY(B_ln_MYAZvIu^4_V70ErNcsNOlbFA}vDPT8FQ?B+!nUwW zt=YJdtTL+%2Vizt?YL5g#d-zzfPTyR6hEIn%^VdQ^xKEm6Vry(= z=0rex1+aW6?>n}>uYC~Sw2ZzMNtp{N7m zjWz%M#vTE!TVU&z% z_Py}QscrTMcw(}|&VqkV6x+)YtoUZT9C1$k$3B2uCc@aCArl3k9g~pX_$tQ&)E1A$ zzXnD2^tT*FxjBa&G3X8KAO{Vd$U-}q=oTi=k%+#<=&^o|dfYe4`a0@z-!SXFD2@Av z^<(rbyT~>_T4kJUI~jvfpR-Y87x#R#)yCdvZ?#>FsQe@ z*n_UmRJ~7woz6-2UAj9wj!W+eOh^dxPv9(GO)} z`>mMrj=hetvA`CLV-H|y!)QkwV5s_=BNLcXanzv$9WJ@-cnEr2Sm&G(SDM%9JPbaZ z{nCj7-^qkH3n1}nf1NVO*Oc4N%TRvOUFUb$KZ#>q^I(j4v}*_Kq4=sR0PZ7#y0GwO z;WC#H{+s{Qm5MmTlex+fVs4j9hH!CAt^wo<_6^r{B!uSVR-5C-*&b?h8lvJ#hMkn;orAdIa9&>uikN zqFLs=8u?icca4j(bZ&I*isrYXU2!p68Yj3?WA4?Caj9a9DSND}e@A5zNsbPC~pZl)B@^};aKEvK{*Y(eWdvk*Nm%~Nu z6y$r8LjDm|W}erk*iLEt|@`u{qXxc}MVPY#Y)S5m(v+5^6~QIpBh4lo)3e zyN@bzt)$PUQCwF^ee|tvGH#IWbbmt6V)*nC;f)M^-+c(3xyl1M5HO4TRk3d7`+-@} zJ6M4Ol!(`??t!7OYpmac|AyRPdk><5m$C~6djciwyMy2Se{-e}Z9UV-@g2hWfjIF) zb*I;IY(qDEmvcUy9p|%wJMZjv?_J!ZX91`DxVW>4Cq>AYrXKlwRIurDM*(`OnN!b0 zcbb2c&B9!?SaL7n5LQcC4q>P5zl8CmiH=bMFuC11fgMHp?tD%&)5f@3NXfJzw-+vp zPIjL|-KT%;I}K+rsC{P0X~y;bwV+_;>HfmlDrQsv=je&7kpsaI4i4tdI3j+F0B- zTTncLaM8}-Ye>s2qA|-$?i>`t?3OWH{qU z-xJU{hO9p%Hk>)FUlHYE;s>Tih?oNd*f1<>;ebAb%z_R66QuSaUIPN>u)Yiy_~)~? z44yx8gbg1Wd-^-OV(6%^jeUKH>7(P!9+G+wagGdKJ9UeLJUjg4drtP*wI^5L=IcTg zy}0SRRo#CypZ-cd6#vK|O)nt4HH}OtC3(oaf;w`pHJnYR4!4!i z-qKdv2S`qu!(qj#=|pETdK%r}@`5KY_IN&{F$}wV4v52e;H1b&3-d*+>g$gF_3+FJLlxU zpzkVFwLR4dzLtRY_HU`)BVZJayi z%_s}k&wLkN!0oo2hE#F?SgwI?@WQPDfYUswwJl~O@3n1dG{T8gTp9^de039O&V1iP|R{yPnD-Ot+4Z^98BEJK|WsZ-h4+;I8b9}>v z4Cg_gG`3gAZ#A2}vO}y)Vo&V|m-et{c7W^H?BgBUvSI9=PD!3G$EPbleGlhPcW>fo z-Y}WJP{&`Zn895x*rRka{tBn6r%{&*O}(3lX`=1DH*t$Z6`Fk1N6`=M47ew0qAi0S z64&VF#L2{Obxh#@SUStFCKvyW+aBYn$L>CMcefrz6h#36=~#DnvS7i0F<>y*7$ZjK zf_0CyTaVq{anwJ*>-xXBUq9FLV!NLEzQ6Ye#9q_!?Cd{mf+Zp*jNND{KaB_FCx>f&7w+YlZ3|DzIPYwcCxqOIw$d;$cbDz)aTPbkKK@uMmuuf1 z`jGLUGT!)!;i!0E+`-USwANo^s4FzOTa4NYtBTI}w{k(An|Y%0m$a4npn8me#ggk! za3-+@HDBofPEOq|@?kEnArVi?SkqXJev?t%ghohs6Ps5-fjnfh4TR?zTEfy>`J-Dd zq%P-&weCo|%@?-TC7Ag=ZBydhg3)c@v!et%+uSk90z~_qGnWOG?Zhaa;6}SS@__J< z_RkTcgi8$jPJI?0GYG?f2uX&{@G(M-;pfSvLbq}Di5T9Wni=NAjL+&8b7;m>b$*jC z`VKqEA6z7Dd)9LbQo$YkHwx(Z|{-@E_tswYLBaF{3UzZMC?g&XY1$GO&JG z(k#j5`kaJhNqYT@IFqEfVb9rhk}D0_F^{E#8lFb0rHdL@o=KG+ZA3<$lHwZcB4edx zjn5)b(qPld)0xuSO(~~ZM6E?DIvPZJ<^7IwQI+y$D^k>|d|UHLWGxz|eI*JOEiR51 z-6@LA3l)zla%Bw>!;8y=Jn?f?D_19xmri2FO3~^!)WWQTWyPfBSr@f#+Z@&dG9 zrqG>0+>+hVorlfOo>P$m&drXixB)zxU0As{eP#B!N^|P^oMBbVlc_nIs~Cxwb3j#> z6OQHNR&S2`mgBDOCxhiYtL}@X=l-Q19)rwXuRj`%%RQ}^pJC^c`>z{Rxj8k%BfDg8 z^5m9hvR8SjmWQ(UdFb}r*`xES>if6s^X^tSvUe&bm7dOyP#i0W&4wvBIWw}e6*tBF z?DzRDet8bO-~s2K+`p9nFaWu?i|0`OlZ#YY#BTZP5(2I}U0H#qR8cvcZbvY(vp91wH$B-T;L%=btQs!kCktiOnCDdzv>ipDAau zCl;(wjHDM9^yRB5kiz2y24YHKLtzDuU-(S94Bf3Me(STV8XiM zMWy58cNgz3jfjgZPA$zpD^#u(h1#bnH;Xp+>u%9$^A{yhWNDe9RERg!WGVgP)^d>Y zyJVZHzG#u8Hovs!AL)Rc#YM@|P|2F2Olg~-rRYKykXut6Dyw8oD}J6ckM>-Zm>WWV zpt>ZFAx#p>Ejf{wfxc0atr&|eEwL&%aAwI{#W$#^ba6fye5>?y{&~>0QbNHR zKwW8Z0YCk0X`tYC+RW0|g_}|ytA`X)lFzAU6&jN+sJ9lrOT4R&RxVBWrY0)k39CvH zd3BB%C2718$IKD{uhnv)M8;p*HnqgbZ>-aod>0(4P?W9{JS_cE3KWu*14;{pzvZgZ zU?wfgR(dbfC)%f;AUet4sNN=O;o#H_;-Ad*nhnx}w5=L#7MKjvJeAERILqeBw79Kh zXR^1Tf0XgE^~if=?Kv~xugV_gD79O2PlG3D&*nA&9a@%rEP$@9k;BrD zY5j6-+79i%^6RO)wO{gPrW`Gwke860T)rW%EUBPu6??mLaM^nHO6QQWjqE+Pl(H1I zt^G=wf^(`tPyF#zJMlH{K(n~`Ll9fmK4-oc_8aOFuyWZwh_RqM9LuP{7Rv$G%c^P zTy`zBuF{(QcgnxI9{L>TBV8Z;uYT>KPjw8^eW4c_Gb)xbHZ&cpNMYR8r&g$$`P!Ei zcUWO1(<*1M2NYbXjAGZy|Ed&oLbJ@3MoyQ=Q2C5|LNKywEZ4Y;oTbx!q0{#Q~#HAEmFBvh+}!*Iu{y+R5my84~)EviyKKQj$EMt>;N0vGDjMAKlK z^#TzN@=0GW3V=QObK*ZiX8i;4F<^)OyI2ee)=Urw)9==-mJCauRK1+M*JZ3;OWx`- zRj(rNaz<6hll|u5)j1Sk^ULa9>h#(<`ah{xbq0M1EvNLoo zU_<>Rfe_@WUnb}S-mE_)oCF+K8;&n@GioF8(tbUG&vf-$VT5rV_}V%`Lo2-Y5i!25 zx^6CML1lPdZ2uZmL7jrEFNW4#paAks^<$~?a&h$ssOPh|^$Z$W^sK&(zEF@`|Ca8{ zpf@aFq_K+|QvR1>Gzged8ll0+`iru=;W?{-w61X^djw%u? zjc!zMWT@GVEu5=}Ta6dE^Wl|^Z@ElZNz-7i394zD#C;8^Yg(GI80>D^lK}*MZa9jG z^6Y8|!Gw8sHtfXw)8C>`!E{^94Kgge&D-F?&1@Lg@C$dn%HOyJU#Oklh#^F%zBJYl z#}poKd`R@=jcuAn0%b33I!T@+ku-71ZJFDe?37sk(x$hR*W4q`%c;5j{rPCxc*gQ( z0j-q!x!KasA9~&VfUY17Xc@{FM>yWHk|DsgwnQ*KV7InFnfuWXTe!?Zl%_?^eB0lj z_po*&fGyWp8E|;ZLzV-EZ+Xx92^F@EWN(64o4z2!JkOebAVWOQo8BRJcuJdRAwAaT z%_mVn!^mbKdR8N}*@?cQU)%fxBP-8pS&uzZN@xLNzbG%ZXmOPaWy>Y}k(`#+VfbHJ zvs*V1ibb8R0AiTH)G8z1&A8U;Ch<6%TVIl=FimY!$hmZG+kVP&DzObf(U3)LnbZNq zTWvK|GGTAqIqGwqr|mgyDHhv4goeeeZJ$Z&Mg7;li@vbGKOawrB8Rr4=yJq_b{72> zd`Y{KF&h@&N{6AnqE;3R=oPmTU}wAsS_@#e?1NjqaISG>>o>%s{1mg5h``=8-ypVOZkj)kCZHd83?xOO zK6Ly^%0vz8m`AcAw;A68gT7|t2cX~AVtfd!^HrM$gXTFdnbv@8=DDUMFtSBw%7x6W zlbZaHb5$cv-=Q4s2=f})wi22-4faSGZdSm>3YxhS5t8%8`~mSWtEOWSvPi7!2t%#y z-=CqPF7nrQ=+QW?y`vZXiY@8*f?+UumbutL{rfZ9u#wb{mME;75@R9Z){yR6R5%H- z$kK$nNr<)t@ayo4EKl)V+yd(#`19EH)|rGUn1j~831R3c>m~vlB{V-v=lj>2U#7GA z^+7t^zq(^U`ZH%;$0|Tx$KZ}c;IURohYU2Tp55U9`KpI^yam(BM_cAYHkYz3VUPz! z(H1H+FP~?rhaHd)v0Q;Yky))H;1Y?^x)!lK^MN%1VGyPsTA8u^asj78xa%V|3xRl$cc2D26LYfVzXj5TIsK{)TZkEm6p=fT))O*P8;evZF!Vd(P6YsOpj^{ zvmOGBZa8Ko0Rq*xt#!bR@|V^}pb#~}HW~D@IMj9&++4u6u_3^`;kFv+h-{DT7PLz0 zwhxCL6uq~vg8ao9F6EZIHtpl8HbfSx-eTY0b4@y*T4+h z+2l8YX}06Z*8&r4z?2=X&o*hw1xvckn#yV)WqX~ruCd=yPkW}<+fS$KbWXbvkfJ$k zHv`A0mfPO|t%d21g&<7cOGgBFVotL|2zF$(IV_NP@k__Eey++H=On0#|I)b$Hlu&^ z%gsgIJfGA~=S*%vlQWp-Y_x#4_3h=T(G^((8PQctMsqza!U>VqD{pC}M0r7HNR>)JX$aNnIV%NJzK(DaIxaYz4FbM8F zuqyfhcLIC})#@g}6De#r7p^5Aa~HrLlMcBX5le}u-JJ+L0qVYu@ZtIHXNdPWvlEwa zF7U#MPPiO+?o3Ir1RgkviL*T`ovK8OwaV#Ff*7KmACl)cVO(>QZ`MwAg{9Cf5#`wd?&MHBX^?}g+a5AR#ysdzKz`7BJ!WVsP3pM|4N~JhZ(*Y-%e|vu zvE-%RrLbDk4(}n@S7MYm5x$>5^n&0}e5K10&j{{wwZ@}@yIke*r-PeZruYU=q3eFa zDcgMagv8N?yY7RDUCqPXA zn%0sx&|^$LlrzlpApKF+9`6u9ytu}@1aLQVuQwbB7tHg*fZe=VUI}O)cdyp~aW5{vEC=(G)94M1h|JD?OOraPFv*L2BAM#TkC(Tvm6` z^Dyy66~Q|tsl0rwHzYYuJ>1JlnN=L+ZA$SKJn`O3h36T4LsLKHSbeM0xLIF(Vd*0! z={`hyX6ARF0x+-NKd%Mwd6#_wzNGiaL{ks zReu`zIJL@;2lFUpelhq8xyi4CtRZ#!O%N*anLh|=AkOtJkNp{Z_I5UH10DrQy zK@=dFnG_TO42)I5O5i;DuwWZ7hBhGR0t%=jgXe&4l-a?1z#ru8!SA4>B$7WW`a>tx ze%f)75G5x#An{#(Oz`g{nmjFdEO~miE{IRA&6*cfq^uNo1f41F zOkMD9>Uu#<@ONr0?_%fTv}GAPI*+AkIBlJ2X+PQfJGtp8tf8IibPMA`r=|ZcsixBp zI8M`bUg*D0s_(o5sGvAIUjeR=?{p0YE+$V0e|IiuI|?ax^6Ec9CpaJI20?$gI7Khv zq3*M}w-FCLvEl|)xfjJ-iaFzBGLhKJek>&lKRFPBHxb4Kexh-N^T9kgnaJ;41incc z)Tso3NZhV*sryMUyNF50$WdK);&aK4?)_)~q)g~8h_+E6-LIpx6noF!h+4{jJ)Bc7 zsXKan;RmSH-ak&5sIK0B!jRMty|m+h(-!tNg+8an^gcLxo0i)*Iph_sukUckaN4In z)R7tVseO5eL%?sGv)c|qPCFADCP2qI@9Snj3tf>#c9_;ZCYOO2ff4w4d|tqhUP3?yA@E(qWx=1|GGb#V5wMlCrSnbdR8mD(Ow!-v zKfCPlP%^Q5LF^-PXE!;zfHJMSD~d#c_RNatA3E+yJ>{dk?$L$Mp|0t9dLoZX>|Gpo zj9TBDczihZR&P#d7j0ax=ctu-u=is~kVftM`^Y_-zVGDWpR}Gn{Nd%`$Ij_(`yd0H zn;Rq$oKvA&1l{FYRuqKZceUhhhYxi#M9m19hmkP=73$4l9K;OtX~>~ixnG6*7v~Ou zQ5|@5a60S(ff;NDA16-iT$lcuSk$Rc=^~BmnwofrMChW&|4q8zbw5^3-qO7-I)cpY z7Da6!U+lgav4b+JXW=O>u|?!TUAz0ApVbu+b(;LE3mZYCEa`fAs-6_}RT1Y`_7im8EhJ7dYD<$B-p%zf-&eO0=+IZJw@ERJ)WlaA~d+I)vI)T2{ZA}WL z(>-hA+v$Ct?6U~Q7|-jN!;Hh;s51u{5^q2DlhNn>bovEzgm34mMCLkQLHJN+vhVE) zJ2Th6FigM<_>Ui_u?G5y$Hc6uet)QpwInd@sFD>DI1Y^#cX%za~fe`bHiEc?O8ri>7~Dk3(6X@7lsYDTMLarmQ*hmP=**LcGnk`p(1 zOB|hH{VV5=-^YLQP|nTA*RoXA^`@IFTJ>hr99DYu*#4ehQuW}9e_5F7#U+_6eRa0t zI(vpbC99XMuSpS>a1PWGxr?}K>IXBh8LJwCl;gZbO<01I_iu9*b||0K(t)(|pSA*E z`GQkzgTal0!Zrcmwct_P*R&+zrgnJBY$2@ueBxJOondYKZ{bISBrYs-h2cqTb!Mz_ zYs}0{sgZZ4Gt+Cl5S5wv(=;VAMl{6~8?i^U$&`0`pD4-{ICWe^GkpmMh^ov>PnPnV zwcL&!{Cw@SjzxTa*{9|jKC|pu^*27R?2{(QFVU`0F6Lj;R^?6+>@FvX?+KhbJRc-H zTT#T8W$vgtN>3Io(2pgTiayn_2+PFDq>x^y5-!V2T(+{4v+z~Nkqep1@e z+y*^6B`5c}{&~_T`Lvp~i4gg&8ezf&Ii%)x+&Q_jcIDX;xxF?qRwBPqn-wFKf2i$@ z&d(cHH|R`l-iEqeQTKA#1xKyc9BRQRYikavV3a|hBQ99ifXpc^I9pkm(^Qb5UYQdp zFcfafxmWN$=XdUi!f**P7pPn-5a-@4I>22c#}%`fNAfn6?4n-H`(1jIWKzJ?xA5hP z^O`b@KYwmn1ZqltY*{Z{kgw7nh91tpp!I>57Yr$10bEnCvpg%ET7WG7m3pfnUl)~f zqQIfkCH+_MTK7KDTsWy>PXecKeT6U{U3j#@8iyY z75%I7!ao*vpsODBU?7uS`t0NKU2O0T4kRt;1yN;Rk!s0k@Z)nT3wYw#ya4F&Ts?$UP!#VEFVY2hLSLVc=G3d5?| zh3_GDb&E0%JWqW~=>-<5e-w=Y?AOdG3Qzl~*;}Mc^=VRy-ldo{K%(Mzh9}2&>ol{TDB-Mk|M@2&_qtpyhw%Vv} z6i-sR)wjihykyN_@iQ4iGflEsJVdikQow(&p-7i-cWa(yg)zUDVPzHcA!QGS~WrxoO$!q3xo~lJ`1sR*1 zZf#LUsC|akm*FJtwurc}@2-4t|I@8<8# zNT`PMo7vl|&kK4ONc{of7wR*;JhO{T*1JTuMB8lYqt z@?MQhl7dL8(Myc*(KRl~Z>YQGU+F=JxOR{<6U?ohD}4Zx)UL^z3RKkY&pHaIu05N@ zOuwZ^(<0qqJ)U-~Us1Gh=TE(gcEQ}B@1uiS3TuWk{;KV(*~@TOfNCgAgu1+@g*BxJ zS@WD_RkYR4VMpbp)t+X*lp<@%oP|Xq~e#?rw9yKd_7k<8-2OHM#w=$)}IqzME+6#EOQ#%)i5*@ z1QRtZ$}~XP4I!c-knDz3(KfKA0WTteS{o#yR^XGm9Fp0yqE1O_^Q^ARCmG!{>pbKg zmIZZR$v4{O)vu?B>Qn2X)csXs>owFbWs&t)X%(ua4P)u23y2K|=-=e48*q$5+3p5C zbG=yGaEWOX{?j;ub&R*VaW$)(bEq+eeS%ri*v^TdZ)v>C>7x8>8pl0EdegL>>n9Fw zipiLUKi)*ofMOe)N;9rtRyTQg8&MCMZt~DbRnr$-_P-RPCBS6TTrKaIZz;{K(^&vgpmjZ~i}+XTG4@hCq7}~0z`kjfvfp5| zt!mB|bZl!Yhk=^cdY~*0)t7mELDP1`q=p?`m7DLScn zNBbGfU$tY}g&1!IvE7CxYe4PqaVv{^4fAoA3lxS3JYQ}y2nkEGmm3U(^OAoJFNu)M z3&t6wzxdybA*B3_Xd{ulmVMt?LM~_48{L%AbdB*DMNBoB#!%i;#+X)6caqSi5UQ5& z!Gxp@$Jdy$Xs2;VQw2?g-DYyqZerG%?$Vc`_nLmwsi-sN33L+@WnMskgU}cr!dLk0 z|F75JvwekzFK~&2X`GK(U~(EG5a(L<7==h?-5jF>wW(5J{Dyi{mTOvzt|%F7O2L7H5Wf}E2%4yk7B_cnV2SJ|skM`?Be~9Tl#O2>-9tU0FOf+wY+RXK4X#c{| z7PA^Yx&CkS6?mYkqGK$Ap{?mSh+I`Vr-O{Vto+i^gc9d3?YN8Hnp2%6f*doK|Cn5V+J)Ru16~ zS!69IZX_MDx{1Za(bn_CfAJTrPe^ldLE9iwBKC@H2B{YF!nU3~4D*L=FL^b3t7R;x z+ke3_3S{)3>-Y-F_xmkl!2?`dEgQjw9a2jY1+ET5we1yTv%dHFH zv(z)Jr{Ud2AFX_ZpkS%hfLtsuw?0MQ$WFISMxmt%wgc!1BB>3G77E_kWSE&ehRuf2 zaHDLuv45~b?E|nJCeXeT`-AScAI62zR@qZ=&6FlPA3uQ%x7Xvbq-}OD-bVbxeuprE zFwp*)a1{TiV;n(@Tj*FuxPaa7*hKh^!CHNQJAr*xC*WdWkF^=l5!h<&0WNagw|)nD zEFrdKAZ*(sTP%1Os;*4ZR3F;ds%Hc$VSUAUX^!MI7za;`R}yI;}Vbezo%=?lvye`2_zb zmSs;%9~Y>xC!`MyRM}6aJq&2<(DXxYx?Pce&+^Xh2V}J??LUD>8*3aJ`uF3GIKZHO z6tANcjL|%IT!Ac6U2=|wTv3j9Zi5mPawixzG54%93sxkHa+=|bB|_(IxFPeM^A}>X zfZOrrk!dx%VC6tZs!RYVg zVeZM8^~7K9l^8s6lzTVEPMGBm#}3DDb3?F)aahOK)P&#!$NSWy!Eug#jy{ zUw(q?HiRHw>>dUkoxRw-7FsEdbH~B9iMrhsm{}O@*1~u2H@j`{=8RSD>xh}0Q1>rH z221amf%wjx>RF8pr7Jy0kt$k*2Z;PZo$cYEQpxWS`ka={R_(o z3iY@53*si_vTrzYBDu#m3Au-K*|!J@CqDIUL28IYd?%4F2)p~;je=mW+mw_Y>~>cs z;e#HxIjPS(*L^P;Vyp6uPMK&-_v}dNY?gYUsqDJFp5nAkRZvfN+RO5Ro}cOJ($C(- zfbGRwz2SgM1zs-|h|0_M>Occ?^1a=l?5tkz5AYJnA>T}Japra3KagdD4j&9s#!OdW3IMYGt|Bw=eCOy2uAf`?vV6FE5>5i1OJ0qZPY-&j8xo zBmS|#Mg9Hr9l&nMH-8jpw@Botfx3h+e;GJ}kM^6vEg3ofTaZL zRzD_np=P~bk!n$q{r0qY0lP;&)^2|LzXgl6tbeff1cP+VVo5tKrZ(8&$FQO zsULy`(EXI}K^>Gr`7_uKwUL(w`(VRK0RP6gE1j+W6>*)NjsDqj?VWo6`uIt{Xn$OM zhy9aZm;f{R{2hs_T1WX`C%&z}5SWovs{b=^I5||;*zfHR(liB1Q_5671AVDSmHC0M zsW0*&!9{5zIW>4NeSCIn5Sd<)wKgaQ{4EXy8vv!5HNh*urGmELYhV`dTIXoshm5VA zD?w?ThR&m)i|jp}G2l_mFP%{EVTQGn30BdwJ5}J%w7kv=$V_TUXCq_}rJ>Ufp_02g zuRuKHKLR_>KJNSxSawimeySj|v#ncmBF7QbTxa%sokX#PC;-a>T;SATE##s1W z_xg%{#HHJ-!Xxi_BzY<5NH0mc1oOqm;LCAJKZkXdFe^Z!dWnGG3F2xJv~w8d1NnGo z4RSpBTh}Hilv2=T1Wlrj>t3Apj4JNVOBqOg(ETBCCv8_xSX?bl*;5${p#9tPF?tVu zN$;MheROhfW`vAx?Cn1Foc^J2WOy87UEjfze=;zA%&&%#qhoyLh;tJ{ zWz22o_8iqR)6RiIEKK>i+#?@h9v8Nq3t#MNX~e?s^*_G~an`L;g(DAp{>l3jmF=A? zX~N9%&ESv0y8R1SC-I4ah14)YXK)muoA@f&htZK@Dq@u~!b()~$(8QITsk{m)0^cM1%m|~xb*@iphFQ=IB z=K@N?5#rP!60@1KzH=3VNc!CAhTJDNc7+2~lto?r(LY7my)v0g`Q4qB&_#{vejc}t z+TL?8<|}PbkNnJ4+R>i7kvD0@y~`t((Vq5VPD$vqd+YoA=VyDLpQxu7^(_oT(r@)8 z9N*9QqfdNnEn|6KYv@|W$-di1cQQ!lhJ~DFRGnLMM2v*lVeRjbD0^r#7^$)|s|KTH z*uRz(qFfHEVlEoyjFiS>LR=vJN$g4YCDtZfKUJIZ2H);GM>tKm6c~qDMp_rBM&ywH z42DBTlkWukfR`xSI+1CG6j9g6g?`;ahs^=-GrFO)XwhKGnZ+by01jO zp~d%vM*L07?CCg#r#XARoqSAR)I0Pta6%&NzONGb9*t>;`8{Fe~&PXJxQEbS(8}^EOi) z^|0m+ypBZlEw|%h5;!VOKb&c{{AEVA1NC%{Px7e z_q@OCUGZ0WVU9UxukmCKV(fh04M$hBfIr?jJ?a;KixV1I#!qwVBhK>W&ikkT=KEbU zPR-;$a_tMB!T;sLoSY|^;nJMgAlT`;5|+j}TH`jiahBJdFn#7sty$G*t|8UBX%Ogyi?DW7_fU)8dbm?40-vT#F% z6WcOTE}^(R8D1s)(Ebi$%M39TfJSD@j04k&nYWFg)D5DU#;3`XMG>Z5iBm**rkwZ` z(FN0+vo7&q^YPd%;?-tp^j&eH*>|Q`EI0p%0*g%@A(7GI%N_KHXz_=Rs?#Zw$sOlU zktKUOeuOs(59;bHBZW(KyE{Gzr|V|7aD|g~Q}nlmb95`pjKb}@w4#|plJ1dwyzp*C ztK?p0N@bk@n)$k_i6ap;=~pwt#EP056p;j47e|~S9aAsC-jWtH2vFyw?;DrFA7+I% zUV?7S%4_-uRF!q1$pMIyO={khc0hKrS((|{6WSs#tHFZ%8L%~v zfKhp~YEPuc<%QO^rfTxob>mV7=9%jfljwQZ>#7nLZ@Ya3Q_&dmZDdtG_f2Ftyyj5Ma@K2hQu*W`Xv7F8w4 zM=O2m@A3u8@5&MKJw@AdFUjFWI%%l9vzRUf=WSF$Glu0kO0rnf6)5!*nmT`n#zJQ2 zU(`+}WEO1DUcl-LMCB6npn?m!`3PF!I9(QOOW~1846#%;McIBG1 zZsmwdY3c#x>dLFhua&2&#wS%O300>O;mZ6fO+viVQuR6>puAi?Ee@r8U%lrnuV{QV zBGy!(%;VXm{TgG>EGW)PHM0uZ^R&&Jf{S@i^*0JWC{}9ag<}-ZVte62g+@_WxLfgW z_QXO!{$}y4LPxVa16(-Y*KDvt}jX|>ZXk@{!0~3UQ|pf*-i*6zF0a4TdP`B zT8&<#idO%Pc&5r#m%uKn&S}O%9;!ZSz~DtCb2Kg>yCke^O8T!7d>J6Ewj{f(HZ`fF zvFvTi;*u-c^~p0z2WYWLOG>9`8xq%*F4I0p*k5{}d}=(p_>-)|kyHFlR^*Ts|0k=n zB&+6T4{lYc4riy;O;EwJ{kpfRyqra)n^Y}1*uurC?wr=#M%DA&K~j6ksNBfR{UxX6 zBYC?@+VcjpOG`r(F$_rQqx>sWhB~R>6Um_V7G5XJ(o9hHpHyfL7Y#=zY3M~9WQeAr z=m-3a=1TEVXtCy3aVhv)+25)GAXM3LRSa-`8B8Tlzg{L$T})G#=}YFPW|wuBz*CfE zFG^~X_1eKD7n1DS*`)&$-)aVm*E=&b!^Ly^b+mYcZM|lbSk=zaq)H|=%-1L+xmA-i z9_c6zUh_&yEMk<6mtIuNC|jL1J$qBx-mEaOsSKKB7U;|BWr-OBwDYq$EUUIY=O(?g zd|vJk>Y(xr`3Dlb{AJ#4!cg5bMGV%VJFMtJSM_`NTaZRwaehAhr_P@L1{SS*UT^?% zxng`l8JJ(Otl%kVXT_nyWxzodz(Qz0e^yjjpFXIfvhY{h_zHt^b?W?zUS(2BczJ;T z)&(i=+G#xJ^9Axu9^Cl&tCQgqHtj;cWSI`enI;fl#3 zU@o>|hp0PiR7IqCeCGFx46%ZLw4zD!2j^bpROwvi%}RMzJbhNx02!1btxC*JCM~MU z%f5$yUS-cYjlEFyCdZGyUp+Nr&JSlqm6%I5 zJ*cvBe>b;Pea?Rw(2BrDqC1u%GDfi-t32)r5-|)ADNCC95gxYhFk^#Ba5er7Q6dYWGP?upeuI zS$|;m)bg`pP^#LxtUBcM+H?JkiSF9hvNV{W?hly;dZKQz><;8$-Tv&A;A3@3*)&jM z9WmPoB-BZ=9|0MnAed42jMu>ZP(P7B zn?14~DOkiH)n68FrcG~{A$&o8)37fyfq1!R>7@_0K}78m^0;qo+3f z7Vky&G|m+(5R%3X;v4Yr#^aJ%u!D_INdh#iQ6$koQX9)8FTvEt7U^tIb-kae^<1p) zrWSiH)w`)VZd?5`+AxcyVG1p)&C+m$zNY?X1C4&WO5f1T$SnKV@SM3t)zvtMd9!eO z<7pOEezB3qo-BLPXkwR3jx^rpOclOt8p|o-U1-|C9m9Fvl*pyB_B0tXnDiUXgLucN zZOzMg4dk-saQ-4G29e3x+W;C%2`XQ6T-%a+&$J zsJe9+vq>QD_x6`(w6?~uia8@&`RuVwN$UmnJ36%W6DNuq-8O^cBtzTwaQ6^xZ82OW zVOAS~`wFLQQ)GluuC!0#^}wIDujS8y4{kre zKLp#@x)UGcThh7NmhB>d!LJ#%hiQ$unBGLlC9LKJIq-`F0P6?+doOF$AB#y&044gSVf< zTz4#O|BgkNVhu}i6PkU7I9z9~+K`QBR*p4z32Vy+8NL&4sldk7L~-F}V;X5sUV^cJ zbTj*$v6IY|3XI< z6DU^mA^LgpVsjE>1yN__FnIm_c|GGUezCcSxdQv${E&&oyy+OoG@}3On8^H&9^J8+ zwGp+jV+RY1j4^&e{pF7|enyS(pEf@0XV$GVjYh$oV@=!8gUyj9U_XlKqNx}YQD-up z#}2JpZyt(m)vhsb!zGoJn&J3yO02mYZ&0Ys7YX6HlRAbFo@e!StRrH?u8u_FFX77$ z35m}?*|}4#%9ZuAn!e!PX=64=8QNAb6YqYQI+bub4l= zrT)H-$?#v!XB`I+xg9$@@W?H#fsO{`i+XFvQ&eg7KFd6GczK8=1~aJCZINS|iqsZA zHYvZ)@(%k`e#kl#mnZveJ%C>-`DlgW+eNdi3c_Il+iD6QuBIQXA!WmYNN z*HCJ8A(;9V)=$Vyx~;aQ$mi--TRf_ySZ))c_Y`<+X7shZeYPhUQqBPTBi78n;@gu;<}g`Sa}_{8sJ{`%8Qa`>SI(VHRtwV>yA%069()Uem5Q(us$tXB=!| z9%ZaUO?*VU;;@i*6002NNMu5(<1R^uuW-C4UBnrj!^uOi7oBs+A=pti2e>}aWix}d zfq<n3%Oi#)tL&-sCe(pfh{Q`Io+_Hl4R!__*rG4Yc~8x{#;iGf|vWiMMBP% zJ$98K%cPTCov6d24A(Q1T{zx77JZQS+`Sonk^91Z60?>w)Q!eyS&42rb{6BDy9rCD zN4vYQ-L!G;d$_rji|(&D9J$;x5oaf9J@awTh?kJ_9TZ z<~yGN<^&ba+kg?lZ09!s#G`X90S>h-bj1Q243}M5AZXKjmm9pIw!rlPe5caro(mCb z54c02Yf4wS(a^3UfLjHF<-c(|VZY=}?l*8%cDrXBVxjbrXBVPFe8v-p+%A0LVI!OP zE>AUTPlns$LFqVmJ&(~t*}J^M(R5~=cMN zd+gXvB$2lSn?zK3>#=17gV%?Bh=1pfOe+h1cArQq4t{X&O%n%SxzD7%@h)()(q*9#y^d zwg9us1>Sq0t!kQYH0XS>!?y=aFO2Y|Lq;j)_>_>Q+*LjsbfYZQ_XgS{x#gb*<6hF}~g9kHs{(8i6&I5lJg2O)Te}=fjyyyRhoX=1MMj+Ga(SaFAJ#ATF zU4Is{B(M*)kFq`xfbnfZpl z)C~lHcthQ}fNz|!ZX*!N+UgzzUS|m1Z$W!#zdaK`WmJJ@Dd;ujgl7kM4|$>|7)&ER z@B~~cg!>*OWGeox2M;-f`{7|gV7O_Xe25Br+BH7@vG<*8T>Sk&4v!!3zH-e^*zCl+ zjwd)fX1O4V@usJ)!ldE4g)UoCUHv`R+vJFvY3{ix!z*>}!zmRNwQfM_;gYZJg4EYV z0=GF0CyjBxN?()<^h``wiK{$2Gxi1c&*L-t_*M@!^ANAhqsr{&RC#=WU{=590U(FD z-t!;eE4|n|6L^KT*1Hi{MS0;p1bj`d^Iin)BT>9iP&Sd_6@cy&3cZEkiTE0CHTWdX z>9v44xIf&B;tam+?s;)~UyyrBT%B*Tdv*Mu&VKjV_^J-Ln~-p}HP~I9@KeWk-$<-) zxaj#K=~9izvmyD9s_mYO$tChF9#YEwQi?~Na!)qL(~}C9zV>`io0$94yD+UJXSX*v zeYsHYg{609U-F7FHfQbhHfLzK2fWuZm$NgyFEW8lhi^!xjj`P~53q*j@a+JQsZ8H7 zKqKX(FB0&RJl_WobgV7%34s;FAYU=iM+o*+1ApQZeHPFGT#08?XJPp@2msqn{6e5xe~* z05#!>UkUKzfB5yl3HTrg-DWWup^NOZ8!Mm`J3#e3U|juJ`UHN)QIp?|sB!XyeAGr4 zh4U8O;U>`6VE1@3NHcJ3?_XFJUhNx(j3cmpN+^N2&%XtDk9fnc&0vxuyO*RUlDfLt zNnrBU?laz%8s75QC_~!(cWL`hPfPpz6bdKoI8b!k*Tf~90clZsnw=Y7;YeY3+*R6t)y=z3~tALZ<4>h->+ zGq0#W`fi83rOoXha{7O?J^d?AkD(>^pFXt@a>k}KltZ94d()=C%wa(3TQEU5N zobpqz_fI-C1SaX6X!s5*>iFKwfZ03utApT6JA2CfaBY`bdKR(Cc1egs?y%3|Fi&zkU!IZlG!||1|oB!4x<-(_Fsb0UwMER|Hqi@(OoEF9P&Iqe}R$YT@*HrA@W9rj$qil z!gEs@FTC|<7c$;@-r zQui`XPyWzyOVC8Y>gzdB>TbhT`Y76B(*aTleQv7*w}>&_yc!k7xNX6}t~2TF;a~x4 zxHSlXW`V7i^lVm7$H|mi?8P1aq;qUg=c7AcG079 zIP$LE$gv#1ZT_Vu&R5%+@C@#18}Z^cZmg~L!aAW?18CVi+ z8f!Z{q_LU`;H+)lLfp=srE9=KxX<+qkY9Kb!&;arK=>De)mc1aC%~C?-*h=+GJm`2 zWh$RfZatQKly7P^B`)XxuWd>Ey6p9BNwJXZgtnR(UpC)7Py}qS>S53;A+-ewT2td2i6D}#O(E&pOpRCKk7&Xkl<>= zFzgT^LAx925KV0ihINVPO_RV+MSnMGf!oAE&BrtJVra82EmN%4%}Y5g{zpeh3eTCX zb0-w#9BP>t_bvz00*Fn{scJD^nU&Ms^5$}1&P)BKXrW}H9v(%OY}YqNawPHk*Ac}M ziec=fCP}{GQ21TZdimt`VWN2z2Fpj$l!^+yTQsvmRi7zZT+v#E5(QN}E&VRKC|@o8 zPn0cJh#jKW3K0K{I93_X28-`jo}f?65m$AQcStT*pTN6vC#ba;X|As3DN>QQMB{^b z@<_En$ilq7x+%c2{Bd>6%uD&l>K>=>%_r8MPCcBju2(0s@~_u_N_;3C+psqwTDq+v zKYon#Qp4>)e-2JNEzqAM*M`JkrG72zGDG@Gdo?k+AJSJ0u;a%Wc-Q3amqeSSfQly5t3i{qACaWsA#up4Vd>-GDFRbgdEx5H6ig4vd=ZS zaYu`1*4&CcUA#{-_eyN>70sy_Off+NzN{{MDedbx7|8OD-GwitRc#v!e@U-4?;!I1XS0eLN`qHMHc0-(NZs{)_# zr7Tk6Nk3OcSI$WFlr;ndZ1}RPN^A0tvbV|~iQmd6Rqjl9RlcJV9{<1cOO>thqsn2G zzvAYXv#Zv}o+{lYnbx_tbVts=ox211#WJ+?f@Dw2zEY%wQ`cIWEBU)hT58N)SN5>< zdM>K)TIt7JOKwuxq`WagMA?qKMBeu@ZvH0L@3QC8Y4q6gw1T~qMHNE})x<3orLs9V zYQ-MTkrd(JO1m7k%mlQ&0%3qd_0xwZ4D1`vwiX)|_%x*<$+0=}~3PD*$ z+DC=C%#x~C+$#H+LQs4x-<_PHoKj9nf+~Z`yAtWj=!&5UawVc-Rs4Ybn4qC+i#%8$ z?%EW%E@-r3VGVYM(e5$6)=#Ls?36a z;7L_Qg(so#Do3FOY^{1xGzBzQ^=DBmAXgPs)SP)t6(yUTF+zowoloqJR?JRXQ29Szrfq!XH(sc1T;&&DRL8lh`8O zY?ii0S*79cR4%Hz%h#74RE^ADUhqz}CYzo+M|CFP%5GAn2^M52Rk;EQ`(M?da2rEf zy;-!D%CD{yCzE>AGjh@i2h|YCDeP6XH+KPAtNu5ajm)o^pZgK6s5z5&8TzFLnWu+b zs>#cr0P3kR=O+NEHBa)J1OC}R@_%KH*UXY0O#iOgCZ(ni)tr}hq)pSnq@PkZYUl+U zQexBu7Q*&OO=iW}9;&gdgw7}GGFERZLhWatX+Ej`&AwHeQ4_=gSAMHW=l)T?uBMpF zD|%hy=S|FCRr8()7yC6cc-OOinyp!jdDAsXSsIo>!{iU6XK5Z}523Wzh6v`8w$(NW zr{VkS{t&*$YU(zL0?wYgNRbz*s-ubb!oSqjhzns+b$;<<$Y9;;oP%IS{iK{C(6Rch zIWK_I>d#6R0!G%SOOi7u)KetNjCu8e)5YmQ_4?ddX_>VaTD@IW+eIr2q=i;)TUz@M zeMZ}}y4my+-SxUNjG+3dbsWYmm9EalBv*W``^j2R?5W?zG89a!Ph}sLIP3G+ox=Wl zEoUZwX?+hTiDRjM&2chw8^&=L(3A}cylDadY**HNqE@?@KOUd2J;yJ?vb3n|A?Q4< zB0CxRLhH=#N1WC^5iEi^8b=F2P;BE`feo^!@sw~ecuZrw@G|gQBTgs;4r$C0S^$$8 ztAxKZS2lKt{>q4M=q1l{BsN?nPYk4wJlcMw;Uk%7IjLPj8KXa?Jx{4@5NJ8nQ1u~g z2la)&V^vpnsd3g(B@`4?;vV*^L<_pLZSPE_W~ZS zTamRNHdl8#D;x4g7n{`$zM}*2M}Y3>DExiES2_tF2^^}c=QjX$Hr3%@J7)y)k#l-e zIsT?2vdKvZZ6`H-B-}UTHZLRMwXd5mla|%gHRqCgD#tea$>_3ox?z<0vJl-aibXm} z2cVvitkKD+eZm}_opy}BPxqFl=PqxVMPJD}+;V^}rWdtj(Ep>(YiVUXCH-#s!Bi9f z&@W_-#ZS>6Vv(_l`c&3Ov`Bpa&!=e zVGidLSZvt9-3qEUoZ^Ck4_p4iJax9T9K+lW{U_=7De*yDly`F!jRqrb(E!!!ly zN8^{*j?o{*U#mjssRUX@ir!3ITkO}rC3*{T4RcBHxmrUo>5F)t0YPSF`wTM57@po> zqwv_*4X>#qncIxxsTf+baVPaTg<{0fI!H{Tl)jvhZ|tDcaj%V!>EEyyjlUTe&;zCg zj1m;vw4d<`dCGK=c@Qzf1Yy$P6HGLw1~%1H$h-z!W~yOLgX}TcSQo%hLn~^G>s%m* zxy~ADk>8yU4Sp1)Lv8qq9%XuDT!XG@4mDm0v`B3-=3=L)DvW-tU0!4wf=dhR&j;bB z6b_n_@anuTrb5DBIY5(xa9g<8^n(cC&uU#k{LbCqdWFPiRkbq6V;SpP8_68%uhwV( zKgDPpLIIE_wk@ah5E9!$sGD$oZ5dQCHnfdFy@wgzR!&=ha*xfRc-nO|Ix{9U5gO54z@-k zx9K8UMaT#B2U}ezQFVLkcXW`#(zYIbvutBqJccM6-X_LQkgjjDW9uYUZU5qSiQ>#F zaRb>=<}iF1k7{P(pRr$=wS)*J+I*XEgMPv?nix$zW(l-@l4C5vq|HRF1wc{|=2-;f zQ8>9pNj`_YU}+_nVWwKHlHZ~pT0T*BA@8@32%Not+CGg^1OM2*l=2ilu6;LkF6@wb z2sGRsZypK_bH}%RgC2CpnCC+qyTIm?u)}Q*GamM|<)XO(E^0VsevAlG_gQ8j29-A~ zCy;Pt-ZF^3klSndj(#X+wXeg_1+?~a*pXT4b`n;`ozgDHEo2q9 zdvOv5r2Sv~0$QeZ3Z6@$TZ8b=Nq4N52$zY+t!P3AzT3(te8o|$a^imMA*+!n!c4T@ zAl^lfv%VosM9r}NB<(@2=onAJA@+4FBkAEt%RBH4_pLxq3FHIt2=}1nCm3xD3K0Hj z=DhZ3h*iI?oeza**S1?=b81ZOZ(+7dmvu25SaHM}hL~Ei%t}Et7KU3Jk)e4vtk;nb za>N~DP{kzak!*T2|f(Ft+N4Nf!WmQ#NR{j?YvGHjym1>g0K#m+WCtB zK$KXO!2O<+RylBw=Y&-PT(ohI|6x{>3AQ;H3Te1)9j1?9ux>N_uG z_S$`;y& zLX)J`whhpixgc9Sj3-9gSn$aLrA-Uh@Tb~tA@*{sZNCsLY>Isuaxar&KZ$In%k7D% zan!GNA__=Jvdd82q_=iGdLFUb?nS2&GVFKJP57Pm|DnI&f*g}E2eHQ-voUZ?m}3b> ziB59_Vg5#yblpwA=bhj6ApN#?LD#i(k9T(0`-~Ni#kQFlwe4lLqnXEy=WU?OS4{w0 z0U)<-lFb3!U%lD(5%^MJwa*7J%2f7X@M_sJI|}S8fY@b_D|tb7FXU&=Ui*6}PY7|$ zh0WkUa2$ix^RSL|_*_nygAbRn!W<2VDGap3jfkT4I36O5)Lo8W$T?)2a~={vqBu7p ztB8l4hmoHNQ=GA=L-;99B8rb&?i8R**j-K;>Jui^*@)hZ=GqUWo%5pXd(+Mba&y{A zFVuc4P2ni81Jk!#7u$={ZyE2{-5Jd0q4uwtTkDz}%QJ6P-*lV@P?SIi0l1(%+Mxor z7neG&fg%gnIeviN=Y4jr1=DhV1@`l2incikkfLmrvkJO3>#)-em2>AiU%*DP=ex$j zD9pcH%V6DfnQK3M4sDDp5>5;>4&dN7$md;Ih;gJDt}?_a!ZVi_=1xRC}l#W+W# zPj2QqgVNjT4>?mZ($p}gG;@08c&8&%Uoq7A1rS|w+O-PstMI<-JTN!E-bDeel$c!A zAie0Ls~@~akmmXccJN08c>X5t1NRbxlZ}Wcu5+Csn8W)0L5Sx!&)RrH`r^?((JAR?1!9 zG6L={_u7otB`@7knOQ{?HwUmtdckc3m~#`|Pk?|9Uuf>@3{ne!OQhP z!C@SUM+i2vT0JVr0_IGQ83Lu#JXawO+62#g=n_h|cL)?f7I`N^Ye;e4Wzd(zE8ab@ z?F6tl493N?y^*kHT!}Xg_85EB^(Kkq%XB?Sg85QigGpz7v94!HMb3xriODNF$nHJK zj@EPTloY5=;1;LOYY209qG1s&$^3>67HEJ;&19OK~1(MzritPjSXK=@XAD zGdK66=QChyPLOvtpi!vt?g#G54)(?ZE3?*k380zWwcZjCkA2Z=0lj7#y@TLj#!Byd za3xLWn+O>~#rT#$PEii{HbA)K3BJP+A8DK~3Oa!}KR{Ze2s?auC?9{$$AMaK4A00! zuutdyo*3h6aKA`A;8VH3C1$(!corlr?6~VWo@8xp@*t8kb>BT@DbpJ49)C)QW`yT! zYC@ITyCiM6yv7@r)>!)6i%&l$%lE3%Ulc&R{TcW?iuXt6%$zRY+)TP?m+v58T=sQe z0)Ud$>LURjbK89-z)S3Zd{&^972+ENjc1sBZ$TOKQ~rq{H*KPS6?g{awtp8mid^dt z1uIE)egODAvCGef>?1tz=Rptwey)Hh@LN6K6C!>8dOjwc^1bssP1xpp;rW)pb8);& z6PI;v_nt}gv`zQolVB|=-m2s|+92;ha;FC8{h5-aTIO4oI#RLP7m?anM)gtBjug-J z)uufw_~N^o4$2?p`!D^sHYOy>vtahaXG5Ptz+GY8{01LUmx z{$9XS=2`!9;6D1D?vX$lt-O0F@Dml%y$Q60a;Q5P1SB8sP5>E6;oSuAXdVtoGNYvXARn95p2as~7rC=56p(|T-A9L1?=Iz8fJV}gn z{5tOm@@WFnHxJiJ%<;lYkMO>f{| z9Afo3M7ra1`5NRJCsXVsBmDLiqIMB~ z`h#Jaq&xm+pjTu{cUoovWp4N5G!8}Fb0)crI;5vD;XM`DJ2ehMwe%)kSw@@Q+j4mV zEv0W*)J&SJ?_k75+CU#Myp}$(&vbDyJ*4mB`9V6We`y$-F7H1ddWt^SPdm4tF{WR8 z_B3Nh|LrrejEnuhL%&qGqY(2PedT))1ufnpiw zW6?^K)K$+tg?{H2(i5;T9t`O?&f~p;^$_OxwjnzLQ>k~b;iTpMT#$ftt9xN)aNsV= z()Lq^^-N5T349lbggVNzo*QwSsoQ&3$2_CbdePAyYIkpEWIt_e-yadvXovd_gac@l zKEj2Ew9Y>Lc`5C6-}A5#`mFw$p_Az+`;VU+MyK?n&Q7K`^~=w!qIdT@LUzzU^#5}@ z6;akDHU1CL(nZrr5O=$JYc3<#+5qL>k!t(d0upMR{ky0X^}|uYEkplys_883U#>b* zD30OwVO#Mc?-V4LVDP?%4id9{S3&0jw4a|joIK1QFd~o@-4~J%QnqwU6BLx5?w+_q z)Tuq2W8PDb_XHH{)bgI*$ZJ$j@5YGn)ZX5z@T1gEz5iXPr5)&7cRr2A>pK*-mDbyL zA#^0|eP7<$cl0rRkI%fKZ|GkV@|Av~|4hheI;lVA^kLi?bCl@~?zDNK{ub_vc~|XQ zT%K8|u;6}MmdGOUGRp^vp0J?3j4vkKw&tdJ?z9mw^C@P#4so7} zbKHQ~Y1^EQKnAVGMaW2?FLEzUCDCc_k|Yn^?%9^Gg)z;O9s7a-^tfWKG1%VY(VdK5 zFF$G`bD>uofnp|lABKNm5`D)mikK2#>4m*am#^#mNY)77Ls_@{pfe0gc+0)EiIkHqfp<1aa0|Pki4xz^P*qPU)=w#orjFCs<+oBR3}Rs` zZMiX&i>2K#MKVUywXIF$U`DZdF@7qOYaydgu+Fu2!tLy_Rv(1N=693;5uAyg;TbYc zX6Lok=Nv;-i*+)d@@>bf9M2+K}wHHJ* z^9c3_mq5HK$Jp>7-VMk0i>tH7JK`_w%v#~7Ie#eYu;WG8#jGUf#83t+zJX>AW}R$U z*jC9p&@ieA$qH_mtX8qo8je>$Sk(=+g;&|rw7{He?9#??zJ@ciX%TxR$Jcz07R@cy z8AywGB>i06`K(h03hEYrys;6k=8H_lkb>-atuUZBJH7Q==AYSyHbNRpFuLtU$}zzn zb8ylk0nA*PuvE}!84?E(Jhkk-;t`Is@MCrecUf*nKNSMoS41g=()M$a0HL{^84)GC z+3vn{S@_*LIy}I}tw%00MTf1)7xer^>MRS5KT5sWl9u&NJ*;I?)_>|@wIu#n^QzHcGt!*!v(0i8tMe$)`oG!ZKAPSHr6S!H9kg3 z#gR?V;JM<5&3zD8&Nf{-XnGD;_bM|d=V}Wi{k&vUi!XJP;EtoYjAD9%(!+sni;3Y-Bej#CgC76(2NsWywLiuN+IxK=rcBP&X>$$_siM zpT(vZd}^9?C8}^i)5)0R!re`R%h19LO`d3GA*AVBlrEoE>aY&xqe_uhXMSdBjLDdf zEDfxWgZO%)S{#jNpd?p2!ld{H2Z&#$VY75TDqiDK< ze-&2p_CiJFO2W9JomENL$wgij7ZoPkR2>O#4lK33hi;a6)D+MU*$?$=z`f#iHD@xO z7AMx!rf)6I(F_gr=d@_TQid1b*Hk1mmQ2vRPK1~2s@;@uuq3P&8o#ClQri%>u_U|p zaqRw*`nt(iE|pxZI}npCn^M@*aa%UNP~0&f8(GM0bI9fvHaGXnHWfau-5@(zG*kIX zmRxkPbdii&R8TNNrYL%v!<7xlPG%PtuPFHfqB$TXLWDvcTQ%MF#k z(sIflRUJ<~QZcfsG-XJ|`l=5}{)$tom5FT?0M*5W&I+cA9p6(SQ`zDkRTx#j+5tIS>cv&#_6~JWmx%T&`u?zybVyIlvj+;oTPMC#H6$`Hwz9EuVmi5E;&=1Mwv!<093 z(^%1!>+|-~M^!5GqbOsl)=JBWAyw*v+c>XkY+(&1R&};02DMJbFM5Mms4~fp!q%xC z$+Qr3^`zq2pxf2kij#mBs-ueQ0mG~DB_lFAt4m8RrDs>SmGILj)z?aNsr2d>C9hKi z>LH~ol9lRtrEy6&R1^48Te)fqpJFQuB&XwvYA64t37|^Oj&9nZl4K8R{!%#v7nSX* zPXb@*!|FN0O@-p>-9mbb6kV)N6@K9#tQLvVIKpbL=nHd`dX@MkZKb+gGMk)Q zGb{Hf;c*QxZxIezW6yhqIj0$upN~4J*^vJgaX}L$jf5#QEU5)LTB9nM38re?1xcVy zn%4z&fcLfI3qEDG)h;jGouR4SRhW@pS9`8dn$}jES!hoktfdtVO&wW7;*{BeH8f6k zAjuqYS7uEm=V$BpngK4R`MPEV_gC!?%`P6limw4?%?QZlO0%RghQ`Gok#E&J;h)cm zuN}@;3NF_!dFOD5`-HaE3bTeMss_Nb|qs*ZCh0HrGiS?l@ zKz&6$n?0iXXni}oRL-e?$5~wx(J-G=Sy0w+f;&6+Tmyv55M64>=HBAhHdOKEa}PHR z@>Hx94Ig-)=|S3~Sw1> zd(mMyqG`N{3|rc?T4aShXgVyO0Iq3D5J!S4n$Thfu(C-Yt^>3*m5ZNcdYcS6%QAjy z`=}X?H`?peSjSs!KQ-3gul-IPu=F*qrp4>8H^$I@X%{u-(5uwf8a<5T$`y@28TZQm zXxhR=6ooe>vWDhQY7($0Ig6V*Sic19rW@?jS<9M!u`4+vo2RqCGG{dJ<6NKtnt9w^ zl%dT}d8>)fb%(OX;lJttSrXhtojB_wCRW$R4@J3k_xW1n3EgM@2l(ffN!goWO)VR< z!B9%eiEIl5)e@Ec1B`7+7i<7ATJVBcU{Oo1Kn&<@E+*}C7BrWVHaiOggnymmVRIWv z(f+OZ1$nb^rfxpDw-KegKmluZ=s46dmASfhs-m2r`@^T`e0CS8;}(SBlkNZ#xTG;3SVvb$m7A58Yl9c&<)0Uyx)*r#x+?% z;1J`XtPBuUe;9w(bx?l{e=LxD@q3(heImZTV~Jiw*kd}UcMz^Nne|_Zz*>P}18G#% zS3?p>Uh$8iki5U-jKM>`UO3(GKMF8!n{gR+h`7RdhRPI#8WGf=S$mBIGz2Hw*g<>F zG#Ve!!|1zAW9UZe2vaCSMxJ02G9!rFOifHRo^9%7jmEw*y=SFiK&=y4YV?xUm8{3e zhpl_rTM(MoNHzhkY{jt6u%^~5_I+qqtBf-P@^@<^CloT?*nok#28~(_+;z=ZiGjEP zMi=Iv&Q-?GSW;`UX*q6Y^G(wwTx*@t#KXr|uQPQJMk$t?z7Xn4C9Nxor-~9=!-@DCGeTc43d{OY#Rl(Ae-+YSnwy}m7)@*hLjMxiFrC~Y-?mt}0*3tApY zZXQW{LilK2Mc;zIY(7R8VDFg|>9;WwGoCRWeZid1IEz|hZe&Q2^UPkxOT>|7 zR`XNl3D^nqe@qgT*gA+B>5gu_h8iA75Av&fOY0jHuxn`B4Aj4EXWNdU`MT?E7|fb_ zYg;YGr{3T85DQfvGS9@#Dl?daagDMpGYNk}YBD$BpXY8jKO`VUA1t$o)b>InnP;nwTK zW3>OQ--$-*td6;)5oA!uHc~Qiup^ArNr>z~k!Rp%ba2TR0{inNfhmT(!$f|DF6sE2 zvJO?>@t%^5w0HcZ6eDhRPNobX{%n5;&GlRfWKkdoplnY>`zz>co5nf`hPI5i?uAd$ zE3D~oy;fn(N5p8hTHVN@RY$B}k;;nBj%BF7N=iGBeW#)^$F^KcLXNh7s10-gGS_ zWD#LqhX~II8@nQj^Kt)n0g0Ef)-D#Y64TnHAihTXy4p!=P>;KMNT-lLx*n0}$SoZ_ zu+ih{V1pYy&JHwK>S^x~gTL61ceFwn7GuXt=u$&$=Uk|(5zu)C2B{s@NrTT)E$(cA zTji?Gr--=H?5-JzUq$Y&qezJ~qzj5#l{>ks45b%O?((C91;@I+pxs$bw#AsE++()G zm?ri-TQYVkbEb`rCD3=+RM@|%B3l=3DfzqY9u7sK*}ma!6ZhE19fZXPN1LJGYD|h4?B@iirU<@9QfY5p=%NFfp=}!WT4HvtZNNuzWr&} z1(2#eu8RsjVw}{a1OL;sy6YK)U+cHcg>F;5v7LqvDzG*Z3|f|GYl2UaRoNcHYYH~n zXCU_HezzY%{4M@vha+La?e=`+H-5R@f+FyO?DtXcITP&P(2=YWj@jr=#&XAY%nBOC zaT0^4Ja;5wddNTr6}ybI#*vFf5#Bfy*cQCe(Te?qYjzCcwqtFM7dSTNrsEUNjQ-#p zfqR8sZfgYW^NMY?fYn}strRfM%eLtOu?~jq0pOW+w0%5~VQjVU25oA(ZBGN;s-xTU z!OZGvyA85N8DxJC@suxhEP`T-Qyr&ae-^xR;9w1TZ4M>;NKS{NAAVQ(pW`#)Y<8-1 zHsUJpyYnFODCckIWn=?u&`ClqWPEWdP&9g^vlVrd+T|QXZ=;-Y{tul+9`BllzC*n3 zT8vphsBmq^#NdlvXEDXNT30&eF4o~fVdr7)yBOG0n5m9=8C~9Yj;R?s?<>b288Yu< z$Fz)(&OaQxGpSatBMGq3bkrdRc$%S(4j`<4iQ_G3mim-)F36y~?>r8UDere;AtOuX zIF*pR!YXG!bWc9o`2*T6AqLofs7UWR0qYd3Z~@?lvdk_C+{7(*H6o_5i(GvO2GipD zf_TqZ;{Fr4jh5|Rg%nX|xPy`ZkgvPbQF}=WHx30S!rdZND*@`(poie8ZV&nxuGIYy zO~zW?pU^tY|C|@nFZ=d6&!mU?b~_KH@AYkSMx^IE!A@$%>W&f4h77;S@4TOh)D3Y> z1k9;#b?pVTt6#d(fpL{|S3c;E3WCc8l9#w$|AKcGMYtD(uSwUsk3r7mZgztqe~W=` z3G|HMzS{`xs^Qn!`8cKX(N3c7b*3tkLiM> zKJZaothDXUn=Wmds{`e_m!8&o)IBLAUJyrZoEc+|rbMpVwWN@{jAd`$j6Z_rnvPj%=`bL>Y@Ue|W4Jo~laE+f10e%DWJ-u=JbvI6x~CcwxX}1<771us09l zwSq3^GX1jXe01XGgv{*kbIB#wU`d@ixjzZsrDX!0L{SK|l#q42BtQJ(f>rGKuc zC0Xj9>8VPl`X_r@ldrpqJr7bcI}drsrH*Zz?cJ4X2=Mc?v?T2|Z+`kj4a)0C*QpkI zKV`%zR`?cX{8xtY9nWMI|LKDO<`+Ekd z@`r$@@(%hlz+_IEUjTl|>hsq@PBV}Bt&k#mum2|GB~9r62;EJM=^g{+Qnq%_fjY<= zyEnjwk`8nqg6$$kbceza1XOndtQueMwIe(c6}E%k|3pC>hjQ z;2WPZz76Bsozl|c^QEQ6Y0G^1X`?jHefG3^Ri5vCdZ?nrKRf+l*}win8Ia;^e|pC6 z!c@N?laY_{>i`oZCjT9PSiIZ+12|l8BS7^T{Lb#bfUkMp?pV-y&c|*lsGS|%T>)Oq z9PBoLA&mI$YhV|BS@%cCBI>7}$q*Q&zh^n5h1}P(3-W>Vpyw!bIq`GPMQ9XpYEKF@ zpAdpfagH+GKz?#YH@`()a@N)$P_JAID`;r1tF15<^TLhKnTp%u3Cp@1ptW0>6v7+d zWJ)4wo9{8cpB&~dN7qu$b%($oP^Wj_gM?CDJ;}f^w8);@=^ts&dP7p@(ogkjk`n3F zeIw#;(tq?t#EKYy^_9nf7`(n0(J;n9|N2M^b7X&7#AN2a{)%uK6Wf3D;x=aUz@+n^ zn0E&DhqbWA4rGQZSvv>v&egHf2RhGovGN99p1H>|T%B-cJo2RDKa&rsa0clnqK-Hf zHB3~UYiI=+9pPdXuELylZxy#-@$TQe*SLPq9p-q#Rz>%@#!S1KMoy6?(d!s z&!yCKH$Wy+K|T8c*J#6g^Z~C(LGQYhceF3P?4%%ic<-b5TDrDxM{GL%Qy(Sf7-Mgr zJNhJp(?2n?kkQ_M;?g_Dzx~wkIOfKF)5Xb5VE>2ngG|Z5!mvDM$H1vjI`jPi`dl_^ z@qqlSf^}h_=ZuYo9{3RQ5joHC#AHAoc8<{DkyXyf8UZTY`F8~t<#Qb^9FER%1^Nsz zx$Zn38GF@}&d9=V@t!1S5ORF0anFgjecw=b$fNvi@O9)*-Lc>ninseSfJsg7fu*CV z-+P{=$Z5&F!HMr^&R#`)8huso_t>@c^uEI}Bk8q$+~_g%Z+*Ry5sWSU<1c9$Y5m8- zmoOClqzi+L2mLMQrOXNaPs3uEy9XwRo@Qna>^m3EEFQ=>3t;vRBz8`Wh$tVuyHx3|h?qpKXkLM7%8XOP&7F*`r=ny>=*Fa{NO-`!8XNLc0Z z<7`Bb*ND=SB)%&6P;!jF5R4-K>@EVVpvZfsrq87Ud%{xEsMmX}i7mAAJ>TOG&<1;V z#Ll4o>@B*BM$|jHy6?}(VEXO8=u5@)?|n7lLl~R;{<+Y=;PwwYPh(u`pB)y% zc;6op`WJIZfAzVY%qjg}&hBO|7&vt15cAkTd-!t$uqP8e>fF&GKcES|c%gwyQ{ zl}3WLy{R~Yc*07|)f3w~R%8oEiJgD4FOc_jt)RZ6Y_x%h+o|*HR?K(WO2@%qBf_4r#ofZtuk68YS?Daz zxbDVtdpN^;CZ9b|y=OqS4N&_HOIn9h2MjBJa(@s$} zy~6a0m&`cb`k3)AbGCUYWgYXA1&M#ldfe{9EN9nt3_&P3h|aN4IOlig-=G98zAGz} z$^FN+DD5t9v#l^Cgh#bcN*c%W*;C>_@V?u-V&7zKbu7HHH4E$rJSwtOj*93pSzgEc z$oj00&OH%n{KZbnrLFukPF46)KGEsExREb$e!mdJuXb%ce}wOHWrV@mw#ND9|JZd} zllc<6MqAswgKgB>YEbOEjl<+8IP)6;MOqH4X}P4CJE3_(b{3b~?B=vZ{^+B zuO+?CvKT1%1$?6M8oDGqxOEr;k=@t&6`CTr)Yb};2&`sc<{RNe^Rx6MVTvUpb+u4s zu_ga0yw^TEak6MZduDvBD6!ob>ku)lL$7QS)mu+rz9qV66-P_OldSzwsp25(@5qbd z6CGP4LdEeNNtYtTqz-X7P+ZYry;z=|s#)2-GCQ=UqkU9%aE+#=EBj21u5MR$a?QQU z4cR=+vXaW|K8+^7PO!Z;UBnb<>rQ7)6E3cw&RQolHteI`6hX91;&<_;#z#1+_+|4} z^!Xf`E*Nn^GOlG6lqEs7dD4!nc6R(&UAMN-Ebj^yJi59#=ifaaH2Wu{obAZxwPSJE{^T z36cWUitP8fW2;ATr{}_}2N-pEV`@fF?0E)FF!5-9N^K)V0k-BE~WN>45*R5sNoO)m5`eNM0x zzHdGpk13kkOp7~Ew5!<=ySXT``PP-7B8YB$%>E*#?%?HfMG74%nkto*V>(i#!tym8 zky2Lq^w!hTobu&O8>AKGM{0o5z|ktj9O;en#^T)tLo3GS&nh@rArh4r6v{7V*$RFs zR=s)Q`LK^+rc zBJWq{#`Tngq{F*X%YpgVx)RDW^9S3PmeZvZ^=ai5(sT81%dOIU)j;`u>HUgD<=+by z%jQ(fEQrt3RO~5e5jiSS3a9ZeROku^IhW)UiWCgJ94{-Ug5+O{og|1NyL2JGO*yaZ z0``CsUcMUTQ(DTMh=R)D6<1)Q%B>ZB5LsoMd@bmCrC3e_hEy8lk24*WR~3shz?B~r zSJGEk%~D8HKUW1Q9;H01I<1_W{7+S)@_5pxDuNQ0G_EQjIZiyNjLxaHg(zckn6{IF zYo7JC5}$L!ctBYu*`R%hh_{oa#RXIri1nQv`VXs_MxCN@rsAHo+a!yXq^#qk;Y$ zj<8ANt8Nl4s61YMOGGP6ul^~zT{K(0K)gOLSiMV}DY~Z)71#6o)Rdgn++}J*j-F|+ z87*PbbT#-~Ir-n3k9iIvSQD537(XchKvkF*nqLKxsOPmo1y2#bYOfUThM%gX6=p#- zwUvd>AuDQaMH@hawGWF@fuh>qMOA>Py17N~Gehcj%C=>M*M-Pp(i7@ZWQ;Uy9YNNX zs@9Ns4fg+O=)BTEQhCa*hZ=R(gf@!iS{7XwTRS}KdmX2CD<7+xT^q;$P!Uqg&yFvi zRNIu@B|Tm17mUq$UHd|CUhq%d2!SLksBV*R6nn4^AS_^*>jMAi)VK9P;&O6&eOZo@ zIKKXs1crOmuqSsL=6M4(_YQhYLuuX?WLSXYGvG}P&-1RqHfx9FuYf$z&dpB&7ixFp zSAvqXm-3$gqqGR=IzY0PF1?Zo(&kI~88mI3v^~A0-oPH=Fw|REUmeDJ6YINuPW?l6 zhWT~FIQE^EhYh;me>#w1yLEp^#u~+9Ha?nVPWTiI@jX z#o`F`hNd=gBT~?GFJ~-bLi5m^OR%oy`8gsexj883IwZI`OfnC=uNf|h1D$N-HrLsQXrU(4sS6Dpvb|NI|4U? z*YZg?6nfeq3w(OxnH2M}8eN5G?78PAtF|_42BVZ-bPhdC- zR_G5i&*dJ~LzzBNy}ppOGyAgM%o6eb(m!OqV#gYWvX3%!hPCWc+D-$AlR}viVEac% zbB&{T(+MYy>v#fOvGEx1Ddwj!DQg#+Xk=yyQQM3KS=SM7jT-)JxZddIhr{ZO&-i)J zR^vDReTdgIB6||}u4zv80q~!OrNn?P+OUEM4CHKLq$|jZlrMxWta+KJV+^(rx{_?Kns&mPVFwtHTKg|@(jkGw0AknO{?fg!FAJV`s1t) z6Nqt|^S~rw7+HHwTIO_mo9QYulgenF{(l^uWl)<7*LK@Jb$6Fj_fmIP>V@KkQYghG z?(RlH2$nzy5D4ypK-^uh_S8?^-MwGl@6R>&Tt znaURWLlj!+VeCcxRDNRQz&llw7#wS+kxdQi2G83oy)ie(mq162g(El|9Q%Nh-Y zt14Lg0JYr`l-eHFU5skBhjg=0WwyuNHRw@>!fqehzdzso8?#J)QW=1;HLX*|VUuer zl>*!-sYGePNhM>HpYVG`w^YmU*9wQJA_xfrq>4y*le1pcPW00f|G(P1tU%Qt(ph?~ zdOoRzx=y{9Jc{(qPx#{quhmk@D*R0KZHgabs((_)q91BzQsYopG`px>$oZN`>Tmc% z4T!b@)}mq3U{IMxLNh^HHC^-xV5`PX-w(R2xlPXiO;pJd`|MX$?TAhGew7R{-!4LYTZO0QmwtnE0djzXPj-mT`L-qmWNb(?qnmX>au2DjtInHakp*I{sntG_tu}|ZMEioO}e1p}gE43@(`#QI4W8n{4wrcYc zv=dkm91~YZzdD;J@`_hSpVbyrWl6tgh<>a!!kkx=APjg;U~J-kU%_( zx@-UuxyaQ9I?;_-Y^WfOgl{ltNP)291}`Zadf9N7q=w|_8o>&OM^_DQa=3JPV4WnE4UxExYVeoem;U*#BA2`sY zAjHB1CI^8JwHcy;_nkWoQNSC{?S|7pi*utP5wy(QYT$xev`Y=$;NuFH;U)NG>uuv) zNKOOFcpAE)T42ON`=zsujWCF0i18kLQt^J%1b9`U#k32tIgf2hK(z3gCN6RdS8Y-t zn>Z`|Y=1seWgdwtp%WeBzeb=)!o`wSUsS&Q3@NV6Qp;o&SxC{7B~7+(R#Iz`48fWc0o@lMtY zr@;6FaME(dv<&dC)@2IyJHK!yCTM0`u}KTkHXb&81SixanU_OGNWYk)AXSpbW)5^; z$ue^n)KS!Eegr$454VhjUC)JD0^rfSYD+NuUiMTA7!l5@v41z_D+)YDUdXZv^ z(DDH_lJvzo7L`nlw=P0;;GbCcp@-rstdZ!;*feVb1ZqF$jSzb1w5!sVtEf1m)y6`fvgdxTaQ4r1zW9I(4&H#)&i(6 z2Vm91g0ml4AHY0pgl#nZpx-~U9Ns_=u^mKAq=IaT2mra?MnLqD4%qUM3keom3o--m z$6!be?zHU@Y7%yV?F;H8W~O}{ih^EYUxMmJ?Xz!2{Xkx@A3?7}&SrZAw1qX@j)6^Q z%(e?*1ln%97WSA@YJUJfOrC204lg7YJ7&UP5H2{jB6i}JIf4*$>~F_qgc0-A0Ym)2 z40SM&E6}qYCCG5p4o3?z2MM&zN~5`IY?ITlt}5Hmv}BjWHaksk_1X@mpVcSYGSXiv z*V#%kc=9VYcjmU{g|=Urx9h^}tFy3GAMN3Q>E$o&M1Z7pv%MY|AhOs8fL(?8_P?Ng zd1a1eAT9rvBN%*?7wUk3TR5*A#gH{DuR{+hU|e4Gx^mOz~0uUXdOA2`|YSvZxm6dsCII2+(RjKQgfJJDC29>g%zN9Pm7LDYJCVCq)a zC;QRVb*_*0U8(b3Z|tF|{w7yDK5exAuDw33O4)3`nSR{wZyA&Ry1C77T1-I@>b1(wWYGGv`UJxCUjm6#sH9 z&DvJvb)Ctw=HGQ?0S*gh`Hy0JIfbqc;6ZMH>jtouGtKo26u_G2o(5tw_PaNOp3$W4 z^WX^TYwP&ZG!aRhq!wo-*DsI_n@n=OWbdv$(a3~ zVbCfx#^1MUcN3kUB!e68ypq)BMmf>RV{G4?(&P$*)Y+4AR7G$NO8L;?b*)b2x0Jdf z($>}AbCJ@V)ofRDda5+Xbv^y3^5)?)5^$3fCD^IXtGr`zPpOfkN%dI>->Az-KWX@I2dCr2{e979oG*-`=RIXCS`WCs#<3X1i2G_cQY-!A8tb=TZ(B zd)E1r#>Yuq{lpCXZMOt-gYegL5z$Q=gR z)Zsm;R|wRLJ-YahRAukfORcmKy_YWL(N6SMMd#D2rntL+|V#eEu!{UjORgTZ|F?=Y#GsR`eszyMJTe7MA* z>Us}c1kwieQlo*iz+QWlhL+PeCUP;&)ORSHPy5}63_C#I($^R|h@RE=;JlAs*grN{ zP4DX85TvHx><>R@qyOqhpS{gk)?apZ5`2^Ou2KSzwEpdYz}2>(dMP5==BW@P?%H>V zwjgVUIr(T&c1)JDu_*AxN~cf|D^{T0u2EBwFKl^!5u15xCi0Wgq~yfqnY z@)Y07R64oTCrWChEbSR_Wg>;p6B|#Z-0SJM6iD6CJN)7nD!TVn^j4~&H#>?*8`awr z@r1UwZ&Y|V4cfOiY&fl<4;*5pJ?fL47tqJ{^#l{>Yx_P25$I?8XP;x!LH+yBmeY&- zubjDtm}6lo+YqxXg`H7|bW3}~ImA2b5b0bb&)Oi;BcI#Ca$lm@_StMV`jBH8m5WJn z{2-jdnw(u|D}JHt3fxARF$&L9-dDqh)J&1a=cSKYewXJtSL=W{{Z%FuY+SFcg=qp-6Z&!$t zR@!^(Jd@_=8y$?K+519*uFzb4qH{5{{=U0s<7i*|N1hR2i*yH6Osq^dqKkr6>jL~5 z%g;J?RTVBmzfgPz_d@?NzXcy|;Bpywzh{|of}k*gNOy=-a}91H>4N1M(ngN6{)7#s zEV0i9p((HJpR$fpp^lsB>#6=;mXuH$*ZDlrM7!s@n6Q<;*5!$NL#Mbm#NMXM-He!P z^f&IC(X$zIJX@oHjB_4L#A62C(-fZ1pm`^UZDMe|nIR7uajZx*r$uDD_G` zpHH2uN@Jg)%GKwoeY7MEfbf^TUMs_NGN$MrAs#aZ40EAz%tGS=&^p#8)6}e${*!)H z`dRj7b4*G*n_|A7w2FPhax&osXRDRm zZR?^cvM<Z*|oMC;bXGce9-uli=(1E;S#lEcaykCm{GFIdt>k3bOmQU~cH@Pq0+Py3BZo%Mg z%9T|GtGn-9CKZG!*TsD;ASe?qRTR`Ib7Nx*T*{t{iwa((2Wf(-0+dOHlqR{r;DMk^lU64FnRMY-nVw~u@e0jo6(O>zM z%k<*ea%udo;$8Cp;szDRb$h+=t%EM{i0x8vXFV?~V>ll32q zq~#X<)1s2{Hsy_?+Hz}~xkz39tbTOSK*da{w&-I;Sjj!%{EDUmy)at3iGNzyE`84d zh^AF`GscNfRUFDh(RW!X0aGllevCa)vaNOlDy+m_7XmL7AFn?L9V2dNSn02>{n}6m zh%epM7?63s6xP_79$#A4_&K$v)Yr5tWn}56rracqWLDG7#FdiW%@Y$ING>-YzT6-o zG&ABw5=pZ=u0o<{{&J~N($_LK)+qVda`@sG@jh{&;iq_~c(mbzcvHzA^?%|c;(z2{ z#bM$DjnU#vah7a}m?o~0M2ltO=fdM+U+DqCzonx}HQdjoF%m3GP^vCFMH5N>DPKzZ zC6QJH;?-q4q&$qh%vPyGjVnJ?)e9$<8)QD{(uyI~v7l!ahpYW9c@?ypOPL=k>S|gt zwpRFR2dD8Xe$<{x9V=Z{%TLxx_to|#L8Q@j6BBnzadl^|tdUCV7zx{@y1I_b$E3Y= zkK-ex&+BK!(aKYcl*X6kDMf7K^N~_-)wg_|_^xb5!O$X-Y*WDzL8UCD zAfLBGMk^f6-XiNQ)X@ditBP_dN2+;3DsgYk5Rw1%u!dUPgZ^4OrsOBGsy0k4hr?=f zOAkR)Yp<3%!PMH{lJ&sex&;yfAfWDu#FJT92Pm7JajA}07Mnh!uB@yi^-i6>>_$pY z-GlO}$+zqNl%G#}T|c3mkodQLX?bhnx|%;ZDdw8mK{+SPvYH<`M+~=WXXo&h$+i1( zUbe5Ty~01$aHy8cZ>uuZcIHl&JgvQvn<^@<{gK<1@2s1i`<0(iw?hz;9b0!SK-aqpH)Fpv>@P|}mo}6N47mQ2iC-}s^ASo*i7u_c_e=S?e1e5oIrPKYO_j%d0h z-kdV82`avve5L`(kyy|TC=SVjXaI4rrt=K~&NbE724(gh`L%{8+09Ku8mDrXR~I(! z;}({C8dG>fO8AW|-i1O}V->GLklASEed1*`-pL7IE1SmUG%+qV9p&$$9&Y024kH1Y zeha4HpEM`uO~bO9b@{{5DJ>)O70A?ElckmbLug zK=aSH&gD4x(XHFEXJj|GhGfUEPPY=W|D&&O?c}CXf?NOa)({nKmvT1ZBir=+>Dc}4 zL-;-Dz3qXy1Z0Ar=TC-P+hu}8*wS{ZKmn;}f1Ni194ViacMdd9zAP^X@JPNduP5tY zd365x%m;Ez{)vola$Y_uW4v6F-;utjO-4mopSRUg6RpqMB-AL2ugyp`YdhLr(Dp0z z?K5e%)^Y8}>5+A|b|n2-)!g=421xR~{U+l}@frCLW=7!%`3h#gV7B}`YcCHg&tS1Q z^W_{?FXOkL_D9j?$#1b`WI)Fv4uJT-4ovn%+>4Gr?kddJ&dJ>S=sBI|d2}S96Uy_# zA9f0I7Qilb%5xyl>7D=Pn87zY-{*V^lRF~Qtw_jS zm+`kFg%oMa=}0G?^k*FDptYxiL2A+c*C8iw=>A{FW3sL-xpNLBtYKs4Im!!JekX~F zEhlug(?*s2*ZGjfDXLV=pijs%EB4Sa{{GoS`lIX{3Or*ut6NddK>GbT21Y-1t>PYY z9;vQtA@ebT(v{BA;y7L1Y$it8^_jC9J->T0rvypp4&c0i|LqRS-T~|APR}lY!n+CC z*C6}5i?|cOTe>^BfuMukPOboWzWYA+HXyV66K{ByMDZRUZC|PQj6dbim-xLlPS-@d zO#icMA7QyNpbJQlw@bQeh-VwoUH6F3s$X``AQ39=cL$Q^lpgEGklRGlx@#!M3buD& zqj+*<-M^_vcoE8ZR4He_avSvvGg=uzJ4@?O0%&EFjY|$ z<_?TlmCbBIk5tK6gOF5}oplPaSM`!r03W9M!@3Xks;98$L5%8k>Qh8dzD|IbAc8a*r6N38RYfOic;x0``l>N4t(m)4ZZDMZMIHr6Z71Z2;Yd zNY|cb42SR4#xVk68?{gd54uasVO)cp)k>Mu!RgvA=5A1#nugluII5j+)k2igJR3eGs~HzJD((EUSvPy4CcLkgzYbrGZ{l2QjFk0A8w zn#l(I4&8s0i`YipH%c{Tt$sS?JL<81Jv9Vbt3OVaB2fBE)EjW19!{G9!|0i`XlS;+ zm{tU-*0<7Z;5%9({H8;zCBb|BiG*t%6J?AXn!CNbXMv%A|JHKbSWrG z{dQd$dZ{c>*N=9VTlK>+Y2qsVM$8}KHGK@0Q*d5S#Z47V)HmXaaz^U=@iVeF>wn-m ztYX7#{BOom!y!Tn^`{}4U?aaZz=?}UBMc%Uf)HZWl!ISyHGJVh2F%8dzR54_2UBL9RLjSR{T=q+O@1q_|6Pl47rx9Ah0Qs*XpIJCey zOAmtnF=yzDVQkHS-T_~x0P4TP-K}WD8U&NusQV(b zaSl4YFwl4y{WEW*U!Q~Lk1~p|L%G|HPArvOV|?v*No_UF#DVA&P5W`Ts1r>W@dwGP zO%!}3kzr~i48#9283-XbjOh+Rg57HRNqCO_W1daiff_KcAwrQ(^Il>FV!#|s^ueE* zQ;0v|!_64dF4%744Df(cVw?i@IK{?cV3m_+TnJfU8EZTNsne2-2F)d-(kA$C=Ox%7v!9u|m;kH}K zaPR#6t!jKAdce|yN25HJJ9s&A!14Ygu1W#_dWL*hvsij-PAg8M4Sc#AaeL89z<)D2lN=%a5&!N5%ciU6Z z`|#iFBs2l1w-=zjSiZdhGZvF=S7SD#i|jtk1yqy$4yFKUvwy_&AqQKTnFFqFD>bv% zrLZD1O|CX;PS#>;msOc1*PpaL1B5BZ+ol0N$oJR|0J%*cZCRj|b&G6bzXeNabAT_F zx7t2|--y53mq5rOmi;7jTw$0U3oXvOVlRWuc#$@1u&F^rH1@Fjx>)H&q-bBBR~QU>`_Z+&kbq3BTN@{p}<@?qs+F z*XKsSe`5c0QxKalAKU^&8fJpK79mBSaIQ=n?5=XIO#SVybS_MN=Pq|{OWSWB;*3r+ z7;2oP^avH+S)cx{!{WS}!EVX+bN&_eZr7Sjb2Y>jk`*R}xUg9-BxY9)fLIdias!78 zH@dz7MFof5b3ii%1ot6ONzNa4GI%~$>}G(O9D=(6@;?^S?S=pt?e1p~3w@erFmxf6 z=9vq{P^Np4jDDDs5C_7So?Suh$N=pn+oaRd(+_86PzDS^+&G<#a$k?0q$ z4Jo(XPhD&M`NXv-#p}NB+LAioe%5s%wc7B@MNK=Py5nk1yW6?ObtfIy^2a?oV{XG? z_tuQg>i6!L%s}Z!H#PHCS)jWmE2HF*`)bx_p~^D|Kq~NgmH>z4P4JuqlK5N?5Hymv z-opohv!{C6K@ZsrJXgVC%#)s1;4*rhcNq8`ZGm?I4;pltj+Z!WYIx4|oc-ou{pw!`LN=|IC@8y^KG9k+eQXdJDg_rv{kRqJTR|qj< zANpz`zp(R>dA6S_8ETyUaK}wlraiZTi+W@KF6}@!I4H$pjMN#BcL-~BzRxD${XATlax$M@SMSVNLcR(WDObYZG>K@1p5L(F_b?(XVw&IMbEMHv9tv}Eh(#L<-M~K z8T9}4f)oBnkLoqYY3TC4X|WCTAAJ{Mni+fhiZ6U)Q2K61MKi4Zvm>rDKJ=dm$1>;j zBf~Z_1N&tmUzv#h{`1e7!v1f;FPL2ebAvuHuMg}C8o~TM5PxnvGR^i>B|xg}^E!T@ z&e+Kfeg(AszO)*B&JkIhg<0(QDEN+D?X1gQj63H7(AVKf?j6LRgig;O>}BG8j{$jt z^u!B*lF9%2CWEF@1is?TtJJ`r1!>o*_8w;PH`?i*Pl-`9MQ`xsoAimjm2n01wBFCL zH2+)diQ&+{_F*qvW9;fvN9|ys`@ToCF{=7khDR`Z`Xj<7Fn;z^Lk5_u`diOindkbi z2RoUW{Xc{Hn4E$6=bkXz1`eK^iCkxMsZhvp+pEsY$Zq?dhFVmty;ItXy5U$<9EQd^ zWP&bCtn&=V>@N==PE+A>TrMI3Z*mJTj|o3KQHWmBWbY*C3_mT`0Ncn9e5W(96shl8 z8jZT4Cos90s_1D?oJ?EQJN0rAjnbPO7eRZ_+Z}tHzOip;Oeh`JcjQ7TUC~F5{6l}& zr-^_v=JdS|pUXJhKPR-8k=cJdq<|srhn;6I?ER&|e8!W0Ly(X;y#LX;M&{~)k!Sxy zYOD?w7OA%Wr&y1gWc|~)8P#apR5=r!VQVbzN58i(&YOz~bByNvhk555N6W)Lay};R z@LR!Tm;yqyI|9KYMtY7zOeC!5DG*4W>b;#ghy2TTGHowK?JG>CQhxQsUC~gHJ=V)7 zs8@Su$Bm|K>CL?Oi^l0y#f+z2?|pgUqJK6qG}1vQ^!*cYj$YY!DeM#7-Ny~BWen+S z4uSc@qTAh{68achJv-vXj7AUSQW-PABf98eUi93H z8Ox-5S6ql?wtF)peatsrQ3Q$k!TTou(zAr|fX^tgJ`uo925N6F3(w z$W$n&!@4@@L-q(O?@CMdCF|SE71=`Dg}AEh0h=)PHFu(|_u^^pDf`H1I~Qp`bphtz zIKV`$<~r;(5udo9>^H+7`#WUDguUk-c5Dd!!wYuAg^uE-I&wocvo5y(&>m%lwO46s z{LeCZISbNmtpCO;k&lqxVBM3WOM=*kIu_-JvW*?TcmbScomI>lPOXARv1Fg=sw4op zBf8xf9#^9pj~v6ps5d}w+@dJ)arqGw`+p*ad~|;JGxK!pAWZ=%6nInRJ$gBa!qBqGyh2KXwlPrdTn-|CI5ci zUS4Ry+4`|8R6%pSjW)4xwcma{r_j;(0GC^o*t{GaDV)+0gGd*OTd~k;(Tuim@MICA zeF30ak{jVZp_0lY#k8Qq~s*jBQl<7fPv zlEBW5acw0ToynIfOA0$hu`MOa&Z`%VC0@mlnEsMyiuEyrg-U6z0V`~f?lEKvE2N86 z7yZv0+s_HL(xCc6;dLpgGDtK?+9$?})>m#SOb`JoRs4@4a}^+aTJdt(PDV#Dt$Gke zQ8Kt@2ytPFpmr7ZiFjRII_iViP%lAjD?Ql2ht`%>Hl~7imi}lO0~{&Y(S*zVECDoq z$`~S%HHW1IOZuA&Qd%Tmnx7^wE}P%7EwQicNDKT*PFYGzRYGJLwdKL(V`UYsOX5$L znOfuGE|%SGWn6-m{c3H9m6dKTbsJHot4nD{Km*+i72VoCK>#KelynxW8^ijOr$FiE<$b`KCB&8Th8qDsr_{>k`PYOYI9-ynTe zCr_=ZoL%=l$Vvj$## zKt+V;s41!9ylAW`w&IlVk8W;7oM?sON(D+3)BLWYKqRcWUZD`(uL!8PQM|fjQ^oIM zbb(j8wD>CjwKTM3cQ#2{D;~|vmi`u-sV^!cONAt1rB_mhFRVIS){D7bb*ua>DoS>! z;vM{>tWs)+_Q;-89tWGN=TzE(SF1y+_5;>bW2?xStZH#pf5xC{qiji9YxN5mAQfCQ zN+wC!S+hiTJ9$;j{_1&2>uWAnM<*Vt!Bq3E#MBg4%M-Y={RLypCuMu{@0gFsw&f4# zEwb|k6T3Ic00p6~cVxVR(z-h`dBNMt6SAv?J4<6_p9=B9q1BTL?Rl%JcNVSWnXA)_ zL~LVqr!a`Iux7YuJjGjcMf8qns&N zDq95^Q+KPZ78Fdf ztonNu?qp*9cj=@gVZ%7-o|wEx31ts-Mc&}|7rd7ysOzy>JR51VePD^=f9>s zuJ;v)$-ah_g*d|B27VC;2WcEC6k%pJ!bCFE@J3DXDa6pm&&AhabDGwdT!6rvVoKzo z+f69(FkncNSR4Wv(PS1&GM!Bi#WyqZn|_wgNvAYVFO5vgZr)OwpIX)&R_aU9HK&z+ zO@7mOkh{V1xbZM|s^wwhZtg^rvN4vMsE%!c(padn?~eJuh`eL zAqOoU+7z7AS9Gum#9t(M-X!3Id9Rw9_#K>GO}BFc73MT|UML}| zWq$r??C%y*K|K0#OJCt)B32U{_kbj&u_aV8c1tygNS~o-fID~gjQ(_f<>}cw18N6 z^N*GS);*1*#lSw-X>EDScC?IYUC23I+tGTSqHA$ecX}xy{#{} zXZioO{^fGHtJ^AwYFo*};}&hcRgfFgshg}qd8 zawk9~il*FX$Q4CTZVh;=;&JXH&-JX&^3{{ox8tlHIu+z(shbyXYB7nv5rwCT>=(|JiDuh9Z2}l zy@0b4_oq9J^B%jpTb5ml=62uZ9!3rA{?5(z_ejm=UW0E_ZsG+%zbeo1$Pk+{m8S%& zl|UOEe_rFO?hbNiOmjiWp0%T)g`ruijl`x%!=sVW?E4k1%zW`CAl&GhUeAed%NHUU_# znv1*SSf-kTi*hVgO~8fN%T)n5oiSV$g+Hb$Q8DqiI_9X<1XS}-)jQ&>TB3R(v91!Y z4kqo8yj2rOwqldIo_wP4h59zxofoeeL^;5pu31m%rVD5B!1r_jmH|9Nvj_dhQLEXD{^HLK=w}Y3<~%0E6rjOl zZm8*+CTv#cEX@Pl=$7%?X*h9Rp7sbnpsH94!|TeYYO4sRO5SMyC3uDNbi;^Y`9j@# zqBl2G7efl z4{;0hI$AuYL4S)@kG`z;PYX~>4I}A?5T6W-=veq0!)AIl?2F+b{XT4%;XGp&biN^- zaTXG$3q&fND|M%k?ao!YL&z%Uc-+YQ6;iwZgoYw%J5*bqionUiHe5z4ZQ3=-l*_8^0n zh+wb`kBE0^mkfVMJ1AksStK4Q!?=rdk6<%`$+`H0#xlxsY@bm@xq@LD2PhTjGsb6> z*QmLsA=LHAnWkyfFvLRBN-7q<#k7s8fSod(roM-g3`^iNr^vAQ|L1f#)=4yM_7irS z;UWT|-Qt&ij8$ASbR#QU?-`z<_B9}lvryNoxyF-dpmdrMff-r)-6+Ep6>l)!#I7mq zHVwl1OTbMVaNGG9Q!uWLD>D)B>o_w^W%y!drO8YfN=KVs`llFZ^H73;EHE!7P9?rF zA0;LcV$3koP~2NHo3s~OX_k@@m^8D7BuDQtUnBiS?Jz$juRtC&{~!k;LM`LTC^*ov zfUJO38J*B3*ASxvTIU*U)Ii0~&&FG@p_a?0p)i*AKht{n?5=E6EWEL;%)~_;Zaiet zB5v2jncgDd(%0sBsF9MZ=2NJ=k||~!dSy|mS%$95zihsN*^!%O8H{P;mG}w&mh1_Z zXl#w&rb@)k@$b(!;8--Wr5E>xBC~wNpCbRyItAZE1X(xy-z|o9KOqp;WDO#)u>k88 zf(LWJiX)Ck@3At8$5Dr^c|;8IytTsL_nmH45bwgJ<^=FtSF%5!`!fQ3-4$$3oEsjPQ>D}2FnvfbIBX)4CDbJ z*1892DL7FUbbR(}>mBrcHrdbigP0d>OE3<9f9p}~W-7^+fXyM_ zwPCR@{PSBO?hs+X)`G*}xi%BdgbTL)iyw_$Wcz?WgIQ=Fg~y@S+o$0>Q2XtR@h|=T ztvd*d5V@9jpd&7qi!hCb2VS6#79BAxk^jrr6w;Hw8A;w)sX4wt^jPCiieE_q2o-F{-;GS+f z0vuu+XG;Sz^yRh!(0paG%>?R_3vKVgVSa!6Lh#2riv0|PEn8qmK<8CVwO2q}N~8Up zf3N6`{R_-isB$cUpUty7j>G$N2RXoqGdzStgy_qj>QEzhv)(%%AS)T)oP$x5=<}R& zP*GH*a~rCH{K6T8`bmO1)6n~g8=ZJG9RJOkk8Z)aoek(OSeMg+*@n689Kb}Q-#H&+ z2t84fylhD_mT2iH}!IUYfFO9ne9Lwv=B&OOk`qBLhZ^l?7gSpZAP?RM&6 zPjfaoU%?Zy2V7&}K6aZc0I`ADMXlYDD%DKe;rh ziG(hf7j+iTay>%va17UX)NO2$dnkGgrq(?Hy#sA>FGQ!HemZJ1XSo%Qip&x2c1K>u zD|dtclU=s^j-E`7f#Ud;6{Nc0T$S~#L*k4C5L%L)bl}|jN~Z$YT7AO#2y{St!Zj5% zAQ8I`f-jeBb)|t{3&*(fAcTV1e!@Ro5aoIV<>U;w$HAs@VeWM>JSWV3684l8y}bfg>Izn!Y|O7|CMPx?FiY3Jt*gyDm0e&#rp+jSzd zu5*S9nsuz@p{qRWNyAc?3xKP3yS@M?Nqz3cz=pCV?o*&WCH~VfkV}~FmVm*PS%A=ZI?{ zt;uu1WlqcU>~vjAdt@(h{YXzUo^UTo|D#^*KATb8iFczix3>nnW&Z18k-Il5rRJ#n zXV%}!Q=a7jVOfGiB=MF5 z*B5qpoj`5gFYimxid>{`97vQi*S8itlsm+C9DI>8#+L*(vbOoD{v1Y$PY8*pPxQ4y zTB#DB7do7B#rFVun7rQi35p;M>lp=A5r_B8hYcmn?AZhh#Bb`^1Ixml={W@}$I{R^ zzc&zp{@_^Jsm6plpp6WS*YR(q8jEm-msH?FoFDV|;iFtNTmS*#PG+EqV$Uk_L6Xt) z99KpD*DFC0C_djYSR1v~_W-<;mfn++^^-oa=W+Tcy0|wqbv|QuuQCb6DC}EsWd!48 zUsk-HxxY_+sh*kLKkQ-$)7-y5`YZEiKkC9c*4F;^NDC{Y|7ir2B^a0*zJjG1*dO|m z^>iRDQvC#v6g0`T~+nwq}wA3-E^EM{Hak)`|DRgKm z8?m#UYf2#4tIqDc&p4wifjiAVNt?%*PI%|OO}a&z?J33WBk%TJKrNyi@r{PXQ8)SO zKyPV-dUj?hX-z%KbQS$rZ$Qc$x~;b$=@jE=@2`Yg3~ArF_+rMpKH()Ib5GxciyZ%K zVnK8-v#~$o!YbzD{+viLYhk}NBA6A}|1o?R3ox)C)X6FxI2EE|c?MwTt*p-jCBawO zlLj=q{=uM7LvH9A{^ z`|9eZHxfp>q5k>HCeJpkopizT1=&Ofc;BN%ag7cT8%H1}0rJjHn5_b57_xvYO))Ej0@e^_KZQ`FCn zn87slcZYeIFZv&c=CGy@Obj8gjt=ZP&t`!J5`rZx&Hy>6h1E1rb?zSeg6)NRKRVhz zSn(U(VxQGC8MDWJuJRk^w!Ock27BHSnD-X@%5gut7gy<&(o67}u58k30@9s~MH1Pb z{m65qT<>Hko7~`)gEmo0d=XhwsSw{l`Wo7~p0z178nx$pqW`YGH!a~1{bH{negwU# zZ(Qs<`rp2YnBR=!eS+vS3{syps+OVY`w{sM<46Dc@T<(#{V`!V{x?F0USQ_+3qyjL zzJA5|E3DD|SA&VHCH-H5_^kB<0q5j|Ov79CX9Ct>=>9<{Hau-P=coN!t4|RR8QV+$ z5WS{^!er7u)7zXAq&{;AYb+UPVNf`f}kHz$fNA@K6Atvc0|wgux>V@=S--SUDE>#X<^^)DLHTFOzDvYzvRs5c@jLD z`c=iz+@gM0olsAujZ#IonP?kTIkj(T2-UlCHSIq&L9~{ht_c)uq4#MXaNaY5wXO6l z##>!IDTgW5YjFEmQHJ}daP~aYFxUXwYn}}jaiIQ-$zsk=%j*nBHqwesTbe5mvzi& zC}Dd#Vk>E!X&qki5DumjR4|V7S8<&8COcm7f|Zi}q{~L7bMf6aVgPTs@(%V0?}mCZ zQk%olY=qJI%d~sI48B~q4xq_ht-F=EFqf<+r{<&ohLO3E)?e(O`a%8-YxTl$U6Uq z&d~^6{tR<+_`94t%~y0!a(vBWbb5adRfux#HP3Bc!ynWfRK1PAp;;m^@X;;Himvf* zv<&2SxfUZN$Q;mUyImk;^m~GF10m& zM$vQ4@Jly@<1{;BCBhXN=tYJwP}3O06{cw(L`#G@+Nl@R!ZvL{)Z6^$wXgK=@^94& z^!M_w)snk?`44LgS_|@j*BWb$1^?6yskl-QUYAu&Ehwq`oS$0orC!SWSs32{WG^h# zHZJ$~SZ-{ZK++ajn&;s+2t!)}(eH&{ThkD~M5HzvY=`J)dn&lHI77YyxTDx0znwL# zWN63f^p7Qh9gS&2OHiHjQi4jVIsr*dC4HSuiA%*pI$tMT7cWulyDShNR-oe}#Yu{W zxZ~n%#qCQW;Gpiq1ML z&Bg8Gi{ILHoz+?QS@(8UXWg4lUAnoco6e@YyG1}z1XNUP0l}cV!CH5BcfP#;-2Zc3 z&vOBv`+I-BeUwLVW(leKG#XtprUr+=m&j|Yp*HF4x>E2uDXAU|a7&*xtjv+imNaOx z__CzNxfvxgNh9~tJ6TubgS2?rr>4ahJ@Sc7@Cy+6_9k=68hLutx8%NZs%pvkck(h- z`ngYXi>mxwKlxqNmBgv?pQ^8C4@*bM{=WLdV9BfBoXC^gF0=l_xZlv}tnWrs_#45v(4wt?c4{VDrSoGZUregk_| z{!;N1b+Z&!ISnzj^ljBLXkJ;Wate5PnM?TwIJkUBH9qH0`JU=`*`vy_HHn!i<+U}g zbXSDx55Bai{8#OP)OU*MwFMU&6kBWWU4SXh)Qw9?RbcD(BYzy^g|4pQe1RfR zcki65Y;DB-daZ0_QHHIfY*A5yiC(s~h^)I@cCx6gF|`a@^jR5KR#3dDw7yJVOe=0K zyI*`;6jwe%@?Rdje78i)9#@`Ul1ZOj{#ZJjj8JTlJ|)ail*>ZcDHXHiKTxMD6lGEH z>y^XH2SP!Wkn$Jc*h-&52#l}%T`@8@rD|0LF}tlQv*KmeoGMo3stj>eLnSVKZ`I{W z@1?<2f2xM1URO@2+J4caTwaB}5LE82YDl@EJYRJ)`GXRt9F)AEa+oOB-dq_a+GcO8 z>@QkpnO`|g1ZWjkZWd`(dn?b1{?r_8}e(b#uv)C z`>M7U{$_5gqKnnkva0T)1kyp}!s5mFO-in0Bqpc2SIH9OlWMGV7d)@}vFu+csAi4q zHyBa_lp}$h8m0VG?xUI;r5QPgYJQcfvRt*ZOFv~IYIl_F$XH*SQpQj3UyCdArhTa` zE_D?d6Nxw^hI4ztW7X z8I!-OZc)vK{IZIsn#BBXvKuvc!LA~HjZ{Dr+G|XLKweVKZQ*owLhT5lfUd1QB3es1 zTPqR0BOb2(Sm4E>>kb!6(9i3vVhfU2zpTg&N7ZwRtDv+9;a>_assAOZ1Ac8-TQVDv z)(~HU$hqGDEwN|w8;Yb+S+NZkX>{hChRae`#^{FUQbYRq#@^EBm*zB1l#NT<+_*}% zI~7;I2{GrUIhC)7q7Ts_)e;j#J>z0CMaJ*#+X`V#e~;+RWGP3xI+T~SS&m?K<6n$|Ff zIF2=)WTqPbX(BSabPJmrS$i4*O?O$2>c3S{>{aEds+H^_>A$Mu>~CVS3e7nrT&K$C z@bfmQG@K`Fk;=`T#8|5O#x12zP|xE{A+1)Y@m%;KwJlGJU8|YJ7ow+W(D_2-QjJBh z10K`dPjCaOYhEWzfy`|_EA)Ys%~;V0;OS<$=pbNPbE`;@^Srr3)SZ2+`LXCv*8S#R z1@kgLXh#(s%N(MeTacHrQL~b2a_KeesdX-cW(l?0$@{i^!TGaWJoQf7}ep|M>r91z5mbc}NU_w?e?GsXs z`;7KENgA2=NChs6u0OetS*%-5j%YA+XUKol%XAzHuJ(t{O#NTwIo(?-zVuMbWa@WG zW6Lhu#X@ikh}JFOx8&33^S-y}=va0|%VoNc!EE`+h@w`u&SJ30gIaeo-V*4oSY|Qq zY-^B(!(_BgVjn<>+m5k6A^x)m#Xdkms!d&iZ6bK3`UAAvTt&*jYl zu4&)Q+Y8v*zMqH9JHyA_Uak63i1gc%lNtB)XV z``Y@0I8l?;wumUL-`{qIG%wOW%OI)CRBbx)2I-`>hh&5Jar;2ZDpCLTC6sbLxcv}y z5O-F4E;W@kqMbyor_XO!(gst=?Oqy$G^G70&4BOJ&!lH#d-RtW|6%&-)r|M3Z2cRi z2=Ux7jkN#{HLPcygDo_~vkD-u4e6{q;5Gx9JrkrhNZ3b!27{Un280Ywc6sho!wvS0 z+{x`%u;V=R_N&-Ykr}`a^NeYKgN0kw`f=Eg?cep=ahPV59*7^_kfJZg%a!-_mkBG% z9~cG^?6PBqRmAMUCyp)YFd?%wBBI87|kNVlTmNJ8k zGDcG_5qB5?6g7T>v5tBcd(QZlHU=Fqt)S^p2TbYoLx_7OGQ9vUFv;j0uwy12V>ooK zDaeR}{B63;$Oq3hy!sInxG@7ups^1ykVVe~{OtWyiVcZ;kx8*xd!R@e4#sAIvW!;XaGLo%{_$So2 zRuW-1*={W%NQo_09pMGOBf|NY;O5!-6a5&eZ6gVQUS&%mT|s`fp~xc;Z8i=$9!{|- z$ptXH%|Y&l=Gm^1KSLC@N0dcigY7#d5%j@w8y4&9Ww{PJ;Qej!!q#~oSsud*9h0q5 z@QFs6bq&0#+M-=KPz<=Q5qc+yzgZuE>IjtzpYE*N8z zV3y@ywgoXwylb|1*u|WI_9@s>CfL3aH;CTfeg>CLxo#)moTTgaLi{Mgd%Ff7kKbeO zz!zaPj=qGom_3dqgnIN)#}2|nWQQYxI2lpu01*@65(kGUht)euiEgOHp(4J8+;CV) z^C81+a7d=_oDBj=^qsX`gzWXj*a#8#t;$vtdGeOpu0nM!_w0jUhg9F~8(@#?O6=)y zT$Lq~=O15w(C$MhW$W#KkQ<7TjwMJ>VL!)dRE!|#V4$w%bvd-?IPPG_9dv*NcSd3U zV~ln#z{sgjo%=CA$d8>F*u$iOPCT}dkl-x9KEk=2D%?`+LFYAGD`uqg8SWdZ!}$Zh z7AbR$!2=`y`FVIFTJX#XtG{Wx| z-gZ7mWC)e6(THFCdecd<}Z##>h%>J`o7@}XlXPS;CxE9rTJ>JKCC zbWg*a$2YnE#b|LG+zJ1`#c*H3?m+9^NGuV>aOYtyNQ%1_`wLO%ZjW4K)VLkERG8I$ z1t)@jb+Q0Y{L`Hbz-9kbCmPV^|H~-^j&MG6wgUy`T<1g3yoi5hB*>{b>DmN7-!RN| z3H+yeol6K2D1t64bb;LLdINQq402C`9Ttn+J7D)k$?hC@YJP@W4FAllbXyVWoXPG- zh(}DdX8>{!o$Hy6R8l#f9jK9HwI>O6jx^eXLNyVv9s#;Pevqdb9T&;Z`_arue*P9Z zj6U!Aj2VSW^p3zBK?1zccSa6Qbe za-DDw0xUAWa<2dw+BEJ&;Bn0hHw*Z&p~Bq`Vpd;uKLt;(0C+}&b*1T^{~(7;T09w$ z%SC%VB4}#CB##aHOfc8;3I@wd_Kt$x<6QBsg2%FQy~p5sMzj}(7)^_fuzffM=50oF zkgj<{$Z^Dd-lxb^e7A1^vK1%rO+|jfp7E_fEx;`I?L}pvm-x=3>QMjrkf^7~Q$8Ac zC<5v$KyQcFdj858;ACZ(X88+pE#(XSPC$YT=YI=$DVY+O3`7=w4Qv5^67>%x zgCP040#wjbo;6SnPT-sigunsT-U!=Y%s3bv2;tEn!G)0blsmz#&~4A?b6GVb4C4NQjJ5VXKP=w$II2PIFPtQ0K;QNy@ zb_KZp*o@@?x<4(0?0)FyWDd9T{jHg$dZ7Pt))uWV(l2|fsWh-98(#Y|kdZU8swhyH zQ&V0MaOQ54_X@np^-3hc@qnXZSa1WtBccTpf&26QK_aj{Z(pz+w3PEa=mnLrx`U5E zKNvSceZgnx{X?_B7HU@LU&s*h{m@a!X;OA58&XGH5n@7q68eRTp{sCLLnN zHe+6d?n6If28BMu7NZx0{|7sbN(`i=9|?2^&ZO@Mgae1umj=9nP`kPW)D;j5Aw516;p!7oMm!&@KKJsWI`w^cb)iC zXjyJ!!QfCFV6os(2o5OC3x>qNVceXM2}od{4&4CWU?zvYg4WZy;lDt|)bHVCpeK~< zaOBF7^gEmc#uKe!EVzrn5Az@c@oC|5$R1p3xD~>}BEmsP7e*L<03C&H4ZnkKLA^um z@~92}qUt;!bQJU;@8N(Jr=vG} zu?il#)%#p>8k6P&2<~Ec`^T_<;&%G&)Gzqs0W?8N00q}!#u914*YNiweyA9-oQw_s z3oubmhdZ(hr~^9=XNahZ4o8}wHnnrX#d$PtCoQ>-_Pz7oc^G|r*Mh{;bXHgPnUu(< zP@isL4DWh*Y6RoI?inYrk*!4h@f8epH!c1X<7&4iPRH!ieLGgcT-G!2Xang;i1eKUPpM_l= zDQixp3US!LWWqkYFwlc8C)5X-a2(MT+7!v3>qCzK3FN9UE_*ZORLB1^wo?0bVAIf4 zYRA(Hcd0)*cPC$`}a(Zu4c~e*?i zF=IkEWyDvi>(@fXW6bv z^@O2zdckZ0%JCO(0I`?DMRyS8P8n$r>9|XX1&|lHNyvZ5A0pqnyC_v&DNskD7oM4Lm=Pb& zJ5|6Cg>@%KGhT$l$1gJvhA$seGlk*j@hoP0$K*IT^G(O*SPE-)$C;yYR%{10#==VO zsEK|;nX6YCBX=$OEPVxKi=L)ViP(p2)nZD6VSZ@_b(Eo9e2-daMDw4~`kKbEs%Zq% zW$FU@6tju2pYFG4(O(&Os~<6vx!iUcLSSCE-v@4Ip&ZVfZLD9;vdj!N&UN%s5Bs+3 zX=*HIl^b$l0*B_lkvxbK@GLt&I>Pqz6Hjv2c%GhVjj;WR2}`(g@1axoxq5HuNj~?M z_wk8iyn()<$M^8o`IaAx=Vkbg#Aor~K4u(($MdyE-V2#F!<51-)=o8AnHAav%^ggO zHl}VJ^Mh8dSioAZ`%6;CD$%tGTi8=t=v*-y+q#G`p8d7;CwV!C)OH`&#a+_=81;7kpbZ zy_Er+CK9wkbEu*p?NhVH6eP84)1MVo=y#=EE_k4?xOlg4j{eVuRfP$L#N@(4qCt@~ zq)=sebgsSdk#SlgT0GWx`s_jR3Zv-EI`I*sC1ImD%lP#4UNPGgbt*}$HZ4C{AiP^M z!E#A>x!P_yCG4zjYuhh;P~EATBI;H1zv{!H`85Yizl+Y*=!>U`l(oBr0}J}re&!Yz zq}R1Y{Q0K(^OU&4g$=6+#|vv3=U~j@^-VjF7;!*#3`QtArOp7Gi>_&!s9f=}wzSAmu}X2F=zRsFq^Nj7#kT@hae5`1KeO0WwSc`>GNbA#?S%xa6p@}v zZd9k@_mrHe$;JGyeJY7xnx|%-=ap8e zTh2*Jt?K)U>eBm~p=X~+U&<3~C#6s16K&DbyYfNCmC|?ex!TjRLGq*ZU9x#{PGybk zp!~Y*gA82ykNCB$yp%4W$nKYo=GMxWlv$Vu<&<&|^{D)s;vZst>E?=FxP(%52_;|Ie8mN69lc1=Dmzd9SrH|l9`Wa2l)u1=DxQ>$LS3m$DW8alsSGJ5 zKwnp_QhWgis>Brz;PtAG%0s!YlmjXaIa`%mtL9|YDKo1mng1wRRsQsA%39^XO9Ev` zxjF5e^0g9?8du#*S$#3CdaUxwg>%)5tNWzDs}EE!O0KKCTHtg{jZBeaVr6Fm+d{2; zQQ&CnQ#H77fJ$4npm2YUscL^AU$M9jws=6V*%C#tm6m4M| zl<`GBXw#LlVkya|d@DJNZ>^3lS%Z02ZIT{DovB$XJC5jIBbD!q`18M&&IZ4){jbyn z8dVD|TLDO|tthL=>8QP2J}f(?_DlKJtiE+4%W)Zox_`>8>7=^-ie8rxb;*i(Y1lfH z;&3Xbj;+97EUi;0v=_Q+a`LY_-qrx}HI7#`nfdj$s2WE8$96?conWg5QWF;N>hfzo z2p&}aRXa|&T>f9}Y9XrVXYDbePqe%iBpRF-u8l<6+2PuN=q_VH-OvJT#GfBqxR7Y6 zt1A2v@#psu+b}2V(~GVnf7V|wz6pQQuvy}Perv#&z#tPE+DhJoavMHMlL7Y|CrLYU z6C2mahUE-zjFs)m@;8EI=uB}VTV{`39+%6$q;nfvwUbx zotpX}ueVcG@8SNor`JE{9Wcyn7{Zfjhcqnb{cPCMa5C?7)s+Tpo~~?ELpgt_W-=UW98+3xpxu_DBV&1bwIJ zX@LUiR2?Xkz^|#Q#F?JgSZ_9u4TH&MH2dV^-6OdD%>L zRdFB-ueKNe&Sa{)B}+33)K4U5)9ciKB%Dk4n%=U6uFR%SEUYV|=?x3vP^pHqyhc)l z^Uv3jRj1j!#-NJA=~WF^sW_L)9jY6gkhDnMo4ZK-R6UD}5sKBDxxTzI^;zC@_8&Er zcaBk{R`MQEN$Oj9>7)wHWPTK3uqKUv3oF-n@>|iA=9vN&Qq&9+3gE8h7SS}={N|^k zVu(mPreHXDvUYXBabSlwrho+m!cjR#w9>+T*(bG{!kny2T2En7qoz3DD?9uLIJa}P#kab2YVQcBzv|i3?N|N?Br;%va z{mYHV$LjKU>#*x|&+~?$_qJ@vdx3;SI6oYIwWTh<5A0ye{d_FsdTa0et6)y+1i@I) z!PaGhBftr*dj&ke@YXYeE4kxZGll(gX11b*E3?Uflq zuB$o?CCmIqcaw6XZ9>aHYP_1w`P*P@3+8H@ zox?!)Yx~WehrHOnl&gndYft9wf?aIq^J<{;+ZDVw;79H4dCNeJ?N{?MfmQ9_@+ttW z`hj`ZbDjDz{HUDk`uY3~Im6oK5|4O}x6LQ6_Z(}RN}T5ww{0cjtwY<=i67f{w~0wP z8dF<<^rc?j_KS>Fj%{B+8B`wC9!p_Jf$do8;G+N9%c)4w`F1b$DZiur8Eq#Qs~ zvoiHFX)ozC{SNw8%42;d-Ac;QGZ|5Yb$Sb<0=LdEfCND4KJqW#EhC6>f!%53QrZ|FjrG*Nv}j`o^*s5e@fEd^ zs4xwrzQ7llHqoe9y$M5Kg_&zI(YsL!(|1N1a=m#0<2n4dc?)wE%w&#bo`o{amzXjL z-i&2F1GCIL)(lXIS;{&D)R>!DFu-%85VP8w9GP>xNk$rGly{!78UwOjG4^2I7?zs) zU}0LjX*F(0qs5epE3P?UD#9{5j?p z(n{`B^COasbHk zKJng)%*)=JW@^N6EiqT2rr2xE-6)}Pw52clZ(W^b4Z5*OXGz8Es6Aj2VQy3=SnSxW z(p#4I*xw~4>r@<1{Mot>KTZU)g7C%pYplhDalGYLJAunSXMIR`!EjoC5ZBWV+9nZc zl-*hViG0bt^Dnqc1 z9abN5atp}%1F2C_Yzt5a>gL!^pzc*|wo%c5GKWor=_jqTJ;aELp4&%ZClzGbH(<*J zEA45xX?d&dOdOw+Vprq7F+1!*{9$^6{Uu&bUG5l;|3F^qm_hiLxXZDb5D`&1P7utv zCdoBE``k?(5BCGDRV<@t( za=c>$Qdq8Vq@m`@_>N*!bMa+|8@;jcjN>!fDO}*3irL8j$GHnr&rOVQ{_(7!Garj) zq&OR~9kdP3$c~1x&iM`pC7p2f!`TRpu8H_4`~=r>dgll@~IGRO%3Xh%Nyhkux(2@>y= zIBr6&nrAu(Lz7!?IyXXpYWh2~Vfm5#d?|ckBtPE`H%9XF0}w~#>8=fk2NI3z0um(N z;>tty77cajP}uz8uG^7Tvz@L#=q$F{Jr#Y6xyQW~vyDF6eF7t+PIW^fTa3+aKK39{ z;#Ocqg#PY!>>V7#eGNAgyVw02SBaVA8H#&=dghshpNxFy*@!=i_~bc)FGLLSoWXa( z=XkR5zhNg`(?N;;T-P+vQGd2;3}~Z2&Giqc(6!VR1Drb< z@Bd(NMRM;yup0%r-dOk%0n&?rhw^mZQp8s760aRm&vJWTAg42Gd{IaUt-&`Rd6m-X z+mBj9Uh7LmVTsi~EGj@)>64%*Me_4{^hK=A*MTm^2z^h`*CQQ`e=y@w3jYMmQKZ?w z1j9w#^KZmh5#u~fx#GYWPi-zYFv=szMFoaNfgw;dj}%w{ea@L4H~>4r>K{mjnHYlu zMEFG7vOp;uP7wt3@GkPeKnG$9F)#1}kwQ2c?2Bl_PYaGi_Qrk;E{E%wHkk2F1v~1zX@1W8wv~r7^@J06~IH~xWEbERatic4>~K!2`E7i#Crmr;1toR zz$fsX{G#9_$cem3!F3QPM;AN|UCt^A!l4BWMUW5uK=TJxumjW;!2qm^Tot?r`#@SA z`~lxU_!t@kC*!T5dGJnLL1;ZvjQ`-%B@!ehqBk}jR92l72Wtibq=`cUEp%=;JS^$Ub&*G zm%)XAh2>v^(SQc|!5|X2Qt~<|2eyh`5zfCxbSwA@q!COFjR!ByD+{d#mvFa*PC|yU z{|TWW0Oq=o2+~DQ47EU)Q9YrnP&#FM=moTg6b$!;O(Al^Q(!5Cv*DGn2K>744%k!N z>hN*+bnLEhIy@S4HjIMf(bzB@u0rVouQM(Orv;v61cQGEZe{3$e+52dj`Cy#CuNFl z^MgCHmK**G0<-)&SWudMPIWBk$$nQ?8T^ogRh|k>$sMUk3vJKMliNa>fJr46LwNvk z(Y8=KaB{)P&>bLOP!dV+kLJ$~&jZ1^&hS3ab9Q4m6MUFy3RA&K`txuVWFRdj?17|E zLg71*8uIDzx5zEYw2m>*9fWrsOQAe`uwyGUi1T+u!vQJMgeF z^g;A(Z;s(P=09&k%SMdM`=engwx2Ji0*Ed2xk}FAPW$78zwx{LKe=-W+XL0~dBnrP zGsMTFgwSa0W^zi%f*eOV9!`etrY;SC1A3^RJBT^?G;znDOb&fvXVxV>y{_|e>Qu&G zUCUEs3_=$zDV=e(>+-o{%qiUy&z@o?cb`nCVODk*oF2x!-W@oJW{v9UePRh~U(c#z zZ&~P`On8PmgFb9qY4|In4*V}>sDYcHkc3?|ik zuVEFY+xKrp8g`FQUa|rE+CNKZ!CCw!&UL&dkVfky=zG>V~2p#8LZfHPbywNQN^fj-fVP~ZAV?aeJ=9(|FWHvUzcTdQ~ zjrHen*tqwBQ8Xz2dB8xNM|c^`z(9#FLlY3YNpC}T2!VVzoD3XGF^7LA}bVISjm_tsMy=7?_a z$=S?Z-O31mMt9#lCS+=QhQ?oD-sxEr7su+;b1L>2Yeo;|XfkVSk1PhxO6jpi*PyW; zkf9hY_CQ;+&^;b)gA((%cTEKgL-al?S%DqmJ0zrHL%u=|4OitKM$5oc{Y}K7goFSB zvz7RFFdhD!)F-q9GMe-?^a4;p=@m}T7E)?DW@QK>TO?-MUE17^*B39)V4cY1>$Df0 zSI$?{AnfO> z^n_0PGZ{GY3sF{Zo2YWG;8{rvoOc;0Qj4pG^o4xf&Bl$PO!r(sIw()QC!zPLB3~Tn z2rb&bF?SrjcVJM~1p2AK$MpI17eP^~fN?N1`@&d8K}eGnV)hUJbuPq=4ac6n#XJ+f zdu9;xLid$NJ)?|673lQpg5%kix&VaK&&Ygxw5KJjx{;m*}@Q(2EYQ(|Yc zM|C2O{>MJlNr)j*j~KMZKh#qOf?*Xk+fb_MO)WA!sM$)rXWUmdk+#M7uqcmaHkIZV z&}W-hvrp0s&5x)(j2RX!;T6MW6=3q2IksX%1#6qQS9I1; z4%R&)9m;v+u1)>LUGG_Y!Ne7KbjdpIZSRotHr_CA=DC5qtzP%p3p}WAXu=&{qi@~m ze4g7!IJKR3&u2f`H?N=X^YOQN%luKtzUQ6sPdhdu59B`(KRu5YX*%A^YKp92Ua~a0 ze@&}dX59hpS=MbGs;-kgQWsWu*(X{KmBg}JTb_%~a+b8#@-}gpZ95rloUd(v$U!cq zy%V3oo22)lQM@`s82&i#r13VSHt&_`9#F|gnw>d!@`qZuSx58Jth>^$=6kIjY2|`t zwnG;cf^?fcrA|<5AC>e=@Y} zh8*=LzYA|W?w$B8eCHf-VyI}C^WWne^X@lQnjhueY&v1?%6rgsuBANhM-#d60Dnf4 zyDFJ~Ts2SLi(jHD6_4Y8Rqx<`$-k%>%4XynG<7tYU`}&7X|qqkz6`rfV!aP=}YJgLoi6=E~BfJpvnr34U7fn*FMnx4V)SKW#ikE8kKz0?^ zHU9_HN#<+E$N)EMbPQ#R7TjUq-l{B?{ypT|Gy>&)P zRLSSovq?7TsMezM6zQtg?sG6{T^mv8hbIZazWkS#g&zp6pxBKD~;00l0j8-3x`SeSJm??BobvDJ1F^8 zJ&c}HaPzEPof%Q3EcKjAz|wX#HuX*E4Yl>6xb(OB>xKBT8JdMD)5~^h5|hW2 zozfI0jW5g9SkKQWV`!e8TU%D$JTfs|W-VpgTry+nKAS)p}&NO5qLL zWZz3wRa52DO25fd<$KEx6{X5iWm;i>xxRcGZ%OH(^5@KO>3M~mdbLzl5lvcNHmY(0 z?rs^bY8?7nc|YYudP(-tnk#|NVQcwXqa%3R@tW^_5z}EMgt{mT;mf7Rw$m##UhEJPNoXSh|}ywQ_#hK-}=k!t$}`T~*^0 z6A+dve8o)I*{UZMzaX2H2P<8m{mT3*I3P`FtGbcXs{Eo{lRdL~mQoO@8Q7_Om~o^! zsd{qy&}u^Uk+dt-<<-as~t?H*WlTtp^{I6zv%G@fcILbk+DlY7C zV5;&8t(N;$RfVtH&Q@8)bJXLi?ut`trz`u38x#WNJn=WFN_n7Yk2p!0TO<|mm6GDV zyp_tXVjycx^%ThhT48mXq?^2}T35m$tgIO+J&aAP!N|^`F4w%4pF_ZE<4X_15^8J9 zWKQ6E!Lo;tHWwW8-@Ozj-uWapvUIf7Tty|q&Ww{1zaYlIWpe?j`_#5it3Y46!b;QEajKVrs zp@F)yewg?SX=VM1qN(_VdUerVjHh92@pIJ028`qZ;!wkb5*sYBafy@-AvIo*4FTP0 zERy8{_cz*P*K>W1&*iIg@J;>Y>Dil`=E$X4QB9lWcQbx99WR}p(Z4CH^icY^CSob* z(xN6=X>nR&11T@vHMW7Ax6?JU0hPDTZfGdX!x$h9`n<6Ae8WBd{D#8DL42xmP2*zz zoib2kbpDExO^w<4s6tF5JK`f-(5MkiO-dmfmf+-6yFB6X$DBP0w9_x z5^U~r&1y+&_D{`G$@{E#8eqwS%-#w)6;oRhk1>fRi4(+u?@?myMt>Ub_+F++{vewKb!m-CJk?NmE?Wy0_3 z$Gornftr4KyEx}GbMuOr12nPxvDDWZ4!@o}R^!j#Mu0Yt7WBalZcY)HBmVq$p%VF3 zJ4(bs%+sDKSPSE7nFWoIKU!_!G%!K?u#g1Ws{3D|1=v?NvG7lBK(|7?DaWikEJkDp zbeF_+S@(2UaaZOy9j|CW=KN*>gX)GxX0{vLOkpIs)-+czjOM?az0A3-E1N$u3sg+) zG}g%4L)v{TVnvM>#QG>_YfIRtil1nW?B;?p?L*GU{B~V$PCRd-ZU(2GWz%ityre61 z04{>!*U7n0N%M8rc~HErWoF)bY<>%b-wR#Z;^N;xcC<$2=ONa$?iBn5t8YaJ_|Ofl zrNUm|&#ijlL6Ek!OGpOdT3-n*07zSJ(STe`+j!CL9A4X8QEql++a^(A*7cUHRIF!Q z%QkA7XKc$_>S_0kmXp*r%a#@bZC+b?O9M@&zTR?=KBKO_brfAzHK}zgV?tR}YX*Z> zlHDp~yc4f&wK9(ikGI}o%JPhDeVDH}nQfCH3}ge<1ty$M|XBv3dYs z4vNzA_*a0F^p*J&0Za7i{C&CG^sanp4yesS5_ziIB2r0@vaOv2a^GsZO$u3$w+|w3 zX&1DwBeyjVYfqISn(J3kf1aEVBidZxFKx7>nT^dnI~_aWdP3 ztTOK7#35E1F`O{$o3Wa^6zVn_xfu|?@iJElrWxOJAAkx>BYBg6O{O`#odCaSEf13W z+b{|L&b!Vq5&zJ;#xMkb)l+6zKv-|vWr!xI^n3$~xJLVzp_XWG9B8;nims*`qewRt zY~u!UqP(v$nS8hSx{*gYUfAELr}zbE<4x*W`ViL?HQQE%PfP-h7*t37>6#&r(3& zSq88kK%Q78vFCx`S(dRcMf^G2*iz6`OFY{Jj4`dm=6hRAYp|5ajNB!AlT8P(H|^6+ zFx)W%)}+AQ(Tz1-!Dlv&HV?x8tSL2bAkZor%$JCxOBb2NL{Z65bAU8K{Ga&~i6t~x zrjfq#k(U3+aok)>8d=3Ev0%tQ=szrc$`&ftqN2#ihb=bBJ>n+Ib?P*Hv~>_wjcvAW zrJcbnvBGITQFdzsorGjruP_E7PFbHacEab`dNI(jX|{{!)6Yd>slZHaXy zZd;|wdLDPVY?U<+e^ENoYQTRgI%0i7$QFfdLkZ9GxwhrR<2<_UDACH++90H9%&9g8 zDV3(MRg=^dn9WG~LQ1!Fk=GHhw#c0^?z(*nr62aNJ({9GKeW@R%TWz>6SW0NwRh6` zBI4{%XdB@N9ldEl*lEXPS~V2xSWJ5k;W;+Z$Aj&*-pIMW66+u2R9~_69de8>!4`!C zI?8P;k)KR|+0LQ}Ek+v$JyF$ZGohR60Jb-nT~!?WG|aW~iS|R-Oj$oW4Ewrxlf4|5 zR$#Y#agPKP`)7Q79@Q}pZ{uhqgnuDxPK5BI=_&_=;H8osBH~|UqNAF4nkaTSi6!`t zj{C%0k^b2cq>GsM&K;yLXoC|;#-c<{2|0kwajGao5UEZdWhWf!d`Q7Zn(cm2tk4G6 zV9E!`1A7(xsK1}R0>01xKYJm3z3-j98D8kzV!wl!V6r-fASzp-j(?H=s)Z3ndPn_M zhXi#&nc@hbzL$S-{6G_AkDc={y(P1q(HLxDy%UM~CWJT@*epK6>BrvW);mAocCn|s zCgPL~t!p*zD~;)j#qXxjT>yLmN$Dct?-P5u#DoR-ORgqDCiac%CgBT4;~q?;q3P}g z#Mh{E?yaPm$kXl^QVJr~okCK=(QX9k1x(^*kcUG%o$H`Xe~NQGlo**ypa6fO^B}at zdCv)l9W`e-m9PhG3!T^D5KWvb3K7*X(6tF6t6t?wM=n(OTt&!6xyfZmEidWqdV$i3 zneI{OH4*>(8gz613HM3NLLSGB#z;B6-4g6zX1?2m&7kMFuVC%e4EKB7Br?M@9CwNM z+%prWA;fyt;=bXodyeAQVMQJ^-i}H4ND1rEJ3Sgg7HW&fPbftm@!TOiL|pK^B~F7A zyuFBfVJ$8dIOI1)radw%!5V*?%M2Og%62`46kB?^$3U02S>69ZLz<87Tv$d!y}Jb7 zr~0s1 zvsuaB#putB?cV*ESlUi+GNz7_;w52wkz8IW_7HKMSA`Ye4c-9uG7jN=iW`UB_2(>uH9(Yuw_w2gTNay~AKbE5~}*!-^vL`Sb9p(vw~` zyu9dbB+oy)!0f$`kPAY-{>aJvLB178A(!ksiu}W#>Vu;)n7w^cRG2=**N$F9UF5ro zrjWV*-sroeA^yKG3kiAtl^7sC#vhH*$p~YZ1?x&Hh`+Xu8G!4XL0$4va$$r0fo?LZy<7fqkeZ;-0{HbZkQWk7=&idF~gm~AL`pbG;-J`Oy?)FP+*(sGS~YTt$2=77?7GPf*H z<^$$_cWZpb0E{)!=K&7aZ}xoxinUb#bkN+UIR8PAsw45BG`j^i_Qu@ zM9)Prf?v_6kWN1-2M~A@ndy;<%sCx+?&s&UdM5bwxjU?0|D)VaeNA9EAW8cxunzF4 zDHJ#dB-M=zFhOIhYyl0Zq}(020iG+L66^ZN6Q-E`Igdhd*LAg5E2*fJ32Cst# z%L_vTK!TD@p@raaMdL%qz(obiLQu#EK~6{tq2_%InIYe}g3w*)IW{uB{YUr@K<X(O5zF0RoAs z4Szr=(f*G9h&$;1L1@;YV0wh`?+c~{Q?oV(lY{6imZvf(&mLmC5cFmj7>)-&<;>Bw zgr?V&kgRA7c>pg;hlM@?p(UE|MBv9FZg?jMQBV_31-%u# z4fDVmd~moKe3LghdnMbAh&wv!U;)D49VU1beoBWIz5zGC;|e?tySd{Lya1EX@fq$z7hscpbB#Q#!*{;r z6>hGtvEeEHP^dpo723!1Tyy1(mbYC6^1 zeL5*f+tpp4aET`C84|aUKDs9&W;Xp?kNC<$dQs2qs2uv;;GdWK7&C)sFP&tZ4iY1N zGqAyy3+)V5@X>iZ<9hGt@Epdc-c{$anG<_YorN*i_GX8%m}h(Q&lpfE-J^97RIYn_ z+j!IqH>ds+I>P;?ax2>DIbAXi6X)^q_}C@htE?K_Kwp1KG48ET7V>XD@}EF)3HSV; zVR6KsKoN*fYVF(rSV$&xnzKGo4tE{N7)ZI-)t3yJsnXeLwE7>ax?vAaLc8&j1j@4h`WsSLGA?}BQj_>AH^UCpNF4d z$a_bhJHfE`t~wjR__y~|SO#-sZ_XJB@|x?h?ksAMduUq*D%yQoISlp0-B!6NGHgGFfPYRVi zXYt5|o!`@|DLc9VDUT`FyPhOnpkC}g8vl}N@0P~4($;lY2+sg&FTjU>(NTJr60< zu|jVqt{F%14M2XyZ}I(t3J7!jnmjXcYT#UM1Zip@nDsYF-&ve~fSlbmJ%vb_(#1;r zO_6o|h%cf}?hcPlqSCuducp(6cDthsXlr^_LAn9yRXqHqS_JHmPwx9VXnq zehp`FT5D8QDt@H(PU&Ji&_)w5@VD&K^0Np>?9H?#1g|5HP(qAx9z(Z~R=Os`Q%N@W z9B>9X$1?$NlQP0PDVs*=^;$E^s3&}aR15Wue_`@AT9&^h!B1-m9Ec;(#|BzrAoTN{ z3$768d7Ydn9X+#a_T|rXNGQuFjPB?vyEu_Cy{r7fV+OekbH0yJ*wq={%%FC!J||{W zbcdgnF#_H3VHW0y?#!@(Qm&h3hGu z23Elq>PF)N#t&+#(L)B%=9$B%2{4buG2qtHar{{uz^N;7rc?BocJ2>3TL3y{Gd&$tZ5)A1K zQ|lpp2gBETq4_D}Wh=fehB>n}D2rrXX*(`{#?-ex<$YnT*2vhsEV_0N?JVnq_6;$K z4Qy}44$2?UAw`bP=jtR-AZN9{9JG#OGl&6exkruk>{#w?)0vEG1-s3ErNtD8&B~OO zg##_il2#P%w=^YeD@0j-#1RV()}1kLc>S#Ks~NmGR>zeoygk+*Q9fRxZCNCbS6~af zOygN?&`UyIr>*9qnD@YTEkeQjVIOee2B)h*Z@kR$H)I%3aIQ6EwawwYYhWt9+^G$2 z`7`c`#=lC5TtTC}sDk^x=^rkoAWA)sIlG`qT~AqGIK4Rm?1F^o+Q_ij(xgm>b1xL;tIV#d^bES7M8A8RDZ)7Jo97MTH5+8XS?)!WD+6 zm-B?DjKeNf^QE=tO~?7d+99Sre39a}b|b%`c1GiPepl^@niKqAwT04tf-QAJMJol! zItp*PpeK}Vq$=7`|D1NSh@qsCGK$`*4&XA2lN;utdWxSk&V*BixlMB+G~pNZ>^!R| zuXzGsqv%WX`|NAt(=FwhGI2@krgX9RO{+dtQ?j6KZpyHd<87d%_!2~$BjH|&QZpu= zSK`qeh&x{LM1zbSFBz&)$Mlyh*F3#CN^)E~;>s+^743%Tm6AMdT+}7edihcF4$<<; zALccpC6%u_7K*mYhpAVJ&dE2_(nVl7NER-tmiLtuiXK)S6wt+stGwL5#K7uw<_U3c z%@WFok_9z>!n+cbf`C0*@}@Qu`CF1!7jjrg{;ki1tS!w{rsOF~Z>p{U4uo9&f96at z<2AHq%__Ur7?!cNd~BmG4HqK(f22Gw&uxlLjxQHBX_Kaww>P~@=q|sbo*OTe4pN_r zV@YSI*|A*dI<+~bRQiwl>D6Xwa`Wgb&q^`nBFmCeSos;t%+lQQUAm8@gz}3m%Subi z@%2@ux^kVIRQgOhy7YS4RB2N2-LhlSoX7i0aq7PyeM&$|By|P z%oLB2?T~=@&9XGfEzW(Jtn>mCBm1vx6qQ!FzpRP)s*+J2iz}@BS2_)ilOL%VgJ_l; zWkX>rtCm#`1Usu}mG|>1t6s}X0IKSZRmXEek$qLYp*}Qe^~y|kb!RmxV{G-8>PKmo znrStQQZY4~YtE+}tGQ4^P2OFTS>sMRSVK_^Ner(ME0!gs)@T%`<3&|Ri>Fy{RUIz6 zZw*%ME((~|SA`e-&@@%$6mMwEtYQ`CDiBrbVnfBJs++c50-1;45z zM2pzcYK}-quc^KzK0z5%vrPPr&{30DqQX|y*d*ssor)Eu5r};XUfFTzL&fLv8cj0fFSYaxBXKq&9;Vo-FuK2~v zQZJ~T$J5mvtUb)1SlL~h#!oC8RLkPG2~D+4g5kWMwKoKpInufjf=*^_-PWRQw4rsV zqL-xBI#V$QUtT{%xEkZAKQFw8T3xReU4y%o6UBOHtrA)y1nZSnNnG9|)tJ)pz$2E%DYtDeHUY5O2Pj47pz9tRWFsD2fb~K|Qf#XGXkwX$dMlPrb9GDUG2%Q*t*|*SL)}z%jjX2lIhrO5+A* z&~~cv9BYAoK_irfYF*k`&U&Zm7Hlhke^gs)|8ar!HZ}j zaQ@&VG*xns^`pjKKKBZpCZ6*NKsRc){*VW3x!RS==*TP!l-_0j@ba+^E z1wRvtYyKkG1pd&nN}vTLw45(m0({mIY5@euT2w{Pb8}l9#S3zFwA?MelD)d+dvQ_L zw$^FIotdXv*9iw^q_^%Du1^;>FQ?TzY|YDPe21lZCXHc-HSeH3F~l`rr5|rYHdE*w z4cD5R8S50H=KG9t*^ib{%(0~pTGlfGq8%;a%mDvK3zW5}V0;UomCOdVw6Z!Fvs(IC z->Lmu2eHAV1+AOeAMyCsjC?qDLTf!|IqGFwKhAT+*S1q!9ei<{uz(8Xw%smV2pOXp zUnl|QG@|3o2+P3n@ zw%;_l*rZuP|D%YeIYEyptk$H`6`Tng8vPy9ppi2+(PSDEBa3X(ykvYL&eKj{#^Wlr z2bga$P%Vk2Mq#v_Y!ITZeMp`Q>?qig!{|6wfXc4wh%2bhx~YvIbUD9iBMJJDo((lJuF*n>qfI4R zDG{N)s|^yrs4uq@nog{HPFf=1!Mn^q;8TNI@zjPz|oo*R}jQUfT!`y_R z=<1n4_z>MKRuq(_AH(W}oYn7P9|kYcN3%=wzUzVPo4_}EM*euf4}Eq1LBK@4Egzn{ zP9F@lGsJetajRUoj!N8o7q+7aH_iE_LxY2wi5(Ac@7u5G#^Cdsuj+OY1}M+yG6=Nl zKAo62sp5{#MP!$T>HZ@P7A@0HCuIskzeoxexb;!wW%(#QmW*Zs^g^IfrKE8 z48}w7Ib%6<2IwE7ni-iFW^^${z(nI6W-kD1e9!!r+p0IC``m-|7PQMfNZ*R?a5d(JLkzZBb} zm%!o;F$xJ^I98*cc#73-d_=6JKQVqM{-7Q*{XyD6a+{Wucm#pz5a}b1Wx5>d5-T^6 z$r|)vlZld!#F)NQhaskz*HW3V`{oO@vCuj*f`$#{=WuB)V3fIz_6$Tf>*$N~O3Xfb zG_cM5fKCOxG3rCx;RvG%Nern533ab9-bP-xZZQo!$_JW0V5gMh&2z9tCCTOkxT(cLb2^UApJis@2Xb$j)%XndHFGyUz#L%yL|8>j zvkW6-lmD~KCo~aFmR-bA_;$-F;t{Ohl1jv3mRJO&@hGvyM^Yl!SqGE1!hczJkae&= z>lMmQsLBeY03mWKjUof9t!0z|$YX7!4#|6BwNp3e%{0^DVE1z~4W8qEW=6u3-72#X z?y){JTM;Mpm(1@GciM(n<{`5hXIf4mf7W(b;3%T}rlkfwPMTopMGGV+t^F`lL;bTW zF@=H&)-%}A1-(`j7M*{?D#1Qu4YN9NXXp^?BV0LksP#AQCF#0t4t_o1x@|2Uh6nV^1R~z)$Q5 z(jD+XJCi&Cw8gp_TJAYvT?G|-j$7wL>7KpTJ_U@$8Jfp&*-v5mvwqq^ zm^4PFU5xS2hT7Y()5y2%eb^Y{P5XOnBmS#nF!n3%gkw5xH%8-FgF~ZtIU?`_QG*;r zJQs1@(M*^P*E%{0F|anrT>=kka=a#ZAwkD4;sEeF=Op4f@G_ef{I5q9(mNq-1A9F+ zwm!%*`)vCFNR6S^z7o1hlV-mRZD}gBQ(=4SkJvRZS9PBKIXq1Ehhr+dw``zeH{z1` zpd$(KsHn$5M@I34jwa+it~A8?PqVK%zN0M6qs|%VRkZug9cTun-5G|yN76XcG3yD} zoMa3dA46uo#(j=*Fhe`c;e*UpZ*_cu z)Yrdv&V%l%neRLS^~m&25bSK3+F1g-CH~=b!()n>&e!le{EM#Xh^T@@*EU2~z9_`` z53r`Vut*iX)+IwtrqV(l{!B8IdG)ghCKx1x_hxusLK5uTL*dWBm#BbOHMpc>%Hg%16AI0 zPIlgK$24bi9^TmEyayVqCAda|L~5gJGkBE}x@nPn5>VRS-@P~Q|Ni-m zJe_KcTL?O)IOcYOZdZPAe*njX`djCM|CJmJx%xAO_dI!!XM!eAIW)Dq2w zPDbecSCL2HxBNgP3_jUAF8h{mn|D;U%eUF{BfHVJ#yd7=p!1Y>T@KpZ&wD9%bo&D@ zK3CMT$y*Ot)iBC?9bl*p^9=%?s2b>70qm<7?mL$kTYANZ%zG~G=PLhUstL9ckP zeeb{t1*`m1!FTfO{o5fISZDl~AzH>3KLWahwm(Gp>6A==EA%$0$KMHCMLg_(4nyOw z`G3K*xWd2$*hlQuz(V*I%;v!MP}297z%jTCbvSSt?hEKd+My@V^HgFK7)+0~tBn0z1IlS@#2%!4if& zfPxIB1p{J8I(0yx8PZIS4+J2;iMIpKpkaixz%M8ZzoK(I)Q_Z_^qzjTlMg;cWp~zti^v~49pFc# zw9W^R)r8-jUm#g{L)QpM6^`2VC*(0Uwrdr15hk{4H#8az=sF6ep~zhqpl!&?u4L#l z!~^tgcTm3;v&}QMtsr#nBbBw7_a23O05;1zvE)5&l9$7$;BNYsu;utxpN%RcNc>5J zqeOOK47z}X4>Z7I$Vr{Y!3@f-&U?V|)InXz*|(@|UC%Qfg=l$X+BDjYZfi1veyL|^ z;&{5D2N`#bv9Ko)69^IhSy!Gi^udVe)r@b!{743KL(p}32s1AD{bB=?(YrVzh1u47 z=E7R$lV14w`K&R$W#LO%%X-b{*0KKXeR%dDE52`FST4H4t<_IMKXX58Yr}+lwks7F zy@ylz2|L&Gro@L;cw_meaZ%nk>?`<{J|gvKh?y_OeSz3DN$+36JTSJs0EZ=-oYvm`cW)o^Mz5 zjEvx>=%EZnFgr4d@jO_4=>c(ny=yLvVHWg8g#Tn3d(q*;n74b& z&W&S!>ouKS!1}ZIVc1#pF?YW10~+8~X(pg;?k`F$W{>AW(&x?-fEaRD=fmu66n$pdJBZc9Q*h>g#ROQ#>{$%;v&%X{=!Q1qug-=o}&`N0j5%NbF@^h;7k zVNi1MeCWA&BK}}J34S>rWRCBh8*XLp>^*!gz`WF(eD)?2)Jq9_%@p)jhs{RExcYS0 z(0G?mqebi7BUCfd-`zy{M9e17KP3$qqo<5N3A@KTne`p(^tMu(aTUJh`15#@PlqZX z9P!g&dx-l(XB13Y73csABQNRPn)NQUvoI?C2?f=~NL@>v*F7kyimLAhBpj!0=nllq zp^1B@#muBn>N$R8KYd?MWfY!{>bZOQU%DYU=~4{+SMboq>5SPy_ysRxPq6+xlaU&{ z7LH38Rp(eXT^-iy(_|+nFD&yoOy`fX#K1|gpaa1+E3%z*5?fm@ZGiz)dL7? zY_d`Zfp0%mw2tt@{)jV;c-4WV1&DW@8;J)j^GFPNhxpUraklQ~Mt!Yw6*EsKi)$Q{YzoUyMPWhhnENj&?R(UBEzhjg3xW z^@iU8cdz zBAU!3ql~A|3vKQ$qBmOBpe&5d)_E{9p7cpBo(>$xM@HuBZ>CqE8Oph$m%Tapn zUB+^(-dUG+a~^w7UtG!^ZT(_1c}Cl=tFL(f+Sph4{Gqna=u`Yhey6=NB9U9wSYxzt<&BX>CAYCLp^d@yHPTeOxnCLsRj~zYnpTtz zEkHEY7B4Bdq5h{}T;bo%qnYwTNwb_{;tg&ICq(cdt+7UM$x)CH55G*MCjeA{=Ts z5mzHzZxF^t3a=RYVrB`chM!lS3+2Z3(Y->WF*EAA@U~GF`9%1|XuteRG~M|4@@heP z-5!%tkW~A@R3S*O{h%!p;OeF{A_Vff(={eRu&!7NEE-ooS|l&JP|xM@i)xkY^H zQ2s~1R2-+uC;eA!Y}k!^D_q|=34KN=Yy5#2BwE?@3EE#&qkaO~D4yFK0F;WwEfqO? z#6Mb-vnG}tY5kHhs-&n5p0>E;R@?U!lw_FZc+wroW=(P81xcFbUcxvDSGzc_Q=-&f zjxCUMX_+y2$rr8uDyww1_Qe%h>8AF{(c02~+V@BOEBa8i!CWkQBY$dUieAa@c3{Q* z<-gP%@tmr)wO_=4SAk@9F{J9IWQ15Y-IAudC={f0S^Zvkc4@J48>Fmknrb0vN*ShM9H6%B--i1+#PYq3&@6H}u4zI> zNx7}5DD7+ckEU0t(b8q=oyj+)r`4P!niQ(X#E*3oW>^a4AJOybLUL%HNb# zRQy@CudJ^ED*UH>OvTH>x8)~f;QU$TqRM%6OZnHzAlWb7FNYHTk``3`i3v!5R`*9* zDpIR&!9G_6Yl4ti*Z1{*Tg^+#!!u4NpSLQL0^u+453VP6AwRRh7lF<@Z%xaW(Q!4gF%T$(Bi$ zSue`|DtT!=Bb#4x+we`cRWh(GLUvBFRrOs4mO!gN$s`i5G+O2?T_^_1zLeqwb1RpX zzU7{(OfJh~eyMCMpF`^}?_X{rU6CJ<#^MLdxfO%aZ{;5R`oQJ9ii6k8QP5*>=OwQCa|Dl%%%CQPh)CY)$nS@pE|wrz3M{bHX9QT3(x zr*=^FWZ|YpbM;0cOwm^zDRjxsRO3Z6C7|kBQEu_7>g%H3!i1VJ;v@NEYxann7!zs; zC6_6Hnn1}n;#|dKNf~aGBBpdNdaa_p>@S39=<-TE>) zIr(FKtK5-1y51}Ql(aoW^*7i)hIFXyU2Qz?tNBMQn!mPPR9ngis)4mOzNN0X_N8E& ze0kk?L26la-DZJ7G_NkYXcGTQ9kD2#JF-q$)Xf@O_n>$eEvap zv;e!T{)5PYVku9Gn-R;DiV_}dwCWE@I%KBmLg_ltUR7!7ePE^PQCS8cly6@a$PqTI zD_@o!)^NEToi(EYU2e{J*&rzYk$$T|DczLzxWOe2CHplzkyfNmZ0sksryNu^b7}TQ zWh*z%Uazd@MpzFieO#e#r1A~-W%Do9q=J3QZK_=blB(OPgn}Q^xhiVm8Sz_HU153A zW>t6Lw}R)YkG$RNcMY?7m5h@ONBQF^pBl(~1@TdXU9cTLym7eTUrbtKcu@hWe`7^) z3jB8CPvJk%=S`PH^B^;uB%+%jOw(;K6!=9wQhWyhS8poWn!8zjp@f(HLk%f;n&nY* zB{MSh>ITWt43F9&A*J6|-;o&7KB@ncJWpHPc#S>7k0$rx;?YW~DXZnL$_X7n{KY&pt2qIl5)U^Z1A zYY~Q8nAf!!S(%|mmisKD;8^Pb_8$dTTNkn;*pAk{>`+r!Ya;s#^+GErKaB)!_2z%U zKWH1k0b|qK_HskH>1`yg2YI6HdVv5A*DNTEgFe?}@fJW*HF91F=$ppLACafhyyj;C zA=-)jF2E`6D#75~gWBDKeK|+9rv%{ai`qCrbrwL26a+J?+hQqQPGws>Mdz$*yG&_t zRJI|hqm7QXN@||wds`RvMJPXi04=8Opk@`VQ{JSxK;KqgsX@_&C8IQQ`q!dfjhAt( z@PpFht|t_h4HlyVHcx1L(Kmo z;%9pSXCgeQy^nJj`ftZ5ZaM_ev6p)XytN~?;0S0y2fjcB?CX#eya0GRS_>!SUhnV} z?$3GNajOuPGoa(YLPhpw?Hf{m*J14k;+v4ZB0h9d+Q*Z2n;y6CBGtDqZO7(B&i)6soBEq9br^I|8hqjZ5h|wL8E1{Asw|eGb6b} zPy0p1c08aTAwAL!r5g!px;2cya65HZ84Ao!os^l0O42=NO+y6rD_BnWS$z~c9{Nzv zWZ!_u^rrlOz!3fOd^IS{&@cZ(-eJRJ&TL?qVHM{PAjxoulbuU2T;x>dXmsoGS6qJG z2K+gfPqzer)OAXC7_T%tblHR@9W!*rg!1M}os&3U$=7`%me$PH&nL~2Ez%z+6_yJ1 z0P<4X*+ zwCPx};TEk3tvAl1A4V-RUZKB5D2yTo4!+-LXAXo7GQMLXAl;_v%-7&r(`MFIP?hN* zD#yp8cm6;AmFA6#U2QlU^t8&?mlMt2lFeWyD)EEzYJHgVU|(@8EerEFsN~R zT119NIFm|foPgh_SZUmgH&yO5W)OCkbr_2YjbfqEL0niAFuoyDdB;stiEp{1O?MNfO3NQ#R=}m1!c9*O4cgq+}A|k;zW}h`VdLOWBI~XdX^!L!UM8qoyD`&2ZXi zM54Kg#)hvoU!xC){xbih!ywlzv*})NpJfC6J?N2TA7g3W2g_+jblzx7B7+IsZ#s(V zbUREZQMQmC40T>YP4Vb)R*;E_M(G}#bm-r$B-1ktp@CzbgdJPE!n_O1m+v(v<7SoH z%p9DkL~d@wPc6P{zK>_{uUH1*e-_NP{6&b%|I>1iU}7G$B!{}BRTcy>p0d@#BUX?` zSei+L2}3Mi(rMgG%Tp2s1F%jYk3qe#9w9d&QC1{n6XJ-qk)njpvj(XPq2H~asW`}Y z+em5+WT#J*e#*_oF=SV5N*ANTT(dR zHV{|DS!|n&`^h?M`x_rcx7cFvN@|!5ihoC5XyX&s5$D_L2`Kyyn~k8sa%}erA29vx zqlmdEwtYMC6Eeb{PRc>7u}etL;S=pv@)_7vdytHV&a*!xt03#_@5%SUCme$*6F^w2 z8urw~3+Y`?p;ZQRdPr6?e7>#C`W!AW?6gfn%x?Q?+mDbp&9LPl*Vfr>rO1w|H?{!k z?+UE#2g*^JV_%LA^&r{9(V;zFI|{QSl%J!(G;$}|yRoy_N9^CQct*Qp9`*?>+_4?E zCe%NB9tR;Ub!6jgghLK2egsbFD8L^H<>yr6F=(2@hyQ>&?)XZ8Am=(45WXY&J5LkS z;3J)}#A?_SXD0DBbcqu|8Uxwq%qMLJL+uBki#%WK`=FCOpX?hUzdVoaXP{yBa61(0 zG(5Cd!j5Yy?7gtQrf$a&_?3E+VsyWP15x?7#&OojTDE1f)8 zbj=l~3HCzv)A&x`m2jMY?{V zy!21*S?HD2pnE$SPwsPvp?ip5-IE>>=Q(*XBBQO-0RtcI}dy4IfWy@`gvk-t#er@V(=folwC ztK+0=1E|IL#uW|Tr!}}};I8KWE)66`X>mP)ysP=`9uI|8O5EFFgUUtjL>RT?m75J8 zEyTE6;WWWn_ans6!Z^=x1d=21tVX)1=Di~GD^PDlMCTWw}fc_3<<;IgGxk8LazSVMg6>sU?ScG?4Y=V1U|nfx9N5YS%hd6qY@rN4Jd9!u5jJph_jJKdWDlF4meF?gla>ve(KOBZ_o zgX|OOebXVfBED}g^f0g5mkhOYU-=lY-T5g#HB7_$!`B11iYEOvv534xh^MMLWrM}PLY2tnU*&fG+uYLSp9eVHpz|6qMg#7b+U}H%0JI}+S2&&F(SQS366A!zM+uO;5Pr**>RKU+-rgfU&O!SJ*Znze8 zu=64O0Wz-hJz^q4x zWffvO37~7-!JTsOKDMIM4wf+sIv<07(aX99LL#W0U9%w7lr3EwA@4$ct|y>diF>+| zpg6*iE(lbQ>+GUHzhJAnM6eB*sxBoAh}L%LVb!SaE;p#2tofr+5uvd{}JIWNff|gHj{Ck z^WncKF`Zh-U)0TA$AJp!&#t~4Fs;7(Tqcr!vD=@fr{C$>m@=PnzNa8j#W3}}jE6J- z3~r6hU;=}ehU7KTEkk|yZ*9_mC&1T=^`t?mveCEtvMTH zFYG&Yb`XZ)S)zwy)SkaJ66_EURTYj!c%I8S*mvIJl7!G*H1WG}?|p08e!SGzPOT=S z`A-oJ5)b)bqH&}Z0W$nBd3@(0a31+nrw-Vk;^{h>eVxkc>dSaW`@8#G+G^VMZgaAj z9@DcdaTEP!4>5ieV@pqOY<~tfIREMt#?xS8bQW`7P!btp`@w6M4>1dSM_v5IboOqK zXlK6djlY0qP3>iz&tmQAZ3>65l6!BQqqFe6-_A-{6@Amf{FpemTpy01xXZPhFx~D> zRb^=MvQ@6cQaxr#5^kz@8b64mdO7S?+*jWbYBIhov_JBWfbwUdR}xQ$<`<7ikpU!l z33*%Rd_X;ARi`k!kYWtYFG$qft}m$`+W79&C?!JV(^u;}!g&*-HLSTHP-%xDdgE)QgU4z`8(`O4sn2n6$3@5~E3nR&hY&#z!s^u~m5V+MQC z=gu&{_7MSh4BcxZ5q9WkYZ!C2M8>isWFD&wNI`l5*ORaWoL+d$KoOjX`-Wy zqai_^o9RH(d*?Iab27>$#|{X!&>#_f3d4hd(5d^p$MgD8si9dVo_5r~EHj_>*#98S zLC*<5Q#LUE2)szV&N$s!9?xRPx(3Cfnf*#VbkW#~#X<3HXF-k1| zp~IOAtT*A|OpC1%Y+~)PR{>L4j~u|9RCa_jGLy}|>6)1KH9y)_pTfy+bVntf=ZtsT z5>9fGJWJvdIbx3}ril~qytz7#JIuR0n!^3Z8yR(o3-n4O2XhO(y_cL^i}%~b4(@y3 z>4x2=^6)=6ZO|8RIb)O*7uWVwGx^wggxS64vS7bs{AIo%(sB4wg&@O0y4WP3JE|fc z7eJdxrWFP7roE~laZ66C{O;A;RL06Nh>RRDw_2M#gVT4*Z6t7gW`4fw=s#W=Q#s8{a(QgPhG!V#HLQ3O& ze2VaG;}f(^6xq~)0Eqh3QfP|!Tr&eC5nEb-z~LpkT94$&N+fOLvS1}|+Zr-}lHHmO zX)Fm&Q=jr&(yX16d_wYAo08}#ovN)(K$Y&-evaQ)dbNE=-0)INds@twQdxU(%)nA# zyXES%(wFU@udFNU-!VTrS}d=gZvH5)tm-nq5X-AP9XG{>syFJ7;)m4>>!M2jsLra~ zP;#KUM*=Is*8EchFLBpgE0`sjt^l$QOLA(LP+v(jwFcso(lK?BxZS1c^~+JuORv}e zgx@YZtb7k0Q>ImQg5c$g8(M*r$|;ScoY&>gn>J>BkgjZUWsa0)s86KFO6%3;)NbkB z<}oQJDh4)RP5M=_thqkXP;t8XZ33eL*fK31RY7Yx9fzx^Xd%aPDhw@}n3{?kEw``U zD!WyYX9otx9Yl#{a0oH8jLet}1MJ6t_9rEg9%8Lcgh}d+vL;A6IjvmDCuBY zg1kNy)8mxCt2l&Dui8;@4|Be%NM=Fes=ig`!`@cM$}tdnwWTT!lv1;>dR3@DH?#VB zZb6NzCNuj(&BvObSxJgTim;4lio=TP^dd!u;zwGff>(Pub&aC67MQX?;jOJpUZQwV zdpBvL;#=M5#N)M->NX{ys&S%0Hh6WYc;1#*jS`wn)@r`+Kkb?7me3SyQuPfHxOR0- zf0090TeCzwMbcGsQk+sutAU9_pZhh6l1=$(HTO%TjBLeX$uUY$ktz8%)HSLqCE-#O zKgt%MS+&Q@J|jNYHkIFlaqA{awUE5Jq>2I%yskrb3@EK1A$tuNS--C`6qj6|RrxaO zN4-eCBU4>(l`}J-^-tuF)BjNpsG6O&T{*MraOwf&wyMmO^U4!dWyu-J*s9(namc;D z%6_nJq@cfjPu*btN6VhNxq=n#&+GOGvedS^M1ijET^+e-q#RYJC^}!JuInt4i9mIq zi@x$(>Sq_9;KtM+EpBC{)}w_hXr6kb&`Sm@hlx@MNy@|Gu~?dtDORA~DW8?l5ERt` zNeV1A#QZlwAgbr3-$0^`C*Y>qD_NS$Q@@trb1pUiA?eFr(Y&H`V%EIoze~4eE^m$~P0QHU zoK{+re!3Z3>QBQp#pM6#XlzPg|8%IDqS*i0`kIjWyY#B2vV2ynw#k|QqG5E?Th8Gc zlX@zrTsB3$gY#YTpE{a*TDV`0;ui6~t3}*b+!1O^!C_Xq`f))qeSGuO!l{&g&BqGM zi3>u^e-)10?Bw0VOm7*(MZl5K(IOtF}Ky{H%{{>qO?Pp>4-RFESUjMT_TVoNYPIxa*8+ zImxg)FSi_E80?>0VwmF%FI#ZTG|kACYG$A@wWXW2xpr;KcUEyFr*$6dYZn@mx zF40UXP$4TcQH2@sPE9p$BW$PU6Yo7luiefs0*7la@_&OyYoUURz;3Nb&B9YIq|Z;^l2^f6|aztsF@pi08Dix}67XKIfzSMYXfGnpt(jh4kU zup+dLthw|tCX!eIYv@f2#cq`#yGVJ0+itUeNC0Y(gIG7|(eQZ|Ml* zHo!J?a0?P4t`1v)56tLzQn(s)PB*xa7Rt|GQg{crP`8IS2(UWz!nrn-pC8Lh2<7L4 zd4-|;d?0z6i`fn#4-9E$C|BCq&L;0Q&u(ucSG32qKc-AoKj;`uVb?oDw0~svzK%#L zvSN1!p88r++fhY3D};AAX^nhI$1D2ig7Lb+^b2f*ZZW-vq0;T3zo+_iQH)LGRXP%* zgV3&1GUwrFy8Fx$3{^jabqv*@k7m6`&eoT)g>bR{c78Z)ond6Y1@h6bjk64FGhE@& zKqUqg=RsbPfyW&Wlo{%{TL4-^=;bK)n&CP(KX;_AgFtXk)wL6H-IH~7gcuiB=OySY z19b0+p%!8NOkzdzBmGg*eC16&h$N|r(M!pH%2M@yGOP5V{sZ}!NMo2qi4W!H@1>Xv zuNb1K6FE~17-|e_q@jo^qpviyP@jeVQrBr)NHYw-X%hTP<5K#-P=5X;ItlZKv52u2 z1u$Vx!;P>%hXQO4)QE#>`8lZguPJ<~qYjN&P#WD=6cF>y%uxo1r(@;dfWQ-Dlm08CHFebk`2 zA7vgn%KRrKo4CTfgK`VM#2iK4jy+(;QRV1TvzB%eHPieb?KPsovXq`0iVHtVzXv;H z$zq&@&a?0sD#$`hE8{=#W{Z`%5Om1W!@Q7p#qx|v02Z38=zl#UOm=jSXSk^yZE%;F zZeb=`Yt4f(Sp5w1I&8nz4s#@y)ZjG}apP+f%?&ud9A&KS6qI!YiA6eT{fqR1aMXH;d=!^# zjU+=bIxCL+0=?GSN}(cc)>qWA2v&&m6XA)r{nT%;y|yG;6m*}BOsj#Mw~1+faJsFI z_8Ua98R@I?IxI!Vdmf0T5ZUbkS%^rpXPu=KHOqF+Vn=cHotAg#DQyVrEVQJt$a(~` zv~HIbgi%#RTg$NY_p`-`Wd%QG}$%}S1l0P4&tX5#@I6PL{5T@fq%j(ur(46 zG6vha2*p&M?HS=FImteVIEff%pG(ZdW9%D=W!UTXoq9dZ2=Uct z=_d#m)C{@>ze8Qe*oix+9$=JU&#NCY?qDL+@0erIY|Rj+D@vwp#JcL&11{08RhD5V z>nAH!*bpU0`4M|xHd8ehccJ-~${qKne!Pl+kFD%cRp9@Yd{f;ekP8H0w0}$vRlNpE z%rL0EiPKVj)FfhJvXi=yWSi)sHjwC|%j%D$&-^=@iDYkXv}P5#l6_3Gll+-^P;;8H zjvk_kphQx;H4vqYvO*)EJR#L+il|eGVHz!!1Z~rNrVS;`)y|_u;~lk!X!me?wEpyI zSRd^b`T%-I=(K3~t`YdLftXNIQC|bhRHCV6u zV)Z@j^QudlQMl;RRLwfvzrqcgvv@}C8V!puITO;<5%_77G`FG2$&akqPXy22;Oatvdax|H%n@TPu z9n?9K2Z@t)9+drr54u=N3;w$0P&wEmy4%!N3`K)O&Cx&5piqh*>#zh-{1aUk;hWH3*9H0Ve(4@T4V>Hhp~SJQ zM_?xZDduqfT4Dk{Q14E>LA{~BNSaEyphuDRljrHVBn%zL8SE*}*u&bg*cQW5ZE^svvgu~L773w=~wlUxNVZXdI_!} z$x|=KFG)z&Kg07ylMLhV|MBY$%L&K1Nrr=jQg*r_7#hY@7|_r`#zF%Ril-$Q@}XPQ z`Gy9f9r><7LG&Qy8U~0oVyxj6u?dPcjwUT8aEyycM0~N)g;a)97tp@dIL8JzJuj}lW`e#AwX^)R{tZf3 zY-5;?KAk_oup9j>`;y@*=32&3LlWjc$pb?R_FB?=!z1jo#5KlYxKm*MydzF7IA%P6 zU&3=UUc^&5Ta6I@J}cOmLRiVrf)RcceT%W1AOkCs--Cuw*v2=|Ch|$+FDQz%*fbt0 zBrY^9fNnzTP1}fD2&YU3iI?%=rZdDuT%rD5^ejWI{$=z;L$&^P)IUS1{$unhb**7q zbiX{vus!B%+X2Ism`@FPhNM_>4Z+YAH>F%_co&ybj5p3it;%N__n_LcpBlr^J2I$7 zF}gc7z}SM>kQ`%tfT>ArG7ZDdiQi~igyjhCn)YKq@_I}caYr}?6ND>a{V-+X{xJhg z_4tGI0h1mtrd>3>z~7}VHT@&ZCVw;A5`0KH^Fl%*QDfdj&_nml$KhWw%)ZbX!Zh<0 z=p5d|@G{EA@X_!j^0(ogp+EAq;f3K%)Hd}mvGn4PrYUjL3am}rtBq^jOyzT zjf;#ABG+nmnMOp`bdNBtjM~!n+vF3aZwxZgqWx-*m};WmROFfN#$Za$n@7dk6hxcX z#Ikb+%-(UMGO=c`sY{xlxghRmO0-#v3KzGT-=pp%?6gco?-IVWtU;Ia2P{W1L%5GE z*DyXDTQI_3!@^o}Fh3ZdEzQ`ibh5>QrP20VUSf^Z>6Rb3;pBI{V{qF@?|SFp@Fc5V z7hE%OR_|8aOK4NCJAN`DigHOmv~xYBLGRjJNu91IRo|lq>2<|>skaR-**j?whJutk z^o7P%qVM!~Mg`{uqs!z^7cw(V-${KeoLPt$v(H$TpgTBAEDf|r?IbpD#))xgEG2I2gH z6#tzS}#m@n)*PFfMyOZIS_-QbMaY{1r9Q!;EZB7Gtw%K7BWH zs;QYoVSX~7#P4Gn&9BiB>~sqz<|F4~@6gB&?u=e?xRTr5`zI9aUEg>4N-S@nPZu(Z z@6o>`=mEc?KknjyU|7HG!VAIaf#K(Of)V~5XA1?EfjIxU!m$ITz82x$fxA9Q!tlXS z-e-l0gDcM*61EMVI(<_3co6LsBpN-K?g@#O47Q%CAj@^qPAl?j-9XDy$|n8H>bI0C zeO&Px>LUH^?D60%wx>X}`G#f@j;1zl=XlcTMkDP#!^;#%TFP8u`h|PO8fg}x$FuHO z7RCtJC6?;Q08Vi4+VC*$wBD*~HQf3>hbv2YTlyH6I(aR9&x0iV`TZL%Ch*bV_m^V6 zv0r_DxM14A$g^RBqXXOgo(fn4k-ic^*Fc`nS-}TTmP>_p1K-Zr2{#YUIXzbxFu2pp zMaUWq@;odo8Kj=Vl7n<19TqY}cdezGd`Bm!aiMJ1Julu%(d)NnPooCv*(rRg!7v)E zpR>{+=h)M_jaR|?IV96CqK%hMHJ7zqLf^VeA-th|;-G!Ju)fz9_wqFTt{43H3;PM@TKL!dJI*fQm-K)0%LIQd zvc%U*uyEkC&s@RD0s5Jj0?a_^=|Mr^fZFS^pl{&0=MSOv;4se_!r6n4r}ofyE3bEM zrUxrM+xF8LN`CD_dYAH5={PXvADDB45vv}Xx{vWvosh7R>8qK>{lomI0fRd%jP@}2 zL;L^0nt6-aF?uV^Y|bRTIu_zwHav-%z@2PNjIia_n|6jC;w>{ec%n5%ly8@f#`}*0{K%6fNXE)D~_*hM#mfuMz&o#o>MNPm4|Zv zlfBOO;~wjZPJhT%$mfXP@m%DUf_9#ydkcFre@ypXng^etNFv_n|LqCG-4Sq=Zs={o zF)GKH7s3qH=g0@5nQBYKXi=gjIW#-0Re}R$EqJMbaI^nlr;@OtOHHHKJP~t{Ig`Znuu)*xRG%>~S)@Ng)**L`8OFYgv z_6#ImY+QS~Oz7XTKvplj)cmURlaSD2)3{xj-?FpPEWF<$DSRMW(rTB57SUQuQ-q=~ zZ9ehQ@yFXiuixii_$?N)C&kO6_ufC9RT*)8;498l1$VlU_935o9HAZM@EI zPEKeVPCt_TuSrTilybQlA{3;&YVpE)OMF}1PzNLr+UCaKQ@z?gN4`w$Y;TW1r#W|o zg`G%ablP1zo~G}Nzj86%PG%j_o*p0zy0j`?C~FBSPH*WN7I-H8Mc4j|vofZ2(J#Eo zaO-M3e>>w)*UNJ^GtSGWoqdvlmhbTYnUO3H_FpdfT=_{JCiz-fDGyGys%&cYPMur% ztj;}kch%Cev{Y0TIsa^GP1XAhQR=tqh-7No{u-P3`DuAIt-M2NA8U^@AEfWCeL=mQ zo?DkgT9+}g{yP3q22OeyW6t=~;DQ>N8QeHECM@%ADF&2L>D;+idMjS7C7{k~NiRGl-SZA2g@XGPoQiy=84ZRZ27 z=Ui_iT_EQO+KSF+2MT6M4M4$JhPx`s*>_(fL#B|AgxEPfO#j zZOs=-2d~KTYa5na4$r^Y5EbH*|F1zB{I6h9!_%P81sfYD2mV*!-nc8!x*(`A{Nl6% zs4+R4i>C^I} z3wx6~^6HEHL?7~g7kvWz=N>PXu+sCzCF^Kk^PiR|$Y}+eN(B(3Ag}BKuCZ`f`7X@- z!qAGvaV>>6D!#|06**NZqSA{{RhO@~74=koh_EmEU5yH37q6^-5jw8ew`TQKc`>sl z@(Q!Kpr+&U$>Q#se<6E{@7FqBI$Zpx_DHZ_$?V$5AXLf9+JeCR!tm^0ia&+dvpW^v zfZZTVETm`OYql!P13MuX7OHbjmX;KL$jQl{Rx~r`d*O0NrT4aEl)7h( zt~*~Emf>EGD^1KuEBIa7p7Az&ap{Z91F4V8re&5V%`MxPHASQ>gRV_8@BO7@!a zaoH;RgYv^U!4!3QLe5{}yYeTwD#FQ%?Rn|gHx=3W(P%@(mjd^=zRClI<756*CKZ-P z2UZ%3c1QMAjV#h#_p4e}JSAdE)#+m2u$xs;#U-J6RSCr(uSu#ZN@iWnsnV2ezfxay zza;#!w(4_9cF3=aWXVh=uR@aYTFI&qrQGVKRFq1_wk@yFNDfNJRJ@ajD%Vv`mOL&} zSGuOI$+fOLn@USpR?<>$r;MsBPg|2vUwJnzUm&ZRls=j3P<1@Lo@uH|%5bN3R`qAR zCqJ&9ok=I|tG<$T6o03>Cwm#TrN$xqKeW2$YK|=KeNA2N<=B%ofAU5~8*AP2Qlflo zee&K$POOFUH$?Q;7Uo0YMYTQos<6!3Tls%O^J?E0ECYMa+7z6+s;`@0fV*m4eOpXW z9Rxh4+EZ;2Z&!3zzZIj}MK$BZ?G4PDl}Tf(G&NpH0VR<&xFl&_V@*!-=uA$HGTC2p zqvlO=m6%;?mtrH5)b36}^ZwLEr#xjB*49WUjHKF6sgtQ4b*oZq$qsdqX&z8*U1$1K zJg0tQ`b)5XZcs)wy1Tw2GYI8e|2k__Y>sqUR!+6xrQQ6HtT*~cPlq>0&C*GbaG z?B@|!X@Ac2aJuwG&c3ij>Cc?l(DDY`oV;uI>t4o>Q~juWEqbQG>+6dF*bRRbYY@7;f(a4 zc&VU88YX6N1EpEwKdj@@!6ZICu3>Vr9p!Grkz^_9T7xjf3)<6gOEMmRxN(u>E;gny zDpibr+}N778+D=aOWM=e_f7WcU>;7>{`Ab~n5HY~AEFL4(KEJ2Zg0xYKwm%H)R2)K z;n!r&P=%wK9%uXtD{dIz532JT`uPoNFcifvQmtxu%>OD|+&Em|-n_qYnV_<^xbdWL zYI$@cRv24&voS~5pVQT-5IJScZG0laq}*>BEz&3cYFZXQU38(zBR-rzp(!q2$p-7~ zB;?qYn?11M}KPFATdOJ0Qo{&TCXAVZMfx>E3)D`<5Wy0fZVQ9>WhuaSrNkdtj1vTwXgV$u~Bx zJuj&=CaPVT^gf!_emi-3RC4>v?F{R$bVeJ*j;$KnR?L1|0=1bqXY=uG-#OZ>H|?{zE@`dpTfr{OkK504 zpC@{@V|g1zHtp#=I`3P16Yl|MX8TS4945MBIKPBGs$-?VmU64ZM?fGAc5sE$p&uPO zVHF{ubAreN_qg*wybU&{lNg_Z+1^r=ylz09akCi+PEDFjKqdHU~d1U z>Zu)X!4Pm}=M2`+g5u5{tmvHiox!a8=|4L8?7b4F&T4k1IIGjl{u=My`H8bb;4YiQ ziRZ@3mUDVp{W1^kJVt;ln#-WAm8EhYQdY^7yyIZ~d~4n-sJUw!pF(i!!U|^N3|*xH z88)HIBwU3#-}OzHiryrjC;WlhB3~yu8h22>M?{PDk)IOP#YD+3i|$4j%XU!hwPrA@ zf1K7RbEW*&ddWPgCl$6b0=26>QdUCS)Hp$Qlh#}_t!os0Ls?mu8@;x$v+E+mDR)Pg zfRUEDu&a$ZD%H2^5%Y4=4f$B6Iw4i=$eJzW%lEJ%c+GMjRwHMoJc9L;nJee8chj%S zOW65f{d_HF2$?Sb#)&1q>|V~D4Fz^z&!<0rY1LaH4m|4AKPp548O$}MW{_MlD3+un_$v9cVyGw4Io&Ug3FuO~n1eonuc zn5P)a*euFcI5I?honk-Z5!Y4W%UsOrR75k+GlU8Ovx3G}RIx{Uu=`P9hB?O?HKQk=FiJnIClCKeZ`YH8f1`WZBPHxt zF6_BaXb0=(jD~hJUsAe3syd-En0TymmokAkSQ4s~k$ek=D&LXrWPel5A$wP7wC0?ob2yyVO?HX3lN(4C-H2wR$OSGox6&l@>=+s87)} z)OqRv+CMT)9Zg?D8m$)7Ga;Q?##l_qQom;8;vvm6<|G_lvw<0h&D5M=_F7BuivfOii=jZs)BK^Wge<{d}zx=RX6@y{a)371Y(u7 zdJ#0LbglX%Bq%Vd3B;K>J?bK2PUd*EnY17^L;Zu4nH;K_O}0&p)NCh1qEgLy@?*hV z4S}+oTd&EYq_E>PRg_yyu!;_K2E9acmwJpgQuC5Zr-W<1Q(H-&wBxC-h!t8F+DV9@ zJx%K+_-P^fZhWA&lwOJ>X$=fpY>xIOV>_l*`-*V|{ZXBVVe573Obl7CQ427!`fPO( z#;Dq<)?<&zZmGXv`&zO!4!Dc;cQqck&sFIf3?3@&*Ax=Q6h><-1aWQznA<-mvt8>5 zC8r(N9wtssS)h#~lEf>tiNr5p|Jhd38NoyC4N?mat^G-!%JBgs{O4G{x+UZ+23og+ ze4BPlcbYPtdO#OUaVP6_SPFr})QKqN#8bLD>NLnjcZbR#xao&eKjBa5U1+CqSp6;< z2P@H^q%~nony2VRhMAg&=-GzpnqKr6!%)o|^hH&fb`tu2*HP_eOmOQ$Z3yOz^pZ9a zOR8R_?ZQnc3)8;GNs6ZGX5km*P1Ehg7i0zN!U*NGhBi&FBE6+#>Ti?hk$v?a z$sQy}gAJJg{V{-f!O#%HVajpBEJHY@6Ti(srdr|78AMcPY=UlXoWT&Jn-$k>xTqT! zS8eduIif~__2=DDq^@pV9C~zXwk{u?Bz>pr#VoAu0AnSU<-_zVuwag;-Ww~+lj>=> z&Dmr06}X1iCm1fGUl#8*a4=!{;BN{rAF^`|H?iRv+YSG)uTp0i7vL@=I~n)k z`V+4jL-4yruZ#?QxqxLXCfM>KjB>&iPMq-`LB`55{(#0ahnvPiC+V@K`A`aNh-o8q zgVJp}K%7YCnobkO1F)Ix34PG&h zhBt--G1Cpt4CiCQ)prfFnD_DoLscxM4QIF$H?HBPaa3GpjnudfwW?yc@f@nDxXH*w z@5t{lR-xrN^NhDJJ2N^>R+!GzG?OFNExFco2wRc()f9o78;>ywaZIrOd>!sR-^OIY zyK^U+-r)<`o6KYI-ebKHcA2$N@=xWvf>q2?8AG8LdQa+1IrK65fRo4%q`(q@9u ze%q8a<{cQS7-bH|{1^Y%Ovj!T=9-JK3O?7Y#?9rXnV;Y=>>kSyoB`~OIu}2aQEFL- z52SCjxZ_Kxe=L{q?X7D|DI!YKy~ZSo_H18n>WO~Zm~8qO6HyD9XUF`gxM|)K z3zdk?VR0i1O3g`el-#lA4%G0>TJtj$AuZlA4)ryq(y|I2BK~UeLf=Y&EGW!Yk)tIA zlP{QLX~J6b7FhbRo}8nWPuNmcQ}1}}Pv*Mb#kehWMek-Dg~sSTfzwmHdoSU~Qr7mO z@Vm*YdzpBMw7WMA-%LE$TZ#VmhW{+PCLY0Peunc>9Zn*+!f*?#8#2=h2AEHunc&imf+u`S$^ zUQrZ@x2JDJ1cvvj4;R|Vhx%S!b>e^S-xpFR29fZ`!R?n z8}1I~7E?U^4r{1+A$c;(Y?k5;>}<<^^hZvJr8hR5yQ0@OYBTq7@9l`aJWk)qPzrxZ zpZv;Ceo_D85T3xkpBQ{m!0R6j3=%vZun&k8t{n(CZxoUSa?foQwhr9#uNQt99P1Y% zavt33>nsWw4D<;3)kj(osf)5{Hi$9>p0GISM>+K0VT%D3%%9I}_s>E97NS76E3mEP&oQ|txl8&`h7LE)N|nXi+i+T`nv3P zTAu!wWEbt50g9gmRtQ_e>82};cjy}!VWv=$4|A{SG2V_f%1l77Vwo&s!QYRRSh$fC zPHeADxP)ulTYAmNZS7ld#hvHb$GY^9*W33#NXvKcKX|bpWF+yz8*nan&L0qX4%nY< z5hM-x_-_!H2e`iPgkuIed}@U51CPDg!mz=KXJUlH!4;>m!rH;ZUTopOV2Ed)@HhDV z;s#@<%D%Ij;j6N3Yh++mC+f~Is#SHRJjNgOx?DfzN%f7?9%i@3JE4iSMx*CpSu*Wz zrWJdG_8nzBTLZQPE##cghhuU$_Y7{a|F}Dh+oR&SgT|i`EFNS^3)S%6n***c=0}=8 zhqUsw7EUmc|E+gVpub>$Z&5%P_=BN`+paj`u6#ii^lfF`9_PD z_ci%!5bf*x?LANA((iL-sAy4tiPtxgL;nZQ@1mUplRTGlmvs%7d2zSP?sc%Z=eov9 z$=vv^)8((ZH@cehZ}3*gH)WjVrO0n2UE*7J2MXQz0o^azwS29DOp^=t^{fNmZj?R0 z@TY|*mCfiTp+%J$dr{=Az7pjn8r1BFfZ~s8Z9<>M_iBr-5)xMG4qe`tfYZIWv?;-; z_Y69kXs4H6%un2ESaIQBVyJ<0J|?l$(0XoV;#~u zOfZVQ)#55+;h8sLy-{~&mS|1Oi>_IsEiHAj3nH(Un~minLhID3-J-hIkfM{KpRISY z-o~G3yDS+N-`qYS{&~WT_H15wLR5z{laz3$LrtBQxWAK6oR}z=dEmmt+qzuPv&G7; zZ?RL7w#x5BZA+4MXGWAIuTgl1ZBOR+48Jxu`EyU&mGLS2l`}&eQ;14-aBNDm@>}4Y zl&`827yTrQRqTKXk{znP^WBp3>gnfL5}MlMEKX9TzT{7r^s1?TDU$o@Hs1otSM_Tj zOOma0QP+p0srAphEJ=>_f1BHq_DY>=C`l30sFJ#*66vknz@#q?U>oq{{SB|g=;VS% ziEu*l@1~WUWhp0`TIp>m_05;b&5}7SPS6xde9I4PSL%>f3#uv=-&P&-AoW{26y=`g z-Ek`7cABDdNLX#UV`srNY5En})+_4t8d=e0hxET)V=pCStnR`DPs;G`Y6$Gg;C8*g zNX=-HFAng`cp~??a46%aoO%9m=45%zxigu|<+sj;Wge9O_0LQ#tkTF;spVBPxh%D@ zirZS3+E-OqSCaax>SNijv=!C6^TCd~)zuk4(`swhC4WpGR-=vQrk}0F^BU7j>n5{2 z(*M@w(+*~wsrMsgXUL>;3GSIr(l6M}nK=y_R9M!S#z$)}5R+yp-Bb&ze_SDlN#`S^A{X zE-SRmrSM}`URh%HwycNcHmSR^7nZXVpJs1O2LF!SRM$m-`E%8|Q>16r?u#T)J4GXcPte6g+5D1YIcj-1s^0YT>A+ zxfh9r3!C-^)Z{r9&R3xF78Tr4gy$_RFn7A;Z7TTMNXqjrTvlzHM<|Re8JbsFXvhu7 zdsMV4Ju-hzQDL%uzHhN}{IUGp;x68Q`QJ;fvaJiYmJXwP7cff&6sv-}Wnjmp!mZ`g z@zV>_%RghF!ao&SlwHx~%9NOIMa@+~QQwQlRnLu_RqR!r5rHk{)XWWgUM#B-hh8au zSM%bUL&?nAg;$=JY^V*rTwUT-TOE>H5>xx^QhAA}Zgg;aNe$T7_*O}Goqy1XqMzQc-QLDU(+8ByXK$Q}Oh? zw8XIDllk+7(~2ee9oz-QuL{mFX(h`Fe$bptq6?X1yON%wqtMpUMa464#ida3Gq7&! z-I6ZUtg@}8>{!P#e%ayZ!)1oD8<9ojw&i};XO*8Q9}F)lkEz%Y<_kvnq0rgoEfrl? z-;_V9_UU8Ut24a$k7Wf?f-=+c6WtMX%D zoL}7XsPuM*v97T6Pv(^J?lQ;Bpu&S?$1_{Ay=e4#g>R`RgX%hg|DvqR}v8Vw|Z_#(X~(2+e)5Y z{a5W>I{NCw>afyvSC&>2O9L-^RnC??Rhj{-mD+L#nbe5*D$<$>sJtx4j}KUz0jB4_`r+m(8b@xG3l`iVB9t}9JI z#?)Jnt-|0MGqX0mii)+iKO8kkiY`(B!xy(o*#<Bfs2C8;cId*joztr(}Km1!?g#Z5u!j5yb(w2Y}Sznc^p!O@DQ7a8?YDa}JOheYz4 z9WwV{PjB9wiH@jlKAD*ju5S*?)QA0P+%G6oKLF&a?>24};8lT*UIMkurx7KzZzeRR z3!&OajVj@j@`}dyqP<0SP18g)2svM=c={z3~gIUTEMF{PZu z9Bj3dSfd`a?v{w-vRi{BKVw6{2){?n=GM~Gr05N;^3*3$yITj+7DRfsK2JM(J+$>t zT5Lpi^K)*q2HpIUo2H3tzQ<*&y_)}VZ*`$t7V_L$Dq0Tn(&`trp!hbG!&>tAp~dJH z1K*ez(ej_bIrCQQ9057CsCBnsFiF=MEL@zhsg*5^6})dP5}LU;TD77jtlzDlMQIHG zw)ye1sju2j#3zwE+Gq)Di0y5y2@1l)wjYV7@cY|c#gnn}_E@n3bEds9$sfI>{Xvp0 z?sNN}zd!#ewmw{?bOcY4Nv>s zUdancS=ipoYf4ON|G=LlI?`dwKf~YLv65fIIp1-F|CZU&5hJ)pKhlvSxI=a5&vmH<;FK9i7(9 z=!T=6E1B=B4|RI8f=dTFDXcpMk2=fQhjM&7d)c)auARR*(O^~xhJz)L(?D$z={ru+mYq14#b-W~|U4A!S7X4Y) zK%1zWAZw!j)s2^xQ{QRhWd_<_#SYn5T5Wq_mjiuSV^ zu3OAWxsZG~lb9JOcVWItO_iTy?Mt31$FR~8Zp($N*FuB5lvd%DkXSCbsOIa~{r)!oIrN?6|5U%ESKzw>b2FX^#afr|0;7isB=b&O*v z_KFjX%EU)toPU()o`TCf4c5=EVCHe76*A^i)*r=f)_kxX;#byHnx3wd`@ zj>-o9=r|um7}216tGGt&(!Eyr6YF$o3Jl4%2W&4xB6qqdG~{7T4;A0ZtUBwSg%sP0 z(w<|K#9~tqj%t^GuBU)1%J%3n(uSsUd%n>kBzDT_w0`j&<#zh|`1?vFqjDneFW96yMV95PR1qob zGon<5l>AgHm6>XrWKeyjMke&CXH$Dcqt%;ei}+ZzKMlp5tOkp2v0kXDv_Fi8>J+*w z?T@;a&ZT;*d+0`TH<;mXP1>ve#t0&g)HpCc5$LZDiPj6Pf}IkQOZ}UTln`fNIjAe*|Jx?f$*~) zuf7bCt2U`6#4)8|>TV*haE$sb$u@VWW)g{$xnJW(9+o<&@gt*?^ED9p8CX9ji*j7_ zNYhEF5}elDp^o9c(fp$Nvo+eW)HG(db`Eur{y@8)W=q?qJwWrKl!DQICV7SSDosj! zq23a{wqJEkvk3=w*VY8#ZngAkg!mBYBuyLsTUDRtB>^fMr=1E7D=gP;ftb0a z+Cbun%&%Gj5lZ7|>xkb|{IqvTA>u3AzofzVT%99%tI%GzlbptD&;^jcaFTTd%63+& zPDmjznsmh!DSd{ngYu5b)ETG_lySO;)T1Po?kg2f6zQi?A3|aJt+eBWXnhc^2`|+1 z=yP!m`f56aeW>rGmtyU-M=*;F$F&DBa}3A8X#aS_HmxV-lB!>e!#wW7X$!E|T2E>F zu-~N;ofVE)9jJ50+mz+%yzrc&!#apyn|DN4LSSX3>-wM(>8`q85Kb~izX*DlG+V!) z=$mjxA4cpJ4uW-i7V@L@l_Wg(l-^7-vd`*Ykf$&q{a^AC`a{DsGM(mWa3*(B?i#j{ zKaf)lCn@ttfriVJ!^BMnI;9laYAB)3CU_YPR5~7Q_(c7P%QFt6Ex_K<5m9~dGV0Jpg4vAz{o znD-K_=QBThn_&_@J^hYhBVnSX&TxT1Nm3e^gb#_M43&_Nh+*i3S_DppkHqP`vBq)4 zNX}H_QeqElvvDKIhLLP^C+(w;F$R#B)I?)6Nk%ztB$K|8XBb7~WyE*Je6kPp$|xtd zLe|D76eq$0(+G+P?{1n+QQ;W+$~cPQnZ7&@ZFs8Bj=N;IuWyZOQloNCh+D3f*5hUJB;VE74WO z?~NZZuKB-B(=iP>UZx$`^%*}+f!NB_UK1PVnEb|6j!O}*F!kbX;%iNx@DajO=E-;y zf2-Mru!4Kge1Je^UpEI6%*X?M(pPzp7}+zt&=Ld`njIPz}u9pYBf zHuDGKHR3UgH8ByoVwp?)k07$RlD6Z`#^#ts#*0R2%sk@-V@Zsy(a+cw6Qc1jzKD6) zZEKnsd#QbxX;bXS#t>6r90tsv7odh!GeaKVx1JbGuPtJ`sDdw!(~$ zeOo!&Toe~mqBfi3eiYm@|3by(?yxLE{mguAIf#x((^w+WZ&F@b5;49>E|yk|KB38S z54%PbVEG63@^!n-A8KQunstyQwL? z7Q!e>Z0{4oR&q@5C&G0Swa=Q6OU&q-Na%+;`xe2!VuYW+e%|W;eOOyr{ZG%Wz%l>7 z$N%vBf9mi5e*N0c9rkelLx;k!>IVN3z`u*&*-`M%{{KGye|m0jZx7z~|2>8v=B6-t zu$9%uG4*UKE4QA)yH-}NnUeEXR_o)r)2yu46+^aGR%>rYE(Kf=6mMmllm zClr(gl-%)N0qE@>0&Cdm2FO_tG`s9s26}UuWIrAFdNaijP(92V5Ye`h0baCPc?sbj zg!2)CBdn}eJVe-rP=YW9A&3!pbv?ofFqgkaXhc{E(@iLk0?KFBCj-s0!Z$!OU2+|0 z4&gch&Ee1@pjHsM9ca@9RRAvV-UgJUxT68*?{o+KD_n;IqL+c_uGnpV7;xs4eBkTn zFe2ap;!BE9j4%S>A%viJa10V*XCx!eEpUr7au&{Ui0z4RIl?h8m%T(Nhv_;|jsnUB z^_f8V^1{zR^D_z1wyKM}2B>X;T!2nf)58mtSHU;$KY&Yx+@bwY#rA1hbkdE*?!i@+)rCM1zfujLIEdnB0b0Q~W?q;C&GXy-Wu#WTsYL^G8fvPy~ zvq04&_iVuPJ8_`T->zF>kITXVuh>@rZkq~nRxi8+j3^-5E3hRFS>IfS%{>wSfLR4m`hXBb5ZEAgfFL?R`C&Ow>ylm% z^sJmvGzw_WlK@rDo?K85%T_`jK=Z;#(BIN6L63o|2yZ-4WpM8S+_19*crm!f0ERDX z1za&7+<6xLnW_i0i~vd(fxH5OJOQ3UxD@6>kZC|9k_(Fw8-oy3Drlbva{*FO3lPl< zQjwNx2zMbws?J3$2T@sZs~$vX`Q{=}U&}fq;8>>sE~uHMOCUJ56C*+2jx&Qk!7=d$ zmA@$2{T86r&Q9Qq=?czw;lgG2fX6%Y!JThGk)0hNVZ;l-V~8&#`wk!sRNq9&%Z#k zF9hzv^G8O4n9sW#JQL^{^zHz9{&;{&o3mvX@G!f?71YV>rOt;y&&K&6X0y0k)dmRi3V0Raa+ou~`2*G>1pa`%2Ill{2%8b25Uz(g4QZbS^Z^_BbXYn; z4qt;`>U-gOE?NPUFP4Bf%@5~df#w?!sKL3{BEd0p9D~8x%^u@zfK_>bXwTfYYc}wh z;|r? zG2fi;0`7F+SXqs(nf3v2C+uxh7wl!!Hkcz-2$5>BF#xqMY}`RF?jvr4-Wl+x#k5(& zfju*QII!omz~4XYQ-%?NTFOvhFZuv~qg}FoD9DAA*ANoi+q@h(i0$lq_2BGhIu;!U zeb6M}9z5kUHw)Gbl>*IkB0+VHyBT~ID6I4u5A+y4LV=zkyJCO}nOl^V)$k(cKUP-5 zUO0fd80Is5CHTsJd$b178}>5fAvnS?Bp94+x%G26w${M5OR)M3ypFSifZ7xAarP{j z3zorLlm^og91YYWuR0@rtvCd?xH!QC%B$qy{xl<{{y(_CB5>Sfss!ZO7Q-zDngbwE zU86lBpIKSi_yk{r75dDD^>~1@w|3mcgZpq3!d&hE)8RGD>5(I3a5nx|eN1`+x7mTn z0=0OUa}ZVbX4qbUs9FRf1Y&y;rV|^cGt&189BjM9!(8nNb1jHI_}*3t6Da4(L2cOC z)&B-j5fp*G#y^$30lr6YYk}rjP$!6CUF0WlXlF16euvKrm>!8RcOloMTZy#<=-)pU z0%~SY(gOXp@EvqaQjSw$kf1k+*L zXA4Y^LYTXnhJz@%$tRBm`Y+Eo0`%>hvkU0|U=Ok}cBTWkRzM{nRpF?BZ71Lds0DW~ zpcd)LWddxk0vQHsO)%HR!E~Jn(=8L`Mt7K-+F@=%DrYOwCs4jg4)QuKKspjc`$bU* zsEr;8$c2>^7x4#yv$L{_0-x5C!x{z~9wo ztbx^zWjoD*k9FP*bH#j^|648MVGX$QfLd@>0ky+nx^=?bxC7>EkyHDEH98_n2KT z?Lo%f{wziT{WVS_fc{Kpkfj-sD?on7es=+91b@ecxdvnvsLhAzifDF2K20}XhFdnh zfVl;!(5*LNd;2PwJ0O@l-^1L!9Oj-tn0vw95q=Dp$&q(Tr@_yPfDWL4JWMXq3k0qO zpdX1{a5ZfEgiQlIdpvRgSK{uWOF{NG%vug=e))il8tAvI2In=Sd2JTRYUp}@_#H^G zSZzS6V&h-9Wiub^08t5oxjPf)9;EX3Im7n;lQ0j&z&t312|wh> zxk-_C7LnkV)afv}$Xx^a4%<;KFoV0M?gjcu@IBJw$FgO>$2=D%(7$CZ7u1Kf>tgVE zIBvrjaF?;!NCW!cZAPN91*z4oci=v@Z-==9WDThO0dqGJ=RL^h?p_t#vJc7B0Xx_} zxDn=|XqbnA7b~kH=`h`qih?aUqENaNwu?A0Qy0SI!uK32;z*cLyC#A93Labl^6Qi0 z{2C15Oj(l)d~b7G1oQ`PN&))UZ@CBbAKAtR`p<2@1?~s?JHwz`MHl&*tWgj^M= zYharPu1TPO)`aCi|LKL`vp4v|N|1LS>3R^!qpq95y?Xbh?dyU5B=~#KipV`Hf&Q$$ zAht6N`z+v7+Vuc9>;Dr&y3vTC49wr0&S1bVM7ZvIPs`S#R4KslLzHOkI zj-J^CuD;#;eV`^cXb*r&UQv6f8|eRZ1jKFDHg^!W2~RzcC>=co_jl|V%;TOgPaxOe zNrb16s`f;p>U9Es_4F2)XOPHyBf0Py0k`-d73~XDSy}lZk%q1ASumwQABevcW-8JP zZ?Qe_NZbkEL!xLK(}4a(JD!1FzU%`%AH^R6N_Mxq|38eqd0bb;8^??Lii#-6zVG|K z?+A*50t$)(3IYl$C@3nZsA!;}qJ_C)p}B-5?qP~+VTq*{mS|$RXKIm^nRVaK*z4Zc z@4oK6ulxPu?RdWDJI`mHd1lU>nRA9@`nxWpX%WtUi8ia)MEW0thB0Ma!?%wmjo%gu zlQV_mR9VI=YbpM6WP*<3OX0*{gsEQ$(^UISpCjo>lZ2D;8&o|&hH5GD|8pwxkEBU@ z_h-V**@l#0b%09;`o{-cME~|kee_4fpmySrxZlvfE8!#b|1vg1`s-v`sLQbN{MPEj z6k5NbR|nCy-Da_=vssRu|b#7Uo3rB(U~}EY3j7Z64XQ_SD^o9 z%D1#ew^ZWJ|IKs{^zWU7x2>%vFGv5k8MK#yV>0dE_E z;j}_wu8Sgdt)Y>(RXAN;BW4&&dd8Q+nM;K7IX7H*q`dzc^gnav{LOC#4?_RUVRh(# zYxG+5|CqEL8*3(z&%}asT1@%u%uVKA&9t~1qt{)nW;e|IPy$By_Xe_2>L6uvXYCDXKPF>{p zK@(55a8)0)|8JtAkXGv3GK@8<}?;A`cxgB#)hov?scN=LyKjr4ozYz9Pwp7%( zQq$PotEjx~N}O_Jn4-NRIntNiRm69scPTDWRBgp2Or=$CIA~|xMyQ_FwQPs=qdqn3{b;MgyN9gpsBDs)OZNh1dN~3@yDrdi-i$9=z z|4E7Mum(Le|5}IlJWkYTqIpjR-?}xFe2vcQ`NV^(X$IfAEJ<34lHX$-;G4l8LKkNS zBi=~b2i;>5QPLQE8z#HofLb!&VRy}N3jAmQrM7!R*~(B1QdC~GB}eYyRsUnF{BJv7 z9Z@x9Yo*cx4VyN_dc_rrs*E;%lJ?wxu>)_vIQatQQyQpYm#1~rXs)TDEKV5}|Drj% zgi<(+&Bwm|;tcB0?u#V6ZRZ#>6%7Z1@uh9FJ2}|=ZA%NXIc-Q8Z8m5HK-vQgQ>1T_ zxmLx`6>Alha_d-?HWgZt7gV+L-wMb)btGPqIAEmvQs^<@q9`AE@*kA%Y9Q{Mjp{a{ z`B;q$nu{uXp?Op(XWGT)$Dnh1#v%0VPr3xV#gw3DdB{Mh?SVS0^S0h_g&~%$QnXe> zXR)H($!xr&Eom*VOff-`XyeWk1@MBRDwoAvl^&_6D||h>WPVDe@iNM1T@>Y8o4Voc zI}LcuaYP;UY5z@)51N-%qRnZg9<E$ zN~_-*U6ZuY4#iyNr^1YUCGB*l1>ZW{Ya(v#yEhDzNUozlu-;um+RC|-ShHv;H9>7{ z{!DaMWwfJecM|QwMaJ>AM2FEUqq*?nzzVotSsbruBQ$)bcvx|X zVyq$xWZqj*#g760;)s)|)qlc#-avhn4cM+v=>}`*hsw7OKer4ZPOdc#!P{*OqtN`S z?kL`ltQjr!Ug?bHz)}ZvcH|T7#?2Xc-so~NzcPFta}kDxpw{3650o1C*;3p3w~hA0 zx`D)wzKREZG%%~8TJHa>w)o5OA+Ho073a&`-w%q{2-e+_h=4x9(a}DZ6r%i0>Y*titq0?W|gFltoRaq_W zeR41{Kj5XTwhYda=MVJs;YEyfLSkpF=IdYlPg^TfR+(37HTc>ps-v(%v^ZOz#j_Ae8)xz-EfD&wfJAg>J}Gxbn)KACb2tQgS~6(u2`;JFPR&zNy|ViyZ18FPNW7uqMf z-0!!(Q%>){`iXC+YJSJ>duh%T-)eTjMoHiIP@CE}5Va0{KEt^@0FBw z(9Y6i)V`O$4;2S8@lF4(GSi_sbA%DIoK_*=#HdVVu# z@Ze8-#&^1}w_a9T43GDifZ7wX+G4(^J83JQZVym9M?EKTR90IYyLQDYPp))A?REA1 z&@NeR@u-p27OxkS9I!x=!$P)gIfW$ZoSEwahff}botwt!my^3iK2Rw^fA_=wh1o-w#p~niL7i|@_EkfVb zLjOL(0M%y&{w!&H?$yG127{WYL)~W$)XboZb$5x1JvGE;zeSbQVIS|(>9Sgse-5>t znGxL6K20XJH9AIw_aeSRyXp>NBoZsVvt5&1lZ@|MZkBqpv5>VIJ0b?P1wyAXq05^> zw;Z8dxA`@7j@mk*ucy%Os4#%I;Qs1@FxWvDLa&U?>q3-wYVno!*c3@r-)x|T4X~-B zY<;b2sHGmyE2)vLHl@X!dOu%zEi*xWm%O6aVdg8x>EV-5Lo>8_=2`QN-A{H+M2V3+ zV>IY5XWB=X92fc|)E*OhEEIah2)#RmzLGa{V8Q@Az&)Yrn}St&L%xtBVNt^HRl*2W zQ$xvFK00r;gb*iVn((9M#|@ON=lZ%opwO8s&>h z)S&+@Vg7I3!q8u0=!O16HtFbJEvqV_lRZq)|B1}@+mG_4u1)s&PegxH05#e5bkJn^ zbujhCxhh)1mP0E+XV`%V@qj z)r4&gjfO449h$;gz>k9 z3G{!=QGYEQqsle*hNP2JI$51RPI+36wy0j9NyS#fF*&kBMPZHledTHWYV==r?1O$k z@AuLFc@W=>(~6jirhlR-edxWICFsu>Nm(2$;wTHx*O04j)M)Cu$DDZ8?h-f$RZE3q z)(Xd}<4J{*PF5<$QG?8!tCFU8OL_txV9rd{+Qi3_PW@Dv_J8SDzi(14wBa-PZby)? z=AI7asJtdm5SBjjC2kAGguadbhf&n{I4@b#8R-!BE3HmH9?yI2Ogw=8d1IYr43gx4 z{u{~U&~wE&W64j2fW~;GA*Ef8OgJx`xK)_CNSHQLm>waVq@#FWIJrfbu}PRYML5Mt zD4!PPm!`KQ-SDk&$LN0KR`XJxWvqPS*NwTnuHoCzKU-S;6wOhbGcGML68+DnP#p?>wEoaAwG!z9m0m6ggdh2?s~&Ozbp-nl|3Uf(Qh`AQWw0H z@Fw~_lJW4kl_~$Ce@*Ho^sk>p?RW=IMyI1&#?LaE$)rZ~tfy?`>eoF>+0C|)yt9>s z99k3esj4TL<|FB8zYB9!Y~-oq(>>(K^asKj4Z@lDie6B~QvNAP%cn&tZ)%kEfzGy* z(7(w4PxL!S(?VC;j6%=C$fQH)KQU1g{gWr5WZdb@Rp`H*O>SYgr&^(Z>on9l*5`hV z{_}bB(f`+UBC&7T^gkr;8Op;m(CR;bp8oiquXrSa%^G|r4KKgOU^zS#mCUkpL9e2Kl2l1Bs>2V zV^yC8v>mJ~B_&rRt;Qo73zd?EDz+De%kf1jS{5&qbeSrtJb%P2exzcnaH;ac(hf<> zs%}fWH{Uk>J&ZPWAZE-#^tYthpuZxEdR)0G4=y}XKn%|cE=ocFAH}oLpTA(B^y8(( zSopPtc*Ez5MOT@9F(xZ zJXF5`%^SAeL32&@TGW16J{Fz#il>U&Tx|N(rcp*8{dhd+eIRNG953TtZ(V0pc(t2P zgvaHs*K14nIdF-xsA}FTTBVg=y@*Oi9!jC7DwpR$b!5F_u_AeKj%v-GMk+1%Zv`YI zzcn7^9nBsn-_S_C1|-&(q1TX#ZTx*`6-C)S zFZfXw&vIv!ddA9AaGut>2Czr>=h)&r__<=eVwK_y#nFl=;G6+M_YOrB@BgiUD4)B} zSI1R}+yf*XY}}fR@-5AND0gohhUQ20#EkFpZNH&;U-i4FJyxEJ&i3LmQJZ@ZRd1xN z!PZ~#f5OTr>fFQLkLYm!(V5b@?~x}w+?VNQ!pt7{-(AJKyQQ+;UHJNWCAae`y-TrD zaf%`_%{exT-Gu-1zR3=CWVtZ#LMx>S2xtyLd2{0^lo!{pMtShIzfo>oy%)_6<%Qza zVj|yTMeb?z+>_OD_oM{s-|fdJ+LGI18PB0c`Rv{3yP{NE)^=Br8rd4OtF*D`KICtVZgN3$tb_vj1PUsG!p0Dzt_Kw=EJpI z4?H(i(_%cTu`_C2d@OWfUwQV{ z`9aS-cwSlDsaURvRgTlzp^9p!SCamJc;AHje6T72W)QB5Sc-79|soqra;2W@h%i_WwY*lkT9@|{znR*?TwdFspQU6;Nv z!y+2G4Y7rNWX{9!CuQ+-MOBK|&+9p=tMTjS%N%v&+yB@1O;Xjjsuern9Y*TJH_BJH zPDlBTW?HdVbYlkIzFJ?0@`bh9D37YfbFOaX)#BA+eD0i*i-(C;M2=oQuSn6{$te zq5Uww(x!MwakZjq(XUrqYzE4a|K2w_EorZ+R(e^FQ_VzdUl8qAej4yOmMrpr$|8Z1%g*(ru>5Duj*e5R}_=>rKwq zN|m)zWvx_M^GlBVDE1Rt-B&!SxJFUcj#Yq4t8*;xO4?GLW2y4-__?)IlsD6!Tt_v| z#oHg%<7X$QS_d?LS$zx5Ysx=DZE^7>bk5JyMAhyzdQR*637l`85Jg>BUGU!n^IU46 zfyE1~+|_duTQV1DS*h%%E4nLo5n5bRBrZuWR-{HrTMPg1@0&0amdE`>h;+v`uEJiZn?c0X3*72E3akI_7}7@gMXdBl~~!t|b^ErHmy z)QNh6#d3dY!NSl5ADdsWw1m}qM85fCnbDN-1ner5Hyq%*imGohi&kkB8>a1&Ha*DG z$z`ULsArlyMb&?#DXl~MXL&nO_l61nH5g%1A!oY2*}4Md70okIzO!*D-o9D?8Or@? zsW+QL)xU^`%ZVH--Qs&Fe354hd#3A(s)S7_Sr*+5i;w(o!38dO)YM3xmNU7j_deV$ z^Rg!M#Foi0MWyq<)fVM>W4`TdV;qHVZx~a%{hMU9WssWB8{%SAfZ7*E?#$}_VMOej zH5#_ywGde&M0soLn<#H;CT{J|G*Twpd-cSLjZJMhn%7iIBp8(Q3-j~El*MdAo+k=7 zrdy$BU&3B;{WV%2#>+jA(KVOfVS!~Cbkb{Q4EnsUo6Ox}O2hCC#YB92%1{g6{$S9? z9A%r#glV5Jn8qEanXI<3(e!WRxK95t_9n^`-6r(ZeJ5zvxv-ZjMh| ztNGu_=J|ZHvypaVy}$k&esQgK1b((&*O@%lm5W!+i(irJ%{mdOl0|M0^uX zbQlZ`7$kQru6i(5))@6Q^i8=3JJt8S&MA6j__nuRG`>xe8OK3mhoE6d!Vv1-VB-)h z86O+c7fV-kPh)$6F2}78=~5%MPjvnzn&Whi(I!Xe(B52Jqn^ znkl9Ay2iKpbxHjVy!}Qkelk6{t~YtVD!+~9x$`K!p;jL8tbbkR2=q=Re2I#-=t!s? zfai1g>@^>EBgnl4cj}n>xlEJv5kn4TcV0C%zqwHnW1kc*o+|pcB~6 z88ibO_XZK?4qdfdP|K72#K%+ZAfo)GJcIB4$-s?VS!WI$$rY=g7Ukj>zqW4S*Grl? z*V3tRE4e`Ucu`JS^`qx$qw`?iM6^sur*t|x36yKFp3DIavI-d1 zGhTa+>v-+110P#;8{#ssLVv44+dy~CnZ|#}YKz(XvL0+1DXT5kR|e24*%_!O3>?&R z629tbj}-OHii3Lc=An9iXp^kAc<0J$i_a^~WsG%}Xj(8ne%Y5cNlu4a-y>I(=2cjD zw{Zu`-RtSw4e!)uqWSPTJU3)}`E%4Bn`eT~pYn)P?Xl?@%(350=#UxI=vkT{_g@h( zWr$0^U9O9aQ#GGhxtl%LoT-1^@_=R+&F^eX`clVsVbT&DW=MN>S|`1d%W~;k-G<9L zi-)$Xvv@w2tF`x98FToW$U2MPPFZIO7$KwBz>j;74mRwLA42AL?efcuqrr>%Ux|%LwRvcMxXuR63zyUG2fEL5KyB|la_!eIy-?=Z6MOW#+k0trrNQl< zuL72sZ|>3Ny4}XJ`*W*I`+nUg80b4jcWdi6!g)kD>eAJ)>jTtw$O?Q&-F`}ujse7$XMSX-xCY{zVbROmVCm5zVrm>#0UK1cVW;NVekoIXpk@r z|DyA%Fj8Ci-_zZ7l8(M497Z|iW2oDDln5zo=DR_M8_8wBxqUtHZB1>ts9lHEE^W(+ zB8|{_aq^42Z3D5G{;pgL6N4P+HKIRr3rEeDa%bq)*_X4de)Nw(|Am0-^f-kVH>0Uq8AAMGi47)Fkq5oi>b(nBux-fQ@FpmC4J~~#dr}1-n z^M`1TZv342;;H)v(?e_25>Xl&>k@>^=^>e&nLIER{YPY`DE+webo5X3qF$pP`_nQ4 z{s}5We+YHWd$eJA$u2hxbNl2 zsC&YARSLOV!e)2HS3+5pYyCprzi9qg{@3`8aG$xb_Fdt+4B_%{%@^pOYl*77ORluT z^zVF!l2>U^6KV#9Q_F!avZmu!8Xb%Ng~Ny0{HdfH?+Ev~3u_Mu z*Ugptr{&4=9L&76?(`#hKLyaor@sh8VPahrkvuFS#vA>)BU{jaChiLQTSwc`s&wNc zq;CIvVqfVWqvB-jaLGFR^dCr}O$9!iScd*-X`E?uNX8e&UXv(=w%4Q%+EdPCazl@bfy`V< zPw`WHAk7fvMR$9T#(V%X1V^L%?r=l?7$*eskC zt@w*jKGy~bFVObT?{S|U&;9)bp82vkEOy){nIFp(h+<7KG>^dQTnOG?BQB>Avy(j6}!xWYO z3L7L{G)@ukF<-r1I9HW=E;Y`4^+w@5m5-#Z*$FQg>s>|vQ14*$Zh)RB(y z+(vr1uwtb_#;{nYPRTDuQMJF3Y>NIb z=38=oie9jR5zK%R%3^o5bUFH;E~NH#%@@*Ud-h+HEY=qNDqO63k}|$!p8TkA31x>* zg-gqX%QO{Lizp9}bUAU0FB24R3gvSx!L=3rBZuOXC-S>6sJ@jX1;j8r_(<#e} zfLX-V{OY;pM5osLRp^hCIsCC+i$3HEWKy;U{U0phSDq`EQp@&v%MLKAIxO?nLtM(S z)w}<4Vhro5w^&gr={Iy0mBI=Y1r?{{NTrIXN-Q#euhg!5An8@p6`u*;oGp|&qiea5 z73j|%L)$sNE}eMT*D;lt*pq%{H_gDa zzE!=6@4Uqw^pZzs{|?Qw$t7UJ_{-2f_BJE33t_|IGOyz>N}llbHi(jEOsjxHJKF;0`UB|a$>s0J>I5CVC>!+BhQ6@VTp~O6Q|I?NhCe6e*5ZR4u?qdEEyE+$B5^ zhF`taj`FdW>rmctmfr<`a2O8-E!!o2F5a{d%}c7dmiX6~^+e&%g_>|g_9s|BIUW!B zj)?0a8p7tnjb4<+XS_V0wi{WYSfWZMM}=Mk%}rtyvdPRe60AD z;sM3=it`jzt%bdFi_(V{gmSxG;_X43R-jzJid_AI%BTh31%-Id z=W6!nFjz(^-k-_4Ro-bbYWLRi9)#VmWERuwJ>v?vNS@L2%1{=g6>SxXNLstT;g-4j9T!1QAk<5M`wSFs>3M*pnse*O1=tvA1?CdOwS;DBdBS70xS3B-uHjr zbE#6+X;&PNRdiL<7XJ613-w3(h~h>?YL_FbM6Xv~+*OG}`rdkm^1{pbJmAGyqR4;a z;nOHj-rX1Fo|~v=AG<07)jO=r2DLK_-OzR_n_Ba!hf97?%f<{-2c>rOhQv9UrP_CUpKsk-8+^sJKZOIQiBK zlpng>gmTNX`%%9C@Rul`u$!p%vf3n3(Yq=J&6;I_Xm%?k?KVdW?|LC66o$v~AD0VZ zc-y7G8~ZL+_G@J3#v}orANVzVSEB_k5sR`y34;_>3^@HIX{YZL4=AovoTWHQ(Mqwa z@b$`zBZ^V}&#iw^9&z~`%6H3NBHng~@ucU4-IUv7#iozYoLQBK=E-H$t?RtPu_!#0 z(+_q_p@(svD|?YS{T1FBZj~npokrLngac)U)$zVO?d$kir&zdCS*JcorzjGaq;-V< zv+| zc-2JIHk6Gmu2-C?7^X-}FuMI+o=UU5B57Zv_FgEDx%?%{ z*Pq3L`-{UrpnUOeV%ybb6MCEh}tcU{cd45!+A0fS3ajGK9yYH5j z7fnA|c^Np;`aGlBxz@@L-tV{fL;0tdiBb=Zv&|?^Is6cBf3=&sb)LHEQ?PvVe3?wKik|dTY%d0g=@*9MfTFMe3-Hwy2pJ>-c{jq;XogE#+~~dhsIKV6rwN_@Dj8fZ8+fiE}`(caTCd0ah4YW6*ZgdtIqeMT&cpqvv8ZYGRYl-fVddSG#5RaKU$;yj`raTF2wcdc1Z*xgjUhI3z%8O%yyyxOPOx|;GwUGB* z+#c(PqV_tS8)GRw?D^>Gt)So8p+{~K=k4@f4m&UZg7Vq2mxxXJ5w49^IlI%avu+c| z&2Cq1!*YBXE#CNt!XxP1pRG_+P zn>`!yZ176U$|3u@#aUk&Qiu&xdAG$OOLk9jnkD;8xr~%|TihIE&o2)n*>}hDqU^us zoue}ewXbw^=;c2g+`{U!vb(TDuG0{{8Zwc)RxOQ@oviWDtJ# z-#r!0KAT>mIa&5HGJL0u*fi)=_!-fo>)atNvNuGDL;u(#y7D7<~DJy?2% zEA&am_s?}kvzF|Iq8Ggz-{`!#nYz&arV5{HMV4J)Hou{emeMydr_n&a*YgPm)+c&A z7&Xm#O?TS}Ymc>E+kE@@Bz8INxXkZz=T~Nb1?=jaqVs8xVW;~&<^&gZ!fzqh<$WHW z=O-P$K@>z>77is!P)H4-aFcLYlW_QL;RrL~NIzlh2w@y0l#j{2_Tgv_yFv^PIVF3E z40b(&SF}oYSJ5kP+>Ez+6;^#GJzv@P%%f=(b(Xi&a=x*rz9$68TbrY*;>xv!u&@Gp1)P zGH?n+e}}x8G9fj{6H7Ej}n4?T$f#lvROGIe6e!~FON?CSn7lG^LFB$o5hc1Ji` zDUa_f>4YA_#9qQNroyrKlG*8QioXeyX@$&Ds}aU{qJTN-y+Smnx8s*ytFJiW+t_n< za_k5tVlRt*!p$+l)t!uvFuT;p8NU^I%PuZcwL-b-PFNDfFGjV?^XCyqV^^X77>v(1L7|uuAIbqUyVe&EIxXr@xmBJKyMsm#&P7D{Onh4Xh6z>bu zj|(SZOMR@{r^~-r@F{y)_zI6q5$--E+?*~~i`DwB_UN|>#8*XQBN^RH^^94Gr9Gq2 zKYBm{nj?N4Oa1zFOa21==f>lIi_Iw+)Ue5f5v-nlHql)2OYN#iuZ*gT!gLkwlL{q0 zd4ezlTd+fzc|tfv#X{C(NoQLr-V@5Fy;OK5R(K9e=wBe*{jDKh-8|nt8~xrPcwk6J!BUYOS_CW(BGapj+Uf1#XxeM z!WD+ua-}MpZ;8Y(;nePm)D&~ns$J)fl5}2A#czbuRUOTszhM@Q>&NR)`mEY?Q+MKX^SaQZ=ue0t_LgKPP!~nD<0fIRB9(}n*k{ri^e@Z&6#Waco}mB3 z9OBM->(n36e_+}rdf%~!>3OdP^5Kb`D_ z{=->I(H}AuC8N*eEkyt4Gm5#N>ytl#Yij=jN@q1}7G5>ToJHH|zj3yTjl$kyr%?5c zMY)omqmIm>?K4k4O<3GV@dM$!7)4d;`5Ps@0PB$J#OqJ{NAmBLa^blOdH(UpCvq>o z$1H9I`o9=Q4X$1<>+MTE%8Ew+vuSPUzc=F)`sWv5H@;gTc@EW|Lu~ucn7au5Zx-`g zs~_j#NkgxBMEih;^H++61rCZ|3rn~{GDF@&affhWoZ>yB7VPP58;kUvi zs-%)?KQFwpMeeT8)kTz{|GW4k^oLJakN#(w@1p;BE}mR+Gd~c2Sr(2VM$PA5Lx0nJ z;yga7qy_yY3+JK#heceCCmGMYf31cOvCEARYvzO3scgk7nDb|(}SIm%4R(vd! zCp4Lz)>qsqT;ZzND0~Bp@P@ErisDZ~`LwsmuGUu$g};yfPZG?~|9fgF`X^_P(9qa2 zaK=>h|4?X&)n3Klqd%!+Gx}2&QAeqrmf+#|x@9xa|84o7j0qBDM%s1n8z`}fd*f5C z>O(3LxP~9D;QTI2Dyc_i$hodDH%{r`E8!~qz^pj&3CW+CYC}azjeQqI6)9^}dJV0N z9&RrBe+?sIuUtx)iT-cX{?gDmI%q0Uv1eI95&FI7e$DK5pVDsV_bD5P{x_F>j{c1+ z(3Toq$#3I-U)4)SCvVP2|Ai{N=N7)2wqUEd20bP{)}Uvw)><8|;iuQWBX+Ct5~OCC z6{n<7Xb_Nd`p$(En+}J<81@Qw}dr)6qgBkIzr=ip9CNDKb$le{lDj)M88+z zQ1tJTcOSN-FJ^?W#<%nqklL!c@oh)=1OAQ5|AI|x~^MWFwmn-K7_prj7LAT{C_Mp$?S(qSI|3Pny-Pb!E z22D}vk&5n$y23yeQ-P=2?zTM)Ygw zjqs=i0wk|gr*0z9HvtN4auzGA$hucC=!S7Ef#!!ne=+lH?q z!!G`U=2s_a+hJE5i0sf$WiOqOuioZJ@bij&(4(Xhoon)m!oa^W`or?Ezd`-sj#xhz zG#4&$(}!_Z_&mU7$b8tV7y0;826#=8cqFY_fIm5sE>KiDrEI=?S@3;N{q zZNQcc`iKB?87cZV3=f0pL2IDCTLAgrwb}_Ahcv>i@^qCSmY}M4zc`gvF(czaMt&-0 zeA`u;zJVk73sx%@DW)i@8uV2)7fe=8W=hE|N!R`AJF<64OBGgPmnBogf$4 ziz#qq#c9+oE}=*Bzao3-_RXnb^T^OS#sUOE9+YPzEKe#PfdSN8Jq%aXlxe9vb1!|)^c-F)9 zDF333hzp5r>4owKO{fjr(cpyg`LdUef3EDsN%qq5iOd*=s*_26 zFnai6@_!t318#BK3bU;7fR~Tn0;tz#0{81mq312J>v>ACPEo~`r&8!STph7j#47jt zs?~V3sPukC6my)GM$9-q+<@|mwqTUMYN3V$-)icO@`wfxlxxXeI=-)JbYQoN@6l{6 zdwF^1%3eBNCo__vo9rFwd1UxHI6kNY_Hg4Ij~44#xJ9oKE|jMZJtm1ok5ENZMfzN3 zq*OoYu43N(eRYId=lC>5)w{Z@61n4Ft}gVF@JnIHorhb9bFa1t@p+3j%3Yg?IKOKR z)Vpu3?4{$gxW*XGi!1J3cvM*=fVIr&#=N&FH*J?@(N>I9ZW6;2iwLUBo|%*AvxVRJ#>-wV-gg_K@pere5$8Fz#s$qu6)(lNvX__J z`uqa)T+N`*aP>_p#o~v358T&O=Aj?yGDoyi4q<=_tUfnu}b zZbj7!oYGX9+LBoSMob2dzcXJ`<9LNRk*^)=8Hx0FT*Y18K}Qu`0lz=oOPpJ^C7`^h zg%;<1qX{2+Wi^aKxu)!;<9=24VsblHNxODEUh)$<@5){}F2?dSmGgq6Ds25U{4OjD zrbRdz%L=FCP1#G(ai=~t=(t#RJ^Al#9d&JT)E0&Rtr@9EcHq2j{bbFk&sB$1)Ve$P zGwxd_Z|msolQkp5NAgCs$rXDd)qL6OzYgQSDImKctoTc(q~CE2~A~uf*oZm03>k`@T zyw56Ie55tamRtsZBX8^I&9Fg%;b%50WvnW@N|+yzw{@)SY{=1Op*7{Vdun|Gdw*N6 zL&2}sv^STptRqFgPtn6hl+SC+K>5ZNZ@m4T?B(L>+b{*q2kWR?r^K3gH21GWiTy97 zeWmpIv`0Jbj8D)uF6j(*_QzO3S9!|T`n3DjE@9S1HghyTwstqj)V8wj)~`W#kQLt6 z|H$ef_cYp8D^UBwifFf3Y=u3mS602qYq{kO@rb-X;8<@-i*Vj#IRP~vS`riP1+sSI zX<x^Kzvw;JlguCCGv3)4$! zn>JJO8_-#haS6+Nlddt>@Q3WhXE`JIOutVpese#oyTYQ@rq1wNixh(oOnX{5^tUkI zEW5c|Ih*qvn|kwFa{S3WAFuvwjwhXdHK%r6`iJ&A9oQ@BX?HKP@R$j@QKq|t@0n_vn!7)#Y{ ziqW~KawId=JxeKt$(elW#duxD-+c;=)+hHd$}-#^v(UPm!M`E>9sV}R^ssQbsQ;U- zmHT%64Tfo+3-nV4jP%yhH$~xoy>=8P>upEjEqOyJFk0TT3OYLEAqs=!owv~S^5$OH z_wxQ>goQ50BP--x(4n8m8?8}K*i%bm*brIipx&Gw;t%_e+LjU<5iR4<{96;fm&Nf0 zN@?~%9d&N9uZCzfx>3n-L%UMSsJ|!w=YC0gp_w|Sc|)|5?d(6&`7`ES*XKIMApu@H z2d8?Z_P5$UpkGF%R6MKbr8i_QTu6#_+Z`(Y&sO z8Z&*=l#6duWiJH1dEHxAY+&FX(e+o+(2_(Q{-yV%VV`572f? z-l~XsE^k$g)a_1v#}1db&Ev**BRy(zH~OE^*f+8H zh<=M54}V5;b{pRqnYR#+dhJc~=!xHIsAtw==nhln&f027_f4y;(C*uFU+H3-72TE; zSbI$Cyft%dfUZVL@|-YokNImT^&PT%7^U~PAF~JF7|5;{M#p2<$ox;-+cN(%isLe4 zCyf6>m~cv%s5s`Tq{m(mCeenOqkdO7j_6^IdbKbmUpQg3ka+m^;R{*0Xyc4QGh{E3 z{>@F5%y-XiI4P?DJ3QsAn$ucbwJNvUbueGH*_$XUh?IT%GfRe2i^kLzdafx|F)eMw!9~7 zsuwogmHp>;q|3gjHNX15h5lI7zi4nt+Y*WcQ`&VI(^6*r8ZswCzJ?D0nw9G*C!cOBN(0?p- z2R`aF8Ly7>&(cBvBUw`oy)bPPSDo0r-spcQ)=h2YN$J5aX3(ei2%o9qCtvwI|AN>o zP<1iOLejG+JG14gjtW(Y3h8T@Gk#k*$6t{?i<#<0Lis%M5w<-NwxAFHe`oK?UL3l? zgV0|y!U+AYW8P(^(qJN`UT8b{FjjxeCWk2=xqLfr&J1jgbjvTM*EX3o7X8O&@8o(i zqi{d^+lsR34}O``P2M4#^O0DXt74;=$Yr)%)%kzBbN?Yn=2KtHRHFf^h$@*c=~7}C z?iDT!6UygNjIiw=VN1L974-iSjI9Iive(m&gR;})hSBLR=nu)l+Y94!kK-wAnE{$I zZ8rWKcX*CH`b&!g(LaCQZ(L37WS-pN?-En4Asb}(W!-0`sq_jzl)e-@3#kic$Z0R| zbK&df$>j-CX2_{QX1g5~KM^iXQ>3S4*1AMkuFjOyBl6YIxG~7=Hv0dRx3Nz3iCvEV zxbf!bzmfqr6iy35e@;FgTezt3E%Zkfm!W^hf@SD`vCt6xEsH62*mZfzz^iPn zO0AhsT*hzpx-R>SKKNMqII&j#Ot`#ExT1%m^7$KhiFxv4!irEuensR?QoJi%IZg4Y zP(F|5m}H{gIXFf`4i);I^Rd~rFdKLYdeyGfi_xt2c<@qWnv0T+4 z{BLgjprqHRs91AG(rZH$PYA2g20s<93s*cTlxK?`RR!v!KYCO<`dw2$M*py>@#wEE zAWn7~NqlbjOf;`NzvM6UKUj`$XPvCX+gUEFs?oo>ikxGs*5H}&Q)?-&&nMO7@AT`s zaz;;<>w9x0PhG#1RhV+Bj?Y^hXI8wEBCUorQAamk`MtI#$G@|M!)gv&eY00s8;0wn2aK z`sL_<`Zls+f7!tC2=8|?$Tx1|2u6iFH+5w^)oT+mX86V?`pkh5n^o;^z9-hVOi=t> zxHVW&d3&3xoo!p>NNr!mN=4PWw`WUw`&D6_75bafb!k4U>TeGcvS)T%{9%Yp0V z=g>c64ikq#w+W_IY&_FmrEMi0KPHHLA_{AP2;R;i5^jI+|~CovwJv#o)#;m+#ejA0)v zbxP#$0_Ek@^L?za32sMZ6J-Um`+%-C$owREFO+F@k5b0^mNe|N5zo@G_O2 zs+gciE9YA?MdkId-z6QU$`MBHr0I|0CPm_rT2JjTM)|LI>QG+WIvVAf&9*2X+K8{C zL+h~+HEJ8JVrWTqB5F^TcZP=YHcmukE-@4_AQfMS*Nx^17(P1k0qh~~aE4uVEP(IJ zb82C4$h*s7vz6V6ijj)cD#r&4L;qF0qexA1MFyr=k;qEZ{8)XE-;oRhDp)P|_q39(j3 zRP6*mm-L9J4vr0Pxl@nwf>v5ov|}@>qB=MFp!t{jxoCc|tr;3t6ZhfC<#;P>Uoqth z8=M=Co(-vgLd(&wu-GEc@q{e%rB#Q-I39VSVqjEVyhaQ5Wpt`yLkmbi4^K$et5H zdu1={pmp*DQ_wtRJzX(c(M55PFz_$M+lm(yQO5DN6iXHHBS%IGhnsW|C()bk96`Br zYZl6HHHV;lS7QXqSJf{=bLF;g(Y&LYx(NBE+zwh60cbZV%+Bys6b7e21Ft5hZDDP8`&fr(uh=Jg~ z)e-}q<-}EBY4K*XeVIE4My25!{|oVy+CO(F9`M)o{S8~!E{k0sjzV&Wln`bpMk*4c9O)zc|K2q&a&t#G%74Fe z0p&AVOHlrAvnc$jtP;gSMhHeB<*Zo>=m! z7+M2e{Ak7AKg(YW@jhnS4%f;q=H7F=+=t_pssKe(Mb#F(RA1`#nH=$=H-uG+vlJ5* zJ-G)xf+a{Q4yIP(I`KB=S!l+thEf~dt@)8p!mj2ln<)kh3045{zdK2)$hU1 zvS3q5}3jjl~=B zc*}Fm8$s8QnV^3!2rs3gr))r%IeO z7NFd|{xF*VsO^v1AF2(iq?jaJ~HAO9{I_6)rahx;vpyc5G* z?0K{KaFaZ(>{cp&SJo{>?7E?<`)XOI=dVP*l#!`CGoka)^%(aGvt2hb;#==JkGszT z*YVs#WXirUR##jHGfOzwg;LlD%1%SlD|S%IpsG9Hqx`z;rQ;vfj6&awjr`hYRy}dz z?Or=XG|QOYb3i$9;^A6+8-E zpKC2qd#d^ie%DaG5{2iBeW30oeub&@4d+>!#Q!#RwrY# z=X(1bpAJ51_^som?z>HH${LpWDfug%RGn~wGpI|d9?KB=b7XP?wk%N1br;e5VNxz?s?d)@$ zD=g;Po0*4L@3-sFv9kTa?#mui9R}F#;+MX5^qDRmcGSJ=pLXQ#{;6FbtnRTT4!mP* z8&Pw^_HC49*wX(5^tFwkH(6k7gvY?NoSiCNnN)wDC4gmNrc+s$*K{`=*b@<)*@(_UKXT8vC^bMi9Z z5mn)#Z?5g1GFlXuN4#uaUv$P3h4>edP_8u(hVqX#2{P z))lEQ+u)4}%fnv|s)~9X^;mnW|Chr*82H#_*NAHaM_M$+j?lV0 zBs(riYeS#HQ8{uaIeMAATM=I+s}c#zWK|-uTvjEWxSF>A|3C9k#xy9J(17N7p6Am% z&!xE(&4yGYN+p`8s7OjkD3n=-%oPfu3?V}<8A9FuulM@g-~aLW_ITXqW8dwZy`Jm6 z-fQi(*V$(u*A2+pFb^6pR(fS)WQp*>yBFW|^}(?p_{n0Oe$am^mFoY27;ureB7+#{ zMhwzm93=){B8F@xhT;fVGZ$v;CWaRfu`c;+2zfp?v)>rD=3Qg-nME6mOACw9QG3xL ztirUYPQl7ooZ(mao6)`8Yi>C5z`xzi2L5ec==V;Gd|_pNC}0Qt&jlvH|9;RPw5>zP zM4VH1h9DnjEeb_T!i3p|3(4@$8 z(_S#oC^>wz=Q&1G|B;3Y$P?lJO{^Xv7 z*UWjI#4=~iE-Gg&vI|56uudLJTra|iBV(Q1fsws_Lm_RaFuRlsw4Lfmq`#r}#QqJ$ zZoT>b@L#SG4}Wt@wA#@s7u32^z*issJ;BlNKO2dBSj$;;2mTRpYv8{&5pC-9a}CTb zs@DC4|3As7qmtbQj4x8ADX!>Yx+y4!S2lGMKJ)QR6Q|PBP7^nxUSJP#(|Th1bjIDp z&8($pB@iX!ECjOnZ^7~Z_cz4yyuV=PZ}_{=HP1~mt8wrTqLu%nR|0UfO3knrxG#C! zDnu;fUA!**Q`VrBSMFPn`1m)cJiypzoQ9UN7}?a0^QhnEMey&+P=)_+#y5NlCbMNN z=4~6cPNloJx9*{`Gg&+{57Ty*8Y3GMw>i=FHkMu4UbLP44>2c>@jEd$kw|~vSnD~!vfw^-L z{Z^i(-?j$$cV&OVSv@=l`7C`Zw}eLJ?SdHFo^9WYYm$3;QdDvtO2Ilgi|`KQ7*@zt z7;yx&HtP}jY+Nl+qCExm#6niAh-Lkb70t=>xK5cnI4McpRHMqIMj2~ zOusUF18QC1lRg*zHuNdO+OOMgVRVqnEyFnIyn`41!#iPX`LF;vpchzJiTRXJQ4Y@J zyNWS#ikTNzVYG|bC4#%S3wBjd$-7Y_5U;_iIC2u)%E&UJbQNuvz9yEjY$-#8v1)C> z*i2MF?tM3=Z;*#lTZ|;wU?b(~_XTo1`;~n^)+Uf)UoSYf(PtSXd{w7x- z2mh#|yYN3iCN6FzotO=nlv%=mV2>yKFYVR9>?w5beVk|9%8_+~H_A`o`bw=rhDxtM zTj1EpC~zI)58}Q+M!buQYd_uvHW8~N7;_na6X`SD?>^qq@E?spw7YL6sKfti3e3-b z$#90hXLdY}{$|H^_+Kb|3IB7ugW(@tmInV*d%wYdxKaTAXZM|ge@oRo%x>2n;KST7 z^1xe~o6vf=L}c|doCUNFqINUt51ysc|631d@vj-CJ+&(t9}o{|GO|3WL;G@Z)vaah zB_1{*dW*q-ZKMkq*IVHv#H9N}8jgJPeda+fu50|9$T+`2Vha z4*wHXS8+y}cn~eJ!l4#<9F7SvCNq8@HrOy8B_2m4LF6Qe2;g%GZN@Spvesz?dmVoa8eu-w(0h;O zRvj6b_eHm&6>a01Hef!OU4!~?E|$&*r{wH`WoYU(#JW2cd1>Vrj2yN6M)xRK?&YL_ zj{11LrLZzu+TtU9Q{UpIU7N5}WskDj>3IX@M+I?Y^WtgxAVvs~Ws12g+eYlLM~)GF z5!>U5W`m568Lu$H1N&L*&0q%e*pYrje)^y_%+L2efq7=f4w#3x!i^Ksgg99z)lgp}V8F_d`Dy$uZEpcTx8^dF&=7xcV;vwFJc&MbHSd@zoF zbL)TKL;c?`N|`A!AB;)Z&-$?`Vu9-zWGILug2x$48MiR5X7naHq>Kz8^0No+V1BL_ zxo)$uqX^~!t%)#qZ`uj-uo}eEa(k&FY;WfvYb~Tx-@r3B7RNK66~cqk_qwA-W=5Q5 zl=xjAkuyD``~ln|Nqd6lV>~jonXU%nKM;KaR&L$_=HjA?fb2dRV@k)0_ zV@7$Rea6UVM4orh8RpHs$YjpC4!qCWu{9ay7EQZh?pSjb&WWX(usxP@8Jv=ecbP@d zFSVF{2oVP3-N{yna~GxDGMEVF(khyXrzDPPqBb9SWg{*IDHOtRIR+zp?9R`hKE8ufE1S6M;h5K)m`;mj*WW2{<0qCuQ(u}3)E>7b~^mII< z58TKUBjgr%p79_f@)dj5Fa|Ipo3Tfg5y!$dB7!UCFO1!ch$ChD2wKmEd(ao=HNA+c zl}`tbYPq~M6XyI)=&k00H7MOorPK<}p*h$#Ih{5ETUbFh(avT}BB;mRANpXxo70l>ssU+eaC36l|vw zZ8ApwAo3Fi17W_q_Z!SDIu65pZtHe9|8Byz>CYOpv+0ad2RLixJcI4lv>7mb8H>JP zv#vECtnUPz(K+1|eXD3d+Q4TOk`dE!Cz zcFZu)PT&(pHa6-VV%vF)ESL0<6L^g|qa33EQFoN_Ezvq@bUe)84MxH|ws!>C!ry_Y zns&9K-X;xA&2X-&!5C$9taJrzALR^!3)9ff22rv1;L{s|2D!KTFyGr+3G>*di!k@C`3mQ-Qq<8PD+m2lzby@(`U0^% zFw6*vhSit{2i#?229&=3567ku&4_P#2Tp4rGO~d20>K zd7Ey)`A^Ls*p8G^>kH(fj(QGhn(*8ki+0hSLU&^6qAzOHTG?Cu|k2KLQ zgiSTC;Y!F&6Ma&Ap(blP^U_h&-t_ArTHGXno@He8x#Je1UC;^#1GlDjI4jpqfU{g_ zDr}8%XTvjzzDum#9E+G~i-zok&rXj7P=cP$ta-@*W0Yos>U2;;S`XwFF2H){;7n_< z6L)ZUYBbSvB{bkai=%<#&g0WSZx>uiPc;_4ud$5oThy2X&wTY?Sc8dD@4}VzEp=pu z^uOx+F{>3;$M^{I&!gyxCK`jAV7{l1pK`kcCFq}SMXdCqo6w%RMzyGyj!J0`Y;|)N z!ZRWban{@)#|@4TsfJaI2mV!k)Fu}!rjbwGN>v4%D!rC_soE3a&vRnc&dluLd#1J* zt3h|w;Ji>mEdW<$Lu!bH#0jEE9QaqgJYE%)TUGeHBdO9I$r1G31BPJh?WHPm+`5v~0#?zsa6AOjDjA>#O=&?H^fg znGnsa<(&&Pv^AC=nf+I%kv@6RQ>IT|^h=lPpw(Y37lM`QvSC=2FGJK!o-I3q(PS2V z@?x&L3@vSuvkcCb_4LV$)h+tu#rnP~$IaE?d%<6AJTA7RUX z3VleSpq2wq`BJpJ?8n>)w0URRk%{k@-HwYEeZKT-DF5&Euk3eA%3!Wsx?~hH{^BKQZ>PK^_2jR9Z4|vnb?YE{iE>~c zJQaO9(Oc!?TK~ZI@F@xOp<#L!)6!L?Z_um8=Wd*IPwHCQ^+o?mmc?Z&JXo?XR8#ZA z;?thm`o9+aYwKrnd6B2#R|_GDXKHa)Z4&WI#X0*VBt;Bty2XFY-ETW6ew8cDe!6%* zeE7vf;4@QP9X_+gF~&K|h;`sfT0{)l;L0P0I=cQ9Gs1fH1hJ{$C(*}PwQd(h?L3eF z?>9}9Wk;Q<-wdL+$~pCUA-3F|BJk|J%7c-h^OPz^h2GkDjA1iMN2U)-c;}W$g^Bf~ z^{bv0jf$(+>lD!n4KV$@P{1?7>g57?+alZd!ahbC4mX6(s@-rF6jENA=h8I)u1L4* zwfVWc8E!4}ZN|NGZ<>#B#$&%AqV1U~Sb+8OP(eprkNeQCc=%`vv|;^xwm=TpFMyeo z-$Q}PSZ6xOe-Wz%3H&Lz<~HEhrufU6jIN;A4kBr!YUx=ni@$ZEM@ZOS6~owe{uBq} zoN;Z=On;$wWdh4y2v+8{XwBiz**Mk2V%~@eHd=`Xup8ST@`D6}ORSrr*Qqx8`N|ADwPDVS7OCH01dT|7kdSpyX6!a^R1t zXyc#Gzr^b4U-VZ@RgI$CnJ_j+(`bC0;4goJv8_l zwz7T5IN`&cIJXP(UPa{R1)mC>F>`iqZMAGCPg`@uJMZS`RCaf1OauMte_;Zt*gHWAOhH6o(9$6M7c@UJ+_8$7E31v1*J@iE$W}a6ALXeqzElV&ZZ}L>Fu3 zn}}-=6YvrdbE3zi=t&dezaVyamIcOIJPTqK@#+e>W$-Vi-%751VT*W{#kt`)+r|Cn z!+%{cMud3J@at$-$*2qPccf>b*d3zhvl?e4Ov0GHA~BQBPf5Em4``xip$Jscvrwjv zuH8c=tkY$DNc`_vC<|#j`4n*j@*ZS$Ny(w@R8hu8VwxF|{zh3#d|~hGJ5PH$vlM2* zKg}c^{!NY;qYsVq4uXGaP$>LuB1++Zbkzs==f{tOe@Idu{L9yAV5A$DydM7FQkKAf zAQg3&bxK2vNEB~ejCStX*n;&#+fA-i&ZYrkI@%8FOWHwO$mJg_;U+(eG)`u-(R@ zwe294nJvY5jF@A{c#W9LB1}&{Lz(W3-NZa(H`qm_ztMK$7t5t+-@eZ#@a#PA0>i5< z0Vw^{_sH?^w}>r)|NAvhajXLy9wT zKY1%KD(~B&iBZjF2YQXL6x~Ta%V=i@m6`9rc#BwI$;kE>a%j8oDzQk95y!;c-MWlT z#9hek|NV`=TY|Rxvcg0V&qA5%>H+_rzykO`jl$7R3nU`z4n-%UUVC^qA)mKD+KP7B zWR?vk7;Z-^gv;+ht9fS@%*8or9<7&}>KCJSS}D6=BJZ}F59bi=-DMapd`srhojoNu zKGw!@4gisF;5TAf9OGN!9v0_4H)(sX1>+fFxill|N+F;hRgX;s0q5a>gNR zZ$JERRfu73B2_7gbE9l!AI53ReZDx8T;6w|#<~5J)p7ezf?QQBm#UCgxQlxt<0{4{ z#A=rR)h)Dra1kSW<-s4cZS)2H3*7OqU-r`PO}sRZ8|C79Ai7~E{1<0L!ap)+3jA;F z%!dD(Vi@L`mh!;=>fTuRcT|eQ|Iz-0Dfmh!PmV_>kD7#E95p8_tNF9sFIA%;5iYQw;pGviHM3 ztiT2S@g*Jbzf$3kPY#wI;D!I|TC{cEg~NzUI;TDu{*eur;h%m2dFadEh`KoTH=*6l zSDxy{41U4sbC|2;y-Bd7c@wT42b%k!z}2G3Sj_mBcowCD$B5@x zw9iGc?Hk1NVvK8vIP3o&8^cVh=2stDBXYnNcT8A3eS>+Q_MLs037TKPah*dO$}mIR zvmgD+@m-NVXq~BtTxnT{NI4ir;RyB*{d2(-XN=wUisq=N-7mUQw`-Mk0xRgruXbBz z!_O|3%C+-hSoOKaS_{y~rGN&IIkRtZN1>qS4ZJkNr_cyG``_I(91N zsD$LI$>gt%$a0t$4_J4=%-y#RlD-*Q4vF<9! zi55V)PyNv;Z8te10=6pV$Vi(X+LOV{vL#>{-NkLQaSmF+CX$tonqb?MQJGPck@a29 zFWTlHrr-m{^NfcXaYXFjN^}oq{!@P;wk}r&5EbYAr|@)Idk1AXCSM@)9Ssd|zOa83 z99QH4XTMA@cwS$359CB6ayH%m&EN*-U{KZ^$Kia@h7sqiEK24S(X)g(Yvv$U^qpGJ zj!~OYh7nP~evDYS8e^Gb-NUwTGP1~9SFr6I#`i>_<;wvuR!T1T>9SLb)COH^6vjWD94Jc?=xhYQxU@ znCx>flkVcSj-2ZZy0X%Z7-boS8K)AhzB2YQ-eF{CEi0DuRy)|94U8D=U|vc7E?U2S z!u;bvD9lej#U6*kJBXY8_6tpL-rIm}+v`<4;J6};Xf__1(eS*u?hU9LjlOJs!@nC0 zcSfsP^P7WK-P$m<+9x*-TuXOxTlvgIKe9q@fv7Vm%829QI+*2*f=qBzij z=6}}5=^J9!veDKsIpvSh$;!>S1e|D&UT=9>dli@^w-^i%>jTZ^A~P+~w?RS1Nkj{@ zJ;=rxiyLgak+Fi2Ws5~3+YV&3Wn{hH`9AqO`3_^3K=P=`L#?6e#MeKKH#Idl=B47?1n7<@{$H?J{i2Td}WUt+= zo|!POxN{HY*%#VizO$hd&PS^j!S-blj%uZpnGM^V^>~-%q-aFNVq3s?P|~>t$G>NO z4b0U(06NPdPtBLoZ?u|o^J2_1`$50OVD^GaH^b3EfPQL~Q?(4XEk$s!oRV1t z+ko|RVD&H>t!C~TfC!rnIo|=x%zHpr?F*og9NORX3*E(S+QHiows5@ztC$0hg>C#B zh$w(Ij2euH7xv5`{`VOr>m4Sy*dA7EhkfL4FE&guKQ)jB^WYw|3`hPB^3i(k1@uZQ zo`zR&7Ohf+vvmTs zoM!YQrZu=T;fO_GA&V!t`e*GThW`y*wP6q60i06rF_IVCF?obG;Ev_C@2^MtlLzSYfSo5e6+Sw6Lx@ zq61HZbMi~T?GmEM*h}3!;2B^40;xsg-{R5HEX*= z&UqJp!a3&nB-pO1@`C5)BE-Y6C9{JJ*SmlL(Wr}ld%!Bt+Xd!&Kj@AOy+b+yQ+@S9 zM2W9%-7PJgS+To=nhZ#E;d0I{a4}=eHOMvPWK3|54P*VQ|4d#cH44pUA$jz zoGv`&U(#n`im&OjFy#{ZEKJpyJ_}Rp)wx6dR&4%YacWo&(H0-r59fnD`fxVAI}y%Y z7m=ZckB;-g^Ey4t5zj(=1h>DLZ)p{IeH3QNdGz~mI>Q0EV5*Bh&n%sJ7CAy8+Lv`o zC5p9^7g5P2JJMGDn#>xGmxt+punxQHcXr0Cyx0BW$SjlK@#JbTr ztx#M&8)%`;w9e5t!gRdpvn1Wi^jVVr0{S&8gILWr@;CoN@i$vGtPbb&fuo4p2auB?92v%It=)@PuEglM#p=EHzvg7TUUE*Xo@ zY4lmNEF0Fy)_I_4si80bQ>9&F(xNDJG4)>luNqI)uS^!!TBBY~N1@MvbludWQN|^8 zCzNMEzu#cEoqmPF=z-b@ocPsx5z|<;%do6gI|$=;dXAsPPc_62|Ne;ljs6as;C;IE zEGGS3Jsvn7&s{Ot9=M3UtnGAM4W1HJJK)J(gx6~bWbq+Rs_Uz`Mbr{k2}%^J-UxUk z8>Oo2a#EFFrPbn_mYT{6T>(8+mDvh*27i3hBjfsZxmMLMTnaUyXxvGo| zF@LKpi`<>3JOkO_LEq@Hj#Fw!W@jliU`#1dDnKu7qi^)swJSMd#CfQsiV^>z62=HP z`;otX=rBem-OK^BiT2f=FtWX?2+xv>=nLx0k6R+|`l@Qs&JD$a$i#zL3VhR)j;y~d zU9I?Rm9|QfqR1?k$p5jFGkq&xpc`PRAg`=YZ@pgb%i?ewZn?{X{O4ynWyoK%J9%QA0*j*Ql0a_O^ z<}6=*93?EhRn@&>AjCT@Opa0!oUwi`hjQ}zFoFd>meNM5Wg+8YU%ofwZ z`gsI>P7$m?pHl>X6UAr}a#|Fb6Phcki*+)NC~_=(x=1(JDpE`SO0DFtAU2Hp$>!0s zbe7HT*^9BZ{%!=u-N1`@_hO~vd19^-;#EJ?#KdHaqm90cL}e9ljxK0QR&c5j)?C%% zv2Om|6$L)cf(Kpm11tqfEyn`;`LFBwhRop~r}#Uxf-hcDEbKVn9HFP-o9A7d5goyq zhloT@pNDfpP|jaAQ=K?7^!v)~UeZFr8c+JPp{Zzce z{^hLUtTXOCJg<|zecPrDtojuAaPp58cS3hgY;=7Tad!M+D~G5#FHSVNUzd_YXdAtuT*wiA=kHdrlR%-Bj?>&J-kkNzZf zlE27?;eB*><_A%%E;aPrz&(y<@0N(la?ibZQ1j`;%g1k6q8}Vkat_2Q7)FY1Jkfk8`)n+ZyxJ}CJp8TKUWb2JvOh+^ z@hLFZFHQXiW7U?8VrXHdjo4n;uxTg0EipTN8H(Xb$Gfm*ZqA5|$C`OOBaE<;|a!|1F2Dm zu<|=Kt_}WrYjNb{pBt3nUq;VD3EZ7t0RO8Q@U)JiXQ3D@$ijP76tppAC&1X5JIndRee!}-cl!z7b1&qisw5=%P zF5<2kjEEub@t)3@!uXw75>BMQv9W3Bsl%h%SK*)T5DI@4e@{G1WL6|{>XLLkTK0rn zvOfIVH$~yNL0g02U!9Fs*bttlhY>*}AMpuNF06%rLNTJsG2N|(bE9ZU8qOp!rO5N8 zHD&ym^?omd8-LFpUd-mp_H3o{_xvR8jbI!gmZNm=Cb2@D5hl0`8+{){27)YWXlrbY zzODOPkiNhBp)%kR{2im0!(TD!7yNC~roumE3nF}AG{+qN#XBCt|9Rna_}A^81^>{} z5AffzR}lV>%SYkgTnQh;!}}_5ZV}s`ig9i$T|G+(R3XO%S00!`zZr5Mk;*@S<6xcK zit!Th;8I4s65E&q;ZE;Z#wWyDLq^03XWTsUcS5`TRu4jbKU|K%(VitG<6L;pV{-@m z*Jl5Q|FNCO>T2a(6XD-khTfMgR^A8ypZhxDf9^m6{68FAhqEcCRu{7t<3os&kz-v0 z{68N?`!3HuG8dmB1s+MqI44ElO60kB)Ri2Lo+j2WWMt!K{UB{0Lz{vpi4Ee6n;2gc zkDCx35rMI>VC2ki=eQm4f0crM{H!c<68uy1>fyh?82#(S^Rh$m52^G(E^^Z|;j;Z| zYVeI3-MTQGOJ*H;iSwmpJ;oo8mImaQ%{6-ZozdqLXE7f+dJ^%MO>UfqGhu!sA}M^n z@hQ#%aZOs}&{WL$lXwc50G=nFp3ewFY$K{%TxT>Hix|HWgSU}?d>{Pd>DwzGCv1BM z|4Rk3@UJOd4F7wT=wByiR3qlqWrw!H-<C_zeHxCVd?1$Z2Gn=khb~ zv9)hTZ!+H50%|0kMf=LdogKp&^5(ffjH0&ZuHg!H@H~s^`6Mzqk9OqZx}eIqow1*I z5v>VUFe0B}WXo7hOt?e-n-GoPMY*Z)mo5%~|GT~K;oo@xS#)XiP&@n$>e24i4^JQ` zcV{%A?%4xpaI}=iXG7qB@jRSE_%52lzxvVz_`kS}W147P!SOZC=uTw$B>HVAsYzE| zF^ayrdID!2(`#sv35M6a$mAOKaB*Fq&4@Z;`xNm8HzQgZ+h|REJ8dST9}%-B7aBhU zW)uBhenVdRUVjsW+27Si*yH`^2Ks>4NOJ?Ic^LiHb4&RoWXb0p@bmCX7ebGHm#71- z4J!mCyeHrs@Q~K&-FDG+xm$qBW>8DA3ltG70jEy5hk5Z&D&3XE*!2RU9^MQ&xKEk#&`4*h7ABL41cR6y#HDbpoJRhYSfgXtw zDE)QVZ7_>|HOg6)KEHDMX@uVHbe^8`;Z#7^PfiK*k^fGBC{->C=Zu}0jX8fzw*jLQ6W}l$_82Vnb^tBxP&As51BNTHp`W~HA`A$KQ{Q{6QLhyLsoV=;A|t*+P+KG6+A>&q(1rf0KVI~|#))(wqkG4k*@vkiYc3)`Q z?gb+<7~5wUYZ!}&UMHBjJ<(&r5Z>)}{|$UxPjoGV^N}`Wvh%s-x3GPEgkmmIZU)=< zov58dS9&zrCYGVZ$Kl9a`$X>yP{aOdMqY?x6UCUn3udMfO%3EMiS@fHngNu zQZpjqSat-N?9f?`k;GxiP6c?Tr(+DT8%?YO)4~P7h2Eto>xx|zm}1Ne8maCFd8Pd^ zD;lC-*R**ubq&pssC1j-j1`QC8ulbHvh1=!6tIV7mkpwcZ5V)4i1bYr#QcBejpXm@ zP0xaJ5qYx*&fmMxs*e3_aB%q0{2QElWC@(L%l+WFZKocr-lU^UTd%|mIOdb^3yKFFnTvfhVDA#@G%F%|NXS|D%->A_1~wZ+t{82+_kP^ z9f*0ifVDkle~YYZXH4^J0-uVhPh3bDV){YMBuF6g50pPJAxLmO)f`l zZLaOK1%=ZQIZj?;C&(Rc43mA{_dz4OBe;hDV;lgs&~MROZIea@T7?Op207EwyR9^+ zbgM;-vx%0Y_*R7>{fYqhTuU5r_94rQxK^8QiP2`hjb$OO{&Oui;u>y)C9+mR)zX9B z<#L*ts}db=4=KYr`OPsn8_}}_?UuBmMz+E&b78ye2wIZkP>vk5F5Kyl()-g-f=-Da zQ2NbqKhVefE7n&3*r9xj2IHMzw3-R1C!;wb)IxB9D$g175pI#WA?BzL{~_~sx*9M) zhdF74IXuP6&GDW^dgdr&Nu7BFW_-i+9mA!5<`^}WhnvGj&eNP9D^@Dzq|fEVGRIMp z{Oykq;Z=5SZ<^uE+vN@0k8SF(ebOQh&zDC~Bg?V!JWzXQ9IP_ZZ({xRQ_=*`FMI=5 zWCwjvQ?qQlzo4e^rMV%dKh-t~A2+=$lPA`1TDqWN@p{t@JVH`)O+#@_>}l$NE3*K) ze@ZsWR2s9?9Mf5J2eS!AJ!JtC)KTTSNe8ZhicQdR8cR&jmo#flkhR(pCg??owmzBL zRTFK+hb-ZI`ptDXhjyX%R!VJVu$|YU2-~?wR={&f`2o1O)BQ}QyVGA|mOPv!1_p*# zV8%b_qs2eYc$57y@ju4$#v?Kpjozx=l{;p1OlC;&lTp?}4HbK%h#7KfLPn0bvS~Kb zf{%vLVyqWmG~%IkenX5|x|ivhllmfth>k&mVFRv2-_y6ojAacsp`-{yn3?V~bRmCR zmj4{~DS)-t5ZcP}H9ZT58slo#qhHPO&W($7^F(h=2nUh1Z|OJ8Q;9fJh@DKiZX zU+ZBcGFH+=W+B}y@M#}U%hQ8TUrmTYiXs246s_Mhkj^XqlebvoY$L!Jie=o z*0Fs|YdrWDXNtUKKGFRBP!PrT4Mp{BR~Aahp=V(kS+}^sQ-(c@PqZAlt*=4PlG5|t zyg+cRZcS3)(&sv3;U86g=p^|R>a5cK*S^?rhjxWYs_8LpYxP8nVr`zKomRWGdPUZ7 z#I?@NO1811=kM8uYHdN=hihR(uus%NE;;PhQbRv1)>?qf&PC&JIcI3TM=#x_c^l*7 z7JB}kTZ|_9vb(1y&MR;}N#>>xh$gd!P;aB)H)unHM_py`3~Ixx^rpA0MB8>8LFQ=J zmw!TQH|~5U)~DIFSzl3Ab9_>kj-iG{gn)5@`bnP~mci=s_FXo4YFABe+5c6GP=DYQ zttPq5)@6z6H&F@KIMrLT54o+OC%n0b(G%W0tW;xg9#W z(zlp=PpVwPTsf1jCHy^Aw&J=)MkSK`joJFM;Z^e2e>Rj3+gbe+VH?nO6rOk5b|6EY zTab6^qesr7Cta?XyjV^3$j(1%i&PG7_BWiSd_Aeba=p^;2ot*~C0C!n&i0BI9p<{d zP_#7V_k5(#r=jTmTcKdtZQr#DKBAp|`xF%CJoL|0;D&>*JYumzO8yQwEMJE;uqX1F zSjniAN2>=1$s=<@Wa#tD(DCx)z{_&av5KB5hkOgymfK7IdQZq)=Lk`&a0o4TSKV*^(sT#U6^b%{Ov8h2$)svjgw)H3E%ywYApJtDB%DXOj+ZC=sq{wNH&-I< zj`eeEX(gEhFy8@(qiidi!&pj|>M;$(=3xQ_4o@atj@4u@B!itaYO6@6Fao96u08${MD{~2>k zL_|CxwrpYdyx=(Jg%$WE;c@f}7xDWR!au>9eqlUu9R0#YV$}lVRg&of)Gn!i!9uK` z?-qWEm2(y0!(gZID%|@WC9FyQifhPRE|0kE%n({e`dhyV*6X#qhHxe+YwMBk7oXbl z$XHDz|EQq7*#h~BD37N3fAUubBnz}{eiiD=_h^mr%2?j#5reDs=W6?2ic6n;$YC_$ z$1GPfg*DtW7iku*&7UDByLVj;PrQWf`c&>-zKh9H+@TW#mjBQP+!KS3TPc1xM# zm^b-c6>u*mUqB#M`g|kwv7&k|Mhf>{w6az3Dgnoii}9I3A;C zn43?^!Z}21-!?eQeaWuJ`rF)`5UhXt=U{}JCXl<1403-FwZ5Z_;FXr;V|3n`4I4#(@0{&a`5p!+h!sX~s7mM)TC5wyDF7x|}6){Wu zRg9WqJyndcl(<`zv4~hQjWLB-ioOA24hp^}mU$8B@BjJJx81&rSv`S&1Fhn8hlbsU zzZZSS^lZR-MCRzpjqO;up1;)y_q#94!D}*F@?N7ysTWvb?3h;c4x{tb-DoeT%_X04 z9vxp63IFGNaF$ZowAT*3YQbLY7d9MQ&)}IKa~M+@{}A`1 z?Z5}bDqSM|jg2kaOSIYme;pr~^xum_%)2ua`r)6Nat{7k8HnW37de6`!;-Fj3sw}N z^)rTdqxIIN>{$YTk8+H@{=t=v@c*{o3H}*X%@~_g4`57D`GYBc-M z!EaQ4jTnpsU~yFe4?);{5_+P1O0<*PQm~1 zrbY0t-ZmcoC+Ybu^)rga;J=}?0sec+uc6mz?w9m{x=RGhR&gNsI}#c zBhxV(lRApbQ4%|fdP&RG>tp?sw;q`@_t`Ou@VjF%WOD2gvB8)TR#+jQ%oxhZVtzuI zwrLF(WOcVfZj6o5ou^}CtC3ybQ<7WpEEm2lSKV~0 zARE6|X6=H%7CpDWdxUz;&9TZTdKOJJj$gmF4t1~mS)Yh+cZeS!hJSnGP57@qjZ&iG znjPU^cNTSYS$!@9b4QEwxj4fgybuQe(Tfvt9kTUeD#mGvi#VEq*(EJ}7b)@*S{Ccv z=sR3omn|797}2I&Tvx0a4-;GA1G+M@J+Z!Io>ofC5r%(j(INQz??rEVEOnrWi|f|% zx-|G(9Ls@!!^uzRSIVdJ;2+%b7$fz9^YB@B<6=MjyDy{dRxD_Rt;^4=IKI`pYuKY7 zejWL#^63WhbJ>v_C`+R32HfVGx515PNn08DwEaW8$zf#qf0OOGWk`E&?PVM!-qvT_ zLEQK+nQwO>?#_n)`+dvdpIHmr$IkW7@J{bWclaka^T7YZ`6cj=r-&8Sw<1foMqOWw z?`|z>i@;39;FcWx3vVOyUDNNNEbHxee_euiBkhL(?*V#b&E84(FC z?B&Ny@M!yW%nF}gNe34+ronI3LDVzgafv#}$ws{VyHhZp`iHGXPxGH0h+6qwb`=BD zEmwjZ?X94M>}7BQJV?_VM_F+b}54I6MFokh7qaPz8jr}MOR3e6( zGk6^8R*`)zRkl}wnsH^L;K?jT|jFtwwtq^!5Jyma4TOO z51Iy^#F2lv;@G~YEK|W0?R}uL>`PEp^gXy>#!L_+6K3};>OP;?_6x>4j29S>F;*}l zXYu-tjBLd6SwY)j?EZ&PN9HdxVgrBv&j;Yo-zx_5@8EAVSO)A|- zno)?6o9NAI|F};1MP@`|BWjY^Kp%PV9q&M3)_Yg4^SijXR(-36&;KlO6E0+1NeDFd9@vnFVsLZ&CaSr1I zqUU$Uequ-<^A{loej4$D`Tfr)V1Bb#9?nnOU%~m$m3^R6V-=h?9BhDXZ%F`XmAxK@ z_fwKUuhr3Ih1>kveW)0ZL9Pl1&qjkY8jCd!u zQGXD539{DlRAt*s82K5e5QEwMw?S+bC~*3SKg>UV#wg+cvR4hxpWEMqJXa{@MvWNh ze6kPXU%fw+Am-jq*%@%_PT2&mSPdhuiGiai@tEs2Fxv71s7%i|@tiDIfGhQWG3@cU zO;3mQI7OvvbPh;b0x(}`|>84(3+_YeaE zm^u6W$iICAt?XC#`5MeidT9*V+dd5E(^r~d`?eAF@{&4u54Pzg>2Mp!t^`9>x={)%7fn|J4f7ayzLL4{nzG2?mO<1ubSvfyz|6n*`%r#&JZ~FO0p6?Tl>X zaXrem_cCTPvbwLBPyYTFiGCYK;$ZIZ`7X@0dJ#8oosRKvw!eayd#9GWJJwp2fx)_yKxKKv+;OHv4%P_&nJW(VQ0We6QSc1zgLvlvf9_NV z^r+c?9X4Wq?cxxFS>AjHUtIBAcCe;-w}U2Te*q52(Z$ak`02ggon-FiPxPETf|hi@ z_W2W>clAcYc5??_>$3F<_BdBIqQ#tU(>G(C_)8Eu$H?qKGD$(S9h_ryu!=blgfoTx zRySmhy|&dItZx3$H6J&_?y|zHSrhH>3$FZ!?2_kx5|*_K#dVAueNHAm!_EjR6Q}Hu zVUjEDgmINqXNTUp^tvsMyZn~z8(jSl*|y^v^rkKPf>M_4Va#WBZA-}C^AMSP$PwMz zMi4RAr;a>iA_-n+Je)QgG}J)rz&Hvd^9F) z@=R;>paGFwt2=I0GNx8*t#uTxSSjc}R6S$)OW~U449nY#{?#tAJTz~wZlonzTJNFd z2AGJ`Q%DWh)A!Mg-dn=fWU1v+tSJXrB16myEzz&c-&lOa_1rXz$GEDHvABlvOe{{2 zzl$lEJF!-9lpZ+++Y5tyu#N6TCfI6qxWZPTl{|Ty(8AV>YB)HCQ|T-mZ+ng&uF?lm zodsT5IK~{5ZZUrt%%^N)9^%%mC2h`ay;eWd?1G-SF~@A9;xf|@X3mSV%)go`@TFTu znDKMjSmm2xbhEB9{fwhuHtnL8Grfqi@o4}&CYcr@f>TXX5lw0OyvAvfDO$u?$P{&S znN7b`gnxfX{`O0VwmU{pGn+Ysk`&M0qwoyuKx{0PTGimWu*m|E5Us(H%nV9p5uxau z0EwF>7gCdznoR^_I(0b4MZuQF`;3L$c`a@lowdGdGr=fKZ=L;2BT2;rj>?8Vm&iH2 zHf-n5a1k>+F@A=t0R57e>li&D!|ki#DrCcV`c%cE#}I~|XANc0Gs_Hl(Mt;qeqnr! zGI)g%$Hd?^#`^gNEdI7L$ehDk!K!fN5j_7L)PU#a-b?UY)RBhveAa4n| zn$6RG7#=O=bJ84O$Z;DQjK#pIY&bbNS{lj$jW4@xKvkm9|$vUy%2OVTlV51Jkf}nLe zi!r}3p!rkC0&TQW$P1dwhVIoqhk3sjT~{EsqvUVFPc*X}c?;XZK`VIv?R|i(+(6IL zG!SYHrfh9Wo;{#jS5ql>MCU+hlwP6sp`2QacUs-4w;d$4=ETam&C*;QeA4S*jXw8$ zziN$Wj@OD7jj8$?!Q<4Mm5M{E)l((oL;q2?7t9TNrM`SpPk6OD`c;Ix+7MRn1k|2@ zuhq_AC1$tUUR+Oe)HZ=*YH081tMrVoRdMu;uhkN2bHID5tpA$)A#$^>h% zAU0^lJ*BMRuc31k``n*L7%O^mPOcnLc%y%C)p&(0WwF&s3Z_!aW6Bj~%|95sR=$7g z_&7;g^NYJFUxQWjczI+|!ZLcoRYE&G;VLnPo^X}KEB7yWLk_)TO{m-{tTs)MD+c$; zB~twLTF6`{f~ci1IveBG%t4%k)TZ=J#3(D)aZ~uWl4EPR#v_FTO=m5a$j_>I=j<(e zthB`^Xt`@HSJ2{RN@?=p-4~P11{%z|)JTlD~QenX7aWm9$6EbLATcaXeX*K9PkyOTTu!)xINL z-+F=bS~9=sxyRzgS+zVXbR(7;6bxPDREhxTyVMlE5nuZ0rAt}k+!ag3G zQc8qEY?9J$&rdVhvnfXKo{C3$m7uls_02^B&lXI|uoTGQY0Y>{&sN&vColv2%zqv0 z8C&VuN}03xwZUROWJuORz6P+74;j2oix1=fwhQyn3$l&o<&wYLPcmP|KE;+^JBog@ z#9**y{sW0=eHuF3M7ldC*vSi5w7&2*5?t9d7UIXJP^%ohbncY0nek6&?#=aEH;dag ztt6#p%9XeUo1`bc54oD5KHkQoYill-fz9)*0`wulY<@)OM~(v4-*)99cNa?KBBnFj zx1%(yoHrBmbQv+SVC5YB4@7;ia*kOr*iOvH$PKm;3yg`FO|X$)gpES;B}ZKZ^m&^G zujoyh5!mPAaBtG(&P9G*coxdIh^@FURw`}@R#$!3e#QE=ek#VY+@j5hLRwemN#ya0 zZ1nz6zU?P4_NngZ#&~R-k8Q(!g@QP(9df{jpq(3T_Q*$XT}r_y|lsj=Y-k<2c#~tL0CKCs?+hsHW|c6B&aT?-Ltk8PVd{ z{z%luabWI23~zz|?W6+8$LYdTvB_QU^RsWAMXRUAU3qz<6p?Gdf@g8$CL zN8tahz8?Muk57Sr_DQ_bYoPHIW+e`%L~uS7JdJWSnobX4v~WGM6LaMQ&3L8YKr?E} z9oKx3Oj=N15UmEX$e%?`v1Y!5@h9<|9V4QO`@P2zJy7?tv6Xj-^j*@?uUi+xKVk=3 z_9f45oWVLjRCK|=r}`A`V&|*73IEXgQTPX+xDEflre2K2oHKPe>u|RqhT&Z2ZehL> za{(=A|Lr33%H-*#-S`ZD|7EnV{Km`gFv7`Palw5*f36(G`t8L3R>cuRtc^Dlug+u) zV8lp;ySw=qBN#6bud_^xav<{!+{COxJd0*t!2tYsP(Hs@t@?%4Uj90idyVH9qI8-AR54Y#%-N~XDOUvX~Sc(W2S z{ybWvmdvG`j_;RMEAN~RLXsHM0jX2IV{btnebjJBV@PBo=2L7L~j=_J;4YbRq zpSN)Qg!^|E!T-hG7nms~+*ie{cTqcPYGz5-5ZXZ^KwHnt zeSpzm;=Knfst@Op)k7BfhiDyaqeL#QM=Wz5m9cGBN4mQZRr$^UgB;KvVatutS3}3>j+oFF zQrHuEg>OB`q8nOH4xu|4H!~(NhBKmm_*a};Km$g0W(bvJ+c+Zbv#XaUJ7I zMpnBR_RWRWZ2lk3=F(ALf1$Nj{(XM~6n^RgbL-oKaLzlAJ>mVw4uN+2{2N5u+ORBPYOPjQfeJ+4Cz_MYG7WyNIJqexZ-8w0VzsL`FPCHb<1)##j^n{QNyo z;TU2QR=QsePpeR^~qJjb{Dkx&_bIttz=e#&C&hf?fGv4fd&oyh-teIJN>_JCpp6EfZ zI_U_~aN821!8V5ypGG-=(wP$dha<2BC`l3Aq0HJ7~78>4DC!Qj80GksMiQyPCiXDhDq^Efa3r!8}W-u+`By z1+J6BD71MejB#Oea~J%|rhFrM#3r58ZWBofe?=KbL48VUbDKl7yql8R+y-$CJAN8L zt*1!Y?F+RzwY*ClDLZ@2ra-ytIMg~u48oTj%6is9?ThR1ZTnp{=oh=>Qfp|N$Rd-%J#znnCqy=aLA#gLz5W+Euhxu$ zY^7dM7?Z;Q=O-M1lC)s>lJ#CUw21MDT+3yo>%0cF?+5FmtC}K6VNe%2E zwOch((y?H5oR%>k;&=$93#B$?GqjvbnLrs#=tTGLjt7Zy z`&mM}hqJJU?Tv{AP}?zB0JSfA;1$+OThYS|)!KPbSX!C|&dZ61hNuKfa9*$jYCqwY z1j<^X@63Pd?gyL5Z=RUPilG0^E%-t~$<6K{_Z)I$J<(vkkkITqn7stG4<}YbZQtNo=p5})1edk$f=-26 zjC+g1QXDs*%|TC@dnE*-u1~@6G_wS^N|4WL1NM-^x@ebafqVvNFN$xOO7lGj+1b!9 zrt{~{nfu!08`eJQCU3Eht}=Oq)m(=OY`&?$q#pN2Oq#&Mw@sSB=3Mhl;*j%CGV#Ug zb=brXYp9JT`lMZU5k$EyeTv_@kCYijvu#itI>8CGK7*H`Hmt`8I#0DqK-v{YC@-Utu#~}EgeA4 z^;yn+P%)tnS=g3foYhd>4PIa{ZsoPU*WkGBogKCYnhG2CY&6&?+9tS6|HJOqgV*&t zw|I)U=vU4ECdRE_2qmZWQ?S0~)(^rewN>8{IkoNju$Oe0K6+iIPhW`S0Q50h<&NsZ zC*<4ppi<$R-Y25p%AIJo_(o`+MQEltJ4Dn@NJHnh!KYC8u_p}Lez&6E3^{9YZUaUs zJY2sr2j|dVozRcmc2w|(bwhf~+;{Nq&@Hn%BgoX%&|4&?tjnTcD=DwjCB`Mwq*J&@ zQO;e*Z>zY1tB&!)^NKfg6tKR2P1boTtU6Grs;9FOxo=NxL^}1O+K8VTx!QxsWZc$< z9kqJ2VRP+1?Go&b`m{5Ne)A}z*_4i46FQcS_s&j2=lcmA=)5`j0Sc>njzM8B_Jumd8n+g^>NaZB;JoKFPN0r68W@!ZjT-)_`>Y1$GNVilC@>Dz zkVLPCYrwBetu)|QW-=OxAm;4qQ$)YPp2`#w%6si2XG+R>|9IZ7!(d!T!-AM@4gKjAg8fC_F$%1re69M+LFedaW|N-Fig% zEj;_8@dq+Ixwjhk zD7J2k)D{v^f+eXMgI^=5~B!6n}U&pob-rF8Jsmg0E_j6{K7sGu2kjxM+ z$K=tMt_(8UxviIb0p1}qw|lr;Jytmia>d|`+)=F9%H%w;Zq}AFCHl4L^+&DwM85`Y zh1$g*JkZHEk&f#E?au|^q2Afp|nIuNB+Z2QWzJ3N2C^jBa#?zK{1k#kw0gb zY$5v9=*n58h3HorCRE(|Ljt4RcLF_jv+bx2r0!T*Zb4W&bYuf*&R`v?1p zaq+8#w2F>%)`vEWwy?5?S&N<`?;sI{Rl~DH5#u5biK>G4ME4?pZY#PPoDo4piz*O- z=IFg5*T5E$)5sZUh~Qg@L-hGsxkE&`EH9xn-w#7vzfhWh&xpr8cij8=&|vQ-xd&pJ zZL4(aM273uSr`lFmECaQ60*vD=GJ>qJ8{sb=zwl0Tj2ctF&+^iPX*ho#lyP=IudTf^Tkuqy5;f5!Izj$Y$8T*De~z<&^#^C9x)s08PI)5w{#?8C|< zF=^igDBlQ%~t@7*T@){!?yr3jNZN2Ofd`;6$9qED`gQ~Mt>BKk!a|A2o9 zJ)U?eAa&r%^P@@@g3Y~$3KboteU_*v)9yqimRy2*t3q4tIjS^ zmwl*wQ~0+nX?fzYyEjKAsV3ap=p9;+V!OV?b5(lE+PBtkGk>q~Fu0VxZS{QRGdXRm zo=ZsN&aA|9FnLoe_w9Ih{L+f_^#%FDD|XBq%Rj&T7P94>%k{vrWy45jZCd6FrY!vh z{#%N1SQJH`ZYY{2Pd60XEMM`SC5i)D{(%Ip3`ASgazl*s4kU@xBlRui7tM2XQ({%sH<%2)1SGWYk-gMLkn>K|R!8}Kd>DGx-4=aa!0C%qS9Fs|Ba zl1h;&?#Rf)8RK%^LVrU6VqemO;-46Y2Ty&6{x*`gx2Y?yf&S97h}0@wB%3E$ejfdO zz`UXh*3zhS$DJ7(l`rSaS=xO;hUmCZL0H8`8A17m@FJ`MUM8&GOo>?(WqkL4|Cmhv zuO$Db1+QWz81Cxv1U;zXdQ_ z-$!&bpf|xHO85=li(*7cm6JR+^50>UPYIhu2>E7-W=(vH$+Tl3^hGT{7e{`8{Ra}Ym;p^FoUY)w10yBCpYgPT5P@r-{2d&y#y_DtXp4F2Q)4FmM7!!!{V2m9mGror~ zYcBK~7TH7p(=uJ?&#l}I{Wcg1b8ZARu800oa-aN};OqOKzw?GRV)49Ng3y1g!w>mL zjV|=EUDTbm(BIk}g4KuK-3+XQ+j=aqfVcR_cjAH+L(L~R^ zLBjidl;~NMsm=R1NVyNb2VNt501M#GcV42IJe|a3=5!FAyb1jg=OoFybgH3b=vD)I z=U(nr#EKg=t)HR))lJy^OiO1ht{1Z2K`kjpJ(w@UKi|`W{wsaxH9O`5)MBF5zY2ZK zGOz)2W99&~i5_@_7VXV@G=pfj_OS}~TEUOAaTVs;<5xt_6Jg3I%DaS5VKLB|vVrm+ z;WK5zA2ic9CoqN9x z`WX)q@lt9ZL1Bd6ldZ^S?|wRoHDb&le9UCxIlNk9}&L7*+5&$ddi=KuVpCVIhZeS9wxKAg0LFLnas

L*}XwHEBnxBwMzo0n?HfUn}&SceW0;4o5 zL55}y(QiU$UPePiv!M>50ga;dO7TXNXkANWbeHLf&%RV~&_46&fYB>0zE{?^9hypy z_1(ENJR7V1V%6_gd= zRn)G`=8UTB5^Bq{RUYMH%g~9ooj?z$l}6>onSDI&r!dR_ll&cVMNnrQ9b;7 zfn}n~{7+Y1*_9?#OM%JhF#{V=D_}CQh8IYLvOdeC$S$Ov2jnY7Vka zQC%#fi_G~_nd_jIj40SBa}t^JgEIR;Pniwipv(ef{!U3x5&h~^zv^M4Tp1%T_a?<= z?4RGFaFoH&pT3T9!S1KrmEVWG`eYY>at*1Le)_5>rutg#<7dgkS4;1*WtLrOtu)ME zAT^rxv{*ojHCDZR*JWG(V^!Re!;U|0u9m!RTw5b2F`~AkmPx|*nn+!Z#EJ9T^=rgG zoxIwxUcCB1UBgrHpbgcH`r@$p#zAp-y1QKB7@O|;i^I>{9TeYzY&pL;?5ZhBY#RJ1 zHiWlmoE3XQ^vl!vube8B>&h52VByy=i!t7FkxwNlIshQFv}#BbTiP>F4y3X(2} z-5Ok&X>rNn$>RKP7e(%Bl=6x4Ru)w46XDL@d~5jyrP$Ki^z%Xf0reijgH8%}S%goU za5P^ODp$+C_ftst+Smh2!Ql%WE!Bcy-14n?f)XqoZ3=?BHlJzxDDVq8b6J5tFjt@% z{3TF=ocToo_@alI0n^C*)bYSJz24CLu z+1kwqcsS!0J+M2)>i?&pbYI;;eM)lSr=HBFmnlici@- z%Q`;GdbdmbcNw)OZtvspHr-E-Gb3BP<2Yt6J?5Mr!8*zHO^HsJ<26@^#);)bi_JTWatY4ZbaCg*VK3X*YKoiF^ z#Qs$Qy=(A`nl*h~@X-$j;0FWl4PqR1Zg`Unf805wN>(+8?;<8U@a``n$nnu7$R7@l zJ|n*Zc&~%~!*%ap&6%_O=!a7fJLiKlWdq?ys01Y`5oe&>O*ls94EC?LBialST(5;) z=!_-%kokvIAs3xOc-x1NyuJU=R`M%}&(4o=wZZZ3wRo4#+!yf0P1Xa59jjiD9r8K4 z!$KHWm`C6V0*`%w*Kpw-6U0is;yC=cCdcQq(Eok{{^ert7cG)M{0g6PB>HO^-k~`& z$wa;dJZVp~O`@(r^ardw&?owaF&O1WLh5$rO!1R)h!;_qj5@)d{~p2{b%bPIgg~@wwni}83FWg`qvw{A*pP@EB;7c#`XHI^F{@YVS z(EsJTHT1vyQH5x@?B^5gLT~>CC1?3(@K;9<%;4_(4$bP#nX^7>ww9NaCYEZdFY=Vb%TEMu@BH6 z@de{Y^QLdGlN)~DOYttIL%*buPnt6eZ9y!5pv3hu1Al9tNXM28!s~QCBu2-4zBF>= zUtd0FP9WvYu7vY3W)f}xFRZ{5A@l!;ux$n5Q$*DaMjz@Bx#)VrQK z5pN(8Cuiiz5$4iZE{ED;_A_!Mdoy7ct;fvv>7$7IxJNiizv=A(Pqy4coY-Cy4XPJd zfyyG8)afK&FfBL_RCLAh)NN)4SY>#p9!XaCuEC?FgbP7eirG;_nklkd zFM#k{AnX@}PX%{S;%QM{NeOR(Y(H!n{7yMRm8H1f|HB?>cX&&=FK zHA_*=VT5V4Pp0uq%Ry(xh%&hS`2r|RXu&;G*lN)KlN$?gy=0xFTi}}D*SJeN`J!%; zpIH@nMSUD(zJ~sv_(urOo7jI0t&rHbtqepw113`9X;DTm1f40ZDUB($D4_uVD?^y& zN|n=|lMzKVS5nQiN2M{5aw_6d=xm+V1rLpwKw*{0Bw-sRyg16J9gKy4 zDA7VFk5l4KD8r+GU4$9b7o^jgPp8?EH0l{srKx6G|H;&kCm)-(h0f>^jA2R3pR+@o zPwQTALk;eekW(-UiY0x+m8U|`+v1DdI6*ygJVpEwjcedMY5Y~(3-T`XxGM4%&$##< zBA^#h5@$)NLrH5mj@EFT1U({5d4`gU@(^JP_=2Wd0Rhvf`*H5{PFxFtY653iu-~(b#KF9T<3tCYt(VVxh;+hSG=RuWZw0zV* zA@Nwdx#?C5nwl4ZT$<1vxj<$$GWLDsR{#-}$8kI&cK2eC)^h}{;RvcNg4S)sWuh)N&$FU$6=#qAfv;FrG3_o~oteYfLUFN7KF>eRR4F+5$%Uq2&8>)KH{e zYY?vanfyXE!mbc?6R{x~wj6$od^0TEz-p)W9Fhz)&A&X4;< z)%Fm^Jf>=25JpW=?j($){URb|8eTbkY6PQ4xbpLS-0NX0>M-o`?P#pj^c2E!L(P-R z!F3@sh|Qbb4}x|U@Gc>|BwG`*Sf*(;M{xfImE8itRa_$n%Y$R~t~@+H*k!Kx(eJ^A zh~|cZ(PvI%1fxZ{j|N}DE|uzF0nBw2gJGAaTZ8eWXW4=eVCLu@yo>0Mp<{0JMXL5J zRVzdoK_iNAXHpI;B@CUO{sW4Pu7#4K=Plso)=tD~vA1u7+Y4(DH&-POf>+7!w}a-n ztFI^ytg`k+OEv5C6@f zI)~r*-E+@6{lw48qVD`MKTfTyVnMzP*-)tuzK=xIWX||zoxE^e%h!7!pF)MN@ggpz zKwo)eaAtikVz0`uFF$sCRQR66{#1A0!(_L-FB9gVM}46{W7c;K=0lCXi-`U(sz3B! zYL8I0n9)P$VZuPn>!FbLZvUL`C&>EIs1zvnVg=R?irTh-%(W|)viPJIZ906;hbu*x zuiU#cH1%Sew~hPA)mz@omW$=3yoR(2Rd~D#WM?(>yzE8ZX}|KieDaT;i5JIyd4p?S z8<*-C_Iu64ezp~!U%^gK^biv#&sUf|vw3!b>aed-ClC%?lhcpoG0qV)28!HHFakv5?NS3IxR^74s$JSn;)e$GQB z#YK+E{aff;)fMjX9vs@w-OpPp8Lo7nqrJv-nOlpTrG>Lwq^N_nnwt)Ht8IXrFmt#) zv)iE+!4Bqb7)2cI+|YBKcDbVGI^A%^vp8RJ#j`knbM41`)Z6t5W_4R!AAkj}bwt0v z231Sr1fTCzC-s?LPe|F5mOUm(*<;6dSfab^Xv{xL-LhX?=bCW+(`GE{rYx_@_Abzygjtwt=@C8(jul_P+es4Nc^6aJx6A0Zc3Eh+lT@?vk3<;eBz9%ucIMt0d2yAtl|HA9q8^4x@jqBpP%x}f!&@n%+NK^?wLo2mx`T@)q1}pb}ZWO16ggyuUiDS+E!ky z37co@$zvK`W~;)oC}Pr9VBPY_AGWOUdM&oF$mol<%fUw5x$rOCHb1~SHh7{~PMbk6 z&juD1x6=ks1fA(rC$)3uzohKcO6W*uP!6=`+G9t}k$St*?{_cN+V+lqP#m@0_@Z22 z-bTLdk)^uz&Dt)fUDn%+raYcnC8YBDJ+Rstb|cua(mh*KKV((cr zU!O_XW8rs6EorxfG_O>0w#8xAODU}ut2czF-Z1}(NY}y~z98*`c`qUxY4e9*qj@8u zG+y%xFvmO>QSw@IM5>vN=AlHt<1A6@5K3r&lF;@Wp-m&9btZ#xg53)GrA#a{zQ5Oy zv#5K&##G7t%ZmYrOXjR?43B0r*Sf_4mreVN4~HE$y`1V8?PAgqJ~zI~M9tGW+28n= zRc~5~ai-40%%#RE@^0D3jQ5Bw$z5#p@ia@Gp-}^yPri*&>ZV5pSBwxd7tS#<1C5Q~ zCkvk%p}!TKFuDY08Dab_UTg&4S8QOk59~17O!V7O4{t@E!jkq`ixWh-86uxElBSrQ z$}KQKTj=#0C;wPu<71Tj{;c~R!;ZdH0SX4c+K-2q7zox0#YyRh7n>#r>HSH)mm#ia z7JfBni|(xF)BGsiKx@GwEnN=XizNvMMkFbkA(64AkLae^KS3vw7=* z8)DkOk;xd>euw$=742@4OV@_axw%XmQOHd*?P9P)I~DnJ7Hy0Xx4g7{h<-CVLo}fl zPF6AIP8pgo7{bd8*5HjO5B1uxf4)^05uLNIj?E7~zuVdd?@hz2wVe8d<8Nt3x0|G~ zX*{a)%2}teqWES(tGa&L#?tj_kHU*9eAOhqxNqE4?Y6GDC8}zw+jIM>>Q054x_v5L z;y!oER3gr9uYawgc37yPS%r7ITcfkec4W)fsr&<)Dt`m-E8|(3wkxCmHaRHY2cIb4 zM9yQsGOVcCPC1_F*I!3!TlXr1vAjqdF`KBR7LI6SYDD9`BJb4?c6gtbc2dc*&puZ{(W>Mr>uX*##>Uss7(d}m7TkylFN zJGt{V9L?utyY!Urv&z~kDm>_y-7g{0Dk1ZdZ+n}rOy-fC_A@f}JImY0WMt<~J+zYH zMV`Dvh6Ne&?K0@g9fmSX!28nhOPw2~;Y&NUq|rM%E2Z&77}>%YjD-hPVIdbs$(K8{ zuPPxYVrQ$MkN1l3U5D~W1vxe37`0^Q{Yc23m9BpOw0O(4;J(tzn5%~EBe&jPF~76$ zPM?%>iOAiq%OzlA-KX%SbFT>Xqm zdy8&QT{zvdO-vGba$_+(MbAz0&duHhVjIBgV$j-~d1)M+ zxPoR!fe~2s_EWDTO&U8w?x)E>A`6GpzkF$}4@(hMJ+NE$&-K_NvWUS5 z?-hpSq*Mu>!h1#R`KR$l@rJX=rQEJKUHNn2-2$G<4;NYjxQF_Wbj+Mw|IqxY1DC^{ zl%5LC;gYX?yN-FMn-5$(dNh)2aDZd2_vBlF!!x$k!(4|~8SH=8bVyR!bo3y5{N=9q z^6Ya2q(2C;`EY*wFwMrcf8R$h)`2xbAAhl?AUA%F)duurMO%#BXJyAXH`lN(1h26S zg3&Cu!RKWEpJ_86YToN9FJ`#WeB7|5j501{v`Xe3TaNdNCT4zQXky9IQNS7o4h!;YtzFU16JF2+!=eLxA{Zq`Qg+Jlj)B}(plDD zQ(C4`+Fw`_RN#&vlz^Fp3GGB%KAswxf1HEb4kK*C*o<5>#%b(}#x)s?*GHkh_#MW= z4}U+pL;uw0Y4`<^NnF1^@cR+y|M?3wmJv031Nt5R3?VXAXQ02?(@4Z<74dVb`Gi;L zm?KQ*cHAQ52-_yYZ8Tc^C!UnaJ^wpPg2{Qcii8g+A0y6yW>_9H7ZQ&05q?6C`Z+m? zn)!I)dk)^^B0TdL`qTbOK>rxIR~d~2GnbNbH2wnmzZ3rJ+j>UNNLek2@LylZIsc24 z|MlhbLzhT-C!Gua|Li}nPa@jd_Y!t96AsYYeur^_!5EJsoUA4MiMIQ7?9X!O4He%6Jlrst}(3MtBrngnUDeaDyS?KXm?0?);yg;^k{{ z#)vQB#0EmL5(Lc-gye7kcmBFbj*RUf95_VSnM~L?m#{pFFpJi349z6@)8}&hLXMmM zL#Vl)P}ZODViMt5TS881{|6S3@)lRZWwfry{r{7Gyn$$#oKX%x55nib4roo4x{z{7 z3nf)t?D{tgk>KYEFVOf6{BhyeC!L^I6P~tkXC-=g!ToHE_5~Kvv*2N0_`&>7cIw~_ zvKJ=bPvI-5cIgRt_7vjE{Jl)|Ao@Kr`S=?UJsx~Z`I54mvV-zICH@BIz{a7OT5VZ3 z(OF8{vUC^Ke4VhE)?g8Rx+2-X<0H(WoazcTuC**qTEPWMCV_H#iU%g>Td(oI!vI?tpxS$;Kg!}=|flU0!3-8HT07hC#U)pGFLhA`w(O1c+KGl zEr^~R4N7^+tCVOb92cZKP02-hn6Q+CXe;5Rny*pK)OHKYNx9$$CGCOv*?-|N^H)z) zL1(}l=*(OCbP-e~G}V9{l~%Y*Z#Gfr79$0o@Rs3doWZn6x0!m0|j_g zK<544;Hr60lJ%SD$wHffLzL8hvbt%xgOavU)*V`=EmchGyr_=oETo>LfclOC>P_;E z$??29lw1G8Dsw$1TA=Os8wt?v>2`2Q(^F_jszlpn3uL1fv&LcwGyLR06?@z)i`ifs zeA7?zMZU}qu~9IWrxgrfMlEJq&BshPlh%ADt@BJ#qA>FuC29&~v?$0*$wY~J!$PQ? z6mBC53us&9U!`iPkIQW$!*@!ro3%&KVKyBRvrm$8RtRG;w0)cS3hKRafRdr7 zXoU=uW*pC$Q;8N%PtQj5kbW_y9E~IA#eYO7iXpp z9)Rl97V<@`)Jmc!mBuxx@w6OH89?bliM!$)v@U2!n5RKCt5MB#EX)p|YO4q{Cn)Kt zlM%?+0d1eZKyA9}n@A{m{?q`}Y(`&BovfSy!?XKA?wAi)Y5L?h0A|}Kfcgecz*9;& z;0p0+{ugxtDpI0FQP1az!fbx3 zS(K`!Pn1E&`}BHpB>f-4G#Lgbv{ioD1MYuQ3MC0o(atGM&F68=(yDc!WX^o7CVY#9 zcTLLnho4MRv`1{3wA&Cz5+{^qz`Nvk?TPWHn?VN_VNi1gdO_l4q9>7`5_X9)JLP^# zYVC>ZX?X?Z0>Uh6+nMu;!VDUFrPI+W?HoChN=LyI+7>DE7-CSU@`V?AI^H}4`JbXb z6Yn?cf>Kr7h-W|N90EgQp(;Uue33T(hXbA~{+6K%S;0|;=Zu$=fES79I3oqFVMUw9 z{aPinsy=QQ5p-PKGrUD-dmQ@q?iF#3fn(a z1!Tw`$J&7|{;niv=795KrVLA#Y>H`AF4>(M6E1m{T`xxW%oonmmlAilGR+=eJgBN8nqCmD%5U6+cSi@kcNV5VnNOLri&20K#|Ld%ffkqOPip4xq(DPVtS3}$knp&@v0h)}3E(I3}9)h1B2 zzJ$?Ugi+yyk<^Puyd>p_&5U}i9BF*PxEI#=_A1Eyj0Y<+$@iA+8VKE9HO@U1Qj#+* zk{5D5j``~G;E4c1g%81rj;GYkgJq3w=%@$pRv9(O2pYe9$K-fW1K($};h@ArlNRrT z+%~0Jg$2RGSicW~wb?WUp{Lnu2MJ>K`A-n;VOJG|QN&&{=pgtpXeVYBo_;0*N4zXFA830&DN_i1Y<=-PkKV z9?+c2p=uBy8>gpx%>Qpdi1D<4u49-bx4)Y44%-X<%&JNb&-}hhNjZ1>HSw3a?e8l#~ za@>&BKj?Ei*TCG?=TcmO?F;YE0e#NC-cgS4Jr;UjGwfu9H`M z;(A=`1q2c@Tw{;&B{E#?cK9UkbybBoS?P+WNXcIf zPV09?k4_hHfhOpTBHDZf34Q1&;6;11Cym)WZjj^dD4&&dgGI?myDj)Ct$oS$!rQ+V zoGziyrX6RUzutT973VB-<58f9Q+Mvya6u>ec)^%?j^6@36XYC2oeGn?9nYF*r$syb zR(qSd!lC{uTQ-}6pWud^hYl*owDT4_@b5CpU*iDV$bav!0x^v_8F&l&?57Y@^4Wg` zOY8>`tF5!|0&VQuz!&xnME}3O)8s*|$Q@ZAthvyb*`<@gSRLaGza$jqgr`vCalFr9 z7*066`|4t+@33Qt&2x>tV%NbyeY>jrDIwf5X?*)b!fTUQ=fEpEYA9udg}RR+(f9wcOccVs-ph z{eF|nOxqh4nsCg2-*CrdGv?D=CX2ve<5_T+d_U!`kTGKSyYa?7;1}}!lqTVSe?MiA zXtudbXa%)www7jiBg$5b-N@+vGQ;R*|I`$%;QNnB4zi7>dd$H+@8&(ebwr;f;Y@9{USUvD{ck-^=P!4&bvsN4njh%eYsB9# z)jcA8u0>AglW=`&s?N<5^V{Ne!uGFiH`Fm*s`qfC&NXE9ymZciJvzscVPe+7h}Pk% zgXijatg{R`gI(It+G(skN$TJ13sG(g`{!siF2K(J7e?sOCc6!8p|*MT)v>#HL=Vpr zx1PLFDm_H|`Q(OtHLd=k&N3&>k*>aKNzFC)AJ0q{UB=}3&6FGBXWsLpLgOw4-Jb$5lo#@y1gz}HN7<1+4Yh#{n zE}$ijHH%#uwW#fL>H^68&m-#>InPysu~YY|vdrX#YHg*{!}IHg6j{4BH1R5&d9b#H zNB-(f_J@MkL-WlaG31^lOg>vG#~G~G{aQBBrSJJs*_~#e`c}wPYj*eFlDRHZJ8(#5 z!G+{k;?noI-3M8v!w;4ZzLnNlJN(*K8j;`Y7t)AF-|UgbIQ2$X8lLk_^|cxB@3jxe zoC{rp6}=6(hLM_+Q_Y#dP&%h#fp6v>Q9>{FjaNYA79&hnE;5wlFpDh8lZixj)P$@K z+}U`wVA8eO`-;x+xi&kggWYnEbS|%bpwP8Ia^6kH-un_;^4t3b#Ca2CUTqO`4Sw;u z;ZldI{M%2LxXfLL3oh1Zxs9B?C?Xp$njrd4B<+2^X!NNkAM8aHSOY#D5Iwlj`D2yH zZ)BL(h+w1~lNRX&V?_{4j17roAZN}jf?3eGj))VOFQSipUW)Vse5au5ss`Siqc63d z!AR1Q=)<1>7h=_Tqqxe&BIKgoMBsn!sh)p@cXV79-Z5GK^r)cMuy=3Hxli30FFE-G z9u#54f%#_7(2p}S1xH3tobE}y|KTO?V2IqfEYBC$vCpbJ2Q3bKnRm)rTi~lB_lTVN zWHYylXydo0lT*Csr+iMPvjbhrV!GtyZsf)np1=t8{rrhR(CY*&>U;YM=>M_w zgfA#^!U*&^f%$^d4-w?l!d!$Ad8X|U_=r9KoB6lmojH5XC^8s#6L?@(ZDZVHHqVG|eqHo;=FWkOZGWP7t~;IhS8|8-VWqzxw}08O zkfBHR^D%C3M|8;exeZUjU~Frmbfd)Rh9m0_PADE!eS~!FZ*(sgc1LzOts~8}|pprNQr(d_FdJs^{3`F}%x2bQ;!q z%kvjT$AZtZ-!WrI{3}iN+7RF1_J`0Co&fP>38DNx!b>j*&rtut0iS_ANlytEP%lmt zlK%OhnR9JR5Z*uIvWf|re?M||`xnCQg@iBRf1!C5;Ya%96NC5_f$dZ--lZe?iy3Qd z&cDZ@pT-xrUXyzjUL#CiK^Te=52JSoq16&XU1LIp#e`xLgnU;BkA5fI>qEHwDj~V& ze`gIwV$?SLEZ#Z)jj&&ya43uLBWe=4Xm`RNVuZiZir<>ZmEWZj_Rv_Ph1PJ*C32*Y z&ViC?^c|)^j(D6Pw4%rL#7S9kC7}cz?fmSi(q~`MY!=R;aqA_)(r>8k7+i()<)2CL#ID{_AaMe$8q1}l+^20TK%+uwr?Mv zgO+{pM-_`6u7;k(TKKGTA@W7bvd<|TU{2_JP}7YZVKcvoT>Wni)LH41s~AyB3(rAU zY0#k%&}NMus6q6UqIJOwlzf!jlt(F9DVZoSBZFpYXE&*Lu0B9?-ndHDVq8G2c2Uyf z6+Wa~{_UqXXz~F)r|e5#4CwaoAh@x%0r#yf#`syPoq`!g>8>!$rAl77VO%LmB~z*r zGfi?t_!>r(lAQvJz`2L_V3p_N+9t4@=qW~1i{dzKg<{$Y#k3Wwsa4#t zpqlAOQ;CQIwMzR%1sB!qO<4AhQt~HkptR-VJW!;s7#eyX3V?>SFTvHt3FPi6R-kDZ z7s%!YEk$3=VG%`*n&M#8HMB^Pv49D9`EVV`y?#GPYqbcy1!X)N#*)93@Qx@?P=25s zqU z{Ke2y_&x>oRG1v53d*{Tf!oc|UIk;C;b8qW)N4VUz#wRML=9BkK#rq7fIO6kDKWz1 z$Sz9U59KwK=q)It=Rh+ZUCN(RwVx^1QMJNUEoKK$_?VK8RYhUsyD3GB$d`2r-TQ{Y zRSz9;wbZ)ppg{3k%)&pU+y|4xLO>b!-QZTT3p($ECfX>kR(d5EDJTb8a;yavH!TFI z&F3K&K$(RSe~B`BK1h}4Eu-as2y=fEmUU3I)c=$WQO*BQwZ{mHObH9AMHQ|lioqnQIl+0J6DXN0$Dxg&|n01zkD8(#D{+ zU=Mhn11*?yXtN!-iRj5$K$ty4IZ64E67_=P)Mm1u(Q*f2Ni0=MS(HuH(lMrhwnYK$ zx&K}TYbO7j$Mo|TR7HK%1DE&j#vLOc-U0X4Y2*5hC7hsUDvoDw44X!N{-Jv`7;I4m zDrh-_?9$!fJRwD_j|?4!*UfC*0#Bb=LG)y%QASbX|8T^M(vi}N63>t0I)p|4in^$^ z{Ch1)m+A~9%)LiRy;F`nDQ8#z+5jH-=mQN2{pY~F58vQwg>^)UXbJj4##riQFfp7R zyiDFMld;C)4{}ZeTBy17BAK(GhtT^)0_keUu57MIzpzbXPfPkyL_mY-JFy$ZG#yrT zs3#q5dE{m~JjK!aG_(k(MH*U!YgZat>eqPWGYX@rDO`boRLg%<75?>lcKYITKHxPo>`ci?WxlXd9J$pIzx;K9_oB_EQy!||QGBrgv&9_}PT%QV5-q!rpx zm(C~l%d$vaNGv(OSvo&4@c10L(L}SIMhd}+@_0*VRiZFv%41?+s5MgO^?PtLQdyO>|N}T-xZ4%HE)eA z#cyzZV$t4~Y_X}}BLb(Ka!U97&)vy#yM&$7}t< zU&q}aTMx4J!ym+Eb@&~!i)FfVLBJ@cs`Sw1KQUry+zLCRry@8svZB*G=j!i|mbbcY zvMqYIj-iEV)VSPXn=Mgw7xeAkMa6OTIQ|pmu*cV_JxU$fz;jU&$YAnB@qr(sxG?*4 zh&qfp+|HF9s2^kaas zzhwG~&_{lsB6meK`-OO|jcf4Zw~kJH@5|7Am2$_o>H0)Ehi`~zR^}#OE$*SLAYWl- z`Rq1dmIb*vkI8Raa$S7kGjnHseqg*&_xS|&_`qA{pZ4hk(|jId99`t|faninCOSiq zn?k!$UmD~_%7Mm&0fr35zJ31o*j=pRmw+!te)nyi;Wb(2yK?NlgNKj&%OtO@-gTYI zLFwN6>W@ZV^2#XVh!^uZn0`HFvu9(Zb%wjAvX@oPI?rV`i}S`kTJ+Ql9XL^U$36>U(Pu;c2!Z% zDtaT;6V5vn4&Rz}8oG4yc7#(E&ur}@r!W?mx))C7E6eWObdtq>Mlq-J;0-5u(S{XH zM?e#&{osA4t;neFa9RagkT1euRftADUUba$Ttk$*!*g=oal>3jHq{kvVL0OgzvS5B z?7(37**HbaL`Q@>HjT3+1~~i}SdwwiLA3K(zMg$jeML#N{fe?Xm63KH=`%OI>{dmw z)E=@;^%ksWwH37a(HLs;L*J&U#->!E?_QFPx!Ae~n{D_{?`q+-*}}G~^_ca{+R(N+ z)&qDqu%C51IBpG3(SF7ntLur!p7AL*(`4iTquvV`1NSh%@7Oz z`oDGZ=9%Sd8y}dj%8^ao`^A? zJ~2r+bM4uni8=d=uKOku8~1m6nV`0N7MNhn?ol;a2^N~nMV?@;F(RbiOUCHSz0t-m z!8gX}1z1@%BFb$ZW1Z--?{dC#(2&+zvtQSGsZdlkI!D?;`YA3*IIMUIagfk5^8xUrz6nU znk0Ans7_nF+`?_T?Js1%EE4G8k*&o1d6H~0X3M9^V&v6%MHZId=__jizLV9(%=u1P zM9|kNvNEJ!33DH(TpkL;!aqC+$Nu@5_ZMKz;^#eNq^_=aF^UPCDUVzzDqYTn=5=Ki zfA7iKEOYxqO+k>fcxz7CU$<2&J*sEja?G-=-yqc#6W=%}wZ?CH%iNo04iaq~$)V?d zozjx(YA?F3NX}O{-!oq#Nn*+yFA13oWp7_ftUeadn=Afx$GkoZ@w}xA-W?S8#17LC zapX_$ev3ordv0-Q&_rAaEEPY6ne%Dl`@u`%$Scm++(A^j>mrAm*S#Y15Nj6cw?lDq zPOB8=$ijSXqF*FrNxa1w9rwgBzf(9~Y}4=iIi5+;bgP@!>YA!Zt7FKGRa zXg(t_>EqRo{BuriLOnOmUadOZ7tKFEo9E+^Gk?V@e=+AnUf+NEG?(M~?{%ln7{?5K zJ!$zY?`Ht-&--z|_wwGCj32f+@%d8Ih~Ejb6DR(to#5W>z}a&A_sSYh-tp`)RvgZ8 z*bJz{c$X3Nk1K~5kxQVA-eFQLh*>08aJFCSZmd{*3U>;4_Fby3FZhWjMV13f-5{TFxrKPLh`6tZxQ>mMW>`|06#g?~ zMr}F=+m2mx2etip8NRVTWIhzM`AnUGebMMe(2SUeQ_v9?F-M9%KYWj#FZi^EzQ3J~ zlB>5;IS1c_sEH_z(a&b06Ydy0CWMF@o660A642Yz%^97?h<0WHZgD`(HXr8xe0s#BIH!!BX-x)E2%89mv{!g4ZG-B zYi>iEWA_{TM9lq2OpqZ4vHEvmW9t{p=C#%7`eVdKoW(Srcuj?P&YyV9 zn7GS?xH^wGH=j64hwnN#~QADLm*1y7u@wjMJ9>8bfjpmgFma7JJ#G!!}?0QF1|Ez|g)odOr% zgU-}XH=ct9{J59Yz`fr=i)FaqR5j9*D#wVrKv|HHpOKgG2;)A+9mHH_uelSMX66U8 zC7D_erk1rx=5Z=#u-Uncc~nlf>&M(w`n)d8KcofMW6mkgh+G1HjbjWa z<{;W(G{CGg%adtl^`FUXCPRd&4P|64lEyxn`m_H8v_0!80jJiZo>RQ?gTd2@=uydE z0zZR+bgoRYlnLx2dEGPAeA0J?m0*z=+AhiK>>f~OA3R->>>agTgrn#J$@riLMQ_Ga6u{%obrz@$PKR?8=wdn*lz8?U+)8iWOW=sz0bibV1rzsMgYH~todj4F zsLUwKh@OKhB8(Rq(Q|MGbq6wA`df24^XchJNL$)zrdEsTWWFGU*-WxBT}f(Xyw(qE zPpt34Oa?Z^pqwz6-wV1V8iU8_6vFsH=N1~dnxaPImDHDmJPK%q_}O9^h|_)NCW3_r z5FO(pR_cR}q$ zF`<(2Oh2qWKCgQzC|GZU?|)q|1=LT3wa0A?LJh~Zx=aJ@P0>$duc}LcYZTC1V+O?+ zfu-lPz>ovzDKS>7&=xVQ|HiPIkGW3TVlFW9G4e1TWZcb&9tcZlB0b5kiAgMGB(0!w zq9D`BqI*26^Z0#qCC-g;RzIvg)~x#wIKMs?zvWMFq>VY1_!4UheL)VOn+y6vw2)~G zI9J^lD>xnZPl7Sx&p@Mdzd)ITs^GcR2_RDywSrVd&0=I04kN^Wkv|x}GQMMEJw1u} z!$hVt!H=}X7chkbj5~?3tSw@ys2sD07#+}G2rlowf!_+Ohqs8@Q-HROtVtRRJ_*8K zBiFe=TST)delx;V{XHmm-x=I5-U&`QkNOYqJ+u|9pr??+aSxymqaC9Op2NEku7@)P ze}${#EFJT3^p1IB!eLhn3&a2JBkM^|JYyWI;aJvBW0?I%vs^7|ggz5>nHU+xxU&BZ zG}w2;??o)DhYtx4EYJl{C2hxgO;6BI(B1`A7k0*MC-|4fUd%bw-2Vc4OYl#U4Sgao zc6m{#;Gv!kC82xQP2Qdpx(w&%d=H(3Y;;e^Z@eE#Hw2$PvN)s<`9)Yr2cq=kkS3f| zFA-9UJ@%m?rF4(6nA<_EGA|nakm+QxJTj8X5#5YyiQz2Xht*IyjAvjnltgvIDnj?Y zT#H$;^nyt6T9OoI%Z7rXIXJ)tUNrcs*|T|3!E-fCHhm3hdmy+!HYh|QgQp@$OTdwD zWzhA*5$B?VxYwV(C>OK_V}g4@Gw^(>e9&m*r_F&w$nv@ZKOtB85QzG^Ru|Zgz4S?e zjo3rv99T{IqdZ7YB+F?coSDurrjSJeIDY&!^awG8WhcR`rv#rHK<^1k?k)z8yu65v zEvujvyq;u>?Eic4-4*=-KCavL6$S{JW%GUtn5NNkzS;lfgV-x;{e2{NiB9)dzOYT= zssDu|DpI-rJ2&V`8~86AV`okre+6zpl0MmJc7|d!r$d}52&5Wyv0Z)nkEdy6TzHayvzk-*rB0s*u znX4c9wj`AusrFR~4mo$$m&^5uh`Ue4i`f#rKE|2{WmfoHR9t>n&1aEh{Da@#eHUt! z9(d<*UwtyoJ78n8%4u)22^DHw-cPYZUdkJ`tuEk=-laa|ErijJkM~)OAr5+<0IR(Z zBOjOb-b4CBSXL7}o+)H@9ypHaWU;`XWe$GK^ZO>yb>9g@ANc|J5bw&K<+J8{^S=x` zSnX9<$a{XX*Y)JF*K0k$1oz%{@^o}fz4ycO#EaWX4?TWqI;cGG$Wk;_uk|pwxlh~4 ziX!dCcCt!pPfwX!0-PgYF#|m0xs6J)16e&j%yi(=mqNb&mrJ+{2KM z^Sk?jW$x~zKY-P?|6x+)$3}g=TbRN_L~l`|ml4r3mvIWw)Q|ameNF%{)tG zmwlJkTMxNRKeouW*ZI>H4SO5sn(03shMZHd((v9n1fx$6XAg{lxSZjOoqe2NU_7zF z*#I3szJ|XsYv(Ni}u!o=YE4050>%3!+nCIVSFN|8g zLhqFcNVn&OHLtUW{REoZ?;`ykEc0}$V+vWe@8U^iXLq6#>&uSC9L}a$4nsK0J=I|s z-Ye>4ulIel;#a$do)~peyORy)3@_Nm7WTgwwmpzsVB2Do8>jiVuGVIa}|N`V_js>X)Ef_-3oh#YSkRfG`Hyr`xOyQ9-GfWW$v*w$=2Jf4~BSEJj)488$4cow) z3-j=n$*_|ei&*UZ_czDAJUm0=K<&$BfADtB(Pl@#-?Be!s{dw*`)!lXh77+3lM_Xc zLh_AMQZ7gBF+LP37U%rD++8#&>bZ;sciN=qQ?(N_QjKySak94?>D*qID`Lbev^;;J z(cBZi3q%b+?wU}jWmvXkTG10jM3Lg6G`qck2g@@9vtCl!w?Fi>BS(qB6E*^96l6;aP- zdaSBhq2_GKRX3!zTPLOAglfm*&982#+DMx;?@_&QrM@Ltb^fU>traTo_D*gqR>|WM zY4=irZ|vBmf|~E}P=TN6_^5(9?>s_pf$!8;L0;NfqJq5i^-LAS0<5pXH!gdsjm%Sc zvKB`B52G{}Va-BC9W`(J;h72MqT|)zV?(7?Phm&5iwZZ+yEyw)aBy0#*pqv2>WlX( z`!yO@L_cmXzEr#J@xfHS1_33Wx|deUmIK{JWVf#wp*cWl_(A3uX6$S7p(=2km7SfpxO5E790TFJR&C6ytH` z&+GdG*gt<);S6ef>Rl*LFuJpw!^u*S%ZKKPvX3yY>nO7wJG#e8PaiaF`E%>r+iRU8 zQomj;c#|YGzWCEShnxFS2R`kUydS>x>n@30PpN^i5-Y5X2d|6U>0SMCOq}b<*q_5< ziL!~mjl_hnY7b|KO*->@B=$zxL9IVVH=Nc>a}M6PJ81zY{sz1~hjRlN0=SxS7UNi= zD0~r!oLjR-))>8VNE+IFGjAdPjP}22fSG?K3FM!J_F`Y5S>p!osF9oACDFe68tkX% zFOfHc|?cWA`-h4&jl|sLj(CL!1Lz^!Pq>28r5EKpf91*=_=Go5qb1~O?A$rvk zz2A64vc;1OaFU!g&P=kshF=!g&5y`)zVGl>FmU5r@ZpReke?LN+ZI9eVvs36hm0D} z6*V&=cXXH{nu;|G)oaMy;@=4O!$LL)h2lAd3_%UdMGsuOjk)Nh0^-no>f93!=Y1%@ zH}>mpLf;TjqmT=B9%yNa4XBj7^Nlf^fx$(TMRr zvbW&#d$Fn&MsM^ixPST}=AxB(k&8AjxHy~vWbSvF0>S_4lBYIxHDngiIdDFXj`oh0pHSz}_e4sQkjVt^W6X``}?!{It| z2jvxGMAhIqM$RMhEZce%-?Q||HgHMhLS*Pm;M+lrAMu<*HX|}0lm!^)5*J|Ge|L>Xqcg(^DkTbzHUjLue{=e_y z$5HzJK9+Yhb5Xf$BQZmk7>PcJ+?JJXzfswUeNs)4%J>e{IH;J?lUJgYZ1%fRiM9t7=?Zh{j81bEU9eNNBsMQ zMFnOp5(RWc@DcH3B5_|Yaa}WUUMBIM^pBkS@0I_37eCM^pr8F>a|e~nm{nw+r*ahX z4vf`UU$BR7zwth^{I3Rz5% zst@wtqTM!_ohbZ4J7NlplrgVR=z1ID!otUb@Q8(%kNScKHeiffxRR6>P9qlJH$cQG z5ZM~|hOvVYzl|&P#7gD`Dx67GIqQLC!&ENgVQOud+K-G^h{deci}{8zt5H<;5&o>` zW}7{Jcc|hO=#h0AB+ZcG-Om`e8h+m8U8B6D9L!8SpJh#mCqxV9V3>)ccX5ZMV7GkF1|@uikR{u zR{wX4Z>JoTyw}#yE{> zX1=eGd5XdXbfv(6aqI|uZoc71ZE!&wB6(hDC8A2+C3??&?yqQQ$&L1bUFFKtJ9~4t z=!;;j;kR-uSSIZPV%saI%QFv@p;H5M&`#h%#?6dejA$WTpUF6xaU3xlYEaM2+ZHox zFJdvKXf!D-WNlHvdQpBmUCBQ|%tKxTZW-AFRbd~YB$vDGExy015?6ARv!FI-X*9~& zH9oQO5Wq>%BB=DJx3|pULv%@doubD}(n&?*?(7;2FjvjQAX`Y++o_ z$a+c^Y7kZt!PGJ@P{6!)!5pR*Sp;-C5_8`(o+IWk-;uL(1hthN^)UfF){Z!zRb6=% zRL;W8P1fRQNsLx2e9$8@jcj4(nP>DXz8zi~A>KusfgZl-mFZV((Z|#08KC{sI_SCfv?v)5(16}W zk|uQ=_my^PD-XEkFL{tzOBy^E)+2@)2N*vxqF>>92P0|+H7w86K4of|x5-YSa@H5d z-Na1h$1_@~oNi5~)fKVsvA)V|>Ag-i5#FFsc!A#*m)u zDa5Qb#LP3q40U2UyO(t4h0-MHN@_0S{t?)AO5~?S;6XZ%GP$4<{W1A=HpWcJ6QVz1 zH6+0ozmRmtwiw)K06S0Yf4URQrk!7jcEV_pL`B}k;N|W6!2{FBO--Wp%LQK&VH?XA zCQiVaf}DgAoXqzr;X8KMb0>U8d{d$|=FQI&x=4Q}^CuaspQf{%GA)xS{KUA4n4&~X zE@EU^PLj(AshatT8^7z+?gXx?9Kz~SX0{F}83Ppw(|zG>;o7x>k{t(Lj}Zqa_`-5y66}Q6d&Vdk9^d~U=J3<^CtPAC$nl<= z9^D|aT5xrA^hteTuV~wy{MWBVtIjbOdl(Jn5+>1t*g3yA`XqMFAB#SW9XH#e(U))i zjNXd<^EuJ@C25oB6{J78lWJm zgxkj=5=7$U!XqqC9ltj%;?b___uoYb&!714N(5T;(QpL3@7h5sV`3Cc|8U8eIs)2U62@gznwj}*;%M-hpPr+&C!}(>zK&T)>_S^T(-2qejekccsu~Q0Xkgrs6rzOeRWtY3i_Ua-LCJo3%6UQ3_9xW$2Q4FQTAhd}<*ZRVc>H|+7X90;7exXC&q;2TD4uLC+T?kT3{jO?BUpr_f7 z4afpD0+PXjfEbM26#_ybe^exksu8SLhI28Ue=9sl!a@jUVWZ-G4t?qS{v}nv6s!EN=eVgE`+bO&)E)0<1Tu%&Q`U6=%4Y)v8{8<$9i{@}Pw)+lY z{$ho%;GcBKcRmrHPdzy0!_|@WOvKxvdYAqq@0B^tX4+m+vHsRgUYGoDIR<)uxBu=Y z>KXKWsn;S;S+(iDI-VQvln1DJ^k3%>s`Ds3;}jC+;kSQc*eMUg71zQ8JYXjgt{zuW zvmze+V21~MPSjPoev_oT&Nc_GB)2*%tqe$A zO79Fx9d2g=W4>Ep~L@beV*=bIx=Y=BzX?aq|Bh>-d+`l+Nv*a*j``69OhX ze9yfbw%9>E?qu{BhdBXr;%)3B95Rvx?XMe;P7|@8^K4$`V!P^lW3tWc97OYT)$L@@ zYUYoz<2mS3aMf=4>heNO3bsZ3wulx*J+>{#hOgTqqbg3eEkLe0*){_dvrPcQZ6ip( zJF^+r9#ZZC3&DzpC1zf>I%#62EQ8L0m3MG3#VIr|?Qs_-d+i!p)oNfAuRdm4JoQ+mz9l7$IEx#H+D!OGE_{_fK zi>1^(m-3yKt8Qpjj97d*CsTFDqUcafwV#Fm+VYwN3)p$>QwwAjb$?k%f{*E4Fm+`X zu%-Hi7CfM|#Q`wNVms+~WUBwy|q@jBP&x&U(EbJ zv&iRg0(O{>a7-fx&5wLpo3Q+aZD&YYzS)Nw?wqw|61kj0F4LEBeWiO$r2|STCz=d6 zn%C?$aWMW^mv3@LeRabs<39>KuMQfgik)fdF@Antwq?Ju*pcP>dceRNb!$R7p zKSw>b+tHIF?LVJ)U>5!S^Lo(sc^TOB9PzSqizKI*kHUS@ zi?P1C3iFaPjD4{4U;p`j?4RFgh<<7rY=ArRP|=sh>D=vlh{Ey0x_fZ`jDpTy%rwr> zzKnClmuV?|39R|08TI-=qmIUxn#R^~8t3zZJCCSG#s_pKs&5K(?H&Cr*y-83v}cD+ zet#HJ>(IFRd90e*{opSRYRAMm-_EOzx?t3=tXgsO{lHUIzb(tZi>PW&yZ!x}>MhKW z%d1`hvsK}Lh9;|`FAwpnV*E1nTy+^(pgJ3;7whSL;Be&5=t7T9k~VS)+iIyM%dNT~%%lr&d$t6n01detP-Kn|App+OIXc&6Fc**YsvR z9?l#25c~L2!kEuPN*O_8`==`Ha{Bn)^HGYa=1|h3s~R7F20r}x;QDW=hyD_k!#NKn zFTNOg^>8x}_n&gbU)!c|d=#r@%ffPz`GIbXFBr8Ll^Eq1MKKe0=o$RK;YL+g*h$jU zuXul}<`Z0rk9gdOng1@Odzc*!eKZT2*D03cy_}&BJg}pC-hK4wxAPU$zi#=k{GP?@ z;xBLR`q!!s)ZJ;%zxLz#9j*kq-;VO?L684v$+bA&M-2&^O~(@wJ(|{_hT?p1xg;!6 zrs`54XmcE%Pey#lY;fEB*WgrADE*DGoe^FLSF#zABchBLXC|x&tM;6AKMb`!_a5p$ z&EU=mPRpMpe;RYq9N8dfE|Xcp;k?$l?a$%#N!>!tf98|=3%jH1B+I^P{M436>RK@} zARbs-kG0B-eB`hCSm30vtTFa z&$|zl*@gahb;}ZX#H-^-p-2y71!Ec`at2&Sjs%*)`x{D&;Aw?Lw@@S56D0AyWk1C6 z+YRD3;3qqju0uhu*|lZR942xbC!);0l8*hl_Cm+e?Ky(^U*U}|J?&D&3dP2{ZSc5L z3YKH7p+E5?I6hbov3ik<4xSzpe1ZGs57znyPI(xIsG=?92Tl?igVoN^ljwhZqI+-` ze6yFM&Q7`JZZaLD+c<--TYRRurCpfPK;H z&rZdOC_#LvsbPUrdZd|Gl6V|8iWLflZ)kCDzpiYoL^RbIW8L9=0b=-pti))nd*2K0 zfLB}WiniMG{RPUqN3@}H_smCH9L}x-x9stBgV7b#_KqK?XMn2oF4P?pSH8hB4oPEi zkK38eZ@)-tw<8LJ$e*#|(94*Q829A$I$R?`uarEA2*~ z#lK1=Zdpa#ph;ZwiMVpvHz}+>-0fa~)dZosw;awq;etLqzwk0?4OR-)hDhMuAiA#5 zIXci>oBZ_OPiraRTQLs7Z(^5{Fp|2^{dI; zcn;^6^M-i{~5YMvvJ+hI?o8c|6KhK=_Px^mp{`Z>yANudmuk@hb zVMTuhvFI4_@6&6-P#?&!;DZt2t%-W9&Y!UBvT1bXIxG#Nan>$JXHj|UOX4#0JnTLc zCI08T_*XsuZMi>>zQ4zb_|lA6gnow^3wAGI%)&jU&=o8AAB+rHi#&mcz*$~pL{T}S zKq&FpFmVU7#+3`HJhhSd@AYHtEr34ps+8Es{(U2}*9Q0zXkvBoaxazZy%<>^t8=7s z-LgSlWQ(zH{lIe#Ie3!cTk&MjJ^3am9O4bmaB;yCCbedm?Wy+BI0!zz_XXs?{u5l! z#{*8?C4!ZRZ`0kuR?=Hl&WLD*GRD|oG$R``R{68C7xC3rQqssgLW4GyUnVn-Ce~je z*2OR~yR2n)Sqpy$ZFYlB;KsL^(2&&tpIt3m3_n*rD_IY}SQt_W>bm5Cr_7Fnb2J`f z#i3ha511^9?55IzFOt?EcHv$sZ_P9Z&y%W3ZpIyq$a!#ui*XU-T*ev126#7UhUbCW zF2<$AI(SCZDpOuNoys+=?W)RrJA2u#r#DTv+PPwx>C7v5czmT?AsxbuW=c^ z^J6i7r`$dnF~9t5=n`;@>l&;wR2P{u=sUx3TTqD8ay1T4uAB`)e4M#0i8vfn&|IE0{77i zidNi!)fN8cPXOEYegN|p;I0e9NL3+n9?+7}kWrISmGKdy0gC|lhV`X6=6!ljSOz$Wvkbi;N zF4(PE368#BjTMJFF<47};9YKiCD{6oaMb9ylb#Z06~)JxPI+RXJJZ?0$b4+RF_rT^GTtKQHV-`jWqJefo!=T; zLCX>zaA!&~))YF!R)V%}sNrlu^U>g9Ewq1D&jTkgLHs0WbqgrV0}I^YXY*oBU#XWFe~#H{x_`dfEA%$FtMJ4$AS}O}ARH>ipPr6`Yf^h|WS1 zyqA6rPpPg>$G^OylYR=h>LWViNkl6B5b~xA>AOjPKJ)*1uB0kAf+?(E3YmpuAE0uU z7BRDiaVIgun{nPyI%dUOdVhnfULD4qSy~BNHSK!pCU8QS=hADbac)g}YEvJY`<>uR z-K)Lx{PWaNichZCrc_E?5!Fr!JpWeWTZ+*k>08k$ce#Gbw543a{`pxc$FP4sBL(s6 z-sqHd*fT#W1=g+*pRxeE59Cu|qYoCRpuSM6ZloleSxXknLNW`Pwy%sEi0OBUX{n5? zkEgO0N$DSYgIwonA7W7Q?^o~#$+jgeD<39rO_e!(A*nH}^IU0?q5Ima(~^#v|ByV8 zG)~)Ac1vQp;#&ngS0&N@P&M(ffb-*biGqj4p0*|KSrwxum$(?aB(^3_#GZMR1Vm*` z+k{WpEiawW1O7-rjMp|#Xv9cjc|r~8&)m**viv)J7gKnKn5sZb@gOF*GO~L~(xGx< zFQdp0*k(dqpXiF-gsZQ7j=qY2U%E(8C*CkMSYk~4*6>a858@i!)gDU4Sz26ssu?Gw zGfKTPZZQr|FpPa8sb#PxHtm9p(T`ZyBMK%8v6^da%*-5;Y zV0J8egw@elw1rh#>~icCKJ@o_iK#iHBqf0mAga|O!8j($ zQ%Av^J4)tZkM)kI9XIFOU5FZgajipE-b&LBN21mrbeP)xzC7%=XbA* zRKuLCQshIhGx9F>@n4F>+Jk3iBzhNWvYshqcM+e?v@!dMZKHB5i*7Nj7e}+W994ud zBySYF>$x$J=0B7rBqPW7<=oec&~BQmY7{ZO)Lw6TxOdtvlV{;4!}G27hV^-@v-b*f zw_N7jA10>L>E0T)^3g-@3!!~Cv;8K9W?cLoup`vv=!>8^q3Rn}1}BF~VBGdP^ejd{ zMRb;3m}=-&tnQ2pT?5L~Gd|&^q38t>+d^lO{#fQ!VzNkWG|SziSX)FE(3QXUu|=?) zIb0B<^tEBmn7J?xMZCKc5-Rk=Uqv*eu=5pzi!UYy7nRoAjSs$>rsi@pXfR@q z*Zv@94;{Z>L1!)XgUW*@>I#RQ4J>~2BT^#JT1qy$Ht_bPlGyyfqsP4Cp9L=4*qksJ z2tS)NKHvlRGN1*v`!t{u91K9TNVyb{0fq)7!oJ4`M3Mf;{Y>X9V%TpYX+s_SVTAoG z3=hWY#@V8vhuG2WLht2K_6i)2d0oE%i65=z3jSs9_Bu}U=Wep`aP!M8Tkfy!Cy-Ve zI?nffghJFtUlWg>xZA$_Ee8`Te7@CoV`0n>*QN{Q_L3dP60c-5v>ZZc>92X-pDHoe|g)&?+bXFk^Yd|q%)ZH+@RT1 z4rG~sz$l!{AnQL9`=WjPw%`<+_rBM$qkE-~4ffAp^hR8B$nxIxbG~Pbm&-e)pv_+6 zn(8A;J&nrbb92mP`0+kY+y~qA#-(@1K~p3GhOk731;zhJDc%o~Uhud=K~^8xMEfg?p5n7k0f` zyT1P^5NYQs@Gd-I*d?lYepk2%$QhF9b{sarKxdpqsW zYpUaOeD^r>rH^CqZSzJW$0tH6O_LnY@vdwZb6mT9e~XdhxM^ywq7Ja1R*pl{s8Ma2 z^q!ZtPKPYarEhdVTyKBq5Dg|epr@lBvuNePvKn`O?47N5vkE1ebL99 zQFh^ST7ezi`HrVB(5mL9PESoWvtgsp6PPMxgH zw@B^Ai#7&ci<&KL)>vO@+h<*`FWV7pZKf>!`jz!*>C4^j)-$dsycuWJbyD>0ajVpw zV|uSzIn7q-TWY0^y>$szXoYuMti(Z6D?zZ_3K{wPnN~cYkkx+D@61Ov@Aw}6WUGTG z>_psN2DV*ccNps|qim5E`7E$miaq}o*6T6z|Jn*Im36@qeW7T&h5yg;if88i?+?@& znxAZrc=hB(WVvwLoEOV8R&{on`9=2iXq#>IvhLM2EwpZa_rp|4pY!pU>FOu*KJ%M2 z%WU}a(ZpN$@wX!;4^M^k%b4)(dNXjxglm4^_f;knu=6~|_$%hmxr{qNRpVMP(YOR0 zG|tBS`5xmW(r@zs^O*as&~ufhS|S!32Ux(jyKFN@j}B5cL!63xVTv}&sHfAV3agE) zIGjrP=di1nPo6LQHKRquNc6o<=UYRM=HWLg2AuNHcUcCvGjuFS>D{}Zb#v?qZRth;4#B+kN_ zPIC@AKNyjrqKudeBEtsr7}2|h^vsa$KRIKP3Og~Uw|IDX7{T+0%hP_@5YZvF*@iSEkAW8VRy8e_Of4>dOvDidSCEqsit8I|2IjE#_~Udw>7qBwEj#| z_lim$?oyxc{fuMs%+uyI?D2>p;=Ee>Q?#C%nJhfC+UcvPKeef6;2~67_aRSFjaoJY zT9ZOmL@rR85i=AhpJPN{MtL7jUvk!~#rg9WXdtBJ!@yGk|Ulljdk^-5i ziARyqQ2S^u`Gbd6wvWJ7hGkflNKwIcMKL*laQZd)j|Wx!+Mv^cBcSX`B64dG9tK2? z0*)cxA7XsZh+N1qSrz^yM2b%LPA*W6!`e{&V|=b==_8D=nm;LG{;1pk0m>gP+#iE^ z-Ocynaf-|QyC&Ej9ehXX7wk*^#s}1!oM_7kRwcA55Xof%G7$r%KSu|GN9YN;+rDc}q=MLT>yW$$ha=T-9XX?v)7kIf)kFKhWozJ}Z}yMj0qaQT%~VF@wJ19? znlfr2zOK2i2-}`=tK81Ti72|aW<#^vO?3|bllVat zcP5G*`Hj*1jY%J1eb-;M;ybQYSFXnDLsiyFMCpN;<=|4^DTpC5cDR=-MbD9UT-mRh zi8q8q-GR>&Iw6Yk<#*@Lfv$&tgCgq{z_pVD&@YjfgRP8+zbMBs`ZC%eZ*IEjfd1Gl zf!}NXaU%=6&>gNn#%jfntBAQjP6;o9%nTt|JO1r_;>CSL0Zrn$!rwZG%sd}wU?n1{ zH5#iAvX!Xq(+jgKaUR%@7<@Nxt1s&F#2b5VaKZC>tQ`ocK{=1--TUAqS|>SXBj5|J z;m*YK4mq1PfSR*lzeo8<=TT&vSY;St>|#Vjz!ls}?a(DHhA@J2iHKjO37h1zfzTh~^8!cz=iv+?~K z24m;oDTV>R6&%jmZT77k&T3au|Vsb9PbN*)#h zPcKKjYT8D6o0c-pU>r|;HOx53h`b0_kfTDgG%4vcC3d6{+tFvilf*VwYpwA4(0QBK z!s@Q&I+dH-If~%pFDl^Vj;HwDsA?}zG#lAU(@c5`!K-2)lwX6XdLg0 zxsZk;+xwuMffaaLSpeL3OADNJ=`dCwz8|p!UvYVW$SpxOHhhUO7s^hI_yo!(jQWiD z_fY$ul(fOyLNoIbEv#QPGdpgc!gMm9_^N`+uZ|HLGZ~L_5Y-#%zQllcIugNY)xG$Y zxSaLio!Bej3STI!@3h5eqdwdKS#Z6&vMYGuRvWnSQam`7o5odNS9XH0NL5`SBStGI zM=<&`dNR5&qP|eK%&J>htu~)#YBib8EXJ8kC-V*sh*eN{l=zZa+DmQ@TED*X3#q!* z(F9JYLFQW*mU9`r8EXK}^L>OkS#SFW^fp`sDk^^hd2XKqmk931NO6Q4_EXcjdIwlc zs%lUdU@#+E1!bnT2JMG3S{*bbHnBe6G=Ztz&eXCV(ZFKQOV+zz^3(PDaK^>N|5?AA z&*_E+|1aoOwfj0p<2##b4uIM@I^fP&sHpDoMgOh#r}t`BD;i3J-1O$R>KV6TBUOEZ znPAD$05Eb5{#6yzS%o`C`3d7)#+!_YytppRc!}5;L3$bri7!7gGA~>&&U6M5YgrrB zBHlw)F(WUr8W9=1_;oS9v%Pa8s9hriuFiqB%KF%kpouRms*=wRW5LRqhOo4X)+fGT zgf#MkiszTnqbuZ(;jb0v*S3SZNmT_G<7~#ih~?-};1J_CMtnOo3y_BTTf{m;Vr?9; z<})Mn@6{$$uIgpHM64`fWU;EE`s;E0;>}L@z;aHF4d|WI1q#Nk1IPKH=F4*I;z3iR z@u2Y2ao{>>qCqD5vx0kJV}4`9MVv=l32-2tYG$E z?!>e;GqU`qRENqX>|RQ)Qn{FUq+;Q(@SjB;o$wPy>NVfN#ksJG!lF1&P{j|wT)5l* z(wx?UpGFB=y$f=m)*bFIu$Hkub+JJH%Gz^Z3eFtw6cjDkv}v+%bHPlUlhdD%$Z_LR zJ}g9hMScgeJcs-SNp5OT~Fi=QLsw zv$4V)Di`h{7O?E9V9VDWtRuvA;&<{d)Na8V&3k&IeV#*H*B1S}lYYa;`f~r+2b}*a zH~0A>;gDQ26+ZF%xz}a6Zu8{sxKb|{l{@`J**&$KFPon~NXx0i{`v7a**Gh)GzWLC zyeS8@{e(XUKKIG59N5)Uw;aR*7494s3rfe6l9I{9VrCUZhnYforqG+1-@|x-n8z}b zys=cyeN4<5`uYV_e?14BTPwXICp#jy>{NI5wfJ>chO@`|pOK8oO0^%B^U2bAuKqwX zi%%t4Ss-h!Y?x|AX0Ncm#-+>x-YD%GnSoor>5a~Ofn5@vnJU;he=SoUd*(GVZ(z6l zy-c*|b57=2ocQoO^CU9y>6u5V{tNX<1MQlEP8M_Xn9s>&-adC6Q+Se?ZA;8zeI!em z%9**0yx-RBh{(u$eU9HEL$uaM)GPgK-b~pS>CW*=4kgj2OPAy3x#3Dr(y) zG1U-rRr^!5z_3(R>=j;-%6fF(-wH=aNe-*k?1fC{A*PK*t_*)Fr+;GPC8mX7yp)=T zzQg+|)$*Ij^|I9Iul3{)r+C-4DsM{JmnW#XH@P`J)$nApzW*1qsO0?)$yNnPL&ie( zl1XW*3C{9KhH@=#?n&20IG*d0_MGzemQI?xeb84dad5n=Uv6S2^6vITSbIQfB0NIi zqeR5wz^=p??2kW}7zV~9!md!C%ziQknYO>l?kJ5#fm9Z`Qncx>$$5;>eBf)+6O73d z6Op6Jxh4vIvwS)yq5O50PI1DGx|OC|;y>oOS-*(4PMGGz7r!^)yn9;QTgO#COXC8J zivyO#$*b`M`^N2%*9%jL8*{ZhA|bZrbVO84Y|2iPn8&ehQ_N!HVvR6*h>3lI99%6H zR+O+L7P(!5ZY;96gx1&#ShqMFdxrF<{w7r^%)e_hA|+*qM!Fdg=RiKV`P?-{a`;WzJ9XEj92+x2Os&t3$-Tu z@grj%?Z->{!<9*G7>li;i>MreUVO$h2t8VUP0(Mc?eM^5IE7|Gz$u)FuIK*@`{zYz zP9bWk-*n8P&+t|1*UnV-Y3M4?eyDtA#rH!{-;=S4~uMr&2r{U$})YkOC zOV~8Kb)(lbb>ntd&+>amI~_b7Z>;ay;(71vk8Vd#-u-Dkjhx1ZK zpW+SuzB|0&ks=&CrD^8h!ymKge(t@Pk>`^kO{ggGjov$P-q5 zW4(tvW_3@x!)KcBal^g12f7}>SuTPuu=a!!XViaIs?%+pDWpIC4Y6a`Q_X(z-1F));*|UBck!@ zhnvk5g{oh|)|KKjekWSH3)~nUuzqxS#-C}{XIFCmG+J-Nm|e|!0XS$qp2qL=wh<5+ z1=!7q-mztz3$kLVtxiK&+gk7Fh5hrq4ma?$!X$h2=;(Gkj0@7^ZTeBq4b}tDoM8>? zYCLbX31_)nwL}!_;kIxY5PtX4{B?KKXC?EKFOT+@z6dS&IwbdEW0KdeMzfIM?IUSs zM_gn$9MjGhXlGM1&FA3Z`)=5B`db3OU{Y`ap3KDYNHlnVO$&&+1@|znWSq_T7t#0+ z<9F$%Nwlf zgqvf8t#?UlD}M9W16ZPNoCIQy?z4-@;OV10;G*?vv~n@}Er=Qhix?9b;d5}shY{mq zBPmmS&h42AJWRy$=h@glUuJX`7IN7D*Xy|SVJEFYde-reB*_UXXnJ0P-XFq09ZIF!8@k?*36{LOc{jt5qVK4~?e zwre!k!a}Uo4KWuTp!O5>d`(p!nn&o=nD1^+VC}=I%C^wVp|?vQf}vfoLLv2?7d>9S z2Q8-P(13e=P*k)LT#yW_ysr=vg;lkeZn$rS>lU!qd)?ajzSLw8t zXFPyK_75tcW`FnJyFxne;2z;q?-Auz5oKD5(&^vrur}fK23hv4poSFmr{p4Bx%nYQ z0bCin8&3r(xdmYDpxtsjD58V55P$h-2B>fgwJknh2sS2G%qs=zZ^vK7E-knXZXlgv zh{EtLh-e_YiyQ1NZe(HXBy|V(+%!f`8MXad<``CmL~e7zHaw&d#qhgmdwl&3)thlnDmS>!>NzxQD!;>#Pf_~o2N)Tf|R@n}5P;E)2Fzvvp8Oiz-zbA#h8Be8ZM zth*OaH^e^r25!9#-*ztJ3M}W`jZ+iAF*{#jO(AE=N6>;apOs-e!AO3Ia~9bJI1y3o zs%Qw-S$wX-+P|v^qoz3XFI$nSiv*4UYzg1FhmA52U|9UeFqb_(kS{q9Y8t4x!XBvuW|bpPNfhH@pe-mah00^oU( z!&pa%IF0()xoi*WW=9+s>|)1F(z%0+xV@JVSp>>{jED|jXP$)R3~%LGKuV4*B_5bX z+zs2sCzGS`44vnGDzjY(Ng3V(*_mG&TMhw>=dctO)|20vcsa0lW*$BFF9d(AM0C$B9=ZNrdtvtqKRG>L|Yl6 zAyfObjmme%5^vNH1^kKJfy8aB6_(^u`QPiu+7-M1kMI|GrVtj4oe}Ue*eg-U$VKea zBldn~lqJ4}Uj>=sw-bK)VyP$hkxa#9MllLz)!4wVT z0^Kj}t_S6=c7gmSO~I|3e8IV-w|fk+tDo^LBRnUrAfkaajL1cyc^4^pFGhUF+O@Bm z%6-d-z3{8h$?owjyeJeVFdiiKWH1W-#B4`*U!MnP*%SmGC`rSwd`is%{X^A2IaiEd zyLP=Gj?zFb|GM_B1{iVe5@>m98TfcJ?)NqR2A*cbTq??27?A~`49^M9XT(eqG_#)8 z=SWI=OBg2;-!eOR6HMhd@MTb|MC@k1qg#&3UCe`YY5(j%d0t-@zB#1{weni3qz7D( zifpm7JQR_?)7_a@WJGoc&CD*}#xkAVjLc?wSTE{MWt!ptp^#b8>wYS~X6@36+zWb4evJl~^}!N4 zvYQ4#`O+ES(zK;m8L0{F0Il7&f@0?Q{q{{7$Q;{#-$U)T)m`TX<4=o#PFvkUEmGBX zk5P<~>2G8D+nD|~roU}3{q>CrY3KZxSoNx1QhUT`jrBKy6k|qGgge|0zAMFThJ#79Q{7Vx(qNVYk2N-=l6|_G6 z2UOmM?6QT;khk!WwwC>jn;4n>v@Bv})<;@UM^G!p)c#$!%oleu3+Y5&0<|i{_9{k1 zdT8@wTuE&8V%+%)zt)oTZU=a~naUGOp|&|WO%J>uCIoJAi-d3bZe9y!Y5IUx3b@~< zJEA-wKVLYwWjms46SL}9Bc$yW><{c@tY@rbEMd$izMerEI=2!#go*8@#I{n#g~V3o z4O>{hZsDdY%`5^nvpZ_a|MdXBd*vN!?$to^6VS2L6FifK*@DJjVb)-h+aRc8u?jq= ziP~;lqM(j-hknrtu;z?B7`FrCss?9L)nLeo??U+wqc|h%3|BCU2hS7RotaK%|E-No z?G$3m8K%>Q*z|^xkN7H@aTBqT`Rm4=ztHa*GT*^-Hb^x4gQH7P&;J*3ZynX;_U-$- zjcs>rySu@}z!n=53qer{Q9)D`1Oy2I=@cYI0qO4U?(XjHzVEsA9(RoUJLi1Ix#yno zJNu82m&G|>QJ5#?jvU^udq0dEJKad=gv@V6+=S0%NUo>7FOEZ38bo+do)CK?h>S;Ikz7!ZvJ2)*-XlWW|gr^#5Sm%T# z(k5Y*o|xKC@2yP5EG!n4iu#_*rq+@Eyj7$jcRMlXEHRr|dzKB;##%U&wSUHEI+D)j z*!0^}{wIsXJG2aWguJG|K*{3M;LPODOEpsbLwvXnr#y9WzEF^|!gAm3amf`rUj?=% zJ1W>c^G|;B@{PE3@_Bx4iQ43i7xmu+B~RMt^L~C({p{N^Z^-^W-b%uFmdi{+zbee4 zyplpek`3;hmrOFplc3}O&M{@d^F(`2W@?ucGmaC}nU9j@MCDXwW2x-wQrP^HGM|no zt1wO;x&)8sYtyAA_mb8Xe>}D`F(f&H_j96f$lyb@#JMg5BFPB}mR}__629uROJ7O2 z_GzKqiiBk^M-(07+xhEMj>IQj68rKn{`dYa%{B2_^CxPph?mCw^B(a}ap!zTJRk0v zABw*S@6{n5{i?q?9;<-=YX${F5d$Q5*{`SACSz`PPgyWGGhDdkQa zffK_Hc&rHc>2}{|B;cm?(txgjS$ZBJ=Kd*4tHR6u^(CK2srm~Fmd4ooALQK;r|rMs z$hCx%ex0jcB+C0?hD?(4i-moh^Fy2@xzo=PmM!RK4SM>SVNCwvXGr?P*nAS2NIFAU z`v=3Sv3F$_6^N00S|bp>AhbK+4x&q4{uYR$U-j!n6#b)LJu#w-&Up%ex}MDb z1A9nqKqk>Ygy`poHwbk4h9Lq{=7Z7k;-2>)Mfbch$Le-^VWeB!_QaJs-10=fcpUPO z8~zpW(!HTMHhiYLcR~PE5e4SEu$R*~nX2nF8Z`aRMTDeGab5_rBxw5{zW`zsZ;F=znmGCcrxXgq%ztq>GgdU@m!J(fmn5PWyv?;Pp5GDQ5%GYvzggxE>-xgs7K7+$oohSd zx^1o-asRxoixlqH<#0w%MJ#pRI9wess!uGAlb=xBB<2RjX z54MLt*P&_;zoc`Ey$a}I56`1(sy$|*u8a1Vg}OBDnMdS)gp|8sCgHf`l7raUWM^3Z z$4O4O7M%=={aN`qLZ@@ALnY$6-41i0`IJ2@Cn56}X4>?|pFJa6^2~nTY`Ix7&n~Id zt8%~HnY7)tAAV$oJ2tBR5ON=AY56hUrnx=X*25sQ>z?fsW!atp+ZAv2^*Pv7JvlmX z(8l|w;Gnh5my;8Rs%;)^2^&tc!74bSZL@vcxY3O^OTeEt)4+Z#U*pF1S@(mI)>w=2 zi-5c$7h1J5UMtqp7@^SSj! zMD3PasUhB|VOcctrq<4KcgxQv2MepR8SPIj=BDX&-}-JEv7mp^_thS+hmM;E+P)qs zF@I`^Ilz3r$|l^QA5U)~Fw=O-0rK6#+G4i(6y}d_W82Sx6_ekB@Z3Nz#vhEPjJk|p z@ZJkw+hW9Cui7XeBLCVN=d!$PiLvSW!~zx-l>HsvX50(&UwFHSsF@2iAN_{DsE9Oe z#(PncOtD_K`j|W!3F*FT?AFpdFy44Unb3%s(Z{q-jPKzHIZ)1{4xD3)vl{pqV)Zk4 zsFDHBd=&a#>$wNq%6## zQ(MRkbBk@XX+PfOa@oWI7P8k^43Yl@M#qq0`DnNn?W|+47@B|RufW~W`g&Y=>&0KX z_YvJS(=i$S6X(cjJp=A4^GEjPE8V@KH9n#SPZh{`-UBE7z)nch*60J}Emcw0XnUst z+6zwsU+_VN#-X#S;MCoPn3Zc6;40J;NT)iyWzdRIpAjvOBMOMe@EUxr*!()k9fPtdrcl_j?~zU_loaPN4t!ee_1nz|I~I7Rqu`7Lat1; z6(e3bvmAe|ygD6o*k_H%+sIb*dgg&|?IwcLjPcisKh(B?r=Todsl#s#t!2}GIVQT*ydYwHNOwp;@DJm7Jnf;S)(ftCe-SfWqA2?FjnX~%DQ}LS4+AIe`;PoV!OG*H59yR* zHZS#wmEn=&2vz|Q`@QIM3ailCo8`D+AroXJ5&1v;0T$46@cleIp)l_zb;+Yz3?qtMMx0BVVH6+c78?;B50k zZemph{*HfkCamSbx~OPm4UT!g#9Nr&{7gjdAc?+{b9aln1XdVbnepI)=deURmj{6$ z?UiRjJY8b@u(dZccH(+6>nJ5rFUKM+>bsEUvHiF z5T0mQ^b1yWW|t{uuhUmF_Tj!2B^k_1C$q%SawpI6<2NUwuRH>;99fJRy=QYR=rRrC z@;G+!AUuC?4I}n=c;2CF+_<3*URWgZ6tEoBzJYkQf_Mt!pZ=D3l-Uf|4k{m*OWeDf zxMvP=C%d|B9PO}y&61TH@w9?zChA?=6P=0Y2oCs|BVS-={}-M_xb_Xb_gA|n6fXKI z+lucsKYj6dY;2x_fG~U(YhKhpEA|-boOxwC`e?@N`6-C%50ctxY%EWGM&&7$jL(Vt znUdYVNy%1>H@sU(nz-U9ae*9hvJa7d{jb=L_C!3!h?w<;7z4Y)-7Dx-xz5#_RpuS|%K{~+GDMLdbN#8V6c#Fcr(|DW`SQe9Q(F~k61kGLxhqXhme zEChZE<}-XlEQF}V`ba*N$`XM@A*TE$yXw;sbY$Ni;<|gpKZ}U}-c^hn*KbY#)|bXO zmDqcQ*n<&`dnNiA9}v4RuYo6tovckeFH^arno+h(8RfOrh?cb{X5R!q#bD>ue!x2n zUu*8S%LAi~5PxdZRXG4YlDY(PJ;HC=mR^A`**dac0j!*aJyvT9>21X>5_D&@W5iw( zM@$&87DFww#a_&7(0qy5txN1GVcbvbG-aGb?2sk4k1{GVE+w|Pcl`u!Rb$W5I+Be& zN2_NHsS@#S2RHx3Zm*@ws0R#J`2^}p*@B{v%)#?lu*SA*J8%P>GX=hL^9X5cZe}cH z%w$YrjA0BX_RON%yAKh&Fy_hECU%T4V*Z3$Z^kvmHrDrTi>XW=1Be+A^+tEagQC^& z7F*_I|3dB2F`A%^&wB9C&-35}W3+rznhILC$w~?uo1`Dl0Qs)UfQJt51Xs?$RWwZ{ zZH)trO^juX=tUgQU}SyNwUBD>JVxx0BDORAZEU2q@zRl2cSiUR(Ds#aCb60IR5Sb) z)acjM3f`|S2FGQiwHm!*fww{mfsF7jpmu<2Z^tZ(w!KDd)giXzGGZ-;PBmgv8>1kx zkqv+yQn zIgNiS%x5~;sH_)b+9DaTvO<+UBfE+kb`>?t=t%YNZZYsejS%M0<{V+rB31yr;tSiT zn)(YfQe}n-JjY5iwXLAYTPyI`lbPW1>r;?}7(UzrmM(4p6G>YI>xBwOR<>Y7U*fnn zqdKvH&4l$;q~V|TWHV%~A|0t=b94=}@M;x0Qq|5VO02A9e9btn8?#!4WsM=oonwh? zNJ}hcyK)QPTj1Sa*5E1=cSq2ReAT?;mpZCUzkty&rS zX=_IrtZ=tSDaOLS&84+?GOVez6#4nQQjFrmS4z>Z==Uj9d+l0c4G*#U1F_1NSc&Bq zyiTlOsL(D16w`xsZp|m~s!I8qlrmxQR6^{SHe`9Gu ziu8>8TMMk8#y#RJ_;~a1v)cvtxo3#Q6&zW$_(glcMy$+I1@mziy;Q+OdJBDiAMQ9f zlaD#>-TeG|&?mo&^jEMox11>{JH!+UF>T+7#YK#piAA4?g>1DgWb6IkZ|y5!vsQk7 z&rW2NBx^C+@@M2;-{q0#8~6C!v%JTC9JjaUEwMKhG|eqG%@P&JwfT}J5t=J5ZTRk0 z?y+YtWh!!)+?pXDlhb#6kJ7%J{55Zt-E$&vZ<|YwEAEy*n`4E$<$vYq;ps`OoG-oH@0x zFCNKu%+d@*WdPiYR=lPeo{3kbL{;x&6}AS!gI9; zGo5bb>F>={KXK7$VW#LhE0Z0W*Kp5#Y34C_d`B|TF6JVctMOi%otcZlP|7Y@?8=-@ z`U_dx7VIVs`KO3^Pl>rqc}_CZHkX+Fn3%;puq?JNWTKC@3T0wMTr$Wo>#-Kl%-B`y z{qjkAY;OLCyXoR_y-FkL3;gmmEYsp0Zs|9e#Pb%4OPJO?j&Y?e55cdJUO1+4;u~?-Z#yvzoQ+MD_oa?FU!1UDR*tzdb z#kD}E5>v?LmTW_&(2bbMX3m>l|M{X*0+mxH5|eQi9KA_a*h%Up;mGs8MEJ+DjtLkM>Jt+L zdY2mPi*Kzv^!-M>eBSdP-{V)uoBX~T7v-<%Ru%W!ahbPJ+%7X!fA!c_jp*Q0v7R3) z!_LQk5K@#j?*nM^|5od?u~mG(~Hc6R!jx*J)dLJky*JDgAtKf6XS=t z`lT3m&?4qH=}+Cm6mDP&HxZNAjFiaiKS7R;#Cu`a`Y^5+_ZKF|p|#)rh_yr9$36B> zM9O+%J|ZGr7v0r+_m@(%e4U)@{pcBaKHdRQzvCMMU7{}d*M(U|_B(!#`W5MEHW2qT z@|7k}Vss>jjC_i6#HeUTT4+S}UEz%I2-mZ#v-Bb~wja-~kC4E)8jZlJoLe4o9yVV%!O0EDtdT{j%m-v;tatCB2vIRZwITVp0<# z_acht8ljCyqewW8IB14HKomVIETz{v;8fVHy2SAHp=J5gV({*qgtJLYLKg>IN&6BK z?%12PJ>52v9aIK>4k{r1(ae6Lj+5p{))x^N%lrMqk0LT65q1YL zsfbWq#n)#cK8U@F2BR13rGhWwO&v#rF!KjZ3Yvv`U-tyc_SPn(2aMD&N*fONoc}Oq zVZf3E+kz&4&j6p2e*b&FMJlfP&oUpbe&rYURif^+pNecjgQ4H$=ekYOeyi_4ZQ17A z%M;b==bN@$y{*{SYx>IeL|XYeG=1SGbaMKB0Dt(t0K0vk!PnpGD?s|gnB|AExiJJ@ z{c(|Cj9KC2pg9P+Sq830r1gEkNkm7#_)8-4&*A5c$iJ2E05q@ny?}`Hh>trW()>P) z`?lpj_BN`2R65OjVZM81pqE3!aNQoSqk&5rJ3Y&P=eN%AH2D6Zz1x#VYh0I!=lG9` zJrN!W;&=K~JcSs`dLHLEJ`CA;Y@NGhSlI)f)5szBQ83RPdzn#gcZ`V9 zukQI^ygTzB0`#cm{m}~-rTq>f7QNqh9dZ_yJ}c1L+};=$zdv~$M&y5=Cq{SV4iA02 zse|7=4^g{f_tl6ucDSK;D(qa#`lRbNx$@O}HQ#Z`D45>v zmy5MyE~0i99T(u<*FcBoh}{+2NAxB3wAk-ym^tYG>u14>(STpu6BF^qBcH%A@TyZG zvNr=3rr=NQbKqTh)NHr(@DGt?lR?a!-~mQ>&M0Hf2WK(D zFXA_IhP5lm{w_g=h~Lo+SGdwa1QudskF_lJ=PwS}#`vE*a7TBs9Tzlz|8Wy{&i`eL z^`dKyjX&-*o@+A^kRsjvqz_s+Ow&jncec<|_x0s*&ozcS<_bs=96SdoL z&%395H2CTj=CJPv1hDdapLk^_`aI_#jWe%R<3VH6X|BKs?;K@*#_Nn&-9B^v#QJOg z<3}WN7R9zN@UoK-8yrbKY}Jj(f01P--aNnDA{24m#ovRVd9`^Q0*y1w8qug@W*8&L zk6a^~8uX(dOxhcQLEb`Kv2k1y?8Nv)P(7YONpUU(#Vm0Sqv<-ZK|>z}tel1~U)6wn z1Z^`<*?bf143{*&`0kal^+pK(!@dzU)a`eUDhj9PAm^pqOZAp4E#Z7Vj zrB6&mk*z48ucdcxH<}8~!UkQWQ@@$0H_AAlsC$~IBi)ZS(2i|f3N9@~dupj9V`lo= z6^tJF`pyMAp|8`eFk5Ka(O+nu{RG?8=#$6?eIG@EGQ92JsUvpavJEJ!!)FG|7~>eR ze&L8S;}5LMN(Qqr9?SJ4@I8exok~2XFkKtE1yT9Xz*5W zuiZ+*X9k)5OEN2xWL6{zE2?@dXHWP1%Ys9ZA3{lqG+G3;qcu^ZH1RdN3dws^e#QRv zr3sZ^@DRmU5yg53@GH^Yrc2083>Bd#Mb@T##7c58WEi;vJvS(P+F^4Ayr&OqeUhwH z4c?Y2K{lc1DIaKlO9<0gmdue7T?0GtVrL+ zyd@Q?igzxl(fbr{gwVUNu8$aSgXccO=C8TG!8xvRJX1%uKm2wfcA?K&-alamH+i8{s^MoHlh(M9Q#{y;(K;POo+<&)ri#3_!a}K4tGfw z5vRdg|KqFpuc`gFe>K!dwX`S`OPS`s-)a!vKu0{qiFT~zjkT$)#`pntg1ZSFiTtyP zmtc>03V@ZjvEG~?LP!3+UicSn{gD1~x>aYTplPvY=bMyy}Rp|QG$jt^s;4c4|G zS~aL$vKl;*eL`p_`7!MOiG>F3(3m^}1$cJ$UanOSi;~Gkm86OXO zpgg%n24{9F!JeuAaq0~4uMh>~NAg_YKlWK$UIoRqu$K05$s&H!H&3(&If!;XBQWE{ zCeV8YeB@p$($=fRh`&c!l2L>a^CynL7lLLhs(plM7{OZhzttL3d9aO*eA7xKvkEk3;wn1tz{v2 zTw55N_0a}VSXzYAN+B#Vacf$Tq=4L#=xQh|10MtIF+6Od= z{b9sDm=wrtrq_bXJwuF7h~2r2w~1Zs>bgX!+&MIYm>+KQ8~{(2WMSvmm5QtA_!SC! z?s)9V4Q{pCfLueDHu|DHT<%ZM$_U)QZVkAaw6(*}M^*y+FR-1l zj@sJZKCmwfE7k$tC9{@&Q@MISaj=#=egkcyPcT1Do*2HTO!vN zgYYoHZ;aUgqWqEZHRE$eoEK^hNkcbVW4f>kLhWi|=ToN5mvIiU9ex7zR57yIskMa4 ztAVBo$)jvi7Ke>A3EndY zxz9WR*KD)`r;)bCK1SB&jRmZn#u(2SMeJlY-?@M^bZ`^frHO59jcH@EWh+zL63%pP zCpOzNt|KMx1_4weeFY~^l)?}e5WCblqZX@&;_og0`o_%6`Hjx?U4azhX!8|n3I)YM-b!E9ew z-x>j`mb!tQX|U(o^00m2H#hWoEx+}7L;1s%eo=KT%i{@k0LMz8dofP>06 zla^Iwhsks9uhMi2KJ%vPigo7oq^kM4j{JKnOB60XX{dC2IZrI9QvHG7tFlUAo+EFr zSDxLLE3HuduiqxFvk0 ztZcEZyM$6p@nah^b;IHfdfGZqi<&>(F`QZy{OYDjSdr1gljgIEBrjaDoLY2s*CT7L zqW!pAeo_%;(jOm-(64q;G+F+%E$qd+DtHQ8!SKR*YX8bUQc^jdDO^G1xrl)?UrXKu-ru>@72ZU?yK@H?K$W< zIgfL^u9s;ZMy_{7-gMl<@<;A47?az9`$70}VLyK1xy*jbPB5M4n8LeE8=HTMY^hvW z#JGa^_mjQ((Rh;iO8!plku>wnursvETZ}ztX0GvQpR!=?=C)3qYdJw>BPNYG0vQvm z;&Ud3C;#Hi_VM6w63TvU`^J51_8$E&-mkNI6lMKdvZ5s10>iS*1X@BaWxcs1A7++y zjiWu{de;7_cOwI`R^#6NiY%;R(Y2Xa#bS&zyAWSqn%M|`$gH9EFPg>_G8QbPGHFA^ z`X(_~m6#L7I15p99?HTzI-3=Toq2cGF2o&LGtozS6`AYD4w_eFc(ot0tI0TBe$jb- zdUXb$XLY)2#5Vu;>3coChfGRqw{40zmgZ_OGiGL*gwnG3EosLjpC@{x%@fQ_9!hPx z?3gw;HEwT0x@D^K?97a+RLozQ?WwT*tm0IxT-kD|ShKQwQy)Up#Z=~z=B6=i(1U+T zC1#Z~jw5Em+gurv0ng#amh|7)C-*Kq75NF7uyvk<1kf}g zlG;C`k#wdrJ4s{yOll1sNg0N1-$+@9oxgZ8`a;Gq$p8_kjKmVe-MSMGA&M@TfH}(J ze!^6Iqf;whb}S;IH-3D3a(rRj*Yf7n&v6?wr({*cMn<&dKZ#F%{+sJRyNX7c{ov?jXt;L~Qw=!7N5TU4Umu_lQ|f5&Rd z5v>UZMayHwS{IG=yInl`73oi|Ahk&e#6+|wG8z%st0%^1qP0)PVdN@*iCac-z}Opz zx5mamv%5Nd#U^M=^ch6aOQO6GZyXo38nHX8$R8a`^Rps1SDYy6iwMnpR#_au7s*#U z6h7?P(D)?W-A8Q4D_z9RUYIyW#O4qjeoQmkiPz%Y1+sbJ)qDXk)~EjG`XtN|gb6+rl}pf;ln;|oS1#s{RI-Z{4Tet0hK`&>eif{z`c4v3jrg#1L* z`*ASZ)_YS>3htjb2<$yMsJ-3-n1z0v+9_Fnj9O{ORGx4ftCeRMT?U@aJ&=l*OApSX0(B~Q@pLM3d? zH6u$GydPzQ^L2Y;#JgDj#OQaqV62Y*99G>32EO9}Rh}7uH*QS^H*nj56E^KeMx&N= zI;AoOFgh_>Gk(L}mj}Et&wst<1s}lH!4r1wZS39#tJZVN!m|~(T`?~eeRhe5=9A8a z(A?qFkNb5+oVMew7ZUXCjIl9CPe!bO$mTuoe1VajTZt>P=gS(x%v2El7x=;(E%9s4 zudnD;Ka*YHQ`K5{-no=W25JC4#Tb>iralW<5K3()r^T(KekC zEj~78gSBsL%-X*b>znnmDjc&i$i}>DH7i;ZSqw8De(<3E5{#z;6O1_vMKx>ikThn3 z??WP1U=$zbhVMEQOZzTDZ=w0lGocQI7Y#0Cg#U~=yPpxhoU`LkHDrix*`dC)3ASj- zVp*FLX?> z+3Xx-E1F`af-ijej^$@Ba8N`;_9%1!Ge*k;2~-~Cw_JA(!spdSp_AU*XZku8Xhsm;3i)cWDq>*IUDtp-%cZs zkgt9jRQym59uPw>sCD0a1^S-DC{R=5hy?`~YJkj&)YvFiW20E@57Ms+U#{q+UOm1_ zd|7uNtopmQK2yRhSyP$H8cT^^!ij2VQ~cFgq6+#LD+4SWIg7PKCA0vt6?eMOW1rNk zA0TUxo0AA`h{dnuHT)KVlN~1_6QS`9wjsAbV>xC!Pnk^cp*Y(7X$uFYGt=D&SPY=kPP&KYX>L~Q|+I(5fw24Q7^L=d8YH@Z#p7-gh=g$ zYz0OQyf$ItyQ{>vtasj=>*hml;%+s1|FuT$DdZi(Vlg%)XZhhA5^o(HkU^-X@65mA z*FYb=Y?4Jgzto~<4qoo%--I=@>Vg$$e*o?JLTXhd$n?Kp?f+sb=@*A`5MJDvhYVT- zN=k`ulZa9&M9B)G#7yGL^F(pzK#pJ%QB;R0!g}W!`#sIz$VUitM<8Etyyh7E4xZdF z_@3pphK)?RPiiL$6DQa+ZX_O9O||d2LEJWjxE`w*>Y7BH8%X?vSqS}_e5HTQ zzhjEE0rboK`^5NGV&Ea7^GBjZIZ+!|ggtpL@%3b)(0Jl?)Q@j5v=DdUdhr$@Rxi~| z9?$=m|60%g?Z5Ww(fR9`+Wa~yCww6WRuWw>%JD8K52B6|QE>`U3L_nF(}U&UDF$}E zr_l@J#&M#z@hxLk{&ndcIfHxOSV z>Vi3AGx35NahpH!KhQtQj${7BZ?KoAU;a1i*QImTo(6kzTR_Lyv*0sdPH@LB)H&K` zEC5C;e+JE7BhoV}E$9i}zIYrwxMMQ7nzW71B#sO-V$MOiiV;1EGUgwg^Z!M^6}$F5 z#8J$vpm1+6IHMMkb5@wh8RQbu!eFqC?K^BJpAYcxbzad zv!S7#i0BUC-@r7+Fh=YpapV`HC8H_vKc!!cX@f@%ZSWtUCyo*88tN@%6la`8Uj!cV zs6{@&C{tN*YE-82{F3##Hq&3J~dwJ0Rv|QpL!Q542Hv zK&Njh$WdE}%tA$;KBylHo9(~sOPptqKJP0uc>?}Y@d7`*!6@jv^%(ut$9dTToVRB+ zGCPB$t+$qu*-39KE2DRD9DfPA5J#Dwk$$RuWHWL2DRIb&ILNML5GxQ=v8x-{LFIm| zJs|sipD&gB&JcU6`!0bhbr_+&oO$qkd#d7K8$A|&7r;jjTfogG(a1P-sjdfO-~0w` zgcgJHSKfmUIn=?kq^)}oT)i-g*hRPWGn;vhT^ z=yV|VH!~h4_OX?wmtAA;6FSmU#>m#E?s_VBzh#`)ho0~9th)#b%e`f38yvX!R)F4f+rOzg#)3xz|B=ZM|#F`#6WQH0o8 z!T5mKQOo$6ab_RvyxqADn%nvEuYwcf(kXJ|*YHPoo4iBO&Wg5Ern)Dh+h(ZEyPVQm z`ZnhFgI3=slKgL54S2bQR9au}dnugLdUtZ<^Yg8zvBO=^%7J_7Kew*MD!sE6^Rkpg z>nz++&) zyRRM8t&0H<=j(6y-dr2M^u*fc@BW8*^P3+!9^hZxyw-H!Sx-}=+SixjO+oMY-f%V< zJYDLOq&X^8U7Z?uD6NJNKNdD8d;AtzVF|$dv)Xd z`pFke8-ntS9z--ejejm`*s#>!SZYOmp`(TDi+YQ1;!1|~Prl6ia3Y@GU0-K-sV?TAh;dil?|BN}*47!~{`uBACEPQwRwoI+$-3?-ypQ*Fm|?9J)!ioj zZKg~i8?7ygOdI@XDBMnLVk4rFSybaZI@0ilSYOS^#&ul@*33tBkKi|#)%Ny_2^!Su z)L(d+T)V$uolIFxNqn#}ca5HZyQWDE@9%N?oHcX5m6%Sg&ii8WJ)ruRw1KsJwcIn? zA63!#b=Ez;WWYJfrHS`uiXOAkhx$AAB9*J*W38A`%@3cYv8oh%727I7_yWC^-Tkhg zlq)sr4K+$DcNV-g+*y&Gu*lrKLM7m)jc>)N->>WsS4=Q_;Jl+ePJN5}u5zRIC%h!e zp9@R*J}y6Vb3?$~^3{i>gXWb_S}GnKRE9M-bZHq@+pt?@3AmGGS6K*{Q|67g%v>vD z^Jo1Zq^E8wQ@Dy)bAl;kEnnq8$jzQ3Zfj&mt-f1yZV%<1bBP3l$`io3n|-+unMPMD1!2|*+m|peUUvP z&Wnqzsr{?iXsrxp+LDRo^^9|f|9r&>^U^Aw5{%R9DJ2`RljJY{iXC!bQ8%IwONw40 zp5jx8abfqR@cqC67ktsQVXL=WfkWYvpw|WG6Otol<@W}zjB&_!ce<9)mH)#0K}v4^ zPK_HGQ}PBrSY`dpOBG#``)A(I+b8q)A1+nBEk+dN);YKWkZ5%pV_!m4x!2+za@7?m<5tTTc zkFoG=VIF>O7n%!Oa=V#}RnIRrr+q*^OgBfaK{}=*XKCS!r2g!H#4Q;Uv!4X2lH0o9HOn&E3&5W@z$=+tT?{B&Nee@-DrJPrW3|n zd!{k$yDalFY+W_;9Y*G)OmXlDeJKYDx)sUKZJT1F0x!5V~ zRia)6SK42JgEiw*Q=HG#Yp1GwmuyN(J*jEbDw8@*c5%B)N|9Jmr+bR~9ocTp6txox zJ?$x?n=LMyyrpDSv@uDVYBU`BGT>=ZKKn>|4aFE7&)l%S8G9 zrVQBghs){c3!MpR{)ht(q;?@1J16xZB8?^~y0~9=ZZd2p*)y3B(cRRf7(_~6Ch-ie zsBlb7XX*YVr$+JfUxK~Y@QmOLG*ok=p;C@9c0QcwCo?{lCys%DH^9 zPu_*rUX^qn(NW$+Sh$aL0?r;`5?_fZx^Mhmyzd&G0pg9>v2BRm?TN))+ITW1Z&0*t zB<4<|ba!lYW0CT}!)Uprha;z=R|l1#m(pFZT1I`g&;bvBg%1)r_R$PX7Pkj2?*)O9 zr#rxF+aH1OFhQ(h;8bD+{5r6Wv5xd7%Fu|hwft}1HrzMIp>|f5bo&i^Lq%}81hBA)yfCQ`;L2m$KC!OUidvS zBj^R>LGT;o@!S}f4M|~St2LQ{Q;N}7ZkoyHAGehuum{&jdIy!Oh!y4u*9AJWP-m*b z2GH=81NiVE{?=vN1*|PDllGoM7Nce!+RPa%7sy6|vo$LlFsj3^sPRR=d%p5c#CTlj zh1E7|yyuOvv9fxPorwHzaz|_SY;~Ip%@bUgl0ui=M0y$lnGuX`Jn_J;<@YiwJIW5h zLL4fZ2EltJTQPcaQecnvk3!1Pw_|SdppEr>kVgk&_UDK~KNv1y1F8!A1bHtSgPZmf zC;cUe*{*@q+NCjK6+_vL@h6^pS>uXxCC+wsLTmFlL3!=l-!l;TpX2}w9zJOALaKfl z5`StF?O6GT2bFCz7^f3$&JwM^4{yg@)zgd~vwBv7zOu|q!8t4+gg!^MqSO5^P}4dB z+^(yMoI>%ZGVq%udhh#v!8UNsWy~4oy@z0r<{2xLKh@SHlkD zr@Ya&4i<9SMhda$N!D{niDfv^;uG;ZEET`!AeyZseuGNb-9e&>Adzxfi0q^f!@n?E z(u~>9@M9_Z#Gowo5XcwyCo%|C?$O{I8>rHsrYDLq=c!l@ioPxaH$J|H%tGzeO`y+V zJ5Xyau3Gmwsnxy2cz_XW0ghn*Qqyb}h1uihw^gV-*hGso7&EIjw4$=XNupjaQ8$#R zV?@+eBWlSKzv>V*VF6f~vxi|h8Z%m8z3LB3^^rSpPYnW>hQS`x%skL9YAbCqPF0=s z_k!n@lCU=ROSOQ`La-l|XT0cnmEA|XzzG}05hp4owaVD}f_990j93Nw^>xQnz1lbz zl*kY@GKuO(iS%A3)Pgwze~aEl)C_eXTk(#lh@Qq;ah#~IpD52eB8c3?ixyAhBOJ=6 zA!|^bb^_!I-+~;zqvs@Wxos2H#%~4_!7ZNy;gzJkg^KsmPoVkzrt1ob=Qke5`J{cf zt^hSjt+Ws$475M%c5BS$j4rFxGPQC~AcA!^`-#F8#HUQBP&1Vuv(X`VkID~WqsTriCEou^ytixgG@fF}Z~cvYfkXLXJjEcB z4m-ak5g~zCy{6X-eLs0$W=Gv6ap76IR79wDwdKwLUVoWFxO75z=#-#^?ySk6Sj+Hyem+sAf%v?Sc>gT%qArn3 zkGKIX_ivTck^e`n|K1fMPKmXofLQjBn5s<-y-sv(Bw8Y(gV}C3QHIUyB4??51KvG) z9($DkNbkRQoR0mswLY9dI$Im|7SPX>r$$pbREy}ggJ`Kh{0jdC`u&I^%+tRSN#z4< zzMOc4%73@;zvh3lejBQ{jd|{65mZhcA%><9-Pp=+$;RT>S~?=To+x^ic$59>LF~>k zsyEI7)B7Kooe{>NbZ9p3XJgQ>^9@j4B9 zElapnFld3*tb0%cPlhQEV&xU+8bsvhQQ9DUIU&wLTnqIP)%br9Yb%Z%C62Q7W~73t z!m1A?Zj76WL$-`qg%OWoE9l@2Di5@`D}vuEwu9%=wc+QEhHGw+>kspIdhBlhXPfa? zIQlQ@yt})gf0_KYM~nKp#CwIS`cm(1f05Yd#9jS*R-fKVhqs^m(DLu^^gYA+R@`?B z_tKm9@nFx}+lO7S{9qsU0?^4?Y!p5W+K{dB!}U}i{#&6G(+2+s3fVe3z`TJ0_`y&m z$M`3)kFA$|Td3R{(;f!CtdKb1(7PnP@bb5w)bNt~zCGF=5yCrquG@%9*!KK|chNU= z*U1OUnRkc1uu-z={&sJ&+KTSCCpKxk=)SjxPiu2GdQnHL8=j}0ME453bH0eONCw^A zlW`Y)LKkX+PNrmN71cXUuR>{cLlB{OaycEYDe&ImpwC{Ao|hsSw=p6=nxYlk-| z7S(3k!Snt^8&BoL&&{oE8FE@nTWul?4Ii`$dTN?=wyw72wN7fO*6shP+Tx+m?)acZ z_0>Y>>=wcMCGN=DoXYSNY+1Qc#rs|hW+mV8&7HVgUa`3hyLIj6OuUyyusI(0Q;cg4 zC;i<4q@gR3*vTxXb1u`y`l4Nh%57xr$Oi7g#?nwP8PG5q_e<|^z}mNh@cT&U92 zkDZ%IlU9d;fp^pHO1|$^jky_lc6S<8Bl>?oY&_*T=+@LY-Zs^{u_0Pd!+)ef_mg?> zwT7p!%ERt89DPt0xvpXH8Sd!A^@Ceh#|+h1;QnB#`efY05?3F9J3;*Foe^<+U2lUs zp2yW=7C`Hvb|^#}f>W46c;QgUPi!_NHkC5&8XKFg(1;Oz@q0rre3nTKLhxTw>M^=C z#OnpIbLOh+L<}ONPPwDVab4ZU%Af8nwegv|{2tUwN8SzoUc1NZS%gAO>kpoo<{A(E zMF~1J9~HTiHEXU)*rlDR*}$Kj5nnxa)-=ndx?YXU?;hw2IE@&Lp63i zCO4{Y<9<-PDtPuTyj8dg-z}Bxo!dhmRO(cYM6apbovE7;S5Xuho%*uE$g3nXp@R2E zN^V5OY<-WyDdh!<-Ngar&XO`^9Oa4+ODbf_@AAy7+FQ=GqpkW^`5HtRO3J4r_tQ_l zNL_dtX5{(@W!TZzXO`uX{(9__@h^I=>fLN_atimY1G_JA@yUOIsgV-$}uE6fX zprgD6(Vy$(*P%JE4Er7bt@Ip6xO!b<&E1vY4r$w}=K%k;cxya+ZM8}FEz1@2|rHbHr zbQu&0!pgrDVYTYHUUU?!D%yildaY;+>94|092ugW#0pMg`C06>B+8y(S1D79Sy9Hc zBo=WKxss`{jSUpjba_*Rl`G(3(E`Mg=NDo`C$A~MOqC^HfO)C#X~Fc)jPh0ac2yoV zCi&c1e2x3_YNM=MXXKfCXLLB{UAL>~9?P3)(9#!~oBjFe;Iv#jsa?bCa-{`_M;GQ^ zy3jwSox6?08u#DK9gmuG255cCsb*xJM@|AOhmro$g`~OUPh#;z#G-qOFhh!_6mCSs zq`%+-VpZb#GKdTY<@q5RE18R>E;1~a4>8ieaxiP3x2a!^N?0NJx!z|;j z&22?l+pFhvmt;m~g$=C86pdau?3lUKhZk>BPyHzgelauzFDYYI%UJpbb4GgeV`xba zzw{ck+}jK)&6of(FDm^8X{NOt#99vSB>nlFq&yEhx^u?48Hk2x1DHz^ zo997GBIZmmn9+&RiV^DqaxROpZ*$D(g`HTYS0d^clZL-{=uWMGg$SkKc-+I3MX(KC zii4MABwHHlxSXy+P^cR15!*p;HH+28q%aoC z<$DYFlhyw+1}*3g<(LO5zrl@f3lKl;Y&_r#E7?ABg@sHr9VJ z3d+WsqVOC1R+1Qz%6Nhp?%RC~Mb18k(1e9wBWM$H#fhi9z{{+lYY*#DGS|yWKW8Utx_C z$e#nt@oSHr3>x@-01w$?J@KtExd&RP-3K2_XMtOvxgeL(dtDPuJ&Kvk$BEv8?xRD> zecm#{XF!>a1s@)~)p&JiC^VUdNMWD)Js9m=vM~trOhaM-#!q*-e+eT034UlDoWFq) zV;pDLOZ0w5^l~S94l+I@dPMd70dm*Q$Brc^rw`VQ6X+ir?}ajp2W z6|{XH0}2bHS6z4BL=CPJxr;H+m2b!d*{m;ZxqI3lFw7LwwX7^ zfBR?89NhC?=kbe_xMOZaU2lo5=p&p#k?8z`=oHWRC-L`bqN4@Tp}*%j_`DXjVPBGq zzqWrAHy3$?et%0)-*F?zX_}6lLZ$k2(CR}HC@4AuTz?CFYu9@cS7DdF1%2^Pwt~f+ z?LLxnJM02L0nC_hT=v6|MV&%mA@aX(v)Tz`_I|`)n9p%e^f7*ahWO(s(H7$cISWCe zwHDDTm~j%(@?{-4FlJoLqP(>P~vLjYzhb6>|=@X9wQWD|NdaP?-+GA*F6 z*fVe=A0OuIp3@J&q#aadE&olGG=F==h@A_{SK$3v{qTo{%(Puc^;%mIt#%OU`xmHD zj%dy_o6V-OX*I@v(`l4PWy2Fhef$k-yiC+V>)`h`M6D;pucwHb>xmj0i0X`A(7wnTyy^`>*1)r_ z2RVq|e2iR`Yw^jL=VAh3kIF}!F2EBBGUo=bYQkETy5!IXN|xg27p1HBFgldx@O(y8 zznJqE=r$kqE3)=i6eZ1yZ2T&oq_P$l)u?%us4h)Z^CYSe#*`lul~4!%il0dLTO&{5 zN|X~Jemp~zT}_l>SM*_X-)>|LuF@A#rQhc3A}HsZfa`uYKWHa12ydOC_D%WsdEjHZ zi(aZm5$|&n@1j=hS_oq|;d@Zjm3VC* z@v0W_a#cSxUlMD84P0m`fF+(cOT@MEyrXsF+-(;#Jj-y}q72V6+|kAid0OYwYvd8K zBs#z~0_ggaCRe(_RYx!@oCw~4YdP_V)SkdD7&}yW(O?AewjI@YV-E2uyOxV=Cg;H! zapo@K38tSiYRC?}B_3En%e*xfZM7IqhQV=Ib9 zs0auah@ya~lprNasDy%~beD8@cgJ^K%e~Lp`<#8gv-dgUH{bm6bIrs1KI>Zdy4PCw zisyOBiRkI@jw5&get$u$&KkeJFudSrJh^ZW$GJLhjB1NQKW3lu@W@EkpH zUA-%>T*CS}#x&8cSH5I=tf;R)OMk;SYA6srOnf5K0hZ*)?WC1A`Bc<``a`BKFCh$?V{obxz$JcSfE6XS53HVfX9%Q}-QF-GG3aEN2@mNgfW-{QZ2G#jLO&w@fSVI&zK zTIfgNKh|RgRzbhqEKfvR{g-3Zzns1i5zt{tDU6Y;WA`I!ndp7Eh02aqlcz9mYt!aT z5qS>L2Ts&)B>#Bjyem!-nURH4$OM^wP!hO)es9b;e_B5ca~-Wch&i5CNDqhpS7)3N z+1mE$reMH`~C%>EitkHVVe`#eh z^tXwJ`?r)H$$4bl60mNl zPTQ6@Q!Vr&TChU$YiWa(Q)ywVcNG=D>G z(zs^CmmB9dt2d56Y|uQh&{MWcQ*>hY>y}No16$Pfnc<)%`r`HTzWLX!mM%ddMRs#hL-78HgOHvI5{8N5RTLGRt;GHv9D=(i#HMC z>2SO^Iix}V|Em9@P$gPP3*uMo&Kx0|M6EW>Wtz|U3~6petiS$E1KQb9g@)De<{)1O(<@jwyJOUPPb{~FOss)c_3I?{|IRhF0uEUfBzU$k^mf zi8NMK?2FT}GBvmO99G$yidvea{Kgl(DDD_iS@e6-)hN@#+~E6hI|~in)RTM*cfHx2 z7KQgokII@_ka~Y#PF;bmLP7rBf?Fq)3yTYOZ8=ozUNC>YV(IFFA-y}4JuN`AS00j& z*sj7lKOOpZ=SPEC`557FZJ1DqddF&n@SMN=iV%9-F-MEvASzTYD#Xn8ha&XT4`K@M zVSVIF0cy?WZNXM(j?E9k8shN$W$0sM@+tFW zxgW4D)0l&KnRRszMo6cOY%8q%Yi0k0_2p4n_)P3DzVRVhE>jMx=!Y}gHnkLt%y?G( zxzsviX7b{yUFq>5C+e1_YkpR2tVv(?_Dt)cv}S|-IAP$W;RimvhSrmI=#)A*Ydf^0 z^;(49BDMP0Phb+&rhXB8FDPQx)ECsBn@!C*2_)Z^w(VRNyh1KJs{>X~OfyjyvxGo@M!v2{#g$aw)L-x$oiQnx>6OT#yKk-XO1{-B)$n8Tz>*=Y z1Cs2LQP!lbA-H!^`_HgJqSM?``%19)xU9%0!r(2=`j!VIq z8XFLb)*mb9eiXo8zQ$D!w2)glQ($p*=L|XrjwL2Rx~p?bBy*GwHXvqRJ4eb zqHnM)(K3QZak9)L=__^;2PL8ucdsW{qdh*2hrQmr#i2j<(f&$*o)Syn$c-Hi&C6p@ z>*d3vp|AdO6zqtdfrDh^7eNU!;!_JeD`Hhi8rI;yrYM0IL*XakL)@Ej9wpdr2zbM2 zJ-AQ{dcry=jlueH#90f_XxA`Me)&*v*VtHa0o8_%5EOBCXj`U3YA|D76^mB+xO)t2 zWNjIRsLIVaG7o=KjQ|t-gxA71+JvKxl%EcpkGRGy6t#=LzaxVi1$U7_j)LRKK;sq} zaBL|Q2H2*;VxCbG>4DG;T`1A7sSiXL906vYp zU^U!x73r%+ei1hRGLUH>C`Ox35nR_2i9RW`^dq=A6~6766&41ndqSt@M4p27_-gza zeDDyS>#<3>C)i&Gxw)tBg$j44Rk*AB<0;DEWvX@GDY#q^<1(&{#_qhl|4mq@+;0(D z$Sz-uzj;bNnP`KV-oa23%BMw;qc7=^K)TlpP9i@;2WrfgbQN{sdWh*y0j)DY$+D4% z_`OoG9`kWSIO@Ws$n!O*Vc!ByGdYj>d^X>F@BB&`p6Gny0`hmBvQHLlx4I1dT=Mi| zpj(HTpb<4Y-4m1(JcXxsdU`xYZ{_B`5c^r9-0HCMAIRTNNAAzak1C`KdPUq5{Uq+7 zMLIf>AJPPelkY`Y-od8W(HPunfE^93GF`BJ+5yz?-S9YYnAbAyXgI*n?e@H!0(RDh zU)g%Az$&)4WZ?z2EB0fwvF*1u3p)-av-X0)-KT&}#^Yb@?eaib{t>=1L z5qB;kU{&+mUhqou{_mu*r(kdTBe?VN67ZK>Xkli47ga&EgAc&X_*K|ev(a;}fo=O= z#J)ocHJgf2z|>BpO%P3LzX@SpHY-VMcr7%XB`pV#=CS0fm!z2zX?lu$37K`2Sb{azf1MDEWsz3+mj-}l0JSZ^8#K6?WDJzJ%QEBcL> z-huB9qh0GOZbbi~zxH=T1p2=Xk-}`JiJG4xegMVX_~}Pciu=sV1hoYvn@B@ZA_Gwu z&xKb%v*vYuQLd+GDcCO`PHG|8fo~I(hpl5u*=}P z_$sJ9rVczrwKoIou8K^3$gsfAr-4hh2x}LJ$Y4=ydp_n zLJxvZQ>!%+u zeNy=O@i$CMi!vS^&GcdM*Mp)Sxpt3rz(M5R#7dNV&+|+RJXvrf8tr%2UEf)FzChQh z3(jiUTa3c$eX(9CD0%l3POn(klXzw6dvY;6 zxV3fBy{f@D4{|$eK6VZ4V^A0K`ugT#??B!u9H+PPE!*N*2F<6qGGpI8d}I3Wis*%= zjXW8NJq5{KDD{*(t6=}h$unnzOYlcL(Ll|Ugy&BZrC4*Dd9C=FTylwA@R^*GN=`?u z)XyUCo08Y| zk*5!nd(cB;ttyb5^Nt*NjARb~&cDy^Z}a{m(iKa1|8z0hhhr9qkzCl!ZW+^tVlJYw ziD`w$lgM+&!v(GG3I!+W!io|X(VDvO{_v;4|yPYVk)`uCOI8zB!9O4%3;)yAuJpb z%(R#Ac6(uABT+lwP61pKb#y}1$R=5Sa^~v)5A=)OmJH$lk$r`JQ_{YSH10z_ctBnk zs|zP}ncghg$gDJ`|B?Un>ci`U&;RwW{P+8`-%2CiIpZA}DaK5%2BsahlE!MJR(JAx zRR3Cxu3M%iu-kc+P*`0b!?@lB6UHd;38Dto+lW%l#Gs1KjfwS#ReFNU5+dU-2xdx&IG1_u&~JtR3`_nu9~h5W&!At>_E>XZpv$_h6@N zQU)y%Gn4zRu-QY6)+LxLMzq9W=BeHySG~tpv1L$}fn!p0K(w-JRL zyO=2*8-u{oM#NI7uNocx3H`1tacg_B1+nbP#m$a*s=2&*1p18nCRjzww5c0nfqsqX z53Dvc{tEAqYd~2(y>Hl9{l;6SzAURIAhX^eIx}om{f;j#(KG6Md^jHGQx|5|Iq6ZI z-s2&uAL@>)XlEGI{eFIE_O`knyT|38s4ZL8Ie$`Z^oYF$cD0|dzTCeS@lf%vwHWz| z%WKu~9EEay~&g5#xlVPIMcJfK?bX%)9O7i+qu9!4$akdDwv<= z)S@j~XVxCadWua=CRT|0)SSmUS70@2B&@R9pytO|_v!`NQb}@EIWZg3=T#Z_PRVwv z+VP<<|7%rGGn3+#mGO^*%SKjOs_v}_s8qbryIQhx)1DKx6Dub#53CES>@g~#VM+yd zUK5C^~EO%Ez?T3O&c&yyhZ5hVq;hGMnP^#aOWqP6!Kc$Vi6OE!+J z0cX+6OGG?f@-x%LVnit}r~c|Zs{Qs3x=I)hI~!fmhV(0@BPy3DKaBbOsWP;=SN%&d z(|E5@Is;MU?{d`@FyT^_yK8Y3S-bKkcBYlET!4z*VEXG;%p@r%-pX=-jhvp1# zK3m`uI}!WYSN+hZ6ijeL`^nFGg;ttxp)(b{e5)Q@ez61CcV7Wk0V`HXf>9GEfzH&N zXDle9jXWihzDWIL_S9U8K50zb5WtN^{)G#%R=BP}33lF< z9{|mg`OuMeC=Xtg7sY2@%98p1v09ZJl(9J~2PMK@NlWce@JY^na89fVdZHXZGf>}2 z1KemX4|dmq+RQ|?FwpwakD$T zDL9ATw>AGPe0xfs9M-C4_Is5Z<=)wnx!+*ip$k9QB(DE zGN1$g0*?ZZkZC9dc)3;)?39DvGu7g2cW}G^P_Tn@Z`{enf|S=qn@d@u4nIxldZ`iX z^hpO#gN|#_BPZ)liv{JWIr)I#TEX81r{F|{N;W(}u5H#etO51Tgag`mWL&~3?a*}C zHdHAMo|71!>VsAE-6?g@{5)k2R?&|qt5ac8oFHlkpL!`cm`r#oIHooOr)S>h9tJmm zh0Ws{{LMjg=hxs)3wN-O-T~}!B;8g5Ev|F|FCN16uWQ$%6ko^BGzPo;upV^|ZwHeE z(TgJe8RzC~QeYh;!{ku3$Lu6$^d7?#;Za{7CA>%NCdT{0H+18&p*b@S7Q|mxkg=#8 z?3D=pF(?tnCtbmx$f%owo$59r?$pl32oyOkt_S8YVF7bNc^Bx37;PzsS!L?eX`tDi z^Wd4Qqrurn#(=+UT!lWYU=HjW7TC2tC{BKaJ*Dz6F;5Fay_h@1;XAI)v9-9mD+aZd zQWfouU--Qd<%$#CQjxGc@W)8FlYh#QV**^xSPivD)$g8KOUkjcx=R5-i8M3!#R-+{wQtz zG2ck$`$Z`CQDNE}^@_aUi@5V;(gS{s_TfZ+&Jr9)x}7Cmg9Rs$pN#5}`={RdOR!*5hbT&cAI#K2CKKuz*w4aP)0X zh!#M7K{4}jx`MubyT=dA>$9*kPsc)o@ZpcB3*6sKnJmwfb%cC!U zOG3@)&9HTCh{YL&R~%3pQc&i%)(s~&jO zhUtDUj&oN+6Ln-Ne=Q1}dJ47kvSugR?@Qn1u;|O@;~hbaR^Sdnu?qcif+!2x81#%G zt%N6AirP2#$0FN3l{qq9}tmHdhZv>@JqlWcH@BSG*dijdCpyy;= zP|WRh;WJ3@5nMr+hKNbmlMik;s$)F#EJO>_?2(v{Ie}sba=V}Jh8nxS@6BiIBjoZI$?qv^EeA&^ zjmIvu|5+%%tGoxLzPo%ia=zPb`f9B6CsXYm5lh^8F4AH}NgGx`zQVRzqF2#e$t(A7 zlXsKJJBvwm;W=uOOsk6CMunYUtFknCb2`blp&_z{-(yW-N>g8~Os(L%$P}+8=^&o^ z5(3)F zFCb6-+5}HH(Nc65GlrIA)Xec=?4ggXa=(K(OTktFr=J4&J10k{Ke~?7d#1{$ks|}n zkH&ib+XFAbE$eH+cJpwDL(cut-Vce$?a&q~KZN)JyA?vixoYNkW;J=zo;*H=Jo=72 zyn#GGwC?jF_q--|Js_n-tJ!YN^wuJB%S3XMVe?R|2L4oxHnH9)IRd)|N5gL6>F04C z$Y*t{-Bz68sx#>g4%B{#xzP$0c)<#}3s5c@dkCH@xqcIDzC2=qC%AX$2~gO4nKzX$ z(;#;e1?jG3+t$L&{~$#$Sfd=9@u0yW)2iPTEh!Z!4U5`3s(081vYYQSdE{zc|w{ zf;=KYZh__T6hjg@3ayF}=iie5$N&F6Y?R=g3wo3BV$2DMW!gEFG#6*2pNO>TJYJCz zGnE~fDPsMlfc%eo|IwB2sQ)rG6kwc({x4*pm_@k=&$Z~uD>|!4Rm=sUKa7+TJ^g}- zOt<$W|L>*vj{3z4bAj;Fgw9kFc${=mB`su09Y^xkZ1VgWa;GTKLQ#sJ#CqwUreCc5 z7X(vPf~bW+VP}^FUg5jwF{+3)#&2)eyCBwbca7xrMK~$h+S>g9`Df{G`i;34b|Vu+ z5nr>%Y~$_F{!qaynvMw^e7$4#r??M(d3_||1fhe+(ss3lR>-5kJ_ZA1*tcP zR1@u5_7u~*#Y}6-C8qm(@YzSaK`n=z*o~Yn(sRE2wOsu7`}99eq9-X7XBHBL&4V16 z*T*W-N?2I$1y84|pPe3$v2plPL~467*6CsGCT1Jd4&J#7BN(0&M=y^jtAu9hS4$JlHA1Y_!mP(2Xm+%OK~6g|dKoT3-{ z88>|&{UevNHdn*8&2k5kd(o})(3UhqQ3d(~)nGT*Ne`w#zoJfGMANgLp%iyk8=-WU z51S#f*dJ@*hmpUhHR8ol@7_pIr>zcYzlwCgCvkp0fc&F8XOxJ6HoylEIrSi~Dnq}o z8X~`<_=jtt|It%Klp)iM4WZw}LKFI1-@u0YA@-rrU+35n5#=lwSpGnsYcXOXZTG8q zipRv$lsdgpkNEx8-$>uxq#vTEKSKX%#9xRhJxF;G_uM_fw9YQ90`y{ZSv=V?1^SC^ zOQ2uRQ66*Uo~}nQXS(SLuXuLw%L>HlX8!dkbGzU(cnYZ^3>H|^K4LR|S73A066%cU zPR1T3zv2#f?*{JwKh-a>mkN*mNGj|gHBOWIMdYh2(pDDwPdLL$#rNG&}Sw#oEL%FQlG*Q%ws;6JjV=ReAyR7+`m*9;T(-w)g0=qb|P!S z$y$-FyYSEIUz$f%r`wZ!+bhPLi=@RRl5Zr%dWu79HP)fpw4#khn75*~w)Rea z(Xy^&RrZ1Anv{_R6Pj&83rn1uk9>YmQP4c(&7_)hO<6D2*6(X_xS!P2uSr$jy2Yw# z$5AP~k7W7=wCbi_GvHf|^=ze$X@VhwSUJQM`~S}V+mE!OR^?8%q+^CD)q+05v{$nl zRz?b&3ZQvH(`IO{ZbVNI-JubFnl!&580*F5{Jookef1TsXUgu@YnE76`_<1%(QKGd zmmjvjMXJuo9W_z6>x~CE_(cWQtqU|@_gWW)2jG2aIq(>Nm9BQ>EC+BR)z*q=wFdUb zJ6B2tGpPSBzrPd1+GxtgxfQLZw&+808b@PPG-!Zd7%ZySfj^I^OGeHAR)6*q>skDY-4{~5>Z@%9>^#|}mSSmQu9eq$m z5}(4ZFf_o7r{bih3^-Tu9@z01{G&W`Gb~Z=HFp(g&XZ&1_o=!3s^D=!#3I;p(W3G? z4b0qruhqpE^1j9zs|hyMf$)$ERketAr&LYCT48PFdDz*j0-l?yUNHbW4R_1Y8p_Mc zaH2CX$l%=Rmx0e{jv#7Z+T+l-hu?Tivw&BFYg-VPY*UBr_pgry`hs|vV zm7)Le2q@LZT5WgJ`PCqU7f^F=xz^@4BI za^EITFEtlj#@~6)t@L;gzOsD*9x*~&$(^9}6LxQ^ucJ-oc%OuAa-MI)=X2y2pjGAU z=?m-TNKkXmIKlpcm<#V;T!KDT-KcmI)~6N~LBEq*A<_Zo3t*SH6Zto>cOsXE(W5Lj zHw~JbbB9q?4sya@d<4gnSq}w&CNpmf_8~J~mcc?9i_&nv^xO#YvFBQFshuQtH(HD$ zKyNM7VVdTROW@8^=wZ{Q?6?E|EP?N)77bPev2zEC^`BG`xuzl_f7p`yneSoAF@m-0 zveAAbA7$Oc-JfS_qt;C`puAybI_!_T!IyYvGF6^T5&Ba`F`cYNCN&6((k0e0ov2)f zR*=}A&z&TEj(|@k9P=y!d)hT(RvFCkI9}@^N)f+Z=`J|rv^^|Wv2zI+vIHYU+?(O( zTjRveSDYM65hpFU1F=MN8rq=$T)smrzC7g(yn0l!5!&GCB*clx7y6Nx2N|C&*qh{- zgT0LBWUTP>*mX?Dd=#8OM!yxDUM`6p4e#`m;IT+$u(KB|6lrg71D-I!^~f=g;O7yA zH}ydKGcDk)UHRa?<%7WmqfsLfVxADup31|;`JwPM?8U1k!2eR8#3i8Z4fyJSe#1KU zsnBp=d!{4sNl=s`d;`;A#$;%@AleS11TR4eGT5!$1zeL3`v>Jjbph4A z5yu2gaDb}7q?Z#xeQop{fxDGqkH8`4@V$W2Jqn=jiWT6?@hd@PDi07nPrz1@UW#$K zPvl&jQ-}>mEkMa9GW0PSB1bYFL0*D^icANfFGY5o9xQX8XM}MK*PgvMj*z-#-=If0Xh5P%Ho~T{i!I5Dx-?dJgL0Waft{k)VD;yj56bF1{T=+#Dc-aY)O?~1 zu23xk+gyN0I0o*A7dgIIiyRy;O&<@gr_CLw2@Vkak#tXFE}w;k-F{*ElN9q@fnku7g1lv)rU8OZW|AP znsbA}gWQEQ7CRTlBdFh4?BZFYokPhY(!!K9A4Hm&kfy@7|MGN$A+H$0I@q&VM;eGS zzL?4M^V#Gx(SG%X<)41$6}^_KP2jdHSFDwI#*P4I_`E)|qXN&pwIdEb+f=Mdmw}V}!G4cBQMtC5S8I#0_=WJ~=N*`r{#=nGY=Jv} zC7&!MwUIYs3gJsyqDCIP;uXz9q=p1}UzD1^3602lD0ycIdHZNpF-OR3SX-?+HW}RL zw-=GDy%XB+t+5tLTs?eh1g^OA0w;-*ub>sH+>_1)mu-c2sI-@W=O_mZJqrq-Q5I2< z@-CL;!Bys>v4_03k-W2mR6kGNG9p!yNM+&eO1ezn5NfX(Gp#7Z*r%Rjf|U{ZxEWaAk@b(oD%BIOZNcFLh1+KF)Sko`l!!xVCcv*h>I5Cd7 zNF#+EjZAWX1i2@K+!;@9hX-J90#?JW#2RwF@SioJ)T_?$iewnM>wE5<)>O`%tQRXQK1?0#@VMkznV01CLdfU6-8N&u3>uJ zoS|>f>rCMjz<66eMr{11I!2NK$1_!ksoS)X89-hrC;1CT|Bv)% z2>r)++eujCP39UF9`1kcGis^T+K+;1ax zz}s?iNKFM&OP74Kn&h4N@Au+N#8TDMH({j8`h3V0^UGN>P~~$~0pp^BnJR2+B6$yS z#>3SQF@jw`qI(jf`Y(LmbyHiz#TePzm>{OXTjhZYgvP+YUmqd=x?!~gf*R&oL$Tu z?HEX%E_29FKaj4X74WI`KTiJwBdXoInUsZBBib`0wc0{|oc?3zzhu$`{moWyG0WU; z2Y-HN?6?p!fTJHX5ZgX>9}E3O-lK5-qMh$doMm|BAB9-sXi#tJ3_;w4UvWhp;hA@| z7yPQyQ1XA{Ig>h4;m)5(*%joiPUPbbq@fXMHH~kGwvUGX2xmktu}9pGK)>IYZJ09+ z3tR;K)uD*gw11C;PNfeqDD_FPy0Nt;!3GhNQj!C8rXXU%o6Uv&(@{Hk@5b=|iT-v% z?Pj6#{8lQw1*>9Cg5ChL9keOT*@#wWcrqe|+0cLA{~lJn=7qxMvC+{>G1p%nkJ<8j z+hoLirh4gTpuZ{$UU&0RZY6xKcY!owM(LuPi2GbikW0HuWnHMYd<$7|n5;zW_*d*d ze=7Aze| z=-DN(t=aVQM%>H1`e*pu;o5SX;u+L11yS?oCVY26L~~GU>n~kf4^b`e`1kz#|NGB> z=aucKcg#uhNi7S~<5VU&^;8oZq`5zO8+mX^ULaWflwD<_qrVCiHo!00M%@K`*vD4t*poshi)fe%5^?S*>R6+DH zu)Am(wVHJ|k)E6fYu6;j!~QiI{`geQVy74ATU*TwKtEj%P+JXcp!(o>%uTE3?&V+m zNWwd-YDOaes(5Oy@)2|pG^PIL1@MzcO|Zhfq{iP-pW_I)vtwj z=gh190d_uCvj*j_uQsK^swTmcWM#DAcCtcPqT(3S<+XLFzj9r^S*mPRM8$t8lGST;xp^kA)cw`BzhE?`4WU=s; z;?7JLK@HfGEHtX$3C_=7jopo`gvsE80F=96p>q;eyX!2sfv!(cJNc^W#o&6`8gRsc zJE-U8)$qr>qzM_I8Mrni zaFLfAnO`C}mdwLv&?aFi@Ha9?mCP1ClYO4)ta?G^`bebv=Z9hr;F{nL9u0f}c6UMD zX82kS1@G!F2RGbq0Q+2$K<|}*2zO2QT5ALvO?e9{QFHonL3lpWOYuJ7ru+z4ds80T zRhD9|F8p9CpI3nrO)|@n%yc3%QU!aE>D$RPlpXCD_5ww(k>bvD$}}?hz2KY%SUxF` zr=XKgC9VU137U_cg%2N>fG7Db_r!6}5H}yDr@eE$}?we+4BNEujJShlbl^(o-@~lp-OG>4d>#{4SDx3VQYy zLD3dsVR4MLo5`4v2Gm~6o&wlEx-Kym)C+>mqJRHb1j`jzn}Zgt=BVR$o58VHY%$NT zJ31Z=-DnM3&YlaZQFG*JK{02JT!N>M>Jmlmf7@G$6Bhfb&3t38kukzgq7|5q5;YR} zn(2rnK~WdsyO|C{uLX+OClu`yBXEk~Hueg^iG@<&#iTP}m*A`LR_jl%K&jX8*`RLE z3(;Ey-R}zCy9&Px+#&4_j@#@Cwws4>Js_!_GU!450ak)yUKCNvT*8H)gzaHERJ6yC zwoC^Vkb$XWKql#5DcGO%lOTOXNx!%-{iQqUBlLU2*64kgHu|Gi@GL9?Hz)T(Oq3Ne z8B}zY1xMJR<$A=tfC>*y4V2VlrTkH_`*B6A?Wb-R<3vnNpZB45X z%>@))2e%}@L2r>15(l1jn*w%uGYup0CxcY*tmZ~=gn}(%i`>iK{&Zp)NLj^mFQp{qGZq6j1WJT`i#V`Vh8gV|zv=ef|ox73mVG&T&&buF(b`bSt zzk+GITcoY0ps1s_=bC~Mcf=KU0e7UJE!%tzRR#CEm0&la`fW$hz%U$K^#FciU8~pt zI-W8Hm878Gdi~N1;Lu_4WveD?wn`QBBfq`3%0bxBeu2o>gM7P#v=M4w+cRw~M_R2X zEm6~mEXI-M!UC@(m^Ksb*Hnk;mx+SIn$g3XC>BGHaZyS>crXm#FiQN4)@F3#Z8rF$ zQ6OdvR$3^%;l}G5z)ol8A_@rH4Lcb;k(>`67~Kz?N6iNP$rsI}xv-TP+6-dxrKHIV zl5c0jebh;Vp5$}%W!RxOOzKY}_3B7n(JpjCn0}H#KF$;DO=?Rt!}A}hmY{AQrl!6G zCBl)fmIZ%NT5E)D23AiTj8TdQD<1}6B`Ea<>OxcVTqkhlUMSM+#AhKjf+yI4#?-7K zRxvd8GW`_aga*MULeJx0dF2tThWi_ln&P^Kup-6m3DC@Hs< zykbTE<(*6DDX>#eL7sn3$}Azz^&rnAwW8ge4l0GupGr)t#{94>;tJS}bF&j`>>V&; zfB6z^;rI`a2VwQ(n6d^Uvcd~!_0l&FN`fQSV?;gbJM%QC+SL~nD_lnh(f*f3+mt=P zyktb1J%iFBuXW^c4^nzDdH5@N@CLbG{FQIY!%oDHq*N)nLwMS@sZ4KCCN~APzQQvF zi^@h}O)8!5iClL(at_Xi&GPyMr`) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +} +Root { + inputs 0 + name C:/Depot/o3de/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/Test_Extreme_Grade/Nuke_Test_Extreme_Grade.nk + project_directory "\"C:/Depot/o3de-engine/Gems/AtomLyIntegration/CommonFeatures/Tools/ColorGrading/TestData/Nuke/" + format "2048 1556 0 0 2048 1556 1 2K_Super_35(full-ap)" + proxy_type scale + proxy_format "1024 778 0 0 1024 778 1 1K_Super_35(full-ap)" + colorManagement OCIO + OCIO_config aces_1.0.3 + defaultViewerLUT "OCIO LUTs" + workingSpaceLUT scene_linear + monitorLut ACES/Rec.709 + monitorOutLUT "sRGB (ACES)" + int8Lut matte_paint + int16Lut texture_paint + logLut compositing_log + floatLut scene_linear +} +Read { + inputs 0 + file_type exr + file C:/Depot/o3de/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/LUTs/linear_32_LUT.exr + format "1024 32 0 0 1024 32 1 " + origset true + colorspace data + name Read_Linear_LUT_32 + xpos -846 + ypos 10 +} +set Nb1e9800 [stack 0] +Viewer { + frame 1 + frame_range 1-100 + viewerProcess "sRGB (ACES)" + name Viewer1 + xpos -847 + ypos 135 +} +push $Nb1e9800 +OCIOFileTransform { + file C:/Depot/o3de-engine/Tools/ColorGrading/OpenColorIO-Configs/aces_1.0.3/luts/Log2_48_nits_Shaper_to_linear.spi1d + working_space scene_linear + name Log2_48_nits_Shaper_to_linear + xpos -710 + ypos 46 +} +set Nb1e9000 [stack 0] +Transform { + center {1024 778} + name Transform_Position_LUT + xpos -579 + ypos 3 +} +set Nb1e8c00 [stack 0] +Read { + inputs 0 + file_type exr + file C:/Depot/o3de/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/displaymapperpassthrough.exr + format "2802 1854 0 0 2802 1854 1 " + origset true + name Read_DisplayMapperPassthrough + xpos -577 + ypos -119 +} +ZMerge { + inputs 2 + name ZMerge_Combine + xpos -413 + ypos -83 +} +set Nb18fc00 [stack 0] +HueShift { + ingray 0.136 + outgray 0.31 + saturation 2 + color_saturation 0.3 + hue_rotation -150 + brightness 0.81 + name HueShift1 + xpos -256 + ypos -83 +} +set Nb18f800 [stack 0] +OCIOCDLTransform { + saturation 1.23 + working_space scene_linear + name INV_Log2_48_nits_Shaper_to_linear + xpos -86 + ypos -83 +} +set Nb18f400 [stack 0] +Crop { + box {0 0 1024 32} + reformat true + crop false + name Crop1 + xpos -86 + ypos 32 +} +set Nb18f000 [stack 0] +OCIOFileTransform { + file C:/Depot/o3de-engine/Tools/ColorGrading/OpenColorIO-Configs/aces_1.0.3/luts/Log2_48_nits_Shaper_to_linear.spi1d + direction inverse + working_space reference + name OCIOFileTransform2 + xpos 84 + ypos 32 +} +Write { + file C:/Depot/o3de/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/Test_Extreme_Grade/test-extreme-grade_inv-Log2-48nits_32_LUT.exr + colorspace data + raw true + file_type exr + write_ACES_compliant_EXR true + datatype "32 bit float" + first_part rgba + version 8 + in_colorspace scene_linear + out_colorspace scene_linear + name Write_RAW_LUT + xpos 242 + ypos 20 +} +Viewer { + frame_range 1-100 + viewerProcess "sRGB (ACES)" + name Viewer7 + xpos 242 + ypos 135 +} +push $Nb18f400 +Write { + file C:/Depot/o3de/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/Test_Extreme_Grade/Shot_post_test-extreme-grade.exr + colorspace compositing_linear + file_type exr + write_ACES_compliant_EXR true + datatype "32 bit float" + first_part rgba + version 9 + name Write_Shot_Grade_Comp + selected true + xpos 353 + ypos -95 +} +Viewer { + frame 1 + frame_range 1-100 + viewerProcess "sRGB (ACES)" + name Viewer8 + xpos 357 + ypos 135 +} +push $Nb1e9000 +Viewer { + frame 1 + frame_range 1-100 + viewerProcess "sRGB (ACES)" + name Viewer2 + xpos -710 + ypos 137 +} +push $Nb1e8c00 +Viewer { + frame 1 + frame_range 1-100 + viewerProcess "sRGB (ACES)" + name Viewer3 + xpos -579 + ypos 135 +} +push $Nb18fc00 +Viewer { + frame 1 + frame_range 1-100 + viewerProcess "sRGB (ACES)" + name Viewer4 + xpos -413 + ypos 133 +} +push $Nb18f800 +Viewer { + frame 1 + frame_range 1-100 + viewerProcess "sRGB (ACES)" + name Viewer5 + xpos -254 + ypos 133 +} +push $Nb18f000 +Viewer { + frame 1 + frame_range 1-100 + viewerProcess "sRGB (ACES)" + name Viewer6 + xpos -86 + ypos 134 +} diff --git a/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/Test_Extreme_Grade/Nuke_Test_Extreme_Grade.nk~ b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/Test_Extreme_Grade/Nuke_Test_Extreme_Grade.nk~ new file mode 100644 index 0000000000..a7c1f478b2 --- /dev/null +++ b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/Test_Extreme_Grade/Nuke_Test_Extreme_Grade.nk~ @@ -0,0 +1,232 @@ +#! C:/Program Files/Nuke13.0v3/nuke-13.0.3.dll -nx +version 13.0 v3 +define_window_layout_xml { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +} +Root { + inputs 0 + name C:/Depot/o3de/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/Test_Extreme_Grade/Nuke_Test_Extreme_Grade.nk + project_directory "\"C:/Depot/o3de-engine/Gems/AtomLyIntegration/CommonFeatures/Tools/ColorGrading/TestData/Nuke/" + format "2048 1556 0 0 2048 1556 1 2K_Super_35(full-ap)" + proxy_type scale + proxy_format "1024 778 0 0 1024 778 1 1K_Super_35(full-ap)" + colorManagement OCIO + OCIO_config aces_1.0.3 + defaultViewerLUT "OCIO LUTs" + workingSpaceLUT scene_linear + monitorLut ACES/Rec.709 + monitorOutLUT "sRGB (ACES)" + int8Lut matte_paint + int16Lut texture_paint + logLut compositing_log + floatLut scene_linear +} +Read { + inputs 0 + file_type exr + file C:/Depot/o3de/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/LUTs/linear_32_LUT.exr + format "1024 32 0 0 1024 32 1 " + origset true + colorspace data + name Read_Linear_LUT_32 + xpos -846 + ypos 10 +} +set Ncf69800 [stack 0] +Viewer { + frame 1 + frame_range 1-100 + viewerProcess "sRGB (ACES)" + name Viewer1 + xpos -847 + ypos 135 +} +push $Ncf69800 +OCIOFileTransform { + file C:/Depot/o3de-engine/Tools/ColorGrading/OpenColorIO-Configs/aces_1.0.3/luts/Log2_48_nits_Shaper_to_linear.spi1d + working_space scene_linear + name Log2_48_nits_Shaper_to_linear + xpos -710 + ypos 46 +} +set Ncf69000 [stack 0] +Transform { + center {1024 778} + name Transform_Position_LUT + xpos -579 + ypos 3 +} +set Ncf68c00 [stack 0] +Read { + inputs 0 + file_type exr + file C:/Depot/o3de/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/displaymapperpassthrough.exr + format "2802 1854 0 0 2802 1854 1 " + origset true + name Read_DisplayMapperPassthrough + xpos -577 + ypos -119 +} +ZMerge { + inputs 2 + name ZMerge_Combine + xpos -413 + ypos -83 +} +set Ncef7c00 [stack 0] +HueShift { + ingray 0.136 + outgray 0.31 + saturation 2 + color_saturation 0.3 + hue_rotation -150 + brightness 0.81 + name HueShift1 + xpos -256 + ypos -83 +} +set Ncef7800 [stack 0] +OCIOCDLTransform { + saturation 1.23 + working_space scene_linear + name INV_Log2_48_nits_Shaper_to_linear + xpos -86 + ypos -83 +} +set Ncef7400 [stack 0] +Crop { + box {0 0 1024 32} + reformat true + crop false + name Crop1 + xpos -86 + ypos 32 +} +set Ncef7000 [stack 0] +OCIOFileTransform { + file C:/Depot/o3de-engine/Tools/ColorGrading/OpenColorIO-Configs/aces_1.0.3/luts/Log2_48_nits_Shaper_to_linear.spi1d + direction inverse + working_space reference + name OCIOFileTransform2 + xpos 84 + ypos 32 +} +Write { + file C:/Depot/o3de/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/Test_Extreme_Grade/test-extreme-grade_inv-Log2-48nits_32_LUT.exr + colorspace data + raw true + file_type exr + write_ACES_compliant_EXR true + datatype "32 bit float" + first_part rgba + version 8 + name Write_RAW_LUT + xpos 242 + ypos 20 +} +Viewer { + frame_range 1-100 + viewerProcess "sRGB (ACES)" + name Viewer7 + xpos 242 + ypos 135 +} +push $Ncef7400 +Write { + file C:/Depot/o3de/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/Test_Grade/Shot_post_test-extreme-grade.exr + colorspace compositing_linear + file_type exr + write_ACES_compliant_EXR true + datatype "32 bit float" + first_part rgba + version 7 + name Write_Shot_Grade_Comp + xpos 353 + ypos -95 +} +Viewer { + frame 1 + frame_range 1-100 + viewerProcess "sRGB (ACES)" + name Viewer8 + xpos 357 + ypos 135 +} +push $Ncf69000 +Viewer { + frame 1 + frame_range 1-100 + viewerProcess "sRGB (ACES)" + name Viewer2 + xpos -710 + ypos 137 +} +push $Ncf68c00 +Viewer { + frame 1 + frame_range 1-100 + viewerProcess "sRGB (ACES)" + name Viewer3 + xpos -579 + ypos 135 +} +push $Ncef7c00 +Viewer { + frame 1 + frame_range 1-100 + viewerProcess "sRGB (ACES)" + name Viewer4 + xpos -413 + ypos 133 +} +push $Ncef7800 +Viewer { + frame 1 + frame_range 1-100 + viewerProcess "sRGB (ACES)" + name Viewer5 + xpos -254 + ypos 133 +} +push $Ncef7000 +Viewer { + frame 1 + frame_range 1-100 + viewerProcess "sRGB (ACES)" + name Viewer6 + xpos -86 + ypos 134 +} diff --git a/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/Test_Extreme_Grade/Shot_post_test-extreme-grade.exr b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/Test_Extreme_Grade/Shot_post_test-extreme-grade.exr new file mode 100644 index 0000000000..f9235dac3a --- /dev/null +++ b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/Test_Extreme_Grade/Shot_post_test-extreme-grade.exr @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7ea4288b55725bfa89d7add69ea45b0ac9315cfffd6acfba66082f4d21c1ac1a +size 31227624 diff --git a/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/Test_Extreme_Grade/test-extreme-grade_inv-Log2-48nits_32_LUT.3dl b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/Test_Extreme_Grade/test-extreme-grade_inv-Log2-48nits_32_LUT.3dl new file mode 100644 index 0000000000..00a68043ad --- /dev/null +++ b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/Test_Extreme_Grade/test-extreme-grade_inv-Log2-48nits_32_LUT.3dl @@ -0,0 +1,32769 @@ +0 33 66 99 132 165 198 231 264 297 330 363 396 429 462 495 528 561 594 627 660 693 726 759 792 825 858 891 924 957 990 1023 +0 0 0 +0 40 0 +0 176 0 +0 310 0 +0 444 0 +0 578 0 +0 711 0 +0 844 0 +0 976 0 +0 1109 0 +0 1241 0 +0 1374 0 +0 1506 0 +0 1638 0 +0 1770 0 +0 1903 0 +0 2035 0 +0 2167 0 +0 2299 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +235 0 150 +0 22 0 +0 162 0 +0 300 0 +0 437 0 +0 572 0 +0 707 0 +0 841 0 +0 974 0 +0 1107 0 +0 1240 0 +0 1373 0 +0 1505 0 +0 1638 0 +0 1770 0 +0 1902 0 +0 2035 0 +0 2167 0 +0 2299 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +474 0 352 +349 0 225 +98 143 0 +0 286 0 +0 427 0 +0 565 0 +0 701 0 +0 836 0 +0 971 0 +0 1105 0 +0 1238 0 +0 1371 0 +0 1504 0 +0 1637 0 +0 1769 0 +0 1902 0 +0 2034 0 +0 2167 0 +0 2299 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +672 0 529 +595 0 448 +467 117 309 +205 267 14 +0 412 0 +0 554 0 +0 693 0 +0 831 0 +0 967 0 +0 1102 0 +0 1236 0 +0 1370 0 +0 1503 0 +0 1636 0 +0 1769 0 +0 1901 0 +0 2034 0 +0 2167 0 +0 2299 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +848 0 693 +797 0 638 +719 78 551 +588 240 402 +318 393 67 +0 540 0 +0 683 0 +0 823 0 +0 961 0 +0 1097 0 +0 1233 0 +0 1367 0 +0 1501 0 +0 1635 0 +0 1768 0 +0 1901 0 +0 2033 0 +0 2165 0 +0 2299 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1010 0 848 +975 0 809 +924 22 751 +845 201 661 +712 365 502 +435 520 130 +0 669 0 +0 813 0 +0 953 0 +0 1092 0 +0 1228 0 +0 1364 0 +0 1499 0 +0 1633 0 +0 1766 0 +0 1900 0 +0 2033 0 +0 2165 0 +0 2297 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1163 0 996 +1139 0 968 +1104 0 928 +1052 143 869 +972 326 775 +837 493 609 +555 649 202 +0 798 0 +0 943 0 +0 1084 0 +0 1223 0 +0 1360 0 +0 1496 0 +0 1631 0 +0 1765 0 +0 1898 0 +0 2032 0 +0 2165 0 +0 2297 0 +0 2429 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1311 0 1139 +1293 0 1119 +1269 0 1091 +1233 52 1050 +1181 267 990 +1101 452 893 +965 621 721 +678 778 283 +0 928 0 +0 1073 0 +0 1215 0 +0 1354 0 +0 1491 0 +0 1627 0 +0 1762 0 +0 1897 0 +0 2030 0 +0 2163 0 +0 2297 0 +0 2429 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3355 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1454 0 1280 +1441 0 1265 +1424 0 1245 +1399 0 1216 +1363 174 1175 +1311 393 1113 +1230 580 1015 +1093 750 837 +804 908 374 +0 1059 0 +0 1204 0 +0 1346 0 +0 1486 0 +0 1623 0 +0 1759 0 +0 1894 0 +0 2029 0 +0 2163 0 +0 2295 0 +0 2429 0 +0 2561 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3355 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1595 0 1418 +1585 0 1407 +1572 0 1393 +1554 0 1372 +1530 9 1343 +1494 298 1301 +1441 520 1239 +1360 709 1139 +1222 880 957 +931 1039 472 +0 1190 0 +0 1336 0 +0 1478 0 +0 1617 0 +0 1755 0 +0 1891 0 +0 2026 0 +0 2161 0 +0 2295 0 +0 2427 0 +0 2561 0 +0 2693 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3355 0 +0 3487 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1733 0 1555 +1726 0 1547 +1716 0 1536 +1703 0 1521 +1686 0 1501 +1661 130 1471 +1625 424 1429 +1572 649 1366 +1491 839 1265 +1352 1011 1080 +1059 1170 577 +0 1321 0 +0 1467 0 +0 1610 0 +0 1749 0 +0 1887 0 +0 2023 0 +0 2159 0 +0 2293 0 +0 2427 0 +0 2559 0 +0 2693 0 +0 2825 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3355 0 +0 3487 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1869 0 1690 +1864 0 1684 +1857 0 1676 +1848 0 1666 +1835 0 1651 +1817 0 1630 +1792 254 1601 +1756 552 1558 +1704 778 1494 +1622 970 1392 +1483 1141 1205 +1188 1301 687 +0 1453 0 +0 1599 0 +0 1741 0 +0 1881 0 +0 2019 0 +0 2155 0 +0 2291 0 +0 2425 0 +0 2559 0 +0 2691 0 +0 2825 0 +0 2957 0 +0 3091 0 +0 3223 0 +0 3355 0 +0 3487 0 +0 3619 0 +0 3753 0 +0 3885 0 +0 4017 0 +2005 0 1825 +2001 0 1821 +1996 0 1815 +1989 0 1807 +1979 0 1796 +1966 0 1781 +1949 0 1760 +1924 379 1731 +1888 681 1688 +1835 908 1624 +1753 1100 1521 +1614 1272 1332 +1318 1432 803 +0 1584 0 +0 1731 0 +0 1873 0 +0 2013 0 +0 2151 0 +0 2287 0 +0 2423 0 +0 2557 0 +0 2691 0 +0 2823 0 +0 2957 0 +0 3089 0 +0 3223 0 +0 3355 0 +0 3487 0 +0 3619 0 +0 3753 0 +0 3885 0 +0 4017 0 +2139 0 1959 +2137 0 1956 +2133 0 1951 +2127 0 1945 +2121 0 1937 +2111 0 1927 +2099 0 1912 +2081 0 1891 +2055 506 1861 +2019 810 1818 +1967 1038 1754 +1885 1231 1650 +1745 1404 1460 +1448 1564 922 +0 1716 0 +0 1863 0 +0 2005 0 +0 2145 0 +0 2283 0 +0 2419 0 +0 2555 0 +0 2689 0 +0 2823 0 +0 2957 0 +0 3089 0 +0 3221 0 +0 3355 0 +0 3487 0 +0 3619 0 +0 3751 0 +0 3885 0 +0 4017 0 +2273 0 2093 +2271 0 2091 +2269 0 2087 +2265 0 2083 +2259 0 2077 +2253 0 2069 +2243 0 2057 +2231 0 2043 +2213 60 2022 +2187 635 1992 +2151 941 1949 +2099 1169 1884 +2016 1363 1781 +1877 1536 1589 +1579 1696 1044 +0 1848 0 +0 1995 0 +0 2137 0 +0 2277 0 +0 2415 0 +0 2551 0 +0 2687 0 +0 2821 0 +0 2955 0 +0 3089 0 +0 3221 0 +0 3355 0 +0 3487 0 +0 3619 0 +0 3751 0 +0 3885 0 +0 4017 0 +2407 0 2225 +2405 0 2223 +2403 0 2221 +2401 0 2219 +2397 0 2213 +2391 0 2207 +2385 0 2199 +2375 0 2189 +2361 0 2173 +2345 182 2153 +2319 764 2123 +2283 1071 2081 +2231 1301 2015 +2149 1494 1911 +2008 1667 1719 +1710 1828 1168 +0 1980 0 +0 2127 0 +0 2269 0 +0 2409 0 +0 2547 0 +0 2683 0 +0 2819 0 +0 2953 0 +0 3087 0 +0 3221 0 +0 3353 0 +0 3487 0 +0 3619 0 +0 3751 0 +0 3883 0 +0 4017 0 +2539 0 2359 +2539 0 2357 +2537 0 2355 +2535 0 2353 +2533 0 2349 +2529 0 2345 +2523 0 2339 +2517 0 2331 +2507 0 2321 +2493 0 2305 +2475 306 2285 +2451 894 2255 +2415 1202 2211 +2363 1432 2147 +2279 1626 2042 +2141 1799 1850 +1842 1960 1295 +0 2113 0 +0 2259 0 +0 2401 0 +0 2541 0 +0 2679 0 +0 2815 0 +0 2951 0 +0 3085 0 +0 3219 0 +0 3353 0 +0 3485 0 +0 3619 0 +0 3751 0 +0 3883 0 +0 4015 0 +2673 0 2491 +2671 0 2491 +2671 0 2489 +2669 0 2487 +2667 0 2485 +2665 0 2481 +2661 0 2477 +2655 0 2471 +2649 0 2463 +2639 0 2453 +2625 0 2437 +2607 433 2415 +2583 1025 2387 +2547 1334 2343 +2493 1564 2279 +2411 1758 2173 +2273 1931 1981 +1973 2091 1423 +0 2245 0 +0 2391 0 +0 2533 0 +0 2673 0 +0 2811 0 +0 2947 0 +0 3083 0 +0 3217 0 +0 3351 0 +0 3485 0 +0 3617 0 +0 3751 0 +0 3883 0 +0 4015 0 +2805 0 2623 +2805 0 2623 +2803 0 2623 +2803 0 2621 +2801 0 2619 +2799 0 2617 +2797 0 2613 +2793 0 2609 +2787 0 2603 +2781 0 2595 +2771 0 2583 +2757 0 2569 +2741 560 2547 +2715 1155 2517 +2679 1465 2475 +2625 1696 2409 +2543 1890 2305 +2403 2063 2111 +2105 2223 1552 +0 2377 0 +0 2523 0 +0 2665 0 +0 2805 0 +0 2943 0 +0 3079 0 +0 3215 0 +0 3349 0 +0 3483 0 +0 3617 0 +0 3749 0 +0 3883 0 +0 4015 0 +2937 0 2757 +2937 0 2755 +2937 0 2755 +2935 0 2755 +2935 0 2753 +2933 0 2751 +2931 0 2749 +2929 0 2745 +2925 0 2741 +2919 0 2735 +2913 0 2727 +2903 0 2715 +2891 0 2701 +2873 689 2679 +2847 1287 2649 +2811 1597 2607 +2759 1828 2541 +2675 2022 2437 +2535 2195 2243 +2237 2355 1681 +0 2509 0 +0 2655 0 +0 2797 0 +0 2937 0 +0 3075 0 +0 3211 0 +0 3347 0 +0 3481 0 +0 3615 0 +0 3749 0 +0 3881 0 +0 4015 0 +3071 0 2889 +3069 0 2889 +3069 0 2887 +3069 0 2887 +3067 0 2885 +3067 0 2885 +3065 0 2883 +3063 0 2881 +3061 0 2877 +3057 0 2873 +3051 0 2867 +3045 0 2859 +3035 0 2847 +3023 0 2833 +3005 819 2811 +2979 1418 2781 +2943 1729 2739 +2891 1959 2673 +2807 2153 2569 +2667 2327 2375 +2369 2487 1811 +0 2641 0 +0 2787 0 +0 2929 0 +0 3069 0 +0 3207 0 +0 3343 0 +0 3479 0 +0 3613 0 +0 3747 0 +0 3881 0 +0 4015 0 +3203 0 3021 +3203 0 3021 +3203 0 3021 +3201 0 3019 +3201 0 3019 +3201 0 3017 +3199 0 3017 +3197 0 3015 +3195 0 3013 +3193 0 3009 +3189 0 3005 +3183 0 2999 +3177 0 2991 +3167 0 2979 +3155 0 2965 +3137 949 2943 +3111 1550 2913 +3075 1860 2871 +3023 2091 2805 +2939 2285 2701 +2801 2459 2507 +2501 2619 1942 +0 2773 0 +0 2919 0 +0 3061 0 +0 3201 0 +0 3339 0 +0 3475 0 +0 3611 0 +0 3745 0 +0 3879 0 +0 4013 0 +3335 0 3153 +3335 0 3153 +3335 0 3153 +3335 0 3153 +3333 0 3151 +3333 0 3151 +3333 0 3151 +3331 0 3149 +3329 0 3147 +3327 0 3145 +3325 0 3141 +3321 0 3137 +3315 0 3131 +3309 0 3123 +3299 0 3111 +3287 0 3097 +3269 1080 3075 +3243 1682 3045 +3207 1992 3003 +3155 2223 2937 +3073 2417 2833 +2933 2591 2639 +2633 2751 2073 +0 2905 0 +0 3051 0 +0 3193 0 +0 3333 0 +0 3471 0 +0 3609 0 +0 3743 0 +0 3877 0 +0 4011 0 +3467 0 3285 +3467 0 3285 +3467 0 3285 +3467 0 3285 +3467 0 3285 +3465 0 3283 +3465 0 3283 +3465 0 3283 +3463 0 3281 +3461 0 3279 +3459 0 3277 +3457 0 3273 +3453 0 3269 +3447 0 3263 +3441 0 3255 +3431 0 3243 +3419 0 3229 +3401 1211 3207 +3375 1813 3177 +3339 2125 3135 +3287 2355 3069 +3205 2549 2965 +3065 2723 2771 +2765 2885 2205 +0 3037 0 +0 3183 0 +0 3327 0 +0 3465 0 +0 3603 0 +0 3741 0 +0 3875 0 +0 4009 0 +3599 0 3417 +3599 0 3417 +3599 0 3417 +3599 0 3417 +3599 0 3417 +3599 0 3417 +3597 0 3415 +3597 0 3415 +3597 0 3415 +3595 0 3413 +3593 0 3411 +3591 0 3409 +3589 0 3405 +3585 0 3401 +3579 0 3395 +3573 0 3387 +3563 0 3375 +3551 0 3361 +3533 1342 3339 +3507 1945 3309 +3471 2257 3267 +3419 2487 3201 +3337 2681 3097 +3197 2855 2903 +2897 3017 2337 +0 3169 0 +0 3315 0 +0 3459 0 +0 3599 0 +0 3735 0 +0 3873 0 +0 4007 0 +3731 0 3549 +3731 0 3549 +3731 0 3549 +3731 0 3549 +3731 0 3549 +3731 0 3549 +3731 0 3549 +3731 0 3547 +3729 0 3547 +3729 0 3547 +3727 0 3545 +3725 0 3543 +3723 0 3541 +3721 0 3537 +3717 0 3533 +3711 0 3527 +3705 0 3519 +3695 0 3507 +3683 0 3493 +3665 1474 3471 +3639 2077 3441 +3603 2389 3399 +3551 2619 3333 +3469 2813 3229 +3329 2987 3035 +3029 3149 2467 +0 3301 0 +0 3447 0 +0 3591 0 +0 3731 0 +0 3869 0 +0 4005 0 +3863 0 3683 +3863 0 3681 +3863 0 3681 +3863 0 3681 +3863 0 3681 +3863 0 3681 +3863 0 3681 +3863 0 3681 +3863 0 3681 +3861 0 3679 +3861 0 3679 +3859 0 3677 +3857 0 3675 +3855 0 3673 +3853 0 3669 +3849 0 3665 +3845 0 3659 +3837 0 3651 +3827 0 3641 +3815 0 3625 +3797 1605 3603 +3771 2209 3573 +3735 2521 3531 +3683 2751 3465 +3601 2947 3361 +3461 3119 3167 +3161 3281 2599 +0 3433 0 +0 3579 0 +0 3723 0 +0 3863 0 +0 4001 0 +3997 0 3815 +3997 0 3815 +3995 0 3815 +3995 0 3813 +3995 0 3813 +3995 0 3813 +3995 0 3813 +3995 0 3813 +3995 0 3813 +3995 0 3813 +3993 0 3811 +3993 0 3811 +3991 0 3809 +3991 0 3807 +3987 0 3805 +3985 0 3801 +3981 0 3797 +3977 0 3791 +3969 0 3783 +3959 0 3773 +3947 0 3757 +3929 1737 3735 +3903 2341 3705 +3867 2653 3663 +3815 2883 3597 +3733 3079 3493 +3593 3251 3299 +3293 3413 2731 +0 3565 0 +0 3711 0 +0 3855 0 +0 3995 0 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3945 +4095 0 3945 +4095 0 3945 +4095 0 3945 +4095 0 3945 +4095 0 3945 +4095 0 3943 +4095 0 3943 +4095 0 3941 +4095 0 3939 +4095 0 3937 +4095 0 3933 +4095 0 3929 +4095 0 3923 +4095 0 3915 +4091 0 3905 +4079 0 3889 +4061 1869 3867 +4035 2473 3839 +3999 2785 3795 +3947 3015 3729 +3865 3211 3625 +3725 3383 3431 +3425 3545 2863 +0 3697 0 +0 3843 0 +0 3987 0 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4077 +4095 0 4077 +4095 0 4077 +4095 0 4077 +4095 0 4077 +4095 0 4075 +4095 0 4075 +4095 0 4073 +4095 0 4071 +4095 0 4069 +4095 0 4065 +4095 0 4061 +4095 0 4055 +4095 0 4047 +4095 0 4037 +4095 0 4021 +4095 2001 4001 +4095 2605 3971 +4095 2917 3927 +4079 3149 3861 +3997 3343 3757 +3857 3515 3563 +3557 3677 2995 +0 3829 0 +0 3977 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 2133 4095 +4095 2737 4095 +4095 3049 4059 +4095 3281 3993 +4095 3475 3889 +3989 3649 3695 +3689 3809 3127 +0 3961 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 2265 4095 +4095 2869 4095 +4095 3181 4095 +4095 3413 4095 +4095 3607 4021 +4095 3781 3827 +3821 3941 3259 +0 0 13 +0 54 0 +0 186 0 +0 318 0 +0 450 0 +0 582 0 +0 714 0 +0 846 0 +0 978 0 +0 1110 0 +0 1242 0 +0 1374 0 +0 1506 0 +0 1639 0 +0 1771 0 +0 1903 0 +0 2035 0 +0 2167 0 +0 2299 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +258 0 216 +36 36 36 +0 172 0 +0 308 0 +0 442 0 +0 576 0 +0 710 0 +0 843 0 +0 976 0 +0 1108 0 +0 1241 0 +0 1373 0 +0 1506 0 +0 1638 0 +0 1770 0 +0 1903 0 +0 2035 0 +0 2167 0 +0 2299 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +488 0 395 +367 11 282 +129 154 65 +0 294 0 +0 432 0 +0 569 0 +0 704 0 +0 839 0 +0 973 0 +0 1106 0 +0 1239 0 +0 1372 0 +0 1505 0 +0 1637 0 +0 1770 0 +0 1902 0 +0 2034 0 +0 2167 0 +0 2299 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +681 0 560 +606 0 484 +481 128 357 +230 275 101 +0 418 0 +0 559 0 +0 697 0 +0 833 0 +0 969 0 +0 1103 0 +0 1237 0 +0 1370 0 +0 1503 0 +0 1636 0 +0 1769 0 +0 1902 0 +0 2034 0 +0 2167 0 +0 2299 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +854 0 714 +804 0 662 +727 91 580 +599 249 441 +337 399 146 +0 544 0 +0 686 0 +0 826 0 +0 963 0 +0 1099 0 +0 1234 0 +0 1368 0 +0 1502 0 +0 1635 0 +0 1768 0 +0 1901 0 +0 2033 0 +0 2165 0 +0 2299 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1015 0 863 +980 0 825 +929 36 770 +851 210 683 +720 372 534 +450 525 199 +0 672 0 +0 815 0 +0 955 0 +0 1093 0 +0 1229 0 +0 1365 0 +0 1499 0 +0 1633 0 +0 1767 0 +0 1900 0 +0 2033 0 +0 2165 0 +0 2297 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1167 0 1007 +1142 0 980 +1107 0 941 +1056 154 883 +977 333 793 +844 498 634 +567 652 262 +0 801 0 +0 945 0 +0 1085 0 +0 1224 0 +0 1361 0 +0 1496 0 +0 1631 0 +0 1765 0 +0 1899 0 +0 2032 0 +0 2165 0 +0 2297 0 +0 2429 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1313 0 1147 +1296 0 1128 +1271 0 1100 +1236 65 1060 +1184 275 1001 +1104 458 907 +969 625 741 +687 781 334 +0 930 0 +0 1075 0 +0 1216 0 +0 1355 0 +0 1492 0 +0 1628 0 +0 1763 0 +0 1897 0 +0 2030 0 +0 2163 0 +0 2297 0 +0 2429 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3355 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1456 0 1286 +1443 0 1271 +1425 0 1251 +1401 0 1223 +1365 184 1182 +1313 399 1122 +1233 584 1025 +1097 753 853 +810 910 416 +0 1060 0 +0 1206 0 +0 1347 0 +0 1486 0 +0 1624 0 +0 1760 0 +0 1894 0 +0 2029 0 +0 2163 0 +0 2295 0 +0 2429 0 +0 2561 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3355 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1596 0 1422 +1586 0 1412 +1574 0 1397 +1556 0 1377 +1531 23 1348 +1495 306 1307 +1443 525 1245 +1362 712 1147 +1225 882 969 +936 1040 506 +0 1191 0 +0 1337 0 +0 1479 0 +0 1618 0 +0 1755 0 +0 1891 0 +0 2026 0 +0 2161 0 +0 2295 0 +0 2427 0 +0 2561 0 +0 2693 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3355 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1734 0 1558 +1727 0 1550 +1717 0 1539 +1704 0 1525 +1687 0 1504 +1662 141 1475 +1626 430 1434 +1574 652 1371 +1492 841 1271 +1354 1012 1089 +1063 1171 604 +0 1322 0 +0 1468 0 +0 1610 0 +0 1750 0 +0 1887 0 +0 2023 0 +0 2159 0 +0 2293 0 +0 2427 0 +0 2559 0 +0 2693 0 +0 2825 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3355 0 +0 3487 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1870 0 1693 +1865 0 1687 +1858 0 1679 +1848 0 1668 +1836 0 1653 +1818 0 1633 +1793 262 1604 +1757 556 1561 +1704 781 1498 +1623 971 1397 +1485 1142 1212 +1191 1302 709 +0 1453 0 +0 1599 0 +0 1742 0 +0 1881 0 +0 2019 0 +0 2155 0 +0 2291 0 +0 2425 0 +0 2559 0 +0 2691 0 +0 2825 0 +0 2957 0 +0 3091 0 +0 3223 0 +0 3355 0 +0 3487 0 +0 3619 0 +0 3753 0 +0 3885 0 +0 4017 0 +2005 0 1827 +2001 0 1822 +1996 0 1817 +1989 0 1809 +1980 0 1798 +1967 0 1783 +1949 0 1762 +1924 386 1733 +1888 684 1690 +1836 910 1627 +1754 1101 1524 +1615 1273 1337 +1320 1433 819 +0 1585 0 +0 1731 0 +0 1874 0 +0 2013 0 +0 2151 0 +0 2287 0 +0 2423 0 +0 2557 0 +0 2691 0 +0 2823 0 +0 2957 0 +0 3089 0 +0 3223 0 +0 3355 0 +0 3487 0 +0 3619 0 +0 3753 0 +0 3885 0 +0 4017 0 +2139 0 1960 +2137 0 1957 +2133 0 1953 +2127 0 1947 +2121 0 1939 +2111 0 1928 +2099 0 1913 +2081 0 1892 +2055 511 1863 +2020 813 1820 +1967 1040 1756 +1885 1232 1653 +1746 1405 1464 +1450 1565 935 +0 1717 0 +0 1863 0 +0 2005 0 +0 2145 0 +0 2283 0 +0 2419 0 +0 2555 0 +0 2689 0 +0 2823 0 +0 2957 0 +0 3089 0 +0 3221 0 +0 3355 0 +0 3487 0 +0 3619 0 +0 3751 0 +0 3885 0 +0 4017 0 +2273 0 2093 +2271 0 2091 +2269 0 2087 +2265 0 2083 +2259 0 2077 +2253 0 2069 +2243 0 2059 +2231 0 2044 +2213 72 2023 +2187 638 1993 +2151 943 1950 +2099 1171 1886 +2017 1363 1783 +1877 1536 1592 +1580 1696 1054 +0 1848 0 +0 1995 0 +0 2137 0 +0 2277 0 +0 2415 0 +0 2551 0 +0 2687 0 +0 2821 0 +0 2955 0 +0 3089 0 +0 3221 0 +0 3355 0 +0 3487 0 +0 3619 0 +0 3751 0 +0 3885 0 +0 4017 0 +2407 0 2227 +2405 0 2225 +2403 0 2223 +2401 0 2219 +2397 0 2215 +2391 0 2209 +2385 0 2201 +2375 0 2189 +2363 0 2175 +2345 192 2153 +2319 767 2125 +2283 1073 2081 +2231 1302 2017 +2149 1495 1913 +2009 1668 1722 +1711 1828 1176 +0 1980 0 +0 2127 0 +0 2269 0 +0 2409 0 +0 2547 0 +0 2683 0 +0 2819 0 +0 2953 0 +0 3087 0 +0 3221 0 +0 3353 0 +0 3487 0 +0 3619 0 +0 3751 0 +0 3883 0 +0 4017 0 +2539 0 2359 +2539 0 2357 +2537 0 2357 +2535 0 2353 +2533 0 2351 +2529 0 2345 +2523 0 2341 +2517 0 2333 +2507 0 2321 +2495 0 2305 +2477 314 2285 +2451 896 2255 +2415 1203 2213 +2363 1433 2147 +2281 1626 2043 +2141 1799 1851 +1842 1960 1301 +0 2113 0 +0 2259 0 +0 2401 0 +0 2541 0 +0 2679 0 +0 2815 0 +0 2951 0 +0 3085 0 +0 3219 0 +0 3353 0 +0 3485 0 +0 3619 0 +0 3751 0 +0 3883 0 +0 4015 0 +2673 0 2491 +2671 0 2491 +2671 0 2489 +2669 0 2487 +2667 0 2485 +2665 0 2481 +2661 0 2477 +2655 0 2471 +2649 0 2463 +2639 0 2453 +2627 0 2437 +2609 438 2417 +2583 1026 2387 +2547 1334 2343 +2495 1564 2279 +2413 1758 2175 +2273 1931 1982 +1974 2091 1427 +0 2245 0 +0 2391 0 +0 2533 0 +0 2673 0 +0 2811 0 +0 2947 0 +0 3083 0 +0 3217 0 +0 3351 0 +0 3485 0 +0 3617 0 +0 3751 0 +0 3883 0 +0 4015 0 +2805 0 2625 +2805 0 2623 +2803 0 2623 +2803 0 2621 +2801 0 2619 +2799 0 2617 +2797 0 2613 +2793 0 2609 +2787 0 2603 +2781 0 2595 +2771 0 2585 +2759 0 2569 +2741 565 2549 +2715 1157 2519 +2679 1466 2475 +2627 1696 2411 +2543 1890 2305 +2405 2063 2113 +2105 2223 1555 +0 2377 0 +0 2523 0 +0 2665 0 +0 2805 0 +0 2943 0 +0 3079 0 +0 3215 0 +0 3349 0 +0 3483 0 +0 3617 0 +0 3749 0 +0 3883 0 +0 4015 0 +2937 0 2757 +2937 0 2755 +2937 0 2755 +2935 0 2755 +2935 0 2753 +2933 0 2751 +2931 0 2749 +2929 0 2745 +2925 0 2741 +2919 0 2735 +2913 0 2727 +2903 0 2717 +2891 0 2701 +2873 693 2679 +2847 1288 2651 +2811 1597 2607 +2759 1828 2541 +2675 2022 2437 +2537 2195 2243 +2237 2355 1684 +0 2509 0 +0 2655 0 +0 2797 0 +0 2937 0 +0 3075 0 +0 3211 0 +0 3347 0 +0 3481 0 +0 3615 0 +0 3749 0 +0 3881 0 +0 4015 0 +3071 0 2889 +3071 0 2889 +3069 0 2887 +3069 0 2887 +3069 0 2887 +3067 0 2885 +3065 0 2883 +3063 0 2881 +3061 0 2877 +3057 0 2873 +3051 0 2867 +3045 0 2859 +3035 0 2847 +3023 0 2833 +3005 821 2811 +2979 1419 2781 +2943 1729 2739 +2891 1960 2673 +2807 2153 2569 +2669 2327 2375 +2369 2487 1813 +0 2641 0 +0 2787 0 +0 2929 0 +0 3069 0 +0 3207 0 +0 3343 0 +0 3479 0 +0 3613 0 +0 3747 0 +0 3881 0 +0 4015 0 +3203 0 3021 +3203 0 3021 +3203 0 3021 +3201 0 3019 +3201 0 3019 +3201 0 3019 +3199 0 3017 +3197 0 3015 +3195 0 3013 +3193 0 3009 +3189 0 3005 +3183 0 2999 +3177 0 2991 +3167 0 2979 +3155 0 2965 +3137 951 2943 +3111 1550 2913 +3075 1861 2871 +3023 2091 2805 +2941 2285 2701 +2801 2459 2507 +2501 2619 1944 +0 2773 0 +0 2919 0 +0 3061 0 +0 3201 0 +0 3339 0 +0 3477 0 +0 3611 0 +0 3745 0 +0 3879 0 +0 4013 0 +3335 0 3153 +3335 0 3153 +3335 0 3153 +3335 0 3153 +3333 0 3151 +3333 0 3151 +3333 0 3151 +3331 0 3149 +3329 0 3147 +3327 0 3145 +3325 0 3141 +3321 0 3137 +3315 0 3131 +3309 0 3123 +3299 0 3111 +3287 0 3097 +3269 1081 3075 +3243 1682 3045 +3207 1993 3003 +3155 2223 2937 +3073 2417 2833 +2933 2591 2639 +2633 2753 2075 +0 2905 0 +0 3051 0 +0 3193 0 +0 3333 0 +0 3471 0 +0 3609 0 +0 3743 0 +0 3877 0 +0 4011 0 +3467 0 3285 +3467 0 3285 +3467 0 3285 +3467 0 3285 +3467 0 3285 +3465 0 3283 +3465 0 3283 +3465 0 3283 +3463 0 3281 +3461 0 3279 +3459 0 3277 +3457 0 3273 +3453 0 3269 +3447 0 3263 +3441 0 3255 +3431 0 3243 +3419 0 3229 +3401 1212 3207 +3375 1814 3177 +3339 2125 3135 +3287 2355 3069 +3205 2549 2965 +3065 2723 2771 +2765 2885 2205 +0 3037 0 +0 3183 0 +0 3327 0 +0 3467 0 +0 3603 0 +0 3741 0 +0 3875 0 +0 4009 0 +3599 0 3417 +3599 0 3417 +3599 0 3417 +3599 0 3417 +3599 0 3417 +3599 0 3417 +3597 0 3415 +3597 0 3415 +3597 0 3415 +3595 0 3413 +3593 0 3411 +3591 0 3409 +3589 0 3405 +3585 0 3401 +3579 0 3395 +3573 0 3387 +3563 0 3375 +3551 0 3361 +3533 1343 3339 +3507 1946 3309 +3471 2257 3267 +3419 2487 3201 +3337 2681 3097 +3197 2855 2903 +2897 3017 2337 +0 3169 0 +0 3315 0 +0 3459 0 +0 3599 0 +0 3735 0 +0 3873 0 +0 4007 0 +3731 0 3549 +3731 0 3549 +3731 0 3549 +3731 0 3549 +3731 0 3549 +3731 0 3549 +3731 0 3549 +3731 0 3549 +3729 0 3547 +3729 0 3547 +3727 0 3545 +3725 0 3543 +3723 0 3541 +3721 0 3537 +3717 0 3533 +3711 0 3527 +3705 0 3519 +3695 0 3507 +3683 0 3493 +3665 1474 3471 +3639 2077 3441 +3603 2389 3399 +3551 2619 3333 +3469 2813 3229 +3329 2987 3035 +3029 3149 2469 +0 3301 0 +0 3447 0 +0 3591 0 +0 3731 0 +0 3869 0 +0 4005 0 +3863 0 3683 +3863 0 3683 +3863 0 3681 +3863 0 3681 +3863 0 3681 +3863 0 3681 +3863 0 3681 +3863 0 3681 +3863 0 3681 +3861 0 3679 +3861 0 3679 +3859 0 3677 +3857 0 3675 +3855 0 3673 +3853 0 3669 +3849 0 3665 +3845 0 3659 +3837 0 3651 +3827 0 3641 +3815 0 3625 +3797 1606 3603 +3771 2209 3573 +3735 2521 3531 +3683 2751 3465 +3601 2947 3361 +3461 3119 3167 +3161 3281 2601 +0 3433 0 +0 3579 0 +0 3723 0 +0 3863 0 +0 4001 0 +3997 0 3815 +3997 0 3815 +3995 0 3815 +3995 0 3815 +3995 0 3813 +3995 0 3813 +3995 0 3813 +3995 0 3813 +3995 0 3813 +3995 0 3813 +3993 0 3811 +3993 0 3811 +3991 0 3809 +3991 0 3807 +3987 0 3805 +3985 0 3801 +3981 0 3797 +3977 0 3791 +3969 0 3783 +3959 0 3773 +3947 0 3757 +3929 1738 3735 +3903 2341 3707 +3867 2653 3663 +3815 2883 3597 +3733 3079 3493 +3593 3251 3299 +3293 3413 2731 +0 3565 0 +0 3711 0 +0 3855 0 +0 3995 0 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3945 +4095 0 3945 +4095 0 3945 +4095 0 3945 +4095 0 3945 +4095 0 3945 +4095 0 3943 +4095 0 3943 +4095 0 3941 +4095 0 3939 +4095 0 3937 +4095 0 3933 +4095 0 3929 +4095 0 3923 +4095 0 3915 +4091 0 3905 +4079 0 3889 +4061 1869 3867 +4035 2473 3839 +3999 2785 3795 +3947 3015 3729 +3865 3211 3625 +3725 3383 3431 +3425 3545 2863 +0 3697 0 +0 3843 0 +0 3987 0 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4077 +4095 0 4077 +4095 0 4077 +4095 0 4077 +4095 0 4077 +4095 0 4075 +4095 0 4075 +4095 0 4073 +4095 0 4071 +4095 0 4069 +4095 0 4065 +4095 0 4061 +4095 0 4055 +4095 0 4047 +4095 0 4037 +4095 0 4021 +4095 2001 4001 +4095 2605 3971 +4095 2917 3927 +4079 3149 3861 +3997 3343 3757 +3857 3515 3563 +3557 3677 2995 +0 3829 0 +0 3977 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 2133 4095 +4095 2737 4095 +4095 3049 4059 +4095 3281 3993 +4095 3475 3889 +3989 3649 3695 +3689 3809 3127 +0 3961 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 2265 4095 +4095 2869 4095 +4095 3181 4095 +4095 3413 4095 +4095 3607 4021 +4095 3781 3827 +3821 3941 3259 +7 0 127 +0 71 0 +0 199 0 +0 328 0 +0 457 0 +0 587 0 +0 718 0 +0 849 0 +0 980 0 +0 1112 0 +0 1243 0 +0 1375 0 +0 1507 0 +0 1639 0 +0 1771 0 +0 1903 0 +0 2035 0 +0 2167 0 +0 2299 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +287 0 292 +83 54 145 +0 186 0 +0 318 0 +0 450 0 +0 582 0 +0 714 0 +0 846 0 +0 978 0 +0 1110 0 +0 1242 0 +0 1374 0 +0 1506 0 +0 1639 0 +0 1771 0 +0 1903 0 +0 2035 0 +0 2167 0 +0 2299 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +506 0 448 +390 30 348 +168 168 168 +0 304 0 +0 440 0 +0 574 0 +0 708 0 +0 842 0 +0 975 0 +0 1108 0 +0 1240 0 +0 1373 0 +0 1505 0 +0 1638 0 +0 1770 0 +0 1902 0 +0 2035 0 +0 2167 0 +0 2299 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +693 0 597 +620 0 527 +499 143 414 +261 286 197 +0 426 0 +0 564 0 +0 701 0 +0 836 0 +0 971 0 +0 1105 0 +0 1238 0 +0 1371 0 +0 1504 0 +0 1637 0 +0 1769 0 +0 1902 0 +0 2034 0 +0 2167 0 +0 2299 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +862 0 741 +813 0 692 +738 107 616 +613 260 489 +362 407 233 +0 550 0 +0 691 0 +0 829 0 +0 965 0 +0 1100 0 +0 1235 0 +0 1369 0 +0 1502 0 +0 1636 0 +0 1768 0 +0 1901 0 +0 2034 0 +0 2167 0 +0 2299 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1020 0 882 +986 0 846 +936 54 794 +859 223 712 +731 381 573 +469 531 278 +0 677 0 +0 818 0 +0 958 0 +0 1095 0 +0 1231 0 +0 1366 0 +0 1500 0 +0 1634 0 +0 1767 0 +0 1900 0 +0 2033 0 +0 2165 0 +0 2299 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1171 0 1021 +1146 0 995 +1112 0 957 +1061 168 902 +983 343 815 +852 504 666 +582 657 331 +0 804 0 +0 947 0 +0 1087 0 +0 1225 0 +0 1362 0 +0 1497 0 +0 1632 0 +0 1765 0 +0 1899 0 +0 2032 0 +0 2165 0 +0 2297 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1316 0 1158 +1299 0 1139 +1274 0 1112 +1239 82 1073 +1188 286 1015 +1109 465 925 +976 630 766 +699 784 394 +0 933 0 +0 1077 0 +0 1217 0 +0 1356 0 +0 1493 0 +0 1628 0 +0 1763 0 +0 1897 0 +0 2031 0 +0 2163 0 +0 2297 0 +0 2429 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3355 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1458 0 1293 +1445 0 1279 +1428 0 1260 +1403 0 1232 +1368 197 1192 +1316 407 1133 +1236 590 1039 +1101 757 873 +819 913 466 +0 1062 0 +0 1207 0 +0 1348 0 +0 1487 0 +0 1624 0 +0 1760 0 +0 1895 0 +0 2029 0 +0 2163 0 +0 2295 0 +0 2429 0 +0 2561 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3355 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1597 0 1428 +1588 0 1418 +1575 0 1403 +1558 0 1383 +1533 42 1355 +1497 316 1315 +1445 531 1254 +1365 717 1157 +1229 885 985 +943 1042 548 +0 1192 0 +0 1338 0 +0 1479 0 +0 1618 0 +0 1756 0 +0 1892 0 +0 2027 0 +0 2161 0 +0 2295 0 +0 2427 0 +0 2561 0 +0 2693 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3355 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1735 0 1562 +1728 0 1555 +1718 0 1544 +1706 0 1529 +1688 0 1509 +1663 155 1480 +1628 438 1439 +1575 657 1377 +1494 845 1279 +1357 1014 1101 +1068 1172 638 +0 1323 0 +0 1469 0 +0 1611 0 +0 1750 0 +0 1887 0 +0 2023 0 +0 2159 0 +0 2293 0 +0 2427 0 +0 2559 0 +0 2693 0 +0 2825 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3355 0 +0 3487 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1871 0 1696 +1866 0 1690 +1859 0 1682 +1849 0 1672 +1837 0 1657 +1819 0 1636 +1794 273 1607 +1758 562 1566 +1706 784 1503 +1624 974 1403 +1487 1144 1221 +1195 1303 736 +0 1454 0 +0 1600 0 +0 1742 0 +0 1882 0 +0 2019 0 +0 2155 0 +0 2291 0 +0 2425 0 +0 2559 0 +0 2691 0 +0 2825 0 +0 2957 0 +0 3091 0 +0 3223 0 +0 3355 0 +0 3487 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +2006 0 1829 +2002 0 1825 +1997 0 1819 +1990 0 1811 +1981 0 1800 +1968 0 1785 +1950 0 1765 +1925 394 1736 +1889 689 1694 +1837 913 1630 +1755 1103 1529 +1617 1275 1344 +1323 1434 841 +0 1585 0 +0 1732 0 +0 1874 0 +0 2013 0 +0 2151 0 +0 2287 0 +0 2423 0 +0 2557 0 +0 2691 0 +0 2825 0 +0 2957 0 +0 3089 0 +0 3223 0 +0 3355 0 +0 3487 0 +0 3619 0 +0 3753 0 +0 3885 0 +0 4017 0 +2141 0 1962 +2137 0 1959 +2133 0 1955 +2129 0 1949 +2121 0 1941 +2113 0 1930 +2099 0 1915 +2081 0 1894 +2057 518 1865 +2020 816 1822 +1968 1042 1759 +1886 1234 1657 +1747 1405 1470 +1452 1565 952 +0 1717 0 +0 1863 0 +0 2006 0 +0 2145 0 +0 2283 0 +0 2419 0 +0 2555 0 +0 2689 0 +0 2823 0 +0 2957 0 +0 3089 0 +0 3223 0 +0 3355 0 +0 3487 0 +0 3619 0 +0 3751 0 +0 3885 0 +0 4017 0 +2273 0 2095 +2271 0 2093 +2269 0 2089 +2265 0 2085 +2259 0 2079 +2253 0 2071 +2243 0 2061 +2231 0 2045 +2213 89 2024 +2187 643 1995 +2151 945 1952 +2099 1172 1888 +2017 1364 1785 +1878 1537 1596 +1582 1697 1067 +0 1849 0 +0 1995 0 +0 2137 0 +0 2277 0 +0 2415 0 +0 2551 0 +0 2687 0 +0 2821 0 +0 2955 0 +0 3089 0 +0 3221 0 +0 3355 0 +0 3487 0 +0 3619 0 +0 3751 0 +0 3885 0 +0 4017 0 +2407 0 2227 +2405 0 2225 +2403 0 2223 +2401 0 2219 +2397 0 2215 +2391 0 2209 +2385 0 2201 +2375 0 2191 +2363 0 2175 +2345 205 2155 +2319 771 2125 +2283 1074 2083 +2231 1303 2018 +2149 1495 1915 +2010 1668 1725 +1713 1828 1186 +0 1980 0 +0 2127 0 +0 2269 0 +0 2409 0 +0 2547 0 +0 2683 0 +0 2819 0 +0 2953 0 +0 3087 0 +0 3221 0 +0 3353 0 +0 3487 0 +0 3619 0 +0 3751 0 +0 3883 0 +0 4017 0 +2541 0 2359 +2539 0 2359 +2537 0 2357 +2535 0 2355 +2533 0 2351 +2529 0 2347 +2523 0 2341 +2517 0 2333 +2507 0 2321 +2495 0 2307 +2477 324 2285 +2451 899 2257 +2415 1205 2213 +2363 1434 2149 +2281 1627 2045 +2141 1800 1854 +1843 1960 1308 +0 2113 0 +0 2259 0 +0 2401 0 +0 2541 0 +0 2679 0 +0 2815 0 +0 2951 0 +0 3085 0 +0 3219 0 +0 3353 0 +0 3485 0 +0 3619 0 +0 3751 0 +0 3883 0 +0 4015 0 +2673 0 2493 +2673 0 2491 +2671 0 2489 +2669 0 2489 +2667 0 2485 +2665 0 2483 +2661 0 2479 +2655 0 2473 +2649 0 2465 +2639 0 2453 +2627 0 2439 +2609 446 2417 +2583 1028 2387 +2547 1335 2345 +2495 1565 2279 +2413 1758 2175 +2273 1932 1984 +1975 2093 1433 +0 2245 0 +0 2391 0 +0 2533 0 +0 2673 0 +0 2811 0 +0 2947 0 +0 3083 0 +0 3217 0 +0 3351 0 +0 3485 0 +0 3617 0 +0 3751 0 +0 3883 0 +0 4015 0 +2805 0 2625 +2805 0 2623 +2805 0 2623 +2803 0 2621 +2801 0 2619 +2799 0 2617 +2797 0 2615 +2793 0 2609 +2787 0 2603 +2781 0 2595 +2771 0 2585 +2759 0 2569 +2741 570 2549 +2715 1158 2519 +2679 1467 2475 +2627 1697 2411 +2545 1890 2307 +2405 2063 2113 +2107 2223 1559 +0 2377 0 +0 2523 0 +0 2665 0 +0 2805 0 +0 2943 0 +0 3079 0 +0 3215 0 +0 3349 0 +0 3483 0 +0 3617 0 +0 3749 0 +0 3883 0 +0 4015 0 +2939 0 2757 +2937 0 2757 +2937 0 2755 +2937 0 2755 +2935 0 2753 +2933 0 2751 +2931 0 2749 +2929 0 2745 +2925 0 2741 +2919 0 2735 +2913 0 2727 +2903 0 2717 +2891 0 2701 +2873 697 2681 +2847 1289 2651 +2811 1598 2607 +2759 1828 2543 +2677 2022 2437 +2537 2195 2245 +2237 2355 1687 +0 2509 0 +0 2655 0 +0 2797 0 +0 2937 0 +0 3075 0 +0 3211 0 +0 3347 0 +0 3481 0 +0 3615 0 +0 3749 0 +0 3881 0 +0 4015 0 +3071 0 2889 +3071 0 2889 +3069 0 2889 +3069 0 2887 +3069 0 2887 +3067 0 2885 +3065 0 2883 +3063 0 2881 +3061 0 2877 +3057 0 2873 +3051 0 2867 +3045 0 2859 +3035 0 2849 +3023 0 2833 +3005 825 2811 +2979 1420 2783 +2943 1729 2739 +2891 1960 2673 +2809 2153 2569 +2669 2327 2377 +2369 2487 1816 +0 2641 0 +0 2787 0 +0 2929 0 +0 3069 0 +0 3207 0 +0 3343 0 +0 3479 0 +0 3613 0 +0 3747 0 +0 3881 0 +0 4015 0 +3203 0 3021 +3203 0 3021 +3203 0 3021 +3201 0 3021 +3201 0 3019 +3201 0 3019 +3199 0 3017 +3197 0 3015 +3195 0 3013 +3193 0 3009 +3189 0 3005 +3183 0 2999 +3177 0 2991 +3167 0 2981 +3155 0 2965 +3137 954 2943 +3111 1551 2913 +3075 1861 2871 +3023 2091 2805 +2941 2285 2701 +2801 2459 2507 +2501 2621 1945 +0 2773 0 +0 2919 0 +0 3061 0 +0 3201 0 +0 3339 0 +0 3477 0 +0 3611 0 +0 3745 0 +0 3879 0 +0 4013 0 +3335 0 3153 +3335 0 3153 +3335 0 3153 +3335 0 3153 +3333 0 3151 +3333 0 3151 +3333 0 3151 +3331 0 3149 +3329 0 3147 +3327 0 3145 +3325 0 3141 +3321 0 3137 +3315 0 3131 +3309 0 3123 +3299 0 3111 +3287 0 3097 +3269 1083 3075 +3243 1682 3045 +3207 1993 3003 +3155 2223 2937 +3073 2417 2833 +2933 2591 2639 +2633 2753 2075 +0 2905 0 +0 3051 0 +0 3193 0 +0 3333 0 +0 3471 0 +0 3609 0 +0 3743 0 +0 3877 0 +0 4011 0 +3467 0 3285 +3467 0 3285 +3467 0 3285 +3467 0 3285 +3467 0 3285 +3465 0 3283 +3465 0 3283 +3465 0 3283 +3463 0 3281 +3461 0 3279 +3459 0 3277 +3457 0 3273 +3453 0 3269 +3447 0 3263 +3441 0 3255 +3431 0 3243 +3419 0 3229 +3401 1213 3207 +3375 1814 3177 +3339 2125 3135 +3287 2355 3069 +3205 2549 2965 +3065 2723 2771 +2765 2885 2207 +0 3037 0 +0 3183 0 +0 3327 0 +0 3467 0 +0 3603 0 +0 3741 0 +0 3875 0 +0 4009 0 +3599 0 3417 +3599 0 3417 +3599 0 3417 +3599 0 3417 +3599 0 3417 +3599 0 3417 +3597 0 3417 +3597 0 3415 +3597 0 3415 +3595 0 3413 +3593 0 3411 +3591 0 3409 +3589 0 3405 +3585 0 3401 +3579 0 3395 +3573 0 3387 +3563 0 3377 +3551 0 3361 +3533 1344 3339 +3507 1946 3309 +3471 2257 3267 +3419 2487 3201 +3337 2681 3097 +3197 2855 2903 +2897 3017 2337 +0 3169 0 +0 3315 0 +0 3459 0 +0 3599 0 +0 3737 0 +0 3873 0 +0 4007 0 +3731 0 3549 +3731 0 3549 +3731 0 3549 +3731 0 3549 +3731 0 3549 +3731 0 3549 +3731 0 3549 +3731 0 3549 +3729 0 3547 +3729 0 3547 +3727 0 3545 +3725 0 3543 +3723 0 3541 +3721 0 3537 +3717 0 3533 +3711 0 3527 +3705 0 3519 +3695 0 3509 +3683 0 3493 +3665 1475 3471 +3639 2077 3441 +3603 2389 3399 +3551 2619 3333 +3469 2813 3229 +3329 2987 3035 +3029 3149 2469 +0 3301 0 +0 3447 0 +0 3591 0 +0 3731 0 +0 3869 0 +0 4005 0 +3863 0 3683 +3863 0 3683 +3863 0 3681 +3863 0 3681 +3863 0 3681 +3863 0 3681 +3863 0 3681 +3863 0 3681 +3863 0 3681 +3861 0 3679 +3861 0 3679 +3859 0 3677 +3857 0 3675 +3855 0 3673 +3853 0 3669 +3849 0 3665 +3845 0 3659 +3837 0 3651 +3827 0 3641 +3815 0 3625 +3797 1606 3603 +3771 2209 3573 +3735 2521 3531 +3683 2751 3465 +3601 2947 3361 +3461 3119 3167 +3161 3281 2601 +0 3433 0 +0 3579 0 +0 3723 0 +0 3863 0 +0 4001 0 +3997 0 3815 +3997 0 3815 +3995 0 3815 +3995 0 3815 +3995 0 3813 +3995 0 3813 +3995 0 3813 +3995 0 3813 +3995 0 3813 +3995 0 3813 +3993 0 3811 +3993 0 3811 +3991 0 3809 +3991 0 3807 +3987 0 3805 +3985 0 3801 +3981 0 3797 +3977 0 3791 +3969 0 3783 +3959 0 3773 +3947 0 3757 +3929 1738 3735 +3903 2341 3707 +3867 2653 3663 +3815 2883 3597 +3733 3079 3493 +3593 3251 3299 +3293 3413 2733 +0 3565 0 +0 3711 0 +0 3855 0 +0 3995 0 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3945 +4095 0 3945 +4095 0 3945 +4095 0 3945 +4095 0 3945 +4095 0 3943 +4095 0 3943 +4095 0 3941 +4095 0 3939 +4095 0 3937 +4095 0 3933 +4095 0 3929 +4095 0 3923 +4095 0 3915 +4091 0 3905 +4079 0 3889 +4061 1870 3869 +4035 2473 3839 +3999 2785 3795 +3947 3017 3729 +3865 3211 3625 +3725 3383 3431 +3425 3545 2863 +0 3697 0 +0 3843 0 +0 3987 0 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4077 +4095 0 4077 +4095 0 4077 +4095 0 4077 +4095 0 4077 +4095 0 4075 +4095 0 4075 +4095 0 4073 +4095 0 4071 +4095 0 4069 +4095 0 4065 +4095 0 4061 +4095 0 4055 +4095 0 4047 +4095 0 4037 +4095 0 4021 +4095 2002 4001 +4095 2605 3971 +4095 2917 3927 +4079 3149 3861 +3997 3343 3757 +3857 3515 3563 +3557 3677 2995 +0 3829 0 +0 3977 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 2133 4095 +4095 2737 4095 +4095 3049 4059 +4095 3281 3993 +4095 3475 3889 +3989 3649 3695 +3689 3809 3127 +0 3961 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 2265 4095 +4095 2869 4095 +4095 3181 4095 +4095 3413 4095 +4095 3607 4021 +4095 3781 3827 +3821 3941 3259 +73 0 245 +0 93 78 +0 216 0 +0 340 0 +0 467 0 +0 595 0 +0 724 0 +0 853 0 +0 984 0 +0 1114 0 +0 1245 0 +0 1377 0 +0 1508 0 +0 1640 0 +0 1772 0 +0 1904 0 +0 2035 0 +0 2167 0 +0 2299 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +324 0 378 +139 77 259 +0 203 27 +0 331 0 +0 460 0 +0 589 0 +0 719 0 +0 850 0 +0 981 0 +0 1112 0 +0 1244 0 +0 1376 0 +0 1507 0 +0 1639 0 +0 1771 0 +0 1903 0 +0 2035 0 +0 2167 0 +0 2299 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +528 0 510 +420 54 424 +215 186 277 +0 318 0 +0 450 0 +0 582 0 +0 714 0 +0 846 0 +0 978 0 +0 1110 0 +0 1242 0 +0 1374 0 +0 1506 0 +0 1639 0 +0 1771 0 +0 1903 0 +0 2035 0 +0 2167 0 +0 2299 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +708 0 642 +638 21 580 +522 162 481 +300 300 300 +0 437 0 +0 572 0 +0 707 0 +0 841 0 +0 974 0 +0 1107 0 +0 1240 0 +0 1373 0 +0 1505 0 +0 1638 0 +0 1770 0 +0 1902 0 +0 2035 0 +0 2167 0 +0 2299 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +873 0 775 +825 0 729 +752 127 659 +631 275 546 +393 418 329 +0 558 0 +0 696 0 +0 833 0 +0 968 0 +0 1103 0 +0 1237 0 +0 1370 0 +0 1503 0 +0 1636 0 +0 1769 0 +0 1902 0 +0 2034 0 +0 2167 0 +0 2299 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1028 0 907 +994 0 873 +945 77 824 +870 239 748 +745 392 621 +494 539 365 +0 683 0 +0 823 0 +0 961 0 +0 1097 0 +0 1233 0 +0 1367 0 +0 1501 0 +0 1635 0 +0 1768 0 +0 1901 0 +0 2033 0 +0 2165 0 +0 2299 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1176 0 1039 +1152 0 1014 +1118 0 979 +1068 186 926 +991 355 844 +863 513 705 +601 663 410 +0 809 0 +0 951 0 +0 1090 0 +0 1227 0 +0 1363 0 +0 1498 0 +0 1632 0 +0 1766 0 +0 1899 0 +0 2032 0 +0 2165 0 +0 2297 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1320 0 1171 +1303 0 1153 +1279 0 1127 +1244 103 1089 +1193 300 1034 +1115 475 948 +984 636 798 +714 789 463 +0 936 0 +0 1079 0 +0 1219 0 +0 1357 0 +0 1494 0 +0 1629 0 +0 1764 0 +0 1898 0 +0 2031 0 +0 2165 0 +0 2297 0 +0 2429 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1461 0 1304 +1448 0 1290 +1431 0 1271 +1406 0 1244 +1371 214 1205 +1320 418 1147 +1241 597 1057 +1108 762 898 +831 917 526 +0 1065 0 +0 1209 0 +0 1350 0 +0 1488 0 +0 1625 0 +0 1760 0 +0 1895 0 +0 2029 0 +0 2163 0 +0 2297 0 +0 2429 0 +0 2561 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3355 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1599 0 1436 +1590 0 1426 +1577 0 1411 +1560 0 1392 +1535 65 1364 +1500 329 1324 +1448 539 1265 +1368 722 1171 +1233 889 1005 +952 1045 598 +0 1194 0 +0 1339 0 +0 1480 0 +0 1619 0 +0 1756 0 +0 1892 0 +0 2027 0 +0 2161 0 +0 2295 0 +0 2427 0 +0 2561 0 +0 2693 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3355 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1736 0 1568 +1729 0 1560 +1720 0 1550 +1707 0 1535 +1690 0 1515 +1665 174 1487 +1630 448 1447 +1578 663 1386 +1497 849 1289 +1361 1017 1117 +1074 1174 680 +0 1325 0 +0 1470 0 +0 1611 0 +0 1751 0 +0 1888 0 +0 2024 0 +0 2159 0 +0 2293 0 +0 2427 0 +0 2559 0 +0 2693 0 +0 2825 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3355 0 +0 3487 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1872 0 1700 +1867 0 1694 +1860 0 1687 +1851 0 1676 +1838 0 1661 +1820 0 1641 +1795 287 1613 +1760 570 1571 +1707 789 1510 +1627 977 1411 +1489 1146 1233 +1200 1304 770 +0 1455 0 +0 1601 0 +0 1743 0 +0 1882 0 +0 2020 0 +0 2155 0 +0 2291 0 +0 2425 0 +0 2559 0 +0 2693 0 +0 2825 0 +0 2957 0 +0 3091 0 +0 3223 0 +0 3355 0 +0 3487 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +2007 0 1832 +2003 0 1828 +1998 0 1822 +1991 0 1814 +1982 0 1804 +1969 0 1789 +1951 0 1768 +1926 405 1740 +1890 694 1698 +1838 916 1635 +1757 1105 1535 +1619 1276 1354 +1327 1435 868 +0 1586 0 +0 1732 0 +0 1874 0 +0 2014 0 +0 2151 0 +0 2287 0 +0 2423 0 +0 2557 0 +0 2691 0 +0 2825 0 +0 2957 0 +0 3089 0 +0 3223 0 +0 3355 0 +0 3487 0 +0 3619 0 +0 3753 0 +0 3885 0 +0 4017 0 +2141 0 1964 +2137 0 1961 +2135 0 1957 +2129 0 1951 +2123 0 1943 +2113 0 1932 +2099 0 1918 +2083 6 1897 +2057 526 1868 +2021 821 1826 +1969 1045 1762 +1887 1235 1661 +1749 1407 1477 +1455 1566 973 +0 1718 0 +0 1864 0 +0 2006 0 +0 2145 0 +0 2283 0 +0 2419 0 +0 2555 0 +0 2689 0 +0 2823 0 +0 2957 0 +0 3089 0 +0 3223 0 +0 3355 0 +0 3487 0 +0 3619 0 +0 3751 0 +0 3885 0 +0 4017 0 +2275 0 2097 +2273 0 2095 +2269 0 2091 +2265 0 2087 +2261 0 2081 +2253 0 2073 +2245 0 2063 +2231 0 2047 +2213 111 2026 +2189 650 1997 +2153 948 1955 +2099 1174 1891 +2018 1366 1789 +1879 1538 1602 +1584 1697 1083 +0 1849 0 +0 1995 0 +0 2137 0 +0 2277 0 +0 2415 0 +0 2551 0 +0 2687 0 +0 2821 0 +0 2955 0 +0 3089 0 +0 3221 0 +0 3355 0 +0 3487 0 +0 3619 0 +0 3751 0 +0 3885 0 +0 4017 0 +2407 0 2229 +2405 0 2227 +2403 0 2225 +2401 0 2221 +2397 0 2217 +2393 0 2211 +2385 0 2203 +2375 0 2193 +2363 0 2177 +2345 221 2157 +2319 775 2127 +2285 1077 2085 +2231 1304 2020 +2149 1496 1917 +2010 1669 1729 +1714 1829 1199 +0 1981 0 +0 2127 0 +0 2269 0 +0 2409 0 +0 2547 0 +0 2683 0 +0 2819 0 +0 2953 0 +0 3087 0 +0 3221 0 +0 3353 0 +0 3487 0 +0 3619 0 +0 3751 0 +0 3883 0 +0 4017 0 +2541 0 2361 +2539 0 2359 +2537 0 2357 +2535 0 2355 +2533 0 2353 +2529 0 2347 +2523 0 2341 +2517 0 2333 +2507 0 2323 +2495 0 2307 +2477 337 2287 +2451 903 2257 +2415 1207 2215 +2363 1435 2151 +2281 1628 2047 +2141 1800 1857 +1845 1961 1318 +0 2113 0 +0 2259 0 +0 2401 0 +0 2541 0 +0 2679 0 +0 2815 0 +0 2951 0 +0 3085 0 +0 3219 0 +0 3353 0 +0 3485 0 +0 3619 0 +0 3751 0 +0 3883 0 +0 4015 0 +2673 0 2493 +2673 0 2493 +2671 0 2491 +2669 0 2489 +2667 0 2487 +2665 0 2483 +2661 0 2479 +2655 0 2473 +2649 0 2465 +2639 0 2453 +2627 0 2439 +2609 456 2417 +2583 1031 2389 +2547 1337 2345 +2495 1566 2281 +2413 1759 2177 +2273 1932 1986 +1976 2093 1440 +0 2245 0 +0 2391 0 +0 2533 0 +0 2673 0 +0 2811 0 +0 2947 0 +0 3083 0 +0 3217 0 +0 3351 0 +0 3485 0 +0 3617 0 +0 3751 0 +0 3883 0 +0 4015 0 +2805 0 2625 +2805 0 2625 +2805 0 2623 +2803 0 2623 +2801 0 2621 +2799 0 2617 +2797 0 2615 +2793 0 2611 +2787 0 2605 +2781 0 2597 +2771 0 2585 +2759 0 2571 +2741 578 2549 +2715 1160 2519 +2679 1468 2477 +2627 1697 2411 +2545 1891 2307 +2405 2063 2115 +2107 2225 1565 +0 2377 0 +0 2523 0 +0 2665 0 +0 2805 0 +0 2943 0 +0 3079 0 +0 3215 0 +0 3349 0 +0 3483 0 +0 3617 0 +0 3749 0 +0 3883 0 +0 4015 0 +2939 0 2757 +2937 0 2757 +2937 0 2755 +2937 0 2755 +2935 0 2753 +2933 0 2751 +2931 0 2749 +2929 0 2747 +2925 0 2741 +2919 0 2735 +2913 0 2727 +2903 0 2717 +2891 0 2701 +2873 703 2681 +2847 1290 2651 +2811 1599 2607 +2759 1829 2543 +2677 2022 2439 +2537 2195 2247 +2239 2357 1691 +0 2509 0 +0 2655 0 +0 2797 0 +0 2937 0 +0 3075 0 +0 3211 0 +0 3347 0 +0 3481 0 +0 3615 0 +0 3749 0 +0 3881 0 +0 4015 0 +3071 0 2889 +3071 0 2889 +3069 0 2889 +3069 0 2887 +3069 0 2887 +3067 0 2885 +3065 0 2883 +3063 0 2881 +3061 0 2877 +3057 0 2873 +3051 0 2867 +3045 0 2859 +3035 0 2849 +3023 0 2833 +3005 829 2813 +2979 1421 2783 +2943 1730 2739 +2891 1960 2675 +2809 2155 2569 +2669 2327 2377 +2369 2489 1819 +0 2641 0 +0 2787 0 +0 2929 0 +0 3069 0 +0 3207 0 +0 3343 0 +0 3479 0 +0 3613 0 +0 3747 0 +0 3881 0 +0 4015 0 +3203 0 3021 +3203 0 3021 +3203 0 3021 +3201 0 3021 +3201 0 3019 +3201 0 3019 +3199 0 3017 +3197 0 3015 +3195 0 3013 +3193 0 3009 +3189 0 3005 +3183 0 2999 +3177 0 2991 +3167 0 2981 +3155 0 2965 +3137 957 2945 +3111 1552 2915 +3075 1862 2871 +3023 2093 2807 +2941 2285 2701 +2801 2459 2509 +2501 2621 1948 +0 2773 0 +0 2919 0 +0 3061 0 +0 3201 0 +0 3339 0 +0 3477 0 +0 3611 0 +0 3745 0 +0 3879 0 +0 4013 0 +3335 0 3153 +3335 0 3153 +3335 0 3153 +3335 0 3153 +3333 0 3153 +3333 0 3151 +3333 0 3151 +3331 0 3149 +3329 0 3147 +3327 0 3145 +3325 0 3141 +3321 0 3137 +3315 0 3131 +3309 0 3123 +3299 0 3113 +3287 0 3097 +3269 1085 3075 +3243 1683 3047 +3207 1993 3003 +3155 2223 2937 +3073 2417 2833 +2933 2591 2639 +2633 2753 2077 +0 2905 0 +0 3051 0 +0 3195 0 +0 3333 0 +0 3471 0 +0 3609 0 +0 3743 0 +0 3877 0 +0 4011 0 +3467 0 3285 +3467 0 3285 +3467 0 3285 +3467 0 3285 +3467 0 3285 +3465 0 3285 +3465 0 3283 +3465 0 3283 +3463 0 3281 +3461 0 3279 +3459 0 3277 +3457 0 3273 +3453 0 3269 +3447 0 3263 +3441 0 3255 +3431 0 3245 +3419 0 3229 +3401 1215 3207 +3375 1815 3179 +3339 2125 3135 +3287 2355 3069 +3205 2549 2965 +3065 2723 2771 +2765 2885 2207 +0 3037 0 +0 3183 0 +0 3327 0 +0 3467 0 +0 3603 0 +0 3741 0 +0 3875 0 +0 4011 0 +3599 0 3417 +3599 0 3417 +3599 0 3417 +3599 0 3417 +3599 0 3417 +3599 0 3417 +3597 0 3417 +3597 0 3415 +3597 0 3415 +3595 0 3413 +3593 0 3411 +3591 0 3409 +3589 0 3405 +3585 0 3401 +3579 0 3395 +3573 0 3387 +3563 0 3377 +3551 0 3361 +3533 1345 3339 +3507 1946 3309 +3471 2257 3267 +3419 2487 3201 +3337 2681 3097 +3197 2855 2903 +2897 3017 2339 +0 3169 0 +0 3315 0 +0 3459 0 +0 3599 0 +0 3737 0 +0 3873 0 +0 4007 0 +3731 0 3551 +3731 0 3549 +3731 0 3549 +3731 0 3549 +3731 0 3549 +3731 0 3549 +3731 0 3549 +3731 0 3549 +3729 0 3547 +3729 0 3547 +3727 0 3545 +3725 0 3543 +3723 0 3541 +3721 0 3537 +3717 0 3533 +3713 0 3527 +3705 0 3519 +3695 0 3509 +3683 0 3493 +3665 1476 3471 +3639 2077 3441 +3603 2389 3399 +3551 2619 3333 +3469 2815 3229 +3329 2987 3035 +3029 3149 2469 +0 3301 0 +0 3447 0 +0 3591 0 +0 3731 0 +0 3869 0 +0 4005 0 +3863 0 3683 +3863 0 3683 +3863 0 3683 +3863 0 3681 +3863 0 3681 +3863 0 3681 +3863 0 3681 +3863 0 3681 +3863 0 3681 +3861 0 3679 +3861 0 3679 +3859 0 3677 +3857 0 3675 +3855 0 3673 +3853 0 3669 +3849 0 3665 +3845 0 3659 +3837 0 3651 +3827 0 3641 +3815 0 3625 +3797 1607 3603 +3771 2209 3575 +3735 2521 3531 +3683 2751 3465 +3601 2947 3361 +3461 3119 3167 +3161 3281 2601 +0 3433 0 +0 3579 0 +0 3723 0 +0 3863 0 +0 4001 0 +3997 0 3815 +3997 0 3815 +3995 0 3815 +3995 0 3815 +3995 0 3813 +3995 0 3813 +3995 0 3813 +3995 0 3813 +3995 0 3813 +3995 0 3813 +3993 0 3811 +3993 0 3811 +3991 0 3809 +3991 0 3807 +3987 0 3805 +3985 0 3801 +3981 0 3797 +3977 0 3791 +3969 0 3783 +3959 0 3773 +3947 0 3757 +3929 1739 3735 +3903 2341 3707 +3867 2653 3663 +3815 2883 3597 +3733 3079 3493 +3593 3251 3299 +3293 3413 2733 +0 3565 0 +0 3711 0 +0 3855 0 +0 3995 0 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3945 +4095 0 3945 +4095 0 3945 +4095 0 3945 +4095 0 3945 +4095 0 3943 +4095 0 3943 +4095 0 3941 +4095 0 3939 +4095 0 3937 +4095 0 3933 +4095 0 3929 +4095 0 3923 +4095 0 3915 +4091 0 3905 +4079 0 3889 +4061 1870 3869 +4035 2473 3839 +3999 2785 3795 +3947 3017 3729 +3865 3211 3625 +3725 3383 3431 +3425 3545 2865 +0 3697 0 +0 3843 0 +0 3987 0 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4077 +4095 0 4077 +4095 0 4077 +4095 0 4077 +4095 0 4077 +4095 0 4075 +4095 0 4075 +4095 0 4073 +4095 0 4071 +4095 0 4069 +4095 0 4065 +4095 0 4061 +4095 0 4055 +4095 0 4047 +4095 0 4037 +4095 0 4021 +4095 2002 4001 +4095 2605 3971 +4095 2917 3927 +4079 3149 3861 +3997 3343 3757 +3857 3515 3563 +3557 3677 2997 +0 3829 0 +0 3977 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 2133 4095 +4095 2737 4095 +4095 3049 4059 +4095 3281 3993 +4095 3475 3889 +3989 3649 3695 +3689 3809 3127 +0 3961 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 2265 4095 +4095 2869 4095 +4095 3181 4095 +4095 3413 4095 +4095 3607 4021 +4095 3781 3827 +3821 3941 3259 +148 10 366 +0 122 244 +0 237 2 +0 357 0 +0 479 0 +0 604 0 +0 731 0 +0 859 0 +0 988 0 +0 1117 0 +0 1247 0 +0 1378 0 +0 1509 0 +0 1641 0 +0 1772 0 +0 1904 0 +0 2036 0 +0 2167 0 +0 2299 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +369 0 471 +205 106 377 +0 225 210 +0 348 0 +0 473 0 +0 599 0 +0 727 0 +0 856 0 +0 985 0 +0 1115 0 +0 1246 0 +0 1377 0 +0 1509 0 +0 1640 0 +0 1772 0 +0 1904 0 +0 2036 0 +0 2167 0 +0 2299 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +558 0 582 +456 85 510 +271 209 391 +0 335 159 +0 463 0 +0 592 0 +0 721 0 +0 852 0 +0 982 0 +0 1113 0 +0 1245 0 +0 1376 0 +0 1508 0 +0 1640 0 +0 1771 0 +0 1903 0 +0 2035 0 +0 2167 0 +0 2299 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +728 0 697 +661 54 642 +552 186 556 +347 318 409 +0 450 82 +0 582 0 +0 714 0 +0 846 0 +0 978 0 +0 1110 0 +0 1242 0 +0 1374 0 +0 1506 0 +0 1639 0 +0 1771 0 +0 1903 0 +0 2035 0 +0 2167 0 +0 2299 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +887 0 816 +840 10 775 +770 153 712 +654 294 613 +432 432 432 +0 569 0 +0 704 0 +0 839 0 +0 973 0 +0 1106 0 +0 1239 0 +0 1372 0 +0 1505 0 +0 1637 0 +0 1770 0 +0 1902 0 +0 2034 0 +0 2167 0 +0 2299 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1037 0 938 +1005 0 907 +957 106 861 +884 259 792 +763 407 678 +525 550 461 +0 690 0 +0 829 0 +0 965 0 +0 1100 0 +0 1235 0 +0 1369 0 +0 1502 0 +0 1636 0 +0 1768 0 +0 1901 0 +0 2034 0 +0 2167 0 +0 2299 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1183 0 1063 +1160 0 1039 +1126 33 1005 +1077 209 956 +1002 371 880 +877 524 753 +626 672 498 +0 815 0 +0 955 0 +0 1093 0 +0 1229 0 +0 1365 0 +0 1499 0 +0 1633 0 +0 1767 0 +0 1900 0 +0 2033 0 +0 2165 0 +0 2297 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1325 0 1189 +1308 0 1171 +1284 0 1146 +1250 131 1110 +1200 318 1058 +1123 487 976 +995 645 837 +734 795 542 +0 941 0 +0 1082 0 +0 1222 0 +0 1359 0 +0 1495 0 +0 1630 0 +0 1764 0 +0 1898 0 +0 2031 0 +0 2165 0 +0 2297 0 +0 2429 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1465 0 1317 +1452 0 1304 +1435 0 1285 +1411 0 1259 +1376 236 1221 +1325 432 1166 +1247 607 1079 +1116 768 930 +846 921 595 +0 1068 0 +0 1211 0 +0 1351 0 +0 1489 0 +0 1626 0 +0 1761 0 +0 1896 0 +0 2030 0 +0 2163 0 +0 2297 0 +0 2429 0 +0 2561 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3355 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1602 0 1446 +1593 0 1436 +1580 0 1422 +1563 0 1403 +1538 95 1376 +1504 346 1337 +1452 550 1279 +1373 729 1189 +1240 894 1030 +963 1048 658 +0 1197 0 +0 1341 0 +0 1482 0 +0 1620 0 +0 1757 0 +0 1893 0 +0 2027 0 +0 2161 0 +0 2295 0 +0 2429 0 +0 2561 0 +0 2693 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3355 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1738 0 1575 +1732 0 1568 +1722 0 1558 +1710 0 1544 +1692 0 1524 +1667 198 1496 +1632 461 1456 +1580 671 1397 +1501 854 1303 +1366 1021 1137 +1083 1177 730 +0 1327 0 +0 1471 0 +0 1612 0 +0 1751 0 +0 1888 0 +0 2024 0 +0 2159 0 +0 2293 0 +0 2427 0 +0 2561 0 +0 2693 0 +0 2825 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3355 0 +0 3487 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1873 0 1706 +1868 0 1700 +1862 0 1692 +1852 0 1682 +1839 0 1668 +1822 0 1648 +1797 306 1619 +1762 580 1579 +1710 795 1518 +1629 981 1422 +1493 1149 1249 +1207 1307 812 +0 1457 0 +0 1602 0 +0 1744 0 +0 1883 0 +0 2020 0 +0 2155 0 +0 2291 0 +0 2425 0 +0 2559 0 +0 2693 0 +0 2825 0 +0 2957 0 +0 3091 0 +0 3223 0 +0 3355 0 +0 3487 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +2008 0 1837 +2004 0 1832 +1999 0 1827 +1992 0 1819 +1983 0 1808 +1970 0 1794 +1952 0 1773 +1927 419 1745 +1892 702 1703 +1840 921 1642 +1759 1109 1543 +1621 1278 1366 +1332 1437 902 +0 1587 0 +0 1733 0 +0 1875 0 +0 2014 0 +0 2151 0 +0 2287 0 +0 2423 0 +0 2557 0 +0 2691 0 +0 2825 0 +0 2957 0 +0 3089 0 +0 3223 0 +0 3355 0 +0 3487 0 +0 3619 0 +0 3753 0 +0 3885 0 +0 4017 0 +2141 0 1968 +2139 0 1964 +2135 0 1960 +2129 0 1954 +2123 0 1947 +2113 0 1936 +2101 0 1921 +2083 39 1901 +2059 537 1872 +2022 826 1830 +1970 1048 1767 +1889 1238 1667 +1751 1408 1486 +1459 1567 1000 +0 1718 0 +0 1864 0 +0 2006 0 +0 2145 0 +0 2283 0 +0 2419 0 +0 2555 0 +0 2689 0 +0 2823 0 +0 2957 0 +0 3089 0 +0 3223 0 +0 3355 0 +0 3487 0 +0 3619 0 +0 3751 0 +0 3885 0 +0 4017 0 +2275 0 2099 +2273 0 2097 +2271 0 2093 +2267 0 2089 +2261 0 2083 +2255 0 2075 +2245 0 2065 +2231 0 2049 +2215 138 2029 +2189 658 2000 +2153 953 1958 +2101 1177 1895 +2019 1367 1793 +1881 1539 1609 +1587 1698 1105 +0 1850 0 +0 1996 0 +0 2139 0 +0 2277 0 +0 2415 0 +0 2551 0 +0 2687 0 +0 2821 0 +0 2955 0 +0 3089 0 +0 3221 0 +0 3355 0 +0 3487 0 +0 3619 0 +0 3751 0 +0 3885 0 +0 4017 0 +2407 0 2231 +2407 0 2229 +2405 0 2227 +2401 0 2223 +2397 0 2219 +2393 0 2213 +2385 0 2205 +2377 0 2195 +2363 0 2179 +2345 243 2159 +2321 782 2129 +2285 1080 2087 +2233 1306 2023 +2151 1498 1921 +2012 1670 1734 +1716 1830 1216 +0 1981 0 +0 2127 0 +0 2269 0 +0 2409 0 +0 2547 0 +0 2683 0 +0 2819 0 +0 2953 0 +0 3087 0 +0 3221 0 +0 3353 0 +0 3487 0 +0 3619 0 +0 3751 0 +0 3883 0 +0 4017 0 +2541 0 2363 +2539 0 2361 +2539 0 2359 +2535 0 2357 +2533 0 2353 +2529 0 2349 +2525 0 2343 +2517 0 2335 +2507 0 2325 +2495 0 2309 +2477 353 2289 +2453 908 2259 +2417 1209 2217 +2363 1436 2153 +2281 1629 2049 +2143 1801 1861 +1846 1961 1331 +0 2113 0 +0 2259 0 +0 2401 0 +0 2541 0 +0 2679 0 +0 2815 0 +0 2951 0 +0 3085 0 +0 3219 0 +0 3353 0 +0 3485 0 +0 3619 0 +0 3751 0 +0 3883 0 +0 4015 0 +2673 0 2493 +2673 0 2493 +2671 0 2491 +2669 0 2489 +2667 0 2487 +2665 0 2485 +2661 0 2479 +2657 0 2475 +2649 0 2465 +2639 0 2455 +2627 0 2441 +2609 469 2419 +2583 1035 2389 +2547 1339 2347 +2495 1567 2283 +2413 1760 2179 +2273 1932 1989 +1977 2093 1450 +0 2245 0 +0 2391 0 +0 2533 0 +0 2673 0 +0 2811 0 +0 2947 0 +0 3083 0 +0 3217 0 +0 3351 0 +0 3485 0 +0 3617 0 +0 3751 0 +0 3883 0 +0 4015 0 +2805 0 2625 +2805 0 2625 +2805 0 2625 +2803 0 2623 +2801 0 2621 +2799 0 2619 +2797 0 2615 +2793 0 2611 +2787 0 2605 +2781 0 2597 +2771 0 2587 +2759 0 2571 +2741 588 2551 +2715 1163 2521 +2679 1469 2477 +2627 1698 2413 +2545 1891 2309 +2405 2065 2117 +2107 2225 1572 +0 2377 0 +0 2523 0 +0 2665 0 +0 2805 0 +0 2943 0 +0 3079 0 +0 3215 0 +0 3349 0 +0 3483 0 +0 3617 0 +0 3749 0 +0 3883 0 +0 4015 0 +2939 0 2757 +2937 0 2757 +2937 0 2757 +2937 0 2755 +2935 0 2755 +2933 0 2753 +2931 0 2749 +2929 0 2747 +2925 0 2743 +2919 0 2737 +2913 0 2729 +2903 0 2717 +2891 0 2703 +2873 710 2681 +2847 1292 2651 +2811 1600 2609 +2759 1829 2543 +2677 2023 2439 +2537 2195 2247 +2239 2357 1697 +0 2509 0 +0 2655 0 +0 2797 0 +0 2937 0 +0 3075 0 +0 3211 0 +0 3347 0 +0 3481 0 +0 3615 0 +0 3749 0 +0 3881 0 +0 4015 0 +3071 0 2889 +3071 0 2889 +3069 0 2889 +3069 0 2889 +3069 0 2887 +3067 0 2885 +3065 0 2883 +3063 0 2881 +3061 0 2879 +3057 0 2873 +3051 0 2869 +3045 0 2859 +3035 0 2849 +3023 0 2833 +3005 835 2813 +2979 1422 2783 +2943 1731 2739 +2891 1961 2675 +2809 2155 2571 +2669 2327 2379 +2371 2489 1823 +0 2641 0 +0 2787 0 +0 2929 0 +0 3069 0 +0 3207 0 +0 3343 0 +0 3479 0 +0 3613 0 +0 3747 0 +0 3881 0 +0 4015 0 +3203 0 3021 +3203 0 3021 +3203 0 3021 +3201 0 3021 +3201 0 3019 +3201 0 3019 +3199 0 3017 +3197 0 3015 +3195 0 3013 +3193 0 3011 +3189 0 3005 +3183 0 2999 +3177 0 2991 +3167 0 2981 +3155 0 2965 +3137 961 2945 +3111 1553 2915 +3075 1862 2871 +3023 2093 2807 +2941 2287 2703 +2801 2459 2509 +2501 2621 1951 +0 2773 0 +0 2919 0 +0 3061 0 +0 3201 0 +0 3339 0 +0 3477 0 +0 3611 0 +0 3745 0 +0 3879 0 +0 4013 0 +3335 0 3153 +3335 0 3153 +3335 0 3153 +3335 0 3153 +3333 0 3153 +3333 0 3151 +3333 0 3151 +3331 0 3149 +3329 0 3147 +3327 0 3145 +3325 0 3141 +3321 0 3137 +3315 0 3131 +3309 0 3123 +3299 0 3113 +3287 0 3097 +3269 1089 3077 +3243 1684 3047 +3207 1994 3003 +3155 2225 2939 +3073 2419 2833 +2933 2591 2641 +2633 2753 2081 +0 2905 0 +0 3051 0 +0 3195 0 +0 3333 0 +0 3471 0 +0 3609 0 +0 3743 0 +0 3877 0 +0 4011 0 +3467 0 3285 +3467 0 3285 +3467 0 3285 +3467 0 3285 +3467 0 3285 +3465 0 3285 +3465 0 3283 +3465 0 3283 +3463 0 3281 +3461 0 3279 +3459 0 3277 +3457 0 3273 +3453 0 3269 +3447 0 3263 +3441 0 3255 +3431 0 3245 +3419 0 3229 +3401 1218 3209 +3375 1815 3179 +3339 2125 3135 +3287 2357 3069 +3205 2551 2965 +3065 2723 2771 +2765 2885 2209 +0 3037 0 +0 3183 0 +0 3327 0 +0 3467 0 +0 3603 0 +0 3741 0 +0 3875 0 +0 4011 0 +3599 0 3419 +3599 0 3417 +3599 0 3417 +3599 0 3417 +3599 0 3417 +3599 0 3417 +3599 0 3417 +3597 0 3415 +3597 0 3415 +3595 0 3413 +3593 0 3411 +3591 0 3409 +3589 0 3405 +3585 0 3401 +3579 0 3395 +3573 0 3387 +3563 0 3377 +3551 0 3361 +3533 1347 3339 +3507 1947 3311 +3471 2257 3267 +3419 2487 3201 +3337 2683 3097 +3197 2855 2903 +2897 3017 2339 +0 3169 0 +0 3315 0 +0 3459 0 +0 3599 0 +0 3737 0 +0 3873 0 +0 4007 0 +3731 0 3551 +3731 0 3551 +3731 0 3549 +3731 0 3549 +3731 0 3549 +3731 0 3549 +3731 0 3549 +3731 0 3549 +3729 0 3547 +3729 0 3547 +3727 0 3545 +3725 0 3543 +3723 0 3541 +3721 0 3537 +3717 0 3533 +3713 0 3527 +3705 0 3519 +3695 0 3509 +3683 0 3493 +3665 1478 3471 +3639 2079 3443 +3603 2389 3399 +3551 2619 3333 +3469 2815 3229 +3329 2987 3035 +3029 3149 2471 +0 3301 0 +0 3447 0 +0 3591 0 +0 3731 0 +0 3869 0 +0 4005 0 +3863 0 3683 +3863 0 3683 +3863 0 3683 +3863 0 3681 +3863 0 3681 +3863 0 3681 +3863 0 3681 +3863 0 3681 +3863 0 3681 +3861 0 3679 +3861 0 3679 +3859 0 3677 +3857 0 3675 +3855 0 3673 +3853 0 3669 +3849 0 3665 +3845 0 3659 +3837 0 3651 +3827 0 3641 +3815 0 3625 +3797 1608 3603 +3771 2211 3575 +3735 2521 3531 +3683 2751 3465 +3601 2947 3361 +3461 3119 3167 +3161 3281 2601 +0 3433 0 +0 3579 0 +0 3723 0 +0 3863 0 +0 4001 0 +3997 0 3815 +3997 0 3815 +3995 0 3815 +3995 0 3815 +3995 0 3815 +3995 0 3813 +3995 0 3813 +3995 0 3813 +3995 0 3813 +3995 0 3813 +3993 0 3811 +3993 0 3811 +3991 0 3809 +3991 0 3807 +3987 0 3805 +3985 0 3801 +3981 0 3797 +3977 0 3791 +3969 0 3783 +3959 0 3773 +3947 0 3757 +3929 1739 3737 +3903 2341 3707 +3867 2653 3663 +3815 2885 3597 +3733 3079 3493 +3593 3251 3299 +3293 3413 2733 +0 3565 0 +0 3711 0 +0 3855 0 +0 3995 0 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3945 +4095 0 3945 +4095 0 3945 +4095 0 3945 +4095 0 3945 +4095 0 3943 +4095 0 3943 +4095 0 3941 +4095 0 3939 +4095 0 3937 +4095 0 3933 +4095 0 3929 +4095 0 3923 +4095 0 3915 +4091 0 3905 +4079 0 3889 +4061 1871 3869 +4035 2473 3839 +3999 2785 3795 +3947 3017 3729 +3865 3211 3625 +3725 3383 3431 +3425 3545 2865 +0 3697 0 +0 3843 0 +0 3987 0 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4077 +4095 0 4077 +4095 0 4077 +4095 0 4077 +4095 0 4075 +4095 0 4075 +4095 0 4073 +4095 0 4071 +4095 0 4069 +4095 0 4065 +4095 0 4061 +4095 0 4055 +4095 0 4047 +4095 0 4037 +4095 0 4021 +4095 2002 4001 +4095 2605 3971 +4095 2917 3927 +4079 3149 3861 +3997 3343 3757 +3857 3515 3563 +3557 3677 2997 +0 3829 0 +0 3977 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 2133 4095 +4095 2737 4095 +4095 3049 4059 +4095 3281 3993 +4095 3475 3889 +3989 3649 3695 +3689 3809 3129 +0 3961 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 2265 4095 +4095 2869 4095 +4095 3181 4095 +4095 3413 4095 +4095 3607 4021 +4095 3781 3827 +3821 3941 3261 +232 55 490 +0 157 400 +0 265 243 +0 378 0 +0 496 0 +0 617 0 +0 740 0 +0 866 0 +0 993 0 +0 1121 0 +0 1251 0 +0 1381 0 +0 1511 0 +0 1642 0 +0 1773 0 +0 1905 0 +0 2036 0 +0 2169 0 +0 2301 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +422 37 572 +280 142 498 +0 254 376 +0 369 134 +0 489 0 +0 611 0 +0 736 0 +0 863 0 +0 991 0 +0 1120 0 +0 1249 0 +0 1380 0 +0 1510 0 +0 1642 0 +0 1773 0 +0 1904 0 +0 2036 0 +0 2167 0 +0 2299 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +594 12 663 +501 123 603 +337 238 509 +0 358 342 +0 480 0 +0 605 0 +0 731 0 +0 859 0 +0 988 0 +0 1117 0 +0 1248 0 +0 1378 0 +0 1509 0 +0 1641 0 +0 1772 0 +0 1904 0 +0 2036 0 +0 2167 0 +0 2299 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +753 0 761 +690 95 714 +588 217 642 +403 341 523 +0 467 291 +0 595 0 +0 724 0 +0 853 0 +0 984 0 +0 1114 0 +0 1245 0 +0 1377 0 +0 1508 0 +0 1640 0 +0 1772 0 +0 1904 0 +0 2035 0 +0 2167 0 +0 2299 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +905 0 866 +860 54 829 +793 186 774 +684 318 689 +479 450 541 +0 582 214 +0 714 0 +0 846 0 +0 978 0 +0 1110 0 +0 1242 0 +0 1374 0 +0 1506 0 +0 1639 0 +0 1771 0 +0 1903 0 +0 2035 0 +0 2167 0 +0 2299 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1050 0 977 +1019 0 948 +972 142 907 +902 286 844 +786 426 745 +564 564 564 +0 701 84 +0 836 0 +0 971 0 +0 1105 0 +0 1238 0 +0 1371 0 +0 1504 0 +0 1637 0 +0 1769 0 +0 1902 0 +0 2034 0 +0 2167 0 +0 2299 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1193 0 1093 +1170 0 1070 +1137 76 1039 +1089 238 993 +1016 392 924 +895 539 810 +658 682 593 +0 823 0 +0 961 0 +0 1097 0 +0 1232 0 +0 1367 0 +0 1501 0 +0 1635 0 +0 1768 0 +0 1901 0 +0 2033 0 +0 2165 0 +0 2299 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1332 0 1212 +1315 0 1195 +1292 0 1171 +1258 165 1137 +1209 341 1088 +1134 503 1012 +1009 656 885 +758 804 630 +0 947 0 +0 1087 0 +0 1225 0 +0 1361 0 +0 1497 0 +0 1631 0 +0 1765 0 +0 1899 0 +0 2032 0 +0 2165 0 +0 2297 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1470 0 1334 +1457 0 1321 +1440 0 1303 +1416 46 1278 +1382 263 1243 +1332 450 1190 +1255 619 1108 +1127 777 970 +866 928 674 +0 1073 0 +0 1215 0 +0 1354 0 +0 1491 0 +0 1627 0 +0 1762 0 +0 1896 0 +0 2030 0 +0 2163 0 +0 2297 0 +0 2429 0 +0 2561 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3355 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1606 0 1459 +1597 0 1449 +1584 0 1436 +1567 0 1417 +1543 132 1391 +1508 368 1354 +1458 564 1298 +1379 739 1212 +1248 900 1062 +978 1053 727 +0 1200 0 +0 1343 0 +0 1484 0 +0 1622 0 +0 1758 0 +0 1893 0 +0 2028 0 +0 2161 0 +0 2295 0 +0 2429 0 +0 2561 0 +0 2693 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3355 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1741 0 1585 +1734 0 1578 +1725 0 1568 +1713 0 1554 +1695 0 1535 +1671 227 1508 +1636 478 1469 +1584 682 1412 +1505 861 1321 +1372 1026 1162 +1095 1181 790 +0 1329 0 +0 1473 0 +0 1614 0 +0 1752 0 +0 1889 0 +0 2025 0 +0 2159 0 +0 2293 0 +0 2427 0 +0 2561 0 +0 2693 0 +0 2825 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3355 0 +0 3487 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1876 0 1713 +1871 0 1708 +1864 0 1700 +1854 0 1690 +1842 0 1676 +1824 0 1656 +1799 330 1628 +1764 593 1589 +1713 803 1529 +1633 986 1435 +1498 1153 1269 +1216 1309 862 +0 1459 0 +0 1603 0 +0 1745 0 +0 1883 0 +0 2021 0 +0 2157 0 +0 2291 0 +0 2425 0 +0 2559 0 +0 2693 0 +0 2825 0 +0 2957 0 +0 3091 0 +0 3223 0 +0 3355 0 +0 3487 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +2009 0 1842 +2006 0 1838 +2001 0 1832 +1994 0 1825 +1984 0 1814 +1972 0 1800 +1954 0 1780 +1929 438 1752 +1894 712 1711 +1842 927 1650 +1761 1113 1554 +1625 1281 1381 +1339 1439 944 +0 1589 0 +0 1734 0 +0 1876 0 +0 2015 0 +0 2153 0 +0 2289 0 +0 2423 0 +0 2557 0 +0 2691 0 +0 2825 0 +0 2957 0 +0 3091 0 +0 3223 0 +0 3355 0 +0 3487 0 +0 3619 0 +0 3753 0 +0 3885 0 +0 4017 0 +2143 0 1972 +2139 0 1969 +2137 0 1964 +2131 0 1959 +2125 0 1951 +2115 0 1940 +2103 0 1926 +2085 81 1905 +2059 551 1877 +2024 834 1836 +1972 1053 1774 +1891 1241 1675 +1754 1410 1498 +1464 1569 1034 +0 1720 0 +0 1865 0 +0 2007 0 +0 2147 0 +0 2283 0 +0 2419 0 +0 2555 0 +0 2689 0 +0 2823 0 +0 2957 0 +0 3089 0 +0 3223 0 +0 3355 0 +0 3487 0 +0 3619 0 +0 3751 0 +0 3885 0 +0 4017 0 +2275 0 2103 +2273 0 2099 +2271 0 2097 +2267 0 2093 +2263 0 2087 +2255 0 2079 +2245 0 2067 +2233 0 2053 +2215 172 2033 +2191 669 2004 +2155 959 1962 +2103 1180 1899 +2021 1370 1799 +1883 1540 1618 +1591 1699 1132 +0 1851 0 +0 1996 0 +0 2139 0 +0 2279 0 +0 2415 0 +0 2551 0 +0 2687 0 +0 2821 0 +0 2955 0 +0 3089 0 +0 3221 0 +0 3355 0 +0 3487 0 +0 3619 0 +0 3751 0 +0 3885 0 +0 4017 0 +2409 0 2233 +2407 0 2231 +2405 0 2229 +2403 0 2225 +2399 0 2221 +2393 0 2215 +2387 0 2207 +2377 0 2197 +2365 0 2181 +2347 270 2161 +2321 790 2133 +2285 1085 2089 +2233 1309 2027 +2151 1500 1925 +2013 1671 1741 +1719 1830 1237 +0 1982 0 +0 2127 0 +0 2271 0 +0 2409 0 +0 2547 0 +0 2683 0 +0 2819 0 +0 2953 0 +0 3087 0 +0 3221 0 +0 3353 0 +0 3487 0 +0 3619 0 +0 3751 0 +0 3883 0 +0 4017 0 +2541 0 2363 +2541 0 2363 +2539 0 2361 +2537 0 2359 +2533 0 2355 +2529 0 2351 +2525 0 2345 +2517 0 2337 +2509 0 2327 +2495 0 2311 +2477 375 2291 +2453 914 2261 +2417 1212 2219 +2365 1438 2155 +2283 1630 2053 +2143 1802 1866 +1849 1962 1348 +0 2113 0 +0 2259 0 +0 2403 0 +0 2541 0 +0 2679 0 +0 2815 0 +0 2951 0 +0 3085 0 +0 3219 0 +0 3353 0 +0 3485 0 +0 3619 0 +0 3751 0 +0 3883 0 +0 4015 0 +2673 0 2495 +2673 0 2495 +2671 0 2493 +2671 0 2491 +2669 0 2489 +2665 0 2485 +2661 0 2481 +2657 0 2475 +2649 0 2467 +2641 0 2457 +2627 0 2441 +2609 485 2421 +2585 1039 2391 +2549 1341 2349 +2495 1569 2285 +2413 1761 2181 +2275 1933 1993 +1978 2093 1463 +0 2245 0 +0 2391 0 +0 2533 0 +0 2673 0 +0 2811 0 +0 2947 0 +0 3083 0 +0 3217 0 +0 3351 0 +0 3485 0 +0 3617 0 +0 3751 0 +0 3883 0 +0 4015 0 +2807 0 2627 +2805 0 2627 +2805 0 2625 +2803 0 2623 +2801 0 2623 +2799 0 2619 +2797 0 2617 +2793 0 2613 +2789 0 2607 +2781 0 2599 +2771 0 2587 +2759 0 2573 +2741 601 2551 +2715 1167 2521 +2681 1471 2479 +2627 1699 2415 +2545 1892 2311 +2405 2065 2121 +2109 2225 1582 +0 2377 0 +0 2523 0 +0 2665 0 +0 2805 0 +0 2943 0 +0 3079 0 +0 3215 0 +0 3349 0 +0 3483 0 +0 3617 0 +0 3749 0 +0 3883 0 +0 4015 0 +2939 0 2759 +2939 0 2759 +2937 0 2757 +2937 0 2757 +2935 0 2755 +2933 0 2753 +2931 0 2751 +2929 0 2747 +2925 0 2743 +2919 0 2737 +2913 0 2729 +2903 0 2719 +2891 0 2703 +2873 720 2683 +2847 1295 2653 +2811 1601 2609 +2759 1830 2545 +2677 2023 2441 +2537 2197 2251 +2239 2357 1705 +0 2509 0 +0 2655 0 +0 2797 0 +0 2937 0 +0 3075 0 +0 3211 0 +0 3347 0 +0 3481 0 +0 3615 0 +0 3749 0 +0 3881 0 +0 4015 0 +3071 0 2891 +3071 0 2889 +3069 0 2889 +3069 0 2889 +3069 0 2887 +3067 0 2887 +3065 0 2885 +3063 0 2883 +3061 0 2879 +3057 0 2875 +3051 0 2869 +3045 0 2861 +3035 0 2849 +3023 0 2835 +3005 842 2813 +2979 1425 2783 +2943 1732 2741 +2891 1961 2675 +2809 2155 2571 +2669 2327 2379 +2371 2489 1829 +0 2641 0 +0 2787 0 +0 2929 0 +0 3069 0 +0 3207 0 +0 3343 0 +0 3479 0 +0 3613 0 +0 3747 0 +0 3881 0 +0 4015 0 +3203 0 3023 +3203 0 3021 +3203 0 3021 +3201 0 3021 +3201 0 3021 +3201 0 3019 +3199 0 3017 +3197 0 3017 +3195 0 3013 +3193 0 3011 +3189 0 3007 +3183 0 3001 +3177 0 2993 +3167 0 2981 +3155 0 2965 +3137 967 2945 +3111 1555 2915 +3075 1863 2873 +3023 2093 2807 +2941 2287 2703 +2801 2459 2511 +2503 2621 1956 +0 2773 0 +0 2919 0 +0 3063 0 +0 3201 0 +0 3339 0 +0 3477 0 +0 3611 0 +0 3745 0 +0 3879 0 +0 4013 0 +3335 0 3155 +3335 0 3153 +3335 0 3153 +3335 0 3153 +3333 0 3153 +3333 0 3151 +3333 0 3151 +3331 0 3149 +3329 0 3147 +3327 0 3145 +3325 0 3143 +3321 0 3137 +3315 0 3131 +3309 0 3123 +3299 0 3113 +3287 0 3097 +3269 1093 3077 +3243 1685 3047 +3207 1994 3003 +3155 2225 2939 +3073 2419 2835 +2933 2591 2641 +2635 2753 2083 +0 2905 0 +0 3051 0 +0 3195 0 +0 3333 0 +0 3471 0 +0 3609 0 +0 3743 0 +0 3877 0 +0 4011 0 +3467 0 3287 +3467 0 3287 +3467 0 3285 +3467 0 3285 +3467 0 3285 +3465 0 3285 +3465 0 3283 +3465 0 3283 +3463 0 3281 +3461 0 3279 +3459 0 3277 +3457 0 3273 +3453 0 3269 +3447 0 3263 +3441 0 3255 +3431 0 3245 +3419 0 3229 +3401 1221 3209 +3375 1816 3179 +3339 2125 3135 +3287 2357 3071 +3205 2551 2965 +3065 2723 2773 +2765 2885 2213 +0 3037 0 +0 3183 0 +0 3327 0 +0 3467 0 +0 3603 0 +0 3741 0 +0 3875 0 +0 4011 0 +3599 0 3419 +3599 0 3419 +3599 0 3417 +3599 0 3417 +3599 0 3417 +3599 0 3417 +3599 0 3417 +3597 0 3415 +3597 0 3415 +3595 0 3413 +3593 0 3411 +3591 0 3409 +3589 0 3405 +3585 0 3401 +3581 0 3395 +3573 0 3387 +3563 0 3377 +3551 0 3361 +3533 1350 3341 +3507 1947 3311 +3471 2257 3267 +3419 2489 3203 +3337 2683 3097 +3197 2855 2903 +2897 3017 2341 +0 3169 0 +0 3315 0 +0 3459 0 +0 3599 0 +0 3737 0 +0 3873 0 +0 4007 0 +3731 0 3551 +3731 0 3551 +3731 0 3551 +3731 0 3549 +3731 0 3549 +3731 0 3549 +3731 0 3549 +3731 0 3549 +3729 0 3547 +3729 0 3547 +3727 0 3545 +3725 0 3543 +3723 0 3541 +3721 0 3537 +3717 0 3533 +3713 0 3527 +3705 0 3519 +3695 0 3509 +3683 0 3493 +3665 1479 3473 +3639 2079 3443 +3603 2389 3399 +3551 2621 3333 +3469 2815 3229 +3329 2987 3035 +3029 3149 2473 +0 3301 0 +0 3447 0 +0 3591 0 +0 3731 0 +0 3869 0 +0 4005 0 +3863 0 3683 +3863 0 3683 +3863 0 3683 +3863 0 3683 +3863 0 3681 +3863 0 3681 +3863 0 3681 +3863 0 3681 +3863 0 3681 +3861 0 3679 +3861 0 3679 +3859 0 3677 +3859 0 3675 +3855 0 3673 +3853 0 3669 +3849 0 3665 +3845 0 3659 +3837 0 3651 +3827 0 3641 +3815 0 3625 +3797 1610 3605 +3771 2211 3575 +3735 2521 3531 +3683 2753 3465 +3601 2947 3361 +3461 3119 3167 +3161 3281 2603 +0 3433 0 +0 3579 0 +0 3723 0 +0 3863 0 +0 4001 0 +3997 0 3815 +3997 0 3815 +3997 0 3815 +3995 0 3815 +3995 0 3815 +3995 0 3813 +3995 0 3813 +3995 0 3813 +3995 0 3813 +3995 0 3813 +3993 0 3811 +3993 0 3811 +3991 0 3809 +3991 0 3807 +3989 0 3805 +3985 0 3801 +3981 0 3797 +3977 0 3791 +3969 0 3783 +3959 0 3773 +3947 0 3757 +3929 1740 3737 +3903 2343 3707 +3867 2653 3663 +3815 2885 3597 +3733 3079 3493 +3593 3251 3299 +3293 3413 2733 +0 3565 0 +0 3711 0 +0 3855 0 +0 3995 0 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3945 +4095 0 3945 +4095 0 3945 +4095 0 3945 +4095 0 3945 +4095 0 3943 +4095 0 3943 +4095 0 3941 +4095 0 3939 +4095 0 3937 +4095 0 3933 +4095 0 3929 +4095 0 3923 +4095 0 3915 +4091 0 3905 +4079 0 3889 +4061 1872 3869 +4035 2475 3839 +3999 2785 3795 +3947 3017 3729 +3865 3211 3625 +3725 3383 3431 +3425 3545 2865 +0 3697 0 +0 3843 0 +0 3987 0 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4077 +4095 0 4077 +4095 0 4077 +4095 0 4077 +4095 0 4075 +4095 0 4075 +4095 0 4073 +4095 0 4071 +4095 0 4069 +4095 0 4065 +4095 0 4061 +4095 0 4055 +4095 0 4047 +4095 0 4037 +4095 0 4021 +4095 2003 4001 +4095 2607 3971 +4095 2917 3927 +4079 3149 3861 +3997 3343 3757 +3857 3517 3563 +3557 3677 2997 +0 3829 0 +0 3977 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 2135 4095 +4095 2737 4095 +4095 3049 4059 +4095 3281 3993 +4095 3475 3889 +3989 3649 3695 +3689 3809 3129 +0 3961 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 2267 4095 +4095 2869 4095 +4095 3181 4095 +4095 3413 4095 +4095 3607 4021 +4095 3781 3827 +3821 3941 3261 +325 108 616 +140 200 549 +0 299 442 +0 405 242 +0 517 0 +0 633 0 +0 753 0 +0 875 0 +0 1000 0 +0 1127 0 +0 1255 0 +0 1384 0 +0 1513 0 +0 1644 0 +0 1775 0 +0 1906 0 +0 2037 0 +0 2169 0 +0 2301 0 +0 2433 0 +0 2565 0 +0 2697 0 +0 2829 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +486 92 679 +364 187 622 +125 289 532 +0 397 375 +0 510 9 +0 628 0 +0 749 0 +0 872 0 +0 998 0 +0 1125 0 +0 1253 0 +0 1383 0 +0 1513 0 +0 1643 0 +0 1774 0 +0 1905 0 +0 2037 0 +0 2169 0 +0 2301 0 +0 2433 0 +0 2565 0 +0 2697 0 +0 2829 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +638 70 752 +554 169 704 +412 274 630 +103 386 508 +0 502 267 +0 621 0 +0 744 0 +0 868 0 +0 995 0 +0 1123 0 +0 1252 0 +0 1381 0 +0 1512 0 +0 1643 0 +0 1774 0 +0 1905 0 +0 2037 0 +0 2169 0 +0 2301 0 +0 2433 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +785 38 835 +726 144 795 +633 255 735 +469 370 641 +73 490 474 +0 612 63 +0 737 0 +0 863 0 +0 991 0 +0 1120 0 +0 1249 0 +0 1380 0 +0 1510 0 +0 1642 0 +0 1773 0 +0 1905 0 +0 2036 0 +0 2169 0 +0 2299 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +927 0 926 +885 108 893 +822 227 846 +720 349 774 +535 473 655 +29 599 424 +0 727 0 +0 856 0 +0 986 0 +0 1116 0 +0 1246 0 +0 1377 0 +0 1509 0 +0 1640 0 +0 1772 0 +0 1904 0 +0 2036 0 +0 2167 0 +0 2299 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1067 0 1024 +1036 55 998 +992 187 961 +925 318 906 +816 450 821 +611 582 673 +0 714 346 +0 846 0 +0 978 0 +0 1110 0 +0 1242 0 +0 1374 0 +0 1506 0 +0 1639 0 +0 1771 0 +0 1903 0 +0 2035 0 +0 2167 0 +0 2299 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1205 0 1129 +1182 0 1109 +1151 127 1080 +1104 274 1039 +1034 418 976 +919 558 877 +696 696 696 +0 833 216 +0 968 0 +0 1103 0 +0 1237 0 +0 1370 0 +0 1503 0 +0 1636 0 +0 1769 0 +0 1902 0 +0 2034 0 +0 2167 0 +0 2299 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1341 0 1241 +1325 0 1225 +1302 31 1202 +1269 208 1171 +1221 370 1125 +1148 524 1056 +1027 671 942 +790 814 725 +0 955 0 +0 1093 0 +0 1229 0 +0 1365 0 +0 1499 0 +0 1633 0 +0 1767 0 +0 1900 0 +0 2033 0 +0 2165 0 +0 2297 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1477 0 1356 +1464 0 1344 +1447 0 1327 +1424 100 1303 +1390 297 1269 +1341 473 1220 +1266 635 1144 +1141 788 1017 +891 936 762 +0 1079 0 +0 1219 0 +0 1357 0 +0 1494 0 +0 1629 0 +0 1764 0 +0 1897 0 +0 2031 0 +0 2165 0 +0 2297 0 +0 2429 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1611 0 1476 +1602 0 1466 +1590 0 1453 +1572 0 1436 +1549 178 1411 +1514 395 1375 +1464 582 1322 +1388 751 1240 +1259 909 1101 +998 1059 806 +0 1205 0 +0 1347 0 +0 1486 0 +0 1623 0 +0 1759 0 +0 1894 0 +0 2029 0 +0 2163 0 +0 2295 0 +0 2429 0 +0 2561 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3355 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1745 0 1598 +1738 0 1591 +1729 0 1581 +1716 0 1568 +1699 0 1549 +1675 264 1523 +1640 500 1486 +1590 696 1430 +1511 871 1344 +1380 1032 1194 +1110 1185 859 +0 1332 0 +0 1476 0 +0 1616 0 +0 1754 0 +0 1890 0 +0 2025 0 +0 2161 0 +0 2293 0 +0 2427 0 +0 2561 0 +0 2693 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3355 0 +0 3487 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1878 0 1723 +1873 0 1717 +1867 0 1710 +1857 0 1700 +1845 0 1686 +1827 0 1667 +1803 359 1640 +1768 610 1601 +1717 814 1544 +1637 994 1453 +1504 1158 1294 +1227 1313 922 +0 1461 0 +0 1605 0 +0 1746 0 +0 1884 0 +0 2021 0 +0 2157 0 +0 2291 0 +0 2425 0 +0 2559 0 +0 2693 0 +0 2825 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3355 0 +0 3487 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +2011 0 1849 +2008 0 1845 +2003 0 1840 +1996 0 1832 +1987 0 1822 +1974 0 1808 +1956 59 1788 +1932 462 1761 +1896 725 1721 +1845 936 1661 +1765 1118 1568 +1630 1285 1401 +1348 1441 994 +0 1591 0 +0 1735 0 +0 1877 0 +0 2016 0 +0 2153 0 +0 2289 0 +0 2423 0 +0 2557 0 +0 2691 0 +0 2825 0 +0 2957 0 +0 3091 0 +0 3223 0 +0 3355 0 +0 3487 0 +0 3619 0 +0 3753 0 +0 3885 0 +0 4017 0 +2145 0 1977 +2141 0 1974 +2137 0 1970 +2133 0 1964 +2125 0 1957 +2117 0 1946 +2103 0 1932 +2087 132 1912 +2061 570 1884 +2026 844 1843 +1974 1059 1782 +1893 1245 1686 +1757 1413 1513 +1471 1571 1076 +0 1721 0 +0 1866 0 +0 2008 0 +0 2147 0 +0 2285 0 +0 2421 0 +0 2555 0 +0 2689 0 +0 2823 0 +0 2957 0 +0 3089 0 +0 3223 0 +0 3355 0 +0 3487 0 +0 3619 0 +0 3753 0 +0 3885 0 +0 4017 0 +2277 0 2107 +2275 0 2103 +2273 0 2101 +2269 0 2097 +2263 0 2091 +2257 0 2083 +2247 0 2073 +2235 0 2057 +2217 213 2038 +2191 684 2009 +2157 966 1968 +2103 1185 1906 +2023 1373 1807 +1886 1543 1630 +1596 1701 1166 +0 1852 0 +0 1997 0 +0 2139 0 +0 2279 0 +0 2415 0 +0 2551 0 +0 2687 0 +0 2821 0 +0 2955 0 +0 3089 0 +0 3221 0 +0 3355 0 +0 3487 0 +0 3619 0 +0 3751 0 +0 3885 0 +0 4017 0 +2409 0 2235 +2407 0 2235 +2405 0 2231 +2403 0 2229 +2399 0 2225 +2395 0 2219 +2387 0 2211 +2377 0 2201 +2365 0 2185 +2347 304 2165 +2323 801 2135 +2287 1090 2095 +2235 1313 2032 +2153 1502 1932 +2015 1673 1750 +1723 1831 1264 +0 1983 0 +0 2129 0 +0 2271 0 +0 2411 0 +0 2547 0 +0 2683 0 +0 2819 0 +0 2953 0 +0 3087 0 +0 3221 0 +0 3353 0 +0 3487 0 +0 3619 0 +0 3751 0 +0 3883 0 +0 4017 0 +2541 0 2367 +2541 0 2365 +2539 0 2363 +2537 0 2361 +2535 0 2357 +2531 0 2353 +2525 0 2347 +2519 0 2339 +2509 0 2329 +2497 0 2313 +2479 402 2293 +2453 922 2265 +2417 1217 2223 +2365 1441 2159 +2283 1632 2057 +2145 1803 1873 +1851 1962 1369 +0 2115 0 +0 2261 0 +0 2403 0 +0 2543 0 +0 2679 0 +0 2815 0 +0 2951 0 +0 3085 0 +0 3219 0 +0 3353 0 +0 3485 0 +0 3619 0 +0 3751 0 +0 3883 0 +0 4017 0 +2675 0 2497 +2673 0 2497 +2673 0 2495 +2671 0 2493 +2669 0 2491 +2665 0 2487 +2661 0 2483 +2657 0 2477 +2649 0 2469 +2641 0 2459 +2627 0 2443 +2609 507 2423 +2585 1046 2393 +2549 1345 2351 +2497 1571 2287 +2415 1762 2185 +2275 1934 1998 +1981 2093 1480 +0 2245 0 +0 2391 0 +0 2535 0 +0 2673 0 +0 2811 0 +0 2947 0 +0 3083 0 +0 3217 0 +0 3351 0 +0 3485 0 +0 3617 0 +0 3751 0 +0 3883 0 +0 4015 0 +2807 0 2629 +2805 0 2627 +2805 0 2627 +2803 0 2625 +2803 0 2623 +2801 0 2621 +2797 0 2617 +2793 0 2613 +2789 0 2607 +2781 0 2599 +2773 0 2589 +2759 0 2573 +2741 617 2553 +2717 1172 2523 +2681 1473 2481 +2627 1701 2417 +2545 1893 2313 +2407 2065 2125 +2111 2225 1595 +0 2377 0 +0 2523 0 +0 2667 0 +0 2805 0 +0 2943 0 +0 3079 0 +0 3215 0 +0 3349 0 +0 3483 0 +0 3617 0 +0 3749 0 +0 3883 0 +0 4015 0 +2939 0 2759 +2939 0 2759 +2937 0 2759 +2937 0 2757 +2935 0 2755 +2935 0 2755 +2931 0 2751 +2929 0 2749 +2925 0 2745 +2921 0 2739 +2913 0 2731 +2903 0 2719 +2891 0 2705 +2873 733 2683 +2849 1299 2653 +2813 1603 2611 +2759 1831 2547 +2677 2024 2443 +2539 2197 2253 +2241 2357 1714 +0 2509 0 +0 2655 0 +0 2799 0 +0 2937 0 +0 3075 0 +0 3211 0 +0 3347 0 +0 3481 0 +0 3615 0 +0 3749 0 +0 3881 0 +0 4015 0 +3071 0 2891 +3071 0 2891 +3071 0 2891 +3069 0 2889 +3069 0 2889 +3067 0 2887 +3065 0 2885 +3063 0 2883 +3061 0 2879 +3057 0 2875 +3053 0 2869 +3045 0 2861 +3035 0 2851 +3023 0 2835 +3005 852 2815 +2979 1427 2785 +2943 1733 2741 +2891 1962 2677 +2809 2155 2573 +2669 2329 2383 +2371 2489 1837 +0 2641 0 +0 2787 0 +0 2931 0 +0 3069 0 +0 3207 0 +0 3345 0 +0 3479 0 +0 3613 0 +0 3747 0 +0 3881 0 +0 4015 0 +3203 0 3023 +3203 0 3023 +3203 0 3023 +3203 0 3021 +3201 0 3021 +3201 0 3019 +3199 0 3019 +3197 0 3017 +3195 0 3015 +3193 0 3011 +3189 0 3007 +3185 0 3001 +3177 0 2993 +3167 0 2981 +3155 0 2967 +3137 974 2945 +3111 1557 2915 +3075 1864 2873 +3023 2093 2809 +2941 2287 2703 +2801 2461 2513 +2503 2621 1961 +0 2773 0 +0 2919 0 +0 3063 0 +0 3201 0 +0 3339 0 +0 3477 0 +0 3611 0 +0 3745 0 +0 3879 0 +0 4013 0 +3335 0 3155 +3335 0 3155 +3335 0 3155 +3335 0 3153 +3335 0 3153 +3333 0 3153 +3333 0 3151 +3331 0 3151 +3329 0 3149 +3327 0 3145 +3325 0 3143 +3321 0 3139 +3317 0 3133 +3309 0 3125 +3299 0 3113 +3287 0 3099 +3269 1099 3077 +3243 1687 3047 +3207 1995 3005 +3155 2225 2939 +3073 2419 2835 +2933 2591 2643 +2635 2753 2087 +0 2905 0 +0 3051 0 +0 3195 0 +0 3335 0 +0 3471 0 +0 3609 0 +0 3743 0 +0 3877 0 +0 4011 0 +3467 0 3287 +3467 0 3287 +3467 0 3287 +3467 0 3285 +3467 0 3285 +3467 0 3285 +3465 0 3285 +3465 0 3283 +3463 0 3281 +3461 0 3279 +3459 0 3277 +3457 0 3275 +3453 0 3269 +3449 0 3263 +3441 0 3255 +3431 0 3245 +3419 0 3229 +3401 1225 3209 +3375 1817 3179 +3339 2127 3135 +3287 2357 3071 +3205 2551 2967 +3065 2723 2773 +2767 2885 2215 +0 3037 0 +0 3183 0 +0 3327 0 +0 3467 0 +0 3603 0 +0 3741 0 +0 3875 0 +0 4011 0 +3599 0 3419 +3599 0 3419 +3599 0 3419 +3599 0 3417 +3599 0 3417 +3599 0 3417 +3599 0 3417 +3597 0 3415 +3597 0 3415 +3595 0 3413 +3593 0 3411 +3591 0 3409 +3589 0 3407 +3585 0 3401 +3581 0 3395 +3573 0 3387 +3563 0 3377 +3551 0 3361 +3533 1353 3341 +3507 1948 3311 +3471 2257 3267 +3419 2489 3203 +3337 2683 3097 +3197 2855 2905 +2897 3017 2345 +0 3169 0 +0 3315 0 +0 3459 0 +0 3599 0 +0 3737 0 +0 3873 0 +0 4007 0 +3731 0 3551 +3731 0 3551 +3731 0 3551 +3731 0 3551 +3731 0 3549 +3731 0 3549 +3731 0 3549 +3731 0 3549 +3729 0 3547 +3729 0 3547 +3727 0 3545 +3725 0 3543 +3723 0 3541 +3721 0 3537 +3717 0 3533 +3713 0 3527 +3705 0 3519 +3695 0 3509 +3683 0 3493 +3665 1482 3473 +3639 2079 3443 +3603 2389 3399 +3551 2621 3335 +3469 2815 3229 +3329 2987 3035 +3029 3149 2473 +0 3301 0 +0 3447 0 +0 3591 0 +0 3731 0 +0 3869 0 +0 4005 0 +3865 0 3683 +3863 0 3683 +3863 0 3683 +3863 0 3683 +3863 0 3683 +3863 0 3681 +3863 0 3681 +3863 0 3681 +3863 0 3681 +3861 0 3679 +3861 0 3679 +3859 0 3677 +3859 0 3675 +3855 0 3673 +3853 0 3669 +3849 0 3665 +3845 0 3659 +3837 0 3651 +3827 0 3641 +3815 0 3625 +3797 1612 3605 +3771 2211 3575 +3735 2521 3531 +3683 2753 3467 +3601 2947 3361 +3461 3119 3167 +3161 3281 2605 +0 3433 0 +0 3579 0 +0 3723 0 +0 3863 0 +0 4001 0 +3997 0 3815 +3997 0 3815 +3997 0 3815 +3995 0 3815 +3995 0 3815 +3995 0 3815 +3995 0 3813 +3995 0 3813 +3995 0 3813 +3995 0 3813 +3993 0 3811 +3993 0 3811 +3991 0 3809 +3991 0 3807 +3989 0 3805 +3985 0 3801 +3981 0 3797 +3977 0 3791 +3969 0 3783 +3959 0 3773 +3947 0 3757 +3929 1742 3737 +3903 2343 3707 +3867 2653 3663 +3815 2885 3597 +3733 3079 3493 +3593 3251 3299 +3293 3413 2735 +0 3565 0 +0 3711 0 +0 3855 0 +0 3995 0 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3945 +4095 0 3945 +4095 0 3945 +4095 0 3945 +4095 0 3943 +4095 0 3943 +4095 0 3941 +4095 0 3939 +4095 0 3937 +4095 0 3933 +4095 0 3929 +4095 0 3923 +4095 0 3915 +4093 0 3905 +4079 0 3889 +4061 1873 3869 +4035 2475 3839 +4001 2785 3795 +3947 3017 3729 +3865 3211 3625 +3725 3383 3431 +3425 3545 2867 +0 3697 0 +0 3843 0 +0 3987 0 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4077 +4095 0 4077 +4095 0 4077 +4095 0 4077 +4095 0 4075 +4095 0 4075 +4095 0 4073 +4095 0 4071 +4095 0 4069 +4095 0 4067 +4095 0 4061 +4095 0 4055 +4095 0 4047 +4095 0 4037 +4095 0 4021 +4095 2004 4001 +4095 2607 3971 +4095 2917 3927 +4079 3149 3861 +3997 3343 3757 +3857 3517 3563 +3557 3677 2997 +0 3829 0 +0 3977 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 2135 4095 +4095 2739 4095 +4095 3049 4059 +4095 3281 3993 +4095 3475 3889 +3989 3649 3695 +3689 3809 3129 +0 3961 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 2267 4095 +4095 2871 4095 +4095 3181 4095 +4095 3413 4095 +4095 3607 4021 +4095 3781 3827 +3821 3941 3261 +425 171 743 +284 251 694 +0 341 618 +0 439 493 +0 543 240 +0 653 0 +0 769 0 +0 887 0 +0 1009 0 +0 1134 0 +0 1260 0 +0 1388 0 +0 1516 0 +0 1646 0 +0 1776 0 +0 1907 0 +0 2038 0 +0 2169 0 +0 2301 0 +0 2433 0 +0 2565 0 +0 2697 0 +0 2829 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +558 157 792 +457 240 748 +272 332 682 +0 431 574 +0 537 374 +0 649 0 +0 765 0 +0 885 0 +0 1007 0 +0 1132 0 +0 1259 0 +0 1387 0 +0 1516 0 +0 1646 0 +0 1776 0 +0 1907 0 +0 2038 0 +0 2169 0 +0 2301 0 +0 2433 0 +0 2565 0 +0 2697 0 +0 2829 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +691 138 850 +618 224 811 +496 319 754 +257 421 664 +0 529 507 +0 642 141 +0 760 0 +0 881 0 +0 1004 0 +0 1130 0 +0 1257 0 +0 1385 0 +0 1515 0 +0 1645 0 +0 1775 0 +0 1906 0 +0 2038 0 +0 2169 0 +0 2301 0 +0 2433 0 +0 2565 0 +0 2697 0 +0 2829 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +824 111 918 +770 202 885 +687 301 836 +544 407 762 +235 518 640 +0 634 399 +0 753 0 +0 876 0 +0 1001 0 +0 1127 0 +0 1255 0 +0 1384 0 +0 1514 0 +0 1644 0 +0 1775 0 +0 1906 0 +0 2037 0 +0 2169 0 +0 2301 0 +0 2433 0 +0 2565 0 +0 2697 0 +0 2829 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +956 72 995 +917 170 967 +858 276 927 +765 387 867 +601 502 773 +205 622 606 +0 744 196 +0 869 0 +0 995 0 +0 1123 0 +0 1252 0 +0 1382 0 +0 1512 0 +0 1643 0 +0 1774 0 +0 1905 0 +0 2037 0 +0 2169 0 +0 2301 0 +0 2433 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1088 14 1080 +1059 125 1058 +1017 240 1025 +954 359 978 +852 481 906 +667 605 787 +161 732 556 +0 859 0 +0 988 0 +0 1117 0 +0 1248 0 +0 1378 0 +0 1510 0 +0 1641 0 +0 1772 0 +0 1904 0 +0 2036 0 +0 2167 0 +0 2299 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1221 0 1175 +1199 55 1156 +1169 187 1130 +1124 319 1093 +1057 450 1038 +948 582 953 +743 714 805 +94 846 478 +0 978 0 +0 1110 0 +0 1242 0 +0 1374 0 +0 1506 0 +0 1639 0 +0 1771 0 +0 1903 0 +0 2035 0 +0 2167 0 +0 2299 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1353 0 1276 +1337 0 1262 +1315 105 1241 +1283 259 1212 +1236 406 1171 +1166 550 1108 +1050 690 1009 +828 828 828 +0 965 349 +0 1100 0 +0 1235 0 +0 1369 0 +0 1502 0 +0 1636 0 +0 1768 0 +0 1901 0 +0 2034 0 +0 2167 0 +0 2299 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1485 0 1384 +1473 0 1373 +1457 0 1357 +1434 164 1335 +1401 340 1303 +1353 502 1257 +1280 656 1188 +1159 803 1074 +922 947 858 +0 1087 83 +0 1225 0 +0 1361 0 +0 1497 0 +0 1631 0 +0 1765 0 +0 1899 0 +0 2032 0 +0 2165 0 +0 2297 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1618 0 1497 +1609 0 1488 +1596 0 1476 +1580 0 1459 +1556 232 1435 +1523 430 1402 +1473 605 1352 +1398 767 1276 +1273 921 1149 +1023 1068 894 +0 1211 0 +0 1351 0 +0 1489 0 +0 1626 0 +0 1761 0 +0 1896 0 +0 2030 0 +0 2163 0 +0 2297 0 +0 2429 0 +0 2561 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3355 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1750 0 1615 +1743 0 1608 +1734 0 1598 +1722 0 1586 +1705 31 1568 +1681 310 1543 +1647 527 1507 +1597 714 1454 +1520 883 1372 +1391 1041 1234 +1130 1192 938 +0 1337 0 +0 1479 0 +0 1618 0 +0 1755 0 +0 1891 0 +0 2026 0 +0 2161 0 +0 2295 0 +0 2427 0 +0 2561 0 +0 2693 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3355 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1882 0 1736 +1877 0 1730 +1870 0 1723 +1861 0 1713 +1849 0 1700 +1831 75 1681 +1807 397 1655 +1773 632 1618 +1722 828 1562 +1644 1003 1476 +1512 1164 1326 +1242 1317 992 +0 1465 0 +0 1608 0 +0 1748 0 +0 1886 0 +0 2022 0 +0 2157 0 +0 2293 0 +0 2427 0 +0 2559 0 +0 2693 0 +0 2825 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3355 0 +0 3487 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +2014 0 1859 +2010 0 1855 +2005 0 1850 +1999 0 1842 +1989 0 1832 +1977 0 1818 +1959 128 1799 +1935 492 1772 +1900 742 1733 +1849 946 1676 +1770 1125 1585 +1636 1290 1426 +1359 1445 1054 +0 1593 0 +0 1737 0 +0 1878 0 +0 2017 0 +0 2153 0 +0 2289 0 +0 2423 0 +0 2557 0 +0 2691 0 +0 2825 0 +0 2957 0 +0 3091 0 +0 3223 0 +0 3355 0 +0 3487 0 +0 3619 0 +0 3753 0 +0 3885 0 +0 4017 0 +2147 0 1985 +2143 0 1982 +2139 0 1977 +2135 0 1972 +2127 0 1964 +2119 0 1954 +2105 0 1940 +2089 191 1920 +2063 594 1893 +2029 857 1853 +1977 1067 1793 +1897 1250 1700 +1762 1417 1533 +1480 1573 1126 +0 1723 0 +0 1868 0 +0 2009 0 +0 2147 0 +0 2285 0 +0 2421 0 +0 2555 0 +0 2689 0 +0 2823 0 +0 2957 0 +0 3089 0 +0 3223 0 +0 3355 0 +0 3487 0 +0 3619 0 +0 3753 0 +0 3885 0 +0 4017 0 +2279 0 2111 +2277 0 2109 +2273 0 2107 +2269 0 2103 +2265 0 2097 +2257 0 2089 +2249 0 2079 +2235 0 2063 +2219 264 2044 +2193 702 2016 +2159 976 1975 +2107 1191 1914 +2026 1377 1818 +1889 1545 1645 +1603 1703 1208 +0 1853 0 +0 1998 0 +0 2139 0 +0 2279 0 +0 2417 0 +0 2553 0 +0 2687 0 +0 2821 0 +0 2955 0 +0 3089 0 +0 3221 0 +0 3355 0 +0 3487 0 +0 3619 0 +0 3751 0 +0 3885 0 +0 4017 0 +2411 0 2241 +2409 0 2239 +2407 0 2237 +2405 0 2233 +2401 0 2229 +2395 0 2223 +2389 0 2215 +2379 0 2205 +2367 0 2189 +2349 345 2169 +2323 816 2141 +2289 1098 2099 +2235 1317 2038 +2155 1505 1940 +2018 1675 1762 +1728 1833 1298 +0 1984 0 +0 2129 0 +0 2271 0 +0 2411 0 +0 2549 0 +0 2685 0 +0 2819 0 +0 2953 0 +0 3087 0 +0 3221 0 +0 3353 0 +0 3487 0 +0 3619 0 +0 3751 0 +0 3883 0 +0 4017 0 +2543 0 2369 +2541 0 2369 +2541 0 2367 +2537 0 2363 +2535 0 2361 +2531 0 2357 +2527 0 2351 +2519 0 2343 +2511 0 2333 +2497 0 2317 +2479 436 2297 +2455 933 2269 +2419 1223 2227 +2367 1445 2163 +2285 1634 2063 +2147 1805 1882 +1855 1964 1396 +0 2115 0 +0 2261 0 +0 2403 0 +0 2543 0 +0 2679 0 +0 2817 0 +0 2951 0 +0 3085 0 +0 3219 0 +0 3353 0 +0 3485 0 +0 3619 0 +0 3751 0 +0 3883 0 +0 4017 0 +2675 0 2499 +2675 0 2499 +2673 0 2497 +2671 0 2495 +2669 0 2493 +2667 0 2489 +2663 0 2485 +2657 0 2479 +2651 0 2471 +2641 0 2461 +2629 0 2447 +2611 534 2425 +2585 1054 2397 +2549 1349 2355 +2497 1573 2291 +2415 1764 2189 +2277 1935 2005 +1984 2095 1501 +0 2247 0 +0 2393 0 +0 2535 0 +0 2675 0 +0 2811 0 +0 2947 0 +0 3083 0 +0 3217 0 +0 3351 0 +0 3485 0 +0 3617 0 +0 3751 0 +0 3883 0 +0 4015 0 +2807 0 2629 +2807 0 2629 +2805 0 2629 +2805 0 2627 +2803 0 2625 +2801 0 2623 +2797 0 2619 +2795 0 2615 +2789 0 2609 +2783 0 2601 +2773 0 2591 +2759 0 2575 +2741 639 2555 +2717 1178 2525 +2681 1477 2483 +2629 1703 2419 +2547 1894 2317 +2407 2067 2131 +2113 2225 1612 +0 2377 0 +0 2523 0 +0 2667 0 +0 2807 0 +0 2943 0 +0 3079 0 +0 3215 0 +0 3349 0 +0 3483 0 +0 3617 0 +0 3749 0 +0 3883 0 +0 4015 0 +2939 0 2761 +2939 0 2761 +2939 0 2759 +2937 0 2759 +2935 0 2757 +2935 0 2755 +2933 0 2753 +2929 0 2749 +2925 0 2745 +2921 0 2739 +2913 0 2731 +2905 0 2721 +2891 0 2705 +2873 750 2685 +2849 1304 2655 +2813 1605 2613 +2759 1833 2549 +2679 2025 2445 +2539 2197 2257 +2243 2357 1727 +0 2509 0 +0 2655 0 +0 2799 0 +0 2937 0 +0 3075 0 +0 3213 0 +0 3347 0 +0 3481 0 +0 3615 0 +0 3749 0 +0 3881 0 +0 4015 0 +3071 0 2893 +3071 0 2891 +3071 0 2891 +3069 0 2891 +3069 0 2889 +3067 0 2889 +3067 0 2887 +3065 0 2883 +3061 0 2881 +3057 0 2877 +3053 0 2871 +3045 0 2863 +3037 0 2851 +3023 0 2837 +3005 865 2815 +2981 1431 2785 +2945 1735 2743 +2891 1963 2679 +2809 2157 2575 +2671 2329 2385 +2373 2489 1847 +0 2641 0 +0 2787 0 +0 2931 0 +0 3069 0 +0 3207 0 +0 3345 0 +0 3479 0 +0 3613 0 +0 3747 0 +0 3881 0 +0 4015 0 +3203 0 3023 +3203 0 3023 +3203 0 3023 +3203 0 3023 +3201 0 3021 +3201 0 3021 +3199 0 3019 +3199 0 3017 +3195 0 3015 +3193 0 3011 +3189 0 3007 +3185 0 3001 +3177 0 2993 +3167 0 2983 +3155 0 2967 +3137 984 2947 +3111 1559 2917 +3077 1865 2873 +3023 2095 2809 +2941 2287 2705 +2801 2461 2515 +2505 2621 1969 +0 2773 0 +0 2919 0 +0 3063 0 +0 3203 0 +0 3339 0 +0 3477 0 +0 3611 0 +0 3745 0 +0 3879 0 +0 4013 0 +3335 0 3155 +3335 0 3155 +3335 0 3155 +3335 0 3155 +3335 0 3153 +3333 0 3153 +3333 0 3151 +3331 0 3151 +3329 0 3149 +3327 0 3147 +3325 0 3143 +3321 0 3139 +3317 0 3133 +3309 0 3125 +3299 0 3113 +3287 0 3099 +3269 1106 3077 +3243 1689 3049 +3207 1996 3005 +3155 2225 2941 +3073 2419 2837 +2933 2593 2645 +2635 2753 2093 +0 2905 0 +0 3051 0 +0 3195 0 +0 3335 0 +0 3471 0 +0 3609 0 +0 3743 0 +0 3877 0 +0 4011 0 +3467 0 3287 +3467 0 3287 +3467 0 3287 +3467 0 3287 +3467 0 3285 +3467 0 3285 +3465 0 3285 +3465 0 3283 +3463 0 3283 +3461 0 3281 +3459 0 3277 +3457 0 3275 +3453 0 3271 +3449 0 3265 +3441 0 3257 +3431 0 3245 +3419 0 3231 +3401 1231 3209 +3375 1819 3179 +3339 2127 3137 +3287 2357 3071 +3205 2551 2967 +3065 2725 2775 +2767 2885 2219 +0 3037 0 +0 3183 0 +0 3327 0 +0 3467 0 +0 3603 0 +0 3741 0 +0 3875 0 +0 4011 0 +3599 0 3419 +3599 0 3419 +3599 0 3419 +3599 0 3419 +3599 0 3417 +3599 0 3417 +3599 0 3417 +3597 0 3417 +3597 0 3415 +3595 0 3413 +3593 0 3413 +3591 0 3409 +3589 0 3407 +3585 0 3403 +3581 0 3397 +3573 0 3389 +3563 0 3377 +3551 0 3361 +3533 1357 3341 +3507 1949 3311 +3471 2259 3267 +3419 2489 3203 +3337 2683 3099 +3197 2855 2905 +2899 3017 2347 +0 3169 0 +0 3315 0 +0 3459 0 +0 3599 0 +0 3737 0 +0 3873 0 +0 4007 0 +3731 0 3551 +3731 0 3551 +3731 0 3551 +3731 0 3551 +3731 0 3551 +3731 0 3549 +3731 0 3549 +3731 0 3549 +3729 0 3549 +3729 0 3547 +3727 0 3545 +3727 0 3543 +3723 0 3541 +3721 0 3539 +3717 0 3533 +3713 0 3527 +3705 0 3519 +3695 0 3509 +3683 0 3493 +3665 1485 3473 +3639 2081 3443 +3603 2391 3399 +3551 2621 3335 +3469 2815 3229 +3329 2987 3037 +3031 3149 2477 +0 3301 0 +0 3447 0 +0 3591 0 +0 3731 0 +0 3869 0 +0 4005 0 +3865 0 3683 +3863 0 3683 +3863 0 3683 +3863 0 3683 +3863 0 3683 +3863 0 3681 +3863 0 3681 +3863 0 3681 +3863 0 3681 +3861 0 3679 +3861 0 3679 +3859 0 3677 +3859 0 3675 +3855 0 3673 +3853 0 3671 +3849 0 3665 +3845 0 3659 +3837 0 3651 +3827 0 3641 +3815 0 3625 +3797 1614 3605 +3771 2211 3575 +3735 2521 3531 +3683 2753 3467 +3601 2947 3361 +3461 3119 3169 +3161 3281 2607 +0 3433 0 +0 3579 0 +0 3723 0 +0 3863 0 +0 4001 0 +3997 0 3815 +3997 0 3815 +3997 0 3815 +3995 0 3815 +3995 0 3815 +3995 0 3815 +3995 0 3813 +3995 0 3813 +3995 0 3813 +3995 0 3813 +3993 0 3811 +3993 0 3811 +3991 0 3809 +3991 0 3807 +3989 0 3805 +3985 0 3803 +3981 0 3797 +3977 0 3791 +3969 0 3783 +3959 0 3773 +3947 0 3757 +3929 1744 3737 +3903 2343 3707 +3867 2653 3663 +3815 2885 3599 +3733 3079 3493 +3593 3251 3299 +3293 3413 2737 +0 3565 0 +0 3711 0 +0 3855 0 +0 3995 0 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3945 +4095 0 3945 +4095 0 3945 +4095 0 3945 +4095 0 3943 +4095 0 3943 +4095 0 3941 +4095 0 3939 +4095 0 3937 +4095 0 3935 +4095 0 3929 +4095 0 3923 +4095 0 3915 +4093 0 3905 +4079 0 3889 +4061 1874 3869 +4037 2475 3839 +4001 2785 3795 +3947 3017 3731 +3865 3211 3625 +3725 3385 3431 +3425 3545 2867 +0 3697 0 +0 3843 0 +0 3987 0 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4077 +4095 0 4077 +4095 0 4077 +4095 0 4077 +4095 0 4075 +4095 0 4075 +4095 0 4073 +4095 0 4071 +4095 0 4069 +4095 0 4067 +4095 0 4061 +4095 0 4055 +4095 0 4047 +4095 0 4037 +4095 0 4021 +4095 2005 4001 +4095 2607 3971 +4095 2917 3927 +4079 3149 3863 +3997 3343 3757 +3857 3517 3563 +3557 3677 2999 +0 3829 0 +0 3977 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 2135 4095 +4095 2739 4095 +4095 3049 4059 +4095 3281 3995 +4095 3475 3889 +3989 3649 3695 +3689 3809 3129 +0 3961 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 2267 4095 +4095 2871 4095 +4095 3181 4095 +4095 3413 4095 +4095 3607 4021 +4095 3781 3827 +3821 3941 3261 +532 243 872 +424 313 835 +222 392 781 +0 480 697 +0 576 552 +0 680 237 +0 789 0 +0 903 0 +0 1022 0 +0 1143 0 +0 1267 0 +0 1393 0 +0 1520 0 +0 1649 0 +0 1779 0 +0 1909 0 +0 2039 0 +0 2171 0 +0 2301 0 +0 2433 0 +0 2565 0 +0 2697 0 +0 2829 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +640 231 909 +557 303 875 +416 384 826 +111 473 750 +0 571 625 +0 675 372 +0 786 0 +0 901 0 +0 1020 0 +0 1141 0 +0 1266 0 +0 1392 0 +0 1520 0 +0 1649 0 +0 1778 0 +0 1908 0 +0 2039 0 +0 2171 0 +0 2301 0 +0 2433 0 +0 2565 0 +0 2697 0 +0 2829 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +754 215 955 +690 289 924 +589 372 880 +404 464 814 +0 563 706 +0 669 506 +0 781 0 +0 897 0 +0 1017 0 +0 1139 0 +0 1264 0 +0 1391 0 +0 1519 0 +0 1648 0 +0 1778 0 +0 1908 0 +0 2039 0 +0 2169 0 +0 2301 0 +0 2433 0 +0 2565 0 +0 2697 0 +0 2829 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +871 192 1009 +823 270 982 +750 356 944 +628 451 886 +389 553 796 +0 661 639 +0 774 273 +0 892 0 +0 1013 0 +0 1136 0 +0 1262 0 +0 1389 0 +0 1518 0 +0 1647 0 +0 1777 0 +0 1908 0 +0 2038 0 +0 2169 0 +0 2301 0 +0 2433 0 +0 2565 0 +0 2697 0 +0 2829 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +992 160 1073 +956 243 1049 +902 334 1017 +819 433 968 +676 539 895 +367 650 772 +0 766 531 +0 885 0 +0 1008 0 +0 1132 0 +0 1259 0 +0 1387 0 +0 1516 0 +0 1646 0 +0 1776 0 +0 1907 0 +0 2038 0 +0 2169 0 +0 2301 0 +0 2433 0 +0 2565 0 +0 2697 0 +0 2829 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1116 113 1146 +1088 204 1126 +1049 302 1099 +990 408 1059 +897 519 1000 +733 634 905 +337 754 738 +0 876 328 +0 1001 0 +0 1127 0 +0 1255 0 +0 1384 0 +0 1514 0 +0 1644 0 +0 1775 0 +0 1906 0 +0 2037 0 +0 2169 0 +0 2301 0 +0 2433 0 +0 2565 0 +0 2697 0 +0 2829 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1241 42 1229 +1221 146 1212 +1191 257 1190 +1149 372 1157 +1086 491 1110 +985 613 1038 +799 737 919 +293 864 688 +0 991 0 +0 1120 0 +0 1250 0 +0 1380 0 +0 1511 0 +0 1642 0 +0 1773 0 +0 1905 0 +0 2036 0 +0 2169 0 +0 2299 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1368 0 1320 +1353 56 1307 +1331 187 1288 +1301 319 1262 +1256 451 1225 +1189 582 1170 +1080 714 1085 +875 846 937 +226 978 610 +0 1110 0 +0 1242 0 +0 1374 0 +0 1507 0 +0 1639 0 +0 1771 0 +0 1903 0 +0 2035 0 +0 2167 0 +0 2299 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1497 0 1419 +1485 0 1408 +1469 74 1394 +1447 237 1373 +1415 391 1345 +1369 538 1303 +1298 682 1240 +1183 822 1141 +960 960 960 +118 1097 481 +0 1232 0 +0 1367 0 +0 1501 0 +0 1634 0 +0 1768 0 +0 1901 0 +0 2033 0 +0 2165 0 +0 2299 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1626 0 1525 +1617 0 1516 +1606 0 1505 +1589 97 1489 +1566 296 1467 +1533 472 1435 +1485 634 1389 +1412 788 1320 +1291 935 1206 +1054 1078 990 +0 1219 216 +0 1357 0 +0 1493 0 +0 1629 0 +0 1763 0 +0 1897 0 +0 2031 0 +0 2165 0 +0 2297 0 +0 2429 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3355 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1756 0 1636 +1750 0 1630 +1741 0 1621 +1729 0 1608 +1712 126 1591 +1688 364 1568 +1655 562 1534 +1606 737 1484 +1530 899 1408 +1405 1052 1281 +1155 1200 1026 +0 1343 0 +0 1483 0 +0 1621 0 +0 1758 0 +0 1893 0 +0 2028 0 +0 2161 0 +0 2295 0 +0 2429 0 +0 2561 0 +0 2693 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3355 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1887 0 1752 +1882 0 1747 +1875 0 1740 +1866 0 1731 +1854 0 1718 +1837 163 1700 +1813 442 1675 +1779 659 1639 +1729 846 1586 +1652 1015 1505 +1523 1173 1366 +1262 1324 1070 +0 1469 0 +0 1611 0 +0 1750 0 +0 1888 0 +0 2024 0 +0 2159 0 +0 2293 0 +0 2427 0 +0 2559 0 +0 2693 0 +0 2825 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3355 0 +0 3487 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +2018 0 1872 +2014 0 1868 +2009 0 1862 +2002 0 1855 +1993 0 1845 +1981 0 1832 +1963 207 1813 +1939 529 1787 +1905 764 1750 +1854 960 1695 +1776 1135 1608 +1644 1297 1458 +1374 1450 1123 +0 1597 0 +0 1740 0 +0 1880 0 +0 2018 0 +0 2155 0 +0 2289 0 +0 2425 0 +0 2559 0 +0 2691 0 +0 2825 0 +0 2957 0 +0 3091 0 +0 3223 0 +0 3355 0 +0 3487 0 +0 3619 0 +0 3753 0 +0 3885 0 +0 4017 0 +2149 0 1994 +2147 0 1991 +2143 0 1987 +2137 0 1982 +2131 0 1974 +2121 0 1964 +2109 0 1950 +2091 260 1931 +2067 624 1904 +2032 874 1866 +1981 1078 1808 +1902 1258 1717 +1768 1422 1559 +1491 1577 1186 +0 1725 0 +0 1869 0 +0 2010 0 +0 2149 0 +0 2285 0 +0 2421 0 +0 2555 0 +0 2689 0 +0 2823 0 +0 2957 0 +0 3089 0 +0 3223 0 +0 3355 0 +0 3487 0 +0 3619 0 +0 3753 0 +0 3885 0 +0 4017 0 +2281 0 2119 +2279 0 2117 +2275 0 2113 +2271 0 2109 +2267 0 2105 +2261 0 2097 +2251 0 2087 +2239 0 2073 +2221 323 2053 +2195 726 2025 +2161 989 1985 +2109 1200 1926 +2029 1382 1832 +1894 1549 1665 +1612 1706 1258 +0 1855 0 +0 2000 0 +0 2141 0 +0 2279 0 +0 2417 0 +0 2553 0 +0 2687 0 +0 2821 0 +0 2955 0 +0 3089 0 +0 3221 0 +0 3355 0 +0 3487 0 +0 3619 0 +0 3751 0 +0 3885 0 +0 4017 0 +2413 0 2245 +2411 0 2243 +2409 0 2241 +2405 0 2239 +2401 0 2235 +2397 0 2229 +2391 0 2221 +2381 0 2211 +2367 0 2197 +2351 396 2177 +2325 834 2147 +2291 1108 2107 +2239 1323 2047 +2157 1509 1950 +2021 1678 1777 +1735 1835 1340 +0 1985 0 +0 2131 0 +0 2273 0 +0 2411 0 +0 2549 0 +0 2685 0 +0 2819 0 +0 2953 0 +0 3087 0 +0 3221 0 +0 3353 0 +0 3487 0 +0 3619 0 +0 3751 0 +0 3883 0 +0 4017 0 +2543 0 2373 +2543 0 2373 +2541 0 2371 +2539 0 2369 +2537 0 2365 +2533 0 2361 +2527 0 2355 +2521 0 2347 +2511 0 2337 +2499 0 2323 +2481 477 2301 +2455 948 2273 +2421 1230 2231 +2369 1449 2171 +2287 1637 2071 +2149 1807 1894 +1860 1965 1430 +0 2115 0 +0 2261 0 +0 2403 0 +0 2543 0 +0 2681 0 +0 2817 0 +0 2951 0 +0 3085 0 +0 3219 0 +0 3353 0 +0 3485 0 +0 3619 0 +0 3751 0 +0 3883 0 +0 4017 0 +2675 0 2503 +2675 0 2501 +2673 0 2501 +2673 0 2499 +2671 0 2497 +2667 0 2493 +2663 0 2489 +2659 0 2483 +2651 0 2475 +2643 0 2465 +2629 0 2449 +2611 568 2429 +2587 1065 2401 +2551 1355 2359 +2499 1577 2295 +2417 1766 2195 +2279 1937 2014 +1987 2095 1528 +0 2247 0 +0 2393 0 +0 2535 0 +0 2675 0 +0 2813 0 +0 2949 0 +0 3083 0 +0 3217 0 +0 3351 0 +0 3485 0 +0 3617 0 +0 3751 0 +0 3883 0 +0 4015 0 +2807 0 2633 +2807 0 2631 +2807 0 2631 +2805 0 2629 +2803 0 2627 +2801 0 2625 +2799 0 2621 +2795 0 2617 +2789 0 2611 +2783 0 2603 +2773 0 2593 +2761 0 2579 +2743 666 2557 +2717 1186 2529 +2681 1481 2487 +2629 1705 2423 +2547 1896 2321 +2409 2067 2137 +2115 2227 1633 +0 2379 0 +0 2525 0 +0 2667 0 +0 2807 0 +0 2943 0 +0 3081 0 +0 3215 0 +0 3349 0 +0 3483 0 +0 3617 0 +0 3749 0 +0 3883 0 +0 4015 0 +2939 0 2763 +2939 0 2763 +2939 0 2761 +2937 0 2761 +2937 0 2759 +2935 0 2757 +2933 0 2755 +2931 0 2751 +2927 0 2747 +2921 0 2741 +2915 0 2733 +2905 0 2723 +2891 0 2707 +2875 771 2687 +2849 1310 2657 +2813 1609 2615 +2761 1835 2551 +2679 2026 2449 +2541 2199 2263 +2245 2359 1744 +0 2509 0 +0 2657 0 +0 2799 0 +0 2939 0 +0 3075 0 +0 3213 0 +0 3347 0 +0 3481 0 +0 3615 0 +0 3749 0 +0 3881 0 +0 4015 0 +3071 0 2893 +3071 0 2893 +3071 0 2893 +3071 0 2891 +3069 0 2891 +3069 0 2889 +3067 0 2887 +3065 0 2885 +3061 0 2881 +3057 0 2877 +3053 0 2871 +3045 0 2863 +3037 0 2853 +3023 0 2837 +3005 882 2817 +2981 1436 2787 +2945 1738 2745 +2891 1965 2681 +2811 2157 2577 +2671 2329 2389 +2375 2489 1860 +0 2641 0 +0 2787 0 +0 2931 0 +0 3071 0 +0 3207 0 +0 3345 0 +0 3479 0 +0 3613 0 +0 3747 0 +0 3881 0 +0 4015 0 +3203 0 3025 +3203 0 3025 +3203 0 3023 +3203 0 3023 +3201 0 3023 +3201 0 3021 +3199 0 3021 +3199 0 3019 +3197 0 3015 +3193 0 3013 +3189 0 3009 +3185 0 3003 +3177 0 2995 +3169 0 2983 +3155 0 2969 +3137 997 2947 +3113 1563 2919 +3077 1867 2875 +3023 2095 2811 +2941 2289 2707 +2803 2461 2517 +2505 2621 1979 +0 2773 0 +0 2919 0 +0 3063 0 +0 3203 0 +0 3339 0 +0 3477 0 +0 3611 0 +0 3745 0 +0 3879 0 +0 4013 0 +3335 0 3155 +3335 0 3155 +3335 0 3155 +3335 0 3155 +3335 0 3155 +3333 0 3153 +3333 0 3153 +3331 0 3151 +3331 0 3149 +3329 0 3147 +3325 0 3143 +3321 0 3139 +3317 0 3133 +3309 0 3125 +3301 0 3115 +3287 0 3099 +3269 1116 3079 +3245 1692 3049 +3209 1997 3007 +3155 2227 2941 +3073 2419 2837 +2933 2593 2647 +2637 2753 2101 +0 2905 0 +0 3051 0 +0 3195 0 +0 3335 0 +0 3471 0 +0 3609 0 +0 3743 0 +0 3877 0 +0 4011 0 +3467 0 3287 +3467 0 3287 +3467 0 3287 +3467 0 3287 +3467 0 3287 +3467 0 3285 +3465 0 3285 +3465 0 3285 +3463 0 3283 +3463 0 3281 +3461 0 3279 +3457 0 3275 +3453 0 3271 +3449 0 3265 +3441 0 3257 +3431 0 3245 +3419 0 3231 +3401 1238 3209 +3375 1821 3181 +3341 2129 3137 +3287 2357 3073 +3205 2551 2969 +3065 2725 2777 +2767 2885 2225 +0 3037 0 +0 3183 0 +0 3327 0 +0 3467 0 +0 3605 0 +0 3741 0 +0 3875 0 +0 4011 0 +3599 0 3419 +3599 0 3419 +3599 0 3419 +3599 0 3419 +3599 0 3419 +3599 0 3417 +3599 0 3417 +3597 0 3417 +3597 0 3415 +3595 0 3415 +3595 0 3413 +3591 0 3411 +3589 0 3407 +3585 0 3403 +3581 0 3397 +3573 0 3389 +3563 0 3377 +3551 0 3363 +3533 1363 3341 +3507 1951 3311 +3471 2259 3269 +3419 2489 3203 +3337 2683 3099 +3197 2857 2907 +2899 3017 2351 +0 3169 0 +0 3315 0 +0 3459 0 +0 3599 0 +0 3737 0 +0 3873 0 +0 4007 0 +3733 0 3551 +3731 0 3551 +3731 0 3551 +3731 0 3551 +3731 0 3551 +3731 0 3551 +3731 0 3549 +3731 0 3549 +3729 0 3549 +3729 0 3547 +3727 0 3545 +3727 0 3545 +3725 0 3541 +3721 0 3539 +3717 0 3535 +3713 0 3529 +3705 0 3521 +3695 0 3509 +3683 0 3495 +3665 1489 3473 +3639 2081 3443 +3603 2391 3401 +3551 2621 3335 +3469 2815 3231 +3329 2989 3037 +3031 3149 2479 +0 3301 0 +0 3447 0 +0 3591 0 +0 3731 0 +0 3869 0 +0 4005 0 +3865 0 3683 +3865 0 3683 +3863 0 3683 +3863 0 3683 +3863 0 3683 +3863 0 3683 +3863 0 3681 +3863 0 3681 +3863 0 3681 +3861 0 3681 +3861 0 3679 +3859 0 3677 +3859 0 3677 +3857 0 3673 +3853 0 3671 +3849 0 3665 +3845 0 3661 +3837 0 3651 +3827 0 3641 +3815 0 3625 +3797 1617 3605 +3771 2213 3575 +3735 2523 3531 +3683 2753 3467 +3601 2947 3363 +3461 3121 3169 +3163 3281 2609 +0 3433 0 +0 3579 0 +0 3723 0 +0 3863 0 +0 4001 0 +3997 0 3815 +3997 0 3815 +3997 0 3815 +3997 0 3815 +3995 0 3815 +3995 0 3815 +3995 0 3815 +3995 0 3813 +3995 0 3813 +3995 0 3813 +3993 0 3813 +3993 0 3811 +3991 0 3809 +3991 0 3807 +3989 0 3805 +3985 0 3803 +3981 0 3797 +3977 0 3791 +3969 0 3783 +3959 0 3773 +3947 0 3757 +3929 1746 3737 +3903 2343 3707 +3869 2653 3663 +3815 2885 3599 +3733 3079 3493 +3593 3253 3301 +3295 3413 2739 +0 3565 0 +0 3711 0 +0 3855 0 +0 3995 0 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3945 +4095 0 3945 +4095 0 3945 +4095 0 3945 +4095 0 3943 +4095 0 3941 +4095 0 3939 +4095 0 3937 +4095 0 3935 +4095 0 3929 +4095 0 3923 +4095 0 3915 +4093 0 3905 +4079 0 3889 +4061 1876 3869 +4037 2475 3839 +4001 2785 3795 +3947 3017 3731 +3865 3211 3625 +3725 3385 3431 +3425 3545 2869 +0 3697 0 +0 3845 0 +0 3987 0 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4077 +4095 0 4077 +4095 0 4077 +4095 0 4077 +4095 0 4075 +4095 0 4073 +4095 0 4071 +4095 0 4069 +4095 0 4067 +4095 0 4061 +4095 0 4055 +4095 0 4047 +4095 0 4037 +4095 0 4021 +4095 2006 4001 +4095 2607 3971 +4095 2917 3927 +4079 3149 3863 +3997 3343 3757 +3857 3517 3563 +3557 3677 2999 +0 3829 0 +0 3977 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 2137 4095 +4095 2739 4095 +4095 3049 4059 +4095 3281 3995 +4095 3475 3889 +3989 3649 3695 +3689 3809 3131 +0 3961 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 2267 4095 +4095 2871 4095 +4095 3181 4095 +4095 3413 4095 +4095 3607 4021 +4095 3781 3827 +3821 3941 3261 +644 324 1001 +562 383 974 +422 452 935 +123 530 876 +0 617 784 +0 713 622 +0 815 233 +0 924 0 +0 1037 0 +0 1155 0 +0 1276 0 +0 1400 0 +0 1526 0 +0 1653 0 +0 1782 0 +0 1911 0 +0 2041 0 +0 2171 0 +0 2303 0 +0 2433 0 +0 2565 0 +0 2697 0 +0 2829 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +731 315 1029 +664 375 1004 +556 445 967 +354 524 913 +0 612 829 +0 708 684 +0 812 369 +0 921 0 +0 1035 0 +0 1154 0 +0 1275 0 +0 1399 0 +0 1525 0 +0 1653 0 +0 1781 0 +0 1911 0 +0 2041 0 +0 2171 0 +0 2303 0 +0 2433 0 +0 2565 0 +0 2697 0 +0 2829 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +826 301 1065 +772 363 1041 +689 435 1008 +548 516 958 +243 605 883 +0 703 757 +0 807 504 +0 918 0 +0 1033 0 +0 1151 0 +0 1273 0 +0 1398 0 +0 1524 0 +0 1652 0 +0 1781 0 +0 1910 0 +0 2041 0 +0 2171 0 +0 2303 0 +0 2433 0 +0 2565 0 +0 2697 0 +0 2829 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +928 282 1108 +886 347 1086 +822 421 1056 +721 504 1012 +536 596 946 +32 695 838 +0 801 638 +0 913 23 +0 1029 0 +0 1149 0 +0 1271 0 +0 1396 0 +0 1523 0 +0 1651 0 +0 1780 0 +0 1910 0 +0 2040 0 +0 2171 0 +0 2303 0 +0 2433 0 +0 2565 0 +0 2697 0 +0 2829 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1036 256 1160 +1003 324 1141 +955 402 1114 +882 488 1075 +760 583 1018 +521 685 929 +0 793 771 +0 907 406 +0 1024 0 +0 1145 0 +0 1268 0 +0 1394 0 +0 1521 0 +0 1650 0 +0 1779 0 +0 1909 0 +0 2040 0 +0 2171 0 +0 2301 0 +0 2433 0 +0 2565 0 +0 2697 0 +0 2829 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1150 219 1221 +1124 292 1205 +1088 375 1182 +1034 466 1149 +951 565 1100 +808 671 1026 +500 782 905 +0 898 663 +0 1017 0 +0 1140 0 +0 1265 0 +0 1391 0 +0 1519 0 +0 1648 0 +0 1778 0 +0 1908 0 +0 2039 0 +0 2171 0 +0 2301 0 +0 2433 0 +0 2565 0 +0 2697 0 +0 2829 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1267 163 1292 +1248 245 1278 +1220 336 1259 +1181 435 1231 +1122 540 1191 +1029 651 1131 +865 767 1037 +469 886 870 +0 1008 460 +0 1133 0 +0 1259 0 +0 1387 0 +0 1516 0 +0 1646 0 +0 1776 0 +0 1907 0 +0 2038 0 +0 2169 0 +0 2301 0 +0 2433 0 +0 2565 0 +0 2697 0 +0 2829 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1388 76 1373 +1373 174 1361 +1353 278 1345 +1324 389 1322 +1281 504 1289 +1218 623 1242 +1116 745 1170 +932 870 1051 +425 996 820 +0 1123 0 +0 1252 0 +0 1382 0 +0 1512 0 +0 1643 0 +0 1774 0 +0 1905 0 +0 2037 0 +0 2169 0 +0 2301 0 +0 2433 0 +0 2563 0 +0 2695 0 +0 2829 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1512 0 1462 +1501 57 1452 +1485 188 1439 +1463 319 1420 +1433 451 1395 +1388 583 1357 +1321 715 1303 +1212 847 1217 +1008 979 1069 +358 1110 742 +0 1242 0 +0 1374 0 +0 1507 0 +0 1639 0 +0 1771 0 +0 1903 0 +0 2035 0 +0 2167 0 +0 2299 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1638 0 1559 +1629 0 1551 +1617 29 1541 +1601 206 1526 +1579 369 1505 +1547 523 1477 +1501 670 1435 +1430 814 1373 +1315 954 1273 +1092 1092 1092 +250 1229 613 +0 1364 0 +0 1499 0 +0 1633 0 +0 1767 0 +0 1900 0 +0 2033 0 +0 2165 0 +0 2297 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1765 0 1663 +1758 0 1657 +1750 0 1649 +1738 0 1637 +1721 229 1621 +1698 428 1599 +1665 604 1567 +1617 766 1522 +1544 920 1452 +1423 1067 1338 +1186 1211 1122 +47 1351 348 +0 1489 0 +0 1626 0 +0 1761 0 +0 1896 0 +0 2030 0 +0 2163 0 +0 2297 0 +0 2429 0 +0 2561 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3355 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1893 0 1773 +1888 0 1768 +1882 0 1762 +1873 0 1753 +1861 0 1740 +1844 258 1723 +1820 496 1700 +1787 694 1666 +1738 869 1616 +1662 1031 1540 +1537 1185 1414 +1287 1332 1158 +0 1475 0 +0 1615 0 +0 1753 0 +0 1890 0 +0 2025 0 +0 2159 0 +0 2293 0 +0 2427 0 +0 2561 0 +0 2693 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3355 0 +0 3487 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +2023 0 1888 +2019 0 1884 +2014 0 1879 +2007 0 1872 +1998 0 1863 +1986 0 1850 +1969 295 1832 +1945 574 1807 +1911 791 1771 +1861 978 1718 +1784 1147 1637 +1655 1305 1498 +1394 1456 1202 +0 1601 0 +0 1743 0 +0 1882 0 +0 2020 0 +0 2155 0 +0 2291 0 +0 2425 0 +0 2559 0 +0 2693 0 +0 2825 0 +0 2957 0 +0 3091 0 +0 3223 0 +0 3355 0 +0 3487 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +2153 0 2007 +2149 0 2004 +2147 0 2000 +2141 0 1995 +2135 0 1987 +2125 0 1978 +2113 0 1964 +2095 339 1946 +2071 661 1920 +2037 896 1882 +1986 1092 1827 +1908 1267 1740 +1777 1429 1590 +1507 1582 1256 +0 1729 0 +0 1872 0 +0 2012 0 +0 2151 0 +0 2287 0 +0 2421 0 +0 2557 0 +0 2691 0 +0 2823 0 +0 2957 0 +0 3089 0 +0 3223 0 +0 3355 0 +0 3487 0 +0 3619 0 +0 3753 0 +0 3885 0 +0 4017 0 +2283 0 2129 +2281 0 2127 +2279 0 2123 +2275 0 2119 +2269 0 2113 +2263 0 2107 +2253 0 2097 +2241 0 2083 +2223 393 2063 +2199 756 2036 +2165 1006 1998 +2113 1210 1940 +2034 1390 1850 +1900 1554 1691 +1624 1709 1318 +0 1858 0 +0 2002 0 +0 2143 0 +0 2281 0 +0 2417 0 +0 2553 0 +0 2687 0 +0 2823 0 +0 2955 0 +0 3089 0 +0 3221 0 +0 3355 0 +0 3487 0 +0 3619 0 +0 3751 0 +0 3885 0 +0 4017 0 +2415 0 2253 +2413 0 2251 +2411 0 2249 +2407 0 2245 +2405 0 2241 +2399 0 2237 +2393 0 2229 +2383 0 2219 +2371 0 2205 +2353 455 2185 +2329 858 2157 +2293 1121 2117 +2241 1332 2057 +2161 1515 1964 +2026 1681 1797 +1744 1838 1391 +0 1987 0 +0 2131 0 +0 2273 0 +0 2411 0 +0 2549 0 +0 2685 0 +0 2819 0 +0 2953 0 +0 3087 0 +0 3221 0 +0 3353 0 +0 3487 0 +0 3619 0 +0 3751 0 +0 3883 0 +0 4017 0 +2545 0 2379 +2545 0 2377 +2543 0 2377 +2541 0 2373 +2537 0 2371 +2535 0 2367 +2529 0 2361 +2523 0 2353 +2513 0 2343 +2501 0 2329 +2483 528 2309 +2457 966 2281 +2423 1240 2239 +2371 1456 2179 +2289 1641 2083 +2153 1810 1910 +1867 1967 1472 +0 2117 0 +0 2263 0 +0 2405 0 +0 2543 0 +0 2681 0 +0 2817 0 +0 2951 0 +0 3085 0 +0 3219 0 +0 3353 0 +0 3485 0 +0 3619 0 +0 3751 0 +0 3883 0 +0 4017 0 +2677 0 2507 +2675 0 2505 +2675 0 2505 +2673 0 2503 +2671 0 2501 +2669 0 2497 +2665 0 2493 +2659 0 2487 +2653 0 2479 +2643 0 2469 +2631 0 2455 +2613 609 2433 +2587 1080 2405 +2553 1362 2365 +2501 1582 2303 +2419 1769 2203 +2283 1939 2026 +1993 2097 1562 +0 2249 0 +0 2393 0 +0 2535 0 +0 2675 0 +0 2813 0 +0 2949 0 +0 3083 0 +0 3217 0 +0 3351 0 +0 3485 0 +0 3617 0 +0 3751 0 +0 3883 0 +0 4015 0 +2809 0 2635 +2807 0 2635 +2807 0 2633 +2805 0 2633 +2805 0 2631 +2803 0 2629 +2799 0 2625 +2795 0 2621 +2791 0 2615 +2783 0 2607 +2775 0 2597 +2761 0 2581 +2743 700 2561 +2719 1198 2533 +2683 1487 2491 +2631 1709 2427 +2549 1898 2327 +2411 2069 2147 +2119 2227 1661 +0 2379 0 +0 2525 0 +0 2667 0 +0 2807 0 +0 2945 0 +0 3081 0 +0 3215 0 +0 3349 0 +0 3483 0 +0 3617 0 +0 3749 0 +0 3883 0 +0 4015 0 +2941 0 2765 +2939 0 2765 +2939 0 2763 +2939 0 2763 +2937 0 2761 +2935 0 2759 +2933 0 2757 +2931 0 2755 +2927 0 2749 +2921 0 2743 +2915 0 2737 +2905 0 2725 +2893 0 2711 +2875 798 2689 +2849 1319 2661 +2815 1613 2619 +2761 1837 2555 +2681 2028 2453 +2541 2199 2269 +2247 2359 1766 +0 2511 0 +0 2657 0 +0 2799 0 +0 2939 0 +0 3077 0 +0 3213 0 +0 3347 0 +0 3481 0 +0 3615 0 +0 3749 0 +0 3881 0 +0 4015 0 +3073 0 2895 +3071 0 2895 +3071 0 2895 +3071 0 2893 +3069 0 2893 +3069 0 2891 +3067 0 2889 +3065 0 2887 +3063 0 2883 +3059 0 2879 +3053 0 2873 +3047 0 2865 +3037 0 2855 +3025 0 2839 +3007 903 2819 +2981 1442 2789 +2945 1741 2747 +2893 1967 2683 +2811 2159 2581 +2673 2331 2395 +2377 2491 1876 +0 2641 0 +0 2789 0 +0 2931 0 +0 3071 0 +0 3207 0 +0 3345 0 +0 3479 0 +0 3613 0 +0 3747 0 +0 3881 0 +0 4015 0 +3205 0 3025 +3203 0 3025 +3203 0 3025 +3203 0 3025 +3203 0 3023 +3201 0 3023 +3201 0 3021 +3199 0 3019 +3197 0 3017 +3193 0 3015 +3191 0 3009 +3185 0 3003 +3177 0 2995 +3169 0 2985 +3155 0 2971 +3137 1014 2949 +3113 1568 2919 +3077 1870 2877 +3025 2097 2813 +2943 2289 2711 +2803 2461 2521 +2507 2621 1992 +0 2773 0 +0 2919 0 +0 3063 0 +0 3203 0 +0 3339 0 +0 3477 0 +0 3611 0 +0 3745 0 +0 3879 0 +0 4013 0 +3335 0 3157 +3335 0 3157 +3335 0 3157 +3335 0 3155 +3335 0 3155 +3335 0 3155 +3333 0 3153 +3333 0 3153 +3331 0 3151 +3329 0 3149 +3325 0 3145 +3321 0 3141 +3317 0 3135 +3309 0 3127 +3301 0 3115 +3287 0 3101 +3269 1129 3079 +3245 1695 3051 +3209 1999 3007 +3155 2227 2943 +3073 2421 2839 +2935 2593 2649 +2637 2753 2111 +0 2905 0 +0 3051 0 +0 3195 0 +0 3335 0 +0 3473 0 +0 3609 0 +0 3743 0 +0 3877 0 +0 4011 0 +3469 0 3289 +3467 0 3289 +3467 0 3287 +3467 0 3287 +3467 0 3287 +3467 0 3287 +3465 0 3285 +3465 0 3285 +3463 0 3283 +3463 0 3281 +3461 0 3279 +3457 0 3277 +3453 0 3271 +3449 0 3265 +3441 0 3257 +3433 0 3247 +3419 0 3231 +3401 1248 3211 +3377 1824 3181 +3341 2129 3139 +3287 2359 3073 +3205 2551 2969 +3065 2725 2779 +2769 2885 2233 +0 3037 0 +0 3183 0 +0 3327 0 +0 3467 0 +0 3605 0 +0 3741 0 +0 3875 0 +0 4011 0 +3601 0 3419 +3599 0 3419 +3599 0 3419 +3599 0 3419 +3599 0 3419 +3599 0 3419 +3599 0 3417 +3597 0 3417 +3597 0 3417 +3595 0 3415 +3595 0 3413 +3593 0 3411 +3589 0 3407 +3585 0 3403 +3581 0 3397 +3573 0 3389 +3565 0 3379 +3551 0 3363 +3533 1371 3341 +3509 1953 3313 +3473 2261 3269 +3419 2489 3205 +3337 2683 3101 +3197 2857 2909 +2899 3017 2357 +0 3169 0 +0 3315 0 +0 3459 0 +0 3599 0 +0 3737 0 +0 3873 0 +0 4007 0 +3733 0 3551 +3733 0 3551 +3731 0 3551 +3731 0 3551 +3731 0 3551 +3731 0 3551 +3731 0 3551 +3731 0 3549 +3729 0 3549 +3729 0 3547 +3727 0 3547 +3727 0 3545 +3725 0 3543 +3721 0 3539 +3717 0 3535 +3713 0 3529 +3705 0 3521 +3697 0 3509 +3683 0 3495 +3665 1495 3473 +3641 2083 3443 +3605 2391 3401 +3551 2621 3335 +3469 2815 3231 +3329 2989 3039 +3031 3149 2485 +0 3301 0 +0 3447 0 +0 3591 0 +0 3731 0 +0 3869 0 +0 4005 0 +3865 0 3683 +3865 0 3683 +3865 0 3683 +3863 0 3683 +3863 0 3683 +3863 0 3683 +3863 0 3683 +3863 0 3681 +3863 0 3681 +3861 0 3681 +3861 0 3679 +3859 0 3679 +3859 0 3677 +3857 0 3673 +3853 0 3671 +3849 0 3667 +3845 0 3661 +3837 0 3653 +3829 0 3641 +3815 0 3627 +3797 1622 3605 +3773 2213 3575 +3737 2523 3533 +3683 2753 3467 +3601 2947 3363 +3461 3121 3169 +3163 3281 2611 +0 3433 0 +0 3579 0 +0 3723 0 +0 3863 0 +0 4001 0 +3997 0 3815 +3997 0 3815 +3997 0 3815 +3997 0 3815 +3995 0 3815 +3995 0 3815 +3995 0 3815 +3995 0 3815 +3995 0 3813 +3995 0 3813 +3993 0 3813 +3993 0 3811 +3991 0 3809 +3991 0 3809 +3989 0 3805 +3985 0 3803 +3981 0 3799 +3977 0 3793 +3969 0 3785 +3961 0 3773 +3947 0 3757 +3929 1749 3737 +3905 2345 3707 +3869 2655 3663 +3815 2885 3599 +3733 3079 3495 +3593 3253 3301 +3295 3413 2741 +0 3565 0 +0 3711 0 +0 3855 0 +0 3995 0 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3945 +4095 0 3945 +4095 0 3945 +4095 0 3945 +4095 0 3943 +4095 0 3941 +4095 0 3941 +4095 0 3937 +4095 0 3935 +4095 0 3929 +4095 0 3925 +4095 0 3915 +4093 0 3905 +4079 0 3889 +4061 1878 3869 +4037 2475 3839 +4001 2785 3795 +3947 3017 3731 +3865 3211 3625 +3725 3385 3433 +3427 3545 2871 +0 3697 0 +0 3845 0 +0 3987 0 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4077 +4095 0 4077 +4095 0 4077 +4095 0 4077 +4095 0 4075 +4095 0 4073 +4095 0 4071 +4095 0 4069 +4095 0 4067 +4095 0 4061 +4095 0 4055 +4095 0 4047 +4095 0 4037 +4095 0 4021 +4095 2008 4001 +4095 2607 3971 +4095 2917 3927 +4079 3149 3863 +3997 3343 3757 +3857 3517 3563 +3559 3677 3001 +0 3829 0 +0 3977 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 2139 4095 +4095 2739 4095 +4095 3049 4059 +4095 3281 3995 +4095 3475 3889 +3989 3649 3695 +3691 3809 3131 +0 3961 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 2269 4095 +4095 2871 4095 +4095 3181 4095 +4095 3413 4095 +4095 3607 4021 +4095 3781 3827 +3823 3941 3263 +761 415 1131 +699 464 1111 +599 522 1082 +420 590 1041 +0 667 979 +0 753 880 +0 848 701 +0 950 229 +0 1058 0 +0 1171 0 +0 1288 0 +0 1409 0 +0 1533 0 +0 1658 0 +0 1786 0 +0 1914 0 +0 2043 0 +0 2173 0 +0 2303 0 +0 2435 0 +0 2567 0 +0 2697 0 +0 2829 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +829 407 1153 +776 456 1133 +694 515 1106 +554 584 1067 +255 662 1008 +0 749 916 +0 845 754 +0 947 365 +0 1056 0 +0 1169 0 +0 1287 0 +0 1408 0 +0 1532 0 +0 1658 0 +0 1785 0 +0 1914 0 +0 2043 0 +0 2173 0 +0 2303 0 +0 2435 0 +0 2567 0 +0 2697 0 +0 2829 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +907 396 1180 +863 447 1161 +796 507 1136 +688 577 1099 +486 656 1045 +0 744 961 +0 841 817 +0 944 501 +0 1053 0 +0 1167 0 +0 1286 0 +0 1407 0 +0 1531 0 +0 1657 0 +0 1785 0 +0 1913 0 +0 2043 0 +0 2173 0 +0 2303 0 +0 2435 0 +0 2565 0 +0 2697 0 +0 2829 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +994 381 1214 +958 433 1197 +904 495 1173 +821 567 1139 +680 648 1090 +375 737 1015 +0 835 889 +0 939 636 +0 1050 0 +0 1165 0 +0 1284 0 +0 1406 0 +0 1530 0 +0 1656 0 +0 1784 0 +0 1913 0 +0 2042 0 +0 2173 0 +0 2303 0 +0 2435 0 +0 2565 0 +0 2697 0 +0 2829 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1089 360 1255 +1060 415 1240 +1018 479 1219 +955 553 1188 +853 636 1144 +669 728 1078 +164 827 970 +0 933 770 +0 1045 155 +0 1161 0 +0 1281 0 +0 1403 0 +0 1528 0 +0 1655 0 +0 1783 0 +0 1912 0 +0 2042 0 +0 2173 0 +0 2303 0 +0 2435 0 +0 2565 0 +0 2697 0 +0 2829 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1191 330 1306 +1168 388 1292 +1135 456 1273 +1087 534 1246 +1014 620 1208 +893 715 1150 +653 817 1060 +0 925 903 +0 1038 538 +0 1156 0 +0 1277 0 +0 1401 0 +0 1526 0 +0 1653 0 +0 1782 0 +0 1911 0 +0 2041 0 +0 2171 0 +0 2303 0 +0 2433 0 +0 2565 0 +0 2697 0 +0 2829 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1300 287 1366 +1282 351 1353 +1256 424 1337 +1220 507 1314 +1166 598 1281 +1083 697 1232 +940 803 1159 +632 914 1036 +0 1030 795 +0 1149 0 +0 1272 0 +0 1397 0 +0 1523 0 +0 1651 0 +0 1780 0 +0 1910 0 +0 2040 0 +0 2171 0 +0 2303 0 +0 2433 0 +0 2565 0 +0 2697 0 +0 2829 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1413 222 1435 +1399 295 1425 +1380 377 1410 +1352 468 1391 +1313 567 1363 +1254 672 1323 +1161 783 1264 +997 899 1169 +601 1018 1002 +0 1140 592 +0 1265 0 +0 1391 0 +0 1519 0 +0 1648 0 +0 1778 0 +0 1908 0 +0 2039 0 +0 2171 0 +0 2301 0 +0 2433 0 +0 2565 0 +0 2697 0 +0 2829 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1531 118 1514 +1520 208 1505 +1505 306 1493 +1485 411 1477 +1456 521 1454 +1413 636 1421 +1350 755 1374 +1249 877 1302 +1063 1002 1183 +557 1128 952 +0 1255 0 +0 1384 0 +0 1514 0 +0 1644 0 +0 1775 0 +0 1906 0 +0 2037 0 +0 2169 0 +0 2301 0 +0 2433 0 +0 2565 0 +0 2697 0 +0 2829 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1652 0 1601 +1644 58 1594 +1633 189 1584 +1617 320 1571 +1596 451 1553 +1565 583 1527 +1520 715 1490 +1453 847 1435 +1344 979 1349 +1139 1110 1201 +490 1242 875 +0 1375 0 +0 1507 0 +0 1639 0 +0 1771 0 +0 1903 0 +0 2035 0 +0 2167 0 +0 2299 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1776 0 1697 +1770 0 1691 +1761 0 1683 +1749 161 1673 +1733 338 1658 +1711 501 1638 +1679 655 1609 +1633 803 1567 +1562 946 1505 +1447 1086 1405 +1225 1225 1225 +382 1361 745 +0 1497 0 +0 1631 0 +0 1765 0 +0 1899 0 +0 2032 0 +0 2165 0 +0 2297 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1902 0 1800 +1897 0 1795 +1890 0 1789 +1882 0 1781 +1870 122 1769 +1853 361 1753 +1830 560 1731 +1797 736 1700 +1750 898 1654 +1676 1052 1584 +1556 1199 1471 +1318 1343 1254 +179 1483 480 +0 1621 0 +0 1758 0 +0 1893 0 +0 2028 0 +0 2161 0 +0 2295 0 +0 2429 0 +0 2561 0 +0 2693 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3355 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +2029 0 1909 +2025 0 1905 +2021 0 1900 +2014 0 1894 +2005 0 1885 +1993 63 1873 +1976 390 1856 +1952 628 1832 +1919 826 1798 +1870 1001 1748 +1795 1163 1672 +1669 1317 1546 +1419 1464 1290 +0 1607 0 +0 1747 0 +0 1886 0 +0 2022 0 +0 2157 0 +0 2293 0 +0 2425 0 +0 2559 0 +0 2693 0 +0 2825 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3355 0 +0 3487 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +2157 0 2023 +2155 0 2020 +2151 0 2016 +2147 0 2011 +2139 0 2004 +2131 0 1995 +2119 0 1982 +2101 427 1964 +2077 706 1939 +2043 924 1903 +1993 1110 1851 +1916 1279 1769 +1787 1437 1630 +1526 1588 1334 +0 1733 0 +0 1875 0 +0 2014 0 +0 2151 0 +0 2287 0 +0 2423 0 +0 2557 0 +0 2691 0 +0 2825 0 +0 2957 0 +0 3089 0 +0 3223 0 +0 3355 0 +0 3487 0 +0 3619 0 +0 3753 0 +0 3885 0 +0 4017 0 +2287 0 2141 +2285 0 2139 +2283 0 2135 +2279 0 2131 +2273 0 2127 +2267 0 2119 +2257 0 2109 +2245 0 2097 +2227 471 2077 +2203 793 2051 +2169 1028 2014 +2119 1224 1959 +2040 1399 1872 +1909 1561 1723 +1639 1714 1388 +0 1861 0 +0 2004 0 +0 2145 0 +0 2283 0 +0 2419 0 +0 2555 0 +0 2689 0 +0 2823 0 +0 2955 0 +0 3089 0 +0 3221 0 +0 3355 0 +0 3487 0 +0 3619 0 +0 3751 0 +0 3885 0 +0 4017 0 +2417 0 2263 +2415 0 2261 +2413 0 2259 +2411 0 2255 +2407 0 2251 +2401 0 2245 +2395 0 2239 +2385 0 2229 +2373 0 2215 +2355 525 2195 +2331 888 2169 +2297 1138 2129 +2245 1342 2073 +2165 1522 1982 +2033 1686 1823 +1756 1841 1450 +0 1990 0 +0 2133 0 +0 2275 0 +0 2413 0 +0 2549 0 +0 2685 0 +0 2821 0 +0 2955 0 +0 3087 0 +0 3221 0 +0 3353 0 +0 3487 0 +0 3619 0 +0 3751 0 +0 3883 0 +0 4017 0 +2547 0 2387 +2547 0 2385 +2545 0 2383 +2543 0 2381 +2539 0 2377 +2537 0 2373 +2531 0 2369 +2525 0 2361 +2515 0 2351 +2503 0 2337 +2485 587 2317 +2461 990 2289 +2425 1253 2249 +2373 1464 2189 +2293 1647 2097 +2159 1813 1930 +1876 1970 1523 +0 2119 0 +0 2263 0 +0 2405 0 +0 2545 0 +0 2681 0 +0 2817 0 +0 2951 0 +0 3085 0 +0 3219 0 +0 3353 0 +0 3485 0 +0 3619 0 +0 3751 0 +0 3883 0 +0 4017 0 +2679 0 2513 +2677 0 2511 +2677 0 2509 +2675 0 2509 +2673 0 2505 +2669 0 2503 +2667 0 2499 +2661 0 2493 +2655 0 2485 +2645 0 2475 +2633 0 2461 +2615 660 2441 +2589 1098 2413 +2555 1372 2371 +2503 1588 2311 +2421 1773 2215 +2285 1942 2042 +1999 2099 1604 +0 2249 0 +0 2395 0 +0 2537 0 +0 2675 0 +0 2813 0 +0 2949 0 +0 3083 0 +0 3217 0 +0 3351 0 +0 3485 0 +0 3617 0 +0 3751 0 +0 3883 0 +0 4015 0 +2809 0 2639 +2809 0 2639 +2809 0 2637 +2807 0 2637 +2805 0 2635 +2803 0 2633 +2801 0 2629 +2797 0 2625 +2791 0 2619 +2785 0 2611 +2775 0 2601 +2763 0 2587 +2745 742 2567 +2721 1212 2537 +2685 1495 2497 +2633 1714 2435 +2551 1901 2335 +2415 2071 2159 +2125 2229 1695 +0 2381 0 +0 2525 0 +0 2667 0 +0 2807 0 +0 2945 0 +0 3081 0 +0 3215 0 +0 3349 0 +0 3483 0 +0 3617 0 +0 3749 0 +0 3883 0 +0 4015 0 +2941 0 2769 +2941 0 2767 +2939 0 2767 +2939 0 2765 +2937 0 2765 +2937 0 2763 +2935 0 2761 +2931 0 2757 +2927 0 2753 +2923 0 2747 +2915 0 2739 +2907 0 2729 +2893 0 2713 +2875 832 2693 +2851 1330 2665 +2815 1619 2623 +2763 1841 2561 +2681 2030 2461 +2543 2201 2279 +2251 2361 1793 +0 2511 0 +0 2657 0 +0 2799 0 +0 2939 0 +0 3077 0 +0 3213 0 +0 3347 0 +0 3481 0 +0 3615 0 +0 3749 0 +0 3883 0 +0 4015 0 +3073 0 2897 +3073 0 2897 +3071 0 2897 +3071 0 2895 +3071 0 2895 +3069 0 2893 +3067 0 2891 +3065 0 2889 +3063 0 2887 +3059 0 2881 +3053 0 2877 +3047 0 2869 +3037 0 2857 +3025 0 2843 +3007 930 2821 +2981 1451 2793 +2947 1745 2751 +2893 1970 2687 +2813 2161 2587 +2673 2331 2401 +2379 2491 1898 +0 2643 0 +0 2789 0 +0 2931 0 +0 3071 0 +0 3209 0 +0 3345 0 +0 3479 0 +0 3613 0 +0 3747 0 +0 3881 0 +0 4015 0 +3205 0 3027 +3205 0 3027 +3203 0 3027 +3203 0 3027 +3203 0 3025 +3201 0 3025 +3201 0 3023 +3199 0 3021 +3197 0 3019 +3195 0 3015 +3191 0 3011 +3185 0 3005 +3179 0 2997 +3169 0 2987 +3157 0 2973 +3139 1035 2951 +3113 1574 2921 +3077 1873 2879 +3025 2099 2815 +2943 2291 2713 +2805 2463 2527 +2509 2623 2008 +0 2775 0 +0 2921 0 +0 3063 0 +0 3203 0 +0 3341 0 +0 3477 0 +0 3611 0 +0 3745 0 +0 3879 0 +0 4013 0 +3337 0 3159 +3337 0 3157 +3335 0 3157 +3335 0 3157 +3335 0 3157 +3335 0 3155 +3333 0 3155 +3333 0 3153 +3331 0 3151 +3329 0 3149 +3325 0 3147 +3323 0 3141 +3317 0 3137 +3311 0 3129 +3301 0 3117 +3287 0 3103 +3269 1146 3081 +3245 1700 3051 +3209 2002 3009 +3157 2229 2945 +3075 2421 2843 +2935 2593 2653 +2639 2753 2123 +0 2905 0 +0 3053 0 +0 3195 0 +0 3335 0 +0 3473 0 +0 3609 0 +0 3743 0 +0 3879 0 +0 4011 0 +3469 0 3289 +3469 0 3289 +3467 0 3289 +3467 0 3289 +3467 0 3289 +3467 0 3287 +3467 0 3287 +3465 0 3285 +3465 0 3285 +3463 0 3283 +3461 0 3281 +3457 0 3277 +3453 0 3273 +3449 0 3267 +3441 0 3259 +3433 0 3247 +3419 0 3233 +3401 1261 3211 +3377 1827 3183 +3341 2131 3139 +3287 2359 3075 +3205 2553 2971 +3067 2725 2781 +2769 2885 2243 +0 3037 0 +0 3183 0 +0 3327 0 +0 3467 0 +0 3605 0 +0 3741 0 +0 3875 0 +0 4011 0 +3601 0 3421 +3601 0 3421 +3599 0 3421 +3599 0 3419 +3599 0 3419 +3599 0 3419 +3599 0 3419 +3599 0 3417 +3597 0 3417 +3595 0 3415 +3595 0 3413 +3593 0 3411 +3589 0 3409 +3585 0 3403 +3581 0 3397 +3573 0 3389 +3565 0 3379 +3551 0 3363 +3533 1380 3343 +3509 1956 3313 +3473 2261 3271 +3419 2491 3205 +3337 2683 3101 +3199 2857 2911 +2901 3017 2365 +0 3169 0 +0 3315 0 +0 3459 0 +0 3599 0 +0 3737 0 +0 3873 0 +0 4007 0 +3733 0 3551 +3733 0 3551 +3733 0 3551 +3731 0 3551 +3731 0 3551 +3731 0 3551 +3731 0 3551 +3731 0 3551 +3729 0 3549 +3729 0 3549 +3727 0 3547 +3727 0 3545 +3725 0 3543 +3721 0 3539 +3717 0 3535 +3713 0 3529 +3705 0 3521 +3697 0 3511 +3683 0 3495 +3665 1503 3475 +3641 2085 3445 +3605 2393 3401 +3551 2623 3337 +3469 2815 3233 +3329 2989 3041 +3031 3149 2489 +0 3301 0 +0 3447 0 +0 3591 0 +0 3731 0 +0 3869 0 +0 4005 0 +3865 0 3683 +3865 0 3683 +3865 0 3683 +3865 0 3683 +3863 0 3683 +3863 0 3683 +3863 0 3683 +3863 0 3683 +3863 0 3681 +3861 0 3681 +3861 0 3679 +3859 0 3679 +3859 0 3677 +3857 0 3675 +3853 0 3671 +3849 0 3667 +3845 0 3661 +3837 0 3653 +3829 0 3641 +3815 0 3627 +3797 1627 3605 +3773 2215 3575 +3737 2523 3533 +3683 2753 3467 +3601 2947 3363 +3461 3121 3171 +3163 3281 2617 +0 3433 0 +0 3579 0 +0 3723 0 +0 3863 0 +0 4001 0 +3997 0 3815 +3997 0 3815 +3997 0 3815 +3997 0 3815 +3997 0 3815 +3995 0 3815 +3995 0 3815 +3995 0 3815 +3995 0 3813 +3995 0 3813 +3993 0 3813 +3993 0 3811 +3991 0 3811 +3991 0 3809 +3989 0 3807 +3985 0 3803 +3981 0 3799 +3977 0 3793 +3969 0 3785 +3961 0 3773 +3947 0 3759 +3929 1754 3737 +3905 2345 3707 +3869 2655 3665 +3815 2885 3599 +3733 3079 3495 +3593 3253 3301 +3295 3413 2743 +0 3565 0 +0 3713 0 +0 3855 0 +0 3995 0 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3945 +4095 0 3945 +4095 0 3945 +4095 0 3943 +4095 0 3943 +4095 0 3941 +4095 0 3937 +4095 0 3935 +4095 0 3931 +4095 0 3925 +4095 0 3917 +4093 0 3905 +4079 0 3891 +4061 1881 3869 +4037 2477 3839 +4001 2787 3795 +3947 3017 3731 +3865 3211 3627 +3725 3385 3433 +3427 3545 2873 +0 3697 0 +0 3845 0 +0 3987 0 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4077 +4095 0 4077 +4095 0 4077 +4095 0 4075 +4095 0 4073 +4095 0 4073 +4095 0 4069 +4095 0 4067 +4095 0 4063 +4095 0 4057 +4095 0 4049 +4095 0 4037 +4095 0 4021 +4095 2010 4001 +4095 2609 3971 +4095 2919 3927 +4079 3149 3863 +3997 3343 3757 +3857 3517 3565 +3559 3677 3003 +0 3829 0 +0 3977 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 2141 4095 +4095 2739 4095 +4095 3049 4059 +4095 3281 3995 +4095 3475 3889 +3989 3649 3697 +3691 3809 3133 +0 3961 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 2271 4095 +4095 2871 4095 +4095 3181 4095 +4095 3413 4095 +4095 3607 4021 +4095 3781 3827 +3823 3941 3263 +881 513 1262 +834 553 1247 +762 601 1225 +645 659 1196 +417 726 1152 +0 802 1087 +0 888 982 +0 982 788 +0 1083 222 +0 1191 0 +0 1304 0 +0 1421 0 +0 1542 0 +0 1665 0 +0 1791 0 +0 1918 0 +0 2046 0 +0 2175 0 +0 2305 0 +0 2437 0 +0 2567 0 +0 2699 0 +0 2829 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +934 506 1278 +893 547 1263 +831 596 1243 +731 654 1214 +552 722 1173 +77 799 1111 +0 885 1012 +0 980 833 +0 1082 361 +0 1190 0 +0 1303 0 +0 1421 0 +0 1541 0 +0 1665 0 +0 1791 0 +0 1918 0 +0 2046 0 +0 2175 0 +0 2305 0 +0 2437 0 +0 2567 0 +0 2699 0 +0 2829 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +997 497 1299 +961 539 1285 +908 588 1265 +826 648 1238 +686 716 1199 +387 794 1140 +0 882 1048 +0 977 886 +0 1079 498 +0 1188 0 +0 1302 0 +0 1419 0 +0 1541 0 +0 1664 0 +0 1790 0 +0 1917 0 +0 2046 0 +0 2175 0 +0 2305 0 +0 2435 0 +0 2567 0 +0 2699 0 +0 2829 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1070 485 1325 +1039 528 1312 +995 579 1294 +928 639 1268 +820 709 1231 +618 788 1177 +0 876 1093 +0 973 949 +0 1076 633 +0 1185 0 +0 1299 0 +0 1418 0 +0 1539 0 +0 1663 0 +0 1789 0 +0 1917 0 +0 2045 0 +0 2175 0 +0 2305 0 +0 2435 0 +0 2567 0 +0 2699 0 +0 2829 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1151 469 1358 +1126 513 1346 +1090 565 1329 +1036 627 1305 +954 699 1272 +812 780 1222 +507 870 1147 +0 967 1021 +0 1071 768 +0 1182 0 +0 1297 0 +0 1416 0 +0 1538 0 +0 1662 0 +0 1788 0 +0 1916 0 +0 2045 0 +0 2175 0 +0 2305 0 +0 2435 0 +0 2567 0 +0 2697 0 +0 2829 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1242 446 1399 +1221 492 1387 +1192 547 1372 +1150 611 1351 +1086 685 1320 +985 768 1276 +801 860 1210 +296 960 1102 +0 1065 902 +0 1177 287 +0 1293 0 +0 1413 0 +0 1536 0 +0 1661 0 +0 1787 0 +0 1915 0 +0 2044 0 +0 2175 0 +0 2305 0 +0 2435 0 +0 2567 0 +0 2697 0 +0 2829 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1340 413 1448 +1323 462 1438 +1300 520 1424 +1267 588 1405 +1219 666 1378 +1146 752 1340 +1024 847 1283 +785 949 1193 +0 1057 1035 +0 1171 670 +0 1288 0 +0 1409 0 +0 1533 0 +0 1658 0 +0 1786 0 +0 1914 0 +0 2043 0 +0 2173 0 +0 2303 0 +0 2435 0 +0 2567 0 +0 2697 0 +0 2829 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1445 365 1506 +1432 419 1498 +1414 483 1486 +1388 556 1469 +1352 639 1446 +1298 730 1413 +1215 829 1365 +1072 935 1291 +764 1046 1169 +0 1162 927 +0 1281 0 +0 1404 0 +0 1529 0 +0 1655 0 +0 1783 0 +0 1912 0 +0 2042 0 +0 2173 0 +0 2303 0 +0 2435 0 +0 2565 0 +0 2697 0 +0 2829 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1556 291 1575 +1546 354 1567 +1531 427 1557 +1512 509 1542 +1485 600 1523 +1445 699 1495 +1386 804 1455 +1293 915 1396 +1129 1031 1301 +733 1150 1134 +0 1272 724 +0 1397 0 +0 1524 0 +0 1651 0 +0 1780 0 +0 1910 0 +0 2040 0 +0 2171 0 +0 2303 0 +0 2433 0 +0 2565 0 +0 2697 0 +0 2829 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1671 169 1652 +1663 250 1646 +1652 340 1637 +1638 438 1625 +1617 543 1609 +1588 653 1586 +1546 768 1554 +1482 887 1506 +1381 1009 1434 +1196 1134 1315 +689 1260 1084 +0 1388 87 +0 1516 0 +0 1646 0 +0 1776 0 +0 1907 0 +0 2038 0 +0 2169 0 +0 2301 0 +0 2433 0 +0 2565 0 +0 2697 0 +0 2829 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1790 0 1739 +1784 59 1733 +1776 190 1726 +1765 321 1716 +1749 452 1703 +1728 583 1685 +1697 715 1659 +1653 847 1622 +1585 979 1567 +1476 1111 1481 +1272 1243 1334 +622 1375 1007 +0 1507 0 +0 1639 0 +0 1771 0 +0 1903 0 +0 2035 0 +0 2167 0 +0 2299 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1913 0 1833 +1908 0 1829 +1902 0 1823 +1893 93 1816 +1882 293 1805 +1866 470 1790 +1843 633 1770 +1811 787 1741 +1765 935 1699 +1694 1078 1637 +1579 1218 1537 +1357 1357 1357 +514 1493 877 +0 1629 0 +0 1763 0 +0 1897 0 +0 2031 0 +0 2165 0 +0 2297 0 +0 2429 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3355 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +2037 0 1935 +2034 0 1932 +2029 0 1927 +2023 0 1921 +2014 0 1913 +2002 254 1901 +1985 493 1885 +1962 692 1863 +1930 868 1832 +1882 1030 1786 +1809 1184 1716 +1688 1331 1603 +1450 1475 1386 +311 1615 612 +0 1753 0 +0 1890 0 +0 2025 0 +0 2159 0 +0 2293 0 +0 2427 0 +0 2561 0 +0 2693 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3355 0 +0 3487 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +2163 0 2044 +2161 0 2041 +2157 0 2037 +2153 0 2033 +2147 0 2026 +2137 0 2017 +2125 195 2005 +2109 522 1988 +2085 760 1964 +2051 958 1930 +2002 1133 1881 +1927 1295 1805 +1802 1449 1678 +1551 1596 1422 +0 1739 0 +0 1880 0 +0 2018 0 +0 2155 0 +0 2289 0 +0 2425 0 +0 2559 0 +0 2691 0 +0 2825 0 +0 2957 0 +0 3091 0 +0 3223 0 +0 3355 0 +0 3487 0 +0 3619 0 +0 3753 0 +0 3885 0 +0 4017 0 +2291 0 2157 +2289 0 2155 +2287 0 2153 +2283 0 2149 +2279 0 2143 +2271 0 2137 +2263 0 2127 +2251 102 2115 +2233 559 2097 +2209 838 2071 +2175 1055 2035 +2125 1242 1983 +2049 1412 1901 +1920 1570 1762 +1658 1720 1466 +0 1866 0 +0 2007 0 +0 2147 0 +0 2283 0 +0 2419 0 +0 2555 0 +0 2689 0 +0 2823 0 +0 2957 0 +0 3089 0 +0 3223 0 +0 3355 0 +0 3487 0 +0 3619 0 +0 3751 0 +0 3885 0 +0 4017 0 +2421 0 2275 +2419 0 2273 +2417 0 2271 +2415 0 2269 +2411 0 2265 +2405 0 2259 +2399 0 2251 +2389 0 2241 +2377 0 2229 +2359 603 2209 +2335 925 2183 +2301 1160 2147 +2251 1356 2091 +2173 1531 2004 +2041 1693 1855 +1771 1846 1520 +0 1993 0 +0 2137 0 +0 2277 0 +0 2415 0 +0 2551 0 +0 2687 0 +0 2821 0 +0 2955 0 +0 3089 0 +0 3221 0 +0 3355 0 +0 3487 0 +0 3619 0 +0 3751 0 +0 3885 0 +0 4017 0 +2551 0 2395 +2549 0 2395 +2547 0 2393 +2545 0 2391 +2543 0 2387 +2539 0 2383 +2533 0 2379 +2527 0 2371 +2517 0 2361 +2505 0 2347 +2487 657 2327 +2463 1020 2301 +2429 1270 2261 +2377 1475 2205 +2299 1654 2113 +2165 1818 1955 +1888 1973 1583 +0 2121 0 +0 2265 0 +0 2407 0 +0 2545 0 +0 2681 0 +0 2817 0 +0 2953 0 +0 3087 0 +0 3219 0 +0 3353 0 +0 3485 0 +0 3619 0 +0 3751 0 +0 3883 0 +0 4017 0 +2681 0 2519 +2679 0 2519 +2679 0 2517 +2677 0 2515 +2675 0 2513 +2673 0 2511 +2669 0 2505 +2663 0 2501 +2657 0 2493 +2647 0 2483 +2635 0 2469 +2617 720 2449 +2593 1122 2421 +2557 1386 2381 +2505 1596 2321 +2425 1779 2229 +2291 1946 2061 +2008 2101 1655 +0 2251 0 +0 2397 0 +0 2537 0 +0 2677 0 +0 2813 0 +0 2949 0 +0 3083 0 +0 3219 0 +0 3351 0 +0 3485 0 +0 3617 0 +0 3751 0 +0 3883 0 +0 4015 0 +2811 0 2645 +2811 0 2645 +2809 0 2643 +2809 0 2641 +2807 0 2641 +2805 0 2637 +2803 0 2635 +2799 0 2631 +2793 0 2625 +2787 0 2617 +2777 0 2607 +2765 0 2593 +2747 792 2573 +2721 1230 2545 +2687 1505 2503 +2635 1720 2443 +2555 1906 2347 +2417 2073 2173 +2131 2231 1736 +0 2381 0 +0 2527 0 +0 2669 0 +0 2807 0 +0 2945 0 +0 3081 0 +0 3215 0 +0 3351 0 +0 3483 0 +0 3617 0 +0 3751 0 +0 3883 0 +0 4015 0 +2943 0 2773 +2941 0 2771 +2941 0 2771 +2941 0 2769 +2939 0 2769 +2937 0 2767 +2935 0 2765 +2933 0 2761 +2929 0 2757 +2923 0 2751 +2917 0 2743 +2907 0 2733 +2895 0 2719 +2877 874 2699 +2853 1344 2669 +2817 1627 2629 +2765 1846 2567 +2683 2034 2469 +2547 2203 2291 +2257 2361 1827 +0 2513 0 +0 2657 0 +0 2799 0 +0 2939 0 +0 3077 0 +0 3213 0 +0 3347 0 +0 3481 0 +0 3615 0 +0 3749 0 +0 3883 0 +0 4015 0 +3073 0 2901 +3073 0 2901 +3073 0 2899 +3073 0 2899 +3071 0 2897 +3071 0 2897 +3069 0 2895 +3067 0 2893 +3063 0 2889 +3059 0 2885 +3055 0 2879 +3047 0 2871 +3039 0 2861 +3025 0 2847 +3007 964 2825 +2983 1462 2797 +2947 1751 2755 +2895 1973 2693 +2813 2163 2593 +2675 2333 2411 +2383 2493 1925 +0 2643 0 +0 2789 0 +0 2931 0 +0 3071 0 +0 3209 0 +0 3345 0 +0 3479 0 +0 3613 0 +0 3747 0 +0 3881 0 +0 4015 0 +3205 0 3029 +3205 0 3029 +3205 0 3029 +3205 0 3029 +3203 0 3027 +3203 0 3027 +3201 0 3025 +3199 0 3023 +3197 0 3021 +3195 0 3019 +3191 0 3013 +3187 0 3009 +3179 0 3001 +3169 0 2989 +3157 0 2975 +3139 1062 2955 +3115 1583 2925 +3079 1877 2883 +3025 2101 2819 +2945 2293 2719 +2805 2463 2533 +2513 2623 2030 +0 2775 0 +0 2921 0 +0 3063 0 +0 3203 0 +0 3341 0 +0 3477 0 +0 3611 0 +0 3747 0 +0 3879 0 +0 4013 0 +3337 0 3159 +3337 0 3159 +3337 0 3159 +3335 0 3159 +3335 0 3159 +3335 0 3157 +3335 0 3157 +3333 0 3155 +3331 0 3153 +3329 0 3151 +3327 0 3149 +3323 0 3143 +3317 0 3137 +3311 0 3129 +3301 0 3119 +3289 0 3105 +3271 1167 3083 +3245 1707 3055 +3209 2005 3011 +3157 2231 2947 +3075 2423 2845 +2937 2595 2659 +2641 2755 2141 +0 2907 0 +0 3053 0 +0 3195 0 +0 3335 0 +0 3473 0 +0 3609 0 +0 3743 0 +0 3879 0 +0 4011 0 +3469 0 3291 +3469 0 3291 +3469 0 3291 +3469 0 3289 +3467 0 3289 +3467 0 3289 +3467 0 3289 +3465 0 3287 +3465 0 3285 +3463 0 3283 +3461 0 3281 +3459 0 3279 +3455 0 3275 +3449 0 3269 +3443 0 3261 +3433 0 3249 +3419 0 3235 +3403 1278 3213 +3377 1832 3183 +3341 2133 3141 +3289 2361 3077 +3207 2553 2975 +3067 2725 2785 +2771 2885 2255 +0 3037 0 +0 3185 0 +0 3327 0 +0 3467 0 +0 3605 0 +0 3741 0 +0 3875 0 +0 4011 0 +3601 0 3421 +3601 0 3421 +3601 0 3421 +3601 0 3421 +3599 0 3421 +3599 0 3421 +3599 0 3419 +3599 0 3419 +3597 0 3417 +3597 0 3417 +3595 0 3415 +3593 0 3413 +3589 0 3409 +3587 0 3405 +3581 0 3399 +3573 0 3391 +3565 0 3379 +3551 0 3365 +3533 1393 3345 +3509 1959 3315 +3473 2263 3271 +3419 2491 3207 +3339 2685 3103 +3199 2857 2913 +2901 3017 2375 +0 3169 0 +0 3317 0 +0 3459 0 +0 3599 0 +0 3737 0 +0 3873 0 +0 4007 0 +3733 0 3553 +3733 0 3553 +3733 0 3553 +3733 0 3553 +3731 0 3553 +3731 0 3551 +3731 0 3551 +3731 0 3551 +3731 0 3551 +3729 0 3549 +3729 0 3547 +3727 0 3545 +3725 0 3543 +3721 0 3541 +3717 0 3535 +3713 0 3531 +3705 0 3521 +3697 0 3511 +3683 0 3495 +3665 1513 3475 +3641 2087 3445 +3605 2393 3403 +3551 2623 3337 +3469 2817 3233 +3331 2989 3043 +3033 3149 2497 +0 3301 0 +0 3449 0 +0 3591 0 +0 3731 0 +0 3869 0 +0 4005 0 +3865 0 3685 +3865 0 3685 +3865 0 3683 +3865 0 3683 +3865 0 3683 +3863 0 3683 +3863 0 3683 +3863 0 3683 +3863 0 3683 +3863 0 3681 +3861 0 3681 +3861 0 3679 +3859 0 3677 +3857 0 3675 +3853 0 3671 +3849 0 3667 +3845 0 3661 +3837 0 3653 +3829 0 3643 +3815 0 3627 +3797 1635 3607 +3773 2217 3577 +3737 2525 3533 +3683 2755 3469 +3601 2947 3365 +3461 3121 3173 +3163 3281 2621 +0 3433 0 +0 3581 0 +0 3723 0 +0 3863 0 +0 4001 0 +3997 0 3815 +3997 0 3815 +3997 0 3815 +3997 0 3815 +3997 0 3815 +3997 0 3815 +3995 0 3815 +3995 0 3815 +3995 0 3815 +3995 0 3813 +3995 0 3813 +3993 0 3813 +3993 0 3811 +3991 0 3809 +3989 0 3807 +3985 0 3803 +3981 0 3799 +3977 0 3793 +3969 0 3785 +3961 0 3773 +3947 0 3759 +3929 1759 3737 +3905 2347 3707 +3869 2655 3665 +3815 2885 3599 +3733 3079 3495 +3593 3253 3303 +3295 3413 2749 +0 3565 0 +0 3713 0 +0 3855 0 +0 3995 0 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3945 +4095 0 3945 +4095 0 3943 +4095 0 3943 +4095 0 3941 +4095 0 3939 +4095 0 3935 +4095 0 3931 +4095 0 3925 +4095 0 3917 +4093 0 3905 +4079 0 3891 +4061 1886 3869 +4037 2477 3839 +4001 2787 3797 +3947 3017 3731 +3865 3211 3627 +3725 3385 3435 +3427 3545 2877 +0 3697 0 +0 3845 0 +0 3987 0 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4077 +4095 0 4077 +4095 0 4077 +4095 0 4075 +4095 0 4075 +4095 0 4073 +4095 0 4069 +4095 0 4067 +4095 0 4063 +4095 0 4057 +4095 0 4049 +4095 0 4037 +4095 0 4023 +4095 2014 4001 +4095 2609 3971 +4095 2919 3929 +4079 3149 3863 +3997 3343 3759 +3857 3517 3565 +3559 3677 3005 +0 3829 0 +0 3977 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 2143 4095 +4095 2741 4095 +4095 3051 4059 +4095 3281 3995 +4095 3475 3891 +3989 3649 3697 +3691 3809 3135 +0 3961 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 2273 4095 +4095 2871 4095 +4095 3183 4095 +4095 3413 4095 +4095 3607 4021 +4095 3781 3829 +3823 3941 3265 +1004 617 1393 +969 649 1381 +916 689 1366 +836 737 1344 +699 794 1313 +412 861 1269 +0 937 1201 +0 1022 1091 +0 1116 884 +0 1217 213 +0 1324 0 +0 1437 0 +0 1554 0 +0 1675 0 +0 1798 0 +0 1923 0 +0 2051 0 +0 2179 0 +0 2307 0 +0 2437 0 +0 2569 0 +0 2699 0 +0 2831 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1045 612 1405 +1013 645 1394 +966 685 1379 +895 733 1358 +777 791 1328 +549 858 1284 +0 935 1219 +0 1020 1114 +0 1114 920 +0 1216 354 +0 1323 0 +0 1436 0 +0 1554 0 +0 1674 0 +0 1798 0 +0 1923 0 +0 2051 0 +0 2179 0 +0 2307 0 +0 2437 0 +0 2569 0 +0 2699 0 +0 2831 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1095 605 1421 +1066 638 1410 +1025 679 1395 +963 728 1375 +864 786 1346 +684 854 1305 +209 931 1243 +0 1018 1144 +0 1112 965 +0 1214 493 +0 1322 0 +0 1435 0 +0 1553 0 +0 1674 0 +0 1797 0 +0 1923 0 +0 2049 0 +0 2179 0 +0 2307 0 +0 2437 0 +0 2569 0 +0 2699 0 +0 2831 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1154 596 1441 +1129 629 1431 +1093 671 1417 +1040 721 1397 +958 780 1370 +818 848 1331 +519 927 1272 +0 1014 1180 +0 1109 1018 +0 1211 630 +0 1320 0 +0 1434 0 +0 1552 0 +0 1673 0 +0 1796 0 +0 1922 0 +0 2049 0 +0 2179 0 +0 2307 0 +0 2437 0 +0 2569 0 +0 2699 0 +0 2831 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1223 583 1467 +1202 617 1457 +1171 660 1444 +1127 711 1426 +1060 771 1400 +952 841 1363 +750 920 1309 +121 1009 1225 +0 1105 1081 +0 1208 765 +0 1317 0 +0 1432 0 +0 1550 0 +0 1671 0 +0 1796 0 +0 1922 0 +0 2049 0 +0 2177 0 +0 2307 0 +0 2437 0 +0 2567 0 +0 2699 0 +0 2831 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1301 565 1499 +1283 601 1490 +1258 645 1478 +1222 697 1461 +1168 759 1437 +1085 831 1404 +944 912 1354 +639 1002 1279 +0 1099 1153 +0 1204 900 +0 1314 0 +0 1429 0 +0 1548 0 +0 1670 0 +0 1794 0 +0 1921 0 +0 2049 0 +0 2177 0 +0 2307 0 +0 2437 0 +0 2567 0 +0 2699 0 +0 2831 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1389 540 1539 +1374 578 1531 +1353 624 1520 +1324 679 1504 +1282 743 1483 +1219 817 1452 +1117 900 1408 +933 992 1342 +429 1091 1234 +0 1197 1034 +0 1309 419 +0 1425 0 +0 1545 0 +0 1668 0 +0 1793 0 +0 1919 0 +0 2047 0 +0 2177 0 +0 2307 0 +0 2437 0 +0 2567 0 +0 2699 0 +0 2829 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1484 504 1587 +1472 545 1580 +1456 594 1570 +1432 652 1556 +1400 721 1537 +1351 798 1510 +1278 885 1472 +1157 979 1415 +917 1081 1325 +0 1189 1167 +0 1303 802 +0 1420 0 +0 1541 0 +0 1665 0 +0 1790 0 +0 1918 0 +0 2046 0 +0 2175 0 +0 2305 0 +0 2437 0 +0 2567 0 +0 2699 0 +0 2829 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1587 451 1645 +1577 497 1639 +1564 551 1630 +1546 615 1618 +1520 688 1601 +1484 771 1578 +1430 862 1545 +1347 961 1497 +1204 1067 1423 +896 1178 1301 +0 1294 1059 +0 1414 0 +0 1536 0 +0 1661 0 +0 1788 0 +0 1915 0 +0 2044 0 +0 2175 0 +0 2305 0 +0 2435 0 +0 2567 0 +0 2697 0 +0 2829 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1695 369 1712 +1688 423 1707 +1678 486 1699 +1664 559 1689 +1644 641 1675 +1617 732 1655 +1577 831 1627 +1518 936 1587 +1425 1047 1528 +1261 1163 1434 +865 1282 1266 +0 1404 856 +0 1529 0 +0 1656 0 +0 1784 0 +0 1912 0 +0 2042 0 +0 2173 0 +0 2303 0 +0 2435 0 +0 2565 0 +0 2697 0 +0 2829 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1809 230 1789 +1803 301 1784 +1795 382 1778 +1785 472 1769 +1770 570 1757 +1749 675 1741 +1720 785 1718 +1678 900 1686 +1614 1019 1638 +1513 1141 1566 +1328 1266 1448 +821 1392 1216 +0 1520 219 +0 1649 0 +0 1778 0 +0 1908 0 +0 2039 0 +0 2171 0 +0 2301 0 +0 2433 0 +0 2565 0 +0 2697 0 +0 2829 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1927 0 1875 +1923 61 1871 +1917 191 1865 +1908 322 1858 +1897 453 1849 +1881 584 1835 +1860 716 1817 +1829 847 1791 +1785 979 1754 +1717 1111 1699 +1608 1243 1613 +1404 1375 1466 +754 1507 1139 +0 1639 0 +0 1771 0 +0 1903 0 +0 2035 0 +0 2167 0 +0 2299 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +2049 0 1969 +2045 0 1966 +2040 0 1961 +2034 0 1955 +2025 225 1948 +2014 425 1937 +1998 602 1922 +1975 765 1902 +1943 919 1873 +1897 1067 1831 +1827 1210 1769 +1711 1351 1669 +1489 1489 1489 +646 1625 1009 +0 1761 0 +0 1896 0 +0 2029 0 +0 2163 0 +0 2297 0 +0 2429 0 +0 2561 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3355 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +2173 0 2071 +2169 0 2067 +2165 0 2065 +2161 0 2059 +2155 0 2053 +2145 53 2045 +2135 386 2033 +2117 625 2017 +2095 824 1995 +2061 1000 1964 +2014 1162 1918 +1941 1316 1848 +1820 1464 1735 +1582 1607 1518 +443 1747 744 +0 1885 0 +0 2022 0 +0 2157 0 +0 2291 0 +0 2425 0 +0 2559 0 +0 2693 0 +0 2825 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3355 0 +0 3487 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +2297 0 2177 +2295 0 2175 +2293 0 2173 +2289 0 2169 +2285 0 2165 +2279 0 2159 +2269 0 2149 +2257 327 2137 +2241 655 2119 +2217 892 2097 +2183 1090 2063 +2135 1265 2013 +2059 1428 1937 +1934 1581 1810 +1683 1728 1554 +0 1871 0 +0 2012 0 +0 2149 0 +0 2287 0 +0 2421 0 +0 2557 0 +0 2691 0 +0 2823 0 +0 2957 0 +0 3089 0 +0 3223 0 +0 3355 0 +0 3487 0 +0 3619 0 +0 3753 0 +0 3885 0 +0 4017 0 +2425 0 2291 +2423 0 2289 +2421 0 2287 +2419 0 2285 +2415 0 2281 +2411 0 2275 +2403 0 2269 +2395 0 2259 +2383 234 2247 +2365 691 2229 +2341 970 2203 +2307 1188 2167 +2257 1374 2115 +2181 1544 2033 +2051 1702 1894 +1790 1852 1599 +0 1998 0 +0 2139 0 +0 2279 0 +0 2417 0 +0 2553 0 +0 2687 0 +0 2821 0 +0 2955 0 +0 3089 0 +0 3221 0 +0 3355 0 +0 3487 0 +0 3619 0 +0 3751 0 +0 3885 0 +0 4017 0 +2553 0 2409 +2553 0 2407 +2551 0 2405 +2549 0 2403 +2547 0 2401 +2543 0 2397 +2537 0 2391 +2531 0 2383 +2521 0 2375 +2509 69 2361 +2491 735 2343 +2467 1057 2315 +2433 1292 2279 +2383 1489 2223 +2305 1663 2137 +2173 1825 1987 +1903 1978 1652 +0 2125 0 +0 2269 0 +0 2409 0 +0 2547 0 +0 2683 0 +0 2819 0 +0 2953 0 +0 3087 0 +0 3221 0 +0 3353 0 +0 3487 0 +0 3619 0 +0 3751 0 +0 3883 0 +0 4017 0 +2683 0 2529 +2683 0 2527 +2681 0 2527 +2679 0 2525 +2677 0 2523 +2675 0 2519 +2671 0 2515 +2667 0 2511 +2659 0 2503 +2651 0 2493 +2637 0 2479 +2619 789 2459 +2595 1152 2433 +2561 1403 2395 +2509 1607 2337 +2431 1786 2245 +2297 1951 2087 +2020 2105 1715 +0 2253 0 +0 2397 0 +0 2539 0 +0 2677 0 +0 2815 0 +0 2949 0 +0 3085 0 +0 3219 0 +0 3351 0 +0 3485 0 +0 3619 0 +0 3751 0 +0 3883 0 +0 4015 0 +2813 0 2653 +2813 0 2651 +2811 0 2651 +2811 0 2649 +2809 0 2647 +2807 0 2645 +2805 0 2643 +2801 0 2639 +2795 0 2633 +2789 0 2625 +2779 0 2615 +2767 0 2601 +2749 852 2581 +2725 1254 2553 +2689 1518 2513 +2637 1728 2455 +2557 1911 2361 +2423 2077 2193 +2141 2235 1787 +0 2383 0 +0 2529 0 +0 2669 0 +0 2809 0 +0 2945 0 +0 3081 0 +0 3217 0 +0 3351 0 +0 3483 0 +0 3617 0 +0 3751 0 +0 3883 0 +0 4015 0 +2943 0 2777 +2943 0 2777 +2943 0 2777 +2941 0 2775 +2941 0 2775 +2939 0 2773 +2937 0 2771 +2935 0 2767 +2931 0 2763 +2925 0 2757 +2919 0 2749 +2909 0 2739 +2897 0 2725 +2879 924 2705 +2855 1363 2677 +2819 1637 2635 +2767 1852 2575 +2687 2038 2479 +2549 2207 2305 +2263 2363 1869 +0 2513 0 +0 2659 0 +0 2801 0 +0 2939 0 +0 3077 0 +0 3213 0 +0 3347 0 +0 3483 0 +0 3615 0 +0 3749 0 +0 3883 0 +0 4015 0 +3075 0 2905 +3075 0 2905 +3073 0 2903 +3073 0 2903 +3073 0 2903 +3071 0 2901 +3069 0 2899 +3067 0 2897 +3065 0 2893 +3061 0 2889 +3055 0 2883 +3049 0 2875 +3039 0 2865 +3027 0 2851 +3009 1006 2831 +2985 1476 2801 +2949 1759 2761 +2897 1978 2699 +2815 2165 2601 +2679 2335 2423 +2389 2493 1959 +0 2645 0 +0 2791 0 +0 2931 0 +0 3071 0 +0 3209 0 +0 3345 0 +0 3479 0 +0 3615 0 +0 3747 0 +0 3881 0 +0 4015 0 +3205 0 3033 +3205 0 3033 +3205 0 3033 +3205 0 3031 +3205 0 3031 +3203 0 3031 +3203 0 3029 +3201 0 3027 +3199 0 3025 +3195 0 3021 +3193 0 3017 +3187 0 3011 +3181 0 3003 +3171 0 2993 +3157 0 2979 +3141 1096 2957 +3115 1594 2929 +3079 1883 2887 +3027 2105 2825 +2945 2295 2725 +2807 2465 2543 +2515 2625 2057 +0 2775 0 +0 2921 0 +0 3063 0 +0 3203 0 +0 3341 0 +0 3477 0 +0 3611 0 +0 3747 0 +0 3879 0 +0 4013 0 +3337 0 3163 +3337 0 3163 +3337 0 3161 +3337 0 3161 +3337 0 3161 +3335 0 3161 +3335 0 3159 +3333 0 3157 +3331 0 3155 +3329 0 3153 +3327 0 3151 +3323 0 3147 +3319 0 3141 +3311 0 3133 +3301 0 3121 +3289 0 3107 +3271 1194 3087 +3247 1715 3057 +3211 2010 3015 +3157 2233 2951 +3077 2425 2851 +2937 2595 2665 +2645 2755 2161 +0 2907 0 +0 3053 0 +0 3195 0 +0 3335 0 +0 3473 0 +0 3609 0 +0 3743 0 +0 3879 0 +0 4011 0 +3469 0 3293 +3469 0 3293 +3469 0 3291 +3469 0 3291 +3469 0 3291 +3467 0 3291 +3467 0 3289 +3467 0 3289 +3465 0 3287 +3463 0 3285 +3461 0 3283 +3459 0 3281 +3455 0 3275 +3449 0 3269 +3443 0 3263 +3433 0 3251 +3421 0 3237 +3403 1299 3215 +3377 1839 3187 +3341 2137 3143 +3289 2363 3079 +3207 2555 2977 +3069 2727 2791 +2773 2887 2273 +0 3039 0 +0 3185 0 +0 3327 0 +0 3467 0 +0 3605 0 +0 3741 0 +0 3875 0 +0 4011 0 +3601 0 3423 +3601 0 3423 +3601 0 3423 +3601 0 3423 +3601 0 3421 +3599 0 3421 +3599 0 3421 +3599 0 3421 +3597 0 3419 +3597 0 3417 +3595 0 3417 +3593 0 3413 +3591 0 3411 +3587 0 3407 +3581 0 3401 +3575 0 3393 +3565 0 3381 +3553 0 3367 +3535 1410 3345 +3509 1964 3317 +3473 2267 3273 +3421 2493 3209 +3339 2685 3107 +3199 2857 2917 +2903 3019 2389 +0 3169 0 +0 3317 0 +0 3459 0 +0 3599 0 +0 3737 0 +0 3873 0 +0 4007 0 +3733 0 3553 +3733 0 3553 +3733 0 3553 +3733 0 3553 +3733 0 3553 +3731 0 3553 +3731 0 3553 +3731 0 3551 +3731 0 3551 +3729 0 3551 +3729 0 3549 +3727 0 3547 +3725 0 3545 +3721 0 3541 +3719 0 3537 +3713 0 3531 +3707 0 3523 +3697 0 3513 +3683 0 3497 +3665 1525 3477 +3641 2091 3447 +3605 2395 3403 +3553 2625 3339 +3471 2817 3235 +3331 2989 3045 +3033 3149 2507 +0 3301 0 +0 3449 0 +0 3591 0 +0 3731 0 +0 3869 0 +0 4005 0 +3865 0 3685 +3865 0 3685 +3865 0 3685 +3865 0 3685 +3865 0 3685 +3865 0 3685 +3863 0 3683 +3863 0 3683 +3863 0 3683 +3863 0 3683 +3861 0 3681 +3861 0 3679 +3859 0 3679 +3857 0 3675 +3853 0 3673 +3851 0 3669 +3845 0 3663 +3837 0 3655 +3829 0 3643 +3815 0 3629 +3797 1645 3607 +3773 2221 3577 +3737 2527 3535 +3683 2755 3469 +3601 2949 3367 +3463 3121 3175 +3165 3281 2629 +0 3433 0 +0 3581 0 +0 3723 0 +0 3863 0 +0 4001 0 +3997 0 3817 +3997 0 3817 +3997 0 3817 +3997 0 3817 +3997 0 3815 +3997 0 3815 +3995 0 3815 +3995 0 3815 +3995 0 3815 +3995 0 3815 +3995 0 3813 +3993 0 3813 +3993 0 3811 +3991 0 3809 +3989 0 3807 +3985 0 3803 +3981 0 3799 +3977 0 3793 +3969 0 3785 +3961 0 3775 +3947 0 3759 +3929 1767 3739 +3905 2349 3709 +3869 2657 3665 +3815 2887 3601 +3733 3079 3497 +3593 3253 3305 +3295 3413 2755 +0 3565 0 +0 3713 0 +0 3855 0 +0 3995 0 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3945 +4095 0 3945 +4095 0 3945 +4095 0 3943 +4095 0 3941 +4095 0 3939 +4095 0 3935 +4095 0 3931 +4095 0 3925 +4095 0 3917 +4093 0 3907 +4079 0 3891 +4061 1892 3869 +4037 2479 3841 +4001 2787 3797 +3947 3017 3733 +3865 3211 3627 +3725 3385 3435 +3427 3545 2881 +0 3697 0 +0 3845 0 +0 3987 0 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4077 +4095 0 4077 +4095 0 4075 +4095 0 4075 +4095 0 4073 +4095 0 4071 +4095 0 4067 +4095 0 4063 +4095 0 4057 +4095 0 4049 +4095 0 4037 +4095 0 4023 +4095 2018 4001 +4095 2611 3971 +4095 2919 3929 +4079 3149 3863 +3997 3343 3759 +3857 3517 3567 +3559 3677 3009 +0 3829 0 +0 3977 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 2145 4095 +4095 2741 4095 +4095 3051 4061 +4095 3281 3995 +4095 3475 3891 +3989 3649 3697 +3691 3809 3137 +0 3961 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 2275 4095 +4095 2873 4095 +4095 3183 4095 +4095 3413 4095 +4095 3607 4023 +4095 3781 3829 +3823 3941 3267 +1129 728 1524 +1102 753 1516 +1064 785 1504 +1008 824 1488 +919 872 1466 +763 929 1434 +407 995 1388 +0 1071 1319 +0 1156 1205 +0 1249 987 +0 1350 201 +0 1457 0 +0 1570 0 +0 1687 0 +0 1807 0 +0 1930 0 +0 2055 0 +0 2183 0 +0 2311 0 +0 2441 0 +0 2571 0 +0 2701 0 +0 2831 0 +0 2963 0 +0 3095 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1161 724 1533 +1136 750 1525 +1100 782 1514 +1048 821 1498 +968 869 1476 +832 926 1445 +544 993 1401 +0 1069 1333 +0 1154 1223 +0 1248 1016 +0 1349 345 +0 1456 0 +0 1569 0 +0 1686 0 +0 1807 0 +0 1930 0 +0 2055 0 +0 2183 0 +0 2311 0 +0 2441 0 +0 2569 0 +0 2701 0 +0 2831 0 +0 2963 0 +0 3095 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1200 719 1545 +1177 745 1537 +1145 777 1526 +1098 817 1511 +1026 865 1490 +909 923 1460 +681 990 1417 +0 1066 1351 +0 1152 1246 +0 1246 1052 +0 1348 486 +0 1455 0 +0 1568 0 +0 1686 0 +0 1806 0 +0 1930 0 +0 2055 0 +0 2183 0 +0 2311 0 +0 2439 0 +0 2569 0 +0 2701 0 +0 2831 0 +0 2963 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1248 711 1561 +1227 738 1553 +1198 770 1542 +1157 811 1528 +1095 860 1507 +996 918 1478 +816 986 1437 +341 1063 1375 +0 1149 1276 +0 1244 1097 +0 1346 625 +0 1454 0 +0 1567 0 +0 1685 0 +0 1806 0 +0 1929 0 +0 2055 0 +0 2183 0 +0 2311 0 +0 2439 0 +0 2569 0 +0 2701 0 +0 2831 0 +0 2963 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1304 701 1581 +1286 728 1573 +1261 762 1563 +1225 803 1549 +1172 853 1530 +1090 912 1502 +951 981 1463 +651 1058 1405 +0 1146 1312 +0 1241 1150 +0 1343 762 +0 1452 0 +0 1566 0 +0 1684 0 +0 1805 0 +0 1929 0 +0 2055 0 +0 2181 0 +0 2311 0 +0 2439 0 +0 2569 0 +0 2701 0 +0 2831 0 +0 2963 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1371 688 1606 +1355 715 1599 +1334 750 1589 +1303 792 1576 +1259 843 1558 +1192 903 1532 +1084 973 1496 +882 1052 1441 +253 1140 1357 +0 1237 1213 +0 1340 897 +0 1449 0 +0 1564 0 +0 1682 0 +0 1804 0 +0 1928 0 +0 2053 0 +0 2181 0 +0 2309 0 +0 2439 0 +0 2569 0 +0 2701 0 +0 2831 0 +0 2963 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1447 669 1638 +1434 697 1631 +1416 733 1622 +1390 777 1610 +1354 829 1593 +1301 891 1569 +1218 963 1536 +1076 1044 1486 +771 1134 1411 +0 1231 1285 +0 1336 1032 +0 1446 0 +0 1561 0 +0 1680 0 +0 1802 0 +0 1926 0 +0 2053 0 +0 2181 0 +0 2309 0 +0 2439 0 +0 2569 0 +0 2699 0 +0 2831 0 +0 2963 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1532 642 1677 +1521 672 1671 +1506 710 1663 +1485 756 1652 +1456 811 1636 +1414 875 1615 +1351 949 1585 +1249 1032 1541 +1065 1124 1474 +561 1224 1367 +0 1330 1166 +0 1441 551 +0 1557 0 +0 1677 0 +0 1800 0 +0 1925 0 +0 2051 0 +0 2179 0 +0 2309 0 +0 2439 0 +0 2569 0 +0 2699 0 +0 2831 0 +0 2963 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1625 603 1725 +1616 636 1720 +1604 677 1712 +1588 726 1702 +1565 785 1688 +1532 853 1669 +1484 930 1643 +1410 1017 1604 +1289 1111 1547 +1049 1213 1457 +0 1321 1300 +0 1435 934 +0 1552 0 +0 1673 0 +0 1797 0 +0 1923 0 +0 2049 0 +0 2179 0 +0 2307 0 +0 2437 0 +0 2569 0 +0 2699 0 +0 2831 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1726 546 1782 +1719 583 1777 +1709 629 1771 +1696 683 1762 +1678 747 1750 +1653 820 1733 +1616 903 1710 +1563 994 1677 +1479 1093 1629 +1336 1199 1555 +1028 1310 1433 +0 1426 1191 +0 1546 0 +0 1668 0 +0 1793 0 +0 1920 0 +0 2047 0 +0 2177 0 +0 2307 0 +0 2437 0 +0 2567 0 +0 2699 0 +0 2829 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1833 456 1848 +1827 501 1844 +1820 555 1839 +1810 618 1831 +1796 691 1821 +1776 774 1807 +1749 864 1787 +1709 963 1759 +1650 1068 1719 +1558 1179 1660 +1393 1295 1566 +997 1414 1398 +0 1537 988 +0 1661 0 +0 1788 0 +0 1916 0 +0 2045 0 +0 2175 0 +0 2305 0 +0 2435 0 +0 2567 0 +0 2697 0 +0 2829 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1946 299 1925 +1941 362 1921 +1935 433 1916 +1928 514 1910 +1917 604 1901 +1902 702 1889 +1881 807 1873 +1852 917 1850 +1810 1032 1818 +1746 1151 1771 +1645 1273 1698 +1460 1398 1580 +953 1524 1348 +0 1652 351 +0 1781 0 +0 1910 0 +0 2041 0 +0 2171 0 +0 2303 0 +0 2433 0 +0 2565 0 +0 2697 0 +0 2829 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +2063 0 2010 +2059 63 2007 +2055 193 2003 +2049 323 1998 +2040 454 1990 +2029 585 1981 +2014 716 1967 +1992 848 1949 +1961 979 1923 +1917 1111 1886 +1850 1243 1831 +1740 1375 1745 +1536 1507 1598 +886 1639 1271 +0 1771 0 +0 1903 0 +0 2035 0 +0 2167 0 +0 2299 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +2183 0 2103 +2181 0 2101 +2177 0 2097 +2173 0 2093 +2167 115 2087 +2157 358 2079 +2145 557 2069 +2129 734 2055 +2107 897 2034 +2075 1051 2005 +2029 1199 1964 +1959 1342 1901 +1843 1483 1801 +1621 1621 1621 +778 1758 1141 +0 1893 0 +0 2028 0 +0 2161 0 +0 2295 0 +0 2429 0 +0 2561 0 +0 2693 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3355 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +2307 0 2205 +2305 0 2203 +2301 0 2199 +2299 0 2197 +2293 0 2191 +2287 0 2185 +2279 185 2177 +2267 518 2165 +2249 757 2149 +2227 956 2127 +2193 1132 2095 +2145 1295 2051 +2073 1448 1981 +1952 1596 1867 +1714 1739 1650 +575 1879 876 +0 2018 0 +0 2155 0 +0 2289 0 +0 2425 0 +0 2559 0 +0 2691 0 +0 2825 0 +0 2957 0 +0 3091 0 +0 3223 0 +0 3355 0 +0 3487 0 +0 3619 0 +0 3753 0 +0 3885 0 +0 4017 0 +2431 0 2311 +2429 0 2309 +2427 0 2307 +2425 0 2305 +2421 0 2301 +2417 0 2297 +2411 0 2291 +2401 0 2281 +2389 459 2269 +2373 787 2251 +2349 1024 2229 +2315 1222 2195 +2267 1398 2145 +2191 1560 2069 +2065 1713 1942 +1815 1860 1686 +0 2004 0 +0 2143 0 +0 2281 0 +0 2419 0 +0 2553 0 +0 2689 0 +0 2823 0 +0 2955 0 +0 3089 0 +0 3221 0 +0 3355 0 +0 3487 0 +0 3619 0 +0 3751 0 +0 3885 0 +0 4017 0 +2559 0 2425 +2557 0 2423 +2555 0 2421 +2553 0 2419 +2551 0 2417 +2547 0 2413 +2543 0 2407 +2535 0 2401 +2527 0 2391 +2515 366 2379 +2497 823 2361 +2473 1102 2335 +2439 1320 2299 +2389 1507 2247 +2313 1676 2165 +2183 1834 2026 +1923 1984 1731 +0 2129 0 +0 2271 0 +0 2411 0 +0 2549 0 +0 2685 0 +0 2819 0 +0 2953 0 +0 3087 0 +0 3221 0 +0 3353 0 +0 3487 0 +0 3619 0 +0 3751 0 +0 3883 0 +0 4017 0 +2687 0 2541 +2685 0 2541 +2685 0 2539 +2683 0 2537 +2681 0 2535 +2679 0 2533 +2675 0 2529 +2669 0 2523 +2663 0 2515 +2653 0 2507 +2641 201 2493 +2625 868 2475 +2599 1189 2449 +2565 1424 2411 +2515 1621 2355 +2437 1796 2269 +2305 1957 2119 +2035 2111 1784 +0 2257 0 +0 2401 0 +0 2541 0 +0 2679 0 +0 2815 0 +0 2951 0 +0 3085 0 +0 3219 0 +0 3353 0 +0 3485 0 +0 3619 0 +0 3751 0 +0 3883 0 +0 4015 0 +2815 0 2661 +2815 0 2661 +2815 0 2659 +2813 0 2659 +2811 0 2657 +2809 0 2655 +2807 0 2651 +2803 0 2647 +2799 0 2643 +2791 0 2635 +2783 0 2625 +2769 0 2611 +2753 921 2591 +2727 1284 2565 +2693 1535 2527 +2641 1739 2469 +2563 1918 2379 +2429 2083 2219 +2153 2237 1847 +0 2387 0 +0 2531 0 +0 2671 0 +0 2809 0 +0 2947 0 +0 3081 0 +0 3217 0 +0 3351 0 +0 3485 0 +0 3617 0 +0 3751 0 +0 3883 0 +0 4015 0 +2945 0 2785 +2945 0 2785 +2945 0 2783 +2943 0 2783 +2943 0 2781 +2941 0 2779 +2939 0 2777 +2937 0 2775 +2933 0 2771 +2927 0 2765 +2921 0 2757 +2911 0 2747 +2899 0 2733 +2881 984 2713 +2857 1386 2685 +2821 1650 2645 +2769 1860 2587 +2689 2043 2493 +2555 2209 2325 +2273 2367 1919 +0 2515 0 +0 2661 0 +0 2801 0 +0 2941 0 +0 3077 0 +0 3213 0 +0 3349 0 +0 3483 0 +0 3617 0 +0 3749 0 +0 3883 0 +0 4015 0 +3077 0 2911 +3075 0 2909 +3075 0 2909 +3075 0 2909 +3073 0 2907 +3073 0 2907 +3071 0 2905 +3069 0 2903 +3067 0 2899 +3063 0 2895 +3057 0 2889 +3051 0 2881 +3041 0 2871 +3029 0 2857 +3011 1056 2837 +2987 1495 2809 +2951 1769 2767 +2899 1984 2707 +2819 2169 2611 +2683 2339 2439 +2395 2495 2001 +0 2645 0 +0 2791 0 +0 2933 0 +0 3071 0 +0 3209 0 +0 3345 0 +0 3481 0 +0 3615 0 +0 3747 0 +0 3881 0 +0 4015 0 +3207 0 3037 +3207 0 3037 +3207 0 3037 +3207 0 3035 +3205 0 3035 +3205 0 3035 +3203 0 3033 +3201 0 3031 +3199 0 3029 +3197 0 3025 +3193 0 3021 +3189 0 3015 +3181 0 3007 +3171 0 2997 +3159 0 2983 +3141 1138 2963 +3117 1608 2933 +3081 1891 2893 +3029 2111 2831 +2947 2297 2733 +2811 2467 2555 +2521 2625 2091 +0 2777 0 +0 2923 0 +0 3065 0 +0 3203 0 +0 3341 0 +0 3477 0 +0 3611 0 +0 3747 0 +0 3879 0 +0 4013 0 +3339 0 3165 +3339 0 3165 +3337 0 3165 +3337 0 3165 +3337 0 3163 +3337 0 3163 +3335 0 3163 +3335 0 3161 +3333 0 3159 +3331 0 3157 +3327 0 3153 +3325 0 3149 +3319 0 3143 +3313 0 3135 +3303 0 3125 +3289 0 3111 +3273 1228 3089 +3247 1726 3061 +3211 2015 3019 +3159 2237 2957 +3077 2427 2857 +2941 2597 2675 +2649 2757 2189 +0 2907 0 +0 3053 0 +0 3195 0 +0 3335 0 +0 3473 0 +0 3609 0 +0 3743 0 +0 3879 0 +0 4013 0 +3469 0 3295 +3469 0 3295 +3469 0 3295 +3469 0 3293 +3469 0 3293 +3469 0 3293 +3467 0 3293 +3467 0 3291 +3465 0 3289 +3465 0 3289 +3461 0 3285 +3459 0 3283 +3455 0 3279 +3451 0 3273 +3443 0 3265 +3435 0 3253 +3421 0 3239 +3403 1326 3219 +3379 1847 3189 +3343 2141 3147 +3291 2365 3083 +3209 2557 2983 +3071 2727 2797 +2777 2887 2295 +0 3039 0 +0 3185 0 +0 3327 0 +0 3467 0 +0 3605 0 +0 3741 0 +0 3875 0 +0 4011 0 +3601 0 3425 +3601 0 3425 +3601 0 3425 +3601 0 3423 +3601 0 3423 +3601 0 3423 +3599 0 3423 +3599 0 3421 +3599 0 3421 +3597 0 3419 +3595 0 3417 +3593 0 3415 +3591 0 3413 +3587 0 3407 +3581 0 3403 +3575 0 3395 +3565 0 3383 +3553 0 3369 +3535 1431 3347 +3509 1971 3319 +3473 2269 3275 +3421 2495 3213 +3339 2687 3109 +3201 2859 2923 +2905 3019 2405 +0 3171 0 +0 3317 0 +0 3459 0 +0 3599 0 +0 3737 0 +0 3873 0 +0 4007 0 +3733 0 3555 +3733 0 3555 +3733 0 3555 +3733 0 3555 +3733 0 3555 +3733 0 3555 +3731 0 3553 +3731 0 3553 +3731 0 3553 +3729 0 3551 +3729 0 3551 +3727 0 3549 +3725 0 3545 +3723 0 3543 +3719 0 3539 +3713 0 3533 +3707 0 3525 +3697 0 3513 +3685 0 3499 +3667 1542 3477 +3641 2097 3449 +3605 2399 3405 +3553 2625 3341 +3471 2817 3239 +3331 2991 3049 +3035 3151 2521 +0 3303 0 +0 3449 0 +0 3591 0 +0 3731 0 +0 3869 0 +0 4005 0 +3865 0 3685 +3865 0 3685 +3865 0 3685 +3865 0 3685 +3865 0 3685 +3865 0 3685 +3865 0 3685 +3863 0 3685 +3863 0 3683 +3863 0 3683 +3861 0 3683 +3861 0 3681 +3859 0 3679 +3857 0 3677 +3855 0 3673 +3851 0 3669 +3845 0 3663 +3839 0 3655 +3829 0 3645 +3815 0 3629 +3797 1658 3609 +3773 2223 3579 +3737 2527 3535 +3685 2757 3471 +3603 2949 3369 +3463 3121 3177 +3165 3281 2639 +0 3433 0 +0 3581 0 +0 3723 0 +0 3863 0 +0 4001 0 +3997 0 3817 +3997 0 3817 +3997 0 3817 +3997 0 3817 +3997 0 3817 +3997 0 3817 +3997 0 3817 +3995 0 3817 +3995 0 3815 +3995 0 3815 +3995 0 3815 +3993 0 3813 +3993 0 3811 +3991 0 3811 +3989 0 3807 +3985 0 3805 +3983 0 3801 +3977 0 3795 +3971 0 3787 +3961 0 3775 +3947 0 3761 +3929 1777 3739 +3905 2353 3709 +3869 2659 3667 +3815 2887 3603 +3733 3081 3499 +3595 3253 3307 +3297 3413 2761 +0 3565 0 +0 3713 0 +0 3855 0 +0 3995 0 +4095 0 3949 +4095 0 3949 +4095 0 3949 +4095 0 3949 +4095 0 3949 +4095 0 3949 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3945 +4095 0 3945 +4095 0 3943 +4095 0 3941 +4095 0 3939 +4095 0 3935 +4095 0 3931 +4095 0 3925 +4095 0 3917 +4093 0 3907 +4079 0 3891 +4061 1899 3871 +4037 2481 3841 +4001 2789 3797 +3947 3019 3733 +3865 3211 3629 +3727 3385 3437 +3429 3545 2887 +0 3697 0 +0 3845 0 +0 3987 0 +4095 0 4081 +4095 0 4081 +4095 0 4081 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4077 +4095 0 4077 +4095 0 4075 +4095 0 4073 +4095 0 4071 +4095 0 4067 +4095 0 4063 +4095 0 4057 +4095 0 4049 +4095 0 4039 +4095 0 4023 +4095 2024 4001 +4095 2611 3973 +4095 2919 3929 +4079 3149 3865 +3997 3343 3759 +3857 3517 3567 +3559 3677 3013 +0 3829 0 +0 3977 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 2151 4095 +4095 2743 4095 +4095 3051 4061 +4095 3281 3995 +4095 3475 3891 +3989 3649 3699 +3691 3809 3141 +0 3961 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 2277 4095 +4095 2873 4095 +4095 3183 4095 +4095 3413 4095 +4095 3607 4023 +4095 3781 3829 +3823 3941 3269 +1256 844 1656 +1236 863 1649 +1208 888 1641 +1167 920 1629 +1106 959 1613 +1010 1006 1590 +837 1063 1558 +399 1129 1511 +0 1204 1440 +0 1289 1323 +0 1382 1096 +0 1483 185 +0 1590 0 +0 1702 0 +0 1819 0 +0 1940 0 +0 2063 0 +0 2189 0 +0 2315 0 +0 2443 0 +0 2573 0 +0 2703 0 +0 2833 0 +0 2963 0 +0 3095 0 +0 3227 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1280 840 1662 +1261 860 1656 +1234 886 1648 +1196 917 1636 +1139 957 1620 +1050 1004 1598 +896 1061 1566 +539 1127 1520 +0 1203 1451 +0 1288 1337 +0 1381 1119 +0 1482 333 +0 1589 0 +0 1702 0 +0 1819 0 +0 1939 0 +0 2063 0 +0 2187 0 +0 2315 0 +0 2443 0 +0 2573 0 +0 2703 0 +0 2833 0 +0 2963 0 +0 3095 0 +0 3227 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1310 836 1671 +1293 856 1665 +1268 882 1657 +1233 914 1646 +1180 953 1630 +1100 1001 1608 +964 1058 1578 +676 1125 1533 +0 1201 1465 +0 1286 1355 +0 1380 1148 +0 1481 478 +0 1589 0 +0 1701 0 +0 1818 0 +0 1939 0 +0 2063 0 +0 2187 0 +0 2315 0 +0 2443 0 +0 2573 0 +0 2703 0 +0 2833 0 +0 2963 0 +0 3095 0 +0 3227 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1348 831 1683 +1332 851 1677 +1309 877 1669 +1277 909 1658 +1230 949 1643 +1159 997 1622 +1041 1055 1592 +813 1122 1549 +0 1199 1483 +0 1284 1378 +0 1378 1184 +0 1480 618 +0 1588 0 +0 1701 0 +0 1818 0 +0 1938 0 +0 2061 0 +0 2187 0 +0 2315 0 +0 2443 0 +0 2573 0 +0 2703 0 +0 2833 0 +0 2963 0 +0 3095 0 +0 3227 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1394 823 1698 +1380 844 1693 +1359 870 1685 +1331 903 1674 +1289 943 1660 +1227 992 1639 +1128 1050 1611 +948 1118 1569 +474 1195 1507 +0 1282 1408 +0 1376 1229 +0 1478 757 +0 1586 0 +0 1699 0 +0 1817 0 +0 1938 0 +0 2061 0 +0 2187 0 +0 2315 0 +0 2443 0 +0 2571 0 +0 2701 0 +0 2833 0 +0 2963 0 +0 3095 0 +0 3227 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1449 812 1718 +1437 834 1713 +1419 860 1705 +1393 894 1695 +1358 935 1681 +1305 985 1662 +1222 1044 1634 +1082 1112 1595 +784 1191 1537 +0 1278 1445 +0 1373 1282 +0 1476 894 +0 1584 0 +0 1698 0 +0 1816 0 +0 1937 0 +0 2061 0 +0 2187 0 +0 2313 0 +0 2443 0 +0 2571 0 +0 2701 0 +0 2833 0 +0 2963 0 +0 3095 0 +0 3227 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1514 798 1743 +1503 820 1738 +1487 847 1731 +1466 882 1721 +1435 924 1708 +1391 975 1690 +1324 1035 1664 +1216 1105 1628 +1014 1184 1574 +385 1273 1489 +0 1369 1345 +0 1472 1029 +0 1582 0 +0 1696 0 +0 1814 0 +0 1936 0 +0 2059 0 +0 2185 0 +0 2313 0 +0 2441 0 +0 2571 0 +0 2701 0 +0 2833 0 +0 2963 0 +0 3095 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1588 778 1775 +1579 801 1770 +1566 829 1763 +1548 865 1754 +1522 909 1742 +1486 962 1725 +1433 1023 1702 +1350 1095 1668 +1208 1176 1619 +903 1266 1543 +0 1363 1417 +0 1468 1164 +0 1578 0 +0 1693 0 +0 1812 0 +0 1934 0 +0 2059 0 +0 2185 0 +0 2313 0 +0 2441 0 +0 2571 0 +0 2701 0 +0 2831 0 +0 2963 0 +0 3095 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1672 750 1814 +1664 774 1809 +1653 804 1803 +1638 842 1795 +1617 888 1784 +1588 943 1768 +1546 1007 1747 +1483 1081 1717 +1382 1164 1673 +1197 1256 1606 +693 1356 1499 +0 1462 1298 +0 1573 683 +0 1689 0 +0 1809 0 +0 1932 0 +0 2057 0 +0 2183 0 +0 2311 0 +0 2441 0 +0 2571 0 +0 2701 0 +0 2831 0 +0 2963 0 +0 3095 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1764 709 1861 +1757 735 1857 +1748 768 1852 +1736 809 1844 +1720 858 1834 +1697 917 1821 +1664 985 1801 +1616 1062 1775 +1542 1149 1736 +1421 1243 1679 +1181 1345 1589 +0 1454 1432 +0 1567 1066 +0 1685 0 +0 1805 0 +0 1929 0 +0 2055 0 +0 2181 0 +0 2311 0 +0 2439 0 +0 2569 0 +0 2701 0 +0 2831 0 +0 2963 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1863 648 1918 +1858 678 1914 +1851 715 1909 +1841 761 1903 +1828 815 1894 +1810 879 1882 +1785 953 1865 +1748 1035 1842 +1695 1126 1809 +1611 1225 1761 +1469 1331 1687 +1160 1442 1565 +0 1558 1323 +0 1678 55 +0 1800 0 +0 1925 0 +0 2051 0 +0 2179 0 +0 2309 0 +0 2439 0 +0 2569 0 +0 2699 0 +0 2831 0 +0 2963 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1969 552 1984 +1965 588 1981 +1960 633 1976 +1952 687 1971 +1942 751 1963 +1928 824 1953 +1908 906 1939 +1881 997 1919 +1841 1095 1891 +1783 1200 1852 +1690 1311 1792 +1526 1427 1698 +1129 1546 1531 +0 1669 1120 +0 1793 0 +0 1920 0 +0 2047 0 +0 2177 0 +0 2307 0 +0 2437 0 +0 2567 0 +0 2699 0 +0 2829 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +2081 379 2059 +2077 431 2057 +2073 494 2053 +2067 565 2049 +2059 647 2042 +2049 737 2033 +2034 834 2022 +2013 939 2005 +1984 1049 1982 +1942 1164 1950 +1879 1283 1903 +1777 1405 1831 +1592 1530 1712 +1085 1656 1480 +0 1784 483 +0 1913 0 +0 2042 0 +0 2173 0 +0 2303 0 +0 2435 0 +0 2565 0 +0 2697 0 +0 2829 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +2197 0 2143 +2195 67 2141 +2191 195 2139 +2187 325 2135 +2181 455 2129 +2173 586 2123 +2161 717 2113 +2145 848 2099 +2125 980 2081 +2093 1111 2055 +2049 1243 2018 +1982 1375 1963 +1873 1507 1878 +1668 1639 1730 +1018 1771 1403 +0 1903 0 +0 2035 0 +0 2167 0 +0 2299 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +2317 0 2237 +2315 0 2235 +2313 0 2233 +2309 0 2229 +2305 0 2225 +2299 247 2219 +2289 490 2211 +2279 689 2201 +2261 866 2187 +2239 1029 2167 +2207 1183 2137 +2161 1331 2095 +2091 1474 2033 +1975 1615 1934 +1753 1753 1753 +910 1890 1273 +0 2025 0 +0 2159 0 +0 2293 0 +0 2427 0 +0 2561 0 +0 2693 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3355 0 +0 3487 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +2439 0 2337 +2439 0 2337 +2437 0 2335 +2433 0 2331 +2431 0 2329 +2425 0 2323 +2419 0 2317 +2411 317 2309 +2399 650 2297 +2381 890 2281 +2359 1088 2259 +2325 1264 2229 +2279 1427 2183 +2205 1580 2113 +2085 1728 1999 +1846 1871 1782 +707 2011 1008 +0 2149 0 +0 2287 0 +0 2421 0 +0 2557 0 +0 2691 0 +0 2823 0 +0 2957 0 +0 3089 0 +0 3223 0 +0 3355 0 +0 3487 0 +0 3619 0 +0 3753 0 +0 3885 0 +0 4017 0 +2565 0 2445 +2563 0 2443 +2563 0 2443 +2561 0 2441 +2557 0 2437 +2553 0 2433 +2549 0 2429 +2543 0 2423 +2533 0 2413 +2521 591 2401 +2505 919 2385 +2481 1156 2361 +2447 1354 2327 +2399 1530 2277 +2323 1692 2201 +2199 1845 2075 +1947 1993 1818 +74 2135 0 +0 2275 0 +0 2415 0 +0 2551 0 +0 2687 0 +0 2821 0 +0 2955 0 +0 3087 0 +0 3221 0 +0 3355 0 +0 3487 0 +0 3619 0 +0 3751 0 +0 3885 0 +0 4017 0 +2691 0 2557 +2691 0 2557 +2689 0 2555 +2687 0 2553 +2685 0 2551 +2683 0 2549 +2679 0 2545 +2675 0 2539 +2669 0 2533 +2659 0 2523 +2647 498 2511 +2629 955 2493 +2605 1234 2467 +2571 1452 2431 +2521 1639 2379 +2445 1808 2297 +2315 1966 2159 +2055 2117 1863 +0 2261 0 +0 2403 0 +0 2543 0 +0 2681 0 +0 2817 0 +0 2951 0 +0 3085 0 +0 3219 0 +0 3353 0 +0 3485 0 +0 3619 0 +0 3751 0 +0 3883 0 +0 4017 0 +2819 0 2673 +2819 0 2673 +2817 0 2673 +2817 0 2671 +2815 0 2669 +2813 0 2667 +2811 0 2665 +2807 0 2661 +2801 0 2655 +2795 0 2649 +2787 0 2639 +2773 333 2625 +2757 1000 2607 +2731 1321 2581 +2697 1556 2543 +2647 1753 2487 +2569 1928 2401 +2437 2089 2251 +2167 2243 1916 +0 2389 0 +0 2533 0 +0 2673 0 +0 2811 0 +0 2947 0 +0 3083 0 +0 3217 0 +0 3351 0 +0 3485 0 +0 3617 0 +0 3751 0 +0 3883 0 +0 4015 0 +2949 0 2795 +2947 0 2793 +2947 0 2793 +2947 0 2793 +2945 0 2791 +2943 0 2789 +2941 0 2787 +2939 0 2783 +2935 0 2779 +2931 0 2775 +2923 0 2767 +2915 0 2757 +2901 0 2743 +2885 1053 2725 +2859 1416 2697 +2825 1667 2659 +2773 1871 2601 +2695 2051 2511 +2561 2215 2351 +2285 2369 1979 +0 2519 0 +0 2663 0 +0 2803 0 +0 2941 0 +0 3079 0 +0 3213 0 +0 3349 0 +0 3483 0 +0 3617 0 +0 3749 0 +0 3883 0 +0 4015 0 +3079 0 2917 +3077 0 2917 +3077 0 2917 +3077 0 2915 +3075 0 2915 +3075 0 2913 +3073 0 2911 +3071 0 2909 +3069 0 2907 +3065 0 2903 +3059 0 2897 +3053 0 2889 +3043 0 2879 +3031 0 2865 +3013 1116 2845 +2989 1518 2817 +2953 1782 2777 +2901 1992 2719 +2821 2175 2625 +2687 2341 2459 +2405 2499 2051 +0 2647 0 +0 2793 0 +0 2933 0 +0 3073 0 +0 3209 0 +0 3345 0 +0 3481 0 +0 3615 0 +0 3749 0 +0 3881 0 +0 4015 0 +3209 0 3043 +3209 0 3043 +3209 0 3041 +3207 0 3041 +3207 0 3041 +3207 0 3039 +3205 0 3039 +3203 0 3037 +3201 0 3035 +3199 0 3031 +3195 0 3027 +3189 0 3021 +3183 0 3013 +3173 0 3003 +3161 0 2989 +3143 1188 2969 +3119 1627 2941 +3083 1901 2901 +3031 2117 2839 +2951 2301 2743 +2815 2471 2571 +2527 2627 2133 +0 2777 0 +0 2923 0 +0 3065 0 +0 3203 0 +0 3341 0 +0 3477 0 +0 3613 0 +0 3747 0 +0 3881 0 +0 4013 0 +3339 0 3169 +3339 0 3169 +3339 0 3169 +3339 0 3169 +3339 0 3169 +3337 0 3167 +3337 0 3167 +3335 0 3165 +3333 0 3163 +3331 0 3161 +3329 0 3157 +3325 0 3153 +3321 0 3147 +3313 0 3141 +3305 0 3129 +3291 0 3115 +3273 1270 3095 +3249 1740 3067 +3213 2023 3025 +3161 2243 2963 +3079 2429 2865 +2943 2599 2687 +2653 2757 2223 +0 2909 0 +0 3055 0 +0 3197 0 +0 3335 0 +0 3473 0 +0 3609 0 +0 3745 0 +0 3879 0 +0 4013 0 +3471 0 3297 +3471 0 3297 +3471 0 3297 +3469 0 3297 +3469 0 3297 +3469 0 3297 +3469 0 3295 +3467 0 3295 +3467 0 3293 +3465 0 3291 +3463 0 3289 +3461 0 3285 +3457 0 3281 +3451 0 3275 +3445 0 3267 +3435 0 3257 +3423 0 3243 +3405 1360 3221 +3379 1858 3193 +3343 2147 3151 +3291 2369 3089 +3211 2559 2989 +3073 2729 2807 +2781 2889 2321 +0 3039 0 +0 3185 0 +0 3327 0 +0 3467 0 +0 3605 0 +0 3741 0 +0 3877 0 +0 4011 0 +3601 0 3427 +3601 0 3427 +3601 0 3427 +3601 0 3427 +3601 0 3427 +3601 0 3425 +3601 0 3425 +3599 0 3425 +3599 0 3423 +3597 0 3423 +3597 0 3421 +3595 0 3417 +3591 0 3415 +3587 0 3411 +3583 0 3405 +3575 0 3397 +3567 0 3385 +3553 0 3371 +3535 1458 3351 +3511 1979 3321 +3475 2273 3279 +3423 2499 3215 +3341 2689 3115 +3203 2861 2929 +2909 3019 2427 +0 3171 0 +0 3317 0 +0 3459 0 +0 3599 0 +0 3737 0 +0 3873 0 +0 4009 0 +3733 0 3557 +3733 0 3557 +3733 0 3557 +3733 0 3557 +3733 0 3557 +3733 0 3555 +3733 0 3555 +3731 0 3555 +3731 0 3555 +3731 0 3553 +3729 0 3551 +3727 0 3551 +3725 0 3547 +3723 0 3545 +3719 0 3541 +3713 0 3535 +3707 0 3527 +3697 0 3515 +3685 0 3501 +3667 1564 3479 +3641 2103 3451 +3607 2401 3409 +3553 2627 3345 +3471 2819 3243 +3333 2991 3055 +3037 3151 2537 +0 3303 0 +0 3449 0 +0 3591 0 +0 3731 0 +0 3869 0 +0 4005 0 +3865 0 3687 +3865 0 3687 +3865 0 3687 +3865 0 3687 +3865 0 3687 +3865 0 3687 +3865 0 3687 +3865 0 3685 +3863 0 3685 +3863 0 3685 +3863 0 3683 +3861 0 3683 +3859 0 3681 +3857 0 3677 +3855 0 3675 +3851 0 3671 +3845 0 3665 +3839 0 3657 +3829 0 3645 +3817 0 3631 +3799 1674 3609 +3773 2229 3581 +3737 2531 3537 +3685 2757 3473 +3603 2949 3371 +3463 3123 3181 +3167 3283 2653 +0 3435 0 +0 3581 0 +0 3723 0 +0 3863 0 +0 4001 0 +3997 0 3819 +3997 0 3819 +3997 0 3817 +3997 0 3817 +3997 0 3817 +3997 0 3817 +3997 0 3817 +3997 0 3817 +3995 0 3817 +3995 0 3817 +3995 0 3815 +3993 0 3815 +3993 0 3813 +3991 0 3811 +3989 0 3809 +3987 0 3805 +3983 0 3801 +3977 0 3795 +3971 0 3787 +3961 0 3777 +3949 0 3761 +3931 1790 3741 +3905 2355 3711 +3869 2661 3669 +3817 2889 3603 +3735 3081 3501 +3595 3253 3311 +3299 3413 2771 +0 3567 0 +0 3713 0 +0 3855 0 +0 3995 0 +4095 0 3949 +4095 0 3949 +4095 0 3949 +4095 0 3949 +4095 0 3949 +4095 0 3949 +4095 0 3949 +4095 0 3949 +4095 0 3949 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3945 +4095 0 3945 +4095 0 3943 +4095 0 3939 +4095 0 3937 +4095 0 3933 +4095 0 3927 +4095 0 3919 +4093 0 3907 +4079 0 3893 +4061 1909 3871 +4037 2485 3841 +4001 2791 3799 +3949 3019 3735 +3867 3213 3631 +3727 3385 3439 +3429 3545 2893 +0 3697 0 +0 3845 0 +0 3987 0 +4095 0 4081 +4095 0 4081 +4095 0 4081 +4095 0 4081 +4095 0 4081 +4095 0 4081 +4095 0 4081 +4095 0 4081 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4077 +4095 0 4077 +4095 0 4075 +4095 0 4073 +4095 0 4071 +4095 0 4069 +4095 0 4063 +4095 0 4057 +4095 0 4049 +4095 0 4039 +4095 0 4023 +4095 2031 4003 +4095 2613 3973 +4095 2921 3929 +4079 3151 3865 +3997 3343 3761 +3859 3517 3569 +3561 3677 3019 +0 3829 0 +0 3977 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 2155 4095 +4095 2743 4095 +4095 3053 4061 +4095 3283 3997 +4095 3475 3893 +3989 3649 3699 +3691 3809 3145 +0 3961 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 2283 4095 +4095 2875 4095 +4095 3183 4095 +4095 3413 4095 +4095 3607 4023 +4095 3781 3831 +3823 3941 3273 +1384 963 1787 +1369 978 1782 +1348 998 1776 +1319 1023 1767 +1276 1054 1755 +1212 1093 1739 +1109 1140 1716 +920 1196 1684 +388 1262 1636 +0 1338 1564 +0 1422 1444 +0 1515 1210 +0 1616 161 +0 1723 0 +0 1835 0 +0 1952 0 +0 2071 0 +0 2195 0 +0 2321 0 +0 2447 0 +0 2575 0 +0 2705 0 +0 2835 0 +0 2965 0 +0 3095 0 +0 3227 0 +0 3359 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1402 960 1792 +1388 976 1788 +1368 995 1781 +1340 1020 1773 +1299 1052 1761 +1238 1091 1745 +1142 1138 1722 +969 1195 1690 +531 1261 1643 +0 1337 1572 +0 1421 1455 +0 1514 1228 +0 1615 317 +0 1722 0 +0 1835 0 +0 1951 0 +0 2071 0 +0 2195 0 +0 2321 0 +0 2447 0 +0 2575 0 +0 2705 0 +0 2835 0 +0 2965 0 +0 3095 0 +0 3227 0 +0 3359 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1426 957 1799 +1412 973 1795 +1393 992 1788 +1367 1018 1780 +1328 1049 1768 +1272 1088 1752 +1183 1136 1730 +1027 1193 1699 +671 1259 1653 +0 1335 1583 +0 1420 1469 +0 1513 1251 +0 1614 465 +0 1722 0 +0 1834 0 +0 1951 0 +0 2071 0 +0 2195 0 +0 2319 0 +0 2447 0 +0 2575 0 +0 2705 0 +0 2835 0 +0 2965 0 +0 3095 0 +0 3227 0 +0 3359 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1455 953 1808 +1443 968 1804 +1425 988 1797 +1400 1014 1789 +1365 1046 1778 +1313 1085 1762 +1232 1133 1740 +1096 1190 1710 +809 1257 1665 +0 1333 1597 +0 1419 1487 +0 1512 1280 +0 1613 610 +0 1721 0 +0 1834 0 +0 1951 0 +0 2071 0 +0 2195 0 +0 2319 0 +0 2447 0 +0 2575 0 +0 2705 0 +0 2835 0 +0 2965 0 +0 3095 0 +0 3227 0 +0 3359 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1492 947 1820 +1480 963 1815 +1464 983 1809 +1441 1009 1801 +1409 1041 1790 +1362 1081 1775 +1291 1129 1754 +1173 1187 1724 +945 1254 1681 +8 1331 1616 +0 1416 1511 +0 1511 1317 +0 1612 750 +0 1720 0 +0 1833 0 +0 1950 0 +0 2071 0 +0 2195 0 +0 2319 0 +0 2447 0 +0 2575 0 +0 2705 0 +0 2835 0 +0 2965 0 +0 3095 0 +0 3227 0 +0 3359 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1537 939 1835 +1526 955 1831 +1512 976 1825 +1491 1002 1817 +1463 1034 1806 +1421 1075 1792 +1359 1124 1771 +1260 1182 1743 +1080 1250 1701 +606 1327 1639 +0 1414 1540 +0 1508 1361 +0 1610 889 +0 1718 0 +0 1832 0 +0 1949 0 +0 2069 0 +0 2193 0 +0 2319 0 +0 2447 0 +0 2575 0 +0 2705 0 +0 2835 0 +0 2965 0 +0 3095 0 +0 3227 0 +0 3359 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1591 928 1854 +1582 945 1850 +1569 966 1845 +1551 992 1837 +1526 1026 1827 +1490 1067 1813 +1437 1117 1794 +1354 1176 1767 +1215 1245 1727 +916 1323 1669 +0 1410 1577 +0 1505 1414 +0 1608 1026 +0 1716 0 +0 1830 0 +0 1948 0 +0 2069 0 +0 2193 0 +0 2319 0 +0 2445 0 +0 2575 0 +0 2703 0 +0 2833 0 +0 2965 0 +0 3095 0 +0 3227 0 +0 3359 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1654 913 1879 +1646 930 1875 +1635 952 1870 +1620 979 1863 +1598 1014 1854 +1568 1056 1840 +1523 1107 1822 +1457 1167 1796 +1348 1237 1760 +1146 1317 1706 +517 1405 1621 +0 1501 1477 +0 1604 1161 +0 1714 0 +0 1828 0 +0 1946 0 +0 2067 0 +0 2191 0 +0 2317 0 +0 2445 0 +0 2575 0 +0 2703 0 +0 2833 0 +0 2965 0 +0 3095 0 +0 3227 0 +0 3359 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1727 892 1910 +1720 910 1907 +1711 933 1902 +1698 962 1895 +1680 997 1886 +1654 1041 1874 +1618 1093 1857 +1565 1156 1834 +1482 1227 1800 +1340 1308 1751 +1035 1398 1675 +0 1495 1549 +0 1600 1296 +0 1710 0 +0 1825 0 +0 1944 0 +0 2067 0 +0 2191 0 +0 2317 0 +0 2445 0 +0 2573 0 +0 2703 0 +0 2833 0 +0 2965 0 +0 3095 0 +0 3227 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1810 863 1949 +1804 882 1946 +1796 906 1941 +1785 936 1935 +1770 974 1927 +1750 1020 1916 +1720 1075 1901 +1678 1139 1879 +1615 1213 1849 +1514 1297 1805 +1329 1388 1738 +825 1488 1631 +0 1594 1430 +0 1705 815 +0 1822 0 +0 1941 0 +0 2065 0 +0 2189 0 +0 2315 0 +0 2443 0 +0 2573 0 +0 2703 0 +0 2833 0 +0 2963 0 +0 3095 0 +0 3227 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1900 820 1996 +1896 841 1993 +1889 868 1989 +1880 900 1984 +1868 941 1976 +1852 990 1966 +1829 1049 1953 +1796 1117 1934 +1748 1194 1907 +1674 1281 1868 +1553 1375 1811 +1314 1477 1721 +121 1586 1564 +0 1699 1198 +0 1817 0 +0 1938 0 +0 2061 0 +0 2187 0 +0 2315 0 +0 2443 0 +0 2571 0 +0 2701 0 +0 2833 0 +0 2963 0 +0 3095 0 +0 3227 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1999 757 2053 +1995 780 2049 +1990 810 2046 +1983 848 2041 +1973 893 2035 +1960 947 2026 +1942 1011 2014 +1917 1084 1998 +1881 1167 1974 +1827 1258 1941 +1743 1357 1893 +1601 1463 1819 +1292 1574 1697 +0 1690 1455 +0 1810 187 +0 1932 0 +0 2057 0 +0 2183 0 +0 2311 0 +0 2441 0 +0 2571 0 +0 2701 0 +0 2831 0 +0 2963 0 +0 3095 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +2105 654 2119 +2101 684 2115 +2097 721 2113 +2091 765 2109 +2085 819 2103 +2075 883 2095 +2059 956 2085 +2040 1038 2071 +2013 1128 2051 +1974 1227 2024 +1915 1332 1984 +1822 1443 1924 +1658 1559 1830 +1261 1678 1663 +0 1801 1252 +0 1926 0 +0 2053 0 +0 2179 0 +0 2309 0 +0 2439 0 +0 2569 0 +0 2699 0 +0 2831 0 +0 2963 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +2215 467 2193 +2213 511 2191 +2209 563 2189 +2205 626 2185 +2199 698 2181 +2191 779 2175 +2181 869 2165 +2167 966 2153 +2145 1071 2137 +2117 1181 2115 +2075 1296 2083 +2011 1415 2035 +1909 1538 1963 +1724 1662 1844 +1217 1788 1612 +0 1916 615 +0 2045 0 +0 2175 0 +0 2305 0 +0 2435 0 +0 2567 0 +0 2697 0 +0 2829 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +2331 0 2277 +2329 71 2277 +2327 199 2273 +2323 327 2271 +2319 457 2267 +2313 587 2261 +2305 718 2255 +2293 849 2245 +2277 980 2231 +2257 1112 2213 +2225 1243 2187 +2181 1375 2151 +2113 1507 2095 +2005 1639 2010 +1800 1771 1862 +1150 1903 1535 +0 2035 0 +0 2167 0 +0 2299 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +2451 0 2371 +2449 0 2369 +2447 0 2367 +2445 0 2365 +2441 0 2361 +2437 40 2357 +2431 379 2351 +2421 622 2345 +2411 822 2333 +2395 999 2319 +2371 1161 2299 +2339 1315 2269 +2293 1463 2227 +2223 1606 2165 +2107 1747 2065 +1885 1885 1885 +1042 2022 1405 +0 2157 0 +0 2291 0 +0 2425 0 +0 2559 0 +0 2693 0 +0 2825 0 +0 2959 0 +0 3091 0 +0 3223 0 +0 3355 0 +0 3487 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +2573 0 2471 +2571 0 2469 +2571 0 2469 +2569 0 2467 +2565 0 2463 +2563 0 2461 +2557 0 2455 +2551 0 2449 +2543 449 2441 +2531 782 2429 +2513 1022 2413 +2491 1220 2391 +2459 1396 2361 +2411 1559 2315 +2337 1712 2245 +2217 1860 2131 +1979 2003 1914 +839 2143 1140 +0 2281 0 +0 2419 0 +0 2553 0 +0 2689 0 +0 2823 0 +0 2955 0 +0 3089 0 +0 3221 0 +0 3355 0 +0 3487 0 +0 3619 0 +0 3751 0 +0 3885 0 +0 4017 0 +2697 0 2577 +2697 0 2577 +2695 0 2575 +2695 0 2575 +2693 0 2573 +2689 0 2569 +2687 0 2565 +2681 0 2561 +2675 0 2555 +2665 12 2545 +2653 723 2533 +2637 1051 2517 +2613 1289 2493 +2579 1486 2459 +2531 1662 2409 +2455 1824 2333 +2331 1977 2207 +2079 2125 1951 +206 2267 0 +0 2409 0 +0 2547 0 +0 2683 0 +0 2819 0 +0 2953 0 +0 3087 0 +0 3221 0 +0 3353 0 +0 3487 0 +0 3619 0 +0 3751 0 +0 3883 0 +0 4017 0 +2825 0 2689 +2823 0 2689 +2823 0 2689 +2821 0 2687 +2821 0 2685 +2819 0 2683 +2815 0 2681 +2811 0 2677 +2807 0 2671 +2801 0 2665 +2791 0 2655 +2779 630 2643 +2761 1087 2625 +2737 1366 2599 +2703 1584 2563 +2653 1771 2511 +2577 1940 2429 +2449 2099 2291 +2187 2249 1995 +0 2395 0 +0 2535 0 +0 2675 0 +0 2813 0 +0 2949 0 +0 3083 0 +0 3217 0 +0 3351 0 +0 3485 0 +0 3617 0 +0 3751 0 +0 3883 0 +0 4015 0 +2953 0 2807 +2951 0 2807 +2951 0 2805 +2951 0 2805 +2949 0 2803 +2947 0 2801 +2945 0 2799 +2943 0 2797 +2939 0 2793 +2935 0 2787 +2927 0 2781 +2919 0 2771 +2905 465 2757 +2889 1132 2739 +2865 1453 2713 +2829 1689 2675 +2779 1885 2619 +2701 2059 2533 +2569 2221 2383 +2299 2375 2049 +0 2521 0 +0 2665 0 +0 2805 0 +0 2943 0 +0 3079 0 +0 3215 0 +0 3349 0 +0 3483 0 +0 3617 0 +0 3749 0 +0 3883 0 +0 4015 0 +3081 0 2927 +3081 0 2927 +3081 0 2925 +3079 0 2925 +3079 0 2925 +3077 0 2923 +3075 0 2921 +3073 0 2919 +3071 0 2917 +3067 0 2913 +3063 0 2907 +3055 0 2899 +3047 0 2889 +3033 66 2875 +3017 1185 2857 +2991 1548 2829 +2957 1799 2791 +2905 2003 2733 +2827 2183 2643 +2693 2347 2483 +2417 2501 2111 +0 2651 0 +0 2795 0 +0 2935 0 +0 3073 0 +0 3211 0 +0 3347 0 +0 3481 0 +0 3615 0 +0 3749 0 +0 3881 0 +0 4015 0 +3211 0 3049 +3211 0 3049 +3211 0 3049 +3209 0 3049 +3209 0 3047 +3209 0 3047 +3207 0 3045 +3205 0 3043 +3203 0 3041 +3201 0 3039 +3197 0 3035 +3191 0 3029 +3185 0 3021 +3175 0 3011 +3163 0 2997 +3145 1248 2977 +3121 1651 2949 +3085 1914 2909 +3033 2125 2851 +2955 2307 2757 +2819 2475 2591 +2537 2631 2183 +0 2779 0 +0 2925 0 +0 3065 0 +0 3205 0 +0 3341 0 +0 3477 0 +0 3613 0 +0 3747 0 +0 3881 0 +0 4013 0 +3341 0 3175 +3341 0 3175 +3341 0 3175 +3341 0 3173 +3339 0 3173 +3339 0 3173 +3339 0 3171 +3337 0 3171 +3335 0 3169 +3333 0 3167 +3331 0 3163 +3327 0 3159 +3321 0 3153 +3315 0 3145 +3305 0 3135 +3293 0 3121 +3275 1320 3101 +3251 1759 3073 +3215 2033 3033 +3163 2249 2971 +3083 2435 2875 +2947 2603 2703 +2661 2759 2265 +0 2911 0 +0 3055 0 +0 3197 0 +0 3337 0 +0 3473 0 +0 3609 0 +0 3745 0 +0 3879 0 +0 4013 0 +3471 0 3301 +3471 0 3301 +3471 0 3301 +3471 0 3301 +3471 0 3301 +3471 0 3301 +3469 0 3299 +3469 0 3299 +3467 0 3297 +3467 0 3295 +3463 0 3293 +3461 0 3289 +3457 0 3285 +3453 0 3279 +3445 0 3273 +3437 0 3261 +3423 0 3247 +3405 1402 3227 +3381 1873 3199 +3345 2155 3157 +3293 2375 3095 +3213 2563 2997 +3075 2731 2819 +2785 2891 2355 +0 3041 0 +0 3187 0 +0 3329 0 +0 3467 0 +0 3605 0 +0 3741 0 +0 3877 0 +0 4011 0 +3603 0 3429 +3603 0 3429 +3603 0 3429 +3603 0 3429 +3603 0 3429 +3601 0 3429 +3601 0 3429 +3601 0 3427 +3599 0 3427 +3599 0 3425 +3597 0 3423 +3595 0 3421 +3593 0 3417 +3589 0 3413 +3583 0 3407 +3577 0 3399 +3567 0 3389 +3555 0 3375 +3537 1492 3355 +3511 1990 3325 +3475 2279 3283 +3423 2501 3221 +3343 2691 3121 +3205 2861 2939 +2913 3021 2453 +0 3171 0 +0 3317 0 +0 3459 0 +0 3599 0 +0 3737 0 +0 3873 0 +0 4009 0 +3735 0 3559 +3735 0 3559 +3735 0 3559 +3733 0 3559 +3733 0 3559 +3733 0 3559 +3733 0 3557 +3733 0 3557 +3731 0 3557 +3731 0 3555 +3729 0 3555 +3729 0 3553 +3727 0 3551 +3723 0 3547 +3719 0 3543 +3715 0 3537 +3707 0 3529 +3699 0 3517 +3685 0 3503 +3667 1591 3483 +3643 2111 3453 +3607 2405 3411 +3555 2631 3347 +3473 2821 3247 +3335 2993 3063 +3041 3151 2559 +0 3303 0 +0 3449 0 +0 3591 0 +0 3731 0 +0 3869 0 +0 4005 0 +3865 0 3689 +3865 0 3689 +3865 0 3689 +3865 0 3689 +3865 0 3689 +3865 0 3689 +3865 0 3687 +3865 0 3687 +3865 0 3687 +3863 0 3687 +3863 0 3685 +3861 0 3683 +3859 0 3683 +3857 0 3679 +3855 0 3677 +3851 0 3673 +3847 0 3667 +3839 0 3659 +3829 0 3647 +3817 0 3633 +3799 1696 3611 +3773 2235 3583 +3739 2533 3541 +3685 2759 3477 +3603 2951 3375 +3465 3123 3187 +3169 3283 2669 +0 3435 0 +0 3581 0 +0 3723 0 +0 3863 0 +0 4001 0 +3997 0 3819 +3997 0 3819 +3997 0 3819 +3997 0 3819 +3997 0 3819 +3997 0 3819 +3997 0 3819 +3997 0 3819 +3997 0 3817 +3995 0 3817 +3995 0 3817 +3995 0 3815 +3993 0 3815 +3991 0 3813 +3989 0 3811 +3987 0 3807 +3983 0 3803 +3977 0 3797 +3971 0 3789 +3961 0 3777 +3949 0 3763 +3931 1806 3741 +3905 2361 3713 +3869 2663 3669 +3817 2889 3605 +3735 3083 3503 +3595 3255 3315 +3299 3415 2785 +0 3567 0 +0 3713 0 +0 3855 0 +0 3995 0 +4095 0 3951 +4095 0 3951 +4095 0 3951 +4095 0 3951 +4095 0 3949 +4095 0 3949 +4095 0 3949 +4095 0 3949 +4095 0 3949 +4095 0 3949 +4095 0 3949 +4095 0 3947 +4095 0 3947 +4095 0 3945 +4095 0 3943 +4095 0 3941 +4095 0 3937 +4095 0 3933 +4095 0 3927 +4095 0 3919 +4093 0 3909 +4081 0 3893 +4063 1922 3873 +4037 2487 3843 +4001 2793 3801 +3949 3021 3735 +3867 3213 3633 +3727 3385 3443 +3431 3547 2903 +0 3699 0 +0 3845 0 +0 3987 0 +4095 0 4081 +4095 0 4081 +4095 0 4081 +4095 0 4081 +4095 0 4081 +4095 0 4081 +4095 0 4081 +4095 0 4081 +4095 0 4081 +4095 0 4081 +4095 0 4079 +4095 0 4079 +4095 0 4079 +4095 0 4077 +4095 0 4077 +4095 0 4075 +4095 0 4073 +4095 0 4069 +4095 0 4065 +4095 0 4059 +4095 0 4051 +4095 0 4039 +4095 0 4025 +4095 2041 4003 +4095 2617 3973 +4095 2923 3931 +4081 3151 3867 +3999 3345 3763 +3859 3517 3571 +3561 3677 3025 +0 3831 0 +0 3977 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 2163 4095 +4095 2745 4095 +4095 3053 4063 +4095 3283 3997 +4095 3477 3893 +3991 3649 3701 +3693 3809 3151 +0 3961 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 2287 4095 +4095 2875 4095 +4095 3185 4095 +4095 3415 4095 +4095 3607 4025 +4095 3781 3831 +3823 3941 3277 +1513 1085 1919 +1502 1096 1915 +1486 1112 1911 +1465 1131 1904 +1434 1156 1895 +1390 1187 1883 +1323 1226 1867 +1214 1273 1844 +1011 1329 1811 +373 1395 1763 +0 1470 1689 +0 1555 1568 +0 1648 1328 +0 1748 128 +0 1855 0 +0 1967 0 +0 2085 0 +0 2205 0 +0 2327 0 +0 2453 0 +0 2579 0 +0 2707 0 +0 2837 0 +0 2967 0 +0 3097 0 +0 3227 0 +0 3359 0 +0 3491 0 +0 3623 0 +0 3753 0 +0 3885 0 +0 4017 0 +1527 1083 1923 +1516 1095 1919 +1501 1110 1915 +1480 1129 1908 +1451 1154 1899 +1408 1186 1888 +1344 1225 1871 +1241 1272 1848 +1052 1328 1816 +520 1394 1768 +0 1470 1696 +0 1554 1576 +0 1647 1342 +0 1748 294 +0 1855 0 +0 1967 0 +0 2083 0 +0 2205 0 +0 2327 0 +0 2453 0 +0 2579 0 +0 2707 0 +0 2837 0 +0 2967 0 +0 3097 0 +0 3227 0 +0 3359 0 +0 3491 0 +0 3623 0 +0 3753 0 +0 3885 0 +0 4017 0 +1545 1080 1928 +1534 1092 1924 +1520 1108 1920 +1500 1127 1913 +1472 1152 1905 +1431 1184 1893 +1370 1223 1877 +1274 1270 1854 +1101 1327 1822 +663 1393 1775 +0 1469 1704 +0 1553 1587 +0 1647 1360 +0 1747 449 +0 1854 0 +0 1967 0 +0 2083 0 +0 2203 0 +0 2327 0 +0 2453 0 +0 2579 0 +0 2707 0 +0 2837 0 +0 2967 0 +0 3097 0 +0 3227 0 +0 3359 0 +0 3491 0 +0 3623 0 +0 3753 0 +0 3885 0 +0 4017 0 +1568 1077 1935 +1558 1089 1931 +1544 1104 1927 +1525 1124 1920 +1499 1150 1912 +1460 1181 1900 +1404 1221 1884 +1315 1268 1862 +1160 1325 1831 +803 1391 1785 +0 1467 1715 +0 1552 1601 +0 1646 1383 +0 1746 597 +0 1854 0 +0 1966 0 +0 2083 0 +0 2203 0 +0 2327 0 +0 2453 0 +0 2579 0 +0 2707 0 +0 2837 0 +0 2967 0 +0 3097 0 +0 3227 0 +0 3359 0 +0 3491 0 +0 3623 0 +0 3753 0 +0 3885 0 +0 4017 0 +1597 1073 1944 +1588 1085 1940 +1575 1100 1936 +1557 1120 1930 +1532 1146 1921 +1497 1178 1910 +1445 1217 1894 +1364 1265 1873 +1228 1322 1842 +941 1389 1797 +0 1465 1729 +0 1551 1619 +0 1644 1412 +0 1745 742 +0 1853 0 +0 1966 0 +0 2083 0 +0 2203 0 +0 2327 0 +0 2451 0 +0 2579 0 +0 2707 0 +0 2837 0 +0 2967 0 +0 3097 0 +0 3227 0 +0 3359 0 +0 3491 0 +0 3623 0 +0 3753 0 +0 3885 0 +0 4017 0 +1633 1067 1955 +1624 1079 1952 +1613 1095 1947 +1596 1115 1942 +1574 1141 1933 +1541 1173 1922 +1494 1213 1907 +1423 1261 1886 +1305 1319 1856 +1077 1386 1813 +140 1463 1748 +0 1549 1643 +0 1643 1449 +0 1744 883 +0 1852 0 +0 1965 0 +0 2083 0 +0 2203 0 +0 2327 0 +0 2451 0 +0 2579 0 +0 2707 0 +0 2837 0 +0 2967 0 +0 3097 0 +0 3227 0 +0 3359 0 +0 3491 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1677 1058 1970 +1669 1071 1967 +1659 1087 1963 +1644 1108 1957 +1624 1134 1949 +1595 1167 1939 +1553 1207 1924 +1491 1256 1904 +1392 1314 1875 +1212 1382 1833 +738 1459 1771 +0 1546 1672 +0 1640 1493 +0 1742 1021 +0 1850 0 +0 1964 0 +0 2081 0 +0 2203 0 +0 2325 0 +0 2451 0 +0 2579 0 +0 2707 0 +0 2837 0 +0 2967 0 +0 3097 0 +0 3227 0 +0 3359 0 +0 3491 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1730 1047 1990 +1723 1060 1987 +1714 1076 1982 +1701 1098 1977 +1683 1124 1969 +1658 1158 1959 +1622 1199 1945 +1569 1249 1926 +1487 1308 1899 +1347 1377 1859 +1048 1455 1801 +0 1542 1709 +0 1637 1546 +0 1740 1158 +0 1848 0 +0 1962 0 +0 2081 0 +0 2201 0 +0 2325 0 +0 2451 0 +0 2579 0 +0 2707 0 +0 2835 0 +0 2965 0 +0 3097 0 +0 3227 0 +0 3359 0 +0 3491 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1793 1032 2014 +1787 1045 2011 +1778 1062 2008 +1767 1084 2002 +1752 1111 1995 +1730 1146 1986 +1700 1188 1972 +1655 1239 1954 +1589 1299 1929 +1481 1369 1892 +1278 1449 1838 +650 1537 1754 +0 1633 1609 +0 1736 1294 +0 1846 0 +0 1960 0 +0 2079 0 +0 2201 0 +0 2325 0 +0 2451 0 +0 2577 0 +0 2707 0 +0 2835 0 +0 2965 0 +0 3097 0 +0 3227 0 +0 3359 0 +0 3491 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1865 1011 2045 +1860 1024 2043 +1853 1042 2039 +1843 1065 2034 +1830 1093 2028 +1812 1129 2019 +1787 1173 2006 +1750 1226 1989 +1697 1288 1966 +1614 1359 1932 +1472 1440 1883 +1167 1530 1807 +0 1628 1681 +0 1732 1428 +0 1842 0 +0 1957 0 +0 2077 0 +0 2199 0 +0 2323 0 +0 2449 0 +0 2577 0 +0 2705 0 +0 2835 0 +0 2965 0 +0 3097 0 +0 3227 0 +0 3359 0 +0 3491 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +1946 980 2083 +1942 995 2081 +1936 1014 2077 +1928 1038 2073 +1917 1068 2067 +1902 1106 2059 +1882 1152 2049 +1853 1207 2033 +1810 1271 2011 +1747 1345 1981 +1646 1429 1937 +1461 1520 1870 +957 1620 1763 +0 1726 1562 +0 1838 947 +0 1954 0 +0 2073 0 +0 2197 0 +0 2321 0 +0 2447 0 +0 2575 0 +0 2705 0 +0 2835 0 +0 2965 0 +0 3095 0 +0 3227 0 +0 3359 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +2036 936 2131 +2033 953 2129 +2028 973 2125 +2021 1000 2121 +2013 1032 2115 +2001 1073 2109 +1984 1122 2099 +1961 1181 2085 +1928 1249 2065 +1880 1326 2039 +1807 1413 2000 +1685 1508 1943 +1446 1610 1853 +253 1718 1696 +0 1831 1330 +0 1949 0 +0 2069 0 +0 2193 0 +0 2319 0 +0 2447 0 +0 2575 0 +0 2703 0 +0 2833 0 +0 2965 0 +0 3095 0 +0 3227 0 +0 3359 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +2135 870 2187 +2131 889 2185 +2127 913 2181 +2123 942 2179 +2115 980 2173 +2105 1025 2167 +2093 1079 2159 +2075 1143 2147 +2049 1217 2129 +2013 1299 2107 +1959 1391 2073 +1876 1490 2025 +1733 1595 1951 +1424 1707 1829 +0 1822 1587 +0 1942 319 +0 2065 0 +0 2189 0 +0 2317 0 +0 2443 0 +0 2573 0 +0 2703 0 +0 2833 0 +0 2963 0 +0 3095 0 +0 3227 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +2239 763 2251 +2237 786 2251 +2233 816 2247 +2229 853 2245 +2223 898 2241 +2217 952 2235 +2207 1015 2227 +2193 1088 2217 +2173 1170 2203 +2145 1261 2183 +2105 1359 2155 +2047 1464 2115 +1954 1575 2057 +1790 1691 1962 +1394 1811 1795 +0 1933 1384 +0 2057 0 +0 2185 0 +0 2313 0 +0 2441 0 +0 2571 0 +0 2701 0 +0 2831 0 +0 2963 0 +0 3095 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +2349 563 2327 +2347 599 2325 +2345 643 2323 +2341 696 2321 +2337 758 2317 +2331 830 2313 +2323 911 2307 +2313 1001 2297 +2299 1098 2285 +2277 1203 2269 +2249 1313 2247 +2207 1429 2215 +2143 1548 2167 +2041 1670 2095 +1856 1794 1976 +1349 1920 1745 +0 2049 747 +0 2177 0 +0 2307 0 +0 2437 0 +0 2567 0 +0 2699 0 +0 2831 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +2465 0 2411 +2463 77 2409 +2461 203 2409 +2459 331 2407 +2455 460 2403 +2451 589 2399 +2445 719 2393 +2437 850 2387 +2425 981 2377 +2409 1112 2363 +2389 1244 2345 +2357 1376 2319 +2313 1507 2283 +2245 1639 2227 +2137 1771 2141 +1932 1903 1994 +1282 2035 1667 +0 2167 0 +0 2299 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +2583 0 2503 +2583 0 2503 +2581 0 2501 +2579 0 2499 +2577 0 2497 +2573 0 2495 +2569 172 2489 +2563 511 2483 +2553 754 2477 +2543 954 2465 +2527 1130 2451 +2503 1293 2431 +2471 1447 2401 +2425 1595 2359 +2355 1739 2297 +2239 1879 2197 +2017 2017 2017 +1174 2153 1537 +0 2289 0 +0 2425 0 +0 2557 0 +0 2691 0 +0 2825 0 +0 2957 0 +0 3091 0 +0 3223 0 +0 3355 0 +0 3487 0 +0 3619 0 +0 3753 0 +0 3885 0 +0 4017 0 +2705 0 2603 +2705 0 2603 +2703 0 2601 +2703 0 2601 +2701 0 2599 +2697 0 2597 +2695 0 2593 +2689 0 2589 +2683 0 2581 +2675 581 2573 +2663 914 2561 +2647 1154 2545 +2623 1352 2523 +2591 1528 2493 +2543 1691 2447 +2469 1845 2377 +2349 1992 2263 +2111 2135 2046 +972 2275 1272 +0 2413 0 +0 2551 0 +0 2685 0 +0 2821 0 +0 2955 0 +0 3087 0 +0 3221 0 +0 3353 0 +0 3487 0 +0 3619 0 +0 3751 0 +0 3885 0 +0 4017 0 +2831 0 2711 +2829 0 2709 +2829 0 2709 +2827 0 2707 +2827 0 2707 +2825 0 2705 +2821 0 2701 +2819 0 2699 +2813 0 2693 +2807 0 2687 +2797 144 2677 +2785 855 2665 +2769 1183 2649 +2745 1421 2625 +2711 1618 2591 +2663 1794 2541 +2587 1956 2465 +2463 2109 2339 +2211 2257 2083 +338 2401 0 +0 2541 0 +0 2679 0 +0 2815 0 +0 2951 0 +0 3085 0 +0 3219 0 +0 3353 0 +0 3485 0 +0 3619 0 +0 3751 0 +0 3883 0 +0 4015 0 +2957 0 2823 +2957 0 2821 +2955 0 2821 +2955 0 2821 +2953 0 2819 +2953 0 2817 +2951 0 2815 +2947 0 2813 +2943 0 2809 +2939 0 2803 +2933 0 2797 +2923 0 2787 +2911 762 2775 +2893 1219 2757 +2869 1499 2731 +2835 1716 2697 +2785 1903 2643 +2709 2073 2561 +2581 2231 2423 +2319 2381 2127 +0 2527 0 +0 2667 0 +0 2807 0 +0 2945 0 +0 3081 0 +0 3215 0 +0 3349 0 +0 3483 0 +0 3617 0 +0 3749 0 +0 3883 0 +0 4015 0 +3085 0 2939 +3085 0 2939 +3083 0 2939 +3083 0 2937 +3083 0 2937 +3081 0 2935 +3079 0 2933 +3077 0 2931 +3075 0 2929 +3071 0 2925 +3067 0 2919 +3059 0 2913 +3051 0 2903 +3037 597 2889 +3021 1264 2871 +2997 1585 2845 +2961 1821 2807 +2911 2017 2751 +2833 2191 2665 +2701 2353 2515 +2431 2507 2181 +0 2653 0 +0 2797 0 +0 2937 0 +0 3075 0 +0 3211 0 +0 3347 0 +0 3481 0 +0 3615 0 +0 3749 0 +0 3881 0 +0 4015 0 +3213 0 3059 +3213 0 3059 +3213 0 3059 +3213 0 3057 +3211 0 3057 +3211 0 3057 +3209 0 3055 +3209 0 3053 +3207 0 3051 +3203 0 3049 +3199 0 3045 +3195 0 3039 +3187 0 3031 +3179 0 3021 +3165 198 3007 +3149 1317 2989 +3125 1680 2961 +3089 1931 2923 +3037 2135 2865 +2959 2315 2775 +2825 2479 2615 +2549 2635 2243 +0 2783 0 +0 2927 0 +0 3067 0 +0 3205 0 +0 3343 0 +0 3479 0 +0 3613 0 +0 3747 0 +0 3881 0 +0 4013 0 +3343 0 3183 +3343 0 3181 +3343 0 3181 +3343 0 3181 +3341 0 3181 +3341 0 3179 +3341 0 3179 +3339 0 3177 +3337 0 3177 +3335 0 3173 +3333 0 3171 +3329 0 3167 +3323 0 3161 +3317 0 3153 +3307 0 3143 +3295 0 3129 +3277 1380 3109 +3253 1783 3081 +3217 2046 3041 +3167 2257 2983 +3087 2439 2889 +2951 2607 2723 +2669 2763 2315 +0 2913 0 +0 3057 0 +0 3197 0 +0 3337 0 +0 3473 0 +0 3609 0 +0 3745 0 +0 3879 0 +0 4013 0 +3473 0 3307 +3473 0 3307 +3473 0 3307 +3473 0 3307 +3473 0 3307 +3471 0 3305 +3471 0 3305 +3471 0 3303 +3469 0 3303 +3467 0 3301 +3465 0 3299 +3463 0 3295 +3459 0 3291 +3453 0 3285 +3447 0 3277 +3437 0 3267 +3425 0 3253 +3407 1452 3233 +3383 1891 3205 +3347 2165 3165 +3295 2381 3103 +3215 2567 3007 +3079 2735 2835 +2793 2893 2397 +0 3043 0 +0 3187 0 +0 3329 0 +0 3469 0 +0 3605 0 +0 3741 0 +0 3877 0 +0 4011 0 +3603 0 3435 +3603 0 3433 +3603 0 3433 +3603 0 3433 +3603 0 3433 +3603 0 3433 +3603 0 3433 +3601 0 3431 +3601 0 3431 +3599 0 3429 +3599 0 3427 +3597 0 3425 +3593 0 3423 +3589 0 3417 +3585 0 3413 +3577 0 3405 +3569 0 3393 +3555 0 3379 +3537 1534 3359 +3513 2005 3331 +3477 2287 3289 +3425 2507 3227 +3345 2695 3129 +3207 2863 2951 +2917 3023 2487 +0 3173 0 +0 3319 0 +0 3461 0 +0 3599 0 +0 3737 0 +0 3873 0 +0 4009 0 +3735 0 3563 +3735 0 3563 +3735 0 3561 +3735 0 3561 +3735 0 3561 +3735 0 3561 +3733 0 3561 +3733 0 3561 +3733 0 3559 +3731 0 3559 +3731 0 3557 +3729 0 3555 +3727 0 3553 +3725 0 3549 +3721 0 3545 +3715 0 3539 +3709 0 3533 +3699 0 3521 +3687 0 3507 +3669 1625 3487 +3643 2123 3457 +3607 2411 3415 +3555 2633 3353 +3475 2823 3253 +3337 2993 3071 +3045 3153 2585 +0 3303 0 +0 3449 0 +0 3593 0 +0 3731 0 +0 3869 0 +0 4005 0 +3867 0 3691 +3867 0 3691 +3867 0 3691 +3867 0 3691 +3865 0 3691 +3865 0 3691 +3865 0 3691 +3865 0 3689 +3865 0 3689 +3865 0 3689 +3863 0 3687 +3863 0 3687 +3861 0 3685 +3859 0 3683 +3855 0 3679 +3851 0 3675 +3847 0 3669 +3839 0 3661 +3831 0 3651 +3817 0 3635 +3799 1723 3615 +3775 2243 3585 +3739 2539 3543 +3687 2763 3481 +3605 2953 3379 +3467 3125 3195 +3173 3283 2691 +0 3435 0 +0 3581 0 +0 3723 0 +0 3863 0 +0 4001 0 +3997 0 3821 +3997 0 3821 +3997 0 3821 +3997 0 3821 +3997 0 3821 +3997 0 3821 +3997 0 3821 +3997 0 3821 +3997 0 3819 +3997 0 3819 +3995 0 3819 +3995 0 3817 +3993 0 3817 +3991 0 3815 +3989 0 3811 +3987 0 3809 +3983 0 3805 +3979 0 3799 +3971 0 3791 +3961 0 3779 +3949 0 3765 +3931 1828 3745 +3907 2367 3715 +3871 2665 3673 +3817 2891 3609 +3735 3083 3507 +3597 3255 3319 +3301 3415 2801 +0 3567 0 +0 3713 0 +0 3855 0 +0 3995 0 +4095 0 3951 +4095 0 3951 +4095 0 3951 +4095 0 3951 +4095 0 3951 +4095 0 3951 +4095 0 3951 +4095 0 3951 +4095 0 3951 +4095 0 3951 +4095 0 3949 +4095 0 3949 +4095 0 3947 +4095 0 3947 +4095 0 3945 +4095 0 3943 +4095 0 3939 +4095 0 3935 +4095 0 3929 +4095 0 3921 +4093 0 3909 +4081 0 3895 +4063 1938 3875 +4037 2493 3845 +4001 2795 3801 +3949 3021 3737 +3867 3215 3635 +3729 3387 3447 +3431 3547 2917 +0 3699 0 +0 3845 0 +0 3987 0 +4095 0 4083 +4095 0 4083 +4095 0 4083 +4095 0 4083 +4095 0 4083 +4095 0 4083 +4095 0 4081 +4095 0 4081 +4095 0 4081 +4095 0 4081 +4095 0 4081 +4095 0 4081 +4095 0 4079 +4095 0 4079 +4095 0 4077 +4095 0 4075 +4095 0 4073 +4095 0 4069 +4095 0 4065 +4095 0 4059 +4095 0 4051 +4095 0 4041 +4095 0 4025 +4095 2053 4005 +4095 2621 3975 +4095 2925 3933 +4081 3153 3867 +3999 3345 3765 +3859 3517 3575 +3563 3679 3035 +0 3831 0 +0 3977 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 2173 4095 +4095 2749 4095 +4095 3055 4063 +4095 3283 3999 +4095 3477 3895 +3991 3649 3703 +3693 3809 3157 +0 3963 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 2295 4095 +4095 2877 4095 +4095 3185 4095 +4095 3415 4095 +4095 3609 4025 +4095 3781 3833 +3825 3941 3283 +1643 1209 2051 +1635 1218 2049 +1623 1230 2045 +1607 1245 2040 +1585 1264 2033 +1554 1289 2025 +1508 1321 2012 +1439 1359 1996 +1326 1406 1972 +1110 1462 1939 +353 1528 1891 +0 1603 1817 +0 1688 1694 +0 1780 1449 +0 1881 80 +0 1987 0 +0 2099 0 +0 2217 0 +0 2337 0 +0 2459 0 +0 2585 0 +0 2711 0 +0 2839 0 +0 2969 0 +0 3099 0 +0 3229 0 +0 3361 0 +0 3491 0 +0 3623 0 +0 3755 0 +0 3885 0 +0 4017 0 +1653 1208 2053 +1645 1217 2051 +1634 1229 2047 +1618 1244 2043 +1597 1263 2036 +1566 1288 2028 +1522 1319 2016 +1455 1358 1999 +1346 1405 1976 +1143 1462 1943 +505 1527 1895 +0 1603 1821 +0 1687 1700 +0 1780 1460 +0 1880 260 +0 1987 0 +0 2099 0 +0 2217 0 +0 2337 0 +0 2459 0 +0 2585 0 +0 2711 0 +0 2839 0 +0 2969 0 +0 3099 0 +0 3229 0 +0 3359 0 +0 3491 0 +0 3623 0 +0 3755 0 +0 3885 0 +0 4017 0 +1667 1206 2057 +1659 1215 2055 +1648 1227 2051 +1633 1242 2047 +1612 1262 2040 +1583 1287 2032 +1540 1318 2020 +1476 1357 2003 +1373 1404 1980 +1184 1461 1948 +652 1526 1900 +0 1602 1828 +0 1686 1708 +0 1779 1474 +0 1880 426 +0 1987 0 +0 2099 0 +0 2215 0 +0 2337 0 +0 2459 0 +0 2585 0 +0 2711 0 +0 2839 0 +0 2969 0 +0 3099 0 +0 3229 0 +0 3359 0 +0 3491 0 +0 3623 0 +0 3755 0 +0 3885 0 +0 4017 0 +1685 1204 2063 +1677 1213 2061 +1667 1224 2057 +1652 1240 2051 +1632 1259 2046 +1604 1284 2037 +1563 1316 2025 +1503 1355 2009 +1406 1403 1986 +1233 1459 1954 +795 1525 1907 +0 1601 1836 +0 1686 1719 +0 1779 1492 +0 1879 581 +0 1986 0 +0 2099 0 +0 2215 0 +0 2337 0 +0 2459 0 +0 2585 0 +0 2711 0 +0 2839 0 +0 2969 0 +0 3099 0 +0 3229 0 +0 3359 0 +0 3491 0 +0 3623 0 +0 3755 0 +0 3885 0 +0 4017 0 +1707 1200 2069 +1700 1209 2067 +1690 1221 2063 +1676 1237 2059 +1657 1256 2053 +1631 1282 2044 +1593 1313 2033 +1536 1353 2017 +1447 1400 1994 +1292 1457 1963 +935 1524 1917 +0 1599 1847 +0 1684 1733 +0 1778 1515 +0 1879 730 +0 1986 0 +0 2099 0 +0 2215 0 +0 2335 0 +0 2459 0 +0 2585 0 +0 2711 0 +0 2839 0 +0 2969 0 +0 3099 0 +0 3229 0 +0 3359 0 +0 3491 0 +0 3623 0 +0 3755 0 +0 3885 0 +0 4017 0 +1736 1196 2079 +1729 1205 2075 +1720 1217 2073 +1707 1232 2067 +1689 1252 2061 +1664 1278 2053 +1629 1310 2042 +1577 1349 2026 +1496 1397 2005 +1360 1455 1974 +1073 1521 1929 +0 1598 1861 +0 1683 1752 +0 1776 1545 +0 1878 874 +0 1985 0 +0 2097 0 +0 2215 0 +0 2335 0 +0 2459 0 +0 2585 0 +0 2711 0 +0 2839 0 +0 2969 0 +0 3099 0 +0 3229 0 +0 3359 0 +0 3491 0 +0 3623 0 +0 3755 0 +0 3885 0 +0 4017 0 +1771 1189 2089 +1765 1199 2087 +1756 1211 2083 +1745 1227 2079 +1728 1247 2073 +1706 1273 2065 +1674 1305 2055 +1627 1345 2039 +1555 1393 2018 +1437 1451 1988 +1209 1518 1945 +272 1595 1880 +0 1681 1775 +0 1775 1581 +0 1876 1015 +0 1984 0 +0 2097 0 +0 2215 0 +0 2335 0 +0 2459 0 +0 2583 0 +0 2711 0 +0 2839 0 +0 2969 0 +0 3099 0 +0 3229 0 +0 3359 0 +0 3491 0 +0 3623 0 +0 3755 0 +0 3885 0 +0 4017 0 +1815 1181 2105 +1809 1191 2103 +1801 1203 2099 +1791 1219 2095 +1776 1240 2089 +1756 1266 2081 +1727 1299 2071 +1685 1339 2057 +1623 1388 2036 +1524 1446 2007 +1344 1514 1966 +870 1592 1903 +0 1678 1804 +0 1772 1625 +0 1874 1153 +0 1982 0 +0 2095 0 +0 2213 0 +0 2335 0 +0 2457 0 +0 2583 0 +0 2711 0 +0 2839 0 +0 2969 0 +0 3099 0 +0 3229 0 +0 3359 0 +0 3491 0 +0 3623 0 +0 3755 0 +0 3885 0 +0 4017 0 +1867 1170 2123 +1862 1179 2121 +1855 1192 2119 +1846 1209 2115 +1833 1230 2109 +1815 1256 2101 +1790 1290 2091 +1754 1331 2077 +1701 1381 2059 +1619 1440 2031 +1479 1509 1992 +1180 1587 1933 +0 1674 1841 +0 1769 1678 +0 1872 1290 +0 1981 0 +0 2095 0 +0 2213 0 +0 2333 0 +0 2457 0 +0 2583 0 +0 2711 0 +0 2839 0 +0 2969 0 +0 3099 0 +0 3229 0 +0 3359 0 +0 3491 0 +0 3623 0 +0 3755 0 +0 3885 0 +0 4017 0 +1929 1154 2149 +1925 1164 2147 +1919 1177 2143 +1910 1194 2139 +1899 1216 2135 +1884 1243 2127 +1862 1278 2117 +1832 1320 2105 +1788 1371 2087 +1721 1432 2061 +1613 1501 2024 +1410 1581 1970 +782 1669 1886 +0 1765 1741 +0 1869 1426 +0 1978 0 +0 2093 0 +0 2211 0 +0 2333 0 +0 2457 0 +0 2583 0 +0 2709 0 +0 2839 0 +0 2967 0 +0 3097 0 +0 3229 0 +0 3359 0 +0 3491 0 +0 3623 0 +0 3753 0 +0 3885 0 +0 4017 0 +2001 1132 2179 +1997 1143 2177 +1992 1156 2175 +1985 1174 2171 +1975 1197 2167 +1962 1226 2159 +1944 1261 2151 +1919 1305 2139 +1883 1358 2121 +1829 1420 2097 +1746 1491 2065 +1604 1572 2015 +1299 1662 1939 +0 1760 1813 +0 1864 1560 +0 1974 0 +0 2089 0 +0 2209 0 +0 2331 0 +0 2455 0 +0 2581 0 +0 2709 0 +0 2837 0 +0 2967 0 +0 3097 0 +0 3229 0 +0 3359 0 +0 3491 0 +0 3623 0 +0 3753 0 +0 3885 0 +0 4017 0 +2081 1101 2217 +2079 1112 2215 +2073 1127 2213 +2069 1146 2211 +2061 1170 2205 +2049 1200 2199 +2034 1238 2191 +2014 1284 2181 +1985 1339 2165 +1943 1404 2143 +1879 1478 2113 +1778 1561 2069 +1593 1653 2003 +1089 1752 1895 +0 1858 1695 +0 1970 1079 +0 2085 0 +0 2205 0 +0 2329 0 +0 2453 0 +0 2579 0 +0 2709 0 +0 2837 0 +0 2967 0 +0 3097 0 +0 3229 0 +0 3359 0 +0 3491 0 +0 3623 0 +0 3753 0 +0 3885 0 +0 4017 0 +2171 1056 2265 +2169 1068 2263 +2165 1084 2261 +2159 1105 2257 +2153 1132 2253 +2145 1164 2249 +2133 1205 2241 +2117 1254 2231 +2093 1313 2217 +2061 1381 2197 +2012 1458 2171 +1939 1545 2133 +1817 1640 2075 +1578 1742 1985 +385 1850 1828 +0 1963 1462 +0 2081 0 +0 2201 0 +0 2325 0 +0 2451 0 +0 2579 0 +0 2707 0 +0 2837 0 +0 2967 0 +0 3097 0 +0 3227 0 +0 3359 0 +0 3491 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +2269 988 2321 +2267 1002 2319 +2263 1021 2317 +2259 1044 2315 +2255 1074 2311 +2247 1112 2305 +2237 1157 2299 +2225 1211 2291 +2207 1275 2279 +2181 1349 2261 +2145 1431 2239 +2091 1523 2205 +2008 1622 2157 +1865 1727 2083 +1556 1839 1961 +0 1955 1720 +0 2075 451 +0 2197 0 +0 2321 0 +0 2449 0 +0 2577 0 +0 2705 0 +0 2835 0 +0 2965 0 +0 3095 0 +0 3227 0 +0 3359 0 +0 3491 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +2373 877 2385 +2371 895 2385 +2369 918 2383 +2365 948 2381 +2361 985 2377 +2357 1029 2373 +2349 1083 2367 +2339 1147 2359 +2325 1220 2349 +2305 1302 2335 +2277 1393 2315 +2237 1491 2287 +2179 1597 2247 +2087 1708 2189 +1922 1823 2095 +1526 1943 1927 +0 2065 1516 +0 2189 0 +0 2317 0 +0 2445 0 +0 2573 0 +0 2703 0 +0 2833 0 +0 2963 0 +0 3095 0 +0 3227 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +2483 666 2461 +2481 695 2459 +2479 731 2457 +2477 775 2455 +2475 828 2453 +2469 890 2449 +2463 962 2445 +2457 1043 2439 +2445 1133 2429 +2431 1230 2417 +2409 1335 2401 +2381 1445 2379 +2339 1561 2347 +2275 1680 2299 +2173 1802 2227 +1988 1926 2109 +1481 2053 1877 +0 2181 879 +0 2309 0 +0 2439 0 +0 2569 0 +0 2699 0 +0 2831 0 +0 2963 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +2597 0 2543 +2597 84 2543 +2595 209 2541 +2593 335 2541 +2591 463 2539 +2587 592 2535 +2583 721 2531 +2577 852 2527 +2569 982 2519 +2557 1113 2509 +2543 1244 2495 +2521 1376 2477 +2489 1508 2451 +2445 1640 2415 +2379 1771 2359 +2269 1903 2273 +2065 2035 2127 +1415 2167 1799 +0 2299 0 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3091 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +2717 0 2637 +2715 0 2635 +2715 0 2635 +2713 0 2633 +2711 0 2631 +2709 0 2629 +2705 0 2627 +2701 304 2621 +2695 644 2617 +2687 886 2609 +2675 1086 2597 +2659 1263 2583 +2635 1426 2563 +2605 1580 2533 +2557 1727 2493 +2487 1871 2429 +2371 2011 2329 +2149 2149 2149 +1306 2287 1669 +0 2421 0 +0 2557 0 +0 2691 0 +0 2823 0 +0 2957 0 +0 3089 0 +0 3223 0 +0 3355 0 +0 3487 0 +0 3619 0 +0 3753 0 +0 3885 0 +0 4017 0 +2839 0 2737 +2837 0 2735 +2837 0 2735 +2837 0 2735 +2835 0 2733 +2833 0 2731 +2831 0 2729 +2827 0 2725 +2821 0 2721 +2815 0 2713 +2807 713 2705 +2795 1046 2693 +2779 1286 2679 +2755 1484 2655 +2723 1661 2625 +2675 1823 2579 +2601 1977 2509 +2481 2125 2395 +2243 2267 2179 +1103 2407 1404 +0 2547 0 +0 2683 0 +0 2819 0 +0 2953 0 +0 3087 0 +0 3221 0 +0 3353 0 +0 3487 0 +0 3619 0 +0 3751 0 +0 3883 0 +0 4017 0 +2963 0 2843 +2963 0 2843 +2961 0 2841 +2961 0 2841 +2959 0 2839 +2959 0 2839 +2957 0 2837 +2953 0 2833 +2951 0 2831 +2945 0 2825 +2939 0 2819 +2929 276 2809 +2917 987 2797 +2901 1315 2781 +2877 1553 2757 +2843 1750 2723 +2795 1926 2673 +2719 2089 2597 +2595 2241 2471 +2343 2389 2215 +471 2533 0 +0 2673 0 +0 2811 0 +0 2947 0 +0 3083 0 +0 3217 0 +0 3351 0 +0 3485 0 +0 3617 0 +0 3751 0 +0 3883 0 +0 4015 0 +3089 0 2955 +3089 0 2955 +3089 0 2955 +3087 0 2953 +3087 0 2953 +3085 0 2951 +3085 0 2949 +3083 0 2947 +3079 0 2945 +3075 0 2941 +3071 0 2937 +3065 0 2929 +3055 0 2919 +3043 894 2907 +3025 1351 2889 +3001 1631 2863 +2967 1848 2829 +2917 2035 2775 +2841 2205 2693 +2713 2363 2555 +2451 2513 2259 +0 2659 0 +0 2801 0 +0 2939 0 +0 3077 0 +0 3213 0 +0 3347 0 +0 3483 0 +0 3615 0 +0 3749 0 +0 3883 0 +0 4015 0 +3217 0 3071 +3217 0 3071 +3217 0 3071 +3215 0 3071 +3215 0 3069 +3215 0 3069 +3213 0 3067 +3211 0 3065 +3209 0 3063 +3207 0 3061 +3203 0 3057 +3199 0 3051 +3191 0 3045 +3183 0 3035 +3169 729 3021 +3153 1396 3003 +3129 1717 2977 +3093 1953 2939 +3043 2149 2883 +2965 2325 2797 +2833 2485 2647 +2563 2639 2313 +0 2785 0 +0 2929 0 +0 3069 0 +0 3207 0 +0 3343 0 +0 3479 0 +0 3613 0 +0 3747 0 +0 3881 0 +0 4013 0 +3345 0 3191 +3345 0 3191 +3345 0 3191 +3345 0 3191 +3345 0 3191 +3343 0 3189 +3343 0 3189 +3341 0 3187 +3341 0 3185 +3339 0 3183 +3335 0 3181 +3331 0 3177 +3327 0 3171 +3319 0 3163 +3311 0 3153 +3299 330 3139 +3281 1449 3121 +3257 1813 3093 +3221 2063 3055 +3169 2267 2997 +3091 2447 2907 +2957 2611 2747 +2681 2767 2375 +0 2915 0 +0 3059 0 +0 3199 0 +0 3337 0 +0 3475 0 +0 3611 0 +0 3745 0 +0 3879 0 +0 4013 0 +3475 0 3315 +3475 0 3315 +3475 0 3313 +3475 0 3313 +3475 0 3313 +3473 0 3313 +3473 0 3313 +3473 0 3311 +3471 0 3309 +3469 0 3309 +3467 0 3305 +3465 0 3303 +3461 0 3299 +3457 0 3293 +3449 0 3285 +3439 0 3275 +3427 0 3261 +3409 1512 3241 +3385 1915 3213 +3349 2179 3175 +3299 2389 3115 +3219 2571 3021 +3083 2739 2855 +2801 2895 2447 +0 3045 0 +0 3189 0 +0 3331 0 +0 3469 0 +0 3607 0 +0 3741 0 +0 3877 0 +0 4011 0 +3605 0 3439 +3605 0 3439 +3605 0 3439 +3605 0 3439 +3605 0 3439 +3605 0 3439 +3603 0 3437 +3603 0 3437 +3603 0 3437 +3601 0 3435 +3599 0 3433 +3597 0 3431 +3595 0 3427 +3591 0 3423 +3587 0 3417 +3579 0 3411 +3569 0 3399 +3557 0 3385 +3539 1585 3365 +3515 2023 3337 +3479 2297 3297 +3427 2513 3235 +3347 2699 3139 +3211 2867 2967 +2925 3025 2529 +0 3175 0 +0 3319 0 +0 3461 0 +0 3601 0 +0 3737 0 +0 3873 0 +0 4009 0 +3737 0 3567 +3737 0 3567 +3735 0 3567 +3735 0 3565 +3735 0 3565 +3735 0 3565 +3735 0 3565 +3735 0 3565 +3733 0 3563 +3733 0 3563 +3731 0 3561 +3731 0 3559 +3729 0 3557 +3725 0 3555 +3721 0 3549 +3717 0 3545 +3709 0 3537 +3701 0 3525 +3687 0 3511 +3669 1666 3491 +3645 2137 3463 +3609 2419 3421 +3557 2639 3359 +3477 2827 3261 +3339 2995 3083 +3049 3155 2619 +0 3305 0 +0 3451 0 +0 3593 0 +0 3731 0 +0 3869 0 +0 4005 0 +3867 0 3695 +3867 0 3695 +3867 0 3695 +3867 0 3695 +3867 0 3693 +3867 0 3693 +3867 0 3693 +3867 0 3693 +3865 0 3693 +3865 0 3691 +3865 0 3691 +3863 0 3689 +3861 0 3687 +3859 0 3685 +3857 0 3683 +3853 0 3677 +3847 0 3673 +3841 0 3665 +3831 0 3653 +3819 0 3639 +3801 1757 3619 +3775 2255 3589 +3741 2543 3547 +3687 2765 3485 +3607 2955 3385 +3469 3125 3203 +3177 3285 2717 +0 3437 0 +0 3581 0 +0 3725 0 +0 3863 0 +0 4001 0 +3999 0 3823 +3999 0 3823 +3999 0 3823 +3999 0 3823 +3999 0 3823 +3999 0 3823 +3997 0 3823 +3997 0 3823 +3997 0 3821 +3997 0 3821 +3997 0 3821 +3995 0 3819 +3995 0 3819 +3993 0 3817 +3991 0 3815 +3987 0 3811 +3983 0 3807 +3979 0 3801 +3971 0 3793 +3963 0 3783 +3949 0 3767 +3931 1855 3747 +3907 2375 3717 +3871 2671 3675 +3819 2895 3613 +3737 3085 3511 +3599 3257 3327 +3305 3415 2823 +0 3567 0 +0 3713 0 +0 3855 0 +0 3995 0 +4095 0 3953 +4095 0 3953 +4095 0 3953 +4095 0 3953 +4095 0 3953 +4095 0 3953 +4095 0 3953 +4095 0 3953 +4095 0 3953 +4095 0 3951 +4095 0 3951 +4095 0 3951 +4095 0 3949 +4095 0 3949 +4095 0 3947 +4095 0 3945 +4095 0 3941 +4095 0 3937 +4095 0 3931 +4095 0 3923 +4093 0 3911 +4081 0 3897 +4063 1960 3877 +4039 2499 3847 +4003 2797 3805 +3949 3023 3741 +3869 3215 3639 +3729 3387 3451 +3435 3547 2933 +0 3699 0 +0 3845 0 +0 3987 0 +4095 0 4083 +4095 0 4083 +4095 0 4083 +4095 0 4083 +4095 0 4083 +4095 0 4083 +4095 0 4083 +4095 0 4083 +4095 0 4083 +4095 0 4083 +4095 0 4083 +4095 0 4081 +4095 0 4081 +4095 0 4079 +4095 0 4079 +4095 0 4077 +4095 0 4075 +4095 0 4071 +4095 0 4067 +4095 0 4061 +4095 0 4053 +4095 0 4043 +4095 0 4027 +4095 2071 4007 +4095 2625 3977 +4095 2927 3935 +4081 3155 3869 +3999 3347 3767 +3861 3519 3579 +3563 3679 3049 +0 3831 0 +0 3977 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 2187 4095 +4095 2753 4095 +4095 3057 4065 +4095 3285 4001 +4095 3477 3897 +3991 3651 3707 +3695 3811 3167 +0 3963 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 2305 4095 +4095 2881 4095 +4095 3187 4095 +4095 3415 4095 +4095 3609 4027 +4095 3781 3835 +3825 3943 3291 +1773 1336 2183 +1767 1342 2181 +1759 1351 2179 +1747 1363 2175 +1731 1378 2169 +1708 1398 2163 +1676 1422 2155 +1629 1453 2143 +1558 1492 2125 +1442 1539 2101 +1216 1595 2069 +324 1661 2020 +0 1736 1945 +0 1820 1821 +0 1913 1573 +0 2013 6 +0 2119 0 +0 2231 0 +0 2349 0 +0 2469 0 +0 2591 0 +0 2717 0 +0 2843 0 +0 2971 0 +0 3101 0 +0 3231 0 +0 3361 0 +0 3493 0 +0 3623 0 +0 3755 0 +0 3887 0 +0 4019 0 +1781 1335 2185 +1775 1341 2183 +1767 1350 2181 +1755 1362 2177 +1739 1377 2171 +1717 1397 2165 +1686 1421 2157 +1640 1453 2145 +1571 1491 2127 +1458 1538 2105 +1242 1594 2071 +485 1660 2023 +0 1735 1949 +0 1820 1826 +0 1912 1582 +0 2013 212 +0 2119 0 +0 2231 0 +0 2349 0 +0 2469 0 +0 2591 0 +0 2717 0 +0 2843 0 +0 2971 0 +0 3101 0 +0 3231 0 +0 3361 0 +0 3493 0 +0 3623 0 +0 3755 0 +0 3887 0 +0 4019 0 +1792 1333 2187 +1786 1340 2185 +1777 1349 2183 +1766 1361 2179 +1751 1376 2175 +1729 1395 2169 +1699 1420 2159 +1654 1452 2147 +1587 1490 2131 +1479 1537 2107 +1275 1594 2075 +637 1659 2027 +0 1735 1954 +0 1819 1832 +0 1912 1592 +0 2012 393 +0 2119 0 +0 2231 0 +0 2349 0 +0 2469 0 +0 2591 0 +0 2717 0 +0 2843 0 +0 2971 0 +0 3101 0 +0 3231 0 +0 3361 0 +0 3493 0 +0 3623 0 +0 3755 0 +0 3887 0 +0 4019 0 +1805 1331 2191 +1799 1338 2189 +1791 1347 2187 +1780 1359 2183 +1765 1374 2179 +1744 1394 2173 +1715 1419 2163 +1672 1450 2151 +1608 1489 2135 +1505 1536 2113 +1316 1593 2079 +784 1659 2032 +0 1734 1960 +0 1819 1840 +0 1912 1606 +0 2012 558 +0 2119 0 +0 2231 0 +0 2349 0 +0 2469 0 +0 2591 0 +0 2717 0 +0 2843 0 +0 2971 0 +0 3101 0 +0 3231 0 +0 3361 0 +0 3493 0 +0 3623 0 +0 3755 0 +0 3887 0 +0 4019 0 +1823 1329 2197 +1817 1336 2195 +1809 1345 2193 +1799 1356 2189 +1784 1372 2185 +1764 1392 2177 +1736 1417 2169 +1695 1448 2157 +1635 1487 2141 +1538 1535 2119 +1365 1591 2087 +927 1657 2040 +0 1733 1968 +0 1818 1851 +0 1911 1624 +0 2011 713 +0 2119 0 +0 2231 0 +0 2347 0 +0 2469 0 +0 2591 0 +0 2717 0 +0 2843 0 +0 2971 0 +0 3101 0 +0 3231 0 +0 3361 0 +0 3493 0 +0 3623 0 +0 3755 0 +0 3887 0 +0 4019 0 +1845 1325 2203 +1839 1332 2201 +1832 1341 2199 +1822 1353 2195 +1809 1369 2191 +1790 1389 2185 +1763 1414 2177 +1725 1446 2165 +1668 1485 2149 +1579 1532 2127 +1424 1589 2095 +1067 1656 2049 +0 1732 1979 +0 1817 1865 +0 1910 1647 +0 2011 862 +0 2117 0 +0 2231 0 +0 2347 0 +0 2467 0 +0 2591 0 +0 2717 0 +0 2843 0 +0 2971 0 +0 3101 0 +0 3231 0 +0 3361 0 +0 3493 0 +0 3623 0 +0 3755 0 +0 3887 0 +0 4019 0 +1873 1321 2213 +1868 1328 2211 +1861 1337 2207 +1852 1349 2205 +1839 1365 2199 +1821 1385 2193 +1797 1410 2185 +1761 1442 2175 +1709 1482 2159 +1628 1530 2137 +1492 1587 2107 +1205 1653 2061 +0 1730 1994 +0 1815 1884 +0 1909 1677 +0 2010 1006 +0 2117 0 +0 2229 0 +0 2347 0 +0 2467 0 +0 2591 0 +0 2717 0 +0 2843 0 +0 2971 0 +0 3101 0 +0 3231 0 +0 3361 0 +0 3493 0 +0 3623 0 +0 3755 0 +0 3887 0 +0 4019 0 +1908 1315 2223 +1904 1322 2221 +1897 1331 2219 +1889 1343 2217 +1877 1359 2211 +1861 1379 2205 +1838 1405 2197 +1806 1437 2187 +1759 1477 2171 +1687 1526 2151 +1570 1583 2121 +1341 1650 2077 +404 1727 2012 +0 1813 1907 +0 1907 1713 +0 2008 1147 +0 2117 0 +0 2229 0 +0 2347 0 +0 2467 0 +0 2591 0 +0 2715 0 +0 2843 0 +0 2971 0 +0 3101 0 +0 3231 0 +0 3361 0 +0 3491 0 +0 3623 0 +0 3755 0 +0 3887 0 +0 4017 0 +1951 1306 2239 +1947 1313 2237 +1941 1323 2235 +1934 1335 2231 +1923 1351 2227 +1908 1372 2221 +1888 1398 2213 +1859 1431 2203 +1818 1471 2189 +1755 1520 2167 +1656 1579 2139 +1476 1646 2097 +1002 1724 2036 +0 1810 1936 +0 1905 1757 +0 2007 1285 +0 2115 0 +0 2227 0 +0 2345 0 +0 2467 0 +0 2589 0 +0 2715 0 +0 2843 0 +0 2971 0 +0 3101 0 +0 3231 0 +0 3361 0 +0 3491 0 +0 3623 0 +0 3755 0 +0 3887 0 +0 4017 0 +2003 1294 2257 +2000 1302 2257 +1994 1312 2253 +1987 1324 2251 +1978 1341 2247 +1965 1362 2241 +1947 1389 2233 +1922 1422 2223 +1886 1463 2209 +1833 1513 2191 +1751 1572 2163 +1611 1641 2123 +1312 1719 2065 +0 1806 1973 +0 1902 1811 +0 2004 1422 +0 2113 0 +0 2227 0 +0 2345 0 +0 2465 0 +0 2589 0 +0 2715 0 +0 2843 0 +0 2971 0 +0 3101 0 +0 3231 0 +0 3361 0 +0 3491 0 +0 3623 0 +0 3755 0 +0 3887 0 +0 4017 0 +2065 1278 2283 +2061 1286 2281 +2057 1296 2279 +2051 1309 2275 +2043 1326 2271 +2031 1348 2267 +2016 1376 2259 +1994 1410 2249 +1964 1452 2237 +1920 1503 2219 +1853 1564 2193 +1745 1634 2157 +1543 1713 2103 +914 1801 2018 +0 1897 1873 +0 2001 1558 +0 2111 0 +0 2225 0 +0 2343 0 +0 2465 0 +0 2589 0 +0 2715 0 +0 2841 0 +0 2971 0 +0 3099 0 +0 3231 0 +0 3361 0 +0 3491 0 +0 3623 0 +0 3755 0 +0 3887 0 +0 4017 0 +2135 1256 2313 +2133 1264 2311 +2129 1275 2309 +2123 1289 2307 +2117 1306 2303 +2107 1329 2299 +2095 1358 2291 +2077 1393 2283 +2051 1437 2271 +2015 1490 2253 +1961 1552 2231 +1878 1624 2197 +1737 1704 2147 +1431 1794 2071 +0 1892 1946 +0 1996 1693 +0 2107 0 +0 2221 0 +0 2341 0 +0 2463 0 +0 2587 0 +0 2713 0 +0 2841 0 +0 2969 0 +0 3099 0 +0 3229 0 +0 3361 0 +0 3491 0 +0 3623 0 +0 3755 0 +0 3887 0 +0 4017 0 +2215 1225 2351 +2213 1233 2349 +2211 1244 2347 +2205 1259 2345 +2201 1278 2343 +2193 1302 2337 +2181 1333 2331 +2167 1370 2323 +2145 1416 2313 +2117 1471 2297 +2075 1536 2275 +2011 1610 2245 +1910 1693 2201 +1725 1785 2135 +1221 1884 2027 +0 1990 1827 +0 2101 1211 +0 2219 0 +0 2337 0 +0 2461 0 +0 2585 0 +0 2713 0 +0 2841 0 +0 2969 0 +0 3099 0 +0 3229 0 +0 3361 0 +0 3491 0 +0 3623 0 +0 3755 0 +0 3885 0 +0 4017 0 +2305 1179 2397 +2303 1188 2397 +2301 1200 2395 +2297 1217 2393 +2293 1237 2389 +2285 1264 2385 +2277 1297 2381 +2265 1337 2373 +2249 1387 2363 +2225 1445 2349 +2193 1513 2329 +2145 1591 2303 +2071 1677 2265 +1949 1772 2207 +1710 1874 2117 +517 1982 1960 +0 2095 1594 +0 2213 0 +0 2335 0 +0 2457 0 +0 2583 0 +0 2711 0 +0 2839 0 +0 2969 0 +0 3099 0 +0 3229 0 +0 3359 0 +0 3491 0 +0 3623 0 +0 3755 0 +0 3885 0 +0 4017 0 +2401 1109 2453 +2401 1120 2453 +2399 1134 2451 +2395 1153 2449 +2391 1177 2447 +2387 1206 2443 +2379 1244 2437 +2369 1289 2431 +2357 1344 2423 +2339 1407 2411 +2313 1481 2393 +2277 1564 2371 +2223 1655 2337 +2139 1754 2289 +1997 1860 2215 +1688 1971 2093 +0 2087 1852 +0 2207 583 +0 2329 0 +0 2453 0 +0 2581 0 +0 2709 0 +0 2837 0 +0 2967 0 +0 3097 0 +0 3229 0 +0 3359 0 +0 3491 0 +0 3623 0 +0 3753 0 +0 3885 0 +0 4017 0 +2505 995 2519 +2505 1009 2517 +2503 1027 2517 +2501 1050 2515 +2497 1080 2513 +2493 1117 2509 +2489 1162 2505 +2481 1216 2499 +2471 1279 2491 +2457 1352 2481 +2437 1434 2467 +2409 1525 2447 +2369 1623 2419 +2311 1729 2381 +2219 1840 2321 +2055 1955 2227 +1658 2075 2059 +0 2197 1649 +0 2321 0 +0 2449 0 +0 2577 0 +0 2705 0 +0 2835 0 +0 2965 0 +0 3097 0 +0 3227 0 +0 3359 0 +0 3491 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +2615 775 2593 +2615 798 2593 +2613 827 2591 +2611 863 2589 +2609 907 2587 +2607 960 2585 +2601 1022 2581 +2597 1094 2577 +2589 1175 2571 +2577 1265 2561 +2563 1363 2551 +2541 1467 2533 +2513 1578 2511 +2471 1693 2479 +2407 1812 2431 +2305 1934 2359 +2121 2059 2241 +1614 2185 2009 +0 2313 1012 +0 2441 0 +0 2571 0 +0 2701 0 +0 2831 0 +0 2963 0 +0 3095 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +2731 0 2677 +2729 94 2677 +2729 216 2675 +2727 341 2675 +2725 467 2673 +2723 595 2671 +2719 724 2667 +2715 853 2663 +2709 984 2659 +2701 1114 2651 +2689 1245 2641 +2675 1377 2629 +2653 1508 2609 +2621 1640 2583 +2577 1772 2547 +2511 1904 2491 +2401 2035 2407 +2197 2167 2259 +1547 2299 1931 +0 2431 0 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +2849 0 2769 +2849 0 2769 +2847 0 2767 +2847 0 2767 +2845 0 2765 +2843 0 2763 +2841 0 2761 +2837 0 2759 +2833 436 2755 +2827 776 2749 +2819 1018 2741 +2807 1218 2729 +2791 1395 2715 +2769 1558 2695 +2737 1712 2665 +2689 1859 2625 +2619 2003 2561 +2503 2143 2463 +2281 2281 2281 +1438 2419 1802 +0 2553 0 +0 2689 0 +0 2823 0 +0 2955 0 +0 3089 0 +0 3221 0 +0 3355 0 +0 3487 0 +0 3619 0 +0 3751 0 +0 3885 0 +0 4017 0 +2971 0 2869 +2971 0 2869 +2971 0 2867 +2969 0 2867 +2969 0 2867 +2967 0 2865 +2965 0 2863 +2963 0 2861 +2959 0 2857 +2953 0 2853 +2947 96 2847 +2939 845 2837 +2927 1178 2827 +2911 1418 2811 +2887 1617 2789 +2855 1793 2757 +2807 1955 2711 +2733 2109 2641 +2613 2257 2527 +2375 2399 2311 +1236 2539 1536 +0 2679 0 +0 2815 0 +0 2951 0 +0 3085 0 +0 3219 0 +0 3353 0 +0 3485 0 +0 3619 0 +0 3751 0 +0 3883 0 +0 4015 0 +3095 0 2975 +3095 0 2975 +3095 0 2975 +3095 0 2973 +3093 0 2973 +3093 0 2973 +3091 0 2971 +3089 0 2969 +3085 0 2965 +3083 0 2963 +3077 0 2957 +3071 0 2951 +3063 409 2941 +3049 1119 2929 +3033 1447 2913 +3009 1685 2889 +2975 1883 2855 +2927 2059 2805 +2851 2221 2729 +2727 2373 2603 +2475 2521 2347 +602 2665 0 +0 2805 0 +0 2943 0 +0 3079 0 +0 3215 0 +0 3349 0 +0 3483 0 +0 3617 0 +0 3749 0 +0 3883 0 +0 4015 0 +3221 0 3087 +3221 0 3087 +3221 0 3087 +3221 0 3087 +3219 0 3085 +3219 0 3085 +3217 0 3083 +3217 0 3083 +3215 0 3079 +3211 0 3077 +3209 0 3073 +3203 0 3069 +3197 0 3061 +3187 0 3051 +3175 1026 3039 +3159 1483 3021 +3135 1763 2997 +3099 1980 2961 +3049 2167 2907 +2973 2337 2825 +2845 2495 2687 +2583 2645 2391 +0 2791 0 +0 2933 0 +0 3071 0 +0 3209 0 +0 3345 0 +0 3479 0 +0 3615 0 +0 3747 0 +0 3881 0 +0 4015 0 +3349 0 3203 +3349 0 3203 +3349 0 3203 +3349 0 3203 +3347 0 3203 +3347 0 3201 +3347 0 3201 +3345 0 3199 +3343 0 3199 +3341 0 3195 +3339 0 3193 +3335 0 3189 +3331 0 3183 +3323 0 3177 +3315 0 3167 +3303 861 3153 +3285 1528 3135 +3261 1850 3109 +3225 2085 3071 +3175 2281 3015 +3097 2457 2929 +2965 2617 2779 +2695 2771 2445 +0 2919 0 +0 3061 0 +0 3201 0 +0 3339 0 +0 3475 0 +0 3611 0 +0 3745 0 +0 3879 0 +0 4013 0 +3477 0 3323 +3477 0 3323 +3477 0 3323 +3477 0 3323 +3477 0 3323 +3477 0 3323 +3475 0 3321 +3475 0 3321 +3473 0 3319 +3473 0 3317 +3471 0 3315 +3467 0 3313 +3463 0 3309 +3459 0 3303 +3453 0 3295 +3443 0 3285 +3431 462 3271 +3413 1581 3253 +3389 1945 3225 +3353 2195 3187 +3303 2399 3129 +3223 2579 3039 +3089 2743 2879 +2813 2899 2507 +0 3047 0 +0 3191 0 +0 3331 0 +0 3469 0 +0 3607 0 +0 3743 0 +0 3877 0 +0 4011 0 +3607 0 3447 +3607 0 3447 +3607 0 3447 +3607 0 3447 +3607 0 3445 +3607 0 3445 +3605 0 3445 +3605 0 3445 +3605 0 3443 +3603 0 3441 +3601 0 3441 +3599 0 3439 +3597 0 3435 +3593 0 3431 +3589 0 3425 +3581 0 3417 +3573 0 3407 +3559 0 3393 +3541 1644 3373 +3517 2047 3347 +3483 2311 3307 +3431 2521 3247 +3351 2703 3153 +3215 2871 2987 +2933 3027 2579 +0 3177 0 +0 3321 0 +0 3463 0 +0 3601 0 +0 3739 0 +0 3875 0 +0 4009 0 +3737 0 3571 +3737 0 3571 +3737 0 3571 +3737 0 3571 +3737 0 3571 +3737 0 3571 +3737 0 3571 +3737 0 3569 +3735 0 3569 +3735 0 3569 +3733 0 3567 +3731 0 3565 +3729 0 3563 +3727 0 3559 +3723 0 3555 +3719 0 3549 +3711 0 3543 +3703 0 3531 +3689 0 3517 +3671 1717 3497 +3647 2155 3469 +3611 2429 3429 +3559 2645 3367 +3479 2831 3271 +3343 2999 3099 +3057 3157 2661 +0 3307 0 +0 3451 0 +0 3593 0 +0 3733 0 +0 3869 0 +0 4005 0 +3869 0 3699 +3869 0 3699 +3869 0 3699 +3869 0 3699 +3867 0 3697 +3867 0 3697 +3867 0 3697 +3867 0 3697 +3867 0 3697 +3867 0 3695 +3865 0 3695 +3865 0 3693 +3863 0 3691 +3861 0 3689 +3857 0 3687 +3853 0 3683 +3849 0 3677 +3841 0 3669 +3833 0 3657 +3819 0 3643 +3801 1798 3623 +3777 2269 3595 +3741 2551 3553 +3689 2771 3491 +3609 2959 3393 +3471 3129 3215 +3181 3287 2751 +0 3437 0 +0 3583 0 +0 3725 0 +0 3865 0 +0 4001 0 +3999 0 3827 +3999 0 3827 +3999 0 3827 +3999 0 3827 +3999 0 3827 +3999 0 3827 +3999 0 3825 +3999 0 3825 +3999 0 3825 +3997 0 3825 +3997 0 3823 +3997 0 3823 +3995 0 3821 +3993 0 3819 +3991 0 3817 +3989 0 3815 +3985 0 3809 +3979 0 3805 +3973 0 3797 +3963 0 3785 +3951 0 3771 +3933 1889 3751 +3907 2387 3721 +3873 2677 3679 +3819 2899 3617 +3739 3087 3517 +3601 3259 3335 +3309 3417 2849 +0 3569 0 +0 3715 0 +0 3857 0 +0 3995 0 +4095 0 3955 +4095 0 3955 +4095 0 3955 +4095 0 3955 +4095 0 3955 +4095 0 3955 +4095 0 3955 +4095 0 3955 +4095 0 3955 +4095 0 3955 +4095 0 3953 +4095 0 3953 +4095 0 3951 +4095 0 3951 +4095 0 3949 +4095 0 3947 +4095 0 3943 +4095 0 3939 +4095 0 3933 +4095 0 3925 +4095 0 3915 +4081 0 3899 +4063 1987 3879 +4039 2507 3849 +4003 2803 3807 +3951 3027 3745 +3869 3217 3643 +3731 3389 3459 +3437 3549 2955 +0 3699 0 +0 3845 0 +0 3987 0 +4095 0 4085 +4095 0 4085 +4095 0 4085 +4095 0 4085 +4095 0 4085 +4095 0 4085 +4095 0 4085 +4095 0 4085 +4095 0 4085 +4095 0 4085 +4095 0 4083 +4095 0 4083 +4095 0 4083 +4095 0 4081 +4095 0 4081 +4095 0 4079 +4095 0 4077 +4095 0 4073 +4095 0 4069 +4095 0 4063 +4095 0 4055 +4095 0 4043 +4095 0 4029 +4095 2093 4009 +4095 2631 3979 +4095 2931 3937 +4081 3157 3873 +4001 3347 3771 +3861 3519 3583 +3567 3679 3065 +0 3831 0 +0 3977 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 2203 4095 +4095 2757 4095 +4095 3059 4067 +4095 3287 4003 +4095 3479 3899 +3993 3651 3711 +3697 3811 3181 +0 3963 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 2319 4095 +4095 2885 4095 +4095 3189 4095 +4095 3417 4095 +4095 3609 4029 +4095 3783 3839 +3827 3943 3299 +1904 1463 2315 +1900 1469 2313 +1893 1475 2311 +1884 1484 2309 +1873 1496 2305 +1856 1511 2301 +1833 1530 2293 +1801 1555 2285 +1753 1586 2273 +1681 1625 2255 +1561 1672 2233 +1327 1728 2199 +282 1793 2149 +0 1868 2075 +0 1952 1949 +0 2045 1699 +0 2145 0 +0 2253 0 +0 2365 0 +0 2481 0 +0 2601 0 +0 2723 0 +0 2849 0 +0 2975 0 +0 3105 0 +0 3233 0 +0 3363 0 +0 3493 0 +0 3625 0 +0 3755 0 +0 3887 0 +0 4019 0 +1910 1463 2317 +1906 1468 2315 +1899 1475 2313 +1891 1483 2311 +1879 1495 2307 +1863 1510 2301 +1840 1530 2295 +1808 1554 2287 +1761 1586 2275 +1690 1624 2257 +1574 1671 2235 +1348 1727 2201 +456 1793 2151 +0 1868 2077 +0 1952 1953 +0 2045 1706 +0 2145 138 +0 2251 0 +0 2365 0 +0 2481 0 +0 2601 0 +0 2723 0 +0 2849 0 +0 2975 0 +0 3103 0 +0 3233 0 +0 3363 0 +0 3493 0 +0 3625 0 +0 3755 0 +0 3887 0 +0 4019 0 +1918 1462 2319 +1913 1467 2317 +1907 1474 2315 +1899 1482 2313 +1887 1494 2309 +1871 1509 2305 +1849 1529 2297 +1818 1554 2289 +1772 1585 2277 +1703 1623 2261 +1590 1670 2237 +1374 1727 2203 +617 1792 2155 +0 1867 2081 +0 1952 1958 +0 2045 1714 +0 2145 344 +0 2251 0 +0 2363 0 +0 2481 0 +0 2601 0 +0 2723 0 +0 2849 0 +0 2975 0 +0 3103 0 +0 3233 0 +0 3363 0 +0 3493 0 +0 3625 0 +0 3755 0 +0 3887 0 +0 4019 0 +1928 1460 2321 +1924 1465 2319 +1918 1472 2317 +1909 1481 2315 +1898 1493 2311 +1883 1508 2307 +1861 1528 2301 +1831 1552 2291 +1786 1584 2279 +1719 1622 2263 +1611 1670 2241 +1407 1726 2207 +769 1792 2159 +0 1867 2085 +0 1951 1964 +0 2044 1724 +0 2145 525 +0 2251 0 +0 2363 0 +0 2481 0 +0 2601 0 +0 2723 0 +0 2849 0 +0 2975 0 +0 3103 0 +0 3233 0 +0 3363 0 +0 3493 0 +0 3625 0 +0 3755 0 +0 3887 0 +0 4019 0 +1942 1458 2325 +1937 1463 2323 +1931 1470 2321 +1923 1479 2319 +1912 1491 2315 +1897 1506 2311 +1877 1526 2305 +1847 1551 2295 +1804 1582 2283 +1740 1621 2267 +1637 1668 2245 +1448 1725 2213 +916 1791 2165 +0 1866 2093 +0 1951 1972 +0 2044 1738 +0 2145 690 +0 2251 0 +0 2363 0 +0 2481 0 +0 2601 0 +0 2723 0 +0 2849 0 +0 2975 0 +0 3103 0 +0 3233 0 +0 3363 0 +0 3493 0 +0 3625 0 +0 3755 0 +0 3887 0 +0 4019 0 +1959 1456 2331 +1955 1461 2329 +1949 1468 2327 +1941 1477 2325 +1931 1489 2321 +1916 1504 2317 +1896 1524 2309 +1868 1549 2301 +1828 1580 2289 +1767 1619 2273 +1670 1667 2251 +1497 1723 2219 +1059 1789 2171 +0 1865 2101 +0 1950 1983 +0 2043 1757 +0 2143 845 +0 2251 0 +0 2363 0 +0 2479 0 +0 2601 0 +0 2723 0 +0 2849 0 +0 2975 0 +0 3103 0 +0 3233 0 +0 3363 0 +0 3493 0 +0 3625 0 +0 3755 0 +0 3887 0 +0 4019 0 +1981 1452 2337 +1977 1457 2335 +1972 1464 2333 +1964 1474 2331 +1954 1485 2327 +1941 1501 2323 +1922 1521 2317 +1895 1546 2309 +1857 1578 2297 +1800 1617 2281 +1711 1665 2259 +1556 1721 2227 +1199 1788 2181 +0 1864 2111 +0 1949 1998 +0 2042 1780 +0 2143 994 +0 2251 0 +0 2363 0 +0 2479 0 +0 2601 0 +0 2723 0 +0 2849 0 +0 2975 0 +0 3103 0 +0 3233 0 +0 3363 0 +0 3493 0 +0 3625 0 +0 3755 0 +0 3887 0 +0 4019 0 +2009 1448 2345 +2005 1453 2345 +2000 1460 2343 +1993 1469 2339 +1984 1481 2337 +1971 1497 2333 +1953 1517 2325 +1929 1542 2317 +1893 1574 2307 +1841 1614 2291 +1761 1662 2269 +1624 1719 2239 +1337 1786 2193 +0 1862 2125 +0 1947 2016 +0 2041 1809 +0 2141 1138 +0 2249 0 +0 2363 0 +0 2479 0 +0 2599 0 +0 2723 0 +0 2849 0 +0 2975 0 +0 3103 0 +0 3233 0 +0 3363 0 +0 3493 0 +0 3625 0 +0 3755 0 +0 3887 0 +0 4019 0 +2044 1441 2357 +2040 1447 2355 +2036 1454 2353 +2029 1463 2351 +2021 1475 2349 +2009 1491 2343 +1993 1511 2337 +1970 1537 2329 +1938 1569 2319 +1891 1609 2303 +1819 1658 2283 +1702 1715 2253 +1473 1783 2209 +536 1859 2145 +0 1945 2039 +0 2039 1845 +0 2141 1279 +0 2249 0 +0 2361 0 +0 2479 0 +0 2599 0 +0 2723 0 +0 2849 0 +0 2975 0 +0 3103 0 +0 3233 0 +0 3363 0 +0 3493 0 +0 3625 0 +0 3755 0 +0 3887 0 +0 4019 0 +2087 1433 2371 +2083 1438 2371 +2079 1445 2369 +2073 1455 2367 +2065 1467 2363 +2055 1483 2359 +2040 1504 2353 +2020 1530 2345 +1991 1563 2335 +1950 1603 2321 +1887 1652 2299 +1788 1711 2271 +1609 1779 2229 +1134 1856 2167 +0 1942 2069 +0 2037 1889 +0 2139 1417 +0 2247 0 +0 2361 0 +0 2477 0 +0 2599 0 +0 2723 0 +0 2847 0 +0 2975 0 +0 3103 0 +0 3233 0 +0 3363 0 +0 3493 0 +0 3625 0 +0 3755 0 +0 3887 0 +0 4019 0 +2139 1421 2391 +2135 1427 2389 +2131 1434 2389 +2127 1444 2385 +2119 1456 2383 +2111 1473 2379 +2097 1494 2373 +2079 1521 2365 +2055 1554 2355 +2018 1595 2341 +1965 1645 2323 +1883 1704 2295 +1743 1773 2255 +1444 1851 2197 +0 1938 2105 +0 2034 1943 +0 2137 1554 +0 2245 0 +0 2359 0 +0 2477 0 +0 2597 0 +0 2721 0 +0 2847 0 +0 2975 0 +0 3103 0 +0 3233 0 +0 3363 0 +0 3493 0 +0 3623 0 +0 3755 0 +0 3887 0 +0 4019 0 +2199 1405 2415 +2197 1411 2415 +2193 1418 2413 +2189 1428 2411 +2183 1441 2407 +2175 1458 2403 +2163 1480 2399 +2149 1508 2391 +2127 1542 2383 +2097 1584 2369 +2051 1635 2351 +1985 1696 2325 +1877 1766 2289 +1675 1845 2235 +1046 1933 2149 +0 2030 2005 +0 2133 1690 +0 2243 0 +0 2357 0 +0 2475 0 +0 2597 0 +0 2721 0 +0 2847 0 +0 2973 0 +0 3103 0 +0 3233 0 +0 3363 0 +0 3493 0 +0 3623 0 +0 3755 0 +0 3887 0 +0 4019 0 +2269 1382 2447 +2267 1388 2445 +2265 1396 2443 +2261 1407 2441 +2255 1421 2439 +2249 1438 2435 +2239 1461 2431 +2227 1490 2423 +2209 1526 2415 +2183 1569 2403 +2147 1622 2385 +2093 1684 2363 +2010 1756 2329 +1869 1837 2279 +1564 1926 2203 +0 2024 2077 +0 2129 1825 +0 2239 0 +0 2353 0 +0 2473 0 +0 2595 0 +0 2719 0 +0 2845 0 +0 2973 0 +0 3101 0 +0 3231 0 +0 3361 0 +0 3493 0 +0 3623 0 +0 3755 0 +0 3887 0 +0 4019 0 +2349 1350 2485 +2347 1357 2483 +2345 1365 2481 +2343 1377 2481 +2339 1391 2477 +2333 1410 2475 +2325 1434 2469 +2313 1465 2463 +2299 1502 2455 +2279 1548 2445 +2249 1603 2429 +2207 1668 2407 +2143 1742 2377 +2042 1825 2333 +1857 1917 2267 +1353 2016 2159 +0 2123 1959 +0 2233 1343 +0 2351 0 +0 2469 0 +0 2593 0 +0 2717 0 +0 2845 0 +0 2973 0 +0 3101 0 +0 3231 0 +0 3361 0 +0 3493 0 +0 3623 0 +0 3755 0 +0 3887 0 +0 4019 0 +2439 1303 2531 +2437 1311 2529 +2435 1320 2529 +2433 1333 2527 +2429 1349 2525 +2425 1369 2521 +2417 1396 2517 +2409 1429 2513 +2397 1469 2505 +2381 1519 2495 +2357 1577 2481 +2325 1645 2463 +2277 1723 2435 +2203 1809 2397 +2081 1904 2339 +1842 2006 2249 +650 2115 2093 +0 2227 1726 +0 2345 0 +0 2467 0 +0 2589 0 +0 2715 0 +0 2843 0 +0 2971 0 +0 3101 0 +0 3231 0 +0 3361 0 +0 3491 0 +0 3623 0 +0 3755 0 +0 3887 0 +0 4017 0 +2535 1232 2587 +2535 1241 2585 +2533 1252 2585 +2531 1266 2583 +2527 1285 2581 +2523 1309 2579 +2519 1339 2575 +2511 1376 2569 +2503 1421 2563 +2489 1476 2555 +2471 1540 2543 +2445 1613 2527 +2409 1696 2503 +2355 1787 2469 +2271 1886 2421 +2129 1992 2347 +1820 2103 2225 +0 2219 1984 +0 2339 715 +0 2461 0 +0 2585 0 +0 2713 0 +0 2841 0 +0 2969 0 +0 3099 0 +0 3229 0 +0 3361 0 +0 3491 0 +0 3623 0 +0 3755 0 +0 3885 0 +0 4017 0 +2639 1115 2651 +2639 1126 2651 +2637 1141 2649 +2635 1159 2649 +2633 1182 2647 +2629 1212 2645 +2625 1249 2641 +2621 1294 2637 +2613 1348 2631 +2603 1411 2623 +2589 1484 2613 +2569 1566 2599 +2541 1657 2579 +2503 1756 2553 +2443 1861 2513 +2351 1972 2453 +2187 2087 2359 +1790 2207 2191 +0 2329 1781 +0 2455 0 +0 2581 0 +0 2709 0 +0 2837 0 +0 2967 0 +0 3097 0 +0 3229 0 +0 3359 0 +0 3491 0 +0 3623 0 +0 3753 0 +0 3885 0 +0 4017 0 +2749 890 2725 +2749 908 2725 +2747 930 2725 +2745 959 2723 +2743 995 2721 +2741 1039 2719 +2739 1092 2717 +2735 1154 2713 +2729 1226 2709 +2721 1307 2703 +2709 1397 2695 +2695 1495 2683 +2673 1599 2665 +2645 1710 2643 +2603 1825 2611 +2539 1944 2563 +2437 2067 2491 +2253 2191 2373 +1746 2317 2141 +0 2445 1143 +0 2573 0 +0 2703 0 +0 2833 0 +0 2965 0 +0 3095 0 +0 3227 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +2863 0 2809 +2863 107 2809 +2863 226 2809 +2861 348 2807 +2859 473 2807 +2857 599 2805 +2855 727 2803 +2851 856 2799 +2847 986 2795 +2841 1116 2791 +2833 1246 2783 +2821 1377 2773 +2807 1509 2761 +2785 1640 2741 +2755 1772 2715 +2709 1904 2679 +2643 2036 2623 +2533 2167 2539 +2329 2299 2391 +1679 2431 2063 +0 2563 0 +0 2695 0 +0 2827 0 +0 2959 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +2981 0 2901 +2981 0 2901 +2981 0 2901 +2981 0 2899 +2979 0 2899 +2977 0 2897 +2975 0 2895 +2973 0 2893 +2969 0 2891 +2965 568 2887 +2959 908 2881 +2951 1150 2873 +2939 1350 2861 +2923 1527 2847 +2901 1690 2827 +2869 1844 2797 +2821 1992 2757 +2751 2135 2693 +2635 2275 2595 +2413 2413 2413 +1570 2551 1934 +0 2685 0 +0 2821 0 +0 2955 0 +0 3087 0 +0 3221 0 +0 3353 0 +0 3487 0 +0 3619 0 +0 3751 0 +0 3885 0 +0 4017 0 +3103 0 3001 +3103 0 3001 +3103 0 3001 +3103 0 3001 +3101 0 2999 +3101 0 2999 +3099 0 2997 +3097 0 2995 +3095 0 2993 +3091 0 2989 +3087 0 2985 +3079 228 2979 +3071 978 2969 +3059 1310 2959 +3043 1550 2943 +3019 1749 2921 +2987 1925 2889 +2939 2087 2843 +2865 2241 2773 +2745 2389 2659 +2507 2531 2443 +1368 2673 1669 +0 2811 0 +0 2947 0 +0 3083 0 +0 3217 0 +0 3351 0 +0 3485 0 +0 3617 0 +0 3751 0 +0 3883 0 +0 4015 0 +3227 0 3107 +3227 0 3107 +3227 0 3107 +3227 0 3107 +3227 0 3107 +3225 0 3105 +3225 0 3105 +3223 0 3103 +3221 0 3101 +3219 0 3099 +3215 0 3095 +3209 0 3089 +3203 0 3083 +3195 541 3073 +3183 1251 3061 +3165 1579 3045 +3141 1817 3021 +3109 2015 2987 +3059 2191 2937 +2983 2353 2861 +2859 2505 2735 +2609 2653 2479 +735 2797 0 +0 2937 0 +0 3075 0 +0 3211 0 +0 3347 0 +0 3481 0 +0 3615 0 +0 3749 0 +0 3881 0 +0 4015 0 +3353 0 3219 +3353 0 3219 +3353 0 3219 +3353 0 3219 +3353 0 3219 +3353 0 3217 +3351 0 3217 +3351 0 3215 +3349 0 3215 +3347 0 3213 +3343 0 3209 +3341 0 3205 +3335 0 3201 +3329 0 3193 +3319 0 3185 +3307 1158 3171 +3291 1616 3153 +3267 1895 3129 +3233 2113 3093 +3183 2299 3039 +3105 2469 2957 +2977 2627 2819 +2715 2777 2523 +0 2923 0 +0 3065 0 +0 3203 0 +0 3341 0 +0 3477 0 +0 3613 0 +0 3747 0 +0 3881 0 +0 4013 0 +3481 0 3337 +3481 0 3335 +3481 0 3335 +3481 0 3335 +3481 0 3335 +3481 0 3335 +3479 0 3333 +3479 0 3333 +3477 0 3331 +3475 0 3331 +3473 0 3327 +3471 0 3325 +3467 0 3321 +3463 0 3315 +3455 0 3309 +3447 0 3299 +3435 994 3285 +3417 1660 3267 +3393 1982 3241 +3359 2217 3203 +3307 2413 3147 +3229 2589 3061 +3097 2749 2911 +2827 2903 2577 +0 3051 0 +0 3193 0 +0 3333 0 +0 3471 0 +0 3607 0 +0 3743 0 +0 3877 0 +0 4011 0 +3611 0 3457 +3611 0 3455 +3609 0 3455 +3609 0 3455 +3609 0 3455 +3609 0 3455 +3609 0 3455 +3607 0 3453 +3607 0 3453 +3605 0 3451 +3605 0 3449 +3603 0 3447 +3599 0 3445 +3595 0 3441 +3591 0 3435 +3585 0 3427 +3575 0 3417 +3563 594 3403 +3545 1714 3385 +3521 2077 3357 +3485 2327 3319 +3435 2531 3261 +3355 2711 3171 +3221 2875 3011 +2945 3031 2639 +0 3179 0 +0 3323 0 +0 3463 0 +0 3603 0 +0 3739 0 +0 3875 0 +0 4009 0 +3739 0 3579 +3739 0 3579 +3739 0 3579 +3739 0 3579 +3739 0 3579 +3739 0 3577 +3739 0 3577 +3739 0 3577 +3737 0 3577 +3737 0 3575 +3735 0 3575 +3733 0 3573 +3731 0 3571 +3729 0 3567 +3725 0 3563 +3721 0 3557 +3713 0 3549 +3705 0 3539 +3691 0 3525 +3673 1776 3505 +3649 2179 3479 +3615 2443 3439 +3563 2653 3379 +3483 2835 3285 +3347 3003 3119 +3065 3159 2711 +0 3309 0 +0 3453 0 +0 3595 0 +0 3733 0 +0 3871 0 +0 4007 0 +3869 0 3703 +3869 0 3703 +3869 0 3703 +3869 0 3703 +3869 0 3703 +3869 0 3703 +3869 0 3703 +3869 0 3703 +3869 0 3701 +3867 0 3701 +3867 0 3701 +3865 0 3699 +3863 0 3697 +3861 0 3695 +3859 0 3691 +3855 0 3687 +3851 0 3683 +3843 0 3675 +3835 0 3663 +3821 0 3649 +3803 1849 3629 +3779 2287 3601 +3743 2561 3561 +3691 2777 3499 +3611 2963 3403 +3475 3131 3231 +3189 3289 2793 +0 3439 0 +0 3583 0 +0 3725 0 +0 3865 0 +0 4001 0 +4001 0 3831 +4001 0 3831 +4001 0 3831 +4001 0 3831 +4001 0 3831 +4001 0 3831 +3999 0 3829 +3999 0 3829 +3999 0 3829 +3999 0 3829 +3999 0 3827 +3997 0 3827 +3997 0 3825 +3995 0 3823 +3993 0 3821 +3989 0 3819 +3985 0 3815 +3981 0 3809 +3975 0 3801 +3965 0 3791 +3951 0 3775 +3935 1931 3755 +3909 2401 3727 +3873 2683 3685 +3821 2903 3623 +3741 3091 3525 +3603 3261 3347 +3313 3419 2883 +0 3569 0 +0 3715 0 +0 3857 0 +0 3997 0 +4095 0 3959 +4095 0 3959 +4095 0 3959 +4095 0 3959 +4095 0 3959 +4095 0 3959 +4095 0 3959 +4095 0 3957 +4095 0 3957 +4095 0 3957 +4095 0 3957 +4095 0 3955 +4095 0 3955 +4095 0 3953 +4095 0 3951 +4095 0 3949 +4095 0 3947 +4095 0 3943 +4095 0 3937 +4095 0 3929 +4095 0 3917 +4083 0 3903 +4065 2021 3883 +4041 2519 3853 +4005 2809 3811 +3951 3031 3749 +3871 3219 3649 +3733 3391 3467 +3441 3549 2981 +0 3701 0 +0 3847 0 +0 3989 0 +4095 0 4087 +4095 0 4087 +4095 0 4087 +4095 0 4087 +4095 0 4087 +4095 0 4087 +4095 0 4087 +4095 0 4087 +4095 0 4087 +4095 0 4087 +4095 0 4087 +4095 0 4085 +4095 0 4085 +4095 0 4083 +4095 0 4083 +4095 0 4081 +4095 0 4079 +4095 0 4075 +4095 0 4071 +4095 0 4065 +4095 0 4057 +4095 0 4047 +4095 0 4031 +4095 2119 4011 +4095 2639 3981 +4095 2935 3939 +4083 3159 3877 +4001 3349 3775 +3863 3521 3591 +3569 3681 3087 +0 3831 0 +0 3977 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 2225 4095 +4095 2763 4095 +4095 3063 4069 +4095 3289 4005 +4095 3479 3903 +3993 3651 3715 +3699 3811 3197 +0 3963 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 2335 4095 +4095 2889 4095 +4095 3191 4095 +4095 3419 4095 +4095 3611 4031 +4095 3783 3843 +3829 3943 3313 +2035 1592 2447 +2032 1596 2445 +2027 1601 2445 +2021 1608 2443 +2012 1617 2439 +2000 1629 2435 +1983 1644 2431 +1960 1663 2425 +1927 1688 2415 +1879 1719 2403 +1805 1757 2387 +1684 1804 2363 +1443 1860 2329 +219 1926 2281 +0 2001 2205 +0 2085 2079 +0 2177 1827 +0 2277 0 +0 2385 0 +0 2497 0 +0 2613 0 +0 2733 0 +0 2857 0 +0 2981 0 +0 3109 0 +0 3237 0 +0 3365 0 +0 3495 0 +0 3625 0 +0 3757 0 +0 3887 0 +0 4019 0 +2040 1592 2447 +2036 1596 2447 +2032 1601 2445 +2025 1607 2443 +2017 1616 2441 +2005 1628 2437 +1988 1643 2433 +1965 1662 2425 +1933 1687 2417 +1885 1718 2405 +1813 1757 2387 +1693 1804 2365 +1459 1860 2331 +414 1925 2281 +0 2000 2207 +0 2085 2081 +0 2177 1831 +0 2277 16 +0 2385 0 +0 2497 0 +0 2613 0 +0 2733 0 +0 2857 0 +0 2981 0 +0 3109 0 +0 3237 0 +0 3365 0 +0 3495 0 +0 3625 0 +0 3757 0 +0 3887 0 +0 4019 0 +2046 1591 2449 +2042 1595 2449 +2038 1600 2447 +2031 1607 2445 +2023 1616 2443 +2011 1627 2439 +1995 1642 2433 +1972 1662 2427 +1940 1687 2419 +1894 1718 2407 +1822 1756 2389 +1706 1803 2367 +1480 1859 2333 +588 1925 2285 +0 2000 2209 +0 2085 2085 +0 2177 1838 +0 2277 270 +0 2385 0 +0 2497 0 +0 2613 0 +0 2733 0 +0 2855 0 +0 2981 0 +0 3107 0 +0 3237 0 +0 3365 0 +0 3495 0 +0 3625 0 +0 3757 0 +0 3887 0 +0 4019 0 +2053 1590 2451 +2051 1594 2451 +2046 1599 2449 +2039 1606 2447 +2031 1615 2445 +2019 1626 2441 +2004 1641 2437 +1981 1661 2429 +1950 1686 2421 +1904 1717 2409 +1835 1756 2393 +1722 1803 2369 +1507 1859 2335 +749 1924 2287 +0 2000 2213 +0 2083 2089 +0 2177 1846 +0 2277 476 +0 2383 0 +0 2497 0 +0 2613 0 +0 2733 0 +0 2855 0 +0 2981 0 +0 3107 0 +0 3237 0 +0 3365 0 +0 3495 0 +0 3625 0 +0 3757 0 +0 3887 0 +0 4019 0 +2063 1588 2455 +2061 1592 2453 +2055 1597 2453 +2049 1604 2451 +2042 1613 2447 +2030 1625 2443 +2015 1640 2439 +1993 1660 2433 +1963 1685 2423 +1918 1716 2411 +1851 1755 2395 +1743 1802 2373 +1540 1858 2339 +902 1924 2291 +0 1999 2217 +0 2083 2097 +0 2177 1857 +0 2277 657 +0 2383 0 +0 2495 0 +0 2613 0 +0 2733 0 +0 2855 0 +0 2981 0 +0 3107 0 +0 3237 0 +0 3365 0 +0 3495 0 +0 3625 0 +0 3757 0 +0 3887 0 +0 4019 0 +2077 1586 2459 +2073 1590 2457 +2069 1596 2455 +2063 1602 2453 +2055 1611 2451 +2045 1623 2447 +2030 1638 2443 +2009 1658 2437 +1979 1683 2429 +1937 1714 2417 +1872 1753 2399 +1769 1801 2377 +1580 1857 2345 +1048 1923 2297 +0 1998 2225 +0 2083 2105 +0 2175 1871 +0 2277 822 +0 2383 0 +0 2495 0 +0 2613 0 +0 2733 0 +0 2855 0 +0 2981 0 +0 3107 0 +0 3237 0 +0 3365 0 +0 3495 0 +0 3625 0 +0 3757 0 +0 3887 0 +0 4019 0 +2095 1584 2463 +2091 1588 2463 +2087 1593 2461 +2081 1600 2459 +2073 1609 2457 +2063 1621 2453 +2049 1636 2449 +2029 1656 2441 +2000 1681 2433 +1960 1712 2421 +1899 1751 2405 +1802 1799 2383 +1630 1855 2351 +1191 1922 2303 +0 1997 2233 +0 2081 2115 +0 2175 1889 +0 2275 977 +0 2383 0 +0 2495 0 +0 2613 0 +0 2733 0 +0 2855 0 +0 2981 0 +0 3107 0 +0 3235 0 +0 3365 0 +0 3495 0 +0 3625 0 +0 3757 0 +0 3887 0 +0 4019 0 +2117 1580 2471 +2113 1584 2469 +2109 1590 2467 +2103 1597 2465 +2097 1606 2463 +2087 1618 2459 +2073 1633 2455 +2053 1653 2449 +2027 1678 2441 +1989 1710 2429 +1932 1749 2413 +1843 1797 2391 +1688 1854 2359 +1331 1920 2313 +0 1996 2243 +0 2081 2129 +0 2175 1912 +0 2275 1126 +0 2383 0 +0 2495 0 +0 2611 0 +0 2733 0 +0 2855 0 +0 2981 0 +0 3107 0 +0 3235 0 +0 3365 0 +0 3495 0 +0 3625 0 +0 3757 0 +0 3887 0 +0 4019 0 +2143 1576 2479 +2141 1580 2477 +2137 1585 2477 +2133 1592 2475 +2125 1601 2473 +2117 1613 2469 +2103 1629 2465 +2085 1649 2459 +2061 1674 2449 +2025 1706 2439 +1973 1746 2423 +1893 1794 2401 +1756 1851 2371 +1469 1918 2325 +0 1994 2257 +0 2079 2147 +0 2173 1941 +0 2273 1270 +0 2381 0 +0 2495 0 +0 2611 0 +0 2731 0 +0 2855 0 +0 2981 0 +0 3107 0 +0 3235 0 +0 3365 0 +0 3495 0 +0 3625 0 +0 3757 0 +0 3887 0 +0 4019 0 +2179 1569 2491 +2175 1573 2489 +2173 1579 2487 +2167 1586 2487 +2161 1595 2483 +2153 1607 2481 +2141 1623 2475 +2125 1643 2471 +2103 1669 2461 +2069 1701 2451 +2023 1741 2435 +1951 1790 2415 +1834 1848 2385 +1605 1915 2341 +668 1991 2277 +0 2077 2171 +0 2171 1977 +0 2273 1411 +0 2381 0 +0 2493 0 +0 2611 0 +0 2731 0 +0 2855 0 +0 2981 0 +0 3107 0 +0 3235 0 +0 3365 0 +0 3495 0 +0 3625 0 +0 3757 0 +0 3887 0 +0 4019 0 +2221 1561 2505 +2219 1565 2505 +2215 1570 2503 +2211 1578 2501 +2205 1587 2499 +2197 1599 2495 +2187 1615 2491 +2173 1636 2485 +2153 1662 2477 +2123 1695 2467 +2081 1736 2453 +2020 1785 2433 +1920 1843 2403 +1741 1911 2361 +1266 1988 2299 +0 2075 2201 +0 2169 2022 +0 2271 1549 +0 2379 0 +0 2493 0 +0 2609 0 +0 2731 0 +0 2855 0 +0 2979 0 +0 3107 0 +0 3235 0 +0 3365 0 +0 3495 0 +0 3625 0 +0 3757 0 +0 3887 0 +0 4019 0 +2273 1549 2525 +2271 1553 2523 +2267 1559 2521 +2263 1566 2521 +2259 1576 2519 +2251 1589 2515 +2243 1605 2511 +2229 1626 2505 +2211 1653 2497 +2187 1686 2487 +2151 1727 2473 +2097 1777 2455 +2015 1837 2427 +1875 1905 2387 +1576 1983 2329 +0 2071 2237 +0 2165 2075 +0 2269 1686 +0 2377 0 +0 2491 0 +0 2609 0 +0 2729 0 +0 2853 0 +0 2979 0 +0 3107 0 +0 3235 0 +0 3365 0 +0 3495 0 +0 3625 0 +0 3757 0 +0 3887 0 +0 4019 0 +2333 1532 2549 +2331 1537 2547 +2329 1543 2547 +2325 1550 2545 +2321 1560 2543 +2315 1574 2539 +2307 1591 2537 +2295 1612 2531 +2281 1640 2523 +2259 1674 2515 +2229 1717 2501 +2183 1768 2483 +2117 1828 2457 +2009 1898 2421 +1807 1977 2367 +1178 2065 2283 +0 2161 2137 +0 2265 1822 +0 2375 0 +0 2489 0 +0 2607 0 +0 2729 0 +0 2853 0 +0 2979 0 +0 3107 0 +0 3235 0 +0 3365 0 +0 3495 0 +0 3625 0 +0 3755 0 +0 3887 0 +0 4019 0 +2403 1510 2579 +2401 1514 2579 +2399 1520 2577 +2397 1528 2575 +2393 1539 2573 +2389 1553 2571 +2381 1571 2567 +2371 1593 2563 +2359 1622 2557 +2341 1658 2547 +2315 1701 2535 +2279 1754 2517 +2225 1816 2495 +2143 1888 2461 +2001 1969 2411 +1696 2059 2335 +0 2157 2209 +0 2261 1957 +0 2371 0 +0 2485 0 +0 2605 0 +0 2727 0 +0 2851 0 +0 2977 0 +0 3105 0 +0 3235 0 +0 3363 0 +0 3493 0 +0 3625 0 +0 3755 0 +0 3887 0 +0 4019 0 +2483 1477 2617 +2481 1482 2617 +2481 1489 2615 +2477 1497 2615 +2475 1509 2613 +2471 1523 2609 +2465 1542 2607 +2457 1566 2603 +2445 1597 2597 +2431 1634 2587 +2411 1680 2577 +2381 1735 2561 +2339 1800 2539 +2275 1874 2509 +2175 1957 2465 +1990 2049 2399 +1485 2149 2291 +0 2255 2091 +0 2367 1476 +0 2483 0 +0 2603 0 +0 2725 0 +0 2849 0 +0 2977 0 +0 3105 0 +0 3233 0 +0 3363 0 +0 3493 0 +0 3625 0 +0 3755 0 +0 3887 0 +0 4019 0 +2571 1430 2663 +2571 1435 2663 +2569 1443 2661 +2567 1452 2661 +2565 1465 2659 +2561 1481 2657 +2557 1502 2653 +2549 1528 2649 +2541 1561 2645 +2529 1602 2637 +2513 1651 2627 +2489 1709 2613 +2457 1777 2595 +2409 1855 2567 +2335 1941 2529 +2213 2036 2471 +1974 2139 2381 +782 2247 2225 +0 2359 1859 +0 2477 0 +0 2599 0 +0 2721 0 +0 2847 0 +0 2975 0 +0 3103 0 +0 3233 0 +0 3363 0 +0 3493 0 +0 3625 0 +0 3755 0 +0 3887 0 +0 4019 0 +2669 1358 2719 +2667 1364 2719 +2667 1373 2717 +2665 1384 2717 +2663 1398 2715 +2659 1417 2713 +2655 1441 2711 +2651 1471 2707 +2643 1508 2703 +2635 1553 2695 +2621 1608 2687 +2603 1672 2675 +2577 1745 2659 +2541 1828 2635 +2487 1919 2601 +2405 2018 2553 +2261 2123 2479 +1953 2235 2357 +0 2351 2115 +0 2471 847 +0 2593 0 +0 2717 0 +0 2845 0 +0 2973 0 +0 3101 0 +0 3231 0 +0 3361 0 +0 3493 0 +0 3623 0 +0 3755 0 +0 3887 0 +0 4019 0 +2771 1239 2783 +2771 1248 2783 +2771 1259 2783 +2769 1273 2781 +2767 1291 2781 +2765 1315 2779 +2763 1344 2777 +2757 1381 2773 +2753 1426 2769 +2745 1480 2763 +2735 1543 2757 +2721 1616 2745 +2701 1698 2731 +2673 1789 2711 +2635 1888 2685 +2575 1993 2645 +2483 2105 2585 +2319 2219 2491 +1922 2339 2323 +0 2461 1913 +0 2587 0 +0 2713 0 +0 2841 0 +0 2969 0 +0 3099 0 +0 3229 0 +0 3361 0 +0 3491 0 +0 3623 0 +0 3755 0 +0 3887 0 +0 4017 0 +2881 1008 2859 +2881 1022 2857 +2881 1039 2857 +2879 1062 2857 +2877 1091 2855 +2877 1127 2853 +2873 1171 2851 +2871 1224 2849 +2867 1286 2845 +2861 1358 2841 +2853 1439 2835 +2841 1529 2827 +2827 1627 2815 +2807 1731 2799 +2777 1842 2775 +2735 1957 2743 +2671 2077 2695 +2569 2199 2623 +2385 2323 2505 +1878 2449 2273 +0 2577 1276 +0 2705 0 +0 2835 0 +0 2965 0 +0 3097 0 +0 3227 0 +0 3359 0 +0 3491 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +2995 13 2941 +2995 124 2941 +2995 239 2941 +2995 358 2941 +2993 481 2939 +2991 605 2939 +2989 731 2937 +2987 859 2935 +2985 988 2931 +2979 1117 2927 +2973 1248 2923 +2965 1378 2915 +2955 1510 2905 +2939 1641 2893 +2917 1772 2873 +2887 1904 2847 +2841 2036 2811 +2775 2167 2755 +2665 2299 2671 +2461 2431 2523 +1811 2563 2195 +0 2695 0 +0 2827 0 +0 2959 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +3115 0 3035 +3115 0 3033 +3113 0 3033 +3113 0 3033 +3113 0 3033 +3111 0 3031 +3109 0 3029 +3107 0 3029 +3105 0 3025 +3101 0 3023 +3097 700 3019 +3091 1040 3013 +3083 1282 3005 +3071 1482 2993 +3055 1659 2979 +3033 1822 2959 +3001 1976 2931 +2955 2123 2889 +2883 2267 2825 +2769 2407 2727 +2545 2545 2545 +1703 2683 2065 +0 2817 0 +0 2953 0 +0 3087 0 +0 3221 0 +0 3353 0 +0 3487 0 +0 3619 0 +0 3751 0 +0 3883 0 +0 4017 0 +3237 0 3133 +3235 0 3133 +3235 0 3133 +3235 0 3133 +3235 0 3133 +3233 0 3131 +3233 0 3131 +3231 0 3129 +3229 0 3127 +3227 0 3125 +3223 0 3121 +3219 0 3117 +3211 360 3111 +3203 1109 3101 +3191 1442 3091 +3175 1682 3075 +3151 1881 3053 +3119 2057 3021 +3071 2219 2975 +2997 2373 2905 +2877 2521 2791 +2639 2663 2575 +1500 2805 1801 +0 2943 0 +0 3079 0 +0 3215 0 +0 3349 0 +0 3483 0 +0 3617 0 +0 3749 0 +0 3883 0 +0 4015 0 +3361 0 3241 +3359 0 3239 +3359 0 3239 +3359 0 3239 +3359 0 3239 +3359 0 3239 +3357 0 3237 +3357 0 3237 +3355 0 3235 +3353 0 3233 +3351 0 3231 +3347 0 3227 +3341 0 3221 +3335 0 3215 +3327 673 3207 +3315 1383 3193 +3297 1711 3177 +3273 1949 3153 +3241 2147 3119 +3191 2323 3069 +3115 2485 2993 +2991 2637 2867 +2741 2785 2611 +867 2929 0 +0 3069 0 +0 3207 0 +0 3343 0 +0 3479 0 +0 3613 0 +0 3747 0 +0 3881 0 +0 4013 0 +3487 0 3351 +3487 0 3351 +3485 0 3351 +3485 0 3351 +3485 0 3351 +3485 0 3351 +3485 0 3349 +3483 0 3349 +3483 0 3347 +3481 0 3347 +3479 0 3345 +3475 0 3341 +3473 0 3337 +3467 0 3333 +3461 0 3325 +3451 0 3317 +3439 1290 3303 +3423 1748 3285 +3399 2027 3261 +3365 2245 3225 +3315 2431 3171 +3237 2601 3091 +3109 2759 2951 +2847 2909 2655 +0 3055 0 +0 3197 0 +0 3335 0 +0 3473 0 +0 3609 0 +0 3745 0 +0 3879 0 +0 4013 0 +3613 0 3469 +3613 0 3469 +3613 0 3469 +3613 0 3467 +3613 0 3467 +3613 0 3467 +3613 0 3467 +3611 0 3465 +3611 0 3465 +3609 0 3463 +3609 0 3463 +3607 0 3461 +3603 0 3457 +3599 0 3453 +3595 0 3447 +3587 0 3441 +3579 0 3431 +3567 1125 3417 +3549 1792 3399 +3525 2113 3373 +3491 2349 3335 +3439 2545 3281 +3361 2721 3193 +3231 2883 3043 +2961 3035 2709 +0 3183 0 +0 3325 0 +0 3465 0 +0 3603 0 +0 3739 0 +0 3875 0 +0 4009 0 +3743 0 3589 +3743 0 3589 +3743 0 3589 +3743 0 3587 +3741 0 3587 +3741 0 3587 +3741 0 3587 +3741 0 3587 +3741 0 3585 +3739 0 3585 +3739 0 3583 +3737 0 3581 +3735 0 3579 +3731 0 3577 +3729 0 3573 +3723 0 3567 +3717 0 3559 +3707 0 3549 +3695 726 3537 +3677 1846 3517 +3653 2209 3489 +3617 2459 3451 +3567 2663 3393 +3487 2843 3303 +3353 3007 3145 +3077 3163 2771 +0 3311 0 +0 3455 0 +0 3595 0 +0 3735 0 +0 3871 0 +0 4007 0 +3871 0 3711 +3871 0 3711 +3871 0 3711 +3871 0 3711 +3871 0 3711 +3871 0 3711 +3871 0 3711 +3871 0 3709 +3871 0 3709 +3869 0 3709 +3869 0 3707 +3867 0 3707 +3867 0 3705 +3863 0 3703 +3861 0 3699 +3857 0 3695 +3853 0 3689 +3845 0 3683 +3837 0 3671 +3823 0 3657 +3807 1909 3637 +3781 2311 3611 +3747 2575 3571 +3695 2785 3511 +3615 2969 3417 +3479 3135 3251 +3197 3291 2843 +0 3441 0 +0 3585 0 +0 3727 0 +0 3865 0 +0 4003 0 +4003 0 3837 +4003 0 3835 +4001 0 3835 +4001 0 3835 +4001 0 3835 +4001 0 3835 +4001 0 3835 +4001 0 3835 +4001 0 3835 +4001 0 3835 +3999 0 3833 +3999 0 3833 +3997 0 3831 +3997 0 3829 +3995 0 3827 +3991 0 3825 +3987 0 3819 +3983 0 3815 +3975 0 3807 +3967 0 3797 +3953 0 3781 +3935 1981 3761 +3911 2419 3733 +3875 2693 3693 +3823 2909 3633 +3743 3095 3535 +3607 3263 3363 +3321 3421 2925 +0 3571 0 +0 3715 0 +0 3857 0 +0 3997 0 +4095 0 3963 +4095 0 3963 +4095 0 3963 +4095 0 3963 +4095 0 3963 +4095 0 3963 +4095 0 3963 +4095 0 3963 +4095 0 3961 +4095 0 3961 +4095 0 3961 +4095 0 3961 +4095 0 3959 +4095 0 3957 +4095 0 3957 +4095 0 3953 +4095 0 3951 +4095 0 3947 +4095 0 3941 +4095 0 3933 +4095 0 3923 +4083 0 3907 +4067 2063 3887 +4041 2533 3859 +4005 2815 3817 +3953 3035 3755 +3873 3223 3657 +3735 3393 3479 +3447 3551 3015 +0 3701 0 +0 3847 0 +0 3989 0 +4095 0 4091 +4095 0 4091 +4095 0 4091 +4095 0 4091 +4095 0 4091 +4095 0 4091 +4095 0 4091 +4095 0 4091 +4095 0 4091 +4095 0 4089 +4095 0 4089 +4095 0 4089 +4095 0 4089 +4095 0 4087 +4095 0 4085 +4095 0 4085 +4095 0 4081 +4095 0 4079 +4095 0 4075 +4095 0 4069 +4095 0 4061 +4095 0 4049 +4095 0 4035 +4095 2153 4015 +4095 2651 3985 +4095 2941 3945 +4085 3163 3881 +4003 3351 3781 +3865 3523 3599 +3573 3681 3115 +0 3833 0 +0 3979 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 2251 4095 +4095 2771 4095 +4095 3067 4071 +4095 3291 4009 +4095 3481 3907 +3995 3653 3723 +3701 3813 3219 +0 3963 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 2357 4095 +4095 2895 4095 +4095 3195 4095 +4095 3421 4095 +4095 3611 4035 +4095 3783 3847 +3831 3943 3329 +2167 1722 2579 +2165 1725 2577 +2161 1729 2577 +2155 1734 2575 +2149 1741 2573 +2141 1749 2571 +2129 1761 2567 +2111 1776 2563 +2089 1795 2555 +2055 1820 2547 +2006 1851 2535 +1932 1890 2517 +1809 1937 2493 +1563 1992 2461 +119 2057 2411 +0 2133 2335 +0 2217 2209 +0 2309 1955 +0 2409 0 +0 2517 0 +0 2629 0 +0 2745 0 +0 2865 0 +0 2989 0 +0 3113 0 +0 3241 0 +0 3369 0 +0 3497 0 +0 3627 0 +0 3757 0 +0 3889 0 +0 4019 0 +2171 1722 2579 +2167 1724 2579 +2165 1728 2577 +2159 1733 2577 +2153 1740 2575 +2145 1749 2571 +2133 1761 2569 +2115 1776 2563 +2093 1795 2557 +2059 1820 2547 +2011 1851 2535 +1938 1889 2519 +1816 1936 2495 +1575 1992 2461 +351 2057 2413 +0 2133 2337 +0 2217 2211 +0 2309 1959 +0 2409 0 +0 2517 0 +0 2629 0 +0 2745 0 +0 2865 0 +0 2989 0 +0 3113 0 +0 3241 0 +0 3369 0 +0 3497 0 +0 3627 0 +0 3757 0 +0 3889 0 +0 4019 0 +2175 1721 2581 +2173 1724 2581 +2169 1728 2579 +2163 1733 2577 +2157 1740 2575 +2149 1748 2573 +2137 1760 2569 +2121 1775 2565 +2097 1795 2557 +2065 1819 2549 +2017 1850 2537 +1945 1889 2519 +1825 1936 2497 +1592 1992 2463 +546 2057 2413 +0 2133 2339 +0 2217 2213 +0 2309 1964 +0 2409 148 +0 2517 0 +0 2629 0 +0 2745 0 +0 2865 0 +0 2989 0 +0 3113 0 +0 3241 0 +0 3369 0 +0 3497 0 +0 3627 0 +0 3757 0 +0 3889 0 +0 4019 0 +2181 1720 2583 +2177 1723 2581 +2175 1727 2581 +2169 1732 2579 +2163 1739 2577 +2155 1748 2575 +2143 1759 2571 +2127 1774 2567 +2105 1794 2559 +2073 1819 2551 +2026 1850 2539 +1955 1888 2521 +1838 1935 2499 +1612 1991 2465 +720 2057 2417 +0 2133 2341 +0 2217 2217 +0 2309 1970 +0 2409 403 +0 2517 0 +0 2629 0 +0 2745 0 +0 2865 0 +0 2989 0 +0 3113 0 +0 3241 0 +0 3369 0 +0 3497 0 +0 3627 0 +0 3757 0 +0 3889 0 +0 4019 0 +2189 1719 2585 +2185 1722 2583 +2183 1726 2583 +2177 1731 2581 +2171 1738 2579 +2163 1747 2577 +2151 1758 2573 +2135 1774 2569 +2113 1793 2561 +2083 1818 2553 +2036 1849 2541 +1967 1888 2525 +1854 1935 2501 +1639 1991 2467 +881 2057 2419 +0 2131 2345 +0 2217 2223 +0 2309 1978 +0 2409 608 +0 2515 0 +0 2629 0 +0 2745 0 +0 2865 0 +0 2989 0 +0 3113 0 +0 3241 0 +0 3369 0 +0 3497 0 +0 3627 0 +0 3757 0 +0 3889 0 +0 4019 0 +2199 1718 2587 +2195 1721 2587 +2193 1724 2585 +2189 1730 2585 +2181 1736 2583 +2173 1745 2579 +2163 1757 2577 +2147 1772 2571 +2125 1792 2565 +2095 1817 2557 +2051 1848 2545 +1984 1887 2527 +1875 1934 2505 +1672 1990 2471 +1033 2055 2423 +0 2131 2349 +0 2215 2229 +0 2309 1989 +0 2409 789 +0 2515 0 +0 2627 0 +0 2745 0 +0 2865 0 +0 2987 0 +0 3113 0 +0 3241 0 +0 3369 0 +0 3497 0 +0 3627 0 +0 3757 0 +0 3889 0 +0 4019 0 +2211 1716 2591 +2209 1719 2591 +2205 1723 2589 +2201 1728 2587 +2195 1735 2587 +2187 1744 2583 +2177 1755 2579 +2161 1771 2575 +2141 1790 2569 +2111 1815 2561 +2069 1847 2549 +2004 1885 2531 +1901 1933 2509 +1712 1989 2477 +1180 2055 2429 +0 2131 2357 +0 2215 2237 +0 2307 2003 +0 2409 954 +0 2515 0 +0 2627 0 +0 2745 0 +0 2865 0 +0 2987 0 +0 3113 0 +0 3239 0 +0 3369 0 +0 3497 0 +0 3627 0 +0 3757 0 +0 3889 0 +0 4019 0 +2229 1713 2597 +2227 1716 2595 +2223 1720 2595 +2219 1725 2593 +2213 1732 2591 +2205 1741 2589 +2195 1753 2585 +2181 1768 2581 +2161 1788 2575 +2133 1813 2565 +2091 1845 2553 +2031 1884 2537 +1935 1931 2515 +1762 1988 2483 +1323 2053 2435 +0 2129 2365 +0 2215 2247 +0 2307 2021 +0 2407 1109 +0 2515 0 +0 2627 0 +0 2745 0 +0 2865 0 +0 2987 0 +0 3113 0 +0 3239 0 +0 3369 0 +0 3497 0 +0 3627 0 +0 3757 0 +0 3889 0 +0 4019 0 +2251 1710 2603 +2249 1713 2603 +2245 1716 2601 +2241 1722 2599 +2235 1729 2597 +2229 1738 2595 +2219 1750 2591 +2205 1765 2587 +2185 1785 2581 +2159 1810 2573 +2121 1842 2561 +2065 1881 2545 +1975 1929 2523 +1820 1986 2491 +1463 2053 2445 +0 2127 2375 +0 2213 2261 +0 2307 2044 +0 2407 1258 +0 2515 0 +0 2627 0 +0 2743 0 +0 2865 0 +0 2987 0 +0 3113 0 +0 3239 0 +0 3367 0 +0 3497 0 +0 3627 0 +0 3757 0 +0 3889 0 +0 4019 0 +2279 1705 2611 +2275 1708 2611 +2273 1712 2609 +2269 1717 2609 +2265 1724 2607 +2257 1733 2605 +2249 1745 2601 +2235 1761 2597 +2217 1781 2591 +2193 1806 2581 +2157 1838 2571 +2105 1878 2555 +2025 1926 2533 +1888 1983 2503 +1601 2049 2457 +0 2127 2389 +0 2211 2281 +0 2305 2073 +0 2407 1402 +0 2513 0 +0 2627 0 +0 2743 0 +0 2863 0 +0 2987 0 +0 3113 0 +0 3239 0 +0 3367 0 +0 3497 0 +0 3627 0 +0 3757 0 +0 3889 0 +0 4019 0 +2313 1698 2623 +2311 1701 2623 +2309 1706 2621 +2305 1711 2619 +2299 1718 2619 +2293 1727 2615 +2285 1739 2613 +2273 1755 2609 +2257 1776 2603 +2235 1801 2595 +2203 1834 2583 +2155 1874 2567 +2083 1922 2547 +1966 1980 2517 +1738 2047 2473 +801 2123 2409 +0 2209 2303 +0 2303 2109 +0 2405 1543 +0 2513 0 +0 2625 0 +0 2743 0 +0 2863 0 +0 2987 0 +0 3113 0 +0 3239 0 +0 3367 0 +0 3497 0 +0 3627 0 +0 3757 0 +0 3889 0 +0 4019 0 +2355 1690 2637 +2353 1693 2637 +2351 1697 2637 +2347 1702 2635 +2343 1710 2633 +2337 1719 2631 +2329 1732 2627 +2319 1748 2623 +2305 1768 2617 +2285 1794 2609 +2255 1827 2599 +2213 1868 2585 +2151 1917 2565 +2053 1975 2535 +1873 2043 2495 +1398 2121 2431 +0 2207 2333 +0 2301 2153 +0 2403 1682 +0 2511 0 +0 2625 0 +0 2741 0 +0 2863 0 +0 2987 0 +0 3111 0 +0 3239 0 +0 3367 0 +0 3497 0 +0 3627 0 +0 3757 0 +0 3889 0 +0 4019 0 +2407 1678 2657 +2405 1681 2657 +2403 1685 2655 +2399 1691 2655 +2395 1698 2653 +2391 1708 2651 +2383 1721 2647 +2375 1737 2643 +2361 1758 2637 +2343 1785 2631 +2319 1818 2619 +2283 1860 2605 +2229 1909 2587 +2147 1969 2559 +2007 2037 2521 +1708 2115 2461 +0 2203 2369 +0 2297 2207 +0 2401 1818 +0 2509 0 +0 2623 0 +0 2741 0 +0 2861 0 +0 2985 0 +0 3111 0 +0 3239 0 +0 3367 0 +0 3497 0 +0 3627 0 +0 3757 0 +0 3889 0 +0 4019 0 +2467 1661 2681 +2465 1665 2681 +2463 1669 2679 +2461 1675 2679 +2457 1683 2677 +2453 1693 2675 +2447 1706 2673 +2439 1723 2669 +2427 1744 2663 +2413 1772 2655 +2391 1806 2647 +2361 1849 2633 +2317 1900 2615 +2249 1960 2589 +2141 2030 2553 +1939 2109 2499 +1310 2197 2415 +0 2293 2269 +0 2397 1954 +0 2507 0 +0 2621 0 +0 2739 0 +0 2861 0 +0 2985 0 +0 3111 0 +0 3239 0 +0 3367 0 +0 3497 0 +0 3627 0 +0 3757 0 +0 3889 0 +0 4019 0 +2537 1638 2711 +2535 1642 2711 +2535 1646 2711 +2531 1653 2709 +2529 1661 2707 +2525 1671 2705 +2521 1685 2703 +2513 1703 2699 +2503 1725 2695 +2491 1754 2689 +2473 1790 2679 +2447 1834 2667 +2411 1886 2651 +2357 1948 2627 +2275 2020 2593 +2133 2101 2543 +1828 2191 2467 +0 2289 2341 +0 2393 2089 +0 2503 0 +0 2619 0 +0 2737 0 +0 2859 0 +0 2983 0 +0 3109 0 +0 3237 0 +0 3367 0 +0 3495 0 +0 3627 0 +0 3757 0 +0 3887 0 +0 4019 0 +2617 1606 2749 +2615 1609 2749 +2613 1614 2749 +2613 1621 2747 +2609 1630 2747 +2607 1641 2745 +2603 1656 2741 +2597 1674 2739 +2589 1699 2735 +2577 1729 2729 +2563 1767 2719 +2543 1813 2709 +2513 1868 2693 +2471 1932 2671 +2407 2006 2641 +2307 2089 2597 +2121 2181 2531 +1617 2281 2423 +0 2387 2223 +0 2499 1608 +0 2615 0 +0 2735 0 +0 2857 0 +0 2981 0 +0 3109 0 +0 3237 0 +0 3365 0 +0 3495 0 +0 3625 0 +0 3757 0 +0 3887 0 +0 4019 0 +2705 1558 2797 +2703 1562 2795 +2703 1568 2795 +2701 1575 2795 +2699 1584 2793 +2697 1597 2791 +2693 1613 2789 +2689 1634 2787 +2683 1660 2781 +2673 1693 2777 +2661 1734 2769 +2645 1783 2759 +2621 1841 2745 +2589 1909 2727 +2541 1987 2699 +2467 2073 2661 +2345 2169 2603 +2107 2271 2513 +914 2379 2357 +0 2491 1991 +0 2609 0 +0 2731 0 +0 2853 0 +0 2979 0 +0 3107 0 +0 3235 0 +0 3365 0 +0 3495 0 +0 3625 0 +0 3757 0 +0 3887 0 +0 4019 0 +2801 1485 2851 +2801 1490 2851 +2799 1496 2851 +2799 1505 2849 +2797 1516 2849 +2795 1531 2847 +2791 1549 2845 +2787 1573 2843 +2783 1603 2839 +2775 1640 2835 +2767 1686 2827 +2753 1740 2819 +2735 1804 2807 +2709 1877 2791 +2673 1960 2767 +2619 2051 2735 +2537 2151 2685 +2393 2255 2613 +2085 2367 2489 +0 2483 2249 +0 2603 980 +0 2725 0 +0 2851 0 +0 2977 0 +0 3105 0 +0 3233 0 +0 3363 0 +0 3493 0 +0 3625 0 +0 3755 0 +0 3887 0 +0 4019 0 +2905 1365 2917 +2903 1371 2915 +2903 1380 2915 +2903 1391 2915 +2901 1405 2913 +2899 1423 2913 +2897 1447 2911 +2895 1476 2909 +2891 1513 2905 +2885 1558 2901 +2877 1612 2895 +2867 1675 2889 +2853 1748 2877 +2833 1830 2863 +2805 1921 2845 +2767 2020 2817 +2707 2125 2777 +2615 2237 2717 +2451 2351 2623 +2055 2471 2455 +0 2593 2045 +0 2719 0 +0 2845 0 +0 2973 0 +0 3101 0 +0 3231 0 +0 3361 0 +0 3493 0 +0 3623 0 +0 3755 0 +0 3887 0 +0 4019 0 +3013 1129 2991 +3013 1140 2991 +3013 1154 2989 +3013 1172 2989 +3011 1194 2989 +3009 1223 2987 +3009 1259 2987 +3005 1303 2985 +3003 1356 2981 +2999 1418 2979 +2993 1490 2973 +2985 1571 2967 +2973 1661 2959 +2959 1759 2947 +2939 1864 2931 +2909 1974 2907 +2867 2089 2875 +2803 2209 2827 +2701 2331 2755 +2517 2455 2637 +2010 2581 2405 +0 2709 1408 +0 2837 0 +0 2967 0 +0 3097 0 +0 3229 0 +0 3359 0 +0 3491 0 +0 3623 0 +0 3753 0 +0 3885 0 +0 4017 0 +3129 41 3075 +3129 145 3075 +3127 256 3073 +3127 371 3073 +3127 491 3073 +3125 613 3071 +3123 737 3071 +3123 864 3069 +3119 991 3067 +3117 1120 3063 +3111 1250 3059 +3105 1380 3055 +3097 1511 3047 +3087 1642 3037 +3071 1773 3025 +3049 1905 3007 +3019 2036 2981 +2973 2169 2943 +2907 2299 2889 +2797 2431 2803 +2593 2563 2655 +1943 2695 2327 +0 2827 0 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +3247 0 3167 +3247 0 3167 +3247 0 3165 +3245 0 3165 +3245 0 3165 +3245 0 3165 +3243 0 3163 +3241 0 3161 +3239 0 3161 +3237 0 3157 +3233 22 3155 +3229 832 3151 +3223 1172 3145 +3215 1414 3137 +3203 1614 3127 +3187 1791 3111 +3165 1954 3091 +3133 2109 3063 +3087 2255 3021 +3015 2399 2959 +2901 2539 2859 +2677 2677 2677 +1835 2815 2197 +0 2951 0 +0 3085 0 +0 3219 0 +0 3353 0 +0 3485 0 +0 3619 0 +0 3751 0 +0 3883 0 +0 4015 0 +3369 0 3267 +3369 0 3265 +3367 0 3265 +3367 0 3265 +3367 0 3265 +3367 0 3265 +3365 0 3263 +3365 0 3263 +3363 0 3261 +3361 0 3259 +3359 0 3257 +3355 0 3253 +3351 0 3249 +3343 492 3243 +3335 1242 3235 +3323 1575 3223 +3307 1814 3207 +3283 2013 3185 +3251 2189 3153 +3203 2351 3107 +3129 2505 3037 +3009 2653 2925 +2771 2797 2707 +1632 2937 1933 +0 3075 0 +0 3211 0 +0 3347 0 +0 3481 0 +0 3615 0 +0 3749 0 +0 3881 0 +0 4015 0 +3493 0 3373 +3493 0 3373 +3493 0 3373 +3491 0 3371 +3491 0 3371 +3491 0 3371 +3491 0 3371 +3489 0 3369 +3489 0 3369 +3487 0 3367 +3485 0 3365 +3483 0 3363 +3479 0 3359 +3473 0 3353 +3467 0 3347 +3459 805 3339 +3447 1516 3325 +3429 1844 3309 +3405 2081 3285 +3373 2279 3251 +3323 2455 3201 +3249 2617 3125 +3123 2771 2999 +2873 2917 2743 +999 3061 0 +0 3201 0 +0 3339 0 +0 3475 0 +0 3611 0 +0 3745 0 +0 3879 0 +0 4013 0 +3619 0 3485 +3619 0 3485 +3619 0 3483 +3617 0 3483 +3617 0 3483 +3617 0 3483 +3617 0 3483 +3617 0 3481 +3615 0 3481 +3615 0 3479 +3613 0 3479 +3611 0 3477 +3609 0 3473 +3605 0 3469 +3599 0 3465 +3593 0 3457 +3583 0 3449 +3571 1422 3435 +3555 1880 3417 +3531 2159 3393 +3497 2377 3357 +3447 2563 3303 +3369 2733 3223 +3241 2891 3083 +2979 3041 2787 +0 3187 0 +0 3329 0 +0 3467 0 +0 3605 0 +0 3741 0 +0 3877 0 +0 4011 0 +3745 0 3601 +3745 0 3601 +3745 0 3601 +3745 0 3601 +3745 0 3599 +3745 0 3599 +3745 0 3599 +3745 0 3599 +3743 0 3599 +3743 0 3597 +3741 0 3597 +3741 0 3595 +3739 0 3593 +3735 0 3589 +3731 0 3585 +3727 0 3581 +3721 0 3573 +3711 0 3563 +3699 1258 3549 +3681 1924 3531 +3657 2245 3505 +3623 2481 3467 +3571 2677 3413 +3493 2853 3325 +3363 3015 3177 +3093 3167 2841 +0 3315 0 +0 3457 0 +0 3597 0 +0 3735 0 +0 3873 0 +0 4007 0 +3875 0 3721 +3875 0 3721 +3875 0 3721 +3875 0 3721 +3875 0 3719 +3873 0 3719 +3873 0 3719 +3873 0 3719 +3873 0 3719 +3873 0 3717 +3871 0 3717 +3871 0 3715 +3869 0 3715 +3867 0 3711 +3863 0 3709 +3861 0 3705 +3855 0 3699 +3849 0 3693 +3839 0 3681 +3827 858 3669 +3809 1978 3649 +3785 2341 3623 +3749 2591 3583 +3699 2795 3525 +3619 2975 3435 +3485 3139 3277 +3209 3295 2903 +0 3443 0 +0 3587 0 +0 3727 0 +0 3867 0 +0 4003 0 +4005 0 3843 +4005 0 3843 +4003 0 3843 +4003 0 3843 +4003 0 3843 +4003 0 3843 +4003 0 3843 +4003 0 3843 +4003 0 3841 +4003 0 3841 +4001 0 3841 +4001 0 3839 +3999 0 3839 +3999 0 3837 +3997 0 3835 +3993 0 3831 +3989 0 3827 +3985 0 3821 +3977 0 3815 +3969 0 3803 +3955 0 3789 +3939 2041 3771 +3913 2443 3743 +3879 2707 3703 +3827 2917 3643 +3747 3101 3549 +3611 3267 3383 +3329 3423 2977 +0 3573 0 +0 3717 0 +0 3859 0 +0 3997 0 +4095 0 3969 +4095 0 3969 +4095 0 3969 +4095 0 3969 +4095 0 3967 +4095 0 3967 +4095 0 3967 +4095 0 3967 +4095 0 3967 +4095 0 3967 +4095 0 3967 +4095 0 3965 +4095 0 3965 +4095 0 3963 +4095 0 3961 +4095 0 3959 +4095 0 3957 +4095 0 3951 +4095 0 3947 +4095 0 3939 +4095 0 3929 +4085 0 3913 +4067 2113 3893 +4043 2551 3865 +4007 2825 3825 +3955 3041 3765 +3875 3227 3667 +3739 3395 3495 +3453 3553 3057 +0 3703 0 +0 3849 0 +0 3989 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4093 +4095 0 4093 +4095 0 4093 +4095 0 4093 +4095 0 4091 +4095 0 4089 +4095 0 4089 +4095 0 4085 +4095 0 4083 +4095 0 4079 +4095 0 4073 +4095 0 4065 +4095 0 4055 +4095 0 4039 +4095 2195 4019 +4095 2665 3991 +4095 2947 3949 +4085 3167 3887 +4005 3355 3789 +3867 3525 3611 +3579 3683 3149 +0 3833 0 +0 3979 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 2285 4095 +4095 2783 4095 +4095 3073 4077 +4095 3295 4013 +4095 3483 3913 +3997 3655 3731 +3705 3813 3247 +0 3965 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 2383 4095 +4095 2905 4095 +4095 3199 4095 +4095 3423 4095 +4095 3613 4039 +4095 3785 3855 +3833 3945 3351 +2299 1852 2711 +2297 1854 2711 +2293 1857 2709 +2291 1861 2709 +2285 1866 2707 +2279 1873 2705 +2269 1882 2703 +2257 1893 2699 +2241 1909 2693 +2217 1928 2687 +2183 1953 2679 +2135 1984 2665 +2059 2022 2649 +1935 2069 2625 +1685 2125 2591 +0 2191 2541 +0 2265 2467 +0 2349 2339 +0 2441 2085 +0 2543 0 +0 2649 0 +0 2761 0 +0 2877 0 +0 2997 0 +0 3121 0 +0 3245 0 +0 3373 0 +0 3501 0 +0 3629 0 +0 3759 0 +0 3889 0 +0 4021 0 +2301 1852 2711 +2299 1854 2711 +2297 1857 2711 +2293 1861 2709 +2287 1866 2707 +2281 1873 2705 +2273 1882 2703 +2261 1893 2699 +2243 1908 2695 +2221 1928 2687 +2187 1952 2679 +2139 1983 2667 +2065 2022 2649 +1941 2069 2627 +1695 2125 2593 +251 2191 2543 +0 2265 2467 +0 2349 2341 +0 2441 2087 +0 2541 0 +0 2649 0 +0 2761 0 +0 2877 0 +0 2997 0 +0 3121 0 +0 3245 0 +0 3373 0 +0 3501 0 +0 3629 0 +0 3759 0 +0 3889 0 +0 4021 0 +2305 1851 2713 +2303 1854 2711 +2299 1857 2711 +2297 1860 2709 +2291 1866 2709 +2285 1872 2707 +2277 1881 2703 +2265 1893 2701 +2247 1908 2695 +2225 1927 2689 +2191 1952 2679 +2143 1983 2667 +2069 2022 2651 +1948 2069 2627 +1708 2125 2593 +483 2189 2545 +0 2265 2469 +0 2349 2343 +0 2441 2091 +0 2541 0 +0 2649 0 +0 2761 0 +0 2877 0 +0 2997 0 +0 3121 0 +0 3245 0 +0 3373 0 +0 3501 0 +0 3629 0 +0 3759 0 +0 3889 0 +0 4021 0 +2309 1851 2713 +2307 1853 2713 +2305 1856 2713 +2301 1860 2711 +2295 1865 2709 +2289 1872 2707 +2281 1881 2705 +2269 1892 2701 +2253 1907 2697 +2229 1927 2691 +2197 1951 2681 +2149 1983 2669 +2077 2021 2653 +1958 2069 2629 +1724 2125 2595 +678 2189 2547 +0 2265 2471 +0 2349 2345 +0 2441 2095 +0 2541 280 +0 2649 0 +0 2761 0 +0 2877 0 +0 2997 0 +0 3121 0 +0 3245 0 +0 3373 0 +0 3501 0 +0 3629 0 +0 3759 0 +0 3889 0 +0 4021 0 +2315 1850 2715 +2313 1852 2715 +2311 1855 2713 +2307 1859 2713 +2301 1864 2711 +2295 1871 2709 +2287 1880 2707 +2275 1891 2703 +2259 1907 2699 +2237 1926 2691 +2205 1951 2683 +2157 1982 2671 +2087 2021 2653 +1970 2067 2631 +1744 2123 2597 +852 2189 2549 +0 2265 2473 +0 2349 2349 +0 2441 2101 +0 2541 535 +0 2649 0 +0 2761 0 +0 2877 0 +0 2997 0 +0 3121 0 +0 3245 0 +0 3373 0 +0 3501 0 +0 3629 0 +0 3759 0 +0 3889 0 +0 4021 0 +2323 1849 2717 +2321 1851 2717 +2317 1854 2715 +2315 1858 2715 +2309 1863 2713 +2303 1870 2711 +2295 1879 2709 +2283 1890 2705 +2267 1906 2701 +2245 1925 2693 +2215 1950 2685 +2169 1981 2673 +2099 2020 2657 +1986 2067 2633 +1771 2123 2599 +1013 2189 2551 +0 2263 2477 +0 2349 2355 +0 2441 2111 +0 2541 741 +0 2649 0 +0 2761 0 +0 2877 0 +0 2997 0 +0 3121 0 +0 3245 0 +0 3373 0 +0 3501 0 +0 3629 0 +0 3759 0 +0 3889 0 +0 4021 0 +2333 1848 2721 +2331 1850 2719 +2327 1853 2719 +2325 1857 2717 +2321 1862 2717 +2315 1869 2715 +2305 1877 2711 +2295 1889 2709 +2279 1904 2703 +2257 1924 2697 +2227 1949 2689 +2183 1980 2677 +2115 2019 2659 +2007 2065 2637 +1804 2123 2603 +1166 2187 2555 +0 2263 2483 +0 2347 2361 +0 2441 2121 +0 2541 921 +0 2647 0 +0 2761 0 +0 2877 0 +0 2997 0 +0 3121 0 +0 3245 0 +0 3373 0 +0 3501 0 +0 3629 0 +0 3759 0 +0 3889 0 +0 4021 0 +2345 1846 2725 +2343 1848 2723 +2341 1851 2723 +2337 1855 2721 +2333 1860 2721 +2327 1867 2719 +2319 1876 2715 +2309 1887 2713 +2293 1903 2707 +2273 1922 2701 +2243 1947 2693 +2201 1979 2681 +2137 2017 2663 +2034 2065 2641 +1845 2121 2609 +1312 2187 2561 +0 2263 2489 +0 2347 2369 +0 2441 2135 +0 2541 1086 +0 2647 0 +0 2759 0 +0 2877 0 +0 2997 0 +0 3119 0 +0 3245 0 +0 3373 0 +0 3501 0 +0 3629 0 +0 3759 0 +0 3889 0 +0 4021 0 +2363 1843 2729 +2361 1845 2729 +2359 1848 2727 +2355 1852 2727 +2351 1857 2725 +2345 1864 2723 +2337 1873 2721 +2327 1885 2717 +2313 1900 2713 +2293 1920 2707 +2265 1945 2697 +2223 1977 2685 +2163 2016 2669 +2067 2063 2647 +1894 2119 2615 +1455 2185 2569 +0 2261 2497 +0 2347 2379 +0 2439 2153 +0 2539 1241 +0 2647 0 +0 2759 0 +0 2877 0 +0 2997 0 +0 3119 0 +0 3245 0 +0 3371 0 +0 3501 0 +0 3629 0 +0 3759 0 +0 3889 0 +0 4021 0 +2385 1839 2735 +2383 1842 2735 +2381 1845 2735 +2377 1849 2733 +2373 1854 2731 +2367 1861 2729 +2361 1870 2727 +2351 1882 2725 +2337 1897 2719 +2319 1917 2713 +2291 1942 2705 +2253 1974 2693 +2197 2013 2677 +2107 2061 2655 +1952 2117 2623 +1595 2185 2577 +0 2261 2507 +0 2345 2393 +0 2439 2175 +0 2539 1390 +0 2647 0 +0 2759 0 +0 2875 0 +0 2997 0 +0 3119 0 +0 3245 0 +0 3371 0 +0 3501 0 +0 3629 0 +0 3759 0 +0 3889 0 +0 4021 0 +2411 1835 2745 +2411 1837 2743 +2409 1840 2743 +2405 1844 2743 +2401 1849 2741 +2397 1856 2739 +2389 1865 2737 +2381 1877 2733 +2367 1893 2729 +2349 1913 2723 +2325 1939 2715 +2289 1971 2703 +2237 2010 2687 +2157 2059 2665 +2020 2115 2635 +1733 2181 2589 +0 2259 2523 +0 2343 2413 +0 2437 2205 +0 2539 1534 +0 2645 0 +0 2759 0 +0 2875 0 +0 2997 0 +0 3119 0 +0 3245 0 +0 3371 0 +0 3499 0 +0 3629 0 +0 3759 0 +0 3889 0 +0 4021 0 +2447 1828 2755 +2445 1831 2755 +2443 1834 2755 +2441 1838 2753 +2437 1843 2753 +2433 1850 2751 +2425 1859 2747 +2417 1872 2745 +2405 1887 2741 +2389 1908 2735 +2367 1933 2727 +2335 1966 2715 +2287 2006 2701 +2215 2055 2679 +2099 2111 2649 +1870 2179 2605 +933 2255 2541 +0 2341 2435 +0 2435 2241 +0 2537 1675 +0 2645 0 +0 2757 0 +0 2875 0 +0 2995 0 +0 3119 0 +0 3245 0 +0 3371 0 +0 3499 0 +0 3629 0 +0 3759 0 +0 3889 0 +0 4021 0 +2489 1819 2771 +2487 1822 2771 +2485 1825 2769 +2483 1829 2769 +2479 1835 2767 +2475 1842 2765 +2469 1851 2763 +2463 1864 2759 +2451 1880 2755 +2437 1900 2749 +2417 1926 2741 +2387 1959 2731 +2347 2000 2717 +2283 2049 2697 +2185 2107 2667 +2005 2175 2627 +1530 2253 2565 +0 2339 2465 +0 2433 2285 +0 2535 1814 +0 2643 0 +0 2757 0 +0 2873 0 +0 2995 0 +0 3119 0 +0 3245 0 +0 3371 0 +0 3499 0 +0 3629 0 +0 3759 0 +0 3889 0 +0 4021 0 +2539 1807 2789 +2539 1810 2789 +2537 1813 2789 +2535 1817 2787 +2531 1823 2787 +2529 1830 2785 +2523 1840 2783 +2515 1853 2779 +2507 1869 2775 +2493 1890 2769 +2475 1917 2763 +2451 1951 2753 +2415 1992 2739 +2361 2042 2719 +2279 2101 2691 +2139 2169 2653 +1840 2247 2593 +0 2335 2501 +0 2431 2339 +0 2533 1951 +0 2641 0 +0 2755 0 +0 2873 0 +0 2993 0 +0 3117 0 +0 3243 0 +0 3371 0 +0 3499 0 +0 3629 0 +0 3759 0 +0 3889 0 +0 4021 0 +2599 1791 2813 +2599 1793 2813 +2597 1797 2813 +2595 1801 2811 +2593 1807 2811 +2589 1815 2809 +2585 1825 2807 +2579 1838 2805 +2571 1855 2801 +2559 1877 2795 +2545 1904 2789 +2523 1938 2779 +2493 1981 2765 +2449 2032 2747 +2381 2093 2721 +2273 2163 2685 +2071 2241 2631 +1442 2329 2547 +0 2425 2401 +0 2529 2087 +0 2639 0 +0 2753 0 +0 2871 0 +0 2993 0 +0 3117 0 +0 3243 0 +0 3371 0 +0 3499 0 +0 3629 0 +0 3759 0 +0 3889 0 +0 4021 0 +2669 1768 2845 +2669 1770 2845 +2667 1774 2843 +2667 1779 2843 +2665 1785 2841 +2661 1793 2841 +2657 1803 2839 +2653 1817 2835 +2645 1835 2831 +2635 1857 2827 +2623 1886 2821 +2605 1922 2811 +2579 1966 2799 +2543 2018 2783 +2489 2081 2759 +2407 2153 2725 +2265 2233 2675 +1960 2323 2601 +0 2421 2475 +0 2525 2221 +0 2635 0 +0 2751 0 +0 2869 0 +0 2991 0 +0 3115 0 +0 3241 0 +0 3369 0 +0 3499 0 +0 3627 0 +0 3759 0 +0 3889 0 +0 4021 0 +2749 1735 2883 +2749 1738 2883 +2747 1742 2881 +2747 1747 2881 +2745 1753 2879 +2741 1762 2879 +2739 1773 2877 +2735 1788 2875 +2729 1807 2871 +2721 1831 2867 +2709 1861 2861 +2695 1899 2853 +2675 1945 2841 +2645 2000 2825 +2603 2065 2805 +2539 2139 2773 +2439 2221 2729 +2253 2313 2663 +1749 2413 2555 +0 2519 2355 +0 2631 1740 +0 2747 0 +0 2867 0 +0 2989 0 +0 3113 0 +0 3241 0 +0 3369 0 +0 3497 0 +0 3627 0 +0 3757 0 +0 3889 0 +0 4019 0 +2837 1687 2929 +2837 1690 2929 +2835 1694 2927 +2835 1700 2927 +2833 1707 2927 +2831 1717 2925 +2829 1729 2923 +2825 1745 2921 +2821 1766 2919 +2815 1792 2915 +2805 1825 2909 +2793 1866 2901 +2777 1915 2891 +2753 1974 2877 +2721 2042 2859 +2673 2119 2831 +2599 2205 2793 +2477 2301 2735 +2239 2403 2647 +1046 2511 2489 +0 2623 2123 +0 2741 0 +0 2863 0 +0 2987 0 +0 3111 0 +0 3239 0 +0 3367 0 +0 3497 0 +0 3627 0 +0 3757 0 +0 3889 0 +0 4019 0 +2933 1614 2983 +2933 1617 2983 +2933 1622 2983 +2931 1629 2983 +2931 1637 2981 +2929 1648 2981 +2927 1663 2979 +2923 1681 2977 +2921 1705 2975 +2915 1735 2971 +2907 1772 2967 +2899 1818 2959 +2885 1872 2951 +2867 1936 2939 +2841 2009 2923 +2805 2093 2899 +2751 2183 2867 +2669 2283 2817 +2525 2389 2745 +2217 2499 2621 +0 2615 2381 +0 2735 1111 +0 2857 0 +0 2983 0 +0 3109 0 +0 3237 0 +0 3365 0 +0 3495 0 +0 3625 0 +0 3757 0 +0 3887 0 +0 4019 0 +3037 1492 3049 +3037 1497 3049 +3037 1503 3049 +3035 1512 3047 +3035 1523 3047 +3033 1537 3045 +3031 1555 3045 +3029 1579 3043 +3027 1608 3041 +3023 1645 3037 +3017 1690 3033 +3009 1744 3027 +2999 1807 3021 +2985 1880 3011 +2965 1962 2995 +2937 2053 2977 +2899 2151 2949 +2839 2257 2909 +2747 2369 2849 +2583 2483 2755 +2187 2603 2587 +0 2725 2177 +0 2851 0 +0 2977 0 +0 3105 0 +0 3233 0 +0 3363 0 +0 3493 0 +0 3625 0 +0 3755 0 +0 3887 0 +0 4019 0 +3147 1253 3123 +3147 1261 3123 +3145 1272 3123 +3145 1286 3123 +3145 1304 3121 +3143 1327 3121 +3143 1355 3119 +3141 1391 3119 +3137 1435 3117 +3135 1488 3113 +3131 1550 3111 +3125 1622 3105 +3117 1703 3099 +3105 1793 3091 +3091 1891 3079 +3071 1996 3063 +3041 2107 3039 +2999 2221 3007 +2935 2341 2959 +2835 2463 2887 +2649 2587 2769 +2143 2713 2537 +0 2841 1540 +0 2969 0 +0 3099 0 +0 3229 0 +0 3361 0 +0 3491 0 +0 3623 0 +0 3755 0 +0 3887 0 +0 4017 0 +3261 75 3207 +3261 173 3207 +3261 278 3207 +3259 388 3205 +3259 504 3205 +3259 623 3205 +3257 745 3203 +3255 869 3203 +3255 996 3201 +3251 1123 3199 +3249 1252 3195 +3243 1382 3193 +3237 1512 3187 +3229 1643 3179 +3219 1774 3169 +3203 1905 3157 +3181 2037 3139 +3151 2169 3113 +3105 2301 3075 +3039 2433 3021 +2929 2563 2935 +2725 2695 2787 +2075 2829 2459 +0 2961 0 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +3379 0 3299 +3379 0 3299 +3379 0 3299 +3379 0 3299 +3377 0 3297 +3377 0 3297 +3377 0 3297 +3375 0 3295 +3375 0 3295 +3373 0 3293 +3369 0 3289 +3367 154 3287 +3361 964 3283 +3355 1304 3277 +3347 1546 3269 +3335 1746 3259 +3319 1923 3243 +3297 2087 3223 +3265 2241 3195 +3219 2387 3153 +3147 2531 3091 +3033 2671 2991 +2811 2811 2811 +1967 2947 2331 +0 3083 0 +0 3217 0 +0 3351 0 +0 3485 0 +0 3617 0 +0 3751 0 +0 3883 0 +0 4015 0 +3501 0 3399 +3501 0 3399 +3501 0 3399 +3501 0 3397 +3499 0 3397 +3499 0 3397 +3499 0 3397 +3497 0 3395 +3497 0 3395 +3495 0 3393 +3493 0 3391 +3491 0 3389 +3487 0 3385 +3483 0 3381 +3477 624 3375 +3467 1374 3367 +3455 1707 3355 +3439 1946 3339 +3415 2145 3317 +3383 2321 3285 +3335 2483 3239 +3261 2637 3169 +3141 2785 3057 +2903 2929 2839 +1764 3069 2065 +0 3207 0 +0 3343 0 +0 3479 0 +0 3613 0 +0 3747 0 +0 3881 0 +0 4013 0 +3625 0 3505 +3625 0 3505 +3625 0 3505 +3625 0 3505 +3623 0 3503 +3623 0 3503 +3623 0 3503 +3623 0 3503 +3621 0 3501 +3621 0 3501 +3619 0 3499 +3617 0 3497 +3615 0 3495 +3611 0 3491 +3607 0 3485 +3599 0 3479 +3591 937 3471 +3579 1648 3459 +3561 1976 3441 +3539 2213 3417 +3505 2411 3383 +3455 2587 3335 +3381 2749 3259 +3255 2903 3131 +3005 3049 2875 +1131 3193 0 +0 3333 0 +0 3471 0 +0 3607 0 +0 3743 0 +0 3877 0 +0 4011 0 +3751 0 3617 +3751 0 3617 +3751 0 3617 +3751 0 3617 +3751 0 3615 +3749 0 3615 +3749 0 3615 +3749 0 3615 +3749 0 3615 +3747 0 3613 +3747 0 3613 +3745 0 3611 +3743 0 3609 +3741 0 3605 +3737 0 3601 +3731 0 3597 +3725 0 3589 +3717 0 3581 +3703 1555 3567 +3687 2012 3549 +3663 2291 3525 +3629 2509 3489 +3579 2695 3437 +3501 2865 3355 +3373 3023 3215 +3111 3173 2919 +0 3319 0 +0 3461 0 +0 3601 0 +0 3737 0 +0 3873 0 +0 4009 0 +3879 0 3733 +3879 0 3733 +3877 0 3733 +3877 0 3733 +3877 0 3733 +3877 0 3733 +3877 0 3731 +3877 0 3731 +3877 0 3731 +3875 0 3731 +3875 0 3729 +3873 0 3729 +3873 0 3727 +3871 0 3725 +3867 0 3721 +3863 0 3717 +3859 0 3713 +3853 0 3705 +3843 0 3695 +3831 1390 3681 +3813 2057 3663 +3789 2379 3637 +3755 2613 3599 +3703 2809 3545 +3625 2985 3457 +3495 3147 3309 +3225 3299 2973 +0 3447 0 +0 3589 0 +0 3729 0 +0 3867 0 +0 4005 0 +4007 0 3853 +4007 0 3853 +4007 0 3853 +4007 0 3853 +4007 0 3853 +4007 0 3853 +4007 0 3851 +4005 0 3851 +4005 0 3851 +4005 0 3851 +4005 0 3851 +4003 0 3849 +4003 0 3847 +4001 0 3847 +3999 0 3843 +3997 0 3841 +3993 0 3837 +3987 0 3831 +3981 0 3825 +3971 0 3815 +3959 990 3801 +3941 2109 3781 +3917 2473 3755 +3881 2723 3715 +3831 2927 3657 +3751 3107 3567 +3619 3271 3409 +3341 3427 3035 +0 3575 0 +0 3719 0 +0 3861 0 +0 3999 0 +4095 0 3975 +4095 0 3975 +4095 0 3975 +4095 0 3975 +4095 0 3975 +4095 0 3975 +4095 0 3975 +4095 0 3975 +4095 0 3975 +4095 0 3973 +4095 0 3973 +4095 0 3973 +4095 0 3971 +4095 0 3971 +4095 0 3969 +4095 0 3967 +4095 0 3963 +4095 0 3959 +4095 0 3953 +4095 0 3947 +4095 0 3935 +4087 0 3921 +4071 2173 3903 +4045 2575 3875 +4011 2839 3835 +3959 3049 3775 +3879 3233 3681 +3743 3399 3515 +3461 3555 3109 +0 3705 0 +0 3849 0 +0 3991 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4093 +4095 0 4091 +4095 0 4089 +4095 0 4085 +4095 0 4079 +4095 0 4071 +4095 0 4061 +4095 0 4045 +4095 2245 4025 +4095 2683 3997 +4095 2959 3957 +4087 3173 3897 +4007 3359 3799 +3871 3527 3627 +3585 3685 3189 +0 3835 0 +0 3981 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 2327 4095 +4095 2797 4095 +4095 3081 4081 +4095 3299 4019 +4095 3487 3921 +3999 3657 3743 +3711 3815 3281 +0 3965 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 2417 4095 +4095 2915 4095 +4095 3205 4095 +4095 3427 4095 +4095 3615 4045 +4095 3787 3865 +3837 3945 3379 +2431 1983 2843 +2429 1985 2843 +2427 1987 2841 +2425 1990 2841 +2421 1994 2839 +2415 1999 2839 +2409 2005 2837 +2401 2014 2833 +2387 2026 2831 +2371 2041 2825 +2347 2061 2819 +2313 2085 2809 +2265 2115 2797 +2189 2155 2781 +2063 2201 2757 +1810 2257 2723 +0 2323 2673 +0 2397 2597 +0 2481 2471 +0 2575 2215 +0 2675 0 +0 2781 0 +0 2893 0 +0 3009 0 +0 3129 0 +0 3253 0 +0 3377 0 +0 3505 0 +0 3633 0 +0 3761 0 +0 3891 0 +0 4021 0 +2433 1983 2843 +2431 1984 2843 +2429 1987 2843 +2425 1989 2841 +2423 1993 2841 +2417 1998 2839 +2411 2005 2837 +2403 2014 2835 +2389 2026 2831 +2373 2041 2825 +2349 2061 2819 +2317 2085 2811 +2267 2115 2797 +2193 2155 2781 +2067 2201 2757 +1818 2257 2723 +69 2323 2675 +0 2397 2599 +0 2481 2471 +0 2575 2217 +0 2675 0 +0 2781 0 +0 2893 0 +0 3009 0 +0 3129 0 +0 3253 0 +0 3377 0 +0 3505 0 +0 3633 0 +0 3761 0 +0 3891 0 +0 4021 0 +2435 1982 2845 +2433 1984 2843 +2431 1986 2843 +2429 1989 2843 +2425 1993 2841 +2421 1998 2839 +2413 2005 2837 +2405 2014 2835 +2393 2025 2831 +2375 2040 2827 +2353 2059 2819 +2319 2085 2811 +2271 2115 2799 +2197 2153 2781 +2073 2201 2759 +1827 2257 2725 +383 2323 2675 +0 2397 2599 +0 2481 2473 +0 2573 2219 +0 2675 0 +0 2781 0 +0 2893 0 +0 3009 0 +0 3129 0 +0 3253 0 +0 3377 0 +0 3505 0 +0 3633 0 +0 3761 0 +0 3891 0 +0 4021 0 +2437 1982 2845 +2437 1984 2845 +2435 1986 2843 +2431 1989 2843 +2429 1993 2843 +2423 1998 2841 +2417 2004 2839 +2409 2013 2835 +2397 2025 2833 +2379 2040 2827 +2357 2059 2821 +2323 2085 2811 +2275 2115 2799 +2201 2153 2783 +2081 2201 2759 +1840 2257 2725 +615 2321 2677 +0 2397 2601 +0 2481 2475 +0 2573 2223 +0 2673 39 +0 2781 0 +0 2893 0 +0 3009 0 +0 3129 0 +0 3253 0 +0 3377 0 +0 3505 0 +0 3633 0 +0 3761 0 +0 3891 0 +0 4021 0 +2443 1981 2847 +2441 1983 2845 +2439 1985 2845 +2437 1988 2845 +2433 1992 2843 +2429 1997 2841 +2421 2004 2839 +2413 2013 2837 +2401 2024 2833 +2385 2039 2829 +2361 2059 2823 +2329 2083 2813 +2281 2115 2801 +2209 2153 2785 +2089 2201 2761 +1856 2257 2727 +810 2321 2679 +0 2397 2603 +0 2481 2477 +0 2573 2227 +0 2673 413 +0 2781 0 +0 2893 0 +0 3009 0 +0 3129 0 +0 3253 0 +0 3377 0 +0 3505 0 +0 3633 0 +0 3761 0 +0 3891 0 +0 4021 0 +2449 1981 2847 +2447 1982 2847 +2445 1984 2847 +2443 1987 2845 +2439 1991 2845 +2435 1996 2843 +2427 2003 2841 +2419 2012 2839 +2407 2024 2835 +2391 2039 2831 +2369 2059 2823 +2337 2083 2815 +2289 2115 2803 +2219 2153 2787 +2103 2199 2763 +1877 2255 2729 +984 2321 2681 +0 2397 2605 +0 2481 2481 +0 2573 2235 +0 2673 667 +0 2781 0 +0 2893 0 +0 3009 0 +0 3129 0 +0 3253 0 +0 3377 0 +0 3505 0 +0 3633 0 +0 3761 0 +0 3891 0 +0 4021 0 +2455 1979 2849 +2455 1981 2849 +2453 1983 2849 +2449 1986 2849 +2447 1990 2847 +2441 1995 2845 +2435 2002 2843 +2427 2011 2841 +2415 2023 2837 +2399 2038 2833 +2377 2057 2827 +2347 2083 2817 +2301 2113 2805 +2231 2151 2789 +2119 2199 2765 +1903 2255 2733 +1145 2321 2683 +0 2395 2609 +0 2481 2487 +0 2573 2243 +0 2673 873 +0 2781 0 +0 2893 0 +0 3009 0 +0 3129 0 +0 3253 0 +0 3377 0 +0 3505 0 +0 3633 0 +0 3761 0 +0 3891 0 +0 4021 0 +2465 1978 2853 +2465 1980 2853 +2463 1982 2851 +2461 1985 2851 +2457 1989 2849 +2453 1994 2849 +2447 2001 2847 +2437 2010 2843 +2427 2021 2841 +2411 2036 2835 +2389 2057 2829 +2359 2081 2821 +2315 2113 2809 +2247 2151 2791 +2139 2199 2769 +1936 2255 2735 +1298 2321 2687 +0 2395 2615 +0 2479 2493 +0 2573 2253 +0 2673 1053 +0 2779 0 +0 2893 0 +0 3009 0 +0 3129 0 +0 3253 0 +0 3377 0 +0 3505 0 +0 3633 0 +0 3761 0 +0 3891 0 +0 4021 0 +2479 1976 2857 +2477 1978 2857 +2475 1980 2855 +2473 1983 2855 +2471 1987 2853 +2465 1992 2853 +2459 1999 2851 +2451 2008 2847 +2441 2020 2845 +2425 2035 2839 +2405 2055 2833 +2375 2079 2825 +2333 2111 2813 +2269 2149 2797 +2165 2197 2773 +1977 2253 2741 +1445 2319 2693 +0 2395 2621 +0 2479 2501 +0 2573 2267 +0 2673 1218 +0 2779 0 +0 2891 0 +0 3009 0 +0 3129 0 +0 3253 0 +0 3377 0 +0 3505 0 +0 3633 0 +0 3761 0 +0 3891 0 +0 4021 0 +2495 1973 2861 +2495 1975 2861 +2493 1977 2861 +2491 1980 2859 +2487 1984 2859 +2483 1989 2857 +2477 1996 2855 +2469 2005 2853 +2459 2017 2849 +2445 2032 2845 +2425 2053 2839 +2397 2077 2829 +2357 2109 2819 +2295 2147 2801 +2199 2195 2779 +2026 2251 2747 +1587 2317 2701 +0 2393 2629 +0 2479 2511 +0 2571 2285 +0 2673 1373 +0 2779 0 +0 2891 0 +0 3009 0 +0 3129 0 +0 3251 0 +0 3377 0 +0 3505 0 +0 3633 0 +0 3761 0 +0 3891 0 +0 4021 0 +2517 1970 2869 +2517 1972 2867 +2515 1974 2867 +2513 1977 2867 +2509 1981 2865 +2505 1986 2863 +2501 1993 2863 +2493 2002 2859 +2483 2014 2857 +2469 2029 2851 +2451 2049 2845 +2423 2075 2837 +2385 2107 2825 +2329 2145 2809 +2239 2193 2787 +2085 2249 2755 +1727 2317 2709 +0 2393 2639 +0 2477 2527 +0 2571 2309 +0 2671 1522 +0 2779 0 +0 2891 0 +0 3009 0 +0 3129 0 +0 3251 0 +0 3377 0 +0 3503 0 +0 3633 0 +0 3761 0 +0 3891 0 +0 4021 0 +2545 1965 2877 +2543 1967 2877 +2543 1969 2875 +2541 1972 2875 +2537 1976 2875 +2533 1981 2873 +2529 1988 2871 +2521 1998 2869 +2513 2010 2865 +2499 2025 2861 +2481 2045 2855 +2457 2071 2847 +2421 2103 2835 +2369 2143 2819 +2289 2191 2797 +2153 2247 2767 +1865 2315 2721 +0 2391 2655 +0 2475 2545 +0 2569 2337 +0 2671 1666 +0 2777 0 +0 2891 0 +0 3007 0 +0 3129 0 +0 3251 0 +0 3377 0 +0 3503 0 +0 3633 0 +0 3761 0 +0 3891 0 +0 4021 0 +2579 1959 2889 +2579 1960 2887 +2577 1963 2887 +2575 1966 2887 +2573 1970 2885 +2569 1975 2885 +2565 1982 2883 +2557 1992 2881 +2549 2004 2877 +2537 2019 2873 +2521 2040 2867 +2499 2065 2859 +2467 2097 2847 +2419 2137 2833 +2347 2187 2811 +2231 2243 2781 +2002 2311 2737 +1065 2387 2673 +0 2473 2567 +0 2567 2373 +0 2669 1807 +0 2777 0 +0 2889 0 +0 3007 0 +0 3127 0 +0 3251 0 +0 3377 0 +0 3503 0 +0 3631 0 +0 3761 0 +0 3891 0 +0 4021 0 +2621 1950 2903 +2621 1952 2903 +2619 1954 2903 +2617 1957 2901 +2615 1961 2901 +2611 1967 2899 +2607 1974 2897 +2601 1983 2895 +2595 1996 2891 +2583 2012 2887 +2569 2032 2881 +2549 2059 2875 +2519 2091 2863 +2479 2131 2849 +2415 2181 2829 +2317 2239 2799 +2137 2307 2759 +1662 2385 2697 +0 2471 2597 +0 2565 2417 +0 2667 1946 +0 2775 0 +0 2889 0 +0 3007 0 +0 3127 0 +0 3251 0 +0 3377 0 +0 3503 0 +0 3631 0 +0 3761 0 +0 3891 0 +0 4021 0 +2673 1938 2923 +2671 1940 2921 +2671 1942 2921 +2669 1945 2921 +2667 1949 2919 +2663 1955 2919 +2661 1962 2917 +2655 1972 2915 +2649 1985 2911 +2639 2001 2907 +2625 2022 2901 +2607 2049 2895 +2583 2083 2885 +2547 2123 2871 +2493 2173 2851 +2411 2233 2823 +2271 2301 2785 +1972 2379 2725 +0 2467 2633 +0 2563 2471 +0 2665 2083 +0 2773 0 +0 2887 0 +0 3005 0 +0 3127 0 +0 3249 0 +0 3375 0 +0 3503 0 +0 3631 0 +0 3761 0 +0 3891 0 +0 4021 0 +2733 1921 2947 +2731 1923 2947 +2731 1926 2945 +2729 1929 2945 +2727 1933 2945 +2725 1939 2943 +2721 1947 2941 +2717 1957 2939 +2711 1970 2937 +2703 1987 2933 +2693 2009 2927 +2677 2036 2921 +2655 2071 2911 +2625 2113 2897 +2581 2163 2879 +2513 2225 2853 +2405 2295 2817 +2203 2373 2763 +1574 2461 2679 +0 2559 2533 +0 2661 2219 +0 2771 0 +0 2885 0 +0 3003 0 +0 3125 0 +0 3249 0 +0 3375 0 +0 3503 0 +0 3631 0 +0 3761 0 +0 3891 0 +0 4021 0 +2803 1898 2977 +2801 1900 2977 +2801 1903 2977 +2799 1906 2975 +2799 1911 2975 +2797 1917 2973 +2793 1925 2973 +2789 1935 2971 +2785 1949 2967 +2777 1967 2963 +2767 1990 2959 +2755 2018 2953 +2737 2055 2943 +2711 2097 2931 +2675 2151 2915 +2621 2213 2891 +2539 2285 2857 +2397 2365 2807 +2093 2455 2733 +0 2553 2607 +0 2657 2353 +0 2767 0 +0 2883 0 +0 3001 0 +0 3123 0 +0 3247 0 +0 3375 0 +0 3501 0 +0 3631 0 +0 3761 0 +0 3891 0 +0 4021 0 +2881 1865 3015 +2881 1867 3015 +2881 1870 3015 +2879 1874 3013 +2879 1879 3013 +2877 1885 3011 +2875 1894 3011 +2871 1905 3009 +2867 1920 3007 +2861 1939 3003 +2853 1963 2999 +2843 1993 2993 +2827 2031 2985 +2807 2077 2973 +2777 2131 2957 +2735 2197 2937 +2673 2271 2905 +2571 2353 2861 +2387 2445 2795 +1882 2545 2687 +0 2651 2487 +0 2763 1872 +0 2879 0 +0 2999 0 +0 3121 0 +0 3247 0 +0 3373 0 +0 3501 0 +0 3629 0 +0 3759 0 +0 3889 0 +0 4021 0 +2969 1817 3061 +2969 1819 3061 +2969 1822 3061 +2969 1826 3059 +2967 1832 3059 +2965 1839 3059 +2963 1849 3057 +2961 1861 3055 +2957 1877 3053 +2953 1898 3051 +2947 1924 3047 +2937 1957 3041 +2925 1998 3033 +2909 2047 3023 +2885 2105 3009 +2853 2173 2991 +2805 2251 2963 +2731 2337 2925 +2611 2433 2869 +2371 2535 2779 +1178 2643 2621 +0 2757 2255 +0 2873 0 +0 2995 0 +0 3119 0 +0 3243 0 +0 3371 0 +0 3499 0 +0 3629 0 +0 3759 0 +0 3889 0 +0 4021 0 +3067 1743 3117 +3065 1746 3117 +3065 1749 3115 +3065 1754 3115 +3063 1761 3115 +3063 1769 3113 +3061 1780 3113 +3059 1795 3111 +3057 1813 3109 +3053 1837 3107 +3047 1867 3103 +3041 1904 3099 +3031 1950 3093 +3017 2004 3083 +2999 2069 3071 +2973 2141 3055 +2937 2225 3031 +2883 2315 2999 +2801 2415 2951 +2657 2521 2877 +2349 2631 2755 +0 2747 2513 +0 2867 1244 +0 2989 0 +0 3115 0 +0 3241 0 +0 3369 0 +0 3497 0 +0 3627 0 +0 3757 0 +0 3889 0 +0 4019 0 +3169 1621 3181 +3169 1624 3181 +3169 1629 3181 +3169 1636 3181 +3167 1644 3179 +3167 1655 3179 +3165 1669 3179 +3163 1687 3177 +3161 1711 3175 +3159 1741 3173 +3155 1777 3169 +3149 1822 3165 +3141 1876 3161 +3131 1940 3153 +3117 2012 3143 +3097 2095 3129 +3071 2185 3109 +3031 2285 3081 +2971 2389 3041 +2879 2501 2981 +2715 2617 2887 +2319 2735 2719 +0 2857 2309 +0 2983 0 +0 3109 0 +0 3237 0 +0 3365 0 +0 3495 0 +0 3625 0 +0 3757 0 +0 3887 0 +0 4019 0 +3279 1379 3255 +3279 1385 3255 +3279 1394 3255 +3277 1404 3255 +3277 1418 3255 +3277 1436 3253 +3275 1459 3253 +3275 1487 3251 +3273 1523 3251 +3271 1567 3249 +3267 1620 3245 +3263 1683 3243 +3257 1754 3237 +3249 1836 3231 +3239 1925 3223 +3223 2023 3211 +3203 2127 3195 +3173 2239 3171 +3131 2353 3139 +3067 2473 3091 +2967 2595 3019 +2781 2719 2901 +2275 2845 2669 +0 2973 1672 +0 3101 0 +0 3231 0 +0 3361 0 +0 3493 0 +0 3623 0 +0 3755 0 +0 3887 0 +0 4019 0 +3393 117 3339 +3393 207 3339 +3393 305 3339 +3393 410 3339 +3391 520 3337 +3391 636 3337 +3391 755 3337 +3389 877 3335 +3389 1001 3335 +3387 1128 3333 +3383 1255 3331 +3381 1384 3329 +3375 1514 3325 +3369 1644 3319 +3361 1775 3311 +3351 1906 3303 +3335 2037 3289 +3313 2169 3271 +3283 2301 3245 +3239 2433 3207 +3171 2565 3153 +3061 2697 3067 +2857 2829 2919 +2207 2961 2591 +0 3093 0 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +3511 0 3431 +3511 0 3431 +3511 0 3431 +3511 0 3431 +3511 0 3431 +3509 0 3429 +3509 0 3429 +3509 0 3429 +3507 0 3427 +3507 0 3427 +3505 0 3425 +3501 0 3423 +3499 286 3419 +3493 1096 3415 +3487 1436 3409 +3479 1678 3401 +3467 1878 3391 +3451 2055 3375 +3429 2219 3355 +3397 2373 3327 +3351 2521 3285 +3279 2663 3223 +3165 2803 3123 +2943 2943 2943 +2099 3079 2463 +0 3215 0 +0 3349 0 +0 3483 0 +0 3617 0 +0 3749 0 +0 3883 0 +0 4015 0 +3633 0 3531 +3633 0 3531 +3633 0 3531 +3633 0 3531 +3633 0 3529 +3631 0 3529 +3631 0 3529 +3631 0 3529 +3629 0 3527 +3629 0 3527 +3627 0 3525 +3625 0 3523 +3623 0 3521 +3619 0 3517 +3615 0 3513 +3609 756 3507 +3599 1506 3499 +3587 1839 3487 +3571 2079 3471 +3547 2277 3449 +3515 2453 3417 +3467 2615 3371 +3395 2769 3301 +3273 2917 3189 +3035 3061 2971 +1896 3201 2197 +0 3339 0 +0 3475 0 +0 3611 0 +0 3745 0 +0 3879 0 +0 4013 0 +3757 0 3637 +3757 0 3637 +3757 0 3637 +3757 0 3637 +3757 0 3637 +3757 0 3637 +3755 0 3635 +3755 0 3635 +3755 0 3635 +3753 0 3633 +3753 0 3633 +3751 0 3631 +3749 0 3629 +3747 0 3627 +3743 0 3623 +3739 0 3619 +3731 0 3611 +3723 1069 3603 +3711 1780 3591 +3693 2107 3573 +3671 2345 3549 +3637 2543 3515 +3587 2719 3467 +3513 2881 3391 +3387 3035 3263 +3137 3181 3007 +1263 3325 0 +0 3465 0 +0 3603 0 +0 3739 0 +0 3875 0 +0 4009 0 +3883 0 3749 +3883 0 3749 +3883 0 3749 +3883 0 3749 +3883 0 3749 +3883 0 3747 +3881 0 3747 +3881 0 3747 +3881 0 3747 +3881 0 3747 +3879 0 3745 +3879 0 3745 +3877 0 3743 +3875 0 3741 +3873 0 3737 +3869 0 3733 +3863 0 3729 +3857 0 3721 +3849 0 3713 +3835 1687 3699 +3819 2145 3681 +3795 2423 3657 +3761 2641 3621 +3711 2827 3569 +3633 2997 3487 +3505 3155 3347 +3243 3305 3053 +0 3451 0 +0 3593 0 +0 3733 0 +0 3869 0 +0 4005 0 +4011 0 3865 +4011 0 3865 +4011 0 3865 +4011 0 3865 +4009 0 3865 +4009 0 3865 +4009 0 3865 +4009 0 3863 +4009 0 3863 +4009 0 3863 +4007 0 3863 +4007 0 3861 +4005 0 3861 +4005 0 3859 +4003 0 3857 +3999 0 3853 +3997 0 3849 +3991 0 3845 +3985 0 3837 +3975 0 3827 +3963 1522 3815 +3945 2189 3795 +3921 2511 3769 +3887 2745 3731 +3835 2941 3677 +3757 3117 3589 +3627 3279 3441 +3357 3431 3105 +0 3579 0 +0 3721 0 +0 3861 0 +0 3999 0 +4095 0 3985 +4095 0 3985 +4095 0 3985 +4095 0 3985 +4095 0 3985 +4095 0 3985 +4095 0 3985 +4095 0 3985 +4095 0 3983 +4095 0 3983 +4095 0 3983 +4095 0 3983 +4095 0 3981 +4095 0 3981 +4095 0 3979 +4095 0 3977 +4095 0 3973 +4095 0 3969 +4095 0 3963 +4095 0 3957 +4095 0 3947 +4091 1122 3933 +4073 2243 3913 +4049 2605 3887 +4015 2855 3847 +3963 3061 3789 +3883 3239 3699 +3751 3405 3541 +3473 3559 3169 +0 3707 0 +0 3851 0 +0 3993 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4091 +4095 0 4085 +4095 0 4079 +4095 0 4069 +4095 0 4053 +4095 2305 4035 +4095 2707 4007 +4095 2971 3967 +4091 3181 3907 +4011 3365 3813 +3877 3531 3647 +3593 3687 3241 +0 3837 0 +0 3981 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 2377 4095 +4095 2815 4095 +4095 3091 4089 +4095 3305 4029 +4095 3491 3933 +4003 3659 3759 +3717 3817 3321 +0 3967 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 2459 4095 +4095 2929 4095 +4095 3213 4095 +4095 3431 4095 +4095 3619 4053 +4095 3789 3877 +3843 3947 3413 +2563 2115 2975 +2561 2115 2975 +2559 2117 2975 +2557 2119 2973 +2555 2123 2973 +2551 2125 2971 +2547 2131 2971 +2539 2137 2969 +2531 2147 2965 +2519 2159 2961 +2501 2173 2957 +2477 2193 2951 +2445 2217 2941 +2395 2249 2929 +2319 2287 2913 +2193 2333 2889 +1937 2389 2855 +0 2455 2805 +0 2529 2729 +0 2613 2601 +0 2707 2345 +0 2807 0 +0 2913 0 +0 3025 0 +0 3141 0 +0 3261 0 +0 3385 0 +0 3509 0 +0 3637 0 +0 3765 0 +0 3893 0 +0 4023 0 +2563 2113 2975 +2563 2115 2975 +2561 2117 2975 +2559 2119 2973 +2557 2121 2973 +2553 2125 2973 +2547 2131 2971 +2541 2137 2969 +2533 2147 2965 +2519 2157 2963 +2503 2173 2957 +2479 2193 2951 +2445 2217 2941 +2397 2249 2929 +2321 2287 2913 +2195 2333 2889 +1942 2389 2855 +0 2455 2805 +0 2529 2729 +0 2613 2603 +0 2707 2347 +0 2807 0 +0 2913 0 +0 3025 0 +0 3141 0 +0 3261 0 +0 3385 0 +0 3509 0 +0 3637 0 +0 3765 0 +0 3893 0 +0 4023 0 +2565 2113 2975 +2565 2115 2975 +2563 2117 2975 +2561 2119 2975 +2559 2121 2973 +2555 2125 2973 +2549 2131 2971 +2543 2137 2969 +2535 2147 2967 +2523 2157 2963 +2505 2173 2957 +2481 2193 2951 +2449 2217 2943 +2399 2247 2931 +2325 2287 2913 +2199 2333 2889 +1950 2389 2855 +201 2455 2807 +0 2529 2731 +0 2613 2603 +0 2707 2349 +0 2807 0 +0 2913 0 +0 3025 0 +0 3141 0 +0 3261 0 +0 3385 0 +0 3509 0 +0 3637 0 +0 3765 0 +0 3893 0 +0 4023 0 +2567 2113 2977 +2567 2115 2977 +2565 2117 2975 +2563 2119 2975 +2561 2121 2975 +2557 2125 2973 +2553 2131 2971 +2545 2137 2969 +2537 2145 2967 +2525 2157 2963 +2509 2173 2959 +2485 2191 2953 +2451 2217 2943 +2403 2247 2931 +2329 2287 2913 +2205 2333 2891 +1959 2389 2857 +515 2455 2807 +0 2529 2731 +0 2613 2605 +0 2707 2351 +0 2807 0 +0 2913 0 +0 3025 0 +0 3141 0 +0 3261 0 +0 3385 0 +0 3509 0 +0 3637 0 +0 3765 0 +0 3893 0 +0 4023 0 +2571 2113 2977 +2569 2115 2977 +2569 2115 2977 +2567 2117 2977 +2563 2121 2975 +2561 2125 2975 +2555 2129 2973 +2549 2137 2971 +2541 2145 2969 +2529 2157 2965 +2511 2173 2959 +2489 2191 2953 +2455 2217 2945 +2407 2247 2931 +2333 2285 2915 +2213 2333 2891 +1972 2389 2857 +748 2455 2809 +0 2529 2733 +0 2613 2607 +0 2705 2355 +0 2807 171 +0 2913 0 +0 3025 0 +0 3141 0 +0 3261 0 +0 3385 0 +0 3509 0 +0 3637 0 +0 3765 0 +0 3893 0 +0 4023 0 +2575 2113 2979 +2575 2113 2979 +2573 2115 2977 +2571 2117 2977 +2569 2121 2977 +2565 2125 2975 +2561 2129 2973 +2553 2135 2971 +2545 2145 2969 +2533 2157 2965 +2517 2171 2961 +2493 2191 2955 +2461 2215 2945 +2413 2247 2933 +2341 2285 2917 +2221 2333 2893 +1988 2389 2859 +942 2453 2811 +0 2529 2735 +0 2613 2611 +0 2705 2359 +0 2805 544 +0 2913 0 +0 3025 0 +0 3141 0 +0 3261 0 +0 3385 0 +0 3509 0 +0 3637 0 +0 3765 0 +0 3893 0 +0 4023 0 +2581 2111 2981 +2581 2113 2979 +2579 2115 2979 +2577 2117 2979 +2575 2119 2979 +2571 2123 2977 +2567 2129 2975 +2559 2135 2973 +2551 2145 2971 +2539 2155 2967 +2523 2171 2963 +2501 2191 2955 +2469 2215 2947 +2423 2247 2935 +2351 2285 2919 +2235 2331 2895 +2009 2387 2861 +1116 2453 2813 +0 2529 2737 +0 2613 2613 +0 2705 2367 +0 2805 799 +0 2913 0 +0 3025 0 +0 3141 0 +0 3261 0 +0 3385 0 +0 3509 0 +0 3637 0 +0 3765 0 +0 3893 0 +0 4023 0 +2589 2111 2983 +2587 2111 2983 +2587 2113 2981 +2585 2115 2981 +2583 2119 2981 +2579 2123 2979 +2575 2127 2977 +2567 2135 2975 +2559 2143 2973 +2547 2155 2969 +2533 2169 2965 +2509 2189 2959 +2479 2215 2949 +2433 2245 2937 +2363 2285 2921 +2251 2331 2897 +2035 2387 2865 +1277 2453 2815 +0 2529 2741 +0 2613 2619 +0 2705 2375 +0 2805 1005 +0 2913 0 +0 3025 0 +0 3141 0 +0 3261 0 +0 3385 0 +0 3509 0 +0 3637 0 +0 3765 0 +0 3893 0 +0 4023 0 +2599 2109 2985 +2597 2111 2985 +2597 2111 2985 +2595 2113 2983 +2593 2117 2983 +2589 2121 2983 +2585 2125 2981 +2579 2133 2979 +2571 2141 2975 +2559 2153 2973 +2543 2169 2967 +2521 2189 2961 +2491 2213 2953 +2447 2245 2941 +2379 2283 2923 +2271 2331 2901 +2069 2387 2867 +1430 2453 2819 +0 2527 2747 +0 2611 2625 +0 2705 2385 +0 2805 1185 +0 2913 0 +0 3025 0 +0 3141 0 +0 3261 0 +0 3385 0 +0 3509 0 +0 3637 0 +0 3765 0 +0 3893 0 +0 4023 0 +2611 2107 2989 +2611 2109 2989 +2609 2109 2989 +2607 2113 2987 +2605 2115 2987 +2603 2119 2985 +2597 2125 2985 +2593 2131 2983 +2585 2139 2979 +2573 2151 2977 +2559 2167 2971 +2537 2187 2965 +2507 2211 2957 +2465 2243 2945 +2401 2281 2929 +2297 2329 2905 +2109 2385 2873 +1577 2451 2825 +0 2527 2753 +0 2611 2633 +0 2705 2399 +0 2805 1350 +0 2911 0 +0 3025 0 +0 3141 0 +0 3261 0 +0 3385 0 +0 3509 0 +0 3637 0 +0 3765 0 +0 3893 0 +0 4023 0 +2629 2105 2995 +2627 2105 2993 +2627 2107 2993 +2625 2109 2993 +2623 2113 2991 +2619 2117 2991 +2615 2121 2989 +2609 2129 2987 +2601 2137 2985 +2591 2149 2981 +2577 2165 2977 +2557 2185 2971 +2529 2209 2961 +2489 2241 2951 +2427 2279 2933 +2331 2327 2911 +2159 2383 2879 +1720 2451 2833 +0 2525 2761 +0 2611 2645 +0 2703 2417 +0 2805 1506 +0 2911 0 +0 3023 0 +0 3141 0 +0 3261 0 +0 3385 0 +0 3509 0 +0 3637 0 +0 3765 0 +0 3893 0 +0 4023 0 +2651 2101 3001 +2649 2101 3001 +2649 2103 2999 +2647 2105 2999 +2645 2109 2999 +2641 2113 2997 +2637 2119 2997 +2633 2125 2995 +2625 2135 2991 +2615 2147 2989 +2601 2161 2983 +2583 2181 2977 +2555 2207 2969 +2517 2239 2957 +2461 2277 2941 +2371 2325 2919 +2217 2383 2887 +1860 2449 2841 +0 2525 2773 +0 2609 2659 +0 2703 2441 +0 2803 1654 +0 2911 0 +0 3023 0 +0 3141 0 +0 3261 0 +0 3383 0 +0 3509 0 +0 3637 0 +0 3765 0 +0 3893 0 +0 4023 0 +2677 2095 3009 +2677 2097 3009 +2675 2099 3009 +2675 2101 3009 +2673 2105 3007 +2669 2109 3007 +2665 2113 3005 +2661 2121 3003 +2653 2129 3001 +2645 2141 2997 +2631 2157 2993 +2615 2177 2987 +2589 2203 2979 +2553 2235 2967 +2501 2275 2951 +2421 2323 2929 +2285 2379 2899 +1998 2447 2855 +0 2523 2787 +0 2607 2677 +0 2701 2469 +0 2803 1798 +0 2909 0 +0 3023 0 +0 3139 0 +0 3261 0 +0 3383 0 +0 3509 0 +0 3635 0 +0 3765 0 +0 3893 0 +0 4023 0 +2713 2089 3021 +2711 2091 3021 +2711 2093 3021 +2709 2095 3019 +2707 2097 3019 +2705 2101 3017 +2701 2107 3017 +2697 2115 3015 +2689 2123 3013 +2681 2135 3009 +2669 2151 3005 +2653 2171 2999 +2631 2197 2991 +2599 2231 2979 +2551 2269 2965 +2479 2319 2943 +2363 2377 2913 +2133 2443 2869 +1197 2519 2805 +0 2605 2699 +0 2699 2505 +0 2801 1939 +0 2909 0 +0 3021 0 +0 3139 0 +0 3259 0 +0 3383 0 +0 3509 0 +0 3635 0 +0 3765 0 +0 3893 0 +0 4023 0 +2755 2081 3035 +2753 2081 3035 +2753 2083 3035 +2751 2087 3035 +2749 2089 3033 +2747 2093 3033 +2745 2099 3031 +2739 2107 3029 +2735 2115 3027 +2727 2127 3025 +2715 2143 3019 +2701 2165 3015 +2681 2191 3007 +2651 2223 2995 +2611 2265 2981 +2549 2313 2961 +2449 2371 2931 +2269 2439 2891 +1794 2517 2829 +0 2603 2729 +0 2697 2551 +0 2799 2077 +0 2907 0 +0 3021 0 +0 3139 0 +0 3259 0 +0 3383 0 +0 3509 0 +0 3635 0 +0 3763 0 +0 3893 0 +0 4023 0 +2805 2069 3055 +2805 2069 3055 +2803 2071 3053 +2803 2075 3053 +2801 2077 3053 +2799 2081 3051 +2797 2087 3051 +2793 2095 3049 +2787 2105 3047 +2781 2117 3043 +2771 2133 3039 +2757 2155 3033 +2739 2181 3027 +2715 2215 3017 +2679 2257 3003 +2625 2305 2983 +2543 2365 2955 +2403 2433 2917 +2105 2511 2857 +0 2599 2765 +0 2695 2603 +0 2797 2215 +0 2905 0 +0 3019 0 +0 3137 0 +0 3259 0 +0 3381 0 +0 3507 0 +0 3635 0 +0 3763 0 +0 3893 0 +0 4023 0 +2865 2051 3079 +2865 2053 3079 +2865 2055 3079 +2863 2057 3077 +2861 2061 3077 +2859 2065 3077 +2857 2071 3075 +2855 2079 3073 +2849 2089 3071 +2843 2103 3069 +2835 2119 3065 +2825 2141 3059 +2809 2169 3053 +2787 2203 3043 +2757 2245 3029 +2713 2297 3011 +2645 2357 2985 +2537 2427 2949 +2335 2505 2895 +1706 2593 2811 +0 2691 2667 +0 2793 2351 +0 2903 0 +0 3017 0 +0 3135 0 +0 3257 0 +0 3381 0 +0 3507 0 +0 3635 0 +0 3763 0 +0 3893 0 +0 4023 0 +2935 2029 3109 +2935 2030 3109 +2935 2032 3109 +2933 2035 3109 +2933 2038 3107 +2931 2043 3107 +2929 2049 3105 +2925 2057 3105 +2921 2067 3103 +2917 2081 3099 +2909 2099 3097 +2901 2121 3091 +2887 2151 3085 +2869 2187 3075 +2843 2229 3063 +2807 2283 3047 +2753 2345 3023 +2671 2417 2989 +2529 2497 2939 +2225 2587 2865 +0 2685 2739 +0 2789 2485 +0 2899 0 +0 3015 0 +0 3133 0 +0 3255 0 +0 3379 0 +0 3507 0 +0 3633 0 +0 3763 0 +0 3893 0 +0 4023 0 +3015 1995 3147 +3013 1997 3147 +3013 1999 3147 +3013 2002 3147 +3011 2006 3145 +3011 2011 3145 +3009 2017 3143 +3007 2026 3143 +3003 2037 3141 +2999 2051 3139 +2993 2071 3135 +2985 2095 3131 +2975 2125 3125 +2959 2163 3117 +2939 2209 3105 +2909 2263 3089 +2867 2329 3069 +2805 2403 3037 +2703 2485 2993 +2519 2577 2927 +2014 2677 2819 +0 2783 2619 +0 2895 2004 +0 3011 0 +0 3131 0 +0 3253 0 +0 3379 0 +0 3505 0 +0 3633 0 +0 3761 0 +0 3891 0 +0 4023 0 +3103 1947 3193 +3103 1949 3193 +3101 1951 3193 +3101 1954 3193 +3101 1958 3193 +3099 1964 3191 +3097 1971 3191 +3095 1981 3189 +3093 1993 3187 +3089 2009 3185 +3085 2030 3183 +3079 2057 3179 +3069 2089 3173 +3057 2131 3165 +3041 2179 3155 +3017 2237 3141 +2985 2305 3123 +2937 2383 3095 +2863 2469 3057 +2743 2565 3001 +2503 2667 2911 +1310 2775 2753 +0 2889 2387 +0 3005 0 +0 3127 0 +0 3251 0 +0 3377 0 +0 3503 0 +0 3631 0 +0 3761 0 +0 3891 0 +0 4021 0 +3199 1873 3249 +3199 1875 3249 +3197 1878 3249 +3197 1882 3247 +3197 1886 3247 +3195 1893 3247 +3195 1901 3247 +3193 1912 3245 +3191 1927 3243 +3189 1946 3241 +3185 1969 3239 +3179 1999 3235 +3173 2036 3231 +3163 2081 3225 +3149 2137 3215 +3131 2201 3203 +3107 2273 3187 +3069 2357 3163 +3015 2447 3131 +2933 2547 3083 +2789 2653 3009 +2481 2763 2887 +0 2879 2645 +0 2999 1376 +0 3121 0 +0 3247 0 +0 3373 0 +0 3501 0 +0 3629 0 +0 3759 0 +0 3891 0 +0 4021 0 +3301 1750 3313 +3301 1753 3313 +3301 1757 3313 +3301 1761 3313 +3301 1768 3313 +3299 1776 3311 +3299 1787 3311 +3297 1801 3311 +3295 1820 3309 +3293 1843 3307 +3291 1873 3305 +3287 1909 3301 +3281 1954 3297 +3273 2008 3293 +3263 2071 3285 +3249 2145 3275 +3229 2227 3261 +3203 2317 3241 +3163 2417 3213 +3103 2521 3173 +3011 2633 3113 +2847 2749 3019 +2451 2867 2851 +0 2991 2441 +0 3115 0 +0 3241 0 +0 3369 0 +0 3497 0 +0 3627 0 +0 3759 0 +0 3889 0 +0 4019 0 +3411 1507 3387 +3411 1511 3387 +3411 1518 3387 +3411 1526 3387 +3409 1536 3387 +3409 1550 3387 +3409 1568 3385 +3407 1591 3385 +3407 1620 3383 +3405 1656 3383 +3403 1700 3381 +3399 1752 3377 +3395 1815 3375 +3389 1886 3369 +3381 1968 3363 +3371 2057 3355 +3355 2155 3343 +3335 2259 3327 +3305 2371 3303 +3263 2485 3271 +3199 2605 3223 +3099 2727 3151 +2913 2851 3033 +2407 2977 2801 +0 3105 1804 +0 3235 0 +0 3363 0 +0 3493 0 +0 3625 0 +0 3755 0 +0 3887 0 +0 4019 0 +3525 167 3471 +3525 249 3471 +3525 339 3471 +3525 437 3471 +3525 542 3471 +3523 652 3471 +3523 768 3469 +3523 887 3469 +3521 1009 3467 +3521 1133 3467 +3519 1260 3465 +3515 1387 3463 +3513 1516 3461 +3509 1646 3457 +3503 1776 3451 +3493 1907 3443 +3483 2038 3435 +3467 2169 3421 +3445 2301 3403 +3415 2433 3377 +3371 2565 3339 +3303 2697 3285 +3193 2829 3199 +2989 2961 3051 +2339 3093 2725 +0 3225 0 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +3643 0 3563 +3643 0 3563 +3643 0 3563 +3643 0 3563 +3643 0 3563 +3643 0 3563 +3643 0 3561 +3641 0 3561 +3641 0 3561 +3639 0 3559 +3639 0 3559 +3637 0 3557 +3633 0 3555 +3631 418 3551 +3625 1228 3547 +3619 1568 3541 +3611 1811 3533 +3599 2011 3523 +3583 2187 3507 +3561 2351 3487 +3529 2505 3459 +3483 2653 3417 +3413 2795 3355 +3297 2937 3255 +3075 3075 3075 +2231 3211 2595 +0 3347 0 +0 3481 0 +0 3615 0 +0 3749 0 +0 3881 0 +0 4015 0 +3765 0 3663 +3765 0 3663 +3765 0 3663 +3765 0 3663 +3765 0 3663 +3765 0 3663 +3763 0 3661 +3763 0 3661 +3763 0 3661 +3763 0 3659 +3761 0 3659 +3759 0 3657 +3757 0 3655 +3755 0 3653 +3751 0 3649 +3747 0 3645 +3741 888 3639 +3731 1638 3631 +3719 1971 3619 +3703 2211 3603 +3681 2409 3581 +3647 2585 3549 +3599 2749 3503 +3527 2901 3433 +3405 3049 3321 +3167 3193 3103 +2028 3333 2329 +0 3471 0 +0 3607 0 +0 3743 0 +0 3877 0 +0 4011 0 +3889 0 3769 +3889 0 3769 +3889 0 3769 +3889 0 3769 +3889 0 3769 +3889 0 3769 +3889 0 3769 +3887 0 3767 +3887 0 3767 +3887 0 3767 +3885 0 3765 +3885 0 3765 +3883 0 3763 +3881 0 3761 +3879 0 3759 +3875 0 3755 +3871 0 3751 +3863 0 3743 +3855 1201 3735 +3843 1912 3723 +3825 2239 3705 +3803 2477 3681 +3769 2675 3647 +3719 2851 3599 +3645 3013 3523 +3519 3167 3395 +3269 3313 3139 +1395 3457 0 +0 3597 0 +0 3735 0 +0 3871 0 +0 4007 0 +4015 0 3881 +4015 0 3881 +4015 0 3881 +4015 0 3881 +4015 0 3881 +4015 0 3881 +4015 0 3881 +4015 0 3879 +4013 0 3879 +4013 0 3879 +4013 0 3879 +4011 0 3877 +4011 0 3877 +4009 0 3875 +4007 0 3873 +4005 0 3869 +4001 0 3867 +3995 0 3861 +3989 0 3855 +3981 0 3845 +3967 1819 3831 +3951 2277 3813 +3927 2555 3789 +3893 2773 3753 +3843 2961 3701 +3765 3129 3619 +3637 3287 3479 +3375 3437 3185 +0 3583 0 +0 3725 0 +0 3865 0 +0 4001 0 +4095 0 3997 +4095 0 3997 +4095 0 3997 +4095 0 3997 +4095 0 3997 +4095 0 3997 +4095 0 3997 +4095 0 3997 +4095 0 3997 +4095 0 3995 +4095 0 3995 +4095 0 3995 +4095 0 3993 +4095 0 3993 +4095 0 3991 +4095 0 3989 +4095 0 3985 +4095 0 3981 +4095 0 3977 +4095 0 3969 +4095 0 3959 +4095 1654 3947 +4077 2321 3927 +4053 2643 3901 +4019 2877 3865 +3967 3075 3809 +3889 3249 3723 +3759 3411 3573 +3489 3563 3237 +0 3711 0 +0 3853 0 +0 3993 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4089 +4095 0 4079 +4095 1254 4065 +4095 2375 4045 +4095 2737 4019 +4095 2989 3979 +4095 3193 3923 +4015 3371 3831 +3883 3537 3673 +3605 3691 3301 +0 3839 0 +0 3983 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 2437 4095 +4095 2839 4095 +4095 3103 4095 +4095 3313 4039 +4095 3497 3945 +4009 3663 3779 +3725 3819 3373 +0 3969 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 2509 4095 +4095 2949 4095 +4095 3223 4095 +4095 3437 4095 +4095 3623 4065 +4095 3791 3891 +3849 3949 3455 +2693 2245 3107 +2693 2247 3107 +2691 2247 3107 +2691 2249 3107 +2689 2251 3105 +2685 2255 3105 +2683 2259 3103 +2677 2263 3103 +2671 2269 3101 +2661 2279 3097 +2649 2291 3093 +2633 2305 3089 +2609 2325 3083 +2575 2349 3073 +2525 2381 3061 +2449 2419 3043 +2321 2465 3021 +2065 2521 2987 +0 2587 2937 +0 2661 2861 +0 2745 2733 +0 2839 2477 +0 2939 0 +0 3045 0 +0 3157 0 +0 3273 0 +0 3393 0 +0 3517 0 +0 3641 0 +0 3769 0 +0 3897 0 +0 4025 0 +2695 2245 3107 +2695 2247 3107 +2693 2247 3107 +2691 2249 3107 +2689 2251 3105 +2687 2255 3105 +2683 2259 3103 +2679 2263 3103 +2671 2269 3101 +2663 2279 3097 +2651 2291 3095 +2633 2305 3089 +2609 2325 3083 +2577 2349 3073 +2527 2381 3061 +2451 2419 3045 +2325 2465 3021 +2069 2521 2987 +0 2587 2937 +0 2661 2861 +0 2745 2733 +0 2839 2477 +0 2939 0 +0 3045 0 +0 3157 0 +0 3273 0 +0 3393 0 +0 3517 0 +0 3641 0 +0 3769 0 +0 3897 0 +0 4025 0 +2697 2245 3107 +2695 2247 3107 +2695 2247 3107 +2693 2249 3107 +2691 2251 3107 +2689 2253 3105 +2685 2257 3105 +2679 2263 3103 +2673 2269 3101 +2665 2279 3099 +2653 2291 3095 +2635 2305 3089 +2611 2325 3083 +2577 2349 3073 +2529 2381 3061 +2453 2419 3045 +2327 2465 3021 +2075 2521 2987 +0 2587 2937 +0 2661 2861 +0 2745 2735 +0 2839 2479 +0 2939 0 +0 3045 0 +0 3157 0 +0 3273 0 +0 3393 0 +0 3517 0 +0 3641 0 +0 3769 0 +0 3897 0 +0 4025 0 +2699 2245 3109 +2697 2245 3109 +2697 2247 3107 +2695 2249 3107 +2693 2251 3107 +2691 2253 3105 +2687 2257 3105 +2681 2263 3103 +2675 2269 3101 +2667 2279 3099 +2655 2289 3095 +2637 2305 3091 +2613 2325 3083 +2581 2349 3075 +2531 2381 3063 +2457 2419 3045 +2331 2465 3021 +2081 2521 2987 +333 2587 2939 +0 2661 2863 +0 2745 2735 +0 2839 2481 +0 2939 0 +0 3045 0 +0 3157 0 +0 3273 0 +0 3393 0 +0 3517 0 +0 3641 0 +0 3769 0 +0 3897 0 +0 4025 0 +2701 2245 3109 +2699 2245 3109 +2699 2247 3109 +2697 2249 3107 +2695 2251 3107 +2693 2253 3107 +2689 2257 3105 +2685 2263 3103 +2677 2269 3101 +2669 2277 3099 +2657 2289 3095 +2641 2305 3091 +2617 2325 3085 +2583 2349 3075 +2535 2379 3063 +2461 2419 3047 +2337 2465 3023 +2091 2521 2989 +647 2587 2939 +0 2661 2863 +0 2745 2737 +0 2839 2483 +0 2939 0 +0 3045 0 +0 3157 0 +0 3273 0 +0 3393 0 +0 3517 0 +0 3641 0 +0 3769 0 +0 3897 0 +0 4025 0 +2705 2245 3109 +2703 2245 3109 +2703 2247 3109 +2701 2247 3109 +2699 2251 3109 +2697 2253 3107 +2693 2257 3107 +2687 2261 3105 +2681 2269 3103 +2673 2277 3101 +2661 2289 3097 +2643 2305 3091 +2621 2323 3085 +2587 2349 3077 +2539 2379 3063 +2467 2417 3047 +2345 2465 3023 +2103 2521 2989 +880 2587 2941 +0 2661 2865 +0 2745 2739 +0 2839 2487 +0 2939 303 +0 3045 0 +0 3157 0 +0 3273 0 +0 3393 0 +0 3517 0 +0 3641 0 +0 3769 0 +0 3897 0 +0 4025 0 +2709 2243 3111 +2707 2245 3111 +2707 2245 3111 +2705 2247 3111 +2703 2249 3109 +2701 2253 3109 +2697 2257 3107 +2693 2261 3107 +2685 2269 3105 +2677 2277 3101 +2665 2289 3097 +2649 2303 3093 +2627 2323 3087 +2593 2347 3077 +2545 2379 3065 +2473 2417 3049 +2353 2465 3025 +2121 2521 2991 +1074 2585 2943 +0 2661 2867 +0 2745 2743 +0 2837 2493 +0 2939 677 +0 3045 0 +0 3157 0 +0 3273 0 +0 3393 0 +0 3517 0 +0 3641 0 +0 3769 0 +0 3897 0 +0 4025 0 +2715 2243 3113 +2713 2243 3113 +2713 2245 3113 +2711 2247 3111 +2709 2249 3111 +2707 2251 3111 +2703 2255 3109 +2699 2261 3107 +2693 2267 3105 +2683 2277 3103 +2671 2287 3099 +2655 2303 3095 +2633 2323 3089 +2601 2347 3079 +2555 2379 3067 +2483 2417 3051 +2367 2463 3027 +2141 2519 2993 +1248 2585 2945 +0 2661 2869 +0 2745 2745 +0 2837 2499 +0 2937 931 +0 3045 0 +0 3157 0 +0 3273 0 +0 3393 0 +0 3517 0 +0 3641 0 +0 3769 0 +0 3897 0 +0 4025 0 +2721 2241 3115 +2721 2243 3115 +2719 2243 3115 +2719 2245 3113 +2717 2247 3113 +2715 2251 3113 +2711 2255 3111 +2707 2259 3109 +2701 2267 3107 +2691 2275 3105 +2681 2287 3101 +2665 2303 3097 +2643 2321 3091 +2611 2347 3081 +2565 2377 3069 +2495 2417 3053 +2383 2463 3029 +2167 2519 2997 +1409 2585 2947 +0 2661 2873 +0 2745 2751 +0 2837 2507 +0 2937 1137 +0 3045 0 +0 3157 0 +0 3273 0 +0 3393 0 +0 3517 0 +0 3641 0 +0 3769 0 +0 3897 0 +0 4025 0 +2731 2241 3117 +2731 2241 3117 +2731 2243 3117 +2729 2243 3117 +2727 2247 3117 +2725 2249 3115 +2721 2253 3115 +2717 2259 3113 +2711 2265 3111 +2703 2273 3109 +2691 2285 3105 +2675 2301 3099 +2653 2321 3093 +2623 2345 3085 +2579 2377 3073 +2513 2415 3057 +2403 2463 3033 +2201 2519 3001 +1562 2585 2951 +0 2659 2879 +0 2745 2757 +0 2837 2517 +0 2937 1317 +0 3045 0 +0 3157 0 +0 3273 0 +0 3393 0 +0 3517 0 +0 3641 0 +0 3769 0 +0 3897 0 +0 4025 0 +2745 2239 3121 +2745 2239 3121 +2743 2241 3121 +2741 2241 3121 +2739 2245 3119 +2737 2247 3119 +2735 2251 3117 +2731 2257 3117 +2725 2263 3115 +2717 2273 3111 +2705 2283 3109 +2691 2299 3103 +2669 2319 3097 +2639 2343 3089 +2597 2375 3077 +2533 2413 3061 +2429 2461 3037 +2241 2517 3005 +1709 2583 2957 +0 2659 2885 +0 2743 2765 +0 2837 2531 +0 2937 1482 +0 3043 0 +0 3157 0 +0 3273 0 +0 3393 0 +0 3517 0 +0 3641 0 +0 3769 0 +0 3897 0 +0 4025 0 +2761 2235 3127 +2761 2237 3127 +2761 2237 3125 +2759 2239 3125 +2757 2241 3125 +2755 2245 3125 +2751 2249 3123 +2747 2253 3121 +2741 2261 3119 +2735 2269 3117 +2723 2281 3113 +2709 2297 3109 +2689 2317 3103 +2661 2341 3095 +2621 2373 3083 +2559 2413 3067 +2463 2459 3043 +2291 2517 3011 +1852 2583 2965 +0 2657 2893 +0 2743 2777 +0 2835 2549 +0 2937 1638 +0 3043 0 +0 3155 0 +0 3273 0 +0 3393 0 +0 3517 0 +0 3641 0 +0 3769 0 +0 3897 0 +0 4025 0 +2783 2231 3133 +2783 2233 3133 +2781 2235 3133 +2781 2235 3133 +2779 2239 3131 +2777 2241 3131 +2773 2245 3129 +2769 2251 3129 +2765 2257 3127 +2757 2267 3123 +2747 2279 3121 +2733 2293 3115 +2715 2313 3109 +2687 2339 3101 +2649 2371 3089 +2593 2409 3073 +2503 2457 3051 +2349 2515 3019 +1992 2581 2973 +0 2657 2905 +0 2741 2791 +0 2835 2573 +0 2935 1786 +0 3043 0 +0 3155 0 +0 3273 0 +0 3393 0 +0 3515 0 +0 3641 0 +0 3769 0 +0 3897 0 +0 4025 0 +2811 2227 3141 +2811 2229 3141 +2809 2229 3141 +2809 2231 3141 +2807 2233 3141 +2805 2237 3139 +2801 2241 3139 +2797 2245 3137 +2793 2253 3135 +2787 2261 3133 +2777 2273 3129 +2763 2289 3125 +2747 2309 3119 +2721 2335 3111 +2687 2367 3099 +2633 2407 3083 +2553 2455 3061 +2417 2511 3031 +2129 2579 2987 +0 2655 2919 +0 2739 2809 +0 2833 2601 +0 2935 1931 +0 3043 0 +0 3155 0 +0 3271 0 +0 3393 0 +0 3515 0 +0 3641 0 +0 3769 0 +0 3897 0 +0 4025 0 +2845 2221 3153 +2845 2221 3153 +2843 2223 3153 +2843 2225 3153 +2841 2227 3151 +2839 2229 3151 +2837 2235 3149 +2833 2239 3149 +2829 2247 3147 +2823 2255 3145 +2813 2267 3141 +2801 2283 3137 +2785 2305 3131 +2763 2329 3123 +2731 2363 3111 +2683 2403 3097 +2613 2451 3075 +2495 2509 3045 +2267 2575 3003 +1329 2653 2937 +0 2737 2831 +0 2831 2637 +0 2933 2071 +0 3041 0 +0 3153 0 +0 3271 0 +0 3391 0 +0 3515 0 +0 3641 0 +0 3767 0 +0 3897 0 +0 4025 0 +2887 2211 3167 +2887 2213 3167 +2885 2215 3167 +2885 2215 3167 +2883 2219 3167 +2881 2221 3165 +2879 2225 3165 +2877 2231 3163 +2873 2239 3161 +2867 2247 3159 +2859 2261 3157 +2847 2277 3151 +2833 2297 3147 +2813 2323 3139 +2785 2355 3127 +2743 2397 3113 +2681 2445 3093 +2581 2503 3065 +2401 2571 3023 +1927 2649 2961 +0 2735 2861 +0 2829 2683 +0 2931 2211 +0 3039 0 +0 3153 0 +0 3271 0 +0 3391 0 +0 3515 0 +0 3641 0 +0 3767 0 +0 3895 0 +0 4025 0 +2937 2199 3187 +2937 2201 3187 +2937 2203 3187 +2935 2203 3185 +2935 2207 3185 +2933 2209 3185 +2931 2213 3183 +2929 2219 3183 +2925 2227 3181 +2919 2237 3179 +2913 2249 3175 +2903 2265 3171 +2889 2287 3167 +2873 2313 3159 +2847 2347 3149 +2811 2389 3135 +2757 2439 3115 +2675 2497 3087 +2535 2565 3049 +2237 2645 2991 +0 2731 2897 +0 2827 2735 +0 2929 2347 +0 3037 0 +0 3151 0 +0 3269 0 +0 3391 0 +0 3515 0 +0 3639 0 +0 3767 0 +0 3895 0 +0 4025 0 +2997 2183 3211 +2997 2185 3211 +2997 2185 3211 +2997 2187 3211 +2995 2189 3209 +2993 2193 3209 +2993 2197 3209 +2989 2203 3207 +2987 2211 3205 +2981 2221 3203 +2975 2235 3201 +2967 2251 3197 +2957 2273 3191 +2941 2301 3185 +2919 2335 3175 +2889 2377 3161 +2845 2429 3143 +2777 2489 3117 +2669 2559 3081 +2467 2637 3027 +1839 2727 2943 +0 2823 2799 +0 2925 2483 +0 3035 0 +0 3149 0 +0 3267 0 +0 3389 0 +0 3513 0 +0 3639 0 +0 3767 0 +0 3895 0 +0 4025 0 +3067 2159 3241 +3067 2161 3241 +3067 2163 3241 +3067 2165 3241 +3065 2167 3241 +3065 2171 3239 +3063 2175 3239 +3061 2181 3237 +3057 2189 3237 +3053 2199 3235 +3049 2213 3231 +3041 2231 3229 +3033 2253 3223 +3019 2283 3217 +3001 2319 3207 +2975 2363 3195 +2939 2415 3179 +2887 2477 3155 +2803 2549 3121 +2661 2629 3073 +2357 2719 2997 +0 2817 2871 +0 2921 2617 +0 3031 83 +0 3147 0 +0 3265 0 +0 3387 0 +0 3511 0 +0 3639 0 +0 3765 0 +0 3895 0 +0 4025 0 +3147 2127 3279 +3147 2127 3279 +3147 2129 3279 +3145 2131 3279 +3145 2135 3279 +3143 2137 3277 +3143 2143 3277 +3141 2149 3277 +3139 2159 3275 +3135 2169 3273 +3131 2185 3271 +3125 2203 3267 +3117 2227 3263 +3107 2257 3257 +3091 2295 3249 +3071 2341 3237 +3041 2397 3221 +2999 2461 3201 +2937 2535 3171 +2835 2617 3127 +2651 2709 3059 +2145 2809 2953 +0 2915 2751 +0 3027 2137 +0 3143 0 +0 3263 0 +0 3385 0 +0 3511 0 +0 3637 0 +0 3765 0 +0 3895 0 +0 4023 0 +3235 2077 3325 +3235 2079 3325 +3235 2081 3325 +3233 2083 3325 +3233 2087 3325 +3233 2091 3325 +3231 2097 3323 +3229 2103 3323 +3227 2113 3321 +3225 2125 3319 +3221 2141 3317 +3217 2163 3315 +3211 2189 3311 +3201 2221 3305 +3189 2263 3297 +3173 2311 3287 +3151 2369 3273 +3117 2437 3255 +3069 2515 3229 +2995 2601 3189 +2875 2697 3133 +2635 2799 3043 +1442 2907 2885 +0 3021 2519 +0 3137 0 +0 3259 0 +0 3383 0 +0 3509 0 +0 3635 0 +0 3763 0 +0 3893 0 +0 4023 0 +3331 2004 3381 +3331 2005 3381 +3331 2007 3381 +3331 2010 3381 +3329 2014 3381 +3329 2019 3379 +3329 2025 3379 +3327 2033 3379 +3325 2045 3377 +3323 2059 3375 +3321 2077 3373 +3317 2101 3371 +3311 2131 3367 +3305 2169 3363 +3295 2215 3357 +3281 2269 3347 +3263 2333 3335 +3239 2405 3319 +3201 2489 3295 +3149 2579 3263 +3065 2679 3215 +2923 2785 3141 +2613 2895 3019 +0 3011 2777 +0 3131 1508 +0 3253 0 +0 3379 0 +0 3505 0 +0 3633 0 +0 3763 0 +0 3891 0 +0 4023 0 +3435 1880 3445 +3433 1882 3445 +3433 1885 3445 +3433 1889 3445 +3433 1894 3445 +3433 1900 3445 +3431 1908 3443 +3431 1919 3443 +3429 1933 3443 +3427 1952 3441 +3425 1975 3439 +3423 2005 3437 +3419 2042 3435 +3413 2087 3429 +3405 2141 3425 +3395 2203 3417 +3381 2277 3407 +3361 2359 3393 +3335 2449 3373 +3295 2549 3345 +3237 2653 3305 +3143 2765 3245 +2979 2881 3151 +2583 2999 2985 +0 3123 2573 +0 3247 0 +0 3373 0 +0 3501 0 +0 3631 0 +0 3759 0 +0 3891 0 +0 4021 0 +3543 1635 3519 +3543 1639 3519 +3543 1644 3519 +3543 1650 3519 +3543 1658 3519 +3543 1668 3519 +3541 1682 3519 +3541 1700 3517 +3539 1723 3517 +3539 1752 3517 +3537 1788 3515 +3535 1832 3513 +3531 1885 3511 +3527 1947 3507 +3521 2019 3501 +3513 2099 3495 +3503 2189 3487 +3487 2287 3475 +3467 2393 3459 +3437 2503 3435 +3395 2617 3403 +3331 2737 3357 +3231 2859 3285 +3045 2983 3165 +2539 3109 2933 +0 3237 1936 +0 3367 0 +0 3495 0 +0 3627 0 +0 3757 0 +0 3887 0 +0 4019 0 +3657 227 3603 +3657 299 3603 +3657 381 3603 +3657 471 3603 +3657 569 3603 +3657 674 3603 +3657 784 3603 +3655 900 3601 +3655 1019 3601 +3653 1141 3601 +3653 1265 3599 +3651 1392 3597 +3649 1520 3595 +3645 1648 3593 +3641 1778 3589 +3635 1908 3583 +3625 2039 3577 +3615 2171 3567 +3599 2301 3553 +3577 2433 3535 +3547 2565 3509 +3503 2697 3471 +3435 2829 3417 +3327 2961 3331 +3121 3093 3183 +2471 3225 2857 +0 3357 0 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +3775 0 3695 +3775 0 3695 +3775 0 3695 +3775 0 3695 +3775 0 3695 +3775 0 3695 +3775 0 3695 +3775 0 3693 +3773 0 3693 +3773 0 3693 +3771 0 3691 +3771 0 3691 +3769 0 3689 +3765 0 3687 +3763 550 3683 +3757 1360 3679 +3751 1700 3673 +3743 1943 3665 +3731 2143 3655 +3715 2319 3639 +3693 2483 3619 +3661 2637 3591 +3615 2785 3549 +3545 2927 3487 +3429 3069 3387 +3207 3207 3207 +2363 3343 2727 +0 3479 0 +0 3613 0 +0 3747 0 +0 3881 0 +0 4013 0 +3897 0 3795 +3897 0 3795 +3897 0 3795 +3897 0 3795 +3897 0 3795 +3897 0 3795 +3897 0 3795 +3897 0 3793 +3895 0 3793 +3895 0 3793 +3895 0 3793 +3893 0 3791 +3891 0 3789 +3889 0 3787 +3887 0 3785 +3883 0 3781 +3879 0 3777 +3873 1021 3771 +3863 1770 3763 +3851 2103 3751 +3835 2343 3735 +3813 2541 3713 +3779 2717 3681 +3731 2881 3635 +3659 3033 3567 +3537 3181 3453 +3299 3325 3235 +2161 3465 2461 +0 3603 0 +0 3739 0 +0 3875 0 +0 4009 0 +4021 0 3901 +4021 0 3901 +4021 0 3901 +4021 0 3901 +4021 0 3901 +4021 0 3901 +4021 0 3901 +4021 0 3901 +4019 0 3899 +4019 0 3899 +4019 0 3899 +4019 0 3899 +4017 0 3897 +4015 0 3895 +4013 0 3893 +4011 0 3891 +4007 0 3887 +4003 0 3883 +3995 0 3875 +3987 1333 3867 +3975 2044 3855 +3957 2373 3837 +3935 2609 3813 +3901 2807 3779 +3851 2983 3731 +3777 3145 3655 +3651 3299 3527 +3401 3445 3271 +1527 3589 0 +0 3729 0 +0 3867 0 +0 4005 0 +4095 0 4013 +4095 0 4013 +4095 0 4013 +4095 0 4013 +4095 0 4013 +4095 0 4013 +4095 0 4013 +4095 0 4013 +4095 0 4011 +4095 0 4011 +4095 0 4011 +4095 0 4011 +4095 0 4009 +4095 0 4009 +4095 0 4007 +4095 0 4005 +4095 0 4003 +4095 0 3999 +4095 0 3993 +4095 0 3987 +4095 0 3977 +4095 1951 3963 +4083 2409 3947 +4059 2687 3921 +4025 2905 3885 +3975 3093 3833 +3897 3261 3751 +3769 3419 3611 +3509 3569 3317 +0 3715 0 +0 3857 0 +0 3997 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4091 +4095 1786 4079 +4095 2453 4059 +4095 2775 4033 +4095 3009 3997 +4095 3207 3941 +4021 3381 3855 +3891 3543 3705 +3621 3695 3369 +0 3843 0 +0 3985 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 1387 4095 +4095 2507 4095 +4095 2869 4095 +4095 3121 4095 +4095 3325 4055 +4095 3503 3963 +4015 3669 3805 +3737 3823 3433 +0 3971 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 2569 4095 +4095 2971 4095 +4095 3235 4095 +4095 3445 4095 +4095 3629 4077 +4095 3795 3911 +3859 3951 3505 +2825 2377 3239 +2825 2377 3239 +2825 2379 3239 +2823 2379 3239 +2821 2381 3237 +2819 2383 3237 +2817 2387 3237 +2813 2391 3235 +2809 2395 3233 +2803 2403 3231 +2793 2411 3229 +2781 2423 3225 +2763 2437 3221 +2739 2457 3215 +2705 2481 3205 +2657 2513 3193 +2579 2551 3175 +2453 2597 3153 +2193 2653 3119 +0 2719 3069 +0 2793 2993 +0 2879 2865 +0 2971 2607 +0 3071 0 +0 3177 0 +0 3289 0 +0 3405 0 +0 3525 0 +0 3649 0 +0 3775 0 +0 3901 0 +0 4029 0 +2827 2377 3239 +2827 2377 3239 +2825 2379 3239 +2825 2379 3239 +2823 2381 3239 +2821 2383 3237 +2817 2387 3237 +2815 2391 3235 +2809 2395 3235 +2803 2403 3233 +2793 2411 3229 +2781 2423 3225 +2765 2437 3221 +2741 2457 3215 +2707 2481 3205 +2657 2513 3193 +2581 2551 3177 +2453 2597 3153 +2197 2653 3119 +0 2719 3069 +0 2793 2993 +0 2877 2865 +0 2971 2609 +0 3071 0 +0 3177 0 +0 3289 0 +0 3405 0 +0 3525 0 +0 3649 0 +0 3775 0 +0 3901 0 +0 4029 0 +2827 2377 3239 +2827 2377 3239 +2827 2379 3239 +2825 2379 3239 +2823 2381 3239 +2821 2383 3237 +2819 2387 3237 +2815 2391 3235 +2811 2395 3235 +2803 2401 3233 +2795 2411 3229 +2783 2423 3227 +2765 2437 3221 +2743 2457 3215 +2709 2481 3205 +2659 2513 3193 +2583 2551 3177 +2457 2597 3153 +2201 2653 3119 +0 2719 3069 +0 2793 2993 +0 2877 2867 +0 2971 2609 +0 3071 0 +0 3177 0 +0 3289 0 +0 3405 0 +0 3525 0 +0 3649 0 +0 3775 0 +0 3901 0 +0 4029 0 +2829 2377 3241 +2829 2377 3239 +2827 2379 3239 +2827 2379 3239 +2825 2381 3239 +2823 2383 3239 +2821 2387 3237 +2817 2389 3237 +2811 2395 3235 +2805 2401 3233 +2797 2411 3231 +2785 2423 3227 +2767 2437 3221 +2743 2457 3215 +2711 2481 3207 +2661 2513 3193 +2585 2551 3177 +2459 2597 3153 +2207 2653 3119 +0 2719 3069 +0 2793 2993 +0 2877 2867 +0 2971 2611 +0 3071 0 +0 3177 0 +0 3289 0 +0 3405 0 +0 3525 0 +0 3649 0 +0 3775 0 +0 3901 0 +0 4029 0 +2831 2377 3241 +2831 2377 3241 +2829 2377 3241 +2829 2379 3239 +2827 2381 3239 +2825 2383 3239 +2823 2385 3237 +2819 2389 3237 +2813 2395 3235 +2807 2401 3233 +2799 2411 3231 +2787 2421 3227 +2769 2437 3223 +2745 2457 3215 +2713 2481 3207 +2663 2513 3195 +2589 2551 3177 +2463 2597 3153 +2213 2653 3119 +465 2719 3071 +0 2793 2995 +0 2877 2869 +0 2971 2613 +0 3071 0 +0 3177 0 +0 3289 0 +0 3405 0 +0 3525 0 +0 3649 0 +0 3775 0 +0 3901 0 +0 4029 0 +2833 2375 3241 +2833 2377 3241 +2833 2377 3241 +2831 2379 3241 +2829 2381 3241 +2827 2383 3239 +2825 2385 3239 +2821 2389 3237 +2817 2395 3237 +2809 2401 3235 +2801 2411 3231 +2789 2421 3227 +2773 2437 3223 +2749 2457 3217 +2715 2481 3207 +2667 2511 3195 +2593 2551 3179 +2469 2597 3155 +2223 2653 3121 +779 2719 3071 +0 2793 2995 +0 2877 2869 +0 2971 2615 +0 3071 0 +0 3177 0 +0 3289 0 +0 3405 0 +0 3525 0 +0 3649 0 +0 3773 0 +0 3901 0 +0 4029 0 +2837 2375 3243 +2837 2377 3243 +2835 2377 3241 +2835 2379 3241 +2833 2379 3241 +2831 2383 3241 +2829 2385 3239 +2825 2389 3239 +2819 2395 3237 +2813 2401 3235 +2805 2409 3233 +2793 2421 3229 +2777 2437 3223 +2753 2455 3217 +2719 2481 3209 +2671 2511 3197 +2599 2551 3179 +2477 2597 3155 +2237 2653 3123 +1012 2719 3073 +0 2793 2997 +0 2877 2871 +0 2971 2619 +0 3071 435 +0 3177 0 +0 3289 0 +0 3405 0 +0 3525 0 +0 3649 0 +0 3773 0 +0 3901 0 +0 4029 0 +2841 2375 3243 +2841 2375 3243 +2839 2377 3243 +2839 2377 3243 +2837 2379 3243 +2835 2381 3241 +2833 2385 3241 +2829 2389 3239 +2825 2393 3239 +2819 2401 3237 +2809 2409 3233 +2797 2421 3229 +2781 2435 3225 +2759 2455 3219 +2725 2479 3209 +2679 2511 3197 +2605 2549 3181 +2487 2597 3157 +2253 2653 3123 +1206 2719 3075 +0 2793 2999 +0 2877 2875 +0 2971 2625 +0 3071 809 +0 3177 0 +0 3289 0 +0 3405 0 +0 3525 0 +0 3649 0 +0 3773 0 +0 3901 0 +0 4029 0 +2847 2375 3245 +2847 2375 3245 +2845 2375 3245 +2845 2377 3245 +2843 2379 3243 +2841 2381 3243 +2839 2383 3243 +2835 2387 3241 +2831 2393 3239 +2825 2399 3237 +2815 2409 3235 +2803 2419 3231 +2787 2435 3227 +2765 2455 3221 +2733 2479 3211 +2687 2511 3199 +2615 2549 3183 +2499 2597 3159 +2273 2653 3125 +1380 2717 3077 +0 2793 3003 +0 2877 2877 +0 2969 2631 +0 3071 1063 +0 3177 0 +0 3289 0 +0 3405 0 +0 3525 0 +0 3649 0 +0 3773 0 +0 3901 0 +0 4029 0 +2855 2373 3247 +2853 2373 3247 +2853 2375 3247 +2853 2375 3247 +2851 2377 3245 +2849 2379 3245 +2847 2383 3245 +2843 2387 3243 +2839 2391 3241 +2833 2399 3239 +2823 2407 3237 +2813 2419 3233 +2797 2435 3229 +2775 2453 3223 +2743 2479 3213 +2697 2509 3201 +2627 2549 3185 +2515 2595 3161 +2299 2651 3129 +1541 2717 3079 +0 2793 3005 +0 2877 2883 +0 2969 2639 +0 3069 1269 +0 3177 0 +0 3289 0 +0 3405 0 +0 3525 0 +0 3649 0 +0 3773 0 +0 3901 0 +0 4029 0 +2865 2371 3249 +2863 2373 3249 +2863 2373 3249 +2863 2375 3249 +2861 2377 3249 +2859 2379 3249 +2857 2381 3247 +2853 2385 3247 +2849 2391 3245 +2843 2397 3243 +2835 2405 3241 +2823 2417 3237 +2807 2433 3231 +2787 2453 3225 +2755 2477 3217 +2711 2509 3205 +2645 2547 3189 +2535 2595 3165 +2333 2651 3133 +1694 2717 3085 +0 2791 3011 +0 2877 2889 +0 2969 2649 +0 3069 1449 +0 3177 0 +0 3289 0 +0 3405 0 +0 3525 0 +0 3649 0 +0 3773 0 +0 3901 0 +0 4029 0 +2877 2369 3253 +2877 2371 3253 +2877 2371 3253 +2875 2373 3253 +2873 2375 3253 +2873 2377 3251 +2869 2379 3251 +2867 2383 3251 +2863 2389 3249 +2857 2395 3247 +2849 2405 3245 +2837 2415 3241 +2823 2431 3235 +2801 2451 3229 +2773 2475 3221 +2729 2507 3209 +2665 2547 3193 +2563 2593 3169 +2373 2649 3137 +1841 2715 3089 +0 2791 3017 +0 2875 2897 +0 2969 2663 +0 3069 1614 +0 3177 0 +0 3289 0 +0 3405 0 +0 3525 0 +0 3649 0 +0 3773 0 +0 3901 0 +0 4029 0 +2895 2367 3259 +2893 2367 3259 +2893 2369 3259 +2893 2369 3259 +2891 2371 3257 +2889 2373 3257 +2887 2377 3257 +2883 2381 3255 +2879 2385 3253 +2873 2393 3251 +2867 2401 3249 +2855 2413 3245 +2841 2429 3241 +2821 2449 3235 +2793 2473 3227 +2753 2505 3215 +2691 2545 3199 +2595 2591 3175 +2423 2649 3143 +1984 2715 3097 +0 2789 3025 +0 2875 2909 +0 2967 2681 +0 3069 1770 +0 3175 0 +0 3289 0 +0 3405 0 +0 3525 0 +0 3649 0 +0 3773 0 +0 3901 0 +0 4029 0 +2915 2363 3265 +2915 2365 3265 +2915 2365 3265 +2913 2367 3265 +2913 2367 3265 +2911 2371 3263 +2909 2373 3263 +2905 2377 3261 +2901 2383 3261 +2897 2389 3259 +2889 2399 3255 +2879 2411 3253 +2865 2425 3247 +2847 2445 3241 +2819 2471 3233 +2781 2503 3221 +2725 2541 3205 +2637 2589 3183 +2481 2647 3151 +2123 2713 3107 +0 2789 3037 +0 2873 2923 +0 2967 2705 +0 3067 1919 +0 3175 0 +0 3287 0 +0 3405 0 +0 3525 0 +0 3649 0 +0 3773 0 +0 3901 0 +0 4029 0 +2943 2359 3275 +2943 2359 3273 +2943 2361 3273 +2941 2361 3273 +2941 2363 3273 +2939 2365 3273 +2937 2369 3271 +2933 2373 3271 +2931 2377 3269 +2925 2385 3267 +2919 2393 3265 +2909 2405 3261 +2897 2421 3257 +2879 2441 3251 +2853 2467 3243 +2819 2499 3231 +2767 2539 3215 +2685 2587 3193 +2549 2643 3163 +2261 2711 3119 +0 2787 3051 +0 2871 2941 +0 2965 2733 +0 3067 2063 +0 3175 0 +0 3287 0 +0 3405 0 +0 3525 0 +0 3647 0 +0 3773 0 +0 3901 0 +0 4029 0 +2977 2353 3285 +2977 2353 3285 +2977 2353 3285 +2975 2355 3285 +2975 2357 3285 +2973 2359 3283 +2971 2363 3283 +2969 2367 3281 +2965 2371 3281 +2961 2379 3279 +2955 2387 3277 +2945 2401 3273 +2933 2415 3269 +2917 2437 3263 +2895 2461 3255 +2863 2495 3243 +2815 2535 3229 +2745 2583 3207 +2627 2641 3177 +2399 2707 3135 +1461 2785 3069 +0 2869 2965 +0 2963 2769 +0 3065 2203 +0 3173 0 +0 3287 0 +0 3403 0 +0 3525 0 +0 3647 0 +0 3773 0 +0 3901 0 +0 4029 0 +3019 2343 3301 +3019 2343 3299 +3019 2345 3299 +3017 2347 3299 +3017 2347 3299 +3015 2351 3299 +3013 2353 3297 +3011 2357 3297 +3009 2363 3295 +3005 2371 3293 +2999 2379 3291 +2991 2393 3289 +2979 2409 3285 +2965 2429 3279 +2945 2455 3271 +2917 2487 3259 +2875 2529 3245 +2813 2577 3225 +2713 2635 3197 +2533 2703 3155 +2059 2781 3093 +0 2867 2993 +0 2961 2815 +0 3063 2343 +0 3171 0 +0 3285 0 +0 3403 0 +0 3523 0 +0 3647 0 +0 3773 0 +0 3899 0 +0 4029 0 +3071 2331 3319 +3069 2331 3319 +3069 2333 3319 +3069 2335 3319 +3067 2335 3319 +3067 2339 3317 +3065 2341 3317 +3063 2345 3315 +3061 2351 3315 +3057 2359 3313 +3051 2369 3311 +3045 2381 3307 +3035 2397 3303 +3023 2419 3299 +3005 2445 3291 +2979 2479 3281 +2943 2521 3267 +2891 2571 3247 +2807 2629 3219 +2667 2699 3181 +2369 2777 3123 +0 2863 3031 +0 2959 2867 +0 3061 2479 +0 3169 0 +0 3283 0 +0 3401 0 +0 3523 0 +0 3647 0 +0 3773 0 +0 3899 0 +0 4027 0 +3131 2315 3343 +3131 2315 3343 +3129 2317 3343 +3129 2317 3343 +3129 2319 3343 +3127 2321 3341 +3125 2325 3341 +3125 2329 3341 +3121 2335 3339 +3119 2343 3337 +3113 2353 3335 +3107 2367 3333 +3099 2383 3329 +3089 2405 3323 +3073 2433 3317 +3051 2467 3307 +3021 2509 3293 +2977 2561 3275 +2909 2621 3249 +2801 2691 3213 +2599 2769 3159 +1971 2859 3075 +0 2955 2931 +0 3057 2615 +0 3167 0 +0 3281 0 +0 3399 0 +0 3521 0 +0 3645 0 +0 3771 0 +0 3899 0 +0 4027 0 +3201 2291 3373 +3199 2291 3373 +3199 2293 3373 +3199 2295 3373 +3199 2297 3373 +3197 2299 3373 +3197 2303 3371 +3195 2307 3371 +3193 2313 3371 +3189 2321 3369 +3185 2331 3367 +3181 2345 3363 +3173 2363 3361 +3165 2387 3355 +3151 2415 3349 +3133 2451 3339 +3107 2495 3327 +3071 2547 3311 +3019 2609 3287 +2935 2681 3253 +2793 2761 3205 +2489 2851 3129 +0 2949 3003 +0 3053 2749 +0 3163 215 +0 3279 0 +0 3397 0 +0 3519 0 +0 3645 0 +0 3771 0 +0 3899 0 +0 4027 0 +3279 2257 3411 +3279 2259 3411 +3279 2259 3411 +3279 2261 3411 +3277 2263 3411 +3277 2267 3411 +3275 2271 3409 +3275 2275 3409 +3273 2281 3409 +3271 2291 3407 +3267 2301 3405 +3263 2317 3403 +3257 2335 3399 +3249 2359 3395 +3239 2389 3389 +3223 2427 3381 +3203 2473 3369 +3173 2529 3355 +3131 2593 3333 +3069 2667 3303 +2967 2749 3259 +2783 2841 3191 +2277 2941 3085 +0 3047 2883 +0 3159 2269 +0 3275 0 +0 3395 0 +0 3517 0 +0 3643 0 +0 3769 0 +0 3897 0 +0 4027 0 +3367 2209 3457 +3367 2209 3457 +3367 2211 3457 +3367 2213 3457 +3365 2215 3457 +3365 2219 3457 +3365 2223 3457 +3363 2229 3455 +3361 2235 3455 +3361 2245 3453 +3357 2257 3451 +3353 2273 3449 +3349 2295 3447 +3343 2321 3443 +3333 2353 3437 +3321 2395 3429 +3305 2443 3419 +3283 2503 3407 +3249 2571 3387 +3201 2647 3361 +3127 2735 3321 +3007 2829 3265 +2767 2931 3175 +1574 3039 3017 +0 3153 2651 +0 3271 0 +0 3391 0 +0 3515 0 +0 3641 0 +0 3767 0 +0 3895 0 +0 4025 0 +3463 2135 3513 +3463 2135 3513 +3463 2137 3513 +3463 2139 3513 +3463 2143 3513 +3461 2145 3513 +3461 2151 3511 +3461 2157 3511 +3459 2165 3511 +3457 2177 3509 +3455 2191 3507 +3453 2209 3505 +3449 2233 3503 +3443 2263 3499 +3437 2301 3495 +3427 2347 3489 +3413 2401 3479 +3395 2465 3467 +3371 2537 3451 +3333 2621 3427 +3281 2711 3395 +3197 2811 3347 +3055 2917 3273 +2745 3027 3151 +0 3143 2909 +0 3263 1640 +0 3385 0 +0 3511 0 +0 3637 0 +0 3765 0 +0 3895 0 +0 4023 0 +3567 2011 3577 +3567 2012 3577 +3567 2014 3577 +3565 2017 3577 +3565 2021 3577 +3565 2026 3577 +3565 2032 3577 +3563 2040 3577 +3563 2051 3575 +3561 2065 3575 +3561 2083 3573 +3557 2107 3571 +3555 2137 3569 +3551 2173 3567 +3545 2219 3563 +3537 2273 3557 +3527 2335 3549 +3513 2409 3539 +3493 2491 3525 +3467 2581 3505 +3427 2681 3477 +3369 2785 3437 +3275 2897 3377 +3111 3013 3283 +2715 3131 3117 +0 3255 2705 +0 3379 0 +0 3505 0 +0 3633 0 +0 3763 0 +0 3891 0 +0 4023 0 +3675 1765 3653 +3675 1767 3653 +3675 1771 3651 +3675 1776 3651 +3675 1782 3651 +3675 1790 3651 +3675 1801 3651 +3673 1814 3651 +3673 1832 3651 +3671 1855 3649 +3671 1884 3649 +3669 1920 3647 +3667 1964 3645 +3663 2017 3643 +3659 2079 3639 +3653 2151 3633 +3645 2231 3627 +3635 2321 3619 +3619 2419 3607 +3599 2525 3591 +3569 2635 3567 +3527 2749 3535 +3465 2869 3489 +3363 2991 3417 +3177 3115 3297 +2671 3241 3065 +0 3369 2069 +0 3499 0 +0 3627 0 +0 3759 0 +0 3889 0 +0 4021 0 +3789 297 3735 +3789 359 3735 +3789 432 3735 +3789 513 3735 +3789 603 3735 +3789 701 3735 +3789 806 3735 +3789 917 3735 +3787 1032 3733 +3787 1151 3733 +3785 1273 3733 +3785 1398 3731 +3783 1524 3729 +3781 1652 3727 +3777 1781 3725 +3773 1910 3721 +3767 2040 3715 +3759 2171 3709 +3747 2303 3699 +3731 2433 3685 +3709 2565 3667 +3679 2697 3641 +3635 2829 3603 +3567 2961 3549 +3459 3093 3463 +3253 3225 3315 +2603 3357 2989 +0 3489 0 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +3907 0 3827 +3907 0 3827 +3907 0 3827 +3907 0 3827 +3907 0 3827 +3907 0 3827 +3907 0 3827 +3907 0 3827 +3907 0 3827 +3905 0 3825 +3905 0 3825 +3903 0 3823 +3903 0 3823 +3901 0 3821 +3899 0 3819 +3895 682 3815 +3891 1493 3811 +3883 1832 3805 +3875 2075 3797 +3863 2275 3787 +3847 2451 3773 +3825 2615 3751 +3793 2769 3723 +3747 2917 3681 +3677 3059 3619 +3561 3201 3519 +3339 3339 3339 +2495 3475 2859 +0 3611 0 +0 3745 0 +0 3879 0 +0 4013 0 +4029 0 3927 +4029 0 3927 +4029 0 3927 +4029 0 3927 +4029 0 3927 +4029 0 3927 +4029 0 3927 +4029 0 3927 +4029 0 3927 +4027 0 3925 +4027 0 3925 +4027 0 3925 +4025 0 3923 +4023 0 3921 +4021 0 3919 +4019 0 3917 +4015 0 3913 +4011 0 3909 +4005 1152 3903 +3995 1902 3895 +3983 2235 3883 +3967 2475 3867 +3945 2673 3845 +3911 2849 3813 +3863 3013 3767 +3791 3165 3699 +3669 3313 3585 +3433 3457 3367 +2293 3597 2593 +0 3735 0 +0 3871 0 +0 4007 0 +4095 0 4033 +4095 0 4033 +4095 0 4033 +4095 0 4033 +4095 0 4033 +4095 0 4033 +4095 0 4033 +4095 0 4033 +4095 0 4033 +4095 0 4033 +4095 0 4031 +4095 0 4031 +4095 0 4031 +4095 0 4029 +4095 0 4027 +4095 0 4025 +4095 0 4023 +4095 0 4019 +4095 0 4015 +4095 0 4007 +4095 1465 3999 +4095 2177 3987 +4091 2505 3969 +4067 2741 3945 +4033 2939 3913 +3983 3115 3863 +3909 3277 3787 +3783 3431 3659 +3533 3579 3405 +1659 3721 0 +0 3861 0 +0 3999 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 2083 4095 +4095 2541 4079 +4095 2819 4053 +4095 3037 4017 +4095 3225 3965 +4031 3393 3883 +3901 3551 3743 +3641 3703 3449 +0 3847 0 +0 3989 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 1918 4095 +4095 2585 4095 +4095 2907 4095 +4095 3141 4095 +4095 3339 4073 +4095 3513 3987 +4023 3675 3837 +3753 3827 3501 +0 3975 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 1519 4095 +4095 2639 4095 +4095 3001 4095 +4095 3253 4095 +4095 3457 4095 +4095 3635 4095 +4095 3801 3937 +3869 3955 3565 +2957 2509 3371 +2957 2509 3371 +2957 2509 3371 +2955 2511 3371 +2955 2513 3371 +2953 2513 3369 +2951 2515 3369 +2949 2519 3369 +2945 2523 3367 +2941 2527 3365 +2933 2535 3363 +2925 2543 3361 +2913 2555 3357 +2895 2569 3353 +2871 2589 3347 +2837 2613 3337 +2787 2645 3325 +2711 2683 3307 +2583 2731 3283 +2323 2785 3251 +0 2851 3201 +0 2927 3125 +0 3011 2997 +0 3103 2739 +0 3203 0 +0 3309 0 +0 3421 0 +0 3539 0 +0 3659 0 +0 3781 0 +0 3907 0 +0 4033 0 +2959 2509 3371 +2959 2509 3371 +2957 2509 3371 +2957 2511 3371 +2955 2511 3371 +2953 2513 3371 +2951 2515 3369 +2949 2519 3369 +2945 2523 3367 +2941 2527 3367 +2935 2535 3365 +2925 2543 3361 +2913 2555 3357 +2895 2569 3353 +2871 2589 3347 +2839 2613 3337 +2789 2645 3325 +2711 2683 3307 +2585 2729 3285 +2327 2785 3251 +0 2851 3201 +0 2927 3125 +0 3011 2997 +0 3103 2739 +0 3203 0 +0 3309 0 +0 3421 0 +0 3539 0 +0 3659 0 +0 3781 0 +0 3907 0 +0 4033 0 +2959 2509 3371 +2959 2509 3371 +2959 2509 3371 +2957 2511 3371 +2957 2511 3371 +2955 2513 3371 +2953 2515 3369 +2951 2519 3369 +2947 2523 3367 +2941 2527 3367 +2935 2535 3365 +2925 2543 3361 +2913 2555 3357 +2897 2569 3353 +2873 2589 3347 +2839 2613 3337 +2789 2645 3325 +2713 2683 3309 +2587 2729 3285 +2329 2785 3251 +0 2851 3201 +0 2927 3125 +0 3011 2997 +0 3103 2741 +0 3203 0 +0 3309 0 +0 3421 0 +0 3539 0 +0 3659 0 +0 3781 0 +0 3907 0 +0 4033 0 +2961 2509 3373 +2959 2509 3371 +2959 2509 3371 +2959 2511 3371 +2957 2511 3371 +2955 2513 3371 +2953 2515 3369 +2951 2519 3369 +2947 2523 3369 +2943 2527 3367 +2937 2535 3365 +2927 2543 3361 +2915 2555 3359 +2897 2569 3353 +2875 2589 3347 +2841 2613 3337 +2791 2645 3325 +2715 2683 3309 +2589 2729 3285 +2333 2785 3251 +0 2851 3201 +0 2925 3125 +0 3011 2999 +0 3103 2741 +0 3203 0 +0 3309 0 +0 3421 0 +0 3537 0 +0 3659 0 +0 3781 0 +0 3907 0 +0 4033 0 +2961 2509 3373 +2961 2509 3373 +2961 2509 3373 +2959 2511 3371 +2959 2511 3371 +2957 2513 3371 +2955 2515 3371 +2953 2519 3369 +2949 2523 3369 +2945 2527 3367 +2937 2533 3365 +2929 2543 3363 +2917 2555 3359 +2899 2569 3353 +2875 2589 3347 +2843 2613 3339 +2793 2645 3325 +2717 2683 3309 +2591 2729 3285 +2339 2785 3251 +0 2851 3201 +0 2925 3125 +0 3011 2999 +0 3103 2743 +0 3203 0 +0 3309 0 +0 3421 0 +0 3537 0 +0 3659 0 +0 3781 0 +0 3907 0 +0 4033 0 +2963 2507 3373 +2963 2509 3373 +2963 2509 3373 +2961 2511 3373 +2961 2511 3371 +2959 2513 3371 +2957 2515 3371 +2955 2517 3371 +2951 2521 3369 +2947 2527 3367 +2939 2533 3365 +2931 2543 3363 +2919 2555 3359 +2901 2569 3355 +2879 2589 3347 +2845 2613 3339 +2795 2645 3327 +2721 2683 3309 +2595 2729 3285 +2347 2785 3253 +597 2851 3203 +0 2925 3127 +0 3009 3001 +0 3103 2745 +0 3203 0 +0 3309 0 +0 3421 0 +0 3537 0 +0 3659 0 +0 3781 0 +0 3907 0 +0 4033 0 +2967 2507 3373 +2965 2509 3373 +2965 2509 3373 +2965 2509 3373 +2963 2511 3373 +2961 2513 3373 +2959 2515 3371 +2957 2517 3371 +2953 2521 3369 +2949 2527 3369 +2943 2533 3367 +2933 2543 3363 +2921 2553 3359 +2905 2569 3355 +2881 2589 3349 +2847 2613 3339 +2799 2645 3327 +2725 2683 3311 +2601 2729 3287 +2355 2785 3253 +912 2851 3203 +0 2925 3127 +0 3009 3001 +0 3103 2749 +0 3203 0 +0 3309 0 +0 3421 0 +0 3537 0 +0 3659 0 +0 3781 0 +0 3907 0 +0 4033 0 +2969 2507 3375 +2969 2507 3375 +2969 2509 3375 +2967 2509 3373 +2967 2511 3373 +2965 2513 3373 +2963 2515 3373 +2961 2517 3371 +2957 2521 3371 +2953 2527 3369 +2945 2533 3367 +2937 2541 3365 +2925 2553 3361 +2909 2569 3355 +2885 2587 3349 +2853 2613 3341 +2803 2643 3329 +2731 2683 3311 +2609 2729 3287 +2369 2785 3255 +1144 2851 3205 +0 2925 3129 +0 3009 3003 +0 3103 2751 +0 3203 567 +0 3309 0 +0 3421 0 +0 3537 0 +0 3659 0 +0 3781 0 +0 3907 0 +0 4033 0 +2973 2507 3375 +2973 2507 3375 +2973 2507 3375 +2971 2509 3375 +2971 2509 3375 +2969 2511 3375 +2967 2513 3373 +2965 2517 3373 +2961 2521 3371 +2957 2525 3371 +2951 2533 3369 +2941 2541 3365 +2929 2553 3363 +2913 2567 3357 +2891 2587 3351 +2857 2613 3341 +2811 2643 3329 +2737 2681 3313 +2619 2729 3289 +2385 2785 3255 +1339 2851 3207 +0 2925 3131 +0 3009 3007 +0 3103 2757 +0 3203 941 +0 3309 0 +0 3421 0 +0 3537 0 +0 3657 0 +0 3781 0 +0 3907 0 +0 4033 0 +2979 2505 3377 +2979 2507 3377 +2979 2507 3377 +2977 2507 3377 +2977 2509 3377 +2975 2511 3375 +2973 2513 3375 +2971 2515 3375 +2967 2519 3373 +2963 2525 3371 +2957 2531 3369 +2947 2541 3367 +2935 2553 3363 +2919 2567 3359 +2897 2587 3353 +2865 2611 3343 +2819 2643 3331 +2747 2681 3315 +2631 2729 3291 +2405 2785 3257 +1513 2849 3209 +0 2925 3135 +0 3009 3011 +0 3101 2763 +0 3203 1195 +0 3309 0 +0 3421 0 +0 3537 0 +0 3657 0 +0 3781 0 +0 3907 0 +0 4033 0 +2987 2505 3379 +2987 2505 3379 +2987 2505 3379 +2985 2507 3379 +2985 2507 3379 +2983 2509 3379 +2981 2511 3377 +2979 2515 3377 +2975 2519 3375 +2971 2523 3375 +2965 2531 3373 +2955 2539 3369 +2945 2551 3365 +2929 2567 3361 +2907 2585 3355 +2875 2611 3345 +2829 2641 3333 +2759 2681 3317 +2647 2727 3293 +2431 2783 3261 +1674 2849 3213 +0 2925 3137 +0 3009 3015 +0 3101 2771 +0 3201 1401 +0 3309 0 +0 3421 0 +0 3537 0 +0 3657 0 +0 3781 0 +0 3905 0 +0 4033 0 +2997 2503 3383 +2997 2503 3383 +2997 2505 3381 +2995 2505 3381 +2995 2507 3381 +2993 2509 3381 +2991 2511 3381 +2989 2513 3379 +2985 2517 3379 +2981 2523 3377 +2975 2529 3375 +2967 2539 3373 +2955 2549 3369 +2939 2565 3365 +2919 2585 3357 +2887 2609 3349 +2843 2641 3337 +2777 2679 3321 +2667 2727 3297 +2465 2783 3265 +1826 2849 3217 +0 2923 3143 +0 3009 3021 +0 3101 2781 +0 3201 1581 +0 3309 0 +0 3421 0 +0 3537 0 +0 3657 0 +0 3781 0 +0 3905 0 +0 4033 0 +3011 2501 3387 +3009 2501 3385 +3009 2503 3385 +3009 2503 3385 +3007 2505 3385 +3007 2507 3385 +3005 2509 3385 +3001 2511 3383 +2999 2515 3383 +2995 2521 3381 +2989 2527 3379 +2981 2537 3377 +2969 2549 3373 +2955 2563 3369 +2933 2583 3361 +2905 2607 3353 +2861 2639 3341 +2797 2679 3325 +2695 2725 3301 +2505 2781 3269 +1973 2847 3221 +0 2923 3149 +0 3007 3029 +0 3101 2795 +0 3201 1747 +0 3309 0 +0 3421 0 +0 3537 0 +0 3657 0 +0 3781 0 +0 3905 0 +0 4033 0 +3027 2499 3391 +3027 2499 3391 +3025 2499 3391 +3025 2501 3391 +3025 2501 3391 +3023 2503 3389 +3021 2505 3389 +3019 2509 3389 +3015 2513 3387 +3011 2517 3385 +3007 2525 3383 +2999 2533 3381 +2987 2545 3377 +2973 2561 3373 +2953 2581 3367 +2925 2605 3359 +2885 2637 3347 +2823 2677 3331 +2727 2723 3307 +2555 2781 3275 +2115 2847 3229 +0 2923 3157 +0 3007 3041 +0 3099 2813 +0 3201 1902 +0 3307 0 +0 3421 0 +0 3537 0 +0 3657 0 +0 3781 0 +0 3905 0 +0 4033 0 +3049 2495 3397 +3049 2495 3397 +3047 2497 3397 +3047 2497 3397 +3045 2499 3397 +3045 2501 3397 +3043 2503 3395 +3041 2505 3395 +3037 2509 3393 +3033 2515 3393 +3029 2521 3391 +3021 2531 3389 +3011 2543 3385 +2997 2557 3381 +2979 2577 3373 +2953 2603 3365 +2913 2635 3353 +2857 2673 3337 +2769 2721 3315 +2613 2779 3285 +2255 2845 3239 +0 2921 3169 +0 3005 3055 +0 3099 2837 +0 3199 2051 +0 3307 0 +0 3419 0 +0 3537 0 +0 3657 0 +0 3781 0 +0 3905 0 +0 4033 0 +3075 2491 3407 +3075 2491 3407 +3075 2491 3405 +3075 2493 3405 +3073 2493 3405 +3073 2495 3405 +3071 2497 3405 +3069 2501 3403 +3065 2505 3403 +3063 2509 3401 +3057 2517 3399 +3051 2527 3397 +3041 2539 3393 +3029 2553 3389 +3011 2573 3383 +2985 2599 3375 +2951 2631 3363 +2899 2671 3347 +2817 2719 3327 +2681 2775 3295 +2393 2843 3251 +0 2919 3183 +0 3005 3073 +0 3097 2865 +0 3199 2195 +0 3307 0 +0 3419 0 +0 3537 0 +0 3657 0 +0 3779 0 +0 3905 0 +0 4033 0 +3109 2483 3417 +3109 2485 3417 +3109 2485 3417 +3109 2485 3417 +3107 2487 3417 +3107 2489 3417 +3105 2491 3415 +3103 2495 3415 +3101 2499 3415 +3097 2503 3413 +3093 2511 3411 +3087 2521 3409 +3077 2533 3405 +3065 2549 3401 +3049 2569 3395 +3027 2595 3387 +2995 2627 3375 +2947 2667 3361 +2877 2715 3339 +2759 2773 3309 +2531 2839 3267 +1593 2917 3201 +0 3003 3097 +0 3097 2903 +0 3197 2335 +0 3305 0 +0 3419 0 +0 3535 0 +0 3657 0 +0 3779 0 +0 3905 0 +0 4033 0 +3153 2475 3433 +3151 2475 3433 +3151 2477 3433 +3151 2477 3431 +3151 2479 3431 +3149 2481 3431 +3147 2483 3431 +3147 2485 3429 +3143 2489 3429 +3141 2495 3427 +3137 2503 3425 +3131 2511 3423 +3123 2525 3421 +3113 2541 3417 +3097 2561 3411 +3077 2587 3403 +3049 2619 3391 +3007 2661 3377 +2945 2709 3357 +2845 2767 3329 +2665 2835 3287 +2191 2913 3225 +0 2999 3125 +0 3093 2947 +0 3195 2475 +0 3303 0 +0 3417 0 +0 3535 0 +0 3655 0 +0 3779 0 +0 3905 0 +0 4031 0 +3203 2463 3451 +3203 2463 3451 +3203 2463 3451 +3201 2465 3451 +3201 2467 3451 +3201 2469 3451 +3199 2471 3449 +3197 2473 3449 +3195 2477 3449 +3193 2483 3447 +3189 2491 3445 +3183 2501 3443 +3177 2513 3439 +3167 2529 3435 +3155 2551 3431 +3137 2577 3423 +3111 2611 3413 +3075 2653 3399 +3023 2703 3379 +2941 2761 3353 +2801 2831 3313 +2501 2909 3255 +0 2995 3163 +0 3091 2999 +0 3193 2611 +0 3301 0 +0 3415 0 +0 3533 0 +0 3655 0 +0 3779 0 +0 3905 0 +0 4031 0 +3263 2445 3475 +3263 2447 3475 +3263 2447 3475 +3261 2449 3475 +3261 2449 3475 +3261 2451 3475 +3259 2455 3475 +3259 2457 3473 +3257 2461 3473 +3253 2467 3471 +3251 2475 3469 +3247 2485 3467 +3239 2499 3465 +3231 2515 3461 +3221 2537 3455 +3205 2565 3449 +3183 2599 3439 +3153 2641 3425 +3109 2693 3407 +3043 2753 3383 +2933 2823 3345 +2731 2903 3291 +2103 2991 3207 +0 3087 3063 +0 3189 2747 +0 3299 0 +0 3413 0 +0 3531 0 +0 3653 0 +0 3777 0 +0 3903 0 +0 4031 0 +3333 2423 3507 +3333 2423 3507 +3331 2423 3505 +3331 2425 3505 +3331 2427 3505 +3331 2429 3505 +3329 2431 3505 +3329 2435 3505 +3327 2439 3503 +3325 2445 3503 +3321 2453 3501 +3319 2463 3499 +3313 2477 3497 +3305 2495 3493 +3297 2519 3487 +3283 2547 3481 +3265 2583 3473 +3241 2627 3459 +3203 2679 3443 +3151 2741 3419 +3067 2813 3385 +2925 2893 3337 +2621 2983 3261 +0 3081 3135 +0 3185 2881 +0 3295 347 +0 3411 0 +0 3529 0 +0 3651 0 +0 3777 0 +0 3903 0 +0 4031 0 +3411 2389 3545 +3411 2389 3543 +3411 2391 3543 +3411 2391 3543 +3411 2393 3543 +3409 2395 3543 +3409 2399 3543 +3409 2403 3543 +3407 2407 3541 +3405 2413 3541 +3403 2423 3539 +3399 2433 3537 +3395 2449 3535 +3389 2467 3531 +3381 2491 3527 +3371 2521 3521 +3355 2559 3513 +3335 2605 3501 +3305 2661 3487 +3263 2725 3465 +3201 2799 3435 +3099 2883 3391 +2915 2973 3323 +2411 3073 3217 +0 3179 3015 +0 3291 2401 +0 3407 0 +0 3527 0 +0 3649 0 +0 3775 0 +0 3901 0 +0 4029 0 +3499 2341 3591 +3499 2341 3591 +3499 2343 3589 +3499 2343 3589 +3499 2345 3589 +3499 2347 3589 +3497 2351 3589 +3497 2355 3589 +3495 2361 3587 +3495 2367 3587 +3493 2377 3585 +3489 2389 3583 +3485 2405 3581 +3481 2427 3579 +3475 2453 3575 +3467 2485 3569 +3455 2527 3563 +3437 2575 3551 +3415 2635 3539 +3381 2703 3519 +3333 2779 3493 +3259 2867 3453 +3139 2961 3397 +2899 3063 3307 +1706 3171 3149 +0 3285 2783 +0 3403 0 +0 3523 0 +0 3647 0 +0 3773 0 +0 3899 0 +0 4029 0 +3595 2265 3645 +3595 2267 3645 +3595 2267 3645 +3595 2269 3645 +3595 2271 3645 +3595 2275 3645 +3593 2277 3645 +3593 2283 3643 +3593 2289 3643 +3591 2297 3643 +3589 2309 3641 +3587 2323 3639 +3585 2341 3637 +3581 2365 3635 +3575 2395 3631 +3569 2433 3627 +3559 2479 3621 +3545 2533 3611 +3527 2597 3599 +3503 2671 3583 +3467 2753 3559 +3413 2845 3527 +3329 2943 3479 +3187 3049 3405 +2877 3161 3283 +0 3275 3041 +0 3395 1772 +0 3519 0 +0 3643 0 +0 3769 0 +0 3897 0 +0 4027 0 +3699 2141 3711 +3699 2143 3711 +3699 2145 3709 +3699 2147 3709 +3697 2149 3709 +3697 2153 3709 +3697 2157 3709 +3697 2165 3709 +3697 2173 3709 +3695 2183 3707 +3693 2197 3707 +3693 2217 3705 +3689 2239 3703 +3687 2269 3701 +3683 2305 3699 +3677 2351 3695 +3669 2405 3689 +3659 2469 3681 +3645 2541 3671 +3627 2623 3657 +3599 2713 3637 +3559 2813 3609 +3501 2917 3569 +3407 3029 3509 +3243 3145 3415 +2847 3263 3249 +0 3387 2837 +0 3511 0 +0 3637 0 +0 3765 0 +0 3895 0 +0 4025 0 +3807 1895 3785 +3807 1897 3785 +3807 1900 3785 +3807 1903 3785 +3807 1908 3783 +3807 1914 3783 +3807 1922 3783 +3807 1933 3783 +3805 1946 3783 +3805 1964 3783 +3805 1987 3781 +3803 2016 3781 +3801 2051 3779 +3799 2095 3777 +3795 2149 3775 +3791 2211 3771 +3785 2283 3767 +3777 2365 3759 +3767 2453 3751 +3751 2551 3739 +3731 2657 3723 +3701 2767 3701 +3659 2881 3667 +3597 3001 3621 +3495 3123 3549 +3309 3247 3429 +2803 3373 3197 +0 3501 2201 +0 3631 0 +0 3761 0 +0 3891 0 +0 4021 0 +3921 376 3867 +3921 429 3867 +3921 491 3867 +3921 564 3867 +3921 645 3867 +3921 735 3867 +3921 833 3867 +3921 938 3867 +3921 1048 3867 +3919 1164 3865 +3919 1283 3865 +3919 1405 3865 +3917 1530 3863 +3915 1656 3861 +3913 1784 3859 +3909 1913 3857 +3905 2042 3853 +3899 2173 3847 +3891 2303 3841 +3879 2435 3831 +3863 2565 3817 +3841 2697 3799 +3811 2829 3773 +3767 2961 3735 +3699 3093 3681 +3591 3225 3595 +3385 3357 3447 +2735 3489 3121 +0 3621 0 +0 3753 0 +0 3885 0 +0 4017 0 +4041 0 3959 +4041 0 3959 +4041 0 3959 +4039 0 3959 +4039 0 3959 +4039 0 3959 +4039 0 3959 +4039 0 3959 +4039 0 3959 +4039 0 3959 +4037 0 3957 +4037 0 3957 +4037 0 3957 +4035 0 3955 +4033 0 3953 +4031 0 3951 +4027 815 3947 +4023 1625 3943 +4015 1965 3937 +4007 2207 3929 +3995 2407 3919 +3979 2583 3905 +3957 2747 3883 +3925 2901 3855 +3879 3049 3813 +3809 3193 3751 +3693 3333 3651 +3471 3471 3471 +2627 3607 2991 +0 3743 0 +0 3877 0 +0 4011 0 +4095 0 4059 +4095 0 4059 +4095 0 4059 +4095 0 4059 +4095 0 4059 +4095 0 4059 +4095 0 4059 +4095 0 4059 +4095 0 4059 +4095 0 4059 +4095 0 4057 +4095 0 4057 +4095 0 4057 +4095 0 4055 +4095 0 4053 +4095 0 4053 +4095 0 4049 +4095 0 4047 +4095 0 4041 +4095 1285 4035 +4095 2034 4027 +4095 2367 4015 +4095 2607 3999 +4077 2805 3977 +4043 2981 3945 +3995 3145 3899 +3923 3297 3831 +3801 3445 3717 +3565 3589 3499 +2425 3729 2725 +0 3867 0 +0 4003 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 1597 4095 +4095 2309 4095 +4095 2637 4095 +4095 2875 4079 +4095 3071 4045 +4095 3247 3995 +4041 3409 3919 +3915 3563 3791 +3665 3711 3537 +1791 3853 0 +0 3993 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 2215 4095 +4095 2673 4095 +4095 2951 4095 +4095 3169 4095 +4095 3357 4095 +4095 3525 4015 +4033 3683 3877 +3773 3835 3581 +0 3979 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 2051 4095 +4095 2717 4095 +4095 3039 4095 +4095 3275 4095 +4095 3471 4095 +4095 3645 4095 +4095 3807 3969 +3885 3961 3633 +3089 2641 3503 +3089 2641 3503 +3089 2641 3503 +3089 2643 3503 +3087 2643 3503 +3087 2645 3503 +3085 2645 3501 +3083 2649 3501 +3081 2651 3501 +3077 2655 3499 +3071 2659 3497 +3065 2667 3495 +3057 2675 3493 +3043 2687 3489 +3027 2703 3485 +3003 2721 3479 +2969 2747 3469 +2919 2777 3457 +2843 2815 3439 +2715 2863 3415 +2453 2919 3383 +0 2983 3333 +0 3059 3257 +0 3143 3129 +0 3235 2871 +0 3335 0 +0 3441 0 +0 3553 0 +0 3671 0 +0 3791 0 +0 3913 0 +0 4039 0 +3091 2641 3503 +3091 2641 3503 +3089 2641 3503 +3089 2641 3503 +3089 2643 3503 +3087 2645 3503 +3085 2645 3503 +3083 2647 3501 +3081 2651 3501 +3077 2655 3499 +3073 2659 3499 +3065 2667 3497 +3057 2675 3493 +3045 2687 3489 +3027 2701 3485 +3003 2721 3479 +2969 2745 3469 +2919 2777 3457 +2843 2815 3439 +2715 2863 3417 +2455 2919 3383 +0 2983 3333 +0 3059 3257 +0 3143 3129 +0 3235 2871 +0 3335 0 +0 3441 0 +0 3553 0 +0 3671 0 +0 3791 0 +0 3913 0 +0 4039 0 +3091 2641 3503 +3091 2641 3503 +3091 2641 3503 +3089 2641 3503 +3089 2643 3503 +3087 2645 3503 +3087 2645 3503 +3085 2647 3501 +3081 2651 3501 +3077 2655 3499 +3073 2659 3499 +3067 2667 3497 +3057 2675 3493 +3045 2687 3489 +3027 2701 3485 +3005 2721 3479 +2971 2745 3469 +2921 2777 3457 +2843 2815 3441 +2717 2863 3417 +2459 2917 3383 +0 2983 3333 +0 3059 3257 +0 3143 3129 +0 3235 2871 +0 3335 0 +0 3441 0 +0 3553 0 +0 3671 0 +0 3791 0 +0 3913 0 +0 4039 0 +3091 2641 3503 +3091 2641 3503 +3091 2641 3503 +3091 2641 3503 +3089 2643 3503 +3089 2643 3503 +3087 2645 3503 +3085 2647 3501 +3083 2651 3501 +3079 2655 3499 +3073 2659 3499 +3067 2667 3497 +3059 2675 3493 +3045 2687 3491 +3029 2701 3485 +3005 2721 3479 +2971 2745 3469 +2921 2777 3457 +2845 2815 3441 +2719 2863 3417 +2461 2917 3383 +0 2983 3333 +0 3059 3257 +0 3143 3129 +0 3235 2873 +0 3335 0 +0 3441 0 +0 3553 0 +0 3671 0 +0 3791 0 +0 3913 0 +0 4039 0 +3093 2641 3505 +3093 2641 3505 +3091 2641 3503 +3091 2641 3503 +3091 2643 3503 +3089 2643 3503 +3087 2645 3503 +3085 2647 3503 +3083 2651 3501 +3079 2655 3501 +3075 2659 3499 +3069 2667 3497 +3059 2675 3495 +3047 2687 3491 +3031 2701 3485 +3007 2721 3479 +2973 2745 3469 +2923 2777 3457 +2847 2815 3441 +2721 2861 3417 +2465 2917 3383 +0 2983 3333 +0 3059 3257 +0 3143 3131 +0 3235 2873 +0 3335 0 +0 3441 0 +0 3553 0 +0 3671 0 +0 3791 0 +0 3913 0 +0 4039 0 +3095 2639 3505 +3093 2641 3505 +3093 2641 3505 +3093 2641 3505 +3091 2643 3503 +3091 2643 3503 +3089 2645 3503 +3087 2647 3503 +3085 2651 3501 +3081 2655 3501 +3077 2659 3499 +3069 2667 3497 +3061 2675 3495 +3049 2687 3491 +3031 2701 3485 +3007 2721 3479 +2975 2745 3471 +2925 2777 3459 +2849 2815 3441 +2723 2861 3417 +2471 2917 3383 +108 2983 3335 +0 3059 3257 +0 3143 3131 +0 3235 2875 +0 3335 0 +0 3441 0 +0 3553 0 +0 3671 0 +0 3791 0 +0 3913 0 +0 4039 0 +3097 2639 3505 +3095 2641 3505 +3095 2641 3505 +3095 2641 3505 +3093 2643 3505 +3093 2643 3505 +3091 2645 3503 +3089 2647 3503 +3087 2651 3503 +3083 2653 3501 +3079 2659 3499 +3071 2665 3497 +3063 2675 3495 +3051 2687 3491 +3033 2701 3487 +3011 2721 3479 +2977 2745 3471 +2927 2777 3459 +2853 2815 3441 +2727 2861 3417 +2479 2917 3385 +729 2983 3335 +0 3057 3259 +0 3143 3133 +0 3235 2877 +0 3335 0 +0 3441 0 +0 3553 0 +0 3671 0 +0 3791 0 +0 3913 0 +0 4039 0 +3099 2639 3505 +3099 2639 3505 +3097 2641 3505 +3097 2641 3505 +3097 2641 3505 +3095 2643 3505 +3093 2645 3505 +3091 2647 3503 +3089 2649 3503 +3085 2653 3501 +3081 2659 3501 +3075 2665 3499 +3065 2675 3495 +3053 2685 3493 +3037 2701 3487 +3013 2721 3481 +2979 2745 3471 +2931 2777 3459 +2857 2815 3443 +2733 2861 3419 +2487 2917 3385 +1043 2983 3335 +0 3057 3261 +0 3141 3133 +0 3235 2881 +0 3335 0 +0 3441 0 +0 3553 0 +0 3671 0 +0 3791 0 +0 3913 0 +0 4039 0 +3101 2639 3507 +3101 2639 3507 +3101 2639 3507 +3101 2641 3507 +3099 2641 3507 +3099 2643 3505 +3097 2645 3505 +3095 2647 3505 +3093 2649 3503 +3089 2653 3503 +3085 2659 3501 +3077 2665 3499 +3069 2673 3497 +3057 2685 3493 +3041 2701 3489 +3017 2721 3481 +2985 2745 3473 +2937 2775 3461 +2863 2815 3443 +2741 2861 3419 +2501 2917 3387 +1276 2983 3337 +0 3057 3261 +0 3141 3135 +0 3235 2883 +0 3335 699 +0 3441 0 +0 3553 0 +0 3669 0 +0 3791 0 +0 3913 0 +0 4039 0 +3107 2639 3507 +3105 2639 3507 +3105 2639 3507 +3105 2639 3507 +3103 2641 3507 +3103 2641 3507 +3101 2643 3507 +3099 2645 3505 +3097 2649 3505 +3093 2653 3503 +3089 2657 3503 +3083 2665 3501 +3073 2673 3497 +3061 2685 3495 +3045 2701 3489 +3023 2719 3483 +2989 2745 3473 +2943 2775 3461 +2869 2813 3445 +2751 2861 3421 +2517 2917 3387 +1471 2983 3339 +0 3057 3263 +0 3141 3139 +0 3235 2889 +0 3335 1073 +0 3441 0 +0 3553 0 +0 3669 0 +0 3791 0 +0 3913 0 +0 4039 0 +3111 2637 3509 +3111 2637 3509 +3111 2639 3509 +3111 2639 3509 +3109 2639 3509 +3109 2641 3509 +3107 2643 3509 +3105 2645 3507 +3103 2647 3507 +3099 2651 3505 +3095 2657 3505 +3089 2663 3503 +3079 2673 3499 +3069 2685 3495 +3051 2699 3491 +3029 2719 3485 +2997 2743 3475 +2951 2775 3463 +2879 2813 3447 +2763 2861 3423 +2537 2917 3389 +1645 2981 3341 +0 3057 3267 +0 3141 3143 +0 3235 2895 +0 3335 1327 +0 3441 0 +0 3553 0 +0 3669 0 +0 3791 0 +0 3913 0 +0 4039 0 +3119 2637 3511 +3119 2637 3511 +3119 2637 3511 +3119 2637 3511 +3117 2639 3511 +3117 2641 3511 +3115 2641 3511 +3113 2643 3509 +3111 2647 3509 +3107 2651 3507 +3103 2655 3507 +3097 2663 3505 +3087 2671 3501 +3077 2683 3499 +3061 2699 3493 +3039 2717 3487 +3007 2743 3477 +2961 2773 3465 +2893 2813 3449 +2779 2859 3425 +2563 2915 3393 +1806 2981 3345 +0 3057 3271 +0 3141 3147 +0 3233 2903 +0 3335 1533 +0 3441 0 +0 3553 0 +0 3669 0 +0 3789 0 +0 3913 0 +0 4039 0 +3129 2635 3515 +3129 2635 3515 +3129 2635 3515 +3129 2637 3515 +3127 2637 3513 +3127 2639 3513 +3125 2641 3513 +3123 2643 3513 +3121 2645 3511 +3117 2649 3511 +3113 2655 3509 +3107 2661 3507 +3099 2671 3505 +3087 2681 3501 +3071 2697 3497 +3051 2717 3489 +3019 2741 3481 +2975 2773 3469 +2909 2811 3453 +2799 2859 3429 +2597 2915 3397 +1958 2981 3349 +0 3057 3275 +0 3141 3153 +0 3233 2913 +0 3333 1714 +0 3441 0 +0 3553 0 +0 3669 0 +0 3789 0 +0 3913 0 +0 4039 0 +3143 2633 3519 +3143 2633 3519 +3141 2633 3519 +3141 2635 3517 +3141 2635 3517 +3139 2637 3517 +3139 2639 3517 +3137 2641 3517 +3133 2643 3515 +3131 2647 3515 +3127 2653 3513 +3121 2659 3511 +3113 2669 3509 +3101 2681 3505 +3087 2695 3501 +3065 2715 3493 +3037 2741 3485 +2993 2771 3473 +2929 2811 3457 +2827 2857 3433 +2637 2913 3401 +2105 2979 3353 +0 3055 3281 +0 3139 3161 +0 3233 2927 +0 3333 1879 +0 3441 0 +0 3553 0 +0 3669 0 +0 3789 0 +0 3913 0 +0 4037 0 +3159 2631 3523 +3159 2631 3523 +3159 2631 3523 +3159 2631 3523 +3157 2633 3523 +3157 2635 3523 +3155 2635 3521 +3153 2637 3521 +3151 2641 3521 +3149 2645 3519 +3143 2651 3517 +3139 2657 3517 +3131 2665 3513 +3121 2677 3511 +3105 2693 3505 +3085 2713 3499 +3057 2737 3491 +3017 2769 3479 +2955 2809 3463 +2859 2855 3439 +2687 2913 3407 +2249 2979 3361 +0 3055 3289 +0 3139 3173 +0 3233 2945 +0 3333 2034 +0 3439 0 +0 3553 0 +0 3669 0 +0 3789 0 +0 3913 0 +0 4037 0 +3181 2627 3529 +3181 2627 3529 +3181 2627 3529 +3179 2629 3529 +3179 2629 3529 +3179 2631 3529 +3177 2633 3529 +3175 2635 3527 +3173 2637 3527 +3171 2641 3527 +3167 2647 3525 +3161 2653 3523 +3153 2663 3521 +3143 2675 3517 +3129 2689 3513 +3111 2709 3505 +3085 2735 3497 +3047 2767 3485 +2989 2807 3469 +2901 2853 3447 +2745 2911 3417 +2389 2977 3371 +0 3053 3301 +0 3137 3187 +0 3231 2969 +0 3333 2183 +0 3439 0 +0 3551 0 +0 3669 0 +0 3789 0 +0 3913 0 +0 4037 0 +3209 2621 3539 +3207 2623 3539 +3207 2623 3539 +3207 2623 3539 +3207 2625 3537 +3205 2625 3537 +3205 2627 3537 +3203 2629 3537 +3201 2633 3535 +3199 2637 3535 +3195 2643 3533 +3189 2649 3531 +3183 2659 3529 +3173 2671 3525 +3161 2685 3521 +3143 2705 3515 +3117 2731 3507 +3083 2763 3495 +3031 2803 3479 +2949 2851 3459 +2813 2909 3427 +2527 2975 3383 +0 3051 3315 +0 3137 3205 +0 3229 2997 +0 3331 2327 +0 3439 0 +0 3551 0 +0 3669 0 +0 3789 0 +0 3913 0 +0 4037 0 +3243 2615 3549 +3243 2615 3549 +3241 2617 3549 +3241 2617 3549 +3241 2617 3549 +3239 2619 3549 +3239 2621 3549 +3237 2623 3547 +3235 2627 3547 +3233 2631 3547 +3229 2635 3545 +3225 2643 3543 +3219 2653 3541 +3209 2665 3537 +3199 2681 3533 +3181 2701 3527 +3159 2727 3519 +3127 2759 3507 +3079 2799 3493 +3009 2847 3471 +2891 2905 3441 +2663 2971 3399 +1725 3049 3333 +0 3135 3229 +0 3229 3035 +0 3329 2467 +0 3437 0 +0 3551 0 +0 3667 0 +0 3789 0 +0 3911 0 +0 4037 0 +3285 2607 3565 +3285 2607 3565 +3283 2607 3565 +3283 2609 3565 +3283 2609 3565 +3283 2611 3563 +3281 2613 3563 +3279 2615 3563 +3279 2617 3563 +3275 2621 3561 +3273 2627 3559 +3269 2635 3559 +3263 2645 3555 +3255 2657 3553 +3245 2673 3549 +3229 2693 3543 +3209 2719 3535 +3181 2753 3525 +3139 2793 3509 +3077 2841 3489 +2977 2899 3461 +2797 2967 3419 +2323 3045 3357 +0 3131 3257 +0 3225 3079 +0 3327 2607 +0 3435 0 +0 3549 0 +0 3667 0 +0 3787 0 +0 3911 0 +0 4037 0 +3335 2595 3583 +3335 2595 3583 +3335 2595 3583 +3335 2597 3583 +3333 2597 3583 +3333 2599 3583 +3333 2601 3583 +3331 2603 3581 +3329 2605 3581 +3327 2611 3581 +3325 2615 3579 +3321 2623 3577 +3315 2633 3575 +3309 2645 3573 +3299 2661 3567 +3287 2683 3563 +3269 2709 3555 +3243 2743 3545 +3207 2785 3531 +3155 2835 3511 +3073 2893 3485 +2933 2963 3445 +2633 3041 3387 +0 3127 3295 +0 3223 3131 +0 3325 2743 +0 3433 0 +0 3547 0 +0 3665 0 +0 3787 0 +0 3911 0 +0 4037 0 +3395 2577 3607 +3395 2577 3607 +3395 2579 3607 +3395 2579 3607 +3393 2581 3607 +3393 2581 3607 +3393 2583 3607 +3391 2587 3607 +3391 2589 3605 +3389 2593 3605 +3385 2599 3603 +3383 2607 3601 +3379 2617 3599 +3373 2631 3597 +3363 2647 3593 +3353 2669 3587 +3337 2697 3581 +3315 2731 3571 +3285 2773 3559 +3241 2825 3539 +3175 2885 3515 +3067 2955 3477 +2863 3035 3423 +2235 3123 3339 +0 3219 3195 +0 3323 2879 +0 3431 0 +0 3545 0 +0 3665 0 +0 3785 0 +0 3909 0 +0 4035 0 +3465 2555 3639 +3465 2555 3639 +3465 2555 3639 +3465 2557 3639 +3463 2557 3637 +3463 2559 3637 +3463 2561 3637 +3461 2563 3637 +3461 2567 3637 +3459 2571 3635 +3457 2577 3635 +3455 2585 3633 +3451 2597 3631 +3445 2609 3629 +3439 2627 3625 +3429 2651 3619 +3415 2679 3613 +3397 2715 3605 +3373 2759 3591 +3335 2811 3575 +3283 2873 3551 +3199 2945 3517 +3057 3025 3469 +2753 3115 3393 +0 3213 3267 +0 3317 3013 +0 3427 479 +0 3543 0 +0 3661 0 +0 3783 0 +0 3909 0 +0 4035 0 +3543 2521 3677 +3543 2521 3677 +3543 2521 3677 +3543 2523 3675 +3543 2525 3675 +3543 2525 3675 +3541 2527 3675 +3541 2531 3675 +3541 2535 3675 +3539 2539 3673 +3537 2545 3673 +3535 2555 3671 +3531 2565 3669 +3527 2581 3667 +3521 2599 3663 +3513 2623 3659 +3503 2653 3653 +3487 2691 3645 +3467 2737 3633 +3439 2793 3619 +3395 2857 3597 +3333 2931 3567 +3231 3015 3523 +3047 3107 3455 +2543 3205 3349 +0 3311 3147 +0 3423 2533 +0 3539 0 +0 3659 0 +0 3781 0 +0 3907 0 +0 4033 0 +3631 2471 3723 +3631 2473 3723 +3631 2473 3723 +3631 2475 3723 +3631 2475 3721 +3631 2477 3721 +3631 2479 3721 +3629 2483 3721 +3629 2487 3721 +3627 2493 3719 +3627 2499 3719 +3625 2509 3717 +3621 2521 3717 +3619 2537 3713 +3613 2559 3711 +3607 2585 3707 +3599 2617 3701 +3587 2659 3695 +3569 2707 3685 +3547 2767 3671 +3513 2835 3651 +3465 2911 3625 +3393 2999 3585 +3271 3093 3529 +3031 3195 3439 +1838 3303 3281 +0 3417 2915 +0 3535 0 +0 3655 0 +0 3779 0 +0 3905 0 +0 4031 0 +3727 2397 3777 +3727 2397 3777 +3727 2399 3777 +3727 2399 3777 +3727 2401 3777 +3727 2403 3777 +3727 2407 3777 +3725 2411 3777 +3725 2415 3775 +3725 2421 3775 +3723 2429 3775 +3721 2441 3773 +3719 2455 3773 +3717 2475 3771 +3713 2497 3767 +3707 2527 3763 +3701 2565 3759 +3691 2611 3753 +3679 2665 3743 +3659 2729 3731 +3635 2803 3715 +3599 2885 3691 +3545 2977 3659 +3461 3075 3611 +3319 3181 3537 +3009 3293 3415 +0 3409 3173 +0 3527 1904 +0 3651 0 +0 3775 0 +0 3901 0 +0 4029 0 +3831 2273 3843 +3831 2273 3843 +3831 2275 3843 +3831 2277 3843 +3831 2279 3841 +3831 2281 3841 +3829 2285 3841 +3829 2289 3841 +3829 2297 3841 +3829 2305 3841 +3827 2315 3839 +3827 2329 3839 +3825 2349 3837 +3823 2371 3835 +3819 2401 3833 +3815 2437 3831 +3809 2483 3827 +3801 2537 3821 +3791 2601 3813 +3777 2673 3803 +3759 2755 3789 +3731 2847 3769 +3691 2945 3741 +3633 3051 3701 +3539 3161 3641 +3375 3277 3547 +2979 3397 3381 +0 3519 2969 +0 3643 0 +0 3769 0 +0 3897 0 +0 4027 0 +3939 2026 3917 +3939 2027 3917 +3939 2029 3917 +3939 2032 3917 +3939 2035 3917 +3939 2040 3917 +3939 2046 3915 +3939 2055 3915 +3939 2065 3915 +3937 2079 3915 +3937 2097 3915 +3937 2119 3913 +3935 2149 3913 +3933 2185 3911 +3931 2229 3909 +3927 2281 3907 +3923 2343 3903 +3917 2415 3899 +3909 2497 3891 +3899 2587 3883 +3883 2683 3871 +3863 2789 3855 +3833 2899 3833 +3791 3015 3799 +3729 3133 3753 +3627 3255 3681 +3441 3379 3561 +2935 3507 3331 +0 3633 2333 +0 3763 0 +0 3893 0 +0 4023 0 +4055 463 3999 +4055 508 3999 +4053 561 3999 +4053 623 3999 +4053 696 3999 +4053 777 3999 +4053 867 3999 +4053 965 3999 +4053 1070 3999 +4053 1181 3999 +4051 1296 3999 +4051 1415 3997 +4051 1537 3997 +4049 1662 3995 +4047 1788 3993 +4045 1916 3991 +4041 2045 3989 +4037 2175 3985 +4031 2305 3979 +4023 2435 3973 +4011 2567 3963 +3995 2697 3949 +3973 2829 3931 +3943 2961 3905 +3899 3093 3867 +3831 3225 3813 +3723 3357 3727 +3517 3489 3579 +2867 3621 3253 +0 3753 0 +0 3885 0 +0 4017 0 +4095 0 4091 +4095 0 4091 +4095 0 4091 +4095 0 4091 +4095 0 4091 +4095 0 4091 +4095 0 4091 +4095 0 4091 +4095 0 4091 +4095 0 4091 +4095 0 4091 +4095 0 4089 +4095 0 4089 +4095 0 4089 +4095 0 4087 +4095 0 4085 +4095 0 4083 +4095 947 4079 +4095 1757 4075 +4095 2097 4069 +4095 2339 4061 +4095 2539 4051 +4095 2717 4037 +4089 2879 4015 +4057 3033 3987 +4011 3181 3945 +3941 3325 3883 +3825 3465 3783 +3603 3603 3603 +2759 3739 3123 +0 3875 0 +0 4009 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 1417 4095 +4095 2167 4095 +4095 2499 4095 +4095 2739 4095 +4095 2937 4095 +4095 3115 4077 +4095 3277 4033 +4055 3431 3963 +3933 3577 3849 +3697 3721 3631 +2557 3861 2857 +0 3999 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 1729 4095 +4095 2441 4095 +4095 2769 4095 +4095 3007 4095 +4095 3203 4095 +4095 3379 4095 +4095 3541 4051 +4047 3695 3923 +3797 3843 3669 +1924 3985 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 2347 4095 +4095 2805 4095 +4095 3085 4095 +4095 3301 4095 +4095 3489 4095 +4095 3657 4095 +4095 3815 4009 +3905 3967 3713 +3221 2773 3635 +3221 2773 3635 +3221 2773 3635 +3221 2773 3635 +3221 2775 3635 +3219 2775 3635 +3219 2777 3635 +3217 2779 3635 +3215 2781 3633 +3213 2783 3633 +3209 2787 3631 +3203 2793 3629 +3197 2799 3627 +3187 2807 3625 +3175 2819 3621 +3159 2835 3617 +3135 2853 3611 +3101 2879 3601 +3051 2909 3589 +2973 2947 3571 +2845 2995 3547 +2585 3051 3515 +0 3115 3465 +0 3191 3387 +0 3275 3261 +0 3367 3003 +0 3467 0 +0 3573 0 +0 3685 0 +0 3803 0 +0 3923 0 +0 4045 0 +3223 2773 3635 +3223 2773 3635 +3221 2773 3635 +3221 2773 3635 +3221 2775 3635 +3219 2775 3635 +3219 2777 3635 +3217 2777 3635 +3215 2781 3633 +3213 2783 3633 +3209 2787 3631 +3203 2791 3631 +3197 2799 3629 +3189 2807 3625 +3175 2819 3621 +3159 2835 3617 +3135 2853 3611 +3101 2879 3601 +3051 2909 3589 +2975 2947 3571 +2847 2995 3549 +2587 3051 3515 +0 3115 3465 +0 3191 3389 +0 3275 3261 +0 3367 3003 +0 3467 0 +0 3573 0 +0 3685 0 +0 3803 0 +0 3923 0 +0 4045 0 +3223 2773 3635 +3223 2773 3635 +3223 2773 3635 +3221 2773 3635 +3221 2775 3635 +3221 2775 3635 +3219 2777 3635 +3217 2777 3635 +3215 2781 3633 +3213 2783 3633 +3209 2787 3631 +3205 2791 3631 +3197 2799 3629 +3189 2807 3625 +3177 2819 3621 +3159 2835 3617 +3135 2853 3611 +3101 2879 3601 +3051 2909 3589 +2975 2947 3573 +2847 2995 3549 +2587 3051 3515 +0 3115 3465 +0 3191 3389 +0 3275 3261 +0 3367 3003 +0 3467 0 +0 3573 0 +0 3685 0 +0 3803 0 +0 3923 0 +0 4045 0 +3223 2773 3635 +3223 2773 3635 +3223 2773 3635 +3223 2773 3635 +3221 2775 3635 +3221 2775 3635 +3219 2777 3635 +3219 2777 3635 +3217 2781 3633 +3213 2783 3633 +3209 2787 3631 +3205 2791 3631 +3199 2799 3629 +3189 2807 3625 +3177 2819 3623 +3161 2835 3617 +3137 2853 3611 +3103 2879 3601 +3053 2909 3589 +2977 2947 3573 +2849 2995 3549 +2591 3051 3515 +0 3115 3465 +0 3191 3389 +0 3275 3261 +0 3367 3005 +0 3467 0 +0 3573 0 +0 3685 0 +0 3803 0 +0 3923 0 +0 4045 0 +3225 2773 3637 +3223 2773 3637 +3223 2773 3635 +3223 2773 3635 +3223 2773 3635 +3221 2775 3635 +3221 2777 3635 +3219 2777 3635 +3217 2779 3633 +3215 2783 3633 +3211 2787 3633 +3205 2791 3631 +3199 2799 3629 +3191 2807 3625 +3177 2819 3623 +3161 2833 3617 +3137 2853 3611 +3103 2877 3601 +3053 2909 3589 +2977 2947 3573 +2851 2995 3549 +2593 3051 3515 +0 3115 3465 +0 3191 3389 +0 3275 3261 +0 3367 3005 +0 3467 0 +0 3573 0 +0 3685 0 +0 3803 0 +0 3923 0 +0 4045 0 +3225 2771 3637 +3225 2773 3637 +3225 2773 3637 +3225 2773 3637 +3223 2773 3635 +3223 2775 3635 +3221 2775 3635 +3221 2777 3635 +3219 2779 3635 +3215 2783 3633 +3211 2787 3633 +3207 2791 3631 +3201 2799 3629 +3191 2807 3627 +3179 2819 3623 +3163 2833 3617 +3139 2853 3611 +3105 2877 3603 +3055 2909 3589 +2979 2947 3573 +2853 2995 3549 +2597 3049 3515 +0 3115 3465 +0 3191 3389 +0 3275 3263 +0 3367 3007 +0 3467 0 +0 3573 0 +0 3685 0 +0 3803 0 +0 3923 0 +0 4045 0 +3227 2771 3637 +3227 2773 3637 +3225 2773 3637 +3225 2773 3637 +3225 2773 3637 +3225 2775 3637 +3223 2775 3635 +3221 2777 3635 +3219 2779 3635 +3217 2783 3633 +3213 2787 3633 +3209 2791 3631 +3201 2799 3629 +3193 2807 3627 +3181 2819 3623 +3163 2833 3619 +3141 2853 3611 +3107 2877 3603 +3057 2909 3591 +2981 2947 3573 +2855 2993 3549 +2603 3049 3515 +240 3115 3467 +0 3191 3391 +0 3275 3263 +0 3367 3007 +0 3467 0 +0 3573 0 +0 3685 0 +0 3803 0 +0 3923 0 +0 4045 0 +3229 2771 3637 +3229 2771 3637 +3227 2773 3637 +3227 2773 3637 +3227 2773 3637 +3225 2775 3637 +3225 2775 3637 +3223 2777 3635 +3221 2779 3635 +3219 2783 3635 +3215 2787 3633 +3211 2791 3631 +3203 2797 3629 +3195 2807 3627 +3183 2819 3623 +3165 2833 3619 +3143 2853 3611 +3109 2877 3603 +3059 2909 3591 +2985 2947 3573 +2861 2993 3551 +2611 3049 3517 +861 3115 3467 +0 3191 3391 +0 3275 3265 +0 3367 3009 +0 3467 0 +0 3573 0 +0 3685 0 +0 3803 0 +0 3923 0 +0 4045 0 +3231 2771 3639 +3231 2771 3637 +3231 2771 3637 +3229 2773 3637 +3229 2773 3637 +3229 2773 3637 +3227 2775 3637 +3225 2777 3637 +3223 2779 3635 +3221 2781 3635 +3217 2785 3633 +3213 2791 3633 +3207 2797 3631 +3197 2807 3627 +3185 2819 3625 +3169 2833 3619 +3145 2853 3613 +3113 2877 3603 +3063 2909 3591 +2989 2947 3575 +2865 2993 3551 +2619 3049 3517 +1175 3115 3467 +0 3189 3393 +0 3275 3267 +0 3367 3013 +0 3467 0 +0 3573 0 +0 3685 0 +0 3803 0 +0 3923 0 +0 4045 0 +3235 2771 3639 +3233 2771 3639 +3233 2771 3639 +3233 2771 3639 +3233 2773 3639 +3231 2773 3639 +3231 2775 3637 +3229 2777 3637 +3227 2779 3637 +3225 2781 3635 +3221 2785 3635 +3217 2791 3633 +3209 2797 3631 +3201 2807 3629 +3189 2817 3625 +3173 2833 3621 +3149 2853 3613 +3117 2877 3605 +3069 2907 3593 +2995 2947 3575 +2873 2993 3553 +2633 3049 3519 +1408 3115 3469 +0 3189 3393 +0 3273 3269 +0 3367 3015 +0 3467 831 +0 3573 0 +0 3685 0 +0 3803 0 +0 3923 0 +0 4045 0 +3239 2771 3641 +3239 2771 3641 +3237 2771 3639 +3237 2771 3639 +3237 2771 3639 +3237 2773 3639 +3235 2775 3639 +3233 2775 3639 +3231 2777 3637 +3229 2781 3637 +3225 2785 3637 +3221 2789 3635 +3215 2797 3633 +3205 2805 3629 +3193 2817 3627 +3177 2833 3621 +3155 2851 3615 +3123 2877 3607 +3075 2907 3593 +3001 2947 3577 +2883 2993 3553 +2649 3049 3519 +1603 3115 3471 +0 3189 3395 +0 3273 3271 +0 3367 3021 +0 3467 1205 +0 3573 0 +0 3685 0 +0 3803 0 +0 3923 0 +0 4045 0 +3245 2769 3641 +3245 2769 3641 +3243 2769 3641 +3243 2771 3641 +3243 2771 3641 +3241 2773 3641 +3241 2773 3641 +3239 2775 3641 +3237 2777 3639 +3235 2781 3639 +3231 2783 3637 +3227 2789 3637 +3221 2795 3635 +3211 2805 3631 +3201 2817 3627 +3185 2831 3623 +3161 2851 3617 +3129 2875 3607 +3083 2907 3595 +3011 2945 3579 +2895 2993 3555 +2669 3049 3523 +1777 3115 3473 +0 3189 3399 +0 3273 3275 +0 3367 3027 +0 3467 1459 +0 3573 0 +0 3685 0 +0 3801 0 +0 3923 0 +0 4045 0 +3251 2769 3643 +3251 2769 3643 +3251 2769 3643 +3251 2769 3643 +3251 2771 3643 +3249 2771 3643 +3249 2773 3643 +3247 2773 3643 +3245 2777 3641 +3243 2779 3641 +3239 2783 3639 +3235 2789 3639 +3229 2795 3637 +3221 2803 3633 +3209 2815 3631 +3193 2831 3625 +3171 2851 3619 +3139 2875 3611 +3093 2907 3597 +3025 2945 3581 +2911 2991 3557 +2695 3047 3525 +1938 3113 3477 +0 3189 3403 +0 3273 3279 +0 3365 3035 +0 3467 1665 +0 3573 0 +0 3685 0 +0 3801 0 +0 3923 0 +0 4045 0 +3261 2767 3647 +3261 2767 3647 +3261 2767 3647 +3261 2767 3647 +3261 2769 3647 +3259 2769 3645 +3259 2771 3645 +3257 2773 3645 +3255 2775 3645 +3253 2777 3643 +3249 2781 3643 +3245 2787 3641 +3239 2793 3639 +3231 2803 3637 +3219 2815 3633 +3205 2829 3629 +3183 2849 3621 +3151 2873 3613 +3107 2905 3601 +3041 2943 3585 +2933 2991 3561 +2729 3047 3529 +2091 3113 3481 +0 3189 3407 +0 3273 3285 +0 3365 3045 +0 3465 1846 +0 3573 0 +0 3685 0 +0 3801 0 +0 3921 0 +0 4045 0 +3275 2765 3651 +3275 2765 3651 +3275 2765 3651 +3273 2765 3651 +3273 2767 3649 +3273 2767 3649 +3271 2769 3649 +3271 2771 3649 +3269 2773 3649 +3267 2775 3647 +3263 2779 3647 +3259 2785 3645 +3253 2791 3643 +3245 2801 3641 +3233 2813 3637 +3219 2827 3633 +3197 2847 3625 +3169 2873 3617 +3125 2903 3605 +3061 2943 3589 +2959 2989 3565 +2769 3047 3533 +2237 3111 3485 +0 3187 3413 +0 3271 3293 +0 3365 3059 +0 3465 2011 +0 3573 0 +0 3685 0 +0 3801 0 +0 3921 0 +0 4045 0 +3291 2763 3655 +3291 2763 3655 +3291 2763 3655 +3291 2763 3655 +3291 2763 3655 +3289 2765 3655 +3289 2767 3655 +3287 2767 3653 +3285 2771 3653 +3283 2773 3653 +3281 2777 3651 +3275 2783 3651 +3271 2789 3649 +3263 2799 3645 +3253 2809 3643 +3237 2825 3637 +3217 2845 3631 +3189 2871 3623 +3149 2901 3611 +3089 2941 3595 +2991 2989 3571 +2819 3045 3539 +2381 3111 3493 +0 3187 3421 +0 3271 3305 +0 3365 3077 +0 3465 2167 +0 3571 0 +0 3685 0 +0 3801 0 +0 3921 0 +0 4045 0 +3313 2759 3663 +3313 2759 3661 +3313 2759 3661 +3313 2759 3661 +3311 2761 3661 +3311 2761 3661 +3311 2763 3661 +3309 2765 3661 +3307 2767 3659 +3305 2769 3659 +3303 2773 3659 +3299 2779 3657 +3293 2785 3655 +3285 2795 3653 +3275 2807 3649 +3261 2823 3645 +3243 2841 3639 +3217 2867 3629 +3179 2899 3619 +3121 2939 3603 +3033 2985 3579 +2877 3043 3549 +2521 3109 3503 +0 3185 3433 +0 3269 3319 +0 3363 3101 +0 3465 2315 +0 3571 0 +0 3683 0 +0 3801 0 +0 3921 0 +0 4045 0 +3341 2753 3671 +3341 2753 3671 +3341 2755 3671 +3339 2755 3671 +3339 2755 3671 +3339 2757 3671 +3337 2757 3669 +3337 2759 3669 +3335 2761 3669 +3333 2765 3667 +3331 2769 3667 +3327 2775 3665 +3321 2781 3663 +3315 2791 3661 +3305 2803 3657 +3293 2817 3653 +3275 2837 3647 +3249 2863 3639 +3215 2895 3627 +3163 2935 3613 +3081 2983 3591 +2945 3041 3559 +2659 3107 3515 +0 3183 3447 +0 3269 3337 +0 3363 3131 +0 3463 2459 +0 3571 0 +0 3683 0 +0 3801 0 +0 3921 0 +0 4045 0 +3375 2747 3683 +3375 2747 3683 +3375 2747 3681 +3373 2749 3681 +3373 2749 3681 +3373 2751 3681 +3373 2751 3681 +3371 2753 3681 +3369 2755 3681 +3367 2759 3679 +3365 2763 3679 +3361 2767 3677 +3357 2775 3675 +3351 2785 3673 +3341 2797 3669 +3331 2813 3665 +3313 2833 3659 +3291 2859 3651 +3259 2891 3641 +3213 2931 3625 +3141 2979 3603 +3023 3037 3573 +2795 3103 3531 +1857 3181 3465 +0 3267 3361 +0 3361 3167 +0 3461 2601 +0 3569 0 +0 3683 0 +0 3799 0 +0 3921 0 +0 4043 0 +3417 2739 3697 +3417 2739 3697 +3417 2739 3697 +3415 2739 3697 +3415 2741 3697 +3415 2741 3697 +3415 2743 3695 +3413 2745 3695 +3413 2747 3695 +3411 2749 3695 +3407 2753 3693 +3405 2759 3691 +3401 2767 3691 +3395 2777 3687 +3387 2789 3685 +3377 2805 3681 +3361 2825 3675 +3341 2851 3667 +3313 2885 3657 +3271 2925 3641 +3209 2973 3621 +3109 3033 3593 +2929 3099 3551 +2455 3177 3489 +0 3263 3389 +0 3359 3211 +0 3459 2739 +0 3569 0 +0 3681 0 +0 3799 0 +0 3919 0 +0 4043 0 +3467 2727 3715 +3467 2727 3715 +3467 2727 3715 +3467 2727 3715 +3467 2729 3715 +3465 2729 3715 +3465 2731 3715 +3465 2733 3715 +3463 2735 3713 +3461 2737 3713 +3459 2743 3713 +3457 2747 3711 +3453 2755 3709 +3447 2765 3707 +3441 2777 3705 +3431 2795 3701 +3419 2815 3695 +3401 2841 3687 +3375 2875 3677 +3339 2917 3663 +3287 2967 3643 +3205 3025 3617 +3065 3095 3577 +2765 3173 3519 +0 3259 3427 +0 3355 3265 +0 3457 2875 +0 3567 0 +0 3679 0 +0 3797 0 +0 3919 0 +0 4043 0 +3527 2709 3741 +3527 2709 3741 +3527 2711 3739 +3527 2711 3739 +3527 2711 3739 +3527 2713 3739 +3525 2713 3739 +3525 2715 3739 +3523 2719 3739 +3523 2721 3737 +3521 2727 3737 +3519 2731 3735 +3515 2739 3735 +3511 2749 3731 +3505 2763 3729 +3497 2779 3725 +3485 2801 3719 +3469 2829 3713 +3447 2863 3703 +3417 2905 3691 +3373 2957 3671 +3307 3017 3647 +3199 3087 3609 +2997 3167 3555 +2367 3255 3471 +0 3351 3327 +0 3455 3011 +0 3563 0 +0 3677 0 +0 3797 0 +0 3917 0 +0 4041 0 +3597 2685 3771 +3597 2687 3771 +3597 2687 3771 +3597 2687 3771 +3597 2689 3771 +3595 2689 3771 +3595 2691 3769 +3595 2693 3769 +3593 2695 3769 +3593 2699 3769 +3591 2703 3767 +3589 2709 3767 +3587 2717 3765 +3583 2729 3763 +3577 2741 3761 +3571 2759 3757 +3561 2783 3751 +3547 2811 3745 +3529 2847 3737 +3505 2891 3725 +3469 2943 3707 +3415 3005 3683 +3331 3077 3649 +3191 3157 3601 +2885 3247 3525 +0 3345 3399 +0 3449 3145 +0 3559 611 +0 3675 0 +0 3795 0 +0 3917 0 +0 4041 0 +3675 2653 3809 +3675 2653 3809 +3675 2653 3809 +3675 2655 3809 +3675 2655 3809 +3675 2657 3807 +3675 2657 3807 +3675 2659 3807 +3673 2663 3807 +3673 2667 3807 +3671 2671 3805 +3669 2677 3805 +3667 2687 3803 +3663 2697 3801 +3659 2713 3799 +3653 2731 3795 +3645 2755 3791 +3635 2785 3785 +3621 2823 3777 +3599 2869 3765 +3571 2925 3751 +3529 2989 3729 +3465 3063 3699 +3363 3147 3655 +3179 3239 3589 +2675 3337 3481 +0 3443 3281 +0 3555 2665 +0 3671 0 +0 3791 0 +0 3913 0 +0 4039 0 +3763 2603 3855 +3763 2605 3855 +3763 2605 3855 +3763 2605 3855 +3763 2607 3855 +3763 2607 3855 +3763 2609 3853 +3763 2611 3853 +3761 2615 3853 +3761 2619 3853 +3759 2625 3853 +3759 2631 3851 +3757 2641 3849 +3753 2653 3849 +3751 2671 3847 +3745 2691 3843 +3739 2717 3839 +3731 2751 3833 +3719 2791 3827 +3701 2839 3817 +3679 2899 3803 +3645 2967 3783 +3597 3043 3757 +3525 3131 3719 +3403 3225 3661 +3163 3327 3571 +1971 3435 3413 +0 3549 3047 +0 3667 0 +0 3787 0 +0 3911 0 +0 4037 0 +3859 2529 3909 +3859 2529 3909 +3859 2531 3909 +3859 2531 3909 +3859 2533 3909 +3859 2533 3909 +3859 2535 3909 +3859 2539 3909 +3859 2543 3909 +3857 2547 3909 +3857 2553 3907 +3855 2561 3907 +3853 2573 3905 +3851 2587 3905 +3849 2607 3903 +3845 2629 3899 +3839 2659 3897 +3833 2697 3891 +3823 2743 3885 +3811 2797 3875 +3793 2861 3863 +3767 2935 3847 +3731 3017 3825 +3677 3109 3791 +3593 3207 3743 +3451 3313 3669 +3141 3425 3547 +0 3541 3305 +0 3659 2036 +0 3783 0 +0 3907 0 +0 4033 0 +3963 2405 3975 +3963 2405 3975 +3963 2407 3975 +3963 2407 3975 +3963 2409 3975 +3963 2411 3975 +3963 2413 3973 +3961 2417 3973 +3961 2423 3973 +3961 2429 3973 +3961 2437 3973 +3959 2447 3971 +3959 2461 3971 +3957 2481 3969 +3955 2503 3967 +3951 2533 3965 +3947 2571 3963 +3941 2615 3959 +3935 2669 3953 +3923 2733 3945 +3909 2805 3935 +3891 2887 3921 +3863 2979 3901 +3823 3077 3873 +3765 3183 3833 +3671 3293 3773 +3507 3409 3679 +3111 3529 3513 +0 3651 3101 +0 3775 0 +0 3901 0 +0 4029 0 +4073 2157 4049 +4073 2157 4049 +4071 2159 4049 +4071 2161 4049 +4071 2163 4049 +4071 2167 4049 +4071 2173 4049 +4071 2179 4049 +4071 2187 4047 +4071 2197 4047 +4071 2211 4047 +4069 2229 4047 +4069 2251 4045 +4067 2281 4045 +4065 2317 4043 +4063 2361 4041 +4059 2413 4039 +4055 2475 4035 +4049 2547 4031 +4041 2629 4025 +4031 2719 4015 +4015 2815 4003 +3995 2921 3987 +3967 3031 3965 +3923 3147 3931 +3861 3265 3885 +3759 3387 3813 +3573 3511 3693 +3067 3639 3463 +0 3765 2465 +0 3895 0 +0 4025 0 +4095 559 4095 +4095 596 4095 +4095 640 4095 +4095 693 4095 +4095 756 4095 +4095 828 4095 +4095 909 4095 +4095 999 4095 +4095 1097 4095 +4095 1202 4095 +4095 1313 4095 +4095 1428 4095 +4095 1547 4095 +4095 1669 4095 +4095 1794 4095 +4095 1920 4095 +4095 2049 4095 +4095 2177 4095 +4095 2307 4095 +4095 2437 4095 +4095 2567 4095 +4095 2699 4095 +4095 2831 4081 +4095 2961 4063 +4075 3093 4037 +4031 3225 4001 +3963 3357 3945 +3855 3489 3859 +3649 3621 3711 +3001 3753 3385 +0 3885 0 +0 4017 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 1079 4095 +4095 1889 4095 +4095 2229 4095 +4095 2471 4095 +4095 2671 4095 +4095 2849 4095 +4095 3011 4095 +4095 3165 4095 +4095 3313 4077 +4073 3457 4015 +3957 3597 3915 +3735 3735 3735 +2891 3871 3255 +0 4007 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 1549 4095 +4095 2299 4095 +4095 2631 4095 +4095 2871 4095 +4095 3069 4095 +4095 3247 4095 +4095 3409 4095 +4095 3563 4095 +4067 3709 3981 +3829 3853 3765 +2689 3993 2989 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 1862 4095 +4095 2573 4095 +4095 2901 4095 +4095 3139 4095 +4095 3337 4095 +4095 3511 4095 +4095 3673 4095 +4095 3827 4057 +3929 3975 3801 +3355 2905 3767 +3353 2905 3767 +3353 2905 3767 +3353 2905 3767 +3353 2905 3767 +3353 2907 3767 +3351 2907 3767 +3351 2909 3767 +3349 2911 3767 +3347 2913 3765 +3345 2915 3765 +3341 2919 3763 +3335 2925 3763 +3329 2931 3761 +3319 2939 3757 +3307 2951 3753 +3291 2967 3749 +3267 2985 3743 +3233 3011 3733 +3183 3041 3721 +3105 3079 3703 +2977 3127 3681 +2715 3183 3647 +0 3247 3597 +0 3323 3521 +0 3407 3393 +0 3499 3135 +0 3599 0 +0 3705 0 +0 3817 0 +0 3935 0 +0 4055 0 +3355 2905 3767 +3355 2905 3767 +3353 2905 3767 +3353 2905 3767 +3353 2905 3767 +3353 2907 3767 +3351 2907 3767 +3351 2909 3767 +3349 2911 3767 +3347 2913 3765 +3345 2915 3765 +3341 2919 3763 +3335 2925 3763 +3329 2931 3761 +3321 2939 3757 +3307 2951 3753 +3291 2967 3749 +3267 2985 3743 +3233 3011 3733 +3183 3041 3721 +3105 3079 3703 +2977 3127 3681 +2717 3183 3647 +0 3247 3597 +0 3323 3521 +0 3407 3393 +0 3499 3135 +0 3599 0 +0 3705 0 +0 3817 0 +0 3935 0 +0 4055 0 +3355 2905 3767 +3355 2905 3767 +3355 2905 3767 +3353 2905 3767 +3353 2905 3767 +3353 2907 3767 +3351 2907 3767 +3351 2909 3767 +3349 2911 3767 +3347 2913 3765 +3345 2915 3765 +3341 2919 3763 +3337 2925 3763 +3329 2931 3761 +3321 2939 3757 +3309 2951 3753 +3291 2967 3749 +3267 2985 3743 +3233 3011 3733 +3183 3041 3721 +3107 3079 3705 +2979 3127 3681 +2719 3183 3647 +0 3247 3597 +0 3323 3521 +0 3407 3393 +0 3499 3135 +0 3599 0 +0 3705 0 +0 3817 0 +0 3935 0 +0 4055 0 +3355 2905 3767 +3355 2905 3767 +3355 2905 3767 +3355 2905 3767 +3353 2905 3767 +3353 2907 3767 +3353 2907 3767 +3351 2909 3767 +3349 2911 3767 +3347 2913 3765 +3345 2915 3765 +3341 2919 3763 +3337 2925 3763 +3329 2931 3761 +3321 2939 3757 +3309 2951 3753 +3291 2967 3749 +3267 2985 3743 +3233 3011 3733 +3183 3041 3721 +3107 3079 3705 +2979 3127 3681 +2721 3183 3647 +0 3247 3597 +0 3323 3521 +0 3407 3393 +0 3499 3135 +0 3599 0 +0 3705 0 +0 3817 0 +0 3935 0 +0 4055 0 +3355 2905 3769 +3355 2905 3769 +3355 2905 3769 +3355 2905 3767 +3355 2905 3767 +3353 2907 3767 +3353 2907 3767 +3351 2909 3767 +3351 2909 3767 +3349 2913 3765 +3345 2915 3765 +3343 2919 3763 +3337 2923 3763 +3331 2931 3761 +3321 2939 3757 +3309 2951 3755 +3293 2967 3749 +3269 2985 3743 +3235 3011 3733 +3185 3041 3721 +3109 3079 3705 +2981 3127 3681 +2723 3183 3647 +0 3247 3597 +0 3323 3521 +0 3407 3393 +0 3499 3137 +0 3599 0 +0 3705 0 +0 3817 0 +0 3935 0 +0 4055 0 +3357 2903 3769 +3357 2905 3769 +3355 2905 3769 +3355 2905 3769 +3355 2905 3767 +3355 2907 3767 +3353 2907 3767 +3353 2909 3767 +3351 2909 3767 +3349 2913 3767 +3347 2915 3765 +3343 2919 3765 +3337 2923 3763 +3331 2931 3761 +3323 2939 3757 +3311 2951 3755 +3293 2967 3749 +3269 2985 3743 +3235 3011 3733 +3185 3041 3721 +3109 3079 3705 +2983 3127 3681 +2725 3183 3647 +0 3247 3597 +0 3323 3521 +0 3407 3393 +0 3499 3137 +0 3599 0 +0 3705 0 +0 3817 0 +0 3935 0 +0 4055 0 +3357 2903 3769 +3357 2905 3769 +3357 2905 3769 +3357 2905 3769 +3357 2905 3769 +3355 2905 3769 +3355 2907 3767 +3353 2909 3767 +3353 2909 3767 +3351 2911 3767 +3347 2915 3765 +3343 2919 3765 +3339 2923 3763 +3333 2931 3761 +3323 2939 3759 +3311 2951 3755 +3295 2965 3749 +3271 2985 3743 +3237 3009 3735 +3187 3041 3721 +3111 3079 3705 +2985 3127 3681 +2729 3183 3647 +0 3247 3597 +0 3323 3521 +0 3407 3395 +0 3499 3139 +0 3599 0 +0 3705 0 +0 3817 0 +0 3935 0 +0 4055 0 +3359 2903 3769 +3359 2903 3769 +3359 2905 3769 +3359 2905 3769 +3357 2905 3769 +3357 2905 3769 +3357 2907 3769 +3355 2907 3767 +3353 2909 3767 +3351 2911 3767 +3349 2915 3765 +3345 2919 3765 +3341 2923 3763 +3333 2931 3761 +3325 2939 3759 +3313 2951 3755 +3295 2965 3751 +3273 2985 3743 +3239 3009 3735 +3189 3041 3723 +3113 3079 3705 +2987 3127 3681 +2735 3181 3647 +372 3247 3599 +0 3323 3523 +0 3407 3395 +0 3499 3139 +0 3599 0 +0 3705 0 +0 3817 0 +0 3935 0 +0 4055 0 +3361 2903 3769 +3361 2903 3769 +3361 2903 3769 +3359 2905 3769 +3359 2905 3769 +3359 2905 3769 +3359 2907 3769 +3357 2907 3769 +3355 2909 3767 +3353 2911 3767 +3351 2915 3767 +3347 2919 3765 +3343 2923 3763 +3335 2931 3761 +3327 2939 3759 +3315 2951 3755 +3297 2965 3751 +3275 2985 3745 +3241 3009 3735 +3193 3041 3723 +3117 3079 3705 +2993 3125 3683 +2743 3181 3649 +994 3247 3599 +0 3323 3523 +0 3407 3397 +0 3499 3141 +0 3599 0 +0 3705 0 +0 3817 0 +0 3935 0 +0 4055 0 +3363 2903 3771 +3363 2903 3771 +3363 2903 3771 +3363 2903 3769 +3361 2905 3769 +3361 2905 3769 +3361 2907 3769 +3359 2907 3769 +3357 2909 3769 +3357 2911 3767 +3353 2915 3767 +3349 2917 3767 +3345 2923 3765 +3339 2929 3763 +3329 2939 3759 +3317 2951 3757 +3301 2965 3751 +3277 2985 3745 +3245 3009 3735 +3195 3041 3723 +3121 3079 3707 +2997 3125 3683 +2753 3181 3649 +1308 3247 3599 +0 3323 3525 +0 3407 3399 +0 3499 3145 +0 3599 0 +0 3705 0 +0 3817 0 +0 3935 0 +0 4055 0 +3367 2903 3771 +3367 2903 3771 +3367 2903 3771 +3365 2903 3771 +3365 2903 3771 +3365 2905 3771 +3363 2905 3771 +3363 2907 3769 +3361 2909 3769 +3359 2911 3769 +3357 2913 3769 +3353 2917 3767 +3349 2923 3765 +3341 2929 3763 +3333 2939 3761 +3321 2949 3757 +3305 2965 3753 +3281 2985 3745 +3249 3009 3737 +3201 3041 3725 +3127 3079 3707 +3005 3125 3685 +2765 3181 3651 +1540 3247 3601 +0 3321 3525 +0 3407 3401 +0 3499 3147 +0 3599 963 +0 3705 0 +0 3817 0 +0 3935 0 +0 4055 0 +3371 2901 3773 +3371 2903 3773 +3371 2903 3773 +3371 2903 3773 +3369 2903 3771 +3369 2905 3771 +3369 2905 3771 +3367 2907 3771 +3365 2907 3771 +3363 2911 3771 +3361 2913 3769 +3357 2917 3769 +3353 2921 3767 +3347 2929 3765 +3337 2937 3763 +3325 2949 3759 +3309 2965 3753 +3287 2983 3747 +3255 3009 3739 +3207 3039 3725 +3135 3079 3709 +3015 3125 3685 +2781 3181 3653 +1735 3247 3603 +0 3321 3527 +0 3405 3403 +0 3499 3153 +0 3599 1337 +0 3705 0 +0 3817 0 +0 3935 0 +0 4055 0 +3377 2901 3773 +3377 2901 3773 +3377 2901 3773 +3375 2903 3773 +3375 2903 3773 +3375 2903 3773 +3375 2905 3773 +3373 2905 3773 +3371 2907 3773 +3369 2909 3771 +3367 2913 3771 +3363 2917 3769 +3359 2921 3769 +3353 2927 3767 +3345 2937 3763 +3333 2949 3761 +3317 2963 3755 +3293 2983 3749 +3261 3007 3739 +3215 3039 3727 +3143 3077 3711 +3027 3125 3687 +2801 3181 3655 +1909 3247 3605 +0 3321 3531 +0 3405 3407 +0 3499 3159 +0 3599 1591 +0 3705 0 +0 3817 0 +0 3935 0 +0 4055 0 +3385 2901 3777 +3385 2901 3775 +3383 2901 3775 +3383 2901 3775 +3383 2901 3775 +3383 2903 3775 +3381 2903 3775 +3381 2905 3775 +3379 2905 3775 +3377 2909 3773 +3375 2911 3773 +3371 2915 3771 +3367 2921 3771 +3361 2927 3769 +3353 2935 3765 +3341 2947 3763 +3325 2963 3757 +3303 2983 3751 +3271 3007 3743 +3225 3039 3731 +3157 3077 3713 +3043 3123 3691 +2827 3181 3657 +2071 3245 3609 +0 3321 3535 +0 3405 3411 +0 3499 3167 +0 3599 1797 +0 3705 0 +0 3817 0 +0 3933 0 +0 4055 0 +3395 2899 3779 +3393 2899 3779 +3393 2899 3779 +3393 2899 3779 +3393 2901 3779 +3393 2901 3779 +3391 2901 3779 +3391 2903 3777 +3389 2905 3777 +3387 2907 3777 +3385 2909 3775 +3381 2913 3775 +3377 2919 3773 +3371 2925 3771 +3363 2935 3769 +3351 2947 3765 +3337 2961 3761 +3315 2981 3755 +3285 3005 3745 +3239 3037 3733 +3173 3075 3717 +3065 3123 3693 +2861 3179 3661 +2223 3245 3613 +0 3321 3539 +0 3405 3417 +0 3497 3177 +0 3599 1978 +0 3705 0 +0 3817 0 +0 3933 0 +0 4055 0 +3407 2897 3783 +3407 2897 3783 +3407 2897 3783 +3407 2897 3783 +3407 2899 3783 +3405 2899 3783 +3405 2899 3781 +3403 2901 3781 +3403 2903 3781 +3401 2905 3781 +3399 2907 3779 +3395 2911 3779 +3391 2917 3777 +3385 2923 3775 +3377 2933 3773 +3365 2945 3769 +3351 2959 3765 +3331 2979 3757 +3301 3005 3749 +3257 3035 3737 +3193 3075 3721 +3091 3121 3699 +2901 3179 3665 +2369 3245 3617 +0 3319 3545 +0 3405 3425 +0 3497 3191 +0 3597 2143 +0 3705 0 +0 3817 0 +0 3933 0 +0 4053 0 +3423 2893 3787 +3423 2895 3787 +3423 2895 3787 +3423 2895 3787 +3423 2895 3787 +3423 2897 3787 +3421 2897 3787 +3421 2899 3787 +3419 2899 3787 +3417 2903 3785 +3415 2905 3785 +3413 2909 3783 +3409 2915 3783 +3403 2921 3781 +3395 2931 3777 +3385 2943 3775 +3369 2957 3769 +3349 2977 3763 +3321 3003 3755 +3281 3033 3743 +3221 3073 3727 +3123 3121 3705 +2951 3177 3671 +2513 3243 3625 +0 3319 3553 +0 3403 3437 +0 3497 3209 +0 3597 2299 +0 3705 0 +0 3817 0 +0 3933 0 +0 4053 0 +3445 2891 3795 +3445 2891 3795 +3445 2891 3795 +3445 2891 3795 +3445 2891 3793 +3443 2893 3793 +3443 2893 3793 +3443 2895 3793 +3441 2897 3793 +3439 2899 3793 +3437 2901 3791 +3435 2905 3791 +3431 2911 3789 +3425 2917 3787 +3417 2927 3785 +3407 2939 3781 +3395 2955 3777 +3375 2975 3771 +3349 2999 3761 +3311 3031 3751 +3253 3071 3735 +3165 3119 3713 +3009 3175 3681 +2653 3241 3635 +0 3317 3565 +0 3403 3451 +0 3495 3233 +0 3597 2447 +0 3703 0 +0 3817 0 +0 3933 0 +0 4053 0 +3473 2885 3803 +3473 2885 3803 +3473 2887 3803 +3473 2887 3803 +3471 2887 3803 +3471 2887 3803 +3471 2889 3803 +3469 2889 3801 +3469 2891 3801 +3467 2893 3801 +3465 2897 3801 +3463 2901 3799 +3459 2907 3797 +3453 2913 3795 +3447 2923 3793 +3437 2935 3789 +3425 2951 3785 +3407 2971 3779 +3383 2995 3771 +3347 3027 3759 +3295 3067 3745 +3213 3115 3723 +3077 3173 3691 +2791 3239 3647 +0 3315 3579 +0 3401 3469 +0 3495 3263 +0 3595 2591 +0 3703 0 +0 3815 0 +0 3933 0 +0 4053 0 +3507 2879 3815 +3507 2879 3815 +3507 2879 3815 +3507 2879 3815 +3507 2881 3813 +3505 2881 3813 +3505 2883 3813 +3505 2883 3813 +3503 2885 3813 +3501 2887 3813 +3499 2891 3811 +3497 2895 3811 +3493 2901 3809 +3489 2907 3807 +3483 2917 3805 +3475 2929 3801 +3463 2945 3797 +3447 2965 3791 +3423 2991 3783 +3391 3023 3773 +3345 3063 3757 +3273 3111 3735 +3155 3169 3707 +2927 3235 3663 +1989 3313 3597 +0 3399 3493 +0 3493 3299 +0 3593 2733 +0 3701 0 +0 3815 0 +0 3931 0 +0 4053 0 +3549 2871 3829 +3549 2871 3829 +3549 2871 3829 +3549 2871 3829 +3549 2871 3829 +3547 2873 3829 +3547 2873 3829 +3547 2875 3827 +3545 2877 3827 +3545 2879 3827 +3543 2881 3827 +3541 2887 3825 +3537 2891 3825 +3533 2899 3823 +3527 2909 3819 +3519 2921 3817 +3509 2937 3813 +3493 2957 3807 +3473 2983 3799 +3445 3017 3789 +3403 3057 3773 +3341 3105 3753 +3241 3165 3725 +3061 3231 3683 +2587 3309 3621 +0 3395 3521 +0 3491 3343 +0 3593 2871 +0 3701 0 +0 3813 0 +0 3931 0 +0 4051 0 +3599 2857 3849 +3599 2859 3847 +3599 2859 3847 +3599 2859 3847 +3599 2859 3847 +3599 2861 3847 +3599 2861 3847 +3597 2863 3847 +3597 2865 3847 +3595 2867 3847 +3593 2871 3845 +3591 2875 3845 +3589 2879 3843 +3585 2887 3841 +3579 2897 3839 +3573 2909 3837 +3563 2927 3833 +3551 2947 3827 +3533 2975 3819 +3507 3007 3809 +3471 3049 3795 +3419 3099 3775 +3337 3157 3749 +3197 3227 3709 +2897 3305 3651 +0 3391 3559 +0 3487 3397 +0 3589 3007 +0 3699 0 +0 3811 0 +0 3929 0 +0 4051 0 +3659 2841 3873 +3659 2841 3873 +3659 2841 3873 +3659 2843 3873 +3659 2843 3871 +3659 2843 3871 +3659 2845 3871 +3657 2847 3871 +3657 2847 3871 +3655 2851 3871 +3655 2853 3869 +3653 2859 3869 +3651 2865 3867 +3647 2871 3867 +3643 2881 3865 +3637 2895 3861 +3629 2911 3857 +3617 2933 3853 +3601 2961 3845 +3579 2995 3835 +3549 3037 3823 +3505 3089 3805 +3439 3149 3779 +3331 3219 3741 +3129 3299 3687 +2499 3387 3603 +0 3483 3459 +0 3587 3143 +0 3695 0 +0 3809 0 +0 3929 0 +0 4049 0 +3729 2817 3903 +3729 2819 3903 +3729 2819 3903 +3729 2819 3903 +3729 2819 3903 +3729 2821 3903 +3727 2821 3903 +3727 2823 3901 +3727 2825 3901 +3725 2827 3901 +3725 2831 3901 +3723 2835 3899 +3721 2841 3899 +3719 2849 3897 +3715 2861 3895 +3709 2875 3893 +3703 2891 3889 +3693 2915 3883 +3679 2943 3877 +3661 2979 3869 +3637 3023 3857 +3601 3075 3839 +3547 3137 3815 +3463 3209 3781 +3323 3291 3733 +3017 3379 3657 +0 3477 3531 +0 3581 3279 +0 3693 744 +0 3807 0 +0 3927 0 +0 4049 0 +3809 2785 3941 +3809 2785 3941 +3807 2785 3941 +3807 2785 3941 +3807 2787 3941 +3807 2787 3941 +3807 2789 3941 +3807 2789 3939 +3807 2791 3939 +3805 2795 3939 +3805 2799 3939 +3803 2803 3937 +3801 2811 3937 +3799 2819 3935 +3795 2831 3933 +3791 2845 3931 +3785 2863 3927 +3777 2887 3923 +3767 2919 3917 +3753 2955 3909 +3731 3001 3897 +3703 3057 3883 +3661 3121 3861 +3597 3195 3831 +3495 3279 3787 +3311 3371 3721 +2807 3469 3613 +0 3575 3413 +0 3687 2797 +0 3803 0 +0 3923 0 +0 4047 0 +3897 2735 3987 +3895 2735 3987 +3895 2737 3987 +3895 2737 3987 +3895 2737 3987 +3895 2739 3987 +3895 2739 3987 +3895 2741 3987 +3895 2743 3985 +3893 2747 3985 +3893 2751 3985 +3891 2757 3985 +3891 2765 3983 +3889 2773 3983 +3885 2787 3981 +3883 2803 3979 +3877 2823 3975 +3871 2849 3971 +3863 2883 3965 +3851 2923 3959 +3833 2973 3949 +3811 3031 3935 +3777 3099 3915 +3729 3177 3889 +3657 3263 3851 +3535 3357 3793 +3295 3459 3703 +2103 3567 3545 +0 3681 3179 +0 3799 0 +0 3919 0 +0 4043 0 +3993 2661 4041 +3991 2661 4041 +3991 2661 4041 +3991 2663 4041 +3991 2663 4041 +3991 2665 4041 +3991 2665 4041 +3991 2667 4041 +3991 2671 4041 +3991 2675 4041 +3989 2679 4041 +3989 2685 4039 +3987 2695 4039 +3985 2705 4037 +3983 2719 4037 +3981 2739 4035 +3977 2763 4031 +3971 2793 4029 +3965 2829 4023 +3955 2875 4017 +3943 2929 4009 +3925 2993 3997 +3899 3067 3979 +3863 3149 3957 +3809 3241 3923 +3725 3339 3875 +3583 3445 3801 +3273 3557 3679 +0 3673 3437 +0 3791 2169 +0 3915 0 +0 4039 0 +4095 2537 4095 +4095 2537 4095 +4095 2537 4095 +4095 2539 4095 +4095 2539 4095 +4095 2541 4095 +4095 2543 4095 +4095 2545 4095 +4095 2549 4095 +4093 2555 4095 +4093 2561 4095 +4093 2569 4095 +4091 2579 4095 +4091 2595 4095 +4089 2613 4095 +4087 2635 4095 +4083 2665 4095 +4079 2703 4095 +4073 2747 4091 +4067 2801 4085 +4055 2865 4077 +4041 2937 4067 +4023 3019 4053 +3995 3111 4033 +3955 3209 4005 +3897 3315 3965 +3803 3425 3907 +3639 3541 3811 +3243 3661 3645 +0 3783 3235 +0 3907 0 +0 4033 0 +4095 2287 4095 +4095 2289 4095 +4095 2289 4095 +4095 2291 4095 +4095 2293 4095 +4095 2295 4095 +4095 2299 4095 +4095 2305 4095 +4095 2311 4095 +4095 2319 4095 +4095 2329 4095 +4095 2343 4095 +4095 2361 4095 +4095 2383 4095 +4095 2413 4095 +4095 2449 4095 +4095 2493 4095 +4095 2545 4095 +4095 2607 4095 +4095 2679 4095 +4095 2761 4095 +4095 2851 4095 +4095 2949 4095 +4095 3053 4095 +4095 3163 4095 +4057 3279 4065 +3993 3397 4017 +3891 3519 3945 +3707 3643 3825 +3199 3771 3595 +0 3899 2597 +0 4027 0 +4095 662 4095 +4095 691 4095 +4095 728 4095 +4095 772 4095 +4095 825 4095 +4095 888 4095 +4095 960 4095 +4095 1041 4095 +4095 1131 4095 +4095 1229 4095 +4095 1334 4095 +4095 1445 4095 +4095 1560 4095 +4095 1679 4095 +4095 1802 4095 +4095 1926 4095 +4095 2053 4095 +4095 2181 4095 +4095 2309 4095 +4095 2439 4095 +4095 2569 4095 +4095 2699 4095 +4095 2831 4095 +4095 2963 4095 +4095 3093 4095 +4095 3225 4095 +4095 3357 4095 +4095 3489 4077 +3987 3621 3991 +3783 3753 3843 +3133 3885 3517 +0 4017 0 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 1211 4095 +4095 2021 4095 +4095 2361 4095 +4095 2603 4095 +4095 2803 4095 +4095 2981 4095 +4095 3143 4095 +4095 3297 4095 +4095 3445 4095 +4095 3589 4095 +4089 3729 4047 +3867 3867 3867 +3023 4003 3387 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 1681 4095 +4095 2431 4095 +4095 2763 4095 +4095 3003 4095 +4095 3203 4095 +4095 3379 4095 +4095 3541 4095 +4095 3695 4095 +4095 3841 4095 +3961 3985 3897 +3487 3037 3899 +3487 3037 3899 +3485 3037 3899 +3485 3037 3899 +3485 3037 3899 +3485 3037 3899 +3485 3039 3899 +3483 3039 3899 +3483 3041 3899 +3481 3043 3899 +3479 3045 3897 +3475 3047 3897 +3473 3051 3895 +3467 3057 3895 +3461 3063 3893 +3451 3071 3889 +3439 3083 3885 +3423 3099 3881 +3399 3117 3875 +3365 3143 3865 +3315 3173 3853 +3237 3211 3835 +3109 3259 3813 +2847 3315 3779 +0 3379 3729 +0 3455 3653 +0 3539 3525 +0 3631 3267 +0 3731 0 +0 3837 0 +0 3951 0 +0 4067 0 +3487 3037 3899 +3487 3037 3899 +3485 3037 3899 +3485 3037 3899 +3485 3037 3899 +3485 3037 3899 +3485 3039 3899 +3483 3039 3899 +3483 3041 3899 +3481 3043 3899 +3479 3045 3897 +3477 3047 3897 +3473 3051 3895 +3467 3057 3895 +3461 3063 3893 +3451 3071 3889 +3439 3083 3885 +3423 3099 3881 +3399 3117 3875 +3365 3143 3865 +3315 3173 3853 +3237 3211 3835 +3109 3259 3813 +2849 3315 3779 +0 3379 3729 +0 3455 3653 +0 3539 3525 +0 3631 3267 +0 3731 0 +0 3837 0 +0 3951 0 +0 4067 0 +3487 3037 3899 +3487 3037 3899 +3487 3037 3899 +3485 3037 3899 +3485 3037 3899 +3485 3037 3899 +3485 3039 3899 +3483 3039 3899 +3483 3041 3899 +3481 3043 3899 +3479 3045 3897 +3477 3047 3897 +3473 3051 3895 +3467 3057 3895 +3461 3063 3893 +3453 3071 3889 +3439 3083 3885 +3423 3099 3881 +3399 3117 3875 +3365 3143 3865 +3315 3173 3853 +3239 3211 3837 +3109 3259 3813 +2849 3315 3779 +0 3379 3729 +0 3455 3653 +0 3539 3525 +0 3631 3267 +0 3731 0 +0 3837 0 +0 3951 0 +0 4067 0 +3487 3037 3901 +3487 3037 3899 +3487 3037 3899 +3487 3037 3899 +3485 3037 3899 +3485 3037 3899 +3485 3039 3899 +3485 3039 3899 +3483 3041 3899 +3481 3043 3899 +3479 3045 3897 +3477 3047 3897 +3473 3051 3895 +3469 3057 3895 +3461 3063 3893 +3453 3071 3889 +3441 3083 3885 +3423 3099 3881 +3399 3117 3875 +3365 3143 3865 +3315 3173 3853 +3239 3211 3837 +3111 3259 3813 +2851 3315 3779 +0 3379 3729 +0 3455 3653 +0 3539 3525 +0 3631 3267 +0 3731 0 +0 3837 0 +0 3951 0 +0 4067 0 +3487 3037 3901 +3487 3037 3901 +3487 3037 3901 +3487 3037 3899 +3487 3037 3899 +3485 3037 3899 +3485 3039 3899 +3485 3039 3899 +3483 3041 3899 +3481 3043 3899 +3479 3045 3897 +3477 3047 3897 +3473 3051 3895 +3469 3057 3895 +3463 3063 3893 +3453 3071 3889 +3441 3083 3887 +3423 3099 3881 +3399 3117 3875 +3365 3143 3865 +3315 3173 3853 +3239 3211 3837 +3111 3259 3813 +2853 3315 3779 +0 3379 3729 +0 3455 3653 +0 3539 3525 +0 3631 3267 +0 3731 0 +0 3837 0 +0 3951 0 +0 4067 0 +3487 3037 3901 +3487 3037 3901 +3487 3037 3901 +3487 3037 3901 +3487 3037 3901 +3487 3037 3899 +3485 3039 3899 +3485 3039 3899 +3483 3041 3899 +3483 3043 3899 +3481 3045 3899 +3477 3047 3897 +3475 3051 3897 +3469 3057 3895 +3463 3063 3893 +3453 3071 3889 +3441 3083 3887 +3425 3099 3881 +3401 3117 3875 +3367 3143 3865 +3317 3173 3853 +3241 3211 3837 +3113 3259 3813 +2855 3315 3779 +0 3379 3729 +0 3455 3653 +0 3539 3525 +0 3631 3269 +0 3731 0 +0 3837 0 +0 3951 0 +0 4067 0 +3489 3035 3901 +3489 3037 3901 +3489 3037 3901 +3489 3037 3901 +3487 3037 3901 +3487 3037 3901 +3487 3039 3899 +3485 3039 3899 +3485 3041 3899 +3483 3041 3899 +3481 3045 3899 +3479 3047 3897 +3475 3051 3897 +3471 3057 3895 +3463 3063 3893 +3455 3071 3891 +3443 3083 3887 +3425 3099 3881 +3401 3117 3875 +3367 3143 3867 +3317 3173 3853 +3241 3211 3837 +3115 3259 3813 +2857 3315 3779 +0 3379 3729 +0 3455 3653 +0 3539 3527 +0 3631 3269 +0 3731 0 +0 3837 0 +0 3949 0 +0 4067 0 +3489 3035 3901 +3489 3035 3901 +3489 3037 3901 +3489 3037 3901 +3489 3037 3901 +3489 3037 3901 +3487 3039 3901 +3487 3039 3899 +3485 3041 3899 +3485 3041 3899 +3483 3045 3899 +3479 3047 3897 +3477 3051 3897 +3471 3055 3895 +3465 3063 3893 +3455 3071 3891 +3443 3083 3887 +3427 3099 3881 +3403 3117 3875 +3369 3143 3867 +3319 3173 3855 +3243 3211 3837 +3117 3259 3813 +2861 3315 3779 +0 3379 3729 +0 3455 3653 +0 3539 3527 +0 3631 3271 +0 3731 0 +0 3837 0 +0 3949 0 +0 4067 0 +3491 3035 3901 +3491 3035 3901 +3491 3035 3901 +3491 3037 3901 +3491 3037 3901 +3489 3037 3901 +3489 3037 3901 +3489 3039 3901 +3487 3041 3899 +3485 3041 3899 +3483 3043 3899 +3481 3047 3899 +3477 3051 3897 +3473 3055 3895 +3467 3063 3893 +3457 3071 3891 +3445 3083 3887 +3427 3097 3883 +3405 3117 3875 +3371 3141 3867 +3321 3173 3855 +3245 3211 3837 +3121 3259 3813 +2867 3315 3779 +504 3379 3731 +0 3455 3655 +0 3539 3527 +0 3631 3271 +0 3731 0 +0 3837 0 +0 3949 0 +0 4067 0 +3493 3035 3901 +3493 3035 3901 +3493 3035 3901 +3493 3037 3901 +3493 3037 3901 +3491 3037 3901 +3491 3037 3901 +3491 3039 3901 +3489 3039 3901 +3487 3041 3901 +3485 3043 3899 +3483 3047 3899 +3479 3051 3897 +3475 3055 3895 +3469 3063 3893 +3459 3071 3891 +3447 3083 3887 +3431 3097 3883 +3407 3117 3877 +3373 3141 3867 +3325 3173 3855 +3249 3211 3839 +3125 3259 3815 +2875 3313 3781 +1125 3379 3731 +0 3455 3655 +0 3539 3529 +0 3631 3273 +0 3731 0 +0 3837 0 +0 3949 0 +0 4067 0 +3495 3035 3903 +3495 3035 3903 +3495 3035 3903 +3495 3035 3903 +3495 3037 3903 +3495 3037 3901 +3493 3037 3901 +3493 3039 3901 +3491 3039 3901 +3491 3041 3901 +3489 3043 3901 +3485 3047 3899 +3481 3051 3899 +3477 3055 3897 +3471 3061 3895 +3461 3071 3893 +3449 3083 3889 +3433 3097 3883 +3409 3117 3877 +3377 3141 3869 +3327 3173 3855 +3253 3211 3839 +3129 3257 3815 +2885 3313 3781 +1440 3379 3733 +0 3455 3657 +0 3539 3531 +0 3631 3277 +0 3731 0 +0 3837 0 +0 3949 0 +0 4067 0 +3499 3035 3903 +3499 3035 3903 +3499 3035 3903 +3499 3035 3903 +3497 3035 3903 +3497 3037 3903 +3497 3037 3903 +3495 3037 3903 +3495 3039 3903 +3493 3041 3901 +3491 3043 3901 +3489 3045 3901 +3485 3049 3899 +3481 3055 3897 +3475 3061 3895 +3465 3071 3893 +3453 3081 3889 +3437 3097 3885 +3413 3117 3877 +3381 3141 3869 +3333 3173 3857 +3259 3211 3839 +3137 3257 3817 +2897 3313 3783 +1672 3379 3733 +0 3455 3657 +0 3539 3533 +0 3631 3281 +0 3731 1095 +0 3837 0 +0 3949 0 +0 4067 0 +3503 3033 3905 +3503 3035 3905 +3503 3035 3905 +3503 3035 3905 +3503 3035 3905 +3501 3035 3905 +3501 3037 3903 +3501 3037 3903 +3499 3039 3903 +3497 3041 3903 +3495 3043 3903 +3493 3045 3901 +3489 3049 3901 +3485 3055 3899 +3479 3061 3897 +3471 3069 3895 +3459 3081 3891 +3441 3097 3885 +3419 3115 3879 +3387 3141 3871 +3339 3171 3859 +3267 3211 3841 +3147 3257 3817 +2913 3313 3785 +1867 3379 3735 +0 3453 3661 +0 3537 3535 +0 3631 3285 +0 3731 1469 +0 3837 0 +0 3949 0 +0 4067 0 +3509 3033 3907 +3509 3033 3907 +3509 3033 3905 +3509 3033 3905 +3507 3035 3905 +3507 3035 3905 +3507 3035 3905 +3507 3037 3905 +3505 3037 3905 +3503 3039 3905 +3501 3041 3903 +3499 3045 3903 +3495 3049 3901 +3491 3053 3901 +3485 3061 3899 +3477 3069 3895 +3465 3081 3893 +3449 3095 3887 +3425 3115 3881 +3393 3139 3873 +3347 3171 3859 +3275 3209 3843 +3159 3257 3819 +2933 3313 3787 +2041 3379 3737 +0 3453 3663 +0 3537 3539 +0 3631 3291 +0 3731 1724 +0 3837 0 +0 3949 0 +0 4067 0 +3517 3033 3909 +3517 3033 3909 +3517 3033 3909 +3515 3033 3909 +3515 3033 3907 +3515 3033 3907 +3515 3035 3907 +3513 3035 3907 +3513 3037 3907 +3511 3039 3907 +3509 3041 3905 +3507 3043 3905 +3503 3047 3905 +3499 3053 3903 +3493 3059 3901 +3485 3067 3897 +3473 3079 3895 +3457 3095 3889 +3435 3115 3883 +3403 3139 3875 +3357 3171 3863 +3289 3209 3845 +3175 3257 3823 +2959 3313 3789 +2203 3377 3741 +0 3453 3667 +0 3537 3543 +0 3631 3299 +0 3731 1929 +0 3837 0 +0 3949 0 +0 4067 0 +3527 3031 3911 +3527 3031 3911 +3527 3031 3911 +3525 3031 3911 +3525 3031 3911 +3525 3033 3911 +3525 3033 3911 +3523 3033 3911 +3523 3035 3909 +3521 3037 3909 +3519 3039 3909 +3517 3041 3907 +3513 3045 3907 +3509 3051 3905 +3503 3057 3903 +3495 3067 3901 +3483 3079 3897 +3469 3093 3893 +3447 3113 3887 +3417 3137 3877 +3371 3169 3865 +3305 3207 3849 +3197 3255 3825 +2993 3311 3793 +2355 3377 3745 +0 3453 3671 +0 3537 3549 +0 3629 3311 +0 3731 2109 +0 3837 0 +0 3949 0 +0 4065 0 +3539 3029 3915 +3539 3029 3915 +3539 3029 3915 +3539 3029 3915 +3539 3029 3915 +3539 3031 3915 +3537 3031 3915 +3537 3031 3913 +3535 3033 3913 +3535 3035 3913 +3533 3037 3913 +3531 3039 3911 +3527 3043 3911 +3523 3049 3909 +3517 3055 3907 +3509 3065 3905 +3499 3077 3901 +3483 3091 3897 +3463 3111 3891 +3433 3137 3881 +3389 3167 3869 +3325 3207 3853 +3223 3253 3831 +3033 3311 3797 +2501 3377 3751 +0 3451 3677 +0 3537 3559 +0 3629 3325 +0 3729 2275 +0 3837 0 +0 3949 0 +0 4065 0 +3557 3025 3919 +3557 3027 3919 +3555 3027 3919 +3555 3027 3919 +3555 3027 3919 +3555 3027 3919 +3555 3029 3919 +3553 3029 3919 +3553 3031 3919 +3551 3033 3919 +3549 3035 3917 +3547 3037 3917 +3545 3041 3915 +3541 3047 3915 +3535 3053 3913 +3527 3063 3909 +3517 3075 3907 +3501 3089 3901 +3483 3109 3895 +3453 3135 3887 +3413 3165 3875 +3353 3205 3859 +3255 3253 3837 +3083 3309 3805 +2645 3375 3757 +0 3451 3685 +0 3535 3569 +0 3629 3343 +0 3729 2431 +0 3837 0 +0 3949 0 +0 4065 0 +3577 3023 3927 +3577 3023 3927 +3577 3023 3927 +3577 3023 3927 +3577 3023 3927 +3577 3023 3927 +3577 3025 3925 +3575 3025 3925 +3575 3027 3925 +3573 3029 3925 +3571 3031 3925 +3569 3033 3923 +3567 3037 3923 +3563 3043 3921 +3557 3049 3919 +3549 3059 3917 +3539 3071 3913 +3527 3087 3909 +3507 3107 3903 +3481 3131 3893 +3443 3163 3883 +3385 3203 3867 +3297 3251 3845 +3141 3307 3813 +2785 3373 3767 +0 3449 3697 +0 3535 3583 +0 3627 3365 +0 3729 2579 +0 3835 0 +0 3949 0 +0 4065 0 +3605 3017 3935 +3605 3017 3935 +3605 3017 3935 +3605 3019 3935 +3605 3019 3935 +3603 3019 3935 +3603 3019 3935 +3603 3021 3935 +3601 3023 3933 +3601 3023 3933 +3599 3027 3933 +3597 3029 3933 +3595 3033 3931 +3591 3039 3929 +3585 3045 3927 +3579 3055 3925 +3569 3067 3923 +3557 3083 3917 +3539 3103 3911 +3515 3127 3903 +3479 3159 3891 +3427 3199 3877 +3347 3247 3855 +3209 3305 3823 +2923 3371 3779 +0 3447 3711 +0 3533 3601 +0 3627 3395 +0 3727 2723 +0 3835 0 +0 3947 0 +0 4065 0 +3639 3011 3947 +3639 3011 3947 +3639 3011 3947 +3639 3011 3947 +3639 3013 3947 +3639 3013 3947 +3637 3013 3945 +3637 3015 3945 +3637 3015 3945 +3635 3017 3945 +3633 3019 3945 +3631 3023 3943 +3629 3027 3943 +3625 3033 3941 +3621 3039 3939 +3615 3049 3937 +3607 3061 3933 +3595 3077 3929 +3579 3097 3923 +3555 3123 3915 +3523 3155 3905 +3477 3195 3889 +3405 3243 3869 +3287 3301 3839 +3059 3369 3795 +2121 3445 3729 +0 3531 3625 +0 3625 3431 +0 3727 2865 +0 3833 0 +0 3947 0 +0 4065 0 +3681 3003 3961 +3681 3003 3961 +3681 3003 3961 +3681 3003 3961 +3681 3003 3961 +3681 3003 3961 +3679 3005 3961 +3679 3005 3961 +3679 3007 3961 +3677 3009 3959 +3677 3011 3959 +3675 3015 3959 +3673 3019 3957 +3669 3023 3957 +3665 3031 3955 +3659 3041 3953 +3651 3053 3949 +3641 3069 3945 +3625 3089 3939 +3605 3115 3931 +3577 3149 3921 +3535 3189 3905 +3473 3237 3885 +3373 3297 3857 +3195 3365 3815 +2719 3441 3753 +0 3527 3655 +0 3623 3475 +0 3725 3003 +0 3833 0 +0 3945 0 +0 4063 0 +3731 2989 3981 +3731 2991 3981 +3731 2991 3981 +3731 2991 3981 +3731 2991 3979 +3731 2991 3979 +3731 2993 3979 +3731 2993 3979 +3729 2995 3979 +3729 2997 3979 +3727 2999 3979 +3725 3003 3977 +3723 3007 3977 +3721 3013 3975 +3717 3019 3973 +3713 3029 3971 +3705 3041 3969 +3695 3059 3965 +3683 3079 3959 +3665 3107 3951 +3639 3139 3941 +3603 3181 3927 +3551 3231 3907 +3469 3289 3881 +3329 3359 3841 +3029 3437 3783 +0 3523 3691 +0 3619 3529 +0 3721 3139 +0 3831 0 +0 3945 0 +0 4061 0 +3791 2973 4005 +3791 2973 4005 +3791 2973 4005 +3791 2973 4005 +3791 2975 4005 +3791 2975 4005 +3791 2975 4003 +3791 2977 4003 +3789 2979 4003 +3789 2981 4003 +3787 2983 4003 +3787 2985 4001 +3785 2991 4001 +3783 2997 3999 +3779 3003 3999 +3775 3013 3997 +3769 3027 3993 +3761 3043 3989 +3749 3065 3985 +3733 3093 3977 +3713 3127 3967 +3681 3169 3955 +3637 3221 3937 +3571 3281 3911 +3463 3351 3873 +3261 3431 3819 +2631 3519 3735 +0 3615 3591 +0 3719 3275 +0 3827 0 +0 3943 0 +0 4061 0 +3861 2949 4035 +3861 2949 4035 +3861 2951 4035 +3861 2951 4035 +3861 2951 4035 +3861 2951 4035 +3861 2953 4035 +3861 2953 4035 +3859 2955 4035 +3859 2957 4033 +3859 2959 4033 +3857 2963 4033 +3855 2967 4031 +3853 2973 4031 +3851 2981 4029 +3847 2993 4027 +3841 3007 4025 +3835 3023 4021 +3825 3047 4017 +3811 3075 4009 +3793 3111 4001 +3769 3155 3989 +3733 3207 3971 +3679 3269 3947 +3595 3341 3915 +3455 3423 3865 +3149 3511 3789 +0 3609 3663 +0 3713 3411 +0 3825 876 +0 3939 0 +0 4059 0 +3941 2917 4073 +3941 2917 4073 +3941 2917 4073 +3941 2917 4073 +3939 2917 4073 +3939 2919 4073 +3939 2919 4073 +3939 2921 4073 +3939 2921 4071 +3939 2925 4071 +3937 2927 4071 +3937 2931 4071 +3935 2935 4069 +3933 2943 4069 +3931 2951 4067 +3927 2963 4065 +3923 2977 4063 +3917 2995 4059 +3909 3019 4055 +3899 3051 4049 +3885 3087 4041 +3863 3133 4031 +3835 3189 4015 +3793 3253 3993 +3729 3327 3963 +3627 3411 3919 +3443 3503 3853 +2939 3601 3745 +0 3707 3545 +0 3819 2929 +0 3935 0 +0 4055 0 +4029 2867 4095 +4029 2867 4095 +4029 2867 4095 +4029 2869 4095 +4027 2869 4095 +4027 2869 4095 +4027 2871 4095 +4027 2871 4095 +4027 2873 4095 +4027 2877 4095 +4025 2879 4095 +4025 2883 4095 +4025 2889 4095 +4023 2897 4095 +4021 2905 4095 +4019 2919 4095 +4015 2935 4095 +4009 2955 4095 +4003 2981 4095 +3995 3015 4095 +3983 3055 4091 +3965 3105 4081 +3943 3163 4067 +3909 3231 4047 +3861 3309 4021 +3789 3395 3983 +3667 3489 3925 +3427 3591 3835 +2235 3699 3677 +0 3813 3313 +0 3931 0 +0 4051 0 +4095 2793 4095 +4095 2793 4095 +4095 2793 4095 +4095 2793 4095 +4095 2795 4095 +4095 2795 4095 +4095 2797 4095 +4095 2797 4095 +4095 2799 4095 +4095 2803 4095 +4095 2807 4095 +4095 2811 4095 +4095 2817 4095 +4095 2827 4095 +4095 2837 4095 +4095 2851 4095 +4095 2871 4095 +4095 2895 4095 +4095 2925 4095 +4095 2961 4095 +4087 3007 4095 +4075 3061 4095 +4057 3125 4095 +4031 3199 4095 +3995 3281 4089 +3941 3373 4055 +3857 3471 4007 +3715 3577 3933 +3407 3689 3811 +0 3805 3569 +0 3925 2301 +0 4047 0 +4095 2667 4095 +4095 2669 4095 +4095 2669 4095 +4095 2669 4095 +4095 2671 4095 +4095 2671 4095 +4095 2673 4095 +4095 2675 4095 +4095 2677 4095 +4095 2681 4095 +4095 2687 4095 +4095 2693 4095 +4095 2701 4095 +4095 2711 4095 +4095 2727 4095 +4095 2745 4095 +4095 2767 4095 +4095 2797 4095 +4095 2835 4095 +4095 2879 4095 +4095 2933 4095 +4095 2997 4095 +4095 3069 4095 +4095 3151 4095 +4095 3243 4095 +4087 3341 4095 +4029 3447 4095 +3935 3557 4039 +3771 3673 3945 +3375 3793 3777 +0 3915 3367 +0 4039 0 +4095 2419 4095 +4095 2421 4095 +4095 2421 4095 +4095 2421 4095 +4095 2423 4095 +4095 2425 4095 +4095 2429 4095 +4095 2431 4095 +4095 2437 4095 +4095 2443 4095 +4095 2451 4095 +4095 2461 4095 +4095 2475 4095 +4095 2493 4095 +4095 2515 4095 +4095 2545 4095 +4095 2581 4095 +4095 2625 4095 +4095 2677 4095 +4095 2739 4095 +4095 2811 4095 +4095 2893 4095 +4095 2983 4095 +4095 3081 4095 +4095 3185 4095 +4095 3295 4095 +4095 3411 4095 +4095 3529 4095 +4023 3651 4077 +3839 3777 3959 +3331 3903 3727 +0 4031 2729 +4095 771 4095 +4095 795 4095 +4095 824 4095 +4095 860 4095 +4095 904 4095 +4095 957 4095 +4095 1020 4095 +4095 1092 4095 +4095 1173 4095 +4095 1263 4095 +4095 1361 4095 +4095 1466 4095 +4095 1577 4095 +4095 1692 4095 +4095 1811 4095 +4095 1934 4095 +4095 2059 4095 +4095 2185 4095 +4095 2313 4095 +4095 2441 4095 +4095 2571 4095 +4095 2701 4095 +4095 2831 4095 +4095 2963 4095 +4095 3095 4095 +4095 3225 4095 +4095 3357 4095 +4095 3489 4095 +4095 3621 4095 +4095 3753 4095 +3915 3885 3977 +3265 4017 3649 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 1343 4095 +4095 2153 4095 +4095 2493 4095 +4095 2735 4095 +4095 2935 4095 +4095 3113 4095 +4095 3275 4095 +4095 3429 4095 +4095 3577 4095 +4095 3721 4095 +4095 3861 4095 +3999 3999 3999 diff --git a/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/Test_Extreme_Grade/test-extreme-grade_inv-Log2-48nits_32_LUT.azasset b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/Test_Extreme_Grade/test-extreme-grade_inv-Log2-48nits_32_LUT.azasset new file mode 100644 index 0000000000..66f3b57564 --- /dev/null +++ b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/Test_Extreme_Grade/test-extreme-grade_inv-Log2-48nits_32_LUT.azasset @@ -0,0 +1,32780 @@ +{ + "Type": "JsonSerialization", + "Version": 1, + "ClassName": "LookupTableAsset", + "ClassData": { + "Name": "LookupTable", + "Intervals": [ + 0, 33, 66, 99, 132, 165, 198, 231, 264, 297, 330, 363, 396, 429, 462, 495, 528, 561, 594, 627, 660, 693, 726, 759, 792, 825, 858, 891, 924, 957, 990, 1023], + "Values": [ + 0, 0, 0, + 0, 40, 0, + 0, 176, 0, + 0, 310, 0, + 0, 444, 0, + 0, 578, 0, + 0, 711, 0, + 0, 844, 0, + 0, 976, 0, + 0, 1109, 0, + 0, 1241, 0, + 0, 1374, 0, + 0, 1506, 0, + 0, 1638, 0, + 0, 1770, 0, + 0, 1903, 0, + 0, 2035, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 235, 0, 150, + 0, 22, 0, + 0, 162, 0, + 0, 300, 0, + 0, 437, 0, + 0, 572, 0, + 0, 707, 0, + 0, 841, 0, + 0, 974, 0, + 0, 1107, 0, + 0, 1240, 0, + 0, 1373, 0, + 0, 1505, 0, + 0, 1638, 0, + 0, 1770, 0, + 0, 1902, 0, + 0, 2035, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 474, 0, 352, + 349, 0, 225, + 98, 143, 0, + 0, 286, 0, + 0, 427, 0, + 0, 565, 0, + 0, 701, 0, + 0, 836, 0, + 0, 971, 0, + 0, 1105, 0, + 0, 1238, 0, + 0, 1371, 0, + 0, 1504, 0, + 0, 1637, 0, + 0, 1769, 0, + 0, 1902, 0, + 0, 2034, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 672, 0, 529, + 595, 0, 448, + 467, 117, 309, + 205, 267, 14, + 0, 412, 0, + 0, 554, 0, + 0, 693, 0, + 0, 831, 0, + 0, 967, 0, + 0, 1102, 0, + 0, 1236, 0, + 0, 1370, 0, + 0, 1503, 0, + 0, 1636, 0, + 0, 1769, 0, + 0, 1901, 0, + 0, 2034, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 848, 0, 693, + 797, 0, 638, + 719, 78, 551, + 588, 240, 402, + 318, 393, 67, + 0, 540, 0, + 0, 683, 0, + 0, 823, 0, + 0, 961, 0, + 0, 1097, 0, + 0, 1233, 0, + 0, 1367, 0, + 0, 1501, 0, + 0, 1635, 0, + 0, 1768, 0, + 0, 1901, 0, + 0, 2033, 0, + 0, 2165, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1010, 0, 848, + 975, 0, 809, + 924, 22, 751, + 845, 201, 661, + 712, 365, 502, + 435, 520, 130, + 0, 669, 0, + 0, 813, 0, + 0, 953, 0, + 0, 1092, 0, + 0, 1228, 0, + 0, 1364, 0, + 0, 1499, 0, + 0, 1633, 0, + 0, 1766, 0, + 0, 1900, 0, + 0, 2033, 0, + 0, 2165, 0, + 0, 2297, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1163, 0, 996, + 1139, 0, 968, + 1104, 0, 928, + 1052, 143, 869, + 972, 326, 775, + 837, 493, 609, + 555, 649, 202, + 0, 798, 0, + 0, 943, 0, + 0, 1084, 0, + 0, 1223, 0, + 0, 1360, 0, + 0, 1496, 0, + 0, 1631, 0, + 0, 1765, 0, + 0, 1898, 0, + 0, 2032, 0, + 0, 2165, 0, + 0, 2297, 0, + 0, 2429, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1311, 0, 1139, + 1293, 0, 1119, + 1269, 0, 1091, + 1233, 52, 1050, + 1181, 267, 990, + 1101, 452, 893, + 965, 621, 721, + 678, 778, 283, + 0, 928, 0, + 0, 1073, 0, + 0, 1215, 0, + 0, 1354, 0, + 0, 1491, 0, + 0, 1627, 0, + 0, 1762, 0, + 0, 1897, 0, + 0, 2030, 0, + 0, 2163, 0, + 0, 2297, 0, + 0, 2429, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1454, 0, 1280, + 1441, 0, 1265, + 1424, 0, 1245, + 1399, 0, 1216, + 1363, 174, 1175, + 1311, 393, 1113, + 1230, 580, 1015, + 1093, 750, 837, + 804, 908, 374, + 0, 1059, 0, + 0, 1204, 0, + 0, 1346, 0, + 0, 1486, 0, + 0, 1623, 0, + 0, 1759, 0, + 0, 1894, 0, + 0, 2029, 0, + 0, 2163, 0, + 0, 2295, 0, + 0, 2429, 0, + 0, 2561, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1595, 0, 1418, + 1585, 0, 1407, + 1572, 0, 1393, + 1554, 0, 1372, + 1530, 9, 1343, + 1494, 298, 1301, + 1441, 520, 1239, + 1360, 709, 1139, + 1222, 880, 957, + 931, 1039, 472, + 0, 1190, 0, + 0, 1336, 0, + 0, 1478, 0, + 0, 1617, 0, + 0, 1755, 0, + 0, 1891, 0, + 0, 2026, 0, + 0, 2161, 0, + 0, 2295, 0, + 0, 2427, 0, + 0, 2561, 0, + 0, 2693, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1733, 0, 1555, + 1726, 0, 1547, + 1716, 0, 1536, + 1703, 0, 1521, + 1686, 0, 1501, + 1661, 130, 1471, + 1625, 424, 1429, + 1572, 649, 1366, + 1491, 839, 1265, + 1352, 1011, 1080, + 1059, 1170, 577, + 0, 1321, 0, + 0, 1467, 0, + 0, 1610, 0, + 0, 1749, 0, + 0, 1887, 0, + 0, 2023, 0, + 0, 2159, 0, + 0, 2293, 0, + 0, 2427, 0, + 0, 2559, 0, + 0, 2693, 0, + 0, 2825, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1869, 0, 1690, + 1864, 0, 1684, + 1857, 0, 1676, + 1848, 0, 1666, + 1835, 0, 1651, + 1817, 0, 1630, + 1792, 254, 1601, + 1756, 552, 1558, + 1704, 778, 1494, + 1622, 970, 1392, + 1483, 1141, 1205, + 1188, 1301, 687, + 0, 1453, 0, + 0, 1599, 0, + 0, 1741, 0, + 0, 1881, 0, + 0, 2019, 0, + 0, 2155, 0, + 0, 2291, 0, + 0, 2425, 0, + 0, 2559, 0, + 0, 2691, 0, + 0, 2825, 0, + 0, 2957, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2005, 0, 1825, + 2001, 0, 1821, + 1996, 0, 1815, + 1989, 0, 1807, + 1979, 0, 1796, + 1966, 0, 1781, + 1949, 0, 1760, + 1924, 379, 1731, + 1888, 681, 1688, + 1835, 908, 1624, + 1753, 1100, 1521, + 1614, 1272, 1332, + 1318, 1432, 803, + 0, 1584, 0, + 0, 1731, 0, + 0, 1873, 0, + 0, 2013, 0, + 0, 2151, 0, + 0, 2287, 0, + 0, 2423, 0, + 0, 2557, 0, + 0, 2691, 0, + 0, 2823, 0, + 0, 2957, 0, + 0, 3089, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2139, 0, 1959, + 2137, 0, 1956, + 2133, 0, 1951, + 2127, 0, 1945, + 2121, 0, 1937, + 2111, 0, 1927, + 2099, 0, 1912, + 2081, 0, 1891, + 2055, 506, 1861, + 2019, 810, 1818, + 1967, 1038, 1754, + 1885, 1231, 1650, + 1745, 1404, 1460, + 1448, 1564, 922, + 0, 1716, 0, + 0, 1863, 0, + 0, 2005, 0, + 0, 2145, 0, + 0, 2283, 0, + 0, 2419, 0, + 0, 2555, 0, + 0, 2689, 0, + 0, 2823, 0, + 0, 2957, 0, + 0, 3089, 0, + 0, 3221, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3885, 0, + 0, 4017, 0, + 2273, 0, 2093, + 2271, 0, 2091, + 2269, 0, 2087, + 2265, 0, 2083, + 2259, 0, 2077, + 2253, 0, 2069, + 2243, 0, 2057, + 2231, 0, 2043, + 2213, 60, 2022, + 2187, 635, 1992, + 2151, 941, 1949, + 2099, 1169, 1884, + 2016, 1363, 1781, + 1877, 1536, 1589, + 1579, 1696, 1044, + 0, 1848, 0, + 0, 1995, 0, + 0, 2137, 0, + 0, 2277, 0, + 0, 2415, 0, + 0, 2551, 0, + 0, 2687, 0, + 0, 2821, 0, + 0, 2955, 0, + 0, 3089, 0, + 0, 3221, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3885, 0, + 0, 4017, 0, + 2407, 0, 2225, + 2405, 0, 2223, + 2403, 0, 2221, + 2401, 0, 2219, + 2397, 0, 2213, + 2391, 0, 2207, + 2385, 0, 2199, + 2375, 0, 2189, + 2361, 0, 2173, + 2345, 182, 2153, + 2319, 764, 2123, + 2283, 1071, 2081, + 2231, 1301, 2015, + 2149, 1494, 1911, + 2008, 1667, 1719, + 1710, 1828, 1168, + 0, 1980, 0, + 0, 2127, 0, + 0, 2269, 0, + 0, 2409, 0, + 0, 2547, 0, + 0, 2683, 0, + 0, 2819, 0, + 0, 2953, 0, + 0, 3087, 0, + 0, 3221, 0, + 0, 3353, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4017, 0, + 2539, 0, 2359, + 2539, 0, 2357, + 2537, 0, 2355, + 2535, 0, 2353, + 2533, 0, 2349, + 2529, 0, 2345, + 2523, 0, 2339, + 2517, 0, 2331, + 2507, 0, 2321, + 2493, 0, 2305, + 2475, 306, 2285, + 2451, 894, 2255, + 2415, 1202, 2211, + 2363, 1432, 2147, + 2279, 1626, 2042, + 2141, 1799, 1850, + 1842, 1960, 1295, + 0, 2113, 0, + 0, 2259, 0, + 0, 2401, 0, + 0, 2541, 0, + 0, 2679, 0, + 0, 2815, 0, + 0, 2951, 0, + 0, 3085, 0, + 0, 3219, 0, + 0, 3353, 0, + 0, 3485, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 2673, 0, 2491, + 2671, 0, 2491, + 2671, 0, 2489, + 2669, 0, 2487, + 2667, 0, 2485, + 2665, 0, 2481, + 2661, 0, 2477, + 2655, 0, 2471, + 2649, 0, 2463, + 2639, 0, 2453, + 2625, 0, 2437, + 2607, 433, 2415, + 2583, 1025, 2387, + 2547, 1334, 2343, + 2493, 1564, 2279, + 2411, 1758, 2173, + 2273, 1931, 1981, + 1973, 2091, 1423, + 0, 2245, 0, + 0, 2391, 0, + 0, 2533, 0, + 0, 2673, 0, + 0, 2811, 0, + 0, 2947, 0, + 0, 3083, 0, + 0, 3217, 0, + 0, 3351, 0, + 0, 3485, 0, + 0, 3617, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 2805, 0, 2623, + 2805, 0, 2623, + 2803, 0, 2623, + 2803, 0, 2621, + 2801, 0, 2619, + 2799, 0, 2617, + 2797, 0, 2613, + 2793, 0, 2609, + 2787, 0, 2603, + 2781, 0, 2595, + 2771, 0, 2583, + 2757, 0, 2569, + 2741, 560, 2547, + 2715, 1155, 2517, + 2679, 1465, 2475, + 2625, 1696, 2409, + 2543, 1890, 2305, + 2403, 2063, 2111, + 2105, 2223, 1552, + 0, 2377, 0, + 0, 2523, 0, + 0, 2665, 0, + 0, 2805, 0, + 0, 2943, 0, + 0, 3079, 0, + 0, 3215, 0, + 0, 3349, 0, + 0, 3483, 0, + 0, 3617, 0, + 0, 3749, 0, + 0, 3883, 0, + 0, 4015, 0, + 2937, 0, 2757, + 2937, 0, 2755, + 2937, 0, 2755, + 2935, 0, 2755, + 2935, 0, 2753, + 2933, 0, 2751, + 2931, 0, 2749, + 2929, 0, 2745, + 2925, 0, 2741, + 2919, 0, 2735, + 2913, 0, 2727, + 2903, 0, 2715, + 2891, 0, 2701, + 2873, 689, 2679, + 2847, 1287, 2649, + 2811, 1597, 2607, + 2759, 1828, 2541, + 2675, 2022, 2437, + 2535, 2195, 2243, + 2237, 2355, 1681, + 0, 2509, 0, + 0, 2655, 0, + 0, 2797, 0, + 0, 2937, 0, + 0, 3075, 0, + 0, 3211, 0, + 0, 3347, 0, + 0, 3481, 0, + 0, 3615, 0, + 0, 3749, 0, + 0, 3881, 0, + 0, 4015, 0, + 3071, 0, 2889, + 3069, 0, 2889, + 3069, 0, 2887, + 3069, 0, 2887, + 3067, 0, 2885, + 3067, 0, 2885, + 3065, 0, 2883, + 3063, 0, 2881, + 3061, 0, 2877, + 3057, 0, 2873, + 3051, 0, 2867, + 3045, 0, 2859, + 3035, 0, 2847, + 3023, 0, 2833, + 3005, 819, 2811, + 2979, 1418, 2781, + 2943, 1729, 2739, + 2891, 1959, 2673, + 2807, 2153, 2569, + 2667, 2327, 2375, + 2369, 2487, 1811, + 0, 2641, 0, + 0, 2787, 0, + 0, 2929, 0, + 0, 3069, 0, + 0, 3207, 0, + 0, 3343, 0, + 0, 3479, 0, + 0, 3613, 0, + 0, 3747, 0, + 0, 3881, 0, + 0, 4015, 0, + 3203, 0, 3021, + 3203, 0, 3021, + 3203, 0, 3021, + 3201, 0, 3019, + 3201, 0, 3019, + 3201, 0, 3017, + 3199, 0, 3017, + 3197, 0, 3015, + 3195, 0, 3013, + 3193, 0, 3009, + 3189, 0, 3005, + 3183, 0, 2999, + 3177, 0, 2991, + 3167, 0, 2979, + 3155, 0, 2965, + 3137, 949, 2943, + 3111, 1550, 2913, + 3075, 1860, 2871, + 3023, 2091, 2805, + 2939, 2285, 2701, + 2801, 2459, 2507, + 2501, 2619, 1942, + 0, 2773, 0, + 0, 2919, 0, + 0, 3061, 0, + 0, 3201, 0, + 0, 3339, 0, + 0, 3475, 0, + 0, 3611, 0, + 0, 3745, 0, + 0, 3879, 0, + 0, 4013, 0, + 3335, 0, 3153, + 3335, 0, 3153, + 3335, 0, 3153, + 3335, 0, 3153, + 3333, 0, 3151, + 3333, 0, 3151, + 3333, 0, 3151, + 3331, 0, 3149, + 3329, 0, 3147, + 3327, 0, 3145, + 3325, 0, 3141, + 3321, 0, 3137, + 3315, 0, 3131, + 3309, 0, 3123, + 3299, 0, 3111, + 3287, 0, 3097, + 3269, 1080, 3075, + 3243, 1682, 3045, + 3207, 1992, 3003, + 3155, 2223, 2937, + 3073, 2417, 2833, + 2933, 2591, 2639, + 2633, 2751, 2073, + 0, 2905, 0, + 0, 3051, 0, + 0, 3193, 0, + 0, 3333, 0, + 0, 3471, 0, + 0, 3609, 0, + 0, 3743, 0, + 0, 3877, 0, + 0, 4011, 0, + 3467, 0, 3285, + 3467, 0, 3285, + 3467, 0, 3285, + 3467, 0, 3285, + 3467, 0, 3285, + 3465, 0, 3283, + 3465, 0, 3283, + 3465, 0, 3283, + 3463, 0, 3281, + 3461, 0, 3279, + 3459, 0, 3277, + 3457, 0, 3273, + 3453, 0, 3269, + 3447, 0, 3263, + 3441, 0, 3255, + 3431, 0, 3243, + 3419, 0, 3229, + 3401, 1211, 3207, + 3375, 1813, 3177, + 3339, 2125, 3135, + 3287, 2355, 3069, + 3205, 2549, 2965, + 3065, 2723, 2771, + 2765, 2885, 2205, + 0, 3037, 0, + 0, 3183, 0, + 0, 3327, 0, + 0, 3465, 0, + 0, 3603, 0, + 0, 3741, 0, + 0, 3875, 0, + 0, 4009, 0, + 3599, 0, 3417, + 3599, 0, 3417, + 3599, 0, 3417, + 3599, 0, 3417, + 3599, 0, 3417, + 3599, 0, 3417, + 3597, 0, 3415, + 3597, 0, 3415, + 3597, 0, 3415, + 3595, 0, 3413, + 3593, 0, 3411, + 3591, 0, 3409, + 3589, 0, 3405, + 3585, 0, 3401, + 3579, 0, 3395, + 3573, 0, 3387, + 3563, 0, 3375, + 3551, 0, 3361, + 3533, 1342, 3339, + 3507, 1945, 3309, + 3471, 2257, 3267, + 3419, 2487, 3201, + 3337, 2681, 3097, + 3197, 2855, 2903, + 2897, 3017, 2337, + 0, 3169, 0, + 0, 3315, 0, + 0, 3459, 0, + 0, 3599, 0, + 0, 3735, 0, + 0, 3873, 0, + 0, 4007, 0, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3547, + 3729, 0, 3547, + 3729, 0, 3547, + 3727, 0, 3545, + 3725, 0, 3543, + 3723, 0, 3541, + 3721, 0, 3537, + 3717, 0, 3533, + 3711, 0, 3527, + 3705, 0, 3519, + 3695, 0, 3507, + 3683, 0, 3493, + 3665, 1474, 3471, + 3639, 2077, 3441, + 3603, 2389, 3399, + 3551, 2619, 3333, + 3469, 2813, 3229, + 3329, 2987, 3035, + 3029, 3149, 2467, + 0, 3301, 0, + 0, 3447, 0, + 0, 3591, 0, + 0, 3731, 0, + 0, 3869, 0, + 0, 4005, 0, + 3863, 0, 3683, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3861, 0, 3679, + 3861, 0, 3679, + 3859, 0, 3677, + 3857, 0, 3675, + 3855, 0, 3673, + 3853, 0, 3669, + 3849, 0, 3665, + 3845, 0, 3659, + 3837, 0, 3651, + 3827, 0, 3641, + 3815, 0, 3625, + 3797, 1605, 3603, + 3771, 2209, 3573, + 3735, 2521, 3531, + 3683, 2751, 3465, + 3601, 2947, 3361, + 3461, 3119, 3167, + 3161, 3281, 2599, + 0, 3433, 0, + 0, 3579, 0, + 0, 3723, 0, + 0, 3863, 0, + 0, 4001, 0, + 3997, 0, 3815, + 3997, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3813, + 3995, 0, 3813, + 3995, 0, 3813, + 3995, 0, 3813, + 3995, 0, 3813, + 3995, 0, 3813, + 3995, 0, 3813, + 3993, 0, 3811, + 3993, 0, 3811, + 3991, 0, 3809, + 3991, 0, 3807, + 3987, 0, 3805, + 3985, 0, 3801, + 3981, 0, 3797, + 3977, 0, 3791, + 3969, 0, 3783, + 3959, 0, 3773, + 3947, 0, 3757, + 3929, 1737, 3735, + 3903, 2341, 3705, + 3867, 2653, 3663, + 3815, 2883, 3597, + 3733, 3079, 3493, + 3593, 3251, 3299, + 3293, 3413, 2731, + 0, 3565, 0, + 0, 3711, 0, + 0, 3855, 0, + 0, 3995, 0, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3943, + 4095, 0, 3943, + 4095, 0, 3941, + 4095, 0, 3939, + 4095, 0, 3937, + 4095, 0, 3933, + 4095, 0, 3929, + 4095, 0, 3923, + 4095, 0, 3915, + 4091, 0, 3905, + 4079, 0, 3889, + 4061, 1869, 3867, + 4035, 2473, 3839, + 3999, 2785, 3795, + 3947, 3015, 3729, + 3865, 3211, 3625, + 3725, 3383, 3431, + 3425, 3545, 2863, + 0, 3697, 0, + 0, 3843, 0, + 0, 3987, 0, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4075, + 4095, 0, 4075, + 4095, 0, 4073, + 4095, 0, 4071, + 4095, 0, 4069, + 4095, 0, 4065, + 4095, 0, 4061, + 4095, 0, 4055, + 4095, 0, 4047, + 4095, 0, 4037, + 4095, 0, 4021, + 4095, 2001, 4001, + 4095, 2605, 3971, + 4095, 2917, 3927, + 4079, 3149, 3861, + 3997, 3343, 3757, + 3857, 3515, 3563, + 3557, 3677, 2995, + 0, 3829, 0, + 0, 3977, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2133, 4095, + 4095, 2737, 4095, + 4095, 3049, 4059, + 4095, 3281, 3993, + 4095, 3475, 3889, + 3989, 3649, 3695, + 3689, 3809, 3127, + 0, 3961, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2265, 4095, + 4095, 2869, 4095, + 4095, 3181, 4095, + 4095, 3413, 4095, + 4095, 3607, 4021, + 4095, 3781, 3827, + 3821, 3941, 3259, + 0, 0, 13, + 0, 54, 0, + 0, 186, 0, + 0, 318, 0, + 0, 450, 0, + 0, 582, 0, + 0, 714, 0, + 0, 846, 0, + 0, 978, 0, + 0, 1110, 0, + 0, 1242, 0, + 0, 1374, 0, + 0, 1506, 0, + 0, 1639, 0, + 0, 1771, 0, + 0, 1903, 0, + 0, 2035, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 258, 0, 216, + 36, 36, 36, + 0, 172, 0, + 0, 308, 0, + 0, 442, 0, + 0, 576, 0, + 0, 710, 0, + 0, 843, 0, + 0, 976, 0, + 0, 1108, 0, + 0, 1241, 0, + 0, 1373, 0, + 0, 1506, 0, + 0, 1638, 0, + 0, 1770, 0, + 0, 1903, 0, + 0, 2035, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 488, 0, 395, + 367, 11, 282, + 129, 154, 65, + 0, 294, 0, + 0, 432, 0, + 0, 569, 0, + 0, 704, 0, + 0, 839, 0, + 0, 973, 0, + 0, 1106, 0, + 0, 1239, 0, + 0, 1372, 0, + 0, 1505, 0, + 0, 1637, 0, + 0, 1770, 0, + 0, 1902, 0, + 0, 2034, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 681, 0, 560, + 606, 0, 484, + 481, 128, 357, + 230, 275, 101, + 0, 418, 0, + 0, 559, 0, + 0, 697, 0, + 0, 833, 0, + 0, 969, 0, + 0, 1103, 0, + 0, 1237, 0, + 0, 1370, 0, + 0, 1503, 0, + 0, 1636, 0, + 0, 1769, 0, + 0, 1902, 0, + 0, 2034, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 854, 0, 714, + 804, 0, 662, + 727, 91, 580, + 599, 249, 441, + 337, 399, 146, + 0, 544, 0, + 0, 686, 0, + 0, 826, 0, + 0, 963, 0, + 0, 1099, 0, + 0, 1234, 0, + 0, 1368, 0, + 0, 1502, 0, + 0, 1635, 0, + 0, 1768, 0, + 0, 1901, 0, + 0, 2033, 0, + 0, 2165, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1015, 0, 863, + 980, 0, 825, + 929, 36, 770, + 851, 210, 683, + 720, 372, 534, + 450, 525, 199, + 0, 672, 0, + 0, 815, 0, + 0, 955, 0, + 0, 1093, 0, + 0, 1229, 0, + 0, 1365, 0, + 0, 1499, 0, + 0, 1633, 0, + 0, 1767, 0, + 0, 1900, 0, + 0, 2033, 0, + 0, 2165, 0, + 0, 2297, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1167, 0, 1007, + 1142, 0, 980, + 1107, 0, 941, + 1056, 154, 883, + 977, 333, 793, + 844, 498, 634, + 567, 652, 262, + 0, 801, 0, + 0, 945, 0, + 0, 1085, 0, + 0, 1224, 0, + 0, 1361, 0, + 0, 1496, 0, + 0, 1631, 0, + 0, 1765, 0, + 0, 1899, 0, + 0, 2032, 0, + 0, 2165, 0, + 0, 2297, 0, + 0, 2429, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1313, 0, 1147, + 1296, 0, 1128, + 1271, 0, 1100, + 1236, 65, 1060, + 1184, 275, 1001, + 1104, 458, 907, + 969, 625, 741, + 687, 781, 334, + 0, 930, 0, + 0, 1075, 0, + 0, 1216, 0, + 0, 1355, 0, + 0, 1492, 0, + 0, 1628, 0, + 0, 1763, 0, + 0, 1897, 0, + 0, 2030, 0, + 0, 2163, 0, + 0, 2297, 0, + 0, 2429, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1456, 0, 1286, + 1443, 0, 1271, + 1425, 0, 1251, + 1401, 0, 1223, + 1365, 184, 1182, + 1313, 399, 1122, + 1233, 584, 1025, + 1097, 753, 853, + 810, 910, 416, + 0, 1060, 0, + 0, 1206, 0, + 0, 1347, 0, + 0, 1486, 0, + 0, 1624, 0, + 0, 1760, 0, + 0, 1894, 0, + 0, 2029, 0, + 0, 2163, 0, + 0, 2295, 0, + 0, 2429, 0, + 0, 2561, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1596, 0, 1422, + 1586, 0, 1412, + 1574, 0, 1397, + 1556, 0, 1377, + 1531, 23, 1348, + 1495, 306, 1307, + 1443, 525, 1245, + 1362, 712, 1147, + 1225, 882, 969, + 936, 1040, 506, + 0, 1191, 0, + 0, 1337, 0, + 0, 1479, 0, + 0, 1618, 0, + 0, 1755, 0, + 0, 1891, 0, + 0, 2026, 0, + 0, 2161, 0, + 0, 2295, 0, + 0, 2427, 0, + 0, 2561, 0, + 0, 2693, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1734, 0, 1558, + 1727, 0, 1550, + 1717, 0, 1539, + 1704, 0, 1525, + 1687, 0, 1504, + 1662, 141, 1475, + 1626, 430, 1434, + 1574, 652, 1371, + 1492, 841, 1271, + 1354, 1012, 1089, + 1063, 1171, 604, + 0, 1322, 0, + 0, 1468, 0, + 0, 1610, 0, + 0, 1750, 0, + 0, 1887, 0, + 0, 2023, 0, + 0, 2159, 0, + 0, 2293, 0, + 0, 2427, 0, + 0, 2559, 0, + 0, 2693, 0, + 0, 2825, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1870, 0, 1693, + 1865, 0, 1687, + 1858, 0, 1679, + 1848, 0, 1668, + 1836, 0, 1653, + 1818, 0, 1633, + 1793, 262, 1604, + 1757, 556, 1561, + 1704, 781, 1498, + 1623, 971, 1397, + 1485, 1142, 1212, + 1191, 1302, 709, + 0, 1453, 0, + 0, 1599, 0, + 0, 1742, 0, + 0, 1881, 0, + 0, 2019, 0, + 0, 2155, 0, + 0, 2291, 0, + 0, 2425, 0, + 0, 2559, 0, + 0, 2691, 0, + 0, 2825, 0, + 0, 2957, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2005, 0, 1827, + 2001, 0, 1822, + 1996, 0, 1817, + 1989, 0, 1809, + 1980, 0, 1798, + 1967, 0, 1783, + 1949, 0, 1762, + 1924, 386, 1733, + 1888, 684, 1690, + 1836, 910, 1627, + 1754, 1101, 1524, + 1615, 1273, 1337, + 1320, 1433, 819, + 0, 1585, 0, + 0, 1731, 0, + 0, 1874, 0, + 0, 2013, 0, + 0, 2151, 0, + 0, 2287, 0, + 0, 2423, 0, + 0, 2557, 0, + 0, 2691, 0, + 0, 2823, 0, + 0, 2957, 0, + 0, 3089, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2139, 0, 1960, + 2137, 0, 1957, + 2133, 0, 1953, + 2127, 0, 1947, + 2121, 0, 1939, + 2111, 0, 1928, + 2099, 0, 1913, + 2081, 0, 1892, + 2055, 511, 1863, + 2020, 813, 1820, + 1967, 1040, 1756, + 1885, 1232, 1653, + 1746, 1405, 1464, + 1450, 1565, 935, + 0, 1717, 0, + 0, 1863, 0, + 0, 2005, 0, + 0, 2145, 0, + 0, 2283, 0, + 0, 2419, 0, + 0, 2555, 0, + 0, 2689, 0, + 0, 2823, 0, + 0, 2957, 0, + 0, 3089, 0, + 0, 3221, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3885, 0, + 0, 4017, 0, + 2273, 0, 2093, + 2271, 0, 2091, + 2269, 0, 2087, + 2265, 0, 2083, + 2259, 0, 2077, + 2253, 0, 2069, + 2243, 0, 2059, + 2231, 0, 2044, + 2213, 72, 2023, + 2187, 638, 1993, + 2151, 943, 1950, + 2099, 1171, 1886, + 2017, 1363, 1783, + 1877, 1536, 1592, + 1580, 1696, 1054, + 0, 1848, 0, + 0, 1995, 0, + 0, 2137, 0, + 0, 2277, 0, + 0, 2415, 0, + 0, 2551, 0, + 0, 2687, 0, + 0, 2821, 0, + 0, 2955, 0, + 0, 3089, 0, + 0, 3221, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3885, 0, + 0, 4017, 0, + 2407, 0, 2227, + 2405, 0, 2225, + 2403, 0, 2223, + 2401, 0, 2219, + 2397, 0, 2215, + 2391, 0, 2209, + 2385, 0, 2201, + 2375, 0, 2189, + 2363, 0, 2175, + 2345, 192, 2153, + 2319, 767, 2125, + 2283, 1073, 2081, + 2231, 1302, 2017, + 2149, 1495, 1913, + 2009, 1668, 1722, + 1711, 1828, 1176, + 0, 1980, 0, + 0, 2127, 0, + 0, 2269, 0, + 0, 2409, 0, + 0, 2547, 0, + 0, 2683, 0, + 0, 2819, 0, + 0, 2953, 0, + 0, 3087, 0, + 0, 3221, 0, + 0, 3353, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4017, 0, + 2539, 0, 2359, + 2539, 0, 2357, + 2537, 0, 2357, + 2535, 0, 2353, + 2533, 0, 2351, + 2529, 0, 2345, + 2523, 0, 2341, + 2517, 0, 2333, + 2507, 0, 2321, + 2495, 0, 2305, + 2477, 314, 2285, + 2451, 896, 2255, + 2415, 1203, 2213, + 2363, 1433, 2147, + 2281, 1626, 2043, + 2141, 1799, 1851, + 1842, 1960, 1301, + 0, 2113, 0, + 0, 2259, 0, + 0, 2401, 0, + 0, 2541, 0, + 0, 2679, 0, + 0, 2815, 0, + 0, 2951, 0, + 0, 3085, 0, + 0, 3219, 0, + 0, 3353, 0, + 0, 3485, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 2673, 0, 2491, + 2671, 0, 2491, + 2671, 0, 2489, + 2669, 0, 2487, + 2667, 0, 2485, + 2665, 0, 2481, + 2661, 0, 2477, + 2655, 0, 2471, + 2649, 0, 2463, + 2639, 0, 2453, + 2627, 0, 2437, + 2609, 438, 2417, + 2583, 1026, 2387, + 2547, 1334, 2343, + 2495, 1564, 2279, + 2413, 1758, 2175, + 2273, 1931, 1982, + 1974, 2091, 1427, + 0, 2245, 0, + 0, 2391, 0, + 0, 2533, 0, + 0, 2673, 0, + 0, 2811, 0, + 0, 2947, 0, + 0, 3083, 0, + 0, 3217, 0, + 0, 3351, 0, + 0, 3485, 0, + 0, 3617, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 2805, 0, 2625, + 2805, 0, 2623, + 2803, 0, 2623, + 2803, 0, 2621, + 2801, 0, 2619, + 2799, 0, 2617, + 2797, 0, 2613, + 2793, 0, 2609, + 2787, 0, 2603, + 2781, 0, 2595, + 2771, 0, 2585, + 2759, 0, 2569, + 2741, 565, 2549, + 2715, 1157, 2519, + 2679, 1466, 2475, + 2627, 1696, 2411, + 2543, 1890, 2305, + 2405, 2063, 2113, + 2105, 2223, 1555, + 0, 2377, 0, + 0, 2523, 0, + 0, 2665, 0, + 0, 2805, 0, + 0, 2943, 0, + 0, 3079, 0, + 0, 3215, 0, + 0, 3349, 0, + 0, 3483, 0, + 0, 3617, 0, + 0, 3749, 0, + 0, 3883, 0, + 0, 4015, 0, + 2937, 0, 2757, + 2937, 0, 2755, + 2937, 0, 2755, + 2935, 0, 2755, + 2935, 0, 2753, + 2933, 0, 2751, + 2931, 0, 2749, + 2929, 0, 2745, + 2925, 0, 2741, + 2919, 0, 2735, + 2913, 0, 2727, + 2903, 0, 2717, + 2891, 0, 2701, + 2873, 693, 2679, + 2847, 1288, 2651, + 2811, 1597, 2607, + 2759, 1828, 2541, + 2675, 2022, 2437, + 2537, 2195, 2243, + 2237, 2355, 1684, + 0, 2509, 0, + 0, 2655, 0, + 0, 2797, 0, + 0, 2937, 0, + 0, 3075, 0, + 0, 3211, 0, + 0, 3347, 0, + 0, 3481, 0, + 0, 3615, 0, + 0, 3749, 0, + 0, 3881, 0, + 0, 4015, 0, + 3071, 0, 2889, + 3071, 0, 2889, + 3069, 0, 2887, + 3069, 0, 2887, + 3069, 0, 2887, + 3067, 0, 2885, + 3065, 0, 2883, + 3063, 0, 2881, + 3061, 0, 2877, + 3057, 0, 2873, + 3051, 0, 2867, + 3045, 0, 2859, + 3035, 0, 2847, + 3023, 0, 2833, + 3005, 821, 2811, + 2979, 1419, 2781, + 2943, 1729, 2739, + 2891, 1960, 2673, + 2807, 2153, 2569, + 2669, 2327, 2375, + 2369, 2487, 1813, + 0, 2641, 0, + 0, 2787, 0, + 0, 2929, 0, + 0, 3069, 0, + 0, 3207, 0, + 0, 3343, 0, + 0, 3479, 0, + 0, 3613, 0, + 0, 3747, 0, + 0, 3881, 0, + 0, 4015, 0, + 3203, 0, 3021, + 3203, 0, 3021, + 3203, 0, 3021, + 3201, 0, 3019, + 3201, 0, 3019, + 3201, 0, 3019, + 3199, 0, 3017, + 3197, 0, 3015, + 3195, 0, 3013, + 3193, 0, 3009, + 3189, 0, 3005, + 3183, 0, 2999, + 3177, 0, 2991, + 3167, 0, 2979, + 3155, 0, 2965, + 3137, 951, 2943, + 3111, 1550, 2913, + 3075, 1861, 2871, + 3023, 2091, 2805, + 2941, 2285, 2701, + 2801, 2459, 2507, + 2501, 2619, 1944, + 0, 2773, 0, + 0, 2919, 0, + 0, 3061, 0, + 0, 3201, 0, + 0, 3339, 0, + 0, 3477, 0, + 0, 3611, 0, + 0, 3745, 0, + 0, 3879, 0, + 0, 4013, 0, + 3335, 0, 3153, + 3335, 0, 3153, + 3335, 0, 3153, + 3335, 0, 3153, + 3333, 0, 3151, + 3333, 0, 3151, + 3333, 0, 3151, + 3331, 0, 3149, + 3329, 0, 3147, + 3327, 0, 3145, + 3325, 0, 3141, + 3321, 0, 3137, + 3315, 0, 3131, + 3309, 0, 3123, + 3299, 0, 3111, + 3287, 0, 3097, + 3269, 1081, 3075, + 3243, 1682, 3045, + 3207, 1993, 3003, + 3155, 2223, 2937, + 3073, 2417, 2833, + 2933, 2591, 2639, + 2633, 2753, 2075, + 0, 2905, 0, + 0, 3051, 0, + 0, 3193, 0, + 0, 3333, 0, + 0, 3471, 0, + 0, 3609, 0, + 0, 3743, 0, + 0, 3877, 0, + 0, 4011, 0, + 3467, 0, 3285, + 3467, 0, 3285, + 3467, 0, 3285, + 3467, 0, 3285, + 3467, 0, 3285, + 3465, 0, 3283, + 3465, 0, 3283, + 3465, 0, 3283, + 3463, 0, 3281, + 3461, 0, 3279, + 3459, 0, 3277, + 3457, 0, 3273, + 3453, 0, 3269, + 3447, 0, 3263, + 3441, 0, 3255, + 3431, 0, 3243, + 3419, 0, 3229, + 3401, 1212, 3207, + 3375, 1814, 3177, + 3339, 2125, 3135, + 3287, 2355, 3069, + 3205, 2549, 2965, + 3065, 2723, 2771, + 2765, 2885, 2205, + 0, 3037, 0, + 0, 3183, 0, + 0, 3327, 0, + 0, 3467, 0, + 0, 3603, 0, + 0, 3741, 0, + 0, 3875, 0, + 0, 4009, 0, + 3599, 0, 3417, + 3599, 0, 3417, + 3599, 0, 3417, + 3599, 0, 3417, + 3599, 0, 3417, + 3599, 0, 3417, + 3597, 0, 3415, + 3597, 0, 3415, + 3597, 0, 3415, + 3595, 0, 3413, + 3593, 0, 3411, + 3591, 0, 3409, + 3589, 0, 3405, + 3585, 0, 3401, + 3579, 0, 3395, + 3573, 0, 3387, + 3563, 0, 3375, + 3551, 0, 3361, + 3533, 1343, 3339, + 3507, 1946, 3309, + 3471, 2257, 3267, + 3419, 2487, 3201, + 3337, 2681, 3097, + 3197, 2855, 2903, + 2897, 3017, 2337, + 0, 3169, 0, + 0, 3315, 0, + 0, 3459, 0, + 0, 3599, 0, + 0, 3735, 0, + 0, 3873, 0, + 0, 4007, 0, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3729, 0, 3547, + 3729, 0, 3547, + 3727, 0, 3545, + 3725, 0, 3543, + 3723, 0, 3541, + 3721, 0, 3537, + 3717, 0, 3533, + 3711, 0, 3527, + 3705, 0, 3519, + 3695, 0, 3507, + 3683, 0, 3493, + 3665, 1474, 3471, + 3639, 2077, 3441, + 3603, 2389, 3399, + 3551, 2619, 3333, + 3469, 2813, 3229, + 3329, 2987, 3035, + 3029, 3149, 2469, + 0, 3301, 0, + 0, 3447, 0, + 0, 3591, 0, + 0, 3731, 0, + 0, 3869, 0, + 0, 4005, 0, + 3863, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3861, 0, 3679, + 3861, 0, 3679, + 3859, 0, 3677, + 3857, 0, 3675, + 3855, 0, 3673, + 3853, 0, 3669, + 3849, 0, 3665, + 3845, 0, 3659, + 3837, 0, 3651, + 3827, 0, 3641, + 3815, 0, 3625, + 3797, 1606, 3603, + 3771, 2209, 3573, + 3735, 2521, 3531, + 3683, 2751, 3465, + 3601, 2947, 3361, + 3461, 3119, 3167, + 3161, 3281, 2601, + 0, 3433, 0, + 0, 3579, 0, + 0, 3723, 0, + 0, 3863, 0, + 0, 4001, 0, + 3997, 0, 3815, + 3997, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3813, + 3995, 0, 3813, + 3995, 0, 3813, + 3995, 0, 3813, + 3995, 0, 3813, + 3995, 0, 3813, + 3993, 0, 3811, + 3993, 0, 3811, + 3991, 0, 3809, + 3991, 0, 3807, + 3987, 0, 3805, + 3985, 0, 3801, + 3981, 0, 3797, + 3977, 0, 3791, + 3969, 0, 3783, + 3959, 0, 3773, + 3947, 0, 3757, + 3929, 1738, 3735, + 3903, 2341, 3707, + 3867, 2653, 3663, + 3815, 2883, 3597, + 3733, 3079, 3493, + 3593, 3251, 3299, + 3293, 3413, 2731, + 0, 3565, 0, + 0, 3711, 0, + 0, 3855, 0, + 0, 3995, 0, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3943, + 4095, 0, 3943, + 4095, 0, 3941, + 4095, 0, 3939, + 4095, 0, 3937, + 4095, 0, 3933, + 4095, 0, 3929, + 4095, 0, 3923, + 4095, 0, 3915, + 4091, 0, 3905, + 4079, 0, 3889, + 4061, 1869, 3867, + 4035, 2473, 3839, + 3999, 2785, 3795, + 3947, 3015, 3729, + 3865, 3211, 3625, + 3725, 3383, 3431, + 3425, 3545, 2863, + 0, 3697, 0, + 0, 3843, 0, + 0, 3987, 0, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4075, + 4095, 0, 4075, + 4095, 0, 4073, + 4095, 0, 4071, + 4095, 0, 4069, + 4095, 0, 4065, + 4095, 0, 4061, + 4095, 0, 4055, + 4095, 0, 4047, + 4095, 0, 4037, + 4095, 0, 4021, + 4095, 2001, 4001, + 4095, 2605, 3971, + 4095, 2917, 3927, + 4079, 3149, 3861, + 3997, 3343, 3757, + 3857, 3515, 3563, + 3557, 3677, 2995, + 0, 3829, 0, + 0, 3977, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2133, 4095, + 4095, 2737, 4095, + 4095, 3049, 4059, + 4095, 3281, 3993, + 4095, 3475, 3889, + 3989, 3649, 3695, + 3689, 3809, 3127, + 0, 3961, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2265, 4095, + 4095, 2869, 4095, + 4095, 3181, 4095, + 4095, 3413, 4095, + 4095, 3607, 4021, + 4095, 3781, 3827, + 3821, 3941, 3259, + 7, 0, 127, + 0, 71, 0, + 0, 199, 0, + 0, 328, 0, + 0, 457, 0, + 0, 587, 0, + 0, 718, 0, + 0, 849, 0, + 0, 980, 0, + 0, 1112, 0, + 0, 1243, 0, + 0, 1375, 0, + 0, 1507, 0, + 0, 1639, 0, + 0, 1771, 0, + 0, 1903, 0, + 0, 2035, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 287, 0, 292, + 83, 54, 145, + 0, 186, 0, + 0, 318, 0, + 0, 450, 0, + 0, 582, 0, + 0, 714, 0, + 0, 846, 0, + 0, 978, 0, + 0, 1110, 0, + 0, 1242, 0, + 0, 1374, 0, + 0, 1506, 0, + 0, 1639, 0, + 0, 1771, 0, + 0, 1903, 0, + 0, 2035, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 506, 0, 448, + 390, 30, 348, + 168, 168, 168, + 0, 304, 0, + 0, 440, 0, + 0, 574, 0, + 0, 708, 0, + 0, 842, 0, + 0, 975, 0, + 0, 1108, 0, + 0, 1240, 0, + 0, 1373, 0, + 0, 1505, 0, + 0, 1638, 0, + 0, 1770, 0, + 0, 1902, 0, + 0, 2035, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 693, 0, 597, + 620, 0, 527, + 499, 143, 414, + 261, 286, 197, + 0, 426, 0, + 0, 564, 0, + 0, 701, 0, + 0, 836, 0, + 0, 971, 0, + 0, 1105, 0, + 0, 1238, 0, + 0, 1371, 0, + 0, 1504, 0, + 0, 1637, 0, + 0, 1769, 0, + 0, 1902, 0, + 0, 2034, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 862, 0, 741, + 813, 0, 692, + 738, 107, 616, + 613, 260, 489, + 362, 407, 233, + 0, 550, 0, + 0, 691, 0, + 0, 829, 0, + 0, 965, 0, + 0, 1100, 0, + 0, 1235, 0, + 0, 1369, 0, + 0, 1502, 0, + 0, 1636, 0, + 0, 1768, 0, + 0, 1901, 0, + 0, 2034, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1020, 0, 882, + 986, 0, 846, + 936, 54, 794, + 859, 223, 712, + 731, 381, 573, + 469, 531, 278, + 0, 677, 0, + 0, 818, 0, + 0, 958, 0, + 0, 1095, 0, + 0, 1231, 0, + 0, 1366, 0, + 0, 1500, 0, + 0, 1634, 0, + 0, 1767, 0, + 0, 1900, 0, + 0, 2033, 0, + 0, 2165, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1171, 0, 1021, + 1146, 0, 995, + 1112, 0, 957, + 1061, 168, 902, + 983, 343, 815, + 852, 504, 666, + 582, 657, 331, + 0, 804, 0, + 0, 947, 0, + 0, 1087, 0, + 0, 1225, 0, + 0, 1362, 0, + 0, 1497, 0, + 0, 1632, 0, + 0, 1765, 0, + 0, 1899, 0, + 0, 2032, 0, + 0, 2165, 0, + 0, 2297, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1316, 0, 1158, + 1299, 0, 1139, + 1274, 0, 1112, + 1239, 82, 1073, + 1188, 286, 1015, + 1109, 465, 925, + 976, 630, 766, + 699, 784, 394, + 0, 933, 0, + 0, 1077, 0, + 0, 1217, 0, + 0, 1356, 0, + 0, 1493, 0, + 0, 1628, 0, + 0, 1763, 0, + 0, 1897, 0, + 0, 2031, 0, + 0, 2163, 0, + 0, 2297, 0, + 0, 2429, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1458, 0, 1293, + 1445, 0, 1279, + 1428, 0, 1260, + 1403, 0, 1232, + 1368, 197, 1192, + 1316, 407, 1133, + 1236, 590, 1039, + 1101, 757, 873, + 819, 913, 466, + 0, 1062, 0, + 0, 1207, 0, + 0, 1348, 0, + 0, 1487, 0, + 0, 1624, 0, + 0, 1760, 0, + 0, 1895, 0, + 0, 2029, 0, + 0, 2163, 0, + 0, 2295, 0, + 0, 2429, 0, + 0, 2561, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1597, 0, 1428, + 1588, 0, 1418, + 1575, 0, 1403, + 1558, 0, 1383, + 1533, 42, 1355, + 1497, 316, 1315, + 1445, 531, 1254, + 1365, 717, 1157, + 1229, 885, 985, + 943, 1042, 548, + 0, 1192, 0, + 0, 1338, 0, + 0, 1479, 0, + 0, 1618, 0, + 0, 1756, 0, + 0, 1892, 0, + 0, 2027, 0, + 0, 2161, 0, + 0, 2295, 0, + 0, 2427, 0, + 0, 2561, 0, + 0, 2693, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1735, 0, 1562, + 1728, 0, 1555, + 1718, 0, 1544, + 1706, 0, 1529, + 1688, 0, 1509, + 1663, 155, 1480, + 1628, 438, 1439, + 1575, 657, 1377, + 1494, 845, 1279, + 1357, 1014, 1101, + 1068, 1172, 638, + 0, 1323, 0, + 0, 1469, 0, + 0, 1611, 0, + 0, 1750, 0, + 0, 1887, 0, + 0, 2023, 0, + 0, 2159, 0, + 0, 2293, 0, + 0, 2427, 0, + 0, 2559, 0, + 0, 2693, 0, + 0, 2825, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1871, 0, 1696, + 1866, 0, 1690, + 1859, 0, 1682, + 1849, 0, 1672, + 1837, 0, 1657, + 1819, 0, 1636, + 1794, 273, 1607, + 1758, 562, 1566, + 1706, 784, 1503, + 1624, 974, 1403, + 1487, 1144, 1221, + 1195, 1303, 736, + 0, 1454, 0, + 0, 1600, 0, + 0, 1742, 0, + 0, 1882, 0, + 0, 2019, 0, + 0, 2155, 0, + 0, 2291, 0, + 0, 2425, 0, + 0, 2559, 0, + 0, 2691, 0, + 0, 2825, 0, + 0, 2957, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2006, 0, 1829, + 2002, 0, 1825, + 1997, 0, 1819, + 1990, 0, 1811, + 1981, 0, 1800, + 1968, 0, 1785, + 1950, 0, 1765, + 1925, 394, 1736, + 1889, 689, 1694, + 1837, 913, 1630, + 1755, 1103, 1529, + 1617, 1275, 1344, + 1323, 1434, 841, + 0, 1585, 0, + 0, 1732, 0, + 0, 1874, 0, + 0, 2013, 0, + 0, 2151, 0, + 0, 2287, 0, + 0, 2423, 0, + 0, 2557, 0, + 0, 2691, 0, + 0, 2825, 0, + 0, 2957, 0, + 0, 3089, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2141, 0, 1962, + 2137, 0, 1959, + 2133, 0, 1955, + 2129, 0, 1949, + 2121, 0, 1941, + 2113, 0, 1930, + 2099, 0, 1915, + 2081, 0, 1894, + 2057, 518, 1865, + 2020, 816, 1822, + 1968, 1042, 1759, + 1886, 1234, 1657, + 1747, 1405, 1470, + 1452, 1565, 952, + 0, 1717, 0, + 0, 1863, 0, + 0, 2006, 0, + 0, 2145, 0, + 0, 2283, 0, + 0, 2419, 0, + 0, 2555, 0, + 0, 2689, 0, + 0, 2823, 0, + 0, 2957, 0, + 0, 3089, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3885, 0, + 0, 4017, 0, + 2273, 0, 2095, + 2271, 0, 2093, + 2269, 0, 2089, + 2265, 0, 2085, + 2259, 0, 2079, + 2253, 0, 2071, + 2243, 0, 2061, + 2231, 0, 2045, + 2213, 89, 2024, + 2187, 643, 1995, + 2151, 945, 1952, + 2099, 1172, 1888, + 2017, 1364, 1785, + 1878, 1537, 1596, + 1582, 1697, 1067, + 0, 1849, 0, + 0, 1995, 0, + 0, 2137, 0, + 0, 2277, 0, + 0, 2415, 0, + 0, 2551, 0, + 0, 2687, 0, + 0, 2821, 0, + 0, 2955, 0, + 0, 3089, 0, + 0, 3221, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3885, 0, + 0, 4017, 0, + 2407, 0, 2227, + 2405, 0, 2225, + 2403, 0, 2223, + 2401, 0, 2219, + 2397, 0, 2215, + 2391, 0, 2209, + 2385, 0, 2201, + 2375, 0, 2191, + 2363, 0, 2175, + 2345, 205, 2155, + 2319, 771, 2125, + 2283, 1074, 2083, + 2231, 1303, 2018, + 2149, 1495, 1915, + 2010, 1668, 1725, + 1713, 1828, 1186, + 0, 1980, 0, + 0, 2127, 0, + 0, 2269, 0, + 0, 2409, 0, + 0, 2547, 0, + 0, 2683, 0, + 0, 2819, 0, + 0, 2953, 0, + 0, 3087, 0, + 0, 3221, 0, + 0, 3353, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4017, 0, + 2541, 0, 2359, + 2539, 0, 2359, + 2537, 0, 2357, + 2535, 0, 2355, + 2533, 0, 2351, + 2529, 0, 2347, + 2523, 0, 2341, + 2517, 0, 2333, + 2507, 0, 2321, + 2495, 0, 2307, + 2477, 324, 2285, + 2451, 899, 2257, + 2415, 1205, 2213, + 2363, 1434, 2149, + 2281, 1627, 2045, + 2141, 1800, 1854, + 1843, 1960, 1308, + 0, 2113, 0, + 0, 2259, 0, + 0, 2401, 0, + 0, 2541, 0, + 0, 2679, 0, + 0, 2815, 0, + 0, 2951, 0, + 0, 3085, 0, + 0, 3219, 0, + 0, 3353, 0, + 0, 3485, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 2673, 0, 2493, + 2673, 0, 2491, + 2671, 0, 2489, + 2669, 0, 2489, + 2667, 0, 2485, + 2665, 0, 2483, + 2661, 0, 2479, + 2655, 0, 2473, + 2649, 0, 2465, + 2639, 0, 2453, + 2627, 0, 2439, + 2609, 446, 2417, + 2583, 1028, 2387, + 2547, 1335, 2345, + 2495, 1565, 2279, + 2413, 1758, 2175, + 2273, 1932, 1984, + 1975, 2093, 1433, + 0, 2245, 0, + 0, 2391, 0, + 0, 2533, 0, + 0, 2673, 0, + 0, 2811, 0, + 0, 2947, 0, + 0, 3083, 0, + 0, 3217, 0, + 0, 3351, 0, + 0, 3485, 0, + 0, 3617, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 2805, 0, 2625, + 2805, 0, 2623, + 2805, 0, 2623, + 2803, 0, 2621, + 2801, 0, 2619, + 2799, 0, 2617, + 2797, 0, 2615, + 2793, 0, 2609, + 2787, 0, 2603, + 2781, 0, 2595, + 2771, 0, 2585, + 2759, 0, 2569, + 2741, 570, 2549, + 2715, 1158, 2519, + 2679, 1467, 2475, + 2627, 1697, 2411, + 2545, 1890, 2307, + 2405, 2063, 2113, + 2107, 2223, 1559, + 0, 2377, 0, + 0, 2523, 0, + 0, 2665, 0, + 0, 2805, 0, + 0, 2943, 0, + 0, 3079, 0, + 0, 3215, 0, + 0, 3349, 0, + 0, 3483, 0, + 0, 3617, 0, + 0, 3749, 0, + 0, 3883, 0, + 0, 4015, 0, + 2939, 0, 2757, + 2937, 0, 2757, + 2937, 0, 2755, + 2937, 0, 2755, + 2935, 0, 2753, + 2933, 0, 2751, + 2931, 0, 2749, + 2929, 0, 2745, + 2925, 0, 2741, + 2919, 0, 2735, + 2913, 0, 2727, + 2903, 0, 2717, + 2891, 0, 2701, + 2873, 697, 2681, + 2847, 1289, 2651, + 2811, 1598, 2607, + 2759, 1828, 2543, + 2677, 2022, 2437, + 2537, 2195, 2245, + 2237, 2355, 1687, + 0, 2509, 0, + 0, 2655, 0, + 0, 2797, 0, + 0, 2937, 0, + 0, 3075, 0, + 0, 3211, 0, + 0, 3347, 0, + 0, 3481, 0, + 0, 3615, 0, + 0, 3749, 0, + 0, 3881, 0, + 0, 4015, 0, + 3071, 0, 2889, + 3071, 0, 2889, + 3069, 0, 2889, + 3069, 0, 2887, + 3069, 0, 2887, + 3067, 0, 2885, + 3065, 0, 2883, + 3063, 0, 2881, + 3061, 0, 2877, + 3057, 0, 2873, + 3051, 0, 2867, + 3045, 0, 2859, + 3035, 0, 2849, + 3023, 0, 2833, + 3005, 825, 2811, + 2979, 1420, 2783, + 2943, 1729, 2739, + 2891, 1960, 2673, + 2809, 2153, 2569, + 2669, 2327, 2377, + 2369, 2487, 1816, + 0, 2641, 0, + 0, 2787, 0, + 0, 2929, 0, + 0, 3069, 0, + 0, 3207, 0, + 0, 3343, 0, + 0, 3479, 0, + 0, 3613, 0, + 0, 3747, 0, + 0, 3881, 0, + 0, 4015, 0, + 3203, 0, 3021, + 3203, 0, 3021, + 3203, 0, 3021, + 3201, 0, 3021, + 3201, 0, 3019, + 3201, 0, 3019, + 3199, 0, 3017, + 3197, 0, 3015, + 3195, 0, 3013, + 3193, 0, 3009, + 3189, 0, 3005, + 3183, 0, 2999, + 3177, 0, 2991, + 3167, 0, 2981, + 3155, 0, 2965, + 3137, 954, 2943, + 3111, 1551, 2913, + 3075, 1861, 2871, + 3023, 2091, 2805, + 2941, 2285, 2701, + 2801, 2459, 2507, + 2501, 2621, 1945, + 0, 2773, 0, + 0, 2919, 0, + 0, 3061, 0, + 0, 3201, 0, + 0, 3339, 0, + 0, 3477, 0, + 0, 3611, 0, + 0, 3745, 0, + 0, 3879, 0, + 0, 4013, 0, + 3335, 0, 3153, + 3335, 0, 3153, + 3335, 0, 3153, + 3335, 0, 3153, + 3333, 0, 3151, + 3333, 0, 3151, + 3333, 0, 3151, + 3331, 0, 3149, + 3329, 0, 3147, + 3327, 0, 3145, + 3325, 0, 3141, + 3321, 0, 3137, + 3315, 0, 3131, + 3309, 0, 3123, + 3299, 0, 3111, + 3287, 0, 3097, + 3269, 1083, 3075, + 3243, 1682, 3045, + 3207, 1993, 3003, + 3155, 2223, 2937, + 3073, 2417, 2833, + 2933, 2591, 2639, + 2633, 2753, 2075, + 0, 2905, 0, + 0, 3051, 0, + 0, 3193, 0, + 0, 3333, 0, + 0, 3471, 0, + 0, 3609, 0, + 0, 3743, 0, + 0, 3877, 0, + 0, 4011, 0, + 3467, 0, 3285, + 3467, 0, 3285, + 3467, 0, 3285, + 3467, 0, 3285, + 3467, 0, 3285, + 3465, 0, 3283, + 3465, 0, 3283, + 3465, 0, 3283, + 3463, 0, 3281, + 3461, 0, 3279, + 3459, 0, 3277, + 3457, 0, 3273, + 3453, 0, 3269, + 3447, 0, 3263, + 3441, 0, 3255, + 3431, 0, 3243, + 3419, 0, 3229, + 3401, 1213, 3207, + 3375, 1814, 3177, + 3339, 2125, 3135, + 3287, 2355, 3069, + 3205, 2549, 2965, + 3065, 2723, 2771, + 2765, 2885, 2207, + 0, 3037, 0, + 0, 3183, 0, + 0, 3327, 0, + 0, 3467, 0, + 0, 3603, 0, + 0, 3741, 0, + 0, 3875, 0, + 0, 4009, 0, + 3599, 0, 3417, + 3599, 0, 3417, + 3599, 0, 3417, + 3599, 0, 3417, + 3599, 0, 3417, + 3599, 0, 3417, + 3597, 0, 3417, + 3597, 0, 3415, + 3597, 0, 3415, + 3595, 0, 3413, + 3593, 0, 3411, + 3591, 0, 3409, + 3589, 0, 3405, + 3585, 0, 3401, + 3579, 0, 3395, + 3573, 0, 3387, + 3563, 0, 3377, + 3551, 0, 3361, + 3533, 1344, 3339, + 3507, 1946, 3309, + 3471, 2257, 3267, + 3419, 2487, 3201, + 3337, 2681, 3097, + 3197, 2855, 2903, + 2897, 3017, 2337, + 0, 3169, 0, + 0, 3315, 0, + 0, 3459, 0, + 0, 3599, 0, + 0, 3737, 0, + 0, 3873, 0, + 0, 4007, 0, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3729, 0, 3547, + 3729, 0, 3547, + 3727, 0, 3545, + 3725, 0, 3543, + 3723, 0, 3541, + 3721, 0, 3537, + 3717, 0, 3533, + 3711, 0, 3527, + 3705, 0, 3519, + 3695, 0, 3509, + 3683, 0, 3493, + 3665, 1475, 3471, + 3639, 2077, 3441, + 3603, 2389, 3399, + 3551, 2619, 3333, + 3469, 2813, 3229, + 3329, 2987, 3035, + 3029, 3149, 2469, + 0, 3301, 0, + 0, 3447, 0, + 0, 3591, 0, + 0, 3731, 0, + 0, 3869, 0, + 0, 4005, 0, + 3863, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3861, 0, 3679, + 3861, 0, 3679, + 3859, 0, 3677, + 3857, 0, 3675, + 3855, 0, 3673, + 3853, 0, 3669, + 3849, 0, 3665, + 3845, 0, 3659, + 3837, 0, 3651, + 3827, 0, 3641, + 3815, 0, 3625, + 3797, 1606, 3603, + 3771, 2209, 3573, + 3735, 2521, 3531, + 3683, 2751, 3465, + 3601, 2947, 3361, + 3461, 3119, 3167, + 3161, 3281, 2601, + 0, 3433, 0, + 0, 3579, 0, + 0, 3723, 0, + 0, 3863, 0, + 0, 4001, 0, + 3997, 0, 3815, + 3997, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3813, + 3995, 0, 3813, + 3995, 0, 3813, + 3995, 0, 3813, + 3995, 0, 3813, + 3995, 0, 3813, + 3993, 0, 3811, + 3993, 0, 3811, + 3991, 0, 3809, + 3991, 0, 3807, + 3987, 0, 3805, + 3985, 0, 3801, + 3981, 0, 3797, + 3977, 0, 3791, + 3969, 0, 3783, + 3959, 0, 3773, + 3947, 0, 3757, + 3929, 1738, 3735, + 3903, 2341, 3707, + 3867, 2653, 3663, + 3815, 2883, 3597, + 3733, 3079, 3493, + 3593, 3251, 3299, + 3293, 3413, 2733, + 0, 3565, 0, + 0, 3711, 0, + 0, 3855, 0, + 0, 3995, 0, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3943, + 4095, 0, 3943, + 4095, 0, 3941, + 4095, 0, 3939, + 4095, 0, 3937, + 4095, 0, 3933, + 4095, 0, 3929, + 4095, 0, 3923, + 4095, 0, 3915, + 4091, 0, 3905, + 4079, 0, 3889, + 4061, 1870, 3869, + 4035, 2473, 3839, + 3999, 2785, 3795, + 3947, 3017, 3729, + 3865, 3211, 3625, + 3725, 3383, 3431, + 3425, 3545, 2863, + 0, 3697, 0, + 0, 3843, 0, + 0, 3987, 0, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4075, + 4095, 0, 4075, + 4095, 0, 4073, + 4095, 0, 4071, + 4095, 0, 4069, + 4095, 0, 4065, + 4095, 0, 4061, + 4095, 0, 4055, + 4095, 0, 4047, + 4095, 0, 4037, + 4095, 0, 4021, + 4095, 2002, 4001, + 4095, 2605, 3971, + 4095, 2917, 3927, + 4079, 3149, 3861, + 3997, 3343, 3757, + 3857, 3515, 3563, + 3557, 3677, 2995, + 0, 3829, 0, + 0, 3977, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2133, 4095, + 4095, 2737, 4095, + 4095, 3049, 4059, + 4095, 3281, 3993, + 4095, 3475, 3889, + 3989, 3649, 3695, + 3689, 3809, 3127, + 0, 3961, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2265, 4095, + 4095, 2869, 4095, + 4095, 3181, 4095, + 4095, 3413, 4095, + 4095, 3607, 4021, + 4095, 3781, 3827, + 3821, 3941, 3259, + 73, 0, 245, + 0, 93, 78, + 0, 216, 0, + 0, 340, 0, + 0, 467, 0, + 0, 595, 0, + 0, 724, 0, + 0, 853, 0, + 0, 984, 0, + 0, 1114, 0, + 0, 1245, 0, + 0, 1377, 0, + 0, 1508, 0, + 0, 1640, 0, + 0, 1772, 0, + 0, 1904, 0, + 0, 2035, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 324, 0, 378, + 139, 77, 259, + 0, 203, 27, + 0, 331, 0, + 0, 460, 0, + 0, 589, 0, + 0, 719, 0, + 0, 850, 0, + 0, 981, 0, + 0, 1112, 0, + 0, 1244, 0, + 0, 1376, 0, + 0, 1507, 0, + 0, 1639, 0, + 0, 1771, 0, + 0, 1903, 0, + 0, 2035, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 528, 0, 510, + 420, 54, 424, + 215, 186, 277, + 0, 318, 0, + 0, 450, 0, + 0, 582, 0, + 0, 714, 0, + 0, 846, 0, + 0, 978, 0, + 0, 1110, 0, + 0, 1242, 0, + 0, 1374, 0, + 0, 1506, 0, + 0, 1639, 0, + 0, 1771, 0, + 0, 1903, 0, + 0, 2035, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 708, 0, 642, + 638, 21, 580, + 522, 162, 481, + 300, 300, 300, + 0, 437, 0, + 0, 572, 0, + 0, 707, 0, + 0, 841, 0, + 0, 974, 0, + 0, 1107, 0, + 0, 1240, 0, + 0, 1373, 0, + 0, 1505, 0, + 0, 1638, 0, + 0, 1770, 0, + 0, 1902, 0, + 0, 2035, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 873, 0, 775, + 825, 0, 729, + 752, 127, 659, + 631, 275, 546, + 393, 418, 329, + 0, 558, 0, + 0, 696, 0, + 0, 833, 0, + 0, 968, 0, + 0, 1103, 0, + 0, 1237, 0, + 0, 1370, 0, + 0, 1503, 0, + 0, 1636, 0, + 0, 1769, 0, + 0, 1902, 0, + 0, 2034, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1028, 0, 907, + 994, 0, 873, + 945, 77, 824, + 870, 239, 748, + 745, 392, 621, + 494, 539, 365, + 0, 683, 0, + 0, 823, 0, + 0, 961, 0, + 0, 1097, 0, + 0, 1233, 0, + 0, 1367, 0, + 0, 1501, 0, + 0, 1635, 0, + 0, 1768, 0, + 0, 1901, 0, + 0, 2033, 0, + 0, 2165, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1176, 0, 1039, + 1152, 0, 1014, + 1118, 0, 979, + 1068, 186, 926, + 991, 355, 844, + 863, 513, 705, + 601, 663, 410, + 0, 809, 0, + 0, 951, 0, + 0, 1090, 0, + 0, 1227, 0, + 0, 1363, 0, + 0, 1498, 0, + 0, 1632, 0, + 0, 1766, 0, + 0, 1899, 0, + 0, 2032, 0, + 0, 2165, 0, + 0, 2297, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1320, 0, 1171, + 1303, 0, 1153, + 1279, 0, 1127, + 1244, 103, 1089, + 1193, 300, 1034, + 1115, 475, 948, + 984, 636, 798, + 714, 789, 463, + 0, 936, 0, + 0, 1079, 0, + 0, 1219, 0, + 0, 1357, 0, + 0, 1494, 0, + 0, 1629, 0, + 0, 1764, 0, + 0, 1898, 0, + 0, 2031, 0, + 0, 2165, 0, + 0, 2297, 0, + 0, 2429, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1461, 0, 1304, + 1448, 0, 1290, + 1431, 0, 1271, + 1406, 0, 1244, + 1371, 214, 1205, + 1320, 418, 1147, + 1241, 597, 1057, + 1108, 762, 898, + 831, 917, 526, + 0, 1065, 0, + 0, 1209, 0, + 0, 1350, 0, + 0, 1488, 0, + 0, 1625, 0, + 0, 1760, 0, + 0, 1895, 0, + 0, 2029, 0, + 0, 2163, 0, + 0, 2297, 0, + 0, 2429, 0, + 0, 2561, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1599, 0, 1436, + 1590, 0, 1426, + 1577, 0, 1411, + 1560, 0, 1392, + 1535, 65, 1364, + 1500, 329, 1324, + 1448, 539, 1265, + 1368, 722, 1171, + 1233, 889, 1005, + 952, 1045, 598, + 0, 1194, 0, + 0, 1339, 0, + 0, 1480, 0, + 0, 1619, 0, + 0, 1756, 0, + 0, 1892, 0, + 0, 2027, 0, + 0, 2161, 0, + 0, 2295, 0, + 0, 2427, 0, + 0, 2561, 0, + 0, 2693, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1736, 0, 1568, + 1729, 0, 1560, + 1720, 0, 1550, + 1707, 0, 1535, + 1690, 0, 1515, + 1665, 174, 1487, + 1630, 448, 1447, + 1578, 663, 1386, + 1497, 849, 1289, + 1361, 1017, 1117, + 1074, 1174, 680, + 0, 1325, 0, + 0, 1470, 0, + 0, 1611, 0, + 0, 1751, 0, + 0, 1888, 0, + 0, 2024, 0, + 0, 2159, 0, + 0, 2293, 0, + 0, 2427, 0, + 0, 2559, 0, + 0, 2693, 0, + 0, 2825, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1872, 0, 1700, + 1867, 0, 1694, + 1860, 0, 1687, + 1851, 0, 1676, + 1838, 0, 1661, + 1820, 0, 1641, + 1795, 287, 1613, + 1760, 570, 1571, + 1707, 789, 1510, + 1627, 977, 1411, + 1489, 1146, 1233, + 1200, 1304, 770, + 0, 1455, 0, + 0, 1601, 0, + 0, 1743, 0, + 0, 1882, 0, + 0, 2020, 0, + 0, 2155, 0, + 0, 2291, 0, + 0, 2425, 0, + 0, 2559, 0, + 0, 2693, 0, + 0, 2825, 0, + 0, 2957, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2007, 0, 1832, + 2003, 0, 1828, + 1998, 0, 1822, + 1991, 0, 1814, + 1982, 0, 1804, + 1969, 0, 1789, + 1951, 0, 1768, + 1926, 405, 1740, + 1890, 694, 1698, + 1838, 916, 1635, + 1757, 1105, 1535, + 1619, 1276, 1354, + 1327, 1435, 868, + 0, 1586, 0, + 0, 1732, 0, + 0, 1874, 0, + 0, 2014, 0, + 0, 2151, 0, + 0, 2287, 0, + 0, 2423, 0, + 0, 2557, 0, + 0, 2691, 0, + 0, 2825, 0, + 0, 2957, 0, + 0, 3089, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2141, 0, 1964, + 2137, 0, 1961, + 2135, 0, 1957, + 2129, 0, 1951, + 2123, 0, 1943, + 2113, 0, 1932, + 2099, 0, 1918, + 2083, 6, 1897, + 2057, 526, 1868, + 2021, 821, 1826, + 1969, 1045, 1762, + 1887, 1235, 1661, + 1749, 1407, 1477, + 1455, 1566, 973, + 0, 1718, 0, + 0, 1864, 0, + 0, 2006, 0, + 0, 2145, 0, + 0, 2283, 0, + 0, 2419, 0, + 0, 2555, 0, + 0, 2689, 0, + 0, 2823, 0, + 0, 2957, 0, + 0, 3089, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3885, 0, + 0, 4017, 0, + 2275, 0, 2097, + 2273, 0, 2095, + 2269, 0, 2091, + 2265, 0, 2087, + 2261, 0, 2081, + 2253, 0, 2073, + 2245, 0, 2063, + 2231, 0, 2047, + 2213, 111, 2026, + 2189, 650, 1997, + 2153, 948, 1955, + 2099, 1174, 1891, + 2018, 1366, 1789, + 1879, 1538, 1602, + 1584, 1697, 1083, + 0, 1849, 0, + 0, 1995, 0, + 0, 2137, 0, + 0, 2277, 0, + 0, 2415, 0, + 0, 2551, 0, + 0, 2687, 0, + 0, 2821, 0, + 0, 2955, 0, + 0, 3089, 0, + 0, 3221, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3885, 0, + 0, 4017, 0, + 2407, 0, 2229, + 2405, 0, 2227, + 2403, 0, 2225, + 2401, 0, 2221, + 2397, 0, 2217, + 2393, 0, 2211, + 2385, 0, 2203, + 2375, 0, 2193, + 2363, 0, 2177, + 2345, 221, 2157, + 2319, 775, 2127, + 2285, 1077, 2085, + 2231, 1304, 2020, + 2149, 1496, 1917, + 2010, 1669, 1729, + 1714, 1829, 1199, + 0, 1981, 0, + 0, 2127, 0, + 0, 2269, 0, + 0, 2409, 0, + 0, 2547, 0, + 0, 2683, 0, + 0, 2819, 0, + 0, 2953, 0, + 0, 3087, 0, + 0, 3221, 0, + 0, 3353, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4017, 0, + 2541, 0, 2361, + 2539, 0, 2359, + 2537, 0, 2357, + 2535, 0, 2355, + 2533, 0, 2353, + 2529, 0, 2347, + 2523, 0, 2341, + 2517, 0, 2333, + 2507, 0, 2323, + 2495, 0, 2307, + 2477, 337, 2287, + 2451, 903, 2257, + 2415, 1207, 2215, + 2363, 1435, 2151, + 2281, 1628, 2047, + 2141, 1800, 1857, + 1845, 1961, 1318, + 0, 2113, 0, + 0, 2259, 0, + 0, 2401, 0, + 0, 2541, 0, + 0, 2679, 0, + 0, 2815, 0, + 0, 2951, 0, + 0, 3085, 0, + 0, 3219, 0, + 0, 3353, 0, + 0, 3485, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 2673, 0, 2493, + 2673, 0, 2493, + 2671, 0, 2491, + 2669, 0, 2489, + 2667, 0, 2487, + 2665, 0, 2483, + 2661, 0, 2479, + 2655, 0, 2473, + 2649, 0, 2465, + 2639, 0, 2453, + 2627, 0, 2439, + 2609, 456, 2417, + 2583, 1031, 2389, + 2547, 1337, 2345, + 2495, 1566, 2281, + 2413, 1759, 2177, + 2273, 1932, 1986, + 1976, 2093, 1440, + 0, 2245, 0, + 0, 2391, 0, + 0, 2533, 0, + 0, 2673, 0, + 0, 2811, 0, + 0, 2947, 0, + 0, 3083, 0, + 0, 3217, 0, + 0, 3351, 0, + 0, 3485, 0, + 0, 3617, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 2805, 0, 2625, + 2805, 0, 2625, + 2805, 0, 2623, + 2803, 0, 2623, + 2801, 0, 2621, + 2799, 0, 2617, + 2797, 0, 2615, + 2793, 0, 2611, + 2787, 0, 2605, + 2781, 0, 2597, + 2771, 0, 2585, + 2759, 0, 2571, + 2741, 578, 2549, + 2715, 1160, 2519, + 2679, 1468, 2477, + 2627, 1697, 2411, + 2545, 1891, 2307, + 2405, 2063, 2115, + 2107, 2225, 1565, + 0, 2377, 0, + 0, 2523, 0, + 0, 2665, 0, + 0, 2805, 0, + 0, 2943, 0, + 0, 3079, 0, + 0, 3215, 0, + 0, 3349, 0, + 0, 3483, 0, + 0, 3617, 0, + 0, 3749, 0, + 0, 3883, 0, + 0, 4015, 0, + 2939, 0, 2757, + 2937, 0, 2757, + 2937, 0, 2755, + 2937, 0, 2755, + 2935, 0, 2753, + 2933, 0, 2751, + 2931, 0, 2749, + 2929, 0, 2747, + 2925, 0, 2741, + 2919, 0, 2735, + 2913, 0, 2727, + 2903, 0, 2717, + 2891, 0, 2701, + 2873, 703, 2681, + 2847, 1290, 2651, + 2811, 1599, 2607, + 2759, 1829, 2543, + 2677, 2022, 2439, + 2537, 2195, 2247, + 2239, 2357, 1691, + 0, 2509, 0, + 0, 2655, 0, + 0, 2797, 0, + 0, 2937, 0, + 0, 3075, 0, + 0, 3211, 0, + 0, 3347, 0, + 0, 3481, 0, + 0, 3615, 0, + 0, 3749, 0, + 0, 3881, 0, + 0, 4015, 0, + 3071, 0, 2889, + 3071, 0, 2889, + 3069, 0, 2889, + 3069, 0, 2887, + 3069, 0, 2887, + 3067, 0, 2885, + 3065, 0, 2883, + 3063, 0, 2881, + 3061, 0, 2877, + 3057, 0, 2873, + 3051, 0, 2867, + 3045, 0, 2859, + 3035, 0, 2849, + 3023, 0, 2833, + 3005, 829, 2813, + 2979, 1421, 2783, + 2943, 1730, 2739, + 2891, 1960, 2675, + 2809, 2155, 2569, + 2669, 2327, 2377, + 2369, 2489, 1819, + 0, 2641, 0, + 0, 2787, 0, + 0, 2929, 0, + 0, 3069, 0, + 0, 3207, 0, + 0, 3343, 0, + 0, 3479, 0, + 0, 3613, 0, + 0, 3747, 0, + 0, 3881, 0, + 0, 4015, 0, + 3203, 0, 3021, + 3203, 0, 3021, + 3203, 0, 3021, + 3201, 0, 3021, + 3201, 0, 3019, + 3201, 0, 3019, + 3199, 0, 3017, + 3197, 0, 3015, + 3195, 0, 3013, + 3193, 0, 3009, + 3189, 0, 3005, + 3183, 0, 2999, + 3177, 0, 2991, + 3167, 0, 2981, + 3155, 0, 2965, + 3137, 957, 2945, + 3111, 1552, 2915, + 3075, 1862, 2871, + 3023, 2093, 2807, + 2941, 2285, 2701, + 2801, 2459, 2509, + 2501, 2621, 1948, + 0, 2773, 0, + 0, 2919, 0, + 0, 3061, 0, + 0, 3201, 0, + 0, 3339, 0, + 0, 3477, 0, + 0, 3611, 0, + 0, 3745, 0, + 0, 3879, 0, + 0, 4013, 0, + 3335, 0, 3153, + 3335, 0, 3153, + 3335, 0, 3153, + 3335, 0, 3153, + 3333, 0, 3153, + 3333, 0, 3151, + 3333, 0, 3151, + 3331, 0, 3149, + 3329, 0, 3147, + 3327, 0, 3145, + 3325, 0, 3141, + 3321, 0, 3137, + 3315, 0, 3131, + 3309, 0, 3123, + 3299, 0, 3113, + 3287, 0, 3097, + 3269, 1085, 3075, + 3243, 1683, 3047, + 3207, 1993, 3003, + 3155, 2223, 2937, + 3073, 2417, 2833, + 2933, 2591, 2639, + 2633, 2753, 2077, + 0, 2905, 0, + 0, 3051, 0, + 0, 3195, 0, + 0, 3333, 0, + 0, 3471, 0, + 0, 3609, 0, + 0, 3743, 0, + 0, 3877, 0, + 0, 4011, 0, + 3467, 0, 3285, + 3467, 0, 3285, + 3467, 0, 3285, + 3467, 0, 3285, + 3467, 0, 3285, + 3465, 0, 3285, + 3465, 0, 3283, + 3465, 0, 3283, + 3463, 0, 3281, + 3461, 0, 3279, + 3459, 0, 3277, + 3457, 0, 3273, + 3453, 0, 3269, + 3447, 0, 3263, + 3441, 0, 3255, + 3431, 0, 3245, + 3419, 0, 3229, + 3401, 1215, 3207, + 3375, 1815, 3179, + 3339, 2125, 3135, + 3287, 2355, 3069, + 3205, 2549, 2965, + 3065, 2723, 2771, + 2765, 2885, 2207, + 0, 3037, 0, + 0, 3183, 0, + 0, 3327, 0, + 0, 3467, 0, + 0, 3603, 0, + 0, 3741, 0, + 0, 3875, 0, + 0, 4011, 0, + 3599, 0, 3417, + 3599, 0, 3417, + 3599, 0, 3417, + 3599, 0, 3417, + 3599, 0, 3417, + 3599, 0, 3417, + 3597, 0, 3417, + 3597, 0, 3415, + 3597, 0, 3415, + 3595, 0, 3413, + 3593, 0, 3411, + 3591, 0, 3409, + 3589, 0, 3405, + 3585, 0, 3401, + 3579, 0, 3395, + 3573, 0, 3387, + 3563, 0, 3377, + 3551, 0, 3361, + 3533, 1345, 3339, + 3507, 1946, 3309, + 3471, 2257, 3267, + 3419, 2487, 3201, + 3337, 2681, 3097, + 3197, 2855, 2903, + 2897, 3017, 2339, + 0, 3169, 0, + 0, 3315, 0, + 0, 3459, 0, + 0, 3599, 0, + 0, 3737, 0, + 0, 3873, 0, + 0, 4007, 0, + 3731, 0, 3551, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3729, 0, 3547, + 3729, 0, 3547, + 3727, 0, 3545, + 3725, 0, 3543, + 3723, 0, 3541, + 3721, 0, 3537, + 3717, 0, 3533, + 3713, 0, 3527, + 3705, 0, 3519, + 3695, 0, 3509, + 3683, 0, 3493, + 3665, 1476, 3471, + 3639, 2077, 3441, + 3603, 2389, 3399, + 3551, 2619, 3333, + 3469, 2815, 3229, + 3329, 2987, 3035, + 3029, 3149, 2469, + 0, 3301, 0, + 0, 3447, 0, + 0, 3591, 0, + 0, 3731, 0, + 0, 3869, 0, + 0, 4005, 0, + 3863, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3861, 0, 3679, + 3861, 0, 3679, + 3859, 0, 3677, + 3857, 0, 3675, + 3855, 0, 3673, + 3853, 0, 3669, + 3849, 0, 3665, + 3845, 0, 3659, + 3837, 0, 3651, + 3827, 0, 3641, + 3815, 0, 3625, + 3797, 1607, 3603, + 3771, 2209, 3575, + 3735, 2521, 3531, + 3683, 2751, 3465, + 3601, 2947, 3361, + 3461, 3119, 3167, + 3161, 3281, 2601, + 0, 3433, 0, + 0, 3579, 0, + 0, 3723, 0, + 0, 3863, 0, + 0, 4001, 0, + 3997, 0, 3815, + 3997, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3813, + 3995, 0, 3813, + 3995, 0, 3813, + 3995, 0, 3813, + 3995, 0, 3813, + 3995, 0, 3813, + 3993, 0, 3811, + 3993, 0, 3811, + 3991, 0, 3809, + 3991, 0, 3807, + 3987, 0, 3805, + 3985, 0, 3801, + 3981, 0, 3797, + 3977, 0, 3791, + 3969, 0, 3783, + 3959, 0, 3773, + 3947, 0, 3757, + 3929, 1739, 3735, + 3903, 2341, 3707, + 3867, 2653, 3663, + 3815, 2883, 3597, + 3733, 3079, 3493, + 3593, 3251, 3299, + 3293, 3413, 2733, + 0, 3565, 0, + 0, 3711, 0, + 0, 3855, 0, + 0, 3995, 0, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3943, + 4095, 0, 3943, + 4095, 0, 3941, + 4095, 0, 3939, + 4095, 0, 3937, + 4095, 0, 3933, + 4095, 0, 3929, + 4095, 0, 3923, + 4095, 0, 3915, + 4091, 0, 3905, + 4079, 0, 3889, + 4061, 1870, 3869, + 4035, 2473, 3839, + 3999, 2785, 3795, + 3947, 3017, 3729, + 3865, 3211, 3625, + 3725, 3383, 3431, + 3425, 3545, 2865, + 0, 3697, 0, + 0, 3843, 0, + 0, 3987, 0, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4075, + 4095, 0, 4075, + 4095, 0, 4073, + 4095, 0, 4071, + 4095, 0, 4069, + 4095, 0, 4065, + 4095, 0, 4061, + 4095, 0, 4055, + 4095, 0, 4047, + 4095, 0, 4037, + 4095, 0, 4021, + 4095, 2002, 4001, + 4095, 2605, 3971, + 4095, 2917, 3927, + 4079, 3149, 3861, + 3997, 3343, 3757, + 3857, 3515, 3563, + 3557, 3677, 2997, + 0, 3829, 0, + 0, 3977, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2133, 4095, + 4095, 2737, 4095, + 4095, 3049, 4059, + 4095, 3281, 3993, + 4095, 3475, 3889, + 3989, 3649, 3695, + 3689, 3809, 3127, + 0, 3961, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2265, 4095, + 4095, 2869, 4095, + 4095, 3181, 4095, + 4095, 3413, 4095, + 4095, 3607, 4021, + 4095, 3781, 3827, + 3821, 3941, 3259, + 148, 10, 366, + 0, 122, 244, + 0, 237, 2, + 0, 357, 0, + 0, 479, 0, + 0, 604, 0, + 0, 731, 0, + 0, 859, 0, + 0, 988, 0, + 0, 1117, 0, + 0, 1247, 0, + 0, 1378, 0, + 0, 1509, 0, + 0, 1641, 0, + 0, 1772, 0, + 0, 1904, 0, + 0, 2036, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 369, 0, 471, + 205, 106, 377, + 0, 225, 210, + 0, 348, 0, + 0, 473, 0, + 0, 599, 0, + 0, 727, 0, + 0, 856, 0, + 0, 985, 0, + 0, 1115, 0, + 0, 1246, 0, + 0, 1377, 0, + 0, 1509, 0, + 0, 1640, 0, + 0, 1772, 0, + 0, 1904, 0, + 0, 2036, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 558, 0, 582, + 456, 85, 510, + 271, 209, 391, + 0, 335, 159, + 0, 463, 0, + 0, 592, 0, + 0, 721, 0, + 0, 852, 0, + 0, 982, 0, + 0, 1113, 0, + 0, 1245, 0, + 0, 1376, 0, + 0, 1508, 0, + 0, 1640, 0, + 0, 1771, 0, + 0, 1903, 0, + 0, 2035, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 728, 0, 697, + 661, 54, 642, + 552, 186, 556, + 347, 318, 409, + 0, 450, 82, + 0, 582, 0, + 0, 714, 0, + 0, 846, 0, + 0, 978, 0, + 0, 1110, 0, + 0, 1242, 0, + 0, 1374, 0, + 0, 1506, 0, + 0, 1639, 0, + 0, 1771, 0, + 0, 1903, 0, + 0, 2035, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 887, 0, 816, + 840, 10, 775, + 770, 153, 712, + 654, 294, 613, + 432, 432, 432, + 0, 569, 0, + 0, 704, 0, + 0, 839, 0, + 0, 973, 0, + 0, 1106, 0, + 0, 1239, 0, + 0, 1372, 0, + 0, 1505, 0, + 0, 1637, 0, + 0, 1770, 0, + 0, 1902, 0, + 0, 2034, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1037, 0, 938, + 1005, 0, 907, + 957, 106, 861, + 884, 259, 792, + 763, 407, 678, + 525, 550, 461, + 0, 690, 0, + 0, 829, 0, + 0, 965, 0, + 0, 1100, 0, + 0, 1235, 0, + 0, 1369, 0, + 0, 1502, 0, + 0, 1636, 0, + 0, 1768, 0, + 0, 1901, 0, + 0, 2034, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1183, 0, 1063, + 1160, 0, 1039, + 1126, 33, 1005, + 1077, 209, 956, + 1002, 371, 880, + 877, 524, 753, + 626, 672, 498, + 0, 815, 0, + 0, 955, 0, + 0, 1093, 0, + 0, 1229, 0, + 0, 1365, 0, + 0, 1499, 0, + 0, 1633, 0, + 0, 1767, 0, + 0, 1900, 0, + 0, 2033, 0, + 0, 2165, 0, + 0, 2297, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1325, 0, 1189, + 1308, 0, 1171, + 1284, 0, 1146, + 1250, 131, 1110, + 1200, 318, 1058, + 1123, 487, 976, + 995, 645, 837, + 734, 795, 542, + 0, 941, 0, + 0, 1082, 0, + 0, 1222, 0, + 0, 1359, 0, + 0, 1495, 0, + 0, 1630, 0, + 0, 1764, 0, + 0, 1898, 0, + 0, 2031, 0, + 0, 2165, 0, + 0, 2297, 0, + 0, 2429, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1465, 0, 1317, + 1452, 0, 1304, + 1435, 0, 1285, + 1411, 0, 1259, + 1376, 236, 1221, + 1325, 432, 1166, + 1247, 607, 1079, + 1116, 768, 930, + 846, 921, 595, + 0, 1068, 0, + 0, 1211, 0, + 0, 1351, 0, + 0, 1489, 0, + 0, 1626, 0, + 0, 1761, 0, + 0, 1896, 0, + 0, 2030, 0, + 0, 2163, 0, + 0, 2297, 0, + 0, 2429, 0, + 0, 2561, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1602, 0, 1446, + 1593, 0, 1436, + 1580, 0, 1422, + 1563, 0, 1403, + 1538, 95, 1376, + 1504, 346, 1337, + 1452, 550, 1279, + 1373, 729, 1189, + 1240, 894, 1030, + 963, 1048, 658, + 0, 1197, 0, + 0, 1341, 0, + 0, 1482, 0, + 0, 1620, 0, + 0, 1757, 0, + 0, 1893, 0, + 0, 2027, 0, + 0, 2161, 0, + 0, 2295, 0, + 0, 2429, 0, + 0, 2561, 0, + 0, 2693, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1738, 0, 1575, + 1732, 0, 1568, + 1722, 0, 1558, + 1710, 0, 1544, + 1692, 0, 1524, + 1667, 198, 1496, + 1632, 461, 1456, + 1580, 671, 1397, + 1501, 854, 1303, + 1366, 1021, 1137, + 1083, 1177, 730, + 0, 1327, 0, + 0, 1471, 0, + 0, 1612, 0, + 0, 1751, 0, + 0, 1888, 0, + 0, 2024, 0, + 0, 2159, 0, + 0, 2293, 0, + 0, 2427, 0, + 0, 2561, 0, + 0, 2693, 0, + 0, 2825, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1873, 0, 1706, + 1868, 0, 1700, + 1862, 0, 1692, + 1852, 0, 1682, + 1839, 0, 1668, + 1822, 0, 1648, + 1797, 306, 1619, + 1762, 580, 1579, + 1710, 795, 1518, + 1629, 981, 1422, + 1493, 1149, 1249, + 1207, 1307, 812, + 0, 1457, 0, + 0, 1602, 0, + 0, 1744, 0, + 0, 1883, 0, + 0, 2020, 0, + 0, 2155, 0, + 0, 2291, 0, + 0, 2425, 0, + 0, 2559, 0, + 0, 2693, 0, + 0, 2825, 0, + 0, 2957, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2008, 0, 1837, + 2004, 0, 1832, + 1999, 0, 1827, + 1992, 0, 1819, + 1983, 0, 1808, + 1970, 0, 1794, + 1952, 0, 1773, + 1927, 419, 1745, + 1892, 702, 1703, + 1840, 921, 1642, + 1759, 1109, 1543, + 1621, 1278, 1366, + 1332, 1437, 902, + 0, 1587, 0, + 0, 1733, 0, + 0, 1875, 0, + 0, 2014, 0, + 0, 2151, 0, + 0, 2287, 0, + 0, 2423, 0, + 0, 2557, 0, + 0, 2691, 0, + 0, 2825, 0, + 0, 2957, 0, + 0, 3089, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2141, 0, 1968, + 2139, 0, 1964, + 2135, 0, 1960, + 2129, 0, 1954, + 2123, 0, 1947, + 2113, 0, 1936, + 2101, 0, 1921, + 2083, 39, 1901, + 2059, 537, 1872, + 2022, 826, 1830, + 1970, 1048, 1767, + 1889, 1238, 1667, + 1751, 1408, 1486, + 1459, 1567, 1000, + 0, 1718, 0, + 0, 1864, 0, + 0, 2006, 0, + 0, 2145, 0, + 0, 2283, 0, + 0, 2419, 0, + 0, 2555, 0, + 0, 2689, 0, + 0, 2823, 0, + 0, 2957, 0, + 0, 3089, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3885, 0, + 0, 4017, 0, + 2275, 0, 2099, + 2273, 0, 2097, + 2271, 0, 2093, + 2267, 0, 2089, + 2261, 0, 2083, + 2255, 0, 2075, + 2245, 0, 2065, + 2231, 0, 2049, + 2215, 138, 2029, + 2189, 658, 2000, + 2153, 953, 1958, + 2101, 1177, 1895, + 2019, 1367, 1793, + 1881, 1539, 1609, + 1587, 1698, 1105, + 0, 1850, 0, + 0, 1996, 0, + 0, 2139, 0, + 0, 2277, 0, + 0, 2415, 0, + 0, 2551, 0, + 0, 2687, 0, + 0, 2821, 0, + 0, 2955, 0, + 0, 3089, 0, + 0, 3221, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3885, 0, + 0, 4017, 0, + 2407, 0, 2231, + 2407, 0, 2229, + 2405, 0, 2227, + 2401, 0, 2223, + 2397, 0, 2219, + 2393, 0, 2213, + 2385, 0, 2205, + 2377, 0, 2195, + 2363, 0, 2179, + 2345, 243, 2159, + 2321, 782, 2129, + 2285, 1080, 2087, + 2233, 1306, 2023, + 2151, 1498, 1921, + 2012, 1670, 1734, + 1716, 1830, 1216, + 0, 1981, 0, + 0, 2127, 0, + 0, 2269, 0, + 0, 2409, 0, + 0, 2547, 0, + 0, 2683, 0, + 0, 2819, 0, + 0, 2953, 0, + 0, 3087, 0, + 0, 3221, 0, + 0, 3353, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4017, 0, + 2541, 0, 2363, + 2539, 0, 2361, + 2539, 0, 2359, + 2535, 0, 2357, + 2533, 0, 2353, + 2529, 0, 2349, + 2525, 0, 2343, + 2517, 0, 2335, + 2507, 0, 2325, + 2495, 0, 2309, + 2477, 353, 2289, + 2453, 908, 2259, + 2417, 1209, 2217, + 2363, 1436, 2153, + 2281, 1629, 2049, + 2143, 1801, 1861, + 1846, 1961, 1331, + 0, 2113, 0, + 0, 2259, 0, + 0, 2401, 0, + 0, 2541, 0, + 0, 2679, 0, + 0, 2815, 0, + 0, 2951, 0, + 0, 3085, 0, + 0, 3219, 0, + 0, 3353, 0, + 0, 3485, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 2673, 0, 2493, + 2673, 0, 2493, + 2671, 0, 2491, + 2669, 0, 2489, + 2667, 0, 2487, + 2665, 0, 2485, + 2661, 0, 2479, + 2657, 0, 2475, + 2649, 0, 2465, + 2639, 0, 2455, + 2627, 0, 2441, + 2609, 469, 2419, + 2583, 1035, 2389, + 2547, 1339, 2347, + 2495, 1567, 2283, + 2413, 1760, 2179, + 2273, 1932, 1989, + 1977, 2093, 1450, + 0, 2245, 0, + 0, 2391, 0, + 0, 2533, 0, + 0, 2673, 0, + 0, 2811, 0, + 0, 2947, 0, + 0, 3083, 0, + 0, 3217, 0, + 0, 3351, 0, + 0, 3485, 0, + 0, 3617, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 2805, 0, 2625, + 2805, 0, 2625, + 2805, 0, 2625, + 2803, 0, 2623, + 2801, 0, 2621, + 2799, 0, 2619, + 2797, 0, 2615, + 2793, 0, 2611, + 2787, 0, 2605, + 2781, 0, 2597, + 2771, 0, 2587, + 2759, 0, 2571, + 2741, 588, 2551, + 2715, 1163, 2521, + 2679, 1469, 2477, + 2627, 1698, 2413, + 2545, 1891, 2309, + 2405, 2065, 2117, + 2107, 2225, 1572, + 0, 2377, 0, + 0, 2523, 0, + 0, 2665, 0, + 0, 2805, 0, + 0, 2943, 0, + 0, 3079, 0, + 0, 3215, 0, + 0, 3349, 0, + 0, 3483, 0, + 0, 3617, 0, + 0, 3749, 0, + 0, 3883, 0, + 0, 4015, 0, + 2939, 0, 2757, + 2937, 0, 2757, + 2937, 0, 2757, + 2937, 0, 2755, + 2935, 0, 2755, + 2933, 0, 2753, + 2931, 0, 2749, + 2929, 0, 2747, + 2925, 0, 2743, + 2919, 0, 2737, + 2913, 0, 2729, + 2903, 0, 2717, + 2891, 0, 2703, + 2873, 710, 2681, + 2847, 1292, 2651, + 2811, 1600, 2609, + 2759, 1829, 2543, + 2677, 2023, 2439, + 2537, 2195, 2247, + 2239, 2357, 1697, + 0, 2509, 0, + 0, 2655, 0, + 0, 2797, 0, + 0, 2937, 0, + 0, 3075, 0, + 0, 3211, 0, + 0, 3347, 0, + 0, 3481, 0, + 0, 3615, 0, + 0, 3749, 0, + 0, 3881, 0, + 0, 4015, 0, + 3071, 0, 2889, + 3071, 0, 2889, + 3069, 0, 2889, + 3069, 0, 2889, + 3069, 0, 2887, + 3067, 0, 2885, + 3065, 0, 2883, + 3063, 0, 2881, + 3061, 0, 2879, + 3057, 0, 2873, + 3051, 0, 2869, + 3045, 0, 2859, + 3035, 0, 2849, + 3023, 0, 2833, + 3005, 835, 2813, + 2979, 1422, 2783, + 2943, 1731, 2739, + 2891, 1961, 2675, + 2809, 2155, 2571, + 2669, 2327, 2379, + 2371, 2489, 1823, + 0, 2641, 0, + 0, 2787, 0, + 0, 2929, 0, + 0, 3069, 0, + 0, 3207, 0, + 0, 3343, 0, + 0, 3479, 0, + 0, 3613, 0, + 0, 3747, 0, + 0, 3881, 0, + 0, 4015, 0, + 3203, 0, 3021, + 3203, 0, 3021, + 3203, 0, 3021, + 3201, 0, 3021, + 3201, 0, 3019, + 3201, 0, 3019, + 3199, 0, 3017, + 3197, 0, 3015, + 3195, 0, 3013, + 3193, 0, 3011, + 3189, 0, 3005, + 3183, 0, 2999, + 3177, 0, 2991, + 3167, 0, 2981, + 3155, 0, 2965, + 3137, 961, 2945, + 3111, 1553, 2915, + 3075, 1862, 2871, + 3023, 2093, 2807, + 2941, 2287, 2703, + 2801, 2459, 2509, + 2501, 2621, 1951, + 0, 2773, 0, + 0, 2919, 0, + 0, 3061, 0, + 0, 3201, 0, + 0, 3339, 0, + 0, 3477, 0, + 0, 3611, 0, + 0, 3745, 0, + 0, 3879, 0, + 0, 4013, 0, + 3335, 0, 3153, + 3335, 0, 3153, + 3335, 0, 3153, + 3335, 0, 3153, + 3333, 0, 3153, + 3333, 0, 3151, + 3333, 0, 3151, + 3331, 0, 3149, + 3329, 0, 3147, + 3327, 0, 3145, + 3325, 0, 3141, + 3321, 0, 3137, + 3315, 0, 3131, + 3309, 0, 3123, + 3299, 0, 3113, + 3287, 0, 3097, + 3269, 1089, 3077, + 3243, 1684, 3047, + 3207, 1994, 3003, + 3155, 2225, 2939, + 3073, 2419, 2833, + 2933, 2591, 2641, + 2633, 2753, 2081, + 0, 2905, 0, + 0, 3051, 0, + 0, 3195, 0, + 0, 3333, 0, + 0, 3471, 0, + 0, 3609, 0, + 0, 3743, 0, + 0, 3877, 0, + 0, 4011, 0, + 3467, 0, 3285, + 3467, 0, 3285, + 3467, 0, 3285, + 3467, 0, 3285, + 3467, 0, 3285, + 3465, 0, 3285, + 3465, 0, 3283, + 3465, 0, 3283, + 3463, 0, 3281, + 3461, 0, 3279, + 3459, 0, 3277, + 3457, 0, 3273, + 3453, 0, 3269, + 3447, 0, 3263, + 3441, 0, 3255, + 3431, 0, 3245, + 3419, 0, 3229, + 3401, 1218, 3209, + 3375, 1815, 3179, + 3339, 2125, 3135, + 3287, 2357, 3069, + 3205, 2551, 2965, + 3065, 2723, 2771, + 2765, 2885, 2209, + 0, 3037, 0, + 0, 3183, 0, + 0, 3327, 0, + 0, 3467, 0, + 0, 3603, 0, + 0, 3741, 0, + 0, 3875, 0, + 0, 4011, 0, + 3599, 0, 3419, + 3599, 0, 3417, + 3599, 0, 3417, + 3599, 0, 3417, + 3599, 0, 3417, + 3599, 0, 3417, + 3599, 0, 3417, + 3597, 0, 3415, + 3597, 0, 3415, + 3595, 0, 3413, + 3593, 0, 3411, + 3591, 0, 3409, + 3589, 0, 3405, + 3585, 0, 3401, + 3579, 0, 3395, + 3573, 0, 3387, + 3563, 0, 3377, + 3551, 0, 3361, + 3533, 1347, 3339, + 3507, 1947, 3311, + 3471, 2257, 3267, + 3419, 2487, 3201, + 3337, 2683, 3097, + 3197, 2855, 2903, + 2897, 3017, 2339, + 0, 3169, 0, + 0, 3315, 0, + 0, 3459, 0, + 0, 3599, 0, + 0, 3737, 0, + 0, 3873, 0, + 0, 4007, 0, + 3731, 0, 3551, + 3731, 0, 3551, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3729, 0, 3547, + 3729, 0, 3547, + 3727, 0, 3545, + 3725, 0, 3543, + 3723, 0, 3541, + 3721, 0, 3537, + 3717, 0, 3533, + 3713, 0, 3527, + 3705, 0, 3519, + 3695, 0, 3509, + 3683, 0, 3493, + 3665, 1478, 3471, + 3639, 2079, 3443, + 3603, 2389, 3399, + 3551, 2619, 3333, + 3469, 2815, 3229, + 3329, 2987, 3035, + 3029, 3149, 2471, + 0, 3301, 0, + 0, 3447, 0, + 0, 3591, 0, + 0, 3731, 0, + 0, 3869, 0, + 0, 4005, 0, + 3863, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3861, 0, 3679, + 3861, 0, 3679, + 3859, 0, 3677, + 3857, 0, 3675, + 3855, 0, 3673, + 3853, 0, 3669, + 3849, 0, 3665, + 3845, 0, 3659, + 3837, 0, 3651, + 3827, 0, 3641, + 3815, 0, 3625, + 3797, 1608, 3603, + 3771, 2211, 3575, + 3735, 2521, 3531, + 3683, 2751, 3465, + 3601, 2947, 3361, + 3461, 3119, 3167, + 3161, 3281, 2601, + 0, 3433, 0, + 0, 3579, 0, + 0, 3723, 0, + 0, 3863, 0, + 0, 4001, 0, + 3997, 0, 3815, + 3997, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3813, + 3995, 0, 3813, + 3995, 0, 3813, + 3995, 0, 3813, + 3995, 0, 3813, + 3993, 0, 3811, + 3993, 0, 3811, + 3991, 0, 3809, + 3991, 0, 3807, + 3987, 0, 3805, + 3985, 0, 3801, + 3981, 0, 3797, + 3977, 0, 3791, + 3969, 0, 3783, + 3959, 0, 3773, + 3947, 0, 3757, + 3929, 1739, 3737, + 3903, 2341, 3707, + 3867, 2653, 3663, + 3815, 2885, 3597, + 3733, 3079, 3493, + 3593, 3251, 3299, + 3293, 3413, 2733, + 0, 3565, 0, + 0, 3711, 0, + 0, 3855, 0, + 0, 3995, 0, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3943, + 4095, 0, 3943, + 4095, 0, 3941, + 4095, 0, 3939, + 4095, 0, 3937, + 4095, 0, 3933, + 4095, 0, 3929, + 4095, 0, 3923, + 4095, 0, 3915, + 4091, 0, 3905, + 4079, 0, 3889, + 4061, 1871, 3869, + 4035, 2473, 3839, + 3999, 2785, 3795, + 3947, 3017, 3729, + 3865, 3211, 3625, + 3725, 3383, 3431, + 3425, 3545, 2865, + 0, 3697, 0, + 0, 3843, 0, + 0, 3987, 0, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4075, + 4095, 0, 4075, + 4095, 0, 4073, + 4095, 0, 4071, + 4095, 0, 4069, + 4095, 0, 4065, + 4095, 0, 4061, + 4095, 0, 4055, + 4095, 0, 4047, + 4095, 0, 4037, + 4095, 0, 4021, + 4095, 2002, 4001, + 4095, 2605, 3971, + 4095, 2917, 3927, + 4079, 3149, 3861, + 3997, 3343, 3757, + 3857, 3515, 3563, + 3557, 3677, 2997, + 0, 3829, 0, + 0, 3977, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2133, 4095, + 4095, 2737, 4095, + 4095, 3049, 4059, + 4095, 3281, 3993, + 4095, 3475, 3889, + 3989, 3649, 3695, + 3689, 3809, 3129, + 0, 3961, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2265, 4095, + 4095, 2869, 4095, + 4095, 3181, 4095, + 4095, 3413, 4095, + 4095, 3607, 4021, + 4095, 3781, 3827, + 3821, 3941, 3261, + 232, 55, 490, + 0, 157, 400, + 0, 265, 243, + 0, 378, 0, + 0, 496, 0, + 0, 617, 0, + 0, 740, 0, + 0, 866, 0, + 0, 993, 0, + 0, 1121, 0, + 0, 1251, 0, + 0, 1381, 0, + 0, 1511, 0, + 0, 1642, 0, + 0, 1773, 0, + 0, 1905, 0, + 0, 2036, 0, + 0, 2169, 0, + 0, 2301, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 422, 37, 572, + 280, 142, 498, + 0, 254, 376, + 0, 369, 134, + 0, 489, 0, + 0, 611, 0, + 0, 736, 0, + 0, 863, 0, + 0, 991, 0, + 0, 1120, 0, + 0, 1249, 0, + 0, 1380, 0, + 0, 1510, 0, + 0, 1642, 0, + 0, 1773, 0, + 0, 1904, 0, + 0, 2036, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 594, 12, 663, + 501, 123, 603, + 337, 238, 509, + 0, 358, 342, + 0, 480, 0, + 0, 605, 0, + 0, 731, 0, + 0, 859, 0, + 0, 988, 0, + 0, 1117, 0, + 0, 1248, 0, + 0, 1378, 0, + 0, 1509, 0, + 0, 1641, 0, + 0, 1772, 0, + 0, 1904, 0, + 0, 2036, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 753, 0, 761, + 690, 95, 714, + 588, 217, 642, + 403, 341, 523, + 0, 467, 291, + 0, 595, 0, + 0, 724, 0, + 0, 853, 0, + 0, 984, 0, + 0, 1114, 0, + 0, 1245, 0, + 0, 1377, 0, + 0, 1508, 0, + 0, 1640, 0, + 0, 1772, 0, + 0, 1904, 0, + 0, 2035, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 905, 0, 866, + 860, 54, 829, + 793, 186, 774, + 684, 318, 689, + 479, 450, 541, + 0, 582, 214, + 0, 714, 0, + 0, 846, 0, + 0, 978, 0, + 0, 1110, 0, + 0, 1242, 0, + 0, 1374, 0, + 0, 1506, 0, + 0, 1639, 0, + 0, 1771, 0, + 0, 1903, 0, + 0, 2035, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1050, 0, 977, + 1019, 0, 948, + 972, 142, 907, + 902, 286, 844, + 786, 426, 745, + 564, 564, 564, + 0, 701, 84, + 0, 836, 0, + 0, 971, 0, + 0, 1105, 0, + 0, 1238, 0, + 0, 1371, 0, + 0, 1504, 0, + 0, 1637, 0, + 0, 1769, 0, + 0, 1902, 0, + 0, 2034, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1193, 0, 1093, + 1170, 0, 1070, + 1137, 76, 1039, + 1089, 238, 993, + 1016, 392, 924, + 895, 539, 810, + 658, 682, 593, + 0, 823, 0, + 0, 961, 0, + 0, 1097, 0, + 0, 1232, 0, + 0, 1367, 0, + 0, 1501, 0, + 0, 1635, 0, + 0, 1768, 0, + 0, 1901, 0, + 0, 2033, 0, + 0, 2165, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1332, 0, 1212, + 1315, 0, 1195, + 1292, 0, 1171, + 1258, 165, 1137, + 1209, 341, 1088, + 1134, 503, 1012, + 1009, 656, 885, + 758, 804, 630, + 0, 947, 0, + 0, 1087, 0, + 0, 1225, 0, + 0, 1361, 0, + 0, 1497, 0, + 0, 1631, 0, + 0, 1765, 0, + 0, 1899, 0, + 0, 2032, 0, + 0, 2165, 0, + 0, 2297, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1470, 0, 1334, + 1457, 0, 1321, + 1440, 0, 1303, + 1416, 46, 1278, + 1382, 263, 1243, + 1332, 450, 1190, + 1255, 619, 1108, + 1127, 777, 970, + 866, 928, 674, + 0, 1073, 0, + 0, 1215, 0, + 0, 1354, 0, + 0, 1491, 0, + 0, 1627, 0, + 0, 1762, 0, + 0, 1896, 0, + 0, 2030, 0, + 0, 2163, 0, + 0, 2297, 0, + 0, 2429, 0, + 0, 2561, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1606, 0, 1459, + 1597, 0, 1449, + 1584, 0, 1436, + 1567, 0, 1417, + 1543, 132, 1391, + 1508, 368, 1354, + 1458, 564, 1298, + 1379, 739, 1212, + 1248, 900, 1062, + 978, 1053, 727, + 0, 1200, 0, + 0, 1343, 0, + 0, 1484, 0, + 0, 1622, 0, + 0, 1758, 0, + 0, 1893, 0, + 0, 2028, 0, + 0, 2161, 0, + 0, 2295, 0, + 0, 2429, 0, + 0, 2561, 0, + 0, 2693, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1741, 0, 1585, + 1734, 0, 1578, + 1725, 0, 1568, + 1713, 0, 1554, + 1695, 0, 1535, + 1671, 227, 1508, + 1636, 478, 1469, + 1584, 682, 1412, + 1505, 861, 1321, + 1372, 1026, 1162, + 1095, 1181, 790, + 0, 1329, 0, + 0, 1473, 0, + 0, 1614, 0, + 0, 1752, 0, + 0, 1889, 0, + 0, 2025, 0, + 0, 2159, 0, + 0, 2293, 0, + 0, 2427, 0, + 0, 2561, 0, + 0, 2693, 0, + 0, 2825, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1876, 0, 1713, + 1871, 0, 1708, + 1864, 0, 1700, + 1854, 0, 1690, + 1842, 0, 1676, + 1824, 0, 1656, + 1799, 330, 1628, + 1764, 593, 1589, + 1713, 803, 1529, + 1633, 986, 1435, + 1498, 1153, 1269, + 1216, 1309, 862, + 0, 1459, 0, + 0, 1603, 0, + 0, 1745, 0, + 0, 1883, 0, + 0, 2021, 0, + 0, 2157, 0, + 0, 2291, 0, + 0, 2425, 0, + 0, 2559, 0, + 0, 2693, 0, + 0, 2825, 0, + 0, 2957, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2009, 0, 1842, + 2006, 0, 1838, + 2001, 0, 1832, + 1994, 0, 1825, + 1984, 0, 1814, + 1972, 0, 1800, + 1954, 0, 1780, + 1929, 438, 1752, + 1894, 712, 1711, + 1842, 927, 1650, + 1761, 1113, 1554, + 1625, 1281, 1381, + 1339, 1439, 944, + 0, 1589, 0, + 0, 1734, 0, + 0, 1876, 0, + 0, 2015, 0, + 0, 2153, 0, + 0, 2289, 0, + 0, 2423, 0, + 0, 2557, 0, + 0, 2691, 0, + 0, 2825, 0, + 0, 2957, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2143, 0, 1972, + 2139, 0, 1969, + 2137, 0, 1964, + 2131, 0, 1959, + 2125, 0, 1951, + 2115, 0, 1940, + 2103, 0, 1926, + 2085, 81, 1905, + 2059, 551, 1877, + 2024, 834, 1836, + 1972, 1053, 1774, + 1891, 1241, 1675, + 1754, 1410, 1498, + 1464, 1569, 1034, + 0, 1720, 0, + 0, 1865, 0, + 0, 2007, 0, + 0, 2147, 0, + 0, 2283, 0, + 0, 2419, 0, + 0, 2555, 0, + 0, 2689, 0, + 0, 2823, 0, + 0, 2957, 0, + 0, 3089, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3885, 0, + 0, 4017, 0, + 2275, 0, 2103, + 2273, 0, 2099, + 2271, 0, 2097, + 2267, 0, 2093, + 2263, 0, 2087, + 2255, 0, 2079, + 2245, 0, 2067, + 2233, 0, 2053, + 2215, 172, 2033, + 2191, 669, 2004, + 2155, 959, 1962, + 2103, 1180, 1899, + 2021, 1370, 1799, + 1883, 1540, 1618, + 1591, 1699, 1132, + 0, 1851, 0, + 0, 1996, 0, + 0, 2139, 0, + 0, 2279, 0, + 0, 2415, 0, + 0, 2551, 0, + 0, 2687, 0, + 0, 2821, 0, + 0, 2955, 0, + 0, 3089, 0, + 0, 3221, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3885, 0, + 0, 4017, 0, + 2409, 0, 2233, + 2407, 0, 2231, + 2405, 0, 2229, + 2403, 0, 2225, + 2399, 0, 2221, + 2393, 0, 2215, + 2387, 0, 2207, + 2377, 0, 2197, + 2365, 0, 2181, + 2347, 270, 2161, + 2321, 790, 2133, + 2285, 1085, 2089, + 2233, 1309, 2027, + 2151, 1500, 1925, + 2013, 1671, 1741, + 1719, 1830, 1237, + 0, 1982, 0, + 0, 2127, 0, + 0, 2271, 0, + 0, 2409, 0, + 0, 2547, 0, + 0, 2683, 0, + 0, 2819, 0, + 0, 2953, 0, + 0, 3087, 0, + 0, 3221, 0, + 0, 3353, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4017, 0, + 2541, 0, 2363, + 2541, 0, 2363, + 2539, 0, 2361, + 2537, 0, 2359, + 2533, 0, 2355, + 2529, 0, 2351, + 2525, 0, 2345, + 2517, 0, 2337, + 2509, 0, 2327, + 2495, 0, 2311, + 2477, 375, 2291, + 2453, 914, 2261, + 2417, 1212, 2219, + 2365, 1438, 2155, + 2283, 1630, 2053, + 2143, 1802, 1866, + 1849, 1962, 1348, + 0, 2113, 0, + 0, 2259, 0, + 0, 2403, 0, + 0, 2541, 0, + 0, 2679, 0, + 0, 2815, 0, + 0, 2951, 0, + 0, 3085, 0, + 0, 3219, 0, + 0, 3353, 0, + 0, 3485, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 2673, 0, 2495, + 2673, 0, 2495, + 2671, 0, 2493, + 2671, 0, 2491, + 2669, 0, 2489, + 2665, 0, 2485, + 2661, 0, 2481, + 2657, 0, 2475, + 2649, 0, 2467, + 2641, 0, 2457, + 2627, 0, 2441, + 2609, 485, 2421, + 2585, 1039, 2391, + 2549, 1341, 2349, + 2495, 1569, 2285, + 2413, 1761, 2181, + 2275, 1933, 1993, + 1978, 2093, 1463, + 0, 2245, 0, + 0, 2391, 0, + 0, 2533, 0, + 0, 2673, 0, + 0, 2811, 0, + 0, 2947, 0, + 0, 3083, 0, + 0, 3217, 0, + 0, 3351, 0, + 0, 3485, 0, + 0, 3617, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 2807, 0, 2627, + 2805, 0, 2627, + 2805, 0, 2625, + 2803, 0, 2623, + 2801, 0, 2623, + 2799, 0, 2619, + 2797, 0, 2617, + 2793, 0, 2613, + 2789, 0, 2607, + 2781, 0, 2599, + 2771, 0, 2587, + 2759, 0, 2573, + 2741, 601, 2551, + 2715, 1167, 2521, + 2681, 1471, 2479, + 2627, 1699, 2415, + 2545, 1892, 2311, + 2405, 2065, 2121, + 2109, 2225, 1582, + 0, 2377, 0, + 0, 2523, 0, + 0, 2665, 0, + 0, 2805, 0, + 0, 2943, 0, + 0, 3079, 0, + 0, 3215, 0, + 0, 3349, 0, + 0, 3483, 0, + 0, 3617, 0, + 0, 3749, 0, + 0, 3883, 0, + 0, 4015, 0, + 2939, 0, 2759, + 2939, 0, 2759, + 2937, 0, 2757, + 2937, 0, 2757, + 2935, 0, 2755, + 2933, 0, 2753, + 2931, 0, 2751, + 2929, 0, 2747, + 2925, 0, 2743, + 2919, 0, 2737, + 2913, 0, 2729, + 2903, 0, 2719, + 2891, 0, 2703, + 2873, 720, 2683, + 2847, 1295, 2653, + 2811, 1601, 2609, + 2759, 1830, 2545, + 2677, 2023, 2441, + 2537, 2197, 2251, + 2239, 2357, 1705, + 0, 2509, 0, + 0, 2655, 0, + 0, 2797, 0, + 0, 2937, 0, + 0, 3075, 0, + 0, 3211, 0, + 0, 3347, 0, + 0, 3481, 0, + 0, 3615, 0, + 0, 3749, 0, + 0, 3881, 0, + 0, 4015, 0, + 3071, 0, 2891, + 3071, 0, 2889, + 3069, 0, 2889, + 3069, 0, 2889, + 3069, 0, 2887, + 3067, 0, 2887, + 3065, 0, 2885, + 3063, 0, 2883, + 3061, 0, 2879, + 3057, 0, 2875, + 3051, 0, 2869, + 3045, 0, 2861, + 3035, 0, 2849, + 3023, 0, 2835, + 3005, 842, 2813, + 2979, 1425, 2783, + 2943, 1732, 2741, + 2891, 1961, 2675, + 2809, 2155, 2571, + 2669, 2327, 2379, + 2371, 2489, 1829, + 0, 2641, 0, + 0, 2787, 0, + 0, 2929, 0, + 0, 3069, 0, + 0, 3207, 0, + 0, 3343, 0, + 0, 3479, 0, + 0, 3613, 0, + 0, 3747, 0, + 0, 3881, 0, + 0, 4015, 0, + 3203, 0, 3023, + 3203, 0, 3021, + 3203, 0, 3021, + 3201, 0, 3021, + 3201, 0, 3021, + 3201, 0, 3019, + 3199, 0, 3017, + 3197, 0, 3017, + 3195, 0, 3013, + 3193, 0, 3011, + 3189, 0, 3007, + 3183, 0, 3001, + 3177, 0, 2993, + 3167, 0, 2981, + 3155, 0, 2965, + 3137, 967, 2945, + 3111, 1555, 2915, + 3075, 1863, 2873, + 3023, 2093, 2807, + 2941, 2287, 2703, + 2801, 2459, 2511, + 2503, 2621, 1956, + 0, 2773, 0, + 0, 2919, 0, + 0, 3063, 0, + 0, 3201, 0, + 0, 3339, 0, + 0, 3477, 0, + 0, 3611, 0, + 0, 3745, 0, + 0, 3879, 0, + 0, 4013, 0, + 3335, 0, 3155, + 3335, 0, 3153, + 3335, 0, 3153, + 3335, 0, 3153, + 3333, 0, 3153, + 3333, 0, 3151, + 3333, 0, 3151, + 3331, 0, 3149, + 3329, 0, 3147, + 3327, 0, 3145, + 3325, 0, 3143, + 3321, 0, 3137, + 3315, 0, 3131, + 3309, 0, 3123, + 3299, 0, 3113, + 3287, 0, 3097, + 3269, 1093, 3077, + 3243, 1685, 3047, + 3207, 1994, 3003, + 3155, 2225, 2939, + 3073, 2419, 2835, + 2933, 2591, 2641, + 2635, 2753, 2083, + 0, 2905, 0, + 0, 3051, 0, + 0, 3195, 0, + 0, 3333, 0, + 0, 3471, 0, + 0, 3609, 0, + 0, 3743, 0, + 0, 3877, 0, + 0, 4011, 0, + 3467, 0, 3287, + 3467, 0, 3287, + 3467, 0, 3285, + 3467, 0, 3285, + 3467, 0, 3285, + 3465, 0, 3285, + 3465, 0, 3283, + 3465, 0, 3283, + 3463, 0, 3281, + 3461, 0, 3279, + 3459, 0, 3277, + 3457, 0, 3273, + 3453, 0, 3269, + 3447, 0, 3263, + 3441, 0, 3255, + 3431, 0, 3245, + 3419, 0, 3229, + 3401, 1221, 3209, + 3375, 1816, 3179, + 3339, 2125, 3135, + 3287, 2357, 3071, + 3205, 2551, 2965, + 3065, 2723, 2773, + 2765, 2885, 2213, + 0, 3037, 0, + 0, 3183, 0, + 0, 3327, 0, + 0, 3467, 0, + 0, 3603, 0, + 0, 3741, 0, + 0, 3875, 0, + 0, 4011, 0, + 3599, 0, 3419, + 3599, 0, 3419, + 3599, 0, 3417, + 3599, 0, 3417, + 3599, 0, 3417, + 3599, 0, 3417, + 3599, 0, 3417, + 3597, 0, 3415, + 3597, 0, 3415, + 3595, 0, 3413, + 3593, 0, 3411, + 3591, 0, 3409, + 3589, 0, 3405, + 3585, 0, 3401, + 3581, 0, 3395, + 3573, 0, 3387, + 3563, 0, 3377, + 3551, 0, 3361, + 3533, 1350, 3341, + 3507, 1947, 3311, + 3471, 2257, 3267, + 3419, 2489, 3203, + 3337, 2683, 3097, + 3197, 2855, 2903, + 2897, 3017, 2341, + 0, 3169, 0, + 0, 3315, 0, + 0, 3459, 0, + 0, 3599, 0, + 0, 3737, 0, + 0, 3873, 0, + 0, 4007, 0, + 3731, 0, 3551, + 3731, 0, 3551, + 3731, 0, 3551, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3729, 0, 3547, + 3729, 0, 3547, + 3727, 0, 3545, + 3725, 0, 3543, + 3723, 0, 3541, + 3721, 0, 3537, + 3717, 0, 3533, + 3713, 0, 3527, + 3705, 0, 3519, + 3695, 0, 3509, + 3683, 0, 3493, + 3665, 1479, 3473, + 3639, 2079, 3443, + 3603, 2389, 3399, + 3551, 2621, 3333, + 3469, 2815, 3229, + 3329, 2987, 3035, + 3029, 3149, 2473, + 0, 3301, 0, + 0, 3447, 0, + 0, 3591, 0, + 0, 3731, 0, + 0, 3869, 0, + 0, 4005, 0, + 3863, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3861, 0, 3679, + 3861, 0, 3679, + 3859, 0, 3677, + 3859, 0, 3675, + 3855, 0, 3673, + 3853, 0, 3669, + 3849, 0, 3665, + 3845, 0, 3659, + 3837, 0, 3651, + 3827, 0, 3641, + 3815, 0, 3625, + 3797, 1610, 3605, + 3771, 2211, 3575, + 3735, 2521, 3531, + 3683, 2753, 3465, + 3601, 2947, 3361, + 3461, 3119, 3167, + 3161, 3281, 2603, + 0, 3433, 0, + 0, 3579, 0, + 0, 3723, 0, + 0, 3863, 0, + 0, 4001, 0, + 3997, 0, 3815, + 3997, 0, 3815, + 3997, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3813, + 3995, 0, 3813, + 3995, 0, 3813, + 3995, 0, 3813, + 3995, 0, 3813, + 3993, 0, 3811, + 3993, 0, 3811, + 3991, 0, 3809, + 3991, 0, 3807, + 3989, 0, 3805, + 3985, 0, 3801, + 3981, 0, 3797, + 3977, 0, 3791, + 3969, 0, 3783, + 3959, 0, 3773, + 3947, 0, 3757, + 3929, 1740, 3737, + 3903, 2343, 3707, + 3867, 2653, 3663, + 3815, 2885, 3597, + 3733, 3079, 3493, + 3593, 3251, 3299, + 3293, 3413, 2733, + 0, 3565, 0, + 0, 3711, 0, + 0, 3855, 0, + 0, 3995, 0, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3943, + 4095, 0, 3943, + 4095, 0, 3941, + 4095, 0, 3939, + 4095, 0, 3937, + 4095, 0, 3933, + 4095, 0, 3929, + 4095, 0, 3923, + 4095, 0, 3915, + 4091, 0, 3905, + 4079, 0, 3889, + 4061, 1872, 3869, + 4035, 2475, 3839, + 3999, 2785, 3795, + 3947, 3017, 3729, + 3865, 3211, 3625, + 3725, 3383, 3431, + 3425, 3545, 2865, + 0, 3697, 0, + 0, 3843, 0, + 0, 3987, 0, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4075, + 4095, 0, 4075, + 4095, 0, 4073, + 4095, 0, 4071, + 4095, 0, 4069, + 4095, 0, 4065, + 4095, 0, 4061, + 4095, 0, 4055, + 4095, 0, 4047, + 4095, 0, 4037, + 4095, 0, 4021, + 4095, 2003, 4001, + 4095, 2607, 3971, + 4095, 2917, 3927, + 4079, 3149, 3861, + 3997, 3343, 3757, + 3857, 3517, 3563, + 3557, 3677, 2997, + 0, 3829, 0, + 0, 3977, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2135, 4095, + 4095, 2737, 4095, + 4095, 3049, 4059, + 4095, 3281, 3993, + 4095, 3475, 3889, + 3989, 3649, 3695, + 3689, 3809, 3129, + 0, 3961, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2267, 4095, + 4095, 2869, 4095, + 4095, 3181, 4095, + 4095, 3413, 4095, + 4095, 3607, 4021, + 4095, 3781, 3827, + 3821, 3941, 3261, + 325, 108, 616, + 140, 200, 549, + 0, 299, 442, + 0, 405, 242, + 0, 517, 0, + 0, 633, 0, + 0, 753, 0, + 0, 875, 0, + 0, 1000, 0, + 0, 1127, 0, + 0, 1255, 0, + 0, 1384, 0, + 0, 1513, 0, + 0, 1644, 0, + 0, 1775, 0, + 0, 1906, 0, + 0, 2037, 0, + 0, 2169, 0, + 0, 2301, 0, + 0, 2433, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 486, 92, 679, + 364, 187, 622, + 125, 289, 532, + 0, 397, 375, + 0, 510, 9, + 0, 628, 0, + 0, 749, 0, + 0, 872, 0, + 0, 998, 0, + 0, 1125, 0, + 0, 1253, 0, + 0, 1383, 0, + 0, 1513, 0, + 0, 1643, 0, + 0, 1774, 0, + 0, 1905, 0, + 0, 2037, 0, + 0, 2169, 0, + 0, 2301, 0, + 0, 2433, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 638, 70, 752, + 554, 169, 704, + 412, 274, 630, + 103, 386, 508, + 0, 502, 267, + 0, 621, 0, + 0, 744, 0, + 0, 868, 0, + 0, 995, 0, + 0, 1123, 0, + 0, 1252, 0, + 0, 1381, 0, + 0, 1512, 0, + 0, 1643, 0, + 0, 1774, 0, + 0, 1905, 0, + 0, 2037, 0, + 0, 2169, 0, + 0, 2301, 0, + 0, 2433, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 785, 38, 835, + 726, 144, 795, + 633, 255, 735, + 469, 370, 641, + 73, 490, 474, + 0, 612, 63, + 0, 737, 0, + 0, 863, 0, + 0, 991, 0, + 0, 1120, 0, + 0, 1249, 0, + 0, 1380, 0, + 0, 1510, 0, + 0, 1642, 0, + 0, 1773, 0, + 0, 1905, 0, + 0, 2036, 0, + 0, 2169, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 927, 0, 926, + 885, 108, 893, + 822, 227, 846, + 720, 349, 774, + 535, 473, 655, + 29, 599, 424, + 0, 727, 0, + 0, 856, 0, + 0, 986, 0, + 0, 1116, 0, + 0, 1246, 0, + 0, 1377, 0, + 0, 1509, 0, + 0, 1640, 0, + 0, 1772, 0, + 0, 1904, 0, + 0, 2036, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1067, 0, 1024, + 1036, 55, 998, + 992, 187, 961, + 925, 318, 906, + 816, 450, 821, + 611, 582, 673, + 0, 714, 346, + 0, 846, 0, + 0, 978, 0, + 0, 1110, 0, + 0, 1242, 0, + 0, 1374, 0, + 0, 1506, 0, + 0, 1639, 0, + 0, 1771, 0, + 0, 1903, 0, + 0, 2035, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1205, 0, 1129, + 1182, 0, 1109, + 1151, 127, 1080, + 1104, 274, 1039, + 1034, 418, 976, + 919, 558, 877, + 696, 696, 696, + 0, 833, 216, + 0, 968, 0, + 0, 1103, 0, + 0, 1237, 0, + 0, 1370, 0, + 0, 1503, 0, + 0, 1636, 0, + 0, 1769, 0, + 0, 1902, 0, + 0, 2034, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1341, 0, 1241, + 1325, 0, 1225, + 1302, 31, 1202, + 1269, 208, 1171, + 1221, 370, 1125, + 1148, 524, 1056, + 1027, 671, 942, + 790, 814, 725, + 0, 955, 0, + 0, 1093, 0, + 0, 1229, 0, + 0, 1365, 0, + 0, 1499, 0, + 0, 1633, 0, + 0, 1767, 0, + 0, 1900, 0, + 0, 2033, 0, + 0, 2165, 0, + 0, 2297, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1477, 0, 1356, + 1464, 0, 1344, + 1447, 0, 1327, + 1424, 100, 1303, + 1390, 297, 1269, + 1341, 473, 1220, + 1266, 635, 1144, + 1141, 788, 1017, + 891, 936, 762, + 0, 1079, 0, + 0, 1219, 0, + 0, 1357, 0, + 0, 1494, 0, + 0, 1629, 0, + 0, 1764, 0, + 0, 1897, 0, + 0, 2031, 0, + 0, 2165, 0, + 0, 2297, 0, + 0, 2429, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1611, 0, 1476, + 1602, 0, 1466, + 1590, 0, 1453, + 1572, 0, 1436, + 1549, 178, 1411, + 1514, 395, 1375, + 1464, 582, 1322, + 1388, 751, 1240, + 1259, 909, 1101, + 998, 1059, 806, + 0, 1205, 0, + 0, 1347, 0, + 0, 1486, 0, + 0, 1623, 0, + 0, 1759, 0, + 0, 1894, 0, + 0, 2029, 0, + 0, 2163, 0, + 0, 2295, 0, + 0, 2429, 0, + 0, 2561, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1745, 0, 1598, + 1738, 0, 1591, + 1729, 0, 1581, + 1716, 0, 1568, + 1699, 0, 1549, + 1675, 264, 1523, + 1640, 500, 1486, + 1590, 696, 1430, + 1511, 871, 1344, + 1380, 1032, 1194, + 1110, 1185, 859, + 0, 1332, 0, + 0, 1476, 0, + 0, 1616, 0, + 0, 1754, 0, + 0, 1890, 0, + 0, 2025, 0, + 0, 2161, 0, + 0, 2293, 0, + 0, 2427, 0, + 0, 2561, 0, + 0, 2693, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1878, 0, 1723, + 1873, 0, 1717, + 1867, 0, 1710, + 1857, 0, 1700, + 1845, 0, 1686, + 1827, 0, 1667, + 1803, 359, 1640, + 1768, 610, 1601, + 1717, 814, 1544, + 1637, 994, 1453, + 1504, 1158, 1294, + 1227, 1313, 922, + 0, 1461, 0, + 0, 1605, 0, + 0, 1746, 0, + 0, 1884, 0, + 0, 2021, 0, + 0, 2157, 0, + 0, 2291, 0, + 0, 2425, 0, + 0, 2559, 0, + 0, 2693, 0, + 0, 2825, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2011, 0, 1849, + 2008, 0, 1845, + 2003, 0, 1840, + 1996, 0, 1832, + 1987, 0, 1822, + 1974, 0, 1808, + 1956, 59, 1788, + 1932, 462, 1761, + 1896, 725, 1721, + 1845, 936, 1661, + 1765, 1118, 1568, + 1630, 1285, 1401, + 1348, 1441, 994, + 0, 1591, 0, + 0, 1735, 0, + 0, 1877, 0, + 0, 2016, 0, + 0, 2153, 0, + 0, 2289, 0, + 0, 2423, 0, + 0, 2557, 0, + 0, 2691, 0, + 0, 2825, 0, + 0, 2957, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2145, 0, 1977, + 2141, 0, 1974, + 2137, 0, 1970, + 2133, 0, 1964, + 2125, 0, 1957, + 2117, 0, 1946, + 2103, 0, 1932, + 2087, 132, 1912, + 2061, 570, 1884, + 2026, 844, 1843, + 1974, 1059, 1782, + 1893, 1245, 1686, + 1757, 1413, 1513, + 1471, 1571, 1076, + 0, 1721, 0, + 0, 1866, 0, + 0, 2008, 0, + 0, 2147, 0, + 0, 2285, 0, + 0, 2421, 0, + 0, 2555, 0, + 0, 2689, 0, + 0, 2823, 0, + 0, 2957, 0, + 0, 3089, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2277, 0, 2107, + 2275, 0, 2103, + 2273, 0, 2101, + 2269, 0, 2097, + 2263, 0, 2091, + 2257, 0, 2083, + 2247, 0, 2073, + 2235, 0, 2057, + 2217, 213, 2038, + 2191, 684, 2009, + 2157, 966, 1968, + 2103, 1185, 1906, + 2023, 1373, 1807, + 1886, 1543, 1630, + 1596, 1701, 1166, + 0, 1852, 0, + 0, 1997, 0, + 0, 2139, 0, + 0, 2279, 0, + 0, 2415, 0, + 0, 2551, 0, + 0, 2687, 0, + 0, 2821, 0, + 0, 2955, 0, + 0, 3089, 0, + 0, 3221, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3885, 0, + 0, 4017, 0, + 2409, 0, 2235, + 2407, 0, 2235, + 2405, 0, 2231, + 2403, 0, 2229, + 2399, 0, 2225, + 2395, 0, 2219, + 2387, 0, 2211, + 2377, 0, 2201, + 2365, 0, 2185, + 2347, 304, 2165, + 2323, 801, 2135, + 2287, 1090, 2095, + 2235, 1313, 2032, + 2153, 1502, 1932, + 2015, 1673, 1750, + 1723, 1831, 1264, + 0, 1983, 0, + 0, 2129, 0, + 0, 2271, 0, + 0, 2411, 0, + 0, 2547, 0, + 0, 2683, 0, + 0, 2819, 0, + 0, 2953, 0, + 0, 3087, 0, + 0, 3221, 0, + 0, 3353, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4017, 0, + 2541, 0, 2367, + 2541, 0, 2365, + 2539, 0, 2363, + 2537, 0, 2361, + 2535, 0, 2357, + 2531, 0, 2353, + 2525, 0, 2347, + 2519, 0, 2339, + 2509, 0, 2329, + 2497, 0, 2313, + 2479, 402, 2293, + 2453, 922, 2265, + 2417, 1217, 2223, + 2365, 1441, 2159, + 2283, 1632, 2057, + 2145, 1803, 1873, + 1851, 1962, 1369, + 0, 2115, 0, + 0, 2261, 0, + 0, 2403, 0, + 0, 2543, 0, + 0, 2679, 0, + 0, 2815, 0, + 0, 2951, 0, + 0, 3085, 0, + 0, 3219, 0, + 0, 3353, 0, + 0, 3485, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4017, 0, + 2675, 0, 2497, + 2673, 0, 2497, + 2673, 0, 2495, + 2671, 0, 2493, + 2669, 0, 2491, + 2665, 0, 2487, + 2661, 0, 2483, + 2657, 0, 2477, + 2649, 0, 2469, + 2641, 0, 2459, + 2627, 0, 2443, + 2609, 507, 2423, + 2585, 1046, 2393, + 2549, 1345, 2351, + 2497, 1571, 2287, + 2415, 1762, 2185, + 2275, 1934, 1998, + 1981, 2093, 1480, + 0, 2245, 0, + 0, 2391, 0, + 0, 2535, 0, + 0, 2673, 0, + 0, 2811, 0, + 0, 2947, 0, + 0, 3083, 0, + 0, 3217, 0, + 0, 3351, 0, + 0, 3485, 0, + 0, 3617, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 2807, 0, 2629, + 2805, 0, 2627, + 2805, 0, 2627, + 2803, 0, 2625, + 2803, 0, 2623, + 2801, 0, 2621, + 2797, 0, 2617, + 2793, 0, 2613, + 2789, 0, 2607, + 2781, 0, 2599, + 2773, 0, 2589, + 2759, 0, 2573, + 2741, 617, 2553, + 2717, 1172, 2523, + 2681, 1473, 2481, + 2627, 1701, 2417, + 2545, 1893, 2313, + 2407, 2065, 2125, + 2111, 2225, 1595, + 0, 2377, 0, + 0, 2523, 0, + 0, 2667, 0, + 0, 2805, 0, + 0, 2943, 0, + 0, 3079, 0, + 0, 3215, 0, + 0, 3349, 0, + 0, 3483, 0, + 0, 3617, 0, + 0, 3749, 0, + 0, 3883, 0, + 0, 4015, 0, + 2939, 0, 2759, + 2939, 0, 2759, + 2937, 0, 2759, + 2937, 0, 2757, + 2935, 0, 2755, + 2935, 0, 2755, + 2931, 0, 2751, + 2929, 0, 2749, + 2925, 0, 2745, + 2921, 0, 2739, + 2913, 0, 2731, + 2903, 0, 2719, + 2891, 0, 2705, + 2873, 733, 2683, + 2849, 1299, 2653, + 2813, 1603, 2611, + 2759, 1831, 2547, + 2677, 2024, 2443, + 2539, 2197, 2253, + 2241, 2357, 1714, + 0, 2509, 0, + 0, 2655, 0, + 0, 2799, 0, + 0, 2937, 0, + 0, 3075, 0, + 0, 3211, 0, + 0, 3347, 0, + 0, 3481, 0, + 0, 3615, 0, + 0, 3749, 0, + 0, 3881, 0, + 0, 4015, 0, + 3071, 0, 2891, + 3071, 0, 2891, + 3071, 0, 2891, + 3069, 0, 2889, + 3069, 0, 2889, + 3067, 0, 2887, + 3065, 0, 2885, + 3063, 0, 2883, + 3061, 0, 2879, + 3057, 0, 2875, + 3053, 0, 2869, + 3045, 0, 2861, + 3035, 0, 2851, + 3023, 0, 2835, + 3005, 852, 2815, + 2979, 1427, 2785, + 2943, 1733, 2741, + 2891, 1962, 2677, + 2809, 2155, 2573, + 2669, 2329, 2383, + 2371, 2489, 1837, + 0, 2641, 0, + 0, 2787, 0, + 0, 2931, 0, + 0, 3069, 0, + 0, 3207, 0, + 0, 3345, 0, + 0, 3479, 0, + 0, 3613, 0, + 0, 3747, 0, + 0, 3881, 0, + 0, 4015, 0, + 3203, 0, 3023, + 3203, 0, 3023, + 3203, 0, 3023, + 3203, 0, 3021, + 3201, 0, 3021, + 3201, 0, 3019, + 3199, 0, 3019, + 3197, 0, 3017, + 3195, 0, 3015, + 3193, 0, 3011, + 3189, 0, 3007, + 3185, 0, 3001, + 3177, 0, 2993, + 3167, 0, 2981, + 3155, 0, 2967, + 3137, 974, 2945, + 3111, 1557, 2915, + 3075, 1864, 2873, + 3023, 2093, 2809, + 2941, 2287, 2703, + 2801, 2461, 2513, + 2503, 2621, 1961, + 0, 2773, 0, + 0, 2919, 0, + 0, 3063, 0, + 0, 3201, 0, + 0, 3339, 0, + 0, 3477, 0, + 0, 3611, 0, + 0, 3745, 0, + 0, 3879, 0, + 0, 4013, 0, + 3335, 0, 3155, + 3335, 0, 3155, + 3335, 0, 3155, + 3335, 0, 3153, + 3335, 0, 3153, + 3333, 0, 3153, + 3333, 0, 3151, + 3331, 0, 3151, + 3329, 0, 3149, + 3327, 0, 3145, + 3325, 0, 3143, + 3321, 0, 3139, + 3317, 0, 3133, + 3309, 0, 3125, + 3299, 0, 3113, + 3287, 0, 3099, + 3269, 1099, 3077, + 3243, 1687, 3047, + 3207, 1995, 3005, + 3155, 2225, 2939, + 3073, 2419, 2835, + 2933, 2591, 2643, + 2635, 2753, 2087, + 0, 2905, 0, + 0, 3051, 0, + 0, 3195, 0, + 0, 3335, 0, + 0, 3471, 0, + 0, 3609, 0, + 0, 3743, 0, + 0, 3877, 0, + 0, 4011, 0, + 3467, 0, 3287, + 3467, 0, 3287, + 3467, 0, 3287, + 3467, 0, 3285, + 3467, 0, 3285, + 3467, 0, 3285, + 3465, 0, 3285, + 3465, 0, 3283, + 3463, 0, 3281, + 3461, 0, 3279, + 3459, 0, 3277, + 3457, 0, 3275, + 3453, 0, 3269, + 3449, 0, 3263, + 3441, 0, 3255, + 3431, 0, 3245, + 3419, 0, 3229, + 3401, 1225, 3209, + 3375, 1817, 3179, + 3339, 2127, 3135, + 3287, 2357, 3071, + 3205, 2551, 2967, + 3065, 2723, 2773, + 2767, 2885, 2215, + 0, 3037, 0, + 0, 3183, 0, + 0, 3327, 0, + 0, 3467, 0, + 0, 3603, 0, + 0, 3741, 0, + 0, 3875, 0, + 0, 4011, 0, + 3599, 0, 3419, + 3599, 0, 3419, + 3599, 0, 3419, + 3599, 0, 3417, + 3599, 0, 3417, + 3599, 0, 3417, + 3599, 0, 3417, + 3597, 0, 3415, + 3597, 0, 3415, + 3595, 0, 3413, + 3593, 0, 3411, + 3591, 0, 3409, + 3589, 0, 3407, + 3585, 0, 3401, + 3581, 0, 3395, + 3573, 0, 3387, + 3563, 0, 3377, + 3551, 0, 3361, + 3533, 1353, 3341, + 3507, 1948, 3311, + 3471, 2257, 3267, + 3419, 2489, 3203, + 3337, 2683, 3097, + 3197, 2855, 2905, + 2897, 3017, 2345, + 0, 3169, 0, + 0, 3315, 0, + 0, 3459, 0, + 0, 3599, 0, + 0, 3737, 0, + 0, 3873, 0, + 0, 4007, 0, + 3731, 0, 3551, + 3731, 0, 3551, + 3731, 0, 3551, + 3731, 0, 3551, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3729, 0, 3547, + 3729, 0, 3547, + 3727, 0, 3545, + 3725, 0, 3543, + 3723, 0, 3541, + 3721, 0, 3537, + 3717, 0, 3533, + 3713, 0, 3527, + 3705, 0, 3519, + 3695, 0, 3509, + 3683, 0, 3493, + 3665, 1482, 3473, + 3639, 2079, 3443, + 3603, 2389, 3399, + 3551, 2621, 3335, + 3469, 2815, 3229, + 3329, 2987, 3035, + 3029, 3149, 2473, + 0, 3301, 0, + 0, 3447, 0, + 0, 3591, 0, + 0, 3731, 0, + 0, 3869, 0, + 0, 4005, 0, + 3865, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3861, 0, 3679, + 3861, 0, 3679, + 3859, 0, 3677, + 3859, 0, 3675, + 3855, 0, 3673, + 3853, 0, 3669, + 3849, 0, 3665, + 3845, 0, 3659, + 3837, 0, 3651, + 3827, 0, 3641, + 3815, 0, 3625, + 3797, 1612, 3605, + 3771, 2211, 3575, + 3735, 2521, 3531, + 3683, 2753, 3467, + 3601, 2947, 3361, + 3461, 3119, 3167, + 3161, 3281, 2605, + 0, 3433, 0, + 0, 3579, 0, + 0, 3723, 0, + 0, 3863, 0, + 0, 4001, 0, + 3997, 0, 3815, + 3997, 0, 3815, + 3997, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3813, + 3995, 0, 3813, + 3995, 0, 3813, + 3995, 0, 3813, + 3993, 0, 3811, + 3993, 0, 3811, + 3991, 0, 3809, + 3991, 0, 3807, + 3989, 0, 3805, + 3985, 0, 3801, + 3981, 0, 3797, + 3977, 0, 3791, + 3969, 0, 3783, + 3959, 0, 3773, + 3947, 0, 3757, + 3929, 1742, 3737, + 3903, 2343, 3707, + 3867, 2653, 3663, + 3815, 2885, 3597, + 3733, 3079, 3493, + 3593, 3251, 3299, + 3293, 3413, 2735, + 0, 3565, 0, + 0, 3711, 0, + 0, 3855, 0, + 0, 3995, 0, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3943, + 4095, 0, 3943, + 4095, 0, 3941, + 4095, 0, 3939, + 4095, 0, 3937, + 4095, 0, 3933, + 4095, 0, 3929, + 4095, 0, 3923, + 4095, 0, 3915, + 4093, 0, 3905, + 4079, 0, 3889, + 4061, 1873, 3869, + 4035, 2475, 3839, + 4001, 2785, 3795, + 3947, 3017, 3729, + 3865, 3211, 3625, + 3725, 3383, 3431, + 3425, 3545, 2867, + 0, 3697, 0, + 0, 3843, 0, + 0, 3987, 0, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4075, + 4095, 0, 4075, + 4095, 0, 4073, + 4095, 0, 4071, + 4095, 0, 4069, + 4095, 0, 4067, + 4095, 0, 4061, + 4095, 0, 4055, + 4095, 0, 4047, + 4095, 0, 4037, + 4095, 0, 4021, + 4095, 2004, 4001, + 4095, 2607, 3971, + 4095, 2917, 3927, + 4079, 3149, 3861, + 3997, 3343, 3757, + 3857, 3517, 3563, + 3557, 3677, 2997, + 0, 3829, 0, + 0, 3977, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2135, 4095, + 4095, 2739, 4095, + 4095, 3049, 4059, + 4095, 3281, 3993, + 4095, 3475, 3889, + 3989, 3649, 3695, + 3689, 3809, 3129, + 0, 3961, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2267, 4095, + 4095, 2871, 4095, + 4095, 3181, 4095, + 4095, 3413, 4095, + 4095, 3607, 4021, + 4095, 3781, 3827, + 3821, 3941, 3261, + 425, 171, 743, + 284, 251, 694, + 0, 341, 618, + 0, 439, 493, + 0, 543, 240, + 0, 653, 0, + 0, 769, 0, + 0, 887, 0, + 0, 1009, 0, + 0, 1134, 0, + 0, 1260, 0, + 0, 1388, 0, + 0, 1516, 0, + 0, 1646, 0, + 0, 1776, 0, + 0, 1907, 0, + 0, 2038, 0, + 0, 2169, 0, + 0, 2301, 0, + 0, 2433, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 558, 157, 792, + 457, 240, 748, + 272, 332, 682, + 0, 431, 574, + 0, 537, 374, + 0, 649, 0, + 0, 765, 0, + 0, 885, 0, + 0, 1007, 0, + 0, 1132, 0, + 0, 1259, 0, + 0, 1387, 0, + 0, 1516, 0, + 0, 1646, 0, + 0, 1776, 0, + 0, 1907, 0, + 0, 2038, 0, + 0, 2169, 0, + 0, 2301, 0, + 0, 2433, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 691, 138, 850, + 618, 224, 811, + 496, 319, 754, + 257, 421, 664, + 0, 529, 507, + 0, 642, 141, + 0, 760, 0, + 0, 881, 0, + 0, 1004, 0, + 0, 1130, 0, + 0, 1257, 0, + 0, 1385, 0, + 0, 1515, 0, + 0, 1645, 0, + 0, 1775, 0, + 0, 1906, 0, + 0, 2038, 0, + 0, 2169, 0, + 0, 2301, 0, + 0, 2433, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 824, 111, 918, + 770, 202, 885, + 687, 301, 836, + 544, 407, 762, + 235, 518, 640, + 0, 634, 399, + 0, 753, 0, + 0, 876, 0, + 0, 1001, 0, + 0, 1127, 0, + 0, 1255, 0, + 0, 1384, 0, + 0, 1514, 0, + 0, 1644, 0, + 0, 1775, 0, + 0, 1906, 0, + 0, 2037, 0, + 0, 2169, 0, + 0, 2301, 0, + 0, 2433, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 956, 72, 995, + 917, 170, 967, + 858, 276, 927, + 765, 387, 867, + 601, 502, 773, + 205, 622, 606, + 0, 744, 196, + 0, 869, 0, + 0, 995, 0, + 0, 1123, 0, + 0, 1252, 0, + 0, 1382, 0, + 0, 1512, 0, + 0, 1643, 0, + 0, 1774, 0, + 0, 1905, 0, + 0, 2037, 0, + 0, 2169, 0, + 0, 2301, 0, + 0, 2433, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1088, 14, 1080, + 1059, 125, 1058, + 1017, 240, 1025, + 954, 359, 978, + 852, 481, 906, + 667, 605, 787, + 161, 732, 556, + 0, 859, 0, + 0, 988, 0, + 0, 1117, 0, + 0, 1248, 0, + 0, 1378, 0, + 0, 1510, 0, + 0, 1641, 0, + 0, 1772, 0, + 0, 1904, 0, + 0, 2036, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1221, 0, 1175, + 1199, 55, 1156, + 1169, 187, 1130, + 1124, 319, 1093, + 1057, 450, 1038, + 948, 582, 953, + 743, 714, 805, + 94, 846, 478, + 0, 978, 0, + 0, 1110, 0, + 0, 1242, 0, + 0, 1374, 0, + 0, 1506, 0, + 0, 1639, 0, + 0, 1771, 0, + 0, 1903, 0, + 0, 2035, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1353, 0, 1276, + 1337, 0, 1262, + 1315, 105, 1241, + 1283, 259, 1212, + 1236, 406, 1171, + 1166, 550, 1108, + 1050, 690, 1009, + 828, 828, 828, + 0, 965, 349, + 0, 1100, 0, + 0, 1235, 0, + 0, 1369, 0, + 0, 1502, 0, + 0, 1636, 0, + 0, 1768, 0, + 0, 1901, 0, + 0, 2034, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1485, 0, 1384, + 1473, 0, 1373, + 1457, 0, 1357, + 1434, 164, 1335, + 1401, 340, 1303, + 1353, 502, 1257, + 1280, 656, 1188, + 1159, 803, 1074, + 922, 947, 858, + 0, 1087, 83, + 0, 1225, 0, + 0, 1361, 0, + 0, 1497, 0, + 0, 1631, 0, + 0, 1765, 0, + 0, 1899, 0, + 0, 2032, 0, + 0, 2165, 0, + 0, 2297, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1618, 0, 1497, + 1609, 0, 1488, + 1596, 0, 1476, + 1580, 0, 1459, + 1556, 232, 1435, + 1523, 430, 1402, + 1473, 605, 1352, + 1398, 767, 1276, + 1273, 921, 1149, + 1023, 1068, 894, + 0, 1211, 0, + 0, 1351, 0, + 0, 1489, 0, + 0, 1626, 0, + 0, 1761, 0, + 0, 1896, 0, + 0, 2030, 0, + 0, 2163, 0, + 0, 2297, 0, + 0, 2429, 0, + 0, 2561, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1750, 0, 1615, + 1743, 0, 1608, + 1734, 0, 1598, + 1722, 0, 1586, + 1705, 31, 1568, + 1681, 310, 1543, + 1647, 527, 1507, + 1597, 714, 1454, + 1520, 883, 1372, + 1391, 1041, 1234, + 1130, 1192, 938, + 0, 1337, 0, + 0, 1479, 0, + 0, 1618, 0, + 0, 1755, 0, + 0, 1891, 0, + 0, 2026, 0, + 0, 2161, 0, + 0, 2295, 0, + 0, 2427, 0, + 0, 2561, 0, + 0, 2693, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1882, 0, 1736, + 1877, 0, 1730, + 1870, 0, 1723, + 1861, 0, 1713, + 1849, 0, 1700, + 1831, 75, 1681, + 1807, 397, 1655, + 1773, 632, 1618, + 1722, 828, 1562, + 1644, 1003, 1476, + 1512, 1164, 1326, + 1242, 1317, 992, + 0, 1465, 0, + 0, 1608, 0, + 0, 1748, 0, + 0, 1886, 0, + 0, 2022, 0, + 0, 2157, 0, + 0, 2293, 0, + 0, 2427, 0, + 0, 2559, 0, + 0, 2693, 0, + 0, 2825, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2014, 0, 1859, + 2010, 0, 1855, + 2005, 0, 1850, + 1999, 0, 1842, + 1989, 0, 1832, + 1977, 0, 1818, + 1959, 128, 1799, + 1935, 492, 1772, + 1900, 742, 1733, + 1849, 946, 1676, + 1770, 1125, 1585, + 1636, 1290, 1426, + 1359, 1445, 1054, + 0, 1593, 0, + 0, 1737, 0, + 0, 1878, 0, + 0, 2017, 0, + 0, 2153, 0, + 0, 2289, 0, + 0, 2423, 0, + 0, 2557, 0, + 0, 2691, 0, + 0, 2825, 0, + 0, 2957, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2147, 0, 1985, + 2143, 0, 1982, + 2139, 0, 1977, + 2135, 0, 1972, + 2127, 0, 1964, + 2119, 0, 1954, + 2105, 0, 1940, + 2089, 191, 1920, + 2063, 594, 1893, + 2029, 857, 1853, + 1977, 1067, 1793, + 1897, 1250, 1700, + 1762, 1417, 1533, + 1480, 1573, 1126, + 0, 1723, 0, + 0, 1868, 0, + 0, 2009, 0, + 0, 2147, 0, + 0, 2285, 0, + 0, 2421, 0, + 0, 2555, 0, + 0, 2689, 0, + 0, 2823, 0, + 0, 2957, 0, + 0, 3089, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2279, 0, 2111, + 2277, 0, 2109, + 2273, 0, 2107, + 2269, 0, 2103, + 2265, 0, 2097, + 2257, 0, 2089, + 2249, 0, 2079, + 2235, 0, 2063, + 2219, 264, 2044, + 2193, 702, 2016, + 2159, 976, 1975, + 2107, 1191, 1914, + 2026, 1377, 1818, + 1889, 1545, 1645, + 1603, 1703, 1208, + 0, 1853, 0, + 0, 1998, 0, + 0, 2139, 0, + 0, 2279, 0, + 0, 2417, 0, + 0, 2553, 0, + 0, 2687, 0, + 0, 2821, 0, + 0, 2955, 0, + 0, 3089, 0, + 0, 3221, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3885, 0, + 0, 4017, 0, + 2411, 0, 2241, + 2409, 0, 2239, + 2407, 0, 2237, + 2405, 0, 2233, + 2401, 0, 2229, + 2395, 0, 2223, + 2389, 0, 2215, + 2379, 0, 2205, + 2367, 0, 2189, + 2349, 345, 2169, + 2323, 816, 2141, + 2289, 1098, 2099, + 2235, 1317, 2038, + 2155, 1505, 1940, + 2018, 1675, 1762, + 1728, 1833, 1298, + 0, 1984, 0, + 0, 2129, 0, + 0, 2271, 0, + 0, 2411, 0, + 0, 2549, 0, + 0, 2685, 0, + 0, 2819, 0, + 0, 2953, 0, + 0, 3087, 0, + 0, 3221, 0, + 0, 3353, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4017, 0, + 2543, 0, 2369, + 2541, 0, 2369, + 2541, 0, 2367, + 2537, 0, 2363, + 2535, 0, 2361, + 2531, 0, 2357, + 2527, 0, 2351, + 2519, 0, 2343, + 2511, 0, 2333, + 2497, 0, 2317, + 2479, 436, 2297, + 2455, 933, 2269, + 2419, 1223, 2227, + 2367, 1445, 2163, + 2285, 1634, 2063, + 2147, 1805, 1882, + 1855, 1964, 1396, + 0, 2115, 0, + 0, 2261, 0, + 0, 2403, 0, + 0, 2543, 0, + 0, 2679, 0, + 0, 2817, 0, + 0, 2951, 0, + 0, 3085, 0, + 0, 3219, 0, + 0, 3353, 0, + 0, 3485, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4017, 0, + 2675, 0, 2499, + 2675, 0, 2499, + 2673, 0, 2497, + 2671, 0, 2495, + 2669, 0, 2493, + 2667, 0, 2489, + 2663, 0, 2485, + 2657, 0, 2479, + 2651, 0, 2471, + 2641, 0, 2461, + 2629, 0, 2447, + 2611, 534, 2425, + 2585, 1054, 2397, + 2549, 1349, 2355, + 2497, 1573, 2291, + 2415, 1764, 2189, + 2277, 1935, 2005, + 1984, 2095, 1501, + 0, 2247, 0, + 0, 2393, 0, + 0, 2535, 0, + 0, 2675, 0, + 0, 2811, 0, + 0, 2947, 0, + 0, 3083, 0, + 0, 3217, 0, + 0, 3351, 0, + 0, 3485, 0, + 0, 3617, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 2807, 0, 2629, + 2807, 0, 2629, + 2805, 0, 2629, + 2805, 0, 2627, + 2803, 0, 2625, + 2801, 0, 2623, + 2797, 0, 2619, + 2795, 0, 2615, + 2789, 0, 2609, + 2783, 0, 2601, + 2773, 0, 2591, + 2759, 0, 2575, + 2741, 639, 2555, + 2717, 1178, 2525, + 2681, 1477, 2483, + 2629, 1703, 2419, + 2547, 1894, 2317, + 2407, 2067, 2131, + 2113, 2225, 1612, + 0, 2377, 0, + 0, 2523, 0, + 0, 2667, 0, + 0, 2807, 0, + 0, 2943, 0, + 0, 3079, 0, + 0, 3215, 0, + 0, 3349, 0, + 0, 3483, 0, + 0, 3617, 0, + 0, 3749, 0, + 0, 3883, 0, + 0, 4015, 0, + 2939, 0, 2761, + 2939, 0, 2761, + 2939, 0, 2759, + 2937, 0, 2759, + 2935, 0, 2757, + 2935, 0, 2755, + 2933, 0, 2753, + 2929, 0, 2749, + 2925, 0, 2745, + 2921, 0, 2739, + 2913, 0, 2731, + 2905, 0, 2721, + 2891, 0, 2705, + 2873, 750, 2685, + 2849, 1304, 2655, + 2813, 1605, 2613, + 2759, 1833, 2549, + 2679, 2025, 2445, + 2539, 2197, 2257, + 2243, 2357, 1727, + 0, 2509, 0, + 0, 2655, 0, + 0, 2799, 0, + 0, 2937, 0, + 0, 3075, 0, + 0, 3213, 0, + 0, 3347, 0, + 0, 3481, 0, + 0, 3615, 0, + 0, 3749, 0, + 0, 3881, 0, + 0, 4015, 0, + 3071, 0, 2893, + 3071, 0, 2891, + 3071, 0, 2891, + 3069, 0, 2891, + 3069, 0, 2889, + 3067, 0, 2889, + 3067, 0, 2887, + 3065, 0, 2883, + 3061, 0, 2881, + 3057, 0, 2877, + 3053, 0, 2871, + 3045, 0, 2863, + 3037, 0, 2851, + 3023, 0, 2837, + 3005, 865, 2815, + 2981, 1431, 2785, + 2945, 1735, 2743, + 2891, 1963, 2679, + 2809, 2157, 2575, + 2671, 2329, 2385, + 2373, 2489, 1847, + 0, 2641, 0, + 0, 2787, 0, + 0, 2931, 0, + 0, 3069, 0, + 0, 3207, 0, + 0, 3345, 0, + 0, 3479, 0, + 0, 3613, 0, + 0, 3747, 0, + 0, 3881, 0, + 0, 4015, 0, + 3203, 0, 3023, + 3203, 0, 3023, + 3203, 0, 3023, + 3203, 0, 3023, + 3201, 0, 3021, + 3201, 0, 3021, + 3199, 0, 3019, + 3199, 0, 3017, + 3195, 0, 3015, + 3193, 0, 3011, + 3189, 0, 3007, + 3185, 0, 3001, + 3177, 0, 2993, + 3167, 0, 2983, + 3155, 0, 2967, + 3137, 984, 2947, + 3111, 1559, 2917, + 3077, 1865, 2873, + 3023, 2095, 2809, + 2941, 2287, 2705, + 2801, 2461, 2515, + 2505, 2621, 1969, + 0, 2773, 0, + 0, 2919, 0, + 0, 3063, 0, + 0, 3203, 0, + 0, 3339, 0, + 0, 3477, 0, + 0, 3611, 0, + 0, 3745, 0, + 0, 3879, 0, + 0, 4013, 0, + 3335, 0, 3155, + 3335, 0, 3155, + 3335, 0, 3155, + 3335, 0, 3155, + 3335, 0, 3153, + 3333, 0, 3153, + 3333, 0, 3151, + 3331, 0, 3151, + 3329, 0, 3149, + 3327, 0, 3147, + 3325, 0, 3143, + 3321, 0, 3139, + 3317, 0, 3133, + 3309, 0, 3125, + 3299, 0, 3113, + 3287, 0, 3099, + 3269, 1106, 3077, + 3243, 1689, 3049, + 3207, 1996, 3005, + 3155, 2225, 2941, + 3073, 2419, 2837, + 2933, 2593, 2645, + 2635, 2753, 2093, + 0, 2905, 0, + 0, 3051, 0, + 0, 3195, 0, + 0, 3335, 0, + 0, 3471, 0, + 0, 3609, 0, + 0, 3743, 0, + 0, 3877, 0, + 0, 4011, 0, + 3467, 0, 3287, + 3467, 0, 3287, + 3467, 0, 3287, + 3467, 0, 3287, + 3467, 0, 3285, + 3467, 0, 3285, + 3465, 0, 3285, + 3465, 0, 3283, + 3463, 0, 3283, + 3461, 0, 3281, + 3459, 0, 3277, + 3457, 0, 3275, + 3453, 0, 3271, + 3449, 0, 3265, + 3441, 0, 3257, + 3431, 0, 3245, + 3419, 0, 3231, + 3401, 1231, 3209, + 3375, 1819, 3179, + 3339, 2127, 3137, + 3287, 2357, 3071, + 3205, 2551, 2967, + 3065, 2725, 2775, + 2767, 2885, 2219, + 0, 3037, 0, + 0, 3183, 0, + 0, 3327, 0, + 0, 3467, 0, + 0, 3603, 0, + 0, 3741, 0, + 0, 3875, 0, + 0, 4011, 0, + 3599, 0, 3419, + 3599, 0, 3419, + 3599, 0, 3419, + 3599, 0, 3419, + 3599, 0, 3417, + 3599, 0, 3417, + 3599, 0, 3417, + 3597, 0, 3417, + 3597, 0, 3415, + 3595, 0, 3413, + 3593, 0, 3413, + 3591, 0, 3409, + 3589, 0, 3407, + 3585, 0, 3403, + 3581, 0, 3397, + 3573, 0, 3389, + 3563, 0, 3377, + 3551, 0, 3361, + 3533, 1357, 3341, + 3507, 1949, 3311, + 3471, 2259, 3267, + 3419, 2489, 3203, + 3337, 2683, 3099, + 3197, 2855, 2905, + 2899, 3017, 2347, + 0, 3169, 0, + 0, 3315, 0, + 0, 3459, 0, + 0, 3599, 0, + 0, 3737, 0, + 0, 3873, 0, + 0, 4007, 0, + 3731, 0, 3551, + 3731, 0, 3551, + 3731, 0, 3551, + 3731, 0, 3551, + 3731, 0, 3551, + 3731, 0, 3549, + 3731, 0, 3549, + 3731, 0, 3549, + 3729, 0, 3549, + 3729, 0, 3547, + 3727, 0, 3545, + 3727, 0, 3543, + 3723, 0, 3541, + 3721, 0, 3539, + 3717, 0, 3533, + 3713, 0, 3527, + 3705, 0, 3519, + 3695, 0, 3509, + 3683, 0, 3493, + 3665, 1485, 3473, + 3639, 2081, 3443, + 3603, 2391, 3399, + 3551, 2621, 3335, + 3469, 2815, 3229, + 3329, 2987, 3037, + 3031, 3149, 2477, + 0, 3301, 0, + 0, 3447, 0, + 0, 3591, 0, + 0, 3731, 0, + 0, 3869, 0, + 0, 4005, 0, + 3865, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3861, 0, 3679, + 3861, 0, 3679, + 3859, 0, 3677, + 3859, 0, 3675, + 3855, 0, 3673, + 3853, 0, 3671, + 3849, 0, 3665, + 3845, 0, 3659, + 3837, 0, 3651, + 3827, 0, 3641, + 3815, 0, 3625, + 3797, 1614, 3605, + 3771, 2211, 3575, + 3735, 2521, 3531, + 3683, 2753, 3467, + 3601, 2947, 3361, + 3461, 3119, 3169, + 3161, 3281, 2607, + 0, 3433, 0, + 0, 3579, 0, + 0, 3723, 0, + 0, 3863, 0, + 0, 4001, 0, + 3997, 0, 3815, + 3997, 0, 3815, + 3997, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3813, + 3995, 0, 3813, + 3995, 0, 3813, + 3995, 0, 3813, + 3993, 0, 3811, + 3993, 0, 3811, + 3991, 0, 3809, + 3991, 0, 3807, + 3989, 0, 3805, + 3985, 0, 3803, + 3981, 0, 3797, + 3977, 0, 3791, + 3969, 0, 3783, + 3959, 0, 3773, + 3947, 0, 3757, + 3929, 1744, 3737, + 3903, 2343, 3707, + 3867, 2653, 3663, + 3815, 2885, 3599, + 3733, 3079, 3493, + 3593, 3251, 3299, + 3293, 3413, 2737, + 0, 3565, 0, + 0, 3711, 0, + 0, 3855, 0, + 0, 3995, 0, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3943, + 4095, 0, 3943, + 4095, 0, 3941, + 4095, 0, 3939, + 4095, 0, 3937, + 4095, 0, 3935, + 4095, 0, 3929, + 4095, 0, 3923, + 4095, 0, 3915, + 4093, 0, 3905, + 4079, 0, 3889, + 4061, 1874, 3869, + 4037, 2475, 3839, + 4001, 2785, 3795, + 3947, 3017, 3731, + 3865, 3211, 3625, + 3725, 3385, 3431, + 3425, 3545, 2867, + 0, 3697, 0, + 0, 3843, 0, + 0, 3987, 0, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4075, + 4095, 0, 4075, + 4095, 0, 4073, + 4095, 0, 4071, + 4095, 0, 4069, + 4095, 0, 4067, + 4095, 0, 4061, + 4095, 0, 4055, + 4095, 0, 4047, + 4095, 0, 4037, + 4095, 0, 4021, + 4095, 2005, 4001, + 4095, 2607, 3971, + 4095, 2917, 3927, + 4079, 3149, 3863, + 3997, 3343, 3757, + 3857, 3517, 3563, + 3557, 3677, 2999, + 0, 3829, 0, + 0, 3977, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2135, 4095, + 4095, 2739, 4095, + 4095, 3049, 4059, + 4095, 3281, 3995, + 4095, 3475, 3889, + 3989, 3649, 3695, + 3689, 3809, 3129, + 0, 3961, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2267, 4095, + 4095, 2871, 4095, + 4095, 3181, 4095, + 4095, 3413, 4095, + 4095, 3607, 4021, + 4095, 3781, 3827, + 3821, 3941, 3261, + 532, 243, 872, + 424, 313, 835, + 222, 392, 781, + 0, 480, 697, + 0, 576, 552, + 0, 680, 237, + 0, 789, 0, + 0, 903, 0, + 0, 1022, 0, + 0, 1143, 0, + 0, 1267, 0, + 0, 1393, 0, + 0, 1520, 0, + 0, 1649, 0, + 0, 1779, 0, + 0, 1909, 0, + 0, 2039, 0, + 0, 2171, 0, + 0, 2301, 0, + 0, 2433, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 640, 231, 909, + 557, 303, 875, + 416, 384, 826, + 111, 473, 750, + 0, 571, 625, + 0, 675, 372, + 0, 786, 0, + 0, 901, 0, + 0, 1020, 0, + 0, 1141, 0, + 0, 1266, 0, + 0, 1392, 0, + 0, 1520, 0, + 0, 1649, 0, + 0, 1778, 0, + 0, 1908, 0, + 0, 2039, 0, + 0, 2171, 0, + 0, 2301, 0, + 0, 2433, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 754, 215, 955, + 690, 289, 924, + 589, 372, 880, + 404, 464, 814, + 0, 563, 706, + 0, 669, 506, + 0, 781, 0, + 0, 897, 0, + 0, 1017, 0, + 0, 1139, 0, + 0, 1264, 0, + 0, 1391, 0, + 0, 1519, 0, + 0, 1648, 0, + 0, 1778, 0, + 0, 1908, 0, + 0, 2039, 0, + 0, 2169, 0, + 0, 2301, 0, + 0, 2433, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 871, 192, 1009, + 823, 270, 982, + 750, 356, 944, + 628, 451, 886, + 389, 553, 796, + 0, 661, 639, + 0, 774, 273, + 0, 892, 0, + 0, 1013, 0, + 0, 1136, 0, + 0, 1262, 0, + 0, 1389, 0, + 0, 1518, 0, + 0, 1647, 0, + 0, 1777, 0, + 0, 1908, 0, + 0, 2038, 0, + 0, 2169, 0, + 0, 2301, 0, + 0, 2433, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 992, 160, 1073, + 956, 243, 1049, + 902, 334, 1017, + 819, 433, 968, + 676, 539, 895, + 367, 650, 772, + 0, 766, 531, + 0, 885, 0, + 0, 1008, 0, + 0, 1132, 0, + 0, 1259, 0, + 0, 1387, 0, + 0, 1516, 0, + 0, 1646, 0, + 0, 1776, 0, + 0, 1907, 0, + 0, 2038, 0, + 0, 2169, 0, + 0, 2301, 0, + 0, 2433, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1116, 113, 1146, + 1088, 204, 1126, + 1049, 302, 1099, + 990, 408, 1059, + 897, 519, 1000, + 733, 634, 905, + 337, 754, 738, + 0, 876, 328, + 0, 1001, 0, + 0, 1127, 0, + 0, 1255, 0, + 0, 1384, 0, + 0, 1514, 0, + 0, 1644, 0, + 0, 1775, 0, + 0, 1906, 0, + 0, 2037, 0, + 0, 2169, 0, + 0, 2301, 0, + 0, 2433, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1241, 42, 1229, + 1221, 146, 1212, + 1191, 257, 1190, + 1149, 372, 1157, + 1086, 491, 1110, + 985, 613, 1038, + 799, 737, 919, + 293, 864, 688, + 0, 991, 0, + 0, 1120, 0, + 0, 1250, 0, + 0, 1380, 0, + 0, 1511, 0, + 0, 1642, 0, + 0, 1773, 0, + 0, 1905, 0, + 0, 2036, 0, + 0, 2169, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1368, 0, 1320, + 1353, 56, 1307, + 1331, 187, 1288, + 1301, 319, 1262, + 1256, 451, 1225, + 1189, 582, 1170, + 1080, 714, 1085, + 875, 846, 937, + 226, 978, 610, + 0, 1110, 0, + 0, 1242, 0, + 0, 1374, 0, + 0, 1507, 0, + 0, 1639, 0, + 0, 1771, 0, + 0, 1903, 0, + 0, 2035, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1497, 0, 1419, + 1485, 0, 1408, + 1469, 74, 1394, + 1447, 237, 1373, + 1415, 391, 1345, + 1369, 538, 1303, + 1298, 682, 1240, + 1183, 822, 1141, + 960, 960, 960, + 118, 1097, 481, + 0, 1232, 0, + 0, 1367, 0, + 0, 1501, 0, + 0, 1634, 0, + 0, 1768, 0, + 0, 1901, 0, + 0, 2033, 0, + 0, 2165, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1626, 0, 1525, + 1617, 0, 1516, + 1606, 0, 1505, + 1589, 97, 1489, + 1566, 296, 1467, + 1533, 472, 1435, + 1485, 634, 1389, + 1412, 788, 1320, + 1291, 935, 1206, + 1054, 1078, 990, + 0, 1219, 216, + 0, 1357, 0, + 0, 1493, 0, + 0, 1629, 0, + 0, 1763, 0, + 0, 1897, 0, + 0, 2031, 0, + 0, 2165, 0, + 0, 2297, 0, + 0, 2429, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1756, 0, 1636, + 1750, 0, 1630, + 1741, 0, 1621, + 1729, 0, 1608, + 1712, 126, 1591, + 1688, 364, 1568, + 1655, 562, 1534, + 1606, 737, 1484, + 1530, 899, 1408, + 1405, 1052, 1281, + 1155, 1200, 1026, + 0, 1343, 0, + 0, 1483, 0, + 0, 1621, 0, + 0, 1758, 0, + 0, 1893, 0, + 0, 2028, 0, + 0, 2161, 0, + 0, 2295, 0, + 0, 2429, 0, + 0, 2561, 0, + 0, 2693, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1887, 0, 1752, + 1882, 0, 1747, + 1875, 0, 1740, + 1866, 0, 1731, + 1854, 0, 1718, + 1837, 163, 1700, + 1813, 442, 1675, + 1779, 659, 1639, + 1729, 846, 1586, + 1652, 1015, 1505, + 1523, 1173, 1366, + 1262, 1324, 1070, + 0, 1469, 0, + 0, 1611, 0, + 0, 1750, 0, + 0, 1888, 0, + 0, 2024, 0, + 0, 2159, 0, + 0, 2293, 0, + 0, 2427, 0, + 0, 2559, 0, + 0, 2693, 0, + 0, 2825, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2018, 0, 1872, + 2014, 0, 1868, + 2009, 0, 1862, + 2002, 0, 1855, + 1993, 0, 1845, + 1981, 0, 1832, + 1963, 207, 1813, + 1939, 529, 1787, + 1905, 764, 1750, + 1854, 960, 1695, + 1776, 1135, 1608, + 1644, 1297, 1458, + 1374, 1450, 1123, + 0, 1597, 0, + 0, 1740, 0, + 0, 1880, 0, + 0, 2018, 0, + 0, 2155, 0, + 0, 2289, 0, + 0, 2425, 0, + 0, 2559, 0, + 0, 2691, 0, + 0, 2825, 0, + 0, 2957, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2149, 0, 1994, + 2147, 0, 1991, + 2143, 0, 1987, + 2137, 0, 1982, + 2131, 0, 1974, + 2121, 0, 1964, + 2109, 0, 1950, + 2091, 260, 1931, + 2067, 624, 1904, + 2032, 874, 1866, + 1981, 1078, 1808, + 1902, 1258, 1717, + 1768, 1422, 1559, + 1491, 1577, 1186, + 0, 1725, 0, + 0, 1869, 0, + 0, 2010, 0, + 0, 2149, 0, + 0, 2285, 0, + 0, 2421, 0, + 0, 2555, 0, + 0, 2689, 0, + 0, 2823, 0, + 0, 2957, 0, + 0, 3089, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2281, 0, 2119, + 2279, 0, 2117, + 2275, 0, 2113, + 2271, 0, 2109, + 2267, 0, 2105, + 2261, 0, 2097, + 2251, 0, 2087, + 2239, 0, 2073, + 2221, 323, 2053, + 2195, 726, 2025, + 2161, 989, 1985, + 2109, 1200, 1926, + 2029, 1382, 1832, + 1894, 1549, 1665, + 1612, 1706, 1258, + 0, 1855, 0, + 0, 2000, 0, + 0, 2141, 0, + 0, 2279, 0, + 0, 2417, 0, + 0, 2553, 0, + 0, 2687, 0, + 0, 2821, 0, + 0, 2955, 0, + 0, 3089, 0, + 0, 3221, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3885, 0, + 0, 4017, 0, + 2413, 0, 2245, + 2411, 0, 2243, + 2409, 0, 2241, + 2405, 0, 2239, + 2401, 0, 2235, + 2397, 0, 2229, + 2391, 0, 2221, + 2381, 0, 2211, + 2367, 0, 2197, + 2351, 396, 2177, + 2325, 834, 2147, + 2291, 1108, 2107, + 2239, 1323, 2047, + 2157, 1509, 1950, + 2021, 1678, 1777, + 1735, 1835, 1340, + 0, 1985, 0, + 0, 2131, 0, + 0, 2273, 0, + 0, 2411, 0, + 0, 2549, 0, + 0, 2685, 0, + 0, 2819, 0, + 0, 2953, 0, + 0, 3087, 0, + 0, 3221, 0, + 0, 3353, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4017, 0, + 2543, 0, 2373, + 2543, 0, 2373, + 2541, 0, 2371, + 2539, 0, 2369, + 2537, 0, 2365, + 2533, 0, 2361, + 2527, 0, 2355, + 2521, 0, 2347, + 2511, 0, 2337, + 2499, 0, 2323, + 2481, 477, 2301, + 2455, 948, 2273, + 2421, 1230, 2231, + 2369, 1449, 2171, + 2287, 1637, 2071, + 2149, 1807, 1894, + 1860, 1965, 1430, + 0, 2115, 0, + 0, 2261, 0, + 0, 2403, 0, + 0, 2543, 0, + 0, 2681, 0, + 0, 2817, 0, + 0, 2951, 0, + 0, 3085, 0, + 0, 3219, 0, + 0, 3353, 0, + 0, 3485, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4017, 0, + 2675, 0, 2503, + 2675, 0, 2501, + 2673, 0, 2501, + 2673, 0, 2499, + 2671, 0, 2497, + 2667, 0, 2493, + 2663, 0, 2489, + 2659, 0, 2483, + 2651, 0, 2475, + 2643, 0, 2465, + 2629, 0, 2449, + 2611, 568, 2429, + 2587, 1065, 2401, + 2551, 1355, 2359, + 2499, 1577, 2295, + 2417, 1766, 2195, + 2279, 1937, 2014, + 1987, 2095, 1528, + 0, 2247, 0, + 0, 2393, 0, + 0, 2535, 0, + 0, 2675, 0, + 0, 2813, 0, + 0, 2949, 0, + 0, 3083, 0, + 0, 3217, 0, + 0, 3351, 0, + 0, 3485, 0, + 0, 3617, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 2807, 0, 2633, + 2807, 0, 2631, + 2807, 0, 2631, + 2805, 0, 2629, + 2803, 0, 2627, + 2801, 0, 2625, + 2799, 0, 2621, + 2795, 0, 2617, + 2789, 0, 2611, + 2783, 0, 2603, + 2773, 0, 2593, + 2761, 0, 2579, + 2743, 666, 2557, + 2717, 1186, 2529, + 2681, 1481, 2487, + 2629, 1705, 2423, + 2547, 1896, 2321, + 2409, 2067, 2137, + 2115, 2227, 1633, + 0, 2379, 0, + 0, 2525, 0, + 0, 2667, 0, + 0, 2807, 0, + 0, 2943, 0, + 0, 3081, 0, + 0, 3215, 0, + 0, 3349, 0, + 0, 3483, 0, + 0, 3617, 0, + 0, 3749, 0, + 0, 3883, 0, + 0, 4015, 0, + 2939, 0, 2763, + 2939, 0, 2763, + 2939, 0, 2761, + 2937, 0, 2761, + 2937, 0, 2759, + 2935, 0, 2757, + 2933, 0, 2755, + 2931, 0, 2751, + 2927, 0, 2747, + 2921, 0, 2741, + 2915, 0, 2733, + 2905, 0, 2723, + 2891, 0, 2707, + 2875, 771, 2687, + 2849, 1310, 2657, + 2813, 1609, 2615, + 2761, 1835, 2551, + 2679, 2026, 2449, + 2541, 2199, 2263, + 2245, 2359, 1744, + 0, 2509, 0, + 0, 2657, 0, + 0, 2799, 0, + 0, 2939, 0, + 0, 3075, 0, + 0, 3213, 0, + 0, 3347, 0, + 0, 3481, 0, + 0, 3615, 0, + 0, 3749, 0, + 0, 3881, 0, + 0, 4015, 0, + 3071, 0, 2893, + 3071, 0, 2893, + 3071, 0, 2893, + 3071, 0, 2891, + 3069, 0, 2891, + 3069, 0, 2889, + 3067, 0, 2887, + 3065, 0, 2885, + 3061, 0, 2881, + 3057, 0, 2877, + 3053, 0, 2871, + 3045, 0, 2863, + 3037, 0, 2853, + 3023, 0, 2837, + 3005, 882, 2817, + 2981, 1436, 2787, + 2945, 1738, 2745, + 2891, 1965, 2681, + 2811, 2157, 2577, + 2671, 2329, 2389, + 2375, 2489, 1860, + 0, 2641, 0, + 0, 2787, 0, + 0, 2931, 0, + 0, 3071, 0, + 0, 3207, 0, + 0, 3345, 0, + 0, 3479, 0, + 0, 3613, 0, + 0, 3747, 0, + 0, 3881, 0, + 0, 4015, 0, + 3203, 0, 3025, + 3203, 0, 3025, + 3203, 0, 3023, + 3203, 0, 3023, + 3201, 0, 3023, + 3201, 0, 3021, + 3199, 0, 3021, + 3199, 0, 3019, + 3197, 0, 3015, + 3193, 0, 3013, + 3189, 0, 3009, + 3185, 0, 3003, + 3177, 0, 2995, + 3169, 0, 2983, + 3155, 0, 2969, + 3137, 997, 2947, + 3113, 1563, 2919, + 3077, 1867, 2875, + 3023, 2095, 2811, + 2941, 2289, 2707, + 2803, 2461, 2517, + 2505, 2621, 1979, + 0, 2773, 0, + 0, 2919, 0, + 0, 3063, 0, + 0, 3203, 0, + 0, 3339, 0, + 0, 3477, 0, + 0, 3611, 0, + 0, 3745, 0, + 0, 3879, 0, + 0, 4013, 0, + 3335, 0, 3155, + 3335, 0, 3155, + 3335, 0, 3155, + 3335, 0, 3155, + 3335, 0, 3155, + 3333, 0, 3153, + 3333, 0, 3153, + 3331, 0, 3151, + 3331, 0, 3149, + 3329, 0, 3147, + 3325, 0, 3143, + 3321, 0, 3139, + 3317, 0, 3133, + 3309, 0, 3125, + 3301, 0, 3115, + 3287, 0, 3099, + 3269, 1116, 3079, + 3245, 1692, 3049, + 3209, 1997, 3007, + 3155, 2227, 2941, + 3073, 2419, 2837, + 2933, 2593, 2647, + 2637, 2753, 2101, + 0, 2905, 0, + 0, 3051, 0, + 0, 3195, 0, + 0, 3335, 0, + 0, 3471, 0, + 0, 3609, 0, + 0, 3743, 0, + 0, 3877, 0, + 0, 4011, 0, + 3467, 0, 3287, + 3467, 0, 3287, + 3467, 0, 3287, + 3467, 0, 3287, + 3467, 0, 3287, + 3467, 0, 3285, + 3465, 0, 3285, + 3465, 0, 3285, + 3463, 0, 3283, + 3463, 0, 3281, + 3461, 0, 3279, + 3457, 0, 3275, + 3453, 0, 3271, + 3449, 0, 3265, + 3441, 0, 3257, + 3431, 0, 3245, + 3419, 0, 3231, + 3401, 1238, 3209, + 3375, 1821, 3181, + 3341, 2129, 3137, + 3287, 2357, 3073, + 3205, 2551, 2969, + 3065, 2725, 2777, + 2767, 2885, 2225, + 0, 3037, 0, + 0, 3183, 0, + 0, 3327, 0, + 0, 3467, 0, + 0, 3605, 0, + 0, 3741, 0, + 0, 3875, 0, + 0, 4011, 0, + 3599, 0, 3419, + 3599, 0, 3419, + 3599, 0, 3419, + 3599, 0, 3419, + 3599, 0, 3419, + 3599, 0, 3417, + 3599, 0, 3417, + 3597, 0, 3417, + 3597, 0, 3415, + 3595, 0, 3415, + 3595, 0, 3413, + 3591, 0, 3411, + 3589, 0, 3407, + 3585, 0, 3403, + 3581, 0, 3397, + 3573, 0, 3389, + 3563, 0, 3377, + 3551, 0, 3363, + 3533, 1363, 3341, + 3507, 1951, 3311, + 3471, 2259, 3269, + 3419, 2489, 3203, + 3337, 2683, 3099, + 3197, 2857, 2907, + 2899, 3017, 2351, + 0, 3169, 0, + 0, 3315, 0, + 0, 3459, 0, + 0, 3599, 0, + 0, 3737, 0, + 0, 3873, 0, + 0, 4007, 0, + 3733, 0, 3551, + 3731, 0, 3551, + 3731, 0, 3551, + 3731, 0, 3551, + 3731, 0, 3551, + 3731, 0, 3551, + 3731, 0, 3549, + 3731, 0, 3549, + 3729, 0, 3549, + 3729, 0, 3547, + 3727, 0, 3545, + 3727, 0, 3545, + 3725, 0, 3541, + 3721, 0, 3539, + 3717, 0, 3535, + 3713, 0, 3529, + 3705, 0, 3521, + 3695, 0, 3509, + 3683, 0, 3495, + 3665, 1489, 3473, + 3639, 2081, 3443, + 3603, 2391, 3401, + 3551, 2621, 3335, + 3469, 2815, 3231, + 3329, 2989, 3037, + 3031, 3149, 2479, + 0, 3301, 0, + 0, 3447, 0, + 0, 3591, 0, + 0, 3731, 0, + 0, 3869, 0, + 0, 4005, 0, + 3865, 0, 3683, + 3865, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3681, + 3863, 0, 3681, + 3863, 0, 3681, + 3861, 0, 3681, + 3861, 0, 3679, + 3859, 0, 3677, + 3859, 0, 3677, + 3857, 0, 3673, + 3853, 0, 3671, + 3849, 0, 3665, + 3845, 0, 3661, + 3837, 0, 3651, + 3827, 0, 3641, + 3815, 0, 3625, + 3797, 1617, 3605, + 3771, 2213, 3575, + 3735, 2523, 3531, + 3683, 2753, 3467, + 3601, 2947, 3363, + 3461, 3121, 3169, + 3163, 3281, 2609, + 0, 3433, 0, + 0, 3579, 0, + 0, 3723, 0, + 0, 3863, 0, + 0, 4001, 0, + 3997, 0, 3815, + 3997, 0, 3815, + 3997, 0, 3815, + 3997, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3813, + 3995, 0, 3813, + 3995, 0, 3813, + 3993, 0, 3813, + 3993, 0, 3811, + 3991, 0, 3809, + 3991, 0, 3807, + 3989, 0, 3805, + 3985, 0, 3803, + 3981, 0, 3797, + 3977, 0, 3791, + 3969, 0, 3783, + 3959, 0, 3773, + 3947, 0, 3757, + 3929, 1746, 3737, + 3903, 2343, 3707, + 3869, 2653, 3663, + 3815, 2885, 3599, + 3733, 3079, 3493, + 3593, 3253, 3301, + 3295, 3413, 2739, + 0, 3565, 0, + 0, 3711, 0, + 0, 3855, 0, + 0, 3995, 0, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3943, + 4095, 0, 3941, + 4095, 0, 3939, + 4095, 0, 3937, + 4095, 0, 3935, + 4095, 0, 3929, + 4095, 0, 3923, + 4095, 0, 3915, + 4093, 0, 3905, + 4079, 0, 3889, + 4061, 1876, 3869, + 4037, 2475, 3839, + 4001, 2785, 3795, + 3947, 3017, 3731, + 3865, 3211, 3625, + 3725, 3385, 3431, + 3425, 3545, 2869, + 0, 3697, 0, + 0, 3845, 0, + 0, 3987, 0, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4075, + 4095, 0, 4073, + 4095, 0, 4071, + 4095, 0, 4069, + 4095, 0, 4067, + 4095, 0, 4061, + 4095, 0, 4055, + 4095, 0, 4047, + 4095, 0, 4037, + 4095, 0, 4021, + 4095, 2006, 4001, + 4095, 2607, 3971, + 4095, 2917, 3927, + 4079, 3149, 3863, + 3997, 3343, 3757, + 3857, 3517, 3563, + 3557, 3677, 2999, + 0, 3829, 0, + 0, 3977, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2137, 4095, + 4095, 2739, 4095, + 4095, 3049, 4059, + 4095, 3281, 3995, + 4095, 3475, 3889, + 3989, 3649, 3695, + 3689, 3809, 3131, + 0, 3961, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2267, 4095, + 4095, 2871, 4095, + 4095, 3181, 4095, + 4095, 3413, 4095, + 4095, 3607, 4021, + 4095, 3781, 3827, + 3821, 3941, 3261, + 644, 324, 1001, + 562, 383, 974, + 422, 452, 935, + 123, 530, 876, + 0, 617, 784, + 0, 713, 622, + 0, 815, 233, + 0, 924, 0, + 0, 1037, 0, + 0, 1155, 0, + 0, 1276, 0, + 0, 1400, 0, + 0, 1526, 0, + 0, 1653, 0, + 0, 1782, 0, + 0, 1911, 0, + 0, 2041, 0, + 0, 2171, 0, + 0, 2303, 0, + 0, 2433, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 731, 315, 1029, + 664, 375, 1004, + 556, 445, 967, + 354, 524, 913, + 0, 612, 829, + 0, 708, 684, + 0, 812, 369, + 0, 921, 0, + 0, 1035, 0, + 0, 1154, 0, + 0, 1275, 0, + 0, 1399, 0, + 0, 1525, 0, + 0, 1653, 0, + 0, 1781, 0, + 0, 1911, 0, + 0, 2041, 0, + 0, 2171, 0, + 0, 2303, 0, + 0, 2433, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 826, 301, 1065, + 772, 363, 1041, + 689, 435, 1008, + 548, 516, 958, + 243, 605, 883, + 0, 703, 757, + 0, 807, 504, + 0, 918, 0, + 0, 1033, 0, + 0, 1151, 0, + 0, 1273, 0, + 0, 1398, 0, + 0, 1524, 0, + 0, 1652, 0, + 0, 1781, 0, + 0, 1910, 0, + 0, 2041, 0, + 0, 2171, 0, + 0, 2303, 0, + 0, 2433, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 928, 282, 1108, + 886, 347, 1086, + 822, 421, 1056, + 721, 504, 1012, + 536, 596, 946, + 32, 695, 838, + 0, 801, 638, + 0, 913, 23, + 0, 1029, 0, + 0, 1149, 0, + 0, 1271, 0, + 0, 1396, 0, + 0, 1523, 0, + 0, 1651, 0, + 0, 1780, 0, + 0, 1910, 0, + 0, 2040, 0, + 0, 2171, 0, + 0, 2303, 0, + 0, 2433, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1036, 256, 1160, + 1003, 324, 1141, + 955, 402, 1114, + 882, 488, 1075, + 760, 583, 1018, + 521, 685, 929, + 0, 793, 771, + 0, 907, 406, + 0, 1024, 0, + 0, 1145, 0, + 0, 1268, 0, + 0, 1394, 0, + 0, 1521, 0, + 0, 1650, 0, + 0, 1779, 0, + 0, 1909, 0, + 0, 2040, 0, + 0, 2171, 0, + 0, 2301, 0, + 0, 2433, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1150, 219, 1221, + 1124, 292, 1205, + 1088, 375, 1182, + 1034, 466, 1149, + 951, 565, 1100, + 808, 671, 1026, + 500, 782, 905, + 0, 898, 663, + 0, 1017, 0, + 0, 1140, 0, + 0, 1265, 0, + 0, 1391, 0, + 0, 1519, 0, + 0, 1648, 0, + 0, 1778, 0, + 0, 1908, 0, + 0, 2039, 0, + 0, 2171, 0, + 0, 2301, 0, + 0, 2433, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1267, 163, 1292, + 1248, 245, 1278, + 1220, 336, 1259, + 1181, 435, 1231, + 1122, 540, 1191, + 1029, 651, 1131, + 865, 767, 1037, + 469, 886, 870, + 0, 1008, 460, + 0, 1133, 0, + 0, 1259, 0, + 0, 1387, 0, + 0, 1516, 0, + 0, 1646, 0, + 0, 1776, 0, + 0, 1907, 0, + 0, 2038, 0, + 0, 2169, 0, + 0, 2301, 0, + 0, 2433, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1388, 76, 1373, + 1373, 174, 1361, + 1353, 278, 1345, + 1324, 389, 1322, + 1281, 504, 1289, + 1218, 623, 1242, + 1116, 745, 1170, + 932, 870, 1051, + 425, 996, 820, + 0, 1123, 0, + 0, 1252, 0, + 0, 1382, 0, + 0, 1512, 0, + 0, 1643, 0, + 0, 1774, 0, + 0, 1905, 0, + 0, 2037, 0, + 0, 2169, 0, + 0, 2301, 0, + 0, 2433, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1512, 0, 1462, + 1501, 57, 1452, + 1485, 188, 1439, + 1463, 319, 1420, + 1433, 451, 1395, + 1388, 583, 1357, + 1321, 715, 1303, + 1212, 847, 1217, + 1008, 979, 1069, + 358, 1110, 742, + 0, 1242, 0, + 0, 1374, 0, + 0, 1507, 0, + 0, 1639, 0, + 0, 1771, 0, + 0, 1903, 0, + 0, 2035, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1638, 0, 1559, + 1629, 0, 1551, + 1617, 29, 1541, + 1601, 206, 1526, + 1579, 369, 1505, + 1547, 523, 1477, + 1501, 670, 1435, + 1430, 814, 1373, + 1315, 954, 1273, + 1092, 1092, 1092, + 250, 1229, 613, + 0, 1364, 0, + 0, 1499, 0, + 0, 1633, 0, + 0, 1767, 0, + 0, 1900, 0, + 0, 2033, 0, + 0, 2165, 0, + 0, 2297, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1765, 0, 1663, + 1758, 0, 1657, + 1750, 0, 1649, + 1738, 0, 1637, + 1721, 229, 1621, + 1698, 428, 1599, + 1665, 604, 1567, + 1617, 766, 1522, + 1544, 920, 1452, + 1423, 1067, 1338, + 1186, 1211, 1122, + 47, 1351, 348, + 0, 1489, 0, + 0, 1626, 0, + 0, 1761, 0, + 0, 1896, 0, + 0, 2030, 0, + 0, 2163, 0, + 0, 2297, 0, + 0, 2429, 0, + 0, 2561, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1893, 0, 1773, + 1888, 0, 1768, + 1882, 0, 1762, + 1873, 0, 1753, + 1861, 0, 1740, + 1844, 258, 1723, + 1820, 496, 1700, + 1787, 694, 1666, + 1738, 869, 1616, + 1662, 1031, 1540, + 1537, 1185, 1414, + 1287, 1332, 1158, + 0, 1475, 0, + 0, 1615, 0, + 0, 1753, 0, + 0, 1890, 0, + 0, 2025, 0, + 0, 2159, 0, + 0, 2293, 0, + 0, 2427, 0, + 0, 2561, 0, + 0, 2693, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2023, 0, 1888, + 2019, 0, 1884, + 2014, 0, 1879, + 2007, 0, 1872, + 1998, 0, 1863, + 1986, 0, 1850, + 1969, 295, 1832, + 1945, 574, 1807, + 1911, 791, 1771, + 1861, 978, 1718, + 1784, 1147, 1637, + 1655, 1305, 1498, + 1394, 1456, 1202, + 0, 1601, 0, + 0, 1743, 0, + 0, 1882, 0, + 0, 2020, 0, + 0, 2155, 0, + 0, 2291, 0, + 0, 2425, 0, + 0, 2559, 0, + 0, 2693, 0, + 0, 2825, 0, + 0, 2957, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2153, 0, 2007, + 2149, 0, 2004, + 2147, 0, 2000, + 2141, 0, 1995, + 2135, 0, 1987, + 2125, 0, 1978, + 2113, 0, 1964, + 2095, 339, 1946, + 2071, 661, 1920, + 2037, 896, 1882, + 1986, 1092, 1827, + 1908, 1267, 1740, + 1777, 1429, 1590, + 1507, 1582, 1256, + 0, 1729, 0, + 0, 1872, 0, + 0, 2012, 0, + 0, 2151, 0, + 0, 2287, 0, + 0, 2421, 0, + 0, 2557, 0, + 0, 2691, 0, + 0, 2823, 0, + 0, 2957, 0, + 0, 3089, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2283, 0, 2129, + 2281, 0, 2127, + 2279, 0, 2123, + 2275, 0, 2119, + 2269, 0, 2113, + 2263, 0, 2107, + 2253, 0, 2097, + 2241, 0, 2083, + 2223, 393, 2063, + 2199, 756, 2036, + 2165, 1006, 1998, + 2113, 1210, 1940, + 2034, 1390, 1850, + 1900, 1554, 1691, + 1624, 1709, 1318, + 0, 1858, 0, + 0, 2002, 0, + 0, 2143, 0, + 0, 2281, 0, + 0, 2417, 0, + 0, 2553, 0, + 0, 2687, 0, + 0, 2823, 0, + 0, 2955, 0, + 0, 3089, 0, + 0, 3221, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3885, 0, + 0, 4017, 0, + 2415, 0, 2253, + 2413, 0, 2251, + 2411, 0, 2249, + 2407, 0, 2245, + 2405, 0, 2241, + 2399, 0, 2237, + 2393, 0, 2229, + 2383, 0, 2219, + 2371, 0, 2205, + 2353, 455, 2185, + 2329, 858, 2157, + 2293, 1121, 2117, + 2241, 1332, 2057, + 2161, 1515, 1964, + 2026, 1681, 1797, + 1744, 1838, 1391, + 0, 1987, 0, + 0, 2131, 0, + 0, 2273, 0, + 0, 2411, 0, + 0, 2549, 0, + 0, 2685, 0, + 0, 2819, 0, + 0, 2953, 0, + 0, 3087, 0, + 0, 3221, 0, + 0, 3353, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4017, 0, + 2545, 0, 2379, + 2545, 0, 2377, + 2543, 0, 2377, + 2541, 0, 2373, + 2537, 0, 2371, + 2535, 0, 2367, + 2529, 0, 2361, + 2523, 0, 2353, + 2513, 0, 2343, + 2501, 0, 2329, + 2483, 528, 2309, + 2457, 966, 2281, + 2423, 1240, 2239, + 2371, 1456, 2179, + 2289, 1641, 2083, + 2153, 1810, 1910, + 1867, 1967, 1472, + 0, 2117, 0, + 0, 2263, 0, + 0, 2405, 0, + 0, 2543, 0, + 0, 2681, 0, + 0, 2817, 0, + 0, 2951, 0, + 0, 3085, 0, + 0, 3219, 0, + 0, 3353, 0, + 0, 3485, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4017, 0, + 2677, 0, 2507, + 2675, 0, 2505, + 2675, 0, 2505, + 2673, 0, 2503, + 2671, 0, 2501, + 2669, 0, 2497, + 2665, 0, 2493, + 2659, 0, 2487, + 2653, 0, 2479, + 2643, 0, 2469, + 2631, 0, 2455, + 2613, 609, 2433, + 2587, 1080, 2405, + 2553, 1362, 2365, + 2501, 1582, 2303, + 2419, 1769, 2203, + 2283, 1939, 2026, + 1993, 2097, 1562, + 0, 2249, 0, + 0, 2393, 0, + 0, 2535, 0, + 0, 2675, 0, + 0, 2813, 0, + 0, 2949, 0, + 0, 3083, 0, + 0, 3217, 0, + 0, 3351, 0, + 0, 3485, 0, + 0, 3617, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 2809, 0, 2635, + 2807, 0, 2635, + 2807, 0, 2633, + 2805, 0, 2633, + 2805, 0, 2631, + 2803, 0, 2629, + 2799, 0, 2625, + 2795, 0, 2621, + 2791, 0, 2615, + 2783, 0, 2607, + 2775, 0, 2597, + 2761, 0, 2581, + 2743, 700, 2561, + 2719, 1198, 2533, + 2683, 1487, 2491, + 2631, 1709, 2427, + 2549, 1898, 2327, + 2411, 2069, 2147, + 2119, 2227, 1661, + 0, 2379, 0, + 0, 2525, 0, + 0, 2667, 0, + 0, 2807, 0, + 0, 2945, 0, + 0, 3081, 0, + 0, 3215, 0, + 0, 3349, 0, + 0, 3483, 0, + 0, 3617, 0, + 0, 3749, 0, + 0, 3883, 0, + 0, 4015, 0, + 2941, 0, 2765, + 2939, 0, 2765, + 2939, 0, 2763, + 2939, 0, 2763, + 2937, 0, 2761, + 2935, 0, 2759, + 2933, 0, 2757, + 2931, 0, 2755, + 2927, 0, 2749, + 2921, 0, 2743, + 2915, 0, 2737, + 2905, 0, 2725, + 2893, 0, 2711, + 2875, 798, 2689, + 2849, 1319, 2661, + 2815, 1613, 2619, + 2761, 1837, 2555, + 2681, 2028, 2453, + 2541, 2199, 2269, + 2247, 2359, 1766, + 0, 2511, 0, + 0, 2657, 0, + 0, 2799, 0, + 0, 2939, 0, + 0, 3077, 0, + 0, 3213, 0, + 0, 3347, 0, + 0, 3481, 0, + 0, 3615, 0, + 0, 3749, 0, + 0, 3881, 0, + 0, 4015, 0, + 3073, 0, 2895, + 3071, 0, 2895, + 3071, 0, 2895, + 3071, 0, 2893, + 3069, 0, 2893, + 3069, 0, 2891, + 3067, 0, 2889, + 3065, 0, 2887, + 3063, 0, 2883, + 3059, 0, 2879, + 3053, 0, 2873, + 3047, 0, 2865, + 3037, 0, 2855, + 3025, 0, 2839, + 3007, 903, 2819, + 2981, 1442, 2789, + 2945, 1741, 2747, + 2893, 1967, 2683, + 2811, 2159, 2581, + 2673, 2331, 2395, + 2377, 2491, 1876, + 0, 2641, 0, + 0, 2789, 0, + 0, 2931, 0, + 0, 3071, 0, + 0, 3207, 0, + 0, 3345, 0, + 0, 3479, 0, + 0, 3613, 0, + 0, 3747, 0, + 0, 3881, 0, + 0, 4015, 0, + 3205, 0, 3025, + 3203, 0, 3025, + 3203, 0, 3025, + 3203, 0, 3025, + 3203, 0, 3023, + 3201, 0, 3023, + 3201, 0, 3021, + 3199, 0, 3019, + 3197, 0, 3017, + 3193, 0, 3015, + 3191, 0, 3009, + 3185, 0, 3003, + 3177, 0, 2995, + 3169, 0, 2985, + 3155, 0, 2971, + 3137, 1014, 2949, + 3113, 1568, 2919, + 3077, 1870, 2877, + 3025, 2097, 2813, + 2943, 2289, 2711, + 2803, 2461, 2521, + 2507, 2621, 1992, + 0, 2773, 0, + 0, 2919, 0, + 0, 3063, 0, + 0, 3203, 0, + 0, 3339, 0, + 0, 3477, 0, + 0, 3611, 0, + 0, 3745, 0, + 0, 3879, 0, + 0, 4013, 0, + 3335, 0, 3157, + 3335, 0, 3157, + 3335, 0, 3157, + 3335, 0, 3155, + 3335, 0, 3155, + 3335, 0, 3155, + 3333, 0, 3153, + 3333, 0, 3153, + 3331, 0, 3151, + 3329, 0, 3149, + 3325, 0, 3145, + 3321, 0, 3141, + 3317, 0, 3135, + 3309, 0, 3127, + 3301, 0, 3115, + 3287, 0, 3101, + 3269, 1129, 3079, + 3245, 1695, 3051, + 3209, 1999, 3007, + 3155, 2227, 2943, + 3073, 2421, 2839, + 2935, 2593, 2649, + 2637, 2753, 2111, + 0, 2905, 0, + 0, 3051, 0, + 0, 3195, 0, + 0, 3335, 0, + 0, 3473, 0, + 0, 3609, 0, + 0, 3743, 0, + 0, 3877, 0, + 0, 4011, 0, + 3469, 0, 3289, + 3467, 0, 3289, + 3467, 0, 3287, + 3467, 0, 3287, + 3467, 0, 3287, + 3467, 0, 3287, + 3465, 0, 3285, + 3465, 0, 3285, + 3463, 0, 3283, + 3463, 0, 3281, + 3461, 0, 3279, + 3457, 0, 3277, + 3453, 0, 3271, + 3449, 0, 3265, + 3441, 0, 3257, + 3433, 0, 3247, + 3419, 0, 3231, + 3401, 1248, 3211, + 3377, 1824, 3181, + 3341, 2129, 3139, + 3287, 2359, 3073, + 3205, 2551, 2969, + 3065, 2725, 2779, + 2769, 2885, 2233, + 0, 3037, 0, + 0, 3183, 0, + 0, 3327, 0, + 0, 3467, 0, + 0, 3605, 0, + 0, 3741, 0, + 0, 3875, 0, + 0, 4011, 0, + 3601, 0, 3419, + 3599, 0, 3419, + 3599, 0, 3419, + 3599, 0, 3419, + 3599, 0, 3419, + 3599, 0, 3419, + 3599, 0, 3417, + 3597, 0, 3417, + 3597, 0, 3417, + 3595, 0, 3415, + 3595, 0, 3413, + 3593, 0, 3411, + 3589, 0, 3407, + 3585, 0, 3403, + 3581, 0, 3397, + 3573, 0, 3389, + 3565, 0, 3379, + 3551, 0, 3363, + 3533, 1371, 3341, + 3509, 1953, 3313, + 3473, 2261, 3269, + 3419, 2489, 3205, + 3337, 2683, 3101, + 3197, 2857, 2909, + 2899, 3017, 2357, + 0, 3169, 0, + 0, 3315, 0, + 0, 3459, 0, + 0, 3599, 0, + 0, 3737, 0, + 0, 3873, 0, + 0, 4007, 0, + 3733, 0, 3551, + 3733, 0, 3551, + 3731, 0, 3551, + 3731, 0, 3551, + 3731, 0, 3551, + 3731, 0, 3551, + 3731, 0, 3551, + 3731, 0, 3549, + 3729, 0, 3549, + 3729, 0, 3547, + 3727, 0, 3547, + 3727, 0, 3545, + 3725, 0, 3543, + 3721, 0, 3539, + 3717, 0, 3535, + 3713, 0, 3529, + 3705, 0, 3521, + 3697, 0, 3509, + 3683, 0, 3495, + 3665, 1495, 3473, + 3641, 2083, 3443, + 3605, 2391, 3401, + 3551, 2621, 3335, + 3469, 2815, 3231, + 3329, 2989, 3039, + 3031, 3149, 2485, + 0, 3301, 0, + 0, 3447, 0, + 0, 3591, 0, + 0, 3731, 0, + 0, 3869, 0, + 0, 4005, 0, + 3865, 0, 3683, + 3865, 0, 3683, + 3865, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3681, + 3863, 0, 3681, + 3861, 0, 3681, + 3861, 0, 3679, + 3859, 0, 3679, + 3859, 0, 3677, + 3857, 0, 3673, + 3853, 0, 3671, + 3849, 0, 3667, + 3845, 0, 3661, + 3837, 0, 3653, + 3829, 0, 3641, + 3815, 0, 3627, + 3797, 1622, 3605, + 3773, 2213, 3575, + 3737, 2523, 3533, + 3683, 2753, 3467, + 3601, 2947, 3363, + 3461, 3121, 3169, + 3163, 3281, 2611, + 0, 3433, 0, + 0, 3579, 0, + 0, 3723, 0, + 0, 3863, 0, + 0, 4001, 0, + 3997, 0, 3815, + 3997, 0, 3815, + 3997, 0, 3815, + 3997, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3813, + 3995, 0, 3813, + 3993, 0, 3813, + 3993, 0, 3811, + 3991, 0, 3809, + 3991, 0, 3809, + 3989, 0, 3805, + 3985, 0, 3803, + 3981, 0, 3799, + 3977, 0, 3793, + 3969, 0, 3785, + 3961, 0, 3773, + 3947, 0, 3757, + 3929, 1749, 3737, + 3905, 2345, 3707, + 3869, 2655, 3663, + 3815, 2885, 3599, + 3733, 3079, 3495, + 3593, 3253, 3301, + 3295, 3413, 2741, + 0, 3565, 0, + 0, 3711, 0, + 0, 3855, 0, + 0, 3995, 0, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3943, + 4095, 0, 3941, + 4095, 0, 3941, + 4095, 0, 3937, + 4095, 0, 3935, + 4095, 0, 3929, + 4095, 0, 3925, + 4095, 0, 3915, + 4093, 0, 3905, + 4079, 0, 3889, + 4061, 1878, 3869, + 4037, 2475, 3839, + 4001, 2785, 3795, + 3947, 3017, 3731, + 3865, 3211, 3625, + 3725, 3385, 3433, + 3427, 3545, 2871, + 0, 3697, 0, + 0, 3845, 0, + 0, 3987, 0, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4075, + 4095, 0, 4073, + 4095, 0, 4071, + 4095, 0, 4069, + 4095, 0, 4067, + 4095, 0, 4061, + 4095, 0, 4055, + 4095, 0, 4047, + 4095, 0, 4037, + 4095, 0, 4021, + 4095, 2008, 4001, + 4095, 2607, 3971, + 4095, 2917, 3927, + 4079, 3149, 3863, + 3997, 3343, 3757, + 3857, 3517, 3563, + 3559, 3677, 3001, + 0, 3829, 0, + 0, 3977, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2139, 4095, + 4095, 2739, 4095, + 4095, 3049, 4059, + 4095, 3281, 3995, + 4095, 3475, 3889, + 3989, 3649, 3695, + 3691, 3809, 3131, + 0, 3961, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2269, 4095, + 4095, 2871, 4095, + 4095, 3181, 4095, + 4095, 3413, 4095, + 4095, 3607, 4021, + 4095, 3781, 3827, + 3823, 3941, 3263, + 761, 415, 1131, + 699, 464, 1111, + 599, 522, 1082, + 420, 590, 1041, + 0, 667, 979, + 0, 753, 880, + 0, 848, 701, + 0, 950, 229, + 0, 1058, 0, + 0, 1171, 0, + 0, 1288, 0, + 0, 1409, 0, + 0, 1533, 0, + 0, 1658, 0, + 0, 1786, 0, + 0, 1914, 0, + 0, 2043, 0, + 0, 2173, 0, + 0, 2303, 0, + 0, 2435, 0, + 0, 2567, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 829, 407, 1153, + 776, 456, 1133, + 694, 515, 1106, + 554, 584, 1067, + 255, 662, 1008, + 0, 749, 916, + 0, 845, 754, + 0, 947, 365, + 0, 1056, 0, + 0, 1169, 0, + 0, 1287, 0, + 0, 1408, 0, + 0, 1532, 0, + 0, 1658, 0, + 0, 1785, 0, + 0, 1914, 0, + 0, 2043, 0, + 0, 2173, 0, + 0, 2303, 0, + 0, 2435, 0, + 0, 2567, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 907, 396, 1180, + 863, 447, 1161, + 796, 507, 1136, + 688, 577, 1099, + 486, 656, 1045, + 0, 744, 961, + 0, 841, 817, + 0, 944, 501, + 0, 1053, 0, + 0, 1167, 0, + 0, 1286, 0, + 0, 1407, 0, + 0, 1531, 0, + 0, 1657, 0, + 0, 1785, 0, + 0, 1913, 0, + 0, 2043, 0, + 0, 2173, 0, + 0, 2303, 0, + 0, 2435, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 994, 381, 1214, + 958, 433, 1197, + 904, 495, 1173, + 821, 567, 1139, + 680, 648, 1090, + 375, 737, 1015, + 0, 835, 889, + 0, 939, 636, + 0, 1050, 0, + 0, 1165, 0, + 0, 1284, 0, + 0, 1406, 0, + 0, 1530, 0, + 0, 1656, 0, + 0, 1784, 0, + 0, 1913, 0, + 0, 2042, 0, + 0, 2173, 0, + 0, 2303, 0, + 0, 2435, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1089, 360, 1255, + 1060, 415, 1240, + 1018, 479, 1219, + 955, 553, 1188, + 853, 636, 1144, + 669, 728, 1078, + 164, 827, 970, + 0, 933, 770, + 0, 1045, 155, + 0, 1161, 0, + 0, 1281, 0, + 0, 1403, 0, + 0, 1528, 0, + 0, 1655, 0, + 0, 1783, 0, + 0, 1912, 0, + 0, 2042, 0, + 0, 2173, 0, + 0, 2303, 0, + 0, 2435, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1191, 330, 1306, + 1168, 388, 1292, + 1135, 456, 1273, + 1087, 534, 1246, + 1014, 620, 1208, + 893, 715, 1150, + 653, 817, 1060, + 0, 925, 903, + 0, 1038, 538, + 0, 1156, 0, + 0, 1277, 0, + 0, 1401, 0, + 0, 1526, 0, + 0, 1653, 0, + 0, 1782, 0, + 0, 1911, 0, + 0, 2041, 0, + 0, 2171, 0, + 0, 2303, 0, + 0, 2433, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1300, 287, 1366, + 1282, 351, 1353, + 1256, 424, 1337, + 1220, 507, 1314, + 1166, 598, 1281, + 1083, 697, 1232, + 940, 803, 1159, + 632, 914, 1036, + 0, 1030, 795, + 0, 1149, 0, + 0, 1272, 0, + 0, 1397, 0, + 0, 1523, 0, + 0, 1651, 0, + 0, 1780, 0, + 0, 1910, 0, + 0, 2040, 0, + 0, 2171, 0, + 0, 2303, 0, + 0, 2433, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1413, 222, 1435, + 1399, 295, 1425, + 1380, 377, 1410, + 1352, 468, 1391, + 1313, 567, 1363, + 1254, 672, 1323, + 1161, 783, 1264, + 997, 899, 1169, + 601, 1018, 1002, + 0, 1140, 592, + 0, 1265, 0, + 0, 1391, 0, + 0, 1519, 0, + 0, 1648, 0, + 0, 1778, 0, + 0, 1908, 0, + 0, 2039, 0, + 0, 2171, 0, + 0, 2301, 0, + 0, 2433, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1531, 118, 1514, + 1520, 208, 1505, + 1505, 306, 1493, + 1485, 411, 1477, + 1456, 521, 1454, + 1413, 636, 1421, + 1350, 755, 1374, + 1249, 877, 1302, + 1063, 1002, 1183, + 557, 1128, 952, + 0, 1255, 0, + 0, 1384, 0, + 0, 1514, 0, + 0, 1644, 0, + 0, 1775, 0, + 0, 1906, 0, + 0, 2037, 0, + 0, 2169, 0, + 0, 2301, 0, + 0, 2433, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1652, 0, 1601, + 1644, 58, 1594, + 1633, 189, 1584, + 1617, 320, 1571, + 1596, 451, 1553, + 1565, 583, 1527, + 1520, 715, 1490, + 1453, 847, 1435, + 1344, 979, 1349, + 1139, 1110, 1201, + 490, 1242, 875, + 0, 1375, 0, + 0, 1507, 0, + 0, 1639, 0, + 0, 1771, 0, + 0, 1903, 0, + 0, 2035, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1776, 0, 1697, + 1770, 0, 1691, + 1761, 0, 1683, + 1749, 161, 1673, + 1733, 338, 1658, + 1711, 501, 1638, + 1679, 655, 1609, + 1633, 803, 1567, + 1562, 946, 1505, + 1447, 1086, 1405, + 1225, 1225, 1225, + 382, 1361, 745, + 0, 1497, 0, + 0, 1631, 0, + 0, 1765, 0, + 0, 1899, 0, + 0, 2032, 0, + 0, 2165, 0, + 0, 2297, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1902, 0, 1800, + 1897, 0, 1795, + 1890, 0, 1789, + 1882, 0, 1781, + 1870, 122, 1769, + 1853, 361, 1753, + 1830, 560, 1731, + 1797, 736, 1700, + 1750, 898, 1654, + 1676, 1052, 1584, + 1556, 1199, 1471, + 1318, 1343, 1254, + 179, 1483, 480, + 0, 1621, 0, + 0, 1758, 0, + 0, 1893, 0, + 0, 2028, 0, + 0, 2161, 0, + 0, 2295, 0, + 0, 2429, 0, + 0, 2561, 0, + 0, 2693, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2029, 0, 1909, + 2025, 0, 1905, + 2021, 0, 1900, + 2014, 0, 1894, + 2005, 0, 1885, + 1993, 63, 1873, + 1976, 390, 1856, + 1952, 628, 1832, + 1919, 826, 1798, + 1870, 1001, 1748, + 1795, 1163, 1672, + 1669, 1317, 1546, + 1419, 1464, 1290, + 0, 1607, 0, + 0, 1747, 0, + 0, 1886, 0, + 0, 2022, 0, + 0, 2157, 0, + 0, 2293, 0, + 0, 2425, 0, + 0, 2559, 0, + 0, 2693, 0, + 0, 2825, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2157, 0, 2023, + 2155, 0, 2020, + 2151, 0, 2016, + 2147, 0, 2011, + 2139, 0, 2004, + 2131, 0, 1995, + 2119, 0, 1982, + 2101, 427, 1964, + 2077, 706, 1939, + 2043, 924, 1903, + 1993, 1110, 1851, + 1916, 1279, 1769, + 1787, 1437, 1630, + 1526, 1588, 1334, + 0, 1733, 0, + 0, 1875, 0, + 0, 2014, 0, + 0, 2151, 0, + 0, 2287, 0, + 0, 2423, 0, + 0, 2557, 0, + 0, 2691, 0, + 0, 2825, 0, + 0, 2957, 0, + 0, 3089, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2287, 0, 2141, + 2285, 0, 2139, + 2283, 0, 2135, + 2279, 0, 2131, + 2273, 0, 2127, + 2267, 0, 2119, + 2257, 0, 2109, + 2245, 0, 2097, + 2227, 471, 2077, + 2203, 793, 2051, + 2169, 1028, 2014, + 2119, 1224, 1959, + 2040, 1399, 1872, + 1909, 1561, 1723, + 1639, 1714, 1388, + 0, 1861, 0, + 0, 2004, 0, + 0, 2145, 0, + 0, 2283, 0, + 0, 2419, 0, + 0, 2555, 0, + 0, 2689, 0, + 0, 2823, 0, + 0, 2955, 0, + 0, 3089, 0, + 0, 3221, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3885, 0, + 0, 4017, 0, + 2417, 0, 2263, + 2415, 0, 2261, + 2413, 0, 2259, + 2411, 0, 2255, + 2407, 0, 2251, + 2401, 0, 2245, + 2395, 0, 2239, + 2385, 0, 2229, + 2373, 0, 2215, + 2355, 525, 2195, + 2331, 888, 2169, + 2297, 1138, 2129, + 2245, 1342, 2073, + 2165, 1522, 1982, + 2033, 1686, 1823, + 1756, 1841, 1450, + 0, 1990, 0, + 0, 2133, 0, + 0, 2275, 0, + 0, 2413, 0, + 0, 2549, 0, + 0, 2685, 0, + 0, 2821, 0, + 0, 2955, 0, + 0, 3087, 0, + 0, 3221, 0, + 0, 3353, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4017, 0, + 2547, 0, 2387, + 2547, 0, 2385, + 2545, 0, 2383, + 2543, 0, 2381, + 2539, 0, 2377, + 2537, 0, 2373, + 2531, 0, 2369, + 2525, 0, 2361, + 2515, 0, 2351, + 2503, 0, 2337, + 2485, 587, 2317, + 2461, 990, 2289, + 2425, 1253, 2249, + 2373, 1464, 2189, + 2293, 1647, 2097, + 2159, 1813, 1930, + 1876, 1970, 1523, + 0, 2119, 0, + 0, 2263, 0, + 0, 2405, 0, + 0, 2545, 0, + 0, 2681, 0, + 0, 2817, 0, + 0, 2951, 0, + 0, 3085, 0, + 0, 3219, 0, + 0, 3353, 0, + 0, 3485, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4017, 0, + 2679, 0, 2513, + 2677, 0, 2511, + 2677, 0, 2509, + 2675, 0, 2509, + 2673, 0, 2505, + 2669, 0, 2503, + 2667, 0, 2499, + 2661, 0, 2493, + 2655, 0, 2485, + 2645, 0, 2475, + 2633, 0, 2461, + 2615, 660, 2441, + 2589, 1098, 2413, + 2555, 1372, 2371, + 2503, 1588, 2311, + 2421, 1773, 2215, + 2285, 1942, 2042, + 1999, 2099, 1604, + 0, 2249, 0, + 0, 2395, 0, + 0, 2537, 0, + 0, 2675, 0, + 0, 2813, 0, + 0, 2949, 0, + 0, 3083, 0, + 0, 3217, 0, + 0, 3351, 0, + 0, 3485, 0, + 0, 3617, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 2809, 0, 2639, + 2809, 0, 2639, + 2809, 0, 2637, + 2807, 0, 2637, + 2805, 0, 2635, + 2803, 0, 2633, + 2801, 0, 2629, + 2797, 0, 2625, + 2791, 0, 2619, + 2785, 0, 2611, + 2775, 0, 2601, + 2763, 0, 2587, + 2745, 742, 2567, + 2721, 1212, 2537, + 2685, 1495, 2497, + 2633, 1714, 2435, + 2551, 1901, 2335, + 2415, 2071, 2159, + 2125, 2229, 1695, + 0, 2381, 0, + 0, 2525, 0, + 0, 2667, 0, + 0, 2807, 0, + 0, 2945, 0, + 0, 3081, 0, + 0, 3215, 0, + 0, 3349, 0, + 0, 3483, 0, + 0, 3617, 0, + 0, 3749, 0, + 0, 3883, 0, + 0, 4015, 0, + 2941, 0, 2769, + 2941, 0, 2767, + 2939, 0, 2767, + 2939, 0, 2765, + 2937, 0, 2765, + 2937, 0, 2763, + 2935, 0, 2761, + 2931, 0, 2757, + 2927, 0, 2753, + 2923, 0, 2747, + 2915, 0, 2739, + 2907, 0, 2729, + 2893, 0, 2713, + 2875, 832, 2693, + 2851, 1330, 2665, + 2815, 1619, 2623, + 2763, 1841, 2561, + 2681, 2030, 2461, + 2543, 2201, 2279, + 2251, 2361, 1793, + 0, 2511, 0, + 0, 2657, 0, + 0, 2799, 0, + 0, 2939, 0, + 0, 3077, 0, + 0, 3213, 0, + 0, 3347, 0, + 0, 3481, 0, + 0, 3615, 0, + 0, 3749, 0, + 0, 3883, 0, + 0, 4015, 0, + 3073, 0, 2897, + 3073, 0, 2897, + 3071, 0, 2897, + 3071, 0, 2895, + 3071, 0, 2895, + 3069, 0, 2893, + 3067, 0, 2891, + 3065, 0, 2889, + 3063, 0, 2887, + 3059, 0, 2881, + 3053, 0, 2877, + 3047, 0, 2869, + 3037, 0, 2857, + 3025, 0, 2843, + 3007, 930, 2821, + 2981, 1451, 2793, + 2947, 1745, 2751, + 2893, 1970, 2687, + 2813, 2161, 2587, + 2673, 2331, 2401, + 2379, 2491, 1898, + 0, 2643, 0, + 0, 2789, 0, + 0, 2931, 0, + 0, 3071, 0, + 0, 3209, 0, + 0, 3345, 0, + 0, 3479, 0, + 0, 3613, 0, + 0, 3747, 0, + 0, 3881, 0, + 0, 4015, 0, + 3205, 0, 3027, + 3205, 0, 3027, + 3203, 0, 3027, + 3203, 0, 3027, + 3203, 0, 3025, + 3201, 0, 3025, + 3201, 0, 3023, + 3199, 0, 3021, + 3197, 0, 3019, + 3195, 0, 3015, + 3191, 0, 3011, + 3185, 0, 3005, + 3179, 0, 2997, + 3169, 0, 2987, + 3157, 0, 2973, + 3139, 1035, 2951, + 3113, 1574, 2921, + 3077, 1873, 2879, + 3025, 2099, 2815, + 2943, 2291, 2713, + 2805, 2463, 2527, + 2509, 2623, 2008, + 0, 2775, 0, + 0, 2921, 0, + 0, 3063, 0, + 0, 3203, 0, + 0, 3341, 0, + 0, 3477, 0, + 0, 3611, 0, + 0, 3745, 0, + 0, 3879, 0, + 0, 4013, 0, + 3337, 0, 3159, + 3337, 0, 3157, + 3335, 0, 3157, + 3335, 0, 3157, + 3335, 0, 3157, + 3335, 0, 3155, + 3333, 0, 3155, + 3333, 0, 3153, + 3331, 0, 3151, + 3329, 0, 3149, + 3325, 0, 3147, + 3323, 0, 3141, + 3317, 0, 3137, + 3311, 0, 3129, + 3301, 0, 3117, + 3287, 0, 3103, + 3269, 1146, 3081, + 3245, 1700, 3051, + 3209, 2002, 3009, + 3157, 2229, 2945, + 3075, 2421, 2843, + 2935, 2593, 2653, + 2639, 2753, 2123, + 0, 2905, 0, + 0, 3053, 0, + 0, 3195, 0, + 0, 3335, 0, + 0, 3473, 0, + 0, 3609, 0, + 0, 3743, 0, + 0, 3879, 0, + 0, 4011, 0, + 3469, 0, 3289, + 3469, 0, 3289, + 3467, 0, 3289, + 3467, 0, 3289, + 3467, 0, 3289, + 3467, 0, 3287, + 3467, 0, 3287, + 3465, 0, 3285, + 3465, 0, 3285, + 3463, 0, 3283, + 3461, 0, 3281, + 3457, 0, 3277, + 3453, 0, 3273, + 3449, 0, 3267, + 3441, 0, 3259, + 3433, 0, 3247, + 3419, 0, 3233, + 3401, 1261, 3211, + 3377, 1827, 3183, + 3341, 2131, 3139, + 3287, 2359, 3075, + 3205, 2553, 2971, + 3067, 2725, 2781, + 2769, 2885, 2243, + 0, 3037, 0, + 0, 3183, 0, + 0, 3327, 0, + 0, 3467, 0, + 0, 3605, 0, + 0, 3741, 0, + 0, 3875, 0, + 0, 4011, 0, + 3601, 0, 3421, + 3601, 0, 3421, + 3599, 0, 3421, + 3599, 0, 3419, + 3599, 0, 3419, + 3599, 0, 3419, + 3599, 0, 3419, + 3599, 0, 3417, + 3597, 0, 3417, + 3595, 0, 3415, + 3595, 0, 3413, + 3593, 0, 3411, + 3589, 0, 3409, + 3585, 0, 3403, + 3581, 0, 3397, + 3573, 0, 3389, + 3565, 0, 3379, + 3551, 0, 3363, + 3533, 1380, 3343, + 3509, 1956, 3313, + 3473, 2261, 3271, + 3419, 2491, 3205, + 3337, 2683, 3101, + 3199, 2857, 2911, + 2901, 3017, 2365, + 0, 3169, 0, + 0, 3315, 0, + 0, 3459, 0, + 0, 3599, 0, + 0, 3737, 0, + 0, 3873, 0, + 0, 4007, 0, + 3733, 0, 3551, + 3733, 0, 3551, + 3733, 0, 3551, + 3731, 0, 3551, + 3731, 0, 3551, + 3731, 0, 3551, + 3731, 0, 3551, + 3731, 0, 3551, + 3729, 0, 3549, + 3729, 0, 3549, + 3727, 0, 3547, + 3727, 0, 3545, + 3725, 0, 3543, + 3721, 0, 3539, + 3717, 0, 3535, + 3713, 0, 3529, + 3705, 0, 3521, + 3697, 0, 3511, + 3683, 0, 3495, + 3665, 1503, 3475, + 3641, 2085, 3445, + 3605, 2393, 3401, + 3551, 2623, 3337, + 3469, 2815, 3233, + 3329, 2989, 3041, + 3031, 3149, 2489, + 0, 3301, 0, + 0, 3447, 0, + 0, 3591, 0, + 0, 3731, 0, + 0, 3869, 0, + 0, 4005, 0, + 3865, 0, 3683, + 3865, 0, 3683, + 3865, 0, 3683, + 3865, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3681, + 3861, 0, 3681, + 3861, 0, 3679, + 3859, 0, 3679, + 3859, 0, 3677, + 3857, 0, 3675, + 3853, 0, 3671, + 3849, 0, 3667, + 3845, 0, 3661, + 3837, 0, 3653, + 3829, 0, 3641, + 3815, 0, 3627, + 3797, 1627, 3605, + 3773, 2215, 3575, + 3737, 2523, 3533, + 3683, 2753, 3467, + 3601, 2947, 3363, + 3461, 3121, 3171, + 3163, 3281, 2617, + 0, 3433, 0, + 0, 3579, 0, + 0, 3723, 0, + 0, 3863, 0, + 0, 4001, 0, + 3997, 0, 3815, + 3997, 0, 3815, + 3997, 0, 3815, + 3997, 0, 3815, + 3997, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3813, + 3995, 0, 3813, + 3993, 0, 3813, + 3993, 0, 3811, + 3991, 0, 3811, + 3991, 0, 3809, + 3989, 0, 3807, + 3985, 0, 3803, + 3981, 0, 3799, + 3977, 0, 3793, + 3969, 0, 3785, + 3961, 0, 3773, + 3947, 0, 3759, + 3929, 1754, 3737, + 3905, 2345, 3707, + 3869, 2655, 3665, + 3815, 2885, 3599, + 3733, 3079, 3495, + 3593, 3253, 3301, + 3295, 3413, 2743, + 0, 3565, 0, + 0, 3713, 0, + 0, 3855, 0, + 0, 3995, 0, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3943, + 4095, 0, 3943, + 4095, 0, 3941, + 4095, 0, 3937, + 4095, 0, 3935, + 4095, 0, 3931, + 4095, 0, 3925, + 4095, 0, 3917, + 4093, 0, 3905, + 4079, 0, 3891, + 4061, 1881, 3869, + 4037, 2477, 3839, + 4001, 2787, 3795, + 3947, 3017, 3731, + 3865, 3211, 3627, + 3725, 3385, 3433, + 3427, 3545, 2873, + 0, 3697, 0, + 0, 3845, 0, + 0, 3987, 0, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4075, + 4095, 0, 4073, + 4095, 0, 4073, + 4095, 0, 4069, + 4095, 0, 4067, + 4095, 0, 4063, + 4095, 0, 4057, + 4095, 0, 4049, + 4095, 0, 4037, + 4095, 0, 4021, + 4095, 2010, 4001, + 4095, 2609, 3971, + 4095, 2919, 3927, + 4079, 3149, 3863, + 3997, 3343, 3757, + 3857, 3517, 3565, + 3559, 3677, 3003, + 0, 3829, 0, + 0, 3977, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2141, 4095, + 4095, 2739, 4095, + 4095, 3049, 4059, + 4095, 3281, 3995, + 4095, 3475, 3889, + 3989, 3649, 3697, + 3691, 3809, 3133, + 0, 3961, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2271, 4095, + 4095, 2871, 4095, + 4095, 3181, 4095, + 4095, 3413, 4095, + 4095, 3607, 4021, + 4095, 3781, 3827, + 3823, 3941, 3263, + 881, 513, 1262, + 834, 553, 1247, + 762, 601, 1225, + 645, 659, 1196, + 417, 726, 1152, + 0, 802, 1087, + 0, 888, 982, + 0, 982, 788, + 0, 1083, 222, + 0, 1191, 0, + 0, 1304, 0, + 0, 1421, 0, + 0, 1542, 0, + 0, 1665, 0, + 0, 1791, 0, + 0, 1918, 0, + 0, 2046, 0, + 0, 2175, 0, + 0, 2305, 0, + 0, 2437, 0, + 0, 2567, 0, + 0, 2699, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 934, 506, 1278, + 893, 547, 1263, + 831, 596, 1243, + 731, 654, 1214, + 552, 722, 1173, + 77, 799, 1111, + 0, 885, 1012, + 0, 980, 833, + 0, 1082, 361, + 0, 1190, 0, + 0, 1303, 0, + 0, 1421, 0, + 0, 1541, 0, + 0, 1665, 0, + 0, 1791, 0, + 0, 1918, 0, + 0, 2046, 0, + 0, 2175, 0, + 0, 2305, 0, + 0, 2437, 0, + 0, 2567, 0, + 0, 2699, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 997, 497, 1299, + 961, 539, 1285, + 908, 588, 1265, + 826, 648, 1238, + 686, 716, 1199, + 387, 794, 1140, + 0, 882, 1048, + 0, 977, 886, + 0, 1079, 498, + 0, 1188, 0, + 0, 1302, 0, + 0, 1419, 0, + 0, 1541, 0, + 0, 1664, 0, + 0, 1790, 0, + 0, 1917, 0, + 0, 2046, 0, + 0, 2175, 0, + 0, 2305, 0, + 0, 2435, 0, + 0, 2567, 0, + 0, 2699, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1070, 485, 1325, + 1039, 528, 1312, + 995, 579, 1294, + 928, 639, 1268, + 820, 709, 1231, + 618, 788, 1177, + 0, 876, 1093, + 0, 973, 949, + 0, 1076, 633, + 0, 1185, 0, + 0, 1299, 0, + 0, 1418, 0, + 0, 1539, 0, + 0, 1663, 0, + 0, 1789, 0, + 0, 1917, 0, + 0, 2045, 0, + 0, 2175, 0, + 0, 2305, 0, + 0, 2435, 0, + 0, 2567, 0, + 0, 2699, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1151, 469, 1358, + 1126, 513, 1346, + 1090, 565, 1329, + 1036, 627, 1305, + 954, 699, 1272, + 812, 780, 1222, + 507, 870, 1147, + 0, 967, 1021, + 0, 1071, 768, + 0, 1182, 0, + 0, 1297, 0, + 0, 1416, 0, + 0, 1538, 0, + 0, 1662, 0, + 0, 1788, 0, + 0, 1916, 0, + 0, 2045, 0, + 0, 2175, 0, + 0, 2305, 0, + 0, 2435, 0, + 0, 2567, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1242, 446, 1399, + 1221, 492, 1387, + 1192, 547, 1372, + 1150, 611, 1351, + 1086, 685, 1320, + 985, 768, 1276, + 801, 860, 1210, + 296, 960, 1102, + 0, 1065, 902, + 0, 1177, 287, + 0, 1293, 0, + 0, 1413, 0, + 0, 1536, 0, + 0, 1661, 0, + 0, 1787, 0, + 0, 1915, 0, + 0, 2044, 0, + 0, 2175, 0, + 0, 2305, 0, + 0, 2435, 0, + 0, 2567, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1340, 413, 1448, + 1323, 462, 1438, + 1300, 520, 1424, + 1267, 588, 1405, + 1219, 666, 1378, + 1146, 752, 1340, + 1024, 847, 1283, + 785, 949, 1193, + 0, 1057, 1035, + 0, 1171, 670, + 0, 1288, 0, + 0, 1409, 0, + 0, 1533, 0, + 0, 1658, 0, + 0, 1786, 0, + 0, 1914, 0, + 0, 2043, 0, + 0, 2173, 0, + 0, 2303, 0, + 0, 2435, 0, + 0, 2567, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1445, 365, 1506, + 1432, 419, 1498, + 1414, 483, 1486, + 1388, 556, 1469, + 1352, 639, 1446, + 1298, 730, 1413, + 1215, 829, 1365, + 1072, 935, 1291, + 764, 1046, 1169, + 0, 1162, 927, + 0, 1281, 0, + 0, 1404, 0, + 0, 1529, 0, + 0, 1655, 0, + 0, 1783, 0, + 0, 1912, 0, + 0, 2042, 0, + 0, 2173, 0, + 0, 2303, 0, + 0, 2435, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1556, 291, 1575, + 1546, 354, 1567, + 1531, 427, 1557, + 1512, 509, 1542, + 1485, 600, 1523, + 1445, 699, 1495, + 1386, 804, 1455, + 1293, 915, 1396, + 1129, 1031, 1301, + 733, 1150, 1134, + 0, 1272, 724, + 0, 1397, 0, + 0, 1524, 0, + 0, 1651, 0, + 0, 1780, 0, + 0, 1910, 0, + 0, 2040, 0, + 0, 2171, 0, + 0, 2303, 0, + 0, 2433, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1671, 169, 1652, + 1663, 250, 1646, + 1652, 340, 1637, + 1638, 438, 1625, + 1617, 543, 1609, + 1588, 653, 1586, + 1546, 768, 1554, + 1482, 887, 1506, + 1381, 1009, 1434, + 1196, 1134, 1315, + 689, 1260, 1084, + 0, 1388, 87, + 0, 1516, 0, + 0, 1646, 0, + 0, 1776, 0, + 0, 1907, 0, + 0, 2038, 0, + 0, 2169, 0, + 0, 2301, 0, + 0, 2433, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1790, 0, 1739, + 1784, 59, 1733, + 1776, 190, 1726, + 1765, 321, 1716, + 1749, 452, 1703, + 1728, 583, 1685, + 1697, 715, 1659, + 1653, 847, 1622, + 1585, 979, 1567, + 1476, 1111, 1481, + 1272, 1243, 1334, + 622, 1375, 1007, + 0, 1507, 0, + 0, 1639, 0, + 0, 1771, 0, + 0, 1903, 0, + 0, 2035, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1913, 0, 1833, + 1908, 0, 1829, + 1902, 0, 1823, + 1893, 93, 1816, + 1882, 293, 1805, + 1866, 470, 1790, + 1843, 633, 1770, + 1811, 787, 1741, + 1765, 935, 1699, + 1694, 1078, 1637, + 1579, 1218, 1537, + 1357, 1357, 1357, + 514, 1493, 877, + 0, 1629, 0, + 0, 1763, 0, + 0, 1897, 0, + 0, 2031, 0, + 0, 2165, 0, + 0, 2297, 0, + 0, 2429, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2037, 0, 1935, + 2034, 0, 1932, + 2029, 0, 1927, + 2023, 0, 1921, + 2014, 0, 1913, + 2002, 254, 1901, + 1985, 493, 1885, + 1962, 692, 1863, + 1930, 868, 1832, + 1882, 1030, 1786, + 1809, 1184, 1716, + 1688, 1331, 1603, + 1450, 1475, 1386, + 311, 1615, 612, + 0, 1753, 0, + 0, 1890, 0, + 0, 2025, 0, + 0, 2159, 0, + 0, 2293, 0, + 0, 2427, 0, + 0, 2561, 0, + 0, 2693, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2163, 0, 2044, + 2161, 0, 2041, + 2157, 0, 2037, + 2153, 0, 2033, + 2147, 0, 2026, + 2137, 0, 2017, + 2125, 195, 2005, + 2109, 522, 1988, + 2085, 760, 1964, + 2051, 958, 1930, + 2002, 1133, 1881, + 1927, 1295, 1805, + 1802, 1449, 1678, + 1551, 1596, 1422, + 0, 1739, 0, + 0, 1880, 0, + 0, 2018, 0, + 0, 2155, 0, + 0, 2289, 0, + 0, 2425, 0, + 0, 2559, 0, + 0, 2691, 0, + 0, 2825, 0, + 0, 2957, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2291, 0, 2157, + 2289, 0, 2155, + 2287, 0, 2153, + 2283, 0, 2149, + 2279, 0, 2143, + 2271, 0, 2137, + 2263, 0, 2127, + 2251, 102, 2115, + 2233, 559, 2097, + 2209, 838, 2071, + 2175, 1055, 2035, + 2125, 1242, 1983, + 2049, 1412, 1901, + 1920, 1570, 1762, + 1658, 1720, 1466, + 0, 1866, 0, + 0, 2007, 0, + 0, 2147, 0, + 0, 2283, 0, + 0, 2419, 0, + 0, 2555, 0, + 0, 2689, 0, + 0, 2823, 0, + 0, 2957, 0, + 0, 3089, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3885, 0, + 0, 4017, 0, + 2421, 0, 2275, + 2419, 0, 2273, + 2417, 0, 2271, + 2415, 0, 2269, + 2411, 0, 2265, + 2405, 0, 2259, + 2399, 0, 2251, + 2389, 0, 2241, + 2377, 0, 2229, + 2359, 603, 2209, + 2335, 925, 2183, + 2301, 1160, 2147, + 2251, 1356, 2091, + 2173, 1531, 2004, + 2041, 1693, 1855, + 1771, 1846, 1520, + 0, 1993, 0, + 0, 2137, 0, + 0, 2277, 0, + 0, 2415, 0, + 0, 2551, 0, + 0, 2687, 0, + 0, 2821, 0, + 0, 2955, 0, + 0, 3089, 0, + 0, 3221, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3885, 0, + 0, 4017, 0, + 2551, 0, 2395, + 2549, 0, 2395, + 2547, 0, 2393, + 2545, 0, 2391, + 2543, 0, 2387, + 2539, 0, 2383, + 2533, 0, 2379, + 2527, 0, 2371, + 2517, 0, 2361, + 2505, 0, 2347, + 2487, 657, 2327, + 2463, 1020, 2301, + 2429, 1270, 2261, + 2377, 1475, 2205, + 2299, 1654, 2113, + 2165, 1818, 1955, + 1888, 1973, 1583, + 0, 2121, 0, + 0, 2265, 0, + 0, 2407, 0, + 0, 2545, 0, + 0, 2681, 0, + 0, 2817, 0, + 0, 2953, 0, + 0, 3087, 0, + 0, 3219, 0, + 0, 3353, 0, + 0, 3485, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4017, 0, + 2681, 0, 2519, + 2679, 0, 2519, + 2679, 0, 2517, + 2677, 0, 2515, + 2675, 0, 2513, + 2673, 0, 2511, + 2669, 0, 2505, + 2663, 0, 2501, + 2657, 0, 2493, + 2647, 0, 2483, + 2635, 0, 2469, + 2617, 720, 2449, + 2593, 1122, 2421, + 2557, 1386, 2381, + 2505, 1596, 2321, + 2425, 1779, 2229, + 2291, 1946, 2061, + 2008, 2101, 1655, + 0, 2251, 0, + 0, 2397, 0, + 0, 2537, 0, + 0, 2677, 0, + 0, 2813, 0, + 0, 2949, 0, + 0, 3083, 0, + 0, 3219, 0, + 0, 3351, 0, + 0, 3485, 0, + 0, 3617, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 2811, 0, 2645, + 2811, 0, 2645, + 2809, 0, 2643, + 2809, 0, 2641, + 2807, 0, 2641, + 2805, 0, 2637, + 2803, 0, 2635, + 2799, 0, 2631, + 2793, 0, 2625, + 2787, 0, 2617, + 2777, 0, 2607, + 2765, 0, 2593, + 2747, 792, 2573, + 2721, 1230, 2545, + 2687, 1505, 2503, + 2635, 1720, 2443, + 2555, 1906, 2347, + 2417, 2073, 2173, + 2131, 2231, 1736, + 0, 2381, 0, + 0, 2527, 0, + 0, 2669, 0, + 0, 2807, 0, + 0, 2945, 0, + 0, 3081, 0, + 0, 3215, 0, + 0, 3351, 0, + 0, 3483, 0, + 0, 3617, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 2943, 0, 2773, + 2941, 0, 2771, + 2941, 0, 2771, + 2941, 0, 2769, + 2939, 0, 2769, + 2937, 0, 2767, + 2935, 0, 2765, + 2933, 0, 2761, + 2929, 0, 2757, + 2923, 0, 2751, + 2917, 0, 2743, + 2907, 0, 2733, + 2895, 0, 2719, + 2877, 874, 2699, + 2853, 1344, 2669, + 2817, 1627, 2629, + 2765, 1846, 2567, + 2683, 2034, 2469, + 2547, 2203, 2291, + 2257, 2361, 1827, + 0, 2513, 0, + 0, 2657, 0, + 0, 2799, 0, + 0, 2939, 0, + 0, 3077, 0, + 0, 3213, 0, + 0, 3347, 0, + 0, 3481, 0, + 0, 3615, 0, + 0, 3749, 0, + 0, 3883, 0, + 0, 4015, 0, + 3073, 0, 2901, + 3073, 0, 2901, + 3073, 0, 2899, + 3073, 0, 2899, + 3071, 0, 2897, + 3071, 0, 2897, + 3069, 0, 2895, + 3067, 0, 2893, + 3063, 0, 2889, + 3059, 0, 2885, + 3055, 0, 2879, + 3047, 0, 2871, + 3039, 0, 2861, + 3025, 0, 2847, + 3007, 964, 2825, + 2983, 1462, 2797, + 2947, 1751, 2755, + 2895, 1973, 2693, + 2813, 2163, 2593, + 2675, 2333, 2411, + 2383, 2493, 1925, + 0, 2643, 0, + 0, 2789, 0, + 0, 2931, 0, + 0, 3071, 0, + 0, 3209, 0, + 0, 3345, 0, + 0, 3479, 0, + 0, 3613, 0, + 0, 3747, 0, + 0, 3881, 0, + 0, 4015, 0, + 3205, 0, 3029, + 3205, 0, 3029, + 3205, 0, 3029, + 3205, 0, 3029, + 3203, 0, 3027, + 3203, 0, 3027, + 3201, 0, 3025, + 3199, 0, 3023, + 3197, 0, 3021, + 3195, 0, 3019, + 3191, 0, 3013, + 3187, 0, 3009, + 3179, 0, 3001, + 3169, 0, 2989, + 3157, 0, 2975, + 3139, 1062, 2955, + 3115, 1583, 2925, + 3079, 1877, 2883, + 3025, 2101, 2819, + 2945, 2293, 2719, + 2805, 2463, 2533, + 2513, 2623, 2030, + 0, 2775, 0, + 0, 2921, 0, + 0, 3063, 0, + 0, 3203, 0, + 0, 3341, 0, + 0, 3477, 0, + 0, 3611, 0, + 0, 3747, 0, + 0, 3879, 0, + 0, 4013, 0, + 3337, 0, 3159, + 3337, 0, 3159, + 3337, 0, 3159, + 3335, 0, 3159, + 3335, 0, 3159, + 3335, 0, 3157, + 3335, 0, 3157, + 3333, 0, 3155, + 3331, 0, 3153, + 3329, 0, 3151, + 3327, 0, 3149, + 3323, 0, 3143, + 3317, 0, 3137, + 3311, 0, 3129, + 3301, 0, 3119, + 3289, 0, 3105, + 3271, 1167, 3083, + 3245, 1707, 3055, + 3209, 2005, 3011, + 3157, 2231, 2947, + 3075, 2423, 2845, + 2937, 2595, 2659, + 2641, 2755, 2141, + 0, 2907, 0, + 0, 3053, 0, + 0, 3195, 0, + 0, 3335, 0, + 0, 3473, 0, + 0, 3609, 0, + 0, 3743, 0, + 0, 3879, 0, + 0, 4011, 0, + 3469, 0, 3291, + 3469, 0, 3291, + 3469, 0, 3291, + 3469, 0, 3289, + 3467, 0, 3289, + 3467, 0, 3289, + 3467, 0, 3289, + 3465, 0, 3287, + 3465, 0, 3285, + 3463, 0, 3283, + 3461, 0, 3281, + 3459, 0, 3279, + 3455, 0, 3275, + 3449, 0, 3269, + 3443, 0, 3261, + 3433, 0, 3249, + 3419, 0, 3235, + 3403, 1278, 3213, + 3377, 1832, 3183, + 3341, 2133, 3141, + 3289, 2361, 3077, + 3207, 2553, 2975, + 3067, 2725, 2785, + 2771, 2885, 2255, + 0, 3037, 0, + 0, 3185, 0, + 0, 3327, 0, + 0, 3467, 0, + 0, 3605, 0, + 0, 3741, 0, + 0, 3875, 0, + 0, 4011, 0, + 3601, 0, 3421, + 3601, 0, 3421, + 3601, 0, 3421, + 3601, 0, 3421, + 3599, 0, 3421, + 3599, 0, 3421, + 3599, 0, 3419, + 3599, 0, 3419, + 3597, 0, 3417, + 3597, 0, 3417, + 3595, 0, 3415, + 3593, 0, 3413, + 3589, 0, 3409, + 3587, 0, 3405, + 3581, 0, 3399, + 3573, 0, 3391, + 3565, 0, 3379, + 3551, 0, 3365, + 3533, 1393, 3345, + 3509, 1959, 3315, + 3473, 2263, 3271, + 3419, 2491, 3207, + 3339, 2685, 3103, + 3199, 2857, 2913, + 2901, 3017, 2375, + 0, 3169, 0, + 0, 3317, 0, + 0, 3459, 0, + 0, 3599, 0, + 0, 3737, 0, + 0, 3873, 0, + 0, 4007, 0, + 3733, 0, 3553, + 3733, 0, 3553, + 3733, 0, 3553, + 3733, 0, 3553, + 3731, 0, 3553, + 3731, 0, 3551, + 3731, 0, 3551, + 3731, 0, 3551, + 3731, 0, 3551, + 3729, 0, 3549, + 3729, 0, 3547, + 3727, 0, 3545, + 3725, 0, 3543, + 3721, 0, 3541, + 3717, 0, 3535, + 3713, 0, 3531, + 3705, 0, 3521, + 3697, 0, 3511, + 3683, 0, 3495, + 3665, 1513, 3475, + 3641, 2087, 3445, + 3605, 2393, 3403, + 3551, 2623, 3337, + 3469, 2817, 3233, + 3331, 2989, 3043, + 3033, 3149, 2497, + 0, 3301, 0, + 0, 3449, 0, + 0, 3591, 0, + 0, 3731, 0, + 0, 3869, 0, + 0, 4005, 0, + 3865, 0, 3685, + 3865, 0, 3685, + 3865, 0, 3683, + 3865, 0, 3683, + 3865, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3681, + 3861, 0, 3681, + 3861, 0, 3679, + 3859, 0, 3677, + 3857, 0, 3675, + 3853, 0, 3671, + 3849, 0, 3667, + 3845, 0, 3661, + 3837, 0, 3653, + 3829, 0, 3643, + 3815, 0, 3627, + 3797, 1635, 3607, + 3773, 2217, 3577, + 3737, 2525, 3533, + 3683, 2755, 3469, + 3601, 2947, 3365, + 3461, 3121, 3173, + 3163, 3281, 2621, + 0, 3433, 0, + 0, 3581, 0, + 0, 3723, 0, + 0, 3863, 0, + 0, 4001, 0, + 3997, 0, 3815, + 3997, 0, 3815, + 3997, 0, 3815, + 3997, 0, 3815, + 3997, 0, 3815, + 3997, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3813, + 3995, 0, 3813, + 3993, 0, 3813, + 3993, 0, 3811, + 3991, 0, 3809, + 3989, 0, 3807, + 3985, 0, 3803, + 3981, 0, 3799, + 3977, 0, 3793, + 3969, 0, 3785, + 3961, 0, 3773, + 3947, 0, 3759, + 3929, 1759, 3737, + 3905, 2347, 3707, + 3869, 2655, 3665, + 3815, 2885, 3599, + 3733, 3079, 3495, + 3593, 3253, 3303, + 3295, 3413, 2749, + 0, 3565, 0, + 0, 3713, 0, + 0, 3855, 0, + 0, 3995, 0, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3943, + 4095, 0, 3943, + 4095, 0, 3941, + 4095, 0, 3939, + 4095, 0, 3935, + 4095, 0, 3931, + 4095, 0, 3925, + 4095, 0, 3917, + 4093, 0, 3905, + 4079, 0, 3891, + 4061, 1886, 3869, + 4037, 2477, 3839, + 4001, 2787, 3797, + 3947, 3017, 3731, + 3865, 3211, 3627, + 3725, 3385, 3435, + 3427, 3545, 2877, + 0, 3697, 0, + 0, 3845, 0, + 0, 3987, 0, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4075, + 4095, 0, 4075, + 4095, 0, 4073, + 4095, 0, 4069, + 4095, 0, 4067, + 4095, 0, 4063, + 4095, 0, 4057, + 4095, 0, 4049, + 4095, 0, 4037, + 4095, 0, 4023, + 4095, 2014, 4001, + 4095, 2609, 3971, + 4095, 2919, 3929, + 4079, 3149, 3863, + 3997, 3343, 3759, + 3857, 3517, 3565, + 3559, 3677, 3005, + 0, 3829, 0, + 0, 3977, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2143, 4095, + 4095, 2741, 4095, + 4095, 3051, 4059, + 4095, 3281, 3995, + 4095, 3475, 3891, + 3989, 3649, 3697, + 3691, 3809, 3135, + 0, 3961, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2273, 4095, + 4095, 2871, 4095, + 4095, 3183, 4095, + 4095, 3413, 4095, + 4095, 3607, 4021, + 4095, 3781, 3829, + 3823, 3941, 3265, + 1004, 617, 1393, + 969, 649, 1381, + 916, 689, 1366, + 836, 737, 1344, + 699, 794, 1313, + 412, 861, 1269, + 0, 937, 1201, + 0, 1022, 1091, + 0, 1116, 884, + 0, 1217, 213, + 0, 1324, 0, + 0, 1437, 0, + 0, 1554, 0, + 0, 1675, 0, + 0, 1798, 0, + 0, 1923, 0, + 0, 2051, 0, + 0, 2179, 0, + 0, 2307, 0, + 0, 2437, 0, + 0, 2569, 0, + 0, 2699, 0, + 0, 2831, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1045, 612, 1405, + 1013, 645, 1394, + 966, 685, 1379, + 895, 733, 1358, + 777, 791, 1328, + 549, 858, 1284, + 0, 935, 1219, + 0, 1020, 1114, + 0, 1114, 920, + 0, 1216, 354, + 0, 1323, 0, + 0, 1436, 0, + 0, 1554, 0, + 0, 1674, 0, + 0, 1798, 0, + 0, 1923, 0, + 0, 2051, 0, + 0, 2179, 0, + 0, 2307, 0, + 0, 2437, 0, + 0, 2569, 0, + 0, 2699, 0, + 0, 2831, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1095, 605, 1421, + 1066, 638, 1410, + 1025, 679, 1395, + 963, 728, 1375, + 864, 786, 1346, + 684, 854, 1305, + 209, 931, 1243, + 0, 1018, 1144, + 0, 1112, 965, + 0, 1214, 493, + 0, 1322, 0, + 0, 1435, 0, + 0, 1553, 0, + 0, 1674, 0, + 0, 1797, 0, + 0, 1923, 0, + 0, 2049, 0, + 0, 2179, 0, + 0, 2307, 0, + 0, 2437, 0, + 0, 2569, 0, + 0, 2699, 0, + 0, 2831, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1154, 596, 1441, + 1129, 629, 1431, + 1093, 671, 1417, + 1040, 721, 1397, + 958, 780, 1370, + 818, 848, 1331, + 519, 927, 1272, + 0, 1014, 1180, + 0, 1109, 1018, + 0, 1211, 630, + 0, 1320, 0, + 0, 1434, 0, + 0, 1552, 0, + 0, 1673, 0, + 0, 1796, 0, + 0, 1922, 0, + 0, 2049, 0, + 0, 2179, 0, + 0, 2307, 0, + 0, 2437, 0, + 0, 2569, 0, + 0, 2699, 0, + 0, 2831, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1223, 583, 1467, + 1202, 617, 1457, + 1171, 660, 1444, + 1127, 711, 1426, + 1060, 771, 1400, + 952, 841, 1363, + 750, 920, 1309, + 121, 1009, 1225, + 0, 1105, 1081, + 0, 1208, 765, + 0, 1317, 0, + 0, 1432, 0, + 0, 1550, 0, + 0, 1671, 0, + 0, 1796, 0, + 0, 1922, 0, + 0, 2049, 0, + 0, 2177, 0, + 0, 2307, 0, + 0, 2437, 0, + 0, 2567, 0, + 0, 2699, 0, + 0, 2831, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1301, 565, 1499, + 1283, 601, 1490, + 1258, 645, 1478, + 1222, 697, 1461, + 1168, 759, 1437, + 1085, 831, 1404, + 944, 912, 1354, + 639, 1002, 1279, + 0, 1099, 1153, + 0, 1204, 900, + 0, 1314, 0, + 0, 1429, 0, + 0, 1548, 0, + 0, 1670, 0, + 0, 1794, 0, + 0, 1921, 0, + 0, 2049, 0, + 0, 2177, 0, + 0, 2307, 0, + 0, 2437, 0, + 0, 2567, 0, + 0, 2699, 0, + 0, 2831, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1389, 540, 1539, + 1374, 578, 1531, + 1353, 624, 1520, + 1324, 679, 1504, + 1282, 743, 1483, + 1219, 817, 1452, + 1117, 900, 1408, + 933, 992, 1342, + 429, 1091, 1234, + 0, 1197, 1034, + 0, 1309, 419, + 0, 1425, 0, + 0, 1545, 0, + 0, 1668, 0, + 0, 1793, 0, + 0, 1919, 0, + 0, 2047, 0, + 0, 2177, 0, + 0, 2307, 0, + 0, 2437, 0, + 0, 2567, 0, + 0, 2699, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1484, 504, 1587, + 1472, 545, 1580, + 1456, 594, 1570, + 1432, 652, 1556, + 1400, 721, 1537, + 1351, 798, 1510, + 1278, 885, 1472, + 1157, 979, 1415, + 917, 1081, 1325, + 0, 1189, 1167, + 0, 1303, 802, + 0, 1420, 0, + 0, 1541, 0, + 0, 1665, 0, + 0, 1790, 0, + 0, 1918, 0, + 0, 2046, 0, + 0, 2175, 0, + 0, 2305, 0, + 0, 2437, 0, + 0, 2567, 0, + 0, 2699, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1587, 451, 1645, + 1577, 497, 1639, + 1564, 551, 1630, + 1546, 615, 1618, + 1520, 688, 1601, + 1484, 771, 1578, + 1430, 862, 1545, + 1347, 961, 1497, + 1204, 1067, 1423, + 896, 1178, 1301, + 0, 1294, 1059, + 0, 1414, 0, + 0, 1536, 0, + 0, 1661, 0, + 0, 1788, 0, + 0, 1915, 0, + 0, 2044, 0, + 0, 2175, 0, + 0, 2305, 0, + 0, 2435, 0, + 0, 2567, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1695, 369, 1712, + 1688, 423, 1707, + 1678, 486, 1699, + 1664, 559, 1689, + 1644, 641, 1675, + 1617, 732, 1655, + 1577, 831, 1627, + 1518, 936, 1587, + 1425, 1047, 1528, + 1261, 1163, 1434, + 865, 1282, 1266, + 0, 1404, 856, + 0, 1529, 0, + 0, 1656, 0, + 0, 1784, 0, + 0, 1912, 0, + 0, 2042, 0, + 0, 2173, 0, + 0, 2303, 0, + 0, 2435, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1809, 230, 1789, + 1803, 301, 1784, + 1795, 382, 1778, + 1785, 472, 1769, + 1770, 570, 1757, + 1749, 675, 1741, + 1720, 785, 1718, + 1678, 900, 1686, + 1614, 1019, 1638, + 1513, 1141, 1566, + 1328, 1266, 1448, + 821, 1392, 1216, + 0, 1520, 219, + 0, 1649, 0, + 0, 1778, 0, + 0, 1908, 0, + 0, 2039, 0, + 0, 2171, 0, + 0, 2301, 0, + 0, 2433, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1927, 0, 1875, + 1923, 61, 1871, + 1917, 191, 1865, + 1908, 322, 1858, + 1897, 453, 1849, + 1881, 584, 1835, + 1860, 716, 1817, + 1829, 847, 1791, + 1785, 979, 1754, + 1717, 1111, 1699, + 1608, 1243, 1613, + 1404, 1375, 1466, + 754, 1507, 1139, + 0, 1639, 0, + 0, 1771, 0, + 0, 1903, 0, + 0, 2035, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2049, 0, 1969, + 2045, 0, 1966, + 2040, 0, 1961, + 2034, 0, 1955, + 2025, 225, 1948, + 2014, 425, 1937, + 1998, 602, 1922, + 1975, 765, 1902, + 1943, 919, 1873, + 1897, 1067, 1831, + 1827, 1210, 1769, + 1711, 1351, 1669, + 1489, 1489, 1489, + 646, 1625, 1009, + 0, 1761, 0, + 0, 1896, 0, + 0, 2029, 0, + 0, 2163, 0, + 0, 2297, 0, + 0, 2429, 0, + 0, 2561, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2173, 0, 2071, + 2169, 0, 2067, + 2165, 0, 2065, + 2161, 0, 2059, + 2155, 0, 2053, + 2145, 53, 2045, + 2135, 386, 2033, + 2117, 625, 2017, + 2095, 824, 1995, + 2061, 1000, 1964, + 2014, 1162, 1918, + 1941, 1316, 1848, + 1820, 1464, 1735, + 1582, 1607, 1518, + 443, 1747, 744, + 0, 1885, 0, + 0, 2022, 0, + 0, 2157, 0, + 0, 2291, 0, + 0, 2425, 0, + 0, 2559, 0, + 0, 2693, 0, + 0, 2825, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2297, 0, 2177, + 2295, 0, 2175, + 2293, 0, 2173, + 2289, 0, 2169, + 2285, 0, 2165, + 2279, 0, 2159, + 2269, 0, 2149, + 2257, 327, 2137, + 2241, 655, 2119, + 2217, 892, 2097, + 2183, 1090, 2063, + 2135, 1265, 2013, + 2059, 1428, 1937, + 1934, 1581, 1810, + 1683, 1728, 1554, + 0, 1871, 0, + 0, 2012, 0, + 0, 2149, 0, + 0, 2287, 0, + 0, 2421, 0, + 0, 2557, 0, + 0, 2691, 0, + 0, 2823, 0, + 0, 2957, 0, + 0, 3089, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2425, 0, 2291, + 2423, 0, 2289, + 2421, 0, 2287, + 2419, 0, 2285, + 2415, 0, 2281, + 2411, 0, 2275, + 2403, 0, 2269, + 2395, 0, 2259, + 2383, 234, 2247, + 2365, 691, 2229, + 2341, 970, 2203, + 2307, 1188, 2167, + 2257, 1374, 2115, + 2181, 1544, 2033, + 2051, 1702, 1894, + 1790, 1852, 1599, + 0, 1998, 0, + 0, 2139, 0, + 0, 2279, 0, + 0, 2417, 0, + 0, 2553, 0, + 0, 2687, 0, + 0, 2821, 0, + 0, 2955, 0, + 0, 3089, 0, + 0, 3221, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3885, 0, + 0, 4017, 0, + 2553, 0, 2409, + 2553, 0, 2407, + 2551, 0, 2405, + 2549, 0, 2403, + 2547, 0, 2401, + 2543, 0, 2397, + 2537, 0, 2391, + 2531, 0, 2383, + 2521, 0, 2375, + 2509, 69, 2361, + 2491, 735, 2343, + 2467, 1057, 2315, + 2433, 1292, 2279, + 2383, 1489, 2223, + 2305, 1663, 2137, + 2173, 1825, 1987, + 1903, 1978, 1652, + 0, 2125, 0, + 0, 2269, 0, + 0, 2409, 0, + 0, 2547, 0, + 0, 2683, 0, + 0, 2819, 0, + 0, 2953, 0, + 0, 3087, 0, + 0, 3221, 0, + 0, 3353, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4017, 0, + 2683, 0, 2529, + 2683, 0, 2527, + 2681, 0, 2527, + 2679, 0, 2525, + 2677, 0, 2523, + 2675, 0, 2519, + 2671, 0, 2515, + 2667, 0, 2511, + 2659, 0, 2503, + 2651, 0, 2493, + 2637, 0, 2479, + 2619, 789, 2459, + 2595, 1152, 2433, + 2561, 1403, 2395, + 2509, 1607, 2337, + 2431, 1786, 2245, + 2297, 1951, 2087, + 2020, 2105, 1715, + 0, 2253, 0, + 0, 2397, 0, + 0, 2539, 0, + 0, 2677, 0, + 0, 2815, 0, + 0, 2949, 0, + 0, 3085, 0, + 0, 3219, 0, + 0, 3351, 0, + 0, 3485, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 2813, 0, 2653, + 2813, 0, 2651, + 2811, 0, 2651, + 2811, 0, 2649, + 2809, 0, 2647, + 2807, 0, 2645, + 2805, 0, 2643, + 2801, 0, 2639, + 2795, 0, 2633, + 2789, 0, 2625, + 2779, 0, 2615, + 2767, 0, 2601, + 2749, 852, 2581, + 2725, 1254, 2553, + 2689, 1518, 2513, + 2637, 1728, 2455, + 2557, 1911, 2361, + 2423, 2077, 2193, + 2141, 2235, 1787, + 0, 2383, 0, + 0, 2529, 0, + 0, 2669, 0, + 0, 2809, 0, + 0, 2945, 0, + 0, 3081, 0, + 0, 3217, 0, + 0, 3351, 0, + 0, 3483, 0, + 0, 3617, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 2943, 0, 2777, + 2943, 0, 2777, + 2943, 0, 2777, + 2941, 0, 2775, + 2941, 0, 2775, + 2939, 0, 2773, + 2937, 0, 2771, + 2935, 0, 2767, + 2931, 0, 2763, + 2925, 0, 2757, + 2919, 0, 2749, + 2909, 0, 2739, + 2897, 0, 2725, + 2879, 924, 2705, + 2855, 1363, 2677, + 2819, 1637, 2635, + 2767, 1852, 2575, + 2687, 2038, 2479, + 2549, 2207, 2305, + 2263, 2363, 1869, + 0, 2513, 0, + 0, 2659, 0, + 0, 2801, 0, + 0, 2939, 0, + 0, 3077, 0, + 0, 3213, 0, + 0, 3347, 0, + 0, 3483, 0, + 0, 3615, 0, + 0, 3749, 0, + 0, 3883, 0, + 0, 4015, 0, + 3075, 0, 2905, + 3075, 0, 2905, + 3073, 0, 2903, + 3073, 0, 2903, + 3073, 0, 2903, + 3071, 0, 2901, + 3069, 0, 2899, + 3067, 0, 2897, + 3065, 0, 2893, + 3061, 0, 2889, + 3055, 0, 2883, + 3049, 0, 2875, + 3039, 0, 2865, + 3027, 0, 2851, + 3009, 1006, 2831, + 2985, 1476, 2801, + 2949, 1759, 2761, + 2897, 1978, 2699, + 2815, 2165, 2601, + 2679, 2335, 2423, + 2389, 2493, 1959, + 0, 2645, 0, + 0, 2791, 0, + 0, 2931, 0, + 0, 3071, 0, + 0, 3209, 0, + 0, 3345, 0, + 0, 3479, 0, + 0, 3615, 0, + 0, 3747, 0, + 0, 3881, 0, + 0, 4015, 0, + 3205, 0, 3033, + 3205, 0, 3033, + 3205, 0, 3033, + 3205, 0, 3031, + 3205, 0, 3031, + 3203, 0, 3031, + 3203, 0, 3029, + 3201, 0, 3027, + 3199, 0, 3025, + 3195, 0, 3021, + 3193, 0, 3017, + 3187, 0, 3011, + 3181, 0, 3003, + 3171, 0, 2993, + 3157, 0, 2979, + 3141, 1096, 2957, + 3115, 1594, 2929, + 3079, 1883, 2887, + 3027, 2105, 2825, + 2945, 2295, 2725, + 2807, 2465, 2543, + 2515, 2625, 2057, + 0, 2775, 0, + 0, 2921, 0, + 0, 3063, 0, + 0, 3203, 0, + 0, 3341, 0, + 0, 3477, 0, + 0, 3611, 0, + 0, 3747, 0, + 0, 3879, 0, + 0, 4013, 0, + 3337, 0, 3163, + 3337, 0, 3163, + 3337, 0, 3161, + 3337, 0, 3161, + 3337, 0, 3161, + 3335, 0, 3161, + 3335, 0, 3159, + 3333, 0, 3157, + 3331, 0, 3155, + 3329, 0, 3153, + 3327, 0, 3151, + 3323, 0, 3147, + 3319, 0, 3141, + 3311, 0, 3133, + 3301, 0, 3121, + 3289, 0, 3107, + 3271, 1194, 3087, + 3247, 1715, 3057, + 3211, 2010, 3015, + 3157, 2233, 2951, + 3077, 2425, 2851, + 2937, 2595, 2665, + 2645, 2755, 2161, + 0, 2907, 0, + 0, 3053, 0, + 0, 3195, 0, + 0, 3335, 0, + 0, 3473, 0, + 0, 3609, 0, + 0, 3743, 0, + 0, 3879, 0, + 0, 4011, 0, + 3469, 0, 3293, + 3469, 0, 3293, + 3469, 0, 3291, + 3469, 0, 3291, + 3469, 0, 3291, + 3467, 0, 3291, + 3467, 0, 3289, + 3467, 0, 3289, + 3465, 0, 3287, + 3463, 0, 3285, + 3461, 0, 3283, + 3459, 0, 3281, + 3455, 0, 3275, + 3449, 0, 3269, + 3443, 0, 3263, + 3433, 0, 3251, + 3421, 0, 3237, + 3403, 1299, 3215, + 3377, 1839, 3187, + 3341, 2137, 3143, + 3289, 2363, 3079, + 3207, 2555, 2977, + 3069, 2727, 2791, + 2773, 2887, 2273, + 0, 3039, 0, + 0, 3185, 0, + 0, 3327, 0, + 0, 3467, 0, + 0, 3605, 0, + 0, 3741, 0, + 0, 3875, 0, + 0, 4011, 0, + 3601, 0, 3423, + 3601, 0, 3423, + 3601, 0, 3423, + 3601, 0, 3423, + 3601, 0, 3421, + 3599, 0, 3421, + 3599, 0, 3421, + 3599, 0, 3421, + 3597, 0, 3419, + 3597, 0, 3417, + 3595, 0, 3417, + 3593, 0, 3413, + 3591, 0, 3411, + 3587, 0, 3407, + 3581, 0, 3401, + 3575, 0, 3393, + 3565, 0, 3381, + 3553, 0, 3367, + 3535, 1410, 3345, + 3509, 1964, 3317, + 3473, 2267, 3273, + 3421, 2493, 3209, + 3339, 2685, 3107, + 3199, 2857, 2917, + 2903, 3019, 2389, + 0, 3169, 0, + 0, 3317, 0, + 0, 3459, 0, + 0, 3599, 0, + 0, 3737, 0, + 0, 3873, 0, + 0, 4007, 0, + 3733, 0, 3553, + 3733, 0, 3553, + 3733, 0, 3553, + 3733, 0, 3553, + 3733, 0, 3553, + 3731, 0, 3553, + 3731, 0, 3553, + 3731, 0, 3551, + 3731, 0, 3551, + 3729, 0, 3551, + 3729, 0, 3549, + 3727, 0, 3547, + 3725, 0, 3545, + 3721, 0, 3541, + 3719, 0, 3537, + 3713, 0, 3531, + 3707, 0, 3523, + 3697, 0, 3513, + 3683, 0, 3497, + 3665, 1525, 3477, + 3641, 2091, 3447, + 3605, 2395, 3403, + 3553, 2625, 3339, + 3471, 2817, 3235, + 3331, 2989, 3045, + 3033, 3149, 2507, + 0, 3301, 0, + 0, 3449, 0, + 0, 3591, 0, + 0, 3731, 0, + 0, 3869, 0, + 0, 4005, 0, + 3865, 0, 3685, + 3865, 0, 3685, + 3865, 0, 3685, + 3865, 0, 3685, + 3865, 0, 3685, + 3865, 0, 3685, + 3863, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3683, + 3863, 0, 3683, + 3861, 0, 3681, + 3861, 0, 3679, + 3859, 0, 3679, + 3857, 0, 3675, + 3853, 0, 3673, + 3851, 0, 3669, + 3845, 0, 3663, + 3837, 0, 3655, + 3829, 0, 3643, + 3815, 0, 3629, + 3797, 1645, 3607, + 3773, 2221, 3577, + 3737, 2527, 3535, + 3683, 2755, 3469, + 3601, 2949, 3367, + 3463, 3121, 3175, + 3165, 3281, 2629, + 0, 3433, 0, + 0, 3581, 0, + 0, 3723, 0, + 0, 3863, 0, + 0, 4001, 0, + 3997, 0, 3817, + 3997, 0, 3817, + 3997, 0, 3817, + 3997, 0, 3817, + 3997, 0, 3815, + 3997, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3813, + 3993, 0, 3813, + 3993, 0, 3811, + 3991, 0, 3809, + 3989, 0, 3807, + 3985, 0, 3803, + 3981, 0, 3799, + 3977, 0, 3793, + 3969, 0, 3785, + 3961, 0, 3775, + 3947, 0, 3759, + 3929, 1767, 3739, + 3905, 2349, 3709, + 3869, 2657, 3665, + 3815, 2887, 3601, + 3733, 3079, 3497, + 3593, 3253, 3305, + 3295, 3413, 2755, + 0, 3565, 0, + 0, 3713, 0, + 0, 3855, 0, + 0, 3995, 0, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3943, + 4095, 0, 3941, + 4095, 0, 3939, + 4095, 0, 3935, + 4095, 0, 3931, + 4095, 0, 3925, + 4095, 0, 3917, + 4093, 0, 3907, + 4079, 0, 3891, + 4061, 1892, 3869, + 4037, 2479, 3841, + 4001, 2787, 3797, + 3947, 3017, 3733, + 3865, 3211, 3627, + 3725, 3385, 3435, + 3427, 3545, 2881, + 0, 3697, 0, + 0, 3845, 0, + 0, 3987, 0, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4075, + 4095, 0, 4075, + 4095, 0, 4073, + 4095, 0, 4071, + 4095, 0, 4067, + 4095, 0, 4063, + 4095, 0, 4057, + 4095, 0, 4049, + 4095, 0, 4037, + 4095, 0, 4023, + 4095, 2018, 4001, + 4095, 2611, 3971, + 4095, 2919, 3929, + 4079, 3149, 3863, + 3997, 3343, 3759, + 3857, 3517, 3567, + 3559, 3677, 3009, + 0, 3829, 0, + 0, 3977, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2145, 4095, + 4095, 2741, 4095, + 4095, 3051, 4061, + 4095, 3281, 3995, + 4095, 3475, 3891, + 3989, 3649, 3697, + 3691, 3809, 3137, + 0, 3961, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2275, 4095, + 4095, 2873, 4095, + 4095, 3183, 4095, + 4095, 3413, 4095, + 4095, 3607, 4023, + 4095, 3781, 3829, + 3823, 3941, 3267, + 1129, 728, 1524, + 1102, 753, 1516, + 1064, 785, 1504, + 1008, 824, 1488, + 919, 872, 1466, + 763, 929, 1434, + 407, 995, 1388, + 0, 1071, 1319, + 0, 1156, 1205, + 0, 1249, 987, + 0, 1350, 201, + 0, 1457, 0, + 0, 1570, 0, + 0, 1687, 0, + 0, 1807, 0, + 0, 1930, 0, + 0, 2055, 0, + 0, 2183, 0, + 0, 2311, 0, + 0, 2441, 0, + 0, 2571, 0, + 0, 2701, 0, + 0, 2831, 0, + 0, 2963, 0, + 0, 3095, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1161, 724, 1533, + 1136, 750, 1525, + 1100, 782, 1514, + 1048, 821, 1498, + 968, 869, 1476, + 832, 926, 1445, + 544, 993, 1401, + 0, 1069, 1333, + 0, 1154, 1223, + 0, 1248, 1016, + 0, 1349, 345, + 0, 1456, 0, + 0, 1569, 0, + 0, 1686, 0, + 0, 1807, 0, + 0, 1930, 0, + 0, 2055, 0, + 0, 2183, 0, + 0, 2311, 0, + 0, 2441, 0, + 0, 2569, 0, + 0, 2701, 0, + 0, 2831, 0, + 0, 2963, 0, + 0, 3095, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1200, 719, 1545, + 1177, 745, 1537, + 1145, 777, 1526, + 1098, 817, 1511, + 1026, 865, 1490, + 909, 923, 1460, + 681, 990, 1417, + 0, 1066, 1351, + 0, 1152, 1246, + 0, 1246, 1052, + 0, 1348, 486, + 0, 1455, 0, + 0, 1568, 0, + 0, 1686, 0, + 0, 1806, 0, + 0, 1930, 0, + 0, 2055, 0, + 0, 2183, 0, + 0, 2311, 0, + 0, 2439, 0, + 0, 2569, 0, + 0, 2701, 0, + 0, 2831, 0, + 0, 2963, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1248, 711, 1561, + 1227, 738, 1553, + 1198, 770, 1542, + 1157, 811, 1528, + 1095, 860, 1507, + 996, 918, 1478, + 816, 986, 1437, + 341, 1063, 1375, + 0, 1149, 1276, + 0, 1244, 1097, + 0, 1346, 625, + 0, 1454, 0, + 0, 1567, 0, + 0, 1685, 0, + 0, 1806, 0, + 0, 1929, 0, + 0, 2055, 0, + 0, 2183, 0, + 0, 2311, 0, + 0, 2439, 0, + 0, 2569, 0, + 0, 2701, 0, + 0, 2831, 0, + 0, 2963, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1304, 701, 1581, + 1286, 728, 1573, + 1261, 762, 1563, + 1225, 803, 1549, + 1172, 853, 1530, + 1090, 912, 1502, + 951, 981, 1463, + 651, 1058, 1405, + 0, 1146, 1312, + 0, 1241, 1150, + 0, 1343, 762, + 0, 1452, 0, + 0, 1566, 0, + 0, 1684, 0, + 0, 1805, 0, + 0, 1929, 0, + 0, 2055, 0, + 0, 2181, 0, + 0, 2311, 0, + 0, 2439, 0, + 0, 2569, 0, + 0, 2701, 0, + 0, 2831, 0, + 0, 2963, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1371, 688, 1606, + 1355, 715, 1599, + 1334, 750, 1589, + 1303, 792, 1576, + 1259, 843, 1558, + 1192, 903, 1532, + 1084, 973, 1496, + 882, 1052, 1441, + 253, 1140, 1357, + 0, 1237, 1213, + 0, 1340, 897, + 0, 1449, 0, + 0, 1564, 0, + 0, 1682, 0, + 0, 1804, 0, + 0, 1928, 0, + 0, 2053, 0, + 0, 2181, 0, + 0, 2309, 0, + 0, 2439, 0, + 0, 2569, 0, + 0, 2701, 0, + 0, 2831, 0, + 0, 2963, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1447, 669, 1638, + 1434, 697, 1631, + 1416, 733, 1622, + 1390, 777, 1610, + 1354, 829, 1593, + 1301, 891, 1569, + 1218, 963, 1536, + 1076, 1044, 1486, + 771, 1134, 1411, + 0, 1231, 1285, + 0, 1336, 1032, + 0, 1446, 0, + 0, 1561, 0, + 0, 1680, 0, + 0, 1802, 0, + 0, 1926, 0, + 0, 2053, 0, + 0, 2181, 0, + 0, 2309, 0, + 0, 2439, 0, + 0, 2569, 0, + 0, 2699, 0, + 0, 2831, 0, + 0, 2963, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1532, 642, 1677, + 1521, 672, 1671, + 1506, 710, 1663, + 1485, 756, 1652, + 1456, 811, 1636, + 1414, 875, 1615, + 1351, 949, 1585, + 1249, 1032, 1541, + 1065, 1124, 1474, + 561, 1224, 1367, + 0, 1330, 1166, + 0, 1441, 551, + 0, 1557, 0, + 0, 1677, 0, + 0, 1800, 0, + 0, 1925, 0, + 0, 2051, 0, + 0, 2179, 0, + 0, 2309, 0, + 0, 2439, 0, + 0, 2569, 0, + 0, 2699, 0, + 0, 2831, 0, + 0, 2963, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1625, 603, 1725, + 1616, 636, 1720, + 1604, 677, 1712, + 1588, 726, 1702, + 1565, 785, 1688, + 1532, 853, 1669, + 1484, 930, 1643, + 1410, 1017, 1604, + 1289, 1111, 1547, + 1049, 1213, 1457, + 0, 1321, 1300, + 0, 1435, 934, + 0, 1552, 0, + 0, 1673, 0, + 0, 1797, 0, + 0, 1923, 0, + 0, 2049, 0, + 0, 2179, 0, + 0, 2307, 0, + 0, 2437, 0, + 0, 2569, 0, + 0, 2699, 0, + 0, 2831, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1726, 546, 1782, + 1719, 583, 1777, + 1709, 629, 1771, + 1696, 683, 1762, + 1678, 747, 1750, + 1653, 820, 1733, + 1616, 903, 1710, + 1563, 994, 1677, + 1479, 1093, 1629, + 1336, 1199, 1555, + 1028, 1310, 1433, + 0, 1426, 1191, + 0, 1546, 0, + 0, 1668, 0, + 0, 1793, 0, + 0, 1920, 0, + 0, 2047, 0, + 0, 2177, 0, + 0, 2307, 0, + 0, 2437, 0, + 0, 2567, 0, + 0, 2699, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1833, 456, 1848, + 1827, 501, 1844, + 1820, 555, 1839, + 1810, 618, 1831, + 1796, 691, 1821, + 1776, 774, 1807, + 1749, 864, 1787, + 1709, 963, 1759, + 1650, 1068, 1719, + 1558, 1179, 1660, + 1393, 1295, 1566, + 997, 1414, 1398, + 0, 1537, 988, + 0, 1661, 0, + 0, 1788, 0, + 0, 1916, 0, + 0, 2045, 0, + 0, 2175, 0, + 0, 2305, 0, + 0, 2435, 0, + 0, 2567, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1946, 299, 1925, + 1941, 362, 1921, + 1935, 433, 1916, + 1928, 514, 1910, + 1917, 604, 1901, + 1902, 702, 1889, + 1881, 807, 1873, + 1852, 917, 1850, + 1810, 1032, 1818, + 1746, 1151, 1771, + 1645, 1273, 1698, + 1460, 1398, 1580, + 953, 1524, 1348, + 0, 1652, 351, + 0, 1781, 0, + 0, 1910, 0, + 0, 2041, 0, + 0, 2171, 0, + 0, 2303, 0, + 0, 2433, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2063, 0, 2010, + 2059, 63, 2007, + 2055, 193, 2003, + 2049, 323, 1998, + 2040, 454, 1990, + 2029, 585, 1981, + 2014, 716, 1967, + 1992, 848, 1949, + 1961, 979, 1923, + 1917, 1111, 1886, + 1850, 1243, 1831, + 1740, 1375, 1745, + 1536, 1507, 1598, + 886, 1639, 1271, + 0, 1771, 0, + 0, 1903, 0, + 0, 2035, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2183, 0, 2103, + 2181, 0, 2101, + 2177, 0, 2097, + 2173, 0, 2093, + 2167, 115, 2087, + 2157, 358, 2079, + 2145, 557, 2069, + 2129, 734, 2055, + 2107, 897, 2034, + 2075, 1051, 2005, + 2029, 1199, 1964, + 1959, 1342, 1901, + 1843, 1483, 1801, + 1621, 1621, 1621, + 778, 1758, 1141, + 0, 1893, 0, + 0, 2028, 0, + 0, 2161, 0, + 0, 2295, 0, + 0, 2429, 0, + 0, 2561, 0, + 0, 2693, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2307, 0, 2205, + 2305, 0, 2203, + 2301, 0, 2199, + 2299, 0, 2197, + 2293, 0, 2191, + 2287, 0, 2185, + 2279, 185, 2177, + 2267, 518, 2165, + 2249, 757, 2149, + 2227, 956, 2127, + 2193, 1132, 2095, + 2145, 1295, 2051, + 2073, 1448, 1981, + 1952, 1596, 1867, + 1714, 1739, 1650, + 575, 1879, 876, + 0, 2018, 0, + 0, 2155, 0, + 0, 2289, 0, + 0, 2425, 0, + 0, 2559, 0, + 0, 2691, 0, + 0, 2825, 0, + 0, 2957, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2431, 0, 2311, + 2429, 0, 2309, + 2427, 0, 2307, + 2425, 0, 2305, + 2421, 0, 2301, + 2417, 0, 2297, + 2411, 0, 2291, + 2401, 0, 2281, + 2389, 459, 2269, + 2373, 787, 2251, + 2349, 1024, 2229, + 2315, 1222, 2195, + 2267, 1398, 2145, + 2191, 1560, 2069, + 2065, 1713, 1942, + 1815, 1860, 1686, + 0, 2004, 0, + 0, 2143, 0, + 0, 2281, 0, + 0, 2419, 0, + 0, 2553, 0, + 0, 2689, 0, + 0, 2823, 0, + 0, 2955, 0, + 0, 3089, 0, + 0, 3221, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3885, 0, + 0, 4017, 0, + 2559, 0, 2425, + 2557, 0, 2423, + 2555, 0, 2421, + 2553, 0, 2419, + 2551, 0, 2417, + 2547, 0, 2413, + 2543, 0, 2407, + 2535, 0, 2401, + 2527, 0, 2391, + 2515, 366, 2379, + 2497, 823, 2361, + 2473, 1102, 2335, + 2439, 1320, 2299, + 2389, 1507, 2247, + 2313, 1676, 2165, + 2183, 1834, 2026, + 1923, 1984, 1731, + 0, 2129, 0, + 0, 2271, 0, + 0, 2411, 0, + 0, 2549, 0, + 0, 2685, 0, + 0, 2819, 0, + 0, 2953, 0, + 0, 3087, 0, + 0, 3221, 0, + 0, 3353, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4017, 0, + 2687, 0, 2541, + 2685, 0, 2541, + 2685, 0, 2539, + 2683, 0, 2537, + 2681, 0, 2535, + 2679, 0, 2533, + 2675, 0, 2529, + 2669, 0, 2523, + 2663, 0, 2515, + 2653, 0, 2507, + 2641, 201, 2493, + 2625, 868, 2475, + 2599, 1189, 2449, + 2565, 1424, 2411, + 2515, 1621, 2355, + 2437, 1796, 2269, + 2305, 1957, 2119, + 2035, 2111, 1784, + 0, 2257, 0, + 0, 2401, 0, + 0, 2541, 0, + 0, 2679, 0, + 0, 2815, 0, + 0, 2951, 0, + 0, 3085, 0, + 0, 3219, 0, + 0, 3353, 0, + 0, 3485, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 2815, 0, 2661, + 2815, 0, 2661, + 2815, 0, 2659, + 2813, 0, 2659, + 2811, 0, 2657, + 2809, 0, 2655, + 2807, 0, 2651, + 2803, 0, 2647, + 2799, 0, 2643, + 2791, 0, 2635, + 2783, 0, 2625, + 2769, 0, 2611, + 2753, 921, 2591, + 2727, 1284, 2565, + 2693, 1535, 2527, + 2641, 1739, 2469, + 2563, 1918, 2379, + 2429, 2083, 2219, + 2153, 2237, 1847, + 0, 2387, 0, + 0, 2531, 0, + 0, 2671, 0, + 0, 2809, 0, + 0, 2947, 0, + 0, 3081, 0, + 0, 3217, 0, + 0, 3351, 0, + 0, 3485, 0, + 0, 3617, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 2945, 0, 2785, + 2945, 0, 2785, + 2945, 0, 2783, + 2943, 0, 2783, + 2943, 0, 2781, + 2941, 0, 2779, + 2939, 0, 2777, + 2937, 0, 2775, + 2933, 0, 2771, + 2927, 0, 2765, + 2921, 0, 2757, + 2911, 0, 2747, + 2899, 0, 2733, + 2881, 984, 2713, + 2857, 1386, 2685, + 2821, 1650, 2645, + 2769, 1860, 2587, + 2689, 2043, 2493, + 2555, 2209, 2325, + 2273, 2367, 1919, + 0, 2515, 0, + 0, 2661, 0, + 0, 2801, 0, + 0, 2941, 0, + 0, 3077, 0, + 0, 3213, 0, + 0, 3349, 0, + 0, 3483, 0, + 0, 3617, 0, + 0, 3749, 0, + 0, 3883, 0, + 0, 4015, 0, + 3077, 0, 2911, + 3075, 0, 2909, + 3075, 0, 2909, + 3075, 0, 2909, + 3073, 0, 2907, + 3073, 0, 2907, + 3071, 0, 2905, + 3069, 0, 2903, + 3067, 0, 2899, + 3063, 0, 2895, + 3057, 0, 2889, + 3051, 0, 2881, + 3041, 0, 2871, + 3029, 0, 2857, + 3011, 1056, 2837, + 2987, 1495, 2809, + 2951, 1769, 2767, + 2899, 1984, 2707, + 2819, 2169, 2611, + 2683, 2339, 2439, + 2395, 2495, 2001, + 0, 2645, 0, + 0, 2791, 0, + 0, 2933, 0, + 0, 3071, 0, + 0, 3209, 0, + 0, 3345, 0, + 0, 3481, 0, + 0, 3615, 0, + 0, 3747, 0, + 0, 3881, 0, + 0, 4015, 0, + 3207, 0, 3037, + 3207, 0, 3037, + 3207, 0, 3037, + 3207, 0, 3035, + 3205, 0, 3035, + 3205, 0, 3035, + 3203, 0, 3033, + 3201, 0, 3031, + 3199, 0, 3029, + 3197, 0, 3025, + 3193, 0, 3021, + 3189, 0, 3015, + 3181, 0, 3007, + 3171, 0, 2997, + 3159, 0, 2983, + 3141, 1138, 2963, + 3117, 1608, 2933, + 3081, 1891, 2893, + 3029, 2111, 2831, + 2947, 2297, 2733, + 2811, 2467, 2555, + 2521, 2625, 2091, + 0, 2777, 0, + 0, 2923, 0, + 0, 3065, 0, + 0, 3203, 0, + 0, 3341, 0, + 0, 3477, 0, + 0, 3611, 0, + 0, 3747, 0, + 0, 3879, 0, + 0, 4013, 0, + 3339, 0, 3165, + 3339, 0, 3165, + 3337, 0, 3165, + 3337, 0, 3165, + 3337, 0, 3163, + 3337, 0, 3163, + 3335, 0, 3163, + 3335, 0, 3161, + 3333, 0, 3159, + 3331, 0, 3157, + 3327, 0, 3153, + 3325, 0, 3149, + 3319, 0, 3143, + 3313, 0, 3135, + 3303, 0, 3125, + 3289, 0, 3111, + 3273, 1228, 3089, + 3247, 1726, 3061, + 3211, 2015, 3019, + 3159, 2237, 2957, + 3077, 2427, 2857, + 2941, 2597, 2675, + 2649, 2757, 2189, + 0, 2907, 0, + 0, 3053, 0, + 0, 3195, 0, + 0, 3335, 0, + 0, 3473, 0, + 0, 3609, 0, + 0, 3743, 0, + 0, 3879, 0, + 0, 4013, 0, + 3469, 0, 3295, + 3469, 0, 3295, + 3469, 0, 3295, + 3469, 0, 3293, + 3469, 0, 3293, + 3469, 0, 3293, + 3467, 0, 3293, + 3467, 0, 3291, + 3465, 0, 3289, + 3465, 0, 3289, + 3461, 0, 3285, + 3459, 0, 3283, + 3455, 0, 3279, + 3451, 0, 3273, + 3443, 0, 3265, + 3435, 0, 3253, + 3421, 0, 3239, + 3403, 1326, 3219, + 3379, 1847, 3189, + 3343, 2141, 3147, + 3291, 2365, 3083, + 3209, 2557, 2983, + 3071, 2727, 2797, + 2777, 2887, 2295, + 0, 3039, 0, + 0, 3185, 0, + 0, 3327, 0, + 0, 3467, 0, + 0, 3605, 0, + 0, 3741, 0, + 0, 3875, 0, + 0, 4011, 0, + 3601, 0, 3425, + 3601, 0, 3425, + 3601, 0, 3425, + 3601, 0, 3423, + 3601, 0, 3423, + 3601, 0, 3423, + 3599, 0, 3423, + 3599, 0, 3421, + 3599, 0, 3421, + 3597, 0, 3419, + 3595, 0, 3417, + 3593, 0, 3415, + 3591, 0, 3413, + 3587, 0, 3407, + 3581, 0, 3403, + 3575, 0, 3395, + 3565, 0, 3383, + 3553, 0, 3369, + 3535, 1431, 3347, + 3509, 1971, 3319, + 3473, 2269, 3275, + 3421, 2495, 3213, + 3339, 2687, 3109, + 3201, 2859, 2923, + 2905, 3019, 2405, + 0, 3171, 0, + 0, 3317, 0, + 0, 3459, 0, + 0, 3599, 0, + 0, 3737, 0, + 0, 3873, 0, + 0, 4007, 0, + 3733, 0, 3555, + 3733, 0, 3555, + 3733, 0, 3555, + 3733, 0, 3555, + 3733, 0, 3555, + 3733, 0, 3555, + 3731, 0, 3553, + 3731, 0, 3553, + 3731, 0, 3553, + 3729, 0, 3551, + 3729, 0, 3551, + 3727, 0, 3549, + 3725, 0, 3545, + 3723, 0, 3543, + 3719, 0, 3539, + 3713, 0, 3533, + 3707, 0, 3525, + 3697, 0, 3513, + 3685, 0, 3499, + 3667, 1542, 3477, + 3641, 2097, 3449, + 3605, 2399, 3405, + 3553, 2625, 3341, + 3471, 2817, 3239, + 3331, 2991, 3049, + 3035, 3151, 2521, + 0, 3303, 0, + 0, 3449, 0, + 0, 3591, 0, + 0, 3731, 0, + 0, 3869, 0, + 0, 4005, 0, + 3865, 0, 3685, + 3865, 0, 3685, + 3865, 0, 3685, + 3865, 0, 3685, + 3865, 0, 3685, + 3865, 0, 3685, + 3865, 0, 3685, + 3863, 0, 3685, + 3863, 0, 3683, + 3863, 0, 3683, + 3861, 0, 3683, + 3861, 0, 3681, + 3859, 0, 3679, + 3857, 0, 3677, + 3855, 0, 3673, + 3851, 0, 3669, + 3845, 0, 3663, + 3839, 0, 3655, + 3829, 0, 3645, + 3815, 0, 3629, + 3797, 1658, 3609, + 3773, 2223, 3579, + 3737, 2527, 3535, + 3685, 2757, 3471, + 3603, 2949, 3369, + 3463, 3121, 3177, + 3165, 3281, 2639, + 0, 3433, 0, + 0, 3581, 0, + 0, 3723, 0, + 0, 3863, 0, + 0, 4001, 0, + 3997, 0, 3817, + 3997, 0, 3817, + 3997, 0, 3817, + 3997, 0, 3817, + 3997, 0, 3817, + 3997, 0, 3817, + 3997, 0, 3817, + 3995, 0, 3817, + 3995, 0, 3815, + 3995, 0, 3815, + 3995, 0, 3815, + 3993, 0, 3813, + 3993, 0, 3811, + 3991, 0, 3811, + 3989, 0, 3807, + 3985, 0, 3805, + 3983, 0, 3801, + 3977, 0, 3795, + 3971, 0, 3787, + 3961, 0, 3775, + 3947, 0, 3761, + 3929, 1777, 3739, + 3905, 2353, 3709, + 3869, 2659, 3667, + 3815, 2887, 3603, + 3733, 3081, 3499, + 3595, 3253, 3307, + 3297, 3413, 2761, + 0, 3565, 0, + 0, 3713, 0, + 0, 3855, 0, + 0, 3995, 0, + 4095, 0, 3949, + 4095, 0, 3949, + 4095, 0, 3949, + 4095, 0, 3949, + 4095, 0, 3949, + 4095, 0, 3949, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3943, + 4095, 0, 3941, + 4095, 0, 3939, + 4095, 0, 3935, + 4095, 0, 3931, + 4095, 0, 3925, + 4095, 0, 3917, + 4093, 0, 3907, + 4079, 0, 3891, + 4061, 1899, 3871, + 4037, 2481, 3841, + 4001, 2789, 3797, + 3947, 3019, 3733, + 3865, 3211, 3629, + 3727, 3385, 3437, + 3429, 3545, 2887, + 0, 3697, 0, + 0, 3845, 0, + 0, 3987, 0, + 4095, 0, 4081, + 4095, 0, 4081, + 4095, 0, 4081, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4075, + 4095, 0, 4073, + 4095, 0, 4071, + 4095, 0, 4067, + 4095, 0, 4063, + 4095, 0, 4057, + 4095, 0, 4049, + 4095, 0, 4039, + 4095, 0, 4023, + 4095, 2024, 4001, + 4095, 2611, 3973, + 4095, 2919, 3929, + 4079, 3149, 3865, + 3997, 3343, 3759, + 3857, 3517, 3567, + 3559, 3677, 3013, + 0, 3829, 0, + 0, 3977, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2151, 4095, + 4095, 2743, 4095, + 4095, 3051, 4061, + 4095, 3281, 3995, + 4095, 3475, 3891, + 3989, 3649, 3699, + 3691, 3809, 3141, + 0, 3961, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2277, 4095, + 4095, 2873, 4095, + 4095, 3183, 4095, + 4095, 3413, 4095, + 4095, 3607, 4023, + 4095, 3781, 3829, + 3823, 3941, 3269, + 1256, 844, 1656, + 1236, 863, 1649, + 1208, 888, 1641, + 1167, 920, 1629, + 1106, 959, 1613, + 1010, 1006, 1590, + 837, 1063, 1558, + 399, 1129, 1511, + 0, 1204, 1440, + 0, 1289, 1323, + 0, 1382, 1096, + 0, 1483, 185, + 0, 1590, 0, + 0, 1702, 0, + 0, 1819, 0, + 0, 1940, 0, + 0, 2063, 0, + 0, 2189, 0, + 0, 2315, 0, + 0, 2443, 0, + 0, 2573, 0, + 0, 2703, 0, + 0, 2833, 0, + 0, 2963, 0, + 0, 3095, 0, + 0, 3227, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1280, 840, 1662, + 1261, 860, 1656, + 1234, 886, 1648, + 1196, 917, 1636, + 1139, 957, 1620, + 1050, 1004, 1598, + 896, 1061, 1566, + 539, 1127, 1520, + 0, 1203, 1451, + 0, 1288, 1337, + 0, 1381, 1119, + 0, 1482, 333, + 0, 1589, 0, + 0, 1702, 0, + 0, 1819, 0, + 0, 1939, 0, + 0, 2063, 0, + 0, 2187, 0, + 0, 2315, 0, + 0, 2443, 0, + 0, 2573, 0, + 0, 2703, 0, + 0, 2833, 0, + 0, 2963, 0, + 0, 3095, 0, + 0, 3227, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1310, 836, 1671, + 1293, 856, 1665, + 1268, 882, 1657, + 1233, 914, 1646, + 1180, 953, 1630, + 1100, 1001, 1608, + 964, 1058, 1578, + 676, 1125, 1533, + 0, 1201, 1465, + 0, 1286, 1355, + 0, 1380, 1148, + 0, 1481, 478, + 0, 1589, 0, + 0, 1701, 0, + 0, 1818, 0, + 0, 1939, 0, + 0, 2063, 0, + 0, 2187, 0, + 0, 2315, 0, + 0, 2443, 0, + 0, 2573, 0, + 0, 2703, 0, + 0, 2833, 0, + 0, 2963, 0, + 0, 3095, 0, + 0, 3227, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1348, 831, 1683, + 1332, 851, 1677, + 1309, 877, 1669, + 1277, 909, 1658, + 1230, 949, 1643, + 1159, 997, 1622, + 1041, 1055, 1592, + 813, 1122, 1549, + 0, 1199, 1483, + 0, 1284, 1378, + 0, 1378, 1184, + 0, 1480, 618, + 0, 1588, 0, + 0, 1701, 0, + 0, 1818, 0, + 0, 1938, 0, + 0, 2061, 0, + 0, 2187, 0, + 0, 2315, 0, + 0, 2443, 0, + 0, 2573, 0, + 0, 2703, 0, + 0, 2833, 0, + 0, 2963, 0, + 0, 3095, 0, + 0, 3227, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1394, 823, 1698, + 1380, 844, 1693, + 1359, 870, 1685, + 1331, 903, 1674, + 1289, 943, 1660, + 1227, 992, 1639, + 1128, 1050, 1611, + 948, 1118, 1569, + 474, 1195, 1507, + 0, 1282, 1408, + 0, 1376, 1229, + 0, 1478, 757, + 0, 1586, 0, + 0, 1699, 0, + 0, 1817, 0, + 0, 1938, 0, + 0, 2061, 0, + 0, 2187, 0, + 0, 2315, 0, + 0, 2443, 0, + 0, 2571, 0, + 0, 2701, 0, + 0, 2833, 0, + 0, 2963, 0, + 0, 3095, 0, + 0, 3227, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1449, 812, 1718, + 1437, 834, 1713, + 1419, 860, 1705, + 1393, 894, 1695, + 1358, 935, 1681, + 1305, 985, 1662, + 1222, 1044, 1634, + 1082, 1112, 1595, + 784, 1191, 1537, + 0, 1278, 1445, + 0, 1373, 1282, + 0, 1476, 894, + 0, 1584, 0, + 0, 1698, 0, + 0, 1816, 0, + 0, 1937, 0, + 0, 2061, 0, + 0, 2187, 0, + 0, 2313, 0, + 0, 2443, 0, + 0, 2571, 0, + 0, 2701, 0, + 0, 2833, 0, + 0, 2963, 0, + 0, 3095, 0, + 0, 3227, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1514, 798, 1743, + 1503, 820, 1738, + 1487, 847, 1731, + 1466, 882, 1721, + 1435, 924, 1708, + 1391, 975, 1690, + 1324, 1035, 1664, + 1216, 1105, 1628, + 1014, 1184, 1574, + 385, 1273, 1489, + 0, 1369, 1345, + 0, 1472, 1029, + 0, 1582, 0, + 0, 1696, 0, + 0, 1814, 0, + 0, 1936, 0, + 0, 2059, 0, + 0, 2185, 0, + 0, 2313, 0, + 0, 2441, 0, + 0, 2571, 0, + 0, 2701, 0, + 0, 2833, 0, + 0, 2963, 0, + 0, 3095, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1588, 778, 1775, + 1579, 801, 1770, + 1566, 829, 1763, + 1548, 865, 1754, + 1522, 909, 1742, + 1486, 962, 1725, + 1433, 1023, 1702, + 1350, 1095, 1668, + 1208, 1176, 1619, + 903, 1266, 1543, + 0, 1363, 1417, + 0, 1468, 1164, + 0, 1578, 0, + 0, 1693, 0, + 0, 1812, 0, + 0, 1934, 0, + 0, 2059, 0, + 0, 2185, 0, + 0, 2313, 0, + 0, 2441, 0, + 0, 2571, 0, + 0, 2701, 0, + 0, 2831, 0, + 0, 2963, 0, + 0, 3095, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1672, 750, 1814, + 1664, 774, 1809, + 1653, 804, 1803, + 1638, 842, 1795, + 1617, 888, 1784, + 1588, 943, 1768, + 1546, 1007, 1747, + 1483, 1081, 1717, + 1382, 1164, 1673, + 1197, 1256, 1606, + 693, 1356, 1499, + 0, 1462, 1298, + 0, 1573, 683, + 0, 1689, 0, + 0, 1809, 0, + 0, 1932, 0, + 0, 2057, 0, + 0, 2183, 0, + 0, 2311, 0, + 0, 2441, 0, + 0, 2571, 0, + 0, 2701, 0, + 0, 2831, 0, + 0, 2963, 0, + 0, 3095, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1764, 709, 1861, + 1757, 735, 1857, + 1748, 768, 1852, + 1736, 809, 1844, + 1720, 858, 1834, + 1697, 917, 1821, + 1664, 985, 1801, + 1616, 1062, 1775, + 1542, 1149, 1736, + 1421, 1243, 1679, + 1181, 1345, 1589, + 0, 1454, 1432, + 0, 1567, 1066, + 0, 1685, 0, + 0, 1805, 0, + 0, 1929, 0, + 0, 2055, 0, + 0, 2181, 0, + 0, 2311, 0, + 0, 2439, 0, + 0, 2569, 0, + 0, 2701, 0, + 0, 2831, 0, + 0, 2963, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1863, 648, 1918, + 1858, 678, 1914, + 1851, 715, 1909, + 1841, 761, 1903, + 1828, 815, 1894, + 1810, 879, 1882, + 1785, 953, 1865, + 1748, 1035, 1842, + 1695, 1126, 1809, + 1611, 1225, 1761, + 1469, 1331, 1687, + 1160, 1442, 1565, + 0, 1558, 1323, + 0, 1678, 55, + 0, 1800, 0, + 0, 1925, 0, + 0, 2051, 0, + 0, 2179, 0, + 0, 2309, 0, + 0, 2439, 0, + 0, 2569, 0, + 0, 2699, 0, + 0, 2831, 0, + 0, 2963, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1969, 552, 1984, + 1965, 588, 1981, + 1960, 633, 1976, + 1952, 687, 1971, + 1942, 751, 1963, + 1928, 824, 1953, + 1908, 906, 1939, + 1881, 997, 1919, + 1841, 1095, 1891, + 1783, 1200, 1852, + 1690, 1311, 1792, + 1526, 1427, 1698, + 1129, 1546, 1531, + 0, 1669, 1120, + 0, 1793, 0, + 0, 1920, 0, + 0, 2047, 0, + 0, 2177, 0, + 0, 2307, 0, + 0, 2437, 0, + 0, 2567, 0, + 0, 2699, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2081, 379, 2059, + 2077, 431, 2057, + 2073, 494, 2053, + 2067, 565, 2049, + 2059, 647, 2042, + 2049, 737, 2033, + 2034, 834, 2022, + 2013, 939, 2005, + 1984, 1049, 1982, + 1942, 1164, 1950, + 1879, 1283, 1903, + 1777, 1405, 1831, + 1592, 1530, 1712, + 1085, 1656, 1480, + 0, 1784, 483, + 0, 1913, 0, + 0, 2042, 0, + 0, 2173, 0, + 0, 2303, 0, + 0, 2435, 0, + 0, 2565, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2197, 0, 2143, + 2195, 67, 2141, + 2191, 195, 2139, + 2187, 325, 2135, + 2181, 455, 2129, + 2173, 586, 2123, + 2161, 717, 2113, + 2145, 848, 2099, + 2125, 980, 2081, + 2093, 1111, 2055, + 2049, 1243, 2018, + 1982, 1375, 1963, + 1873, 1507, 1878, + 1668, 1639, 1730, + 1018, 1771, 1403, + 0, 1903, 0, + 0, 2035, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2317, 0, 2237, + 2315, 0, 2235, + 2313, 0, 2233, + 2309, 0, 2229, + 2305, 0, 2225, + 2299, 247, 2219, + 2289, 490, 2211, + 2279, 689, 2201, + 2261, 866, 2187, + 2239, 1029, 2167, + 2207, 1183, 2137, + 2161, 1331, 2095, + 2091, 1474, 2033, + 1975, 1615, 1934, + 1753, 1753, 1753, + 910, 1890, 1273, + 0, 2025, 0, + 0, 2159, 0, + 0, 2293, 0, + 0, 2427, 0, + 0, 2561, 0, + 0, 2693, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2439, 0, 2337, + 2439, 0, 2337, + 2437, 0, 2335, + 2433, 0, 2331, + 2431, 0, 2329, + 2425, 0, 2323, + 2419, 0, 2317, + 2411, 317, 2309, + 2399, 650, 2297, + 2381, 890, 2281, + 2359, 1088, 2259, + 2325, 1264, 2229, + 2279, 1427, 2183, + 2205, 1580, 2113, + 2085, 1728, 1999, + 1846, 1871, 1782, + 707, 2011, 1008, + 0, 2149, 0, + 0, 2287, 0, + 0, 2421, 0, + 0, 2557, 0, + 0, 2691, 0, + 0, 2823, 0, + 0, 2957, 0, + 0, 3089, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2565, 0, 2445, + 2563, 0, 2443, + 2563, 0, 2443, + 2561, 0, 2441, + 2557, 0, 2437, + 2553, 0, 2433, + 2549, 0, 2429, + 2543, 0, 2423, + 2533, 0, 2413, + 2521, 591, 2401, + 2505, 919, 2385, + 2481, 1156, 2361, + 2447, 1354, 2327, + 2399, 1530, 2277, + 2323, 1692, 2201, + 2199, 1845, 2075, + 1947, 1993, 1818, + 74, 2135, 0, + 0, 2275, 0, + 0, 2415, 0, + 0, 2551, 0, + 0, 2687, 0, + 0, 2821, 0, + 0, 2955, 0, + 0, 3087, 0, + 0, 3221, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3885, 0, + 0, 4017, 0, + 2691, 0, 2557, + 2691, 0, 2557, + 2689, 0, 2555, + 2687, 0, 2553, + 2685, 0, 2551, + 2683, 0, 2549, + 2679, 0, 2545, + 2675, 0, 2539, + 2669, 0, 2533, + 2659, 0, 2523, + 2647, 498, 2511, + 2629, 955, 2493, + 2605, 1234, 2467, + 2571, 1452, 2431, + 2521, 1639, 2379, + 2445, 1808, 2297, + 2315, 1966, 2159, + 2055, 2117, 1863, + 0, 2261, 0, + 0, 2403, 0, + 0, 2543, 0, + 0, 2681, 0, + 0, 2817, 0, + 0, 2951, 0, + 0, 3085, 0, + 0, 3219, 0, + 0, 3353, 0, + 0, 3485, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4017, 0, + 2819, 0, 2673, + 2819, 0, 2673, + 2817, 0, 2673, + 2817, 0, 2671, + 2815, 0, 2669, + 2813, 0, 2667, + 2811, 0, 2665, + 2807, 0, 2661, + 2801, 0, 2655, + 2795, 0, 2649, + 2787, 0, 2639, + 2773, 333, 2625, + 2757, 1000, 2607, + 2731, 1321, 2581, + 2697, 1556, 2543, + 2647, 1753, 2487, + 2569, 1928, 2401, + 2437, 2089, 2251, + 2167, 2243, 1916, + 0, 2389, 0, + 0, 2533, 0, + 0, 2673, 0, + 0, 2811, 0, + 0, 2947, 0, + 0, 3083, 0, + 0, 3217, 0, + 0, 3351, 0, + 0, 3485, 0, + 0, 3617, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 2949, 0, 2795, + 2947, 0, 2793, + 2947, 0, 2793, + 2947, 0, 2793, + 2945, 0, 2791, + 2943, 0, 2789, + 2941, 0, 2787, + 2939, 0, 2783, + 2935, 0, 2779, + 2931, 0, 2775, + 2923, 0, 2767, + 2915, 0, 2757, + 2901, 0, 2743, + 2885, 1053, 2725, + 2859, 1416, 2697, + 2825, 1667, 2659, + 2773, 1871, 2601, + 2695, 2051, 2511, + 2561, 2215, 2351, + 2285, 2369, 1979, + 0, 2519, 0, + 0, 2663, 0, + 0, 2803, 0, + 0, 2941, 0, + 0, 3079, 0, + 0, 3213, 0, + 0, 3349, 0, + 0, 3483, 0, + 0, 3617, 0, + 0, 3749, 0, + 0, 3883, 0, + 0, 4015, 0, + 3079, 0, 2917, + 3077, 0, 2917, + 3077, 0, 2917, + 3077, 0, 2915, + 3075, 0, 2915, + 3075, 0, 2913, + 3073, 0, 2911, + 3071, 0, 2909, + 3069, 0, 2907, + 3065, 0, 2903, + 3059, 0, 2897, + 3053, 0, 2889, + 3043, 0, 2879, + 3031, 0, 2865, + 3013, 1116, 2845, + 2989, 1518, 2817, + 2953, 1782, 2777, + 2901, 1992, 2719, + 2821, 2175, 2625, + 2687, 2341, 2459, + 2405, 2499, 2051, + 0, 2647, 0, + 0, 2793, 0, + 0, 2933, 0, + 0, 3073, 0, + 0, 3209, 0, + 0, 3345, 0, + 0, 3481, 0, + 0, 3615, 0, + 0, 3749, 0, + 0, 3881, 0, + 0, 4015, 0, + 3209, 0, 3043, + 3209, 0, 3043, + 3209, 0, 3041, + 3207, 0, 3041, + 3207, 0, 3041, + 3207, 0, 3039, + 3205, 0, 3039, + 3203, 0, 3037, + 3201, 0, 3035, + 3199, 0, 3031, + 3195, 0, 3027, + 3189, 0, 3021, + 3183, 0, 3013, + 3173, 0, 3003, + 3161, 0, 2989, + 3143, 1188, 2969, + 3119, 1627, 2941, + 3083, 1901, 2901, + 3031, 2117, 2839, + 2951, 2301, 2743, + 2815, 2471, 2571, + 2527, 2627, 2133, + 0, 2777, 0, + 0, 2923, 0, + 0, 3065, 0, + 0, 3203, 0, + 0, 3341, 0, + 0, 3477, 0, + 0, 3613, 0, + 0, 3747, 0, + 0, 3881, 0, + 0, 4013, 0, + 3339, 0, 3169, + 3339, 0, 3169, + 3339, 0, 3169, + 3339, 0, 3169, + 3339, 0, 3169, + 3337, 0, 3167, + 3337, 0, 3167, + 3335, 0, 3165, + 3333, 0, 3163, + 3331, 0, 3161, + 3329, 0, 3157, + 3325, 0, 3153, + 3321, 0, 3147, + 3313, 0, 3141, + 3305, 0, 3129, + 3291, 0, 3115, + 3273, 1270, 3095, + 3249, 1740, 3067, + 3213, 2023, 3025, + 3161, 2243, 2963, + 3079, 2429, 2865, + 2943, 2599, 2687, + 2653, 2757, 2223, + 0, 2909, 0, + 0, 3055, 0, + 0, 3197, 0, + 0, 3335, 0, + 0, 3473, 0, + 0, 3609, 0, + 0, 3745, 0, + 0, 3879, 0, + 0, 4013, 0, + 3471, 0, 3297, + 3471, 0, 3297, + 3471, 0, 3297, + 3469, 0, 3297, + 3469, 0, 3297, + 3469, 0, 3297, + 3469, 0, 3295, + 3467, 0, 3295, + 3467, 0, 3293, + 3465, 0, 3291, + 3463, 0, 3289, + 3461, 0, 3285, + 3457, 0, 3281, + 3451, 0, 3275, + 3445, 0, 3267, + 3435, 0, 3257, + 3423, 0, 3243, + 3405, 1360, 3221, + 3379, 1858, 3193, + 3343, 2147, 3151, + 3291, 2369, 3089, + 3211, 2559, 2989, + 3073, 2729, 2807, + 2781, 2889, 2321, + 0, 3039, 0, + 0, 3185, 0, + 0, 3327, 0, + 0, 3467, 0, + 0, 3605, 0, + 0, 3741, 0, + 0, 3877, 0, + 0, 4011, 0, + 3601, 0, 3427, + 3601, 0, 3427, + 3601, 0, 3427, + 3601, 0, 3427, + 3601, 0, 3427, + 3601, 0, 3425, + 3601, 0, 3425, + 3599, 0, 3425, + 3599, 0, 3423, + 3597, 0, 3423, + 3597, 0, 3421, + 3595, 0, 3417, + 3591, 0, 3415, + 3587, 0, 3411, + 3583, 0, 3405, + 3575, 0, 3397, + 3567, 0, 3385, + 3553, 0, 3371, + 3535, 1458, 3351, + 3511, 1979, 3321, + 3475, 2273, 3279, + 3423, 2499, 3215, + 3341, 2689, 3115, + 3203, 2861, 2929, + 2909, 3019, 2427, + 0, 3171, 0, + 0, 3317, 0, + 0, 3459, 0, + 0, 3599, 0, + 0, 3737, 0, + 0, 3873, 0, + 0, 4009, 0, + 3733, 0, 3557, + 3733, 0, 3557, + 3733, 0, 3557, + 3733, 0, 3557, + 3733, 0, 3557, + 3733, 0, 3555, + 3733, 0, 3555, + 3731, 0, 3555, + 3731, 0, 3555, + 3731, 0, 3553, + 3729, 0, 3551, + 3727, 0, 3551, + 3725, 0, 3547, + 3723, 0, 3545, + 3719, 0, 3541, + 3713, 0, 3535, + 3707, 0, 3527, + 3697, 0, 3515, + 3685, 0, 3501, + 3667, 1564, 3479, + 3641, 2103, 3451, + 3607, 2401, 3409, + 3553, 2627, 3345, + 3471, 2819, 3243, + 3333, 2991, 3055, + 3037, 3151, 2537, + 0, 3303, 0, + 0, 3449, 0, + 0, 3591, 0, + 0, 3731, 0, + 0, 3869, 0, + 0, 4005, 0, + 3865, 0, 3687, + 3865, 0, 3687, + 3865, 0, 3687, + 3865, 0, 3687, + 3865, 0, 3687, + 3865, 0, 3687, + 3865, 0, 3687, + 3865, 0, 3685, + 3863, 0, 3685, + 3863, 0, 3685, + 3863, 0, 3683, + 3861, 0, 3683, + 3859, 0, 3681, + 3857, 0, 3677, + 3855, 0, 3675, + 3851, 0, 3671, + 3845, 0, 3665, + 3839, 0, 3657, + 3829, 0, 3645, + 3817, 0, 3631, + 3799, 1674, 3609, + 3773, 2229, 3581, + 3737, 2531, 3537, + 3685, 2757, 3473, + 3603, 2949, 3371, + 3463, 3123, 3181, + 3167, 3283, 2653, + 0, 3435, 0, + 0, 3581, 0, + 0, 3723, 0, + 0, 3863, 0, + 0, 4001, 0, + 3997, 0, 3819, + 3997, 0, 3819, + 3997, 0, 3817, + 3997, 0, 3817, + 3997, 0, 3817, + 3997, 0, 3817, + 3997, 0, 3817, + 3997, 0, 3817, + 3995, 0, 3817, + 3995, 0, 3817, + 3995, 0, 3815, + 3993, 0, 3815, + 3993, 0, 3813, + 3991, 0, 3811, + 3989, 0, 3809, + 3987, 0, 3805, + 3983, 0, 3801, + 3977, 0, 3795, + 3971, 0, 3787, + 3961, 0, 3777, + 3949, 0, 3761, + 3931, 1790, 3741, + 3905, 2355, 3711, + 3869, 2661, 3669, + 3817, 2889, 3603, + 3735, 3081, 3501, + 3595, 3253, 3311, + 3299, 3413, 2771, + 0, 3567, 0, + 0, 3713, 0, + 0, 3855, 0, + 0, 3995, 0, + 4095, 0, 3949, + 4095, 0, 3949, + 4095, 0, 3949, + 4095, 0, 3949, + 4095, 0, 3949, + 4095, 0, 3949, + 4095, 0, 3949, + 4095, 0, 3949, + 4095, 0, 3949, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3945, + 4095, 0, 3945, + 4095, 0, 3943, + 4095, 0, 3939, + 4095, 0, 3937, + 4095, 0, 3933, + 4095, 0, 3927, + 4095, 0, 3919, + 4093, 0, 3907, + 4079, 0, 3893, + 4061, 1909, 3871, + 4037, 2485, 3841, + 4001, 2791, 3799, + 3949, 3019, 3735, + 3867, 3213, 3631, + 3727, 3385, 3439, + 3429, 3545, 2893, + 0, 3697, 0, + 0, 3845, 0, + 0, 3987, 0, + 4095, 0, 4081, + 4095, 0, 4081, + 4095, 0, 4081, + 4095, 0, 4081, + 4095, 0, 4081, + 4095, 0, 4081, + 4095, 0, 4081, + 4095, 0, 4081, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4075, + 4095, 0, 4073, + 4095, 0, 4071, + 4095, 0, 4069, + 4095, 0, 4063, + 4095, 0, 4057, + 4095, 0, 4049, + 4095, 0, 4039, + 4095, 0, 4023, + 4095, 2031, 4003, + 4095, 2613, 3973, + 4095, 2921, 3929, + 4079, 3151, 3865, + 3997, 3343, 3761, + 3859, 3517, 3569, + 3561, 3677, 3019, + 0, 3829, 0, + 0, 3977, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2155, 4095, + 4095, 2743, 4095, + 4095, 3053, 4061, + 4095, 3283, 3997, + 4095, 3475, 3893, + 3989, 3649, 3699, + 3691, 3809, 3145, + 0, 3961, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2283, 4095, + 4095, 2875, 4095, + 4095, 3183, 4095, + 4095, 3413, 4095, + 4095, 3607, 4023, + 4095, 3781, 3831, + 3823, 3941, 3273, + 1384, 963, 1787, + 1369, 978, 1782, + 1348, 998, 1776, + 1319, 1023, 1767, + 1276, 1054, 1755, + 1212, 1093, 1739, + 1109, 1140, 1716, + 920, 1196, 1684, + 388, 1262, 1636, + 0, 1338, 1564, + 0, 1422, 1444, + 0, 1515, 1210, + 0, 1616, 161, + 0, 1723, 0, + 0, 1835, 0, + 0, 1952, 0, + 0, 2071, 0, + 0, 2195, 0, + 0, 2321, 0, + 0, 2447, 0, + 0, 2575, 0, + 0, 2705, 0, + 0, 2835, 0, + 0, 2965, 0, + 0, 3095, 0, + 0, 3227, 0, + 0, 3359, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1402, 960, 1792, + 1388, 976, 1788, + 1368, 995, 1781, + 1340, 1020, 1773, + 1299, 1052, 1761, + 1238, 1091, 1745, + 1142, 1138, 1722, + 969, 1195, 1690, + 531, 1261, 1643, + 0, 1337, 1572, + 0, 1421, 1455, + 0, 1514, 1228, + 0, 1615, 317, + 0, 1722, 0, + 0, 1835, 0, + 0, 1951, 0, + 0, 2071, 0, + 0, 2195, 0, + 0, 2321, 0, + 0, 2447, 0, + 0, 2575, 0, + 0, 2705, 0, + 0, 2835, 0, + 0, 2965, 0, + 0, 3095, 0, + 0, 3227, 0, + 0, 3359, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1426, 957, 1799, + 1412, 973, 1795, + 1393, 992, 1788, + 1367, 1018, 1780, + 1328, 1049, 1768, + 1272, 1088, 1752, + 1183, 1136, 1730, + 1027, 1193, 1699, + 671, 1259, 1653, + 0, 1335, 1583, + 0, 1420, 1469, + 0, 1513, 1251, + 0, 1614, 465, + 0, 1722, 0, + 0, 1834, 0, + 0, 1951, 0, + 0, 2071, 0, + 0, 2195, 0, + 0, 2319, 0, + 0, 2447, 0, + 0, 2575, 0, + 0, 2705, 0, + 0, 2835, 0, + 0, 2965, 0, + 0, 3095, 0, + 0, 3227, 0, + 0, 3359, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1455, 953, 1808, + 1443, 968, 1804, + 1425, 988, 1797, + 1400, 1014, 1789, + 1365, 1046, 1778, + 1313, 1085, 1762, + 1232, 1133, 1740, + 1096, 1190, 1710, + 809, 1257, 1665, + 0, 1333, 1597, + 0, 1419, 1487, + 0, 1512, 1280, + 0, 1613, 610, + 0, 1721, 0, + 0, 1834, 0, + 0, 1951, 0, + 0, 2071, 0, + 0, 2195, 0, + 0, 2319, 0, + 0, 2447, 0, + 0, 2575, 0, + 0, 2705, 0, + 0, 2835, 0, + 0, 2965, 0, + 0, 3095, 0, + 0, 3227, 0, + 0, 3359, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1492, 947, 1820, + 1480, 963, 1815, + 1464, 983, 1809, + 1441, 1009, 1801, + 1409, 1041, 1790, + 1362, 1081, 1775, + 1291, 1129, 1754, + 1173, 1187, 1724, + 945, 1254, 1681, + 8, 1331, 1616, + 0, 1416, 1511, + 0, 1511, 1317, + 0, 1612, 750, + 0, 1720, 0, + 0, 1833, 0, + 0, 1950, 0, + 0, 2071, 0, + 0, 2195, 0, + 0, 2319, 0, + 0, 2447, 0, + 0, 2575, 0, + 0, 2705, 0, + 0, 2835, 0, + 0, 2965, 0, + 0, 3095, 0, + 0, 3227, 0, + 0, 3359, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1537, 939, 1835, + 1526, 955, 1831, + 1512, 976, 1825, + 1491, 1002, 1817, + 1463, 1034, 1806, + 1421, 1075, 1792, + 1359, 1124, 1771, + 1260, 1182, 1743, + 1080, 1250, 1701, + 606, 1327, 1639, + 0, 1414, 1540, + 0, 1508, 1361, + 0, 1610, 889, + 0, 1718, 0, + 0, 1832, 0, + 0, 1949, 0, + 0, 2069, 0, + 0, 2193, 0, + 0, 2319, 0, + 0, 2447, 0, + 0, 2575, 0, + 0, 2705, 0, + 0, 2835, 0, + 0, 2965, 0, + 0, 3095, 0, + 0, 3227, 0, + 0, 3359, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1591, 928, 1854, + 1582, 945, 1850, + 1569, 966, 1845, + 1551, 992, 1837, + 1526, 1026, 1827, + 1490, 1067, 1813, + 1437, 1117, 1794, + 1354, 1176, 1767, + 1215, 1245, 1727, + 916, 1323, 1669, + 0, 1410, 1577, + 0, 1505, 1414, + 0, 1608, 1026, + 0, 1716, 0, + 0, 1830, 0, + 0, 1948, 0, + 0, 2069, 0, + 0, 2193, 0, + 0, 2319, 0, + 0, 2445, 0, + 0, 2575, 0, + 0, 2703, 0, + 0, 2833, 0, + 0, 2965, 0, + 0, 3095, 0, + 0, 3227, 0, + 0, 3359, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1654, 913, 1879, + 1646, 930, 1875, + 1635, 952, 1870, + 1620, 979, 1863, + 1598, 1014, 1854, + 1568, 1056, 1840, + 1523, 1107, 1822, + 1457, 1167, 1796, + 1348, 1237, 1760, + 1146, 1317, 1706, + 517, 1405, 1621, + 0, 1501, 1477, + 0, 1604, 1161, + 0, 1714, 0, + 0, 1828, 0, + 0, 1946, 0, + 0, 2067, 0, + 0, 2191, 0, + 0, 2317, 0, + 0, 2445, 0, + 0, 2575, 0, + 0, 2703, 0, + 0, 2833, 0, + 0, 2965, 0, + 0, 3095, 0, + 0, 3227, 0, + 0, 3359, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1727, 892, 1910, + 1720, 910, 1907, + 1711, 933, 1902, + 1698, 962, 1895, + 1680, 997, 1886, + 1654, 1041, 1874, + 1618, 1093, 1857, + 1565, 1156, 1834, + 1482, 1227, 1800, + 1340, 1308, 1751, + 1035, 1398, 1675, + 0, 1495, 1549, + 0, 1600, 1296, + 0, 1710, 0, + 0, 1825, 0, + 0, 1944, 0, + 0, 2067, 0, + 0, 2191, 0, + 0, 2317, 0, + 0, 2445, 0, + 0, 2573, 0, + 0, 2703, 0, + 0, 2833, 0, + 0, 2965, 0, + 0, 3095, 0, + 0, 3227, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1810, 863, 1949, + 1804, 882, 1946, + 1796, 906, 1941, + 1785, 936, 1935, + 1770, 974, 1927, + 1750, 1020, 1916, + 1720, 1075, 1901, + 1678, 1139, 1879, + 1615, 1213, 1849, + 1514, 1297, 1805, + 1329, 1388, 1738, + 825, 1488, 1631, + 0, 1594, 1430, + 0, 1705, 815, + 0, 1822, 0, + 0, 1941, 0, + 0, 2065, 0, + 0, 2189, 0, + 0, 2315, 0, + 0, 2443, 0, + 0, 2573, 0, + 0, 2703, 0, + 0, 2833, 0, + 0, 2963, 0, + 0, 3095, 0, + 0, 3227, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1900, 820, 1996, + 1896, 841, 1993, + 1889, 868, 1989, + 1880, 900, 1984, + 1868, 941, 1976, + 1852, 990, 1966, + 1829, 1049, 1953, + 1796, 1117, 1934, + 1748, 1194, 1907, + 1674, 1281, 1868, + 1553, 1375, 1811, + 1314, 1477, 1721, + 121, 1586, 1564, + 0, 1699, 1198, + 0, 1817, 0, + 0, 1938, 0, + 0, 2061, 0, + 0, 2187, 0, + 0, 2315, 0, + 0, 2443, 0, + 0, 2571, 0, + 0, 2701, 0, + 0, 2833, 0, + 0, 2963, 0, + 0, 3095, 0, + 0, 3227, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1999, 757, 2053, + 1995, 780, 2049, + 1990, 810, 2046, + 1983, 848, 2041, + 1973, 893, 2035, + 1960, 947, 2026, + 1942, 1011, 2014, + 1917, 1084, 1998, + 1881, 1167, 1974, + 1827, 1258, 1941, + 1743, 1357, 1893, + 1601, 1463, 1819, + 1292, 1574, 1697, + 0, 1690, 1455, + 0, 1810, 187, + 0, 1932, 0, + 0, 2057, 0, + 0, 2183, 0, + 0, 2311, 0, + 0, 2441, 0, + 0, 2571, 0, + 0, 2701, 0, + 0, 2831, 0, + 0, 2963, 0, + 0, 3095, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2105, 654, 2119, + 2101, 684, 2115, + 2097, 721, 2113, + 2091, 765, 2109, + 2085, 819, 2103, + 2075, 883, 2095, + 2059, 956, 2085, + 2040, 1038, 2071, + 2013, 1128, 2051, + 1974, 1227, 2024, + 1915, 1332, 1984, + 1822, 1443, 1924, + 1658, 1559, 1830, + 1261, 1678, 1663, + 0, 1801, 1252, + 0, 1926, 0, + 0, 2053, 0, + 0, 2179, 0, + 0, 2309, 0, + 0, 2439, 0, + 0, 2569, 0, + 0, 2699, 0, + 0, 2831, 0, + 0, 2963, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2215, 467, 2193, + 2213, 511, 2191, + 2209, 563, 2189, + 2205, 626, 2185, + 2199, 698, 2181, + 2191, 779, 2175, + 2181, 869, 2165, + 2167, 966, 2153, + 2145, 1071, 2137, + 2117, 1181, 2115, + 2075, 1296, 2083, + 2011, 1415, 2035, + 1909, 1538, 1963, + 1724, 1662, 1844, + 1217, 1788, 1612, + 0, 1916, 615, + 0, 2045, 0, + 0, 2175, 0, + 0, 2305, 0, + 0, 2435, 0, + 0, 2567, 0, + 0, 2697, 0, + 0, 2829, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2331, 0, 2277, + 2329, 71, 2277, + 2327, 199, 2273, + 2323, 327, 2271, + 2319, 457, 2267, + 2313, 587, 2261, + 2305, 718, 2255, + 2293, 849, 2245, + 2277, 980, 2231, + 2257, 1112, 2213, + 2225, 1243, 2187, + 2181, 1375, 2151, + 2113, 1507, 2095, + 2005, 1639, 2010, + 1800, 1771, 1862, + 1150, 1903, 1535, + 0, 2035, 0, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2451, 0, 2371, + 2449, 0, 2369, + 2447, 0, 2367, + 2445, 0, 2365, + 2441, 0, 2361, + 2437, 40, 2357, + 2431, 379, 2351, + 2421, 622, 2345, + 2411, 822, 2333, + 2395, 999, 2319, + 2371, 1161, 2299, + 2339, 1315, 2269, + 2293, 1463, 2227, + 2223, 1606, 2165, + 2107, 1747, 2065, + 1885, 1885, 1885, + 1042, 2022, 1405, + 0, 2157, 0, + 0, 2291, 0, + 0, 2425, 0, + 0, 2559, 0, + 0, 2693, 0, + 0, 2825, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2573, 0, 2471, + 2571, 0, 2469, + 2571, 0, 2469, + 2569, 0, 2467, + 2565, 0, 2463, + 2563, 0, 2461, + 2557, 0, 2455, + 2551, 0, 2449, + 2543, 449, 2441, + 2531, 782, 2429, + 2513, 1022, 2413, + 2491, 1220, 2391, + 2459, 1396, 2361, + 2411, 1559, 2315, + 2337, 1712, 2245, + 2217, 1860, 2131, + 1979, 2003, 1914, + 839, 2143, 1140, + 0, 2281, 0, + 0, 2419, 0, + 0, 2553, 0, + 0, 2689, 0, + 0, 2823, 0, + 0, 2955, 0, + 0, 3089, 0, + 0, 3221, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3885, 0, + 0, 4017, 0, + 2697, 0, 2577, + 2697, 0, 2577, + 2695, 0, 2575, + 2695, 0, 2575, + 2693, 0, 2573, + 2689, 0, 2569, + 2687, 0, 2565, + 2681, 0, 2561, + 2675, 0, 2555, + 2665, 12, 2545, + 2653, 723, 2533, + 2637, 1051, 2517, + 2613, 1289, 2493, + 2579, 1486, 2459, + 2531, 1662, 2409, + 2455, 1824, 2333, + 2331, 1977, 2207, + 2079, 2125, 1951, + 206, 2267, 0, + 0, 2409, 0, + 0, 2547, 0, + 0, 2683, 0, + 0, 2819, 0, + 0, 2953, 0, + 0, 3087, 0, + 0, 3221, 0, + 0, 3353, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4017, 0, + 2825, 0, 2689, + 2823, 0, 2689, + 2823, 0, 2689, + 2821, 0, 2687, + 2821, 0, 2685, + 2819, 0, 2683, + 2815, 0, 2681, + 2811, 0, 2677, + 2807, 0, 2671, + 2801, 0, 2665, + 2791, 0, 2655, + 2779, 630, 2643, + 2761, 1087, 2625, + 2737, 1366, 2599, + 2703, 1584, 2563, + 2653, 1771, 2511, + 2577, 1940, 2429, + 2449, 2099, 2291, + 2187, 2249, 1995, + 0, 2395, 0, + 0, 2535, 0, + 0, 2675, 0, + 0, 2813, 0, + 0, 2949, 0, + 0, 3083, 0, + 0, 3217, 0, + 0, 3351, 0, + 0, 3485, 0, + 0, 3617, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 2953, 0, 2807, + 2951, 0, 2807, + 2951, 0, 2805, + 2951, 0, 2805, + 2949, 0, 2803, + 2947, 0, 2801, + 2945, 0, 2799, + 2943, 0, 2797, + 2939, 0, 2793, + 2935, 0, 2787, + 2927, 0, 2781, + 2919, 0, 2771, + 2905, 465, 2757, + 2889, 1132, 2739, + 2865, 1453, 2713, + 2829, 1689, 2675, + 2779, 1885, 2619, + 2701, 2059, 2533, + 2569, 2221, 2383, + 2299, 2375, 2049, + 0, 2521, 0, + 0, 2665, 0, + 0, 2805, 0, + 0, 2943, 0, + 0, 3079, 0, + 0, 3215, 0, + 0, 3349, 0, + 0, 3483, 0, + 0, 3617, 0, + 0, 3749, 0, + 0, 3883, 0, + 0, 4015, 0, + 3081, 0, 2927, + 3081, 0, 2927, + 3081, 0, 2925, + 3079, 0, 2925, + 3079, 0, 2925, + 3077, 0, 2923, + 3075, 0, 2921, + 3073, 0, 2919, + 3071, 0, 2917, + 3067, 0, 2913, + 3063, 0, 2907, + 3055, 0, 2899, + 3047, 0, 2889, + 3033, 66, 2875, + 3017, 1185, 2857, + 2991, 1548, 2829, + 2957, 1799, 2791, + 2905, 2003, 2733, + 2827, 2183, 2643, + 2693, 2347, 2483, + 2417, 2501, 2111, + 0, 2651, 0, + 0, 2795, 0, + 0, 2935, 0, + 0, 3073, 0, + 0, 3211, 0, + 0, 3347, 0, + 0, 3481, 0, + 0, 3615, 0, + 0, 3749, 0, + 0, 3881, 0, + 0, 4015, 0, + 3211, 0, 3049, + 3211, 0, 3049, + 3211, 0, 3049, + 3209, 0, 3049, + 3209, 0, 3047, + 3209, 0, 3047, + 3207, 0, 3045, + 3205, 0, 3043, + 3203, 0, 3041, + 3201, 0, 3039, + 3197, 0, 3035, + 3191, 0, 3029, + 3185, 0, 3021, + 3175, 0, 3011, + 3163, 0, 2997, + 3145, 1248, 2977, + 3121, 1651, 2949, + 3085, 1914, 2909, + 3033, 2125, 2851, + 2955, 2307, 2757, + 2819, 2475, 2591, + 2537, 2631, 2183, + 0, 2779, 0, + 0, 2925, 0, + 0, 3065, 0, + 0, 3205, 0, + 0, 3341, 0, + 0, 3477, 0, + 0, 3613, 0, + 0, 3747, 0, + 0, 3881, 0, + 0, 4013, 0, + 3341, 0, 3175, + 3341, 0, 3175, + 3341, 0, 3175, + 3341, 0, 3173, + 3339, 0, 3173, + 3339, 0, 3173, + 3339, 0, 3171, + 3337, 0, 3171, + 3335, 0, 3169, + 3333, 0, 3167, + 3331, 0, 3163, + 3327, 0, 3159, + 3321, 0, 3153, + 3315, 0, 3145, + 3305, 0, 3135, + 3293, 0, 3121, + 3275, 1320, 3101, + 3251, 1759, 3073, + 3215, 2033, 3033, + 3163, 2249, 2971, + 3083, 2435, 2875, + 2947, 2603, 2703, + 2661, 2759, 2265, + 0, 2911, 0, + 0, 3055, 0, + 0, 3197, 0, + 0, 3337, 0, + 0, 3473, 0, + 0, 3609, 0, + 0, 3745, 0, + 0, 3879, 0, + 0, 4013, 0, + 3471, 0, 3301, + 3471, 0, 3301, + 3471, 0, 3301, + 3471, 0, 3301, + 3471, 0, 3301, + 3471, 0, 3301, + 3469, 0, 3299, + 3469, 0, 3299, + 3467, 0, 3297, + 3467, 0, 3295, + 3463, 0, 3293, + 3461, 0, 3289, + 3457, 0, 3285, + 3453, 0, 3279, + 3445, 0, 3273, + 3437, 0, 3261, + 3423, 0, 3247, + 3405, 1402, 3227, + 3381, 1873, 3199, + 3345, 2155, 3157, + 3293, 2375, 3095, + 3213, 2563, 2997, + 3075, 2731, 2819, + 2785, 2891, 2355, + 0, 3041, 0, + 0, 3187, 0, + 0, 3329, 0, + 0, 3467, 0, + 0, 3605, 0, + 0, 3741, 0, + 0, 3877, 0, + 0, 4011, 0, + 3603, 0, 3429, + 3603, 0, 3429, + 3603, 0, 3429, + 3603, 0, 3429, + 3603, 0, 3429, + 3601, 0, 3429, + 3601, 0, 3429, + 3601, 0, 3427, + 3599, 0, 3427, + 3599, 0, 3425, + 3597, 0, 3423, + 3595, 0, 3421, + 3593, 0, 3417, + 3589, 0, 3413, + 3583, 0, 3407, + 3577, 0, 3399, + 3567, 0, 3389, + 3555, 0, 3375, + 3537, 1492, 3355, + 3511, 1990, 3325, + 3475, 2279, 3283, + 3423, 2501, 3221, + 3343, 2691, 3121, + 3205, 2861, 2939, + 2913, 3021, 2453, + 0, 3171, 0, + 0, 3317, 0, + 0, 3459, 0, + 0, 3599, 0, + 0, 3737, 0, + 0, 3873, 0, + 0, 4009, 0, + 3735, 0, 3559, + 3735, 0, 3559, + 3735, 0, 3559, + 3733, 0, 3559, + 3733, 0, 3559, + 3733, 0, 3559, + 3733, 0, 3557, + 3733, 0, 3557, + 3731, 0, 3557, + 3731, 0, 3555, + 3729, 0, 3555, + 3729, 0, 3553, + 3727, 0, 3551, + 3723, 0, 3547, + 3719, 0, 3543, + 3715, 0, 3537, + 3707, 0, 3529, + 3699, 0, 3517, + 3685, 0, 3503, + 3667, 1591, 3483, + 3643, 2111, 3453, + 3607, 2405, 3411, + 3555, 2631, 3347, + 3473, 2821, 3247, + 3335, 2993, 3063, + 3041, 3151, 2559, + 0, 3303, 0, + 0, 3449, 0, + 0, 3591, 0, + 0, 3731, 0, + 0, 3869, 0, + 0, 4005, 0, + 3865, 0, 3689, + 3865, 0, 3689, + 3865, 0, 3689, + 3865, 0, 3689, + 3865, 0, 3689, + 3865, 0, 3689, + 3865, 0, 3687, + 3865, 0, 3687, + 3865, 0, 3687, + 3863, 0, 3687, + 3863, 0, 3685, + 3861, 0, 3683, + 3859, 0, 3683, + 3857, 0, 3679, + 3855, 0, 3677, + 3851, 0, 3673, + 3847, 0, 3667, + 3839, 0, 3659, + 3829, 0, 3647, + 3817, 0, 3633, + 3799, 1696, 3611, + 3773, 2235, 3583, + 3739, 2533, 3541, + 3685, 2759, 3477, + 3603, 2951, 3375, + 3465, 3123, 3187, + 3169, 3283, 2669, + 0, 3435, 0, + 0, 3581, 0, + 0, 3723, 0, + 0, 3863, 0, + 0, 4001, 0, + 3997, 0, 3819, + 3997, 0, 3819, + 3997, 0, 3819, + 3997, 0, 3819, + 3997, 0, 3819, + 3997, 0, 3819, + 3997, 0, 3819, + 3997, 0, 3819, + 3997, 0, 3817, + 3995, 0, 3817, + 3995, 0, 3817, + 3995, 0, 3815, + 3993, 0, 3815, + 3991, 0, 3813, + 3989, 0, 3811, + 3987, 0, 3807, + 3983, 0, 3803, + 3977, 0, 3797, + 3971, 0, 3789, + 3961, 0, 3777, + 3949, 0, 3763, + 3931, 1806, 3741, + 3905, 2361, 3713, + 3869, 2663, 3669, + 3817, 2889, 3605, + 3735, 3083, 3503, + 3595, 3255, 3315, + 3299, 3415, 2785, + 0, 3567, 0, + 0, 3713, 0, + 0, 3855, 0, + 0, 3995, 0, + 4095, 0, 3951, + 4095, 0, 3951, + 4095, 0, 3951, + 4095, 0, 3951, + 4095, 0, 3949, + 4095, 0, 3949, + 4095, 0, 3949, + 4095, 0, 3949, + 4095, 0, 3949, + 4095, 0, 3949, + 4095, 0, 3949, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3945, + 4095, 0, 3943, + 4095, 0, 3941, + 4095, 0, 3937, + 4095, 0, 3933, + 4095, 0, 3927, + 4095, 0, 3919, + 4093, 0, 3909, + 4081, 0, 3893, + 4063, 1922, 3873, + 4037, 2487, 3843, + 4001, 2793, 3801, + 3949, 3021, 3735, + 3867, 3213, 3633, + 3727, 3385, 3443, + 3431, 3547, 2903, + 0, 3699, 0, + 0, 3845, 0, + 0, 3987, 0, + 4095, 0, 4081, + 4095, 0, 4081, + 4095, 0, 4081, + 4095, 0, 4081, + 4095, 0, 4081, + 4095, 0, 4081, + 4095, 0, 4081, + 4095, 0, 4081, + 4095, 0, 4081, + 4095, 0, 4081, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4077, + 4095, 0, 4077, + 4095, 0, 4075, + 4095, 0, 4073, + 4095, 0, 4069, + 4095, 0, 4065, + 4095, 0, 4059, + 4095, 0, 4051, + 4095, 0, 4039, + 4095, 0, 4025, + 4095, 2041, 4003, + 4095, 2617, 3973, + 4095, 2923, 3931, + 4081, 3151, 3867, + 3999, 3345, 3763, + 3859, 3517, 3571, + 3561, 3677, 3025, + 0, 3831, 0, + 0, 3977, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2163, 4095, + 4095, 2745, 4095, + 4095, 3053, 4063, + 4095, 3283, 3997, + 4095, 3477, 3893, + 3991, 3649, 3701, + 3693, 3809, 3151, + 0, 3961, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2287, 4095, + 4095, 2875, 4095, + 4095, 3185, 4095, + 4095, 3415, 4095, + 4095, 3607, 4025, + 4095, 3781, 3831, + 3823, 3941, 3277, + 1513, 1085, 1919, + 1502, 1096, 1915, + 1486, 1112, 1911, + 1465, 1131, 1904, + 1434, 1156, 1895, + 1390, 1187, 1883, + 1323, 1226, 1867, + 1214, 1273, 1844, + 1011, 1329, 1811, + 373, 1395, 1763, + 0, 1470, 1689, + 0, 1555, 1568, + 0, 1648, 1328, + 0, 1748, 128, + 0, 1855, 0, + 0, 1967, 0, + 0, 2085, 0, + 0, 2205, 0, + 0, 2327, 0, + 0, 2453, 0, + 0, 2579, 0, + 0, 2707, 0, + 0, 2837, 0, + 0, 2967, 0, + 0, 3097, 0, + 0, 3227, 0, + 0, 3359, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1527, 1083, 1923, + 1516, 1095, 1919, + 1501, 1110, 1915, + 1480, 1129, 1908, + 1451, 1154, 1899, + 1408, 1186, 1888, + 1344, 1225, 1871, + 1241, 1272, 1848, + 1052, 1328, 1816, + 520, 1394, 1768, + 0, 1470, 1696, + 0, 1554, 1576, + 0, 1647, 1342, + 0, 1748, 294, + 0, 1855, 0, + 0, 1967, 0, + 0, 2083, 0, + 0, 2205, 0, + 0, 2327, 0, + 0, 2453, 0, + 0, 2579, 0, + 0, 2707, 0, + 0, 2837, 0, + 0, 2967, 0, + 0, 3097, 0, + 0, 3227, 0, + 0, 3359, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1545, 1080, 1928, + 1534, 1092, 1924, + 1520, 1108, 1920, + 1500, 1127, 1913, + 1472, 1152, 1905, + 1431, 1184, 1893, + 1370, 1223, 1877, + 1274, 1270, 1854, + 1101, 1327, 1822, + 663, 1393, 1775, + 0, 1469, 1704, + 0, 1553, 1587, + 0, 1647, 1360, + 0, 1747, 449, + 0, 1854, 0, + 0, 1967, 0, + 0, 2083, 0, + 0, 2203, 0, + 0, 2327, 0, + 0, 2453, 0, + 0, 2579, 0, + 0, 2707, 0, + 0, 2837, 0, + 0, 2967, 0, + 0, 3097, 0, + 0, 3227, 0, + 0, 3359, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1568, 1077, 1935, + 1558, 1089, 1931, + 1544, 1104, 1927, + 1525, 1124, 1920, + 1499, 1150, 1912, + 1460, 1181, 1900, + 1404, 1221, 1884, + 1315, 1268, 1862, + 1160, 1325, 1831, + 803, 1391, 1785, + 0, 1467, 1715, + 0, 1552, 1601, + 0, 1646, 1383, + 0, 1746, 597, + 0, 1854, 0, + 0, 1966, 0, + 0, 2083, 0, + 0, 2203, 0, + 0, 2327, 0, + 0, 2453, 0, + 0, 2579, 0, + 0, 2707, 0, + 0, 2837, 0, + 0, 2967, 0, + 0, 3097, 0, + 0, 3227, 0, + 0, 3359, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1597, 1073, 1944, + 1588, 1085, 1940, + 1575, 1100, 1936, + 1557, 1120, 1930, + 1532, 1146, 1921, + 1497, 1178, 1910, + 1445, 1217, 1894, + 1364, 1265, 1873, + 1228, 1322, 1842, + 941, 1389, 1797, + 0, 1465, 1729, + 0, 1551, 1619, + 0, 1644, 1412, + 0, 1745, 742, + 0, 1853, 0, + 0, 1966, 0, + 0, 2083, 0, + 0, 2203, 0, + 0, 2327, 0, + 0, 2451, 0, + 0, 2579, 0, + 0, 2707, 0, + 0, 2837, 0, + 0, 2967, 0, + 0, 3097, 0, + 0, 3227, 0, + 0, 3359, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1633, 1067, 1955, + 1624, 1079, 1952, + 1613, 1095, 1947, + 1596, 1115, 1942, + 1574, 1141, 1933, + 1541, 1173, 1922, + 1494, 1213, 1907, + 1423, 1261, 1886, + 1305, 1319, 1856, + 1077, 1386, 1813, + 140, 1463, 1748, + 0, 1549, 1643, + 0, 1643, 1449, + 0, 1744, 883, + 0, 1852, 0, + 0, 1965, 0, + 0, 2083, 0, + 0, 2203, 0, + 0, 2327, 0, + 0, 2451, 0, + 0, 2579, 0, + 0, 2707, 0, + 0, 2837, 0, + 0, 2967, 0, + 0, 3097, 0, + 0, 3227, 0, + 0, 3359, 0, + 0, 3491, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1677, 1058, 1970, + 1669, 1071, 1967, + 1659, 1087, 1963, + 1644, 1108, 1957, + 1624, 1134, 1949, + 1595, 1167, 1939, + 1553, 1207, 1924, + 1491, 1256, 1904, + 1392, 1314, 1875, + 1212, 1382, 1833, + 738, 1459, 1771, + 0, 1546, 1672, + 0, 1640, 1493, + 0, 1742, 1021, + 0, 1850, 0, + 0, 1964, 0, + 0, 2081, 0, + 0, 2203, 0, + 0, 2325, 0, + 0, 2451, 0, + 0, 2579, 0, + 0, 2707, 0, + 0, 2837, 0, + 0, 2967, 0, + 0, 3097, 0, + 0, 3227, 0, + 0, 3359, 0, + 0, 3491, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1730, 1047, 1990, + 1723, 1060, 1987, + 1714, 1076, 1982, + 1701, 1098, 1977, + 1683, 1124, 1969, + 1658, 1158, 1959, + 1622, 1199, 1945, + 1569, 1249, 1926, + 1487, 1308, 1899, + 1347, 1377, 1859, + 1048, 1455, 1801, + 0, 1542, 1709, + 0, 1637, 1546, + 0, 1740, 1158, + 0, 1848, 0, + 0, 1962, 0, + 0, 2081, 0, + 0, 2201, 0, + 0, 2325, 0, + 0, 2451, 0, + 0, 2579, 0, + 0, 2707, 0, + 0, 2835, 0, + 0, 2965, 0, + 0, 3097, 0, + 0, 3227, 0, + 0, 3359, 0, + 0, 3491, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1793, 1032, 2014, + 1787, 1045, 2011, + 1778, 1062, 2008, + 1767, 1084, 2002, + 1752, 1111, 1995, + 1730, 1146, 1986, + 1700, 1188, 1972, + 1655, 1239, 1954, + 1589, 1299, 1929, + 1481, 1369, 1892, + 1278, 1449, 1838, + 650, 1537, 1754, + 0, 1633, 1609, + 0, 1736, 1294, + 0, 1846, 0, + 0, 1960, 0, + 0, 2079, 0, + 0, 2201, 0, + 0, 2325, 0, + 0, 2451, 0, + 0, 2577, 0, + 0, 2707, 0, + 0, 2835, 0, + 0, 2965, 0, + 0, 3097, 0, + 0, 3227, 0, + 0, 3359, 0, + 0, 3491, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1865, 1011, 2045, + 1860, 1024, 2043, + 1853, 1042, 2039, + 1843, 1065, 2034, + 1830, 1093, 2028, + 1812, 1129, 2019, + 1787, 1173, 2006, + 1750, 1226, 1989, + 1697, 1288, 1966, + 1614, 1359, 1932, + 1472, 1440, 1883, + 1167, 1530, 1807, + 0, 1628, 1681, + 0, 1732, 1428, + 0, 1842, 0, + 0, 1957, 0, + 0, 2077, 0, + 0, 2199, 0, + 0, 2323, 0, + 0, 2449, 0, + 0, 2577, 0, + 0, 2705, 0, + 0, 2835, 0, + 0, 2965, 0, + 0, 3097, 0, + 0, 3227, 0, + 0, 3359, 0, + 0, 3491, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 1946, 980, 2083, + 1942, 995, 2081, + 1936, 1014, 2077, + 1928, 1038, 2073, + 1917, 1068, 2067, + 1902, 1106, 2059, + 1882, 1152, 2049, + 1853, 1207, 2033, + 1810, 1271, 2011, + 1747, 1345, 1981, + 1646, 1429, 1937, + 1461, 1520, 1870, + 957, 1620, 1763, + 0, 1726, 1562, + 0, 1838, 947, + 0, 1954, 0, + 0, 2073, 0, + 0, 2197, 0, + 0, 2321, 0, + 0, 2447, 0, + 0, 2575, 0, + 0, 2705, 0, + 0, 2835, 0, + 0, 2965, 0, + 0, 3095, 0, + 0, 3227, 0, + 0, 3359, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2036, 936, 2131, + 2033, 953, 2129, + 2028, 973, 2125, + 2021, 1000, 2121, + 2013, 1032, 2115, + 2001, 1073, 2109, + 1984, 1122, 2099, + 1961, 1181, 2085, + 1928, 1249, 2065, + 1880, 1326, 2039, + 1807, 1413, 2000, + 1685, 1508, 1943, + 1446, 1610, 1853, + 253, 1718, 1696, + 0, 1831, 1330, + 0, 1949, 0, + 0, 2069, 0, + 0, 2193, 0, + 0, 2319, 0, + 0, 2447, 0, + 0, 2575, 0, + 0, 2703, 0, + 0, 2833, 0, + 0, 2965, 0, + 0, 3095, 0, + 0, 3227, 0, + 0, 3359, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2135, 870, 2187, + 2131, 889, 2185, + 2127, 913, 2181, + 2123, 942, 2179, + 2115, 980, 2173, + 2105, 1025, 2167, + 2093, 1079, 2159, + 2075, 1143, 2147, + 2049, 1217, 2129, + 2013, 1299, 2107, + 1959, 1391, 2073, + 1876, 1490, 2025, + 1733, 1595, 1951, + 1424, 1707, 1829, + 0, 1822, 1587, + 0, 1942, 319, + 0, 2065, 0, + 0, 2189, 0, + 0, 2317, 0, + 0, 2443, 0, + 0, 2573, 0, + 0, 2703, 0, + 0, 2833, 0, + 0, 2963, 0, + 0, 3095, 0, + 0, 3227, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2239, 763, 2251, + 2237, 786, 2251, + 2233, 816, 2247, + 2229, 853, 2245, + 2223, 898, 2241, + 2217, 952, 2235, + 2207, 1015, 2227, + 2193, 1088, 2217, + 2173, 1170, 2203, + 2145, 1261, 2183, + 2105, 1359, 2155, + 2047, 1464, 2115, + 1954, 1575, 2057, + 1790, 1691, 1962, + 1394, 1811, 1795, + 0, 1933, 1384, + 0, 2057, 0, + 0, 2185, 0, + 0, 2313, 0, + 0, 2441, 0, + 0, 2571, 0, + 0, 2701, 0, + 0, 2831, 0, + 0, 2963, 0, + 0, 3095, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2349, 563, 2327, + 2347, 599, 2325, + 2345, 643, 2323, + 2341, 696, 2321, + 2337, 758, 2317, + 2331, 830, 2313, + 2323, 911, 2307, + 2313, 1001, 2297, + 2299, 1098, 2285, + 2277, 1203, 2269, + 2249, 1313, 2247, + 2207, 1429, 2215, + 2143, 1548, 2167, + 2041, 1670, 2095, + 1856, 1794, 1976, + 1349, 1920, 1745, + 0, 2049, 747, + 0, 2177, 0, + 0, 2307, 0, + 0, 2437, 0, + 0, 2567, 0, + 0, 2699, 0, + 0, 2831, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2465, 0, 2411, + 2463, 77, 2409, + 2461, 203, 2409, + 2459, 331, 2407, + 2455, 460, 2403, + 2451, 589, 2399, + 2445, 719, 2393, + 2437, 850, 2387, + 2425, 981, 2377, + 2409, 1112, 2363, + 2389, 1244, 2345, + 2357, 1376, 2319, + 2313, 1507, 2283, + 2245, 1639, 2227, + 2137, 1771, 2141, + 1932, 1903, 1994, + 1282, 2035, 1667, + 0, 2167, 0, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2583, 0, 2503, + 2583, 0, 2503, + 2581, 0, 2501, + 2579, 0, 2499, + 2577, 0, 2497, + 2573, 0, 2495, + 2569, 172, 2489, + 2563, 511, 2483, + 2553, 754, 2477, + 2543, 954, 2465, + 2527, 1130, 2451, + 2503, 1293, 2431, + 2471, 1447, 2401, + 2425, 1595, 2359, + 2355, 1739, 2297, + 2239, 1879, 2197, + 2017, 2017, 2017, + 1174, 2153, 1537, + 0, 2289, 0, + 0, 2425, 0, + 0, 2557, 0, + 0, 2691, 0, + 0, 2825, 0, + 0, 2957, 0, + 0, 3091, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2705, 0, 2603, + 2705, 0, 2603, + 2703, 0, 2601, + 2703, 0, 2601, + 2701, 0, 2599, + 2697, 0, 2597, + 2695, 0, 2593, + 2689, 0, 2589, + 2683, 0, 2581, + 2675, 581, 2573, + 2663, 914, 2561, + 2647, 1154, 2545, + 2623, 1352, 2523, + 2591, 1528, 2493, + 2543, 1691, 2447, + 2469, 1845, 2377, + 2349, 1992, 2263, + 2111, 2135, 2046, + 972, 2275, 1272, + 0, 2413, 0, + 0, 2551, 0, + 0, 2685, 0, + 0, 2821, 0, + 0, 2955, 0, + 0, 3087, 0, + 0, 3221, 0, + 0, 3353, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3885, 0, + 0, 4017, 0, + 2831, 0, 2711, + 2829, 0, 2709, + 2829, 0, 2709, + 2827, 0, 2707, + 2827, 0, 2707, + 2825, 0, 2705, + 2821, 0, 2701, + 2819, 0, 2699, + 2813, 0, 2693, + 2807, 0, 2687, + 2797, 144, 2677, + 2785, 855, 2665, + 2769, 1183, 2649, + 2745, 1421, 2625, + 2711, 1618, 2591, + 2663, 1794, 2541, + 2587, 1956, 2465, + 2463, 2109, 2339, + 2211, 2257, 2083, + 338, 2401, 0, + 0, 2541, 0, + 0, 2679, 0, + 0, 2815, 0, + 0, 2951, 0, + 0, 3085, 0, + 0, 3219, 0, + 0, 3353, 0, + 0, 3485, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 2957, 0, 2823, + 2957, 0, 2821, + 2955, 0, 2821, + 2955, 0, 2821, + 2953, 0, 2819, + 2953, 0, 2817, + 2951, 0, 2815, + 2947, 0, 2813, + 2943, 0, 2809, + 2939, 0, 2803, + 2933, 0, 2797, + 2923, 0, 2787, + 2911, 762, 2775, + 2893, 1219, 2757, + 2869, 1499, 2731, + 2835, 1716, 2697, + 2785, 1903, 2643, + 2709, 2073, 2561, + 2581, 2231, 2423, + 2319, 2381, 2127, + 0, 2527, 0, + 0, 2667, 0, + 0, 2807, 0, + 0, 2945, 0, + 0, 3081, 0, + 0, 3215, 0, + 0, 3349, 0, + 0, 3483, 0, + 0, 3617, 0, + 0, 3749, 0, + 0, 3883, 0, + 0, 4015, 0, + 3085, 0, 2939, + 3085, 0, 2939, + 3083, 0, 2939, + 3083, 0, 2937, + 3083, 0, 2937, + 3081, 0, 2935, + 3079, 0, 2933, + 3077, 0, 2931, + 3075, 0, 2929, + 3071, 0, 2925, + 3067, 0, 2919, + 3059, 0, 2913, + 3051, 0, 2903, + 3037, 597, 2889, + 3021, 1264, 2871, + 2997, 1585, 2845, + 2961, 1821, 2807, + 2911, 2017, 2751, + 2833, 2191, 2665, + 2701, 2353, 2515, + 2431, 2507, 2181, + 0, 2653, 0, + 0, 2797, 0, + 0, 2937, 0, + 0, 3075, 0, + 0, 3211, 0, + 0, 3347, 0, + 0, 3481, 0, + 0, 3615, 0, + 0, 3749, 0, + 0, 3881, 0, + 0, 4015, 0, + 3213, 0, 3059, + 3213, 0, 3059, + 3213, 0, 3059, + 3213, 0, 3057, + 3211, 0, 3057, + 3211, 0, 3057, + 3209, 0, 3055, + 3209, 0, 3053, + 3207, 0, 3051, + 3203, 0, 3049, + 3199, 0, 3045, + 3195, 0, 3039, + 3187, 0, 3031, + 3179, 0, 3021, + 3165, 198, 3007, + 3149, 1317, 2989, + 3125, 1680, 2961, + 3089, 1931, 2923, + 3037, 2135, 2865, + 2959, 2315, 2775, + 2825, 2479, 2615, + 2549, 2635, 2243, + 0, 2783, 0, + 0, 2927, 0, + 0, 3067, 0, + 0, 3205, 0, + 0, 3343, 0, + 0, 3479, 0, + 0, 3613, 0, + 0, 3747, 0, + 0, 3881, 0, + 0, 4013, 0, + 3343, 0, 3183, + 3343, 0, 3181, + 3343, 0, 3181, + 3343, 0, 3181, + 3341, 0, 3181, + 3341, 0, 3179, + 3341, 0, 3179, + 3339, 0, 3177, + 3337, 0, 3177, + 3335, 0, 3173, + 3333, 0, 3171, + 3329, 0, 3167, + 3323, 0, 3161, + 3317, 0, 3153, + 3307, 0, 3143, + 3295, 0, 3129, + 3277, 1380, 3109, + 3253, 1783, 3081, + 3217, 2046, 3041, + 3167, 2257, 2983, + 3087, 2439, 2889, + 2951, 2607, 2723, + 2669, 2763, 2315, + 0, 2913, 0, + 0, 3057, 0, + 0, 3197, 0, + 0, 3337, 0, + 0, 3473, 0, + 0, 3609, 0, + 0, 3745, 0, + 0, 3879, 0, + 0, 4013, 0, + 3473, 0, 3307, + 3473, 0, 3307, + 3473, 0, 3307, + 3473, 0, 3307, + 3473, 0, 3307, + 3471, 0, 3305, + 3471, 0, 3305, + 3471, 0, 3303, + 3469, 0, 3303, + 3467, 0, 3301, + 3465, 0, 3299, + 3463, 0, 3295, + 3459, 0, 3291, + 3453, 0, 3285, + 3447, 0, 3277, + 3437, 0, 3267, + 3425, 0, 3253, + 3407, 1452, 3233, + 3383, 1891, 3205, + 3347, 2165, 3165, + 3295, 2381, 3103, + 3215, 2567, 3007, + 3079, 2735, 2835, + 2793, 2893, 2397, + 0, 3043, 0, + 0, 3187, 0, + 0, 3329, 0, + 0, 3469, 0, + 0, 3605, 0, + 0, 3741, 0, + 0, 3877, 0, + 0, 4011, 0, + 3603, 0, 3435, + 3603, 0, 3433, + 3603, 0, 3433, + 3603, 0, 3433, + 3603, 0, 3433, + 3603, 0, 3433, + 3603, 0, 3433, + 3601, 0, 3431, + 3601, 0, 3431, + 3599, 0, 3429, + 3599, 0, 3427, + 3597, 0, 3425, + 3593, 0, 3423, + 3589, 0, 3417, + 3585, 0, 3413, + 3577, 0, 3405, + 3569, 0, 3393, + 3555, 0, 3379, + 3537, 1534, 3359, + 3513, 2005, 3331, + 3477, 2287, 3289, + 3425, 2507, 3227, + 3345, 2695, 3129, + 3207, 2863, 2951, + 2917, 3023, 2487, + 0, 3173, 0, + 0, 3319, 0, + 0, 3461, 0, + 0, 3599, 0, + 0, 3737, 0, + 0, 3873, 0, + 0, 4009, 0, + 3735, 0, 3563, + 3735, 0, 3563, + 3735, 0, 3561, + 3735, 0, 3561, + 3735, 0, 3561, + 3735, 0, 3561, + 3733, 0, 3561, + 3733, 0, 3561, + 3733, 0, 3559, + 3731, 0, 3559, + 3731, 0, 3557, + 3729, 0, 3555, + 3727, 0, 3553, + 3725, 0, 3549, + 3721, 0, 3545, + 3715, 0, 3539, + 3709, 0, 3533, + 3699, 0, 3521, + 3687, 0, 3507, + 3669, 1625, 3487, + 3643, 2123, 3457, + 3607, 2411, 3415, + 3555, 2633, 3353, + 3475, 2823, 3253, + 3337, 2993, 3071, + 3045, 3153, 2585, + 0, 3303, 0, + 0, 3449, 0, + 0, 3593, 0, + 0, 3731, 0, + 0, 3869, 0, + 0, 4005, 0, + 3867, 0, 3691, + 3867, 0, 3691, + 3867, 0, 3691, + 3867, 0, 3691, + 3865, 0, 3691, + 3865, 0, 3691, + 3865, 0, 3691, + 3865, 0, 3689, + 3865, 0, 3689, + 3865, 0, 3689, + 3863, 0, 3687, + 3863, 0, 3687, + 3861, 0, 3685, + 3859, 0, 3683, + 3855, 0, 3679, + 3851, 0, 3675, + 3847, 0, 3669, + 3839, 0, 3661, + 3831, 0, 3651, + 3817, 0, 3635, + 3799, 1723, 3615, + 3775, 2243, 3585, + 3739, 2539, 3543, + 3687, 2763, 3481, + 3605, 2953, 3379, + 3467, 3125, 3195, + 3173, 3283, 2691, + 0, 3435, 0, + 0, 3581, 0, + 0, 3723, 0, + 0, 3863, 0, + 0, 4001, 0, + 3997, 0, 3821, + 3997, 0, 3821, + 3997, 0, 3821, + 3997, 0, 3821, + 3997, 0, 3821, + 3997, 0, 3821, + 3997, 0, 3821, + 3997, 0, 3821, + 3997, 0, 3819, + 3997, 0, 3819, + 3995, 0, 3819, + 3995, 0, 3817, + 3993, 0, 3817, + 3991, 0, 3815, + 3989, 0, 3811, + 3987, 0, 3809, + 3983, 0, 3805, + 3979, 0, 3799, + 3971, 0, 3791, + 3961, 0, 3779, + 3949, 0, 3765, + 3931, 1828, 3745, + 3907, 2367, 3715, + 3871, 2665, 3673, + 3817, 2891, 3609, + 3735, 3083, 3507, + 3597, 3255, 3319, + 3301, 3415, 2801, + 0, 3567, 0, + 0, 3713, 0, + 0, 3855, 0, + 0, 3995, 0, + 4095, 0, 3951, + 4095, 0, 3951, + 4095, 0, 3951, + 4095, 0, 3951, + 4095, 0, 3951, + 4095, 0, 3951, + 4095, 0, 3951, + 4095, 0, 3951, + 4095, 0, 3951, + 4095, 0, 3951, + 4095, 0, 3949, + 4095, 0, 3949, + 4095, 0, 3947, + 4095, 0, 3947, + 4095, 0, 3945, + 4095, 0, 3943, + 4095, 0, 3939, + 4095, 0, 3935, + 4095, 0, 3929, + 4095, 0, 3921, + 4093, 0, 3909, + 4081, 0, 3895, + 4063, 1938, 3875, + 4037, 2493, 3845, + 4001, 2795, 3801, + 3949, 3021, 3737, + 3867, 3215, 3635, + 3729, 3387, 3447, + 3431, 3547, 2917, + 0, 3699, 0, + 0, 3845, 0, + 0, 3987, 0, + 4095, 0, 4083, + 4095, 0, 4083, + 4095, 0, 4083, + 4095, 0, 4083, + 4095, 0, 4083, + 4095, 0, 4083, + 4095, 0, 4081, + 4095, 0, 4081, + 4095, 0, 4081, + 4095, 0, 4081, + 4095, 0, 4081, + 4095, 0, 4081, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4077, + 4095, 0, 4075, + 4095, 0, 4073, + 4095, 0, 4069, + 4095, 0, 4065, + 4095, 0, 4059, + 4095, 0, 4051, + 4095, 0, 4041, + 4095, 0, 4025, + 4095, 2053, 4005, + 4095, 2621, 3975, + 4095, 2925, 3933, + 4081, 3153, 3867, + 3999, 3345, 3765, + 3859, 3517, 3575, + 3563, 3679, 3035, + 0, 3831, 0, + 0, 3977, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2173, 4095, + 4095, 2749, 4095, + 4095, 3055, 4063, + 4095, 3283, 3999, + 4095, 3477, 3895, + 3991, 3649, 3703, + 3693, 3809, 3157, + 0, 3963, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2295, 4095, + 4095, 2877, 4095, + 4095, 3185, 4095, + 4095, 3415, 4095, + 4095, 3609, 4025, + 4095, 3781, 3833, + 3825, 3941, 3283, + 1643, 1209, 2051, + 1635, 1218, 2049, + 1623, 1230, 2045, + 1607, 1245, 2040, + 1585, 1264, 2033, + 1554, 1289, 2025, + 1508, 1321, 2012, + 1439, 1359, 1996, + 1326, 1406, 1972, + 1110, 1462, 1939, + 353, 1528, 1891, + 0, 1603, 1817, + 0, 1688, 1694, + 0, 1780, 1449, + 0, 1881, 80, + 0, 1987, 0, + 0, 2099, 0, + 0, 2217, 0, + 0, 2337, 0, + 0, 2459, 0, + 0, 2585, 0, + 0, 2711, 0, + 0, 2839, 0, + 0, 2969, 0, + 0, 3099, 0, + 0, 3229, 0, + 0, 3361, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3885, 0, + 0, 4017, 0, + 1653, 1208, 2053, + 1645, 1217, 2051, + 1634, 1229, 2047, + 1618, 1244, 2043, + 1597, 1263, 2036, + 1566, 1288, 2028, + 1522, 1319, 2016, + 1455, 1358, 1999, + 1346, 1405, 1976, + 1143, 1462, 1943, + 505, 1527, 1895, + 0, 1603, 1821, + 0, 1687, 1700, + 0, 1780, 1460, + 0, 1880, 260, + 0, 1987, 0, + 0, 2099, 0, + 0, 2217, 0, + 0, 2337, 0, + 0, 2459, 0, + 0, 2585, 0, + 0, 2711, 0, + 0, 2839, 0, + 0, 2969, 0, + 0, 3099, 0, + 0, 3229, 0, + 0, 3359, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3885, 0, + 0, 4017, 0, + 1667, 1206, 2057, + 1659, 1215, 2055, + 1648, 1227, 2051, + 1633, 1242, 2047, + 1612, 1262, 2040, + 1583, 1287, 2032, + 1540, 1318, 2020, + 1476, 1357, 2003, + 1373, 1404, 1980, + 1184, 1461, 1948, + 652, 1526, 1900, + 0, 1602, 1828, + 0, 1686, 1708, + 0, 1779, 1474, + 0, 1880, 426, + 0, 1987, 0, + 0, 2099, 0, + 0, 2215, 0, + 0, 2337, 0, + 0, 2459, 0, + 0, 2585, 0, + 0, 2711, 0, + 0, 2839, 0, + 0, 2969, 0, + 0, 3099, 0, + 0, 3229, 0, + 0, 3359, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3885, 0, + 0, 4017, 0, + 1685, 1204, 2063, + 1677, 1213, 2061, + 1667, 1224, 2057, + 1652, 1240, 2051, + 1632, 1259, 2046, + 1604, 1284, 2037, + 1563, 1316, 2025, + 1503, 1355, 2009, + 1406, 1403, 1986, + 1233, 1459, 1954, + 795, 1525, 1907, + 0, 1601, 1836, + 0, 1686, 1719, + 0, 1779, 1492, + 0, 1879, 581, + 0, 1986, 0, + 0, 2099, 0, + 0, 2215, 0, + 0, 2337, 0, + 0, 2459, 0, + 0, 2585, 0, + 0, 2711, 0, + 0, 2839, 0, + 0, 2969, 0, + 0, 3099, 0, + 0, 3229, 0, + 0, 3359, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3885, 0, + 0, 4017, 0, + 1707, 1200, 2069, + 1700, 1209, 2067, + 1690, 1221, 2063, + 1676, 1237, 2059, + 1657, 1256, 2053, + 1631, 1282, 2044, + 1593, 1313, 2033, + 1536, 1353, 2017, + 1447, 1400, 1994, + 1292, 1457, 1963, + 935, 1524, 1917, + 0, 1599, 1847, + 0, 1684, 1733, + 0, 1778, 1515, + 0, 1879, 730, + 0, 1986, 0, + 0, 2099, 0, + 0, 2215, 0, + 0, 2335, 0, + 0, 2459, 0, + 0, 2585, 0, + 0, 2711, 0, + 0, 2839, 0, + 0, 2969, 0, + 0, 3099, 0, + 0, 3229, 0, + 0, 3359, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3885, 0, + 0, 4017, 0, + 1736, 1196, 2079, + 1729, 1205, 2075, + 1720, 1217, 2073, + 1707, 1232, 2067, + 1689, 1252, 2061, + 1664, 1278, 2053, + 1629, 1310, 2042, + 1577, 1349, 2026, + 1496, 1397, 2005, + 1360, 1455, 1974, + 1073, 1521, 1929, + 0, 1598, 1861, + 0, 1683, 1752, + 0, 1776, 1545, + 0, 1878, 874, + 0, 1985, 0, + 0, 2097, 0, + 0, 2215, 0, + 0, 2335, 0, + 0, 2459, 0, + 0, 2585, 0, + 0, 2711, 0, + 0, 2839, 0, + 0, 2969, 0, + 0, 3099, 0, + 0, 3229, 0, + 0, 3359, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3885, 0, + 0, 4017, 0, + 1771, 1189, 2089, + 1765, 1199, 2087, + 1756, 1211, 2083, + 1745, 1227, 2079, + 1728, 1247, 2073, + 1706, 1273, 2065, + 1674, 1305, 2055, + 1627, 1345, 2039, + 1555, 1393, 2018, + 1437, 1451, 1988, + 1209, 1518, 1945, + 272, 1595, 1880, + 0, 1681, 1775, + 0, 1775, 1581, + 0, 1876, 1015, + 0, 1984, 0, + 0, 2097, 0, + 0, 2215, 0, + 0, 2335, 0, + 0, 2459, 0, + 0, 2583, 0, + 0, 2711, 0, + 0, 2839, 0, + 0, 2969, 0, + 0, 3099, 0, + 0, 3229, 0, + 0, 3359, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3885, 0, + 0, 4017, 0, + 1815, 1181, 2105, + 1809, 1191, 2103, + 1801, 1203, 2099, + 1791, 1219, 2095, + 1776, 1240, 2089, + 1756, 1266, 2081, + 1727, 1299, 2071, + 1685, 1339, 2057, + 1623, 1388, 2036, + 1524, 1446, 2007, + 1344, 1514, 1966, + 870, 1592, 1903, + 0, 1678, 1804, + 0, 1772, 1625, + 0, 1874, 1153, + 0, 1982, 0, + 0, 2095, 0, + 0, 2213, 0, + 0, 2335, 0, + 0, 2457, 0, + 0, 2583, 0, + 0, 2711, 0, + 0, 2839, 0, + 0, 2969, 0, + 0, 3099, 0, + 0, 3229, 0, + 0, 3359, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3885, 0, + 0, 4017, 0, + 1867, 1170, 2123, + 1862, 1179, 2121, + 1855, 1192, 2119, + 1846, 1209, 2115, + 1833, 1230, 2109, + 1815, 1256, 2101, + 1790, 1290, 2091, + 1754, 1331, 2077, + 1701, 1381, 2059, + 1619, 1440, 2031, + 1479, 1509, 1992, + 1180, 1587, 1933, + 0, 1674, 1841, + 0, 1769, 1678, + 0, 1872, 1290, + 0, 1981, 0, + 0, 2095, 0, + 0, 2213, 0, + 0, 2333, 0, + 0, 2457, 0, + 0, 2583, 0, + 0, 2711, 0, + 0, 2839, 0, + 0, 2969, 0, + 0, 3099, 0, + 0, 3229, 0, + 0, 3359, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3885, 0, + 0, 4017, 0, + 1929, 1154, 2149, + 1925, 1164, 2147, + 1919, 1177, 2143, + 1910, 1194, 2139, + 1899, 1216, 2135, + 1884, 1243, 2127, + 1862, 1278, 2117, + 1832, 1320, 2105, + 1788, 1371, 2087, + 1721, 1432, 2061, + 1613, 1501, 2024, + 1410, 1581, 1970, + 782, 1669, 1886, + 0, 1765, 1741, + 0, 1869, 1426, + 0, 1978, 0, + 0, 2093, 0, + 0, 2211, 0, + 0, 2333, 0, + 0, 2457, 0, + 0, 2583, 0, + 0, 2709, 0, + 0, 2839, 0, + 0, 2967, 0, + 0, 3097, 0, + 0, 3229, 0, + 0, 3359, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2001, 1132, 2179, + 1997, 1143, 2177, + 1992, 1156, 2175, + 1985, 1174, 2171, + 1975, 1197, 2167, + 1962, 1226, 2159, + 1944, 1261, 2151, + 1919, 1305, 2139, + 1883, 1358, 2121, + 1829, 1420, 2097, + 1746, 1491, 2065, + 1604, 1572, 2015, + 1299, 1662, 1939, + 0, 1760, 1813, + 0, 1864, 1560, + 0, 1974, 0, + 0, 2089, 0, + 0, 2209, 0, + 0, 2331, 0, + 0, 2455, 0, + 0, 2581, 0, + 0, 2709, 0, + 0, 2837, 0, + 0, 2967, 0, + 0, 3097, 0, + 0, 3229, 0, + 0, 3359, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2081, 1101, 2217, + 2079, 1112, 2215, + 2073, 1127, 2213, + 2069, 1146, 2211, + 2061, 1170, 2205, + 2049, 1200, 2199, + 2034, 1238, 2191, + 2014, 1284, 2181, + 1985, 1339, 2165, + 1943, 1404, 2143, + 1879, 1478, 2113, + 1778, 1561, 2069, + 1593, 1653, 2003, + 1089, 1752, 1895, + 0, 1858, 1695, + 0, 1970, 1079, + 0, 2085, 0, + 0, 2205, 0, + 0, 2329, 0, + 0, 2453, 0, + 0, 2579, 0, + 0, 2709, 0, + 0, 2837, 0, + 0, 2967, 0, + 0, 3097, 0, + 0, 3229, 0, + 0, 3359, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2171, 1056, 2265, + 2169, 1068, 2263, + 2165, 1084, 2261, + 2159, 1105, 2257, + 2153, 1132, 2253, + 2145, 1164, 2249, + 2133, 1205, 2241, + 2117, 1254, 2231, + 2093, 1313, 2217, + 2061, 1381, 2197, + 2012, 1458, 2171, + 1939, 1545, 2133, + 1817, 1640, 2075, + 1578, 1742, 1985, + 385, 1850, 1828, + 0, 1963, 1462, + 0, 2081, 0, + 0, 2201, 0, + 0, 2325, 0, + 0, 2451, 0, + 0, 2579, 0, + 0, 2707, 0, + 0, 2837, 0, + 0, 2967, 0, + 0, 3097, 0, + 0, 3227, 0, + 0, 3359, 0, + 0, 3491, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2269, 988, 2321, + 2267, 1002, 2319, + 2263, 1021, 2317, + 2259, 1044, 2315, + 2255, 1074, 2311, + 2247, 1112, 2305, + 2237, 1157, 2299, + 2225, 1211, 2291, + 2207, 1275, 2279, + 2181, 1349, 2261, + 2145, 1431, 2239, + 2091, 1523, 2205, + 2008, 1622, 2157, + 1865, 1727, 2083, + 1556, 1839, 1961, + 0, 1955, 1720, + 0, 2075, 451, + 0, 2197, 0, + 0, 2321, 0, + 0, 2449, 0, + 0, 2577, 0, + 0, 2705, 0, + 0, 2835, 0, + 0, 2965, 0, + 0, 3095, 0, + 0, 3227, 0, + 0, 3359, 0, + 0, 3491, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2373, 877, 2385, + 2371, 895, 2385, + 2369, 918, 2383, + 2365, 948, 2381, + 2361, 985, 2377, + 2357, 1029, 2373, + 2349, 1083, 2367, + 2339, 1147, 2359, + 2325, 1220, 2349, + 2305, 1302, 2335, + 2277, 1393, 2315, + 2237, 1491, 2287, + 2179, 1597, 2247, + 2087, 1708, 2189, + 1922, 1823, 2095, + 1526, 1943, 1927, + 0, 2065, 1516, + 0, 2189, 0, + 0, 2317, 0, + 0, 2445, 0, + 0, 2573, 0, + 0, 2703, 0, + 0, 2833, 0, + 0, 2963, 0, + 0, 3095, 0, + 0, 3227, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2483, 666, 2461, + 2481, 695, 2459, + 2479, 731, 2457, + 2477, 775, 2455, + 2475, 828, 2453, + 2469, 890, 2449, + 2463, 962, 2445, + 2457, 1043, 2439, + 2445, 1133, 2429, + 2431, 1230, 2417, + 2409, 1335, 2401, + 2381, 1445, 2379, + 2339, 1561, 2347, + 2275, 1680, 2299, + 2173, 1802, 2227, + 1988, 1926, 2109, + 1481, 2053, 1877, + 0, 2181, 879, + 0, 2309, 0, + 0, 2439, 0, + 0, 2569, 0, + 0, 2699, 0, + 0, 2831, 0, + 0, 2963, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2597, 0, 2543, + 2597, 84, 2543, + 2595, 209, 2541, + 2593, 335, 2541, + 2591, 463, 2539, + 2587, 592, 2535, + 2583, 721, 2531, + 2577, 852, 2527, + 2569, 982, 2519, + 2557, 1113, 2509, + 2543, 1244, 2495, + 2521, 1376, 2477, + 2489, 1508, 2451, + 2445, 1640, 2415, + 2379, 1771, 2359, + 2269, 1903, 2273, + 2065, 2035, 2127, + 1415, 2167, 1799, + 0, 2299, 0, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3091, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2717, 0, 2637, + 2715, 0, 2635, + 2715, 0, 2635, + 2713, 0, 2633, + 2711, 0, 2631, + 2709, 0, 2629, + 2705, 0, 2627, + 2701, 304, 2621, + 2695, 644, 2617, + 2687, 886, 2609, + 2675, 1086, 2597, + 2659, 1263, 2583, + 2635, 1426, 2563, + 2605, 1580, 2533, + 2557, 1727, 2493, + 2487, 1871, 2429, + 2371, 2011, 2329, + 2149, 2149, 2149, + 1306, 2287, 1669, + 0, 2421, 0, + 0, 2557, 0, + 0, 2691, 0, + 0, 2823, 0, + 0, 2957, 0, + 0, 3089, 0, + 0, 3223, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2839, 0, 2737, + 2837, 0, 2735, + 2837, 0, 2735, + 2837, 0, 2735, + 2835, 0, 2733, + 2833, 0, 2731, + 2831, 0, 2729, + 2827, 0, 2725, + 2821, 0, 2721, + 2815, 0, 2713, + 2807, 713, 2705, + 2795, 1046, 2693, + 2779, 1286, 2679, + 2755, 1484, 2655, + 2723, 1661, 2625, + 2675, 1823, 2579, + 2601, 1977, 2509, + 2481, 2125, 2395, + 2243, 2267, 2179, + 1103, 2407, 1404, + 0, 2547, 0, + 0, 2683, 0, + 0, 2819, 0, + 0, 2953, 0, + 0, 3087, 0, + 0, 3221, 0, + 0, 3353, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4017, 0, + 2963, 0, 2843, + 2963, 0, 2843, + 2961, 0, 2841, + 2961, 0, 2841, + 2959, 0, 2839, + 2959, 0, 2839, + 2957, 0, 2837, + 2953, 0, 2833, + 2951, 0, 2831, + 2945, 0, 2825, + 2939, 0, 2819, + 2929, 276, 2809, + 2917, 987, 2797, + 2901, 1315, 2781, + 2877, 1553, 2757, + 2843, 1750, 2723, + 2795, 1926, 2673, + 2719, 2089, 2597, + 2595, 2241, 2471, + 2343, 2389, 2215, + 471, 2533, 0, + 0, 2673, 0, + 0, 2811, 0, + 0, 2947, 0, + 0, 3083, 0, + 0, 3217, 0, + 0, 3351, 0, + 0, 3485, 0, + 0, 3617, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 3089, 0, 2955, + 3089, 0, 2955, + 3089, 0, 2955, + 3087, 0, 2953, + 3087, 0, 2953, + 3085, 0, 2951, + 3085, 0, 2949, + 3083, 0, 2947, + 3079, 0, 2945, + 3075, 0, 2941, + 3071, 0, 2937, + 3065, 0, 2929, + 3055, 0, 2919, + 3043, 894, 2907, + 3025, 1351, 2889, + 3001, 1631, 2863, + 2967, 1848, 2829, + 2917, 2035, 2775, + 2841, 2205, 2693, + 2713, 2363, 2555, + 2451, 2513, 2259, + 0, 2659, 0, + 0, 2801, 0, + 0, 2939, 0, + 0, 3077, 0, + 0, 3213, 0, + 0, 3347, 0, + 0, 3483, 0, + 0, 3615, 0, + 0, 3749, 0, + 0, 3883, 0, + 0, 4015, 0, + 3217, 0, 3071, + 3217, 0, 3071, + 3217, 0, 3071, + 3215, 0, 3071, + 3215, 0, 3069, + 3215, 0, 3069, + 3213, 0, 3067, + 3211, 0, 3065, + 3209, 0, 3063, + 3207, 0, 3061, + 3203, 0, 3057, + 3199, 0, 3051, + 3191, 0, 3045, + 3183, 0, 3035, + 3169, 729, 3021, + 3153, 1396, 3003, + 3129, 1717, 2977, + 3093, 1953, 2939, + 3043, 2149, 2883, + 2965, 2325, 2797, + 2833, 2485, 2647, + 2563, 2639, 2313, + 0, 2785, 0, + 0, 2929, 0, + 0, 3069, 0, + 0, 3207, 0, + 0, 3343, 0, + 0, 3479, 0, + 0, 3613, 0, + 0, 3747, 0, + 0, 3881, 0, + 0, 4013, 0, + 3345, 0, 3191, + 3345, 0, 3191, + 3345, 0, 3191, + 3345, 0, 3191, + 3345, 0, 3191, + 3343, 0, 3189, + 3343, 0, 3189, + 3341, 0, 3187, + 3341, 0, 3185, + 3339, 0, 3183, + 3335, 0, 3181, + 3331, 0, 3177, + 3327, 0, 3171, + 3319, 0, 3163, + 3311, 0, 3153, + 3299, 330, 3139, + 3281, 1449, 3121, + 3257, 1813, 3093, + 3221, 2063, 3055, + 3169, 2267, 2997, + 3091, 2447, 2907, + 2957, 2611, 2747, + 2681, 2767, 2375, + 0, 2915, 0, + 0, 3059, 0, + 0, 3199, 0, + 0, 3337, 0, + 0, 3475, 0, + 0, 3611, 0, + 0, 3745, 0, + 0, 3879, 0, + 0, 4013, 0, + 3475, 0, 3315, + 3475, 0, 3315, + 3475, 0, 3313, + 3475, 0, 3313, + 3475, 0, 3313, + 3473, 0, 3313, + 3473, 0, 3313, + 3473, 0, 3311, + 3471, 0, 3309, + 3469, 0, 3309, + 3467, 0, 3305, + 3465, 0, 3303, + 3461, 0, 3299, + 3457, 0, 3293, + 3449, 0, 3285, + 3439, 0, 3275, + 3427, 0, 3261, + 3409, 1512, 3241, + 3385, 1915, 3213, + 3349, 2179, 3175, + 3299, 2389, 3115, + 3219, 2571, 3021, + 3083, 2739, 2855, + 2801, 2895, 2447, + 0, 3045, 0, + 0, 3189, 0, + 0, 3331, 0, + 0, 3469, 0, + 0, 3607, 0, + 0, 3741, 0, + 0, 3877, 0, + 0, 4011, 0, + 3605, 0, 3439, + 3605, 0, 3439, + 3605, 0, 3439, + 3605, 0, 3439, + 3605, 0, 3439, + 3605, 0, 3439, + 3603, 0, 3437, + 3603, 0, 3437, + 3603, 0, 3437, + 3601, 0, 3435, + 3599, 0, 3433, + 3597, 0, 3431, + 3595, 0, 3427, + 3591, 0, 3423, + 3587, 0, 3417, + 3579, 0, 3411, + 3569, 0, 3399, + 3557, 0, 3385, + 3539, 1585, 3365, + 3515, 2023, 3337, + 3479, 2297, 3297, + 3427, 2513, 3235, + 3347, 2699, 3139, + 3211, 2867, 2967, + 2925, 3025, 2529, + 0, 3175, 0, + 0, 3319, 0, + 0, 3461, 0, + 0, 3601, 0, + 0, 3737, 0, + 0, 3873, 0, + 0, 4009, 0, + 3737, 0, 3567, + 3737, 0, 3567, + 3735, 0, 3567, + 3735, 0, 3565, + 3735, 0, 3565, + 3735, 0, 3565, + 3735, 0, 3565, + 3735, 0, 3565, + 3733, 0, 3563, + 3733, 0, 3563, + 3731, 0, 3561, + 3731, 0, 3559, + 3729, 0, 3557, + 3725, 0, 3555, + 3721, 0, 3549, + 3717, 0, 3545, + 3709, 0, 3537, + 3701, 0, 3525, + 3687, 0, 3511, + 3669, 1666, 3491, + 3645, 2137, 3463, + 3609, 2419, 3421, + 3557, 2639, 3359, + 3477, 2827, 3261, + 3339, 2995, 3083, + 3049, 3155, 2619, + 0, 3305, 0, + 0, 3451, 0, + 0, 3593, 0, + 0, 3731, 0, + 0, 3869, 0, + 0, 4005, 0, + 3867, 0, 3695, + 3867, 0, 3695, + 3867, 0, 3695, + 3867, 0, 3695, + 3867, 0, 3693, + 3867, 0, 3693, + 3867, 0, 3693, + 3867, 0, 3693, + 3865, 0, 3693, + 3865, 0, 3691, + 3865, 0, 3691, + 3863, 0, 3689, + 3861, 0, 3687, + 3859, 0, 3685, + 3857, 0, 3683, + 3853, 0, 3677, + 3847, 0, 3673, + 3841, 0, 3665, + 3831, 0, 3653, + 3819, 0, 3639, + 3801, 1757, 3619, + 3775, 2255, 3589, + 3741, 2543, 3547, + 3687, 2765, 3485, + 3607, 2955, 3385, + 3469, 3125, 3203, + 3177, 3285, 2717, + 0, 3437, 0, + 0, 3581, 0, + 0, 3725, 0, + 0, 3863, 0, + 0, 4001, 0, + 3999, 0, 3823, + 3999, 0, 3823, + 3999, 0, 3823, + 3999, 0, 3823, + 3999, 0, 3823, + 3999, 0, 3823, + 3997, 0, 3823, + 3997, 0, 3823, + 3997, 0, 3821, + 3997, 0, 3821, + 3997, 0, 3821, + 3995, 0, 3819, + 3995, 0, 3819, + 3993, 0, 3817, + 3991, 0, 3815, + 3987, 0, 3811, + 3983, 0, 3807, + 3979, 0, 3801, + 3971, 0, 3793, + 3963, 0, 3783, + 3949, 0, 3767, + 3931, 1855, 3747, + 3907, 2375, 3717, + 3871, 2671, 3675, + 3819, 2895, 3613, + 3737, 3085, 3511, + 3599, 3257, 3327, + 3305, 3415, 2823, + 0, 3567, 0, + 0, 3713, 0, + 0, 3855, 0, + 0, 3995, 0, + 4095, 0, 3953, + 4095, 0, 3953, + 4095, 0, 3953, + 4095, 0, 3953, + 4095, 0, 3953, + 4095, 0, 3953, + 4095, 0, 3953, + 4095, 0, 3953, + 4095, 0, 3953, + 4095, 0, 3951, + 4095, 0, 3951, + 4095, 0, 3951, + 4095, 0, 3949, + 4095, 0, 3949, + 4095, 0, 3947, + 4095, 0, 3945, + 4095, 0, 3941, + 4095, 0, 3937, + 4095, 0, 3931, + 4095, 0, 3923, + 4093, 0, 3911, + 4081, 0, 3897, + 4063, 1960, 3877, + 4039, 2499, 3847, + 4003, 2797, 3805, + 3949, 3023, 3741, + 3869, 3215, 3639, + 3729, 3387, 3451, + 3435, 3547, 2933, + 0, 3699, 0, + 0, 3845, 0, + 0, 3987, 0, + 4095, 0, 4083, + 4095, 0, 4083, + 4095, 0, 4083, + 4095, 0, 4083, + 4095, 0, 4083, + 4095, 0, 4083, + 4095, 0, 4083, + 4095, 0, 4083, + 4095, 0, 4083, + 4095, 0, 4083, + 4095, 0, 4083, + 4095, 0, 4081, + 4095, 0, 4081, + 4095, 0, 4079, + 4095, 0, 4079, + 4095, 0, 4077, + 4095, 0, 4075, + 4095, 0, 4071, + 4095, 0, 4067, + 4095, 0, 4061, + 4095, 0, 4053, + 4095, 0, 4043, + 4095, 0, 4027, + 4095, 2071, 4007, + 4095, 2625, 3977, + 4095, 2927, 3935, + 4081, 3155, 3869, + 3999, 3347, 3767, + 3861, 3519, 3579, + 3563, 3679, 3049, + 0, 3831, 0, + 0, 3977, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2187, 4095, + 4095, 2753, 4095, + 4095, 3057, 4065, + 4095, 3285, 4001, + 4095, 3477, 3897, + 3991, 3651, 3707, + 3695, 3811, 3167, + 0, 3963, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2305, 4095, + 4095, 2881, 4095, + 4095, 3187, 4095, + 4095, 3415, 4095, + 4095, 3609, 4027, + 4095, 3781, 3835, + 3825, 3943, 3291, + 1773, 1336, 2183, + 1767, 1342, 2181, + 1759, 1351, 2179, + 1747, 1363, 2175, + 1731, 1378, 2169, + 1708, 1398, 2163, + 1676, 1422, 2155, + 1629, 1453, 2143, + 1558, 1492, 2125, + 1442, 1539, 2101, + 1216, 1595, 2069, + 324, 1661, 2020, + 0, 1736, 1945, + 0, 1820, 1821, + 0, 1913, 1573, + 0, 2013, 6, + 0, 2119, 0, + 0, 2231, 0, + 0, 2349, 0, + 0, 2469, 0, + 0, 2591, 0, + 0, 2717, 0, + 0, 2843, 0, + 0, 2971, 0, + 0, 3101, 0, + 0, 3231, 0, + 0, 3361, 0, + 0, 3493, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 1781, 1335, 2185, + 1775, 1341, 2183, + 1767, 1350, 2181, + 1755, 1362, 2177, + 1739, 1377, 2171, + 1717, 1397, 2165, + 1686, 1421, 2157, + 1640, 1453, 2145, + 1571, 1491, 2127, + 1458, 1538, 2105, + 1242, 1594, 2071, + 485, 1660, 2023, + 0, 1735, 1949, + 0, 1820, 1826, + 0, 1912, 1582, + 0, 2013, 212, + 0, 2119, 0, + 0, 2231, 0, + 0, 2349, 0, + 0, 2469, 0, + 0, 2591, 0, + 0, 2717, 0, + 0, 2843, 0, + 0, 2971, 0, + 0, 3101, 0, + 0, 3231, 0, + 0, 3361, 0, + 0, 3493, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 1792, 1333, 2187, + 1786, 1340, 2185, + 1777, 1349, 2183, + 1766, 1361, 2179, + 1751, 1376, 2175, + 1729, 1395, 2169, + 1699, 1420, 2159, + 1654, 1452, 2147, + 1587, 1490, 2131, + 1479, 1537, 2107, + 1275, 1594, 2075, + 637, 1659, 2027, + 0, 1735, 1954, + 0, 1819, 1832, + 0, 1912, 1592, + 0, 2012, 393, + 0, 2119, 0, + 0, 2231, 0, + 0, 2349, 0, + 0, 2469, 0, + 0, 2591, 0, + 0, 2717, 0, + 0, 2843, 0, + 0, 2971, 0, + 0, 3101, 0, + 0, 3231, 0, + 0, 3361, 0, + 0, 3493, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 1805, 1331, 2191, + 1799, 1338, 2189, + 1791, 1347, 2187, + 1780, 1359, 2183, + 1765, 1374, 2179, + 1744, 1394, 2173, + 1715, 1419, 2163, + 1672, 1450, 2151, + 1608, 1489, 2135, + 1505, 1536, 2113, + 1316, 1593, 2079, + 784, 1659, 2032, + 0, 1734, 1960, + 0, 1819, 1840, + 0, 1912, 1606, + 0, 2012, 558, + 0, 2119, 0, + 0, 2231, 0, + 0, 2349, 0, + 0, 2469, 0, + 0, 2591, 0, + 0, 2717, 0, + 0, 2843, 0, + 0, 2971, 0, + 0, 3101, 0, + 0, 3231, 0, + 0, 3361, 0, + 0, 3493, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 1823, 1329, 2197, + 1817, 1336, 2195, + 1809, 1345, 2193, + 1799, 1356, 2189, + 1784, 1372, 2185, + 1764, 1392, 2177, + 1736, 1417, 2169, + 1695, 1448, 2157, + 1635, 1487, 2141, + 1538, 1535, 2119, + 1365, 1591, 2087, + 927, 1657, 2040, + 0, 1733, 1968, + 0, 1818, 1851, + 0, 1911, 1624, + 0, 2011, 713, + 0, 2119, 0, + 0, 2231, 0, + 0, 2347, 0, + 0, 2469, 0, + 0, 2591, 0, + 0, 2717, 0, + 0, 2843, 0, + 0, 2971, 0, + 0, 3101, 0, + 0, 3231, 0, + 0, 3361, 0, + 0, 3493, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 1845, 1325, 2203, + 1839, 1332, 2201, + 1832, 1341, 2199, + 1822, 1353, 2195, + 1809, 1369, 2191, + 1790, 1389, 2185, + 1763, 1414, 2177, + 1725, 1446, 2165, + 1668, 1485, 2149, + 1579, 1532, 2127, + 1424, 1589, 2095, + 1067, 1656, 2049, + 0, 1732, 1979, + 0, 1817, 1865, + 0, 1910, 1647, + 0, 2011, 862, + 0, 2117, 0, + 0, 2231, 0, + 0, 2347, 0, + 0, 2467, 0, + 0, 2591, 0, + 0, 2717, 0, + 0, 2843, 0, + 0, 2971, 0, + 0, 3101, 0, + 0, 3231, 0, + 0, 3361, 0, + 0, 3493, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 1873, 1321, 2213, + 1868, 1328, 2211, + 1861, 1337, 2207, + 1852, 1349, 2205, + 1839, 1365, 2199, + 1821, 1385, 2193, + 1797, 1410, 2185, + 1761, 1442, 2175, + 1709, 1482, 2159, + 1628, 1530, 2137, + 1492, 1587, 2107, + 1205, 1653, 2061, + 0, 1730, 1994, + 0, 1815, 1884, + 0, 1909, 1677, + 0, 2010, 1006, + 0, 2117, 0, + 0, 2229, 0, + 0, 2347, 0, + 0, 2467, 0, + 0, 2591, 0, + 0, 2717, 0, + 0, 2843, 0, + 0, 2971, 0, + 0, 3101, 0, + 0, 3231, 0, + 0, 3361, 0, + 0, 3493, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 1908, 1315, 2223, + 1904, 1322, 2221, + 1897, 1331, 2219, + 1889, 1343, 2217, + 1877, 1359, 2211, + 1861, 1379, 2205, + 1838, 1405, 2197, + 1806, 1437, 2187, + 1759, 1477, 2171, + 1687, 1526, 2151, + 1570, 1583, 2121, + 1341, 1650, 2077, + 404, 1727, 2012, + 0, 1813, 1907, + 0, 1907, 1713, + 0, 2008, 1147, + 0, 2117, 0, + 0, 2229, 0, + 0, 2347, 0, + 0, 2467, 0, + 0, 2591, 0, + 0, 2715, 0, + 0, 2843, 0, + 0, 2971, 0, + 0, 3101, 0, + 0, 3231, 0, + 0, 3361, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4017, 0, + 1951, 1306, 2239, + 1947, 1313, 2237, + 1941, 1323, 2235, + 1934, 1335, 2231, + 1923, 1351, 2227, + 1908, 1372, 2221, + 1888, 1398, 2213, + 1859, 1431, 2203, + 1818, 1471, 2189, + 1755, 1520, 2167, + 1656, 1579, 2139, + 1476, 1646, 2097, + 1002, 1724, 2036, + 0, 1810, 1936, + 0, 1905, 1757, + 0, 2007, 1285, + 0, 2115, 0, + 0, 2227, 0, + 0, 2345, 0, + 0, 2467, 0, + 0, 2589, 0, + 0, 2715, 0, + 0, 2843, 0, + 0, 2971, 0, + 0, 3101, 0, + 0, 3231, 0, + 0, 3361, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4017, 0, + 2003, 1294, 2257, + 2000, 1302, 2257, + 1994, 1312, 2253, + 1987, 1324, 2251, + 1978, 1341, 2247, + 1965, 1362, 2241, + 1947, 1389, 2233, + 1922, 1422, 2223, + 1886, 1463, 2209, + 1833, 1513, 2191, + 1751, 1572, 2163, + 1611, 1641, 2123, + 1312, 1719, 2065, + 0, 1806, 1973, + 0, 1902, 1811, + 0, 2004, 1422, + 0, 2113, 0, + 0, 2227, 0, + 0, 2345, 0, + 0, 2465, 0, + 0, 2589, 0, + 0, 2715, 0, + 0, 2843, 0, + 0, 2971, 0, + 0, 3101, 0, + 0, 3231, 0, + 0, 3361, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4017, 0, + 2065, 1278, 2283, + 2061, 1286, 2281, + 2057, 1296, 2279, + 2051, 1309, 2275, + 2043, 1326, 2271, + 2031, 1348, 2267, + 2016, 1376, 2259, + 1994, 1410, 2249, + 1964, 1452, 2237, + 1920, 1503, 2219, + 1853, 1564, 2193, + 1745, 1634, 2157, + 1543, 1713, 2103, + 914, 1801, 2018, + 0, 1897, 1873, + 0, 2001, 1558, + 0, 2111, 0, + 0, 2225, 0, + 0, 2343, 0, + 0, 2465, 0, + 0, 2589, 0, + 0, 2715, 0, + 0, 2841, 0, + 0, 2971, 0, + 0, 3099, 0, + 0, 3231, 0, + 0, 3361, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4017, 0, + 2135, 1256, 2313, + 2133, 1264, 2311, + 2129, 1275, 2309, + 2123, 1289, 2307, + 2117, 1306, 2303, + 2107, 1329, 2299, + 2095, 1358, 2291, + 2077, 1393, 2283, + 2051, 1437, 2271, + 2015, 1490, 2253, + 1961, 1552, 2231, + 1878, 1624, 2197, + 1737, 1704, 2147, + 1431, 1794, 2071, + 0, 1892, 1946, + 0, 1996, 1693, + 0, 2107, 0, + 0, 2221, 0, + 0, 2341, 0, + 0, 2463, 0, + 0, 2587, 0, + 0, 2713, 0, + 0, 2841, 0, + 0, 2969, 0, + 0, 3099, 0, + 0, 3229, 0, + 0, 3361, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4017, 0, + 2215, 1225, 2351, + 2213, 1233, 2349, + 2211, 1244, 2347, + 2205, 1259, 2345, + 2201, 1278, 2343, + 2193, 1302, 2337, + 2181, 1333, 2331, + 2167, 1370, 2323, + 2145, 1416, 2313, + 2117, 1471, 2297, + 2075, 1536, 2275, + 2011, 1610, 2245, + 1910, 1693, 2201, + 1725, 1785, 2135, + 1221, 1884, 2027, + 0, 1990, 1827, + 0, 2101, 1211, + 0, 2219, 0, + 0, 2337, 0, + 0, 2461, 0, + 0, 2585, 0, + 0, 2713, 0, + 0, 2841, 0, + 0, 2969, 0, + 0, 3099, 0, + 0, 3229, 0, + 0, 3361, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3885, 0, + 0, 4017, 0, + 2305, 1179, 2397, + 2303, 1188, 2397, + 2301, 1200, 2395, + 2297, 1217, 2393, + 2293, 1237, 2389, + 2285, 1264, 2385, + 2277, 1297, 2381, + 2265, 1337, 2373, + 2249, 1387, 2363, + 2225, 1445, 2349, + 2193, 1513, 2329, + 2145, 1591, 2303, + 2071, 1677, 2265, + 1949, 1772, 2207, + 1710, 1874, 2117, + 517, 1982, 1960, + 0, 2095, 1594, + 0, 2213, 0, + 0, 2335, 0, + 0, 2457, 0, + 0, 2583, 0, + 0, 2711, 0, + 0, 2839, 0, + 0, 2969, 0, + 0, 3099, 0, + 0, 3229, 0, + 0, 3359, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3885, 0, + 0, 4017, 0, + 2401, 1109, 2453, + 2401, 1120, 2453, + 2399, 1134, 2451, + 2395, 1153, 2449, + 2391, 1177, 2447, + 2387, 1206, 2443, + 2379, 1244, 2437, + 2369, 1289, 2431, + 2357, 1344, 2423, + 2339, 1407, 2411, + 2313, 1481, 2393, + 2277, 1564, 2371, + 2223, 1655, 2337, + 2139, 1754, 2289, + 1997, 1860, 2215, + 1688, 1971, 2093, + 0, 2087, 1852, + 0, 2207, 583, + 0, 2329, 0, + 0, 2453, 0, + 0, 2581, 0, + 0, 2709, 0, + 0, 2837, 0, + 0, 2967, 0, + 0, 3097, 0, + 0, 3229, 0, + 0, 3359, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2505, 995, 2519, + 2505, 1009, 2517, + 2503, 1027, 2517, + 2501, 1050, 2515, + 2497, 1080, 2513, + 2493, 1117, 2509, + 2489, 1162, 2505, + 2481, 1216, 2499, + 2471, 1279, 2491, + 2457, 1352, 2481, + 2437, 1434, 2467, + 2409, 1525, 2447, + 2369, 1623, 2419, + 2311, 1729, 2381, + 2219, 1840, 2321, + 2055, 1955, 2227, + 1658, 2075, 2059, + 0, 2197, 1649, + 0, 2321, 0, + 0, 2449, 0, + 0, 2577, 0, + 0, 2705, 0, + 0, 2835, 0, + 0, 2965, 0, + 0, 3097, 0, + 0, 3227, 0, + 0, 3359, 0, + 0, 3491, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2615, 775, 2593, + 2615, 798, 2593, + 2613, 827, 2591, + 2611, 863, 2589, + 2609, 907, 2587, + 2607, 960, 2585, + 2601, 1022, 2581, + 2597, 1094, 2577, + 2589, 1175, 2571, + 2577, 1265, 2561, + 2563, 1363, 2551, + 2541, 1467, 2533, + 2513, 1578, 2511, + 2471, 1693, 2479, + 2407, 1812, 2431, + 2305, 1934, 2359, + 2121, 2059, 2241, + 1614, 2185, 2009, + 0, 2313, 1012, + 0, 2441, 0, + 0, 2571, 0, + 0, 2701, 0, + 0, 2831, 0, + 0, 2963, 0, + 0, 3095, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2731, 0, 2677, + 2729, 94, 2677, + 2729, 216, 2675, + 2727, 341, 2675, + 2725, 467, 2673, + 2723, 595, 2671, + 2719, 724, 2667, + 2715, 853, 2663, + 2709, 984, 2659, + 2701, 1114, 2651, + 2689, 1245, 2641, + 2675, 1377, 2629, + 2653, 1508, 2609, + 2621, 1640, 2583, + 2577, 1772, 2547, + 2511, 1904, 2491, + 2401, 2035, 2407, + 2197, 2167, 2259, + 1547, 2299, 1931, + 0, 2431, 0, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2849, 0, 2769, + 2849, 0, 2769, + 2847, 0, 2767, + 2847, 0, 2767, + 2845, 0, 2765, + 2843, 0, 2763, + 2841, 0, 2761, + 2837, 0, 2759, + 2833, 436, 2755, + 2827, 776, 2749, + 2819, 1018, 2741, + 2807, 1218, 2729, + 2791, 1395, 2715, + 2769, 1558, 2695, + 2737, 1712, 2665, + 2689, 1859, 2625, + 2619, 2003, 2561, + 2503, 2143, 2463, + 2281, 2281, 2281, + 1438, 2419, 1802, + 0, 2553, 0, + 0, 2689, 0, + 0, 2823, 0, + 0, 2955, 0, + 0, 3089, 0, + 0, 3221, 0, + 0, 3355, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3885, 0, + 0, 4017, 0, + 2971, 0, 2869, + 2971, 0, 2869, + 2971, 0, 2867, + 2969, 0, 2867, + 2969, 0, 2867, + 2967, 0, 2865, + 2965, 0, 2863, + 2963, 0, 2861, + 2959, 0, 2857, + 2953, 0, 2853, + 2947, 96, 2847, + 2939, 845, 2837, + 2927, 1178, 2827, + 2911, 1418, 2811, + 2887, 1617, 2789, + 2855, 1793, 2757, + 2807, 1955, 2711, + 2733, 2109, 2641, + 2613, 2257, 2527, + 2375, 2399, 2311, + 1236, 2539, 1536, + 0, 2679, 0, + 0, 2815, 0, + 0, 2951, 0, + 0, 3085, 0, + 0, 3219, 0, + 0, 3353, 0, + 0, 3485, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 3095, 0, 2975, + 3095, 0, 2975, + 3095, 0, 2975, + 3095, 0, 2973, + 3093, 0, 2973, + 3093, 0, 2973, + 3091, 0, 2971, + 3089, 0, 2969, + 3085, 0, 2965, + 3083, 0, 2963, + 3077, 0, 2957, + 3071, 0, 2951, + 3063, 409, 2941, + 3049, 1119, 2929, + 3033, 1447, 2913, + 3009, 1685, 2889, + 2975, 1883, 2855, + 2927, 2059, 2805, + 2851, 2221, 2729, + 2727, 2373, 2603, + 2475, 2521, 2347, + 602, 2665, 0, + 0, 2805, 0, + 0, 2943, 0, + 0, 3079, 0, + 0, 3215, 0, + 0, 3349, 0, + 0, 3483, 0, + 0, 3617, 0, + 0, 3749, 0, + 0, 3883, 0, + 0, 4015, 0, + 3221, 0, 3087, + 3221, 0, 3087, + 3221, 0, 3087, + 3221, 0, 3087, + 3219, 0, 3085, + 3219, 0, 3085, + 3217, 0, 3083, + 3217, 0, 3083, + 3215, 0, 3079, + 3211, 0, 3077, + 3209, 0, 3073, + 3203, 0, 3069, + 3197, 0, 3061, + 3187, 0, 3051, + 3175, 1026, 3039, + 3159, 1483, 3021, + 3135, 1763, 2997, + 3099, 1980, 2961, + 3049, 2167, 2907, + 2973, 2337, 2825, + 2845, 2495, 2687, + 2583, 2645, 2391, + 0, 2791, 0, + 0, 2933, 0, + 0, 3071, 0, + 0, 3209, 0, + 0, 3345, 0, + 0, 3479, 0, + 0, 3615, 0, + 0, 3747, 0, + 0, 3881, 0, + 0, 4015, 0, + 3349, 0, 3203, + 3349, 0, 3203, + 3349, 0, 3203, + 3349, 0, 3203, + 3347, 0, 3203, + 3347, 0, 3201, + 3347, 0, 3201, + 3345, 0, 3199, + 3343, 0, 3199, + 3341, 0, 3195, + 3339, 0, 3193, + 3335, 0, 3189, + 3331, 0, 3183, + 3323, 0, 3177, + 3315, 0, 3167, + 3303, 861, 3153, + 3285, 1528, 3135, + 3261, 1850, 3109, + 3225, 2085, 3071, + 3175, 2281, 3015, + 3097, 2457, 2929, + 2965, 2617, 2779, + 2695, 2771, 2445, + 0, 2919, 0, + 0, 3061, 0, + 0, 3201, 0, + 0, 3339, 0, + 0, 3475, 0, + 0, 3611, 0, + 0, 3745, 0, + 0, 3879, 0, + 0, 4013, 0, + 3477, 0, 3323, + 3477, 0, 3323, + 3477, 0, 3323, + 3477, 0, 3323, + 3477, 0, 3323, + 3477, 0, 3323, + 3475, 0, 3321, + 3475, 0, 3321, + 3473, 0, 3319, + 3473, 0, 3317, + 3471, 0, 3315, + 3467, 0, 3313, + 3463, 0, 3309, + 3459, 0, 3303, + 3453, 0, 3295, + 3443, 0, 3285, + 3431, 462, 3271, + 3413, 1581, 3253, + 3389, 1945, 3225, + 3353, 2195, 3187, + 3303, 2399, 3129, + 3223, 2579, 3039, + 3089, 2743, 2879, + 2813, 2899, 2507, + 0, 3047, 0, + 0, 3191, 0, + 0, 3331, 0, + 0, 3469, 0, + 0, 3607, 0, + 0, 3743, 0, + 0, 3877, 0, + 0, 4011, 0, + 3607, 0, 3447, + 3607, 0, 3447, + 3607, 0, 3447, + 3607, 0, 3447, + 3607, 0, 3445, + 3607, 0, 3445, + 3605, 0, 3445, + 3605, 0, 3445, + 3605, 0, 3443, + 3603, 0, 3441, + 3601, 0, 3441, + 3599, 0, 3439, + 3597, 0, 3435, + 3593, 0, 3431, + 3589, 0, 3425, + 3581, 0, 3417, + 3573, 0, 3407, + 3559, 0, 3393, + 3541, 1644, 3373, + 3517, 2047, 3347, + 3483, 2311, 3307, + 3431, 2521, 3247, + 3351, 2703, 3153, + 3215, 2871, 2987, + 2933, 3027, 2579, + 0, 3177, 0, + 0, 3321, 0, + 0, 3463, 0, + 0, 3601, 0, + 0, 3739, 0, + 0, 3875, 0, + 0, 4009, 0, + 3737, 0, 3571, + 3737, 0, 3571, + 3737, 0, 3571, + 3737, 0, 3571, + 3737, 0, 3571, + 3737, 0, 3571, + 3737, 0, 3571, + 3737, 0, 3569, + 3735, 0, 3569, + 3735, 0, 3569, + 3733, 0, 3567, + 3731, 0, 3565, + 3729, 0, 3563, + 3727, 0, 3559, + 3723, 0, 3555, + 3719, 0, 3549, + 3711, 0, 3543, + 3703, 0, 3531, + 3689, 0, 3517, + 3671, 1717, 3497, + 3647, 2155, 3469, + 3611, 2429, 3429, + 3559, 2645, 3367, + 3479, 2831, 3271, + 3343, 2999, 3099, + 3057, 3157, 2661, + 0, 3307, 0, + 0, 3451, 0, + 0, 3593, 0, + 0, 3733, 0, + 0, 3869, 0, + 0, 4005, 0, + 3869, 0, 3699, + 3869, 0, 3699, + 3869, 0, 3699, + 3869, 0, 3699, + 3867, 0, 3697, + 3867, 0, 3697, + 3867, 0, 3697, + 3867, 0, 3697, + 3867, 0, 3697, + 3867, 0, 3695, + 3865, 0, 3695, + 3865, 0, 3693, + 3863, 0, 3691, + 3861, 0, 3689, + 3857, 0, 3687, + 3853, 0, 3683, + 3849, 0, 3677, + 3841, 0, 3669, + 3833, 0, 3657, + 3819, 0, 3643, + 3801, 1798, 3623, + 3777, 2269, 3595, + 3741, 2551, 3553, + 3689, 2771, 3491, + 3609, 2959, 3393, + 3471, 3129, 3215, + 3181, 3287, 2751, + 0, 3437, 0, + 0, 3583, 0, + 0, 3725, 0, + 0, 3865, 0, + 0, 4001, 0, + 3999, 0, 3827, + 3999, 0, 3827, + 3999, 0, 3827, + 3999, 0, 3827, + 3999, 0, 3827, + 3999, 0, 3827, + 3999, 0, 3825, + 3999, 0, 3825, + 3999, 0, 3825, + 3997, 0, 3825, + 3997, 0, 3823, + 3997, 0, 3823, + 3995, 0, 3821, + 3993, 0, 3819, + 3991, 0, 3817, + 3989, 0, 3815, + 3985, 0, 3809, + 3979, 0, 3805, + 3973, 0, 3797, + 3963, 0, 3785, + 3951, 0, 3771, + 3933, 1889, 3751, + 3907, 2387, 3721, + 3873, 2677, 3679, + 3819, 2899, 3617, + 3739, 3087, 3517, + 3601, 3259, 3335, + 3309, 3417, 2849, + 0, 3569, 0, + 0, 3715, 0, + 0, 3857, 0, + 0, 3995, 0, + 4095, 0, 3955, + 4095, 0, 3955, + 4095, 0, 3955, + 4095, 0, 3955, + 4095, 0, 3955, + 4095, 0, 3955, + 4095, 0, 3955, + 4095, 0, 3955, + 4095, 0, 3955, + 4095, 0, 3955, + 4095, 0, 3953, + 4095, 0, 3953, + 4095, 0, 3951, + 4095, 0, 3951, + 4095, 0, 3949, + 4095, 0, 3947, + 4095, 0, 3943, + 4095, 0, 3939, + 4095, 0, 3933, + 4095, 0, 3925, + 4095, 0, 3915, + 4081, 0, 3899, + 4063, 1987, 3879, + 4039, 2507, 3849, + 4003, 2803, 3807, + 3951, 3027, 3745, + 3869, 3217, 3643, + 3731, 3389, 3459, + 3437, 3549, 2955, + 0, 3699, 0, + 0, 3845, 0, + 0, 3987, 0, + 4095, 0, 4085, + 4095, 0, 4085, + 4095, 0, 4085, + 4095, 0, 4085, + 4095, 0, 4085, + 4095, 0, 4085, + 4095, 0, 4085, + 4095, 0, 4085, + 4095, 0, 4085, + 4095, 0, 4085, + 4095, 0, 4083, + 4095, 0, 4083, + 4095, 0, 4083, + 4095, 0, 4081, + 4095, 0, 4081, + 4095, 0, 4079, + 4095, 0, 4077, + 4095, 0, 4073, + 4095, 0, 4069, + 4095, 0, 4063, + 4095, 0, 4055, + 4095, 0, 4043, + 4095, 0, 4029, + 4095, 2093, 4009, + 4095, 2631, 3979, + 4095, 2931, 3937, + 4081, 3157, 3873, + 4001, 3347, 3771, + 3861, 3519, 3583, + 3567, 3679, 3065, + 0, 3831, 0, + 0, 3977, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2203, 4095, + 4095, 2757, 4095, + 4095, 3059, 4067, + 4095, 3287, 4003, + 4095, 3479, 3899, + 3993, 3651, 3711, + 3697, 3811, 3181, + 0, 3963, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2319, 4095, + 4095, 2885, 4095, + 4095, 3189, 4095, + 4095, 3417, 4095, + 4095, 3609, 4029, + 4095, 3783, 3839, + 3827, 3943, 3299, + 1904, 1463, 2315, + 1900, 1469, 2313, + 1893, 1475, 2311, + 1884, 1484, 2309, + 1873, 1496, 2305, + 1856, 1511, 2301, + 1833, 1530, 2293, + 1801, 1555, 2285, + 1753, 1586, 2273, + 1681, 1625, 2255, + 1561, 1672, 2233, + 1327, 1728, 2199, + 282, 1793, 2149, + 0, 1868, 2075, + 0, 1952, 1949, + 0, 2045, 1699, + 0, 2145, 0, + 0, 2253, 0, + 0, 2365, 0, + 0, 2481, 0, + 0, 2601, 0, + 0, 2723, 0, + 0, 2849, 0, + 0, 2975, 0, + 0, 3105, 0, + 0, 3233, 0, + 0, 3363, 0, + 0, 3493, 0, + 0, 3625, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 1910, 1463, 2317, + 1906, 1468, 2315, + 1899, 1475, 2313, + 1891, 1483, 2311, + 1879, 1495, 2307, + 1863, 1510, 2301, + 1840, 1530, 2295, + 1808, 1554, 2287, + 1761, 1586, 2275, + 1690, 1624, 2257, + 1574, 1671, 2235, + 1348, 1727, 2201, + 456, 1793, 2151, + 0, 1868, 2077, + 0, 1952, 1953, + 0, 2045, 1706, + 0, 2145, 138, + 0, 2251, 0, + 0, 2365, 0, + 0, 2481, 0, + 0, 2601, 0, + 0, 2723, 0, + 0, 2849, 0, + 0, 2975, 0, + 0, 3103, 0, + 0, 3233, 0, + 0, 3363, 0, + 0, 3493, 0, + 0, 3625, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 1918, 1462, 2319, + 1913, 1467, 2317, + 1907, 1474, 2315, + 1899, 1482, 2313, + 1887, 1494, 2309, + 1871, 1509, 2305, + 1849, 1529, 2297, + 1818, 1554, 2289, + 1772, 1585, 2277, + 1703, 1623, 2261, + 1590, 1670, 2237, + 1374, 1727, 2203, + 617, 1792, 2155, + 0, 1867, 2081, + 0, 1952, 1958, + 0, 2045, 1714, + 0, 2145, 344, + 0, 2251, 0, + 0, 2363, 0, + 0, 2481, 0, + 0, 2601, 0, + 0, 2723, 0, + 0, 2849, 0, + 0, 2975, 0, + 0, 3103, 0, + 0, 3233, 0, + 0, 3363, 0, + 0, 3493, 0, + 0, 3625, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 1928, 1460, 2321, + 1924, 1465, 2319, + 1918, 1472, 2317, + 1909, 1481, 2315, + 1898, 1493, 2311, + 1883, 1508, 2307, + 1861, 1528, 2301, + 1831, 1552, 2291, + 1786, 1584, 2279, + 1719, 1622, 2263, + 1611, 1670, 2241, + 1407, 1726, 2207, + 769, 1792, 2159, + 0, 1867, 2085, + 0, 1951, 1964, + 0, 2044, 1724, + 0, 2145, 525, + 0, 2251, 0, + 0, 2363, 0, + 0, 2481, 0, + 0, 2601, 0, + 0, 2723, 0, + 0, 2849, 0, + 0, 2975, 0, + 0, 3103, 0, + 0, 3233, 0, + 0, 3363, 0, + 0, 3493, 0, + 0, 3625, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 1942, 1458, 2325, + 1937, 1463, 2323, + 1931, 1470, 2321, + 1923, 1479, 2319, + 1912, 1491, 2315, + 1897, 1506, 2311, + 1877, 1526, 2305, + 1847, 1551, 2295, + 1804, 1582, 2283, + 1740, 1621, 2267, + 1637, 1668, 2245, + 1448, 1725, 2213, + 916, 1791, 2165, + 0, 1866, 2093, + 0, 1951, 1972, + 0, 2044, 1738, + 0, 2145, 690, + 0, 2251, 0, + 0, 2363, 0, + 0, 2481, 0, + 0, 2601, 0, + 0, 2723, 0, + 0, 2849, 0, + 0, 2975, 0, + 0, 3103, 0, + 0, 3233, 0, + 0, 3363, 0, + 0, 3493, 0, + 0, 3625, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 1959, 1456, 2331, + 1955, 1461, 2329, + 1949, 1468, 2327, + 1941, 1477, 2325, + 1931, 1489, 2321, + 1916, 1504, 2317, + 1896, 1524, 2309, + 1868, 1549, 2301, + 1828, 1580, 2289, + 1767, 1619, 2273, + 1670, 1667, 2251, + 1497, 1723, 2219, + 1059, 1789, 2171, + 0, 1865, 2101, + 0, 1950, 1983, + 0, 2043, 1757, + 0, 2143, 845, + 0, 2251, 0, + 0, 2363, 0, + 0, 2479, 0, + 0, 2601, 0, + 0, 2723, 0, + 0, 2849, 0, + 0, 2975, 0, + 0, 3103, 0, + 0, 3233, 0, + 0, 3363, 0, + 0, 3493, 0, + 0, 3625, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 1981, 1452, 2337, + 1977, 1457, 2335, + 1972, 1464, 2333, + 1964, 1474, 2331, + 1954, 1485, 2327, + 1941, 1501, 2323, + 1922, 1521, 2317, + 1895, 1546, 2309, + 1857, 1578, 2297, + 1800, 1617, 2281, + 1711, 1665, 2259, + 1556, 1721, 2227, + 1199, 1788, 2181, + 0, 1864, 2111, + 0, 1949, 1998, + 0, 2042, 1780, + 0, 2143, 994, + 0, 2251, 0, + 0, 2363, 0, + 0, 2479, 0, + 0, 2601, 0, + 0, 2723, 0, + 0, 2849, 0, + 0, 2975, 0, + 0, 3103, 0, + 0, 3233, 0, + 0, 3363, 0, + 0, 3493, 0, + 0, 3625, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 2009, 1448, 2345, + 2005, 1453, 2345, + 2000, 1460, 2343, + 1993, 1469, 2339, + 1984, 1481, 2337, + 1971, 1497, 2333, + 1953, 1517, 2325, + 1929, 1542, 2317, + 1893, 1574, 2307, + 1841, 1614, 2291, + 1761, 1662, 2269, + 1624, 1719, 2239, + 1337, 1786, 2193, + 0, 1862, 2125, + 0, 1947, 2016, + 0, 2041, 1809, + 0, 2141, 1138, + 0, 2249, 0, + 0, 2363, 0, + 0, 2479, 0, + 0, 2599, 0, + 0, 2723, 0, + 0, 2849, 0, + 0, 2975, 0, + 0, 3103, 0, + 0, 3233, 0, + 0, 3363, 0, + 0, 3493, 0, + 0, 3625, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 2044, 1441, 2357, + 2040, 1447, 2355, + 2036, 1454, 2353, + 2029, 1463, 2351, + 2021, 1475, 2349, + 2009, 1491, 2343, + 1993, 1511, 2337, + 1970, 1537, 2329, + 1938, 1569, 2319, + 1891, 1609, 2303, + 1819, 1658, 2283, + 1702, 1715, 2253, + 1473, 1783, 2209, + 536, 1859, 2145, + 0, 1945, 2039, + 0, 2039, 1845, + 0, 2141, 1279, + 0, 2249, 0, + 0, 2361, 0, + 0, 2479, 0, + 0, 2599, 0, + 0, 2723, 0, + 0, 2849, 0, + 0, 2975, 0, + 0, 3103, 0, + 0, 3233, 0, + 0, 3363, 0, + 0, 3493, 0, + 0, 3625, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 2087, 1433, 2371, + 2083, 1438, 2371, + 2079, 1445, 2369, + 2073, 1455, 2367, + 2065, 1467, 2363, + 2055, 1483, 2359, + 2040, 1504, 2353, + 2020, 1530, 2345, + 1991, 1563, 2335, + 1950, 1603, 2321, + 1887, 1652, 2299, + 1788, 1711, 2271, + 1609, 1779, 2229, + 1134, 1856, 2167, + 0, 1942, 2069, + 0, 2037, 1889, + 0, 2139, 1417, + 0, 2247, 0, + 0, 2361, 0, + 0, 2477, 0, + 0, 2599, 0, + 0, 2723, 0, + 0, 2847, 0, + 0, 2975, 0, + 0, 3103, 0, + 0, 3233, 0, + 0, 3363, 0, + 0, 3493, 0, + 0, 3625, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 2139, 1421, 2391, + 2135, 1427, 2389, + 2131, 1434, 2389, + 2127, 1444, 2385, + 2119, 1456, 2383, + 2111, 1473, 2379, + 2097, 1494, 2373, + 2079, 1521, 2365, + 2055, 1554, 2355, + 2018, 1595, 2341, + 1965, 1645, 2323, + 1883, 1704, 2295, + 1743, 1773, 2255, + 1444, 1851, 2197, + 0, 1938, 2105, + 0, 2034, 1943, + 0, 2137, 1554, + 0, 2245, 0, + 0, 2359, 0, + 0, 2477, 0, + 0, 2597, 0, + 0, 2721, 0, + 0, 2847, 0, + 0, 2975, 0, + 0, 3103, 0, + 0, 3233, 0, + 0, 3363, 0, + 0, 3493, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 2199, 1405, 2415, + 2197, 1411, 2415, + 2193, 1418, 2413, + 2189, 1428, 2411, + 2183, 1441, 2407, + 2175, 1458, 2403, + 2163, 1480, 2399, + 2149, 1508, 2391, + 2127, 1542, 2383, + 2097, 1584, 2369, + 2051, 1635, 2351, + 1985, 1696, 2325, + 1877, 1766, 2289, + 1675, 1845, 2235, + 1046, 1933, 2149, + 0, 2030, 2005, + 0, 2133, 1690, + 0, 2243, 0, + 0, 2357, 0, + 0, 2475, 0, + 0, 2597, 0, + 0, 2721, 0, + 0, 2847, 0, + 0, 2973, 0, + 0, 3103, 0, + 0, 3233, 0, + 0, 3363, 0, + 0, 3493, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 2269, 1382, 2447, + 2267, 1388, 2445, + 2265, 1396, 2443, + 2261, 1407, 2441, + 2255, 1421, 2439, + 2249, 1438, 2435, + 2239, 1461, 2431, + 2227, 1490, 2423, + 2209, 1526, 2415, + 2183, 1569, 2403, + 2147, 1622, 2385, + 2093, 1684, 2363, + 2010, 1756, 2329, + 1869, 1837, 2279, + 1564, 1926, 2203, + 0, 2024, 2077, + 0, 2129, 1825, + 0, 2239, 0, + 0, 2353, 0, + 0, 2473, 0, + 0, 2595, 0, + 0, 2719, 0, + 0, 2845, 0, + 0, 2973, 0, + 0, 3101, 0, + 0, 3231, 0, + 0, 3361, 0, + 0, 3493, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 2349, 1350, 2485, + 2347, 1357, 2483, + 2345, 1365, 2481, + 2343, 1377, 2481, + 2339, 1391, 2477, + 2333, 1410, 2475, + 2325, 1434, 2469, + 2313, 1465, 2463, + 2299, 1502, 2455, + 2279, 1548, 2445, + 2249, 1603, 2429, + 2207, 1668, 2407, + 2143, 1742, 2377, + 2042, 1825, 2333, + 1857, 1917, 2267, + 1353, 2016, 2159, + 0, 2123, 1959, + 0, 2233, 1343, + 0, 2351, 0, + 0, 2469, 0, + 0, 2593, 0, + 0, 2717, 0, + 0, 2845, 0, + 0, 2973, 0, + 0, 3101, 0, + 0, 3231, 0, + 0, 3361, 0, + 0, 3493, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 2439, 1303, 2531, + 2437, 1311, 2529, + 2435, 1320, 2529, + 2433, 1333, 2527, + 2429, 1349, 2525, + 2425, 1369, 2521, + 2417, 1396, 2517, + 2409, 1429, 2513, + 2397, 1469, 2505, + 2381, 1519, 2495, + 2357, 1577, 2481, + 2325, 1645, 2463, + 2277, 1723, 2435, + 2203, 1809, 2397, + 2081, 1904, 2339, + 1842, 2006, 2249, + 650, 2115, 2093, + 0, 2227, 1726, + 0, 2345, 0, + 0, 2467, 0, + 0, 2589, 0, + 0, 2715, 0, + 0, 2843, 0, + 0, 2971, 0, + 0, 3101, 0, + 0, 3231, 0, + 0, 3361, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4017, 0, + 2535, 1232, 2587, + 2535, 1241, 2585, + 2533, 1252, 2585, + 2531, 1266, 2583, + 2527, 1285, 2581, + 2523, 1309, 2579, + 2519, 1339, 2575, + 2511, 1376, 2569, + 2503, 1421, 2563, + 2489, 1476, 2555, + 2471, 1540, 2543, + 2445, 1613, 2527, + 2409, 1696, 2503, + 2355, 1787, 2469, + 2271, 1886, 2421, + 2129, 1992, 2347, + 1820, 2103, 2225, + 0, 2219, 1984, + 0, 2339, 715, + 0, 2461, 0, + 0, 2585, 0, + 0, 2713, 0, + 0, 2841, 0, + 0, 2969, 0, + 0, 3099, 0, + 0, 3229, 0, + 0, 3361, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3885, 0, + 0, 4017, 0, + 2639, 1115, 2651, + 2639, 1126, 2651, + 2637, 1141, 2649, + 2635, 1159, 2649, + 2633, 1182, 2647, + 2629, 1212, 2645, + 2625, 1249, 2641, + 2621, 1294, 2637, + 2613, 1348, 2631, + 2603, 1411, 2623, + 2589, 1484, 2613, + 2569, 1566, 2599, + 2541, 1657, 2579, + 2503, 1756, 2553, + 2443, 1861, 2513, + 2351, 1972, 2453, + 2187, 2087, 2359, + 1790, 2207, 2191, + 0, 2329, 1781, + 0, 2455, 0, + 0, 2581, 0, + 0, 2709, 0, + 0, 2837, 0, + 0, 2967, 0, + 0, 3097, 0, + 0, 3229, 0, + 0, 3359, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2749, 890, 2725, + 2749, 908, 2725, + 2747, 930, 2725, + 2745, 959, 2723, + 2743, 995, 2721, + 2741, 1039, 2719, + 2739, 1092, 2717, + 2735, 1154, 2713, + 2729, 1226, 2709, + 2721, 1307, 2703, + 2709, 1397, 2695, + 2695, 1495, 2683, + 2673, 1599, 2665, + 2645, 1710, 2643, + 2603, 1825, 2611, + 2539, 1944, 2563, + 2437, 2067, 2491, + 2253, 2191, 2373, + 1746, 2317, 2141, + 0, 2445, 1143, + 0, 2573, 0, + 0, 2703, 0, + 0, 2833, 0, + 0, 2965, 0, + 0, 3095, 0, + 0, 3227, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2863, 0, 2809, + 2863, 107, 2809, + 2863, 226, 2809, + 2861, 348, 2807, + 2859, 473, 2807, + 2857, 599, 2805, + 2855, 727, 2803, + 2851, 856, 2799, + 2847, 986, 2795, + 2841, 1116, 2791, + 2833, 1246, 2783, + 2821, 1377, 2773, + 2807, 1509, 2761, + 2785, 1640, 2741, + 2755, 1772, 2715, + 2709, 1904, 2679, + 2643, 2036, 2623, + 2533, 2167, 2539, + 2329, 2299, 2391, + 1679, 2431, 2063, + 0, 2563, 0, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2981, 0, 2901, + 2981, 0, 2901, + 2981, 0, 2901, + 2981, 0, 2899, + 2979, 0, 2899, + 2977, 0, 2897, + 2975, 0, 2895, + 2973, 0, 2893, + 2969, 0, 2891, + 2965, 568, 2887, + 2959, 908, 2881, + 2951, 1150, 2873, + 2939, 1350, 2861, + 2923, 1527, 2847, + 2901, 1690, 2827, + 2869, 1844, 2797, + 2821, 1992, 2757, + 2751, 2135, 2693, + 2635, 2275, 2595, + 2413, 2413, 2413, + 1570, 2551, 1934, + 0, 2685, 0, + 0, 2821, 0, + 0, 2955, 0, + 0, 3087, 0, + 0, 3221, 0, + 0, 3353, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3885, 0, + 0, 4017, 0, + 3103, 0, 3001, + 3103, 0, 3001, + 3103, 0, 3001, + 3103, 0, 3001, + 3101, 0, 2999, + 3101, 0, 2999, + 3099, 0, 2997, + 3097, 0, 2995, + 3095, 0, 2993, + 3091, 0, 2989, + 3087, 0, 2985, + 3079, 228, 2979, + 3071, 978, 2969, + 3059, 1310, 2959, + 3043, 1550, 2943, + 3019, 1749, 2921, + 2987, 1925, 2889, + 2939, 2087, 2843, + 2865, 2241, 2773, + 2745, 2389, 2659, + 2507, 2531, 2443, + 1368, 2673, 1669, + 0, 2811, 0, + 0, 2947, 0, + 0, 3083, 0, + 0, 3217, 0, + 0, 3351, 0, + 0, 3485, 0, + 0, 3617, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 3227, 0, 3107, + 3227, 0, 3107, + 3227, 0, 3107, + 3227, 0, 3107, + 3227, 0, 3107, + 3225, 0, 3105, + 3225, 0, 3105, + 3223, 0, 3103, + 3221, 0, 3101, + 3219, 0, 3099, + 3215, 0, 3095, + 3209, 0, 3089, + 3203, 0, 3083, + 3195, 541, 3073, + 3183, 1251, 3061, + 3165, 1579, 3045, + 3141, 1817, 3021, + 3109, 2015, 2987, + 3059, 2191, 2937, + 2983, 2353, 2861, + 2859, 2505, 2735, + 2609, 2653, 2479, + 735, 2797, 0, + 0, 2937, 0, + 0, 3075, 0, + 0, 3211, 0, + 0, 3347, 0, + 0, 3481, 0, + 0, 3615, 0, + 0, 3749, 0, + 0, 3881, 0, + 0, 4015, 0, + 3353, 0, 3219, + 3353, 0, 3219, + 3353, 0, 3219, + 3353, 0, 3219, + 3353, 0, 3219, + 3353, 0, 3217, + 3351, 0, 3217, + 3351, 0, 3215, + 3349, 0, 3215, + 3347, 0, 3213, + 3343, 0, 3209, + 3341, 0, 3205, + 3335, 0, 3201, + 3329, 0, 3193, + 3319, 0, 3185, + 3307, 1158, 3171, + 3291, 1616, 3153, + 3267, 1895, 3129, + 3233, 2113, 3093, + 3183, 2299, 3039, + 3105, 2469, 2957, + 2977, 2627, 2819, + 2715, 2777, 2523, + 0, 2923, 0, + 0, 3065, 0, + 0, 3203, 0, + 0, 3341, 0, + 0, 3477, 0, + 0, 3613, 0, + 0, 3747, 0, + 0, 3881, 0, + 0, 4013, 0, + 3481, 0, 3337, + 3481, 0, 3335, + 3481, 0, 3335, + 3481, 0, 3335, + 3481, 0, 3335, + 3481, 0, 3335, + 3479, 0, 3333, + 3479, 0, 3333, + 3477, 0, 3331, + 3475, 0, 3331, + 3473, 0, 3327, + 3471, 0, 3325, + 3467, 0, 3321, + 3463, 0, 3315, + 3455, 0, 3309, + 3447, 0, 3299, + 3435, 994, 3285, + 3417, 1660, 3267, + 3393, 1982, 3241, + 3359, 2217, 3203, + 3307, 2413, 3147, + 3229, 2589, 3061, + 3097, 2749, 2911, + 2827, 2903, 2577, + 0, 3051, 0, + 0, 3193, 0, + 0, 3333, 0, + 0, 3471, 0, + 0, 3607, 0, + 0, 3743, 0, + 0, 3877, 0, + 0, 4011, 0, + 3611, 0, 3457, + 3611, 0, 3455, + 3609, 0, 3455, + 3609, 0, 3455, + 3609, 0, 3455, + 3609, 0, 3455, + 3609, 0, 3455, + 3607, 0, 3453, + 3607, 0, 3453, + 3605, 0, 3451, + 3605, 0, 3449, + 3603, 0, 3447, + 3599, 0, 3445, + 3595, 0, 3441, + 3591, 0, 3435, + 3585, 0, 3427, + 3575, 0, 3417, + 3563, 594, 3403, + 3545, 1714, 3385, + 3521, 2077, 3357, + 3485, 2327, 3319, + 3435, 2531, 3261, + 3355, 2711, 3171, + 3221, 2875, 3011, + 2945, 3031, 2639, + 0, 3179, 0, + 0, 3323, 0, + 0, 3463, 0, + 0, 3603, 0, + 0, 3739, 0, + 0, 3875, 0, + 0, 4009, 0, + 3739, 0, 3579, + 3739, 0, 3579, + 3739, 0, 3579, + 3739, 0, 3579, + 3739, 0, 3579, + 3739, 0, 3577, + 3739, 0, 3577, + 3739, 0, 3577, + 3737, 0, 3577, + 3737, 0, 3575, + 3735, 0, 3575, + 3733, 0, 3573, + 3731, 0, 3571, + 3729, 0, 3567, + 3725, 0, 3563, + 3721, 0, 3557, + 3713, 0, 3549, + 3705, 0, 3539, + 3691, 0, 3525, + 3673, 1776, 3505, + 3649, 2179, 3479, + 3615, 2443, 3439, + 3563, 2653, 3379, + 3483, 2835, 3285, + 3347, 3003, 3119, + 3065, 3159, 2711, + 0, 3309, 0, + 0, 3453, 0, + 0, 3595, 0, + 0, 3733, 0, + 0, 3871, 0, + 0, 4007, 0, + 3869, 0, 3703, + 3869, 0, 3703, + 3869, 0, 3703, + 3869, 0, 3703, + 3869, 0, 3703, + 3869, 0, 3703, + 3869, 0, 3703, + 3869, 0, 3703, + 3869, 0, 3701, + 3867, 0, 3701, + 3867, 0, 3701, + 3865, 0, 3699, + 3863, 0, 3697, + 3861, 0, 3695, + 3859, 0, 3691, + 3855, 0, 3687, + 3851, 0, 3683, + 3843, 0, 3675, + 3835, 0, 3663, + 3821, 0, 3649, + 3803, 1849, 3629, + 3779, 2287, 3601, + 3743, 2561, 3561, + 3691, 2777, 3499, + 3611, 2963, 3403, + 3475, 3131, 3231, + 3189, 3289, 2793, + 0, 3439, 0, + 0, 3583, 0, + 0, 3725, 0, + 0, 3865, 0, + 0, 4001, 0, + 4001, 0, 3831, + 4001, 0, 3831, + 4001, 0, 3831, + 4001, 0, 3831, + 4001, 0, 3831, + 4001, 0, 3831, + 3999, 0, 3829, + 3999, 0, 3829, + 3999, 0, 3829, + 3999, 0, 3829, + 3999, 0, 3827, + 3997, 0, 3827, + 3997, 0, 3825, + 3995, 0, 3823, + 3993, 0, 3821, + 3989, 0, 3819, + 3985, 0, 3815, + 3981, 0, 3809, + 3975, 0, 3801, + 3965, 0, 3791, + 3951, 0, 3775, + 3935, 1931, 3755, + 3909, 2401, 3727, + 3873, 2683, 3685, + 3821, 2903, 3623, + 3741, 3091, 3525, + 3603, 3261, 3347, + 3313, 3419, 2883, + 0, 3569, 0, + 0, 3715, 0, + 0, 3857, 0, + 0, 3997, 0, + 4095, 0, 3959, + 4095, 0, 3959, + 4095, 0, 3959, + 4095, 0, 3959, + 4095, 0, 3959, + 4095, 0, 3959, + 4095, 0, 3959, + 4095, 0, 3957, + 4095, 0, 3957, + 4095, 0, 3957, + 4095, 0, 3957, + 4095, 0, 3955, + 4095, 0, 3955, + 4095, 0, 3953, + 4095, 0, 3951, + 4095, 0, 3949, + 4095, 0, 3947, + 4095, 0, 3943, + 4095, 0, 3937, + 4095, 0, 3929, + 4095, 0, 3917, + 4083, 0, 3903, + 4065, 2021, 3883, + 4041, 2519, 3853, + 4005, 2809, 3811, + 3951, 3031, 3749, + 3871, 3219, 3649, + 3733, 3391, 3467, + 3441, 3549, 2981, + 0, 3701, 0, + 0, 3847, 0, + 0, 3989, 0, + 4095, 0, 4087, + 4095, 0, 4087, + 4095, 0, 4087, + 4095, 0, 4087, + 4095, 0, 4087, + 4095, 0, 4087, + 4095, 0, 4087, + 4095, 0, 4087, + 4095, 0, 4087, + 4095, 0, 4087, + 4095, 0, 4087, + 4095, 0, 4085, + 4095, 0, 4085, + 4095, 0, 4083, + 4095, 0, 4083, + 4095, 0, 4081, + 4095, 0, 4079, + 4095, 0, 4075, + 4095, 0, 4071, + 4095, 0, 4065, + 4095, 0, 4057, + 4095, 0, 4047, + 4095, 0, 4031, + 4095, 2119, 4011, + 4095, 2639, 3981, + 4095, 2935, 3939, + 4083, 3159, 3877, + 4001, 3349, 3775, + 3863, 3521, 3591, + 3569, 3681, 3087, + 0, 3831, 0, + 0, 3977, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2225, 4095, + 4095, 2763, 4095, + 4095, 3063, 4069, + 4095, 3289, 4005, + 4095, 3479, 3903, + 3993, 3651, 3715, + 3699, 3811, 3197, + 0, 3963, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2335, 4095, + 4095, 2889, 4095, + 4095, 3191, 4095, + 4095, 3419, 4095, + 4095, 3611, 4031, + 4095, 3783, 3843, + 3829, 3943, 3313, + 2035, 1592, 2447, + 2032, 1596, 2445, + 2027, 1601, 2445, + 2021, 1608, 2443, + 2012, 1617, 2439, + 2000, 1629, 2435, + 1983, 1644, 2431, + 1960, 1663, 2425, + 1927, 1688, 2415, + 1879, 1719, 2403, + 1805, 1757, 2387, + 1684, 1804, 2363, + 1443, 1860, 2329, + 219, 1926, 2281, + 0, 2001, 2205, + 0, 2085, 2079, + 0, 2177, 1827, + 0, 2277, 0, + 0, 2385, 0, + 0, 2497, 0, + 0, 2613, 0, + 0, 2733, 0, + 0, 2857, 0, + 0, 2981, 0, + 0, 3109, 0, + 0, 3237, 0, + 0, 3365, 0, + 0, 3495, 0, + 0, 3625, 0, + 0, 3757, 0, + 0, 3887, 0, + 0, 4019, 0, + 2040, 1592, 2447, + 2036, 1596, 2447, + 2032, 1601, 2445, + 2025, 1607, 2443, + 2017, 1616, 2441, + 2005, 1628, 2437, + 1988, 1643, 2433, + 1965, 1662, 2425, + 1933, 1687, 2417, + 1885, 1718, 2405, + 1813, 1757, 2387, + 1693, 1804, 2365, + 1459, 1860, 2331, + 414, 1925, 2281, + 0, 2000, 2207, + 0, 2085, 2081, + 0, 2177, 1831, + 0, 2277, 16, + 0, 2385, 0, + 0, 2497, 0, + 0, 2613, 0, + 0, 2733, 0, + 0, 2857, 0, + 0, 2981, 0, + 0, 3109, 0, + 0, 3237, 0, + 0, 3365, 0, + 0, 3495, 0, + 0, 3625, 0, + 0, 3757, 0, + 0, 3887, 0, + 0, 4019, 0, + 2046, 1591, 2449, + 2042, 1595, 2449, + 2038, 1600, 2447, + 2031, 1607, 2445, + 2023, 1616, 2443, + 2011, 1627, 2439, + 1995, 1642, 2433, + 1972, 1662, 2427, + 1940, 1687, 2419, + 1894, 1718, 2407, + 1822, 1756, 2389, + 1706, 1803, 2367, + 1480, 1859, 2333, + 588, 1925, 2285, + 0, 2000, 2209, + 0, 2085, 2085, + 0, 2177, 1838, + 0, 2277, 270, + 0, 2385, 0, + 0, 2497, 0, + 0, 2613, 0, + 0, 2733, 0, + 0, 2855, 0, + 0, 2981, 0, + 0, 3107, 0, + 0, 3237, 0, + 0, 3365, 0, + 0, 3495, 0, + 0, 3625, 0, + 0, 3757, 0, + 0, 3887, 0, + 0, 4019, 0, + 2053, 1590, 2451, + 2051, 1594, 2451, + 2046, 1599, 2449, + 2039, 1606, 2447, + 2031, 1615, 2445, + 2019, 1626, 2441, + 2004, 1641, 2437, + 1981, 1661, 2429, + 1950, 1686, 2421, + 1904, 1717, 2409, + 1835, 1756, 2393, + 1722, 1803, 2369, + 1507, 1859, 2335, + 749, 1924, 2287, + 0, 2000, 2213, + 0, 2083, 2089, + 0, 2177, 1846, + 0, 2277, 476, + 0, 2383, 0, + 0, 2497, 0, + 0, 2613, 0, + 0, 2733, 0, + 0, 2855, 0, + 0, 2981, 0, + 0, 3107, 0, + 0, 3237, 0, + 0, 3365, 0, + 0, 3495, 0, + 0, 3625, 0, + 0, 3757, 0, + 0, 3887, 0, + 0, 4019, 0, + 2063, 1588, 2455, + 2061, 1592, 2453, + 2055, 1597, 2453, + 2049, 1604, 2451, + 2042, 1613, 2447, + 2030, 1625, 2443, + 2015, 1640, 2439, + 1993, 1660, 2433, + 1963, 1685, 2423, + 1918, 1716, 2411, + 1851, 1755, 2395, + 1743, 1802, 2373, + 1540, 1858, 2339, + 902, 1924, 2291, + 0, 1999, 2217, + 0, 2083, 2097, + 0, 2177, 1857, + 0, 2277, 657, + 0, 2383, 0, + 0, 2495, 0, + 0, 2613, 0, + 0, 2733, 0, + 0, 2855, 0, + 0, 2981, 0, + 0, 3107, 0, + 0, 3237, 0, + 0, 3365, 0, + 0, 3495, 0, + 0, 3625, 0, + 0, 3757, 0, + 0, 3887, 0, + 0, 4019, 0, + 2077, 1586, 2459, + 2073, 1590, 2457, + 2069, 1596, 2455, + 2063, 1602, 2453, + 2055, 1611, 2451, + 2045, 1623, 2447, + 2030, 1638, 2443, + 2009, 1658, 2437, + 1979, 1683, 2429, + 1937, 1714, 2417, + 1872, 1753, 2399, + 1769, 1801, 2377, + 1580, 1857, 2345, + 1048, 1923, 2297, + 0, 1998, 2225, + 0, 2083, 2105, + 0, 2175, 1871, + 0, 2277, 822, + 0, 2383, 0, + 0, 2495, 0, + 0, 2613, 0, + 0, 2733, 0, + 0, 2855, 0, + 0, 2981, 0, + 0, 3107, 0, + 0, 3237, 0, + 0, 3365, 0, + 0, 3495, 0, + 0, 3625, 0, + 0, 3757, 0, + 0, 3887, 0, + 0, 4019, 0, + 2095, 1584, 2463, + 2091, 1588, 2463, + 2087, 1593, 2461, + 2081, 1600, 2459, + 2073, 1609, 2457, + 2063, 1621, 2453, + 2049, 1636, 2449, + 2029, 1656, 2441, + 2000, 1681, 2433, + 1960, 1712, 2421, + 1899, 1751, 2405, + 1802, 1799, 2383, + 1630, 1855, 2351, + 1191, 1922, 2303, + 0, 1997, 2233, + 0, 2081, 2115, + 0, 2175, 1889, + 0, 2275, 977, + 0, 2383, 0, + 0, 2495, 0, + 0, 2613, 0, + 0, 2733, 0, + 0, 2855, 0, + 0, 2981, 0, + 0, 3107, 0, + 0, 3235, 0, + 0, 3365, 0, + 0, 3495, 0, + 0, 3625, 0, + 0, 3757, 0, + 0, 3887, 0, + 0, 4019, 0, + 2117, 1580, 2471, + 2113, 1584, 2469, + 2109, 1590, 2467, + 2103, 1597, 2465, + 2097, 1606, 2463, + 2087, 1618, 2459, + 2073, 1633, 2455, + 2053, 1653, 2449, + 2027, 1678, 2441, + 1989, 1710, 2429, + 1932, 1749, 2413, + 1843, 1797, 2391, + 1688, 1854, 2359, + 1331, 1920, 2313, + 0, 1996, 2243, + 0, 2081, 2129, + 0, 2175, 1912, + 0, 2275, 1126, + 0, 2383, 0, + 0, 2495, 0, + 0, 2611, 0, + 0, 2733, 0, + 0, 2855, 0, + 0, 2981, 0, + 0, 3107, 0, + 0, 3235, 0, + 0, 3365, 0, + 0, 3495, 0, + 0, 3625, 0, + 0, 3757, 0, + 0, 3887, 0, + 0, 4019, 0, + 2143, 1576, 2479, + 2141, 1580, 2477, + 2137, 1585, 2477, + 2133, 1592, 2475, + 2125, 1601, 2473, + 2117, 1613, 2469, + 2103, 1629, 2465, + 2085, 1649, 2459, + 2061, 1674, 2449, + 2025, 1706, 2439, + 1973, 1746, 2423, + 1893, 1794, 2401, + 1756, 1851, 2371, + 1469, 1918, 2325, + 0, 1994, 2257, + 0, 2079, 2147, + 0, 2173, 1941, + 0, 2273, 1270, + 0, 2381, 0, + 0, 2495, 0, + 0, 2611, 0, + 0, 2731, 0, + 0, 2855, 0, + 0, 2981, 0, + 0, 3107, 0, + 0, 3235, 0, + 0, 3365, 0, + 0, 3495, 0, + 0, 3625, 0, + 0, 3757, 0, + 0, 3887, 0, + 0, 4019, 0, + 2179, 1569, 2491, + 2175, 1573, 2489, + 2173, 1579, 2487, + 2167, 1586, 2487, + 2161, 1595, 2483, + 2153, 1607, 2481, + 2141, 1623, 2475, + 2125, 1643, 2471, + 2103, 1669, 2461, + 2069, 1701, 2451, + 2023, 1741, 2435, + 1951, 1790, 2415, + 1834, 1848, 2385, + 1605, 1915, 2341, + 668, 1991, 2277, + 0, 2077, 2171, + 0, 2171, 1977, + 0, 2273, 1411, + 0, 2381, 0, + 0, 2493, 0, + 0, 2611, 0, + 0, 2731, 0, + 0, 2855, 0, + 0, 2981, 0, + 0, 3107, 0, + 0, 3235, 0, + 0, 3365, 0, + 0, 3495, 0, + 0, 3625, 0, + 0, 3757, 0, + 0, 3887, 0, + 0, 4019, 0, + 2221, 1561, 2505, + 2219, 1565, 2505, + 2215, 1570, 2503, + 2211, 1578, 2501, + 2205, 1587, 2499, + 2197, 1599, 2495, + 2187, 1615, 2491, + 2173, 1636, 2485, + 2153, 1662, 2477, + 2123, 1695, 2467, + 2081, 1736, 2453, + 2020, 1785, 2433, + 1920, 1843, 2403, + 1741, 1911, 2361, + 1266, 1988, 2299, + 0, 2075, 2201, + 0, 2169, 2022, + 0, 2271, 1549, + 0, 2379, 0, + 0, 2493, 0, + 0, 2609, 0, + 0, 2731, 0, + 0, 2855, 0, + 0, 2979, 0, + 0, 3107, 0, + 0, 3235, 0, + 0, 3365, 0, + 0, 3495, 0, + 0, 3625, 0, + 0, 3757, 0, + 0, 3887, 0, + 0, 4019, 0, + 2273, 1549, 2525, + 2271, 1553, 2523, + 2267, 1559, 2521, + 2263, 1566, 2521, + 2259, 1576, 2519, + 2251, 1589, 2515, + 2243, 1605, 2511, + 2229, 1626, 2505, + 2211, 1653, 2497, + 2187, 1686, 2487, + 2151, 1727, 2473, + 2097, 1777, 2455, + 2015, 1837, 2427, + 1875, 1905, 2387, + 1576, 1983, 2329, + 0, 2071, 2237, + 0, 2165, 2075, + 0, 2269, 1686, + 0, 2377, 0, + 0, 2491, 0, + 0, 2609, 0, + 0, 2729, 0, + 0, 2853, 0, + 0, 2979, 0, + 0, 3107, 0, + 0, 3235, 0, + 0, 3365, 0, + 0, 3495, 0, + 0, 3625, 0, + 0, 3757, 0, + 0, 3887, 0, + 0, 4019, 0, + 2333, 1532, 2549, + 2331, 1537, 2547, + 2329, 1543, 2547, + 2325, 1550, 2545, + 2321, 1560, 2543, + 2315, 1574, 2539, + 2307, 1591, 2537, + 2295, 1612, 2531, + 2281, 1640, 2523, + 2259, 1674, 2515, + 2229, 1717, 2501, + 2183, 1768, 2483, + 2117, 1828, 2457, + 2009, 1898, 2421, + 1807, 1977, 2367, + 1178, 2065, 2283, + 0, 2161, 2137, + 0, 2265, 1822, + 0, 2375, 0, + 0, 2489, 0, + 0, 2607, 0, + 0, 2729, 0, + 0, 2853, 0, + 0, 2979, 0, + 0, 3107, 0, + 0, 3235, 0, + 0, 3365, 0, + 0, 3495, 0, + 0, 3625, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 2403, 1510, 2579, + 2401, 1514, 2579, + 2399, 1520, 2577, + 2397, 1528, 2575, + 2393, 1539, 2573, + 2389, 1553, 2571, + 2381, 1571, 2567, + 2371, 1593, 2563, + 2359, 1622, 2557, + 2341, 1658, 2547, + 2315, 1701, 2535, + 2279, 1754, 2517, + 2225, 1816, 2495, + 2143, 1888, 2461, + 2001, 1969, 2411, + 1696, 2059, 2335, + 0, 2157, 2209, + 0, 2261, 1957, + 0, 2371, 0, + 0, 2485, 0, + 0, 2605, 0, + 0, 2727, 0, + 0, 2851, 0, + 0, 2977, 0, + 0, 3105, 0, + 0, 3235, 0, + 0, 3363, 0, + 0, 3493, 0, + 0, 3625, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 2483, 1477, 2617, + 2481, 1482, 2617, + 2481, 1489, 2615, + 2477, 1497, 2615, + 2475, 1509, 2613, + 2471, 1523, 2609, + 2465, 1542, 2607, + 2457, 1566, 2603, + 2445, 1597, 2597, + 2431, 1634, 2587, + 2411, 1680, 2577, + 2381, 1735, 2561, + 2339, 1800, 2539, + 2275, 1874, 2509, + 2175, 1957, 2465, + 1990, 2049, 2399, + 1485, 2149, 2291, + 0, 2255, 2091, + 0, 2367, 1476, + 0, 2483, 0, + 0, 2603, 0, + 0, 2725, 0, + 0, 2849, 0, + 0, 2977, 0, + 0, 3105, 0, + 0, 3233, 0, + 0, 3363, 0, + 0, 3493, 0, + 0, 3625, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 2571, 1430, 2663, + 2571, 1435, 2663, + 2569, 1443, 2661, + 2567, 1452, 2661, + 2565, 1465, 2659, + 2561, 1481, 2657, + 2557, 1502, 2653, + 2549, 1528, 2649, + 2541, 1561, 2645, + 2529, 1602, 2637, + 2513, 1651, 2627, + 2489, 1709, 2613, + 2457, 1777, 2595, + 2409, 1855, 2567, + 2335, 1941, 2529, + 2213, 2036, 2471, + 1974, 2139, 2381, + 782, 2247, 2225, + 0, 2359, 1859, + 0, 2477, 0, + 0, 2599, 0, + 0, 2721, 0, + 0, 2847, 0, + 0, 2975, 0, + 0, 3103, 0, + 0, 3233, 0, + 0, 3363, 0, + 0, 3493, 0, + 0, 3625, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 2669, 1358, 2719, + 2667, 1364, 2719, + 2667, 1373, 2717, + 2665, 1384, 2717, + 2663, 1398, 2715, + 2659, 1417, 2713, + 2655, 1441, 2711, + 2651, 1471, 2707, + 2643, 1508, 2703, + 2635, 1553, 2695, + 2621, 1608, 2687, + 2603, 1672, 2675, + 2577, 1745, 2659, + 2541, 1828, 2635, + 2487, 1919, 2601, + 2405, 2018, 2553, + 2261, 2123, 2479, + 1953, 2235, 2357, + 0, 2351, 2115, + 0, 2471, 847, + 0, 2593, 0, + 0, 2717, 0, + 0, 2845, 0, + 0, 2973, 0, + 0, 3101, 0, + 0, 3231, 0, + 0, 3361, 0, + 0, 3493, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 2771, 1239, 2783, + 2771, 1248, 2783, + 2771, 1259, 2783, + 2769, 1273, 2781, + 2767, 1291, 2781, + 2765, 1315, 2779, + 2763, 1344, 2777, + 2757, 1381, 2773, + 2753, 1426, 2769, + 2745, 1480, 2763, + 2735, 1543, 2757, + 2721, 1616, 2745, + 2701, 1698, 2731, + 2673, 1789, 2711, + 2635, 1888, 2685, + 2575, 1993, 2645, + 2483, 2105, 2585, + 2319, 2219, 2491, + 1922, 2339, 2323, + 0, 2461, 1913, + 0, 2587, 0, + 0, 2713, 0, + 0, 2841, 0, + 0, 2969, 0, + 0, 3099, 0, + 0, 3229, 0, + 0, 3361, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4017, 0, + 2881, 1008, 2859, + 2881, 1022, 2857, + 2881, 1039, 2857, + 2879, 1062, 2857, + 2877, 1091, 2855, + 2877, 1127, 2853, + 2873, 1171, 2851, + 2871, 1224, 2849, + 2867, 1286, 2845, + 2861, 1358, 2841, + 2853, 1439, 2835, + 2841, 1529, 2827, + 2827, 1627, 2815, + 2807, 1731, 2799, + 2777, 1842, 2775, + 2735, 1957, 2743, + 2671, 2077, 2695, + 2569, 2199, 2623, + 2385, 2323, 2505, + 1878, 2449, 2273, + 0, 2577, 1276, + 0, 2705, 0, + 0, 2835, 0, + 0, 2965, 0, + 0, 3097, 0, + 0, 3227, 0, + 0, 3359, 0, + 0, 3491, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 2995, 13, 2941, + 2995, 124, 2941, + 2995, 239, 2941, + 2995, 358, 2941, + 2993, 481, 2939, + 2991, 605, 2939, + 2989, 731, 2937, + 2987, 859, 2935, + 2985, 988, 2931, + 2979, 1117, 2927, + 2973, 1248, 2923, + 2965, 1378, 2915, + 2955, 1510, 2905, + 2939, 1641, 2893, + 2917, 1772, 2873, + 2887, 1904, 2847, + 2841, 2036, 2811, + 2775, 2167, 2755, + 2665, 2299, 2671, + 2461, 2431, 2523, + 1811, 2563, 2195, + 0, 2695, 0, + 0, 2827, 0, + 0, 2959, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 3115, 0, 3035, + 3115, 0, 3033, + 3113, 0, 3033, + 3113, 0, 3033, + 3113, 0, 3033, + 3111, 0, 3031, + 3109, 0, 3029, + 3107, 0, 3029, + 3105, 0, 3025, + 3101, 0, 3023, + 3097, 700, 3019, + 3091, 1040, 3013, + 3083, 1282, 3005, + 3071, 1482, 2993, + 3055, 1659, 2979, + 3033, 1822, 2959, + 3001, 1976, 2931, + 2955, 2123, 2889, + 2883, 2267, 2825, + 2769, 2407, 2727, + 2545, 2545, 2545, + 1703, 2683, 2065, + 0, 2817, 0, + 0, 2953, 0, + 0, 3087, 0, + 0, 3221, 0, + 0, 3353, 0, + 0, 3487, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4017, 0, + 3237, 0, 3133, + 3235, 0, 3133, + 3235, 0, 3133, + 3235, 0, 3133, + 3235, 0, 3133, + 3233, 0, 3131, + 3233, 0, 3131, + 3231, 0, 3129, + 3229, 0, 3127, + 3227, 0, 3125, + 3223, 0, 3121, + 3219, 0, 3117, + 3211, 360, 3111, + 3203, 1109, 3101, + 3191, 1442, 3091, + 3175, 1682, 3075, + 3151, 1881, 3053, + 3119, 2057, 3021, + 3071, 2219, 2975, + 2997, 2373, 2905, + 2877, 2521, 2791, + 2639, 2663, 2575, + 1500, 2805, 1801, + 0, 2943, 0, + 0, 3079, 0, + 0, 3215, 0, + 0, 3349, 0, + 0, 3483, 0, + 0, 3617, 0, + 0, 3749, 0, + 0, 3883, 0, + 0, 4015, 0, + 3361, 0, 3241, + 3359, 0, 3239, + 3359, 0, 3239, + 3359, 0, 3239, + 3359, 0, 3239, + 3359, 0, 3239, + 3357, 0, 3237, + 3357, 0, 3237, + 3355, 0, 3235, + 3353, 0, 3233, + 3351, 0, 3231, + 3347, 0, 3227, + 3341, 0, 3221, + 3335, 0, 3215, + 3327, 673, 3207, + 3315, 1383, 3193, + 3297, 1711, 3177, + 3273, 1949, 3153, + 3241, 2147, 3119, + 3191, 2323, 3069, + 3115, 2485, 2993, + 2991, 2637, 2867, + 2741, 2785, 2611, + 867, 2929, 0, + 0, 3069, 0, + 0, 3207, 0, + 0, 3343, 0, + 0, 3479, 0, + 0, 3613, 0, + 0, 3747, 0, + 0, 3881, 0, + 0, 4013, 0, + 3487, 0, 3351, + 3487, 0, 3351, + 3485, 0, 3351, + 3485, 0, 3351, + 3485, 0, 3351, + 3485, 0, 3351, + 3485, 0, 3349, + 3483, 0, 3349, + 3483, 0, 3347, + 3481, 0, 3347, + 3479, 0, 3345, + 3475, 0, 3341, + 3473, 0, 3337, + 3467, 0, 3333, + 3461, 0, 3325, + 3451, 0, 3317, + 3439, 1290, 3303, + 3423, 1748, 3285, + 3399, 2027, 3261, + 3365, 2245, 3225, + 3315, 2431, 3171, + 3237, 2601, 3091, + 3109, 2759, 2951, + 2847, 2909, 2655, + 0, 3055, 0, + 0, 3197, 0, + 0, 3335, 0, + 0, 3473, 0, + 0, 3609, 0, + 0, 3745, 0, + 0, 3879, 0, + 0, 4013, 0, + 3613, 0, 3469, + 3613, 0, 3469, + 3613, 0, 3469, + 3613, 0, 3467, + 3613, 0, 3467, + 3613, 0, 3467, + 3613, 0, 3467, + 3611, 0, 3465, + 3611, 0, 3465, + 3609, 0, 3463, + 3609, 0, 3463, + 3607, 0, 3461, + 3603, 0, 3457, + 3599, 0, 3453, + 3595, 0, 3447, + 3587, 0, 3441, + 3579, 0, 3431, + 3567, 1125, 3417, + 3549, 1792, 3399, + 3525, 2113, 3373, + 3491, 2349, 3335, + 3439, 2545, 3281, + 3361, 2721, 3193, + 3231, 2883, 3043, + 2961, 3035, 2709, + 0, 3183, 0, + 0, 3325, 0, + 0, 3465, 0, + 0, 3603, 0, + 0, 3739, 0, + 0, 3875, 0, + 0, 4009, 0, + 3743, 0, 3589, + 3743, 0, 3589, + 3743, 0, 3589, + 3743, 0, 3587, + 3741, 0, 3587, + 3741, 0, 3587, + 3741, 0, 3587, + 3741, 0, 3587, + 3741, 0, 3585, + 3739, 0, 3585, + 3739, 0, 3583, + 3737, 0, 3581, + 3735, 0, 3579, + 3731, 0, 3577, + 3729, 0, 3573, + 3723, 0, 3567, + 3717, 0, 3559, + 3707, 0, 3549, + 3695, 726, 3537, + 3677, 1846, 3517, + 3653, 2209, 3489, + 3617, 2459, 3451, + 3567, 2663, 3393, + 3487, 2843, 3303, + 3353, 3007, 3145, + 3077, 3163, 2771, + 0, 3311, 0, + 0, 3455, 0, + 0, 3595, 0, + 0, 3735, 0, + 0, 3871, 0, + 0, 4007, 0, + 3871, 0, 3711, + 3871, 0, 3711, + 3871, 0, 3711, + 3871, 0, 3711, + 3871, 0, 3711, + 3871, 0, 3711, + 3871, 0, 3711, + 3871, 0, 3709, + 3871, 0, 3709, + 3869, 0, 3709, + 3869, 0, 3707, + 3867, 0, 3707, + 3867, 0, 3705, + 3863, 0, 3703, + 3861, 0, 3699, + 3857, 0, 3695, + 3853, 0, 3689, + 3845, 0, 3683, + 3837, 0, 3671, + 3823, 0, 3657, + 3807, 1909, 3637, + 3781, 2311, 3611, + 3747, 2575, 3571, + 3695, 2785, 3511, + 3615, 2969, 3417, + 3479, 3135, 3251, + 3197, 3291, 2843, + 0, 3441, 0, + 0, 3585, 0, + 0, 3727, 0, + 0, 3865, 0, + 0, 4003, 0, + 4003, 0, 3837, + 4003, 0, 3835, + 4001, 0, 3835, + 4001, 0, 3835, + 4001, 0, 3835, + 4001, 0, 3835, + 4001, 0, 3835, + 4001, 0, 3835, + 4001, 0, 3835, + 4001, 0, 3835, + 3999, 0, 3833, + 3999, 0, 3833, + 3997, 0, 3831, + 3997, 0, 3829, + 3995, 0, 3827, + 3991, 0, 3825, + 3987, 0, 3819, + 3983, 0, 3815, + 3975, 0, 3807, + 3967, 0, 3797, + 3953, 0, 3781, + 3935, 1981, 3761, + 3911, 2419, 3733, + 3875, 2693, 3693, + 3823, 2909, 3633, + 3743, 3095, 3535, + 3607, 3263, 3363, + 3321, 3421, 2925, + 0, 3571, 0, + 0, 3715, 0, + 0, 3857, 0, + 0, 3997, 0, + 4095, 0, 3963, + 4095, 0, 3963, + 4095, 0, 3963, + 4095, 0, 3963, + 4095, 0, 3963, + 4095, 0, 3963, + 4095, 0, 3963, + 4095, 0, 3963, + 4095, 0, 3961, + 4095, 0, 3961, + 4095, 0, 3961, + 4095, 0, 3961, + 4095, 0, 3959, + 4095, 0, 3957, + 4095, 0, 3957, + 4095, 0, 3953, + 4095, 0, 3951, + 4095, 0, 3947, + 4095, 0, 3941, + 4095, 0, 3933, + 4095, 0, 3923, + 4083, 0, 3907, + 4067, 2063, 3887, + 4041, 2533, 3859, + 4005, 2815, 3817, + 3953, 3035, 3755, + 3873, 3223, 3657, + 3735, 3393, 3479, + 3447, 3551, 3015, + 0, 3701, 0, + 0, 3847, 0, + 0, 3989, 0, + 4095, 0, 4091, + 4095, 0, 4091, + 4095, 0, 4091, + 4095, 0, 4091, + 4095, 0, 4091, + 4095, 0, 4091, + 4095, 0, 4091, + 4095, 0, 4091, + 4095, 0, 4091, + 4095, 0, 4089, + 4095, 0, 4089, + 4095, 0, 4089, + 4095, 0, 4089, + 4095, 0, 4087, + 4095, 0, 4085, + 4095, 0, 4085, + 4095, 0, 4081, + 4095, 0, 4079, + 4095, 0, 4075, + 4095, 0, 4069, + 4095, 0, 4061, + 4095, 0, 4049, + 4095, 0, 4035, + 4095, 2153, 4015, + 4095, 2651, 3985, + 4095, 2941, 3945, + 4085, 3163, 3881, + 4003, 3351, 3781, + 3865, 3523, 3599, + 3573, 3681, 3115, + 0, 3833, 0, + 0, 3979, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2251, 4095, + 4095, 2771, 4095, + 4095, 3067, 4071, + 4095, 3291, 4009, + 4095, 3481, 3907, + 3995, 3653, 3723, + 3701, 3813, 3219, + 0, 3963, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2357, 4095, + 4095, 2895, 4095, + 4095, 3195, 4095, + 4095, 3421, 4095, + 4095, 3611, 4035, + 4095, 3783, 3847, + 3831, 3943, 3329, + 2167, 1722, 2579, + 2165, 1725, 2577, + 2161, 1729, 2577, + 2155, 1734, 2575, + 2149, 1741, 2573, + 2141, 1749, 2571, + 2129, 1761, 2567, + 2111, 1776, 2563, + 2089, 1795, 2555, + 2055, 1820, 2547, + 2006, 1851, 2535, + 1932, 1890, 2517, + 1809, 1937, 2493, + 1563, 1992, 2461, + 119, 2057, 2411, + 0, 2133, 2335, + 0, 2217, 2209, + 0, 2309, 1955, + 0, 2409, 0, + 0, 2517, 0, + 0, 2629, 0, + 0, 2745, 0, + 0, 2865, 0, + 0, 2989, 0, + 0, 3113, 0, + 0, 3241, 0, + 0, 3369, 0, + 0, 3497, 0, + 0, 3627, 0, + 0, 3757, 0, + 0, 3889, 0, + 0, 4019, 0, + 2171, 1722, 2579, + 2167, 1724, 2579, + 2165, 1728, 2577, + 2159, 1733, 2577, + 2153, 1740, 2575, + 2145, 1749, 2571, + 2133, 1761, 2569, + 2115, 1776, 2563, + 2093, 1795, 2557, + 2059, 1820, 2547, + 2011, 1851, 2535, + 1938, 1889, 2519, + 1816, 1936, 2495, + 1575, 1992, 2461, + 351, 2057, 2413, + 0, 2133, 2337, + 0, 2217, 2211, + 0, 2309, 1959, + 0, 2409, 0, + 0, 2517, 0, + 0, 2629, 0, + 0, 2745, 0, + 0, 2865, 0, + 0, 2989, 0, + 0, 3113, 0, + 0, 3241, 0, + 0, 3369, 0, + 0, 3497, 0, + 0, 3627, 0, + 0, 3757, 0, + 0, 3889, 0, + 0, 4019, 0, + 2175, 1721, 2581, + 2173, 1724, 2581, + 2169, 1728, 2579, + 2163, 1733, 2577, + 2157, 1740, 2575, + 2149, 1748, 2573, + 2137, 1760, 2569, + 2121, 1775, 2565, + 2097, 1795, 2557, + 2065, 1819, 2549, + 2017, 1850, 2537, + 1945, 1889, 2519, + 1825, 1936, 2497, + 1592, 1992, 2463, + 546, 2057, 2413, + 0, 2133, 2339, + 0, 2217, 2213, + 0, 2309, 1964, + 0, 2409, 148, + 0, 2517, 0, + 0, 2629, 0, + 0, 2745, 0, + 0, 2865, 0, + 0, 2989, 0, + 0, 3113, 0, + 0, 3241, 0, + 0, 3369, 0, + 0, 3497, 0, + 0, 3627, 0, + 0, 3757, 0, + 0, 3889, 0, + 0, 4019, 0, + 2181, 1720, 2583, + 2177, 1723, 2581, + 2175, 1727, 2581, + 2169, 1732, 2579, + 2163, 1739, 2577, + 2155, 1748, 2575, + 2143, 1759, 2571, + 2127, 1774, 2567, + 2105, 1794, 2559, + 2073, 1819, 2551, + 2026, 1850, 2539, + 1955, 1888, 2521, + 1838, 1935, 2499, + 1612, 1991, 2465, + 720, 2057, 2417, + 0, 2133, 2341, + 0, 2217, 2217, + 0, 2309, 1970, + 0, 2409, 403, + 0, 2517, 0, + 0, 2629, 0, + 0, 2745, 0, + 0, 2865, 0, + 0, 2989, 0, + 0, 3113, 0, + 0, 3241, 0, + 0, 3369, 0, + 0, 3497, 0, + 0, 3627, 0, + 0, 3757, 0, + 0, 3889, 0, + 0, 4019, 0, + 2189, 1719, 2585, + 2185, 1722, 2583, + 2183, 1726, 2583, + 2177, 1731, 2581, + 2171, 1738, 2579, + 2163, 1747, 2577, + 2151, 1758, 2573, + 2135, 1774, 2569, + 2113, 1793, 2561, + 2083, 1818, 2553, + 2036, 1849, 2541, + 1967, 1888, 2525, + 1854, 1935, 2501, + 1639, 1991, 2467, + 881, 2057, 2419, + 0, 2131, 2345, + 0, 2217, 2223, + 0, 2309, 1978, + 0, 2409, 608, + 0, 2515, 0, + 0, 2629, 0, + 0, 2745, 0, + 0, 2865, 0, + 0, 2989, 0, + 0, 3113, 0, + 0, 3241, 0, + 0, 3369, 0, + 0, 3497, 0, + 0, 3627, 0, + 0, 3757, 0, + 0, 3889, 0, + 0, 4019, 0, + 2199, 1718, 2587, + 2195, 1721, 2587, + 2193, 1724, 2585, + 2189, 1730, 2585, + 2181, 1736, 2583, + 2173, 1745, 2579, + 2163, 1757, 2577, + 2147, 1772, 2571, + 2125, 1792, 2565, + 2095, 1817, 2557, + 2051, 1848, 2545, + 1984, 1887, 2527, + 1875, 1934, 2505, + 1672, 1990, 2471, + 1033, 2055, 2423, + 0, 2131, 2349, + 0, 2215, 2229, + 0, 2309, 1989, + 0, 2409, 789, + 0, 2515, 0, + 0, 2627, 0, + 0, 2745, 0, + 0, 2865, 0, + 0, 2987, 0, + 0, 3113, 0, + 0, 3241, 0, + 0, 3369, 0, + 0, 3497, 0, + 0, 3627, 0, + 0, 3757, 0, + 0, 3889, 0, + 0, 4019, 0, + 2211, 1716, 2591, + 2209, 1719, 2591, + 2205, 1723, 2589, + 2201, 1728, 2587, + 2195, 1735, 2587, + 2187, 1744, 2583, + 2177, 1755, 2579, + 2161, 1771, 2575, + 2141, 1790, 2569, + 2111, 1815, 2561, + 2069, 1847, 2549, + 2004, 1885, 2531, + 1901, 1933, 2509, + 1712, 1989, 2477, + 1180, 2055, 2429, + 0, 2131, 2357, + 0, 2215, 2237, + 0, 2307, 2003, + 0, 2409, 954, + 0, 2515, 0, + 0, 2627, 0, + 0, 2745, 0, + 0, 2865, 0, + 0, 2987, 0, + 0, 3113, 0, + 0, 3239, 0, + 0, 3369, 0, + 0, 3497, 0, + 0, 3627, 0, + 0, 3757, 0, + 0, 3889, 0, + 0, 4019, 0, + 2229, 1713, 2597, + 2227, 1716, 2595, + 2223, 1720, 2595, + 2219, 1725, 2593, + 2213, 1732, 2591, + 2205, 1741, 2589, + 2195, 1753, 2585, + 2181, 1768, 2581, + 2161, 1788, 2575, + 2133, 1813, 2565, + 2091, 1845, 2553, + 2031, 1884, 2537, + 1935, 1931, 2515, + 1762, 1988, 2483, + 1323, 2053, 2435, + 0, 2129, 2365, + 0, 2215, 2247, + 0, 2307, 2021, + 0, 2407, 1109, + 0, 2515, 0, + 0, 2627, 0, + 0, 2745, 0, + 0, 2865, 0, + 0, 2987, 0, + 0, 3113, 0, + 0, 3239, 0, + 0, 3369, 0, + 0, 3497, 0, + 0, 3627, 0, + 0, 3757, 0, + 0, 3889, 0, + 0, 4019, 0, + 2251, 1710, 2603, + 2249, 1713, 2603, + 2245, 1716, 2601, + 2241, 1722, 2599, + 2235, 1729, 2597, + 2229, 1738, 2595, + 2219, 1750, 2591, + 2205, 1765, 2587, + 2185, 1785, 2581, + 2159, 1810, 2573, + 2121, 1842, 2561, + 2065, 1881, 2545, + 1975, 1929, 2523, + 1820, 1986, 2491, + 1463, 2053, 2445, + 0, 2127, 2375, + 0, 2213, 2261, + 0, 2307, 2044, + 0, 2407, 1258, + 0, 2515, 0, + 0, 2627, 0, + 0, 2743, 0, + 0, 2865, 0, + 0, 2987, 0, + 0, 3113, 0, + 0, 3239, 0, + 0, 3367, 0, + 0, 3497, 0, + 0, 3627, 0, + 0, 3757, 0, + 0, 3889, 0, + 0, 4019, 0, + 2279, 1705, 2611, + 2275, 1708, 2611, + 2273, 1712, 2609, + 2269, 1717, 2609, + 2265, 1724, 2607, + 2257, 1733, 2605, + 2249, 1745, 2601, + 2235, 1761, 2597, + 2217, 1781, 2591, + 2193, 1806, 2581, + 2157, 1838, 2571, + 2105, 1878, 2555, + 2025, 1926, 2533, + 1888, 1983, 2503, + 1601, 2049, 2457, + 0, 2127, 2389, + 0, 2211, 2281, + 0, 2305, 2073, + 0, 2407, 1402, + 0, 2513, 0, + 0, 2627, 0, + 0, 2743, 0, + 0, 2863, 0, + 0, 2987, 0, + 0, 3113, 0, + 0, 3239, 0, + 0, 3367, 0, + 0, 3497, 0, + 0, 3627, 0, + 0, 3757, 0, + 0, 3889, 0, + 0, 4019, 0, + 2313, 1698, 2623, + 2311, 1701, 2623, + 2309, 1706, 2621, + 2305, 1711, 2619, + 2299, 1718, 2619, + 2293, 1727, 2615, + 2285, 1739, 2613, + 2273, 1755, 2609, + 2257, 1776, 2603, + 2235, 1801, 2595, + 2203, 1834, 2583, + 2155, 1874, 2567, + 2083, 1922, 2547, + 1966, 1980, 2517, + 1738, 2047, 2473, + 801, 2123, 2409, + 0, 2209, 2303, + 0, 2303, 2109, + 0, 2405, 1543, + 0, 2513, 0, + 0, 2625, 0, + 0, 2743, 0, + 0, 2863, 0, + 0, 2987, 0, + 0, 3113, 0, + 0, 3239, 0, + 0, 3367, 0, + 0, 3497, 0, + 0, 3627, 0, + 0, 3757, 0, + 0, 3889, 0, + 0, 4019, 0, + 2355, 1690, 2637, + 2353, 1693, 2637, + 2351, 1697, 2637, + 2347, 1702, 2635, + 2343, 1710, 2633, + 2337, 1719, 2631, + 2329, 1732, 2627, + 2319, 1748, 2623, + 2305, 1768, 2617, + 2285, 1794, 2609, + 2255, 1827, 2599, + 2213, 1868, 2585, + 2151, 1917, 2565, + 2053, 1975, 2535, + 1873, 2043, 2495, + 1398, 2121, 2431, + 0, 2207, 2333, + 0, 2301, 2153, + 0, 2403, 1682, + 0, 2511, 0, + 0, 2625, 0, + 0, 2741, 0, + 0, 2863, 0, + 0, 2987, 0, + 0, 3111, 0, + 0, 3239, 0, + 0, 3367, 0, + 0, 3497, 0, + 0, 3627, 0, + 0, 3757, 0, + 0, 3889, 0, + 0, 4019, 0, + 2407, 1678, 2657, + 2405, 1681, 2657, + 2403, 1685, 2655, + 2399, 1691, 2655, + 2395, 1698, 2653, + 2391, 1708, 2651, + 2383, 1721, 2647, + 2375, 1737, 2643, + 2361, 1758, 2637, + 2343, 1785, 2631, + 2319, 1818, 2619, + 2283, 1860, 2605, + 2229, 1909, 2587, + 2147, 1969, 2559, + 2007, 2037, 2521, + 1708, 2115, 2461, + 0, 2203, 2369, + 0, 2297, 2207, + 0, 2401, 1818, + 0, 2509, 0, + 0, 2623, 0, + 0, 2741, 0, + 0, 2861, 0, + 0, 2985, 0, + 0, 3111, 0, + 0, 3239, 0, + 0, 3367, 0, + 0, 3497, 0, + 0, 3627, 0, + 0, 3757, 0, + 0, 3889, 0, + 0, 4019, 0, + 2467, 1661, 2681, + 2465, 1665, 2681, + 2463, 1669, 2679, + 2461, 1675, 2679, + 2457, 1683, 2677, + 2453, 1693, 2675, + 2447, 1706, 2673, + 2439, 1723, 2669, + 2427, 1744, 2663, + 2413, 1772, 2655, + 2391, 1806, 2647, + 2361, 1849, 2633, + 2317, 1900, 2615, + 2249, 1960, 2589, + 2141, 2030, 2553, + 1939, 2109, 2499, + 1310, 2197, 2415, + 0, 2293, 2269, + 0, 2397, 1954, + 0, 2507, 0, + 0, 2621, 0, + 0, 2739, 0, + 0, 2861, 0, + 0, 2985, 0, + 0, 3111, 0, + 0, 3239, 0, + 0, 3367, 0, + 0, 3497, 0, + 0, 3627, 0, + 0, 3757, 0, + 0, 3889, 0, + 0, 4019, 0, + 2537, 1638, 2711, + 2535, 1642, 2711, + 2535, 1646, 2711, + 2531, 1653, 2709, + 2529, 1661, 2707, + 2525, 1671, 2705, + 2521, 1685, 2703, + 2513, 1703, 2699, + 2503, 1725, 2695, + 2491, 1754, 2689, + 2473, 1790, 2679, + 2447, 1834, 2667, + 2411, 1886, 2651, + 2357, 1948, 2627, + 2275, 2020, 2593, + 2133, 2101, 2543, + 1828, 2191, 2467, + 0, 2289, 2341, + 0, 2393, 2089, + 0, 2503, 0, + 0, 2619, 0, + 0, 2737, 0, + 0, 2859, 0, + 0, 2983, 0, + 0, 3109, 0, + 0, 3237, 0, + 0, 3367, 0, + 0, 3495, 0, + 0, 3627, 0, + 0, 3757, 0, + 0, 3887, 0, + 0, 4019, 0, + 2617, 1606, 2749, + 2615, 1609, 2749, + 2613, 1614, 2749, + 2613, 1621, 2747, + 2609, 1630, 2747, + 2607, 1641, 2745, + 2603, 1656, 2741, + 2597, 1674, 2739, + 2589, 1699, 2735, + 2577, 1729, 2729, + 2563, 1767, 2719, + 2543, 1813, 2709, + 2513, 1868, 2693, + 2471, 1932, 2671, + 2407, 2006, 2641, + 2307, 2089, 2597, + 2121, 2181, 2531, + 1617, 2281, 2423, + 0, 2387, 2223, + 0, 2499, 1608, + 0, 2615, 0, + 0, 2735, 0, + 0, 2857, 0, + 0, 2981, 0, + 0, 3109, 0, + 0, 3237, 0, + 0, 3365, 0, + 0, 3495, 0, + 0, 3625, 0, + 0, 3757, 0, + 0, 3887, 0, + 0, 4019, 0, + 2705, 1558, 2797, + 2703, 1562, 2795, + 2703, 1568, 2795, + 2701, 1575, 2795, + 2699, 1584, 2793, + 2697, 1597, 2791, + 2693, 1613, 2789, + 2689, 1634, 2787, + 2683, 1660, 2781, + 2673, 1693, 2777, + 2661, 1734, 2769, + 2645, 1783, 2759, + 2621, 1841, 2745, + 2589, 1909, 2727, + 2541, 1987, 2699, + 2467, 2073, 2661, + 2345, 2169, 2603, + 2107, 2271, 2513, + 914, 2379, 2357, + 0, 2491, 1991, + 0, 2609, 0, + 0, 2731, 0, + 0, 2853, 0, + 0, 2979, 0, + 0, 3107, 0, + 0, 3235, 0, + 0, 3365, 0, + 0, 3495, 0, + 0, 3625, 0, + 0, 3757, 0, + 0, 3887, 0, + 0, 4019, 0, + 2801, 1485, 2851, + 2801, 1490, 2851, + 2799, 1496, 2851, + 2799, 1505, 2849, + 2797, 1516, 2849, + 2795, 1531, 2847, + 2791, 1549, 2845, + 2787, 1573, 2843, + 2783, 1603, 2839, + 2775, 1640, 2835, + 2767, 1686, 2827, + 2753, 1740, 2819, + 2735, 1804, 2807, + 2709, 1877, 2791, + 2673, 1960, 2767, + 2619, 2051, 2735, + 2537, 2151, 2685, + 2393, 2255, 2613, + 2085, 2367, 2489, + 0, 2483, 2249, + 0, 2603, 980, + 0, 2725, 0, + 0, 2851, 0, + 0, 2977, 0, + 0, 3105, 0, + 0, 3233, 0, + 0, 3363, 0, + 0, 3493, 0, + 0, 3625, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 2905, 1365, 2917, + 2903, 1371, 2915, + 2903, 1380, 2915, + 2903, 1391, 2915, + 2901, 1405, 2913, + 2899, 1423, 2913, + 2897, 1447, 2911, + 2895, 1476, 2909, + 2891, 1513, 2905, + 2885, 1558, 2901, + 2877, 1612, 2895, + 2867, 1675, 2889, + 2853, 1748, 2877, + 2833, 1830, 2863, + 2805, 1921, 2845, + 2767, 2020, 2817, + 2707, 2125, 2777, + 2615, 2237, 2717, + 2451, 2351, 2623, + 2055, 2471, 2455, + 0, 2593, 2045, + 0, 2719, 0, + 0, 2845, 0, + 0, 2973, 0, + 0, 3101, 0, + 0, 3231, 0, + 0, 3361, 0, + 0, 3493, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 3013, 1129, 2991, + 3013, 1140, 2991, + 3013, 1154, 2989, + 3013, 1172, 2989, + 3011, 1194, 2989, + 3009, 1223, 2987, + 3009, 1259, 2987, + 3005, 1303, 2985, + 3003, 1356, 2981, + 2999, 1418, 2979, + 2993, 1490, 2973, + 2985, 1571, 2967, + 2973, 1661, 2959, + 2959, 1759, 2947, + 2939, 1864, 2931, + 2909, 1974, 2907, + 2867, 2089, 2875, + 2803, 2209, 2827, + 2701, 2331, 2755, + 2517, 2455, 2637, + 2010, 2581, 2405, + 0, 2709, 1408, + 0, 2837, 0, + 0, 2967, 0, + 0, 3097, 0, + 0, 3229, 0, + 0, 3359, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 3129, 41, 3075, + 3129, 145, 3075, + 3127, 256, 3073, + 3127, 371, 3073, + 3127, 491, 3073, + 3125, 613, 3071, + 3123, 737, 3071, + 3123, 864, 3069, + 3119, 991, 3067, + 3117, 1120, 3063, + 3111, 1250, 3059, + 3105, 1380, 3055, + 3097, 1511, 3047, + 3087, 1642, 3037, + 3071, 1773, 3025, + 3049, 1905, 3007, + 3019, 2036, 2981, + 2973, 2169, 2943, + 2907, 2299, 2889, + 2797, 2431, 2803, + 2593, 2563, 2655, + 1943, 2695, 2327, + 0, 2827, 0, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 3247, 0, 3167, + 3247, 0, 3167, + 3247, 0, 3165, + 3245, 0, 3165, + 3245, 0, 3165, + 3245, 0, 3165, + 3243, 0, 3163, + 3241, 0, 3161, + 3239, 0, 3161, + 3237, 0, 3157, + 3233, 22, 3155, + 3229, 832, 3151, + 3223, 1172, 3145, + 3215, 1414, 3137, + 3203, 1614, 3127, + 3187, 1791, 3111, + 3165, 1954, 3091, + 3133, 2109, 3063, + 3087, 2255, 3021, + 3015, 2399, 2959, + 2901, 2539, 2859, + 2677, 2677, 2677, + 1835, 2815, 2197, + 0, 2951, 0, + 0, 3085, 0, + 0, 3219, 0, + 0, 3353, 0, + 0, 3485, 0, + 0, 3619, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 3369, 0, 3267, + 3369, 0, 3265, + 3367, 0, 3265, + 3367, 0, 3265, + 3367, 0, 3265, + 3367, 0, 3265, + 3365, 0, 3263, + 3365, 0, 3263, + 3363, 0, 3261, + 3361, 0, 3259, + 3359, 0, 3257, + 3355, 0, 3253, + 3351, 0, 3249, + 3343, 492, 3243, + 3335, 1242, 3235, + 3323, 1575, 3223, + 3307, 1814, 3207, + 3283, 2013, 3185, + 3251, 2189, 3153, + 3203, 2351, 3107, + 3129, 2505, 3037, + 3009, 2653, 2925, + 2771, 2797, 2707, + 1632, 2937, 1933, + 0, 3075, 0, + 0, 3211, 0, + 0, 3347, 0, + 0, 3481, 0, + 0, 3615, 0, + 0, 3749, 0, + 0, 3881, 0, + 0, 4015, 0, + 3493, 0, 3373, + 3493, 0, 3373, + 3493, 0, 3373, + 3491, 0, 3371, + 3491, 0, 3371, + 3491, 0, 3371, + 3491, 0, 3371, + 3489, 0, 3369, + 3489, 0, 3369, + 3487, 0, 3367, + 3485, 0, 3365, + 3483, 0, 3363, + 3479, 0, 3359, + 3473, 0, 3353, + 3467, 0, 3347, + 3459, 805, 3339, + 3447, 1516, 3325, + 3429, 1844, 3309, + 3405, 2081, 3285, + 3373, 2279, 3251, + 3323, 2455, 3201, + 3249, 2617, 3125, + 3123, 2771, 2999, + 2873, 2917, 2743, + 999, 3061, 0, + 0, 3201, 0, + 0, 3339, 0, + 0, 3475, 0, + 0, 3611, 0, + 0, 3745, 0, + 0, 3879, 0, + 0, 4013, 0, + 3619, 0, 3485, + 3619, 0, 3485, + 3619, 0, 3483, + 3617, 0, 3483, + 3617, 0, 3483, + 3617, 0, 3483, + 3617, 0, 3483, + 3617, 0, 3481, + 3615, 0, 3481, + 3615, 0, 3479, + 3613, 0, 3479, + 3611, 0, 3477, + 3609, 0, 3473, + 3605, 0, 3469, + 3599, 0, 3465, + 3593, 0, 3457, + 3583, 0, 3449, + 3571, 1422, 3435, + 3555, 1880, 3417, + 3531, 2159, 3393, + 3497, 2377, 3357, + 3447, 2563, 3303, + 3369, 2733, 3223, + 3241, 2891, 3083, + 2979, 3041, 2787, + 0, 3187, 0, + 0, 3329, 0, + 0, 3467, 0, + 0, 3605, 0, + 0, 3741, 0, + 0, 3877, 0, + 0, 4011, 0, + 3745, 0, 3601, + 3745, 0, 3601, + 3745, 0, 3601, + 3745, 0, 3601, + 3745, 0, 3599, + 3745, 0, 3599, + 3745, 0, 3599, + 3745, 0, 3599, + 3743, 0, 3599, + 3743, 0, 3597, + 3741, 0, 3597, + 3741, 0, 3595, + 3739, 0, 3593, + 3735, 0, 3589, + 3731, 0, 3585, + 3727, 0, 3581, + 3721, 0, 3573, + 3711, 0, 3563, + 3699, 1258, 3549, + 3681, 1924, 3531, + 3657, 2245, 3505, + 3623, 2481, 3467, + 3571, 2677, 3413, + 3493, 2853, 3325, + 3363, 3015, 3177, + 3093, 3167, 2841, + 0, 3315, 0, + 0, 3457, 0, + 0, 3597, 0, + 0, 3735, 0, + 0, 3873, 0, + 0, 4007, 0, + 3875, 0, 3721, + 3875, 0, 3721, + 3875, 0, 3721, + 3875, 0, 3721, + 3875, 0, 3719, + 3873, 0, 3719, + 3873, 0, 3719, + 3873, 0, 3719, + 3873, 0, 3719, + 3873, 0, 3717, + 3871, 0, 3717, + 3871, 0, 3715, + 3869, 0, 3715, + 3867, 0, 3711, + 3863, 0, 3709, + 3861, 0, 3705, + 3855, 0, 3699, + 3849, 0, 3693, + 3839, 0, 3681, + 3827, 858, 3669, + 3809, 1978, 3649, + 3785, 2341, 3623, + 3749, 2591, 3583, + 3699, 2795, 3525, + 3619, 2975, 3435, + 3485, 3139, 3277, + 3209, 3295, 2903, + 0, 3443, 0, + 0, 3587, 0, + 0, 3727, 0, + 0, 3867, 0, + 0, 4003, 0, + 4005, 0, 3843, + 4005, 0, 3843, + 4003, 0, 3843, + 4003, 0, 3843, + 4003, 0, 3843, + 4003, 0, 3843, + 4003, 0, 3843, + 4003, 0, 3843, + 4003, 0, 3841, + 4003, 0, 3841, + 4001, 0, 3841, + 4001, 0, 3839, + 3999, 0, 3839, + 3999, 0, 3837, + 3997, 0, 3835, + 3993, 0, 3831, + 3989, 0, 3827, + 3985, 0, 3821, + 3977, 0, 3815, + 3969, 0, 3803, + 3955, 0, 3789, + 3939, 2041, 3771, + 3913, 2443, 3743, + 3879, 2707, 3703, + 3827, 2917, 3643, + 3747, 3101, 3549, + 3611, 3267, 3383, + 3329, 3423, 2977, + 0, 3573, 0, + 0, 3717, 0, + 0, 3859, 0, + 0, 3997, 0, + 4095, 0, 3969, + 4095, 0, 3969, + 4095, 0, 3969, + 4095, 0, 3969, + 4095, 0, 3967, + 4095, 0, 3967, + 4095, 0, 3967, + 4095, 0, 3967, + 4095, 0, 3967, + 4095, 0, 3967, + 4095, 0, 3967, + 4095, 0, 3965, + 4095, 0, 3965, + 4095, 0, 3963, + 4095, 0, 3961, + 4095, 0, 3959, + 4095, 0, 3957, + 4095, 0, 3951, + 4095, 0, 3947, + 4095, 0, 3939, + 4095, 0, 3929, + 4085, 0, 3913, + 4067, 2113, 3893, + 4043, 2551, 3865, + 4007, 2825, 3825, + 3955, 3041, 3765, + 3875, 3227, 3667, + 3739, 3395, 3495, + 3453, 3553, 3057, + 0, 3703, 0, + 0, 3849, 0, + 0, 3989, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4093, + 4095, 0, 4093, + 4095, 0, 4093, + 4095, 0, 4093, + 4095, 0, 4091, + 4095, 0, 4089, + 4095, 0, 4089, + 4095, 0, 4085, + 4095, 0, 4083, + 4095, 0, 4079, + 4095, 0, 4073, + 4095, 0, 4065, + 4095, 0, 4055, + 4095, 0, 4039, + 4095, 2195, 4019, + 4095, 2665, 3991, + 4095, 2947, 3949, + 4085, 3167, 3887, + 4005, 3355, 3789, + 3867, 3525, 3611, + 3579, 3683, 3149, + 0, 3833, 0, + 0, 3979, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2285, 4095, + 4095, 2783, 4095, + 4095, 3073, 4077, + 4095, 3295, 4013, + 4095, 3483, 3913, + 3997, 3655, 3731, + 3705, 3813, 3247, + 0, 3965, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2383, 4095, + 4095, 2905, 4095, + 4095, 3199, 4095, + 4095, 3423, 4095, + 4095, 3613, 4039, + 4095, 3785, 3855, + 3833, 3945, 3351, + 2299, 1852, 2711, + 2297, 1854, 2711, + 2293, 1857, 2709, + 2291, 1861, 2709, + 2285, 1866, 2707, + 2279, 1873, 2705, + 2269, 1882, 2703, + 2257, 1893, 2699, + 2241, 1909, 2693, + 2217, 1928, 2687, + 2183, 1953, 2679, + 2135, 1984, 2665, + 2059, 2022, 2649, + 1935, 2069, 2625, + 1685, 2125, 2591, + 0, 2191, 2541, + 0, 2265, 2467, + 0, 2349, 2339, + 0, 2441, 2085, + 0, 2543, 0, + 0, 2649, 0, + 0, 2761, 0, + 0, 2877, 0, + 0, 2997, 0, + 0, 3121, 0, + 0, 3245, 0, + 0, 3373, 0, + 0, 3501, 0, + 0, 3629, 0, + 0, 3759, 0, + 0, 3889, 0, + 0, 4021, 0, + 2301, 1852, 2711, + 2299, 1854, 2711, + 2297, 1857, 2711, + 2293, 1861, 2709, + 2287, 1866, 2707, + 2281, 1873, 2705, + 2273, 1882, 2703, + 2261, 1893, 2699, + 2243, 1908, 2695, + 2221, 1928, 2687, + 2187, 1952, 2679, + 2139, 1983, 2667, + 2065, 2022, 2649, + 1941, 2069, 2627, + 1695, 2125, 2593, + 251, 2191, 2543, + 0, 2265, 2467, + 0, 2349, 2341, + 0, 2441, 2087, + 0, 2541, 0, + 0, 2649, 0, + 0, 2761, 0, + 0, 2877, 0, + 0, 2997, 0, + 0, 3121, 0, + 0, 3245, 0, + 0, 3373, 0, + 0, 3501, 0, + 0, 3629, 0, + 0, 3759, 0, + 0, 3889, 0, + 0, 4021, 0, + 2305, 1851, 2713, + 2303, 1854, 2711, + 2299, 1857, 2711, + 2297, 1860, 2709, + 2291, 1866, 2709, + 2285, 1872, 2707, + 2277, 1881, 2703, + 2265, 1893, 2701, + 2247, 1908, 2695, + 2225, 1927, 2689, + 2191, 1952, 2679, + 2143, 1983, 2667, + 2069, 2022, 2651, + 1948, 2069, 2627, + 1708, 2125, 2593, + 483, 2189, 2545, + 0, 2265, 2469, + 0, 2349, 2343, + 0, 2441, 2091, + 0, 2541, 0, + 0, 2649, 0, + 0, 2761, 0, + 0, 2877, 0, + 0, 2997, 0, + 0, 3121, 0, + 0, 3245, 0, + 0, 3373, 0, + 0, 3501, 0, + 0, 3629, 0, + 0, 3759, 0, + 0, 3889, 0, + 0, 4021, 0, + 2309, 1851, 2713, + 2307, 1853, 2713, + 2305, 1856, 2713, + 2301, 1860, 2711, + 2295, 1865, 2709, + 2289, 1872, 2707, + 2281, 1881, 2705, + 2269, 1892, 2701, + 2253, 1907, 2697, + 2229, 1927, 2691, + 2197, 1951, 2681, + 2149, 1983, 2669, + 2077, 2021, 2653, + 1958, 2069, 2629, + 1724, 2125, 2595, + 678, 2189, 2547, + 0, 2265, 2471, + 0, 2349, 2345, + 0, 2441, 2095, + 0, 2541, 280, + 0, 2649, 0, + 0, 2761, 0, + 0, 2877, 0, + 0, 2997, 0, + 0, 3121, 0, + 0, 3245, 0, + 0, 3373, 0, + 0, 3501, 0, + 0, 3629, 0, + 0, 3759, 0, + 0, 3889, 0, + 0, 4021, 0, + 2315, 1850, 2715, + 2313, 1852, 2715, + 2311, 1855, 2713, + 2307, 1859, 2713, + 2301, 1864, 2711, + 2295, 1871, 2709, + 2287, 1880, 2707, + 2275, 1891, 2703, + 2259, 1907, 2699, + 2237, 1926, 2691, + 2205, 1951, 2683, + 2157, 1982, 2671, + 2087, 2021, 2653, + 1970, 2067, 2631, + 1744, 2123, 2597, + 852, 2189, 2549, + 0, 2265, 2473, + 0, 2349, 2349, + 0, 2441, 2101, + 0, 2541, 535, + 0, 2649, 0, + 0, 2761, 0, + 0, 2877, 0, + 0, 2997, 0, + 0, 3121, 0, + 0, 3245, 0, + 0, 3373, 0, + 0, 3501, 0, + 0, 3629, 0, + 0, 3759, 0, + 0, 3889, 0, + 0, 4021, 0, + 2323, 1849, 2717, + 2321, 1851, 2717, + 2317, 1854, 2715, + 2315, 1858, 2715, + 2309, 1863, 2713, + 2303, 1870, 2711, + 2295, 1879, 2709, + 2283, 1890, 2705, + 2267, 1906, 2701, + 2245, 1925, 2693, + 2215, 1950, 2685, + 2169, 1981, 2673, + 2099, 2020, 2657, + 1986, 2067, 2633, + 1771, 2123, 2599, + 1013, 2189, 2551, + 0, 2263, 2477, + 0, 2349, 2355, + 0, 2441, 2111, + 0, 2541, 741, + 0, 2649, 0, + 0, 2761, 0, + 0, 2877, 0, + 0, 2997, 0, + 0, 3121, 0, + 0, 3245, 0, + 0, 3373, 0, + 0, 3501, 0, + 0, 3629, 0, + 0, 3759, 0, + 0, 3889, 0, + 0, 4021, 0, + 2333, 1848, 2721, + 2331, 1850, 2719, + 2327, 1853, 2719, + 2325, 1857, 2717, + 2321, 1862, 2717, + 2315, 1869, 2715, + 2305, 1877, 2711, + 2295, 1889, 2709, + 2279, 1904, 2703, + 2257, 1924, 2697, + 2227, 1949, 2689, + 2183, 1980, 2677, + 2115, 2019, 2659, + 2007, 2065, 2637, + 1804, 2123, 2603, + 1166, 2187, 2555, + 0, 2263, 2483, + 0, 2347, 2361, + 0, 2441, 2121, + 0, 2541, 921, + 0, 2647, 0, + 0, 2761, 0, + 0, 2877, 0, + 0, 2997, 0, + 0, 3121, 0, + 0, 3245, 0, + 0, 3373, 0, + 0, 3501, 0, + 0, 3629, 0, + 0, 3759, 0, + 0, 3889, 0, + 0, 4021, 0, + 2345, 1846, 2725, + 2343, 1848, 2723, + 2341, 1851, 2723, + 2337, 1855, 2721, + 2333, 1860, 2721, + 2327, 1867, 2719, + 2319, 1876, 2715, + 2309, 1887, 2713, + 2293, 1903, 2707, + 2273, 1922, 2701, + 2243, 1947, 2693, + 2201, 1979, 2681, + 2137, 2017, 2663, + 2034, 2065, 2641, + 1845, 2121, 2609, + 1312, 2187, 2561, + 0, 2263, 2489, + 0, 2347, 2369, + 0, 2441, 2135, + 0, 2541, 1086, + 0, 2647, 0, + 0, 2759, 0, + 0, 2877, 0, + 0, 2997, 0, + 0, 3119, 0, + 0, 3245, 0, + 0, 3373, 0, + 0, 3501, 0, + 0, 3629, 0, + 0, 3759, 0, + 0, 3889, 0, + 0, 4021, 0, + 2363, 1843, 2729, + 2361, 1845, 2729, + 2359, 1848, 2727, + 2355, 1852, 2727, + 2351, 1857, 2725, + 2345, 1864, 2723, + 2337, 1873, 2721, + 2327, 1885, 2717, + 2313, 1900, 2713, + 2293, 1920, 2707, + 2265, 1945, 2697, + 2223, 1977, 2685, + 2163, 2016, 2669, + 2067, 2063, 2647, + 1894, 2119, 2615, + 1455, 2185, 2569, + 0, 2261, 2497, + 0, 2347, 2379, + 0, 2439, 2153, + 0, 2539, 1241, + 0, 2647, 0, + 0, 2759, 0, + 0, 2877, 0, + 0, 2997, 0, + 0, 3119, 0, + 0, 3245, 0, + 0, 3371, 0, + 0, 3501, 0, + 0, 3629, 0, + 0, 3759, 0, + 0, 3889, 0, + 0, 4021, 0, + 2385, 1839, 2735, + 2383, 1842, 2735, + 2381, 1845, 2735, + 2377, 1849, 2733, + 2373, 1854, 2731, + 2367, 1861, 2729, + 2361, 1870, 2727, + 2351, 1882, 2725, + 2337, 1897, 2719, + 2319, 1917, 2713, + 2291, 1942, 2705, + 2253, 1974, 2693, + 2197, 2013, 2677, + 2107, 2061, 2655, + 1952, 2117, 2623, + 1595, 2185, 2577, + 0, 2261, 2507, + 0, 2345, 2393, + 0, 2439, 2175, + 0, 2539, 1390, + 0, 2647, 0, + 0, 2759, 0, + 0, 2875, 0, + 0, 2997, 0, + 0, 3119, 0, + 0, 3245, 0, + 0, 3371, 0, + 0, 3501, 0, + 0, 3629, 0, + 0, 3759, 0, + 0, 3889, 0, + 0, 4021, 0, + 2411, 1835, 2745, + 2411, 1837, 2743, + 2409, 1840, 2743, + 2405, 1844, 2743, + 2401, 1849, 2741, + 2397, 1856, 2739, + 2389, 1865, 2737, + 2381, 1877, 2733, + 2367, 1893, 2729, + 2349, 1913, 2723, + 2325, 1939, 2715, + 2289, 1971, 2703, + 2237, 2010, 2687, + 2157, 2059, 2665, + 2020, 2115, 2635, + 1733, 2181, 2589, + 0, 2259, 2523, + 0, 2343, 2413, + 0, 2437, 2205, + 0, 2539, 1534, + 0, 2645, 0, + 0, 2759, 0, + 0, 2875, 0, + 0, 2997, 0, + 0, 3119, 0, + 0, 3245, 0, + 0, 3371, 0, + 0, 3499, 0, + 0, 3629, 0, + 0, 3759, 0, + 0, 3889, 0, + 0, 4021, 0, + 2447, 1828, 2755, + 2445, 1831, 2755, + 2443, 1834, 2755, + 2441, 1838, 2753, + 2437, 1843, 2753, + 2433, 1850, 2751, + 2425, 1859, 2747, + 2417, 1872, 2745, + 2405, 1887, 2741, + 2389, 1908, 2735, + 2367, 1933, 2727, + 2335, 1966, 2715, + 2287, 2006, 2701, + 2215, 2055, 2679, + 2099, 2111, 2649, + 1870, 2179, 2605, + 933, 2255, 2541, + 0, 2341, 2435, + 0, 2435, 2241, + 0, 2537, 1675, + 0, 2645, 0, + 0, 2757, 0, + 0, 2875, 0, + 0, 2995, 0, + 0, 3119, 0, + 0, 3245, 0, + 0, 3371, 0, + 0, 3499, 0, + 0, 3629, 0, + 0, 3759, 0, + 0, 3889, 0, + 0, 4021, 0, + 2489, 1819, 2771, + 2487, 1822, 2771, + 2485, 1825, 2769, + 2483, 1829, 2769, + 2479, 1835, 2767, + 2475, 1842, 2765, + 2469, 1851, 2763, + 2463, 1864, 2759, + 2451, 1880, 2755, + 2437, 1900, 2749, + 2417, 1926, 2741, + 2387, 1959, 2731, + 2347, 2000, 2717, + 2283, 2049, 2697, + 2185, 2107, 2667, + 2005, 2175, 2627, + 1530, 2253, 2565, + 0, 2339, 2465, + 0, 2433, 2285, + 0, 2535, 1814, + 0, 2643, 0, + 0, 2757, 0, + 0, 2873, 0, + 0, 2995, 0, + 0, 3119, 0, + 0, 3245, 0, + 0, 3371, 0, + 0, 3499, 0, + 0, 3629, 0, + 0, 3759, 0, + 0, 3889, 0, + 0, 4021, 0, + 2539, 1807, 2789, + 2539, 1810, 2789, + 2537, 1813, 2789, + 2535, 1817, 2787, + 2531, 1823, 2787, + 2529, 1830, 2785, + 2523, 1840, 2783, + 2515, 1853, 2779, + 2507, 1869, 2775, + 2493, 1890, 2769, + 2475, 1917, 2763, + 2451, 1951, 2753, + 2415, 1992, 2739, + 2361, 2042, 2719, + 2279, 2101, 2691, + 2139, 2169, 2653, + 1840, 2247, 2593, + 0, 2335, 2501, + 0, 2431, 2339, + 0, 2533, 1951, + 0, 2641, 0, + 0, 2755, 0, + 0, 2873, 0, + 0, 2993, 0, + 0, 3117, 0, + 0, 3243, 0, + 0, 3371, 0, + 0, 3499, 0, + 0, 3629, 0, + 0, 3759, 0, + 0, 3889, 0, + 0, 4021, 0, + 2599, 1791, 2813, + 2599, 1793, 2813, + 2597, 1797, 2813, + 2595, 1801, 2811, + 2593, 1807, 2811, + 2589, 1815, 2809, + 2585, 1825, 2807, + 2579, 1838, 2805, + 2571, 1855, 2801, + 2559, 1877, 2795, + 2545, 1904, 2789, + 2523, 1938, 2779, + 2493, 1981, 2765, + 2449, 2032, 2747, + 2381, 2093, 2721, + 2273, 2163, 2685, + 2071, 2241, 2631, + 1442, 2329, 2547, + 0, 2425, 2401, + 0, 2529, 2087, + 0, 2639, 0, + 0, 2753, 0, + 0, 2871, 0, + 0, 2993, 0, + 0, 3117, 0, + 0, 3243, 0, + 0, 3371, 0, + 0, 3499, 0, + 0, 3629, 0, + 0, 3759, 0, + 0, 3889, 0, + 0, 4021, 0, + 2669, 1768, 2845, + 2669, 1770, 2845, + 2667, 1774, 2843, + 2667, 1779, 2843, + 2665, 1785, 2841, + 2661, 1793, 2841, + 2657, 1803, 2839, + 2653, 1817, 2835, + 2645, 1835, 2831, + 2635, 1857, 2827, + 2623, 1886, 2821, + 2605, 1922, 2811, + 2579, 1966, 2799, + 2543, 2018, 2783, + 2489, 2081, 2759, + 2407, 2153, 2725, + 2265, 2233, 2675, + 1960, 2323, 2601, + 0, 2421, 2475, + 0, 2525, 2221, + 0, 2635, 0, + 0, 2751, 0, + 0, 2869, 0, + 0, 2991, 0, + 0, 3115, 0, + 0, 3241, 0, + 0, 3369, 0, + 0, 3499, 0, + 0, 3627, 0, + 0, 3759, 0, + 0, 3889, 0, + 0, 4021, 0, + 2749, 1735, 2883, + 2749, 1738, 2883, + 2747, 1742, 2881, + 2747, 1747, 2881, + 2745, 1753, 2879, + 2741, 1762, 2879, + 2739, 1773, 2877, + 2735, 1788, 2875, + 2729, 1807, 2871, + 2721, 1831, 2867, + 2709, 1861, 2861, + 2695, 1899, 2853, + 2675, 1945, 2841, + 2645, 2000, 2825, + 2603, 2065, 2805, + 2539, 2139, 2773, + 2439, 2221, 2729, + 2253, 2313, 2663, + 1749, 2413, 2555, + 0, 2519, 2355, + 0, 2631, 1740, + 0, 2747, 0, + 0, 2867, 0, + 0, 2989, 0, + 0, 3113, 0, + 0, 3241, 0, + 0, 3369, 0, + 0, 3497, 0, + 0, 3627, 0, + 0, 3757, 0, + 0, 3889, 0, + 0, 4019, 0, + 2837, 1687, 2929, + 2837, 1690, 2929, + 2835, 1694, 2927, + 2835, 1700, 2927, + 2833, 1707, 2927, + 2831, 1717, 2925, + 2829, 1729, 2923, + 2825, 1745, 2921, + 2821, 1766, 2919, + 2815, 1792, 2915, + 2805, 1825, 2909, + 2793, 1866, 2901, + 2777, 1915, 2891, + 2753, 1974, 2877, + 2721, 2042, 2859, + 2673, 2119, 2831, + 2599, 2205, 2793, + 2477, 2301, 2735, + 2239, 2403, 2647, + 1046, 2511, 2489, + 0, 2623, 2123, + 0, 2741, 0, + 0, 2863, 0, + 0, 2987, 0, + 0, 3111, 0, + 0, 3239, 0, + 0, 3367, 0, + 0, 3497, 0, + 0, 3627, 0, + 0, 3757, 0, + 0, 3889, 0, + 0, 4019, 0, + 2933, 1614, 2983, + 2933, 1617, 2983, + 2933, 1622, 2983, + 2931, 1629, 2983, + 2931, 1637, 2981, + 2929, 1648, 2981, + 2927, 1663, 2979, + 2923, 1681, 2977, + 2921, 1705, 2975, + 2915, 1735, 2971, + 2907, 1772, 2967, + 2899, 1818, 2959, + 2885, 1872, 2951, + 2867, 1936, 2939, + 2841, 2009, 2923, + 2805, 2093, 2899, + 2751, 2183, 2867, + 2669, 2283, 2817, + 2525, 2389, 2745, + 2217, 2499, 2621, + 0, 2615, 2381, + 0, 2735, 1111, + 0, 2857, 0, + 0, 2983, 0, + 0, 3109, 0, + 0, 3237, 0, + 0, 3365, 0, + 0, 3495, 0, + 0, 3625, 0, + 0, 3757, 0, + 0, 3887, 0, + 0, 4019, 0, + 3037, 1492, 3049, + 3037, 1497, 3049, + 3037, 1503, 3049, + 3035, 1512, 3047, + 3035, 1523, 3047, + 3033, 1537, 3045, + 3031, 1555, 3045, + 3029, 1579, 3043, + 3027, 1608, 3041, + 3023, 1645, 3037, + 3017, 1690, 3033, + 3009, 1744, 3027, + 2999, 1807, 3021, + 2985, 1880, 3011, + 2965, 1962, 2995, + 2937, 2053, 2977, + 2899, 2151, 2949, + 2839, 2257, 2909, + 2747, 2369, 2849, + 2583, 2483, 2755, + 2187, 2603, 2587, + 0, 2725, 2177, + 0, 2851, 0, + 0, 2977, 0, + 0, 3105, 0, + 0, 3233, 0, + 0, 3363, 0, + 0, 3493, 0, + 0, 3625, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 3147, 1253, 3123, + 3147, 1261, 3123, + 3145, 1272, 3123, + 3145, 1286, 3123, + 3145, 1304, 3121, + 3143, 1327, 3121, + 3143, 1355, 3119, + 3141, 1391, 3119, + 3137, 1435, 3117, + 3135, 1488, 3113, + 3131, 1550, 3111, + 3125, 1622, 3105, + 3117, 1703, 3099, + 3105, 1793, 3091, + 3091, 1891, 3079, + 3071, 1996, 3063, + 3041, 2107, 3039, + 2999, 2221, 3007, + 2935, 2341, 2959, + 2835, 2463, 2887, + 2649, 2587, 2769, + 2143, 2713, 2537, + 0, 2841, 1540, + 0, 2969, 0, + 0, 3099, 0, + 0, 3229, 0, + 0, 3361, 0, + 0, 3491, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4017, 0, + 3261, 75, 3207, + 3261, 173, 3207, + 3261, 278, 3207, + 3259, 388, 3205, + 3259, 504, 3205, + 3259, 623, 3205, + 3257, 745, 3203, + 3255, 869, 3203, + 3255, 996, 3201, + 3251, 1123, 3199, + 3249, 1252, 3195, + 3243, 1382, 3193, + 3237, 1512, 3187, + 3229, 1643, 3179, + 3219, 1774, 3169, + 3203, 1905, 3157, + 3181, 2037, 3139, + 3151, 2169, 3113, + 3105, 2301, 3075, + 3039, 2433, 3021, + 2929, 2563, 2935, + 2725, 2695, 2787, + 2075, 2829, 2459, + 0, 2961, 0, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 3379, 0, 3299, + 3379, 0, 3299, + 3379, 0, 3299, + 3379, 0, 3299, + 3377, 0, 3297, + 3377, 0, 3297, + 3377, 0, 3297, + 3375, 0, 3295, + 3375, 0, 3295, + 3373, 0, 3293, + 3369, 0, 3289, + 3367, 154, 3287, + 3361, 964, 3283, + 3355, 1304, 3277, + 3347, 1546, 3269, + 3335, 1746, 3259, + 3319, 1923, 3243, + 3297, 2087, 3223, + 3265, 2241, 3195, + 3219, 2387, 3153, + 3147, 2531, 3091, + 3033, 2671, 2991, + 2811, 2811, 2811, + 1967, 2947, 2331, + 0, 3083, 0, + 0, 3217, 0, + 0, 3351, 0, + 0, 3485, 0, + 0, 3617, 0, + 0, 3751, 0, + 0, 3883, 0, + 0, 4015, 0, + 3501, 0, 3399, + 3501, 0, 3399, + 3501, 0, 3399, + 3501, 0, 3397, + 3499, 0, 3397, + 3499, 0, 3397, + 3499, 0, 3397, + 3497, 0, 3395, + 3497, 0, 3395, + 3495, 0, 3393, + 3493, 0, 3391, + 3491, 0, 3389, + 3487, 0, 3385, + 3483, 0, 3381, + 3477, 624, 3375, + 3467, 1374, 3367, + 3455, 1707, 3355, + 3439, 1946, 3339, + 3415, 2145, 3317, + 3383, 2321, 3285, + 3335, 2483, 3239, + 3261, 2637, 3169, + 3141, 2785, 3057, + 2903, 2929, 2839, + 1764, 3069, 2065, + 0, 3207, 0, + 0, 3343, 0, + 0, 3479, 0, + 0, 3613, 0, + 0, 3747, 0, + 0, 3881, 0, + 0, 4013, 0, + 3625, 0, 3505, + 3625, 0, 3505, + 3625, 0, 3505, + 3625, 0, 3505, + 3623, 0, 3503, + 3623, 0, 3503, + 3623, 0, 3503, + 3623, 0, 3503, + 3621, 0, 3501, + 3621, 0, 3501, + 3619, 0, 3499, + 3617, 0, 3497, + 3615, 0, 3495, + 3611, 0, 3491, + 3607, 0, 3485, + 3599, 0, 3479, + 3591, 937, 3471, + 3579, 1648, 3459, + 3561, 1976, 3441, + 3539, 2213, 3417, + 3505, 2411, 3383, + 3455, 2587, 3335, + 3381, 2749, 3259, + 3255, 2903, 3131, + 3005, 3049, 2875, + 1131, 3193, 0, + 0, 3333, 0, + 0, 3471, 0, + 0, 3607, 0, + 0, 3743, 0, + 0, 3877, 0, + 0, 4011, 0, + 3751, 0, 3617, + 3751, 0, 3617, + 3751, 0, 3617, + 3751, 0, 3617, + 3751, 0, 3615, + 3749, 0, 3615, + 3749, 0, 3615, + 3749, 0, 3615, + 3749, 0, 3615, + 3747, 0, 3613, + 3747, 0, 3613, + 3745, 0, 3611, + 3743, 0, 3609, + 3741, 0, 3605, + 3737, 0, 3601, + 3731, 0, 3597, + 3725, 0, 3589, + 3717, 0, 3581, + 3703, 1555, 3567, + 3687, 2012, 3549, + 3663, 2291, 3525, + 3629, 2509, 3489, + 3579, 2695, 3437, + 3501, 2865, 3355, + 3373, 3023, 3215, + 3111, 3173, 2919, + 0, 3319, 0, + 0, 3461, 0, + 0, 3601, 0, + 0, 3737, 0, + 0, 3873, 0, + 0, 4009, 0, + 3879, 0, 3733, + 3879, 0, 3733, + 3877, 0, 3733, + 3877, 0, 3733, + 3877, 0, 3733, + 3877, 0, 3733, + 3877, 0, 3731, + 3877, 0, 3731, + 3877, 0, 3731, + 3875, 0, 3731, + 3875, 0, 3729, + 3873, 0, 3729, + 3873, 0, 3727, + 3871, 0, 3725, + 3867, 0, 3721, + 3863, 0, 3717, + 3859, 0, 3713, + 3853, 0, 3705, + 3843, 0, 3695, + 3831, 1390, 3681, + 3813, 2057, 3663, + 3789, 2379, 3637, + 3755, 2613, 3599, + 3703, 2809, 3545, + 3625, 2985, 3457, + 3495, 3147, 3309, + 3225, 3299, 2973, + 0, 3447, 0, + 0, 3589, 0, + 0, 3729, 0, + 0, 3867, 0, + 0, 4005, 0, + 4007, 0, 3853, + 4007, 0, 3853, + 4007, 0, 3853, + 4007, 0, 3853, + 4007, 0, 3853, + 4007, 0, 3853, + 4007, 0, 3851, + 4005, 0, 3851, + 4005, 0, 3851, + 4005, 0, 3851, + 4005, 0, 3851, + 4003, 0, 3849, + 4003, 0, 3847, + 4001, 0, 3847, + 3999, 0, 3843, + 3997, 0, 3841, + 3993, 0, 3837, + 3987, 0, 3831, + 3981, 0, 3825, + 3971, 0, 3815, + 3959, 990, 3801, + 3941, 2109, 3781, + 3917, 2473, 3755, + 3881, 2723, 3715, + 3831, 2927, 3657, + 3751, 3107, 3567, + 3619, 3271, 3409, + 3341, 3427, 3035, + 0, 3575, 0, + 0, 3719, 0, + 0, 3861, 0, + 0, 3999, 0, + 4095, 0, 3975, + 4095, 0, 3975, + 4095, 0, 3975, + 4095, 0, 3975, + 4095, 0, 3975, + 4095, 0, 3975, + 4095, 0, 3975, + 4095, 0, 3975, + 4095, 0, 3975, + 4095, 0, 3973, + 4095, 0, 3973, + 4095, 0, 3973, + 4095, 0, 3971, + 4095, 0, 3971, + 4095, 0, 3969, + 4095, 0, 3967, + 4095, 0, 3963, + 4095, 0, 3959, + 4095, 0, 3953, + 4095, 0, 3947, + 4095, 0, 3935, + 4087, 0, 3921, + 4071, 2173, 3903, + 4045, 2575, 3875, + 4011, 2839, 3835, + 3959, 3049, 3775, + 3879, 3233, 3681, + 3743, 3399, 3515, + 3461, 3555, 3109, + 0, 3705, 0, + 0, 3849, 0, + 0, 3991, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4093, + 4095, 0, 4091, + 4095, 0, 4089, + 4095, 0, 4085, + 4095, 0, 4079, + 4095, 0, 4071, + 4095, 0, 4061, + 4095, 0, 4045, + 4095, 2245, 4025, + 4095, 2683, 3997, + 4095, 2959, 3957, + 4087, 3173, 3897, + 4007, 3359, 3799, + 3871, 3527, 3627, + 3585, 3685, 3189, + 0, 3835, 0, + 0, 3981, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2327, 4095, + 4095, 2797, 4095, + 4095, 3081, 4081, + 4095, 3299, 4019, + 4095, 3487, 3921, + 3999, 3657, 3743, + 3711, 3815, 3281, + 0, 3965, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2417, 4095, + 4095, 2915, 4095, + 4095, 3205, 4095, + 4095, 3427, 4095, + 4095, 3615, 4045, + 4095, 3787, 3865, + 3837, 3945, 3379, + 2431, 1983, 2843, + 2429, 1985, 2843, + 2427, 1987, 2841, + 2425, 1990, 2841, + 2421, 1994, 2839, + 2415, 1999, 2839, + 2409, 2005, 2837, + 2401, 2014, 2833, + 2387, 2026, 2831, + 2371, 2041, 2825, + 2347, 2061, 2819, + 2313, 2085, 2809, + 2265, 2115, 2797, + 2189, 2155, 2781, + 2063, 2201, 2757, + 1810, 2257, 2723, + 0, 2323, 2673, + 0, 2397, 2597, + 0, 2481, 2471, + 0, 2575, 2215, + 0, 2675, 0, + 0, 2781, 0, + 0, 2893, 0, + 0, 3009, 0, + 0, 3129, 0, + 0, 3253, 0, + 0, 3377, 0, + 0, 3505, 0, + 0, 3633, 0, + 0, 3761, 0, + 0, 3891, 0, + 0, 4021, 0, + 2433, 1983, 2843, + 2431, 1984, 2843, + 2429, 1987, 2843, + 2425, 1989, 2841, + 2423, 1993, 2841, + 2417, 1998, 2839, + 2411, 2005, 2837, + 2403, 2014, 2835, + 2389, 2026, 2831, + 2373, 2041, 2825, + 2349, 2061, 2819, + 2317, 2085, 2811, + 2267, 2115, 2797, + 2193, 2155, 2781, + 2067, 2201, 2757, + 1818, 2257, 2723, + 69, 2323, 2675, + 0, 2397, 2599, + 0, 2481, 2471, + 0, 2575, 2217, + 0, 2675, 0, + 0, 2781, 0, + 0, 2893, 0, + 0, 3009, 0, + 0, 3129, 0, + 0, 3253, 0, + 0, 3377, 0, + 0, 3505, 0, + 0, 3633, 0, + 0, 3761, 0, + 0, 3891, 0, + 0, 4021, 0, + 2435, 1982, 2845, + 2433, 1984, 2843, + 2431, 1986, 2843, + 2429, 1989, 2843, + 2425, 1993, 2841, + 2421, 1998, 2839, + 2413, 2005, 2837, + 2405, 2014, 2835, + 2393, 2025, 2831, + 2375, 2040, 2827, + 2353, 2059, 2819, + 2319, 2085, 2811, + 2271, 2115, 2799, + 2197, 2153, 2781, + 2073, 2201, 2759, + 1827, 2257, 2725, + 383, 2323, 2675, + 0, 2397, 2599, + 0, 2481, 2473, + 0, 2573, 2219, + 0, 2675, 0, + 0, 2781, 0, + 0, 2893, 0, + 0, 3009, 0, + 0, 3129, 0, + 0, 3253, 0, + 0, 3377, 0, + 0, 3505, 0, + 0, 3633, 0, + 0, 3761, 0, + 0, 3891, 0, + 0, 4021, 0, + 2437, 1982, 2845, + 2437, 1984, 2845, + 2435, 1986, 2843, + 2431, 1989, 2843, + 2429, 1993, 2843, + 2423, 1998, 2841, + 2417, 2004, 2839, + 2409, 2013, 2835, + 2397, 2025, 2833, + 2379, 2040, 2827, + 2357, 2059, 2821, + 2323, 2085, 2811, + 2275, 2115, 2799, + 2201, 2153, 2783, + 2081, 2201, 2759, + 1840, 2257, 2725, + 615, 2321, 2677, + 0, 2397, 2601, + 0, 2481, 2475, + 0, 2573, 2223, + 0, 2673, 39, + 0, 2781, 0, + 0, 2893, 0, + 0, 3009, 0, + 0, 3129, 0, + 0, 3253, 0, + 0, 3377, 0, + 0, 3505, 0, + 0, 3633, 0, + 0, 3761, 0, + 0, 3891, 0, + 0, 4021, 0, + 2443, 1981, 2847, + 2441, 1983, 2845, + 2439, 1985, 2845, + 2437, 1988, 2845, + 2433, 1992, 2843, + 2429, 1997, 2841, + 2421, 2004, 2839, + 2413, 2013, 2837, + 2401, 2024, 2833, + 2385, 2039, 2829, + 2361, 2059, 2823, + 2329, 2083, 2813, + 2281, 2115, 2801, + 2209, 2153, 2785, + 2089, 2201, 2761, + 1856, 2257, 2727, + 810, 2321, 2679, + 0, 2397, 2603, + 0, 2481, 2477, + 0, 2573, 2227, + 0, 2673, 413, + 0, 2781, 0, + 0, 2893, 0, + 0, 3009, 0, + 0, 3129, 0, + 0, 3253, 0, + 0, 3377, 0, + 0, 3505, 0, + 0, 3633, 0, + 0, 3761, 0, + 0, 3891, 0, + 0, 4021, 0, + 2449, 1981, 2847, + 2447, 1982, 2847, + 2445, 1984, 2847, + 2443, 1987, 2845, + 2439, 1991, 2845, + 2435, 1996, 2843, + 2427, 2003, 2841, + 2419, 2012, 2839, + 2407, 2024, 2835, + 2391, 2039, 2831, + 2369, 2059, 2823, + 2337, 2083, 2815, + 2289, 2115, 2803, + 2219, 2153, 2787, + 2103, 2199, 2763, + 1877, 2255, 2729, + 984, 2321, 2681, + 0, 2397, 2605, + 0, 2481, 2481, + 0, 2573, 2235, + 0, 2673, 667, + 0, 2781, 0, + 0, 2893, 0, + 0, 3009, 0, + 0, 3129, 0, + 0, 3253, 0, + 0, 3377, 0, + 0, 3505, 0, + 0, 3633, 0, + 0, 3761, 0, + 0, 3891, 0, + 0, 4021, 0, + 2455, 1979, 2849, + 2455, 1981, 2849, + 2453, 1983, 2849, + 2449, 1986, 2849, + 2447, 1990, 2847, + 2441, 1995, 2845, + 2435, 2002, 2843, + 2427, 2011, 2841, + 2415, 2023, 2837, + 2399, 2038, 2833, + 2377, 2057, 2827, + 2347, 2083, 2817, + 2301, 2113, 2805, + 2231, 2151, 2789, + 2119, 2199, 2765, + 1903, 2255, 2733, + 1145, 2321, 2683, + 0, 2395, 2609, + 0, 2481, 2487, + 0, 2573, 2243, + 0, 2673, 873, + 0, 2781, 0, + 0, 2893, 0, + 0, 3009, 0, + 0, 3129, 0, + 0, 3253, 0, + 0, 3377, 0, + 0, 3505, 0, + 0, 3633, 0, + 0, 3761, 0, + 0, 3891, 0, + 0, 4021, 0, + 2465, 1978, 2853, + 2465, 1980, 2853, + 2463, 1982, 2851, + 2461, 1985, 2851, + 2457, 1989, 2849, + 2453, 1994, 2849, + 2447, 2001, 2847, + 2437, 2010, 2843, + 2427, 2021, 2841, + 2411, 2036, 2835, + 2389, 2057, 2829, + 2359, 2081, 2821, + 2315, 2113, 2809, + 2247, 2151, 2791, + 2139, 2199, 2769, + 1936, 2255, 2735, + 1298, 2321, 2687, + 0, 2395, 2615, + 0, 2479, 2493, + 0, 2573, 2253, + 0, 2673, 1053, + 0, 2779, 0, + 0, 2893, 0, + 0, 3009, 0, + 0, 3129, 0, + 0, 3253, 0, + 0, 3377, 0, + 0, 3505, 0, + 0, 3633, 0, + 0, 3761, 0, + 0, 3891, 0, + 0, 4021, 0, + 2479, 1976, 2857, + 2477, 1978, 2857, + 2475, 1980, 2855, + 2473, 1983, 2855, + 2471, 1987, 2853, + 2465, 1992, 2853, + 2459, 1999, 2851, + 2451, 2008, 2847, + 2441, 2020, 2845, + 2425, 2035, 2839, + 2405, 2055, 2833, + 2375, 2079, 2825, + 2333, 2111, 2813, + 2269, 2149, 2797, + 2165, 2197, 2773, + 1977, 2253, 2741, + 1445, 2319, 2693, + 0, 2395, 2621, + 0, 2479, 2501, + 0, 2573, 2267, + 0, 2673, 1218, + 0, 2779, 0, + 0, 2891, 0, + 0, 3009, 0, + 0, 3129, 0, + 0, 3253, 0, + 0, 3377, 0, + 0, 3505, 0, + 0, 3633, 0, + 0, 3761, 0, + 0, 3891, 0, + 0, 4021, 0, + 2495, 1973, 2861, + 2495, 1975, 2861, + 2493, 1977, 2861, + 2491, 1980, 2859, + 2487, 1984, 2859, + 2483, 1989, 2857, + 2477, 1996, 2855, + 2469, 2005, 2853, + 2459, 2017, 2849, + 2445, 2032, 2845, + 2425, 2053, 2839, + 2397, 2077, 2829, + 2357, 2109, 2819, + 2295, 2147, 2801, + 2199, 2195, 2779, + 2026, 2251, 2747, + 1587, 2317, 2701, + 0, 2393, 2629, + 0, 2479, 2511, + 0, 2571, 2285, + 0, 2673, 1373, + 0, 2779, 0, + 0, 2891, 0, + 0, 3009, 0, + 0, 3129, 0, + 0, 3251, 0, + 0, 3377, 0, + 0, 3505, 0, + 0, 3633, 0, + 0, 3761, 0, + 0, 3891, 0, + 0, 4021, 0, + 2517, 1970, 2869, + 2517, 1972, 2867, + 2515, 1974, 2867, + 2513, 1977, 2867, + 2509, 1981, 2865, + 2505, 1986, 2863, + 2501, 1993, 2863, + 2493, 2002, 2859, + 2483, 2014, 2857, + 2469, 2029, 2851, + 2451, 2049, 2845, + 2423, 2075, 2837, + 2385, 2107, 2825, + 2329, 2145, 2809, + 2239, 2193, 2787, + 2085, 2249, 2755, + 1727, 2317, 2709, + 0, 2393, 2639, + 0, 2477, 2527, + 0, 2571, 2309, + 0, 2671, 1522, + 0, 2779, 0, + 0, 2891, 0, + 0, 3009, 0, + 0, 3129, 0, + 0, 3251, 0, + 0, 3377, 0, + 0, 3503, 0, + 0, 3633, 0, + 0, 3761, 0, + 0, 3891, 0, + 0, 4021, 0, + 2545, 1965, 2877, + 2543, 1967, 2877, + 2543, 1969, 2875, + 2541, 1972, 2875, + 2537, 1976, 2875, + 2533, 1981, 2873, + 2529, 1988, 2871, + 2521, 1998, 2869, + 2513, 2010, 2865, + 2499, 2025, 2861, + 2481, 2045, 2855, + 2457, 2071, 2847, + 2421, 2103, 2835, + 2369, 2143, 2819, + 2289, 2191, 2797, + 2153, 2247, 2767, + 1865, 2315, 2721, + 0, 2391, 2655, + 0, 2475, 2545, + 0, 2569, 2337, + 0, 2671, 1666, + 0, 2777, 0, + 0, 2891, 0, + 0, 3007, 0, + 0, 3129, 0, + 0, 3251, 0, + 0, 3377, 0, + 0, 3503, 0, + 0, 3633, 0, + 0, 3761, 0, + 0, 3891, 0, + 0, 4021, 0, + 2579, 1959, 2889, + 2579, 1960, 2887, + 2577, 1963, 2887, + 2575, 1966, 2887, + 2573, 1970, 2885, + 2569, 1975, 2885, + 2565, 1982, 2883, + 2557, 1992, 2881, + 2549, 2004, 2877, + 2537, 2019, 2873, + 2521, 2040, 2867, + 2499, 2065, 2859, + 2467, 2097, 2847, + 2419, 2137, 2833, + 2347, 2187, 2811, + 2231, 2243, 2781, + 2002, 2311, 2737, + 1065, 2387, 2673, + 0, 2473, 2567, + 0, 2567, 2373, + 0, 2669, 1807, + 0, 2777, 0, + 0, 2889, 0, + 0, 3007, 0, + 0, 3127, 0, + 0, 3251, 0, + 0, 3377, 0, + 0, 3503, 0, + 0, 3631, 0, + 0, 3761, 0, + 0, 3891, 0, + 0, 4021, 0, + 2621, 1950, 2903, + 2621, 1952, 2903, + 2619, 1954, 2903, + 2617, 1957, 2901, + 2615, 1961, 2901, + 2611, 1967, 2899, + 2607, 1974, 2897, + 2601, 1983, 2895, + 2595, 1996, 2891, + 2583, 2012, 2887, + 2569, 2032, 2881, + 2549, 2059, 2875, + 2519, 2091, 2863, + 2479, 2131, 2849, + 2415, 2181, 2829, + 2317, 2239, 2799, + 2137, 2307, 2759, + 1662, 2385, 2697, + 0, 2471, 2597, + 0, 2565, 2417, + 0, 2667, 1946, + 0, 2775, 0, + 0, 2889, 0, + 0, 3007, 0, + 0, 3127, 0, + 0, 3251, 0, + 0, 3377, 0, + 0, 3503, 0, + 0, 3631, 0, + 0, 3761, 0, + 0, 3891, 0, + 0, 4021, 0, + 2673, 1938, 2923, + 2671, 1940, 2921, + 2671, 1942, 2921, + 2669, 1945, 2921, + 2667, 1949, 2919, + 2663, 1955, 2919, + 2661, 1962, 2917, + 2655, 1972, 2915, + 2649, 1985, 2911, + 2639, 2001, 2907, + 2625, 2022, 2901, + 2607, 2049, 2895, + 2583, 2083, 2885, + 2547, 2123, 2871, + 2493, 2173, 2851, + 2411, 2233, 2823, + 2271, 2301, 2785, + 1972, 2379, 2725, + 0, 2467, 2633, + 0, 2563, 2471, + 0, 2665, 2083, + 0, 2773, 0, + 0, 2887, 0, + 0, 3005, 0, + 0, 3127, 0, + 0, 3249, 0, + 0, 3375, 0, + 0, 3503, 0, + 0, 3631, 0, + 0, 3761, 0, + 0, 3891, 0, + 0, 4021, 0, + 2733, 1921, 2947, + 2731, 1923, 2947, + 2731, 1926, 2945, + 2729, 1929, 2945, + 2727, 1933, 2945, + 2725, 1939, 2943, + 2721, 1947, 2941, + 2717, 1957, 2939, + 2711, 1970, 2937, + 2703, 1987, 2933, + 2693, 2009, 2927, + 2677, 2036, 2921, + 2655, 2071, 2911, + 2625, 2113, 2897, + 2581, 2163, 2879, + 2513, 2225, 2853, + 2405, 2295, 2817, + 2203, 2373, 2763, + 1574, 2461, 2679, + 0, 2559, 2533, + 0, 2661, 2219, + 0, 2771, 0, + 0, 2885, 0, + 0, 3003, 0, + 0, 3125, 0, + 0, 3249, 0, + 0, 3375, 0, + 0, 3503, 0, + 0, 3631, 0, + 0, 3761, 0, + 0, 3891, 0, + 0, 4021, 0, + 2803, 1898, 2977, + 2801, 1900, 2977, + 2801, 1903, 2977, + 2799, 1906, 2975, + 2799, 1911, 2975, + 2797, 1917, 2973, + 2793, 1925, 2973, + 2789, 1935, 2971, + 2785, 1949, 2967, + 2777, 1967, 2963, + 2767, 1990, 2959, + 2755, 2018, 2953, + 2737, 2055, 2943, + 2711, 2097, 2931, + 2675, 2151, 2915, + 2621, 2213, 2891, + 2539, 2285, 2857, + 2397, 2365, 2807, + 2093, 2455, 2733, + 0, 2553, 2607, + 0, 2657, 2353, + 0, 2767, 0, + 0, 2883, 0, + 0, 3001, 0, + 0, 3123, 0, + 0, 3247, 0, + 0, 3375, 0, + 0, 3501, 0, + 0, 3631, 0, + 0, 3761, 0, + 0, 3891, 0, + 0, 4021, 0, + 2881, 1865, 3015, + 2881, 1867, 3015, + 2881, 1870, 3015, + 2879, 1874, 3013, + 2879, 1879, 3013, + 2877, 1885, 3011, + 2875, 1894, 3011, + 2871, 1905, 3009, + 2867, 1920, 3007, + 2861, 1939, 3003, + 2853, 1963, 2999, + 2843, 1993, 2993, + 2827, 2031, 2985, + 2807, 2077, 2973, + 2777, 2131, 2957, + 2735, 2197, 2937, + 2673, 2271, 2905, + 2571, 2353, 2861, + 2387, 2445, 2795, + 1882, 2545, 2687, + 0, 2651, 2487, + 0, 2763, 1872, + 0, 2879, 0, + 0, 2999, 0, + 0, 3121, 0, + 0, 3247, 0, + 0, 3373, 0, + 0, 3501, 0, + 0, 3629, 0, + 0, 3759, 0, + 0, 3889, 0, + 0, 4021, 0, + 2969, 1817, 3061, + 2969, 1819, 3061, + 2969, 1822, 3061, + 2969, 1826, 3059, + 2967, 1832, 3059, + 2965, 1839, 3059, + 2963, 1849, 3057, + 2961, 1861, 3055, + 2957, 1877, 3053, + 2953, 1898, 3051, + 2947, 1924, 3047, + 2937, 1957, 3041, + 2925, 1998, 3033, + 2909, 2047, 3023, + 2885, 2105, 3009, + 2853, 2173, 2991, + 2805, 2251, 2963, + 2731, 2337, 2925, + 2611, 2433, 2869, + 2371, 2535, 2779, + 1178, 2643, 2621, + 0, 2757, 2255, + 0, 2873, 0, + 0, 2995, 0, + 0, 3119, 0, + 0, 3243, 0, + 0, 3371, 0, + 0, 3499, 0, + 0, 3629, 0, + 0, 3759, 0, + 0, 3889, 0, + 0, 4021, 0, + 3067, 1743, 3117, + 3065, 1746, 3117, + 3065, 1749, 3115, + 3065, 1754, 3115, + 3063, 1761, 3115, + 3063, 1769, 3113, + 3061, 1780, 3113, + 3059, 1795, 3111, + 3057, 1813, 3109, + 3053, 1837, 3107, + 3047, 1867, 3103, + 3041, 1904, 3099, + 3031, 1950, 3093, + 3017, 2004, 3083, + 2999, 2069, 3071, + 2973, 2141, 3055, + 2937, 2225, 3031, + 2883, 2315, 2999, + 2801, 2415, 2951, + 2657, 2521, 2877, + 2349, 2631, 2755, + 0, 2747, 2513, + 0, 2867, 1244, + 0, 2989, 0, + 0, 3115, 0, + 0, 3241, 0, + 0, 3369, 0, + 0, 3497, 0, + 0, 3627, 0, + 0, 3757, 0, + 0, 3889, 0, + 0, 4019, 0, + 3169, 1621, 3181, + 3169, 1624, 3181, + 3169, 1629, 3181, + 3169, 1636, 3181, + 3167, 1644, 3179, + 3167, 1655, 3179, + 3165, 1669, 3179, + 3163, 1687, 3177, + 3161, 1711, 3175, + 3159, 1741, 3173, + 3155, 1777, 3169, + 3149, 1822, 3165, + 3141, 1876, 3161, + 3131, 1940, 3153, + 3117, 2012, 3143, + 3097, 2095, 3129, + 3071, 2185, 3109, + 3031, 2285, 3081, + 2971, 2389, 3041, + 2879, 2501, 2981, + 2715, 2617, 2887, + 2319, 2735, 2719, + 0, 2857, 2309, + 0, 2983, 0, + 0, 3109, 0, + 0, 3237, 0, + 0, 3365, 0, + 0, 3495, 0, + 0, 3625, 0, + 0, 3757, 0, + 0, 3887, 0, + 0, 4019, 0, + 3279, 1379, 3255, + 3279, 1385, 3255, + 3279, 1394, 3255, + 3277, 1404, 3255, + 3277, 1418, 3255, + 3277, 1436, 3253, + 3275, 1459, 3253, + 3275, 1487, 3251, + 3273, 1523, 3251, + 3271, 1567, 3249, + 3267, 1620, 3245, + 3263, 1683, 3243, + 3257, 1754, 3237, + 3249, 1836, 3231, + 3239, 1925, 3223, + 3223, 2023, 3211, + 3203, 2127, 3195, + 3173, 2239, 3171, + 3131, 2353, 3139, + 3067, 2473, 3091, + 2967, 2595, 3019, + 2781, 2719, 2901, + 2275, 2845, 2669, + 0, 2973, 1672, + 0, 3101, 0, + 0, 3231, 0, + 0, 3361, 0, + 0, 3493, 0, + 0, 3623, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 3393, 117, 3339, + 3393, 207, 3339, + 3393, 305, 3339, + 3393, 410, 3339, + 3391, 520, 3337, + 3391, 636, 3337, + 3391, 755, 3337, + 3389, 877, 3335, + 3389, 1001, 3335, + 3387, 1128, 3333, + 3383, 1255, 3331, + 3381, 1384, 3329, + 3375, 1514, 3325, + 3369, 1644, 3319, + 3361, 1775, 3311, + 3351, 1906, 3303, + 3335, 2037, 3289, + 3313, 2169, 3271, + 3283, 2301, 3245, + 3239, 2433, 3207, + 3171, 2565, 3153, + 3061, 2697, 3067, + 2857, 2829, 2919, + 2207, 2961, 2591, + 0, 3093, 0, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 3511, 0, 3431, + 3511, 0, 3431, + 3511, 0, 3431, + 3511, 0, 3431, + 3511, 0, 3431, + 3509, 0, 3429, + 3509, 0, 3429, + 3509, 0, 3429, + 3507, 0, 3427, + 3507, 0, 3427, + 3505, 0, 3425, + 3501, 0, 3423, + 3499, 286, 3419, + 3493, 1096, 3415, + 3487, 1436, 3409, + 3479, 1678, 3401, + 3467, 1878, 3391, + 3451, 2055, 3375, + 3429, 2219, 3355, + 3397, 2373, 3327, + 3351, 2521, 3285, + 3279, 2663, 3223, + 3165, 2803, 3123, + 2943, 2943, 2943, + 2099, 3079, 2463, + 0, 3215, 0, + 0, 3349, 0, + 0, 3483, 0, + 0, 3617, 0, + 0, 3749, 0, + 0, 3883, 0, + 0, 4015, 0, + 3633, 0, 3531, + 3633, 0, 3531, + 3633, 0, 3531, + 3633, 0, 3531, + 3633, 0, 3529, + 3631, 0, 3529, + 3631, 0, 3529, + 3631, 0, 3529, + 3629, 0, 3527, + 3629, 0, 3527, + 3627, 0, 3525, + 3625, 0, 3523, + 3623, 0, 3521, + 3619, 0, 3517, + 3615, 0, 3513, + 3609, 756, 3507, + 3599, 1506, 3499, + 3587, 1839, 3487, + 3571, 2079, 3471, + 3547, 2277, 3449, + 3515, 2453, 3417, + 3467, 2615, 3371, + 3395, 2769, 3301, + 3273, 2917, 3189, + 3035, 3061, 2971, + 1896, 3201, 2197, + 0, 3339, 0, + 0, 3475, 0, + 0, 3611, 0, + 0, 3745, 0, + 0, 3879, 0, + 0, 4013, 0, + 3757, 0, 3637, + 3757, 0, 3637, + 3757, 0, 3637, + 3757, 0, 3637, + 3757, 0, 3637, + 3757, 0, 3637, + 3755, 0, 3635, + 3755, 0, 3635, + 3755, 0, 3635, + 3753, 0, 3633, + 3753, 0, 3633, + 3751, 0, 3631, + 3749, 0, 3629, + 3747, 0, 3627, + 3743, 0, 3623, + 3739, 0, 3619, + 3731, 0, 3611, + 3723, 1069, 3603, + 3711, 1780, 3591, + 3693, 2107, 3573, + 3671, 2345, 3549, + 3637, 2543, 3515, + 3587, 2719, 3467, + 3513, 2881, 3391, + 3387, 3035, 3263, + 3137, 3181, 3007, + 1263, 3325, 0, + 0, 3465, 0, + 0, 3603, 0, + 0, 3739, 0, + 0, 3875, 0, + 0, 4009, 0, + 3883, 0, 3749, + 3883, 0, 3749, + 3883, 0, 3749, + 3883, 0, 3749, + 3883, 0, 3749, + 3883, 0, 3747, + 3881, 0, 3747, + 3881, 0, 3747, + 3881, 0, 3747, + 3881, 0, 3747, + 3879, 0, 3745, + 3879, 0, 3745, + 3877, 0, 3743, + 3875, 0, 3741, + 3873, 0, 3737, + 3869, 0, 3733, + 3863, 0, 3729, + 3857, 0, 3721, + 3849, 0, 3713, + 3835, 1687, 3699, + 3819, 2145, 3681, + 3795, 2423, 3657, + 3761, 2641, 3621, + 3711, 2827, 3569, + 3633, 2997, 3487, + 3505, 3155, 3347, + 3243, 3305, 3053, + 0, 3451, 0, + 0, 3593, 0, + 0, 3733, 0, + 0, 3869, 0, + 0, 4005, 0, + 4011, 0, 3865, + 4011, 0, 3865, + 4011, 0, 3865, + 4011, 0, 3865, + 4009, 0, 3865, + 4009, 0, 3865, + 4009, 0, 3865, + 4009, 0, 3863, + 4009, 0, 3863, + 4009, 0, 3863, + 4007, 0, 3863, + 4007, 0, 3861, + 4005, 0, 3861, + 4005, 0, 3859, + 4003, 0, 3857, + 3999, 0, 3853, + 3997, 0, 3849, + 3991, 0, 3845, + 3985, 0, 3837, + 3975, 0, 3827, + 3963, 1522, 3815, + 3945, 2189, 3795, + 3921, 2511, 3769, + 3887, 2745, 3731, + 3835, 2941, 3677, + 3757, 3117, 3589, + 3627, 3279, 3441, + 3357, 3431, 3105, + 0, 3579, 0, + 0, 3721, 0, + 0, 3861, 0, + 0, 3999, 0, + 4095, 0, 3985, + 4095, 0, 3985, + 4095, 0, 3985, + 4095, 0, 3985, + 4095, 0, 3985, + 4095, 0, 3985, + 4095, 0, 3985, + 4095, 0, 3985, + 4095, 0, 3983, + 4095, 0, 3983, + 4095, 0, 3983, + 4095, 0, 3983, + 4095, 0, 3981, + 4095, 0, 3981, + 4095, 0, 3979, + 4095, 0, 3977, + 4095, 0, 3973, + 4095, 0, 3969, + 4095, 0, 3963, + 4095, 0, 3957, + 4095, 0, 3947, + 4091, 1122, 3933, + 4073, 2243, 3913, + 4049, 2605, 3887, + 4015, 2855, 3847, + 3963, 3061, 3789, + 3883, 3239, 3699, + 3751, 3405, 3541, + 3473, 3559, 3169, + 0, 3707, 0, + 0, 3851, 0, + 0, 3993, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4091, + 4095, 0, 4085, + 4095, 0, 4079, + 4095, 0, 4069, + 4095, 0, 4053, + 4095, 2305, 4035, + 4095, 2707, 4007, + 4095, 2971, 3967, + 4091, 3181, 3907, + 4011, 3365, 3813, + 3877, 3531, 3647, + 3593, 3687, 3241, + 0, 3837, 0, + 0, 3981, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2377, 4095, + 4095, 2815, 4095, + 4095, 3091, 4089, + 4095, 3305, 4029, + 4095, 3491, 3933, + 4003, 3659, 3759, + 3717, 3817, 3321, + 0, 3967, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2459, 4095, + 4095, 2929, 4095, + 4095, 3213, 4095, + 4095, 3431, 4095, + 4095, 3619, 4053, + 4095, 3789, 3877, + 3843, 3947, 3413, + 2563, 2115, 2975, + 2561, 2115, 2975, + 2559, 2117, 2975, + 2557, 2119, 2973, + 2555, 2123, 2973, + 2551, 2125, 2971, + 2547, 2131, 2971, + 2539, 2137, 2969, + 2531, 2147, 2965, + 2519, 2159, 2961, + 2501, 2173, 2957, + 2477, 2193, 2951, + 2445, 2217, 2941, + 2395, 2249, 2929, + 2319, 2287, 2913, + 2193, 2333, 2889, + 1937, 2389, 2855, + 0, 2455, 2805, + 0, 2529, 2729, + 0, 2613, 2601, + 0, 2707, 2345, + 0, 2807, 0, + 0, 2913, 0, + 0, 3025, 0, + 0, 3141, 0, + 0, 3261, 0, + 0, 3385, 0, + 0, 3509, 0, + 0, 3637, 0, + 0, 3765, 0, + 0, 3893, 0, + 0, 4023, 0, + 2563, 2113, 2975, + 2563, 2115, 2975, + 2561, 2117, 2975, + 2559, 2119, 2973, + 2557, 2121, 2973, + 2553, 2125, 2973, + 2547, 2131, 2971, + 2541, 2137, 2969, + 2533, 2147, 2965, + 2519, 2157, 2963, + 2503, 2173, 2957, + 2479, 2193, 2951, + 2445, 2217, 2941, + 2397, 2249, 2929, + 2321, 2287, 2913, + 2195, 2333, 2889, + 1942, 2389, 2855, + 0, 2455, 2805, + 0, 2529, 2729, + 0, 2613, 2603, + 0, 2707, 2347, + 0, 2807, 0, + 0, 2913, 0, + 0, 3025, 0, + 0, 3141, 0, + 0, 3261, 0, + 0, 3385, 0, + 0, 3509, 0, + 0, 3637, 0, + 0, 3765, 0, + 0, 3893, 0, + 0, 4023, 0, + 2565, 2113, 2975, + 2565, 2115, 2975, + 2563, 2117, 2975, + 2561, 2119, 2975, + 2559, 2121, 2973, + 2555, 2125, 2973, + 2549, 2131, 2971, + 2543, 2137, 2969, + 2535, 2147, 2967, + 2523, 2157, 2963, + 2505, 2173, 2957, + 2481, 2193, 2951, + 2449, 2217, 2943, + 2399, 2247, 2931, + 2325, 2287, 2913, + 2199, 2333, 2889, + 1950, 2389, 2855, + 201, 2455, 2807, + 0, 2529, 2731, + 0, 2613, 2603, + 0, 2707, 2349, + 0, 2807, 0, + 0, 2913, 0, + 0, 3025, 0, + 0, 3141, 0, + 0, 3261, 0, + 0, 3385, 0, + 0, 3509, 0, + 0, 3637, 0, + 0, 3765, 0, + 0, 3893, 0, + 0, 4023, 0, + 2567, 2113, 2977, + 2567, 2115, 2977, + 2565, 2117, 2975, + 2563, 2119, 2975, + 2561, 2121, 2975, + 2557, 2125, 2973, + 2553, 2131, 2971, + 2545, 2137, 2969, + 2537, 2145, 2967, + 2525, 2157, 2963, + 2509, 2173, 2959, + 2485, 2191, 2953, + 2451, 2217, 2943, + 2403, 2247, 2931, + 2329, 2287, 2913, + 2205, 2333, 2891, + 1959, 2389, 2857, + 515, 2455, 2807, + 0, 2529, 2731, + 0, 2613, 2605, + 0, 2707, 2351, + 0, 2807, 0, + 0, 2913, 0, + 0, 3025, 0, + 0, 3141, 0, + 0, 3261, 0, + 0, 3385, 0, + 0, 3509, 0, + 0, 3637, 0, + 0, 3765, 0, + 0, 3893, 0, + 0, 4023, 0, + 2571, 2113, 2977, + 2569, 2115, 2977, + 2569, 2115, 2977, + 2567, 2117, 2977, + 2563, 2121, 2975, + 2561, 2125, 2975, + 2555, 2129, 2973, + 2549, 2137, 2971, + 2541, 2145, 2969, + 2529, 2157, 2965, + 2511, 2173, 2959, + 2489, 2191, 2953, + 2455, 2217, 2945, + 2407, 2247, 2931, + 2333, 2285, 2915, + 2213, 2333, 2891, + 1972, 2389, 2857, + 748, 2455, 2809, + 0, 2529, 2733, + 0, 2613, 2607, + 0, 2705, 2355, + 0, 2807, 171, + 0, 2913, 0, + 0, 3025, 0, + 0, 3141, 0, + 0, 3261, 0, + 0, 3385, 0, + 0, 3509, 0, + 0, 3637, 0, + 0, 3765, 0, + 0, 3893, 0, + 0, 4023, 0, + 2575, 2113, 2979, + 2575, 2113, 2979, + 2573, 2115, 2977, + 2571, 2117, 2977, + 2569, 2121, 2977, + 2565, 2125, 2975, + 2561, 2129, 2973, + 2553, 2135, 2971, + 2545, 2145, 2969, + 2533, 2157, 2965, + 2517, 2171, 2961, + 2493, 2191, 2955, + 2461, 2215, 2945, + 2413, 2247, 2933, + 2341, 2285, 2917, + 2221, 2333, 2893, + 1988, 2389, 2859, + 942, 2453, 2811, + 0, 2529, 2735, + 0, 2613, 2611, + 0, 2705, 2359, + 0, 2805, 544, + 0, 2913, 0, + 0, 3025, 0, + 0, 3141, 0, + 0, 3261, 0, + 0, 3385, 0, + 0, 3509, 0, + 0, 3637, 0, + 0, 3765, 0, + 0, 3893, 0, + 0, 4023, 0, + 2581, 2111, 2981, + 2581, 2113, 2979, + 2579, 2115, 2979, + 2577, 2117, 2979, + 2575, 2119, 2979, + 2571, 2123, 2977, + 2567, 2129, 2975, + 2559, 2135, 2973, + 2551, 2145, 2971, + 2539, 2155, 2967, + 2523, 2171, 2963, + 2501, 2191, 2955, + 2469, 2215, 2947, + 2423, 2247, 2935, + 2351, 2285, 2919, + 2235, 2331, 2895, + 2009, 2387, 2861, + 1116, 2453, 2813, + 0, 2529, 2737, + 0, 2613, 2613, + 0, 2705, 2367, + 0, 2805, 799, + 0, 2913, 0, + 0, 3025, 0, + 0, 3141, 0, + 0, 3261, 0, + 0, 3385, 0, + 0, 3509, 0, + 0, 3637, 0, + 0, 3765, 0, + 0, 3893, 0, + 0, 4023, 0, + 2589, 2111, 2983, + 2587, 2111, 2983, + 2587, 2113, 2981, + 2585, 2115, 2981, + 2583, 2119, 2981, + 2579, 2123, 2979, + 2575, 2127, 2977, + 2567, 2135, 2975, + 2559, 2143, 2973, + 2547, 2155, 2969, + 2533, 2169, 2965, + 2509, 2189, 2959, + 2479, 2215, 2949, + 2433, 2245, 2937, + 2363, 2285, 2921, + 2251, 2331, 2897, + 2035, 2387, 2865, + 1277, 2453, 2815, + 0, 2529, 2741, + 0, 2613, 2619, + 0, 2705, 2375, + 0, 2805, 1005, + 0, 2913, 0, + 0, 3025, 0, + 0, 3141, 0, + 0, 3261, 0, + 0, 3385, 0, + 0, 3509, 0, + 0, 3637, 0, + 0, 3765, 0, + 0, 3893, 0, + 0, 4023, 0, + 2599, 2109, 2985, + 2597, 2111, 2985, + 2597, 2111, 2985, + 2595, 2113, 2983, + 2593, 2117, 2983, + 2589, 2121, 2983, + 2585, 2125, 2981, + 2579, 2133, 2979, + 2571, 2141, 2975, + 2559, 2153, 2973, + 2543, 2169, 2967, + 2521, 2189, 2961, + 2491, 2213, 2953, + 2447, 2245, 2941, + 2379, 2283, 2923, + 2271, 2331, 2901, + 2069, 2387, 2867, + 1430, 2453, 2819, + 0, 2527, 2747, + 0, 2611, 2625, + 0, 2705, 2385, + 0, 2805, 1185, + 0, 2913, 0, + 0, 3025, 0, + 0, 3141, 0, + 0, 3261, 0, + 0, 3385, 0, + 0, 3509, 0, + 0, 3637, 0, + 0, 3765, 0, + 0, 3893, 0, + 0, 4023, 0, + 2611, 2107, 2989, + 2611, 2109, 2989, + 2609, 2109, 2989, + 2607, 2113, 2987, + 2605, 2115, 2987, + 2603, 2119, 2985, + 2597, 2125, 2985, + 2593, 2131, 2983, + 2585, 2139, 2979, + 2573, 2151, 2977, + 2559, 2167, 2971, + 2537, 2187, 2965, + 2507, 2211, 2957, + 2465, 2243, 2945, + 2401, 2281, 2929, + 2297, 2329, 2905, + 2109, 2385, 2873, + 1577, 2451, 2825, + 0, 2527, 2753, + 0, 2611, 2633, + 0, 2705, 2399, + 0, 2805, 1350, + 0, 2911, 0, + 0, 3025, 0, + 0, 3141, 0, + 0, 3261, 0, + 0, 3385, 0, + 0, 3509, 0, + 0, 3637, 0, + 0, 3765, 0, + 0, 3893, 0, + 0, 4023, 0, + 2629, 2105, 2995, + 2627, 2105, 2993, + 2627, 2107, 2993, + 2625, 2109, 2993, + 2623, 2113, 2991, + 2619, 2117, 2991, + 2615, 2121, 2989, + 2609, 2129, 2987, + 2601, 2137, 2985, + 2591, 2149, 2981, + 2577, 2165, 2977, + 2557, 2185, 2971, + 2529, 2209, 2961, + 2489, 2241, 2951, + 2427, 2279, 2933, + 2331, 2327, 2911, + 2159, 2383, 2879, + 1720, 2451, 2833, + 0, 2525, 2761, + 0, 2611, 2645, + 0, 2703, 2417, + 0, 2805, 1506, + 0, 2911, 0, + 0, 3023, 0, + 0, 3141, 0, + 0, 3261, 0, + 0, 3385, 0, + 0, 3509, 0, + 0, 3637, 0, + 0, 3765, 0, + 0, 3893, 0, + 0, 4023, 0, + 2651, 2101, 3001, + 2649, 2101, 3001, + 2649, 2103, 2999, + 2647, 2105, 2999, + 2645, 2109, 2999, + 2641, 2113, 2997, + 2637, 2119, 2997, + 2633, 2125, 2995, + 2625, 2135, 2991, + 2615, 2147, 2989, + 2601, 2161, 2983, + 2583, 2181, 2977, + 2555, 2207, 2969, + 2517, 2239, 2957, + 2461, 2277, 2941, + 2371, 2325, 2919, + 2217, 2383, 2887, + 1860, 2449, 2841, + 0, 2525, 2773, + 0, 2609, 2659, + 0, 2703, 2441, + 0, 2803, 1654, + 0, 2911, 0, + 0, 3023, 0, + 0, 3141, 0, + 0, 3261, 0, + 0, 3383, 0, + 0, 3509, 0, + 0, 3637, 0, + 0, 3765, 0, + 0, 3893, 0, + 0, 4023, 0, + 2677, 2095, 3009, + 2677, 2097, 3009, + 2675, 2099, 3009, + 2675, 2101, 3009, + 2673, 2105, 3007, + 2669, 2109, 3007, + 2665, 2113, 3005, + 2661, 2121, 3003, + 2653, 2129, 3001, + 2645, 2141, 2997, + 2631, 2157, 2993, + 2615, 2177, 2987, + 2589, 2203, 2979, + 2553, 2235, 2967, + 2501, 2275, 2951, + 2421, 2323, 2929, + 2285, 2379, 2899, + 1998, 2447, 2855, + 0, 2523, 2787, + 0, 2607, 2677, + 0, 2701, 2469, + 0, 2803, 1798, + 0, 2909, 0, + 0, 3023, 0, + 0, 3139, 0, + 0, 3261, 0, + 0, 3383, 0, + 0, 3509, 0, + 0, 3635, 0, + 0, 3765, 0, + 0, 3893, 0, + 0, 4023, 0, + 2713, 2089, 3021, + 2711, 2091, 3021, + 2711, 2093, 3021, + 2709, 2095, 3019, + 2707, 2097, 3019, + 2705, 2101, 3017, + 2701, 2107, 3017, + 2697, 2115, 3015, + 2689, 2123, 3013, + 2681, 2135, 3009, + 2669, 2151, 3005, + 2653, 2171, 2999, + 2631, 2197, 2991, + 2599, 2231, 2979, + 2551, 2269, 2965, + 2479, 2319, 2943, + 2363, 2377, 2913, + 2133, 2443, 2869, + 1197, 2519, 2805, + 0, 2605, 2699, + 0, 2699, 2505, + 0, 2801, 1939, + 0, 2909, 0, + 0, 3021, 0, + 0, 3139, 0, + 0, 3259, 0, + 0, 3383, 0, + 0, 3509, 0, + 0, 3635, 0, + 0, 3765, 0, + 0, 3893, 0, + 0, 4023, 0, + 2755, 2081, 3035, + 2753, 2081, 3035, + 2753, 2083, 3035, + 2751, 2087, 3035, + 2749, 2089, 3033, + 2747, 2093, 3033, + 2745, 2099, 3031, + 2739, 2107, 3029, + 2735, 2115, 3027, + 2727, 2127, 3025, + 2715, 2143, 3019, + 2701, 2165, 3015, + 2681, 2191, 3007, + 2651, 2223, 2995, + 2611, 2265, 2981, + 2549, 2313, 2961, + 2449, 2371, 2931, + 2269, 2439, 2891, + 1794, 2517, 2829, + 0, 2603, 2729, + 0, 2697, 2551, + 0, 2799, 2077, + 0, 2907, 0, + 0, 3021, 0, + 0, 3139, 0, + 0, 3259, 0, + 0, 3383, 0, + 0, 3509, 0, + 0, 3635, 0, + 0, 3763, 0, + 0, 3893, 0, + 0, 4023, 0, + 2805, 2069, 3055, + 2805, 2069, 3055, + 2803, 2071, 3053, + 2803, 2075, 3053, + 2801, 2077, 3053, + 2799, 2081, 3051, + 2797, 2087, 3051, + 2793, 2095, 3049, + 2787, 2105, 3047, + 2781, 2117, 3043, + 2771, 2133, 3039, + 2757, 2155, 3033, + 2739, 2181, 3027, + 2715, 2215, 3017, + 2679, 2257, 3003, + 2625, 2305, 2983, + 2543, 2365, 2955, + 2403, 2433, 2917, + 2105, 2511, 2857, + 0, 2599, 2765, + 0, 2695, 2603, + 0, 2797, 2215, + 0, 2905, 0, + 0, 3019, 0, + 0, 3137, 0, + 0, 3259, 0, + 0, 3381, 0, + 0, 3507, 0, + 0, 3635, 0, + 0, 3763, 0, + 0, 3893, 0, + 0, 4023, 0, + 2865, 2051, 3079, + 2865, 2053, 3079, + 2865, 2055, 3079, + 2863, 2057, 3077, + 2861, 2061, 3077, + 2859, 2065, 3077, + 2857, 2071, 3075, + 2855, 2079, 3073, + 2849, 2089, 3071, + 2843, 2103, 3069, + 2835, 2119, 3065, + 2825, 2141, 3059, + 2809, 2169, 3053, + 2787, 2203, 3043, + 2757, 2245, 3029, + 2713, 2297, 3011, + 2645, 2357, 2985, + 2537, 2427, 2949, + 2335, 2505, 2895, + 1706, 2593, 2811, + 0, 2691, 2667, + 0, 2793, 2351, + 0, 2903, 0, + 0, 3017, 0, + 0, 3135, 0, + 0, 3257, 0, + 0, 3381, 0, + 0, 3507, 0, + 0, 3635, 0, + 0, 3763, 0, + 0, 3893, 0, + 0, 4023, 0, + 2935, 2029, 3109, + 2935, 2030, 3109, + 2935, 2032, 3109, + 2933, 2035, 3109, + 2933, 2038, 3107, + 2931, 2043, 3107, + 2929, 2049, 3105, + 2925, 2057, 3105, + 2921, 2067, 3103, + 2917, 2081, 3099, + 2909, 2099, 3097, + 2901, 2121, 3091, + 2887, 2151, 3085, + 2869, 2187, 3075, + 2843, 2229, 3063, + 2807, 2283, 3047, + 2753, 2345, 3023, + 2671, 2417, 2989, + 2529, 2497, 2939, + 2225, 2587, 2865, + 0, 2685, 2739, + 0, 2789, 2485, + 0, 2899, 0, + 0, 3015, 0, + 0, 3133, 0, + 0, 3255, 0, + 0, 3379, 0, + 0, 3507, 0, + 0, 3633, 0, + 0, 3763, 0, + 0, 3893, 0, + 0, 4023, 0, + 3015, 1995, 3147, + 3013, 1997, 3147, + 3013, 1999, 3147, + 3013, 2002, 3147, + 3011, 2006, 3145, + 3011, 2011, 3145, + 3009, 2017, 3143, + 3007, 2026, 3143, + 3003, 2037, 3141, + 2999, 2051, 3139, + 2993, 2071, 3135, + 2985, 2095, 3131, + 2975, 2125, 3125, + 2959, 2163, 3117, + 2939, 2209, 3105, + 2909, 2263, 3089, + 2867, 2329, 3069, + 2805, 2403, 3037, + 2703, 2485, 2993, + 2519, 2577, 2927, + 2014, 2677, 2819, + 0, 2783, 2619, + 0, 2895, 2004, + 0, 3011, 0, + 0, 3131, 0, + 0, 3253, 0, + 0, 3379, 0, + 0, 3505, 0, + 0, 3633, 0, + 0, 3761, 0, + 0, 3891, 0, + 0, 4023, 0, + 3103, 1947, 3193, + 3103, 1949, 3193, + 3101, 1951, 3193, + 3101, 1954, 3193, + 3101, 1958, 3193, + 3099, 1964, 3191, + 3097, 1971, 3191, + 3095, 1981, 3189, + 3093, 1993, 3187, + 3089, 2009, 3185, + 3085, 2030, 3183, + 3079, 2057, 3179, + 3069, 2089, 3173, + 3057, 2131, 3165, + 3041, 2179, 3155, + 3017, 2237, 3141, + 2985, 2305, 3123, + 2937, 2383, 3095, + 2863, 2469, 3057, + 2743, 2565, 3001, + 2503, 2667, 2911, + 1310, 2775, 2753, + 0, 2889, 2387, + 0, 3005, 0, + 0, 3127, 0, + 0, 3251, 0, + 0, 3377, 0, + 0, 3503, 0, + 0, 3631, 0, + 0, 3761, 0, + 0, 3891, 0, + 0, 4021, 0, + 3199, 1873, 3249, + 3199, 1875, 3249, + 3197, 1878, 3249, + 3197, 1882, 3247, + 3197, 1886, 3247, + 3195, 1893, 3247, + 3195, 1901, 3247, + 3193, 1912, 3245, + 3191, 1927, 3243, + 3189, 1946, 3241, + 3185, 1969, 3239, + 3179, 1999, 3235, + 3173, 2036, 3231, + 3163, 2081, 3225, + 3149, 2137, 3215, + 3131, 2201, 3203, + 3107, 2273, 3187, + 3069, 2357, 3163, + 3015, 2447, 3131, + 2933, 2547, 3083, + 2789, 2653, 3009, + 2481, 2763, 2887, + 0, 2879, 2645, + 0, 2999, 1376, + 0, 3121, 0, + 0, 3247, 0, + 0, 3373, 0, + 0, 3501, 0, + 0, 3629, 0, + 0, 3759, 0, + 0, 3891, 0, + 0, 4021, 0, + 3301, 1750, 3313, + 3301, 1753, 3313, + 3301, 1757, 3313, + 3301, 1761, 3313, + 3301, 1768, 3313, + 3299, 1776, 3311, + 3299, 1787, 3311, + 3297, 1801, 3311, + 3295, 1820, 3309, + 3293, 1843, 3307, + 3291, 1873, 3305, + 3287, 1909, 3301, + 3281, 1954, 3297, + 3273, 2008, 3293, + 3263, 2071, 3285, + 3249, 2145, 3275, + 3229, 2227, 3261, + 3203, 2317, 3241, + 3163, 2417, 3213, + 3103, 2521, 3173, + 3011, 2633, 3113, + 2847, 2749, 3019, + 2451, 2867, 2851, + 0, 2991, 2441, + 0, 3115, 0, + 0, 3241, 0, + 0, 3369, 0, + 0, 3497, 0, + 0, 3627, 0, + 0, 3759, 0, + 0, 3889, 0, + 0, 4019, 0, + 3411, 1507, 3387, + 3411, 1511, 3387, + 3411, 1518, 3387, + 3411, 1526, 3387, + 3409, 1536, 3387, + 3409, 1550, 3387, + 3409, 1568, 3385, + 3407, 1591, 3385, + 3407, 1620, 3383, + 3405, 1656, 3383, + 3403, 1700, 3381, + 3399, 1752, 3377, + 3395, 1815, 3375, + 3389, 1886, 3369, + 3381, 1968, 3363, + 3371, 2057, 3355, + 3355, 2155, 3343, + 3335, 2259, 3327, + 3305, 2371, 3303, + 3263, 2485, 3271, + 3199, 2605, 3223, + 3099, 2727, 3151, + 2913, 2851, 3033, + 2407, 2977, 2801, + 0, 3105, 1804, + 0, 3235, 0, + 0, 3363, 0, + 0, 3493, 0, + 0, 3625, 0, + 0, 3755, 0, + 0, 3887, 0, + 0, 4019, 0, + 3525, 167, 3471, + 3525, 249, 3471, + 3525, 339, 3471, + 3525, 437, 3471, + 3525, 542, 3471, + 3523, 652, 3471, + 3523, 768, 3469, + 3523, 887, 3469, + 3521, 1009, 3467, + 3521, 1133, 3467, + 3519, 1260, 3465, + 3515, 1387, 3463, + 3513, 1516, 3461, + 3509, 1646, 3457, + 3503, 1776, 3451, + 3493, 1907, 3443, + 3483, 2038, 3435, + 3467, 2169, 3421, + 3445, 2301, 3403, + 3415, 2433, 3377, + 3371, 2565, 3339, + 3303, 2697, 3285, + 3193, 2829, 3199, + 2989, 2961, 3051, + 2339, 3093, 2725, + 0, 3225, 0, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 3643, 0, 3563, + 3643, 0, 3563, + 3643, 0, 3563, + 3643, 0, 3563, + 3643, 0, 3563, + 3643, 0, 3563, + 3643, 0, 3561, + 3641, 0, 3561, + 3641, 0, 3561, + 3639, 0, 3559, + 3639, 0, 3559, + 3637, 0, 3557, + 3633, 0, 3555, + 3631, 418, 3551, + 3625, 1228, 3547, + 3619, 1568, 3541, + 3611, 1811, 3533, + 3599, 2011, 3523, + 3583, 2187, 3507, + 3561, 2351, 3487, + 3529, 2505, 3459, + 3483, 2653, 3417, + 3413, 2795, 3355, + 3297, 2937, 3255, + 3075, 3075, 3075, + 2231, 3211, 2595, + 0, 3347, 0, + 0, 3481, 0, + 0, 3615, 0, + 0, 3749, 0, + 0, 3881, 0, + 0, 4015, 0, + 3765, 0, 3663, + 3765, 0, 3663, + 3765, 0, 3663, + 3765, 0, 3663, + 3765, 0, 3663, + 3765, 0, 3663, + 3763, 0, 3661, + 3763, 0, 3661, + 3763, 0, 3661, + 3763, 0, 3659, + 3761, 0, 3659, + 3759, 0, 3657, + 3757, 0, 3655, + 3755, 0, 3653, + 3751, 0, 3649, + 3747, 0, 3645, + 3741, 888, 3639, + 3731, 1638, 3631, + 3719, 1971, 3619, + 3703, 2211, 3603, + 3681, 2409, 3581, + 3647, 2585, 3549, + 3599, 2749, 3503, + 3527, 2901, 3433, + 3405, 3049, 3321, + 3167, 3193, 3103, + 2028, 3333, 2329, + 0, 3471, 0, + 0, 3607, 0, + 0, 3743, 0, + 0, 3877, 0, + 0, 4011, 0, + 3889, 0, 3769, + 3889, 0, 3769, + 3889, 0, 3769, + 3889, 0, 3769, + 3889, 0, 3769, + 3889, 0, 3769, + 3889, 0, 3769, + 3887, 0, 3767, + 3887, 0, 3767, + 3887, 0, 3767, + 3885, 0, 3765, + 3885, 0, 3765, + 3883, 0, 3763, + 3881, 0, 3761, + 3879, 0, 3759, + 3875, 0, 3755, + 3871, 0, 3751, + 3863, 0, 3743, + 3855, 1201, 3735, + 3843, 1912, 3723, + 3825, 2239, 3705, + 3803, 2477, 3681, + 3769, 2675, 3647, + 3719, 2851, 3599, + 3645, 3013, 3523, + 3519, 3167, 3395, + 3269, 3313, 3139, + 1395, 3457, 0, + 0, 3597, 0, + 0, 3735, 0, + 0, 3871, 0, + 0, 4007, 0, + 4015, 0, 3881, + 4015, 0, 3881, + 4015, 0, 3881, + 4015, 0, 3881, + 4015, 0, 3881, + 4015, 0, 3881, + 4015, 0, 3881, + 4015, 0, 3879, + 4013, 0, 3879, + 4013, 0, 3879, + 4013, 0, 3879, + 4011, 0, 3877, + 4011, 0, 3877, + 4009, 0, 3875, + 4007, 0, 3873, + 4005, 0, 3869, + 4001, 0, 3867, + 3995, 0, 3861, + 3989, 0, 3855, + 3981, 0, 3845, + 3967, 1819, 3831, + 3951, 2277, 3813, + 3927, 2555, 3789, + 3893, 2773, 3753, + 3843, 2961, 3701, + 3765, 3129, 3619, + 3637, 3287, 3479, + 3375, 3437, 3185, + 0, 3583, 0, + 0, 3725, 0, + 0, 3865, 0, + 0, 4001, 0, + 4095, 0, 3997, + 4095, 0, 3997, + 4095, 0, 3997, + 4095, 0, 3997, + 4095, 0, 3997, + 4095, 0, 3997, + 4095, 0, 3997, + 4095, 0, 3997, + 4095, 0, 3997, + 4095, 0, 3995, + 4095, 0, 3995, + 4095, 0, 3995, + 4095, 0, 3993, + 4095, 0, 3993, + 4095, 0, 3991, + 4095, 0, 3989, + 4095, 0, 3985, + 4095, 0, 3981, + 4095, 0, 3977, + 4095, 0, 3969, + 4095, 0, 3959, + 4095, 1654, 3947, + 4077, 2321, 3927, + 4053, 2643, 3901, + 4019, 2877, 3865, + 3967, 3075, 3809, + 3889, 3249, 3723, + 3759, 3411, 3573, + 3489, 3563, 3237, + 0, 3711, 0, + 0, 3853, 0, + 0, 3993, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4089, + 4095, 0, 4079, + 4095, 1254, 4065, + 4095, 2375, 4045, + 4095, 2737, 4019, + 4095, 2989, 3979, + 4095, 3193, 3923, + 4015, 3371, 3831, + 3883, 3537, 3673, + 3605, 3691, 3301, + 0, 3839, 0, + 0, 3983, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2437, 4095, + 4095, 2839, 4095, + 4095, 3103, 4095, + 4095, 3313, 4039, + 4095, 3497, 3945, + 4009, 3663, 3779, + 3725, 3819, 3373, + 0, 3969, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2509, 4095, + 4095, 2949, 4095, + 4095, 3223, 4095, + 4095, 3437, 4095, + 4095, 3623, 4065, + 4095, 3791, 3891, + 3849, 3949, 3455, + 2693, 2245, 3107, + 2693, 2247, 3107, + 2691, 2247, 3107, + 2691, 2249, 3107, + 2689, 2251, 3105, + 2685, 2255, 3105, + 2683, 2259, 3103, + 2677, 2263, 3103, + 2671, 2269, 3101, + 2661, 2279, 3097, + 2649, 2291, 3093, + 2633, 2305, 3089, + 2609, 2325, 3083, + 2575, 2349, 3073, + 2525, 2381, 3061, + 2449, 2419, 3043, + 2321, 2465, 3021, + 2065, 2521, 2987, + 0, 2587, 2937, + 0, 2661, 2861, + 0, 2745, 2733, + 0, 2839, 2477, + 0, 2939, 0, + 0, 3045, 0, + 0, 3157, 0, + 0, 3273, 0, + 0, 3393, 0, + 0, 3517, 0, + 0, 3641, 0, + 0, 3769, 0, + 0, 3897, 0, + 0, 4025, 0, + 2695, 2245, 3107, + 2695, 2247, 3107, + 2693, 2247, 3107, + 2691, 2249, 3107, + 2689, 2251, 3105, + 2687, 2255, 3105, + 2683, 2259, 3103, + 2679, 2263, 3103, + 2671, 2269, 3101, + 2663, 2279, 3097, + 2651, 2291, 3095, + 2633, 2305, 3089, + 2609, 2325, 3083, + 2577, 2349, 3073, + 2527, 2381, 3061, + 2451, 2419, 3045, + 2325, 2465, 3021, + 2069, 2521, 2987, + 0, 2587, 2937, + 0, 2661, 2861, + 0, 2745, 2733, + 0, 2839, 2477, + 0, 2939, 0, + 0, 3045, 0, + 0, 3157, 0, + 0, 3273, 0, + 0, 3393, 0, + 0, 3517, 0, + 0, 3641, 0, + 0, 3769, 0, + 0, 3897, 0, + 0, 4025, 0, + 2697, 2245, 3107, + 2695, 2247, 3107, + 2695, 2247, 3107, + 2693, 2249, 3107, + 2691, 2251, 3107, + 2689, 2253, 3105, + 2685, 2257, 3105, + 2679, 2263, 3103, + 2673, 2269, 3101, + 2665, 2279, 3099, + 2653, 2291, 3095, + 2635, 2305, 3089, + 2611, 2325, 3083, + 2577, 2349, 3073, + 2529, 2381, 3061, + 2453, 2419, 3045, + 2327, 2465, 3021, + 2075, 2521, 2987, + 0, 2587, 2937, + 0, 2661, 2861, + 0, 2745, 2735, + 0, 2839, 2479, + 0, 2939, 0, + 0, 3045, 0, + 0, 3157, 0, + 0, 3273, 0, + 0, 3393, 0, + 0, 3517, 0, + 0, 3641, 0, + 0, 3769, 0, + 0, 3897, 0, + 0, 4025, 0, + 2699, 2245, 3109, + 2697, 2245, 3109, + 2697, 2247, 3107, + 2695, 2249, 3107, + 2693, 2251, 3107, + 2691, 2253, 3105, + 2687, 2257, 3105, + 2681, 2263, 3103, + 2675, 2269, 3101, + 2667, 2279, 3099, + 2655, 2289, 3095, + 2637, 2305, 3091, + 2613, 2325, 3083, + 2581, 2349, 3075, + 2531, 2381, 3063, + 2457, 2419, 3045, + 2331, 2465, 3021, + 2081, 2521, 2987, + 333, 2587, 2939, + 0, 2661, 2863, + 0, 2745, 2735, + 0, 2839, 2481, + 0, 2939, 0, + 0, 3045, 0, + 0, 3157, 0, + 0, 3273, 0, + 0, 3393, 0, + 0, 3517, 0, + 0, 3641, 0, + 0, 3769, 0, + 0, 3897, 0, + 0, 4025, 0, + 2701, 2245, 3109, + 2699, 2245, 3109, + 2699, 2247, 3109, + 2697, 2249, 3107, + 2695, 2251, 3107, + 2693, 2253, 3107, + 2689, 2257, 3105, + 2685, 2263, 3103, + 2677, 2269, 3101, + 2669, 2277, 3099, + 2657, 2289, 3095, + 2641, 2305, 3091, + 2617, 2325, 3085, + 2583, 2349, 3075, + 2535, 2379, 3063, + 2461, 2419, 3047, + 2337, 2465, 3023, + 2091, 2521, 2989, + 647, 2587, 2939, + 0, 2661, 2863, + 0, 2745, 2737, + 0, 2839, 2483, + 0, 2939, 0, + 0, 3045, 0, + 0, 3157, 0, + 0, 3273, 0, + 0, 3393, 0, + 0, 3517, 0, + 0, 3641, 0, + 0, 3769, 0, + 0, 3897, 0, + 0, 4025, 0, + 2705, 2245, 3109, + 2703, 2245, 3109, + 2703, 2247, 3109, + 2701, 2247, 3109, + 2699, 2251, 3109, + 2697, 2253, 3107, + 2693, 2257, 3107, + 2687, 2261, 3105, + 2681, 2269, 3103, + 2673, 2277, 3101, + 2661, 2289, 3097, + 2643, 2305, 3091, + 2621, 2323, 3085, + 2587, 2349, 3077, + 2539, 2379, 3063, + 2467, 2417, 3047, + 2345, 2465, 3023, + 2103, 2521, 2989, + 880, 2587, 2941, + 0, 2661, 2865, + 0, 2745, 2739, + 0, 2839, 2487, + 0, 2939, 303, + 0, 3045, 0, + 0, 3157, 0, + 0, 3273, 0, + 0, 3393, 0, + 0, 3517, 0, + 0, 3641, 0, + 0, 3769, 0, + 0, 3897, 0, + 0, 4025, 0, + 2709, 2243, 3111, + 2707, 2245, 3111, + 2707, 2245, 3111, + 2705, 2247, 3111, + 2703, 2249, 3109, + 2701, 2253, 3109, + 2697, 2257, 3107, + 2693, 2261, 3107, + 2685, 2269, 3105, + 2677, 2277, 3101, + 2665, 2289, 3097, + 2649, 2303, 3093, + 2627, 2323, 3087, + 2593, 2347, 3077, + 2545, 2379, 3065, + 2473, 2417, 3049, + 2353, 2465, 3025, + 2121, 2521, 2991, + 1074, 2585, 2943, + 0, 2661, 2867, + 0, 2745, 2743, + 0, 2837, 2493, + 0, 2939, 677, + 0, 3045, 0, + 0, 3157, 0, + 0, 3273, 0, + 0, 3393, 0, + 0, 3517, 0, + 0, 3641, 0, + 0, 3769, 0, + 0, 3897, 0, + 0, 4025, 0, + 2715, 2243, 3113, + 2713, 2243, 3113, + 2713, 2245, 3113, + 2711, 2247, 3111, + 2709, 2249, 3111, + 2707, 2251, 3111, + 2703, 2255, 3109, + 2699, 2261, 3107, + 2693, 2267, 3105, + 2683, 2277, 3103, + 2671, 2287, 3099, + 2655, 2303, 3095, + 2633, 2323, 3089, + 2601, 2347, 3079, + 2555, 2379, 3067, + 2483, 2417, 3051, + 2367, 2463, 3027, + 2141, 2519, 2993, + 1248, 2585, 2945, + 0, 2661, 2869, + 0, 2745, 2745, + 0, 2837, 2499, + 0, 2937, 931, + 0, 3045, 0, + 0, 3157, 0, + 0, 3273, 0, + 0, 3393, 0, + 0, 3517, 0, + 0, 3641, 0, + 0, 3769, 0, + 0, 3897, 0, + 0, 4025, 0, + 2721, 2241, 3115, + 2721, 2243, 3115, + 2719, 2243, 3115, + 2719, 2245, 3113, + 2717, 2247, 3113, + 2715, 2251, 3113, + 2711, 2255, 3111, + 2707, 2259, 3109, + 2701, 2267, 3107, + 2691, 2275, 3105, + 2681, 2287, 3101, + 2665, 2303, 3097, + 2643, 2321, 3091, + 2611, 2347, 3081, + 2565, 2377, 3069, + 2495, 2417, 3053, + 2383, 2463, 3029, + 2167, 2519, 2997, + 1409, 2585, 2947, + 0, 2661, 2873, + 0, 2745, 2751, + 0, 2837, 2507, + 0, 2937, 1137, + 0, 3045, 0, + 0, 3157, 0, + 0, 3273, 0, + 0, 3393, 0, + 0, 3517, 0, + 0, 3641, 0, + 0, 3769, 0, + 0, 3897, 0, + 0, 4025, 0, + 2731, 2241, 3117, + 2731, 2241, 3117, + 2731, 2243, 3117, + 2729, 2243, 3117, + 2727, 2247, 3117, + 2725, 2249, 3115, + 2721, 2253, 3115, + 2717, 2259, 3113, + 2711, 2265, 3111, + 2703, 2273, 3109, + 2691, 2285, 3105, + 2675, 2301, 3099, + 2653, 2321, 3093, + 2623, 2345, 3085, + 2579, 2377, 3073, + 2513, 2415, 3057, + 2403, 2463, 3033, + 2201, 2519, 3001, + 1562, 2585, 2951, + 0, 2659, 2879, + 0, 2745, 2757, + 0, 2837, 2517, + 0, 2937, 1317, + 0, 3045, 0, + 0, 3157, 0, + 0, 3273, 0, + 0, 3393, 0, + 0, 3517, 0, + 0, 3641, 0, + 0, 3769, 0, + 0, 3897, 0, + 0, 4025, 0, + 2745, 2239, 3121, + 2745, 2239, 3121, + 2743, 2241, 3121, + 2741, 2241, 3121, + 2739, 2245, 3119, + 2737, 2247, 3119, + 2735, 2251, 3117, + 2731, 2257, 3117, + 2725, 2263, 3115, + 2717, 2273, 3111, + 2705, 2283, 3109, + 2691, 2299, 3103, + 2669, 2319, 3097, + 2639, 2343, 3089, + 2597, 2375, 3077, + 2533, 2413, 3061, + 2429, 2461, 3037, + 2241, 2517, 3005, + 1709, 2583, 2957, + 0, 2659, 2885, + 0, 2743, 2765, + 0, 2837, 2531, + 0, 2937, 1482, + 0, 3043, 0, + 0, 3157, 0, + 0, 3273, 0, + 0, 3393, 0, + 0, 3517, 0, + 0, 3641, 0, + 0, 3769, 0, + 0, 3897, 0, + 0, 4025, 0, + 2761, 2235, 3127, + 2761, 2237, 3127, + 2761, 2237, 3125, + 2759, 2239, 3125, + 2757, 2241, 3125, + 2755, 2245, 3125, + 2751, 2249, 3123, + 2747, 2253, 3121, + 2741, 2261, 3119, + 2735, 2269, 3117, + 2723, 2281, 3113, + 2709, 2297, 3109, + 2689, 2317, 3103, + 2661, 2341, 3095, + 2621, 2373, 3083, + 2559, 2413, 3067, + 2463, 2459, 3043, + 2291, 2517, 3011, + 1852, 2583, 2965, + 0, 2657, 2893, + 0, 2743, 2777, + 0, 2835, 2549, + 0, 2937, 1638, + 0, 3043, 0, + 0, 3155, 0, + 0, 3273, 0, + 0, 3393, 0, + 0, 3517, 0, + 0, 3641, 0, + 0, 3769, 0, + 0, 3897, 0, + 0, 4025, 0, + 2783, 2231, 3133, + 2783, 2233, 3133, + 2781, 2235, 3133, + 2781, 2235, 3133, + 2779, 2239, 3131, + 2777, 2241, 3131, + 2773, 2245, 3129, + 2769, 2251, 3129, + 2765, 2257, 3127, + 2757, 2267, 3123, + 2747, 2279, 3121, + 2733, 2293, 3115, + 2715, 2313, 3109, + 2687, 2339, 3101, + 2649, 2371, 3089, + 2593, 2409, 3073, + 2503, 2457, 3051, + 2349, 2515, 3019, + 1992, 2581, 2973, + 0, 2657, 2905, + 0, 2741, 2791, + 0, 2835, 2573, + 0, 2935, 1786, + 0, 3043, 0, + 0, 3155, 0, + 0, 3273, 0, + 0, 3393, 0, + 0, 3515, 0, + 0, 3641, 0, + 0, 3769, 0, + 0, 3897, 0, + 0, 4025, 0, + 2811, 2227, 3141, + 2811, 2229, 3141, + 2809, 2229, 3141, + 2809, 2231, 3141, + 2807, 2233, 3141, + 2805, 2237, 3139, + 2801, 2241, 3139, + 2797, 2245, 3137, + 2793, 2253, 3135, + 2787, 2261, 3133, + 2777, 2273, 3129, + 2763, 2289, 3125, + 2747, 2309, 3119, + 2721, 2335, 3111, + 2687, 2367, 3099, + 2633, 2407, 3083, + 2553, 2455, 3061, + 2417, 2511, 3031, + 2129, 2579, 2987, + 0, 2655, 2919, + 0, 2739, 2809, + 0, 2833, 2601, + 0, 2935, 1931, + 0, 3043, 0, + 0, 3155, 0, + 0, 3271, 0, + 0, 3393, 0, + 0, 3515, 0, + 0, 3641, 0, + 0, 3769, 0, + 0, 3897, 0, + 0, 4025, 0, + 2845, 2221, 3153, + 2845, 2221, 3153, + 2843, 2223, 3153, + 2843, 2225, 3153, + 2841, 2227, 3151, + 2839, 2229, 3151, + 2837, 2235, 3149, + 2833, 2239, 3149, + 2829, 2247, 3147, + 2823, 2255, 3145, + 2813, 2267, 3141, + 2801, 2283, 3137, + 2785, 2305, 3131, + 2763, 2329, 3123, + 2731, 2363, 3111, + 2683, 2403, 3097, + 2613, 2451, 3075, + 2495, 2509, 3045, + 2267, 2575, 3003, + 1329, 2653, 2937, + 0, 2737, 2831, + 0, 2831, 2637, + 0, 2933, 2071, + 0, 3041, 0, + 0, 3153, 0, + 0, 3271, 0, + 0, 3391, 0, + 0, 3515, 0, + 0, 3641, 0, + 0, 3767, 0, + 0, 3897, 0, + 0, 4025, 0, + 2887, 2211, 3167, + 2887, 2213, 3167, + 2885, 2215, 3167, + 2885, 2215, 3167, + 2883, 2219, 3167, + 2881, 2221, 3165, + 2879, 2225, 3165, + 2877, 2231, 3163, + 2873, 2239, 3161, + 2867, 2247, 3159, + 2859, 2261, 3157, + 2847, 2277, 3151, + 2833, 2297, 3147, + 2813, 2323, 3139, + 2785, 2355, 3127, + 2743, 2397, 3113, + 2681, 2445, 3093, + 2581, 2503, 3065, + 2401, 2571, 3023, + 1927, 2649, 2961, + 0, 2735, 2861, + 0, 2829, 2683, + 0, 2931, 2211, + 0, 3039, 0, + 0, 3153, 0, + 0, 3271, 0, + 0, 3391, 0, + 0, 3515, 0, + 0, 3641, 0, + 0, 3767, 0, + 0, 3895, 0, + 0, 4025, 0, + 2937, 2199, 3187, + 2937, 2201, 3187, + 2937, 2203, 3187, + 2935, 2203, 3185, + 2935, 2207, 3185, + 2933, 2209, 3185, + 2931, 2213, 3183, + 2929, 2219, 3183, + 2925, 2227, 3181, + 2919, 2237, 3179, + 2913, 2249, 3175, + 2903, 2265, 3171, + 2889, 2287, 3167, + 2873, 2313, 3159, + 2847, 2347, 3149, + 2811, 2389, 3135, + 2757, 2439, 3115, + 2675, 2497, 3087, + 2535, 2565, 3049, + 2237, 2645, 2991, + 0, 2731, 2897, + 0, 2827, 2735, + 0, 2929, 2347, + 0, 3037, 0, + 0, 3151, 0, + 0, 3269, 0, + 0, 3391, 0, + 0, 3515, 0, + 0, 3639, 0, + 0, 3767, 0, + 0, 3895, 0, + 0, 4025, 0, + 2997, 2183, 3211, + 2997, 2185, 3211, + 2997, 2185, 3211, + 2997, 2187, 3211, + 2995, 2189, 3209, + 2993, 2193, 3209, + 2993, 2197, 3209, + 2989, 2203, 3207, + 2987, 2211, 3205, + 2981, 2221, 3203, + 2975, 2235, 3201, + 2967, 2251, 3197, + 2957, 2273, 3191, + 2941, 2301, 3185, + 2919, 2335, 3175, + 2889, 2377, 3161, + 2845, 2429, 3143, + 2777, 2489, 3117, + 2669, 2559, 3081, + 2467, 2637, 3027, + 1839, 2727, 2943, + 0, 2823, 2799, + 0, 2925, 2483, + 0, 3035, 0, + 0, 3149, 0, + 0, 3267, 0, + 0, 3389, 0, + 0, 3513, 0, + 0, 3639, 0, + 0, 3767, 0, + 0, 3895, 0, + 0, 4025, 0, + 3067, 2159, 3241, + 3067, 2161, 3241, + 3067, 2163, 3241, + 3067, 2165, 3241, + 3065, 2167, 3241, + 3065, 2171, 3239, + 3063, 2175, 3239, + 3061, 2181, 3237, + 3057, 2189, 3237, + 3053, 2199, 3235, + 3049, 2213, 3231, + 3041, 2231, 3229, + 3033, 2253, 3223, + 3019, 2283, 3217, + 3001, 2319, 3207, + 2975, 2363, 3195, + 2939, 2415, 3179, + 2887, 2477, 3155, + 2803, 2549, 3121, + 2661, 2629, 3073, + 2357, 2719, 2997, + 0, 2817, 2871, + 0, 2921, 2617, + 0, 3031, 83, + 0, 3147, 0, + 0, 3265, 0, + 0, 3387, 0, + 0, 3511, 0, + 0, 3639, 0, + 0, 3765, 0, + 0, 3895, 0, + 0, 4025, 0, + 3147, 2127, 3279, + 3147, 2127, 3279, + 3147, 2129, 3279, + 3145, 2131, 3279, + 3145, 2135, 3279, + 3143, 2137, 3277, + 3143, 2143, 3277, + 3141, 2149, 3277, + 3139, 2159, 3275, + 3135, 2169, 3273, + 3131, 2185, 3271, + 3125, 2203, 3267, + 3117, 2227, 3263, + 3107, 2257, 3257, + 3091, 2295, 3249, + 3071, 2341, 3237, + 3041, 2397, 3221, + 2999, 2461, 3201, + 2937, 2535, 3171, + 2835, 2617, 3127, + 2651, 2709, 3059, + 2145, 2809, 2953, + 0, 2915, 2751, + 0, 3027, 2137, + 0, 3143, 0, + 0, 3263, 0, + 0, 3385, 0, + 0, 3511, 0, + 0, 3637, 0, + 0, 3765, 0, + 0, 3895, 0, + 0, 4023, 0, + 3235, 2077, 3325, + 3235, 2079, 3325, + 3235, 2081, 3325, + 3233, 2083, 3325, + 3233, 2087, 3325, + 3233, 2091, 3325, + 3231, 2097, 3323, + 3229, 2103, 3323, + 3227, 2113, 3321, + 3225, 2125, 3319, + 3221, 2141, 3317, + 3217, 2163, 3315, + 3211, 2189, 3311, + 3201, 2221, 3305, + 3189, 2263, 3297, + 3173, 2311, 3287, + 3151, 2369, 3273, + 3117, 2437, 3255, + 3069, 2515, 3229, + 2995, 2601, 3189, + 2875, 2697, 3133, + 2635, 2799, 3043, + 1442, 2907, 2885, + 0, 3021, 2519, + 0, 3137, 0, + 0, 3259, 0, + 0, 3383, 0, + 0, 3509, 0, + 0, 3635, 0, + 0, 3763, 0, + 0, 3893, 0, + 0, 4023, 0, + 3331, 2004, 3381, + 3331, 2005, 3381, + 3331, 2007, 3381, + 3331, 2010, 3381, + 3329, 2014, 3381, + 3329, 2019, 3379, + 3329, 2025, 3379, + 3327, 2033, 3379, + 3325, 2045, 3377, + 3323, 2059, 3375, + 3321, 2077, 3373, + 3317, 2101, 3371, + 3311, 2131, 3367, + 3305, 2169, 3363, + 3295, 2215, 3357, + 3281, 2269, 3347, + 3263, 2333, 3335, + 3239, 2405, 3319, + 3201, 2489, 3295, + 3149, 2579, 3263, + 3065, 2679, 3215, + 2923, 2785, 3141, + 2613, 2895, 3019, + 0, 3011, 2777, + 0, 3131, 1508, + 0, 3253, 0, + 0, 3379, 0, + 0, 3505, 0, + 0, 3633, 0, + 0, 3763, 0, + 0, 3891, 0, + 0, 4023, 0, + 3435, 1880, 3445, + 3433, 1882, 3445, + 3433, 1885, 3445, + 3433, 1889, 3445, + 3433, 1894, 3445, + 3433, 1900, 3445, + 3431, 1908, 3443, + 3431, 1919, 3443, + 3429, 1933, 3443, + 3427, 1952, 3441, + 3425, 1975, 3439, + 3423, 2005, 3437, + 3419, 2042, 3435, + 3413, 2087, 3429, + 3405, 2141, 3425, + 3395, 2203, 3417, + 3381, 2277, 3407, + 3361, 2359, 3393, + 3335, 2449, 3373, + 3295, 2549, 3345, + 3237, 2653, 3305, + 3143, 2765, 3245, + 2979, 2881, 3151, + 2583, 2999, 2985, + 0, 3123, 2573, + 0, 3247, 0, + 0, 3373, 0, + 0, 3501, 0, + 0, 3631, 0, + 0, 3759, 0, + 0, 3891, 0, + 0, 4021, 0, + 3543, 1635, 3519, + 3543, 1639, 3519, + 3543, 1644, 3519, + 3543, 1650, 3519, + 3543, 1658, 3519, + 3543, 1668, 3519, + 3541, 1682, 3519, + 3541, 1700, 3517, + 3539, 1723, 3517, + 3539, 1752, 3517, + 3537, 1788, 3515, + 3535, 1832, 3513, + 3531, 1885, 3511, + 3527, 1947, 3507, + 3521, 2019, 3501, + 3513, 2099, 3495, + 3503, 2189, 3487, + 3487, 2287, 3475, + 3467, 2393, 3459, + 3437, 2503, 3435, + 3395, 2617, 3403, + 3331, 2737, 3357, + 3231, 2859, 3285, + 3045, 2983, 3165, + 2539, 3109, 2933, + 0, 3237, 1936, + 0, 3367, 0, + 0, 3495, 0, + 0, 3627, 0, + 0, 3757, 0, + 0, 3887, 0, + 0, 4019, 0, + 3657, 227, 3603, + 3657, 299, 3603, + 3657, 381, 3603, + 3657, 471, 3603, + 3657, 569, 3603, + 3657, 674, 3603, + 3657, 784, 3603, + 3655, 900, 3601, + 3655, 1019, 3601, + 3653, 1141, 3601, + 3653, 1265, 3599, + 3651, 1392, 3597, + 3649, 1520, 3595, + 3645, 1648, 3593, + 3641, 1778, 3589, + 3635, 1908, 3583, + 3625, 2039, 3577, + 3615, 2171, 3567, + 3599, 2301, 3553, + 3577, 2433, 3535, + 3547, 2565, 3509, + 3503, 2697, 3471, + 3435, 2829, 3417, + 3327, 2961, 3331, + 3121, 3093, 3183, + 2471, 3225, 2857, + 0, 3357, 0, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 3775, 0, 3695, + 3775, 0, 3695, + 3775, 0, 3695, + 3775, 0, 3695, + 3775, 0, 3695, + 3775, 0, 3695, + 3775, 0, 3695, + 3775, 0, 3693, + 3773, 0, 3693, + 3773, 0, 3693, + 3771, 0, 3691, + 3771, 0, 3691, + 3769, 0, 3689, + 3765, 0, 3687, + 3763, 550, 3683, + 3757, 1360, 3679, + 3751, 1700, 3673, + 3743, 1943, 3665, + 3731, 2143, 3655, + 3715, 2319, 3639, + 3693, 2483, 3619, + 3661, 2637, 3591, + 3615, 2785, 3549, + 3545, 2927, 3487, + 3429, 3069, 3387, + 3207, 3207, 3207, + 2363, 3343, 2727, + 0, 3479, 0, + 0, 3613, 0, + 0, 3747, 0, + 0, 3881, 0, + 0, 4013, 0, + 3897, 0, 3795, + 3897, 0, 3795, + 3897, 0, 3795, + 3897, 0, 3795, + 3897, 0, 3795, + 3897, 0, 3795, + 3897, 0, 3795, + 3897, 0, 3793, + 3895, 0, 3793, + 3895, 0, 3793, + 3895, 0, 3793, + 3893, 0, 3791, + 3891, 0, 3789, + 3889, 0, 3787, + 3887, 0, 3785, + 3883, 0, 3781, + 3879, 0, 3777, + 3873, 1021, 3771, + 3863, 1770, 3763, + 3851, 2103, 3751, + 3835, 2343, 3735, + 3813, 2541, 3713, + 3779, 2717, 3681, + 3731, 2881, 3635, + 3659, 3033, 3567, + 3537, 3181, 3453, + 3299, 3325, 3235, + 2161, 3465, 2461, + 0, 3603, 0, + 0, 3739, 0, + 0, 3875, 0, + 0, 4009, 0, + 4021, 0, 3901, + 4021, 0, 3901, + 4021, 0, 3901, + 4021, 0, 3901, + 4021, 0, 3901, + 4021, 0, 3901, + 4021, 0, 3901, + 4021, 0, 3901, + 4019, 0, 3899, + 4019, 0, 3899, + 4019, 0, 3899, + 4019, 0, 3899, + 4017, 0, 3897, + 4015, 0, 3895, + 4013, 0, 3893, + 4011, 0, 3891, + 4007, 0, 3887, + 4003, 0, 3883, + 3995, 0, 3875, + 3987, 1333, 3867, + 3975, 2044, 3855, + 3957, 2373, 3837, + 3935, 2609, 3813, + 3901, 2807, 3779, + 3851, 2983, 3731, + 3777, 3145, 3655, + 3651, 3299, 3527, + 3401, 3445, 3271, + 1527, 3589, 0, + 0, 3729, 0, + 0, 3867, 0, + 0, 4005, 0, + 4095, 0, 4013, + 4095, 0, 4013, + 4095, 0, 4013, + 4095, 0, 4013, + 4095, 0, 4013, + 4095, 0, 4013, + 4095, 0, 4013, + 4095, 0, 4013, + 4095, 0, 4011, + 4095, 0, 4011, + 4095, 0, 4011, + 4095, 0, 4011, + 4095, 0, 4009, + 4095, 0, 4009, + 4095, 0, 4007, + 4095, 0, 4005, + 4095, 0, 4003, + 4095, 0, 3999, + 4095, 0, 3993, + 4095, 0, 3987, + 4095, 0, 3977, + 4095, 1951, 3963, + 4083, 2409, 3947, + 4059, 2687, 3921, + 4025, 2905, 3885, + 3975, 3093, 3833, + 3897, 3261, 3751, + 3769, 3419, 3611, + 3509, 3569, 3317, + 0, 3715, 0, + 0, 3857, 0, + 0, 3997, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4091, + 4095, 1786, 4079, + 4095, 2453, 4059, + 4095, 2775, 4033, + 4095, 3009, 3997, + 4095, 3207, 3941, + 4021, 3381, 3855, + 3891, 3543, 3705, + 3621, 3695, 3369, + 0, 3843, 0, + 0, 3985, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 1387, 4095, + 4095, 2507, 4095, + 4095, 2869, 4095, + 4095, 3121, 4095, + 4095, 3325, 4055, + 4095, 3503, 3963, + 4015, 3669, 3805, + 3737, 3823, 3433, + 0, 3971, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2569, 4095, + 4095, 2971, 4095, + 4095, 3235, 4095, + 4095, 3445, 4095, + 4095, 3629, 4077, + 4095, 3795, 3911, + 3859, 3951, 3505, + 2825, 2377, 3239, + 2825, 2377, 3239, + 2825, 2379, 3239, + 2823, 2379, 3239, + 2821, 2381, 3237, + 2819, 2383, 3237, + 2817, 2387, 3237, + 2813, 2391, 3235, + 2809, 2395, 3233, + 2803, 2403, 3231, + 2793, 2411, 3229, + 2781, 2423, 3225, + 2763, 2437, 3221, + 2739, 2457, 3215, + 2705, 2481, 3205, + 2657, 2513, 3193, + 2579, 2551, 3175, + 2453, 2597, 3153, + 2193, 2653, 3119, + 0, 2719, 3069, + 0, 2793, 2993, + 0, 2879, 2865, + 0, 2971, 2607, + 0, 3071, 0, + 0, 3177, 0, + 0, 3289, 0, + 0, 3405, 0, + 0, 3525, 0, + 0, 3649, 0, + 0, 3775, 0, + 0, 3901, 0, + 0, 4029, 0, + 2827, 2377, 3239, + 2827, 2377, 3239, + 2825, 2379, 3239, + 2825, 2379, 3239, + 2823, 2381, 3239, + 2821, 2383, 3237, + 2817, 2387, 3237, + 2815, 2391, 3235, + 2809, 2395, 3235, + 2803, 2403, 3233, + 2793, 2411, 3229, + 2781, 2423, 3225, + 2765, 2437, 3221, + 2741, 2457, 3215, + 2707, 2481, 3205, + 2657, 2513, 3193, + 2581, 2551, 3177, + 2453, 2597, 3153, + 2197, 2653, 3119, + 0, 2719, 3069, + 0, 2793, 2993, + 0, 2877, 2865, + 0, 2971, 2609, + 0, 3071, 0, + 0, 3177, 0, + 0, 3289, 0, + 0, 3405, 0, + 0, 3525, 0, + 0, 3649, 0, + 0, 3775, 0, + 0, 3901, 0, + 0, 4029, 0, + 2827, 2377, 3239, + 2827, 2377, 3239, + 2827, 2379, 3239, + 2825, 2379, 3239, + 2823, 2381, 3239, + 2821, 2383, 3237, + 2819, 2387, 3237, + 2815, 2391, 3235, + 2811, 2395, 3235, + 2803, 2401, 3233, + 2795, 2411, 3229, + 2783, 2423, 3227, + 2765, 2437, 3221, + 2743, 2457, 3215, + 2709, 2481, 3205, + 2659, 2513, 3193, + 2583, 2551, 3177, + 2457, 2597, 3153, + 2201, 2653, 3119, + 0, 2719, 3069, + 0, 2793, 2993, + 0, 2877, 2867, + 0, 2971, 2609, + 0, 3071, 0, + 0, 3177, 0, + 0, 3289, 0, + 0, 3405, 0, + 0, 3525, 0, + 0, 3649, 0, + 0, 3775, 0, + 0, 3901, 0, + 0, 4029, 0, + 2829, 2377, 3241, + 2829, 2377, 3239, + 2827, 2379, 3239, + 2827, 2379, 3239, + 2825, 2381, 3239, + 2823, 2383, 3239, + 2821, 2387, 3237, + 2817, 2389, 3237, + 2811, 2395, 3235, + 2805, 2401, 3233, + 2797, 2411, 3231, + 2785, 2423, 3227, + 2767, 2437, 3221, + 2743, 2457, 3215, + 2711, 2481, 3207, + 2661, 2513, 3193, + 2585, 2551, 3177, + 2459, 2597, 3153, + 2207, 2653, 3119, + 0, 2719, 3069, + 0, 2793, 2993, + 0, 2877, 2867, + 0, 2971, 2611, + 0, 3071, 0, + 0, 3177, 0, + 0, 3289, 0, + 0, 3405, 0, + 0, 3525, 0, + 0, 3649, 0, + 0, 3775, 0, + 0, 3901, 0, + 0, 4029, 0, + 2831, 2377, 3241, + 2831, 2377, 3241, + 2829, 2377, 3241, + 2829, 2379, 3239, + 2827, 2381, 3239, + 2825, 2383, 3239, + 2823, 2385, 3237, + 2819, 2389, 3237, + 2813, 2395, 3235, + 2807, 2401, 3233, + 2799, 2411, 3231, + 2787, 2421, 3227, + 2769, 2437, 3223, + 2745, 2457, 3215, + 2713, 2481, 3207, + 2663, 2513, 3195, + 2589, 2551, 3177, + 2463, 2597, 3153, + 2213, 2653, 3119, + 465, 2719, 3071, + 0, 2793, 2995, + 0, 2877, 2869, + 0, 2971, 2613, + 0, 3071, 0, + 0, 3177, 0, + 0, 3289, 0, + 0, 3405, 0, + 0, 3525, 0, + 0, 3649, 0, + 0, 3775, 0, + 0, 3901, 0, + 0, 4029, 0, + 2833, 2375, 3241, + 2833, 2377, 3241, + 2833, 2377, 3241, + 2831, 2379, 3241, + 2829, 2381, 3241, + 2827, 2383, 3239, + 2825, 2385, 3239, + 2821, 2389, 3237, + 2817, 2395, 3237, + 2809, 2401, 3235, + 2801, 2411, 3231, + 2789, 2421, 3227, + 2773, 2437, 3223, + 2749, 2457, 3217, + 2715, 2481, 3207, + 2667, 2511, 3195, + 2593, 2551, 3179, + 2469, 2597, 3155, + 2223, 2653, 3121, + 779, 2719, 3071, + 0, 2793, 2995, + 0, 2877, 2869, + 0, 2971, 2615, + 0, 3071, 0, + 0, 3177, 0, + 0, 3289, 0, + 0, 3405, 0, + 0, 3525, 0, + 0, 3649, 0, + 0, 3773, 0, + 0, 3901, 0, + 0, 4029, 0, + 2837, 2375, 3243, + 2837, 2377, 3243, + 2835, 2377, 3241, + 2835, 2379, 3241, + 2833, 2379, 3241, + 2831, 2383, 3241, + 2829, 2385, 3239, + 2825, 2389, 3239, + 2819, 2395, 3237, + 2813, 2401, 3235, + 2805, 2409, 3233, + 2793, 2421, 3229, + 2777, 2437, 3223, + 2753, 2455, 3217, + 2719, 2481, 3209, + 2671, 2511, 3197, + 2599, 2551, 3179, + 2477, 2597, 3155, + 2237, 2653, 3123, + 1012, 2719, 3073, + 0, 2793, 2997, + 0, 2877, 2871, + 0, 2971, 2619, + 0, 3071, 435, + 0, 3177, 0, + 0, 3289, 0, + 0, 3405, 0, + 0, 3525, 0, + 0, 3649, 0, + 0, 3773, 0, + 0, 3901, 0, + 0, 4029, 0, + 2841, 2375, 3243, + 2841, 2375, 3243, + 2839, 2377, 3243, + 2839, 2377, 3243, + 2837, 2379, 3243, + 2835, 2381, 3241, + 2833, 2385, 3241, + 2829, 2389, 3239, + 2825, 2393, 3239, + 2819, 2401, 3237, + 2809, 2409, 3233, + 2797, 2421, 3229, + 2781, 2435, 3225, + 2759, 2455, 3219, + 2725, 2479, 3209, + 2679, 2511, 3197, + 2605, 2549, 3181, + 2487, 2597, 3157, + 2253, 2653, 3123, + 1206, 2719, 3075, + 0, 2793, 2999, + 0, 2877, 2875, + 0, 2971, 2625, + 0, 3071, 809, + 0, 3177, 0, + 0, 3289, 0, + 0, 3405, 0, + 0, 3525, 0, + 0, 3649, 0, + 0, 3773, 0, + 0, 3901, 0, + 0, 4029, 0, + 2847, 2375, 3245, + 2847, 2375, 3245, + 2845, 2375, 3245, + 2845, 2377, 3245, + 2843, 2379, 3243, + 2841, 2381, 3243, + 2839, 2383, 3243, + 2835, 2387, 3241, + 2831, 2393, 3239, + 2825, 2399, 3237, + 2815, 2409, 3235, + 2803, 2419, 3231, + 2787, 2435, 3227, + 2765, 2455, 3221, + 2733, 2479, 3211, + 2687, 2511, 3199, + 2615, 2549, 3183, + 2499, 2597, 3159, + 2273, 2653, 3125, + 1380, 2717, 3077, + 0, 2793, 3003, + 0, 2877, 2877, + 0, 2969, 2631, + 0, 3071, 1063, + 0, 3177, 0, + 0, 3289, 0, + 0, 3405, 0, + 0, 3525, 0, + 0, 3649, 0, + 0, 3773, 0, + 0, 3901, 0, + 0, 4029, 0, + 2855, 2373, 3247, + 2853, 2373, 3247, + 2853, 2375, 3247, + 2853, 2375, 3247, + 2851, 2377, 3245, + 2849, 2379, 3245, + 2847, 2383, 3245, + 2843, 2387, 3243, + 2839, 2391, 3241, + 2833, 2399, 3239, + 2823, 2407, 3237, + 2813, 2419, 3233, + 2797, 2435, 3229, + 2775, 2453, 3223, + 2743, 2479, 3213, + 2697, 2509, 3201, + 2627, 2549, 3185, + 2515, 2595, 3161, + 2299, 2651, 3129, + 1541, 2717, 3079, + 0, 2793, 3005, + 0, 2877, 2883, + 0, 2969, 2639, + 0, 3069, 1269, + 0, 3177, 0, + 0, 3289, 0, + 0, 3405, 0, + 0, 3525, 0, + 0, 3649, 0, + 0, 3773, 0, + 0, 3901, 0, + 0, 4029, 0, + 2865, 2371, 3249, + 2863, 2373, 3249, + 2863, 2373, 3249, + 2863, 2375, 3249, + 2861, 2377, 3249, + 2859, 2379, 3249, + 2857, 2381, 3247, + 2853, 2385, 3247, + 2849, 2391, 3245, + 2843, 2397, 3243, + 2835, 2405, 3241, + 2823, 2417, 3237, + 2807, 2433, 3231, + 2787, 2453, 3225, + 2755, 2477, 3217, + 2711, 2509, 3205, + 2645, 2547, 3189, + 2535, 2595, 3165, + 2333, 2651, 3133, + 1694, 2717, 3085, + 0, 2791, 3011, + 0, 2877, 2889, + 0, 2969, 2649, + 0, 3069, 1449, + 0, 3177, 0, + 0, 3289, 0, + 0, 3405, 0, + 0, 3525, 0, + 0, 3649, 0, + 0, 3773, 0, + 0, 3901, 0, + 0, 4029, 0, + 2877, 2369, 3253, + 2877, 2371, 3253, + 2877, 2371, 3253, + 2875, 2373, 3253, + 2873, 2375, 3253, + 2873, 2377, 3251, + 2869, 2379, 3251, + 2867, 2383, 3251, + 2863, 2389, 3249, + 2857, 2395, 3247, + 2849, 2405, 3245, + 2837, 2415, 3241, + 2823, 2431, 3235, + 2801, 2451, 3229, + 2773, 2475, 3221, + 2729, 2507, 3209, + 2665, 2547, 3193, + 2563, 2593, 3169, + 2373, 2649, 3137, + 1841, 2715, 3089, + 0, 2791, 3017, + 0, 2875, 2897, + 0, 2969, 2663, + 0, 3069, 1614, + 0, 3177, 0, + 0, 3289, 0, + 0, 3405, 0, + 0, 3525, 0, + 0, 3649, 0, + 0, 3773, 0, + 0, 3901, 0, + 0, 4029, 0, + 2895, 2367, 3259, + 2893, 2367, 3259, + 2893, 2369, 3259, + 2893, 2369, 3259, + 2891, 2371, 3257, + 2889, 2373, 3257, + 2887, 2377, 3257, + 2883, 2381, 3255, + 2879, 2385, 3253, + 2873, 2393, 3251, + 2867, 2401, 3249, + 2855, 2413, 3245, + 2841, 2429, 3241, + 2821, 2449, 3235, + 2793, 2473, 3227, + 2753, 2505, 3215, + 2691, 2545, 3199, + 2595, 2591, 3175, + 2423, 2649, 3143, + 1984, 2715, 3097, + 0, 2789, 3025, + 0, 2875, 2909, + 0, 2967, 2681, + 0, 3069, 1770, + 0, 3175, 0, + 0, 3289, 0, + 0, 3405, 0, + 0, 3525, 0, + 0, 3649, 0, + 0, 3773, 0, + 0, 3901, 0, + 0, 4029, 0, + 2915, 2363, 3265, + 2915, 2365, 3265, + 2915, 2365, 3265, + 2913, 2367, 3265, + 2913, 2367, 3265, + 2911, 2371, 3263, + 2909, 2373, 3263, + 2905, 2377, 3261, + 2901, 2383, 3261, + 2897, 2389, 3259, + 2889, 2399, 3255, + 2879, 2411, 3253, + 2865, 2425, 3247, + 2847, 2445, 3241, + 2819, 2471, 3233, + 2781, 2503, 3221, + 2725, 2541, 3205, + 2637, 2589, 3183, + 2481, 2647, 3151, + 2123, 2713, 3107, + 0, 2789, 3037, + 0, 2873, 2923, + 0, 2967, 2705, + 0, 3067, 1919, + 0, 3175, 0, + 0, 3287, 0, + 0, 3405, 0, + 0, 3525, 0, + 0, 3649, 0, + 0, 3773, 0, + 0, 3901, 0, + 0, 4029, 0, + 2943, 2359, 3275, + 2943, 2359, 3273, + 2943, 2361, 3273, + 2941, 2361, 3273, + 2941, 2363, 3273, + 2939, 2365, 3273, + 2937, 2369, 3271, + 2933, 2373, 3271, + 2931, 2377, 3269, + 2925, 2385, 3267, + 2919, 2393, 3265, + 2909, 2405, 3261, + 2897, 2421, 3257, + 2879, 2441, 3251, + 2853, 2467, 3243, + 2819, 2499, 3231, + 2767, 2539, 3215, + 2685, 2587, 3193, + 2549, 2643, 3163, + 2261, 2711, 3119, + 0, 2787, 3051, + 0, 2871, 2941, + 0, 2965, 2733, + 0, 3067, 2063, + 0, 3175, 0, + 0, 3287, 0, + 0, 3405, 0, + 0, 3525, 0, + 0, 3647, 0, + 0, 3773, 0, + 0, 3901, 0, + 0, 4029, 0, + 2977, 2353, 3285, + 2977, 2353, 3285, + 2977, 2353, 3285, + 2975, 2355, 3285, + 2975, 2357, 3285, + 2973, 2359, 3283, + 2971, 2363, 3283, + 2969, 2367, 3281, + 2965, 2371, 3281, + 2961, 2379, 3279, + 2955, 2387, 3277, + 2945, 2401, 3273, + 2933, 2415, 3269, + 2917, 2437, 3263, + 2895, 2461, 3255, + 2863, 2495, 3243, + 2815, 2535, 3229, + 2745, 2583, 3207, + 2627, 2641, 3177, + 2399, 2707, 3135, + 1461, 2785, 3069, + 0, 2869, 2965, + 0, 2963, 2769, + 0, 3065, 2203, + 0, 3173, 0, + 0, 3287, 0, + 0, 3403, 0, + 0, 3525, 0, + 0, 3647, 0, + 0, 3773, 0, + 0, 3901, 0, + 0, 4029, 0, + 3019, 2343, 3301, + 3019, 2343, 3299, + 3019, 2345, 3299, + 3017, 2347, 3299, + 3017, 2347, 3299, + 3015, 2351, 3299, + 3013, 2353, 3297, + 3011, 2357, 3297, + 3009, 2363, 3295, + 3005, 2371, 3293, + 2999, 2379, 3291, + 2991, 2393, 3289, + 2979, 2409, 3285, + 2965, 2429, 3279, + 2945, 2455, 3271, + 2917, 2487, 3259, + 2875, 2529, 3245, + 2813, 2577, 3225, + 2713, 2635, 3197, + 2533, 2703, 3155, + 2059, 2781, 3093, + 0, 2867, 2993, + 0, 2961, 2815, + 0, 3063, 2343, + 0, 3171, 0, + 0, 3285, 0, + 0, 3403, 0, + 0, 3523, 0, + 0, 3647, 0, + 0, 3773, 0, + 0, 3899, 0, + 0, 4029, 0, + 3071, 2331, 3319, + 3069, 2331, 3319, + 3069, 2333, 3319, + 3069, 2335, 3319, + 3067, 2335, 3319, + 3067, 2339, 3317, + 3065, 2341, 3317, + 3063, 2345, 3315, + 3061, 2351, 3315, + 3057, 2359, 3313, + 3051, 2369, 3311, + 3045, 2381, 3307, + 3035, 2397, 3303, + 3023, 2419, 3299, + 3005, 2445, 3291, + 2979, 2479, 3281, + 2943, 2521, 3267, + 2891, 2571, 3247, + 2807, 2629, 3219, + 2667, 2699, 3181, + 2369, 2777, 3123, + 0, 2863, 3031, + 0, 2959, 2867, + 0, 3061, 2479, + 0, 3169, 0, + 0, 3283, 0, + 0, 3401, 0, + 0, 3523, 0, + 0, 3647, 0, + 0, 3773, 0, + 0, 3899, 0, + 0, 4027, 0, + 3131, 2315, 3343, + 3131, 2315, 3343, + 3129, 2317, 3343, + 3129, 2317, 3343, + 3129, 2319, 3343, + 3127, 2321, 3341, + 3125, 2325, 3341, + 3125, 2329, 3341, + 3121, 2335, 3339, + 3119, 2343, 3337, + 3113, 2353, 3335, + 3107, 2367, 3333, + 3099, 2383, 3329, + 3089, 2405, 3323, + 3073, 2433, 3317, + 3051, 2467, 3307, + 3021, 2509, 3293, + 2977, 2561, 3275, + 2909, 2621, 3249, + 2801, 2691, 3213, + 2599, 2769, 3159, + 1971, 2859, 3075, + 0, 2955, 2931, + 0, 3057, 2615, + 0, 3167, 0, + 0, 3281, 0, + 0, 3399, 0, + 0, 3521, 0, + 0, 3645, 0, + 0, 3771, 0, + 0, 3899, 0, + 0, 4027, 0, + 3201, 2291, 3373, + 3199, 2291, 3373, + 3199, 2293, 3373, + 3199, 2295, 3373, + 3199, 2297, 3373, + 3197, 2299, 3373, + 3197, 2303, 3371, + 3195, 2307, 3371, + 3193, 2313, 3371, + 3189, 2321, 3369, + 3185, 2331, 3367, + 3181, 2345, 3363, + 3173, 2363, 3361, + 3165, 2387, 3355, + 3151, 2415, 3349, + 3133, 2451, 3339, + 3107, 2495, 3327, + 3071, 2547, 3311, + 3019, 2609, 3287, + 2935, 2681, 3253, + 2793, 2761, 3205, + 2489, 2851, 3129, + 0, 2949, 3003, + 0, 3053, 2749, + 0, 3163, 215, + 0, 3279, 0, + 0, 3397, 0, + 0, 3519, 0, + 0, 3645, 0, + 0, 3771, 0, + 0, 3899, 0, + 0, 4027, 0, + 3279, 2257, 3411, + 3279, 2259, 3411, + 3279, 2259, 3411, + 3279, 2261, 3411, + 3277, 2263, 3411, + 3277, 2267, 3411, + 3275, 2271, 3409, + 3275, 2275, 3409, + 3273, 2281, 3409, + 3271, 2291, 3407, + 3267, 2301, 3405, + 3263, 2317, 3403, + 3257, 2335, 3399, + 3249, 2359, 3395, + 3239, 2389, 3389, + 3223, 2427, 3381, + 3203, 2473, 3369, + 3173, 2529, 3355, + 3131, 2593, 3333, + 3069, 2667, 3303, + 2967, 2749, 3259, + 2783, 2841, 3191, + 2277, 2941, 3085, + 0, 3047, 2883, + 0, 3159, 2269, + 0, 3275, 0, + 0, 3395, 0, + 0, 3517, 0, + 0, 3643, 0, + 0, 3769, 0, + 0, 3897, 0, + 0, 4027, 0, + 3367, 2209, 3457, + 3367, 2209, 3457, + 3367, 2211, 3457, + 3367, 2213, 3457, + 3365, 2215, 3457, + 3365, 2219, 3457, + 3365, 2223, 3457, + 3363, 2229, 3455, + 3361, 2235, 3455, + 3361, 2245, 3453, + 3357, 2257, 3451, + 3353, 2273, 3449, + 3349, 2295, 3447, + 3343, 2321, 3443, + 3333, 2353, 3437, + 3321, 2395, 3429, + 3305, 2443, 3419, + 3283, 2503, 3407, + 3249, 2571, 3387, + 3201, 2647, 3361, + 3127, 2735, 3321, + 3007, 2829, 3265, + 2767, 2931, 3175, + 1574, 3039, 3017, + 0, 3153, 2651, + 0, 3271, 0, + 0, 3391, 0, + 0, 3515, 0, + 0, 3641, 0, + 0, 3767, 0, + 0, 3895, 0, + 0, 4025, 0, + 3463, 2135, 3513, + 3463, 2135, 3513, + 3463, 2137, 3513, + 3463, 2139, 3513, + 3463, 2143, 3513, + 3461, 2145, 3513, + 3461, 2151, 3511, + 3461, 2157, 3511, + 3459, 2165, 3511, + 3457, 2177, 3509, + 3455, 2191, 3507, + 3453, 2209, 3505, + 3449, 2233, 3503, + 3443, 2263, 3499, + 3437, 2301, 3495, + 3427, 2347, 3489, + 3413, 2401, 3479, + 3395, 2465, 3467, + 3371, 2537, 3451, + 3333, 2621, 3427, + 3281, 2711, 3395, + 3197, 2811, 3347, + 3055, 2917, 3273, + 2745, 3027, 3151, + 0, 3143, 2909, + 0, 3263, 1640, + 0, 3385, 0, + 0, 3511, 0, + 0, 3637, 0, + 0, 3765, 0, + 0, 3895, 0, + 0, 4023, 0, + 3567, 2011, 3577, + 3567, 2012, 3577, + 3567, 2014, 3577, + 3565, 2017, 3577, + 3565, 2021, 3577, + 3565, 2026, 3577, + 3565, 2032, 3577, + 3563, 2040, 3577, + 3563, 2051, 3575, + 3561, 2065, 3575, + 3561, 2083, 3573, + 3557, 2107, 3571, + 3555, 2137, 3569, + 3551, 2173, 3567, + 3545, 2219, 3563, + 3537, 2273, 3557, + 3527, 2335, 3549, + 3513, 2409, 3539, + 3493, 2491, 3525, + 3467, 2581, 3505, + 3427, 2681, 3477, + 3369, 2785, 3437, + 3275, 2897, 3377, + 3111, 3013, 3283, + 2715, 3131, 3117, + 0, 3255, 2705, + 0, 3379, 0, + 0, 3505, 0, + 0, 3633, 0, + 0, 3763, 0, + 0, 3891, 0, + 0, 4023, 0, + 3675, 1765, 3653, + 3675, 1767, 3653, + 3675, 1771, 3651, + 3675, 1776, 3651, + 3675, 1782, 3651, + 3675, 1790, 3651, + 3675, 1801, 3651, + 3673, 1814, 3651, + 3673, 1832, 3651, + 3671, 1855, 3649, + 3671, 1884, 3649, + 3669, 1920, 3647, + 3667, 1964, 3645, + 3663, 2017, 3643, + 3659, 2079, 3639, + 3653, 2151, 3633, + 3645, 2231, 3627, + 3635, 2321, 3619, + 3619, 2419, 3607, + 3599, 2525, 3591, + 3569, 2635, 3567, + 3527, 2749, 3535, + 3465, 2869, 3489, + 3363, 2991, 3417, + 3177, 3115, 3297, + 2671, 3241, 3065, + 0, 3369, 2069, + 0, 3499, 0, + 0, 3627, 0, + 0, 3759, 0, + 0, 3889, 0, + 0, 4021, 0, + 3789, 297, 3735, + 3789, 359, 3735, + 3789, 432, 3735, + 3789, 513, 3735, + 3789, 603, 3735, + 3789, 701, 3735, + 3789, 806, 3735, + 3789, 917, 3735, + 3787, 1032, 3733, + 3787, 1151, 3733, + 3785, 1273, 3733, + 3785, 1398, 3731, + 3783, 1524, 3729, + 3781, 1652, 3727, + 3777, 1781, 3725, + 3773, 1910, 3721, + 3767, 2040, 3715, + 3759, 2171, 3709, + 3747, 2303, 3699, + 3731, 2433, 3685, + 3709, 2565, 3667, + 3679, 2697, 3641, + 3635, 2829, 3603, + 3567, 2961, 3549, + 3459, 3093, 3463, + 3253, 3225, 3315, + 2603, 3357, 2989, + 0, 3489, 0, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 3907, 0, 3827, + 3907, 0, 3827, + 3907, 0, 3827, + 3907, 0, 3827, + 3907, 0, 3827, + 3907, 0, 3827, + 3907, 0, 3827, + 3907, 0, 3827, + 3907, 0, 3827, + 3905, 0, 3825, + 3905, 0, 3825, + 3903, 0, 3823, + 3903, 0, 3823, + 3901, 0, 3821, + 3899, 0, 3819, + 3895, 682, 3815, + 3891, 1493, 3811, + 3883, 1832, 3805, + 3875, 2075, 3797, + 3863, 2275, 3787, + 3847, 2451, 3773, + 3825, 2615, 3751, + 3793, 2769, 3723, + 3747, 2917, 3681, + 3677, 3059, 3619, + 3561, 3201, 3519, + 3339, 3339, 3339, + 2495, 3475, 2859, + 0, 3611, 0, + 0, 3745, 0, + 0, 3879, 0, + 0, 4013, 0, + 4029, 0, 3927, + 4029, 0, 3927, + 4029, 0, 3927, + 4029, 0, 3927, + 4029, 0, 3927, + 4029, 0, 3927, + 4029, 0, 3927, + 4029, 0, 3927, + 4029, 0, 3927, + 4027, 0, 3925, + 4027, 0, 3925, + 4027, 0, 3925, + 4025, 0, 3923, + 4023, 0, 3921, + 4021, 0, 3919, + 4019, 0, 3917, + 4015, 0, 3913, + 4011, 0, 3909, + 4005, 1152, 3903, + 3995, 1902, 3895, + 3983, 2235, 3883, + 3967, 2475, 3867, + 3945, 2673, 3845, + 3911, 2849, 3813, + 3863, 3013, 3767, + 3791, 3165, 3699, + 3669, 3313, 3585, + 3433, 3457, 3367, + 2293, 3597, 2593, + 0, 3735, 0, + 0, 3871, 0, + 0, 4007, 0, + 4095, 0, 4033, + 4095, 0, 4033, + 4095, 0, 4033, + 4095, 0, 4033, + 4095, 0, 4033, + 4095, 0, 4033, + 4095, 0, 4033, + 4095, 0, 4033, + 4095, 0, 4033, + 4095, 0, 4033, + 4095, 0, 4031, + 4095, 0, 4031, + 4095, 0, 4031, + 4095, 0, 4029, + 4095, 0, 4027, + 4095, 0, 4025, + 4095, 0, 4023, + 4095, 0, 4019, + 4095, 0, 4015, + 4095, 0, 4007, + 4095, 1465, 3999, + 4095, 2177, 3987, + 4091, 2505, 3969, + 4067, 2741, 3945, + 4033, 2939, 3913, + 3983, 3115, 3863, + 3909, 3277, 3787, + 3783, 3431, 3659, + 3533, 3579, 3405, + 1659, 3721, 0, + 0, 3861, 0, + 0, 3999, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2083, 4095, + 4095, 2541, 4079, + 4095, 2819, 4053, + 4095, 3037, 4017, + 4095, 3225, 3965, + 4031, 3393, 3883, + 3901, 3551, 3743, + 3641, 3703, 3449, + 0, 3847, 0, + 0, 3989, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 1918, 4095, + 4095, 2585, 4095, + 4095, 2907, 4095, + 4095, 3141, 4095, + 4095, 3339, 4073, + 4095, 3513, 3987, + 4023, 3675, 3837, + 3753, 3827, 3501, + 0, 3975, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 1519, 4095, + 4095, 2639, 4095, + 4095, 3001, 4095, + 4095, 3253, 4095, + 4095, 3457, 4095, + 4095, 3635, 4095, + 4095, 3801, 3937, + 3869, 3955, 3565, + 2957, 2509, 3371, + 2957, 2509, 3371, + 2957, 2509, 3371, + 2955, 2511, 3371, + 2955, 2513, 3371, + 2953, 2513, 3369, + 2951, 2515, 3369, + 2949, 2519, 3369, + 2945, 2523, 3367, + 2941, 2527, 3365, + 2933, 2535, 3363, + 2925, 2543, 3361, + 2913, 2555, 3357, + 2895, 2569, 3353, + 2871, 2589, 3347, + 2837, 2613, 3337, + 2787, 2645, 3325, + 2711, 2683, 3307, + 2583, 2731, 3283, + 2323, 2785, 3251, + 0, 2851, 3201, + 0, 2927, 3125, + 0, 3011, 2997, + 0, 3103, 2739, + 0, 3203, 0, + 0, 3309, 0, + 0, 3421, 0, + 0, 3539, 0, + 0, 3659, 0, + 0, 3781, 0, + 0, 3907, 0, + 0, 4033, 0, + 2959, 2509, 3371, + 2959, 2509, 3371, + 2957, 2509, 3371, + 2957, 2511, 3371, + 2955, 2511, 3371, + 2953, 2513, 3371, + 2951, 2515, 3369, + 2949, 2519, 3369, + 2945, 2523, 3367, + 2941, 2527, 3367, + 2935, 2535, 3365, + 2925, 2543, 3361, + 2913, 2555, 3357, + 2895, 2569, 3353, + 2871, 2589, 3347, + 2839, 2613, 3337, + 2789, 2645, 3325, + 2711, 2683, 3307, + 2585, 2729, 3285, + 2327, 2785, 3251, + 0, 2851, 3201, + 0, 2927, 3125, + 0, 3011, 2997, + 0, 3103, 2739, + 0, 3203, 0, + 0, 3309, 0, + 0, 3421, 0, + 0, 3539, 0, + 0, 3659, 0, + 0, 3781, 0, + 0, 3907, 0, + 0, 4033, 0, + 2959, 2509, 3371, + 2959, 2509, 3371, + 2959, 2509, 3371, + 2957, 2511, 3371, + 2957, 2511, 3371, + 2955, 2513, 3371, + 2953, 2515, 3369, + 2951, 2519, 3369, + 2947, 2523, 3367, + 2941, 2527, 3367, + 2935, 2535, 3365, + 2925, 2543, 3361, + 2913, 2555, 3357, + 2897, 2569, 3353, + 2873, 2589, 3347, + 2839, 2613, 3337, + 2789, 2645, 3325, + 2713, 2683, 3309, + 2587, 2729, 3285, + 2329, 2785, 3251, + 0, 2851, 3201, + 0, 2927, 3125, + 0, 3011, 2997, + 0, 3103, 2741, + 0, 3203, 0, + 0, 3309, 0, + 0, 3421, 0, + 0, 3539, 0, + 0, 3659, 0, + 0, 3781, 0, + 0, 3907, 0, + 0, 4033, 0, + 2961, 2509, 3373, + 2959, 2509, 3371, + 2959, 2509, 3371, + 2959, 2511, 3371, + 2957, 2511, 3371, + 2955, 2513, 3371, + 2953, 2515, 3369, + 2951, 2519, 3369, + 2947, 2523, 3369, + 2943, 2527, 3367, + 2937, 2535, 3365, + 2927, 2543, 3361, + 2915, 2555, 3359, + 2897, 2569, 3353, + 2875, 2589, 3347, + 2841, 2613, 3337, + 2791, 2645, 3325, + 2715, 2683, 3309, + 2589, 2729, 3285, + 2333, 2785, 3251, + 0, 2851, 3201, + 0, 2925, 3125, + 0, 3011, 2999, + 0, 3103, 2741, + 0, 3203, 0, + 0, 3309, 0, + 0, 3421, 0, + 0, 3537, 0, + 0, 3659, 0, + 0, 3781, 0, + 0, 3907, 0, + 0, 4033, 0, + 2961, 2509, 3373, + 2961, 2509, 3373, + 2961, 2509, 3373, + 2959, 2511, 3371, + 2959, 2511, 3371, + 2957, 2513, 3371, + 2955, 2515, 3371, + 2953, 2519, 3369, + 2949, 2523, 3369, + 2945, 2527, 3367, + 2937, 2533, 3365, + 2929, 2543, 3363, + 2917, 2555, 3359, + 2899, 2569, 3353, + 2875, 2589, 3347, + 2843, 2613, 3339, + 2793, 2645, 3325, + 2717, 2683, 3309, + 2591, 2729, 3285, + 2339, 2785, 3251, + 0, 2851, 3201, + 0, 2925, 3125, + 0, 3011, 2999, + 0, 3103, 2743, + 0, 3203, 0, + 0, 3309, 0, + 0, 3421, 0, + 0, 3537, 0, + 0, 3659, 0, + 0, 3781, 0, + 0, 3907, 0, + 0, 4033, 0, + 2963, 2507, 3373, + 2963, 2509, 3373, + 2963, 2509, 3373, + 2961, 2511, 3373, + 2961, 2511, 3371, + 2959, 2513, 3371, + 2957, 2515, 3371, + 2955, 2517, 3371, + 2951, 2521, 3369, + 2947, 2527, 3367, + 2939, 2533, 3365, + 2931, 2543, 3363, + 2919, 2555, 3359, + 2901, 2569, 3355, + 2879, 2589, 3347, + 2845, 2613, 3339, + 2795, 2645, 3327, + 2721, 2683, 3309, + 2595, 2729, 3285, + 2347, 2785, 3253, + 597, 2851, 3203, + 0, 2925, 3127, + 0, 3009, 3001, + 0, 3103, 2745, + 0, 3203, 0, + 0, 3309, 0, + 0, 3421, 0, + 0, 3537, 0, + 0, 3659, 0, + 0, 3781, 0, + 0, 3907, 0, + 0, 4033, 0, + 2967, 2507, 3373, + 2965, 2509, 3373, + 2965, 2509, 3373, + 2965, 2509, 3373, + 2963, 2511, 3373, + 2961, 2513, 3373, + 2959, 2515, 3371, + 2957, 2517, 3371, + 2953, 2521, 3369, + 2949, 2527, 3369, + 2943, 2533, 3367, + 2933, 2543, 3363, + 2921, 2553, 3359, + 2905, 2569, 3355, + 2881, 2589, 3349, + 2847, 2613, 3339, + 2799, 2645, 3327, + 2725, 2683, 3311, + 2601, 2729, 3287, + 2355, 2785, 3253, + 912, 2851, 3203, + 0, 2925, 3127, + 0, 3009, 3001, + 0, 3103, 2749, + 0, 3203, 0, + 0, 3309, 0, + 0, 3421, 0, + 0, 3537, 0, + 0, 3659, 0, + 0, 3781, 0, + 0, 3907, 0, + 0, 4033, 0, + 2969, 2507, 3375, + 2969, 2507, 3375, + 2969, 2509, 3375, + 2967, 2509, 3373, + 2967, 2511, 3373, + 2965, 2513, 3373, + 2963, 2515, 3373, + 2961, 2517, 3371, + 2957, 2521, 3371, + 2953, 2527, 3369, + 2945, 2533, 3367, + 2937, 2541, 3365, + 2925, 2553, 3361, + 2909, 2569, 3355, + 2885, 2587, 3349, + 2853, 2613, 3341, + 2803, 2643, 3329, + 2731, 2683, 3311, + 2609, 2729, 3287, + 2369, 2785, 3255, + 1144, 2851, 3205, + 0, 2925, 3129, + 0, 3009, 3003, + 0, 3103, 2751, + 0, 3203, 567, + 0, 3309, 0, + 0, 3421, 0, + 0, 3537, 0, + 0, 3659, 0, + 0, 3781, 0, + 0, 3907, 0, + 0, 4033, 0, + 2973, 2507, 3375, + 2973, 2507, 3375, + 2973, 2507, 3375, + 2971, 2509, 3375, + 2971, 2509, 3375, + 2969, 2511, 3375, + 2967, 2513, 3373, + 2965, 2517, 3373, + 2961, 2521, 3371, + 2957, 2525, 3371, + 2951, 2533, 3369, + 2941, 2541, 3365, + 2929, 2553, 3363, + 2913, 2567, 3357, + 2891, 2587, 3351, + 2857, 2613, 3341, + 2811, 2643, 3329, + 2737, 2681, 3313, + 2619, 2729, 3289, + 2385, 2785, 3255, + 1339, 2851, 3207, + 0, 2925, 3131, + 0, 3009, 3007, + 0, 3103, 2757, + 0, 3203, 941, + 0, 3309, 0, + 0, 3421, 0, + 0, 3537, 0, + 0, 3657, 0, + 0, 3781, 0, + 0, 3907, 0, + 0, 4033, 0, + 2979, 2505, 3377, + 2979, 2507, 3377, + 2979, 2507, 3377, + 2977, 2507, 3377, + 2977, 2509, 3377, + 2975, 2511, 3375, + 2973, 2513, 3375, + 2971, 2515, 3375, + 2967, 2519, 3373, + 2963, 2525, 3371, + 2957, 2531, 3369, + 2947, 2541, 3367, + 2935, 2553, 3363, + 2919, 2567, 3359, + 2897, 2587, 3353, + 2865, 2611, 3343, + 2819, 2643, 3331, + 2747, 2681, 3315, + 2631, 2729, 3291, + 2405, 2785, 3257, + 1513, 2849, 3209, + 0, 2925, 3135, + 0, 3009, 3011, + 0, 3101, 2763, + 0, 3203, 1195, + 0, 3309, 0, + 0, 3421, 0, + 0, 3537, 0, + 0, 3657, 0, + 0, 3781, 0, + 0, 3907, 0, + 0, 4033, 0, + 2987, 2505, 3379, + 2987, 2505, 3379, + 2987, 2505, 3379, + 2985, 2507, 3379, + 2985, 2507, 3379, + 2983, 2509, 3379, + 2981, 2511, 3377, + 2979, 2515, 3377, + 2975, 2519, 3375, + 2971, 2523, 3375, + 2965, 2531, 3373, + 2955, 2539, 3369, + 2945, 2551, 3365, + 2929, 2567, 3361, + 2907, 2585, 3355, + 2875, 2611, 3345, + 2829, 2641, 3333, + 2759, 2681, 3317, + 2647, 2727, 3293, + 2431, 2783, 3261, + 1674, 2849, 3213, + 0, 2925, 3137, + 0, 3009, 3015, + 0, 3101, 2771, + 0, 3201, 1401, + 0, 3309, 0, + 0, 3421, 0, + 0, 3537, 0, + 0, 3657, 0, + 0, 3781, 0, + 0, 3905, 0, + 0, 4033, 0, + 2997, 2503, 3383, + 2997, 2503, 3383, + 2997, 2505, 3381, + 2995, 2505, 3381, + 2995, 2507, 3381, + 2993, 2509, 3381, + 2991, 2511, 3381, + 2989, 2513, 3379, + 2985, 2517, 3379, + 2981, 2523, 3377, + 2975, 2529, 3375, + 2967, 2539, 3373, + 2955, 2549, 3369, + 2939, 2565, 3365, + 2919, 2585, 3357, + 2887, 2609, 3349, + 2843, 2641, 3337, + 2777, 2679, 3321, + 2667, 2727, 3297, + 2465, 2783, 3265, + 1826, 2849, 3217, + 0, 2923, 3143, + 0, 3009, 3021, + 0, 3101, 2781, + 0, 3201, 1581, + 0, 3309, 0, + 0, 3421, 0, + 0, 3537, 0, + 0, 3657, 0, + 0, 3781, 0, + 0, 3905, 0, + 0, 4033, 0, + 3011, 2501, 3387, + 3009, 2501, 3385, + 3009, 2503, 3385, + 3009, 2503, 3385, + 3007, 2505, 3385, + 3007, 2507, 3385, + 3005, 2509, 3385, + 3001, 2511, 3383, + 2999, 2515, 3383, + 2995, 2521, 3381, + 2989, 2527, 3379, + 2981, 2537, 3377, + 2969, 2549, 3373, + 2955, 2563, 3369, + 2933, 2583, 3361, + 2905, 2607, 3353, + 2861, 2639, 3341, + 2797, 2679, 3325, + 2695, 2725, 3301, + 2505, 2781, 3269, + 1973, 2847, 3221, + 0, 2923, 3149, + 0, 3007, 3029, + 0, 3101, 2795, + 0, 3201, 1747, + 0, 3309, 0, + 0, 3421, 0, + 0, 3537, 0, + 0, 3657, 0, + 0, 3781, 0, + 0, 3905, 0, + 0, 4033, 0, + 3027, 2499, 3391, + 3027, 2499, 3391, + 3025, 2499, 3391, + 3025, 2501, 3391, + 3025, 2501, 3391, + 3023, 2503, 3389, + 3021, 2505, 3389, + 3019, 2509, 3389, + 3015, 2513, 3387, + 3011, 2517, 3385, + 3007, 2525, 3383, + 2999, 2533, 3381, + 2987, 2545, 3377, + 2973, 2561, 3373, + 2953, 2581, 3367, + 2925, 2605, 3359, + 2885, 2637, 3347, + 2823, 2677, 3331, + 2727, 2723, 3307, + 2555, 2781, 3275, + 2115, 2847, 3229, + 0, 2923, 3157, + 0, 3007, 3041, + 0, 3099, 2813, + 0, 3201, 1902, + 0, 3307, 0, + 0, 3421, 0, + 0, 3537, 0, + 0, 3657, 0, + 0, 3781, 0, + 0, 3905, 0, + 0, 4033, 0, + 3049, 2495, 3397, + 3049, 2495, 3397, + 3047, 2497, 3397, + 3047, 2497, 3397, + 3045, 2499, 3397, + 3045, 2501, 3397, + 3043, 2503, 3395, + 3041, 2505, 3395, + 3037, 2509, 3393, + 3033, 2515, 3393, + 3029, 2521, 3391, + 3021, 2531, 3389, + 3011, 2543, 3385, + 2997, 2557, 3381, + 2979, 2577, 3373, + 2953, 2603, 3365, + 2913, 2635, 3353, + 2857, 2673, 3337, + 2769, 2721, 3315, + 2613, 2779, 3285, + 2255, 2845, 3239, + 0, 2921, 3169, + 0, 3005, 3055, + 0, 3099, 2837, + 0, 3199, 2051, + 0, 3307, 0, + 0, 3419, 0, + 0, 3537, 0, + 0, 3657, 0, + 0, 3781, 0, + 0, 3905, 0, + 0, 4033, 0, + 3075, 2491, 3407, + 3075, 2491, 3407, + 3075, 2491, 3405, + 3075, 2493, 3405, + 3073, 2493, 3405, + 3073, 2495, 3405, + 3071, 2497, 3405, + 3069, 2501, 3403, + 3065, 2505, 3403, + 3063, 2509, 3401, + 3057, 2517, 3399, + 3051, 2527, 3397, + 3041, 2539, 3393, + 3029, 2553, 3389, + 3011, 2573, 3383, + 2985, 2599, 3375, + 2951, 2631, 3363, + 2899, 2671, 3347, + 2817, 2719, 3327, + 2681, 2775, 3295, + 2393, 2843, 3251, + 0, 2919, 3183, + 0, 3005, 3073, + 0, 3097, 2865, + 0, 3199, 2195, + 0, 3307, 0, + 0, 3419, 0, + 0, 3537, 0, + 0, 3657, 0, + 0, 3779, 0, + 0, 3905, 0, + 0, 4033, 0, + 3109, 2483, 3417, + 3109, 2485, 3417, + 3109, 2485, 3417, + 3109, 2485, 3417, + 3107, 2487, 3417, + 3107, 2489, 3417, + 3105, 2491, 3415, + 3103, 2495, 3415, + 3101, 2499, 3415, + 3097, 2503, 3413, + 3093, 2511, 3411, + 3087, 2521, 3409, + 3077, 2533, 3405, + 3065, 2549, 3401, + 3049, 2569, 3395, + 3027, 2595, 3387, + 2995, 2627, 3375, + 2947, 2667, 3361, + 2877, 2715, 3339, + 2759, 2773, 3309, + 2531, 2839, 3267, + 1593, 2917, 3201, + 0, 3003, 3097, + 0, 3097, 2903, + 0, 3197, 2335, + 0, 3305, 0, + 0, 3419, 0, + 0, 3535, 0, + 0, 3657, 0, + 0, 3779, 0, + 0, 3905, 0, + 0, 4033, 0, + 3153, 2475, 3433, + 3151, 2475, 3433, + 3151, 2477, 3433, + 3151, 2477, 3431, + 3151, 2479, 3431, + 3149, 2481, 3431, + 3147, 2483, 3431, + 3147, 2485, 3429, + 3143, 2489, 3429, + 3141, 2495, 3427, + 3137, 2503, 3425, + 3131, 2511, 3423, + 3123, 2525, 3421, + 3113, 2541, 3417, + 3097, 2561, 3411, + 3077, 2587, 3403, + 3049, 2619, 3391, + 3007, 2661, 3377, + 2945, 2709, 3357, + 2845, 2767, 3329, + 2665, 2835, 3287, + 2191, 2913, 3225, + 0, 2999, 3125, + 0, 3093, 2947, + 0, 3195, 2475, + 0, 3303, 0, + 0, 3417, 0, + 0, 3535, 0, + 0, 3655, 0, + 0, 3779, 0, + 0, 3905, 0, + 0, 4031, 0, + 3203, 2463, 3451, + 3203, 2463, 3451, + 3203, 2463, 3451, + 3201, 2465, 3451, + 3201, 2467, 3451, + 3201, 2469, 3451, + 3199, 2471, 3449, + 3197, 2473, 3449, + 3195, 2477, 3449, + 3193, 2483, 3447, + 3189, 2491, 3445, + 3183, 2501, 3443, + 3177, 2513, 3439, + 3167, 2529, 3435, + 3155, 2551, 3431, + 3137, 2577, 3423, + 3111, 2611, 3413, + 3075, 2653, 3399, + 3023, 2703, 3379, + 2941, 2761, 3353, + 2801, 2831, 3313, + 2501, 2909, 3255, + 0, 2995, 3163, + 0, 3091, 2999, + 0, 3193, 2611, + 0, 3301, 0, + 0, 3415, 0, + 0, 3533, 0, + 0, 3655, 0, + 0, 3779, 0, + 0, 3905, 0, + 0, 4031, 0, + 3263, 2445, 3475, + 3263, 2447, 3475, + 3263, 2447, 3475, + 3261, 2449, 3475, + 3261, 2449, 3475, + 3261, 2451, 3475, + 3259, 2455, 3475, + 3259, 2457, 3473, + 3257, 2461, 3473, + 3253, 2467, 3471, + 3251, 2475, 3469, + 3247, 2485, 3467, + 3239, 2499, 3465, + 3231, 2515, 3461, + 3221, 2537, 3455, + 3205, 2565, 3449, + 3183, 2599, 3439, + 3153, 2641, 3425, + 3109, 2693, 3407, + 3043, 2753, 3383, + 2933, 2823, 3345, + 2731, 2903, 3291, + 2103, 2991, 3207, + 0, 3087, 3063, + 0, 3189, 2747, + 0, 3299, 0, + 0, 3413, 0, + 0, 3531, 0, + 0, 3653, 0, + 0, 3777, 0, + 0, 3903, 0, + 0, 4031, 0, + 3333, 2423, 3507, + 3333, 2423, 3507, + 3331, 2423, 3505, + 3331, 2425, 3505, + 3331, 2427, 3505, + 3331, 2429, 3505, + 3329, 2431, 3505, + 3329, 2435, 3505, + 3327, 2439, 3503, + 3325, 2445, 3503, + 3321, 2453, 3501, + 3319, 2463, 3499, + 3313, 2477, 3497, + 3305, 2495, 3493, + 3297, 2519, 3487, + 3283, 2547, 3481, + 3265, 2583, 3473, + 3241, 2627, 3459, + 3203, 2679, 3443, + 3151, 2741, 3419, + 3067, 2813, 3385, + 2925, 2893, 3337, + 2621, 2983, 3261, + 0, 3081, 3135, + 0, 3185, 2881, + 0, 3295, 347, + 0, 3411, 0, + 0, 3529, 0, + 0, 3651, 0, + 0, 3777, 0, + 0, 3903, 0, + 0, 4031, 0, + 3411, 2389, 3545, + 3411, 2389, 3543, + 3411, 2391, 3543, + 3411, 2391, 3543, + 3411, 2393, 3543, + 3409, 2395, 3543, + 3409, 2399, 3543, + 3409, 2403, 3543, + 3407, 2407, 3541, + 3405, 2413, 3541, + 3403, 2423, 3539, + 3399, 2433, 3537, + 3395, 2449, 3535, + 3389, 2467, 3531, + 3381, 2491, 3527, + 3371, 2521, 3521, + 3355, 2559, 3513, + 3335, 2605, 3501, + 3305, 2661, 3487, + 3263, 2725, 3465, + 3201, 2799, 3435, + 3099, 2883, 3391, + 2915, 2973, 3323, + 2411, 3073, 3217, + 0, 3179, 3015, + 0, 3291, 2401, + 0, 3407, 0, + 0, 3527, 0, + 0, 3649, 0, + 0, 3775, 0, + 0, 3901, 0, + 0, 4029, 0, + 3499, 2341, 3591, + 3499, 2341, 3591, + 3499, 2343, 3589, + 3499, 2343, 3589, + 3499, 2345, 3589, + 3499, 2347, 3589, + 3497, 2351, 3589, + 3497, 2355, 3589, + 3495, 2361, 3587, + 3495, 2367, 3587, + 3493, 2377, 3585, + 3489, 2389, 3583, + 3485, 2405, 3581, + 3481, 2427, 3579, + 3475, 2453, 3575, + 3467, 2485, 3569, + 3455, 2527, 3563, + 3437, 2575, 3551, + 3415, 2635, 3539, + 3381, 2703, 3519, + 3333, 2779, 3493, + 3259, 2867, 3453, + 3139, 2961, 3397, + 2899, 3063, 3307, + 1706, 3171, 3149, + 0, 3285, 2783, + 0, 3403, 0, + 0, 3523, 0, + 0, 3647, 0, + 0, 3773, 0, + 0, 3899, 0, + 0, 4029, 0, + 3595, 2265, 3645, + 3595, 2267, 3645, + 3595, 2267, 3645, + 3595, 2269, 3645, + 3595, 2271, 3645, + 3595, 2275, 3645, + 3593, 2277, 3645, + 3593, 2283, 3643, + 3593, 2289, 3643, + 3591, 2297, 3643, + 3589, 2309, 3641, + 3587, 2323, 3639, + 3585, 2341, 3637, + 3581, 2365, 3635, + 3575, 2395, 3631, + 3569, 2433, 3627, + 3559, 2479, 3621, + 3545, 2533, 3611, + 3527, 2597, 3599, + 3503, 2671, 3583, + 3467, 2753, 3559, + 3413, 2845, 3527, + 3329, 2943, 3479, + 3187, 3049, 3405, + 2877, 3161, 3283, + 0, 3275, 3041, + 0, 3395, 1772, + 0, 3519, 0, + 0, 3643, 0, + 0, 3769, 0, + 0, 3897, 0, + 0, 4027, 0, + 3699, 2141, 3711, + 3699, 2143, 3711, + 3699, 2145, 3709, + 3699, 2147, 3709, + 3697, 2149, 3709, + 3697, 2153, 3709, + 3697, 2157, 3709, + 3697, 2165, 3709, + 3697, 2173, 3709, + 3695, 2183, 3707, + 3693, 2197, 3707, + 3693, 2217, 3705, + 3689, 2239, 3703, + 3687, 2269, 3701, + 3683, 2305, 3699, + 3677, 2351, 3695, + 3669, 2405, 3689, + 3659, 2469, 3681, + 3645, 2541, 3671, + 3627, 2623, 3657, + 3599, 2713, 3637, + 3559, 2813, 3609, + 3501, 2917, 3569, + 3407, 3029, 3509, + 3243, 3145, 3415, + 2847, 3263, 3249, + 0, 3387, 2837, + 0, 3511, 0, + 0, 3637, 0, + 0, 3765, 0, + 0, 3895, 0, + 0, 4025, 0, + 3807, 1895, 3785, + 3807, 1897, 3785, + 3807, 1900, 3785, + 3807, 1903, 3785, + 3807, 1908, 3783, + 3807, 1914, 3783, + 3807, 1922, 3783, + 3807, 1933, 3783, + 3805, 1946, 3783, + 3805, 1964, 3783, + 3805, 1987, 3781, + 3803, 2016, 3781, + 3801, 2051, 3779, + 3799, 2095, 3777, + 3795, 2149, 3775, + 3791, 2211, 3771, + 3785, 2283, 3767, + 3777, 2365, 3759, + 3767, 2453, 3751, + 3751, 2551, 3739, + 3731, 2657, 3723, + 3701, 2767, 3701, + 3659, 2881, 3667, + 3597, 3001, 3621, + 3495, 3123, 3549, + 3309, 3247, 3429, + 2803, 3373, 3197, + 0, 3501, 2201, + 0, 3631, 0, + 0, 3761, 0, + 0, 3891, 0, + 0, 4021, 0, + 3921, 376, 3867, + 3921, 429, 3867, + 3921, 491, 3867, + 3921, 564, 3867, + 3921, 645, 3867, + 3921, 735, 3867, + 3921, 833, 3867, + 3921, 938, 3867, + 3921, 1048, 3867, + 3919, 1164, 3865, + 3919, 1283, 3865, + 3919, 1405, 3865, + 3917, 1530, 3863, + 3915, 1656, 3861, + 3913, 1784, 3859, + 3909, 1913, 3857, + 3905, 2042, 3853, + 3899, 2173, 3847, + 3891, 2303, 3841, + 3879, 2435, 3831, + 3863, 2565, 3817, + 3841, 2697, 3799, + 3811, 2829, 3773, + 3767, 2961, 3735, + 3699, 3093, 3681, + 3591, 3225, 3595, + 3385, 3357, 3447, + 2735, 3489, 3121, + 0, 3621, 0, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 4041, 0, 3959, + 4041, 0, 3959, + 4041, 0, 3959, + 4039, 0, 3959, + 4039, 0, 3959, + 4039, 0, 3959, + 4039, 0, 3959, + 4039, 0, 3959, + 4039, 0, 3959, + 4039, 0, 3959, + 4037, 0, 3957, + 4037, 0, 3957, + 4037, 0, 3957, + 4035, 0, 3955, + 4033, 0, 3953, + 4031, 0, 3951, + 4027, 815, 3947, + 4023, 1625, 3943, + 4015, 1965, 3937, + 4007, 2207, 3929, + 3995, 2407, 3919, + 3979, 2583, 3905, + 3957, 2747, 3883, + 3925, 2901, 3855, + 3879, 3049, 3813, + 3809, 3193, 3751, + 3693, 3333, 3651, + 3471, 3471, 3471, + 2627, 3607, 2991, + 0, 3743, 0, + 0, 3877, 0, + 0, 4011, 0, + 4095, 0, 4059, + 4095, 0, 4059, + 4095, 0, 4059, + 4095, 0, 4059, + 4095, 0, 4059, + 4095, 0, 4059, + 4095, 0, 4059, + 4095, 0, 4059, + 4095, 0, 4059, + 4095, 0, 4059, + 4095, 0, 4057, + 4095, 0, 4057, + 4095, 0, 4057, + 4095, 0, 4055, + 4095, 0, 4053, + 4095, 0, 4053, + 4095, 0, 4049, + 4095, 0, 4047, + 4095, 0, 4041, + 4095, 1285, 4035, + 4095, 2034, 4027, + 4095, 2367, 4015, + 4095, 2607, 3999, + 4077, 2805, 3977, + 4043, 2981, 3945, + 3995, 3145, 3899, + 3923, 3297, 3831, + 3801, 3445, 3717, + 3565, 3589, 3499, + 2425, 3729, 2725, + 0, 3867, 0, + 0, 4003, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 1597, 4095, + 4095, 2309, 4095, + 4095, 2637, 4095, + 4095, 2875, 4079, + 4095, 3071, 4045, + 4095, 3247, 3995, + 4041, 3409, 3919, + 3915, 3563, 3791, + 3665, 3711, 3537, + 1791, 3853, 0, + 0, 3993, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2215, 4095, + 4095, 2673, 4095, + 4095, 2951, 4095, + 4095, 3169, 4095, + 4095, 3357, 4095, + 4095, 3525, 4015, + 4033, 3683, 3877, + 3773, 3835, 3581, + 0, 3979, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2051, 4095, + 4095, 2717, 4095, + 4095, 3039, 4095, + 4095, 3275, 4095, + 4095, 3471, 4095, + 4095, 3645, 4095, + 4095, 3807, 3969, + 3885, 3961, 3633, + 3089, 2641, 3503, + 3089, 2641, 3503, + 3089, 2641, 3503, + 3089, 2643, 3503, + 3087, 2643, 3503, + 3087, 2645, 3503, + 3085, 2645, 3501, + 3083, 2649, 3501, + 3081, 2651, 3501, + 3077, 2655, 3499, + 3071, 2659, 3497, + 3065, 2667, 3495, + 3057, 2675, 3493, + 3043, 2687, 3489, + 3027, 2703, 3485, + 3003, 2721, 3479, + 2969, 2747, 3469, + 2919, 2777, 3457, + 2843, 2815, 3439, + 2715, 2863, 3415, + 2453, 2919, 3383, + 0, 2983, 3333, + 0, 3059, 3257, + 0, 3143, 3129, + 0, 3235, 2871, + 0, 3335, 0, + 0, 3441, 0, + 0, 3553, 0, + 0, 3671, 0, + 0, 3791, 0, + 0, 3913, 0, + 0, 4039, 0, + 3091, 2641, 3503, + 3091, 2641, 3503, + 3089, 2641, 3503, + 3089, 2641, 3503, + 3089, 2643, 3503, + 3087, 2645, 3503, + 3085, 2645, 3503, + 3083, 2647, 3501, + 3081, 2651, 3501, + 3077, 2655, 3499, + 3073, 2659, 3499, + 3065, 2667, 3497, + 3057, 2675, 3493, + 3045, 2687, 3489, + 3027, 2701, 3485, + 3003, 2721, 3479, + 2969, 2745, 3469, + 2919, 2777, 3457, + 2843, 2815, 3439, + 2715, 2863, 3417, + 2455, 2919, 3383, + 0, 2983, 3333, + 0, 3059, 3257, + 0, 3143, 3129, + 0, 3235, 2871, + 0, 3335, 0, + 0, 3441, 0, + 0, 3553, 0, + 0, 3671, 0, + 0, 3791, 0, + 0, 3913, 0, + 0, 4039, 0, + 3091, 2641, 3503, + 3091, 2641, 3503, + 3091, 2641, 3503, + 3089, 2641, 3503, + 3089, 2643, 3503, + 3087, 2645, 3503, + 3087, 2645, 3503, + 3085, 2647, 3501, + 3081, 2651, 3501, + 3077, 2655, 3499, + 3073, 2659, 3499, + 3067, 2667, 3497, + 3057, 2675, 3493, + 3045, 2687, 3489, + 3027, 2701, 3485, + 3005, 2721, 3479, + 2971, 2745, 3469, + 2921, 2777, 3457, + 2843, 2815, 3441, + 2717, 2863, 3417, + 2459, 2917, 3383, + 0, 2983, 3333, + 0, 3059, 3257, + 0, 3143, 3129, + 0, 3235, 2871, + 0, 3335, 0, + 0, 3441, 0, + 0, 3553, 0, + 0, 3671, 0, + 0, 3791, 0, + 0, 3913, 0, + 0, 4039, 0, + 3091, 2641, 3503, + 3091, 2641, 3503, + 3091, 2641, 3503, + 3091, 2641, 3503, + 3089, 2643, 3503, + 3089, 2643, 3503, + 3087, 2645, 3503, + 3085, 2647, 3501, + 3083, 2651, 3501, + 3079, 2655, 3499, + 3073, 2659, 3499, + 3067, 2667, 3497, + 3059, 2675, 3493, + 3045, 2687, 3491, + 3029, 2701, 3485, + 3005, 2721, 3479, + 2971, 2745, 3469, + 2921, 2777, 3457, + 2845, 2815, 3441, + 2719, 2863, 3417, + 2461, 2917, 3383, + 0, 2983, 3333, + 0, 3059, 3257, + 0, 3143, 3129, + 0, 3235, 2873, + 0, 3335, 0, + 0, 3441, 0, + 0, 3553, 0, + 0, 3671, 0, + 0, 3791, 0, + 0, 3913, 0, + 0, 4039, 0, + 3093, 2641, 3505, + 3093, 2641, 3505, + 3091, 2641, 3503, + 3091, 2641, 3503, + 3091, 2643, 3503, + 3089, 2643, 3503, + 3087, 2645, 3503, + 3085, 2647, 3503, + 3083, 2651, 3501, + 3079, 2655, 3501, + 3075, 2659, 3499, + 3069, 2667, 3497, + 3059, 2675, 3495, + 3047, 2687, 3491, + 3031, 2701, 3485, + 3007, 2721, 3479, + 2973, 2745, 3469, + 2923, 2777, 3457, + 2847, 2815, 3441, + 2721, 2861, 3417, + 2465, 2917, 3383, + 0, 2983, 3333, + 0, 3059, 3257, + 0, 3143, 3131, + 0, 3235, 2873, + 0, 3335, 0, + 0, 3441, 0, + 0, 3553, 0, + 0, 3671, 0, + 0, 3791, 0, + 0, 3913, 0, + 0, 4039, 0, + 3095, 2639, 3505, + 3093, 2641, 3505, + 3093, 2641, 3505, + 3093, 2641, 3505, + 3091, 2643, 3503, + 3091, 2643, 3503, + 3089, 2645, 3503, + 3087, 2647, 3503, + 3085, 2651, 3501, + 3081, 2655, 3501, + 3077, 2659, 3499, + 3069, 2667, 3497, + 3061, 2675, 3495, + 3049, 2687, 3491, + 3031, 2701, 3485, + 3007, 2721, 3479, + 2975, 2745, 3471, + 2925, 2777, 3459, + 2849, 2815, 3441, + 2723, 2861, 3417, + 2471, 2917, 3383, + 108, 2983, 3335, + 0, 3059, 3257, + 0, 3143, 3131, + 0, 3235, 2875, + 0, 3335, 0, + 0, 3441, 0, + 0, 3553, 0, + 0, 3671, 0, + 0, 3791, 0, + 0, 3913, 0, + 0, 4039, 0, + 3097, 2639, 3505, + 3095, 2641, 3505, + 3095, 2641, 3505, + 3095, 2641, 3505, + 3093, 2643, 3505, + 3093, 2643, 3505, + 3091, 2645, 3503, + 3089, 2647, 3503, + 3087, 2651, 3503, + 3083, 2653, 3501, + 3079, 2659, 3499, + 3071, 2665, 3497, + 3063, 2675, 3495, + 3051, 2687, 3491, + 3033, 2701, 3487, + 3011, 2721, 3479, + 2977, 2745, 3471, + 2927, 2777, 3459, + 2853, 2815, 3441, + 2727, 2861, 3417, + 2479, 2917, 3385, + 729, 2983, 3335, + 0, 3057, 3259, + 0, 3143, 3133, + 0, 3235, 2877, + 0, 3335, 0, + 0, 3441, 0, + 0, 3553, 0, + 0, 3671, 0, + 0, 3791, 0, + 0, 3913, 0, + 0, 4039, 0, + 3099, 2639, 3505, + 3099, 2639, 3505, + 3097, 2641, 3505, + 3097, 2641, 3505, + 3097, 2641, 3505, + 3095, 2643, 3505, + 3093, 2645, 3505, + 3091, 2647, 3503, + 3089, 2649, 3503, + 3085, 2653, 3501, + 3081, 2659, 3501, + 3075, 2665, 3499, + 3065, 2675, 3495, + 3053, 2685, 3493, + 3037, 2701, 3487, + 3013, 2721, 3481, + 2979, 2745, 3471, + 2931, 2777, 3459, + 2857, 2815, 3443, + 2733, 2861, 3419, + 2487, 2917, 3385, + 1043, 2983, 3335, + 0, 3057, 3261, + 0, 3141, 3133, + 0, 3235, 2881, + 0, 3335, 0, + 0, 3441, 0, + 0, 3553, 0, + 0, 3671, 0, + 0, 3791, 0, + 0, 3913, 0, + 0, 4039, 0, + 3101, 2639, 3507, + 3101, 2639, 3507, + 3101, 2639, 3507, + 3101, 2641, 3507, + 3099, 2641, 3507, + 3099, 2643, 3505, + 3097, 2645, 3505, + 3095, 2647, 3505, + 3093, 2649, 3503, + 3089, 2653, 3503, + 3085, 2659, 3501, + 3077, 2665, 3499, + 3069, 2673, 3497, + 3057, 2685, 3493, + 3041, 2701, 3489, + 3017, 2721, 3481, + 2985, 2745, 3473, + 2937, 2775, 3461, + 2863, 2815, 3443, + 2741, 2861, 3419, + 2501, 2917, 3387, + 1276, 2983, 3337, + 0, 3057, 3261, + 0, 3141, 3135, + 0, 3235, 2883, + 0, 3335, 699, + 0, 3441, 0, + 0, 3553, 0, + 0, 3669, 0, + 0, 3791, 0, + 0, 3913, 0, + 0, 4039, 0, + 3107, 2639, 3507, + 3105, 2639, 3507, + 3105, 2639, 3507, + 3105, 2639, 3507, + 3103, 2641, 3507, + 3103, 2641, 3507, + 3101, 2643, 3507, + 3099, 2645, 3505, + 3097, 2649, 3505, + 3093, 2653, 3503, + 3089, 2657, 3503, + 3083, 2665, 3501, + 3073, 2673, 3497, + 3061, 2685, 3495, + 3045, 2701, 3489, + 3023, 2719, 3483, + 2989, 2745, 3473, + 2943, 2775, 3461, + 2869, 2813, 3445, + 2751, 2861, 3421, + 2517, 2917, 3387, + 1471, 2983, 3339, + 0, 3057, 3263, + 0, 3141, 3139, + 0, 3235, 2889, + 0, 3335, 1073, + 0, 3441, 0, + 0, 3553, 0, + 0, 3669, 0, + 0, 3791, 0, + 0, 3913, 0, + 0, 4039, 0, + 3111, 2637, 3509, + 3111, 2637, 3509, + 3111, 2639, 3509, + 3111, 2639, 3509, + 3109, 2639, 3509, + 3109, 2641, 3509, + 3107, 2643, 3509, + 3105, 2645, 3507, + 3103, 2647, 3507, + 3099, 2651, 3505, + 3095, 2657, 3505, + 3089, 2663, 3503, + 3079, 2673, 3499, + 3069, 2685, 3495, + 3051, 2699, 3491, + 3029, 2719, 3485, + 2997, 2743, 3475, + 2951, 2775, 3463, + 2879, 2813, 3447, + 2763, 2861, 3423, + 2537, 2917, 3389, + 1645, 2981, 3341, + 0, 3057, 3267, + 0, 3141, 3143, + 0, 3235, 2895, + 0, 3335, 1327, + 0, 3441, 0, + 0, 3553, 0, + 0, 3669, 0, + 0, 3791, 0, + 0, 3913, 0, + 0, 4039, 0, + 3119, 2637, 3511, + 3119, 2637, 3511, + 3119, 2637, 3511, + 3119, 2637, 3511, + 3117, 2639, 3511, + 3117, 2641, 3511, + 3115, 2641, 3511, + 3113, 2643, 3509, + 3111, 2647, 3509, + 3107, 2651, 3507, + 3103, 2655, 3507, + 3097, 2663, 3505, + 3087, 2671, 3501, + 3077, 2683, 3499, + 3061, 2699, 3493, + 3039, 2717, 3487, + 3007, 2743, 3477, + 2961, 2773, 3465, + 2893, 2813, 3449, + 2779, 2859, 3425, + 2563, 2915, 3393, + 1806, 2981, 3345, + 0, 3057, 3271, + 0, 3141, 3147, + 0, 3233, 2903, + 0, 3335, 1533, + 0, 3441, 0, + 0, 3553, 0, + 0, 3669, 0, + 0, 3789, 0, + 0, 3913, 0, + 0, 4039, 0, + 3129, 2635, 3515, + 3129, 2635, 3515, + 3129, 2635, 3515, + 3129, 2637, 3515, + 3127, 2637, 3513, + 3127, 2639, 3513, + 3125, 2641, 3513, + 3123, 2643, 3513, + 3121, 2645, 3511, + 3117, 2649, 3511, + 3113, 2655, 3509, + 3107, 2661, 3507, + 3099, 2671, 3505, + 3087, 2681, 3501, + 3071, 2697, 3497, + 3051, 2717, 3489, + 3019, 2741, 3481, + 2975, 2773, 3469, + 2909, 2811, 3453, + 2799, 2859, 3429, + 2597, 2915, 3397, + 1958, 2981, 3349, + 0, 3057, 3275, + 0, 3141, 3153, + 0, 3233, 2913, + 0, 3333, 1714, + 0, 3441, 0, + 0, 3553, 0, + 0, 3669, 0, + 0, 3789, 0, + 0, 3913, 0, + 0, 4039, 0, + 3143, 2633, 3519, + 3143, 2633, 3519, + 3141, 2633, 3519, + 3141, 2635, 3517, + 3141, 2635, 3517, + 3139, 2637, 3517, + 3139, 2639, 3517, + 3137, 2641, 3517, + 3133, 2643, 3515, + 3131, 2647, 3515, + 3127, 2653, 3513, + 3121, 2659, 3511, + 3113, 2669, 3509, + 3101, 2681, 3505, + 3087, 2695, 3501, + 3065, 2715, 3493, + 3037, 2741, 3485, + 2993, 2771, 3473, + 2929, 2811, 3457, + 2827, 2857, 3433, + 2637, 2913, 3401, + 2105, 2979, 3353, + 0, 3055, 3281, + 0, 3139, 3161, + 0, 3233, 2927, + 0, 3333, 1879, + 0, 3441, 0, + 0, 3553, 0, + 0, 3669, 0, + 0, 3789, 0, + 0, 3913, 0, + 0, 4037, 0, + 3159, 2631, 3523, + 3159, 2631, 3523, + 3159, 2631, 3523, + 3159, 2631, 3523, + 3157, 2633, 3523, + 3157, 2635, 3523, + 3155, 2635, 3521, + 3153, 2637, 3521, + 3151, 2641, 3521, + 3149, 2645, 3519, + 3143, 2651, 3517, + 3139, 2657, 3517, + 3131, 2665, 3513, + 3121, 2677, 3511, + 3105, 2693, 3505, + 3085, 2713, 3499, + 3057, 2737, 3491, + 3017, 2769, 3479, + 2955, 2809, 3463, + 2859, 2855, 3439, + 2687, 2913, 3407, + 2249, 2979, 3361, + 0, 3055, 3289, + 0, 3139, 3173, + 0, 3233, 2945, + 0, 3333, 2034, + 0, 3439, 0, + 0, 3553, 0, + 0, 3669, 0, + 0, 3789, 0, + 0, 3913, 0, + 0, 4037, 0, + 3181, 2627, 3529, + 3181, 2627, 3529, + 3181, 2627, 3529, + 3179, 2629, 3529, + 3179, 2629, 3529, + 3179, 2631, 3529, + 3177, 2633, 3529, + 3175, 2635, 3527, + 3173, 2637, 3527, + 3171, 2641, 3527, + 3167, 2647, 3525, + 3161, 2653, 3523, + 3153, 2663, 3521, + 3143, 2675, 3517, + 3129, 2689, 3513, + 3111, 2709, 3505, + 3085, 2735, 3497, + 3047, 2767, 3485, + 2989, 2807, 3469, + 2901, 2853, 3447, + 2745, 2911, 3417, + 2389, 2977, 3371, + 0, 3053, 3301, + 0, 3137, 3187, + 0, 3231, 2969, + 0, 3333, 2183, + 0, 3439, 0, + 0, 3551, 0, + 0, 3669, 0, + 0, 3789, 0, + 0, 3913, 0, + 0, 4037, 0, + 3209, 2621, 3539, + 3207, 2623, 3539, + 3207, 2623, 3539, + 3207, 2623, 3539, + 3207, 2625, 3537, + 3205, 2625, 3537, + 3205, 2627, 3537, + 3203, 2629, 3537, + 3201, 2633, 3535, + 3199, 2637, 3535, + 3195, 2643, 3533, + 3189, 2649, 3531, + 3183, 2659, 3529, + 3173, 2671, 3525, + 3161, 2685, 3521, + 3143, 2705, 3515, + 3117, 2731, 3507, + 3083, 2763, 3495, + 3031, 2803, 3479, + 2949, 2851, 3459, + 2813, 2909, 3427, + 2527, 2975, 3383, + 0, 3051, 3315, + 0, 3137, 3205, + 0, 3229, 2997, + 0, 3331, 2327, + 0, 3439, 0, + 0, 3551, 0, + 0, 3669, 0, + 0, 3789, 0, + 0, 3913, 0, + 0, 4037, 0, + 3243, 2615, 3549, + 3243, 2615, 3549, + 3241, 2617, 3549, + 3241, 2617, 3549, + 3241, 2617, 3549, + 3239, 2619, 3549, + 3239, 2621, 3549, + 3237, 2623, 3547, + 3235, 2627, 3547, + 3233, 2631, 3547, + 3229, 2635, 3545, + 3225, 2643, 3543, + 3219, 2653, 3541, + 3209, 2665, 3537, + 3199, 2681, 3533, + 3181, 2701, 3527, + 3159, 2727, 3519, + 3127, 2759, 3507, + 3079, 2799, 3493, + 3009, 2847, 3471, + 2891, 2905, 3441, + 2663, 2971, 3399, + 1725, 3049, 3333, + 0, 3135, 3229, + 0, 3229, 3035, + 0, 3329, 2467, + 0, 3437, 0, + 0, 3551, 0, + 0, 3667, 0, + 0, 3789, 0, + 0, 3911, 0, + 0, 4037, 0, + 3285, 2607, 3565, + 3285, 2607, 3565, + 3283, 2607, 3565, + 3283, 2609, 3565, + 3283, 2609, 3565, + 3283, 2611, 3563, + 3281, 2613, 3563, + 3279, 2615, 3563, + 3279, 2617, 3563, + 3275, 2621, 3561, + 3273, 2627, 3559, + 3269, 2635, 3559, + 3263, 2645, 3555, + 3255, 2657, 3553, + 3245, 2673, 3549, + 3229, 2693, 3543, + 3209, 2719, 3535, + 3181, 2753, 3525, + 3139, 2793, 3509, + 3077, 2841, 3489, + 2977, 2899, 3461, + 2797, 2967, 3419, + 2323, 3045, 3357, + 0, 3131, 3257, + 0, 3225, 3079, + 0, 3327, 2607, + 0, 3435, 0, + 0, 3549, 0, + 0, 3667, 0, + 0, 3787, 0, + 0, 3911, 0, + 0, 4037, 0, + 3335, 2595, 3583, + 3335, 2595, 3583, + 3335, 2595, 3583, + 3335, 2597, 3583, + 3333, 2597, 3583, + 3333, 2599, 3583, + 3333, 2601, 3583, + 3331, 2603, 3581, + 3329, 2605, 3581, + 3327, 2611, 3581, + 3325, 2615, 3579, + 3321, 2623, 3577, + 3315, 2633, 3575, + 3309, 2645, 3573, + 3299, 2661, 3567, + 3287, 2683, 3563, + 3269, 2709, 3555, + 3243, 2743, 3545, + 3207, 2785, 3531, + 3155, 2835, 3511, + 3073, 2893, 3485, + 2933, 2963, 3445, + 2633, 3041, 3387, + 0, 3127, 3295, + 0, 3223, 3131, + 0, 3325, 2743, + 0, 3433, 0, + 0, 3547, 0, + 0, 3665, 0, + 0, 3787, 0, + 0, 3911, 0, + 0, 4037, 0, + 3395, 2577, 3607, + 3395, 2577, 3607, + 3395, 2579, 3607, + 3395, 2579, 3607, + 3393, 2581, 3607, + 3393, 2581, 3607, + 3393, 2583, 3607, + 3391, 2587, 3607, + 3391, 2589, 3605, + 3389, 2593, 3605, + 3385, 2599, 3603, + 3383, 2607, 3601, + 3379, 2617, 3599, + 3373, 2631, 3597, + 3363, 2647, 3593, + 3353, 2669, 3587, + 3337, 2697, 3581, + 3315, 2731, 3571, + 3285, 2773, 3559, + 3241, 2825, 3539, + 3175, 2885, 3515, + 3067, 2955, 3477, + 2863, 3035, 3423, + 2235, 3123, 3339, + 0, 3219, 3195, + 0, 3323, 2879, + 0, 3431, 0, + 0, 3545, 0, + 0, 3665, 0, + 0, 3785, 0, + 0, 3909, 0, + 0, 4035, 0, + 3465, 2555, 3639, + 3465, 2555, 3639, + 3465, 2555, 3639, + 3465, 2557, 3639, + 3463, 2557, 3637, + 3463, 2559, 3637, + 3463, 2561, 3637, + 3461, 2563, 3637, + 3461, 2567, 3637, + 3459, 2571, 3635, + 3457, 2577, 3635, + 3455, 2585, 3633, + 3451, 2597, 3631, + 3445, 2609, 3629, + 3439, 2627, 3625, + 3429, 2651, 3619, + 3415, 2679, 3613, + 3397, 2715, 3605, + 3373, 2759, 3591, + 3335, 2811, 3575, + 3283, 2873, 3551, + 3199, 2945, 3517, + 3057, 3025, 3469, + 2753, 3115, 3393, + 0, 3213, 3267, + 0, 3317, 3013, + 0, 3427, 479, + 0, 3543, 0, + 0, 3661, 0, + 0, 3783, 0, + 0, 3909, 0, + 0, 4035, 0, + 3543, 2521, 3677, + 3543, 2521, 3677, + 3543, 2521, 3677, + 3543, 2523, 3675, + 3543, 2525, 3675, + 3543, 2525, 3675, + 3541, 2527, 3675, + 3541, 2531, 3675, + 3541, 2535, 3675, + 3539, 2539, 3673, + 3537, 2545, 3673, + 3535, 2555, 3671, + 3531, 2565, 3669, + 3527, 2581, 3667, + 3521, 2599, 3663, + 3513, 2623, 3659, + 3503, 2653, 3653, + 3487, 2691, 3645, + 3467, 2737, 3633, + 3439, 2793, 3619, + 3395, 2857, 3597, + 3333, 2931, 3567, + 3231, 3015, 3523, + 3047, 3107, 3455, + 2543, 3205, 3349, + 0, 3311, 3147, + 0, 3423, 2533, + 0, 3539, 0, + 0, 3659, 0, + 0, 3781, 0, + 0, 3907, 0, + 0, 4033, 0, + 3631, 2471, 3723, + 3631, 2473, 3723, + 3631, 2473, 3723, + 3631, 2475, 3723, + 3631, 2475, 3721, + 3631, 2477, 3721, + 3631, 2479, 3721, + 3629, 2483, 3721, + 3629, 2487, 3721, + 3627, 2493, 3719, + 3627, 2499, 3719, + 3625, 2509, 3717, + 3621, 2521, 3717, + 3619, 2537, 3713, + 3613, 2559, 3711, + 3607, 2585, 3707, + 3599, 2617, 3701, + 3587, 2659, 3695, + 3569, 2707, 3685, + 3547, 2767, 3671, + 3513, 2835, 3651, + 3465, 2911, 3625, + 3393, 2999, 3585, + 3271, 3093, 3529, + 3031, 3195, 3439, + 1838, 3303, 3281, + 0, 3417, 2915, + 0, 3535, 0, + 0, 3655, 0, + 0, 3779, 0, + 0, 3905, 0, + 0, 4031, 0, + 3727, 2397, 3777, + 3727, 2397, 3777, + 3727, 2399, 3777, + 3727, 2399, 3777, + 3727, 2401, 3777, + 3727, 2403, 3777, + 3727, 2407, 3777, + 3725, 2411, 3777, + 3725, 2415, 3775, + 3725, 2421, 3775, + 3723, 2429, 3775, + 3721, 2441, 3773, + 3719, 2455, 3773, + 3717, 2475, 3771, + 3713, 2497, 3767, + 3707, 2527, 3763, + 3701, 2565, 3759, + 3691, 2611, 3753, + 3679, 2665, 3743, + 3659, 2729, 3731, + 3635, 2803, 3715, + 3599, 2885, 3691, + 3545, 2977, 3659, + 3461, 3075, 3611, + 3319, 3181, 3537, + 3009, 3293, 3415, + 0, 3409, 3173, + 0, 3527, 1904, + 0, 3651, 0, + 0, 3775, 0, + 0, 3901, 0, + 0, 4029, 0, + 3831, 2273, 3843, + 3831, 2273, 3843, + 3831, 2275, 3843, + 3831, 2277, 3843, + 3831, 2279, 3841, + 3831, 2281, 3841, + 3829, 2285, 3841, + 3829, 2289, 3841, + 3829, 2297, 3841, + 3829, 2305, 3841, + 3827, 2315, 3839, + 3827, 2329, 3839, + 3825, 2349, 3837, + 3823, 2371, 3835, + 3819, 2401, 3833, + 3815, 2437, 3831, + 3809, 2483, 3827, + 3801, 2537, 3821, + 3791, 2601, 3813, + 3777, 2673, 3803, + 3759, 2755, 3789, + 3731, 2847, 3769, + 3691, 2945, 3741, + 3633, 3051, 3701, + 3539, 3161, 3641, + 3375, 3277, 3547, + 2979, 3397, 3381, + 0, 3519, 2969, + 0, 3643, 0, + 0, 3769, 0, + 0, 3897, 0, + 0, 4027, 0, + 3939, 2026, 3917, + 3939, 2027, 3917, + 3939, 2029, 3917, + 3939, 2032, 3917, + 3939, 2035, 3917, + 3939, 2040, 3917, + 3939, 2046, 3915, + 3939, 2055, 3915, + 3939, 2065, 3915, + 3937, 2079, 3915, + 3937, 2097, 3915, + 3937, 2119, 3913, + 3935, 2149, 3913, + 3933, 2185, 3911, + 3931, 2229, 3909, + 3927, 2281, 3907, + 3923, 2343, 3903, + 3917, 2415, 3899, + 3909, 2497, 3891, + 3899, 2587, 3883, + 3883, 2683, 3871, + 3863, 2789, 3855, + 3833, 2899, 3833, + 3791, 3015, 3799, + 3729, 3133, 3753, + 3627, 3255, 3681, + 3441, 3379, 3561, + 2935, 3507, 3331, + 0, 3633, 2333, + 0, 3763, 0, + 0, 3893, 0, + 0, 4023, 0, + 4055, 463, 3999, + 4055, 508, 3999, + 4053, 561, 3999, + 4053, 623, 3999, + 4053, 696, 3999, + 4053, 777, 3999, + 4053, 867, 3999, + 4053, 965, 3999, + 4053, 1070, 3999, + 4053, 1181, 3999, + 4051, 1296, 3999, + 4051, 1415, 3997, + 4051, 1537, 3997, + 4049, 1662, 3995, + 4047, 1788, 3993, + 4045, 1916, 3991, + 4041, 2045, 3989, + 4037, 2175, 3985, + 4031, 2305, 3979, + 4023, 2435, 3973, + 4011, 2567, 3963, + 3995, 2697, 3949, + 3973, 2829, 3931, + 3943, 2961, 3905, + 3899, 3093, 3867, + 3831, 3225, 3813, + 3723, 3357, 3727, + 3517, 3489, 3579, + 2867, 3621, 3253, + 0, 3753, 0, + 0, 3885, 0, + 0, 4017, 0, + 4095, 0, 4091, + 4095, 0, 4091, + 4095, 0, 4091, + 4095, 0, 4091, + 4095, 0, 4091, + 4095, 0, 4091, + 4095, 0, 4091, + 4095, 0, 4091, + 4095, 0, 4091, + 4095, 0, 4091, + 4095, 0, 4091, + 4095, 0, 4089, + 4095, 0, 4089, + 4095, 0, 4089, + 4095, 0, 4087, + 4095, 0, 4085, + 4095, 0, 4083, + 4095, 947, 4079, + 4095, 1757, 4075, + 4095, 2097, 4069, + 4095, 2339, 4061, + 4095, 2539, 4051, + 4095, 2717, 4037, + 4089, 2879, 4015, + 4057, 3033, 3987, + 4011, 3181, 3945, + 3941, 3325, 3883, + 3825, 3465, 3783, + 3603, 3603, 3603, + 2759, 3739, 3123, + 0, 3875, 0, + 0, 4009, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 1417, 4095, + 4095, 2167, 4095, + 4095, 2499, 4095, + 4095, 2739, 4095, + 4095, 2937, 4095, + 4095, 3115, 4077, + 4095, 3277, 4033, + 4055, 3431, 3963, + 3933, 3577, 3849, + 3697, 3721, 3631, + 2557, 3861, 2857, + 0, 3999, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 1729, 4095, + 4095, 2441, 4095, + 4095, 2769, 4095, + 4095, 3007, 4095, + 4095, 3203, 4095, + 4095, 3379, 4095, + 4095, 3541, 4051, + 4047, 3695, 3923, + 3797, 3843, 3669, + 1924, 3985, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 2347, 4095, + 4095, 2805, 4095, + 4095, 3085, 4095, + 4095, 3301, 4095, + 4095, 3489, 4095, + 4095, 3657, 4095, + 4095, 3815, 4009, + 3905, 3967, 3713, + 3221, 2773, 3635, + 3221, 2773, 3635, + 3221, 2773, 3635, + 3221, 2773, 3635, + 3221, 2775, 3635, + 3219, 2775, 3635, + 3219, 2777, 3635, + 3217, 2779, 3635, + 3215, 2781, 3633, + 3213, 2783, 3633, + 3209, 2787, 3631, + 3203, 2793, 3629, + 3197, 2799, 3627, + 3187, 2807, 3625, + 3175, 2819, 3621, + 3159, 2835, 3617, + 3135, 2853, 3611, + 3101, 2879, 3601, + 3051, 2909, 3589, + 2973, 2947, 3571, + 2845, 2995, 3547, + 2585, 3051, 3515, + 0, 3115, 3465, + 0, 3191, 3387, + 0, 3275, 3261, + 0, 3367, 3003, + 0, 3467, 0, + 0, 3573, 0, + 0, 3685, 0, + 0, 3803, 0, + 0, 3923, 0, + 0, 4045, 0, + 3223, 2773, 3635, + 3223, 2773, 3635, + 3221, 2773, 3635, + 3221, 2773, 3635, + 3221, 2775, 3635, + 3219, 2775, 3635, + 3219, 2777, 3635, + 3217, 2777, 3635, + 3215, 2781, 3633, + 3213, 2783, 3633, + 3209, 2787, 3631, + 3203, 2791, 3631, + 3197, 2799, 3629, + 3189, 2807, 3625, + 3175, 2819, 3621, + 3159, 2835, 3617, + 3135, 2853, 3611, + 3101, 2879, 3601, + 3051, 2909, 3589, + 2975, 2947, 3571, + 2847, 2995, 3549, + 2587, 3051, 3515, + 0, 3115, 3465, + 0, 3191, 3389, + 0, 3275, 3261, + 0, 3367, 3003, + 0, 3467, 0, + 0, 3573, 0, + 0, 3685, 0, + 0, 3803, 0, + 0, 3923, 0, + 0, 4045, 0, + 3223, 2773, 3635, + 3223, 2773, 3635, + 3223, 2773, 3635, + 3221, 2773, 3635, + 3221, 2775, 3635, + 3221, 2775, 3635, + 3219, 2777, 3635, + 3217, 2777, 3635, + 3215, 2781, 3633, + 3213, 2783, 3633, + 3209, 2787, 3631, + 3205, 2791, 3631, + 3197, 2799, 3629, + 3189, 2807, 3625, + 3177, 2819, 3621, + 3159, 2835, 3617, + 3135, 2853, 3611, + 3101, 2879, 3601, + 3051, 2909, 3589, + 2975, 2947, 3573, + 2847, 2995, 3549, + 2587, 3051, 3515, + 0, 3115, 3465, + 0, 3191, 3389, + 0, 3275, 3261, + 0, 3367, 3003, + 0, 3467, 0, + 0, 3573, 0, + 0, 3685, 0, + 0, 3803, 0, + 0, 3923, 0, + 0, 4045, 0, + 3223, 2773, 3635, + 3223, 2773, 3635, + 3223, 2773, 3635, + 3223, 2773, 3635, + 3221, 2775, 3635, + 3221, 2775, 3635, + 3219, 2777, 3635, + 3219, 2777, 3635, + 3217, 2781, 3633, + 3213, 2783, 3633, + 3209, 2787, 3631, + 3205, 2791, 3631, + 3199, 2799, 3629, + 3189, 2807, 3625, + 3177, 2819, 3623, + 3161, 2835, 3617, + 3137, 2853, 3611, + 3103, 2879, 3601, + 3053, 2909, 3589, + 2977, 2947, 3573, + 2849, 2995, 3549, + 2591, 3051, 3515, + 0, 3115, 3465, + 0, 3191, 3389, + 0, 3275, 3261, + 0, 3367, 3005, + 0, 3467, 0, + 0, 3573, 0, + 0, 3685, 0, + 0, 3803, 0, + 0, 3923, 0, + 0, 4045, 0, + 3225, 2773, 3637, + 3223, 2773, 3637, + 3223, 2773, 3635, + 3223, 2773, 3635, + 3223, 2773, 3635, + 3221, 2775, 3635, + 3221, 2777, 3635, + 3219, 2777, 3635, + 3217, 2779, 3633, + 3215, 2783, 3633, + 3211, 2787, 3633, + 3205, 2791, 3631, + 3199, 2799, 3629, + 3191, 2807, 3625, + 3177, 2819, 3623, + 3161, 2833, 3617, + 3137, 2853, 3611, + 3103, 2877, 3601, + 3053, 2909, 3589, + 2977, 2947, 3573, + 2851, 2995, 3549, + 2593, 3051, 3515, + 0, 3115, 3465, + 0, 3191, 3389, + 0, 3275, 3261, + 0, 3367, 3005, + 0, 3467, 0, + 0, 3573, 0, + 0, 3685, 0, + 0, 3803, 0, + 0, 3923, 0, + 0, 4045, 0, + 3225, 2771, 3637, + 3225, 2773, 3637, + 3225, 2773, 3637, + 3225, 2773, 3637, + 3223, 2773, 3635, + 3223, 2775, 3635, + 3221, 2775, 3635, + 3221, 2777, 3635, + 3219, 2779, 3635, + 3215, 2783, 3633, + 3211, 2787, 3633, + 3207, 2791, 3631, + 3201, 2799, 3629, + 3191, 2807, 3627, + 3179, 2819, 3623, + 3163, 2833, 3617, + 3139, 2853, 3611, + 3105, 2877, 3603, + 3055, 2909, 3589, + 2979, 2947, 3573, + 2853, 2995, 3549, + 2597, 3049, 3515, + 0, 3115, 3465, + 0, 3191, 3389, + 0, 3275, 3263, + 0, 3367, 3007, + 0, 3467, 0, + 0, 3573, 0, + 0, 3685, 0, + 0, 3803, 0, + 0, 3923, 0, + 0, 4045, 0, + 3227, 2771, 3637, + 3227, 2773, 3637, + 3225, 2773, 3637, + 3225, 2773, 3637, + 3225, 2773, 3637, + 3225, 2775, 3637, + 3223, 2775, 3635, + 3221, 2777, 3635, + 3219, 2779, 3635, + 3217, 2783, 3633, + 3213, 2787, 3633, + 3209, 2791, 3631, + 3201, 2799, 3629, + 3193, 2807, 3627, + 3181, 2819, 3623, + 3163, 2833, 3619, + 3141, 2853, 3611, + 3107, 2877, 3603, + 3057, 2909, 3591, + 2981, 2947, 3573, + 2855, 2993, 3549, + 2603, 3049, 3515, + 240, 3115, 3467, + 0, 3191, 3391, + 0, 3275, 3263, + 0, 3367, 3007, + 0, 3467, 0, + 0, 3573, 0, + 0, 3685, 0, + 0, 3803, 0, + 0, 3923, 0, + 0, 4045, 0, + 3229, 2771, 3637, + 3229, 2771, 3637, + 3227, 2773, 3637, + 3227, 2773, 3637, + 3227, 2773, 3637, + 3225, 2775, 3637, + 3225, 2775, 3637, + 3223, 2777, 3635, + 3221, 2779, 3635, + 3219, 2783, 3635, + 3215, 2787, 3633, + 3211, 2791, 3631, + 3203, 2797, 3629, + 3195, 2807, 3627, + 3183, 2819, 3623, + 3165, 2833, 3619, + 3143, 2853, 3611, + 3109, 2877, 3603, + 3059, 2909, 3591, + 2985, 2947, 3573, + 2861, 2993, 3551, + 2611, 3049, 3517, + 861, 3115, 3467, + 0, 3191, 3391, + 0, 3275, 3265, + 0, 3367, 3009, + 0, 3467, 0, + 0, 3573, 0, + 0, 3685, 0, + 0, 3803, 0, + 0, 3923, 0, + 0, 4045, 0, + 3231, 2771, 3639, + 3231, 2771, 3637, + 3231, 2771, 3637, + 3229, 2773, 3637, + 3229, 2773, 3637, + 3229, 2773, 3637, + 3227, 2775, 3637, + 3225, 2777, 3637, + 3223, 2779, 3635, + 3221, 2781, 3635, + 3217, 2785, 3633, + 3213, 2791, 3633, + 3207, 2797, 3631, + 3197, 2807, 3627, + 3185, 2819, 3625, + 3169, 2833, 3619, + 3145, 2853, 3613, + 3113, 2877, 3603, + 3063, 2909, 3591, + 2989, 2947, 3575, + 2865, 2993, 3551, + 2619, 3049, 3517, + 1175, 3115, 3467, + 0, 3189, 3393, + 0, 3275, 3267, + 0, 3367, 3013, + 0, 3467, 0, + 0, 3573, 0, + 0, 3685, 0, + 0, 3803, 0, + 0, 3923, 0, + 0, 4045, 0, + 3235, 2771, 3639, + 3233, 2771, 3639, + 3233, 2771, 3639, + 3233, 2771, 3639, + 3233, 2773, 3639, + 3231, 2773, 3639, + 3231, 2775, 3637, + 3229, 2777, 3637, + 3227, 2779, 3637, + 3225, 2781, 3635, + 3221, 2785, 3635, + 3217, 2791, 3633, + 3209, 2797, 3631, + 3201, 2807, 3629, + 3189, 2817, 3625, + 3173, 2833, 3621, + 3149, 2853, 3613, + 3117, 2877, 3605, + 3069, 2907, 3593, + 2995, 2947, 3575, + 2873, 2993, 3553, + 2633, 3049, 3519, + 1408, 3115, 3469, + 0, 3189, 3393, + 0, 3273, 3269, + 0, 3367, 3015, + 0, 3467, 831, + 0, 3573, 0, + 0, 3685, 0, + 0, 3803, 0, + 0, 3923, 0, + 0, 4045, 0, + 3239, 2771, 3641, + 3239, 2771, 3641, + 3237, 2771, 3639, + 3237, 2771, 3639, + 3237, 2771, 3639, + 3237, 2773, 3639, + 3235, 2775, 3639, + 3233, 2775, 3639, + 3231, 2777, 3637, + 3229, 2781, 3637, + 3225, 2785, 3637, + 3221, 2789, 3635, + 3215, 2797, 3633, + 3205, 2805, 3629, + 3193, 2817, 3627, + 3177, 2833, 3621, + 3155, 2851, 3615, + 3123, 2877, 3607, + 3075, 2907, 3593, + 3001, 2947, 3577, + 2883, 2993, 3553, + 2649, 3049, 3519, + 1603, 3115, 3471, + 0, 3189, 3395, + 0, 3273, 3271, + 0, 3367, 3021, + 0, 3467, 1205, + 0, 3573, 0, + 0, 3685, 0, + 0, 3803, 0, + 0, 3923, 0, + 0, 4045, 0, + 3245, 2769, 3641, + 3245, 2769, 3641, + 3243, 2769, 3641, + 3243, 2771, 3641, + 3243, 2771, 3641, + 3241, 2773, 3641, + 3241, 2773, 3641, + 3239, 2775, 3641, + 3237, 2777, 3639, + 3235, 2781, 3639, + 3231, 2783, 3637, + 3227, 2789, 3637, + 3221, 2795, 3635, + 3211, 2805, 3631, + 3201, 2817, 3627, + 3185, 2831, 3623, + 3161, 2851, 3617, + 3129, 2875, 3607, + 3083, 2907, 3595, + 3011, 2945, 3579, + 2895, 2993, 3555, + 2669, 3049, 3523, + 1777, 3115, 3473, + 0, 3189, 3399, + 0, 3273, 3275, + 0, 3367, 3027, + 0, 3467, 1459, + 0, 3573, 0, + 0, 3685, 0, + 0, 3801, 0, + 0, 3923, 0, + 0, 4045, 0, + 3251, 2769, 3643, + 3251, 2769, 3643, + 3251, 2769, 3643, + 3251, 2769, 3643, + 3251, 2771, 3643, + 3249, 2771, 3643, + 3249, 2773, 3643, + 3247, 2773, 3643, + 3245, 2777, 3641, + 3243, 2779, 3641, + 3239, 2783, 3639, + 3235, 2789, 3639, + 3229, 2795, 3637, + 3221, 2803, 3633, + 3209, 2815, 3631, + 3193, 2831, 3625, + 3171, 2851, 3619, + 3139, 2875, 3611, + 3093, 2907, 3597, + 3025, 2945, 3581, + 2911, 2991, 3557, + 2695, 3047, 3525, + 1938, 3113, 3477, + 0, 3189, 3403, + 0, 3273, 3279, + 0, 3365, 3035, + 0, 3467, 1665, + 0, 3573, 0, + 0, 3685, 0, + 0, 3801, 0, + 0, 3923, 0, + 0, 4045, 0, + 3261, 2767, 3647, + 3261, 2767, 3647, + 3261, 2767, 3647, + 3261, 2767, 3647, + 3261, 2769, 3647, + 3259, 2769, 3645, + 3259, 2771, 3645, + 3257, 2773, 3645, + 3255, 2775, 3645, + 3253, 2777, 3643, + 3249, 2781, 3643, + 3245, 2787, 3641, + 3239, 2793, 3639, + 3231, 2803, 3637, + 3219, 2815, 3633, + 3205, 2829, 3629, + 3183, 2849, 3621, + 3151, 2873, 3613, + 3107, 2905, 3601, + 3041, 2943, 3585, + 2933, 2991, 3561, + 2729, 3047, 3529, + 2091, 3113, 3481, + 0, 3189, 3407, + 0, 3273, 3285, + 0, 3365, 3045, + 0, 3465, 1846, + 0, 3573, 0, + 0, 3685, 0, + 0, 3801, 0, + 0, 3921, 0, + 0, 4045, 0, + 3275, 2765, 3651, + 3275, 2765, 3651, + 3275, 2765, 3651, + 3273, 2765, 3651, + 3273, 2767, 3649, + 3273, 2767, 3649, + 3271, 2769, 3649, + 3271, 2771, 3649, + 3269, 2773, 3649, + 3267, 2775, 3647, + 3263, 2779, 3647, + 3259, 2785, 3645, + 3253, 2791, 3643, + 3245, 2801, 3641, + 3233, 2813, 3637, + 3219, 2827, 3633, + 3197, 2847, 3625, + 3169, 2873, 3617, + 3125, 2903, 3605, + 3061, 2943, 3589, + 2959, 2989, 3565, + 2769, 3047, 3533, + 2237, 3111, 3485, + 0, 3187, 3413, + 0, 3271, 3293, + 0, 3365, 3059, + 0, 3465, 2011, + 0, 3573, 0, + 0, 3685, 0, + 0, 3801, 0, + 0, 3921, 0, + 0, 4045, 0, + 3291, 2763, 3655, + 3291, 2763, 3655, + 3291, 2763, 3655, + 3291, 2763, 3655, + 3291, 2763, 3655, + 3289, 2765, 3655, + 3289, 2767, 3655, + 3287, 2767, 3653, + 3285, 2771, 3653, + 3283, 2773, 3653, + 3281, 2777, 3651, + 3275, 2783, 3651, + 3271, 2789, 3649, + 3263, 2799, 3645, + 3253, 2809, 3643, + 3237, 2825, 3637, + 3217, 2845, 3631, + 3189, 2871, 3623, + 3149, 2901, 3611, + 3089, 2941, 3595, + 2991, 2989, 3571, + 2819, 3045, 3539, + 2381, 3111, 3493, + 0, 3187, 3421, + 0, 3271, 3305, + 0, 3365, 3077, + 0, 3465, 2167, + 0, 3571, 0, + 0, 3685, 0, + 0, 3801, 0, + 0, 3921, 0, + 0, 4045, 0, + 3313, 2759, 3663, + 3313, 2759, 3661, + 3313, 2759, 3661, + 3313, 2759, 3661, + 3311, 2761, 3661, + 3311, 2761, 3661, + 3311, 2763, 3661, + 3309, 2765, 3661, + 3307, 2767, 3659, + 3305, 2769, 3659, + 3303, 2773, 3659, + 3299, 2779, 3657, + 3293, 2785, 3655, + 3285, 2795, 3653, + 3275, 2807, 3649, + 3261, 2823, 3645, + 3243, 2841, 3639, + 3217, 2867, 3629, + 3179, 2899, 3619, + 3121, 2939, 3603, + 3033, 2985, 3579, + 2877, 3043, 3549, + 2521, 3109, 3503, + 0, 3185, 3433, + 0, 3269, 3319, + 0, 3363, 3101, + 0, 3465, 2315, + 0, 3571, 0, + 0, 3683, 0, + 0, 3801, 0, + 0, 3921, 0, + 0, 4045, 0, + 3341, 2753, 3671, + 3341, 2753, 3671, + 3341, 2755, 3671, + 3339, 2755, 3671, + 3339, 2755, 3671, + 3339, 2757, 3671, + 3337, 2757, 3669, + 3337, 2759, 3669, + 3335, 2761, 3669, + 3333, 2765, 3667, + 3331, 2769, 3667, + 3327, 2775, 3665, + 3321, 2781, 3663, + 3315, 2791, 3661, + 3305, 2803, 3657, + 3293, 2817, 3653, + 3275, 2837, 3647, + 3249, 2863, 3639, + 3215, 2895, 3627, + 3163, 2935, 3613, + 3081, 2983, 3591, + 2945, 3041, 3559, + 2659, 3107, 3515, + 0, 3183, 3447, + 0, 3269, 3337, + 0, 3363, 3131, + 0, 3463, 2459, + 0, 3571, 0, + 0, 3683, 0, + 0, 3801, 0, + 0, 3921, 0, + 0, 4045, 0, + 3375, 2747, 3683, + 3375, 2747, 3683, + 3375, 2747, 3681, + 3373, 2749, 3681, + 3373, 2749, 3681, + 3373, 2751, 3681, + 3373, 2751, 3681, + 3371, 2753, 3681, + 3369, 2755, 3681, + 3367, 2759, 3679, + 3365, 2763, 3679, + 3361, 2767, 3677, + 3357, 2775, 3675, + 3351, 2785, 3673, + 3341, 2797, 3669, + 3331, 2813, 3665, + 3313, 2833, 3659, + 3291, 2859, 3651, + 3259, 2891, 3641, + 3213, 2931, 3625, + 3141, 2979, 3603, + 3023, 3037, 3573, + 2795, 3103, 3531, + 1857, 3181, 3465, + 0, 3267, 3361, + 0, 3361, 3167, + 0, 3461, 2601, + 0, 3569, 0, + 0, 3683, 0, + 0, 3799, 0, + 0, 3921, 0, + 0, 4043, 0, + 3417, 2739, 3697, + 3417, 2739, 3697, + 3417, 2739, 3697, + 3415, 2739, 3697, + 3415, 2741, 3697, + 3415, 2741, 3697, + 3415, 2743, 3695, + 3413, 2745, 3695, + 3413, 2747, 3695, + 3411, 2749, 3695, + 3407, 2753, 3693, + 3405, 2759, 3691, + 3401, 2767, 3691, + 3395, 2777, 3687, + 3387, 2789, 3685, + 3377, 2805, 3681, + 3361, 2825, 3675, + 3341, 2851, 3667, + 3313, 2885, 3657, + 3271, 2925, 3641, + 3209, 2973, 3621, + 3109, 3033, 3593, + 2929, 3099, 3551, + 2455, 3177, 3489, + 0, 3263, 3389, + 0, 3359, 3211, + 0, 3459, 2739, + 0, 3569, 0, + 0, 3681, 0, + 0, 3799, 0, + 0, 3919, 0, + 0, 4043, 0, + 3467, 2727, 3715, + 3467, 2727, 3715, + 3467, 2727, 3715, + 3467, 2727, 3715, + 3467, 2729, 3715, + 3465, 2729, 3715, + 3465, 2731, 3715, + 3465, 2733, 3715, + 3463, 2735, 3713, + 3461, 2737, 3713, + 3459, 2743, 3713, + 3457, 2747, 3711, + 3453, 2755, 3709, + 3447, 2765, 3707, + 3441, 2777, 3705, + 3431, 2795, 3701, + 3419, 2815, 3695, + 3401, 2841, 3687, + 3375, 2875, 3677, + 3339, 2917, 3663, + 3287, 2967, 3643, + 3205, 3025, 3617, + 3065, 3095, 3577, + 2765, 3173, 3519, + 0, 3259, 3427, + 0, 3355, 3265, + 0, 3457, 2875, + 0, 3567, 0, + 0, 3679, 0, + 0, 3797, 0, + 0, 3919, 0, + 0, 4043, 0, + 3527, 2709, 3741, + 3527, 2709, 3741, + 3527, 2711, 3739, + 3527, 2711, 3739, + 3527, 2711, 3739, + 3527, 2713, 3739, + 3525, 2713, 3739, + 3525, 2715, 3739, + 3523, 2719, 3739, + 3523, 2721, 3737, + 3521, 2727, 3737, + 3519, 2731, 3735, + 3515, 2739, 3735, + 3511, 2749, 3731, + 3505, 2763, 3729, + 3497, 2779, 3725, + 3485, 2801, 3719, + 3469, 2829, 3713, + 3447, 2863, 3703, + 3417, 2905, 3691, + 3373, 2957, 3671, + 3307, 3017, 3647, + 3199, 3087, 3609, + 2997, 3167, 3555, + 2367, 3255, 3471, + 0, 3351, 3327, + 0, 3455, 3011, + 0, 3563, 0, + 0, 3677, 0, + 0, 3797, 0, + 0, 3917, 0, + 0, 4041, 0, + 3597, 2685, 3771, + 3597, 2687, 3771, + 3597, 2687, 3771, + 3597, 2687, 3771, + 3597, 2689, 3771, + 3595, 2689, 3771, + 3595, 2691, 3769, + 3595, 2693, 3769, + 3593, 2695, 3769, + 3593, 2699, 3769, + 3591, 2703, 3767, + 3589, 2709, 3767, + 3587, 2717, 3765, + 3583, 2729, 3763, + 3577, 2741, 3761, + 3571, 2759, 3757, + 3561, 2783, 3751, + 3547, 2811, 3745, + 3529, 2847, 3737, + 3505, 2891, 3725, + 3469, 2943, 3707, + 3415, 3005, 3683, + 3331, 3077, 3649, + 3191, 3157, 3601, + 2885, 3247, 3525, + 0, 3345, 3399, + 0, 3449, 3145, + 0, 3559, 611, + 0, 3675, 0, + 0, 3795, 0, + 0, 3917, 0, + 0, 4041, 0, + 3675, 2653, 3809, + 3675, 2653, 3809, + 3675, 2653, 3809, + 3675, 2655, 3809, + 3675, 2655, 3809, + 3675, 2657, 3807, + 3675, 2657, 3807, + 3675, 2659, 3807, + 3673, 2663, 3807, + 3673, 2667, 3807, + 3671, 2671, 3805, + 3669, 2677, 3805, + 3667, 2687, 3803, + 3663, 2697, 3801, + 3659, 2713, 3799, + 3653, 2731, 3795, + 3645, 2755, 3791, + 3635, 2785, 3785, + 3621, 2823, 3777, + 3599, 2869, 3765, + 3571, 2925, 3751, + 3529, 2989, 3729, + 3465, 3063, 3699, + 3363, 3147, 3655, + 3179, 3239, 3589, + 2675, 3337, 3481, + 0, 3443, 3281, + 0, 3555, 2665, + 0, 3671, 0, + 0, 3791, 0, + 0, 3913, 0, + 0, 4039, 0, + 3763, 2603, 3855, + 3763, 2605, 3855, + 3763, 2605, 3855, + 3763, 2605, 3855, + 3763, 2607, 3855, + 3763, 2607, 3855, + 3763, 2609, 3853, + 3763, 2611, 3853, + 3761, 2615, 3853, + 3761, 2619, 3853, + 3759, 2625, 3853, + 3759, 2631, 3851, + 3757, 2641, 3849, + 3753, 2653, 3849, + 3751, 2671, 3847, + 3745, 2691, 3843, + 3739, 2717, 3839, + 3731, 2751, 3833, + 3719, 2791, 3827, + 3701, 2839, 3817, + 3679, 2899, 3803, + 3645, 2967, 3783, + 3597, 3043, 3757, + 3525, 3131, 3719, + 3403, 3225, 3661, + 3163, 3327, 3571, + 1971, 3435, 3413, + 0, 3549, 3047, + 0, 3667, 0, + 0, 3787, 0, + 0, 3911, 0, + 0, 4037, 0, + 3859, 2529, 3909, + 3859, 2529, 3909, + 3859, 2531, 3909, + 3859, 2531, 3909, + 3859, 2533, 3909, + 3859, 2533, 3909, + 3859, 2535, 3909, + 3859, 2539, 3909, + 3859, 2543, 3909, + 3857, 2547, 3909, + 3857, 2553, 3907, + 3855, 2561, 3907, + 3853, 2573, 3905, + 3851, 2587, 3905, + 3849, 2607, 3903, + 3845, 2629, 3899, + 3839, 2659, 3897, + 3833, 2697, 3891, + 3823, 2743, 3885, + 3811, 2797, 3875, + 3793, 2861, 3863, + 3767, 2935, 3847, + 3731, 3017, 3825, + 3677, 3109, 3791, + 3593, 3207, 3743, + 3451, 3313, 3669, + 3141, 3425, 3547, + 0, 3541, 3305, + 0, 3659, 2036, + 0, 3783, 0, + 0, 3907, 0, + 0, 4033, 0, + 3963, 2405, 3975, + 3963, 2405, 3975, + 3963, 2407, 3975, + 3963, 2407, 3975, + 3963, 2409, 3975, + 3963, 2411, 3975, + 3963, 2413, 3973, + 3961, 2417, 3973, + 3961, 2423, 3973, + 3961, 2429, 3973, + 3961, 2437, 3973, + 3959, 2447, 3971, + 3959, 2461, 3971, + 3957, 2481, 3969, + 3955, 2503, 3967, + 3951, 2533, 3965, + 3947, 2571, 3963, + 3941, 2615, 3959, + 3935, 2669, 3953, + 3923, 2733, 3945, + 3909, 2805, 3935, + 3891, 2887, 3921, + 3863, 2979, 3901, + 3823, 3077, 3873, + 3765, 3183, 3833, + 3671, 3293, 3773, + 3507, 3409, 3679, + 3111, 3529, 3513, + 0, 3651, 3101, + 0, 3775, 0, + 0, 3901, 0, + 0, 4029, 0, + 4073, 2157, 4049, + 4073, 2157, 4049, + 4071, 2159, 4049, + 4071, 2161, 4049, + 4071, 2163, 4049, + 4071, 2167, 4049, + 4071, 2173, 4049, + 4071, 2179, 4049, + 4071, 2187, 4047, + 4071, 2197, 4047, + 4071, 2211, 4047, + 4069, 2229, 4047, + 4069, 2251, 4045, + 4067, 2281, 4045, + 4065, 2317, 4043, + 4063, 2361, 4041, + 4059, 2413, 4039, + 4055, 2475, 4035, + 4049, 2547, 4031, + 4041, 2629, 4025, + 4031, 2719, 4015, + 4015, 2815, 4003, + 3995, 2921, 3987, + 3967, 3031, 3965, + 3923, 3147, 3931, + 3861, 3265, 3885, + 3759, 3387, 3813, + 3573, 3511, 3693, + 3067, 3639, 3463, + 0, 3765, 2465, + 0, 3895, 0, + 0, 4025, 0, + 4095, 559, 4095, + 4095, 596, 4095, + 4095, 640, 4095, + 4095, 693, 4095, + 4095, 756, 4095, + 4095, 828, 4095, + 4095, 909, 4095, + 4095, 999, 4095, + 4095, 1097, 4095, + 4095, 1202, 4095, + 4095, 1313, 4095, + 4095, 1428, 4095, + 4095, 1547, 4095, + 4095, 1669, 4095, + 4095, 1794, 4095, + 4095, 1920, 4095, + 4095, 2049, 4095, + 4095, 2177, 4095, + 4095, 2307, 4095, + 4095, 2437, 4095, + 4095, 2567, 4095, + 4095, 2699, 4095, + 4095, 2831, 4081, + 4095, 2961, 4063, + 4075, 3093, 4037, + 4031, 3225, 4001, + 3963, 3357, 3945, + 3855, 3489, 3859, + 3649, 3621, 3711, + 3001, 3753, 3385, + 0, 3885, 0, + 0, 4017, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 1079, 4095, + 4095, 1889, 4095, + 4095, 2229, 4095, + 4095, 2471, 4095, + 4095, 2671, 4095, + 4095, 2849, 4095, + 4095, 3011, 4095, + 4095, 3165, 4095, + 4095, 3313, 4077, + 4073, 3457, 4015, + 3957, 3597, 3915, + 3735, 3735, 3735, + 2891, 3871, 3255, + 0, 4007, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 1549, 4095, + 4095, 2299, 4095, + 4095, 2631, 4095, + 4095, 2871, 4095, + 4095, 3069, 4095, + 4095, 3247, 4095, + 4095, 3409, 4095, + 4095, 3563, 4095, + 4067, 3709, 3981, + 3829, 3853, 3765, + 2689, 3993, 2989, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 1862, 4095, + 4095, 2573, 4095, + 4095, 2901, 4095, + 4095, 3139, 4095, + 4095, 3337, 4095, + 4095, 3511, 4095, + 4095, 3673, 4095, + 4095, 3827, 4057, + 3929, 3975, 3801, + 3355, 2905, 3767, + 3353, 2905, 3767, + 3353, 2905, 3767, + 3353, 2905, 3767, + 3353, 2905, 3767, + 3353, 2907, 3767, + 3351, 2907, 3767, + 3351, 2909, 3767, + 3349, 2911, 3767, + 3347, 2913, 3765, + 3345, 2915, 3765, + 3341, 2919, 3763, + 3335, 2925, 3763, + 3329, 2931, 3761, + 3319, 2939, 3757, + 3307, 2951, 3753, + 3291, 2967, 3749, + 3267, 2985, 3743, + 3233, 3011, 3733, + 3183, 3041, 3721, + 3105, 3079, 3703, + 2977, 3127, 3681, + 2715, 3183, 3647, + 0, 3247, 3597, + 0, 3323, 3521, + 0, 3407, 3393, + 0, 3499, 3135, + 0, 3599, 0, + 0, 3705, 0, + 0, 3817, 0, + 0, 3935, 0, + 0, 4055, 0, + 3355, 2905, 3767, + 3355, 2905, 3767, + 3353, 2905, 3767, + 3353, 2905, 3767, + 3353, 2905, 3767, + 3353, 2907, 3767, + 3351, 2907, 3767, + 3351, 2909, 3767, + 3349, 2911, 3767, + 3347, 2913, 3765, + 3345, 2915, 3765, + 3341, 2919, 3763, + 3335, 2925, 3763, + 3329, 2931, 3761, + 3321, 2939, 3757, + 3307, 2951, 3753, + 3291, 2967, 3749, + 3267, 2985, 3743, + 3233, 3011, 3733, + 3183, 3041, 3721, + 3105, 3079, 3703, + 2977, 3127, 3681, + 2717, 3183, 3647, + 0, 3247, 3597, + 0, 3323, 3521, + 0, 3407, 3393, + 0, 3499, 3135, + 0, 3599, 0, + 0, 3705, 0, + 0, 3817, 0, + 0, 3935, 0, + 0, 4055, 0, + 3355, 2905, 3767, + 3355, 2905, 3767, + 3355, 2905, 3767, + 3353, 2905, 3767, + 3353, 2905, 3767, + 3353, 2907, 3767, + 3351, 2907, 3767, + 3351, 2909, 3767, + 3349, 2911, 3767, + 3347, 2913, 3765, + 3345, 2915, 3765, + 3341, 2919, 3763, + 3337, 2925, 3763, + 3329, 2931, 3761, + 3321, 2939, 3757, + 3309, 2951, 3753, + 3291, 2967, 3749, + 3267, 2985, 3743, + 3233, 3011, 3733, + 3183, 3041, 3721, + 3107, 3079, 3705, + 2979, 3127, 3681, + 2719, 3183, 3647, + 0, 3247, 3597, + 0, 3323, 3521, + 0, 3407, 3393, + 0, 3499, 3135, + 0, 3599, 0, + 0, 3705, 0, + 0, 3817, 0, + 0, 3935, 0, + 0, 4055, 0, + 3355, 2905, 3767, + 3355, 2905, 3767, + 3355, 2905, 3767, + 3355, 2905, 3767, + 3353, 2905, 3767, + 3353, 2907, 3767, + 3353, 2907, 3767, + 3351, 2909, 3767, + 3349, 2911, 3767, + 3347, 2913, 3765, + 3345, 2915, 3765, + 3341, 2919, 3763, + 3337, 2925, 3763, + 3329, 2931, 3761, + 3321, 2939, 3757, + 3309, 2951, 3753, + 3291, 2967, 3749, + 3267, 2985, 3743, + 3233, 3011, 3733, + 3183, 3041, 3721, + 3107, 3079, 3705, + 2979, 3127, 3681, + 2721, 3183, 3647, + 0, 3247, 3597, + 0, 3323, 3521, + 0, 3407, 3393, + 0, 3499, 3135, + 0, 3599, 0, + 0, 3705, 0, + 0, 3817, 0, + 0, 3935, 0, + 0, 4055, 0, + 3355, 2905, 3769, + 3355, 2905, 3769, + 3355, 2905, 3769, + 3355, 2905, 3767, + 3355, 2905, 3767, + 3353, 2907, 3767, + 3353, 2907, 3767, + 3351, 2909, 3767, + 3351, 2909, 3767, + 3349, 2913, 3765, + 3345, 2915, 3765, + 3343, 2919, 3763, + 3337, 2923, 3763, + 3331, 2931, 3761, + 3321, 2939, 3757, + 3309, 2951, 3755, + 3293, 2967, 3749, + 3269, 2985, 3743, + 3235, 3011, 3733, + 3185, 3041, 3721, + 3109, 3079, 3705, + 2981, 3127, 3681, + 2723, 3183, 3647, + 0, 3247, 3597, + 0, 3323, 3521, + 0, 3407, 3393, + 0, 3499, 3137, + 0, 3599, 0, + 0, 3705, 0, + 0, 3817, 0, + 0, 3935, 0, + 0, 4055, 0, + 3357, 2903, 3769, + 3357, 2905, 3769, + 3355, 2905, 3769, + 3355, 2905, 3769, + 3355, 2905, 3767, + 3355, 2907, 3767, + 3353, 2907, 3767, + 3353, 2909, 3767, + 3351, 2909, 3767, + 3349, 2913, 3767, + 3347, 2915, 3765, + 3343, 2919, 3765, + 3337, 2923, 3763, + 3331, 2931, 3761, + 3323, 2939, 3757, + 3311, 2951, 3755, + 3293, 2967, 3749, + 3269, 2985, 3743, + 3235, 3011, 3733, + 3185, 3041, 3721, + 3109, 3079, 3705, + 2983, 3127, 3681, + 2725, 3183, 3647, + 0, 3247, 3597, + 0, 3323, 3521, + 0, 3407, 3393, + 0, 3499, 3137, + 0, 3599, 0, + 0, 3705, 0, + 0, 3817, 0, + 0, 3935, 0, + 0, 4055, 0, + 3357, 2903, 3769, + 3357, 2905, 3769, + 3357, 2905, 3769, + 3357, 2905, 3769, + 3357, 2905, 3769, + 3355, 2905, 3769, + 3355, 2907, 3767, + 3353, 2909, 3767, + 3353, 2909, 3767, + 3351, 2911, 3767, + 3347, 2915, 3765, + 3343, 2919, 3765, + 3339, 2923, 3763, + 3333, 2931, 3761, + 3323, 2939, 3759, + 3311, 2951, 3755, + 3295, 2965, 3749, + 3271, 2985, 3743, + 3237, 3009, 3735, + 3187, 3041, 3721, + 3111, 3079, 3705, + 2985, 3127, 3681, + 2729, 3183, 3647, + 0, 3247, 3597, + 0, 3323, 3521, + 0, 3407, 3395, + 0, 3499, 3139, + 0, 3599, 0, + 0, 3705, 0, + 0, 3817, 0, + 0, 3935, 0, + 0, 4055, 0, + 3359, 2903, 3769, + 3359, 2903, 3769, + 3359, 2905, 3769, + 3359, 2905, 3769, + 3357, 2905, 3769, + 3357, 2905, 3769, + 3357, 2907, 3769, + 3355, 2907, 3767, + 3353, 2909, 3767, + 3351, 2911, 3767, + 3349, 2915, 3765, + 3345, 2919, 3765, + 3341, 2923, 3763, + 3333, 2931, 3761, + 3325, 2939, 3759, + 3313, 2951, 3755, + 3295, 2965, 3751, + 3273, 2985, 3743, + 3239, 3009, 3735, + 3189, 3041, 3723, + 3113, 3079, 3705, + 2987, 3127, 3681, + 2735, 3181, 3647, + 372, 3247, 3599, + 0, 3323, 3523, + 0, 3407, 3395, + 0, 3499, 3139, + 0, 3599, 0, + 0, 3705, 0, + 0, 3817, 0, + 0, 3935, 0, + 0, 4055, 0, + 3361, 2903, 3769, + 3361, 2903, 3769, + 3361, 2903, 3769, + 3359, 2905, 3769, + 3359, 2905, 3769, + 3359, 2905, 3769, + 3359, 2907, 3769, + 3357, 2907, 3769, + 3355, 2909, 3767, + 3353, 2911, 3767, + 3351, 2915, 3767, + 3347, 2919, 3765, + 3343, 2923, 3763, + 3335, 2931, 3761, + 3327, 2939, 3759, + 3315, 2951, 3755, + 3297, 2965, 3751, + 3275, 2985, 3745, + 3241, 3009, 3735, + 3193, 3041, 3723, + 3117, 3079, 3705, + 2993, 3125, 3683, + 2743, 3181, 3649, + 994, 3247, 3599, + 0, 3323, 3523, + 0, 3407, 3397, + 0, 3499, 3141, + 0, 3599, 0, + 0, 3705, 0, + 0, 3817, 0, + 0, 3935, 0, + 0, 4055, 0, + 3363, 2903, 3771, + 3363, 2903, 3771, + 3363, 2903, 3771, + 3363, 2903, 3769, + 3361, 2905, 3769, + 3361, 2905, 3769, + 3361, 2907, 3769, + 3359, 2907, 3769, + 3357, 2909, 3769, + 3357, 2911, 3767, + 3353, 2915, 3767, + 3349, 2917, 3767, + 3345, 2923, 3765, + 3339, 2929, 3763, + 3329, 2939, 3759, + 3317, 2951, 3757, + 3301, 2965, 3751, + 3277, 2985, 3745, + 3245, 3009, 3735, + 3195, 3041, 3723, + 3121, 3079, 3707, + 2997, 3125, 3683, + 2753, 3181, 3649, + 1308, 3247, 3599, + 0, 3323, 3525, + 0, 3407, 3399, + 0, 3499, 3145, + 0, 3599, 0, + 0, 3705, 0, + 0, 3817, 0, + 0, 3935, 0, + 0, 4055, 0, + 3367, 2903, 3771, + 3367, 2903, 3771, + 3367, 2903, 3771, + 3365, 2903, 3771, + 3365, 2903, 3771, + 3365, 2905, 3771, + 3363, 2905, 3771, + 3363, 2907, 3769, + 3361, 2909, 3769, + 3359, 2911, 3769, + 3357, 2913, 3769, + 3353, 2917, 3767, + 3349, 2923, 3765, + 3341, 2929, 3763, + 3333, 2939, 3761, + 3321, 2949, 3757, + 3305, 2965, 3753, + 3281, 2985, 3745, + 3249, 3009, 3737, + 3201, 3041, 3725, + 3127, 3079, 3707, + 3005, 3125, 3685, + 2765, 3181, 3651, + 1540, 3247, 3601, + 0, 3321, 3525, + 0, 3407, 3401, + 0, 3499, 3147, + 0, 3599, 963, + 0, 3705, 0, + 0, 3817, 0, + 0, 3935, 0, + 0, 4055, 0, + 3371, 2901, 3773, + 3371, 2903, 3773, + 3371, 2903, 3773, + 3371, 2903, 3773, + 3369, 2903, 3771, + 3369, 2905, 3771, + 3369, 2905, 3771, + 3367, 2907, 3771, + 3365, 2907, 3771, + 3363, 2911, 3771, + 3361, 2913, 3769, + 3357, 2917, 3769, + 3353, 2921, 3767, + 3347, 2929, 3765, + 3337, 2937, 3763, + 3325, 2949, 3759, + 3309, 2965, 3753, + 3287, 2983, 3747, + 3255, 3009, 3739, + 3207, 3039, 3725, + 3135, 3079, 3709, + 3015, 3125, 3685, + 2781, 3181, 3653, + 1735, 3247, 3603, + 0, 3321, 3527, + 0, 3405, 3403, + 0, 3499, 3153, + 0, 3599, 1337, + 0, 3705, 0, + 0, 3817, 0, + 0, 3935, 0, + 0, 4055, 0, + 3377, 2901, 3773, + 3377, 2901, 3773, + 3377, 2901, 3773, + 3375, 2903, 3773, + 3375, 2903, 3773, + 3375, 2903, 3773, + 3375, 2905, 3773, + 3373, 2905, 3773, + 3371, 2907, 3773, + 3369, 2909, 3771, + 3367, 2913, 3771, + 3363, 2917, 3769, + 3359, 2921, 3769, + 3353, 2927, 3767, + 3345, 2937, 3763, + 3333, 2949, 3761, + 3317, 2963, 3755, + 3293, 2983, 3749, + 3261, 3007, 3739, + 3215, 3039, 3727, + 3143, 3077, 3711, + 3027, 3125, 3687, + 2801, 3181, 3655, + 1909, 3247, 3605, + 0, 3321, 3531, + 0, 3405, 3407, + 0, 3499, 3159, + 0, 3599, 1591, + 0, 3705, 0, + 0, 3817, 0, + 0, 3935, 0, + 0, 4055, 0, + 3385, 2901, 3777, + 3385, 2901, 3775, + 3383, 2901, 3775, + 3383, 2901, 3775, + 3383, 2901, 3775, + 3383, 2903, 3775, + 3381, 2903, 3775, + 3381, 2905, 3775, + 3379, 2905, 3775, + 3377, 2909, 3773, + 3375, 2911, 3773, + 3371, 2915, 3771, + 3367, 2921, 3771, + 3361, 2927, 3769, + 3353, 2935, 3765, + 3341, 2947, 3763, + 3325, 2963, 3757, + 3303, 2983, 3751, + 3271, 3007, 3743, + 3225, 3039, 3731, + 3157, 3077, 3713, + 3043, 3123, 3691, + 2827, 3181, 3657, + 2071, 3245, 3609, + 0, 3321, 3535, + 0, 3405, 3411, + 0, 3499, 3167, + 0, 3599, 1797, + 0, 3705, 0, + 0, 3817, 0, + 0, 3933, 0, + 0, 4055, 0, + 3395, 2899, 3779, + 3393, 2899, 3779, + 3393, 2899, 3779, + 3393, 2899, 3779, + 3393, 2901, 3779, + 3393, 2901, 3779, + 3391, 2901, 3779, + 3391, 2903, 3777, + 3389, 2905, 3777, + 3387, 2907, 3777, + 3385, 2909, 3775, + 3381, 2913, 3775, + 3377, 2919, 3773, + 3371, 2925, 3771, + 3363, 2935, 3769, + 3351, 2947, 3765, + 3337, 2961, 3761, + 3315, 2981, 3755, + 3285, 3005, 3745, + 3239, 3037, 3733, + 3173, 3075, 3717, + 3065, 3123, 3693, + 2861, 3179, 3661, + 2223, 3245, 3613, + 0, 3321, 3539, + 0, 3405, 3417, + 0, 3497, 3177, + 0, 3599, 1978, + 0, 3705, 0, + 0, 3817, 0, + 0, 3933, 0, + 0, 4055, 0, + 3407, 2897, 3783, + 3407, 2897, 3783, + 3407, 2897, 3783, + 3407, 2897, 3783, + 3407, 2899, 3783, + 3405, 2899, 3783, + 3405, 2899, 3781, + 3403, 2901, 3781, + 3403, 2903, 3781, + 3401, 2905, 3781, + 3399, 2907, 3779, + 3395, 2911, 3779, + 3391, 2917, 3777, + 3385, 2923, 3775, + 3377, 2933, 3773, + 3365, 2945, 3769, + 3351, 2959, 3765, + 3331, 2979, 3757, + 3301, 3005, 3749, + 3257, 3035, 3737, + 3193, 3075, 3721, + 3091, 3121, 3699, + 2901, 3179, 3665, + 2369, 3245, 3617, + 0, 3319, 3545, + 0, 3405, 3425, + 0, 3497, 3191, + 0, 3597, 2143, + 0, 3705, 0, + 0, 3817, 0, + 0, 3933, 0, + 0, 4053, 0, + 3423, 2893, 3787, + 3423, 2895, 3787, + 3423, 2895, 3787, + 3423, 2895, 3787, + 3423, 2895, 3787, + 3423, 2897, 3787, + 3421, 2897, 3787, + 3421, 2899, 3787, + 3419, 2899, 3787, + 3417, 2903, 3785, + 3415, 2905, 3785, + 3413, 2909, 3783, + 3409, 2915, 3783, + 3403, 2921, 3781, + 3395, 2931, 3777, + 3385, 2943, 3775, + 3369, 2957, 3769, + 3349, 2977, 3763, + 3321, 3003, 3755, + 3281, 3033, 3743, + 3221, 3073, 3727, + 3123, 3121, 3705, + 2951, 3177, 3671, + 2513, 3243, 3625, + 0, 3319, 3553, + 0, 3403, 3437, + 0, 3497, 3209, + 0, 3597, 2299, + 0, 3705, 0, + 0, 3817, 0, + 0, 3933, 0, + 0, 4053, 0, + 3445, 2891, 3795, + 3445, 2891, 3795, + 3445, 2891, 3795, + 3445, 2891, 3795, + 3445, 2891, 3793, + 3443, 2893, 3793, + 3443, 2893, 3793, + 3443, 2895, 3793, + 3441, 2897, 3793, + 3439, 2899, 3793, + 3437, 2901, 3791, + 3435, 2905, 3791, + 3431, 2911, 3789, + 3425, 2917, 3787, + 3417, 2927, 3785, + 3407, 2939, 3781, + 3395, 2955, 3777, + 3375, 2975, 3771, + 3349, 2999, 3761, + 3311, 3031, 3751, + 3253, 3071, 3735, + 3165, 3119, 3713, + 3009, 3175, 3681, + 2653, 3241, 3635, + 0, 3317, 3565, + 0, 3403, 3451, + 0, 3495, 3233, + 0, 3597, 2447, + 0, 3703, 0, + 0, 3817, 0, + 0, 3933, 0, + 0, 4053, 0, + 3473, 2885, 3803, + 3473, 2885, 3803, + 3473, 2887, 3803, + 3473, 2887, 3803, + 3471, 2887, 3803, + 3471, 2887, 3803, + 3471, 2889, 3803, + 3469, 2889, 3801, + 3469, 2891, 3801, + 3467, 2893, 3801, + 3465, 2897, 3801, + 3463, 2901, 3799, + 3459, 2907, 3797, + 3453, 2913, 3795, + 3447, 2923, 3793, + 3437, 2935, 3789, + 3425, 2951, 3785, + 3407, 2971, 3779, + 3383, 2995, 3771, + 3347, 3027, 3759, + 3295, 3067, 3745, + 3213, 3115, 3723, + 3077, 3173, 3691, + 2791, 3239, 3647, + 0, 3315, 3579, + 0, 3401, 3469, + 0, 3495, 3263, + 0, 3595, 2591, + 0, 3703, 0, + 0, 3815, 0, + 0, 3933, 0, + 0, 4053, 0, + 3507, 2879, 3815, + 3507, 2879, 3815, + 3507, 2879, 3815, + 3507, 2879, 3815, + 3507, 2881, 3813, + 3505, 2881, 3813, + 3505, 2883, 3813, + 3505, 2883, 3813, + 3503, 2885, 3813, + 3501, 2887, 3813, + 3499, 2891, 3811, + 3497, 2895, 3811, + 3493, 2901, 3809, + 3489, 2907, 3807, + 3483, 2917, 3805, + 3475, 2929, 3801, + 3463, 2945, 3797, + 3447, 2965, 3791, + 3423, 2991, 3783, + 3391, 3023, 3773, + 3345, 3063, 3757, + 3273, 3111, 3735, + 3155, 3169, 3707, + 2927, 3235, 3663, + 1989, 3313, 3597, + 0, 3399, 3493, + 0, 3493, 3299, + 0, 3593, 2733, + 0, 3701, 0, + 0, 3815, 0, + 0, 3931, 0, + 0, 4053, 0, + 3549, 2871, 3829, + 3549, 2871, 3829, + 3549, 2871, 3829, + 3549, 2871, 3829, + 3549, 2871, 3829, + 3547, 2873, 3829, + 3547, 2873, 3829, + 3547, 2875, 3827, + 3545, 2877, 3827, + 3545, 2879, 3827, + 3543, 2881, 3827, + 3541, 2887, 3825, + 3537, 2891, 3825, + 3533, 2899, 3823, + 3527, 2909, 3819, + 3519, 2921, 3817, + 3509, 2937, 3813, + 3493, 2957, 3807, + 3473, 2983, 3799, + 3445, 3017, 3789, + 3403, 3057, 3773, + 3341, 3105, 3753, + 3241, 3165, 3725, + 3061, 3231, 3683, + 2587, 3309, 3621, + 0, 3395, 3521, + 0, 3491, 3343, + 0, 3593, 2871, + 0, 3701, 0, + 0, 3813, 0, + 0, 3931, 0, + 0, 4051, 0, + 3599, 2857, 3849, + 3599, 2859, 3847, + 3599, 2859, 3847, + 3599, 2859, 3847, + 3599, 2859, 3847, + 3599, 2861, 3847, + 3599, 2861, 3847, + 3597, 2863, 3847, + 3597, 2865, 3847, + 3595, 2867, 3847, + 3593, 2871, 3845, + 3591, 2875, 3845, + 3589, 2879, 3843, + 3585, 2887, 3841, + 3579, 2897, 3839, + 3573, 2909, 3837, + 3563, 2927, 3833, + 3551, 2947, 3827, + 3533, 2975, 3819, + 3507, 3007, 3809, + 3471, 3049, 3795, + 3419, 3099, 3775, + 3337, 3157, 3749, + 3197, 3227, 3709, + 2897, 3305, 3651, + 0, 3391, 3559, + 0, 3487, 3397, + 0, 3589, 3007, + 0, 3699, 0, + 0, 3811, 0, + 0, 3929, 0, + 0, 4051, 0, + 3659, 2841, 3873, + 3659, 2841, 3873, + 3659, 2841, 3873, + 3659, 2843, 3873, + 3659, 2843, 3871, + 3659, 2843, 3871, + 3659, 2845, 3871, + 3657, 2847, 3871, + 3657, 2847, 3871, + 3655, 2851, 3871, + 3655, 2853, 3869, + 3653, 2859, 3869, + 3651, 2865, 3867, + 3647, 2871, 3867, + 3643, 2881, 3865, + 3637, 2895, 3861, + 3629, 2911, 3857, + 3617, 2933, 3853, + 3601, 2961, 3845, + 3579, 2995, 3835, + 3549, 3037, 3823, + 3505, 3089, 3805, + 3439, 3149, 3779, + 3331, 3219, 3741, + 3129, 3299, 3687, + 2499, 3387, 3603, + 0, 3483, 3459, + 0, 3587, 3143, + 0, 3695, 0, + 0, 3809, 0, + 0, 3929, 0, + 0, 4049, 0, + 3729, 2817, 3903, + 3729, 2819, 3903, + 3729, 2819, 3903, + 3729, 2819, 3903, + 3729, 2819, 3903, + 3729, 2821, 3903, + 3727, 2821, 3903, + 3727, 2823, 3901, + 3727, 2825, 3901, + 3725, 2827, 3901, + 3725, 2831, 3901, + 3723, 2835, 3899, + 3721, 2841, 3899, + 3719, 2849, 3897, + 3715, 2861, 3895, + 3709, 2875, 3893, + 3703, 2891, 3889, + 3693, 2915, 3883, + 3679, 2943, 3877, + 3661, 2979, 3869, + 3637, 3023, 3857, + 3601, 3075, 3839, + 3547, 3137, 3815, + 3463, 3209, 3781, + 3323, 3291, 3733, + 3017, 3379, 3657, + 0, 3477, 3531, + 0, 3581, 3279, + 0, 3693, 744, + 0, 3807, 0, + 0, 3927, 0, + 0, 4049, 0, + 3809, 2785, 3941, + 3809, 2785, 3941, + 3807, 2785, 3941, + 3807, 2785, 3941, + 3807, 2787, 3941, + 3807, 2787, 3941, + 3807, 2789, 3941, + 3807, 2789, 3939, + 3807, 2791, 3939, + 3805, 2795, 3939, + 3805, 2799, 3939, + 3803, 2803, 3937, + 3801, 2811, 3937, + 3799, 2819, 3935, + 3795, 2831, 3933, + 3791, 2845, 3931, + 3785, 2863, 3927, + 3777, 2887, 3923, + 3767, 2919, 3917, + 3753, 2955, 3909, + 3731, 3001, 3897, + 3703, 3057, 3883, + 3661, 3121, 3861, + 3597, 3195, 3831, + 3495, 3279, 3787, + 3311, 3371, 3721, + 2807, 3469, 3613, + 0, 3575, 3413, + 0, 3687, 2797, + 0, 3803, 0, + 0, 3923, 0, + 0, 4047, 0, + 3897, 2735, 3987, + 3895, 2735, 3987, + 3895, 2737, 3987, + 3895, 2737, 3987, + 3895, 2737, 3987, + 3895, 2739, 3987, + 3895, 2739, 3987, + 3895, 2741, 3987, + 3895, 2743, 3985, + 3893, 2747, 3985, + 3893, 2751, 3985, + 3891, 2757, 3985, + 3891, 2765, 3983, + 3889, 2773, 3983, + 3885, 2787, 3981, + 3883, 2803, 3979, + 3877, 2823, 3975, + 3871, 2849, 3971, + 3863, 2883, 3965, + 3851, 2923, 3959, + 3833, 2973, 3949, + 3811, 3031, 3935, + 3777, 3099, 3915, + 3729, 3177, 3889, + 3657, 3263, 3851, + 3535, 3357, 3793, + 3295, 3459, 3703, + 2103, 3567, 3545, + 0, 3681, 3179, + 0, 3799, 0, + 0, 3919, 0, + 0, 4043, 0, + 3993, 2661, 4041, + 3991, 2661, 4041, + 3991, 2661, 4041, + 3991, 2663, 4041, + 3991, 2663, 4041, + 3991, 2665, 4041, + 3991, 2665, 4041, + 3991, 2667, 4041, + 3991, 2671, 4041, + 3991, 2675, 4041, + 3989, 2679, 4041, + 3989, 2685, 4039, + 3987, 2695, 4039, + 3985, 2705, 4037, + 3983, 2719, 4037, + 3981, 2739, 4035, + 3977, 2763, 4031, + 3971, 2793, 4029, + 3965, 2829, 4023, + 3955, 2875, 4017, + 3943, 2929, 4009, + 3925, 2993, 3997, + 3899, 3067, 3979, + 3863, 3149, 3957, + 3809, 3241, 3923, + 3725, 3339, 3875, + 3583, 3445, 3801, + 3273, 3557, 3679, + 0, 3673, 3437, + 0, 3791, 2169, + 0, 3915, 0, + 0, 4039, 0, + 4095, 2537, 4095, + 4095, 2537, 4095, + 4095, 2537, 4095, + 4095, 2539, 4095, + 4095, 2539, 4095, + 4095, 2541, 4095, + 4095, 2543, 4095, + 4095, 2545, 4095, + 4095, 2549, 4095, + 4093, 2555, 4095, + 4093, 2561, 4095, + 4093, 2569, 4095, + 4091, 2579, 4095, + 4091, 2595, 4095, + 4089, 2613, 4095, + 4087, 2635, 4095, + 4083, 2665, 4095, + 4079, 2703, 4095, + 4073, 2747, 4091, + 4067, 2801, 4085, + 4055, 2865, 4077, + 4041, 2937, 4067, + 4023, 3019, 4053, + 3995, 3111, 4033, + 3955, 3209, 4005, + 3897, 3315, 3965, + 3803, 3425, 3907, + 3639, 3541, 3811, + 3243, 3661, 3645, + 0, 3783, 3235, + 0, 3907, 0, + 0, 4033, 0, + 4095, 2287, 4095, + 4095, 2289, 4095, + 4095, 2289, 4095, + 4095, 2291, 4095, + 4095, 2293, 4095, + 4095, 2295, 4095, + 4095, 2299, 4095, + 4095, 2305, 4095, + 4095, 2311, 4095, + 4095, 2319, 4095, + 4095, 2329, 4095, + 4095, 2343, 4095, + 4095, 2361, 4095, + 4095, 2383, 4095, + 4095, 2413, 4095, + 4095, 2449, 4095, + 4095, 2493, 4095, + 4095, 2545, 4095, + 4095, 2607, 4095, + 4095, 2679, 4095, + 4095, 2761, 4095, + 4095, 2851, 4095, + 4095, 2949, 4095, + 4095, 3053, 4095, + 4095, 3163, 4095, + 4057, 3279, 4065, + 3993, 3397, 4017, + 3891, 3519, 3945, + 3707, 3643, 3825, + 3199, 3771, 3595, + 0, 3899, 2597, + 0, 4027, 0, + 4095, 662, 4095, + 4095, 691, 4095, + 4095, 728, 4095, + 4095, 772, 4095, + 4095, 825, 4095, + 4095, 888, 4095, + 4095, 960, 4095, + 4095, 1041, 4095, + 4095, 1131, 4095, + 4095, 1229, 4095, + 4095, 1334, 4095, + 4095, 1445, 4095, + 4095, 1560, 4095, + 4095, 1679, 4095, + 4095, 1802, 4095, + 4095, 1926, 4095, + 4095, 2053, 4095, + 4095, 2181, 4095, + 4095, 2309, 4095, + 4095, 2439, 4095, + 4095, 2569, 4095, + 4095, 2699, 4095, + 4095, 2831, 4095, + 4095, 2963, 4095, + 4095, 3093, 4095, + 4095, 3225, 4095, + 4095, 3357, 4095, + 4095, 3489, 4077, + 3987, 3621, 3991, + 3783, 3753, 3843, + 3133, 3885, 3517, + 0, 4017, 0, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 1211, 4095, + 4095, 2021, 4095, + 4095, 2361, 4095, + 4095, 2603, 4095, + 4095, 2803, 4095, + 4095, 2981, 4095, + 4095, 3143, 4095, + 4095, 3297, 4095, + 4095, 3445, 4095, + 4095, 3589, 4095, + 4089, 3729, 4047, + 3867, 3867, 3867, + 3023, 4003, 3387, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 1681, 4095, + 4095, 2431, 4095, + 4095, 2763, 4095, + 4095, 3003, 4095, + 4095, 3203, 4095, + 4095, 3379, 4095, + 4095, 3541, 4095, + 4095, 3695, 4095, + 4095, 3841, 4095, + 3961, 3985, 3897, + 3487, 3037, 3899, + 3487, 3037, 3899, + 3485, 3037, 3899, + 3485, 3037, 3899, + 3485, 3037, 3899, + 3485, 3037, 3899, + 3485, 3039, 3899, + 3483, 3039, 3899, + 3483, 3041, 3899, + 3481, 3043, 3899, + 3479, 3045, 3897, + 3475, 3047, 3897, + 3473, 3051, 3895, + 3467, 3057, 3895, + 3461, 3063, 3893, + 3451, 3071, 3889, + 3439, 3083, 3885, + 3423, 3099, 3881, + 3399, 3117, 3875, + 3365, 3143, 3865, + 3315, 3173, 3853, + 3237, 3211, 3835, + 3109, 3259, 3813, + 2847, 3315, 3779, + 0, 3379, 3729, + 0, 3455, 3653, + 0, 3539, 3525, + 0, 3631, 3267, + 0, 3731, 0, + 0, 3837, 0, + 0, 3951, 0, + 0, 4067, 0, + 3487, 3037, 3899, + 3487, 3037, 3899, + 3485, 3037, 3899, + 3485, 3037, 3899, + 3485, 3037, 3899, + 3485, 3037, 3899, + 3485, 3039, 3899, + 3483, 3039, 3899, + 3483, 3041, 3899, + 3481, 3043, 3899, + 3479, 3045, 3897, + 3477, 3047, 3897, + 3473, 3051, 3895, + 3467, 3057, 3895, + 3461, 3063, 3893, + 3451, 3071, 3889, + 3439, 3083, 3885, + 3423, 3099, 3881, + 3399, 3117, 3875, + 3365, 3143, 3865, + 3315, 3173, 3853, + 3237, 3211, 3835, + 3109, 3259, 3813, + 2849, 3315, 3779, + 0, 3379, 3729, + 0, 3455, 3653, + 0, 3539, 3525, + 0, 3631, 3267, + 0, 3731, 0, + 0, 3837, 0, + 0, 3951, 0, + 0, 4067, 0, + 3487, 3037, 3899, + 3487, 3037, 3899, + 3487, 3037, 3899, + 3485, 3037, 3899, + 3485, 3037, 3899, + 3485, 3037, 3899, + 3485, 3039, 3899, + 3483, 3039, 3899, + 3483, 3041, 3899, + 3481, 3043, 3899, + 3479, 3045, 3897, + 3477, 3047, 3897, + 3473, 3051, 3895, + 3467, 3057, 3895, + 3461, 3063, 3893, + 3453, 3071, 3889, + 3439, 3083, 3885, + 3423, 3099, 3881, + 3399, 3117, 3875, + 3365, 3143, 3865, + 3315, 3173, 3853, + 3239, 3211, 3837, + 3109, 3259, 3813, + 2849, 3315, 3779, + 0, 3379, 3729, + 0, 3455, 3653, + 0, 3539, 3525, + 0, 3631, 3267, + 0, 3731, 0, + 0, 3837, 0, + 0, 3951, 0, + 0, 4067, 0, + 3487, 3037, 3901, + 3487, 3037, 3899, + 3487, 3037, 3899, + 3487, 3037, 3899, + 3485, 3037, 3899, + 3485, 3037, 3899, + 3485, 3039, 3899, + 3485, 3039, 3899, + 3483, 3041, 3899, + 3481, 3043, 3899, + 3479, 3045, 3897, + 3477, 3047, 3897, + 3473, 3051, 3895, + 3469, 3057, 3895, + 3461, 3063, 3893, + 3453, 3071, 3889, + 3441, 3083, 3885, + 3423, 3099, 3881, + 3399, 3117, 3875, + 3365, 3143, 3865, + 3315, 3173, 3853, + 3239, 3211, 3837, + 3111, 3259, 3813, + 2851, 3315, 3779, + 0, 3379, 3729, + 0, 3455, 3653, + 0, 3539, 3525, + 0, 3631, 3267, + 0, 3731, 0, + 0, 3837, 0, + 0, 3951, 0, + 0, 4067, 0, + 3487, 3037, 3901, + 3487, 3037, 3901, + 3487, 3037, 3901, + 3487, 3037, 3899, + 3487, 3037, 3899, + 3485, 3037, 3899, + 3485, 3039, 3899, + 3485, 3039, 3899, + 3483, 3041, 3899, + 3481, 3043, 3899, + 3479, 3045, 3897, + 3477, 3047, 3897, + 3473, 3051, 3895, + 3469, 3057, 3895, + 3463, 3063, 3893, + 3453, 3071, 3889, + 3441, 3083, 3887, + 3423, 3099, 3881, + 3399, 3117, 3875, + 3365, 3143, 3865, + 3315, 3173, 3853, + 3239, 3211, 3837, + 3111, 3259, 3813, + 2853, 3315, 3779, + 0, 3379, 3729, + 0, 3455, 3653, + 0, 3539, 3525, + 0, 3631, 3267, + 0, 3731, 0, + 0, 3837, 0, + 0, 3951, 0, + 0, 4067, 0, + 3487, 3037, 3901, + 3487, 3037, 3901, + 3487, 3037, 3901, + 3487, 3037, 3901, + 3487, 3037, 3901, + 3487, 3037, 3899, + 3485, 3039, 3899, + 3485, 3039, 3899, + 3483, 3041, 3899, + 3483, 3043, 3899, + 3481, 3045, 3899, + 3477, 3047, 3897, + 3475, 3051, 3897, + 3469, 3057, 3895, + 3463, 3063, 3893, + 3453, 3071, 3889, + 3441, 3083, 3887, + 3425, 3099, 3881, + 3401, 3117, 3875, + 3367, 3143, 3865, + 3317, 3173, 3853, + 3241, 3211, 3837, + 3113, 3259, 3813, + 2855, 3315, 3779, + 0, 3379, 3729, + 0, 3455, 3653, + 0, 3539, 3525, + 0, 3631, 3269, + 0, 3731, 0, + 0, 3837, 0, + 0, 3951, 0, + 0, 4067, 0, + 3489, 3035, 3901, + 3489, 3037, 3901, + 3489, 3037, 3901, + 3489, 3037, 3901, + 3487, 3037, 3901, + 3487, 3037, 3901, + 3487, 3039, 3899, + 3485, 3039, 3899, + 3485, 3041, 3899, + 3483, 3041, 3899, + 3481, 3045, 3899, + 3479, 3047, 3897, + 3475, 3051, 3897, + 3471, 3057, 3895, + 3463, 3063, 3893, + 3455, 3071, 3891, + 3443, 3083, 3887, + 3425, 3099, 3881, + 3401, 3117, 3875, + 3367, 3143, 3867, + 3317, 3173, 3853, + 3241, 3211, 3837, + 3115, 3259, 3813, + 2857, 3315, 3779, + 0, 3379, 3729, + 0, 3455, 3653, + 0, 3539, 3527, + 0, 3631, 3269, + 0, 3731, 0, + 0, 3837, 0, + 0, 3949, 0, + 0, 4067, 0, + 3489, 3035, 3901, + 3489, 3035, 3901, + 3489, 3037, 3901, + 3489, 3037, 3901, + 3489, 3037, 3901, + 3489, 3037, 3901, + 3487, 3039, 3901, + 3487, 3039, 3899, + 3485, 3041, 3899, + 3485, 3041, 3899, + 3483, 3045, 3899, + 3479, 3047, 3897, + 3477, 3051, 3897, + 3471, 3055, 3895, + 3465, 3063, 3893, + 3455, 3071, 3891, + 3443, 3083, 3887, + 3427, 3099, 3881, + 3403, 3117, 3875, + 3369, 3143, 3867, + 3319, 3173, 3855, + 3243, 3211, 3837, + 3117, 3259, 3813, + 2861, 3315, 3779, + 0, 3379, 3729, + 0, 3455, 3653, + 0, 3539, 3527, + 0, 3631, 3271, + 0, 3731, 0, + 0, 3837, 0, + 0, 3949, 0, + 0, 4067, 0, + 3491, 3035, 3901, + 3491, 3035, 3901, + 3491, 3035, 3901, + 3491, 3037, 3901, + 3491, 3037, 3901, + 3489, 3037, 3901, + 3489, 3037, 3901, + 3489, 3039, 3901, + 3487, 3041, 3899, + 3485, 3041, 3899, + 3483, 3043, 3899, + 3481, 3047, 3899, + 3477, 3051, 3897, + 3473, 3055, 3895, + 3467, 3063, 3893, + 3457, 3071, 3891, + 3445, 3083, 3887, + 3427, 3097, 3883, + 3405, 3117, 3875, + 3371, 3141, 3867, + 3321, 3173, 3855, + 3245, 3211, 3837, + 3121, 3259, 3813, + 2867, 3315, 3779, + 504, 3379, 3731, + 0, 3455, 3655, + 0, 3539, 3527, + 0, 3631, 3271, + 0, 3731, 0, + 0, 3837, 0, + 0, 3949, 0, + 0, 4067, 0, + 3493, 3035, 3901, + 3493, 3035, 3901, + 3493, 3035, 3901, + 3493, 3037, 3901, + 3493, 3037, 3901, + 3491, 3037, 3901, + 3491, 3037, 3901, + 3491, 3039, 3901, + 3489, 3039, 3901, + 3487, 3041, 3901, + 3485, 3043, 3899, + 3483, 3047, 3899, + 3479, 3051, 3897, + 3475, 3055, 3895, + 3469, 3063, 3893, + 3459, 3071, 3891, + 3447, 3083, 3887, + 3431, 3097, 3883, + 3407, 3117, 3877, + 3373, 3141, 3867, + 3325, 3173, 3855, + 3249, 3211, 3839, + 3125, 3259, 3815, + 2875, 3313, 3781, + 1125, 3379, 3731, + 0, 3455, 3655, + 0, 3539, 3529, + 0, 3631, 3273, + 0, 3731, 0, + 0, 3837, 0, + 0, 3949, 0, + 0, 4067, 0, + 3495, 3035, 3903, + 3495, 3035, 3903, + 3495, 3035, 3903, + 3495, 3035, 3903, + 3495, 3037, 3903, + 3495, 3037, 3901, + 3493, 3037, 3901, + 3493, 3039, 3901, + 3491, 3039, 3901, + 3491, 3041, 3901, + 3489, 3043, 3901, + 3485, 3047, 3899, + 3481, 3051, 3899, + 3477, 3055, 3897, + 3471, 3061, 3895, + 3461, 3071, 3893, + 3449, 3083, 3889, + 3433, 3097, 3883, + 3409, 3117, 3877, + 3377, 3141, 3869, + 3327, 3173, 3855, + 3253, 3211, 3839, + 3129, 3257, 3815, + 2885, 3313, 3781, + 1440, 3379, 3733, + 0, 3455, 3657, + 0, 3539, 3531, + 0, 3631, 3277, + 0, 3731, 0, + 0, 3837, 0, + 0, 3949, 0, + 0, 4067, 0, + 3499, 3035, 3903, + 3499, 3035, 3903, + 3499, 3035, 3903, + 3499, 3035, 3903, + 3497, 3035, 3903, + 3497, 3037, 3903, + 3497, 3037, 3903, + 3495, 3037, 3903, + 3495, 3039, 3903, + 3493, 3041, 3901, + 3491, 3043, 3901, + 3489, 3045, 3901, + 3485, 3049, 3899, + 3481, 3055, 3897, + 3475, 3061, 3895, + 3465, 3071, 3893, + 3453, 3081, 3889, + 3437, 3097, 3885, + 3413, 3117, 3877, + 3381, 3141, 3869, + 3333, 3173, 3857, + 3259, 3211, 3839, + 3137, 3257, 3817, + 2897, 3313, 3783, + 1672, 3379, 3733, + 0, 3455, 3657, + 0, 3539, 3533, + 0, 3631, 3281, + 0, 3731, 1095, + 0, 3837, 0, + 0, 3949, 0, + 0, 4067, 0, + 3503, 3033, 3905, + 3503, 3035, 3905, + 3503, 3035, 3905, + 3503, 3035, 3905, + 3503, 3035, 3905, + 3501, 3035, 3905, + 3501, 3037, 3903, + 3501, 3037, 3903, + 3499, 3039, 3903, + 3497, 3041, 3903, + 3495, 3043, 3903, + 3493, 3045, 3901, + 3489, 3049, 3901, + 3485, 3055, 3899, + 3479, 3061, 3897, + 3471, 3069, 3895, + 3459, 3081, 3891, + 3441, 3097, 3885, + 3419, 3115, 3879, + 3387, 3141, 3871, + 3339, 3171, 3859, + 3267, 3211, 3841, + 3147, 3257, 3817, + 2913, 3313, 3785, + 1867, 3379, 3735, + 0, 3453, 3661, + 0, 3537, 3535, + 0, 3631, 3285, + 0, 3731, 1469, + 0, 3837, 0, + 0, 3949, 0, + 0, 4067, 0, + 3509, 3033, 3907, + 3509, 3033, 3907, + 3509, 3033, 3905, + 3509, 3033, 3905, + 3507, 3035, 3905, + 3507, 3035, 3905, + 3507, 3035, 3905, + 3507, 3037, 3905, + 3505, 3037, 3905, + 3503, 3039, 3905, + 3501, 3041, 3903, + 3499, 3045, 3903, + 3495, 3049, 3901, + 3491, 3053, 3901, + 3485, 3061, 3899, + 3477, 3069, 3895, + 3465, 3081, 3893, + 3449, 3095, 3887, + 3425, 3115, 3881, + 3393, 3139, 3873, + 3347, 3171, 3859, + 3275, 3209, 3843, + 3159, 3257, 3819, + 2933, 3313, 3787, + 2041, 3379, 3737, + 0, 3453, 3663, + 0, 3537, 3539, + 0, 3631, 3291, + 0, 3731, 1724, + 0, 3837, 0, + 0, 3949, 0, + 0, 4067, 0, + 3517, 3033, 3909, + 3517, 3033, 3909, + 3517, 3033, 3909, + 3515, 3033, 3909, + 3515, 3033, 3907, + 3515, 3033, 3907, + 3515, 3035, 3907, + 3513, 3035, 3907, + 3513, 3037, 3907, + 3511, 3039, 3907, + 3509, 3041, 3905, + 3507, 3043, 3905, + 3503, 3047, 3905, + 3499, 3053, 3903, + 3493, 3059, 3901, + 3485, 3067, 3897, + 3473, 3079, 3895, + 3457, 3095, 3889, + 3435, 3115, 3883, + 3403, 3139, 3875, + 3357, 3171, 3863, + 3289, 3209, 3845, + 3175, 3257, 3823, + 2959, 3313, 3789, + 2203, 3377, 3741, + 0, 3453, 3667, + 0, 3537, 3543, + 0, 3631, 3299, + 0, 3731, 1929, + 0, 3837, 0, + 0, 3949, 0, + 0, 4067, 0, + 3527, 3031, 3911, + 3527, 3031, 3911, + 3527, 3031, 3911, + 3525, 3031, 3911, + 3525, 3031, 3911, + 3525, 3033, 3911, + 3525, 3033, 3911, + 3523, 3033, 3911, + 3523, 3035, 3909, + 3521, 3037, 3909, + 3519, 3039, 3909, + 3517, 3041, 3907, + 3513, 3045, 3907, + 3509, 3051, 3905, + 3503, 3057, 3903, + 3495, 3067, 3901, + 3483, 3079, 3897, + 3469, 3093, 3893, + 3447, 3113, 3887, + 3417, 3137, 3877, + 3371, 3169, 3865, + 3305, 3207, 3849, + 3197, 3255, 3825, + 2993, 3311, 3793, + 2355, 3377, 3745, + 0, 3453, 3671, + 0, 3537, 3549, + 0, 3629, 3311, + 0, 3731, 2109, + 0, 3837, 0, + 0, 3949, 0, + 0, 4065, 0, + 3539, 3029, 3915, + 3539, 3029, 3915, + 3539, 3029, 3915, + 3539, 3029, 3915, + 3539, 3029, 3915, + 3539, 3031, 3915, + 3537, 3031, 3915, + 3537, 3031, 3913, + 3535, 3033, 3913, + 3535, 3035, 3913, + 3533, 3037, 3913, + 3531, 3039, 3911, + 3527, 3043, 3911, + 3523, 3049, 3909, + 3517, 3055, 3907, + 3509, 3065, 3905, + 3499, 3077, 3901, + 3483, 3091, 3897, + 3463, 3111, 3891, + 3433, 3137, 3881, + 3389, 3167, 3869, + 3325, 3207, 3853, + 3223, 3253, 3831, + 3033, 3311, 3797, + 2501, 3377, 3751, + 0, 3451, 3677, + 0, 3537, 3559, + 0, 3629, 3325, + 0, 3729, 2275, + 0, 3837, 0, + 0, 3949, 0, + 0, 4065, 0, + 3557, 3025, 3919, + 3557, 3027, 3919, + 3555, 3027, 3919, + 3555, 3027, 3919, + 3555, 3027, 3919, + 3555, 3027, 3919, + 3555, 3029, 3919, + 3553, 3029, 3919, + 3553, 3031, 3919, + 3551, 3033, 3919, + 3549, 3035, 3917, + 3547, 3037, 3917, + 3545, 3041, 3915, + 3541, 3047, 3915, + 3535, 3053, 3913, + 3527, 3063, 3909, + 3517, 3075, 3907, + 3501, 3089, 3901, + 3483, 3109, 3895, + 3453, 3135, 3887, + 3413, 3165, 3875, + 3353, 3205, 3859, + 3255, 3253, 3837, + 3083, 3309, 3805, + 2645, 3375, 3757, + 0, 3451, 3685, + 0, 3535, 3569, + 0, 3629, 3343, + 0, 3729, 2431, + 0, 3837, 0, + 0, 3949, 0, + 0, 4065, 0, + 3577, 3023, 3927, + 3577, 3023, 3927, + 3577, 3023, 3927, + 3577, 3023, 3927, + 3577, 3023, 3927, + 3577, 3023, 3927, + 3577, 3025, 3925, + 3575, 3025, 3925, + 3575, 3027, 3925, + 3573, 3029, 3925, + 3571, 3031, 3925, + 3569, 3033, 3923, + 3567, 3037, 3923, + 3563, 3043, 3921, + 3557, 3049, 3919, + 3549, 3059, 3917, + 3539, 3071, 3913, + 3527, 3087, 3909, + 3507, 3107, 3903, + 3481, 3131, 3893, + 3443, 3163, 3883, + 3385, 3203, 3867, + 3297, 3251, 3845, + 3141, 3307, 3813, + 2785, 3373, 3767, + 0, 3449, 3697, + 0, 3535, 3583, + 0, 3627, 3365, + 0, 3729, 2579, + 0, 3835, 0, + 0, 3949, 0, + 0, 4065, 0, + 3605, 3017, 3935, + 3605, 3017, 3935, + 3605, 3017, 3935, + 3605, 3019, 3935, + 3605, 3019, 3935, + 3603, 3019, 3935, + 3603, 3019, 3935, + 3603, 3021, 3935, + 3601, 3023, 3933, + 3601, 3023, 3933, + 3599, 3027, 3933, + 3597, 3029, 3933, + 3595, 3033, 3931, + 3591, 3039, 3929, + 3585, 3045, 3927, + 3579, 3055, 3925, + 3569, 3067, 3923, + 3557, 3083, 3917, + 3539, 3103, 3911, + 3515, 3127, 3903, + 3479, 3159, 3891, + 3427, 3199, 3877, + 3347, 3247, 3855, + 3209, 3305, 3823, + 2923, 3371, 3779, + 0, 3447, 3711, + 0, 3533, 3601, + 0, 3627, 3395, + 0, 3727, 2723, + 0, 3835, 0, + 0, 3947, 0, + 0, 4065, 0, + 3639, 3011, 3947, + 3639, 3011, 3947, + 3639, 3011, 3947, + 3639, 3011, 3947, + 3639, 3013, 3947, + 3639, 3013, 3947, + 3637, 3013, 3945, + 3637, 3015, 3945, + 3637, 3015, 3945, + 3635, 3017, 3945, + 3633, 3019, 3945, + 3631, 3023, 3943, + 3629, 3027, 3943, + 3625, 3033, 3941, + 3621, 3039, 3939, + 3615, 3049, 3937, + 3607, 3061, 3933, + 3595, 3077, 3929, + 3579, 3097, 3923, + 3555, 3123, 3915, + 3523, 3155, 3905, + 3477, 3195, 3889, + 3405, 3243, 3869, + 3287, 3301, 3839, + 3059, 3369, 3795, + 2121, 3445, 3729, + 0, 3531, 3625, + 0, 3625, 3431, + 0, 3727, 2865, + 0, 3833, 0, + 0, 3947, 0, + 0, 4065, 0, + 3681, 3003, 3961, + 3681, 3003, 3961, + 3681, 3003, 3961, + 3681, 3003, 3961, + 3681, 3003, 3961, + 3681, 3003, 3961, + 3679, 3005, 3961, + 3679, 3005, 3961, + 3679, 3007, 3961, + 3677, 3009, 3959, + 3677, 3011, 3959, + 3675, 3015, 3959, + 3673, 3019, 3957, + 3669, 3023, 3957, + 3665, 3031, 3955, + 3659, 3041, 3953, + 3651, 3053, 3949, + 3641, 3069, 3945, + 3625, 3089, 3939, + 3605, 3115, 3931, + 3577, 3149, 3921, + 3535, 3189, 3905, + 3473, 3237, 3885, + 3373, 3297, 3857, + 3195, 3365, 3815, + 2719, 3441, 3753, + 0, 3527, 3655, + 0, 3623, 3475, + 0, 3725, 3003, + 0, 3833, 0, + 0, 3945, 0, + 0, 4063, 0, + 3731, 2989, 3981, + 3731, 2991, 3981, + 3731, 2991, 3981, + 3731, 2991, 3981, + 3731, 2991, 3979, + 3731, 2991, 3979, + 3731, 2993, 3979, + 3731, 2993, 3979, + 3729, 2995, 3979, + 3729, 2997, 3979, + 3727, 2999, 3979, + 3725, 3003, 3977, + 3723, 3007, 3977, + 3721, 3013, 3975, + 3717, 3019, 3973, + 3713, 3029, 3971, + 3705, 3041, 3969, + 3695, 3059, 3965, + 3683, 3079, 3959, + 3665, 3107, 3951, + 3639, 3139, 3941, + 3603, 3181, 3927, + 3551, 3231, 3907, + 3469, 3289, 3881, + 3329, 3359, 3841, + 3029, 3437, 3783, + 0, 3523, 3691, + 0, 3619, 3529, + 0, 3721, 3139, + 0, 3831, 0, + 0, 3945, 0, + 0, 4061, 0, + 3791, 2973, 4005, + 3791, 2973, 4005, + 3791, 2973, 4005, + 3791, 2973, 4005, + 3791, 2975, 4005, + 3791, 2975, 4005, + 3791, 2975, 4003, + 3791, 2977, 4003, + 3789, 2979, 4003, + 3789, 2981, 4003, + 3787, 2983, 4003, + 3787, 2985, 4001, + 3785, 2991, 4001, + 3783, 2997, 3999, + 3779, 3003, 3999, + 3775, 3013, 3997, + 3769, 3027, 3993, + 3761, 3043, 3989, + 3749, 3065, 3985, + 3733, 3093, 3977, + 3713, 3127, 3967, + 3681, 3169, 3955, + 3637, 3221, 3937, + 3571, 3281, 3911, + 3463, 3351, 3873, + 3261, 3431, 3819, + 2631, 3519, 3735, + 0, 3615, 3591, + 0, 3719, 3275, + 0, 3827, 0, + 0, 3943, 0, + 0, 4061, 0, + 3861, 2949, 4035, + 3861, 2949, 4035, + 3861, 2951, 4035, + 3861, 2951, 4035, + 3861, 2951, 4035, + 3861, 2951, 4035, + 3861, 2953, 4035, + 3861, 2953, 4035, + 3859, 2955, 4035, + 3859, 2957, 4033, + 3859, 2959, 4033, + 3857, 2963, 4033, + 3855, 2967, 4031, + 3853, 2973, 4031, + 3851, 2981, 4029, + 3847, 2993, 4027, + 3841, 3007, 4025, + 3835, 3023, 4021, + 3825, 3047, 4017, + 3811, 3075, 4009, + 3793, 3111, 4001, + 3769, 3155, 3989, + 3733, 3207, 3971, + 3679, 3269, 3947, + 3595, 3341, 3915, + 3455, 3423, 3865, + 3149, 3511, 3789, + 0, 3609, 3663, + 0, 3713, 3411, + 0, 3825, 876, + 0, 3939, 0, + 0, 4059, 0, + 3941, 2917, 4073, + 3941, 2917, 4073, + 3941, 2917, 4073, + 3941, 2917, 4073, + 3939, 2917, 4073, + 3939, 2919, 4073, + 3939, 2919, 4073, + 3939, 2921, 4073, + 3939, 2921, 4071, + 3939, 2925, 4071, + 3937, 2927, 4071, + 3937, 2931, 4071, + 3935, 2935, 4069, + 3933, 2943, 4069, + 3931, 2951, 4067, + 3927, 2963, 4065, + 3923, 2977, 4063, + 3917, 2995, 4059, + 3909, 3019, 4055, + 3899, 3051, 4049, + 3885, 3087, 4041, + 3863, 3133, 4031, + 3835, 3189, 4015, + 3793, 3253, 3993, + 3729, 3327, 3963, + 3627, 3411, 3919, + 3443, 3503, 3853, + 2939, 3601, 3745, + 0, 3707, 3545, + 0, 3819, 2929, + 0, 3935, 0, + 0, 4055, 0, + 4029, 2867, 4095, + 4029, 2867, 4095, + 4029, 2867, 4095, + 4029, 2869, 4095, + 4027, 2869, 4095, + 4027, 2869, 4095, + 4027, 2871, 4095, + 4027, 2871, 4095, + 4027, 2873, 4095, + 4027, 2877, 4095, + 4025, 2879, 4095, + 4025, 2883, 4095, + 4025, 2889, 4095, + 4023, 2897, 4095, + 4021, 2905, 4095, + 4019, 2919, 4095, + 4015, 2935, 4095, + 4009, 2955, 4095, + 4003, 2981, 4095, + 3995, 3015, 4095, + 3983, 3055, 4091, + 3965, 3105, 4081, + 3943, 3163, 4067, + 3909, 3231, 4047, + 3861, 3309, 4021, + 3789, 3395, 3983, + 3667, 3489, 3925, + 3427, 3591, 3835, + 2235, 3699, 3677, + 0, 3813, 3313, + 0, 3931, 0, + 0, 4051, 0, + 4095, 2793, 4095, + 4095, 2793, 4095, + 4095, 2793, 4095, + 4095, 2793, 4095, + 4095, 2795, 4095, + 4095, 2795, 4095, + 4095, 2797, 4095, + 4095, 2797, 4095, + 4095, 2799, 4095, + 4095, 2803, 4095, + 4095, 2807, 4095, + 4095, 2811, 4095, + 4095, 2817, 4095, + 4095, 2827, 4095, + 4095, 2837, 4095, + 4095, 2851, 4095, + 4095, 2871, 4095, + 4095, 2895, 4095, + 4095, 2925, 4095, + 4095, 2961, 4095, + 4087, 3007, 4095, + 4075, 3061, 4095, + 4057, 3125, 4095, + 4031, 3199, 4095, + 3995, 3281, 4089, + 3941, 3373, 4055, + 3857, 3471, 4007, + 3715, 3577, 3933, + 3407, 3689, 3811, + 0, 3805, 3569, + 0, 3925, 2301, + 0, 4047, 0, + 4095, 2667, 4095, + 4095, 2669, 4095, + 4095, 2669, 4095, + 4095, 2669, 4095, + 4095, 2671, 4095, + 4095, 2671, 4095, + 4095, 2673, 4095, + 4095, 2675, 4095, + 4095, 2677, 4095, + 4095, 2681, 4095, + 4095, 2687, 4095, + 4095, 2693, 4095, + 4095, 2701, 4095, + 4095, 2711, 4095, + 4095, 2727, 4095, + 4095, 2745, 4095, + 4095, 2767, 4095, + 4095, 2797, 4095, + 4095, 2835, 4095, + 4095, 2879, 4095, + 4095, 2933, 4095, + 4095, 2997, 4095, + 4095, 3069, 4095, + 4095, 3151, 4095, + 4095, 3243, 4095, + 4087, 3341, 4095, + 4029, 3447, 4095, + 3935, 3557, 4039, + 3771, 3673, 3945, + 3375, 3793, 3777, + 0, 3915, 3367, + 0, 4039, 0, + 4095, 2419, 4095, + 4095, 2421, 4095, + 4095, 2421, 4095, + 4095, 2421, 4095, + 4095, 2423, 4095, + 4095, 2425, 4095, + 4095, 2429, 4095, + 4095, 2431, 4095, + 4095, 2437, 4095, + 4095, 2443, 4095, + 4095, 2451, 4095, + 4095, 2461, 4095, + 4095, 2475, 4095, + 4095, 2493, 4095, + 4095, 2515, 4095, + 4095, 2545, 4095, + 4095, 2581, 4095, + 4095, 2625, 4095, + 4095, 2677, 4095, + 4095, 2739, 4095, + 4095, 2811, 4095, + 4095, 2893, 4095, + 4095, 2983, 4095, + 4095, 3081, 4095, + 4095, 3185, 4095, + 4095, 3295, 4095, + 4095, 3411, 4095, + 4095, 3529, 4095, + 4023, 3651, 4077, + 3839, 3777, 3959, + 3331, 3903, 3727, + 0, 4031, 2729, + 4095, 771, 4095, + 4095, 795, 4095, + 4095, 824, 4095, + 4095, 860, 4095, + 4095, 904, 4095, + 4095, 957, 4095, + 4095, 1020, 4095, + 4095, 1092, 4095, + 4095, 1173, 4095, + 4095, 1263, 4095, + 4095, 1361, 4095, + 4095, 1466, 4095, + 4095, 1577, 4095, + 4095, 1692, 4095, + 4095, 1811, 4095, + 4095, 1934, 4095, + 4095, 2059, 4095, + 4095, 2185, 4095, + 4095, 2313, 4095, + 4095, 2441, 4095, + 4095, 2571, 4095, + 4095, 2701, 4095, + 4095, 2831, 4095, + 4095, 2963, 4095, + 4095, 3095, 4095, + 4095, 3225, 4095, + 4095, 3357, 4095, + 4095, 3489, 4095, + 4095, 3621, 4095, + 4095, 3753, 4095, + 3915, 3885, 3977, + 3265, 4017, 3649, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 0, 4095, + 4095, 1343, 4095, + 4095, 2153, 4095, + 4095, 2493, 4095, + 4095, 2735, 4095, + 4095, 2935, 4095, + 4095, 3113, 4095, + 4095, 3275, 4095, + 4095, 3429, 4095, + 4095, 3577, 4095, + 4095, 3721, 4095, + 4095, 3861, 4095, + 3999, 3999, 3999 +] + } +} diff --git a/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/Test_Extreme_Grade/test-extreme-grade_inv-Log2-48nits_32_LUT.exr b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/Test_Extreme_Grade/test-extreme-grade_inv-Log2-48nits_32_LUT.exr new file mode 100644 index 0000000000..bf06ce0bed --- /dev/null +++ b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/Test_Extreme_Grade/test-extreme-grade_inv-Log2-48nits_32_LUT.exr @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ad9a024034bfc356f7c6fd4c19d617a7321306c68b7f824fb44b73ad57613244 +size 197689 diff --git a/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/Test_Grade/Shot_post_test-grade.exr b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/Test_Grade/Shot_post_test-grade.exr new file mode 100644 index 0000000000..49e0460826 --- /dev/null +++ b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/Test_Grade/Shot_post_test-grade.exr @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9ff499c054a259a3cd389b613382066f258287215f61da56115b3e958733dbe6 +size 31227639 diff --git a/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/Test_Grade/Test-Grade.nk b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/Test_Grade/Test-Grade.nk new file mode 100644 index 0000000000..9643c9edbc --- /dev/null +++ b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/Test_Grade/Test-Grade.nk @@ -0,0 +1,225 @@ +#! C:/Program Files/Nuke13.0v3/nuke-13.0.3.dll -nx +version 13.0 v3 +define_window_layout_xml { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +} +Root { + inputs 0 + name C:/Depot/o3de/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/Test_Grade/Test-Grade.nk + project_directory "\"C:/Depot/o3de-engine/Gems/AtomLyIntegration/CommonFeatures/Tools/ColorGrading/TestData/Nuke/" + format "2048 1556 0 0 2048 1556 1 2K_Super_35(full-ap)" + proxy_type scale + proxy_format "1024 778 0 0 1024 778 1 1K_Super_35(full-ap)" + colorManagement OCIO + OCIO_config aces_1.0.3 + defaultViewerLUT "OCIO LUTs" + workingSpaceLUT scene_linear + monitorLut ACES/Rec.709 + monitorOutLUT "sRGB (ACES)" + int8Lut matte_paint + int16Lut texture_paint + logLut compositing_log + floatLut scene_linear +} +Read { + inputs 0 + file_type exr + file C:/Depot/o3de/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/LUTs/linear_32_LUT.exr + format "1024 32 0 0 1024 32 1 " + origset true + colorspace data + raw true + name Read_Linear_LUT_32 + xpos -846 + ypos 10 +} +set N16319800 [stack 0] +Viewer { + frame 1 + frame_range 1-100 + viewerProcess "sRGB (ACES)" + name Viewer1 + xpos -846 + ypos 135 +} +push $N16319800 +OCIOFileTransform { + file C:/Depot/o3de-engine/Tools/ColorGrading/OpenColorIO-Configs/aces_1.0.3/luts/Log2_48_nits_Shaper_to_linear.spi1d + working_space rendering + name Log2_48_nits_Shaper_to_linear + xpos -710 + ypos 46 +} +set N16319000 [stack 0] +Viewer { + frame 1 + frame_range 1-100 + viewerProcess "sRGB (ACES)" + name Viewer2 + xpos -710 + ypos 137 +} +push $N16319000 +Transform { + center {1024 778} + name Transform_Position_LUT + xpos -579 + ypos 3 +} +set N16318c00 [stack 0] +Viewer { + frame 1 + frame_range 1-100 + viewerProcess "sRGB (ACES)" + name Viewer3 + xpos -579 + ypos 135 +} +push $N16318c00 +Read { + inputs 0 + file_type exr + file C:/Depot/o3de/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/displaymapperpassthrough.exr + format "2802 1854 0 0 2802 1854 1 " + origset true + name Read_DisplayMapperPassthrough + xpos -580 + ypos -146 +} +ZMerge { + inputs 2 + name ZMerge_Combine + xpos -413 + ypos -83 +} +set N16297c00 [stack 0] +Viewer { + frame 1 + frame_range 1-100 + viewerProcess "sRGB (ACES)" + name Viewer4 + xpos -413 + ypos 128 +} +push $N16297c00 +HueShift { + ingray {0.18 0.18 0.18} + outgray {0.18 0.18 0.18} + saturation 1.26 + color {0.12 0.12 0.12} + color_saturation 0.78 + hue_rotation -150 + brightness 0.74 + name HueShift1 + xpos -256 + ypos -83 +} +set N16297800 [stack 0] +Crop { + box {0 0 1024 32} + reformat true + crop false + name Crop1 + xpos -86 + ypos 32 +} +set N16297400 [stack 0] +Viewer { + frame 1 + frame_range 1-100 + viewerProcess "sRGB (ACES)" + name Viewer6 + xpos -86 + ypos 134 +} +push $N16297800 +Write { + file C:/Depot/o3de/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/Test_Grade/Shot_post_test-grade.exr + colorspace compositing_linear + file_type exr + write_ACES_compliant_EXR true + datatype "32 bit float" + first_part rgba + version 11 + name Write_Shot_Grade_Comp + xpos 353 + ypos -95 +} +Viewer { + frame 1 + frame_range 1-100 + viewerProcess "sRGB (ACES)" + name Viewer8 + xpos 353 + ypos 135 +} +push $N16297400 +OCIOFileTransform { + file C:/Depot/o3de-engine/Tools/ColorGrading/OpenColorIO-Configs/aces_1.0.3/luts/Log2_48_nits_Shaper_to_linear.spi1d + direction inverse + working_space data + name invLog2_48_nits_Shaper_to_linear + xpos 74 + ypos -14 +} +Write { + file C:/Depot/o3de/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/Test_Grade/test-grade_inv-Log2-48nits_32_LUT.exr + colorspace data + file_type exr + datatype "32 bit float" + first_part rgba + version 11 + name Write_RAW_LUT + xpos 242 + ypos 20 +} +Viewer { + frame 1 + frame_range 1-100 + viewerProcess "sRGB (ACES)" + name Viewer7 + xpos 242 + ypos 135 +} +push $N16297800 +Viewer { + frame 1 + frame_range 1-100 + viewerProcess "sRGB (ACES)" + name Viewer5 + xpos -256 + ypos 130 +} diff --git a/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/Test_Grade/Test-Grade.nk~ b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/Test_Grade/Test-Grade.nk~ new file mode 100644 index 0000000000..084ba1495d --- /dev/null +++ b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/Test_Grade/Test-Grade.nk~ @@ -0,0 +1,227 @@ +#! C:/Program Files/Nuke13.0v3/nuke-13.0.3.dll -nx +version 13.0 v3 +define_window_layout_xml { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +} +Root { + inputs 0 + name C:/Depot/o3de/Gems/Atom/Feature/Common/Assets/ColorGrading/TestData/Nuke/HDR/Test_Grade/Test-Grade.nk + project_directory "\"C:/Depot/o3de-engine/Gems/AtomLyIntegration/CommonFeatures/Tools/ColorGrading/TestData/Nuke/" + format "2048 1556 0 0 2048 1556 1 2K_Super_35(full-ap)" + proxy_type scale + proxy_format "1024 778 0 0 1024 778 1 1K_Super_35(full-ap)" + colorManagement OCIO + OCIO_config aces_1.0.3 + defaultViewerLUT "OCIO LUTs" + workingSpaceLUT scene_linear + monitorLut ACES/Rec.709 + monitorOutLUT "sRGB (ACES)" + int8Lut matte_paint + int16Lut texture_paint + logLut compositing_log + floatLut scene_linear +} +Read { + inputs 0 + file_type exr + file C:/Depot/o3de/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/LUTs/linear_32_LUT.exr + format "1024 32 0 0 1024 32 1 " + origset true + colorspace data + raw true + name Read_Linear_LUT_32 + xpos -846 + ypos 10 +} +set N3bfa9800 [stack 0] +Viewer { + frame 1 + frame_range 1-100 + viewerProcess "sRGB (ACES)" + name Viewer1 + xpos -846 + ypos 135 +} +push $N3bfa9800 +OCIOFileTransform { + file C:/Depot/o3de-engine/Tools/ColorGrading/OpenColorIO-Configs/aces_1.0.3/luts/Log2_48_nits_Shaper_to_linear.spi1d + working_space rendering + name Log2_48_nits_Shaper_to_linear + xpos -710 + ypos 46 +} +set N3bfa9000 [stack 0] +Viewer { + frame 1 + frame_range 1-100 + viewerProcess "sRGB (ACES)" + name Viewer2 + xpos -710 + ypos 137 +} +push $N3bfa9000 +Transform { + center {1024 778} + name Transform_Position_LUT + xpos -579 + ypos 3 +} +set N3bfa8c00 [stack 0] +Viewer { + frame 1 + frame_range 1-100 + viewerProcess "sRGB (ACES)" + name Viewer3 + xpos -579 + ypos 135 +} +push $N3bfa8c00 +Read { + inputs 0 + file_type exr + file C:/Depot/o3de/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/displaymapperpassthrough.exr + format "2802 1854 0 0 2802 1854 1 " + origset true + name Read_DisplayMapperPassthrough + xpos -580 + ypos -146 +} +ZMerge { + inputs 2 + name ZMerge_Combine + xpos -413 + ypos -83 +} +set N3bf5bc00 [stack 0] +Viewer { + frame 1 + frame_range 1-100 + viewerProcess "sRGB (ACES)" + name Viewer4 + xpos -413 + ypos 128 +} +push $N3bf5bc00 +HueShift { + ingray {0.18 0.18 0.18} + outgray {0.18 0.18 0.18} + saturation 1.26 + color {0.12 0.12 0.12} + color_saturation 0.78 + hue_rotation -150 + brightness 0.74 + name HueShift1 + xpos -256 + ypos -83 +} +set N3bf5b800 [stack 0] +Viewer { + frame 1 + frame_range 1-100 + viewerProcess "sRGB (ACES)" + name Viewer5 + xpos -256 + ypos 130 +} +push $N3bf5b800 +Crop { + box {0 0 1024 32} + reformat true + crop false + name Crop1 + xpos -86 + ypos 32 +} +set N3bf5ac00 [stack 0] +Viewer { + frame 1 + frame_range 1-100 + viewerProcess "sRGB (ACES)" + name Viewer6 + xpos -86 + ypos 134 +} +push $N3bf5b800 +Write { + file C:/Depot/o3de/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/Test_Grade/Nuke_Shot_post_grade.exr + colorspace compositing_linear + file_type exr + write_ACES_compliant_EXR true + datatype "32 bit float" + first_part rgba + version 10 + name Write_Shot_Grade_Comp + selected true + xpos 353 + ypos -95 +} +Viewer { + frame 1 + frame_range 1-100 + viewerProcess "sRGB (ACES)" + name Viewer8 + xpos 353 + ypos 135 +} +push $N3bf5ac00 +OCIOFileTransform { + file C:/Depot/o3de-engine/Tools/ColorGrading/OpenColorIO-Configs/aces_1.0.3/luts/Log2_48_nits_Shaper_to_linear.spi1d + direction inverse + working_space data + name invLog2_48_nits_Shaper_to_linear + xpos 74 + ypos -14 +} +Write { + file C:/Depot/o3de/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/Test_Grade/test-grade_inv-Log2-48nits_32_LUT.exr + colorspace data + file_type exr + datatype "32 bit float" + first_part rgba + version 10 + name Write_RAW_LUT + xpos 242 + ypos 20 +} +Viewer { + frame 1 + frame_range 1-100 + viewerProcess "sRGB (ACES)" + name Viewer7 + xpos 242 + ypos 135 +} diff --git a/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/Test_Grade/test-grade_inv-Log2-48nits_32_LUT.3dl b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/Test_Grade/test-grade_inv-Log2-48nits_32_LUT.3dl new file mode 100644 index 0000000000..674cf4d9ce --- /dev/null +++ b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/Test_Grade/test-grade_inv-Log2-48nits_32_LUT.3dl @@ -0,0 +1,32769 @@ +0 33 66 99 132 165 198 231 264 297 330 363 396 429 462 495 528 561 594 627 660 693 726 759 792 825 858 891 924 957 990 1023 +0 0 0 +0 0 0 +0 15 0 +0 104 0 +0 201 0 +0 305 0 +0 415 0 +0 530 0 +0 649 0 +0 771 0 +0 895 0 +0 1022 0 +0 1149 0 +0 1278 0 +0 1408 0 +0 1538 0 +0 1668 0 +0 1799 0 +0 1931 0 +0 2062 0 +0 2194 0 +0 2326 0 +0 2457 0 +0 2589 0 +0 2721 0 +0 2853 0 +0 2985 0 +0 3117 0 +0 3249 0 +0 3381 0 +0 3514 0 +0 3646 0 +130 0 20 +28 0 0 +0 33 0 +0 119 0 +0 213 0 +0 315 0 +0 423 0 +0 536 0 +0 654 0 +0 775 0 +0 898 0 +0 1024 0 +0 1151 0 +0 1279 0 +0 1408 0 +0 1538 0 +0 1669 0 +0 1800 0 +0 1931 0 +0 2062 0 +0 2194 0 +0 2326 0 +0 2458 0 +0 2589 0 +0 2721 0 +0 2853 0 +0 2985 0 +0 3117 0 +0 3249 0 +0 3381 0 +0 3514 0 +0 3646 0 +342 0 170 +280 0 102 +183 56 0 +7 139 0 +0 229 0 +0 328 0 +0 433 0 +0 544 0 +0 660 0 +0 779 0 +0 902 0 +0 1026 0 +0 1153 0 +0 1281 0 +0 1410 0 +0 1539 0 +0 1670 0 +0 1800 0 +0 1931 0 +0 2063 0 +0 2194 0 +0 2326 0 +0 2458 0 +0 2589 0 +0 2721 0 +0 2853 0 +0 2985 0 +0 3117 0 +0 3249 0 +0 3381 0 +0 3514 0 +0 3646 0 +526 0 315 +486 18 266 +426 86 192 +331 163 68 +163 250 0 +0 344 0 +0 446 0 +0 555 0 +0 668 0 +0 785 0 +0 906 0 +0 1030 0 +0 1156 0 +0 1283 0 +0 1411 0 +0 1540 0 +0 1670 0 +0 1801 0 +0 1932 0 +0 2063 0 +0 2194 0 +0 2326 0 +0 2458 0 +0 2590 0 +0 2722 0 +0 2853 0 +0 2985 0 +0 3117 0 +0 3249 0 +0 3382 0 +0 3514 0 +0 3646 0 +693 8 457 +666 60 422 +626 123 370 +568 195 290 +475 276 155 +312 366 0 +0 463 0 +0 568 0 +0 678 0 +0 794 0 +0 913 0 +0 1035 0 +0 1159 0 +0 1285 0 +0 1413 0 +0 1542 0 +0 1672 0 +0 1802 0 +0 1932 0 +0 2064 0 +0 2195 0 +0 2326 0 +0 2458 0 +0 2590 0 +0 2722 0 +0 2854 0 +0 2985 0 +0 3117 0 +0 3249 0 +0 3382 0 +0 3514 0 +0 3646 0 +850 65 596 +831 112 570 +804 168 534 +765 233 479 +707 308 395 +616 393 250 +457 485 0 +82 585 0 +0 692 0 +0 804 0 +0 921 0 +0 1041 0 +0 1164 0 +0 1289 0 +0 1416 0 +0 1544 0 +0 1673 0 +0 1803 0 +0 1933 0 +0 2064 0 +0 2195 0 +0 2327 0 +0 2458 0 +0 2590 0 +0 2722 0 +0 2854 0 +0 2986 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +999 131 733 +986 172 714 +967 222 688 +940 280 650 +901 348 594 +844 426 505 +755 513 352 +598 608 3 +235 710 0 +0 818 0 +0 932 0 +0 1049 0 +0 1170 0 +0 1294 0 +0 1420 0 +0 1547 0 +0 1675 0 +0 1805 0 +0 1935 0 +0 2065 0 +0 2196 0 +0 2327 0 +0 2459 0 +0 2590 0 +0 2722 0 +0 2854 0 +0 2986 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +1144 207 869 +1134 242 855 +1121 285 836 +1102 336 809 +1075 397 770 +1037 468 712 +980 547 621 +892 636 461 +737 732 82 +382 836 0 +0 946 0 +0 1060 0 +0 1179 0 +0 1300 0 +0 1424 0 +0 1550 0 +0 1678 0 +0 1807 0 +0 1936 0 +0 2066 0 +0 2197 0 +0 2328 0 +0 2459 0 +0 2591 0 +0 2722 0 +0 2854 0 +0 2986 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +1286 293 1004 +1278 322 994 +1268 358 980 +1255 402 960 +1236 455 932 +1210 518 893 +1172 590 833 +1115 671 740 +1027 761 574 +874 859 170 +525 964 0 +0 1074 0 +0 1190 0 +0 1309 0 +0 1431 0 +0 1555 0 +0 1682 0 +0 1809 0 +0 1938 0 +0 2068 0 +0 2198 0 +0 2329 0 +0 2460 0 +0 2591 0 +0 2723 0 +0 2854 0 +0 2986 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +1424 386 1138 +1419 410 1131 +1412 440 1120 +1402 477 1106 +1389 523 1086 +1370 577 1058 +1343 641 1018 +1306 714 958 +1250 797 862 +1162 888 692 +1010 987 267 +665 1093 0 +0 1204 0 +0 1320 0 +0 1439 0 +0 1562 0 +0 1687 0 +0 1813 0 +0 1941 0 +0 2070 0 +0 2200 0 +0 2330 0 +0 2461 0 +0 2592 0 +0 2723 0 +0 2855 0 +0 2986 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +1562 487 1272 +1558 506 1266 +1552 531 1258 +1545 561 1248 +1535 599 1234 +1522 646 1213 +1503 701 1185 +1477 766 1144 +1439 840 1084 +1383 924 987 +1296 1016 813 +1145 1116 370 +802 1222 0 +0 1334 0 +0 1450 0 +0 1570 0 +0 1693 0 +0 1818 0 +0 1945 0 +0 2073 0 +0 2202 0 +0 2331 0 +0 2462 0 +0 2593 0 +0 2724 0 +0 2855 0 +0 2987 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +1697 595 1405 +1695 610 1401 +1691 629 1395 +1685 654 1387 +1678 685 1377 +1668 724 1362 +1655 771 1342 +1636 827 1314 +1610 893 1273 +1572 968 1211 +1517 1053 1113 +1430 1145 937 +1279 1246 479 +939 1352 0 +0 1465 0 +0 1581 0 +0 1701 0 +0 1824 0 +0 1950 0 +0 2076 0 +0 2204 0 +0 2334 0 +0 2463 0 +0 2594 0 +0 2725 0 +0 2856 0 +0 2987 0 +0 3119 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +1832 707 1538 +1830 719 1535 +1827 735 1531 +1823 755 1525 +1818 780 1517 +1811 811 1507 +1801 851 1492 +1788 898 1472 +1769 955 1443 +1743 1021 1402 +1705 1097 1340 +1650 1182 1241 +1563 1275 1062 +1412 1376 594 +1074 1483 0 +0 1596 0 +0 1712 0 +0 1833 0 +0 1956 0 +0 2081 0 +0 2208 0 +0 2336 0 +0 2466 0 +0 2595 0 +0 2726 0 +0 2857 0 +0 2988 0 +0 3119 0 +0 3251 0 +0 3383 0 +0 3514 0 +0 3646 0 +1966 824 1671 +1965 834 1668 +1963 846 1665 +1960 861 1661 +1956 881 1655 +1951 907 1647 +1943 939 1637 +1934 978 1622 +1920 1026 1602 +1902 1084 1573 +1875 1150 1531 +1838 1227 1469 +1782 1312 1370 +1696 1406 1190 +1545 1507 712 +1209 1614 0 +0 1727 0 +0 1844 0 +0 1964 0 +0 2088 0 +0 2213 0 +0 2340 0 +0 2468 0 +0 2597 0 +0 2727 0 +0 2858 0 +0 2989 0 +0 3120 0 +0 3251 0 +0 3383 0 +0 3515 0 +0 3646 0 +2100 945 1803 +2099 952 1802 +2097 961 1799 +2095 973 1796 +2092 989 1792 +2088 1009 1786 +2083 1035 1778 +2076 1067 1768 +2066 1107 1753 +2053 1156 1732 +2034 1213 1703 +2008 1280 1662 +1970 1357 1599 +1915 1442 1499 +1828 1536 1318 +1678 1638 834 +1342 1745 0 +0 1858 0 +0 1976 0 +0 2096 0 +0 2220 0 +0 2345 0 +0 2472 0 +0 2600 0 +0 2730 0 +0 2859 0 +0 2990 0 +0 3121 0 +0 3252 0 +0 3383 0 +0 3515 0 +0 3647 0 +2233 1068 1936 +2232 1074 1935 +2231 1081 1933 +2230 1090 1930 +2227 1102 1927 +2225 1118 1923 +2221 1139 1917 +2215 1164 1909 +2208 1197 1899 +2198 1237 1884 +2185 1286 1863 +2166 1343 1834 +2140 1411 1793 +2103 1488 1730 +2047 1573 1629 +1961 1668 1447 +1811 1769 958 +1476 1877 0 +0 1990 0 +0 2107 0 +0 2228 0 +0 2351 0 +0 2477 0 +0 2604 0 +0 2732 0 +0 2862 0 +0 2991 0 +0 3122 0 +0 3253 0 +0 3384 0 +0 3515 0 +0 3647 0 +2366 1194 2068 +2366 1198 2067 +2365 1203 2066 +2364 1210 2064 +2362 1220 2062 +2360 1232 2059 +2357 1248 2054 +2353 1268 2049 +2348 1294 2041 +2340 1327 2030 +2331 1367 2015 +2317 1416 1995 +2299 1474 1966 +2273 1542 1924 +2235 1619 1861 +2180 1705 1760 +2093 1799 1577 +1944 1901 1084 +1609 2009 0 +0 2122 0 +0 2239 0 +0 2360 0 +0 2483 0 +0 2609 0 +0 2736 0 +0 2864 0 +0 2994 0 +0 3124 0 +0 3254 0 +0 3385 0 +0 3516 0 +0 3648 0 +2499 1321 2200 +2499 1324 2200 +2498 1328 2199 +2497 1333 2197 +2496 1340 2196 +2494 1350 2193 +2492 1362 2190 +2489 1378 2186 +2485 1399 2180 +2480 1425 2172 +2473 1458 2161 +2463 1498 2147 +2450 1547 2126 +2431 1605 2097 +2405 1673 2055 +2367 1750 1992 +2312 1836 1891 +2226 1931 1708 +2076 2032 1211 +1742 2140 0 +0 2254 0 +0 2371 0 +0 2492 0 +0 2615 0 +0 2741 0 +0 2868 0 +0 2996 0 +0 3126 0 +0 3256 0 +0 3386 0 +0 3517 0 +0 3648 0 +2632 1449 2333 +2631 1451 2332 +2631 1454 2331 +2630 1458 2330 +2629 1464 2329 +2628 1471 2327 +2626 1481 2325 +2624 1493 2322 +2621 1509 2318 +2617 1530 2312 +2612 1556 2304 +2605 1589 2293 +2595 1629 2278 +2582 1678 2258 +2563 1736 2229 +2537 1804 2187 +2500 1881 2123 +2444 1968 2023 +2358 2062 1839 +2208 2164 1340 +1874 2272 0 +0 2385 0 +0 2503 0 +0 2624 0 +0 2747 0 +0 2873 0 +0 3000 0 +0 3128 0 +0 3258 0 +0 3388 0 +0 3518 0 +0 3649 0 +2764 1578 2465 +2764 1580 2465 +2763 1582 2464 +2763 1585 2463 +2762 1589 2462 +2761 1595 2461 +2760 1602 2459 +2759 1612 2457 +2756 1624 2454 +2753 1640 2449 +2750 1661 2444 +2744 1687 2436 +2737 1720 2425 +2727 1760 2410 +2714 1809 2389 +2695 1868 2360 +2669 1936 2318 +2632 2013 2255 +2577 2099 2154 +2490 2194 1970 +2341 2296 1469 +2007 2404 0 +0 2517 0 +0 2635 0 +0 2756 0 +0 2879 0 +0 3005 0 +0 3132 0 +0 3260 0 +0 3390 0 +0 3520 0 +0 3650 0 +2896 1708 2597 +2896 1709 2597 +2896 1711 2596 +2896 1713 2596 +2895 1716 2595 +2894 1721 2594 +2893 1726 2593 +2892 1733 2591 +2891 1743 2589 +2889 1755 2586 +2886 1771 2581 +2882 1792 2575 +2876 1818 2568 +2869 1851 2557 +2859 1892 2542 +2846 1941 2521 +2828 1999 2492 +2801 2067 2450 +2764 2145 2387 +2709 2231 2286 +2622 2326 2101 +2473 2428 1599 +2139 2536 0 +0 2649 0 +0 2767 0 +0 2888 0 +0 3011 0 +0 3137 0 +0 3264 0 +0 3393 0 +0 3522 0 +0 3652 0 +3029 1838 2729 +3029 1839 2729 +3028 1841 2729 +3028 1842 2728 +3028 1845 2728 +3027 1848 2727 +3027 1852 2726 +3026 1858 2725 +3024 1865 2723 +3023 1874 2721 +3021 1887 2717 +3018 1903 2713 +3014 1924 2707 +3009 1950 2699 +3001 1983 2689 +2992 2024 2674 +2978 2073 2653 +2960 2131 2624 +2934 2199 2582 +2896 2277 2519 +2841 2363 2418 +2755 2458 2233 +2605 2560 1730 +2272 2668 0 +0 2781 0 +0 2899 0 +0 3020 0 +0 3143 0 +0 3269 0 +0 3396 0 +0 3525 0 +0 3654 0 +3161 1969 2861 +3161 1970 2861 +3161 1971 2861 +3160 1972 2861 +3160 1974 2860 +3160 1976 2860 +3159 1980 2859 +3159 1984 2858 +3158 1989 2857 +3157 1996 2855 +3155 2006 2853 +3153 2018 2849 +3150 2035 2845 +3146 2055 2839 +3141 2082 2831 +3134 2115 2821 +3124 2155 2806 +3110 2205 2785 +3092 2263 2756 +3066 2331 2714 +3028 2409 2651 +2973 2495 2549 +2887 2590 2365 +2737 2692 1861 +2404 2800 0 +0 2913 0 +0 3031 0 +0 3152 0 +0 3276 0 +0 3401 0 +0 3528 0 +0 3657 0 +3293 2100 2994 +3293 2101 2993 +3293 2102 2993 +3293 2103 2993 +3293 2104 2993 +3292 2106 2992 +3292 2108 2992 +3291 2111 2991 +3291 2115 2990 +3290 2121 2989 +3289 2128 2987 +3287 2138 2985 +3285 2150 2981 +3282 2166 2977 +3278 2187 2971 +3273 2213 2963 +3266 2246 2953 +3256 2287 2938 +3242 2336 2917 +3224 2395 2888 +3198 2463 2846 +3161 2541 2783 +3105 2627 2681 +3019 2722 2497 +2870 2824 1992 +2536 2932 0 +0 3046 0 +0 3163 0 +0 3284 0 +0 3408 0 +0 3533 0 +0 3660 0 +3425 2232 3126 +3425 2232 3126 +3425 2233 3125 +3425 2233 3125 +3425 2234 3125 +3425 2236 3125 +3424 2238 3124 +3424 2240 3124 +3424 2243 3123 +3423 2247 3122 +3422 2253 3121 +3421 2260 3119 +3419 2270 3117 +3417 2282 3113 +3414 2298 3109 +3410 2319 3103 +3405 2345 3095 +3398 2378 3085 +3388 2419 3070 +3375 2468 3049 +3356 2527 3020 +3330 2595 2978 +3293 2673 2915 +3237 2759 2813 +3151 2854 2629 +3002 2956 2124 +2668 3064 0 +0 3178 0 +0 3295 0 +0 3416 0 +0 3540 0 +0 3665 0 +3557 2363 3258 +3557 2364 3258 +3557 2364 3258 +3557 2365 3258 +3557 2365 3257 +3557 2366 3257 +3557 2368 3257 +3557 2370 3256 +3556 2372 3256 +3556 2375 3255 +3555 2379 3254 +3554 2385 3253 +3553 2392 3251 +3551 2402 3249 +3549 2414 3245 +3546 2430 3241 +3542 2451 3235 +3537 2477 3227 +3530 2510 3217 +3520 2551 3202 +3507 2600 3181 +3488 2659 3152 +3462 2727 3110 +3425 2805 3047 +3369 2891 2945 +3283 2986 2760 +3134 3088 2255 +2800 3196 0 +0 3310 0 +0 3427 0 +0 3548 0 +0 3672 0 +3690 2495 3390 +3690 2495 3390 +3690 2496 3390 +3689 2496 3390 +3689 2497 3390 +3689 2497 3389 +3689 2498 3389 +3689 2500 3389 +3689 2501 3388 +3688 2504 3388 +3688 2507 3387 +3687 2511 3386 +3686 2517 3385 +3685 2524 3383 +3683 2534 3381 +3681 2546 3378 +3678 2562 3373 +3674 2583 3367 +3669 2609 3360 +3662 2642 3349 +3652 2683 3334 +3639 2732 3313 +3620 2791 3284 +3594 2859 3242 +3557 2937 3179 +3502 3023 3077 +3415 3118 2892 +3266 3220 2387 +2933 3328 0 +0 3442 0 +0 3559 0 +0 3680 0 +3822 2627 3522 +3822 2627 3522 +3822 2627 3522 +3822 2628 3522 +3822 2628 3522 +3822 2629 3522 +3821 2629 3521 +3821 2630 3521 +3821 2632 3521 +3821 2633 3521 +3820 2636 3520 +3820 2639 3519 +3819 2643 3518 +3818 2649 3517 +3817 2656 3515 +3816 2666 3513 +3813 2678 3510 +3810 2694 3505 +3807 2715 3499 +3801 2741 3492 +3794 2774 3481 +3784 2815 3466 +3771 2864 3445 +3752 2923 3416 +3726 2991 3374 +3689 3069 3311 +3634 3155 3209 +3547 3250 3024 +3398 3352 2519 +3065 3460 0 +0 3574 0 +0 3691 0 +3954 2759 3654 +3954 2759 3654 +3954 2759 3654 +3954 2759 3654 +3954 2760 3654 +3954 2760 3654 +3954 2761 3654 +3953 2761 3654 +3953 2762 3653 +3953 2764 3653 +3953 2765 3653 +3952 2768 3652 +3952 2771 3651 +3951 2775 3650 +3950 2781 3649 +3949 2788 3647 +3948 2798 3645 +3945 2810 3642 +3943 2826 3637 +3939 2847 3632 +3933 2873 3624 +3926 2906 3613 +3916 2947 3598 +3903 2996 3577 +3884 3055 3548 +3858 3123 3506 +3821 3201 3443 +3766 3287 3341 +3679 3382 3156 +3530 3484 2651 +3197 3592 0 +0 3706 0 +4086 2891 3786 +4086 2891 3786 +4086 2891 3786 +4086 2891 3786 +4086 2891 3786 +4086 2892 3786 +4086 2892 3786 +4086 2893 3786 +4086 2893 3786 +4085 2894 3785 +4085 2896 3785 +4085 2897 3785 +4085 2900 3784 +4084 2903 3783 +4083 2907 3782 +4083 2913 3781 +4081 2920 3779 +4080 2930 3777 +4078 2942 3774 +4075 2958 3769 +4071 2979 3764 +4065 3005 3756 +4058 3038 3745 +4049 3079 3730 +4035 3128 3709 +4017 3187 3680 +3991 3255 3638 +3953 3333 3575 +3898 3419 3473 +3812 3514 3289 +3662 3616 2783 +3329 3725 0 +4095 3023 3918 +4095 3023 3918 +4095 3023 3918 +4095 3023 3918 +4095 3023 3918 +4095 3023 3918 +4095 3024 3918 +4095 3024 3918 +4095 3025 3918 +4095 3025 3918 +4095 3026 3917 +4095 3028 3917 +4095 3030 3917 +4095 3032 3916 +4095 3035 3915 +4095 3039 3915 +4095 3045 3913 +4095 3052 3911 +4095 3062 3909 +4095 3074 3906 +4095 3090 3902 +4095 3111 3896 +4095 3137 3888 +4095 3170 3877 +4095 3211 3862 +4095 3261 3842 +4095 3319 3812 +4095 3387 3770 +4085 3465 3707 +4030 3551 3605 +3944 3646 3421 +3794 3748 2915 +4095 3155 4050 +4095 3155 4050 +4095 3155 4050 +4095 3155 4050 +4095 3155 4050 +4095 3155 4050 +4095 3155 4050 +4095 3156 4050 +4095 3156 4050 +4095 3157 4050 +4095 3157 4050 +4095 3158 4050 +4095 3160 4049 +4095 3162 4049 +4095 3164 4048 +4095 3167 4048 +4095 3171 4047 +4095 3177 4045 +4095 3184 4044 +4095 3194 4041 +4095 3206 4038 +4095 3222 4034 +4095 3243 4028 +4095 3270 4020 +4095 3303 4009 +4095 3343 3994 +4095 3393 3974 +4095 3451 3944 +4095 3519 3902 +4095 3597 3839 +4095 3684 3738 +4076 3778 3553 +0 0 0 +0 0 0 +0 49 0 +0 132 0 +0 224 0 +0 324 0 +0 430 0 +0 542 0 +0 658 0 +0 778 0 +0 901 0 +0 1025 0 +0 1152 0 +0 1280 0 +0 1409 0 +0 1539 0 +0 1669 0 +0 1800 0 +0 1931 0 +0 2063 0 +0 2194 0 +0 2326 0 +0 2458 0 +0 2589 0 +0 2721 0 +0 2853 0 +0 2985 0 +0 3117 0 +0 3249 0 +0 3381 0 +0 3514 0 +0 3646 0 +104 0 80 +0 0 0 +0 66 0 +0 147 0 +0 236 0 +0 333 0 +0 438 0 +0 548 0 +0 662 0 +0 781 0 +0 903 0 +0 1028 0 +0 1154 0 +0 1281 0 +0 1410 0 +0 1540 0 +0 1670 0 +0 1800 0 +0 1931 0 +0 2063 0 +0 2194 0 +0 2326 0 +0 2458 0 +0 2590 0 +0 2721 0 +0 2853 0 +0 2985 0 +0 3117 0 +0 3249 0 +0 3381 0 +0 3514 0 +0 3646 0 +326 0 214 +262 20 152 +160 88 54 +0 165 0 +0 251 0 +0 346 0 +0 447 0 +0 555 0 +0 668 0 +0 786 0 +0 907 0 +0 1030 0 +0 1156 0 +0 1283 0 +0 1411 0 +0 1540 0 +0 1670 0 +0 1801 0 +0 1932 0 +0 2063 0 +0 2194 0 +0 2326 0 +0 2458 0 +0 2590 0 +0 2722 0 +0 2853 0 +0 2985 0 +0 3117 0 +0 3249 0 +0 3382 0 +0 3514 0 +0 3646 0 +515 0 347 +474 52 302 +413 116 234 +315 188 122 +139 271 0 +0 361 0 +0 460 0 +0 565 0 +0 676 0 +0 792 0 +0 911 0 +0 1034 0 +0 1158 0 +0 1285 0 +0 1413 0 +0 1542 0 +0 1671 0 +0 1802 0 +0 1932 0 +0 2063 0 +0 2195 0 +0 2326 0 +0 2458 0 +0 2590 0 +0 2722 0 +0 2854 0 +0 2985 0 +0 3117 0 +0 3249 0 +0 3382 0 +0 3514 0 +0 3646 0 +686 42 481 +658 92 447 +618 150 399 +558 218 324 +463 295 200 +295 382 0 +0 477 0 +0 579 0 +0 687 0 +0 800 0 +0 918 0 +0 1039 0 +0 1162 0 +0 1288 0 +0 1415 0 +0 1543 0 +0 1673 0 +0 1802 0 +0 1933 0 +0 2064 0 +0 2195 0 +0 2327 0 +0 2458 0 +0 2590 0 +0 2722 0 +0 2854 0 +0 2986 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +844 96 614 +825 140 589 +798 192 554 +758 255 502 +700 327 422 +607 408 287 +444 498 4 +53 596 0 +0 700 0 +0 811 0 +0 926 0 +0 1045 0 +0 1167 0 +0 1291 0 +0 1418 0 +0 1545 0 +0 1674 0 +0 1804 0 +0 1934 0 +0 2065 0 +0 2196 0 +0 2327 0 +0 2458 0 +0 2590 0 +0 2722 0 +0 2854 0 +0 2986 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +996 158 746 +982 197 728 +963 244 702 +936 300 666 +897 365 611 +839 440 527 +748 525 382 +589 617 65 +214 718 0 +0 824 0 +0 936 0 +0 1053 0 +0 1173 0 +0 1296 0 +0 1421 0 +0 1548 0 +0 1676 0 +0 1805 0 +0 1935 0 +0 2065 0 +0 2196 0 +0 2327 0 +0 2459 0 +0 2590 0 +0 2722 0 +0 2854 0 +0 2986 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +1141 230 879 +1131 263 865 +1118 304 846 +1099 354 820 +1072 412 782 +1034 481 726 +976 558 638 +887 645 484 +730 740 135 +367 842 0 +0 950 0 +0 1064 0 +0 1181 0 +0 1302 0 +0 1426 0 +0 1552 0 +0 1679 0 +0 1807 0 +0 1937 0 +0 2067 0 +0 2197 0 +0 2328 0 +0 2459 0 +0 2591 0 +0 2722 0 +0 2854 0 +0 2986 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +1284 312 1011 +1276 340 1001 +1266 374 987 +1253 417 968 +1234 468 941 +1207 529 902 +1169 600 844 +1112 679 753 +1024 768 593 +869 865 214 +514 968 0 +0 1078 0 +0 1192 0 +0 1311 0 +0 1432 0 +0 1557 0 +0 1683 0 +0 1810 0 +0 1939 0 +0 2068 0 +0 2198 0 +0 2329 0 +0 2460 0 +0 2591 0 +0 2723 0 +0 2854 0 +0 2986 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +1423 402 1144 +1418 425 1136 +1410 454 1126 +1401 490 1112 +1387 534 1092 +1368 587 1064 +1342 650 1025 +1304 722 966 +1247 803 872 +1159 893 706 +1006 991 302 +657 1096 0 +0 1206 0 +0 1322 0 +0 1441 0 +0 1563 0 +0 1687 0 +0 1814 0 +0 1941 0 +0 2070 0 +0 2200 0 +0 2330 0 +0 2461 0 +0 2592 0 +0 2723 0 +0 2855 0 +0 2986 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +1561 500 1276 +1557 518 1270 +1551 542 1263 +1544 572 1252 +1534 609 1238 +1521 655 1218 +1502 709 1190 +1476 773 1150 +1438 846 1090 +1382 929 994 +1294 1020 824 +1142 1119 399 +797 1225 0 +0 1336 0 +0 1452 0 +0 1571 0 +0 1694 0 +0 1819 0 +0 1945 0 +0 2073 0 +0 2202 0 +0 2332 0 +0 2462 0 +0 2593 0 +0 2724 0 +0 2855 0 +0 2987 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +1697 605 1408 +1694 619 1404 +1690 639 1398 +1684 663 1391 +1677 694 1380 +1667 732 1366 +1654 778 1346 +1635 833 1317 +1609 898 1277 +1571 973 1216 +1515 1056 1119 +1428 1148 945 +1277 1248 502 +935 1354 0 +0 1466 0 +0 1582 0 +0 1702 0 +0 1825 0 +0 1950 0 +0 2077 0 +0 2205 0 +0 2334 0 +0 2464 0 +0 2594 0 +0 2725 0 +0 2856 0 +0 2987 0 +0 3119 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +1832 715 1540 +1830 727 1537 +1827 742 1533 +1823 761 1527 +1817 786 1519 +1810 818 1509 +1800 856 1494 +1787 903 1474 +1768 959 1446 +1742 1025 1405 +1704 1100 1343 +1649 1185 1245 +1562 1277 1069 +1411 1378 612 +1071 1484 0 +0 1597 0 +0 1713 0 +0 1833 0 +0 1956 0 +0 2082 0 +0 2208 0 +0 2337 0 +0 2466 0 +0 2596 0 +0 2726 0 +0 2857 0 +0 2988 0 +0 3119 0 +0 3251 0 +0 3383 0 +0 3514 0 +0 3646 0 +1966 830 1672 +1964 840 1670 +1962 851 1667 +1959 867 1663 +1955 887 1657 +1950 912 1649 +1943 943 1639 +1933 983 1624 +1920 1030 1604 +1901 1087 1575 +1875 1153 1534 +1837 1229 1472 +1782 1314 1373 +1695 1407 1194 +1544 1508 726 +1206 1615 0 +0 1728 0 +0 1845 0 +0 1965 0 +0 2088 0 +0 2213 0 +0 2340 0 +0 2468 0 +0 2598 0 +0 2728 0 +0 2858 0 +0 2989 0 +0 3120 0 +0 3251 0 +0 3383 0 +0 3515 0 +0 3646 0 +2100 950 1805 +2099 957 1803 +2097 966 1801 +2095 978 1797 +2092 993 1793 +2088 1013 1787 +2083 1039 1780 +2075 1071 1769 +2066 1110 1754 +2052 1159 1734 +2034 1216 1705 +2007 1282 1663 +1970 1359 1601 +1914 1444 1502 +1828 1538 1322 +1678 1639 844 +1341 1746 0 +0 1859 0 +0 1976 0 +0 2097 0 +0 2220 0 +0 2345 0 +0 2472 0 +0 2600 0 +0 2730 0 +0 2860 0 +0 2990 0 +0 3121 0 +0 3252 0 +0 3383 0 +0 3515 0 +0 3647 0 +2233 1072 1937 +2232 1077 1935 +2231 1084 1934 +2229 1093 1931 +2227 1106 1928 +2224 1121 1924 +2220 1142 1918 +2215 1167 1910 +2208 1200 1900 +2198 1239 1885 +2185 1288 1864 +2166 1345 1836 +2140 1412 1794 +2103 1489 1731 +2047 1575 1631 +1960 1669 1450 +1810 1770 966 +1475 1878 0 +0 1990 0 +0 2108 0 +0 2228 0 +0 2352 0 +0 2477 0 +0 2604 0 +0 2732 0 +0 2862 0 +0 2992 0 +0 3122 0 +0 3253 0 +0 3384 0 +0 3515 0 +0 3647 0 +2366 1196 2069 +2365 1200 2068 +2365 1206 2067 +2363 1213 2065 +2362 1222 2063 +2360 1234 2059 +2357 1250 2055 +2353 1271 2049 +2347 1297 2041 +2340 1329 2031 +2330 1369 2016 +2317 1418 1995 +2298 1475 1966 +2272 1543 1925 +2235 1620 1862 +2180 1706 1762 +2093 1800 1579 +1943 1901 1090 +1608 2009 0 +0 2122 0 +0 2239 0 +0 2360 0 +0 2483 0 +0 2609 0 +0 2736 0 +0 2864 0 +0 2994 0 +0 3124 0 +0 3254 0 +0 3385 0 +0 3516 0 +0 3648 0 +2499 1323 2201 +2498 1326 2200 +2498 1330 2199 +2497 1335 2198 +2496 1342 2196 +2494 1352 2194 +2492 1364 2191 +2489 1380 2186 +2485 1400 2181 +2480 1426 2173 +2473 1459 2162 +2463 1499 2147 +2449 1548 2127 +2431 1606 2098 +2405 1674 2056 +2367 1751 1993 +2312 1837 1892 +2225 1931 1709 +2076 2033 1216 +1741 2141 0 +0 2254 0 +0 2371 0 +0 2492 0 +0 2615 0 +0 2741 0 +0 2868 0 +0 2996 0 +0 3126 0 +0 3256 0 +0 3386 0 +0 3517 0 +0 3648 0 +2631 1450 2333 +2631 1453 2333 +2631 1456 2332 +2630 1460 2331 +2629 1465 2330 +2628 1473 2328 +2626 1482 2325 +2624 1494 2322 +2621 1510 2318 +2617 1531 2312 +2612 1557 2304 +2605 1590 2294 +2595 1630 2279 +2582 1679 2258 +2563 1737 2229 +2537 1805 2187 +2500 1882 2124 +2444 1968 2023 +2358 2063 1840 +2208 2164 1343 +1874 2272 0 +0 2386 0 +0 2503 0 +0 2624 0 +0 2747 0 +0 2873 0 +0 3000 0 +0 3128 0 +0 3258 0 +0 3388 0 +0 3518 0 +0 3649 0 +2764 1579 2465 +2764 1581 2465 +2763 1583 2464 +2763 1586 2464 +2762 1590 2463 +2761 1596 2461 +2760 1603 2460 +2758 1613 2457 +2756 1625 2454 +2753 1641 2450 +2749 1662 2444 +2744 1688 2436 +2737 1721 2425 +2727 1761 2410 +2714 1810 2390 +2695 1868 2361 +2669 1936 2319 +2632 2013 2256 +2576 2100 2155 +2490 2194 1971 +2341 2296 1472 +2006 2404 0 +0 2518 0 +0 2635 0 +0 2756 0 +0 2879 0 +0 3005 0 +0 3132 0 +0 3261 0 +0 3390 0 +0 3520 0 +0 3650 0 +2896 1709 2597 +2896 1710 2597 +2896 1712 2597 +2895 1714 2596 +2895 1717 2595 +2894 1721 2594 +2893 1727 2593 +2892 1734 2591 +2891 1744 2589 +2888 1756 2586 +2886 1772 2581 +2882 1793 2576 +2876 1819 2568 +2869 1852 2557 +2859 1892 2542 +2846 1942 2522 +2827 2000 2492 +2801 2068 2450 +2764 2145 2387 +2709 2232 2286 +2622 2326 2102 +2473 2428 1601 +2139 2536 0 +0 2650 0 +0 2767 0 +0 2888 0 +0 3011 0 +0 3137 0 +0 3264 0 +0 3393 0 +0 3522 0 +0 3652 0 +3029 1839 2729 +3029 1840 2729 +3028 1841 2729 +3028 1843 2729 +3028 1845 2728 +3027 1849 2727 +3026 1853 2726 +3026 1858 2725 +3024 1865 2723 +3023 1875 2721 +3021 1887 2718 +3018 1904 2713 +3014 1924 2708 +3009 1950 2700 +3001 1983 2689 +2992 2024 2674 +2978 2073 2653 +2960 2132 2624 +2934 2199 2582 +2896 2277 2519 +2841 2363 2418 +2754 2458 2234 +2605 2560 1732 +2271 2668 0 +0 2781 0 +0 2899 0 +0 3020 0 +0 3144 0 +0 3269 0 +0 3396 0 +0 3525 0 +0 3654 0 +3161 1970 2862 +3161 1970 2861 +3161 1971 2861 +3160 1973 2861 +3160 1975 2860 +3160 1977 2860 +3159 1980 2859 +3159 1984 2858 +3158 1990 2857 +3157 1997 2855 +3155 2006 2853 +3153 2019 2850 +3150 2035 2845 +3146 2056 2839 +3141 2082 2832 +3133 2115 2821 +3124 2156 2806 +3110 2205 2785 +3092 2263 2756 +3066 2331 2714 +3028 2409 2651 +2973 2495 2550 +2887 2590 2365 +2737 2692 1862 +2404 2800 0 +0 2914 0 +0 3031 0 +0 3152 0 +0 3276 0 +0 3401 0 +0 3528 0 +0 3657 0 +3293 2101 2994 +3293 2101 2994 +3293 2102 2993 +3293 2103 2993 +3293 2104 2993 +3292 2106 2992 +3292 2109 2992 +3291 2112 2991 +3291 2116 2990 +3290 2121 2989 +3289 2129 2987 +3287 2138 2985 +3285 2151 2982 +3282 2167 2977 +3278 2187 2971 +3273 2214 2963 +3266 2247 2953 +3256 2287 2938 +3242 2337 2917 +3224 2395 2888 +3198 2463 2846 +3160 2541 2783 +3105 2627 2681 +3019 2722 2497 +2870 2824 1993 +2536 2932 0 +0 3046 0 +0 3163 0 +0 3284 0 +0 3408 0 +0 3533 0 +0 3660 0 +3425 2232 3126 +3425 2232 3126 +3425 2233 3126 +3425 2234 3125 +3425 2235 3125 +3425 2236 3125 +3424 2238 3124 +3424 2240 3124 +3424 2243 3123 +3423 2248 3122 +3422 2253 3121 +3421 2260 3119 +3419 2270 3117 +3417 2282 3114 +3414 2299 3109 +3410 2319 3103 +3405 2346 3095 +3398 2379 3085 +3388 2419 3070 +3375 2469 3049 +3356 2527 3020 +3330 2595 2978 +3293 2673 2915 +3237 2759 2813 +3151 2854 2629 +3002 2956 2124 +2668 3064 0 +0 3178 0 +0 3295 0 +0 3416 0 +0 3540 0 +0 3665 0 +3557 2364 3258 +3557 2364 3258 +3557 2364 3258 +3557 2365 3258 +3557 2366 3257 +3557 2367 3257 +3557 2368 3257 +3557 2370 3256 +3556 2372 3256 +3556 2375 3255 +3555 2379 3254 +3554 2385 3253 +3553 2392 3251 +3551 2402 3249 +3549 2414 3246 +3546 2430 3241 +3542 2451 3235 +3537 2477 3228 +3530 2510 3217 +3520 2551 3202 +3507 2600 3181 +3488 2659 3152 +3462 2727 3110 +3425 2805 3047 +3369 2891 2945 +3283 2986 2761 +3134 3088 2256 +2800 3196 0 +0 3310 0 +0 3427 0 +0 3548 0 +0 3672 0 +3690 2495 3390 +3690 2495 3390 +3690 2496 3390 +3689 2496 3390 +3689 2497 3390 +3689 2497 3389 +3689 2498 3389 +3689 2500 3389 +3689 2502 3389 +3688 2504 3388 +3688 2507 3387 +3687 2511 3386 +3686 2517 3385 +3685 2524 3383 +3683 2534 3381 +3681 2546 3378 +3678 2562 3373 +3674 2583 3367 +3669 2609 3360 +3662 2642 3349 +3652 2683 3334 +3639 2732 3313 +3620 2791 3284 +3594 2859 3242 +3557 2937 3179 +3502 3023 3077 +3415 3118 2893 +3266 3220 2387 +2933 3328 0 +0 3442 0 +0 3559 0 +0 3680 0 +3822 2627 3522 +3822 2627 3522 +3822 2627 3522 +3822 2628 3522 +3822 2628 3522 +3821 2629 3522 +3821 2629 3522 +3821 2630 3521 +3821 2632 3521 +3821 2634 3521 +3820 2636 3520 +3820 2639 3519 +3819 2643 3518 +3818 2649 3517 +3817 2656 3515 +3815 2666 3513 +3813 2678 3510 +3810 2694 3505 +3807 2715 3500 +3801 2741 3492 +3794 2774 3481 +3784 2815 3466 +3771 2864 3445 +3752 2923 3416 +3726 2991 3374 +3689 3069 3311 +3634 3155 3209 +3547 3250 3025 +3398 3352 2519 +3065 3460 0 +0 3574 0 +0 3691 0 +3954 2759 3654 +3954 2759 3654 +3954 2759 3654 +3954 2759 3654 +3954 2760 3654 +3954 2760 3654 +3954 2761 3654 +3953 2761 3654 +3953 2762 3653 +3953 2764 3653 +3953 2766 3653 +3952 2768 3652 +3952 2771 3651 +3951 2775 3650 +3950 2781 3649 +3949 2788 3647 +3948 2798 3645 +3945 2810 3642 +3943 2826 3637 +3939 2847 3632 +3933 2873 3624 +3926 2906 3613 +3916 2947 3598 +3903 2996 3577 +3884 3055 3548 +3858 3123 3506 +3821 3201 3443 +3766 3287 3341 +3679 3382 3157 +3530 3484 2651 +3197 3592 0 +0 3706 0 +4086 2891 3786 +4086 2891 3786 +4086 2891 3786 +4086 2891 3786 +4086 2891 3786 +4086 2892 3786 +4086 2892 3786 +4086 2893 3786 +4086 2893 3786 +4085 2894 3785 +4085 2896 3785 +4085 2898 3785 +4085 2900 3784 +4084 2903 3783 +4083 2907 3782 +4083 2913 3781 +4081 2920 3779 +4080 2930 3777 +4078 2942 3774 +4075 2958 3769 +4071 2979 3764 +4065 3005 3756 +4058 3038 3745 +4049 3079 3730 +4035 3129 3709 +4017 3187 3680 +3991 3255 3638 +3953 3333 3575 +3898 3419 3473 +3811 3514 3289 +3662 3616 2783 +3329 3725 0 +4095 3023 3918 +4095 3023 3918 +4095 3023 3918 +4095 3023 3918 +4095 3023 3918 +4095 3023 3918 +4095 3024 3918 +4095 3024 3918 +4095 3025 3918 +4095 3025 3918 +4095 3026 3918 +4095 3028 3917 +4095 3030 3917 +4095 3032 3916 +4095 3035 3916 +4095 3039 3915 +4095 3045 3913 +4095 3052 3911 +4095 3062 3909 +4095 3074 3906 +4095 3090 3902 +4095 3111 3896 +4095 3137 3888 +4095 3171 3877 +4095 3211 3862 +4095 3261 3842 +4095 3319 3812 +4095 3387 3770 +4085 3465 3707 +4030 3551 3605 +3944 3646 3421 +3794 3748 2915 +4095 3155 4050 +4095 3155 4050 +4095 3155 4050 +4095 3155 4050 +4095 3155 4050 +4095 3155 4050 +4095 3155 4050 +4095 3156 4050 +4095 3156 4050 +4095 3157 4050 +4095 3158 4050 +4095 3159 4050 +4095 3160 4049 +4095 3162 4049 +4095 3164 4048 +4095 3167 4048 +4095 3171 4047 +4095 3177 4045 +4095 3184 4044 +4095 3194 4041 +4095 3206 4038 +4095 3222 4034 +4095 3243 4028 +4095 3270 4020 +4095 3303 4009 +4095 3343 3994 +4095 3393 3974 +4095 3451 3944 +4095 3519 3902 +4095 3597 3839 +4095 3684 3738 +4076 3778 3553 +0 0 36 +0 24 0 +0 91 0 +0 168 0 +0 254 0 +0 348 0 +0 449 0 +0 557 0 +0 669 0 +0 787 0 +0 907 0 +0 1031 0 +0 1156 0 +0 1283 0 +0 1411 0 +0 1541 0 +0 1671 0 +0 1801 0 +0 1932 0 +0 2063 0 +0 2195 0 +0 2326 0 +0 2458 0 +0 2590 0 +0 2722 0 +0 2853 0 +0 2985 0 +0 3117 0 +0 3249 0 +0 3382 0 +0 3514 0 +0 3646 0 +67 0 149 +0 42 77 +0 107 0 +0 181 0 +0 264 0 +0 356 0 +0 456 0 +0 562 0 +0 674 0 +0 790 0 +0 910 0 +0 1033 0 +0 1158 0 +0 1284 0 +0 1412 0 +0 1541 0 +0 1671 0 +0 1801 0 +0 1932 0 +0 2063 0 +0 2195 0 +0 2326 0 +0 2458 0 +0 2590 0 +0 2722 0 +0 2853 0 +0 2985 0 +0 3117 0 +0 3249 0 +0 3382 0 +0 3514 0 +0 3646 0 +303 13 267 +236 65 212 +127 127 127 +0 198 0 +0 279 0 +0 368 0 +0 465 0 +0 570 0 +0 680 0 +0 795 0 +0 913 0 +0 1035 0 +0 1160 0 +0 1286 0 +0 1413 0 +0 1542 0 +0 1672 0 +0 1802 0 +0 1933 0 +0 2064 0 +0 2195 0 +0 2326 0 +0 2458 0 +0 2590 0 +0 2722 0 +0 2854 0 +0 2985 0 +0 3117 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +500 45 387 +458 94 346 +394 152 284 +292 220 186 +105 297 8 +0 383 0 +0 478 0 +0 579 0 +0 687 0 +0 801 0 +0 918 0 +0 1039 0 +0 1162 0 +0 1288 0 +0 1415 0 +0 1543 0 +0 1673 0 +0 1803 0 +0 1933 0 +0 2064 0 +0 2195 0 +0 2327 0 +0 2458 0 +0 2590 0 +0 2722 0 +0 2854 0 +0 2986 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +676 85 511 +647 130 480 +606 184 434 +545 248 366 +447 321 254 +271 403 43 +0 494 0 +0 592 0 +0 697 0 +0 808 0 +0 924 0 +0 1044 0 +0 1166 0 +0 1291 0 +0 1417 0 +0 1545 0 +0 1674 0 +0 1803 0 +0 1934 0 +0 2064 0 +0 2196 0 +0 2327 0 +0 2458 0 +0 2590 0 +0 2722 0 +0 2854 0 +0 2986 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +837 134 636 +818 175 613 +790 224 579 +750 282 531 +690 350 456 +596 428 332 +427 514 85 +12 609 0 +0 711 0 +0 819 0 +0 932 0 +0 1050 0 +0 1171 0 +0 1294 0 +0 1420 0 +0 1547 0 +0 1675 0 +0 1805 0 +0 1935 0 +0 2065 0 +0 2196 0 +0 2327 0 +0 2459 0 +0 2590 0 +0 2722 0 +0 2854 0 +0 2986 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +991 192 763 +977 228 746 +957 272 721 +930 325 686 +891 387 634 +832 459 554 +740 540 419 +577 630 136 +186 728 0 +0 832 0 +0 943 0 +0 1058 0 +0 1177 0 +0 1299 0 +0 1423 0 +0 1550 0 +0 1677 0 +0 1806 0 +0 1936 0 +0 2066 0 +0 2197 0 +0 2328 0 +0 2459 0 +0 2591 0 +0 2722 0 +0 2854 0 +0 2986 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +1138 259 892 +1128 290 878 +1114 329 860 +1095 376 834 +1068 432 798 +1029 497 743 +971 572 659 +880 657 514 +721 749 197 +347 850 0 +0 956 0 +0 1068 0 +0 1185 0 +0 1305 0 +0 1428 0 +0 1553 0 +0 1680 0 +0 1808 0 +0 1937 0 +0 2067 0 +0 2198 0 +0 2328 0 +0 2460 0 +0 2591 0 +0 2722 0 +0 2854 0 +0 2986 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +1281 336 1021 +1274 362 1011 +1264 395 997 +1250 436 978 +1231 486 952 +1204 544 914 +1166 613 858 +1109 690 770 +1019 777 616 +862 872 267 +499 974 0 +0 1082 0 +0 1196 0 +0 1314 0 +0 1435 0 +0 1558 0 +0 1684 0 +0 1811 0 +0 1939 0 +0 2069 0 +0 2199 0 +0 2329 0 +0 2460 0 +0 2591 0 +0 2723 0 +0 2854 0 +0 2986 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +1421 422 1151 +1416 444 1143 +1408 472 1133 +1398 506 1119 +1385 549 1100 +1366 601 1073 +1339 661 1034 +1301 732 976 +1245 811 885 +1156 900 725 +1001 997 346 +646 1100 0 +0 1210 0 +0 1324 0 +0 1443 0 +0 1565 0 +0 1689 0 +0 1815 0 +0 1942 0 +0 2071 0 +0 2200 0 +0 2330 0 +0 2461 0 +0 2592 0 +0 2723 0 +0 2855 0 +0 2986 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +1559 516 1281 +1555 534 1276 +1550 557 1268 +1543 586 1258 +1533 622 1244 +1519 666 1224 +1500 719 1197 +1474 782 1157 +1436 854 1098 +1380 935 1004 +1291 1025 838 +1138 1123 434 +789 1228 0 +0 1339 0 +0 1454 0 +0 1573 0 +0 1695 0 +0 1820 0 +0 1946 0 +0 2074 0 +0 2202 0 +0 2332 0 +0 2462 0 +0 2593 0 +0 2724 0 +0 2855 0 +0 2987 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +1696 617 1412 +1693 632 1408 +1689 651 1402 +1683 674 1395 +1676 704 1384 +1666 741 1370 +1653 787 1350 +1634 841 1322 +1608 905 1282 +1570 978 1222 +1514 1061 1126 +1426 1152 956 +1274 1251 531 +929 1357 0 +0 1468 0 +0 1584 0 +0 1703 0 +0 1826 0 +0 1951 0 +0 2077 0 +0 2205 0 +0 2334 0 +0 2464 0 +0 2594 0 +0 2725 0 +0 2856 0 +0 2987 0 +0 3119 0 +0 3251 0 +0 3382 0 +0 3514 0 +0 3646 0 +1831 725 1543 +1829 737 1540 +1826 752 1536 +1822 771 1530 +1817 795 1523 +1809 826 1512 +1800 864 1498 +1786 910 1478 +1767 965 1449 +1741 1030 1409 +1703 1105 1348 +1648 1188 1251 +1560 1280 1077 +1409 1380 634 +1067 1486 0 +0 1598 0 +0 1714 0 +0 1834 0 +0 1957 0 +0 2082 0 +0 2209 0 +0 2337 0 +0 2466 0 +0 2596 0 +0 2726 0 +0 2857 0 +0 2988 0 +0 3119 0 +0 3251 0 +0 3383 0 +0 3514 0 +0 3646 0 +1965 838 1675 +1964 847 1672 +1962 859 1669 +1959 874 1665 +1955 894 1659 +1949 918 1652 +1942 950 1641 +1932 988 1626 +1919 1035 1606 +1900 1092 1578 +1874 1157 1537 +1837 1232 1475 +1781 1317 1377 +1694 1409 1201 +1543 1510 744 +1203 1617 0 +0 1729 0 +0 1845 0 +0 1966 0 +0 2089 0 +0 2214 0 +0 2341 0 +0 2469 0 +0 2598 0 +0 2728 0 +0 2858 0 +0 2989 0 +0 3120 0 +0 3251 0 +0 3383 0 +0 3515 0 +0 3646 0 +2099 956 1806 +2098 963 1805 +2097 972 1802 +2094 983 1799 +2091 999 1795 +2087 1019 1789 +2082 1044 1781 +2075 1076 1771 +2065 1115 1756 +2052 1162 1736 +2033 1219 1707 +2007 1285 1666 +1969 1361 1604 +1914 1446 1505 +1827 1539 1326 +1676 1640 858 +1338 1747 0 +0 1860 0 +0 1977 0 +0 2097 0 +0 2220 0 +0 2345 0 +0 2472 0 +0 2601 0 +0 2730 0 +0 2860 0 +0 2990 0 +0 3121 0 +0 3252 0 +0 3383 0 +0 3515 0 +0 3647 0 +2233 1076 1938 +2232 1082 1937 +2231 1089 1935 +2229 1098 1933 +2227 1110 1929 +2224 1125 1925 +2220 1146 1919 +2215 1171 1912 +2208 1203 1901 +2198 1243 1886 +2184 1291 1866 +2166 1348 1837 +2140 1415 1796 +2102 1491 1733 +2047 1576 1634 +1960 1670 1454 +1810 1771 976 +1473 1878 0 +0 1991 0 +0 2108 0 +0 2229 0 +0 2352 0 +0 2477 0 +0 2604 0 +0 2732 0 +0 2862 0 +0 2992 0 +0 3122 0 +0 3253 0 +0 3384 0 +0 3516 0 +0 3647 0 +2366 1200 2070 +2365 1204 2069 +2364 1209 2068 +2363 1216 2066 +2361 1226 2063 +2359 1238 2060 +2356 1253 2056 +2352 1274 2050 +2347 1299 2042 +2340 1332 2032 +2330 1371 2017 +2317 1420 1997 +2298 1477 1968 +2272 1544 1926 +2235 1621 1863 +2179 1707 1763 +2092 1801 1582 +1943 1902 1098 +1607 2010 0 +0 2123 0 +0 2240 0 +0 2360 0 +0 2484 0 +0 2609 0 +0 2736 0 +0 2864 0 +0 2994 0 +0 3124 0 +0 3254 0 +0 3385 0 +0 3516 0 +0 3648 0 +2499 1325 2202 +2498 1328 2201 +2498 1332 2200 +2497 1338 2199 +2495 1345 2197 +2494 1354 2195 +2492 1367 2191 +2489 1382 2187 +2485 1403 2181 +2480 1429 2174 +2472 1461 2163 +2463 1501 2148 +2449 1550 2128 +2431 1608 2099 +2404 1675 2057 +2367 1752 1994 +2312 1838 1894 +2225 1932 1711 +2075 2033 1222 +1740 2141 0 +0 2254 0 +0 2371 0 +0 2492 0 +0 2616 0 +0 2741 0 +0 2868 0 +0 2996 0 +0 3126 0 +0 3256 0 +0 3386 0 +0 3517 0 +0 3648 0 +2631 1452 2334 +2631 1455 2333 +2630 1458 2332 +2630 1462 2331 +2629 1467 2330 +2628 1474 2328 +2626 1484 2326 +2624 1496 2323 +2621 1512 2319 +2617 1533 2313 +2612 1559 2305 +2605 1591 2294 +2595 1631 2279 +2581 1680 2259 +2563 1738 2230 +2537 1806 2188 +2499 1883 2125 +2444 1969 2024 +2357 2063 1842 +2208 2165 1348 +1873 2273 0 +0 2386 0 +0 2503 0 +0 2624 0 +0 2748 0 +0 2873 0 +0 3000 0 +0 3129 0 +0 3258 0 +0 3388 0 +0 3518 0 +0 3649 0 +2764 1581 2466 +2764 1582 2465 +2763 1585 2465 +2763 1588 2464 +2762 1592 2463 +2761 1597 2462 +2760 1605 2460 +2758 1614 2458 +2756 1626 2454 +2753 1642 2450 +2749 1663 2444 +2744 1689 2436 +2737 1722 2426 +2727 1762 2411 +2714 1811 2390 +2695 1869 2361 +2669 1937 2319 +2632 2014 2256 +2576 2100 2155 +2490 2195 1972 +2340 2297 1475 +2006 2405 0 +0 2518 0 +0 2635 0 +0 2756 0 +0 2880 0 +0 3005 0 +0 3132 0 +0 3261 0 +0 3390 0 +0 3520 0 +0 3650 0 +2896 1710 2598 +2896 1711 2597 +2896 1713 2597 +2895 1715 2596 +2895 1718 2596 +2894 1723 2595 +2893 1728 2593 +2892 1735 2592 +2891 1745 2589 +2888 1757 2586 +2885 1773 2582 +2882 1794 2576 +2876 1820 2568 +2869 1853 2557 +2859 1893 2542 +2846 1942 2522 +2827 2001 2493 +2801 2068 2451 +2764 2146 2388 +2709 2232 2287 +2622 2326 2103 +2473 2428 1604 +2139 2536 0 +0 2650 0 +0 2767 0 +0 2888 0 +0 3012 0 +0 3137 0 +0 3264 0 +0 3393 0 +0 3522 0 +0 3652 0 +3029 1840 2730 +3028 1841 2729 +3028 1842 2729 +3028 1844 2729 +3028 1846 2728 +3027 1849 2727 +3026 1854 2726 +3026 1859 2725 +3024 1866 2723 +3023 1876 2721 +3021 1888 2718 +3018 1904 2714 +3014 1925 2708 +3008 1951 2700 +3001 1984 2689 +2992 2025 2674 +2978 2074 2654 +2960 2132 2625 +2933 2200 2582 +2896 2277 2519 +2841 2364 2418 +2754 2458 2234 +2605 2560 1733 +2271 2668 0 +0 2782 0 +0 2899 0 +0 3020 0 +0 3144 0 +0 3269 0 +0 3396 0 +0 3525 0 +0 3654 0 +3161 1970 2862 +3161 1971 2862 +3161 1972 2861 +3160 1973 2861 +3160 1975 2861 +3160 1978 2860 +3159 1981 2859 +3159 1985 2858 +3158 1990 2857 +3156 1998 2855 +3155 2007 2853 +3153 2020 2850 +3150 2036 2845 +3146 2056 2840 +3141 2083 2832 +3133 2115 2821 +3124 2156 2806 +3110 2205 2785 +3092 2264 2756 +3066 2332 2714 +3028 2409 2651 +2973 2495 2550 +2887 2590 2366 +2737 2692 1864 +2403 2800 0 +0 2914 0 +0 3031 0 +0 3152 0 +0 3276 0 +0 3401 0 +0 3528 0 +0 3657 0 +3293 2101 2994 +3293 2102 2994 +3293 2103 2993 +3293 2104 2993 +3293 2105 2993 +3292 2107 2993 +3292 2109 2992 +3291 2112 2991 +3291 2116 2990 +3290 2122 2989 +3289 2129 2987 +3287 2139 2985 +3285 2151 2982 +3282 2167 2977 +3278 2188 2972 +3273 2214 2964 +3266 2247 2953 +3256 2288 2938 +3242 2337 2917 +3224 2395 2888 +3198 2463 2846 +3160 2541 2783 +3105 2627 2682 +3019 2722 2497 +2869 2824 1994 +2536 2932 0 +0 3046 0 +0 3163 0 +0 3284 0 +0 3408 0 +0 3533 0 +0 3660 0 +3425 2232 3126 +3425 2233 3126 +3425 2233 3126 +3425 2234 3125 +3425 2235 3125 +3425 2236 3125 +3424 2238 3125 +3424 2241 3124 +3424 2244 3123 +3423 2248 3122 +3422 2253 3121 +3421 2261 3119 +3419 2270 3117 +3417 2283 3114 +3414 2299 3109 +3410 2320 3103 +3405 2346 3096 +3398 2379 3085 +3388 2420 3070 +3375 2469 3049 +3356 2527 3020 +3330 2595 2978 +3293 2673 2915 +3237 2759 2814 +3151 2854 2629 +3002 2956 2125 +2668 3064 0 +0 3178 0 +0 3295 0 +0 3416 0 +0 3540 0 +0 3665 0 +3557 2364 3258 +3557 2364 3258 +3557 2365 3258 +3557 2365 3258 +3557 2366 3257 +3557 2367 3257 +3557 2368 3257 +3557 2370 3257 +3556 2372 3256 +3556 2375 3255 +3555 2380 3254 +3554 2385 3253 +3553 2392 3251 +3551 2402 3249 +3549 2414 3246 +3546 2431 3241 +3542 2451 3235 +3537 2478 3228 +3530 2511 3217 +3520 2551 3202 +3507 2601 3181 +3488 2659 3152 +3462 2727 3110 +3425 2805 3047 +3369 2891 2945 +3283 2986 2761 +3134 3088 2256 +2800 3196 0 +0 3310 0 +0 3427 0 +0 3548 0 +0 3672 0 +3690 2495 3390 +3690 2496 3390 +3690 2496 3390 +3689 2496 3390 +3689 2497 3390 +3689 2498 3389 +3689 2499 3389 +3689 2500 3389 +3689 2502 3389 +3688 2504 3388 +3688 2507 3387 +3687 2511 3386 +3686 2517 3385 +3685 2524 3383 +3683 2534 3381 +3681 2546 3378 +3678 2562 3373 +3674 2583 3368 +3669 2610 3360 +3662 2643 3349 +3652 2683 3334 +3639 2733 3313 +3620 2791 3284 +3594 2859 3242 +3557 2937 3179 +3502 3023 3077 +3415 3118 2893 +3266 3220 2388 +2932 3328 0 +0 3442 0 +0 3559 0 +0 3680 0 +3822 2627 3522 +3822 2627 3522 +3822 2628 3522 +3822 2628 3522 +3822 2628 3522 +3821 2629 3522 +3821 2630 3522 +3821 2631 3521 +3821 2632 3521 +3821 2634 3521 +3820 2636 3520 +3820 2639 3519 +3819 2643 3518 +3818 2649 3517 +3817 2656 3515 +3815 2666 3513 +3813 2678 3510 +3810 2694 3505 +3807 2715 3500 +3801 2742 3492 +3794 2775 3481 +3784 2815 3466 +3771 2865 3445 +3752 2923 3416 +3726 2991 3374 +3689 3069 3311 +3634 3155 3209 +3547 3250 3025 +3398 3352 2520 +3065 3460 0 +0 3574 0 +0 3691 0 +3954 2759 3654 +3954 2759 3654 +3954 2759 3654 +3954 2759 3654 +3954 2760 3654 +3954 2760 3654 +3954 2761 3654 +3953 2762 3654 +3953 2763 3653 +3953 2764 3653 +3953 2766 3653 +3952 2768 3652 +3952 2771 3651 +3951 2775 3650 +3950 2781 3649 +3949 2788 3647 +3948 2798 3645 +3945 2810 3642 +3943 2826 3637 +3939 2847 3632 +3933 2873 3624 +3926 2907 3613 +3916 2947 3598 +3903 2997 3577 +3884 3055 3548 +3858 3123 3506 +3821 3201 3443 +3766 3287 3341 +3679 3382 3157 +3530 3484 2651 +3197 3592 0 +0 3706 0 +4086 2891 3786 +4086 2891 3786 +4086 2891 3786 +4086 2891 3786 +4086 2891 3786 +4086 2892 3786 +4086 2892 3786 +4086 2893 3786 +4086 2894 3786 +4085 2895 3785 +4085 2896 3785 +4085 2898 3785 +4085 2900 3784 +4084 2903 3783 +4083 2907 3782 +4083 2913 3781 +4081 2920 3779 +4080 2930 3777 +4078 2942 3774 +4075 2958 3770 +4071 2979 3764 +4065 3005 3756 +4058 3039 3745 +4049 3079 3730 +4035 3129 3709 +4017 3187 3680 +3991 3255 3638 +3953 3333 3575 +3898 3419 3473 +3811 3514 3289 +3662 3616 2783 +3329 3725 0 +4095 3023 3918 +4095 3023 3918 +4095 3023 3918 +4095 3023 3918 +4095 3023 3918 +4095 3023 3918 +4095 3024 3918 +4095 3024 3918 +4095 3025 3918 +4095 3026 3918 +4095 3027 3918 +4095 3028 3917 +4095 3030 3917 +4095 3032 3916 +4095 3035 3916 +4095 3039 3915 +4095 3045 3913 +4095 3052 3911 +4095 3062 3909 +4095 3074 3906 +4095 3090 3902 +4095 3111 3896 +4095 3138 3888 +4095 3171 3877 +4095 3211 3862 +4095 3261 3842 +4095 3319 3812 +4095 3387 3770 +4085 3465 3707 +4030 3551 3606 +3944 3646 3421 +3794 3748 2915 +4095 3155 4050 +4095 3155 4050 +4095 3155 4050 +4095 3155 4050 +4095 3155 4050 +4095 3155 4050 +4095 3156 4050 +4095 3156 4050 +4095 3156 4050 +4095 3157 4050 +4095 3158 4050 +4095 3159 4050 +4095 3160 4049 +4095 3162 4049 +4095 3164 4048 +4095 3167 4048 +4095 3171 4047 +4095 3177 4045 +4095 3184 4044 +4095 3194 4041 +4095 3206 4038 +4095 3222 4034 +4095 3243 4028 +4095 3270 4020 +4095 3303 4009 +4095 3343 3994 +4095 3393 3974 +4095 3451 3944 +4095 3519 3902 +4095 3597 3839 +4095 3684 3738 +4076 3778 3553 +0 33 135 +0 83 61 +0 142 0 +0 211 0 +0 290 0 +0 377 0 +0 473 0 +0 576 0 +0 684 0 +0 798 0 +0 916 0 +0 1037 0 +0 1161 0 +0 1287 0 +0 1414 0 +0 1543 0 +0 1672 0 +0 1802 0 +0 1933 0 +0 2064 0 +0 2195 0 +0 2327 0 +0 2458 0 +0 2590 0 +0 2722 0 +0 2854 0 +0 2986 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +11 50 228 +0 99 168 +0 156 74 +0 223 0 +0 300 0 +0 386 0 +0 480 0 +0 581 0 +0 689 0 +0 802 0 +0 919 0 +0 1039 0 +0 1163 0 +0 1288 0 +0 1415 0 +0 1543 0 +0 1673 0 +0 1803 0 +0 1933 0 +0 2064 0 +0 2195 0 +0 2327 0 +0 2458 0 +0 2590 0 +0 2722 0 +0 2854 0 +0 2986 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +271 73 329 +199 119 281 +79 174 209 +0 239 91 +0 313 0 +0 397 0 +0 489 0 +0 588 0 +0 694 0 +0 806 0 +0 922 0 +0 1042 0 +0 1165 0 +0 1290 0 +0 1416 0 +0 1544 0 +0 1673 0 +0 1803 0 +0 1934 0 +0 2064 0 +0 2195 0 +0 2327 0 +0 2458 0 +0 2590 0 +0 2722 0 +0 2854 0 +0 2986 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +480 102 436 +435 145 399 +368 197 344 +259 259 259 +54 330 113 +0 411 0 +0 500 0 +0 597 0 +0 702 0 +0 812 0 +0 927 0 +0 1045 0 +0 1167 0 +0 1292 0 +0 1418 0 +0 1546 0 +0 1674 0 +0 1804 0 +0 1934 0 +0 2065 0 +0 2196 0 +0 2327 0 +0 2458 0 +0 2590 0 +0 2722 0 +0 2854 0 +0 2986 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +662 137 548 +632 177 519 +590 226 478 +526 284 416 +424 352 318 +237 429 140 +0 515 0 +0 610 0 +0 711 0 +0 819 0 +0 933 0 +0 1050 0 +0 1171 0 +0 1294 0 +0 1420 0 +0 1547 0 +0 1675 0 +0 1805 0 +0 1935 0 +0 2065 0 +0 2196 0 +0 2327 0 +0 2459 0 +0 2590 0 +0 2722 0 +0 2854 0 +0 2986 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +828 181 665 +808 217 643 +779 262 612 +738 316 566 +677 380 498 +579 453 386 +403 535 175 +0 626 0 +0 724 0 +0 830 0 +0 941 0 +0 1056 0 +0 1176 0 +0 1298 0 +0 1423 0 +0 1549 0 +0 1677 0 +0 1806 0 +0 1936 0 +0 2066 0 +0 2197 0 +0 2328 0 +0 2459 0 +0 2590 0 +0 2722 0 +0 2854 0 +0 2986 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +984 233 785 +970 266 768 +950 307 745 +922 356 712 +882 414 663 +822 482 588 +728 560 464 +559 646 217 +144 741 0 +0 843 0 +0 951 0 +0 1064 0 +0 1182 0 +0 1303 0 +0 1426 0 +0 1552 0 +0 1679 0 +0 1807 0 +0 1937 0 +0 2067 0 +0 2197 0 +0 2328 0 +0 2459 0 +0 2591 0 +0 2722 0 +0 2854 0 +0 2986 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +1133 295 908 +1123 324 895 +1109 360 878 +1089 404 853 +1062 457 818 +1023 519 766 +964 591 686 +872 672 551 +709 762 268 +318 860 0 +0 964 0 +0 1075 0 +0 1190 0 +0 1309 0 +0 1431 0 +0 1555 0 +0 1682 0 +0 1809 0 +0 1938 0 +0 2068 0 +0 2198 0 +0 2329 0 +0 2460 0 +0 2591 0 +0 2723 0 +0 2854 0 +0 2986 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +1277 366 1033 +1270 391 1024 +1260 422 1010 +1246 461 992 +1227 508 967 +1200 564 930 +1161 629 876 +1103 705 791 +1013 789 646 +853 882 329 +479 982 0 +0 1088 0 +0 1201 0 +0 1317 0 +0 1437 0 +0 1560 0 +0 1685 0 +0 1812 0 +0 1940 0 +0 2069 0 +0 2199 0 +0 2330 0 +0 2460 0 +0 2592 0 +0 2723 0 +0 2855 0 +0 2986 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +1418 447 1160 +1413 468 1153 +1406 494 1143 +1396 528 1129 +1382 568 1111 +1363 618 1084 +1336 677 1046 +1298 745 990 +1241 822 902 +1151 909 748 +994 1004 399 +631 1106 0 +0 1214 0 +0 1328 0 +0 1446 0 +0 1567 0 +0 1690 0 +0 1816 0 +0 1943 0 +0 2072 0 +0 2201 0 +0 2331 0 +0 2461 0 +0 2592 0 +0 2724 0 +0 2855 0 +0 2987 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +1557 537 1288 +1553 554 1283 +1548 576 1275 +1540 604 1265 +1531 639 1251 +1517 681 1232 +1498 733 1205 +1471 793 1166 +1433 864 1108 +1377 944 1017 +1288 1032 857 +1133 1129 478 +778 1232 0 +0 1342 0 +0 1456 0 +0 1575 0 +0 1697 0 +0 1821 0 +0 1947 0 +0 2074 0 +0 2203 0 +0 2332 0 +0 2463 0 +0 2593 0 +0 2724 0 +0 2855 0 +0 2987 0 +0 3119 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +1694 634 1417 +1691 648 1413 +1687 666 1408 +1682 689 1400 +1675 718 1390 +1665 754 1376 +1651 798 1356 +1632 851 1329 +1606 914 1289 +1568 986 1230 +1512 1067 1136 +1424 1157 970 +1270 1255 567 +921 1360 0 +0 1471 0 +0 1586 0 +0 1705 0 +0 1827 0 +0 1952 0 +0 2078 0 +0 2206 0 +0 2334 0 +0 2464 0 +0 2594 0 +0 2725 0 +0 2856 0 +0 2987 0 +0 3119 0 +0 3251 0 +0 3382 0 +0 3514 0 +0 3646 0 +1830 738 1547 +1828 750 1544 +1825 764 1540 +1821 783 1534 +1815 806 1527 +1808 836 1516 +1798 873 1502 +1785 919 1482 +1766 973 1454 +1740 1037 1414 +1702 1110 1354 +1646 1193 1258 +1558 1284 1088 +1406 1383 663 +1061 1489 0 +0 1600 0 +0 1716 0 +0 1836 0 +0 1958 0 +0 2083 0 +0 2209 0 +0 2337 0 +0 2466 0 +0 2596 0 +0 2726 0 +0 2857 0 +0 2988 0 +0 3119 0 +0 3251 0 +0 3383 0 +0 3514 0 +0 3646 0 +1965 849 1678 +1963 857 1675 +1961 869 1672 +1958 884 1668 +1954 903 1662 +1949 927 1655 +1941 958 1644 +1932 996 1630 +1918 1042 1610 +1899 1097 1582 +1873 1162 1541 +1835 1237 1480 +1780 1320 1383 +1692 1412 1209 +1541 1512 766 +1199 1618 0 +0 1730 0 +0 1847 0 +0 1966 0 +0 2089 0 +0 2214 0 +0 2341 0 +0 2469 0 +0 2598 0 +0 2728 0 +0 2858 0 +0 2989 0 +0 3120 0 +0 3251 0 +0 3383 0 +0 3515 0 +0 3646 0 +2099 964 1809 +2098 970 1807 +2096 979 1804 +2094 991 1801 +2091 1006 1797 +2087 1026 1791 +2082 1051 1784 +2074 1082 1773 +2065 1120 1759 +2051 1167 1738 +2032 1224 1710 +2006 1289 1669 +1969 1364 1607 +1913 1449 1509 +1826 1542 1333 +1675 1642 876 +1335 1749 0 +0 1861 0 +0 1978 0 +0 2098 0 +0 2221 0 +0 2346 0 +0 2473 0 +0 2601 0 +0 2730 0 +0 2860 0 +0 2990 0 +0 3121 0 +0 3252 0 +0 3383 0 +0 3515 0 +0 3647 0 +2232 1083 1940 +2231 1088 1938 +2230 1095 1937 +2229 1104 1934 +2226 1116 1931 +2224 1131 1927 +2220 1151 1921 +2214 1176 1913 +2207 1208 1903 +2197 1247 1888 +2184 1294 1868 +2165 1351 1839 +2139 1417 1798 +2101 1493 1736 +2046 1578 1637 +1959 1671 1459 +1809 1772 990 +1470 1879 0 +0 1992 0 +0 2109 0 +0 2229 0 +0 2352 0 +0 2478 0 +0 2604 0 +0 2733 0 +0 2862 0 +0 2992 0 +0 3122 0 +0 3253 0 +0 3384 0 +0 3516 0 +0 3647 0 +2366 1204 2071 +2365 1208 2070 +2364 1214 2069 +2363 1221 2067 +2361 1230 2065 +2359 1242 2062 +2356 1258 2057 +2352 1278 2052 +2347 1303 2044 +2340 1335 2033 +2330 1375 2018 +2316 1423 1998 +2298 1480 1969 +2272 1547 1928 +2234 1623 1865 +2179 1708 1766 +2092 1802 1586 +1942 1903 1108 +1605 2010 0 +0 2123 0 +0 2240 0 +0 2361 0 +0 2484 0 +0 2609 0 +0 2736 0 +0 2865 0 +0 2994 0 +0 3124 0 +0 3254 0 +0 3385 0 +0 3516 0 +0 3648 0 +2498 1329 2203 +2498 1332 2202 +2497 1336 2201 +2496 1341 2200 +2495 1348 2198 +2494 1358 2196 +2491 1370 2192 +2488 1385 2188 +2485 1406 2182 +2479 1431 2175 +2472 1464 2164 +2462 1504 2149 +2449 1552 2129 +2430 1609 2100 +2404 1677 2058 +2367 1753 1995 +2311 1839 1896 +2225 1933 1714 +2075 2034 1230 +1739 2142 0 +0 2255 0 +0 2372 0 +0 2492 0 +0 2616 0 +0 2741 0 +0 2868 0 +0 2997 0 +0 3126 0 +0 3256 0 +0 3386 0 +0 3517 0 +0 3648 0 +2631 1455 2334 +2631 1457 2334 +2630 1460 2333 +2630 1464 2332 +2629 1470 2331 +2628 1477 2329 +2626 1486 2327 +2624 1499 2324 +2621 1514 2319 +2617 1535 2313 +2612 1561 2306 +2604 1593 2295 +2595 1633 2280 +2581 1682 2260 +2563 1740 2231 +2537 1807 2189 +2499 1884 2126 +2444 1970 2026 +2357 2064 1844 +2207 2165 1354 +1872 2273 0 +0 2386 0 +0 2504 0 +0 2624 0 +0 2748 0 +0 2873 0 +0 3000 0 +0 3129 0 +0 3258 0 +0 3388 0 +0 3518 0 +0 3649 0 +2764 1583 2466 +2763 1584 2466 +2763 1587 2465 +2763 1590 2464 +2762 1594 2464 +2761 1599 2462 +2760 1607 2460 +2758 1616 2458 +2756 1628 2455 +2753 1644 2451 +2749 1665 2445 +2744 1691 2437 +2737 1723 2426 +2727 1764 2411 +2714 1812 2391 +2695 1870 2362 +2669 1938 2320 +2631 2015 2257 +2576 2101 2156 +2490 2195 1974 +2340 2297 1480 +2005 2405 0 +0 2518 0 +0 2635 0 +0 2756 0 +0 2880 0 +0 3005 0 +0 3132 0 +0 3261 0 +0 3390 0 +0 3520 0 +0 3650 0 +2896 1711 2598 +2896 1713 2598 +2896 1714 2597 +2895 1717 2597 +2895 1720 2596 +2894 1724 2595 +2893 1730 2594 +2892 1737 2592 +2890 1746 2590 +2888 1759 2586 +2885 1775 2582 +2881 1795 2576 +2876 1821 2568 +2869 1854 2558 +2859 1894 2543 +2846 1943 2522 +2827 2001 2493 +2801 2069 2451 +2764 2146 2388 +2708 2232 2288 +2622 2327 2104 +2472 2429 1608 +2138 2537 0 +0 2650 0 +0 2767 0 +0 2888 0 +0 3012 0 +0 3137 0 +0 3264 0 +0 3393 0 +0 3522 0 +0 3652 0 +3029 1841 2730 +3028 1842 2730 +3028 1843 2729 +3028 1845 2729 +3028 1847 2728 +3027 1851 2728 +3026 1855 2727 +3025 1860 2725 +3024 1867 2724 +3023 1877 2721 +3020 1889 2718 +3018 1905 2714 +3014 1926 2708 +3008 1952 2700 +3001 1985 2689 +2991 2025 2675 +2978 2074 2654 +2959 2133 2625 +2933 2200 2583 +2896 2278 2520 +2841 2364 2419 +2754 2459 2235 +2605 2560 1736 +2271 2668 0 +0 2782 0 +0 2899 0 +0 3020 0 +0 3144 0 +0 3269 0 +0 3396 0 +0 3525 0 +0 3654 0 +3161 1971 2862 +3161 1972 2862 +3161 1973 2862 +3160 1974 2861 +3160 1976 2861 +3160 1978 2860 +3159 1981 2860 +3159 1986 2859 +3158 1991 2857 +3156 1998 2856 +3155 2008 2853 +3153 2020 2850 +3150 2036 2846 +3146 2057 2840 +3141 2083 2832 +3133 2116 2821 +3124 2157 2806 +3110 2206 2786 +3092 2264 2757 +3066 2332 2715 +3028 2409 2651 +2973 2496 2550 +2886 2590 2366 +2737 2692 1866 +2403 2800 0 +0 2914 0 +0 3031 0 +0 3152 0 +0 3276 0 +0 3401 0 +0 3528 0 +0 3657 0 +3293 2102 2994 +3293 2102 2994 +3293 2103 2994 +3293 2104 2993 +3292 2105 2993 +3292 2107 2993 +3292 2110 2992 +3291 2113 2991 +3291 2117 2990 +3290 2122 2989 +3289 2130 2987 +3287 2139 2985 +3285 2152 2982 +3282 2168 2978 +3278 2188 2972 +3273 2215 2964 +3266 2248 2953 +3256 2288 2938 +3242 2337 2918 +3224 2396 2888 +3198 2464 2846 +3160 2541 2783 +3105 2628 2682 +3019 2722 2498 +2869 2824 1996 +2536 2932 0 +0 3046 0 +0 3163 0 +0 3284 0 +0 3408 0 +0 3533 0 +0 3660 0 +3425 2233 3126 +3425 2233 3126 +3425 2234 3126 +3425 2235 3126 +3425 2236 3125 +3425 2237 3125 +3424 2239 3125 +3424 2241 3124 +3423 2244 3123 +3423 2248 3122 +3422 2254 3121 +3421 2261 3119 +3419 2271 3117 +3417 2283 3114 +3414 2299 3109 +3410 2320 3104 +3405 2346 3096 +3398 2379 3085 +3388 2420 3070 +3375 2469 3049 +3356 2527 3020 +3330 2595 2978 +3293 2673 2915 +3237 2759 2814 +3151 2854 2629 +3002 2956 2126 +2668 3064 0 +0 3178 0 +0 3295 0 +0 3416 0 +0 3540 0 +0 3665 0 +3557 2364 3258 +3557 2365 3258 +3557 2365 3258 +3557 2365 3258 +3557 2366 3258 +3557 2367 3257 +3557 2369 3257 +3556 2370 3257 +3556 2373 3256 +3556 2376 3255 +3555 2380 3254 +3554 2386 3253 +3553 2393 3251 +3551 2402 3249 +3549 2415 3246 +3546 2431 3241 +3542 2452 3236 +3537 2478 3228 +3530 2511 3217 +3520 2552 3202 +3507 2601 3181 +3488 2659 3152 +3462 2727 3110 +3425 2805 3047 +3369 2891 2946 +3283 2986 2761 +3134 3088 2257 +2800 3196 0 +0 3310 0 +0 3427 0 +0 3548 0 +0 3672 0 +3690 2496 3390 +3690 2496 3390 +3690 2496 3390 +3689 2497 3390 +3689 2497 3390 +3689 2498 3390 +3689 2499 3389 +3689 2500 3389 +3689 2502 3389 +3688 2504 3388 +3688 2508 3387 +3687 2512 3386 +3686 2517 3385 +3685 2525 3383 +3683 2534 3381 +3681 2547 3378 +3678 2563 3373 +3674 2583 3368 +3669 2610 3360 +3662 2643 3349 +3652 2683 3334 +3639 2733 3313 +3620 2791 3284 +3594 2859 3242 +3557 2937 3179 +3501 3023 3078 +3415 3118 2893 +3266 3220 2389 +2932 3328 0 +0 3442 0 +0 3559 0 +0 3680 0 +3822 2627 3522 +3822 2628 3522 +3822 2628 3522 +3822 2628 3522 +3822 2628 3522 +3821 2629 3522 +3821 2630 3522 +3821 2631 3521 +3821 2632 3521 +3821 2634 3521 +3820 2636 3520 +3820 2639 3519 +3819 2644 3518 +3818 2649 3517 +3817 2656 3515 +3815 2666 3513 +3813 2678 3510 +3810 2695 3505 +3806 2715 3500 +3801 2742 3492 +3794 2775 3481 +3784 2815 3466 +3771 2865 3445 +3752 2923 3416 +3726 2991 3374 +3689 3069 3311 +3634 3155 3210 +3547 3250 3025 +3398 3352 2520 +3065 3460 0 +0 3574 0 +0 3691 0 +3954 2759 3654 +3954 2759 3654 +3954 2759 3654 +3954 2760 3654 +3954 2760 3654 +3954 2760 3654 +3954 2761 3654 +3953 2762 3654 +3953 2763 3653 +3953 2764 3653 +3953 2766 3653 +3952 2768 3652 +3952 2771 3651 +3951 2775 3650 +3950 2781 3649 +3949 2788 3647 +3948 2798 3645 +3945 2810 3642 +3943 2826 3637 +3939 2847 3632 +3933 2874 3624 +3926 2907 3613 +3916 2947 3598 +3903 2997 3577 +3884 3055 3548 +3858 3123 3506 +3821 3201 3443 +3766 3287 3342 +3679 3382 3157 +3530 3484 2652 +3197 3593 0 +0 3706 0 +4086 2891 3786 +4086 2891 3786 +4086 2891 3786 +4086 2891 3786 +4086 2892 3786 +4086 2892 3786 +4086 2892 3786 +4086 2893 3786 +4086 2894 3786 +4085 2895 3785 +4085 2896 3785 +4085 2898 3785 +4085 2900 3784 +4084 2903 3783 +4083 2907 3782 +4082 2913 3781 +4081 2920 3779 +4080 2930 3777 +4078 2942 3774 +4075 2958 3770 +4071 2979 3764 +4065 3006 3756 +4058 3039 3745 +4048 3079 3730 +4035 3129 3710 +4017 3187 3680 +3990 3255 3638 +3953 3333 3575 +3898 3419 3474 +3811 3514 3289 +3662 3616 2783 +3329 3725 0 +4095 3023 3918 +4095 3023 3918 +4095 3023 3918 +4095 3023 3918 +4095 3023 3918 +4095 3024 3918 +4095 3024 3918 +4095 3024 3918 +4095 3025 3918 +4095 3026 3918 +4095 3027 3918 +4095 3028 3917 +4095 3030 3917 +4095 3032 3916 +4095 3035 3916 +4095 3039 3915 +4095 3045 3913 +4095 3052 3911 +4095 3062 3909 +4095 3074 3906 +4095 3090 3902 +4095 3111 3896 +4095 3138 3888 +4095 3171 3877 +4095 3211 3862 +4095 3261 3842 +4095 3319 3812 +4095 3387 3770 +4085 3465 3707 +4030 3552 3606 +3944 3646 3421 +3794 3748 2915 +4095 3155 4050 +4095 3155 4050 +4095 3155 4050 +4095 3155 4050 +4095 3155 4050 +4095 3155 4050 +4095 3156 4050 +4095 3156 4050 +4095 3156 4050 +4095 3157 4050 +4095 3158 4050 +4095 3159 4050 +4095 3160 4049 +4095 3162 4049 +4095 3164 4048 +4095 3167 4048 +4095 3171 4047 +4095 3177 4045 +4095 3184 4044 +4095 3194 4041 +4095 3206 4038 +4095 3222 4034 +4095 3243 4028 +4095 3270 4020 +4095 3303 4009 +4095 3343 3994 +4095 3393 3974 +4095 3451 3944 +4095 3519 3902 +4095 3597 3839 +4095 3684 3738 +4076 3778 3553 +0 108 241 +0 151 183 +0 203 91 +0 264 0 +0 334 0 +0 414 0 +0 503 0 +0 600 0 +0 704 0 +0 813 0 +0 928 0 +0 1046 0 +0 1168 0 +0 1292 0 +0 1418 0 +0 1546 0 +0 1674 0 +0 1804 0 +0 1934 0 +0 2065 0 +0 2196 0 +0 2327 0 +0 2459 0 +0 2590 0 +0 2722 0 +0 2854 0 +0 2986 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +0 123 316 +0 165 267 +0 215 193 +0 274 69 +0 343 0 +0 422 0 +0 509 0 +0 605 0 +0 708 0 +0 816 0 +0 930 0 +0 1048 0 +0 1170 0 +0 1293 0 +0 1419 0 +0 1546 0 +0 1675 0 +0 1804 0 +0 1934 0 +0 2065 0 +0 2196 0 +0 2327 0 +0 2459 0 +0 2590 0 +0 2722 0 +0 2854 0 +0 2986 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +225 143 400 +144 182 360 +6 231 300 +0 288 206 +0 355 37 +0 432 0 +0 518 0 +0 612 0 +0 713 0 +0 821 0 +0 934 0 +0 1051 0 +0 1171 0 +0 1295 0 +0 1420 0 +0 1547 0 +0 1676 0 +0 1805 0 +0 1935 0 +0 2065 0 +0 2196 0 +0 2327 0 +0 2459 0 +0 2590 0 +0 2722 0 +0 2854 0 +0 2986 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +451 167 493 +403 205 461 +331 251 413 +211 306 341 +0 371 223 +0 445 0 +0 529 0 +0 621 0 +0 720 0 +0 826 0 +0 938 0 +0 1054 0 +0 1174 0 +0 1297 0 +0 1422 0 +0 1548 0 +0 1676 0 +0 1805 0 +0 1935 0 +0 2066 0 +0 2196 0 +0 2328 0 +0 2459 0 +0 2590 0 +0 2722 0 +0 2854 0 +0 2986 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +643 198 593 +612 234 568 +567 277 531 +500 329 476 +391 391 391 +186 462 245 +0 543 0 +0 632 0 +0 730 0 +0 834 0 +0 944 0 +0 1059 0 +0 1178 0 +0 1299 0 +0 1424 0 +0 1550 0 +0 1678 0 +0 1806 0 +0 1936 0 +0 2066 0 +0 2197 0 +0 2328 0 +0 2459 0 +0 2591 0 +0 2722 0 +0 2854 0 +0 2986 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +815 237 700 +794 269 680 +765 310 651 +722 358 610 +658 417 548 +556 484 450 +369 561 272 +0 647 0 +0 742 0 +0 844 0 +0 952 0 +0 1065 0 +0 1182 0 +0 1303 0 +0 1426 0 +0 1552 0 +0 1679 0 +0 1808 0 +0 1937 0 +0 2067 0 +0 2197 0 +0 2328 0 +0 2459 0 +0 2591 0 +0 2722 0 +0 2854 0 +0 2986 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +974 283 813 +960 313 797 +940 350 775 +911 395 744 +870 448 699 +809 512 630 +711 585 518 +535 667 307 +81 758 0 +0 856 0 +0 962 0 +0 1073 0 +0 1188 0 +0 1308 0 +0 1430 0 +0 1555 0 +0 1681 0 +0 1809 0 +0 1938 0 +0 2068 0 +0 2198 0 +0 2329 0 +0 2460 0 +0 2591 0 +0 2723 0 +0 2854 0 +0 2986 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +1126 339 929 +1116 365 917 +1102 398 900 +1082 439 877 +1054 488 844 +1014 546 795 +954 614 720 +860 692 596 +691 778 349 +276 873 0 +0 975 0 +0 1083 0 +0 1196 0 +0 1314 0 +0 1435 0 +0 1558 0 +0 1684 0 +0 1811 0 +0 1939 0 +0 2069 0 +0 2199 0 +0 2329 0 +0 2460 0 +0 2591 0 +0 2723 0 +0 2854 0 +0 2986 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +1272 404 1049 +1265 427 1040 +1255 456 1027 +1241 492 1010 +1221 536 985 +1194 589 950 +1155 651 898 +1096 723 818 +1004 804 683 +841 894 400 +450 992 0 +0 1096 0 +0 1207 0 +0 1322 0 +0 1441 0 +0 1563 0 +0 1688 0 +0 1814 0 +0 1942 0 +0 2070 0 +0 2200 0 +0 2330 0 +0 2461 0 +0 2592 0 +0 2723 0 +0 2855 0 +0 2986 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +1415 479 1172 +1409 499 1165 +1402 523 1156 +1392 554 1143 +1378 593 1124 +1359 640 1099 +1332 696 1062 +1293 762 1008 +1235 837 923 +1145 921 778 +985 1014 461 +611 1114 0 +0 1221 0 +0 1333 0 +0 1449 0 +0 1569 0 +0 1692 0 +0 1817 0 +0 1944 0 +0 2072 0 +0 2202 0 +0 2331 0 +0 2462 0 +0 2593 0 +0 2724 0 +0 2855 0 +0 2987 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +1555 563 1298 +1551 579 1292 +1545 600 1285 +1538 627 1275 +1528 660 1262 +1514 701 1243 +1495 750 1216 +1468 809 1178 +1430 877 1122 +1373 955 1034 +1283 1041 880 +1127 1136 531 +763 1238 0 +0 1347 0 +0 1460 0 +0 1578 0 +0 1699 0 +0 1822 0 +0 1948 0 +0 2075 0 +0 2204 0 +0 2333 0 +0 2463 0 +0 2593 0 +0 2724 0 +0 2856 0 +0 2987 0 +0 3119 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +1692 656 1424 +1689 669 1420 +1685 686 1415 +1680 708 1408 +1673 736 1397 +1663 771 1384 +1649 813 1364 +1630 865 1337 +1604 926 1298 +1565 996 1240 +1509 1076 1149 +1420 1164 989 +1265 1261 610 +910 1365 0 +0 1474 0 +0 1589 0 +0 1707 0 +0 1829 0 +0 1953 0 +0 2079 0 +0 2206 0 +0 2335 0 +0 2464 0 +0 2595 0 +0 2725 0 +0 2856 0 +0 2988 0 +0 3119 0 +0 3251 0 +0 3382 0 +0 3514 0 +0 3646 0 +1828 756 1553 +1826 766 1550 +1823 780 1545 +1819 798 1540 +1814 821 1532 +1807 850 1522 +1797 886 1508 +1783 930 1488 +1764 983 1461 +1738 1046 1421 +1700 1118 1362 +1644 1199 1268 +1556 1289 1103 +1402 1387 699 +1053 1492 0 +0 1603 0 +0 1718 0 +0 1837 0 +0 1959 0 +0 2084 0 +0 2210 0 +0 2338 0 +0 2467 0 +0 2596 0 +0 2726 0 +0 2857 0 +0 2988 0 +0 3120 0 +0 3251 0 +0 3383 0 +0 3514 0 +0 3646 0 +1964 862 1682 +1962 871 1679 +1960 882 1676 +1957 896 1672 +1953 915 1667 +1948 938 1659 +1940 968 1649 +1930 1006 1634 +1917 1051 1614 +1898 1105 1586 +1872 1169 1546 +1834 1243 1486 +1778 1325 1391 +1690 1416 1220 +1538 1515 795 +1193 1621 0 +0 1732 0 +0 1848 0 +0 1968 0 +0 2090 0 +0 2215 0 +0 2341 0 +0 2469 0 +0 2598 0 +0 2728 0 +0 2858 0 +0 2989 0 +0 3120 0 +0 3252 0 +0 3383 0 +0 3515 0 +0 3646 0 +2098 974 1812 +2097 981 1810 +2095 989 1808 +2093 1001 1804 +2090 1016 1800 +2086 1035 1795 +2081 1059 1787 +2074 1090 1776 +2064 1128 1762 +2050 1174 1742 +2032 1230 1714 +2005 1294 1673 +1968 1369 1612 +1912 1452 1515 +1824 1545 1341 +1673 1644 898 +1331 1751 0 +0 1862 0 +0 1979 0 +0 2099 0 +0 2221 0 +0 2346 0 +0 2473 0 +0 2601 0 +0 2730 0 +0 2860 0 +0 2990 0 +0 3121 0 +0 3252 0 +0 3384 0 +0 3515 0 +0 3647 0 +2232 1091 1942 +2231 1096 1941 +2230 1103 1939 +2228 1111 1937 +2226 1123 1933 +2223 1138 1929 +2219 1158 1924 +2214 1183 1916 +2206 1214 1905 +2197 1253 1891 +2183 1300 1870 +2165 1356 1842 +2138 1421 1801 +2101 1497 1739 +2045 1581 1641 +1958 1674 1465 +1807 1774 1008 +1467 1881 0 +0 1993 0 +0 2110 0 +0 2230 0 +0 2353 0 +0 2478 0 +0 2605 0 +0 2733 0 +0 2862 0 +0 2992 0 +0 3122 0 +0 3253 0 +0 3384 0 +0 3516 0 +0 3647 0 +2365 1211 2073 +2364 1215 2072 +2364 1220 2071 +2362 1227 2069 +2361 1236 2066 +2359 1248 2063 +2356 1263 2059 +2352 1283 2053 +2346 1308 2046 +2339 1340 2035 +2329 1379 2020 +2316 1427 2000 +2297 1483 1971 +2271 1550 1930 +2234 1625 1868 +2178 1710 1769 +2091 1804 1591 +1941 1904 1122 +1603 2011 0 +0 2124 0 +0 2241 0 +0 2361 0 +0 2484 0 +0 2610 0 +0 2737 0 +0 2865 0 +0 2994 0 +0 3124 0 +0 3254 0 +0 3385 0 +0 3516 0 +0 3648 0 +2498 1334 2204 +2498 1337 2203 +2497 1341 2202 +2496 1346 2201 +2495 1353 2199 +2493 1362 2197 +2491 1374 2194 +2488 1390 2189 +2484 1410 2184 +2479 1435 2176 +2472 1467 2165 +2462 1507 2150 +2449 1555 2130 +2430 1612 2101 +2404 1679 2060 +2366 1755 1997 +2311 1840 1898 +2224 1934 1718 +2074 2035 1241 +1737 2142 0 +0 2255 0 +0 2372 0 +0 2493 0 +0 2616 0 +0 2741 0 +0 2868 0 +0 2997 0 +0 3126 0 +0 3256 0 +0 3386 0 +0 3517 0 +0 3648 0 +2631 1459 2335 +2631 1461 2335 +2630 1464 2334 +2629 1468 2333 +2628 1473 2332 +2627 1480 2330 +2626 1490 2328 +2624 1502 2324 +2621 1518 2320 +2617 1538 2314 +2611 1564 2307 +2604 1596 2296 +2594 1636 2281 +2581 1684 2261 +2562 1742 2232 +2536 1809 2190 +2499 1885 2128 +2443 1971 2028 +2357 2065 1846 +2207 2166 1362 +1871 2274 0 +0 2387 0 +0 2504 0 +0 2625 0 +0 2748 0 +0 2873 0 +0 3000 0 +0 3129 0 +0 3258 0 +0 3388 0 +0 3518 0 +0 3649 0 +2764 1585 2467 +2763 1587 2466 +2763 1589 2466 +2762 1593 2465 +2762 1597 2464 +2761 1602 2463 +2760 1609 2461 +2758 1618 2459 +2756 1631 2456 +2753 1647 2451 +2749 1667 2446 +2744 1693 2438 +2737 1725 2427 +2727 1765 2412 +2713 1814 2392 +2695 1872 2363 +2669 1939 2321 +2631 2016 2258 +2576 2102 2158 +2489 2196 1976 +2340 2297 1486 +2004 2405 0 +0 2518 0 +0 2636 0 +0 2756 0 +0 2880 0 +0 3005 0 +0 3132 0 +0 3261 0 +0 3390 0 +0 3520 0 +0 3650 0 +2896 1713 2599 +2896 1715 2598 +2896 1717 2598 +2895 1719 2597 +2895 1722 2597 +2894 1726 2596 +2893 1731 2594 +2892 1739 2593 +2890 1748 2590 +2888 1760 2587 +2885 1776 2583 +2881 1797 2577 +2876 1823 2569 +2869 1855 2558 +2859 1896 2544 +2846 1944 2523 +2827 2002 2494 +2801 2070 2452 +2764 2147 2389 +2708 2233 2289 +2622 2327 2106 +2472 2429 1612 +2137 2537 0 +0 2650 0 +0 2767 0 +0 2888 0 +0 3012 0 +0 3137 0 +0 3264 0 +0 3393 0 +0 3522 0 +0 3652 0 +3028 1843 2730 +3028 1844 2730 +3028 1845 2730 +3028 1847 2729 +3027 1849 2729 +3027 1852 2728 +3026 1856 2727 +3025 1862 2726 +3024 1869 2724 +3023 1878 2722 +3020 1891 2719 +3017 1907 2714 +3014 1927 2708 +3008 1953 2701 +3001 1986 2690 +2991 2026 2675 +2978 2075 2654 +2959 2133 2625 +2933 2201 2583 +2896 2278 2520 +2840 2364 2420 +2754 2459 2236 +2605 2561 1740 +2270 2669 0 +0 2782 0 +0 2899 0 +0 3020 0 +0 3144 0 +0 3269 0 +0 3396 0 +0 3525 0 +0 3654 0 +3161 1972 2862 +3161 1973 2862 +3160 1974 2862 +3160 1975 2862 +3160 1977 2861 +3160 1980 2861 +3159 1983 2860 +3158 1987 2859 +3158 1992 2858 +3156 1999 2856 +3155 2009 2853 +3153 2021 2850 +3150 2037 2846 +3146 2058 2840 +3140 2084 2832 +3133 2117 2821 +3124 2157 2807 +3110 2206 2786 +3092 2265 2757 +3065 2333 2715 +3028 2410 2652 +2973 2496 2551 +2886 2591 2367 +2737 2692 1868 +2403 2801 0 +0 2914 0 +0 3031 0 +0 3152 0 +0 3276 0 +0 3401 0 +0 3528 0 +0 3657 0 +3293 2103 2994 +3293 2103 2994 +3293 2104 2994 +3293 2105 2994 +3292 2106 2993 +3292 2108 2993 +3292 2110 2992 +3291 2114 2992 +3291 2118 2991 +3290 2123 2989 +3289 2130 2988 +3287 2140 2985 +3285 2152 2982 +3282 2168 2978 +3278 2189 2972 +3273 2215 2964 +3265 2248 2953 +3256 2289 2938 +3242 2338 2918 +3224 2396 2889 +3198 2464 2847 +3160 2541 2784 +3105 2628 2682 +3019 2722 2498 +2869 2824 1998 +2535 2932 0 +0 3046 0 +0 3163 0 +0 3284 0 +0 3408 0 +0 3533 0 +0 3660 0 +3425 2234 3126 +3425 2234 3126 +3425 2235 3126 +3425 2235 3126 +3425 2236 3126 +3425 2238 3125 +3424 2239 3125 +3424 2242 3124 +3423 2245 3124 +3423 2249 3123 +3422 2255 3121 +3421 2262 3119 +3419 2271 3117 +3417 2284 3114 +3414 2300 3110 +3410 2320 3104 +3405 2347 3096 +3398 2380 3085 +3388 2420 3070 +3374 2469 3050 +3356 2528 3021 +3330 2596 2978 +3292 2673 2915 +3237 2760 2814 +3151 2854 2630 +3001 2956 2128 +2668 3064 0 +0 3178 0 +0 3295 0 +0 3416 0 +0 3540 0 +0 3665 0 +3557 2365 3258 +3557 2365 3258 +3557 2365 3258 +3557 2366 3258 +3557 2367 3258 +3557 2368 3257 +3557 2369 3257 +3556 2371 3257 +3556 2373 3256 +3556 2376 3255 +3555 2380 3254 +3554 2386 3253 +3553 2393 3251 +3551 2403 3249 +3549 2415 3246 +3546 2431 3242 +3542 2452 3236 +3537 2478 3228 +3530 2511 3217 +3520 2552 3202 +3507 2601 3182 +3488 2660 3152 +3462 2728 3110 +3425 2805 3047 +3369 2892 2946 +3283 2986 2761 +3134 3088 2258 +2800 3196 0 +0 3310 0 +0 3427 0 +0 3548 0 +0 3672 0 +3690 2496 3390 +3690 2496 3390 +3689 2497 3390 +3689 2497 3390 +3689 2498 3390 +3689 2498 3390 +3689 2499 3389 +3689 2501 3389 +3689 2502 3389 +3688 2505 3388 +3688 2508 3387 +3687 2512 3386 +3686 2518 3385 +3685 2525 3383 +3683 2534 3381 +3681 2547 3378 +3678 2563 3374 +3674 2584 3368 +3669 2610 3360 +3662 2643 3349 +3652 2684 3334 +3639 2733 3314 +3620 2791 3284 +3594 2859 3242 +3557 2937 3179 +3501 3023 3078 +3415 3118 2893 +3266 3220 2389 +2932 3328 0 +0 3442 0 +0 3559 0 +0 3680 0 +3822 2628 3522 +3822 2628 3522 +3822 2628 3522 +3822 2628 3522 +3822 2629 3522 +3821 2629 3522 +3821 2630 3522 +3821 2631 3521 +3821 2632 3521 +3821 2634 3521 +3820 2637 3520 +3820 2640 3519 +3819 2644 3518 +3818 2649 3517 +3817 2657 3515 +3815 2666 3513 +3813 2679 3510 +3810 2695 3506 +3806 2716 3500 +3801 2742 3492 +3794 2775 3481 +3784 2816 3466 +3771 2865 3446 +3752 2923 3416 +3726 2991 3374 +3689 3069 3311 +3634 3155 3210 +3547 3250 3025 +3398 3352 2521 +3064 3460 0 +0 3574 0 +0 3691 0 +3954 2759 3654 +3954 2759 3654 +3954 2760 3654 +3954 2760 3654 +3954 2760 3654 +3954 2761 3654 +3954 2761 3654 +3953 2762 3654 +3953 2763 3653 +3953 2764 3653 +3953 2766 3653 +3952 2768 3652 +3952 2772 3651 +3951 2776 3650 +3950 2781 3649 +3949 2788 3647 +3948 2798 3645 +3945 2811 3642 +3943 2827 3638 +3939 2847 3632 +3933 2874 3624 +3926 2907 3613 +3916 2947 3598 +3903 2997 3578 +3884 3055 3548 +3858 3123 3506 +3821 3201 3443 +3766 3287 3342 +3679 3382 3157 +3530 3484 2652 +3197 3593 0 +0 3706 0 +4086 2891 3786 +4086 2891 3786 +4086 2891 3786 +4086 2891 3786 +4086 2892 3786 +4086 2892 3786 +4086 2892 3786 +4086 2893 3786 +4086 2894 3786 +4085 2895 3786 +4085 2896 3785 +4085 2898 3785 +4085 2900 3784 +4084 2903 3784 +4083 2908 3783 +4082 2913 3781 +4081 2920 3779 +4080 2930 3777 +4078 2942 3774 +4075 2959 3770 +4071 2979 3764 +4065 3006 3756 +4058 3039 3745 +4048 3079 3730 +4035 3129 3710 +4017 3187 3680 +3990 3255 3638 +3953 3333 3575 +3898 3420 3474 +3811 3514 3289 +3662 3616 2784 +3329 3725 0 +4095 3023 3918 +4095 3023 3918 +4095 3023 3918 +4095 3023 3918 +4095 3023 3918 +4095 3024 3918 +4095 3024 3918 +4095 3024 3918 +4095 3025 3918 +4095 3026 3918 +4095 3027 3918 +4095 3028 3917 +4095 3030 3917 +4095 3032 3916 +4095 3035 3916 +4095 3040 3915 +4095 3045 3913 +4095 3052 3912 +4095 3062 3909 +4095 3074 3906 +4095 3091 3902 +4095 3111 3896 +4095 3138 3888 +4095 3171 3877 +4095 3211 3862 +4095 3261 3842 +4095 3319 3812 +4095 3387 3770 +4085 3465 3707 +4030 3552 3606 +3944 3646 3421 +3794 3748 2916 +4095 3155 4051 +4095 3155 4050 +4095 3155 4050 +4095 3155 4050 +4095 3155 4050 +4095 3155 4050 +4095 3156 4050 +4095 3156 4050 +4095 3156 4050 +4095 3157 4050 +4095 3158 4050 +4095 3159 4050 +4095 3160 4049 +4095 3162 4049 +4095 3164 4048 +4095 3167 4048 +4095 3172 4047 +4095 3177 4045 +4095 3184 4044 +4095 3194 4041 +4095 3206 4038 +4095 3223 4034 +4095 3243 4028 +4095 3270 4020 +4095 3303 4009 +4095 3343 3994 +4095 3393 3974 +4095 3451 3945 +4095 3519 3902 +4095 3597 3839 +4095 3684 3738 +4076 3778 3553 +0 193 352 +0 229 307 +0 273 239 +0 326 129 +0 388 0 +0 459 0 +0 540 0 +0 630 0 +0 728 0 +0 833 0 +0 943 0 +0 1058 0 +0 1177 0 +0 1299 0 +0 1423 0 +0 1550 0 +0 1677 0 +0 1806 0 +0 1936 0 +0 2066 0 +0 2197 0 +0 2328 0 +0 2459 0 +0 2591 0 +0 2722 0 +0 2854 0 +0 2986 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +0 205 412 +0 240 373 +0 283 315 +0 335 223 +0 396 62 +0 466 0 +0 546 0 +0 635 0 +0 732 0 +0 836 0 +0 945 0 +0 1060 0 +0 1178 0 +0 1300 0 +0 1424 0 +0 1550 0 +0 1678 0 +0 1807 0 +0 1936 0 +0 2066 0 +0 2197 0 +0 2328 0 +0 2459 0 +0 2591 0 +0 2722 0 +0 2854 0 +0 2986 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +154 222 481 +58 255 448 +0 297 399 +0 347 325 +0 407 201 +0 476 0 +0 554 0 +0 641 0 +0 737 0 +0 840 0 +0 949 0 +0 1062 0 +0 1180 0 +0 1302 0 +0 1425 0 +0 1551 0 +0 1679 0 +0 1807 0 +0 1936 0 +0 2066 0 +0 2197 0 +0 2328 0 +0 2459 0 +0 2591 0 +0 2722 0 +0 2854 0 +0 2986 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +409 242 560 +357 275 532 +276 315 492 +138 363 433 +0 420 338 +0 488 170 +0 564 0 +0 650 0 +0 744 0 +0 845 0 +0 953 0 +0 1066 0 +0 1183 0 +0 1304 0 +0 1427 0 +0 1552 0 +0 1679 0 +0 1808 0 +0 1937 0 +0 2067 0 +0 2197 0 +0 2328 0 +0 2459 0 +0 2591 0 +0 2722 0 +0 2854 0 +0 2986 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +616 269 648 +583 299 625 +535 337 593 +463 383 546 +343 438 474 +109 503 355 +0 577 124 +0 661 0 +0 753 0 +0 852 0 +0 958 0 +0 1070 0 +0 1186 0 +0 1306 0 +0 1429 0 +0 1554 0 +0 1681 0 +0 1809 0 +0 1938 0 +0 2067 0 +0 2198 0 +0 2328 0 +0 2460 0 +0 2591 0 +0 2723 0 +0 2854 0 +0 2986 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +796 302 744 +775 330 726 +744 366 700 +700 409 663 +632 461 608 +523 523 523 +318 594 377 +0 675 54 +0 764 0 +0 862 0 +0 966 0 +0 1076 0 +0 1191 0 +0 1310 0 +0 1432 0 +0 1556 0 +0 1682 0 +0 1810 0 +0 1938 0 +0 2068 0 +0 2198 0 +0 2329 0 +0 2460 0 +0 2591 0 +0 2723 0 +0 2854 0 +0 2986 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +962 343 847 +947 369 832 +926 401 812 +897 442 784 +854 490 742 +790 549 680 +688 616 582 +501 693 404 +0 780 0 +0 874 0 +0 976 0 +0 1084 0 +0 1197 0 +0 1314 0 +0 1435 0 +0 1559 0 +0 1684 0 +0 1811 0 +0 1940 0 +0 2069 0 +0 2199 0 +0 2329 0 +0 2460 0 +0 2591 0 +0 2723 0 +0 2854 0 +0 2986 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +1117 392 956 +1107 415 945 +1092 445 929 +1072 482 907 +1043 527 876 +1002 581 831 +941 644 762 +843 717 650 +667 799 439 +213 890 0 +0 988 0 +0 1094 0 +0 1205 0 +0 1320 0 +0 1440 0 +0 1562 0 +0 1687 0 +0 1813 0 +0 1941 0 +0 2070 0 +0 2200 0 +0 2330 0 +0 2461 0 +0 2592 0 +0 2723 0 +0 2855 0 +0 2986 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +1266 450 1070 +1258 471 1061 +1248 497 1049 +1234 530 1032 +1214 571 1009 +1186 620 976 +1146 678 927 +1086 746 852 +992 824 728 +824 910 481 +408 1005 0 +0 1107 0 +0 1215 0 +0 1328 0 +0 1446 0 +0 1567 0 +0 1690 0 +0 1816 0 +0 1943 0 +0 2072 0 +0 2201 0 +0 2331 0 +0 2461 0 +0 2592 0 +0 2724 0 +0 2855 0 +0 2987 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +1410 519 1188 +1405 536 1182 +1397 559 1172 +1387 588 1160 +1373 624 1142 +1353 668 1117 +1326 721 1082 +1287 783 1030 +1228 855 950 +1136 936 815 +973 1026 532 +582 1124 0 +0 1229 0 +0 1339 0 +0 1454 0 +0 1573 0 +0 1695 0 +0 1820 0 +0 1946 0 +0 2074 0 +0 2202 0 +0 2332 0 +0 2462 0 +0 2593 0 +0 2724 0 +0 2855 0 +0 2987 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +1551 596 1310 +1547 611 1305 +1542 631 1297 +1534 655 1288 +1524 687 1275 +1510 725 1256 +1491 772 1231 +1464 828 1194 +1425 894 1140 +1367 969 1055 +1277 1053 910 +1117 1146 593 +743 1246 0 +0 1353 0 +0 1465 0 +0 1581 0 +0 1702 0 +0 1824 0 +0 1950 0 +0 2076 0 +0 2205 0 +0 2334 0 +0 2463 0 +0 2594 0 +0 2725 0 +0 2856 0 +0 2987 0 +0 3119 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +1690 683 1434 +1687 695 1430 +1683 711 1424 +1677 732 1417 +1670 759 1407 +1660 792 1394 +1646 833 1375 +1627 882 1348 +1600 941 1310 +1562 1009 1254 +1505 1087 1166 +1415 1173 1013 +1259 1268 663 +895 1370 0 +0 1479 0 +0 1592 0 +0 1710 0 +0 1831 0 +0 1954 0 +0 2080 0 +0 2207 0 +0 2336 0 +0 2465 0 +0 2595 0 +0 2726 0 +0 2856 0 +0 2988 0 +0 3119 0 +0 3251 0 +0 3382 0 +0 3514 0 +0 3646 0 +1826 777 1560 +1824 788 1557 +1821 801 1552 +1817 818 1547 +1812 840 1540 +1805 868 1530 +1795 903 1516 +1781 945 1496 +1762 997 1469 +1736 1058 1430 +1697 1128 1372 +1641 1208 1281 +1552 1296 1121 +1397 1393 742 +1042 1497 0 +0 1606 0 +0 1721 0 +0 1839 0 +0 1961 0 +0 2085 0 +0 2211 0 +0 2338 0 +0 2467 0 +0 2597 0 +0 2727 0 +0 2857 0 +0 2988 0 +0 3120 0 +0 3251 0 +0 3383 0 +0 3514 0 +0 3646 0 +1962 880 1687 +1961 888 1685 +1958 898 1682 +1955 912 1678 +1951 930 1672 +1946 953 1664 +1939 982 1654 +1929 1018 1640 +1915 1062 1620 +1897 1116 1593 +1870 1178 1553 +1832 1250 1494 +1776 1331 1400 +1688 1422 1235 +1534 1520 831 +1185 1624 0 +0 1735 0 +0 1850 0 +0 1969 0 +0 2091 0 +0 2216 0 +0 2342 0 +0 2470 0 +0 2599 0 +0 2728 0 +0 2859 0 +0 2989 0 +0 3120 0 +0 3252 0 +0 3383 0 +0 3515 0 +0 3647 0 +2097 988 1815 +2096 994 1814 +2094 1003 1811 +2092 1014 1808 +2089 1028 1804 +2085 1047 1799 +2080 1071 1791 +2072 1100 1781 +2063 1138 1766 +2049 1183 1746 +2030 1237 1719 +2004 1301 1678 +1966 1375 1618 +1910 1457 1523 +1822 1548 1352 +1670 1647 927 +1325 1753 0 +0 1864 0 +0 1980 0 +0 2100 0 +0 2222 0 +0 2347 0 +0 2474 0 +0 2601 0 +0 2730 0 +0 2860 0 +0 2990 0 +0 3121 0 +0 3252 0 +0 3384 0 +0 3515 0 +0 3647 0 +2231 1101 1945 +2230 1106 1944 +2229 1113 1942 +2227 1122 1940 +2225 1133 1936 +2222 1148 1932 +2218 1167 1927 +2213 1191 1919 +2206 1222 1908 +2196 1260 1894 +2182 1306 1874 +2164 1362 1846 +2137 1427 1805 +2100 1501 1744 +2044 1585 1647 +1956 1677 1473 +1805 1776 1031 +1463 1883 0 +0 1994 0 +0 2111 0 +0 2231 0 +0 2353 0 +0 2478 0 +0 2605 0 +0 2733 0 +0 2862 0 +0 2992 0 +0 3122 0 +0 3253 0 +0 3384 0 +0 3516 0 +0 3647 0 +2364 1219 2075 +2364 1223 2074 +2363 1228 2073 +2362 1235 2071 +2360 1244 2069 +2358 1255 2066 +2355 1270 2061 +2351 1290 2056 +2346 1315 2048 +2339 1346 2037 +2329 1385 2023 +2315 1432 2003 +2297 1488 1974 +2270 1553 1933 +2233 1629 1871 +2177 1713 1773 +2090 1806 1597 +1939 1906 1140 +1599 2013 0 +0 2125 0 +0 2242 0 +0 2362 0 +0 2485 0 +0 2610 0 +0 2737 0 +0 2865 0 +0 2994 0 +0 3124 0 +0 3254 0 +0 3385 0 +0 3516 0 +0 3648 0 +2498 1340 2206 +2497 1343 2205 +2497 1347 2204 +2496 1352 2203 +2494 1359 2201 +2493 1368 2199 +2491 1380 2195 +2488 1395 2191 +2484 1415 2185 +2478 1440 2178 +2471 1472 2167 +2461 1511 2152 +2448 1559 2132 +2429 1615 2103 +2403 1682 2062 +2366 1757 2000 +2310 1842 1901 +2223 1936 1723 +2073 2036 1254 +1735 2144 0 +0 2256 0 +0 2373 0 +0 2493 0 +0 2616 0 +0 2742 0 +0 2869 0 +0 2997 0 +0 3126 0 +0 3256 0 +0 3386 0 +0 3517 0 +0 3648 0 +2631 1463 2337 +2630 1466 2336 +2630 1469 2335 +2629 1473 2334 +2628 1478 2333 +2627 1485 2331 +2625 1494 2329 +2623 1506 2326 +2620 1522 2322 +2616 1542 2316 +2611 1567 2308 +2604 1599 2297 +2594 1639 2283 +2581 1687 2262 +2562 1744 2233 +2536 1811 2192 +2498 1887 2130 +2443 1972 2030 +2356 2066 1850 +2206 2167 1373 +1869 2275 0 +0 2387 0 +0 2504 0 +0 2625 0 +0 2748 0 +0 2874 0 +0 3001 0 +0 3129 0 +0 3258 0 +0 3388 0 +0 3518 0 +0 3649 0 +2763 1589 2468 +2763 1591 2467 +2763 1593 2467 +2762 1596 2466 +2761 1600 2465 +2761 1605 2464 +2759 1613 2462 +2758 1622 2460 +2756 1634 2457 +2753 1650 2452 +2749 1670 2447 +2743 1696 2439 +2736 1728 2428 +2727 1768 2413 +2713 1816 2393 +2694 1874 2364 +2668 1941 2322 +2631 2017 2260 +2575 2103 2160 +2489 2197 1978 +2339 2298 1494 +2003 2406 0 +0 2519 0 +0 2636 0 +0 2757 0 +0 2880 0 +0 3005 0 +0 3132 0 +0 3261 0 +0 3390 0 +0 3520 0 +0 3650 0 +2896 1716 2599 +2896 1717 2599 +2895 1719 2599 +2895 1722 2598 +2894 1725 2597 +2894 1729 2596 +2893 1734 2595 +2892 1741 2593 +2890 1751 2591 +2888 1763 2588 +2885 1779 2583 +2881 1799 2578 +2876 1825 2570 +2869 1857 2559 +2859 1897 2544 +2845 1946 2524 +2827 2004 2495 +2801 2071 2453 +2763 2148 2390 +2708 2234 2290 +2621 2328 2108 +2472 2430 1618 +2136 2537 0 +0 2650 0 +0 2768 0 +0 2888 0 +0 3012 0 +0 3137 0 +0 3264 0 +0 3393 0 +0 3522 0 +0 3652 0 +3028 1845 2731 +3028 1846 2731 +3028 1847 2730 +3028 1849 2730 +3027 1851 2729 +3027 1854 2729 +3026 1858 2728 +3025 1864 2726 +3024 1871 2725 +3022 1880 2722 +3020 1892 2719 +3017 1908 2715 +3013 1929 2709 +3008 1955 2701 +3001 1987 2690 +2991 2028 2676 +2978 2076 2655 +2959 2134 2626 +2933 2202 2584 +2896 2279 2521 +2840 2365 2421 +2754 2459 2238 +2604 2561 1744 +2269 2669 0 +0 2782 0 +0 2900 0 +0 3020 0 +0 3144 0 +0 3269 0 +0 3396 0 +0 3525 0 +0 3654 0 +3161 1974 2863 +3161 1975 2862 +3160 1976 2862 +3160 1977 2862 +3160 1979 2862 +3160 1981 2861 +3159 1984 2860 +3158 1988 2859 +3157 1994 2858 +3156 2001 2856 +3155 2010 2854 +3152 2023 2851 +3150 2039 2846 +3146 2059 2841 +3140 2085 2833 +3133 2118 2822 +3123 2158 2807 +3110 2207 2787 +3091 2266 2758 +3065 2333 2716 +3028 2410 2653 +2973 2497 2552 +2886 2591 2368 +2737 2693 1872 +2402 2801 0 +0 2914 0 +0 3031 0 +0 3152 0 +0 3276 0 +0 3401 0 +0 3528 0 +0 3657 0 +3293 2104 2994 +3293 2104 2994 +3293 2105 2994 +3293 2106 2994 +3292 2107 2994 +3292 2109 2993 +3292 2112 2993 +3291 2115 2992 +3291 2119 2991 +3290 2124 2990 +3288 2132 2988 +3287 2141 2986 +3285 2153 2982 +3282 2169 2978 +3278 2190 2972 +3273 2216 2964 +3265 2249 2954 +3256 2290 2939 +3242 2339 2918 +3224 2397 2889 +3198 2465 2847 +3160 2542 2784 +3105 2628 2683 +3018 2723 2499 +2869 2825 2000 +2535 2933 0 +0 3046 0 +0 3163 0 +0 3284 0 +0 3408 0 +0 3533 0 +0 3661 0 +3425 2234 3126 +3425 2235 3126 +3425 2235 3126 +3425 2236 3126 +3425 2237 3126 +3425 2238 3125 +3424 2240 3125 +3424 2243 3124 +3423 2246 3124 +3423 2250 3123 +3422 2255 3121 +3421 2263 3120 +3419 2272 3117 +3417 2284 3114 +3414 2301 3110 +3410 2321 3104 +3405 2347 3096 +3398 2380 3085 +3388 2421 3071 +3374 2470 3050 +3356 2528 3021 +3330 2596 2979 +3292 2674 2916 +3237 2760 2815 +3151 2855 2631 +3001 2956 2130 +2667 3065 0 +0 3178 0 +0 3295 0 +0 3416 0 +0 3540 0 +0 3665 0 +3557 2365 3258 +3557 2366 3258 +3557 2366 3258 +3557 2367 3258 +3557 2367 3258 +3557 2368 3258 +3557 2370 3257 +3556 2371 3257 +3556 2374 3256 +3556 2377 3256 +3555 2381 3255 +3554 2387 3253 +3553 2394 3252 +3551 2403 3249 +3549 2416 3246 +3546 2432 3242 +3542 2453 3236 +3537 2479 3228 +3530 2512 3217 +3520 2552 3202 +3507 2602 3182 +3488 2660 3153 +3462 2728 3111 +3425 2805 3047 +3369 2892 2946 +3283 2986 2762 +3134 3088 2260 +2800 3197 0 +0 3310 0 +0 3427 0 +0 3548 0 +0 3672 0 +3690 2497 3390 +3690 2497 3390 +3689 2497 3390 +3689 2498 3390 +3689 2498 3390 +3689 2499 3390 +3689 2500 3390 +3689 2501 3389 +3689 2503 3389 +3688 2505 3388 +3688 2508 3388 +3687 2513 3387 +3686 2518 3385 +3685 2525 3384 +3683 2535 3381 +3681 2547 3378 +3678 2563 3374 +3674 2584 3368 +3669 2610 3360 +3662 2643 3349 +3652 2684 3334 +3639 2733 3314 +3620 2792 3285 +3594 2860 3242 +3557 2937 3179 +3501 3024 3078 +3415 3118 2894 +3266 3220 2391 +2932 3329 0 +0 3442 0 +0 3559 0 +0 3680 0 +3822 2628 3522 +3822 2628 3522 +3822 2628 3522 +3822 2629 3522 +3822 2629 3522 +3821 2630 3522 +3821 2630 3522 +3821 2631 3522 +3821 2633 3521 +3821 2635 3521 +3820 2637 3520 +3820 2640 3520 +3819 2644 3519 +3818 2650 3517 +3817 2657 3515 +3815 2667 3513 +3813 2679 3510 +3810 2695 3506 +3806 2716 3500 +3801 2742 3492 +3794 2775 3481 +3784 2816 3466 +3771 2865 3446 +3752 2924 3416 +3726 2992 3374 +3689 3069 3311 +3634 3156 3210 +3547 3250 3025 +3398 3352 2521 +3064 3461 0 +0 3574 0 +0 3692 0 +3954 2760 3654 +3954 2760 3654 +3954 2760 3654 +3954 2760 3654 +3954 2760 3654 +3954 2761 3654 +3954 2761 3654 +3953 2762 3654 +3953 2763 3654 +3953 2764 3653 +3953 2766 3653 +3952 2769 3652 +3952 2772 3652 +3951 2776 3651 +3950 2781 3649 +3949 2789 3647 +3948 2798 3645 +3945 2811 3642 +3942 2827 3638 +3939 2848 3632 +3933 2874 3624 +3926 2907 3613 +3916 2948 3598 +3903 2997 3578 +3884 3055 3548 +3858 3123 3506 +3821 3201 3443 +3766 3288 3342 +3679 3382 3157 +3530 3484 2653 +3197 3593 0 +0 3706 0 +4086 2891 3786 +4086 2891 3786 +4086 2892 3786 +4086 2892 3786 +4086 2892 3786 +4086 2892 3786 +4086 2893 3786 +4086 2893 3786 +4086 2894 3786 +4085 2895 3786 +4085 2896 3785 +4085 2898 3785 +4085 2900 3784 +4084 2904 3784 +4083 2908 3783 +4082 2913 3781 +4081 2921 3780 +4080 2930 3777 +4078 2943 3774 +4075 2959 3770 +4071 2980 3764 +4065 3006 3756 +4058 3039 3745 +4048 3080 3730 +4035 3129 3710 +4017 3187 3680 +3990 3255 3638 +3953 3333 3575 +3898 3420 3474 +3811 3514 3289 +3662 3616 2784 +3329 3725 0 +4095 3023 3918 +4095 3023 3918 +4095 3023 3918 +4095 3023 3918 +4095 3024 3918 +4095 3024 3918 +4095 3024 3918 +4095 3025 3918 +4095 3025 3918 +4095 3026 3918 +4095 3027 3918 +4095 3028 3917 +4095 3030 3917 +4095 3032 3916 +4095 3036 3916 +4095 3040 3915 +4095 3045 3913 +4095 3052 3912 +4095 3062 3909 +4095 3075 3906 +4095 3091 3902 +4095 3111 3896 +4095 3138 3888 +4095 3171 3877 +4095 3212 3862 +4095 3261 3842 +4095 3319 3813 +4095 3387 3770 +4085 3465 3707 +4030 3552 3606 +3944 3646 3421 +3794 3748 2916 +4095 3155 4051 +4095 3155 4051 +4095 3155 4051 +4095 3155 4050 +4095 3155 4050 +4095 3156 4050 +4095 3156 4050 +4095 3156 4050 +4095 3157 4050 +4095 3157 4050 +4095 3158 4050 +4095 3159 4050 +4095 3160 4049 +4095 3162 4049 +4095 3164 4048 +4095 3167 4048 +4095 3172 4047 +4095 3177 4045 +4095 3184 4044 +4095 3194 4041 +4095 3206 4038 +4095 3223 4034 +4095 3243 4028 +4095 3270 4020 +4095 3303 4009 +4095 3344 3994 +4095 3393 3974 +4095 3451 3945 +4095 3520 3902 +4095 3597 3839 +4095 3684 3738 +4076 3778 3553 +0 286 468 +0 316 433 +0 352 383 +0 397 305 +0 450 175 +0 514 0 +0 586 0 +0 668 0 +0 759 0 +0 857 0 +0 962 0 +0 1073 0 +0 1189 0 +0 1308 0 +0 1430 0 +0 1555 0 +0 1681 0 +0 1809 0 +0 1938 0 +0 2068 0 +0 2198 0 +0 2329 0 +0 2460 0 +0 2591 0 +0 2723 0 +0 2854 0 +0 2986 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +0 296 515 +0 325 484 +0 361 439 +0 405 371 +0 458 261 +0 520 54 +0 592 0 +0 673 0 +0 762 0 +0 860 0 +0 965 0 +0 1075 0 +0 1190 0 +0 1309 0 +0 1431 0 +0 1556 0 +0 1682 0 +0 1810 0 +0 1938 0 +0 2068 0 +0 2198 0 +0 2329 0 +0 2460 0 +0 2591 0 +0 2723 0 +0 2854 0 +0 2986 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +38 310 571 +0 338 544 +0 372 505 +0 415 447 +0 467 355 +0 528 195 +0 599 0 +0 678 0 +0 767 0 +0 864 0 +0 968 0 +0 1077 0 +0 1192 0 +0 1311 0 +0 1432 0 +0 1556 0 +0 1682 0 +0 1810 0 +0 1939 0 +0 2068 0 +0 2198 0 +0 2329 0 +0 2460 0 +0 2591 0 +0 2723 0 +0 2854 0 +0 2986 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +347 327 637 +286 354 613 +190 387 580 +17 429 531 +0 479 457 +0 539 333 +0 608 87 +0 686 0 +0 774 0 +0 869 0 +0 972 0 +0 1081 0 +0 1194 0 +0 1312 0 +0 1434 0 +0 1558 0 +0 1683 0 +0 1811 0 +0 1939 0 +0 2069 0 +0 2199 0 +0 2329 0 +0 2460 0 +0 2591 0 +0 2723 0 +0 2854 0 +0 2986 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +577 349 712 +541 375 692 +489 407 664 +408 447 624 +270 495 565 +0 553 470 +0 620 302 +0 696 0 +0 782 0 +0 876 0 +0 977 0 +0 1085 0 +0 1198 0 +0 1315 0 +0 1436 0 +0 1559 0 +0 1684 0 +0 1812 0 +0 1940 0 +0 2069 0 +0 2199 0 +0 2329 0 +0 2460 0 +0 2591 0 +0 2723 0 +0 2854 0 +0 2986 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +771 377 796 +748 401 780 +715 431 757 +668 469 725 +595 515 678 +475 571 606 +241 635 487 +0 709 256 +0 793 0 +0 885 0 +0 984 0 +0 1091 0 +0 1202 0 +0 1318 0 +0 1438 0 +0 1561 0 +0 1686 0 +0 1813 0 +0 1941 0 +0 2070 0 +0 2199 0 +0 2330 0 +0 2461 0 +0 2592 0 +0 2723 0 +0 2855 0 +0 2986 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +944 411 889 +928 434 876 +907 462 858 +876 498 832 +832 541 795 +764 594 740 +655 655 655 +450 726 509 +0 807 186 +0 896 0 +0 994 0 +0 1098 0 +0 1208 0 +0 1323 0 +0 1442 0 +0 1564 0 +0 1688 0 +0 1814 0 +0 1942 0 +0 2071 0 +0 2200 0 +0 2330 0 +0 2461 0 +0 2592 0 +0 2723 0 +0 2855 0 +0 2986 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +1105 454 990 +1094 475 979 +1079 501 965 +1058 533 944 +1029 574 916 +986 623 874 +922 681 813 +820 748 714 +633 825 536 +113 912 73 +0 1006 0 +0 1108 0 +0 1216 0 +0 1329 0 +0 1446 0 +0 1567 0 +0 1691 0 +0 1816 0 +0 1943 0 +0 2072 0 +0 2201 0 +0 2331 0 +0 2461 0 +0 2592 0 +0 2724 0 +0 2855 0 +0 2987 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +1257 506 1097 +1249 524 1088 +1239 547 1077 +1224 577 1061 +1204 614 1039 +1175 659 1008 +1134 713 963 +1073 776 894 +975 849 783 +799 931 571 +345 1022 0 +0 1121 0 +0 1226 0 +0 1337 0 +0 1452 0 +0 1572 0 +0 1694 0 +0 1819 0 +0 1945 0 +0 2073 0 +0 2202 0 +0 2332 0 +0 2462 0 +0 2593 0 +0 2724 0 +0 2855 0 +0 2987 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +1404 566 1209 +1398 582 1202 +1390 603 1193 +1380 629 1181 +1366 662 1165 +1346 703 1141 +1318 752 1108 +1278 811 1059 +1218 878 984 +1124 956 860 +956 1042 613 +540 1137 0 +0 1239 0 +0 1347 0 +0 1461 0 +0 1578 0 +0 1699 0 +0 1823 0 +0 1948 0 +0 2075 0 +0 2204 0 +0 2333 0 +0 2463 0 +0 2593 0 +0 2724 0 +0 2856 0 +0 2987 0 +0 3119 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +1546 637 1325 +1542 651 1320 +1537 668 1314 +1529 691 1304 +1519 720 1292 +1505 756 1274 +1486 800 1249 +1458 853 1214 +1419 915 1162 +1360 987 1082 +1268 1068 947 +1105 1158 665 +714 1256 0 +0 1361 0 +0 1471 0 +0 1586 0 +0 1705 0 +0 1827 0 +0 1952 0 +0 2078 0 +0 2206 0 +0 2335 0 +0 2464 0 +0 2594 0 +0 2725 0 +0 2856 0 +0 2987 0 +0 3119 0 +0 3251 0 +0 3382 0 +0 3514 0 +0 3646 0 +1686 717 1446 +1683 728 1442 +1679 743 1437 +1674 763 1430 +1666 787 1420 +1656 819 1407 +1642 857 1388 +1623 904 1363 +1596 960 1326 +1557 1026 1272 +1500 1101 1187 +1409 1185 1042 +1250 1278 725 +875 1378 0 +0 1485 0 +0 1597 0 +0 1713 0 +0 1834 0 +0 1957 0 +0 2082 0 +0 2209 0 +0 2337 0 +0 2466 0 +0 2596 0 +0 2726 0 +0 2857 0 +0 2988 0 +0 3119 0 +0 3251 0 +0 3383 0 +0 3514 0 +0 3646 0 +1824 805 1569 +1822 815 1566 +1819 827 1562 +1815 843 1556 +1809 864 1549 +1802 891 1539 +1792 924 1526 +1778 965 1507 +1759 1014 1480 +1732 1073 1442 +1694 1141 1386 +1637 1219 1298 +1547 1305 1145 +1391 1400 795 +1028 1502 0 +0 1611 0 +0 1724 0 +0 1842 0 +0 1963 0 +0 2087 0 +0 2212 0 +0 2339 0 +0 2468 0 +0 2597 0 +0 2727 0 +0 2858 0 +0 2989 0 +0 3120 0 +0 3251 0 +0 3383 0 +0 3515 0 +0 3646 0 +1960 902 1694 +1959 910 1692 +1956 920 1689 +1953 933 1685 +1949 950 1679 +1944 972 1672 +1937 1000 1662 +1927 1035 1648 +1913 1077 1628 +1894 1129 1601 +1868 1190 1562 +1830 1260 1505 +1773 1340 1413 +1684 1428 1253 +1530 1525 875 +1174 1629 0 +0 1738 0 +0 1853 0 +0 1971 0 +0 2093 0 +0 2217 0 +0 2343 0 +0 2471 0 +0 2599 0 +0 2729 0 +0 2859 0 +0 2989 0 +0 3120 0 +0 3252 0 +0 3383 0 +0 3515 0 +0 3647 0 +2095 1005 1821 +2094 1012 1819 +2093 1020 1817 +2090 1030 1814 +2087 1044 1810 +2084 1062 1804 +2078 1085 1797 +2071 1114 1786 +2061 1150 1772 +2047 1195 1753 +2029 1248 1725 +2002 1310 1685 +1964 1382 1626 +1908 1464 1533 +1820 1554 1367 +1667 1652 963 +1317 1756 0 +0 1867 0 +0 1982 0 +0 2101 0 +0 2223 0 +0 2348 0 +0 2474 0 +0 2602 0 +0 2731 0 +0 2860 0 +0 2991 0 +0 3121 0 +0 3252 0 +0 3384 0 +0 3515 0 +0 3647 0 +2230 1115 1949 +2229 1120 1948 +2228 1126 1946 +2226 1135 1944 +2224 1146 1941 +2221 1160 1936 +2217 1179 1931 +2212 1203 1923 +2205 1233 1913 +2195 1270 1898 +2181 1315 1879 +2162 1369 1851 +2136 1433 1810 +2098 1507 1750 +2042 1589 1655 +1955 1681 1484 +1802 1780 1059 +1457 1885 0 +0 1996 0 +0 2112 0 +0 2232 0 +0 2354 0 +0 2479 0 +0 2606 0 +0 2734 0 +0 2862 0 +0 2992 0 +0 3123 0 +0 3253 0 +0 3384 0 +0 3516 0 +0 3647 0 +2364 1229 2078 +2363 1233 2077 +2362 1238 2076 +2361 1245 2074 +2359 1254 2072 +2357 1265 2069 +2354 1280 2064 +2350 1299 2059 +2345 1323 2051 +2338 1354 2041 +2328 1392 2026 +2314 1438 2006 +2296 1494 1978 +2269 1559 1937 +2232 1633 1876 +2176 1717 1779 +2089 1809 1606 +1937 1908 1163 +1595 2015 0 +0 2127 0 +0 2243 0 +0 2363 0 +0 2486 0 +0 2611 0 +0 2737 0 +0 2865 0 +0 2994 0 +0 3124 0 +0 3254 0 +0 3385 0 +0 3516 0 +0 3648 0 +2497 1348 2208 +2497 1351 2207 +2496 1355 2206 +2495 1360 2205 +2494 1367 2203 +2492 1376 2201 +2490 1387 2198 +2487 1402 2193 +2483 1422 2188 +2478 1447 2180 +2471 1478 2169 +2461 1517 2155 +2447 1564 2135 +2429 1620 2106 +2402 1686 2065 +2365 1761 2004 +2309 1845 1906 +2222 1938 1729 +2071 2038 1272 +1731 2145 0 +0 2257 0 +0 2374 0 +0 2494 0 +0 2617 0 +0 2742 0 +0 2869 0 +0 2997 0 +0 3126 0 +0 3256 0 +0 3386 0 +0 3517 0 +0 3648 0 +2630 1470 2338 +2630 1472 2338 +2629 1475 2337 +2629 1479 2336 +2628 1484 2335 +2627 1491 2333 +2625 1500 2331 +2623 1512 2327 +2620 1527 2323 +2616 1547 2317 +2611 1572 2310 +2603 1604 2299 +2594 1643 2284 +2580 1691 2264 +2561 1748 2236 +2535 1814 2194 +2498 1890 2132 +2442 1974 2033 +2355 2068 1855 +2205 2168 1386 +1867 2276 0 +0 2388 0 +0 2505 0 +0 2625 0 +0 2749 0 +0 2874 0 +0 3001 0 +0 3129 0 +0 3258 0 +0 3388 0 +0 3518 0 +0 3649 0 +2763 1594 2469 +2763 1595 2469 +2762 1598 2468 +2762 1601 2467 +2761 1605 2466 +2760 1610 2465 +2759 1617 2463 +2757 1626 2461 +2755 1638 2458 +2752 1654 2454 +2748 1674 2448 +2743 1699 2440 +2736 1731 2429 +2726 1771 2415 +2713 1819 2394 +2694 1876 2366 +2668 1943 2324 +2630 2019 2262 +2575 2104 2162 +2488 2198 1982 +2338 2299 1505 +2001 2407 0 +0 2519 0 +0 2637 0 +0 2757 0 +0 2880 0 +0 3006 0 +0 3133 0 +0 3261 0 +0 3390 0 +0 3520 0 +0 3650 0 +2896 1720 2600 +2895 1721 2600 +2895 1723 2600 +2895 1725 2599 +2894 1728 2598 +2894 1732 2597 +2893 1738 2596 +2891 1745 2594 +2890 1754 2592 +2888 1766 2589 +2885 1782 2584 +2881 1802 2579 +2876 1828 2571 +2868 1860 2560 +2859 1900 2545 +2845 1948 2525 +2827 2006 2496 +2800 2073 2454 +2763 2149 2392 +2708 2235 2292 +2621 2329 2111 +2471 2430 1626 +2135 2538 0 +0 2651 0 +0 2768 0 +0 2889 0 +0 3012 0 +0 3138 0 +0 3265 0 +0 3393 0 +0 3522 0 +0 3652 0 +3028 1847 2732 +3028 1848 2731 +3028 1850 2731 +3027 1851 2731 +3027 1854 2730 +3027 1857 2729 +3026 1861 2728 +3025 1866 2727 +3024 1873 2725 +3022 1883 2723 +3020 1895 2720 +3017 1911 2716 +3013 1931 2710 +3008 1957 2702 +3001 1989 2691 +2991 2030 2676 +2978 2078 2656 +2959 2136 2627 +2933 2203 2585 +2895 2280 2522 +2840 2366 2422 +2753 2460 2240 +2604 2562 1750 +2268 2670 0 +0 2783 0 +0 2900 0 +0 3021 0 +0 3144 0 +0 3269 0 +0 3397 0 +0 3525 0 +0 3654 0 +3160 1976 2863 +3160 1977 2863 +3160 1978 2863 +3160 1979 2862 +3160 1981 2862 +3159 1983 2862 +3159 1986 2861 +3158 1990 2860 +3157 1996 2858 +3156 2003 2857 +3154 2012 2854 +3152 2025 2851 +3149 2040 2847 +3146 2061 2841 +3140 2087 2833 +3133 2120 2822 +3123 2160 2808 +3110 2209 2787 +3091 2267 2758 +3065 2334 2716 +3028 2411 2653 +2972 2497 2553 +2886 2592 2370 +2736 2693 1876 +2401 2801 0 +0 2914 0 +0 3032 0 +0 3152 0 +0 3276 0 +0 3401 0 +0 3529 0 +0 3657 0 +3293 2105 2995 +3293 2106 2995 +3293 2107 2995 +3292 2108 2994 +3292 2109 2994 +3292 2111 2994 +3292 2113 2993 +3291 2116 2992 +3290 2120 2991 +3290 2126 2990 +3288 2133 2988 +3287 2142 2986 +3285 2155 2983 +3282 2171 2978 +3278 2191 2973 +3272 2217 2965 +3265 2250 2954 +3256 2291 2939 +3242 2339 2919 +3224 2398 2890 +3197 2465 2848 +3160 2542 2785 +3105 2629 2684 +3018 2723 2500 +2869 2825 2004 +2534 2933 0 +0 3046 0 +0 3164 0 +0 3284 0 +0 3408 0 +0 3533 0 +0 3661 0 +3425 2236 3127 +3425 2236 3127 +3425 2237 3126 +3425 2237 3126 +3425 2238 3126 +3424 2240 3126 +3424 2241 3125 +3424 2244 3125 +3423 2247 3124 +3423 2251 3123 +3422 2256 3122 +3421 2264 3120 +3419 2273 3118 +3417 2286 3114 +3414 2302 3110 +3410 2322 3104 +3405 2348 3096 +3397 2381 3086 +3388 2422 3071 +3374 2471 3050 +3356 2529 3021 +3330 2597 2979 +3292 2674 2916 +3237 2760 2815 +3150 2855 2631 +3001 2957 2132 +2667 3065 0 +0 3178 0 +0 3296 0 +0 3416 0 +0 3540 0 +0 3665 0 +3557 2366 3259 +3557 2367 3258 +3557 2367 3258 +3557 2367 3258 +3557 2368 3258 +3557 2369 3258 +3557 2371 3258 +3556 2372 3257 +3556 2375 3257 +3555 2378 3256 +3555 2382 3255 +3554 2387 3254 +3553 2395 3252 +3551 2404 3249 +3549 2417 3246 +3546 2433 3242 +3542 2453 3236 +3537 2480 3228 +3530 2512 3217 +3520 2553 3203 +3506 2602 3182 +3488 2660 3153 +3462 2728 3111 +3424 2806 3048 +3369 2892 2947 +3283 2987 2763 +3133 3089 2262 +2799 3197 0 +0 3310 0 +0 3428 0 +0 3548 0 +0 3672 0 +3689 2497 3390 +3689 2497 3390 +3689 2498 3390 +3689 2498 3390 +3689 2499 3390 +3689 2499 3390 +3689 2500 3390 +3689 2502 3389 +3688 2504 3389 +3688 2506 3388 +3688 2509 3388 +3687 2513 3387 +3686 2519 3385 +3685 2526 3384 +3683 2535 3381 +3681 2548 3378 +3678 2564 3374 +3674 2585 3368 +3669 2611 3360 +3662 2644 3349 +3652 2684 3334 +3639 2734 3314 +3620 2792 3285 +3594 2860 3243 +3557 2937 3179 +3501 3024 3078 +3415 3119 2894 +3266 3220 2392 +2932 3329 0 +0 3442 0 +0 3560 0 +0 3680 0 +3822 2628 3522 +3822 2629 3522 +3822 2629 3522 +3822 2629 3522 +3821 2630 3522 +3821 2630 3522 +3821 2631 3522 +3821 2632 3522 +3821 2633 3521 +3821 2635 3521 +3820 2637 3520 +3820 2641 3520 +3819 2645 3519 +3818 2650 3517 +3817 2657 3516 +3815 2667 3513 +3813 2679 3510 +3810 2696 3506 +3806 2716 3500 +3801 2743 3492 +3794 2775 3481 +3784 2816 3466 +3771 2865 3446 +3752 2924 3417 +3726 2992 3375 +3689 3069 3311 +3633 3156 3210 +3547 3250 3026 +3398 3352 2523 +3064 3461 0 +0 3574 0 +0 3692 0 +3954 2760 3654 +3954 2760 3654 +3954 2760 3654 +3954 2760 3654 +3954 2761 3654 +3954 2761 3654 +3954 2762 3654 +3953 2763 3654 +3953 2764 3654 +3953 2765 3653 +3953 2767 3653 +3952 2769 3652 +3952 2772 3652 +3951 2776 3651 +3950 2782 3649 +3949 2789 3648 +3948 2799 3645 +3945 2811 3642 +3942 2827 3638 +3939 2848 3632 +3933 2874 3624 +3926 2907 3613 +3916 2948 3598 +3903 2997 3578 +3884 3056 3549 +3858 3124 3506 +3821 3201 3443 +3766 3288 3342 +3679 3382 3157 +3530 3484 2654 +3196 3593 0 +0 3706 0 +4086 2892 3786 +4086 2892 3786 +4086 2892 3786 +4086 2892 3786 +4086 2892 3786 +4086 2893 3786 +4086 2893 3786 +4086 2894 3786 +4086 2894 3786 +4085 2895 3786 +4085 2897 3785 +4085 2898 3785 +4085 2901 3784 +4084 2904 3784 +4083 2908 3783 +4082 2914 3781 +4081 2921 3780 +4080 2930 3777 +4077 2943 3774 +4075 2959 3770 +4071 2980 3764 +4065 3006 3756 +4058 3039 3745 +4048 3080 3730 +4035 3129 3710 +4017 3188 3681 +3990 3256 3638 +3953 3333 3575 +3898 3420 3474 +3811 3514 3289 +3662 3616 2785 +3329 3725 0 +4095 3023 3919 +4095 3023 3918 +4095 3023 3918 +4095 3024 3918 +4095 3024 3918 +4095 3024 3918 +4095 3024 3918 +4095 3025 3918 +4095 3025 3918 +4095 3026 3918 +4095 3027 3918 +4095 3028 3917 +4095 3030 3917 +4095 3033 3916 +4095 3036 3916 +4095 3040 3915 +4095 3045 3913 +4095 3053 3912 +4095 3062 3909 +4095 3075 3906 +4095 3091 3902 +4095 3112 3896 +4095 3138 3888 +4095 3171 3877 +4095 3212 3862 +4095 3261 3842 +4095 3319 3813 +4095 3388 3770 +4085 3465 3707 +4030 3552 3606 +3944 3646 3421 +3794 3748 2916 +4095 3155 4051 +4095 3155 4051 +4095 3155 4051 +4095 3155 4051 +4095 3156 4050 +4095 3156 4050 +4095 3156 4050 +4095 3156 4050 +4095 3157 4050 +4095 3157 4050 +4095 3158 4050 +4095 3159 4050 +4095 3160 4049 +4095 3162 4049 +4095 3164 4048 +4095 3168 4048 +4095 3172 4047 +4095 3177 4045 +4095 3185 4044 +4095 3194 4041 +4095 3207 4038 +4095 3223 4034 +4095 3244 4028 +4095 3270 4020 +4095 3303 4009 +4095 3344 3994 +4095 3393 3974 +4095 3451 3945 +4095 3520 3902 +4095 3597 3839 +4095 3684 3738 +4076 3778 3553 +0 387 587 +0 410 561 +0 440 523 +0 477 468 +0 523 381 +0 577 231 +0 641 0 +0 714 0 +0 797 0 +0 888 0 +0 987 0 +0 1093 0 +0 1204 0 +0 1320 0 +0 1439 0 +0 1562 0 +0 1687 0 +0 1813 0 +0 1941 0 +0 2070 0 +0 2200 0 +0 2330 0 +0 2461 0 +0 2592 0 +0 2723 0 +0 2855 0 +0 2986 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +0 395 624 +0 418 600 +0 448 565 +0 484 515 +0 529 437 +0 583 307 +0 646 42 +0 718 0 +0 800 0 +0 891 0 +0 989 0 +0 1094 0 +0 1205 0 +0 1321 0 +0 1440 0 +0 1562 0 +0 1687 0 +0 1813 0 +0 1941 0 +0 2070 0 +0 2200 0 +0 2330 0 +0 2461 0 +0 2592 0 +0 2723 0 +0 2855 0 +0 2986 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +0 406 669 +0 428 647 +0 457 616 +0 493 571 +0 537 503 +0 590 393 +0 652 186 +0 724 0 +0 805 0 +0 894 0 +0 992 0 +0 1097 0 +0 1207 0 +0 1322 0 +0 1441 0 +0 1563 0 +0 1688 0 +0 1814 0 +0 1942 0 +0 2070 0 +0 2200 0 +0 2330 0 +0 2461 0 +0 2592 0 +0 2723 0 +0 2855 0 +0 2986 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +247 420 722 +170 442 703 +41 470 676 +0 505 637 +0 547 579 +0 599 487 +0 660 327 +0 731 0 +0 811 0 +0 899 0 +0 996 0 +0 1100 0 +0 1210 0 +0 1324 0 +0 1443 0 +0 1564 0 +0 1688 0 +0 1815 0 +0 1942 0 +0 2071 0 +0 2200 0 +0 2330 0 +0 2461 0 +0 2592 0 +0 2723 0 +0 2855 0 +0 2986 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +519 438 786 +479 459 769 +418 486 745 +322 520 712 +149 561 663 +0 611 589 +0 671 465 +0 740 219 +0 818 0 +0 906 0 +0 1001 0 +0 1104 0 +0 1213 0 +0 1327 0 +0 1445 0 +0 1566 0 +0 1690 0 +0 1815 0 +0 1943 0 +0 2071 0 +0 2201 0 +0 2331 0 +0 2461 0 +0 2592 0 +0 2723 0 +0 2855 0 +0 2987 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +734 461 858 +709 481 844 +673 507 824 +621 539 797 +540 579 756 +402 627 697 +110 685 602 +0 752 434 +0 828 18 +0 914 0 +0 1008 0 +0 1109 0 +0 1217 0 +0 1330 0 +0 1447 0 +0 1568 0 +0 1691 0 +0 1817 0 +0 1944 0 +0 2072 0 +0 2201 0 +0 2331 0 +0 2462 0 +0 2592 0 +0 2724 0 +0 2855 0 +0 2987 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +919 490 940 +903 509 929 +880 533 912 +847 563 889 +800 601 857 +727 647 810 +607 703 738 +373 767 619 +0 842 388 +0 925 0 +0 1017 0 +0 1116 0 +0 1223 0 +0 1334 0 +0 1451 0 +0 1570 0 +0 1693 0 +0 1818 0 +0 1945 0 +0 2073 0 +0 2202 0 +0 2332 0 +0 2462 0 +0 2593 0 +0 2724 0 +0 2855 0 +0 2987 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +1087 526 1031 +1076 544 1021 +1061 566 1008 +1039 594 990 +1008 630 964 +964 673 927 +896 726 872 +787 787 787 +582 859 641 +0 939 318 +0 1029 0 +0 1126 0 +0 1230 0 +0 1340 0 +0 1455 0 +0 1574 0 +0 1696 0 +0 1820 0 +0 1946 0 +0 2074 0 +0 2203 0 +0 2332 0 +0 2462 0 +0 2593 0 +0 2724 0 +0 2855 0 +0 2987 0 +0 3119 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +1245 570 1130 +1237 586 1122 +1226 607 1111 +1211 633 1097 +1190 665 1076 +1161 706 1048 +1118 755 1006 +1055 813 945 +952 880 846 +765 958 669 +245 1044 205 +0 1138 0 +0 1240 0 +0 1348 0 +0 1461 0 +0 1578 0 +0 1699 0 +0 1823 0 +0 1948 0 +0 2075 0 +0 2204 0 +0 2333 0 +0 2463 0 +0 2594 0 +0 2724 0 +0 2856 0 +0 2987 0 +0 3119 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +1395 623 1235 +1389 638 1229 +1381 656 1220 +1371 679 1209 +1356 709 1193 +1336 746 1171 +1308 791 1140 +1267 845 1095 +1205 908 1026 +1107 981 915 +932 1063 703 +477 1154 0 +0 1253 0 +0 1358 0 +0 1469 0 +0 1585 0 +0 1704 0 +0 1826 0 +0 1951 0 +0 2077 0 +0 2205 0 +0 2334 0 +0 2464 0 +0 2594 0 +0 2725 0 +0 2856 0 +0 2987 0 +0 3119 0 +0 3251 0 +0 3382 0 +0 3514 0 +0 3646 0 +1540 686 1346 +1536 698 1341 +1530 715 1334 +1522 735 1326 +1512 762 1313 +1498 794 1297 +1478 835 1273 +1450 884 1240 +1410 943 1191 +1351 1011 1116 +1256 1088 993 +1088 1174 745 +672 1269 0 +0 1371 0 +0 1479 0 +0 1593 0 +0 1710 0 +0 1831 0 +0 1955 0 +0 2080 0 +0 2207 0 +0 2336 0 +0 2465 0 +0 2595 0 +0 2726 0 +0 2857 0 +0 2988 0 +0 3119 0 +0 3251 0 +0 3382 0 +0 3514 0 +0 3646 0 +1681 758 1461 +1678 769 1458 +1674 783 1453 +1669 801 1446 +1661 823 1436 +1651 852 1424 +1637 888 1406 +1618 932 1381 +1590 985 1346 +1551 1047 1295 +1492 1119 1215 +1400 1200 1079 +1237 1290 797 +846 1388 0 +0 1493 0 +0 1603 0 +0 1718 0 +0 1837 0 +0 1959 0 +0 2084 0 +0 2210 0 +0 2338 0 +0 2467 0 +0 2596 0 +0 2726 0 +0 2857 0 +0 2988 0 +0 3120 0 +0 3251 0 +0 3383 0 +0 3514 0 +0 3646 0 +1820 840 1581 +1818 849 1578 +1815 860 1574 +1811 875 1569 +1806 895 1562 +1798 920 1552 +1788 951 1539 +1774 989 1521 +1755 1036 1495 +1728 1092 1458 +1689 1158 1404 +1632 1233 1319 +1541 1317 1174 +1382 1410 857 +1007 1510 0 +0 1617 0 +0 1729 0 +0 1846 0 +0 1966 0 +0 2089 0 +0 2214 0 +0 2341 0 +0 2469 0 +0 2598 0 +0 2728 0 +0 2858 0 +0 2989 0 +0 3120 0 +0 3251 0 +0 3383 0 +0 3515 0 +0 3646 0 +1958 930 1703 +1956 937 1701 +1954 947 1698 +1951 959 1694 +1947 976 1689 +1941 996 1681 +1934 1023 1671 +1924 1056 1658 +1910 1097 1639 +1891 1146 1613 +1865 1205 1575 +1826 1273 1518 +1769 1351 1430 +1679 1437 1277 +1523 1532 927 +1160 1635 0 +0 1743 0 +0 1856 0 +0 1974 0 +0 2095 0 +0 2219 0 +0 2344 0 +0 2471 0 +0 2600 0 +0 2729 0 +0 2859 0 +0 2990 0 +0 3121 0 +0 3252 0 +0 3383 0 +0 3515 0 +0 3647 0 +2094 1028 1828 +2092 1034 1826 +2091 1042 1824 +2088 1052 1821 +2086 1065 1817 +2082 1082 1811 +2076 1104 1804 +2069 1132 1794 +2059 1167 1780 +2045 1210 1761 +2026 1261 1733 +2000 1322 1695 +1962 1392 1637 +1905 1472 1545 +1816 1561 1385 +1662 1657 1007 +1307 1761 0 +0 1870 0 +0 1985 0 +0 2103 0 +0 2225 0 +0 2349 0 +0 2475 0 +0 2603 0 +0 2731 0 +0 2861 0 +0 2991 0 +0 3122 0 +0 3253 0 +0 3384 0 +0 3515 0 +0 3647 0 +2228 1133 1954 +2228 1138 1953 +2226 1144 1951 +2225 1152 1949 +2223 1163 1946 +2220 1176 1942 +2216 1194 1936 +2210 1217 1929 +2203 1246 1918 +2193 1282 1904 +2180 1327 1885 +2161 1380 1857 +2134 1442 1817 +2096 1514 1758 +2040 1596 1665 +1952 1686 1499 +1799 1784 1095 +1449 1888 0 +0 1999 0 +0 2114 0 +0 2233 0 +0 2356 0 +0 2480 0 +0 2606 0 +0 2734 0 +0 2863 0 +0 2992 0 +0 3123 0 +0 3253 0 +0 3384 0 +0 3516 0 +0 3647 0 +2363 1243 2082 +2362 1247 2081 +2361 1252 2080 +2360 1258 2078 +2358 1267 2076 +2356 1278 2073 +2353 1292 2068 +2349 1311 2063 +2344 1335 2055 +2337 1365 2045 +2327 1402 2031 +2313 1447 2011 +2294 1502 1983 +2268 1565 1942 +2230 1639 1882 +2174 1721 1787 +2087 1813 1617 +1934 1912 1191 +1589 2017 0 +0 2129 0 +0 2244 0 +0 2364 0 +0 2486 0 +0 2611 0 +0 2738 0 +0 2866 0 +0 2995 0 +0 3124 0 +0 3255 0 +0 3385 0 +0 3516 0 +0 3648 0 +2496 1359 2211 +2496 1362 2210 +2495 1365 2209 +2494 1370 2208 +2493 1377 2206 +2491 1386 2204 +2489 1397 2201 +2486 1412 2196 +2482 1431 2191 +2477 1455 2183 +2470 1486 2173 +2460 1524 2158 +2446 1570 2138 +2428 1626 2110 +2402 1691 2069 +2364 1765 2008 +2308 1849 1911 +2221 1941 1738 +2069 2041 1295 +1727 2147 0 +0 2259 0 +0 2375 0 +0 2495 0 +0 2618 0 +0 2743 0 +0 2869 0 +0 2997 0 +0 3126 0 +0 3256 0 +0 3387 0 +0 3517 0 +0 3648 0 +2630 1478 2340 +2629 1480 2340 +2629 1483 2339 +2628 1487 2338 +2627 1492 2337 +2626 1499 2335 +2624 1508 2333 +2622 1519 2330 +2619 1535 2326 +2615 1554 2320 +2610 1579 2312 +2603 1610 2302 +2593 1649 2287 +2579 1696 2267 +2561 1752 2238 +2535 1818 2197 +2497 1893 2136 +2441 1977 2038 +2354 2070 1861 +2203 2170 1404 +1864 2277 0 +0 2389 0 +0 2506 0 +0 2626 0 +0 2749 0 +0 2874 0 +0 3001 0 +0 3129 0 +0 3258 0 +0 3388 0 +0 3519 0 +0 3649 0 +2763 1600 2471 +2762 1602 2470 +2762 1604 2470 +2761 1607 2469 +2761 1611 2468 +2760 1616 2467 +2759 1623 2465 +2757 1632 2463 +2755 1644 2460 +2752 1659 2455 +2748 1679 2450 +2743 1704 2442 +2735 1736 2431 +2726 1775 2417 +2712 1823 2396 +2694 1880 2368 +2667 1946 2326 +2630 2022 2264 +2574 2107 2165 +2487 2200 1987 +2337 2301 1518 +1999 2408 0 +0 2520 0 +0 2637 0 +0 2758 0 +0 2881 0 +0 3006 0 +0 3133 0 +0 3261 0 +0 3390 0 +0 3520 0 +0 3651 0 +2895 1725 2601 +2895 1726 2601 +2895 1728 2601 +2894 1730 2600 +2894 1733 2599 +2893 1737 2599 +2892 1742 2597 +2891 1749 2595 +2890 1758 2593 +2887 1770 2590 +2884 1786 2586 +2881 1806 2580 +2875 1832 2572 +2868 1864 2561 +2858 1903 2547 +2845 1951 2526 +2826 2008 2498 +2800 2075 2456 +2763 2151 2394 +2707 2237 2294 +2620 2330 2114 +2470 2431 1637 +2133 2539 0 +0 2652 0 +0 2769 0 +0 2889 0 +0 3012 0 +0 3138 0 +0 3265 0 +0 3393 0 +0 3522 0 +0 3652 0 +3028 1851 2733 +3028 1852 2732 +3027 1853 2732 +3027 1855 2732 +3027 1857 2731 +3026 1860 2730 +3026 1864 2729 +3025 1870 2728 +3024 1877 2726 +3022 1886 2724 +3020 1898 2721 +3017 1914 2717 +3013 1934 2711 +3008 1960 2703 +3000 1992 2692 +2991 2032 2677 +2977 2080 2657 +2959 2138 2628 +2933 2205 2586 +2895 2282 2524 +2840 2367 2424 +2753 2461 2243 +2603 2562 1758 +2267 2670 0 +0 2783 0 +0 2900 0 +0 3021 0 +0 3144 0 +0 3270 0 +0 3397 0 +0 3525 0 +0 3654 0 +3160 1979 2864 +3160 1979 2864 +3160 1980 2863 +3160 1982 2863 +3160 1983 2863 +3159 1986 2862 +3159 1989 2861 +3158 1993 2861 +3157 1998 2859 +3156 2005 2857 +3154 2015 2855 +3152 2027 2852 +3149 2043 2848 +3145 2063 2842 +3140 2089 2834 +3133 2122 2823 +3123 2162 2809 +3110 2210 2788 +3091 2268 2759 +3065 2335 2717 +3028 2412 2654 +2972 2498 2554 +2886 2592 2372 +2736 2694 1882 +2401 2802 0 +0 2915 0 +0 3032 0 +0 3153 0 +0 3276 0 +0 3402 0 +0 3529 0 +0 3657 0 +3293 2107 2995 +3293 2108 2995 +3292 2109 2995 +3292 2110 2995 +3292 2111 2995 +3292 2113 2994 +3291 2115 2994 +3291 2118 2993 +3290 2122 2992 +3289 2128 2991 +3288 2135 2989 +3287 2144 2986 +3284 2157 2983 +3282 2173 2979 +3278 2193 2973 +3272 2219 2965 +3265 2252 2955 +3255 2292 2940 +3242 2341 2919 +3223 2399 2890 +3197 2466 2848 +3160 2543 2785 +3104 2629 2685 +3018 2724 2502 +2868 2825 2008 +2534 2933 0 +0 3046 0 +0 3164 0 +0 3285 0 +0 3408 0 +0 3534 0 +0 3661 0 +3425 2237 3127 +3425 2238 3127 +3425 2238 3127 +3425 2239 3127 +3425 2240 3126 +3424 2241 3126 +3424 2243 3126 +3424 2245 3125 +3423 2248 3124 +3423 2252 3123 +3422 2258 3122 +3420 2265 3120 +3419 2275 3118 +3417 2287 3115 +3414 2303 3111 +3410 2323 3105 +3405 2350 3097 +3397 2382 3086 +3388 2423 3071 +3374 2472 3051 +3356 2530 3022 +3330 2597 2980 +3292 2675 2917 +3237 2761 2816 +3150 2855 2633 +3001 2957 2136 +2666 3065 0 +0 3178 0 +0 3296 0 +0 3417 0 +0 3540 0 +0 3666 0 +3557 2367 3259 +3557 2368 3259 +3557 2368 3259 +3557 2369 3259 +3557 2369 3258 +3557 2370 3258 +3557 2372 3258 +3556 2373 3257 +3556 2376 3257 +3555 2379 3256 +3555 2383 3255 +3554 2389 3254 +3553 2396 3252 +3551 2405 3250 +3549 2418 3247 +3546 2434 3242 +3542 2454 3236 +3537 2480 3229 +3530 2513 3218 +3520 2554 3203 +3506 2603 3182 +3488 2661 3153 +3462 2729 3111 +3424 2806 3048 +3369 2892 2947 +3283 2987 2763 +3133 3089 2264 +2799 3197 0 +0 3310 0 +0 3428 0 +0 3548 0 +0 3672 0 +3689 2498 3391 +3689 2498 3391 +3689 2499 3391 +3689 2499 3390 +3689 2500 3390 +3689 2500 3390 +3689 2501 3390 +3689 2503 3390 +3688 2504 3389 +3688 2507 3389 +3688 2510 3388 +3687 2514 3387 +3686 2520 3386 +3685 2527 3384 +3683 2536 3382 +3681 2549 3378 +3678 2565 3374 +3674 2585 3368 +3669 2612 3360 +3662 2644 3350 +3652 2685 3335 +3639 2734 3314 +3620 2792 3285 +3594 2860 3243 +3557 2938 3180 +3501 3024 3079 +3415 3119 2895 +3265 3221 2394 +2932 3329 0 +0 3442 0 +0 3560 0 +0 3681 0 +3822 2629 3523 +3822 2629 3523 +3822 2630 3523 +3822 2630 3522 +3821 2630 3522 +3821 2631 3522 +3821 2632 3522 +3821 2633 3522 +3821 2634 3522 +3821 2636 3521 +3820 2638 3521 +3820 2641 3520 +3819 2645 3519 +3818 2651 3518 +3817 2658 3516 +3815 2668 3513 +3813 2680 3510 +3810 2696 3506 +3806 2717 3500 +3801 2743 3492 +3794 2776 3481 +3784 2817 3467 +3771 2866 3446 +3752 2924 3417 +3726 2992 3375 +3689 3069 3312 +3633 3156 3210 +3547 3251 3026 +3398 3353 2524 +3064 3461 0 +0 3574 0 +0 3692 0 +3954 2760 3655 +3954 2761 3655 +3954 2761 3654 +3954 2761 3654 +3954 2761 3654 +3954 2762 3654 +3953 2762 3654 +3953 2763 3654 +3953 2764 3654 +3953 2765 3653 +3953 2767 3653 +3952 2769 3652 +3952 2773 3652 +3951 2777 3651 +3950 2782 3649 +3949 2790 3648 +3947 2799 3645 +3945 2812 3642 +3942 2828 3638 +3939 2848 3632 +3933 2875 3624 +3926 2908 3613 +3916 2948 3598 +3903 2997 3578 +3884 3056 3549 +3858 3124 3507 +3821 3201 3443 +3766 3288 3342 +3679 3383 3158 +3530 3485 2655 +3196 3593 0 +0 3706 0 +4086 2892 3787 +4086 2892 3787 +4086 2892 3787 +4086 2892 3786 +4086 2893 3786 +4086 2893 3786 +4086 2893 3786 +4086 2894 3786 +4086 2895 3786 +4085 2896 3786 +4085 2897 3785 +4085 2899 3785 +4084 2901 3784 +4084 2904 3784 +4083 2908 3783 +4082 2914 3781 +4081 2921 3780 +4080 2931 3777 +4077 2943 3774 +4075 2959 3770 +4071 2980 3764 +4065 3006 3756 +4058 3039 3745 +4048 3080 3730 +4035 3129 3710 +4016 3188 3681 +3990 3256 3639 +3953 3333 3575 +3898 3420 3474 +3811 3515 3289 +3662 3617 2786 +3329 3725 0 +4095 3024 3919 +4095 3024 3919 +4095 3024 3919 +4095 3024 3919 +4095 3024 3918 +4095 3024 3918 +4095 3025 3918 +4095 3025 3918 +4095 3026 3918 +4095 3026 3918 +4095 3027 3918 +4095 3029 3917 +4095 3030 3917 +4095 3033 3916 +4095 3036 3916 +4095 3040 3915 +4095 3046 3913 +4095 3053 3912 +4095 3062 3909 +4095 3075 3906 +4095 3091 3902 +4095 3112 3896 +4095 3138 3888 +4095 3171 3877 +4095 3212 3862 +4095 3261 3842 +4095 3320 3813 +4095 3388 3771 +4085 3465 3707 +4030 3552 3606 +3943 3647 3421 +3794 3749 2917 +4095 3155 4051 +4095 3155 4051 +4095 3155 4051 +4095 3156 4051 +4095 3156 4051 +4095 3156 4051 +4095 3156 4050 +4095 3156 4050 +4095 3157 4050 +4095 3157 4050 +4095 3158 4050 +4095 3159 4050 +4095 3161 4049 +4095 3162 4049 +4095 3165 4048 +4095 3168 4048 +4095 3172 4047 +4095 3177 4045 +4095 3185 4044 +4095 3194 4041 +4095 3207 4038 +4095 3223 4034 +4095 3244 4028 +4095 3270 4020 +4095 3303 4009 +4095 3344 3994 +4095 3393 3974 +4095 3452 3945 +4095 3520 3903 +4095 3597 3839 +4095 3684 3738 +4076 3779 3553 +0 494 709 +0 513 690 +0 537 662 +0 567 621 +0 604 561 +0 650 466 +0 705 295 +0 770 0 +0 843 0 +0 927 0 +0 1018 0 +0 1118 0 +0 1223 0 +0 1335 0 +0 1451 0 +0 1571 0 +0 1693 0 +0 1818 0 +0 1945 0 +0 2073 0 +0 2202 0 +0 2332 0 +0 2462 0 +0 2593 0 +0 2724 0 +0 2855 0 +0 2987 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +0 500 738 +0 519 719 +0 543 693 +0 572 655 +0 610 600 +0 655 513 +0 709 363 +0 773 25 +0 846 0 +0 929 0 +0 1020 0 +0 1119 0 +0 1225 0 +0 1336 0 +0 1452 0 +0 1571 0 +0 1694 0 +0 1819 0 +0 1945 0 +0 2073 0 +0 2202 0 +0 2332 0 +0 2462 0 +0 2593 0 +0 2724 0 +0 2855 0 +0 2987 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +0 509 773 +0 527 756 +0 550 732 +0 580 697 +0 616 647 +0 661 569 +0 715 440 +0 778 174 +0 850 0 +0 932 0 +0 1023 0 +0 1121 0 +0 1227 0 +0 1337 0 +0 1453 0 +0 1572 0 +0 1694 0 +0 1819 0 +0 1946 0 +0 2073 0 +0 2202 0 +0 2332 0 +0 2462 0 +0 2593 0 +0 2724 0 +0 2855 0 +0 2987 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +66 520 816 +0 538 801 +0 561 779 +0 589 748 +0 625 703 +0 669 635 +0 722 525 +0 784 318 +0 856 0 +0 937 0 +0 1027 0 +0 1124 0 +0 1229 0 +0 1339 0 +0 1454 0 +0 1573 0 +0 1695 0 +0 1820 0 +0 1946 0 +0 2074 0 +0 2202 0 +0 2332 0 +0 2462 0 +0 2593 0 +0 2724 0 +0 2855 0 +0 2987 0 +0 3118 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +429 534 868 +379 552 854 +302 574 835 +173 602 808 +0 637 769 +0 680 711 +0 731 620 +0 792 459 +0 863 78 +0 943 0 +0 1031 0 +0 1128 0 +0 1232 0 +0 1342 0 +0 1456 0 +0 1575 0 +0 1696 0 +0 1821 0 +0 1947 0 +0 2074 0 +0 2203 0 +0 2332 0 +0 2463 0 +0 2593 0 +0 2724 0 +0 2855 0 +0 2987 0 +0 3119 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +680 553 930 +652 570 918 +611 591 901 +550 618 878 +454 652 844 +281 693 796 +0 743 721 +0 803 597 +0 872 351 +0 950 0 +0 1038 0 +0 1133 0 +0 1236 0 +0 1345 0 +0 1459 0 +0 1577 0 +0 1698 0 +0 1822 0 +0 1948 0 +0 2075 0 +0 2203 0 +0 2333 0 +0 2463 0 +0 2593 0 +0 2724 0 +0 2856 0 +0 2987 0 +0 3119 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +884 577 1001 +866 593 990 +841 613 976 +806 639 956 +753 671 929 +672 711 889 +534 759 829 +243 817 734 +0 884 566 +0 960 150 +0 1046 0 +0 1140 0 +0 1241 0 +0 1349 0 +0 1462 0 +0 1579 0 +0 1700 0 +0 1823 0 +0 1949 0 +0 2076 0 +0 2204 0 +0 2333 0 +0 2463 0 +0 2594 0 +0 2725 0 +0 2856 0 +0 2987 0 +0 3119 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +1063 607 1081 +1051 622 1072 +1035 641 1061 +1012 665 1044 +979 696 1022 +932 733 989 +859 780 942 +739 835 870 +505 899 751 +0 974 520 +0 1057 0 +0 1149 0 +0 1249 0 +0 1355 0 +0 1466 0 +0 1583 0 +0 1702 0 +0 1825 0 +0 1950 0 +0 2077 0 +0 2205 0 +0 2334 0 +0 2464 0 +0 2594 0 +0 2725 0 +0 2856 0 +0 2987 0 +0 3119 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +1228 644 1170 +1219 658 1163 +1208 676 1153 +1193 698 1140 +1171 727 1122 +1140 762 1096 +1096 805 1059 +1029 858 1005 +919 919 919 +715 991 773 +63 1071 450 +0 1161 0 +0 1258 0 +0 1362 0 +0 1472 0 +0 1587 0 +0 1706 0 +0 1828 0 +0 1952 0 +0 2078 0 +0 2206 0 +0 2335 0 +0 2464 0 +0 2594 0 +0 2725 0 +0 2856 0 +0 2987 0 +0 3119 0 +0 3251 0 +0 3382 0 +0 3514 0 +0 3646 0 +1383 690 1267 +1377 702 1262 +1369 718 1254 +1358 739 1243 +1343 765 1229 +1322 798 1208 +1293 838 1180 +1250 887 1139 +1187 945 1077 +1084 1013 978 +897 1090 801 +377 1176 337 +0 1270 0 +0 1372 0 +0 1480 0 +0 1593 0 +0 1711 0 +0 1831 0 +0 1955 0 +0 2080 0 +0 2208 0 +0 2336 0 +0 2465 0 +0 2595 0 +0 2726 0 +0 2857 0 +0 2988 0 +0 3119 0 +0 3251 0 +0 3382 0 +0 3514 0 +0 3646 0 +1531 745 1371 +1527 756 1367 +1521 770 1361 +1513 788 1352 +1503 812 1341 +1488 841 1325 +1468 878 1303 +1440 923 1272 +1399 977 1227 +1337 1040 1158 +1239 1113 1047 +1064 1195 835 +609 1286 120 +0 1385 0 +0 1490 0 +0 1601 0 +0 1717 0 +0 1836 0 +0 1958 0 +0 2083 0 +0 2210 0 +0 2337 0 +0 2466 0 +0 2596 0 +0 2726 0 +0 2857 0 +0 2988 0 +0 3119 0 +0 3251 0 +0 3383 0 +0 3514 0 +0 3646 0 +1675 809 1481 +1672 818 1478 +1668 831 1473 +1662 847 1466 +1655 867 1458 +1644 894 1445 +1630 927 1429 +1610 967 1405 +1582 1016 1372 +1542 1075 1323 +1483 1143 1249 +1388 1220 1125 +1220 1307 878 +804 1401 0 +0 1503 0 +0 1611 0 +0 1725 0 +0 1842 0 +0 1963 0 +0 2087 0 +0 2212 0 +0 2340 0 +0 2468 0 +0 2597 0 +0 2727 0 +0 2858 0 +0 2989 0 +0 3120 0 +0 3251 0 +0 3383 0 +0 3515 0 +0 3646 0 +1816 882 1596 +1813 890 1593 +1810 901 1590 +1806 915 1585 +1801 933 1578 +1793 955 1569 +1783 984 1556 +1769 1020 1538 +1750 1064 1514 +1722 1117 1478 +1683 1179 1427 +1625 1251 1347 +1532 1333 1212 +1369 1422 929 +978 1520 0 +0 1625 0 +0 1735 0 +0 1850 0 +0 1969 0 +0 2092 0 +0 2216 0 +0 2342 0 +0 2470 0 +0 2599 0 +0 2728 0 +0 2859 0 +0 2989 0 +0 3120 0 +0 3252 0 +0 3383 0 +0 3515 0 +0 3647 0 +1954 965 1715 +1952 972 1713 +1950 981 1710 +1947 992 1706 +1943 1007 1701 +1938 1027 1694 +1930 1052 1684 +1920 1083 1671 +1906 1121 1653 +1887 1168 1627 +1860 1224 1590 +1821 1290 1536 +1764 1365 1452 +1673 1449 1307 +1514 1542 989 +1139 1642 0 +0 1749 0 +0 1861 0 +0 1978 0 +0 2098 0 +0 2221 0 +0 2346 0 +0 2473 0 +0 2601 0 +0 2730 0 +0 2860 0 +0 2990 0 +0 3121 0 +0 3252 0 +0 3383 0 +0 3515 0 +0 3647 0 +2091 1056 1837 +2090 1062 1835 +2088 1069 1833 +2086 1079 1830 +2083 1091 1826 +2079 1108 1821 +2073 1129 1813 +2066 1155 1803 +2056 1188 1790 +2042 1229 1771 +2023 1278 1745 +1997 1337 1707 +1958 1405 1650 +1901 1483 1562 +1812 1570 1409 +1655 1664 1059 +1292 1767 0 +0 1875 0 +0 1988 0 +0 2106 0 +0 2227 0 +0 2351 0 +0 2476 0 +0 2604 0 +0 2732 0 +0 2861 0 +0 2991 0 +0 3122 0 +0 3253 0 +0 3384 0 +0 3515 0 +0 3647 0 +2227 1156 1961 +2226 1160 1960 +2224 1166 1958 +2223 1174 1956 +2221 1184 1953 +2218 1197 1949 +2214 1214 1943 +2208 1236 1936 +2201 1264 1926 +2191 1299 1912 +2177 1342 1893 +2158 1393 1866 +2132 1454 1827 +2094 1524 1769 +2037 1604 1678 +1948 1693 1517 +1794 1789 1139 +1439 1893 0 +0 2002 0 +0 2117 0 +0 2235 0 +0 2357 0 +0 2481 0 +0 2607 0 +0 2735 0 +0 2863 0 +0 2993 0 +0 3123 0 +0 3254 0 +0 3385 0 +0 3516 0 +0 3647 0 +2361 1261 2087 +2361 1265 2086 +2360 1270 2085 +2358 1276 2083 +2357 1284 2081 +2355 1295 2078 +2352 1309 2074 +2348 1327 2068 +2342 1349 2061 +2335 1378 2050 +2325 1415 2036 +2312 1459 2017 +2293 1512 1989 +2266 1574 1949 +2228 1646 1890 +2172 1728 1797 +2084 1818 1631 +1931 1916 1227 +1581 2021 0 +0 2131 0 +0 2246 0 +0 2365 0 +0 2488 0 +0 2612 0 +0 2738 0 +0 2866 0 +0 2995 0 +0 3125 0 +0 3255 0 +0 3386 0 +0 3517 0 +0 3648 0 +2495 1373 2215 +2495 1376 2214 +2494 1379 2213 +2493 1384 2212 +2492 1391 2210 +2490 1399 2208 +2488 1410 2205 +2485 1424 2201 +2481 1443 2195 +2476 1467 2187 +2469 1497 2177 +2459 1534 2163 +2445 1579 2143 +2427 1634 2115 +2400 1698 2074 +2362 1771 2014 +2306 1854 1919 +2219 1945 1749 +2066 2044 1323 +1721 2149 0 +0 2261 0 +0 2376 0 +0 2496 0 +0 2619 0 +0 2743 0 +0 2870 0 +0 2998 0 +0 3127 0 +0 3256 0 +0 3387 0 +0 3517 0 +0 3649 0 +2629 1489 2343 +2628 1491 2343 +2628 1494 2342 +2627 1497 2341 +2626 1503 2340 +2625 1509 2338 +2623 1518 2336 +2621 1529 2333 +2618 1544 2329 +2614 1563 2323 +2609 1588 2315 +2602 1618 2305 +2592 1656 2290 +2579 1703 2270 +2560 1758 2242 +2534 1823 2201 +2496 1897 2140 +2440 1981 2043 +2353 2073 1870 +2201 2173 1427 +1859 2279 0 +0 2391 0 +0 2507 0 +0 2627 0 +0 2750 0 +0 2875 0 +0 3001 0 +0 3129 0 +0 3258 0 +0 3388 0 +0 3519 0 +0 3649 0 +2762 1608 2473 +2762 1610 2473 +2761 1612 2472 +2761 1615 2471 +2760 1619 2470 +2759 1624 2469 +2758 1631 2467 +2756 1640 2465 +2754 1652 2462 +2751 1667 2458 +2747 1686 2452 +2742 1711 2444 +2735 1742 2434 +2725 1781 2419 +2712 1828 2399 +2693 1884 2370 +2667 1950 2329 +2629 2025 2268 +2573 2109 2170 +2486 2202 1993 +2335 2302 1536 +1996 2409 0 +0 2521 0 +0 2638 0 +0 2758 0 +0 2881 0 +0 3006 0 +0 3133 0 +0 3261 0 +0 3390 0 +0 3520 0 +0 3651 0 +2895 1731 2603 +2895 1732 2603 +2894 1734 2602 +2894 1736 2602 +2893 1739 2601 +2893 1743 2600 +2892 1748 2599 +2891 1755 2597 +2889 1764 2595 +2887 1776 2592 +2884 1791 2587 +2880 1811 2582 +2875 1836 2574 +2868 1868 2563 +2858 1907 2549 +2844 1955 2528 +2826 2012 2500 +2800 2078 2458 +2762 2154 2396 +2706 2239 2298 +2619 2332 2119 +2469 2433 1651 +2131 2540 0 +0 2652 0 +0 2769 0 +0 2890 0 +0 3013 0 +0 3138 0 +0 3265 0 +0 3393 0 +0 3522 0 +0 3652 0 +3028 1856 2734 +3027 1857 2734 +3027 1858 2733 +3027 1860 2733 +3027 1862 2732 +3026 1865 2732 +3025 1869 2731 +3024 1874 2729 +3023 1881 2728 +3022 1890 2725 +3019 1902 2722 +3017 1918 2718 +3013 1938 2712 +3007 1964 2704 +3000 1996 2694 +2990 2035 2679 +2977 2083 2658 +2958 2140 2630 +2932 2207 2588 +2895 2283 2526 +2839 2369 2426 +2752 2462 2246 +2602 2563 1769 +2265 2671 0 +0 2784 0 +0 2901 0 +0 3021 0 +0 3144 0 +0 3270 0 +0 3397 0 +0 3525 0 +0 3654 0 +3160 1982 2865 +3160 1983 2865 +3160 1984 2864 +3160 1985 2864 +3159 1987 2864 +3159 1989 2863 +3158 1992 2862 +3158 1996 2861 +3157 2002 2860 +3156 2009 2858 +3154 2018 2856 +3152 2030 2853 +3149 2046 2849 +3145 2066 2843 +3140 2092 2835 +3133 2124 2824 +3123 2164 2810 +3109 2212 2789 +3091 2270 2760 +3065 2337 2719 +3027 2414 2656 +2972 2499 2556 +2885 2593 2375 +2735 2695 1890 +2399 2802 0 +0 2915 0 +0 3032 0 +0 3153 0 +0 3276 0 +0 3402 0 +0 3529 0 +0 3657 0 +3292 2110 2996 +3292 2111 2996 +3292 2111 2996 +3292 2112 2996 +3292 2114 2995 +3292 2116 2995 +3291 2118 2994 +3291 2121 2994 +3290 2125 2993 +3289 2130 2991 +3288 2138 2990 +3286 2147 2987 +3284 2159 2984 +3281 2175 2980 +3277 2195 2974 +3272 2221 2966 +3265 2254 2955 +3255 2294 2941 +3242 2342 2920 +3223 2400 2891 +3197 2467 2849 +3160 2544 2787 +3104 2630 2686 +3018 2724 2504 +2868 2826 2015 +2533 2934 0 +0 3047 0 +0 3164 0 +0 3285 0 +0 3408 0 +0 3534 0 +0 3661 0 +3425 2239 3128 +3425 2240 3127 +3425 2240 3127 +3425 2241 3127 +3424 2242 3127 +3424 2243 3127 +3424 2245 3126 +3424 2247 3126 +3423 2250 3125 +3422 2254 3124 +3421 2260 3123 +3420 2267 3121 +3419 2276 3119 +3417 2289 3115 +3414 2305 3111 +3410 2325 3105 +3404 2351 3097 +3397 2384 3087 +3387 2424 3072 +3374 2473 3051 +3355 2531 3022 +3329 2598 2980 +3292 2675 2918 +3237 2761 2817 +3150 2856 2634 +3000 2957 2141 +2666 3065 0 +0 3178 0 +0 3296 0 +0 3417 0 +0 3540 0 +0 3666 0 +3557 2369 3259 +3557 2369 3259 +3557 2370 3259 +3557 2370 3259 +3557 2371 3259 +3557 2372 3259 +3556 2373 3258 +3556 2375 3258 +3556 2377 3257 +3555 2380 3257 +3555 2385 3256 +3554 2390 3254 +3553 2397 3252 +3551 2407 3250 +3549 2419 3247 +3546 2435 3243 +3542 2456 3237 +3537 2482 3229 +3529 2514 3218 +3520 2555 3203 +3506 2604 3183 +3488 2662 3154 +3462 2729 3112 +3424 2807 3049 +3369 2893 2948 +3282 2987 2765 +3133 3089 2268 +2799 3197 0 +0 3310 0 +0 3428 0 +0 3549 0 +0 3672 0 +3689 2499 3391 +3689 2499 3391 +3689 2500 3391 +3689 2500 3391 +3689 2501 3391 +3689 2501 3390 +3689 2502 3390 +3689 2504 3390 +3688 2506 3390 +3688 2508 3389 +3687 2511 3388 +3687 2515 3387 +3686 2521 3386 +3685 2528 3384 +3683 2537 3382 +3681 2550 3379 +3678 2566 3374 +3674 2586 3369 +3669 2613 3361 +3662 2645 3350 +3652 2686 3335 +3639 2735 3314 +3620 2793 3285 +3594 2861 3243 +3556 2938 3180 +3501 3024 3079 +3415 3119 2896 +3265 3221 2397 +2931 3329 0 +0 3442 0 +0 3560 0 +0 3681 0 +3822 2630 3523 +3822 2630 3523 +3821 2630 3523 +3821 2631 3523 +3821 2631 3523 +3821 2632 3522 +3821 2632 3522 +3821 2633 3522 +3821 2635 3522 +3821 2637 3521 +3820 2639 3521 +3820 2642 3520 +3819 2646 3519 +3818 2652 3518 +3817 2659 3516 +3815 2668 3514 +3813 2681 3510 +3810 2697 3506 +3806 2717 3500 +3801 2744 3492 +3794 2777 3482 +3784 2817 3467 +3771 2866 3446 +3752 2925 3417 +3726 2992 3375 +3689 3070 3312 +3633 3156 3211 +3547 3251 3027 +3398 3353 2526 +3064 3461 0 +0 3574 0 +0 3692 0 +3954 2761 3655 +3954 2761 3655 +3954 2761 3655 +3954 2762 3655 +3954 2762 3655 +3954 2762 3654 +3953 2763 3654 +3953 2764 3654 +3953 2765 3654 +3953 2766 3654 +3953 2768 3653 +3952 2770 3653 +3952 2773 3652 +3951 2777 3651 +3950 2783 3650 +3949 2790 3648 +3947 2800 3645 +3945 2812 3642 +3942 2828 3638 +3938 2849 3632 +3933 2875 3624 +3926 2908 3614 +3916 2949 3599 +3903 2998 3578 +3884 3056 3549 +3858 3124 3507 +3821 3202 3444 +3766 3288 3343 +3679 3383 3158 +3530 3485 2656 +3196 3593 0 +0 3706 0 +4086 2892 3787 +4086 2893 3787 +4086 2893 3787 +4086 2893 3787 +4086 2893 3787 +4086 2893 3786 +4086 2894 3786 +4086 2894 3786 +4085 2895 3786 +4085 2896 3786 +4085 2897 3786 +4085 2899 3785 +4084 2902 3785 +4084 2905 3784 +4083 2909 3783 +4082 2914 3782 +4081 2922 3780 +4080 2931 3777 +4077 2944 3774 +4075 2960 3770 +4071 2980 3764 +4065 3007 3756 +4058 3040 3745 +4048 3080 3731 +4035 3130 3710 +4016 3188 3681 +3990 3256 3639 +3953 3333 3575 +3898 3420 3474 +3811 3515 3290 +3662 3617 2787 +3328 3725 0 +4095 3024 3919 +4095 3024 3919 +4095 3024 3919 +4095 3024 3919 +4095 3024 3919 +4095 3025 3919 +4095 3025 3918 +4095 3025 3918 +4095 3026 3918 +4095 3027 3918 +4095 3028 3918 +4095 3029 3918 +4095 3031 3917 +4095 3033 3917 +4095 3036 3916 +4095 3040 3915 +4095 3046 3914 +4095 3053 3912 +4095 3063 3909 +4095 3075 3906 +4095 3091 3902 +4095 3112 3896 +4095 3138 3888 +4095 3171 3877 +4095 3212 3863 +4095 3261 3842 +4095 3320 3813 +4095 3388 3771 +4085 3465 3707 +4030 3552 3606 +3943 3647 3422 +3794 3749 2918 +4095 3156 4051 +4095 3156 4051 +4095 3156 4051 +4095 3156 4051 +4095 3156 4051 +4095 3156 4051 +4095 3156 4051 +4095 3157 4050 +4095 3157 4050 +4095 3158 4050 +4095 3158 4050 +4095 3159 4050 +4095 3161 4050 +4095 3163 4049 +4095 3165 4049 +4095 3168 4048 +4095 3172 4047 +4095 3178 4046 +4095 3185 4044 +4095 3195 4041 +4095 3207 4038 +4095 3223 4034 +4095 3244 4028 +4095 3270 4020 +4095 3303 4009 +4095 3344 3995 +4095 3393 3974 +4095 3452 3945 +4095 3520 3903 +4095 3597 3839 +4095 3684 3738 +4076 3779 3553 +0 606 834 +0 621 819 +0 640 798 +0 664 769 +0 695 726 +0 733 662 +0 779 559 +0 834 370 +0 899 0 +0 973 0 +0 1057 0 +0 1149 0 +0 1248 0 +0 1355 0 +0 1466 0 +0 1583 0 +0 1702 0 +0 1825 0 +0 1950 0 +0 2077 0 +0 2205 0 +0 2334 0 +0 2464 0 +0 2594 0 +0 2725 0 +0 2856 0 +0 2987 0 +0 3119 0 +0 3250 0 +0 3382 0 +0 3514 0 +0 3646 0 +0 611 856 +0 626 842 +0 645 822 +0 669 794 +0 699 753 +0 737 693 +0 782 598 +0 837 427 +0 902 2 +0 976 0 +0 1059 0 +0 1150 0 +0 1250 0 +0 1356 0 +0 1467 0 +0 1583 0 +0 1703 0 +0 1825 0 +0 1950 0 +0 2077 0 +0 2205 0 +0 2334 0 +0 2464 0 +0 2594 0 +0 2725 0 +0 2856 0 +0 2987 0 +0 3119 0 +0 3251 0 +0 3382 0 +0 3514 0 +0 3646 0 +0 618 883 +0 632 870 +0 651 851 +0 675 825 +0 705 788 +0 742 732 +0 787 645 +0 841 495 +0 905 157 +0 979 0 +0 1061 0 +0 1152 0 +0 1251 0 +0 1357 0 +0 1468 0 +0 1584 0 +0 1703 0 +0 1826 0 +0 1951 0 +0 2077 0 +0 2205 0 +0 2334 0 +0 2464 0 +0 2594 0 +0 2725 0 +0 2856 0 +0 2987 0 +0 3119 0 +0 3251 0 +0 3382 0 +0 3514 0 +0 3646 0 +0 627 918 +0 641 905 +0 659 888 +0 682 864 +0 712 829 +0 748 779 +0 793 702 +0 847 572 +0 910 306 +0 983 0 +0 1064 0 +0 1155 0 +0 1253 0 +0 1359 0 +0 1469 0 +0 1585 0 +0 1704 0 +0 1827 0 +0 1951 0 +0 2078 0 +0 2205 0 +0 2334 0 +0 2464 0 +0 2594 0 +0 2725 0 +0 2856 0 +0 2987 0 +0 3119 0 +0 3251 0 +0 3382 0 +0 3514 0 +0 3646 0 +271 638 960 +198 652 948 +78 670 933 +0 693 911 +0 721 880 +0 757 835 +0 801 768 +0 854 657 +0 916 450 +0 988 0 +0 1069 0 +0 1159 0 +0 1256 0 +0 1361 0 +0 1471 0 +0 1586 0 +0 1705 0 +0 1827 0 +0 1952 0 +0 2078 0 +0 2206 0 +0 2335 0 +0 2464 0 +0 2594 0 +0 2725 0 +0 2856 0 +0 2987 0 +0 3119 0 +0 3251 0 +0 3382 0 +0 3514 0 +0 3646 0 +595 653 1011 +561 667 1000 +511 684 986 +434 706 967 +305 734 940 +43 769 901 +0 812 843 +0 863 752 +0 924 591 +0 995 210 +0 1075 0 +0 1164 0 +0 1260 0 +0 1364 0 +0 1474 0 +0 1588 0 +0 1707 0 +0 1829 0 +0 1953 0 +0 2079 0 +0 2206 0 +0 2335 0 +0 2464 0 +0 2595 0 +0 2725 0 +0 2856 0 +0 2988 0 +0 3119 0 +0 3251 0 +0 3382 0 +0 3514 0 +0 3646 0 +832 672 1071 +812 685 1062 +784 702 1050 +743 723 1033 +682 750 1010 +586 784 976 +413 825 928 +0 875 853 +0 935 729 +0 1004 483 +0 1082 0 +0 1170 0 +0 1265 0 +0 1368 0 +0 1477 0 +0 1591 0 +0 1709 0 +0 1830 0 +0 1954 0 +0 2080 0 +0 2207 0 +0 2335 0 +0 2465 0 +0 2595 0 +0 2725 0 +0 2856 0 +0 2988 0 +0 3119 0 +0 3251 0 +0 3382 0 +0 3514 0 +0 3646 0 +1029 697 1140 +1016 709 1133 +998 725 1122 +973 745 1108 +938 771 1089 +885 803 1061 +804 843 1021 +666 891 961 +375 949 866 +0 1016 698 +0 1093 282 +0 1178 0 +0 1272 0 +0 1374 0 +0 1481 0 +0 1594 0 +0 1711 0 +0 1832 0 +0 1955 0 +0 2081 0 +0 2208 0 +0 2336 0 +0 2465 0 +0 2595 0 +0 2726 0 +0 2857 0 +0 2988 0 +0 3119 0 +0 3251 0 +0 3383 0 +0 3514 0 +0 3646 0 +1204 728 1220 +1195 739 1213 +1183 754 1205 +1167 773 1193 +1144 797 1176 +1111 828 1154 +1064 866 1121 +991 912 1074 +872 967 1002 +637 1032 883 +0 1106 652 +0 1189 0 +0 1281 0 +0 1381 0 +0 1487 0 +0 1599 0 +0 1715 0 +0 1835 0 +0 1957 0 +0 2082 0 +0 2209 0 +0 2337 0 +0 2466 0 +0 2596 0 +0 2726 0 +0 2857 0 +0 2988 0 +0 3119 0 +0 3251 0 +0 3383 0 +0 3514 0 +0 3646 0 +1366 766 1308 +1360 777 1302 +1352 790 1295 +1340 808 1286 +1325 830 1272 +1303 859 1254 +1272 894 1228 +1228 938 1191 +1161 990 1137 +1052 1052 1052 +847 1123 905 +195 1203 583 +0 1293 0 +0 1390 0 +0 1494 0 +0 1604 0 +0 1719 0 +0 1838 0 +0 1960 0 +0 2084 0 +0 2210 0 +0 2338 0 +0 2467 0 +0 2596 0 +0 2727 0 +0 2857 0 +0 2988 0 +0 3120 0 +0 3251 0 +0 3383 0 +0 3514 0 +0 3646 0 +1519 813 1404 +1515 822 1399 +1509 834 1394 +1501 850 1386 +1490 871 1375 +1475 897 1361 +1454 930 1341 +1425 970 1312 +1383 1019 1271 +1319 1077 1209 +1216 1145 1110 +1029 1222 933 +509 1308 469 +0 1402 0 +0 1504 0 +0 1612 0 +0 1725 0 +0 1843 0 +0 1963 0 +0 2087 0 +0 2213 0 +0 2340 0 +0 2468 0 +0 2597 0 +0 2727 0 +0 2858 0 +0 2989 0 +0 3120 0 +0 3251 0 +0 3383 0 +0 3515 0 +0 3646 0 +1666 868 1507 +1663 877 1504 +1659 888 1499 +1653 902 1493 +1645 920 1484 +1635 944 1473 +1620 973 1457 +1600 1010 1435 +1572 1055 1404 +1531 1109 1359 +1469 1172 1290 +1372 1245 1179 +1196 1327 967 +741 1418 252 +0 1517 0 +0 1622 0 +0 1733 0 +0 1849 0 +0 1968 0 +0 2091 0 +0 2215 0 +0 2342 0 +0 2470 0 +0 2598 0 +0 2728 0 +0 2858 0 +0 2989 0 +0 3120 0 +0 3252 0 +0 3383 0 +0 3515 0 +0 3647 0 +1809 933 1616 +1807 941 1613 +1804 950 1610 +1800 963 1605 +1794 979 1599 +1787 999 1590 +1776 1026 1578 +1762 1059 1561 +1742 1099 1537 +1715 1148 1504 +1675 1207 1455 +1615 1275 1381 +1520 1352 1257 +1352 1439 1010 +936 1533 0 +0 1635 0 +0 1743 0 +0 1857 0 +0 1974 0 +0 2095 0 +0 2219 0 +0 2344 0 +0 2472 0 +0 2600 0 +0 2729 0 +0 2859 0 +0 2990 0 +0 3121 0 +0 3252 0 +0 3383 0 +0 3515 0 +0 3647 0 +1949 1008 1730 +1948 1014 1728 +1946 1022 1725 +1943 1033 1722 +1938 1047 1717 +1933 1065 1710 +1925 1088 1701 +1915 1116 1688 +1901 1152 1670 +1882 1196 1646 +1855 1249 1610 +1815 1312 1559 +1757 1383 1479 +1664 1465 1344 +1501 1555 1061 +1110 1652 0 +0 1757 0 +0 1867 0 +0 1983 0 +0 2102 0 +0 2224 0 +0 2348 0 +0 2474 0 +0 2602 0 +0 2731 0 +0 2860 0 +0 2991 0 +0 3121 0 +0 3252 0 +0 3384 0 +0 3515 0 +0 3647 0 +2087 1092 1849 +2086 1097 1847 +2085 1104 1845 +2082 1113 1842 +2079 1124 1838 +2075 1140 1833 +2070 1159 1826 +2062 1184 1816 +2052 1215 1803 +2039 1254 1785 +2019 1300 1759 +1992 1357 1722 +1954 1422 1668 +1896 1497 1584 +1805 1581 1439 +1646 1674 1121 +1271 1774 0 +0 1881 0 +0 1993 0 +0 2110 0 +0 2230 0 +0 2353 0 +0 2478 0 +0 2605 0 +0 2733 0 +0 2862 0 +0 2992 0 +0 3122 0 +0 3253 0 +0 3384 0 +0 3516 0 +0 3647 0 +2224 1184 1970 +2223 1189 1969 +2222 1194 1967 +2220 1201 1965 +2218 1211 1962 +2215 1224 1958 +2211 1240 1953 +2206 1261 1945 +2198 1287 1936 +2188 1320 1922 +2175 1361 1903 +2156 1410 1877 +2129 1469 1839 +2090 1537 1782 +2033 1615 1694 +1944 1702 1541 +1787 1797 1191 +1424 1899 0 +0 2007 0 +0 2121 0 +0 2238 0 +0 2359 0 +0 2483 0 +0 2608 0 +0 2736 0 +0 2864 0 +0 2993 0 +0 3123 0 +0 3254 0 +0 3385 0 +0 3516 0 +0 3648 0 +2359 1284 2094 +2359 1288 2093 +2358 1292 2092 +2357 1298 2090 +2355 1306 2088 +2353 1316 2085 +2350 1329 2081 +2346 1346 2075 +2340 1368 2068 +2333 1396 2058 +2323 1431 2044 +2309 1474 2025 +2291 1525 1998 +2264 1586 1959 +2226 1656 1901 +2169 1736 1810 +2080 1825 1649 +1926 1921 1271 +1571 2025 0 +0 2135 0 +0 2249 0 +0 2368 0 +0 2489 0 +0 2613 0 +0 2739 0 +0 2867 0 +0 2995 0 +0 3125 0 +0 3255 0 +0 3386 0 +0 3517 0 +0 3648 0 +2494 1391 2220 +2493 1393 2219 +2493 1397 2218 +2492 1402 2217 +2491 1408 2215 +2489 1416 2213 +2487 1427 2210 +2484 1441 2206 +2480 1459 2200 +2474 1482 2193 +2467 1511 2183 +2457 1547 2168 +2444 1591 2149 +2425 1644 2121 +2398 1706 2082 +2361 1779 2022 +2304 1860 1929 +2216 1950 1763 +2063 2048 1359 +1714 2153 0 +0 2263 0 +0 2378 0 +0 2498 0 +0 2620 0 +0 2744 0 +0 2871 0 +0 2998 0 +0 3127 0 +0 3257 0 +0 3387 0 +0 3518 0 +0 3649 0 +2628 1503 2347 +2627 1505 2347 +2627 1508 2346 +2626 1511 2345 +2625 1516 2344 +2624 1523 2342 +2622 1531 2340 +2620 1542 2337 +2617 1557 2333 +2613 1575 2327 +2608 1599 2319 +2601 1629 2309 +2591 1666 2295 +2577 1711 2275 +2559 1766 2247 +2532 1830 2207 +2495 1903 2146 +2438 1986 2051 +2351 2077 1881 +2199 2176 1456 +1853 2281 0 +0 2393 0 +0 2509 0 +0 2628 0 +0 2751 0 +0 2875 0 +0 3002 0 +0 3130 0 +0 3259 0 +0 3388 0 +0 3519 0 +0 3650 0 +2761 1619 2476 +2761 1621 2476 +2760 1623 2475 +2760 1626 2474 +2759 1630 2473 +2758 1635 2472 +2757 1641 2470 +2756 1650 2468 +2753 1661 2465 +2750 1676 2461 +2747 1695 2455 +2741 1720 2447 +2734 1750 2437 +2724 1788 2422 +2711 1835 2402 +2692 1890 2374 +2666 1955 2333 +2628 2029 2272 +2572 2113 2176 +2485 2205 2002 +2333 2305 1559 +1991 2411 0 +0 2523 0 +0 2639 0 +0 2759 0 +0 2882 0 +0 3007 0 +0 3134 0 +0 3262 0 +0 3391 0 +0 3520 0 +0 3651 0 +2894 1739 2605 +2894 1740 2605 +2894 1742 2605 +2893 1744 2604 +2893 1747 2603 +2892 1751 2602 +2891 1756 2601 +2890 1763 2599 +2888 1772 2597 +2886 1784 2594 +2883 1799 2590 +2879 1818 2584 +2874 1843 2576 +2867 1874 2566 +2857 1913 2551 +2844 1960 2531 +2825 2016 2502 +2799 2082 2461 +2761 2157 2400 +2705 2241 2302 +2618 2334 2125 +2468 2434 1668 +2128 2541 0 +0 2653 0 +0 2770 0 +0 2890 0 +0 3013 0 +0 3138 0 +0 3265 0 +0 3393 0 +0 3522 0 +0 3652 0 +3027 1862 2735 +3027 1863 2735 +3027 1864 2735 +3026 1866 2735 +3026 1868 2734 +3026 1871 2733 +3025 1875 2732 +3024 1880 2731 +3023 1887 2729 +3021 1896 2727 +3019 1908 2724 +3016 1924 2720 +3012 1943 2714 +3007 1969 2706 +3000 2000 2695 +2990 2039 2681 +2976 2087 2660 +2958 2144 2632 +2932 2210 2590 +2894 2286 2528 +2838 2371 2430 +2752 2464 2251 +2601 2565 1783 +2263 2672 0 +0 2784 0 +0 2901 0 +0 3022 0 +0 3145 0 +0 3270 0 +0 3397 0 +0 3525 0 +0 3654 0 +3160 1987 2866 +3160 1988 2866 +3159 1989 2866 +3159 1990 2865 +3159 1992 2865 +3159 1994 2864 +3158 1997 2864 +3157 2001 2863 +3157 2006 2861 +3155 2013 2860 +3154 2023 2857 +3152 2035 2854 +3149 2050 2850 +3145 2070 2844 +3139 2096 2836 +3132 2128 2826 +3122 2167 2811 +3109 2215 2791 +3090 2272 2762 +3064 2339 2720 +3027 2415 2658 +2971 2501 2558 +2884 2594 2378 +2734 2696 1901 +2397 2803 0 +0 2916 0 +0 3033 0 +0 3153 0 +0 3277 0 +0 3402 0 +0 3529 0 +0 3657 0 +3292 2114 2997 +3292 2114 2997 +3292 2115 2997 +3292 2116 2997 +3292 2117 2996 +3291 2119 2996 +3291 2121 2995 +3291 2124 2995 +3290 2128 2994 +3289 2134 2992 +3288 2141 2990 +3286 2150 2988 +3284 2162 2985 +3281 2178 2981 +3277 2198 2975 +3272 2224 2967 +3265 2256 2956 +3255 2296 2942 +3241 2344 2921 +3223 2402 2892 +3197 2469 2851 +3159 2546 2788 +3104 2631 2688 +3017 2725 2507 +2867 2827 2023 +2531 2934 0 +0 3047 0 +0 3164 0 +0 3285 0 +0 3408 0 +0 3534 0 +0 3661 0 +3425 2242 3128 +3425 2242 3128 +3425 2243 3128 +3424 2244 3128 +3424 2245 3128 +3424 2246 3127 +3424 2248 3127 +3423 2250 3126 +3423 2253 3126 +3422 2257 3125 +3421 2262 3123 +3420 2270 3122 +3418 2279 3119 +3416 2291 3116 +3413 2307 3112 +3410 2327 3106 +3404 2353 3098 +3397 2386 3087 +3387 2426 3073 +3374 2474 3052 +3355 2532 3023 +3329 2600 2981 +3292 2676 2919 +3236 2762 2818 +3150 2856 2636 +3000 2958 2147 +2665 3066 0 +0 3179 0 +0 3296 0 +0 3417 0 +0 3540 0 +0 3666 0 +3557 2371 3260 +3557 2371 3260 +3557 2372 3260 +3557 2372 3259 +3557 2373 3259 +3557 2374 3259 +3556 2375 3259 +3556 2377 3258 +3556 2379 3258 +3555 2382 3257 +3554 2387 3256 +3554 2392 3255 +3552 2399 3253 +3551 2409 3251 +3549 2421 3247 +3546 2437 3243 +3542 2457 3237 +3537 2483 3230 +3529 2516 3219 +3520 2556 3204 +3506 2605 3183 +3488 2663 3154 +3461 2730 3113 +3424 2807 3050 +3369 2894 2949 +3282 2988 2766 +3133 3090 2273 +2798 3197 0 +0 3311 0 +0 3428 0 +0 3549 0 +0 3672 0 +3689 2501 3391 +3689 2501 3391 +3689 2501 3391 +3689 2502 3391 +3689 2502 3391 +3689 2503 3391 +3689 2504 3391 +3689 2505 3390 +3688 2507 3390 +3688 2509 3389 +3687 2513 3389 +3687 2517 3388 +3686 2522 3386 +3685 2529 3385 +3683 2539 3382 +3681 2551 3379 +3678 2567 3375 +3674 2588 3369 +3669 2614 3361 +3662 2646 3350 +3652 2687 3336 +3638 2736 3315 +3620 2794 3286 +3594 2862 3244 +3556 2939 3181 +3501 3025 3080 +3414 3119 2897 +3265 3221 2400 +2931 3329 0 +0 3442 0 +0 3560 0 +0 3681 0 +3821 2631 3523 +3821 2631 3523 +3821 2632 3523 +3821 2632 3523 +3821 2632 3523 +3821 2633 3523 +3821 2634 3523 +3821 2635 3522 +3821 2636 3522 +3820 2638 3522 +3820 2640 3521 +3820 2643 3520 +3819 2647 3519 +3818 2653 3518 +3817 2660 3516 +3815 2669 3514 +3813 2682 3511 +3810 2698 3506 +3806 2718 3501 +3801 2745 3493 +3794 2777 3482 +3784 2818 3467 +3771 2867 3447 +3752 2925 3418 +3726 2993 3375 +3689 3070 3312 +3633 3157 3211 +3547 3251 3028 +3397 3353 2529 +3063 3461 0 +0 3574 0 +0 3692 0 +3954 2762 3655 +3954 2762 3655 +3954 2762 3655 +3954 2762 3655 +3954 2763 3655 +3953 2763 3655 +3953 2764 3655 +3953 2765 3654 +3953 2766 3654 +3953 2767 3654 +3953 2769 3653 +3952 2771 3653 +3952 2774 3652 +3951 2778 3651 +3950 2784 3650 +3949 2791 3648 +3947 2800 3646 +3945 2813 3643 +3942 2829 3638 +3938 2850 3632 +3933 2876 3625 +3926 2909 3614 +3916 2949 3599 +3903 2998 3578 +3884 3057 3549 +3858 3125 3507 +3821 3202 3444 +3765 3288 3343 +3679 3383 3159 +3530 3485 2658 +3196 3593 0 +0 3706 0 +4086 2893 3787 +4086 2893 3787 +4086 2893 3787 +4086 2893 3787 +4086 2894 3787 +4086 2894 3787 +4086 2894 3787 +4086 2895 3786 +4085 2896 3786 +4085 2897 3786 +4085 2898 3786 +4085 2900 3785 +4084 2902 3785 +4084 2905 3784 +4083 2909 3783 +4082 2915 3782 +4081 2922 3780 +4080 2932 3778 +4077 2944 3774 +4074 2960 3770 +4071 2981 3764 +4065 3007 3756 +4058 3040 3746 +4048 3081 3731 +4035 3130 3710 +4016 3188 3681 +3990 3256 3639 +3953 3334 3576 +3898 3420 3475 +3811 3515 3290 +3662 3617 2788 +3328 3725 0 +4095 3024 3919 +4095 3025 3919 +4095 3025 3919 +4095 3025 3919 +4095 3025 3919 +4095 3025 3919 +4095 3025 3919 +4095 3026 3918 +4095 3026 3918 +4095 3027 3918 +4095 3028 3918 +4095 3030 3918 +4095 3031 3917 +4095 3034 3917 +4095 3037 3916 +4095 3041 3915 +4095 3046 3914 +4095 3054 3912 +4095 3063 3910 +4095 3076 3906 +4095 3092 3902 +4095 3113 3896 +4095 3139 3888 +4095 3172 3878 +4095 3212 3863 +4095 3262 3842 +4095 3320 3813 +4095 3388 3771 +4085 3466 3708 +4030 3552 3606 +3943 3647 3422 +3794 3749 2919 +4095 3156 4051 +4095 3156 4051 +4095 3156 4051 +4095 3156 4051 +4095 3156 4051 +4095 3157 4051 +4095 3157 4051 +4095 3157 4051 +4095 3158 4050 +4095 3158 4050 +4095 3159 4050 +4095 3160 4050 +4095 3161 4050 +4095 3163 4049 +4095 3165 4049 +4095 3168 4048 +4095 3173 4047 +4095 3178 4046 +4095 3185 4044 +4095 3195 4041 +4095 3207 4038 +4095 3224 4034 +4095 3244 4028 +4095 3271 4020 +4095 3304 4009 +4095 3344 3995 +4095 3393 3974 +4095 3452 3945 +4095 3520 3903 +4095 3597 3839 +4095 3684 3738 +4076 3779 3554 +0 723 961 +0 734 949 +0 749 934 +0 769 912 +0 793 881 +0 824 837 +0 862 769 +0 908 660 +0 964 453 +0 1029 0 +0 1104 0 +0 1187 0 +0 1280 0 +0 1380 0 +0 1486 0 +0 1598 0 +0 1714 0 +0 1834 0 +0 1957 0 +0 2082 0 +0 2209 0 +0 2337 0 +0 2466 0 +0 2596 0 +0 2726 0 +0 2857 0 +0 2988 0 +0 3119 0 +0 3251 0 +0 3383 0 +0 3514 0 +0 3646 0 +0 727 977 +0 738 966 +0 753 951 +0 772 930 +0 796 901 +0 827 858 +0 865 794 +0 911 691 +0 966 502 +0 1031 0 +0 1105 0 +0 1189 0 +0 1281 0 +0 1380 0 +0 1487 0 +0 1598 0 +0 1715 0 +0 1835 0 +0 1957 0 +0 2082 0 +0 2209 0 +0 2337 0 +0 2466 0 +0 2596 0 +0 2726 0 +0 2857 0 +0 2988 0 +0 3119 0 +0 3251 0 +0 3383 0 +0 3514 0 +0 3646 0 +0 732 998 +0 743 988 +0 758 974 +0 777 954 +0 801 926 +0 831 886 +0 869 825 +0 915 730 +0 969 560 +0 1034 134 +0 1108 0 +0 1191 0 +0 1282 0 +0 1382 0 +0 1488 0 +0 1599 0 +0 1715 0 +0 1835 0 +0 1958 0 +0 2082 0 +0 2209 0 +0 2337 0 +0 2466 0 +0 2596 0 +0 2726 0 +0 2857 0 +0 2988 0 +0 3119 0 +0 3251 0 +0 3383 0 +0 3514 0 +0 3646 0 +0 739 1025 +0 750 1015 +0 764 1002 +0 783 983 +0 807 957 +0 837 920 +0 874 864 +0 919 777 +0 973 627 +0 1037 289 +0 1111 0 +0 1193 0 +0 1284 0 +0 1383 0 +0 1489 0 +0 1600 0 +0 1716 0 +0 1836 0 +0 1958 0 +0 2083 0 +0 2209 0 +0 2337 0 +0 2466 0 +0 2596 0 +0 2726 0 +0 2857 0 +0 2988 0 +0 3119 0 +0 3251 0 +0 3383 0 +0 3514 0 +0 3646 0 +0 748 1059 +0 759 1050 +0 773 1037 +0 791 1020 +0 815 996 +0 844 962 +0 880 911 +0 925 834 +0 979 704 +0 1042 438 +0 1115 0 +0 1197 0 +0 1287 0 +0 1386 0 +0 1491 0 +0 1602 0 +0 1717 0 +0 1836 0 +0 1959 0 +0 2083 0 +0 2210 0 +0 2338 0 +0 2466 0 +0 2596 0 +0 2726 0 +0 2857 0 +0 2988 0 +0 3119 0 +0 3251 0 +0 3383 0 +0 3514 0 +0 3646 0 +450 760 1100 +403 770 1092 +330 784 1080 +210 802 1065 +0 825 1043 +0 853 1012 +0 889 967 +0 933 900 +0 986 790 +0 1048 582 +0 1120 0 +0 1201 0 +0 1291 0 +0 1388 0 +0 1493 0 +0 1603 0 +0 1718 0 +0 1837 0 +0 1960 0 +0 2084 0 +0 2210 0 +0 2338 0 +0 2467 0 +0 2596 0 +0 2726 0 +0 2857 0 +0 2988 0 +0 3120 0 +0 3251 0 +0 3383 0 +0 3514 0 +0 3646 0 +751 775 1150 +727 785 1143 +693 799 1132 +643 816 1119 +566 838 1099 +437 866 1072 +175 901 1033 +0 944 975 +0 995 884 +0 1056 723 +0 1127 342 +0 1207 0 +0 1296 0 +0 1392 0 +0 1496 0 +0 1606 0 +0 1720 0 +0 1839 0 +0 1961 0 +0 2085 0 +0 2211 0 +0 2338 0 +0 2467 0 +0 2597 0 +0 2727 0 +0 2857 0 +0 2988 0 +0 3120 0 +0 3251 0 +0 3383 0 +0 3514 0 +0 3646 0 +978 795 1209 +964 805 1203 +944 817 1194 +916 834 1182 +875 855 1165 +814 882 1142 +718 916 1108 +545 957 1060 +108 1008 985 +0 1067 862 +0 1136 615 +0 1215 0 +0 1302 0 +0 1397 0 +0 1500 0 +0 1609 0 +0 1723 0 +0 1841 0 +0 1962 0 +0 2086 0 +0 2212 0 +0 2339 0 +0 2468 0 +0 2597 0 +0 2727 0 +0 2858 0 +0 2988 0 +0 3120 0 +0 3251 0 +0 3383 0 +0 3515 0 +0 3646 0 +1170 820 1278 +1161 829 1273 +1148 841 1265 +1130 857 1255 +1105 877 1240 +1070 903 1221 +1017 935 1193 +936 975 1153 +798 1023 1093 +507 1081 998 +0 1148 830 +0 1225 414 +0 1310 0 +0 1404 0 +0 1506 0 +0 1613 0 +0 1726 0 +0 1843 0 +0 1964 0 +0 2087 0 +0 2213 0 +0 2340 0 +0 2468 0 +0 2597 0 +0 2727 0 +0 2858 0 +0 2989 0 +0 3120 0 +0 3251 0 +0 3383 0 +0 3515 0 +0 3646 0 +1343 851 1356 +1336 860 1352 +1327 871 1345 +1316 886 1337 +1299 905 1325 +1276 929 1308 +1244 960 1286 +1196 998 1253 +1123 1044 1206 +1004 1099 1134 +769 1164 1015 +0 1238 784 +0 1321 0 +0 1413 0 +0 1513 0 +0 1619 0 +0 1731 0 +0 1847 0 +0 1967 0 +0 2089 0 +0 2214 0 +0 2341 0 +0 2469 0 +0 2598 0 +0 2728 0 +0 2858 0 +0 2989 0 +0 3120 0 +0 3251 0 +0 3383 0 +0 3515 0 +0 3646 0 +1502 890 1444 +1498 898 1440 +1492 909 1434 +1484 922 1427 +1472 940 1418 +1457 962 1404 +1435 991 1386 +1405 1026 1360 +1360 1070 1323 +1293 1122 1269 +1184 1184 1184 +979 1255 1037 +327 1335 715 +0 1425 0 +0 1522 0 +0 1626 0 +0 1736 0 +0 1851 0 +0 1970 0 +0 2092 0 +0 2216 0 +0 2343 0 +0 2470 0 +0 2599 0 +0 2728 0 +0 2859 0 +0 2989 0 +0 3120 0 +0 3252 0 +0 3383 0 +0 3515 0 +0 3647 0 +1654 938 1539 +1651 945 1536 +1647 954 1532 +1641 967 1526 +1633 982 1518 +1622 1003 1507 +1607 1029 1493 +1586 1062 1473 +1557 1102 1444 +1515 1151 1403 +1451 1209 1341 +1349 1277 1243 +1161 1354 1065 +641 1440 601 +0 1534 0 +0 1636 0 +0 1744 0 +0 1857 0 +0 1975 0 +0 2096 0 +0 2219 0 +0 2345 0 +0 2472 0 +0 2600 0 +0 2729 0 +0 2859 0 +0 2990 0 +0 3121 0 +0 3252 0 +0 3383 0 +0 3515 0 +0 3647 0 +1801 994 1642 +1798 1000 1639 +1795 1009 1636 +1791 1020 1631 +1785 1034 1625 +1778 1052 1617 +1767 1076 1605 +1752 1105 1589 +1732 1142 1567 +1704 1187 1536 +1663 1241 1491 +1601 1304 1423 +1504 1377 1311 +1328 1459 1099 +874 1550 384 +0 1649 0 +0 1754 0 +0 1865 0 +0 1981 0 +0 2100 0 +0 2223 0 +0 2347 0 +0 2474 0 +0 2602 0 +0 2731 0 +0 2860 0 +0 2990 0 +0 3121 0 +0 3252 0 +0 3384 0 +0 3515 0 +0 3647 0 +1943 1060 1750 +1941 1066 1748 +1939 1073 1746 +1936 1082 1742 +1932 1095 1737 +1926 1111 1731 +1919 1132 1722 +1908 1158 1710 +1894 1191 1693 +1874 1231 1670 +1847 1281 1636 +1807 1339 1587 +1747 1407 1513 +1652 1484 1389 +1484 1571 1142 +1068 1665 0 +0 1767 0 +0 1876 0 +0 1989 0 +0 2106 0 +0 2227 0 +0 2351 0 +0 2477 0 +0 2604 0 +0 2732 0 +0 2861 0 +0 2991 0 +0 3122 0 +0 3253 0 +0 3384 0 +0 3515 0 +0 3647 0 +2083 1136 1864 +2082 1140 1862 +2080 1146 1860 +2078 1155 1858 +2075 1165 1854 +2071 1179 1849 +2065 1197 1842 +2058 1220 1833 +2047 1249 1820 +2033 1284 1802 +2014 1328 1778 +1987 1381 1743 +1947 1444 1691 +1889 1516 1611 +1796 1597 1476 +1633 1687 1193 +1242 1784 0 +0 1889 0 +0 1999 0 +0 2115 0 +0 2234 0 +0 2356 0 +0 2480 0 +0 2606 0 +0 2734 0 +0 2863 0 +0 2993 0 +0 3123 0 +0 3253 0 +0 3385 0 +0 3516 0 +0 3647 0 +2221 1220 1982 +2220 1224 1981 +2218 1229 1979 +2217 1236 1977 +2214 1245 1974 +2211 1257 1970 +2207 1272 1965 +2202 1291 1958 +2195 1316 1948 +2185 1347 1935 +2171 1386 1917 +2151 1433 1891 +2124 1489 1854 +2086 1554 1800 +2028 1629 1716 +1937 1713 1571 +1778 1806 1253 +1403 1906 0 +0 2013 0 +0 2125 0 +0 2242 0 +0 2362 0 +0 2485 0 +0 2610 0 +0 2737 0 +0 2865 0 +0 2994 0 +0 3124 0 +0 3254 0 +0 3385 0 +0 3516 0 +0 3648 0 +2357 1313 2103 +2356 1316 2102 +2355 1321 2101 +2354 1326 2099 +2352 1334 2097 +2350 1343 2094 +2347 1356 2090 +2343 1372 2085 +2338 1393 2078 +2330 1419 2068 +2320 1452 2054 +2307 1493 2035 +2288 1543 2009 +2261 1601 1971 +2222 1669 1915 +2165 1747 1826 +2076 1834 1673 +1919 1929 1323 +1556 2031 0 +0 2139 0 +0 2253 0 +0 2370 0 +0 2491 0 +0 2615 0 +0 2741 0 +0 2868 0 +0 2996 0 +0 3126 0 +0 3256 0 +0 3386 0 +0 3517 0 +0 3648 0 +2492 1414 2227 +2491 1416 2226 +2491 1420 2225 +2490 1424 2224 +2489 1430 2222 +2487 1438 2220 +2485 1448 2217 +2482 1461 2213 +2478 1479 2208 +2472 1501 2200 +2465 1528 2190 +2455 1563 2176 +2442 1606 2157 +2423 1657 2130 +2396 1718 2091 +2358 1788 2033 +2301 1868 1942 +2213 1957 1782 +2058 2053 1403 +1703 2157 0 +0 2267 0 +0 2381 0 +0 2500 0 +0 2621 0 +0 2745 0 +0 2871 0 +0 2999 0 +0 3128 0 +0 3257 0 +0 3387 0 +0 3518 0 +0 3649 0 +2626 1521 2353 +2626 1523 2352 +2625 1526 2351 +2625 1529 2350 +2624 1534 2349 +2623 1540 2347 +2621 1548 2345 +2619 1559 2342 +2616 1573 2338 +2612 1591 2332 +2607 1614 2325 +2599 1643 2315 +2589 1679 2301 +2576 1723 2281 +2557 1776 2253 +2531 1839 2214 +2493 1911 2154 +2436 1992 2061 +2348 2082 1895 +2195 2180 1491 +1846 2285 0 +0 2395 0 +0 2511 0 +0 2630 0 +0 2752 0 +0 2876 0 +0 3003 0 +0 3130 0 +0 3259 0 +0 3389 0 +0 3519 0 +0 3650 0 +2760 1633 2480 +2760 1635 2479 +2759 1637 2479 +2759 1640 2478 +2758 1643 2477 +2757 1648 2476 +2756 1655 2474 +2755 1663 2472 +2752 1674 2469 +2749 1689 2465 +2745 1707 2459 +2740 1731 2451 +2733 1761 2441 +2723 1798 2427 +2710 1843 2407 +2691 1898 2379 +2664 1962 2339 +2627 2035 2278 +2571 2118 2183 +2483 2209 2013 +2331 2308 1588 +1986 2414 0 +0 2525 0 +0 2641 0 +0 2760 0 +0 2883 0 +0 3007 0 +0 3134 0 +0 3262 0 +0 3391 0 +0 3521 0 +0 3651 0 +2893 1750 2608 +2893 1751 2608 +2893 1753 2608 +2893 1755 2607 +2892 1758 2606 +2891 1762 2605 +2891 1767 2604 +2889 1773 2602 +2888 1782 2600 +2886 1793 2597 +2883 1808 2593 +2879 1827 2587 +2873 1852 2579 +2866 1882 2569 +2856 1920 2554 +2843 1967 2534 +2824 2022 2506 +2798 2087 2465 +2760 2161 2404 +2704 2245 2308 +2617 2337 2134 +2465 2437 1691 +2123 2543 0 +0 2655 0 +0 2771 0 +0 2891 0 +0 3014 0 +0 3139 0 +0 3266 0 +0 3394 0 +0 3523 0 +0 3652 0 +3026 1870 2738 +3026 1871 2737 +3026 1873 2737 +3026 1874 2737 +3025 1876 2736 +3025 1879 2735 +3024 1883 2735 +3023 1888 2733 +3022 1895 2732 +3021 1904 2729 +3018 1916 2726 +3015 1931 2722 +3012 1950 2716 +3006 1975 2708 +2999 2006 2698 +2989 2045 2683 +2976 2092 2663 +2957 2148 2635 +2931 2214 2593 +2893 2289 2532 +2838 2373 2434 +2750 2466 2258 +2600 2567 1800 +2260 2673 0 +0 2786 0 +0 2902 0 +0 3022 0 +0 3145 0 +0 3270 0 +0 3397 0 +0 3525 0 +0 3655 0 +3159 1993 2868 +3159 1994 2868 +3159 1995 2867 +3159 1996 2867 +3159 1998 2867 +3158 2000 2866 +3158 2003 2865 +3157 2007 2864 +3156 2012 2863 +3155 2019 2861 +3153 2028 2859 +3151 2040 2856 +3148 2056 2852 +3144 2075 2846 +3139 2101 2838 +3132 2132 2827 +3122 2172 2813 +3109 2219 2793 +3090 2276 2764 +3064 2342 2723 +3026 2418 2661 +2971 2503 2562 +2884 2596 2383 +2733 2697 1915 +2395 2804 0 +0 2917 0 +0 3033 0 +0 3154 0 +0 3277 0 +0 3402 0 +0 3529 0 +0 3657 0 +3292 2119 2998 +3292 2119 2998 +3292 2120 2998 +3292 2121 2998 +3291 2122 2997 +3291 2124 2997 +3291 2126 2997 +3290 2129 2996 +3290 2133 2995 +3289 2138 2994 +3287 2145 2992 +3286 2155 2989 +3284 2167 2986 +3281 2182 2982 +3277 2202 2976 +3272 2228 2968 +3264 2260 2958 +3255 2299 2943 +3241 2347 2923 +3222 2405 2894 +3196 2471 2852 +3159 2548 2790 +3103 2633 2691 +3017 2727 2510 +2866 2828 2033 +2530 2935 0 +0 3048 0 +0 3165 0 +0 3285 0 +0 3409 0 +0 3534 0 +0 3661 0 +3424 2246 3129 +3424 2246 3129 +3424 2246 3129 +3424 2247 3129 +3424 2248 3129 +3424 2249 3128 +3424 2251 3128 +3423 2253 3127 +3423 2257 3127 +3422 2261 3126 +3421 2266 3124 +3420 2273 3123 +3418 2282 3120 +3416 2294 3117 +3413 2310 3113 +3409 2330 3107 +3404 2356 3099 +3397 2388 3088 +3387 2428 3074 +3374 2477 3053 +3355 2534 3024 +3329 2601 2983 +3291 2678 2920 +3236 2763 2820 +3149 2857 2639 +2999 2959 2155 +2663 3066 0 +0 3179 0 +0 3297 0 +0 3417 0 +0 3540 0 +0 3666 0 +3557 2374 3260 +3557 2374 3260 +3557 2374 3260 +3557 2375 3260 +3556 2376 3260 +3556 2377 3260 +3556 2378 3259 +3556 2380 3259 +3555 2382 3259 +3555 2385 3258 +3554 2389 3257 +3553 2395 3255 +3552 2402 3254 +3551 2411 3251 +3548 2423 3248 +3546 2439 3244 +3542 2459 3238 +3536 2485 3230 +3529 2518 3220 +3519 2558 3205 +3506 2607 3184 +3487 2664 3155 +3461 2732 3114 +3424 2808 3051 +3368 2894 2950 +3282 2989 2768 +3132 3090 2279 +2797 3198 0 +0 3311 0 +0 3428 0 +0 3549 0 +0 3672 0 +3689 2503 3392 +3689 2503 3392 +3689 2503 3392 +3689 2504 3392 +3689 2504 3392 +3689 2505 3391 +3689 2506 3391 +3688 2507 3391 +3688 2509 3390 +3688 2511 3390 +3687 2515 3389 +3687 2519 3388 +3686 2524 3387 +3684 2531 3385 +3683 2541 3383 +3681 2553 3380 +3678 2569 3375 +3674 2589 3369 +3669 2615 3362 +3661 2648 3351 +3652 2688 3336 +3638 2737 3316 +3620 2795 3287 +3594 2863 3245 +3556 2940 3182 +3501 3026 3081 +3414 3120 2898 +3265 3222 2405 +2930 3330 0 +0 3443 0 +0 3560 0 +0 3681 0 +3821 2633 3524 +3821 2633 3523 +3821 2633 3523 +3821 2633 3523 +3821 2634 3523 +3821 2634 3523 +3821 2635 3523 +3821 2636 3523 +3821 2637 3522 +3820 2639 3522 +3820 2642 3521 +3819 2645 3521 +3819 2649 3520 +3818 2654 3518 +3817 2661 3517 +3815 2671 3514 +3813 2683 3511 +3810 2699 3507 +3806 2720 3501 +3801 2746 3493 +3794 2779 3482 +3784 2819 3468 +3770 2868 3447 +3752 2926 3418 +3726 2994 3376 +3688 3071 3313 +3633 3157 3212 +3547 3252 3029 +3397 3353 2532 +3063 3461 0 +0 3575 0 +0 3692 0 +3954 2763 3655 +3954 2763 3655 +3954 2763 3655 +3954 2764 3655 +3953 2764 3655 +3953 2764 3655 +3953 2765 3655 +3953 2766 3655 +3953 2767 3654 +3953 2768 3654 +3953 2770 3654 +3952 2772 3653 +3952 2775 3652 +3951 2779 3651 +3950 2785 3650 +3949 2792 3648 +3947 2802 3646 +3945 2814 3643 +3942 2830 3639 +3938 2851 3633 +3933 2877 3625 +3926 2910 3614 +3916 2950 3599 +3903 2999 3579 +3884 3057 3550 +3858 3125 3508 +3821 3202 3444 +3765 3289 3344 +3679 3383 3160 +3529 3485 2661 +3195 3593 0 +0 3706 0 +4086 2894 3787 +4086 2894 3787 +4086 2894 3787 +4086 2894 3787 +4086 2895 3787 +4086 2895 3787 +4086 2895 3787 +4085 2896 3787 +4085 2897 3786 +4085 2898 3786 +4085 2899 3786 +4085 2901 3786 +4084 2903 3785 +4084 2906 3784 +4083 2910 3783 +4082 2916 3782 +4081 2923 3780 +4079 2933 3778 +4077 2945 3775 +4074 2961 3770 +4071 2982 3765 +4065 3008 3757 +4058 3041 3746 +4048 3081 3731 +4035 3130 3710 +4016 3189 3681 +3990 3257 3639 +3953 3334 3576 +3898 3420 3475 +3811 3515 3291 +3662 3617 2790 +3328 3725 0 +4095 3025 3919 +4095 3025 3919 +4095 3025 3919 +4095 3025 3919 +4095 3026 3919 +4095 3026 3919 +4095 3026 3919 +4095 3027 3919 +4095 3027 3919 +4095 3028 3918 +4095 3029 3918 +4095 3030 3918 +4095 3032 3917 +4095 3034 3917 +4095 3037 3916 +4095 3042 3915 +4095 3047 3914 +4095 3054 3912 +4095 3064 3910 +4095 3076 3906 +4095 3092 3902 +4095 3113 3896 +4095 3139 3888 +4095 3172 3878 +4095 3213 3863 +4095 3262 3842 +4095 3320 3813 +4095 3388 3771 +4085 3466 3708 +4030 3552 3607 +3943 3647 3422 +3794 3749 2920 +4095 3156 4051 +4095 3157 4051 +4095 3157 4051 +4095 3157 4051 +4095 3157 4051 +4095 3157 4051 +4095 3157 4051 +4095 3158 4051 +4095 3158 4051 +4095 3159 4050 +4095 3159 4050 +4095 3160 4050 +4095 3162 4050 +4095 3163 4049 +4095 3166 4049 +4095 3169 4048 +4095 3173 4047 +4095 3179 4046 +4095 3186 4044 +4095 3195 4042 +4095 3208 4038 +4095 3224 4034 +4095 3245 4028 +4095 3271 4020 +4095 3304 4010 +4095 3345 3995 +4095 3394 3974 +4095 3452 3945 +4095 3520 3903 +4095 3598 3840 +4095 3684 3738 +4075 3779 3554 +0 843 1089 +0 852 1080 +0 864 1068 +0 879 1052 +0 898 1030 +0 923 998 +0 954 952 +0 992 882 +0 1039 767 +0 1094 545 +0 1160 0 +0 1234 0 +0 1318 0 +0 1411 0 +0 1511 0 +0 1617 0 +0 1729 0 +0 1846 0 +0 1966 0 +0 2089 0 +0 2214 0 +0 2341 0 +0 2469 0 +0 2598 0 +0 2728 0 +0 2858 0 +0 2989 0 +0 3120 0 +0 3251 0 +0 3383 0 +0 3515 0 +0 3646 0 +0 846 1101 +0 855 1093 +0 867 1082 +0 881 1066 +0 901 1044 +0 925 1013 +0 956 969 +0 994 901 +0 1041 792 +0 1096 585 +0 1161 0 +0 1236 0 +0 1319 0 +0 1412 0 +0 1512 0 +0 1618 0 +0 1730 0 +0 1846 0 +0 1966 0 +0 2089 0 +0 2214 0 +0 2341 0 +0 2469 0 +0 2598 0 +0 2728 0 +0 2858 0 +0 2989 0 +0 3120 0 +0 3251 0 +0 3383 0 +0 3515 0 +0 3646 0 +0 850 1117 +0 859 1109 +0 870 1098 +0 885 1083 +0 904 1063 +0 928 1033 +0 959 990 +0 997 926 +0 1043 823 +0 1098 634 +0 1163 101 +0 1237 0 +0 1321 0 +0 1413 0 +0 1513 0 +0 1619 0 +0 1730 0 +0 1847 0 +0 1967 0 +0 2089 0 +0 2214 0 +0 2341 0 +0 2469 0 +0 2598 0 +0 2728 0 +0 2858 0 +0 2989 0 +0 3120 0 +0 3251 0 +0 3383 0 +0 3515 0 +0 3646 0 +0 856 1138 +0 864 1130 +0 875 1120 +0 890 1106 +0 909 1086 +0 933 1058 +0 963 1018 +0 1001 957 +0 1047 862 +0 1101 692 +0 1166 266 +0 1240 0 +0 1323 0 +0 1414 0 +0 1514 0 +0 1620 0 +0 1731 0 +0 1847 0 +0 1967 0 +0 2090 0 +0 2215 0 +0 2341 0 +0 2469 0 +0 2598 0 +0 2728 0 +0 2858 0 +0 2989 0 +0 3120 0 +0 3251 0 +0 3383 0 +0 3515 0 +0 3646 0 +0 863 1164 +0 871 1157 +0 882 1147 +0 897 1134 +0 915 1115 +0 939 1089 +0 969 1052 +0 1006 996 +0 1051 909 +0 1106 759 +0 1169 421 +0 1243 0 +0 1325 0 +0 1417 0 +0 1515 0 +0 1621 0 +0 1732 0 +0 1848 0 +0 1968 0 +0 2090 0 +0 2215 0 +0 2341 0 +0 2469 0 +0 2598 0 +0 2728 0 +0 2858 0 +0 2989 0 +0 3120 0 +0 3252 0 +0 3383 0 +0 3515 0 +0 3646 0 +133 872 1198 +32 880 1191 +0 891 1182 +0 905 1169 +0 923 1152 +0 947 1128 +0 976 1094 +0 1013 1043 +0 1057 966 +0 1111 836 +0 1174 570 +0 1247 0 +0 1329 0 +0 1419 0 +0 1518 0 +0 1623 0 +0 1734 0 +0 1849 0 +0 1968 0 +0 2091 0 +0 2215 0 +0 2342 0 +0 2470 0 +0 2599 0 +0 2728 0 +0 2858 0 +0 2989 0 +0 3120 0 +0 3252 0 +0 3383 0 +0 3515 0 +0 3647 0 +615 884 1238 +582 892 1232 +535 902 1224 +462 916 1213 +342 934 1197 +107 957 1175 +0 986 1144 +0 1021 1100 +0 1065 1032 +0 1118 922 +0 1180 714 +0 1252 39 +0 1333 0 +0 1423 0 +0 1521 0 +0 1625 0 +0 1735 0 +0 1851 0 +0 1970 0 +0 2092 0 +0 2216 0 +0 2342 0 +0 2470 0 +0 2599 0 +0 2728 0 +0 2859 0 +0 2989 0 +0 3120 0 +0 3252 0 +0 3383 0 +0 3515 0 +0 3647 0 +901 899 1288 +883 907 1282 +859 917 1275 +825 931 1265 +775 948 1251 +698 970 1231 +569 998 1204 +307 1033 1165 +0 1076 1107 +0 1127 1016 +0 1188 855 +0 1259 474 +0 1339 0 +0 1428 0 +0 1524 0 +0 1628 0 +0 1738 0 +0 1852 0 +0 1971 0 +0 2093 0 +0 2217 0 +0 2343 0 +0 2470 0 +0 2599 0 +0 2729 0 +0 2859 0 +0 2989 0 +0 3120 0 +0 3252 0 +0 3383 0 +0 3515 0 +0 3647 0 +1121 919 1346 +1110 927 1341 +1096 937 1335 +1076 949 1326 +1048 966 1314 +1007 987 1297 +947 1014 1274 +850 1048 1241 +677 1089 1192 +240 1140 1117 +0 1199 994 +0 1268 747 +0 1347 0 +0 1434 0 +0 1530 0 +0 1632 0 +0 1741 0 +0 1855 0 +0 1973 0 +0 2094 0 +0 2218 0 +0 2344 0 +0 2471 0 +0 2600 0 +0 2729 0 +0 2859 0 +0 2990 0 +0 3121 0 +0 3252 0 +0 3383 0 +0 3515 0 +0 3647 0 +1309 945 1414 +1302 952 1410 +1293 961 1405 +1280 973 1397 +1262 989 1387 +1237 1009 1372 +1202 1035 1353 +1149 1067 1325 +1068 1107 1285 +930 1156 1225 +639 1213 1130 +0 1280 962 +0 1357 546 +0 1442 0 +0 1536 0 +0 1638 0 +0 1745 0 +0 1858 0 +0 1976 0 +0 2096 0 +0 2220 0 +0 2345 0 +0 2472 0 +0 2600 0 +0 2729 0 +0 2859 0 +0 2990 0 +0 3121 0 +0 3252 0 +0 3383 0 +0 3515 0 +0 3647 0 +1479 977 1492 +1475 983 1488 +1468 992 1484 +1460 1003 1477 +1448 1018 1469 +1431 1037 1457 +1408 1061 1441 +1376 1092 1418 +1328 1130 1385 +1255 1176 1338 +1136 1231 1266 +901 1296 1148 +0 1370 916 +0 1453 0 +0 1545 0 +0 1645 0 +0 1751 0 +0 1863 0 +0 1979 0 +0 2099 0 +0 2221 0 +0 2346 0 +0 2473 0 +0 2601 0 +0 2730 0 +0 2860 0 +0 2990 0 +0 3121 0 +0 3252 0 +0 3384 0 +0 3515 0 +0 3647 0 +1638 1016 1579 +1635 1022 1576 +1630 1030 1572 +1624 1041 1567 +1616 1054 1559 +1604 1072 1550 +1589 1094 1537 +1567 1123 1518 +1537 1158 1492 +1492 1202 1455 +1425 1254 1401 +1316 1316 1316 +1111 1387 1169 +459 1468 847 +0 1557 0 +0 1654 0 +0 1758 0 +0 1869 0 +0 1983 0 +0 2102 0 +0 2224 0 +0 2348 0 +0 2475 0 +0 2602 0 +0 2731 0 +0 2861 0 +0 2991 0 +0 3121 0 +0 3252 0 +0 3384 0 +0 3515 0 +0 3647 0 +1789 1064 1673 +1786 1070 1671 +1783 1077 1668 +1779 1086 1664 +1773 1099 1658 +1765 1115 1650 +1754 1135 1640 +1739 1161 1625 +1719 1194 1605 +1689 1234 1576 +1647 1283 1535 +1583 1341 1473 +1481 1409 1375 +1293 1486 1197 +773 1572 733 +0 1667 0 +0 1768 0 +0 1876 0 +0 1989 0 +0 2107 0 +0 2228 0 +0 2351 0 +0 2477 0 +0 2604 0 +0 2732 0 +0 2861 0 +0 2991 0 +0 3122 0 +0 3253 0 +0 3384 0 +0 3515 0 +0 3647 0 +1934 1121 1775 +1933 1126 1774 +1930 1133 1771 +1927 1141 1768 +1923 1152 1763 +1917 1166 1757 +1910 1184 1749 +1899 1208 1737 +1885 1237 1721 +1864 1274 1700 +1836 1319 1668 +1795 1373 1623 +1734 1436 1555 +1636 1509 1443 +1460 1592 1231 +1006 1682 516 +0 1781 0 +0 1886 0 +0 1997 0 +0 2113 0 +0 2232 0 +0 2355 0 +0 2479 0 +0 2606 0 +0 2734 0 +0 2863 0 +0 2992 0 +0 3123 0 +0 3253 0 +0 3384 0 +0 3516 0 +0 3647 0 +2076 1188 1884 +2075 1192 1882 +2074 1198 1880 +2071 1205 1878 +2068 1214 1874 +2064 1227 1869 +2058 1243 1863 +2051 1264 1854 +2041 1290 1842 +2026 1323 1825 +2007 1363 1802 +1979 1413 1768 +1939 1471 1720 +1879 1539 1645 +1784 1616 1521 +1616 1703 1274 +1200 1798 0 +0 1899 0 +0 2008 0 +0 2121 0 +0 2239 0 +0 2359 0 +0 2483 0 +0 2609 0 +0 2736 0 +0 2864 0 +0 2993 0 +0 3123 0 +0 3254 0 +0 3385 0 +0 3516 0 +0 3648 0 +2216 1264 1997 +2215 1268 1996 +2214 1272 1995 +2212 1279 1992 +2210 1287 1990 +2207 1297 1986 +2203 1311 1981 +2197 1329 1974 +2190 1352 1965 +2179 1381 1952 +2165 1417 1935 +2146 1461 1910 +2119 1513 1875 +2079 1576 1823 +2021 1648 1743 +1928 1729 1608 +1765 1819 1325 +1374 1916 0 +0 2021 0 +0 2132 0 +0 2247 0 +0 2366 0 +0 2488 0 +0 2612 0 +0 2739 0 +0 2866 0 +0 2995 0 +0 3125 0 +0 3255 0 +0 3386 0 +0 3517 0 +0 3648 0 +2353 1349 2115 +2353 1352 2114 +2352 1356 2113 +2350 1361 2111 +2349 1368 2109 +2347 1377 2106 +2344 1389 2102 +2340 1404 2097 +2334 1423 2090 +2327 1448 2080 +2317 1479 2067 +2303 1518 2049 +2284 1565 2023 +2257 1621 1987 +2218 1686 1932 +2160 1761 1848 +2069 1846 1703 +1910 1938 1386 +1535 2039 0 +0 2145 0 +0 2257 0 +0 2374 0 +0 2494 0 +0 2617 0 +0 2742 0 +0 2869 0 +0 2997 0 +0 3126 0 +0 3256 0 +0 3386 0 +0 3517 0 +0 3648 0 +2489 1443 2236 +2489 1445 2235 +2488 1449 2234 +2487 1453 2233 +2486 1458 2231 +2484 1466 2229 +2482 1475 2226 +2479 1488 2222 +2475 1504 2217 +2470 1525 2210 +2462 1551 2200 +2452 1584 2186 +2439 1625 2167 +2420 1675 2141 +2393 1733 2103 +2355 1802 2047 +2297 1879 1958 +2208 1966 1805 +2051 2061 1456 +1688 2163 0 +0 2271 0 +0 2385 0 +0 2502 0 +0 2623 0 +0 2747 0 +0 2873 0 +0 3000 0 +0 3128 0 +0 3258 0 +0 3388 0 +0 3518 0 +0 3649 0 +2624 1544 2359 +2624 1546 2359 +2624 1549 2358 +2623 1552 2357 +2622 1556 2356 +2621 1562 2354 +2619 1570 2352 +2617 1580 2349 +2614 1593 2345 +2610 1611 2340 +2605 1633 2332 +2597 1661 2322 +2587 1695 2308 +2574 1738 2289 +2555 1789 2262 +2528 1850 2223 +2490 1921 2165 +2433 2000 2074 +2345 2089 1914 +2190 2186 1535 +1835 2289 0 +0 2399 0 +0 2513 0 +0 2632 0 +0 2753 0 +0 2877 0 +0 3004 0 +0 3131 0 +0 3260 0 +0 3389 0 +0 3519 0 +0 3650 0 +2759 1651 2485 +2758 1653 2485 +2758 1655 2484 +2758 1658 2483 +2757 1661 2482 +2756 1666 2481 +2755 1672 2480 +2753 1680 2477 +2751 1691 2474 +2748 1705 2470 +2744 1723 2465 +2739 1746 2457 +2731 1775 2447 +2721 1811 2433 +2708 1855 2413 +2689 1908 2385 +2663 1971 2346 +2625 2043 2287 +2568 2124 2193 +2480 2214 2027 +2327 2312 1623 +1978 2417 0 +0 2527 0 +0 2643 0 +0 2762 0 +0 2884 0 +0 3008 0 +0 3135 0 +0 3262 0 +0 3391 0 +0 3521 0 +0 3651 0 +2892 1764 2612 +2892 1765 2612 +2892 1767 2612 +2892 1769 2611 +2891 1772 2610 +2890 1775 2609 +2889 1780 2608 +2888 1787 2606 +2887 1795 2604 +2884 1806 2601 +2882 1821 2597 +2878 1839 2591 +2872 1863 2584 +2865 1893 2573 +2855 1930 2559 +2842 1976 2539 +2823 2030 2511 +2797 2094 2471 +2759 2167 2411 +2703 2250 2315 +2615 2341 2145 +2463 2440 1720 +2118 2546 0 +0 2657 0 +0 2773 0 +0 2892 0 +0 3015 0 +0 3140 0 +0 3266 0 +0 3394 0 +0 3523 0 +0 3653 0 +3026 1881 2741 +3026 1882 2740 +3025 1883 2740 +3025 1885 2740 +3025 1887 2739 +3024 1890 2738 +3024 1894 2737 +3023 1899 2736 +3021 1905 2734 +3020 1914 2732 +3018 1926 2729 +3015 1940 2725 +3011 1960 2719 +3005 1984 2712 +2998 2015 2701 +2988 2053 2687 +2975 2099 2667 +2956 2154 2638 +2930 2219 2598 +2892 2294 2537 +2836 2377 2440 +2749 2469 2266 +2598 2569 1823 +2256 2675 0 +0 2787 0 +0 2903 0 +0 3023 0 +0 3146 0 +0 3271 0 +0 3398 0 +0 3526 0 +0 3655 0 +3159 2002 2870 +3159 2002 2870 +3158 2003 2870 +3158 2005 2869 +3158 2006 2869 +3158 2008 2868 +3157 2011 2868 +3156 2015 2867 +3156 2020 2865 +3154 2027 2864 +3153 2036 2861 +3151 2048 2858 +3148 2063 2854 +3144 2082 2848 +3138 2107 2840 +3131 2139 2830 +3121 2177 2815 +3108 2224 2795 +3089 2280 2767 +3063 2346 2726 +3025 2421 2664 +2970 2506 2566 +2883 2598 2390 +2732 2699 1933 +2392 2805 0 +0 2918 0 +0 3034 0 +0 3154 0 +0 3277 0 +0 3403 0 +0 3529 0 +0 3658 0 +3291 2125 3000 +3291 2125 3000 +3291 2126 3000 +3291 2127 2999 +3291 2128 2999 +3291 2130 2999 +3290 2132 2998 +3290 2135 2997 +3289 2139 2996 +3288 2145 2995 +3287 2151 2993 +3285 2161 2991 +3283 2172 2988 +3280 2188 2984 +3276 2208 2978 +3271 2233 2970 +3264 2264 2960 +3254 2304 2945 +3241 2351 2925 +3222 2408 2896 +3196 2474 2855 +3158 2550 2793 +3103 2635 2694 +3016 2728 2515 +2865 2829 2047 +2527 2936 0 +0 3049 0 +0 3166 0 +0 3286 0 +0 3409 0 +0 3534 0 +0 3661 0 +3424 2250 3130 +3424 2251 3130 +3424 2251 3130 +3424 2252 3130 +3424 2253 3130 +3423 2254 3130 +3423 2256 3129 +3423 2258 3129 +3422 2261 3128 +3422 2265 3127 +3421 2271 3126 +3420 2278 3124 +3418 2287 3122 +3416 2299 3118 +3413 2314 3114 +3409 2334 3108 +3404 2360 3101 +3396 2392 3090 +3387 2431 3075 +3373 2479 3055 +3355 2537 3026 +3328 2603 2984 +3291 2680 2922 +3235 2765 2823 +3149 2859 2643 +2999 2960 2165 +2662 3067 0 +0 3180 0 +0 3297 0 +0 3418 0 +0 3541 0 +0 3666 0 +3557 2377 3261 +3557 2378 3261 +3556 2378 3261 +3556 2379 3261 +3556 2379 3261 +3556 2380 3261 +3556 2382 3260 +3556 2383 3260 +3555 2386 3259 +3555 2389 3259 +3554 2393 3258 +3553 2398 3256 +3552 2405 3255 +3550 2414 3252 +3548 2427 3249 +3545 2442 3245 +3541 2462 3239 +3536 2488 3231 +3529 2520 3221 +3519 2560 3206 +3506 2609 3185 +3487 2666 3157 +3461 2733 3115 +3423 2810 3052 +3368 2896 2952 +3281 2989 2771 +3131 3091 2287 +2795 3198 0 +0 3311 0 +0 3429 0 +0 3549 0 +0 3673 0 +3689 2506 3393 +3689 2506 3393 +3689 2506 3392 +3689 2506 3392 +3689 2507 3392 +3689 2508 3392 +3688 2509 3392 +3688 2510 3392 +3688 2512 3391 +3688 2514 3391 +3687 2517 3390 +3686 2521 3389 +3686 2527 3388 +3684 2534 3386 +3683 2543 3383 +3681 2555 3380 +3678 2571 3376 +3674 2592 3370 +3668 2617 3362 +3661 2650 3352 +3651 2690 3337 +3638 2739 3316 +3619 2796 3287 +3593 2864 3246 +3556 2941 3183 +3500 3026 3083 +3414 3121 2900 +3264 3222 2411 +2929 3330 0 +0 3443 0 +0 3560 0 +0 3681 0 +3821 2635 3524 +3821 2635 3524 +3821 2635 3524 +3821 2635 3524 +3821 2636 3524 +3821 2636 3524 +3821 2637 3523 +3821 2638 3523 +3821 2639 3523 +3820 2641 3523 +3820 2644 3522 +3819 2647 3521 +3819 2651 3520 +3818 2656 3519 +3817 2663 3517 +3815 2673 3515 +3813 2685 3512 +3810 2701 3507 +3806 2721 3502 +3801 2747 3494 +3794 2780 3483 +3784 2820 3468 +3770 2869 3448 +3752 2927 3419 +3726 2995 3377 +3688 3072 3314 +3633 3158 3213 +3546 3252 3030 +3397 3354 2537 +3062 3462 0 +0 3575 0 +0 3692 0 +3953 2765 3656 +3953 2765 3656 +3953 2765 3656 +3953 2765 3656 +3953 2765 3655 +3953 2766 3655 +3953 2766 3655 +3953 2767 3655 +3953 2768 3655 +3953 2770 3655 +3952 2771 3654 +3952 2774 3654 +3952 2777 3653 +3951 2781 3652 +3950 2786 3651 +3949 2793 3649 +3947 2803 3646 +3945 2815 3643 +3942 2831 3639 +3938 2852 3633 +3933 2878 3625 +3926 2911 3615 +3916 2951 3600 +3903 3000 3579 +3884 3058 3550 +3858 3126 3508 +3821 3203 3445 +3765 3289 3344 +3679 3384 3161 +3529 3485 2664 +3195 3593 0 +0 3707 0 +4086 2895 3787 +4086 2895 3787 +4086 2895 3787 +4086 2896 3787 +4086 2896 3787 +4086 2896 3787 +4086 2896 3787 +4085 2897 3787 +4085 2898 3787 +4085 2899 3787 +4085 2900 3786 +4085 2902 3786 +4084 2904 3785 +4084 2907 3785 +4083 2911 3784 +4082 2917 3782 +4081 2924 3780 +4079 2934 3778 +4077 2946 3775 +4074 2962 3771 +4070 2983 3765 +4065 3009 3757 +4058 3042 3746 +4048 3082 3731 +4035 3131 3711 +4016 3189 3682 +3990 3257 3640 +3953 3334 3577 +3897 3421 3476 +3811 3515 3292 +3662 3617 2793 +3327 3725 0 +4095 3026 3919 +4095 3026 3919 +4095 3026 3919 +4095 3026 3919 +4095 3026 3919 +4095 3027 3919 +4095 3027 3919 +4095 3027 3919 +4095 3028 3919 +4095 3029 3919 +4095 3030 3918 +4095 3031 3918 +4095 3033 3918 +4095 3035 3917 +4095 3038 3916 +4095 3042 3915 +4095 3048 3914 +4095 3055 3912 +4095 3065 3910 +4095 3077 3907 +4095 3093 3902 +4095 3114 3897 +4095 3140 3889 +4095 3173 3878 +4095 3213 3863 +4095 3263 3843 +4095 3321 3813 +4095 3389 3771 +4085 3466 3708 +4030 3552 3607 +3943 3647 3423 +3794 3749 2922 +4095 3157 4051 +4095 3157 4051 +4095 3157 4051 +4095 3157 4051 +4095 3157 4051 +4095 3158 4051 +4095 3158 4051 +4095 3158 4051 +4095 3159 4051 +4095 3159 4051 +4095 3160 4050 +4095 3161 4050 +4095 3162 4050 +4095 3164 4049 +4095 3166 4049 +4095 3170 4048 +4095 3174 4047 +4095 3179 4046 +4095 3186 4044 +4095 3196 4042 +4095 3208 4039 +4095 3224 4034 +4095 3245 4028 +4095 3271 4021 +4095 3304 4010 +4095 3345 3995 +4095 3394 3974 +4095 3453 3945 +4095 3520 3903 +4095 3598 3840 +4095 3684 3739 +4075 3779 3555 +0 966 1218 +0 973 1211 +0 982 1202 +0 994 1191 +0 1009 1174 +0 1028 1151 +0 1053 1119 +0 1084 1071 +0 1122 999 +0 1169 879 +0 1225 645 +0 1291 0 +0 1366 0 +0 1450 0 +0 1542 0 +0 1643 0 +0 1749 0 +0 1861 0 +0 1978 0 +0 2098 0 +0 2221 0 +0 2346 0 +0 2473 0 +0 2601 0 +0 2730 0 +0 2860 0 +0 2990 0 +0 3121 0 +0 3252 0 +0 3383 0 +0 3515 0 +0 3647 0 +0 969 1227 +0 975 1221 +0 984 1212 +0 996 1201 +0 1011 1185 +0 1030 1162 +0 1055 1130 +0 1086 1084 +0 1124 1014 +0 1171 899 +0 1226 677 +0 1292 0 +0 1367 0 +0 1451 0 +0 1543 0 +0 1643 0 +0 1750 0 +0 1862 0 +0 1978 0 +0 2098 0 +0 2221 0 +0 2346 0 +0 2473 0 +0 2601 0 +0 2730 0 +0 2860 0 +0 2990 0 +0 3121 0 +0 3252 0 +0 3384 0 +0 3515 0 +0 3647 0 +0 972 1239 +0 978 1233 +0 987 1225 +0 999 1214 +0 1014 1198 +0 1033 1176 +0 1057 1146 +0 1088 1101 +0 1126 1033 +0 1173 924 +0 1228 717 +0 1293 53 +0 1368 0 +0 1452 0 +0 1544 0 +0 1644 0 +0 1750 0 +0 1862 0 +0 1978 0 +0 2098 0 +0 2221 0 +0 2346 0 +0 2473 0 +0 2601 0 +0 2730 0 +0 2860 0 +0 2990 0 +0 3121 0 +0 3252 0 +0 3384 0 +0 3515 0 +0 3647 0 +0 976 1255 +0 982 1249 +0 991 1241 +0 1002 1230 +0 1017 1215 +0 1036 1195 +0 1061 1165 +0 1091 1122 +0 1129 1058 +0 1175 955 +0 1231 766 +0 1295 233 +0 1370 0 +0 1453 0 +0 1545 0 +0 1645 0 +0 1751 0 +0 1863 0 +0 1979 0 +0 2099 0 +0 2221 0 +0 2346 0 +0 2473 0 +0 2601 0 +0 2730 0 +0 2860 0 +0 2990 0 +0 3121 0 +0 3252 0 +0 3384 0 +0 3515 0 +0 3647 0 +0 981 1276 +0 988 1270 +0 996 1263 +0 1008 1252 +0 1022 1238 +0 1041 1218 +0 1065 1190 +0 1095 1150 +0 1133 1090 +0 1179 994 +0 1234 824 +0 1298 398 +0 1372 0 +0 1455 0 +0 1547 0 +0 1646 0 +0 1752 0 +0 1863 0 +0 1979 0 +0 2099 0 +0 2222 0 +0 2347 0 +0 2473 0 +0 2601 0 +0 2730 0 +0 2860 0 +0 2990 0 +0 3121 0 +0 3252 0 +0 3384 0 +0 3515 0 +0 3647 0 +0 988 1302 +0 995 1297 +0 1003 1289 +0 1014 1280 +0 1029 1266 +0 1047 1247 +0 1071 1221 +0 1101 1184 +0 1138 1128 +0 1183 1041 +0 1238 891 +0 1301 553 +0 1375 0 +0 1457 0 +0 1549 0 +0 1648 0 +0 1753 0 +0 1864 0 +0 1980 0 +0 2100 0 +0 2222 0 +0 2347 0 +0 2474 0 +0 2601 0 +0 2730 0 +0 2860 0 +0 2990 0 +0 3121 0 +0 3252 0 +0 3384 0 +0 3515 0 +0 3647 0 +329 998 1335 +265 1004 1330 +164 1012 1323 +0 1023 1314 +0 1037 1301 +0 1055 1284 +0 1079 1260 +0 1108 1226 +0 1145 1175 +0 1189 1098 +0 1243 968 +0 1306 702 +0 1379 0 +0 1461 0 +0 1551 0 +0 1650 0 +0 1755 0 +0 1866 0 +0 1981 0 +0 2101 0 +0 2223 0 +0 2347 0 +0 2474 0 +0 2602 0 +0 2731 0 +0 2860 0 +0 2991 0 +0 3121 0 +0 3252 0 +0 3384 0 +0 3515 0 +0 3647 0 +770 1010 1375 +747 1016 1370 +715 1024 1364 +667 1035 1356 +594 1048 1345 +474 1066 1329 +239 1089 1307 +0 1118 1276 +0 1154 1232 +0 1197 1164 +0 1250 1054 +0 1312 846 +0 1384 171 +0 1465 0 +0 1555 0 +0 1653 0 +0 1757 0 +0 1868 0 +0 1983 0 +0 2102 0 +0 2224 0 +0 2348 0 +0 2474 0 +0 2602 0 +0 2731 0 +0 2860 0 +0 2991 0 +0 3121 0 +0 3252 0 +0 3384 0 +0 3515 0 +0 3647 0 +1045 1025 1424 +1033 1031 1420 +1016 1039 1414 +992 1049 1407 +957 1063 1397 +907 1080 1383 +830 1102 1364 +702 1130 1336 +440 1165 1297 +0 1208 1239 +0 1260 1148 +0 1321 987 +0 1391 606 +0 1471 0 +0 1560 0 +0 1657 0 +0 1760 0 +0 1870 0 +0 1985 0 +0 2103 0 +0 2225 0 +0 2349 0 +0 2475 0 +0 2603 0 +0 2731 0 +0 2861 0 +0 2991 0 +0 3122 0 +0 3253 0 +0 3384 0 +0 3515 0 +0 3647 0 +1261 1046 1482 +1253 1051 1478 +1242 1059 1473 +1228 1069 1467 +1208 1082 1458 +1180 1098 1446 +1139 1119 1429 +1079 1146 1406 +982 1180 1373 +810 1222 1324 +372 1272 1249 +0 1331 1126 +0 1400 879 +0 1479 0 +0 1566 0 +0 1662 0 +0 1764 0 +0 1873 0 +0 1987 0 +0 2105 0 +0 2226 0 +0 2350 0 +0 2476 0 +0 2603 0 +0 2732 0 +0 2861 0 +0 2991 0 +0 3122 0 +0 3253 0 +0 3384 0 +0 3515 0 +0 3647 0 +1446 1072 1550 +1441 1077 1546 +1434 1084 1542 +1425 1093 1537 +1412 1105 1529 +1394 1121 1519 +1370 1141 1505 +1334 1167 1485 +1282 1199 1457 +1200 1239 1417 +1063 1288 1357 +771 1345 1263 +0 1412 1094 +0 1489 678 +0 1575 0 +0 1668 0 +0 1770 0 +0 1877 0 +0 1990 0 +0 2108 0 +0 2228 0 +0 2352 0 +0 2477 0 +0 2604 0 +0 2732 0 +0 2862 0 +0 2992 0 +0 3122 0 +0 3253 0 +0 3384 0 +0 3515 0 +0 3647 0 +1615 1104 1627 +1611 1109 1624 +1607 1115 1621 +1600 1124 1616 +1592 1135 1609 +1580 1150 1601 +1563 1169 1589 +1540 1193 1573 +1508 1224 1550 +1460 1262 1518 +1388 1308 1470 +1268 1363 1398 +1033 1428 1280 +0 1502 1048 +0 1585 57 +0 1677 0 +0 1777 0 +0 1883 0 +0 1995 0 +0 2111 0 +0 2231 0 +0 2354 0 +0 2479 0 +0 2605 0 +0 2733 0 +0 2862 0 +0 2992 0 +0 3122 0 +0 3253 0 +0 3384 0 +0 3516 0 +0 3647 0 +1772 1144 1713 +1770 1148 1711 +1767 1154 1708 +1762 1162 1704 +1756 1173 1699 +1748 1186 1692 +1737 1204 1682 +1721 1226 1669 +1699 1255 1650 +1669 1290 1624 +1624 1334 1588 +1557 1386 1533 +1448 1448 1448 +1243 1519 1301 +591 1600 979 +0 1689 0 +0 1786 0 +0 1891 0 +0 2001 0 +0 2116 0 +0 2234 0 +0 2356 0 +0 2481 0 +0 2607 0 +0 2734 0 +0 2863 0 +0 2993 0 +0 3123 0 +0 3254 0 +0 3385 0 +0 3516 0 +0 3647 0 +1923 1192 1807 +1921 1196 1805 +1919 1202 1803 +1915 1209 1800 +1911 1218 1796 +1905 1231 1790 +1897 1247 1782 +1886 1267 1772 +1871 1293 1757 +1851 1326 1737 +1821 1366 1708 +1779 1415 1667 +1715 1473 1605 +1613 1541 1507 +1426 1618 1329 +905 1704 865 +0 1799 0 +0 1900 0 +0 2008 0 +0 2122 0 +0 2239 0 +0 2360 0 +0 2483 0 +0 2609 0 +0 2736 0 +0 2864 0 +0 2994 0 +0 3124 0 +0 3254 0 +0 3385 0 +0 3516 0 +0 3648 0 +2068 1250 1909 +2067 1253 1908 +2065 1258 1906 +2063 1265 1903 +2059 1273 1900 +2055 1284 1895 +2049 1298 1889 +2042 1317 1881 +2031 1340 1869 +2017 1370 1854 +1997 1406 1832 +1968 1451 1801 +1927 1505 1755 +1866 1569 1687 +1768 1641 1575 +1592 1724 1364 +1138 1815 648 +0 1913 0 +0 2018 0 +0 2129 0 +0 2245 0 +0 2364 0 +0 2487 0 +0 2612 0 +0 2738 0 +0 2866 0 +0 2995 0 +0 3124 0 +0 3255 0 +0 3385 0 +0 3516 0 +0 3648 0 +2210 1317 2017 +2209 1320 2016 +2207 1324 2014 +2206 1330 2012 +2203 1337 2010 +2200 1347 2006 +2196 1359 2001 +2191 1375 1995 +2183 1396 1986 +2173 1422 1974 +2158 1455 1957 +2139 1496 1934 +2111 1545 1900 +2071 1603 1852 +2011 1671 1777 +1916 1749 1653 +1748 1835 1406 +1333 1930 0 +0 2032 0 +0 2140 0 +0 2253 0 +0 2371 0 +0 2492 0 +0 2615 0 +0 2741 0 +0 2868 0 +0 2996 0 +0 3126 0 +0 3256 0 +0 3386 0 +0 3517 0 +0 3648 0 +2349 1394 2130 +2348 1396 2129 +2347 1400 2128 +2346 1404 2127 +2344 1411 2125 +2342 1419 2122 +2339 1429 2118 +2335 1443 2113 +2329 1461 2106 +2322 1484 2097 +2312 1513 2084 +2298 1549 2067 +2278 1593 2042 +2251 1646 2007 +2211 1708 1955 +2153 1780 1875 +2061 1861 1740 +1898 1951 1457 +1507 2049 0 +0 2153 0 +0 2264 0 +0 2379 0 +0 2498 0 +0 2620 0 +0 2744 0 +0 2871 0 +0 2998 0 +0 3127 0 +0 3257 0 +0 3387 0 +0 3518 0 +0 3649 0 +2486 1479 2248 +2485 1482 2247 +2485 1484 2246 +2484 1488 2245 +2483 1493 2243 +2481 1500 2241 +2479 1509 2238 +2476 1521 2234 +2472 1536 2229 +2466 1555 2222 +2459 1580 2213 +2449 1611 2199 +2435 1650 2181 +2416 1697 2155 +2389 1753 2119 +2350 1818 2064 +2292 1893 1980 +2201 1978 1835 +2042 2070 1518 +1668 2171 0 +0 2277 0 +0 2389 0 +0 2506 0 +0 2626 0 +0 2749 0 +0 2874 0 +0 3001 0 +0 3129 0 +0 3258 0 +0 3388 0 +0 3519 0 +0 3649 0 +2622 1573 2368 +2621 1575 2368 +2621 1578 2367 +2620 1581 2366 +2619 1585 2365 +2618 1590 2363 +2616 1598 2361 +2614 1607 2358 +2611 1620 2354 +2607 1636 2349 +2602 1657 2342 +2595 1683 2332 +2585 1716 2318 +2571 1757 2299 +2552 1807 2273 +2525 1865 2235 +2487 1934 2179 +2430 2011 2091 +2340 2098 1937 +2183 2193 1588 +1820 2295 0 +0 2403 0 +0 2517 0 +0 2634 0 +0 2755 0 +0 2879 0 +0 3005 0 +0 3132 0 +0 3260 0 +0 3390 0 +0 3520 0 +0 3650 0 +2757 1675 2492 +2756 1676 2491 +2756 1678 2491 +2756 1681 2490 +2755 1684 2489 +2754 1688 2488 +2753 1694 2486 +2751 1702 2484 +2749 1712 2481 +2746 1726 2477 +2742 1743 2472 +2737 1765 2464 +2729 1793 2454 +2719 1827 2440 +2706 1870 2421 +2687 1922 2394 +2660 1982 2355 +2622 2053 2297 +2566 2132 2206 +2477 2221 2046 +2322 2318 1667 +1967 2421 0 +0 2531 0 +0 2645 0 +0 2764 0 +0 2885 0 +0 3010 0 +0 3136 0 +0 3263 0 +0 3392 0 +0 3521 0 +0 3651 0 +2891 1782 2617 +2891 1784 2617 +2890 1785 2617 +2890 1787 2616 +2890 1790 2615 +2889 1793 2615 +2888 1798 2613 +2887 1804 2612 +2885 1812 2609 +2883 1823 2606 +2880 1837 2602 +2876 1855 2597 +2871 1878 2589 +2863 1907 2579 +2854 1943 2565 +2840 1987 2545 +2821 2040 2518 +2795 2103 2478 +2757 2175 2419 +2701 2256 2325 +2612 2346 2159 +2459 2444 1755 +2110 2549 0 +0 2659 0 +0 2775 0 +0 2894 0 +0 3016 0 +0 3140 0 +0 3267 0 +0 3395 0 +0 3523 0 +0 3653 0 +3025 1895 2745 +3024 1896 2744 +3024 1897 2744 +3024 1899 2744 +3024 1901 2743 +3023 1904 2742 +3022 1908 2741 +3022 1912 2740 +3020 1919 2738 +3019 1927 2736 +3017 1938 2733 +3014 1953 2729 +3010 1971 2723 +3004 1995 2716 +2997 2025 2705 +2987 2062 2691 +2974 2108 2671 +2955 2162 2643 +2929 2226 2603 +2891 2299 2543 +2835 2382 2447 +2747 2473 2277 +2595 2572 1852 +2250 2678 0 +0 2789 0 +0 2905 0 +0 3024 0 +0 3147 0 +0 3272 0 +0 3398 0 +0 3526 0 +0 3655 0 +3158 2013 2873 +3158 2013 2873 +3158 2014 2872 +3157 2015 2872 +3157 2017 2872 +3157 2019 2871 +3156 2022 2871 +3156 2026 2870 +3155 2031 2868 +3154 2038 2867 +3152 2046 2864 +3150 2058 2861 +3147 2073 2857 +3143 2092 2851 +3138 2116 2844 +3130 2147 2833 +3120 2185 2819 +3107 2231 2799 +3088 2286 2770 +3062 2351 2730 +3024 2426 2669 +2968 2509 2572 +2881 2601 2398 +2730 2701 1955 +2388 2807 0 +0 2919 0 +0 3035 0 +0 3155 0 +0 3278 0 +0 3403 0 +0 3530 0 +0 3658 0 +3291 2133 3002 +3291 2134 3002 +3291 2135 3002 +3291 2135 3002 +3290 2137 3001 +3290 2138 3001 +3290 2141 3000 +3289 2143 3000 +3288 2147 2999 +3288 2153 2997 +3286 2159 2996 +3285 2168 2993 +3283 2180 2990 +3280 2195 2986 +3276 2215 2980 +3270 2239 2973 +3263 2271 2962 +3253 2309 2947 +3240 2356 2927 +3221 2412 2899 +3195 2478 2858 +3157 2553 2796 +3102 2638 2698 +3015 2730 2522 +2864 2831 2065 +2524 2938 0 +0 3050 0 +0 3166 0 +0 3287 0 +0 3410 0 +0 3535 0 +0 3662 0 +3424 2257 3132 +3424 2257 3132 +3423 2258 3132 +3423 2258 3132 +3423 2259 3132 +3423 2261 3131 +3423 2262 3131 +3422 2264 3130 +3422 2267 3130 +3421 2271 3129 +3420 2277 3127 +3419 2284 3126 +3417 2293 3123 +3415 2304 3120 +3412 2320 3116 +3408 2340 3110 +3403 2365 3102 +3396 2397 3092 +3386 2436 3077 +3373 2483 3057 +3354 2540 3028 +3328 2606 2987 +3290 2682 2925 +3235 2767 2826 +3148 2860 2647 +2997 2961 2179 +2659 3068 0 +0 3181 0 +0 3298 0 +0 3418 0 +0 3541 0 +0 3666 0 +3556 2382 3263 +3556 2382 3263 +3556 2383 3262 +3556 2383 3262 +3556 2384 3262 +3556 2385 3262 +3556 2386 3262 +3555 2388 3261 +3555 2390 3261 +3554 2393 3260 +3554 2397 3259 +3553 2403 3258 +3552 2410 3256 +3550 2419 3254 +3548 2431 3250 +3545 2446 3246 +3541 2466 3240 +3536 2492 3233 +3529 2524 3222 +3519 2564 3207 +3505 2612 3187 +3487 2669 3158 +3461 2736 3117 +3423 2812 3054 +3368 2897 2955 +3281 2991 2775 +3131 3092 2297 +2794 3199 0 +0 3312 0 +0 3429 0 +0 3550 0 +0 3673 0 +3689 2509 3394 +3689 2509 3393 +3689 2510 3393 +3689 2510 3393 +3688 2511 3393 +3688 2511 3393 +3688 2512 3393 +3688 2514 3392 +3688 2515 3392 +3687 2518 3392 +3687 2521 3391 +3686 2525 3390 +3685 2530 3389 +3684 2537 3387 +3682 2546 3384 +3680 2559 3381 +3677 2574 3377 +3673 2595 3371 +3668 2620 3363 +3661 2653 3353 +3651 2692 3338 +3638 2741 3318 +3619 2798 3289 +3593 2865 3247 +3556 2942 3184 +3500 3028 3084 +3413 3122 2903 +3264 3223 2419 +2928 3331 0 +0 3443 0 +0 3561 0 +0 3681 0 +3821 2637 3525 +3821 2638 3525 +3821 2638 3525 +3821 2638 3525 +3821 2639 3524 +3821 2639 3524 +3821 2640 3524 +3821 2641 3524 +3820 2642 3524 +3820 2644 3523 +3820 2646 3523 +3819 2649 3522 +3818 2653 3521 +3818 2659 3520 +3816 2666 3518 +3815 2675 3516 +3813 2687 3512 +3810 2703 3508 +3806 2724 3502 +3801 2750 3494 +3793 2782 3484 +3784 2822 3469 +3770 2871 3448 +3752 2929 3420 +3725 2996 3378 +3688 3073 3315 +3633 3159 3215 +3546 3253 3032 +3396 3354 2543 +3061 3462 0 +0 3575 0 +0 3692 0 +3953 2767 3656 +3953 2767 3656 +3953 2767 3656 +3953 2767 3656 +3953 2768 3656 +3953 2768 3656 +3953 2769 3656 +3953 2769 3656 +3953 2770 3655 +3953 2772 3655 +3952 2773 3655 +3952 2776 3654 +3951 2779 3653 +3951 2783 3652 +3950 2788 3651 +3949 2795 3649 +3947 2805 3647 +3945 2817 3644 +3942 2833 3639 +3938 2854 3634 +3933 2880 3626 +3926 2912 3615 +3916 2952 3600 +3902 3001 3580 +3884 3059 3551 +3858 3127 3509 +3820 3204 3446 +3765 3290 3345 +3678 3384 3162 +3529 3486 2669 +3194 3594 0 +0 3707 0 +4086 2897 3788 +4086 2897 3788 +4086 2897 3788 +4086 2897 3788 +4086 2897 3788 +4085 2898 3788 +4085 2898 3787 +4085 2899 3787 +4085 2899 3787 +4085 2900 3787 +4085 2902 3787 +4085 2903 3786 +4084 2906 3786 +4084 2909 3785 +4083 2913 3784 +4082 2918 3783 +4081 2926 3781 +4079 2935 3779 +4077 2947 3775 +4074 2963 3771 +4070 2984 3765 +4065 3010 3757 +4058 3043 3747 +4048 3083 3732 +4035 3132 3711 +4016 3190 3682 +3990 3258 3640 +3953 3335 3577 +3897 3421 3476 +3811 3516 3293 +3661 3617 2796 +3327 3725 0 +4095 3027 3919 +4095 3027 3919 +4095 3027 3919 +4095 3027 3919 +4095 3028 3919 +4095 3028 3919 +4095 3028 3919 +4095 3029 3919 +4095 3029 3919 +4095 3030 3919 +4095 3031 3919 +4095 3032 3918 +4095 3034 3918 +4095 3036 3917 +4095 3039 3917 +4095 3044 3916 +4095 3049 3914 +4095 3056 3913 +4095 3066 3910 +4095 3078 3907 +4095 3094 3903 +4095 3115 3897 +4095 3141 3889 +4095 3174 3878 +4095 3214 3863 +4095 3263 3843 +4095 3321 3814 +4095 3389 3772 +4085 3467 3709 +4030 3553 3608 +3943 3647 3424 +3794 3749 2925 +4095 3158 4051 +4095 3158 4051 +4095 3158 4051 +4095 3158 4051 +4095 3158 4051 +4095 3159 4051 +4095 3159 4051 +4095 3159 4051 +4095 3160 4051 +4095 3160 4051 +4095 3161 4051 +4095 3162 4050 +4095 3163 4050 +4095 3165 4050 +4095 3167 4049 +4095 3170 4048 +4095 3175 4047 +4095 3180 4046 +4095 3187 4044 +4095 3197 4042 +4095 3209 4039 +4095 3225 4035 +4095 3246 4029 +4095 3272 4021 +4095 3305 4010 +4095 3346 3995 +4095 3395 3975 +4095 3453 3946 +4095 3521 3903 +4095 3598 3840 +4095 3685 3739 +4075 3779 3555 +0 1092 1347 +0 1097 1342 +0 1104 1336 +0 1112 1327 +0 1124 1315 +0 1139 1298 +0 1159 1275 +0 1183 1242 +0 1215 1193 +0 1253 1119 +0 1300 996 +0 1356 751 +0 1422 0 +0 1497 0 +0 1581 0 +0 1674 0 +0 1774 0 +0 1881 0 +0 1993 0 +0 2110 0 +0 2230 0 +0 2353 0 +0 2478 0 +0 2605 0 +0 2733 0 +0 2862 0 +0 2992 0 +0 3122 0 +0 3253 0 +0 3384 0 +0 3516 0 +0 3647 0 +0 1093 1354 +0 1098 1350 +0 1105 1343 +0 1114 1335 +0 1126 1323 +0 1141 1306 +0 1160 1283 +0 1185 1251 +0 1216 1203 +0 1254 1131 +0 1301 1011 +0 1357 777 +0 1423 0 +0 1498 0 +0 1582 0 +0 1674 0 +0 1775 0 +0 1881 0 +0 1993 0 +0 2110 0 +0 2230 0 +0 2353 0 +0 2478 0 +0 2605 0 +0 2733 0 +0 2862 0 +0 2992 0 +0 3122 0 +0 3253 0 +0 3384 0 +0 3516 0 +0 3647 0 +0 1096 1364 +0 1101 1359 +0 1107 1353 +0 1116 1344 +0 1128 1333 +0 1143 1317 +0 1162 1294 +0 1187 1262 +0 1218 1216 +0 1256 1146 +0 1303 1031 +0 1359 809 +0 1424 0 +0 1499 0 +0 1583 0 +0 1675 0 +0 1775 0 +0 1882 0 +0 1994 0 +0 2110 0 +0 2230 0 +0 2353 0 +0 2478 0 +0 2605 0 +0 2733 0 +0 2862 0 +0 2992 0 +0 3122 0 +0 3253 0 +0 3384 0 +0 3516 0 +0 3647 0 +0 1099 1376 +0 1104 1371 +0 1110 1365 +0 1119 1357 +0 1131 1346 +0 1146 1330 +0 1165 1308 +0 1189 1278 +0 1220 1233 +0 1258 1165 +0 1305 1056 +0 1360 850 +0 1425 185 +0 1500 0 +0 1584 0 +0 1676 0 +0 1776 0 +0 1882 0 +0 1994 0 +0 2110 0 +0 2230 0 +0 2353 0 +0 2478 0 +0 2605 0 +0 2733 0 +0 2862 0 +0 2992 0 +0 3122 0 +0 3253 0 +0 3384 0 +0 3516 0 +0 3647 0 +0 1103 1392 +0 1108 1387 +0 1114 1381 +0 1123 1373 +0 1135 1363 +0 1149 1348 +0 1168 1327 +0 1193 1297 +0 1223 1255 +0 1261 1190 +0 1307 1087 +0 1363 898 +0 1427 365 +0 1502 0 +0 1585 0 +0 1677 0 +0 1777 0 +0 1883 0 +0 1995 0 +0 2111 0 +0 2231 0 +0 2354 0 +0 2479 0 +0 2605 0 +0 2733 0 +0 2862 0 +0 2992 0 +0 3122 0 +0 3253 0 +0 3384 0 +0 3516 0 +0 3647 0 +0 1108 1412 +0 1113 1408 +0 1120 1402 +0 1128 1395 +0 1140 1384 +0 1154 1370 +0 1173 1350 +0 1197 1322 +0 1227 1282 +0 1265 1222 +0 1311 1126 +0 1366 956 +0 1430 530 +0 1504 0 +0 1587 0 +0 1679 0 +0 1778 0 +0 1884 0 +0 1995 0 +0 2112 0 +0 2231 0 +0 2354 0 +0 2479 0 +0 2605 0 +0 2733 0 +0 2862 0 +0 2992 0 +0 3122 0 +0 3253 0 +0 3384 0 +0 3516 0 +0 3647 0 +0 1115 1438 +0 1120 1434 +0 1127 1429 +0 1135 1421 +0 1146 1412 +0 1161 1398 +0 1179 1380 +0 1203 1353 +0 1233 1316 +0 1270 1260 +0 1315 1173 +0 1370 1023 +0 1434 686 +0 1507 0 +0 1590 0 +0 1681 0 +0 1780 0 +0 1885 0 +0 1996 0 +0 2112 0 +0 2232 0 +0 2354 0 +0 2479 0 +0 2606 0 +0 2734 0 +0 2862 0 +0 2992 0 +0 3123 0 +0 3253 0 +0 3384 0 +0 3516 0 +0 3647 0 +503 1125 1470 +461 1130 1467 +397 1136 1462 +296 1144 1455 +111 1155 1446 +0 1169 1433 +0 1188 1416 +0 1211 1392 +0 1240 1358 +0 1277 1307 +0 1322 1230 +0 1375 1100 +0 1438 834 +0 1511 0 +0 1593 0 +0 1683 0 +0 1782 0 +0 1887 0 +0 1998 0 +0 2113 0 +0 2233 0 +0 2355 0 +0 2480 0 +0 2606 0 +0 2734 0 +0 2863 0 +0 2992 0 +0 3123 0 +0 3253 0 +0 3384 0 +0 3516 0 +0 3647 0 +919 1137 1510 +902 1142 1507 +879 1148 1502 +847 1156 1496 +799 1167 1488 +726 1180 1477 +606 1198 1461 +371 1221 1439 +0 1250 1409 +0 1286 1364 +0 1330 1296 +0 1382 1186 +0 1444 978 +0 1516 303 +0 1597 0 +0 1687 0 +0 1785 0 +0 1889 0 +0 2000 0 +0 2115 0 +0 2234 0 +0 2356 0 +0 2480 0 +0 2606 0 +0 2734 0 +0 2863 0 +0 2993 0 +0 3123 0 +0 3253 0 +0 3385 0 +0 3516 0 +0 3647 0 +1186 1153 1559 +1177 1158 1556 +1165 1164 1552 +1148 1171 1546 +1124 1182 1539 +1090 1195 1529 +1039 1212 1515 +962 1234 1496 +834 1262 1468 +572 1297 1429 +0 1340 1371 +0 1392 1280 +0 1453 1119 +0 1523 738 +0 1603 0 +0 1692 0 +0 1789 0 +0 1892 0 +0 2002 0 +0 2117 0 +0 2235 0 +0 2357 0 +0 2481 0 +0 2607 0 +0 2735 0 +0 2863 0 +0 2993 0 +0 3123 0 +0 3254 0 +0 3385 0 +0 3516 0 +0 3647 0 +1398 1174 1617 +1393 1178 1614 +1385 1184 1610 +1375 1191 1606 +1360 1201 1599 +1340 1214 1590 +1312 1230 1578 +1271 1251 1561 +1211 1278 1538 +1114 1312 1505 +942 1354 1456 +504 1404 1382 +0 1463 1258 +0 1532 1012 +0 1611 0 +0 1698 0 +0 1794 0 +0 1896 0 +0 2005 0 +0 2119 0 +0 2237 0 +0 2358 0 +0 2482 0 +0 2608 0 +0 2735 0 +0 2864 0 +0 2993 0 +0 3123 0 +0 3254 0 +0 3385 0 +0 3516 0 +0 3647 0 +1582 1200 1684 +1579 1204 1682 +1573 1209 1679 +1567 1216 1674 +1557 1225 1669 +1544 1237 1661 +1527 1253 1651 +1502 1273 1637 +1466 1299 1617 +1414 1331 1589 +1332 1371 1549 +1195 1420 1489 +903 1477 1395 +0 1544 1226 +0 1621 810 +0 1707 0 +0 1801 0 +0 1902 0 +0 2010 0 +0 2123 0 +0 2240 0 +0 2360 0 +0 2484 0 +0 2609 0 +0 2736 0 +0 2864 0 +0 2994 0 +0 3124 0 +0 3254 0 +0 3385 0 +0 3516 0 +0 3648 0 +1750 1232 1761 +1747 1236 1759 +1744 1241 1756 +1739 1248 1753 +1732 1256 1748 +1724 1268 1742 +1712 1282 1733 +1695 1301 1721 +1672 1326 1705 +1640 1356 1682 +1592 1394 1650 +1520 1440 1602 +1400 1495 1530 +1165 1560 1412 +102 1634 1180 +0 1718 189 +0 1809 0 +0 1909 0 +0 2015 0 +0 2127 0 +0 2243 0 +0 2363 0 +0 2486 0 +0 2611 0 +0 2737 0 +0 2865 0 +0 2994 0 +0 3124 0 +0 3254 0 +0 3385 0 +0 3516 0 +0 3648 0 +1906 1272 1846 +1905 1276 1845 +1902 1280 1843 +1899 1286 1840 +1894 1294 1836 +1888 1305 1831 +1880 1319 1824 +1869 1336 1814 +1853 1359 1801 +1831 1387 1782 +1801 1422 1757 +1756 1466 1720 +1689 1518 1665 +1580 1580 1580 +1375 1651 1434 +723 1732 1111 +0 1821 0 +0 1918 0 +0 2023 0 +0 2133 0 +0 2248 0 +0 2366 0 +0 2488 0 +0 2613 0 +0 2739 0 +0 2866 0 +0 2995 0 +0 3125 0 +0 3255 0 +0 3386 0 +0 3517 0 +0 3648 0 +2056 1321 1941 +2055 1324 1939 +2053 1328 1938 +2051 1334 1935 +2047 1341 1932 +2043 1350 1928 +2037 1363 1922 +2029 1379 1914 +2018 1399 1904 +2003 1425 1889 +1983 1458 1869 +1953 1498 1840 +1911 1547 1799 +1847 1605 1737 +1745 1673 1639 +1558 1750 1461 +1037 1836 997 +0 1931 0 +0 2032 0 +0 2140 0 +0 2254 0 +0 2371 0 +0 2492 0 +0 2615 0 +0 2741 0 +0 2868 0 +0 2996 0 +0 3126 0 +0 3256 0 +0 3386 0 +0 3517 0 +0 3648 0 +2201 1379 2042 +2200 1382 2041 +2199 1386 2040 +2197 1390 2038 +2195 1397 2035 +2191 1405 2032 +2187 1416 2027 +2182 1430 2021 +2174 1449 2013 +2163 1472 2001 +2149 1502 1986 +2129 1538 1964 +2100 1583 1933 +2059 1637 1887 +1998 1701 1819 +1900 1774 1707 +1724 1856 1496 +1270 1947 780 +0 2045 0 +0 2151 0 +0 2262 0 +0 2377 0 +0 2497 0 +0 2619 0 +0 2744 0 +0 2870 0 +0 2998 0 +0 3127 0 +0 3256 0 +0 3387 0 +0 3518 0 +0 3649 0 +2342 1447 2150 +2342 1449 2149 +2341 1452 2148 +2339 1456 2146 +2338 1462 2145 +2335 1469 2142 +2332 1479 2138 +2328 1491 2133 +2323 1507 2127 +2315 1528 2118 +2305 1554 2106 +2290 1587 2089 +2271 1628 2066 +2243 1677 2032 +2203 1735 1984 +2143 1803 1909 +2049 1881 1785 +1880 1967 1538 +1465 2062 3 +0 2164 0 +0 2272 0 +0 2385 0 +0 2503 0 +0 2624 0 +0 2747 0 +0 2873 0 +0 3000 0 +0 3128 0 +0 3258 0 +0 3388 0 +0 3518 0 +0 3649 0 +2481 1524 2263 +2481 1526 2262 +2480 1528 2261 +2479 1532 2260 +2478 1537 2259 +2476 1543 2257 +2474 1551 2254 +2471 1561 2250 +2467 1575 2245 +2461 1593 2238 +2454 1616 2229 +2444 1645 2216 +2430 1681 2199 +2410 1725 2174 +2383 1778 2139 +2344 1840 2087 +2285 1912 2007 +2193 1993 1872 +2030 2083 1589 +1639 2181 0 +0 2285 0 +0 2396 0 +0 2511 0 +0 2630 0 +0 2752 0 +0 2876 0 +0 3003 0 +0 3130 0 +0 3259 0 +0 3389 0 +0 3519 0 +0 3650 0 +2618 1610 2380 +2618 1611 2380 +2617 1614 2379 +2617 1617 2378 +2616 1620 2377 +2615 1626 2375 +2613 1632 2373 +2611 1641 2370 +2608 1653 2367 +2604 1668 2361 +2598 1687 2354 +2591 1712 2345 +2581 1743 2331 +2567 1782 2313 +2548 1829 2287 +2521 1885 2251 +2482 1950 2197 +2424 2026 2112 +2333 2110 1967 +2174 2202 1650 +1800 2303 0 +0 2409 0 +0 2522 0 +0 2638 0 +0 2758 0 +0 2881 0 +0 3006 0 +0 3133 0 +0 3261 0 +0 3390 0 +0 3520 0 +0 3651 0 +2754 1704 2501 +2754 1705 2500 +2754 1707 2500 +2753 1710 2499 +2752 1713 2498 +2751 1717 2497 +2750 1723 2496 +2749 1730 2493 +2746 1739 2490 +2743 1752 2486 +2739 1768 2481 +2734 1789 2474 +2727 1815 2464 +2717 1849 2450 +2703 1889 2432 +2684 1939 2405 +2657 1997 2367 +2619 2066 2311 +2562 2143 2223 +2472 2230 2069 +2315 2325 1720 +1952 2427 0 +0 2535 0 +0 2649 0 +0 2767 0 +0 2888 0 +0 3011 0 +0 3137 0 +0 3264 0 +0 3392 0 +0 3522 0 +0 3652 0 +2889 1806 2624 +2889 1807 2624 +2889 1808 2624 +2888 1810 2623 +2888 1813 2622 +2887 1816 2621 +2886 1821 2620 +2885 1826 2619 +2883 1834 2616 +2881 1844 2613 +2878 1858 2609 +2874 1875 2604 +2869 1897 2596 +2861 1925 2586 +2852 1959 2572 +2838 2002 2553 +2819 2054 2526 +2792 2114 2487 +2754 2185 2429 +2698 2265 2338 +2609 2353 2178 +2454 2450 1799 +2099 2553 0 +0 2663 0 +0 2777 0 +0 2896 0 +0 3018 0 +0 3142 0 +0 3268 0 +0 3395 0 +0 3524 0 +0 3653 0 +3023 1914 2750 +3023 1915 2749 +3023 1916 2749 +3023 1917 2749 +3022 1919 2748 +3022 1922 2748 +3021 1925 2747 +3020 1930 2745 +3019 1936 2744 +3017 1944 2741 +3015 1955 2738 +3012 1969 2734 +3008 1987 2729 +3003 2010 2721 +2996 2039 2711 +2986 2075 2697 +2972 2119 2677 +2953 2172 2650 +2927 2235 2610 +2889 2307 2551 +2833 2388 2457 +2744 2478 2291 +2591 2576 1888 +2242 2681 0 +0 2792 0 +0 2907 0 +0 3026 0 +0 3148 0 +0 3273 0 +0 3399 0 +0 3527 0 +0 3655 0 +3157 2027 2877 +3157 2028 2877 +3157 2028 2876 +3156 2030 2876 +3156 2031 2876 +3156 2033 2875 +3155 2036 2874 +3155 2040 2874 +3154 2045 2872 +3152 2051 2871 +3151 2059 2868 +3149 2071 2865 +3146 2085 2861 +3142 2104 2855 +3136 2127 2848 +3129 2157 2837 +3119 2194 2823 +3106 2240 2803 +3087 2294 2775 +3061 2358 2735 +3023 2431 2675 +2967 2514 2579 +2879 2605 2409 +2727 2704 1984 +2382 2810 0 +0 2921 0 +0 3037 0 +0 3157 0 +0 3279 0 +0 3404 0 +0 3530 0 +0 3658 0 +3290 2144 3005 +3290 2145 3005 +3290 2145 3005 +3290 2146 3005 +3290 2148 3004 +3289 2149 3004 +3289 2151 3003 +3288 2154 3003 +3288 2158 3002 +3287 2163 3000 +3286 2170 2999 +3284 2178 2996 +3282 2190 2993 +3279 2205 2989 +3275 2224 2983 +3270 2248 2976 +3262 2279 2965 +3253 2317 2951 +3239 2363 2931 +3220 2418 2902 +3194 2483 2862 +3156 2558 2801 +3101 2641 2704 +3013 2733 2530 +2862 2833 2087 +2520 2939 0 +0 3051 0 +0 3168 0 +0 3287 0 +0 3410 0 +0 3535 0 +0 3662 0 +3423 2265 3134 +3423 2265 3134 +3423 2266 3134 +3423 2267 3134 +3423 2268 3134 +3422 2269 3133 +3422 2270 3133 +3422 2273 3132 +3421 2276 3132 +3421 2279 3131 +3420 2285 3130 +3418 2291 3128 +3417 2300 3125 +3415 2312 3122 +3412 2327 3118 +3408 2347 3112 +3403 2371 3105 +3395 2403 3094 +3386 2441 3080 +3372 2488 3059 +3353 2545 3031 +3327 2610 2990 +3290 2685 2928 +3234 2770 2830 +3147 2863 2654 +2996 2963 2197 +2656 3070 0 +0 3182 0 +0 3298 0 +0 3419 0 +0 3542 0 +0 3667 0 +3556 2388 3264 +3556 2389 3264 +3556 2389 3264 +3556 2390 3264 +3555 2390 3264 +3555 2391 3264 +3555 2393 3263 +3555 2394 3263 +3554 2397 3262 +3554 2400 3262 +3553 2403 3261 +3552 2409 3259 +3551 2416 3258 +3550 2425 3255 +3547 2437 3252 +3544 2452 3248 +3541 2472 3242 +3535 2497 3234 +3528 2529 3224 +3518 2568 3209 +3505 2615 3189 +3486 2672 3160 +3460 2738 3119 +3422 2814 3057 +3367 2899 2958 +3280 2992 2780 +3130 3093 2311 +2791 3200 0 +0 3313 0 +0 3430 0 +0 3550 0 +0 3673 0 +3688 2514 3395 +3688 2514 3395 +3688 2515 3395 +3688 2515 3395 +3688 2515 3394 +3688 2516 3394 +3688 2517 3394 +3688 2518 3394 +3687 2520 3393 +3687 2522 3393 +3686 2525 3392 +3686 2529 3391 +3685 2535 3390 +3684 2542 3388 +3682 2551 3386 +3680 2563 3383 +3677 2579 3378 +3673 2599 3373 +3668 2624 3365 +3661 2656 3354 +3651 2696 3339 +3637 2744 3319 +3619 2801 3290 +3593 2868 3249 +3555 2944 3186 +3500 3029 3087 +3413 3123 2907 +3263 3224 2429 +2926 3331 0 +0 3444 0 +0 3561 0 +0 3682 0 +3821 2641 3526 +3821 2641 3526 +3821 2641 3526 +3821 2642 3526 +3821 2642 3525 +3821 2643 3525 +3820 2643 3525 +3820 2644 3525 +3820 2646 3525 +3820 2647 3524 +3819 2650 3524 +3819 2653 3523 +3818 2657 3522 +3817 2662 3521 +3816 2669 3519 +3815 2679 3517 +3812 2691 3513 +3809 2706 3509 +3806 2727 3503 +3800 2752 3495 +3793 2785 3485 +3783 2825 3470 +3770 2873 3450 +3751 2930 3421 +3725 2998 3379 +3688 3074 3316 +3632 3160 3216 +3546 3254 3035 +3396 3355 2551 +3060 3463 0 +0 3576 0 +0 3693 0 +3953 2769 3657 +3953 2770 3657 +3953 2770 3657 +3953 2770 3657 +3953 2770 3657 +3953 2771 3657 +3953 2771 3656 +3953 2772 3656 +3953 2773 3656 +3952 2774 3656 +3952 2776 3655 +3952 2778 3655 +3951 2781 3654 +3951 2785 3653 +3950 2791 3652 +3948 2798 3650 +3947 2807 3648 +3945 2820 3644 +3942 2835 3640 +3938 2856 3634 +3933 2882 3627 +3925 2914 3616 +3916 2954 3601 +3902 3003 3581 +3884 3061 3552 +3858 3128 3510 +3820 3205 3447 +3765 3291 3347 +3678 3385 3165 +3528 3486 2675 +3193 3594 0 +0 3707 0 +4085 2899 3788 +4085 2899 3788 +4085 2899 3788 +4085 2899 3788 +4085 2899 3788 +4085 2900 3788 +4085 2900 3788 +4085 2901 3788 +4085 2901 3788 +4085 2902 3787 +4085 2904 3787 +4084 2905 3787 +4084 2908 3786 +4084 2911 3785 +4083 2915 3784 +4082 2920 3783 +4081 2928 3781 +4079 2937 3779 +4077 2949 3776 +4074 2965 3772 +4070 2986 3766 +4065 3012 3758 +4058 3044 3747 +4048 3084 3732 +4035 3133 3712 +4016 3191 3683 +3990 3259 3641 +3952 3336 3578 +3897 3422 3477 +3811 3516 3295 +3661 3618 2801 +3326 3726 0 +4095 3029 3920 +4095 3029 3920 +4095 3029 3920 +4095 3029 3920 +4095 3029 3920 +4095 3029 3920 +4095 3030 3920 +4095 3030 3920 +4095 3031 3919 +4095 3031 3919 +4095 3032 3919 +4095 3034 3919 +4095 3035 3918 +4095 3038 3918 +4095 3041 3917 +4095 3045 3916 +4095 3050 3915 +4095 3058 3913 +4095 3067 3911 +4095 3079 3907 +4095 3095 3903 +4095 3116 3897 +4095 3142 3889 +4095 3175 3879 +4095 3215 3864 +4095 3264 3843 +4095 3322 3814 +4095 3390 3772 +4085 3467 3709 +4029 3553 3609 +3943 3648 3425 +3793 3750 2928 +4095 3159 4052 +4095 3159 4052 +4095 3159 4052 +4095 3159 4052 +4095 3160 4052 +4095 3160 4051 +4095 3160 4051 +4095 3160 4051 +4095 3161 4051 +4095 3161 4051 +4095 3162 4051 +4095 3163 4051 +4095 3164 4050 +4095 3166 4050 +4095 3168 4049 +4095 3171 4049 +4095 3176 4048 +4095 3181 4046 +4095 3188 4045 +4095 3198 4042 +4095 3210 4039 +4095 3226 4035 +4095 3247 4029 +4095 3273 4021 +4095 3306 4010 +4095 3346 3996 +4095 3395 3975 +4095 3454 3946 +4095 3521 3904 +4095 3599 3841 +4095 3685 3740 +4075 3780 3556 +0 1218 1478 +0 1222 1474 +0 1228 1469 +0 1234 1463 +0 1243 1454 +0 1255 1441 +0 1270 1424 +0 1290 1401 +0 1314 1367 +0 1346 1318 +0 1384 1242 +0 1431 1116 +0 1488 863 +0 1553 0 +0 1629 0 +0 1713 0 +0 1806 0 +0 1906 0 +0 2013 0 +0 2125 0 +0 2242 0 +0 2362 0 +0 2485 0 +0 2610 0 +0 2737 0 +0 2865 0 +0 2994 0 +0 3124 0 +0 3254 0 +0 3385 0 +0 3516 0 +0 3648 0 +0 1220 1483 +0 1224 1479 +0 1229 1475 +0 1236 1468 +0 1245 1459 +0 1256 1447 +0 1271 1430 +0 1291 1407 +0 1316 1374 +0 1347 1325 +0 1385 1251 +0 1432 1128 +0 1488 883 +0 1554 0 +0 1629 0 +0 1713 0 +0 1806 0 +0 1906 0 +0 2013 0 +0 2125 0 +0 2242 0 +0 2362 0 +0 2485 0 +0 2610 0 +0 2737 0 +0 2865 0 +0 2994 0 +0 3124 0 +0 3254 0 +0 3385 0 +0 3516 0 +0 3648 0 +0 1222 1490 +0 1225 1486 +0 1231 1482 +0 1237 1475 +0 1246 1467 +0 1258 1455 +0 1273 1438 +0 1292 1415 +0 1317 1383 +0 1348 1335 +0 1387 1263 +0 1433 1143 +0 1489 909 +0 1555 0 +0 1630 0 +0 1714 0 +0 1807 0 +0 1907 0 +0 2013 0 +0 2125 0 +0 2242 0 +0 2362 0 +0 2485 0 +0 2610 0 +0 2737 0 +0 2865 0 +0 2994 0 +0 3124 0 +0 3254 0 +0 3385 0 +0 3516 0 +0 3648 0 +0 1224 1499 +0 1228 1496 +0 1233 1491 +0 1240 1485 +0 1248 1476 +0 1260 1465 +0 1275 1449 +0 1294 1426 +0 1319 1395 +0 1350 1348 +0 1388 1278 +0 1435 1163 +0 1491 942 +0 1556 111 +0 1631 0 +0 1715 0 +0 1807 0 +0 1907 0 +0 2014 0 +0 2126 0 +0 2242 0 +0 2362 0 +0 2485 0 +0 2610 0 +0 2737 0 +0 2865 0 +0 2994 0 +0 3124 0 +0 3254 0 +0 3385 0 +0 3516 0 +0 3648 0 +0 1227 1511 +0 1231 1508 +0 1236 1503 +0 1243 1497 +0 1251 1489 +0 1263 1478 +0 1278 1462 +0 1297 1441 +0 1321 1410 +0 1352 1365 +0 1390 1298 +0 1437 1188 +0 1492 982 +0 1557 317 +0 1632 0 +0 1716 0 +0 1808 0 +0 1908 0 +0 2014 0 +0 2126 0 +0 2243 0 +0 2363 0 +0 2485 0 +0 2610 0 +0 2737 0 +0 2865 0 +0 2994 0 +0 3124 0 +0 3254 0 +0 3385 0 +0 3516 0 +0 3648 0 +0 1231 1527 +0 1235 1524 +0 1240 1519 +0 1247 1514 +0 1255 1506 +0 1267 1495 +0 1281 1480 +0 1300 1459 +0 1325 1429 +0 1355 1387 +0 1393 1322 +0 1439 1219 +0 1495 1030 +0 1559 497 +0 1634 0 +0 1717 0 +0 1809 0 +0 1909 0 +0 2015 0 +0 2127 0 +0 2243 0 +0 2363 0 +0 2486 0 +0 2611 0 +0 2737 0 +0 2865 0 +0 2994 0 +0 3124 0 +0 3254 0 +0 3385 0 +0 3516 0 +0 3648 0 +0 1237 1547 +0 1240 1544 +0 1245 1540 +0 1252 1534 +0 1260 1527 +0 1272 1516 +0 1286 1502 +0 1305 1482 +0 1329 1454 +0 1360 1414 +0 1397 1354 +0 1443 1258 +0 1498 1088 +0 1562 662 +0 1636 0 +0 1719 0 +0 1811 0 +0 1910 0 +0 2016 0 +0 2128 0 +0 2244 0 +0 2363 0 +0 2486 0 +0 2611 0 +0 2737 0 +0 2865 0 +0 2994 0 +0 3124 0 +0 3255 0 +0 3385 0 +0 3516 0 +0 3648 0 +0 1244 1573 +0 1248 1570 +0 1252 1566 +0 1259 1561 +0 1267 1554 +0 1278 1544 +0 1293 1530 +0 1311 1512 +0 1335 1486 +0 1365 1448 +0 1402 1392 +0 1448 1306 +0 1502 1155 +0 1566 818 +0 1639 0 +0 1722 0 +0 1813 0 +0 1912 0 +0 2017 0 +0 2129 0 +0 2244 0 +0 2364 0 +0 2486 0 +0 2611 0 +0 2738 0 +0 2866 0 +0 2995 0 +0 3124 0 +0 3255 0 +0 3385 0 +0 3516 0 +0 3648 0 +664 1253 1605 +635 1257 1602 +593 1262 1599 +530 1268 1594 +428 1276 1587 +243 1287 1578 +0 1301 1566 +0 1320 1548 +0 1343 1524 +0 1372 1490 +0 1409 1440 +0 1454 1362 +0 1507 1232 +0 1570 966 +0 1643 0 +0 1725 0 +0 1816 0 +0 1914 0 +0 2019 0 +0 2130 0 +0 2245 0 +0 2365 0 +0 2487 0 +0 2612 0 +0 2738 0 +0 2866 0 +0 2995 0 +0 3124 0 +0 3255 0 +0 3385 0 +0 3517 0 +0 3648 0 +1063 1266 1645 +1051 1269 1642 +1034 1274 1639 +1011 1280 1635 +979 1288 1628 +931 1299 1620 +858 1313 1609 +738 1330 1593 +503 1353 1571 +0 1382 1541 +0 1418 1496 +0 1462 1428 +0 1514 1318 +0 1577 1110 +0 1648 435 +0 1729 0 +0 1819 0 +0 1917 0 +0 2021 0 +0 2132 0 +0 2247 0 +0 2366 0 +0 2488 0 +0 2612 0 +0 2739 0 +0 2866 0 +0 2995 0 +0 3125 0 +0 3255 0 +0 3386 0 +0 3517 0 +0 3648 0 +1325 1282 1693 +1318 1285 1691 +1309 1290 1688 +1297 1296 1684 +1280 1303 1678 +1256 1314 1671 +1222 1327 1661 +1172 1344 1647 +1095 1366 1628 +966 1394 1601 +704 1429 1562 +0 1472 1503 +0 1524 1412 +0 1585 1251 +0 1655 870 +0 1735 0 +0 1824 0 +0 1921 0 +0 2024 0 +0 2134 0 +0 2249 0 +0 2367 0 +0 2489 0 +0 2613 0 +0 2739 0 +0 2867 0 +0 2995 0 +0 3125 0 +0 3255 0 +0 3386 0 +0 3517 0 +0 3648 0 +1535 1302 1751 +1530 1306 1749 +1525 1310 1746 +1517 1316 1742 +1507 1323 1738 +1492 1333 1731 +1472 1346 1722 +1444 1362 1710 +1404 1384 1693 +1343 1411 1670 +1246 1444 1637 +1074 1486 1588 +636 1536 1514 +0 1595 1390 +0 1664 1144 +0 1743 0 +0 1830 0 +0 1926 0 +0 2029 0 +0 2137 0 +0 2251 0 +0 2369 0 +0 2490 0 +0 2614 0 +0 2740 0 +0 2867 0 +0 2996 0 +0 3125 0 +0 3255 0 +0 3386 0 +0 3517 0 +0 3648 0 +1717 1329 1818 +1714 1332 1816 +1711 1336 1814 +1706 1341 1811 +1699 1348 1806 +1689 1357 1801 +1676 1370 1793 +1659 1385 1783 +1634 1406 1769 +1598 1431 1749 +1546 1464 1721 +1465 1503 1681 +1327 1552 1621 +1035 1609 1527 +0 1676 1358 +0 1753 942 +0 1839 0 +0 1933 0 +0 2034 0 +0 2142 0 +0 2255 0 +0 2372 0 +0 2492 0 +0 2616 0 +0 2741 0 +0 2868 0 +0 2997 0 +0 3126 0 +0 3256 0 +0 3386 0 +0 3517 0 +0 3648 0 +1884 1361 1894 +1882 1364 1893 +1879 1368 1891 +1876 1373 1888 +1871 1380 1885 +1865 1388 1880 +1856 1400 1874 +1844 1414 1865 +1827 1433 1853 +1805 1458 1837 +1772 1488 1814 +1724 1526 1782 +1652 1572 1734 +1532 1627 1662 +1297 1692 1544 +234 1766 1313 +0 1850 322 +0 1942 0 +0 2041 0 +0 2147 0 +0 2259 0 +0 2375 0 +0 2495 0 +0 2618 0 +0 2743 0 +0 2869 0 +0 2997 0 +0 3126 0 +0 3256 0 +0 3387 0 +0 3517 0 +0 3648 0 +2040 1402 1980 +2038 1405 1979 +2037 1408 1977 +2034 1413 1975 +2031 1419 1972 +2026 1427 1968 +2020 1437 1963 +2012 1451 1956 +2001 1468 1946 +1985 1491 1933 +1964 1519 1914 +1933 1555 1889 +1888 1598 1852 +1821 1650 1797 +1712 1712 1712 +1507 1783 1566 +855 1864 1243 +0 1953 0 +0 2051 0 +0 2155 0 +0 2265 0 +0 2380 0 +0 2499 0 +0 2620 0 +0 2745 0 +0 2871 0 +0 2999 0 +0 3127 0 +0 3257 0 +0 3387 0 +0 3518 0 +0 3649 0 +2189 1451 2074 +2188 1453 2073 +2187 1456 2071 +2185 1461 2070 +2183 1466 2067 +2180 1473 2064 +2175 1483 2060 +2169 1495 2054 +2161 1511 2046 +2151 1531 2036 +2136 1557 2021 +2115 1590 2001 +2085 1630 1972 +2043 1679 1931 +1979 1737 1869 +1877 1805 1771 +1690 1882 1593 +1170 1968 1129 +0 2063 0 +0 2165 0 +0 2273 0 +0 2386 0 +0 2503 0 +0 2624 0 +0 2747 0 +0 2873 0 +0 3000 0 +0 3128 0 +0 3258 0 +0 3388 0 +0 3518 0 +0 3649 0 +2334 1509 2175 +2333 1511 2174 +2332 1514 2173 +2331 1518 2172 +2329 1522 2170 +2327 1529 2167 +2324 1537 2164 +2319 1548 2159 +2314 1562 2153 +2306 1581 2145 +2295 1604 2134 +2281 1634 2118 +2261 1671 2096 +2232 1716 2065 +2191 1769 2019 +2130 1833 1951 +2032 1906 1839 +1856 1988 1628 +1402 2079 912 +0 2177 0 +0 2283 0 +0 2394 0 +0 2509 0 +0 2629 0 +0 2751 0 +0 2876 0 +0 3002 0 +0 3130 0 +0 3259 0 +0 3389 0 +0 3519 0 +0 3650 0 +2475 1577 2283 +2474 1579 2282 +2474 1581 2281 +2473 1584 2280 +2472 1588 2279 +2470 1594 2277 +2468 1601 2274 +2464 1611 2270 +2460 1623 2266 +2455 1639 2259 +2447 1660 2250 +2437 1686 2238 +2423 1719 2221 +2403 1760 2198 +2375 1809 2165 +2335 1867 2116 +2275 1935 2041 +2181 2013 1917 +2012 2099 1670 +1597 2194 135 +0 2296 0 +0 2404 0 +0 2517 0 +0 2635 0 +0 2756 0 +0 2879 0 +0 3005 0 +0 3132 0 +0 3260 0 +0 3390 0 +0 3520 0 +0 3650 0 +2614 1654 2395 +2613 1656 2395 +2613 1658 2394 +2612 1660 2393 +2611 1664 2392 +2610 1669 2391 +2608 1675 2389 +2606 1683 2386 +2603 1694 2382 +2599 1707 2377 +2593 1725 2370 +2586 1748 2361 +2576 1777 2348 +2562 1813 2331 +2542 1857 2306 +2515 1910 2271 +2476 1972 2219 +2417 2044 2139 +2325 2125 2004 +2162 2215 1721 +1771 2313 0 +0 2417 0 +0 2528 0 +0 2643 0 +0 2762 0 +0 2884 0 +0 3009 0 +0 3135 0 +0 3263 0 +0 3391 0 +0 3521 0 +0 3651 0 +2751 1741 2513 +2750 1742 2512 +2750 1744 2512 +2750 1746 2511 +2749 1749 2510 +2748 1753 2509 +2747 1758 2507 +2745 1764 2505 +2743 1773 2502 +2740 1785 2499 +2736 1800 2493 +2730 1819 2486 +2723 1844 2477 +2713 1875 2464 +2699 1914 2445 +2680 1961 2420 +2653 2017 2383 +2614 2083 2329 +2556 2158 2244 +2466 2242 2099 +2306 2335 1782 +1932 2435 0 +0 2542 0 +0 2654 0 +0 2770 0 +0 2890 0 +0 3013 0 +0 3138 0 +0 3265 0 +0 3393 0 +0 3522 0 +0 3652 0 +2887 1835 2633 +2886 1836 2633 +2886 1838 2633 +2886 1839 2632 +2885 1842 2631 +2884 1845 2630 +2884 1849 2629 +2882 1855 2628 +2881 1862 2625 +2878 1872 2623 +2875 1884 2619 +2871 1900 2613 +2866 1921 2606 +2859 1948 2596 +2849 1981 2582 +2835 2021 2564 +2816 2071 2537 +2789 2130 2499 +2751 2198 2443 +2694 2275 2355 +2604 2362 2201 +2447 2457 1852 +2084 2559 0 +0 2668 0 +0 2781 0 +0 2899 0 +0 3020 0 +0 3143 0 +0 3269 0 +0 3396 0 +0 3525 0 +0 3654 0 +3021 1937 2757 +3021 1938 2756 +3021 1939 2756 +3021 1940 2756 +3020 1942 2755 +3020 1945 2754 +3019 1948 2754 +3018 1953 2752 +3017 1959 2751 +3015 1966 2748 +3013 1977 2745 +3010 1990 2741 +3006 2007 2736 +3001 2029 2728 +2994 2057 2718 +2984 2092 2705 +2970 2134 2685 +2951 2186 2658 +2924 2247 2619 +2886 2317 2561 +2830 2397 2470 +2741 2485 2310 +2586 2582 1931 +2231 2685 0 +0 2795 0 +0 2910 0 +0 3028 0 +0 3150 0 +0 3274 0 +0 3400 0 +0 3527 0 +0 3656 0 +3155 2045 2882 +3155 2046 2882 +3155 2047 2882 +3155 2048 2881 +3155 2049 2881 +3154 2051 2880 +3154 2054 2880 +3153 2057 2879 +3152 2062 2877 +3151 2068 2876 +3149 2077 2874 +3147 2087 2870 +3144 2101 2866 +3140 2119 2861 +3135 2142 2853 +3128 2171 2843 +3118 2207 2829 +3104 2251 2809 +3085 2304 2782 +3059 2367 2742 +3021 2439 2683 +2965 2520 2589 +2877 2610 2423 +2723 2708 2020 +2374 2813 0 +0 2924 0 +0 3039 0 +0 3158 0 +0 3280 0 +0 3405 0 +0 3531 0 +0 3659 0 +3289 2158 3009 +3289 2159 3009 +3289 2160 3009 +3289 2160 3009 +3288 2162 3008 +3288 2163 3008 +3288 2165 3007 +3287 2168 3007 +3287 2172 3006 +3286 2177 3004 +3285 2183 3003 +3283 2192 3000 +3281 2203 2997 +3278 2217 2993 +3274 2236 2988 +3269 2259 2980 +3261 2289 2969 +3251 2326 2955 +3238 2372 2935 +3219 2426 2907 +3193 2490 2867 +3155 2563 2807 +3099 2646 2711 +3011 2737 2541 +2859 2836 2116 +2514 2942 0 +0 3053 0 +0 3169 0 +0 3289 0 +0 3411 0 +0 3536 0 +0 3662 0 +3422 2276 3137 +3422 2276 3137 +3422 2277 3137 +3422 2278 3137 +3422 2278 3137 +3422 2280 3136 +3421 2281 3136 +3421 2283 3135 +3420 2286 3135 +3420 2290 3134 +3419 2295 3133 +3418 2302 3131 +3416 2310 3128 +3414 2322 3125 +3411 2337 3121 +3407 2356 3115 +3402 2380 3108 +3394 2411 3097 +3385 2449 3083 +3371 2495 3063 +3352 2551 3035 +3326 2615 2994 +3289 2690 2933 +3233 2773 2836 +3145 2866 2662 +2994 2965 2219 +2652 3072 0 +0 3183 0 +0 3300 0 +0 3420 0 +0 3542 0 +0 3667 0 +3555 2397 3267 +3555 2397 3266 +3555 2398 3266 +3555 2398 3266 +3555 2399 3266 +3555 2400 3266 +3555 2401 3266 +3554 2403 3265 +3554 2405 3265 +3553 2408 3264 +3553 2412 3263 +3552 2417 3262 +3551 2423 3260 +3549 2432 3258 +3547 2444 3254 +3544 2459 3250 +3540 2479 3245 +3535 2504 3237 +3527 2535 3226 +3518 2573 3212 +3504 2621 3191 +3485 2677 3163 +3459 2742 3122 +3422 2818 3060 +3366 2902 2962 +3279 2995 2786 +3128 3095 2329 +2788 3202 0 +0 3314 0 +0 3431 0 +0 3551 0 +0 3674 0 +3688 2520 3396 +3688 2521 3396 +3688 2521 3396 +3688 2521 3396 +3688 2522 3396 +3688 2522 3396 +3687 2523 3396 +3687 2525 3395 +3687 2526 3395 +3687 2529 3394 +3686 2532 3394 +3685 2536 3393 +3684 2541 3391 +3683 2548 3390 +3682 2557 3387 +3679 2569 3384 +3677 2584 3380 +3673 2604 3374 +3667 2629 3366 +3660 2661 3356 +3650 2700 3341 +3637 2748 3321 +3618 2804 3292 +3592 2871 3251 +3555 2946 3189 +3499 3031 3090 +3412 3125 2912 +3262 3225 2443 +2923 3332 0 +0 3445 0 +0 3562 0 +0 3682 0 +3820 2646 3527 +3820 2646 3527 +3820 2646 3527 +3820 2647 3527 +3820 2647 3527 +3820 2648 3527 +3820 2648 3526 +3820 2649 3526 +3820 2651 3526 +3819 2652 3525 +3819 2654 3525 +3819 2658 3524 +3818 2662 3523 +3817 2667 3522 +3816 2674 3520 +3814 2683 3518 +3812 2695 3515 +3809 2711 3510 +3805 2731 3505 +3800 2756 3497 +3793 2788 3486 +3783 2828 3471 +3769 2876 3451 +3751 2933 3422 +3725 3000 3381 +3687 3076 3318 +3632 3161 3219 +3545 3255 3039 +3395 3356 2562 +3058 3463 0 +0 3576 0 +0 3693 0 +3953 2773 3658 +3953 2773 3658 +3953 2773 3658 +3953 2774 3658 +3953 2774 3658 +3953 2774 3658 +3953 2775 3657 +3953 2776 3657 +3952 2777 3657 +3952 2778 3657 +3952 2780 3656 +3952 2782 3656 +3951 2785 3655 +3950 2789 3654 +3949 2794 3653 +3948 2801 3651 +3947 2811 3649 +3944 2823 3645 +3942 2839 3641 +3938 2859 3635 +3932 2885 3628 +3925 2917 3617 +3915 2957 3602 +3902 3005 3582 +3883 3063 3553 +3857 3130 3511 +3820 3206 3449 +3764 3292 3349 +3678 3386 3167 +3528 3487 2683 +3192 3595 0 +0 3708 0 +4085 2901 3789 +4085 2902 3789 +4085 2902 3789 +4085 2902 3789 +4085 2902 3789 +4085 2902 3789 +4085 2903 3789 +4085 2903 3789 +4085 2904 3788 +4085 2905 3788 +4085 2906 3788 +4084 2908 3787 +4084 2910 3787 +4083 2913 3786 +4083 2918 3785 +4082 2923 3784 +4081 2930 3782 +4079 2939 3780 +4077 2952 3777 +4074 2968 3772 +4070 2988 3767 +4065 3014 3759 +4058 3046 3748 +4048 3086 3733 +4034 3135 3713 +4016 3193 3684 +3990 3260 3642 +3952 3337 3579 +3897 3423 3479 +3810 3517 3297 +3660 3618 2807 +3325 3726 0 +4095 3031 3920 +4095 3031 3920 +4095 3031 3920 +4095 3031 3920 +4095 3031 3920 +4095 3031 3920 +4095 3032 3920 +4095 3032 3920 +4095 3033 3920 +4095 3033 3920 +4095 3034 3920 +4095 3036 3919 +4095 3037 3919 +4095 3040 3918 +4095 3043 3918 +4095 3047 3917 +4095 3052 3915 +4095 3060 3914 +4095 3069 3911 +4095 3081 3908 +4095 3097 3904 +4095 3118 3898 +4095 3144 3890 +4095 3176 3879 +4095 3217 3864 +4095 3265 3844 +4095 3323 3815 +4095 3391 3773 +4085 3468 3710 +4029 3554 3610 +3943 3648 3427 +3793 3750 2933 +4095 3161 4052 +4095 3161 4052 +4095 3161 4052 +4095 3161 4052 +4095 3161 4052 +4095 3161 4052 +4095 3161 4052 +4095 3162 4052 +4095 3162 4052 +4095 3163 4052 +4095 3163 4051 +4095 3164 4051 +4095 3166 4051 +4095 3168 4050 +4095 3170 4050 +4095 3173 4049 +4095 3177 4048 +4095 3183 4047 +4095 3190 4045 +4095 3199 4043 +4095 3212 4040 +4095 3228 4035 +4095 3248 4029 +4095 3274 4022 +4095 3307 4011 +4095 3347 3996 +4095 3396 3975 +4095 3454 3946 +4095 3522 3904 +4095 3599 3841 +4095 3685 3741 +4075 3780 3557 +0 1347 1608 +0 1350 1606 +0 1354 1602 +0 1359 1597 +0 1365 1590 +0 1374 1581 +0 1386 1569 +0 1401 1552 +0 1421 1528 +0 1446 1494 +0 1477 1444 +0 1516 1367 +0 1563 1239 +0 1619 979 +0 1685 0 +0 1760 0 +0 1845 0 +0 1938 0 +0 2038 0 +0 2145 0 +0 2257 0 +0 2374 0 +0 2494 0 +0 2617 0 +0 2742 0 +0 2869 0 +0 2997 0 +0 3126 0 +0 3256 0 +0 3386 0 +0 3517 0 +0 3648 0 +0 1348 1612 +0 1351 1610 +0 1354 1606 +0 1360 1601 +0 1366 1595 +0 1375 1586 +0 1387 1573 +0 1402 1557 +0 1422 1533 +0 1447 1499 +0 1478 1450 +0 1516 1374 +0 1564 1248 +0 1620 995 +0 1685 0 +0 1761 0 +0 1845 0 +0 1938 0 +0 2038 0 +0 2145 0 +0 2257 0 +0 2374 0 +0 2494 0 +0 2617 0 +0 2742 0 +0 2869 0 +0 2997 0 +0 3126 0 +0 3256 0 +0 3386 0 +0 3517 0 +0 3648 0 +0 1349 1618 +0 1352 1615 +0 1356 1611 +0 1361 1607 +0 1368 1600 +0 1377 1591 +0 1388 1579 +0 1403 1563 +0 1423 1539 +0 1448 1506 +0 1479 1457 +0 1517 1383 +0 1564 1260 +0 1620 1015 +0 1686 0 +0 1761 0 +0 1845 0 +0 1938 0 +0 2038 0 +0 2145 0 +0 2257 0 +0 2374 0 +0 2494 0 +0 2617 0 +0 2742 0 +0 2869 0 +0 2997 0 +0 3126 0 +0 3256 0 +0 3386 0 +0 3517 0 +0 3648 0 +0 1351 1625 +0 1354 1622 +0 1358 1619 +0 1363 1614 +0 1369 1607 +0 1378 1599 +0 1390 1587 +0 1405 1570 +0 1424 1548 +0 1449 1515 +0 1480 1467 +0 1519 1395 +0 1565 1275 +0 1621 1041 +0 1687 0 +0 1762 0 +0 1846 0 +0 1939 0 +0 2039 0 +0 2145 0 +0 2258 0 +0 2374 0 +0 2494 0 +0 2617 0 +0 2742 0 +0 2869 0 +0 2997 0 +0 3126 0 +0 3256 0 +0 3386 0 +0 3517 0 +0 3648 0 +0 1353 1634 +0 1356 1631 +0 1360 1628 +0 1365 1623 +0 1372 1617 +0 1381 1608 +0 1392 1597 +0 1407 1581 +0 1426 1558 +0 1451 1527 +0 1482 1480 +0 1520 1410 +0 1567 1295 +0 1623 1074 +0 1688 244 +0 1763 0 +0 1847 0 +0 1939 0 +0 2039 0 +0 2146 0 +0 2258 0 +0 2374 0 +0 2494 0 +0 2617 0 +0 2742 0 +0 2869 0 +0 2997 0 +0 3126 0 +0 3256 0 +0 3386 0 +0 3517 0 +0 3648 0 +0 1356 1646 +0 1359 1643 +0 1363 1640 +0 1368 1636 +0 1375 1629 +0 1383 1621 +0 1395 1610 +0 1410 1594 +0 1429 1573 +0 1453 1542 +0 1484 1497 +0 1522 1430 +0 1569 1320 +0 1624 1114 +0 1690 449 +0 1764 0 +0 1848 0 +0 1940 0 +0 2040 0 +0 2146 0 +0 2258 0 +0 2375 0 +0 2495 0 +0 2617 0 +0 2742 0 +0 2869 0 +0 2997 0 +0 3126 0 +0 3256 0 +0 3387 0 +0 3517 0 +0 3648 0 +0 1360 1662 +0 1363 1659 +0 1367 1656 +0 1372 1652 +0 1379 1646 +0 1387 1638 +0 1399 1627 +0 1414 1612 +0 1433 1591 +0 1457 1561 +0 1487 1519 +0 1525 1455 +0 1572 1351 +0 1627 1162 +0 1692 629 +0 1766 0 +0 1849 0 +0 1941 0 +0 2041 0 +0 2147 0 +0 2259 0 +0 2375 0 +0 2495 0 +0 2618 0 +0 2743 0 +0 2869 0 +0 2997 0 +0 3126 0 +0 3256 0 +0 3387 0 +0 3517 0 +0 3648 0 +0 1366 1682 +0 1369 1679 +0 1373 1676 +0 1377 1672 +0 1384 1666 +0 1393 1659 +0 1404 1648 +0 1418 1634 +0 1437 1614 +0 1461 1586 +0 1492 1546 +0 1529 1486 +0 1575 1390 +0 1630 1220 +0 1694 795 +0 1768 0 +0 1851 0 +0 1943 0 +0 2042 0 +0 2148 0 +0 2260 0 +0 2376 0 +0 2495 0 +0 2618 0 +0 2743 0 +0 2870 0 +0 2998 0 +0 3127 0 +0 3256 0 +0 3387 0 +0 3517 0 +0 3649 0 +0 1373 1707 +0 1376 1705 +0 1380 1702 +0 1385 1698 +0 1391 1693 +0 1399 1686 +0 1411 1676 +0 1425 1662 +0 1444 1644 +0 1467 1618 +0 1497 1580 +0 1534 1525 +0 1580 1438 +0 1634 1287 +0 1698 950 +0 1771 0 +0 1854 0 +0 1945 0 +0 2044 0 +0 2149 0 +0 2261 0 +0 2377 0 +0 2496 0 +0 2619 0 +0 2743 0 +0 2870 0 +0 2998 0 +0 3127 0 +0 3256 0 +0 3387 0 +0 3517 0 +0 3649 0 +817 1383 1739 +796 1385 1737 +767 1389 1734 +725 1394 1731 +662 1400 1726 +560 1408 1719 +375 1419 1710 +0 1433 1698 +0 1452 1680 +0 1475 1656 +0 1504 1622 +0 1541 1572 +0 1586 1494 +0 1639 1364 +0 1702 1098 +0 1775 0 +0 1857 0 +0 1948 0 +0 2046 0 +0 2151 0 +0 2262 0 +0 2378 0 +0 2497 0 +0 2619 0 +0 2744 0 +0 2870 0 +0 2998 0 +0 3127 0 +0 3257 0 +0 3387 0 +0 3518 0 +0 3649 0 +1204 1395 1779 +1195 1398 1777 +1183 1401 1775 +1166 1406 1771 +1143 1412 1767 +1111 1420 1761 +1063 1431 1752 +990 1445 1741 +870 1462 1725 +635 1485 1704 +0 1514 1673 +0 1550 1628 +0 1594 1560 +0 1646 1450 +0 1709 1243 +0 1780 567 +0 1861 0 +0 1951 0 +0 2049 0 +0 2154 0 +0 2264 0 +0 2379 0 +0 2498 0 +0 2620 0 +0 2744 0 +0 2871 0 +0 2998 0 +0 3127 0 +0 3257 0 +0 3387 0 +0 3518 0 +0 3649 0 +1462 1411 1827 +1457 1414 1825 +1450 1417 1823 +1441 1422 1820 +1429 1428 1816 +1412 1436 1811 +1388 1446 1803 +1354 1459 1793 +1304 1476 1779 +1227 1498 1760 +1098 1526 1733 +836 1561 1694 +0 1604 1636 +0 1656 1544 +0 1717 1383 +0 1787 1003 +0 1867 0 +0 1956 0 +0 2053 0 +0 2157 0 +0 2266 0 +0 2381 0 +0 2499 0 +0 2621 0 +0 2745 0 +0 2871 0 +0 2999 0 +0 3128 0 +0 3257 0 +0 3387 0 +0 3518 0 +0 3649 0 +1670 1432 1884 +1667 1435 1883 +1663 1438 1881 +1657 1442 1878 +1649 1448 1875 +1639 1455 1870 +1624 1465 1863 +1604 1478 1854 +1576 1494 1842 +1536 1516 1826 +1475 1543 1802 +1378 1576 1769 +1206 1618 1720 +769 1668 1646 +0 1728 1522 +0 1797 1276 +0 1875 0 +0 1962 0 +0 2058 0 +0 2161 0 +0 2270 0 +0 2383 0 +0 2501 0 +0 2623 0 +0 2746 0 +0 2872 0 +0 3000 0 +0 3128 0 +0 3257 0 +0 3387 0 +0 3518 0 +0 3649 0 +1851 1458 1951 +1849 1461 1950 +1847 1464 1948 +1843 1468 1946 +1838 1473 1943 +1831 1480 1939 +1821 1490 1933 +1809 1502 1925 +1791 1517 1915 +1766 1538 1901 +1730 1563 1881 +1678 1596 1853 +1597 1636 1813 +1459 1684 1753 +1167 1741 1659 +0 1809 1491 +0 1885 1074 +0 1971 0 +0 2065 0 +0 2166 0 +0 2274 0 +0 2387 0 +0 2504 0 +0 2625 0 +0 2748 0 +0 2873 0 +0 3000 0 +0 3129 0 +0 3258 0 +0 3388 0 +0 3518 0 +0 3649 0 +2017 1491 2027 +2016 1494 2026 +2014 1496 2025 +2011 1500 2023 +2008 1505 2020 +2003 1512 2017 +1997 1520 2012 +1988 1532 2006 +1976 1547 1997 +1960 1566 1985 +1937 1590 1969 +1904 1620 1946 +1856 1658 1914 +1784 1704 1867 +1664 1759 1794 +1430 1824 1676 +367 1898 1445 +0 1982 454 +0 2074 0 +0 2173 0 +0 2279 0 +0 2391 0 +0 2507 0 +0 2627 0 +0 2750 0 +0 2875 0 +0 3002 0 +0 3130 0 +0 3259 0 +0 3388 0 +0 3519 0 +0 3649 0 +2173 1532 2113 +2172 1534 2112 +2171 1537 2111 +2169 1540 2109 +2166 1545 2107 +2163 1551 2104 +2158 1559 2100 +2152 1569 2095 +2144 1583 2088 +2133 1600 2078 +2117 1623 2065 +2096 1651 2047 +2065 1687 2021 +2021 1730 1984 +1953 1782 1929 +1844 1844 1844 +1639 1915 1698 +988 1996 1375 +0 2085 0 +0 2183 0 +0 2287 0 +0 2397 0 +0 2512 0 +0 2631 0 +0 2753 0 +0 2877 0 +0 3003 0 +0 3131 0 +0 3259 0 +0 3389 0 +0 3519 0 +0 3650 0 +2322 1581 2206 +2321 1583 2206 +2320 1585 2205 +2319 1588 2204 +2317 1593 2202 +2315 1598 2199 +2312 1605 2196 +2307 1615 2192 +2301 1627 2186 +2293 1643 2179 +2283 1663 2168 +2268 1690 2153 +2247 1722 2133 +2218 1763 2105 +2175 1811 2063 +2111 1870 2001 +2009 1937 1903 +1822 2014 1725 +1302 2100 1261 +0 2195 0 +0 2297 0 +0 2405 0 +0 2518 0 +0 2635 0 +0 2756 0 +0 2880 0 +0 3005 0 +0 3132 0 +0 3261 0 +0 3390 0 +0 3520 0 +0 3650 0 +2466 1640 2308 +2466 1641 2307 +2465 1643 2306 +2464 1646 2305 +2463 1650 2304 +2461 1655 2302 +2459 1661 2299 +2456 1669 2296 +2451 1680 2292 +2446 1694 2285 +2438 1713 2277 +2427 1736 2266 +2413 1766 2250 +2393 1803 2228 +2364 1848 2197 +2323 1902 2152 +2262 1965 2083 +2164 2038 1971 +1988 2120 1760 +1534 2211 1044 +0 2309 0 +0 2415 0 +0 2526 0 +0 2641 0 +0 2761 0 +0 2883 0 +0 3008 0 +0 3134 0 +0 3262 0 +0 3391 0 +0 3521 0 +0 3651 0 +2607 1708 2415 +2607 1709 2415 +2607 1711 2414 +2606 1713 2413 +2605 1716 2412 +2604 1721 2411 +2602 1726 2409 +2600 1733 2406 +2597 1743 2402 +2592 1755 2398 +2587 1771 2391 +2579 1792 2382 +2569 1818 2370 +2555 1851 2353 +2535 1892 2330 +2507 1941 2297 +2467 1999 2248 +2407 2067 2173 +2313 2145 2049 +2144 2231 1802 +1729 2326 267 +0 2428 0 +0 2536 0 +0 2649 0 +0 2767 0 +0 2888 0 +0 3011 0 +0 3137 0 +0 3264 0 +0 3393 0 +0 3522 0 +0 3652 0 +2746 1785 2528 +2746 1786 2528 +2745 1788 2527 +2745 1790 2526 +2744 1793 2526 +2743 1796 2524 +2742 1801 2523 +2740 1807 2521 +2738 1815 2518 +2735 1826 2514 +2731 1839 2509 +2726 1857 2502 +2718 1880 2493 +2708 1909 2480 +2694 1945 2463 +2674 1989 2438 +2647 2042 2403 +2608 2104 2351 +2549 2176 2271 +2457 2257 2136 +2294 2347 1853 +1903 2445 0 +0 2549 0 +0 2660 0 +0 2775 0 +0 2894 0 +0 3016 0 +0 3141 0 +0 3267 0 +0 3395 0 +0 3523 0 +0 3653 0 +2883 1872 2645 +2883 1873 2645 +2883 1874 2644 +2882 1876 2644 +2882 1878 2643 +2881 1881 2642 +2880 1885 2641 +2879 1890 2640 +2877 1897 2637 +2875 1905 2635 +2872 1917 2631 +2868 1932 2625 +2862 1952 2618 +2855 1976 2609 +2845 2008 2596 +2831 2046 2577 +2812 2093 2552 +2785 2149 2515 +2746 2215 2461 +2688 2290 2376 +2598 2374 2231 +2438 2467 1914 +2064 2567 0 +0 2674 0 +0 2786 0 +0 2902 0 +0 3022 0 +0 3145 0 +0 3271 0 +0 3397 0 +0 3525 0 +0 3655 0 +3019 1967 2766 +3019 1967 2765 +3018 1968 2765 +3018 1970 2765 +3018 1971 2764 +3017 1974 2763 +3017 1977 2763 +3016 1981 2761 +3014 1987 2760 +3013 1994 2758 +3011 2004 2755 +3008 2016 2751 +3004 2032 2745 +2998 2053 2738 +2991 2080 2728 +2981 2113 2715 +2967 2154 2696 +2948 2203 2669 +2921 2262 2631 +2883 2330 2575 +2826 2408 2487 +2736 2494 2334 +2580 2589 1984 +2216 2691 0 +0 2800 0 +0 2913 0 +0 3031 0 +0 3152 0 +0 3275 0 +0 3401 0 +0 3528 0 +0 3657 0 +3154 2069 2889 +3153 2069 2889 +3153 2070 2888 +3153 2071 2888 +3153 2072 2888 +3152 2074 2887 +3152 2077 2887 +3151 2080 2886 +3150 2085 2884 +3149 2091 2883 +3147 2098 2881 +3145 2109 2878 +3142 2122 2873 +3138 2139 2868 +3133 2161 2861 +3126 2189 2850 +3116 2224 2837 +3102 2266 2817 +3083 2318 2790 +3057 2379 2751 +3018 2449 2693 +2962 2529 2602 +2873 2617 2442 +2718 2714 2063 +2363 2818 0 +0 2927 0 +0 3042 0 +0 3160 0 +0 3282 0 +0 3406 0 +0 3532 0 +0 3659 0 +3288 2177 3014 +3288 2177 3014 +3287 2178 3014 +3287 2179 3014 +3287 2180 3013 +3287 2181 3013 +3286 2183 3012 +3286 2186 3012 +3285 2190 3011 +3284 2194 3010 +3283 2200 3008 +3281 2209 3006 +3279 2219 3003 +3276 2233 2998 +3272 2251 2993 +3267 2274 2985 +3260 2303 2975 +3250 2339 2961 +3236 2383 2941 +3217 2437 2914 +3191 2499 2874 +3153 2571 2815 +3097 2652 2721 +3009 2743 2556 +2855 2840 2152 +2506 2945 0 +0 3056 0 +0 3171 0 +0 3290 0 +0 3412 0 +0 3537 0 +0 3663 0 +3421 2290 3141 +3421 2291 3141 +3421 2291 3141 +3421 2292 3141 +3421 2293 3141 +3421 2294 3140 +3420 2295 3140 +3420 2297 3139 +3419 2300 3139 +3419 2304 3138 +3418 2309 3136 +3417 2315 3135 +3415 2324 3132 +3413 2335 3129 +3410 2349 3125 +3406 2368 3120 +3401 2392 3112 +3393 2421 3102 +3384 2459 3087 +3370 2504 3067 +3351 2558 3039 +3325 2622 2999 +3287 2696 2939 +3231 2778 2844 +3143 2869 2673 +2991 2968 2248 +2646 3074 0 +0 3185 0 +0 3301 0 +0 3421 0 +0 3543 0 +0 3668 0 +3554 2408 3269 +3554 2408 3269 +3554 2408 3269 +3554 2409 3269 +3554 2410 3269 +3554 2411 3269 +3554 2412 3268 +3553 2413 3268 +3553 2416 3268 +3553 2418 3267 +3552 2422 3266 +3551 2427 3265 +3550 2434 3263 +3548 2443 3261 +3546 2454 3257 +3543 2469 3253 +3539 2488 3248 +3534 2512 3240 +3527 2543 3229 +3517 2581 3215 +3503 2627 3195 +3485 2683 3167 +3458 2747 3126 +3421 2822 3065 +3365 2905 2968 +3277 2998 2794 +3126 3097 2352 +2784 3204 0 +0 3315 0 +0 3432 0 +0 3552 0 +0 3674 0 +3687 2529 3399 +3687 2529 3399 +3687 2529 3399 +3687 2530 3398 +3687 2530 3398 +3687 2531 3398 +3687 2532 3398 +3687 2533 3398 +3686 2535 3397 +3686 2537 3397 +3685 2540 3396 +3685 2544 3395 +3684 2549 3394 +3683 2556 3392 +3681 2565 3390 +3679 2576 3387 +3676 2591 3382 +3672 2611 3377 +3667 2636 3369 +3660 2667 3358 +3650 2706 3344 +3636 2753 3324 +3618 2809 3295 +3591 2874 3254 +3554 2950 3192 +3498 3034 3094 +3411 3127 2918 +3260 3227 2461 +2920 3334 0 +0 3446 0 +0 3563 0 +0 3683 0 +3820 2652 3529 +3820 2652 3529 +3820 2653 3528 +3820 2653 3528 +3820 2653 3528 +3820 2654 3528 +3820 2655 3528 +3820 2656 3528 +3819 2657 3528 +3819 2658 3527 +3819 2661 3527 +3818 2664 3526 +3817 2668 3525 +3817 2673 3524 +3815 2680 3522 +3814 2689 3519 +3812 2701 3516 +3809 2716 3512 +3805 2736 3506 +3799 2761 3499 +3792 2793 3488 +3782 2832 3473 +3769 2880 3453 +3750 2936 3424 +3724 3003 3383 +3687 3078 3321 +3631 3163 3222 +3544 3257 3044 +3394 3357 2575 +3056 3465 0 +0 3577 0 +0 3694 0 +3953 2778 3659 +3953 2778 3659 +3953 2778 3659 +3953 2778 3659 +3952 2779 3659 +3952 2779 3659 +3952 2780 3659 +3952 2780 3658 +3952 2781 3658 +3952 2783 3658 +3952 2784 3658 +3951 2787 3657 +3951 2790 3656 +3950 2794 3655 +3949 2799 3654 +3948 2806 3652 +3946 2815 3650 +3944 2827 3647 +3941 2843 3642 +3937 2863 3637 +3932 2888 3629 +3925 2920 3618 +3915 2960 3604 +3902 3008 3583 +3883 3065 3554 +3857 3132 3513 +3819 3208 3450 +3764 3293 3351 +3677 3387 3171 +3527 3488 2694 +3190 3596 0 +0 3708 0 +4085 2905 3790 +4085 2905 3790 +4085 2905 3790 +4085 2905 3790 +4085 2906 3790 +4085 2906 3790 +4085 2906 3790 +4085 2907 3789 +4085 2908 3789 +4084 2909 3789 +4084 2910 3789 +4084 2912 3788 +4084 2914 3788 +4083 2917 3787 +4082 2921 3786 +4082 2926 3785 +4080 2933 3783 +4079 2943 3781 +4077 2955 3778 +4074 2971 3773 +4070 2991 3768 +4064 3017 3760 +4057 3049 3749 +4047 3089 3734 +4034 3137 3714 +4015 3195 3685 +3989 3262 3643 +3952 3338 3581 +3896 3424 3481 +3810 3518 3299 +3660 3619 2815 +3324 3727 0 +4095 3033 3921 +4095 3034 3921 +4095 3034 3921 +4095 3034 3921 +4095 3034 3921 +4095 3034 3921 +4095 3034 3921 +4095 3035 3921 +4095 3035 3921 +4095 3036 3920 +4095 3037 3920 +4095 3038 3920 +4095 3040 3920 +4095 3042 3919 +4095 3046 3918 +4095 3050 3917 +4095 3055 3916 +4095 3062 3914 +4095 3072 3912 +4095 3084 3909 +4095 3100 3904 +4095 3120 3899 +4095 3146 3891 +4095 3178 3880 +4095 3218 3865 +4095 3267 3845 +4095 3325 3816 +4095 3392 3774 +4084 3469 3711 +4029 3555 3611 +3942 3649 3429 +3793 3751 2939 +4095 3163 4053 +4095 3163 4052 +4095 3163 4052 +4095 3163 4052 +4095 3163 4052 +4095 3163 4052 +4095 3164 4052 +4095 3164 4052 +4095 3164 4052 +4095 3165 4052 +4095 3166 4052 +4095 3167 4052 +4095 3168 4051 +4095 3170 4051 +4095 3172 4050 +4095 3175 4050 +4095 3179 4049 +4095 3185 4047 +4095 3192 4046 +4095 3201 4043 +4095 3213 4040 +4095 3229 4036 +4095 3250 4030 +4095 3276 4022 +4095 3308 4011 +4095 3349 3997 +4095 3397 3976 +4095 3455 3947 +4095 3523 3905 +4095 3600 3842 +4095 3686 3742 +4075 3780 3559 +0 1476 1739 +0 1478 1737 +0 1481 1735 +0 1485 1731 +0 1490 1726 +0 1497 1719 +0 1506 1710 +0 1518 1698 +0 1533 1681 +0 1552 1657 +0 1577 1622 +0 1609 1572 +0 1647 1494 +0 1695 1365 +0 1751 1099 +0 1817 0 +0 1892 0 +0 1976 0 +0 2069 0 +0 2170 0 +0 2277 0 +0 2389 0 +0 2506 0 +0 2626 0 +0 2749 0 +0 2874 0 +0 3001 0 +0 3129 0 +0 3258 0 +0 3388 0 +0 3518 0 +0 3649 0 +0 1477 1742 +0 1479 1740 +0 1482 1738 +0 1486 1734 +0 1491 1729 +0 1498 1723 +0 1507 1713 +0 1518 1701 +0 1533 1684 +0 1553 1660 +0 1578 1626 +0 1609 1576 +0 1648 1500 +0 1695 1371 +0 1751 1111 +0 1817 0 +0 1892 0 +0 1977 0 +0 2070 0 +0 2170 0 +0 2277 0 +0 2389 0 +0 2506 0 +0 2626 0 +0 2749 0 +0 2874 0 +0 3001 0 +0 3129 0 +0 3258 0 +0 3388 0 +0 3519 0 +0 3649 0 +0 1478 1746 +0 1480 1744 +0 1483 1742 +0 1487 1738 +0 1492 1733 +0 1499 1727 +0 1507 1718 +0 1519 1706 +0 1534 1689 +0 1554 1665 +0 1579 1631 +0 1610 1582 +0 1649 1506 +0 1696 1380 +0 1752 1127 +0 1818 0 +0 1893 0 +0 1977 0 +0 2070 0 +0 2170 0 +0 2277 0 +0 2389 0 +0 2506 0 +0 2626 0 +0 2749 0 +0 2874 0 +0 3001 0 +0 3129 0 +0 3258 0 +0 3388 0 +0 3519 0 +0 3649 0 +0 1479 1752 +0 1481 1750 +0 1484 1747 +0 1488 1744 +0 1493 1739 +0 1500 1732 +0 1509 1723 +0 1520 1711 +0 1535 1695 +0 1555 1671 +0 1580 1638 +0 1611 1590 +0 1650 1515 +0 1696 1392 +0 1753 1147 +0 1818 0 +0 1893 0 +0 1978 0 +0 2070 0 +0 2171 0 +0 2277 0 +0 2389 0 +0 2506 0 +0 2626 0 +0 2749 0 +0 2874 0 +0 3001 0 +0 3129 0 +0 3258 0 +0 3388 0 +0 3519 0 +0 3649 0 +0 1481 1759 +0 1483 1757 +0 1486 1754 +0 1490 1751 +0 1495 1746 +0 1502 1740 +0 1510 1731 +0 1522 1719 +0 1537 1703 +0 1556 1680 +0 1581 1647 +0 1612 1600 +0 1651 1527 +0 1698 1407 +0 1754 1173 +0 1819 122 +0 1894 0 +0 1978 0 +0 2071 0 +0 2171 0 +0 2278 0 +0 2390 0 +0 2506 0 +0 2626 0 +0 2749 0 +0 2874 0 +0 3001 0 +0 3129 0 +0 3258 0 +0 3388 0 +0 3519 0 +0 3649 0 +0 1483 1768 +0 1485 1766 +0 1488 1763 +0 1492 1760 +0 1497 1755 +0 1504 1749 +0 1513 1741 +0 1524 1729 +0 1539 1713 +0 1558 1691 +0 1583 1659 +0 1614 1612 +0 1652 1542 +0 1699 1427 +0 1755 1206 +0 1820 376 +0 1895 0 +0 1979 0 +0 2071 0 +0 2171 0 +0 2278 0 +0 2390 0 +0 2506 0 +0 2626 0 +0 2749 0 +0 2874 0 +0 3001 0 +0 3129 0 +0 3258 0 +0 3388 0 +0 3519 0 +0 3649 0 +0 1486 1780 +0 1488 1778 +0 1491 1776 +0 1495 1772 +0 1500 1768 +0 1507 1762 +0 1516 1753 +0 1527 1742 +0 1542 1726 +0 1561 1705 +0 1586 1674 +0 1616 1629 +0 1655 1562 +0 1701 1452 +0 1757 1246 +0 1822 581 +0 1896 0 +0 1980 0 +0 2072 0 +0 2172 0 +0 2279 0 +0 2390 0 +0 2507 0 +0 2627 0 +0 2750 0 +0 2875 0 +0 3001 0 +0 3129 0 +0 3258 0 +0 3388 0 +0 3519 0 +0 3649 0 +0 1490 1795 +0 1493 1794 +0 1495 1791 +0 1499 1788 +0 1504 1784 +0 1511 1778 +0 1519 1770 +0 1531 1759 +0 1546 1744 +0 1565 1723 +0 1589 1694 +0 1620 1651 +0 1657 1587 +0 1704 1484 +0 1759 1294 +0 1824 762 +0 1898 0 +0 1981 0 +0 2073 0 +0 2173 0 +0 2279 0 +0 2391 0 +0 2507 0 +0 2627 0 +0 2750 0 +0 2875 0 +0 3001 0 +0 3129 0 +0 3259 0 +0 3388 0 +0 3519 0 +0 3649 0 +0 1496 1815 +0 1498 1814 +0 1501 1811 +0 1505 1808 +0 1510 1804 +0 1516 1799 +0 1525 1791 +0 1536 1781 +0 1551 1766 +0 1569 1746 +0 1593 1718 +0 1624 1678 +0 1661 1618 +0 1707 1522 +0 1762 1352 +0 1826 927 +0 1900 0 +0 1983 0 +0 2075 0 +0 2174 0 +0 2280 0 +0 2392 0 +0 2508 0 +0 2628 0 +0 2750 0 +0 2875 0 +0 3002 0 +0 3130 0 +0 3259 0 +0 3388 0 +0 3519 0 +0 3649 0 +0 1503 1841 +0 1505 1839 +0 1508 1837 +0 1512 1834 +0 1517 1830 +0 1523 1825 +0 1532 1818 +0 1543 1808 +0 1557 1795 +0 1576 1776 +0 1599 1750 +0 1629 1712 +0 1666 1657 +0 1712 1570 +0 1766 1419 +0 1830 1082 +0 1903 0 +0 1986 0 +0 2077 0 +0 2176 0 +0 2282 0 +0 2393 0 +0 2509 0 +0 2628 0 +0 2751 0 +0 2875 0 +0 3002 0 +0 3130 0 +0 3259 0 +0 3388 0 +0 3519 0 +0 3650 0 +964 1513 1873 +949 1515 1871 +928 1518 1869 +899 1521 1867 +857 1526 1863 +794 1532 1858 +692 1541 1851 +507 1551 1842 +0 1566 1830 +0 1584 1813 +0 1607 1788 +0 1637 1754 +0 1673 1704 +0 1718 1626 +0 1771 1496 +0 1835 1231 +0 1907 0 +0 1989 0 +0 2080 0 +0 2178 0 +0 2283 0 +0 2394 0 +0 2510 0 +0 2629 0 +0 2751 0 +0 2876 0 +0 3002 0 +0 3130 0 +0 3259 0 +0 3389 0 +0 3519 0 +0 3650 0 +1342 1525 1912 +1336 1527 1911 +1327 1530 1909 +1315 1533 1907 +1299 1538 1903 +1276 1544 1899 +1243 1552 1893 +1195 1563 1884 +1123 1577 1873 +1003 1595 1857 +767 1617 1836 +0 1646 1805 +0 1682 1760 +0 1726 1692 +0 1779 1582 +0 1841 1375 +0 1912 699 +0 1994 0 +0 2083 0 +0 2181 0 +0 2286 0 +0 2396 0 +0 2511 0 +0 2630 0 +0 2752 0 +0 2877 0 +0 3003 0 +0 3130 0 +0 3259 0 +0 3389 0 +0 3519 0 +0 3650 0 +1598 1542 1960 +1594 1543 1959 +1589 1546 1957 +1582 1549 1955 +1573 1554 1952 +1561 1560 1948 +1544 1568 1943 +1520 1578 1935 +1486 1591 1925 +1436 1608 1911 +1359 1631 1892 +1230 1659 1865 +968 1693 1826 +0 1736 1768 +0 1788 1676 +0 1849 1516 +0 1919 1135 +0 1999 0 +0 2088 0 +0 2185 0 +0 2289 0 +0 2398 0 +0 2513 0 +0 2632 0 +0 2753 0 +0 2877 0 +0 3003 0 +0 3131 0 +0 3260 0 +0 3389 0 +0 3519 0 +0 3650 0 +1804 1562 2017 +1802 1564 2016 +1799 1567 2015 +1795 1570 2013 +1789 1574 2010 +1781 1580 2007 +1771 1587 2002 +1756 1597 1995 +1737 1610 1987 +1708 1626 1974 +1668 1648 1958 +1607 1675 1934 +1511 1708 1901 +1338 1750 1852 +901 1800 1778 +0 1860 1654 +0 1929 1408 +0 2007 0 +0 2095 0 +0 2190 0 +0 2293 0 +0 2402 0 +0 2515 0 +0 2633 0 +0 2755 0 +0 2878 0 +0 3004 0 +0 3132 0 +0 3260 0 +0 3389 0 +0 3520 0 +0 3650 0 +1985 1589 2084 +1983 1591 2083 +1981 1593 2082 +1979 1596 2080 +1975 1600 2078 +1970 1605 2075 +1963 1612 2071 +1953 1622 2065 +1941 1634 2058 +1923 1650 2047 +1898 1670 2033 +1862 1695 2013 +1810 1728 1985 +1729 1768 1945 +1591 1816 1886 +1299 1874 1791 +0 1941 1623 +0 2017 1207 +0 2103 0 +0 2197 0 +0 2298 0 +0 2406 0 +0 2519 0 +0 2636 0 +0 2757 0 +0 2880 0 +0 3005 0 +0 3132 0 +0 3261 0 +0 3390 0 +0 3520 0 +0 3650 0 +2150 1622 2160 +2149 1623 2159 +2148 1626 2158 +2146 1628 2157 +2143 1632 2155 +2140 1637 2152 +2135 1644 2149 +2129 1653 2144 +2120 1664 2138 +2108 1679 2129 +2092 1698 2117 +2069 1722 2101 +2036 1752 2078 +1989 1790 2046 +1916 1836 1999 +1796 1892 1927 +1562 1956 1808 +499 2030 1577 +0 2114 586 +0 2206 0 +0 2305 0 +0 2412 0 +0 2523 0 +0 2639 0 +0 2759 0 +0 2882 0 +0 3007 0 +0 3134 0 +0 3262 0 +0 3391 0 +0 3520 0 +0 3651 0 +2306 1663 2246 +2305 1664 2245 +2304 1666 2244 +2303 1669 2243 +2301 1672 2241 +2298 1677 2239 +2295 1683 2236 +2291 1691 2232 +2284 1701 2227 +2276 1715 2220 +2265 1732 2210 +2249 1755 2197 +2228 1783 2179 +2197 1819 2153 +2153 1862 2116 +2085 1915 2061 +1976 1976 1976 +1771 2047 1830 +1120 2128 1507 +0 2217 0 +0 2315 0 +0 2419 0 +0 2529 0 +0 2644 0 +0 2763 0 +0 2885 0 +0 3009 0 +0 3135 0 +0 3263 0 +0 3392 0 +0 3521 0 +0 3651 0 +2455 1712 2339 +2454 1713 2339 +2453 1715 2338 +2452 1717 2337 +2451 1721 2336 +2449 1725 2334 +2447 1730 2332 +2444 1737 2328 +2439 1747 2324 +2434 1759 2318 +2426 1775 2311 +2415 1796 2300 +2400 1822 2285 +2379 1854 2265 +2350 1895 2237 +2307 1944 2195 +2243 2002 2134 +2141 2069 2035 +1954 2146 1857 +1434 2233 1394 +0 2327 0 +0 2429 0 +0 2537 0 +0 2650 0 +0 2767 0 +0 2888 0 +0 3012 0 +0 3137 0 +0 3264 0 +0 3393 0 +0 3522 0 +0 3652 0 +2599 1771 2440 +2598 1772 2440 +2598 1773 2439 +2597 1775 2438 +2596 1778 2437 +2595 1782 2436 +2593 1787 2434 +2591 1793 2432 +2588 1801 2428 +2584 1812 2424 +2578 1827 2418 +2570 1845 2409 +2560 1868 2398 +2545 1898 2382 +2525 1935 2360 +2496 1980 2329 +2455 2034 2284 +2394 2097 2215 +2296 2170 2104 +2120 2252 1892 +1666 2343 1176 +0 2441 0 +0 2547 0 +0 2658 0 +0 2773 0 +0 2893 0 +0 3015 0 +0 3140 0 +0 3266 0 +0 3394 0 +0 3523 0 +0 3653 0 +2740 1839 2548 +2740 1840 2547 +2739 1841 2547 +2739 1843 2546 +2738 1845 2545 +2737 1848 2544 +2736 1853 2543 +2734 1858 2541 +2732 1865 2538 +2729 1875 2535 +2725 1887 2530 +2719 1903 2523 +2711 1924 2514 +2701 1950 2502 +2687 1983 2486 +2667 2024 2462 +2639 2073 2429 +2599 2132 2380 +2539 2199 2305 +2445 2277 2181 +2277 2363 1934 +1861 2458 400 +0 2560 0 +0 2668 0 +0 2781 0 +0 2899 0 +0 3020 0 +0 3144 0 +0 3269 0 +0 3396 0 +0 3525 0 +0 3654 0 +2878 1917 2660 +2878 1917 2660 +2878 1919 2660 +2878 1920 2659 +2877 1922 2659 +2876 1925 2658 +2875 1928 2657 +2874 1933 2655 +2872 1939 2653 +2870 1947 2650 +2867 1958 2646 +2863 1972 2641 +2858 1989 2635 +2850 2012 2625 +2840 2041 2613 +2826 2077 2595 +2807 2121 2570 +2779 2174 2535 +2740 2236 2483 +2681 2308 2403 +2589 2389 2268 +2426 2479 1986 +2035 2577 0 +0 2682 0 +0 2792 0 +0 2907 0 +0 3026 0 +0 3148 0 +0 3273 0 +0 3399 0 +0 3527 0 +0 3656 0 +3015 2003 2777 +3015 2004 2777 +3015 2005 2777 +3015 2006 2776 +3014 2008 2776 +3014 2010 2775 +3013 2013 2774 +3012 2017 2773 +3011 2022 2772 +3009 2029 2770 +3007 2038 2767 +3004 2049 2763 +3000 2064 2758 +2995 2084 2751 +2987 2108 2741 +2977 2140 2728 +2963 2178 2709 +2944 2225 2684 +2917 2281 2647 +2878 2347 2593 +2821 2422 2508 +2730 2506 2363 +2570 2599 2046 +2196 2699 0 +0 2806 0 +0 2918 0 +0 3034 0 +0 3155 0 +0 3278 0 +0 3403 0 +0 3529 0 +0 3658 0 +3151 2098 2898 +3151 2099 2898 +3151 2099 2897 +3150 2100 2897 +3150 2102 2897 +3150 2104 2896 +3149 2106 2896 +3149 2109 2895 +3148 2113 2893 +3147 2119 2892 +3145 2126 2890 +3143 2136 2887 +3140 2148 2883 +3136 2164 2877 +3130 2185 2870 +3123 2212 2860 +3113 2245 2847 +3099 2286 2828 +3080 2335 2801 +3053 2394 2763 +3015 2462 2707 +2958 2540 2619 +2868 2626 2466 +2712 2721 2116 +2349 2823 0 +0 2932 0 +0 3045 0 +0 3163 0 +0 3284 0 +0 3407 0 +0 3533 0 +0 3660 0 +3286 2200 3021 +3286 2201 3021 +3286 2201 3021 +3285 2202 3021 +3285 2203 3020 +3285 2205 3020 +3284 2206 3019 +3284 2209 3019 +3283 2212 3018 +3282 2217 3016 +3281 2223 3015 +3280 2231 3013 +3277 2241 3010 +3274 2254 3006 +3270 2271 3000 +3265 2293 2993 +3258 2321 2983 +3248 2356 2969 +3234 2398 2949 +3215 2450 2922 +3189 2511 2883 +3151 2581 2825 +3094 2661 2734 +3005 2749 2574 +2850 2846 2196 +2495 2950 0 +0 3059 0 +0 3174 0 +0 3292 0 +0 3414 0 +0 3538 0 +0 3664 0 +3420 2309 3146 +3420 2309 3146 +3420 2309 3146 +3420 2310 3146 +3419 2311 3146 +3419 2312 3145 +3419 2313 3145 +3418 2315 3145 +3418 2318 3144 +3417 2322 3143 +3416 2326 3142 +3415 2333 3140 +3414 2341 3138 +3411 2351 3135 +3408 2365 3131 +3404 2383 3125 +3399 2406 3117 +3392 2435 3107 +3382 2471 3093 +3368 2516 3074 +3350 2569 3046 +3323 2631 3006 +3285 2703 2947 +3229 2785 2853 +3141 2875 2688 +2988 2973 2284 +2638 3077 0 +0 3188 0 +0 3303 0 +0 3422 0 +0 3544 0 +0 3669 0 +3553 2422 3273 +3553 2422 3273 +3553 2423 3273 +3553 2423 3273 +3553 2424 3273 +3553 2425 3273 +3553 2426 3272 +3552 2427 3272 +3552 2430 3271 +3552 2432 3271 +3551 2436 3270 +3550 2441 3269 +3549 2447 3267 +3547 2456 3265 +3545 2467 3261 +3542 2481 3257 +3538 2500 3252 +3533 2524 3244 +3525 2554 3234 +3516 2591 3219 +3502 2636 3200 +3483 2690 3172 +3457 2754 3131 +3419 2828 3071 +3363 2910 2976 +3275 3002 2805 +3123 3100 2380 +2778 3206 0 +0 3317 0 +0 3433 0 +0 3553 0 +0 3675 0 +3687 2540 3402 +3687 2540 3402 +3686 2540 3401 +3686 2541 3401 +3686 2541 3401 +3686 2542 3401 +3686 2543 3401 +3686 2544 3401 +3686 2545 3400 +3685 2548 3400 +3685 2550 3399 +3684 2554 3398 +3683 2559 3397 +3682 2566 3395 +3680 2575 3393 +3678 2586 3390 +3675 2601 3385 +3671 2620 3380 +3666 2644 3372 +3659 2675 3362 +3649 2713 3347 +3635 2759 3327 +3617 2815 3299 +3590 2880 3258 +3553 2954 3197 +3497 3038 3100 +3410 3130 2926 +3258 3229 2484 +2916 3336 0 +0 3448 0 +0 3564 0 +0 3684 0 +3819 2661 3531 +3819 2661 3531 +3819 2661 3531 +3819 2661 3531 +3819 2662 3531 +3819 2662 3530 +3819 2663 3530 +3819 2664 3530 +3819 2665 3530 +3818 2667 3529 +3818 2669 3529 +3818 2672 3528 +3817 2676 3527 +3816 2681 3526 +3815 2688 3524 +3813 2697 3522 +3811 2708 3519 +3808 2723 3514 +3804 2743 3509 +3799 2768 3501 +3792 2799 3490 +3782 2838 3476 +3768 2885 3456 +3750 2941 3427 +3723 3007 3386 +3686 3082 3325 +3630 3166 3227 +3543 3259 3050 +3392 3359 2593 +3052 3466 0 +0 3578 0 +0 3695 0 +3952 2784 3661 +3952 2784 3661 +3952 2785 3661 +3952 2785 3661 +3952 2785 3661 +3952 2785 3660 +3952 2786 3660 +3952 2787 3660 +3952 2788 3660 +3951 2789 3660 +3951 2791 3659 +3951 2793 3659 +3950 2796 3658 +3950 2800 3657 +3949 2805 3656 +3947 2812 3654 +3946 2821 3652 +3944 2833 3648 +3941 2848 3644 +3937 2868 3638 +3932 2893 3631 +3924 2925 3620 +3915 2964 3605 +3901 3012 3585 +3882 3068 3556 +3856 3135 3515 +3819 3211 3453 +3763 3295 3354 +3676 3389 3176 +3526 3489 2707 +3188 3597 0 +0 3709 0 +4085 2910 3791 +4085 2910 3791 +4085 2910 3791 +4085 2910 3791 +4085 2911 3791 +4085 2911 3791 +4085 2911 3791 +4084 2912 3791 +4084 2912 3791 +4084 2913 3790 +4084 2915 3790 +4084 2916 3790 +4083 2919 3789 +4083 2922 3788 +4082 2926 3787 +4081 2931 3786 +4080 2938 3784 +4078 2947 3782 +4076 2959 3779 +4073 2975 3775 +4069 2995 3769 +4064 3020 3761 +4057 3052 3750 +4047 3092 3736 +4034 3140 3715 +4015 3197 3686 +3989 3264 3645 +3951 3340 3583 +3896 3425 3483 +3809 3519 3303 +3659 3620 2826 +3322 3728 0 +4095 3037 3922 +4095 3037 3922 +4095 3037 3922 +4095 3037 3922 +4095 3038 3922 +4095 3038 3922 +4095 3038 3922 +4095 3039 3922 +4095 3039 3922 +4095 3040 3921 +4095 3041 3921 +4095 3042 3921 +4095 3044 3920 +4095 3046 3920 +4095 3049 3919 +4095 3053 3918 +4095 3059 3917 +4095 3066 3915 +4095 3075 3913 +4095 3087 3910 +4095 3103 3905 +4095 3123 3900 +4095 3149 3892 +4095 3181 3881 +4095 3221 3866 +4095 3269 3846 +4095 3327 3817 +4095 3394 3775 +4084 3470 3713 +4029 3556 3613 +3942 3650 3432 +3792 3751 2947 +4095 3166 4053 +4095 3166 4053 +4095 3166 4053 +4095 3166 4053 +4095 3166 4053 +4095 3166 4053 +4095 3166 4053 +4095 3167 4053 +4095 3167 4053 +4095 3168 4053 +4095 3168 4053 +4095 3169 4052 +4095 3171 4052 +4095 3172 4052 +4095 3175 4051 +4095 3178 4050 +4095 3182 4049 +4095 3187 4048 +4095 3194 4046 +4095 3204 4044 +4095 3216 4041 +4095 3232 4037 +4095 3252 4031 +4095 3278 4023 +4095 3310 4012 +4095 3350 3997 +4095 3399 3977 +4095 3457 3948 +4095 3524 3906 +4095 3601 3843 +4095 3687 3743 +4074 3781 3561 +0 1606 1871 +0 1607 1869 +0 1610 1867 +0 1612 1864 +0 1616 1861 +0 1622 1856 +0 1628 1849 +0 1637 1840 +0 1649 1827 +0 1664 1810 +0 1684 1786 +0 1709 1751 +0 1740 1701 +0 1779 1623 +0 1826 1491 +0 1883 1222 +0 1949 0 +0 2024 0 +0 2108 0 +0 2201 0 +0 2302 0 +0 2409 0 +0 2521 0 +0 2638 0 +0 2758 0 +0 2881 0 +0 3006 0 +0 3133 0 +0 3261 0 +0 3390 0 +0 3520 0 +0 3651 0 +0 1606 1873 +0 1608 1871 +0 1610 1869 +0 1613 1867 +0 1617 1863 +0 1622 1858 +0 1629 1851 +0 1638 1842 +0 1650 1830 +0 1665 1813 +0 1684 1789 +0 1709 1754 +0 1741 1704 +0 1779 1626 +0 1827 1497 +0 1883 1231 +0 1949 0 +0 2024 0 +0 2109 0 +0 2202 0 +0 2302 0 +0 2409 0 +0 2521 0 +0 2638 0 +0 2758 0 +0 2881 0 +0 3006 0 +0 3133 0 +0 3261 0 +0 3390 0 +0 3520 0 +0 3651 0 +0 1607 1876 +0 1609 1874 +0 1611 1872 +0 1614 1870 +0 1618 1866 +0 1623 1861 +0 1630 1855 +0 1639 1846 +0 1650 1833 +0 1666 1816 +0 1685 1792 +0 1710 1758 +0 1741 1708 +0 1780 1632 +0 1827 1503 +0 1883 1243 +0 1949 0 +0 2024 0 +0 2109 0 +0 2202 0 +0 2302 0 +0 2409 0 +0 2521 0 +0 2638 0 +0 2758 0 +0 2881 0 +0 3006 0 +0 3133 0 +0 3261 0 +0 3390 0 +0 3520 0 +0 3651 0 +0 1608 1880 +0 1610 1878 +0 1612 1876 +0 1615 1874 +0 1619 1870 +0 1624 1865 +0 1631 1859 +0 1640 1850 +0 1651 1838 +0 1666 1821 +0 1686 1797 +0 1711 1763 +0 1742 1714 +0 1781 1638 +0 1828 1512 +0 1884 1259 +0 1950 0 +0 2025 0 +0 2109 0 +0 2202 0 +0 2302 0 +0 2409 0 +0 2521 0 +0 2638 0 +0 2758 0 +0 2881 0 +0 3006 0 +0 3133 0 +0 3261 0 +0 3390 0 +0 3520 0 +0 3651 0 +0 1609 1885 +0 1611 1884 +0 1613 1882 +0 1616 1879 +0 1620 1876 +0 1625 1871 +0 1632 1864 +0 1641 1855 +0 1652 1843 +0 1668 1827 +0 1687 1803 +0 1712 1770 +0 1743 1722 +0 1782 1647 +0 1829 1524 +0 1885 1280 +0 1950 0 +0 2025 0 +0 2110 0 +0 2202 0 +0 2303 0 +0 2409 0 +0 2522 0 +0 2638 0 +0 2758 0 +0 2881 0 +0 3006 0 +0 3133 0 +0 3261 0 +0 3390 0 +0 3520 0 +0 3651 0 +0 1611 1892 +0 1613 1891 +0 1615 1889 +0 1618 1886 +0 1622 1883 +0 1627 1878 +0 1634 1872 +0 1642 1863 +0 1654 1851 +0 1669 1835 +0 1689 1812 +0 1713 1779 +0 1744 1732 +0 1783 1659 +0 1830 1540 +0 1886 1305 +0 1951 254 +0 2026 0 +0 2110 0 +0 2203 0 +0 2303 0 +0 2410 0 +0 2522 0 +0 2638 0 +0 2758 0 +0 2881 0 +0 3006 0 +0 3133 0 +0 3261 0 +0 3390 0 +0 3520 0 +0 3651 0 +0 1614 1901 +0 1615 1900 +0 1617 1898 +0 1620 1896 +0 1624 1892 +0 1629 1887 +0 1636 1881 +0 1645 1873 +0 1656 1861 +0 1671 1845 +0 1691 1823 +0 1715 1791 +0 1746 1745 +0 1784 1674 +0 1831 1559 +0 1887 1338 +0 1952 508 +0 2027 0 +0 2111 0 +0 2203 0 +0 2304 0 +0 2410 0 +0 2522 0 +0 2639 0 +0 2759 0 +0 2881 0 +0 3007 0 +0 3133 0 +0 3261 0 +0 3390 0 +0 3520 0 +0 3651 0 +0 1617 1913 +0 1618 1912 +0 1620 1910 +0 1623 1908 +0 1627 1904 +0 1632 1900 +0 1639 1894 +0 1648 1885 +0 1659 1874 +0 1674 1859 +0 1693 1837 +0 1718 1806 +0 1748 1761 +0 1787 1694 +0 1833 1584 +0 1889 1378 +0 1954 713 +0 2028 0 +0 2112 0 +0 2204 0 +0 2304 0 +0 2411 0 +0 2522 0 +0 2639 0 +0 2759 0 +0 2882 0 +0 3007 0 +0 3133 0 +0 3261 0 +0 3391 0 +0 3520 0 +0 3651 0 +0 1621 1929 +0 1622 1928 +0 1625 1926 +0 1627 1923 +0 1631 1920 +0 1636 1916 +0 1643 1910 +0 1652 1902 +0 1663 1891 +0 1678 1876 +0 1697 1855 +0 1721 1826 +0 1752 1783 +0 1790 1719 +0 1836 1616 +0 1891 1426 +0 1956 894 +0 2030 0 +0 2113 0 +0 2206 0 +0 2305 0 +0 2411 0 +0 2523 0 +0 2639 0 +0 2759 0 +0 2882 0 +0 3007 0 +0 3134 0 +0 3262 0 +0 3391 0 +0 3520 0 +0 3651 0 +0 1626 1949 +0 1628 1948 +0 1630 1946 +0 1633 1944 +0 1637 1940 +0 1642 1936 +0 1648 1931 +0 1657 1923 +0 1668 1913 +0 1683 1898 +0 1701 1878 +0 1726 1851 +0 1756 1810 +0 1793 1750 +0 1839 1655 +0 1894 1484 +0 1958 1059 +0 2032 0 +0 2115 0 +0 2207 0 +0 2306 0 +0 2412 0 +0 2524 0 +0 2640 0 +0 2760 0 +0 2882 0 +0 3007 0 +0 3134 0 +0 3262 0 +0 3391 0 +0 3520 0 +0 3651 0 +0 1634 1974 +0 1635 1973 +0 1637 1971 +0 1640 1969 +0 1644 1966 +0 1649 1962 +0 1655 1957 +0 1664 1950 +0 1675 1940 +0 1689 1927 +0 1708 1908 +0 1731 1882 +0 1761 1844 +0 1798 1789 +0 1844 1702 +0 1898 1552 +0 1962 1214 +0 2035 0 +0 2118 0 +0 2209 0 +0 2308 0 +0 2414 0 +0 2525 0 +0 2641 0 +0 2760 0 +0 2883 0 +0 3008 0 +0 3134 0 +0 3262 0 +0 3391 0 +0 3521 0 +0 3651 0 +1107 1643 2006 +1096 1645 2005 +1081 1647 2003 +1061 1650 2001 +1031 1653 1999 +989 1658 1995 +926 1664 1990 +824 1673 1983 +639 1684 1974 +132 1698 1962 +0 1716 1945 +0 1739 1921 +0 1769 1886 +0 1805 1836 +0 1850 1758 +0 1904 1628 +0 1967 1363 +0 2039 0 +0 2121 0 +0 2212 0 +0 2310 0 +0 2415 0 +0 2526 0 +0 2642 0 +0 2761 0 +0 2883 0 +0 3008 0 +0 3134 0 +0 3262 0 +0 3391 0 +0 3521 0 +0 3651 0 +1479 1656 2045 +1474 1657 2044 +1468 1659 2043 +1459 1662 2041 +1447 1666 2039 +1431 1670 2035 +1408 1676 2031 +1375 1684 2025 +1327 1695 2016 +1255 1709 2005 +1135 1727 1989 +899 1749 1968 +0 1778 1937 +0 1814 1892 +0 1858 1824 +0 1911 1714 +0 1973 1507 +0 2045 831 +0 2126 0 +0 2215 0 +0 2313 0 +0 2418 0 +0 2528 0 +0 2643 0 +0 2762 0 +0 2884 0 +0 3009 0 +0 3135 0 +0 3263 0 +0 3391 0 +0 3521 0 +0 3651 0 +1732 1672 2093 +1730 1674 2092 +1726 1676 2091 +1721 1678 2089 +1715 1681 2087 +1706 1686 2084 +1693 1692 2080 +1676 1700 2075 +1652 1710 2067 +1618 1723 2057 +1568 1741 2043 +1491 1763 2024 +1362 1791 1997 +1100 1826 1958 +0 1868 1900 +0 1920 1808 +0 1981 1648 +0 2052 1267 +0 2132 0 +0 2220 0 +0 2317 0 +0 2421 0 +0 2530 0 +0 2645 0 +0 2764 0 +0 2885 0 +0 3009 0 +0 3136 0 +0 3263 0 +0 3392 0 +0 3521 0 +0 3651 0 +1938 1693 2150 +1936 1694 2150 +1934 1696 2148 +1931 1699 2147 +1927 1702 2145 +1921 1706 2142 +1913 1712 2139 +1903 1719 2134 +1889 1729 2127 +1869 1742 2119 +1840 1759 2106 +1800 1780 2090 +1739 1807 2066 +1643 1841 2033 +1470 1882 1984 +1033 1932 1910 +0 1992 1786 +0 2061 1540 +0 2139 54 +0 2227 0 +0 2322 0 +0 2425 0 +0 2534 0 +0 2648 0 +0 2766 0 +0 2887 0 +0 3011 0 +0 3136 0 +0 3264 0 +0 3392 0 +0 3522 0 +0 3652 0 +2118 1720 2217 +2117 1721 2216 +2116 1723 2215 +2113 1725 2214 +2111 1728 2212 +2107 1732 2210 +2102 1737 2207 +2095 1744 2203 +2086 1754 2197 +2073 1766 2190 +2055 1782 2179 +2030 1802 2165 +1994 1828 2145 +1942 1860 2118 +1861 1900 2077 +1723 1948 2018 +1431 2006 1923 +0 2073 1755 +0 2149 1339 +0 2235 0 +0 2329 0 +0 2430 0 +0 2538 0 +0 2651 0 +0 2768 0 +0 2889 0 +0 3012 0 +0 3138 0 +0 3265 0 +0 3393 0 +0 3522 0 +0 3652 0 +2283 1753 2293 +2282 1754 2292 +2281 1756 2292 +2280 1758 2290 +2278 1761 2289 +2275 1764 2287 +2272 1769 2285 +2267 1776 2281 +2261 1785 2276 +2252 1796 2270 +2240 1811 2261 +2224 1830 2249 +2201 1854 2233 +2168 1884 2210 +2121 1922 2178 +2048 1968 2131 +1928 2024 2059 +1694 2088 1940 +631 2163 1709 +0 2246 718 +0 2338 0 +0 2437 0 +0 2544 0 +0 2655 0 +0 2772 0 +0 2891 0 +0 3014 0 +0 3139 0 +0 3266 0 +0 3394 0 +0 3523 0 +0 3653 0 +2439 1794 2378 +2438 1795 2378 +2437 1796 2377 +2436 1798 2376 +2435 1801 2375 +2433 1804 2373 +2430 1809 2371 +2427 1815 2368 +2423 1823 2364 +2417 1833 2359 +2408 1847 2352 +2397 1864 2342 +2382 1887 2329 +2360 1915 2311 +2329 1951 2285 +2285 1994 2248 +2217 2047 2193 +2108 2108 2108 +1903 2180 1962 +1252 2260 1639 +0 2350 0 +0 2447 0 +0 2551 0 +0 2661 0 +0 2776 0 +0 2895 0 +0 3017 0 +0 3141 0 +0 3267 0 +0 3395 0 +0 3524 0 +0 3653 0 +2587 1843 2472 +2587 1844 2471 +2586 1845 2471 +2585 1847 2470 +2584 1850 2469 +2583 1853 2468 +2581 1857 2466 +2579 1862 2464 +2576 1869 2460 +2571 1879 2456 +2566 1891 2451 +2558 1907 2443 +2547 1928 2432 +2532 1954 2418 +2511 1986 2397 +2482 2027 2369 +2439 2076 2327 +2375 2134 2266 +2273 2201 2167 +2086 2279 1990 +1566 2365 1526 +0 2459 0 +0 2561 0 +0 2669 0 +0 2782 0 +0 2899 0 +0 3020 0 +0 3144 0 +0 3269 0 +0 3396 0 +0 3525 0 +0 3654 0 +2731 1902 2573 +2731 1903 2572 +2731 1904 2572 +2730 1906 2571 +2729 1908 2570 +2728 1910 2569 +2727 1914 2568 +2725 1919 2566 +2723 1925 2564 +2720 1933 2560 +2716 1944 2556 +2710 1959 2550 +2702 1977 2541 +2692 2000 2530 +2677 2030 2514 +2657 2067 2492 +2629 2112 2461 +2588 2166 2416 +2526 2229 2347 +2428 2302 2236 +2252 2384 2024 +1798 2475 1309 +0 2574 0 +0 2679 0 +0 2790 0 +0 2906 0 +0 3025 0 +0 3147 0 +0 3272 0 +0 3398 0 +0 3526 0 +0 3655 0 +2872 1970 2680 +2872 1971 2680 +2872 1972 2679 +2871 1973 2679 +2871 1975 2678 +2870 1977 2677 +2869 1981 2676 +2868 1985 2675 +2866 1990 2673 +2864 1998 2670 +2861 2007 2667 +2857 2019 2662 +2851 2036 2655 +2843 2056 2646 +2833 2083 2634 +2819 2115 2618 +2799 2156 2594 +2771 2205 2561 +2731 2264 2512 +2672 2332 2437 +2577 2409 2314 +2409 2495 2066 +1993 2590 532 +0 2692 0 +0 2800 0 +0 2914 0 +0 3031 0 +0 3152 0 +0 3276 0 +0 3401 0 +0 3528 0 +0 3657 0 +3011 2048 2793 +3011 2049 2792 +3010 2050 2792 +3010 2051 2792 +3010 2052 2791 +3009 2054 2791 +3008 2057 2790 +3007 2060 2789 +3006 2065 2787 +3005 2071 2785 +3002 2079 2782 +2999 2090 2779 +2995 2104 2774 +2990 2122 2767 +2982 2144 2757 +2972 2173 2745 +2958 2209 2727 +2939 2253 2702 +2911 2306 2667 +2872 2368 2616 +2813 2440 2536 +2721 2521 2400 +2558 2611 2118 +2167 2709 0 +0 2814 0 +0 2924 0 +0 3039 0 +0 3158 0 +0 3280 0 +0 3405 0 +0 3531 0 +0 3659 0 +3148 2135 2910 +3147 2135 2909 +3147 2136 2909 +3147 2137 2909 +3147 2138 2909 +3146 2140 2908 +3146 2142 2907 +3145 2145 2907 +3144 2149 2905 +3143 2154 2904 +3141 2161 2902 +3139 2170 2899 +3136 2181 2895 +3132 2196 2890 +3127 2216 2883 +3119 2241 2873 +3109 2272 2860 +3095 2310 2842 +3076 2357 2816 +3049 2413 2779 +3010 2479 2725 +2953 2554 2640 +2862 2638 2495 +2703 2731 2178 +2328 2831 0 +0 2938 0 +0 3050 0 +0 3167 0 +0 3287 0 +0 3410 0 +0 3535 0 +0 3662 0 +3283 2230 3030 +3283 2230 3030 +3283 2231 3030 +3283 2232 3030 +3283 2233 3029 +3282 2234 3029 +3282 2236 3028 +3281 2238 3028 +3281 2241 3027 +3280 2245 3026 +3279 2251 3024 +3277 2258 3022 +3275 2268 3019 +3272 2280 3015 +3268 2297 3010 +3262 2317 3002 +3255 2344 2992 +3245 2377 2979 +3231 2418 2960 +3212 2467 2933 +3186 2526 2896 +3147 2594 2839 +3090 2672 2751 +3000 2758 2598 +2844 2853 2248 +2481 2955 0 +0 3064 0 +0 3177 0 +0 3295 0 +0 3416 0 +0 3540 0 +0 3665 0 +3418 2332 3153 +3418 2332 3153 +3418 2333 3153 +3418 2333 3153 +3417 2334 3153 +3417 2335 3152 +3417 2337 3152 +3417 2339 3151 +3416 2341 3151 +3415 2344 3150 +3414 2349 3149 +3413 2355 3147 +3412 2363 3145 +3409 2373 3142 +3406 2386 3138 +3403 2403 3132 +3397 2425 3125 +3390 2453 3115 +3380 2488 3101 +3366 2531 3082 +3347 2582 3054 +3321 2643 3016 +3283 2713 2958 +3226 2793 2866 +3137 2882 2706 +2983 2978 2328 +2627 3082 0 +0 3191 0 +0 3306 0 +0 3424 0 +0 3546 0 +0 3670 0 +3552 2440 3279 +3552 2441 3278 +3552 2441 3278 +3552 2441 3278 +3552 2442 3278 +3551 2443 3278 +3551 2444 3278 +3551 2446 3277 +3551 2448 3277 +3550 2450 3276 +3549 2454 3275 +3549 2458 3274 +3547 2465 3272 +3546 2473 3270 +3543 2484 3267 +3541 2497 3263 +3537 2515 3257 +3531 2538 3250 +3524 2567 3239 +3514 2603 3225 +3500 2648 3206 +3482 2701 3178 +3455 2763 3138 +3417 2835 3079 +3361 2917 2986 +3273 3007 2820 +3120 3105 2416 +2770 3209 0 +0 3320 0 +0 3435 0 +0 3554 0 +0 3676 0 +3685 2554 3406 +3685 2554 3405 +3685 2554 3405 +3685 2555 3405 +3685 2555 3405 +3685 2556 3405 +3685 2557 3405 +3685 2558 3405 +3684 2560 3404 +3684 2562 3404 +3684 2564 3403 +3683 2568 3402 +3682 2573 3401 +3681 2579 3399 +3679 2588 3397 +3677 2599 3394 +3674 2613 3389 +3670 2632 3384 +3665 2656 3376 +3658 2686 3366 +3648 2723 3351 +3634 2768 3332 +3615 2823 3304 +3589 2886 3263 +3551 2960 3203 +3495 3042 3108 +3408 3134 2938 +3255 3233 2512 +2910 3338 0 +0 3449 0 +0 3565 0 +0 3685 0 +3819 2672 3534 +3819 2672 3534 +3819 2672 3534 +3819 2672 3534 +3818 2673 3533 +3818 2673 3533 +3818 2674 3533 +3818 2675 3533 +3818 2676 3533 +3818 2678 3532 +3817 2680 3532 +3817 2683 3531 +3816 2686 3530 +3815 2691 3529 +3814 2698 3527 +3812 2707 3525 +3810 2718 3522 +3807 2733 3517 +3803 2752 3512 +3798 2776 3504 +3791 2807 3494 +3781 2845 3479 +3767 2891 3459 +3749 2947 3431 +3722 3012 3390 +3685 3086 3329 +3629 3170 3232 +3542 3262 3059 +3390 3362 2616 +3048 3468 0 +0 3580 0 +0 3696 0 +3952 2793 3663 +3952 2793 3663 +3952 2793 3663 +3951 2793 3663 +3951 2793 3663 +3951 2794 3663 +3951 2794 3663 +3951 2795 3662 +3951 2796 3662 +3951 2797 3662 +3951 2799 3661 +3950 2801 3661 +3950 2804 3660 +3949 2808 3659 +3948 2813 3658 +3947 2820 3656 +3945 2829 3654 +3943 2840 3651 +3940 2856 3646 +3936 2875 3641 +3931 2900 3633 +3924 2931 3622 +3914 2970 3608 +3900 3017 3588 +3882 3073 3559 +3856 3139 3518 +3818 3214 3457 +3762 3298 3359 +3675 3391 3182 +3524 3491 2725 +3184 3598 0 +0 3710 0 +4084 2916 3793 +4084 2916 3793 +4084 2916 3793 +4084 2917 3793 +4084 2917 3793 +4084 2917 3793 +4084 2918 3793 +4084 2918 3792 +4084 2919 3792 +4084 2920 3792 +4083 2921 3792 +4083 2923 3791 +4083 2925 3791 +4082 2928 3790 +4082 2932 3789 +4081 2937 3788 +4080 2944 3786 +4078 2953 3784 +4076 2965 3781 +4073 2980 3776 +4069 3000 3771 +4064 3025 3763 +4056 3057 3752 +4047 3096 3738 +4033 3144 3717 +4015 3201 3689 +3988 3267 3647 +3951 3343 3585 +3895 3428 3486 +3808 3521 3308 +3658 3622 2839 +3320 3729 0 +4095 3042 3923 +4095 3042 3923 +4095 3042 3923 +4095 3042 3923 +4095 3042 3923 +4095 3043 3923 +4095 3043 3923 +4095 3043 3923 +4095 3044 3923 +4095 3045 3923 +4095 3046 3922 +4095 3047 3922 +4095 3049 3922 +4095 3051 3921 +4095 3054 3920 +4095 3058 3919 +4095 3063 3918 +4095 3070 3916 +4095 3079 3914 +4095 3091 3911 +4095 3107 3907 +4095 3127 3901 +4095 3152 3893 +4095 3184 3882 +4095 3224 3868 +4095 3272 3847 +4095 3329 3819 +4095 3396 3777 +4084 3472 3715 +4028 3558 3615 +3941 3651 3435 +3791 3752 2958 +4095 3169 4054 +4095 3169 4054 +4095 3169 4054 +4095 3169 4054 +4095 3169 4054 +4095 3170 4054 +4095 3170 4054 +4095 3170 4054 +4095 3171 4054 +4095 3171 4054 +4095 3172 4054 +4095 3173 4053 +4095 3174 4053 +4095 3176 4053 +4095 3178 4052 +4095 3181 4051 +4095 3185 4050 +4095 3191 4049 +4095 3198 4047 +4095 3207 4045 +4095 3219 4042 +4095 3235 4037 +4095 3255 4032 +4095 3281 4024 +4095 3313 4013 +4095 3353 3998 +4095 3401 3978 +4095 3459 3949 +4095 3526 3907 +4095 3602 3845 +4095 3688 3745 +4074 3782 3564 +0 1736 2002 +0 1737 2001 +0 1739 2000 +0 1741 1998 +0 1744 1995 +0 1748 1991 +0 1753 1986 +0 1760 1979 +0 1769 1970 +0 1781 1958 +0 1796 1940 +0 1816 1916 +0 1841 1881 +0 1872 1830 +0 1911 1752 +0 1958 1620 +0 2015 1347 +0 2080 0 +0 2156 0 +0 2240 0 +0 2333 0 +0 2434 0 +0 2541 0 +0 2653 0 +0 2770 0 +0 2890 0 +0 3013 0 +0 3138 0 +0 3265 0 +0 3393 0 +0 3522 0 +0 3652 0 +0 1737 2004 +0 1738 2003 +0 1739 2001 +0 1742 1999 +0 1745 1997 +0 1749 1993 +0 1754 1988 +0 1761 1981 +0 1769 1972 +0 1781 1960 +0 1796 1942 +0 1816 1918 +0 1841 1883 +0 1872 1833 +0 1911 1755 +0 1958 1624 +0 2015 1354 +0 2081 0 +0 2156 0 +0 2241 0 +0 2333 0 +0 2434 0 +0 2541 0 +0 2653 0 +0 2770 0 +0 2890 0 +0 3013 0 +0 3138 0 +0 3265 0 +0 3393 0 +0 3522 0 +0 3652 0 +0 1737 2006 +0 1738 2005 +0 1740 2004 +0 1742 2002 +0 1745 1999 +0 1749 1995 +0 1754 1990 +0 1761 1984 +0 1770 1974 +0 1782 1962 +0 1797 1945 +0 1817 1921 +0 1841 1886 +0 1873 1836 +0 1912 1759 +0 1959 1629 +0 2015 1363 +0 2081 0 +0 2156 0 +0 2241 0 +0 2334 0 +0 2434 0 +0 2541 0 +0 2653 0 +0 2770 0 +0 2890 0 +0 3013 0 +0 3138 0 +0 3265 0 +0 3393 0 +0 3522 0 +0 3652 0 +0 1738 2009 +0 1739 2008 +0 1741 2007 +0 1743 2005 +0 1746 2002 +0 1750 1998 +0 1755 1993 +0 1762 1987 +0 1771 1978 +0 1782 1965 +0 1798 1948 +0 1817 1924 +0 1842 1890 +0 1873 1840 +0 1912 1764 +0 1959 1636 +0 2015 1375 +0 2081 0 +0 2157 0 +0 2241 0 +0 2334 0 +0 2434 0 +0 2541 0 +0 2653 0 +0 2770 0 +0 2890 0 +0 3013 0 +0 3138 0 +0 3265 0 +0 3393 0 +0 3522 0 +0 3652 0 +0 1739 2013 +0 1740 2012 +0 1742 2011 +0 1744 2009 +0 1747 2006 +0 1751 2002 +0 1756 1997 +0 1763 1991 +0 1772 1982 +0 1783 1970 +0 1798 1953 +0 1818 1929 +0 1843 1895 +0 1874 1846 +0 1913 1771 +0 1960 1645 +0 2016 1391 +0 2082 0 +0 2157 0 +0 2241 0 +0 2334 0 +0 2434 0 +0 2541 0 +0 2653 0 +0 2770 0 +0 2890 0 +0 3013 0 +0 3138 0 +0 3265 0 +0 3393 0 +0 3522 0 +0 3652 0 +0 1740 2018 +0 1741 2017 +0 1743 2016 +0 1745 2014 +0 1748 2011 +0 1752 2008 +0 1757 2003 +0 1764 1996 +0 1773 1988 +0 1785 1975 +0 1800 1959 +0 1819 1935 +0 1844 1902 +0 1875 1854 +0 1914 1779 +0 1961 1656 +0 2017 1412 +0 2082 13 +0 2157 0 +0 2242 0 +0 2334 0 +0 2435 0 +0 2541 0 +0 2654 0 +0 2770 0 +0 2890 0 +0 3013 0 +0 3138 0 +0 3265 0 +0 3393 0 +0 3522 0 +0 3652 0 +0 1742 2025 +0 1743 2024 +0 1745 2023 +0 1747 2021 +0 1750 2018 +0 1754 2015 +0 1759 2010 +0 1766 2004 +0 1775 1995 +0 1786 1983 +0 1801 1967 +0 1821 1944 +0 1845 1911 +0 1876 1864 +0 1915 1791 +0 1962 1672 +0 2018 1438 +0 2083 386 +0 2158 0 +0 2242 0 +0 2335 0 +0 2435 0 +0 2542 0 +0 2654 0 +0 2770 0 +0 2890 0 +0 3013 0 +0 3139 0 +0 3265 0 +0 3393 0 +0 3523 0 +0 3652 0 +0 1744 2035 +0 1746 2033 +0 1747 2032 +0 1749 2030 +0 1752 2028 +0 1756 2024 +0 1761 2020 +0 1768 2013 +0 1777 2005 +0 1788 1993 +0 1803 1977 +0 1823 1955 +0 1847 1923 +0 1878 1877 +0 1917 1806 +0 1963 1691 +0 2019 1470 +0 2084 640 +0 2159 0 +0 2243 0 +0 2336 0 +0 2436 0 +0 2542 0 +0 2654 0 +0 2771 0 +0 2891 0 +0 3014 0 +0 3139 0 +0 3265 0 +0 3393 0 +0 3523 0 +0 3652 0 +0 1748 2046 +0 1749 2045 +0 1750 2044 +0 1753 2042 +0 1755 2040 +0 1759 2036 +0 1764 2032 +0 1771 2026 +0 1780 2018 +0 1791 2006 +0 1806 1991 +0 1825 1969 +0 1850 1938 +0 1881 1893 +0 1919 1826 +0 1965 1716 +0 2021 1510 +0 2086 846 +0 2160 0 +0 2244 0 +0 2336 0 +0 2436 0 +0 2543 0 +0 2655 0 +0 2771 0 +0 2891 0 +0 3014 0 +0 3139 0 +0 3266 0 +0 3394 0 +0 3523 0 +0 3652 0 +0 1752 2062 +0 1753 2061 +0 1755 2060 +0 1757 2058 +0 1760 2055 +0 1763 2052 +0 1768 2048 +0 1775 2042 +0 1784 2034 +0 1795 2023 +0 1810 2008 +0 1829 1987 +0 1853 1958 +0 1884 1915 +0 1922 1851 +0 1968 1748 +0 2023 1559 +0 2088 1026 +0 2162 0 +0 2246 0 +0 2338 0 +0 2437 0 +0 2543 0 +0 2655 0 +0 2771 0 +0 2891 0 +0 3014 0 +0 3139 0 +0 3266 0 +0 3394 0 +0 3523 0 +0 3652 0 +0 1757 2082 +0 1759 2081 +0 1760 2080 +0 1762 2078 +0 1765 2076 +0 1769 2073 +0 1774 2068 +0 1780 2063 +0 1789 2055 +0 1800 2045 +0 1815 2030 +0 1834 2011 +0 1858 1983 +0 1888 1942 +0 1925 1882 +0 1971 1787 +0 2026 1616 +0 2090 1191 +0 2164 0 +0 2247 0 +0 2339 0 +0 2438 0 +0 2544 0 +0 2656 0 +0 2772 0 +0 2892 0 +0 3014 0 +0 3139 0 +0 3266 0 +0 3394 0 +0 3523 0 +0 3653 0 +30 1765 2107 +0 1766 2106 +0 1767 2105 +0 1770 2103 +0 1772 2101 +0 1776 2098 +0 1781 2094 +0 1787 2089 +0 1796 2082 +0 1807 2072 +0 1821 2059 +0 1840 2040 +0 1864 2014 +0 1893 1976 +0 1931 1921 +0 1976 1834 +0 2030 1684 +0 2094 1346 +0 2167 0 +0 2250 0 +0 2341 0 +0 2440 0 +0 2546 0 +0 2657 0 +0 2773 0 +0 2892 0 +0 3015 0 +0 3140 0 +0 3266 0 +0 3394 0 +0 3523 0 +0 3653 0 +1247 1774 2139 +1239 1775 2138 +1228 1777 2137 +1213 1779 2136 +1193 1782 2133 +1163 1785 2131 +1121 1790 2127 +1058 1796 2122 +956 1805 2116 +771 1816 2106 +265 1830 2094 +0 1848 2077 +0 1871 2053 +0 1901 2018 +0 1937 1968 +0 1982 1890 +0 2036 1760 +0 2099 1495 +0 2171 0 +0 2253 0 +0 2344 0 +0 2442 0 +0 2547 0 +0 2658 0 +0 2774 0 +0 2893 0 +0 3015 0 +0 3140 0 +0 3267 0 +0 3394 0 +0 3523 0 +0 3653 0 +1614 1787 2178 +1611 1788 2178 +1606 1790 2177 +1600 1792 2175 +1591 1794 2173 +1579 1798 2171 +1563 1802 2167 +1540 1808 2163 +1507 1817 2157 +1459 1827 2149 +1387 1841 2137 +1267 1859 2122 +1031 1881 2100 +0 1910 2069 +0 1946 2024 +0 1990 1956 +0 2043 1846 +0 2105 1639 +0 2177 963 +0 2258 0 +0 2348 0 +0 2445 0 +0 2550 0 +0 2660 0 +0 2775 0 +0 2894 0 +0 3016 0 +0 3141 0 +0 3267 0 +0 3395 0 +0 3523 0 +0 3653 0 +1867 1803 2226 +1865 1804 2225 +1862 1806 2224 +1858 1808 2223 +1853 1810 2222 +1847 1814 2219 +1838 1818 2216 +1825 1824 2212 +1808 1832 2207 +1784 1842 2199 +1750 1855 2189 +1700 1873 2175 +1623 1895 2156 +1494 1923 2129 +1232 1958 2090 +0 2000 2032 +0 2052 1940 +0 2113 1780 +0 2184 1399 +0 2264 0 +0 2352 0 +0 2449 0 +0 2553 0 +0 2663 0 +0 2777 0 +0 2896 0 +0 3017 0 +0 3142 0 +0 3268 0 +0 3395 0 +0 3524 0 +0 3653 0 +2071 1824 2283 +2070 1825 2282 +2068 1827 2282 +2066 1828 2281 +2063 1831 2279 +2059 1834 2277 +2053 1838 2274 +2046 1844 2271 +2035 1851 2266 +2021 1861 2260 +2001 1874 2251 +1973 1891 2239 +1932 1912 2222 +1871 1939 2198 +1775 1973 2165 +1602 2014 2117 +1165 2064 2042 +0 2124 1918 +0 2193 1672 +0 2271 186 +0 2359 0 +0 2454 0 +0 2557 0 +0 2666 0 +0 2780 0 +0 2898 0 +0 3019 0 +0 3143 0 +0 3268 0 +0 3396 0 +0 3524 0 +0 3654 0 +2251 1851 2350 +2250 1852 2349 +2249 1853 2348 +2248 1855 2347 +2246 1857 2346 +2243 1860 2344 +2239 1864 2342 +2234 1869 2339 +2227 1877 2335 +2218 1886 2329 +2205 1898 2322 +2187 1914 2311 +2162 1934 2297 +2127 1960 2277 +2074 1992 2250 +1993 2032 2210 +1855 2080 2150 +1563 2138 2055 +0 2205 1887 +0 2281 1471 +0 2367 0 +0 2461 0 +0 2562 0 +0 2670 0 +0 2783 0 +0 2900 0 +0 3021 0 +0 3144 0 +0 3270 0 +0 3397 0 +0 3525 0 +0 3654 0 +2416 1884 2425 +2415 1885 2425 +2415 1886 2424 +2413 1888 2424 +2412 1890 2423 +2410 1893 2421 +2408 1896 2419 +2404 1901 2417 +2399 1908 2413 +2393 1917 2408 +2384 1928 2402 +2372 1943 2393 +2356 1962 2382 +2333 1986 2365 +2300 2017 2342 +2253 2054 2310 +2180 2101 2263 +2060 2156 2191 +1826 2220 2072 +763 2295 1841 +0 2378 850 +0 2470 0 +0 2570 0 +0 2676 0 +0 2787 0 +0 2904 0 +0 3023 0 +0 3146 0 +0 3271 0 +0 3398 0 +0 3526 0 +0 3655 0 +2571 1925 2511 +2571 1926 2510 +2570 1927 2510 +2569 1928 2509 +2568 1930 2508 +2567 1933 2507 +2565 1936 2505 +2563 1941 2503 +2559 1947 2500 +2555 1955 2496 +2549 1965 2491 +2540 1979 2484 +2529 1997 2474 +2514 2019 2461 +2492 2048 2443 +2461 2083 2417 +2417 2126 2380 +2350 2179 2326 +2240 2240 2240 +2036 2312 2094 +1384 2392 1771 +0 2482 0 +0 2579 0 +0 2683 0 +0 2793 0 +0 2908 0 +0 3027 0 +0 3149 0 +0 3273 0 +0 3399 0 +0 3527 0 +0 3656 0 +2720 1975 2604 +2719 1975 2604 +2719 1976 2603 +2718 1978 2603 +2718 1979 2602 +2717 1982 2601 +2715 1985 2600 +2713 1989 2598 +2711 1994 2596 +2708 2002 2593 +2704 2011 2588 +2698 2023 2583 +2690 2039 2575 +2679 2060 2564 +2664 2086 2550 +2643 2119 2529 +2614 2159 2501 +2571 2208 2460 +2508 2266 2398 +2405 2333 2299 +2218 2411 2122 +1698 2497 1658 +0 2591 0 +0 2693 0 +0 2801 0 +0 2914 0 +0 3032 0 +0 3152 0 +0 3276 0 +0 3401 0 +0 3529 0 +0 3657 0 +2864 2033 2705 +2863 2034 2705 +2863 2035 2704 +2863 2036 2704 +2862 2038 2703 +2861 2040 2703 +2860 2042 2702 +2859 2046 2700 +2857 2051 2698 +2855 2057 2696 +2852 2066 2692 +2848 2076 2688 +2842 2091 2682 +2834 2109 2673 +2824 2133 2662 +2809 2162 2646 +2789 2199 2624 +2761 2244 2593 +2720 2298 2548 +2658 2361 2479 +2560 2434 2368 +2385 2516 2156 +1930 2607 1441 +0 2706 0 +0 2811 0 +0 2922 0 +0 3038 0 +0 3157 0 +0 3279 0 +0 3404 0 +0 3531 0 +0 3658 0 +3004 2102 2812 +3004 2102 2812 +3004 2103 2812 +3004 2104 2811 +3003 2105 2811 +3003 2107 2810 +3002 2110 2810 +3001 2113 2808 +3000 2117 2807 +2998 2122 2805 +2996 2130 2802 +2993 2139 2799 +2989 2152 2794 +2983 2168 2787 +2976 2188 2779 +2965 2215 2766 +2951 2248 2750 +2931 2288 2726 +2903 2337 2693 +2863 2396 2644 +2804 2464 2570 +2709 2541 2446 +2541 2628 2199 +2125 2722 664 +0 2824 0 +0 2932 0 +0 3046 0 +0 3163 0 +0 3284 0 +0 3408 0 +0 3533 0 +0 3660 0 +3143 2180 2925 +3143 2180 2925 +3143 2181 2924 +3142 2182 2924 +3142 2183 2924 +3142 2184 2923 +3141 2186 2923 +3141 2189 2922 +3140 2192 2921 +3138 2197 2919 +3137 2203 2917 +3134 2211 2914 +3131 2222 2911 +3127 2236 2906 +3122 2254 2899 +3114 2276 2890 +3104 2305 2877 +3090 2341 2859 +3071 2385 2835 +3043 2438 2799 +3004 2500 2748 +2945 2572 2668 +2853 2653 2532 +2690 2743 2250 +2299 2841 0 +0 2946 0 +0 3056 0 +0 3171 0 +0 3290 0 +0 3412 0 +0 3537 0 +0 3663 0 +3280 2267 3042 +3280 2267 3042 +3280 2267 3041 +3279 2268 3041 +3279 2269 3041 +3279 2270 3041 +3278 2272 3040 +3278 2274 3039 +3277 2277 3039 +3276 2281 3037 +3275 2286 3036 +3273 2293 3034 +3271 2302 3031 +3268 2313 3027 +3264 2328 3022 +3259 2348 3015 +3251 2373 3005 +3241 2404 2992 +3227 2442 2974 +3208 2489 2948 +3181 2545 2911 +3142 2611 2857 +3085 2686 2773 +2994 2770 2628 +2835 2863 2310 +2460 2963 0 +0 3070 0 +0 3182 0 +0 3299 0 +0 3419 0 +0 3542 0 +0 3667 0 +3415 2362 3162 +3415 2362 3162 +3415 2362 3162 +3415 2363 3162 +3415 2364 3162 +3415 2365 3161 +3414 2366 3161 +3414 2368 3160 +3414 2370 3160 +3413 2373 3159 +3412 2377 3158 +3411 2383 3156 +3409 2390 3154 +3407 2400 3151 +3404 2412 3147 +3400 2429 3142 +3394 2449 3134 +3387 2476 3124 +3377 2509 3111 +3363 2550 3092 +3344 2599 3066 +3318 2658 3028 +3279 2726 2971 +3222 2804 2883 +3132 2891 2730 +2976 2985 2380 +2613 3088 0 +0 3196 0 +0 3309 0 +0 3427 0 +0 3548 0 +0 3672 0 +3550 2464 3285 +3550 2464 3285 +3550 2464 3285 +3550 2465 3285 +3550 2465 3285 +3550 2466 3285 +3549 2467 3284 +3549 2469 3284 +3549 2471 3284 +3548 2473 3283 +3548 2477 3282 +3547 2481 3281 +3545 2487 3279 +3544 2495 3277 +3542 2505 3274 +3539 2518 3270 +3535 2535 3264 +3529 2557 3257 +3522 2585 3247 +3512 2620 3233 +3498 2663 3214 +3479 2714 3187 +3453 2775 3148 +3415 2845 3090 +3358 2925 2999 +3269 3014 2838 +3115 3110 2460 +2760 3214 0 +0 3323 0 +0 3438 0 +0 3556 0 +0 3678 0 +3684 2572 3411 +3684 2572 3411 +3684 2573 3411 +3684 2573 3410 +3684 2574 3410 +3684 2574 3410 +3684 2575 3410 +3683 2576 3410 +3683 2578 3409 +3683 2580 3409 +3682 2582 3408 +3682 2586 3407 +3681 2591 3406 +3679 2597 3404 +3678 2605 3402 +3676 2616 3399 +3673 2630 3395 +3669 2647 3389 +3663 2670 3382 +3656 2699 3371 +3646 2736 3357 +3633 2780 3338 +3614 2833 3310 +3587 2895 3270 +3549 2967 3211 +3493 3049 3118 +3405 3139 2952 +3252 3237 2548 +2902 3342 0 +0 3452 0 +0 3567 0 +0 3686 0 +3818 2686 3538 +3818 2686 3538 +3818 2686 3538 +3818 2686 3537 +3817 2687 3537 +3817 2687 3537 +3817 2688 3537 +3817 2689 3537 +3817 2690 3537 +3817 2692 3536 +3816 2694 3536 +3816 2696 3535 +3815 2700 3534 +3814 2705 3533 +3813 2711 3531 +3811 2720 3529 +3809 2731 3526 +3806 2745 3522 +3802 2764 3516 +3797 2788 3508 +3790 2818 3498 +3780 2855 3484 +3766 2900 3464 +3748 2955 3436 +3721 3018 3395 +3683 3092 3335 +3627 3174 3240 +3540 3266 3070 +3387 3365 2644 +3042 3470 0 +0 3582 0 +0 3697 0 +3951 2804 3666 +3951 2804 3666 +3951 2804 3666 +3951 2804 3666 +3951 2804 3666 +3951 2805 3666 +3951 2805 3665 +3950 2806 3665 +3950 2807 3665 +3950 2808 3665 +3950 2810 3664 +3949 2812 3664 +3949 2815 3663 +3948 2818 3662 +3947 2823 3661 +3946 2830 3659 +3944 2839 3657 +3942 2850 3654 +3939 2865 3650 +3935 2884 3644 +3930 2909 3636 +3923 2939 3626 +3913 2977 3611 +3900 3024 3591 +3881 3079 3563 +3855 3144 3522 +3817 3218 3461 +3761 3302 3364 +3674 3394 3191 +3522 3494 2748 +3180 3600 0 +0 3712 0 +4084 2925 3795 +4084 2925 3795 +4084 2925 3795 +4084 2925 3795 +4084 2925 3795 +4084 2926 3795 +4083 2926 3795 +4083 2926 3795 +4083 2927 3794 +4083 2928 3794 +4083 2929 3794 +4083 2931 3794 +4082 2933 3793 +4082 2936 3792 +4081 2940 3791 +4080 2945 3790 +4079 2952 3788 +4077 2961 3786 +4075 2972 3783 +4072 2988 3779 +4068 3007 3773 +4063 3032 3765 +4056 3063 3755 +4046 3102 3740 +4033 3149 3720 +4014 3205 3691 +3988 3271 3650 +3950 3346 3589 +3894 3430 3491 +3807 3523 3314 +3656 3623 2857 +3317 3730 0 +4095 3048 3925 +4095 3048 3925 +4095 3048 3925 +4095 3049 3925 +4095 3049 3925 +4095 3049 3925 +4095 3049 3925 +4095 3050 3925 +4095 3050 3924 +4095 3051 3924 +4095 3052 3924 +4095 3053 3924 +4095 3055 3923 +4095 3057 3923 +4095 3060 3922 +4095 3064 3921 +4095 3069 3920 +4095 3076 3918 +4095 3085 3916 +4095 3097 3913 +4095 3112 3908 +4095 3132 3903 +4095 3157 3895 +4095 3189 3884 +4095 3228 3870 +4095 3276 3849 +4095 3333 3821 +4095 3399 3779 +4083 3475 3717 +4027 3560 3619 +3940 3653 3440 +3790 3754 2972 +4095 3174 4055 +4095 3174 4055 +4095 3174 4055 +4095 3174 4055 +4095 3174 4055 +4095 3174 4055 +4095 3175 4055 +4095 3175 4055 +4095 3175 4055 +4095 3176 4055 +4095 3177 4055 +4095 3178 4055 +4095 3179 4054 +4095 3181 4054 +4095 3183 4053 +4095 3186 4053 +4095 3190 4052 +4095 3195 4050 +4095 3202 4049 +4095 3211 4046 +4095 3223 4043 +4095 3239 4039 +4095 3259 4033 +4095 3285 4025 +4095 3317 4015 +4095 3356 4000 +4095 3404 3979 +4095 3461 3951 +4095 3528 3909 +4095 3604 3847 +4095 3690 3747 +4073 3783 3567 +0 1867 2134 +0 1868 2133 +0 1869 2132 +0 1871 2130 +0 1873 2128 +0 1876 2126 +0 1880 2122 +0 1885 2117 +0 1892 2110 +0 1901 2101 +0 1913 2088 +0 1928 2071 +0 1948 2047 +0 1973 2012 +0 2004 1961 +0 2043 1882 +0 2090 1749 +0 2146 1473 +0 2212 0 +0 2288 0 +0 2372 0 +0 2465 0 +0 2566 0 +0 2673 0 +0 2785 0 +0 2902 0 +0 3022 0 +0 3145 0 +0 3270 0 +0 3397 0 +0 3525 0 +0 3654 0 +0 1867 2135 +0 1868 2134 +0 1869 2133 +0 1871 2132 +0 1873 2130 +0 1876 2127 +0 1880 2123 +0 1885 2118 +0 1892 2112 +0 1901 2102 +0 1913 2090 +0 1928 2072 +0 1948 2048 +0 1973 2013 +0 2004 1962 +0 2043 1884 +0 2090 1752 +0 2147 1479 +0 2213 0 +0 2288 0 +0 2372 0 +0 2465 0 +0 2566 0 +0 2673 0 +0 2785 0 +0 2902 0 +0 3022 0 +0 3145 0 +0 3270 0 +0 3397 0 +0 3525 0 +0 3654 0 +0 1868 2137 +0 1869 2136 +0 1870 2135 +0 1872 2133 +0 1874 2131 +0 1877 2129 +0 1881 2125 +0 1886 2120 +0 1893 2113 +0 1902 2104 +0 1913 2092 +0 1929 2074 +0 1948 2050 +0 1973 2016 +0 2004 1965 +0 2043 1887 +0 2091 1756 +0 2147 1486 +0 2213 0 +0 2288 0 +0 2373 0 +0 2466 0 +0 2566 0 +0 2673 0 +0 2785 0 +0 2902 0 +0 3022 0 +0 3145 0 +0 3270 0 +0 3397 0 +0 3525 0 +0 3655 0 +0 1868 2139 +0 1869 2138 +0 1870 2137 +0 1872 2136 +0 1874 2134 +0 1877 2131 +0 1881 2127 +0 1886 2122 +0 1893 2116 +0 1902 2107 +0 1914 2094 +0 1929 2077 +0 1949 2053 +0 1974 2019 +0 2005 1968 +0 2044 1891 +0 2091 1761 +0 2147 1495 +0 2213 0 +0 2288 0 +0 2373 0 +0 2466 0 +0 2566 0 +0 2673 0 +0 2785 0 +0 2902 0 +0 3022 0 +0 3145 0 +0 3270 0 +0 3397 0 +0 3525 0 +0 3655 0 +0 1869 2142 +0 1870 2141 +0 1871 2140 +0 1873 2139 +0 1875 2137 +0 1878 2134 +0 1882 2130 +0 1887 2125 +0 1894 2119 +0 1903 2110 +0 1915 2097 +0 1930 2080 +0 1949 2056 +0 1974 2022 +0 2005 1973 +0 2044 1896 +0 2091 1768 +0 2148 1508 +0 2213 0 +0 2289 0 +0 2373 0 +0 2466 0 +0 2566 0 +0 2673 0 +0 2785 0 +0 2902 0 +0 3022 0 +0 3145 0 +0 3270 0 +0 3397 0 +0 3525 0 +0 3655 0 +0 1870 2146 +0 1871 2145 +0 1872 2144 +0 1874 2143 +0 1876 2141 +0 1879 2138 +0 1883 2134 +0 1888 2130 +0 1895 2123 +0 1904 2114 +0 1915 2102 +0 1931 2085 +0 1950 2061 +0 1975 2028 +0 2006 1978 +0 2045 1903 +0 2092 1777 +0 2148 1523 +0 2214 0 +0 2289 0 +0 2373 0 +0 2466 0 +0 2567 0 +0 2673 0 +0 2786 0 +0 2902 0 +0 3022 0 +0 3145 0 +0 3270 0 +0 3397 0 +0 3525 0 +0 3655 0 +0 1871 2151 +0 1872 2151 +0 1874 2149 +0 1875 2148 +0 1877 2146 +0 1880 2143 +0 1884 2140 +0 1889 2135 +0 1896 2129 +0 1905 2120 +0 1917 2108 +0 1932 2091 +0 1951 2068 +0 1976 2034 +0 2007 1986 +0 2046 1912 +0 2093 1788 +0 2149 1544 +0 2214 145 +0 2290 0 +0 2374 0 +0 2467 0 +0 2567 0 +0 2674 0 +0 2786 0 +0 2902 0 +0 3022 0 +0 3145 0 +0 3271 0 +0 3397 0 +0 3525 0 +0 3655 0 +0 1873 2158 +0 1874 2157 +0 1875 2156 +0 1877 2155 +0 1879 2153 +0 1882 2150 +0 1886 2147 +0 1891 2142 +0 1898 2136 +0 1907 2127 +0 1918 2115 +0 1933 2099 +0 1953 2076 +0 1977 2043 +0 2009 1996 +0 2047 1923 +0 2094 1804 +0 2150 1570 +0 2215 518 +0 2290 0 +0 2374 0 +0 2467 0 +0 2567 0 +0 2674 0 +0 2786 0 +0 2902 0 +0 3023 0 +0 3146 0 +0 3271 0 +0 3397 0 +0 3526 0 +0 3655 0 +0 1876 2167 +0 1876 2167 +0 1878 2166 +0 1879 2164 +0 1882 2162 +0 1884 2160 +0 1888 2156 +0 1893 2152 +0 1900 2145 +0 1909 2137 +0 1920 2125 +0 1935 2109 +0 1955 2087 +0 1979 2055 +0 2010 2009 +0 2049 1938 +0 2095 1823 +0 2151 1602 +0 2216 772 +0 2291 0 +0 2375 0 +0 2468 0 +0 2568 0 +0 2674 0 +0 2786 0 +0 2903 0 +0 3023 0 +0 3146 0 +0 3271 0 +0 3398 0 +0 3526 0 +0 3655 0 +0 1879 2179 +0 1880 2179 +0 1881 2178 +0 1883 2176 +0 1885 2174 +0 1888 2172 +0 1891 2168 +0 1896 2164 +0 1903 2158 +0 1912 2150 +0 1923 2138 +0 1938 2123 +0 1957 2101 +0 1982 2070 +0 2013 2026 +0 2051 1958 +0 2097 1848 +0 2153 1642 +0 2218 978 +0 2293 0 +0 2376 0 +0 2469 0 +0 2568 0 +0 2675 0 +0 2787 0 +0 2903 0 +0 3023 0 +0 3146 0 +0 3271 0 +0 3398 0 +0 3526 0 +0 3655 0 +0 1883 2195 +0 1884 2194 +0 1885 2193 +0 1887 2192 +0 1889 2190 +0 1892 2188 +0 1895 2184 +0 1900 2180 +0 1907 2174 +0 1916 2166 +0 1927 2155 +0 1942 2140 +0 1961 2119 +0 1985 2090 +0 2016 2047 +0 2054 1983 +0 2100 1880 +0 2155 1691 +0 2220 1158 +0 2294 0 +0 2378 0 +0 2470 0 +0 2569 0 +0 2676 0 +0 2787 0 +0 2904 0 +0 3023 0 +0 3146 0 +0 3271 0 +0 3398 0 +0 3526 0 +0 3655 0 +0 1889 2215 +0 1889 2214 +0 1891 2213 +0 1892 2212 +0 1894 2210 +0 1897 2208 +0 1901 2205 +0 1906 2200 +0 1912 2195 +0 1921 2187 +0 1932 2177 +0 1947 2163 +0 1966 2143 +0 1990 2115 +0 2020 2074 +0 2058 2014 +0 2103 1919 +0 2158 1748 +0 2223 1323 +0 2296 0 +0 2380 0 +0 2471 0 +0 2571 0 +0 2677 0 +0 2788 0 +0 2904 0 +0 3024 0 +0 3146 0 +0 3271 0 +0 3398 0 +0 3526 0 +0 3655 0 +241 1896 2240 +162 1897 2239 +31 1898 2238 +0 1900 2237 +0 1902 2236 +0 1904 2233 +0 1908 2230 +0 1913 2227 +0 1919 2221 +0 1928 2214 +0 1939 2204 +0 1953 2191 +0 1972 2172 +0 1996 2146 +0 2026 2108 +0 2063 2053 +0 2108 1966 +0 2162 1816 +0 2226 1478 +0 2299 0 +0 2382 0 +0 2473 0 +0 2572 0 +0 2678 0 +0 2789 0 +0 2905 0 +0 3024 0 +0 3147 0 +0 3272 0 +0 3398 0 +0 3526 0 +0 3655 0 +1385 1906 2272 +1379 1906 2271 +1371 1908 2270 +1360 1909 2269 +1345 1911 2268 +1325 1914 2266 +1296 1917 2263 +1253 1922 2259 +1190 1929 2254 +1089 1937 2248 +903 1948 2239 +397 1962 2226 +0 1980 2209 +0 2003 2185 +0 2033 2150 +0 2069 2100 +0 2114 2023 +0 2168 1893 +0 2231 1627 +0 2303 0 +0 2385 0 +0 2476 0 +0 2574 0 +0 2680 0 +0 2790 0 +0 2906 0 +0 3025 0 +0 3148 0 +0 3272 0 +0 3399 0 +0 3526 0 +0 3655 0 +1749 1918 2311 +1747 1919 2310 +1743 1920 2310 +1738 1922 2309 +1732 1924 2307 +1723 1926 2305 +1711 1930 2303 +1695 1934 2300 +1672 1941 2295 +1639 1949 2289 +1592 1959 2281 +1519 1973 2269 +1399 1991 2254 +1164 2014 2232 +83 2042 2201 +0 2078 2156 +0 2122 2088 +0 2175 1978 +0 2237 1771 +0 2309 1096 +0 2390 0 +0 2480 0 +0 2577 0 +0 2682 0 +0 2792 0 +0 2907 0 +0 3026 0 +0 3148 0 +0 3273 0 +0 3399 0 +0 3527 0 +0 3656 0 +2000 1935 2359 +1999 1935 2358 +1997 1936 2358 +1994 1938 2357 +1990 1940 2355 +1985 1942 2354 +1979 1946 2351 +1970 1950 2348 +1957 1956 2344 +1940 1964 2339 +1916 1974 2331 +1882 1988 2321 +1832 2005 2307 +1755 2027 2288 +1626 2055 2261 +1364 2090 2222 +0 2133 2164 +0 2184 2073 +0 2245 1912 +0 2316 1531 +0 2396 0 +0 2484 0 +0 2581 0 +0 2685 0 +0 2795 0 +0 2909 0 +0 3028 0 +0 3149 0 +0 3274 0 +0 3400 0 +0 3527 0 +0 3656 0 +2205 1955 2416 +2204 1956 2415 +2202 1957 2415 +2201 1959 2414 +2198 1960 2413 +2195 1963 2411 +2191 1966 2409 +2185 1970 2407 +2178 1976 2403 +2167 1984 2398 +2153 1993 2392 +2133 2006 2383 +2105 2023 2371 +2064 2044 2354 +2003 2071 2331 +1907 2105 2297 +1734 2146 2249 +1297 2196 2174 +0 2256 2050 +0 2325 1804 +0 2403 318 +0 2491 0 +0 2586 0 +0 2689 0 +0 2798 0 +0 2912 0 +0 3030 0 +0 3151 0 +0 3275 0 +0 3401 0 +0 3528 0 +0 3656 0 +2384 1982 2482 +2383 1983 2482 +2382 1984 2481 +2381 1985 2480 +2380 1987 2479 +2378 1989 2478 +2375 1992 2476 +2371 1996 2474 +2366 2002 2471 +2359 2009 2467 +2350 2018 2461 +2337 2030 2454 +2319 2046 2443 +2294 2066 2429 +2259 2092 2410 +2206 2124 2382 +2125 2164 2342 +1987 2212 2282 +1696 2270 2187 +0 2337 2019 +0 2414 1603 +0 2499 0 +0 2593 0 +0 2694 0 +0 2802 0 +0 2915 0 +0 3032 0 +0 3153 0 +0 3276 0 +0 3402 0 +0 3529 0 +0 3657 0 +2549 2015 2558 +2548 2016 2558 +2547 2017 2557 +2547 2018 2557 +2546 2020 2556 +2544 2022 2555 +2542 2025 2553 +2540 2029 2551 +2536 2034 2549 +2531 2040 2545 +2525 2049 2541 +2516 2060 2534 +2504 2075 2526 +2488 2094 2514 +2465 2118 2497 +2432 2149 2475 +2385 2187 2442 +2312 2233 2395 +2192 2288 2323 +1958 2352 2204 +895 2427 1973 +0 2510 982 +0 2602 0 +0 2702 0 +0 2808 0 +0 2919 0 +0 3036 0 +0 3156 0 +0 3278 0 +0 3403 0 +0 3530 0 +0 3658 0 +2703 2056 2643 +2703 2057 2643 +2703 2058 2642 +2702 2059 2642 +2701 2060 2641 +2700 2062 2640 +2699 2065 2639 +2697 2068 2637 +2695 2073 2635 +2691 2079 2632 +2687 2087 2629 +2681 2097 2623 +2673 2111 2616 +2661 2129 2607 +2646 2151 2593 +2624 2180 2575 +2593 2215 2549 +2549 2259 2512 +2482 2311 2458 +2373 2373 2373 +2168 2444 2226 +1516 2524 1903 +0 2614 0 +0 2711 0 +0 2815 0 +0 2925 0 +0 3040 0 +0 3159 0 +0 3281 0 +0 3405 0 +0 3531 0 +0 3659 0 +2852 2106 2736 +2852 2107 2736 +2851 2107 2736 +2851 2108 2735 +2850 2110 2735 +2850 2111 2734 +2849 2114 2733 +2847 2117 2732 +2846 2121 2730 +2843 2126 2728 +2840 2134 2725 +2836 2143 2720 +2830 2155 2715 +2822 2171 2707 +2811 2192 2696 +2796 2218 2682 +2775 2251 2662 +2746 2291 2633 +2703 2340 2592 +2640 2398 2530 +2537 2466 2431 +2350 2543 2254 +1830 2629 1790 +0 2723 0 +0 2825 0 +0 2933 0 +0 3046 0 +0 3164 0 +0 3284 0 +0 3408 0 +0 3533 0 +0 3661 0 +2996 2165 2837 +2996 2165 2837 +2995 2166 2837 +2995 2167 2836 +2995 2168 2836 +2994 2170 2835 +2994 2172 2835 +2993 2174 2834 +2991 2178 2832 +2990 2183 2830 +2987 2189 2828 +2984 2198 2825 +2980 2209 2820 +2974 2223 2814 +2966 2241 2805 +2956 2265 2794 +2941 2294 2778 +2921 2331 2756 +2893 2376 2725 +2852 2430 2680 +2790 2493 2611 +2693 2566 2500 +2517 2648 2288 +2062 2739 1573 +0 2838 0 +0 2943 0 +0 3054 0 +0 3170 0 +0 3289 0 +0 3412 0 +0 3536 0 +0 3663 0 +3137 2233 2944 +3136 2234 2944 +3136 2234 2944 +3136 2235 2944 +3136 2236 2944 +3135 2238 2943 +3135 2239 2942 +3134 2242 2942 +3133 2245 2941 +3132 2249 2939 +3130 2254 2937 +3128 2262 2934 +3125 2271 2931 +3121 2284 2926 +3115 2300 2920 +3108 2320 2911 +3097 2347 2899 +3083 2380 2882 +3063 2420 2858 +3036 2469 2825 +2996 2528 2776 +2936 2596 2702 +2841 2673 2578 +2673 2760 2331 +2257 2854 796 +0 2956 0 +0 3064 0 +0 3178 0 +0 3295 0 +0 3416 0 +0 3540 0 +0 3665 0 +3275 2311 3057 +3275 2312 3057 +3275 2312 3057 +3275 2313 3057 +3275 2314 3056 +3274 2315 3056 +3274 2316 3055 +3273 2318 3055 +3273 2321 3054 +3272 2324 3053 +3270 2329 3051 +3269 2335 3049 +3267 2343 3046 +3263 2354 3043 +3259 2368 3038 +3254 2386 3031 +3246 2409 3022 +3236 2437 3009 +3222 2473 2991 +3203 2517 2967 +3175 2570 2931 +3136 2633 2880 +3078 2704 2800 +2985 2786 2665 +2822 2875 2382 +2431 2973 0 +0 3078 0 +0 3188 0 +0 3303 0 +0 3422 0 +0 3545 0 +0 3669 0 +3412 2398 3174 +3412 2399 3174 +3412 2399 3174 +3412 2400 3174 +3411 2400 3173 +3411 2401 3173 +3411 2402 3173 +3411 2404 3172 +3410 2406 3172 +3409 2409 3171 +3408 2413 3170 +3407 2418 3168 +3406 2425 3166 +3403 2434 3163 +3400 2445 3159 +3396 2461 3154 +3391 2480 3147 +3383 2505 3137 +3373 2536 3124 +3360 2574 3106 +3340 2621 3080 +3313 2677 3043 +3275 2743 2989 +3217 2818 2905 +3126 2902 2760 +2967 2995 2442 +2592 3095 0 +0 3202 0 +0 3314 0 +0 3431 0 +0 3551 0 +0 3674 0 +3547 2493 3294 +3547 2494 3294 +3547 2494 3294 +3547 2494 3294 +3547 2495 3294 +3547 2496 3294 +3547 2497 3293 +3547 2498 3293 +3546 2500 3293 +3546 2502 3292 +3545 2505 3291 +3544 2510 3290 +3543 2515 3288 +3541 2522 3286 +3539 2532 3283 +3536 2545 3279 +3532 2561 3274 +3527 2582 3266 +3519 2608 3257 +3509 2641 3243 +3496 2682 3224 +3476 2731 3198 +3450 2790 3160 +3411 2858 3103 +3354 2936 3015 +3265 3023 2862 +3108 3118 2512 +2745 3220 0 +0 3328 0 +0 3442 0 +0 3559 0 +0 3680 0 +3682 2596 3418 +3682 2596 3417 +3682 2596 3417 +3682 2597 3417 +3682 2597 3417 +3682 2598 3417 +3682 2598 3417 +3681 2599 3417 +3681 2601 3416 +3681 2603 3416 +3680 2605 3415 +3680 2609 3414 +3679 2613 3413 +3677 2619 3411 +3676 2627 3409 +3674 2637 3406 +3671 2650 3402 +3667 2667 3396 +3661 2689 3389 +3654 2717 3379 +3644 2752 3365 +3630 2795 3346 +3612 2846 3319 +3585 2907 3280 +3547 2977 3222 +3490 3057 3131 +3401 3146 2970 +3247 3242 2592 +2892 3346 0 +0 3456 0 +0 3570 0 +0 3689 0 +3816 2704 3543 +3816 2704 3543 +3816 2705 3543 +3816 2705 3543 +3816 2705 3543 +3816 2706 3542 +3816 2706 3542 +3816 2707 3542 +3815 2708 3542 +3815 2710 3541 +3815 2712 3541 +3814 2714 3540 +3814 2718 3539 +3813 2723 3538 +3811 2729 3536 +3810 2737 3534 +3808 2748 3531 +3805 2762 3527 +3801 2780 3521 +3795 2803 3514 +3788 2832 3504 +3778 2868 3489 +3765 2912 3470 +3746 2965 3442 +3719 3027 3403 +3681 3099 3343 +3625 3181 3250 +3537 3271 3084 +3384 3369 2680 +3034 3474 0 +0 3584 0 +0 3699 0 +3950 2818 3670 +3950 2818 3670 +3950 2818 3670 +3950 2818 3670 +3950 2819 3670 +3950 2819 3669 +3949 2819 3669 +3949 2820 3669 +3949 2821 3669 +3949 2822 3669 +3949 2824 3668 +3948 2826 3668 +3948 2829 3667 +3947 2832 3666 +3946 2837 3665 +3945 2844 3663 +3943 2852 3661 +3941 2863 3658 +3938 2878 3654 +3934 2896 3648 +3929 2920 3640 +3922 2950 3630 +3912 2987 3616 +3898 3032 3596 +3880 3087 3568 +3853 3151 3528 +3815 3224 3467 +3759 3307 3372 +3672 3398 3202 +3520 3497 2776 +3174 3602 0 +0 3714 0 +4083 2936 3798 +4083 2936 3798 +4083 2936 3798 +4083 2936 3798 +4083 2936 3798 +4083 2936 3798 +4083 2937 3798 +4083 2937 3798 +4082 2938 3797 +4082 2939 3797 +4082 2940 3797 +4082 2942 3796 +4081 2944 3796 +4081 2947 3795 +4080 2951 3794 +4079 2956 3793 +4078 2962 3791 +4077 2971 3789 +4074 2982 3786 +4071 2997 3782 +4068 3016 3776 +4062 3041 3768 +4055 3071 3758 +4045 3109 3743 +4032 3156 3723 +4013 3211 3695 +3987 3276 3654 +3949 3350 3593 +3893 3434 3496 +3806 3526 3323 +3654 3626 2880 +3312 3732 0 +4095 3057 3927 +4095 3057 3927 +4095 3057 3927 +4095 3057 3927 +4095 3057 3927 +4095 3057 3927 +4095 3058 3927 +4095 3058 3927 +4095 3059 3927 +4095 3059 3927 +4095 3060 3926 +4095 3061 3926 +4095 3063 3926 +4095 3065 3925 +4095 3068 3924 +4095 3072 3923 +4095 3077 3922 +4095 3084 3920 +4095 3093 3918 +4095 3105 3915 +4095 3120 3911 +4095 3139 3905 +4095 3164 3897 +4095 3195 3887 +4095 3234 3872 +4095 3281 3852 +4095 3337 3823 +4095 3403 3782 +4082 3478 3721 +4026 3562 3623 +3939 3655 3446 +3788 3755 2989 +4095 3180 4057 +4095 3180 4057 +4095 3180 4057 +4095 3181 4057 +4095 3181 4057 +4095 3181 4057 +4095 3181 4057 +4095 3181 4057 +4095 3182 4057 +4095 3182 4057 +4095 3183 4056 +4095 3184 4056 +4095 3185 4056 +4095 3187 4055 +4095 3189 4055 +4095 3192 4054 +4095 3196 4053 +4095 3201 4052 +4095 3208 4050 +4095 3217 4048 +4095 3229 4045 +4095 3245 4040 +4095 3264 4035 +4095 3290 4027 +4095 3321 4016 +4095 3360 4002 +4095 3408 3981 +4095 3465 3953 +4095 3531 3911 +4095 3607 3849 +4095 3692 3751 +4073 3785 3572 +0 1998 2266 +0 1999 2265 +0 2000 2264 +0 2001 2263 +0 2003 2262 +0 2005 2260 +0 2008 2257 +0 2012 2253 +0 2017 2248 +0 2024 2241 +0 2033 2232 +0 2045 2219 +0 2060 2202 +0 2079 2177 +0 2104 2143 +0 2136 2091 +0 2175 2012 +0 2222 1879 +0 2278 1601 +0 2344 0 +0 2420 0 +0 2504 0 +0 2597 0 +0 2698 0 +0 2805 0 +0 2917 0 +0 3034 0 +0 3154 0 +0 3277 0 +0 3402 0 +0 3529 0 +0 3657 0 +0 1998 2267 +0 1999 2266 +0 2000 2265 +0 2001 2264 +0 2003 2263 +0 2005 2260 +0 2008 2258 +0 2012 2254 +0 2017 2249 +0 2024 2242 +0 2033 2233 +0 2045 2220 +0 2060 2203 +0 2080 2179 +0 2105 2144 +0 2136 2093 +0 2175 2014 +0 2222 1881 +0 2279 1606 +0 2344 0 +0 2420 0 +0 2504 0 +0 2597 0 +0 2698 0 +0 2805 0 +0 2917 0 +0 3034 0 +0 3154 0 +0 3277 0 +0 3402 0 +0 3529 0 +0 3657 0 +0 1999 2268 +0 1999 2267 +0 2000 2266 +0 2002 2265 +0 2003 2264 +0 2005 2262 +0 2008 2259 +0 2012 2255 +0 2017 2250 +0 2024 2244 +0 2033 2234 +0 2045 2222 +0 2060 2204 +0 2080 2180 +0 2105 2145 +0 2136 2095 +0 2175 2016 +0 2222 1884 +0 2279 1611 +0 2345 0 +0 2420 0 +0 2505 0 +0 2598 0 +0 2698 0 +0 2805 0 +0 2917 0 +0 3034 0 +0 3154 0 +0 3277 0 +0 3402 0 +0 3529 0 +0 3657 0 +0 1999 2270 +0 2000 2269 +0 2001 2268 +0 2002 2267 +0 2004 2265 +0 2006 2263 +0 2009 2261 +0 2013 2257 +0 2018 2252 +0 2025 2245 +0 2034 2236 +0 2045 2224 +0 2061 2206 +0 2080 2182 +0 2105 2148 +0 2137 2097 +0 2175 2019 +0 2223 1888 +0 2279 1618 +0 2345 0 +0 2420 0 +0 2505 0 +0 2598 0 +0 2698 0 +0 2805 0 +0 2917 0 +0 3034 0 +0 3154 0 +0 3277 0 +0 3402 0 +0 3529 0 +0 3657 0 +0 2000 2272 +0 2000 2271 +0 2001 2270 +0 2003 2269 +0 2004 2268 +0 2006 2266 +0 2009 2263 +0 2013 2259 +0 2018 2254 +0 2025 2248 +0 2034 2239 +0 2046 2226 +0 2061 2209 +0 2081 2185 +0 2106 2151 +0 2137 2100 +0 2176 2023 +0 2223 1893 +0 2279 1627 +0 2345 0 +0 2420 0 +0 2505 0 +0 2598 0 +0 2698 0 +0 2805 0 +0 2917 0 +0 3034 0 +0 3154 0 +0 3277 0 +0 3402 0 +0 3529 0 +0 3657 0 +0 2000 2275 +0 2001 2274 +0 2002 2273 +0 2003 2272 +0 2005 2271 +0 2007 2269 +0 2010 2266 +0 2014 2262 +0 2019 2258 +0 2026 2251 +0 2035 2242 +0 2047 2230 +0 2062 2212 +0 2081 2189 +0 2106 2155 +0 2138 2105 +0 2176 2028 +0 2223 1900 +0 2280 1640 +0 2345 0 +0 2421 0 +0 2505 0 +0 2598 0 +0 2698 0 +0 2805 0 +0 2917 0 +0 3034 0 +0 3154 0 +0 3277 0 +0 3403 0 +0 3529 0 +0 3658 0 +0 2001 2279 +0 2002 2278 +0 2003 2277 +0 2004 2276 +0 2006 2275 +0 2008 2273 +0 2011 2270 +0 2015 2267 +0 2020 2262 +0 2027 2255 +0 2036 2246 +0 2048 2234 +0 2063 2217 +0 2082 2193 +0 2107 2160 +0 2138 2110 +0 2177 2035 +0 2224 1909 +0 2280 1655 +0 2346 0 +0 2421 0 +0 2505 0 +0 2598 0 +0 2699 0 +0 2805 0 +0 2918 0 +0 3034 0 +0 3154 0 +0 3277 0 +0 3403 0 +0 3529 0 +0 3658 0 +0 2003 2284 +0 2003 2283 +0 2004 2283 +0 2006 2282 +0 2007 2280 +0 2009 2278 +0 2012 2275 +0 2016 2272 +0 2021 2267 +0 2028 2261 +0 2037 2252 +0 2049 2240 +0 2064 2223 +0 2083 2200 +0 2108 2166 +0 2139 2118 +0 2178 2044 +0 2225 1921 +0 2281 1676 +0 2347 277 +0 2422 0 +0 2506 0 +0 2599 0 +0 2699 0 +0 2806 0 +0 2918 0 +0 3034 0 +0 3155 0 +0 3278 0 +0 3403 0 +0 3529 0 +0 3658 0 +0 2005 2291 +0 2005 2290 +0 2006 2290 +0 2007 2288 +0 2009 2287 +0 2011 2285 +0 2014 2283 +0 2018 2279 +0 2023 2274 +0 2030 2268 +0 2039 2259 +0 2050 2247 +0 2065 2231 +0 2085 2208 +0 2110 2175 +0 2141 2128 +0 2179 2055 +0 2226 1936 +0 2282 1702 +0 2347 650 +0 2422 0 +0 2507 0 +0 2599 0 +0 2699 0 +0 2806 0 +0 2918 0 +0 3035 0 +0 3155 0 +0 3278 0 +0 3403 0 +0 3530 0 +0 3658 0 +0 2007 2300 +0 2008 2299 +0 2009 2299 +0 2010 2298 +0 2011 2296 +0 2014 2294 +0 2017 2292 +0 2020 2288 +0 2025 2284 +0 2032 2277 +0 2041 2269 +0 2053 2257 +0 2068 2241 +0 2087 2219 +0 2111 2187 +0 2142 2141 +0 2181 2071 +0 2227 1955 +0 2283 1734 +0 2349 904 +0 2423 0 +0 2507 0 +0 2600 0 +0 2700 0 +0 2806 0 +0 2918 0 +0 3035 0 +0 3155 0 +0 3278 0 +0 3403 0 +0 3530 0 +0 3658 0 +0 2010 2312 +0 2011 2311 +0 2012 2311 +0 2013 2310 +0 2015 2308 +0 2017 2306 +0 2020 2304 +0 2023 2301 +0 2029 2296 +0 2035 2290 +0 2044 2282 +0 2055 2270 +0 2070 2255 +0 2090 2233 +0 2114 2202 +0 2145 2158 +0 2183 2090 +0 2229 1980 +0 2285 1774 +0 2350 1110 +0 2425 0 +0 2508 0 +0 2601 0 +0 2700 0 +0 2807 0 +0 2919 0 +0 3035 0 +0 3155 0 +0 3278 0 +0 3403 0 +0 3530 0 +0 3658 0 +0 2014 2327 +0 2015 2327 +0 2016 2326 +0 2017 2325 +0 2019 2324 +0 2021 2322 +0 2024 2320 +0 2028 2316 +0 2033 2312 +0 2039 2306 +0 2048 2298 +0 2059 2287 +0 2074 2272 +0 2093 2251 +0 2117 2222 +0 2148 2179 +0 2186 2115 +0 2232 2012 +0 2287 1823 +0 2352 1290 +0 2426 0 +0 2510 0 +0 2602 0 +0 2701 0 +0 2808 0 +0 2919 0 +0 3036 0 +0 3155 0 +0 3278 0 +0 3403 0 +0 3530 0 +0 3658 0 +0 2020 2347 +0 2021 2347 +0 2022 2346 +0 2023 2345 +0 2024 2344 +0 2026 2342 +0 2029 2340 +0 2033 2337 +0 2038 2333 +0 2044 2327 +0 2053 2319 +0 2064 2309 +0 2079 2295 +0 2098 2275 +0 2122 2247 +0 2152 2206 +0 2190 2146 +0 2235 2051 +0 2290 1881 +0 2355 1455 +0 2429 0 +0 2512 0 +0 2603 0 +0 2703 0 +0 2809 0 +0 2920 0 +0 3036 0 +0 3156 0 +0 3279 0 +0 3403 0 +0 3530 0 +0 3658 0 +423 2027 2373 +373 2028 2372 +295 2029 2371 +163 2030 2370 +0 2032 2369 +0 2034 2368 +0 2036 2365 +0 2040 2363 +0 2045 2359 +0 2051 2353 +0 2060 2346 +0 2071 2336 +0 2085 2323 +0 2104 2304 +0 2128 2278 +0 2158 2241 +0 2195 2185 +0 2240 2098 +0 2294 1948 +0 2358 1610 +0 2432 0 +0 2514 0 +0 2605 0 +0 2704 0 +0 2810 0 +0 2921 0 +0 3037 0 +0 3157 0 +0 3279 0 +0 3404 0 +0 3530 0 +0 3658 0 +1521 2037 2404 +1517 2038 2404 +1511 2039 2403 +1503 2040 2402 +1492 2041 2401 +1477 2043 2400 +1457 2046 2398 +1428 2050 2395 +1385 2054 2391 +1322 2061 2386 +1221 2069 2380 +1036 2080 2371 +529 2094 2358 +0 2112 2341 +0 2135 2317 +0 2165 2283 +0 2201 2232 +0 2246 2155 +0 2300 2025 +0 2363 1759 +0 2436 0 +0 2518 0 +0 2608 0 +0 2707 0 +0 2812 0 +0 2923 0 +0 3038 0 +0 3157 0 +0 3280 0 +0 3404 0 +0 3531 0 +0 3659 0 +1883 2050 2444 +1881 2050 2443 +1879 2051 2443 +1875 2052 2442 +1870 2054 2441 +1864 2056 2439 +1855 2058 2437 +1843 2062 2435 +1827 2066 2432 +1804 2073 2427 +1771 2081 2421 +1724 2091 2413 +1651 2105 2401 +1531 2123 2386 +1296 2146 2364 +216 2174 2333 +0 2210 2288 +0 2254 2221 +0 2307 2111 +0 2369 1903 +0 2441 1228 +0 2522 0 +0 2612 0 +0 2709 0 +0 2814 0 +0 2924 0 +0 3039 0 +0 3158 0 +0 3280 0 +0 3405 0 +0 3531 0 +0 3659 0 +2133 2066 2491 +2132 2067 2491 +2131 2067 2490 +2129 2068 2490 +2126 2070 2489 +2122 2072 2487 +2118 2074 2486 +2111 2078 2484 +2102 2082 2481 +2089 2088 2476 +2072 2096 2471 +2048 2106 2464 +2014 2120 2453 +1964 2137 2440 +1887 2159 2420 +1758 2187 2393 +1496 2222 2354 +0 2265 2296 +0 2316 2205 +0 2377 2044 +0 2448 1663 +0 2528 0 +0 2617 0 +0 2713 0 +0 2817 0 +0 2927 0 +0 3041 0 +0 3160 0 +0 3282 0 +0 3406 0 +0 3532 0 +0 3659 0 +2337 2087 2548 +2337 2088 2548 +2336 2088 2547 +2334 2089 2547 +2333 2091 2546 +2330 2093 2545 +2327 2095 2543 +2323 2098 2541 +2317 2103 2539 +2310 2108 2535 +2299 2116 2530 +2285 2126 2524 +2265 2138 2515 +2237 2155 2503 +2196 2176 2486 +2135 2203 2463 +2039 2237 2429 +1866 2278 2381 +1429 2329 2306 +0 2388 2182 +0 2457 1936 +0 2536 450 +0 2623 0 +0 2718 0 +0 2821 0 +0 2930 0 +0 3044 0 +0 3162 0 +0 3283 0 +0 3407 0 +0 3533 0 +0 3660 0 +2517 2114 2614 +2516 2114 2614 +2515 2115 2614 +2515 2116 2613 +2513 2117 2612 +2512 2119 2612 +2510 2121 2610 +2507 2124 2609 +2503 2128 2606 +2498 2134 2603 +2491 2141 2599 +2482 2150 2593 +2469 2162 2586 +2451 2178 2576 +2426 2198 2561 +2391 2224 2542 +2338 2256 2514 +2257 2296 2474 +2119 2344 2414 +1828 2402 2319 +0 2469 2151 +0 2546 1735 +0 2631 0 +0 2725 0 +0 2827 0 +0 2934 0 +0 3047 0 +0 3164 0 +0 3285 0 +0 3408 0 +0 3534 0 +0 3661 0 +2681 2147 2690 +2681 2147 2690 +2680 2148 2690 +2680 2149 2689 +2679 2150 2689 +2678 2152 2688 +2676 2154 2687 +2674 2157 2685 +2672 2161 2683 +2668 2166 2681 +2663 2172 2677 +2657 2181 2673 +2648 2192 2666 +2636 2207 2658 +2620 2226 2646 +2597 2250 2629 +2565 2281 2607 +2517 2319 2574 +2444 2365 2527 +2325 2420 2455 +2090 2485 2336 +1027 2559 2105 +0 2642 1114 +0 2734 0 +0 2834 0 +0 2940 0 +0 3052 0 +0 3168 0 +0 3288 0 +0 3410 0 +0 3535 0 +0 3662 0 +2836 2188 2775 +2836 2189 2775 +2835 2189 2775 +2835 2190 2774 +2834 2191 2774 +2833 2193 2773 +2832 2194 2772 +2831 2197 2771 +2829 2201 2770 +2827 2205 2767 +2823 2211 2765 +2819 2219 2761 +2813 2230 2755 +2805 2243 2748 +2793 2261 2739 +2778 2283 2725 +2756 2312 2707 +2726 2347 2681 +2681 2391 2644 +2614 2443 2590 +2505 2505 2505 +2300 2576 2358 +1648 2656 2036 +0 2746 0 +0 2843 0 +0 2947 0 +0 3057 0 +0 3172 0 +0 3291 0 +0 3413 0 +0 3537 0 +0 3664 0 +2984 2238 2869 +2984 2238 2868 +2984 2239 2868 +2983 2239 2868 +2983 2240 2868 +2983 2242 2867 +2982 2244 2866 +2981 2246 2865 +2979 2249 2864 +2978 2253 2862 +2975 2259 2860 +2972 2266 2857 +2968 2275 2853 +2962 2287 2847 +2954 2303 2839 +2943 2324 2828 +2928 2350 2814 +2907 2383 2794 +2878 2423 2765 +2836 2472 2724 +2772 2530 2662 +2669 2598 2563 +2482 2675 2386 +1962 2761 1922 +0 2855 0 +0 2957 0 +0 3065 0 +0 3178 0 +0 3296 0 +0 3417 0 +0 3540 0 +0 3666 0 +3128 2297 2969 +3128 2297 2969 +3128 2298 2969 +3128 2298 2969 +3127 2299 2969 +3127 2300 2968 +3126 2302 2968 +3126 2304 2967 +3125 2307 2966 +3123 2310 2964 +3122 2315 2962 +3119 2321 2960 +3116 2330 2957 +3112 2341 2952 +3106 2355 2946 +3099 2373 2938 +3088 2397 2926 +3073 2426 2910 +3053 2463 2888 +3025 2508 2857 +2984 2562 2812 +2922 2625 2744 +2825 2698 2632 +2649 2780 2420 +2195 2871 1705 +0 2970 0 +0 3075 0 +0 3186 0 +0 3302 0 +0 3421 0 +0 3544 0 +0 3668 0 +3269 2365 3077 +3269 2366 3077 +3269 2366 3076 +3268 2367 3076 +3268 2367 3076 +3268 2368 3076 +3268 2370 3075 +3267 2371 3075 +3266 2374 3074 +3265 2377 3073 +3264 2381 3071 +3262 2387 3069 +3260 2394 3067 +3257 2403 3063 +3253 2416 3058 +3247 2432 3052 +3240 2453 3043 +3229 2479 3031 +3215 2512 3014 +3195 2552 2990 +3168 2601 2957 +3128 2660 2908 +3068 2728 2834 +2973 2805 2710 +2805 2892 2463 +2389 2986 928 +0 3088 0 +0 3197 0 +0 3310 0 +0 3427 0 +0 3548 0 +0 3672 0 +3407 2443 3189 +3407 2444 3189 +3407 2444 3189 +3407 2444 3189 +3407 2445 3189 +3407 2446 3188 +3406 2447 3188 +3406 2448 3188 +3405 2450 3187 +3405 2453 3186 +3404 2457 3185 +3403 2461 3183 +3401 2467 3181 +3399 2475 3179 +3396 2486 3175 +3392 2500 3170 +3386 2518 3163 +3379 2541 3154 +3368 2570 3141 +3354 2605 3123 +3335 2649 3099 +3308 2702 3064 +3268 2765 3012 +3210 2836 2932 +3117 2918 2797 +2954 3008 2514 +2563 3105 0 +0 3210 0 +0 3320 0 +0 3436 0 +0 3555 0 +0 3677 0 +3544 2530 3306 +3544 2530 3306 +3544 2531 3306 +3544 2531 3306 +3544 2532 3306 +3544 2532 3305 +3543 2533 3305 +3543 2534 3305 +3543 2536 3304 +3542 2538 3304 +3541 2541 3303 +3541 2545 3302 +3539 2550 3300 +3538 2557 3298 +3535 2566 3295 +3532 2578 3291 +3528 2593 3286 +3523 2612 3279 +3516 2637 3269 +3505 2668 3256 +3492 2707 3238 +3472 2754 3212 +3445 2810 3175 +3407 2875 3121 +3349 2950 3037 +3258 3034 2892 +3099 3127 2574 +2724 3227 0 +0 3334 0 +0 3446 0 +0 3563 0 +0 3683 0 +3680 2625 3427 +3680 2626 3426 +3680 2626 3426 +3679 2626 3426 +3679 2626 3426 +3679 2627 3426 +3679 2628 3426 +3679 2629 3426 +3679 2630 3425 +3678 2632 3425 +3678 2634 3424 +3677 2637 3423 +3676 2642 3422 +3675 2647 3420 +3673 2655 3418 +3671 2664 3415 +3668 2677 3411 +3664 2693 3406 +3659 2714 3399 +3651 2740 3389 +3641 2773 3375 +3628 2814 3356 +3609 2863 3330 +3582 2922 3292 +3543 2990 3236 +3486 3068 3147 +3397 3155 2994 +3240 3250 2644 +2877 3352 0 +0 3460 0 +0 3574 0 +0 3691 0 +3814 2728 3550 +3814 2728 3550 +3814 2728 3550 +3814 2728 3550 +3814 2729 3549 +3814 2729 3549 +3814 2730 3549 +3814 2730 3549 +3814 2732 3549 +3813 2733 3548 +3813 2735 3548 +3812 2737 3547 +3812 2741 3546 +3811 2745 3545 +3810 2751 3543 +3808 2759 3541 +3806 2769 3538 +3803 2782 3534 +3799 2800 3528 +3793 2822 3521 +3786 2849 3511 +3776 2884 3497 +3763 2927 3478 +3744 2978 3451 +3717 3039 3412 +3679 3109 3354 +3622 3189 3263 +3534 3278 3102 +3379 3374 2724 +3024 3478 0 +0 3588 0 +0 3702 0 +3948 2836 3675 +3948 2836 3675 +3948 2836 3675 +3948 2837 3675 +3948 2837 3675 +3948 2837 3675 +3948 2838 3675 +3948 2838 3674 +3948 2839 3674 +3948 2840 3674 +3947 2842 3673 +3947 2844 3673 +3946 2847 3672 +3946 2850 3671 +3945 2855 3670 +3944 2861 3668 +3942 2869 3666 +3940 2880 3663 +3937 2894 3659 +3933 2912 3653 +3928 2935 3646 +3920 2964 3636 +3910 3000 3622 +3897 3044 3602 +3878 3097 3574 +3852 3160 3535 +3814 3232 3475 +3757 3313 3382 +3669 3403 3216 +3516 3501 2812 +3167 3606 0 +0 3716 0 +4082 2950 3802 +4082 2950 3802 +4082 2950 3802 +4082 2950 3802 +4082 2950 3802 +4082 2951 3802 +4082 2951 3802 +4082 2952 3801 +4081 2952 3801 +4081 2953 3801 +4081 2954 3801 +4081 2956 3800 +4080 2958 3800 +4080 2961 3799 +4079 2964 3798 +4078 2969 3797 +4077 2976 3795 +4075 2984 3793 +4073 2995 3790 +4070 3010 3786 +4066 3028 3780 +4061 3052 3772 +4054 3082 3762 +4044 3119 3748 +4030 3164 3728 +4012 3219 3700 +3985 3283 3660 +3948 3356 3599 +3892 3439 3504 +3804 3530 3334 +3652 3629 2909 +3307 3735 0 +4095 3068 3930 +4095 3068 3930 +4095 3068 3930 +4095 3068 3930 +4095 3068 3930 +4095 3068 3930 +4095 3069 3930 +4095 3069 3930 +4095 3069 3930 +4095 3070 3929 +4095 3071 3929 +4095 3072 3929 +4095 3074 3929 +4095 3076 3928 +4095 3079 3927 +4095 3083 3926 +4095 3088 3925 +4095 3094 3923 +4095 3103 3921 +4095 3114 3918 +4095 3129 3914 +4095 3148 3908 +4095 3173 3900 +4095 3203 3890 +4095 3241 3875 +4095 3288 3855 +4095 3343 3827 +4095 3408 3786 +4081 3482 3725 +4025 3566 3629 +3938 3658 3455 +3786 3758 3012 +4095 3189 4059 +4095 3189 4059 +4095 3189 4059 +4095 3189 4059 +4095 3189 4059 +4095 3189 4059 +4095 3189 4059 +4095 3190 4059 +4095 3190 4059 +4095 3191 4059 +4095 3191 4059 +4095 3192 4058 +4095 3193 4058 +4095 3195 4058 +4095 3197 4057 +4095 3200 4056 +4095 3204 4055 +4095 3209 4054 +4095 3216 4052 +4095 3225 4050 +4095 3237 4047 +4095 3252 4043 +4095 3271 4037 +4095 3296 4029 +4095 3327 4019 +4095 3366 4004 +4095 3413 3984 +4095 3469 3956 +4095 3535 3914 +4095 3610 3853 +4095 3694 3755 +4071 3787 3579 +0 2129 2398 +0 2130 2397 +0 2131 2396 +0 2132 2396 +0 2133 2394 +0 2135 2393 +0 2137 2391 +0 2140 2388 +0 2144 2384 +0 2149 2379 +0 2156 2373 +0 2165 2363 +0 2176 2351 +0 2192 2333 +0 2211 2309 +0 2236 2274 +0 2268 2222 +0 2307 2143 +0 2354 2009 +0 2410 1731 +0 2476 0 +0 2552 0 +0 2636 0 +0 2729 0 +0 2830 0 +0 2937 0 +0 3049 0 +0 3166 0 +0 3286 0 +0 3409 0 +0 3535 0 +0 3661 0 +0 2130 2398 +0 2130 2398 +0 2131 2397 +0 2132 2396 +0 2133 2395 +0 2135 2394 +0 2137 2392 +0 2140 2389 +0 2144 2385 +0 2149 2380 +0 2156 2373 +0 2165 2364 +0 2177 2352 +0 2192 2334 +0 2212 2310 +0 2237 2275 +0 2268 2223 +0 2307 2144 +0 2354 2011 +0 2411 1734 +0 2476 0 +0 2552 0 +0 2636 0 +0 2729 0 +0 2830 0 +0 2937 0 +0 3049 0 +0 3166 0 +0 3286 0 +0 3409 0 +0 3535 0 +0 3661 0 +0 2130 2399 +0 2130 2399 +0 2131 2398 +0 2132 2397 +0 2133 2396 +0 2135 2395 +0 2137 2393 +0 2140 2390 +0 2144 2386 +0 2149 2381 +0 2156 2374 +0 2165 2365 +0 2177 2353 +0 2192 2335 +0 2212 2311 +0 2237 2276 +0 2268 2225 +0 2307 2146 +0 2354 2013 +0 2411 1738 +0 2477 0 +0 2552 0 +0 2637 0 +0 2730 0 +0 2830 0 +0 2937 0 +0 3049 0 +0 3166 0 +0 3286 0 +0 3409 0 +0 3535 0 +0 3661 0 +0 2130 2400 +0 2131 2400 +0 2131 2399 +0 2132 2399 +0 2134 2397 +0 2135 2396 +0 2138 2394 +0 2140 2391 +0 2144 2387 +0 2150 2382 +0 2156 2376 +0 2165 2367 +0 2177 2354 +0 2192 2337 +0 2212 2312 +0 2237 2278 +0 2268 2227 +0 2307 2148 +0 2354 2016 +0 2411 1743 +0 2477 0 +0 2552 0 +0 2637 0 +0 2730 0 +0 2830 0 +0 2937 0 +0 3049 0 +0 3166 0 +0 3286 0 +0 3409 0 +0 3535 0 +0 3661 0 +0 2131 2402 +0 2131 2402 +0 2132 2401 +0 2133 2400 +0 2134 2399 +0 2136 2398 +0 2138 2396 +0 2141 2393 +0 2145 2389 +0 2150 2384 +0 2157 2377 +0 2166 2368 +0 2177 2356 +0 2193 2339 +0 2212 2314 +0 2237 2280 +0 2269 2229 +0 2307 2151 +0 2355 2020 +0 2411 1750 +0 2477 0 +0 2552 0 +0 2637 0 +0 2730 0 +0 2830 0 +0 2937 0 +0 3049 0 +0 3166 0 +0 3286 0 +0 3409 0 +0 3535 0 +0 3661 0 +0 2131 2404 +0 2132 2404 +0 2132 2403 +0 2133 2402 +0 2135 2401 +0 2136 2400 +0 2139 2398 +0 2141 2395 +0 2145 2391 +0 2151 2387 +0 2157 2380 +0 2166 2371 +0 2178 2358 +0 2193 2341 +0 2213 2317 +0 2238 2283 +0 2269 2232 +0 2308 2155 +0 2355 2025 +0 2411 1760 +0 2477 0 +0 2553 0 +0 2637 0 +0 2730 0 +0 2830 0 +0 2937 0 +0 3049 0 +0 3166 0 +0 3286 0 +0 3409 0 +0 3535 0 +0 3661 0 +0 2132 2407 +0 2133 2407 +0 2133 2406 +0 2134 2405 +0 2135 2404 +0 2137 2403 +0 2139 2401 +0 2142 2398 +0 2146 2395 +0 2151 2390 +0 2158 2383 +0 2167 2374 +0 2179 2362 +0 2194 2345 +0 2213 2321 +0 2238 2287 +0 2270 2237 +0 2308 2160 +0 2356 2032 +0 2412 1772 +0 2478 0 +0 2553 0 +0 2637 0 +0 2730 0 +0 2830 0 +0 2937 0 +0 3050 0 +0 3166 0 +0 3286 0 +0 3409 0 +0 3535 0 +0 3661 0 +0 2133 2411 +0 2134 2411 +0 2134 2410 +0 2135 2409 +0 2136 2408 +0 2138 2407 +0 2140 2405 +0 2143 2402 +0 2147 2399 +0 2152 2394 +0 2159 2387 +0 2168 2378 +0 2180 2366 +0 2195 2349 +0 2214 2325 +0 2239 2292 +0 2270 2242 +0 2309 2167 +0 2356 2041 +0 2412 1788 +0 2478 0 +0 2553 0 +0 2638 0 +0 2730 0 +0 2831 0 +0 2937 0 +0 3050 0 +0 3166 0 +0 3287 0 +0 3410 0 +0 3535 0 +0 3662 0 +0 2134 2417 +0 2135 2416 +0 2136 2416 +0 2136 2415 +0 2138 2414 +0 2139 2412 +0 2142 2410 +0 2144 2408 +0 2148 2404 +0 2154 2399 +0 2160 2393 +0 2169 2384 +0 2181 2372 +0 2196 2355 +0 2215 2332 +0 2240 2299 +0 2271 2250 +0 2310 2176 +0 2357 2053 +0 2413 1808 +0 2479 410 +0 2554 0 +0 2638 0 +0 2731 0 +0 2831 0 +0 2938 0 +0 3050 0 +0 3166 0 +0 3287 0 +0 3410 0 +0 3535 0 +0 3662 0 +0 2136 2424 +0 2137 2423 +0 2137 2422 +0 2138 2422 +0 2140 2421 +0 2141 2419 +0 2143 2417 +0 2146 2415 +0 2150 2411 +0 2155 2406 +0 2162 2400 +0 2171 2391 +0 2182 2379 +0 2198 2363 +0 2217 2340 +0 2242 2308 +0 2273 2260 +0 2311 2187 +0 2358 2068 +0 2414 1834 +0 2479 782 +0 2554 0 +0 2639 0 +0 2731 0 +0 2831 0 +0 2938 0 +0 3050 0 +0 3167 0 +0 3287 0 +0 3410 0 +0 3535 0 +0 3662 0 +0 2139 2433 +0 2139 2432 +0 2140 2432 +0 2141 2431 +0 2142 2430 +0 2144 2428 +0 2146 2426 +0 2149 2424 +0 2152 2420 +0 2158 2416 +0 2164 2410 +0 2173 2401 +0 2185 2389 +0 2200 2373 +0 2219 2351 +0 2244 2319 +0 2274 2273 +0 2313 2203 +0 2360 2088 +0 2415 1866 +0 2481 1036 +0 2555 0 +0 2639 0 +0 2732 0 +0 2832 0 +0 2938 0 +0 3050 0 +0 3167 0 +0 3287 0 +0 3410 0 +0 3535 0 +0 3662 0 +0 2142 2444 +0 2142 2444 +0 2143 2443 +0 2144 2443 +0 2145 2442 +0 2147 2440 +0 2149 2438 +0 2152 2436 +0 2156 2433 +0 2161 2428 +0 2167 2422 +0 2176 2414 +0 2188 2402 +0 2202 2387 +0 2222 2365 +0 2246 2334 +0 2277 2290 +0 2315 2222 +0 2362 2113 +0 2417 1906 +0 2482 1242 +0 2557 0 +0 2640 0 +0 2733 0 +0 2833 0 +0 2939 0 +0 3051 0 +0 3167 0 +0 3287 0 +0 3410 0 +0 3535 0 +0 3662 0 +0 2146 2460 +0 2146 2460 +0 2147 2459 +0 2148 2458 +0 2149 2457 +0 2151 2456 +0 2153 2454 +0 2156 2452 +0 2160 2448 +0 2165 2444 +0 2171 2438 +0 2180 2430 +0 2191 2419 +0 2206 2404 +0 2225 2383 +0 2249 2354 +0 2280 2311 +0 2318 2247 +0 2364 2144 +0 2419 1955 +0 2484 1422 +0 2558 0 +0 2642 0 +0 2734 0 +0 2834 0 +0 2940 0 +0 3051 0 +0 3168 0 +0 3288 0 +0 3410 0 +0 3535 0 +0 3662 0 +0 2152 2480 +0 2152 2479 +0 2153 2479 +0 2154 2478 +0 2155 2477 +0 2156 2476 +0 2159 2474 +0 2161 2472 +0 2165 2469 +0 2170 2465 +0 2177 2459 +0 2185 2451 +0 2196 2441 +0 2211 2427 +0 2230 2407 +0 2254 2379 +0 2284 2339 +0 2322 2278 +0 2368 2183 +0 2422 2013 +0 2487 1587 +0 2561 0 +0 2644 0 +0 2735 0 +0 2835 0 +0 2941 0 +0 3052 0 +0 3168 0 +0 3288 0 +0 3411 0 +0 3536 0 +0 3662 0 +590 2159 2505 +556 2159 2505 +505 2160 2504 +427 2161 2503 +295 2162 2503 +26 2164 2501 +0 2166 2500 +0 2169 2498 +0 2172 2495 +0 2177 2491 +0 2184 2485 +0 2192 2478 +0 2203 2468 +0 2218 2455 +0 2236 2436 +0 2260 2410 +0 2290 2373 +0 2327 2317 +0 2372 2230 +0 2427 2080 +0 2490 1742 +0 2564 0 +0 2646 0 +0 2737 0 +0 2836 0 +0 2942 0 +0 3053 0 +0 3169 0 +0 3289 0 +0 3411 0 +0 3536 0 +0 3662 0 +1656 2169 2537 +1653 2169 2536 +1649 2170 2536 +1643 2171 2535 +1635 2172 2534 +1624 2173 2533 +1610 2175 2532 +1589 2178 2530 +1560 2182 2527 +1518 2186 2523 +1454 2193 2518 +1353 2201 2512 +1168 2212 2503 +661 2226 2490 +0 2244 2473 +0 2268 2449 +0 2297 2415 +0 2334 2364 +0 2378 2287 +0 2432 2157 +0 2495 1891 +0 2568 0 +0 2650 0 +0 2740 0 +0 2839 0 +0 2944 0 +0 3055 0 +0 3170 0 +0 3289 0 +0 3412 0 +0 3536 0 +0 3663 0 +2017 2181 2576 +2015 2182 2576 +2013 2182 2575 +2011 2183 2575 +2007 2184 2574 +2002 2186 2573 +1996 2188 2571 +1987 2190 2570 +1975 2194 2567 +1959 2199 2564 +1936 2205 2559 +1903 2213 2553 +1856 2223 2545 +1783 2237 2533 +1663 2255 2518 +1428 2278 2496 +348 2307 2465 +0 2342 2420 +0 2386 2353 +0 2439 2243 +0 2501 2035 +0 2573 1360 +0 2654 0 +0 2744 0 +0 2842 0 +0 2946 0 +0 3056 0 +0 3172 0 +0 3291 0 +0 3413 0 +0 3537 0 +0 3663 0 +2266 2198 2624 +2266 2198 2623 +2264 2199 2623 +2263 2200 2622 +2261 2201 2622 +2258 2202 2621 +2255 2204 2620 +2250 2206 2618 +2243 2210 2616 +2234 2214 2613 +2222 2220 2609 +2204 2228 2603 +2180 2238 2596 +2146 2252 2586 +2096 2269 2572 +2019 2291 2552 +1890 2319 2525 +1628 2354 2486 +0 2397 2428 +0 2448 2337 +0 2509 2176 +0 2580 1795 +0 2660 0 +0 2749 0 +0 2845 0 +0 2949 0 +0 3059 0 +0 3173 0 +0 3292 0 +0 3414 0 +0 3538 0 +0 3664 0 +2470 2219 2680 +2469 2219 2680 +2469 2220 2680 +2468 2220 2679 +2466 2221 2679 +2465 2223 2678 +2462 2225 2677 +2459 2227 2675 +2455 2230 2673 +2450 2235 2671 +2442 2240 2667 +2431 2248 2662 +2417 2258 2656 +2397 2270 2647 +2369 2287 2635 +2328 2308 2618 +2267 2335 2595 +2171 2369 2561 +1998 2410 2513 +1561 2461 2438 +0 2520 2315 +0 2589 2068 +0 2668 582 +0 2755 0 +0 2851 0 +0 2953 0 +0 3062 0 +0 3176 0 +0 3294 0 +0 3415 0 +0 3539 0 +0 3665 0 +2649 2245 2747 +2649 2246 2746 +2648 2246 2746 +2648 2247 2746 +2647 2248 2745 +2646 2249 2745 +2644 2251 2744 +2642 2253 2742 +2639 2256 2741 +2635 2260 2738 +2630 2266 2735 +2623 2273 2731 +2614 2282 2726 +2601 2294 2718 +2583 2310 2708 +2558 2330 2693 +2523 2356 2674 +2470 2388 2646 +2389 2428 2606 +2251 2476 2546 +1960 2534 2451 +0 2601 2283 +0 2678 1867 +0 2763 0 +0 2857 0 +0 2959 0 +0 3066 0 +0 3179 0 +0 3296 0 +0 3417 0 +0 3540 0 +0 3666 0 +2813 2279 2823 +2813 2279 2822 +2813 2280 2822 +2812 2280 2822 +2812 2281 2821 +2811 2282 2821 +2810 2284 2820 +2808 2286 2819 +2806 2289 2817 +2804 2293 2816 +2800 2298 2813 +2796 2304 2809 +2789 2313 2805 +2780 2324 2798 +2769 2339 2790 +2752 2358 2778 +2729 2382 2762 +2697 2413 2739 +2649 2451 2706 +2576 2497 2659 +2457 2552 2587 +2222 2617 2468 +1159 2691 2237 +0 2774 1246 +0 2866 0 +0 2966 0 +0 3072 0 +0 3184 0 +0 3300 0 +0 3420 0 +0 3542 0 +0 3667 0 +2968 2320 2907 +2968 2320 2907 +2968 2321 2907 +2967 2321 2907 +2967 2322 2906 +2966 2323 2906 +2966 2325 2905 +2965 2327 2904 +2963 2329 2903 +2961 2333 2902 +2959 2337 2900 +2956 2343 2897 +2951 2351 2893 +2945 2362 2888 +2937 2375 2880 +2925 2393 2871 +2910 2415 2857 +2888 2444 2839 +2858 2479 2813 +2813 2523 2776 +2746 2575 2722 +2637 2637 2637 +2432 2708 2490 +1780 2789 2168 +0 2878 0 +0 2975 0 +0 3079 0 +0 3190 0 +0 3304 0 +0 3423 0 +0 3545 0 +0 3669 0 +3116 2370 3001 +3116 2370 3001 +3116 2370 3001 +3116 2371 3000 +3116 2372 3000 +3115 2373 3000 +3115 2374 2999 +3114 2376 2998 +3113 2378 2997 +3112 2381 2996 +3110 2385 2994 +3107 2391 2992 +3104 2398 2989 +3100 2407 2985 +3094 2420 2979 +3086 2436 2971 +3075 2456 2961 +3060 2482 2946 +3039 2515 2926 +3010 2555 2897 +2968 2604 2856 +2904 2662 2794 +2802 2730 2696 +2614 2807 2518 +2094 2893 2054 +0 2987 0 +0 3089 0 +0 3197 0 +0 3310 0 +0 3428 0 +0 3549 0 +0 3672 0 +3260 2429 3102 +3260 2429 3102 +3260 2429 3101 +3260 2430 3101 +3260 2430 3101 +3259 2431 3101 +3259 2432 3100 +3258 2434 3100 +3258 2436 3099 +3257 2439 3098 +3255 2442 3096 +3254 2447 3095 +3251 2453 3092 +3248 2462 3089 +3244 2473 3084 +3238 2487 3078 +3231 2505 3070 +3220 2529 3058 +3206 2558 3042 +3185 2595 3021 +3157 2640 2989 +3116 2694 2944 +3054 2757 2876 +2957 2830 2764 +2781 2913 2552 +2327 3003 1837 +0 3102 0 +0 3207 0 +0 3318 0 +0 3434 0 +0 3553 0 +0 3676 0 +3401 2497 3209 +3401 2497 3209 +3401 2498 3209 +3401 2498 3208 +3401 2499 3208 +3400 2499 3208 +3400 2500 3208 +3400 2502 3207 +3399 2503 3207 +3398 2506 3206 +3397 2509 3205 +3396 2513 3203 +3394 2519 3201 +3392 2526 3199 +3389 2535 3195 +3385 2548 3190 +3379 2564 3184 +3372 2585 3175 +3361 2611 3163 +3347 2644 3146 +3328 2684 3123 +3300 2734 3089 +3260 2792 3040 +3200 2860 2966 +3105 2937 2842 +2937 3024 2595 +2521 3118 1060 +0 3220 0 +0 3329 0 +0 3442 0 +0 3560 0 +0 3680 0 +3539 2575 3321 +3539 2575 3321 +3539 2576 3321 +3539 2576 3321 +3539 2576 3321 +3539 2577 3321 +3539 2578 3320 +3538 2579 3320 +3538 2581 3320 +3537 2582 3319 +3537 2585 3318 +3536 2589 3317 +3535 2593 3315 +3533 2599 3313 +3531 2608 3311 +3528 2618 3307 +3524 2632 3302 +3518 2650 3295 +3511 2673 3286 +3500 2702 3273 +3486 2738 3255 +3467 2782 3231 +3440 2834 3196 +3400 2897 3144 +3342 2969 3064 +3249 3050 2929 +3086 3140 2646 +2695 3237 0 +0 3342 0 +0 3452 0 +0 3568 0 +0 3687 0 +3676 2662 3438 +3676 2662 3438 +3676 2663 3438 +3676 2663 3438 +3676 2663 3438 +3676 2664 3438 +3676 2664 3438 +3675 2665 3437 +3675 2667 3437 +3675 2668 3436 +3674 2670 3436 +3674 2673 3435 +3673 2677 3434 +3671 2682 3432 +3670 2689 3430 +3668 2698 3427 +3665 2710 3423 +3661 2725 3418 +3655 2744 3411 +3648 2769 3401 +3638 2800 3388 +3624 2839 3370 +3605 2886 3344 +3578 2942 3308 +3539 3007 3253 +3481 3082 3169 +3390 3167 3024 +3231 3259 2706 +2856 3359 0 +0 3466 0 +0 3578 0 +0 3695 0 +3812 2757 3559 +3812 2757 3559 +3812 2758 3559 +3812 2758 3558 +3812 2758 3558 +3811 2759 3558 +3811 2759 3558 +3811 2760 3558 +3811 2761 3558 +3811 2762 3557 +3810 2764 3557 +3810 2766 3556 +3809 2770 3555 +3808 2774 3554 +3807 2779 3552 +3805 2787 3550 +3803 2796 3547 +3800 2809 3543 +3796 2825 3538 +3791 2846 3531 +3783 2872 3521 +3773 2905 3507 +3760 2946 3488 +3741 2996 3462 +3714 3054 3424 +3675 3122 3368 +3618 3200 3279 +3529 3287 3126 +3372 3382 2777 +3009 3484 0 +0 3592 0 +0 3706 0 +3946 2860 3682 +3946 2860 3682 +3946 2860 3682 +3946 2860 3682 +3946 2860 3682 +3946 2861 3682 +3946 2861 3681 +3946 2862 3681 +3946 2863 3681 +3946 2864 3681 +3945 2865 3680 +3945 2867 3680 +3944 2869 3679 +3944 2873 3678 +3943 2877 3677 +3942 2883 3675 +3940 2891 3673 +3938 2901 3670 +3935 2914 3666 +3931 2932 3661 +3926 2954 3653 +3918 2981 3643 +3908 3016 3629 +3895 3059 3610 +3876 3110 3583 +3849 3171 3544 +3811 3242 3486 +3754 3321 3395 +3666 3410 3235 +3511 3507 2856 +3156 3610 0 +0 3720 0 +4080 2968 3807 +4080 2968 3807 +4080 2968 3807 +4080 2969 3807 +4080 2969 3807 +4080 2969 3807 +4080 2969 3807 +4080 2970 3807 +4080 2970 3806 +4080 2971 3806 +4080 2972 3806 +4079 2974 3806 +4079 2976 3805 +4078 2979 3804 +4078 2982 3803 +4077 2987 3802 +4076 2993 3800 +4074 3001 3798 +4072 3012 3795 +4069 3026 3791 +4065 3044 3786 +4060 3067 3778 +4052 3096 3768 +4042 3132 3754 +4029 3176 3734 +4010 3229 3706 +3984 3292 3667 +3946 3364 3608 +3889 3445 3514 +3801 3535 3348 +3648 3633 2944 +3299 3738 0 +4095 3082 3934 +4095 3082 3934 +4095 3082 3934 +4095 3082 3934 +4095 3082 3934 +4095 3082 3934 +4095 3083 3934 +4095 3083 3934 +4095 3084 3934 +4095 3084 3933 +4095 3085 3933 +4095 3086 3933 +4095 3088 3932 +4095 3090 3932 +4095 3093 3931 +4095 3096 3930 +4095 3101 3929 +4095 3108 3927 +4095 3116 3925 +4095 3127 3922 +4095 3142 3918 +4095 3160 3912 +4095 3184 3905 +4095 3214 3894 +4095 3251 3880 +4095 3297 3860 +4095 3351 3832 +4095 3415 3792 +4080 3488 3732 +4024 3571 3636 +3936 3662 3466 +3784 3761 3041 +4095 3200 4062 +4095 3200 4062 +4095 3200 4062 +4095 3200 4062 +4095 3200 4062 +4095 3200 4062 +4095 3200 4062 +4095 3201 4062 +4095 3201 4062 +4095 3202 4062 +4095 3202 4062 +4095 3203 4061 +4095 3204 4061 +4095 3206 4061 +4095 3208 4060 +4095 3211 4059 +4095 3215 4058 +4095 3220 4057 +4095 3226 4055 +4095 3235 4053 +4095 3247 4050 +4095 3261 4046 +4095 3280 4040 +4095 3305 4032 +4095 3335 4022 +4095 3374 4008 +4095 3420 3988 +4095 3475 3959 +4095 3540 3918 +4095 3614 3858 +4095 3698 3761 +4070 3790 3587 +0 2261 2529 +0 2261 2529 +0 2262 2529 +0 2263 2528 +0 2264 2527 +0 2265 2526 +0 2267 2524 +0 2269 2522 +0 2272 2520 +0 2276 2516 +0 2281 2511 +0 2288 2504 +0 2297 2495 +0 2308 2482 +0 2324 2465 +0 2343 2440 +0 2368 2405 +0 2400 2354 +0 2439 2274 +0 2486 2140 +0 2542 1860 +0 2608 0 +0 2684 0 +0 2768 0 +0 2861 0 +0 2962 0 +0 3069 0 +0 3181 0 +0 3298 0 +0 3418 0 +0 3541 0 +0 3667 0 +0 2261 2530 +0 2262 2530 +0 2262 2529 +0 2263 2529 +0 2264 2528 +0 2265 2527 +0 2267 2525 +0 2269 2523 +0 2272 2520 +0 2276 2517 +0 2281 2512 +0 2288 2505 +0 2297 2495 +0 2309 2483 +0 2324 2465 +0 2343 2441 +0 2368 2406 +0 2400 2354 +0 2439 2275 +0 2486 2141 +0 2543 1863 +0 2608 0 +0 2684 0 +0 2769 0 +0 2862 0 +0 2962 0 +0 3069 0 +0 3181 0 +0 3298 0 +0 3418 0 +0 3541 0 +0 3667 0 +0 2261 2531 +0 2262 2530 +0 2262 2530 +0 2263 2529 +0 2264 2528 +0 2265 2527 +0 2267 2526 +0 2269 2524 +0 2272 2521 +0 2276 2517 +0 2281 2512 +0 2288 2505 +0 2297 2496 +0 2309 2484 +0 2324 2466 +0 2344 2442 +0 2369 2407 +0 2400 2355 +0 2439 2276 +0 2486 2143 +0 2543 1866 +0 2609 0 +0 2684 0 +0 2769 0 +0 2862 0 +0 2962 0 +0 3069 0 +0 3181 0 +0 3298 0 +0 3418 0 +0 3541 0 +0 3667 0 +0 2262 2532 +0 2262 2531 +0 2263 2531 +0 2263 2530 +0 2264 2529 +0 2265 2528 +0 2267 2527 +0 2269 2525 +0 2272 2522 +0 2276 2518 +0 2281 2513 +0 2288 2506 +0 2297 2497 +0 2309 2485 +0 2324 2467 +0 2344 2443 +0 2369 2408 +0 2400 2357 +0 2439 2278 +0 2486 2145 +0 2543 1870 +0 2609 0 +0 2684 0 +0 2769 0 +0 2862 0 +0 2962 0 +0 3069 0 +0 3181 0 +0 3298 0 +0 3418 0 +0 3541 0 +0 3667 0 +0 2262 2533 +0 2262 2533 +0 2263 2532 +0 2264 2531 +0 2264 2531 +0 2266 2529 +0 2267 2528 +0 2270 2526 +0 2273 2523 +0 2276 2520 +0 2282 2515 +0 2288 2508 +0 2297 2499 +0 2309 2486 +0 2324 2469 +0 2344 2444 +0 2369 2410 +0 2400 2359 +0 2439 2280 +0 2487 2148 +0 2543 1875 +0 2609 0 +0 2684 0 +0 2769 0 +0 2862 0 +0 2962 0 +0 3069 0 +0 3181 0 +0 3298 0 +0 3418 0 +0 3541 0 +0 3667 0 +0 2262 2535 +0 2263 2534 +0 2263 2534 +0 2264 2533 +0 2265 2532 +0 2266 2531 +0 2268 2530 +0 2270 2528 +0 2273 2525 +0 2277 2521 +0 2282 2516 +0 2289 2510 +0 2298 2500 +0 2310 2488 +0 2325 2471 +0 2344 2446 +0 2369 2412 +0 2401 2361 +0 2440 2283 +0 2487 2152 +0 2543 1882 +0 2609 0 +0 2684 0 +0 2769 0 +0 2862 0 +0 2962 0 +0 3069 0 +0 3181 0 +0 3298 0 +0 3418 0 +0 3541 0 +0 3667 0 +0 2263 2537 +0 2263 2537 +0 2264 2536 +0 2265 2535 +0 2265 2535 +0 2267 2533 +0 2268 2532 +0 2271 2530 +0 2274 2527 +0 2277 2524 +0 2283 2519 +0 2289 2512 +0 2298 2503 +0 2310 2490 +0 2325 2473 +0 2345 2449 +0 2370 2415 +0 2401 2364 +0 2440 2287 +0 2487 2157 +0 2543 1892 +0 2609 0 +0 2685 0 +0 2769 0 +0 2862 0 +0 2962 0 +0 3069 0 +0 3182 0 +0 3298 0 +0 3418 0 +0 3542 0 +0 3667 0 +0 2264 2540 +0 2264 2539 +0 2265 2539 +0 2265 2538 +0 2266 2538 +0 2267 2536 +0 2269 2535 +0 2271 2533 +0 2274 2530 +0 2278 2527 +0 2283 2522 +0 2290 2515 +0 2299 2506 +0 2311 2494 +0 2326 2477 +0 2346 2453 +0 2370 2419 +0 2402 2369 +0 2440 2292 +0 2488 2164 +0 2544 1904 +0 2610 0 +0 2685 0 +0 2769 0 +0 2862 0 +0 2963 0 +0 3069 0 +0 3182 0 +0 3298 0 +0 3419 0 +0 3542 0 +0 3667 0 +0 2265 2544 +0 2265 2543 +0 2266 2543 +0 2266 2542 +0 2267 2542 +0 2268 2540 +0 2270 2539 +0 2272 2537 +0 2275 2534 +0 2279 2531 +0 2284 2526 +0 2291 2519 +0 2300 2510 +0 2312 2498 +0 2327 2481 +0 2346 2458 +0 2371 2424 +0 2402 2375 +0 2441 2299 +0 2488 2173 +0 2544 1920 +0 2610 0 +0 2685 0 +0 2770 0 +0 2862 0 +0 2963 0 +0 3070 0 +0 3182 0 +0 3298 0 +0 3419 0 +0 3542 0 +0 3667 0 +0 2266 2549 +0 2266 2549 +0 2267 2548 +0 2268 2548 +0 2269 2547 +0 2270 2546 +0 2271 2544 +0 2274 2542 +0 2277 2540 +0 2280 2536 +0 2286 2531 +0 2292 2525 +0 2301 2516 +0 2313 2504 +0 2328 2487 +0 2348 2464 +0 2372 2431 +0 2403 2382 +0 2442 2308 +0 2489 2185 +0 2545 1940 +0 2611 542 +0 2686 0 +0 2770 0 +0 2863 0 +0 2963 0 +0 3070 0 +0 3182 0 +0 3299 0 +0 3419 0 +0 3542 0 +0 3667 0 +0 2268 2556 +0 2268 2556 +0 2269 2555 +0 2269 2555 +0 2270 2554 +0 2272 2553 +0 2273 2551 +0 2275 2549 +0 2278 2547 +0 2282 2543 +0 2287 2538 +0 2294 2532 +0 2303 2523 +0 2315 2512 +0 2330 2495 +0 2349 2472 +0 2374 2440 +0 2405 2392 +0 2443 2320 +0 2490 2200 +0 2546 1966 +0 2612 914 +0 2687 0 +0 2771 0 +0 2863 0 +0 2963 0 +0 3070 0 +0 3182 0 +0 3299 0 +0 3419 0 +0 3542 0 +0 3667 0 +0 2270 2565 +0 2271 2565 +0 2271 2564 +0 2272 2564 +0 2273 2563 +0 2274 2562 +0 2276 2560 +0 2278 2559 +0 2281 2556 +0 2285 2553 +0 2290 2548 +0 2296 2542 +0 2305 2533 +0 2317 2522 +0 2332 2505 +0 2351 2483 +0 2376 2451 +0 2407 2405 +0 2445 2335 +0 2492 2220 +0 2547 1998 +0 2613 1168 +0 2688 0 +0 2772 0 +0 2864 0 +0 2964 0 +0 3071 0 +0 3183 0 +0 3299 0 +0 3419 0 +0 3542 0 +0 3667 0 +0 2273 2577 +0 2274 2577 +0 2274 2576 +0 2275 2576 +0 2276 2575 +0 2277 2574 +0 2279 2572 +0 2281 2571 +0 2284 2568 +0 2288 2565 +0 2293 2560 +0 2299 2554 +0 2308 2546 +0 2320 2535 +0 2335 2519 +0 2354 2497 +0 2378 2467 +0 2409 2422 +0 2447 2354 +0 2494 2245 +0 2549 2038 +0 2614 1374 +0 2689 0 +0 2773 0 +0 2865 0 +0 2965 0 +0 3071 0 +0 3183 0 +0 3299 0 +0 3419 0 +0 3542 0 +0 3667 0 +0 2278 2592 +0 2278 2592 +0 2279 2592 +0 2279 2591 +0 2280 2590 +0 2281 2589 +0 2283 2588 +0 2285 2586 +0 2288 2584 +0 2292 2581 +0 2297 2576 +0 2303 2570 +0 2312 2562 +0 2323 2551 +0 2338 2536 +0 2357 2516 +0 2382 2486 +0 2412 2443 +0 2450 2379 +0 2496 2276 +0 2551 2087 +0 2616 1554 +0 2690 0 +0 2774 0 +0 2866 0 +0 2966 0 +0 3072 0 +0 3184 0 +0 3300 0 +0 3420 0 +0 3542 0 +0 3667 0 +0 2283 2612 +0 2284 2612 +0 2284 2611 +0 2285 2611 +0 2286 2610 +0 2287 2609 +0 2289 2608 +0 2291 2606 +0 2293 2604 +0 2297 2601 +0 2302 2597 +0 2309 2591 +0 2317 2584 +0 2329 2573 +0 2343 2559 +0 2362 2539 +0 2386 2511 +0 2416 2471 +0 2454 2410 +0 2500 2315 +0 2555 2145 +0 2619 1719 +0 2693 0 +0 2776 0 +0 2868 0 +0 2967 0 +0 3073 0 +0 3184 0 +0 3300 0 +0 3420 0 +0 3543 0 +0 3668 0 +746 2291 2637 +722 2291 2637 +688 2292 2637 +637 2292 2636 +559 2293 2636 +428 2294 2635 +158 2296 2633 +0 2298 2632 +0 2301 2630 +0 2304 2627 +0 2309 2623 +0 2316 2618 +0 2324 2610 +0 2335 2601 +0 2350 2587 +0 2368 2568 +0 2392 2542 +0 2422 2505 +0 2459 2449 +0 2504 2362 +0 2559 2212 +0 2622 1874 +0 2696 0 +0 2778 0 +0 2870 0 +0 2969 0 +0 3074 0 +0 3185 0 +0 3301 0 +0 3421 0 +0 3543 0 +0 3668 0 +1791 2300 2669 +1789 2301 2669 +1785 2301 2668 +1781 2302 2668 +1775 2303 2667 +1767 2304 2667 +1757 2305 2665 +1742 2307 2664 +1721 2310 2662 +1692 2314 2659 +1650 2319 2656 +1586 2325 2651 +1485 2333 2644 +1300 2344 2635 +793 2358 2622 +0 2376 2605 +0 2400 2581 +0 2429 2547 +0 2466 2496 +0 2510 2419 +0 2564 2289 +0 2627 2023 +0 2700 0 +0 2782 0 +0 2872 0 +0 2971 0 +0 3076 0 +0 3187 0 +0 3302 0 +0 3422 0 +0 3544 0 +0 3668 0 +2150 2313 2708 +2149 2313 2708 +2147 2314 2708 +2145 2314 2707 +2143 2315 2707 +2139 2316 2706 +2135 2318 2705 +2128 2320 2704 +2119 2323 2702 +2108 2326 2699 +2091 2331 2696 +2068 2337 2691 +2036 2345 2685 +1988 2356 2677 +1915 2369 2666 +1795 2387 2650 +1560 2410 2628 +480 2439 2597 +0 2474 2553 +0 2518 2485 +0 2571 2375 +0 2633 2167 +0 2705 1492 +0 2786 0 +0 2876 0 +0 2974 0 +0 3078 0 +0 3189 0 +0 3304 0 +0 3423 0 +0 3545 0 +0 3669 0 +2399 2329 2756 +2398 2330 2756 +2398 2330 2755 +2396 2331 2755 +2395 2332 2754 +2393 2333 2754 +2390 2334 2753 +2387 2336 2752 +2382 2339 2750 +2375 2342 2748 +2366 2346 2745 +2354 2352 2741 +2337 2360 2735 +2313 2370 2728 +2278 2384 2718 +2228 2401 2704 +2151 2423 2684 +2023 2451 2657 +1760 2486 2618 +0 2529 2560 +0 2581 2469 +0 2642 2308 +0 2712 1927 +0 2792 0 +0 2881 0 +0 2978 0 +0 3081 0 +0 3191 0 +0 3306 0 +0 3424 0 +0 3546 0 +0 3670 0 +2602 2350 2813 +2602 2351 2812 +2602 2351 2812 +2601 2352 2812 +2600 2353 2811 +2599 2354 2811 +2597 2355 2810 +2595 2357 2809 +2591 2359 2807 +2587 2362 2805 +2582 2367 2803 +2574 2372 2799 +2563 2380 2794 +2549 2390 2788 +2529 2402 2779 +2501 2419 2767 +2460 2440 2750 +2400 2467 2727 +2303 2501 2694 +2131 2543 2645 +1693 2593 2570 +0 2652 2447 +0 2721 2200 +0 2800 714 +0 2887 0 +0 2983 0 +0 3085 0 +0 3194 0 +0 3308 0 +0 3426 0 +0 3547 0 +0 3671 0 +2781 2377 2879 +2781 2377 2879 +2781 2378 2879 +2780 2378 2878 +2780 2379 2878 +2779 2380 2877 +2778 2381 2877 +2776 2383 2876 +2774 2385 2874 +2771 2388 2873 +2767 2392 2870 +2762 2398 2867 +2755 2405 2863 +2746 2414 2858 +2733 2426 2850 +2715 2442 2840 +2691 2462 2826 +2655 2488 2806 +2602 2520 2778 +2521 2560 2738 +2384 2609 2678 +2092 2666 2584 +0 2733 2415 +0 2810 1999 +0 2895 0 +0 2989 0 +0 3091 0 +0 3198 0 +0 3311 0 +0 3429 0 +0 3549 0 +0 3673 0 +2946 2411 2955 +2945 2411 2955 +2945 2411 2954 +2945 2412 2954 +2944 2412 2954 +2944 2413 2953 +2943 2414 2953 +2942 2416 2952 +2940 2418 2951 +2939 2421 2950 +2936 2425 2948 +2932 2430 2945 +2928 2436 2942 +2921 2445 2937 +2913 2456 2930 +2901 2471 2922 +2884 2490 2910 +2861 2514 2894 +2829 2545 2871 +2781 2583 2838 +2709 2629 2791 +2589 2684 2719 +2354 2749 2601 +1291 2823 2369 +0 2906 1378 +0 2998 0 +0 3098 0 +0 3204 0 +0 3316 0 +0 3432 0 +0 3552 0 +0 3675 0 +3100 2452 3040 +3100 2452 3040 +3100 2452 3039 +3100 2453 3039 +3099 2453 3039 +3099 2454 3039 +3098 2455 3038 +3098 2457 3037 +3097 2459 3037 +3095 2461 3035 +3093 2465 3034 +3091 2469 3032 +3088 2475 3029 +3083 2483 3025 +3077 2494 3020 +3069 2507 3013 +3058 2525 3003 +3042 2547 2990 +3020 2576 2971 +2990 2611 2945 +2945 2655 2909 +2878 2707 2854 +2769 2769 2769 +2564 2840 2622 +1912 2921 2300 +0 3010 0 +0 3107 0 +0 3212 0 +0 3322 0 +0 3437 0 +0 3555 0 +0 3677 0 +3249 2501 3133 +3248 2502 3133 +3248 2502 3133 +3248 2502 3133 +3248 2503 3132 +3248 2504 3132 +3247 2505 3132 +3247 2506 3131 +3246 2508 3130 +3245 2510 3129 +3244 2513 3128 +3242 2517 3126 +3239 2523 3124 +3236 2530 3121 +3232 2539 3117 +3226 2552 3111 +3218 2568 3103 +3207 2588 3093 +3192 2614 3078 +3172 2647 3058 +3142 2687 3029 +3100 2736 2988 +3036 2794 2926 +2934 2862 2828 +2746 2939 2650 +2226 3025 2186 +0 3120 0 +0 3221 0 +0 3329 0 +0 3443 0 +0 3560 0 +0 3681 0 +3392 2560 3234 +3392 2561 3234 +3392 2561 3234 +3392 2561 3233 +3392 2562 3233 +3392 2562 3233 +3391 2563 3233 +3391 2564 3232 +3391 2566 3232 +3390 2568 3231 +3389 2571 3230 +3388 2574 3229 +3386 2579 3227 +3383 2586 3224 +3380 2594 3221 +3376 2605 3216 +3370 2619 3210 +3363 2637 3202 +3352 2661 3190 +3338 2691 3175 +3317 2727 3153 +3289 2772 3121 +3248 2826 3076 +3187 2890 3008 +3089 2962 2896 +2913 3045 2685 +2459 3135 1969 +0 3234 0 +0 3339 0 +0 3450 0 +0 3566 0 +0 3685 0 +3533 2629 3341 +3533 2629 3341 +3533 2629 3341 +3533 2630 3341 +3533 2630 3341 +3533 2631 3340 +3532 2631 3340 +3532 2632 3340 +3532 2634 3339 +3531 2636 3339 +3530 2638 3338 +3530 2641 3337 +3528 2645 3335 +3527 2651 3333 +3524 2658 3331 +3521 2668 3327 +3517 2680 3322 +3512 2696 3316 +3504 2717 3307 +3494 2743 3295 +3479 2776 3278 +3460 2817 3255 +3432 2866 3221 +3392 2924 3173 +3332 2992 3098 +3237 3069 2974 +3069 3156 2727 +2654 3251 1192 +0 3353 0 +0 3461 0 +0 3574 0 +0 3692 0 +3672 2707 3453 +3672 2707 3453 +3671 2707 3453 +3671 2708 3453 +3671 2708 3453 +3671 2709 3453 +3671 2709 3453 +3671 2710 3453 +3671 2711 3452 +3670 2713 3452 +3670 2715 3451 +3669 2717 3450 +3668 2721 3449 +3667 2725 3448 +3665 2732 3446 +3663 2740 3443 +3660 2750 3439 +3656 2764 3434 +3650 2782 3427 +3643 2805 3418 +3633 2834 3405 +3619 2870 3388 +3599 2914 3363 +3572 2967 3328 +3532 3029 3276 +3474 3101 3196 +3382 3182 3061 +3218 3272 2778 +2827 3370 0 +0 3474 0 +0 3585 0 +0 3700 0 +3808 2794 3570 +3808 2794 3570 +3808 2794 3570 +3808 2795 3570 +3808 2795 3570 +3808 2795 3570 +3808 2796 3570 +3808 2796 3570 +3808 2797 3569 +3807 2799 3569 +3807 2800 3569 +3806 2803 3568 +3806 2805 3567 +3805 2809 3566 +3804 2814 3564 +3802 2821 3562 +3800 2830 3559 +3797 2842 3555 +3793 2857 3550 +3787 2876 3543 +3780 2901 3533 +3770 2932 3520 +3756 2971 3502 +3737 3018 3476 +3710 3074 3440 +3671 3139 3385 +3613 3214 3301 +3522 3299 3156 +3363 3391 2839 +2989 3492 0 +0 3598 0 +0 3710 0 +3944 2889 3691 +3944 2889 3691 +3944 2890 3691 +3944 2890 3691 +3944 2890 3691 +3944 2890 3691 +3944 2891 3690 +3943 2891 3690 +3943 2892 3690 +3943 2893 3690 +3943 2894 3689 +3942 2896 3689 +3942 2898 3688 +3941 2902 3687 +3940 2906 3686 +3939 2911 3684 +3937 2919 3682 +3935 2928 3679 +3932 2941 3675 +3928 2957 3670 +3923 2978 3663 +3916 3004 3653 +3906 3037 3639 +3892 3078 3620 +3873 3128 3594 +3846 3186 3556 +3808 3255 3500 +3750 3332 3412 +3661 3419 3258 +3504 3514 2909 +3141 3616 0 +0 3724 0 +4079 2992 3814 +4079 2992 3814 +4078 2992 3814 +4078 2992 3814 +4078 2992 3814 +4078 2992 3814 +4078 2993 3814 +4078 2993 3813 +4078 2994 3813 +4078 2995 3813 +4078 2996 3813 +4077 2997 3812 +4077 2999 3812 +4077 3002 3811 +4076 3005 3810 +4075 3009 3809 +4074 3015 3807 +4072 3023 3805 +4070 3033 3802 +4067 3047 3798 +4063 3064 3793 +4058 3086 3785 +4050 3114 3775 +4040 3148 3761 +4027 3191 3742 +4008 3242 3715 +3981 3303 3676 +3943 3374 3618 +3886 3453 3527 +3798 3542 3367 +3643 3639 2988 +3288 3742 0 +4095 3100 3939 +4095 3100 3939 +4095 3100 3939 +4095 3101 3939 +4095 3101 3939 +4095 3101 3939 +4095 3101 3939 +4095 3101 3939 +4095 3102 3939 +4095 3103 3939 +4095 3103 3938 +4095 3105 3938 +4095 3106 3938 +4095 3108 3937 +4095 3111 3936 +4095 3114 3936 +4095 3119 3934 +4095 3125 3933 +4095 3133 3930 +4095 3144 3927 +4095 3158 3923 +4095 3176 3918 +4095 3199 3910 +4095 3228 3900 +4095 3264 3886 +4095 3308 3866 +4095 3361 3839 +4095 3424 3799 +4078 3496 3740 +4021 3577 3646 +3933 3667 3480 +3780 3765 3076 +4095 3214 4066 +4095 3214 4066 +4095 3214 4066 +4095 3214 4066 +4095 3214 4066 +4095 3214 4066 +4095 3215 4066 +4095 3215 4066 +4095 3215 4066 +4095 3216 4066 +4095 3216 4066 +4095 3217 4065 +4095 3218 4065 +4095 3220 4065 +4095 3222 4064 +4095 3225 4063 +4095 3229 4062 +4095 3233 4061 +4095 3240 4059 +4095 3248 4057 +4095 3259 4054 +4095 3274 4050 +4095 3292 4044 +4095 3316 4037 +4095 3346 4026 +4095 3383 4012 +4095 3429 3992 +4095 3483 3964 +4095 3547 3924 +4095 3620 3864 +4095 3703 3768 +4068 3794 3598 +0 2393 2661 +0 2393 2661 +0 2393 2661 +0 2394 2660 +0 2395 2660 +0 2396 2659 +0 2397 2658 +0 2399 2656 +0 2401 2654 +0 2404 2651 +0 2408 2648 +0 2413 2643 +0 2420 2636 +0 2429 2627 +0 2440 2614 +0 2456 2596 +0 2475 2572 +0 2500 2537 +0 2532 2485 +0 2571 2406 +0 2618 2271 +0 2674 1991 +0 2740 0 +0 2816 0 +0 2901 0 +0 2994 0 +0 3094 0 +0 3201 0 +0 3313 0 +0 3430 0 +0 3550 0 +0 3673 0 +0 2393 2662 +0 2393 2662 +0 2394 2661 +0 2394 2661 +0 2395 2660 +0 2396 2659 +0 2397 2658 +0 2399 2657 +0 2401 2655 +0 2404 2652 +0 2408 2648 +0 2413 2643 +0 2420 2636 +0 2429 2627 +0 2441 2614 +0 2456 2597 +0 2475 2572 +0 2500 2537 +0 2532 2486 +0 2571 2406 +0 2618 2272 +0 2675 1992 +0 2740 0 +0 2816 0 +0 2901 0 +0 2994 0 +0 3094 0 +0 3201 0 +0 3313 0 +0 3430 0 +0 3550 0 +0 3673 0 +0 2393 2662 +0 2393 2662 +0 2394 2662 +0 2394 2661 +0 2395 2661 +0 2396 2660 +0 2397 2659 +0 2399 2657 +0 2401 2655 +0 2404 2652 +0 2408 2649 +0 2413 2644 +0 2420 2637 +0 2429 2628 +0 2441 2615 +0 2456 2597 +0 2476 2573 +0 2501 2538 +0 2532 2487 +0 2571 2407 +0 2618 2273 +0 2675 1995 +0 2741 0 +0 2816 0 +0 2901 0 +0 2994 0 +0 3094 0 +0 3201 0 +0 3313 0 +0 3430 0 +0 3550 0 +0 3673 0 +0 2393 2663 +0 2393 2663 +0 2394 2662 +0 2394 2662 +0 2395 2661 +0 2396 2661 +0 2397 2659 +0 2399 2658 +0 2401 2656 +0 2404 2653 +0 2408 2649 +0 2413 2644 +0 2420 2638 +0 2429 2628 +0 2441 2616 +0 2456 2598 +0 2476 2574 +0 2501 2539 +0 2532 2488 +0 2571 2408 +0 2618 2275 +0 2675 1998 +0 2741 0 +0 2816 0 +0 2901 0 +0 2994 0 +0 3094 0 +0 3201 0 +0 3313 0 +0 3430 0 +0 3550 0 +0 3674 0 +0 2393 2664 +0 2394 2664 +0 2394 2663 +0 2395 2663 +0 2395 2662 +0 2396 2661 +0 2398 2660 +0 2399 2659 +0 2401 2657 +0 2404 2654 +0 2408 2650 +0 2413 2645 +0 2420 2639 +0 2429 2629 +0 2441 2617 +0 2456 2599 +0 2476 2575 +0 2501 2540 +0 2532 2489 +0 2571 2410 +0 2618 2277 +0 2675 2002 +0 2741 0 +0 2816 0 +0 2901 0 +0 2994 0 +0 3094 0 +0 3201 0 +0 3313 0 +0 3430 0 +0 3550 0 +0 3674 0 +0 2394 2665 +0 2394 2665 +0 2394 2665 +0 2395 2664 +0 2396 2664 +0 2397 2663 +0 2398 2662 +0 2399 2660 +0 2402 2658 +0 2405 2655 +0 2409 2652 +0 2414 2647 +0 2421 2640 +0 2430 2631 +0 2441 2618 +0 2457 2601 +0 2476 2576 +0 2501 2542 +0 2533 2491 +0 2571 2412 +0 2619 2280 +0 2675 2007 +0 2741 0 +0 2816 0 +0 2901 0 +0 2994 0 +0 3094 0 +0 3201 0 +0 3314 0 +0 3430 0 +0 3551 0 +0 3674 0 +0 2394 2667 +0 2394 2667 +0 2395 2666 +0 2395 2666 +0 2396 2665 +0 2397 2664 +0 2398 2663 +0 2400 2662 +0 2402 2660 +0 2405 2657 +0 2409 2653 +0 2414 2648 +0 2421 2642 +0 2430 2633 +0 2442 2620 +0 2457 2603 +0 2477 2579 +0 2501 2544 +0 2533 2493 +0 2572 2415 +0 2619 2284 +0 2675 2014 +0 2741 0 +0 2816 0 +0 2901 0 +0 2994 0 +0 3094 0 +0 3201 0 +0 3314 0 +0 3430 0 +0 3551 0 +0 3674 0 +0 2395 2669 +0 2395 2669 +0 2395 2669 +0 2396 2668 +0 2397 2668 +0 2398 2667 +0 2399 2666 +0 2400 2664 +0 2403 2662 +0 2406 2659 +0 2410 2656 +0 2415 2651 +0 2422 2644 +0 2430 2635 +0 2442 2623 +0 2457 2605 +0 2477 2581 +0 2502 2547 +0 2533 2497 +0 2572 2419 +0 2619 2289 +0 2676 2024 +0 2741 0 +0 2817 0 +0 2901 0 +0 2994 0 +0 3095 0 +0 3201 0 +0 3314 0 +0 3430 0 +0 3551 0 +0 3674 0 +0 2395 2672 +0 2396 2672 +0 2396 2672 +0 2397 2671 +0 2397 2670 +0 2398 2670 +0 2400 2669 +0 2401 2667 +0 2403 2665 +0 2406 2662 +0 2410 2659 +0 2415 2654 +0 2422 2647 +0 2431 2638 +0 2443 2626 +0 2458 2609 +0 2478 2585 +0 2503 2551 +0 2534 2501 +0 2573 2424 +0 2620 2296 +0 2676 2036 +0 2742 0 +0 2817 0 +0 2901 0 +0 2994 0 +0 3095 0 +0 3202 0 +0 3314 0 +0 3430 0 +0 3551 0 +0 3674 0 +0 2397 2676 +0 2397 2676 +0 2397 2676 +0 2398 2675 +0 2398 2674 +0 2399 2674 +0 2401 2673 +0 2402 2671 +0 2404 2669 +0 2407 2666 +0 2411 2663 +0 2416 2658 +0 2423 2651 +0 2432 2642 +0 2444 2630 +0 2459 2613 +0 2478 2590 +0 2503 2556 +0 2535 2507 +0 2573 2431 +0 2620 2305 +0 2677 2052 +0 2742 0 +0 2817 0 +0 2902 0 +0 2995 0 +0 3095 0 +0 3202 0 +0 3314 0 +0 3431 0 +0 3551 0 +0 3674 0 +0 2398 2681 +0 2398 2681 +0 2399 2681 +0 2399 2680 +0 2400 2680 +0 2401 2679 +0 2402 2678 +0 2404 2676 +0 2406 2674 +0 2409 2672 +0 2413 2668 +0 2418 2663 +0 2424 2657 +0 2433 2648 +0 2445 2636 +0 2460 2619 +0 2480 2596 +0 2504 2563 +0 2536 2514 +0 2574 2440 +0 2621 2317 +0 2677 2072 +0 2743 674 +0 2818 0 +0 2902 0 +0 2995 0 +0 3095 0 +0 3202 0 +0 3314 0 +0 3431 0 +0 3551 0 +0 3674 0 +0 2400 2688 +0 2400 2688 +0 2400 2688 +0 2401 2687 +0 2402 2687 +0 2402 2686 +0 2404 2685 +0 2405 2683 +0 2408 2681 +0 2410 2679 +0 2414 2675 +0 2419 2671 +0 2426 2664 +0 2435 2656 +0 2447 2644 +0 2462 2627 +0 2481 2604 +0 2506 2572 +0 2537 2524 +0 2575 2452 +0 2622 2332 +0 2678 2098 +0 2744 1046 +0 2819 0 +0 2903 0 +0 2995 0 +0 3096 0 +0 3202 0 +0 3314 0 +0 3431 0 +0 3551 0 +0 3674 0 +0 2402 2697 +0 2402 2697 +0 2403 2697 +0 2403 2696 +0 2404 2696 +0 2405 2695 +0 2406 2694 +0 2408 2693 +0 2410 2691 +0 2413 2688 +0 2417 2685 +0 2422 2680 +0 2428 2674 +0 2437 2665 +0 2449 2654 +0 2464 2638 +0 2483 2615 +0 2508 2583 +0 2539 2537 +0 2577 2467 +0 2624 2352 +0 2680 2130 +0 2745 1300 +0 2820 0 +0 2904 0 +0 2996 0 +0 3096 0 +0 3203 0 +0 3315 0 +0 3431 0 +0 3551 0 +0 3674 0 +0 2405 2709 +0 2406 2709 +0 2406 2709 +0 2406 2708 +0 2407 2708 +0 2408 2707 +0 2409 2706 +0 2411 2705 +0 2413 2703 +0 2416 2700 +0 2420 2697 +0 2425 2692 +0 2431 2686 +0 2440 2678 +0 2452 2667 +0 2467 2651 +0 2486 2629 +0 2510 2599 +0 2541 2554 +0 2579 2486 +0 2626 2377 +0 2681 2170 +0 2746 1506 +0 2821 0 +0 2905 0 +0 2997 0 +0 3097 0 +0 3203 0 +0 3315 0 +0 3431 0 +0 3551 0 +0 3674 0 +0 2410 2725 +0 2410 2724 +0 2410 2724 +0 2411 2724 +0 2411 2723 +0 2412 2722 +0 2413 2721 +0 2415 2720 +0 2417 2718 +0 2420 2716 +0 2424 2713 +0 2429 2708 +0 2435 2702 +0 2444 2694 +0 2456 2684 +0 2470 2669 +0 2489 2648 +0 2514 2618 +0 2544 2575 +0 2582 2511 +0 2628 2408 +0 2684 2219 +0 2748 1686 +0 2823 0 +0 2906 0 +0 2998 0 +0 3098 0 +0 3204 0 +0 3316 0 +0 3432 0 +0 3552 0 +0 3675 0 +0 2415 2744 +0 2415 2744 +0 2416 2744 +0 2416 2744 +0 2417 2743 +0 2418 2742 +0 2419 2741 +0 2421 2740 +0 2423 2738 +0 2426 2736 +0 2429 2733 +0 2434 2729 +0 2441 2723 +0 2449 2716 +0 2461 2705 +0 2475 2691 +0 2494 2671 +0 2518 2643 +0 2548 2603 +0 2586 2543 +0 2632 2447 +0 2687 2277 +0 2751 1851 +0 2825 0 +0 2908 0 +0 3000 0 +0 3099 0 +0 3205 0 +0 3316 0 +0 3432 0 +0 3552 0 +0 3675 0 +896 2423 2770 +879 2423 2769 +854 2423 2769 +820 2424 2769 +769 2424 2768 +691 2425 2768 +560 2426 2767 +290 2428 2766 +0 2430 2764 +0 2433 2762 +0 2436 2759 +0 2441 2755 +0 2448 2750 +0 2456 2742 +0 2467 2733 +0 2482 2719 +0 2500 2701 +0 2524 2674 +0 2554 2637 +0 2591 2581 +0 2636 2494 +0 2691 2344 +0 2755 2007 +0 2828 0 +0 2910 0 +0 3002 0 +0 3101 0 +0 3206 0 +0 3317 0 +0 3433 0 +0 3553 0 +0 3675 0 +1925 2432 2801 +1923 2432 2801 +1921 2433 2801 +1917 2433 2801 +1913 2434 2800 +1907 2435 2799 +1899 2436 2799 +1889 2438 2798 +1874 2440 2796 +1853 2442 2794 +1824 2446 2791 +1782 2451 2788 +1718 2457 2783 +1617 2465 2776 +1432 2476 2767 +925 2490 2754 +0 2508 2737 +0 2532 2713 +0 2561 2679 +0 2598 2628 +0 2642 2551 +0 2696 2421 +0 2759 2155 +0 2832 0 +0 2914 0 +0 3004 0 +0 3103 0 +0 3208 0 +0 3319 0 +0 3434 0 +0 3554 0 +0 3676 0 +2283 2445 2841 +2282 2445 2840 +2281 2445 2840 +2279 2446 2840 +2278 2447 2839 +2275 2447 2839 +2271 2449 2838 +2267 2450 2837 +2260 2452 2836 +2252 2455 2834 +2240 2458 2831 +2223 2463 2828 +2200 2469 2823 +2168 2477 2817 +2120 2488 2809 +2047 2501 2798 +1927 2519 2782 +1692 2542 2760 +612 2571 2729 +0 2607 2685 +0 2650 2617 +0 2703 2507 +0 2765 2299 +0 2837 1624 +0 2918 0 +0 3008 0 +0 3106 0 +0 3210 0 +0 3321 0 +0 3436 0 +0 3555 0 +0 3677 0 +2532 2461 2888 +2531 2462 2888 +2531 2462 2888 +2530 2462 2887 +2529 2463 2887 +2527 2464 2887 +2525 2465 2886 +2522 2466 2885 +2519 2468 2884 +2514 2471 2882 +2507 2474 2880 +2498 2479 2877 +2486 2484 2873 +2469 2492 2867 +2445 2503 2860 +2411 2516 2850 +2360 2533 2836 +2283 2555 2817 +2155 2583 2789 +1893 2618 2750 +0 2661 2692 +0 2713 2601 +0 2774 2440 +0 2844 2059 +0 2924 0 +0 3013 0 +0 3110 0 +0 3213 0 +0 3323 0 +0 3438 0 +0 3556 0 +0 3678 0 +2735 2482 2945 +2735 2483 2945 +2734 2483 2945 +2734 2483 2944 +2733 2484 2944 +2732 2485 2944 +2731 2486 2943 +2729 2487 2942 +2727 2489 2941 +2724 2491 2940 +2719 2495 2938 +2714 2499 2935 +2706 2504 2931 +2696 2512 2927 +2681 2522 2920 +2661 2535 2911 +2633 2551 2899 +2592 2572 2882 +2532 2599 2859 +2435 2633 2826 +2263 2675 2777 +1825 2725 2702 +0 2784 2579 +0 2853 2332 +0 2932 847 +0 3019 0 +0 3115 0 +0 3217 0 +0 3326 0 +0 3440 0 +0 3558 0 +0 3679 0 +2914 2509 3011 +2913 2509 3011 +2913 2510 3011 +2913 2510 3011 +2912 2510 3010 +2912 2511 3010 +2911 2512 3009 +2910 2513 3009 +2908 2515 3008 +2906 2517 3007 +2903 2521 3005 +2900 2525 3003 +2894 2530 3000 +2888 2537 2995 +2878 2546 2990 +2865 2558 2982 +2848 2574 2972 +2823 2594 2958 +2787 2620 2938 +2735 2652 2910 +2653 2692 2870 +2516 2741 2810 +2224 2798 2716 +0 2865 2547 +0 2942 2131 +0 3028 0 +0 3122 0 +0 3223 0 +0 3331 0 +0 3443 0 +0 3561 0 +0 3681 0 +3078 2542 3087 +3078 2543 3087 +3077 2543 3087 +3077 2543 3087 +3077 2544 3086 +3076 2544 3086 +3076 2545 3086 +3075 2547 3085 +3074 2548 3084 +3073 2550 3083 +3071 2553 3082 +3068 2557 3080 +3064 2562 3077 +3060 2569 3074 +3053 2577 3069 +3045 2589 3063 +3033 2603 3054 +3016 2622 3042 +2993 2647 3026 +2961 2677 3003 +2913 2715 2971 +2841 2761 2923 +2721 2816 2851 +2486 2881 2733 +1423 2955 2501 +0 3039 1510 +0 3130 0 +0 3230 0 +0 3336 0 +0 3448 0 +0 3564 0 +0 3684 0 +3232 2584 3172 +3232 2584 3172 +3232 2584 3172 +3232 2584 3172 +3232 2585 3171 +3232 2585 3171 +3231 2586 3171 +3231 2587 3170 +3230 2589 3170 +3229 2591 3169 +3227 2593 3167 +3226 2597 3166 +3223 2601 3164 +3220 2607 3161 +3215 2615 3157 +3209 2626 3152 +3201 2639 3145 +3190 2657 3135 +3174 2680 3122 +3152 2708 3103 +3122 2743 3078 +3077 2787 3041 +3010 2839 2986 +2901 2901 2901 +2696 2972 2754 +2044 3053 2432 +0 3142 0 +0 3239 0 +0 3344 0 +0 3454 0 +0 3569 0 +0 3687 0 +3381 2633 3265 +3381 2634 3265 +3381 2634 3265 +3380 2634 3265 +3380 2634 3265 +3380 2635 3265 +3380 2636 3264 +3379 2637 3264 +3379 2638 3263 +3378 2640 3263 +3377 2642 3262 +3376 2645 3260 +3374 2649 3259 +3372 2655 3256 +3368 2662 3253 +3364 2671 3249 +3358 2684 3243 +3350 2700 3235 +3339 2720 3225 +3324 2746 3210 +3304 2779 3190 +3274 2819 3161 +3232 2868 3120 +3168 2926 3058 +3066 2994 2960 +2879 3071 2782 +2358 3157 2318 +0 3252 0 +0 3353 0 +0 3461 0 +0 3575 0 +0 3692 0 +3525 2692 3366 +3525 2693 3366 +3524 2693 3366 +3524 2693 3366 +3524 2693 3366 +3524 2694 3365 +3524 2695 3365 +3524 2695 3365 +3523 2697 3364 +3523 2698 3364 +3522 2700 3363 +3521 2703 3362 +3520 2707 3361 +3518 2711 3359 +3516 2718 3356 +3512 2726 3353 +3508 2737 3348 +3503 2751 3342 +3495 2770 3334 +3484 2793 3322 +3470 2823 3307 +3450 2859 3285 +3421 2904 3254 +3380 2958 3208 +3319 3022 3140 +3221 3095 3028 +3045 3177 2817 +2591 3268 2101 +0 3366 0 +0 3471 0 +0 3582 0 +0 3698 0 +3665 2761 3473 +3665 2761 3473 +3665 2761 3473 +3665 2762 3473 +3665 2762 3473 +3665 2762 3473 +3665 2763 3472 +3665 2764 3472 +3664 2765 3472 +3664 2766 3471 +3663 2768 3471 +3663 2770 3470 +3662 2773 3469 +3660 2777 3467 +3659 2783 3465 +3656 2790 3463 +3653 2800 3459 +3649 2812 3454 +3644 2828 3448 +3636 2849 3439 +3626 2875 3427 +3611 2908 3410 +3592 2949 3387 +3564 2998 3353 +3524 3056 3305 +3464 3124 3230 +3370 3202 3106 +3201 3288 2859 +2786 3383 1324 +0 3485 0 +0 3593 0 +0 3706 0 +3804 2839 3586 +3804 2839 3586 +3804 2839 3586 +3804 2840 3585 +3803 2840 3585 +3803 2840 3585 +3803 2841 3585 +3803 2841 3585 +3803 2842 3585 +3803 2843 3584 +3802 2845 3584 +3802 2847 3583 +3801 2849 3582 +3800 2853 3581 +3799 2858 3580 +3797 2864 3578 +3795 2872 3575 +3792 2882 3571 +3788 2896 3566 +3782 2914 3559 +3775 2937 3550 +3765 2966 3537 +3751 3002 3520 +3731 3046 3495 +3704 3099 3460 +3665 3161 3408 +3606 3233 3328 +3514 3314 3193 +3351 3404 2910 +2960 3502 0 +0 3606 0 +0 3717 0 +3940 2926 3703 +3940 2926 3702 +3940 2926 3702 +3940 2926 3702 +3940 2927 3702 +3940 2927 3702 +3940 2927 3702 +3940 2928 3702 +3940 2929 3702 +3940 2930 3702 +3939 2931 3701 +3939 2932 3701 +3938 2935 3700 +3938 2938 3699 +3937 2941 3698 +3936 2947 3696 +3934 2953 3694 +3932 2962 3691 +3929 2974 3687 +3925 2989 3682 +3919 3008 3675 +3912 3033 3666 +3902 3064 3652 +3888 3103 3634 +3869 3150 3608 +3842 3206 3572 +3803 3271 3517 +3745 3347 3433 +3654 3431 3288 +3495 3523 2971 +3121 3624 0 +0 3730 0 +4076 3021 3823 +4076 3021 3823 +4076 3021 3823 +4076 3022 3823 +4076 3022 3823 +4076 3022 3823 +4076 3022 3823 +4076 3023 3822 +4076 3023 3822 +4075 3024 3822 +4075 3025 3822 +4075 3026 3821 +4075 3028 3821 +4074 3031 3820 +4073 3034 3819 +4072 3038 3818 +4071 3043 3817 +4070 3051 3814 +4067 3060 3811 +4064 3073 3807 +4060 3089 3802 +4055 3110 3795 +4048 3136 3785 +4038 3170 3771 +4024 3210 3753 +4005 3260 3726 +3978 3318 3688 +3940 3387 3632 +3883 3464 3544 +3793 3551 3390 +3636 3646 3041 +3273 3748 0 +4095 3124 3946 +4095 3124 3946 +4095 3124 3946 +4095 3124 3946 +4095 3124 3946 +4095 3124 3946 +4095 3125 3946 +4095 3125 3946 +4095 3125 3946 +4095 3126 3945 +4095 3127 3945 +4095 3128 3945 +4095 3129 3945 +4095 3131 3944 +4095 3134 3943 +4095 3137 3942 +4095 3142 3941 +4095 3147 3940 +4095 3155 3937 +4095 3165 3934 +4095 3179 3930 +4095 3196 3925 +4095 3218 3917 +4095 3246 3907 +4095 3280 3893 +4095 3323 3874 +4095 3375 3847 +4095 3435 3808 +4075 3506 3750 +4019 3586 3659 +3930 3674 3499 +3775 3771 3120 +4095 3232 4071 +4095 3232 4071 +4095 3232 4071 +4095 3232 4071 +4095 3233 4071 +4095 3233 4071 +4095 3233 4071 +4095 3233 4071 +4095 3234 4071 +4095 3234 4071 +4095 3235 4071 +4095 3236 4070 +4095 3237 4070 +4095 3238 4070 +4095 3240 4069 +4095 3243 4069 +4095 3246 4068 +4095 3251 4066 +4095 3257 4065 +4095 3265 4062 +4095 3276 4059 +4095 3290 4055 +4095 3308 4050 +4095 3331 4042 +4095 3360 4032 +4095 3396 4018 +4095 3440 3998 +4095 3493 3971 +4095 3556 3931 +4095 3628 3872 +4095 3709 3778 +4065 3799 3612 +0 2525 2793 +0 2525 2793 +0 2525 2793 +0 2525 2793 +0 2526 2792 +0 2527 2792 +0 2528 2791 +0 2529 2790 +0 2531 2788 +0 2533 2786 +0 2536 2783 +0 2540 2779 +0 2545 2774 +0 2552 2768 +0 2561 2758 +0 2572 2746 +0 2588 2728 +0 2607 2704 +0 2632 2668 +0 2664 2617 +0 2703 2537 +0 2750 2402 +0 2807 2121 +0 2873 0 +0 2948 0 +0 3033 0 +0 3126 0 +0 3226 0 +0 3333 0 +0 3445 0 +0 3562 0 +0 3683 0 +0 2525 2794 +0 2525 2794 +0 2525 2793 +0 2526 2793 +0 2526 2792 +0 2527 2792 +0 2528 2791 +0 2529 2790 +0 2531 2788 +0 2533 2786 +0 2536 2783 +0 2540 2780 +0 2545 2775 +0 2552 2768 +0 2561 2759 +0 2573 2746 +0 2588 2728 +0 2607 2704 +0 2632 2669 +0 2664 2617 +0 2703 2538 +0 2750 2403 +0 2807 2123 +0 2873 0 +0 2948 0 +0 3033 0 +0 3126 0 +0 3226 0 +0 3333 0 +0 3446 0 +0 3562 0 +0 3683 0 +0 2525 2794 +0 2525 2794 +0 2525 2794 +0 2526 2793 +0 2526 2793 +0 2527 2792 +0 2528 2791 +0 2529 2790 +0 2531 2789 +0 2533 2787 +0 2536 2784 +0 2540 2780 +0 2545 2775 +0 2552 2768 +0 2561 2759 +0 2573 2746 +0 2588 2729 +0 2608 2704 +0 2633 2669 +0 2664 2618 +0 2703 2538 +0 2750 2404 +0 2807 2124 +0 2873 0 +0 2948 0 +0 3033 0 +0 3126 0 +0 3226 0 +0 3333 0 +0 3446 0 +0 3562 0 +0 3683 0 +0 2525 2795 +0 2525 2794 +0 2525 2794 +0 2526 2794 +0 2526 2793 +0 2527 2793 +0 2528 2792 +0 2529 2791 +0 2531 2789 +0 2533 2787 +0 2536 2784 +0 2540 2781 +0 2545 2776 +0 2552 2769 +0 2561 2760 +0 2573 2747 +0 2588 2730 +0 2608 2705 +0 2633 2670 +0 2664 2619 +0 2703 2539 +0 2750 2405 +0 2807 2127 +0 2873 0 +0 2948 0 +0 3033 0 +0 3126 0 +0 3226 0 +0 3333 0 +0 3446 0 +0 3562 0 +0 3683 0 +0 2525 2795 +0 2525 2795 +0 2526 2795 +0 2526 2795 +0 2526 2794 +0 2527 2793 +0 2528 2793 +0 2529 2791 +0 2531 2790 +0 2533 2788 +0 2536 2785 +0 2540 2781 +0 2545 2776 +0 2552 2770 +0 2561 2760 +0 2573 2748 +0 2588 2730 +0 2608 2706 +0 2633 2671 +0 2664 2620 +0 2703 2540 +0 2750 2407 +0 2807 2130 +0 2873 0 +0 2948 0 +0 3033 0 +0 3126 0 +0 3226 0 +0 3333 0 +0 3446 0 +0 3562 0 +0 3683 0 +0 2525 2796 +0 2526 2796 +0 2526 2796 +0 2526 2795 +0 2527 2795 +0 2527 2794 +0 2528 2794 +0 2530 2792 +0 2531 2791 +0 2533 2789 +0 2536 2786 +0 2540 2782 +0 2546 2777 +0 2552 2771 +0 2561 2761 +0 2573 2749 +0 2588 2731 +0 2608 2707 +0 2633 2672 +0 2664 2621 +0 2703 2542 +0 2751 2409 +0 2807 2134 +0 2873 0 +0 2948 0 +0 3033 0 +0 3126 0 +0 3226 0 +0 3333 0 +0 3446 0 +0 3562 0 +0 3683 0 +0 2526 2798 +0 2526 2797 +0 2526 2797 +0 2527 2797 +0 2527 2796 +0 2528 2796 +0 2529 2795 +0 2530 2794 +0 2532 2792 +0 2534 2790 +0 2537 2787 +0 2541 2784 +0 2546 2779 +0 2553 2772 +0 2562 2763 +0 2573 2750 +0 2589 2733 +0 2608 2709 +0 2633 2674 +0 2665 2623 +0 2703 2544 +0 2751 2412 +0 2807 2139 +0 2873 0 +0 2948 0 +0 3033 0 +0 3126 0 +0 3226 0 +0 3333 0 +0 3446 0 +0 3562 0 +0 3683 0 +0 2526 2799 +0 2526 2799 +0 2527 2799 +0 2527 2798 +0 2527 2798 +0 2528 2797 +0 2529 2797 +0 2530 2795 +0 2532 2794 +0 2534 2792 +0 2537 2789 +0 2541 2785 +0 2546 2780 +0 2553 2774 +0 2562 2765 +0 2574 2752 +0 2589 2735 +0 2609 2711 +0 2634 2676 +0 2665 2625 +0 2704 2547 +0 2751 2416 +0 2807 2146 +0 2873 0 +0 2949 0 +0 3033 0 +0 3126 0 +0 3226 0 +0 3333 0 +0 3446 0 +0 3562 0 +0 3683 0 +0 2527 2801 +0 2527 2801 +0 2527 2801 +0 2528 2801 +0 2528 2800 +0 2529 2800 +0 2530 2799 +0 2531 2798 +0 2533 2796 +0 2535 2794 +0 2538 2791 +0 2542 2788 +0 2547 2783 +0 2554 2776 +0 2563 2767 +0 2574 2755 +0 2590 2737 +0 2609 2713 +0 2634 2679 +0 2665 2629 +0 2704 2551 +0 2751 2421 +0 2808 2156 +0 2873 0 +0 2949 0 +0 3033 0 +0 3126 0 +0 3227 0 +0 3333 0 +0 3446 0 +0 3562 0 +0 3683 0 +0 2527 2804 +0 2528 2804 +0 2528 2804 +0 2528 2804 +0 2529 2803 +0 2529 2803 +0 2530 2802 +0 2532 2801 +0 2533 2799 +0 2536 2797 +0 2538 2794 +0 2542 2791 +0 2548 2786 +0 2554 2779 +0 2563 2770 +0 2575 2758 +0 2590 2741 +0 2610 2717 +0 2635 2683 +0 2666 2633 +0 2705 2556 +0 2752 2428 +0 2808 2168 +0 2874 0 +0 2949 0 +0 3034 0 +0 3126 0 +0 3227 0 +0 3334 0 +0 3446 0 +0 3563 0 +0 3683 0 +0 2528 2808 +0 2529 2808 +0 2529 2808 +0 2529 2808 +0 2530 2807 +0 2531 2807 +0 2531 2806 +0 2533 2805 +0 2534 2803 +0 2537 2801 +0 2539 2799 +0 2543 2795 +0 2549 2790 +0 2555 2783 +0 2564 2775 +0 2576 2762 +0 2591 2745 +0 2611 2722 +0 2635 2688 +0 2667 2639 +0 2705 2563 +0 2752 2437 +0 2809 2184 +0 2874 0 +0 2949 0 +0 3034 0 +0 3127 0 +0 3227 0 +0 3334 0 +0 3446 0 +0 3563 0 +0 3683 0 +0 2530 2814 +0 2530 2813 +0 2530 2813 +0 2531 2813 +0 2531 2812 +0 2532 2812 +0 2533 2811 +0 2534 2810 +0 2536 2808 +0 2538 2806 +0 2541 2804 +0 2545 2800 +0 2550 2795 +0 2557 2789 +0 2565 2780 +0 2577 2768 +0 2592 2751 +0 2612 2728 +0 2636 2695 +0 2668 2646 +0 2706 2572 +0 2753 2449 +0 2809 2204 +0 2875 806 +0 2950 0 +0 3034 0 +0 3127 0 +0 3227 0 +0 3334 0 +0 3446 0 +0 3563 0 +0 3683 0 +0 2532 2821 +0 2532 2820 +0 2532 2820 +0 2532 2820 +0 2533 2819 +0 2534 2819 +0 2535 2818 +0 2536 2817 +0 2537 2815 +0 2540 2814 +0 2543 2811 +0 2546 2807 +0 2552 2803 +0 2558 2796 +0 2567 2788 +0 2579 2776 +0 2594 2759 +0 2613 2736 +0 2638 2704 +0 2669 2656 +0 2708 2584 +0 2754 2464 +0 2810 2230 +0 2876 1179 +0 2951 0 +0 3035 0 +0 3128 0 +0 3228 0 +0 3334 0 +0 3446 0 +0 3563 0 +0 3683 0 +0 2534 2830 +0 2534 2829 +0 2534 2829 +0 2535 2829 +0 2535 2828 +0 2536 2828 +0 2537 2827 +0 2538 2826 +0 2540 2825 +0 2542 2823 +0 2545 2820 +0 2549 2817 +0 2554 2812 +0 2561 2806 +0 2569 2797 +0 2581 2786 +0 2596 2770 +0 2615 2747 +0 2640 2716 +0 2671 2669 +0 2709 2599 +0 2756 2484 +0 2812 2263 +0 2877 1432 +0 2952 0 +0 3036 0 +0 3128 0 +0 3228 0 +0 3335 0 +0 3447 0 +0 3563 0 +0 3683 0 +0 2537 2842 +0 2537 2841 +0 2538 2841 +0 2538 2841 +0 2539 2840 +0 2539 2840 +0 2540 2839 +0 2541 2838 +0 2543 2837 +0 2545 2835 +0 2548 2832 +0 2552 2829 +0 2557 2824 +0 2564 2818 +0 2572 2810 +0 2584 2799 +0 2599 2783 +0 2618 2761 +0 2642 2731 +0 2673 2686 +0 2711 2618 +0 2758 2509 +0 2813 2303 +0 2878 1638 +0 2953 0 +0 3037 0 +0 3129 0 +0 3229 0 +0 3335 0 +0 3447 0 +0 3564 0 +0 3684 0 +0 2541 2857 +0 2542 2857 +0 2542 2857 +0 2542 2856 +0 2543 2856 +0 2543 2855 +0 2544 2854 +0 2546 2854 +0 2547 2852 +0 2549 2850 +0 2552 2848 +0 2556 2845 +0 2561 2840 +0 2568 2835 +0 2576 2827 +0 2588 2816 +0 2602 2801 +0 2621 2780 +0 2646 2750 +0 2676 2708 +0 2714 2643 +0 2760 2540 +0 2816 2351 +0 2880 1818 +0 2955 0 +0 3038 0 +0 3130 0 +0 3230 0 +0 3336 0 +0 3448 0 +0 3564 0 +0 3684 0 +0 2547 2877 +0 2547 2877 +0 2547 2876 +0 2548 2876 +0 2548 2876 +0 2549 2875 +0 2550 2874 +0 2551 2873 +0 2553 2872 +0 2555 2870 +0 2558 2868 +0 2561 2865 +0 2566 2861 +0 2573 2855 +0 2581 2848 +0 2593 2837 +0 2607 2823 +0 2626 2803 +0 2650 2775 +0 2680 2735 +0 2718 2675 +0 2764 2579 +0 2819 2409 +0 2883 1983 +0 2957 0 +0 3040 0 +0 3132 0 +0 3231 0 +0 3337 0 +0 3449 0 +0 3565 0 +0 3684 0 +1040 2554 2902 +1028 2555 2902 +1011 2555 2902 +986 2555 2901 +952 2556 2901 +901 2556 2900 +823 2557 2900 +692 2558 2899 +422 2560 2898 +0 2562 2896 +0 2565 2894 +0 2569 2891 +0 2573 2887 +0 2580 2882 +0 2588 2875 +0 2599 2865 +0 2614 2851 +0 2632 2833 +0 2656 2806 +0 2686 2769 +0 2723 2713 +0 2768 2627 +0 2823 2476 +0 2887 2139 +0 2960 0 +0 3043 0 +0 3134 0 +0 3233 0 +0 3338 0 +0 3450 0 +0 3565 0 +0 3685 0 +2058 2564 2934 +2057 2564 2933 +2055 2565 2933 +2053 2565 2933 +2050 2565 2933 +2045 2566 2932 +2039 2567 2932 +2032 2568 2931 +2021 2570 2930 +2006 2572 2928 +1985 2574 2926 +1956 2578 2923 +1914 2583 2920 +1850 2589 2915 +1749 2597 2908 +1564 2608 2899 +1057 2622 2887 +0 2641 2869 +0 2664 2845 +0 2693 2811 +0 2730 2761 +0 2775 2683 +0 2828 2553 +0 2891 2287 +0 2964 0 +0 3046 0 +0 3137 0 +0 3235 0 +0 3340 0 +0 3451 0 +0 3566 0 +0 3686 0 +2415 2577 2973 +2415 2577 2973 +2414 2577 2972 +2413 2578 2972 +2412 2578 2972 +2410 2579 2971 +2407 2580 2971 +2404 2581 2970 +2399 2582 2969 +2392 2584 2968 +2384 2587 2966 +2372 2590 2963 +2355 2595 2960 +2332 2601 2956 +2300 2609 2949 +2252 2620 2941 +2179 2633 2930 +2059 2651 2914 +1824 2674 2892 +744 2703 2862 +0 2739 2817 +0 2783 2749 +0 2835 2639 +0 2898 2431 +0 2969 1756 +0 3050 0 +0 3140 0 +0 3238 0 +0 3342 0 +0 3453 0 +0 3568 0 +0 3687 0 +2664 2593 3020 +2664 2593 3020 +2663 2594 3020 +2663 2594 3020 +2662 2594 3020 +2661 2595 3019 +2659 2596 3019 +2657 2597 3018 +2654 2598 3017 +2651 2600 3016 +2646 2603 3014 +2639 2606 3012 +2630 2611 3009 +2618 2617 3005 +2601 2624 2999 +2577 2635 2992 +2543 2648 2982 +2493 2665 2968 +2416 2687 2949 +2287 2715 2922 +2025 2750 2883 +0 2793 2824 +0 2845 2733 +0 2906 2572 +0 2976 2191 +0 3056 0 +0 3145 0 +0 3242 0 +0 3345 0 +0 3455 0 +0 3570 0 +0 3688 0 +2867 2614 3077 +2867 2614 3077 +2867 2615 3077 +2866 2615 3077 +2866 2615 3076 +2865 2616 3076 +2864 2617 3076 +2863 2618 3075 +2861 2619 3074 +2859 2621 3073 +2856 2623 3072 +2851 2627 3070 +2846 2631 3067 +2838 2637 3063 +2828 2644 3059 +2813 2654 3052 +2793 2667 3043 +2765 2683 3031 +2724 2705 3014 +2664 2731 2991 +2567 2765 2958 +2395 2807 2909 +1957 2857 2835 +0 2916 2711 +0 2985 2465 +0 3064 979 +0 3151 0 +0 3247 0 +0 3350 0 +0 3458 0 +0 3572 0 +0 3690 0 +3046 2641 3143 +3046 2641 3143 +3046 2641 3143 +3045 2642 3143 +3045 2642 3143 +3044 2643 3142 +3044 2643 3142 +3043 2644 3142 +3042 2646 3141 +3040 2647 3140 +3038 2650 3139 +3035 2653 3137 +3032 2657 3135 +3027 2662 3132 +3020 2669 3127 +3010 2678 3122 +2997 2691 3114 +2980 2706 3104 +2955 2727 3090 +2919 2752 3070 +2867 2785 3042 +2786 2824 3002 +2648 2873 2942 +2356 2930 2848 +0 2997 2679 +0 3074 2263 +0 3160 0 +0 3254 0 +0 3355 0 +0 3463 0 +0 3576 0 +0 3693 0 +3210 2674 3219 +3210 2674 3219 +3210 2675 3219 +3210 2675 3219 +3209 2675 3219 +3209 2676 3218 +3209 2677 3218 +3208 2677 3218 +3207 2679 3217 +3206 2680 3216 +3205 2682 3215 +3203 2685 3214 +3200 2689 3212 +3197 2694 3209 +3192 2701 3206 +3185 2709 3201 +3177 2721 3195 +3165 2735 3186 +3148 2754 3174 +3126 2779 3158 +3093 2809 3135 +3045 2847 3103 +2973 2893 3055 +2853 2948 2983 +2618 3013 2865 +1555 3087 2634 +0 3171 1643 +0 3263 0 +0 3362 0 +0 3468 0 +0 3580 0 +0 3696 0 +3365 2716 3304 +3365 2716 3304 +3364 2716 3304 +3364 2716 3304 +3364 2716 3304 +3364 2717 3303 +3364 2718 3303 +3363 2718 3303 +3363 2719 3302 +3362 2721 3302 +3361 2723 3301 +3359 2725 3300 +3358 2729 3298 +3355 2734 3296 +3352 2740 3293 +3347 2748 3289 +3341 2758 3284 +3333 2772 3277 +3322 2789 3267 +3306 2812 3254 +3285 2840 3235 +3254 2876 3210 +3209 2919 3173 +3142 2971 3118 +3033 3033 3033 +2828 3104 2887 +2176 3185 2564 +0 3274 0 +0 3372 0 +0 3476 0 +0 3586 0 +0 3701 0 +3513 2765 3397 +3513 2765 3397 +3513 2766 3397 +3513 2766 3397 +3513 2766 3397 +3512 2767 3397 +3512 2767 3397 +3512 2768 3396 +3511 2769 3396 +3511 2770 3395 +3510 2772 3395 +3509 2774 3394 +3508 2777 3392 +3506 2781 3391 +3504 2787 3388 +3500 2794 3385 +3496 2804 3381 +3490 2816 3375 +3482 2832 3367 +3471 2852 3357 +3457 2878 3342 +3436 2911 3322 +3406 2951 3293 +3364 3000 3252 +3300 3058 3190 +3198 3126 3092 +3011 3203 2914 +2491 3289 2450 +0 3384 0 +0 3486 0 +0 3594 0 +0 3707 0 +3657 2824 3498 +3657 2824 3498 +3657 2825 3498 +3657 2825 3498 +3656 2825 3498 +3656 2825 3498 +3656 2826 3497 +3656 2827 3497 +3656 2827 3497 +3655 2829 3497 +3655 2830 3496 +3654 2832 3495 +3653 2835 3494 +3652 2839 3493 +3650 2843 3491 +3648 2850 3488 +3645 2858 3485 +3640 2869 3480 +3635 2883 3474 +3627 2902 3466 +3616 2925 3454 +3602 2955 3439 +3582 2992 3417 +3553 3036 3386 +3512 3090 3340 +3451 3154 3272 +3353 3227 3160 +3177 3309 2949 +2723 3400 2233 +0 3498 0 +0 3604 0 +0 3715 0 +3797 2893 3605 +3797 2893 3605 +3797 2893 3605 +3797 2893 3605 +3797 2894 3605 +3797 2894 3605 +3797 2894 3605 +3797 2895 3605 +3797 2896 3604 +3796 2897 3604 +3796 2898 3604 +3795 2900 3603 +3795 2902 3602 +3794 2905 3601 +3792 2909 3600 +3791 2915 3598 +3788 2922 3595 +3785 2932 3591 +3781 2944 3587 +3776 2960 3580 +3768 2981 3571 +3758 3007 3559 +3744 3040 3542 +3724 3081 3519 +3696 3130 3486 +3656 3188 3437 +3596 3256 3362 +3502 3334 3238 +3333 3420 2991 +2918 3515 1456 +0 3617 0 +0 3725 0 +3936 2971 3718 +3936 2971 3718 +3936 2971 3718 +3936 2971 3718 +3936 2972 3718 +3936 2972 3717 +3935 2972 3717 +3935 2973 3717 +3935 2973 3717 +3935 2974 3717 +3935 2975 3716 +3934 2977 3716 +3934 2979 3715 +3933 2981 3714 +3932 2985 3713 +3931 2990 3712 +3929 2996 3710 +3927 3004 3707 +3924 3015 3703 +3920 3028 3698 +3914 3046 3691 +3907 3069 3682 +3897 3098 3669 +3883 3134 3652 +3863 3178 3627 +3836 3231 3592 +3797 3293 3540 +3738 3365 3460 +3646 3446 3325 +3483 3536 3042 +3092 3634 0 +0 3738 0 +4073 3058 3835 +4073 3058 3835 +4072 3058 3835 +4072 3058 3835 +4072 3059 3834 +4072 3059 3834 +4072 3059 3834 +4072 3059 3834 +4072 3060 3834 +4072 3061 3834 +4072 3062 3834 +4071 3063 3833 +4071 3064 3833 +4071 3067 3832 +4070 3070 3831 +4069 3073 3830 +4068 3079 3828 +4066 3085 3826 +4064 3094 3823 +4061 3106 3820 +4057 3121 3814 +4051 3140 3807 +4044 3165 3798 +4034 3196 3784 +4020 3235 3766 +4001 3282 3741 +3974 3338 3704 +3935 3404 3650 +3877 3479 3565 +3787 3563 3420 +3627 3656 3103 +3253 3756 0 +4095 3153 3955 +4095 3153 3955 +4095 3153 3955 +4095 3154 3955 +4095 3154 3955 +4095 3154 3955 +4095 3154 3955 +4095 3154 3955 +4095 3155 3955 +4095 3155 3954 +4095 3156 3954 +4095 3157 3954 +4095 3159 3954 +4095 3160 3953 +4095 3163 3952 +4095 3166 3951 +4095 3170 3950 +4095 3176 3949 +4095 3183 3946 +4095 3192 3943 +4095 3205 3940 +4095 3221 3934 +4095 3242 3927 +4095 3269 3917 +4095 3302 3903 +4095 3342 3885 +4095 3392 3858 +4095 3451 3820 +4072 3519 3764 +4015 3596 3676 +3925 3683 3522 +3768 3778 3173 +4095 3256 4078 +4095 3256 4078 +4095 3256 4078 +4095 3256 4078 +4095 3256 4078 +4095 3256 4078 +4095 3256 4078 +4095 3257 4078 +4095 3257 4078 +4095 3257 4078 +4095 3258 4078 +4095 3259 4077 +4095 3260 4077 +4095 3261 4077 +4095 3263 4076 +4095 3266 4075 +4095 3269 4075 +4095 3274 4073 +4095 3280 4072 +4095 3287 4069 +4095 3297 4066 +4095 3311 4062 +4095 3328 4057 +4095 3350 4049 +4095 3378 4039 +4095 3413 4025 +4095 3455 4006 +4095 3507 3979 +4095 3567 3940 +4095 3638 3882 +4095 3718 3791 +4062 3806 3631 +0 2656 2925 +0 2657 2925 +0 2657 2925 +0 2657 2925 +0 2658 2924 +0 2658 2924 +0 2659 2923 +0 2660 2923 +0 2661 2921 +0 2663 2920 +0 2665 2918 +0 2668 2915 +0 2672 2911 +0 2677 2906 +0 2684 2899 +0 2693 2890 +0 2705 2878 +0 2720 2860 +0 2739 2835 +0 2764 2800 +0 2796 2749 +0 2835 2669 +0 2882 2534 +0 2939 2253 +0 3005 0 +0 3080 0 +0 3165 0 +0 3258 0 +0 3358 0 +0 3465 0 +0 3578 0 +0 3694 0 +0 2657 2926 +0 2657 2926 +0 2657 2925 +0 2657 2925 +0 2658 2925 +0 2658 2924 +0 2659 2924 +0 2660 2923 +0 2661 2922 +0 2663 2920 +0 2665 2918 +0 2668 2915 +0 2672 2912 +0 2677 2907 +0 2684 2900 +0 2693 2890 +0 2705 2878 +0 2720 2860 +0 2739 2836 +0 2765 2801 +0 2796 2749 +0 2835 2669 +0 2882 2535 +0 2939 2254 +0 3005 0 +0 3080 0 +0 3165 0 +0 3258 0 +0 3358 0 +0 3465 0 +0 3578 0 +0 3694 0 +0 2657 2926 +0 2657 2926 +0 2657 2926 +0 2657 2925 +0 2658 2925 +0 2658 2925 +0 2659 2924 +0 2660 2923 +0 2661 2922 +0 2663 2920 +0 2665 2918 +0 2668 2916 +0 2672 2912 +0 2677 2907 +0 2684 2900 +0 2693 2891 +0 2705 2878 +0 2720 2861 +0 2740 2836 +0 2765 2801 +0 2796 2749 +0 2835 2670 +0 2882 2535 +0 2939 2255 +0 3005 0 +0 3080 0 +0 3165 0 +0 3258 0 +0 3358 0 +0 3465 0 +0 3578 0 +0 3694 0 +0 2657 2926 +0 2657 2926 +0 2657 2926 +0 2657 2926 +0 2658 2925 +0 2658 2925 +0 2659 2924 +0 2660 2923 +0 2661 2922 +0 2663 2921 +0 2665 2919 +0 2668 2916 +0 2672 2912 +0 2677 2907 +0 2684 2900 +0 2693 2891 +0 2705 2879 +0 2720 2861 +0 2740 2836 +0 2765 2801 +0 2796 2750 +0 2835 2670 +0 2882 2536 +0 2939 2257 +0 3005 0 +0 3080 0 +0 3165 0 +0 3258 0 +0 3358 0 +0 3465 0 +0 3578 0 +0 3694 0 +0 2657 2927 +0 2657 2927 +0 2657 2927 +0 2657 2926 +0 2658 2926 +0 2658 2925 +0 2659 2925 +0 2660 2924 +0 2661 2923 +0 2663 2921 +0 2665 2919 +0 2668 2917 +0 2672 2913 +0 2677 2908 +0 2684 2901 +0 2693 2892 +0 2705 2879 +0 2720 2862 +0 2740 2837 +0 2765 2802 +0 2796 2751 +0 2835 2671 +0 2882 2537 +0 2939 2259 +0 3005 0 +0 3080 0 +0 3165 0 +0 3258 0 +0 3358 0 +0 3465 0 +0 3578 0 +0 3694 0 +0 2657 2928 +0 2657 2927 +0 2657 2927 +0 2658 2927 +0 2658 2927 +0 2659 2926 +0 2659 2926 +0 2660 2925 +0 2661 2924 +0 2663 2922 +0 2665 2920 +0 2668 2917 +0 2672 2914 +0 2677 2909 +0 2684 2902 +0 2693 2893 +0 2705 2880 +0 2720 2862 +0 2740 2838 +0 2765 2803 +0 2796 2752 +0 2835 2673 +0 2882 2539 +0 2939 2262 +0 3005 0 +0 3080 0 +0 3165 0 +0 3258 0 +0 3358 0 +0 3465 0 +0 3578 0 +0 3694 0 +0 2657 2929 +0 2657 2928 +0 2658 2928 +0 2658 2928 +0 2658 2928 +0 2659 2927 +0 2660 2926 +0 2660 2926 +0 2662 2925 +0 2663 2923 +0 2666 2921 +0 2669 2918 +0 2672 2915 +0 2678 2910 +0 2684 2903 +0 2693 2894 +0 2705 2881 +0 2720 2864 +0 2740 2839 +0 2765 2804 +0 2796 2753 +0 2835 2674 +0 2883 2541 +0 2939 2266 +0 3005 0 +0 3080 0 +0 3165 0 +0 3258 0 +0 3358 0 +0 3465 0 +0 3578 0 +0 3694 0 +0 2658 2930 +0 2658 2930 +0 2658 2929 +0 2658 2929 +0 2659 2929 +0 2659 2928 +0 2660 2928 +0 2661 2927 +0 2662 2926 +0 2664 2924 +0 2666 2922 +0 2669 2919 +0 2673 2916 +0 2678 2911 +0 2685 2904 +0 2694 2895 +0 2706 2882 +0 2721 2865 +0 2740 2841 +0 2765 2806 +0 2797 2755 +0 2836 2676 +0 2883 2544 +0 2939 2271 +0 3005 0 +0 3080 0 +0 3165 0 +0 3258 0 +0 3358 0 +0 3465 0 +0 3578 0 +0 3694 0 +0 2658 2931 +0 2658 2931 +0 2658 2931 +0 2659 2931 +0 2659 2931 +0 2660 2930 +0 2660 2929 +0 2661 2929 +0 2662 2927 +0 2664 2926 +0 2666 2924 +0 2669 2921 +0 2673 2918 +0 2678 2913 +0 2685 2906 +0 2694 2897 +0 2706 2884 +0 2721 2867 +0 2741 2843 +0 2766 2808 +0 2797 2757 +0 2836 2679 +0 2883 2548 +0 2939 2279 +0 3005 0 +0 3081 0 +0 3165 0 +0 3258 0 +0 3359 0 +0 3465 0 +0 3578 0 +0 3694 0 +0 2659 2934 +0 2659 2934 +0 2659 2933 +0 2659 2933 +0 2660 2933 +0 2660 2932 +0 2661 2932 +0 2662 2931 +0 2663 2930 +0 2665 2928 +0 2667 2926 +0 2670 2924 +0 2674 2920 +0 2679 2915 +0 2686 2908 +0 2695 2899 +0 2706 2887 +0 2722 2870 +0 2741 2845 +0 2766 2811 +0 2797 2761 +0 2836 2683 +0 2883 2553 +0 2940 2288 +0 3006 0 +0 3081 0 +0 3165 0 +0 3258 0 +0 3359 0 +0 3466 0 +0 3578 0 +0 3695 0 +0 2659 2937 +0 2659 2937 +0 2660 2936 +0 2660 2936 +0 2660 2936 +0 2661 2935 +0 2662 2935 +0 2663 2934 +0 2664 2933 +0 2665 2931 +0 2668 2929 +0 2671 2927 +0 2674 2923 +0 2680 2918 +0 2686 2911 +0 2695 2902 +0 2707 2890 +0 2722 2873 +0 2742 2849 +0 2767 2815 +0 2798 2765 +0 2837 2688 +0 2884 2560 +0 2940 2300 +0 3006 0 +0 3081 0 +0 3166 0 +0 3258 0 +0 3359 0 +0 3466 0 +0 3578 0 +0 3695 0 +0 2660 2941 +0 2660 2941 +0 2661 2940 +0 2661 2940 +0 2661 2940 +0 2662 2939 +0 2663 2939 +0 2664 2938 +0 2665 2937 +0 2666 2935 +0 2669 2933 +0 2672 2931 +0 2675 2927 +0 2681 2922 +0 2687 2916 +0 2696 2907 +0 2708 2894 +0 2723 2877 +0 2743 2854 +0 2768 2820 +0 2799 2771 +0 2837 2695 +0 2885 2569 +0 2941 2316 +0 3006 0 +0 3082 0 +0 3166 0 +0 3259 0 +0 3359 0 +0 3466 0 +0 3578 0 +0 3695 0 +0 2662 2946 +0 2662 2946 +0 2662 2946 +0 2662 2945 +0 2663 2945 +0 2663 2945 +0 2664 2944 +0 2665 2943 +0 2666 2942 +0 2668 2941 +0 2670 2939 +0 2673 2936 +0 2677 2932 +0 2682 2928 +0 2689 2921 +0 2698 2912 +0 2709 2900 +0 2724 2883 +0 2744 2860 +0 2769 2827 +0 2800 2778 +0 2838 2704 +0 2885 2581 +0 2941 2336 +0 3007 938 +0 3082 0 +0 3166 0 +0 3259 0 +0 3359 0 +0 3466 0 +0 3578 0 +0 3695 0 +0 2663 2953 +0 2664 2953 +0 2664 2952 +0 2664 2952 +0 2665 2952 +0 2665 2951 +0 2666 2951 +0 2667 2950 +0 2668 2949 +0 2670 2948 +0 2672 2946 +0 2675 2943 +0 2679 2940 +0 2684 2935 +0 2690 2928 +0 2699 2920 +0 2711 2908 +0 2726 2891 +0 2745 2868 +0 2770 2836 +0 2801 2788 +0 2840 2716 +0 2886 2596 +0 2942 2362 +0 3008 1311 +0 3083 0 +0 3167 0 +0 3260 0 +0 3360 0 +0 3466 0 +0 3579 0 +0 3695 0 +0 2666 2962 +0 2666 2962 +0 2666 2962 +0 2667 2961 +0 2667 2961 +0 2667 2961 +0 2668 2960 +0 2669 2959 +0 2670 2958 +0 2672 2957 +0 2674 2955 +0 2677 2952 +0 2681 2949 +0 2686 2944 +0 2693 2938 +0 2701 2929 +0 2713 2918 +0 2728 2902 +0 2747 2879 +0 2772 2848 +0 2803 2801 +0 2841 2731 +0 2888 2616 +0 2944 2395 +0 3009 1565 +0 3084 0 +0 3168 0 +0 3260 0 +0 3360 0 +0 3467 0 +0 3579 0 +0 3695 0 +0 2669 2974 +0 2669 2974 +0 2669 2973 +0 2670 2973 +0 2670 2973 +0 2671 2972 +0 2671 2972 +0 2672 2971 +0 2673 2970 +0 2675 2969 +0 2677 2967 +0 2680 2964 +0 2684 2961 +0 2689 2957 +0 2696 2950 +0 2704 2942 +0 2716 2931 +0 2731 2915 +0 2750 2894 +0 2774 2863 +0 2805 2818 +0 2843 2751 +0 2890 2641 +0 2945 2435 +0 3010 1770 +0 3085 0 +0 3169 0 +0 3261 0 +0 3361 0 +0 3467 0 +0 3579 0 +0 3696 0 +0 2673 2989 +0 2673 2989 +0 2674 2989 +0 2674 2989 +0 2674 2988 +0 2675 2988 +0 2676 2987 +0 2676 2987 +0 2678 2986 +0 2679 2984 +0 2681 2982 +0 2684 2980 +0 2688 2977 +0 2693 2973 +0 2700 2967 +0 2708 2959 +0 2720 2948 +0 2735 2933 +0 2754 2912 +0 2778 2882 +0 2808 2840 +0 2846 2775 +0 2893 2672 +0 2948 2483 +0 3013 1950 +0 3087 0 +0 3170 0 +0 3262 0 +0 3362 0 +0 3468 0 +0 3580 0 +0 3696 0 +0 2679 3009 +0 2679 3009 +0 2679 3009 +0 2680 3008 +0 2680 3008 +0 2680 3008 +0 2681 3007 +0 2682 3007 +0 2683 3006 +0 2685 3004 +0 2687 3003 +0 2690 3000 +0 2693 2997 +0 2698 2993 +0 2705 2987 +0 2714 2980 +0 2725 2969 +0 2739 2955 +0 2758 2935 +0 2782 2907 +0 2813 2867 +0 2850 2807 +0 2896 2711 +0 2951 2541 +0 3015 2115 +0 3089 0 +0 3172 0 +0 3264 0 +0 3363 0 +0 3469 0 +0 3581 0 +0 3697 0 +1182 2686 3034 +1173 2686 3034 +1160 2687 3034 +1143 2687 3034 +1119 2687 3033 +1084 2688 3033 +1033 2688 3033 +955 2689 3032 +824 2691 3031 +554 2692 3030 +0 2694 3028 +0 2697 3026 +0 2701 3023 +0 2706 3019 +0 2712 3014 +0 2720 3007 +0 2731 2997 +0 2746 2983 +0 2764 2965 +0 2788 2939 +0 2818 2901 +0 2855 2846 +0 2901 2759 +0 2955 2608 +0 3019 2271 +0 3092 0 +0 3175 0 +0 3266 0 +0 3365 0 +0 3470 0 +0 3582 0 +0 3697 0 +2191 2696 3066 +2190 2696 3066 +2189 2696 3066 +2187 2697 3065 +2185 2697 3065 +2182 2698 3065 +2177 2698 3064 +2172 2699 3064 +2164 2700 3063 +2153 2702 3062 +2138 2704 3060 +2117 2706 3058 +2088 2710 3055 +2046 2715 3052 +1983 2721 3047 +1881 2729 3040 +1696 2740 3031 +1189 2754 3019 +0 2773 3001 +0 2796 2977 +0 2825 2943 +0 2862 2893 +0 2907 2815 +0 2960 2685 +0 3023 2419 +0 3096 0 +0 3178 0 +0 3269 0 +0 3367 0 +0 3472 0 +0 3583 0 +0 3699 0 +2548 2709 3105 +2548 2709 3105 +2547 2709 3105 +2546 2709 3105 +2545 2710 3104 +2544 2710 3104 +2542 2711 3104 +2539 2712 3103 +2536 2713 3102 +2531 2714 3101 +2524 2716 3100 +2516 2719 3098 +2504 2722 3095 +2487 2727 3092 +2464 2733 3088 +2432 2741 3082 +2384 2752 3073 +2311 2766 3062 +2191 2783 3046 +1956 2806 3025 +876 2835 2994 +0 2871 2949 +0 2915 2881 +0 2967 2771 +0 3030 2564 +0 3101 1888 +0 3182 0 +0 3272 0 +0 3370 0 +0 3474 0 +0 3585 0 +0 3700 0 +2796 2725 3153 +2796 2725 3152 +2796 2725 3152 +2795 2726 3152 +2795 2726 3152 +2794 2726 3152 +2793 2727 3151 +2791 2728 3151 +2789 2729 3150 +2787 2730 3149 +2783 2732 3148 +2778 2735 3146 +2771 2738 3144 +2762 2743 3141 +2750 2749 3137 +2733 2756 3131 +2709 2767 3124 +2675 2780 3114 +2625 2797 3100 +2548 2819 3081 +2419 2847 3054 +2157 2882 3015 +0 2925 2957 +0 2977 2865 +0 3038 2704 +0 3108 2323 +0 3188 0 +0 3277 0 +0 3374 0 +0 3478 0 +0 3587 0 +0 3702 0 +2999 2746 3209 +2999 2746 3209 +2999 2746 3209 +2999 2747 3209 +2998 2747 3209 +2998 2747 3209 +2997 2748 3208 +2996 2749 3208 +2995 2750 3207 +2993 2751 3206 +2991 2753 3205 +2988 2755 3204 +2984 2759 3202 +2978 2763 3199 +2970 2769 3196 +2960 2776 3191 +2945 2786 3184 +2925 2799 3175 +2897 2815 3163 +2857 2837 3147 +2796 2864 3123 +2699 2897 3090 +2527 2939 3041 +2089 2989 2967 +0 3048 2843 +0 3118 2597 +0 3196 1111 +0 3283 0 +0 3379 0 +0 3482 0 +0 3590 0 +0 3704 0 +3178 2773 3276 +3178 2773 3275 +3178 2773 3275 +3178 2773 3275 +3177 2774 3275 +3177 2774 3275 +3177 2775 3275 +3176 2775 3274 +3175 2776 3274 +3174 2778 3273 +3172 2779 3272 +3170 2782 3271 +3167 2785 3269 +3164 2789 3267 +3159 2794 3264 +3152 2801 3260 +3142 2811 3254 +3130 2823 3246 +3112 2838 3236 +3087 2859 3222 +3051 2884 3202 +2999 2917 3174 +2918 2956 3134 +2780 3005 3074 +2488 3062 2980 +0 3130 2811 +0 3206 2395 +0 3292 0 +0 3386 0 +0 3487 0 +0 3595 0 +0 3708 0 +3342 2806 3351 +3342 2806 3351 +3342 2807 3351 +3342 2807 3351 +3342 2807 3351 +3341 2807 3351 +3341 2808 3350 +3341 2809 3350 +3340 2810 3350 +3339 2811 3349 +3338 2812 3348 +3337 2814 3347 +3335 2817 3346 +3332 2821 3344 +3329 2826 3341 +3324 2833 3338 +3318 2841 3333 +3309 2853 3327 +3297 2867 3318 +3281 2886 3306 +3258 2911 3290 +3225 2941 3267 +3177 2979 3235 +3105 3025 3187 +2985 3080 3115 +2750 3145 2997 +1687 3219 2766 +0 3303 1775 +0 3395 0 +0 3494 0 +0 3600 0 +0 3712 0 +3497 2847 3436 +3497 2848 3436 +3497 2848 3436 +3497 2848 3436 +3496 2848 3436 +3496 2849 3436 +3496 2849 3436 +3496 2850 3435 +3495 2850 3435 +3495 2852 3434 +3494 2853 3434 +3493 2855 3433 +3492 2858 3432 +3490 2861 3430 +3487 2866 3428 +3484 2872 3425 +3479 2880 3421 +3473 2890 3416 +3465 2904 3409 +3454 2921 3399 +3438 2944 3386 +3417 2972 3368 +3386 3008 3342 +3341 3051 3305 +3274 3103 3250 +3165 3165 3165 +2960 3236 3019 +2308 3317 2696 +0 3406 0 +0 3504 0 +0 3608 0 +0 3718 0 +3645 2897 3529 +3645 2897 3529 +3645 2898 3529 +3645 2898 3529 +3645 2898 3529 +3645 2898 3529 +3644 2899 3529 +3644 2899 3529 +3644 2900 3528 +3644 2901 3528 +3643 2902 3527 +3642 2904 3527 +3641 2906 3526 +3640 2909 3524 +3638 2914 3523 +3636 2919 3520 +3633 2926 3517 +3628 2936 3513 +3622 2948 3507 +3614 2964 3500 +3604 2984 3489 +3589 3011 3474 +3568 3043 3454 +3539 3084 3426 +3496 3132 3384 +3432 3191 3322 +3330 3258 3224 +3143 3335 3046 +2623 3421 2582 +0 3516 0 +0 3618 0 +0 3726 0 +3789 2956 3630 +3789 2956 3630 +3789 2957 3630 +3789 2957 3630 +3789 2957 3630 +3789 2957 3630 +3788 2958 3630 +3788 2958 3630 +3788 2959 3629 +3788 2960 3629 +3787 2961 3629 +3787 2962 3628 +3786 2964 3627 +3785 2967 3626 +3784 2971 3625 +3782 2976 3623 +3780 2982 3620 +3777 2990 3617 +3772 3001 3613 +3767 3015 3606 +3759 3034 3598 +3748 3057 3587 +3734 3087 3571 +3714 3124 3549 +3685 3169 3518 +3644 3222 3473 +3583 3286 3404 +3485 3359 3292 +3309 3441 3081 +2855 3532 2365 +0 3630 0 +0 3736 0 +3929 3025 3737 +3929 3025 3737 +3929 3025 3737 +3929 3025 3737 +3929 3026 3737 +3929 3026 3737 +3929 3026 3737 +3929 3026 3737 +3929 3027 3737 +3929 3028 3736 +3928 3029 3736 +3928 3030 3736 +3927 3032 3735 +3927 3034 3734 +3926 3037 3733 +3925 3042 3732 +3923 3047 3730 +3921 3054 3727 +3918 3064 3723 +3913 3076 3719 +3908 3092 3712 +3900 3113 3703 +3890 3139 3691 +3876 3172 3674 +3856 3213 3651 +3828 3262 3618 +3788 3320 3569 +3728 3388 3494 +3634 3466 3370 +3465 3552 3123 +3050 3647 1588 +0 3749 0 +4068 3103 3850 +4068 3103 3850 +4068 3103 3850 +4068 3103 3850 +4068 3104 3850 +4068 3104 3850 +4068 3104 3850 +4068 3104 3849 +4067 3105 3849 +4067 3105 3849 +4067 3106 3849 +4067 3107 3849 +4066 3109 3848 +4066 3111 3847 +4065 3114 3847 +4064 3117 3845 +4063 3122 3844 +4061 3128 3842 +4059 3136 3839 +4056 3147 3835 +4052 3160 3830 +4046 3178 3823 +4039 3201 3814 +4029 3230 3801 +4015 3266 3784 +3995 3310 3759 +3968 3363 3724 +3929 3425 3672 +3870 3497 3592 +3778 3578 3457 +3615 3668 3174 +3224 3766 0 +4095 3190 3967 +4095 3190 3967 +4095 3190 3967 +4095 3190 3967 +4095 3191 3967 +4095 3191 3967 +4095 3191 3967 +4095 3191 3966 +4095 3192 3966 +4095 3192 3966 +4095 3193 3966 +4095 3194 3966 +4095 3195 3965 +4095 3197 3965 +4095 3199 3964 +4095 3202 3963 +4095 3206 3962 +4095 3211 3961 +4095 3217 3958 +4095 3226 3956 +4095 3238 3952 +4095 3253 3946 +4095 3273 3939 +4095 3297 3930 +4095 3328 3917 +4095 3367 3898 +4095 3414 3873 +4095 3470 3836 +4067 3536 3782 +4009 3611 3697 +3919 3695 3552 +3759 3788 3235 +4095 3285 4087 +4095 3285 4087 +4095 3286 4087 +4095 3286 4087 +4095 3286 4087 +4095 3286 4087 +4095 3286 4087 +4095 3286 4087 +4095 3287 4087 +4095 3287 4087 +4095 3288 4087 +4095 3288 4086 +4095 3289 4086 +4095 3291 4086 +4095 3292 4085 +4095 3295 4084 +4095 3298 4084 +4095 3302 4082 +4095 3308 4081 +4095 3315 4079 +4095 3325 4076 +4095 3337 4072 +4095 3353 4066 +4095 3374 4059 +4095 3401 4049 +4095 3434 4036 +4095 3475 4017 +4095 3524 3990 +4095 3583 3952 +4095 3651 3896 +4095 3729 3808 +4057 3815 3655 +0 2788 3057 +0 2789 3057 +0 2789 3057 +0 2789 3057 +0 2789 3057 +0 2790 3056 +0 2790 3056 +0 2791 3055 +0 2792 3054 +0 2793 3053 +0 2795 3052 +0 2797 3050 +0 2800 3047 +0 2804 3043 +0 2809 3038 +0 2816 3031 +0 2825 3022 +0 2837 3009 +0 2852 2992 +0 2872 2967 +0 2897 2932 +0 2928 2880 +0 2967 2801 +0 3014 2666 +0 3071 2384 +0 3137 0 +0 3212 0 +0 3297 0 +0 3390 0 +0 3490 0 +0 3597 0 +0 3710 0 +0 2788 3058 +0 2789 3058 +0 2789 3057 +0 2789 3057 +0 2789 3057 +0 2790 3057 +0 2790 3056 +0 2791 3055 +0 2792 3055 +0 2793 3053 +0 2795 3052 +0 2797 3050 +0 2800 3047 +0 2804 3043 +0 2809 3038 +0 2816 3032 +0 2825 3022 +0 2837 3010 +0 2852 2992 +0 2872 2967 +0 2897 2932 +0 2928 2881 +0 2967 2801 +0 3014 2666 +0 3071 2385 +0 3137 0 +0 3212 0 +0 3297 0 +0 3390 0 +0 3490 0 +0 3597 0 +0 3710 0 +0 2788 3058 +0 2789 3058 +0 2789 3058 +0 2789 3057 +0 2789 3057 +0 2790 3057 +0 2790 3056 +0 2791 3056 +0 2792 3055 +0 2793 3054 +0 2795 3052 +0 2797 3050 +0 2800 3047 +0 2804 3044 +0 2809 3039 +0 2816 3032 +0 2825 3023 +0 2837 3010 +0 2852 2992 +0 2872 2968 +0 2897 2933 +0 2928 2881 +0 2967 2801 +0 3014 2667 +0 3071 2386 +0 3137 0 +0 3212 0 +0 3297 0 +0 3390 0 +0 3490 0 +0 3597 0 +0 3710 0 +0 2789 3058 +0 2789 3058 +0 2789 3058 +0 2789 3058 +0 2789 3057 +0 2790 3057 +0 2790 3057 +0 2791 3056 +0 2792 3055 +0 2793 3054 +0 2795 3052 +0 2797 3050 +0 2800 3048 +0 2804 3044 +0 2809 3039 +0 2816 3032 +0 2825 3023 +0 2837 3010 +0 2852 2993 +0 2872 2968 +0 2897 2933 +0 2928 2881 +0 2967 2802 +0 3014 2667 +0 3071 2387 +0 3137 0 +0 3212 0 +0 3297 0 +0 3390 0 +0 3490 0 +0 3597 0 +0 3710 0 +0 2789 3059 +0 2789 3058 +0 2789 3058 +0 2789 3058 +0 2789 3058 +0 2790 3058 +0 2790 3057 +0 2791 3056 +0 2792 3056 +0 2793 3054 +0 2795 3053 +0 2797 3051 +0 2800 3048 +0 2804 3044 +0 2809 3039 +0 2816 3033 +0 2825 3023 +0 2837 3011 +0 2852 2993 +0 2872 2969 +0 2897 2934 +0 2928 2882 +0 2967 2802 +0 3014 2668 +0 3071 2389 +0 3137 0 +0 3212 0 +0 3297 0 +0 3390 0 +0 3490 0 +0 3597 0 +0 3710 0 +0 2789 3059 +0 2789 3059 +0 2789 3059 +0 2789 3059 +0 2790 3058 +0 2790 3058 +0 2791 3058 +0 2791 3057 +0 2792 3056 +0 2793 3055 +0 2795 3053 +0 2797 3051 +0 2800 3049 +0 2804 3045 +0 2809 3040 +0 2816 3033 +0 2825 3024 +0 2837 3011 +0 2852 2994 +0 2872 2969 +0 2897 2934 +0 2928 2883 +0 2967 2803 +0 3014 2670 +0 3071 2391 +0 3137 0 +0 3212 0 +0 3297 0 +0 3390 0 +0 3490 0 +0 3597 0 +0 3710 0 +0 2789 3060 +0 2789 3060 +0 2789 3060 +0 2789 3059 +0 2790 3059 +0 2790 3059 +0 2791 3058 +0 2791 3058 +0 2792 3057 +0 2794 3056 +0 2795 3054 +0 2797 3052 +0 2800 3049 +0 2804 3046 +0 2810 3041 +0 2816 3034 +0 2825 3025 +0 2837 3012 +0 2852 2995 +0 2872 2970 +0 2897 2935 +0 2928 2884 +0 2967 2805 +0 3015 2671 +0 3071 2394 +0 3137 0 +0 3212 0 +0 3297 0 +0 3390 0 +0 3490 0 +0 3597 0 +0 3710 0 +0 2789 3061 +0 2789 3061 +0 2789 3061 +0 2790 3060 +0 2790 3060 +0 2790 3060 +0 2791 3059 +0 2792 3059 +0 2793 3058 +0 2794 3057 +0 2795 3055 +0 2798 3053 +0 2801 3050 +0 2805 3047 +0 2810 3042 +0 2817 3035 +0 2826 3026 +0 2837 3013 +0 2853 2996 +0 2872 2971 +0 2897 2936 +0 2929 2885 +0 2967 2806 +0 3015 2673 +0 3071 2398 +0 3137 0 +0 3212 0 +0 3297 0 +0 3390 0 +0 3491 0 +0 3597 0 +0 3710 0 +0 2790 3062 +0 2790 3062 +0 2790 3062 +0 2790 3062 +0 2790 3061 +0 2791 3061 +0 2791 3060 +0 2792 3060 +0 2793 3059 +0 2794 3058 +0 2796 3056 +0 2798 3054 +0 2801 3052 +0 2805 3048 +0 2810 3043 +0 2817 3036 +0 2826 3027 +0 2838 3014 +0 2853 2997 +0 2872 2973 +0 2897 2938 +0 2929 2887 +0 2968 2809 +0 3015 2676 +0 3071 2404 +0 3137 0 +0 3213 0 +0 3297 0 +0 3390 0 +0 3491 0 +0 3598 0 +0 3710 0 +0 2790 3064 +0 2790 3064 +0 2790 3063 +0 2790 3063 +0 2791 3063 +0 2791 3063 +0 2792 3062 +0 2792 3062 +0 2793 3061 +0 2795 3060 +0 2796 3058 +0 2798 3056 +0 2801 3053 +0 2805 3050 +0 2810 3045 +0 2817 3038 +0 2826 3029 +0 2838 3016 +0 2853 2999 +0 2873 2975 +0 2898 2940 +0 2929 2890 +0 2968 2811 +0 3015 2680 +0 3072 2411 +0 3137 0 +0 3213 0 +0 3297 0 +0 3390 0 +0 3491 0 +0 3598 0 +0 3710 0 +0 2791 3066 +0 2791 3066 +0 2791 3066 +0 2791 3065 +0 2791 3065 +0 2792 3065 +0 2792 3064 +0 2793 3064 +0 2794 3063 +0 2795 3062 +0 2797 3060 +0 2799 3058 +0 2802 3056 +0 2806 3052 +0 2811 3047 +0 2818 3040 +0 2827 3031 +0 2838 3019 +0 2854 3002 +0 2873 2978 +0 2898 2943 +0 2930 2893 +0 2968 2815 +0 3016 2685 +0 3072 2420 +0 3138 0 +0 3213 0 +0 3297 0 +0 3390 0 +0 3491 0 +0 3598 0 +0 3710 0 +0 2791 3069 +0 2791 3069 +0 2792 3069 +0 2792 3068 +0 2792 3068 +0 2792 3068 +0 2793 3067 +0 2794 3067 +0 2795 3066 +0 2796 3065 +0 2798 3063 +0 2800 3061 +0 2803 3059 +0 2807 3055 +0 2812 3050 +0 2819 3043 +0 2827 3034 +0 2839 3022 +0 2854 3005 +0 2874 2981 +0 2899 2947 +0 2930 2897 +0 2969 2821 +0 3016 2692 +0 3072 2432 +0 3138 0 +0 3213 0 +0 3298 0 +0 3391 0 +0 3491 0 +0 3598 0 +0 3710 0 +0 2792 3073 +0 2792 3073 +0 2793 3073 +0 2793 3072 +0 2793 3072 +0 2793 3072 +0 2794 3071 +0 2795 3071 +0 2796 3070 +0 2797 3069 +0 2799 3067 +0 2801 3065 +0 2804 3063 +0 2808 3059 +0 2813 3054 +0 2819 3048 +0 2828 3039 +0 2840 3026 +0 2855 3010 +0 2875 2986 +0 2900 2952 +0 2931 2903 +0 2970 2827 +0 3017 2701 +0 3073 2448 +0 3138 0 +0 3214 0 +0 3298 0 +0 3391 0 +0 3491 0 +0 3598 0 +0 3710 0 +0 2794 3078 +0 2794 3078 +0 2794 3078 +0 2794 3078 +0 2794 3077 +0 2795 3077 +0 2795 3077 +0 2796 3076 +0 2797 3075 +0 2798 3074 +0 2800 3073 +0 2802 3071 +0 2805 3068 +0 2809 3064 +0 2814 3060 +0 2821 3053 +0 2830 3044 +0 2841 3032 +0 2856 3016 +0 2876 2992 +0 2901 2959 +0 2932 2911 +0 2970 2836 +0 3017 2713 +0 3074 2468 +0 3139 1070 +0 3214 0 +0 3298 0 +0 3391 0 +0 3491 0 +0 3598 0 +0 3710 0 +0 2795 3085 +0 2796 3085 +0 2796 3085 +0 2796 3085 +0 2796 3084 +0 2797 3084 +0 2797 3084 +0 2798 3083 +0 2799 3082 +0 2800 3081 +0 2802 3080 +0 2804 3078 +0 2807 3075 +0 2811 3072 +0 2816 3067 +0 2822 3060 +0 2831 3052 +0 2843 3040 +0 2858 3023 +0 2877 3001 +0 2902 2968 +0 2933 2920 +0 2972 2848 +0 3019 2728 +0 3075 2494 +0 3140 1443 +0 3215 0 +0 3299 0 +0 3392 0 +0 3492 0 +0 3599 0 +0 3711 0 +0 2798 3094 +0 2798 3094 +0 2798 3094 +0 2798 3094 +0 2799 3093 +0 2799 3093 +0 2800 3093 +0 2800 3092 +0 2801 3091 +0 2802 3090 +0 2804 3089 +0 2806 3087 +0 2809 3084 +0 2813 3081 +0 2818 3076 +0 2825 3070 +0 2834 3062 +0 2845 3050 +0 2860 3034 +0 2879 3011 +0 2904 2980 +0 2935 2933 +0 2973 2863 +0 3020 2748 +0 3076 2527 +0 3141 1697 +0 3216 0 +0 3300 0 +0 3392 0 +0 3492 0 +0 3599 0 +0 3711 0 +0 2801 3106 +0 2801 3106 +0 2801 3106 +0 2802 3106 +0 2802 3105 +0 2802 3105 +0 2803 3105 +0 2803 3104 +0 2804 3103 +0 2806 3102 +0 2807 3101 +0 2809 3099 +0 2812 3096 +0 2816 3093 +0 2821 3089 +0 2828 3083 +0 2837 3074 +0 2848 3063 +0 2863 3047 +0 2882 3026 +0 2907 2995 +0 2937 2950 +0 2976 2883 +0 3022 2773 +0 3078 2567 +0 3143 1902 +0 3217 0 +0 3301 0 +0 3393 0 +0 3493 0 +0 3599 0 +0 3711 0 +0 2805 3121 +0 2805 3121 +0 2806 3121 +0 2806 3121 +0 2806 3121 +0 2806 3120 +0 2807 3120 +0 2808 3119 +0 2809 3119 +0 2810 3118 +0 2811 3116 +0 2814 3115 +0 2816 3112 +0 2820 3109 +0 2825 3105 +0 2832 3099 +0 2840 3091 +0 2852 3080 +0 2867 3065 +0 2886 3044 +0 2910 3014 +0 2940 2972 +0 2978 2908 +0 3025 2805 +0 3080 2615 +0 3145 2083 +0 3219 0 +0 3302 0 +0 3394 0 +0 3494 0 +0 3600 0 +0 3712 0 +0 2811 3141 +0 2811 3141 +0 2811 3141 +0 2811 3141 +0 2812 3141 +0 2812 3140 +0 2813 3140 +0 2813 3139 +0 2814 3139 +0 2815 3138 +0 2817 3136 +0 2819 3135 +0 2822 3132 +0 2826 3129 +0 2831 3125 +0 2837 3120 +0 2846 3112 +0 2857 3101 +0 2872 3087 +0 2890 3067 +0 2914 3039 +0 2945 2999 +0 2982 2939 +0 3028 2843 +0 3083 2673 +0 3147 2248 +0 3221 0 +0 3304 0 +0 3396 0 +0 3495 0 +0 3601 0 +0 3713 0 +1321 2818 3166 +1314 2818 3166 +1305 2819 3166 +1292 2819 3166 +1275 2819 3166 +1251 2819 3165 +1216 2820 3165 +1165 2821 3165 +1087 2821 3164 +956 2823 3163 +686 2824 3162 +0 2826 3160 +0 2829 3158 +0 2833 3155 +0 2838 3151 +0 2844 3146 +0 2853 3139 +0 2864 3129 +0 2878 3115 +0 2897 3097 +0 2920 3071 +0 2950 3033 +0 2987 2978 +0 3033 2891 +0 3087 2740 +0 3151 2403 +0 3224 0 +0 3307 0 +0 3398 0 +0 3497 0 +0 3603 0 +0 3714 0 +2324 2828 3198 +2323 2828 3198 +2322 2828 3198 +2321 2828 3198 +2319 2829 3197 +2317 2829 3197 +2314 2830 3197 +2309 2830 3196 +2304 2831 3196 +2296 2832 3195 +2285 2834 3194 +2270 2836 3192 +2249 2839 3190 +2220 2842 3188 +2178 2847 3184 +2115 2853 3179 +2013 2862 3172 +1828 2872 3163 +1321 2887 3151 +0 2905 3134 +0 2928 3109 +0 2957 3075 +0 2994 3025 +0 3039 2947 +0 3092 2817 +0 3156 2552 +0 3228 0 +0 3310 0 +0 3401 0 +0 3499 0 +0 3604 0 +0 3715 0 +2680 2841 3237 +2680 2841 3237 +2680 2841 3237 +2679 2841 3237 +2678 2841 3237 +2677 2842 3236 +2676 2842 3236 +2674 2843 3236 +2671 2844 3235 +2668 2845 3234 +2663 2846 3233 +2657 2848 3232 +2648 2851 3230 +2636 2854 3228 +2620 2859 3224 +2597 2865 3220 +2564 2873 3214 +2516 2884 3205 +2444 2898 3194 +2324 2915 3178 +2088 2938 3157 +1008 2967 3126 +0 3003 3081 +0 3047 3013 +0 3100 2903 +0 3162 2696 +0 3233 2020 +0 3315 0 +0 3404 0 +0 3502 0 +0 3607 0 +0 3717 0 +2929 2857 3285 +2929 2857 3285 +2928 2857 3285 +2928 2858 3284 +2927 2858 3284 +2927 2858 3284 +2926 2859 3284 +2925 2859 3283 +2923 2860 3283 +2921 2861 3282 +2919 2863 3281 +2915 2864 3280 +2910 2867 3278 +2903 2870 3276 +2894 2875 3273 +2882 2881 3269 +2865 2889 3264 +2841 2899 3256 +2807 2912 3246 +2757 2929 3232 +2680 2952 3213 +2551 2980 3186 +2289 3014 3147 +0 3057 3089 +0 3109 2997 +0 3170 2837 +0 3240 2456 +0 3320 0 +0 3409 0 +0 3506 0 +0 3610 0 +0 3719 0 +3132 2878 3341 +3132 2878 3341 +3131 2878 3341 +3131 2879 3341 +3131 2879 3341 +3130 2879 3341 +3130 2880 3341 +3129 2880 3340 +3128 2881 3340 +3127 2882 3339 +3125 2883 3338 +3123 2885 3337 +3120 2888 3336 +3116 2891 3334 +3110 2895 3331 +3102 2901 3328 +3092 2908 3323 +3077 2918 3316 +3057 2931 3307 +3029 2947 3295 +2989 2969 3279 +2928 2996 3255 +2832 3029 3222 +2659 3071 3173 +2222 3121 3099 +0 3181 2975 +0 3250 2729 +0 3328 1243 +0 3415 0 +0 3511 0 +0 3614 0 +0 3723 0 +3310 2905 3408 +3310 2905 3408 +3310 2905 3408 +3310 2905 3407 +3310 2906 3407 +3309 2906 3407 +3309 2906 3407 +3309 2907 3407 +3308 2907 3406 +3307 2908 3406 +3306 2910 3405 +3304 2911 3404 +3302 2914 3403 +3300 2917 3401 +3296 2921 3399 +3291 2926 3396 +3284 2933 3392 +3274 2943 3386 +3262 2955 3378 +3244 2970 3368 +3219 2991 3354 +3183 3016 3334 +3131 3049 3306 +3050 3089 3266 +2912 3137 3207 +2620 3195 3112 +0 3262 2944 +0 3338 2528 +0 3424 0 +0 3518 0 +0 3619 0 +0 3727 0 +3474 2938 3483 +3474 2938 3483 +3474 2939 3483 +3474 2939 3483 +3474 2939 3483 +3474 2939 3483 +3474 2940 3483 +3473 2940 3483 +3473 2941 3482 +3472 2942 3482 +3471 2943 3481 +3470 2944 3480 +3469 2947 3479 +3467 2949 3478 +3464 2953 3476 +3461 2958 3473 +3456 2965 3470 +3450 2973 3465 +3441 2985 3459 +3429 3000 3450 +3413 3019 3438 +3390 3043 3422 +3357 3073 3399 +3310 3111 3367 +3237 3157 3320 +3117 3213 3248 +2883 3277 3129 +1820 3351 2898 +0 3435 1907 +0 3527 0 +0 3626 0 +0 3732 0 +3629 2980 3568 +3629 2980 3568 +3629 2980 3568 +3629 2980 3568 +3629 2980 3568 +3629 2980 3568 +3628 2981 3568 +3628 2981 3568 +3628 2982 3567 +3627 2983 3567 +3627 2984 3566 +3626 2985 3566 +3625 2987 3565 +3624 2990 3564 +3622 2993 3562 +3619 2998 3560 +3616 3004 3557 +3612 3012 3553 +3605 3022 3548 +3597 3036 3541 +3586 3053 3531 +3570 3076 3518 +3549 3104 3500 +3518 3140 3474 +3474 3183 3437 +3406 3235 3382 +3297 3297 3297 +3092 3368 3151 +2441 3449 2828 +0 3538 0 +0 3636 0 +0 3740 0 +3777 3029 3662 +3777 3029 3662 +3777 3030 3662 +3777 3030 3661 +3777 3030 3661 +3777 3030 3661 +3777 3030 3661 +3777 3031 3661 +3776 3031 3661 +3776 3032 3660 +3776 3033 3660 +3775 3034 3660 +3774 3036 3659 +3773 3038 3658 +3772 3042 3657 +3770 3046 3655 +3768 3051 3652 +3765 3058 3649 +3760 3068 3645 +3754 3080 3639 +3747 3096 3632 +3736 3117 3621 +3721 3143 3606 +3700 3175 3586 +3671 3216 3558 +3628 3265 3516 +3564 3323 3455 +3462 3390 3356 +3275 3467 3178 +2755 3554 2715 +0 3648 0 +0 3750 0 +3921 3088 3762 +3921 3088 3762 +3921 3089 3762 +3921 3089 3762 +3921 3089 3762 +3921 3089 3762 +3921 3089 3762 +3921 3090 3762 +3920 3090 3762 +3920 3091 3761 +3920 3092 3761 +3919 3093 3761 +3919 3094 3760 +3918 3096 3759 +3917 3099 3758 +3916 3103 3757 +3914 3108 3755 +3912 3114 3753 +3909 3122 3749 +3905 3133 3745 +3899 3148 3738 +3891 3166 3730 +3881 3189 3719 +3866 3219 3703 +3846 3256 3681 +3817 3301 3650 +3776 3355 3605 +3715 3418 3536 +3617 3491 3424 +3441 3573 3213 +2987 3664 2497 +0 3762 0 +4062 3157 3869 +4062 3157 3869 +4062 3157 3869 +4062 3157 3869 +4062 3157 3869 +4061 3158 3869 +4061 3158 3869 +4061 3158 3869 +4061 3159 3869 +4061 3159 3869 +4061 3160 3869 +4060 3161 3868 +4060 3162 3868 +4060 3164 3867 +4059 3166 3866 +4058 3169 3865 +4057 3174 3864 +4055 3179 3862 +4053 3186 3859 +4050 3196 3856 +4045 3208 3851 +4040 3224 3844 +4032 3245 3835 +4022 3271 3823 +4008 3304 3806 +3988 3345 3783 +3960 3394 3750 +3920 3452 3701 +3860 3520 3626 +3766 3598 3502 +3598 3684 3255 +3182 3779 1720 +4095 3235 3982 +4095 3235 3982 +4095 3235 3982 +4095 3235 3982 +4095 3235 3982 +4095 3236 3982 +4095 3236 3982 +4095 3236 3982 +4095 3236 3982 +4095 3237 3981 +4095 3238 3981 +4095 3238 3981 +4095 3239 3981 +4095 3241 3980 +4095 3243 3979 +4095 3246 3979 +4095 3249 3978 +4095 3254 3976 +4095 3260 3974 +4095 3268 3971 +4095 3279 3967 +4095 3293 3962 +4095 3310 3956 +4095 3333 3946 +4095 3362 3934 +4095 3398 3916 +4095 3442 3891 +4095 3495 3856 +4061 3557 3804 +4002 3629 3724 +3910 3710 3589 +3747 3800 3306 +4095 3322 4095 +4095 3322 4095 +4095 3322 4095 +4095 3322 4095 +4095 3322 4095 +4095 3323 4095 +4095 3323 4095 +4095 3323 4095 +4095 3323 4095 +4095 3324 4095 +4095 3324 4095 +4095 3325 4095 +4095 3326 4095 +4095 3327 4095 +4095 3329 4095 +4095 3331 4095 +4095 3334 4095 +4095 3338 4094 +4095 3343 4093 +4095 3350 4090 +4095 3358 4088 +4095 3370 4084 +4095 3385 4079 +4095 3405 4071 +4095 3429 4062 +4095 3461 4049 +4095 3499 4030 +4095 3546 4005 +4095 3602 3968 +4095 3668 3914 +4095 3743 3829 +4051 3827 3684 +0 2920 3190 +0 2920 3189 +0 2921 3189 +0 2921 3189 +0 2921 3189 +0 2921 3189 +0 2922 3188 +0 2922 3188 +0 2923 3187 +0 2924 3186 +0 2925 3185 +0 2927 3184 +0 2929 3182 +0 2932 3179 +0 2936 3175 +0 2941 3170 +0 2948 3163 +0 2957 3154 +0 2969 3141 +0 2984 3124 +0 3004 3099 +0 3029 3064 +0 3060 3012 +0 3099 2932 +0 3146 2798 +0 3203 2515 +0 3269 0 +0 3344 0 +0 3429 0 +0 3522 0 +0 3622 0 +0 3729 0 +0 2920 3190 +0 2920 3190 +0 2921 3189 +0 2921 3189 +0 2921 3189 +0 2921 3189 +0 2922 3189 +0 2922 3188 +0 2923 3187 +0 2924 3187 +0 2925 3185 +0 2927 3184 +0 2929 3182 +0 2932 3179 +0 2936 3175 +0 2941 3170 +0 2948 3163 +0 2957 3154 +0 2969 3142 +0 2984 3124 +0 3004 3099 +0 3029 3064 +0 3060 3013 +0 3099 2933 +0 3146 2798 +0 3203 2516 +0 3269 0 +0 3344 0 +0 3429 0 +0 3522 0 +0 3622 0 +0 3729 0 +0 2920 3190 +0 2921 3190 +0 2921 3190 +0 2921 3189 +0 2921 3189 +0 2921 3189 +0 2922 3189 +0 2922 3188 +0 2923 3188 +0 2924 3187 +0 2925 3186 +0 2927 3184 +0 2929 3182 +0 2932 3179 +0 2936 3176 +0 2941 3170 +0 2948 3164 +0 2957 3154 +0 2969 3142 +0 2984 3124 +0 3004 3100 +0 3029 3064 +0 3060 3013 +0 3099 2933 +0 3146 2798 +0 3203 2517 +0 3269 0 +0 3344 0 +0 3429 0 +0 3522 0 +0 3622 0 +0 3729 0 +0 2920 3190 +0 2921 3190 +0 2921 3190 +0 2921 3190 +0 2921 3190 +0 2921 3189 +0 2922 3189 +0 2922 3188 +0 2923 3188 +0 2924 3187 +0 2925 3186 +0 2927 3184 +0 2929 3182 +0 2932 3179 +0 2936 3176 +0 2941 3171 +0 2948 3164 +0 2957 3155 +0 2969 3142 +0 2984 3124 +0 3004 3100 +0 3029 3065 +0 3060 3013 +0 3099 2933 +0 3146 2799 +0 3203 2518 +0 3269 0 +0 3344 0 +0 3429 0 +0 3522 0 +0 3622 0 +0 3729 0 +0 2921 3190 +0 2921 3190 +0 2921 3190 +0 2921 3190 +0 2921 3190 +0 2921 3190 +0 2922 3189 +0 2922 3189 +0 2923 3188 +0 2924 3187 +0 2925 3186 +0 2927 3185 +0 2929 3183 +0 2932 3180 +0 2936 3176 +0 2941 3171 +0 2948 3164 +0 2957 3155 +0 2969 3142 +0 2984 3125 +0 3004 3100 +0 3029 3065 +0 3060 3014 +0 3099 2934 +0 3146 2799 +0 3203 2519 +0 3269 0 +0 3344 0 +0 3429 0 +0 3522 0 +0 3622 0 +0 3729 0 +0 2921 3191 +0 2921 3191 +0 2921 3191 +0 2921 3190 +0 2921 3190 +0 2922 3190 +0 2922 3190 +0 2922 3189 +0 2923 3188 +0 2924 3188 +0 2925 3187 +0 2927 3185 +0 2929 3183 +0 2932 3180 +0 2936 3176 +0 2941 3171 +0 2948 3165 +0 2957 3155 +0 2969 3143 +0 2984 3125 +0 3004 3101 +0 3029 3066 +0 3060 3014 +0 3099 2935 +0 3146 2800 +0 3203 2521 +0 3269 0 +0 3344 0 +0 3429 0 +0 3522 0 +0 3622 0 +0 3729 0 +0 2921 3191 +0 2921 3191 +0 2921 3191 +0 2921 3191 +0 2921 3191 +0 2922 3190 +0 2922 3190 +0 2923 3190 +0 2923 3189 +0 2924 3188 +0 2925 3187 +0 2927 3186 +0 2929 3183 +0 2932 3181 +0 2936 3177 +0 2941 3172 +0 2948 3165 +0 2957 3156 +0 2969 3143 +0 2984 3126 +0 3004 3101 +0 3029 3066 +0 3060 3015 +0 3099 2936 +0 3147 2802 +0 3203 2523 +0 3269 0 +0 3344 0 +0 3429 0 +0 3522 0 +0 3623 0 +0 3729 0 +0 2921 3192 +0 2921 3192 +0 2921 3192 +0 2921 3192 +0 2922 3191 +0 2922 3191 +0 2922 3191 +0 2923 3190 +0 2923 3190 +0 2924 3189 +0 2926 3188 +0 2927 3186 +0 2930 3184 +0 2933 3181 +0 2936 3178 +0 2942 3173 +0 2948 3166 +0 2957 3157 +0 2969 3144 +0 2984 3127 +0 3004 3102 +0 3029 3067 +0 3061 3016 +0 3099 2937 +0 3147 2803 +0 3203 2526 +0 3269 0 +0 3344 0 +0 3429 0 +0 3522 0 +0 3623 0 +0 3730 0 +0 2921 3193 +0 2921 3193 +0 2921 3193 +0 2922 3193 +0 2922 3192 +0 2922 3192 +0 2922 3192 +0 2923 3191 +0 2924 3191 +0 2925 3190 +0 2926 3189 +0 2928 3187 +0 2930 3185 +0 2933 3182 +0 2937 3179 +0 2942 3174 +0 2949 3167 +0 2958 3158 +0 2969 3145 +0 2985 3128 +0 3004 3103 +0 3029 3069 +0 3061 3017 +0 3100 2938 +0 3147 2806 +0 3203 2530 +0 3269 0 +0 3345 0 +0 3429 0 +0 3522 0 +0 3623 0 +0 3730 0 +0 2922 3194 +0 2922 3194 +0 2922 3194 +0 2922 3194 +0 2922 3194 +0 2922 3193 +0 2923 3193 +0 2923 3193 +0 2924 3192 +0 2925 3191 +0 2926 3190 +0 2928 3188 +0 2930 3186 +0 2933 3184 +0 2937 3180 +0 2942 3175 +0 2949 3168 +0 2958 3159 +0 2970 3147 +0 2985 3129 +0 3005 3105 +0 3030 3070 +0 3061 3019 +0 3100 2941 +0 3147 2808 +0 3203 2536 +0 3269 0 +0 3345 0 +0 3429 0 +0 3522 0 +0 3623 0 +0 3730 0 +0 2922 3196 +0 2922 3196 +0 2922 3196 +0 2922 3196 +0 2923 3195 +0 2923 3195 +0 2923 3195 +0 2924 3194 +0 2924 3194 +0 2925 3193 +0 2927 3192 +0 2928 3190 +0 2931 3188 +0 2933 3185 +0 2937 3182 +0 2943 3177 +0 2949 3170 +0 2958 3161 +0 2970 3148 +0 2985 3131 +0 3005 3107 +0 3030 3072 +0 3061 3022 +0 3100 2944 +0 3147 2812 +0 3204 2543 +0 3269 0 +0 3345 0 +0 3429 0 +0 3522 0 +0 3623 0 +0 3730 0 +0 2923 3198 +0 2923 3198 +0 2923 3198 +0 2923 3198 +0 2923 3198 +0 2923 3197 +0 2924 3197 +0 2924 3197 +0 2925 3196 +0 2926 3195 +0 2927 3194 +0 2929 3192 +0 2931 3190 +0 2934 3188 +0 2938 3184 +0 2943 3179 +0 2950 3172 +0 2959 3163 +0 2971 3151 +0 2986 3134 +0 3005 3110 +0 3030 3075 +0 3062 3025 +0 3100 2947 +0 3148 2818 +0 3204 2552 +0 3270 0 +0 3345 0 +0 3430 0 +0 3522 0 +0 3623 0 +0 3730 0 +0 2923 3201 +0 2923 3201 +0 2924 3201 +0 2924 3201 +0 2924 3201 +0 2924 3200 +0 2925 3200 +0 2925 3200 +0 2926 3199 +0 2927 3198 +0 2928 3197 +0 2930 3195 +0 2932 3193 +0 2935 3191 +0 2939 3187 +0 2944 3182 +0 2951 3176 +0 2960 3167 +0 2971 3154 +0 2986 3137 +0 3006 3113 +0 3031 3079 +0 3062 3029 +0 3101 2953 +0 3148 2824 +0 3204 2564 +0 3270 0 +0 3345 0 +0 3430 0 +0 3523 0 +0 3623 0 +0 3730 0 +0 2924 3205 +0 2924 3205 +0 2925 3205 +0 2925 3205 +0 2925 3205 +0 2925 3204 +0 2926 3204 +0 2926 3203 +0 2927 3203 +0 2928 3202 +0 2929 3201 +0 2931 3199 +0 2933 3197 +0 2936 3195 +0 2940 3191 +0 2945 3186 +0 2952 3180 +0 2961 3171 +0 2972 3159 +0 2987 3142 +0 3007 3118 +0 3032 3084 +0 3063 3035 +0 3102 2959 +0 3149 2833 +0 3205 2580 +0 3271 0 +0 3346 0 +0 3430 0 +0 3523 0 +0 3623 0 +0 3730 0 +0 2926 3210 +0 2926 3210 +0 2926 3210 +0 2926 3210 +0 2926 3210 +0 2927 3210 +0 2927 3209 +0 2927 3209 +0 2928 3208 +0 2929 3207 +0 2930 3206 +0 2932 3205 +0 2934 3203 +0 2937 3200 +0 2941 3197 +0 2946 3192 +0 2953 3185 +0 2962 3176 +0 2973 3164 +0 2989 3148 +0 3008 3124 +0 3033 3091 +0 3064 3043 +0 3103 2968 +0 3150 2845 +0 3206 2601 +0 3271 1202 +0 3346 0 +0 3431 0 +0 3523 0 +0 3624 0 +0 3730 0 +0 2927 3217 +0 2928 3217 +0 2928 3217 +0 2928 3217 +0 2928 3217 +0 2928 3216 +0 2929 3216 +0 2929 3216 +0 2930 3215 +0 2931 3214 +0 2932 3213 +0 2934 3212 +0 2936 3210 +0 2939 3207 +0 2943 3204 +0 2948 3199 +0 2955 3193 +0 2963 3184 +0 2975 3172 +0 2990 3156 +0 3010 3133 +0 3034 3100 +0 3065 3053 +0 3104 2980 +0 3151 2860 +0 3207 2626 +0 3272 1575 +0 3347 0 +0 3431 0 +0 3524 0 +0 3624 0 +0 3731 0 +0 2930 3226 +0 2930 3226 +0 2930 3226 +0 2930 3226 +0 2930 3226 +0 2931 3226 +0 2931 3225 +0 2932 3225 +0 2932 3224 +0 2933 3223 +0 2934 3222 +0 2936 3221 +0 2938 3219 +0 2941 3216 +0 2945 3213 +0 2950 3208 +0 2957 3202 +0 2966 3194 +0 2977 3182 +0 2992 3166 +0 3012 3144 +0 3036 3112 +0 3067 3066 +0 3105 2995 +0 3152 2880 +0 3208 2659 +0 3273 1829 +0 3348 0 +0 3432 0 +0 3524 0 +0 3624 0 +0 3731 0 +0 2933 3238 +0 2933 3238 +0 2933 3238 +0 2933 3238 +0 2934 3238 +0 2934 3237 +0 2934 3237 +0 2935 3237 +0 2936 3236 +0 2936 3235 +0 2938 3234 +0 2939 3233 +0 2941 3231 +0 2944 3229 +0 2948 3225 +0 2953 3221 +0 2960 3215 +0 2969 3206 +0 2980 3195 +0 2995 3179 +0 3014 3158 +0 3039 3127 +0 3069 3082 +0 3108 3015 +0 3154 2905 +0 3210 2699 +0 3275 2034 +0 3349 0 +0 3433 0 +0 3525 0 +0 3625 0 +0 3732 0 +0 2937 3254 +0 2937 3253 +0 2938 3253 +0 2938 3253 +0 2938 3253 +0 2938 3253 +0 2939 3252 +0 2939 3252 +0 2940 3252 +0 2941 3251 +0 2942 3250 +0 2943 3248 +0 2946 3247 +0 2948 3244 +0 2952 3241 +0 2957 3237 +0 2964 3231 +0 2973 3223 +0 2984 3212 +0 2999 3197 +0 3018 3176 +0 3042 3147 +0 3073 3104 +0 3110 3040 +0 3157 2937 +0 3212 2747 +0 3277 2215 +0 3351 0 +0 3434 0 +0 3526 0 +0 3626 0 +0 3732 0 +0 2943 3273 +0 2943 3273 +0 2943 3273 +0 2943 3273 +0 2944 3273 +0 2944 3273 +0 2944 3272 +0 2945 3272 +0 2945 3271 +0 2946 3271 +0 2947 3270 +0 2949 3268 +0 2951 3267 +0 2954 3264 +0 2958 3261 +0 2963 3257 +0 2969 3252 +0 2978 3244 +0 2989 3234 +0 3004 3219 +0 3022 3199 +0 3046 3171 +0 3077 3131 +0 3114 3071 +0 3160 2976 +0 3215 2805 +0 3279 2380 +0 3353 0 +0 3436 0 +0 3528 0 +0 3627 0 +0 3733 0 +1458 2950 3298 +1453 2950 3298 +1446 2951 3298 +1437 2951 3298 +1424 2951 3298 +1407 2951 3298 +1383 2952 3298 +1348 2952 3297 +1297 2953 3297 +1219 2954 3296 +1088 2955 3295 +818 2956 3294 +0 2958 3292 +0 2961 3290 +0 2965 3287 +0 2970 3283 +0 2976 3278 +0 2985 3271 +0 2996 3261 +0 3010 3248 +0 3029 3229 +0 3052 3203 +0 3082 3165 +0 3119 3110 +0 3165 3023 +0 3219 2873 +0 3283 2535 +0 3356 0 +0 3439 0 +0 3530 0 +0 3629 0 +0 3735 0 +2457 2960 3330 +2456 2960 3330 +2456 2960 3330 +2455 2960 3330 +2453 2961 3330 +2451 2961 3330 +2449 2961 3329 +2446 2962 3329 +2442 2962 3328 +2436 2963 3328 +2428 2964 3327 +2417 2966 3326 +2402 2968 3324 +2382 2971 3322 +2352 2974 3320 +2310 2979 3316 +2247 2985 3311 +2145 2994 3304 +1960 3004 3295 +1453 3019 3283 +0 3037 3266 +0 3060 3242 +0 3090 3207 +0 3126 3157 +0 3171 3079 +0 3225 2949 +0 3288 2684 +0 3360 0 +0 3442 0 +0 3533 0 +0 3631 0 +0 3736 0 +2813 2973 3369 +2813 2973 3369 +2812 2973 3369 +2812 2973 3369 +2811 2973 3369 +2810 2974 3369 +2809 2974 3369 +2808 2974 3368 +2806 2975 3368 +2803 2976 3367 +2800 2977 3366 +2795 2978 3365 +2789 2980 3364 +2780 2983 3362 +2768 2987 3360 +2752 2991 3356 +2729 2997 3352 +2696 3005 3346 +2648 3016 3337 +2576 3030 3326 +2456 3048 3310 +2220 3070 3289 +1140 3099 3258 +0 3135 3213 +0 3179 3145 +0 3232 3035 +0 3294 2828 +0 3366 2152 +0 3447 0 +0 3536 0 +0 3634 0 +0 3739 0 +3061 2989 3417 +3061 2989 3417 +3061 2989 3417 +3060 2989 3417 +3060 2990 3417 +3060 2990 3416 +3059 2990 3416 +3058 2991 3416 +3057 2991 3415 +3055 2992 3415 +3053 2993 3414 +3051 2995 3413 +3047 2997 3412 +3042 2999 3410 +3036 3002 3408 +3027 3007 3405 +3014 3013 3401 +2997 3021 3396 +2973 3031 3388 +2939 3044 3378 +2889 3062 3364 +2812 3084 3345 +2683 3112 3318 +2421 3147 3279 +0 3189 3221 +0 3241 3129 +0 3302 2969 +0 3373 2588 +0 3452 0 +0 3541 0 +0 3638 0 +0 3742 0 +3264 3010 3474 +3264 3010 3474 +3264 3010 3473 +3263 3010 3473 +3263 3011 3473 +3263 3011 3473 +3263 3011 3473 +3262 3012 3473 +3261 3012 3472 +3260 3013 3472 +3259 3014 3471 +3257 3015 3470 +3255 3017 3469 +3252 3020 3468 +3248 3023 3466 +3242 3027 3463 +3234 3033 3460 +3224 3040 3455 +3210 3050 3448 +3190 3063 3440 +3161 3080 3427 +3121 3101 3411 +3060 3128 3387 +2964 3162 3354 +2791 3203 3305 +2354 3253 3231 +0 3313 3107 +0 3382 2861 +0 3460 1375 +0 3548 0 +0 3643 0 +0 3746 0 +3442 3037 3540 +3442 3037 3540 +3442 3037 3540 +3442 3037 3540 +3442 3037 3540 +3442 3038 3539 +3442 3038 3539 +3441 3038 3539 +3441 3039 3539 +3440 3040 3538 +3439 3041 3538 +3438 3042 3537 +3437 3044 3536 +3434 3046 3535 +3432 3049 3533 +3428 3053 3531 +3423 3058 3528 +3416 3065 3524 +3407 3075 3518 +3394 3087 3511 +3376 3103 3500 +3351 3123 3486 +3315 3149 3466 +3263 3181 3438 +3182 3221 3398 +3044 3269 3339 +2752 3327 3244 +0 3394 3076 +0 3470 2660 +0 3556 0 +0 3650 0 +0 3751 0 +3606 3070 3616 +3606 3070 3616 +3606 3071 3616 +3606 3071 3615 +3606 3071 3615 +3606 3071 3615 +3606 3071 3615 +3606 3072 3615 +3605 3072 3615 +3605 3073 3614 +3604 3074 3614 +3603 3075 3613 +3602 3077 3613 +3601 3079 3611 +3599 3082 3610 +3596 3085 3608 +3593 3090 3605 +3588 3097 3602 +3582 3106 3597 +3573 3117 3591 +3561 3132 3582 +3545 3151 3570 +3522 3175 3554 +3489 3205 3531 +3442 3243 3499 +3369 3289 3452 +3249 3345 3380 +3015 3409 3261 +1952 3483 3030 +0 3567 2039 +0 3659 0 +0 3758 0 +3761 3112 3700 +3761 3112 3700 +3761 3112 3700 +3761 3112 3700 +3761 3112 3700 +3761 3112 3700 +3761 3112 3700 +3760 3113 3700 +3760 3113 3700 +3760 3114 3699 +3759 3115 3699 +3759 3116 3699 +3758 3117 3698 +3757 3119 3697 +3756 3122 3696 +3754 3125 3694 +3751 3130 3692 +3748 3136 3689 +3744 3144 3685 +3738 3154 3680 +3729 3168 3673 +3718 3185 3663 +3702 3208 3650 +3681 3236 3632 +3650 3272 3606 +3606 3315 3569 +3538 3368 3514 +3429 3429 3429 +3224 3501 3283 +2573 3581 2960 +0 3671 0 +0 3768 0 +3909 3161 3794 +3909 3161 3794 +3909 3162 3794 +3909 3162 3794 +3909 3162 3794 +3909 3162 3794 +3909 3162 3793 +3909 3162 3793 +3909 3163 3793 +3908 3163 3793 +3908 3164 3793 +3908 3165 3792 +3907 3166 3792 +3906 3168 3791 +3905 3171 3790 +3904 3174 3789 +3902 3178 3787 +3900 3183 3785 +3897 3190 3781 +3892 3200 3777 +3887 3212 3771 +3879 3228 3764 +3868 3249 3753 +3853 3275 3739 +3832 3307 3718 +3803 3348 3690 +3760 3397 3648 +3696 3455 3587 +3594 3522 3488 +3407 3599 3311 +2887 3686 2847 +0 3780 0 +4053 3220 3894 +4053 3221 3894 +4053 3221 3894 +4053 3221 3894 +4053 3221 3894 +4053 3221 3894 +4053 3221 3894 +4053 3221 3894 +4053 3222 3894 +4052 3222 3894 +4052 3223 3894 +4052 3224 3893 +4052 3225 3893 +4051 3226 3892 +4050 3229 3891 +4049 3231 3890 +4048 3235 3889 +4046 3240 3887 +4044 3246 3885 +4041 3254 3881 +4037 3265 3877 +4031 3280 3871 +4023 3298 3862 +4013 3321 3851 +3998 3351 3835 +3978 3388 3813 +3950 3433 3782 +3908 3487 3737 +3847 3550 3668 +3749 3623 3557 +3573 3705 3345 +3119 3796 2630 +4095 3289 4002 +4095 3289 4002 +4095 3289 4002 +4095 3289 4002 +4095 3289 4001 +4095 3290 4001 +4095 3290 4001 +4095 3290 4001 +4095 3290 4001 +4095 3291 4001 +4095 3291 4001 +4095 3292 4001 +4095 3293 4000 +4095 3294 4000 +4095 3296 3999 +4095 3298 3998 +4095 3302 3997 +4095 3306 3996 +4095 3311 3994 +4095 3318 3991 +4095 3328 3988 +4095 3340 3983 +4095 3357 3976 +4095 3377 3967 +4095 3403 3955 +4095 3436 3939 +4095 3477 3915 +4092 3526 3882 +4052 3585 3833 +3993 3653 3758 +3898 3730 3634 +3730 3816 3387 +4095 3367 4095 +4095 3367 4095 +4095 3367 4095 +4095 3367 4095 +4095 3367 4095 +4095 3368 4095 +4095 3368 4095 +4095 3368 4095 +4095 3368 4095 +4095 3369 4095 +4095 3369 4095 +4095 3370 4095 +4095 3370 4095 +4095 3372 4095 +4095 3373 4095 +4095 3375 4095 +4095 3378 4095 +4095 3381 4095 +4095 3386 4095 +4095 3392 4095 +4095 3400 4095 +4095 3411 4095 +4095 3425 4094 +4095 3442 4088 +4095 3465 4078 +4095 3494 4066 +4095 3530 4048 +4095 3574 4023 +4095 3627 3988 +4095 3689 3936 +4095 3761 3857 +4042 3842 3721 +0 3052 3322 +0 3052 3322 +0 3053 3321 +0 3053 3321 +0 3053 3321 +0 3053 3321 +0 3053 3321 +0 3054 3320 +0 3054 3320 +0 3055 3319 +0 3056 3318 +0 3057 3317 +0 3059 3316 +0 3061 3314 +0 3064 3311 +0 3068 3307 +0 3073 3302 +0 3080 3295 +0 3089 3286 +0 3101 3273 +0 3116 3256 +0 3136 3231 +0 3161 3196 +0 3192 3144 +0 3231 3064 +0 3278 2929 +0 3335 2647 +0 3401 0 +0 3476 0 +0 3561 0 +0 3654 0 +0 3755 0 +0 3052 3322 +0 3052 3322 +0 3053 3322 +0 3053 3321 +0 3053 3321 +0 3053 3321 +0 3053 3321 +0 3054 3320 +0 3054 3320 +0 3055 3319 +0 3056 3319 +0 3057 3317 +0 3059 3316 +0 3061 3314 +0 3064 3311 +0 3068 3307 +0 3073 3302 +0 3080 3295 +0 3089 3286 +0 3101 3273 +0 3116 3256 +0 3136 3231 +0 3161 3196 +0 3192 3144 +0 3231 3065 +0 3278 2930 +0 3335 2648 +0 3401 0 +0 3476 0 +0 3561 0 +0 3654 0 +0 3755 0 +0 3052 3322 +0 3052 3322 +0 3053 3322 +0 3053 3322 +0 3053 3321 +0 3053 3321 +0 3053 3321 +0 3054 3321 +0 3054 3320 +0 3055 3319 +0 3056 3319 +0 3057 3318 +0 3059 3316 +0 3061 3314 +0 3064 3311 +0 3068 3307 +0 3073 3302 +0 3080 3296 +0 3089 3286 +0 3101 3274 +0 3116 3256 +0 3136 3231 +0 3161 3196 +0 3192 3145 +0 3231 3065 +0 3278 2930 +0 3335 2648 +0 3401 0 +0 3476 0 +0 3561 0 +0 3654 0 +0 3755 0 +0 3052 3322 +0 3053 3322 +0 3053 3322 +0 3053 3322 +0 3053 3322 +0 3053 3321 +0 3053 3321 +0 3054 3321 +0 3054 3320 +0 3055 3320 +0 3056 3319 +0 3057 3318 +0 3059 3316 +0 3061 3314 +0 3064 3311 +0 3068 3308 +0 3073 3303 +0 3080 3296 +0 3089 3286 +0 3101 3274 +0 3116 3256 +0 3136 3232 +0 3161 3197 +0 3192 3145 +0 3231 3065 +0 3278 2930 +0 3335 2649 +0 3401 0 +0 3476 0 +0 3561 0 +0 3654 0 +0 3755 0 +0 3053 3322 +0 3053 3322 +0 3053 3322 +0 3053 3322 +0 3053 3322 +0 3053 3322 +0 3053 3321 +0 3054 3321 +0 3054 3321 +0 3055 3320 +0 3056 3319 +0 3057 3318 +0 3059 3316 +0 3061 3314 +0 3064 3312 +0 3068 3308 +0 3073 3303 +0 3080 3296 +0 3089 3287 +0 3101 3274 +0 3116 3256 +0 3136 3232 +0 3161 3197 +0 3192 3145 +0 3231 3065 +0 3278 2931 +0 3335 2650 +0 3401 0 +0 3476 0 +0 3561 0 +0 3654 0 +0 3755 0 +0 3053 3323 +0 3053 3322 +0 3053 3322 +0 3053 3322 +0 3053 3322 +0 3053 3322 +0 3054 3322 +0 3054 3321 +0 3054 3321 +0 3055 3320 +0 3056 3319 +0 3057 3318 +0 3059 3317 +0 3061 3315 +0 3064 3312 +0 3068 3308 +0 3073 3303 +0 3080 3296 +0 3089 3287 +0 3101 3274 +0 3116 3257 +0 3136 3232 +0 3161 3197 +0 3192 3146 +0 3231 3066 +0 3279 2932 +0 3335 2651 +0 3401 0 +0 3476 0 +0 3561 0 +0 3654 0 +0 3755 0 +0 3053 3323 +0 3053 3323 +0 3053 3323 +0 3053 3323 +0 3053 3323 +0 3053 3322 +0 3054 3322 +0 3054 3322 +0 3055 3321 +0 3055 3321 +0 3056 3320 +0 3057 3319 +0 3059 3317 +0 3061 3315 +0 3064 3312 +0 3068 3309 +0 3073 3304 +0 3080 3297 +0 3089 3287 +0 3101 3275 +0 3116 3257 +0 3136 3233 +0 3161 3198 +0 3192 3146 +0 3231 3067 +0 3279 2932 +0 3335 2653 +0 3401 0 +0 3476 0 +0 3561 0 +0 3654 0 +0 3755 0 +0 3053 3323 +0 3053 3323 +0 3053 3323 +0 3053 3323 +0 3053 3323 +0 3053 3323 +0 3054 3323 +0 3054 3322 +0 3055 3322 +0 3055 3321 +0 3056 3320 +0 3058 3319 +0 3059 3318 +0 3061 3316 +0 3064 3313 +0 3068 3309 +0 3074 3304 +0 3080 3297 +0 3089 3288 +0 3101 3275 +0 3116 3258 +0 3136 3233 +0 3161 3198 +0 3192 3147 +0 3231 3068 +0 3279 2934 +0 3335 2655 +0 3401 0 +0 3476 0 +0 3561 0 +0 3654 0 +0 3755 0 +0 3053 3324 +0 3053 3324 +0 3053 3324 +0 3053 3324 +0 3053 3324 +0 3054 3324 +0 3054 3323 +0 3054 3323 +0 3055 3322 +0 3056 3322 +0 3057 3321 +0 3058 3320 +0 3059 3318 +0 3062 3316 +0 3065 3314 +0 3069 3310 +0 3074 3305 +0 3081 3298 +0 3090 3289 +0 3101 3276 +0 3117 3259 +0 3136 3234 +0 3161 3199 +0 3193 3148 +0 3231 3069 +0 3279 2935 +0 3335 2658 +0 3401 0 +0 3477 0 +0 3561 0 +0 3654 0 +0 3755 0 +0 3053 3325 +0 3053 3325 +0 3053 3325 +0 3054 3325 +0 3054 3325 +0 3054 3325 +0 3054 3324 +0 3055 3324 +0 3055 3323 +0 3056 3323 +0 3057 3322 +0 3058 3321 +0 3060 3319 +0 3062 3317 +0 3065 3314 +0 3069 3311 +0 3074 3306 +0 3081 3299 +0 3090 3290 +0 3102 3277 +0 3117 3260 +0 3136 3235 +0 3161 3201 +0 3193 3149 +0 3232 3071 +0 3279 2938 +0 3335 2662 +0 3401 0 +0 3477 0 +0 3561 0 +0 3654 0 +0 3755 0 +0 3054 3326 +0 3054 3326 +0 3054 3326 +0 3054 3326 +0 3054 3326 +0 3054 3326 +0 3055 3326 +0 3055 3325 +0 3055 3325 +0 3056 3324 +0 3057 3323 +0 3058 3322 +0 3060 3321 +0 3062 3319 +0 3065 3316 +0 3069 3312 +0 3074 3307 +0 3081 3300 +0 3090 3291 +0 3102 3279 +0 3117 3261 +0 3137 3237 +0 3162 3202 +0 3193 3151 +0 3232 3073 +0 3279 2941 +0 3335 2668 +0 3401 0 +0 3477 0 +0 3561 0 +0 3654 0 +0 3755 0 +0 3054 3328 +0 3054 3328 +0 3054 3328 +0 3054 3328 +0 3054 3328 +0 3055 3327 +0 3055 3327 +0 3055 3327 +0 3056 3326 +0 3057 3326 +0 3057 3325 +0 3059 3324 +0 3060 3322 +0 3063 3320 +0 3066 3318 +0 3069 3314 +0 3075 3309 +0 3081 3302 +0 3090 3293 +0 3102 3281 +0 3117 3263 +0 3137 3239 +0 3162 3204 +0 3193 3154 +0 3232 3076 +0 3279 2944 +0 3336 2675 +0 3402 0 +0 3477 0 +0 3561 0 +0 3654 0 +0 3755 0 +0 3055 3330 +0 3055 3330 +0 3055 3330 +0 3055 3330 +0 3055 3330 +0 3055 3330 +0 3056 3329 +0 3056 3329 +0 3056 3329 +0 3057 3328 +0 3058 3327 +0 3059 3326 +0 3061 3325 +0 3063 3323 +0 3066 3320 +0 3070 3316 +0 3075 3311 +0 3082 3305 +0 3091 3295 +0 3103 3283 +0 3118 3266 +0 3137 3242 +0 3162 3207 +0 3194 3157 +0 3233 3080 +0 3280 2950 +0 3336 2684 +0 3402 0 +0 3477 0 +0 3562 0 +0 3655 0 +0 3755 0 +0 3055 3333 +0 3055 3333 +0 3055 3333 +0 3056 3333 +0 3056 3333 +0 3056 3333 +0 3056 3332 +0 3057 3332 +0 3057 3332 +0 3058 3331 +0 3059 3330 +0 3060 3329 +0 3062 3328 +0 3064 3326 +0 3067 3323 +0 3071 3319 +0 3076 3314 +0 3083 3308 +0 3092 3299 +0 3103 3286 +0 3119 3269 +0 3138 3245 +0 3163 3211 +0 3194 3161 +0 3233 3085 +0 3280 2957 +0 3336 2696 +0 3402 0 +0 3477 0 +0 3562 0 +0 3655 0 +0 3755 0 +0 3056 3337 +0 3056 3337 +0 3056 3337 +0 3057 3337 +0 3057 3337 +0 3057 3337 +0 3057 3336 +0 3058 3336 +0 3058 3336 +0 3059 3335 +0 3060 3334 +0 3061 3333 +0 3063 3332 +0 3065 3330 +0 3068 3327 +0 3072 3323 +0 3077 3318 +0 3084 3312 +0 3093 3303 +0 3104 3291 +0 3119 3274 +0 3139 3250 +0 3164 3216 +0 3195 3167 +0 3234 3092 +0 3281 2966 +0 3337 2712 +0 3403 0 +0 3478 0 +0 3562 0 +0 3655 0 +0 3755 0 +0 3058 3342 +0 3058 3342 +0 3058 3342 +0 3058 3342 +0 3058 3342 +0 3058 3342 +0 3059 3342 +0 3059 3341 +0 3060 3341 +0 3060 3340 +0 3061 3339 +0 3062 3338 +0 3064 3337 +0 3066 3335 +0 3069 3332 +0 3073 3329 +0 3078 3324 +0 3085 3317 +0 3094 3309 +0 3106 3296 +0 3121 3280 +0 3140 3256 +0 3165 3223 +0 3196 3175 +0 3235 3100 +0 3282 2977 +0 3338 2733 +0 3403 1334 +0 3478 0 +0 3563 0 +0 3655 0 +0 3756 0 +0 3059 3349 +0 3060 3349 +0 3060 3349 +0 3060 3349 +0 3060 3349 +0 3060 3349 +0 3060 3349 +0 3061 3348 +0 3061 3348 +0 3062 3347 +0 3063 3346 +0 3064 3345 +0 3066 3344 +0 3068 3342 +0 3071 3339 +0 3075 3336 +0 3080 3331 +0 3087 3325 +0 3096 3316 +0 3107 3304 +0 3122 3288 +0 3142 3265 +0 3166 3232 +0 3197 3185 +0 3236 3112 +0 3283 2993 +0 3339 2758 +0 3404 1707 +0 3479 0 +0 3563 0 +0 3656 0 +0 3756 0 +0 3062 3358 +0 3062 3358 +0 3062 3358 +0 3062 3358 +0 3062 3358 +0 3063 3358 +0 3063 3358 +0 3063 3357 +0 3064 3357 +0 3064 3356 +0 3065 3355 +0 3067 3354 +0 3068 3353 +0 3070 3351 +0 3073 3349 +0 3077 3345 +0 3082 3341 +0 3089 3334 +0 3098 3326 +0 3109 3314 +0 3124 3298 +0 3144 3276 +0 3168 3244 +0 3199 3198 +0 3238 3127 +0 3284 3012 +0 3340 2791 +0 3405 1961 +0 3480 0 +0 3564 0 +0 3657 0 +0 3757 0 +0 3065 3370 +0 3065 3370 +0 3065 3370 +0 3065 3370 +0 3066 3370 +0 3066 3370 +0 3066 3369 +0 3066 3369 +0 3067 3369 +0 3068 3368 +0 3069 3367 +0 3070 3366 +0 3071 3365 +0 3074 3363 +0 3076 3361 +0 3080 3357 +0 3085 3353 +0 3092 3347 +0 3101 3338 +0 3112 3327 +0 3127 3312 +0 3146 3290 +0 3171 3259 +0 3202 3214 +0 3240 3147 +0 3286 3037 +0 3342 2831 +0 3407 2166 +0 3481 0 +0 3565 0 +0 3657 0 +0 3757 0 +0 3069 3386 +0 3069 3386 +0 3070 3386 +0 3070 3385 +0 3070 3385 +0 3070 3385 +0 3070 3385 +0 3071 3385 +0 3071 3384 +0 3072 3384 +0 3073 3383 +0 3074 3382 +0 3076 3381 +0 3078 3379 +0 3081 3376 +0 3084 3373 +0 3089 3369 +0 3096 3363 +0 3105 3355 +0 3116 3344 +0 3131 3329 +0 3150 3308 +0 3174 3279 +0 3205 3236 +0 3243 3172 +0 3289 3069 +0 3344 2880 +0 3409 2347 +0 3483 0 +0 3567 0 +0 3659 0 +0 3758 0 +0 3075 3405 +0 3075 3405 +0 3075 3405 +0 3075 3405 +0 3075 3405 +0 3076 3405 +0 3076 3405 +0 3076 3404 +0 3077 3404 +0 3077 3404 +0 3078 3403 +0 3080 3402 +0 3081 3401 +0 3083 3399 +0 3086 3397 +0 3090 3393 +0 3095 3389 +0 3101 3384 +0 3110 3376 +0 3121 3366 +0 3136 3351 +0 3155 3332 +0 3179 3304 +0 3209 3263 +0 3246 3203 +0 3292 3108 +0 3347 2937 +0 3411 2512 +0 3485 0 +0 3568 0 +0 3660 0 +0 3759 0 +1593 3082 3431 +1590 3082 3431 +1585 3083 3431 +1578 3083 3430 +1569 3083 3430 +1556 3083 3430 +1539 3083 3430 +1515 3084 3430 +1480 3084 3429 +1429 3085 3429 +1351 3086 3428 +1220 3087 3427 +950 3088 3426 +0 3090 3424 +0 3093 3422 +0 3097 3419 +0 3102 3415 +0 3108 3410 +0 3117 3403 +0 3128 3393 +0 3142 3380 +0 3161 3361 +0 3184 3335 +0 3214 3297 +0 3252 3242 +0 3297 3155 +0 3351 3005 +0 3415 2667 +0 3488 0 +0 3571 0 +0 3662 0 +0 3761 0 +2589 3092 3462 +2589 3092 3462 +2588 3092 3462 +2588 3092 3462 +2587 3092 3462 +2585 3093 3462 +2584 3093 3462 +2581 3093 3461 +2578 3094 3461 +2574 3094 3461 +2568 3095 3460 +2560 3096 3459 +2549 3098 3458 +2534 3100 3456 +2514 3103 3454 +2484 3106 3452 +2442 3111 3448 +2379 3117 3443 +2277 3126 3436 +2092 3137 3427 +1586 3151 3415 +0 3169 3398 +0 3192 3374 +0 3222 3339 +0 3258 3289 +0 3303 3211 +0 3357 3081 +0 3420 2816 +0 3492 0 +0 3574 0 +0 3665 0 +0 3763 0 +2945 3105 3501 +2945 3105 3501 +2945 3105 3501 +2944 3105 3501 +2944 3105 3501 +2943 3105 3501 +2942 3106 3501 +2941 3106 3501 +2940 3106 3500 +2938 3107 3500 +2935 3108 3499 +2932 3109 3499 +2927 3110 3497 +2921 3112 3496 +2912 3115 3494 +2900 3119 3492 +2884 3123 3488 +2861 3129 3484 +2828 3137 3478 +2780 3148 3470 +2708 3162 3458 +2588 3180 3443 +2352 3202 3421 +1272 3231 3390 +0 3267 3345 +0 3311 3277 +0 3364 3167 +0 3426 2960 +0 3498 2284 +0 3579 0 +0 3669 0 +0 3766 0 +3193 3121 3549 +3193 3121 3549 +3193 3121 3549 +3193 3121 3549 +3192 3122 3549 +3192 3122 3549 +3192 3122 3548 +3191 3122 3548 +3190 3123 3548 +3189 3123 3548 +3188 3124 3547 +3186 3125 3546 +3183 3127 3545 +3179 3129 3544 +3174 3131 3543 +3168 3135 3540 +3159 3139 3537 +3146 3145 3533 +3129 3153 3528 +3105 3163 3520 +3071 3176 3510 +3021 3194 3496 +2944 3216 3477 +2815 3244 3450 +2553 3279 3411 +0 3321 3353 +0 3373 3261 +0 3434 3101 +0 3505 2720 +0 3585 0 +0 3673 0 +0 3770 0 +3396 3142 3606 +3396 3142 3606 +3396 3142 3606 +3396 3142 3606 +3396 3143 3605 +3395 3143 3605 +3395 3143 3605 +3395 3143 3605 +3394 3144 3605 +3393 3144 3604 +3392 3145 3604 +3391 3146 3603 +3389 3148 3603 +3387 3149 3601 +3384 3152 3600 +3380 3155 3598 +3374 3159 3595 +3367 3165 3592 +3356 3172 3587 +3342 3182 3581 +3322 3195 3572 +3294 3212 3560 +3253 3233 3543 +3192 3260 3519 +3096 3294 3486 +2923 3335 3437 +2486 3385 3363 +0 3445 3239 +0 3514 2993 +0 3592 1507 +0 3680 0 +0 3775 0 +3575 3169 3672 +3575 3169 3672 +3574 3169 3672 +3574 3169 3672 +3574 3169 3672 +3574 3169 3672 +3574 3170 3672 +3574 3170 3671 +3573 3170 3671 +3573 3171 3671 +3572 3172 3670 +3571 3173 3670 +3570 3174 3669 +3569 3176 3668 +3567 3178 3667 +3564 3181 3665 +3560 3185 3663 +3555 3190 3660 +3548 3198 3656 +3539 3207 3650 +3526 3219 3643 +3508 3235 3632 +3483 3255 3618 +3448 3281 3598 +3395 3313 3571 +3314 3353 3531 +3176 3401 3471 +2884 3459 3376 +0 3526 3208 +0 3602 2792 +0 3688 0 +0 3782 0 +3739 3202 3748 +3739 3202 3748 +3739 3203 3748 +3738 3203 3748 +3738 3203 3748 +3738 3203 3747 +3738 3203 3747 +3738 3203 3747 +3738 3204 3747 +3737 3204 3747 +3737 3205 3746 +3736 3206 3746 +3736 3207 3745 +3734 3209 3745 +3733 3211 3744 +3731 3214 3742 +3728 3217 3740 +3725 3222 3738 +3720 3229 3734 +3714 3238 3729 +3705 3249 3723 +3693 3264 3714 +3677 3283 3703 +3654 3307 3686 +3621 3338 3663 +3574 3375 3631 +3501 3422 3584 +3381 3477 3512 +3147 3541 3393 +2084 3616 3162 +0 3699 2171 +0 3791 0 +3893 3244 3833 +3893 3244 3833 +3893 3244 3833 +3893 3244 3832 +3893 3244 3832 +3893 3244 3832 +3893 3244 3832 +3893 3244 3832 +3893 3245 3832 +3892 3245 3832 +3892 3246 3832 +3892 3247 3831 +3891 3248 3831 +3890 3249 3830 +3889 3251 3829 +3888 3254 3828 +3886 3257 3826 +3884 3262 3824 +3880 3268 3821 +3876 3276 3817 +3870 3286 3812 +3861 3300 3805 +3850 3318 3795 +3835 3340 3782 +3813 3368 3764 +3782 3404 3738 +3738 3447 3701 +3670 3500 3646 +3561 3561 3561 +3357 3633 3415 +2705 3713 3092 +0 3803 0 +4041 3293 3926 +4041 3293 3926 +4041 3294 3926 +4041 3294 3926 +4041 3294 3926 +4041 3294 3926 +4041 3294 3926 +4041 3294 3926 +4041 3295 3925 +4041 3295 3925 +4041 3296 3925 +4040 3296 3925 +4040 3297 3924 +4039 3299 3924 +4039 3300 3923 +4038 3303 3922 +4036 3306 3921 +4034 3310 3919 +4032 3315 3917 +4029 3322 3914 +4025 3332 3909 +4019 3344 3904 +4011 3360 3896 +4000 3381 3885 +3985 3407 3871 +3964 3440 3850 +3935 3480 3822 +3892 3529 3781 +3829 3587 3719 +3726 3654 3620 +3539 3732 3443 +3019 3818 2979 +4095 3353 4027 +4095 3353 4027 +4095 3353 4027 +4095 3353 4027 +4095 3353 4026 +4095 3353 4026 +4095 3353 4026 +4095 3353 4026 +4095 3354 4026 +4095 3354 4026 +4095 3354 4026 +4095 3355 4026 +4095 3356 4025 +4095 3357 4025 +4095 3359 4024 +4095 3361 4024 +4095 3363 4023 +4095 3367 4021 +4095 3372 4019 +4095 3378 4017 +4095 3387 4013 +4095 3397 4009 +4095 3412 4003 +4095 3430 3994 +4095 3454 3983 +4095 3483 3967 +4095 3520 3945 +4082 3565 3914 +4041 3619 3869 +3979 3682 3800 +3881 3755 3689 +3706 3837 3477 +4095 3421 4095 +4095 3421 4095 +4095 3421 4095 +4095 3421 4095 +4095 3421 4095 +4095 3421 4095 +4095 3422 4095 +4095 3422 4095 +4095 3422 4095 +4095 3422 4095 +4095 3423 4095 +4095 3423 4095 +4095 3424 4095 +4095 3425 4095 +4095 3426 4095 +4095 3428 4095 +4095 3431 4095 +4095 3434 4095 +4095 3438 4095 +4095 3443 4095 +4095 3451 4095 +4095 3460 4095 +4095 3473 4095 +4095 3489 4095 +4095 3509 4095 +4095 3536 4087 +4095 3568 4071 +4095 3609 4047 +4095 3658 4014 +4095 3717 3965 +4095 3785 3891 +4030 3862 3767 +0 3184 3454 +0 3184 3454 +0 3185 3454 +0 3185 3453 +0 3185 3453 +0 3185 3453 +0 3185 3453 +0 3185 3453 +0 3186 3452 +0 3186 3452 +0 3187 3451 +0 3188 3450 +0 3189 3449 +0 3191 3448 +0 3193 3446 +0 3196 3443 +0 3200 3439 +0 3205 3434 +0 3212 3427 +0 3221 3418 +0 3233 3405 +0 3248 3388 +0 3268 3363 +0 3293 3328 +0 3324 3276 +0 3363 3196 +0 3410 3061 +0 3467 2779 +0 3533 0 +0 3608 0 +0 3693 0 +0 3786 0 +0 3184 3454 +0 3184 3454 +0 3185 3454 +0 3185 3454 +0 3185 3453 +0 3185 3453 +0 3185 3453 +0 3185 3453 +0 3186 3452 +0 3186 3452 +0 3187 3451 +0 3188 3451 +0 3189 3449 +0 3191 3448 +0 3193 3446 +0 3196 3443 +0 3200 3439 +0 3205 3434 +0 3212 3427 +0 3221 3418 +0 3233 3405 +0 3248 3388 +0 3268 3363 +0 3293 3328 +0 3324 3276 +0 3363 3196 +0 3410 3061 +0 3467 2779 +0 3533 0 +0 3608 0 +0 3693 0 +0 3786 0 +0 3184 3454 +0 3184 3454 +0 3185 3454 +0 3185 3454 +0 3185 3454 +0 3185 3453 +0 3185 3453 +0 3185 3453 +0 3186 3453 +0 3186 3452 +0 3187 3451 +0 3188 3451 +0 3189 3449 +0 3191 3448 +0 3193 3446 +0 3196 3443 +0 3200 3439 +0 3205 3434 +0 3212 3428 +0 3221 3418 +0 3233 3406 +0 3248 3388 +0 3268 3363 +0 3293 3328 +0 3324 3277 +0 3363 3197 +0 3411 3062 +0 3467 2780 +0 3533 0 +0 3608 0 +0 3693 0 +0 3786 0 +0 3184 3454 +0 3185 3454 +0 3185 3454 +0 3185 3454 +0 3185 3454 +0 3185 3454 +0 3185 3453 +0 3185 3453 +0 3186 3453 +0 3186 3452 +0 3187 3452 +0 3188 3451 +0 3189 3450 +0 3191 3448 +0 3193 3446 +0 3196 3443 +0 3200 3440 +0 3205 3434 +0 3212 3428 +0 3221 3418 +0 3233 3406 +0 3248 3388 +0 3268 3364 +0 3293 3328 +0 3324 3277 +0 3363 3197 +0 3411 3062 +0 3467 2780 +0 3533 0 +0 3608 0 +0 3693 0 +0 3786 0 +0 3184 3454 +0 3185 3454 +0 3185 3454 +0 3185 3454 +0 3185 3454 +0 3185 3454 +0 3185 3453 +0 3186 3453 +0 3186 3453 +0 3186 3452 +0 3187 3452 +0 3188 3451 +0 3189 3450 +0 3191 3448 +0 3193 3446 +0 3196 3443 +0 3200 3440 +0 3205 3435 +0 3212 3428 +0 3221 3419 +0 3233 3406 +0 3248 3388 +0 3268 3364 +0 3293 3329 +0 3324 3277 +0 3363 3197 +0 3411 3062 +0 3467 2781 +0 3533 0 +0 3608 0 +0 3693 0 +0 3786 0 +0 3185 3454 +0 3185 3454 +0 3185 3454 +0 3185 3454 +0 3185 3454 +0 3185 3454 +0 3185 3454 +0 3186 3453 +0 3186 3453 +0 3186 3453 +0 3187 3452 +0 3188 3451 +0 3189 3450 +0 3191 3448 +0 3193 3446 +0 3196 3444 +0 3200 3440 +0 3205 3435 +0 3212 3428 +0 3221 3419 +0 3233 3406 +0 3248 3389 +0 3268 3364 +0 3293 3329 +0 3324 3277 +0 3363 3198 +0 3411 3063 +0 3467 2782 +0 3533 0 +0 3608 0 +0 3693 0 +0 3786 0 +0 3185 3455 +0 3185 3455 +0 3185 3455 +0 3185 3454 +0 3185 3454 +0 3185 3454 +0 3185 3454 +0 3186 3454 +0 3186 3453 +0 3187 3453 +0 3187 3452 +0 3188 3451 +0 3189 3450 +0 3191 3449 +0 3193 3447 +0 3196 3444 +0 3200 3440 +0 3205 3435 +0 3212 3428 +0 3221 3419 +0 3233 3406 +0 3248 3389 +0 3268 3364 +0 3293 3329 +0 3324 3278 +0 3363 3198 +0 3411 3064 +0 3467 2783 +0 3533 0 +0 3609 0 +0 3693 0 +0 3786 0 +0 3185 3455 +0 3185 3455 +0 3185 3455 +0 3185 3455 +0 3185 3455 +0 3185 3455 +0 3185 3454 +0 3186 3454 +0 3186 3454 +0 3187 3453 +0 3187 3453 +0 3188 3452 +0 3190 3451 +0 3191 3449 +0 3193 3447 +0 3196 3444 +0 3200 3441 +0 3205 3436 +0 3212 3429 +0 3221 3420 +0 3233 3407 +0 3248 3389 +0 3268 3365 +0 3293 3330 +0 3324 3278 +0 3363 3199 +0 3411 3065 +0 3467 2785 +0 3533 0 +0 3609 0 +0 3693 0 +0 3786 0 +0 3185 3456 +0 3185 3456 +0 3185 3455 +0 3185 3455 +0 3185 3455 +0 3185 3455 +0 3186 3455 +0 3186 3455 +0 3186 3454 +0 3187 3454 +0 3187 3453 +0 3188 3452 +0 3190 3451 +0 3191 3450 +0 3194 3448 +0 3197 3445 +0 3200 3441 +0 3206 3436 +0 3212 3429 +0 3221 3420 +0 3233 3407 +0 3248 3390 +0 3268 3365 +0 3293 3331 +0 3325 3279 +0 3363 3200 +0 3411 3066 +0 3467 2787 +0 3533 0 +0 3609 0 +0 3693 0 +0 3786 0 +0 3185 3456 +0 3185 3456 +0 3185 3456 +0 3185 3456 +0 3185 3456 +0 3186 3456 +0 3186 3456 +0 3186 3455 +0 3186 3455 +0 3187 3455 +0 3188 3454 +0 3189 3453 +0 3190 3452 +0 3192 3450 +0 3194 3448 +0 3197 3446 +0 3201 3442 +0 3206 3437 +0 3213 3430 +0 3222 3421 +0 3233 3408 +0 3249 3391 +0 3268 3366 +0 3293 3331 +0 3325 3280 +0 3364 3201 +0 3411 3067 +0 3467 2790 +0 3533 0 +0 3609 0 +0 3693 0 +0 3786 0 +0 3185 3457 +0 3185 3457 +0 3185 3457 +0 3185 3457 +0 3186 3457 +0 3186 3457 +0 3186 3457 +0 3186 3456 +0 3187 3456 +0 3187 3456 +0 3188 3455 +0 3189 3454 +0 3190 3453 +0 3192 3451 +0 3194 3449 +0 3197 3447 +0 3201 3443 +0 3206 3438 +0 3213 3431 +0 3222 3422 +0 3234 3409 +0 3249 3392 +0 3268 3368 +0 3293 3333 +0 3325 3282 +0 3364 3203 +0 3411 3070 +0 3467 2794 +0 3533 0 +0 3609 0 +0 3693 0 +0 3786 0 +0 3186 3459 +0 3186 3458 +0 3186 3458 +0 3186 3458 +0 3186 3458 +0 3186 3458 +0 3186 3458 +0 3187 3458 +0 3187 3457 +0 3188 3457 +0 3188 3456 +0 3189 3455 +0 3190 3454 +0 3192 3453 +0 3194 3451 +0 3197 3448 +0 3201 3444 +0 3206 3439 +0 3213 3432 +0 3222 3423 +0 3234 3411 +0 3249 3393 +0 3269 3369 +0 3294 3334 +0 3325 3283 +0 3364 3205 +0 3411 3073 +0 3468 2800 +0 3533 0 +0 3609 0 +0 3693 0 +0 3786 0 +0 3186 3460 +0 3186 3460 +0 3186 3460 +0 3186 3460 +0 3186 3460 +0 3187 3460 +0 3187 3460 +0 3187 3459 +0 3187 3459 +0 3188 3458 +0 3189 3458 +0 3190 3457 +0 3191 3456 +0 3193 3454 +0 3195 3452 +0 3198 3450 +0 3202 3446 +0 3207 3441 +0 3214 3434 +0 3223 3425 +0 3234 3413 +0 3250 3395 +0 3269 3371 +0 3294 3337 +0 3325 3286 +0 3364 3208 +0 3411 3077 +0 3468 2807 +0 3534 0 +0 3609 0 +0 3694 0 +0 3787 0 +0 3187 3462 +0 3187 3462 +0 3187 3462 +0 3187 3462 +0 3187 3462 +0 3187 3462 +0 3187 3462 +0 3188 3462 +0 3188 3461 +0 3189 3461 +0 3189 3460 +0 3190 3459 +0 3191 3458 +0 3193 3457 +0 3195 3455 +0 3198 3452 +0 3202 3448 +0 3207 3443 +0 3214 3437 +0 3223 3428 +0 3235 3415 +0 3250 3398 +0 3270 3374 +0 3295 3339 +0 3326 3289 +0 3365 3212 +0 3412 3082 +0 3468 2816 +0 3534 0 +0 3609 0 +0 3694 0 +0 3787 0 +0 3187 3465 +0 3187 3465 +0 3187 3465 +0 3188 3465 +0 3188 3465 +0 3188 3465 +0 3188 3465 +0 3188 3465 +0 3189 3464 +0 3189 3464 +0 3190 3463 +0 3191 3462 +0 3192 3461 +0 3194 3460 +0 3196 3458 +0 3199 3455 +0 3203 3451 +0 3208 3446 +0 3215 3440 +0 3224 3431 +0 3235 3418 +0 3251 3401 +0 3270 3377 +0 3295 3343 +0 3326 3293 +0 3365 3217 +0 3412 3089 +0 3469 2829 +0 3534 0 +0 3610 0 +0 3694 0 +0 3787 0 +0 3188 3469 +0 3188 3469 +0 3188 3469 +0 3189 3469 +0 3189 3469 +0 3189 3469 +0 3189 3469 +0 3189 3468 +0 3190 3468 +0 3190 3468 +0 3191 3467 +0 3192 3466 +0 3193 3465 +0 3195 3464 +0 3197 3462 +0 3200 3459 +0 3204 3455 +0 3209 3451 +0 3216 3444 +0 3225 3435 +0 3236 3423 +0 3252 3406 +0 3271 3382 +0 3296 3349 +0 3327 3299 +0 3366 3224 +0 3413 3098 +0 3469 2844 +0 3535 106 +0 3610 0 +0 3694 0 +0 3787 0 +0 3190 3475 +0 3190 3475 +0 3190 3474 +0 3190 3474 +0 3190 3474 +0 3190 3474 +0 3190 3474 +0 3191 3474 +0 3191 3473 +0 3192 3473 +0 3192 3472 +0 3193 3471 +0 3195 3470 +0 3196 3469 +0 3198 3467 +0 3201 3464 +0 3205 3461 +0 3210 3456 +0 3217 3449 +0 3226 3441 +0 3238 3429 +0 3253 3412 +0 3272 3389 +0 3297 3355 +0 3328 3307 +0 3367 3233 +0 3414 3109 +0 3470 2865 +0 3535 1466 +0 3611 0 +0 3695 0 +0 3788 0 +0 3192 3481 +0 3192 3481 +0 3192 3481 +0 3192 3481 +0 3192 3481 +0 3192 3481 +0 3192 3481 +0 3193 3481 +0 3193 3480 +0 3193 3480 +0 3194 3479 +0 3195 3478 +0 3196 3477 +0 3198 3476 +0 3200 3474 +0 3203 3471 +0 3207 3468 +0 3212 3463 +0 3219 3457 +0 3228 3448 +0 3239 3436 +0 3254 3420 +0 3274 3397 +0 3298 3364 +0 3329 3317 +0 3368 3244 +0 3415 3125 +0 3471 2891 +0 3536 1839 +0 3611 0 +0 3695 0 +0 3788 0 +0 3194 3491 +0 3194 3491 +0 3194 3490 +0 3194 3490 +0 3194 3490 +0 3194 3490 +0 3195 3490 +0 3195 3490 +0 3195 3489 +0 3196 3489 +0 3197 3488 +0 3197 3488 +0 3199 3487 +0 3200 3485 +0 3202 3483 +0 3205 3481 +0 3209 3477 +0 3214 3473 +0 3221 3466 +0 3230 3458 +0 3241 3446 +0 3256 3430 +0 3276 3408 +0 3300 3376 +0 3331 3330 +0 3370 3259 +0 3416 3144 +0 3472 2923 +0 3537 2093 +0 3612 0 +0 3696 0 +0 3789 0 +0 3197 3502 +0 3197 3502 +0 3197 3502 +0 3197 3502 +0 3197 3502 +0 3198 3502 +0 3198 3502 +0 3198 3502 +0 3199 3501 +0 3199 3501 +0 3200 3500 +0 3201 3500 +0 3202 3498 +0 3203 3497 +0 3206 3495 +0 3209 3493 +0 3212 3489 +0 3217 3485 +0 3224 3479 +0 3233 3471 +0 3244 3459 +0 3259 3444 +0 3278 3422 +0 3303 3391 +0 3334 3347 +0 3372 3279 +0 3418 3169 +0 3474 2963 +0 3539 2299 +0 3613 0 +0 3697 0 +0 3790 0 +0 3201 3518 +0 3201 3518 +0 3202 3518 +0 3202 3518 +0 3202 3518 +0 3202 3517 +0 3202 3517 +0 3202 3517 +0 3203 3517 +0 3203 3516 +0 3204 3516 +0 3205 3515 +0 3206 3514 +0 3208 3513 +0 3210 3511 +0 3213 3508 +0 3216 3505 +0 3221 3501 +0 3228 3495 +0 3237 3487 +0 3248 3476 +0 3263 3461 +0 3282 3440 +0 3306 3411 +0 3337 3368 +0 3375 3304 +0 3421 3201 +0 3476 3012 +0 3541 2479 +0 3615 0 +0 3699 0 +0 3791 0 +0 3207 3538 +0 3207 3538 +0 3207 3537 +0 3207 3537 +0 3207 3537 +0 3207 3537 +0 3208 3537 +0 3208 3537 +0 3208 3537 +0 3209 3536 +0 3210 3536 +0 3210 3535 +0 3212 3534 +0 3213 3533 +0 3215 3531 +0 3218 3529 +0 3222 3526 +0 3227 3521 +0 3233 3516 +0 3242 3508 +0 3253 3498 +0 3268 3483 +0 3287 3464 +0 3311 3436 +0 3341 3395 +0 3379 3335 +0 3424 3240 +0 3479 3069 +0 3544 2644 +0 3617 0 +0 3701 0 +0 3792 0 +1728 3214 3563 +1725 3214 3563 +1722 3215 3563 +1717 3215 3563 +1710 3215 3563 +1701 3215 3562 +1688 3215 3562 +1671 3215 3562 +1647 3216 3562 +1612 3216 3561 +1562 3217 3561 +1483 3218 3560 +1352 3219 3559 +1082 3220 3558 +0 3223 3557 +0 3225 3554 +0 3229 3551 +0 3234 3548 +0 3240 3542 +0 3249 3535 +0 3260 3525 +0 3274 3512 +0 3293 3493 +0 3317 3467 +0 3346 3429 +0 3384 3374 +0 3429 3287 +0 3483 3137 +0 3547 2799 +0 3620 0 +0 3703 0 +0 3794 0 +2722 3224 3594 +2721 3224 3594 +2721 3224 3594 +2720 3224 3594 +2720 3224 3594 +2719 3225 3594 +2717 3225 3594 +2716 3225 3594 +2713 3225 3593 +2710 3226 3593 +2706 3227 3593 +2700 3227 3592 +2692 3229 3591 +2681 3230 3590 +2666 3232 3589 +2646 3235 3587 +2617 3238 3584 +2574 3243 3580 +2511 3250 3575 +2410 3258 3569 +2224 3269 3559 +1718 3283 3547 +0 3301 3530 +0 3324 3506 +0 3354 3471 +0 3390 3421 +0 3435 3343 +0 3489 3214 +0 3552 2948 +0 3624 0 +0 3706 0 +0 3797 0 +3077 3237 3634 +3077 3237 3634 +3077 3237 3633 +3077 3237 3633 +3076 3237 3633 +3076 3237 3633 +3075 3237 3633 +3075 3238 3633 +3073 3238 3633 +3072 3239 3632 +3070 3239 3632 +3068 3240 3631 +3064 3241 3631 +3059 3243 3630 +3053 3245 3628 +3044 3247 3626 +3032 3251 3624 +3016 3255 3621 +2993 3262 3616 +2960 3270 3610 +2913 3280 3602 +2840 3294 3590 +2720 3312 3575 +2485 3335 3553 +1404 3363 3522 +0 3399 3477 +0 3443 3409 +0 3496 3299 +0 3558 3092 +0 3630 2417 +0 3711 0 +0 3801 0 +3325 3253 3681 +3325 3253 3681 +3325 3253 3681 +3325 3253 3681 +3325 3254 3681 +3325 3254 3681 +3324 3254 3681 +3324 3254 3681 +3323 3254 3680 +3322 3255 3680 +3321 3255 3680 +3320 3256 3679 +3318 3257 3678 +3315 3259 3678 +3311 3261 3676 +3306 3263 3675 +3300 3267 3672 +3291 3271 3669 +3278 3277 3665 +3261 3285 3660 +3237 3295 3652 +3203 3308 3642 +3153 3326 3628 +3076 3348 3609 +2947 3376 3582 +2685 3411 3543 +0 3454 3485 +0 3505 3394 +0 3566 3233 +0 3637 2852 +0 3717 0 +0 3805 0 +3528 3274 3738 +3528 3274 3738 +3528 3274 3738 +3528 3274 3738 +3528 3275 3738 +3528 3275 3738 +3527 3275 3737 +3527 3275 3737 +3527 3275 3737 +3526 3276 3737 +3525 3276 3737 +3525 3277 3736 +3523 3278 3735 +3522 3280 3735 +3519 3281 3734 +3516 3284 3732 +3512 3287 3730 +3506 3291 3728 +3499 3297 3724 +3488 3305 3719 +3474 3314 3713 +3454 3327 3704 +3426 3344 3692 +3385 3365 3675 +3324 3392 3652 +3228 3426 3618 +3055 3467 3570 +2618 3517 3495 +0 3577 3371 +0 3646 3125 +0 3724 1639 +0 3812 0 +3707 3301 3804 +3707 3301 3804 +3707 3301 3804 +3707 3301 3804 +3707 3301 3804 +3706 3301 3804 +3706 3302 3804 +3706 3302 3804 +3706 3302 3803 +3705 3303 3803 +3705 3303 3803 +3704 3304 3803 +3703 3305 3802 +3702 3306 3801 +3701 3308 3800 +3699 3310 3799 +3696 3313 3797 +3692 3317 3795 +3687 3323 3792 +3680 3330 3788 +3671 3339 3782 +3658 3351 3775 +3640 3367 3764 +3615 3387 3750 +3580 3413 3730 +3527 3445 3703 +3446 3485 3663 +3308 3533 3603 +3017 3591 3508 +0 3658 3340 +0 3734 2924 +0 3820 0 +3871 3334 3880 +3871 3334 3880 +3871 3335 3880 +3871 3335 3880 +3871 3335 3880 +3871 3335 3880 +3870 3335 3880 +3870 3335 3879 +3870 3335 3879 +3870 3336 3879 +3869 3336 3879 +3869 3337 3879 +3868 3338 3878 +3868 3339 3878 +3867 3341 3877 +3865 3343 3876 +3863 3346 3874 +3861 3349 3872 +3857 3354 3870 +3852 3361 3866 +3846 3370 3862 +3837 3381 3855 +3825 3396 3846 +3809 3415 3835 +3786 3439 3818 +3753 3470 3796 +3706 3507 3763 +3633 3554 3716 +3513 3609 3644 +3279 3673 3525 +2216 3748 3294 +0 3831 2303 +4025 3376 3965 +4025 3376 3965 +4025 3376 3965 +4025 3376 3965 +4025 3376 3965 +4025 3376 3965 +4025 3376 3964 +4025 3376 3964 +4025 3377 3964 +4025 3377 3964 +4024 3377 3964 +4024 3378 3964 +4024 3379 3963 +4023 3380 3963 +4022 3381 3962 +4021 3383 3961 +4020 3386 3960 +4018 3389 3958 +4016 3394 3956 +4012 3400 3953 +4008 3408 3950 +4002 3418 3944 +3993 3432 3937 +3982 3450 3928 +3967 3472 3914 +3945 3501 3896 +3914 3536 3870 +3870 3579 3833 +3803 3632 3779 +3693 3693 3693 +3489 3765 3547 +2837 3845 3224 +4095 3425 4058 +4095 3426 4058 +4095 3426 4058 +4095 3426 4058 +4095 3426 4058 +4095 3426 4058 +4095 3426 4058 +4095 3426 4058 +4095 3426 4058 +4095 3427 4057 +4095 3427 4057 +4095 3428 4057 +4095 3428 4057 +4095 3429 4056 +4095 3431 4056 +4095 3432 4055 +4095 3435 4054 +4095 3438 4053 +4095 3442 4051 +4095 3447 4049 +4095 3455 4046 +4095 3464 4041 +4095 3476 4036 +4095 3492 4028 +4095 3513 4017 +4095 3539 4003 +4095 3572 3982 +4067 3612 3954 +4024 3661 3913 +3961 3719 3851 +3858 3787 3752 +3671 3864 3575 +4095 3485 4095 +4095 3485 4095 +4095 3485 4095 +4095 3485 4095 +4095 3485 4095 +4095 3485 4095 +4095 3485 4095 +4095 3485 4095 +4095 3485 4095 +4095 3486 4095 +4095 3486 4095 +4095 3486 4095 +4095 3487 4095 +4095 3488 4095 +4095 3489 4095 +4095 3491 4095 +4095 3493 4095 +4095 3495 4095 +4095 3499 4095 +4095 3504 4095 +4095 3510 4095 +4095 3519 4095 +4095 3530 4095 +4095 3544 4095 +4095 3562 4095 +4095 3586 4095 +4095 3615 4095 +4095 3652 4077 +4095 3697 4046 +4095 3751 4001 +4095 3814 3932 +4014 3887 3821 +0 3316 3586 +0 3316 3586 +0 3317 3586 +0 3317 3586 +0 3317 3586 +0 3317 3585 +0 3317 3585 +0 3317 3585 +0 3317 3585 +0 3318 3584 +0 3318 3584 +0 3319 3583 +0 3320 3582 +0 3321 3581 +0 3323 3580 +0 3325 3578 +0 3328 3575 +0 3332 3571 +0 3337 3566 +0 3344 3559 +0 3353 3550 +0 3365 3537 +0 3380 3520 +0 3400 3495 +0 3425 3460 +0 3456 3408 +0 3495 3328 +0 3543 3193 +0 3599 2911 +0 3665 0 +0 3740 0 +0 3825 0 +0 3316 3586 +0 3316 3586 +0 3317 3586 +0 3317 3586 +0 3317 3586 +0 3317 3585 +0 3317 3585 +0 3317 3585 +0 3317 3585 +0 3318 3585 +0 3318 3584 +0 3319 3583 +0 3320 3583 +0 3321 3581 +0 3323 3580 +0 3325 3578 +0 3328 3575 +0 3332 3571 +0 3337 3566 +0 3344 3559 +0 3353 3550 +0 3365 3537 +0 3380 3520 +0 3400 3495 +0 3425 3460 +0 3456 3408 +0 3495 3328 +0 3543 3193 +0 3599 2911 +0 3665 0 +0 3741 0 +0 3825 0 +0 3316 3586 +0 3316 3586 +0 3317 3586 +0 3317 3586 +0 3317 3586 +0 3317 3586 +0 3317 3585 +0 3317 3585 +0 3318 3585 +0 3318 3585 +0 3318 3584 +0 3319 3583 +0 3320 3583 +0 3321 3581 +0 3323 3580 +0 3325 3578 +0 3328 3575 +0 3332 3571 +0 3337 3566 +0 3344 3560 +0 3353 3550 +0 3365 3538 +0 3380 3520 +0 3400 3495 +0 3425 3460 +0 3456 3408 +0 3495 3329 +0 3543 3194 +0 3599 2911 +0 3665 0 +0 3741 0 +0 3825 0 +0 3316 3586 +0 3317 3586 +0 3317 3586 +0 3317 3586 +0 3317 3586 +0 3317 3586 +0 3317 3585 +0 3317 3585 +0 3318 3585 +0 3318 3585 +0 3318 3584 +0 3319 3584 +0 3320 3583 +0 3321 3582 +0 3323 3580 +0 3325 3578 +0 3328 3575 +0 3332 3571 +0 3337 3566 +0 3344 3560 +0 3353 3550 +0 3365 3538 +0 3380 3520 +0 3400 3495 +0 3425 3460 +0 3456 3409 +0 3495 3329 +0 3543 3194 +0 3599 2912 +0 3665 0 +0 3741 0 +0 3825 0 +0 3317 3586 +0 3317 3586 +0 3317 3586 +0 3317 3586 +0 3317 3586 +0 3317 3586 +0 3317 3586 +0 3317 3585 +0 3318 3585 +0 3318 3585 +0 3318 3584 +0 3319 3584 +0 3320 3583 +0 3321 3582 +0 3323 3580 +0 3325 3578 +0 3328 3575 +0 3332 3572 +0 3337 3567 +0 3344 3560 +0 3353 3551 +0 3365 3538 +0 3380 3520 +0 3400 3496 +0 3425 3460 +0 3456 3409 +0 3495 3329 +0 3543 3194 +0 3599 2912 +0 3665 0 +0 3741 0 +0 3825 0 +0 3317 3586 +0 3317 3586 +0 3317 3586 +0 3317 3586 +0 3317 3586 +0 3317 3586 +0 3317 3586 +0 3317 3586 +0 3318 3585 +0 3318 3585 +0 3319 3584 +0 3319 3584 +0 3320 3583 +0 3321 3582 +0 3323 3580 +0 3325 3578 +0 3328 3576 +0 3332 3572 +0 3337 3567 +0 3344 3560 +0 3353 3551 +0 3365 3538 +0 3380 3520 +0 3400 3496 +0 3425 3461 +0 3456 3409 +0 3495 3329 +0 3543 3194 +0 3599 2913 +0 3665 0 +0 3741 0 +0 3825 0 +0 3317 3586 +0 3317 3586 +0 3317 3586 +0 3317 3586 +0 3317 3586 +0 3317 3586 +0 3317 3586 +0 3317 3586 +0 3318 3586 +0 3318 3585 +0 3319 3585 +0 3319 3584 +0 3320 3583 +0 3321 3582 +0 3323 3581 +0 3325 3579 +0 3328 3576 +0 3332 3572 +0 3337 3567 +0 3344 3560 +0 3353 3551 +0 3365 3538 +0 3380 3521 +0 3400 3496 +0 3425 3461 +0 3456 3409 +0 3495 3330 +0 3543 3195 +0 3599 2914 +0 3665 0 +0 3741 0 +0 3825 0 +0 3317 3587 +0 3317 3587 +0 3317 3587 +0 3317 3587 +0 3317 3587 +0 3317 3586 +0 3317 3586 +0 3317 3586 +0 3318 3586 +0 3318 3585 +0 3319 3585 +0 3319 3584 +0 3320 3584 +0 3322 3582 +0 3323 3581 +0 3325 3579 +0 3328 3576 +0 3332 3572 +0 3338 3567 +0 3344 3561 +0 3353 3551 +0 3365 3539 +0 3380 3521 +0 3400 3496 +0 3425 3461 +0 3456 3410 +0 3495 3330 +0 3543 3196 +0 3599 2915 +0 3665 0 +0 3741 0 +0 3825 0 +0 3317 3587 +0 3317 3587 +0 3317 3587 +0 3317 3587 +0 3317 3587 +0 3317 3587 +0 3317 3587 +0 3318 3587 +0 3318 3586 +0 3318 3586 +0 3319 3585 +0 3319 3585 +0 3320 3584 +0 3322 3583 +0 3323 3581 +0 3326 3579 +0 3328 3576 +0 3332 3573 +0 3338 3568 +0 3344 3561 +0 3353 3552 +0 3365 3539 +0 3380 3521 +0 3400 3497 +0 3425 3462 +0 3457 3410 +0 3495 3331 +0 3543 3197 +0 3599 2917 +0 3665 0 +0 3741 0 +0 3825 0 +0 3317 3588 +0 3317 3588 +0 3317 3588 +0 3317 3588 +0 3317 3587 +0 3317 3587 +0 3317 3587 +0 3318 3587 +0 3318 3587 +0 3318 3586 +0 3319 3586 +0 3320 3585 +0 3321 3584 +0 3322 3583 +0 3323 3582 +0 3326 3580 +0 3329 3577 +0 3333 3573 +0 3338 3568 +0 3345 3561 +0 3354 3552 +0 3365 3540 +0 3381 3522 +0 3400 3498 +0 3425 3463 +0 3457 3411 +0 3496 3332 +0 3543 3198 +0 3599 2919 +0 3665 0 +0 3741 0 +0 3825 0 +0 3317 3588 +0 3317 3588 +0 3317 3588 +0 3317 3588 +0 3317 3588 +0 3317 3588 +0 3318 3588 +0 3318 3588 +0 3318 3587 +0 3319 3587 +0 3319 3587 +0 3320 3586 +0 3321 3585 +0 3322 3584 +0 3324 3583 +0 3326 3580 +0 3329 3578 +0 3333 3574 +0 3338 3569 +0 3345 3562 +0 3354 3553 +0 3365 3540 +0 3381 3523 +0 3400 3498 +0 3425 3464 +0 3457 3412 +0 3496 3333 +0 3543 3200 +0 3599 2922 +0 3665 0 +0 3741 0 +0 3825 0 +0 3317 3589 +0 3317 3589 +0 3317 3589 +0 3317 3589 +0 3318 3589 +0 3318 3589 +0 3318 3589 +0 3318 3589 +0 3318 3588 +0 3319 3588 +0 3319 3588 +0 3320 3587 +0 3321 3586 +0 3322 3585 +0 3324 3583 +0 3326 3581 +0 3329 3579 +0 3333 3575 +0 3338 3570 +0 3345 3563 +0 3354 3554 +0 3366 3541 +0 3381 3524 +0 3401 3500 +0 3426 3465 +0 3457 3414 +0 3496 3335 +0 3543 3202 +0 3600 2927 +0 3665 0 +0 3741 0 +0 3825 0 +0 3318 3591 +0 3318 3591 +0 3318 3591 +0 3318 3590 +0 3318 3590 +0 3318 3590 +0 3318 3590 +0 3318 3590 +0 3319 3590 +0 3319 3589 +0 3320 3589 +0 3320 3588 +0 3321 3587 +0 3323 3586 +0 3324 3585 +0 3326 3583 +0 3329 3580 +0 3333 3576 +0 3338 3571 +0 3345 3565 +0 3354 3555 +0 3366 3543 +0 3381 3525 +0 3401 3501 +0 3426 3466 +0 3457 3415 +0 3496 3337 +0 3543 3205 +0 3600 2932 +0 3666 0 +0 3741 0 +0 3826 0 +0 3318 3592 +0 3318 3592 +0 3318 3592 +0 3318 3592 +0 3318 3592 +0 3318 3592 +0 3319 3592 +0 3319 3592 +0 3319 3591 +0 3320 3591 +0 3320 3591 +0 3321 3590 +0 3322 3589 +0 3323 3588 +0 3325 3586 +0 3327 3584 +0 3330 3582 +0 3334 3578 +0 3339 3573 +0 3346 3566 +0 3355 3557 +0 3366 3545 +0 3382 3527 +0 3401 3503 +0 3426 3469 +0 3458 3418 +0 3496 3340 +0 3544 3209 +0 3600 2939 +0 3666 0 +0 3741 0 +0 3826 0 +0 3319 3595 +0 3319 3595 +0 3319 3594 +0 3319 3594 +0 3319 3594 +0 3319 3594 +0 3319 3594 +0 3319 3594 +0 3320 3594 +0 3320 3593 +0 3321 3593 +0 3321 3592 +0 3322 3591 +0 3324 3590 +0 3325 3589 +0 3327 3587 +0 3330 3584 +0 3334 3580 +0 3339 3575 +0 3346 3569 +0 3355 3560 +0 3367 3547 +0 3382 3530 +0 3402 3506 +0 3427 3472 +0 3458 3421 +0 3497 3344 +0 3544 3214 +0 3600 2948 +0 3666 0 +0 3741 0 +0 3826 0 +0 3319 3598 +0 3319 3597 +0 3320 3597 +0 3320 3597 +0 3320 3597 +0 3320 3597 +0 3320 3597 +0 3320 3597 +0 3320 3597 +0 3321 3596 +0 3321 3596 +0 3322 3595 +0 3323 3594 +0 3324 3593 +0 3326 3592 +0 3328 3590 +0 3331 3587 +0 3335 3583 +0 3340 3579 +0 3347 3572 +0 3356 3563 +0 3368 3550 +0 3383 3533 +0 3402 3510 +0 3427 3475 +0 3459 3426 +0 3497 3349 +0 3544 3221 +0 3601 2961 +0 3666 0 +0 3742 0 +0 3826 0 +0 3320 3601 +0 3320 3601 +0 3321 3601 +0 3321 3601 +0 3321 3601 +0 3321 3601 +0 3321 3601 +0 3321 3601 +0 3321 3601 +0 3322 3600 +0 3322 3600 +0 3323 3599 +0 3324 3598 +0 3325 3597 +0 3327 3596 +0 3329 3594 +0 3332 3591 +0 3336 3587 +0 3341 3583 +0 3348 3576 +0 3357 3567 +0 3368 3555 +0 3384 3538 +0 3403 3514 +0 3428 3481 +0 3459 3431 +0 3498 3356 +0 3545 3230 +0 3601 2976 +0 3667 238 +0 3742 0 +0 3826 0 +0 3322 3607 +0 3322 3607 +0 3322 3607 +0 3322 3607 +0 3322 3606 +0 3322 3606 +0 3322 3606 +0 3323 3606 +0 3323 3606 +0 3323 3605 +0 3324 3605 +0 3324 3604 +0 3325 3604 +0 3327 3603 +0 3328 3601 +0 3330 3599 +0 3333 3596 +0 3337 3593 +0 3342 3588 +0 3349 3582 +0 3358 3573 +0 3370 3561 +0 3385 3544 +0 3404 3521 +0 3429 3487 +0 3460 3439 +0 3499 3365 +0 3546 3241 +0 3602 2997 +0 3668 1599 +0 3743 0 +0 3827 0 +0 3324 3614 +0 3324 3614 +0 3324 3614 +0 3324 3613 +0 3324 3613 +0 3324 3613 +0 3324 3613 +0 3324 3613 +0 3325 3613 +0 3325 3612 +0 3326 3612 +0 3326 3611 +0 3327 3611 +0 3328 3609 +0 3330 3608 +0 3332 3606 +0 3335 3603 +0 3339 3600 +0 3344 3595 +0 3351 3589 +0 3360 3580 +0 3371 3568 +0 3386 3552 +0 3406 3529 +0 3431 3496 +0 3462 3449 +0 3500 3376 +0 3547 3257 +0 3603 3023 +0 3668 1971 +0 3743 0 +0 3827 0 +0 3326 3623 +0 3326 3623 +0 3326 3623 +0 3326 3623 +0 3326 3622 +0 3326 3622 +0 3327 3622 +0 3327 3622 +0 3327 3622 +0 3327 3621 +0 3328 3621 +0 3329 3620 +0 3330 3620 +0 3331 3619 +0 3332 3617 +0 3335 3615 +0 3337 3613 +0 3341 3609 +0 3346 3605 +0 3353 3598 +0 3362 3590 +0 3374 3578 +0 3388 3562 +0 3408 3540 +0 3432 3508 +0 3463 3462 +0 3502 3392 +0 3548 3276 +0 3604 3055 +0 3669 2225 +0 3744 0 +0 3828 0 +0 3329 3635 +0 3329 3635 +0 3329 3634 +0 3329 3634 +0 3329 3634 +0 3330 3634 +0 3330 3634 +0 3330 3634 +0 3330 3634 +0 3331 3633 +0 3331 3633 +0 3332 3632 +0 3333 3632 +0 3334 3631 +0 3336 3629 +0 3338 3627 +0 3341 3625 +0 3344 3622 +0 3349 3617 +0 3356 3611 +0 3365 3603 +0 3376 3591 +0 3391 3576 +0 3410 3554 +0 3435 3523 +0 3466 3479 +0 3504 3411 +0 3550 3301 +0 3606 3095 +0 3671 2431 +0 3746 0 +0 3829 0 +0 3333 3650 +0 3333 3650 +0 3334 3650 +0 3334 3650 +0 3334 3650 +0 3334 3650 +0 3334 3649 +0 3334 3649 +0 3334 3649 +0 3335 3649 +0 3335 3648 +0 3336 3648 +0 3337 3647 +0 3338 3646 +0 3340 3645 +0 3342 3643 +0 3345 3641 +0 3349 3637 +0 3354 3633 +0 3360 3627 +0 3369 3619 +0 3380 3608 +0 3395 3593 +0 3414 3572 +0 3438 3543 +0 3469 3500 +0 3507 3436 +0 3553 3333 +0 3608 3144 +0 3673 2611 +0 3747 0 +0 3831 0 +0 3339 3670 +0 3339 3670 +0 3339 3670 +0 3339 3670 +0 3339 3670 +0 3339 3669 +0 3340 3669 +0 3340 3669 +0 3340 3669 +0 3340 3669 +0 3341 3668 +0 3342 3668 +0 3343 3667 +0 3344 3666 +0 3345 3665 +0 3347 3663 +0 3350 3661 +0 3354 3658 +0 3359 3654 +0 3365 3648 +0 3374 3640 +0 3385 3630 +0 3400 3616 +0 3419 3596 +0 3443 3568 +0 3473 3527 +0 3511 3467 +0 3556 3372 +0 3611 3202 +0 3676 2776 +0 3750 0 +0 3833 0 +1862 3346 3695 +1860 3347 3695 +1858 3347 3695 +1854 3347 3695 +1849 3347 3695 +1842 3347 3695 +1833 3347 3695 +1821 3347 3694 +1803 3347 3694 +1779 3348 3694 +1744 3348 3693 +1694 3349 3693 +1616 3350 3692 +1484 3351 3691 +1214 3353 3690 +0 3355 3689 +0 3357 3686 +0 3361 3684 +0 3366 3680 +0 3372 3674 +0 3381 3667 +0 3392 3657 +0 3406 3644 +0 3425 3625 +0 3449 3599 +0 3479 3562 +0 3516 3506 +0 3561 3419 +0 3615 3269 +0 3679 2931 +0 3753 0 +0 3835 0 +2854 3356 3727 +2854 3356 3727 +2853 3356 3726 +2853 3356 3726 +2853 3356 3726 +2852 3357 3726 +2851 3357 3726 +2849 3357 3726 +2848 3357 3726 +2845 3358 3726 +2842 3358 3725 +2838 3359 3725 +2832 3360 3724 +2824 3361 3723 +2813 3362 3722 +2798 3364 3721 +2778 3367 3719 +2749 3371 3716 +2706 3375 3712 +2643 3382 3707 +2542 3390 3701 +2357 3401 3692 +1850 3415 3679 +0 3433 3662 +0 3456 3638 +0 3486 3604 +0 3522 3553 +0 3567 3476 +0 3621 3346 +0 3684 3080 +0 3757 0 +0 3838 0 +3210 3369 3766 +3209 3369 3766 +3209 3369 3766 +3209 3369 3766 +3209 3369 3766 +3209 3369 3765 +3208 3369 3765 +3207 3370 3765 +3207 3370 3765 +3206 3370 3765 +3204 3371 3764 +3202 3371 3764 +3200 3372 3763 +3196 3373 3763 +3191 3375 3762 +3185 3377 3760 +3176 3379 3758 +3164 3383 3756 +3148 3387 3753 +3125 3394 3748 +3092 3402 3742 +3045 3412 3734 +2972 3426 3722 +2852 3444 3707 +2617 3467 3685 +1537 3495 3654 +0 3531 3609 +0 3575 3542 +0 3628 3431 +0 3690 3224 +0 3762 2549 +0 3843 0 +3457 3385 3813 +3457 3385 3813 +3457 3385 3813 +3457 3385 3813 +3457 3385 3813 +3457 3386 3813 +3457 3386 3813 +3456 3386 3813 +3456 3386 3813 +3455 3387 3812 +3454 3387 3812 +3453 3388 3812 +3452 3388 3811 +3450 3389 3811 +3447 3391 3810 +3443 3393 3808 +3439 3395 3807 +3432 3399 3805 +3423 3403 3802 +3410 3409 3797 +3393 3417 3792 +3369 3427 3785 +3335 3441 3774 +3285 3458 3761 +3208 3480 3741 +3079 3508 3714 +2817 3543 3675 +0 3586 3617 +0 3637 3526 +0 3698 3365 +0 3769 2984 +0 3849 0 +3660 3406 3870 +3660 3406 3870 +3660 3406 3870 +3660 3406 3870 +3660 3407 3870 +3660 3407 3870 +3660 3407 3870 +3660 3407 3870 +3659 3407 3869 +3659 3408 3869 +3658 3408 3869 +3658 3409 3869 +3657 3409 3868 +3655 3410 3868 +3654 3412 3867 +3651 3414 3866 +3648 3416 3864 +3644 3419 3862 +3638 3424 3860 +3631 3429 3856 +3620 3437 3851 +3606 3446 3845 +3586 3459 3836 +3558 3476 3824 +3517 3497 3807 +3456 3524 3784 +3360 3558 3750 +3187 3599 3702 +2750 3650 3627 +0 3709 3503 +0 3778 3257 +0 3856 1771 +3839 3433 3936 +3839 3433 3936 +3839 3433 3936 +3839 3433 3936 +3839 3433 3936 +3839 3433 3936 +3838 3433 3936 +3838 3434 3936 +3838 3434 3936 +3838 3434 3936 +3838 3435 3935 +3837 3435 3935 +3836 3436 3935 +3836 3437 3934 +3834 3438 3933 +3833 3440 3932 +3831 3442 3931 +3828 3445 3930 +3824 3449 3927 +3819 3455 3924 +3812 3462 3920 +3803 3471 3914 +3790 3483 3907 +3772 3499 3897 +3747 3519 3882 +3712 3545 3863 +3659 3577 3835 +3578 3617 3795 +3440 3665 3735 +3149 3723 3640 +0 3790 3472 +0 3867 3056 +4003 3467 4012 +4003 3467 4012 +4003 3467 4012 +4003 3467 4012 +4003 3467 4012 +4003 3467 4012 +4003 3467 4012 +4002 3467 4012 +4002 3467 4012 +4002 3468 4011 +4002 3468 4011 +4002 3468 4011 +4001 3469 4011 +4001 3470 4010 +4000 3471 4010 +3999 3473 4009 +3997 3475 4008 +3995 3478 4006 +3993 3482 4004 +3989 3487 4002 +3984 3493 3998 +3978 3502 3994 +3969 3513 3987 +3957 3528 3979 +3941 3547 3967 +3918 3571 3950 +3886 3602 3928 +3838 3640 3895 +3765 3686 3848 +3646 3741 3776 +3411 3806 3657 +2348 3880 3426 +4095 3508 4095 +4095 3508 4095 +4095 3508 4095 +4095 3508 4095 +4095 3508 4095 +4095 3508 4095 +4095 3508 4095 +4095 3508 4095 +4095 3508 4095 +4095 3509 4095 +4095 3509 4095 +4095 3509 4095 +4095 3510 4095 +4095 3511 4095 +4095 3512 4095 +4095 3513 4094 +4095 3515 4093 +4095 3518 4092 +4095 3522 4091 +4095 3526 4088 +4095 3532 4086 +4095 3540 4082 +4095 3551 4076 +4095 3564 4069 +4095 3582 4060 +4095 3604 4046 +4077 3633 4028 +4046 3668 4002 +4002 3712 3965 +3935 3764 3911 +3826 3826 3826 +3621 3897 3679 +4095 3558 4095 +4095 3558 4095 +4095 3558 4095 +4095 3558 4095 +4095 3558 4095 +4095 3558 4095 +4095 3558 4095 +4095 3558 4095 +4095 3558 4095 +4095 3558 4095 +4095 3559 4095 +4095 3559 4095 +4095 3560 4095 +4095 3560 4095 +4095 3561 4095 +4095 3563 4095 +4095 3564 4095 +4095 3567 4095 +4095 3570 4095 +4095 3574 4095 +4095 3580 4095 +4095 3587 4095 +4095 3596 4095 +4095 3608 4095 +4095 3624 4095 +4095 3645 4095 +4095 3671 4095 +4095 3704 4095 +4095 3744 4086 +4095 3793 4045 +4093 3851 3983 +3990 3919 3884 +0 3448 3718 +0 3449 3718 +0 3449 3718 +0 3449 3718 +0 3449 3718 +0 3449 3718 +0 3449 3717 +0 3449 3717 +0 3449 3717 +0 3450 3717 +0 3450 3717 +0 3450 3716 +0 3451 3715 +0 3452 3715 +0 3453 3713 +0 3455 3712 +0 3457 3710 +0 3460 3707 +0 3464 3703 +0 3469 3698 +0 3476 3691 +0 3485 3682 +0 3497 3669 +0 3512 3652 +0 3532 3627 +0 3557 3592 +0 3588 3540 +0 3627 3460 +0 3675 3325 +0 3731 3043 +0 3797 0 +0 3873 0 +0 3448 3718 +0 3449 3718 +0 3449 3718 +0 3449 3718 +0 3449 3718 +0 3449 3718 +0 3449 3718 +0 3449 3717 +0 3449 3717 +0 3450 3717 +0 3450 3717 +0 3451 3716 +0 3451 3715 +0 3452 3715 +0 3453 3713 +0 3455 3712 +0 3457 3710 +0 3460 3707 +0 3464 3703 +0 3469 3698 +0 3476 3692 +0 3485 3682 +0 3497 3670 +0 3512 3652 +0 3532 3627 +0 3557 3592 +0 3588 3540 +0 3627 3460 +0 3675 3325 +0 3731 3043 +0 3797 0 +0 3873 0 +0 3449 3718 +0 3449 3718 +0 3449 3718 +0 3449 3718 +0 3449 3718 +0 3449 3718 +0 3449 3718 +0 3449 3717 +0 3449 3717 +0 3450 3717 +0 3450 3717 +0 3451 3716 +0 3451 3716 +0 3452 3715 +0 3453 3714 +0 3455 3712 +0 3457 3710 +0 3460 3707 +0 3464 3703 +0 3469 3698 +0 3476 3692 +0 3485 3682 +0 3497 3670 +0 3512 3652 +0 3532 3627 +0 3557 3592 +0 3588 3540 +0 3627 3461 +0 3675 3326 +0 3731 3043 +0 3797 0 +0 3873 0 +0 3449 3718 +0 3449 3718 +0 3449 3718 +0 3449 3718 +0 3449 3718 +0 3449 3718 +0 3449 3718 +0 3449 3718 +0 3449 3717 +0 3450 3717 +0 3450 3717 +0 3451 3716 +0 3451 3716 +0 3452 3715 +0 3453 3714 +0 3455 3712 +0 3457 3710 +0 3460 3707 +0 3464 3703 +0 3469 3698 +0 3476 3692 +0 3485 3682 +0 3497 3670 +0 3512 3652 +0 3532 3627 +0 3557 3592 +0 3588 3541 +0 3627 3461 +0 3675 3326 +0 3731 3043 +0 3797 0 +0 3873 0 +0 3449 3718 +0 3449 3718 +0 3449 3718 +0 3449 3718 +0 3449 3718 +0 3449 3718 +0 3449 3718 +0 3449 3718 +0 3449 3717 +0 3450 3717 +0 3450 3717 +0 3451 3716 +0 3451 3716 +0 3452 3715 +0 3453 3714 +0 3455 3712 +0 3457 3710 +0 3460 3707 +0 3464 3704 +0 3469 3699 +0 3476 3692 +0 3485 3682 +0 3497 3670 +0 3512 3652 +0 3532 3628 +0 3557 3592 +0 3588 3541 +0 3627 3461 +0 3675 3326 +0 3731 3044 +0 3797 0 +0 3873 0 +0 3449 3718 +0 3449 3718 +0 3449 3718 +0 3449 3718 +0 3449 3718 +0 3449 3718 +0 3449 3718 +0 3449 3718 +0 3449 3718 +0 3450 3717 +0 3450 3717 +0 3451 3716 +0 3451 3716 +0 3452 3715 +0 3453 3714 +0 3455 3712 +0 3457 3710 +0 3460 3707 +0 3464 3704 +0 3469 3699 +0 3476 3692 +0 3485 3683 +0 3497 3670 +0 3512 3652 +0 3532 3628 +0 3557 3593 +0 3588 3541 +0 3627 3461 +0 3675 3326 +0 3731 3044 +0 3797 0 +0 3873 0 +0 3449 3718 +0 3449 3718 +0 3449 3718 +0 3449 3718 +0 3449 3718 +0 3449 3718 +0 3449 3718 +0 3449 3718 +0 3449 3718 +0 3450 3717 +0 3450 3717 +0 3451 3717 +0 3451 3716 +0 3452 3715 +0 3454 3714 +0 3455 3712 +0 3457 3710 +0 3460 3708 +0 3464 3704 +0 3469 3699 +0 3476 3692 +0 3485 3683 +0 3497 3670 +0 3512 3653 +0 3532 3628 +0 3557 3593 +0 3588 3541 +0 3627 3461 +0 3675 3327 +0 3731 3045 +0 3797 0 +0 3873 0 +0 3449 3719 +0 3449 3719 +0 3449 3719 +0 3449 3719 +0 3449 3718 +0 3449 3718 +0 3449 3718 +0 3449 3718 +0 3449 3718 +0 3450 3718 +0 3450 3717 +0 3451 3717 +0 3451 3716 +0 3452 3715 +0 3454 3714 +0 3455 3713 +0 3457 3711 +0 3460 3708 +0 3464 3704 +0 3470 3699 +0 3476 3692 +0 3485 3683 +0 3497 3670 +0 3512 3653 +0 3532 3628 +0 3557 3593 +0 3589 3541 +0 3627 3462 +0 3675 3327 +0 3731 3046 +0 3797 0 +0 3873 0 +0 3449 3719 +0 3449 3719 +0 3449 3719 +0 3449 3719 +0 3449 3719 +0 3449 3719 +0 3449 3719 +0 3449 3718 +0 3450 3718 +0 3450 3718 +0 3450 3718 +0 3451 3717 +0 3451 3716 +0 3452 3716 +0 3454 3714 +0 3455 3713 +0 3458 3711 +0 3460 3708 +0 3464 3704 +0 3470 3699 +0 3476 3693 +0 3485 3683 +0 3497 3671 +0 3512 3653 +0 3532 3629 +0 3557 3593 +0 3589 3542 +0 3627 3462 +0 3675 3328 +0 3731 3047 +0 3797 0 +0 3873 0 +0 3449 3719 +0 3449 3719 +0 3449 3719 +0 3449 3719 +0 3449 3719 +0 3449 3719 +0 3449 3719 +0 3449 3719 +0 3450 3719 +0 3450 3718 +0 3450 3718 +0 3451 3718 +0 3452 3717 +0 3452 3716 +0 3454 3715 +0 3455 3713 +0 3458 3711 +0 3461 3709 +0 3465 3705 +0 3470 3700 +0 3477 3693 +0 3486 3684 +0 3497 3671 +0 3513 3654 +0 3532 3629 +0 3557 3594 +0 3589 3542 +0 3628 3463 +0 3675 3329 +0 3731 3049 +0 3797 0 +0 3873 0 +0 3449 3720 +0 3449 3720 +0 3449 3720 +0 3449 3720 +0 3449 3720 +0 3449 3720 +0 3449 3719 +0 3450 3719 +0 3450 3719 +0 3450 3719 +0 3450 3719 +0 3451 3718 +0 3452 3717 +0 3453 3717 +0 3454 3715 +0 3456 3714 +0 3458 3712 +0 3461 3709 +0 3465 3705 +0 3470 3700 +0 3477 3694 +0 3486 3684 +0 3497 3672 +0 3513 3654 +0 3532 3630 +0 3557 3595 +0 3589 3543 +0 3628 3464 +0 3675 3330 +0 3731 3051 +0 3797 0 +0 3873 0 +0 3449 3721 +0 3449 3721 +0 3449 3720 +0 3449 3720 +0 3449 3720 +0 3449 3720 +0 3450 3720 +0 3450 3720 +0 3450 3720 +0 3450 3720 +0 3451 3719 +0 3451 3719 +0 3452 3718 +0 3453 3717 +0 3454 3716 +0 3456 3715 +0 3458 3713 +0 3461 3710 +0 3465 3706 +0 3470 3701 +0 3477 3694 +0 3486 3685 +0 3498 3672 +0 3513 3655 +0 3532 3631 +0 3557 3596 +0 3589 3544 +0 3628 3465 +0 3675 3332 +0 3731 3055 +0 3797 0 +0 3873 0 +0 3449 3721 +0 3449 3721 +0 3449 3721 +0 3450 3721 +0 3450 3721 +0 3450 3721 +0 3450 3721 +0 3450 3721 +0 3450 3721 +0 3450 3721 +0 3451 3720 +0 3451 3720 +0 3452 3719 +0 3453 3718 +0 3454 3717 +0 3456 3716 +0 3458 3714 +0 3461 3711 +0 3465 3707 +0 3470 3702 +0 3477 3695 +0 3486 3686 +0 3498 3674 +0 3513 3656 +0 3533 3632 +0 3558 3597 +0 3589 3546 +0 3628 3467 +0 3675 3334 +0 3732 3059 +0 3798 0 +0 3873 0 +0 3450 3723 +0 3450 3723 +0 3450 3723 +0 3450 3723 +0 3450 3723 +0 3450 3723 +0 3450 3722 +0 3450 3722 +0 3451 3722 +0 3451 3722 +0 3451 3721 +0 3452 3721 +0 3452 3720 +0 3453 3719 +0 3455 3718 +0 3456 3717 +0 3458 3715 +0 3461 3712 +0 3465 3708 +0 3471 3703 +0 3477 3697 +0 3486 3687 +0 3498 3675 +0 3513 3658 +0 3533 3633 +0 3558 3599 +0 3589 3548 +0 3628 3469 +0 3675 3337 +0 3732 3064 +0 3798 0 +0 3873 0 +0 3450 3724 +0 3450 3724 +0 3450 3724 +0 3450 3724 +0 3450 3724 +0 3450 3724 +0 3451 3724 +0 3451 3724 +0 3451 3724 +0 3451 3723 +0 3452 3723 +0 3452 3723 +0 3453 3722 +0 3454 3721 +0 3455 3720 +0 3457 3719 +0 3459 3717 +0 3462 3714 +0 3466 3710 +0 3471 3705 +0 3478 3698 +0 3487 3689 +0 3498 3677 +0 3514 3659 +0 3533 3635 +0 3558 3601 +0 3590 3550 +0 3628 3472 +0 3676 3341 +0 3732 3071 +0 3798 0 +0 3873 0 +0 3451 3727 +0 3451 3727 +0 3451 3727 +0 3451 3727 +0 3451 3727 +0 3451 3726 +0 3451 3726 +0 3451 3726 +0 3452 3726 +0 3452 3726 +0 3452 3725 +0 3453 3725 +0 3453 3724 +0 3454 3723 +0 3456 3722 +0 3457 3721 +0 3459 3719 +0 3462 3716 +0 3466 3712 +0 3471 3708 +0 3478 3701 +0 3487 3692 +0 3499 3679 +0 3514 3662 +0 3534 3638 +0 3559 3604 +0 3590 3553 +0 3629 3476 +0 3676 3346 +0 3732 3081 +0 3798 0 +0 3873 0 +0 3451 3730 +0 3452 3730 +0 3452 3730 +0 3452 3730 +0 3452 3729 +0 3452 3729 +0 3452 3729 +0 3452 3729 +0 3452 3729 +0 3453 3729 +0 3453 3728 +0 3453 3728 +0 3454 3727 +0 3455 3726 +0 3456 3725 +0 3458 3724 +0 3460 3722 +0 3463 3719 +0 3467 3716 +0 3472 3711 +0 3479 3704 +0 3488 3695 +0 3500 3683 +0 3515 3666 +0 3534 3642 +0 3559 3608 +0 3591 3558 +0 3629 3481 +0 3676 3353 +0 3733 3093 +0 3798 0 +0 3874 0 +0 3453 3734 +0 3453 3734 +0 3453 3734 +0 3453 3734 +0 3453 3733 +0 3453 3733 +0 3453 3733 +0 3453 3733 +0 3453 3733 +0 3454 3733 +0 3454 3732 +0 3454 3732 +0 3455 3731 +0 3456 3730 +0 3457 3729 +0 3459 3728 +0 3461 3726 +0 3464 3723 +0 3468 3720 +0 3473 3715 +0 3480 3708 +0 3489 3699 +0 3501 3687 +0 3516 3670 +0 3535 3646 +0 3560 3613 +0 3591 3563 +0 3630 3488 +0 3677 3362 +0 3733 3109 +0 3799 370 +0 3874 0 +0 3454 3739 +0 3454 3739 +0 3454 3739 +0 3454 3739 +0 3454 3739 +0 3454 3739 +0 3454 3738 +0 3454 3738 +0 3455 3738 +0 3455 3738 +0 3455 3738 +0 3456 3737 +0 3457 3737 +0 3457 3736 +0 3459 3735 +0 3460 3733 +0 3463 3731 +0 3465 3729 +0 3469 3725 +0 3474 3720 +0 3481 3714 +0 3490 3705 +0 3502 3693 +0 3517 3676 +0 3536 3653 +0 3561 3620 +0 3592 3571 +0 3631 3497 +0 3678 3374 +0 3734 3129 +0 3800 1731 +0 3875 0 +0 3456 3746 +0 3456 3746 +0 3456 3746 +0 3456 3746 +0 3456 3746 +0 3456 3745 +0 3456 3745 +0 3456 3745 +0 3456 3745 +0 3457 3745 +0 3457 3744 +0 3458 3744 +0 3458 3743 +0 3459 3743 +0 3460 3742 +0 3462 3740 +0 3464 3738 +0 3467 3736 +0 3471 3732 +0 3476 3727 +0 3483 3721 +0 3492 3712 +0 3503 3700 +0 3518 3684 +0 3538 3661 +0 3563 3629 +0 3594 3581 +0 3632 3508 +0 3679 3389 +0 3735 3155 +0 3800 2103 +0 3875 0 +0 3458 3755 +0 3458 3755 +0 3458 3755 +0 3458 3755 +0 3458 3755 +0 3458 3755 +0 3458 3754 +0 3459 3754 +0 3459 3754 +0 3459 3754 +0 3460 3754 +0 3460 3753 +0 3461 3753 +0 3462 3752 +0 3463 3751 +0 3465 3749 +0 3467 3747 +0 3470 3745 +0 3473 3741 +0 3479 3737 +0 3485 3731 +0 3494 3722 +0 3506 3710 +0 3521 3694 +0 3540 3672 +0 3565 3640 +0 3595 3594 +0 3634 3524 +0 3681 3409 +0 3736 3187 +0 3802 2357 +0 3876 0 +0 3461 3767 +0 3461 3767 +0 3461 3767 +0 3461 3767 +0 3461 3767 +0 3462 3766 +0 3462 3766 +0 3462 3766 +0 3462 3766 +0 3462 3766 +0 3463 3765 +0 3463 3765 +0 3464 3764 +0 3465 3764 +0 3466 3763 +0 3468 3761 +0 3470 3759 +0 3473 3757 +0 3477 3754 +0 3482 3749 +0 3488 3743 +0 3497 3735 +0 3508 3723 +0 3523 3708 +0 3543 3686 +0 3567 3655 +0 3598 3611 +0 3636 3543 +0 3682 3434 +0 3738 3227 +0 3803 2563 +0 3878 0 +0 3466 3782 +0 3466 3782 +0 3466 3782 +0 3466 3782 +0 3466 3782 +0 3466 3782 +0 3466 3782 +0 3466 3782 +0 3466 3781 +0 3467 3781 +0 3467 3781 +0 3467 3780 +0 3468 3780 +0 3469 3779 +0 3470 3778 +0 3472 3777 +0 3474 3775 +0 3477 3773 +0 3481 3769 +0 3486 3765 +0 3492 3759 +0 3501 3751 +0 3512 3740 +0 3527 3725 +0 3546 3704 +0 3570 3675 +0 3601 3632 +0 3639 3568 +0 3685 3465 +0 3740 3276 +0 3805 2743 +0 3879 0 +0 3471 3802 +0 3471 3802 +0 3471 3802 +0 3471 3802 +0 3471 3802 +0 3471 3802 +0 3472 3802 +0 3472 3801 +0 3472 3801 +0 3472 3801 +0 3473 3801 +0 3473 3800 +0 3474 3800 +0 3475 3799 +0 3476 3798 +0 3477 3797 +0 3480 3795 +0 3482 3793 +0 3486 3790 +0 3491 3786 +0 3498 3780 +0 3506 3772 +0 3517 3762 +0 3532 3748 +0 3551 3728 +0 3575 3700 +0 3605 3660 +0 3643 3599 +0 3689 3504 +0 3743 3334 +0 3808 2908 +0 3882 0 +1996 3479 3827 +1994 3479 3827 +1992 3479 3827 +1990 3479 3827 +1986 3479 3827 +1981 3479 3827 +1974 3479 3827 +1965 3479 3827 +1953 3479 3826 +1935 3480 3826 +1911 3480 3826 +1877 3480 3826 +1826 3481 3825 +1748 3482 3824 +1616 3483 3824 +1346 3485 3822 +0 3487 3821 +0 3490 3819 +0 3493 3816 +0 3498 3812 +0 3505 3806 +0 3513 3799 +0 3524 3789 +0 3538 3776 +0 3557 3757 +0 3581 3731 +0 3611 3694 +0 3648 3638 +0 3693 3551 +0 3748 3401 +0 3811 3063 +0 3885 0 +2986 3488 3859 +2986 3488 3859 +2986 3488 3859 +2986 3488 3859 +2985 3488 3859 +2985 3489 3858 +2984 3489 3858 +2983 3489 3858 +2982 3489 3858 +2980 3489 3858 +2977 3490 3858 +2974 3490 3857 +2970 3491 3857 +2964 3492 3856 +2956 3493 3855 +2945 3494 3854 +2931 3496 3853 +2910 3499 3851 +2881 3503 3848 +2839 3507 3844 +2775 3514 3839 +2674 3522 3833 +2489 3533 3824 +1982 3547 3811 +0 3565 3794 +0 3589 3770 +0 3618 3736 +0 3655 3685 +0 3699 3608 +0 3753 3478 +0 3816 3212 +0 3889 0 +3342 3501 3898 +3342 3501 3898 +3342 3501 3898 +3341 3501 3898 +3341 3501 3898 +3341 3501 3898 +3341 3501 3898 +3340 3501 3897 +3340 3502 3897 +3339 3502 3897 +3338 3502 3897 +3336 3503 3897 +3334 3503 3896 +3332 3504 3896 +3328 3505 3895 +3323 3507 3894 +3317 3509 3892 +3308 3511 3891 +3296 3515 3888 +3280 3520 3885 +3257 3526 3880 +3224 3534 3874 +3177 3544 3866 +3104 3558 3854 +2984 3576 3839 +2749 3599 3817 +1669 3628 3786 +0 3663 3741 +0 3707 3674 +0 3760 3564 +0 3822 3356 +0 3894 2681 +3590 3517 3945 +3590 3517 3945 +3590 3517 3945 +3589 3517 3945 +3589 3518 3945 +3589 3518 3945 +3589 3518 3945 +3589 3518 3945 +3588 3518 3945 +3588 3518 3945 +3587 3519 3945 +3586 3519 3944 +3585 3520 3944 +3584 3520 3943 +3582 3522 3943 +3579 3523 3942 +3576 3525 3941 +3571 3527 3939 +3564 3531 3937 +3555 3535 3934 +3543 3541 3930 +3525 3549 3924 +3501 3559 3917 +3467 3573 3907 +3417 3590 3893 +3340 3612 3873 +3211 3640 3846 +2949 3675 3807 +0 3718 3749 +0 3769 3658 +0 3830 3497 +0 3901 3116 +3792 3538 4002 +3792 3538 4002 +3792 3538 4002 +3792 3539 4002 +3792 3539 4002 +3792 3539 4002 +3792 3539 4002 +3792 3539 4002 +3792 3539 4002 +3791 3539 4002 +3791 3540 4001 +3790 3540 4001 +3790 3541 4001 +3789 3541 4000 +3787 3542 4000 +3786 3544 3999 +3783 3546 3998 +3780 3548 3996 +3776 3551 3994 +3770 3556 3992 +3763 3561 3988 +3752 3569 3983 +3738 3579 3977 +3718 3591 3968 +3690 3608 3956 +3649 3629 3939 +3588 3656 3916 +3492 3690 3882 +3319 3731 3834 +2882 3782 3759 +0 3841 3636 +0 3910 3389 +3971 3565 4068 +3971 3565 4068 +3971 3565 4068 +3971 3565 4068 +3971 3565 4068 +3971 3565 4068 +3971 3565 4068 +3971 3566 4068 +3970 3566 4068 +3970 3566 4068 +3970 3566 4068 +3970 3567 4067 +3969 3567 4067 +3968 3568 4067 +3968 3569 4066 +3966 3570 4066 +3965 3572 4065 +3963 3574 4063 +3960 3577 4062 +3956 3581 4059 +3951 3587 4056 +3944 3594 4052 +3935 3603 4047 +3922 3615 4039 +3904 3631 4029 +3879 3651 4014 +3844 3677 3995 +3791 3709 3967 +3710 3749 3927 +3572 3797 3867 +3281 3855 3772 +0 3922 3604 +4095 3599 4095 +4095 3599 4095 +4095 3599 4095 +4095 3599 4095 +4095 3599 4095 +4095 3599 4095 +4095 3599 4095 +4095 3599 4095 +4095 3599 4095 +4095 3599 4095 +4095 3600 4095 +4095 3600 4095 +4095 3601 4095 +4095 3601 4095 +4095 3602 4095 +4095 3603 4095 +4095 3605 4095 +4095 3607 4095 +4095 3610 4095 +4095 3614 4095 +4095 3619 4095 +4095 3625 4095 +4095 3634 4095 +4095 3645 4095 +4090 3660 4095 +4073 3679 4095 +4050 3703 4083 +4018 3734 4060 +3970 3772 4027 +3897 3818 3980 +3778 3873 3908 +3543 3938 3789 +4095 3640 4095 +4095 3640 4095 +4095 3640 4095 +4095 3640 4095 +4095 3640 4095 +4095 3640 4095 +4095 3640 4095 +4095 3640 4095 +4095 3640 4095 +4095 3641 4095 +4095 3641 4095 +4095 3641 4095 +4095 3642 4095 +4095 3642 4095 +4095 3643 4095 +4095 3644 4095 +4095 3646 4095 +4095 3648 4095 +4095 3650 4095 +4095 3654 4095 +4095 3658 4095 +4095 3664 4095 +4095 3672 4095 +4095 3683 4095 +4095 3696 4095 +4095 3714 4095 +4095 3736 4095 +4095 3765 4095 +4095 3800 4095 +4095 3844 4095 +4067 3896 4043 +3958 3958 3958 diff --git a/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/Test_Grade/test-grade_inv-Log2-48nits_32_LUT.azasset b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/Test_Grade/test-grade_inv-Log2-48nits_32_LUT.azasset new file mode 100644 index 0000000000..a91e9d0c1a --- /dev/null +++ b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/Test_Grade/test-grade_inv-Log2-48nits_32_LUT.azasset @@ -0,0 +1,32780 @@ +{ + "Type": "JsonSerialization", + "Version": 1, + "ClassName": "LookupTableAsset", + "ClassData": { + "Name": "LookupTable", + "Intervals": [ + 0, 33, 66, 99, 132, 165, 198, 231, 264, 297, 330, 363, 396, 429, 462, 495, 528, 561, 594, 627, 660, 693, 726, 759, 792, 825, 858, 891, 924, 957, 990, 1023], + "Values": [ + 0, 0, 0, + 0, 0, 0, + 0, 15, 0, + 0, 104, 0, + 0, 201, 0, + 0, 305, 0, + 0, 415, 0, + 0, 530, 0, + 0, 649, 0, + 0, 771, 0, + 0, 895, 0, + 0, 1022, 0, + 0, 1149, 0, + 0, 1278, 0, + 0, 1408, 0, + 0, 1538, 0, + 0, 1668, 0, + 0, 1799, 0, + 0, 1931, 0, + 0, 2062, 0, + 0, 2194, 0, + 0, 2326, 0, + 0, 2457, 0, + 0, 2589, 0, + 0, 2721, 0, + 0, 2853, 0, + 0, 2985, 0, + 0, 3117, 0, + 0, 3249, 0, + 0, 3381, 0, + 0, 3514, 0, + 0, 3646, 0, + 130, 0, 20, + 28, 0, 0, + 0, 33, 0, + 0, 119, 0, + 0, 213, 0, + 0, 315, 0, + 0, 423, 0, + 0, 536, 0, + 0, 654, 0, + 0, 775, 0, + 0, 898, 0, + 0, 1024, 0, + 0, 1151, 0, + 0, 1279, 0, + 0, 1408, 0, + 0, 1538, 0, + 0, 1669, 0, + 0, 1800, 0, + 0, 1931, 0, + 0, 2062, 0, + 0, 2194, 0, + 0, 2326, 0, + 0, 2458, 0, + 0, 2589, 0, + 0, 2721, 0, + 0, 2853, 0, + 0, 2985, 0, + 0, 3117, 0, + 0, 3249, 0, + 0, 3381, 0, + 0, 3514, 0, + 0, 3646, 0, + 342, 0, 170, + 280, 0, 102, + 183, 56, 0, + 7, 139, 0, + 0, 229, 0, + 0, 328, 0, + 0, 433, 0, + 0, 544, 0, + 0, 660, 0, + 0, 779, 0, + 0, 902, 0, + 0, 1026, 0, + 0, 1153, 0, + 0, 1281, 0, + 0, 1410, 0, + 0, 1539, 0, + 0, 1670, 0, + 0, 1800, 0, + 0, 1931, 0, + 0, 2063, 0, + 0, 2194, 0, + 0, 2326, 0, + 0, 2458, 0, + 0, 2589, 0, + 0, 2721, 0, + 0, 2853, 0, + 0, 2985, 0, + 0, 3117, 0, + 0, 3249, 0, + 0, 3381, 0, + 0, 3514, 0, + 0, 3646, 0, + 526, 0, 315, + 486, 18, 266, + 426, 86, 192, + 331, 163, 68, + 163, 250, 0, + 0, 344, 0, + 0, 446, 0, + 0, 555, 0, + 0, 668, 0, + 0, 785, 0, + 0, 906, 0, + 0, 1030, 0, + 0, 1156, 0, + 0, 1283, 0, + 0, 1411, 0, + 0, 1540, 0, + 0, 1670, 0, + 0, 1801, 0, + 0, 1932, 0, + 0, 2063, 0, + 0, 2194, 0, + 0, 2326, 0, + 0, 2458, 0, + 0, 2590, 0, + 0, 2722, 0, + 0, 2853, 0, + 0, 2985, 0, + 0, 3117, 0, + 0, 3249, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 693, 8, 457, + 666, 60, 422, + 626, 123, 370, + 568, 195, 290, + 475, 276, 155, + 312, 366, 0, + 0, 463, 0, + 0, 568, 0, + 0, 678, 0, + 0, 794, 0, + 0, 913, 0, + 0, 1035, 0, + 0, 1159, 0, + 0, 1285, 0, + 0, 1413, 0, + 0, 1542, 0, + 0, 1672, 0, + 0, 1802, 0, + 0, 1932, 0, + 0, 2064, 0, + 0, 2195, 0, + 0, 2326, 0, + 0, 2458, 0, + 0, 2590, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2985, 0, + 0, 3117, 0, + 0, 3249, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 850, 65, 596, + 831, 112, 570, + 804, 168, 534, + 765, 233, 479, + 707, 308, 395, + 616, 393, 250, + 457, 485, 0, + 82, 585, 0, + 0, 692, 0, + 0, 804, 0, + 0, 921, 0, + 0, 1041, 0, + 0, 1164, 0, + 0, 1289, 0, + 0, 1416, 0, + 0, 1544, 0, + 0, 1673, 0, + 0, 1803, 0, + 0, 1933, 0, + 0, 2064, 0, + 0, 2195, 0, + 0, 2327, 0, + 0, 2458, 0, + 0, 2590, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 999, 131, 733, + 986, 172, 714, + 967, 222, 688, + 940, 280, 650, + 901, 348, 594, + 844, 426, 505, + 755, 513, 352, + 598, 608, 3, + 235, 710, 0, + 0, 818, 0, + 0, 932, 0, + 0, 1049, 0, + 0, 1170, 0, + 0, 1294, 0, + 0, 1420, 0, + 0, 1547, 0, + 0, 1675, 0, + 0, 1805, 0, + 0, 1935, 0, + 0, 2065, 0, + 0, 2196, 0, + 0, 2327, 0, + 0, 2459, 0, + 0, 2590, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1144, 207, 869, + 1134, 242, 855, + 1121, 285, 836, + 1102, 336, 809, + 1075, 397, 770, + 1037, 468, 712, + 980, 547, 621, + 892, 636, 461, + 737, 732, 82, + 382, 836, 0, + 0, 946, 0, + 0, 1060, 0, + 0, 1179, 0, + 0, 1300, 0, + 0, 1424, 0, + 0, 1550, 0, + 0, 1678, 0, + 0, 1807, 0, + 0, 1936, 0, + 0, 2066, 0, + 0, 2197, 0, + 0, 2328, 0, + 0, 2459, 0, + 0, 2591, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1286, 293, 1004, + 1278, 322, 994, + 1268, 358, 980, + 1255, 402, 960, + 1236, 455, 932, + 1210, 518, 893, + 1172, 590, 833, + 1115, 671, 740, + 1027, 761, 574, + 874, 859, 170, + 525, 964, 0, + 0, 1074, 0, + 0, 1190, 0, + 0, 1309, 0, + 0, 1431, 0, + 0, 1555, 0, + 0, 1682, 0, + 0, 1809, 0, + 0, 1938, 0, + 0, 2068, 0, + 0, 2198, 0, + 0, 2329, 0, + 0, 2460, 0, + 0, 2591, 0, + 0, 2723, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1424, 386, 1138, + 1419, 410, 1131, + 1412, 440, 1120, + 1402, 477, 1106, + 1389, 523, 1086, + 1370, 577, 1058, + 1343, 641, 1018, + 1306, 714, 958, + 1250, 797, 862, + 1162, 888, 692, + 1010, 987, 267, + 665, 1093, 0, + 0, 1204, 0, + 0, 1320, 0, + 0, 1439, 0, + 0, 1562, 0, + 0, 1687, 0, + 0, 1813, 0, + 0, 1941, 0, + 0, 2070, 0, + 0, 2200, 0, + 0, 2330, 0, + 0, 2461, 0, + 0, 2592, 0, + 0, 2723, 0, + 0, 2855, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1562, 487, 1272, + 1558, 506, 1266, + 1552, 531, 1258, + 1545, 561, 1248, + 1535, 599, 1234, + 1522, 646, 1213, + 1503, 701, 1185, + 1477, 766, 1144, + 1439, 840, 1084, + 1383, 924, 987, + 1296, 1016, 813, + 1145, 1116, 370, + 802, 1222, 0, + 0, 1334, 0, + 0, 1450, 0, + 0, 1570, 0, + 0, 1693, 0, + 0, 1818, 0, + 0, 1945, 0, + 0, 2073, 0, + 0, 2202, 0, + 0, 2331, 0, + 0, 2462, 0, + 0, 2593, 0, + 0, 2724, 0, + 0, 2855, 0, + 0, 2987, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1697, 595, 1405, + 1695, 610, 1401, + 1691, 629, 1395, + 1685, 654, 1387, + 1678, 685, 1377, + 1668, 724, 1362, + 1655, 771, 1342, + 1636, 827, 1314, + 1610, 893, 1273, + 1572, 968, 1211, + 1517, 1053, 1113, + 1430, 1145, 937, + 1279, 1246, 479, + 939, 1352, 0, + 0, 1465, 0, + 0, 1581, 0, + 0, 1701, 0, + 0, 1824, 0, + 0, 1950, 0, + 0, 2076, 0, + 0, 2204, 0, + 0, 2334, 0, + 0, 2463, 0, + 0, 2594, 0, + 0, 2725, 0, + 0, 2856, 0, + 0, 2987, 0, + 0, 3119, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1832, 707, 1538, + 1830, 719, 1535, + 1827, 735, 1531, + 1823, 755, 1525, + 1818, 780, 1517, + 1811, 811, 1507, + 1801, 851, 1492, + 1788, 898, 1472, + 1769, 955, 1443, + 1743, 1021, 1402, + 1705, 1097, 1340, + 1650, 1182, 1241, + 1563, 1275, 1062, + 1412, 1376, 594, + 1074, 1483, 0, + 0, 1596, 0, + 0, 1712, 0, + 0, 1833, 0, + 0, 1956, 0, + 0, 2081, 0, + 0, 2208, 0, + 0, 2336, 0, + 0, 2466, 0, + 0, 2595, 0, + 0, 2726, 0, + 0, 2857, 0, + 0, 2988, 0, + 0, 3119, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3514, 0, + 0, 3646, 0, + 1966, 824, 1671, + 1965, 834, 1668, + 1963, 846, 1665, + 1960, 861, 1661, + 1956, 881, 1655, + 1951, 907, 1647, + 1943, 939, 1637, + 1934, 978, 1622, + 1920, 1026, 1602, + 1902, 1084, 1573, + 1875, 1150, 1531, + 1838, 1227, 1469, + 1782, 1312, 1370, + 1696, 1406, 1190, + 1545, 1507, 712, + 1209, 1614, 0, + 0, 1727, 0, + 0, 1844, 0, + 0, 1964, 0, + 0, 2088, 0, + 0, 2213, 0, + 0, 2340, 0, + 0, 2468, 0, + 0, 2597, 0, + 0, 2727, 0, + 0, 2858, 0, + 0, 2989, 0, + 0, 3120, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3646, 0, + 2100, 945, 1803, + 2099, 952, 1802, + 2097, 961, 1799, + 2095, 973, 1796, + 2092, 989, 1792, + 2088, 1009, 1786, + 2083, 1035, 1778, + 2076, 1067, 1768, + 2066, 1107, 1753, + 2053, 1156, 1732, + 2034, 1213, 1703, + 2008, 1280, 1662, + 1970, 1357, 1599, + 1915, 1442, 1499, + 1828, 1536, 1318, + 1678, 1638, 834, + 1342, 1745, 0, + 0, 1858, 0, + 0, 1976, 0, + 0, 2096, 0, + 0, 2220, 0, + 0, 2345, 0, + 0, 2472, 0, + 0, 2600, 0, + 0, 2730, 0, + 0, 2859, 0, + 0, 2990, 0, + 0, 3121, 0, + 0, 3252, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3647, 0, + 2233, 1068, 1936, + 2232, 1074, 1935, + 2231, 1081, 1933, + 2230, 1090, 1930, + 2227, 1102, 1927, + 2225, 1118, 1923, + 2221, 1139, 1917, + 2215, 1164, 1909, + 2208, 1197, 1899, + 2198, 1237, 1884, + 2185, 1286, 1863, + 2166, 1343, 1834, + 2140, 1411, 1793, + 2103, 1488, 1730, + 2047, 1573, 1629, + 1961, 1668, 1447, + 1811, 1769, 958, + 1476, 1877, 0, + 0, 1990, 0, + 0, 2107, 0, + 0, 2228, 0, + 0, 2351, 0, + 0, 2477, 0, + 0, 2604, 0, + 0, 2732, 0, + 0, 2862, 0, + 0, 2991, 0, + 0, 3122, 0, + 0, 3253, 0, + 0, 3384, 0, + 0, 3515, 0, + 0, 3647, 0, + 2366, 1194, 2068, + 2366, 1198, 2067, + 2365, 1203, 2066, + 2364, 1210, 2064, + 2362, 1220, 2062, + 2360, 1232, 2059, + 2357, 1248, 2054, + 2353, 1268, 2049, + 2348, 1294, 2041, + 2340, 1327, 2030, + 2331, 1367, 2015, + 2317, 1416, 1995, + 2299, 1474, 1966, + 2273, 1542, 1924, + 2235, 1619, 1861, + 2180, 1705, 1760, + 2093, 1799, 1577, + 1944, 1901, 1084, + 1609, 2009, 0, + 0, 2122, 0, + 0, 2239, 0, + 0, 2360, 0, + 0, 2483, 0, + 0, 2609, 0, + 0, 2736, 0, + 0, 2864, 0, + 0, 2994, 0, + 0, 3124, 0, + 0, 3254, 0, + 0, 3385, 0, + 0, 3516, 0, + 0, 3648, 0, + 2499, 1321, 2200, + 2499, 1324, 2200, + 2498, 1328, 2199, + 2497, 1333, 2197, + 2496, 1340, 2196, + 2494, 1350, 2193, + 2492, 1362, 2190, + 2489, 1378, 2186, + 2485, 1399, 2180, + 2480, 1425, 2172, + 2473, 1458, 2161, + 2463, 1498, 2147, + 2450, 1547, 2126, + 2431, 1605, 2097, + 2405, 1673, 2055, + 2367, 1750, 1992, + 2312, 1836, 1891, + 2226, 1931, 1708, + 2076, 2032, 1211, + 1742, 2140, 0, + 0, 2254, 0, + 0, 2371, 0, + 0, 2492, 0, + 0, 2615, 0, + 0, 2741, 0, + 0, 2868, 0, + 0, 2996, 0, + 0, 3126, 0, + 0, 3256, 0, + 0, 3386, 0, + 0, 3517, 0, + 0, 3648, 0, + 2632, 1449, 2333, + 2631, 1451, 2332, + 2631, 1454, 2331, + 2630, 1458, 2330, + 2629, 1464, 2329, + 2628, 1471, 2327, + 2626, 1481, 2325, + 2624, 1493, 2322, + 2621, 1509, 2318, + 2617, 1530, 2312, + 2612, 1556, 2304, + 2605, 1589, 2293, + 2595, 1629, 2278, + 2582, 1678, 2258, + 2563, 1736, 2229, + 2537, 1804, 2187, + 2500, 1881, 2123, + 2444, 1968, 2023, + 2358, 2062, 1839, + 2208, 2164, 1340, + 1874, 2272, 0, + 0, 2385, 0, + 0, 2503, 0, + 0, 2624, 0, + 0, 2747, 0, + 0, 2873, 0, + 0, 3000, 0, + 0, 3128, 0, + 0, 3258, 0, + 0, 3388, 0, + 0, 3518, 0, + 0, 3649, 0, + 2764, 1578, 2465, + 2764, 1580, 2465, + 2763, 1582, 2464, + 2763, 1585, 2463, + 2762, 1589, 2462, + 2761, 1595, 2461, + 2760, 1602, 2459, + 2759, 1612, 2457, + 2756, 1624, 2454, + 2753, 1640, 2449, + 2750, 1661, 2444, + 2744, 1687, 2436, + 2737, 1720, 2425, + 2727, 1760, 2410, + 2714, 1809, 2389, + 2695, 1868, 2360, + 2669, 1936, 2318, + 2632, 2013, 2255, + 2577, 2099, 2154, + 2490, 2194, 1970, + 2341, 2296, 1469, + 2007, 2404, 0, + 0, 2517, 0, + 0, 2635, 0, + 0, 2756, 0, + 0, 2879, 0, + 0, 3005, 0, + 0, 3132, 0, + 0, 3260, 0, + 0, 3390, 0, + 0, 3520, 0, + 0, 3650, 0, + 2896, 1708, 2597, + 2896, 1709, 2597, + 2896, 1711, 2596, + 2896, 1713, 2596, + 2895, 1716, 2595, + 2894, 1721, 2594, + 2893, 1726, 2593, + 2892, 1733, 2591, + 2891, 1743, 2589, + 2889, 1755, 2586, + 2886, 1771, 2581, + 2882, 1792, 2575, + 2876, 1818, 2568, + 2869, 1851, 2557, + 2859, 1892, 2542, + 2846, 1941, 2521, + 2828, 1999, 2492, + 2801, 2067, 2450, + 2764, 2145, 2387, + 2709, 2231, 2286, + 2622, 2326, 2101, + 2473, 2428, 1599, + 2139, 2536, 0, + 0, 2649, 0, + 0, 2767, 0, + 0, 2888, 0, + 0, 3011, 0, + 0, 3137, 0, + 0, 3264, 0, + 0, 3393, 0, + 0, 3522, 0, + 0, 3652, 0, + 3029, 1838, 2729, + 3029, 1839, 2729, + 3028, 1841, 2729, + 3028, 1842, 2728, + 3028, 1845, 2728, + 3027, 1848, 2727, + 3027, 1852, 2726, + 3026, 1858, 2725, + 3024, 1865, 2723, + 3023, 1874, 2721, + 3021, 1887, 2717, + 3018, 1903, 2713, + 3014, 1924, 2707, + 3009, 1950, 2699, + 3001, 1983, 2689, + 2992, 2024, 2674, + 2978, 2073, 2653, + 2960, 2131, 2624, + 2934, 2199, 2582, + 2896, 2277, 2519, + 2841, 2363, 2418, + 2755, 2458, 2233, + 2605, 2560, 1730, + 2272, 2668, 0, + 0, 2781, 0, + 0, 2899, 0, + 0, 3020, 0, + 0, 3143, 0, + 0, 3269, 0, + 0, 3396, 0, + 0, 3525, 0, + 0, 3654, 0, + 3161, 1969, 2861, + 3161, 1970, 2861, + 3161, 1971, 2861, + 3160, 1972, 2861, + 3160, 1974, 2860, + 3160, 1976, 2860, + 3159, 1980, 2859, + 3159, 1984, 2858, + 3158, 1989, 2857, + 3157, 1996, 2855, + 3155, 2006, 2853, + 3153, 2018, 2849, + 3150, 2035, 2845, + 3146, 2055, 2839, + 3141, 2082, 2831, + 3134, 2115, 2821, + 3124, 2155, 2806, + 3110, 2205, 2785, + 3092, 2263, 2756, + 3066, 2331, 2714, + 3028, 2409, 2651, + 2973, 2495, 2549, + 2887, 2590, 2365, + 2737, 2692, 1861, + 2404, 2800, 0, + 0, 2913, 0, + 0, 3031, 0, + 0, 3152, 0, + 0, 3276, 0, + 0, 3401, 0, + 0, 3528, 0, + 0, 3657, 0, + 3293, 2100, 2994, + 3293, 2101, 2993, + 3293, 2102, 2993, + 3293, 2103, 2993, + 3293, 2104, 2993, + 3292, 2106, 2992, + 3292, 2108, 2992, + 3291, 2111, 2991, + 3291, 2115, 2990, + 3290, 2121, 2989, + 3289, 2128, 2987, + 3287, 2138, 2985, + 3285, 2150, 2981, + 3282, 2166, 2977, + 3278, 2187, 2971, + 3273, 2213, 2963, + 3266, 2246, 2953, + 3256, 2287, 2938, + 3242, 2336, 2917, + 3224, 2395, 2888, + 3198, 2463, 2846, + 3161, 2541, 2783, + 3105, 2627, 2681, + 3019, 2722, 2497, + 2870, 2824, 1992, + 2536, 2932, 0, + 0, 3046, 0, + 0, 3163, 0, + 0, 3284, 0, + 0, 3408, 0, + 0, 3533, 0, + 0, 3660, 0, + 3425, 2232, 3126, + 3425, 2232, 3126, + 3425, 2233, 3125, + 3425, 2233, 3125, + 3425, 2234, 3125, + 3425, 2236, 3125, + 3424, 2238, 3124, + 3424, 2240, 3124, + 3424, 2243, 3123, + 3423, 2247, 3122, + 3422, 2253, 3121, + 3421, 2260, 3119, + 3419, 2270, 3117, + 3417, 2282, 3113, + 3414, 2298, 3109, + 3410, 2319, 3103, + 3405, 2345, 3095, + 3398, 2378, 3085, + 3388, 2419, 3070, + 3375, 2468, 3049, + 3356, 2527, 3020, + 3330, 2595, 2978, + 3293, 2673, 2915, + 3237, 2759, 2813, + 3151, 2854, 2629, + 3002, 2956, 2124, + 2668, 3064, 0, + 0, 3178, 0, + 0, 3295, 0, + 0, 3416, 0, + 0, 3540, 0, + 0, 3665, 0, + 3557, 2363, 3258, + 3557, 2364, 3258, + 3557, 2364, 3258, + 3557, 2365, 3258, + 3557, 2365, 3257, + 3557, 2366, 3257, + 3557, 2368, 3257, + 3557, 2370, 3256, + 3556, 2372, 3256, + 3556, 2375, 3255, + 3555, 2379, 3254, + 3554, 2385, 3253, + 3553, 2392, 3251, + 3551, 2402, 3249, + 3549, 2414, 3245, + 3546, 2430, 3241, + 3542, 2451, 3235, + 3537, 2477, 3227, + 3530, 2510, 3217, + 3520, 2551, 3202, + 3507, 2600, 3181, + 3488, 2659, 3152, + 3462, 2727, 3110, + 3425, 2805, 3047, + 3369, 2891, 2945, + 3283, 2986, 2760, + 3134, 3088, 2255, + 2800, 3196, 0, + 0, 3310, 0, + 0, 3427, 0, + 0, 3548, 0, + 0, 3672, 0, + 3690, 2495, 3390, + 3690, 2495, 3390, + 3690, 2496, 3390, + 3689, 2496, 3390, + 3689, 2497, 3390, + 3689, 2497, 3389, + 3689, 2498, 3389, + 3689, 2500, 3389, + 3689, 2501, 3388, + 3688, 2504, 3388, + 3688, 2507, 3387, + 3687, 2511, 3386, + 3686, 2517, 3385, + 3685, 2524, 3383, + 3683, 2534, 3381, + 3681, 2546, 3378, + 3678, 2562, 3373, + 3674, 2583, 3367, + 3669, 2609, 3360, + 3662, 2642, 3349, + 3652, 2683, 3334, + 3639, 2732, 3313, + 3620, 2791, 3284, + 3594, 2859, 3242, + 3557, 2937, 3179, + 3502, 3023, 3077, + 3415, 3118, 2892, + 3266, 3220, 2387, + 2933, 3328, 0, + 0, 3442, 0, + 0, 3559, 0, + 0, 3680, 0, + 3822, 2627, 3522, + 3822, 2627, 3522, + 3822, 2627, 3522, + 3822, 2628, 3522, + 3822, 2628, 3522, + 3822, 2629, 3522, + 3821, 2629, 3521, + 3821, 2630, 3521, + 3821, 2632, 3521, + 3821, 2633, 3521, + 3820, 2636, 3520, + 3820, 2639, 3519, + 3819, 2643, 3518, + 3818, 2649, 3517, + 3817, 2656, 3515, + 3816, 2666, 3513, + 3813, 2678, 3510, + 3810, 2694, 3505, + 3807, 2715, 3499, + 3801, 2741, 3492, + 3794, 2774, 3481, + 3784, 2815, 3466, + 3771, 2864, 3445, + 3752, 2923, 3416, + 3726, 2991, 3374, + 3689, 3069, 3311, + 3634, 3155, 3209, + 3547, 3250, 3024, + 3398, 3352, 2519, + 3065, 3460, 0, + 0, 3574, 0, + 0, 3691, 0, + 3954, 2759, 3654, + 3954, 2759, 3654, + 3954, 2759, 3654, + 3954, 2759, 3654, + 3954, 2760, 3654, + 3954, 2760, 3654, + 3954, 2761, 3654, + 3953, 2761, 3654, + 3953, 2762, 3653, + 3953, 2764, 3653, + 3953, 2765, 3653, + 3952, 2768, 3652, + 3952, 2771, 3651, + 3951, 2775, 3650, + 3950, 2781, 3649, + 3949, 2788, 3647, + 3948, 2798, 3645, + 3945, 2810, 3642, + 3943, 2826, 3637, + 3939, 2847, 3632, + 3933, 2873, 3624, + 3926, 2906, 3613, + 3916, 2947, 3598, + 3903, 2996, 3577, + 3884, 3055, 3548, + 3858, 3123, 3506, + 3821, 3201, 3443, + 3766, 3287, 3341, + 3679, 3382, 3156, + 3530, 3484, 2651, + 3197, 3592, 0, + 0, 3706, 0, + 4086, 2891, 3786, + 4086, 2891, 3786, + 4086, 2891, 3786, + 4086, 2891, 3786, + 4086, 2891, 3786, + 4086, 2892, 3786, + 4086, 2892, 3786, + 4086, 2893, 3786, + 4086, 2893, 3786, + 4085, 2894, 3785, + 4085, 2896, 3785, + 4085, 2897, 3785, + 4085, 2900, 3784, + 4084, 2903, 3783, + 4083, 2907, 3782, + 4083, 2913, 3781, + 4081, 2920, 3779, + 4080, 2930, 3777, + 4078, 2942, 3774, + 4075, 2958, 3769, + 4071, 2979, 3764, + 4065, 3005, 3756, + 4058, 3038, 3745, + 4049, 3079, 3730, + 4035, 3128, 3709, + 4017, 3187, 3680, + 3991, 3255, 3638, + 3953, 3333, 3575, + 3898, 3419, 3473, + 3812, 3514, 3289, + 3662, 3616, 2783, + 3329, 3725, 0, + 4095, 3023, 3918, + 4095, 3023, 3918, + 4095, 3023, 3918, + 4095, 3023, 3918, + 4095, 3023, 3918, + 4095, 3023, 3918, + 4095, 3024, 3918, + 4095, 3024, 3918, + 4095, 3025, 3918, + 4095, 3025, 3918, + 4095, 3026, 3917, + 4095, 3028, 3917, + 4095, 3030, 3917, + 4095, 3032, 3916, + 4095, 3035, 3915, + 4095, 3039, 3915, + 4095, 3045, 3913, + 4095, 3052, 3911, + 4095, 3062, 3909, + 4095, 3074, 3906, + 4095, 3090, 3902, + 4095, 3111, 3896, + 4095, 3137, 3888, + 4095, 3170, 3877, + 4095, 3211, 3862, + 4095, 3261, 3842, + 4095, 3319, 3812, + 4095, 3387, 3770, + 4085, 3465, 3707, + 4030, 3551, 3605, + 3944, 3646, 3421, + 3794, 3748, 2915, + 4095, 3155, 4050, + 4095, 3155, 4050, + 4095, 3155, 4050, + 4095, 3155, 4050, + 4095, 3155, 4050, + 4095, 3155, 4050, + 4095, 3155, 4050, + 4095, 3156, 4050, + 4095, 3156, 4050, + 4095, 3157, 4050, + 4095, 3157, 4050, + 4095, 3158, 4050, + 4095, 3160, 4049, + 4095, 3162, 4049, + 4095, 3164, 4048, + 4095, 3167, 4048, + 4095, 3171, 4047, + 4095, 3177, 4045, + 4095, 3184, 4044, + 4095, 3194, 4041, + 4095, 3206, 4038, + 4095, 3222, 4034, + 4095, 3243, 4028, + 4095, 3270, 4020, + 4095, 3303, 4009, + 4095, 3343, 3994, + 4095, 3393, 3974, + 4095, 3451, 3944, + 4095, 3519, 3902, + 4095, 3597, 3839, + 4095, 3684, 3738, + 4076, 3778, 3553, + 0, 0, 0, + 0, 0, 0, + 0, 49, 0, + 0, 132, 0, + 0, 224, 0, + 0, 324, 0, + 0, 430, 0, + 0, 542, 0, + 0, 658, 0, + 0, 778, 0, + 0, 901, 0, + 0, 1025, 0, + 0, 1152, 0, + 0, 1280, 0, + 0, 1409, 0, + 0, 1539, 0, + 0, 1669, 0, + 0, 1800, 0, + 0, 1931, 0, + 0, 2063, 0, + 0, 2194, 0, + 0, 2326, 0, + 0, 2458, 0, + 0, 2589, 0, + 0, 2721, 0, + 0, 2853, 0, + 0, 2985, 0, + 0, 3117, 0, + 0, 3249, 0, + 0, 3381, 0, + 0, 3514, 0, + 0, 3646, 0, + 104, 0, 80, + 0, 0, 0, + 0, 66, 0, + 0, 147, 0, + 0, 236, 0, + 0, 333, 0, + 0, 438, 0, + 0, 548, 0, + 0, 662, 0, + 0, 781, 0, + 0, 903, 0, + 0, 1028, 0, + 0, 1154, 0, + 0, 1281, 0, + 0, 1410, 0, + 0, 1540, 0, + 0, 1670, 0, + 0, 1800, 0, + 0, 1931, 0, + 0, 2063, 0, + 0, 2194, 0, + 0, 2326, 0, + 0, 2458, 0, + 0, 2590, 0, + 0, 2721, 0, + 0, 2853, 0, + 0, 2985, 0, + 0, 3117, 0, + 0, 3249, 0, + 0, 3381, 0, + 0, 3514, 0, + 0, 3646, 0, + 326, 0, 214, + 262, 20, 152, + 160, 88, 54, + 0, 165, 0, + 0, 251, 0, + 0, 346, 0, + 0, 447, 0, + 0, 555, 0, + 0, 668, 0, + 0, 786, 0, + 0, 907, 0, + 0, 1030, 0, + 0, 1156, 0, + 0, 1283, 0, + 0, 1411, 0, + 0, 1540, 0, + 0, 1670, 0, + 0, 1801, 0, + 0, 1932, 0, + 0, 2063, 0, + 0, 2194, 0, + 0, 2326, 0, + 0, 2458, 0, + 0, 2590, 0, + 0, 2722, 0, + 0, 2853, 0, + 0, 2985, 0, + 0, 3117, 0, + 0, 3249, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 515, 0, 347, + 474, 52, 302, + 413, 116, 234, + 315, 188, 122, + 139, 271, 0, + 0, 361, 0, + 0, 460, 0, + 0, 565, 0, + 0, 676, 0, + 0, 792, 0, + 0, 911, 0, + 0, 1034, 0, + 0, 1158, 0, + 0, 1285, 0, + 0, 1413, 0, + 0, 1542, 0, + 0, 1671, 0, + 0, 1802, 0, + 0, 1932, 0, + 0, 2063, 0, + 0, 2195, 0, + 0, 2326, 0, + 0, 2458, 0, + 0, 2590, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2985, 0, + 0, 3117, 0, + 0, 3249, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 686, 42, 481, + 658, 92, 447, + 618, 150, 399, + 558, 218, 324, + 463, 295, 200, + 295, 382, 0, + 0, 477, 0, + 0, 579, 0, + 0, 687, 0, + 0, 800, 0, + 0, 918, 0, + 0, 1039, 0, + 0, 1162, 0, + 0, 1288, 0, + 0, 1415, 0, + 0, 1543, 0, + 0, 1673, 0, + 0, 1802, 0, + 0, 1933, 0, + 0, 2064, 0, + 0, 2195, 0, + 0, 2327, 0, + 0, 2458, 0, + 0, 2590, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 844, 96, 614, + 825, 140, 589, + 798, 192, 554, + 758, 255, 502, + 700, 327, 422, + 607, 408, 287, + 444, 498, 4, + 53, 596, 0, + 0, 700, 0, + 0, 811, 0, + 0, 926, 0, + 0, 1045, 0, + 0, 1167, 0, + 0, 1291, 0, + 0, 1418, 0, + 0, 1545, 0, + 0, 1674, 0, + 0, 1804, 0, + 0, 1934, 0, + 0, 2065, 0, + 0, 2196, 0, + 0, 2327, 0, + 0, 2458, 0, + 0, 2590, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 996, 158, 746, + 982, 197, 728, + 963, 244, 702, + 936, 300, 666, + 897, 365, 611, + 839, 440, 527, + 748, 525, 382, + 589, 617, 65, + 214, 718, 0, + 0, 824, 0, + 0, 936, 0, + 0, 1053, 0, + 0, 1173, 0, + 0, 1296, 0, + 0, 1421, 0, + 0, 1548, 0, + 0, 1676, 0, + 0, 1805, 0, + 0, 1935, 0, + 0, 2065, 0, + 0, 2196, 0, + 0, 2327, 0, + 0, 2459, 0, + 0, 2590, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1141, 230, 879, + 1131, 263, 865, + 1118, 304, 846, + 1099, 354, 820, + 1072, 412, 782, + 1034, 481, 726, + 976, 558, 638, + 887, 645, 484, + 730, 740, 135, + 367, 842, 0, + 0, 950, 0, + 0, 1064, 0, + 0, 1181, 0, + 0, 1302, 0, + 0, 1426, 0, + 0, 1552, 0, + 0, 1679, 0, + 0, 1807, 0, + 0, 1937, 0, + 0, 2067, 0, + 0, 2197, 0, + 0, 2328, 0, + 0, 2459, 0, + 0, 2591, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1284, 312, 1011, + 1276, 340, 1001, + 1266, 374, 987, + 1253, 417, 968, + 1234, 468, 941, + 1207, 529, 902, + 1169, 600, 844, + 1112, 679, 753, + 1024, 768, 593, + 869, 865, 214, + 514, 968, 0, + 0, 1078, 0, + 0, 1192, 0, + 0, 1311, 0, + 0, 1432, 0, + 0, 1557, 0, + 0, 1683, 0, + 0, 1810, 0, + 0, 1939, 0, + 0, 2068, 0, + 0, 2198, 0, + 0, 2329, 0, + 0, 2460, 0, + 0, 2591, 0, + 0, 2723, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1423, 402, 1144, + 1418, 425, 1136, + 1410, 454, 1126, + 1401, 490, 1112, + 1387, 534, 1092, + 1368, 587, 1064, + 1342, 650, 1025, + 1304, 722, 966, + 1247, 803, 872, + 1159, 893, 706, + 1006, 991, 302, + 657, 1096, 0, + 0, 1206, 0, + 0, 1322, 0, + 0, 1441, 0, + 0, 1563, 0, + 0, 1687, 0, + 0, 1814, 0, + 0, 1941, 0, + 0, 2070, 0, + 0, 2200, 0, + 0, 2330, 0, + 0, 2461, 0, + 0, 2592, 0, + 0, 2723, 0, + 0, 2855, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1561, 500, 1276, + 1557, 518, 1270, + 1551, 542, 1263, + 1544, 572, 1252, + 1534, 609, 1238, + 1521, 655, 1218, + 1502, 709, 1190, + 1476, 773, 1150, + 1438, 846, 1090, + 1382, 929, 994, + 1294, 1020, 824, + 1142, 1119, 399, + 797, 1225, 0, + 0, 1336, 0, + 0, 1452, 0, + 0, 1571, 0, + 0, 1694, 0, + 0, 1819, 0, + 0, 1945, 0, + 0, 2073, 0, + 0, 2202, 0, + 0, 2332, 0, + 0, 2462, 0, + 0, 2593, 0, + 0, 2724, 0, + 0, 2855, 0, + 0, 2987, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1697, 605, 1408, + 1694, 619, 1404, + 1690, 639, 1398, + 1684, 663, 1391, + 1677, 694, 1380, + 1667, 732, 1366, + 1654, 778, 1346, + 1635, 833, 1317, + 1609, 898, 1277, + 1571, 973, 1216, + 1515, 1056, 1119, + 1428, 1148, 945, + 1277, 1248, 502, + 935, 1354, 0, + 0, 1466, 0, + 0, 1582, 0, + 0, 1702, 0, + 0, 1825, 0, + 0, 1950, 0, + 0, 2077, 0, + 0, 2205, 0, + 0, 2334, 0, + 0, 2464, 0, + 0, 2594, 0, + 0, 2725, 0, + 0, 2856, 0, + 0, 2987, 0, + 0, 3119, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1832, 715, 1540, + 1830, 727, 1537, + 1827, 742, 1533, + 1823, 761, 1527, + 1817, 786, 1519, + 1810, 818, 1509, + 1800, 856, 1494, + 1787, 903, 1474, + 1768, 959, 1446, + 1742, 1025, 1405, + 1704, 1100, 1343, + 1649, 1185, 1245, + 1562, 1277, 1069, + 1411, 1378, 612, + 1071, 1484, 0, + 0, 1597, 0, + 0, 1713, 0, + 0, 1833, 0, + 0, 1956, 0, + 0, 2082, 0, + 0, 2208, 0, + 0, 2337, 0, + 0, 2466, 0, + 0, 2596, 0, + 0, 2726, 0, + 0, 2857, 0, + 0, 2988, 0, + 0, 3119, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3514, 0, + 0, 3646, 0, + 1966, 830, 1672, + 1964, 840, 1670, + 1962, 851, 1667, + 1959, 867, 1663, + 1955, 887, 1657, + 1950, 912, 1649, + 1943, 943, 1639, + 1933, 983, 1624, + 1920, 1030, 1604, + 1901, 1087, 1575, + 1875, 1153, 1534, + 1837, 1229, 1472, + 1782, 1314, 1373, + 1695, 1407, 1194, + 1544, 1508, 726, + 1206, 1615, 0, + 0, 1728, 0, + 0, 1845, 0, + 0, 1965, 0, + 0, 2088, 0, + 0, 2213, 0, + 0, 2340, 0, + 0, 2468, 0, + 0, 2598, 0, + 0, 2728, 0, + 0, 2858, 0, + 0, 2989, 0, + 0, 3120, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3646, 0, + 2100, 950, 1805, + 2099, 957, 1803, + 2097, 966, 1801, + 2095, 978, 1797, + 2092, 993, 1793, + 2088, 1013, 1787, + 2083, 1039, 1780, + 2075, 1071, 1769, + 2066, 1110, 1754, + 2052, 1159, 1734, + 2034, 1216, 1705, + 2007, 1282, 1663, + 1970, 1359, 1601, + 1914, 1444, 1502, + 1828, 1538, 1322, + 1678, 1639, 844, + 1341, 1746, 0, + 0, 1859, 0, + 0, 1976, 0, + 0, 2097, 0, + 0, 2220, 0, + 0, 2345, 0, + 0, 2472, 0, + 0, 2600, 0, + 0, 2730, 0, + 0, 2860, 0, + 0, 2990, 0, + 0, 3121, 0, + 0, 3252, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3647, 0, + 2233, 1072, 1937, + 2232, 1077, 1935, + 2231, 1084, 1934, + 2229, 1093, 1931, + 2227, 1106, 1928, + 2224, 1121, 1924, + 2220, 1142, 1918, + 2215, 1167, 1910, + 2208, 1200, 1900, + 2198, 1239, 1885, + 2185, 1288, 1864, + 2166, 1345, 1836, + 2140, 1412, 1794, + 2103, 1489, 1731, + 2047, 1575, 1631, + 1960, 1669, 1450, + 1810, 1770, 966, + 1475, 1878, 0, + 0, 1990, 0, + 0, 2108, 0, + 0, 2228, 0, + 0, 2352, 0, + 0, 2477, 0, + 0, 2604, 0, + 0, 2732, 0, + 0, 2862, 0, + 0, 2992, 0, + 0, 3122, 0, + 0, 3253, 0, + 0, 3384, 0, + 0, 3515, 0, + 0, 3647, 0, + 2366, 1196, 2069, + 2365, 1200, 2068, + 2365, 1206, 2067, + 2363, 1213, 2065, + 2362, 1222, 2063, + 2360, 1234, 2059, + 2357, 1250, 2055, + 2353, 1271, 2049, + 2347, 1297, 2041, + 2340, 1329, 2031, + 2330, 1369, 2016, + 2317, 1418, 1995, + 2298, 1475, 1966, + 2272, 1543, 1925, + 2235, 1620, 1862, + 2180, 1706, 1762, + 2093, 1800, 1579, + 1943, 1901, 1090, + 1608, 2009, 0, + 0, 2122, 0, + 0, 2239, 0, + 0, 2360, 0, + 0, 2483, 0, + 0, 2609, 0, + 0, 2736, 0, + 0, 2864, 0, + 0, 2994, 0, + 0, 3124, 0, + 0, 3254, 0, + 0, 3385, 0, + 0, 3516, 0, + 0, 3648, 0, + 2499, 1323, 2201, + 2498, 1326, 2200, + 2498, 1330, 2199, + 2497, 1335, 2198, + 2496, 1342, 2196, + 2494, 1352, 2194, + 2492, 1364, 2191, + 2489, 1380, 2186, + 2485, 1400, 2181, + 2480, 1426, 2173, + 2473, 1459, 2162, + 2463, 1499, 2147, + 2449, 1548, 2127, + 2431, 1606, 2098, + 2405, 1674, 2056, + 2367, 1751, 1993, + 2312, 1837, 1892, + 2225, 1931, 1709, + 2076, 2033, 1216, + 1741, 2141, 0, + 0, 2254, 0, + 0, 2371, 0, + 0, 2492, 0, + 0, 2615, 0, + 0, 2741, 0, + 0, 2868, 0, + 0, 2996, 0, + 0, 3126, 0, + 0, 3256, 0, + 0, 3386, 0, + 0, 3517, 0, + 0, 3648, 0, + 2631, 1450, 2333, + 2631, 1453, 2333, + 2631, 1456, 2332, + 2630, 1460, 2331, + 2629, 1465, 2330, + 2628, 1473, 2328, + 2626, 1482, 2325, + 2624, 1494, 2322, + 2621, 1510, 2318, + 2617, 1531, 2312, + 2612, 1557, 2304, + 2605, 1590, 2294, + 2595, 1630, 2279, + 2582, 1679, 2258, + 2563, 1737, 2229, + 2537, 1805, 2187, + 2500, 1882, 2124, + 2444, 1968, 2023, + 2358, 2063, 1840, + 2208, 2164, 1343, + 1874, 2272, 0, + 0, 2386, 0, + 0, 2503, 0, + 0, 2624, 0, + 0, 2747, 0, + 0, 2873, 0, + 0, 3000, 0, + 0, 3128, 0, + 0, 3258, 0, + 0, 3388, 0, + 0, 3518, 0, + 0, 3649, 0, + 2764, 1579, 2465, + 2764, 1581, 2465, + 2763, 1583, 2464, + 2763, 1586, 2464, + 2762, 1590, 2463, + 2761, 1596, 2461, + 2760, 1603, 2460, + 2758, 1613, 2457, + 2756, 1625, 2454, + 2753, 1641, 2450, + 2749, 1662, 2444, + 2744, 1688, 2436, + 2737, 1721, 2425, + 2727, 1761, 2410, + 2714, 1810, 2390, + 2695, 1868, 2361, + 2669, 1936, 2319, + 2632, 2013, 2256, + 2576, 2100, 2155, + 2490, 2194, 1971, + 2341, 2296, 1472, + 2006, 2404, 0, + 0, 2518, 0, + 0, 2635, 0, + 0, 2756, 0, + 0, 2879, 0, + 0, 3005, 0, + 0, 3132, 0, + 0, 3261, 0, + 0, 3390, 0, + 0, 3520, 0, + 0, 3650, 0, + 2896, 1709, 2597, + 2896, 1710, 2597, + 2896, 1712, 2597, + 2895, 1714, 2596, + 2895, 1717, 2595, + 2894, 1721, 2594, + 2893, 1727, 2593, + 2892, 1734, 2591, + 2891, 1744, 2589, + 2888, 1756, 2586, + 2886, 1772, 2581, + 2882, 1793, 2576, + 2876, 1819, 2568, + 2869, 1852, 2557, + 2859, 1892, 2542, + 2846, 1942, 2522, + 2827, 2000, 2492, + 2801, 2068, 2450, + 2764, 2145, 2387, + 2709, 2232, 2286, + 2622, 2326, 2102, + 2473, 2428, 1601, + 2139, 2536, 0, + 0, 2650, 0, + 0, 2767, 0, + 0, 2888, 0, + 0, 3011, 0, + 0, 3137, 0, + 0, 3264, 0, + 0, 3393, 0, + 0, 3522, 0, + 0, 3652, 0, + 3029, 1839, 2729, + 3029, 1840, 2729, + 3028, 1841, 2729, + 3028, 1843, 2729, + 3028, 1845, 2728, + 3027, 1849, 2727, + 3026, 1853, 2726, + 3026, 1858, 2725, + 3024, 1865, 2723, + 3023, 1875, 2721, + 3021, 1887, 2718, + 3018, 1904, 2713, + 3014, 1924, 2708, + 3009, 1950, 2700, + 3001, 1983, 2689, + 2992, 2024, 2674, + 2978, 2073, 2653, + 2960, 2132, 2624, + 2934, 2199, 2582, + 2896, 2277, 2519, + 2841, 2363, 2418, + 2754, 2458, 2234, + 2605, 2560, 1732, + 2271, 2668, 0, + 0, 2781, 0, + 0, 2899, 0, + 0, 3020, 0, + 0, 3144, 0, + 0, 3269, 0, + 0, 3396, 0, + 0, 3525, 0, + 0, 3654, 0, + 3161, 1970, 2862, + 3161, 1970, 2861, + 3161, 1971, 2861, + 3160, 1973, 2861, + 3160, 1975, 2860, + 3160, 1977, 2860, + 3159, 1980, 2859, + 3159, 1984, 2858, + 3158, 1990, 2857, + 3157, 1997, 2855, + 3155, 2006, 2853, + 3153, 2019, 2850, + 3150, 2035, 2845, + 3146, 2056, 2839, + 3141, 2082, 2832, + 3133, 2115, 2821, + 3124, 2156, 2806, + 3110, 2205, 2785, + 3092, 2263, 2756, + 3066, 2331, 2714, + 3028, 2409, 2651, + 2973, 2495, 2550, + 2887, 2590, 2365, + 2737, 2692, 1862, + 2404, 2800, 0, + 0, 2914, 0, + 0, 3031, 0, + 0, 3152, 0, + 0, 3276, 0, + 0, 3401, 0, + 0, 3528, 0, + 0, 3657, 0, + 3293, 2101, 2994, + 3293, 2101, 2994, + 3293, 2102, 2993, + 3293, 2103, 2993, + 3293, 2104, 2993, + 3292, 2106, 2992, + 3292, 2109, 2992, + 3291, 2112, 2991, + 3291, 2116, 2990, + 3290, 2121, 2989, + 3289, 2129, 2987, + 3287, 2138, 2985, + 3285, 2151, 2982, + 3282, 2167, 2977, + 3278, 2187, 2971, + 3273, 2214, 2963, + 3266, 2247, 2953, + 3256, 2287, 2938, + 3242, 2337, 2917, + 3224, 2395, 2888, + 3198, 2463, 2846, + 3160, 2541, 2783, + 3105, 2627, 2681, + 3019, 2722, 2497, + 2870, 2824, 1993, + 2536, 2932, 0, + 0, 3046, 0, + 0, 3163, 0, + 0, 3284, 0, + 0, 3408, 0, + 0, 3533, 0, + 0, 3660, 0, + 3425, 2232, 3126, + 3425, 2232, 3126, + 3425, 2233, 3126, + 3425, 2234, 3125, + 3425, 2235, 3125, + 3425, 2236, 3125, + 3424, 2238, 3124, + 3424, 2240, 3124, + 3424, 2243, 3123, + 3423, 2248, 3122, + 3422, 2253, 3121, + 3421, 2260, 3119, + 3419, 2270, 3117, + 3417, 2282, 3114, + 3414, 2299, 3109, + 3410, 2319, 3103, + 3405, 2346, 3095, + 3398, 2379, 3085, + 3388, 2419, 3070, + 3375, 2469, 3049, + 3356, 2527, 3020, + 3330, 2595, 2978, + 3293, 2673, 2915, + 3237, 2759, 2813, + 3151, 2854, 2629, + 3002, 2956, 2124, + 2668, 3064, 0, + 0, 3178, 0, + 0, 3295, 0, + 0, 3416, 0, + 0, 3540, 0, + 0, 3665, 0, + 3557, 2364, 3258, + 3557, 2364, 3258, + 3557, 2364, 3258, + 3557, 2365, 3258, + 3557, 2366, 3257, + 3557, 2367, 3257, + 3557, 2368, 3257, + 3557, 2370, 3256, + 3556, 2372, 3256, + 3556, 2375, 3255, + 3555, 2379, 3254, + 3554, 2385, 3253, + 3553, 2392, 3251, + 3551, 2402, 3249, + 3549, 2414, 3246, + 3546, 2430, 3241, + 3542, 2451, 3235, + 3537, 2477, 3228, + 3530, 2510, 3217, + 3520, 2551, 3202, + 3507, 2600, 3181, + 3488, 2659, 3152, + 3462, 2727, 3110, + 3425, 2805, 3047, + 3369, 2891, 2945, + 3283, 2986, 2761, + 3134, 3088, 2256, + 2800, 3196, 0, + 0, 3310, 0, + 0, 3427, 0, + 0, 3548, 0, + 0, 3672, 0, + 3690, 2495, 3390, + 3690, 2495, 3390, + 3690, 2496, 3390, + 3689, 2496, 3390, + 3689, 2497, 3390, + 3689, 2497, 3389, + 3689, 2498, 3389, + 3689, 2500, 3389, + 3689, 2502, 3389, + 3688, 2504, 3388, + 3688, 2507, 3387, + 3687, 2511, 3386, + 3686, 2517, 3385, + 3685, 2524, 3383, + 3683, 2534, 3381, + 3681, 2546, 3378, + 3678, 2562, 3373, + 3674, 2583, 3367, + 3669, 2609, 3360, + 3662, 2642, 3349, + 3652, 2683, 3334, + 3639, 2732, 3313, + 3620, 2791, 3284, + 3594, 2859, 3242, + 3557, 2937, 3179, + 3502, 3023, 3077, + 3415, 3118, 2893, + 3266, 3220, 2387, + 2933, 3328, 0, + 0, 3442, 0, + 0, 3559, 0, + 0, 3680, 0, + 3822, 2627, 3522, + 3822, 2627, 3522, + 3822, 2627, 3522, + 3822, 2628, 3522, + 3822, 2628, 3522, + 3821, 2629, 3522, + 3821, 2629, 3522, + 3821, 2630, 3521, + 3821, 2632, 3521, + 3821, 2634, 3521, + 3820, 2636, 3520, + 3820, 2639, 3519, + 3819, 2643, 3518, + 3818, 2649, 3517, + 3817, 2656, 3515, + 3815, 2666, 3513, + 3813, 2678, 3510, + 3810, 2694, 3505, + 3807, 2715, 3500, + 3801, 2741, 3492, + 3794, 2774, 3481, + 3784, 2815, 3466, + 3771, 2864, 3445, + 3752, 2923, 3416, + 3726, 2991, 3374, + 3689, 3069, 3311, + 3634, 3155, 3209, + 3547, 3250, 3025, + 3398, 3352, 2519, + 3065, 3460, 0, + 0, 3574, 0, + 0, 3691, 0, + 3954, 2759, 3654, + 3954, 2759, 3654, + 3954, 2759, 3654, + 3954, 2759, 3654, + 3954, 2760, 3654, + 3954, 2760, 3654, + 3954, 2761, 3654, + 3953, 2761, 3654, + 3953, 2762, 3653, + 3953, 2764, 3653, + 3953, 2766, 3653, + 3952, 2768, 3652, + 3952, 2771, 3651, + 3951, 2775, 3650, + 3950, 2781, 3649, + 3949, 2788, 3647, + 3948, 2798, 3645, + 3945, 2810, 3642, + 3943, 2826, 3637, + 3939, 2847, 3632, + 3933, 2873, 3624, + 3926, 2906, 3613, + 3916, 2947, 3598, + 3903, 2996, 3577, + 3884, 3055, 3548, + 3858, 3123, 3506, + 3821, 3201, 3443, + 3766, 3287, 3341, + 3679, 3382, 3157, + 3530, 3484, 2651, + 3197, 3592, 0, + 0, 3706, 0, + 4086, 2891, 3786, + 4086, 2891, 3786, + 4086, 2891, 3786, + 4086, 2891, 3786, + 4086, 2891, 3786, + 4086, 2892, 3786, + 4086, 2892, 3786, + 4086, 2893, 3786, + 4086, 2893, 3786, + 4085, 2894, 3785, + 4085, 2896, 3785, + 4085, 2898, 3785, + 4085, 2900, 3784, + 4084, 2903, 3783, + 4083, 2907, 3782, + 4083, 2913, 3781, + 4081, 2920, 3779, + 4080, 2930, 3777, + 4078, 2942, 3774, + 4075, 2958, 3769, + 4071, 2979, 3764, + 4065, 3005, 3756, + 4058, 3038, 3745, + 4049, 3079, 3730, + 4035, 3129, 3709, + 4017, 3187, 3680, + 3991, 3255, 3638, + 3953, 3333, 3575, + 3898, 3419, 3473, + 3811, 3514, 3289, + 3662, 3616, 2783, + 3329, 3725, 0, + 4095, 3023, 3918, + 4095, 3023, 3918, + 4095, 3023, 3918, + 4095, 3023, 3918, + 4095, 3023, 3918, + 4095, 3023, 3918, + 4095, 3024, 3918, + 4095, 3024, 3918, + 4095, 3025, 3918, + 4095, 3025, 3918, + 4095, 3026, 3918, + 4095, 3028, 3917, + 4095, 3030, 3917, + 4095, 3032, 3916, + 4095, 3035, 3916, + 4095, 3039, 3915, + 4095, 3045, 3913, + 4095, 3052, 3911, + 4095, 3062, 3909, + 4095, 3074, 3906, + 4095, 3090, 3902, + 4095, 3111, 3896, + 4095, 3137, 3888, + 4095, 3171, 3877, + 4095, 3211, 3862, + 4095, 3261, 3842, + 4095, 3319, 3812, + 4095, 3387, 3770, + 4085, 3465, 3707, + 4030, 3551, 3605, + 3944, 3646, 3421, + 3794, 3748, 2915, + 4095, 3155, 4050, + 4095, 3155, 4050, + 4095, 3155, 4050, + 4095, 3155, 4050, + 4095, 3155, 4050, + 4095, 3155, 4050, + 4095, 3155, 4050, + 4095, 3156, 4050, + 4095, 3156, 4050, + 4095, 3157, 4050, + 4095, 3158, 4050, + 4095, 3159, 4050, + 4095, 3160, 4049, + 4095, 3162, 4049, + 4095, 3164, 4048, + 4095, 3167, 4048, + 4095, 3171, 4047, + 4095, 3177, 4045, + 4095, 3184, 4044, + 4095, 3194, 4041, + 4095, 3206, 4038, + 4095, 3222, 4034, + 4095, 3243, 4028, + 4095, 3270, 4020, + 4095, 3303, 4009, + 4095, 3343, 3994, + 4095, 3393, 3974, + 4095, 3451, 3944, + 4095, 3519, 3902, + 4095, 3597, 3839, + 4095, 3684, 3738, + 4076, 3778, 3553, + 0, 0, 36, + 0, 24, 0, + 0, 91, 0, + 0, 168, 0, + 0, 254, 0, + 0, 348, 0, + 0, 449, 0, + 0, 557, 0, + 0, 669, 0, + 0, 787, 0, + 0, 907, 0, + 0, 1031, 0, + 0, 1156, 0, + 0, 1283, 0, + 0, 1411, 0, + 0, 1541, 0, + 0, 1671, 0, + 0, 1801, 0, + 0, 1932, 0, + 0, 2063, 0, + 0, 2195, 0, + 0, 2326, 0, + 0, 2458, 0, + 0, 2590, 0, + 0, 2722, 0, + 0, 2853, 0, + 0, 2985, 0, + 0, 3117, 0, + 0, 3249, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 67, 0, 149, + 0, 42, 77, + 0, 107, 0, + 0, 181, 0, + 0, 264, 0, + 0, 356, 0, + 0, 456, 0, + 0, 562, 0, + 0, 674, 0, + 0, 790, 0, + 0, 910, 0, + 0, 1033, 0, + 0, 1158, 0, + 0, 1284, 0, + 0, 1412, 0, + 0, 1541, 0, + 0, 1671, 0, + 0, 1801, 0, + 0, 1932, 0, + 0, 2063, 0, + 0, 2195, 0, + 0, 2326, 0, + 0, 2458, 0, + 0, 2590, 0, + 0, 2722, 0, + 0, 2853, 0, + 0, 2985, 0, + 0, 3117, 0, + 0, 3249, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 303, 13, 267, + 236, 65, 212, + 127, 127, 127, + 0, 198, 0, + 0, 279, 0, + 0, 368, 0, + 0, 465, 0, + 0, 570, 0, + 0, 680, 0, + 0, 795, 0, + 0, 913, 0, + 0, 1035, 0, + 0, 1160, 0, + 0, 1286, 0, + 0, 1413, 0, + 0, 1542, 0, + 0, 1672, 0, + 0, 1802, 0, + 0, 1933, 0, + 0, 2064, 0, + 0, 2195, 0, + 0, 2326, 0, + 0, 2458, 0, + 0, 2590, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2985, 0, + 0, 3117, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 500, 45, 387, + 458, 94, 346, + 394, 152, 284, + 292, 220, 186, + 105, 297, 8, + 0, 383, 0, + 0, 478, 0, + 0, 579, 0, + 0, 687, 0, + 0, 801, 0, + 0, 918, 0, + 0, 1039, 0, + 0, 1162, 0, + 0, 1288, 0, + 0, 1415, 0, + 0, 1543, 0, + 0, 1673, 0, + 0, 1803, 0, + 0, 1933, 0, + 0, 2064, 0, + 0, 2195, 0, + 0, 2327, 0, + 0, 2458, 0, + 0, 2590, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 676, 85, 511, + 647, 130, 480, + 606, 184, 434, + 545, 248, 366, + 447, 321, 254, + 271, 403, 43, + 0, 494, 0, + 0, 592, 0, + 0, 697, 0, + 0, 808, 0, + 0, 924, 0, + 0, 1044, 0, + 0, 1166, 0, + 0, 1291, 0, + 0, 1417, 0, + 0, 1545, 0, + 0, 1674, 0, + 0, 1803, 0, + 0, 1934, 0, + 0, 2064, 0, + 0, 2196, 0, + 0, 2327, 0, + 0, 2458, 0, + 0, 2590, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 837, 134, 636, + 818, 175, 613, + 790, 224, 579, + 750, 282, 531, + 690, 350, 456, + 596, 428, 332, + 427, 514, 85, + 12, 609, 0, + 0, 711, 0, + 0, 819, 0, + 0, 932, 0, + 0, 1050, 0, + 0, 1171, 0, + 0, 1294, 0, + 0, 1420, 0, + 0, 1547, 0, + 0, 1675, 0, + 0, 1805, 0, + 0, 1935, 0, + 0, 2065, 0, + 0, 2196, 0, + 0, 2327, 0, + 0, 2459, 0, + 0, 2590, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 991, 192, 763, + 977, 228, 746, + 957, 272, 721, + 930, 325, 686, + 891, 387, 634, + 832, 459, 554, + 740, 540, 419, + 577, 630, 136, + 186, 728, 0, + 0, 832, 0, + 0, 943, 0, + 0, 1058, 0, + 0, 1177, 0, + 0, 1299, 0, + 0, 1423, 0, + 0, 1550, 0, + 0, 1677, 0, + 0, 1806, 0, + 0, 1936, 0, + 0, 2066, 0, + 0, 2197, 0, + 0, 2328, 0, + 0, 2459, 0, + 0, 2591, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1138, 259, 892, + 1128, 290, 878, + 1114, 329, 860, + 1095, 376, 834, + 1068, 432, 798, + 1029, 497, 743, + 971, 572, 659, + 880, 657, 514, + 721, 749, 197, + 347, 850, 0, + 0, 956, 0, + 0, 1068, 0, + 0, 1185, 0, + 0, 1305, 0, + 0, 1428, 0, + 0, 1553, 0, + 0, 1680, 0, + 0, 1808, 0, + 0, 1937, 0, + 0, 2067, 0, + 0, 2198, 0, + 0, 2328, 0, + 0, 2460, 0, + 0, 2591, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1281, 336, 1021, + 1274, 362, 1011, + 1264, 395, 997, + 1250, 436, 978, + 1231, 486, 952, + 1204, 544, 914, + 1166, 613, 858, + 1109, 690, 770, + 1019, 777, 616, + 862, 872, 267, + 499, 974, 0, + 0, 1082, 0, + 0, 1196, 0, + 0, 1314, 0, + 0, 1435, 0, + 0, 1558, 0, + 0, 1684, 0, + 0, 1811, 0, + 0, 1939, 0, + 0, 2069, 0, + 0, 2199, 0, + 0, 2329, 0, + 0, 2460, 0, + 0, 2591, 0, + 0, 2723, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1421, 422, 1151, + 1416, 444, 1143, + 1408, 472, 1133, + 1398, 506, 1119, + 1385, 549, 1100, + 1366, 601, 1073, + 1339, 661, 1034, + 1301, 732, 976, + 1245, 811, 885, + 1156, 900, 725, + 1001, 997, 346, + 646, 1100, 0, + 0, 1210, 0, + 0, 1324, 0, + 0, 1443, 0, + 0, 1565, 0, + 0, 1689, 0, + 0, 1815, 0, + 0, 1942, 0, + 0, 2071, 0, + 0, 2200, 0, + 0, 2330, 0, + 0, 2461, 0, + 0, 2592, 0, + 0, 2723, 0, + 0, 2855, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1559, 516, 1281, + 1555, 534, 1276, + 1550, 557, 1268, + 1543, 586, 1258, + 1533, 622, 1244, + 1519, 666, 1224, + 1500, 719, 1197, + 1474, 782, 1157, + 1436, 854, 1098, + 1380, 935, 1004, + 1291, 1025, 838, + 1138, 1123, 434, + 789, 1228, 0, + 0, 1339, 0, + 0, 1454, 0, + 0, 1573, 0, + 0, 1695, 0, + 0, 1820, 0, + 0, 1946, 0, + 0, 2074, 0, + 0, 2202, 0, + 0, 2332, 0, + 0, 2462, 0, + 0, 2593, 0, + 0, 2724, 0, + 0, 2855, 0, + 0, 2987, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1696, 617, 1412, + 1693, 632, 1408, + 1689, 651, 1402, + 1683, 674, 1395, + 1676, 704, 1384, + 1666, 741, 1370, + 1653, 787, 1350, + 1634, 841, 1322, + 1608, 905, 1282, + 1570, 978, 1222, + 1514, 1061, 1126, + 1426, 1152, 956, + 1274, 1251, 531, + 929, 1357, 0, + 0, 1468, 0, + 0, 1584, 0, + 0, 1703, 0, + 0, 1826, 0, + 0, 1951, 0, + 0, 2077, 0, + 0, 2205, 0, + 0, 2334, 0, + 0, 2464, 0, + 0, 2594, 0, + 0, 2725, 0, + 0, 2856, 0, + 0, 2987, 0, + 0, 3119, 0, + 0, 3251, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1831, 725, 1543, + 1829, 737, 1540, + 1826, 752, 1536, + 1822, 771, 1530, + 1817, 795, 1523, + 1809, 826, 1512, + 1800, 864, 1498, + 1786, 910, 1478, + 1767, 965, 1449, + 1741, 1030, 1409, + 1703, 1105, 1348, + 1648, 1188, 1251, + 1560, 1280, 1077, + 1409, 1380, 634, + 1067, 1486, 0, + 0, 1598, 0, + 0, 1714, 0, + 0, 1834, 0, + 0, 1957, 0, + 0, 2082, 0, + 0, 2209, 0, + 0, 2337, 0, + 0, 2466, 0, + 0, 2596, 0, + 0, 2726, 0, + 0, 2857, 0, + 0, 2988, 0, + 0, 3119, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3514, 0, + 0, 3646, 0, + 1965, 838, 1675, + 1964, 847, 1672, + 1962, 859, 1669, + 1959, 874, 1665, + 1955, 894, 1659, + 1949, 918, 1652, + 1942, 950, 1641, + 1932, 988, 1626, + 1919, 1035, 1606, + 1900, 1092, 1578, + 1874, 1157, 1537, + 1837, 1232, 1475, + 1781, 1317, 1377, + 1694, 1409, 1201, + 1543, 1510, 744, + 1203, 1617, 0, + 0, 1729, 0, + 0, 1845, 0, + 0, 1966, 0, + 0, 2089, 0, + 0, 2214, 0, + 0, 2341, 0, + 0, 2469, 0, + 0, 2598, 0, + 0, 2728, 0, + 0, 2858, 0, + 0, 2989, 0, + 0, 3120, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3646, 0, + 2099, 956, 1806, + 2098, 963, 1805, + 2097, 972, 1802, + 2094, 983, 1799, + 2091, 999, 1795, + 2087, 1019, 1789, + 2082, 1044, 1781, + 2075, 1076, 1771, + 2065, 1115, 1756, + 2052, 1162, 1736, + 2033, 1219, 1707, + 2007, 1285, 1666, + 1969, 1361, 1604, + 1914, 1446, 1505, + 1827, 1539, 1326, + 1676, 1640, 858, + 1338, 1747, 0, + 0, 1860, 0, + 0, 1977, 0, + 0, 2097, 0, + 0, 2220, 0, + 0, 2345, 0, + 0, 2472, 0, + 0, 2601, 0, + 0, 2730, 0, + 0, 2860, 0, + 0, 2990, 0, + 0, 3121, 0, + 0, 3252, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3647, 0, + 2233, 1076, 1938, + 2232, 1082, 1937, + 2231, 1089, 1935, + 2229, 1098, 1933, + 2227, 1110, 1929, + 2224, 1125, 1925, + 2220, 1146, 1919, + 2215, 1171, 1912, + 2208, 1203, 1901, + 2198, 1243, 1886, + 2184, 1291, 1866, + 2166, 1348, 1837, + 2140, 1415, 1796, + 2102, 1491, 1733, + 2047, 1576, 1634, + 1960, 1670, 1454, + 1810, 1771, 976, + 1473, 1878, 0, + 0, 1991, 0, + 0, 2108, 0, + 0, 2229, 0, + 0, 2352, 0, + 0, 2477, 0, + 0, 2604, 0, + 0, 2732, 0, + 0, 2862, 0, + 0, 2992, 0, + 0, 3122, 0, + 0, 3253, 0, + 0, 3384, 0, + 0, 3516, 0, + 0, 3647, 0, + 2366, 1200, 2070, + 2365, 1204, 2069, + 2364, 1209, 2068, + 2363, 1216, 2066, + 2361, 1226, 2063, + 2359, 1238, 2060, + 2356, 1253, 2056, + 2352, 1274, 2050, + 2347, 1299, 2042, + 2340, 1332, 2032, + 2330, 1371, 2017, + 2317, 1420, 1997, + 2298, 1477, 1968, + 2272, 1544, 1926, + 2235, 1621, 1863, + 2179, 1707, 1763, + 2092, 1801, 1582, + 1943, 1902, 1098, + 1607, 2010, 0, + 0, 2123, 0, + 0, 2240, 0, + 0, 2360, 0, + 0, 2484, 0, + 0, 2609, 0, + 0, 2736, 0, + 0, 2864, 0, + 0, 2994, 0, + 0, 3124, 0, + 0, 3254, 0, + 0, 3385, 0, + 0, 3516, 0, + 0, 3648, 0, + 2499, 1325, 2202, + 2498, 1328, 2201, + 2498, 1332, 2200, + 2497, 1338, 2199, + 2495, 1345, 2197, + 2494, 1354, 2195, + 2492, 1367, 2191, + 2489, 1382, 2187, + 2485, 1403, 2181, + 2480, 1429, 2174, + 2472, 1461, 2163, + 2463, 1501, 2148, + 2449, 1550, 2128, + 2431, 1608, 2099, + 2404, 1675, 2057, + 2367, 1752, 1994, + 2312, 1838, 1894, + 2225, 1932, 1711, + 2075, 2033, 1222, + 1740, 2141, 0, + 0, 2254, 0, + 0, 2371, 0, + 0, 2492, 0, + 0, 2616, 0, + 0, 2741, 0, + 0, 2868, 0, + 0, 2996, 0, + 0, 3126, 0, + 0, 3256, 0, + 0, 3386, 0, + 0, 3517, 0, + 0, 3648, 0, + 2631, 1452, 2334, + 2631, 1455, 2333, + 2630, 1458, 2332, + 2630, 1462, 2331, + 2629, 1467, 2330, + 2628, 1474, 2328, + 2626, 1484, 2326, + 2624, 1496, 2323, + 2621, 1512, 2319, + 2617, 1533, 2313, + 2612, 1559, 2305, + 2605, 1591, 2294, + 2595, 1631, 2279, + 2581, 1680, 2259, + 2563, 1738, 2230, + 2537, 1806, 2188, + 2499, 1883, 2125, + 2444, 1969, 2024, + 2357, 2063, 1842, + 2208, 2165, 1348, + 1873, 2273, 0, + 0, 2386, 0, + 0, 2503, 0, + 0, 2624, 0, + 0, 2748, 0, + 0, 2873, 0, + 0, 3000, 0, + 0, 3129, 0, + 0, 3258, 0, + 0, 3388, 0, + 0, 3518, 0, + 0, 3649, 0, + 2764, 1581, 2466, + 2764, 1582, 2465, + 2763, 1585, 2465, + 2763, 1588, 2464, + 2762, 1592, 2463, + 2761, 1597, 2462, + 2760, 1605, 2460, + 2758, 1614, 2458, + 2756, 1626, 2454, + 2753, 1642, 2450, + 2749, 1663, 2444, + 2744, 1689, 2436, + 2737, 1722, 2426, + 2727, 1762, 2411, + 2714, 1811, 2390, + 2695, 1869, 2361, + 2669, 1937, 2319, + 2632, 2014, 2256, + 2576, 2100, 2155, + 2490, 2195, 1972, + 2340, 2297, 1475, + 2006, 2405, 0, + 0, 2518, 0, + 0, 2635, 0, + 0, 2756, 0, + 0, 2880, 0, + 0, 3005, 0, + 0, 3132, 0, + 0, 3261, 0, + 0, 3390, 0, + 0, 3520, 0, + 0, 3650, 0, + 2896, 1710, 2598, + 2896, 1711, 2597, + 2896, 1713, 2597, + 2895, 1715, 2596, + 2895, 1718, 2596, + 2894, 1723, 2595, + 2893, 1728, 2593, + 2892, 1735, 2592, + 2891, 1745, 2589, + 2888, 1757, 2586, + 2885, 1773, 2582, + 2882, 1794, 2576, + 2876, 1820, 2568, + 2869, 1853, 2557, + 2859, 1893, 2542, + 2846, 1942, 2522, + 2827, 2001, 2493, + 2801, 2068, 2451, + 2764, 2146, 2388, + 2709, 2232, 2287, + 2622, 2326, 2103, + 2473, 2428, 1604, + 2139, 2536, 0, + 0, 2650, 0, + 0, 2767, 0, + 0, 2888, 0, + 0, 3012, 0, + 0, 3137, 0, + 0, 3264, 0, + 0, 3393, 0, + 0, 3522, 0, + 0, 3652, 0, + 3029, 1840, 2730, + 3028, 1841, 2729, + 3028, 1842, 2729, + 3028, 1844, 2729, + 3028, 1846, 2728, + 3027, 1849, 2727, + 3026, 1854, 2726, + 3026, 1859, 2725, + 3024, 1866, 2723, + 3023, 1876, 2721, + 3021, 1888, 2718, + 3018, 1904, 2714, + 3014, 1925, 2708, + 3008, 1951, 2700, + 3001, 1984, 2689, + 2992, 2025, 2674, + 2978, 2074, 2654, + 2960, 2132, 2625, + 2933, 2200, 2582, + 2896, 2277, 2519, + 2841, 2364, 2418, + 2754, 2458, 2234, + 2605, 2560, 1733, + 2271, 2668, 0, + 0, 2782, 0, + 0, 2899, 0, + 0, 3020, 0, + 0, 3144, 0, + 0, 3269, 0, + 0, 3396, 0, + 0, 3525, 0, + 0, 3654, 0, + 3161, 1970, 2862, + 3161, 1971, 2862, + 3161, 1972, 2861, + 3160, 1973, 2861, + 3160, 1975, 2861, + 3160, 1978, 2860, + 3159, 1981, 2859, + 3159, 1985, 2858, + 3158, 1990, 2857, + 3156, 1998, 2855, + 3155, 2007, 2853, + 3153, 2020, 2850, + 3150, 2036, 2845, + 3146, 2056, 2840, + 3141, 2083, 2832, + 3133, 2115, 2821, + 3124, 2156, 2806, + 3110, 2205, 2785, + 3092, 2264, 2756, + 3066, 2332, 2714, + 3028, 2409, 2651, + 2973, 2495, 2550, + 2887, 2590, 2366, + 2737, 2692, 1864, + 2403, 2800, 0, + 0, 2914, 0, + 0, 3031, 0, + 0, 3152, 0, + 0, 3276, 0, + 0, 3401, 0, + 0, 3528, 0, + 0, 3657, 0, + 3293, 2101, 2994, + 3293, 2102, 2994, + 3293, 2103, 2993, + 3293, 2104, 2993, + 3293, 2105, 2993, + 3292, 2107, 2993, + 3292, 2109, 2992, + 3291, 2112, 2991, + 3291, 2116, 2990, + 3290, 2122, 2989, + 3289, 2129, 2987, + 3287, 2139, 2985, + 3285, 2151, 2982, + 3282, 2167, 2977, + 3278, 2188, 2972, + 3273, 2214, 2964, + 3266, 2247, 2953, + 3256, 2288, 2938, + 3242, 2337, 2917, + 3224, 2395, 2888, + 3198, 2463, 2846, + 3160, 2541, 2783, + 3105, 2627, 2682, + 3019, 2722, 2497, + 2869, 2824, 1994, + 2536, 2932, 0, + 0, 3046, 0, + 0, 3163, 0, + 0, 3284, 0, + 0, 3408, 0, + 0, 3533, 0, + 0, 3660, 0, + 3425, 2232, 3126, + 3425, 2233, 3126, + 3425, 2233, 3126, + 3425, 2234, 3125, + 3425, 2235, 3125, + 3425, 2236, 3125, + 3424, 2238, 3125, + 3424, 2241, 3124, + 3424, 2244, 3123, + 3423, 2248, 3122, + 3422, 2253, 3121, + 3421, 2261, 3119, + 3419, 2270, 3117, + 3417, 2283, 3114, + 3414, 2299, 3109, + 3410, 2320, 3103, + 3405, 2346, 3096, + 3398, 2379, 3085, + 3388, 2420, 3070, + 3375, 2469, 3049, + 3356, 2527, 3020, + 3330, 2595, 2978, + 3293, 2673, 2915, + 3237, 2759, 2814, + 3151, 2854, 2629, + 3002, 2956, 2125, + 2668, 3064, 0, + 0, 3178, 0, + 0, 3295, 0, + 0, 3416, 0, + 0, 3540, 0, + 0, 3665, 0, + 3557, 2364, 3258, + 3557, 2364, 3258, + 3557, 2365, 3258, + 3557, 2365, 3258, + 3557, 2366, 3257, + 3557, 2367, 3257, + 3557, 2368, 3257, + 3557, 2370, 3257, + 3556, 2372, 3256, + 3556, 2375, 3255, + 3555, 2380, 3254, + 3554, 2385, 3253, + 3553, 2392, 3251, + 3551, 2402, 3249, + 3549, 2414, 3246, + 3546, 2431, 3241, + 3542, 2451, 3235, + 3537, 2478, 3228, + 3530, 2511, 3217, + 3520, 2551, 3202, + 3507, 2601, 3181, + 3488, 2659, 3152, + 3462, 2727, 3110, + 3425, 2805, 3047, + 3369, 2891, 2945, + 3283, 2986, 2761, + 3134, 3088, 2256, + 2800, 3196, 0, + 0, 3310, 0, + 0, 3427, 0, + 0, 3548, 0, + 0, 3672, 0, + 3690, 2495, 3390, + 3690, 2496, 3390, + 3690, 2496, 3390, + 3689, 2496, 3390, + 3689, 2497, 3390, + 3689, 2498, 3389, + 3689, 2499, 3389, + 3689, 2500, 3389, + 3689, 2502, 3389, + 3688, 2504, 3388, + 3688, 2507, 3387, + 3687, 2511, 3386, + 3686, 2517, 3385, + 3685, 2524, 3383, + 3683, 2534, 3381, + 3681, 2546, 3378, + 3678, 2562, 3373, + 3674, 2583, 3368, + 3669, 2610, 3360, + 3662, 2643, 3349, + 3652, 2683, 3334, + 3639, 2733, 3313, + 3620, 2791, 3284, + 3594, 2859, 3242, + 3557, 2937, 3179, + 3502, 3023, 3077, + 3415, 3118, 2893, + 3266, 3220, 2388, + 2932, 3328, 0, + 0, 3442, 0, + 0, 3559, 0, + 0, 3680, 0, + 3822, 2627, 3522, + 3822, 2627, 3522, + 3822, 2628, 3522, + 3822, 2628, 3522, + 3822, 2628, 3522, + 3821, 2629, 3522, + 3821, 2630, 3522, + 3821, 2631, 3521, + 3821, 2632, 3521, + 3821, 2634, 3521, + 3820, 2636, 3520, + 3820, 2639, 3519, + 3819, 2643, 3518, + 3818, 2649, 3517, + 3817, 2656, 3515, + 3815, 2666, 3513, + 3813, 2678, 3510, + 3810, 2694, 3505, + 3807, 2715, 3500, + 3801, 2742, 3492, + 3794, 2775, 3481, + 3784, 2815, 3466, + 3771, 2865, 3445, + 3752, 2923, 3416, + 3726, 2991, 3374, + 3689, 3069, 3311, + 3634, 3155, 3209, + 3547, 3250, 3025, + 3398, 3352, 2520, + 3065, 3460, 0, + 0, 3574, 0, + 0, 3691, 0, + 3954, 2759, 3654, + 3954, 2759, 3654, + 3954, 2759, 3654, + 3954, 2759, 3654, + 3954, 2760, 3654, + 3954, 2760, 3654, + 3954, 2761, 3654, + 3953, 2762, 3654, + 3953, 2763, 3653, + 3953, 2764, 3653, + 3953, 2766, 3653, + 3952, 2768, 3652, + 3952, 2771, 3651, + 3951, 2775, 3650, + 3950, 2781, 3649, + 3949, 2788, 3647, + 3948, 2798, 3645, + 3945, 2810, 3642, + 3943, 2826, 3637, + 3939, 2847, 3632, + 3933, 2873, 3624, + 3926, 2907, 3613, + 3916, 2947, 3598, + 3903, 2997, 3577, + 3884, 3055, 3548, + 3858, 3123, 3506, + 3821, 3201, 3443, + 3766, 3287, 3341, + 3679, 3382, 3157, + 3530, 3484, 2651, + 3197, 3592, 0, + 0, 3706, 0, + 4086, 2891, 3786, + 4086, 2891, 3786, + 4086, 2891, 3786, + 4086, 2891, 3786, + 4086, 2891, 3786, + 4086, 2892, 3786, + 4086, 2892, 3786, + 4086, 2893, 3786, + 4086, 2894, 3786, + 4085, 2895, 3785, + 4085, 2896, 3785, + 4085, 2898, 3785, + 4085, 2900, 3784, + 4084, 2903, 3783, + 4083, 2907, 3782, + 4083, 2913, 3781, + 4081, 2920, 3779, + 4080, 2930, 3777, + 4078, 2942, 3774, + 4075, 2958, 3770, + 4071, 2979, 3764, + 4065, 3005, 3756, + 4058, 3039, 3745, + 4049, 3079, 3730, + 4035, 3129, 3709, + 4017, 3187, 3680, + 3991, 3255, 3638, + 3953, 3333, 3575, + 3898, 3419, 3473, + 3811, 3514, 3289, + 3662, 3616, 2783, + 3329, 3725, 0, + 4095, 3023, 3918, + 4095, 3023, 3918, + 4095, 3023, 3918, + 4095, 3023, 3918, + 4095, 3023, 3918, + 4095, 3023, 3918, + 4095, 3024, 3918, + 4095, 3024, 3918, + 4095, 3025, 3918, + 4095, 3026, 3918, + 4095, 3027, 3918, + 4095, 3028, 3917, + 4095, 3030, 3917, + 4095, 3032, 3916, + 4095, 3035, 3916, + 4095, 3039, 3915, + 4095, 3045, 3913, + 4095, 3052, 3911, + 4095, 3062, 3909, + 4095, 3074, 3906, + 4095, 3090, 3902, + 4095, 3111, 3896, + 4095, 3138, 3888, + 4095, 3171, 3877, + 4095, 3211, 3862, + 4095, 3261, 3842, + 4095, 3319, 3812, + 4095, 3387, 3770, + 4085, 3465, 3707, + 4030, 3551, 3606, + 3944, 3646, 3421, + 3794, 3748, 2915, + 4095, 3155, 4050, + 4095, 3155, 4050, + 4095, 3155, 4050, + 4095, 3155, 4050, + 4095, 3155, 4050, + 4095, 3155, 4050, + 4095, 3156, 4050, + 4095, 3156, 4050, + 4095, 3156, 4050, + 4095, 3157, 4050, + 4095, 3158, 4050, + 4095, 3159, 4050, + 4095, 3160, 4049, + 4095, 3162, 4049, + 4095, 3164, 4048, + 4095, 3167, 4048, + 4095, 3171, 4047, + 4095, 3177, 4045, + 4095, 3184, 4044, + 4095, 3194, 4041, + 4095, 3206, 4038, + 4095, 3222, 4034, + 4095, 3243, 4028, + 4095, 3270, 4020, + 4095, 3303, 4009, + 4095, 3343, 3994, + 4095, 3393, 3974, + 4095, 3451, 3944, + 4095, 3519, 3902, + 4095, 3597, 3839, + 4095, 3684, 3738, + 4076, 3778, 3553, + 0, 33, 135, + 0, 83, 61, + 0, 142, 0, + 0, 211, 0, + 0, 290, 0, + 0, 377, 0, + 0, 473, 0, + 0, 576, 0, + 0, 684, 0, + 0, 798, 0, + 0, 916, 0, + 0, 1037, 0, + 0, 1161, 0, + 0, 1287, 0, + 0, 1414, 0, + 0, 1543, 0, + 0, 1672, 0, + 0, 1802, 0, + 0, 1933, 0, + 0, 2064, 0, + 0, 2195, 0, + 0, 2327, 0, + 0, 2458, 0, + 0, 2590, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 11, 50, 228, + 0, 99, 168, + 0, 156, 74, + 0, 223, 0, + 0, 300, 0, + 0, 386, 0, + 0, 480, 0, + 0, 581, 0, + 0, 689, 0, + 0, 802, 0, + 0, 919, 0, + 0, 1039, 0, + 0, 1163, 0, + 0, 1288, 0, + 0, 1415, 0, + 0, 1543, 0, + 0, 1673, 0, + 0, 1803, 0, + 0, 1933, 0, + 0, 2064, 0, + 0, 2195, 0, + 0, 2327, 0, + 0, 2458, 0, + 0, 2590, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 271, 73, 329, + 199, 119, 281, + 79, 174, 209, + 0, 239, 91, + 0, 313, 0, + 0, 397, 0, + 0, 489, 0, + 0, 588, 0, + 0, 694, 0, + 0, 806, 0, + 0, 922, 0, + 0, 1042, 0, + 0, 1165, 0, + 0, 1290, 0, + 0, 1416, 0, + 0, 1544, 0, + 0, 1673, 0, + 0, 1803, 0, + 0, 1934, 0, + 0, 2064, 0, + 0, 2195, 0, + 0, 2327, 0, + 0, 2458, 0, + 0, 2590, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 480, 102, 436, + 435, 145, 399, + 368, 197, 344, + 259, 259, 259, + 54, 330, 113, + 0, 411, 0, + 0, 500, 0, + 0, 597, 0, + 0, 702, 0, + 0, 812, 0, + 0, 927, 0, + 0, 1045, 0, + 0, 1167, 0, + 0, 1292, 0, + 0, 1418, 0, + 0, 1546, 0, + 0, 1674, 0, + 0, 1804, 0, + 0, 1934, 0, + 0, 2065, 0, + 0, 2196, 0, + 0, 2327, 0, + 0, 2458, 0, + 0, 2590, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 662, 137, 548, + 632, 177, 519, + 590, 226, 478, + 526, 284, 416, + 424, 352, 318, + 237, 429, 140, + 0, 515, 0, + 0, 610, 0, + 0, 711, 0, + 0, 819, 0, + 0, 933, 0, + 0, 1050, 0, + 0, 1171, 0, + 0, 1294, 0, + 0, 1420, 0, + 0, 1547, 0, + 0, 1675, 0, + 0, 1805, 0, + 0, 1935, 0, + 0, 2065, 0, + 0, 2196, 0, + 0, 2327, 0, + 0, 2459, 0, + 0, 2590, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 828, 181, 665, + 808, 217, 643, + 779, 262, 612, + 738, 316, 566, + 677, 380, 498, + 579, 453, 386, + 403, 535, 175, + 0, 626, 0, + 0, 724, 0, + 0, 830, 0, + 0, 941, 0, + 0, 1056, 0, + 0, 1176, 0, + 0, 1298, 0, + 0, 1423, 0, + 0, 1549, 0, + 0, 1677, 0, + 0, 1806, 0, + 0, 1936, 0, + 0, 2066, 0, + 0, 2197, 0, + 0, 2328, 0, + 0, 2459, 0, + 0, 2590, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 984, 233, 785, + 970, 266, 768, + 950, 307, 745, + 922, 356, 712, + 882, 414, 663, + 822, 482, 588, + 728, 560, 464, + 559, 646, 217, + 144, 741, 0, + 0, 843, 0, + 0, 951, 0, + 0, 1064, 0, + 0, 1182, 0, + 0, 1303, 0, + 0, 1426, 0, + 0, 1552, 0, + 0, 1679, 0, + 0, 1807, 0, + 0, 1937, 0, + 0, 2067, 0, + 0, 2197, 0, + 0, 2328, 0, + 0, 2459, 0, + 0, 2591, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1133, 295, 908, + 1123, 324, 895, + 1109, 360, 878, + 1089, 404, 853, + 1062, 457, 818, + 1023, 519, 766, + 964, 591, 686, + 872, 672, 551, + 709, 762, 268, + 318, 860, 0, + 0, 964, 0, + 0, 1075, 0, + 0, 1190, 0, + 0, 1309, 0, + 0, 1431, 0, + 0, 1555, 0, + 0, 1682, 0, + 0, 1809, 0, + 0, 1938, 0, + 0, 2068, 0, + 0, 2198, 0, + 0, 2329, 0, + 0, 2460, 0, + 0, 2591, 0, + 0, 2723, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1277, 366, 1033, + 1270, 391, 1024, + 1260, 422, 1010, + 1246, 461, 992, + 1227, 508, 967, + 1200, 564, 930, + 1161, 629, 876, + 1103, 705, 791, + 1013, 789, 646, + 853, 882, 329, + 479, 982, 0, + 0, 1088, 0, + 0, 1201, 0, + 0, 1317, 0, + 0, 1437, 0, + 0, 1560, 0, + 0, 1685, 0, + 0, 1812, 0, + 0, 1940, 0, + 0, 2069, 0, + 0, 2199, 0, + 0, 2330, 0, + 0, 2460, 0, + 0, 2592, 0, + 0, 2723, 0, + 0, 2855, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1418, 447, 1160, + 1413, 468, 1153, + 1406, 494, 1143, + 1396, 528, 1129, + 1382, 568, 1111, + 1363, 618, 1084, + 1336, 677, 1046, + 1298, 745, 990, + 1241, 822, 902, + 1151, 909, 748, + 994, 1004, 399, + 631, 1106, 0, + 0, 1214, 0, + 0, 1328, 0, + 0, 1446, 0, + 0, 1567, 0, + 0, 1690, 0, + 0, 1816, 0, + 0, 1943, 0, + 0, 2072, 0, + 0, 2201, 0, + 0, 2331, 0, + 0, 2461, 0, + 0, 2592, 0, + 0, 2724, 0, + 0, 2855, 0, + 0, 2987, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1557, 537, 1288, + 1553, 554, 1283, + 1548, 576, 1275, + 1540, 604, 1265, + 1531, 639, 1251, + 1517, 681, 1232, + 1498, 733, 1205, + 1471, 793, 1166, + 1433, 864, 1108, + 1377, 944, 1017, + 1288, 1032, 857, + 1133, 1129, 478, + 778, 1232, 0, + 0, 1342, 0, + 0, 1456, 0, + 0, 1575, 0, + 0, 1697, 0, + 0, 1821, 0, + 0, 1947, 0, + 0, 2074, 0, + 0, 2203, 0, + 0, 2332, 0, + 0, 2463, 0, + 0, 2593, 0, + 0, 2724, 0, + 0, 2855, 0, + 0, 2987, 0, + 0, 3119, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1694, 634, 1417, + 1691, 648, 1413, + 1687, 666, 1408, + 1682, 689, 1400, + 1675, 718, 1390, + 1665, 754, 1376, + 1651, 798, 1356, + 1632, 851, 1329, + 1606, 914, 1289, + 1568, 986, 1230, + 1512, 1067, 1136, + 1424, 1157, 970, + 1270, 1255, 567, + 921, 1360, 0, + 0, 1471, 0, + 0, 1586, 0, + 0, 1705, 0, + 0, 1827, 0, + 0, 1952, 0, + 0, 2078, 0, + 0, 2206, 0, + 0, 2334, 0, + 0, 2464, 0, + 0, 2594, 0, + 0, 2725, 0, + 0, 2856, 0, + 0, 2987, 0, + 0, 3119, 0, + 0, 3251, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1830, 738, 1547, + 1828, 750, 1544, + 1825, 764, 1540, + 1821, 783, 1534, + 1815, 806, 1527, + 1808, 836, 1516, + 1798, 873, 1502, + 1785, 919, 1482, + 1766, 973, 1454, + 1740, 1037, 1414, + 1702, 1110, 1354, + 1646, 1193, 1258, + 1558, 1284, 1088, + 1406, 1383, 663, + 1061, 1489, 0, + 0, 1600, 0, + 0, 1716, 0, + 0, 1836, 0, + 0, 1958, 0, + 0, 2083, 0, + 0, 2209, 0, + 0, 2337, 0, + 0, 2466, 0, + 0, 2596, 0, + 0, 2726, 0, + 0, 2857, 0, + 0, 2988, 0, + 0, 3119, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3514, 0, + 0, 3646, 0, + 1965, 849, 1678, + 1963, 857, 1675, + 1961, 869, 1672, + 1958, 884, 1668, + 1954, 903, 1662, + 1949, 927, 1655, + 1941, 958, 1644, + 1932, 996, 1630, + 1918, 1042, 1610, + 1899, 1097, 1582, + 1873, 1162, 1541, + 1835, 1237, 1480, + 1780, 1320, 1383, + 1692, 1412, 1209, + 1541, 1512, 766, + 1199, 1618, 0, + 0, 1730, 0, + 0, 1847, 0, + 0, 1966, 0, + 0, 2089, 0, + 0, 2214, 0, + 0, 2341, 0, + 0, 2469, 0, + 0, 2598, 0, + 0, 2728, 0, + 0, 2858, 0, + 0, 2989, 0, + 0, 3120, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3646, 0, + 2099, 964, 1809, + 2098, 970, 1807, + 2096, 979, 1804, + 2094, 991, 1801, + 2091, 1006, 1797, + 2087, 1026, 1791, + 2082, 1051, 1784, + 2074, 1082, 1773, + 2065, 1120, 1759, + 2051, 1167, 1738, + 2032, 1224, 1710, + 2006, 1289, 1669, + 1969, 1364, 1607, + 1913, 1449, 1509, + 1826, 1542, 1333, + 1675, 1642, 876, + 1335, 1749, 0, + 0, 1861, 0, + 0, 1978, 0, + 0, 2098, 0, + 0, 2221, 0, + 0, 2346, 0, + 0, 2473, 0, + 0, 2601, 0, + 0, 2730, 0, + 0, 2860, 0, + 0, 2990, 0, + 0, 3121, 0, + 0, 3252, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3647, 0, + 2232, 1083, 1940, + 2231, 1088, 1938, + 2230, 1095, 1937, + 2229, 1104, 1934, + 2226, 1116, 1931, + 2224, 1131, 1927, + 2220, 1151, 1921, + 2214, 1176, 1913, + 2207, 1208, 1903, + 2197, 1247, 1888, + 2184, 1294, 1868, + 2165, 1351, 1839, + 2139, 1417, 1798, + 2101, 1493, 1736, + 2046, 1578, 1637, + 1959, 1671, 1459, + 1809, 1772, 990, + 1470, 1879, 0, + 0, 1992, 0, + 0, 2109, 0, + 0, 2229, 0, + 0, 2352, 0, + 0, 2478, 0, + 0, 2604, 0, + 0, 2733, 0, + 0, 2862, 0, + 0, 2992, 0, + 0, 3122, 0, + 0, 3253, 0, + 0, 3384, 0, + 0, 3516, 0, + 0, 3647, 0, + 2366, 1204, 2071, + 2365, 1208, 2070, + 2364, 1214, 2069, + 2363, 1221, 2067, + 2361, 1230, 2065, + 2359, 1242, 2062, + 2356, 1258, 2057, + 2352, 1278, 2052, + 2347, 1303, 2044, + 2340, 1335, 2033, + 2330, 1375, 2018, + 2316, 1423, 1998, + 2298, 1480, 1969, + 2272, 1547, 1928, + 2234, 1623, 1865, + 2179, 1708, 1766, + 2092, 1802, 1586, + 1942, 1903, 1108, + 1605, 2010, 0, + 0, 2123, 0, + 0, 2240, 0, + 0, 2361, 0, + 0, 2484, 0, + 0, 2609, 0, + 0, 2736, 0, + 0, 2865, 0, + 0, 2994, 0, + 0, 3124, 0, + 0, 3254, 0, + 0, 3385, 0, + 0, 3516, 0, + 0, 3648, 0, + 2498, 1329, 2203, + 2498, 1332, 2202, + 2497, 1336, 2201, + 2496, 1341, 2200, + 2495, 1348, 2198, + 2494, 1358, 2196, + 2491, 1370, 2192, + 2488, 1385, 2188, + 2485, 1406, 2182, + 2479, 1431, 2175, + 2472, 1464, 2164, + 2462, 1504, 2149, + 2449, 1552, 2129, + 2430, 1609, 2100, + 2404, 1677, 2058, + 2367, 1753, 1995, + 2311, 1839, 1896, + 2225, 1933, 1714, + 2075, 2034, 1230, + 1739, 2142, 0, + 0, 2255, 0, + 0, 2372, 0, + 0, 2492, 0, + 0, 2616, 0, + 0, 2741, 0, + 0, 2868, 0, + 0, 2997, 0, + 0, 3126, 0, + 0, 3256, 0, + 0, 3386, 0, + 0, 3517, 0, + 0, 3648, 0, + 2631, 1455, 2334, + 2631, 1457, 2334, + 2630, 1460, 2333, + 2630, 1464, 2332, + 2629, 1470, 2331, + 2628, 1477, 2329, + 2626, 1486, 2327, + 2624, 1499, 2324, + 2621, 1514, 2319, + 2617, 1535, 2313, + 2612, 1561, 2306, + 2604, 1593, 2295, + 2595, 1633, 2280, + 2581, 1682, 2260, + 2563, 1740, 2231, + 2537, 1807, 2189, + 2499, 1884, 2126, + 2444, 1970, 2026, + 2357, 2064, 1844, + 2207, 2165, 1354, + 1872, 2273, 0, + 0, 2386, 0, + 0, 2504, 0, + 0, 2624, 0, + 0, 2748, 0, + 0, 2873, 0, + 0, 3000, 0, + 0, 3129, 0, + 0, 3258, 0, + 0, 3388, 0, + 0, 3518, 0, + 0, 3649, 0, + 2764, 1583, 2466, + 2763, 1584, 2466, + 2763, 1587, 2465, + 2763, 1590, 2464, + 2762, 1594, 2464, + 2761, 1599, 2462, + 2760, 1607, 2460, + 2758, 1616, 2458, + 2756, 1628, 2455, + 2753, 1644, 2451, + 2749, 1665, 2445, + 2744, 1691, 2437, + 2737, 1723, 2426, + 2727, 1764, 2411, + 2714, 1812, 2391, + 2695, 1870, 2362, + 2669, 1938, 2320, + 2631, 2015, 2257, + 2576, 2101, 2156, + 2490, 2195, 1974, + 2340, 2297, 1480, + 2005, 2405, 0, + 0, 2518, 0, + 0, 2635, 0, + 0, 2756, 0, + 0, 2880, 0, + 0, 3005, 0, + 0, 3132, 0, + 0, 3261, 0, + 0, 3390, 0, + 0, 3520, 0, + 0, 3650, 0, + 2896, 1711, 2598, + 2896, 1713, 2598, + 2896, 1714, 2597, + 2895, 1717, 2597, + 2895, 1720, 2596, + 2894, 1724, 2595, + 2893, 1730, 2594, + 2892, 1737, 2592, + 2890, 1746, 2590, + 2888, 1759, 2586, + 2885, 1775, 2582, + 2881, 1795, 2576, + 2876, 1821, 2568, + 2869, 1854, 2558, + 2859, 1894, 2543, + 2846, 1943, 2522, + 2827, 2001, 2493, + 2801, 2069, 2451, + 2764, 2146, 2388, + 2708, 2232, 2288, + 2622, 2327, 2104, + 2472, 2429, 1608, + 2138, 2537, 0, + 0, 2650, 0, + 0, 2767, 0, + 0, 2888, 0, + 0, 3012, 0, + 0, 3137, 0, + 0, 3264, 0, + 0, 3393, 0, + 0, 3522, 0, + 0, 3652, 0, + 3029, 1841, 2730, + 3028, 1842, 2730, + 3028, 1843, 2729, + 3028, 1845, 2729, + 3028, 1847, 2728, + 3027, 1851, 2728, + 3026, 1855, 2727, + 3025, 1860, 2725, + 3024, 1867, 2724, + 3023, 1877, 2721, + 3020, 1889, 2718, + 3018, 1905, 2714, + 3014, 1926, 2708, + 3008, 1952, 2700, + 3001, 1985, 2689, + 2991, 2025, 2675, + 2978, 2074, 2654, + 2959, 2133, 2625, + 2933, 2200, 2583, + 2896, 2278, 2520, + 2841, 2364, 2419, + 2754, 2459, 2235, + 2605, 2560, 1736, + 2271, 2668, 0, + 0, 2782, 0, + 0, 2899, 0, + 0, 3020, 0, + 0, 3144, 0, + 0, 3269, 0, + 0, 3396, 0, + 0, 3525, 0, + 0, 3654, 0, + 3161, 1971, 2862, + 3161, 1972, 2862, + 3161, 1973, 2862, + 3160, 1974, 2861, + 3160, 1976, 2861, + 3160, 1978, 2860, + 3159, 1981, 2860, + 3159, 1986, 2859, + 3158, 1991, 2857, + 3156, 1998, 2856, + 3155, 2008, 2853, + 3153, 2020, 2850, + 3150, 2036, 2846, + 3146, 2057, 2840, + 3141, 2083, 2832, + 3133, 2116, 2821, + 3124, 2157, 2806, + 3110, 2206, 2786, + 3092, 2264, 2757, + 3066, 2332, 2715, + 3028, 2409, 2651, + 2973, 2496, 2550, + 2886, 2590, 2366, + 2737, 2692, 1866, + 2403, 2800, 0, + 0, 2914, 0, + 0, 3031, 0, + 0, 3152, 0, + 0, 3276, 0, + 0, 3401, 0, + 0, 3528, 0, + 0, 3657, 0, + 3293, 2102, 2994, + 3293, 2102, 2994, + 3293, 2103, 2994, + 3293, 2104, 2993, + 3292, 2105, 2993, + 3292, 2107, 2993, + 3292, 2110, 2992, + 3291, 2113, 2991, + 3291, 2117, 2990, + 3290, 2122, 2989, + 3289, 2130, 2987, + 3287, 2139, 2985, + 3285, 2152, 2982, + 3282, 2168, 2978, + 3278, 2188, 2972, + 3273, 2215, 2964, + 3266, 2248, 2953, + 3256, 2288, 2938, + 3242, 2337, 2918, + 3224, 2396, 2888, + 3198, 2464, 2846, + 3160, 2541, 2783, + 3105, 2628, 2682, + 3019, 2722, 2498, + 2869, 2824, 1996, + 2536, 2932, 0, + 0, 3046, 0, + 0, 3163, 0, + 0, 3284, 0, + 0, 3408, 0, + 0, 3533, 0, + 0, 3660, 0, + 3425, 2233, 3126, + 3425, 2233, 3126, + 3425, 2234, 3126, + 3425, 2235, 3126, + 3425, 2236, 3125, + 3425, 2237, 3125, + 3424, 2239, 3125, + 3424, 2241, 3124, + 3423, 2244, 3123, + 3423, 2248, 3122, + 3422, 2254, 3121, + 3421, 2261, 3119, + 3419, 2271, 3117, + 3417, 2283, 3114, + 3414, 2299, 3109, + 3410, 2320, 3104, + 3405, 2346, 3096, + 3398, 2379, 3085, + 3388, 2420, 3070, + 3375, 2469, 3049, + 3356, 2527, 3020, + 3330, 2595, 2978, + 3293, 2673, 2915, + 3237, 2759, 2814, + 3151, 2854, 2629, + 3002, 2956, 2126, + 2668, 3064, 0, + 0, 3178, 0, + 0, 3295, 0, + 0, 3416, 0, + 0, 3540, 0, + 0, 3665, 0, + 3557, 2364, 3258, + 3557, 2365, 3258, + 3557, 2365, 3258, + 3557, 2365, 3258, + 3557, 2366, 3258, + 3557, 2367, 3257, + 3557, 2369, 3257, + 3556, 2370, 3257, + 3556, 2373, 3256, + 3556, 2376, 3255, + 3555, 2380, 3254, + 3554, 2386, 3253, + 3553, 2393, 3251, + 3551, 2402, 3249, + 3549, 2415, 3246, + 3546, 2431, 3241, + 3542, 2452, 3236, + 3537, 2478, 3228, + 3530, 2511, 3217, + 3520, 2552, 3202, + 3507, 2601, 3181, + 3488, 2659, 3152, + 3462, 2727, 3110, + 3425, 2805, 3047, + 3369, 2891, 2946, + 3283, 2986, 2761, + 3134, 3088, 2257, + 2800, 3196, 0, + 0, 3310, 0, + 0, 3427, 0, + 0, 3548, 0, + 0, 3672, 0, + 3690, 2496, 3390, + 3690, 2496, 3390, + 3690, 2496, 3390, + 3689, 2497, 3390, + 3689, 2497, 3390, + 3689, 2498, 3390, + 3689, 2499, 3389, + 3689, 2500, 3389, + 3689, 2502, 3389, + 3688, 2504, 3388, + 3688, 2508, 3387, + 3687, 2512, 3386, + 3686, 2517, 3385, + 3685, 2525, 3383, + 3683, 2534, 3381, + 3681, 2547, 3378, + 3678, 2563, 3373, + 3674, 2583, 3368, + 3669, 2610, 3360, + 3662, 2643, 3349, + 3652, 2683, 3334, + 3639, 2733, 3313, + 3620, 2791, 3284, + 3594, 2859, 3242, + 3557, 2937, 3179, + 3501, 3023, 3078, + 3415, 3118, 2893, + 3266, 3220, 2389, + 2932, 3328, 0, + 0, 3442, 0, + 0, 3559, 0, + 0, 3680, 0, + 3822, 2627, 3522, + 3822, 2628, 3522, + 3822, 2628, 3522, + 3822, 2628, 3522, + 3822, 2628, 3522, + 3821, 2629, 3522, + 3821, 2630, 3522, + 3821, 2631, 3521, + 3821, 2632, 3521, + 3821, 2634, 3521, + 3820, 2636, 3520, + 3820, 2639, 3519, + 3819, 2644, 3518, + 3818, 2649, 3517, + 3817, 2656, 3515, + 3815, 2666, 3513, + 3813, 2678, 3510, + 3810, 2695, 3505, + 3806, 2715, 3500, + 3801, 2742, 3492, + 3794, 2775, 3481, + 3784, 2815, 3466, + 3771, 2865, 3445, + 3752, 2923, 3416, + 3726, 2991, 3374, + 3689, 3069, 3311, + 3634, 3155, 3210, + 3547, 3250, 3025, + 3398, 3352, 2520, + 3065, 3460, 0, + 0, 3574, 0, + 0, 3691, 0, + 3954, 2759, 3654, + 3954, 2759, 3654, + 3954, 2759, 3654, + 3954, 2760, 3654, + 3954, 2760, 3654, + 3954, 2760, 3654, + 3954, 2761, 3654, + 3953, 2762, 3654, + 3953, 2763, 3653, + 3953, 2764, 3653, + 3953, 2766, 3653, + 3952, 2768, 3652, + 3952, 2771, 3651, + 3951, 2775, 3650, + 3950, 2781, 3649, + 3949, 2788, 3647, + 3948, 2798, 3645, + 3945, 2810, 3642, + 3943, 2826, 3637, + 3939, 2847, 3632, + 3933, 2874, 3624, + 3926, 2907, 3613, + 3916, 2947, 3598, + 3903, 2997, 3577, + 3884, 3055, 3548, + 3858, 3123, 3506, + 3821, 3201, 3443, + 3766, 3287, 3342, + 3679, 3382, 3157, + 3530, 3484, 2652, + 3197, 3593, 0, + 0, 3706, 0, + 4086, 2891, 3786, + 4086, 2891, 3786, + 4086, 2891, 3786, + 4086, 2891, 3786, + 4086, 2892, 3786, + 4086, 2892, 3786, + 4086, 2892, 3786, + 4086, 2893, 3786, + 4086, 2894, 3786, + 4085, 2895, 3785, + 4085, 2896, 3785, + 4085, 2898, 3785, + 4085, 2900, 3784, + 4084, 2903, 3783, + 4083, 2907, 3782, + 4082, 2913, 3781, + 4081, 2920, 3779, + 4080, 2930, 3777, + 4078, 2942, 3774, + 4075, 2958, 3770, + 4071, 2979, 3764, + 4065, 3006, 3756, + 4058, 3039, 3745, + 4048, 3079, 3730, + 4035, 3129, 3710, + 4017, 3187, 3680, + 3990, 3255, 3638, + 3953, 3333, 3575, + 3898, 3419, 3474, + 3811, 3514, 3289, + 3662, 3616, 2783, + 3329, 3725, 0, + 4095, 3023, 3918, + 4095, 3023, 3918, + 4095, 3023, 3918, + 4095, 3023, 3918, + 4095, 3023, 3918, + 4095, 3024, 3918, + 4095, 3024, 3918, + 4095, 3024, 3918, + 4095, 3025, 3918, + 4095, 3026, 3918, + 4095, 3027, 3918, + 4095, 3028, 3917, + 4095, 3030, 3917, + 4095, 3032, 3916, + 4095, 3035, 3916, + 4095, 3039, 3915, + 4095, 3045, 3913, + 4095, 3052, 3911, + 4095, 3062, 3909, + 4095, 3074, 3906, + 4095, 3090, 3902, + 4095, 3111, 3896, + 4095, 3138, 3888, + 4095, 3171, 3877, + 4095, 3211, 3862, + 4095, 3261, 3842, + 4095, 3319, 3812, + 4095, 3387, 3770, + 4085, 3465, 3707, + 4030, 3552, 3606, + 3944, 3646, 3421, + 3794, 3748, 2915, + 4095, 3155, 4050, + 4095, 3155, 4050, + 4095, 3155, 4050, + 4095, 3155, 4050, + 4095, 3155, 4050, + 4095, 3155, 4050, + 4095, 3156, 4050, + 4095, 3156, 4050, + 4095, 3156, 4050, + 4095, 3157, 4050, + 4095, 3158, 4050, + 4095, 3159, 4050, + 4095, 3160, 4049, + 4095, 3162, 4049, + 4095, 3164, 4048, + 4095, 3167, 4048, + 4095, 3171, 4047, + 4095, 3177, 4045, + 4095, 3184, 4044, + 4095, 3194, 4041, + 4095, 3206, 4038, + 4095, 3222, 4034, + 4095, 3243, 4028, + 4095, 3270, 4020, + 4095, 3303, 4009, + 4095, 3343, 3994, + 4095, 3393, 3974, + 4095, 3451, 3944, + 4095, 3519, 3902, + 4095, 3597, 3839, + 4095, 3684, 3738, + 4076, 3778, 3553, + 0, 108, 241, + 0, 151, 183, + 0, 203, 91, + 0, 264, 0, + 0, 334, 0, + 0, 414, 0, + 0, 503, 0, + 0, 600, 0, + 0, 704, 0, + 0, 813, 0, + 0, 928, 0, + 0, 1046, 0, + 0, 1168, 0, + 0, 1292, 0, + 0, 1418, 0, + 0, 1546, 0, + 0, 1674, 0, + 0, 1804, 0, + 0, 1934, 0, + 0, 2065, 0, + 0, 2196, 0, + 0, 2327, 0, + 0, 2459, 0, + 0, 2590, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 0, 123, 316, + 0, 165, 267, + 0, 215, 193, + 0, 274, 69, + 0, 343, 0, + 0, 422, 0, + 0, 509, 0, + 0, 605, 0, + 0, 708, 0, + 0, 816, 0, + 0, 930, 0, + 0, 1048, 0, + 0, 1170, 0, + 0, 1293, 0, + 0, 1419, 0, + 0, 1546, 0, + 0, 1675, 0, + 0, 1804, 0, + 0, 1934, 0, + 0, 2065, 0, + 0, 2196, 0, + 0, 2327, 0, + 0, 2459, 0, + 0, 2590, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 225, 143, 400, + 144, 182, 360, + 6, 231, 300, + 0, 288, 206, + 0, 355, 37, + 0, 432, 0, + 0, 518, 0, + 0, 612, 0, + 0, 713, 0, + 0, 821, 0, + 0, 934, 0, + 0, 1051, 0, + 0, 1171, 0, + 0, 1295, 0, + 0, 1420, 0, + 0, 1547, 0, + 0, 1676, 0, + 0, 1805, 0, + 0, 1935, 0, + 0, 2065, 0, + 0, 2196, 0, + 0, 2327, 0, + 0, 2459, 0, + 0, 2590, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 451, 167, 493, + 403, 205, 461, + 331, 251, 413, + 211, 306, 341, + 0, 371, 223, + 0, 445, 0, + 0, 529, 0, + 0, 621, 0, + 0, 720, 0, + 0, 826, 0, + 0, 938, 0, + 0, 1054, 0, + 0, 1174, 0, + 0, 1297, 0, + 0, 1422, 0, + 0, 1548, 0, + 0, 1676, 0, + 0, 1805, 0, + 0, 1935, 0, + 0, 2066, 0, + 0, 2196, 0, + 0, 2328, 0, + 0, 2459, 0, + 0, 2590, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 643, 198, 593, + 612, 234, 568, + 567, 277, 531, + 500, 329, 476, + 391, 391, 391, + 186, 462, 245, + 0, 543, 0, + 0, 632, 0, + 0, 730, 0, + 0, 834, 0, + 0, 944, 0, + 0, 1059, 0, + 0, 1178, 0, + 0, 1299, 0, + 0, 1424, 0, + 0, 1550, 0, + 0, 1678, 0, + 0, 1806, 0, + 0, 1936, 0, + 0, 2066, 0, + 0, 2197, 0, + 0, 2328, 0, + 0, 2459, 0, + 0, 2591, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 815, 237, 700, + 794, 269, 680, + 765, 310, 651, + 722, 358, 610, + 658, 417, 548, + 556, 484, 450, + 369, 561, 272, + 0, 647, 0, + 0, 742, 0, + 0, 844, 0, + 0, 952, 0, + 0, 1065, 0, + 0, 1182, 0, + 0, 1303, 0, + 0, 1426, 0, + 0, 1552, 0, + 0, 1679, 0, + 0, 1808, 0, + 0, 1937, 0, + 0, 2067, 0, + 0, 2197, 0, + 0, 2328, 0, + 0, 2459, 0, + 0, 2591, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 974, 283, 813, + 960, 313, 797, + 940, 350, 775, + 911, 395, 744, + 870, 448, 699, + 809, 512, 630, + 711, 585, 518, + 535, 667, 307, + 81, 758, 0, + 0, 856, 0, + 0, 962, 0, + 0, 1073, 0, + 0, 1188, 0, + 0, 1308, 0, + 0, 1430, 0, + 0, 1555, 0, + 0, 1681, 0, + 0, 1809, 0, + 0, 1938, 0, + 0, 2068, 0, + 0, 2198, 0, + 0, 2329, 0, + 0, 2460, 0, + 0, 2591, 0, + 0, 2723, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1126, 339, 929, + 1116, 365, 917, + 1102, 398, 900, + 1082, 439, 877, + 1054, 488, 844, + 1014, 546, 795, + 954, 614, 720, + 860, 692, 596, + 691, 778, 349, + 276, 873, 0, + 0, 975, 0, + 0, 1083, 0, + 0, 1196, 0, + 0, 1314, 0, + 0, 1435, 0, + 0, 1558, 0, + 0, 1684, 0, + 0, 1811, 0, + 0, 1939, 0, + 0, 2069, 0, + 0, 2199, 0, + 0, 2329, 0, + 0, 2460, 0, + 0, 2591, 0, + 0, 2723, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1272, 404, 1049, + 1265, 427, 1040, + 1255, 456, 1027, + 1241, 492, 1010, + 1221, 536, 985, + 1194, 589, 950, + 1155, 651, 898, + 1096, 723, 818, + 1004, 804, 683, + 841, 894, 400, + 450, 992, 0, + 0, 1096, 0, + 0, 1207, 0, + 0, 1322, 0, + 0, 1441, 0, + 0, 1563, 0, + 0, 1688, 0, + 0, 1814, 0, + 0, 1942, 0, + 0, 2070, 0, + 0, 2200, 0, + 0, 2330, 0, + 0, 2461, 0, + 0, 2592, 0, + 0, 2723, 0, + 0, 2855, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1415, 479, 1172, + 1409, 499, 1165, + 1402, 523, 1156, + 1392, 554, 1143, + 1378, 593, 1124, + 1359, 640, 1099, + 1332, 696, 1062, + 1293, 762, 1008, + 1235, 837, 923, + 1145, 921, 778, + 985, 1014, 461, + 611, 1114, 0, + 0, 1221, 0, + 0, 1333, 0, + 0, 1449, 0, + 0, 1569, 0, + 0, 1692, 0, + 0, 1817, 0, + 0, 1944, 0, + 0, 2072, 0, + 0, 2202, 0, + 0, 2331, 0, + 0, 2462, 0, + 0, 2593, 0, + 0, 2724, 0, + 0, 2855, 0, + 0, 2987, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1555, 563, 1298, + 1551, 579, 1292, + 1545, 600, 1285, + 1538, 627, 1275, + 1528, 660, 1262, + 1514, 701, 1243, + 1495, 750, 1216, + 1468, 809, 1178, + 1430, 877, 1122, + 1373, 955, 1034, + 1283, 1041, 880, + 1127, 1136, 531, + 763, 1238, 0, + 0, 1347, 0, + 0, 1460, 0, + 0, 1578, 0, + 0, 1699, 0, + 0, 1822, 0, + 0, 1948, 0, + 0, 2075, 0, + 0, 2204, 0, + 0, 2333, 0, + 0, 2463, 0, + 0, 2593, 0, + 0, 2724, 0, + 0, 2856, 0, + 0, 2987, 0, + 0, 3119, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1692, 656, 1424, + 1689, 669, 1420, + 1685, 686, 1415, + 1680, 708, 1408, + 1673, 736, 1397, + 1663, 771, 1384, + 1649, 813, 1364, + 1630, 865, 1337, + 1604, 926, 1298, + 1565, 996, 1240, + 1509, 1076, 1149, + 1420, 1164, 989, + 1265, 1261, 610, + 910, 1365, 0, + 0, 1474, 0, + 0, 1589, 0, + 0, 1707, 0, + 0, 1829, 0, + 0, 1953, 0, + 0, 2079, 0, + 0, 2206, 0, + 0, 2335, 0, + 0, 2464, 0, + 0, 2595, 0, + 0, 2725, 0, + 0, 2856, 0, + 0, 2988, 0, + 0, 3119, 0, + 0, 3251, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1828, 756, 1553, + 1826, 766, 1550, + 1823, 780, 1545, + 1819, 798, 1540, + 1814, 821, 1532, + 1807, 850, 1522, + 1797, 886, 1508, + 1783, 930, 1488, + 1764, 983, 1461, + 1738, 1046, 1421, + 1700, 1118, 1362, + 1644, 1199, 1268, + 1556, 1289, 1103, + 1402, 1387, 699, + 1053, 1492, 0, + 0, 1603, 0, + 0, 1718, 0, + 0, 1837, 0, + 0, 1959, 0, + 0, 2084, 0, + 0, 2210, 0, + 0, 2338, 0, + 0, 2467, 0, + 0, 2596, 0, + 0, 2726, 0, + 0, 2857, 0, + 0, 2988, 0, + 0, 3120, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3514, 0, + 0, 3646, 0, + 1964, 862, 1682, + 1962, 871, 1679, + 1960, 882, 1676, + 1957, 896, 1672, + 1953, 915, 1667, + 1948, 938, 1659, + 1940, 968, 1649, + 1930, 1006, 1634, + 1917, 1051, 1614, + 1898, 1105, 1586, + 1872, 1169, 1546, + 1834, 1243, 1486, + 1778, 1325, 1391, + 1690, 1416, 1220, + 1538, 1515, 795, + 1193, 1621, 0, + 0, 1732, 0, + 0, 1848, 0, + 0, 1968, 0, + 0, 2090, 0, + 0, 2215, 0, + 0, 2341, 0, + 0, 2469, 0, + 0, 2598, 0, + 0, 2728, 0, + 0, 2858, 0, + 0, 2989, 0, + 0, 3120, 0, + 0, 3252, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3646, 0, + 2098, 974, 1812, + 2097, 981, 1810, + 2095, 989, 1808, + 2093, 1001, 1804, + 2090, 1016, 1800, + 2086, 1035, 1795, + 2081, 1059, 1787, + 2074, 1090, 1776, + 2064, 1128, 1762, + 2050, 1174, 1742, + 2032, 1230, 1714, + 2005, 1294, 1673, + 1968, 1369, 1612, + 1912, 1452, 1515, + 1824, 1545, 1341, + 1673, 1644, 898, + 1331, 1751, 0, + 0, 1862, 0, + 0, 1979, 0, + 0, 2099, 0, + 0, 2221, 0, + 0, 2346, 0, + 0, 2473, 0, + 0, 2601, 0, + 0, 2730, 0, + 0, 2860, 0, + 0, 2990, 0, + 0, 3121, 0, + 0, 3252, 0, + 0, 3384, 0, + 0, 3515, 0, + 0, 3647, 0, + 2232, 1091, 1942, + 2231, 1096, 1941, + 2230, 1103, 1939, + 2228, 1111, 1937, + 2226, 1123, 1933, + 2223, 1138, 1929, + 2219, 1158, 1924, + 2214, 1183, 1916, + 2206, 1214, 1905, + 2197, 1253, 1891, + 2183, 1300, 1870, + 2165, 1356, 1842, + 2138, 1421, 1801, + 2101, 1497, 1739, + 2045, 1581, 1641, + 1958, 1674, 1465, + 1807, 1774, 1008, + 1467, 1881, 0, + 0, 1993, 0, + 0, 2110, 0, + 0, 2230, 0, + 0, 2353, 0, + 0, 2478, 0, + 0, 2605, 0, + 0, 2733, 0, + 0, 2862, 0, + 0, 2992, 0, + 0, 3122, 0, + 0, 3253, 0, + 0, 3384, 0, + 0, 3516, 0, + 0, 3647, 0, + 2365, 1211, 2073, + 2364, 1215, 2072, + 2364, 1220, 2071, + 2362, 1227, 2069, + 2361, 1236, 2066, + 2359, 1248, 2063, + 2356, 1263, 2059, + 2352, 1283, 2053, + 2346, 1308, 2046, + 2339, 1340, 2035, + 2329, 1379, 2020, + 2316, 1427, 2000, + 2297, 1483, 1971, + 2271, 1550, 1930, + 2234, 1625, 1868, + 2178, 1710, 1769, + 2091, 1804, 1591, + 1941, 1904, 1122, + 1603, 2011, 0, + 0, 2124, 0, + 0, 2241, 0, + 0, 2361, 0, + 0, 2484, 0, + 0, 2610, 0, + 0, 2737, 0, + 0, 2865, 0, + 0, 2994, 0, + 0, 3124, 0, + 0, 3254, 0, + 0, 3385, 0, + 0, 3516, 0, + 0, 3648, 0, + 2498, 1334, 2204, + 2498, 1337, 2203, + 2497, 1341, 2202, + 2496, 1346, 2201, + 2495, 1353, 2199, + 2493, 1362, 2197, + 2491, 1374, 2194, + 2488, 1390, 2189, + 2484, 1410, 2184, + 2479, 1435, 2176, + 2472, 1467, 2165, + 2462, 1507, 2150, + 2449, 1555, 2130, + 2430, 1612, 2101, + 2404, 1679, 2060, + 2366, 1755, 1997, + 2311, 1840, 1898, + 2224, 1934, 1718, + 2074, 2035, 1241, + 1737, 2142, 0, + 0, 2255, 0, + 0, 2372, 0, + 0, 2493, 0, + 0, 2616, 0, + 0, 2741, 0, + 0, 2868, 0, + 0, 2997, 0, + 0, 3126, 0, + 0, 3256, 0, + 0, 3386, 0, + 0, 3517, 0, + 0, 3648, 0, + 2631, 1459, 2335, + 2631, 1461, 2335, + 2630, 1464, 2334, + 2629, 1468, 2333, + 2628, 1473, 2332, + 2627, 1480, 2330, + 2626, 1490, 2328, + 2624, 1502, 2324, + 2621, 1518, 2320, + 2617, 1538, 2314, + 2611, 1564, 2307, + 2604, 1596, 2296, + 2594, 1636, 2281, + 2581, 1684, 2261, + 2562, 1742, 2232, + 2536, 1809, 2190, + 2499, 1885, 2128, + 2443, 1971, 2028, + 2357, 2065, 1846, + 2207, 2166, 1362, + 1871, 2274, 0, + 0, 2387, 0, + 0, 2504, 0, + 0, 2625, 0, + 0, 2748, 0, + 0, 2873, 0, + 0, 3000, 0, + 0, 3129, 0, + 0, 3258, 0, + 0, 3388, 0, + 0, 3518, 0, + 0, 3649, 0, + 2764, 1585, 2467, + 2763, 1587, 2466, + 2763, 1589, 2466, + 2762, 1593, 2465, + 2762, 1597, 2464, + 2761, 1602, 2463, + 2760, 1609, 2461, + 2758, 1618, 2459, + 2756, 1631, 2456, + 2753, 1647, 2451, + 2749, 1667, 2446, + 2744, 1693, 2438, + 2737, 1725, 2427, + 2727, 1765, 2412, + 2713, 1814, 2392, + 2695, 1872, 2363, + 2669, 1939, 2321, + 2631, 2016, 2258, + 2576, 2102, 2158, + 2489, 2196, 1976, + 2340, 2297, 1486, + 2004, 2405, 0, + 0, 2518, 0, + 0, 2636, 0, + 0, 2756, 0, + 0, 2880, 0, + 0, 3005, 0, + 0, 3132, 0, + 0, 3261, 0, + 0, 3390, 0, + 0, 3520, 0, + 0, 3650, 0, + 2896, 1713, 2599, + 2896, 1715, 2598, + 2896, 1717, 2598, + 2895, 1719, 2597, + 2895, 1722, 2597, + 2894, 1726, 2596, + 2893, 1731, 2594, + 2892, 1739, 2593, + 2890, 1748, 2590, + 2888, 1760, 2587, + 2885, 1776, 2583, + 2881, 1797, 2577, + 2876, 1823, 2569, + 2869, 1855, 2558, + 2859, 1896, 2544, + 2846, 1944, 2523, + 2827, 2002, 2494, + 2801, 2070, 2452, + 2764, 2147, 2389, + 2708, 2233, 2289, + 2622, 2327, 2106, + 2472, 2429, 1612, + 2137, 2537, 0, + 0, 2650, 0, + 0, 2767, 0, + 0, 2888, 0, + 0, 3012, 0, + 0, 3137, 0, + 0, 3264, 0, + 0, 3393, 0, + 0, 3522, 0, + 0, 3652, 0, + 3028, 1843, 2730, + 3028, 1844, 2730, + 3028, 1845, 2730, + 3028, 1847, 2729, + 3027, 1849, 2729, + 3027, 1852, 2728, + 3026, 1856, 2727, + 3025, 1862, 2726, + 3024, 1869, 2724, + 3023, 1878, 2722, + 3020, 1891, 2719, + 3017, 1907, 2714, + 3014, 1927, 2708, + 3008, 1953, 2701, + 3001, 1986, 2690, + 2991, 2026, 2675, + 2978, 2075, 2654, + 2959, 2133, 2625, + 2933, 2201, 2583, + 2896, 2278, 2520, + 2840, 2364, 2420, + 2754, 2459, 2236, + 2605, 2561, 1740, + 2270, 2669, 0, + 0, 2782, 0, + 0, 2899, 0, + 0, 3020, 0, + 0, 3144, 0, + 0, 3269, 0, + 0, 3396, 0, + 0, 3525, 0, + 0, 3654, 0, + 3161, 1972, 2862, + 3161, 1973, 2862, + 3160, 1974, 2862, + 3160, 1975, 2862, + 3160, 1977, 2861, + 3160, 1980, 2861, + 3159, 1983, 2860, + 3158, 1987, 2859, + 3158, 1992, 2858, + 3156, 1999, 2856, + 3155, 2009, 2853, + 3153, 2021, 2850, + 3150, 2037, 2846, + 3146, 2058, 2840, + 3140, 2084, 2832, + 3133, 2117, 2821, + 3124, 2157, 2807, + 3110, 2206, 2786, + 3092, 2265, 2757, + 3065, 2333, 2715, + 3028, 2410, 2652, + 2973, 2496, 2551, + 2886, 2591, 2367, + 2737, 2692, 1868, + 2403, 2801, 0, + 0, 2914, 0, + 0, 3031, 0, + 0, 3152, 0, + 0, 3276, 0, + 0, 3401, 0, + 0, 3528, 0, + 0, 3657, 0, + 3293, 2103, 2994, + 3293, 2103, 2994, + 3293, 2104, 2994, + 3293, 2105, 2994, + 3292, 2106, 2993, + 3292, 2108, 2993, + 3292, 2110, 2992, + 3291, 2114, 2992, + 3291, 2118, 2991, + 3290, 2123, 2989, + 3289, 2130, 2988, + 3287, 2140, 2985, + 3285, 2152, 2982, + 3282, 2168, 2978, + 3278, 2189, 2972, + 3273, 2215, 2964, + 3265, 2248, 2953, + 3256, 2289, 2938, + 3242, 2338, 2918, + 3224, 2396, 2889, + 3198, 2464, 2847, + 3160, 2541, 2784, + 3105, 2628, 2682, + 3019, 2722, 2498, + 2869, 2824, 1998, + 2535, 2932, 0, + 0, 3046, 0, + 0, 3163, 0, + 0, 3284, 0, + 0, 3408, 0, + 0, 3533, 0, + 0, 3660, 0, + 3425, 2234, 3126, + 3425, 2234, 3126, + 3425, 2235, 3126, + 3425, 2235, 3126, + 3425, 2236, 3126, + 3425, 2238, 3125, + 3424, 2239, 3125, + 3424, 2242, 3124, + 3423, 2245, 3124, + 3423, 2249, 3123, + 3422, 2255, 3121, + 3421, 2262, 3119, + 3419, 2271, 3117, + 3417, 2284, 3114, + 3414, 2300, 3110, + 3410, 2320, 3104, + 3405, 2347, 3096, + 3398, 2380, 3085, + 3388, 2420, 3070, + 3374, 2469, 3050, + 3356, 2528, 3021, + 3330, 2596, 2978, + 3292, 2673, 2915, + 3237, 2760, 2814, + 3151, 2854, 2630, + 3001, 2956, 2128, + 2668, 3064, 0, + 0, 3178, 0, + 0, 3295, 0, + 0, 3416, 0, + 0, 3540, 0, + 0, 3665, 0, + 3557, 2365, 3258, + 3557, 2365, 3258, + 3557, 2365, 3258, + 3557, 2366, 3258, + 3557, 2367, 3258, + 3557, 2368, 3257, + 3557, 2369, 3257, + 3556, 2371, 3257, + 3556, 2373, 3256, + 3556, 2376, 3255, + 3555, 2380, 3254, + 3554, 2386, 3253, + 3553, 2393, 3251, + 3551, 2403, 3249, + 3549, 2415, 3246, + 3546, 2431, 3242, + 3542, 2452, 3236, + 3537, 2478, 3228, + 3530, 2511, 3217, + 3520, 2552, 3202, + 3507, 2601, 3182, + 3488, 2660, 3152, + 3462, 2728, 3110, + 3425, 2805, 3047, + 3369, 2892, 2946, + 3283, 2986, 2761, + 3134, 3088, 2258, + 2800, 3196, 0, + 0, 3310, 0, + 0, 3427, 0, + 0, 3548, 0, + 0, 3672, 0, + 3690, 2496, 3390, + 3690, 2496, 3390, + 3689, 2497, 3390, + 3689, 2497, 3390, + 3689, 2498, 3390, + 3689, 2498, 3390, + 3689, 2499, 3389, + 3689, 2501, 3389, + 3689, 2502, 3389, + 3688, 2505, 3388, + 3688, 2508, 3387, + 3687, 2512, 3386, + 3686, 2518, 3385, + 3685, 2525, 3383, + 3683, 2534, 3381, + 3681, 2547, 3378, + 3678, 2563, 3374, + 3674, 2584, 3368, + 3669, 2610, 3360, + 3662, 2643, 3349, + 3652, 2684, 3334, + 3639, 2733, 3314, + 3620, 2791, 3284, + 3594, 2859, 3242, + 3557, 2937, 3179, + 3501, 3023, 3078, + 3415, 3118, 2893, + 3266, 3220, 2389, + 2932, 3328, 0, + 0, 3442, 0, + 0, 3559, 0, + 0, 3680, 0, + 3822, 2628, 3522, + 3822, 2628, 3522, + 3822, 2628, 3522, + 3822, 2628, 3522, + 3822, 2629, 3522, + 3821, 2629, 3522, + 3821, 2630, 3522, + 3821, 2631, 3521, + 3821, 2632, 3521, + 3821, 2634, 3521, + 3820, 2637, 3520, + 3820, 2640, 3519, + 3819, 2644, 3518, + 3818, 2649, 3517, + 3817, 2657, 3515, + 3815, 2666, 3513, + 3813, 2679, 3510, + 3810, 2695, 3506, + 3806, 2716, 3500, + 3801, 2742, 3492, + 3794, 2775, 3481, + 3784, 2816, 3466, + 3771, 2865, 3446, + 3752, 2923, 3416, + 3726, 2991, 3374, + 3689, 3069, 3311, + 3634, 3155, 3210, + 3547, 3250, 3025, + 3398, 3352, 2521, + 3064, 3460, 0, + 0, 3574, 0, + 0, 3691, 0, + 3954, 2759, 3654, + 3954, 2759, 3654, + 3954, 2760, 3654, + 3954, 2760, 3654, + 3954, 2760, 3654, + 3954, 2761, 3654, + 3954, 2761, 3654, + 3953, 2762, 3654, + 3953, 2763, 3653, + 3953, 2764, 3653, + 3953, 2766, 3653, + 3952, 2768, 3652, + 3952, 2772, 3651, + 3951, 2776, 3650, + 3950, 2781, 3649, + 3949, 2788, 3647, + 3948, 2798, 3645, + 3945, 2811, 3642, + 3943, 2827, 3638, + 3939, 2847, 3632, + 3933, 2874, 3624, + 3926, 2907, 3613, + 3916, 2947, 3598, + 3903, 2997, 3578, + 3884, 3055, 3548, + 3858, 3123, 3506, + 3821, 3201, 3443, + 3766, 3287, 3342, + 3679, 3382, 3157, + 3530, 3484, 2652, + 3197, 3593, 0, + 0, 3706, 0, + 4086, 2891, 3786, + 4086, 2891, 3786, + 4086, 2891, 3786, + 4086, 2891, 3786, + 4086, 2892, 3786, + 4086, 2892, 3786, + 4086, 2892, 3786, + 4086, 2893, 3786, + 4086, 2894, 3786, + 4085, 2895, 3786, + 4085, 2896, 3785, + 4085, 2898, 3785, + 4085, 2900, 3784, + 4084, 2903, 3784, + 4083, 2908, 3783, + 4082, 2913, 3781, + 4081, 2920, 3779, + 4080, 2930, 3777, + 4078, 2942, 3774, + 4075, 2959, 3770, + 4071, 2979, 3764, + 4065, 3006, 3756, + 4058, 3039, 3745, + 4048, 3079, 3730, + 4035, 3129, 3710, + 4017, 3187, 3680, + 3990, 3255, 3638, + 3953, 3333, 3575, + 3898, 3420, 3474, + 3811, 3514, 3289, + 3662, 3616, 2784, + 3329, 3725, 0, + 4095, 3023, 3918, + 4095, 3023, 3918, + 4095, 3023, 3918, + 4095, 3023, 3918, + 4095, 3023, 3918, + 4095, 3024, 3918, + 4095, 3024, 3918, + 4095, 3024, 3918, + 4095, 3025, 3918, + 4095, 3026, 3918, + 4095, 3027, 3918, + 4095, 3028, 3917, + 4095, 3030, 3917, + 4095, 3032, 3916, + 4095, 3035, 3916, + 4095, 3040, 3915, + 4095, 3045, 3913, + 4095, 3052, 3912, + 4095, 3062, 3909, + 4095, 3074, 3906, + 4095, 3091, 3902, + 4095, 3111, 3896, + 4095, 3138, 3888, + 4095, 3171, 3877, + 4095, 3211, 3862, + 4095, 3261, 3842, + 4095, 3319, 3812, + 4095, 3387, 3770, + 4085, 3465, 3707, + 4030, 3552, 3606, + 3944, 3646, 3421, + 3794, 3748, 2916, + 4095, 3155, 4051, + 4095, 3155, 4050, + 4095, 3155, 4050, + 4095, 3155, 4050, + 4095, 3155, 4050, + 4095, 3155, 4050, + 4095, 3156, 4050, + 4095, 3156, 4050, + 4095, 3156, 4050, + 4095, 3157, 4050, + 4095, 3158, 4050, + 4095, 3159, 4050, + 4095, 3160, 4049, + 4095, 3162, 4049, + 4095, 3164, 4048, + 4095, 3167, 4048, + 4095, 3172, 4047, + 4095, 3177, 4045, + 4095, 3184, 4044, + 4095, 3194, 4041, + 4095, 3206, 4038, + 4095, 3223, 4034, + 4095, 3243, 4028, + 4095, 3270, 4020, + 4095, 3303, 4009, + 4095, 3343, 3994, + 4095, 3393, 3974, + 4095, 3451, 3945, + 4095, 3519, 3902, + 4095, 3597, 3839, + 4095, 3684, 3738, + 4076, 3778, 3553, + 0, 193, 352, + 0, 229, 307, + 0, 273, 239, + 0, 326, 129, + 0, 388, 0, + 0, 459, 0, + 0, 540, 0, + 0, 630, 0, + 0, 728, 0, + 0, 833, 0, + 0, 943, 0, + 0, 1058, 0, + 0, 1177, 0, + 0, 1299, 0, + 0, 1423, 0, + 0, 1550, 0, + 0, 1677, 0, + 0, 1806, 0, + 0, 1936, 0, + 0, 2066, 0, + 0, 2197, 0, + 0, 2328, 0, + 0, 2459, 0, + 0, 2591, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 0, 205, 412, + 0, 240, 373, + 0, 283, 315, + 0, 335, 223, + 0, 396, 62, + 0, 466, 0, + 0, 546, 0, + 0, 635, 0, + 0, 732, 0, + 0, 836, 0, + 0, 945, 0, + 0, 1060, 0, + 0, 1178, 0, + 0, 1300, 0, + 0, 1424, 0, + 0, 1550, 0, + 0, 1678, 0, + 0, 1807, 0, + 0, 1936, 0, + 0, 2066, 0, + 0, 2197, 0, + 0, 2328, 0, + 0, 2459, 0, + 0, 2591, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 154, 222, 481, + 58, 255, 448, + 0, 297, 399, + 0, 347, 325, + 0, 407, 201, + 0, 476, 0, + 0, 554, 0, + 0, 641, 0, + 0, 737, 0, + 0, 840, 0, + 0, 949, 0, + 0, 1062, 0, + 0, 1180, 0, + 0, 1302, 0, + 0, 1425, 0, + 0, 1551, 0, + 0, 1679, 0, + 0, 1807, 0, + 0, 1936, 0, + 0, 2066, 0, + 0, 2197, 0, + 0, 2328, 0, + 0, 2459, 0, + 0, 2591, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 409, 242, 560, + 357, 275, 532, + 276, 315, 492, + 138, 363, 433, + 0, 420, 338, + 0, 488, 170, + 0, 564, 0, + 0, 650, 0, + 0, 744, 0, + 0, 845, 0, + 0, 953, 0, + 0, 1066, 0, + 0, 1183, 0, + 0, 1304, 0, + 0, 1427, 0, + 0, 1552, 0, + 0, 1679, 0, + 0, 1808, 0, + 0, 1937, 0, + 0, 2067, 0, + 0, 2197, 0, + 0, 2328, 0, + 0, 2459, 0, + 0, 2591, 0, + 0, 2722, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 616, 269, 648, + 583, 299, 625, + 535, 337, 593, + 463, 383, 546, + 343, 438, 474, + 109, 503, 355, + 0, 577, 124, + 0, 661, 0, + 0, 753, 0, + 0, 852, 0, + 0, 958, 0, + 0, 1070, 0, + 0, 1186, 0, + 0, 1306, 0, + 0, 1429, 0, + 0, 1554, 0, + 0, 1681, 0, + 0, 1809, 0, + 0, 1938, 0, + 0, 2067, 0, + 0, 2198, 0, + 0, 2328, 0, + 0, 2460, 0, + 0, 2591, 0, + 0, 2723, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 796, 302, 744, + 775, 330, 726, + 744, 366, 700, + 700, 409, 663, + 632, 461, 608, + 523, 523, 523, + 318, 594, 377, + 0, 675, 54, + 0, 764, 0, + 0, 862, 0, + 0, 966, 0, + 0, 1076, 0, + 0, 1191, 0, + 0, 1310, 0, + 0, 1432, 0, + 0, 1556, 0, + 0, 1682, 0, + 0, 1810, 0, + 0, 1938, 0, + 0, 2068, 0, + 0, 2198, 0, + 0, 2329, 0, + 0, 2460, 0, + 0, 2591, 0, + 0, 2723, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 962, 343, 847, + 947, 369, 832, + 926, 401, 812, + 897, 442, 784, + 854, 490, 742, + 790, 549, 680, + 688, 616, 582, + 501, 693, 404, + 0, 780, 0, + 0, 874, 0, + 0, 976, 0, + 0, 1084, 0, + 0, 1197, 0, + 0, 1314, 0, + 0, 1435, 0, + 0, 1559, 0, + 0, 1684, 0, + 0, 1811, 0, + 0, 1940, 0, + 0, 2069, 0, + 0, 2199, 0, + 0, 2329, 0, + 0, 2460, 0, + 0, 2591, 0, + 0, 2723, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1117, 392, 956, + 1107, 415, 945, + 1092, 445, 929, + 1072, 482, 907, + 1043, 527, 876, + 1002, 581, 831, + 941, 644, 762, + 843, 717, 650, + 667, 799, 439, + 213, 890, 0, + 0, 988, 0, + 0, 1094, 0, + 0, 1205, 0, + 0, 1320, 0, + 0, 1440, 0, + 0, 1562, 0, + 0, 1687, 0, + 0, 1813, 0, + 0, 1941, 0, + 0, 2070, 0, + 0, 2200, 0, + 0, 2330, 0, + 0, 2461, 0, + 0, 2592, 0, + 0, 2723, 0, + 0, 2855, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1266, 450, 1070, + 1258, 471, 1061, + 1248, 497, 1049, + 1234, 530, 1032, + 1214, 571, 1009, + 1186, 620, 976, + 1146, 678, 927, + 1086, 746, 852, + 992, 824, 728, + 824, 910, 481, + 408, 1005, 0, + 0, 1107, 0, + 0, 1215, 0, + 0, 1328, 0, + 0, 1446, 0, + 0, 1567, 0, + 0, 1690, 0, + 0, 1816, 0, + 0, 1943, 0, + 0, 2072, 0, + 0, 2201, 0, + 0, 2331, 0, + 0, 2461, 0, + 0, 2592, 0, + 0, 2724, 0, + 0, 2855, 0, + 0, 2987, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1410, 519, 1188, + 1405, 536, 1182, + 1397, 559, 1172, + 1387, 588, 1160, + 1373, 624, 1142, + 1353, 668, 1117, + 1326, 721, 1082, + 1287, 783, 1030, + 1228, 855, 950, + 1136, 936, 815, + 973, 1026, 532, + 582, 1124, 0, + 0, 1229, 0, + 0, 1339, 0, + 0, 1454, 0, + 0, 1573, 0, + 0, 1695, 0, + 0, 1820, 0, + 0, 1946, 0, + 0, 2074, 0, + 0, 2202, 0, + 0, 2332, 0, + 0, 2462, 0, + 0, 2593, 0, + 0, 2724, 0, + 0, 2855, 0, + 0, 2987, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1551, 596, 1310, + 1547, 611, 1305, + 1542, 631, 1297, + 1534, 655, 1288, + 1524, 687, 1275, + 1510, 725, 1256, + 1491, 772, 1231, + 1464, 828, 1194, + 1425, 894, 1140, + 1367, 969, 1055, + 1277, 1053, 910, + 1117, 1146, 593, + 743, 1246, 0, + 0, 1353, 0, + 0, 1465, 0, + 0, 1581, 0, + 0, 1702, 0, + 0, 1824, 0, + 0, 1950, 0, + 0, 2076, 0, + 0, 2205, 0, + 0, 2334, 0, + 0, 2463, 0, + 0, 2594, 0, + 0, 2725, 0, + 0, 2856, 0, + 0, 2987, 0, + 0, 3119, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1690, 683, 1434, + 1687, 695, 1430, + 1683, 711, 1424, + 1677, 732, 1417, + 1670, 759, 1407, + 1660, 792, 1394, + 1646, 833, 1375, + 1627, 882, 1348, + 1600, 941, 1310, + 1562, 1009, 1254, + 1505, 1087, 1166, + 1415, 1173, 1013, + 1259, 1268, 663, + 895, 1370, 0, + 0, 1479, 0, + 0, 1592, 0, + 0, 1710, 0, + 0, 1831, 0, + 0, 1954, 0, + 0, 2080, 0, + 0, 2207, 0, + 0, 2336, 0, + 0, 2465, 0, + 0, 2595, 0, + 0, 2726, 0, + 0, 2856, 0, + 0, 2988, 0, + 0, 3119, 0, + 0, 3251, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1826, 777, 1560, + 1824, 788, 1557, + 1821, 801, 1552, + 1817, 818, 1547, + 1812, 840, 1540, + 1805, 868, 1530, + 1795, 903, 1516, + 1781, 945, 1496, + 1762, 997, 1469, + 1736, 1058, 1430, + 1697, 1128, 1372, + 1641, 1208, 1281, + 1552, 1296, 1121, + 1397, 1393, 742, + 1042, 1497, 0, + 0, 1606, 0, + 0, 1721, 0, + 0, 1839, 0, + 0, 1961, 0, + 0, 2085, 0, + 0, 2211, 0, + 0, 2338, 0, + 0, 2467, 0, + 0, 2597, 0, + 0, 2727, 0, + 0, 2857, 0, + 0, 2988, 0, + 0, 3120, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3514, 0, + 0, 3646, 0, + 1962, 880, 1687, + 1961, 888, 1685, + 1958, 898, 1682, + 1955, 912, 1678, + 1951, 930, 1672, + 1946, 953, 1664, + 1939, 982, 1654, + 1929, 1018, 1640, + 1915, 1062, 1620, + 1897, 1116, 1593, + 1870, 1178, 1553, + 1832, 1250, 1494, + 1776, 1331, 1400, + 1688, 1422, 1235, + 1534, 1520, 831, + 1185, 1624, 0, + 0, 1735, 0, + 0, 1850, 0, + 0, 1969, 0, + 0, 2091, 0, + 0, 2216, 0, + 0, 2342, 0, + 0, 2470, 0, + 0, 2599, 0, + 0, 2728, 0, + 0, 2859, 0, + 0, 2989, 0, + 0, 3120, 0, + 0, 3252, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3647, 0, + 2097, 988, 1815, + 2096, 994, 1814, + 2094, 1003, 1811, + 2092, 1014, 1808, + 2089, 1028, 1804, + 2085, 1047, 1799, + 2080, 1071, 1791, + 2072, 1100, 1781, + 2063, 1138, 1766, + 2049, 1183, 1746, + 2030, 1237, 1719, + 2004, 1301, 1678, + 1966, 1375, 1618, + 1910, 1457, 1523, + 1822, 1548, 1352, + 1670, 1647, 927, + 1325, 1753, 0, + 0, 1864, 0, + 0, 1980, 0, + 0, 2100, 0, + 0, 2222, 0, + 0, 2347, 0, + 0, 2474, 0, + 0, 2601, 0, + 0, 2730, 0, + 0, 2860, 0, + 0, 2990, 0, + 0, 3121, 0, + 0, 3252, 0, + 0, 3384, 0, + 0, 3515, 0, + 0, 3647, 0, + 2231, 1101, 1945, + 2230, 1106, 1944, + 2229, 1113, 1942, + 2227, 1122, 1940, + 2225, 1133, 1936, + 2222, 1148, 1932, + 2218, 1167, 1927, + 2213, 1191, 1919, + 2206, 1222, 1908, + 2196, 1260, 1894, + 2182, 1306, 1874, + 2164, 1362, 1846, + 2137, 1427, 1805, + 2100, 1501, 1744, + 2044, 1585, 1647, + 1956, 1677, 1473, + 1805, 1776, 1031, + 1463, 1883, 0, + 0, 1994, 0, + 0, 2111, 0, + 0, 2231, 0, + 0, 2353, 0, + 0, 2478, 0, + 0, 2605, 0, + 0, 2733, 0, + 0, 2862, 0, + 0, 2992, 0, + 0, 3122, 0, + 0, 3253, 0, + 0, 3384, 0, + 0, 3516, 0, + 0, 3647, 0, + 2364, 1219, 2075, + 2364, 1223, 2074, + 2363, 1228, 2073, + 2362, 1235, 2071, + 2360, 1244, 2069, + 2358, 1255, 2066, + 2355, 1270, 2061, + 2351, 1290, 2056, + 2346, 1315, 2048, + 2339, 1346, 2037, + 2329, 1385, 2023, + 2315, 1432, 2003, + 2297, 1488, 1974, + 2270, 1553, 1933, + 2233, 1629, 1871, + 2177, 1713, 1773, + 2090, 1806, 1597, + 1939, 1906, 1140, + 1599, 2013, 0, + 0, 2125, 0, + 0, 2242, 0, + 0, 2362, 0, + 0, 2485, 0, + 0, 2610, 0, + 0, 2737, 0, + 0, 2865, 0, + 0, 2994, 0, + 0, 3124, 0, + 0, 3254, 0, + 0, 3385, 0, + 0, 3516, 0, + 0, 3648, 0, + 2498, 1340, 2206, + 2497, 1343, 2205, + 2497, 1347, 2204, + 2496, 1352, 2203, + 2494, 1359, 2201, + 2493, 1368, 2199, + 2491, 1380, 2195, + 2488, 1395, 2191, + 2484, 1415, 2185, + 2478, 1440, 2178, + 2471, 1472, 2167, + 2461, 1511, 2152, + 2448, 1559, 2132, + 2429, 1615, 2103, + 2403, 1682, 2062, + 2366, 1757, 2000, + 2310, 1842, 1901, + 2223, 1936, 1723, + 2073, 2036, 1254, + 1735, 2144, 0, + 0, 2256, 0, + 0, 2373, 0, + 0, 2493, 0, + 0, 2616, 0, + 0, 2742, 0, + 0, 2869, 0, + 0, 2997, 0, + 0, 3126, 0, + 0, 3256, 0, + 0, 3386, 0, + 0, 3517, 0, + 0, 3648, 0, + 2631, 1463, 2337, + 2630, 1466, 2336, + 2630, 1469, 2335, + 2629, 1473, 2334, + 2628, 1478, 2333, + 2627, 1485, 2331, + 2625, 1494, 2329, + 2623, 1506, 2326, + 2620, 1522, 2322, + 2616, 1542, 2316, + 2611, 1567, 2308, + 2604, 1599, 2297, + 2594, 1639, 2283, + 2581, 1687, 2262, + 2562, 1744, 2233, + 2536, 1811, 2192, + 2498, 1887, 2130, + 2443, 1972, 2030, + 2356, 2066, 1850, + 2206, 2167, 1373, + 1869, 2275, 0, + 0, 2387, 0, + 0, 2504, 0, + 0, 2625, 0, + 0, 2748, 0, + 0, 2874, 0, + 0, 3001, 0, + 0, 3129, 0, + 0, 3258, 0, + 0, 3388, 0, + 0, 3518, 0, + 0, 3649, 0, + 2763, 1589, 2468, + 2763, 1591, 2467, + 2763, 1593, 2467, + 2762, 1596, 2466, + 2761, 1600, 2465, + 2761, 1605, 2464, + 2759, 1613, 2462, + 2758, 1622, 2460, + 2756, 1634, 2457, + 2753, 1650, 2452, + 2749, 1670, 2447, + 2743, 1696, 2439, + 2736, 1728, 2428, + 2727, 1768, 2413, + 2713, 1816, 2393, + 2694, 1874, 2364, + 2668, 1941, 2322, + 2631, 2017, 2260, + 2575, 2103, 2160, + 2489, 2197, 1978, + 2339, 2298, 1494, + 2003, 2406, 0, + 0, 2519, 0, + 0, 2636, 0, + 0, 2757, 0, + 0, 2880, 0, + 0, 3005, 0, + 0, 3132, 0, + 0, 3261, 0, + 0, 3390, 0, + 0, 3520, 0, + 0, 3650, 0, + 2896, 1716, 2599, + 2896, 1717, 2599, + 2895, 1719, 2599, + 2895, 1722, 2598, + 2894, 1725, 2597, + 2894, 1729, 2596, + 2893, 1734, 2595, + 2892, 1741, 2593, + 2890, 1751, 2591, + 2888, 1763, 2588, + 2885, 1779, 2583, + 2881, 1799, 2578, + 2876, 1825, 2570, + 2869, 1857, 2559, + 2859, 1897, 2544, + 2845, 1946, 2524, + 2827, 2004, 2495, + 2801, 2071, 2453, + 2763, 2148, 2390, + 2708, 2234, 2290, + 2621, 2328, 2108, + 2472, 2430, 1618, + 2136, 2537, 0, + 0, 2650, 0, + 0, 2768, 0, + 0, 2888, 0, + 0, 3012, 0, + 0, 3137, 0, + 0, 3264, 0, + 0, 3393, 0, + 0, 3522, 0, + 0, 3652, 0, + 3028, 1845, 2731, + 3028, 1846, 2731, + 3028, 1847, 2730, + 3028, 1849, 2730, + 3027, 1851, 2729, + 3027, 1854, 2729, + 3026, 1858, 2728, + 3025, 1864, 2726, + 3024, 1871, 2725, + 3022, 1880, 2722, + 3020, 1892, 2719, + 3017, 1908, 2715, + 3013, 1929, 2709, + 3008, 1955, 2701, + 3001, 1987, 2690, + 2991, 2028, 2676, + 2978, 2076, 2655, + 2959, 2134, 2626, + 2933, 2202, 2584, + 2896, 2279, 2521, + 2840, 2365, 2421, + 2754, 2459, 2238, + 2604, 2561, 1744, + 2269, 2669, 0, + 0, 2782, 0, + 0, 2900, 0, + 0, 3020, 0, + 0, 3144, 0, + 0, 3269, 0, + 0, 3396, 0, + 0, 3525, 0, + 0, 3654, 0, + 3161, 1974, 2863, + 3161, 1975, 2862, + 3160, 1976, 2862, + 3160, 1977, 2862, + 3160, 1979, 2862, + 3160, 1981, 2861, + 3159, 1984, 2860, + 3158, 1988, 2859, + 3157, 1994, 2858, + 3156, 2001, 2856, + 3155, 2010, 2854, + 3152, 2023, 2851, + 3150, 2039, 2846, + 3146, 2059, 2841, + 3140, 2085, 2833, + 3133, 2118, 2822, + 3123, 2158, 2807, + 3110, 2207, 2787, + 3091, 2266, 2758, + 3065, 2333, 2716, + 3028, 2410, 2653, + 2973, 2497, 2552, + 2886, 2591, 2368, + 2737, 2693, 1872, + 2402, 2801, 0, + 0, 2914, 0, + 0, 3031, 0, + 0, 3152, 0, + 0, 3276, 0, + 0, 3401, 0, + 0, 3528, 0, + 0, 3657, 0, + 3293, 2104, 2994, + 3293, 2104, 2994, + 3293, 2105, 2994, + 3293, 2106, 2994, + 3292, 2107, 2994, + 3292, 2109, 2993, + 3292, 2112, 2993, + 3291, 2115, 2992, + 3291, 2119, 2991, + 3290, 2124, 2990, + 3288, 2132, 2988, + 3287, 2141, 2986, + 3285, 2153, 2982, + 3282, 2169, 2978, + 3278, 2190, 2972, + 3273, 2216, 2964, + 3265, 2249, 2954, + 3256, 2290, 2939, + 3242, 2339, 2918, + 3224, 2397, 2889, + 3198, 2465, 2847, + 3160, 2542, 2784, + 3105, 2628, 2683, + 3018, 2723, 2499, + 2869, 2825, 2000, + 2535, 2933, 0, + 0, 3046, 0, + 0, 3163, 0, + 0, 3284, 0, + 0, 3408, 0, + 0, 3533, 0, + 0, 3661, 0, + 3425, 2234, 3126, + 3425, 2235, 3126, + 3425, 2235, 3126, + 3425, 2236, 3126, + 3425, 2237, 3126, + 3425, 2238, 3125, + 3424, 2240, 3125, + 3424, 2243, 3124, + 3423, 2246, 3124, + 3423, 2250, 3123, + 3422, 2255, 3121, + 3421, 2263, 3120, + 3419, 2272, 3117, + 3417, 2284, 3114, + 3414, 2301, 3110, + 3410, 2321, 3104, + 3405, 2347, 3096, + 3398, 2380, 3085, + 3388, 2421, 3071, + 3374, 2470, 3050, + 3356, 2528, 3021, + 3330, 2596, 2979, + 3292, 2674, 2916, + 3237, 2760, 2815, + 3151, 2855, 2631, + 3001, 2956, 2130, + 2667, 3065, 0, + 0, 3178, 0, + 0, 3295, 0, + 0, 3416, 0, + 0, 3540, 0, + 0, 3665, 0, + 3557, 2365, 3258, + 3557, 2366, 3258, + 3557, 2366, 3258, + 3557, 2367, 3258, + 3557, 2367, 3258, + 3557, 2368, 3258, + 3557, 2370, 3257, + 3556, 2371, 3257, + 3556, 2374, 3256, + 3556, 2377, 3256, + 3555, 2381, 3255, + 3554, 2387, 3253, + 3553, 2394, 3252, + 3551, 2403, 3249, + 3549, 2416, 3246, + 3546, 2432, 3242, + 3542, 2453, 3236, + 3537, 2479, 3228, + 3530, 2512, 3217, + 3520, 2552, 3202, + 3507, 2602, 3182, + 3488, 2660, 3153, + 3462, 2728, 3111, + 3425, 2805, 3047, + 3369, 2892, 2946, + 3283, 2986, 2762, + 3134, 3088, 2260, + 2800, 3197, 0, + 0, 3310, 0, + 0, 3427, 0, + 0, 3548, 0, + 0, 3672, 0, + 3690, 2497, 3390, + 3690, 2497, 3390, + 3689, 2497, 3390, + 3689, 2498, 3390, + 3689, 2498, 3390, + 3689, 2499, 3390, + 3689, 2500, 3390, + 3689, 2501, 3389, + 3689, 2503, 3389, + 3688, 2505, 3388, + 3688, 2508, 3388, + 3687, 2513, 3387, + 3686, 2518, 3385, + 3685, 2525, 3384, + 3683, 2535, 3381, + 3681, 2547, 3378, + 3678, 2563, 3374, + 3674, 2584, 3368, + 3669, 2610, 3360, + 3662, 2643, 3349, + 3652, 2684, 3334, + 3639, 2733, 3314, + 3620, 2792, 3285, + 3594, 2860, 3242, + 3557, 2937, 3179, + 3501, 3024, 3078, + 3415, 3118, 2894, + 3266, 3220, 2391, + 2932, 3329, 0, + 0, 3442, 0, + 0, 3559, 0, + 0, 3680, 0, + 3822, 2628, 3522, + 3822, 2628, 3522, + 3822, 2628, 3522, + 3822, 2629, 3522, + 3822, 2629, 3522, + 3821, 2630, 3522, + 3821, 2630, 3522, + 3821, 2631, 3522, + 3821, 2633, 3521, + 3821, 2635, 3521, + 3820, 2637, 3520, + 3820, 2640, 3520, + 3819, 2644, 3519, + 3818, 2650, 3517, + 3817, 2657, 3515, + 3815, 2667, 3513, + 3813, 2679, 3510, + 3810, 2695, 3506, + 3806, 2716, 3500, + 3801, 2742, 3492, + 3794, 2775, 3481, + 3784, 2816, 3466, + 3771, 2865, 3446, + 3752, 2924, 3416, + 3726, 2992, 3374, + 3689, 3069, 3311, + 3634, 3156, 3210, + 3547, 3250, 3025, + 3398, 3352, 2521, + 3064, 3461, 0, + 0, 3574, 0, + 0, 3692, 0, + 3954, 2760, 3654, + 3954, 2760, 3654, + 3954, 2760, 3654, + 3954, 2760, 3654, + 3954, 2760, 3654, + 3954, 2761, 3654, + 3954, 2761, 3654, + 3953, 2762, 3654, + 3953, 2763, 3654, + 3953, 2764, 3653, + 3953, 2766, 3653, + 3952, 2769, 3652, + 3952, 2772, 3652, + 3951, 2776, 3651, + 3950, 2781, 3649, + 3949, 2789, 3647, + 3948, 2798, 3645, + 3945, 2811, 3642, + 3942, 2827, 3638, + 3939, 2848, 3632, + 3933, 2874, 3624, + 3926, 2907, 3613, + 3916, 2948, 3598, + 3903, 2997, 3578, + 3884, 3055, 3548, + 3858, 3123, 3506, + 3821, 3201, 3443, + 3766, 3288, 3342, + 3679, 3382, 3157, + 3530, 3484, 2653, + 3197, 3593, 0, + 0, 3706, 0, + 4086, 2891, 3786, + 4086, 2891, 3786, + 4086, 2892, 3786, + 4086, 2892, 3786, + 4086, 2892, 3786, + 4086, 2892, 3786, + 4086, 2893, 3786, + 4086, 2893, 3786, + 4086, 2894, 3786, + 4085, 2895, 3786, + 4085, 2896, 3785, + 4085, 2898, 3785, + 4085, 2900, 3784, + 4084, 2904, 3784, + 4083, 2908, 3783, + 4082, 2913, 3781, + 4081, 2921, 3780, + 4080, 2930, 3777, + 4078, 2943, 3774, + 4075, 2959, 3770, + 4071, 2980, 3764, + 4065, 3006, 3756, + 4058, 3039, 3745, + 4048, 3080, 3730, + 4035, 3129, 3710, + 4017, 3187, 3680, + 3990, 3255, 3638, + 3953, 3333, 3575, + 3898, 3420, 3474, + 3811, 3514, 3289, + 3662, 3616, 2784, + 3329, 3725, 0, + 4095, 3023, 3918, + 4095, 3023, 3918, + 4095, 3023, 3918, + 4095, 3023, 3918, + 4095, 3024, 3918, + 4095, 3024, 3918, + 4095, 3024, 3918, + 4095, 3025, 3918, + 4095, 3025, 3918, + 4095, 3026, 3918, + 4095, 3027, 3918, + 4095, 3028, 3917, + 4095, 3030, 3917, + 4095, 3032, 3916, + 4095, 3036, 3916, + 4095, 3040, 3915, + 4095, 3045, 3913, + 4095, 3052, 3912, + 4095, 3062, 3909, + 4095, 3075, 3906, + 4095, 3091, 3902, + 4095, 3111, 3896, + 4095, 3138, 3888, + 4095, 3171, 3877, + 4095, 3212, 3862, + 4095, 3261, 3842, + 4095, 3319, 3813, + 4095, 3387, 3770, + 4085, 3465, 3707, + 4030, 3552, 3606, + 3944, 3646, 3421, + 3794, 3748, 2916, + 4095, 3155, 4051, + 4095, 3155, 4051, + 4095, 3155, 4051, + 4095, 3155, 4050, + 4095, 3155, 4050, + 4095, 3156, 4050, + 4095, 3156, 4050, + 4095, 3156, 4050, + 4095, 3157, 4050, + 4095, 3157, 4050, + 4095, 3158, 4050, + 4095, 3159, 4050, + 4095, 3160, 4049, + 4095, 3162, 4049, + 4095, 3164, 4048, + 4095, 3167, 4048, + 4095, 3172, 4047, + 4095, 3177, 4045, + 4095, 3184, 4044, + 4095, 3194, 4041, + 4095, 3206, 4038, + 4095, 3223, 4034, + 4095, 3243, 4028, + 4095, 3270, 4020, + 4095, 3303, 4009, + 4095, 3344, 3994, + 4095, 3393, 3974, + 4095, 3451, 3945, + 4095, 3520, 3902, + 4095, 3597, 3839, + 4095, 3684, 3738, + 4076, 3778, 3553, + 0, 286, 468, + 0, 316, 433, + 0, 352, 383, + 0, 397, 305, + 0, 450, 175, + 0, 514, 0, + 0, 586, 0, + 0, 668, 0, + 0, 759, 0, + 0, 857, 0, + 0, 962, 0, + 0, 1073, 0, + 0, 1189, 0, + 0, 1308, 0, + 0, 1430, 0, + 0, 1555, 0, + 0, 1681, 0, + 0, 1809, 0, + 0, 1938, 0, + 0, 2068, 0, + 0, 2198, 0, + 0, 2329, 0, + 0, 2460, 0, + 0, 2591, 0, + 0, 2723, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 0, 296, 515, + 0, 325, 484, + 0, 361, 439, + 0, 405, 371, + 0, 458, 261, + 0, 520, 54, + 0, 592, 0, + 0, 673, 0, + 0, 762, 0, + 0, 860, 0, + 0, 965, 0, + 0, 1075, 0, + 0, 1190, 0, + 0, 1309, 0, + 0, 1431, 0, + 0, 1556, 0, + 0, 1682, 0, + 0, 1810, 0, + 0, 1938, 0, + 0, 2068, 0, + 0, 2198, 0, + 0, 2329, 0, + 0, 2460, 0, + 0, 2591, 0, + 0, 2723, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 38, 310, 571, + 0, 338, 544, + 0, 372, 505, + 0, 415, 447, + 0, 467, 355, + 0, 528, 195, + 0, 599, 0, + 0, 678, 0, + 0, 767, 0, + 0, 864, 0, + 0, 968, 0, + 0, 1077, 0, + 0, 1192, 0, + 0, 1311, 0, + 0, 1432, 0, + 0, 1556, 0, + 0, 1682, 0, + 0, 1810, 0, + 0, 1939, 0, + 0, 2068, 0, + 0, 2198, 0, + 0, 2329, 0, + 0, 2460, 0, + 0, 2591, 0, + 0, 2723, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 347, 327, 637, + 286, 354, 613, + 190, 387, 580, + 17, 429, 531, + 0, 479, 457, + 0, 539, 333, + 0, 608, 87, + 0, 686, 0, + 0, 774, 0, + 0, 869, 0, + 0, 972, 0, + 0, 1081, 0, + 0, 1194, 0, + 0, 1312, 0, + 0, 1434, 0, + 0, 1558, 0, + 0, 1683, 0, + 0, 1811, 0, + 0, 1939, 0, + 0, 2069, 0, + 0, 2199, 0, + 0, 2329, 0, + 0, 2460, 0, + 0, 2591, 0, + 0, 2723, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 577, 349, 712, + 541, 375, 692, + 489, 407, 664, + 408, 447, 624, + 270, 495, 565, + 0, 553, 470, + 0, 620, 302, + 0, 696, 0, + 0, 782, 0, + 0, 876, 0, + 0, 977, 0, + 0, 1085, 0, + 0, 1198, 0, + 0, 1315, 0, + 0, 1436, 0, + 0, 1559, 0, + 0, 1684, 0, + 0, 1812, 0, + 0, 1940, 0, + 0, 2069, 0, + 0, 2199, 0, + 0, 2329, 0, + 0, 2460, 0, + 0, 2591, 0, + 0, 2723, 0, + 0, 2854, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 771, 377, 796, + 748, 401, 780, + 715, 431, 757, + 668, 469, 725, + 595, 515, 678, + 475, 571, 606, + 241, 635, 487, + 0, 709, 256, + 0, 793, 0, + 0, 885, 0, + 0, 984, 0, + 0, 1091, 0, + 0, 1202, 0, + 0, 1318, 0, + 0, 1438, 0, + 0, 1561, 0, + 0, 1686, 0, + 0, 1813, 0, + 0, 1941, 0, + 0, 2070, 0, + 0, 2199, 0, + 0, 2330, 0, + 0, 2461, 0, + 0, 2592, 0, + 0, 2723, 0, + 0, 2855, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 944, 411, 889, + 928, 434, 876, + 907, 462, 858, + 876, 498, 832, + 832, 541, 795, + 764, 594, 740, + 655, 655, 655, + 450, 726, 509, + 0, 807, 186, + 0, 896, 0, + 0, 994, 0, + 0, 1098, 0, + 0, 1208, 0, + 0, 1323, 0, + 0, 1442, 0, + 0, 1564, 0, + 0, 1688, 0, + 0, 1814, 0, + 0, 1942, 0, + 0, 2071, 0, + 0, 2200, 0, + 0, 2330, 0, + 0, 2461, 0, + 0, 2592, 0, + 0, 2723, 0, + 0, 2855, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1105, 454, 990, + 1094, 475, 979, + 1079, 501, 965, + 1058, 533, 944, + 1029, 574, 916, + 986, 623, 874, + 922, 681, 813, + 820, 748, 714, + 633, 825, 536, + 113, 912, 73, + 0, 1006, 0, + 0, 1108, 0, + 0, 1216, 0, + 0, 1329, 0, + 0, 1446, 0, + 0, 1567, 0, + 0, 1691, 0, + 0, 1816, 0, + 0, 1943, 0, + 0, 2072, 0, + 0, 2201, 0, + 0, 2331, 0, + 0, 2461, 0, + 0, 2592, 0, + 0, 2724, 0, + 0, 2855, 0, + 0, 2987, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1257, 506, 1097, + 1249, 524, 1088, + 1239, 547, 1077, + 1224, 577, 1061, + 1204, 614, 1039, + 1175, 659, 1008, + 1134, 713, 963, + 1073, 776, 894, + 975, 849, 783, + 799, 931, 571, + 345, 1022, 0, + 0, 1121, 0, + 0, 1226, 0, + 0, 1337, 0, + 0, 1452, 0, + 0, 1572, 0, + 0, 1694, 0, + 0, 1819, 0, + 0, 1945, 0, + 0, 2073, 0, + 0, 2202, 0, + 0, 2332, 0, + 0, 2462, 0, + 0, 2593, 0, + 0, 2724, 0, + 0, 2855, 0, + 0, 2987, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1404, 566, 1209, + 1398, 582, 1202, + 1390, 603, 1193, + 1380, 629, 1181, + 1366, 662, 1165, + 1346, 703, 1141, + 1318, 752, 1108, + 1278, 811, 1059, + 1218, 878, 984, + 1124, 956, 860, + 956, 1042, 613, + 540, 1137, 0, + 0, 1239, 0, + 0, 1347, 0, + 0, 1461, 0, + 0, 1578, 0, + 0, 1699, 0, + 0, 1823, 0, + 0, 1948, 0, + 0, 2075, 0, + 0, 2204, 0, + 0, 2333, 0, + 0, 2463, 0, + 0, 2593, 0, + 0, 2724, 0, + 0, 2856, 0, + 0, 2987, 0, + 0, 3119, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1546, 637, 1325, + 1542, 651, 1320, + 1537, 668, 1314, + 1529, 691, 1304, + 1519, 720, 1292, + 1505, 756, 1274, + 1486, 800, 1249, + 1458, 853, 1214, + 1419, 915, 1162, + 1360, 987, 1082, + 1268, 1068, 947, + 1105, 1158, 665, + 714, 1256, 0, + 0, 1361, 0, + 0, 1471, 0, + 0, 1586, 0, + 0, 1705, 0, + 0, 1827, 0, + 0, 1952, 0, + 0, 2078, 0, + 0, 2206, 0, + 0, 2335, 0, + 0, 2464, 0, + 0, 2594, 0, + 0, 2725, 0, + 0, 2856, 0, + 0, 2987, 0, + 0, 3119, 0, + 0, 3251, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1686, 717, 1446, + 1683, 728, 1442, + 1679, 743, 1437, + 1674, 763, 1430, + 1666, 787, 1420, + 1656, 819, 1407, + 1642, 857, 1388, + 1623, 904, 1363, + 1596, 960, 1326, + 1557, 1026, 1272, + 1500, 1101, 1187, + 1409, 1185, 1042, + 1250, 1278, 725, + 875, 1378, 0, + 0, 1485, 0, + 0, 1597, 0, + 0, 1713, 0, + 0, 1834, 0, + 0, 1957, 0, + 0, 2082, 0, + 0, 2209, 0, + 0, 2337, 0, + 0, 2466, 0, + 0, 2596, 0, + 0, 2726, 0, + 0, 2857, 0, + 0, 2988, 0, + 0, 3119, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3514, 0, + 0, 3646, 0, + 1824, 805, 1569, + 1822, 815, 1566, + 1819, 827, 1562, + 1815, 843, 1556, + 1809, 864, 1549, + 1802, 891, 1539, + 1792, 924, 1526, + 1778, 965, 1507, + 1759, 1014, 1480, + 1732, 1073, 1442, + 1694, 1141, 1386, + 1637, 1219, 1298, + 1547, 1305, 1145, + 1391, 1400, 795, + 1028, 1502, 0, + 0, 1611, 0, + 0, 1724, 0, + 0, 1842, 0, + 0, 1963, 0, + 0, 2087, 0, + 0, 2212, 0, + 0, 2339, 0, + 0, 2468, 0, + 0, 2597, 0, + 0, 2727, 0, + 0, 2858, 0, + 0, 2989, 0, + 0, 3120, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3646, 0, + 1960, 902, 1694, + 1959, 910, 1692, + 1956, 920, 1689, + 1953, 933, 1685, + 1949, 950, 1679, + 1944, 972, 1672, + 1937, 1000, 1662, + 1927, 1035, 1648, + 1913, 1077, 1628, + 1894, 1129, 1601, + 1868, 1190, 1562, + 1830, 1260, 1505, + 1773, 1340, 1413, + 1684, 1428, 1253, + 1530, 1525, 875, + 1174, 1629, 0, + 0, 1738, 0, + 0, 1853, 0, + 0, 1971, 0, + 0, 2093, 0, + 0, 2217, 0, + 0, 2343, 0, + 0, 2471, 0, + 0, 2599, 0, + 0, 2729, 0, + 0, 2859, 0, + 0, 2989, 0, + 0, 3120, 0, + 0, 3252, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3647, 0, + 2095, 1005, 1821, + 2094, 1012, 1819, + 2093, 1020, 1817, + 2090, 1030, 1814, + 2087, 1044, 1810, + 2084, 1062, 1804, + 2078, 1085, 1797, + 2071, 1114, 1786, + 2061, 1150, 1772, + 2047, 1195, 1753, + 2029, 1248, 1725, + 2002, 1310, 1685, + 1964, 1382, 1626, + 1908, 1464, 1533, + 1820, 1554, 1367, + 1667, 1652, 963, + 1317, 1756, 0, + 0, 1867, 0, + 0, 1982, 0, + 0, 2101, 0, + 0, 2223, 0, + 0, 2348, 0, + 0, 2474, 0, + 0, 2602, 0, + 0, 2731, 0, + 0, 2860, 0, + 0, 2991, 0, + 0, 3121, 0, + 0, 3252, 0, + 0, 3384, 0, + 0, 3515, 0, + 0, 3647, 0, + 2230, 1115, 1949, + 2229, 1120, 1948, + 2228, 1126, 1946, + 2226, 1135, 1944, + 2224, 1146, 1941, + 2221, 1160, 1936, + 2217, 1179, 1931, + 2212, 1203, 1923, + 2205, 1233, 1913, + 2195, 1270, 1898, + 2181, 1315, 1879, + 2162, 1369, 1851, + 2136, 1433, 1810, + 2098, 1507, 1750, + 2042, 1589, 1655, + 1955, 1681, 1484, + 1802, 1780, 1059, + 1457, 1885, 0, + 0, 1996, 0, + 0, 2112, 0, + 0, 2232, 0, + 0, 2354, 0, + 0, 2479, 0, + 0, 2606, 0, + 0, 2734, 0, + 0, 2862, 0, + 0, 2992, 0, + 0, 3123, 0, + 0, 3253, 0, + 0, 3384, 0, + 0, 3516, 0, + 0, 3647, 0, + 2364, 1229, 2078, + 2363, 1233, 2077, + 2362, 1238, 2076, + 2361, 1245, 2074, + 2359, 1254, 2072, + 2357, 1265, 2069, + 2354, 1280, 2064, + 2350, 1299, 2059, + 2345, 1323, 2051, + 2338, 1354, 2041, + 2328, 1392, 2026, + 2314, 1438, 2006, + 2296, 1494, 1978, + 2269, 1559, 1937, + 2232, 1633, 1876, + 2176, 1717, 1779, + 2089, 1809, 1606, + 1937, 1908, 1163, + 1595, 2015, 0, + 0, 2127, 0, + 0, 2243, 0, + 0, 2363, 0, + 0, 2486, 0, + 0, 2611, 0, + 0, 2737, 0, + 0, 2865, 0, + 0, 2994, 0, + 0, 3124, 0, + 0, 3254, 0, + 0, 3385, 0, + 0, 3516, 0, + 0, 3648, 0, + 2497, 1348, 2208, + 2497, 1351, 2207, + 2496, 1355, 2206, + 2495, 1360, 2205, + 2494, 1367, 2203, + 2492, 1376, 2201, + 2490, 1387, 2198, + 2487, 1402, 2193, + 2483, 1422, 2188, + 2478, 1447, 2180, + 2471, 1478, 2169, + 2461, 1517, 2155, + 2447, 1564, 2135, + 2429, 1620, 2106, + 2402, 1686, 2065, + 2365, 1761, 2004, + 2309, 1845, 1906, + 2222, 1938, 1729, + 2071, 2038, 1272, + 1731, 2145, 0, + 0, 2257, 0, + 0, 2374, 0, + 0, 2494, 0, + 0, 2617, 0, + 0, 2742, 0, + 0, 2869, 0, + 0, 2997, 0, + 0, 3126, 0, + 0, 3256, 0, + 0, 3386, 0, + 0, 3517, 0, + 0, 3648, 0, + 2630, 1470, 2338, + 2630, 1472, 2338, + 2629, 1475, 2337, + 2629, 1479, 2336, + 2628, 1484, 2335, + 2627, 1491, 2333, + 2625, 1500, 2331, + 2623, 1512, 2327, + 2620, 1527, 2323, + 2616, 1547, 2317, + 2611, 1572, 2310, + 2603, 1604, 2299, + 2594, 1643, 2284, + 2580, 1691, 2264, + 2561, 1748, 2236, + 2535, 1814, 2194, + 2498, 1890, 2132, + 2442, 1974, 2033, + 2355, 2068, 1855, + 2205, 2168, 1386, + 1867, 2276, 0, + 0, 2388, 0, + 0, 2505, 0, + 0, 2625, 0, + 0, 2749, 0, + 0, 2874, 0, + 0, 3001, 0, + 0, 3129, 0, + 0, 3258, 0, + 0, 3388, 0, + 0, 3518, 0, + 0, 3649, 0, + 2763, 1594, 2469, + 2763, 1595, 2469, + 2762, 1598, 2468, + 2762, 1601, 2467, + 2761, 1605, 2466, + 2760, 1610, 2465, + 2759, 1617, 2463, + 2757, 1626, 2461, + 2755, 1638, 2458, + 2752, 1654, 2454, + 2748, 1674, 2448, + 2743, 1699, 2440, + 2736, 1731, 2429, + 2726, 1771, 2415, + 2713, 1819, 2394, + 2694, 1876, 2366, + 2668, 1943, 2324, + 2630, 2019, 2262, + 2575, 2104, 2162, + 2488, 2198, 1982, + 2338, 2299, 1505, + 2001, 2407, 0, + 0, 2519, 0, + 0, 2637, 0, + 0, 2757, 0, + 0, 2880, 0, + 0, 3006, 0, + 0, 3133, 0, + 0, 3261, 0, + 0, 3390, 0, + 0, 3520, 0, + 0, 3650, 0, + 2896, 1720, 2600, + 2895, 1721, 2600, + 2895, 1723, 2600, + 2895, 1725, 2599, + 2894, 1728, 2598, + 2894, 1732, 2597, + 2893, 1738, 2596, + 2891, 1745, 2594, + 2890, 1754, 2592, + 2888, 1766, 2589, + 2885, 1782, 2584, + 2881, 1802, 2579, + 2876, 1828, 2571, + 2868, 1860, 2560, + 2859, 1900, 2545, + 2845, 1948, 2525, + 2827, 2006, 2496, + 2800, 2073, 2454, + 2763, 2149, 2392, + 2708, 2235, 2292, + 2621, 2329, 2111, + 2471, 2430, 1626, + 2135, 2538, 0, + 0, 2651, 0, + 0, 2768, 0, + 0, 2889, 0, + 0, 3012, 0, + 0, 3138, 0, + 0, 3265, 0, + 0, 3393, 0, + 0, 3522, 0, + 0, 3652, 0, + 3028, 1847, 2732, + 3028, 1848, 2731, + 3028, 1850, 2731, + 3027, 1851, 2731, + 3027, 1854, 2730, + 3027, 1857, 2729, + 3026, 1861, 2728, + 3025, 1866, 2727, + 3024, 1873, 2725, + 3022, 1883, 2723, + 3020, 1895, 2720, + 3017, 1911, 2716, + 3013, 1931, 2710, + 3008, 1957, 2702, + 3001, 1989, 2691, + 2991, 2030, 2676, + 2978, 2078, 2656, + 2959, 2136, 2627, + 2933, 2203, 2585, + 2895, 2280, 2522, + 2840, 2366, 2422, + 2753, 2460, 2240, + 2604, 2562, 1750, + 2268, 2670, 0, + 0, 2783, 0, + 0, 2900, 0, + 0, 3021, 0, + 0, 3144, 0, + 0, 3269, 0, + 0, 3397, 0, + 0, 3525, 0, + 0, 3654, 0, + 3160, 1976, 2863, + 3160, 1977, 2863, + 3160, 1978, 2863, + 3160, 1979, 2862, + 3160, 1981, 2862, + 3159, 1983, 2862, + 3159, 1986, 2861, + 3158, 1990, 2860, + 3157, 1996, 2858, + 3156, 2003, 2857, + 3154, 2012, 2854, + 3152, 2025, 2851, + 3149, 2040, 2847, + 3146, 2061, 2841, + 3140, 2087, 2833, + 3133, 2120, 2822, + 3123, 2160, 2808, + 3110, 2209, 2787, + 3091, 2267, 2758, + 3065, 2334, 2716, + 3028, 2411, 2653, + 2972, 2497, 2553, + 2886, 2592, 2370, + 2736, 2693, 1876, + 2401, 2801, 0, + 0, 2914, 0, + 0, 3032, 0, + 0, 3152, 0, + 0, 3276, 0, + 0, 3401, 0, + 0, 3529, 0, + 0, 3657, 0, + 3293, 2105, 2995, + 3293, 2106, 2995, + 3293, 2107, 2995, + 3292, 2108, 2994, + 3292, 2109, 2994, + 3292, 2111, 2994, + 3292, 2113, 2993, + 3291, 2116, 2992, + 3290, 2120, 2991, + 3290, 2126, 2990, + 3288, 2133, 2988, + 3287, 2142, 2986, + 3285, 2155, 2983, + 3282, 2171, 2978, + 3278, 2191, 2973, + 3272, 2217, 2965, + 3265, 2250, 2954, + 3256, 2291, 2939, + 3242, 2339, 2919, + 3224, 2398, 2890, + 3197, 2465, 2848, + 3160, 2542, 2785, + 3105, 2629, 2684, + 3018, 2723, 2500, + 2869, 2825, 2004, + 2534, 2933, 0, + 0, 3046, 0, + 0, 3164, 0, + 0, 3284, 0, + 0, 3408, 0, + 0, 3533, 0, + 0, 3661, 0, + 3425, 2236, 3127, + 3425, 2236, 3127, + 3425, 2237, 3126, + 3425, 2237, 3126, + 3425, 2238, 3126, + 3424, 2240, 3126, + 3424, 2241, 3125, + 3424, 2244, 3125, + 3423, 2247, 3124, + 3423, 2251, 3123, + 3422, 2256, 3122, + 3421, 2264, 3120, + 3419, 2273, 3118, + 3417, 2286, 3114, + 3414, 2302, 3110, + 3410, 2322, 3104, + 3405, 2348, 3096, + 3397, 2381, 3086, + 3388, 2422, 3071, + 3374, 2471, 3050, + 3356, 2529, 3021, + 3330, 2597, 2979, + 3292, 2674, 2916, + 3237, 2760, 2815, + 3150, 2855, 2631, + 3001, 2957, 2132, + 2667, 3065, 0, + 0, 3178, 0, + 0, 3296, 0, + 0, 3416, 0, + 0, 3540, 0, + 0, 3665, 0, + 3557, 2366, 3259, + 3557, 2367, 3258, + 3557, 2367, 3258, + 3557, 2367, 3258, + 3557, 2368, 3258, + 3557, 2369, 3258, + 3557, 2371, 3258, + 3556, 2372, 3257, + 3556, 2375, 3257, + 3555, 2378, 3256, + 3555, 2382, 3255, + 3554, 2387, 3254, + 3553, 2395, 3252, + 3551, 2404, 3249, + 3549, 2417, 3246, + 3546, 2433, 3242, + 3542, 2453, 3236, + 3537, 2480, 3228, + 3530, 2512, 3217, + 3520, 2553, 3203, + 3506, 2602, 3182, + 3488, 2660, 3153, + 3462, 2728, 3111, + 3424, 2806, 3048, + 3369, 2892, 2947, + 3283, 2987, 2763, + 3133, 3089, 2262, + 2799, 3197, 0, + 0, 3310, 0, + 0, 3428, 0, + 0, 3548, 0, + 0, 3672, 0, + 3689, 2497, 3390, + 3689, 2497, 3390, + 3689, 2498, 3390, + 3689, 2498, 3390, + 3689, 2499, 3390, + 3689, 2499, 3390, + 3689, 2500, 3390, + 3689, 2502, 3389, + 3688, 2504, 3389, + 3688, 2506, 3388, + 3688, 2509, 3388, + 3687, 2513, 3387, + 3686, 2519, 3385, + 3685, 2526, 3384, + 3683, 2535, 3381, + 3681, 2548, 3378, + 3678, 2564, 3374, + 3674, 2585, 3368, + 3669, 2611, 3360, + 3662, 2644, 3349, + 3652, 2684, 3334, + 3639, 2734, 3314, + 3620, 2792, 3285, + 3594, 2860, 3243, + 3557, 2937, 3179, + 3501, 3024, 3078, + 3415, 3119, 2894, + 3266, 3220, 2392, + 2932, 3329, 0, + 0, 3442, 0, + 0, 3560, 0, + 0, 3680, 0, + 3822, 2628, 3522, + 3822, 2629, 3522, + 3822, 2629, 3522, + 3822, 2629, 3522, + 3821, 2630, 3522, + 3821, 2630, 3522, + 3821, 2631, 3522, + 3821, 2632, 3522, + 3821, 2633, 3521, + 3821, 2635, 3521, + 3820, 2637, 3520, + 3820, 2641, 3520, + 3819, 2645, 3519, + 3818, 2650, 3517, + 3817, 2657, 3516, + 3815, 2667, 3513, + 3813, 2679, 3510, + 3810, 2696, 3506, + 3806, 2716, 3500, + 3801, 2743, 3492, + 3794, 2775, 3481, + 3784, 2816, 3466, + 3771, 2865, 3446, + 3752, 2924, 3417, + 3726, 2992, 3375, + 3689, 3069, 3311, + 3633, 3156, 3210, + 3547, 3250, 3026, + 3398, 3352, 2523, + 3064, 3461, 0, + 0, 3574, 0, + 0, 3692, 0, + 3954, 2760, 3654, + 3954, 2760, 3654, + 3954, 2760, 3654, + 3954, 2760, 3654, + 3954, 2761, 3654, + 3954, 2761, 3654, + 3954, 2762, 3654, + 3953, 2763, 3654, + 3953, 2764, 3654, + 3953, 2765, 3653, + 3953, 2767, 3653, + 3952, 2769, 3652, + 3952, 2772, 3652, + 3951, 2776, 3651, + 3950, 2782, 3649, + 3949, 2789, 3648, + 3948, 2799, 3645, + 3945, 2811, 3642, + 3942, 2827, 3638, + 3939, 2848, 3632, + 3933, 2874, 3624, + 3926, 2907, 3613, + 3916, 2948, 3598, + 3903, 2997, 3578, + 3884, 3056, 3549, + 3858, 3124, 3506, + 3821, 3201, 3443, + 3766, 3288, 3342, + 3679, 3382, 3157, + 3530, 3484, 2654, + 3196, 3593, 0, + 0, 3706, 0, + 4086, 2892, 3786, + 4086, 2892, 3786, + 4086, 2892, 3786, + 4086, 2892, 3786, + 4086, 2892, 3786, + 4086, 2893, 3786, + 4086, 2893, 3786, + 4086, 2894, 3786, + 4086, 2894, 3786, + 4085, 2895, 3786, + 4085, 2897, 3785, + 4085, 2898, 3785, + 4085, 2901, 3784, + 4084, 2904, 3784, + 4083, 2908, 3783, + 4082, 2914, 3781, + 4081, 2921, 3780, + 4080, 2930, 3777, + 4077, 2943, 3774, + 4075, 2959, 3770, + 4071, 2980, 3764, + 4065, 3006, 3756, + 4058, 3039, 3745, + 4048, 3080, 3730, + 4035, 3129, 3710, + 4017, 3188, 3681, + 3990, 3256, 3638, + 3953, 3333, 3575, + 3898, 3420, 3474, + 3811, 3514, 3289, + 3662, 3616, 2785, + 3329, 3725, 0, + 4095, 3023, 3919, + 4095, 3023, 3918, + 4095, 3023, 3918, + 4095, 3024, 3918, + 4095, 3024, 3918, + 4095, 3024, 3918, + 4095, 3024, 3918, + 4095, 3025, 3918, + 4095, 3025, 3918, + 4095, 3026, 3918, + 4095, 3027, 3918, + 4095, 3028, 3917, + 4095, 3030, 3917, + 4095, 3033, 3916, + 4095, 3036, 3916, + 4095, 3040, 3915, + 4095, 3045, 3913, + 4095, 3053, 3912, + 4095, 3062, 3909, + 4095, 3075, 3906, + 4095, 3091, 3902, + 4095, 3112, 3896, + 4095, 3138, 3888, + 4095, 3171, 3877, + 4095, 3212, 3862, + 4095, 3261, 3842, + 4095, 3319, 3813, + 4095, 3388, 3770, + 4085, 3465, 3707, + 4030, 3552, 3606, + 3944, 3646, 3421, + 3794, 3748, 2916, + 4095, 3155, 4051, + 4095, 3155, 4051, + 4095, 3155, 4051, + 4095, 3155, 4051, + 4095, 3156, 4050, + 4095, 3156, 4050, + 4095, 3156, 4050, + 4095, 3156, 4050, + 4095, 3157, 4050, + 4095, 3157, 4050, + 4095, 3158, 4050, + 4095, 3159, 4050, + 4095, 3160, 4049, + 4095, 3162, 4049, + 4095, 3164, 4048, + 4095, 3168, 4048, + 4095, 3172, 4047, + 4095, 3177, 4045, + 4095, 3185, 4044, + 4095, 3194, 4041, + 4095, 3207, 4038, + 4095, 3223, 4034, + 4095, 3244, 4028, + 4095, 3270, 4020, + 4095, 3303, 4009, + 4095, 3344, 3994, + 4095, 3393, 3974, + 4095, 3451, 3945, + 4095, 3520, 3902, + 4095, 3597, 3839, + 4095, 3684, 3738, + 4076, 3778, 3553, + 0, 387, 587, + 0, 410, 561, + 0, 440, 523, + 0, 477, 468, + 0, 523, 381, + 0, 577, 231, + 0, 641, 0, + 0, 714, 0, + 0, 797, 0, + 0, 888, 0, + 0, 987, 0, + 0, 1093, 0, + 0, 1204, 0, + 0, 1320, 0, + 0, 1439, 0, + 0, 1562, 0, + 0, 1687, 0, + 0, 1813, 0, + 0, 1941, 0, + 0, 2070, 0, + 0, 2200, 0, + 0, 2330, 0, + 0, 2461, 0, + 0, 2592, 0, + 0, 2723, 0, + 0, 2855, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 0, 395, 624, + 0, 418, 600, + 0, 448, 565, + 0, 484, 515, + 0, 529, 437, + 0, 583, 307, + 0, 646, 42, + 0, 718, 0, + 0, 800, 0, + 0, 891, 0, + 0, 989, 0, + 0, 1094, 0, + 0, 1205, 0, + 0, 1321, 0, + 0, 1440, 0, + 0, 1562, 0, + 0, 1687, 0, + 0, 1813, 0, + 0, 1941, 0, + 0, 2070, 0, + 0, 2200, 0, + 0, 2330, 0, + 0, 2461, 0, + 0, 2592, 0, + 0, 2723, 0, + 0, 2855, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 0, 406, 669, + 0, 428, 647, + 0, 457, 616, + 0, 493, 571, + 0, 537, 503, + 0, 590, 393, + 0, 652, 186, + 0, 724, 0, + 0, 805, 0, + 0, 894, 0, + 0, 992, 0, + 0, 1097, 0, + 0, 1207, 0, + 0, 1322, 0, + 0, 1441, 0, + 0, 1563, 0, + 0, 1688, 0, + 0, 1814, 0, + 0, 1942, 0, + 0, 2070, 0, + 0, 2200, 0, + 0, 2330, 0, + 0, 2461, 0, + 0, 2592, 0, + 0, 2723, 0, + 0, 2855, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 247, 420, 722, + 170, 442, 703, + 41, 470, 676, + 0, 505, 637, + 0, 547, 579, + 0, 599, 487, + 0, 660, 327, + 0, 731, 0, + 0, 811, 0, + 0, 899, 0, + 0, 996, 0, + 0, 1100, 0, + 0, 1210, 0, + 0, 1324, 0, + 0, 1443, 0, + 0, 1564, 0, + 0, 1688, 0, + 0, 1815, 0, + 0, 1942, 0, + 0, 2071, 0, + 0, 2200, 0, + 0, 2330, 0, + 0, 2461, 0, + 0, 2592, 0, + 0, 2723, 0, + 0, 2855, 0, + 0, 2986, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 519, 438, 786, + 479, 459, 769, + 418, 486, 745, + 322, 520, 712, + 149, 561, 663, + 0, 611, 589, + 0, 671, 465, + 0, 740, 219, + 0, 818, 0, + 0, 906, 0, + 0, 1001, 0, + 0, 1104, 0, + 0, 1213, 0, + 0, 1327, 0, + 0, 1445, 0, + 0, 1566, 0, + 0, 1690, 0, + 0, 1815, 0, + 0, 1943, 0, + 0, 2071, 0, + 0, 2201, 0, + 0, 2331, 0, + 0, 2461, 0, + 0, 2592, 0, + 0, 2723, 0, + 0, 2855, 0, + 0, 2987, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 734, 461, 858, + 709, 481, 844, + 673, 507, 824, + 621, 539, 797, + 540, 579, 756, + 402, 627, 697, + 110, 685, 602, + 0, 752, 434, + 0, 828, 18, + 0, 914, 0, + 0, 1008, 0, + 0, 1109, 0, + 0, 1217, 0, + 0, 1330, 0, + 0, 1447, 0, + 0, 1568, 0, + 0, 1691, 0, + 0, 1817, 0, + 0, 1944, 0, + 0, 2072, 0, + 0, 2201, 0, + 0, 2331, 0, + 0, 2462, 0, + 0, 2592, 0, + 0, 2724, 0, + 0, 2855, 0, + 0, 2987, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 919, 490, 940, + 903, 509, 929, + 880, 533, 912, + 847, 563, 889, + 800, 601, 857, + 727, 647, 810, + 607, 703, 738, + 373, 767, 619, + 0, 842, 388, + 0, 925, 0, + 0, 1017, 0, + 0, 1116, 0, + 0, 1223, 0, + 0, 1334, 0, + 0, 1451, 0, + 0, 1570, 0, + 0, 1693, 0, + 0, 1818, 0, + 0, 1945, 0, + 0, 2073, 0, + 0, 2202, 0, + 0, 2332, 0, + 0, 2462, 0, + 0, 2593, 0, + 0, 2724, 0, + 0, 2855, 0, + 0, 2987, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1087, 526, 1031, + 1076, 544, 1021, + 1061, 566, 1008, + 1039, 594, 990, + 1008, 630, 964, + 964, 673, 927, + 896, 726, 872, + 787, 787, 787, + 582, 859, 641, + 0, 939, 318, + 0, 1029, 0, + 0, 1126, 0, + 0, 1230, 0, + 0, 1340, 0, + 0, 1455, 0, + 0, 1574, 0, + 0, 1696, 0, + 0, 1820, 0, + 0, 1946, 0, + 0, 2074, 0, + 0, 2203, 0, + 0, 2332, 0, + 0, 2462, 0, + 0, 2593, 0, + 0, 2724, 0, + 0, 2855, 0, + 0, 2987, 0, + 0, 3119, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1245, 570, 1130, + 1237, 586, 1122, + 1226, 607, 1111, + 1211, 633, 1097, + 1190, 665, 1076, + 1161, 706, 1048, + 1118, 755, 1006, + 1055, 813, 945, + 952, 880, 846, + 765, 958, 669, + 245, 1044, 205, + 0, 1138, 0, + 0, 1240, 0, + 0, 1348, 0, + 0, 1461, 0, + 0, 1578, 0, + 0, 1699, 0, + 0, 1823, 0, + 0, 1948, 0, + 0, 2075, 0, + 0, 2204, 0, + 0, 2333, 0, + 0, 2463, 0, + 0, 2594, 0, + 0, 2724, 0, + 0, 2856, 0, + 0, 2987, 0, + 0, 3119, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1395, 623, 1235, + 1389, 638, 1229, + 1381, 656, 1220, + 1371, 679, 1209, + 1356, 709, 1193, + 1336, 746, 1171, + 1308, 791, 1140, + 1267, 845, 1095, + 1205, 908, 1026, + 1107, 981, 915, + 932, 1063, 703, + 477, 1154, 0, + 0, 1253, 0, + 0, 1358, 0, + 0, 1469, 0, + 0, 1585, 0, + 0, 1704, 0, + 0, 1826, 0, + 0, 1951, 0, + 0, 2077, 0, + 0, 2205, 0, + 0, 2334, 0, + 0, 2464, 0, + 0, 2594, 0, + 0, 2725, 0, + 0, 2856, 0, + 0, 2987, 0, + 0, 3119, 0, + 0, 3251, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1540, 686, 1346, + 1536, 698, 1341, + 1530, 715, 1334, + 1522, 735, 1326, + 1512, 762, 1313, + 1498, 794, 1297, + 1478, 835, 1273, + 1450, 884, 1240, + 1410, 943, 1191, + 1351, 1011, 1116, + 1256, 1088, 993, + 1088, 1174, 745, + 672, 1269, 0, + 0, 1371, 0, + 0, 1479, 0, + 0, 1593, 0, + 0, 1710, 0, + 0, 1831, 0, + 0, 1955, 0, + 0, 2080, 0, + 0, 2207, 0, + 0, 2336, 0, + 0, 2465, 0, + 0, 2595, 0, + 0, 2726, 0, + 0, 2857, 0, + 0, 2988, 0, + 0, 3119, 0, + 0, 3251, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1681, 758, 1461, + 1678, 769, 1458, + 1674, 783, 1453, + 1669, 801, 1446, + 1661, 823, 1436, + 1651, 852, 1424, + 1637, 888, 1406, + 1618, 932, 1381, + 1590, 985, 1346, + 1551, 1047, 1295, + 1492, 1119, 1215, + 1400, 1200, 1079, + 1237, 1290, 797, + 846, 1388, 0, + 0, 1493, 0, + 0, 1603, 0, + 0, 1718, 0, + 0, 1837, 0, + 0, 1959, 0, + 0, 2084, 0, + 0, 2210, 0, + 0, 2338, 0, + 0, 2467, 0, + 0, 2596, 0, + 0, 2726, 0, + 0, 2857, 0, + 0, 2988, 0, + 0, 3120, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3514, 0, + 0, 3646, 0, + 1820, 840, 1581, + 1818, 849, 1578, + 1815, 860, 1574, + 1811, 875, 1569, + 1806, 895, 1562, + 1798, 920, 1552, + 1788, 951, 1539, + 1774, 989, 1521, + 1755, 1036, 1495, + 1728, 1092, 1458, + 1689, 1158, 1404, + 1632, 1233, 1319, + 1541, 1317, 1174, + 1382, 1410, 857, + 1007, 1510, 0, + 0, 1617, 0, + 0, 1729, 0, + 0, 1846, 0, + 0, 1966, 0, + 0, 2089, 0, + 0, 2214, 0, + 0, 2341, 0, + 0, 2469, 0, + 0, 2598, 0, + 0, 2728, 0, + 0, 2858, 0, + 0, 2989, 0, + 0, 3120, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3646, 0, + 1958, 930, 1703, + 1956, 937, 1701, + 1954, 947, 1698, + 1951, 959, 1694, + 1947, 976, 1689, + 1941, 996, 1681, + 1934, 1023, 1671, + 1924, 1056, 1658, + 1910, 1097, 1639, + 1891, 1146, 1613, + 1865, 1205, 1575, + 1826, 1273, 1518, + 1769, 1351, 1430, + 1679, 1437, 1277, + 1523, 1532, 927, + 1160, 1635, 0, + 0, 1743, 0, + 0, 1856, 0, + 0, 1974, 0, + 0, 2095, 0, + 0, 2219, 0, + 0, 2344, 0, + 0, 2471, 0, + 0, 2600, 0, + 0, 2729, 0, + 0, 2859, 0, + 0, 2990, 0, + 0, 3121, 0, + 0, 3252, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3647, 0, + 2094, 1028, 1828, + 2092, 1034, 1826, + 2091, 1042, 1824, + 2088, 1052, 1821, + 2086, 1065, 1817, + 2082, 1082, 1811, + 2076, 1104, 1804, + 2069, 1132, 1794, + 2059, 1167, 1780, + 2045, 1210, 1761, + 2026, 1261, 1733, + 2000, 1322, 1695, + 1962, 1392, 1637, + 1905, 1472, 1545, + 1816, 1561, 1385, + 1662, 1657, 1007, + 1307, 1761, 0, + 0, 1870, 0, + 0, 1985, 0, + 0, 2103, 0, + 0, 2225, 0, + 0, 2349, 0, + 0, 2475, 0, + 0, 2603, 0, + 0, 2731, 0, + 0, 2861, 0, + 0, 2991, 0, + 0, 3122, 0, + 0, 3253, 0, + 0, 3384, 0, + 0, 3515, 0, + 0, 3647, 0, + 2228, 1133, 1954, + 2228, 1138, 1953, + 2226, 1144, 1951, + 2225, 1152, 1949, + 2223, 1163, 1946, + 2220, 1176, 1942, + 2216, 1194, 1936, + 2210, 1217, 1929, + 2203, 1246, 1918, + 2193, 1282, 1904, + 2180, 1327, 1885, + 2161, 1380, 1857, + 2134, 1442, 1817, + 2096, 1514, 1758, + 2040, 1596, 1665, + 1952, 1686, 1499, + 1799, 1784, 1095, + 1449, 1888, 0, + 0, 1999, 0, + 0, 2114, 0, + 0, 2233, 0, + 0, 2356, 0, + 0, 2480, 0, + 0, 2606, 0, + 0, 2734, 0, + 0, 2863, 0, + 0, 2992, 0, + 0, 3123, 0, + 0, 3253, 0, + 0, 3384, 0, + 0, 3516, 0, + 0, 3647, 0, + 2363, 1243, 2082, + 2362, 1247, 2081, + 2361, 1252, 2080, + 2360, 1258, 2078, + 2358, 1267, 2076, + 2356, 1278, 2073, + 2353, 1292, 2068, + 2349, 1311, 2063, + 2344, 1335, 2055, + 2337, 1365, 2045, + 2327, 1402, 2031, + 2313, 1447, 2011, + 2294, 1502, 1983, + 2268, 1565, 1942, + 2230, 1639, 1882, + 2174, 1721, 1787, + 2087, 1813, 1617, + 1934, 1912, 1191, + 1589, 2017, 0, + 0, 2129, 0, + 0, 2244, 0, + 0, 2364, 0, + 0, 2486, 0, + 0, 2611, 0, + 0, 2738, 0, + 0, 2866, 0, + 0, 2995, 0, + 0, 3124, 0, + 0, 3255, 0, + 0, 3385, 0, + 0, 3516, 0, + 0, 3648, 0, + 2496, 1359, 2211, + 2496, 1362, 2210, + 2495, 1365, 2209, + 2494, 1370, 2208, + 2493, 1377, 2206, + 2491, 1386, 2204, + 2489, 1397, 2201, + 2486, 1412, 2196, + 2482, 1431, 2191, + 2477, 1455, 2183, + 2470, 1486, 2173, + 2460, 1524, 2158, + 2446, 1570, 2138, + 2428, 1626, 2110, + 2402, 1691, 2069, + 2364, 1765, 2008, + 2308, 1849, 1911, + 2221, 1941, 1738, + 2069, 2041, 1295, + 1727, 2147, 0, + 0, 2259, 0, + 0, 2375, 0, + 0, 2495, 0, + 0, 2618, 0, + 0, 2743, 0, + 0, 2869, 0, + 0, 2997, 0, + 0, 3126, 0, + 0, 3256, 0, + 0, 3387, 0, + 0, 3517, 0, + 0, 3648, 0, + 2630, 1478, 2340, + 2629, 1480, 2340, + 2629, 1483, 2339, + 2628, 1487, 2338, + 2627, 1492, 2337, + 2626, 1499, 2335, + 2624, 1508, 2333, + 2622, 1519, 2330, + 2619, 1535, 2326, + 2615, 1554, 2320, + 2610, 1579, 2312, + 2603, 1610, 2302, + 2593, 1649, 2287, + 2579, 1696, 2267, + 2561, 1752, 2238, + 2535, 1818, 2197, + 2497, 1893, 2136, + 2441, 1977, 2038, + 2354, 2070, 1861, + 2203, 2170, 1404, + 1864, 2277, 0, + 0, 2389, 0, + 0, 2506, 0, + 0, 2626, 0, + 0, 2749, 0, + 0, 2874, 0, + 0, 3001, 0, + 0, 3129, 0, + 0, 3258, 0, + 0, 3388, 0, + 0, 3519, 0, + 0, 3649, 0, + 2763, 1600, 2471, + 2762, 1602, 2470, + 2762, 1604, 2470, + 2761, 1607, 2469, + 2761, 1611, 2468, + 2760, 1616, 2467, + 2759, 1623, 2465, + 2757, 1632, 2463, + 2755, 1644, 2460, + 2752, 1659, 2455, + 2748, 1679, 2450, + 2743, 1704, 2442, + 2735, 1736, 2431, + 2726, 1775, 2417, + 2712, 1823, 2396, + 2694, 1880, 2368, + 2667, 1946, 2326, + 2630, 2022, 2264, + 2574, 2107, 2165, + 2487, 2200, 1987, + 2337, 2301, 1518, + 1999, 2408, 0, + 0, 2520, 0, + 0, 2637, 0, + 0, 2758, 0, + 0, 2881, 0, + 0, 3006, 0, + 0, 3133, 0, + 0, 3261, 0, + 0, 3390, 0, + 0, 3520, 0, + 0, 3651, 0, + 2895, 1725, 2601, + 2895, 1726, 2601, + 2895, 1728, 2601, + 2894, 1730, 2600, + 2894, 1733, 2599, + 2893, 1737, 2599, + 2892, 1742, 2597, + 2891, 1749, 2595, + 2890, 1758, 2593, + 2887, 1770, 2590, + 2884, 1786, 2586, + 2881, 1806, 2580, + 2875, 1832, 2572, + 2868, 1864, 2561, + 2858, 1903, 2547, + 2845, 1951, 2526, + 2826, 2008, 2498, + 2800, 2075, 2456, + 2763, 2151, 2394, + 2707, 2237, 2294, + 2620, 2330, 2114, + 2470, 2431, 1637, + 2133, 2539, 0, + 0, 2652, 0, + 0, 2769, 0, + 0, 2889, 0, + 0, 3012, 0, + 0, 3138, 0, + 0, 3265, 0, + 0, 3393, 0, + 0, 3522, 0, + 0, 3652, 0, + 3028, 1851, 2733, + 3028, 1852, 2732, + 3027, 1853, 2732, + 3027, 1855, 2732, + 3027, 1857, 2731, + 3026, 1860, 2730, + 3026, 1864, 2729, + 3025, 1870, 2728, + 3024, 1877, 2726, + 3022, 1886, 2724, + 3020, 1898, 2721, + 3017, 1914, 2717, + 3013, 1934, 2711, + 3008, 1960, 2703, + 3000, 1992, 2692, + 2991, 2032, 2677, + 2977, 2080, 2657, + 2959, 2138, 2628, + 2933, 2205, 2586, + 2895, 2282, 2524, + 2840, 2367, 2424, + 2753, 2461, 2243, + 2603, 2562, 1758, + 2267, 2670, 0, + 0, 2783, 0, + 0, 2900, 0, + 0, 3021, 0, + 0, 3144, 0, + 0, 3270, 0, + 0, 3397, 0, + 0, 3525, 0, + 0, 3654, 0, + 3160, 1979, 2864, + 3160, 1979, 2864, + 3160, 1980, 2863, + 3160, 1982, 2863, + 3160, 1983, 2863, + 3159, 1986, 2862, + 3159, 1989, 2861, + 3158, 1993, 2861, + 3157, 1998, 2859, + 3156, 2005, 2857, + 3154, 2015, 2855, + 3152, 2027, 2852, + 3149, 2043, 2848, + 3145, 2063, 2842, + 3140, 2089, 2834, + 3133, 2122, 2823, + 3123, 2162, 2809, + 3110, 2210, 2788, + 3091, 2268, 2759, + 3065, 2335, 2717, + 3028, 2412, 2654, + 2972, 2498, 2554, + 2886, 2592, 2372, + 2736, 2694, 1882, + 2401, 2802, 0, + 0, 2915, 0, + 0, 3032, 0, + 0, 3153, 0, + 0, 3276, 0, + 0, 3402, 0, + 0, 3529, 0, + 0, 3657, 0, + 3293, 2107, 2995, + 3293, 2108, 2995, + 3292, 2109, 2995, + 3292, 2110, 2995, + 3292, 2111, 2995, + 3292, 2113, 2994, + 3291, 2115, 2994, + 3291, 2118, 2993, + 3290, 2122, 2992, + 3289, 2128, 2991, + 3288, 2135, 2989, + 3287, 2144, 2986, + 3284, 2157, 2983, + 3282, 2173, 2979, + 3278, 2193, 2973, + 3272, 2219, 2965, + 3265, 2252, 2955, + 3255, 2292, 2940, + 3242, 2341, 2919, + 3223, 2399, 2890, + 3197, 2466, 2848, + 3160, 2543, 2785, + 3104, 2629, 2685, + 3018, 2724, 2502, + 2868, 2825, 2008, + 2534, 2933, 0, + 0, 3046, 0, + 0, 3164, 0, + 0, 3285, 0, + 0, 3408, 0, + 0, 3534, 0, + 0, 3661, 0, + 3425, 2237, 3127, + 3425, 2238, 3127, + 3425, 2238, 3127, + 3425, 2239, 3127, + 3425, 2240, 3126, + 3424, 2241, 3126, + 3424, 2243, 3126, + 3424, 2245, 3125, + 3423, 2248, 3124, + 3423, 2252, 3123, + 3422, 2258, 3122, + 3420, 2265, 3120, + 3419, 2275, 3118, + 3417, 2287, 3115, + 3414, 2303, 3111, + 3410, 2323, 3105, + 3405, 2350, 3097, + 3397, 2382, 3086, + 3388, 2423, 3071, + 3374, 2472, 3051, + 3356, 2530, 3022, + 3330, 2597, 2980, + 3292, 2675, 2917, + 3237, 2761, 2816, + 3150, 2855, 2633, + 3001, 2957, 2136, + 2666, 3065, 0, + 0, 3178, 0, + 0, 3296, 0, + 0, 3417, 0, + 0, 3540, 0, + 0, 3666, 0, + 3557, 2367, 3259, + 3557, 2368, 3259, + 3557, 2368, 3259, + 3557, 2369, 3259, + 3557, 2369, 3258, + 3557, 2370, 3258, + 3557, 2372, 3258, + 3556, 2373, 3257, + 3556, 2376, 3257, + 3555, 2379, 3256, + 3555, 2383, 3255, + 3554, 2389, 3254, + 3553, 2396, 3252, + 3551, 2405, 3250, + 3549, 2418, 3247, + 3546, 2434, 3242, + 3542, 2454, 3236, + 3537, 2480, 3229, + 3530, 2513, 3218, + 3520, 2554, 3203, + 3506, 2603, 3182, + 3488, 2661, 3153, + 3462, 2729, 3111, + 3424, 2806, 3048, + 3369, 2892, 2947, + 3283, 2987, 2763, + 3133, 3089, 2264, + 2799, 3197, 0, + 0, 3310, 0, + 0, 3428, 0, + 0, 3548, 0, + 0, 3672, 0, + 3689, 2498, 3391, + 3689, 2498, 3391, + 3689, 2499, 3391, + 3689, 2499, 3390, + 3689, 2500, 3390, + 3689, 2500, 3390, + 3689, 2501, 3390, + 3689, 2503, 3390, + 3688, 2504, 3389, + 3688, 2507, 3389, + 3688, 2510, 3388, + 3687, 2514, 3387, + 3686, 2520, 3386, + 3685, 2527, 3384, + 3683, 2536, 3382, + 3681, 2549, 3378, + 3678, 2565, 3374, + 3674, 2585, 3368, + 3669, 2612, 3360, + 3662, 2644, 3350, + 3652, 2685, 3335, + 3639, 2734, 3314, + 3620, 2792, 3285, + 3594, 2860, 3243, + 3557, 2938, 3180, + 3501, 3024, 3079, + 3415, 3119, 2895, + 3265, 3221, 2394, + 2932, 3329, 0, + 0, 3442, 0, + 0, 3560, 0, + 0, 3681, 0, + 3822, 2629, 3523, + 3822, 2629, 3523, + 3822, 2630, 3523, + 3822, 2630, 3522, + 3821, 2630, 3522, + 3821, 2631, 3522, + 3821, 2632, 3522, + 3821, 2633, 3522, + 3821, 2634, 3522, + 3821, 2636, 3521, + 3820, 2638, 3521, + 3820, 2641, 3520, + 3819, 2645, 3519, + 3818, 2651, 3518, + 3817, 2658, 3516, + 3815, 2668, 3513, + 3813, 2680, 3510, + 3810, 2696, 3506, + 3806, 2717, 3500, + 3801, 2743, 3492, + 3794, 2776, 3481, + 3784, 2817, 3467, + 3771, 2866, 3446, + 3752, 2924, 3417, + 3726, 2992, 3375, + 3689, 3069, 3312, + 3633, 3156, 3210, + 3547, 3251, 3026, + 3398, 3353, 2524, + 3064, 3461, 0, + 0, 3574, 0, + 0, 3692, 0, + 3954, 2760, 3655, + 3954, 2761, 3655, + 3954, 2761, 3654, + 3954, 2761, 3654, + 3954, 2761, 3654, + 3954, 2762, 3654, + 3953, 2762, 3654, + 3953, 2763, 3654, + 3953, 2764, 3654, + 3953, 2765, 3653, + 3953, 2767, 3653, + 3952, 2769, 3652, + 3952, 2773, 3652, + 3951, 2777, 3651, + 3950, 2782, 3649, + 3949, 2790, 3648, + 3947, 2799, 3645, + 3945, 2812, 3642, + 3942, 2828, 3638, + 3939, 2848, 3632, + 3933, 2875, 3624, + 3926, 2908, 3613, + 3916, 2948, 3598, + 3903, 2997, 3578, + 3884, 3056, 3549, + 3858, 3124, 3507, + 3821, 3201, 3443, + 3766, 3288, 3342, + 3679, 3383, 3158, + 3530, 3485, 2655, + 3196, 3593, 0, + 0, 3706, 0, + 4086, 2892, 3787, + 4086, 2892, 3787, + 4086, 2892, 3787, + 4086, 2892, 3786, + 4086, 2893, 3786, + 4086, 2893, 3786, + 4086, 2893, 3786, + 4086, 2894, 3786, + 4086, 2895, 3786, + 4085, 2896, 3786, + 4085, 2897, 3785, + 4085, 2899, 3785, + 4084, 2901, 3784, + 4084, 2904, 3784, + 4083, 2908, 3783, + 4082, 2914, 3781, + 4081, 2921, 3780, + 4080, 2931, 3777, + 4077, 2943, 3774, + 4075, 2959, 3770, + 4071, 2980, 3764, + 4065, 3006, 3756, + 4058, 3039, 3745, + 4048, 3080, 3730, + 4035, 3129, 3710, + 4016, 3188, 3681, + 3990, 3256, 3639, + 3953, 3333, 3575, + 3898, 3420, 3474, + 3811, 3515, 3289, + 3662, 3617, 2786, + 3329, 3725, 0, + 4095, 3024, 3919, + 4095, 3024, 3919, + 4095, 3024, 3919, + 4095, 3024, 3919, + 4095, 3024, 3918, + 4095, 3024, 3918, + 4095, 3025, 3918, + 4095, 3025, 3918, + 4095, 3026, 3918, + 4095, 3026, 3918, + 4095, 3027, 3918, + 4095, 3029, 3917, + 4095, 3030, 3917, + 4095, 3033, 3916, + 4095, 3036, 3916, + 4095, 3040, 3915, + 4095, 3046, 3913, + 4095, 3053, 3912, + 4095, 3062, 3909, + 4095, 3075, 3906, + 4095, 3091, 3902, + 4095, 3112, 3896, + 4095, 3138, 3888, + 4095, 3171, 3877, + 4095, 3212, 3862, + 4095, 3261, 3842, + 4095, 3320, 3813, + 4095, 3388, 3771, + 4085, 3465, 3707, + 4030, 3552, 3606, + 3943, 3647, 3421, + 3794, 3749, 2917, + 4095, 3155, 4051, + 4095, 3155, 4051, + 4095, 3155, 4051, + 4095, 3156, 4051, + 4095, 3156, 4051, + 4095, 3156, 4051, + 4095, 3156, 4050, + 4095, 3156, 4050, + 4095, 3157, 4050, + 4095, 3157, 4050, + 4095, 3158, 4050, + 4095, 3159, 4050, + 4095, 3161, 4049, + 4095, 3162, 4049, + 4095, 3165, 4048, + 4095, 3168, 4048, + 4095, 3172, 4047, + 4095, 3177, 4045, + 4095, 3185, 4044, + 4095, 3194, 4041, + 4095, 3207, 4038, + 4095, 3223, 4034, + 4095, 3244, 4028, + 4095, 3270, 4020, + 4095, 3303, 4009, + 4095, 3344, 3994, + 4095, 3393, 3974, + 4095, 3452, 3945, + 4095, 3520, 3903, + 4095, 3597, 3839, + 4095, 3684, 3738, + 4076, 3779, 3553, + 0, 494, 709, + 0, 513, 690, + 0, 537, 662, + 0, 567, 621, + 0, 604, 561, + 0, 650, 466, + 0, 705, 295, + 0, 770, 0, + 0, 843, 0, + 0, 927, 0, + 0, 1018, 0, + 0, 1118, 0, + 0, 1223, 0, + 0, 1335, 0, + 0, 1451, 0, + 0, 1571, 0, + 0, 1693, 0, + 0, 1818, 0, + 0, 1945, 0, + 0, 2073, 0, + 0, 2202, 0, + 0, 2332, 0, + 0, 2462, 0, + 0, 2593, 0, + 0, 2724, 0, + 0, 2855, 0, + 0, 2987, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 0, 500, 738, + 0, 519, 719, + 0, 543, 693, + 0, 572, 655, + 0, 610, 600, + 0, 655, 513, + 0, 709, 363, + 0, 773, 25, + 0, 846, 0, + 0, 929, 0, + 0, 1020, 0, + 0, 1119, 0, + 0, 1225, 0, + 0, 1336, 0, + 0, 1452, 0, + 0, 1571, 0, + 0, 1694, 0, + 0, 1819, 0, + 0, 1945, 0, + 0, 2073, 0, + 0, 2202, 0, + 0, 2332, 0, + 0, 2462, 0, + 0, 2593, 0, + 0, 2724, 0, + 0, 2855, 0, + 0, 2987, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 0, 509, 773, + 0, 527, 756, + 0, 550, 732, + 0, 580, 697, + 0, 616, 647, + 0, 661, 569, + 0, 715, 440, + 0, 778, 174, + 0, 850, 0, + 0, 932, 0, + 0, 1023, 0, + 0, 1121, 0, + 0, 1227, 0, + 0, 1337, 0, + 0, 1453, 0, + 0, 1572, 0, + 0, 1694, 0, + 0, 1819, 0, + 0, 1946, 0, + 0, 2073, 0, + 0, 2202, 0, + 0, 2332, 0, + 0, 2462, 0, + 0, 2593, 0, + 0, 2724, 0, + 0, 2855, 0, + 0, 2987, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 66, 520, 816, + 0, 538, 801, + 0, 561, 779, + 0, 589, 748, + 0, 625, 703, + 0, 669, 635, + 0, 722, 525, + 0, 784, 318, + 0, 856, 0, + 0, 937, 0, + 0, 1027, 0, + 0, 1124, 0, + 0, 1229, 0, + 0, 1339, 0, + 0, 1454, 0, + 0, 1573, 0, + 0, 1695, 0, + 0, 1820, 0, + 0, 1946, 0, + 0, 2074, 0, + 0, 2202, 0, + 0, 2332, 0, + 0, 2462, 0, + 0, 2593, 0, + 0, 2724, 0, + 0, 2855, 0, + 0, 2987, 0, + 0, 3118, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 429, 534, 868, + 379, 552, 854, + 302, 574, 835, + 173, 602, 808, + 0, 637, 769, + 0, 680, 711, + 0, 731, 620, + 0, 792, 459, + 0, 863, 78, + 0, 943, 0, + 0, 1031, 0, + 0, 1128, 0, + 0, 1232, 0, + 0, 1342, 0, + 0, 1456, 0, + 0, 1575, 0, + 0, 1696, 0, + 0, 1821, 0, + 0, 1947, 0, + 0, 2074, 0, + 0, 2203, 0, + 0, 2332, 0, + 0, 2463, 0, + 0, 2593, 0, + 0, 2724, 0, + 0, 2855, 0, + 0, 2987, 0, + 0, 3119, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 680, 553, 930, + 652, 570, 918, + 611, 591, 901, + 550, 618, 878, + 454, 652, 844, + 281, 693, 796, + 0, 743, 721, + 0, 803, 597, + 0, 872, 351, + 0, 950, 0, + 0, 1038, 0, + 0, 1133, 0, + 0, 1236, 0, + 0, 1345, 0, + 0, 1459, 0, + 0, 1577, 0, + 0, 1698, 0, + 0, 1822, 0, + 0, 1948, 0, + 0, 2075, 0, + 0, 2203, 0, + 0, 2333, 0, + 0, 2463, 0, + 0, 2593, 0, + 0, 2724, 0, + 0, 2856, 0, + 0, 2987, 0, + 0, 3119, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 884, 577, 1001, + 866, 593, 990, + 841, 613, 976, + 806, 639, 956, + 753, 671, 929, + 672, 711, 889, + 534, 759, 829, + 243, 817, 734, + 0, 884, 566, + 0, 960, 150, + 0, 1046, 0, + 0, 1140, 0, + 0, 1241, 0, + 0, 1349, 0, + 0, 1462, 0, + 0, 1579, 0, + 0, 1700, 0, + 0, 1823, 0, + 0, 1949, 0, + 0, 2076, 0, + 0, 2204, 0, + 0, 2333, 0, + 0, 2463, 0, + 0, 2594, 0, + 0, 2725, 0, + 0, 2856, 0, + 0, 2987, 0, + 0, 3119, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1063, 607, 1081, + 1051, 622, 1072, + 1035, 641, 1061, + 1012, 665, 1044, + 979, 696, 1022, + 932, 733, 989, + 859, 780, 942, + 739, 835, 870, + 505, 899, 751, + 0, 974, 520, + 0, 1057, 0, + 0, 1149, 0, + 0, 1249, 0, + 0, 1355, 0, + 0, 1466, 0, + 0, 1583, 0, + 0, 1702, 0, + 0, 1825, 0, + 0, 1950, 0, + 0, 2077, 0, + 0, 2205, 0, + 0, 2334, 0, + 0, 2464, 0, + 0, 2594, 0, + 0, 2725, 0, + 0, 2856, 0, + 0, 2987, 0, + 0, 3119, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1228, 644, 1170, + 1219, 658, 1163, + 1208, 676, 1153, + 1193, 698, 1140, + 1171, 727, 1122, + 1140, 762, 1096, + 1096, 805, 1059, + 1029, 858, 1005, + 919, 919, 919, + 715, 991, 773, + 63, 1071, 450, + 0, 1161, 0, + 0, 1258, 0, + 0, 1362, 0, + 0, 1472, 0, + 0, 1587, 0, + 0, 1706, 0, + 0, 1828, 0, + 0, 1952, 0, + 0, 2078, 0, + 0, 2206, 0, + 0, 2335, 0, + 0, 2464, 0, + 0, 2594, 0, + 0, 2725, 0, + 0, 2856, 0, + 0, 2987, 0, + 0, 3119, 0, + 0, 3251, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1383, 690, 1267, + 1377, 702, 1262, + 1369, 718, 1254, + 1358, 739, 1243, + 1343, 765, 1229, + 1322, 798, 1208, + 1293, 838, 1180, + 1250, 887, 1139, + 1187, 945, 1077, + 1084, 1013, 978, + 897, 1090, 801, + 377, 1176, 337, + 0, 1270, 0, + 0, 1372, 0, + 0, 1480, 0, + 0, 1593, 0, + 0, 1711, 0, + 0, 1831, 0, + 0, 1955, 0, + 0, 2080, 0, + 0, 2208, 0, + 0, 2336, 0, + 0, 2465, 0, + 0, 2595, 0, + 0, 2726, 0, + 0, 2857, 0, + 0, 2988, 0, + 0, 3119, 0, + 0, 3251, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1531, 745, 1371, + 1527, 756, 1367, + 1521, 770, 1361, + 1513, 788, 1352, + 1503, 812, 1341, + 1488, 841, 1325, + 1468, 878, 1303, + 1440, 923, 1272, + 1399, 977, 1227, + 1337, 1040, 1158, + 1239, 1113, 1047, + 1064, 1195, 835, + 609, 1286, 120, + 0, 1385, 0, + 0, 1490, 0, + 0, 1601, 0, + 0, 1717, 0, + 0, 1836, 0, + 0, 1958, 0, + 0, 2083, 0, + 0, 2210, 0, + 0, 2337, 0, + 0, 2466, 0, + 0, 2596, 0, + 0, 2726, 0, + 0, 2857, 0, + 0, 2988, 0, + 0, 3119, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3514, 0, + 0, 3646, 0, + 1675, 809, 1481, + 1672, 818, 1478, + 1668, 831, 1473, + 1662, 847, 1466, + 1655, 867, 1458, + 1644, 894, 1445, + 1630, 927, 1429, + 1610, 967, 1405, + 1582, 1016, 1372, + 1542, 1075, 1323, + 1483, 1143, 1249, + 1388, 1220, 1125, + 1220, 1307, 878, + 804, 1401, 0, + 0, 1503, 0, + 0, 1611, 0, + 0, 1725, 0, + 0, 1842, 0, + 0, 1963, 0, + 0, 2087, 0, + 0, 2212, 0, + 0, 2340, 0, + 0, 2468, 0, + 0, 2597, 0, + 0, 2727, 0, + 0, 2858, 0, + 0, 2989, 0, + 0, 3120, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3646, 0, + 1816, 882, 1596, + 1813, 890, 1593, + 1810, 901, 1590, + 1806, 915, 1585, + 1801, 933, 1578, + 1793, 955, 1569, + 1783, 984, 1556, + 1769, 1020, 1538, + 1750, 1064, 1514, + 1722, 1117, 1478, + 1683, 1179, 1427, + 1625, 1251, 1347, + 1532, 1333, 1212, + 1369, 1422, 929, + 978, 1520, 0, + 0, 1625, 0, + 0, 1735, 0, + 0, 1850, 0, + 0, 1969, 0, + 0, 2092, 0, + 0, 2216, 0, + 0, 2342, 0, + 0, 2470, 0, + 0, 2599, 0, + 0, 2728, 0, + 0, 2859, 0, + 0, 2989, 0, + 0, 3120, 0, + 0, 3252, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3647, 0, + 1954, 965, 1715, + 1952, 972, 1713, + 1950, 981, 1710, + 1947, 992, 1706, + 1943, 1007, 1701, + 1938, 1027, 1694, + 1930, 1052, 1684, + 1920, 1083, 1671, + 1906, 1121, 1653, + 1887, 1168, 1627, + 1860, 1224, 1590, + 1821, 1290, 1536, + 1764, 1365, 1452, + 1673, 1449, 1307, + 1514, 1542, 989, + 1139, 1642, 0, + 0, 1749, 0, + 0, 1861, 0, + 0, 1978, 0, + 0, 2098, 0, + 0, 2221, 0, + 0, 2346, 0, + 0, 2473, 0, + 0, 2601, 0, + 0, 2730, 0, + 0, 2860, 0, + 0, 2990, 0, + 0, 3121, 0, + 0, 3252, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3647, 0, + 2091, 1056, 1837, + 2090, 1062, 1835, + 2088, 1069, 1833, + 2086, 1079, 1830, + 2083, 1091, 1826, + 2079, 1108, 1821, + 2073, 1129, 1813, + 2066, 1155, 1803, + 2056, 1188, 1790, + 2042, 1229, 1771, + 2023, 1278, 1745, + 1997, 1337, 1707, + 1958, 1405, 1650, + 1901, 1483, 1562, + 1812, 1570, 1409, + 1655, 1664, 1059, + 1292, 1767, 0, + 0, 1875, 0, + 0, 1988, 0, + 0, 2106, 0, + 0, 2227, 0, + 0, 2351, 0, + 0, 2476, 0, + 0, 2604, 0, + 0, 2732, 0, + 0, 2861, 0, + 0, 2991, 0, + 0, 3122, 0, + 0, 3253, 0, + 0, 3384, 0, + 0, 3515, 0, + 0, 3647, 0, + 2227, 1156, 1961, + 2226, 1160, 1960, + 2224, 1166, 1958, + 2223, 1174, 1956, + 2221, 1184, 1953, + 2218, 1197, 1949, + 2214, 1214, 1943, + 2208, 1236, 1936, + 2201, 1264, 1926, + 2191, 1299, 1912, + 2177, 1342, 1893, + 2158, 1393, 1866, + 2132, 1454, 1827, + 2094, 1524, 1769, + 2037, 1604, 1678, + 1948, 1693, 1517, + 1794, 1789, 1139, + 1439, 1893, 0, + 0, 2002, 0, + 0, 2117, 0, + 0, 2235, 0, + 0, 2357, 0, + 0, 2481, 0, + 0, 2607, 0, + 0, 2735, 0, + 0, 2863, 0, + 0, 2993, 0, + 0, 3123, 0, + 0, 3254, 0, + 0, 3385, 0, + 0, 3516, 0, + 0, 3647, 0, + 2361, 1261, 2087, + 2361, 1265, 2086, + 2360, 1270, 2085, + 2358, 1276, 2083, + 2357, 1284, 2081, + 2355, 1295, 2078, + 2352, 1309, 2074, + 2348, 1327, 2068, + 2342, 1349, 2061, + 2335, 1378, 2050, + 2325, 1415, 2036, + 2312, 1459, 2017, + 2293, 1512, 1989, + 2266, 1574, 1949, + 2228, 1646, 1890, + 2172, 1728, 1797, + 2084, 1818, 1631, + 1931, 1916, 1227, + 1581, 2021, 0, + 0, 2131, 0, + 0, 2246, 0, + 0, 2365, 0, + 0, 2488, 0, + 0, 2612, 0, + 0, 2738, 0, + 0, 2866, 0, + 0, 2995, 0, + 0, 3125, 0, + 0, 3255, 0, + 0, 3386, 0, + 0, 3517, 0, + 0, 3648, 0, + 2495, 1373, 2215, + 2495, 1376, 2214, + 2494, 1379, 2213, + 2493, 1384, 2212, + 2492, 1391, 2210, + 2490, 1399, 2208, + 2488, 1410, 2205, + 2485, 1424, 2201, + 2481, 1443, 2195, + 2476, 1467, 2187, + 2469, 1497, 2177, + 2459, 1534, 2163, + 2445, 1579, 2143, + 2427, 1634, 2115, + 2400, 1698, 2074, + 2362, 1771, 2014, + 2306, 1854, 1919, + 2219, 1945, 1749, + 2066, 2044, 1323, + 1721, 2149, 0, + 0, 2261, 0, + 0, 2376, 0, + 0, 2496, 0, + 0, 2619, 0, + 0, 2743, 0, + 0, 2870, 0, + 0, 2998, 0, + 0, 3127, 0, + 0, 3256, 0, + 0, 3387, 0, + 0, 3517, 0, + 0, 3649, 0, + 2629, 1489, 2343, + 2628, 1491, 2343, + 2628, 1494, 2342, + 2627, 1497, 2341, + 2626, 1503, 2340, + 2625, 1509, 2338, + 2623, 1518, 2336, + 2621, 1529, 2333, + 2618, 1544, 2329, + 2614, 1563, 2323, + 2609, 1588, 2315, + 2602, 1618, 2305, + 2592, 1656, 2290, + 2579, 1703, 2270, + 2560, 1758, 2242, + 2534, 1823, 2201, + 2496, 1897, 2140, + 2440, 1981, 2043, + 2353, 2073, 1870, + 2201, 2173, 1427, + 1859, 2279, 0, + 0, 2391, 0, + 0, 2507, 0, + 0, 2627, 0, + 0, 2750, 0, + 0, 2875, 0, + 0, 3001, 0, + 0, 3129, 0, + 0, 3258, 0, + 0, 3388, 0, + 0, 3519, 0, + 0, 3649, 0, + 2762, 1608, 2473, + 2762, 1610, 2473, + 2761, 1612, 2472, + 2761, 1615, 2471, + 2760, 1619, 2470, + 2759, 1624, 2469, + 2758, 1631, 2467, + 2756, 1640, 2465, + 2754, 1652, 2462, + 2751, 1667, 2458, + 2747, 1686, 2452, + 2742, 1711, 2444, + 2735, 1742, 2434, + 2725, 1781, 2419, + 2712, 1828, 2399, + 2693, 1884, 2370, + 2667, 1950, 2329, + 2629, 2025, 2268, + 2573, 2109, 2170, + 2486, 2202, 1993, + 2335, 2302, 1536, + 1996, 2409, 0, + 0, 2521, 0, + 0, 2638, 0, + 0, 2758, 0, + 0, 2881, 0, + 0, 3006, 0, + 0, 3133, 0, + 0, 3261, 0, + 0, 3390, 0, + 0, 3520, 0, + 0, 3651, 0, + 2895, 1731, 2603, + 2895, 1732, 2603, + 2894, 1734, 2602, + 2894, 1736, 2602, + 2893, 1739, 2601, + 2893, 1743, 2600, + 2892, 1748, 2599, + 2891, 1755, 2597, + 2889, 1764, 2595, + 2887, 1776, 2592, + 2884, 1791, 2587, + 2880, 1811, 2582, + 2875, 1836, 2574, + 2868, 1868, 2563, + 2858, 1907, 2549, + 2844, 1955, 2528, + 2826, 2012, 2500, + 2800, 2078, 2458, + 2762, 2154, 2396, + 2706, 2239, 2298, + 2619, 2332, 2119, + 2469, 2433, 1651, + 2131, 2540, 0, + 0, 2652, 0, + 0, 2769, 0, + 0, 2890, 0, + 0, 3013, 0, + 0, 3138, 0, + 0, 3265, 0, + 0, 3393, 0, + 0, 3522, 0, + 0, 3652, 0, + 3028, 1856, 2734, + 3027, 1857, 2734, + 3027, 1858, 2733, + 3027, 1860, 2733, + 3027, 1862, 2732, + 3026, 1865, 2732, + 3025, 1869, 2731, + 3024, 1874, 2729, + 3023, 1881, 2728, + 3022, 1890, 2725, + 3019, 1902, 2722, + 3017, 1918, 2718, + 3013, 1938, 2712, + 3007, 1964, 2704, + 3000, 1996, 2694, + 2990, 2035, 2679, + 2977, 2083, 2658, + 2958, 2140, 2630, + 2932, 2207, 2588, + 2895, 2283, 2526, + 2839, 2369, 2426, + 2752, 2462, 2246, + 2602, 2563, 1769, + 2265, 2671, 0, + 0, 2784, 0, + 0, 2901, 0, + 0, 3021, 0, + 0, 3144, 0, + 0, 3270, 0, + 0, 3397, 0, + 0, 3525, 0, + 0, 3654, 0, + 3160, 1982, 2865, + 3160, 1983, 2865, + 3160, 1984, 2864, + 3160, 1985, 2864, + 3159, 1987, 2864, + 3159, 1989, 2863, + 3158, 1992, 2862, + 3158, 1996, 2861, + 3157, 2002, 2860, + 3156, 2009, 2858, + 3154, 2018, 2856, + 3152, 2030, 2853, + 3149, 2046, 2849, + 3145, 2066, 2843, + 3140, 2092, 2835, + 3133, 2124, 2824, + 3123, 2164, 2810, + 3109, 2212, 2789, + 3091, 2270, 2760, + 3065, 2337, 2719, + 3027, 2414, 2656, + 2972, 2499, 2556, + 2885, 2593, 2375, + 2735, 2695, 1890, + 2399, 2802, 0, + 0, 2915, 0, + 0, 3032, 0, + 0, 3153, 0, + 0, 3276, 0, + 0, 3402, 0, + 0, 3529, 0, + 0, 3657, 0, + 3292, 2110, 2996, + 3292, 2111, 2996, + 3292, 2111, 2996, + 3292, 2112, 2996, + 3292, 2114, 2995, + 3292, 2116, 2995, + 3291, 2118, 2994, + 3291, 2121, 2994, + 3290, 2125, 2993, + 3289, 2130, 2991, + 3288, 2138, 2990, + 3286, 2147, 2987, + 3284, 2159, 2984, + 3281, 2175, 2980, + 3277, 2195, 2974, + 3272, 2221, 2966, + 3265, 2254, 2955, + 3255, 2294, 2941, + 3242, 2342, 2920, + 3223, 2400, 2891, + 3197, 2467, 2849, + 3160, 2544, 2787, + 3104, 2630, 2686, + 3018, 2724, 2504, + 2868, 2826, 2015, + 2533, 2934, 0, + 0, 3047, 0, + 0, 3164, 0, + 0, 3285, 0, + 0, 3408, 0, + 0, 3534, 0, + 0, 3661, 0, + 3425, 2239, 3128, + 3425, 2240, 3127, + 3425, 2240, 3127, + 3425, 2241, 3127, + 3424, 2242, 3127, + 3424, 2243, 3127, + 3424, 2245, 3126, + 3424, 2247, 3126, + 3423, 2250, 3125, + 3422, 2254, 3124, + 3421, 2260, 3123, + 3420, 2267, 3121, + 3419, 2276, 3119, + 3417, 2289, 3115, + 3414, 2305, 3111, + 3410, 2325, 3105, + 3404, 2351, 3097, + 3397, 2384, 3087, + 3387, 2424, 3072, + 3374, 2473, 3051, + 3355, 2531, 3022, + 3329, 2598, 2980, + 3292, 2675, 2918, + 3237, 2761, 2817, + 3150, 2856, 2634, + 3000, 2957, 2141, + 2666, 3065, 0, + 0, 3178, 0, + 0, 3296, 0, + 0, 3417, 0, + 0, 3540, 0, + 0, 3666, 0, + 3557, 2369, 3259, + 3557, 2369, 3259, + 3557, 2370, 3259, + 3557, 2370, 3259, + 3557, 2371, 3259, + 3557, 2372, 3259, + 3556, 2373, 3258, + 3556, 2375, 3258, + 3556, 2377, 3257, + 3555, 2380, 3257, + 3555, 2385, 3256, + 3554, 2390, 3254, + 3553, 2397, 3252, + 3551, 2407, 3250, + 3549, 2419, 3247, + 3546, 2435, 3243, + 3542, 2456, 3237, + 3537, 2482, 3229, + 3529, 2514, 3218, + 3520, 2555, 3203, + 3506, 2604, 3183, + 3488, 2662, 3154, + 3462, 2729, 3112, + 3424, 2807, 3049, + 3369, 2893, 2948, + 3282, 2987, 2765, + 3133, 3089, 2268, + 2799, 3197, 0, + 0, 3310, 0, + 0, 3428, 0, + 0, 3549, 0, + 0, 3672, 0, + 3689, 2499, 3391, + 3689, 2499, 3391, + 3689, 2500, 3391, + 3689, 2500, 3391, + 3689, 2501, 3391, + 3689, 2501, 3390, + 3689, 2502, 3390, + 3689, 2504, 3390, + 3688, 2506, 3390, + 3688, 2508, 3389, + 3687, 2511, 3388, + 3687, 2515, 3387, + 3686, 2521, 3386, + 3685, 2528, 3384, + 3683, 2537, 3382, + 3681, 2550, 3379, + 3678, 2566, 3374, + 3674, 2586, 3369, + 3669, 2613, 3361, + 3662, 2645, 3350, + 3652, 2686, 3335, + 3639, 2735, 3314, + 3620, 2793, 3285, + 3594, 2861, 3243, + 3556, 2938, 3180, + 3501, 3024, 3079, + 3415, 3119, 2896, + 3265, 3221, 2397, + 2931, 3329, 0, + 0, 3442, 0, + 0, 3560, 0, + 0, 3681, 0, + 3822, 2630, 3523, + 3822, 2630, 3523, + 3821, 2630, 3523, + 3821, 2631, 3523, + 3821, 2631, 3523, + 3821, 2632, 3522, + 3821, 2632, 3522, + 3821, 2633, 3522, + 3821, 2635, 3522, + 3821, 2637, 3521, + 3820, 2639, 3521, + 3820, 2642, 3520, + 3819, 2646, 3519, + 3818, 2652, 3518, + 3817, 2659, 3516, + 3815, 2668, 3514, + 3813, 2681, 3510, + 3810, 2697, 3506, + 3806, 2717, 3500, + 3801, 2744, 3492, + 3794, 2777, 3482, + 3784, 2817, 3467, + 3771, 2866, 3446, + 3752, 2925, 3417, + 3726, 2992, 3375, + 3689, 3070, 3312, + 3633, 3156, 3211, + 3547, 3251, 3027, + 3398, 3353, 2526, + 3064, 3461, 0, + 0, 3574, 0, + 0, 3692, 0, + 3954, 2761, 3655, + 3954, 2761, 3655, + 3954, 2761, 3655, + 3954, 2762, 3655, + 3954, 2762, 3655, + 3954, 2762, 3654, + 3953, 2763, 3654, + 3953, 2764, 3654, + 3953, 2765, 3654, + 3953, 2766, 3654, + 3953, 2768, 3653, + 3952, 2770, 3653, + 3952, 2773, 3652, + 3951, 2777, 3651, + 3950, 2783, 3650, + 3949, 2790, 3648, + 3947, 2800, 3645, + 3945, 2812, 3642, + 3942, 2828, 3638, + 3938, 2849, 3632, + 3933, 2875, 3624, + 3926, 2908, 3614, + 3916, 2949, 3599, + 3903, 2998, 3578, + 3884, 3056, 3549, + 3858, 3124, 3507, + 3821, 3202, 3444, + 3766, 3288, 3343, + 3679, 3383, 3158, + 3530, 3485, 2656, + 3196, 3593, 0, + 0, 3706, 0, + 4086, 2892, 3787, + 4086, 2893, 3787, + 4086, 2893, 3787, + 4086, 2893, 3787, + 4086, 2893, 3787, + 4086, 2893, 3786, + 4086, 2894, 3786, + 4086, 2894, 3786, + 4085, 2895, 3786, + 4085, 2896, 3786, + 4085, 2897, 3786, + 4085, 2899, 3785, + 4084, 2902, 3785, + 4084, 2905, 3784, + 4083, 2909, 3783, + 4082, 2914, 3782, + 4081, 2922, 3780, + 4080, 2931, 3777, + 4077, 2944, 3774, + 4075, 2960, 3770, + 4071, 2980, 3764, + 4065, 3007, 3756, + 4058, 3040, 3745, + 4048, 3080, 3731, + 4035, 3130, 3710, + 4016, 3188, 3681, + 3990, 3256, 3639, + 3953, 3333, 3575, + 3898, 3420, 3474, + 3811, 3515, 3290, + 3662, 3617, 2787, + 3328, 3725, 0, + 4095, 3024, 3919, + 4095, 3024, 3919, + 4095, 3024, 3919, + 4095, 3024, 3919, + 4095, 3024, 3919, + 4095, 3025, 3919, + 4095, 3025, 3918, + 4095, 3025, 3918, + 4095, 3026, 3918, + 4095, 3027, 3918, + 4095, 3028, 3918, + 4095, 3029, 3918, + 4095, 3031, 3917, + 4095, 3033, 3917, + 4095, 3036, 3916, + 4095, 3040, 3915, + 4095, 3046, 3914, + 4095, 3053, 3912, + 4095, 3063, 3909, + 4095, 3075, 3906, + 4095, 3091, 3902, + 4095, 3112, 3896, + 4095, 3138, 3888, + 4095, 3171, 3877, + 4095, 3212, 3863, + 4095, 3261, 3842, + 4095, 3320, 3813, + 4095, 3388, 3771, + 4085, 3465, 3707, + 4030, 3552, 3606, + 3943, 3647, 3422, + 3794, 3749, 2918, + 4095, 3156, 4051, + 4095, 3156, 4051, + 4095, 3156, 4051, + 4095, 3156, 4051, + 4095, 3156, 4051, + 4095, 3156, 4051, + 4095, 3156, 4051, + 4095, 3157, 4050, + 4095, 3157, 4050, + 4095, 3158, 4050, + 4095, 3158, 4050, + 4095, 3159, 4050, + 4095, 3161, 4050, + 4095, 3163, 4049, + 4095, 3165, 4049, + 4095, 3168, 4048, + 4095, 3172, 4047, + 4095, 3178, 4046, + 4095, 3185, 4044, + 4095, 3195, 4041, + 4095, 3207, 4038, + 4095, 3223, 4034, + 4095, 3244, 4028, + 4095, 3270, 4020, + 4095, 3303, 4009, + 4095, 3344, 3995, + 4095, 3393, 3974, + 4095, 3452, 3945, + 4095, 3520, 3903, + 4095, 3597, 3839, + 4095, 3684, 3738, + 4076, 3779, 3553, + 0, 606, 834, + 0, 621, 819, + 0, 640, 798, + 0, 664, 769, + 0, 695, 726, + 0, 733, 662, + 0, 779, 559, + 0, 834, 370, + 0, 899, 0, + 0, 973, 0, + 0, 1057, 0, + 0, 1149, 0, + 0, 1248, 0, + 0, 1355, 0, + 0, 1466, 0, + 0, 1583, 0, + 0, 1702, 0, + 0, 1825, 0, + 0, 1950, 0, + 0, 2077, 0, + 0, 2205, 0, + 0, 2334, 0, + 0, 2464, 0, + 0, 2594, 0, + 0, 2725, 0, + 0, 2856, 0, + 0, 2987, 0, + 0, 3119, 0, + 0, 3250, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 0, 611, 856, + 0, 626, 842, + 0, 645, 822, + 0, 669, 794, + 0, 699, 753, + 0, 737, 693, + 0, 782, 598, + 0, 837, 427, + 0, 902, 2, + 0, 976, 0, + 0, 1059, 0, + 0, 1150, 0, + 0, 1250, 0, + 0, 1356, 0, + 0, 1467, 0, + 0, 1583, 0, + 0, 1703, 0, + 0, 1825, 0, + 0, 1950, 0, + 0, 2077, 0, + 0, 2205, 0, + 0, 2334, 0, + 0, 2464, 0, + 0, 2594, 0, + 0, 2725, 0, + 0, 2856, 0, + 0, 2987, 0, + 0, 3119, 0, + 0, 3251, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 0, 618, 883, + 0, 632, 870, + 0, 651, 851, + 0, 675, 825, + 0, 705, 788, + 0, 742, 732, + 0, 787, 645, + 0, 841, 495, + 0, 905, 157, + 0, 979, 0, + 0, 1061, 0, + 0, 1152, 0, + 0, 1251, 0, + 0, 1357, 0, + 0, 1468, 0, + 0, 1584, 0, + 0, 1703, 0, + 0, 1826, 0, + 0, 1951, 0, + 0, 2077, 0, + 0, 2205, 0, + 0, 2334, 0, + 0, 2464, 0, + 0, 2594, 0, + 0, 2725, 0, + 0, 2856, 0, + 0, 2987, 0, + 0, 3119, 0, + 0, 3251, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 0, 627, 918, + 0, 641, 905, + 0, 659, 888, + 0, 682, 864, + 0, 712, 829, + 0, 748, 779, + 0, 793, 702, + 0, 847, 572, + 0, 910, 306, + 0, 983, 0, + 0, 1064, 0, + 0, 1155, 0, + 0, 1253, 0, + 0, 1359, 0, + 0, 1469, 0, + 0, 1585, 0, + 0, 1704, 0, + 0, 1827, 0, + 0, 1951, 0, + 0, 2078, 0, + 0, 2205, 0, + 0, 2334, 0, + 0, 2464, 0, + 0, 2594, 0, + 0, 2725, 0, + 0, 2856, 0, + 0, 2987, 0, + 0, 3119, 0, + 0, 3251, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 271, 638, 960, + 198, 652, 948, + 78, 670, 933, + 0, 693, 911, + 0, 721, 880, + 0, 757, 835, + 0, 801, 768, + 0, 854, 657, + 0, 916, 450, + 0, 988, 0, + 0, 1069, 0, + 0, 1159, 0, + 0, 1256, 0, + 0, 1361, 0, + 0, 1471, 0, + 0, 1586, 0, + 0, 1705, 0, + 0, 1827, 0, + 0, 1952, 0, + 0, 2078, 0, + 0, 2206, 0, + 0, 2335, 0, + 0, 2464, 0, + 0, 2594, 0, + 0, 2725, 0, + 0, 2856, 0, + 0, 2987, 0, + 0, 3119, 0, + 0, 3251, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 595, 653, 1011, + 561, 667, 1000, + 511, 684, 986, + 434, 706, 967, + 305, 734, 940, + 43, 769, 901, + 0, 812, 843, + 0, 863, 752, + 0, 924, 591, + 0, 995, 210, + 0, 1075, 0, + 0, 1164, 0, + 0, 1260, 0, + 0, 1364, 0, + 0, 1474, 0, + 0, 1588, 0, + 0, 1707, 0, + 0, 1829, 0, + 0, 1953, 0, + 0, 2079, 0, + 0, 2206, 0, + 0, 2335, 0, + 0, 2464, 0, + 0, 2595, 0, + 0, 2725, 0, + 0, 2856, 0, + 0, 2988, 0, + 0, 3119, 0, + 0, 3251, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 832, 672, 1071, + 812, 685, 1062, + 784, 702, 1050, + 743, 723, 1033, + 682, 750, 1010, + 586, 784, 976, + 413, 825, 928, + 0, 875, 853, + 0, 935, 729, + 0, 1004, 483, + 0, 1082, 0, + 0, 1170, 0, + 0, 1265, 0, + 0, 1368, 0, + 0, 1477, 0, + 0, 1591, 0, + 0, 1709, 0, + 0, 1830, 0, + 0, 1954, 0, + 0, 2080, 0, + 0, 2207, 0, + 0, 2335, 0, + 0, 2465, 0, + 0, 2595, 0, + 0, 2725, 0, + 0, 2856, 0, + 0, 2988, 0, + 0, 3119, 0, + 0, 3251, 0, + 0, 3382, 0, + 0, 3514, 0, + 0, 3646, 0, + 1029, 697, 1140, + 1016, 709, 1133, + 998, 725, 1122, + 973, 745, 1108, + 938, 771, 1089, + 885, 803, 1061, + 804, 843, 1021, + 666, 891, 961, + 375, 949, 866, + 0, 1016, 698, + 0, 1093, 282, + 0, 1178, 0, + 0, 1272, 0, + 0, 1374, 0, + 0, 1481, 0, + 0, 1594, 0, + 0, 1711, 0, + 0, 1832, 0, + 0, 1955, 0, + 0, 2081, 0, + 0, 2208, 0, + 0, 2336, 0, + 0, 2465, 0, + 0, 2595, 0, + 0, 2726, 0, + 0, 2857, 0, + 0, 2988, 0, + 0, 3119, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3514, 0, + 0, 3646, 0, + 1204, 728, 1220, + 1195, 739, 1213, + 1183, 754, 1205, + 1167, 773, 1193, + 1144, 797, 1176, + 1111, 828, 1154, + 1064, 866, 1121, + 991, 912, 1074, + 872, 967, 1002, + 637, 1032, 883, + 0, 1106, 652, + 0, 1189, 0, + 0, 1281, 0, + 0, 1381, 0, + 0, 1487, 0, + 0, 1599, 0, + 0, 1715, 0, + 0, 1835, 0, + 0, 1957, 0, + 0, 2082, 0, + 0, 2209, 0, + 0, 2337, 0, + 0, 2466, 0, + 0, 2596, 0, + 0, 2726, 0, + 0, 2857, 0, + 0, 2988, 0, + 0, 3119, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3514, 0, + 0, 3646, 0, + 1366, 766, 1308, + 1360, 777, 1302, + 1352, 790, 1295, + 1340, 808, 1286, + 1325, 830, 1272, + 1303, 859, 1254, + 1272, 894, 1228, + 1228, 938, 1191, + 1161, 990, 1137, + 1052, 1052, 1052, + 847, 1123, 905, + 195, 1203, 583, + 0, 1293, 0, + 0, 1390, 0, + 0, 1494, 0, + 0, 1604, 0, + 0, 1719, 0, + 0, 1838, 0, + 0, 1960, 0, + 0, 2084, 0, + 0, 2210, 0, + 0, 2338, 0, + 0, 2467, 0, + 0, 2596, 0, + 0, 2727, 0, + 0, 2857, 0, + 0, 2988, 0, + 0, 3120, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3514, 0, + 0, 3646, 0, + 1519, 813, 1404, + 1515, 822, 1399, + 1509, 834, 1394, + 1501, 850, 1386, + 1490, 871, 1375, + 1475, 897, 1361, + 1454, 930, 1341, + 1425, 970, 1312, + 1383, 1019, 1271, + 1319, 1077, 1209, + 1216, 1145, 1110, + 1029, 1222, 933, + 509, 1308, 469, + 0, 1402, 0, + 0, 1504, 0, + 0, 1612, 0, + 0, 1725, 0, + 0, 1843, 0, + 0, 1963, 0, + 0, 2087, 0, + 0, 2213, 0, + 0, 2340, 0, + 0, 2468, 0, + 0, 2597, 0, + 0, 2727, 0, + 0, 2858, 0, + 0, 2989, 0, + 0, 3120, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3646, 0, + 1666, 868, 1507, + 1663, 877, 1504, + 1659, 888, 1499, + 1653, 902, 1493, + 1645, 920, 1484, + 1635, 944, 1473, + 1620, 973, 1457, + 1600, 1010, 1435, + 1572, 1055, 1404, + 1531, 1109, 1359, + 1469, 1172, 1290, + 1372, 1245, 1179, + 1196, 1327, 967, + 741, 1418, 252, + 0, 1517, 0, + 0, 1622, 0, + 0, 1733, 0, + 0, 1849, 0, + 0, 1968, 0, + 0, 2091, 0, + 0, 2215, 0, + 0, 2342, 0, + 0, 2470, 0, + 0, 2598, 0, + 0, 2728, 0, + 0, 2858, 0, + 0, 2989, 0, + 0, 3120, 0, + 0, 3252, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3647, 0, + 1809, 933, 1616, + 1807, 941, 1613, + 1804, 950, 1610, + 1800, 963, 1605, + 1794, 979, 1599, + 1787, 999, 1590, + 1776, 1026, 1578, + 1762, 1059, 1561, + 1742, 1099, 1537, + 1715, 1148, 1504, + 1675, 1207, 1455, + 1615, 1275, 1381, + 1520, 1352, 1257, + 1352, 1439, 1010, + 936, 1533, 0, + 0, 1635, 0, + 0, 1743, 0, + 0, 1857, 0, + 0, 1974, 0, + 0, 2095, 0, + 0, 2219, 0, + 0, 2344, 0, + 0, 2472, 0, + 0, 2600, 0, + 0, 2729, 0, + 0, 2859, 0, + 0, 2990, 0, + 0, 3121, 0, + 0, 3252, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3647, 0, + 1949, 1008, 1730, + 1948, 1014, 1728, + 1946, 1022, 1725, + 1943, 1033, 1722, + 1938, 1047, 1717, + 1933, 1065, 1710, + 1925, 1088, 1701, + 1915, 1116, 1688, + 1901, 1152, 1670, + 1882, 1196, 1646, + 1855, 1249, 1610, + 1815, 1312, 1559, + 1757, 1383, 1479, + 1664, 1465, 1344, + 1501, 1555, 1061, + 1110, 1652, 0, + 0, 1757, 0, + 0, 1867, 0, + 0, 1983, 0, + 0, 2102, 0, + 0, 2224, 0, + 0, 2348, 0, + 0, 2474, 0, + 0, 2602, 0, + 0, 2731, 0, + 0, 2860, 0, + 0, 2991, 0, + 0, 3121, 0, + 0, 3252, 0, + 0, 3384, 0, + 0, 3515, 0, + 0, 3647, 0, + 2087, 1092, 1849, + 2086, 1097, 1847, + 2085, 1104, 1845, + 2082, 1113, 1842, + 2079, 1124, 1838, + 2075, 1140, 1833, + 2070, 1159, 1826, + 2062, 1184, 1816, + 2052, 1215, 1803, + 2039, 1254, 1785, + 2019, 1300, 1759, + 1992, 1357, 1722, + 1954, 1422, 1668, + 1896, 1497, 1584, + 1805, 1581, 1439, + 1646, 1674, 1121, + 1271, 1774, 0, + 0, 1881, 0, + 0, 1993, 0, + 0, 2110, 0, + 0, 2230, 0, + 0, 2353, 0, + 0, 2478, 0, + 0, 2605, 0, + 0, 2733, 0, + 0, 2862, 0, + 0, 2992, 0, + 0, 3122, 0, + 0, 3253, 0, + 0, 3384, 0, + 0, 3516, 0, + 0, 3647, 0, + 2224, 1184, 1970, + 2223, 1189, 1969, + 2222, 1194, 1967, + 2220, 1201, 1965, + 2218, 1211, 1962, + 2215, 1224, 1958, + 2211, 1240, 1953, + 2206, 1261, 1945, + 2198, 1287, 1936, + 2188, 1320, 1922, + 2175, 1361, 1903, + 2156, 1410, 1877, + 2129, 1469, 1839, + 2090, 1537, 1782, + 2033, 1615, 1694, + 1944, 1702, 1541, + 1787, 1797, 1191, + 1424, 1899, 0, + 0, 2007, 0, + 0, 2121, 0, + 0, 2238, 0, + 0, 2359, 0, + 0, 2483, 0, + 0, 2608, 0, + 0, 2736, 0, + 0, 2864, 0, + 0, 2993, 0, + 0, 3123, 0, + 0, 3254, 0, + 0, 3385, 0, + 0, 3516, 0, + 0, 3648, 0, + 2359, 1284, 2094, + 2359, 1288, 2093, + 2358, 1292, 2092, + 2357, 1298, 2090, + 2355, 1306, 2088, + 2353, 1316, 2085, + 2350, 1329, 2081, + 2346, 1346, 2075, + 2340, 1368, 2068, + 2333, 1396, 2058, + 2323, 1431, 2044, + 2309, 1474, 2025, + 2291, 1525, 1998, + 2264, 1586, 1959, + 2226, 1656, 1901, + 2169, 1736, 1810, + 2080, 1825, 1649, + 1926, 1921, 1271, + 1571, 2025, 0, + 0, 2135, 0, + 0, 2249, 0, + 0, 2368, 0, + 0, 2489, 0, + 0, 2613, 0, + 0, 2739, 0, + 0, 2867, 0, + 0, 2995, 0, + 0, 3125, 0, + 0, 3255, 0, + 0, 3386, 0, + 0, 3517, 0, + 0, 3648, 0, + 2494, 1391, 2220, + 2493, 1393, 2219, + 2493, 1397, 2218, + 2492, 1402, 2217, + 2491, 1408, 2215, + 2489, 1416, 2213, + 2487, 1427, 2210, + 2484, 1441, 2206, + 2480, 1459, 2200, + 2474, 1482, 2193, + 2467, 1511, 2183, + 2457, 1547, 2168, + 2444, 1591, 2149, + 2425, 1644, 2121, + 2398, 1706, 2082, + 2361, 1779, 2022, + 2304, 1860, 1929, + 2216, 1950, 1763, + 2063, 2048, 1359, + 1714, 2153, 0, + 0, 2263, 0, + 0, 2378, 0, + 0, 2498, 0, + 0, 2620, 0, + 0, 2744, 0, + 0, 2871, 0, + 0, 2998, 0, + 0, 3127, 0, + 0, 3257, 0, + 0, 3387, 0, + 0, 3518, 0, + 0, 3649, 0, + 2628, 1503, 2347, + 2627, 1505, 2347, + 2627, 1508, 2346, + 2626, 1511, 2345, + 2625, 1516, 2344, + 2624, 1523, 2342, + 2622, 1531, 2340, + 2620, 1542, 2337, + 2617, 1557, 2333, + 2613, 1575, 2327, + 2608, 1599, 2319, + 2601, 1629, 2309, + 2591, 1666, 2295, + 2577, 1711, 2275, + 2559, 1766, 2247, + 2532, 1830, 2207, + 2495, 1903, 2146, + 2438, 1986, 2051, + 2351, 2077, 1881, + 2199, 2176, 1456, + 1853, 2281, 0, + 0, 2393, 0, + 0, 2509, 0, + 0, 2628, 0, + 0, 2751, 0, + 0, 2875, 0, + 0, 3002, 0, + 0, 3130, 0, + 0, 3259, 0, + 0, 3388, 0, + 0, 3519, 0, + 0, 3650, 0, + 2761, 1619, 2476, + 2761, 1621, 2476, + 2760, 1623, 2475, + 2760, 1626, 2474, + 2759, 1630, 2473, + 2758, 1635, 2472, + 2757, 1641, 2470, + 2756, 1650, 2468, + 2753, 1661, 2465, + 2750, 1676, 2461, + 2747, 1695, 2455, + 2741, 1720, 2447, + 2734, 1750, 2437, + 2724, 1788, 2422, + 2711, 1835, 2402, + 2692, 1890, 2374, + 2666, 1955, 2333, + 2628, 2029, 2272, + 2572, 2113, 2176, + 2485, 2205, 2002, + 2333, 2305, 1559, + 1991, 2411, 0, + 0, 2523, 0, + 0, 2639, 0, + 0, 2759, 0, + 0, 2882, 0, + 0, 3007, 0, + 0, 3134, 0, + 0, 3262, 0, + 0, 3391, 0, + 0, 3520, 0, + 0, 3651, 0, + 2894, 1739, 2605, + 2894, 1740, 2605, + 2894, 1742, 2605, + 2893, 1744, 2604, + 2893, 1747, 2603, + 2892, 1751, 2602, + 2891, 1756, 2601, + 2890, 1763, 2599, + 2888, 1772, 2597, + 2886, 1784, 2594, + 2883, 1799, 2590, + 2879, 1818, 2584, + 2874, 1843, 2576, + 2867, 1874, 2566, + 2857, 1913, 2551, + 2844, 1960, 2531, + 2825, 2016, 2502, + 2799, 2082, 2461, + 2761, 2157, 2400, + 2705, 2241, 2302, + 2618, 2334, 2125, + 2468, 2434, 1668, + 2128, 2541, 0, + 0, 2653, 0, + 0, 2770, 0, + 0, 2890, 0, + 0, 3013, 0, + 0, 3138, 0, + 0, 3265, 0, + 0, 3393, 0, + 0, 3522, 0, + 0, 3652, 0, + 3027, 1862, 2735, + 3027, 1863, 2735, + 3027, 1864, 2735, + 3026, 1866, 2735, + 3026, 1868, 2734, + 3026, 1871, 2733, + 3025, 1875, 2732, + 3024, 1880, 2731, + 3023, 1887, 2729, + 3021, 1896, 2727, + 3019, 1908, 2724, + 3016, 1924, 2720, + 3012, 1943, 2714, + 3007, 1969, 2706, + 3000, 2000, 2695, + 2990, 2039, 2681, + 2976, 2087, 2660, + 2958, 2144, 2632, + 2932, 2210, 2590, + 2894, 2286, 2528, + 2838, 2371, 2430, + 2752, 2464, 2251, + 2601, 2565, 1783, + 2263, 2672, 0, + 0, 2784, 0, + 0, 2901, 0, + 0, 3022, 0, + 0, 3145, 0, + 0, 3270, 0, + 0, 3397, 0, + 0, 3525, 0, + 0, 3654, 0, + 3160, 1987, 2866, + 3160, 1988, 2866, + 3159, 1989, 2866, + 3159, 1990, 2865, + 3159, 1992, 2865, + 3159, 1994, 2864, + 3158, 1997, 2864, + 3157, 2001, 2863, + 3157, 2006, 2861, + 3155, 2013, 2860, + 3154, 2023, 2857, + 3152, 2035, 2854, + 3149, 2050, 2850, + 3145, 2070, 2844, + 3139, 2096, 2836, + 3132, 2128, 2826, + 3122, 2167, 2811, + 3109, 2215, 2791, + 3090, 2272, 2762, + 3064, 2339, 2720, + 3027, 2415, 2658, + 2971, 2501, 2558, + 2884, 2594, 2378, + 2734, 2696, 1901, + 2397, 2803, 0, + 0, 2916, 0, + 0, 3033, 0, + 0, 3153, 0, + 0, 3277, 0, + 0, 3402, 0, + 0, 3529, 0, + 0, 3657, 0, + 3292, 2114, 2997, + 3292, 2114, 2997, + 3292, 2115, 2997, + 3292, 2116, 2997, + 3292, 2117, 2996, + 3291, 2119, 2996, + 3291, 2121, 2995, + 3291, 2124, 2995, + 3290, 2128, 2994, + 3289, 2134, 2992, + 3288, 2141, 2990, + 3286, 2150, 2988, + 3284, 2162, 2985, + 3281, 2178, 2981, + 3277, 2198, 2975, + 3272, 2224, 2967, + 3265, 2256, 2956, + 3255, 2296, 2942, + 3241, 2344, 2921, + 3223, 2402, 2892, + 3197, 2469, 2851, + 3159, 2546, 2788, + 3104, 2631, 2688, + 3017, 2725, 2507, + 2867, 2827, 2023, + 2531, 2934, 0, + 0, 3047, 0, + 0, 3164, 0, + 0, 3285, 0, + 0, 3408, 0, + 0, 3534, 0, + 0, 3661, 0, + 3425, 2242, 3128, + 3425, 2242, 3128, + 3425, 2243, 3128, + 3424, 2244, 3128, + 3424, 2245, 3128, + 3424, 2246, 3127, + 3424, 2248, 3127, + 3423, 2250, 3126, + 3423, 2253, 3126, + 3422, 2257, 3125, + 3421, 2262, 3123, + 3420, 2270, 3122, + 3418, 2279, 3119, + 3416, 2291, 3116, + 3413, 2307, 3112, + 3410, 2327, 3106, + 3404, 2353, 3098, + 3397, 2386, 3087, + 3387, 2426, 3073, + 3374, 2474, 3052, + 3355, 2532, 3023, + 3329, 2600, 2981, + 3292, 2676, 2919, + 3236, 2762, 2818, + 3150, 2856, 2636, + 3000, 2958, 2147, + 2665, 3066, 0, + 0, 3179, 0, + 0, 3296, 0, + 0, 3417, 0, + 0, 3540, 0, + 0, 3666, 0, + 3557, 2371, 3260, + 3557, 2371, 3260, + 3557, 2372, 3260, + 3557, 2372, 3259, + 3557, 2373, 3259, + 3557, 2374, 3259, + 3556, 2375, 3259, + 3556, 2377, 3258, + 3556, 2379, 3258, + 3555, 2382, 3257, + 3554, 2387, 3256, + 3554, 2392, 3255, + 3552, 2399, 3253, + 3551, 2409, 3251, + 3549, 2421, 3247, + 3546, 2437, 3243, + 3542, 2457, 3237, + 3537, 2483, 3230, + 3529, 2516, 3219, + 3520, 2556, 3204, + 3506, 2605, 3183, + 3488, 2663, 3154, + 3461, 2730, 3113, + 3424, 2807, 3050, + 3369, 2894, 2949, + 3282, 2988, 2766, + 3133, 3090, 2273, + 2798, 3197, 0, + 0, 3311, 0, + 0, 3428, 0, + 0, 3549, 0, + 0, 3672, 0, + 3689, 2501, 3391, + 3689, 2501, 3391, + 3689, 2501, 3391, + 3689, 2502, 3391, + 3689, 2502, 3391, + 3689, 2503, 3391, + 3689, 2504, 3391, + 3689, 2505, 3390, + 3688, 2507, 3390, + 3688, 2509, 3389, + 3687, 2513, 3389, + 3687, 2517, 3388, + 3686, 2522, 3386, + 3685, 2529, 3385, + 3683, 2539, 3382, + 3681, 2551, 3379, + 3678, 2567, 3375, + 3674, 2588, 3369, + 3669, 2614, 3361, + 3662, 2646, 3350, + 3652, 2687, 3336, + 3638, 2736, 3315, + 3620, 2794, 3286, + 3594, 2862, 3244, + 3556, 2939, 3181, + 3501, 3025, 3080, + 3414, 3119, 2897, + 3265, 3221, 2400, + 2931, 3329, 0, + 0, 3442, 0, + 0, 3560, 0, + 0, 3681, 0, + 3821, 2631, 3523, + 3821, 2631, 3523, + 3821, 2632, 3523, + 3821, 2632, 3523, + 3821, 2632, 3523, + 3821, 2633, 3523, + 3821, 2634, 3523, + 3821, 2635, 3522, + 3821, 2636, 3522, + 3820, 2638, 3522, + 3820, 2640, 3521, + 3820, 2643, 3520, + 3819, 2647, 3519, + 3818, 2653, 3518, + 3817, 2660, 3516, + 3815, 2669, 3514, + 3813, 2682, 3511, + 3810, 2698, 3506, + 3806, 2718, 3501, + 3801, 2745, 3493, + 3794, 2777, 3482, + 3784, 2818, 3467, + 3771, 2867, 3447, + 3752, 2925, 3418, + 3726, 2993, 3375, + 3689, 3070, 3312, + 3633, 3157, 3211, + 3547, 3251, 3028, + 3397, 3353, 2529, + 3063, 3461, 0, + 0, 3574, 0, + 0, 3692, 0, + 3954, 2762, 3655, + 3954, 2762, 3655, + 3954, 2762, 3655, + 3954, 2762, 3655, + 3954, 2763, 3655, + 3953, 2763, 3655, + 3953, 2764, 3655, + 3953, 2765, 3654, + 3953, 2766, 3654, + 3953, 2767, 3654, + 3953, 2769, 3653, + 3952, 2771, 3653, + 3952, 2774, 3652, + 3951, 2778, 3651, + 3950, 2784, 3650, + 3949, 2791, 3648, + 3947, 2800, 3646, + 3945, 2813, 3643, + 3942, 2829, 3638, + 3938, 2850, 3632, + 3933, 2876, 3625, + 3926, 2909, 3614, + 3916, 2949, 3599, + 3903, 2998, 3578, + 3884, 3057, 3549, + 3858, 3125, 3507, + 3821, 3202, 3444, + 3765, 3288, 3343, + 3679, 3383, 3159, + 3530, 3485, 2658, + 3196, 3593, 0, + 0, 3706, 0, + 4086, 2893, 3787, + 4086, 2893, 3787, + 4086, 2893, 3787, + 4086, 2893, 3787, + 4086, 2894, 3787, + 4086, 2894, 3787, + 4086, 2894, 3787, + 4086, 2895, 3786, + 4085, 2896, 3786, + 4085, 2897, 3786, + 4085, 2898, 3786, + 4085, 2900, 3785, + 4084, 2902, 3785, + 4084, 2905, 3784, + 4083, 2909, 3783, + 4082, 2915, 3782, + 4081, 2922, 3780, + 4080, 2932, 3778, + 4077, 2944, 3774, + 4074, 2960, 3770, + 4071, 2981, 3764, + 4065, 3007, 3756, + 4058, 3040, 3746, + 4048, 3081, 3731, + 4035, 3130, 3710, + 4016, 3188, 3681, + 3990, 3256, 3639, + 3953, 3334, 3576, + 3898, 3420, 3475, + 3811, 3515, 3290, + 3662, 3617, 2788, + 3328, 3725, 0, + 4095, 3024, 3919, + 4095, 3025, 3919, + 4095, 3025, 3919, + 4095, 3025, 3919, + 4095, 3025, 3919, + 4095, 3025, 3919, + 4095, 3025, 3919, + 4095, 3026, 3918, + 4095, 3026, 3918, + 4095, 3027, 3918, + 4095, 3028, 3918, + 4095, 3030, 3918, + 4095, 3031, 3917, + 4095, 3034, 3917, + 4095, 3037, 3916, + 4095, 3041, 3915, + 4095, 3046, 3914, + 4095, 3054, 3912, + 4095, 3063, 3910, + 4095, 3076, 3906, + 4095, 3092, 3902, + 4095, 3113, 3896, + 4095, 3139, 3888, + 4095, 3172, 3878, + 4095, 3212, 3863, + 4095, 3262, 3842, + 4095, 3320, 3813, + 4095, 3388, 3771, + 4085, 3466, 3708, + 4030, 3552, 3606, + 3943, 3647, 3422, + 3794, 3749, 2919, + 4095, 3156, 4051, + 4095, 3156, 4051, + 4095, 3156, 4051, + 4095, 3156, 4051, + 4095, 3156, 4051, + 4095, 3157, 4051, + 4095, 3157, 4051, + 4095, 3157, 4051, + 4095, 3158, 4050, + 4095, 3158, 4050, + 4095, 3159, 4050, + 4095, 3160, 4050, + 4095, 3161, 4050, + 4095, 3163, 4049, + 4095, 3165, 4049, + 4095, 3168, 4048, + 4095, 3173, 4047, + 4095, 3178, 4046, + 4095, 3185, 4044, + 4095, 3195, 4041, + 4095, 3207, 4038, + 4095, 3224, 4034, + 4095, 3244, 4028, + 4095, 3271, 4020, + 4095, 3304, 4009, + 4095, 3344, 3995, + 4095, 3393, 3974, + 4095, 3452, 3945, + 4095, 3520, 3903, + 4095, 3597, 3839, + 4095, 3684, 3738, + 4076, 3779, 3554, + 0, 723, 961, + 0, 734, 949, + 0, 749, 934, + 0, 769, 912, + 0, 793, 881, + 0, 824, 837, + 0, 862, 769, + 0, 908, 660, + 0, 964, 453, + 0, 1029, 0, + 0, 1104, 0, + 0, 1187, 0, + 0, 1280, 0, + 0, 1380, 0, + 0, 1486, 0, + 0, 1598, 0, + 0, 1714, 0, + 0, 1834, 0, + 0, 1957, 0, + 0, 2082, 0, + 0, 2209, 0, + 0, 2337, 0, + 0, 2466, 0, + 0, 2596, 0, + 0, 2726, 0, + 0, 2857, 0, + 0, 2988, 0, + 0, 3119, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3514, 0, + 0, 3646, 0, + 0, 727, 977, + 0, 738, 966, + 0, 753, 951, + 0, 772, 930, + 0, 796, 901, + 0, 827, 858, + 0, 865, 794, + 0, 911, 691, + 0, 966, 502, + 0, 1031, 0, + 0, 1105, 0, + 0, 1189, 0, + 0, 1281, 0, + 0, 1380, 0, + 0, 1487, 0, + 0, 1598, 0, + 0, 1715, 0, + 0, 1835, 0, + 0, 1957, 0, + 0, 2082, 0, + 0, 2209, 0, + 0, 2337, 0, + 0, 2466, 0, + 0, 2596, 0, + 0, 2726, 0, + 0, 2857, 0, + 0, 2988, 0, + 0, 3119, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3514, 0, + 0, 3646, 0, + 0, 732, 998, + 0, 743, 988, + 0, 758, 974, + 0, 777, 954, + 0, 801, 926, + 0, 831, 886, + 0, 869, 825, + 0, 915, 730, + 0, 969, 560, + 0, 1034, 134, + 0, 1108, 0, + 0, 1191, 0, + 0, 1282, 0, + 0, 1382, 0, + 0, 1488, 0, + 0, 1599, 0, + 0, 1715, 0, + 0, 1835, 0, + 0, 1958, 0, + 0, 2082, 0, + 0, 2209, 0, + 0, 2337, 0, + 0, 2466, 0, + 0, 2596, 0, + 0, 2726, 0, + 0, 2857, 0, + 0, 2988, 0, + 0, 3119, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3514, 0, + 0, 3646, 0, + 0, 739, 1025, + 0, 750, 1015, + 0, 764, 1002, + 0, 783, 983, + 0, 807, 957, + 0, 837, 920, + 0, 874, 864, + 0, 919, 777, + 0, 973, 627, + 0, 1037, 289, + 0, 1111, 0, + 0, 1193, 0, + 0, 1284, 0, + 0, 1383, 0, + 0, 1489, 0, + 0, 1600, 0, + 0, 1716, 0, + 0, 1836, 0, + 0, 1958, 0, + 0, 2083, 0, + 0, 2209, 0, + 0, 2337, 0, + 0, 2466, 0, + 0, 2596, 0, + 0, 2726, 0, + 0, 2857, 0, + 0, 2988, 0, + 0, 3119, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3514, 0, + 0, 3646, 0, + 0, 748, 1059, + 0, 759, 1050, + 0, 773, 1037, + 0, 791, 1020, + 0, 815, 996, + 0, 844, 962, + 0, 880, 911, + 0, 925, 834, + 0, 979, 704, + 0, 1042, 438, + 0, 1115, 0, + 0, 1197, 0, + 0, 1287, 0, + 0, 1386, 0, + 0, 1491, 0, + 0, 1602, 0, + 0, 1717, 0, + 0, 1836, 0, + 0, 1959, 0, + 0, 2083, 0, + 0, 2210, 0, + 0, 2338, 0, + 0, 2466, 0, + 0, 2596, 0, + 0, 2726, 0, + 0, 2857, 0, + 0, 2988, 0, + 0, 3119, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3514, 0, + 0, 3646, 0, + 450, 760, 1100, + 403, 770, 1092, + 330, 784, 1080, + 210, 802, 1065, + 0, 825, 1043, + 0, 853, 1012, + 0, 889, 967, + 0, 933, 900, + 0, 986, 790, + 0, 1048, 582, + 0, 1120, 0, + 0, 1201, 0, + 0, 1291, 0, + 0, 1388, 0, + 0, 1493, 0, + 0, 1603, 0, + 0, 1718, 0, + 0, 1837, 0, + 0, 1960, 0, + 0, 2084, 0, + 0, 2210, 0, + 0, 2338, 0, + 0, 2467, 0, + 0, 2596, 0, + 0, 2726, 0, + 0, 2857, 0, + 0, 2988, 0, + 0, 3120, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3514, 0, + 0, 3646, 0, + 751, 775, 1150, + 727, 785, 1143, + 693, 799, 1132, + 643, 816, 1119, + 566, 838, 1099, + 437, 866, 1072, + 175, 901, 1033, + 0, 944, 975, + 0, 995, 884, + 0, 1056, 723, + 0, 1127, 342, + 0, 1207, 0, + 0, 1296, 0, + 0, 1392, 0, + 0, 1496, 0, + 0, 1606, 0, + 0, 1720, 0, + 0, 1839, 0, + 0, 1961, 0, + 0, 2085, 0, + 0, 2211, 0, + 0, 2338, 0, + 0, 2467, 0, + 0, 2597, 0, + 0, 2727, 0, + 0, 2857, 0, + 0, 2988, 0, + 0, 3120, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3514, 0, + 0, 3646, 0, + 978, 795, 1209, + 964, 805, 1203, + 944, 817, 1194, + 916, 834, 1182, + 875, 855, 1165, + 814, 882, 1142, + 718, 916, 1108, + 545, 957, 1060, + 108, 1008, 985, + 0, 1067, 862, + 0, 1136, 615, + 0, 1215, 0, + 0, 1302, 0, + 0, 1397, 0, + 0, 1500, 0, + 0, 1609, 0, + 0, 1723, 0, + 0, 1841, 0, + 0, 1962, 0, + 0, 2086, 0, + 0, 2212, 0, + 0, 2339, 0, + 0, 2468, 0, + 0, 2597, 0, + 0, 2727, 0, + 0, 2858, 0, + 0, 2988, 0, + 0, 3120, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3646, 0, + 1170, 820, 1278, + 1161, 829, 1273, + 1148, 841, 1265, + 1130, 857, 1255, + 1105, 877, 1240, + 1070, 903, 1221, + 1017, 935, 1193, + 936, 975, 1153, + 798, 1023, 1093, + 507, 1081, 998, + 0, 1148, 830, + 0, 1225, 414, + 0, 1310, 0, + 0, 1404, 0, + 0, 1506, 0, + 0, 1613, 0, + 0, 1726, 0, + 0, 1843, 0, + 0, 1964, 0, + 0, 2087, 0, + 0, 2213, 0, + 0, 2340, 0, + 0, 2468, 0, + 0, 2597, 0, + 0, 2727, 0, + 0, 2858, 0, + 0, 2989, 0, + 0, 3120, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3646, 0, + 1343, 851, 1356, + 1336, 860, 1352, + 1327, 871, 1345, + 1316, 886, 1337, + 1299, 905, 1325, + 1276, 929, 1308, + 1244, 960, 1286, + 1196, 998, 1253, + 1123, 1044, 1206, + 1004, 1099, 1134, + 769, 1164, 1015, + 0, 1238, 784, + 0, 1321, 0, + 0, 1413, 0, + 0, 1513, 0, + 0, 1619, 0, + 0, 1731, 0, + 0, 1847, 0, + 0, 1967, 0, + 0, 2089, 0, + 0, 2214, 0, + 0, 2341, 0, + 0, 2469, 0, + 0, 2598, 0, + 0, 2728, 0, + 0, 2858, 0, + 0, 2989, 0, + 0, 3120, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3646, 0, + 1502, 890, 1444, + 1498, 898, 1440, + 1492, 909, 1434, + 1484, 922, 1427, + 1472, 940, 1418, + 1457, 962, 1404, + 1435, 991, 1386, + 1405, 1026, 1360, + 1360, 1070, 1323, + 1293, 1122, 1269, + 1184, 1184, 1184, + 979, 1255, 1037, + 327, 1335, 715, + 0, 1425, 0, + 0, 1522, 0, + 0, 1626, 0, + 0, 1736, 0, + 0, 1851, 0, + 0, 1970, 0, + 0, 2092, 0, + 0, 2216, 0, + 0, 2343, 0, + 0, 2470, 0, + 0, 2599, 0, + 0, 2728, 0, + 0, 2859, 0, + 0, 2989, 0, + 0, 3120, 0, + 0, 3252, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3647, 0, + 1654, 938, 1539, + 1651, 945, 1536, + 1647, 954, 1532, + 1641, 967, 1526, + 1633, 982, 1518, + 1622, 1003, 1507, + 1607, 1029, 1493, + 1586, 1062, 1473, + 1557, 1102, 1444, + 1515, 1151, 1403, + 1451, 1209, 1341, + 1349, 1277, 1243, + 1161, 1354, 1065, + 641, 1440, 601, + 0, 1534, 0, + 0, 1636, 0, + 0, 1744, 0, + 0, 1857, 0, + 0, 1975, 0, + 0, 2096, 0, + 0, 2219, 0, + 0, 2345, 0, + 0, 2472, 0, + 0, 2600, 0, + 0, 2729, 0, + 0, 2859, 0, + 0, 2990, 0, + 0, 3121, 0, + 0, 3252, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3647, 0, + 1801, 994, 1642, + 1798, 1000, 1639, + 1795, 1009, 1636, + 1791, 1020, 1631, + 1785, 1034, 1625, + 1778, 1052, 1617, + 1767, 1076, 1605, + 1752, 1105, 1589, + 1732, 1142, 1567, + 1704, 1187, 1536, + 1663, 1241, 1491, + 1601, 1304, 1423, + 1504, 1377, 1311, + 1328, 1459, 1099, + 874, 1550, 384, + 0, 1649, 0, + 0, 1754, 0, + 0, 1865, 0, + 0, 1981, 0, + 0, 2100, 0, + 0, 2223, 0, + 0, 2347, 0, + 0, 2474, 0, + 0, 2602, 0, + 0, 2731, 0, + 0, 2860, 0, + 0, 2990, 0, + 0, 3121, 0, + 0, 3252, 0, + 0, 3384, 0, + 0, 3515, 0, + 0, 3647, 0, + 1943, 1060, 1750, + 1941, 1066, 1748, + 1939, 1073, 1746, + 1936, 1082, 1742, + 1932, 1095, 1737, + 1926, 1111, 1731, + 1919, 1132, 1722, + 1908, 1158, 1710, + 1894, 1191, 1693, + 1874, 1231, 1670, + 1847, 1281, 1636, + 1807, 1339, 1587, + 1747, 1407, 1513, + 1652, 1484, 1389, + 1484, 1571, 1142, + 1068, 1665, 0, + 0, 1767, 0, + 0, 1876, 0, + 0, 1989, 0, + 0, 2106, 0, + 0, 2227, 0, + 0, 2351, 0, + 0, 2477, 0, + 0, 2604, 0, + 0, 2732, 0, + 0, 2861, 0, + 0, 2991, 0, + 0, 3122, 0, + 0, 3253, 0, + 0, 3384, 0, + 0, 3515, 0, + 0, 3647, 0, + 2083, 1136, 1864, + 2082, 1140, 1862, + 2080, 1146, 1860, + 2078, 1155, 1858, + 2075, 1165, 1854, + 2071, 1179, 1849, + 2065, 1197, 1842, + 2058, 1220, 1833, + 2047, 1249, 1820, + 2033, 1284, 1802, + 2014, 1328, 1778, + 1987, 1381, 1743, + 1947, 1444, 1691, + 1889, 1516, 1611, + 1796, 1597, 1476, + 1633, 1687, 1193, + 1242, 1784, 0, + 0, 1889, 0, + 0, 1999, 0, + 0, 2115, 0, + 0, 2234, 0, + 0, 2356, 0, + 0, 2480, 0, + 0, 2606, 0, + 0, 2734, 0, + 0, 2863, 0, + 0, 2993, 0, + 0, 3123, 0, + 0, 3253, 0, + 0, 3385, 0, + 0, 3516, 0, + 0, 3647, 0, + 2221, 1220, 1982, + 2220, 1224, 1981, + 2218, 1229, 1979, + 2217, 1236, 1977, + 2214, 1245, 1974, + 2211, 1257, 1970, + 2207, 1272, 1965, + 2202, 1291, 1958, + 2195, 1316, 1948, + 2185, 1347, 1935, + 2171, 1386, 1917, + 2151, 1433, 1891, + 2124, 1489, 1854, + 2086, 1554, 1800, + 2028, 1629, 1716, + 1937, 1713, 1571, + 1778, 1806, 1253, + 1403, 1906, 0, + 0, 2013, 0, + 0, 2125, 0, + 0, 2242, 0, + 0, 2362, 0, + 0, 2485, 0, + 0, 2610, 0, + 0, 2737, 0, + 0, 2865, 0, + 0, 2994, 0, + 0, 3124, 0, + 0, 3254, 0, + 0, 3385, 0, + 0, 3516, 0, + 0, 3648, 0, + 2357, 1313, 2103, + 2356, 1316, 2102, + 2355, 1321, 2101, + 2354, 1326, 2099, + 2352, 1334, 2097, + 2350, 1343, 2094, + 2347, 1356, 2090, + 2343, 1372, 2085, + 2338, 1393, 2078, + 2330, 1419, 2068, + 2320, 1452, 2054, + 2307, 1493, 2035, + 2288, 1543, 2009, + 2261, 1601, 1971, + 2222, 1669, 1915, + 2165, 1747, 1826, + 2076, 1834, 1673, + 1919, 1929, 1323, + 1556, 2031, 0, + 0, 2139, 0, + 0, 2253, 0, + 0, 2370, 0, + 0, 2491, 0, + 0, 2615, 0, + 0, 2741, 0, + 0, 2868, 0, + 0, 2996, 0, + 0, 3126, 0, + 0, 3256, 0, + 0, 3386, 0, + 0, 3517, 0, + 0, 3648, 0, + 2492, 1414, 2227, + 2491, 1416, 2226, + 2491, 1420, 2225, + 2490, 1424, 2224, + 2489, 1430, 2222, + 2487, 1438, 2220, + 2485, 1448, 2217, + 2482, 1461, 2213, + 2478, 1479, 2208, + 2472, 1501, 2200, + 2465, 1528, 2190, + 2455, 1563, 2176, + 2442, 1606, 2157, + 2423, 1657, 2130, + 2396, 1718, 2091, + 2358, 1788, 2033, + 2301, 1868, 1942, + 2213, 1957, 1782, + 2058, 2053, 1403, + 1703, 2157, 0, + 0, 2267, 0, + 0, 2381, 0, + 0, 2500, 0, + 0, 2621, 0, + 0, 2745, 0, + 0, 2871, 0, + 0, 2999, 0, + 0, 3128, 0, + 0, 3257, 0, + 0, 3387, 0, + 0, 3518, 0, + 0, 3649, 0, + 2626, 1521, 2353, + 2626, 1523, 2352, + 2625, 1526, 2351, + 2625, 1529, 2350, + 2624, 1534, 2349, + 2623, 1540, 2347, + 2621, 1548, 2345, + 2619, 1559, 2342, + 2616, 1573, 2338, + 2612, 1591, 2332, + 2607, 1614, 2325, + 2599, 1643, 2315, + 2589, 1679, 2301, + 2576, 1723, 2281, + 2557, 1776, 2253, + 2531, 1839, 2214, + 2493, 1911, 2154, + 2436, 1992, 2061, + 2348, 2082, 1895, + 2195, 2180, 1491, + 1846, 2285, 0, + 0, 2395, 0, + 0, 2511, 0, + 0, 2630, 0, + 0, 2752, 0, + 0, 2876, 0, + 0, 3003, 0, + 0, 3130, 0, + 0, 3259, 0, + 0, 3389, 0, + 0, 3519, 0, + 0, 3650, 0, + 2760, 1633, 2480, + 2760, 1635, 2479, + 2759, 1637, 2479, + 2759, 1640, 2478, + 2758, 1643, 2477, + 2757, 1648, 2476, + 2756, 1655, 2474, + 2755, 1663, 2472, + 2752, 1674, 2469, + 2749, 1689, 2465, + 2745, 1707, 2459, + 2740, 1731, 2451, + 2733, 1761, 2441, + 2723, 1798, 2427, + 2710, 1843, 2407, + 2691, 1898, 2379, + 2664, 1962, 2339, + 2627, 2035, 2278, + 2571, 2118, 2183, + 2483, 2209, 2013, + 2331, 2308, 1588, + 1986, 2414, 0, + 0, 2525, 0, + 0, 2641, 0, + 0, 2760, 0, + 0, 2883, 0, + 0, 3007, 0, + 0, 3134, 0, + 0, 3262, 0, + 0, 3391, 0, + 0, 3521, 0, + 0, 3651, 0, + 2893, 1750, 2608, + 2893, 1751, 2608, + 2893, 1753, 2608, + 2893, 1755, 2607, + 2892, 1758, 2606, + 2891, 1762, 2605, + 2891, 1767, 2604, + 2889, 1773, 2602, + 2888, 1782, 2600, + 2886, 1793, 2597, + 2883, 1808, 2593, + 2879, 1827, 2587, + 2873, 1852, 2579, + 2866, 1882, 2569, + 2856, 1920, 2554, + 2843, 1967, 2534, + 2824, 2022, 2506, + 2798, 2087, 2465, + 2760, 2161, 2404, + 2704, 2245, 2308, + 2617, 2337, 2134, + 2465, 2437, 1691, + 2123, 2543, 0, + 0, 2655, 0, + 0, 2771, 0, + 0, 2891, 0, + 0, 3014, 0, + 0, 3139, 0, + 0, 3266, 0, + 0, 3394, 0, + 0, 3523, 0, + 0, 3652, 0, + 3026, 1870, 2738, + 3026, 1871, 2737, + 3026, 1873, 2737, + 3026, 1874, 2737, + 3025, 1876, 2736, + 3025, 1879, 2735, + 3024, 1883, 2735, + 3023, 1888, 2733, + 3022, 1895, 2732, + 3021, 1904, 2729, + 3018, 1916, 2726, + 3015, 1931, 2722, + 3012, 1950, 2716, + 3006, 1975, 2708, + 2999, 2006, 2698, + 2989, 2045, 2683, + 2976, 2092, 2663, + 2957, 2148, 2635, + 2931, 2214, 2593, + 2893, 2289, 2532, + 2838, 2373, 2434, + 2750, 2466, 2258, + 2600, 2567, 1800, + 2260, 2673, 0, + 0, 2786, 0, + 0, 2902, 0, + 0, 3022, 0, + 0, 3145, 0, + 0, 3270, 0, + 0, 3397, 0, + 0, 3525, 0, + 0, 3655, 0, + 3159, 1993, 2868, + 3159, 1994, 2868, + 3159, 1995, 2867, + 3159, 1996, 2867, + 3159, 1998, 2867, + 3158, 2000, 2866, + 3158, 2003, 2865, + 3157, 2007, 2864, + 3156, 2012, 2863, + 3155, 2019, 2861, + 3153, 2028, 2859, + 3151, 2040, 2856, + 3148, 2056, 2852, + 3144, 2075, 2846, + 3139, 2101, 2838, + 3132, 2132, 2827, + 3122, 2172, 2813, + 3109, 2219, 2793, + 3090, 2276, 2764, + 3064, 2342, 2723, + 3026, 2418, 2661, + 2971, 2503, 2562, + 2884, 2596, 2383, + 2733, 2697, 1915, + 2395, 2804, 0, + 0, 2917, 0, + 0, 3033, 0, + 0, 3154, 0, + 0, 3277, 0, + 0, 3402, 0, + 0, 3529, 0, + 0, 3657, 0, + 3292, 2119, 2998, + 3292, 2119, 2998, + 3292, 2120, 2998, + 3292, 2121, 2998, + 3291, 2122, 2997, + 3291, 2124, 2997, + 3291, 2126, 2997, + 3290, 2129, 2996, + 3290, 2133, 2995, + 3289, 2138, 2994, + 3287, 2145, 2992, + 3286, 2155, 2989, + 3284, 2167, 2986, + 3281, 2182, 2982, + 3277, 2202, 2976, + 3272, 2228, 2968, + 3264, 2260, 2958, + 3255, 2299, 2943, + 3241, 2347, 2923, + 3222, 2405, 2894, + 3196, 2471, 2852, + 3159, 2548, 2790, + 3103, 2633, 2691, + 3017, 2727, 2510, + 2866, 2828, 2033, + 2530, 2935, 0, + 0, 3048, 0, + 0, 3165, 0, + 0, 3285, 0, + 0, 3409, 0, + 0, 3534, 0, + 0, 3661, 0, + 3424, 2246, 3129, + 3424, 2246, 3129, + 3424, 2246, 3129, + 3424, 2247, 3129, + 3424, 2248, 3129, + 3424, 2249, 3128, + 3424, 2251, 3128, + 3423, 2253, 3127, + 3423, 2257, 3127, + 3422, 2261, 3126, + 3421, 2266, 3124, + 3420, 2273, 3123, + 3418, 2282, 3120, + 3416, 2294, 3117, + 3413, 2310, 3113, + 3409, 2330, 3107, + 3404, 2356, 3099, + 3397, 2388, 3088, + 3387, 2428, 3074, + 3374, 2477, 3053, + 3355, 2534, 3024, + 3329, 2601, 2983, + 3291, 2678, 2920, + 3236, 2763, 2820, + 3149, 2857, 2639, + 2999, 2959, 2155, + 2663, 3066, 0, + 0, 3179, 0, + 0, 3297, 0, + 0, 3417, 0, + 0, 3540, 0, + 0, 3666, 0, + 3557, 2374, 3260, + 3557, 2374, 3260, + 3557, 2374, 3260, + 3557, 2375, 3260, + 3556, 2376, 3260, + 3556, 2377, 3260, + 3556, 2378, 3259, + 3556, 2380, 3259, + 3555, 2382, 3259, + 3555, 2385, 3258, + 3554, 2389, 3257, + 3553, 2395, 3255, + 3552, 2402, 3254, + 3551, 2411, 3251, + 3548, 2423, 3248, + 3546, 2439, 3244, + 3542, 2459, 3238, + 3536, 2485, 3230, + 3529, 2518, 3220, + 3519, 2558, 3205, + 3506, 2607, 3184, + 3487, 2664, 3155, + 3461, 2732, 3114, + 3424, 2808, 3051, + 3368, 2894, 2950, + 3282, 2989, 2768, + 3132, 3090, 2279, + 2797, 3198, 0, + 0, 3311, 0, + 0, 3428, 0, + 0, 3549, 0, + 0, 3672, 0, + 3689, 2503, 3392, + 3689, 2503, 3392, + 3689, 2503, 3392, + 3689, 2504, 3392, + 3689, 2504, 3392, + 3689, 2505, 3391, + 3689, 2506, 3391, + 3688, 2507, 3391, + 3688, 2509, 3390, + 3688, 2511, 3390, + 3687, 2515, 3389, + 3687, 2519, 3388, + 3686, 2524, 3387, + 3684, 2531, 3385, + 3683, 2541, 3383, + 3681, 2553, 3380, + 3678, 2569, 3375, + 3674, 2589, 3369, + 3669, 2615, 3362, + 3661, 2648, 3351, + 3652, 2688, 3336, + 3638, 2737, 3316, + 3620, 2795, 3287, + 3594, 2863, 3245, + 3556, 2940, 3182, + 3501, 3026, 3081, + 3414, 3120, 2898, + 3265, 3222, 2405, + 2930, 3330, 0, + 0, 3443, 0, + 0, 3560, 0, + 0, 3681, 0, + 3821, 2633, 3524, + 3821, 2633, 3523, + 3821, 2633, 3523, + 3821, 2633, 3523, + 3821, 2634, 3523, + 3821, 2634, 3523, + 3821, 2635, 3523, + 3821, 2636, 3523, + 3821, 2637, 3522, + 3820, 2639, 3522, + 3820, 2642, 3521, + 3819, 2645, 3521, + 3819, 2649, 3520, + 3818, 2654, 3518, + 3817, 2661, 3517, + 3815, 2671, 3514, + 3813, 2683, 3511, + 3810, 2699, 3507, + 3806, 2720, 3501, + 3801, 2746, 3493, + 3794, 2779, 3482, + 3784, 2819, 3468, + 3770, 2868, 3447, + 3752, 2926, 3418, + 3726, 2994, 3376, + 3688, 3071, 3313, + 3633, 3157, 3212, + 3547, 3252, 3029, + 3397, 3353, 2532, + 3063, 3461, 0, + 0, 3575, 0, + 0, 3692, 0, + 3954, 2763, 3655, + 3954, 2763, 3655, + 3954, 2763, 3655, + 3954, 2764, 3655, + 3953, 2764, 3655, + 3953, 2764, 3655, + 3953, 2765, 3655, + 3953, 2766, 3655, + 3953, 2767, 3654, + 3953, 2768, 3654, + 3953, 2770, 3654, + 3952, 2772, 3653, + 3952, 2775, 3652, + 3951, 2779, 3651, + 3950, 2785, 3650, + 3949, 2792, 3648, + 3947, 2802, 3646, + 3945, 2814, 3643, + 3942, 2830, 3639, + 3938, 2851, 3633, + 3933, 2877, 3625, + 3926, 2910, 3614, + 3916, 2950, 3599, + 3903, 2999, 3579, + 3884, 3057, 3550, + 3858, 3125, 3508, + 3821, 3202, 3444, + 3765, 3289, 3344, + 3679, 3383, 3160, + 3529, 3485, 2661, + 3195, 3593, 0, + 0, 3706, 0, + 4086, 2894, 3787, + 4086, 2894, 3787, + 4086, 2894, 3787, + 4086, 2894, 3787, + 4086, 2895, 3787, + 4086, 2895, 3787, + 4086, 2895, 3787, + 4085, 2896, 3787, + 4085, 2897, 3786, + 4085, 2898, 3786, + 4085, 2899, 3786, + 4085, 2901, 3786, + 4084, 2903, 3785, + 4084, 2906, 3784, + 4083, 2910, 3783, + 4082, 2916, 3782, + 4081, 2923, 3780, + 4079, 2933, 3778, + 4077, 2945, 3775, + 4074, 2961, 3770, + 4071, 2982, 3765, + 4065, 3008, 3757, + 4058, 3041, 3746, + 4048, 3081, 3731, + 4035, 3130, 3710, + 4016, 3189, 3681, + 3990, 3257, 3639, + 3953, 3334, 3576, + 3898, 3420, 3475, + 3811, 3515, 3291, + 3662, 3617, 2790, + 3328, 3725, 0, + 4095, 3025, 3919, + 4095, 3025, 3919, + 4095, 3025, 3919, + 4095, 3025, 3919, + 4095, 3026, 3919, + 4095, 3026, 3919, + 4095, 3026, 3919, + 4095, 3027, 3919, + 4095, 3027, 3919, + 4095, 3028, 3918, + 4095, 3029, 3918, + 4095, 3030, 3918, + 4095, 3032, 3917, + 4095, 3034, 3917, + 4095, 3037, 3916, + 4095, 3042, 3915, + 4095, 3047, 3914, + 4095, 3054, 3912, + 4095, 3064, 3910, + 4095, 3076, 3906, + 4095, 3092, 3902, + 4095, 3113, 3896, + 4095, 3139, 3888, + 4095, 3172, 3878, + 4095, 3213, 3863, + 4095, 3262, 3842, + 4095, 3320, 3813, + 4095, 3388, 3771, + 4085, 3466, 3708, + 4030, 3552, 3607, + 3943, 3647, 3422, + 3794, 3749, 2920, + 4095, 3156, 4051, + 4095, 3157, 4051, + 4095, 3157, 4051, + 4095, 3157, 4051, + 4095, 3157, 4051, + 4095, 3157, 4051, + 4095, 3157, 4051, + 4095, 3158, 4051, + 4095, 3158, 4051, + 4095, 3159, 4050, + 4095, 3159, 4050, + 4095, 3160, 4050, + 4095, 3162, 4050, + 4095, 3163, 4049, + 4095, 3166, 4049, + 4095, 3169, 4048, + 4095, 3173, 4047, + 4095, 3179, 4046, + 4095, 3186, 4044, + 4095, 3195, 4042, + 4095, 3208, 4038, + 4095, 3224, 4034, + 4095, 3245, 4028, + 4095, 3271, 4020, + 4095, 3304, 4010, + 4095, 3345, 3995, + 4095, 3394, 3974, + 4095, 3452, 3945, + 4095, 3520, 3903, + 4095, 3598, 3840, + 4095, 3684, 3738, + 4075, 3779, 3554, + 0, 843, 1089, + 0, 852, 1080, + 0, 864, 1068, + 0, 879, 1052, + 0, 898, 1030, + 0, 923, 998, + 0, 954, 952, + 0, 992, 882, + 0, 1039, 767, + 0, 1094, 545, + 0, 1160, 0, + 0, 1234, 0, + 0, 1318, 0, + 0, 1411, 0, + 0, 1511, 0, + 0, 1617, 0, + 0, 1729, 0, + 0, 1846, 0, + 0, 1966, 0, + 0, 2089, 0, + 0, 2214, 0, + 0, 2341, 0, + 0, 2469, 0, + 0, 2598, 0, + 0, 2728, 0, + 0, 2858, 0, + 0, 2989, 0, + 0, 3120, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3646, 0, + 0, 846, 1101, + 0, 855, 1093, + 0, 867, 1082, + 0, 881, 1066, + 0, 901, 1044, + 0, 925, 1013, + 0, 956, 969, + 0, 994, 901, + 0, 1041, 792, + 0, 1096, 585, + 0, 1161, 0, + 0, 1236, 0, + 0, 1319, 0, + 0, 1412, 0, + 0, 1512, 0, + 0, 1618, 0, + 0, 1730, 0, + 0, 1846, 0, + 0, 1966, 0, + 0, 2089, 0, + 0, 2214, 0, + 0, 2341, 0, + 0, 2469, 0, + 0, 2598, 0, + 0, 2728, 0, + 0, 2858, 0, + 0, 2989, 0, + 0, 3120, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3646, 0, + 0, 850, 1117, + 0, 859, 1109, + 0, 870, 1098, + 0, 885, 1083, + 0, 904, 1063, + 0, 928, 1033, + 0, 959, 990, + 0, 997, 926, + 0, 1043, 823, + 0, 1098, 634, + 0, 1163, 101, + 0, 1237, 0, + 0, 1321, 0, + 0, 1413, 0, + 0, 1513, 0, + 0, 1619, 0, + 0, 1730, 0, + 0, 1847, 0, + 0, 1967, 0, + 0, 2089, 0, + 0, 2214, 0, + 0, 2341, 0, + 0, 2469, 0, + 0, 2598, 0, + 0, 2728, 0, + 0, 2858, 0, + 0, 2989, 0, + 0, 3120, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3646, 0, + 0, 856, 1138, + 0, 864, 1130, + 0, 875, 1120, + 0, 890, 1106, + 0, 909, 1086, + 0, 933, 1058, + 0, 963, 1018, + 0, 1001, 957, + 0, 1047, 862, + 0, 1101, 692, + 0, 1166, 266, + 0, 1240, 0, + 0, 1323, 0, + 0, 1414, 0, + 0, 1514, 0, + 0, 1620, 0, + 0, 1731, 0, + 0, 1847, 0, + 0, 1967, 0, + 0, 2090, 0, + 0, 2215, 0, + 0, 2341, 0, + 0, 2469, 0, + 0, 2598, 0, + 0, 2728, 0, + 0, 2858, 0, + 0, 2989, 0, + 0, 3120, 0, + 0, 3251, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3646, 0, + 0, 863, 1164, + 0, 871, 1157, + 0, 882, 1147, + 0, 897, 1134, + 0, 915, 1115, + 0, 939, 1089, + 0, 969, 1052, + 0, 1006, 996, + 0, 1051, 909, + 0, 1106, 759, + 0, 1169, 421, + 0, 1243, 0, + 0, 1325, 0, + 0, 1417, 0, + 0, 1515, 0, + 0, 1621, 0, + 0, 1732, 0, + 0, 1848, 0, + 0, 1968, 0, + 0, 2090, 0, + 0, 2215, 0, + 0, 2341, 0, + 0, 2469, 0, + 0, 2598, 0, + 0, 2728, 0, + 0, 2858, 0, + 0, 2989, 0, + 0, 3120, 0, + 0, 3252, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3646, 0, + 133, 872, 1198, + 32, 880, 1191, + 0, 891, 1182, + 0, 905, 1169, + 0, 923, 1152, + 0, 947, 1128, + 0, 976, 1094, + 0, 1013, 1043, + 0, 1057, 966, + 0, 1111, 836, + 0, 1174, 570, + 0, 1247, 0, + 0, 1329, 0, + 0, 1419, 0, + 0, 1518, 0, + 0, 1623, 0, + 0, 1734, 0, + 0, 1849, 0, + 0, 1968, 0, + 0, 2091, 0, + 0, 2215, 0, + 0, 2342, 0, + 0, 2470, 0, + 0, 2599, 0, + 0, 2728, 0, + 0, 2858, 0, + 0, 2989, 0, + 0, 3120, 0, + 0, 3252, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3647, 0, + 615, 884, 1238, + 582, 892, 1232, + 535, 902, 1224, + 462, 916, 1213, + 342, 934, 1197, + 107, 957, 1175, + 0, 986, 1144, + 0, 1021, 1100, + 0, 1065, 1032, + 0, 1118, 922, + 0, 1180, 714, + 0, 1252, 39, + 0, 1333, 0, + 0, 1423, 0, + 0, 1521, 0, + 0, 1625, 0, + 0, 1735, 0, + 0, 1851, 0, + 0, 1970, 0, + 0, 2092, 0, + 0, 2216, 0, + 0, 2342, 0, + 0, 2470, 0, + 0, 2599, 0, + 0, 2728, 0, + 0, 2859, 0, + 0, 2989, 0, + 0, 3120, 0, + 0, 3252, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3647, 0, + 901, 899, 1288, + 883, 907, 1282, + 859, 917, 1275, + 825, 931, 1265, + 775, 948, 1251, + 698, 970, 1231, + 569, 998, 1204, + 307, 1033, 1165, + 0, 1076, 1107, + 0, 1127, 1016, + 0, 1188, 855, + 0, 1259, 474, + 0, 1339, 0, + 0, 1428, 0, + 0, 1524, 0, + 0, 1628, 0, + 0, 1738, 0, + 0, 1852, 0, + 0, 1971, 0, + 0, 2093, 0, + 0, 2217, 0, + 0, 2343, 0, + 0, 2470, 0, + 0, 2599, 0, + 0, 2729, 0, + 0, 2859, 0, + 0, 2989, 0, + 0, 3120, 0, + 0, 3252, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3647, 0, + 1121, 919, 1346, + 1110, 927, 1341, + 1096, 937, 1335, + 1076, 949, 1326, + 1048, 966, 1314, + 1007, 987, 1297, + 947, 1014, 1274, + 850, 1048, 1241, + 677, 1089, 1192, + 240, 1140, 1117, + 0, 1199, 994, + 0, 1268, 747, + 0, 1347, 0, + 0, 1434, 0, + 0, 1530, 0, + 0, 1632, 0, + 0, 1741, 0, + 0, 1855, 0, + 0, 1973, 0, + 0, 2094, 0, + 0, 2218, 0, + 0, 2344, 0, + 0, 2471, 0, + 0, 2600, 0, + 0, 2729, 0, + 0, 2859, 0, + 0, 2990, 0, + 0, 3121, 0, + 0, 3252, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3647, 0, + 1309, 945, 1414, + 1302, 952, 1410, + 1293, 961, 1405, + 1280, 973, 1397, + 1262, 989, 1387, + 1237, 1009, 1372, + 1202, 1035, 1353, + 1149, 1067, 1325, + 1068, 1107, 1285, + 930, 1156, 1225, + 639, 1213, 1130, + 0, 1280, 962, + 0, 1357, 546, + 0, 1442, 0, + 0, 1536, 0, + 0, 1638, 0, + 0, 1745, 0, + 0, 1858, 0, + 0, 1976, 0, + 0, 2096, 0, + 0, 2220, 0, + 0, 2345, 0, + 0, 2472, 0, + 0, 2600, 0, + 0, 2729, 0, + 0, 2859, 0, + 0, 2990, 0, + 0, 3121, 0, + 0, 3252, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3647, 0, + 1479, 977, 1492, + 1475, 983, 1488, + 1468, 992, 1484, + 1460, 1003, 1477, + 1448, 1018, 1469, + 1431, 1037, 1457, + 1408, 1061, 1441, + 1376, 1092, 1418, + 1328, 1130, 1385, + 1255, 1176, 1338, + 1136, 1231, 1266, + 901, 1296, 1148, + 0, 1370, 916, + 0, 1453, 0, + 0, 1545, 0, + 0, 1645, 0, + 0, 1751, 0, + 0, 1863, 0, + 0, 1979, 0, + 0, 2099, 0, + 0, 2221, 0, + 0, 2346, 0, + 0, 2473, 0, + 0, 2601, 0, + 0, 2730, 0, + 0, 2860, 0, + 0, 2990, 0, + 0, 3121, 0, + 0, 3252, 0, + 0, 3384, 0, + 0, 3515, 0, + 0, 3647, 0, + 1638, 1016, 1579, + 1635, 1022, 1576, + 1630, 1030, 1572, + 1624, 1041, 1567, + 1616, 1054, 1559, + 1604, 1072, 1550, + 1589, 1094, 1537, + 1567, 1123, 1518, + 1537, 1158, 1492, + 1492, 1202, 1455, + 1425, 1254, 1401, + 1316, 1316, 1316, + 1111, 1387, 1169, + 459, 1468, 847, + 0, 1557, 0, + 0, 1654, 0, + 0, 1758, 0, + 0, 1869, 0, + 0, 1983, 0, + 0, 2102, 0, + 0, 2224, 0, + 0, 2348, 0, + 0, 2475, 0, + 0, 2602, 0, + 0, 2731, 0, + 0, 2861, 0, + 0, 2991, 0, + 0, 3121, 0, + 0, 3252, 0, + 0, 3384, 0, + 0, 3515, 0, + 0, 3647, 0, + 1789, 1064, 1673, + 1786, 1070, 1671, + 1783, 1077, 1668, + 1779, 1086, 1664, + 1773, 1099, 1658, + 1765, 1115, 1650, + 1754, 1135, 1640, + 1739, 1161, 1625, + 1719, 1194, 1605, + 1689, 1234, 1576, + 1647, 1283, 1535, + 1583, 1341, 1473, + 1481, 1409, 1375, + 1293, 1486, 1197, + 773, 1572, 733, + 0, 1667, 0, + 0, 1768, 0, + 0, 1876, 0, + 0, 1989, 0, + 0, 2107, 0, + 0, 2228, 0, + 0, 2351, 0, + 0, 2477, 0, + 0, 2604, 0, + 0, 2732, 0, + 0, 2861, 0, + 0, 2991, 0, + 0, 3122, 0, + 0, 3253, 0, + 0, 3384, 0, + 0, 3515, 0, + 0, 3647, 0, + 1934, 1121, 1775, + 1933, 1126, 1774, + 1930, 1133, 1771, + 1927, 1141, 1768, + 1923, 1152, 1763, + 1917, 1166, 1757, + 1910, 1184, 1749, + 1899, 1208, 1737, + 1885, 1237, 1721, + 1864, 1274, 1700, + 1836, 1319, 1668, + 1795, 1373, 1623, + 1734, 1436, 1555, + 1636, 1509, 1443, + 1460, 1592, 1231, + 1006, 1682, 516, + 0, 1781, 0, + 0, 1886, 0, + 0, 1997, 0, + 0, 2113, 0, + 0, 2232, 0, + 0, 2355, 0, + 0, 2479, 0, + 0, 2606, 0, + 0, 2734, 0, + 0, 2863, 0, + 0, 2992, 0, + 0, 3123, 0, + 0, 3253, 0, + 0, 3384, 0, + 0, 3516, 0, + 0, 3647, 0, + 2076, 1188, 1884, + 2075, 1192, 1882, + 2074, 1198, 1880, + 2071, 1205, 1878, + 2068, 1214, 1874, + 2064, 1227, 1869, + 2058, 1243, 1863, + 2051, 1264, 1854, + 2041, 1290, 1842, + 2026, 1323, 1825, + 2007, 1363, 1802, + 1979, 1413, 1768, + 1939, 1471, 1720, + 1879, 1539, 1645, + 1784, 1616, 1521, + 1616, 1703, 1274, + 1200, 1798, 0, + 0, 1899, 0, + 0, 2008, 0, + 0, 2121, 0, + 0, 2239, 0, + 0, 2359, 0, + 0, 2483, 0, + 0, 2609, 0, + 0, 2736, 0, + 0, 2864, 0, + 0, 2993, 0, + 0, 3123, 0, + 0, 3254, 0, + 0, 3385, 0, + 0, 3516, 0, + 0, 3648, 0, + 2216, 1264, 1997, + 2215, 1268, 1996, + 2214, 1272, 1995, + 2212, 1279, 1992, + 2210, 1287, 1990, + 2207, 1297, 1986, + 2203, 1311, 1981, + 2197, 1329, 1974, + 2190, 1352, 1965, + 2179, 1381, 1952, + 2165, 1417, 1935, + 2146, 1461, 1910, + 2119, 1513, 1875, + 2079, 1576, 1823, + 2021, 1648, 1743, + 1928, 1729, 1608, + 1765, 1819, 1325, + 1374, 1916, 0, + 0, 2021, 0, + 0, 2132, 0, + 0, 2247, 0, + 0, 2366, 0, + 0, 2488, 0, + 0, 2612, 0, + 0, 2739, 0, + 0, 2866, 0, + 0, 2995, 0, + 0, 3125, 0, + 0, 3255, 0, + 0, 3386, 0, + 0, 3517, 0, + 0, 3648, 0, + 2353, 1349, 2115, + 2353, 1352, 2114, + 2352, 1356, 2113, + 2350, 1361, 2111, + 2349, 1368, 2109, + 2347, 1377, 2106, + 2344, 1389, 2102, + 2340, 1404, 2097, + 2334, 1423, 2090, + 2327, 1448, 2080, + 2317, 1479, 2067, + 2303, 1518, 2049, + 2284, 1565, 2023, + 2257, 1621, 1987, + 2218, 1686, 1932, + 2160, 1761, 1848, + 2069, 1846, 1703, + 1910, 1938, 1386, + 1535, 2039, 0, + 0, 2145, 0, + 0, 2257, 0, + 0, 2374, 0, + 0, 2494, 0, + 0, 2617, 0, + 0, 2742, 0, + 0, 2869, 0, + 0, 2997, 0, + 0, 3126, 0, + 0, 3256, 0, + 0, 3386, 0, + 0, 3517, 0, + 0, 3648, 0, + 2489, 1443, 2236, + 2489, 1445, 2235, + 2488, 1449, 2234, + 2487, 1453, 2233, + 2486, 1458, 2231, + 2484, 1466, 2229, + 2482, 1475, 2226, + 2479, 1488, 2222, + 2475, 1504, 2217, + 2470, 1525, 2210, + 2462, 1551, 2200, + 2452, 1584, 2186, + 2439, 1625, 2167, + 2420, 1675, 2141, + 2393, 1733, 2103, + 2355, 1802, 2047, + 2297, 1879, 1958, + 2208, 1966, 1805, + 2051, 2061, 1456, + 1688, 2163, 0, + 0, 2271, 0, + 0, 2385, 0, + 0, 2502, 0, + 0, 2623, 0, + 0, 2747, 0, + 0, 2873, 0, + 0, 3000, 0, + 0, 3128, 0, + 0, 3258, 0, + 0, 3388, 0, + 0, 3518, 0, + 0, 3649, 0, + 2624, 1544, 2359, + 2624, 1546, 2359, + 2624, 1549, 2358, + 2623, 1552, 2357, + 2622, 1556, 2356, + 2621, 1562, 2354, + 2619, 1570, 2352, + 2617, 1580, 2349, + 2614, 1593, 2345, + 2610, 1611, 2340, + 2605, 1633, 2332, + 2597, 1661, 2322, + 2587, 1695, 2308, + 2574, 1738, 2289, + 2555, 1789, 2262, + 2528, 1850, 2223, + 2490, 1921, 2165, + 2433, 2000, 2074, + 2345, 2089, 1914, + 2190, 2186, 1535, + 1835, 2289, 0, + 0, 2399, 0, + 0, 2513, 0, + 0, 2632, 0, + 0, 2753, 0, + 0, 2877, 0, + 0, 3004, 0, + 0, 3131, 0, + 0, 3260, 0, + 0, 3389, 0, + 0, 3519, 0, + 0, 3650, 0, + 2759, 1651, 2485, + 2758, 1653, 2485, + 2758, 1655, 2484, + 2758, 1658, 2483, + 2757, 1661, 2482, + 2756, 1666, 2481, + 2755, 1672, 2480, + 2753, 1680, 2477, + 2751, 1691, 2474, + 2748, 1705, 2470, + 2744, 1723, 2465, + 2739, 1746, 2457, + 2731, 1775, 2447, + 2721, 1811, 2433, + 2708, 1855, 2413, + 2689, 1908, 2385, + 2663, 1971, 2346, + 2625, 2043, 2287, + 2568, 2124, 2193, + 2480, 2214, 2027, + 2327, 2312, 1623, + 1978, 2417, 0, + 0, 2527, 0, + 0, 2643, 0, + 0, 2762, 0, + 0, 2884, 0, + 0, 3008, 0, + 0, 3135, 0, + 0, 3262, 0, + 0, 3391, 0, + 0, 3521, 0, + 0, 3651, 0, + 2892, 1764, 2612, + 2892, 1765, 2612, + 2892, 1767, 2612, + 2892, 1769, 2611, + 2891, 1772, 2610, + 2890, 1775, 2609, + 2889, 1780, 2608, + 2888, 1787, 2606, + 2887, 1795, 2604, + 2884, 1806, 2601, + 2882, 1821, 2597, + 2878, 1839, 2591, + 2872, 1863, 2584, + 2865, 1893, 2573, + 2855, 1930, 2559, + 2842, 1976, 2539, + 2823, 2030, 2511, + 2797, 2094, 2471, + 2759, 2167, 2411, + 2703, 2250, 2315, + 2615, 2341, 2145, + 2463, 2440, 1720, + 2118, 2546, 0, + 0, 2657, 0, + 0, 2773, 0, + 0, 2892, 0, + 0, 3015, 0, + 0, 3140, 0, + 0, 3266, 0, + 0, 3394, 0, + 0, 3523, 0, + 0, 3653, 0, + 3026, 1881, 2741, + 3026, 1882, 2740, + 3025, 1883, 2740, + 3025, 1885, 2740, + 3025, 1887, 2739, + 3024, 1890, 2738, + 3024, 1894, 2737, + 3023, 1899, 2736, + 3021, 1905, 2734, + 3020, 1914, 2732, + 3018, 1926, 2729, + 3015, 1940, 2725, + 3011, 1960, 2719, + 3005, 1984, 2712, + 2998, 2015, 2701, + 2988, 2053, 2687, + 2975, 2099, 2667, + 2956, 2154, 2638, + 2930, 2219, 2598, + 2892, 2294, 2537, + 2836, 2377, 2440, + 2749, 2469, 2266, + 2598, 2569, 1823, + 2256, 2675, 0, + 0, 2787, 0, + 0, 2903, 0, + 0, 3023, 0, + 0, 3146, 0, + 0, 3271, 0, + 0, 3398, 0, + 0, 3526, 0, + 0, 3655, 0, + 3159, 2002, 2870, + 3159, 2002, 2870, + 3158, 2003, 2870, + 3158, 2005, 2869, + 3158, 2006, 2869, + 3158, 2008, 2868, + 3157, 2011, 2868, + 3156, 2015, 2867, + 3156, 2020, 2865, + 3154, 2027, 2864, + 3153, 2036, 2861, + 3151, 2048, 2858, + 3148, 2063, 2854, + 3144, 2082, 2848, + 3138, 2107, 2840, + 3131, 2139, 2830, + 3121, 2177, 2815, + 3108, 2224, 2795, + 3089, 2280, 2767, + 3063, 2346, 2726, + 3025, 2421, 2664, + 2970, 2506, 2566, + 2883, 2598, 2390, + 2732, 2699, 1933, + 2392, 2805, 0, + 0, 2918, 0, + 0, 3034, 0, + 0, 3154, 0, + 0, 3277, 0, + 0, 3403, 0, + 0, 3529, 0, + 0, 3658, 0, + 3291, 2125, 3000, + 3291, 2125, 3000, + 3291, 2126, 3000, + 3291, 2127, 2999, + 3291, 2128, 2999, + 3291, 2130, 2999, + 3290, 2132, 2998, + 3290, 2135, 2997, + 3289, 2139, 2996, + 3288, 2145, 2995, + 3287, 2151, 2993, + 3285, 2161, 2991, + 3283, 2172, 2988, + 3280, 2188, 2984, + 3276, 2208, 2978, + 3271, 2233, 2970, + 3264, 2264, 2960, + 3254, 2304, 2945, + 3241, 2351, 2925, + 3222, 2408, 2896, + 3196, 2474, 2855, + 3158, 2550, 2793, + 3103, 2635, 2694, + 3016, 2728, 2515, + 2865, 2829, 2047, + 2527, 2936, 0, + 0, 3049, 0, + 0, 3166, 0, + 0, 3286, 0, + 0, 3409, 0, + 0, 3534, 0, + 0, 3661, 0, + 3424, 2250, 3130, + 3424, 2251, 3130, + 3424, 2251, 3130, + 3424, 2252, 3130, + 3424, 2253, 3130, + 3423, 2254, 3130, + 3423, 2256, 3129, + 3423, 2258, 3129, + 3422, 2261, 3128, + 3422, 2265, 3127, + 3421, 2271, 3126, + 3420, 2278, 3124, + 3418, 2287, 3122, + 3416, 2299, 3118, + 3413, 2314, 3114, + 3409, 2334, 3108, + 3404, 2360, 3101, + 3396, 2392, 3090, + 3387, 2431, 3075, + 3373, 2479, 3055, + 3355, 2537, 3026, + 3328, 2603, 2984, + 3291, 2680, 2922, + 3235, 2765, 2823, + 3149, 2859, 2643, + 2999, 2960, 2165, + 2662, 3067, 0, + 0, 3180, 0, + 0, 3297, 0, + 0, 3418, 0, + 0, 3541, 0, + 0, 3666, 0, + 3557, 2377, 3261, + 3557, 2378, 3261, + 3556, 2378, 3261, + 3556, 2379, 3261, + 3556, 2379, 3261, + 3556, 2380, 3261, + 3556, 2382, 3260, + 3556, 2383, 3260, + 3555, 2386, 3259, + 3555, 2389, 3259, + 3554, 2393, 3258, + 3553, 2398, 3256, + 3552, 2405, 3255, + 3550, 2414, 3252, + 3548, 2427, 3249, + 3545, 2442, 3245, + 3541, 2462, 3239, + 3536, 2488, 3231, + 3529, 2520, 3221, + 3519, 2560, 3206, + 3506, 2609, 3185, + 3487, 2666, 3157, + 3461, 2733, 3115, + 3423, 2810, 3052, + 3368, 2896, 2952, + 3281, 2989, 2771, + 3131, 3091, 2287, + 2795, 3198, 0, + 0, 3311, 0, + 0, 3429, 0, + 0, 3549, 0, + 0, 3673, 0, + 3689, 2506, 3393, + 3689, 2506, 3393, + 3689, 2506, 3392, + 3689, 2506, 3392, + 3689, 2507, 3392, + 3689, 2508, 3392, + 3688, 2509, 3392, + 3688, 2510, 3392, + 3688, 2512, 3391, + 3688, 2514, 3391, + 3687, 2517, 3390, + 3686, 2521, 3389, + 3686, 2527, 3388, + 3684, 2534, 3386, + 3683, 2543, 3383, + 3681, 2555, 3380, + 3678, 2571, 3376, + 3674, 2592, 3370, + 3668, 2617, 3362, + 3661, 2650, 3352, + 3651, 2690, 3337, + 3638, 2739, 3316, + 3619, 2796, 3287, + 3593, 2864, 3246, + 3556, 2941, 3183, + 3500, 3026, 3083, + 3414, 3121, 2900, + 3264, 3222, 2411, + 2929, 3330, 0, + 0, 3443, 0, + 0, 3560, 0, + 0, 3681, 0, + 3821, 2635, 3524, + 3821, 2635, 3524, + 3821, 2635, 3524, + 3821, 2635, 3524, + 3821, 2636, 3524, + 3821, 2636, 3524, + 3821, 2637, 3523, + 3821, 2638, 3523, + 3821, 2639, 3523, + 3820, 2641, 3523, + 3820, 2644, 3522, + 3819, 2647, 3521, + 3819, 2651, 3520, + 3818, 2656, 3519, + 3817, 2663, 3517, + 3815, 2673, 3515, + 3813, 2685, 3512, + 3810, 2701, 3507, + 3806, 2721, 3502, + 3801, 2747, 3494, + 3794, 2780, 3483, + 3784, 2820, 3468, + 3770, 2869, 3448, + 3752, 2927, 3419, + 3726, 2995, 3377, + 3688, 3072, 3314, + 3633, 3158, 3213, + 3546, 3252, 3030, + 3397, 3354, 2537, + 3062, 3462, 0, + 0, 3575, 0, + 0, 3692, 0, + 3953, 2765, 3656, + 3953, 2765, 3656, + 3953, 2765, 3656, + 3953, 2765, 3656, + 3953, 2765, 3655, + 3953, 2766, 3655, + 3953, 2766, 3655, + 3953, 2767, 3655, + 3953, 2768, 3655, + 3953, 2770, 3655, + 3952, 2771, 3654, + 3952, 2774, 3654, + 3952, 2777, 3653, + 3951, 2781, 3652, + 3950, 2786, 3651, + 3949, 2793, 3649, + 3947, 2803, 3646, + 3945, 2815, 3643, + 3942, 2831, 3639, + 3938, 2852, 3633, + 3933, 2878, 3625, + 3926, 2911, 3615, + 3916, 2951, 3600, + 3903, 3000, 3579, + 3884, 3058, 3550, + 3858, 3126, 3508, + 3821, 3203, 3445, + 3765, 3289, 3344, + 3679, 3384, 3161, + 3529, 3485, 2664, + 3195, 3593, 0, + 0, 3707, 0, + 4086, 2895, 3787, + 4086, 2895, 3787, + 4086, 2895, 3787, + 4086, 2896, 3787, + 4086, 2896, 3787, + 4086, 2896, 3787, + 4086, 2896, 3787, + 4085, 2897, 3787, + 4085, 2898, 3787, + 4085, 2899, 3787, + 4085, 2900, 3786, + 4085, 2902, 3786, + 4084, 2904, 3785, + 4084, 2907, 3785, + 4083, 2911, 3784, + 4082, 2917, 3782, + 4081, 2924, 3780, + 4079, 2934, 3778, + 4077, 2946, 3775, + 4074, 2962, 3771, + 4070, 2983, 3765, + 4065, 3009, 3757, + 4058, 3042, 3746, + 4048, 3082, 3731, + 4035, 3131, 3711, + 4016, 3189, 3682, + 3990, 3257, 3640, + 3953, 3334, 3577, + 3897, 3421, 3476, + 3811, 3515, 3292, + 3662, 3617, 2793, + 3327, 3725, 0, + 4095, 3026, 3919, + 4095, 3026, 3919, + 4095, 3026, 3919, + 4095, 3026, 3919, + 4095, 3026, 3919, + 4095, 3027, 3919, + 4095, 3027, 3919, + 4095, 3027, 3919, + 4095, 3028, 3919, + 4095, 3029, 3919, + 4095, 3030, 3918, + 4095, 3031, 3918, + 4095, 3033, 3918, + 4095, 3035, 3917, + 4095, 3038, 3916, + 4095, 3042, 3915, + 4095, 3048, 3914, + 4095, 3055, 3912, + 4095, 3065, 3910, + 4095, 3077, 3907, + 4095, 3093, 3902, + 4095, 3114, 3897, + 4095, 3140, 3889, + 4095, 3173, 3878, + 4095, 3213, 3863, + 4095, 3263, 3843, + 4095, 3321, 3813, + 4095, 3389, 3771, + 4085, 3466, 3708, + 4030, 3552, 3607, + 3943, 3647, 3423, + 3794, 3749, 2922, + 4095, 3157, 4051, + 4095, 3157, 4051, + 4095, 3157, 4051, + 4095, 3157, 4051, + 4095, 3157, 4051, + 4095, 3158, 4051, + 4095, 3158, 4051, + 4095, 3158, 4051, + 4095, 3159, 4051, + 4095, 3159, 4051, + 4095, 3160, 4050, + 4095, 3161, 4050, + 4095, 3162, 4050, + 4095, 3164, 4049, + 4095, 3166, 4049, + 4095, 3170, 4048, + 4095, 3174, 4047, + 4095, 3179, 4046, + 4095, 3186, 4044, + 4095, 3196, 4042, + 4095, 3208, 4039, + 4095, 3224, 4034, + 4095, 3245, 4028, + 4095, 3271, 4021, + 4095, 3304, 4010, + 4095, 3345, 3995, + 4095, 3394, 3974, + 4095, 3453, 3945, + 4095, 3520, 3903, + 4095, 3598, 3840, + 4095, 3684, 3739, + 4075, 3779, 3555, + 0, 966, 1218, + 0, 973, 1211, + 0, 982, 1202, + 0, 994, 1191, + 0, 1009, 1174, + 0, 1028, 1151, + 0, 1053, 1119, + 0, 1084, 1071, + 0, 1122, 999, + 0, 1169, 879, + 0, 1225, 645, + 0, 1291, 0, + 0, 1366, 0, + 0, 1450, 0, + 0, 1542, 0, + 0, 1643, 0, + 0, 1749, 0, + 0, 1861, 0, + 0, 1978, 0, + 0, 2098, 0, + 0, 2221, 0, + 0, 2346, 0, + 0, 2473, 0, + 0, 2601, 0, + 0, 2730, 0, + 0, 2860, 0, + 0, 2990, 0, + 0, 3121, 0, + 0, 3252, 0, + 0, 3383, 0, + 0, 3515, 0, + 0, 3647, 0, + 0, 969, 1227, + 0, 975, 1221, + 0, 984, 1212, + 0, 996, 1201, + 0, 1011, 1185, + 0, 1030, 1162, + 0, 1055, 1130, + 0, 1086, 1084, + 0, 1124, 1014, + 0, 1171, 899, + 0, 1226, 677, + 0, 1292, 0, + 0, 1367, 0, + 0, 1451, 0, + 0, 1543, 0, + 0, 1643, 0, + 0, 1750, 0, + 0, 1862, 0, + 0, 1978, 0, + 0, 2098, 0, + 0, 2221, 0, + 0, 2346, 0, + 0, 2473, 0, + 0, 2601, 0, + 0, 2730, 0, + 0, 2860, 0, + 0, 2990, 0, + 0, 3121, 0, + 0, 3252, 0, + 0, 3384, 0, + 0, 3515, 0, + 0, 3647, 0, + 0, 972, 1239, + 0, 978, 1233, + 0, 987, 1225, + 0, 999, 1214, + 0, 1014, 1198, + 0, 1033, 1176, + 0, 1057, 1146, + 0, 1088, 1101, + 0, 1126, 1033, + 0, 1173, 924, + 0, 1228, 717, + 0, 1293, 53, + 0, 1368, 0, + 0, 1452, 0, + 0, 1544, 0, + 0, 1644, 0, + 0, 1750, 0, + 0, 1862, 0, + 0, 1978, 0, + 0, 2098, 0, + 0, 2221, 0, + 0, 2346, 0, + 0, 2473, 0, + 0, 2601, 0, + 0, 2730, 0, + 0, 2860, 0, + 0, 2990, 0, + 0, 3121, 0, + 0, 3252, 0, + 0, 3384, 0, + 0, 3515, 0, + 0, 3647, 0, + 0, 976, 1255, + 0, 982, 1249, + 0, 991, 1241, + 0, 1002, 1230, + 0, 1017, 1215, + 0, 1036, 1195, + 0, 1061, 1165, + 0, 1091, 1122, + 0, 1129, 1058, + 0, 1175, 955, + 0, 1231, 766, + 0, 1295, 233, + 0, 1370, 0, + 0, 1453, 0, + 0, 1545, 0, + 0, 1645, 0, + 0, 1751, 0, + 0, 1863, 0, + 0, 1979, 0, + 0, 2099, 0, + 0, 2221, 0, + 0, 2346, 0, + 0, 2473, 0, + 0, 2601, 0, + 0, 2730, 0, + 0, 2860, 0, + 0, 2990, 0, + 0, 3121, 0, + 0, 3252, 0, + 0, 3384, 0, + 0, 3515, 0, + 0, 3647, 0, + 0, 981, 1276, + 0, 988, 1270, + 0, 996, 1263, + 0, 1008, 1252, + 0, 1022, 1238, + 0, 1041, 1218, + 0, 1065, 1190, + 0, 1095, 1150, + 0, 1133, 1090, + 0, 1179, 994, + 0, 1234, 824, + 0, 1298, 398, + 0, 1372, 0, + 0, 1455, 0, + 0, 1547, 0, + 0, 1646, 0, + 0, 1752, 0, + 0, 1863, 0, + 0, 1979, 0, + 0, 2099, 0, + 0, 2222, 0, + 0, 2347, 0, + 0, 2473, 0, + 0, 2601, 0, + 0, 2730, 0, + 0, 2860, 0, + 0, 2990, 0, + 0, 3121, 0, + 0, 3252, 0, + 0, 3384, 0, + 0, 3515, 0, + 0, 3647, 0, + 0, 988, 1302, + 0, 995, 1297, + 0, 1003, 1289, + 0, 1014, 1280, + 0, 1029, 1266, + 0, 1047, 1247, + 0, 1071, 1221, + 0, 1101, 1184, + 0, 1138, 1128, + 0, 1183, 1041, + 0, 1238, 891, + 0, 1301, 553, + 0, 1375, 0, + 0, 1457, 0, + 0, 1549, 0, + 0, 1648, 0, + 0, 1753, 0, + 0, 1864, 0, + 0, 1980, 0, + 0, 2100, 0, + 0, 2222, 0, + 0, 2347, 0, + 0, 2474, 0, + 0, 2601, 0, + 0, 2730, 0, + 0, 2860, 0, + 0, 2990, 0, + 0, 3121, 0, + 0, 3252, 0, + 0, 3384, 0, + 0, 3515, 0, + 0, 3647, 0, + 329, 998, 1335, + 265, 1004, 1330, + 164, 1012, 1323, + 0, 1023, 1314, + 0, 1037, 1301, + 0, 1055, 1284, + 0, 1079, 1260, + 0, 1108, 1226, + 0, 1145, 1175, + 0, 1189, 1098, + 0, 1243, 968, + 0, 1306, 702, + 0, 1379, 0, + 0, 1461, 0, + 0, 1551, 0, + 0, 1650, 0, + 0, 1755, 0, + 0, 1866, 0, + 0, 1981, 0, + 0, 2101, 0, + 0, 2223, 0, + 0, 2347, 0, + 0, 2474, 0, + 0, 2602, 0, + 0, 2731, 0, + 0, 2860, 0, + 0, 2991, 0, + 0, 3121, 0, + 0, 3252, 0, + 0, 3384, 0, + 0, 3515, 0, + 0, 3647, 0, + 770, 1010, 1375, + 747, 1016, 1370, + 715, 1024, 1364, + 667, 1035, 1356, + 594, 1048, 1345, + 474, 1066, 1329, + 239, 1089, 1307, + 0, 1118, 1276, + 0, 1154, 1232, + 0, 1197, 1164, + 0, 1250, 1054, + 0, 1312, 846, + 0, 1384, 171, + 0, 1465, 0, + 0, 1555, 0, + 0, 1653, 0, + 0, 1757, 0, + 0, 1868, 0, + 0, 1983, 0, + 0, 2102, 0, + 0, 2224, 0, + 0, 2348, 0, + 0, 2474, 0, + 0, 2602, 0, + 0, 2731, 0, + 0, 2860, 0, + 0, 2991, 0, + 0, 3121, 0, + 0, 3252, 0, + 0, 3384, 0, + 0, 3515, 0, + 0, 3647, 0, + 1045, 1025, 1424, + 1033, 1031, 1420, + 1016, 1039, 1414, + 992, 1049, 1407, + 957, 1063, 1397, + 907, 1080, 1383, + 830, 1102, 1364, + 702, 1130, 1336, + 440, 1165, 1297, + 0, 1208, 1239, + 0, 1260, 1148, + 0, 1321, 987, + 0, 1391, 606, + 0, 1471, 0, + 0, 1560, 0, + 0, 1657, 0, + 0, 1760, 0, + 0, 1870, 0, + 0, 1985, 0, + 0, 2103, 0, + 0, 2225, 0, + 0, 2349, 0, + 0, 2475, 0, + 0, 2603, 0, + 0, 2731, 0, + 0, 2861, 0, + 0, 2991, 0, + 0, 3122, 0, + 0, 3253, 0, + 0, 3384, 0, + 0, 3515, 0, + 0, 3647, 0, + 1261, 1046, 1482, + 1253, 1051, 1478, + 1242, 1059, 1473, + 1228, 1069, 1467, + 1208, 1082, 1458, + 1180, 1098, 1446, + 1139, 1119, 1429, + 1079, 1146, 1406, + 982, 1180, 1373, + 810, 1222, 1324, + 372, 1272, 1249, + 0, 1331, 1126, + 0, 1400, 879, + 0, 1479, 0, + 0, 1566, 0, + 0, 1662, 0, + 0, 1764, 0, + 0, 1873, 0, + 0, 1987, 0, + 0, 2105, 0, + 0, 2226, 0, + 0, 2350, 0, + 0, 2476, 0, + 0, 2603, 0, + 0, 2732, 0, + 0, 2861, 0, + 0, 2991, 0, + 0, 3122, 0, + 0, 3253, 0, + 0, 3384, 0, + 0, 3515, 0, + 0, 3647, 0, + 1446, 1072, 1550, + 1441, 1077, 1546, + 1434, 1084, 1542, + 1425, 1093, 1537, + 1412, 1105, 1529, + 1394, 1121, 1519, + 1370, 1141, 1505, + 1334, 1167, 1485, + 1282, 1199, 1457, + 1200, 1239, 1417, + 1063, 1288, 1357, + 771, 1345, 1263, + 0, 1412, 1094, + 0, 1489, 678, + 0, 1575, 0, + 0, 1668, 0, + 0, 1770, 0, + 0, 1877, 0, + 0, 1990, 0, + 0, 2108, 0, + 0, 2228, 0, + 0, 2352, 0, + 0, 2477, 0, + 0, 2604, 0, + 0, 2732, 0, + 0, 2862, 0, + 0, 2992, 0, + 0, 3122, 0, + 0, 3253, 0, + 0, 3384, 0, + 0, 3515, 0, + 0, 3647, 0, + 1615, 1104, 1627, + 1611, 1109, 1624, + 1607, 1115, 1621, + 1600, 1124, 1616, + 1592, 1135, 1609, + 1580, 1150, 1601, + 1563, 1169, 1589, + 1540, 1193, 1573, + 1508, 1224, 1550, + 1460, 1262, 1518, + 1388, 1308, 1470, + 1268, 1363, 1398, + 1033, 1428, 1280, + 0, 1502, 1048, + 0, 1585, 57, + 0, 1677, 0, + 0, 1777, 0, + 0, 1883, 0, + 0, 1995, 0, + 0, 2111, 0, + 0, 2231, 0, + 0, 2354, 0, + 0, 2479, 0, + 0, 2605, 0, + 0, 2733, 0, + 0, 2862, 0, + 0, 2992, 0, + 0, 3122, 0, + 0, 3253, 0, + 0, 3384, 0, + 0, 3516, 0, + 0, 3647, 0, + 1772, 1144, 1713, + 1770, 1148, 1711, + 1767, 1154, 1708, + 1762, 1162, 1704, + 1756, 1173, 1699, + 1748, 1186, 1692, + 1737, 1204, 1682, + 1721, 1226, 1669, + 1699, 1255, 1650, + 1669, 1290, 1624, + 1624, 1334, 1588, + 1557, 1386, 1533, + 1448, 1448, 1448, + 1243, 1519, 1301, + 591, 1600, 979, + 0, 1689, 0, + 0, 1786, 0, + 0, 1891, 0, + 0, 2001, 0, + 0, 2116, 0, + 0, 2234, 0, + 0, 2356, 0, + 0, 2481, 0, + 0, 2607, 0, + 0, 2734, 0, + 0, 2863, 0, + 0, 2993, 0, + 0, 3123, 0, + 0, 3254, 0, + 0, 3385, 0, + 0, 3516, 0, + 0, 3647, 0, + 1923, 1192, 1807, + 1921, 1196, 1805, + 1919, 1202, 1803, + 1915, 1209, 1800, + 1911, 1218, 1796, + 1905, 1231, 1790, + 1897, 1247, 1782, + 1886, 1267, 1772, + 1871, 1293, 1757, + 1851, 1326, 1737, + 1821, 1366, 1708, + 1779, 1415, 1667, + 1715, 1473, 1605, + 1613, 1541, 1507, + 1426, 1618, 1329, + 905, 1704, 865, + 0, 1799, 0, + 0, 1900, 0, + 0, 2008, 0, + 0, 2122, 0, + 0, 2239, 0, + 0, 2360, 0, + 0, 2483, 0, + 0, 2609, 0, + 0, 2736, 0, + 0, 2864, 0, + 0, 2994, 0, + 0, 3124, 0, + 0, 3254, 0, + 0, 3385, 0, + 0, 3516, 0, + 0, 3648, 0, + 2068, 1250, 1909, + 2067, 1253, 1908, + 2065, 1258, 1906, + 2063, 1265, 1903, + 2059, 1273, 1900, + 2055, 1284, 1895, + 2049, 1298, 1889, + 2042, 1317, 1881, + 2031, 1340, 1869, + 2017, 1370, 1854, + 1997, 1406, 1832, + 1968, 1451, 1801, + 1927, 1505, 1755, + 1866, 1569, 1687, + 1768, 1641, 1575, + 1592, 1724, 1364, + 1138, 1815, 648, + 0, 1913, 0, + 0, 2018, 0, + 0, 2129, 0, + 0, 2245, 0, + 0, 2364, 0, + 0, 2487, 0, + 0, 2612, 0, + 0, 2738, 0, + 0, 2866, 0, + 0, 2995, 0, + 0, 3124, 0, + 0, 3255, 0, + 0, 3385, 0, + 0, 3516, 0, + 0, 3648, 0, + 2210, 1317, 2017, + 2209, 1320, 2016, + 2207, 1324, 2014, + 2206, 1330, 2012, + 2203, 1337, 2010, + 2200, 1347, 2006, + 2196, 1359, 2001, + 2191, 1375, 1995, + 2183, 1396, 1986, + 2173, 1422, 1974, + 2158, 1455, 1957, + 2139, 1496, 1934, + 2111, 1545, 1900, + 2071, 1603, 1852, + 2011, 1671, 1777, + 1916, 1749, 1653, + 1748, 1835, 1406, + 1333, 1930, 0, + 0, 2032, 0, + 0, 2140, 0, + 0, 2253, 0, + 0, 2371, 0, + 0, 2492, 0, + 0, 2615, 0, + 0, 2741, 0, + 0, 2868, 0, + 0, 2996, 0, + 0, 3126, 0, + 0, 3256, 0, + 0, 3386, 0, + 0, 3517, 0, + 0, 3648, 0, + 2349, 1394, 2130, + 2348, 1396, 2129, + 2347, 1400, 2128, + 2346, 1404, 2127, + 2344, 1411, 2125, + 2342, 1419, 2122, + 2339, 1429, 2118, + 2335, 1443, 2113, + 2329, 1461, 2106, + 2322, 1484, 2097, + 2312, 1513, 2084, + 2298, 1549, 2067, + 2278, 1593, 2042, + 2251, 1646, 2007, + 2211, 1708, 1955, + 2153, 1780, 1875, + 2061, 1861, 1740, + 1898, 1951, 1457, + 1507, 2049, 0, + 0, 2153, 0, + 0, 2264, 0, + 0, 2379, 0, + 0, 2498, 0, + 0, 2620, 0, + 0, 2744, 0, + 0, 2871, 0, + 0, 2998, 0, + 0, 3127, 0, + 0, 3257, 0, + 0, 3387, 0, + 0, 3518, 0, + 0, 3649, 0, + 2486, 1479, 2248, + 2485, 1482, 2247, + 2485, 1484, 2246, + 2484, 1488, 2245, + 2483, 1493, 2243, + 2481, 1500, 2241, + 2479, 1509, 2238, + 2476, 1521, 2234, + 2472, 1536, 2229, + 2466, 1555, 2222, + 2459, 1580, 2213, + 2449, 1611, 2199, + 2435, 1650, 2181, + 2416, 1697, 2155, + 2389, 1753, 2119, + 2350, 1818, 2064, + 2292, 1893, 1980, + 2201, 1978, 1835, + 2042, 2070, 1518, + 1668, 2171, 0, + 0, 2277, 0, + 0, 2389, 0, + 0, 2506, 0, + 0, 2626, 0, + 0, 2749, 0, + 0, 2874, 0, + 0, 3001, 0, + 0, 3129, 0, + 0, 3258, 0, + 0, 3388, 0, + 0, 3519, 0, + 0, 3649, 0, + 2622, 1573, 2368, + 2621, 1575, 2368, + 2621, 1578, 2367, + 2620, 1581, 2366, + 2619, 1585, 2365, + 2618, 1590, 2363, + 2616, 1598, 2361, + 2614, 1607, 2358, + 2611, 1620, 2354, + 2607, 1636, 2349, + 2602, 1657, 2342, + 2595, 1683, 2332, + 2585, 1716, 2318, + 2571, 1757, 2299, + 2552, 1807, 2273, + 2525, 1865, 2235, + 2487, 1934, 2179, + 2430, 2011, 2091, + 2340, 2098, 1937, + 2183, 2193, 1588, + 1820, 2295, 0, + 0, 2403, 0, + 0, 2517, 0, + 0, 2634, 0, + 0, 2755, 0, + 0, 2879, 0, + 0, 3005, 0, + 0, 3132, 0, + 0, 3260, 0, + 0, 3390, 0, + 0, 3520, 0, + 0, 3650, 0, + 2757, 1675, 2492, + 2756, 1676, 2491, + 2756, 1678, 2491, + 2756, 1681, 2490, + 2755, 1684, 2489, + 2754, 1688, 2488, + 2753, 1694, 2486, + 2751, 1702, 2484, + 2749, 1712, 2481, + 2746, 1726, 2477, + 2742, 1743, 2472, + 2737, 1765, 2464, + 2729, 1793, 2454, + 2719, 1827, 2440, + 2706, 1870, 2421, + 2687, 1922, 2394, + 2660, 1982, 2355, + 2622, 2053, 2297, + 2566, 2132, 2206, + 2477, 2221, 2046, + 2322, 2318, 1667, + 1967, 2421, 0, + 0, 2531, 0, + 0, 2645, 0, + 0, 2764, 0, + 0, 2885, 0, + 0, 3010, 0, + 0, 3136, 0, + 0, 3263, 0, + 0, 3392, 0, + 0, 3521, 0, + 0, 3651, 0, + 2891, 1782, 2617, + 2891, 1784, 2617, + 2890, 1785, 2617, + 2890, 1787, 2616, + 2890, 1790, 2615, + 2889, 1793, 2615, + 2888, 1798, 2613, + 2887, 1804, 2612, + 2885, 1812, 2609, + 2883, 1823, 2606, + 2880, 1837, 2602, + 2876, 1855, 2597, + 2871, 1878, 2589, + 2863, 1907, 2579, + 2854, 1943, 2565, + 2840, 1987, 2545, + 2821, 2040, 2518, + 2795, 2103, 2478, + 2757, 2175, 2419, + 2701, 2256, 2325, + 2612, 2346, 2159, + 2459, 2444, 1755, + 2110, 2549, 0, + 0, 2659, 0, + 0, 2775, 0, + 0, 2894, 0, + 0, 3016, 0, + 0, 3140, 0, + 0, 3267, 0, + 0, 3395, 0, + 0, 3523, 0, + 0, 3653, 0, + 3025, 1895, 2745, + 3024, 1896, 2744, + 3024, 1897, 2744, + 3024, 1899, 2744, + 3024, 1901, 2743, + 3023, 1904, 2742, + 3022, 1908, 2741, + 3022, 1912, 2740, + 3020, 1919, 2738, + 3019, 1927, 2736, + 3017, 1938, 2733, + 3014, 1953, 2729, + 3010, 1971, 2723, + 3004, 1995, 2716, + 2997, 2025, 2705, + 2987, 2062, 2691, + 2974, 2108, 2671, + 2955, 2162, 2643, + 2929, 2226, 2603, + 2891, 2299, 2543, + 2835, 2382, 2447, + 2747, 2473, 2277, + 2595, 2572, 1852, + 2250, 2678, 0, + 0, 2789, 0, + 0, 2905, 0, + 0, 3024, 0, + 0, 3147, 0, + 0, 3272, 0, + 0, 3398, 0, + 0, 3526, 0, + 0, 3655, 0, + 3158, 2013, 2873, + 3158, 2013, 2873, + 3158, 2014, 2872, + 3157, 2015, 2872, + 3157, 2017, 2872, + 3157, 2019, 2871, + 3156, 2022, 2871, + 3156, 2026, 2870, + 3155, 2031, 2868, + 3154, 2038, 2867, + 3152, 2046, 2864, + 3150, 2058, 2861, + 3147, 2073, 2857, + 3143, 2092, 2851, + 3138, 2116, 2844, + 3130, 2147, 2833, + 3120, 2185, 2819, + 3107, 2231, 2799, + 3088, 2286, 2770, + 3062, 2351, 2730, + 3024, 2426, 2669, + 2968, 2509, 2572, + 2881, 2601, 2398, + 2730, 2701, 1955, + 2388, 2807, 0, + 0, 2919, 0, + 0, 3035, 0, + 0, 3155, 0, + 0, 3278, 0, + 0, 3403, 0, + 0, 3530, 0, + 0, 3658, 0, + 3291, 2133, 3002, + 3291, 2134, 3002, + 3291, 2135, 3002, + 3291, 2135, 3002, + 3290, 2137, 3001, + 3290, 2138, 3001, + 3290, 2141, 3000, + 3289, 2143, 3000, + 3288, 2147, 2999, + 3288, 2153, 2997, + 3286, 2159, 2996, + 3285, 2168, 2993, + 3283, 2180, 2990, + 3280, 2195, 2986, + 3276, 2215, 2980, + 3270, 2239, 2973, + 3263, 2271, 2962, + 3253, 2309, 2947, + 3240, 2356, 2927, + 3221, 2412, 2899, + 3195, 2478, 2858, + 3157, 2553, 2796, + 3102, 2638, 2698, + 3015, 2730, 2522, + 2864, 2831, 2065, + 2524, 2938, 0, + 0, 3050, 0, + 0, 3166, 0, + 0, 3287, 0, + 0, 3410, 0, + 0, 3535, 0, + 0, 3662, 0, + 3424, 2257, 3132, + 3424, 2257, 3132, + 3423, 2258, 3132, + 3423, 2258, 3132, + 3423, 2259, 3132, + 3423, 2261, 3131, + 3423, 2262, 3131, + 3422, 2264, 3130, + 3422, 2267, 3130, + 3421, 2271, 3129, + 3420, 2277, 3127, + 3419, 2284, 3126, + 3417, 2293, 3123, + 3415, 2304, 3120, + 3412, 2320, 3116, + 3408, 2340, 3110, + 3403, 2365, 3102, + 3396, 2397, 3092, + 3386, 2436, 3077, + 3373, 2483, 3057, + 3354, 2540, 3028, + 3328, 2606, 2987, + 3290, 2682, 2925, + 3235, 2767, 2826, + 3148, 2860, 2647, + 2997, 2961, 2179, + 2659, 3068, 0, + 0, 3181, 0, + 0, 3298, 0, + 0, 3418, 0, + 0, 3541, 0, + 0, 3666, 0, + 3556, 2382, 3263, + 3556, 2382, 3263, + 3556, 2383, 3262, + 3556, 2383, 3262, + 3556, 2384, 3262, + 3556, 2385, 3262, + 3556, 2386, 3262, + 3555, 2388, 3261, + 3555, 2390, 3261, + 3554, 2393, 3260, + 3554, 2397, 3259, + 3553, 2403, 3258, + 3552, 2410, 3256, + 3550, 2419, 3254, + 3548, 2431, 3250, + 3545, 2446, 3246, + 3541, 2466, 3240, + 3536, 2492, 3233, + 3529, 2524, 3222, + 3519, 2564, 3207, + 3505, 2612, 3187, + 3487, 2669, 3158, + 3461, 2736, 3117, + 3423, 2812, 3054, + 3368, 2897, 2955, + 3281, 2991, 2775, + 3131, 3092, 2297, + 2794, 3199, 0, + 0, 3312, 0, + 0, 3429, 0, + 0, 3550, 0, + 0, 3673, 0, + 3689, 2509, 3394, + 3689, 2509, 3393, + 3689, 2510, 3393, + 3689, 2510, 3393, + 3688, 2511, 3393, + 3688, 2511, 3393, + 3688, 2512, 3393, + 3688, 2514, 3392, + 3688, 2515, 3392, + 3687, 2518, 3392, + 3687, 2521, 3391, + 3686, 2525, 3390, + 3685, 2530, 3389, + 3684, 2537, 3387, + 3682, 2546, 3384, + 3680, 2559, 3381, + 3677, 2574, 3377, + 3673, 2595, 3371, + 3668, 2620, 3363, + 3661, 2653, 3353, + 3651, 2692, 3338, + 3638, 2741, 3318, + 3619, 2798, 3289, + 3593, 2865, 3247, + 3556, 2942, 3184, + 3500, 3028, 3084, + 3413, 3122, 2903, + 3264, 3223, 2419, + 2928, 3331, 0, + 0, 3443, 0, + 0, 3561, 0, + 0, 3681, 0, + 3821, 2637, 3525, + 3821, 2638, 3525, + 3821, 2638, 3525, + 3821, 2638, 3525, + 3821, 2639, 3524, + 3821, 2639, 3524, + 3821, 2640, 3524, + 3821, 2641, 3524, + 3820, 2642, 3524, + 3820, 2644, 3523, + 3820, 2646, 3523, + 3819, 2649, 3522, + 3818, 2653, 3521, + 3818, 2659, 3520, + 3816, 2666, 3518, + 3815, 2675, 3516, + 3813, 2687, 3512, + 3810, 2703, 3508, + 3806, 2724, 3502, + 3801, 2750, 3494, + 3793, 2782, 3484, + 3784, 2822, 3469, + 3770, 2871, 3448, + 3752, 2929, 3420, + 3725, 2996, 3378, + 3688, 3073, 3315, + 3633, 3159, 3215, + 3546, 3253, 3032, + 3396, 3354, 2543, + 3061, 3462, 0, + 0, 3575, 0, + 0, 3692, 0, + 3953, 2767, 3656, + 3953, 2767, 3656, + 3953, 2767, 3656, + 3953, 2767, 3656, + 3953, 2768, 3656, + 3953, 2768, 3656, + 3953, 2769, 3656, + 3953, 2769, 3656, + 3953, 2770, 3655, + 3953, 2772, 3655, + 3952, 2773, 3655, + 3952, 2776, 3654, + 3951, 2779, 3653, + 3951, 2783, 3652, + 3950, 2788, 3651, + 3949, 2795, 3649, + 3947, 2805, 3647, + 3945, 2817, 3644, + 3942, 2833, 3639, + 3938, 2854, 3634, + 3933, 2880, 3626, + 3926, 2912, 3615, + 3916, 2952, 3600, + 3902, 3001, 3580, + 3884, 3059, 3551, + 3858, 3127, 3509, + 3820, 3204, 3446, + 3765, 3290, 3345, + 3678, 3384, 3162, + 3529, 3486, 2669, + 3194, 3594, 0, + 0, 3707, 0, + 4086, 2897, 3788, + 4086, 2897, 3788, + 4086, 2897, 3788, + 4086, 2897, 3788, + 4086, 2897, 3788, + 4085, 2898, 3788, + 4085, 2898, 3787, + 4085, 2899, 3787, + 4085, 2899, 3787, + 4085, 2900, 3787, + 4085, 2902, 3787, + 4085, 2903, 3786, + 4084, 2906, 3786, + 4084, 2909, 3785, + 4083, 2913, 3784, + 4082, 2918, 3783, + 4081, 2926, 3781, + 4079, 2935, 3779, + 4077, 2947, 3775, + 4074, 2963, 3771, + 4070, 2984, 3765, + 4065, 3010, 3757, + 4058, 3043, 3747, + 4048, 3083, 3732, + 4035, 3132, 3711, + 4016, 3190, 3682, + 3990, 3258, 3640, + 3953, 3335, 3577, + 3897, 3421, 3476, + 3811, 3516, 3293, + 3661, 3617, 2796, + 3327, 3725, 0, + 4095, 3027, 3919, + 4095, 3027, 3919, + 4095, 3027, 3919, + 4095, 3027, 3919, + 4095, 3028, 3919, + 4095, 3028, 3919, + 4095, 3028, 3919, + 4095, 3029, 3919, + 4095, 3029, 3919, + 4095, 3030, 3919, + 4095, 3031, 3919, + 4095, 3032, 3918, + 4095, 3034, 3918, + 4095, 3036, 3917, + 4095, 3039, 3917, + 4095, 3044, 3916, + 4095, 3049, 3914, + 4095, 3056, 3913, + 4095, 3066, 3910, + 4095, 3078, 3907, + 4095, 3094, 3903, + 4095, 3115, 3897, + 4095, 3141, 3889, + 4095, 3174, 3878, + 4095, 3214, 3863, + 4095, 3263, 3843, + 4095, 3321, 3814, + 4095, 3389, 3772, + 4085, 3467, 3709, + 4030, 3553, 3608, + 3943, 3647, 3424, + 3794, 3749, 2925, + 4095, 3158, 4051, + 4095, 3158, 4051, + 4095, 3158, 4051, + 4095, 3158, 4051, + 4095, 3158, 4051, + 4095, 3159, 4051, + 4095, 3159, 4051, + 4095, 3159, 4051, + 4095, 3160, 4051, + 4095, 3160, 4051, + 4095, 3161, 4051, + 4095, 3162, 4050, + 4095, 3163, 4050, + 4095, 3165, 4050, + 4095, 3167, 4049, + 4095, 3170, 4048, + 4095, 3175, 4047, + 4095, 3180, 4046, + 4095, 3187, 4044, + 4095, 3197, 4042, + 4095, 3209, 4039, + 4095, 3225, 4035, + 4095, 3246, 4029, + 4095, 3272, 4021, + 4095, 3305, 4010, + 4095, 3346, 3995, + 4095, 3395, 3975, + 4095, 3453, 3946, + 4095, 3521, 3903, + 4095, 3598, 3840, + 4095, 3685, 3739, + 4075, 3779, 3555, + 0, 1092, 1347, + 0, 1097, 1342, + 0, 1104, 1336, + 0, 1112, 1327, + 0, 1124, 1315, + 0, 1139, 1298, + 0, 1159, 1275, + 0, 1183, 1242, + 0, 1215, 1193, + 0, 1253, 1119, + 0, 1300, 996, + 0, 1356, 751, + 0, 1422, 0, + 0, 1497, 0, + 0, 1581, 0, + 0, 1674, 0, + 0, 1774, 0, + 0, 1881, 0, + 0, 1993, 0, + 0, 2110, 0, + 0, 2230, 0, + 0, 2353, 0, + 0, 2478, 0, + 0, 2605, 0, + 0, 2733, 0, + 0, 2862, 0, + 0, 2992, 0, + 0, 3122, 0, + 0, 3253, 0, + 0, 3384, 0, + 0, 3516, 0, + 0, 3647, 0, + 0, 1093, 1354, + 0, 1098, 1350, + 0, 1105, 1343, + 0, 1114, 1335, + 0, 1126, 1323, + 0, 1141, 1306, + 0, 1160, 1283, + 0, 1185, 1251, + 0, 1216, 1203, + 0, 1254, 1131, + 0, 1301, 1011, + 0, 1357, 777, + 0, 1423, 0, + 0, 1498, 0, + 0, 1582, 0, + 0, 1674, 0, + 0, 1775, 0, + 0, 1881, 0, + 0, 1993, 0, + 0, 2110, 0, + 0, 2230, 0, + 0, 2353, 0, + 0, 2478, 0, + 0, 2605, 0, + 0, 2733, 0, + 0, 2862, 0, + 0, 2992, 0, + 0, 3122, 0, + 0, 3253, 0, + 0, 3384, 0, + 0, 3516, 0, + 0, 3647, 0, + 0, 1096, 1364, + 0, 1101, 1359, + 0, 1107, 1353, + 0, 1116, 1344, + 0, 1128, 1333, + 0, 1143, 1317, + 0, 1162, 1294, + 0, 1187, 1262, + 0, 1218, 1216, + 0, 1256, 1146, + 0, 1303, 1031, + 0, 1359, 809, + 0, 1424, 0, + 0, 1499, 0, + 0, 1583, 0, + 0, 1675, 0, + 0, 1775, 0, + 0, 1882, 0, + 0, 1994, 0, + 0, 2110, 0, + 0, 2230, 0, + 0, 2353, 0, + 0, 2478, 0, + 0, 2605, 0, + 0, 2733, 0, + 0, 2862, 0, + 0, 2992, 0, + 0, 3122, 0, + 0, 3253, 0, + 0, 3384, 0, + 0, 3516, 0, + 0, 3647, 0, + 0, 1099, 1376, + 0, 1104, 1371, + 0, 1110, 1365, + 0, 1119, 1357, + 0, 1131, 1346, + 0, 1146, 1330, + 0, 1165, 1308, + 0, 1189, 1278, + 0, 1220, 1233, + 0, 1258, 1165, + 0, 1305, 1056, + 0, 1360, 850, + 0, 1425, 185, + 0, 1500, 0, + 0, 1584, 0, + 0, 1676, 0, + 0, 1776, 0, + 0, 1882, 0, + 0, 1994, 0, + 0, 2110, 0, + 0, 2230, 0, + 0, 2353, 0, + 0, 2478, 0, + 0, 2605, 0, + 0, 2733, 0, + 0, 2862, 0, + 0, 2992, 0, + 0, 3122, 0, + 0, 3253, 0, + 0, 3384, 0, + 0, 3516, 0, + 0, 3647, 0, + 0, 1103, 1392, + 0, 1108, 1387, + 0, 1114, 1381, + 0, 1123, 1373, + 0, 1135, 1363, + 0, 1149, 1348, + 0, 1168, 1327, + 0, 1193, 1297, + 0, 1223, 1255, + 0, 1261, 1190, + 0, 1307, 1087, + 0, 1363, 898, + 0, 1427, 365, + 0, 1502, 0, + 0, 1585, 0, + 0, 1677, 0, + 0, 1777, 0, + 0, 1883, 0, + 0, 1995, 0, + 0, 2111, 0, + 0, 2231, 0, + 0, 2354, 0, + 0, 2479, 0, + 0, 2605, 0, + 0, 2733, 0, + 0, 2862, 0, + 0, 2992, 0, + 0, 3122, 0, + 0, 3253, 0, + 0, 3384, 0, + 0, 3516, 0, + 0, 3647, 0, + 0, 1108, 1412, + 0, 1113, 1408, + 0, 1120, 1402, + 0, 1128, 1395, + 0, 1140, 1384, + 0, 1154, 1370, + 0, 1173, 1350, + 0, 1197, 1322, + 0, 1227, 1282, + 0, 1265, 1222, + 0, 1311, 1126, + 0, 1366, 956, + 0, 1430, 530, + 0, 1504, 0, + 0, 1587, 0, + 0, 1679, 0, + 0, 1778, 0, + 0, 1884, 0, + 0, 1995, 0, + 0, 2112, 0, + 0, 2231, 0, + 0, 2354, 0, + 0, 2479, 0, + 0, 2605, 0, + 0, 2733, 0, + 0, 2862, 0, + 0, 2992, 0, + 0, 3122, 0, + 0, 3253, 0, + 0, 3384, 0, + 0, 3516, 0, + 0, 3647, 0, + 0, 1115, 1438, + 0, 1120, 1434, + 0, 1127, 1429, + 0, 1135, 1421, + 0, 1146, 1412, + 0, 1161, 1398, + 0, 1179, 1380, + 0, 1203, 1353, + 0, 1233, 1316, + 0, 1270, 1260, + 0, 1315, 1173, + 0, 1370, 1023, + 0, 1434, 686, + 0, 1507, 0, + 0, 1590, 0, + 0, 1681, 0, + 0, 1780, 0, + 0, 1885, 0, + 0, 1996, 0, + 0, 2112, 0, + 0, 2232, 0, + 0, 2354, 0, + 0, 2479, 0, + 0, 2606, 0, + 0, 2734, 0, + 0, 2862, 0, + 0, 2992, 0, + 0, 3123, 0, + 0, 3253, 0, + 0, 3384, 0, + 0, 3516, 0, + 0, 3647, 0, + 503, 1125, 1470, + 461, 1130, 1467, + 397, 1136, 1462, + 296, 1144, 1455, + 111, 1155, 1446, + 0, 1169, 1433, + 0, 1188, 1416, + 0, 1211, 1392, + 0, 1240, 1358, + 0, 1277, 1307, + 0, 1322, 1230, + 0, 1375, 1100, + 0, 1438, 834, + 0, 1511, 0, + 0, 1593, 0, + 0, 1683, 0, + 0, 1782, 0, + 0, 1887, 0, + 0, 1998, 0, + 0, 2113, 0, + 0, 2233, 0, + 0, 2355, 0, + 0, 2480, 0, + 0, 2606, 0, + 0, 2734, 0, + 0, 2863, 0, + 0, 2992, 0, + 0, 3123, 0, + 0, 3253, 0, + 0, 3384, 0, + 0, 3516, 0, + 0, 3647, 0, + 919, 1137, 1510, + 902, 1142, 1507, + 879, 1148, 1502, + 847, 1156, 1496, + 799, 1167, 1488, + 726, 1180, 1477, + 606, 1198, 1461, + 371, 1221, 1439, + 0, 1250, 1409, + 0, 1286, 1364, + 0, 1330, 1296, + 0, 1382, 1186, + 0, 1444, 978, + 0, 1516, 303, + 0, 1597, 0, + 0, 1687, 0, + 0, 1785, 0, + 0, 1889, 0, + 0, 2000, 0, + 0, 2115, 0, + 0, 2234, 0, + 0, 2356, 0, + 0, 2480, 0, + 0, 2606, 0, + 0, 2734, 0, + 0, 2863, 0, + 0, 2993, 0, + 0, 3123, 0, + 0, 3253, 0, + 0, 3385, 0, + 0, 3516, 0, + 0, 3647, 0, + 1186, 1153, 1559, + 1177, 1158, 1556, + 1165, 1164, 1552, + 1148, 1171, 1546, + 1124, 1182, 1539, + 1090, 1195, 1529, + 1039, 1212, 1515, + 962, 1234, 1496, + 834, 1262, 1468, + 572, 1297, 1429, + 0, 1340, 1371, + 0, 1392, 1280, + 0, 1453, 1119, + 0, 1523, 738, + 0, 1603, 0, + 0, 1692, 0, + 0, 1789, 0, + 0, 1892, 0, + 0, 2002, 0, + 0, 2117, 0, + 0, 2235, 0, + 0, 2357, 0, + 0, 2481, 0, + 0, 2607, 0, + 0, 2735, 0, + 0, 2863, 0, + 0, 2993, 0, + 0, 3123, 0, + 0, 3254, 0, + 0, 3385, 0, + 0, 3516, 0, + 0, 3647, 0, + 1398, 1174, 1617, + 1393, 1178, 1614, + 1385, 1184, 1610, + 1375, 1191, 1606, + 1360, 1201, 1599, + 1340, 1214, 1590, + 1312, 1230, 1578, + 1271, 1251, 1561, + 1211, 1278, 1538, + 1114, 1312, 1505, + 942, 1354, 1456, + 504, 1404, 1382, + 0, 1463, 1258, + 0, 1532, 1012, + 0, 1611, 0, + 0, 1698, 0, + 0, 1794, 0, + 0, 1896, 0, + 0, 2005, 0, + 0, 2119, 0, + 0, 2237, 0, + 0, 2358, 0, + 0, 2482, 0, + 0, 2608, 0, + 0, 2735, 0, + 0, 2864, 0, + 0, 2993, 0, + 0, 3123, 0, + 0, 3254, 0, + 0, 3385, 0, + 0, 3516, 0, + 0, 3647, 0, + 1582, 1200, 1684, + 1579, 1204, 1682, + 1573, 1209, 1679, + 1567, 1216, 1674, + 1557, 1225, 1669, + 1544, 1237, 1661, + 1527, 1253, 1651, + 1502, 1273, 1637, + 1466, 1299, 1617, + 1414, 1331, 1589, + 1332, 1371, 1549, + 1195, 1420, 1489, + 903, 1477, 1395, + 0, 1544, 1226, + 0, 1621, 810, + 0, 1707, 0, + 0, 1801, 0, + 0, 1902, 0, + 0, 2010, 0, + 0, 2123, 0, + 0, 2240, 0, + 0, 2360, 0, + 0, 2484, 0, + 0, 2609, 0, + 0, 2736, 0, + 0, 2864, 0, + 0, 2994, 0, + 0, 3124, 0, + 0, 3254, 0, + 0, 3385, 0, + 0, 3516, 0, + 0, 3648, 0, + 1750, 1232, 1761, + 1747, 1236, 1759, + 1744, 1241, 1756, + 1739, 1248, 1753, + 1732, 1256, 1748, + 1724, 1268, 1742, + 1712, 1282, 1733, + 1695, 1301, 1721, + 1672, 1326, 1705, + 1640, 1356, 1682, + 1592, 1394, 1650, + 1520, 1440, 1602, + 1400, 1495, 1530, + 1165, 1560, 1412, + 102, 1634, 1180, + 0, 1718, 189, + 0, 1809, 0, + 0, 1909, 0, + 0, 2015, 0, + 0, 2127, 0, + 0, 2243, 0, + 0, 2363, 0, + 0, 2486, 0, + 0, 2611, 0, + 0, 2737, 0, + 0, 2865, 0, + 0, 2994, 0, + 0, 3124, 0, + 0, 3254, 0, + 0, 3385, 0, + 0, 3516, 0, + 0, 3648, 0, + 1906, 1272, 1846, + 1905, 1276, 1845, + 1902, 1280, 1843, + 1899, 1286, 1840, + 1894, 1294, 1836, + 1888, 1305, 1831, + 1880, 1319, 1824, + 1869, 1336, 1814, + 1853, 1359, 1801, + 1831, 1387, 1782, + 1801, 1422, 1757, + 1756, 1466, 1720, + 1689, 1518, 1665, + 1580, 1580, 1580, + 1375, 1651, 1434, + 723, 1732, 1111, + 0, 1821, 0, + 0, 1918, 0, + 0, 2023, 0, + 0, 2133, 0, + 0, 2248, 0, + 0, 2366, 0, + 0, 2488, 0, + 0, 2613, 0, + 0, 2739, 0, + 0, 2866, 0, + 0, 2995, 0, + 0, 3125, 0, + 0, 3255, 0, + 0, 3386, 0, + 0, 3517, 0, + 0, 3648, 0, + 2056, 1321, 1941, + 2055, 1324, 1939, + 2053, 1328, 1938, + 2051, 1334, 1935, + 2047, 1341, 1932, + 2043, 1350, 1928, + 2037, 1363, 1922, + 2029, 1379, 1914, + 2018, 1399, 1904, + 2003, 1425, 1889, + 1983, 1458, 1869, + 1953, 1498, 1840, + 1911, 1547, 1799, + 1847, 1605, 1737, + 1745, 1673, 1639, + 1558, 1750, 1461, + 1037, 1836, 997, + 0, 1931, 0, + 0, 2032, 0, + 0, 2140, 0, + 0, 2254, 0, + 0, 2371, 0, + 0, 2492, 0, + 0, 2615, 0, + 0, 2741, 0, + 0, 2868, 0, + 0, 2996, 0, + 0, 3126, 0, + 0, 3256, 0, + 0, 3386, 0, + 0, 3517, 0, + 0, 3648, 0, + 2201, 1379, 2042, + 2200, 1382, 2041, + 2199, 1386, 2040, + 2197, 1390, 2038, + 2195, 1397, 2035, + 2191, 1405, 2032, + 2187, 1416, 2027, + 2182, 1430, 2021, + 2174, 1449, 2013, + 2163, 1472, 2001, + 2149, 1502, 1986, + 2129, 1538, 1964, + 2100, 1583, 1933, + 2059, 1637, 1887, + 1998, 1701, 1819, + 1900, 1774, 1707, + 1724, 1856, 1496, + 1270, 1947, 780, + 0, 2045, 0, + 0, 2151, 0, + 0, 2262, 0, + 0, 2377, 0, + 0, 2497, 0, + 0, 2619, 0, + 0, 2744, 0, + 0, 2870, 0, + 0, 2998, 0, + 0, 3127, 0, + 0, 3256, 0, + 0, 3387, 0, + 0, 3518, 0, + 0, 3649, 0, + 2342, 1447, 2150, + 2342, 1449, 2149, + 2341, 1452, 2148, + 2339, 1456, 2146, + 2338, 1462, 2145, + 2335, 1469, 2142, + 2332, 1479, 2138, + 2328, 1491, 2133, + 2323, 1507, 2127, + 2315, 1528, 2118, + 2305, 1554, 2106, + 2290, 1587, 2089, + 2271, 1628, 2066, + 2243, 1677, 2032, + 2203, 1735, 1984, + 2143, 1803, 1909, + 2049, 1881, 1785, + 1880, 1967, 1538, + 1465, 2062, 3, + 0, 2164, 0, + 0, 2272, 0, + 0, 2385, 0, + 0, 2503, 0, + 0, 2624, 0, + 0, 2747, 0, + 0, 2873, 0, + 0, 3000, 0, + 0, 3128, 0, + 0, 3258, 0, + 0, 3388, 0, + 0, 3518, 0, + 0, 3649, 0, + 2481, 1524, 2263, + 2481, 1526, 2262, + 2480, 1528, 2261, + 2479, 1532, 2260, + 2478, 1537, 2259, + 2476, 1543, 2257, + 2474, 1551, 2254, + 2471, 1561, 2250, + 2467, 1575, 2245, + 2461, 1593, 2238, + 2454, 1616, 2229, + 2444, 1645, 2216, + 2430, 1681, 2199, + 2410, 1725, 2174, + 2383, 1778, 2139, + 2344, 1840, 2087, + 2285, 1912, 2007, + 2193, 1993, 1872, + 2030, 2083, 1589, + 1639, 2181, 0, + 0, 2285, 0, + 0, 2396, 0, + 0, 2511, 0, + 0, 2630, 0, + 0, 2752, 0, + 0, 2876, 0, + 0, 3003, 0, + 0, 3130, 0, + 0, 3259, 0, + 0, 3389, 0, + 0, 3519, 0, + 0, 3650, 0, + 2618, 1610, 2380, + 2618, 1611, 2380, + 2617, 1614, 2379, + 2617, 1617, 2378, + 2616, 1620, 2377, + 2615, 1626, 2375, + 2613, 1632, 2373, + 2611, 1641, 2370, + 2608, 1653, 2367, + 2604, 1668, 2361, + 2598, 1687, 2354, + 2591, 1712, 2345, + 2581, 1743, 2331, + 2567, 1782, 2313, + 2548, 1829, 2287, + 2521, 1885, 2251, + 2482, 1950, 2197, + 2424, 2026, 2112, + 2333, 2110, 1967, + 2174, 2202, 1650, + 1800, 2303, 0, + 0, 2409, 0, + 0, 2522, 0, + 0, 2638, 0, + 0, 2758, 0, + 0, 2881, 0, + 0, 3006, 0, + 0, 3133, 0, + 0, 3261, 0, + 0, 3390, 0, + 0, 3520, 0, + 0, 3651, 0, + 2754, 1704, 2501, + 2754, 1705, 2500, + 2754, 1707, 2500, + 2753, 1710, 2499, + 2752, 1713, 2498, + 2751, 1717, 2497, + 2750, 1723, 2496, + 2749, 1730, 2493, + 2746, 1739, 2490, + 2743, 1752, 2486, + 2739, 1768, 2481, + 2734, 1789, 2474, + 2727, 1815, 2464, + 2717, 1849, 2450, + 2703, 1889, 2432, + 2684, 1939, 2405, + 2657, 1997, 2367, + 2619, 2066, 2311, + 2562, 2143, 2223, + 2472, 2230, 2069, + 2315, 2325, 1720, + 1952, 2427, 0, + 0, 2535, 0, + 0, 2649, 0, + 0, 2767, 0, + 0, 2888, 0, + 0, 3011, 0, + 0, 3137, 0, + 0, 3264, 0, + 0, 3392, 0, + 0, 3522, 0, + 0, 3652, 0, + 2889, 1806, 2624, + 2889, 1807, 2624, + 2889, 1808, 2624, + 2888, 1810, 2623, + 2888, 1813, 2622, + 2887, 1816, 2621, + 2886, 1821, 2620, + 2885, 1826, 2619, + 2883, 1834, 2616, + 2881, 1844, 2613, + 2878, 1858, 2609, + 2874, 1875, 2604, + 2869, 1897, 2596, + 2861, 1925, 2586, + 2852, 1959, 2572, + 2838, 2002, 2553, + 2819, 2054, 2526, + 2792, 2114, 2487, + 2754, 2185, 2429, + 2698, 2265, 2338, + 2609, 2353, 2178, + 2454, 2450, 1799, + 2099, 2553, 0, + 0, 2663, 0, + 0, 2777, 0, + 0, 2896, 0, + 0, 3018, 0, + 0, 3142, 0, + 0, 3268, 0, + 0, 3395, 0, + 0, 3524, 0, + 0, 3653, 0, + 3023, 1914, 2750, + 3023, 1915, 2749, + 3023, 1916, 2749, + 3023, 1917, 2749, + 3022, 1919, 2748, + 3022, 1922, 2748, + 3021, 1925, 2747, + 3020, 1930, 2745, + 3019, 1936, 2744, + 3017, 1944, 2741, + 3015, 1955, 2738, + 3012, 1969, 2734, + 3008, 1987, 2729, + 3003, 2010, 2721, + 2996, 2039, 2711, + 2986, 2075, 2697, + 2972, 2119, 2677, + 2953, 2172, 2650, + 2927, 2235, 2610, + 2889, 2307, 2551, + 2833, 2388, 2457, + 2744, 2478, 2291, + 2591, 2576, 1888, + 2242, 2681, 0, + 0, 2792, 0, + 0, 2907, 0, + 0, 3026, 0, + 0, 3148, 0, + 0, 3273, 0, + 0, 3399, 0, + 0, 3527, 0, + 0, 3655, 0, + 3157, 2027, 2877, + 3157, 2028, 2877, + 3157, 2028, 2876, + 3156, 2030, 2876, + 3156, 2031, 2876, + 3156, 2033, 2875, + 3155, 2036, 2874, + 3155, 2040, 2874, + 3154, 2045, 2872, + 3152, 2051, 2871, + 3151, 2059, 2868, + 3149, 2071, 2865, + 3146, 2085, 2861, + 3142, 2104, 2855, + 3136, 2127, 2848, + 3129, 2157, 2837, + 3119, 2194, 2823, + 3106, 2240, 2803, + 3087, 2294, 2775, + 3061, 2358, 2735, + 3023, 2431, 2675, + 2967, 2514, 2579, + 2879, 2605, 2409, + 2727, 2704, 1984, + 2382, 2810, 0, + 0, 2921, 0, + 0, 3037, 0, + 0, 3157, 0, + 0, 3279, 0, + 0, 3404, 0, + 0, 3530, 0, + 0, 3658, 0, + 3290, 2144, 3005, + 3290, 2145, 3005, + 3290, 2145, 3005, + 3290, 2146, 3005, + 3290, 2148, 3004, + 3289, 2149, 3004, + 3289, 2151, 3003, + 3288, 2154, 3003, + 3288, 2158, 3002, + 3287, 2163, 3000, + 3286, 2170, 2999, + 3284, 2178, 2996, + 3282, 2190, 2993, + 3279, 2205, 2989, + 3275, 2224, 2983, + 3270, 2248, 2976, + 3262, 2279, 2965, + 3253, 2317, 2951, + 3239, 2363, 2931, + 3220, 2418, 2902, + 3194, 2483, 2862, + 3156, 2558, 2801, + 3101, 2641, 2704, + 3013, 2733, 2530, + 2862, 2833, 2087, + 2520, 2939, 0, + 0, 3051, 0, + 0, 3168, 0, + 0, 3287, 0, + 0, 3410, 0, + 0, 3535, 0, + 0, 3662, 0, + 3423, 2265, 3134, + 3423, 2265, 3134, + 3423, 2266, 3134, + 3423, 2267, 3134, + 3423, 2268, 3134, + 3422, 2269, 3133, + 3422, 2270, 3133, + 3422, 2273, 3132, + 3421, 2276, 3132, + 3421, 2279, 3131, + 3420, 2285, 3130, + 3418, 2291, 3128, + 3417, 2300, 3125, + 3415, 2312, 3122, + 3412, 2327, 3118, + 3408, 2347, 3112, + 3403, 2371, 3105, + 3395, 2403, 3094, + 3386, 2441, 3080, + 3372, 2488, 3059, + 3353, 2545, 3031, + 3327, 2610, 2990, + 3290, 2685, 2928, + 3234, 2770, 2830, + 3147, 2863, 2654, + 2996, 2963, 2197, + 2656, 3070, 0, + 0, 3182, 0, + 0, 3298, 0, + 0, 3419, 0, + 0, 3542, 0, + 0, 3667, 0, + 3556, 2388, 3264, + 3556, 2389, 3264, + 3556, 2389, 3264, + 3556, 2390, 3264, + 3555, 2390, 3264, + 3555, 2391, 3264, + 3555, 2393, 3263, + 3555, 2394, 3263, + 3554, 2397, 3262, + 3554, 2400, 3262, + 3553, 2403, 3261, + 3552, 2409, 3259, + 3551, 2416, 3258, + 3550, 2425, 3255, + 3547, 2437, 3252, + 3544, 2452, 3248, + 3541, 2472, 3242, + 3535, 2497, 3234, + 3528, 2529, 3224, + 3518, 2568, 3209, + 3505, 2615, 3189, + 3486, 2672, 3160, + 3460, 2738, 3119, + 3422, 2814, 3057, + 3367, 2899, 2958, + 3280, 2992, 2780, + 3130, 3093, 2311, + 2791, 3200, 0, + 0, 3313, 0, + 0, 3430, 0, + 0, 3550, 0, + 0, 3673, 0, + 3688, 2514, 3395, + 3688, 2514, 3395, + 3688, 2515, 3395, + 3688, 2515, 3395, + 3688, 2515, 3394, + 3688, 2516, 3394, + 3688, 2517, 3394, + 3688, 2518, 3394, + 3687, 2520, 3393, + 3687, 2522, 3393, + 3686, 2525, 3392, + 3686, 2529, 3391, + 3685, 2535, 3390, + 3684, 2542, 3388, + 3682, 2551, 3386, + 3680, 2563, 3383, + 3677, 2579, 3378, + 3673, 2599, 3373, + 3668, 2624, 3365, + 3661, 2656, 3354, + 3651, 2696, 3339, + 3637, 2744, 3319, + 3619, 2801, 3290, + 3593, 2868, 3249, + 3555, 2944, 3186, + 3500, 3029, 3087, + 3413, 3123, 2907, + 3263, 3224, 2429, + 2926, 3331, 0, + 0, 3444, 0, + 0, 3561, 0, + 0, 3682, 0, + 3821, 2641, 3526, + 3821, 2641, 3526, + 3821, 2641, 3526, + 3821, 2642, 3526, + 3821, 2642, 3525, + 3821, 2643, 3525, + 3820, 2643, 3525, + 3820, 2644, 3525, + 3820, 2646, 3525, + 3820, 2647, 3524, + 3819, 2650, 3524, + 3819, 2653, 3523, + 3818, 2657, 3522, + 3817, 2662, 3521, + 3816, 2669, 3519, + 3815, 2679, 3517, + 3812, 2691, 3513, + 3809, 2706, 3509, + 3806, 2727, 3503, + 3800, 2752, 3495, + 3793, 2785, 3485, + 3783, 2825, 3470, + 3770, 2873, 3450, + 3751, 2930, 3421, + 3725, 2998, 3379, + 3688, 3074, 3316, + 3632, 3160, 3216, + 3546, 3254, 3035, + 3396, 3355, 2551, + 3060, 3463, 0, + 0, 3576, 0, + 0, 3693, 0, + 3953, 2769, 3657, + 3953, 2770, 3657, + 3953, 2770, 3657, + 3953, 2770, 3657, + 3953, 2770, 3657, + 3953, 2771, 3657, + 3953, 2771, 3656, + 3953, 2772, 3656, + 3953, 2773, 3656, + 3952, 2774, 3656, + 3952, 2776, 3655, + 3952, 2778, 3655, + 3951, 2781, 3654, + 3951, 2785, 3653, + 3950, 2791, 3652, + 3948, 2798, 3650, + 3947, 2807, 3648, + 3945, 2820, 3644, + 3942, 2835, 3640, + 3938, 2856, 3634, + 3933, 2882, 3627, + 3925, 2914, 3616, + 3916, 2954, 3601, + 3902, 3003, 3581, + 3884, 3061, 3552, + 3858, 3128, 3510, + 3820, 3205, 3447, + 3765, 3291, 3347, + 3678, 3385, 3165, + 3528, 3486, 2675, + 3193, 3594, 0, + 0, 3707, 0, + 4085, 2899, 3788, + 4085, 2899, 3788, + 4085, 2899, 3788, + 4085, 2899, 3788, + 4085, 2899, 3788, + 4085, 2900, 3788, + 4085, 2900, 3788, + 4085, 2901, 3788, + 4085, 2901, 3788, + 4085, 2902, 3787, + 4085, 2904, 3787, + 4084, 2905, 3787, + 4084, 2908, 3786, + 4084, 2911, 3785, + 4083, 2915, 3784, + 4082, 2920, 3783, + 4081, 2928, 3781, + 4079, 2937, 3779, + 4077, 2949, 3776, + 4074, 2965, 3772, + 4070, 2986, 3766, + 4065, 3012, 3758, + 4058, 3044, 3747, + 4048, 3084, 3732, + 4035, 3133, 3712, + 4016, 3191, 3683, + 3990, 3259, 3641, + 3952, 3336, 3578, + 3897, 3422, 3477, + 3811, 3516, 3295, + 3661, 3618, 2801, + 3326, 3726, 0, + 4095, 3029, 3920, + 4095, 3029, 3920, + 4095, 3029, 3920, + 4095, 3029, 3920, + 4095, 3029, 3920, + 4095, 3029, 3920, + 4095, 3030, 3920, + 4095, 3030, 3920, + 4095, 3031, 3919, + 4095, 3031, 3919, + 4095, 3032, 3919, + 4095, 3034, 3919, + 4095, 3035, 3918, + 4095, 3038, 3918, + 4095, 3041, 3917, + 4095, 3045, 3916, + 4095, 3050, 3915, + 4095, 3058, 3913, + 4095, 3067, 3911, + 4095, 3079, 3907, + 4095, 3095, 3903, + 4095, 3116, 3897, + 4095, 3142, 3889, + 4095, 3175, 3879, + 4095, 3215, 3864, + 4095, 3264, 3843, + 4095, 3322, 3814, + 4095, 3390, 3772, + 4085, 3467, 3709, + 4029, 3553, 3609, + 3943, 3648, 3425, + 3793, 3750, 2928, + 4095, 3159, 4052, + 4095, 3159, 4052, + 4095, 3159, 4052, + 4095, 3159, 4052, + 4095, 3160, 4052, + 4095, 3160, 4051, + 4095, 3160, 4051, + 4095, 3160, 4051, + 4095, 3161, 4051, + 4095, 3161, 4051, + 4095, 3162, 4051, + 4095, 3163, 4051, + 4095, 3164, 4050, + 4095, 3166, 4050, + 4095, 3168, 4049, + 4095, 3171, 4049, + 4095, 3176, 4048, + 4095, 3181, 4046, + 4095, 3188, 4045, + 4095, 3198, 4042, + 4095, 3210, 4039, + 4095, 3226, 4035, + 4095, 3247, 4029, + 4095, 3273, 4021, + 4095, 3306, 4010, + 4095, 3346, 3996, + 4095, 3395, 3975, + 4095, 3454, 3946, + 4095, 3521, 3904, + 4095, 3599, 3841, + 4095, 3685, 3740, + 4075, 3780, 3556, + 0, 1218, 1478, + 0, 1222, 1474, + 0, 1228, 1469, + 0, 1234, 1463, + 0, 1243, 1454, + 0, 1255, 1441, + 0, 1270, 1424, + 0, 1290, 1401, + 0, 1314, 1367, + 0, 1346, 1318, + 0, 1384, 1242, + 0, 1431, 1116, + 0, 1488, 863, + 0, 1553, 0, + 0, 1629, 0, + 0, 1713, 0, + 0, 1806, 0, + 0, 1906, 0, + 0, 2013, 0, + 0, 2125, 0, + 0, 2242, 0, + 0, 2362, 0, + 0, 2485, 0, + 0, 2610, 0, + 0, 2737, 0, + 0, 2865, 0, + 0, 2994, 0, + 0, 3124, 0, + 0, 3254, 0, + 0, 3385, 0, + 0, 3516, 0, + 0, 3648, 0, + 0, 1220, 1483, + 0, 1224, 1479, + 0, 1229, 1475, + 0, 1236, 1468, + 0, 1245, 1459, + 0, 1256, 1447, + 0, 1271, 1430, + 0, 1291, 1407, + 0, 1316, 1374, + 0, 1347, 1325, + 0, 1385, 1251, + 0, 1432, 1128, + 0, 1488, 883, + 0, 1554, 0, + 0, 1629, 0, + 0, 1713, 0, + 0, 1806, 0, + 0, 1906, 0, + 0, 2013, 0, + 0, 2125, 0, + 0, 2242, 0, + 0, 2362, 0, + 0, 2485, 0, + 0, 2610, 0, + 0, 2737, 0, + 0, 2865, 0, + 0, 2994, 0, + 0, 3124, 0, + 0, 3254, 0, + 0, 3385, 0, + 0, 3516, 0, + 0, 3648, 0, + 0, 1222, 1490, + 0, 1225, 1486, + 0, 1231, 1482, + 0, 1237, 1475, + 0, 1246, 1467, + 0, 1258, 1455, + 0, 1273, 1438, + 0, 1292, 1415, + 0, 1317, 1383, + 0, 1348, 1335, + 0, 1387, 1263, + 0, 1433, 1143, + 0, 1489, 909, + 0, 1555, 0, + 0, 1630, 0, + 0, 1714, 0, + 0, 1807, 0, + 0, 1907, 0, + 0, 2013, 0, + 0, 2125, 0, + 0, 2242, 0, + 0, 2362, 0, + 0, 2485, 0, + 0, 2610, 0, + 0, 2737, 0, + 0, 2865, 0, + 0, 2994, 0, + 0, 3124, 0, + 0, 3254, 0, + 0, 3385, 0, + 0, 3516, 0, + 0, 3648, 0, + 0, 1224, 1499, + 0, 1228, 1496, + 0, 1233, 1491, + 0, 1240, 1485, + 0, 1248, 1476, + 0, 1260, 1465, + 0, 1275, 1449, + 0, 1294, 1426, + 0, 1319, 1395, + 0, 1350, 1348, + 0, 1388, 1278, + 0, 1435, 1163, + 0, 1491, 942, + 0, 1556, 111, + 0, 1631, 0, + 0, 1715, 0, + 0, 1807, 0, + 0, 1907, 0, + 0, 2014, 0, + 0, 2126, 0, + 0, 2242, 0, + 0, 2362, 0, + 0, 2485, 0, + 0, 2610, 0, + 0, 2737, 0, + 0, 2865, 0, + 0, 2994, 0, + 0, 3124, 0, + 0, 3254, 0, + 0, 3385, 0, + 0, 3516, 0, + 0, 3648, 0, + 0, 1227, 1511, + 0, 1231, 1508, + 0, 1236, 1503, + 0, 1243, 1497, + 0, 1251, 1489, + 0, 1263, 1478, + 0, 1278, 1462, + 0, 1297, 1441, + 0, 1321, 1410, + 0, 1352, 1365, + 0, 1390, 1298, + 0, 1437, 1188, + 0, 1492, 982, + 0, 1557, 317, + 0, 1632, 0, + 0, 1716, 0, + 0, 1808, 0, + 0, 1908, 0, + 0, 2014, 0, + 0, 2126, 0, + 0, 2243, 0, + 0, 2363, 0, + 0, 2485, 0, + 0, 2610, 0, + 0, 2737, 0, + 0, 2865, 0, + 0, 2994, 0, + 0, 3124, 0, + 0, 3254, 0, + 0, 3385, 0, + 0, 3516, 0, + 0, 3648, 0, + 0, 1231, 1527, + 0, 1235, 1524, + 0, 1240, 1519, + 0, 1247, 1514, + 0, 1255, 1506, + 0, 1267, 1495, + 0, 1281, 1480, + 0, 1300, 1459, + 0, 1325, 1429, + 0, 1355, 1387, + 0, 1393, 1322, + 0, 1439, 1219, + 0, 1495, 1030, + 0, 1559, 497, + 0, 1634, 0, + 0, 1717, 0, + 0, 1809, 0, + 0, 1909, 0, + 0, 2015, 0, + 0, 2127, 0, + 0, 2243, 0, + 0, 2363, 0, + 0, 2486, 0, + 0, 2611, 0, + 0, 2737, 0, + 0, 2865, 0, + 0, 2994, 0, + 0, 3124, 0, + 0, 3254, 0, + 0, 3385, 0, + 0, 3516, 0, + 0, 3648, 0, + 0, 1237, 1547, + 0, 1240, 1544, + 0, 1245, 1540, + 0, 1252, 1534, + 0, 1260, 1527, + 0, 1272, 1516, + 0, 1286, 1502, + 0, 1305, 1482, + 0, 1329, 1454, + 0, 1360, 1414, + 0, 1397, 1354, + 0, 1443, 1258, + 0, 1498, 1088, + 0, 1562, 662, + 0, 1636, 0, + 0, 1719, 0, + 0, 1811, 0, + 0, 1910, 0, + 0, 2016, 0, + 0, 2128, 0, + 0, 2244, 0, + 0, 2363, 0, + 0, 2486, 0, + 0, 2611, 0, + 0, 2737, 0, + 0, 2865, 0, + 0, 2994, 0, + 0, 3124, 0, + 0, 3255, 0, + 0, 3385, 0, + 0, 3516, 0, + 0, 3648, 0, + 0, 1244, 1573, + 0, 1248, 1570, + 0, 1252, 1566, + 0, 1259, 1561, + 0, 1267, 1554, + 0, 1278, 1544, + 0, 1293, 1530, + 0, 1311, 1512, + 0, 1335, 1486, + 0, 1365, 1448, + 0, 1402, 1392, + 0, 1448, 1306, + 0, 1502, 1155, + 0, 1566, 818, + 0, 1639, 0, + 0, 1722, 0, + 0, 1813, 0, + 0, 1912, 0, + 0, 2017, 0, + 0, 2129, 0, + 0, 2244, 0, + 0, 2364, 0, + 0, 2486, 0, + 0, 2611, 0, + 0, 2738, 0, + 0, 2866, 0, + 0, 2995, 0, + 0, 3124, 0, + 0, 3255, 0, + 0, 3385, 0, + 0, 3516, 0, + 0, 3648, 0, + 664, 1253, 1605, + 635, 1257, 1602, + 593, 1262, 1599, + 530, 1268, 1594, + 428, 1276, 1587, + 243, 1287, 1578, + 0, 1301, 1566, + 0, 1320, 1548, + 0, 1343, 1524, + 0, 1372, 1490, + 0, 1409, 1440, + 0, 1454, 1362, + 0, 1507, 1232, + 0, 1570, 966, + 0, 1643, 0, + 0, 1725, 0, + 0, 1816, 0, + 0, 1914, 0, + 0, 2019, 0, + 0, 2130, 0, + 0, 2245, 0, + 0, 2365, 0, + 0, 2487, 0, + 0, 2612, 0, + 0, 2738, 0, + 0, 2866, 0, + 0, 2995, 0, + 0, 3124, 0, + 0, 3255, 0, + 0, 3385, 0, + 0, 3517, 0, + 0, 3648, 0, + 1063, 1266, 1645, + 1051, 1269, 1642, + 1034, 1274, 1639, + 1011, 1280, 1635, + 979, 1288, 1628, + 931, 1299, 1620, + 858, 1313, 1609, + 738, 1330, 1593, + 503, 1353, 1571, + 0, 1382, 1541, + 0, 1418, 1496, + 0, 1462, 1428, + 0, 1514, 1318, + 0, 1577, 1110, + 0, 1648, 435, + 0, 1729, 0, + 0, 1819, 0, + 0, 1917, 0, + 0, 2021, 0, + 0, 2132, 0, + 0, 2247, 0, + 0, 2366, 0, + 0, 2488, 0, + 0, 2612, 0, + 0, 2739, 0, + 0, 2866, 0, + 0, 2995, 0, + 0, 3125, 0, + 0, 3255, 0, + 0, 3386, 0, + 0, 3517, 0, + 0, 3648, 0, + 1325, 1282, 1693, + 1318, 1285, 1691, + 1309, 1290, 1688, + 1297, 1296, 1684, + 1280, 1303, 1678, + 1256, 1314, 1671, + 1222, 1327, 1661, + 1172, 1344, 1647, + 1095, 1366, 1628, + 966, 1394, 1601, + 704, 1429, 1562, + 0, 1472, 1503, + 0, 1524, 1412, + 0, 1585, 1251, + 0, 1655, 870, + 0, 1735, 0, + 0, 1824, 0, + 0, 1921, 0, + 0, 2024, 0, + 0, 2134, 0, + 0, 2249, 0, + 0, 2367, 0, + 0, 2489, 0, + 0, 2613, 0, + 0, 2739, 0, + 0, 2867, 0, + 0, 2995, 0, + 0, 3125, 0, + 0, 3255, 0, + 0, 3386, 0, + 0, 3517, 0, + 0, 3648, 0, + 1535, 1302, 1751, + 1530, 1306, 1749, + 1525, 1310, 1746, + 1517, 1316, 1742, + 1507, 1323, 1738, + 1492, 1333, 1731, + 1472, 1346, 1722, + 1444, 1362, 1710, + 1404, 1384, 1693, + 1343, 1411, 1670, + 1246, 1444, 1637, + 1074, 1486, 1588, + 636, 1536, 1514, + 0, 1595, 1390, + 0, 1664, 1144, + 0, 1743, 0, + 0, 1830, 0, + 0, 1926, 0, + 0, 2029, 0, + 0, 2137, 0, + 0, 2251, 0, + 0, 2369, 0, + 0, 2490, 0, + 0, 2614, 0, + 0, 2740, 0, + 0, 2867, 0, + 0, 2996, 0, + 0, 3125, 0, + 0, 3255, 0, + 0, 3386, 0, + 0, 3517, 0, + 0, 3648, 0, + 1717, 1329, 1818, + 1714, 1332, 1816, + 1711, 1336, 1814, + 1706, 1341, 1811, + 1699, 1348, 1806, + 1689, 1357, 1801, + 1676, 1370, 1793, + 1659, 1385, 1783, + 1634, 1406, 1769, + 1598, 1431, 1749, + 1546, 1464, 1721, + 1465, 1503, 1681, + 1327, 1552, 1621, + 1035, 1609, 1527, + 0, 1676, 1358, + 0, 1753, 942, + 0, 1839, 0, + 0, 1933, 0, + 0, 2034, 0, + 0, 2142, 0, + 0, 2255, 0, + 0, 2372, 0, + 0, 2492, 0, + 0, 2616, 0, + 0, 2741, 0, + 0, 2868, 0, + 0, 2997, 0, + 0, 3126, 0, + 0, 3256, 0, + 0, 3386, 0, + 0, 3517, 0, + 0, 3648, 0, + 1884, 1361, 1894, + 1882, 1364, 1893, + 1879, 1368, 1891, + 1876, 1373, 1888, + 1871, 1380, 1885, + 1865, 1388, 1880, + 1856, 1400, 1874, + 1844, 1414, 1865, + 1827, 1433, 1853, + 1805, 1458, 1837, + 1772, 1488, 1814, + 1724, 1526, 1782, + 1652, 1572, 1734, + 1532, 1627, 1662, + 1297, 1692, 1544, + 234, 1766, 1313, + 0, 1850, 322, + 0, 1942, 0, + 0, 2041, 0, + 0, 2147, 0, + 0, 2259, 0, + 0, 2375, 0, + 0, 2495, 0, + 0, 2618, 0, + 0, 2743, 0, + 0, 2869, 0, + 0, 2997, 0, + 0, 3126, 0, + 0, 3256, 0, + 0, 3387, 0, + 0, 3517, 0, + 0, 3648, 0, + 2040, 1402, 1980, + 2038, 1405, 1979, + 2037, 1408, 1977, + 2034, 1413, 1975, + 2031, 1419, 1972, + 2026, 1427, 1968, + 2020, 1437, 1963, + 2012, 1451, 1956, + 2001, 1468, 1946, + 1985, 1491, 1933, + 1964, 1519, 1914, + 1933, 1555, 1889, + 1888, 1598, 1852, + 1821, 1650, 1797, + 1712, 1712, 1712, + 1507, 1783, 1566, + 855, 1864, 1243, + 0, 1953, 0, + 0, 2051, 0, + 0, 2155, 0, + 0, 2265, 0, + 0, 2380, 0, + 0, 2499, 0, + 0, 2620, 0, + 0, 2745, 0, + 0, 2871, 0, + 0, 2999, 0, + 0, 3127, 0, + 0, 3257, 0, + 0, 3387, 0, + 0, 3518, 0, + 0, 3649, 0, + 2189, 1451, 2074, + 2188, 1453, 2073, + 2187, 1456, 2071, + 2185, 1461, 2070, + 2183, 1466, 2067, + 2180, 1473, 2064, + 2175, 1483, 2060, + 2169, 1495, 2054, + 2161, 1511, 2046, + 2151, 1531, 2036, + 2136, 1557, 2021, + 2115, 1590, 2001, + 2085, 1630, 1972, + 2043, 1679, 1931, + 1979, 1737, 1869, + 1877, 1805, 1771, + 1690, 1882, 1593, + 1170, 1968, 1129, + 0, 2063, 0, + 0, 2165, 0, + 0, 2273, 0, + 0, 2386, 0, + 0, 2503, 0, + 0, 2624, 0, + 0, 2747, 0, + 0, 2873, 0, + 0, 3000, 0, + 0, 3128, 0, + 0, 3258, 0, + 0, 3388, 0, + 0, 3518, 0, + 0, 3649, 0, + 2334, 1509, 2175, + 2333, 1511, 2174, + 2332, 1514, 2173, + 2331, 1518, 2172, + 2329, 1522, 2170, + 2327, 1529, 2167, + 2324, 1537, 2164, + 2319, 1548, 2159, + 2314, 1562, 2153, + 2306, 1581, 2145, + 2295, 1604, 2134, + 2281, 1634, 2118, + 2261, 1671, 2096, + 2232, 1716, 2065, + 2191, 1769, 2019, + 2130, 1833, 1951, + 2032, 1906, 1839, + 1856, 1988, 1628, + 1402, 2079, 912, + 0, 2177, 0, + 0, 2283, 0, + 0, 2394, 0, + 0, 2509, 0, + 0, 2629, 0, + 0, 2751, 0, + 0, 2876, 0, + 0, 3002, 0, + 0, 3130, 0, + 0, 3259, 0, + 0, 3389, 0, + 0, 3519, 0, + 0, 3650, 0, + 2475, 1577, 2283, + 2474, 1579, 2282, + 2474, 1581, 2281, + 2473, 1584, 2280, + 2472, 1588, 2279, + 2470, 1594, 2277, + 2468, 1601, 2274, + 2464, 1611, 2270, + 2460, 1623, 2266, + 2455, 1639, 2259, + 2447, 1660, 2250, + 2437, 1686, 2238, + 2423, 1719, 2221, + 2403, 1760, 2198, + 2375, 1809, 2165, + 2335, 1867, 2116, + 2275, 1935, 2041, + 2181, 2013, 1917, + 2012, 2099, 1670, + 1597, 2194, 135, + 0, 2296, 0, + 0, 2404, 0, + 0, 2517, 0, + 0, 2635, 0, + 0, 2756, 0, + 0, 2879, 0, + 0, 3005, 0, + 0, 3132, 0, + 0, 3260, 0, + 0, 3390, 0, + 0, 3520, 0, + 0, 3650, 0, + 2614, 1654, 2395, + 2613, 1656, 2395, + 2613, 1658, 2394, + 2612, 1660, 2393, + 2611, 1664, 2392, + 2610, 1669, 2391, + 2608, 1675, 2389, + 2606, 1683, 2386, + 2603, 1694, 2382, + 2599, 1707, 2377, + 2593, 1725, 2370, + 2586, 1748, 2361, + 2576, 1777, 2348, + 2562, 1813, 2331, + 2542, 1857, 2306, + 2515, 1910, 2271, + 2476, 1972, 2219, + 2417, 2044, 2139, + 2325, 2125, 2004, + 2162, 2215, 1721, + 1771, 2313, 0, + 0, 2417, 0, + 0, 2528, 0, + 0, 2643, 0, + 0, 2762, 0, + 0, 2884, 0, + 0, 3009, 0, + 0, 3135, 0, + 0, 3263, 0, + 0, 3391, 0, + 0, 3521, 0, + 0, 3651, 0, + 2751, 1741, 2513, + 2750, 1742, 2512, + 2750, 1744, 2512, + 2750, 1746, 2511, + 2749, 1749, 2510, + 2748, 1753, 2509, + 2747, 1758, 2507, + 2745, 1764, 2505, + 2743, 1773, 2502, + 2740, 1785, 2499, + 2736, 1800, 2493, + 2730, 1819, 2486, + 2723, 1844, 2477, + 2713, 1875, 2464, + 2699, 1914, 2445, + 2680, 1961, 2420, + 2653, 2017, 2383, + 2614, 2083, 2329, + 2556, 2158, 2244, + 2466, 2242, 2099, + 2306, 2335, 1782, + 1932, 2435, 0, + 0, 2542, 0, + 0, 2654, 0, + 0, 2770, 0, + 0, 2890, 0, + 0, 3013, 0, + 0, 3138, 0, + 0, 3265, 0, + 0, 3393, 0, + 0, 3522, 0, + 0, 3652, 0, + 2887, 1835, 2633, + 2886, 1836, 2633, + 2886, 1838, 2633, + 2886, 1839, 2632, + 2885, 1842, 2631, + 2884, 1845, 2630, + 2884, 1849, 2629, + 2882, 1855, 2628, + 2881, 1862, 2625, + 2878, 1872, 2623, + 2875, 1884, 2619, + 2871, 1900, 2613, + 2866, 1921, 2606, + 2859, 1948, 2596, + 2849, 1981, 2582, + 2835, 2021, 2564, + 2816, 2071, 2537, + 2789, 2130, 2499, + 2751, 2198, 2443, + 2694, 2275, 2355, + 2604, 2362, 2201, + 2447, 2457, 1852, + 2084, 2559, 0, + 0, 2668, 0, + 0, 2781, 0, + 0, 2899, 0, + 0, 3020, 0, + 0, 3143, 0, + 0, 3269, 0, + 0, 3396, 0, + 0, 3525, 0, + 0, 3654, 0, + 3021, 1937, 2757, + 3021, 1938, 2756, + 3021, 1939, 2756, + 3021, 1940, 2756, + 3020, 1942, 2755, + 3020, 1945, 2754, + 3019, 1948, 2754, + 3018, 1953, 2752, + 3017, 1959, 2751, + 3015, 1966, 2748, + 3013, 1977, 2745, + 3010, 1990, 2741, + 3006, 2007, 2736, + 3001, 2029, 2728, + 2994, 2057, 2718, + 2984, 2092, 2705, + 2970, 2134, 2685, + 2951, 2186, 2658, + 2924, 2247, 2619, + 2886, 2317, 2561, + 2830, 2397, 2470, + 2741, 2485, 2310, + 2586, 2582, 1931, + 2231, 2685, 0, + 0, 2795, 0, + 0, 2910, 0, + 0, 3028, 0, + 0, 3150, 0, + 0, 3274, 0, + 0, 3400, 0, + 0, 3527, 0, + 0, 3656, 0, + 3155, 2045, 2882, + 3155, 2046, 2882, + 3155, 2047, 2882, + 3155, 2048, 2881, + 3155, 2049, 2881, + 3154, 2051, 2880, + 3154, 2054, 2880, + 3153, 2057, 2879, + 3152, 2062, 2877, + 3151, 2068, 2876, + 3149, 2077, 2874, + 3147, 2087, 2870, + 3144, 2101, 2866, + 3140, 2119, 2861, + 3135, 2142, 2853, + 3128, 2171, 2843, + 3118, 2207, 2829, + 3104, 2251, 2809, + 3085, 2304, 2782, + 3059, 2367, 2742, + 3021, 2439, 2683, + 2965, 2520, 2589, + 2877, 2610, 2423, + 2723, 2708, 2020, + 2374, 2813, 0, + 0, 2924, 0, + 0, 3039, 0, + 0, 3158, 0, + 0, 3280, 0, + 0, 3405, 0, + 0, 3531, 0, + 0, 3659, 0, + 3289, 2158, 3009, + 3289, 2159, 3009, + 3289, 2160, 3009, + 3289, 2160, 3009, + 3288, 2162, 3008, + 3288, 2163, 3008, + 3288, 2165, 3007, + 3287, 2168, 3007, + 3287, 2172, 3006, + 3286, 2177, 3004, + 3285, 2183, 3003, + 3283, 2192, 3000, + 3281, 2203, 2997, + 3278, 2217, 2993, + 3274, 2236, 2988, + 3269, 2259, 2980, + 3261, 2289, 2969, + 3251, 2326, 2955, + 3238, 2372, 2935, + 3219, 2426, 2907, + 3193, 2490, 2867, + 3155, 2563, 2807, + 3099, 2646, 2711, + 3011, 2737, 2541, + 2859, 2836, 2116, + 2514, 2942, 0, + 0, 3053, 0, + 0, 3169, 0, + 0, 3289, 0, + 0, 3411, 0, + 0, 3536, 0, + 0, 3662, 0, + 3422, 2276, 3137, + 3422, 2276, 3137, + 3422, 2277, 3137, + 3422, 2278, 3137, + 3422, 2278, 3137, + 3422, 2280, 3136, + 3421, 2281, 3136, + 3421, 2283, 3135, + 3420, 2286, 3135, + 3420, 2290, 3134, + 3419, 2295, 3133, + 3418, 2302, 3131, + 3416, 2310, 3128, + 3414, 2322, 3125, + 3411, 2337, 3121, + 3407, 2356, 3115, + 3402, 2380, 3108, + 3394, 2411, 3097, + 3385, 2449, 3083, + 3371, 2495, 3063, + 3352, 2551, 3035, + 3326, 2615, 2994, + 3289, 2690, 2933, + 3233, 2773, 2836, + 3145, 2866, 2662, + 2994, 2965, 2219, + 2652, 3072, 0, + 0, 3183, 0, + 0, 3300, 0, + 0, 3420, 0, + 0, 3542, 0, + 0, 3667, 0, + 3555, 2397, 3267, + 3555, 2397, 3266, + 3555, 2398, 3266, + 3555, 2398, 3266, + 3555, 2399, 3266, + 3555, 2400, 3266, + 3555, 2401, 3266, + 3554, 2403, 3265, + 3554, 2405, 3265, + 3553, 2408, 3264, + 3553, 2412, 3263, + 3552, 2417, 3262, + 3551, 2423, 3260, + 3549, 2432, 3258, + 3547, 2444, 3254, + 3544, 2459, 3250, + 3540, 2479, 3245, + 3535, 2504, 3237, + 3527, 2535, 3226, + 3518, 2573, 3212, + 3504, 2621, 3191, + 3485, 2677, 3163, + 3459, 2742, 3122, + 3422, 2818, 3060, + 3366, 2902, 2962, + 3279, 2995, 2786, + 3128, 3095, 2329, + 2788, 3202, 0, + 0, 3314, 0, + 0, 3431, 0, + 0, 3551, 0, + 0, 3674, 0, + 3688, 2520, 3396, + 3688, 2521, 3396, + 3688, 2521, 3396, + 3688, 2521, 3396, + 3688, 2522, 3396, + 3688, 2522, 3396, + 3687, 2523, 3396, + 3687, 2525, 3395, + 3687, 2526, 3395, + 3687, 2529, 3394, + 3686, 2532, 3394, + 3685, 2536, 3393, + 3684, 2541, 3391, + 3683, 2548, 3390, + 3682, 2557, 3387, + 3679, 2569, 3384, + 3677, 2584, 3380, + 3673, 2604, 3374, + 3667, 2629, 3366, + 3660, 2661, 3356, + 3650, 2700, 3341, + 3637, 2748, 3321, + 3618, 2804, 3292, + 3592, 2871, 3251, + 3555, 2946, 3189, + 3499, 3031, 3090, + 3412, 3125, 2912, + 3262, 3225, 2443, + 2923, 3332, 0, + 0, 3445, 0, + 0, 3562, 0, + 0, 3682, 0, + 3820, 2646, 3527, + 3820, 2646, 3527, + 3820, 2646, 3527, + 3820, 2647, 3527, + 3820, 2647, 3527, + 3820, 2648, 3527, + 3820, 2648, 3526, + 3820, 2649, 3526, + 3820, 2651, 3526, + 3819, 2652, 3525, + 3819, 2654, 3525, + 3819, 2658, 3524, + 3818, 2662, 3523, + 3817, 2667, 3522, + 3816, 2674, 3520, + 3814, 2683, 3518, + 3812, 2695, 3515, + 3809, 2711, 3510, + 3805, 2731, 3505, + 3800, 2756, 3497, + 3793, 2788, 3486, + 3783, 2828, 3471, + 3769, 2876, 3451, + 3751, 2933, 3422, + 3725, 3000, 3381, + 3687, 3076, 3318, + 3632, 3161, 3219, + 3545, 3255, 3039, + 3395, 3356, 2562, + 3058, 3463, 0, + 0, 3576, 0, + 0, 3693, 0, + 3953, 2773, 3658, + 3953, 2773, 3658, + 3953, 2773, 3658, + 3953, 2774, 3658, + 3953, 2774, 3658, + 3953, 2774, 3658, + 3953, 2775, 3657, + 3953, 2776, 3657, + 3952, 2777, 3657, + 3952, 2778, 3657, + 3952, 2780, 3656, + 3952, 2782, 3656, + 3951, 2785, 3655, + 3950, 2789, 3654, + 3949, 2794, 3653, + 3948, 2801, 3651, + 3947, 2811, 3649, + 3944, 2823, 3645, + 3942, 2839, 3641, + 3938, 2859, 3635, + 3932, 2885, 3628, + 3925, 2917, 3617, + 3915, 2957, 3602, + 3902, 3005, 3582, + 3883, 3063, 3553, + 3857, 3130, 3511, + 3820, 3206, 3449, + 3764, 3292, 3349, + 3678, 3386, 3167, + 3528, 3487, 2683, + 3192, 3595, 0, + 0, 3708, 0, + 4085, 2901, 3789, + 4085, 2902, 3789, + 4085, 2902, 3789, + 4085, 2902, 3789, + 4085, 2902, 3789, + 4085, 2902, 3789, + 4085, 2903, 3789, + 4085, 2903, 3789, + 4085, 2904, 3788, + 4085, 2905, 3788, + 4085, 2906, 3788, + 4084, 2908, 3787, + 4084, 2910, 3787, + 4083, 2913, 3786, + 4083, 2918, 3785, + 4082, 2923, 3784, + 4081, 2930, 3782, + 4079, 2939, 3780, + 4077, 2952, 3777, + 4074, 2968, 3772, + 4070, 2988, 3767, + 4065, 3014, 3759, + 4058, 3046, 3748, + 4048, 3086, 3733, + 4034, 3135, 3713, + 4016, 3193, 3684, + 3990, 3260, 3642, + 3952, 3337, 3579, + 3897, 3423, 3479, + 3810, 3517, 3297, + 3660, 3618, 2807, + 3325, 3726, 0, + 4095, 3031, 3920, + 4095, 3031, 3920, + 4095, 3031, 3920, + 4095, 3031, 3920, + 4095, 3031, 3920, + 4095, 3031, 3920, + 4095, 3032, 3920, + 4095, 3032, 3920, + 4095, 3033, 3920, + 4095, 3033, 3920, + 4095, 3034, 3920, + 4095, 3036, 3919, + 4095, 3037, 3919, + 4095, 3040, 3918, + 4095, 3043, 3918, + 4095, 3047, 3917, + 4095, 3052, 3915, + 4095, 3060, 3914, + 4095, 3069, 3911, + 4095, 3081, 3908, + 4095, 3097, 3904, + 4095, 3118, 3898, + 4095, 3144, 3890, + 4095, 3176, 3879, + 4095, 3217, 3864, + 4095, 3265, 3844, + 4095, 3323, 3815, + 4095, 3391, 3773, + 4085, 3468, 3710, + 4029, 3554, 3610, + 3943, 3648, 3427, + 3793, 3750, 2933, + 4095, 3161, 4052, + 4095, 3161, 4052, + 4095, 3161, 4052, + 4095, 3161, 4052, + 4095, 3161, 4052, + 4095, 3161, 4052, + 4095, 3161, 4052, + 4095, 3162, 4052, + 4095, 3162, 4052, + 4095, 3163, 4052, + 4095, 3163, 4051, + 4095, 3164, 4051, + 4095, 3166, 4051, + 4095, 3168, 4050, + 4095, 3170, 4050, + 4095, 3173, 4049, + 4095, 3177, 4048, + 4095, 3183, 4047, + 4095, 3190, 4045, + 4095, 3199, 4043, + 4095, 3212, 4040, + 4095, 3228, 4035, + 4095, 3248, 4029, + 4095, 3274, 4022, + 4095, 3307, 4011, + 4095, 3347, 3996, + 4095, 3396, 3975, + 4095, 3454, 3946, + 4095, 3522, 3904, + 4095, 3599, 3841, + 4095, 3685, 3741, + 4075, 3780, 3557, + 0, 1347, 1608, + 0, 1350, 1606, + 0, 1354, 1602, + 0, 1359, 1597, + 0, 1365, 1590, + 0, 1374, 1581, + 0, 1386, 1569, + 0, 1401, 1552, + 0, 1421, 1528, + 0, 1446, 1494, + 0, 1477, 1444, + 0, 1516, 1367, + 0, 1563, 1239, + 0, 1619, 979, + 0, 1685, 0, + 0, 1760, 0, + 0, 1845, 0, + 0, 1938, 0, + 0, 2038, 0, + 0, 2145, 0, + 0, 2257, 0, + 0, 2374, 0, + 0, 2494, 0, + 0, 2617, 0, + 0, 2742, 0, + 0, 2869, 0, + 0, 2997, 0, + 0, 3126, 0, + 0, 3256, 0, + 0, 3386, 0, + 0, 3517, 0, + 0, 3648, 0, + 0, 1348, 1612, + 0, 1351, 1610, + 0, 1354, 1606, + 0, 1360, 1601, + 0, 1366, 1595, + 0, 1375, 1586, + 0, 1387, 1573, + 0, 1402, 1557, + 0, 1422, 1533, + 0, 1447, 1499, + 0, 1478, 1450, + 0, 1516, 1374, + 0, 1564, 1248, + 0, 1620, 995, + 0, 1685, 0, + 0, 1761, 0, + 0, 1845, 0, + 0, 1938, 0, + 0, 2038, 0, + 0, 2145, 0, + 0, 2257, 0, + 0, 2374, 0, + 0, 2494, 0, + 0, 2617, 0, + 0, 2742, 0, + 0, 2869, 0, + 0, 2997, 0, + 0, 3126, 0, + 0, 3256, 0, + 0, 3386, 0, + 0, 3517, 0, + 0, 3648, 0, + 0, 1349, 1618, + 0, 1352, 1615, + 0, 1356, 1611, + 0, 1361, 1607, + 0, 1368, 1600, + 0, 1377, 1591, + 0, 1388, 1579, + 0, 1403, 1563, + 0, 1423, 1539, + 0, 1448, 1506, + 0, 1479, 1457, + 0, 1517, 1383, + 0, 1564, 1260, + 0, 1620, 1015, + 0, 1686, 0, + 0, 1761, 0, + 0, 1845, 0, + 0, 1938, 0, + 0, 2038, 0, + 0, 2145, 0, + 0, 2257, 0, + 0, 2374, 0, + 0, 2494, 0, + 0, 2617, 0, + 0, 2742, 0, + 0, 2869, 0, + 0, 2997, 0, + 0, 3126, 0, + 0, 3256, 0, + 0, 3386, 0, + 0, 3517, 0, + 0, 3648, 0, + 0, 1351, 1625, + 0, 1354, 1622, + 0, 1358, 1619, + 0, 1363, 1614, + 0, 1369, 1607, + 0, 1378, 1599, + 0, 1390, 1587, + 0, 1405, 1570, + 0, 1424, 1548, + 0, 1449, 1515, + 0, 1480, 1467, + 0, 1519, 1395, + 0, 1565, 1275, + 0, 1621, 1041, + 0, 1687, 0, + 0, 1762, 0, + 0, 1846, 0, + 0, 1939, 0, + 0, 2039, 0, + 0, 2145, 0, + 0, 2258, 0, + 0, 2374, 0, + 0, 2494, 0, + 0, 2617, 0, + 0, 2742, 0, + 0, 2869, 0, + 0, 2997, 0, + 0, 3126, 0, + 0, 3256, 0, + 0, 3386, 0, + 0, 3517, 0, + 0, 3648, 0, + 0, 1353, 1634, + 0, 1356, 1631, + 0, 1360, 1628, + 0, 1365, 1623, + 0, 1372, 1617, + 0, 1381, 1608, + 0, 1392, 1597, + 0, 1407, 1581, + 0, 1426, 1558, + 0, 1451, 1527, + 0, 1482, 1480, + 0, 1520, 1410, + 0, 1567, 1295, + 0, 1623, 1074, + 0, 1688, 244, + 0, 1763, 0, + 0, 1847, 0, + 0, 1939, 0, + 0, 2039, 0, + 0, 2146, 0, + 0, 2258, 0, + 0, 2374, 0, + 0, 2494, 0, + 0, 2617, 0, + 0, 2742, 0, + 0, 2869, 0, + 0, 2997, 0, + 0, 3126, 0, + 0, 3256, 0, + 0, 3386, 0, + 0, 3517, 0, + 0, 3648, 0, + 0, 1356, 1646, + 0, 1359, 1643, + 0, 1363, 1640, + 0, 1368, 1636, + 0, 1375, 1629, + 0, 1383, 1621, + 0, 1395, 1610, + 0, 1410, 1594, + 0, 1429, 1573, + 0, 1453, 1542, + 0, 1484, 1497, + 0, 1522, 1430, + 0, 1569, 1320, + 0, 1624, 1114, + 0, 1690, 449, + 0, 1764, 0, + 0, 1848, 0, + 0, 1940, 0, + 0, 2040, 0, + 0, 2146, 0, + 0, 2258, 0, + 0, 2375, 0, + 0, 2495, 0, + 0, 2617, 0, + 0, 2742, 0, + 0, 2869, 0, + 0, 2997, 0, + 0, 3126, 0, + 0, 3256, 0, + 0, 3387, 0, + 0, 3517, 0, + 0, 3648, 0, + 0, 1360, 1662, + 0, 1363, 1659, + 0, 1367, 1656, + 0, 1372, 1652, + 0, 1379, 1646, + 0, 1387, 1638, + 0, 1399, 1627, + 0, 1414, 1612, + 0, 1433, 1591, + 0, 1457, 1561, + 0, 1487, 1519, + 0, 1525, 1455, + 0, 1572, 1351, + 0, 1627, 1162, + 0, 1692, 629, + 0, 1766, 0, + 0, 1849, 0, + 0, 1941, 0, + 0, 2041, 0, + 0, 2147, 0, + 0, 2259, 0, + 0, 2375, 0, + 0, 2495, 0, + 0, 2618, 0, + 0, 2743, 0, + 0, 2869, 0, + 0, 2997, 0, + 0, 3126, 0, + 0, 3256, 0, + 0, 3387, 0, + 0, 3517, 0, + 0, 3648, 0, + 0, 1366, 1682, + 0, 1369, 1679, + 0, 1373, 1676, + 0, 1377, 1672, + 0, 1384, 1666, + 0, 1393, 1659, + 0, 1404, 1648, + 0, 1418, 1634, + 0, 1437, 1614, + 0, 1461, 1586, + 0, 1492, 1546, + 0, 1529, 1486, + 0, 1575, 1390, + 0, 1630, 1220, + 0, 1694, 795, + 0, 1768, 0, + 0, 1851, 0, + 0, 1943, 0, + 0, 2042, 0, + 0, 2148, 0, + 0, 2260, 0, + 0, 2376, 0, + 0, 2495, 0, + 0, 2618, 0, + 0, 2743, 0, + 0, 2870, 0, + 0, 2998, 0, + 0, 3127, 0, + 0, 3256, 0, + 0, 3387, 0, + 0, 3517, 0, + 0, 3649, 0, + 0, 1373, 1707, + 0, 1376, 1705, + 0, 1380, 1702, + 0, 1385, 1698, + 0, 1391, 1693, + 0, 1399, 1686, + 0, 1411, 1676, + 0, 1425, 1662, + 0, 1444, 1644, + 0, 1467, 1618, + 0, 1497, 1580, + 0, 1534, 1525, + 0, 1580, 1438, + 0, 1634, 1287, + 0, 1698, 950, + 0, 1771, 0, + 0, 1854, 0, + 0, 1945, 0, + 0, 2044, 0, + 0, 2149, 0, + 0, 2261, 0, + 0, 2377, 0, + 0, 2496, 0, + 0, 2619, 0, + 0, 2743, 0, + 0, 2870, 0, + 0, 2998, 0, + 0, 3127, 0, + 0, 3256, 0, + 0, 3387, 0, + 0, 3517, 0, + 0, 3649, 0, + 817, 1383, 1739, + 796, 1385, 1737, + 767, 1389, 1734, + 725, 1394, 1731, + 662, 1400, 1726, + 560, 1408, 1719, + 375, 1419, 1710, + 0, 1433, 1698, + 0, 1452, 1680, + 0, 1475, 1656, + 0, 1504, 1622, + 0, 1541, 1572, + 0, 1586, 1494, + 0, 1639, 1364, + 0, 1702, 1098, + 0, 1775, 0, + 0, 1857, 0, + 0, 1948, 0, + 0, 2046, 0, + 0, 2151, 0, + 0, 2262, 0, + 0, 2378, 0, + 0, 2497, 0, + 0, 2619, 0, + 0, 2744, 0, + 0, 2870, 0, + 0, 2998, 0, + 0, 3127, 0, + 0, 3257, 0, + 0, 3387, 0, + 0, 3518, 0, + 0, 3649, 0, + 1204, 1395, 1779, + 1195, 1398, 1777, + 1183, 1401, 1775, + 1166, 1406, 1771, + 1143, 1412, 1767, + 1111, 1420, 1761, + 1063, 1431, 1752, + 990, 1445, 1741, + 870, 1462, 1725, + 635, 1485, 1704, + 0, 1514, 1673, + 0, 1550, 1628, + 0, 1594, 1560, + 0, 1646, 1450, + 0, 1709, 1243, + 0, 1780, 567, + 0, 1861, 0, + 0, 1951, 0, + 0, 2049, 0, + 0, 2154, 0, + 0, 2264, 0, + 0, 2379, 0, + 0, 2498, 0, + 0, 2620, 0, + 0, 2744, 0, + 0, 2871, 0, + 0, 2998, 0, + 0, 3127, 0, + 0, 3257, 0, + 0, 3387, 0, + 0, 3518, 0, + 0, 3649, 0, + 1462, 1411, 1827, + 1457, 1414, 1825, + 1450, 1417, 1823, + 1441, 1422, 1820, + 1429, 1428, 1816, + 1412, 1436, 1811, + 1388, 1446, 1803, + 1354, 1459, 1793, + 1304, 1476, 1779, + 1227, 1498, 1760, + 1098, 1526, 1733, + 836, 1561, 1694, + 0, 1604, 1636, + 0, 1656, 1544, + 0, 1717, 1383, + 0, 1787, 1003, + 0, 1867, 0, + 0, 1956, 0, + 0, 2053, 0, + 0, 2157, 0, + 0, 2266, 0, + 0, 2381, 0, + 0, 2499, 0, + 0, 2621, 0, + 0, 2745, 0, + 0, 2871, 0, + 0, 2999, 0, + 0, 3128, 0, + 0, 3257, 0, + 0, 3387, 0, + 0, 3518, 0, + 0, 3649, 0, + 1670, 1432, 1884, + 1667, 1435, 1883, + 1663, 1438, 1881, + 1657, 1442, 1878, + 1649, 1448, 1875, + 1639, 1455, 1870, + 1624, 1465, 1863, + 1604, 1478, 1854, + 1576, 1494, 1842, + 1536, 1516, 1826, + 1475, 1543, 1802, + 1378, 1576, 1769, + 1206, 1618, 1720, + 769, 1668, 1646, + 0, 1728, 1522, + 0, 1797, 1276, + 0, 1875, 0, + 0, 1962, 0, + 0, 2058, 0, + 0, 2161, 0, + 0, 2270, 0, + 0, 2383, 0, + 0, 2501, 0, + 0, 2623, 0, + 0, 2746, 0, + 0, 2872, 0, + 0, 3000, 0, + 0, 3128, 0, + 0, 3257, 0, + 0, 3387, 0, + 0, 3518, 0, + 0, 3649, 0, + 1851, 1458, 1951, + 1849, 1461, 1950, + 1847, 1464, 1948, + 1843, 1468, 1946, + 1838, 1473, 1943, + 1831, 1480, 1939, + 1821, 1490, 1933, + 1809, 1502, 1925, + 1791, 1517, 1915, + 1766, 1538, 1901, + 1730, 1563, 1881, + 1678, 1596, 1853, + 1597, 1636, 1813, + 1459, 1684, 1753, + 1167, 1741, 1659, + 0, 1809, 1491, + 0, 1885, 1074, + 0, 1971, 0, + 0, 2065, 0, + 0, 2166, 0, + 0, 2274, 0, + 0, 2387, 0, + 0, 2504, 0, + 0, 2625, 0, + 0, 2748, 0, + 0, 2873, 0, + 0, 3000, 0, + 0, 3129, 0, + 0, 3258, 0, + 0, 3388, 0, + 0, 3518, 0, + 0, 3649, 0, + 2017, 1491, 2027, + 2016, 1494, 2026, + 2014, 1496, 2025, + 2011, 1500, 2023, + 2008, 1505, 2020, + 2003, 1512, 2017, + 1997, 1520, 2012, + 1988, 1532, 2006, + 1976, 1547, 1997, + 1960, 1566, 1985, + 1937, 1590, 1969, + 1904, 1620, 1946, + 1856, 1658, 1914, + 1784, 1704, 1867, + 1664, 1759, 1794, + 1430, 1824, 1676, + 367, 1898, 1445, + 0, 1982, 454, + 0, 2074, 0, + 0, 2173, 0, + 0, 2279, 0, + 0, 2391, 0, + 0, 2507, 0, + 0, 2627, 0, + 0, 2750, 0, + 0, 2875, 0, + 0, 3002, 0, + 0, 3130, 0, + 0, 3259, 0, + 0, 3388, 0, + 0, 3519, 0, + 0, 3649, 0, + 2173, 1532, 2113, + 2172, 1534, 2112, + 2171, 1537, 2111, + 2169, 1540, 2109, + 2166, 1545, 2107, + 2163, 1551, 2104, + 2158, 1559, 2100, + 2152, 1569, 2095, + 2144, 1583, 2088, + 2133, 1600, 2078, + 2117, 1623, 2065, + 2096, 1651, 2047, + 2065, 1687, 2021, + 2021, 1730, 1984, + 1953, 1782, 1929, + 1844, 1844, 1844, + 1639, 1915, 1698, + 988, 1996, 1375, + 0, 2085, 0, + 0, 2183, 0, + 0, 2287, 0, + 0, 2397, 0, + 0, 2512, 0, + 0, 2631, 0, + 0, 2753, 0, + 0, 2877, 0, + 0, 3003, 0, + 0, 3131, 0, + 0, 3259, 0, + 0, 3389, 0, + 0, 3519, 0, + 0, 3650, 0, + 2322, 1581, 2206, + 2321, 1583, 2206, + 2320, 1585, 2205, + 2319, 1588, 2204, + 2317, 1593, 2202, + 2315, 1598, 2199, + 2312, 1605, 2196, + 2307, 1615, 2192, + 2301, 1627, 2186, + 2293, 1643, 2179, + 2283, 1663, 2168, + 2268, 1690, 2153, + 2247, 1722, 2133, + 2218, 1763, 2105, + 2175, 1811, 2063, + 2111, 1870, 2001, + 2009, 1937, 1903, + 1822, 2014, 1725, + 1302, 2100, 1261, + 0, 2195, 0, + 0, 2297, 0, + 0, 2405, 0, + 0, 2518, 0, + 0, 2635, 0, + 0, 2756, 0, + 0, 2880, 0, + 0, 3005, 0, + 0, 3132, 0, + 0, 3261, 0, + 0, 3390, 0, + 0, 3520, 0, + 0, 3650, 0, + 2466, 1640, 2308, + 2466, 1641, 2307, + 2465, 1643, 2306, + 2464, 1646, 2305, + 2463, 1650, 2304, + 2461, 1655, 2302, + 2459, 1661, 2299, + 2456, 1669, 2296, + 2451, 1680, 2292, + 2446, 1694, 2285, + 2438, 1713, 2277, + 2427, 1736, 2266, + 2413, 1766, 2250, + 2393, 1803, 2228, + 2364, 1848, 2197, + 2323, 1902, 2152, + 2262, 1965, 2083, + 2164, 2038, 1971, + 1988, 2120, 1760, + 1534, 2211, 1044, + 0, 2309, 0, + 0, 2415, 0, + 0, 2526, 0, + 0, 2641, 0, + 0, 2761, 0, + 0, 2883, 0, + 0, 3008, 0, + 0, 3134, 0, + 0, 3262, 0, + 0, 3391, 0, + 0, 3521, 0, + 0, 3651, 0, + 2607, 1708, 2415, + 2607, 1709, 2415, + 2607, 1711, 2414, + 2606, 1713, 2413, + 2605, 1716, 2412, + 2604, 1721, 2411, + 2602, 1726, 2409, + 2600, 1733, 2406, + 2597, 1743, 2402, + 2592, 1755, 2398, + 2587, 1771, 2391, + 2579, 1792, 2382, + 2569, 1818, 2370, + 2555, 1851, 2353, + 2535, 1892, 2330, + 2507, 1941, 2297, + 2467, 1999, 2248, + 2407, 2067, 2173, + 2313, 2145, 2049, + 2144, 2231, 1802, + 1729, 2326, 267, + 0, 2428, 0, + 0, 2536, 0, + 0, 2649, 0, + 0, 2767, 0, + 0, 2888, 0, + 0, 3011, 0, + 0, 3137, 0, + 0, 3264, 0, + 0, 3393, 0, + 0, 3522, 0, + 0, 3652, 0, + 2746, 1785, 2528, + 2746, 1786, 2528, + 2745, 1788, 2527, + 2745, 1790, 2526, + 2744, 1793, 2526, + 2743, 1796, 2524, + 2742, 1801, 2523, + 2740, 1807, 2521, + 2738, 1815, 2518, + 2735, 1826, 2514, + 2731, 1839, 2509, + 2726, 1857, 2502, + 2718, 1880, 2493, + 2708, 1909, 2480, + 2694, 1945, 2463, + 2674, 1989, 2438, + 2647, 2042, 2403, + 2608, 2104, 2351, + 2549, 2176, 2271, + 2457, 2257, 2136, + 2294, 2347, 1853, + 1903, 2445, 0, + 0, 2549, 0, + 0, 2660, 0, + 0, 2775, 0, + 0, 2894, 0, + 0, 3016, 0, + 0, 3141, 0, + 0, 3267, 0, + 0, 3395, 0, + 0, 3523, 0, + 0, 3653, 0, + 2883, 1872, 2645, + 2883, 1873, 2645, + 2883, 1874, 2644, + 2882, 1876, 2644, + 2882, 1878, 2643, + 2881, 1881, 2642, + 2880, 1885, 2641, + 2879, 1890, 2640, + 2877, 1897, 2637, + 2875, 1905, 2635, + 2872, 1917, 2631, + 2868, 1932, 2625, + 2862, 1952, 2618, + 2855, 1976, 2609, + 2845, 2008, 2596, + 2831, 2046, 2577, + 2812, 2093, 2552, + 2785, 2149, 2515, + 2746, 2215, 2461, + 2688, 2290, 2376, + 2598, 2374, 2231, + 2438, 2467, 1914, + 2064, 2567, 0, + 0, 2674, 0, + 0, 2786, 0, + 0, 2902, 0, + 0, 3022, 0, + 0, 3145, 0, + 0, 3271, 0, + 0, 3397, 0, + 0, 3525, 0, + 0, 3655, 0, + 3019, 1967, 2766, + 3019, 1967, 2765, + 3018, 1968, 2765, + 3018, 1970, 2765, + 3018, 1971, 2764, + 3017, 1974, 2763, + 3017, 1977, 2763, + 3016, 1981, 2761, + 3014, 1987, 2760, + 3013, 1994, 2758, + 3011, 2004, 2755, + 3008, 2016, 2751, + 3004, 2032, 2745, + 2998, 2053, 2738, + 2991, 2080, 2728, + 2981, 2113, 2715, + 2967, 2154, 2696, + 2948, 2203, 2669, + 2921, 2262, 2631, + 2883, 2330, 2575, + 2826, 2408, 2487, + 2736, 2494, 2334, + 2580, 2589, 1984, + 2216, 2691, 0, + 0, 2800, 0, + 0, 2913, 0, + 0, 3031, 0, + 0, 3152, 0, + 0, 3275, 0, + 0, 3401, 0, + 0, 3528, 0, + 0, 3657, 0, + 3154, 2069, 2889, + 3153, 2069, 2889, + 3153, 2070, 2888, + 3153, 2071, 2888, + 3153, 2072, 2888, + 3152, 2074, 2887, + 3152, 2077, 2887, + 3151, 2080, 2886, + 3150, 2085, 2884, + 3149, 2091, 2883, + 3147, 2098, 2881, + 3145, 2109, 2878, + 3142, 2122, 2873, + 3138, 2139, 2868, + 3133, 2161, 2861, + 3126, 2189, 2850, + 3116, 2224, 2837, + 3102, 2266, 2817, + 3083, 2318, 2790, + 3057, 2379, 2751, + 3018, 2449, 2693, + 2962, 2529, 2602, + 2873, 2617, 2442, + 2718, 2714, 2063, + 2363, 2818, 0, + 0, 2927, 0, + 0, 3042, 0, + 0, 3160, 0, + 0, 3282, 0, + 0, 3406, 0, + 0, 3532, 0, + 0, 3659, 0, + 3288, 2177, 3014, + 3288, 2177, 3014, + 3287, 2178, 3014, + 3287, 2179, 3014, + 3287, 2180, 3013, + 3287, 2181, 3013, + 3286, 2183, 3012, + 3286, 2186, 3012, + 3285, 2190, 3011, + 3284, 2194, 3010, + 3283, 2200, 3008, + 3281, 2209, 3006, + 3279, 2219, 3003, + 3276, 2233, 2998, + 3272, 2251, 2993, + 3267, 2274, 2985, + 3260, 2303, 2975, + 3250, 2339, 2961, + 3236, 2383, 2941, + 3217, 2437, 2914, + 3191, 2499, 2874, + 3153, 2571, 2815, + 3097, 2652, 2721, + 3009, 2743, 2556, + 2855, 2840, 2152, + 2506, 2945, 0, + 0, 3056, 0, + 0, 3171, 0, + 0, 3290, 0, + 0, 3412, 0, + 0, 3537, 0, + 0, 3663, 0, + 3421, 2290, 3141, + 3421, 2291, 3141, + 3421, 2291, 3141, + 3421, 2292, 3141, + 3421, 2293, 3141, + 3421, 2294, 3140, + 3420, 2295, 3140, + 3420, 2297, 3139, + 3419, 2300, 3139, + 3419, 2304, 3138, + 3418, 2309, 3136, + 3417, 2315, 3135, + 3415, 2324, 3132, + 3413, 2335, 3129, + 3410, 2349, 3125, + 3406, 2368, 3120, + 3401, 2392, 3112, + 3393, 2421, 3102, + 3384, 2459, 3087, + 3370, 2504, 3067, + 3351, 2558, 3039, + 3325, 2622, 2999, + 3287, 2696, 2939, + 3231, 2778, 2844, + 3143, 2869, 2673, + 2991, 2968, 2248, + 2646, 3074, 0, + 0, 3185, 0, + 0, 3301, 0, + 0, 3421, 0, + 0, 3543, 0, + 0, 3668, 0, + 3554, 2408, 3269, + 3554, 2408, 3269, + 3554, 2408, 3269, + 3554, 2409, 3269, + 3554, 2410, 3269, + 3554, 2411, 3269, + 3554, 2412, 3268, + 3553, 2413, 3268, + 3553, 2416, 3268, + 3553, 2418, 3267, + 3552, 2422, 3266, + 3551, 2427, 3265, + 3550, 2434, 3263, + 3548, 2443, 3261, + 3546, 2454, 3257, + 3543, 2469, 3253, + 3539, 2488, 3248, + 3534, 2512, 3240, + 3527, 2543, 3229, + 3517, 2581, 3215, + 3503, 2627, 3195, + 3485, 2683, 3167, + 3458, 2747, 3126, + 3421, 2822, 3065, + 3365, 2905, 2968, + 3277, 2998, 2794, + 3126, 3097, 2352, + 2784, 3204, 0, + 0, 3315, 0, + 0, 3432, 0, + 0, 3552, 0, + 0, 3674, 0, + 3687, 2529, 3399, + 3687, 2529, 3399, + 3687, 2529, 3399, + 3687, 2530, 3398, + 3687, 2530, 3398, + 3687, 2531, 3398, + 3687, 2532, 3398, + 3687, 2533, 3398, + 3686, 2535, 3397, + 3686, 2537, 3397, + 3685, 2540, 3396, + 3685, 2544, 3395, + 3684, 2549, 3394, + 3683, 2556, 3392, + 3681, 2565, 3390, + 3679, 2576, 3387, + 3676, 2591, 3382, + 3672, 2611, 3377, + 3667, 2636, 3369, + 3660, 2667, 3358, + 3650, 2706, 3344, + 3636, 2753, 3324, + 3618, 2809, 3295, + 3591, 2874, 3254, + 3554, 2950, 3192, + 3498, 3034, 3094, + 3411, 3127, 2918, + 3260, 3227, 2461, + 2920, 3334, 0, + 0, 3446, 0, + 0, 3563, 0, + 0, 3683, 0, + 3820, 2652, 3529, + 3820, 2652, 3529, + 3820, 2653, 3528, + 3820, 2653, 3528, + 3820, 2653, 3528, + 3820, 2654, 3528, + 3820, 2655, 3528, + 3820, 2656, 3528, + 3819, 2657, 3528, + 3819, 2658, 3527, + 3819, 2661, 3527, + 3818, 2664, 3526, + 3817, 2668, 3525, + 3817, 2673, 3524, + 3815, 2680, 3522, + 3814, 2689, 3519, + 3812, 2701, 3516, + 3809, 2716, 3512, + 3805, 2736, 3506, + 3799, 2761, 3499, + 3792, 2793, 3488, + 3782, 2832, 3473, + 3769, 2880, 3453, + 3750, 2936, 3424, + 3724, 3003, 3383, + 3687, 3078, 3321, + 3631, 3163, 3222, + 3544, 3257, 3044, + 3394, 3357, 2575, + 3056, 3465, 0, + 0, 3577, 0, + 0, 3694, 0, + 3953, 2778, 3659, + 3953, 2778, 3659, + 3953, 2778, 3659, + 3953, 2778, 3659, + 3952, 2779, 3659, + 3952, 2779, 3659, + 3952, 2780, 3659, + 3952, 2780, 3658, + 3952, 2781, 3658, + 3952, 2783, 3658, + 3952, 2784, 3658, + 3951, 2787, 3657, + 3951, 2790, 3656, + 3950, 2794, 3655, + 3949, 2799, 3654, + 3948, 2806, 3652, + 3946, 2815, 3650, + 3944, 2827, 3647, + 3941, 2843, 3642, + 3937, 2863, 3637, + 3932, 2888, 3629, + 3925, 2920, 3618, + 3915, 2960, 3604, + 3902, 3008, 3583, + 3883, 3065, 3554, + 3857, 3132, 3513, + 3819, 3208, 3450, + 3764, 3293, 3351, + 3677, 3387, 3171, + 3527, 3488, 2694, + 3190, 3596, 0, + 0, 3708, 0, + 4085, 2905, 3790, + 4085, 2905, 3790, + 4085, 2905, 3790, + 4085, 2905, 3790, + 4085, 2906, 3790, + 4085, 2906, 3790, + 4085, 2906, 3790, + 4085, 2907, 3789, + 4085, 2908, 3789, + 4084, 2909, 3789, + 4084, 2910, 3789, + 4084, 2912, 3788, + 4084, 2914, 3788, + 4083, 2917, 3787, + 4082, 2921, 3786, + 4082, 2926, 3785, + 4080, 2933, 3783, + 4079, 2943, 3781, + 4077, 2955, 3778, + 4074, 2971, 3773, + 4070, 2991, 3768, + 4064, 3017, 3760, + 4057, 3049, 3749, + 4047, 3089, 3734, + 4034, 3137, 3714, + 4015, 3195, 3685, + 3989, 3262, 3643, + 3952, 3338, 3581, + 3896, 3424, 3481, + 3810, 3518, 3299, + 3660, 3619, 2815, + 3324, 3727, 0, + 4095, 3033, 3921, + 4095, 3034, 3921, + 4095, 3034, 3921, + 4095, 3034, 3921, + 4095, 3034, 3921, + 4095, 3034, 3921, + 4095, 3034, 3921, + 4095, 3035, 3921, + 4095, 3035, 3921, + 4095, 3036, 3920, + 4095, 3037, 3920, + 4095, 3038, 3920, + 4095, 3040, 3920, + 4095, 3042, 3919, + 4095, 3046, 3918, + 4095, 3050, 3917, + 4095, 3055, 3916, + 4095, 3062, 3914, + 4095, 3072, 3912, + 4095, 3084, 3909, + 4095, 3100, 3904, + 4095, 3120, 3899, + 4095, 3146, 3891, + 4095, 3178, 3880, + 4095, 3218, 3865, + 4095, 3267, 3845, + 4095, 3325, 3816, + 4095, 3392, 3774, + 4084, 3469, 3711, + 4029, 3555, 3611, + 3942, 3649, 3429, + 3793, 3751, 2939, + 4095, 3163, 4053, + 4095, 3163, 4052, + 4095, 3163, 4052, + 4095, 3163, 4052, + 4095, 3163, 4052, + 4095, 3163, 4052, + 4095, 3164, 4052, + 4095, 3164, 4052, + 4095, 3164, 4052, + 4095, 3165, 4052, + 4095, 3166, 4052, + 4095, 3167, 4052, + 4095, 3168, 4051, + 4095, 3170, 4051, + 4095, 3172, 4050, + 4095, 3175, 4050, + 4095, 3179, 4049, + 4095, 3185, 4047, + 4095, 3192, 4046, + 4095, 3201, 4043, + 4095, 3213, 4040, + 4095, 3229, 4036, + 4095, 3250, 4030, + 4095, 3276, 4022, + 4095, 3308, 4011, + 4095, 3349, 3997, + 4095, 3397, 3976, + 4095, 3455, 3947, + 4095, 3523, 3905, + 4095, 3600, 3842, + 4095, 3686, 3742, + 4075, 3780, 3559, + 0, 1476, 1739, + 0, 1478, 1737, + 0, 1481, 1735, + 0, 1485, 1731, + 0, 1490, 1726, + 0, 1497, 1719, + 0, 1506, 1710, + 0, 1518, 1698, + 0, 1533, 1681, + 0, 1552, 1657, + 0, 1577, 1622, + 0, 1609, 1572, + 0, 1647, 1494, + 0, 1695, 1365, + 0, 1751, 1099, + 0, 1817, 0, + 0, 1892, 0, + 0, 1976, 0, + 0, 2069, 0, + 0, 2170, 0, + 0, 2277, 0, + 0, 2389, 0, + 0, 2506, 0, + 0, 2626, 0, + 0, 2749, 0, + 0, 2874, 0, + 0, 3001, 0, + 0, 3129, 0, + 0, 3258, 0, + 0, 3388, 0, + 0, 3518, 0, + 0, 3649, 0, + 0, 1477, 1742, + 0, 1479, 1740, + 0, 1482, 1738, + 0, 1486, 1734, + 0, 1491, 1729, + 0, 1498, 1723, + 0, 1507, 1713, + 0, 1518, 1701, + 0, 1533, 1684, + 0, 1553, 1660, + 0, 1578, 1626, + 0, 1609, 1576, + 0, 1648, 1500, + 0, 1695, 1371, + 0, 1751, 1111, + 0, 1817, 0, + 0, 1892, 0, + 0, 1977, 0, + 0, 2070, 0, + 0, 2170, 0, + 0, 2277, 0, + 0, 2389, 0, + 0, 2506, 0, + 0, 2626, 0, + 0, 2749, 0, + 0, 2874, 0, + 0, 3001, 0, + 0, 3129, 0, + 0, 3258, 0, + 0, 3388, 0, + 0, 3519, 0, + 0, 3649, 0, + 0, 1478, 1746, + 0, 1480, 1744, + 0, 1483, 1742, + 0, 1487, 1738, + 0, 1492, 1733, + 0, 1499, 1727, + 0, 1507, 1718, + 0, 1519, 1706, + 0, 1534, 1689, + 0, 1554, 1665, + 0, 1579, 1631, + 0, 1610, 1582, + 0, 1649, 1506, + 0, 1696, 1380, + 0, 1752, 1127, + 0, 1818, 0, + 0, 1893, 0, + 0, 1977, 0, + 0, 2070, 0, + 0, 2170, 0, + 0, 2277, 0, + 0, 2389, 0, + 0, 2506, 0, + 0, 2626, 0, + 0, 2749, 0, + 0, 2874, 0, + 0, 3001, 0, + 0, 3129, 0, + 0, 3258, 0, + 0, 3388, 0, + 0, 3519, 0, + 0, 3649, 0, + 0, 1479, 1752, + 0, 1481, 1750, + 0, 1484, 1747, + 0, 1488, 1744, + 0, 1493, 1739, + 0, 1500, 1732, + 0, 1509, 1723, + 0, 1520, 1711, + 0, 1535, 1695, + 0, 1555, 1671, + 0, 1580, 1638, + 0, 1611, 1590, + 0, 1650, 1515, + 0, 1696, 1392, + 0, 1753, 1147, + 0, 1818, 0, + 0, 1893, 0, + 0, 1978, 0, + 0, 2070, 0, + 0, 2171, 0, + 0, 2277, 0, + 0, 2389, 0, + 0, 2506, 0, + 0, 2626, 0, + 0, 2749, 0, + 0, 2874, 0, + 0, 3001, 0, + 0, 3129, 0, + 0, 3258, 0, + 0, 3388, 0, + 0, 3519, 0, + 0, 3649, 0, + 0, 1481, 1759, + 0, 1483, 1757, + 0, 1486, 1754, + 0, 1490, 1751, + 0, 1495, 1746, + 0, 1502, 1740, + 0, 1510, 1731, + 0, 1522, 1719, + 0, 1537, 1703, + 0, 1556, 1680, + 0, 1581, 1647, + 0, 1612, 1600, + 0, 1651, 1527, + 0, 1698, 1407, + 0, 1754, 1173, + 0, 1819, 122, + 0, 1894, 0, + 0, 1978, 0, + 0, 2071, 0, + 0, 2171, 0, + 0, 2278, 0, + 0, 2390, 0, + 0, 2506, 0, + 0, 2626, 0, + 0, 2749, 0, + 0, 2874, 0, + 0, 3001, 0, + 0, 3129, 0, + 0, 3258, 0, + 0, 3388, 0, + 0, 3519, 0, + 0, 3649, 0, + 0, 1483, 1768, + 0, 1485, 1766, + 0, 1488, 1763, + 0, 1492, 1760, + 0, 1497, 1755, + 0, 1504, 1749, + 0, 1513, 1741, + 0, 1524, 1729, + 0, 1539, 1713, + 0, 1558, 1691, + 0, 1583, 1659, + 0, 1614, 1612, + 0, 1652, 1542, + 0, 1699, 1427, + 0, 1755, 1206, + 0, 1820, 376, + 0, 1895, 0, + 0, 1979, 0, + 0, 2071, 0, + 0, 2171, 0, + 0, 2278, 0, + 0, 2390, 0, + 0, 2506, 0, + 0, 2626, 0, + 0, 2749, 0, + 0, 2874, 0, + 0, 3001, 0, + 0, 3129, 0, + 0, 3258, 0, + 0, 3388, 0, + 0, 3519, 0, + 0, 3649, 0, + 0, 1486, 1780, + 0, 1488, 1778, + 0, 1491, 1776, + 0, 1495, 1772, + 0, 1500, 1768, + 0, 1507, 1762, + 0, 1516, 1753, + 0, 1527, 1742, + 0, 1542, 1726, + 0, 1561, 1705, + 0, 1586, 1674, + 0, 1616, 1629, + 0, 1655, 1562, + 0, 1701, 1452, + 0, 1757, 1246, + 0, 1822, 581, + 0, 1896, 0, + 0, 1980, 0, + 0, 2072, 0, + 0, 2172, 0, + 0, 2279, 0, + 0, 2390, 0, + 0, 2507, 0, + 0, 2627, 0, + 0, 2750, 0, + 0, 2875, 0, + 0, 3001, 0, + 0, 3129, 0, + 0, 3258, 0, + 0, 3388, 0, + 0, 3519, 0, + 0, 3649, 0, + 0, 1490, 1795, + 0, 1493, 1794, + 0, 1495, 1791, + 0, 1499, 1788, + 0, 1504, 1784, + 0, 1511, 1778, + 0, 1519, 1770, + 0, 1531, 1759, + 0, 1546, 1744, + 0, 1565, 1723, + 0, 1589, 1694, + 0, 1620, 1651, + 0, 1657, 1587, + 0, 1704, 1484, + 0, 1759, 1294, + 0, 1824, 762, + 0, 1898, 0, + 0, 1981, 0, + 0, 2073, 0, + 0, 2173, 0, + 0, 2279, 0, + 0, 2391, 0, + 0, 2507, 0, + 0, 2627, 0, + 0, 2750, 0, + 0, 2875, 0, + 0, 3001, 0, + 0, 3129, 0, + 0, 3259, 0, + 0, 3388, 0, + 0, 3519, 0, + 0, 3649, 0, + 0, 1496, 1815, + 0, 1498, 1814, + 0, 1501, 1811, + 0, 1505, 1808, + 0, 1510, 1804, + 0, 1516, 1799, + 0, 1525, 1791, + 0, 1536, 1781, + 0, 1551, 1766, + 0, 1569, 1746, + 0, 1593, 1718, + 0, 1624, 1678, + 0, 1661, 1618, + 0, 1707, 1522, + 0, 1762, 1352, + 0, 1826, 927, + 0, 1900, 0, + 0, 1983, 0, + 0, 2075, 0, + 0, 2174, 0, + 0, 2280, 0, + 0, 2392, 0, + 0, 2508, 0, + 0, 2628, 0, + 0, 2750, 0, + 0, 2875, 0, + 0, 3002, 0, + 0, 3130, 0, + 0, 3259, 0, + 0, 3388, 0, + 0, 3519, 0, + 0, 3649, 0, + 0, 1503, 1841, + 0, 1505, 1839, + 0, 1508, 1837, + 0, 1512, 1834, + 0, 1517, 1830, + 0, 1523, 1825, + 0, 1532, 1818, + 0, 1543, 1808, + 0, 1557, 1795, + 0, 1576, 1776, + 0, 1599, 1750, + 0, 1629, 1712, + 0, 1666, 1657, + 0, 1712, 1570, + 0, 1766, 1419, + 0, 1830, 1082, + 0, 1903, 0, + 0, 1986, 0, + 0, 2077, 0, + 0, 2176, 0, + 0, 2282, 0, + 0, 2393, 0, + 0, 2509, 0, + 0, 2628, 0, + 0, 2751, 0, + 0, 2875, 0, + 0, 3002, 0, + 0, 3130, 0, + 0, 3259, 0, + 0, 3388, 0, + 0, 3519, 0, + 0, 3650, 0, + 964, 1513, 1873, + 949, 1515, 1871, + 928, 1518, 1869, + 899, 1521, 1867, + 857, 1526, 1863, + 794, 1532, 1858, + 692, 1541, 1851, + 507, 1551, 1842, + 0, 1566, 1830, + 0, 1584, 1813, + 0, 1607, 1788, + 0, 1637, 1754, + 0, 1673, 1704, + 0, 1718, 1626, + 0, 1771, 1496, + 0, 1835, 1231, + 0, 1907, 0, + 0, 1989, 0, + 0, 2080, 0, + 0, 2178, 0, + 0, 2283, 0, + 0, 2394, 0, + 0, 2510, 0, + 0, 2629, 0, + 0, 2751, 0, + 0, 2876, 0, + 0, 3002, 0, + 0, 3130, 0, + 0, 3259, 0, + 0, 3389, 0, + 0, 3519, 0, + 0, 3650, 0, + 1342, 1525, 1912, + 1336, 1527, 1911, + 1327, 1530, 1909, + 1315, 1533, 1907, + 1299, 1538, 1903, + 1276, 1544, 1899, + 1243, 1552, 1893, + 1195, 1563, 1884, + 1123, 1577, 1873, + 1003, 1595, 1857, + 767, 1617, 1836, + 0, 1646, 1805, + 0, 1682, 1760, + 0, 1726, 1692, + 0, 1779, 1582, + 0, 1841, 1375, + 0, 1912, 699, + 0, 1994, 0, + 0, 2083, 0, + 0, 2181, 0, + 0, 2286, 0, + 0, 2396, 0, + 0, 2511, 0, + 0, 2630, 0, + 0, 2752, 0, + 0, 2877, 0, + 0, 3003, 0, + 0, 3130, 0, + 0, 3259, 0, + 0, 3389, 0, + 0, 3519, 0, + 0, 3650, 0, + 1598, 1542, 1960, + 1594, 1543, 1959, + 1589, 1546, 1957, + 1582, 1549, 1955, + 1573, 1554, 1952, + 1561, 1560, 1948, + 1544, 1568, 1943, + 1520, 1578, 1935, + 1486, 1591, 1925, + 1436, 1608, 1911, + 1359, 1631, 1892, + 1230, 1659, 1865, + 968, 1693, 1826, + 0, 1736, 1768, + 0, 1788, 1676, + 0, 1849, 1516, + 0, 1919, 1135, + 0, 1999, 0, + 0, 2088, 0, + 0, 2185, 0, + 0, 2289, 0, + 0, 2398, 0, + 0, 2513, 0, + 0, 2632, 0, + 0, 2753, 0, + 0, 2877, 0, + 0, 3003, 0, + 0, 3131, 0, + 0, 3260, 0, + 0, 3389, 0, + 0, 3519, 0, + 0, 3650, 0, + 1804, 1562, 2017, + 1802, 1564, 2016, + 1799, 1567, 2015, + 1795, 1570, 2013, + 1789, 1574, 2010, + 1781, 1580, 2007, + 1771, 1587, 2002, + 1756, 1597, 1995, + 1737, 1610, 1987, + 1708, 1626, 1974, + 1668, 1648, 1958, + 1607, 1675, 1934, + 1511, 1708, 1901, + 1338, 1750, 1852, + 901, 1800, 1778, + 0, 1860, 1654, + 0, 1929, 1408, + 0, 2007, 0, + 0, 2095, 0, + 0, 2190, 0, + 0, 2293, 0, + 0, 2402, 0, + 0, 2515, 0, + 0, 2633, 0, + 0, 2755, 0, + 0, 2878, 0, + 0, 3004, 0, + 0, 3132, 0, + 0, 3260, 0, + 0, 3389, 0, + 0, 3520, 0, + 0, 3650, 0, + 1985, 1589, 2084, + 1983, 1591, 2083, + 1981, 1593, 2082, + 1979, 1596, 2080, + 1975, 1600, 2078, + 1970, 1605, 2075, + 1963, 1612, 2071, + 1953, 1622, 2065, + 1941, 1634, 2058, + 1923, 1650, 2047, + 1898, 1670, 2033, + 1862, 1695, 2013, + 1810, 1728, 1985, + 1729, 1768, 1945, + 1591, 1816, 1886, + 1299, 1874, 1791, + 0, 1941, 1623, + 0, 2017, 1207, + 0, 2103, 0, + 0, 2197, 0, + 0, 2298, 0, + 0, 2406, 0, + 0, 2519, 0, + 0, 2636, 0, + 0, 2757, 0, + 0, 2880, 0, + 0, 3005, 0, + 0, 3132, 0, + 0, 3261, 0, + 0, 3390, 0, + 0, 3520, 0, + 0, 3650, 0, + 2150, 1622, 2160, + 2149, 1623, 2159, + 2148, 1626, 2158, + 2146, 1628, 2157, + 2143, 1632, 2155, + 2140, 1637, 2152, + 2135, 1644, 2149, + 2129, 1653, 2144, + 2120, 1664, 2138, + 2108, 1679, 2129, + 2092, 1698, 2117, + 2069, 1722, 2101, + 2036, 1752, 2078, + 1989, 1790, 2046, + 1916, 1836, 1999, + 1796, 1892, 1927, + 1562, 1956, 1808, + 499, 2030, 1577, + 0, 2114, 586, + 0, 2206, 0, + 0, 2305, 0, + 0, 2412, 0, + 0, 2523, 0, + 0, 2639, 0, + 0, 2759, 0, + 0, 2882, 0, + 0, 3007, 0, + 0, 3134, 0, + 0, 3262, 0, + 0, 3391, 0, + 0, 3520, 0, + 0, 3651, 0, + 2306, 1663, 2246, + 2305, 1664, 2245, + 2304, 1666, 2244, + 2303, 1669, 2243, + 2301, 1672, 2241, + 2298, 1677, 2239, + 2295, 1683, 2236, + 2291, 1691, 2232, + 2284, 1701, 2227, + 2276, 1715, 2220, + 2265, 1732, 2210, + 2249, 1755, 2197, + 2228, 1783, 2179, + 2197, 1819, 2153, + 2153, 1862, 2116, + 2085, 1915, 2061, + 1976, 1976, 1976, + 1771, 2047, 1830, + 1120, 2128, 1507, + 0, 2217, 0, + 0, 2315, 0, + 0, 2419, 0, + 0, 2529, 0, + 0, 2644, 0, + 0, 2763, 0, + 0, 2885, 0, + 0, 3009, 0, + 0, 3135, 0, + 0, 3263, 0, + 0, 3392, 0, + 0, 3521, 0, + 0, 3651, 0, + 2455, 1712, 2339, + 2454, 1713, 2339, + 2453, 1715, 2338, + 2452, 1717, 2337, + 2451, 1721, 2336, + 2449, 1725, 2334, + 2447, 1730, 2332, + 2444, 1737, 2328, + 2439, 1747, 2324, + 2434, 1759, 2318, + 2426, 1775, 2311, + 2415, 1796, 2300, + 2400, 1822, 2285, + 2379, 1854, 2265, + 2350, 1895, 2237, + 2307, 1944, 2195, + 2243, 2002, 2134, + 2141, 2069, 2035, + 1954, 2146, 1857, + 1434, 2233, 1394, + 0, 2327, 0, + 0, 2429, 0, + 0, 2537, 0, + 0, 2650, 0, + 0, 2767, 0, + 0, 2888, 0, + 0, 3012, 0, + 0, 3137, 0, + 0, 3264, 0, + 0, 3393, 0, + 0, 3522, 0, + 0, 3652, 0, + 2599, 1771, 2440, + 2598, 1772, 2440, + 2598, 1773, 2439, + 2597, 1775, 2438, + 2596, 1778, 2437, + 2595, 1782, 2436, + 2593, 1787, 2434, + 2591, 1793, 2432, + 2588, 1801, 2428, + 2584, 1812, 2424, + 2578, 1827, 2418, + 2570, 1845, 2409, + 2560, 1868, 2398, + 2545, 1898, 2382, + 2525, 1935, 2360, + 2496, 1980, 2329, + 2455, 2034, 2284, + 2394, 2097, 2215, + 2296, 2170, 2104, + 2120, 2252, 1892, + 1666, 2343, 1176, + 0, 2441, 0, + 0, 2547, 0, + 0, 2658, 0, + 0, 2773, 0, + 0, 2893, 0, + 0, 3015, 0, + 0, 3140, 0, + 0, 3266, 0, + 0, 3394, 0, + 0, 3523, 0, + 0, 3653, 0, + 2740, 1839, 2548, + 2740, 1840, 2547, + 2739, 1841, 2547, + 2739, 1843, 2546, + 2738, 1845, 2545, + 2737, 1848, 2544, + 2736, 1853, 2543, + 2734, 1858, 2541, + 2732, 1865, 2538, + 2729, 1875, 2535, + 2725, 1887, 2530, + 2719, 1903, 2523, + 2711, 1924, 2514, + 2701, 1950, 2502, + 2687, 1983, 2486, + 2667, 2024, 2462, + 2639, 2073, 2429, + 2599, 2132, 2380, + 2539, 2199, 2305, + 2445, 2277, 2181, + 2277, 2363, 1934, + 1861, 2458, 400, + 0, 2560, 0, + 0, 2668, 0, + 0, 2781, 0, + 0, 2899, 0, + 0, 3020, 0, + 0, 3144, 0, + 0, 3269, 0, + 0, 3396, 0, + 0, 3525, 0, + 0, 3654, 0, + 2878, 1917, 2660, + 2878, 1917, 2660, + 2878, 1919, 2660, + 2878, 1920, 2659, + 2877, 1922, 2659, + 2876, 1925, 2658, + 2875, 1928, 2657, + 2874, 1933, 2655, + 2872, 1939, 2653, + 2870, 1947, 2650, + 2867, 1958, 2646, + 2863, 1972, 2641, + 2858, 1989, 2635, + 2850, 2012, 2625, + 2840, 2041, 2613, + 2826, 2077, 2595, + 2807, 2121, 2570, + 2779, 2174, 2535, + 2740, 2236, 2483, + 2681, 2308, 2403, + 2589, 2389, 2268, + 2426, 2479, 1986, + 2035, 2577, 0, + 0, 2682, 0, + 0, 2792, 0, + 0, 2907, 0, + 0, 3026, 0, + 0, 3148, 0, + 0, 3273, 0, + 0, 3399, 0, + 0, 3527, 0, + 0, 3656, 0, + 3015, 2003, 2777, + 3015, 2004, 2777, + 3015, 2005, 2777, + 3015, 2006, 2776, + 3014, 2008, 2776, + 3014, 2010, 2775, + 3013, 2013, 2774, + 3012, 2017, 2773, + 3011, 2022, 2772, + 3009, 2029, 2770, + 3007, 2038, 2767, + 3004, 2049, 2763, + 3000, 2064, 2758, + 2995, 2084, 2751, + 2987, 2108, 2741, + 2977, 2140, 2728, + 2963, 2178, 2709, + 2944, 2225, 2684, + 2917, 2281, 2647, + 2878, 2347, 2593, + 2821, 2422, 2508, + 2730, 2506, 2363, + 2570, 2599, 2046, + 2196, 2699, 0, + 0, 2806, 0, + 0, 2918, 0, + 0, 3034, 0, + 0, 3155, 0, + 0, 3278, 0, + 0, 3403, 0, + 0, 3529, 0, + 0, 3658, 0, + 3151, 2098, 2898, + 3151, 2099, 2898, + 3151, 2099, 2897, + 3150, 2100, 2897, + 3150, 2102, 2897, + 3150, 2104, 2896, + 3149, 2106, 2896, + 3149, 2109, 2895, + 3148, 2113, 2893, + 3147, 2119, 2892, + 3145, 2126, 2890, + 3143, 2136, 2887, + 3140, 2148, 2883, + 3136, 2164, 2877, + 3130, 2185, 2870, + 3123, 2212, 2860, + 3113, 2245, 2847, + 3099, 2286, 2828, + 3080, 2335, 2801, + 3053, 2394, 2763, + 3015, 2462, 2707, + 2958, 2540, 2619, + 2868, 2626, 2466, + 2712, 2721, 2116, + 2349, 2823, 0, + 0, 2932, 0, + 0, 3045, 0, + 0, 3163, 0, + 0, 3284, 0, + 0, 3407, 0, + 0, 3533, 0, + 0, 3660, 0, + 3286, 2200, 3021, + 3286, 2201, 3021, + 3286, 2201, 3021, + 3285, 2202, 3021, + 3285, 2203, 3020, + 3285, 2205, 3020, + 3284, 2206, 3019, + 3284, 2209, 3019, + 3283, 2212, 3018, + 3282, 2217, 3016, + 3281, 2223, 3015, + 3280, 2231, 3013, + 3277, 2241, 3010, + 3274, 2254, 3006, + 3270, 2271, 3000, + 3265, 2293, 2993, + 3258, 2321, 2983, + 3248, 2356, 2969, + 3234, 2398, 2949, + 3215, 2450, 2922, + 3189, 2511, 2883, + 3151, 2581, 2825, + 3094, 2661, 2734, + 3005, 2749, 2574, + 2850, 2846, 2196, + 2495, 2950, 0, + 0, 3059, 0, + 0, 3174, 0, + 0, 3292, 0, + 0, 3414, 0, + 0, 3538, 0, + 0, 3664, 0, + 3420, 2309, 3146, + 3420, 2309, 3146, + 3420, 2309, 3146, + 3420, 2310, 3146, + 3419, 2311, 3146, + 3419, 2312, 3145, + 3419, 2313, 3145, + 3418, 2315, 3145, + 3418, 2318, 3144, + 3417, 2322, 3143, + 3416, 2326, 3142, + 3415, 2333, 3140, + 3414, 2341, 3138, + 3411, 2351, 3135, + 3408, 2365, 3131, + 3404, 2383, 3125, + 3399, 2406, 3117, + 3392, 2435, 3107, + 3382, 2471, 3093, + 3368, 2516, 3074, + 3350, 2569, 3046, + 3323, 2631, 3006, + 3285, 2703, 2947, + 3229, 2785, 2853, + 3141, 2875, 2688, + 2988, 2973, 2284, + 2638, 3077, 0, + 0, 3188, 0, + 0, 3303, 0, + 0, 3422, 0, + 0, 3544, 0, + 0, 3669, 0, + 3553, 2422, 3273, + 3553, 2422, 3273, + 3553, 2423, 3273, + 3553, 2423, 3273, + 3553, 2424, 3273, + 3553, 2425, 3273, + 3553, 2426, 3272, + 3552, 2427, 3272, + 3552, 2430, 3271, + 3552, 2432, 3271, + 3551, 2436, 3270, + 3550, 2441, 3269, + 3549, 2447, 3267, + 3547, 2456, 3265, + 3545, 2467, 3261, + 3542, 2481, 3257, + 3538, 2500, 3252, + 3533, 2524, 3244, + 3525, 2554, 3234, + 3516, 2591, 3219, + 3502, 2636, 3200, + 3483, 2690, 3172, + 3457, 2754, 3131, + 3419, 2828, 3071, + 3363, 2910, 2976, + 3275, 3002, 2805, + 3123, 3100, 2380, + 2778, 3206, 0, + 0, 3317, 0, + 0, 3433, 0, + 0, 3553, 0, + 0, 3675, 0, + 3687, 2540, 3402, + 3687, 2540, 3402, + 3686, 2540, 3401, + 3686, 2541, 3401, + 3686, 2541, 3401, + 3686, 2542, 3401, + 3686, 2543, 3401, + 3686, 2544, 3401, + 3686, 2545, 3400, + 3685, 2548, 3400, + 3685, 2550, 3399, + 3684, 2554, 3398, + 3683, 2559, 3397, + 3682, 2566, 3395, + 3680, 2575, 3393, + 3678, 2586, 3390, + 3675, 2601, 3385, + 3671, 2620, 3380, + 3666, 2644, 3372, + 3659, 2675, 3362, + 3649, 2713, 3347, + 3635, 2759, 3327, + 3617, 2815, 3299, + 3590, 2880, 3258, + 3553, 2954, 3197, + 3497, 3038, 3100, + 3410, 3130, 2926, + 3258, 3229, 2484, + 2916, 3336, 0, + 0, 3448, 0, + 0, 3564, 0, + 0, 3684, 0, + 3819, 2661, 3531, + 3819, 2661, 3531, + 3819, 2661, 3531, + 3819, 2661, 3531, + 3819, 2662, 3531, + 3819, 2662, 3530, + 3819, 2663, 3530, + 3819, 2664, 3530, + 3819, 2665, 3530, + 3818, 2667, 3529, + 3818, 2669, 3529, + 3818, 2672, 3528, + 3817, 2676, 3527, + 3816, 2681, 3526, + 3815, 2688, 3524, + 3813, 2697, 3522, + 3811, 2708, 3519, + 3808, 2723, 3514, + 3804, 2743, 3509, + 3799, 2768, 3501, + 3792, 2799, 3490, + 3782, 2838, 3476, + 3768, 2885, 3456, + 3750, 2941, 3427, + 3723, 3007, 3386, + 3686, 3082, 3325, + 3630, 3166, 3227, + 3543, 3259, 3050, + 3392, 3359, 2593, + 3052, 3466, 0, + 0, 3578, 0, + 0, 3695, 0, + 3952, 2784, 3661, + 3952, 2784, 3661, + 3952, 2785, 3661, + 3952, 2785, 3661, + 3952, 2785, 3661, + 3952, 2785, 3660, + 3952, 2786, 3660, + 3952, 2787, 3660, + 3952, 2788, 3660, + 3951, 2789, 3660, + 3951, 2791, 3659, + 3951, 2793, 3659, + 3950, 2796, 3658, + 3950, 2800, 3657, + 3949, 2805, 3656, + 3947, 2812, 3654, + 3946, 2821, 3652, + 3944, 2833, 3648, + 3941, 2848, 3644, + 3937, 2868, 3638, + 3932, 2893, 3631, + 3924, 2925, 3620, + 3915, 2964, 3605, + 3901, 3012, 3585, + 3882, 3068, 3556, + 3856, 3135, 3515, + 3819, 3211, 3453, + 3763, 3295, 3354, + 3676, 3389, 3176, + 3526, 3489, 2707, + 3188, 3597, 0, + 0, 3709, 0, + 4085, 2910, 3791, + 4085, 2910, 3791, + 4085, 2910, 3791, + 4085, 2910, 3791, + 4085, 2911, 3791, + 4085, 2911, 3791, + 4085, 2911, 3791, + 4084, 2912, 3791, + 4084, 2912, 3791, + 4084, 2913, 3790, + 4084, 2915, 3790, + 4084, 2916, 3790, + 4083, 2919, 3789, + 4083, 2922, 3788, + 4082, 2926, 3787, + 4081, 2931, 3786, + 4080, 2938, 3784, + 4078, 2947, 3782, + 4076, 2959, 3779, + 4073, 2975, 3775, + 4069, 2995, 3769, + 4064, 3020, 3761, + 4057, 3052, 3750, + 4047, 3092, 3736, + 4034, 3140, 3715, + 4015, 3197, 3686, + 3989, 3264, 3645, + 3951, 3340, 3583, + 3896, 3425, 3483, + 3809, 3519, 3303, + 3659, 3620, 2826, + 3322, 3728, 0, + 4095, 3037, 3922, + 4095, 3037, 3922, + 4095, 3037, 3922, + 4095, 3037, 3922, + 4095, 3038, 3922, + 4095, 3038, 3922, + 4095, 3038, 3922, + 4095, 3039, 3922, + 4095, 3039, 3922, + 4095, 3040, 3921, + 4095, 3041, 3921, + 4095, 3042, 3921, + 4095, 3044, 3920, + 4095, 3046, 3920, + 4095, 3049, 3919, + 4095, 3053, 3918, + 4095, 3059, 3917, + 4095, 3066, 3915, + 4095, 3075, 3913, + 4095, 3087, 3910, + 4095, 3103, 3905, + 4095, 3123, 3900, + 4095, 3149, 3892, + 4095, 3181, 3881, + 4095, 3221, 3866, + 4095, 3269, 3846, + 4095, 3327, 3817, + 4095, 3394, 3775, + 4084, 3470, 3713, + 4029, 3556, 3613, + 3942, 3650, 3432, + 3792, 3751, 2947, + 4095, 3166, 4053, + 4095, 3166, 4053, + 4095, 3166, 4053, + 4095, 3166, 4053, + 4095, 3166, 4053, + 4095, 3166, 4053, + 4095, 3166, 4053, + 4095, 3167, 4053, + 4095, 3167, 4053, + 4095, 3168, 4053, + 4095, 3168, 4053, + 4095, 3169, 4052, + 4095, 3171, 4052, + 4095, 3172, 4052, + 4095, 3175, 4051, + 4095, 3178, 4050, + 4095, 3182, 4049, + 4095, 3187, 4048, + 4095, 3194, 4046, + 4095, 3204, 4044, + 4095, 3216, 4041, + 4095, 3232, 4037, + 4095, 3252, 4031, + 4095, 3278, 4023, + 4095, 3310, 4012, + 4095, 3350, 3997, + 4095, 3399, 3977, + 4095, 3457, 3948, + 4095, 3524, 3906, + 4095, 3601, 3843, + 4095, 3687, 3743, + 4074, 3781, 3561, + 0, 1606, 1871, + 0, 1607, 1869, + 0, 1610, 1867, + 0, 1612, 1864, + 0, 1616, 1861, + 0, 1622, 1856, + 0, 1628, 1849, + 0, 1637, 1840, + 0, 1649, 1827, + 0, 1664, 1810, + 0, 1684, 1786, + 0, 1709, 1751, + 0, 1740, 1701, + 0, 1779, 1623, + 0, 1826, 1491, + 0, 1883, 1222, + 0, 1949, 0, + 0, 2024, 0, + 0, 2108, 0, + 0, 2201, 0, + 0, 2302, 0, + 0, 2409, 0, + 0, 2521, 0, + 0, 2638, 0, + 0, 2758, 0, + 0, 2881, 0, + 0, 3006, 0, + 0, 3133, 0, + 0, 3261, 0, + 0, 3390, 0, + 0, 3520, 0, + 0, 3651, 0, + 0, 1606, 1873, + 0, 1608, 1871, + 0, 1610, 1869, + 0, 1613, 1867, + 0, 1617, 1863, + 0, 1622, 1858, + 0, 1629, 1851, + 0, 1638, 1842, + 0, 1650, 1830, + 0, 1665, 1813, + 0, 1684, 1789, + 0, 1709, 1754, + 0, 1741, 1704, + 0, 1779, 1626, + 0, 1827, 1497, + 0, 1883, 1231, + 0, 1949, 0, + 0, 2024, 0, + 0, 2109, 0, + 0, 2202, 0, + 0, 2302, 0, + 0, 2409, 0, + 0, 2521, 0, + 0, 2638, 0, + 0, 2758, 0, + 0, 2881, 0, + 0, 3006, 0, + 0, 3133, 0, + 0, 3261, 0, + 0, 3390, 0, + 0, 3520, 0, + 0, 3651, 0, + 0, 1607, 1876, + 0, 1609, 1874, + 0, 1611, 1872, + 0, 1614, 1870, + 0, 1618, 1866, + 0, 1623, 1861, + 0, 1630, 1855, + 0, 1639, 1846, + 0, 1650, 1833, + 0, 1666, 1816, + 0, 1685, 1792, + 0, 1710, 1758, + 0, 1741, 1708, + 0, 1780, 1632, + 0, 1827, 1503, + 0, 1883, 1243, + 0, 1949, 0, + 0, 2024, 0, + 0, 2109, 0, + 0, 2202, 0, + 0, 2302, 0, + 0, 2409, 0, + 0, 2521, 0, + 0, 2638, 0, + 0, 2758, 0, + 0, 2881, 0, + 0, 3006, 0, + 0, 3133, 0, + 0, 3261, 0, + 0, 3390, 0, + 0, 3520, 0, + 0, 3651, 0, + 0, 1608, 1880, + 0, 1610, 1878, + 0, 1612, 1876, + 0, 1615, 1874, + 0, 1619, 1870, + 0, 1624, 1865, + 0, 1631, 1859, + 0, 1640, 1850, + 0, 1651, 1838, + 0, 1666, 1821, + 0, 1686, 1797, + 0, 1711, 1763, + 0, 1742, 1714, + 0, 1781, 1638, + 0, 1828, 1512, + 0, 1884, 1259, + 0, 1950, 0, + 0, 2025, 0, + 0, 2109, 0, + 0, 2202, 0, + 0, 2302, 0, + 0, 2409, 0, + 0, 2521, 0, + 0, 2638, 0, + 0, 2758, 0, + 0, 2881, 0, + 0, 3006, 0, + 0, 3133, 0, + 0, 3261, 0, + 0, 3390, 0, + 0, 3520, 0, + 0, 3651, 0, + 0, 1609, 1885, + 0, 1611, 1884, + 0, 1613, 1882, + 0, 1616, 1879, + 0, 1620, 1876, + 0, 1625, 1871, + 0, 1632, 1864, + 0, 1641, 1855, + 0, 1652, 1843, + 0, 1668, 1827, + 0, 1687, 1803, + 0, 1712, 1770, + 0, 1743, 1722, + 0, 1782, 1647, + 0, 1829, 1524, + 0, 1885, 1280, + 0, 1950, 0, + 0, 2025, 0, + 0, 2110, 0, + 0, 2202, 0, + 0, 2303, 0, + 0, 2409, 0, + 0, 2522, 0, + 0, 2638, 0, + 0, 2758, 0, + 0, 2881, 0, + 0, 3006, 0, + 0, 3133, 0, + 0, 3261, 0, + 0, 3390, 0, + 0, 3520, 0, + 0, 3651, 0, + 0, 1611, 1892, + 0, 1613, 1891, + 0, 1615, 1889, + 0, 1618, 1886, + 0, 1622, 1883, + 0, 1627, 1878, + 0, 1634, 1872, + 0, 1642, 1863, + 0, 1654, 1851, + 0, 1669, 1835, + 0, 1689, 1812, + 0, 1713, 1779, + 0, 1744, 1732, + 0, 1783, 1659, + 0, 1830, 1540, + 0, 1886, 1305, + 0, 1951, 254, + 0, 2026, 0, + 0, 2110, 0, + 0, 2203, 0, + 0, 2303, 0, + 0, 2410, 0, + 0, 2522, 0, + 0, 2638, 0, + 0, 2758, 0, + 0, 2881, 0, + 0, 3006, 0, + 0, 3133, 0, + 0, 3261, 0, + 0, 3390, 0, + 0, 3520, 0, + 0, 3651, 0, + 0, 1614, 1901, + 0, 1615, 1900, + 0, 1617, 1898, + 0, 1620, 1896, + 0, 1624, 1892, + 0, 1629, 1887, + 0, 1636, 1881, + 0, 1645, 1873, + 0, 1656, 1861, + 0, 1671, 1845, + 0, 1691, 1823, + 0, 1715, 1791, + 0, 1746, 1745, + 0, 1784, 1674, + 0, 1831, 1559, + 0, 1887, 1338, + 0, 1952, 508, + 0, 2027, 0, + 0, 2111, 0, + 0, 2203, 0, + 0, 2304, 0, + 0, 2410, 0, + 0, 2522, 0, + 0, 2639, 0, + 0, 2759, 0, + 0, 2881, 0, + 0, 3007, 0, + 0, 3133, 0, + 0, 3261, 0, + 0, 3390, 0, + 0, 3520, 0, + 0, 3651, 0, + 0, 1617, 1913, + 0, 1618, 1912, + 0, 1620, 1910, + 0, 1623, 1908, + 0, 1627, 1904, + 0, 1632, 1900, + 0, 1639, 1894, + 0, 1648, 1885, + 0, 1659, 1874, + 0, 1674, 1859, + 0, 1693, 1837, + 0, 1718, 1806, + 0, 1748, 1761, + 0, 1787, 1694, + 0, 1833, 1584, + 0, 1889, 1378, + 0, 1954, 713, + 0, 2028, 0, + 0, 2112, 0, + 0, 2204, 0, + 0, 2304, 0, + 0, 2411, 0, + 0, 2522, 0, + 0, 2639, 0, + 0, 2759, 0, + 0, 2882, 0, + 0, 3007, 0, + 0, 3133, 0, + 0, 3261, 0, + 0, 3391, 0, + 0, 3520, 0, + 0, 3651, 0, + 0, 1621, 1929, + 0, 1622, 1928, + 0, 1625, 1926, + 0, 1627, 1923, + 0, 1631, 1920, + 0, 1636, 1916, + 0, 1643, 1910, + 0, 1652, 1902, + 0, 1663, 1891, + 0, 1678, 1876, + 0, 1697, 1855, + 0, 1721, 1826, + 0, 1752, 1783, + 0, 1790, 1719, + 0, 1836, 1616, + 0, 1891, 1426, + 0, 1956, 894, + 0, 2030, 0, + 0, 2113, 0, + 0, 2206, 0, + 0, 2305, 0, + 0, 2411, 0, + 0, 2523, 0, + 0, 2639, 0, + 0, 2759, 0, + 0, 2882, 0, + 0, 3007, 0, + 0, 3134, 0, + 0, 3262, 0, + 0, 3391, 0, + 0, 3520, 0, + 0, 3651, 0, + 0, 1626, 1949, + 0, 1628, 1948, + 0, 1630, 1946, + 0, 1633, 1944, + 0, 1637, 1940, + 0, 1642, 1936, + 0, 1648, 1931, + 0, 1657, 1923, + 0, 1668, 1913, + 0, 1683, 1898, + 0, 1701, 1878, + 0, 1726, 1851, + 0, 1756, 1810, + 0, 1793, 1750, + 0, 1839, 1655, + 0, 1894, 1484, + 0, 1958, 1059, + 0, 2032, 0, + 0, 2115, 0, + 0, 2207, 0, + 0, 2306, 0, + 0, 2412, 0, + 0, 2524, 0, + 0, 2640, 0, + 0, 2760, 0, + 0, 2882, 0, + 0, 3007, 0, + 0, 3134, 0, + 0, 3262, 0, + 0, 3391, 0, + 0, 3520, 0, + 0, 3651, 0, + 0, 1634, 1974, + 0, 1635, 1973, + 0, 1637, 1971, + 0, 1640, 1969, + 0, 1644, 1966, + 0, 1649, 1962, + 0, 1655, 1957, + 0, 1664, 1950, + 0, 1675, 1940, + 0, 1689, 1927, + 0, 1708, 1908, + 0, 1731, 1882, + 0, 1761, 1844, + 0, 1798, 1789, + 0, 1844, 1702, + 0, 1898, 1552, + 0, 1962, 1214, + 0, 2035, 0, + 0, 2118, 0, + 0, 2209, 0, + 0, 2308, 0, + 0, 2414, 0, + 0, 2525, 0, + 0, 2641, 0, + 0, 2760, 0, + 0, 2883, 0, + 0, 3008, 0, + 0, 3134, 0, + 0, 3262, 0, + 0, 3391, 0, + 0, 3521, 0, + 0, 3651, 0, + 1107, 1643, 2006, + 1096, 1645, 2005, + 1081, 1647, 2003, + 1061, 1650, 2001, + 1031, 1653, 1999, + 989, 1658, 1995, + 926, 1664, 1990, + 824, 1673, 1983, + 639, 1684, 1974, + 132, 1698, 1962, + 0, 1716, 1945, + 0, 1739, 1921, + 0, 1769, 1886, + 0, 1805, 1836, + 0, 1850, 1758, + 0, 1904, 1628, + 0, 1967, 1363, + 0, 2039, 0, + 0, 2121, 0, + 0, 2212, 0, + 0, 2310, 0, + 0, 2415, 0, + 0, 2526, 0, + 0, 2642, 0, + 0, 2761, 0, + 0, 2883, 0, + 0, 3008, 0, + 0, 3134, 0, + 0, 3262, 0, + 0, 3391, 0, + 0, 3521, 0, + 0, 3651, 0, + 1479, 1656, 2045, + 1474, 1657, 2044, + 1468, 1659, 2043, + 1459, 1662, 2041, + 1447, 1666, 2039, + 1431, 1670, 2035, + 1408, 1676, 2031, + 1375, 1684, 2025, + 1327, 1695, 2016, + 1255, 1709, 2005, + 1135, 1727, 1989, + 899, 1749, 1968, + 0, 1778, 1937, + 0, 1814, 1892, + 0, 1858, 1824, + 0, 1911, 1714, + 0, 1973, 1507, + 0, 2045, 831, + 0, 2126, 0, + 0, 2215, 0, + 0, 2313, 0, + 0, 2418, 0, + 0, 2528, 0, + 0, 2643, 0, + 0, 2762, 0, + 0, 2884, 0, + 0, 3009, 0, + 0, 3135, 0, + 0, 3263, 0, + 0, 3391, 0, + 0, 3521, 0, + 0, 3651, 0, + 1732, 1672, 2093, + 1730, 1674, 2092, + 1726, 1676, 2091, + 1721, 1678, 2089, + 1715, 1681, 2087, + 1706, 1686, 2084, + 1693, 1692, 2080, + 1676, 1700, 2075, + 1652, 1710, 2067, + 1618, 1723, 2057, + 1568, 1741, 2043, + 1491, 1763, 2024, + 1362, 1791, 1997, + 1100, 1826, 1958, + 0, 1868, 1900, + 0, 1920, 1808, + 0, 1981, 1648, + 0, 2052, 1267, + 0, 2132, 0, + 0, 2220, 0, + 0, 2317, 0, + 0, 2421, 0, + 0, 2530, 0, + 0, 2645, 0, + 0, 2764, 0, + 0, 2885, 0, + 0, 3009, 0, + 0, 3136, 0, + 0, 3263, 0, + 0, 3392, 0, + 0, 3521, 0, + 0, 3651, 0, + 1938, 1693, 2150, + 1936, 1694, 2150, + 1934, 1696, 2148, + 1931, 1699, 2147, + 1927, 1702, 2145, + 1921, 1706, 2142, + 1913, 1712, 2139, + 1903, 1719, 2134, + 1889, 1729, 2127, + 1869, 1742, 2119, + 1840, 1759, 2106, + 1800, 1780, 2090, + 1739, 1807, 2066, + 1643, 1841, 2033, + 1470, 1882, 1984, + 1033, 1932, 1910, + 0, 1992, 1786, + 0, 2061, 1540, + 0, 2139, 54, + 0, 2227, 0, + 0, 2322, 0, + 0, 2425, 0, + 0, 2534, 0, + 0, 2648, 0, + 0, 2766, 0, + 0, 2887, 0, + 0, 3011, 0, + 0, 3136, 0, + 0, 3264, 0, + 0, 3392, 0, + 0, 3522, 0, + 0, 3652, 0, + 2118, 1720, 2217, + 2117, 1721, 2216, + 2116, 1723, 2215, + 2113, 1725, 2214, + 2111, 1728, 2212, + 2107, 1732, 2210, + 2102, 1737, 2207, + 2095, 1744, 2203, + 2086, 1754, 2197, + 2073, 1766, 2190, + 2055, 1782, 2179, + 2030, 1802, 2165, + 1994, 1828, 2145, + 1942, 1860, 2118, + 1861, 1900, 2077, + 1723, 1948, 2018, + 1431, 2006, 1923, + 0, 2073, 1755, + 0, 2149, 1339, + 0, 2235, 0, + 0, 2329, 0, + 0, 2430, 0, + 0, 2538, 0, + 0, 2651, 0, + 0, 2768, 0, + 0, 2889, 0, + 0, 3012, 0, + 0, 3138, 0, + 0, 3265, 0, + 0, 3393, 0, + 0, 3522, 0, + 0, 3652, 0, + 2283, 1753, 2293, + 2282, 1754, 2292, + 2281, 1756, 2292, + 2280, 1758, 2290, + 2278, 1761, 2289, + 2275, 1764, 2287, + 2272, 1769, 2285, + 2267, 1776, 2281, + 2261, 1785, 2276, + 2252, 1796, 2270, + 2240, 1811, 2261, + 2224, 1830, 2249, + 2201, 1854, 2233, + 2168, 1884, 2210, + 2121, 1922, 2178, + 2048, 1968, 2131, + 1928, 2024, 2059, + 1694, 2088, 1940, + 631, 2163, 1709, + 0, 2246, 718, + 0, 2338, 0, + 0, 2437, 0, + 0, 2544, 0, + 0, 2655, 0, + 0, 2772, 0, + 0, 2891, 0, + 0, 3014, 0, + 0, 3139, 0, + 0, 3266, 0, + 0, 3394, 0, + 0, 3523, 0, + 0, 3653, 0, + 2439, 1794, 2378, + 2438, 1795, 2378, + 2437, 1796, 2377, + 2436, 1798, 2376, + 2435, 1801, 2375, + 2433, 1804, 2373, + 2430, 1809, 2371, + 2427, 1815, 2368, + 2423, 1823, 2364, + 2417, 1833, 2359, + 2408, 1847, 2352, + 2397, 1864, 2342, + 2382, 1887, 2329, + 2360, 1915, 2311, + 2329, 1951, 2285, + 2285, 1994, 2248, + 2217, 2047, 2193, + 2108, 2108, 2108, + 1903, 2180, 1962, + 1252, 2260, 1639, + 0, 2350, 0, + 0, 2447, 0, + 0, 2551, 0, + 0, 2661, 0, + 0, 2776, 0, + 0, 2895, 0, + 0, 3017, 0, + 0, 3141, 0, + 0, 3267, 0, + 0, 3395, 0, + 0, 3524, 0, + 0, 3653, 0, + 2587, 1843, 2472, + 2587, 1844, 2471, + 2586, 1845, 2471, + 2585, 1847, 2470, + 2584, 1850, 2469, + 2583, 1853, 2468, + 2581, 1857, 2466, + 2579, 1862, 2464, + 2576, 1869, 2460, + 2571, 1879, 2456, + 2566, 1891, 2451, + 2558, 1907, 2443, + 2547, 1928, 2432, + 2532, 1954, 2418, + 2511, 1986, 2397, + 2482, 2027, 2369, + 2439, 2076, 2327, + 2375, 2134, 2266, + 2273, 2201, 2167, + 2086, 2279, 1990, + 1566, 2365, 1526, + 0, 2459, 0, + 0, 2561, 0, + 0, 2669, 0, + 0, 2782, 0, + 0, 2899, 0, + 0, 3020, 0, + 0, 3144, 0, + 0, 3269, 0, + 0, 3396, 0, + 0, 3525, 0, + 0, 3654, 0, + 2731, 1902, 2573, + 2731, 1903, 2572, + 2731, 1904, 2572, + 2730, 1906, 2571, + 2729, 1908, 2570, + 2728, 1910, 2569, + 2727, 1914, 2568, + 2725, 1919, 2566, + 2723, 1925, 2564, + 2720, 1933, 2560, + 2716, 1944, 2556, + 2710, 1959, 2550, + 2702, 1977, 2541, + 2692, 2000, 2530, + 2677, 2030, 2514, + 2657, 2067, 2492, + 2629, 2112, 2461, + 2588, 2166, 2416, + 2526, 2229, 2347, + 2428, 2302, 2236, + 2252, 2384, 2024, + 1798, 2475, 1309, + 0, 2574, 0, + 0, 2679, 0, + 0, 2790, 0, + 0, 2906, 0, + 0, 3025, 0, + 0, 3147, 0, + 0, 3272, 0, + 0, 3398, 0, + 0, 3526, 0, + 0, 3655, 0, + 2872, 1970, 2680, + 2872, 1971, 2680, + 2872, 1972, 2679, + 2871, 1973, 2679, + 2871, 1975, 2678, + 2870, 1977, 2677, + 2869, 1981, 2676, + 2868, 1985, 2675, + 2866, 1990, 2673, + 2864, 1998, 2670, + 2861, 2007, 2667, + 2857, 2019, 2662, + 2851, 2036, 2655, + 2843, 2056, 2646, + 2833, 2083, 2634, + 2819, 2115, 2618, + 2799, 2156, 2594, + 2771, 2205, 2561, + 2731, 2264, 2512, + 2672, 2332, 2437, + 2577, 2409, 2314, + 2409, 2495, 2066, + 1993, 2590, 532, + 0, 2692, 0, + 0, 2800, 0, + 0, 2914, 0, + 0, 3031, 0, + 0, 3152, 0, + 0, 3276, 0, + 0, 3401, 0, + 0, 3528, 0, + 0, 3657, 0, + 3011, 2048, 2793, + 3011, 2049, 2792, + 3010, 2050, 2792, + 3010, 2051, 2792, + 3010, 2052, 2791, + 3009, 2054, 2791, + 3008, 2057, 2790, + 3007, 2060, 2789, + 3006, 2065, 2787, + 3005, 2071, 2785, + 3002, 2079, 2782, + 2999, 2090, 2779, + 2995, 2104, 2774, + 2990, 2122, 2767, + 2982, 2144, 2757, + 2972, 2173, 2745, + 2958, 2209, 2727, + 2939, 2253, 2702, + 2911, 2306, 2667, + 2872, 2368, 2616, + 2813, 2440, 2536, + 2721, 2521, 2400, + 2558, 2611, 2118, + 2167, 2709, 0, + 0, 2814, 0, + 0, 2924, 0, + 0, 3039, 0, + 0, 3158, 0, + 0, 3280, 0, + 0, 3405, 0, + 0, 3531, 0, + 0, 3659, 0, + 3148, 2135, 2910, + 3147, 2135, 2909, + 3147, 2136, 2909, + 3147, 2137, 2909, + 3147, 2138, 2909, + 3146, 2140, 2908, + 3146, 2142, 2907, + 3145, 2145, 2907, + 3144, 2149, 2905, + 3143, 2154, 2904, + 3141, 2161, 2902, + 3139, 2170, 2899, + 3136, 2181, 2895, + 3132, 2196, 2890, + 3127, 2216, 2883, + 3119, 2241, 2873, + 3109, 2272, 2860, + 3095, 2310, 2842, + 3076, 2357, 2816, + 3049, 2413, 2779, + 3010, 2479, 2725, + 2953, 2554, 2640, + 2862, 2638, 2495, + 2703, 2731, 2178, + 2328, 2831, 0, + 0, 2938, 0, + 0, 3050, 0, + 0, 3167, 0, + 0, 3287, 0, + 0, 3410, 0, + 0, 3535, 0, + 0, 3662, 0, + 3283, 2230, 3030, + 3283, 2230, 3030, + 3283, 2231, 3030, + 3283, 2232, 3030, + 3283, 2233, 3029, + 3282, 2234, 3029, + 3282, 2236, 3028, + 3281, 2238, 3028, + 3281, 2241, 3027, + 3280, 2245, 3026, + 3279, 2251, 3024, + 3277, 2258, 3022, + 3275, 2268, 3019, + 3272, 2280, 3015, + 3268, 2297, 3010, + 3262, 2317, 3002, + 3255, 2344, 2992, + 3245, 2377, 2979, + 3231, 2418, 2960, + 3212, 2467, 2933, + 3186, 2526, 2896, + 3147, 2594, 2839, + 3090, 2672, 2751, + 3000, 2758, 2598, + 2844, 2853, 2248, + 2481, 2955, 0, + 0, 3064, 0, + 0, 3177, 0, + 0, 3295, 0, + 0, 3416, 0, + 0, 3540, 0, + 0, 3665, 0, + 3418, 2332, 3153, + 3418, 2332, 3153, + 3418, 2333, 3153, + 3418, 2333, 3153, + 3417, 2334, 3153, + 3417, 2335, 3152, + 3417, 2337, 3152, + 3417, 2339, 3151, + 3416, 2341, 3151, + 3415, 2344, 3150, + 3414, 2349, 3149, + 3413, 2355, 3147, + 3412, 2363, 3145, + 3409, 2373, 3142, + 3406, 2386, 3138, + 3403, 2403, 3132, + 3397, 2425, 3125, + 3390, 2453, 3115, + 3380, 2488, 3101, + 3366, 2531, 3082, + 3347, 2582, 3054, + 3321, 2643, 3016, + 3283, 2713, 2958, + 3226, 2793, 2866, + 3137, 2882, 2706, + 2983, 2978, 2328, + 2627, 3082, 0, + 0, 3191, 0, + 0, 3306, 0, + 0, 3424, 0, + 0, 3546, 0, + 0, 3670, 0, + 3552, 2440, 3279, + 3552, 2441, 3278, + 3552, 2441, 3278, + 3552, 2441, 3278, + 3552, 2442, 3278, + 3551, 2443, 3278, + 3551, 2444, 3278, + 3551, 2446, 3277, + 3551, 2448, 3277, + 3550, 2450, 3276, + 3549, 2454, 3275, + 3549, 2458, 3274, + 3547, 2465, 3272, + 3546, 2473, 3270, + 3543, 2484, 3267, + 3541, 2497, 3263, + 3537, 2515, 3257, + 3531, 2538, 3250, + 3524, 2567, 3239, + 3514, 2603, 3225, + 3500, 2648, 3206, + 3482, 2701, 3178, + 3455, 2763, 3138, + 3417, 2835, 3079, + 3361, 2917, 2986, + 3273, 3007, 2820, + 3120, 3105, 2416, + 2770, 3209, 0, + 0, 3320, 0, + 0, 3435, 0, + 0, 3554, 0, + 0, 3676, 0, + 3685, 2554, 3406, + 3685, 2554, 3405, + 3685, 2554, 3405, + 3685, 2555, 3405, + 3685, 2555, 3405, + 3685, 2556, 3405, + 3685, 2557, 3405, + 3685, 2558, 3405, + 3684, 2560, 3404, + 3684, 2562, 3404, + 3684, 2564, 3403, + 3683, 2568, 3402, + 3682, 2573, 3401, + 3681, 2579, 3399, + 3679, 2588, 3397, + 3677, 2599, 3394, + 3674, 2613, 3389, + 3670, 2632, 3384, + 3665, 2656, 3376, + 3658, 2686, 3366, + 3648, 2723, 3351, + 3634, 2768, 3332, + 3615, 2823, 3304, + 3589, 2886, 3263, + 3551, 2960, 3203, + 3495, 3042, 3108, + 3408, 3134, 2938, + 3255, 3233, 2512, + 2910, 3338, 0, + 0, 3449, 0, + 0, 3565, 0, + 0, 3685, 0, + 3819, 2672, 3534, + 3819, 2672, 3534, + 3819, 2672, 3534, + 3819, 2672, 3534, + 3818, 2673, 3533, + 3818, 2673, 3533, + 3818, 2674, 3533, + 3818, 2675, 3533, + 3818, 2676, 3533, + 3818, 2678, 3532, + 3817, 2680, 3532, + 3817, 2683, 3531, + 3816, 2686, 3530, + 3815, 2691, 3529, + 3814, 2698, 3527, + 3812, 2707, 3525, + 3810, 2718, 3522, + 3807, 2733, 3517, + 3803, 2752, 3512, + 3798, 2776, 3504, + 3791, 2807, 3494, + 3781, 2845, 3479, + 3767, 2891, 3459, + 3749, 2947, 3431, + 3722, 3012, 3390, + 3685, 3086, 3329, + 3629, 3170, 3232, + 3542, 3262, 3059, + 3390, 3362, 2616, + 3048, 3468, 0, + 0, 3580, 0, + 0, 3696, 0, + 3952, 2793, 3663, + 3952, 2793, 3663, + 3952, 2793, 3663, + 3951, 2793, 3663, + 3951, 2793, 3663, + 3951, 2794, 3663, + 3951, 2794, 3663, + 3951, 2795, 3662, + 3951, 2796, 3662, + 3951, 2797, 3662, + 3951, 2799, 3661, + 3950, 2801, 3661, + 3950, 2804, 3660, + 3949, 2808, 3659, + 3948, 2813, 3658, + 3947, 2820, 3656, + 3945, 2829, 3654, + 3943, 2840, 3651, + 3940, 2856, 3646, + 3936, 2875, 3641, + 3931, 2900, 3633, + 3924, 2931, 3622, + 3914, 2970, 3608, + 3900, 3017, 3588, + 3882, 3073, 3559, + 3856, 3139, 3518, + 3818, 3214, 3457, + 3762, 3298, 3359, + 3675, 3391, 3182, + 3524, 3491, 2725, + 3184, 3598, 0, + 0, 3710, 0, + 4084, 2916, 3793, + 4084, 2916, 3793, + 4084, 2916, 3793, + 4084, 2917, 3793, + 4084, 2917, 3793, + 4084, 2917, 3793, + 4084, 2918, 3793, + 4084, 2918, 3792, + 4084, 2919, 3792, + 4084, 2920, 3792, + 4083, 2921, 3792, + 4083, 2923, 3791, + 4083, 2925, 3791, + 4082, 2928, 3790, + 4082, 2932, 3789, + 4081, 2937, 3788, + 4080, 2944, 3786, + 4078, 2953, 3784, + 4076, 2965, 3781, + 4073, 2980, 3776, + 4069, 3000, 3771, + 4064, 3025, 3763, + 4056, 3057, 3752, + 4047, 3096, 3738, + 4033, 3144, 3717, + 4015, 3201, 3689, + 3988, 3267, 3647, + 3951, 3343, 3585, + 3895, 3428, 3486, + 3808, 3521, 3308, + 3658, 3622, 2839, + 3320, 3729, 0, + 4095, 3042, 3923, + 4095, 3042, 3923, + 4095, 3042, 3923, + 4095, 3042, 3923, + 4095, 3042, 3923, + 4095, 3043, 3923, + 4095, 3043, 3923, + 4095, 3043, 3923, + 4095, 3044, 3923, + 4095, 3045, 3923, + 4095, 3046, 3922, + 4095, 3047, 3922, + 4095, 3049, 3922, + 4095, 3051, 3921, + 4095, 3054, 3920, + 4095, 3058, 3919, + 4095, 3063, 3918, + 4095, 3070, 3916, + 4095, 3079, 3914, + 4095, 3091, 3911, + 4095, 3107, 3907, + 4095, 3127, 3901, + 4095, 3152, 3893, + 4095, 3184, 3882, + 4095, 3224, 3868, + 4095, 3272, 3847, + 4095, 3329, 3819, + 4095, 3396, 3777, + 4084, 3472, 3715, + 4028, 3558, 3615, + 3941, 3651, 3435, + 3791, 3752, 2958, + 4095, 3169, 4054, + 4095, 3169, 4054, + 4095, 3169, 4054, + 4095, 3169, 4054, + 4095, 3169, 4054, + 4095, 3170, 4054, + 4095, 3170, 4054, + 4095, 3170, 4054, + 4095, 3171, 4054, + 4095, 3171, 4054, + 4095, 3172, 4054, + 4095, 3173, 4053, + 4095, 3174, 4053, + 4095, 3176, 4053, + 4095, 3178, 4052, + 4095, 3181, 4051, + 4095, 3185, 4050, + 4095, 3191, 4049, + 4095, 3198, 4047, + 4095, 3207, 4045, + 4095, 3219, 4042, + 4095, 3235, 4037, + 4095, 3255, 4032, + 4095, 3281, 4024, + 4095, 3313, 4013, + 4095, 3353, 3998, + 4095, 3401, 3978, + 4095, 3459, 3949, + 4095, 3526, 3907, + 4095, 3602, 3845, + 4095, 3688, 3745, + 4074, 3782, 3564, + 0, 1736, 2002, + 0, 1737, 2001, + 0, 1739, 2000, + 0, 1741, 1998, + 0, 1744, 1995, + 0, 1748, 1991, + 0, 1753, 1986, + 0, 1760, 1979, + 0, 1769, 1970, + 0, 1781, 1958, + 0, 1796, 1940, + 0, 1816, 1916, + 0, 1841, 1881, + 0, 1872, 1830, + 0, 1911, 1752, + 0, 1958, 1620, + 0, 2015, 1347, + 0, 2080, 0, + 0, 2156, 0, + 0, 2240, 0, + 0, 2333, 0, + 0, 2434, 0, + 0, 2541, 0, + 0, 2653, 0, + 0, 2770, 0, + 0, 2890, 0, + 0, 3013, 0, + 0, 3138, 0, + 0, 3265, 0, + 0, 3393, 0, + 0, 3522, 0, + 0, 3652, 0, + 0, 1737, 2004, + 0, 1738, 2003, + 0, 1739, 2001, + 0, 1742, 1999, + 0, 1745, 1997, + 0, 1749, 1993, + 0, 1754, 1988, + 0, 1761, 1981, + 0, 1769, 1972, + 0, 1781, 1960, + 0, 1796, 1942, + 0, 1816, 1918, + 0, 1841, 1883, + 0, 1872, 1833, + 0, 1911, 1755, + 0, 1958, 1624, + 0, 2015, 1354, + 0, 2081, 0, + 0, 2156, 0, + 0, 2241, 0, + 0, 2333, 0, + 0, 2434, 0, + 0, 2541, 0, + 0, 2653, 0, + 0, 2770, 0, + 0, 2890, 0, + 0, 3013, 0, + 0, 3138, 0, + 0, 3265, 0, + 0, 3393, 0, + 0, 3522, 0, + 0, 3652, 0, + 0, 1737, 2006, + 0, 1738, 2005, + 0, 1740, 2004, + 0, 1742, 2002, + 0, 1745, 1999, + 0, 1749, 1995, + 0, 1754, 1990, + 0, 1761, 1984, + 0, 1770, 1974, + 0, 1782, 1962, + 0, 1797, 1945, + 0, 1817, 1921, + 0, 1841, 1886, + 0, 1873, 1836, + 0, 1912, 1759, + 0, 1959, 1629, + 0, 2015, 1363, + 0, 2081, 0, + 0, 2156, 0, + 0, 2241, 0, + 0, 2334, 0, + 0, 2434, 0, + 0, 2541, 0, + 0, 2653, 0, + 0, 2770, 0, + 0, 2890, 0, + 0, 3013, 0, + 0, 3138, 0, + 0, 3265, 0, + 0, 3393, 0, + 0, 3522, 0, + 0, 3652, 0, + 0, 1738, 2009, + 0, 1739, 2008, + 0, 1741, 2007, + 0, 1743, 2005, + 0, 1746, 2002, + 0, 1750, 1998, + 0, 1755, 1993, + 0, 1762, 1987, + 0, 1771, 1978, + 0, 1782, 1965, + 0, 1798, 1948, + 0, 1817, 1924, + 0, 1842, 1890, + 0, 1873, 1840, + 0, 1912, 1764, + 0, 1959, 1636, + 0, 2015, 1375, + 0, 2081, 0, + 0, 2157, 0, + 0, 2241, 0, + 0, 2334, 0, + 0, 2434, 0, + 0, 2541, 0, + 0, 2653, 0, + 0, 2770, 0, + 0, 2890, 0, + 0, 3013, 0, + 0, 3138, 0, + 0, 3265, 0, + 0, 3393, 0, + 0, 3522, 0, + 0, 3652, 0, + 0, 1739, 2013, + 0, 1740, 2012, + 0, 1742, 2011, + 0, 1744, 2009, + 0, 1747, 2006, + 0, 1751, 2002, + 0, 1756, 1997, + 0, 1763, 1991, + 0, 1772, 1982, + 0, 1783, 1970, + 0, 1798, 1953, + 0, 1818, 1929, + 0, 1843, 1895, + 0, 1874, 1846, + 0, 1913, 1771, + 0, 1960, 1645, + 0, 2016, 1391, + 0, 2082, 0, + 0, 2157, 0, + 0, 2241, 0, + 0, 2334, 0, + 0, 2434, 0, + 0, 2541, 0, + 0, 2653, 0, + 0, 2770, 0, + 0, 2890, 0, + 0, 3013, 0, + 0, 3138, 0, + 0, 3265, 0, + 0, 3393, 0, + 0, 3522, 0, + 0, 3652, 0, + 0, 1740, 2018, + 0, 1741, 2017, + 0, 1743, 2016, + 0, 1745, 2014, + 0, 1748, 2011, + 0, 1752, 2008, + 0, 1757, 2003, + 0, 1764, 1996, + 0, 1773, 1988, + 0, 1785, 1975, + 0, 1800, 1959, + 0, 1819, 1935, + 0, 1844, 1902, + 0, 1875, 1854, + 0, 1914, 1779, + 0, 1961, 1656, + 0, 2017, 1412, + 0, 2082, 13, + 0, 2157, 0, + 0, 2242, 0, + 0, 2334, 0, + 0, 2435, 0, + 0, 2541, 0, + 0, 2654, 0, + 0, 2770, 0, + 0, 2890, 0, + 0, 3013, 0, + 0, 3138, 0, + 0, 3265, 0, + 0, 3393, 0, + 0, 3522, 0, + 0, 3652, 0, + 0, 1742, 2025, + 0, 1743, 2024, + 0, 1745, 2023, + 0, 1747, 2021, + 0, 1750, 2018, + 0, 1754, 2015, + 0, 1759, 2010, + 0, 1766, 2004, + 0, 1775, 1995, + 0, 1786, 1983, + 0, 1801, 1967, + 0, 1821, 1944, + 0, 1845, 1911, + 0, 1876, 1864, + 0, 1915, 1791, + 0, 1962, 1672, + 0, 2018, 1438, + 0, 2083, 386, + 0, 2158, 0, + 0, 2242, 0, + 0, 2335, 0, + 0, 2435, 0, + 0, 2542, 0, + 0, 2654, 0, + 0, 2770, 0, + 0, 2890, 0, + 0, 3013, 0, + 0, 3139, 0, + 0, 3265, 0, + 0, 3393, 0, + 0, 3523, 0, + 0, 3652, 0, + 0, 1744, 2035, + 0, 1746, 2033, + 0, 1747, 2032, + 0, 1749, 2030, + 0, 1752, 2028, + 0, 1756, 2024, + 0, 1761, 2020, + 0, 1768, 2013, + 0, 1777, 2005, + 0, 1788, 1993, + 0, 1803, 1977, + 0, 1823, 1955, + 0, 1847, 1923, + 0, 1878, 1877, + 0, 1917, 1806, + 0, 1963, 1691, + 0, 2019, 1470, + 0, 2084, 640, + 0, 2159, 0, + 0, 2243, 0, + 0, 2336, 0, + 0, 2436, 0, + 0, 2542, 0, + 0, 2654, 0, + 0, 2771, 0, + 0, 2891, 0, + 0, 3014, 0, + 0, 3139, 0, + 0, 3265, 0, + 0, 3393, 0, + 0, 3523, 0, + 0, 3652, 0, + 0, 1748, 2046, + 0, 1749, 2045, + 0, 1750, 2044, + 0, 1753, 2042, + 0, 1755, 2040, + 0, 1759, 2036, + 0, 1764, 2032, + 0, 1771, 2026, + 0, 1780, 2018, + 0, 1791, 2006, + 0, 1806, 1991, + 0, 1825, 1969, + 0, 1850, 1938, + 0, 1881, 1893, + 0, 1919, 1826, + 0, 1965, 1716, + 0, 2021, 1510, + 0, 2086, 846, + 0, 2160, 0, + 0, 2244, 0, + 0, 2336, 0, + 0, 2436, 0, + 0, 2543, 0, + 0, 2655, 0, + 0, 2771, 0, + 0, 2891, 0, + 0, 3014, 0, + 0, 3139, 0, + 0, 3266, 0, + 0, 3394, 0, + 0, 3523, 0, + 0, 3652, 0, + 0, 1752, 2062, + 0, 1753, 2061, + 0, 1755, 2060, + 0, 1757, 2058, + 0, 1760, 2055, + 0, 1763, 2052, + 0, 1768, 2048, + 0, 1775, 2042, + 0, 1784, 2034, + 0, 1795, 2023, + 0, 1810, 2008, + 0, 1829, 1987, + 0, 1853, 1958, + 0, 1884, 1915, + 0, 1922, 1851, + 0, 1968, 1748, + 0, 2023, 1559, + 0, 2088, 1026, + 0, 2162, 0, + 0, 2246, 0, + 0, 2338, 0, + 0, 2437, 0, + 0, 2543, 0, + 0, 2655, 0, + 0, 2771, 0, + 0, 2891, 0, + 0, 3014, 0, + 0, 3139, 0, + 0, 3266, 0, + 0, 3394, 0, + 0, 3523, 0, + 0, 3652, 0, + 0, 1757, 2082, + 0, 1759, 2081, + 0, 1760, 2080, + 0, 1762, 2078, + 0, 1765, 2076, + 0, 1769, 2073, + 0, 1774, 2068, + 0, 1780, 2063, + 0, 1789, 2055, + 0, 1800, 2045, + 0, 1815, 2030, + 0, 1834, 2011, + 0, 1858, 1983, + 0, 1888, 1942, + 0, 1925, 1882, + 0, 1971, 1787, + 0, 2026, 1616, + 0, 2090, 1191, + 0, 2164, 0, + 0, 2247, 0, + 0, 2339, 0, + 0, 2438, 0, + 0, 2544, 0, + 0, 2656, 0, + 0, 2772, 0, + 0, 2892, 0, + 0, 3014, 0, + 0, 3139, 0, + 0, 3266, 0, + 0, 3394, 0, + 0, 3523, 0, + 0, 3653, 0, + 30, 1765, 2107, + 0, 1766, 2106, + 0, 1767, 2105, + 0, 1770, 2103, + 0, 1772, 2101, + 0, 1776, 2098, + 0, 1781, 2094, + 0, 1787, 2089, + 0, 1796, 2082, + 0, 1807, 2072, + 0, 1821, 2059, + 0, 1840, 2040, + 0, 1864, 2014, + 0, 1893, 1976, + 0, 1931, 1921, + 0, 1976, 1834, + 0, 2030, 1684, + 0, 2094, 1346, + 0, 2167, 0, + 0, 2250, 0, + 0, 2341, 0, + 0, 2440, 0, + 0, 2546, 0, + 0, 2657, 0, + 0, 2773, 0, + 0, 2892, 0, + 0, 3015, 0, + 0, 3140, 0, + 0, 3266, 0, + 0, 3394, 0, + 0, 3523, 0, + 0, 3653, 0, + 1247, 1774, 2139, + 1239, 1775, 2138, + 1228, 1777, 2137, + 1213, 1779, 2136, + 1193, 1782, 2133, + 1163, 1785, 2131, + 1121, 1790, 2127, + 1058, 1796, 2122, + 956, 1805, 2116, + 771, 1816, 2106, + 265, 1830, 2094, + 0, 1848, 2077, + 0, 1871, 2053, + 0, 1901, 2018, + 0, 1937, 1968, + 0, 1982, 1890, + 0, 2036, 1760, + 0, 2099, 1495, + 0, 2171, 0, + 0, 2253, 0, + 0, 2344, 0, + 0, 2442, 0, + 0, 2547, 0, + 0, 2658, 0, + 0, 2774, 0, + 0, 2893, 0, + 0, 3015, 0, + 0, 3140, 0, + 0, 3267, 0, + 0, 3394, 0, + 0, 3523, 0, + 0, 3653, 0, + 1614, 1787, 2178, + 1611, 1788, 2178, + 1606, 1790, 2177, + 1600, 1792, 2175, + 1591, 1794, 2173, + 1579, 1798, 2171, + 1563, 1802, 2167, + 1540, 1808, 2163, + 1507, 1817, 2157, + 1459, 1827, 2149, + 1387, 1841, 2137, + 1267, 1859, 2122, + 1031, 1881, 2100, + 0, 1910, 2069, + 0, 1946, 2024, + 0, 1990, 1956, + 0, 2043, 1846, + 0, 2105, 1639, + 0, 2177, 963, + 0, 2258, 0, + 0, 2348, 0, + 0, 2445, 0, + 0, 2550, 0, + 0, 2660, 0, + 0, 2775, 0, + 0, 2894, 0, + 0, 3016, 0, + 0, 3141, 0, + 0, 3267, 0, + 0, 3395, 0, + 0, 3523, 0, + 0, 3653, 0, + 1867, 1803, 2226, + 1865, 1804, 2225, + 1862, 1806, 2224, + 1858, 1808, 2223, + 1853, 1810, 2222, + 1847, 1814, 2219, + 1838, 1818, 2216, + 1825, 1824, 2212, + 1808, 1832, 2207, + 1784, 1842, 2199, + 1750, 1855, 2189, + 1700, 1873, 2175, + 1623, 1895, 2156, + 1494, 1923, 2129, + 1232, 1958, 2090, + 0, 2000, 2032, + 0, 2052, 1940, + 0, 2113, 1780, + 0, 2184, 1399, + 0, 2264, 0, + 0, 2352, 0, + 0, 2449, 0, + 0, 2553, 0, + 0, 2663, 0, + 0, 2777, 0, + 0, 2896, 0, + 0, 3017, 0, + 0, 3142, 0, + 0, 3268, 0, + 0, 3395, 0, + 0, 3524, 0, + 0, 3653, 0, + 2071, 1824, 2283, + 2070, 1825, 2282, + 2068, 1827, 2282, + 2066, 1828, 2281, + 2063, 1831, 2279, + 2059, 1834, 2277, + 2053, 1838, 2274, + 2046, 1844, 2271, + 2035, 1851, 2266, + 2021, 1861, 2260, + 2001, 1874, 2251, + 1973, 1891, 2239, + 1932, 1912, 2222, + 1871, 1939, 2198, + 1775, 1973, 2165, + 1602, 2014, 2117, + 1165, 2064, 2042, + 0, 2124, 1918, + 0, 2193, 1672, + 0, 2271, 186, + 0, 2359, 0, + 0, 2454, 0, + 0, 2557, 0, + 0, 2666, 0, + 0, 2780, 0, + 0, 2898, 0, + 0, 3019, 0, + 0, 3143, 0, + 0, 3268, 0, + 0, 3396, 0, + 0, 3524, 0, + 0, 3654, 0, + 2251, 1851, 2350, + 2250, 1852, 2349, + 2249, 1853, 2348, + 2248, 1855, 2347, + 2246, 1857, 2346, + 2243, 1860, 2344, + 2239, 1864, 2342, + 2234, 1869, 2339, + 2227, 1877, 2335, + 2218, 1886, 2329, + 2205, 1898, 2322, + 2187, 1914, 2311, + 2162, 1934, 2297, + 2127, 1960, 2277, + 2074, 1992, 2250, + 1993, 2032, 2210, + 1855, 2080, 2150, + 1563, 2138, 2055, + 0, 2205, 1887, + 0, 2281, 1471, + 0, 2367, 0, + 0, 2461, 0, + 0, 2562, 0, + 0, 2670, 0, + 0, 2783, 0, + 0, 2900, 0, + 0, 3021, 0, + 0, 3144, 0, + 0, 3270, 0, + 0, 3397, 0, + 0, 3525, 0, + 0, 3654, 0, + 2416, 1884, 2425, + 2415, 1885, 2425, + 2415, 1886, 2424, + 2413, 1888, 2424, + 2412, 1890, 2423, + 2410, 1893, 2421, + 2408, 1896, 2419, + 2404, 1901, 2417, + 2399, 1908, 2413, + 2393, 1917, 2408, + 2384, 1928, 2402, + 2372, 1943, 2393, + 2356, 1962, 2382, + 2333, 1986, 2365, + 2300, 2017, 2342, + 2253, 2054, 2310, + 2180, 2101, 2263, + 2060, 2156, 2191, + 1826, 2220, 2072, + 763, 2295, 1841, + 0, 2378, 850, + 0, 2470, 0, + 0, 2570, 0, + 0, 2676, 0, + 0, 2787, 0, + 0, 2904, 0, + 0, 3023, 0, + 0, 3146, 0, + 0, 3271, 0, + 0, 3398, 0, + 0, 3526, 0, + 0, 3655, 0, + 2571, 1925, 2511, + 2571, 1926, 2510, + 2570, 1927, 2510, + 2569, 1928, 2509, + 2568, 1930, 2508, + 2567, 1933, 2507, + 2565, 1936, 2505, + 2563, 1941, 2503, + 2559, 1947, 2500, + 2555, 1955, 2496, + 2549, 1965, 2491, + 2540, 1979, 2484, + 2529, 1997, 2474, + 2514, 2019, 2461, + 2492, 2048, 2443, + 2461, 2083, 2417, + 2417, 2126, 2380, + 2350, 2179, 2326, + 2240, 2240, 2240, + 2036, 2312, 2094, + 1384, 2392, 1771, + 0, 2482, 0, + 0, 2579, 0, + 0, 2683, 0, + 0, 2793, 0, + 0, 2908, 0, + 0, 3027, 0, + 0, 3149, 0, + 0, 3273, 0, + 0, 3399, 0, + 0, 3527, 0, + 0, 3656, 0, + 2720, 1975, 2604, + 2719, 1975, 2604, + 2719, 1976, 2603, + 2718, 1978, 2603, + 2718, 1979, 2602, + 2717, 1982, 2601, + 2715, 1985, 2600, + 2713, 1989, 2598, + 2711, 1994, 2596, + 2708, 2002, 2593, + 2704, 2011, 2588, + 2698, 2023, 2583, + 2690, 2039, 2575, + 2679, 2060, 2564, + 2664, 2086, 2550, + 2643, 2119, 2529, + 2614, 2159, 2501, + 2571, 2208, 2460, + 2508, 2266, 2398, + 2405, 2333, 2299, + 2218, 2411, 2122, + 1698, 2497, 1658, + 0, 2591, 0, + 0, 2693, 0, + 0, 2801, 0, + 0, 2914, 0, + 0, 3032, 0, + 0, 3152, 0, + 0, 3276, 0, + 0, 3401, 0, + 0, 3529, 0, + 0, 3657, 0, + 2864, 2033, 2705, + 2863, 2034, 2705, + 2863, 2035, 2704, + 2863, 2036, 2704, + 2862, 2038, 2703, + 2861, 2040, 2703, + 2860, 2042, 2702, + 2859, 2046, 2700, + 2857, 2051, 2698, + 2855, 2057, 2696, + 2852, 2066, 2692, + 2848, 2076, 2688, + 2842, 2091, 2682, + 2834, 2109, 2673, + 2824, 2133, 2662, + 2809, 2162, 2646, + 2789, 2199, 2624, + 2761, 2244, 2593, + 2720, 2298, 2548, + 2658, 2361, 2479, + 2560, 2434, 2368, + 2385, 2516, 2156, + 1930, 2607, 1441, + 0, 2706, 0, + 0, 2811, 0, + 0, 2922, 0, + 0, 3038, 0, + 0, 3157, 0, + 0, 3279, 0, + 0, 3404, 0, + 0, 3531, 0, + 0, 3658, 0, + 3004, 2102, 2812, + 3004, 2102, 2812, + 3004, 2103, 2812, + 3004, 2104, 2811, + 3003, 2105, 2811, + 3003, 2107, 2810, + 3002, 2110, 2810, + 3001, 2113, 2808, + 3000, 2117, 2807, + 2998, 2122, 2805, + 2996, 2130, 2802, + 2993, 2139, 2799, + 2989, 2152, 2794, + 2983, 2168, 2787, + 2976, 2188, 2779, + 2965, 2215, 2766, + 2951, 2248, 2750, + 2931, 2288, 2726, + 2903, 2337, 2693, + 2863, 2396, 2644, + 2804, 2464, 2570, + 2709, 2541, 2446, + 2541, 2628, 2199, + 2125, 2722, 664, + 0, 2824, 0, + 0, 2932, 0, + 0, 3046, 0, + 0, 3163, 0, + 0, 3284, 0, + 0, 3408, 0, + 0, 3533, 0, + 0, 3660, 0, + 3143, 2180, 2925, + 3143, 2180, 2925, + 3143, 2181, 2924, + 3142, 2182, 2924, + 3142, 2183, 2924, + 3142, 2184, 2923, + 3141, 2186, 2923, + 3141, 2189, 2922, + 3140, 2192, 2921, + 3138, 2197, 2919, + 3137, 2203, 2917, + 3134, 2211, 2914, + 3131, 2222, 2911, + 3127, 2236, 2906, + 3122, 2254, 2899, + 3114, 2276, 2890, + 3104, 2305, 2877, + 3090, 2341, 2859, + 3071, 2385, 2835, + 3043, 2438, 2799, + 3004, 2500, 2748, + 2945, 2572, 2668, + 2853, 2653, 2532, + 2690, 2743, 2250, + 2299, 2841, 0, + 0, 2946, 0, + 0, 3056, 0, + 0, 3171, 0, + 0, 3290, 0, + 0, 3412, 0, + 0, 3537, 0, + 0, 3663, 0, + 3280, 2267, 3042, + 3280, 2267, 3042, + 3280, 2267, 3041, + 3279, 2268, 3041, + 3279, 2269, 3041, + 3279, 2270, 3041, + 3278, 2272, 3040, + 3278, 2274, 3039, + 3277, 2277, 3039, + 3276, 2281, 3037, + 3275, 2286, 3036, + 3273, 2293, 3034, + 3271, 2302, 3031, + 3268, 2313, 3027, + 3264, 2328, 3022, + 3259, 2348, 3015, + 3251, 2373, 3005, + 3241, 2404, 2992, + 3227, 2442, 2974, + 3208, 2489, 2948, + 3181, 2545, 2911, + 3142, 2611, 2857, + 3085, 2686, 2773, + 2994, 2770, 2628, + 2835, 2863, 2310, + 2460, 2963, 0, + 0, 3070, 0, + 0, 3182, 0, + 0, 3299, 0, + 0, 3419, 0, + 0, 3542, 0, + 0, 3667, 0, + 3415, 2362, 3162, + 3415, 2362, 3162, + 3415, 2362, 3162, + 3415, 2363, 3162, + 3415, 2364, 3162, + 3415, 2365, 3161, + 3414, 2366, 3161, + 3414, 2368, 3160, + 3414, 2370, 3160, + 3413, 2373, 3159, + 3412, 2377, 3158, + 3411, 2383, 3156, + 3409, 2390, 3154, + 3407, 2400, 3151, + 3404, 2412, 3147, + 3400, 2429, 3142, + 3394, 2449, 3134, + 3387, 2476, 3124, + 3377, 2509, 3111, + 3363, 2550, 3092, + 3344, 2599, 3066, + 3318, 2658, 3028, + 3279, 2726, 2971, + 3222, 2804, 2883, + 3132, 2891, 2730, + 2976, 2985, 2380, + 2613, 3088, 0, + 0, 3196, 0, + 0, 3309, 0, + 0, 3427, 0, + 0, 3548, 0, + 0, 3672, 0, + 3550, 2464, 3285, + 3550, 2464, 3285, + 3550, 2464, 3285, + 3550, 2465, 3285, + 3550, 2465, 3285, + 3550, 2466, 3285, + 3549, 2467, 3284, + 3549, 2469, 3284, + 3549, 2471, 3284, + 3548, 2473, 3283, + 3548, 2477, 3282, + 3547, 2481, 3281, + 3545, 2487, 3279, + 3544, 2495, 3277, + 3542, 2505, 3274, + 3539, 2518, 3270, + 3535, 2535, 3264, + 3529, 2557, 3257, + 3522, 2585, 3247, + 3512, 2620, 3233, + 3498, 2663, 3214, + 3479, 2714, 3187, + 3453, 2775, 3148, + 3415, 2845, 3090, + 3358, 2925, 2999, + 3269, 3014, 2838, + 3115, 3110, 2460, + 2760, 3214, 0, + 0, 3323, 0, + 0, 3438, 0, + 0, 3556, 0, + 0, 3678, 0, + 3684, 2572, 3411, + 3684, 2572, 3411, + 3684, 2573, 3411, + 3684, 2573, 3410, + 3684, 2574, 3410, + 3684, 2574, 3410, + 3684, 2575, 3410, + 3683, 2576, 3410, + 3683, 2578, 3409, + 3683, 2580, 3409, + 3682, 2582, 3408, + 3682, 2586, 3407, + 3681, 2591, 3406, + 3679, 2597, 3404, + 3678, 2605, 3402, + 3676, 2616, 3399, + 3673, 2630, 3395, + 3669, 2647, 3389, + 3663, 2670, 3382, + 3656, 2699, 3371, + 3646, 2736, 3357, + 3633, 2780, 3338, + 3614, 2833, 3310, + 3587, 2895, 3270, + 3549, 2967, 3211, + 3493, 3049, 3118, + 3405, 3139, 2952, + 3252, 3237, 2548, + 2902, 3342, 0, + 0, 3452, 0, + 0, 3567, 0, + 0, 3686, 0, + 3818, 2686, 3538, + 3818, 2686, 3538, + 3818, 2686, 3538, + 3818, 2686, 3537, + 3817, 2687, 3537, + 3817, 2687, 3537, + 3817, 2688, 3537, + 3817, 2689, 3537, + 3817, 2690, 3537, + 3817, 2692, 3536, + 3816, 2694, 3536, + 3816, 2696, 3535, + 3815, 2700, 3534, + 3814, 2705, 3533, + 3813, 2711, 3531, + 3811, 2720, 3529, + 3809, 2731, 3526, + 3806, 2745, 3522, + 3802, 2764, 3516, + 3797, 2788, 3508, + 3790, 2818, 3498, + 3780, 2855, 3484, + 3766, 2900, 3464, + 3748, 2955, 3436, + 3721, 3018, 3395, + 3683, 3092, 3335, + 3627, 3174, 3240, + 3540, 3266, 3070, + 3387, 3365, 2644, + 3042, 3470, 0, + 0, 3582, 0, + 0, 3697, 0, + 3951, 2804, 3666, + 3951, 2804, 3666, + 3951, 2804, 3666, + 3951, 2804, 3666, + 3951, 2804, 3666, + 3951, 2805, 3666, + 3951, 2805, 3665, + 3950, 2806, 3665, + 3950, 2807, 3665, + 3950, 2808, 3665, + 3950, 2810, 3664, + 3949, 2812, 3664, + 3949, 2815, 3663, + 3948, 2818, 3662, + 3947, 2823, 3661, + 3946, 2830, 3659, + 3944, 2839, 3657, + 3942, 2850, 3654, + 3939, 2865, 3650, + 3935, 2884, 3644, + 3930, 2909, 3636, + 3923, 2939, 3626, + 3913, 2977, 3611, + 3900, 3024, 3591, + 3881, 3079, 3563, + 3855, 3144, 3522, + 3817, 3218, 3461, + 3761, 3302, 3364, + 3674, 3394, 3191, + 3522, 3494, 2748, + 3180, 3600, 0, + 0, 3712, 0, + 4084, 2925, 3795, + 4084, 2925, 3795, + 4084, 2925, 3795, + 4084, 2925, 3795, + 4084, 2925, 3795, + 4084, 2926, 3795, + 4083, 2926, 3795, + 4083, 2926, 3795, + 4083, 2927, 3794, + 4083, 2928, 3794, + 4083, 2929, 3794, + 4083, 2931, 3794, + 4082, 2933, 3793, + 4082, 2936, 3792, + 4081, 2940, 3791, + 4080, 2945, 3790, + 4079, 2952, 3788, + 4077, 2961, 3786, + 4075, 2972, 3783, + 4072, 2988, 3779, + 4068, 3007, 3773, + 4063, 3032, 3765, + 4056, 3063, 3755, + 4046, 3102, 3740, + 4033, 3149, 3720, + 4014, 3205, 3691, + 3988, 3271, 3650, + 3950, 3346, 3589, + 3894, 3430, 3491, + 3807, 3523, 3314, + 3656, 3623, 2857, + 3317, 3730, 0, + 4095, 3048, 3925, + 4095, 3048, 3925, + 4095, 3048, 3925, + 4095, 3049, 3925, + 4095, 3049, 3925, + 4095, 3049, 3925, + 4095, 3049, 3925, + 4095, 3050, 3925, + 4095, 3050, 3924, + 4095, 3051, 3924, + 4095, 3052, 3924, + 4095, 3053, 3924, + 4095, 3055, 3923, + 4095, 3057, 3923, + 4095, 3060, 3922, + 4095, 3064, 3921, + 4095, 3069, 3920, + 4095, 3076, 3918, + 4095, 3085, 3916, + 4095, 3097, 3913, + 4095, 3112, 3908, + 4095, 3132, 3903, + 4095, 3157, 3895, + 4095, 3189, 3884, + 4095, 3228, 3870, + 4095, 3276, 3849, + 4095, 3333, 3821, + 4095, 3399, 3779, + 4083, 3475, 3717, + 4027, 3560, 3619, + 3940, 3653, 3440, + 3790, 3754, 2972, + 4095, 3174, 4055, + 4095, 3174, 4055, + 4095, 3174, 4055, + 4095, 3174, 4055, + 4095, 3174, 4055, + 4095, 3174, 4055, + 4095, 3175, 4055, + 4095, 3175, 4055, + 4095, 3175, 4055, + 4095, 3176, 4055, + 4095, 3177, 4055, + 4095, 3178, 4055, + 4095, 3179, 4054, + 4095, 3181, 4054, + 4095, 3183, 4053, + 4095, 3186, 4053, + 4095, 3190, 4052, + 4095, 3195, 4050, + 4095, 3202, 4049, + 4095, 3211, 4046, + 4095, 3223, 4043, + 4095, 3239, 4039, + 4095, 3259, 4033, + 4095, 3285, 4025, + 4095, 3317, 4015, + 4095, 3356, 4000, + 4095, 3404, 3979, + 4095, 3461, 3951, + 4095, 3528, 3909, + 4095, 3604, 3847, + 4095, 3690, 3747, + 4073, 3783, 3567, + 0, 1867, 2134, + 0, 1868, 2133, + 0, 1869, 2132, + 0, 1871, 2130, + 0, 1873, 2128, + 0, 1876, 2126, + 0, 1880, 2122, + 0, 1885, 2117, + 0, 1892, 2110, + 0, 1901, 2101, + 0, 1913, 2088, + 0, 1928, 2071, + 0, 1948, 2047, + 0, 1973, 2012, + 0, 2004, 1961, + 0, 2043, 1882, + 0, 2090, 1749, + 0, 2146, 1473, + 0, 2212, 0, + 0, 2288, 0, + 0, 2372, 0, + 0, 2465, 0, + 0, 2566, 0, + 0, 2673, 0, + 0, 2785, 0, + 0, 2902, 0, + 0, 3022, 0, + 0, 3145, 0, + 0, 3270, 0, + 0, 3397, 0, + 0, 3525, 0, + 0, 3654, 0, + 0, 1867, 2135, + 0, 1868, 2134, + 0, 1869, 2133, + 0, 1871, 2132, + 0, 1873, 2130, + 0, 1876, 2127, + 0, 1880, 2123, + 0, 1885, 2118, + 0, 1892, 2112, + 0, 1901, 2102, + 0, 1913, 2090, + 0, 1928, 2072, + 0, 1948, 2048, + 0, 1973, 2013, + 0, 2004, 1962, + 0, 2043, 1884, + 0, 2090, 1752, + 0, 2147, 1479, + 0, 2213, 0, + 0, 2288, 0, + 0, 2372, 0, + 0, 2465, 0, + 0, 2566, 0, + 0, 2673, 0, + 0, 2785, 0, + 0, 2902, 0, + 0, 3022, 0, + 0, 3145, 0, + 0, 3270, 0, + 0, 3397, 0, + 0, 3525, 0, + 0, 3654, 0, + 0, 1868, 2137, + 0, 1869, 2136, + 0, 1870, 2135, + 0, 1872, 2133, + 0, 1874, 2131, + 0, 1877, 2129, + 0, 1881, 2125, + 0, 1886, 2120, + 0, 1893, 2113, + 0, 1902, 2104, + 0, 1913, 2092, + 0, 1929, 2074, + 0, 1948, 2050, + 0, 1973, 2016, + 0, 2004, 1965, + 0, 2043, 1887, + 0, 2091, 1756, + 0, 2147, 1486, + 0, 2213, 0, + 0, 2288, 0, + 0, 2373, 0, + 0, 2466, 0, + 0, 2566, 0, + 0, 2673, 0, + 0, 2785, 0, + 0, 2902, 0, + 0, 3022, 0, + 0, 3145, 0, + 0, 3270, 0, + 0, 3397, 0, + 0, 3525, 0, + 0, 3655, 0, + 0, 1868, 2139, + 0, 1869, 2138, + 0, 1870, 2137, + 0, 1872, 2136, + 0, 1874, 2134, + 0, 1877, 2131, + 0, 1881, 2127, + 0, 1886, 2122, + 0, 1893, 2116, + 0, 1902, 2107, + 0, 1914, 2094, + 0, 1929, 2077, + 0, 1949, 2053, + 0, 1974, 2019, + 0, 2005, 1968, + 0, 2044, 1891, + 0, 2091, 1761, + 0, 2147, 1495, + 0, 2213, 0, + 0, 2288, 0, + 0, 2373, 0, + 0, 2466, 0, + 0, 2566, 0, + 0, 2673, 0, + 0, 2785, 0, + 0, 2902, 0, + 0, 3022, 0, + 0, 3145, 0, + 0, 3270, 0, + 0, 3397, 0, + 0, 3525, 0, + 0, 3655, 0, + 0, 1869, 2142, + 0, 1870, 2141, + 0, 1871, 2140, + 0, 1873, 2139, + 0, 1875, 2137, + 0, 1878, 2134, + 0, 1882, 2130, + 0, 1887, 2125, + 0, 1894, 2119, + 0, 1903, 2110, + 0, 1915, 2097, + 0, 1930, 2080, + 0, 1949, 2056, + 0, 1974, 2022, + 0, 2005, 1973, + 0, 2044, 1896, + 0, 2091, 1768, + 0, 2148, 1508, + 0, 2213, 0, + 0, 2289, 0, + 0, 2373, 0, + 0, 2466, 0, + 0, 2566, 0, + 0, 2673, 0, + 0, 2785, 0, + 0, 2902, 0, + 0, 3022, 0, + 0, 3145, 0, + 0, 3270, 0, + 0, 3397, 0, + 0, 3525, 0, + 0, 3655, 0, + 0, 1870, 2146, + 0, 1871, 2145, + 0, 1872, 2144, + 0, 1874, 2143, + 0, 1876, 2141, + 0, 1879, 2138, + 0, 1883, 2134, + 0, 1888, 2130, + 0, 1895, 2123, + 0, 1904, 2114, + 0, 1915, 2102, + 0, 1931, 2085, + 0, 1950, 2061, + 0, 1975, 2028, + 0, 2006, 1978, + 0, 2045, 1903, + 0, 2092, 1777, + 0, 2148, 1523, + 0, 2214, 0, + 0, 2289, 0, + 0, 2373, 0, + 0, 2466, 0, + 0, 2567, 0, + 0, 2673, 0, + 0, 2786, 0, + 0, 2902, 0, + 0, 3022, 0, + 0, 3145, 0, + 0, 3270, 0, + 0, 3397, 0, + 0, 3525, 0, + 0, 3655, 0, + 0, 1871, 2151, + 0, 1872, 2151, + 0, 1874, 2149, + 0, 1875, 2148, + 0, 1877, 2146, + 0, 1880, 2143, + 0, 1884, 2140, + 0, 1889, 2135, + 0, 1896, 2129, + 0, 1905, 2120, + 0, 1917, 2108, + 0, 1932, 2091, + 0, 1951, 2068, + 0, 1976, 2034, + 0, 2007, 1986, + 0, 2046, 1912, + 0, 2093, 1788, + 0, 2149, 1544, + 0, 2214, 145, + 0, 2290, 0, + 0, 2374, 0, + 0, 2467, 0, + 0, 2567, 0, + 0, 2674, 0, + 0, 2786, 0, + 0, 2902, 0, + 0, 3022, 0, + 0, 3145, 0, + 0, 3271, 0, + 0, 3397, 0, + 0, 3525, 0, + 0, 3655, 0, + 0, 1873, 2158, + 0, 1874, 2157, + 0, 1875, 2156, + 0, 1877, 2155, + 0, 1879, 2153, + 0, 1882, 2150, + 0, 1886, 2147, + 0, 1891, 2142, + 0, 1898, 2136, + 0, 1907, 2127, + 0, 1918, 2115, + 0, 1933, 2099, + 0, 1953, 2076, + 0, 1977, 2043, + 0, 2009, 1996, + 0, 2047, 1923, + 0, 2094, 1804, + 0, 2150, 1570, + 0, 2215, 518, + 0, 2290, 0, + 0, 2374, 0, + 0, 2467, 0, + 0, 2567, 0, + 0, 2674, 0, + 0, 2786, 0, + 0, 2902, 0, + 0, 3023, 0, + 0, 3146, 0, + 0, 3271, 0, + 0, 3397, 0, + 0, 3526, 0, + 0, 3655, 0, + 0, 1876, 2167, + 0, 1876, 2167, + 0, 1878, 2166, + 0, 1879, 2164, + 0, 1882, 2162, + 0, 1884, 2160, + 0, 1888, 2156, + 0, 1893, 2152, + 0, 1900, 2145, + 0, 1909, 2137, + 0, 1920, 2125, + 0, 1935, 2109, + 0, 1955, 2087, + 0, 1979, 2055, + 0, 2010, 2009, + 0, 2049, 1938, + 0, 2095, 1823, + 0, 2151, 1602, + 0, 2216, 772, + 0, 2291, 0, + 0, 2375, 0, + 0, 2468, 0, + 0, 2568, 0, + 0, 2674, 0, + 0, 2786, 0, + 0, 2903, 0, + 0, 3023, 0, + 0, 3146, 0, + 0, 3271, 0, + 0, 3398, 0, + 0, 3526, 0, + 0, 3655, 0, + 0, 1879, 2179, + 0, 1880, 2179, + 0, 1881, 2178, + 0, 1883, 2176, + 0, 1885, 2174, + 0, 1888, 2172, + 0, 1891, 2168, + 0, 1896, 2164, + 0, 1903, 2158, + 0, 1912, 2150, + 0, 1923, 2138, + 0, 1938, 2123, + 0, 1957, 2101, + 0, 1982, 2070, + 0, 2013, 2026, + 0, 2051, 1958, + 0, 2097, 1848, + 0, 2153, 1642, + 0, 2218, 978, + 0, 2293, 0, + 0, 2376, 0, + 0, 2469, 0, + 0, 2568, 0, + 0, 2675, 0, + 0, 2787, 0, + 0, 2903, 0, + 0, 3023, 0, + 0, 3146, 0, + 0, 3271, 0, + 0, 3398, 0, + 0, 3526, 0, + 0, 3655, 0, + 0, 1883, 2195, + 0, 1884, 2194, + 0, 1885, 2193, + 0, 1887, 2192, + 0, 1889, 2190, + 0, 1892, 2188, + 0, 1895, 2184, + 0, 1900, 2180, + 0, 1907, 2174, + 0, 1916, 2166, + 0, 1927, 2155, + 0, 1942, 2140, + 0, 1961, 2119, + 0, 1985, 2090, + 0, 2016, 2047, + 0, 2054, 1983, + 0, 2100, 1880, + 0, 2155, 1691, + 0, 2220, 1158, + 0, 2294, 0, + 0, 2378, 0, + 0, 2470, 0, + 0, 2569, 0, + 0, 2676, 0, + 0, 2787, 0, + 0, 2904, 0, + 0, 3023, 0, + 0, 3146, 0, + 0, 3271, 0, + 0, 3398, 0, + 0, 3526, 0, + 0, 3655, 0, + 0, 1889, 2215, + 0, 1889, 2214, + 0, 1891, 2213, + 0, 1892, 2212, + 0, 1894, 2210, + 0, 1897, 2208, + 0, 1901, 2205, + 0, 1906, 2200, + 0, 1912, 2195, + 0, 1921, 2187, + 0, 1932, 2177, + 0, 1947, 2163, + 0, 1966, 2143, + 0, 1990, 2115, + 0, 2020, 2074, + 0, 2058, 2014, + 0, 2103, 1919, + 0, 2158, 1748, + 0, 2223, 1323, + 0, 2296, 0, + 0, 2380, 0, + 0, 2471, 0, + 0, 2571, 0, + 0, 2677, 0, + 0, 2788, 0, + 0, 2904, 0, + 0, 3024, 0, + 0, 3146, 0, + 0, 3271, 0, + 0, 3398, 0, + 0, 3526, 0, + 0, 3655, 0, + 241, 1896, 2240, + 162, 1897, 2239, + 31, 1898, 2238, + 0, 1900, 2237, + 0, 1902, 2236, + 0, 1904, 2233, + 0, 1908, 2230, + 0, 1913, 2227, + 0, 1919, 2221, + 0, 1928, 2214, + 0, 1939, 2204, + 0, 1953, 2191, + 0, 1972, 2172, + 0, 1996, 2146, + 0, 2026, 2108, + 0, 2063, 2053, + 0, 2108, 1966, + 0, 2162, 1816, + 0, 2226, 1478, + 0, 2299, 0, + 0, 2382, 0, + 0, 2473, 0, + 0, 2572, 0, + 0, 2678, 0, + 0, 2789, 0, + 0, 2905, 0, + 0, 3024, 0, + 0, 3147, 0, + 0, 3272, 0, + 0, 3398, 0, + 0, 3526, 0, + 0, 3655, 0, + 1385, 1906, 2272, + 1379, 1906, 2271, + 1371, 1908, 2270, + 1360, 1909, 2269, + 1345, 1911, 2268, + 1325, 1914, 2266, + 1296, 1917, 2263, + 1253, 1922, 2259, + 1190, 1929, 2254, + 1089, 1937, 2248, + 903, 1948, 2239, + 397, 1962, 2226, + 0, 1980, 2209, + 0, 2003, 2185, + 0, 2033, 2150, + 0, 2069, 2100, + 0, 2114, 2023, + 0, 2168, 1893, + 0, 2231, 1627, + 0, 2303, 0, + 0, 2385, 0, + 0, 2476, 0, + 0, 2574, 0, + 0, 2680, 0, + 0, 2790, 0, + 0, 2906, 0, + 0, 3025, 0, + 0, 3148, 0, + 0, 3272, 0, + 0, 3399, 0, + 0, 3526, 0, + 0, 3655, 0, + 1749, 1918, 2311, + 1747, 1919, 2310, + 1743, 1920, 2310, + 1738, 1922, 2309, + 1732, 1924, 2307, + 1723, 1926, 2305, + 1711, 1930, 2303, + 1695, 1934, 2300, + 1672, 1941, 2295, + 1639, 1949, 2289, + 1592, 1959, 2281, + 1519, 1973, 2269, + 1399, 1991, 2254, + 1164, 2014, 2232, + 83, 2042, 2201, + 0, 2078, 2156, + 0, 2122, 2088, + 0, 2175, 1978, + 0, 2237, 1771, + 0, 2309, 1096, + 0, 2390, 0, + 0, 2480, 0, + 0, 2577, 0, + 0, 2682, 0, + 0, 2792, 0, + 0, 2907, 0, + 0, 3026, 0, + 0, 3148, 0, + 0, 3273, 0, + 0, 3399, 0, + 0, 3527, 0, + 0, 3656, 0, + 2000, 1935, 2359, + 1999, 1935, 2358, + 1997, 1936, 2358, + 1994, 1938, 2357, + 1990, 1940, 2355, + 1985, 1942, 2354, + 1979, 1946, 2351, + 1970, 1950, 2348, + 1957, 1956, 2344, + 1940, 1964, 2339, + 1916, 1974, 2331, + 1882, 1988, 2321, + 1832, 2005, 2307, + 1755, 2027, 2288, + 1626, 2055, 2261, + 1364, 2090, 2222, + 0, 2133, 2164, + 0, 2184, 2073, + 0, 2245, 1912, + 0, 2316, 1531, + 0, 2396, 0, + 0, 2484, 0, + 0, 2581, 0, + 0, 2685, 0, + 0, 2795, 0, + 0, 2909, 0, + 0, 3028, 0, + 0, 3149, 0, + 0, 3274, 0, + 0, 3400, 0, + 0, 3527, 0, + 0, 3656, 0, + 2205, 1955, 2416, + 2204, 1956, 2415, + 2202, 1957, 2415, + 2201, 1959, 2414, + 2198, 1960, 2413, + 2195, 1963, 2411, + 2191, 1966, 2409, + 2185, 1970, 2407, + 2178, 1976, 2403, + 2167, 1984, 2398, + 2153, 1993, 2392, + 2133, 2006, 2383, + 2105, 2023, 2371, + 2064, 2044, 2354, + 2003, 2071, 2331, + 1907, 2105, 2297, + 1734, 2146, 2249, + 1297, 2196, 2174, + 0, 2256, 2050, + 0, 2325, 1804, + 0, 2403, 318, + 0, 2491, 0, + 0, 2586, 0, + 0, 2689, 0, + 0, 2798, 0, + 0, 2912, 0, + 0, 3030, 0, + 0, 3151, 0, + 0, 3275, 0, + 0, 3401, 0, + 0, 3528, 0, + 0, 3656, 0, + 2384, 1982, 2482, + 2383, 1983, 2482, + 2382, 1984, 2481, + 2381, 1985, 2480, + 2380, 1987, 2479, + 2378, 1989, 2478, + 2375, 1992, 2476, + 2371, 1996, 2474, + 2366, 2002, 2471, + 2359, 2009, 2467, + 2350, 2018, 2461, + 2337, 2030, 2454, + 2319, 2046, 2443, + 2294, 2066, 2429, + 2259, 2092, 2410, + 2206, 2124, 2382, + 2125, 2164, 2342, + 1987, 2212, 2282, + 1696, 2270, 2187, + 0, 2337, 2019, + 0, 2414, 1603, + 0, 2499, 0, + 0, 2593, 0, + 0, 2694, 0, + 0, 2802, 0, + 0, 2915, 0, + 0, 3032, 0, + 0, 3153, 0, + 0, 3276, 0, + 0, 3402, 0, + 0, 3529, 0, + 0, 3657, 0, + 2549, 2015, 2558, + 2548, 2016, 2558, + 2547, 2017, 2557, + 2547, 2018, 2557, + 2546, 2020, 2556, + 2544, 2022, 2555, + 2542, 2025, 2553, + 2540, 2029, 2551, + 2536, 2034, 2549, + 2531, 2040, 2545, + 2525, 2049, 2541, + 2516, 2060, 2534, + 2504, 2075, 2526, + 2488, 2094, 2514, + 2465, 2118, 2497, + 2432, 2149, 2475, + 2385, 2187, 2442, + 2312, 2233, 2395, + 2192, 2288, 2323, + 1958, 2352, 2204, + 895, 2427, 1973, + 0, 2510, 982, + 0, 2602, 0, + 0, 2702, 0, + 0, 2808, 0, + 0, 2919, 0, + 0, 3036, 0, + 0, 3156, 0, + 0, 3278, 0, + 0, 3403, 0, + 0, 3530, 0, + 0, 3658, 0, + 2703, 2056, 2643, + 2703, 2057, 2643, + 2703, 2058, 2642, + 2702, 2059, 2642, + 2701, 2060, 2641, + 2700, 2062, 2640, + 2699, 2065, 2639, + 2697, 2068, 2637, + 2695, 2073, 2635, + 2691, 2079, 2632, + 2687, 2087, 2629, + 2681, 2097, 2623, + 2673, 2111, 2616, + 2661, 2129, 2607, + 2646, 2151, 2593, + 2624, 2180, 2575, + 2593, 2215, 2549, + 2549, 2259, 2512, + 2482, 2311, 2458, + 2373, 2373, 2373, + 2168, 2444, 2226, + 1516, 2524, 1903, + 0, 2614, 0, + 0, 2711, 0, + 0, 2815, 0, + 0, 2925, 0, + 0, 3040, 0, + 0, 3159, 0, + 0, 3281, 0, + 0, 3405, 0, + 0, 3531, 0, + 0, 3659, 0, + 2852, 2106, 2736, + 2852, 2107, 2736, + 2851, 2107, 2736, + 2851, 2108, 2735, + 2850, 2110, 2735, + 2850, 2111, 2734, + 2849, 2114, 2733, + 2847, 2117, 2732, + 2846, 2121, 2730, + 2843, 2126, 2728, + 2840, 2134, 2725, + 2836, 2143, 2720, + 2830, 2155, 2715, + 2822, 2171, 2707, + 2811, 2192, 2696, + 2796, 2218, 2682, + 2775, 2251, 2662, + 2746, 2291, 2633, + 2703, 2340, 2592, + 2640, 2398, 2530, + 2537, 2466, 2431, + 2350, 2543, 2254, + 1830, 2629, 1790, + 0, 2723, 0, + 0, 2825, 0, + 0, 2933, 0, + 0, 3046, 0, + 0, 3164, 0, + 0, 3284, 0, + 0, 3408, 0, + 0, 3533, 0, + 0, 3661, 0, + 2996, 2165, 2837, + 2996, 2165, 2837, + 2995, 2166, 2837, + 2995, 2167, 2836, + 2995, 2168, 2836, + 2994, 2170, 2835, + 2994, 2172, 2835, + 2993, 2174, 2834, + 2991, 2178, 2832, + 2990, 2183, 2830, + 2987, 2189, 2828, + 2984, 2198, 2825, + 2980, 2209, 2820, + 2974, 2223, 2814, + 2966, 2241, 2805, + 2956, 2265, 2794, + 2941, 2294, 2778, + 2921, 2331, 2756, + 2893, 2376, 2725, + 2852, 2430, 2680, + 2790, 2493, 2611, + 2693, 2566, 2500, + 2517, 2648, 2288, + 2062, 2739, 1573, + 0, 2838, 0, + 0, 2943, 0, + 0, 3054, 0, + 0, 3170, 0, + 0, 3289, 0, + 0, 3412, 0, + 0, 3536, 0, + 0, 3663, 0, + 3137, 2233, 2944, + 3136, 2234, 2944, + 3136, 2234, 2944, + 3136, 2235, 2944, + 3136, 2236, 2944, + 3135, 2238, 2943, + 3135, 2239, 2942, + 3134, 2242, 2942, + 3133, 2245, 2941, + 3132, 2249, 2939, + 3130, 2254, 2937, + 3128, 2262, 2934, + 3125, 2271, 2931, + 3121, 2284, 2926, + 3115, 2300, 2920, + 3108, 2320, 2911, + 3097, 2347, 2899, + 3083, 2380, 2882, + 3063, 2420, 2858, + 3036, 2469, 2825, + 2996, 2528, 2776, + 2936, 2596, 2702, + 2841, 2673, 2578, + 2673, 2760, 2331, + 2257, 2854, 796, + 0, 2956, 0, + 0, 3064, 0, + 0, 3178, 0, + 0, 3295, 0, + 0, 3416, 0, + 0, 3540, 0, + 0, 3665, 0, + 3275, 2311, 3057, + 3275, 2312, 3057, + 3275, 2312, 3057, + 3275, 2313, 3057, + 3275, 2314, 3056, + 3274, 2315, 3056, + 3274, 2316, 3055, + 3273, 2318, 3055, + 3273, 2321, 3054, + 3272, 2324, 3053, + 3270, 2329, 3051, + 3269, 2335, 3049, + 3267, 2343, 3046, + 3263, 2354, 3043, + 3259, 2368, 3038, + 3254, 2386, 3031, + 3246, 2409, 3022, + 3236, 2437, 3009, + 3222, 2473, 2991, + 3203, 2517, 2967, + 3175, 2570, 2931, + 3136, 2633, 2880, + 3078, 2704, 2800, + 2985, 2786, 2665, + 2822, 2875, 2382, + 2431, 2973, 0, + 0, 3078, 0, + 0, 3188, 0, + 0, 3303, 0, + 0, 3422, 0, + 0, 3545, 0, + 0, 3669, 0, + 3412, 2398, 3174, + 3412, 2399, 3174, + 3412, 2399, 3174, + 3412, 2400, 3174, + 3411, 2400, 3173, + 3411, 2401, 3173, + 3411, 2402, 3173, + 3411, 2404, 3172, + 3410, 2406, 3172, + 3409, 2409, 3171, + 3408, 2413, 3170, + 3407, 2418, 3168, + 3406, 2425, 3166, + 3403, 2434, 3163, + 3400, 2445, 3159, + 3396, 2461, 3154, + 3391, 2480, 3147, + 3383, 2505, 3137, + 3373, 2536, 3124, + 3360, 2574, 3106, + 3340, 2621, 3080, + 3313, 2677, 3043, + 3275, 2743, 2989, + 3217, 2818, 2905, + 3126, 2902, 2760, + 2967, 2995, 2442, + 2592, 3095, 0, + 0, 3202, 0, + 0, 3314, 0, + 0, 3431, 0, + 0, 3551, 0, + 0, 3674, 0, + 3547, 2493, 3294, + 3547, 2494, 3294, + 3547, 2494, 3294, + 3547, 2494, 3294, + 3547, 2495, 3294, + 3547, 2496, 3294, + 3547, 2497, 3293, + 3547, 2498, 3293, + 3546, 2500, 3293, + 3546, 2502, 3292, + 3545, 2505, 3291, + 3544, 2510, 3290, + 3543, 2515, 3288, + 3541, 2522, 3286, + 3539, 2532, 3283, + 3536, 2545, 3279, + 3532, 2561, 3274, + 3527, 2582, 3266, + 3519, 2608, 3257, + 3509, 2641, 3243, + 3496, 2682, 3224, + 3476, 2731, 3198, + 3450, 2790, 3160, + 3411, 2858, 3103, + 3354, 2936, 3015, + 3265, 3023, 2862, + 3108, 3118, 2512, + 2745, 3220, 0, + 0, 3328, 0, + 0, 3442, 0, + 0, 3559, 0, + 0, 3680, 0, + 3682, 2596, 3418, + 3682, 2596, 3417, + 3682, 2596, 3417, + 3682, 2597, 3417, + 3682, 2597, 3417, + 3682, 2598, 3417, + 3682, 2598, 3417, + 3681, 2599, 3417, + 3681, 2601, 3416, + 3681, 2603, 3416, + 3680, 2605, 3415, + 3680, 2609, 3414, + 3679, 2613, 3413, + 3677, 2619, 3411, + 3676, 2627, 3409, + 3674, 2637, 3406, + 3671, 2650, 3402, + 3667, 2667, 3396, + 3661, 2689, 3389, + 3654, 2717, 3379, + 3644, 2752, 3365, + 3630, 2795, 3346, + 3612, 2846, 3319, + 3585, 2907, 3280, + 3547, 2977, 3222, + 3490, 3057, 3131, + 3401, 3146, 2970, + 3247, 3242, 2592, + 2892, 3346, 0, + 0, 3456, 0, + 0, 3570, 0, + 0, 3689, 0, + 3816, 2704, 3543, + 3816, 2704, 3543, + 3816, 2705, 3543, + 3816, 2705, 3543, + 3816, 2705, 3543, + 3816, 2706, 3542, + 3816, 2706, 3542, + 3816, 2707, 3542, + 3815, 2708, 3542, + 3815, 2710, 3541, + 3815, 2712, 3541, + 3814, 2714, 3540, + 3814, 2718, 3539, + 3813, 2723, 3538, + 3811, 2729, 3536, + 3810, 2737, 3534, + 3808, 2748, 3531, + 3805, 2762, 3527, + 3801, 2780, 3521, + 3795, 2803, 3514, + 3788, 2832, 3504, + 3778, 2868, 3489, + 3765, 2912, 3470, + 3746, 2965, 3442, + 3719, 3027, 3403, + 3681, 3099, 3343, + 3625, 3181, 3250, + 3537, 3271, 3084, + 3384, 3369, 2680, + 3034, 3474, 0, + 0, 3584, 0, + 0, 3699, 0, + 3950, 2818, 3670, + 3950, 2818, 3670, + 3950, 2818, 3670, + 3950, 2818, 3670, + 3950, 2819, 3670, + 3950, 2819, 3669, + 3949, 2819, 3669, + 3949, 2820, 3669, + 3949, 2821, 3669, + 3949, 2822, 3669, + 3949, 2824, 3668, + 3948, 2826, 3668, + 3948, 2829, 3667, + 3947, 2832, 3666, + 3946, 2837, 3665, + 3945, 2844, 3663, + 3943, 2852, 3661, + 3941, 2863, 3658, + 3938, 2878, 3654, + 3934, 2896, 3648, + 3929, 2920, 3640, + 3922, 2950, 3630, + 3912, 2987, 3616, + 3898, 3032, 3596, + 3880, 3087, 3568, + 3853, 3151, 3528, + 3815, 3224, 3467, + 3759, 3307, 3372, + 3672, 3398, 3202, + 3520, 3497, 2776, + 3174, 3602, 0, + 0, 3714, 0, + 4083, 2936, 3798, + 4083, 2936, 3798, + 4083, 2936, 3798, + 4083, 2936, 3798, + 4083, 2936, 3798, + 4083, 2936, 3798, + 4083, 2937, 3798, + 4083, 2937, 3798, + 4082, 2938, 3797, + 4082, 2939, 3797, + 4082, 2940, 3797, + 4082, 2942, 3796, + 4081, 2944, 3796, + 4081, 2947, 3795, + 4080, 2951, 3794, + 4079, 2956, 3793, + 4078, 2962, 3791, + 4077, 2971, 3789, + 4074, 2982, 3786, + 4071, 2997, 3782, + 4068, 3016, 3776, + 4062, 3041, 3768, + 4055, 3071, 3758, + 4045, 3109, 3743, + 4032, 3156, 3723, + 4013, 3211, 3695, + 3987, 3276, 3654, + 3949, 3350, 3593, + 3893, 3434, 3496, + 3806, 3526, 3323, + 3654, 3626, 2880, + 3312, 3732, 0, + 4095, 3057, 3927, + 4095, 3057, 3927, + 4095, 3057, 3927, + 4095, 3057, 3927, + 4095, 3057, 3927, + 4095, 3057, 3927, + 4095, 3058, 3927, + 4095, 3058, 3927, + 4095, 3059, 3927, + 4095, 3059, 3927, + 4095, 3060, 3926, + 4095, 3061, 3926, + 4095, 3063, 3926, + 4095, 3065, 3925, + 4095, 3068, 3924, + 4095, 3072, 3923, + 4095, 3077, 3922, + 4095, 3084, 3920, + 4095, 3093, 3918, + 4095, 3105, 3915, + 4095, 3120, 3911, + 4095, 3139, 3905, + 4095, 3164, 3897, + 4095, 3195, 3887, + 4095, 3234, 3872, + 4095, 3281, 3852, + 4095, 3337, 3823, + 4095, 3403, 3782, + 4082, 3478, 3721, + 4026, 3562, 3623, + 3939, 3655, 3446, + 3788, 3755, 2989, + 4095, 3180, 4057, + 4095, 3180, 4057, + 4095, 3180, 4057, + 4095, 3181, 4057, + 4095, 3181, 4057, + 4095, 3181, 4057, + 4095, 3181, 4057, + 4095, 3181, 4057, + 4095, 3182, 4057, + 4095, 3182, 4057, + 4095, 3183, 4056, + 4095, 3184, 4056, + 4095, 3185, 4056, + 4095, 3187, 4055, + 4095, 3189, 4055, + 4095, 3192, 4054, + 4095, 3196, 4053, + 4095, 3201, 4052, + 4095, 3208, 4050, + 4095, 3217, 4048, + 4095, 3229, 4045, + 4095, 3245, 4040, + 4095, 3264, 4035, + 4095, 3290, 4027, + 4095, 3321, 4016, + 4095, 3360, 4002, + 4095, 3408, 3981, + 4095, 3465, 3953, + 4095, 3531, 3911, + 4095, 3607, 3849, + 4095, 3692, 3751, + 4073, 3785, 3572, + 0, 1998, 2266, + 0, 1999, 2265, + 0, 2000, 2264, + 0, 2001, 2263, + 0, 2003, 2262, + 0, 2005, 2260, + 0, 2008, 2257, + 0, 2012, 2253, + 0, 2017, 2248, + 0, 2024, 2241, + 0, 2033, 2232, + 0, 2045, 2219, + 0, 2060, 2202, + 0, 2079, 2177, + 0, 2104, 2143, + 0, 2136, 2091, + 0, 2175, 2012, + 0, 2222, 1879, + 0, 2278, 1601, + 0, 2344, 0, + 0, 2420, 0, + 0, 2504, 0, + 0, 2597, 0, + 0, 2698, 0, + 0, 2805, 0, + 0, 2917, 0, + 0, 3034, 0, + 0, 3154, 0, + 0, 3277, 0, + 0, 3402, 0, + 0, 3529, 0, + 0, 3657, 0, + 0, 1998, 2267, + 0, 1999, 2266, + 0, 2000, 2265, + 0, 2001, 2264, + 0, 2003, 2263, + 0, 2005, 2260, + 0, 2008, 2258, + 0, 2012, 2254, + 0, 2017, 2249, + 0, 2024, 2242, + 0, 2033, 2233, + 0, 2045, 2220, + 0, 2060, 2203, + 0, 2080, 2179, + 0, 2105, 2144, + 0, 2136, 2093, + 0, 2175, 2014, + 0, 2222, 1881, + 0, 2279, 1606, + 0, 2344, 0, + 0, 2420, 0, + 0, 2504, 0, + 0, 2597, 0, + 0, 2698, 0, + 0, 2805, 0, + 0, 2917, 0, + 0, 3034, 0, + 0, 3154, 0, + 0, 3277, 0, + 0, 3402, 0, + 0, 3529, 0, + 0, 3657, 0, + 0, 1999, 2268, + 0, 1999, 2267, + 0, 2000, 2266, + 0, 2002, 2265, + 0, 2003, 2264, + 0, 2005, 2262, + 0, 2008, 2259, + 0, 2012, 2255, + 0, 2017, 2250, + 0, 2024, 2244, + 0, 2033, 2234, + 0, 2045, 2222, + 0, 2060, 2204, + 0, 2080, 2180, + 0, 2105, 2145, + 0, 2136, 2095, + 0, 2175, 2016, + 0, 2222, 1884, + 0, 2279, 1611, + 0, 2345, 0, + 0, 2420, 0, + 0, 2505, 0, + 0, 2598, 0, + 0, 2698, 0, + 0, 2805, 0, + 0, 2917, 0, + 0, 3034, 0, + 0, 3154, 0, + 0, 3277, 0, + 0, 3402, 0, + 0, 3529, 0, + 0, 3657, 0, + 0, 1999, 2270, + 0, 2000, 2269, + 0, 2001, 2268, + 0, 2002, 2267, + 0, 2004, 2265, + 0, 2006, 2263, + 0, 2009, 2261, + 0, 2013, 2257, + 0, 2018, 2252, + 0, 2025, 2245, + 0, 2034, 2236, + 0, 2045, 2224, + 0, 2061, 2206, + 0, 2080, 2182, + 0, 2105, 2148, + 0, 2137, 2097, + 0, 2175, 2019, + 0, 2223, 1888, + 0, 2279, 1618, + 0, 2345, 0, + 0, 2420, 0, + 0, 2505, 0, + 0, 2598, 0, + 0, 2698, 0, + 0, 2805, 0, + 0, 2917, 0, + 0, 3034, 0, + 0, 3154, 0, + 0, 3277, 0, + 0, 3402, 0, + 0, 3529, 0, + 0, 3657, 0, + 0, 2000, 2272, + 0, 2000, 2271, + 0, 2001, 2270, + 0, 2003, 2269, + 0, 2004, 2268, + 0, 2006, 2266, + 0, 2009, 2263, + 0, 2013, 2259, + 0, 2018, 2254, + 0, 2025, 2248, + 0, 2034, 2239, + 0, 2046, 2226, + 0, 2061, 2209, + 0, 2081, 2185, + 0, 2106, 2151, + 0, 2137, 2100, + 0, 2176, 2023, + 0, 2223, 1893, + 0, 2279, 1627, + 0, 2345, 0, + 0, 2420, 0, + 0, 2505, 0, + 0, 2598, 0, + 0, 2698, 0, + 0, 2805, 0, + 0, 2917, 0, + 0, 3034, 0, + 0, 3154, 0, + 0, 3277, 0, + 0, 3402, 0, + 0, 3529, 0, + 0, 3657, 0, + 0, 2000, 2275, + 0, 2001, 2274, + 0, 2002, 2273, + 0, 2003, 2272, + 0, 2005, 2271, + 0, 2007, 2269, + 0, 2010, 2266, + 0, 2014, 2262, + 0, 2019, 2258, + 0, 2026, 2251, + 0, 2035, 2242, + 0, 2047, 2230, + 0, 2062, 2212, + 0, 2081, 2189, + 0, 2106, 2155, + 0, 2138, 2105, + 0, 2176, 2028, + 0, 2223, 1900, + 0, 2280, 1640, + 0, 2345, 0, + 0, 2421, 0, + 0, 2505, 0, + 0, 2598, 0, + 0, 2698, 0, + 0, 2805, 0, + 0, 2917, 0, + 0, 3034, 0, + 0, 3154, 0, + 0, 3277, 0, + 0, 3403, 0, + 0, 3529, 0, + 0, 3658, 0, + 0, 2001, 2279, + 0, 2002, 2278, + 0, 2003, 2277, + 0, 2004, 2276, + 0, 2006, 2275, + 0, 2008, 2273, + 0, 2011, 2270, + 0, 2015, 2267, + 0, 2020, 2262, + 0, 2027, 2255, + 0, 2036, 2246, + 0, 2048, 2234, + 0, 2063, 2217, + 0, 2082, 2193, + 0, 2107, 2160, + 0, 2138, 2110, + 0, 2177, 2035, + 0, 2224, 1909, + 0, 2280, 1655, + 0, 2346, 0, + 0, 2421, 0, + 0, 2505, 0, + 0, 2598, 0, + 0, 2699, 0, + 0, 2805, 0, + 0, 2918, 0, + 0, 3034, 0, + 0, 3154, 0, + 0, 3277, 0, + 0, 3403, 0, + 0, 3529, 0, + 0, 3658, 0, + 0, 2003, 2284, + 0, 2003, 2283, + 0, 2004, 2283, + 0, 2006, 2282, + 0, 2007, 2280, + 0, 2009, 2278, + 0, 2012, 2275, + 0, 2016, 2272, + 0, 2021, 2267, + 0, 2028, 2261, + 0, 2037, 2252, + 0, 2049, 2240, + 0, 2064, 2223, + 0, 2083, 2200, + 0, 2108, 2166, + 0, 2139, 2118, + 0, 2178, 2044, + 0, 2225, 1921, + 0, 2281, 1676, + 0, 2347, 277, + 0, 2422, 0, + 0, 2506, 0, + 0, 2599, 0, + 0, 2699, 0, + 0, 2806, 0, + 0, 2918, 0, + 0, 3034, 0, + 0, 3155, 0, + 0, 3278, 0, + 0, 3403, 0, + 0, 3529, 0, + 0, 3658, 0, + 0, 2005, 2291, + 0, 2005, 2290, + 0, 2006, 2290, + 0, 2007, 2288, + 0, 2009, 2287, + 0, 2011, 2285, + 0, 2014, 2283, + 0, 2018, 2279, + 0, 2023, 2274, + 0, 2030, 2268, + 0, 2039, 2259, + 0, 2050, 2247, + 0, 2065, 2231, + 0, 2085, 2208, + 0, 2110, 2175, + 0, 2141, 2128, + 0, 2179, 2055, + 0, 2226, 1936, + 0, 2282, 1702, + 0, 2347, 650, + 0, 2422, 0, + 0, 2507, 0, + 0, 2599, 0, + 0, 2699, 0, + 0, 2806, 0, + 0, 2918, 0, + 0, 3035, 0, + 0, 3155, 0, + 0, 3278, 0, + 0, 3403, 0, + 0, 3530, 0, + 0, 3658, 0, + 0, 2007, 2300, + 0, 2008, 2299, + 0, 2009, 2299, + 0, 2010, 2298, + 0, 2011, 2296, + 0, 2014, 2294, + 0, 2017, 2292, + 0, 2020, 2288, + 0, 2025, 2284, + 0, 2032, 2277, + 0, 2041, 2269, + 0, 2053, 2257, + 0, 2068, 2241, + 0, 2087, 2219, + 0, 2111, 2187, + 0, 2142, 2141, + 0, 2181, 2071, + 0, 2227, 1955, + 0, 2283, 1734, + 0, 2349, 904, + 0, 2423, 0, + 0, 2507, 0, + 0, 2600, 0, + 0, 2700, 0, + 0, 2806, 0, + 0, 2918, 0, + 0, 3035, 0, + 0, 3155, 0, + 0, 3278, 0, + 0, 3403, 0, + 0, 3530, 0, + 0, 3658, 0, + 0, 2010, 2312, + 0, 2011, 2311, + 0, 2012, 2311, + 0, 2013, 2310, + 0, 2015, 2308, + 0, 2017, 2306, + 0, 2020, 2304, + 0, 2023, 2301, + 0, 2029, 2296, + 0, 2035, 2290, + 0, 2044, 2282, + 0, 2055, 2270, + 0, 2070, 2255, + 0, 2090, 2233, + 0, 2114, 2202, + 0, 2145, 2158, + 0, 2183, 2090, + 0, 2229, 1980, + 0, 2285, 1774, + 0, 2350, 1110, + 0, 2425, 0, + 0, 2508, 0, + 0, 2601, 0, + 0, 2700, 0, + 0, 2807, 0, + 0, 2919, 0, + 0, 3035, 0, + 0, 3155, 0, + 0, 3278, 0, + 0, 3403, 0, + 0, 3530, 0, + 0, 3658, 0, + 0, 2014, 2327, + 0, 2015, 2327, + 0, 2016, 2326, + 0, 2017, 2325, + 0, 2019, 2324, + 0, 2021, 2322, + 0, 2024, 2320, + 0, 2028, 2316, + 0, 2033, 2312, + 0, 2039, 2306, + 0, 2048, 2298, + 0, 2059, 2287, + 0, 2074, 2272, + 0, 2093, 2251, + 0, 2117, 2222, + 0, 2148, 2179, + 0, 2186, 2115, + 0, 2232, 2012, + 0, 2287, 1823, + 0, 2352, 1290, + 0, 2426, 0, + 0, 2510, 0, + 0, 2602, 0, + 0, 2701, 0, + 0, 2808, 0, + 0, 2919, 0, + 0, 3036, 0, + 0, 3155, 0, + 0, 3278, 0, + 0, 3403, 0, + 0, 3530, 0, + 0, 3658, 0, + 0, 2020, 2347, + 0, 2021, 2347, + 0, 2022, 2346, + 0, 2023, 2345, + 0, 2024, 2344, + 0, 2026, 2342, + 0, 2029, 2340, + 0, 2033, 2337, + 0, 2038, 2333, + 0, 2044, 2327, + 0, 2053, 2319, + 0, 2064, 2309, + 0, 2079, 2295, + 0, 2098, 2275, + 0, 2122, 2247, + 0, 2152, 2206, + 0, 2190, 2146, + 0, 2235, 2051, + 0, 2290, 1881, + 0, 2355, 1455, + 0, 2429, 0, + 0, 2512, 0, + 0, 2603, 0, + 0, 2703, 0, + 0, 2809, 0, + 0, 2920, 0, + 0, 3036, 0, + 0, 3156, 0, + 0, 3279, 0, + 0, 3403, 0, + 0, 3530, 0, + 0, 3658, 0, + 423, 2027, 2373, + 373, 2028, 2372, + 295, 2029, 2371, + 163, 2030, 2370, + 0, 2032, 2369, + 0, 2034, 2368, + 0, 2036, 2365, + 0, 2040, 2363, + 0, 2045, 2359, + 0, 2051, 2353, + 0, 2060, 2346, + 0, 2071, 2336, + 0, 2085, 2323, + 0, 2104, 2304, + 0, 2128, 2278, + 0, 2158, 2241, + 0, 2195, 2185, + 0, 2240, 2098, + 0, 2294, 1948, + 0, 2358, 1610, + 0, 2432, 0, + 0, 2514, 0, + 0, 2605, 0, + 0, 2704, 0, + 0, 2810, 0, + 0, 2921, 0, + 0, 3037, 0, + 0, 3157, 0, + 0, 3279, 0, + 0, 3404, 0, + 0, 3530, 0, + 0, 3658, 0, + 1521, 2037, 2404, + 1517, 2038, 2404, + 1511, 2039, 2403, + 1503, 2040, 2402, + 1492, 2041, 2401, + 1477, 2043, 2400, + 1457, 2046, 2398, + 1428, 2050, 2395, + 1385, 2054, 2391, + 1322, 2061, 2386, + 1221, 2069, 2380, + 1036, 2080, 2371, + 529, 2094, 2358, + 0, 2112, 2341, + 0, 2135, 2317, + 0, 2165, 2283, + 0, 2201, 2232, + 0, 2246, 2155, + 0, 2300, 2025, + 0, 2363, 1759, + 0, 2436, 0, + 0, 2518, 0, + 0, 2608, 0, + 0, 2707, 0, + 0, 2812, 0, + 0, 2923, 0, + 0, 3038, 0, + 0, 3157, 0, + 0, 3280, 0, + 0, 3404, 0, + 0, 3531, 0, + 0, 3659, 0, + 1883, 2050, 2444, + 1881, 2050, 2443, + 1879, 2051, 2443, + 1875, 2052, 2442, + 1870, 2054, 2441, + 1864, 2056, 2439, + 1855, 2058, 2437, + 1843, 2062, 2435, + 1827, 2066, 2432, + 1804, 2073, 2427, + 1771, 2081, 2421, + 1724, 2091, 2413, + 1651, 2105, 2401, + 1531, 2123, 2386, + 1296, 2146, 2364, + 216, 2174, 2333, + 0, 2210, 2288, + 0, 2254, 2221, + 0, 2307, 2111, + 0, 2369, 1903, + 0, 2441, 1228, + 0, 2522, 0, + 0, 2612, 0, + 0, 2709, 0, + 0, 2814, 0, + 0, 2924, 0, + 0, 3039, 0, + 0, 3158, 0, + 0, 3280, 0, + 0, 3405, 0, + 0, 3531, 0, + 0, 3659, 0, + 2133, 2066, 2491, + 2132, 2067, 2491, + 2131, 2067, 2490, + 2129, 2068, 2490, + 2126, 2070, 2489, + 2122, 2072, 2487, + 2118, 2074, 2486, + 2111, 2078, 2484, + 2102, 2082, 2481, + 2089, 2088, 2476, + 2072, 2096, 2471, + 2048, 2106, 2464, + 2014, 2120, 2453, + 1964, 2137, 2440, + 1887, 2159, 2420, + 1758, 2187, 2393, + 1496, 2222, 2354, + 0, 2265, 2296, + 0, 2316, 2205, + 0, 2377, 2044, + 0, 2448, 1663, + 0, 2528, 0, + 0, 2617, 0, + 0, 2713, 0, + 0, 2817, 0, + 0, 2927, 0, + 0, 3041, 0, + 0, 3160, 0, + 0, 3282, 0, + 0, 3406, 0, + 0, 3532, 0, + 0, 3659, 0, + 2337, 2087, 2548, + 2337, 2088, 2548, + 2336, 2088, 2547, + 2334, 2089, 2547, + 2333, 2091, 2546, + 2330, 2093, 2545, + 2327, 2095, 2543, + 2323, 2098, 2541, + 2317, 2103, 2539, + 2310, 2108, 2535, + 2299, 2116, 2530, + 2285, 2126, 2524, + 2265, 2138, 2515, + 2237, 2155, 2503, + 2196, 2176, 2486, + 2135, 2203, 2463, + 2039, 2237, 2429, + 1866, 2278, 2381, + 1429, 2329, 2306, + 0, 2388, 2182, + 0, 2457, 1936, + 0, 2536, 450, + 0, 2623, 0, + 0, 2718, 0, + 0, 2821, 0, + 0, 2930, 0, + 0, 3044, 0, + 0, 3162, 0, + 0, 3283, 0, + 0, 3407, 0, + 0, 3533, 0, + 0, 3660, 0, + 2517, 2114, 2614, + 2516, 2114, 2614, + 2515, 2115, 2614, + 2515, 2116, 2613, + 2513, 2117, 2612, + 2512, 2119, 2612, + 2510, 2121, 2610, + 2507, 2124, 2609, + 2503, 2128, 2606, + 2498, 2134, 2603, + 2491, 2141, 2599, + 2482, 2150, 2593, + 2469, 2162, 2586, + 2451, 2178, 2576, + 2426, 2198, 2561, + 2391, 2224, 2542, + 2338, 2256, 2514, + 2257, 2296, 2474, + 2119, 2344, 2414, + 1828, 2402, 2319, + 0, 2469, 2151, + 0, 2546, 1735, + 0, 2631, 0, + 0, 2725, 0, + 0, 2827, 0, + 0, 2934, 0, + 0, 3047, 0, + 0, 3164, 0, + 0, 3285, 0, + 0, 3408, 0, + 0, 3534, 0, + 0, 3661, 0, + 2681, 2147, 2690, + 2681, 2147, 2690, + 2680, 2148, 2690, + 2680, 2149, 2689, + 2679, 2150, 2689, + 2678, 2152, 2688, + 2676, 2154, 2687, + 2674, 2157, 2685, + 2672, 2161, 2683, + 2668, 2166, 2681, + 2663, 2172, 2677, + 2657, 2181, 2673, + 2648, 2192, 2666, + 2636, 2207, 2658, + 2620, 2226, 2646, + 2597, 2250, 2629, + 2565, 2281, 2607, + 2517, 2319, 2574, + 2444, 2365, 2527, + 2325, 2420, 2455, + 2090, 2485, 2336, + 1027, 2559, 2105, + 0, 2642, 1114, + 0, 2734, 0, + 0, 2834, 0, + 0, 2940, 0, + 0, 3052, 0, + 0, 3168, 0, + 0, 3288, 0, + 0, 3410, 0, + 0, 3535, 0, + 0, 3662, 0, + 2836, 2188, 2775, + 2836, 2189, 2775, + 2835, 2189, 2775, + 2835, 2190, 2774, + 2834, 2191, 2774, + 2833, 2193, 2773, + 2832, 2194, 2772, + 2831, 2197, 2771, + 2829, 2201, 2770, + 2827, 2205, 2767, + 2823, 2211, 2765, + 2819, 2219, 2761, + 2813, 2230, 2755, + 2805, 2243, 2748, + 2793, 2261, 2739, + 2778, 2283, 2725, + 2756, 2312, 2707, + 2726, 2347, 2681, + 2681, 2391, 2644, + 2614, 2443, 2590, + 2505, 2505, 2505, + 2300, 2576, 2358, + 1648, 2656, 2036, + 0, 2746, 0, + 0, 2843, 0, + 0, 2947, 0, + 0, 3057, 0, + 0, 3172, 0, + 0, 3291, 0, + 0, 3413, 0, + 0, 3537, 0, + 0, 3664, 0, + 2984, 2238, 2869, + 2984, 2238, 2868, + 2984, 2239, 2868, + 2983, 2239, 2868, + 2983, 2240, 2868, + 2983, 2242, 2867, + 2982, 2244, 2866, + 2981, 2246, 2865, + 2979, 2249, 2864, + 2978, 2253, 2862, + 2975, 2259, 2860, + 2972, 2266, 2857, + 2968, 2275, 2853, + 2962, 2287, 2847, + 2954, 2303, 2839, + 2943, 2324, 2828, + 2928, 2350, 2814, + 2907, 2383, 2794, + 2878, 2423, 2765, + 2836, 2472, 2724, + 2772, 2530, 2662, + 2669, 2598, 2563, + 2482, 2675, 2386, + 1962, 2761, 1922, + 0, 2855, 0, + 0, 2957, 0, + 0, 3065, 0, + 0, 3178, 0, + 0, 3296, 0, + 0, 3417, 0, + 0, 3540, 0, + 0, 3666, 0, + 3128, 2297, 2969, + 3128, 2297, 2969, + 3128, 2298, 2969, + 3128, 2298, 2969, + 3127, 2299, 2969, + 3127, 2300, 2968, + 3126, 2302, 2968, + 3126, 2304, 2967, + 3125, 2307, 2966, + 3123, 2310, 2964, + 3122, 2315, 2962, + 3119, 2321, 2960, + 3116, 2330, 2957, + 3112, 2341, 2952, + 3106, 2355, 2946, + 3099, 2373, 2938, + 3088, 2397, 2926, + 3073, 2426, 2910, + 3053, 2463, 2888, + 3025, 2508, 2857, + 2984, 2562, 2812, + 2922, 2625, 2744, + 2825, 2698, 2632, + 2649, 2780, 2420, + 2195, 2871, 1705, + 0, 2970, 0, + 0, 3075, 0, + 0, 3186, 0, + 0, 3302, 0, + 0, 3421, 0, + 0, 3544, 0, + 0, 3668, 0, + 3269, 2365, 3077, + 3269, 2366, 3077, + 3269, 2366, 3076, + 3268, 2367, 3076, + 3268, 2367, 3076, + 3268, 2368, 3076, + 3268, 2370, 3075, + 3267, 2371, 3075, + 3266, 2374, 3074, + 3265, 2377, 3073, + 3264, 2381, 3071, + 3262, 2387, 3069, + 3260, 2394, 3067, + 3257, 2403, 3063, + 3253, 2416, 3058, + 3247, 2432, 3052, + 3240, 2453, 3043, + 3229, 2479, 3031, + 3215, 2512, 3014, + 3195, 2552, 2990, + 3168, 2601, 2957, + 3128, 2660, 2908, + 3068, 2728, 2834, + 2973, 2805, 2710, + 2805, 2892, 2463, + 2389, 2986, 928, + 0, 3088, 0, + 0, 3197, 0, + 0, 3310, 0, + 0, 3427, 0, + 0, 3548, 0, + 0, 3672, 0, + 3407, 2443, 3189, + 3407, 2444, 3189, + 3407, 2444, 3189, + 3407, 2444, 3189, + 3407, 2445, 3189, + 3407, 2446, 3188, + 3406, 2447, 3188, + 3406, 2448, 3188, + 3405, 2450, 3187, + 3405, 2453, 3186, + 3404, 2457, 3185, + 3403, 2461, 3183, + 3401, 2467, 3181, + 3399, 2475, 3179, + 3396, 2486, 3175, + 3392, 2500, 3170, + 3386, 2518, 3163, + 3379, 2541, 3154, + 3368, 2570, 3141, + 3354, 2605, 3123, + 3335, 2649, 3099, + 3308, 2702, 3064, + 3268, 2765, 3012, + 3210, 2836, 2932, + 3117, 2918, 2797, + 2954, 3008, 2514, + 2563, 3105, 0, + 0, 3210, 0, + 0, 3320, 0, + 0, 3436, 0, + 0, 3555, 0, + 0, 3677, 0, + 3544, 2530, 3306, + 3544, 2530, 3306, + 3544, 2531, 3306, + 3544, 2531, 3306, + 3544, 2532, 3306, + 3544, 2532, 3305, + 3543, 2533, 3305, + 3543, 2534, 3305, + 3543, 2536, 3304, + 3542, 2538, 3304, + 3541, 2541, 3303, + 3541, 2545, 3302, + 3539, 2550, 3300, + 3538, 2557, 3298, + 3535, 2566, 3295, + 3532, 2578, 3291, + 3528, 2593, 3286, + 3523, 2612, 3279, + 3516, 2637, 3269, + 3505, 2668, 3256, + 3492, 2707, 3238, + 3472, 2754, 3212, + 3445, 2810, 3175, + 3407, 2875, 3121, + 3349, 2950, 3037, + 3258, 3034, 2892, + 3099, 3127, 2574, + 2724, 3227, 0, + 0, 3334, 0, + 0, 3446, 0, + 0, 3563, 0, + 0, 3683, 0, + 3680, 2625, 3427, + 3680, 2626, 3426, + 3680, 2626, 3426, + 3679, 2626, 3426, + 3679, 2626, 3426, + 3679, 2627, 3426, + 3679, 2628, 3426, + 3679, 2629, 3426, + 3679, 2630, 3425, + 3678, 2632, 3425, + 3678, 2634, 3424, + 3677, 2637, 3423, + 3676, 2642, 3422, + 3675, 2647, 3420, + 3673, 2655, 3418, + 3671, 2664, 3415, + 3668, 2677, 3411, + 3664, 2693, 3406, + 3659, 2714, 3399, + 3651, 2740, 3389, + 3641, 2773, 3375, + 3628, 2814, 3356, + 3609, 2863, 3330, + 3582, 2922, 3292, + 3543, 2990, 3236, + 3486, 3068, 3147, + 3397, 3155, 2994, + 3240, 3250, 2644, + 2877, 3352, 0, + 0, 3460, 0, + 0, 3574, 0, + 0, 3691, 0, + 3814, 2728, 3550, + 3814, 2728, 3550, + 3814, 2728, 3550, + 3814, 2728, 3550, + 3814, 2729, 3549, + 3814, 2729, 3549, + 3814, 2730, 3549, + 3814, 2730, 3549, + 3814, 2732, 3549, + 3813, 2733, 3548, + 3813, 2735, 3548, + 3812, 2737, 3547, + 3812, 2741, 3546, + 3811, 2745, 3545, + 3810, 2751, 3543, + 3808, 2759, 3541, + 3806, 2769, 3538, + 3803, 2782, 3534, + 3799, 2800, 3528, + 3793, 2822, 3521, + 3786, 2849, 3511, + 3776, 2884, 3497, + 3763, 2927, 3478, + 3744, 2978, 3451, + 3717, 3039, 3412, + 3679, 3109, 3354, + 3622, 3189, 3263, + 3534, 3278, 3102, + 3379, 3374, 2724, + 3024, 3478, 0, + 0, 3588, 0, + 0, 3702, 0, + 3948, 2836, 3675, + 3948, 2836, 3675, + 3948, 2836, 3675, + 3948, 2837, 3675, + 3948, 2837, 3675, + 3948, 2837, 3675, + 3948, 2838, 3675, + 3948, 2838, 3674, + 3948, 2839, 3674, + 3948, 2840, 3674, + 3947, 2842, 3673, + 3947, 2844, 3673, + 3946, 2847, 3672, + 3946, 2850, 3671, + 3945, 2855, 3670, + 3944, 2861, 3668, + 3942, 2869, 3666, + 3940, 2880, 3663, + 3937, 2894, 3659, + 3933, 2912, 3653, + 3928, 2935, 3646, + 3920, 2964, 3636, + 3910, 3000, 3622, + 3897, 3044, 3602, + 3878, 3097, 3574, + 3852, 3160, 3535, + 3814, 3232, 3475, + 3757, 3313, 3382, + 3669, 3403, 3216, + 3516, 3501, 2812, + 3167, 3606, 0, + 0, 3716, 0, + 4082, 2950, 3802, + 4082, 2950, 3802, + 4082, 2950, 3802, + 4082, 2950, 3802, + 4082, 2950, 3802, + 4082, 2951, 3802, + 4082, 2951, 3802, + 4082, 2952, 3801, + 4081, 2952, 3801, + 4081, 2953, 3801, + 4081, 2954, 3801, + 4081, 2956, 3800, + 4080, 2958, 3800, + 4080, 2961, 3799, + 4079, 2964, 3798, + 4078, 2969, 3797, + 4077, 2976, 3795, + 4075, 2984, 3793, + 4073, 2995, 3790, + 4070, 3010, 3786, + 4066, 3028, 3780, + 4061, 3052, 3772, + 4054, 3082, 3762, + 4044, 3119, 3748, + 4030, 3164, 3728, + 4012, 3219, 3700, + 3985, 3283, 3660, + 3948, 3356, 3599, + 3892, 3439, 3504, + 3804, 3530, 3334, + 3652, 3629, 2909, + 3307, 3735, 0, + 4095, 3068, 3930, + 4095, 3068, 3930, + 4095, 3068, 3930, + 4095, 3068, 3930, + 4095, 3068, 3930, + 4095, 3068, 3930, + 4095, 3069, 3930, + 4095, 3069, 3930, + 4095, 3069, 3930, + 4095, 3070, 3929, + 4095, 3071, 3929, + 4095, 3072, 3929, + 4095, 3074, 3929, + 4095, 3076, 3928, + 4095, 3079, 3927, + 4095, 3083, 3926, + 4095, 3088, 3925, + 4095, 3094, 3923, + 4095, 3103, 3921, + 4095, 3114, 3918, + 4095, 3129, 3914, + 4095, 3148, 3908, + 4095, 3173, 3900, + 4095, 3203, 3890, + 4095, 3241, 3875, + 4095, 3288, 3855, + 4095, 3343, 3827, + 4095, 3408, 3786, + 4081, 3482, 3725, + 4025, 3566, 3629, + 3938, 3658, 3455, + 3786, 3758, 3012, + 4095, 3189, 4059, + 4095, 3189, 4059, + 4095, 3189, 4059, + 4095, 3189, 4059, + 4095, 3189, 4059, + 4095, 3189, 4059, + 4095, 3189, 4059, + 4095, 3190, 4059, + 4095, 3190, 4059, + 4095, 3191, 4059, + 4095, 3191, 4059, + 4095, 3192, 4058, + 4095, 3193, 4058, + 4095, 3195, 4058, + 4095, 3197, 4057, + 4095, 3200, 4056, + 4095, 3204, 4055, + 4095, 3209, 4054, + 4095, 3216, 4052, + 4095, 3225, 4050, + 4095, 3237, 4047, + 4095, 3252, 4043, + 4095, 3271, 4037, + 4095, 3296, 4029, + 4095, 3327, 4019, + 4095, 3366, 4004, + 4095, 3413, 3984, + 4095, 3469, 3956, + 4095, 3535, 3914, + 4095, 3610, 3853, + 4095, 3694, 3755, + 4071, 3787, 3579, + 0, 2129, 2398, + 0, 2130, 2397, + 0, 2131, 2396, + 0, 2132, 2396, + 0, 2133, 2394, + 0, 2135, 2393, + 0, 2137, 2391, + 0, 2140, 2388, + 0, 2144, 2384, + 0, 2149, 2379, + 0, 2156, 2373, + 0, 2165, 2363, + 0, 2176, 2351, + 0, 2192, 2333, + 0, 2211, 2309, + 0, 2236, 2274, + 0, 2268, 2222, + 0, 2307, 2143, + 0, 2354, 2009, + 0, 2410, 1731, + 0, 2476, 0, + 0, 2552, 0, + 0, 2636, 0, + 0, 2729, 0, + 0, 2830, 0, + 0, 2937, 0, + 0, 3049, 0, + 0, 3166, 0, + 0, 3286, 0, + 0, 3409, 0, + 0, 3535, 0, + 0, 3661, 0, + 0, 2130, 2398, + 0, 2130, 2398, + 0, 2131, 2397, + 0, 2132, 2396, + 0, 2133, 2395, + 0, 2135, 2394, + 0, 2137, 2392, + 0, 2140, 2389, + 0, 2144, 2385, + 0, 2149, 2380, + 0, 2156, 2373, + 0, 2165, 2364, + 0, 2177, 2352, + 0, 2192, 2334, + 0, 2212, 2310, + 0, 2237, 2275, + 0, 2268, 2223, + 0, 2307, 2144, + 0, 2354, 2011, + 0, 2411, 1734, + 0, 2476, 0, + 0, 2552, 0, + 0, 2636, 0, + 0, 2729, 0, + 0, 2830, 0, + 0, 2937, 0, + 0, 3049, 0, + 0, 3166, 0, + 0, 3286, 0, + 0, 3409, 0, + 0, 3535, 0, + 0, 3661, 0, + 0, 2130, 2399, + 0, 2130, 2399, + 0, 2131, 2398, + 0, 2132, 2397, + 0, 2133, 2396, + 0, 2135, 2395, + 0, 2137, 2393, + 0, 2140, 2390, + 0, 2144, 2386, + 0, 2149, 2381, + 0, 2156, 2374, + 0, 2165, 2365, + 0, 2177, 2353, + 0, 2192, 2335, + 0, 2212, 2311, + 0, 2237, 2276, + 0, 2268, 2225, + 0, 2307, 2146, + 0, 2354, 2013, + 0, 2411, 1738, + 0, 2477, 0, + 0, 2552, 0, + 0, 2637, 0, + 0, 2730, 0, + 0, 2830, 0, + 0, 2937, 0, + 0, 3049, 0, + 0, 3166, 0, + 0, 3286, 0, + 0, 3409, 0, + 0, 3535, 0, + 0, 3661, 0, + 0, 2130, 2400, + 0, 2131, 2400, + 0, 2131, 2399, + 0, 2132, 2399, + 0, 2134, 2397, + 0, 2135, 2396, + 0, 2138, 2394, + 0, 2140, 2391, + 0, 2144, 2387, + 0, 2150, 2382, + 0, 2156, 2376, + 0, 2165, 2367, + 0, 2177, 2354, + 0, 2192, 2337, + 0, 2212, 2312, + 0, 2237, 2278, + 0, 2268, 2227, + 0, 2307, 2148, + 0, 2354, 2016, + 0, 2411, 1743, + 0, 2477, 0, + 0, 2552, 0, + 0, 2637, 0, + 0, 2730, 0, + 0, 2830, 0, + 0, 2937, 0, + 0, 3049, 0, + 0, 3166, 0, + 0, 3286, 0, + 0, 3409, 0, + 0, 3535, 0, + 0, 3661, 0, + 0, 2131, 2402, + 0, 2131, 2402, + 0, 2132, 2401, + 0, 2133, 2400, + 0, 2134, 2399, + 0, 2136, 2398, + 0, 2138, 2396, + 0, 2141, 2393, + 0, 2145, 2389, + 0, 2150, 2384, + 0, 2157, 2377, + 0, 2166, 2368, + 0, 2177, 2356, + 0, 2193, 2339, + 0, 2212, 2314, + 0, 2237, 2280, + 0, 2269, 2229, + 0, 2307, 2151, + 0, 2355, 2020, + 0, 2411, 1750, + 0, 2477, 0, + 0, 2552, 0, + 0, 2637, 0, + 0, 2730, 0, + 0, 2830, 0, + 0, 2937, 0, + 0, 3049, 0, + 0, 3166, 0, + 0, 3286, 0, + 0, 3409, 0, + 0, 3535, 0, + 0, 3661, 0, + 0, 2131, 2404, + 0, 2132, 2404, + 0, 2132, 2403, + 0, 2133, 2402, + 0, 2135, 2401, + 0, 2136, 2400, + 0, 2139, 2398, + 0, 2141, 2395, + 0, 2145, 2391, + 0, 2151, 2387, + 0, 2157, 2380, + 0, 2166, 2371, + 0, 2178, 2358, + 0, 2193, 2341, + 0, 2213, 2317, + 0, 2238, 2283, + 0, 2269, 2232, + 0, 2308, 2155, + 0, 2355, 2025, + 0, 2411, 1760, + 0, 2477, 0, + 0, 2553, 0, + 0, 2637, 0, + 0, 2730, 0, + 0, 2830, 0, + 0, 2937, 0, + 0, 3049, 0, + 0, 3166, 0, + 0, 3286, 0, + 0, 3409, 0, + 0, 3535, 0, + 0, 3661, 0, + 0, 2132, 2407, + 0, 2133, 2407, + 0, 2133, 2406, + 0, 2134, 2405, + 0, 2135, 2404, + 0, 2137, 2403, + 0, 2139, 2401, + 0, 2142, 2398, + 0, 2146, 2395, + 0, 2151, 2390, + 0, 2158, 2383, + 0, 2167, 2374, + 0, 2179, 2362, + 0, 2194, 2345, + 0, 2213, 2321, + 0, 2238, 2287, + 0, 2270, 2237, + 0, 2308, 2160, + 0, 2356, 2032, + 0, 2412, 1772, + 0, 2478, 0, + 0, 2553, 0, + 0, 2637, 0, + 0, 2730, 0, + 0, 2830, 0, + 0, 2937, 0, + 0, 3050, 0, + 0, 3166, 0, + 0, 3286, 0, + 0, 3409, 0, + 0, 3535, 0, + 0, 3661, 0, + 0, 2133, 2411, + 0, 2134, 2411, + 0, 2134, 2410, + 0, 2135, 2409, + 0, 2136, 2408, + 0, 2138, 2407, + 0, 2140, 2405, + 0, 2143, 2402, + 0, 2147, 2399, + 0, 2152, 2394, + 0, 2159, 2387, + 0, 2168, 2378, + 0, 2180, 2366, + 0, 2195, 2349, + 0, 2214, 2325, + 0, 2239, 2292, + 0, 2270, 2242, + 0, 2309, 2167, + 0, 2356, 2041, + 0, 2412, 1788, + 0, 2478, 0, + 0, 2553, 0, + 0, 2638, 0, + 0, 2730, 0, + 0, 2831, 0, + 0, 2937, 0, + 0, 3050, 0, + 0, 3166, 0, + 0, 3287, 0, + 0, 3410, 0, + 0, 3535, 0, + 0, 3662, 0, + 0, 2134, 2417, + 0, 2135, 2416, + 0, 2136, 2416, + 0, 2136, 2415, + 0, 2138, 2414, + 0, 2139, 2412, + 0, 2142, 2410, + 0, 2144, 2408, + 0, 2148, 2404, + 0, 2154, 2399, + 0, 2160, 2393, + 0, 2169, 2384, + 0, 2181, 2372, + 0, 2196, 2355, + 0, 2215, 2332, + 0, 2240, 2299, + 0, 2271, 2250, + 0, 2310, 2176, + 0, 2357, 2053, + 0, 2413, 1808, + 0, 2479, 410, + 0, 2554, 0, + 0, 2638, 0, + 0, 2731, 0, + 0, 2831, 0, + 0, 2938, 0, + 0, 3050, 0, + 0, 3166, 0, + 0, 3287, 0, + 0, 3410, 0, + 0, 3535, 0, + 0, 3662, 0, + 0, 2136, 2424, + 0, 2137, 2423, + 0, 2137, 2422, + 0, 2138, 2422, + 0, 2140, 2421, + 0, 2141, 2419, + 0, 2143, 2417, + 0, 2146, 2415, + 0, 2150, 2411, + 0, 2155, 2406, + 0, 2162, 2400, + 0, 2171, 2391, + 0, 2182, 2379, + 0, 2198, 2363, + 0, 2217, 2340, + 0, 2242, 2308, + 0, 2273, 2260, + 0, 2311, 2187, + 0, 2358, 2068, + 0, 2414, 1834, + 0, 2479, 782, + 0, 2554, 0, + 0, 2639, 0, + 0, 2731, 0, + 0, 2831, 0, + 0, 2938, 0, + 0, 3050, 0, + 0, 3167, 0, + 0, 3287, 0, + 0, 3410, 0, + 0, 3535, 0, + 0, 3662, 0, + 0, 2139, 2433, + 0, 2139, 2432, + 0, 2140, 2432, + 0, 2141, 2431, + 0, 2142, 2430, + 0, 2144, 2428, + 0, 2146, 2426, + 0, 2149, 2424, + 0, 2152, 2420, + 0, 2158, 2416, + 0, 2164, 2410, + 0, 2173, 2401, + 0, 2185, 2389, + 0, 2200, 2373, + 0, 2219, 2351, + 0, 2244, 2319, + 0, 2274, 2273, + 0, 2313, 2203, + 0, 2360, 2088, + 0, 2415, 1866, + 0, 2481, 1036, + 0, 2555, 0, + 0, 2639, 0, + 0, 2732, 0, + 0, 2832, 0, + 0, 2938, 0, + 0, 3050, 0, + 0, 3167, 0, + 0, 3287, 0, + 0, 3410, 0, + 0, 3535, 0, + 0, 3662, 0, + 0, 2142, 2444, + 0, 2142, 2444, + 0, 2143, 2443, + 0, 2144, 2443, + 0, 2145, 2442, + 0, 2147, 2440, + 0, 2149, 2438, + 0, 2152, 2436, + 0, 2156, 2433, + 0, 2161, 2428, + 0, 2167, 2422, + 0, 2176, 2414, + 0, 2188, 2402, + 0, 2202, 2387, + 0, 2222, 2365, + 0, 2246, 2334, + 0, 2277, 2290, + 0, 2315, 2222, + 0, 2362, 2113, + 0, 2417, 1906, + 0, 2482, 1242, + 0, 2557, 0, + 0, 2640, 0, + 0, 2733, 0, + 0, 2833, 0, + 0, 2939, 0, + 0, 3051, 0, + 0, 3167, 0, + 0, 3287, 0, + 0, 3410, 0, + 0, 3535, 0, + 0, 3662, 0, + 0, 2146, 2460, + 0, 2146, 2460, + 0, 2147, 2459, + 0, 2148, 2458, + 0, 2149, 2457, + 0, 2151, 2456, + 0, 2153, 2454, + 0, 2156, 2452, + 0, 2160, 2448, + 0, 2165, 2444, + 0, 2171, 2438, + 0, 2180, 2430, + 0, 2191, 2419, + 0, 2206, 2404, + 0, 2225, 2383, + 0, 2249, 2354, + 0, 2280, 2311, + 0, 2318, 2247, + 0, 2364, 2144, + 0, 2419, 1955, + 0, 2484, 1422, + 0, 2558, 0, + 0, 2642, 0, + 0, 2734, 0, + 0, 2834, 0, + 0, 2940, 0, + 0, 3051, 0, + 0, 3168, 0, + 0, 3288, 0, + 0, 3410, 0, + 0, 3535, 0, + 0, 3662, 0, + 0, 2152, 2480, + 0, 2152, 2479, + 0, 2153, 2479, + 0, 2154, 2478, + 0, 2155, 2477, + 0, 2156, 2476, + 0, 2159, 2474, + 0, 2161, 2472, + 0, 2165, 2469, + 0, 2170, 2465, + 0, 2177, 2459, + 0, 2185, 2451, + 0, 2196, 2441, + 0, 2211, 2427, + 0, 2230, 2407, + 0, 2254, 2379, + 0, 2284, 2339, + 0, 2322, 2278, + 0, 2368, 2183, + 0, 2422, 2013, + 0, 2487, 1587, + 0, 2561, 0, + 0, 2644, 0, + 0, 2735, 0, + 0, 2835, 0, + 0, 2941, 0, + 0, 3052, 0, + 0, 3168, 0, + 0, 3288, 0, + 0, 3411, 0, + 0, 3536, 0, + 0, 3662, 0, + 590, 2159, 2505, + 556, 2159, 2505, + 505, 2160, 2504, + 427, 2161, 2503, + 295, 2162, 2503, + 26, 2164, 2501, + 0, 2166, 2500, + 0, 2169, 2498, + 0, 2172, 2495, + 0, 2177, 2491, + 0, 2184, 2485, + 0, 2192, 2478, + 0, 2203, 2468, + 0, 2218, 2455, + 0, 2236, 2436, + 0, 2260, 2410, + 0, 2290, 2373, + 0, 2327, 2317, + 0, 2372, 2230, + 0, 2427, 2080, + 0, 2490, 1742, + 0, 2564, 0, + 0, 2646, 0, + 0, 2737, 0, + 0, 2836, 0, + 0, 2942, 0, + 0, 3053, 0, + 0, 3169, 0, + 0, 3289, 0, + 0, 3411, 0, + 0, 3536, 0, + 0, 3662, 0, + 1656, 2169, 2537, + 1653, 2169, 2536, + 1649, 2170, 2536, + 1643, 2171, 2535, + 1635, 2172, 2534, + 1624, 2173, 2533, + 1610, 2175, 2532, + 1589, 2178, 2530, + 1560, 2182, 2527, + 1518, 2186, 2523, + 1454, 2193, 2518, + 1353, 2201, 2512, + 1168, 2212, 2503, + 661, 2226, 2490, + 0, 2244, 2473, + 0, 2268, 2449, + 0, 2297, 2415, + 0, 2334, 2364, + 0, 2378, 2287, + 0, 2432, 2157, + 0, 2495, 1891, + 0, 2568, 0, + 0, 2650, 0, + 0, 2740, 0, + 0, 2839, 0, + 0, 2944, 0, + 0, 3055, 0, + 0, 3170, 0, + 0, 3289, 0, + 0, 3412, 0, + 0, 3536, 0, + 0, 3663, 0, + 2017, 2181, 2576, + 2015, 2182, 2576, + 2013, 2182, 2575, + 2011, 2183, 2575, + 2007, 2184, 2574, + 2002, 2186, 2573, + 1996, 2188, 2571, + 1987, 2190, 2570, + 1975, 2194, 2567, + 1959, 2199, 2564, + 1936, 2205, 2559, + 1903, 2213, 2553, + 1856, 2223, 2545, + 1783, 2237, 2533, + 1663, 2255, 2518, + 1428, 2278, 2496, + 348, 2307, 2465, + 0, 2342, 2420, + 0, 2386, 2353, + 0, 2439, 2243, + 0, 2501, 2035, + 0, 2573, 1360, + 0, 2654, 0, + 0, 2744, 0, + 0, 2842, 0, + 0, 2946, 0, + 0, 3056, 0, + 0, 3172, 0, + 0, 3291, 0, + 0, 3413, 0, + 0, 3537, 0, + 0, 3663, 0, + 2266, 2198, 2624, + 2266, 2198, 2623, + 2264, 2199, 2623, + 2263, 2200, 2622, + 2261, 2201, 2622, + 2258, 2202, 2621, + 2255, 2204, 2620, + 2250, 2206, 2618, + 2243, 2210, 2616, + 2234, 2214, 2613, + 2222, 2220, 2609, + 2204, 2228, 2603, + 2180, 2238, 2596, + 2146, 2252, 2586, + 2096, 2269, 2572, + 2019, 2291, 2552, + 1890, 2319, 2525, + 1628, 2354, 2486, + 0, 2397, 2428, + 0, 2448, 2337, + 0, 2509, 2176, + 0, 2580, 1795, + 0, 2660, 0, + 0, 2749, 0, + 0, 2845, 0, + 0, 2949, 0, + 0, 3059, 0, + 0, 3173, 0, + 0, 3292, 0, + 0, 3414, 0, + 0, 3538, 0, + 0, 3664, 0, + 2470, 2219, 2680, + 2469, 2219, 2680, + 2469, 2220, 2680, + 2468, 2220, 2679, + 2466, 2221, 2679, + 2465, 2223, 2678, + 2462, 2225, 2677, + 2459, 2227, 2675, + 2455, 2230, 2673, + 2450, 2235, 2671, + 2442, 2240, 2667, + 2431, 2248, 2662, + 2417, 2258, 2656, + 2397, 2270, 2647, + 2369, 2287, 2635, + 2328, 2308, 2618, + 2267, 2335, 2595, + 2171, 2369, 2561, + 1998, 2410, 2513, + 1561, 2461, 2438, + 0, 2520, 2315, + 0, 2589, 2068, + 0, 2668, 582, + 0, 2755, 0, + 0, 2851, 0, + 0, 2953, 0, + 0, 3062, 0, + 0, 3176, 0, + 0, 3294, 0, + 0, 3415, 0, + 0, 3539, 0, + 0, 3665, 0, + 2649, 2245, 2747, + 2649, 2246, 2746, + 2648, 2246, 2746, + 2648, 2247, 2746, + 2647, 2248, 2745, + 2646, 2249, 2745, + 2644, 2251, 2744, + 2642, 2253, 2742, + 2639, 2256, 2741, + 2635, 2260, 2738, + 2630, 2266, 2735, + 2623, 2273, 2731, + 2614, 2282, 2726, + 2601, 2294, 2718, + 2583, 2310, 2708, + 2558, 2330, 2693, + 2523, 2356, 2674, + 2470, 2388, 2646, + 2389, 2428, 2606, + 2251, 2476, 2546, + 1960, 2534, 2451, + 0, 2601, 2283, + 0, 2678, 1867, + 0, 2763, 0, + 0, 2857, 0, + 0, 2959, 0, + 0, 3066, 0, + 0, 3179, 0, + 0, 3296, 0, + 0, 3417, 0, + 0, 3540, 0, + 0, 3666, 0, + 2813, 2279, 2823, + 2813, 2279, 2822, + 2813, 2280, 2822, + 2812, 2280, 2822, + 2812, 2281, 2821, + 2811, 2282, 2821, + 2810, 2284, 2820, + 2808, 2286, 2819, + 2806, 2289, 2817, + 2804, 2293, 2816, + 2800, 2298, 2813, + 2796, 2304, 2809, + 2789, 2313, 2805, + 2780, 2324, 2798, + 2769, 2339, 2790, + 2752, 2358, 2778, + 2729, 2382, 2762, + 2697, 2413, 2739, + 2649, 2451, 2706, + 2576, 2497, 2659, + 2457, 2552, 2587, + 2222, 2617, 2468, + 1159, 2691, 2237, + 0, 2774, 1246, + 0, 2866, 0, + 0, 2966, 0, + 0, 3072, 0, + 0, 3184, 0, + 0, 3300, 0, + 0, 3420, 0, + 0, 3542, 0, + 0, 3667, 0, + 2968, 2320, 2907, + 2968, 2320, 2907, + 2968, 2321, 2907, + 2967, 2321, 2907, + 2967, 2322, 2906, + 2966, 2323, 2906, + 2966, 2325, 2905, + 2965, 2327, 2904, + 2963, 2329, 2903, + 2961, 2333, 2902, + 2959, 2337, 2900, + 2956, 2343, 2897, + 2951, 2351, 2893, + 2945, 2362, 2888, + 2937, 2375, 2880, + 2925, 2393, 2871, + 2910, 2415, 2857, + 2888, 2444, 2839, + 2858, 2479, 2813, + 2813, 2523, 2776, + 2746, 2575, 2722, + 2637, 2637, 2637, + 2432, 2708, 2490, + 1780, 2789, 2168, + 0, 2878, 0, + 0, 2975, 0, + 0, 3079, 0, + 0, 3190, 0, + 0, 3304, 0, + 0, 3423, 0, + 0, 3545, 0, + 0, 3669, 0, + 3116, 2370, 3001, + 3116, 2370, 3001, + 3116, 2370, 3001, + 3116, 2371, 3000, + 3116, 2372, 3000, + 3115, 2373, 3000, + 3115, 2374, 2999, + 3114, 2376, 2998, + 3113, 2378, 2997, + 3112, 2381, 2996, + 3110, 2385, 2994, + 3107, 2391, 2992, + 3104, 2398, 2989, + 3100, 2407, 2985, + 3094, 2420, 2979, + 3086, 2436, 2971, + 3075, 2456, 2961, + 3060, 2482, 2946, + 3039, 2515, 2926, + 3010, 2555, 2897, + 2968, 2604, 2856, + 2904, 2662, 2794, + 2802, 2730, 2696, + 2614, 2807, 2518, + 2094, 2893, 2054, + 0, 2987, 0, + 0, 3089, 0, + 0, 3197, 0, + 0, 3310, 0, + 0, 3428, 0, + 0, 3549, 0, + 0, 3672, 0, + 3260, 2429, 3102, + 3260, 2429, 3102, + 3260, 2429, 3101, + 3260, 2430, 3101, + 3260, 2430, 3101, + 3259, 2431, 3101, + 3259, 2432, 3100, + 3258, 2434, 3100, + 3258, 2436, 3099, + 3257, 2439, 3098, + 3255, 2442, 3096, + 3254, 2447, 3095, + 3251, 2453, 3092, + 3248, 2462, 3089, + 3244, 2473, 3084, + 3238, 2487, 3078, + 3231, 2505, 3070, + 3220, 2529, 3058, + 3206, 2558, 3042, + 3185, 2595, 3021, + 3157, 2640, 2989, + 3116, 2694, 2944, + 3054, 2757, 2876, + 2957, 2830, 2764, + 2781, 2913, 2552, + 2327, 3003, 1837, + 0, 3102, 0, + 0, 3207, 0, + 0, 3318, 0, + 0, 3434, 0, + 0, 3553, 0, + 0, 3676, 0, + 3401, 2497, 3209, + 3401, 2497, 3209, + 3401, 2498, 3209, + 3401, 2498, 3208, + 3401, 2499, 3208, + 3400, 2499, 3208, + 3400, 2500, 3208, + 3400, 2502, 3207, + 3399, 2503, 3207, + 3398, 2506, 3206, + 3397, 2509, 3205, + 3396, 2513, 3203, + 3394, 2519, 3201, + 3392, 2526, 3199, + 3389, 2535, 3195, + 3385, 2548, 3190, + 3379, 2564, 3184, + 3372, 2585, 3175, + 3361, 2611, 3163, + 3347, 2644, 3146, + 3328, 2684, 3123, + 3300, 2734, 3089, + 3260, 2792, 3040, + 3200, 2860, 2966, + 3105, 2937, 2842, + 2937, 3024, 2595, + 2521, 3118, 1060, + 0, 3220, 0, + 0, 3329, 0, + 0, 3442, 0, + 0, 3560, 0, + 0, 3680, 0, + 3539, 2575, 3321, + 3539, 2575, 3321, + 3539, 2576, 3321, + 3539, 2576, 3321, + 3539, 2576, 3321, + 3539, 2577, 3321, + 3539, 2578, 3320, + 3538, 2579, 3320, + 3538, 2581, 3320, + 3537, 2582, 3319, + 3537, 2585, 3318, + 3536, 2589, 3317, + 3535, 2593, 3315, + 3533, 2599, 3313, + 3531, 2608, 3311, + 3528, 2618, 3307, + 3524, 2632, 3302, + 3518, 2650, 3295, + 3511, 2673, 3286, + 3500, 2702, 3273, + 3486, 2738, 3255, + 3467, 2782, 3231, + 3440, 2834, 3196, + 3400, 2897, 3144, + 3342, 2969, 3064, + 3249, 3050, 2929, + 3086, 3140, 2646, + 2695, 3237, 0, + 0, 3342, 0, + 0, 3452, 0, + 0, 3568, 0, + 0, 3687, 0, + 3676, 2662, 3438, + 3676, 2662, 3438, + 3676, 2663, 3438, + 3676, 2663, 3438, + 3676, 2663, 3438, + 3676, 2664, 3438, + 3676, 2664, 3438, + 3675, 2665, 3437, + 3675, 2667, 3437, + 3675, 2668, 3436, + 3674, 2670, 3436, + 3674, 2673, 3435, + 3673, 2677, 3434, + 3671, 2682, 3432, + 3670, 2689, 3430, + 3668, 2698, 3427, + 3665, 2710, 3423, + 3661, 2725, 3418, + 3655, 2744, 3411, + 3648, 2769, 3401, + 3638, 2800, 3388, + 3624, 2839, 3370, + 3605, 2886, 3344, + 3578, 2942, 3308, + 3539, 3007, 3253, + 3481, 3082, 3169, + 3390, 3167, 3024, + 3231, 3259, 2706, + 2856, 3359, 0, + 0, 3466, 0, + 0, 3578, 0, + 0, 3695, 0, + 3812, 2757, 3559, + 3812, 2757, 3559, + 3812, 2758, 3559, + 3812, 2758, 3558, + 3812, 2758, 3558, + 3811, 2759, 3558, + 3811, 2759, 3558, + 3811, 2760, 3558, + 3811, 2761, 3558, + 3811, 2762, 3557, + 3810, 2764, 3557, + 3810, 2766, 3556, + 3809, 2770, 3555, + 3808, 2774, 3554, + 3807, 2779, 3552, + 3805, 2787, 3550, + 3803, 2796, 3547, + 3800, 2809, 3543, + 3796, 2825, 3538, + 3791, 2846, 3531, + 3783, 2872, 3521, + 3773, 2905, 3507, + 3760, 2946, 3488, + 3741, 2996, 3462, + 3714, 3054, 3424, + 3675, 3122, 3368, + 3618, 3200, 3279, + 3529, 3287, 3126, + 3372, 3382, 2777, + 3009, 3484, 0, + 0, 3592, 0, + 0, 3706, 0, + 3946, 2860, 3682, + 3946, 2860, 3682, + 3946, 2860, 3682, + 3946, 2860, 3682, + 3946, 2860, 3682, + 3946, 2861, 3682, + 3946, 2861, 3681, + 3946, 2862, 3681, + 3946, 2863, 3681, + 3946, 2864, 3681, + 3945, 2865, 3680, + 3945, 2867, 3680, + 3944, 2869, 3679, + 3944, 2873, 3678, + 3943, 2877, 3677, + 3942, 2883, 3675, + 3940, 2891, 3673, + 3938, 2901, 3670, + 3935, 2914, 3666, + 3931, 2932, 3661, + 3926, 2954, 3653, + 3918, 2981, 3643, + 3908, 3016, 3629, + 3895, 3059, 3610, + 3876, 3110, 3583, + 3849, 3171, 3544, + 3811, 3242, 3486, + 3754, 3321, 3395, + 3666, 3410, 3235, + 3511, 3507, 2856, + 3156, 3610, 0, + 0, 3720, 0, + 4080, 2968, 3807, + 4080, 2968, 3807, + 4080, 2968, 3807, + 4080, 2969, 3807, + 4080, 2969, 3807, + 4080, 2969, 3807, + 4080, 2969, 3807, + 4080, 2970, 3807, + 4080, 2970, 3806, + 4080, 2971, 3806, + 4080, 2972, 3806, + 4079, 2974, 3806, + 4079, 2976, 3805, + 4078, 2979, 3804, + 4078, 2982, 3803, + 4077, 2987, 3802, + 4076, 2993, 3800, + 4074, 3001, 3798, + 4072, 3012, 3795, + 4069, 3026, 3791, + 4065, 3044, 3786, + 4060, 3067, 3778, + 4052, 3096, 3768, + 4042, 3132, 3754, + 4029, 3176, 3734, + 4010, 3229, 3706, + 3984, 3292, 3667, + 3946, 3364, 3608, + 3889, 3445, 3514, + 3801, 3535, 3348, + 3648, 3633, 2944, + 3299, 3738, 0, + 4095, 3082, 3934, + 4095, 3082, 3934, + 4095, 3082, 3934, + 4095, 3082, 3934, + 4095, 3082, 3934, + 4095, 3082, 3934, + 4095, 3083, 3934, + 4095, 3083, 3934, + 4095, 3084, 3934, + 4095, 3084, 3933, + 4095, 3085, 3933, + 4095, 3086, 3933, + 4095, 3088, 3932, + 4095, 3090, 3932, + 4095, 3093, 3931, + 4095, 3096, 3930, + 4095, 3101, 3929, + 4095, 3108, 3927, + 4095, 3116, 3925, + 4095, 3127, 3922, + 4095, 3142, 3918, + 4095, 3160, 3912, + 4095, 3184, 3905, + 4095, 3214, 3894, + 4095, 3251, 3880, + 4095, 3297, 3860, + 4095, 3351, 3832, + 4095, 3415, 3792, + 4080, 3488, 3732, + 4024, 3571, 3636, + 3936, 3662, 3466, + 3784, 3761, 3041, + 4095, 3200, 4062, + 4095, 3200, 4062, + 4095, 3200, 4062, + 4095, 3200, 4062, + 4095, 3200, 4062, + 4095, 3200, 4062, + 4095, 3200, 4062, + 4095, 3201, 4062, + 4095, 3201, 4062, + 4095, 3202, 4062, + 4095, 3202, 4062, + 4095, 3203, 4061, + 4095, 3204, 4061, + 4095, 3206, 4061, + 4095, 3208, 4060, + 4095, 3211, 4059, + 4095, 3215, 4058, + 4095, 3220, 4057, + 4095, 3226, 4055, + 4095, 3235, 4053, + 4095, 3247, 4050, + 4095, 3261, 4046, + 4095, 3280, 4040, + 4095, 3305, 4032, + 4095, 3335, 4022, + 4095, 3374, 4008, + 4095, 3420, 3988, + 4095, 3475, 3959, + 4095, 3540, 3918, + 4095, 3614, 3858, + 4095, 3698, 3761, + 4070, 3790, 3587, + 0, 2261, 2529, + 0, 2261, 2529, + 0, 2262, 2529, + 0, 2263, 2528, + 0, 2264, 2527, + 0, 2265, 2526, + 0, 2267, 2524, + 0, 2269, 2522, + 0, 2272, 2520, + 0, 2276, 2516, + 0, 2281, 2511, + 0, 2288, 2504, + 0, 2297, 2495, + 0, 2308, 2482, + 0, 2324, 2465, + 0, 2343, 2440, + 0, 2368, 2405, + 0, 2400, 2354, + 0, 2439, 2274, + 0, 2486, 2140, + 0, 2542, 1860, + 0, 2608, 0, + 0, 2684, 0, + 0, 2768, 0, + 0, 2861, 0, + 0, 2962, 0, + 0, 3069, 0, + 0, 3181, 0, + 0, 3298, 0, + 0, 3418, 0, + 0, 3541, 0, + 0, 3667, 0, + 0, 2261, 2530, + 0, 2262, 2530, + 0, 2262, 2529, + 0, 2263, 2529, + 0, 2264, 2528, + 0, 2265, 2527, + 0, 2267, 2525, + 0, 2269, 2523, + 0, 2272, 2520, + 0, 2276, 2517, + 0, 2281, 2512, + 0, 2288, 2505, + 0, 2297, 2495, + 0, 2309, 2483, + 0, 2324, 2465, + 0, 2343, 2441, + 0, 2368, 2406, + 0, 2400, 2354, + 0, 2439, 2275, + 0, 2486, 2141, + 0, 2543, 1863, + 0, 2608, 0, + 0, 2684, 0, + 0, 2769, 0, + 0, 2862, 0, + 0, 2962, 0, + 0, 3069, 0, + 0, 3181, 0, + 0, 3298, 0, + 0, 3418, 0, + 0, 3541, 0, + 0, 3667, 0, + 0, 2261, 2531, + 0, 2262, 2530, + 0, 2262, 2530, + 0, 2263, 2529, + 0, 2264, 2528, + 0, 2265, 2527, + 0, 2267, 2526, + 0, 2269, 2524, + 0, 2272, 2521, + 0, 2276, 2517, + 0, 2281, 2512, + 0, 2288, 2505, + 0, 2297, 2496, + 0, 2309, 2484, + 0, 2324, 2466, + 0, 2344, 2442, + 0, 2369, 2407, + 0, 2400, 2355, + 0, 2439, 2276, + 0, 2486, 2143, + 0, 2543, 1866, + 0, 2609, 0, + 0, 2684, 0, + 0, 2769, 0, + 0, 2862, 0, + 0, 2962, 0, + 0, 3069, 0, + 0, 3181, 0, + 0, 3298, 0, + 0, 3418, 0, + 0, 3541, 0, + 0, 3667, 0, + 0, 2262, 2532, + 0, 2262, 2531, + 0, 2263, 2531, + 0, 2263, 2530, + 0, 2264, 2529, + 0, 2265, 2528, + 0, 2267, 2527, + 0, 2269, 2525, + 0, 2272, 2522, + 0, 2276, 2518, + 0, 2281, 2513, + 0, 2288, 2506, + 0, 2297, 2497, + 0, 2309, 2485, + 0, 2324, 2467, + 0, 2344, 2443, + 0, 2369, 2408, + 0, 2400, 2357, + 0, 2439, 2278, + 0, 2486, 2145, + 0, 2543, 1870, + 0, 2609, 0, + 0, 2684, 0, + 0, 2769, 0, + 0, 2862, 0, + 0, 2962, 0, + 0, 3069, 0, + 0, 3181, 0, + 0, 3298, 0, + 0, 3418, 0, + 0, 3541, 0, + 0, 3667, 0, + 0, 2262, 2533, + 0, 2262, 2533, + 0, 2263, 2532, + 0, 2264, 2531, + 0, 2264, 2531, + 0, 2266, 2529, + 0, 2267, 2528, + 0, 2270, 2526, + 0, 2273, 2523, + 0, 2276, 2520, + 0, 2282, 2515, + 0, 2288, 2508, + 0, 2297, 2499, + 0, 2309, 2486, + 0, 2324, 2469, + 0, 2344, 2444, + 0, 2369, 2410, + 0, 2400, 2359, + 0, 2439, 2280, + 0, 2487, 2148, + 0, 2543, 1875, + 0, 2609, 0, + 0, 2684, 0, + 0, 2769, 0, + 0, 2862, 0, + 0, 2962, 0, + 0, 3069, 0, + 0, 3181, 0, + 0, 3298, 0, + 0, 3418, 0, + 0, 3541, 0, + 0, 3667, 0, + 0, 2262, 2535, + 0, 2263, 2534, + 0, 2263, 2534, + 0, 2264, 2533, + 0, 2265, 2532, + 0, 2266, 2531, + 0, 2268, 2530, + 0, 2270, 2528, + 0, 2273, 2525, + 0, 2277, 2521, + 0, 2282, 2516, + 0, 2289, 2510, + 0, 2298, 2500, + 0, 2310, 2488, + 0, 2325, 2471, + 0, 2344, 2446, + 0, 2369, 2412, + 0, 2401, 2361, + 0, 2440, 2283, + 0, 2487, 2152, + 0, 2543, 1882, + 0, 2609, 0, + 0, 2684, 0, + 0, 2769, 0, + 0, 2862, 0, + 0, 2962, 0, + 0, 3069, 0, + 0, 3181, 0, + 0, 3298, 0, + 0, 3418, 0, + 0, 3541, 0, + 0, 3667, 0, + 0, 2263, 2537, + 0, 2263, 2537, + 0, 2264, 2536, + 0, 2265, 2535, + 0, 2265, 2535, + 0, 2267, 2533, + 0, 2268, 2532, + 0, 2271, 2530, + 0, 2274, 2527, + 0, 2277, 2524, + 0, 2283, 2519, + 0, 2289, 2512, + 0, 2298, 2503, + 0, 2310, 2490, + 0, 2325, 2473, + 0, 2345, 2449, + 0, 2370, 2415, + 0, 2401, 2364, + 0, 2440, 2287, + 0, 2487, 2157, + 0, 2543, 1892, + 0, 2609, 0, + 0, 2685, 0, + 0, 2769, 0, + 0, 2862, 0, + 0, 2962, 0, + 0, 3069, 0, + 0, 3182, 0, + 0, 3298, 0, + 0, 3418, 0, + 0, 3542, 0, + 0, 3667, 0, + 0, 2264, 2540, + 0, 2264, 2539, + 0, 2265, 2539, + 0, 2265, 2538, + 0, 2266, 2538, + 0, 2267, 2536, + 0, 2269, 2535, + 0, 2271, 2533, + 0, 2274, 2530, + 0, 2278, 2527, + 0, 2283, 2522, + 0, 2290, 2515, + 0, 2299, 2506, + 0, 2311, 2494, + 0, 2326, 2477, + 0, 2346, 2453, + 0, 2370, 2419, + 0, 2402, 2369, + 0, 2440, 2292, + 0, 2488, 2164, + 0, 2544, 1904, + 0, 2610, 0, + 0, 2685, 0, + 0, 2769, 0, + 0, 2862, 0, + 0, 2963, 0, + 0, 3069, 0, + 0, 3182, 0, + 0, 3298, 0, + 0, 3419, 0, + 0, 3542, 0, + 0, 3667, 0, + 0, 2265, 2544, + 0, 2265, 2543, + 0, 2266, 2543, + 0, 2266, 2542, + 0, 2267, 2542, + 0, 2268, 2540, + 0, 2270, 2539, + 0, 2272, 2537, + 0, 2275, 2534, + 0, 2279, 2531, + 0, 2284, 2526, + 0, 2291, 2519, + 0, 2300, 2510, + 0, 2312, 2498, + 0, 2327, 2481, + 0, 2346, 2458, + 0, 2371, 2424, + 0, 2402, 2375, + 0, 2441, 2299, + 0, 2488, 2173, + 0, 2544, 1920, + 0, 2610, 0, + 0, 2685, 0, + 0, 2770, 0, + 0, 2862, 0, + 0, 2963, 0, + 0, 3070, 0, + 0, 3182, 0, + 0, 3298, 0, + 0, 3419, 0, + 0, 3542, 0, + 0, 3667, 0, + 0, 2266, 2549, + 0, 2266, 2549, + 0, 2267, 2548, + 0, 2268, 2548, + 0, 2269, 2547, + 0, 2270, 2546, + 0, 2271, 2544, + 0, 2274, 2542, + 0, 2277, 2540, + 0, 2280, 2536, + 0, 2286, 2531, + 0, 2292, 2525, + 0, 2301, 2516, + 0, 2313, 2504, + 0, 2328, 2487, + 0, 2348, 2464, + 0, 2372, 2431, + 0, 2403, 2382, + 0, 2442, 2308, + 0, 2489, 2185, + 0, 2545, 1940, + 0, 2611, 542, + 0, 2686, 0, + 0, 2770, 0, + 0, 2863, 0, + 0, 2963, 0, + 0, 3070, 0, + 0, 3182, 0, + 0, 3299, 0, + 0, 3419, 0, + 0, 3542, 0, + 0, 3667, 0, + 0, 2268, 2556, + 0, 2268, 2556, + 0, 2269, 2555, + 0, 2269, 2555, + 0, 2270, 2554, + 0, 2272, 2553, + 0, 2273, 2551, + 0, 2275, 2549, + 0, 2278, 2547, + 0, 2282, 2543, + 0, 2287, 2538, + 0, 2294, 2532, + 0, 2303, 2523, + 0, 2315, 2512, + 0, 2330, 2495, + 0, 2349, 2472, + 0, 2374, 2440, + 0, 2405, 2392, + 0, 2443, 2320, + 0, 2490, 2200, + 0, 2546, 1966, + 0, 2612, 914, + 0, 2687, 0, + 0, 2771, 0, + 0, 2863, 0, + 0, 2963, 0, + 0, 3070, 0, + 0, 3182, 0, + 0, 3299, 0, + 0, 3419, 0, + 0, 3542, 0, + 0, 3667, 0, + 0, 2270, 2565, + 0, 2271, 2565, + 0, 2271, 2564, + 0, 2272, 2564, + 0, 2273, 2563, + 0, 2274, 2562, + 0, 2276, 2560, + 0, 2278, 2559, + 0, 2281, 2556, + 0, 2285, 2553, + 0, 2290, 2548, + 0, 2296, 2542, + 0, 2305, 2533, + 0, 2317, 2522, + 0, 2332, 2505, + 0, 2351, 2483, + 0, 2376, 2451, + 0, 2407, 2405, + 0, 2445, 2335, + 0, 2492, 2220, + 0, 2547, 1998, + 0, 2613, 1168, + 0, 2688, 0, + 0, 2772, 0, + 0, 2864, 0, + 0, 2964, 0, + 0, 3071, 0, + 0, 3183, 0, + 0, 3299, 0, + 0, 3419, 0, + 0, 3542, 0, + 0, 3667, 0, + 0, 2273, 2577, + 0, 2274, 2577, + 0, 2274, 2576, + 0, 2275, 2576, + 0, 2276, 2575, + 0, 2277, 2574, + 0, 2279, 2572, + 0, 2281, 2571, + 0, 2284, 2568, + 0, 2288, 2565, + 0, 2293, 2560, + 0, 2299, 2554, + 0, 2308, 2546, + 0, 2320, 2535, + 0, 2335, 2519, + 0, 2354, 2497, + 0, 2378, 2467, + 0, 2409, 2422, + 0, 2447, 2354, + 0, 2494, 2245, + 0, 2549, 2038, + 0, 2614, 1374, + 0, 2689, 0, + 0, 2773, 0, + 0, 2865, 0, + 0, 2965, 0, + 0, 3071, 0, + 0, 3183, 0, + 0, 3299, 0, + 0, 3419, 0, + 0, 3542, 0, + 0, 3667, 0, + 0, 2278, 2592, + 0, 2278, 2592, + 0, 2279, 2592, + 0, 2279, 2591, + 0, 2280, 2590, + 0, 2281, 2589, + 0, 2283, 2588, + 0, 2285, 2586, + 0, 2288, 2584, + 0, 2292, 2581, + 0, 2297, 2576, + 0, 2303, 2570, + 0, 2312, 2562, + 0, 2323, 2551, + 0, 2338, 2536, + 0, 2357, 2516, + 0, 2382, 2486, + 0, 2412, 2443, + 0, 2450, 2379, + 0, 2496, 2276, + 0, 2551, 2087, + 0, 2616, 1554, + 0, 2690, 0, + 0, 2774, 0, + 0, 2866, 0, + 0, 2966, 0, + 0, 3072, 0, + 0, 3184, 0, + 0, 3300, 0, + 0, 3420, 0, + 0, 3542, 0, + 0, 3667, 0, + 0, 2283, 2612, + 0, 2284, 2612, + 0, 2284, 2611, + 0, 2285, 2611, + 0, 2286, 2610, + 0, 2287, 2609, + 0, 2289, 2608, + 0, 2291, 2606, + 0, 2293, 2604, + 0, 2297, 2601, + 0, 2302, 2597, + 0, 2309, 2591, + 0, 2317, 2584, + 0, 2329, 2573, + 0, 2343, 2559, + 0, 2362, 2539, + 0, 2386, 2511, + 0, 2416, 2471, + 0, 2454, 2410, + 0, 2500, 2315, + 0, 2555, 2145, + 0, 2619, 1719, + 0, 2693, 0, + 0, 2776, 0, + 0, 2868, 0, + 0, 2967, 0, + 0, 3073, 0, + 0, 3184, 0, + 0, 3300, 0, + 0, 3420, 0, + 0, 3543, 0, + 0, 3668, 0, + 746, 2291, 2637, + 722, 2291, 2637, + 688, 2292, 2637, + 637, 2292, 2636, + 559, 2293, 2636, + 428, 2294, 2635, + 158, 2296, 2633, + 0, 2298, 2632, + 0, 2301, 2630, + 0, 2304, 2627, + 0, 2309, 2623, + 0, 2316, 2618, + 0, 2324, 2610, + 0, 2335, 2601, + 0, 2350, 2587, + 0, 2368, 2568, + 0, 2392, 2542, + 0, 2422, 2505, + 0, 2459, 2449, + 0, 2504, 2362, + 0, 2559, 2212, + 0, 2622, 1874, + 0, 2696, 0, + 0, 2778, 0, + 0, 2870, 0, + 0, 2969, 0, + 0, 3074, 0, + 0, 3185, 0, + 0, 3301, 0, + 0, 3421, 0, + 0, 3543, 0, + 0, 3668, 0, + 1791, 2300, 2669, + 1789, 2301, 2669, + 1785, 2301, 2668, + 1781, 2302, 2668, + 1775, 2303, 2667, + 1767, 2304, 2667, + 1757, 2305, 2665, + 1742, 2307, 2664, + 1721, 2310, 2662, + 1692, 2314, 2659, + 1650, 2319, 2656, + 1586, 2325, 2651, + 1485, 2333, 2644, + 1300, 2344, 2635, + 793, 2358, 2622, + 0, 2376, 2605, + 0, 2400, 2581, + 0, 2429, 2547, + 0, 2466, 2496, + 0, 2510, 2419, + 0, 2564, 2289, + 0, 2627, 2023, + 0, 2700, 0, + 0, 2782, 0, + 0, 2872, 0, + 0, 2971, 0, + 0, 3076, 0, + 0, 3187, 0, + 0, 3302, 0, + 0, 3422, 0, + 0, 3544, 0, + 0, 3668, 0, + 2150, 2313, 2708, + 2149, 2313, 2708, + 2147, 2314, 2708, + 2145, 2314, 2707, + 2143, 2315, 2707, + 2139, 2316, 2706, + 2135, 2318, 2705, + 2128, 2320, 2704, + 2119, 2323, 2702, + 2108, 2326, 2699, + 2091, 2331, 2696, + 2068, 2337, 2691, + 2036, 2345, 2685, + 1988, 2356, 2677, + 1915, 2369, 2666, + 1795, 2387, 2650, + 1560, 2410, 2628, + 480, 2439, 2597, + 0, 2474, 2553, + 0, 2518, 2485, + 0, 2571, 2375, + 0, 2633, 2167, + 0, 2705, 1492, + 0, 2786, 0, + 0, 2876, 0, + 0, 2974, 0, + 0, 3078, 0, + 0, 3189, 0, + 0, 3304, 0, + 0, 3423, 0, + 0, 3545, 0, + 0, 3669, 0, + 2399, 2329, 2756, + 2398, 2330, 2756, + 2398, 2330, 2755, + 2396, 2331, 2755, + 2395, 2332, 2754, + 2393, 2333, 2754, + 2390, 2334, 2753, + 2387, 2336, 2752, + 2382, 2339, 2750, + 2375, 2342, 2748, + 2366, 2346, 2745, + 2354, 2352, 2741, + 2337, 2360, 2735, + 2313, 2370, 2728, + 2278, 2384, 2718, + 2228, 2401, 2704, + 2151, 2423, 2684, + 2023, 2451, 2657, + 1760, 2486, 2618, + 0, 2529, 2560, + 0, 2581, 2469, + 0, 2642, 2308, + 0, 2712, 1927, + 0, 2792, 0, + 0, 2881, 0, + 0, 2978, 0, + 0, 3081, 0, + 0, 3191, 0, + 0, 3306, 0, + 0, 3424, 0, + 0, 3546, 0, + 0, 3670, 0, + 2602, 2350, 2813, + 2602, 2351, 2812, + 2602, 2351, 2812, + 2601, 2352, 2812, + 2600, 2353, 2811, + 2599, 2354, 2811, + 2597, 2355, 2810, + 2595, 2357, 2809, + 2591, 2359, 2807, + 2587, 2362, 2805, + 2582, 2367, 2803, + 2574, 2372, 2799, + 2563, 2380, 2794, + 2549, 2390, 2788, + 2529, 2402, 2779, + 2501, 2419, 2767, + 2460, 2440, 2750, + 2400, 2467, 2727, + 2303, 2501, 2694, + 2131, 2543, 2645, + 1693, 2593, 2570, + 0, 2652, 2447, + 0, 2721, 2200, + 0, 2800, 714, + 0, 2887, 0, + 0, 2983, 0, + 0, 3085, 0, + 0, 3194, 0, + 0, 3308, 0, + 0, 3426, 0, + 0, 3547, 0, + 0, 3671, 0, + 2781, 2377, 2879, + 2781, 2377, 2879, + 2781, 2378, 2879, + 2780, 2378, 2878, + 2780, 2379, 2878, + 2779, 2380, 2877, + 2778, 2381, 2877, + 2776, 2383, 2876, + 2774, 2385, 2874, + 2771, 2388, 2873, + 2767, 2392, 2870, + 2762, 2398, 2867, + 2755, 2405, 2863, + 2746, 2414, 2858, + 2733, 2426, 2850, + 2715, 2442, 2840, + 2691, 2462, 2826, + 2655, 2488, 2806, + 2602, 2520, 2778, + 2521, 2560, 2738, + 2384, 2609, 2678, + 2092, 2666, 2584, + 0, 2733, 2415, + 0, 2810, 1999, + 0, 2895, 0, + 0, 2989, 0, + 0, 3091, 0, + 0, 3198, 0, + 0, 3311, 0, + 0, 3429, 0, + 0, 3549, 0, + 0, 3673, 0, + 2946, 2411, 2955, + 2945, 2411, 2955, + 2945, 2411, 2954, + 2945, 2412, 2954, + 2944, 2412, 2954, + 2944, 2413, 2953, + 2943, 2414, 2953, + 2942, 2416, 2952, + 2940, 2418, 2951, + 2939, 2421, 2950, + 2936, 2425, 2948, + 2932, 2430, 2945, + 2928, 2436, 2942, + 2921, 2445, 2937, + 2913, 2456, 2930, + 2901, 2471, 2922, + 2884, 2490, 2910, + 2861, 2514, 2894, + 2829, 2545, 2871, + 2781, 2583, 2838, + 2709, 2629, 2791, + 2589, 2684, 2719, + 2354, 2749, 2601, + 1291, 2823, 2369, + 0, 2906, 1378, + 0, 2998, 0, + 0, 3098, 0, + 0, 3204, 0, + 0, 3316, 0, + 0, 3432, 0, + 0, 3552, 0, + 0, 3675, 0, + 3100, 2452, 3040, + 3100, 2452, 3040, + 3100, 2452, 3039, + 3100, 2453, 3039, + 3099, 2453, 3039, + 3099, 2454, 3039, + 3098, 2455, 3038, + 3098, 2457, 3037, + 3097, 2459, 3037, + 3095, 2461, 3035, + 3093, 2465, 3034, + 3091, 2469, 3032, + 3088, 2475, 3029, + 3083, 2483, 3025, + 3077, 2494, 3020, + 3069, 2507, 3013, + 3058, 2525, 3003, + 3042, 2547, 2990, + 3020, 2576, 2971, + 2990, 2611, 2945, + 2945, 2655, 2909, + 2878, 2707, 2854, + 2769, 2769, 2769, + 2564, 2840, 2622, + 1912, 2921, 2300, + 0, 3010, 0, + 0, 3107, 0, + 0, 3212, 0, + 0, 3322, 0, + 0, 3437, 0, + 0, 3555, 0, + 0, 3677, 0, + 3249, 2501, 3133, + 3248, 2502, 3133, + 3248, 2502, 3133, + 3248, 2502, 3133, + 3248, 2503, 3132, + 3248, 2504, 3132, + 3247, 2505, 3132, + 3247, 2506, 3131, + 3246, 2508, 3130, + 3245, 2510, 3129, + 3244, 2513, 3128, + 3242, 2517, 3126, + 3239, 2523, 3124, + 3236, 2530, 3121, + 3232, 2539, 3117, + 3226, 2552, 3111, + 3218, 2568, 3103, + 3207, 2588, 3093, + 3192, 2614, 3078, + 3172, 2647, 3058, + 3142, 2687, 3029, + 3100, 2736, 2988, + 3036, 2794, 2926, + 2934, 2862, 2828, + 2746, 2939, 2650, + 2226, 3025, 2186, + 0, 3120, 0, + 0, 3221, 0, + 0, 3329, 0, + 0, 3443, 0, + 0, 3560, 0, + 0, 3681, 0, + 3392, 2560, 3234, + 3392, 2561, 3234, + 3392, 2561, 3234, + 3392, 2561, 3233, + 3392, 2562, 3233, + 3392, 2562, 3233, + 3391, 2563, 3233, + 3391, 2564, 3232, + 3391, 2566, 3232, + 3390, 2568, 3231, + 3389, 2571, 3230, + 3388, 2574, 3229, + 3386, 2579, 3227, + 3383, 2586, 3224, + 3380, 2594, 3221, + 3376, 2605, 3216, + 3370, 2619, 3210, + 3363, 2637, 3202, + 3352, 2661, 3190, + 3338, 2691, 3175, + 3317, 2727, 3153, + 3289, 2772, 3121, + 3248, 2826, 3076, + 3187, 2890, 3008, + 3089, 2962, 2896, + 2913, 3045, 2685, + 2459, 3135, 1969, + 0, 3234, 0, + 0, 3339, 0, + 0, 3450, 0, + 0, 3566, 0, + 0, 3685, 0, + 3533, 2629, 3341, + 3533, 2629, 3341, + 3533, 2629, 3341, + 3533, 2630, 3341, + 3533, 2630, 3341, + 3533, 2631, 3340, + 3532, 2631, 3340, + 3532, 2632, 3340, + 3532, 2634, 3339, + 3531, 2636, 3339, + 3530, 2638, 3338, + 3530, 2641, 3337, + 3528, 2645, 3335, + 3527, 2651, 3333, + 3524, 2658, 3331, + 3521, 2668, 3327, + 3517, 2680, 3322, + 3512, 2696, 3316, + 3504, 2717, 3307, + 3494, 2743, 3295, + 3479, 2776, 3278, + 3460, 2817, 3255, + 3432, 2866, 3221, + 3392, 2924, 3173, + 3332, 2992, 3098, + 3237, 3069, 2974, + 3069, 3156, 2727, + 2654, 3251, 1192, + 0, 3353, 0, + 0, 3461, 0, + 0, 3574, 0, + 0, 3692, 0, + 3672, 2707, 3453, + 3672, 2707, 3453, + 3671, 2707, 3453, + 3671, 2708, 3453, + 3671, 2708, 3453, + 3671, 2709, 3453, + 3671, 2709, 3453, + 3671, 2710, 3453, + 3671, 2711, 3452, + 3670, 2713, 3452, + 3670, 2715, 3451, + 3669, 2717, 3450, + 3668, 2721, 3449, + 3667, 2725, 3448, + 3665, 2732, 3446, + 3663, 2740, 3443, + 3660, 2750, 3439, + 3656, 2764, 3434, + 3650, 2782, 3427, + 3643, 2805, 3418, + 3633, 2834, 3405, + 3619, 2870, 3388, + 3599, 2914, 3363, + 3572, 2967, 3328, + 3532, 3029, 3276, + 3474, 3101, 3196, + 3382, 3182, 3061, + 3218, 3272, 2778, + 2827, 3370, 0, + 0, 3474, 0, + 0, 3585, 0, + 0, 3700, 0, + 3808, 2794, 3570, + 3808, 2794, 3570, + 3808, 2794, 3570, + 3808, 2795, 3570, + 3808, 2795, 3570, + 3808, 2795, 3570, + 3808, 2796, 3570, + 3808, 2796, 3570, + 3808, 2797, 3569, + 3807, 2799, 3569, + 3807, 2800, 3569, + 3806, 2803, 3568, + 3806, 2805, 3567, + 3805, 2809, 3566, + 3804, 2814, 3564, + 3802, 2821, 3562, + 3800, 2830, 3559, + 3797, 2842, 3555, + 3793, 2857, 3550, + 3787, 2876, 3543, + 3780, 2901, 3533, + 3770, 2932, 3520, + 3756, 2971, 3502, + 3737, 3018, 3476, + 3710, 3074, 3440, + 3671, 3139, 3385, + 3613, 3214, 3301, + 3522, 3299, 3156, + 3363, 3391, 2839, + 2989, 3492, 0, + 0, 3598, 0, + 0, 3710, 0, + 3944, 2889, 3691, + 3944, 2889, 3691, + 3944, 2890, 3691, + 3944, 2890, 3691, + 3944, 2890, 3691, + 3944, 2890, 3691, + 3944, 2891, 3690, + 3943, 2891, 3690, + 3943, 2892, 3690, + 3943, 2893, 3690, + 3943, 2894, 3689, + 3942, 2896, 3689, + 3942, 2898, 3688, + 3941, 2902, 3687, + 3940, 2906, 3686, + 3939, 2911, 3684, + 3937, 2919, 3682, + 3935, 2928, 3679, + 3932, 2941, 3675, + 3928, 2957, 3670, + 3923, 2978, 3663, + 3916, 3004, 3653, + 3906, 3037, 3639, + 3892, 3078, 3620, + 3873, 3128, 3594, + 3846, 3186, 3556, + 3808, 3255, 3500, + 3750, 3332, 3412, + 3661, 3419, 3258, + 3504, 3514, 2909, + 3141, 3616, 0, + 0, 3724, 0, + 4079, 2992, 3814, + 4079, 2992, 3814, + 4078, 2992, 3814, + 4078, 2992, 3814, + 4078, 2992, 3814, + 4078, 2992, 3814, + 4078, 2993, 3814, + 4078, 2993, 3813, + 4078, 2994, 3813, + 4078, 2995, 3813, + 4078, 2996, 3813, + 4077, 2997, 3812, + 4077, 2999, 3812, + 4077, 3002, 3811, + 4076, 3005, 3810, + 4075, 3009, 3809, + 4074, 3015, 3807, + 4072, 3023, 3805, + 4070, 3033, 3802, + 4067, 3047, 3798, + 4063, 3064, 3793, + 4058, 3086, 3785, + 4050, 3114, 3775, + 4040, 3148, 3761, + 4027, 3191, 3742, + 4008, 3242, 3715, + 3981, 3303, 3676, + 3943, 3374, 3618, + 3886, 3453, 3527, + 3798, 3542, 3367, + 3643, 3639, 2988, + 3288, 3742, 0, + 4095, 3100, 3939, + 4095, 3100, 3939, + 4095, 3100, 3939, + 4095, 3101, 3939, + 4095, 3101, 3939, + 4095, 3101, 3939, + 4095, 3101, 3939, + 4095, 3101, 3939, + 4095, 3102, 3939, + 4095, 3103, 3939, + 4095, 3103, 3938, + 4095, 3105, 3938, + 4095, 3106, 3938, + 4095, 3108, 3937, + 4095, 3111, 3936, + 4095, 3114, 3936, + 4095, 3119, 3934, + 4095, 3125, 3933, + 4095, 3133, 3930, + 4095, 3144, 3927, + 4095, 3158, 3923, + 4095, 3176, 3918, + 4095, 3199, 3910, + 4095, 3228, 3900, + 4095, 3264, 3886, + 4095, 3308, 3866, + 4095, 3361, 3839, + 4095, 3424, 3799, + 4078, 3496, 3740, + 4021, 3577, 3646, + 3933, 3667, 3480, + 3780, 3765, 3076, + 4095, 3214, 4066, + 4095, 3214, 4066, + 4095, 3214, 4066, + 4095, 3214, 4066, + 4095, 3214, 4066, + 4095, 3214, 4066, + 4095, 3215, 4066, + 4095, 3215, 4066, + 4095, 3215, 4066, + 4095, 3216, 4066, + 4095, 3216, 4066, + 4095, 3217, 4065, + 4095, 3218, 4065, + 4095, 3220, 4065, + 4095, 3222, 4064, + 4095, 3225, 4063, + 4095, 3229, 4062, + 4095, 3233, 4061, + 4095, 3240, 4059, + 4095, 3248, 4057, + 4095, 3259, 4054, + 4095, 3274, 4050, + 4095, 3292, 4044, + 4095, 3316, 4037, + 4095, 3346, 4026, + 4095, 3383, 4012, + 4095, 3429, 3992, + 4095, 3483, 3964, + 4095, 3547, 3924, + 4095, 3620, 3864, + 4095, 3703, 3768, + 4068, 3794, 3598, + 0, 2393, 2661, + 0, 2393, 2661, + 0, 2393, 2661, + 0, 2394, 2660, + 0, 2395, 2660, + 0, 2396, 2659, + 0, 2397, 2658, + 0, 2399, 2656, + 0, 2401, 2654, + 0, 2404, 2651, + 0, 2408, 2648, + 0, 2413, 2643, + 0, 2420, 2636, + 0, 2429, 2627, + 0, 2440, 2614, + 0, 2456, 2596, + 0, 2475, 2572, + 0, 2500, 2537, + 0, 2532, 2485, + 0, 2571, 2406, + 0, 2618, 2271, + 0, 2674, 1991, + 0, 2740, 0, + 0, 2816, 0, + 0, 2901, 0, + 0, 2994, 0, + 0, 3094, 0, + 0, 3201, 0, + 0, 3313, 0, + 0, 3430, 0, + 0, 3550, 0, + 0, 3673, 0, + 0, 2393, 2662, + 0, 2393, 2662, + 0, 2394, 2661, + 0, 2394, 2661, + 0, 2395, 2660, + 0, 2396, 2659, + 0, 2397, 2658, + 0, 2399, 2657, + 0, 2401, 2655, + 0, 2404, 2652, + 0, 2408, 2648, + 0, 2413, 2643, + 0, 2420, 2636, + 0, 2429, 2627, + 0, 2441, 2614, + 0, 2456, 2597, + 0, 2475, 2572, + 0, 2500, 2537, + 0, 2532, 2486, + 0, 2571, 2406, + 0, 2618, 2272, + 0, 2675, 1992, + 0, 2740, 0, + 0, 2816, 0, + 0, 2901, 0, + 0, 2994, 0, + 0, 3094, 0, + 0, 3201, 0, + 0, 3313, 0, + 0, 3430, 0, + 0, 3550, 0, + 0, 3673, 0, + 0, 2393, 2662, + 0, 2393, 2662, + 0, 2394, 2662, + 0, 2394, 2661, + 0, 2395, 2661, + 0, 2396, 2660, + 0, 2397, 2659, + 0, 2399, 2657, + 0, 2401, 2655, + 0, 2404, 2652, + 0, 2408, 2649, + 0, 2413, 2644, + 0, 2420, 2637, + 0, 2429, 2628, + 0, 2441, 2615, + 0, 2456, 2597, + 0, 2476, 2573, + 0, 2501, 2538, + 0, 2532, 2487, + 0, 2571, 2407, + 0, 2618, 2273, + 0, 2675, 1995, + 0, 2741, 0, + 0, 2816, 0, + 0, 2901, 0, + 0, 2994, 0, + 0, 3094, 0, + 0, 3201, 0, + 0, 3313, 0, + 0, 3430, 0, + 0, 3550, 0, + 0, 3673, 0, + 0, 2393, 2663, + 0, 2393, 2663, + 0, 2394, 2662, + 0, 2394, 2662, + 0, 2395, 2661, + 0, 2396, 2661, + 0, 2397, 2659, + 0, 2399, 2658, + 0, 2401, 2656, + 0, 2404, 2653, + 0, 2408, 2649, + 0, 2413, 2644, + 0, 2420, 2638, + 0, 2429, 2628, + 0, 2441, 2616, + 0, 2456, 2598, + 0, 2476, 2574, + 0, 2501, 2539, + 0, 2532, 2488, + 0, 2571, 2408, + 0, 2618, 2275, + 0, 2675, 1998, + 0, 2741, 0, + 0, 2816, 0, + 0, 2901, 0, + 0, 2994, 0, + 0, 3094, 0, + 0, 3201, 0, + 0, 3313, 0, + 0, 3430, 0, + 0, 3550, 0, + 0, 3674, 0, + 0, 2393, 2664, + 0, 2394, 2664, + 0, 2394, 2663, + 0, 2395, 2663, + 0, 2395, 2662, + 0, 2396, 2661, + 0, 2398, 2660, + 0, 2399, 2659, + 0, 2401, 2657, + 0, 2404, 2654, + 0, 2408, 2650, + 0, 2413, 2645, + 0, 2420, 2639, + 0, 2429, 2629, + 0, 2441, 2617, + 0, 2456, 2599, + 0, 2476, 2575, + 0, 2501, 2540, + 0, 2532, 2489, + 0, 2571, 2410, + 0, 2618, 2277, + 0, 2675, 2002, + 0, 2741, 0, + 0, 2816, 0, + 0, 2901, 0, + 0, 2994, 0, + 0, 3094, 0, + 0, 3201, 0, + 0, 3313, 0, + 0, 3430, 0, + 0, 3550, 0, + 0, 3674, 0, + 0, 2394, 2665, + 0, 2394, 2665, + 0, 2394, 2665, + 0, 2395, 2664, + 0, 2396, 2664, + 0, 2397, 2663, + 0, 2398, 2662, + 0, 2399, 2660, + 0, 2402, 2658, + 0, 2405, 2655, + 0, 2409, 2652, + 0, 2414, 2647, + 0, 2421, 2640, + 0, 2430, 2631, + 0, 2441, 2618, + 0, 2457, 2601, + 0, 2476, 2576, + 0, 2501, 2542, + 0, 2533, 2491, + 0, 2571, 2412, + 0, 2619, 2280, + 0, 2675, 2007, + 0, 2741, 0, + 0, 2816, 0, + 0, 2901, 0, + 0, 2994, 0, + 0, 3094, 0, + 0, 3201, 0, + 0, 3314, 0, + 0, 3430, 0, + 0, 3551, 0, + 0, 3674, 0, + 0, 2394, 2667, + 0, 2394, 2667, + 0, 2395, 2666, + 0, 2395, 2666, + 0, 2396, 2665, + 0, 2397, 2664, + 0, 2398, 2663, + 0, 2400, 2662, + 0, 2402, 2660, + 0, 2405, 2657, + 0, 2409, 2653, + 0, 2414, 2648, + 0, 2421, 2642, + 0, 2430, 2633, + 0, 2442, 2620, + 0, 2457, 2603, + 0, 2477, 2579, + 0, 2501, 2544, + 0, 2533, 2493, + 0, 2572, 2415, + 0, 2619, 2284, + 0, 2675, 2014, + 0, 2741, 0, + 0, 2816, 0, + 0, 2901, 0, + 0, 2994, 0, + 0, 3094, 0, + 0, 3201, 0, + 0, 3314, 0, + 0, 3430, 0, + 0, 3551, 0, + 0, 3674, 0, + 0, 2395, 2669, + 0, 2395, 2669, + 0, 2395, 2669, + 0, 2396, 2668, + 0, 2397, 2668, + 0, 2398, 2667, + 0, 2399, 2666, + 0, 2400, 2664, + 0, 2403, 2662, + 0, 2406, 2659, + 0, 2410, 2656, + 0, 2415, 2651, + 0, 2422, 2644, + 0, 2430, 2635, + 0, 2442, 2623, + 0, 2457, 2605, + 0, 2477, 2581, + 0, 2502, 2547, + 0, 2533, 2497, + 0, 2572, 2419, + 0, 2619, 2289, + 0, 2676, 2024, + 0, 2741, 0, + 0, 2817, 0, + 0, 2901, 0, + 0, 2994, 0, + 0, 3095, 0, + 0, 3201, 0, + 0, 3314, 0, + 0, 3430, 0, + 0, 3551, 0, + 0, 3674, 0, + 0, 2395, 2672, + 0, 2396, 2672, + 0, 2396, 2672, + 0, 2397, 2671, + 0, 2397, 2670, + 0, 2398, 2670, + 0, 2400, 2669, + 0, 2401, 2667, + 0, 2403, 2665, + 0, 2406, 2662, + 0, 2410, 2659, + 0, 2415, 2654, + 0, 2422, 2647, + 0, 2431, 2638, + 0, 2443, 2626, + 0, 2458, 2609, + 0, 2478, 2585, + 0, 2503, 2551, + 0, 2534, 2501, + 0, 2573, 2424, + 0, 2620, 2296, + 0, 2676, 2036, + 0, 2742, 0, + 0, 2817, 0, + 0, 2901, 0, + 0, 2994, 0, + 0, 3095, 0, + 0, 3202, 0, + 0, 3314, 0, + 0, 3430, 0, + 0, 3551, 0, + 0, 3674, 0, + 0, 2397, 2676, + 0, 2397, 2676, + 0, 2397, 2676, + 0, 2398, 2675, + 0, 2398, 2674, + 0, 2399, 2674, + 0, 2401, 2673, + 0, 2402, 2671, + 0, 2404, 2669, + 0, 2407, 2666, + 0, 2411, 2663, + 0, 2416, 2658, + 0, 2423, 2651, + 0, 2432, 2642, + 0, 2444, 2630, + 0, 2459, 2613, + 0, 2478, 2590, + 0, 2503, 2556, + 0, 2535, 2507, + 0, 2573, 2431, + 0, 2620, 2305, + 0, 2677, 2052, + 0, 2742, 0, + 0, 2817, 0, + 0, 2902, 0, + 0, 2995, 0, + 0, 3095, 0, + 0, 3202, 0, + 0, 3314, 0, + 0, 3431, 0, + 0, 3551, 0, + 0, 3674, 0, + 0, 2398, 2681, + 0, 2398, 2681, + 0, 2399, 2681, + 0, 2399, 2680, + 0, 2400, 2680, + 0, 2401, 2679, + 0, 2402, 2678, + 0, 2404, 2676, + 0, 2406, 2674, + 0, 2409, 2672, + 0, 2413, 2668, + 0, 2418, 2663, + 0, 2424, 2657, + 0, 2433, 2648, + 0, 2445, 2636, + 0, 2460, 2619, + 0, 2480, 2596, + 0, 2504, 2563, + 0, 2536, 2514, + 0, 2574, 2440, + 0, 2621, 2317, + 0, 2677, 2072, + 0, 2743, 674, + 0, 2818, 0, + 0, 2902, 0, + 0, 2995, 0, + 0, 3095, 0, + 0, 3202, 0, + 0, 3314, 0, + 0, 3431, 0, + 0, 3551, 0, + 0, 3674, 0, + 0, 2400, 2688, + 0, 2400, 2688, + 0, 2400, 2688, + 0, 2401, 2687, + 0, 2402, 2687, + 0, 2402, 2686, + 0, 2404, 2685, + 0, 2405, 2683, + 0, 2408, 2681, + 0, 2410, 2679, + 0, 2414, 2675, + 0, 2419, 2671, + 0, 2426, 2664, + 0, 2435, 2656, + 0, 2447, 2644, + 0, 2462, 2627, + 0, 2481, 2604, + 0, 2506, 2572, + 0, 2537, 2524, + 0, 2575, 2452, + 0, 2622, 2332, + 0, 2678, 2098, + 0, 2744, 1046, + 0, 2819, 0, + 0, 2903, 0, + 0, 2995, 0, + 0, 3096, 0, + 0, 3202, 0, + 0, 3314, 0, + 0, 3431, 0, + 0, 3551, 0, + 0, 3674, 0, + 0, 2402, 2697, + 0, 2402, 2697, + 0, 2403, 2697, + 0, 2403, 2696, + 0, 2404, 2696, + 0, 2405, 2695, + 0, 2406, 2694, + 0, 2408, 2693, + 0, 2410, 2691, + 0, 2413, 2688, + 0, 2417, 2685, + 0, 2422, 2680, + 0, 2428, 2674, + 0, 2437, 2665, + 0, 2449, 2654, + 0, 2464, 2638, + 0, 2483, 2615, + 0, 2508, 2583, + 0, 2539, 2537, + 0, 2577, 2467, + 0, 2624, 2352, + 0, 2680, 2130, + 0, 2745, 1300, + 0, 2820, 0, + 0, 2904, 0, + 0, 2996, 0, + 0, 3096, 0, + 0, 3203, 0, + 0, 3315, 0, + 0, 3431, 0, + 0, 3551, 0, + 0, 3674, 0, + 0, 2405, 2709, + 0, 2406, 2709, + 0, 2406, 2709, + 0, 2406, 2708, + 0, 2407, 2708, + 0, 2408, 2707, + 0, 2409, 2706, + 0, 2411, 2705, + 0, 2413, 2703, + 0, 2416, 2700, + 0, 2420, 2697, + 0, 2425, 2692, + 0, 2431, 2686, + 0, 2440, 2678, + 0, 2452, 2667, + 0, 2467, 2651, + 0, 2486, 2629, + 0, 2510, 2599, + 0, 2541, 2554, + 0, 2579, 2486, + 0, 2626, 2377, + 0, 2681, 2170, + 0, 2746, 1506, + 0, 2821, 0, + 0, 2905, 0, + 0, 2997, 0, + 0, 3097, 0, + 0, 3203, 0, + 0, 3315, 0, + 0, 3431, 0, + 0, 3551, 0, + 0, 3674, 0, + 0, 2410, 2725, + 0, 2410, 2724, + 0, 2410, 2724, + 0, 2411, 2724, + 0, 2411, 2723, + 0, 2412, 2722, + 0, 2413, 2721, + 0, 2415, 2720, + 0, 2417, 2718, + 0, 2420, 2716, + 0, 2424, 2713, + 0, 2429, 2708, + 0, 2435, 2702, + 0, 2444, 2694, + 0, 2456, 2684, + 0, 2470, 2669, + 0, 2489, 2648, + 0, 2514, 2618, + 0, 2544, 2575, + 0, 2582, 2511, + 0, 2628, 2408, + 0, 2684, 2219, + 0, 2748, 1686, + 0, 2823, 0, + 0, 2906, 0, + 0, 2998, 0, + 0, 3098, 0, + 0, 3204, 0, + 0, 3316, 0, + 0, 3432, 0, + 0, 3552, 0, + 0, 3675, 0, + 0, 2415, 2744, + 0, 2415, 2744, + 0, 2416, 2744, + 0, 2416, 2744, + 0, 2417, 2743, + 0, 2418, 2742, + 0, 2419, 2741, + 0, 2421, 2740, + 0, 2423, 2738, + 0, 2426, 2736, + 0, 2429, 2733, + 0, 2434, 2729, + 0, 2441, 2723, + 0, 2449, 2716, + 0, 2461, 2705, + 0, 2475, 2691, + 0, 2494, 2671, + 0, 2518, 2643, + 0, 2548, 2603, + 0, 2586, 2543, + 0, 2632, 2447, + 0, 2687, 2277, + 0, 2751, 1851, + 0, 2825, 0, + 0, 2908, 0, + 0, 3000, 0, + 0, 3099, 0, + 0, 3205, 0, + 0, 3316, 0, + 0, 3432, 0, + 0, 3552, 0, + 0, 3675, 0, + 896, 2423, 2770, + 879, 2423, 2769, + 854, 2423, 2769, + 820, 2424, 2769, + 769, 2424, 2768, + 691, 2425, 2768, + 560, 2426, 2767, + 290, 2428, 2766, + 0, 2430, 2764, + 0, 2433, 2762, + 0, 2436, 2759, + 0, 2441, 2755, + 0, 2448, 2750, + 0, 2456, 2742, + 0, 2467, 2733, + 0, 2482, 2719, + 0, 2500, 2701, + 0, 2524, 2674, + 0, 2554, 2637, + 0, 2591, 2581, + 0, 2636, 2494, + 0, 2691, 2344, + 0, 2755, 2007, + 0, 2828, 0, + 0, 2910, 0, + 0, 3002, 0, + 0, 3101, 0, + 0, 3206, 0, + 0, 3317, 0, + 0, 3433, 0, + 0, 3553, 0, + 0, 3675, 0, + 1925, 2432, 2801, + 1923, 2432, 2801, + 1921, 2433, 2801, + 1917, 2433, 2801, + 1913, 2434, 2800, + 1907, 2435, 2799, + 1899, 2436, 2799, + 1889, 2438, 2798, + 1874, 2440, 2796, + 1853, 2442, 2794, + 1824, 2446, 2791, + 1782, 2451, 2788, + 1718, 2457, 2783, + 1617, 2465, 2776, + 1432, 2476, 2767, + 925, 2490, 2754, + 0, 2508, 2737, + 0, 2532, 2713, + 0, 2561, 2679, + 0, 2598, 2628, + 0, 2642, 2551, + 0, 2696, 2421, + 0, 2759, 2155, + 0, 2832, 0, + 0, 2914, 0, + 0, 3004, 0, + 0, 3103, 0, + 0, 3208, 0, + 0, 3319, 0, + 0, 3434, 0, + 0, 3554, 0, + 0, 3676, 0, + 2283, 2445, 2841, + 2282, 2445, 2840, + 2281, 2445, 2840, + 2279, 2446, 2840, + 2278, 2447, 2839, + 2275, 2447, 2839, + 2271, 2449, 2838, + 2267, 2450, 2837, + 2260, 2452, 2836, + 2252, 2455, 2834, + 2240, 2458, 2831, + 2223, 2463, 2828, + 2200, 2469, 2823, + 2168, 2477, 2817, + 2120, 2488, 2809, + 2047, 2501, 2798, + 1927, 2519, 2782, + 1692, 2542, 2760, + 612, 2571, 2729, + 0, 2607, 2685, + 0, 2650, 2617, + 0, 2703, 2507, + 0, 2765, 2299, + 0, 2837, 1624, + 0, 2918, 0, + 0, 3008, 0, + 0, 3106, 0, + 0, 3210, 0, + 0, 3321, 0, + 0, 3436, 0, + 0, 3555, 0, + 0, 3677, 0, + 2532, 2461, 2888, + 2531, 2462, 2888, + 2531, 2462, 2888, + 2530, 2462, 2887, + 2529, 2463, 2887, + 2527, 2464, 2887, + 2525, 2465, 2886, + 2522, 2466, 2885, + 2519, 2468, 2884, + 2514, 2471, 2882, + 2507, 2474, 2880, + 2498, 2479, 2877, + 2486, 2484, 2873, + 2469, 2492, 2867, + 2445, 2503, 2860, + 2411, 2516, 2850, + 2360, 2533, 2836, + 2283, 2555, 2817, + 2155, 2583, 2789, + 1893, 2618, 2750, + 0, 2661, 2692, + 0, 2713, 2601, + 0, 2774, 2440, + 0, 2844, 2059, + 0, 2924, 0, + 0, 3013, 0, + 0, 3110, 0, + 0, 3213, 0, + 0, 3323, 0, + 0, 3438, 0, + 0, 3556, 0, + 0, 3678, 0, + 2735, 2482, 2945, + 2735, 2483, 2945, + 2734, 2483, 2945, + 2734, 2483, 2944, + 2733, 2484, 2944, + 2732, 2485, 2944, + 2731, 2486, 2943, + 2729, 2487, 2942, + 2727, 2489, 2941, + 2724, 2491, 2940, + 2719, 2495, 2938, + 2714, 2499, 2935, + 2706, 2504, 2931, + 2696, 2512, 2927, + 2681, 2522, 2920, + 2661, 2535, 2911, + 2633, 2551, 2899, + 2592, 2572, 2882, + 2532, 2599, 2859, + 2435, 2633, 2826, + 2263, 2675, 2777, + 1825, 2725, 2702, + 0, 2784, 2579, + 0, 2853, 2332, + 0, 2932, 847, + 0, 3019, 0, + 0, 3115, 0, + 0, 3217, 0, + 0, 3326, 0, + 0, 3440, 0, + 0, 3558, 0, + 0, 3679, 0, + 2914, 2509, 3011, + 2913, 2509, 3011, + 2913, 2510, 3011, + 2913, 2510, 3011, + 2912, 2510, 3010, + 2912, 2511, 3010, + 2911, 2512, 3009, + 2910, 2513, 3009, + 2908, 2515, 3008, + 2906, 2517, 3007, + 2903, 2521, 3005, + 2900, 2525, 3003, + 2894, 2530, 3000, + 2888, 2537, 2995, + 2878, 2546, 2990, + 2865, 2558, 2982, + 2848, 2574, 2972, + 2823, 2594, 2958, + 2787, 2620, 2938, + 2735, 2652, 2910, + 2653, 2692, 2870, + 2516, 2741, 2810, + 2224, 2798, 2716, + 0, 2865, 2547, + 0, 2942, 2131, + 0, 3028, 0, + 0, 3122, 0, + 0, 3223, 0, + 0, 3331, 0, + 0, 3443, 0, + 0, 3561, 0, + 0, 3681, 0, + 3078, 2542, 3087, + 3078, 2543, 3087, + 3077, 2543, 3087, + 3077, 2543, 3087, + 3077, 2544, 3086, + 3076, 2544, 3086, + 3076, 2545, 3086, + 3075, 2547, 3085, + 3074, 2548, 3084, + 3073, 2550, 3083, + 3071, 2553, 3082, + 3068, 2557, 3080, + 3064, 2562, 3077, + 3060, 2569, 3074, + 3053, 2577, 3069, + 3045, 2589, 3063, + 3033, 2603, 3054, + 3016, 2622, 3042, + 2993, 2647, 3026, + 2961, 2677, 3003, + 2913, 2715, 2971, + 2841, 2761, 2923, + 2721, 2816, 2851, + 2486, 2881, 2733, + 1423, 2955, 2501, + 0, 3039, 1510, + 0, 3130, 0, + 0, 3230, 0, + 0, 3336, 0, + 0, 3448, 0, + 0, 3564, 0, + 0, 3684, 0, + 3232, 2584, 3172, + 3232, 2584, 3172, + 3232, 2584, 3172, + 3232, 2584, 3172, + 3232, 2585, 3171, + 3232, 2585, 3171, + 3231, 2586, 3171, + 3231, 2587, 3170, + 3230, 2589, 3170, + 3229, 2591, 3169, + 3227, 2593, 3167, + 3226, 2597, 3166, + 3223, 2601, 3164, + 3220, 2607, 3161, + 3215, 2615, 3157, + 3209, 2626, 3152, + 3201, 2639, 3145, + 3190, 2657, 3135, + 3174, 2680, 3122, + 3152, 2708, 3103, + 3122, 2743, 3078, + 3077, 2787, 3041, + 3010, 2839, 2986, + 2901, 2901, 2901, + 2696, 2972, 2754, + 2044, 3053, 2432, + 0, 3142, 0, + 0, 3239, 0, + 0, 3344, 0, + 0, 3454, 0, + 0, 3569, 0, + 0, 3687, 0, + 3381, 2633, 3265, + 3381, 2634, 3265, + 3381, 2634, 3265, + 3380, 2634, 3265, + 3380, 2634, 3265, + 3380, 2635, 3265, + 3380, 2636, 3264, + 3379, 2637, 3264, + 3379, 2638, 3263, + 3378, 2640, 3263, + 3377, 2642, 3262, + 3376, 2645, 3260, + 3374, 2649, 3259, + 3372, 2655, 3256, + 3368, 2662, 3253, + 3364, 2671, 3249, + 3358, 2684, 3243, + 3350, 2700, 3235, + 3339, 2720, 3225, + 3324, 2746, 3210, + 3304, 2779, 3190, + 3274, 2819, 3161, + 3232, 2868, 3120, + 3168, 2926, 3058, + 3066, 2994, 2960, + 2879, 3071, 2782, + 2358, 3157, 2318, + 0, 3252, 0, + 0, 3353, 0, + 0, 3461, 0, + 0, 3575, 0, + 0, 3692, 0, + 3525, 2692, 3366, + 3525, 2693, 3366, + 3524, 2693, 3366, + 3524, 2693, 3366, + 3524, 2693, 3366, + 3524, 2694, 3365, + 3524, 2695, 3365, + 3524, 2695, 3365, + 3523, 2697, 3364, + 3523, 2698, 3364, + 3522, 2700, 3363, + 3521, 2703, 3362, + 3520, 2707, 3361, + 3518, 2711, 3359, + 3516, 2718, 3356, + 3512, 2726, 3353, + 3508, 2737, 3348, + 3503, 2751, 3342, + 3495, 2770, 3334, + 3484, 2793, 3322, + 3470, 2823, 3307, + 3450, 2859, 3285, + 3421, 2904, 3254, + 3380, 2958, 3208, + 3319, 3022, 3140, + 3221, 3095, 3028, + 3045, 3177, 2817, + 2591, 3268, 2101, + 0, 3366, 0, + 0, 3471, 0, + 0, 3582, 0, + 0, 3698, 0, + 3665, 2761, 3473, + 3665, 2761, 3473, + 3665, 2761, 3473, + 3665, 2762, 3473, + 3665, 2762, 3473, + 3665, 2762, 3473, + 3665, 2763, 3472, + 3665, 2764, 3472, + 3664, 2765, 3472, + 3664, 2766, 3471, + 3663, 2768, 3471, + 3663, 2770, 3470, + 3662, 2773, 3469, + 3660, 2777, 3467, + 3659, 2783, 3465, + 3656, 2790, 3463, + 3653, 2800, 3459, + 3649, 2812, 3454, + 3644, 2828, 3448, + 3636, 2849, 3439, + 3626, 2875, 3427, + 3611, 2908, 3410, + 3592, 2949, 3387, + 3564, 2998, 3353, + 3524, 3056, 3305, + 3464, 3124, 3230, + 3370, 3202, 3106, + 3201, 3288, 2859, + 2786, 3383, 1324, + 0, 3485, 0, + 0, 3593, 0, + 0, 3706, 0, + 3804, 2839, 3586, + 3804, 2839, 3586, + 3804, 2839, 3586, + 3804, 2840, 3585, + 3803, 2840, 3585, + 3803, 2840, 3585, + 3803, 2841, 3585, + 3803, 2841, 3585, + 3803, 2842, 3585, + 3803, 2843, 3584, + 3802, 2845, 3584, + 3802, 2847, 3583, + 3801, 2849, 3582, + 3800, 2853, 3581, + 3799, 2858, 3580, + 3797, 2864, 3578, + 3795, 2872, 3575, + 3792, 2882, 3571, + 3788, 2896, 3566, + 3782, 2914, 3559, + 3775, 2937, 3550, + 3765, 2966, 3537, + 3751, 3002, 3520, + 3731, 3046, 3495, + 3704, 3099, 3460, + 3665, 3161, 3408, + 3606, 3233, 3328, + 3514, 3314, 3193, + 3351, 3404, 2910, + 2960, 3502, 0, + 0, 3606, 0, + 0, 3717, 0, + 3940, 2926, 3703, + 3940, 2926, 3702, + 3940, 2926, 3702, + 3940, 2926, 3702, + 3940, 2927, 3702, + 3940, 2927, 3702, + 3940, 2927, 3702, + 3940, 2928, 3702, + 3940, 2929, 3702, + 3940, 2930, 3702, + 3939, 2931, 3701, + 3939, 2932, 3701, + 3938, 2935, 3700, + 3938, 2938, 3699, + 3937, 2941, 3698, + 3936, 2947, 3696, + 3934, 2953, 3694, + 3932, 2962, 3691, + 3929, 2974, 3687, + 3925, 2989, 3682, + 3919, 3008, 3675, + 3912, 3033, 3666, + 3902, 3064, 3652, + 3888, 3103, 3634, + 3869, 3150, 3608, + 3842, 3206, 3572, + 3803, 3271, 3517, + 3745, 3347, 3433, + 3654, 3431, 3288, + 3495, 3523, 2971, + 3121, 3624, 0, + 0, 3730, 0, + 4076, 3021, 3823, + 4076, 3021, 3823, + 4076, 3021, 3823, + 4076, 3022, 3823, + 4076, 3022, 3823, + 4076, 3022, 3823, + 4076, 3022, 3823, + 4076, 3023, 3822, + 4076, 3023, 3822, + 4075, 3024, 3822, + 4075, 3025, 3822, + 4075, 3026, 3821, + 4075, 3028, 3821, + 4074, 3031, 3820, + 4073, 3034, 3819, + 4072, 3038, 3818, + 4071, 3043, 3817, + 4070, 3051, 3814, + 4067, 3060, 3811, + 4064, 3073, 3807, + 4060, 3089, 3802, + 4055, 3110, 3795, + 4048, 3136, 3785, + 4038, 3170, 3771, + 4024, 3210, 3753, + 4005, 3260, 3726, + 3978, 3318, 3688, + 3940, 3387, 3632, + 3883, 3464, 3544, + 3793, 3551, 3390, + 3636, 3646, 3041, + 3273, 3748, 0, + 4095, 3124, 3946, + 4095, 3124, 3946, + 4095, 3124, 3946, + 4095, 3124, 3946, + 4095, 3124, 3946, + 4095, 3124, 3946, + 4095, 3125, 3946, + 4095, 3125, 3946, + 4095, 3125, 3946, + 4095, 3126, 3945, + 4095, 3127, 3945, + 4095, 3128, 3945, + 4095, 3129, 3945, + 4095, 3131, 3944, + 4095, 3134, 3943, + 4095, 3137, 3942, + 4095, 3142, 3941, + 4095, 3147, 3940, + 4095, 3155, 3937, + 4095, 3165, 3934, + 4095, 3179, 3930, + 4095, 3196, 3925, + 4095, 3218, 3917, + 4095, 3246, 3907, + 4095, 3280, 3893, + 4095, 3323, 3874, + 4095, 3375, 3847, + 4095, 3435, 3808, + 4075, 3506, 3750, + 4019, 3586, 3659, + 3930, 3674, 3499, + 3775, 3771, 3120, + 4095, 3232, 4071, + 4095, 3232, 4071, + 4095, 3232, 4071, + 4095, 3232, 4071, + 4095, 3233, 4071, + 4095, 3233, 4071, + 4095, 3233, 4071, + 4095, 3233, 4071, + 4095, 3234, 4071, + 4095, 3234, 4071, + 4095, 3235, 4071, + 4095, 3236, 4070, + 4095, 3237, 4070, + 4095, 3238, 4070, + 4095, 3240, 4069, + 4095, 3243, 4069, + 4095, 3246, 4068, + 4095, 3251, 4066, + 4095, 3257, 4065, + 4095, 3265, 4062, + 4095, 3276, 4059, + 4095, 3290, 4055, + 4095, 3308, 4050, + 4095, 3331, 4042, + 4095, 3360, 4032, + 4095, 3396, 4018, + 4095, 3440, 3998, + 4095, 3493, 3971, + 4095, 3556, 3931, + 4095, 3628, 3872, + 4095, 3709, 3778, + 4065, 3799, 3612, + 0, 2525, 2793, + 0, 2525, 2793, + 0, 2525, 2793, + 0, 2525, 2793, + 0, 2526, 2792, + 0, 2527, 2792, + 0, 2528, 2791, + 0, 2529, 2790, + 0, 2531, 2788, + 0, 2533, 2786, + 0, 2536, 2783, + 0, 2540, 2779, + 0, 2545, 2774, + 0, 2552, 2768, + 0, 2561, 2758, + 0, 2572, 2746, + 0, 2588, 2728, + 0, 2607, 2704, + 0, 2632, 2668, + 0, 2664, 2617, + 0, 2703, 2537, + 0, 2750, 2402, + 0, 2807, 2121, + 0, 2873, 0, + 0, 2948, 0, + 0, 3033, 0, + 0, 3126, 0, + 0, 3226, 0, + 0, 3333, 0, + 0, 3445, 0, + 0, 3562, 0, + 0, 3683, 0, + 0, 2525, 2794, + 0, 2525, 2794, + 0, 2525, 2793, + 0, 2526, 2793, + 0, 2526, 2792, + 0, 2527, 2792, + 0, 2528, 2791, + 0, 2529, 2790, + 0, 2531, 2788, + 0, 2533, 2786, + 0, 2536, 2783, + 0, 2540, 2780, + 0, 2545, 2775, + 0, 2552, 2768, + 0, 2561, 2759, + 0, 2573, 2746, + 0, 2588, 2728, + 0, 2607, 2704, + 0, 2632, 2669, + 0, 2664, 2617, + 0, 2703, 2538, + 0, 2750, 2403, + 0, 2807, 2123, + 0, 2873, 0, + 0, 2948, 0, + 0, 3033, 0, + 0, 3126, 0, + 0, 3226, 0, + 0, 3333, 0, + 0, 3446, 0, + 0, 3562, 0, + 0, 3683, 0, + 0, 2525, 2794, + 0, 2525, 2794, + 0, 2525, 2794, + 0, 2526, 2793, + 0, 2526, 2793, + 0, 2527, 2792, + 0, 2528, 2791, + 0, 2529, 2790, + 0, 2531, 2789, + 0, 2533, 2787, + 0, 2536, 2784, + 0, 2540, 2780, + 0, 2545, 2775, + 0, 2552, 2768, + 0, 2561, 2759, + 0, 2573, 2746, + 0, 2588, 2729, + 0, 2608, 2704, + 0, 2633, 2669, + 0, 2664, 2618, + 0, 2703, 2538, + 0, 2750, 2404, + 0, 2807, 2124, + 0, 2873, 0, + 0, 2948, 0, + 0, 3033, 0, + 0, 3126, 0, + 0, 3226, 0, + 0, 3333, 0, + 0, 3446, 0, + 0, 3562, 0, + 0, 3683, 0, + 0, 2525, 2795, + 0, 2525, 2794, + 0, 2525, 2794, + 0, 2526, 2794, + 0, 2526, 2793, + 0, 2527, 2793, + 0, 2528, 2792, + 0, 2529, 2791, + 0, 2531, 2789, + 0, 2533, 2787, + 0, 2536, 2784, + 0, 2540, 2781, + 0, 2545, 2776, + 0, 2552, 2769, + 0, 2561, 2760, + 0, 2573, 2747, + 0, 2588, 2730, + 0, 2608, 2705, + 0, 2633, 2670, + 0, 2664, 2619, + 0, 2703, 2539, + 0, 2750, 2405, + 0, 2807, 2127, + 0, 2873, 0, + 0, 2948, 0, + 0, 3033, 0, + 0, 3126, 0, + 0, 3226, 0, + 0, 3333, 0, + 0, 3446, 0, + 0, 3562, 0, + 0, 3683, 0, + 0, 2525, 2795, + 0, 2525, 2795, + 0, 2526, 2795, + 0, 2526, 2795, + 0, 2526, 2794, + 0, 2527, 2793, + 0, 2528, 2793, + 0, 2529, 2791, + 0, 2531, 2790, + 0, 2533, 2788, + 0, 2536, 2785, + 0, 2540, 2781, + 0, 2545, 2776, + 0, 2552, 2770, + 0, 2561, 2760, + 0, 2573, 2748, + 0, 2588, 2730, + 0, 2608, 2706, + 0, 2633, 2671, + 0, 2664, 2620, + 0, 2703, 2540, + 0, 2750, 2407, + 0, 2807, 2130, + 0, 2873, 0, + 0, 2948, 0, + 0, 3033, 0, + 0, 3126, 0, + 0, 3226, 0, + 0, 3333, 0, + 0, 3446, 0, + 0, 3562, 0, + 0, 3683, 0, + 0, 2525, 2796, + 0, 2526, 2796, + 0, 2526, 2796, + 0, 2526, 2795, + 0, 2527, 2795, + 0, 2527, 2794, + 0, 2528, 2794, + 0, 2530, 2792, + 0, 2531, 2791, + 0, 2533, 2789, + 0, 2536, 2786, + 0, 2540, 2782, + 0, 2546, 2777, + 0, 2552, 2771, + 0, 2561, 2761, + 0, 2573, 2749, + 0, 2588, 2731, + 0, 2608, 2707, + 0, 2633, 2672, + 0, 2664, 2621, + 0, 2703, 2542, + 0, 2751, 2409, + 0, 2807, 2134, + 0, 2873, 0, + 0, 2948, 0, + 0, 3033, 0, + 0, 3126, 0, + 0, 3226, 0, + 0, 3333, 0, + 0, 3446, 0, + 0, 3562, 0, + 0, 3683, 0, + 0, 2526, 2798, + 0, 2526, 2797, + 0, 2526, 2797, + 0, 2527, 2797, + 0, 2527, 2796, + 0, 2528, 2796, + 0, 2529, 2795, + 0, 2530, 2794, + 0, 2532, 2792, + 0, 2534, 2790, + 0, 2537, 2787, + 0, 2541, 2784, + 0, 2546, 2779, + 0, 2553, 2772, + 0, 2562, 2763, + 0, 2573, 2750, + 0, 2589, 2733, + 0, 2608, 2709, + 0, 2633, 2674, + 0, 2665, 2623, + 0, 2703, 2544, + 0, 2751, 2412, + 0, 2807, 2139, + 0, 2873, 0, + 0, 2948, 0, + 0, 3033, 0, + 0, 3126, 0, + 0, 3226, 0, + 0, 3333, 0, + 0, 3446, 0, + 0, 3562, 0, + 0, 3683, 0, + 0, 2526, 2799, + 0, 2526, 2799, + 0, 2527, 2799, + 0, 2527, 2798, + 0, 2527, 2798, + 0, 2528, 2797, + 0, 2529, 2797, + 0, 2530, 2795, + 0, 2532, 2794, + 0, 2534, 2792, + 0, 2537, 2789, + 0, 2541, 2785, + 0, 2546, 2780, + 0, 2553, 2774, + 0, 2562, 2765, + 0, 2574, 2752, + 0, 2589, 2735, + 0, 2609, 2711, + 0, 2634, 2676, + 0, 2665, 2625, + 0, 2704, 2547, + 0, 2751, 2416, + 0, 2807, 2146, + 0, 2873, 0, + 0, 2949, 0, + 0, 3033, 0, + 0, 3126, 0, + 0, 3226, 0, + 0, 3333, 0, + 0, 3446, 0, + 0, 3562, 0, + 0, 3683, 0, + 0, 2527, 2801, + 0, 2527, 2801, + 0, 2527, 2801, + 0, 2528, 2801, + 0, 2528, 2800, + 0, 2529, 2800, + 0, 2530, 2799, + 0, 2531, 2798, + 0, 2533, 2796, + 0, 2535, 2794, + 0, 2538, 2791, + 0, 2542, 2788, + 0, 2547, 2783, + 0, 2554, 2776, + 0, 2563, 2767, + 0, 2574, 2755, + 0, 2590, 2737, + 0, 2609, 2713, + 0, 2634, 2679, + 0, 2665, 2629, + 0, 2704, 2551, + 0, 2751, 2421, + 0, 2808, 2156, + 0, 2873, 0, + 0, 2949, 0, + 0, 3033, 0, + 0, 3126, 0, + 0, 3227, 0, + 0, 3333, 0, + 0, 3446, 0, + 0, 3562, 0, + 0, 3683, 0, + 0, 2527, 2804, + 0, 2528, 2804, + 0, 2528, 2804, + 0, 2528, 2804, + 0, 2529, 2803, + 0, 2529, 2803, + 0, 2530, 2802, + 0, 2532, 2801, + 0, 2533, 2799, + 0, 2536, 2797, + 0, 2538, 2794, + 0, 2542, 2791, + 0, 2548, 2786, + 0, 2554, 2779, + 0, 2563, 2770, + 0, 2575, 2758, + 0, 2590, 2741, + 0, 2610, 2717, + 0, 2635, 2683, + 0, 2666, 2633, + 0, 2705, 2556, + 0, 2752, 2428, + 0, 2808, 2168, + 0, 2874, 0, + 0, 2949, 0, + 0, 3034, 0, + 0, 3126, 0, + 0, 3227, 0, + 0, 3334, 0, + 0, 3446, 0, + 0, 3563, 0, + 0, 3683, 0, + 0, 2528, 2808, + 0, 2529, 2808, + 0, 2529, 2808, + 0, 2529, 2808, + 0, 2530, 2807, + 0, 2531, 2807, + 0, 2531, 2806, + 0, 2533, 2805, + 0, 2534, 2803, + 0, 2537, 2801, + 0, 2539, 2799, + 0, 2543, 2795, + 0, 2549, 2790, + 0, 2555, 2783, + 0, 2564, 2775, + 0, 2576, 2762, + 0, 2591, 2745, + 0, 2611, 2722, + 0, 2635, 2688, + 0, 2667, 2639, + 0, 2705, 2563, + 0, 2752, 2437, + 0, 2809, 2184, + 0, 2874, 0, + 0, 2949, 0, + 0, 3034, 0, + 0, 3127, 0, + 0, 3227, 0, + 0, 3334, 0, + 0, 3446, 0, + 0, 3563, 0, + 0, 3683, 0, + 0, 2530, 2814, + 0, 2530, 2813, + 0, 2530, 2813, + 0, 2531, 2813, + 0, 2531, 2812, + 0, 2532, 2812, + 0, 2533, 2811, + 0, 2534, 2810, + 0, 2536, 2808, + 0, 2538, 2806, + 0, 2541, 2804, + 0, 2545, 2800, + 0, 2550, 2795, + 0, 2557, 2789, + 0, 2565, 2780, + 0, 2577, 2768, + 0, 2592, 2751, + 0, 2612, 2728, + 0, 2636, 2695, + 0, 2668, 2646, + 0, 2706, 2572, + 0, 2753, 2449, + 0, 2809, 2204, + 0, 2875, 806, + 0, 2950, 0, + 0, 3034, 0, + 0, 3127, 0, + 0, 3227, 0, + 0, 3334, 0, + 0, 3446, 0, + 0, 3563, 0, + 0, 3683, 0, + 0, 2532, 2821, + 0, 2532, 2820, + 0, 2532, 2820, + 0, 2532, 2820, + 0, 2533, 2819, + 0, 2534, 2819, + 0, 2535, 2818, + 0, 2536, 2817, + 0, 2537, 2815, + 0, 2540, 2814, + 0, 2543, 2811, + 0, 2546, 2807, + 0, 2552, 2803, + 0, 2558, 2796, + 0, 2567, 2788, + 0, 2579, 2776, + 0, 2594, 2759, + 0, 2613, 2736, + 0, 2638, 2704, + 0, 2669, 2656, + 0, 2708, 2584, + 0, 2754, 2464, + 0, 2810, 2230, + 0, 2876, 1179, + 0, 2951, 0, + 0, 3035, 0, + 0, 3128, 0, + 0, 3228, 0, + 0, 3334, 0, + 0, 3446, 0, + 0, 3563, 0, + 0, 3683, 0, + 0, 2534, 2830, + 0, 2534, 2829, + 0, 2534, 2829, + 0, 2535, 2829, + 0, 2535, 2828, + 0, 2536, 2828, + 0, 2537, 2827, + 0, 2538, 2826, + 0, 2540, 2825, + 0, 2542, 2823, + 0, 2545, 2820, + 0, 2549, 2817, + 0, 2554, 2812, + 0, 2561, 2806, + 0, 2569, 2797, + 0, 2581, 2786, + 0, 2596, 2770, + 0, 2615, 2747, + 0, 2640, 2716, + 0, 2671, 2669, + 0, 2709, 2599, + 0, 2756, 2484, + 0, 2812, 2263, + 0, 2877, 1432, + 0, 2952, 0, + 0, 3036, 0, + 0, 3128, 0, + 0, 3228, 0, + 0, 3335, 0, + 0, 3447, 0, + 0, 3563, 0, + 0, 3683, 0, + 0, 2537, 2842, + 0, 2537, 2841, + 0, 2538, 2841, + 0, 2538, 2841, + 0, 2539, 2840, + 0, 2539, 2840, + 0, 2540, 2839, + 0, 2541, 2838, + 0, 2543, 2837, + 0, 2545, 2835, + 0, 2548, 2832, + 0, 2552, 2829, + 0, 2557, 2824, + 0, 2564, 2818, + 0, 2572, 2810, + 0, 2584, 2799, + 0, 2599, 2783, + 0, 2618, 2761, + 0, 2642, 2731, + 0, 2673, 2686, + 0, 2711, 2618, + 0, 2758, 2509, + 0, 2813, 2303, + 0, 2878, 1638, + 0, 2953, 0, + 0, 3037, 0, + 0, 3129, 0, + 0, 3229, 0, + 0, 3335, 0, + 0, 3447, 0, + 0, 3564, 0, + 0, 3684, 0, + 0, 2541, 2857, + 0, 2542, 2857, + 0, 2542, 2857, + 0, 2542, 2856, + 0, 2543, 2856, + 0, 2543, 2855, + 0, 2544, 2854, + 0, 2546, 2854, + 0, 2547, 2852, + 0, 2549, 2850, + 0, 2552, 2848, + 0, 2556, 2845, + 0, 2561, 2840, + 0, 2568, 2835, + 0, 2576, 2827, + 0, 2588, 2816, + 0, 2602, 2801, + 0, 2621, 2780, + 0, 2646, 2750, + 0, 2676, 2708, + 0, 2714, 2643, + 0, 2760, 2540, + 0, 2816, 2351, + 0, 2880, 1818, + 0, 2955, 0, + 0, 3038, 0, + 0, 3130, 0, + 0, 3230, 0, + 0, 3336, 0, + 0, 3448, 0, + 0, 3564, 0, + 0, 3684, 0, + 0, 2547, 2877, + 0, 2547, 2877, + 0, 2547, 2876, + 0, 2548, 2876, + 0, 2548, 2876, + 0, 2549, 2875, + 0, 2550, 2874, + 0, 2551, 2873, + 0, 2553, 2872, + 0, 2555, 2870, + 0, 2558, 2868, + 0, 2561, 2865, + 0, 2566, 2861, + 0, 2573, 2855, + 0, 2581, 2848, + 0, 2593, 2837, + 0, 2607, 2823, + 0, 2626, 2803, + 0, 2650, 2775, + 0, 2680, 2735, + 0, 2718, 2675, + 0, 2764, 2579, + 0, 2819, 2409, + 0, 2883, 1983, + 0, 2957, 0, + 0, 3040, 0, + 0, 3132, 0, + 0, 3231, 0, + 0, 3337, 0, + 0, 3449, 0, + 0, 3565, 0, + 0, 3684, 0, + 1040, 2554, 2902, + 1028, 2555, 2902, + 1011, 2555, 2902, + 986, 2555, 2901, + 952, 2556, 2901, + 901, 2556, 2900, + 823, 2557, 2900, + 692, 2558, 2899, + 422, 2560, 2898, + 0, 2562, 2896, + 0, 2565, 2894, + 0, 2569, 2891, + 0, 2573, 2887, + 0, 2580, 2882, + 0, 2588, 2875, + 0, 2599, 2865, + 0, 2614, 2851, + 0, 2632, 2833, + 0, 2656, 2806, + 0, 2686, 2769, + 0, 2723, 2713, + 0, 2768, 2627, + 0, 2823, 2476, + 0, 2887, 2139, + 0, 2960, 0, + 0, 3043, 0, + 0, 3134, 0, + 0, 3233, 0, + 0, 3338, 0, + 0, 3450, 0, + 0, 3565, 0, + 0, 3685, 0, + 2058, 2564, 2934, + 2057, 2564, 2933, + 2055, 2565, 2933, + 2053, 2565, 2933, + 2050, 2565, 2933, + 2045, 2566, 2932, + 2039, 2567, 2932, + 2032, 2568, 2931, + 2021, 2570, 2930, + 2006, 2572, 2928, + 1985, 2574, 2926, + 1956, 2578, 2923, + 1914, 2583, 2920, + 1850, 2589, 2915, + 1749, 2597, 2908, + 1564, 2608, 2899, + 1057, 2622, 2887, + 0, 2641, 2869, + 0, 2664, 2845, + 0, 2693, 2811, + 0, 2730, 2761, + 0, 2775, 2683, + 0, 2828, 2553, + 0, 2891, 2287, + 0, 2964, 0, + 0, 3046, 0, + 0, 3137, 0, + 0, 3235, 0, + 0, 3340, 0, + 0, 3451, 0, + 0, 3566, 0, + 0, 3686, 0, + 2415, 2577, 2973, + 2415, 2577, 2973, + 2414, 2577, 2972, + 2413, 2578, 2972, + 2412, 2578, 2972, + 2410, 2579, 2971, + 2407, 2580, 2971, + 2404, 2581, 2970, + 2399, 2582, 2969, + 2392, 2584, 2968, + 2384, 2587, 2966, + 2372, 2590, 2963, + 2355, 2595, 2960, + 2332, 2601, 2956, + 2300, 2609, 2949, + 2252, 2620, 2941, + 2179, 2633, 2930, + 2059, 2651, 2914, + 1824, 2674, 2892, + 744, 2703, 2862, + 0, 2739, 2817, + 0, 2783, 2749, + 0, 2835, 2639, + 0, 2898, 2431, + 0, 2969, 1756, + 0, 3050, 0, + 0, 3140, 0, + 0, 3238, 0, + 0, 3342, 0, + 0, 3453, 0, + 0, 3568, 0, + 0, 3687, 0, + 2664, 2593, 3020, + 2664, 2593, 3020, + 2663, 2594, 3020, + 2663, 2594, 3020, + 2662, 2594, 3020, + 2661, 2595, 3019, + 2659, 2596, 3019, + 2657, 2597, 3018, + 2654, 2598, 3017, + 2651, 2600, 3016, + 2646, 2603, 3014, + 2639, 2606, 3012, + 2630, 2611, 3009, + 2618, 2617, 3005, + 2601, 2624, 2999, + 2577, 2635, 2992, + 2543, 2648, 2982, + 2493, 2665, 2968, + 2416, 2687, 2949, + 2287, 2715, 2922, + 2025, 2750, 2883, + 0, 2793, 2824, + 0, 2845, 2733, + 0, 2906, 2572, + 0, 2976, 2191, + 0, 3056, 0, + 0, 3145, 0, + 0, 3242, 0, + 0, 3345, 0, + 0, 3455, 0, + 0, 3570, 0, + 0, 3688, 0, + 2867, 2614, 3077, + 2867, 2614, 3077, + 2867, 2615, 3077, + 2866, 2615, 3077, + 2866, 2615, 3076, + 2865, 2616, 3076, + 2864, 2617, 3076, + 2863, 2618, 3075, + 2861, 2619, 3074, + 2859, 2621, 3073, + 2856, 2623, 3072, + 2851, 2627, 3070, + 2846, 2631, 3067, + 2838, 2637, 3063, + 2828, 2644, 3059, + 2813, 2654, 3052, + 2793, 2667, 3043, + 2765, 2683, 3031, + 2724, 2705, 3014, + 2664, 2731, 2991, + 2567, 2765, 2958, + 2395, 2807, 2909, + 1957, 2857, 2835, + 0, 2916, 2711, + 0, 2985, 2465, + 0, 3064, 979, + 0, 3151, 0, + 0, 3247, 0, + 0, 3350, 0, + 0, 3458, 0, + 0, 3572, 0, + 0, 3690, 0, + 3046, 2641, 3143, + 3046, 2641, 3143, + 3046, 2641, 3143, + 3045, 2642, 3143, + 3045, 2642, 3143, + 3044, 2643, 3142, + 3044, 2643, 3142, + 3043, 2644, 3142, + 3042, 2646, 3141, + 3040, 2647, 3140, + 3038, 2650, 3139, + 3035, 2653, 3137, + 3032, 2657, 3135, + 3027, 2662, 3132, + 3020, 2669, 3127, + 3010, 2678, 3122, + 2997, 2691, 3114, + 2980, 2706, 3104, + 2955, 2727, 3090, + 2919, 2752, 3070, + 2867, 2785, 3042, + 2786, 2824, 3002, + 2648, 2873, 2942, + 2356, 2930, 2848, + 0, 2997, 2679, + 0, 3074, 2263, + 0, 3160, 0, + 0, 3254, 0, + 0, 3355, 0, + 0, 3463, 0, + 0, 3576, 0, + 0, 3693, 0, + 3210, 2674, 3219, + 3210, 2674, 3219, + 3210, 2675, 3219, + 3210, 2675, 3219, + 3209, 2675, 3219, + 3209, 2676, 3218, + 3209, 2677, 3218, + 3208, 2677, 3218, + 3207, 2679, 3217, + 3206, 2680, 3216, + 3205, 2682, 3215, + 3203, 2685, 3214, + 3200, 2689, 3212, + 3197, 2694, 3209, + 3192, 2701, 3206, + 3185, 2709, 3201, + 3177, 2721, 3195, + 3165, 2735, 3186, + 3148, 2754, 3174, + 3126, 2779, 3158, + 3093, 2809, 3135, + 3045, 2847, 3103, + 2973, 2893, 3055, + 2853, 2948, 2983, + 2618, 3013, 2865, + 1555, 3087, 2634, + 0, 3171, 1643, + 0, 3263, 0, + 0, 3362, 0, + 0, 3468, 0, + 0, 3580, 0, + 0, 3696, 0, + 3365, 2716, 3304, + 3365, 2716, 3304, + 3364, 2716, 3304, + 3364, 2716, 3304, + 3364, 2716, 3304, + 3364, 2717, 3303, + 3364, 2718, 3303, + 3363, 2718, 3303, + 3363, 2719, 3302, + 3362, 2721, 3302, + 3361, 2723, 3301, + 3359, 2725, 3300, + 3358, 2729, 3298, + 3355, 2734, 3296, + 3352, 2740, 3293, + 3347, 2748, 3289, + 3341, 2758, 3284, + 3333, 2772, 3277, + 3322, 2789, 3267, + 3306, 2812, 3254, + 3285, 2840, 3235, + 3254, 2876, 3210, + 3209, 2919, 3173, + 3142, 2971, 3118, + 3033, 3033, 3033, + 2828, 3104, 2887, + 2176, 3185, 2564, + 0, 3274, 0, + 0, 3372, 0, + 0, 3476, 0, + 0, 3586, 0, + 0, 3701, 0, + 3513, 2765, 3397, + 3513, 2765, 3397, + 3513, 2766, 3397, + 3513, 2766, 3397, + 3513, 2766, 3397, + 3512, 2767, 3397, + 3512, 2767, 3397, + 3512, 2768, 3396, + 3511, 2769, 3396, + 3511, 2770, 3395, + 3510, 2772, 3395, + 3509, 2774, 3394, + 3508, 2777, 3392, + 3506, 2781, 3391, + 3504, 2787, 3388, + 3500, 2794, 3385, + 3496, 2804, 3381, + 3490, 2816, 3375, + 3482, 2832, 3367, + 3471, 2852, 3357, + 3457, 2878, 3342, + 3436, 2911, 3322, + 3406, 2951, 3293, + 3364, 3000, 3252, + 3300, 3058, 3190, + 3198, 3126, 3092, + 3011, 3203, 2914, + 2491, 3289, 2450, + 0, 3384, 0, + 0, 3486, 0, + 0, 3594, 0, + 0, 3707, 0, + 3657, 2824, 3498, + 3657, 2824, 3498, + 3657, 2825, 3498, + 3657, 2825, 3498, + 3656, 2825, 3498, + 3656, 2825, 3498, + 3656, 2826, 3497, + 3656, 2827, 3497, + 3656, 2827, 3497, + 3655, 2829, 3497, + 3655, 2830, 3496, + 3654, 2832, 3495, + 3653, 2835, 3494, + 3652, 2839, 3493, + 3650, 2843, 3491, + 3648, 2850, 3488, + 3645, 2858, 3485, + 3640, 2869, 3480, + 3635, 2883, 3474, + 3627, 2902, 3466, + 3616, 2925, 3454, + 3602, 2955, 3439, + 3582, 2992, 3417, + 3553, 3036, 3386, + 3512, 3090, 3340, + 3451, 3154, 3272, + 3353, 3227, 3160, + 3177, 3309, 2949, + 2723, 3400, 2233, + 0, 3498, 0, + 0, 3604, 0, + 0, 3715, 0, + 3797, 2893, 3605, + 3797, 2893, 3605, + 3797, 2893, 3605, + 3797, 2893, 3605, + 3797, 2894, 3605, + 3797, 2894, 3605, + 3797, 2894, 3605, + 3797, 2895, 3605, + 3797, 2896, 3604, + 3796, 2897, 3604, + 3796, 2898, 3604, + 3795, 2900, 3603, + 3795, 2902, 3602, + 3794, 2905, 3601, + 3792, 2909, 3600, + 3791, 2915, 3598, + 3788, 2922, 3595, + 3785, 2932, 3591, + 3781, 2944, 3587, + 3776, 2960, 3580, + 3768, 2981, 3571, + 3758, 3007, 3559, + 3744, 3040, 3542, + 3724, 3081, 3519, + 3696, 3130, 3486, + 3656, 3188, 3437, + 3596, 3256, 3362, + 3502, 3334, 3238, + 3333, 3420, 2991, + 2918, 3515, 1456, + 0, 3617, 0, + 0, 3725, 0, + 3936, 2971, 3718, + 3936, 2971, 3718, + 3936, 2971, 3718, + 3936, 2971, 3718, + 3936, 2972, 3718, + 3936, 2972, 3717, + 3935, 2972, 3717, + 3935, 2973, 3717, + 3935, 2973, 3717, + 3935, 2974, 3717, + 3935, 2975, 3716, + 3934, 2977, 3716, + 3934, 2979, 3715, + 3933, 2981, 3714, + 3932, 2985, 3713, + 3931, 2990, 3712, + 3929, 2996, 3710, + 3927, 3004, 3707, + 3924, 3015, 3703, + 3920, 3028, 3698, + 3914, 3046, 3691, + 3907, 3069, 3682, + 3897, 3098, 3669, + 3883, 3134, 3652, + 3863, 3178, 3627, + 3836, 3231, 3592, + 3797, 3293, 3540, + 3738, 3365, 3460, + 3646, 3446, 3325, + 3483, 3536, 3042, + 3092, 3634, 0, + 0, 3738, 0, + 4073, 3058, 3835, + 4073, 3058, 3835, + 4072, 3058, 3835, + 4072, 3058, 3835, + 4072, 3059, 3834, + 4072, 3059, 3834, + 4072, 3059, 3834, + 4072, 3059, 3834, + 4072, 3060, 3834, + 4072, 3061, 3834, + 4072, 3062, 3834, + 4071, 3063, 3833, + 4071, 3064, 3833, + 4071, 3067, 3832, + 4070, 3070, 3831, + 4069, 3073, 3830, + 4068, 3079, 3828, + 4066, 3085, 3826, + 4064, 3094, 3823, + 4061, 3106, 3820, + 4057, 3121, 3814, + 4051, 3140, 3807, + 4044, 3165, 3798, + 4034, 3196, 3784, + 4020, 3235, 3766, + 4001, 3282, 3741, + 3974, 3338, 3704, + 3935, 3404, 3650, + 3877, 3479, 3565, + 3787, 3563, 3420, + 3627, 3656, 3103, + 3253, 3756, 0, + 4095, 3153, 3955, + 4095, 3153, 3955, + 4095, 3153, 3955, + 4095, 3154, 3955, + 4095, 3154, 3955, + 4095, 3154, 3955, + 4095, 3154, 3955, + 4095, 3154, 3955, + 4095, 3155, 3955, + 4095, 3155, 3954, + 4095, 3156, 3954, + 4095, 3157, 3954, + 4095, 3159, 3954, + 4095, 3160, 3953, + 4095, 3163, 3952, + 4095, 3166, 3951, + 4095, 3170, 3950, + 4095, 3176, 3949, + 4095, 3183, 3946, + 4095, 3192, 3943, + 4095, 3205, 3940, + 4095, 3221, 3934, + 4095, 3242, 3927, + 4095, 3269, 3917, + 4095, 3302, 3903, + 4095, 3342, 3885, + 4095, 3392, 3858, + 4095, 3451, 3820, + 4072, 3519, 3764, + 4015, 3596, 3676, + 3925, 3683, 3522, + 3768, 3778, 3173, + 4095, 3256, 4078, + 4095, 3256, 4078, + 4095, 3256, 4078, + 4095, 3256, 4078, + 4095, 3256, 4078, + 4095, 3256, 4078, + 4095, 3256, 4078, + 4095, 3257, 4078, + 4095, 3257, 4078, + 4095, 3257, 4078, + 4095, 3258, 4078, + 4095, 3259, 4077, + 4095, 3260, 4077, + 4095, 3261, 4077, + 4095, 3263, 4076, + 4095, 3266, 4075, + 4095, 3269, 4075, + 4095, 3274, 4073, + 4095, 3280, 4072, + 4095, 3287, 4069, + 4095, 3297, 4066, + 4095, 3311, 4062, + 4095, 3328, 4057, + 4095, 3350, 4049, + 4095, 3378, 4039, + 4095, 3413, 4025, + 4095, 3455, 4006, + 4095, 3507, 3979, + 4095, 3567, 3940, + 4095, 3638, 3882, + 4095, 3718, 3791, + 4062, 3806, 3631, + 0, 2656, 2925, + 0, 2657, 2925, + 0, 2657, 2925, + 0, 2657, 2925, + 0, 2658, 2924, + 0, 2658, 2924, + 0, 2659, 2923, + 0, 2660, 2923, + 0, 2661, 2921, + 0, 2663, 2920, + 0, 2665, 2918, + 0, 2668, 2915, + 0, 2672, 2911, + 0, 2677, 2906, + 0, 2684, 2899, + 0, 2693, 2890, + 0, 2705, 2878, + 0, 2720, 2860, + 0, 2739, 2835, + 0, 2764, 2800, + 0, 2796, 2749, + 0, 2835, 2669, + 0, 2882, 2534, + 0, 2939, 2253, + 0, 3005, 0, + 0, 3080, 0, + 0, 3165, 0, + 0, 3258, 0, + 0, 3358, 0, + 0, 3465, 0, + 0, 3578, 0, + 0, 3694, 0, + 0, 2657, 2926, + 0, 2657, 2926, + 0, 2657, 2925, + 0, 2657, 2925, + 0, 2658, 2925, + 0, 2658, 2924, + 0, 2659, 2924, + 0, 2660, 2923, + 0, 2661, 2922, + 0, 2663, 2920, + 0, 2665, 2918, + 0, 2668, 2915, + 0, 2672, 2912, + 0, 2677, 2907, + 0, 2684, 2900, + 0, 2693, 2890, + 0, 2705, 2878, + 0, 2720, 2860, + 0, 2739, 2836, + 0, 2765, 2801, + 0, 2796, 2749, + 0, 2835, 2669, + 0, 2882, 2535, + 0, 2939, 2254, + 0, 3005, 0, + 0, 3080, 0, + 0, 3165, 0, + 0, 3258, 0, + 0, 3358, 0, + 0, 3465, 0, + 0, 3578, 0, + 0, 3694, 0, + 0, 2657, 2926, + 0, 2657, 2926, + 0, 2657, 2926, + 0, 2657, 2925, + 0, 2658, 2925, + 0, 2658, 2925, + 0, 2659, 2924, + 0, 2660, 2923, + 0, 2661, 2922, + 0, 2663, 2920, + 0, 2665, 2918, + 0, 2668, 2916, + 0, 2672, 2912, + 0, 2677, 2907, + 0, 2684, 2900, + 0, 2693, 2891, + 0, 2705, 2878, + 0, 2720, 2861, + 0, 2740, 2836, + 0, 2765, 2801, + 0, 2796, 2749, + 0, 2835, 2670, + 0, 2882, 2535, + 0, 2939, 2255, + 0, 3005, 0, + 0, 3080, 0, + 0, 3165, 0, + 0, 3258, 0, + 0, 3358, 0, + 0, 3465, 0, + 0, 3578, 0, + 0, 3694, 0, + 0, 2657, 2926, + 0, 2657, 2926, + 0, 2657, 2926, + 0, 2657, 2926, + 0, 2658, 2925, + 0, 2658, 2925, + 0, 2659, 2924, + 0, 2660, 2923, + 0, 2661, 2922, + 0, 2663, 2921, + 0, 2665, 2919, + 0, 2668, 2916, + 0, 2672, 2912, + 0, 2677, 2907, + 0, 2684, 2900, + 0, 2693, 2891, + 0, 2705, 2879, + 0, 2720, 2861, + 0, 2740, 2836, + 0, 2765, 2801, + 0, 2796, 2750, + 0, 2835, 2670, + 0, 2882, 2536, + 0, 2939, 2257, + 0, 3005, 0, + 0, 3080, 0, + 0, 3165, 0, + 0, 3258, 0, + 0, 3358, 0, + 0, 3465, 0, + 0, 3578, 0, + 0, 3694, 0, + 0, 2657, 2927, + 0, 2657, 2927, + 0, 2657, 2927, + 0, 2657, 2926, + 0, 2658, 2926, + 0, 2658, 2925, + 0, 2659, 2925, + 0, 2660, 2924, + 0, 2661, 2923, + 0, 2663, 2921, + 0, 2665, 2919, + 0, 2668, 2917, + 0, 2672, 2913, + 0, 2677, 2908, + 0, 2684, 2901, + 0, 2693, 2892, + 0, 2705, 2879, + 0, 2720, 2862, + 0, 2740, 2837, + 0, 2765, 2802, + 0, 2796, 2751, + 0, 2835, 2671, + 0, 2882, 2537, + 0, 2939, 2259, + 0, 3005, 0, + 0, 3080, 0, + 0, 3165, 0, + 0, 3258, 0, + 0, 3358, 0, + 0, 3465, 0, + 0, 3578, 0, + 0, 3694, 0, + 0, 2657, 2928, + 0, 2657, 2927, + 0, 2657, 2927, + 0, 2658, 2927, + 0, 2658, 2927, + 0, 2659, 2926, + 0, 2659, 2926, + 0, 2660, 2925, + 0, 2661, 2924, + 0, 2663, 2922, + 0, 2665, 2920, + 0, 2668, 2917, + 0, 2672, 2914, + 0, 2677, 2909, + 0, 2684, 2902, + 0, 2693, 2893, + 0, 2705, 2880, + 0, 2720, 2862, + 0, 2740, 2838, + 0, 2765, 2803, + 0, 2796, 2752, + 0, 2835, 2673, + 0, 2882, 2539, + 0, 2939, 2262, + 0, 3005, 0, + 0, 3080, 0, + 0, 3165, 0, + 0, 3258, 0, + 0, 3358, 0, + 0, 3465, 0, + 0, 3578, 0, + 0, 3694, 0, + 0, 2657, 2929, + 0, 2657, 2928, + 0, 2658, 2928, + 0, 2658, 2928, + 0, 2658, 2928, + 0, 2659, 2927, + 0, 2660, 2926, + 0, 2660, 2926, + 0, 2662, 2925, + 0, 2663, 2923, + 0, 2666, 2921, + 0, 2669, 2918, + 0, 2672, 2915, + 0, 2678, 2910, + 0, 2684, 2903, + 0, 2693, 2894, + 0, 2705, 2881, + 0, 2720, 2864, + 0, 2740, 2839, + 0, 2765, 2804, + 0, 2796, 2753, + 0, 2835, 2674, + 0, 2883, 2541, + 0, 2939, 2266, + 0, 3005, 0, + 0, 3080, 0, + 0, 3165, 0, + 0, 3258, 0, + 0, 3358, 0, + 0, 3465, 0, + 0, 3578, 0, + 0, 3694, 0, + 0, 2658, 2930, + 0, 2658, 2930, + 0, 2658, 2929, + 0, 2658, 2929, + 0, 2659, 2929, + 0, 2659, 2928, + 0, 2660, 2928, + 0, 2661, 2927, + 0, 2662, 2926, + 0, 2664, 2924, + 0, 2666, 2922, + 0, 2669, 2919, + 0, 2673, 2916, + 0, 2678, 2911, + 0, 2685, 2904, + 0, 2694, 2895, + 0, 2706, 2882, + 0, 2721, 2865, + 0, 2740, 2841, + 0, 2765, 2806, + 0, 2797, 2755, + 0, 2836, 2676, + 0, 2883, 2544, + 0, 2939, 2271, + 0, 3005, 0, + 0, 3080, 0, + 0, 3165, 0, + 0, 3258, 0, + 0, 3358, 0, + 0, 3465, 0, + 0, 3578, 0, + 0, 3694, 0, + 0, 2658, 2931, + 0, 2658, 2931, + 0, 2658, 2931, + 0, 2659, 2931, + 0, 2659, 2931, + 0, 2660, 2930, + 0, 2660, 2929, + 0, 2661, 2929, + 0, 2662, 2927, + 0, 2664, 2926, + 0, 2666, 2924, + 0, 2669, 2921, + 0, 2673, 2918, + 0, 2678, 2913, + 0, 2685, 2906, + 0, 2694, 2897, + 0, 2706, 2884, + 0, 2721, 2867, + 0, 2741, 2843, + 0, 2766, 2808, + 0, 2797, 2757, + 0, 2836, 2679, + 0, 2883, 2548, + 0, 2939, 2279, + 0, 3005, 0, + 0, 3081, 0, + 0, 3165, 0, + 0, 3258, 0, + 0, 3359, 0, + 0, 3465, 0, + 0, 3578, 0, + 0, 3694, 0, + 0, 2659, 2934, + 0, 2659, 2934, + 0, 2659, 2933, + 0, 2659, 2933, + 0, 2660, 2933, + 0, 2660, 2932, + 0, 2661, 2932, + 0, 2662, 2931, + 0, 2663, 2930, + 0, 2665, 2928, + 0, 2667, 2926, + 0, 2670, 2924, + 0, 2674, 2920, + 0, 2679, 2915, + 0, 2686, 2908, + 0, 2695, 2899, + 0, 2706, 2887, + 0, 2722, 2870, + 0, 2741, 2845, + 0, 2766, 2811, + 0, 2797, 2761, + 0, 2836, 2683, + 0, 2883, 2553, + 0, 2940, 2288, + 0, 3006, 0, + 0, 3081, 0, + 0, 3165, 0, + 0, 3258, 0, + 0, 3359, 0, + 0, 3466, 0, + 0, 3578, 0, + 0, 3695, 0, + 0, 2659, 2937, + 0, 2659, 2937, + 0, 2660, 2936, + 0, 2660, 2936, + 0, 2660, 2936, + 0, 2661, 2935, + 0, 2662, 2935, + 0, 2663, 2934, + 0, 2664, 2933, + 0, 2665, 2931, + 0, 2668, 2929, + 0, 2671, 2927, + 0, 2674, 2923, + 0, 2680, 2918, + 0, 2686, 2911, + 0, 2695, 2902, + 0, 2707, 2890, + 0, 2722, 2873, + 0, 2742, 2849, + 0, 2767, 2815, + 0, 2798, 2765, + 0, 2837, 2688, + 0, 2884, 2560, + 0, 2940, 2300, + 0, 3006, 0, + 0, 3081, 0, + 0, 3166, 0, + 0, 3258, 0, + 0, 3359, 0, + 0, 3466, 0, + 0, 3578, 0, + 0, 3695, 0, + 0, 2660, 2941, + 0, 2660, 2941, + 0, 2661, 2940, + 0, 2661, 2940, + 0, 2661, 2940, + 0, 2662, 2939, + 0, 2663, 2939, + 0, 2664, 2938, + 0, 2665, 2937, + 0, 2666, 2935, + 0, 2669, 2933, + 0, 2672, 2931, + 0, 2675, 2927, + 0, 2681, 2922, + 0, 2687, 2916, + 0, 2696, 2907, + 0, 2708, 2894, + 0, 2723, 2877, + 0, 2743, 2854, + 0, 2768, 2820, + 0, 2799, 2771, + 0, 2837, 2695, + 0, 2885, 2569, + 0, 2941, 2316, + 0, 3006, 0, + 0, 3082, 0, + 0, 3166, 0, + 0, 3259, 0, + 0, 3359, 0, + 0, 3466, 0, + 0, 3578, 0, + 0, 3695, 0, + 0, 2662, 2946, + 0, 2662, 2946, + 0, 2662, 2946, + 0, 2662, 2945, + 0, 2663, 2945, + 0, 2663, 2945, + 0, 2664, 2944, + 0, 2665, 2943, + 0, 2666, 2942, + 0, 2668, 2941, + 0, 2670, 2939, + 0, 2673, 2936, + 0, 2677, 2932, + 0, 2682, 2928, + 0, 2689, 2921, + 0, 2698, 2912, + 0, 2709, 2900, + 0, 2724, 2883, + 0, 2744, 2860, + 0, 2769, 2827, + 0, 2800, 2778, + 0, 2838, 2704, + 0, 2885, 2581, + 0, 2941, 2336, + 0, 3007, 938, + 0, 3082, 0, + 0, 3166, 0, + 0, 3259, 0, + 0, 3359, 0, + 0, 3466, 0, + 0, 3578, 0, + 0, 3695, 0, + 0, 2663, 2953, + 0, 2664, 2953, + 0, 2664, 2952, + 0, 2664, 2952, + 0, 2665, 2952, + 0, 2665, 2951, + 0, 2666, 2951, + 0, 2667, 2950, + 0, 2668, 2949, + 0, 2670, 2948, + 0, 2672, 2946, + 0, 2675, 2943, + 0, 2679, 2940, + 0, 2684, 2935, + 0, 2690, 2928, + 0, 2699, 2920, + 0, 2711, 2908, + 0, 2726, 2891, + 0, 2745, 2868, + 0, 2770, 2836, + 0, 2801, 2788, + 0, 2840, 2716, + 0, 2886, 2596, + 0, 2942, 2362, + 0, 3008, 1311, + 0, 3083, 0, + 0, 3167, 0, + 0, 3260, 0, + 0, 3360, 0, + 0, 3466, 0, + 0, 3579, 0, + 0, 3695, 0, + 0, 2666, 2962, + 0, 2666, 2962, + 0, 2666, 2962, + 0, 2667, 2961, + 0, 2667, 2961, + 0, 2667, 2961, + 0, 2668, 2960, + 0, 2669, 2959, + 0, 2670, 2958, + 0, 2672, 2957, + 0, 2674, 2955, + 0, 2677, 2952, + 0, 2681, 2949, + 0, 2686, 2944, + 0, 2693, 2938, + 0, 2701, 2929, + 0, 2713, 2918, + 0, 2728, 2902, + 0, 2747, 2879, + 0, 2772, 2848, + 0, 2803, 2801, + 0, 2841, 2731, + 0, 2888, 2616, + 0, 2944, 2395, + 0, 3009, 1565, + 0, 3084, 0, + 0, 3168, 0, + 0, 3260, 0, + 0, 3360, 0, + 0, 3467, 0, + 0, 3579, 0, + 0, 3695, 0, + 0, 2669, 2974, + 0, 2669, 2974, + 0, 2669, 2973, + 0, 2670, 2973, + 0, 2670, 2973, + 0, 2671, 2972, + 0, 2671, 2972, + 0, 2672, 2971, + 0, 2673, 2970, + 0, 2675, 2969, + 0, 2677, 2967, + 0, 2680, 2964, + 0, 2684, 2961, + 0, 2689, 2957, + 0, 2696, 2950, + 0, 2704, 2942, + 0, 2716, 2931, + 0, 2731, 2915, + 0, 2750, 2894, + 0, 2774, 2863, + 0, 2805, 2818, + 0, 2843, 2751, + 0, 2890, 2641, + 0, 2945, 2435, + 0, 3010, 1770, + 0, 3085, 0, + 0, 3169, 0, + 0, 3261, 0, + 0, 3361, 0, + 0, 3467, 0, + 0, 3579, 0, + 0, 3696, 0, + 0, 2673, 2989, + 0, 2673, 2989, + 0, 2674, 2989, + 0, 2674, 2989, + 0, 2674, 2988, + 0, 2675, 2988, + 0, 2676, 2987, + 0, 2676, 2987, + 0, 2678, 2986, + 0, 2679, 2984, + 0, 2681, 2982, + 0, 2684, 2980, + 0, 2688, 2977, + 0, 2693, 2973, + 0, 2700, 2967, + 0, 2708, 2959, + 0, 2720, 2948, + 0, 2735, 2933, + 0, 2754, 2912, + 0, 2778, 2882, + 0, 2808, 2840, + 0, 2846, 2775, + 0, 2893, 2672, + 0, 2948, 2483, + 0, 3013, 1950, + 0, 3087, 0, + 0, 3170, 0, + 0, 3262, 0, + 0, 3362, 0, + 0, 3468, 0, + 0, 3580, 0, + 0, 3696, 0, + 0, 2679, 3009, + 0, 2679, 3009, + 0, 2679, 3009, + 0, 2680, 3008, + 0, 2680, 3008, + 0, 2680, 3008, + 0, 2681, 3007, + 0, 2682, 3007, + 0, 2683, 3006, + 0, 2685, 3004, + 0, 2687, 3003, + 0, 2690, 3000, + 0, 2693, 2997, + 0, 2698, 2993, + 0, 2705, 2987, + 0, 2714, 2980, + 0, 2725, 2969, + 0, 2739, 2955, + 0, 2758, 2935, + 0, 2782, 2907, + 0, 2813, 2867, + 0, 2850, 2807, + 0, 2896, 2711, + 0, 2951, 2541, + 0, 3015, 2115, + 0, 3089, 0, + 0, 3172, 0, + 0, 3264, 0, + 0, 3363, 0, + 0, 3469, 0, + 0, 3581, 0, + 0, 3697, 0, + 1182, 2686, 3034, + 1173, 2686, 3034, + 1160, 2687, 3034, + 1143, 2687, 3034, + 1119, 2687, 3033, + 1084, 2688, 3033, + 1033, 2688, 3033, + 955, 2689, 3032, + 824, 2691, 3031, + 554, 2692, 3030, + 0, 2694, 3028, + 0, 2697, 3026, + 0, 2701, 3023, + 0, 2706, 3019, + 0, 2712, 3014, + 0, 2720, 3007, + 0, 2731, 2997, + 0, 2746, 2983, + 0, 2764, 2965, + 0, 2788, 2939, + 0, 2818, 2901, + 0, 2855, 2846, + 0, 2901, 2759, + 0, 2955, 2608, + 0, 3019, 2271, + 0, 3092, 0, + 0, 3175, 0, + 0, 3266, 0, + 0, 3365, 0, + 0, 3470, 0, + 0, 3582, 0, + 0, 3697, 0, + 2191, 2696, 3066, + 2190, 2696, 3066, + 2189, 2696, 3066, + 2187, 2697, 3065, + 2185, 2697, 3065, + 2182, 2698, 3065, + 2177, 2698, 3064, + 2172, 2699, 3064, + 2164, 2700, 3063, + 2153, 2702, 3062, + 2138, 2704, 3060, + 2117, 2706, 3058, + 2088, 2710, 3055, + 2046, 2715, 3052, + 1983, 2721, 3047, + 1881, 2729, 3040, + 1696, 2740, 3031, + 1189, 2754, 3019, + 0, 2773, 3001, + 0, 2796, 2977, + 0, 2825, 2943, + 0, 2862, 2893, + 0, 2907, 2815, + 0, 2960, 2685, + 0, 3023, 2419, + 0, 3096, 0, + 0, 3178, 0, + 0, 3269, 0, + 0, 3367, 0, + 0, 3472, 0, + 0, 3583, 0, + 0, 3699, 0, + 2548, 2709, 3105, + 2548, 2709, 3105, + 2547, 2709, 3105, + 2546, 2709, 3105, + 2545, 2710, 3104, + 2544, 2710, 3104, + 2542, 2711, 3104, + 2539, 2712, 3103, + 2536, 2713, 3102, + 2531, 2714, 3101, + 2524, 2716, 3100, + 2516, 2719, 3098, + 2504, 2722, 3095, + 2487, 2727, 3092, + 2464, 2733, 3088, + 2432, 2741, 3082, + 2384, 2752, 3073, + 2311, 2766, 3062, + 2191, 2783, 3046, + 1956, 2806, 3025, + 876, 2835, 2994, + 0, 2871, 2949, + 0, 2915, 2881, + 0, 2967, 2771, + 0, 3030, 2564, + 0, 3101, 1888, + 0, 3182, 0, + 0, 3272, 0, + 0, 3370, 0, + 0, 3474, 0, + 0, 3585, 0, + 0, 3700, 0, + 2796, 2725, 3153, + 2796, 2725, 3152, + 2796, 2725, 3152, + 2795, 2726, 3152, + 2795, 2726, 3152, + 2794, 2726, 3152, + 2793, 2727, 3151, + 2791, 2728, 3151, + 2789, 2729, 3150, + 2787, 2730, 3149, + 2783, 2732, 3148, + 2778, 2735, 3146, + 2771, 2738, 3144, + 2762, 2743, 3141, + 2750, 2749, 3137, + 2733, 2756, 3131, + 2709, 2767, 3124, + 2675, 2780, 3114, + 2625, 2797, 3100, + 2548, 2819, 3081, + 2419, 2847, 3054, + 2157, 2882, 3015, + 0, 2925, 2957, + 0, 2977, 2865, + 0, 3038, 2704, + 0, 3108, 2323, + 0, 3188, 0, + 0, 3277, 0, + 0, 3374, 0, + 0, 3478, 0, + 0, 3587, 0, + 0, 3702, 0, + 2999, 2746, 3209, + 2999, 2746, 3209, + 2999, 2746, 3209, + 2999, 2747, 3209, + 2998, 2747, 3209, + 2998, 2747, 3209, + 2997, 2748, 3208, + 2996, 2749, 3208, + 2995, 2750, 3207, + 2993, 2751, 3206, + 2991, 2753, 3205, + 2988, 2755, 3204, + 2984, 2759, 3202, + 2978, 2763, 3199, + 2970, 2769, 3196, + 2960, 2776, 3191, + 2945, 2786, 3184, + 2925, 2799, 3175, + 2897, 2815, 3163, + 2857, 2837, 3147, + 2796, 2864, 3123, + 2699, 2897, 3090, + 2527, 2939, 3041, + 2089, 2989, 2967, + 0, 3048, 2843, + 0, 3118, 2597, + 0, 3196, 1111, + 0, 3283, 0, + 0, 3379, 0, + 0, 3482, 0, + 0, 3590, 0, + 0, 3704, 0, + 3178, 2773, 3276, + 3178, 2773, 3275, + 3178, 2773, 3275, + 3178, 2773, 3275, + 3177, 2774, 3275, + 3177, 2774, 3275, + 3177, 2775, 3275, + 3176, 2775, 3274, + 3175, 2776, 3274, + 3174, 2778, 3273, + 3172, 2779, 3272, + 3170, 2782, 3271, + 3167, 2785, 3269, + 3164, 2789, 3267, + 3159, 2794, 3264, + 3152, 2801, 3260, + 3142, 2811, 3254, + 3130, 2823, 3246, + 3112, 2838, 3236, + 3087, 2859, 3222, + 3051, 2884, 3202, + 2999, 2917, 3174, + 2918, 2956, 3134, + 2780, 3005, 3074, + 2488, 3062, 2980, + 0, 3130, 2811, + 0, 3206, 2395, + 0, 3292, 0, + 0, 3386, 0, + 0, 3487, 0, + 0, 3595, 0, + 0, 3708, 0, + 3342, 2806, 3351, + 3342, 2806, 3351, + 3342, 2807, 3351, + 3342, 2807, 3351, + 3342, 2807, 3351, + 3341, 2807, 3351, + 3341, 2808, 3350, + 3341, 2809, 3350, + 3340, 2810, 3350, + 3339, 2811, 3349, + 3338, 2812, 3348, + 3337, 2814, 3347, + 3335, 2817, 3346, + 3332, 2821, 3344, + 3329, 2826, 3341, + 3324, 2833, 3338, + 3318, 2841, 3333, + 3309, 2853, 3327, + 3297, 2867, 3318, + 3281, 2886, 3306, + 3258, 2911, 3290, + 3225, 2941, 3267, + 3177, 2979, 3235, + 3105, 3025, 3187, + 2985, 3080, 3115, + 2750, 3145, 2997, + 1687, 3219, 2766, + 0, 3303, 1775, + 0, 3395, 0, + 0, 3494, 0, + 0, 3600, 0, + 0, 3712, 0, + 3497, 2847, 3436, + 3497, 2848, 3436, + 3497, 2848, 3436, + 3497, 2848, 3436, + 3496, 2848, 3436, + 3496, 2849, 3436, + 3496, 2849, 3436, + 3496, 2850, 3435, + 3495, 2850, 3435, + 3495, 2852, 3434, + 3494, 2853, 3434, + 3493, 2855, 3433, + 3492, 2858, 3432, + 3490, 2861, 3430, + 3487, 2866, 3428, + 3484, 2872, 3425, + 3479, 2880, 3421, + 3473, 2890, 3416, + 3465, 2904, 3409, + 3454, 2921, 3399, + 3438, 2944, 3386, + 3417, 2972, 3368, + 3386, 3008, 3342, + 3341, 3051, 3305, + 3274, 3103, 3250, + 3165, 3165, 3165, + 2960, 3236, 3019, + 2308, 3317, 2696, + 0, 3406, 0, + 0, 3504, 0, + 0, 3608, 0, + 0, 3718, 0, + 3645, 2897, 3529, + 3645, 2897, 3529, + 3645, 2898, 3529, + 3645, 2898, 3529, + 3645, 2898, 3529, + 3645, 2898, 3529, + 3644, 2899, 3529, + 3644, 2899, 3529, + 3644, 2900, 3528, + 3644, 2901, 3528, + 3643, 2902, 3527, + 3642, 2904, 3527, + 3641, 2906, 3526, + 3640, 2909, 3524, + 3638, 2914, 3523, + 3636, 2919, 3520, + 3633, 2926, 3517, + 3628, 2936, 3513, + 3622, 2948, 3507, + 3614, 2964, 3500, + 3604, 2984, 3489, + 3589, 3011, 3474, + 3568, 3043, 3454, + 3539, 3084, 3426, + 3496, 3132, 3384, + 3432, 3191, 3322, + 3330, 3258, 3224, + 3143, 3335, 3046, + 2623, 3421, 2582, + 0, 3516, 0, + 0, 3618, 0, + 0, 3726, 0, + 3789, 2956, 3630, + 3789, 2956, 3630, + 3789, 2957, 3630, + 3789, 2957, 3630, + 3789, 2957, 3630, + 3789, 2957, 3630, + 3788, 2958, 3630, + 3788, 2958, 3630, + 3788, 2959, 3629, + 3788, 2960, 3629, + 3787, 2961, 3629, + 3787, 2962, 3628, + 3786, 2964, 3627, + 3785, 2967, 3626, + 3784, 2971, 3625, + 3782, 2976, 3623, + 3780, 2982, 3620, + 3777, 2990, 3617, + 3772, 3001, 3613, + 3767, 3015, 3606, + 3759, 3034, 3598, + 3748, 3057, 3587, + 3734, 3087, 3571, + 3714, 3124, 3549, + 3685, 3169, 3518, + 3644, 3222, 3473, + 3583, 3286, 3404, + 3485, 3359, 3292, + 3309, 3441, 3081, + 2855, 3532, 2365, + 0, 3630, 0, + 0, 3736, 0, + 3929, 3025, 3737, + 3929, 3025, 3737, + 3929, 3025, 3737, + 3929, 3025, 3737, + 3929, 3026, 3737, + 3929, 3026, 3737, + 3929, 3026, 3737, + 3929, 3026, 3737, + 3929, 3027, 3737, + 3929, 3028, 3736, + 3928, 3029, 3736, + 3928, 3030, 3736, + 3927, 3032, 3735, + 3927, 3034, 3734, + 3926, 3037, 3733, + 3925, 3042, 3732, + 3923, 3047, 3730, + 3921, 3054, 3727, + 3918, 3064, 3723, + 3913, 3076, 3719, + 3908, 3092, 3712, + 3900, 3113, 3703, + 3890, 3139, 3691, + 3876, 3172, 3674, + 3856, 3213, 3651, + 3828, 3262, 3618, + 3788, 3320, 3569, + 3728, 3388, 3494, + 3634, 3466, 3370, + 3465, 3552, 3123, + 3050, 3647, 1588, + 0, 3749, 0, + 4068, 3103, 3850, + 4068, 3103, 3850, + 4068, 3103, 3850, + 4068, 3103, 3850, + 4068, 3104, 3850, + 4068, 3104, 3850, + 4068, 3104, 3850, + 4068, 3104, 3849, + 4067, 3105, 3849, + 4067, 3105, 3849, + 4067, 3106, 3849, + 4067, 3107, 3849, + 4066, 3109, 3848, + 4066, 3111, 3847, + 4065, 3114, 3847, + 4064, 3117, 3845, + 4063, 3122, 3844, + 4061, 3128, 3842, + 4059, 3136, 3839, + 4056, 3147, 3835, + 4052, 3160, 3830, + 4046, 3178, 3823, + 4039, 3201, 3814, + 4029, 3230, 3801, + 4015, 3266, 3784, + 3995, 3310, 3759, + 3968, 3363, 3724, + 3929, 3425, 3672, + 3870, 3497, 3592, + 3778, 3578, 3457, + 3615, 3668, 3174, + 3224, 3766, 0, + 4095, 3190, 3967, + 4095, 3190, 3967, + 4095, 3190, 3967, + 4095, 3190, 3967, + 4095, 3191, 3967, + 4095, 3191, 3967, + 4095, 3191, 3967, + 4095, 3191, 3966, + 4095, 3192, 3966, + 4095, 3192, 3966, + 4095, 3193, 3966, + 4095, 3194, 3966, + 4095, 3195, 3965, + 4095, 3197, 3965, + 4095, 3199, 3964, + 4095, 3202, 3963, + 4095, 3206, 3962, + 4095, 3211, 3961, + 4095, 3217, 3958, + 4095, 3226, 3956, + 4095, 3238, 3952, + 4095, 3253, 3946, + 4095, 3273, 3939, + 4095, 3297, 3930, + 4095, 3328, 3917, + 4095, 3367, 3898, + 4095, 3414, 3873, + 4095, 3470, 3836, + 4067, 3536, 3782, + 4009, 3611, 3697, + 3919, 3695, 3552, + 3759, 3788, 3235, + 4095, 3285, 4087, + 4095, 3285, 4087, + 4095, 3286, 4087, + 4095, 3286, 4087, + 4095, 3286, 4087, + 4095, 3286, 4087, + 4095, 3286, 4087, + 4095, 3286, 4087, + 4095, 3287, 4087, + 4095, 3287, 4087, + 4095, 3288, 4087, + 4095, 3288, 4086, + 4095, 3289, 4086, + 4095, 3291, 4086, + 4095, 3292, 4085, + 4095, 3295, 4084, + 4095, 3298, 4084, + 4095, 3302, 4082, + 4095, 3308, 4081, + 4095, 3315, 4079, + 4095, 3325, 4076, + 4095, 3337, 4072, + 4095, 3353, 4066, + 4095, 3374, 4059, + 4095, 3401, 4049, + 4095, 3434, 4036, + 4095, 3475, 4017, + 4095, 3524, 3990, + 4095, 3583, 3952, + 4095, 3651, 3896, + 4095, 3729, 3808, + 4057, 3815, 3655, + 0, 2788, 3057, + 0, 2789, 3057, + 0, 2789, 3057, + 0, 2789, 3057, + 0, 2789, 3057, + 0, 2790, 3056, + 0, 2790, 3056, + 0, 2791, 3055, + 0, 2792, 3054, + 0, 2793, 3053, + 0, 2795, 3052, + 0, 2797, 3050, + 0, 2800, 3047, + 0, 2804, 3043, + 0, 2809, 3038, + 0, 2816, 3031, + 0, 2825, 3022, + 0, 2837, 3009, + 0, 2852, 2992, + 0, 2872, 2967, + 0, 2897, 2932, + 0, 2928, 2880, + 0, 2967, 2801, + 0, 3014, 2666, + 0, 3071, 2384, + 0, 3137, 0, + 0, 3212, 0, + 0, 3297, 0, + 0, 3390, 0, + 0, 3490, 0, + 0, 3597, 0, + 0, 3710, 0, + 0, 2788, 3058, + 0, 2789, 3058, + 0, 2789, 3057, + 0, 2789, 3057, + 0, 2789, 3057, + 0, 2790, 3057, + 0, 2790, 3056, + 0, 2791, 3055, + 0, 2792, 3055, + 0, 2793, 3053, + 0, 2795, 3052, + 0, 2797, 3050, + 0, 2800, 3047, + 0, 2804, 3043, + 0, 2809, 3038, + 0, 2816, 3032, + 0, 2825, 3022, + 0, 2837, 3010, + 0, 2852, 2992, + 0, 2872, 2967, + 0, 2897, 2932, + 0, 2928, 2881, + 0, 2967, 2801, + 0, 3014, 2666, + 0, 3071, 2385, + 0, 3137, 0, + 0, 3212, 0, + 0, 3297, 0, + 0, 3390, 0, + 0, 3490, 0, + 0, 3597, 0, + 0, 3710, 0, + 0, 2788, 3058, + 0, 2789, 3058, + 0, 2789, 3058, + 0, 2789, 3057, + 0, 2789, 3057, + 0, 2790, 3057, + 0, 2790, 3056, + 0, 2791, 3056, + 0, 2792, 3055, + 0, 2793, 3054, + 0, 2795, 3052, + 0, 2797, 3050, + 0, 2800, 3047, + 0, 2804, 3044, + 0, 2809, 3039, + 0, 2816, 3032, + 0, 2825, 3023, + 0, 2837, 3010, + 0, 2852, 2992, + 0, 2872, 2968, + 0, 2897, 2933, + 0, 2928, 2881, + 0, 2967, 2801, + 0, 3014, 2667, + 0, 3071, 2386, + 0, 3137, 0, + 0, 3212, 0, + 0, 3297, 0, + 0, 3390, 0, + 0, 3490, 0, + 0, 3597, 0, + 0, 3710, 0, + 0, 2789, 3058, + 0, 2789, 3058, + 0, 2789, 3058, + 0, 2789, 3058, + 0, 2789, 3057, + 0, 2790, 3057, + 0, 2790, 3057, + 0, 2791, 3056, + 0, 2792, 3055, + 0, 2793, 3054, + 0, 2795, 3052, + 0, 2797, 3050, + 0, 2800, 3048, + 0, 2804, 3044, + 0, 2809, 3039, + 0, 2816, 3032, + 0, 2825, 3023, + 0, 2837, 3010, + 0, 2852, 2993, + 0, 2872, 2968, + 0, 2897, 2933, + 0, 2928, 2881, + 0, 2967, 2802, + 0, 3014, 2667, + 0, 3071, 2387, + 0, 3137, 0, + 0, 3212, 0, + 0, 3297, 0, + 0, 3390, 0, + 0, 3490, 0, + 0, 3597, 0, + 0, 3710, 0, + 0, 2789, 3059, + 0, 2789, 3058, + 0, 2789, 3058, + 0, 2789, 3058, + 0, 2789, 3058, + 0, 2790, 3058, + 0, 2790, 3057, + 0, 2791, 3056, + 0, 2792, 3056, + 0, 2793, 3054, + 0, 2795, 3053, + 0, 2797, 3051, + 0, 2800, 3048, + 0, 2804, 3044, + 0, 2809, 3039, + 0, 2816, 3033, + 0, 2825, 3023, + 0, 2837, 3011, + 0, 2852, 2993, + 0, 2872, 2969, + 0, 2897, 2934, + 0, 2928, 2882, + 0, 2967, 2802, + 0, 3014, 2668, + 0, 3071, 2389, + 0, 3137, 0, + 0, 3212, 0, + 0, 3297, 0, + 0, 3390, 0, + 0, 3490, 0, + 0, 3597, 0, + 0, 3710, 0, + 0, 2789, 3059, + 0, 2789, 3059, + 0, 2789, 3059, + 0, 2789, 3059, + 0, 2790, 3058, + 0, 2790, 3058, + 0, 2791, 3058, + 0, 2791, 3057, + 0, 2792, 3056, + 0, 2793, 3055, + 0, 2795, 3053, + 0, 2797, 3051, + 0, 2800, 3049, + 0, 2804, 3045, + 0, 2809, 3040, + 0, 2816, 3033, + 0, 2825, 3024, + 0, 2837, 3011, + 0, 2852, 2994, + 0, 2872, 2969, + 0, 2897, 2934, + 0, 2928, 2883, + 0, 2967, 2803, + 0, 3014, 2670, + 0, 3071, 2391, + 0, 3137, 0, + 0, 3212, 0, + 0, 3297, 0, + 0, 3390, 0, + 0, 3490, 0, + 0, 3597, 0, + 0, 3710, 0, + 0, 2789, 3060, + 0, 2789, 3060, + 0, 2789, 3060, + 0, 2789, 3059, + 0, 2790, 3059, + 0, 2790, 3059, + 0, 2791, 3058, + 0, 2791, 3058, + 0, 2792, 3057, + 0, 2794, 3056, + 0, 2795, 3054, + 0, 2797, 3052, + 0, 2800, 3049, + 0, 2804, 3046, + 0, 2810, 3041, + 0, 2816, 3034, + 0, 2825, 3025, + 0, 2837, 3012, + 0, 2852, 2995, + 0, 2872, 2970, + 0, 2897, 2935, + 0, 2928, 2884, + 0, 2967, 2805, + 0, 3015, 2671, + 0, 3071, 2394, + 0, 3137, 0, + 0, 3212, 0, + 0, 3297, 0, + 0, 3390, 0, + 0, 3490, 0, + 0, 3597, 0, + 0, 3710, 0, + 0, 2789, 3061, + 0, 2789, 3061, + 0, 2789, 3061, + 0, 2790, 3060, + 0, 2790, 3060, + 0, 2790, 3060, + 0, 2791, 3059, + 0, 2792, 3059, + 0, 2793, 3058, + 0, 2794, 3057, + 0, 2795, 3055, + 0, 2798, 3053, + 0, 2801, 3050, + 0, 2805, 3047, + 0, 2810, 3042, + 0, 2817, 3035, + 0, 2826, 3026, + 0, 2837, 3013, + 0, 2853, 2996, + 0, 2872, 2971, + 0, 2897, 2936, + 0, 2929, 2885, + 0, 2967, 2806, + 0, 3015, 2673, + 0, 3071, 2398, + 0, 3137, 0, + 0, 3212, 0, + 0, 3297, 0, + 0, 3390, 0, + 0, 3491, 0, + 0, 3597, 0, + 0, 3710, 0, + 0, 2790, 3062, + 0, 2790, 3062, + 0, 2790, 3062, + 0, 2790, 3062, + 0, 2790, 3061, + 0, 2791, 3061, + 0, 2791, 3060, + 0, 2792, 3060, + 0, 2793, 3059, + 0, 2794, 3058, + 0, 2796, 3056, + 0, 2798, 3054, + 0, 2801, 3052, + 0, 2805, 3048, + 0, 2810, 3043, + 0, 2817, 3036, + 0, 2826, 3027, + 0, 2838, 3014, + 0, 2853, 2997, + 0, 2872, 2973, + 0, 2897, 2938, + 0, 2929, 2887, + 0, 2968, 2809, + 0, 3015, 2676, + 0, 3071, 2404, + 0, 3137, 0, + 0, 3213, 0, + 0, 3297, 0, + 0, 3390, 0, + 0, 3491, 0, + 0, 3598, 0, + 0, 3710, 0, + 0, 2790, 3064, + 0, 2790, 3064, + 0, 2790, 3063, + 0, 2790, 3063, + 0, 2791, 3063, + 0, 2791, 3063, + 0, 2792, 3062, + 0, 2792, 3062, + 0, 2793, 3061, + 0, 2795, 3060, + 0, 2796, 3058, + 0, 2798, 3056, + 0, 2801, 3053, + 0, 2805, 3050, + 0, 2810, 3045, + 0, 2817, 3038, + 0, 2826, 3029, + 0, 2838, 3016, + 0, 2853, 2999, + 0, 2873, 2975, + 0, 2898, 2940, + 0, 2929, 2890, + 0, 2968, 2811, + 0, 3015, 2680, + 0, 3072, 2411, + 0, 3137, 0, + 0, 3213, 0, + 0, 3297, 0, + 0, 3390, 0, + 0, 3491, 0, + 0, 3598, 0, + 0, 3710, 0, + 0, 2791, 3066, + 0, 2791, 3066, + 0, 2791, 3066, + 0, 2791, 3065, + 0, 2791, 3065, + 0, 2792, 3065, + 0, 2792, 3064, + 0, 2793, 3064, + 0, 2794, 3063, + 0, 2795, 3062, + 0, 2797, 3060, + 0, 2799, 3058, + 0, 2802, 3056, + 0, 2806, 3052, + 0, 2811, 3047, + 0, 2818, 3040, + 0, 2827, 3031, + 0, 2838, 3019, + 0, 2854, 3002, + 0, 2873, 2978, + 0, 2898, 2943, + 0, 2930, 2893, + 0, 2968, 2815, + 0, 3016, 2685, + 0, 3072, 2420, + 0, 3138, 0, + 0, 3213, 0, + 0, 3297, 0, + 0, 3390, 0, + 0, 3491, 0, + 0, 3598, 0, + 0, 3710, 0, + 0, 2791, 3069, + 0, 2791, 3069, + 0, 2792, 3069, + 0, 2792, 3068, + 0, 2792, 3068, + 0, 2792, 3068, + 0, 2793, 3067, + 0, 2794, 3067, + 0, 2795, 3066, + 0, 2796, 3065, + 0, 2798, 3063, + 0, 2800, 3061, + 0, 2803, 3059, + 0, 2807, 3055, + 0, 2812, 3050, + 0, 2819, 3043, + 0, 2827, 3034, + 0, 2839, 3022, + 0, 2854, 3005, + 0, 2874, 2981, + 0, 2899, 2947, + 0, 2930, 2897, + 0, 2969, 2821, + 0, 3016, 2692, + 0, 3072, 2432, + 0, 3138, 0, + 0, 3213, 0, + 0, 3298, 0, + 0, 3391, 0, + 0, 3491, 0, + 0, 3598, 0, + 0, 3710, 0, + 0, 2792, 3073, + 0, 2792, 3073, + 0, 2793, 3073, + 0, 2793, 3072, + 0, 2793, 3072, + 0, 2793, 3072, + 0, 2794, 3071, + 0, 2795, 3071, + 0, 2796, 3070, + 0, 2797, 3069, + 0, 2799, 3067, + 0, 2801, 3065, + 0, 2804, 3063, + 0, 2808, 3059, + 0, 2813, 3054, + 0, 2819, 3048, + 0, 2828, 3039, + 0, 2840, 3026, + 0, 2855, 3010, + 0, 2875, 2986, + 0, 2900, 2952, + 0, 2931, 2903, + 0, 2970, 2827, + 0, 3017, 2701, + 0, 3073, 2448, + 0, 3138, 0, + 0, 3214, 0, + 0, 3298, 0, + 0, 3391, 0, + 0, 3491, 0, + 0, 3598, 0, + 0, 3710, 0, + 0, 2794, 3078, + 0, 2794, 3078, + 0, 2794, 3078, + 0, 2794, 3078, + 0, 2794, 3077, + 0, 2795, 3077, + 0, 2795, 3077, + 0, 2796, 3076, + 0, 2797, 3075, + 0, 2798, 3074, + 0, 2800, 3073, + 0, 2802, 3071, + 0, 2805, 3068, + 0, 2809, 3064, + 0, 2814, 3060, + 0, 2821, 3053, + 0, 2830, 3044, + 0, 2841, 3032, + 0, 2856, 3016, + 0, 2876, 2992, + 0, 2901, 2959, + 0, 2932, 2911, + 0, 2970, 2836, + 0, 3017, 2713, + 0, 3074, 2468, + 0, 3139, 1070, + 0, 3214, 0, + 0, 3298, 0, + 0, 3391, 0, + 0, 3491, 0, + 0, 3598, 0, + 0, 3710, 0, + 0, 2795, 3085, + 0, 2796, 3085, + 0, 2796, 3085, + 0, 2796, 3085, + 0, 2796, 3084, + 0, 2797, 3084, + 0, 2797, 3084, + 0, 2798, 3083, + 0, 2799, 3082, + 0, 2800, 3081, + 0, 2802, 3080, + 0, 2804, 3078, + 0, 2807, 3075, + 0, 2811, 3072, + 0, 2816, 3067, + 0, 2822, 3060, + 0, 2831, 3052, + 0, 2843, 3040, + 0, 2858, 3023, + 0, 2877, 3001, + 0, 2902, 2968, + 0, 2933, 2920, + 0, 2972, 2848, + 0, 3019, 2728, + 0, 3075, 2494, + 0, 3140, 1443, + 0, 3215, 0, + 0, 3299, 0, + 0, 3392, 0, + 0, 3492, 0, + 0, 3599, 0, + 0, 3711, 0, + 0, 2798, 3094, + 0, 2798, 3094, + 0, 2798, 3094, + 0, 2798, 3094, + 0, 2799, 3093, + 0, 2799, 3093, + 0, 2800, 3093, + 0, 2800, 3092, + 0, 2801, 3091, + 0, 2802, 3090, + 0, 2804, 3089, + 0, 2806, 3087, + 0, 2809, 3084, + 0, 2813, 3081, + 0, 2818, 3076, + 0, 2825, 3070, + 0, 2834, 3062, + 0, 2845, 3050, + 0, 2860, 3034, + 0, 2879, 3011, + 0, 2904, 2980, + 0, 2935, 2933, + 0, 2973, 2863, + 0, 3020, 2748, + 0, 3076, 2527, + 0, 3141, 1697, + 0, 3216, 0, + 0, 3300, 0, + 0, 3392, 0, + 0, 3492, 0, + 0, 3599, 0, + 0, 3711, 0, + 0, 2801, 3106, + 0, 2801, 3106, + 0, 2801, 3106, + 0, 2802, 3106, + 0, 2802, 3105, + 0, 2802, 3105, + 0, 2803, 3105, + 0, 2803, 3104, + 0, 2804, 3103, + 0, 2806, 3102, + 0, 2807, 3101, + 0, 2809, 3099, + 0, 2812, 3096, + 0, 2816, 3093, + 0, 2821, 3089, + 0, 2828, 3083, + 0, 2837, 3074, + 0, 2848, 3063, + 0, 2863, 3047, + 0, 2882, 3026, + 0, 2907, 2995, + 0, 2937, 2950, + 0, 2976, 2883, + 0, 3022, 2773, + 0, 3078, 2567, + 0, 3143, 1902, + 0, 3217, 0, + 0, 3301, 0, + 0, 3393, 0, + 0, 3493, 0, + 0, 3599, 0, + 0, 3711, 0, + 0, 2805, 3121, + 0, 2805, 3121, + 0, 2806, 3121, + 0, 2806, 3121, + 0, 2806, 3121, + 0, 2806, 3120, + 0, 2807, 3120, + 0, 2808, 3119, + 0, 2809, 3119, + 0, 2810, 3118, + 0, 2811, 3116, + 0, 2814, 3115, + 0, 2816, 3112, + 0, 2820, 3109, + 0, 2825, 3105, + 0, 2832, 3099, + 0, 2840, 3091, + 0, 2852, 3080, + 0, 2867, 3065, + 0, 2886, 3044, + 0, 2910, 3014, + 0, 2940, 2972, + 0, 2978, 2908, + 0, 3025, 2805, + 0, 3080, 2615, + 0, 3145, 2083, + 0, 3219, 0, + 0, 3302, 0, + 0, 3394, 0, + 0, 3494, 0, + 0, 3600, 0, + 0, 3712, 0, + 0, 2811, 3141, + 0, 2811, 3141, + 0, 2811, 3141, + 0, 2811, 3141, + 0, 2812, 3141, + 0, 2812, 3140, + 0, 2813, 3140, + 0, 2813, 3139, + 0, 2814, 3139, + 0, 2815, 3138, + 0, 2817, 3136, + 0, 2819, 3135, + 0, 2822, 3132, + 0, 2826, 3129, + 0, 2831, 3125, + 0, 2837, 3120, + 0, 2846, 3112, + 0, 2857, 3101, + 0, 2872, 3087, + 0, 2890, 3067, + 0, 2914, 3039, + 0, 2945, 2999, + 0, 2982, 2939, + 0, 3028, 2843, + 0, 3083, 2673, + 0, 3147, 2248, + 0, 3221, 0, + 0, 3304, 0, + 0, 3396, 0, + 0, 3495, 0, + 0, 3601, 0, + 0, 3713, 0, + 1321, 2818, 3166, + 1314, 2818, 3166, + 1305, 2819, 3166, + 1292, 2819, 3166, + 1275, 2819, 3166, + 1251, 2819, 3165, + 1216, 2820, 3165, + 1165, 2821, 3165, + 1087, 2821, 3164, + 956, 2823, 3163, + 686, 2824, 3162, + 0, 2826, 3160, + 0, 2829, 3158, + 0, 2833, 3155, + 0, 2838, 3151, + 0, 2844, 3146, + 0, 2853, 3139, + 0, 2864, 3129, + 0, 2878, 3115, + 0, 2897, 3097, + 0, 2920, 3071, + 0, 2950, 3033, + 0, 2987, 2978, + 0, 3033, 2891, + 0, 3087, 2740, + 0, 3151, 2403, + 0, 3224, 0, + 0, 3307, 0, + 0, 3398, 0, + 0, 3497, 0, + 0, 3603, 0, + 0, 3714, 0, + 2324, 2828, 3198, + 2323, 2828, 3198, + 2322, 2828, 3198, + 2321, 2828, 3198, + 2319, 2829, 3197, + 2317, 2829, 3197, + 2314, 2830, 3197, + 2309, 2830, 3196, + 2304, 2831, 3196, + 2296, 2832, 3195, + 2285, 2834, 3194, + 2270, 2836, 3192, + 2249, 2839, 3190, + 2220, 2842, 3188, + 2178, 2847, 3184, + 2115, 2853, 3179, + 2013, 2862, 3172, + 1828, 2872, 3163, + 1321, 2887, 3151, + 0, 2905, 3134, + 0, 2928, 3109, + 0, 2957, 3075, + 0, 2994, 3025, + 0, 3039, 2947, + 0, 3092, 2817, + 0, 3156, 2552, + 0, 3228, 0, + 0, 3310, 0, + 0, 3401, 0, + 0, 3499, 0, + 0, 3604, 0, + 0, 3715, 0, + 2680, 2841, 3237, + 2680, 2841, 3237, + 2680, 2841, 3237, + 2679, 2841, 3237, + 2678, 2841, 3237, + 2677, 2842, 3236, + 2676, 2842, 3236, + 2674, 2843, 3236, + 2671, 2844, 3235, + 2668, 2845, 3234, + 2663, 2846, 3233, + 2657, 2848, 3232, + 2648, 2851, 3230, + 2636, 2854, 3228, + 2620, 2859, 3224, + 2597, 2865, 3220, + 2564, 2873, 3214, + 2516, 2884, 3205, + 2444, 2898, 3194, + 2324, 2915, 3178, + 2088, 2938, 3157, + 1008, 2967, 3126, + 0, 3003, 3081, + 0, 3047, 3013, + 0, 3100, 2903, + 0, 3162, 2696, + 0, 3233, 2020, + 0, 3315, 0, + 0, 3404, 0, + 0, 3502, 0, + 0, 3607, 0, + 0, 3717, 0, + 2929, 2857, 3285, + 2929, 2857, 3285, + 2928, 2857, 3285, + 2928, 2858, 3284, + 2927, 2858, 3284, + 2927, 2858, 3284, + 2926, 2859, 3284, + 2925, 2859, 3283, + 2923, 2860, 3283, + 2921, 2861, 3282, + 2919, 2863, 3281, + 2915, 2864, 3280, + 2910, 2867, 3278, + 2903, 2870, 3276, + 2894, 2875, 3273, + 2882, 2881, 3269, + 2865, 2889, 3264, + 2841, 2899, 3256, + 2807, 2912, 3246, + 2757, 2929, 3232, + 2680, 2952, 3213, + 2551, 2980, 3186, + 2289, 3014, 3147, + 0, 3057, 3089, + 0, 3109, 2997, + 0, 3170, 2837, + 0, 3240, 2456, + 0, 3320, 0, + 0, 3409, 0, + 0, 3506, 0, + 0, 3610, 0, + 0, 3719, 0, + 3132, 2878, 3341, + 3132, 2878, 3341, + 3131, 2878, 3341, + 3131, 2879, 3341, + 3131, 2879, 3341, + 3130, 2879, 3341, + 3130, 2880, 3341, + 3129, 2880, 3340, + 3128, 2881, 3340, + 3127, 2882, 3339, + 3125, 2883, 3338, + 3123, 2885, 3337, + 3120, 2888, 3336, + 3116, 2891, 3334, + 3110, 2895, 3331, + 3102, 2901, 3328, + 3092, 2908, 3323, + 3077, 2918, 3316, + 3057, 2931, 3307, + 3029, 2947, 3295, + 2989, 2969, 3279, + 2928, 2996, 3255, + 2832, 3029, 3222, + 2659, 3071, 3173, + 2222, 3121, 3099, + 0, 3181, 2975, + 0, 3250, 2729, + 0, 3328, 1243, + 0, 3415, 0, + 0, 3511, 0, + 0, 3614, 0, + 0, 3723, 0, + 3310, 2905, 3408, + 3310, 2905, 3408, + 3310, 2905, 3408, + 3310, 2905, 3407, + 3310, 2906, 3407, + 3309, 2906, 3407, + 3309, 2906, 3407, + 3309, 2907, 3407, + 3308, 2907, 3406, + 3307, 2908, 3406, + 3306, 2910, 3405, + 3304, 2911, 3404, + 3302, 2914, 3403, + 3300, 2917, 3401, + 3296, 2921, 3399, + 3291, 2926, 3396, + 3284, 2933, 3392, + 3274, 2943, 3386, + 3262, 2955, 3378, + 3244, 2970, 3368, + 3219, 2991, 3354, + 3183, 3016, 3334, + 3131, 3049, 3306, + 3050, 3089, 3266, + 2912, 3137, 3207, + 2620, 3195, 3112, + 0, 3262, 2944, + 0, 3338, 2528, + 0, 3424, 0, + 0, 3518, 0, + 0, 3619, 0, + 0, 3727, 0, + 3474, 2938, 3483, + 3474, 2938, 3483, + 3474, 2939, 3483, + 3474, 2939, 3483, + 3474, 2939, 3483, + 3474, 2939, 3483, + 3474, 2940, 3483, + 3473, 2940, 3483, + 3473, 2941, 3482, + 3472, 2942, 3482, + 3471, 2943, 3481, + 3470, 2944, 3480, + 3469, 2947, 3479, + 3467, 2949, 3478, + 3464, 2953, 3476, + 3461, 2958, 3473, + 3456, 2965, 3470, + 3450, 2973, 3465, + 3441, 2985, 3459, + 3429, 3000, 3450, + 3413, 3019, 3438, + 3390, 3043, 3422, + 3357, 3073, 3399, + 3310, 3111, 3367, + 3237, 3157, 3320, + 3117, 3213, 3248, + 2883, 3277, 3129, + 1820, 3351, 2898, + 0, 3435, 1907, + 0, 3527, 0, + 0, 3626, 0, + 0, 3732, 0, + 3629, 2980, 3568, + 3629, 2980, 3568, + 3629, 2980, 3568, + 3629, 2980, 3568, + 3629, 2980, 3568, + 3629, 2980, 3568, + 3628, 2981, 3568, + 3628, 2981, 3568, + 3628, 2982, 3567, + 3627, 2983, 3567, + 3627, 2984, 3566, + 3626, 2985, 3566, + 3625, 2987, 3565, + 3624, 2990, 3564, + 3622, 2993, 3562, + 3619, 2998, 3560, + 3616, 3004, 3557, + 3612, 3012, 3553, + 3605, 3022, 3548, + 3597, 3036, 3541, + 3586, 3053, 3531, + 3570, 3076, 3518, + 3549, 3104, 3500, + 3518, 3140, 3474, + 3474, 3183, 3437, + 3406, 3235, 3382, + 3297, 3297, 3297, + 3092, 3368, 3151, + 2441, 3449, 2828, + 0, 3538, 0, + 0, 3636, 0, + 0, 3740, 0, + 3777, 3029, 3662, + 3777, 3029, 3662, + 3777, 3030, 3662, + 3777, 3030, 3661, + 3777, 3030, 3661, + 3777, 3030, 3661, + 3777, 3030, 3661, + 3777, 3031, 3661, + 3776, 3031, 3661, + 3776, 3032, 3660, + 3776, 3033, 3660, + 3775, 3034, 3660, + 3774, 3036, 3659, + 3773, 3038, 3658, + 3772, 3042, 3657, + 3770, 3046, 3655, + 3768, 3051, 3652, + 3765, 3058, 3649, + 3760, 3068, 3645, + 3754, 3080, 3639, + 3747, 3096, 3632, + 3736, 3117, 3621, + 3721, 3143, 3606, + 3700, 3175, 3586, + 3671, 3216, 3558, + 3628, 3265, 3516, + 3564, 3323, 3455, + 3462, 3390, 3356, + 3275, 3467, 3178, + 2755, 3554, 2715, + 0, 3648, 0, + 0, 3750, 0, + 3921, 3088, 3762, + 3921, 3088, 3762, + 3921, 3089, 3762, + 3921, 3089, 3762, + 3921, 3089, 3762, + 3921, 3089, 3762, + 3921, 3089, 3762, + 3921, 3090, 3762, + 3920, 3090, 3762, + 3920, 3091, 3761, + 3920, 3092, 3761, + 3919, 3093, 3761, + 3919, 3094, 3760, + 3918, 3096, 3759, + 3917, 3099, 3758, + 3916, 3103, 3757, + 3914, 3108, 3755, + 3912, 3114, 3753, + 3909, 3122, 3749, + 3905, 3133, 3745, + 3899, 3148, 3738, + 3891, 3166, 3730, + 3881, 3189, 3719, + 3866, 3219, 3703, + 3846, 3256, 3681, + 3817, 3301, 3650, + 3776, 3355, 3605, + 3715, 3418, 3536, + 3617, 3491, 3424, + 3441, 3573, 3213, + 2987, 3664, 2497, + 0, 3762, 0, + 4062, 3157, 3869, + 4062, 3157, 3869, + 4062, 3157, 3869, + 4062, 3157, 3869, + 4062, 3157, 3869, + 4061, 3158, 3869, + 4061, 3158, 3869, + 4061, 3158, 3869, + 4061, 3159, 3869, + 4061, 3159, 3869, + 4061, 3160, 3869, + 4060, 3161, 3868, + 4060, 3162, 3868, + 4060, 3164, 3867, + 4059, 3166, 3866, + 4058, 3169, 3865, + 4057, 3174, 3864, + 4055, 3179, 3862, + 4053, 3186, 3859, + 4050, 3196, 3856, + 4045, 3208, 3851, + 4040, 3224, 3844, + 4032, 3245, 3835, + 4022, 3271, 3823, + 4008, 3304, 3806, + 3988, 3345, 3783, + 3960, 3394, 3750, + 3920, 3452, 3701, + 3860, 3520, 3626, + 3766, 3598, 3502, + 3598, 3684, 3255, + 3182, 3779, 1720, + 4095, 3235, 3982, + 4095, 3235, 3982, + 4095, 3235, 3982, + 4095, 3235, 3982, + 4095, 3235, 3982, + 4095, 3236, 3982, + 4095, 3236, 3982, + 4095, 3236, 3982, + 4095, 3236, 3982, + 4095, 3237, 3981, + 4095, 3238, 3981, + 4095, 3238, 3981, + 4095, 3239, 3981, + 4095, 3241, 3980, + 4095, 3243, 3979, + 4095, 3246, 3979, + 4095, 3249, 3978, + 4095, 3254, 3976, + 4095, 3260, 3974, + 4095, 3268, 3971, + 4095, 3279, 3967, + 4095, 3293, 3962, + 4095, 3310, 3956, + 4095, 3333, 3946, + 4095, 3362, 3934, + 4095, 3398, 3916, + 4095, 3442, 3891, + 4095, 3495, 3856, + 4061, 3557, 3804, + 4002, 3629, 3724, + 3910, 3710, 3589, + 3747, 3800, 3306, + 4095, 3322, 4095, + 4095, 3322, 4095, + 4095, 3322, 4095, + 4095, 3322, 4095, + 4095, 3322, 4095, + 4095, 3323, 4095, + 4095, 3323, 4095, + 4095, 3323, 4095, + 4095, 3323, 4095, + 4095, 3324, 4095, + 4095, 3324, 4095, + 4095, 3325, 4095, + 4095, 3326, 4095, + 4095, 3327, 4095, + 4095, 3329, 4095, + 4095, 3331, 4095, + 4095, 3334, 4095, + 4095, 3338, 4094, + 4095, 3343, 4093, + 4095, 3350, 4090, + 4095, 3358, 4088, + 4095, 3370, 4084, + 4095, 3385, 4079, + 4095, 3405, 4071, + 4095, 3429, 4062, + 4095, 3461, 4049, + 4095, 3499, 4030, + 4095, 3546, 4005, + 4095, 3602, 3968, + 4095, 3668, 3914, + 4095, 3743, 3829, + 4051, 3827, 3684, + 0, 2920, 3190, + 0, 2920, 3189, + 0, 2921, 3189, + 0, 2921, 3189, + 0, 2921, 3189, + 0, 2921, 3189, + 0, 2922, 3188, + 0, 2922, 3188, + 0, 2923, 3187, + 0, 2924, 3186, + 0, 2925, 3185, + 0, 2927, 3184, + 0, 2929, 3182, + 0, 2932, 3179, + 0, 2936, 3175, + 0, 2941, 3170, + 0, 2948, 3163, + 0, 2957, 3154, + 0, 2969, 3141, + 0, 2984, 3124, + 0, 3004, 3099, + 0, 3029, 3064, + 0, 3060, 3012, + 0, 3099, 2932, + 0, 3146, 2798, + 0, 3203, 2515, + 0, 3269, 0, + 0, 3344, 0, + 0, 3429, 0, + 0, 3522, 0, + 0, 3622, 0, + 0, 3729, 0, + 0, 2920, 3190, + 0, 2920, 3190, + 0, 2921, 3189, + 0, 2921, 3189, + 0, 2921, 3189, + 0, 2921, 3189, + 0, 2922, 3189, + 0, 2922, 3188, + 0, 2923, 3187, + 0, 2924, 3187, + 0, 2925, 3185, + 0, 2927, 3184, + 0, 2929, 3182, + 0, 2932, 3179, + 0, 2936, 3175, + 0, 2941, 3170, + 0, 2948, 3163, + 0, 2957, 3154, + 0, 2969, 3142, + 0, 2984, 3124, + 0, 3004, 3099, + 0, 3029, 3064, + 0, 3060, 3013, + 0, 3099, 2933, + 0, 3146, 2798, + 0, 3203, 2516, + 0, 3269, 0, + 0, 3344, 0, + 0, 3429, 0, + 0, 3522, 0, + 0, 3622, 0, + 0, 3729, 0, + 0, 2920, 3190, + 0, 2921, 3190, + 0, 2921, 3190, + 0, 2921, 3189, + 0, 2921, 3189, + 0, 2921, 3189, + 0, 2922, 3189, + 0, 2922, 3188, + 0, 2923, 3188, + 0, 2924, 3187, + 0, 2925, 3186, + 0, 2927, 3184, + 0, 2929, 3182, + 0, 2932, 3179, + 0, 2936, 3176, + 0, 2941, 3170, + 0, 2948, 3164, + 0, 2957, 3154, + 0, 2969, 3142, + 0, 2984, 3124, + 0, 3004, 3100, + 0, 3029, 3064, + 0, 3060, 3013, + 0, 3099, 2933, + 0, 3146, 2798, + 0, 3203, 2517, + 0, 3269, 0, + 0, 3344, 0, + 0, 3429, 0, + 0, 3522, 0, + 0, 3622, 0, + 0, 3729, 0, + 0, 2920, 3190, + 0, 2921, 3190, + 0, 2921, 3190, + 0, 2921, 3190, + 0, 2921, 3190, + 0, 2921, 3189, + 0, 2922, 3189, + 0, 2922, 3188, + 0, 2923, 3188, + 0, 2924, 3187, + 0, 2925, 3186, + 0, 2927, 3184, + 0, 2929, 3182, + 0, 2932, 3179, + 0, 2936, 3176, + 0, 2941, 3171, + 0, 2948, 3164, + 0, 2957, 3155, + 0, 2969, 3142, + 0, 2984, 3124, + 0, 3004, 3100, + 0, 3029, 3065, + 0, 3060, 3013, + 0, 3099, 2933, + 0, 3146, 2799, + 0, 3203, 2518, + 0, 3269, 0, + 0, 3344, 0, + 0, 3429, 0, + 0, 3522, 0, + 0, 3622, 0, + 0, 3729, 0, + 0, 2921, 3190, + 0, 2921, 3190, + 0, 2921, 3190, + 0, 2921, 3190, + 0, 2921, 3190, + 0, 2921, 3190, + 0, 2922, 3189, + 0, 2922, 3189, + 0, 2923, 3188, + 0, 2924, 3187, + 0, 2925, 3186, + 0, 2927, 3185, + 0, 2929, 3183, + 0, 2932, 3180, + 0, 2936, 3176, + 0, 2941, 3171, + 0, 2948, 3164, + 0, 2957, 3155, + 0, 2969, 3142, + 0, 2984, 3125, + 0, 3004, 3100, + 0, 3029, 3065, + 0, 3060, 3014, + 0, 3099, 2934, + 0, 3146, 2799, + 0, 3203, 2519, + 0, 3269, 0, + 0, 3344, 0, + 0, 3429, 0, + 0, 3522, 0, + 0, 3622, 0, + 0, 3729, 0, + 0, 2921, 3191, + 0, 2921, 3191, + 0, 2921, 3191, + 0, 2921, 3190, + 0, 2921, 3190, + 0, 2922, 3190, + 0, 2922, 3190, + 0, 2922, 3189, + 0, 2923, 3188, + 0, 2924, 3188, + 0, 2925, 3187, + 0, 2927, 3185, + 0, 2929, 3183, + 0, 2932, 3180, + 0, 2936, 3176, + 0, 2941, 3171, + 0, 2948, 3165, + 0, 2957, 3155, + 0, 2969, 3143, + 0, 2984, 3125, + 0, 3004, 3101, + 0, 3029, 3066, + 0, 3060, 3014, + 0, 3099, 2935, + 0, 3146, 2800, + 0, 3203, 2521, + 0, 3269, 0, + 0, 3344, 0, + 0, 3429, 0, + 0, 3522, 0, + 0, 3622, 0, + 0, 3729, 0, + 0, 2921, 3191, + 0, 2921, 3191, + 0, 2921, 3191, + 0, 2921, 3191, + 0, 2921, 3191, + 0, 2922, 3190, + 0, 2922, 3190, + 0, 2923, 3190, + 0, 2923, 3189, + 0, 2924, 3188, + 0, 2925, 3187, + 0, 2927, 3186, + 0, 2929, 3183, + 0, 2932, 3181, + 0, 2936, 3177, + 0, 2941, 3172, + 0, 2948, 3165, + 0, 2957, 3156, + 0, 2969, 3143, + 0, 2984, 3126, + 0, 3004, 3101, + 0, 3029, 3066, + 0, 3060, 3015, + 0, 3099, 2936, + 0, 3147, 2802, + 0, 3203, 2523, + 0, 3269, 0, + 0, 3344, 0, + 0, 3429, 0, + 0, 3522, 0, + 0, 3623, 0, + 0, 3729, 0, + 0, 2921, 3192, + 0, 2921, 3192, + 0, 2921, 3192, + 0, 2921, 3192, + 0, 2922, 3191, + 0, 2922, 3191, + 0, 2922, 3191, + 0, 2923, 3190, + 0, 2923, 3190, + 0, 2924, 3189, + 0, 2926, 3188, + 0, 2927, 3186, + 0, 2930, 3184, + 0, 2933, 3181, + 0, 2936, 3178, + 0, 2942, 3173, + 0, 2948, 3166, + 0, 2957, 3157, + 0, 2969, 3144, + 0, 2984, 3127, + 0, 3004, 3102, + 0, 3029, 3067, + 0, 3061, 3016, + 0, 3099, 2937, + 0, 3147, 2803, + 0, 3203, 2526, + 0, 3269, 0, + 0, 3344, 0, + 0, 3429, 0, + 0, 3522, 0, + 0, 3623, 0, + 0, 3730, 0, + 0, 2921, 3193, + 0, 2921, 3193, + 0, 2921, 3193, + 0, 2922, 3193, + 0, 2922, 3192, + 0, 2922, 3192, + 0, 2922, 3192, + 0, 2923, 3191, + 0, 2924, 3191, + 0, 2925, 3190, + 0, 2926, 3189, + 0, 2928, 3187, + 0, 2930, 3185, + 0, 2933, 3182, + 0, 2937, 3179, + 0, 2942, 3174, + 0, 2949, 3167, + 0, 2958, 3158, + 0, 2969, 3145, + 0, 2985, 3128, + 0, 3004, 3103, + 0, 3029, 3069, + 0, 3061, 3017, + 0, 3100, 2938, + 0, 3147, 2806, + 0, 3203, 2530, + 0, 3269, 0, + 0, 3345, 0, + 0, 3429, 0, + 0, 3522, 0, + 0, 3623, 0, + 0, 3730, 0, + 0, 2922, 3194, + 0, 2922, 3194, + 0, 2922, 3194, + 0, 2922, 3194, + 0, 2922, 3194, + 0, 2922, 3193, + 0, 2923, 3193, + 0, 2923, 3193, + 0, 2924, 3192, + 0, 2925, 3191, + 0, 2926, 3190, + 0, 2928, 3188, + 0, 2930, 3186, + 0, 2933, 3184, + 0, 2937, 3180, + 0, 2942, 3175, + 0, 2949, 3168, + 0, 2958, 3159, + 0, 2970, 3147, + 0, 2985, 3129, + 0, 3005, 3105, + 0, 3030, 3070, + 0, 3061, 3019, + 0, 3100, 2941, + 0, 3147, 2808, + 0, 3203, 2536, + 0, 3269, 0, + 0, 3345, 0, + 0, 3429, 0, + 0, 3522, 0, + 0, 3623, 0, + 0, 3730, 0, + 0, 2922, 3196, + 0, 2922, 3196, + 0, 2922, 3196, + 0, 2922, 3196, + 0, 2923, 3195, + 0, 2923, 3195, + 0, 2923, 3195, + 0, 2924, 3194, + 0, 2924, 3194, + 0, 2925, 3193, + 0, 2927, 3192, + 0, 2928, 3190, + 0, 2931, 3188, + 0, 2933, 3185, + 0, 2937, 3182, + 0, 2943, 3177, + 0, 2949, 3170, + 0, 2958, 3161, + 0, 2970, 3148, + 0, 2985, 3131, + 0, 3005, 3107, + 0, 3030, 3072, + 0, 3061, 3022, + 0, 3100, 2944, + 0, 3147, 2812, + 0, 3204, 2543, + 0, 3269, 0, + 0, 3345, 0, + 0, 3429, 0, + 0, 3522, 0, + 0, 3623, 0, + 0, 3730, 0, + 0, 2923, 3198, + 0, 2923, 3198, + 0, 2923, 3198, + 0, 2923, 3198, + 0, 2923, 3198, + 0, 2923, 3197, + 0, 2924, 3197, + 0, 2924, 3197, + 0, 2925, 3196, + 0, 2926, 3195, + 0, 2927, 3194, + 0, 2929, 3192, + 0, 2931, 3190, + 0, 2934, 3188, + 0, 2938, 3184, + 0, 2943, 3179, + 0, 2950, 3172, + 0, 2959, 3163, + 0, 2971, 3151, + 0, 2986, 3134, + 0, 3005, 3110, + 0, 3030, 3075, + 0, 3062, 3025, + 0, 3100, 2947, + 0, 3148, 2818, + 0, 3204, 2552, + 0, 3270, 0, + 0, 3345, 0, + 0, 3430, 0, + 0, 3522, 0, + 0, 3623, 0, + 0, 3730, 0, + 0, 2923, 3201, + 0, 2923, 3201, + 0, 2924, 3201, + 0, 2924, 3201, + 0, 2924, 3201, + 0, 2924, 3200, + 0, 2925, 3200, + 0, 2925, 3200, + 0, 2926, 3199, + 0, 2927, 3198, + 0, 2928, 3197, + 0, 2930, 3195, + 0, 2932, 3193, + 0, 2935, 3191, + 0, 2939, 3187, + 0, 2944, 3182, + 0, 2951, 3176, + 0, 2960, 3167, + 0, 2971, 3154, + 0, 2986, 3137, + 0, 3006, 3113, + 0, 3031, 3079, + 0, 3062, 3029, + 0, 3101, 2953, + 0, 3148, 2824, + 0, 3204, 2564, + 0, 3270, 0, + 0, 3345, 0, + 0, 3430, 0, + 0, 3523, 0, + 0, 3623, 0, + 0, 3730, 0, + 0, 2924, 3205, + 0, 2924, 3205, + 0, 2925, 3205, + 0, 2925, 3205, + 0, 2925, 3205, + 0, 2925, 3204, + 0, 2926, 3204, + 0, 2926, 3203, + 0, 2927, 3203, + 0, 2928, 3202, + 0, 2929, 3201, + 0, 2931, 3199, + 0, 2933, 3197, + 0, 2936, 3195, + 0, 2940, 3191, + 0, 2945, 3186, + 0, 2952, 3180, + 0, 2961, 3171, + 0, 2972, 3159, + 0, 2987, 3142, + 0, 3007, 3118, + 0, 3032, 3084, + 0, 3063, 3035, + 0, 3102, 2959, + 0, 3149, 2833, + 0, 3205, 2580, + 0, 3271, 0, + 0, 3346, 0, + 0, 3430, 0, + 0, 3523, 0, + 0, 3623, 0, + 0, 3730, 0, + 0, 2926, 3210, + 0, 2926, 3210, + 0, 2926, 3210, + 0, 2926, 3210, + 0, 2926, 3210, + 0, 2927, 3210, + 0, 2927, 3209, + 0, 2927, 3209, + 0, 2928, 3208, + 0, 2929, 3207, + 0, 2930, 3206, + 0, 2932, 3205, + 0, 2934, 3203, + 0, 2937, 3200, + 0, 2941, 3197, + 0, 2946, 3192, + 0, 2953, 3185, + 0, 2962, 3176, + 0, 2973, 3164, + 0, 2989, 3148, + 0, 3008, 3124, + 0, 3033, 3091, + 0, 3064, 3043, + 0, 3103, 2968, + 0, 3150, 2845, + 0, 3206, 2601, + 0, 3271, 1202, + 0, 3346, 0, + 0, 3431, 0, + 0, 3523, 0, + 0, 3624, 0, + 0, 3730, 0, + 0, 2927, 3217, + 0, 2928, 3217, + 0, 2928, 3217, + 0, 2928, 3217, + 0, 2928, 3217, + 0, 2928, 3216, + 0, 2929, 3216, + 0, 2929, 3216, + 0, 2930, 3215, + 0, 2931, 3214, + 0, 2932, 3213, + 0, 2934, 3212, + 0, 2936, 3210, + 0, 2939, 3207, + 0, 2943, 3204, + 0, 2948, 3199, + 0, 2955, 3193, + 0, 2963, 3184, + 0, 2975, 3172, + 0, 2990, 3156, + 0, 3010, 3133, + 0, 3034, 3100, + 0, 3065, 3053, + 0, 3104, 2980, + 0, 3151, 2860, + 0, 3207, 2626, + 0, 3272, 1575, + 0, 3347, 0, + 0, 3431, 0, + 0, 3524, 0, + 0, 3624, 0, + 0, 3731, 0, + 0, 2930, 3226, + 0, 2930, 3226, + 0, 2930, 3226, + 0, 2930, 3226, + 0, 2930, 3226, + 0, 2931, 3226, + 0, 2931, 3225, + 0, 2932, 3225, + 0, 2932, 3224, + 0, 2933, 3223, + 0, 2934, 3222, + 0, 2936, 3221, + 0, 2938, 3219, + 0, 2941, 3216, + 0, 2945, 3213, + 0, 2950, 3208, + 0, 2957, 3202, + 0, 2966, 3194, + 0, 2977, 3182, + 0, 2992, 3166, + 0, 3012, 3144, + 0, 3036, 3112, + 0, 3067, 3066, + 0, 3105, 2995, + 0, 3152, 2880, + 0, 3208, 2659, + 0, 3273, 1829, + 0, 3348, 0, + 0, 3432, 0, + 0, 3524, 0, + 0, 3624, 0, + 0, 3731, 0, + 0, 2933, 3238, + 0, 2933, 3238, + 0, 2933, 3238, + 0, 2933, 3238, + 0, 2934, 3238, + 0, 2934, 3237, + 0, 2934, 3237, + 0, 2935, 3237, + 0, 2936, 3236, + 0, 2936, 3235, + 0, 2938, 3234, + 0, 2939, 3233, + 0, 2941, 3231, + 0, 2944, 3229, + 0, 2948, 3225, + 0, 2953, 3221, + 0, 2960, 3215, + 0, 2969, 3206, + 0, 2980, 3195, + 0, 2995, 3179, + 0, 3014, 3158, + 0, 3039, 3127, + 0, 3069, 3082, + 0, 3108, 3015, + 0, 3154, 2905, + 0, 3210, 2699, + 0, 3275, 2034, + 0, 3349, 0, + 0, 3433, 0, + 0, 3525, 0, + 0, 3625, 0, + 0, 3732, 0, + 0, 2937, 3254, + 0, 2937, 3253, + 0, 2938, 3253, + 0, 2938, 3253, + 0, 2938, 3253, + 0, 2938, 3253, + 0, 2939, 3252, + 0, 2939, 3252, + 0, 2940, 3252, + 0, 2941, 3251, + 0, 2942, 3250, + 0, 2943, 3248, + 0, 2946, 3247, + 0, 2948, 3244, + 0, 2952, 3241, + 0, 2957, 3237, + 0, 2964, 3231, + 0, 2973, 3223, + 0, 2984, 3212, + 0, 2999, 3197, + 0, 3018, 3176, + 0, 3042, 3147, + 0, 3073, 3104, + 0, 3110, 3040, + 0, 3157, 2937, + 0, 3212, 2747, + 0, 3277, 2215, + 0, 3351, 0, + 0, 3434, 0, + 0, 3526, 0, + 0, 3626, 0, + 0, 3732, 0, + 0, 2943, 3273, + 0, 2943, 3273, + 0, 2943, 3273, + 0, 2943, 3273, + 0, 2944, 3273, + 0, 2944, 3273, + 0, 2944, 3272, + 0, 2945, 3272, + 0, 2945, 3271, + 0, 2946, 3271, + 0, 2947, 3270, + 0, 2949, 3268, + 0, 2951, 3267, + 0, 2954, 3264, + 0, 2958, 3261, + 0, 2963, 3257, + 0, 2969, 3252, + 0, 2978, 3244, + 0, 2989, 3234, + 0, 3004, 3219, + 0, 3022, 3199, + 0, 3046, 3171, + 0, 3077, 3131, + 0, 3114, 3071, + 0, 3160, 2976, + 0, 3215, 2805, + 0, 3279, 2380, + 0, 3353, 0, + 0, 3436, 0, + 0, 3528, 0, + 0, 3627, 0, + 0, 3733, 0, + 1458, 2950, 3298, + 1453, 2950, 3298, + 1446, 2951, 3298, + 1437, 2951, 3298, + 1424, 2951, 3298, + 1407, 2951, 3298, + 1383, 2952, 3298, + 1348, 2952, 3297, + 1297, 2953, 3297, + 1219, 2954, 3296, + 1088, 2955, 3295, + 818, 2956, 3294, + 0, 2958, 3292, + 0, 2961, 3290, + 0, 2965, 3287, + 0, 2970, 3283, + 0, 2976, 3278, + 0, 2985, 3271, + 0, 2996, 3261, + 0, 3010, 3248, + 0, 3029, 3229, + 0, 3052, 3203, + 0, 3082, 3165, + 0, 3119, 3110, + 0, 3165, 3023, + 0, 3219, 2873, + 0, 3283, 2535, + 0, 3356, 0, + 0, 3439, 0, + 0, 3530, 0, + 0, 3629, 0, + 0, 3735, 0, + 2457, 2960, 3330, + 2456, 2960, 3330, + 2456, 2960, 3330, + 2455, 2960, 3330, + 2453, 2961, 3330, + 2451, 2961, 3330, + 2449, 2961, 3329, + 2446, 2962, 3329, + 2442, 2962, 3328, + 2436, 2963, 3328, + 2428, 2964, 3327, + 2417, 2966, 3326, + 2402, 2968, 3324, + 2382, 2971, 3322, + 2352, 2974, 3320, + 2310, 2979, 3316, + 2247, 2985, 3311, + 2145, 2994, 3304, + 1960, 3004, 3295, + 1453, 3019, 3283, + 0, 3037, 3266, + 0, 3060, 3242, + 0, 3090, 3207, + 0, 3126, 3157, + 0, 3171, 3079, + 0, 3225, 2949, + 0, 3288, 2684, + 0, 3360, 0, + 0, 3442, 0, + 0, 3533, 0, + 0, 3631, 0, + 0, 3736, 0, + 2813, 2973, 3369, + 2813, 2973, 3369, + 2812, 2973, 3369, + 2812, 2973, 3369, + 2811, 2973, 3369, + 2810, 2974, 3369, + 2809, 2974, 3369, + 2808, 2974, 3368, + 2806, 2975, 3368, + 2803, 2976, 3367, + 2800, 2977, 3366, + 2795, 2978, 3365, + 2789, 2980, 3364, + 2780, 2983, 3362, + 2768, 2987, 3360, + 2752, 2991, 3356, + 2729, 2997, 3352, + 2696, 3005, 3346, + 2648, 3016, 3337, + 2576, 3030, 3326, + 2456, 3048, 3310, + 2220, 3070, 3289, + 1140, 3099, 3258, + 0, 3135, 3213, + 0, 3179, 3145, + 0, 3232, 3035, + 0, 3294, 2828, + 0, 3366, 2152, + 0, 3447, 0, + 0, 3536, 0, + 0, 3634, 0, + 0, 3739, 0, + 3061, 2989, 3417, + 3061, 2989, 3417, + 3061, 2989, 3417, + 3060, 2989, 3417, + 3060, 2990, 3417, + 3060, 2990, 3416, + 3059, 2990, 3416, + 3058, 2991, 3416, + 3057, 2991, 3415, + 3055, 2992, 3415, + 3053, 2993, 3414, + 3051, 2995, 3413, + 3047, 2997, 3412, + 3042, 2999, 3410, + 3036, 3002, 3408, + 3027, 3007, 3405, + 3014, 3013, 3401, + 2997, 3021, 3396, + 2973, 3031, 3388, + 2939, 3044, 3378, + 2889, 3062, 3364, + 2812, 3084, 3345, + 2683, 3112, 3318, + 2421, 3147, 3279, + 0, 3189, 3221, + 0, 3241, 3129, + 0, 3302, 2969, + 0, 3373, 2588, + 0, 3452, 0, + 0, 3541, 0, + 0, 3638, 0, + 0, 3742, 0, + 3264, 3010, 3474, + 3264, 3010, 3474, + 3264, 3010, 3473, + 3263, 3010, 3473, + 3263, 3011, 3473, + 3263, 3011, 3473, + 3263, 3011, 3473, + 3262, 3012, 3473, + 3261, 3012, 3472, + 3260, 3013, 3472, + 3259, 3014, 3471, + 3257, 3015, 3470, + 3255, 3017, 3469, + 3252, 3020, 3468, + 3248, 3023, 3466, + 3242, 3027, 3463, + 3234, 3033, 3460, + 3224, 3040, 3455, + 3210, 3050, 3448, + 3190, 3063, 3440, + 3161, 3080, 3427, + 3121, 3101, 3411, + 3060, 3128, 3387, + 2964, 3162, 3354, + 2791, 3203, 3305, + 2354, 3253, 3231, + 0, 3313, 3107, + 0, 3382, 2861, + 0, 3460, 1375, + 0, 3548, 0, + 0, 3643, 0, + 0, 3746, 0, + 3442, 3037, 3540, + 3442, 3037, 3540, + 3442, 3037, 3540, + 3442, 3037, 3540, + 3442, 3037, 3540, + 3442, 3038, 3539, + 3442, 3038, 3539, + 3441, 3038, 3539, + 3441, 3039, 3539, + 3440, 3040, 3538, + 3439, 3041, 3538, + 3438, 3042, 3537, + 3437, 3044, 3536, + 3434, 3046, 3535, + 3432, 3049, 3533, + 3428, 3053, 3531, + 3423, 3058, 3528, + 3416, 3065, 3524, + 3407, 3075, 3518, + 3394, 3087, 3511, + 3376, 3103, 3500, + 3351, 3123, 3486, + 3315, 3149, 3466, + 3263, 3181, 3438, + 3182, 3221, 3398, + 3044, 3269, 3339, + 2752, 3327, 3244, + 0, 3394, 3076, + 0, 3470, 2660, + 0, 3556, 0, + 0, 3650, 0, + 0, 3751, 0, + 3606, 3070, 3616, + 3606, 3070, 3616, + 3606, 3071, 3616, + 3606, 3071, 3615, + 3606, 3071, 3615, + 3606, 3071, 3615, + 3606, 3071, 3615, + 3606, 3072, 3615, + 3605, 3072, 3615, + 3605, 3073, 3614, + 3604, 3074, 3614, + 3603, 3075, 3613, + 3602, 3077, 3613, + 3601, 3079, 3611, + 3599, 3082, 3610, + 3596, 3085, 3608, + 3593, 3090, 3605, + 3588, 3097, 3602, + 3582, 3106, 3597, + 3573, 3117, 3591, + 3561, 3132, 3582, + 3545, 3151, 3570, + 3522, 3175, 3554, + 3489, 3205, 3531, + 3442, 3243, 3499, + 3369, 3289, 3452, + 3249, 3345, 3380, + 3015, 3409, 3261, + 1952, 3483, 3030, + 0, 3567, 2039, + 0, 3659, 0, + 0, 3758, 0, + 3761, 3112, 3700, + 3761, 3112, 3700, + 3761, 3112, 3700, + 3761, 3112, 3700, + 3761, 3112, 3700, + 3761, 3112, 3700, + 3761, 3112, 3700, + 3760, 3113, 3700, + 3760, 3113, 3700, + 3760, 3114, 3699, + 3759, 3115, 3699, + 3759, 3116, 3699, + 3758, 3117, 3698, + 3757, 3119, 3697, + 3756, 3122, 3696, + 3754, 3125, 3694, + 3751, 3130, 3692, + 3748, 3136, 3689, + 3744, 3144, 3685, + 3738, 3154, 3680, + 3729, 3168, 3673, + 3718, 3185, 3663, + 3702, 3208, 3650, + 3681, 3236, 3632, + 3650, 3272, 3606, + 3606, 3315, 3569, + 3538, 3368, 3514, + 3429, 3429, 3429, + 3224, 3501, 3283, + 2573, 3581, 2960, + 0, 3671, 0, + 0, 3768, 0, + 3909, 3161, 3794, + 3909, 3161, 3794, + 3909, 3162, 3794, + 3909, 3162, 3794, + 3909, 3162, 3794, + 3909, 3162, 3794, + 3909, 3162, 3793, + 3909, 3162, 3793, + 3909, 3163, 3793, + 3908, 3163, 3793, + 3908, 3164, 3793, + 3908, 3165, 3792, + 3907, 3166, 3792, + 3906, 3168, 3791, + 3905, 3171, 3790, + 3904, 3174, 3789, + 3902, 3178, 3787, + 3900, 3183, 3785, + 3897, 3190, 3781, + 3892, 3200, 3777, + 3887, 3212, 3771, + 3879, 3228, 3764, + 3868, 3249, 3753, + 3853, 3275, 3739, + 3832, 3307, 3718, + 3803, 3348, 3690, + 3760, 3397, 3648, + 3696, 3455, 3587, + 3594, 3522, 3488, + 3407, 3599, 3311, + 2887, 3686, 2847, + 0, 3780, 0, + 4053, 3220, 3894, + 4053, 3221, 3894, + 4053, 3221, 3894, + 4053, 3221, 3894, + 4053, 3221, 3894, + 4053, 3221, 3894, + 4053, 3221, 3894, + 4053, 3221, 3894, + 4053, 3222, 3894, + 4052, 3222, 3894, + 4052, 3223, 3894, + 4052, 3224, 3893, + 4052, 3225, 3893, + 4051, 3226, 3892, + 4050, 3229, 3891, + 4049, 3231, 3890, + 4048, 3235, 3889, + 4046, 3240, 3887, + 4044, 3246, 3885, + 4041, 3254, 3881, + 4037, 3265, 3877, + 4031, 3280, 3871, + 4023, 3298, 3862, + 4013, 3321, 3851, + 3998, 3351, 3835, + 3978, 3388, 3813, + 3950, 3433, 3782, + 3908, 3487, 3737, + 3847, 3550, 3668, + 3749, 3623, 3557, + 3573, 3705, 3345, + 3119, 3796, 2630, + 4095, 3289, 4002, + 4095, 3289, 4002, + 4095, 3289, 4002, + 4095, 3289, 4002, + 4095, 3289, 4001, + 4095, 3290, 4001, + 4095, 3290, 4001, + 4095, 3290, 4001, + 4095, 3290, 4001, + 4095, 3291, 4001, + 4095, 3291, 4001, + 4095, 3292, 4001, + 4095, 3293, 4000, + 4095, 3294, 4000, + 4095, 3296, 3999, + 4095, 3298, 3998, + 4095, 3302, 3997, + 4095, 3306, 3996, + 4095, 3311, 3994, + 4095, 3318, 3991, + 4095, 3328, 3988, + 4095, 3340, 3983, + 4095, 3357, 3976, + 4095, 3377, 3967, + 4095, 3403, 3955, + 4095, 3436, 3939, + 4095, 3477, 3915, + 4092, 3526, 3882, + 4052, 3585, 3833, + 3993, 3653, 3758, + 3898, 3730, 3634, + 3730, 3816, 3387, + 4095, 3367, 4095, + 4095, 3367, 4095, + 4095, 3367, 4095, + 4095, 3367, 4095, + 4095, 3367, 4095, + 4095, 3368, 4095, + 4095, 3368, 4095, + 4095, 3368, 4095, + 4095, 3368, 4095, + 4095, 3369, 4095, + 4095, 3369, 4095, + 4095, 3370, 4095, + 4095, 3370, 4095, + 4095, 3372, 4095, + 4095, 3373, 4095, + 4095, 3375, 4095, + 4095, 3378, 4095, + 4095, 3381, 4095, + 4095, 3386, 4095, + 4095, 3392, 4095, + 4095, 3400, 4095, + 4095, 3411, 4095, + 4095, 3425, 4094, + 4095, 3442, 4088, + 4095, 3465, 4078, + 4095, 3494, 4066, + 4095, 3530, 4048, + 4095, 3574, 4023, + 4095, 3627, 3988, + 4095, 3689, 3936, + 4095, 3761, 3857, + 4042, 3842, 3721, + 0, 3052, 3322, + 0, 3052, 3322, + 0, 3053, 3321, + 0, 3053, 3321, + 0, 3053, 3321, + 0, 3053, 3321, + 0, 3053, 3321, + 0, 3054, 3320, + 0, 3054, 3320, + 0, 3055, 3319, + 0, 3056, 3318, + 0, 3057, 3317, + 0, 3059, 3316, + 0, 3061, 3314, + 0, 3064, 3311, + 0, 3068, 3307, + 0, 3073, 3302, + 0, 3080, 3295, + 0, 3089, 3286, + 0, 3101, 3273, + 0, 3116, 3256, + 0, 3136, 3231, + 0, 3161, 3196, + 0, 3192, 3144, + 0, 3231, 3064, + 0, 3278, 2929, + 0, 3335, 2647, + 0, 3401, 0, + 0, 3476, 0, + 0, 3561, 0, + 0, 3654, 0, + 0, 3755, 0, + 0, 3052, 3322, + 0, 3052, 3322, + 0, 3053, 3322, + 0, 3053, 3321, + 0, 3053, 3321, + 0, 3053, 3321, + 0, 3053, 3321, + 0, 3054, 3320, + 0, 3054, 3320, + 0, 3055, 3319, + 0, 3056, 3319, + 0, 3057, 3317, + 0, 3059, 3316, + 0, 3061, 3314, + 0, 3064, 3311, + 0, 3068, 3307, + 0, 3073, 3302, + 0, 3080, 3295, + 0, 3089, 3286, + 0, 3101, 3273, + 0, 3116, 3256, + 0, 3136, 3231, + 0, 3161, 3196, + 0, 3192, 3144, + 0, 3231, 3065, + 0, 3278, 2930, + 0, 3335, 2648, + 0, 3401, 0, + 0, 3476, 0, + 0, 3561, 0, + 0, 3654, 0, + 0, 3755, 0, + 0, 3052, 3322, + 0, 3052, 3322, + 0, 3053, 3322, + 0, 3053, 3322, + 0, 3053, 3321, + 0, 3053, 3321, + 0, 3053, 3321, + 0, 3054, 3321, + 0, 3054, 3320, + 0, 3055, 3319, + 0, 3056, 3319, + 0, 3057, 3318, + 0, 3059, 3316, + 0, 3061, 3314, + 0, 3064, 3311, + 0, 3068, 3307, + 0, 3073, 3302, + 0, 3080, 3296, + 0, 3089, 3286, + 0, 3101, 3274, + 0, 3116, 3256, + 0, 3136, 3231, + 0, 3161, 3196, + 0, 3192, 3145, + 0, 3231, 3065, + 0, 3278, 2930, + 0, 3335, 2648, + 0, 3401, 0, + 0, 3476, 0, + 0, 3561, 0, + 0, 3654, 0, + 0, 3755, 0, + 0, 3052, 3322, + 0, 3053, 3322, + 0, 3053, 3322, + 0, 3053, 3322, + 0, 3053, 3322, + 0, 3053, 3321, + 0, 3053, 3321, + 0, 3054, 3321, + 0, 3054, 3320, + 0, 3055, 3320, + 0, 3056, 3319, + 0, 3057, 3318, + 0, 3059, 3316, + 0, 3061, 3314, + 0, 3064, 3311, + 0, 3068, 3308, + 0, 3073, 3303, + 0, 3080, 3296, + 0, 3089, 3286, + 0, 3101, 3274, + 0, 3116, 3256, + 0, 3136, 3232, + 0, 3161, 3197, + 0, 3192, 3145, + 0, 3231, 3065, + 0, 3278, 2930, + 0, 3335, 2649, + 0, 3401, 0, + 0, 3476, 0, + 0, 3561, 0, + 0, 3654, 0, + 0, 3755, 0, + 0, 3053, 3322, + 0, 3053, 3322, + 0, 3053, 3322, + 0, 3053, 3322, + 0, 3053, 3322, + 0, 3053, 3322, + 0, 3053, 3321, + 0, 3054, 3321, + 0, 3054, 3321, + 0, 3055, 3320, + 0, 3056, 3319, + 0, 3057, 3318, + 0, 3059, 3316, + 0, 3061, 3314, + 0, 3064, 3312, + 0, 3068, 3308, + 0, 3073, 3303, + 0, 3080, 3296, + 0, 3089, 3287, + 0, 3101, 3274, + 0, 3116, 3256, + 0, 3136, 3232, + 0, 3161, 3197, + 0, 3192, 3145, + 0, 3231, 3065, + 0, 3278, 2931, + 0, 3335, 2650, + 0, 3401, 0, + 0, 3476, 0, + 0, 3561, 0, + 0, 3654, 0, + 0, 3755, 0, + 0, 3053, 3323, + 0, 3053, 3322, + 0, 3053, 3322, + 0, 3053, 3322, + 0, 3053, 3322, + 0, 3053, 3322, + 0, 3054, 3322, + 0, 3054, 3321, + 0, 3054, 3321, + 0, 3055, 3320, + 0, 3056, 3319, + 0, 3057, 3318, + 0, 3059, 3317, + 0, 3061, 3315, + 0, 3064, 3312, + 0, 3068, 3308, + 0, 3073, 3303, + 0, 3080, 3296, + 0, 3089, 3287, + 0, 3101, 3274, + 0, 3116, 3257, + 0, 3136, 3232, + 0, 3161, 3197, + 0, 3192, 3146, + 0, 3231, 3066, + 0, 3279, 2932, + 0, 3335, 2651, + 0, 3401, 0, + 0, 3476, 0, + 0, 3561, 0, + 0, 3654, 0, + 0, 3755, 0, + 0, 3053, 3323, + 0, 3053, 3323, + 0, 3053, 3323, + 0, 3053, 3323, + 0, 3053, 3323, + 0, 3053, 3322, + 0, 3054, 3322, + 0, 3054, 3322, + 0, 3055, 3321, + 0, 3055, 3321, + 0, 3056, 3320, + 0, 3057, 3319, + 0, 3059, 3317, + 0, 3061, 3315, + 0, 3064, 3312, + 0, 3068, 3309, + 0, 3073, 3304, + 0, 3080, 3297, + 0, 3089, 3287, + 0, 3101, 3275, + 0, 3116, 3257, + 0, 3136, 3233, + 0, 3161, 3198, + 0, 3192, 3146, + 0, 3231, 3067, + 0, 3279, 2932, + 0, 3335, 2653, + 0, 3401, 0, + 0, 3476, 0, + 0, 3561, 0, + 0, 3654, 0, + 0, 3755, 0, + 0, 3053, 3323, + 0, 3053, 3323, + 0, 3053, 3323, + 0, 3053, 3323, + 0, 3053, 3323, + 0, 3053, 3323, + 0, 3054, 3323, + 0, 3054, 3322, + 0, 3055, 3322, + 0, 3055, 3321, + 0, 3056, 3320, + 0, 3058, 3319, + 0, 3059, 3318, + 0, 3061, 3316, + 0, 3064, 3313, + 0, 3068, 3309, + 0, 3074, 3304, + 0, 3080, 3297, + 0, 3089, 3288, + 0, 3101, 3275, + 0, 3116, 3258, + 0, 3136, 3233, + 0, 3161, 3198, + 0, 3192, 3147, + 0, 3231, 3068, + 0, 3279, 2934, + 0, 3335, 2655, + 0, 3401, 0, + 0, 3476, 0, + 0, 3561, 0, + 0, 3654, 0, + 0, 3755, 0, + 0, 3053, 3324, + 0, 3053, 3324, + 0, 3053, 3324, + 0, 3053, 3324, + 0, 3053, 3324, + 0, 3054, 3324, + 0, 3054, 3323, + 0, 3054, 3323, + 0, 3055, 3322, + 0, 3056, 3322, + 0, 3057, 3321, + 0, 3058, 3320, + 0, 3059, 3318, + 0, 3062, 3316, + 0, 3065, 3314, + 0, 3069, 3310, + 0, 3074, 3305, + 0, 3081, 3298, + 0, 3090, 3289, + 0, 3101, 3276, + 0, 3117, 3259, + 0, 3136, 3234, + 0, 3161, 3199, + 0, 3193, 3148, + 0, 3231, 3069, + 0, 3279, 2935, + 0, 3335, 2658, + 0, 3401, 0, + 0, 3477, 0, + 0, 3561, 0, + 0, 3654, 0, + 0, 3755, 0, + 0, 3053, 3325, + 0, 3053, 3325, + 0, 3053, 3325, + 0, 3054, 3325, + 0, 3054, 3325, + 0, 3054, 3325, + 0, 3054, 3324, + 0, 3055, 3324, + 0, 3055, 3323, + 0, 3056, 3323, + 0, 3057, 3322, + 0, 3058, 3321, + 0, 3060, 3319, + 0, 3062, 3317, + 0, 3065, 3314, + 0, 3069, 3311, + 0, 3074, 3306, + 0, 3081, 3299, + 0, 3090, 3290, + 0, 3102, 3277, + 0, 3117, 3260, + 0, 3136, 3235, + 0, 3161, 3201, + 0, 3193, 3149, + 0, 3232, 3071, + 0, 3279, 2938, + 0, 3335, 2662, + 0, 3401, 0, + 0, 3477, 0, + 0, 3561, 0, + 0, 3654, 0, + 0, 3755, 0, + 0, 3054, 3326, + 0, 3054, 3326, + 0, 3054, 3326, + 0, 3054, 3326, + 0, 3054, 3326, + 0, 3054, 3326, + 0, 3055, 3326, + 0, 3055, 3325, + 0, 3055, 3325, + 0, 3056, 3324, + 0, 3057, 3323, + 0, 3058, 3322, + 0, 3060, 3321, + 0, 3062, 3319, + 0, 3065, 3316, + 0, 3069, 3312, + 0, 3074, 3307, + 0, 3081, 3300, + 0, 3090, 3291, + 0, 3102, 3279, + 0, 3117, 3261, + 0, 3137, 3237, + 0, 3162, 3202, + 0, 3193, 3151, + 0, 3232, 3073, + 0, 3279, 2941, + 0, 3335, 2668, + 0, 3401, 0, + 0, 3477, 0, + 0, 3561, 0, + 0, 3654, 0, + 0, 3755, 0, + 0, 3054, 3328, + 0, 3054, 3328, + 0, 3054, 3328, + 0, 3054, 3328, + 0, 3054, 3328, + 0, 3055, 3327, + 0, 3055, 3327, + 0, 3055, 3327, + 0, 3056, 3326, + 0, 3057, 3326, + 0, 3057, 3325, + 0, 3059, 3324, + 0, 3060, 3322, + 0, 3063, 3320, + 0, 3066, 3318, + 0, 3069, 3314, + 0, 3075, 3309, + 0, 3081, 3302, + 0, 3090, 3293, + 0, 3102, 3281, + 0, 3117, 3263, + 0, 3137, 3239, + 0, 3162, 3204, + 0, 3193, 3154, + 0, 3232, 3076, + 0, 3279, 2944, + 0, 3336, 2675, + 0, 3402, 0, + 0, 3477, 0, + 0, 3561, 0, + 0, 3654, 0, + 0, 3755, 0, + 0, 3055, 3330, + 0, 3055, 3330, + 0, 3055, 3330, + 0, 3055, 3330, + 0, 3055, 3330, + 0, 3055, 3330, + 0, 3056, 3329, + 0, 3056, 3329, + 0, 3056, 3329, + 0, 3057, 3328, + 0, 3058, 3327, + 0, 3059, 3326, + 0, 3061, 3325, + 0, 3063, 3323, + 0, 3066, 3320, + 0, 3070, 3316, + 0, 3075, 3311, + 0, 3082, 3305, + 0, 3091, 3295, + 0, 3103, 3283, + 0, 3118, 3266, + 0, 3137, 3242, + 0, 3162, 3207, + 0, 3194, 3157, + 0, 3233, 3080, + 0, 3280, 2950, + 0, 3336, 2684, + 0, 3402, 0, + 0, 3477, 0, + 0, 3562, 0, + 0, 3655, 0, + 0, 3755, 0, + 0, 3055, 3333, + 0, 3055, 3333, + 0, 3055, 3333, + 0, 3056, 3333, + 0, 3056, 3333, + 0, 3056, 3333, + 0, 3056, 3332, + 0, 3057, 3332, + 0, 3057, 3332, + 0, 3058, 3331, + 0, 3059, 3330, + 0, 3060, 3329, + 0, 3062, 3328, + 0, 3064, 3326, + 0, 3067, 3323, + 0, 3071, 3319, + 0, 3076, 3314, + 0, 3083, 3308, + 0, 3092, 3299, + 0, 3103, 3286, + 0, 3119, 3269, + 0, 3138, 3245, + 0, 3163, 3211, + 0, 3194, 3161, + 0, 3233, 3085, + 0, 3280, 2957, + 0, 3336, 2696, + 0, 3402, 0, + 0, 3477, 0, + 0, 3562, 0, + 0, 3655, 0, + 0, 3755, 0, + 0, 3056, 3337, + 0, 3056, 3337, + 0, 3056, 3337, + 0, 3057, 3337, + 0, 3057, 3337, + 0, 3057, 3337, + 0, 3057, 3336, + 0, 3058, 3336, + 0, 3058, 3336, + 0, 3059, 3335, + 0, 3060, 3334, + 0, 3061, 3333, + 0, 3063, 3332, + 0, 3065, 3330, + 0, 3068, 3327, + 0, 3072, 3323, + 0, 3077, 3318, + 0, 3084, 3312, + 0, 3093, 3303, + 0, 3104, 3291, + 0, 3119, 3274, + 0, 3139, 3250, + 0, 3164, 3216, + 0, 3195, 3167, + 0, 3234, 3092, + 0, 3281, 2966, + 0, 3337, 2712, + 0, 3403, 0, + 0, 3478, 0, + 0, 3562, 0, + 0, 3655, 0, + 0, 3755, 0, + 0, 3058, 3342, + 0, 3058, 3342, + 0, 3058, 3342, + 0, 3058, 3342, + 0, 3058, 3342, + 0, 3058, 3342, + 0, 3059, 3342, + 0, 3059, 3341, + 0, 3060, 3341, + 0, 3060, 3340, + 0, 3061, 3339, + 0, 3062, 3338, + 0, 3064, 3337, + 0, 3066, 3335, + 0, 3069, 3332, + 0, 3073, 3329, + 0, 3078, 3324, + 0, 3085, 3317, + 0, 3094, 3309, + 0, 3106, 3296, + 0, 3121, 3280, + 0, 3140, 3256, + 0, 3165, 3223, + 0, 3196, 3175, + 0, 3235, 3100, + 0, 3282, 2977, + 0, 3338, 2733, + 0, 3403, 1334, + 0, 3478, 0, + 0, 3563, 0, + 0, 3655, 0, + 0, 3756, 0, + 0, 3059, 3349, + 0, 3060, 3349, + 0, 3060, 3349, + 0, 3060, 3349, + 0, 3060, 3349, + 0, 3060, 3349, + 0, 3060, 3349, + 0, 3061, 3348, + 0, 3061, 3348, + 0, 3062, 3347, + 0, 3063, 3346, + 0, 3064, 3345, + 0, 3066, 3344, + 0, 3068, 3342, + 0, 3071, 3339, + 0, 3075, 3336, + 0, 3080, 3331, + 0, 3087, 3325, + 0, 3096, 3316, + 0, 3107, 3304, + 0, 3122, 3288, + 0, 3142, 3265, + 0, 3166, 3232, + 0, 3197, 3185, + 0, 3236, 3112, + 0, 3283, 2993, + 0, 3339, 2758, + 0, 3404, 1707, + 0, 3479, 0, + 0, 3563, 0, + 0, 3656, 0, + 0, 3756, 0, + 0, 3062, 3358, + 0, 3062, 3358, + 0, 3062, 3358, + 0, 3062, 3358, + 0, 3062, 3358, + 0, 3063, 3358, + 0, 3063, 3358, + 0, 3063, 3357, + 0, 3064, 3357, + 0, 3064, 3356, + 0, 3065, 3355, + 0, 3067, 3354, + 0, 3068, 3353, + 0, 3070, 3351, + 0, 3073, 3349, + 0, 3077, 3345, + 0, 3082, 3341, + 0, 3089, 3334, + 0, 3098, 3326, + 0, 3109, 3314, + 0, 3124, 3298, + 0, 3144, 3276, + 0, 3168, 3244, + 0, 3199, 3198, + 0, 3238, 3127, + 0, 3284, 3012, + 0, 3340, 2791, + 0, 3405, 1961, + 0, 3480, 0, + 0, 3564, 0, + 0, 3657, 0, + 0, 3757, 0, + 0, 3065, 3370, + 0, 3065, 3370, + 0, 3065, 3370, + 0, 3065, 3370, + 0, 3066, 3370, + 0, 3066, 3370, + 0, 3066, 3369, + 0, 3066, 3369, + 0, 3067, 3369, + 0, 3068, 3368, + 0, 3069, 3367, + 0, 3070, 3366, + 0, 3071, 3365, + 0, 3074, 3363, + 0, 3076, 3361, + 0, 3080, 3357, + 0, 3085, 3353, + 0, 3092, 3347, + 0, 3101, 3338, + 0, 3112, 3327, + 0, 3127, 3312, + 0, 3146, 3290, + 0, 3171, 3259, + 0, 3202, 3214, + 0, 3240, 3147, + 0, 3286, 3037, + 0, 3342, 2831, + 0, 3407, 2166, + 0, 3481, 0, + 0, 3565, 0, + 0, 3657, 0, + 0, 3757, 0, + 0, 3069, 3386, + 0, 3069, 3386, + 0, 3070, 3386, + 0, 3070, 3385, + 0, 3070, 3385, + 0, 3070, 3385, + 0, 3070, 3385, + 0, 3071, 3385, + 0, 3071, 3384, + 0, 3072, 3384, + 0, 3073, 3383, + 0, 3074, 3382, + 0, 3076, 3381, + 0, 3078, 3379, + 0, 3081, 3376, + 0, 3084, 3373, + 0, 3089, 3369, + 0, 3096, 3363, + 0, 3105, 3355, + 0, 3116, 3344, + 0, 3131, 3329, + 0, 3150, 3308, + 0, 3174, 3279, + 0, 3205, 3236, + 0, 3243, 3172, + 0, 3289, 3069, + 0, 3344, 2880, + 0, 3409, 2347, + 0, 3483, 0, + 0, 3567, 0, + 0, 3659, 0, + 0, 3758, 0, + 0, 3075, 3405, + 0, 3075, 3405, + 0, 3075, 3405, + 0, 3075, 3405, + 0, 3075, 3405, + 0, 3076, 3405, + 0, 3076, 3405, + 0, 3076, 3404, + 0, 3077, 3404, + 0, 3077, 3404, + 0, 3078, 3403, + 0, 3080, 3402, + 0, 3081, 3401, + 0, 3083, 3399, + 0, 3086, 3397, + 0, 3090, 3393, + 0, 3095, 3389, + 0, 3101, 3384, + 0, 3110, 3376, + 0, 3121, 3366, + 0, 3136, 3351, + 0, 3155, 3332, + 0, 3179, 3304, + 0, 3209, 3263, + 0, 3246, 3203, + 0, 3292, 3108, + 0, 3347, 2937, + 0, 3411, 2512, + 0, 3485, 0, + 0, 3568, 0, + 0, 3660, 0, + 0, 3759, 0, + 1593, 3082, 3431, + 1590, 3082, 3431, + 1585, 3083, 3431, + 1578, 3083, 3430, + 1569, 3083, 3430, + 1556, 3083, 3430, + 1539, 3083, 3430, + 1515, 3084, 3430, + 1480, 3084, 3429, + 1429, 3085, 3429, + 1351, 3086, 3428, + 1220, 3087, 3427, + 950, 3088, 3426, + 0, 3090, 3424, + 0, 3093, 3422, + 0, 3097, 3419, + 0, 3102, 3415, + 0, 3108, 3410, + 0, 3117, 3403, + 0, 3128, 3393, + 0, 3142, 3380, + 0, 3161, 3361, + 0, 3184, 3335, + 0, 3214, 3297, + 0, 3252, 3242, + 0, 3297, 3155, + 0, 3351, 3005, + 0, 3415, 2667, + 0, 3488, 0, + 0, 3571, 0, + 0, 3662, 0, + 0, 3761, 0, + 2589, 3092, 3462, + 2589, 3092, 3462, + 2588, 3092, 3462, + 2588, 3092, 3462, + 2587, 3092, 3462, + 2585, 3093, 3462, + 2584, 3093, 3462, + 2581, 3093, 3461, + 2578, 3094, 3461, + 2574, 3094, 3461, + 2568, 3095, 3460, + 2560, 3096, 3459, + 2549, 3098, 3458, + 2534, 3100, 3456, + 2514, 3103, 3454, + 2484, 3106, 3452, + 2442, 3111, 3448, + 2379, 3117, 3443, + 2277, 3126, 3436, + 2092, 3137, 3427, + 1586, 3151, 3415, + 0, 3169, 3398, + 0, 3192, 3374, + 0, 3222, 3339, + 0, 3258, 3289, + 0, 3303, 3211, + 0, 3357, 3081, + 0, 3420, 2816, + 0, 3492, 0, + 0, 3574, 0, + 0, 3665, 0, + 0, 3763, 0, + 2945, 3105, 3501, + 2945, 3105, 3501, + 2945, 3105, 3501, + 2944, 3105, 3501, + 2944, 3105, 3501, + 2943, 3105, 3501, + 2942, 3106, 3501, + 2941, 3106, 3501, + 2940, 3106, 3500, + 2938, 3107, 3500, + 2935, 3108, 3499, + 2932, 3109, 3499, + 2927, 3110, 3497, + 2921, 3112, 3496, + 2912, 3115, 3494, + 2900, 3119, 3492, + 2884, 3123, 3488, + 2861, 3129, 3484, + 2828, 3137, 3478, + 2780, 3148, 3470, + 2708, 3162, 3458, + 2588, 3180, 3443, + 2352, 3202, 3421, + 1272, 3231, 3390, + 0, 3267, 3345, + 0, 3311, 3277, + 0, 3364, 3167, + 0, 3426, 2960, + 0, 3498, 2284, + 0, 3579, 0, + 0, 3669, 0, + 0, 3766, 0, + 3193, 3121, 3549, + 3193, 3121, 3549, + 3193, 3121, 3549, + 3193, 3121, 3549, + 3192, 3122, 3549, + 3192, 3122, 3549, + 3192, 3122, 3548, + 3191, 3122, 3548, + 3190, 3123, 3548, + 3189, 3123, 3548, + 3188, 3124, 3547, + 3186, 3125, 3546, + 3183, 3127, 3545, + 3179, 3129, 3544, + 3174, 3131, 3543, + 3168, 3135, 3540, + 3159, 3139, 3537, + 3146, 3145, 3533, + 3129, 3153, 3528, + 3105, 3163, 3520, + 3071, 3176, 3510, + 3021, 3194, 3496, + 2944, 3216, 3477, + 2815, 3244, 3450, + 2553, 3279, 3411, + 0, 3321, 3353, + 0, 3373, 3261, + 0, 3434, 3101, + 0, 3505, 2720, + 0, 3585, 0, + 0, 3673, 0, + 0, 3770, 0, + 3396, 3142, 3606, + 3396, 3142, 3606, + 3396, 3142, 3606, + 3396, 3142, 3606, + 3396, 3143, 3605, + 3395, 3143, 3605, + 3395, 3143, 3605, + 3395, 3143, 3605, + 3394, 3144, 3605, + 3393, 3144, 3604, + 3392, 3145, 3604, + 3391, 3146, 3603, + 3389, 3148, 3603, + 3387, 3149, 3601, + 3384, 3152, 3600, + 3380, 3155, 3598, + 3374, 3159, 3595, + 3367, 3165, 3592, + 3356, 3172, 3587, + 3342, 3182, 3581, + 3322, 3195, 3572, + 3294, 3212, 3560, + 3253, 3233, 3543, + 3192, 3260, 3519, + 3096, 3294, 3486, + 2923, 3335, 3437, + 2486, 3385, 3363, + 0, 3445, 3239, + 0, 3514, 2993, + 0, 3592, 1507, + 0, 3680, 0, + 0, 3775, 0, + 3575, 3169, 3672, + 3575, 3169, 3672, + 3574, 3169, 3672, + 3574, 3169, 3672, + 3574, 3169, 3672, + 3574, 3169, 3672, + 3574, 3170, 3672, + 3574, 3170, 3671, + 3573, 3170, 3671, + 3573, 3171, 3671, + 3572, 3172, 3670, + 3571, 3173, 3670, + 3570, 3174, 3669, + 3569, 3176, 3668, + 3567, 3178, 3667, + 3564, 3181, 3665, + 3560, 3185, 3663, + 3555, 3190, 3660, + 3548, 3198, 3656, + 3539, 3207, 3650, + 3526, 3219, 3643, + 3508, 3235, 3632, + 3483, 3255, 3618, + 3448, 3281, 3598, + 3395, 3313, 3571, + 3314, 3353, 3531, + 3176, 3401, 3471, + 2884, 3459, 3376, + 0, 3526, 3208, + 0, 3602, 2792, + 0, 3688, 0, + 0, 3782, 0, + 3739, 3202, 3748, + 3739, 3202, 3748, + 3739, 3203, 3748, + 3738, 3203, 3748, + 3738, 3203, 3748, + 3738, 3203, 3747, + 3738, 3203, 3747, + 3738, 3203, 3747, + 3738, 3204, 3747, + 3737, 3204, 3747, + 3737, 3205, 3746, + 3736, 3206, 3746, + 3736, 3207, 3745, + 3734, 3209, 3745, + 3733, 3211, 3744, + 3731, 3214, 3742, + 3728, 3217, 3740, + 3725, 3222, 3738, + 3720, 3229, 3734, + 3714, 3238, 3729, + 3705, 3249, 3723, + 3693, 3264, 3714, + 3677, 3283, 3703, + 3654, 3307, 3686, + 3621, 3338, 3663, + 3574, 3375, 3631, + 3501, 3422, 3584, + 3381, 3477, 3512, + 3147, 3541, 3393, + 2084, 3616, 3162, + 0, 3699, 2171, + 0, 3791, 0, + 3893, 3244, 3833, + 3893, 3244, 3833, + 3893, 3244, 3833, + 3893, 3244, 3832, + 3893, 3244, 3832, + 3893, 3244, 3832, + 3893, 3244, 3832, + 3893, 3244, 3832, + 3893, 3245, 3832, + 3892, 3245, 3832, + 3892, 3246, 3832, + 3892, 3247, 3831, + 3891, 3248, 3831, + 3890, 3249, 3830, + 3889, 3251, 3829, + 3888, 3254, 3828, + 3886, 3257, 3826, + 3884, 3262, 3824, + 3880, 3268, 3821, + 3876, 3276, 3817, + 3870, 3286, 3812, + 3861, 3300, 3805, + 3850, 3318, 3795, + 3835, 3340, 3782, + 3813, 3368, 3764, + 3782, 3404, 3738, + 3738, 3447, 3701, + 3670, 3500, 3646, + 3561, 3561, 3561, + 3357, 3633, 3415, + 2705, 3713, 3092, + 0, 3803, 0, + 4041, 3293, 3926, + 4041, 3293, 3926, + 4041, 3294, 3926, + 4041, 3294, 3926, + 4041, 3294, 3926, + 4041, 3294, 3926, + 4041, 3294, 3926, + 4041, 3294, 3926, + 4041, 3295, 3925, + 4041, 3295, 3925, + 4041, 3296, 3925, + 4040, 3296, 3925, + 4040, 3297, 3924, + 4039, 3299, 3924, + 4039, 3300, 3923, + 4038, 3303, 3922, + 4036, 3306, 3921, + 4034, 3310, 3919, + 4032, 3315, 3917, + 4029, 3322, 3914, + 4025, 3332, 3909, + 4019, 3344, 3904, + 4011, 3360, 3896, + 4000, 3381, 3885, + 3985, 3407, 3871, + 3964, 3440, 3850, + 3935, 3480, 3822, + 3892, 3529, 3781, + 3829, 3587, 3719, + 3726, 3654, 3620, + 3539, 3732, 3443, + 3019, 3818, 2979, + 4095, 3353, 4027, + 4095, 3353, 4027, + 4095, 3353, 4027, + 4095, 3353, 4027, + 4095, 3353, 4026, + 4095, 3353, 4026, + 4095, 3353, 4026, + 4095, 3353, 4026, + 4095, 3354, 4026, + 4095, 3354, 4026, + 4095, 3354, 4026, + 4095, 3355, 4026, + 4095, 3356, 4025, + 4095, 3357, 4025, + 4095, 3359, 4024, + 4095, 3361, 4024, + 4095, 3363, 4023, + 4095, 3367, 4021, + 4095, 3372, 4019, + 4095, 3378, 4017, + 4095, 3387, 4013, + 4095, 3397, 4009, + 4095, 3412, 4003, + 4095, 3430, 3994, + 4095, 3454, 3983, + 4095, 3483, 3967, + 4095, 3520, 3945, + 4082, 3565, 3914, + 4041, 3619, 3869, + 3979, 3682, 3800, + 3881, 3755, 3689, + 3706, 3837, 3477, + 4095, 3421, 4095, + 4095, 3421, 4095, + 4095, 3421, 4095, + 4095, 3421, 4095, + 4095, 3421, 4095, + 4095, 3421, 4095, + 4095, 3422, 4095, + 4095, 3422, 4095, + 4095, 3422, 4095, + 4095, 3422, 4095, + 4095, 3423, 4095, + 4095, 3423, 4095, + 4095, 3424, 4095, + 4095, 3425, 4095, + 4095, 3426, 4095, + 4095, 3428, 4095, + 4095, 3431, 4095, + 4095, 3434, 4095, + 4095, 3438, 4095, + 4095, 3443, 4095, + 4095, 3451, 4095, + 4095, 3460, 4095, + 4095, 3473, 4095, + 4095, 3489, 4095, + 4095, 3509, 4095, + 4095, 3536, 4087, + 4095, 3568, 4071, + 4095, 3609, 4047, + 4095, 3658, 4014, + 4095, 3717, 3965, + 4095, 3785, 3891, + 4030, 3862, 3767, + 0, 3184, 3454, + 0, 3184, 3454, + 0, 3185, 3454, + 0, 3185, 3453, + 0, 3185, 3453, + 0, 3185, 3453, + 0, 3185, 3453, + 0, 3185, 3453, + 0, 3186, 3452, + 0, 3186, 3452, + 0, 3187, 3451, + 0, 3188, 3450, + 0, 3189, 3449, + 0, 3191, 3448, + 0, 3193, 3446, + 0, 3196, 3443, + 0, 3200, 3439, + 0, 3205, 3434, + 0, 3212, 3427, + 0, 3221, 3418, + 0, 3233, 3405, + 0, 3248, 3388, + 0, 3268, 3363, + 0, 3293, 3328, + 0, 3324, 3276, + 0, 3363, 3196, + 0, 3410, 3061, + 0, 3467, 2779, + 0, 3533, 0, + 0, 3608, 0, + 0, 3693, 0, + 0, 3786, 0, + 0, 3184, 3454, + 0, 3184, 3454, + 0, 3185, 3454, + 0, 3185, 3454, + 0, 3185, 3453, + 0, 3185, 3453, + 0, 3185, 3453, + 0, 3185, 3453, + 0, 3186, 3452, + 0, 3186, 3452, + 0, 3187, 3451, + 0, 3188, 3451, + 0, 3189, 3449, + 0, 3191, 3448, + 0, 3193, 3446, + 0, 3196, 3443, + 0, 3200, 3439, + 0, 3205, 3434, + 0, 3212, 3427, + 0, 3221, 3418, + 0, 3233, 3405, + 0, 3248, 3388, + 0, 3268, 3363, + 0, 3293, 3328, + 0, 3324, 3276, + 0, 3363, 3196, + 0, 3410, 3061, + 0, 3467, 2779, + 0, 3533, 0, + 0, 3608, 0, + 0, 3693, 0, + 0, 3786, 0, + 0, 3184, 3454, + 0, 3184, 3454, + 0, 3185, 3454, + 0, 3185, 3454, + 0, 3185, 3454, + 0, 3185, 3453, + 0, 3185, 3453, + 0, 3185, 3453, + 0, 3186, 3453, + 0, 3186, 3452, + 0, 3187, 3451, + 0, 3188, 3451, + 0, 3189, 3449, + 0, 3191, 3448, + 0, 3193, 3446, + 0, 3196, 3443, + 0, 3200, 3439, + 0, 3205, 3434, + 0, 3212, 3428, + 0, 3221, 3418, + 0, 3233, 3406, + 0, 3248, 3388, + 0, 3268, 3363, + 0, 3293, 3328, + 0, 3324, 3277, + 0, 3363, 3197, + 0, 3411, 3062, + 0, 3467, 2780, + 0, 3533, 0, + 0, 3608, 0, + 0, 3693, 0, + 0, 3786, 0, + 0, 3184, 3454, + 0, 3185, 3454, + 0, 3185, 3454, + 0, 3185, 3454, + 0, 3185, 3454, + 0, 3185, 3454, + 0, 3185, 3453, + 0, 3185, 3453, + 0, 3186, 3453, + 0, 3186, 3452, + 0, 3187, 3452, + 0, 3188, 3451, + 0, 3189, 3450, + 0, 3191, 3448, + 0, 3193, 3446, + 0, 3196, 3443, + 0, 3200, 3440, + 0, 3205, 3434, + 0, 3212, 3428, + 0, 3221, 3418, + 0, 3233, 3406, + 0, 3248, 3388, + 0, 3268, 3364, + 0, 3293, 3328, + 0, 3324, 3277, + 0, 3363, 3197, + 0, 3411, 3062, + 0, 3467, 2780, + 0, 3533, 0, + 0, 3608, 0, + 0, 3693, 0, + 0, 3786, 0, + 0, 3184, 3454, + 0, 3185, 3454, + 0, 3185, 3454, + 0, 3185, 3454, + 0, 3185, 3454, + 0, 3185, 3454, + 0, 3185, 3453, + 0, 3186, 3453, + 0, 3186, 3453, + 0, 3186, 3452, + 0, 3187, 3452, + 0, 3188, 3451, + 0, 3189, 3450, + 0, 3191, 3448, + 0, 3193, 3446, + 0, 3196, 3443, + 0, 3200, 3440, + 0, 3205, 3435, + 0, 3212, 3428, + 0, 3221, 3419, + 0, 3233, 3406, + 0, 3248, 3388, + 0, 3268, 3364, + 0, 3293, 3329, + 0, 3324, 3277, + 0, 3363, 3197, + 0, 3411, 3062, + 0, 3467, 2781, + 0, 3533, 0, + 0, 3608, 0, + 0, 3693, 0, + 0, 3786, 0, + 0, 3185, 3454, + 0, 3185, 3454, + 0, 3185, 3454, + 0, 3185, 3454, + 0, 3185, 3454, + 0, 3185, 3454, + 0, 3185, 3454, + 0, 3186, 3453, + 0, 3186, 3453, + 0, 3186, 3453, + 0, 3187, 3452, + 0, 3188, 3451, + 0, 3189, 3450, + 0, 3191, 3448, + 0, 3193, 3446, + 0, 3196, 3444, + 0, 3200, 3440, + 0, 3205, 3435, + 0, 3212, 3428, + 0, 3221, 3419, + 0, 3233, 3406, + 0, 3248, 3389, + 0, 3268, 3364, + 0, 3293, 3329, + 0, 3324, 3277, + 0, 3363, 3198, + 0, 3411, 3063, + 0, 3467, 2782, + 0, 3533, 0, + 0, 3608, 0, + 0, 3693, 0, + 0, 3786, 0, + 0, 3185, 3455, + 0, 3185, 3455, + 0, 3185, 3455, + 0, 3185, 3454, + 0, 3185, 3454, + 0, 3185, 3454, + 0, 3185, 3454, + 0, 3186, 3454, + 0, 3186, 3453, + 0, 3187, 3453, + 0, 3187, 3452, + 0, 3188, 3451, + 0, 3189, 3450, + 0, 3191, 3449, + 0, 3193, 3447, + 0, 3196, 3444, + 0, 3200, 3440, + 0, 3205, 3435, + 0, 3212, 3428, + 0, 3221, 3419, + 0, 3233, 3406, + 0, 3248, 3389, + 0, 3268, 3364, + 0, 3293, 3329, + 0, 3324, 3278, + 0, 3363, 3198, + 0, 3411, 3064, + 0, 3467, 2783, + 0, 3533, 0, + 0, 3609, 0, + 0, 3693, 0, + 0, 3786, 0, + 0, 3185, 3455, + 0, 3185, 3455, + 0, 3185, 3455, + 0, 3185, 3455, + 0, 3185, 3455, + 0, 3185, 3455, + 0, 3185, 3454, + 0, 3186, 3454, + 0, 3186, 3454, + 0, 3187, 3453, + 0, 3187, 3453, + 0, 3188, 3452, + 0, 3190, 3451, + 0, 3191, 3449, + 0, 3193, 3447, + 0, 3196, 3444, + 0, 3200, 3441, + 0, 3205, 3436, + 0, 3212, 3429, + 0, 3221, 3420, + 0, 3233, 3407, + 0, 3248, 3389, + 0, 3268, 3365, + 0, 3293, 3330, + 0, 3324, 3278, + 0, 3363, 3199, + 0, 3411, 3065, + 0, 3467, 2785, + 0, 3533, 0, + 0, 3609, 0, + 0, 3693, 0, + 0, 3786, 0, + 0, 3185, 3456, + 0, 3185, 3456, + 0, 3185, 3455, + 0, 3185, 3455, + 0, 3185, 3455, + 0, 3185, 3455, + 0, 3186, 3455, + 0, 3186, 3455, + 0, 3186, 3454, + 0, 3187, 3454, + 0, 3187, 3453, + 0, 3188, 3452, + 0, 3190, 3451, + 0, 3191, 3450, + 0, 3194, 3448, + 0, 3197, 3445, + 0, 3200, 3441, + 0, 3206, 3436, + 0, 3212, 3429, + 0, 3221, 3420, + 0, 3233, 3407, + 0, 3248, 3390, + 0, 3268, 3365, + 0, 3293, 3331, + 0, 3325, 3279, + 0, 3363, 3200, + 0, 3411, 3066, + 0, 3467, 2787, + 0, 3533, 0, + 0, 3609, 0, + 0, 3693, 0, + 0, 3786, 0, + 0, 3185, 3456, + 0, 3185, 3456, + 0, 3185, 3456, + 0, 3185, 3456, + 0, 3185, 3456, + 0, 3186, 3456, + 0, 3186, 3456, + 0, 3186, 3455, + 0, 3186, 3455, + 0, 3187, 3455, + 0, 3188, 3454, + 0, 3189, 3453, + 0, 3190, 3452, + 0, 3192, 3450, + 0, 3194, 3448, + 0, 3197, 3446, + 0, 3201, 3442, + 0, 3206, 3437, + 0, 3213, 3430, + 0, 3222, 3421, + 0, 3233, 3408, + 0, 3249, 3391, + 0, 3268, 3366, + 0, 3293, 3331, + 0, 3325, 3280, + 0, 3364, 3201, + 0, 3411, 3067, + 0, 3467, 2790, + 0, 3533, 0, + 0, 3609, 0, + 0, 3693, 0, + 0, 3786, 0, + 0, 3185, 3457, + 0, 3185, 3457, + 0, 3185, 3457, + 0, 3185, 3457, + 0, 3186, 3457, + 0, 3186, 3457, + 0, 3186, 3457, + 0, 3186, 3456, + 0, 3187, 3456, + 0, 3187, 3456, + 0, 3188, 3455, + 0, 3189, 3454, + 0, 3190, 3453, + 0, 3192, 3451, + 0, 3194, 3449, + 0, 3197, 3447, + 0, 3201, 3443, + 0, 3206, 3438, + 0, 3213, 3431, + 0, 3222, 3422, + 0, 3234, 3409, + 0, 3249, 3392, + 0, 3268, 3368, + 0, 3293, 3333, + 0, 3325, 3282, + 0, 3364, 3203, + 0, 3411, 3070, + 0, 3467, 2794, + 0, 3533, 0, + 0, 3609, 0, + 0, 3693, 0, + 0, 3786, 0, + 0, 3186, 3459, + 0, 3186, 3458, + 0, 3186, 3458, + 0, 3186, 3458, + 0, 3186, 3458, + 0, 3186, 3458, + 0, 3186, 3458, + 0, 3187, 3458, + 0, 3187, 3457, + 0, 3188, 3457, + 0, 3188, 3456, + 0, 3189, 3455, + 0, 3190, 3454, + 0, 3192, 3453, + 0, 3194, 3451, + 0, 3197, 3448, + 0, 3201, 3444, + 0, 3206, 3439, + 0, 3213, 3432, + 0, 3222, 3423, + 0, 3234, 3411, + 0, 3249, 3393, + 0, 3269, 3369, + 0, 3294, 3334, + 0, 3325, 3283, + 0, 3364, 3205, + 0, 3411, 3073, + 0, 3468, 2800, + 0, 3533, 0, + 0, 3609, 0, + 0, 3693, 0, + 0, 3786, 0, + 0, 3186, 3460, + 0, 3186, 3460, + 0, 3186, 3460, + 0, 3186, 3460, + 0, 3186, 3460, + 0, 3187, 3460, + 0, 3187, 3460, + 0, 3187, 3459, + 0, 3187, 3459, + 0, 3188, 3458, + 0, 3189, 3458, + 0, 3190, 3457, + 0, 3191, 3456, + 0, 3193, 3454, + 0, 3195, 3452, + 0, 3198, 3450, + 0, 3202, 3446, + 0, 3207, 3441, + 0, 3214, 3434, + 0, 3223, 3425, + 0, 3234, 3413, + 0, 3250, 3395, + 0, 3269, 3371, + 0, 3294, 3337, + 0, 3325, 3286, + 0, 3364, 3208, + 0, 3411, 3077, + 0, 3468, 2807, + 0, 3534, 0, + 0, 3609, 0, + 0, 3694, 0, + 0, 3787, 0, + 0, 3187, 3462, + 0, 3187, 3462, + 0, 3187, 3462, + 0, 3187, 3462, + 0, 3187, 3462, + 0, 3187, 3462, + 0, 3187, 3462, + 0, 3188, 3462, + 0, 3188, 3461, + 0, 3189, 3461, + 0, 3189, 3460, + 0, 3190, 3459, + 0, 3191, 3458, + 0, 3193, 3457, + 0, 3195, 3455, + 0, 3198, 3452, + 0, 3202, 3448, + 0, 3207, 3443, + 0, 3214, 3437, + 0, 3223, 3428, + 0, 3235, 3415, + 0, 3250, 3398, + 0, 3270, 3374, + 0, 3295, 3339, + 0, 3326, 3289, + 0, 3365, 3212, + 0, 3412, 3082, + 0, 3468, 2816, + 0, 3534, 0, + 0, 3609, 0, + 0, 3694, 0, + 0, 3787, 0, + 0, 3187, 3465, + 0, 3187, 3465, + 0, 3187, 3465, + 0, 3188, 3465, + 0, 3188, 3465, + 0, 3188, 3465, + 0, 3188, 3465, + 0, 3188, 3465, + 0, 3189, 3464, + 0, 3189, 3464, + 0, 3190, 3463, + 0, 3191, 3462, + 0, 3192, 3461, + 0, 3194, 3460, + 0, 3196, 3458, + 0, 3199, 3455, + 0, 3203, 3451, + 0, 3208, 3446, + 0, 3215, 3440, + 0, 3224, 3431, + 0, 3235, 3418, + 0, 3251, 3401, + 0, 3270, 3377, + 0, 3295, 3343, + 0, 3326, 3293, + 0, 3365, 3217, + 0, 3412, 3089, + 0, 3469, 2829, + 0, 3534, 0, + 0, 3610, 0, + 0, 3694, 0, + 0, 3787, 0, + 0, 3188, 3469, + 0, 3188, 3469, + 0, 3188, 3469, + 0, 3189, 3469, + 0, 3189, 3469, + 0, 3189, 3469, + 0, 3189, 3469, + 0, 3189, 3468, + 0, 3190, 3468, + 0, 3190, 3468, + 0, 3191, 3467, + 0, 3192, 3466, + 0, 3193, 3465, + 0, 3195, 3464, + 0, 3197, 3462, + 0, 3200, 3459, + 0, 3204, 3455, + 0, 3209, 3451, + 0, 3216, 3444, + 0, 3225, 3435, + 0, 3236, 3423, + 0, 3252, 3406, + 0, 3271, 3382, + 0, 3296, 3349, + 0, 3327, 3299, + 0, 3366, 3224, + 0, 3413, 3098, + 0, 3469, 2844, + 0, 3535, 106, + 0, 3610, 0, + 0, 3694, 0, + 0, 3787, 0, + 0, 3190, 3475, + 0, 3190, 3475, + 0, 3190, 3474, + 0, 3190, 3474, + 0, 3190, 3474, + 0, 3190, 3474, + 0, 3190, 3474, + 0, 3191, 3474, + 0, 3191, 3473, + 0, 3192, 3473, + 0, 3192, 3472, + 0, 3193, 3471, + 0, 3195, 3470, + 0, 3196, 3469, + 0, 3198, 3467, + 0, 3201, 3464, + 0, 3205, 3461, + 0, 3210, 3456, + 0, 3217, 3449, + 0, 3226, 3441, + 0, 3238, 3429, + 0, 3253, 3412, + 0, 3272, 3389, + 0, 3297, 3355, + 0, 3328, 3307, + 0, 3367, 3233, + 0, 3414, 3109, + 0, 3470, 2865, + 0, 3535, 1466, + 0, 3611, 0, + 0, 3695, 0, + 0, 3788, 0, + 0, 3192, 3481, + 0, 3192, 3481, + 0, 3192, 3481, + 0, 3192, 3481, + 0, 3192, 3481, + 0, 3192, 3481, + 0, 3192, 3481, + 0, 3193, 3481, + 0, 3193, 3480, + 0, 3193, 3480, + 0, 3194, 3479, + 0, 3195, 3478, + 0, 3196, 3477, + 0, 3198, 3476, + 0, 3200, 3474, + 0, 3203, 3471, + 0, 3207, 3468, + 0, 3212, 3463, + 0, 3219, 3457, + 0, 3228, 3448, + 0, 3239, 3436, + 0, 3254, 3420, + 0, 3274, 3397, + 0, 3298, 3364, + 0, 3329, 3317, + 0, 3368, 3244, + 0, 3415, 3125, + 0, 3471, 2891, + 0, 3536, 1839, + 0, 3611, 0, + 0, 3695, 0, + 0, 3788, 0, + 0, 3194, 3491, + 0, 3194, 3491, + 0, 3194, 3490, + 0, 3194, 3490, + 0, 3194, 3490, + 0, 3194, 3490, + 0, 3195, 3490, + 0, 3195, 3490, + 0, 3195, 3489, + 0, 3196, 3489, + 0, 3197, 3488, + 0, 3197, 3488, + 0, 3199, 3487, + 0, 3200, 3485, + 0, 3202, 3483, + 0, 3205, 3481, + 0, 3209, 3477, + 0, 3214, 3473, + 0, 3221, 3466, + 0, 3230, 3458, + 0, 3241, 3446, + 0, 3256, 3430, + 0, 3276, 3408, + 0, 3300, 3376, + 0, 3331, 3330, + 0, 3370, 3259, + 0, 3416, 3144, + 0, 3472, 2923, + 0, 3537, 2093, + 0, 3612, 0, + 0, 3696, 0, + 0, 3789, 0, + 0, 3197, 3502, + 0, 3197, 3502, + 0, 3197, 3502, + 0, 3197, 3502, + 0, 3197, 3502, + 0, 3198, 3502, + 0, 3198, 3502, + 0, 3198, 3502, + 0, 3199, 3501, + 0, 3199, 3501, + 0, 3200, 3500, + 0, 3201, 3500, + 0, 3202, 3498, + 0, 3203, 3497, + 0, 3206, 3495, + 0, 3209, 3493, + 0, 3212, 3489, + 0, 3217, 3485, + 0, 3224, 3479, + 0, 3233, 3471, + 0, 3244, 3459, + 0, 3259, 3444, + 0, 3278, 3422, + 0, 3303, 3391, + 0, 3334, 3347, + 0, 3372, 3279, + 0, 3418, 3169, + 0, 3474, 2963, + 0, 3539, 2299, + 0, 3613, 0, + 0, 3697, 0, + 0, 3790, 0, + 0, 3201, 3518, + 0, 3201, 3518, + 0, 3202, 3518, + 0, 3202, 3518, + 0, 3202, 3518, + 0, 3202, 3517, + 0, 3202, 3517, + 0, 3202, 3517, + 0, 3203, 3517, + 0, 3203, 3516, + 0, 3204, 3516, + 0, 3205, 3515, + 0, 3206, 3514, + 0, 3208, 3513, + 0, 3210, 3511, + 0, 3213, 3508, + 0, 3216, 3505, + 0, 3221, 3501, + 0, 3228, 3495, + 0, 3237, 3487, + 0, 3248, 3476, + 0, 3263, 3461, + 0, 3282, 3440, + 0, 3306, 3411, + 0, 3337, 3368, + 0, 3375, 3304, + 0, 3421, 3201, + 0, 3476, 3012, + 0, 3541, 2479, + 0, 3615, 0, + 0, 3699, 0, + 0, 3791, 0, + 0, 3207, 3538, + 0, 3207, 3538, + 0, 3207, 3537, + 0, 3207, 3537, + 0, 3207, 3537, + 0, 3207, 3537, + 0, 3208, 3537, + 0, 3208, 3537, + 0, 3208, 3537, + 0, 3209, 3536, + 0, 3210, 3536, + 0, 3210, 3535, + 0, 3212, 3534, + 0, 3213, 3533, + 0, 3215, 3531, + 0, 3218, 3529, + 0, 3222, 3526, + 0, 3227, 3521, + 0, 3233, 3516, + 0, 3242, 3508, + 0, 3253, 3498, + 0, 3268, 3483, + 0, 3287, 3464, + 0, 3311, 3436, + 0, 3341, 3395, + 0, 3379, 3335, + 0, 3424, 3240, + 0, 3479, 3069, + 0, 3544, 2644, + 0, 3617, 0, + 0, 3701, 0, + 0, 3792, 0, + 1728, 3214, 3563, + 1725, 3214, 3563, + 1722, 3215, 3563, + 1717, 3215, 3563, + 1710, 3215, 3563, + 1701, 3215, 3562, + 1688, 3215, 3562, + 1671, 3215, 3562, + 1647, 3216, 3562, + 1612, 3216, 3561, + 1562, 3217, 3561, + 1483, 3218, 3560, + 1352, 3219, 3559, + 1082, 3220, 3558, + 0, 3223, 3557, + 0, 3225, 3554, + 0, 3229, 3551, + 0, 3234, 3548, + 0, 3240, 3542, + 0, 3249, 3535, + 0, 3260, 3525, + 0, 3274, 3512, + 0, 3293, 3493, + 0, 3317, 3467, + 0, 3346, 3429, + 0, 3384, 3374, + 0, 3429, 3287, + 0, 3483, 3137, + 0, 3547, 2799, + 0, 3620, 0, + 0, 3703, 0, + 0, 3794, 0, + 2722, 3224, 3594, + 2721, 3224, 3594, + 2721, 3224, 3594, + 2720, 3224, 3594, + 2720, 3224, 3594, + 2719, 3225, 3594, + 2717, 3225, 3594, + 2716, 3225, 3594, + 2713, 3225, 3593, + 2710, 3226, 3593, + 2706, 3227, 3593, + 2700, 3227, 3592, + 2692, 3229, 3591, + 2681, 3230, 3590, + 2666, 3232, 3589, + 2646, 3235, 3587, + 2617, 3238, 3584, + 2574, 3243, 3580, + 2511, 3250, 3575, + 2410, 3258, 3569, + 2224, 3269, 3559, + 1718, 3283, 3547, + 0, 3301, 3530, + 0, 3324, 3506, + 0, 3354, 3471, + 0, 3390, 3421, + 0, 3435, 3343, + 0, 3489, 3214, + 0, 3552, 2948, + 0, 3624, 0, + 0, 3706, 0, + 0, 3797, 0, + 3077, 3237, 3634, + 3077, 3237, 3634, + 3077, 3237, 3633, + 3077, 3237, 3633, + 3076, 3237, 3633, + 3076, 3237, 3633, + 3075, 3237, 3633, + 3075, 3238, 3633, + 3073, 3238, 3633, + 3072, 3239, 3632, + 3070, 3239, 3632, + 3068, 3240, 3631, + 3064, 3241, 3631, + 3059, 3243, 3630, + 3053, 3245, 3628, + 3044, 3247, 3626, + 3032, 3251, 3624, + 3016, 3255, 3621, + 2993, 3262, 3616, + 2960, 3270, 3610, + 2913, 3280, 3602, + 2840, 3294, 3590, + 2720, 3312, 3575, + 2485, 3335, 3553, + 1404, 3363, 3522, + 0, 3399, 3477, + 0, 3443, 3409, + 0, 3496, 3299, + 0, 3558, 3092, + 0, 3630, 2417, + 0, 3711, 0, + 0, 3801, 0, + 3325, 3253, 3681, + 3325, 3253, 3681, + 3325, 3253, 3681, + 3325, 3253, 3681, + 3325, 3254, 3681, + 3325, 3254, 3681, + 3324, 3254, 3681, + 3324, 3254, 3681, + 3323, 3254, 3680, + 3322, 3255, 3680, + 3321, 3255, 3680, + 3320, 3256, 3679, + 3318, 3257, 3678, + 3315, 3259, 3678, + 3311, 3261, 3676, + 3306, 3263, 3675, + 3300, 3267, 3672, + 3291, 3271, 3669, + 3278, 3277, 3665, + 3261, 3285, 3660, + 3237, 3295, 3652, + 3203, 3308, 3642, + 3153, 3326, 3628, + 3076, 3348, 3609, + 2947, 3376, 3582, + 2685, 3411, 3543, + 0, 3454, 3485, + 0, 3505, 3394, + 0, 3566, 3233, + 0, 3637, 2852, + 0, 3717, 0, + 0, 3805, 0, + 3528, 3274, 3738, + 3528, 3274, 3738, + 3528, 3274, 3738, + 3528, 3274, 3738, + 3528, 3275, 3738, + 3528, 3275, 3738, + 3527, 3275, 3737, + 3527, 3275, 3737, + 3527, 3275, 3737, + 3526, 3276, 3737, + 3525, 3276, 3737, + 3525, 3277, 3736, + 3523, 3278, 3735, + 3522, 3280, 3735, + 3519, 3281, 3734, + 3516, 3284, 3732, + 3512, 3287, 3730, + 3506, 3291, 3728, + 3499, 3297, 3724, + 3488, 3305, 3719, + 3474, 3314, 3713, + 3454, 3327, 3704, + 3426, 3344, 3692, + 3385, 3365, 3675, + 3324, 3392, 3652, + 3228, 3426, 3618, + 3055, 3467, 3570, + 2618, 3517, 3495, + 0, 3577, 3371, + 0, 3646, 3125, + 0, 3724, 1639, + 0, 3812, 0, + 3707, 3301, 3804, + 3707, 3301, 3804, + 3707, 3301, 3804, + 3707, 3301, 3804, + 3707, 3301, 3804, + 3706, 3301, 3804, + 3706, 3302, 3804, + 3706, 3302, 3804, + 3706, 3302, 3803, + 3705, 3303, 3803, + 3705, 3303, 3803, + 3704, 3304, 3803, + 3703, 3305, 3802, + 3702, 3306, 3801, + 3701, 3308, 3800, + 3699, 3310, 3799, + 3696, 3313, 3797, + 3692, 3317, 3795, + 3687, 3323, 3792, + 3680, 3330, 3788, + 3671, 3339, 3782, + 3658, 3351, 3775, + 3640, 3367, 3764, + 3615, 3387, 3750, + 3580, 3413, 3730, + 3527, 3445, 3703, + 3446, 3485, 3663, + 3308, 3533, 3603, + 3017, 3591, 3508, + 0, 3658, 3340, + 0, 3734, 2924, + 0, 3820, 0, + 3871, 3334, 3880, + 3871, 3334, 3880, + 3871, 3335, 3880, + 3871, 3335, 3880, + 3871, 3335, 3880, + 3871, 3335, 3880, + 3870, 3335, 3880, + 3870, 3335, 3879, + 3870, 3335, 3879, + 3870, 3336, 3879, + 3869, 3336, 3879, + 3869, 3337, 3879, + 3868, 3338, 3878, + 3868, 3339, 3878, + 3867, 3341, 3877, + 3865, 3343, 3876, + 3863, 3346, 3874, + 3861, 3349, 3872, + 3857, 3354, 3870, + 3852, 3361, 3866, + 3846, 3370, 3862, + 3837, 3381, 3855, + 3825, 3396, 3846, + 3809, 3415, 3835, + 3786, 3439, 3818, + 3753, 3470, 3796, + 3706, 3507, 3763, + 3633, 3554, 3716, + 3513, 3609, 3644, + 3279, 3673, 3525, + 2216, 3748, 3294, + 0, 3831, 2303, + 4025, 3376, 3965, + 4025, 3376, 3965, + 4025, 3376, 3965, + 4025, 3376, 3965, + 4025, 3376, 3965, + 4025, 3376, 3965, + 4025, 3376, 3964, + 4025, 3376, 3964, + 4025, 3377, 3964, + 4025, 3377, 3964, + 4024, 3377, 3964, + 4024, 3378, 3964, + 4024, 3379, 3963, + 4023, 3380, 3963, + 4022, 3381, 3962, + 4021, 3383, 3961, + 4020, 3386, 3960, + 4018, 3389, 3958, + 4016, 3394, 3956, + 4012, 3400, 3953, + 4008, 3408, 3950, + 4002, 3418, 3944, + 3993, 3432, 3937, + 3982, 3450, 3928, + 3967, 3472, 3914, + 3945, 3501, 3896, + 3914, 3536, 3870, + 3870, 3579, 3833, + 3803, 3632, 3779, + 3693, 3693, 3693, + 3489, 3765, 3547, + 2837, 3845, 3224, + 4095, 3425, 4058, + 4095, 3426, 4058, + 4095, 3426, 4058, + 4095, 3426, 4058, + 4095, 3426, 4058, + 4095, 3426, 4058, + 4095, 3426, 4058, + 4095, 3426, 4058, + 4095, 3426, 4058, + 4095, 3427, 4057, + 4095, 3427, 4057, + 4095, 3428, 4057, + 4095, 3428, 4057, + 4095, 3429, 4056, + 4095, 3431, 4056, + 4095, 3432, 4055, + 4095, 3435, 4054, + 4095, 3438, 4053, + 4095, 3442, 4051, + 4095, 3447, 4049, + 4095, 3455, 4046, + 4095, 3464, 4041, + 4095, 3476, 4036, + 4095, 3492, 4028, + 4095, 3513, 4017, + 4095, 3539, 4003, + 4095, 3572, 3982, + 4067, 3612, 3954, + 4024, 3661, 3913, + 3961, 3719, 3851, + 3858, 3787, 3752, + 3671, 3864, 3575, + 4095, 3485, 4095, + 4095, 3485, 4095, + 4095, 3485, 4095, + 4095, 3485, 4095, + 4095, 3485, 4095, + 4095, 3485, 4095, + 4095, 3485, 4095, + 4095, 3485, 4095, + 4095, 3485, 4095, + 4095, 3486, 4095, + 4095, 3486, 4095, + 4095, 3486, 4095, + 4095, 3487, 4095, + 4095, 3488, 4095, + 4095, 3489, 4095, + 4095, 3491, 4095, + 4095, 3493, 4095, + 4095, 3495, 4095, + 4095, 3499, 4095, + 4095, 3504, 4095, + 4095, 3510, 4095, + 4095, 3519, 4095, + 4095, 3530, 4095, + 4095, 3544, 4095, + 4095, 3562, 4095, + 4095, 3586, 4095, + 4095, 3615, 4095, + 4095, 3652, 4077, + 4095, 3697, 4046, + 4095, 3751, 4001, + 4095, 3814, 3932, + 4014, 3887, 3821, + 0, 3316, 3586, + 0, 3316, 3586, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3317, 3585, + 0, 3317, 3585, + 0, 3317, 3585, + 0, 3317, 3585, + 0, 3318, 3584, + 0, 3318, 3584, + 0, 3319, 3583, + 0, 3320, 3582, + 0, 3321, 3581, + 0, 3323, 3580, + 0, 3325, 3578, + 0, 3328, 3575, + 0, 3332, 3571, + 0, 3337, 3566, + 0, 3344, 3559, + 0, 3353, 3550, + 0, 3365, 3537, + 0, 3380, 3520, + 0, 3400, 3495, + 0, 3425, 3460, + 0, 3456, 3408, + 0, 3495, 3328, + 0, 3543, 3193, + 0, 3599, 2911, + 0, 3665, 0, + 0, 3740, 0, + 0, 3825, 0, + 0, 3316, 3586, + 0, 3316, 3586, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3317, 3585, + 0, 3317, 3585, + 0, 3317, 3585, + 0, 3317, 3585, + 0, 3318, 3585, + 0, 3318, 3584, + 0, 3319, 3583, + 0, 3320, 3583, + 0, 3321, 3581, + 0, 3323, 3580, + 0, 3325, 3578, + 0, 3328, 3575, + 0, 3332, 3571, + 0, 3337, 3566, + 0, 3344, 3559, + 0, 3353, 3550, + 0, 3365, 3537, + 0, 3380, 3520, + 0, 3400, 3495, + 0, 3425, 3460, + 0, 3456, 3408, + 0, 3495, 3328, + 0, 3543, 3193, + 0, 3599, 2911, + 0, 3665, 0, + 0, 3741, 0, + 0, 3825, 0, + 0, 3316, 3586, + 0, 3316, 3586, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3317, 3585, + 0, 3317, 3585, + 0, 3318, 3585, + 0, 3318, 3585, + 0, 3318, 3584, + 0, 3319, 3583, + 0, 3320, 3583, + 0, 3321, 3581, + 0, 3323, 3580, + 0, 3325, 3578, + 0, 3328, 3575, + 0, 3332, 3571, + 0, 3337, 3566, + 0, 3344, 3560, + 0, 3353, 3550, + 0, 3365, 3538, + 0, 3380, 3520, + 0, 3400, 3495, + 0, 3425, 3460, + 0, 3456, 3408, + 0, 3495, 3329, + 0, 3543, 3194, + 0, 3599, 2911, + 0, 3665, 0, + 0, 3741, 0, + 0, 3825, 0, + 0, 3316, 3586, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3317, 3585, + 0, 3317, 3585, + 0, 3318, 3585, + 0, 3318, 3585, + 0, 3318, 3584, + 0, 3319, 3584, + 0, 3320, 3583, + 0, 3321, 3582, + 0, 3323, 3580, + 0, 3325, 3578, + 0, 3328, 3575, + 0, 3332, 3571, + 0, 3337, 3566, + 0, 3344, 3560, + 0, 3353, 3550, + 0, 3365, 3538, + 0, 3380, 3520, + 0, 3400, 3495, + 0, 3425, 3460, + 0, 3456, 3409, + 0, 3495, 3329, + 0, 3543, 3194, + 0, 3599, 2912, + 0, 3665, 0, + 0, 3741, 0, + 0, 3825, 0, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3317, 3585, + 0, 3318, 3585, + 0, 3318, 3585, + 0, 3318, 3584, + 0, 3319, 3584, + 0, 3320, 3583, + 0, 3321, 3582, + 0, 3323, 3580, + 0, 3325, 3578, + 0, 3328, 3575, + 0, 3332, 3572, + 0, 3337, 3567, + 0, 3344, 3560, + 0, 3353, 3551, + 0, 3365, 3538, + 0, 3380, 3520, + 0, 3400, 3496, + 0, 3425, 3460, + 0, 3456, 3409, + 0, 3495, 3329, + 0, 3543, 3194, + 0, 3599, 2912, + 0, 3665, 0, + 0, 3741, 0, + 0, 3825, 0, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3318, 3585, + 0, 3318, 3585, + 0, 3319, 3584, + 0, 3319, 3584, + 0, 3320, 3583, + 0, 3321, 3582, + 0, 3323, 3580, + 0, 3325, 3578, + 0, 3328, 3576, + 0, 3332, 3572, + 0, 3337, 3567, + 0, 3344, 3560, + 0, 3353, 3551, + 0, 3365, 3538, + 0, 3380, 3520, + 0, 3400, 3496, + 0, 3425, 3461, + 0, 3456, 3409, + 0, 3495, 3329, + 0, 3543, 3194, + 0, 3599, 2913, + 0, 3665, 0, + 0, 3741, 0, + 0, 3825, 0, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3318, 3586, + 0, 3318, 3585, + 0, 3319, 3585, + 0, 3319, 3584, + 0, 3320, 3583, + 0, 3321, 3582, + 0, 3323, 3581, + 0, 3325, 3579, + 0, 3328, 3576, + 0, 3332, 3572, + 0, 3337, 3567, + 0, 3344, 3560, + 0, 3353, 3551, + 0, 3365, 3538, + 0, 3380, 3521, + 0, 3400, 3496, + 0, 3425, 3461, + 0, 3456, 3409, + 0, 3495, 3330, + 0, 3543, 3195, + 0, 3599, 2914, + 0, 3665, 0, + 0, 3741, 0, + 0, 3825, 0, + 0, 3317, 3587, + 0, 3317, 3587, + 0, 3317, 3587, + 0, 3317, 3587, + 0, 3317, 3587, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3317, 3586, + 0, 3318, 3586, + 0, 3318, 3585, + 0, 3319, 3585, + 0, 3319, 3584, + 0, 3320, 3584, + 0, 3322, 3582, + 0, 3323, 3581, + 0, 3325, 3579, + 0, 3328, 3576, + 0, 3332, 3572, + 0, 3338, 3567, + 0, 3344, 3561, + 0, 3353, 3551, + 0, 3365, 3539, + 0, 3380, 3521, + 0, 3400, 3496, + 0, 3425, 3461, + 0, 3456, 3410, + 0, 3495, 3330, + 0, 3543, 3196, + 0, 3599, 2915, + 0, 3665, 0, + 0, 3741, 0, + 0, 3825, 0, + 0, 3317, 3587, + 0, 3317, 3587, + 0, 3317, 3587, + 0, 3317, 3587, + 0, 3317, 3587, + 0, 3317, 3587, + 0, 3317, 3587, + 0, 3318, 3587, + 0, 3318, 3586, + 0, 3318, 3586, + 0, 3319, 3585, + 0, 3319, 3585, + 0, 3320, 3584, + 0, 3322, 3583, + 0, 3323, 3581, + 0, 3326, 3579, + 0, 3328, 3576, + 0, 3332, 3573, + 0, 3338, 3568, + 0, 3344, 3561, + 0, 3353, 3552, + 0, 3365, 3539, + 0, 3380, 3521, + 0, 3400, 3497, + 0, 3425, 3462, + 0, 3457, 3410, + 0, 3495, 3331, + 0, 3543, 3197, + 0, 3599, 2917, + 0, 3665, 0, + 0, 3741, 0, + 0, 3825, 0, + 0, 3317, 3588, + 0, 3317, 3588, + 0, 3317, 3588, + 0, 3317, 3588, + 0, 3317, 3587, + 0, 3317, 3587, + 0, 3317, 3587, + 0, 3318, 3587, + 0, 3318, 3587, + 0, 3318, 3586, + 0, 3319, 3586, + 0, 3320, 3585, + 0, 3321, 3584, + 0, 3322, 3583, + 0, 3323, 3582, + 0, 3326, 3580, + 0, 3329, 3577, + 0, 3333, 3573, + 0, 3338, 3568, + 0, 3345, 3561, + 0, 3354, 3552, + 0, 3365, 3540, + 0, 3381, 3522, + 0, 3400, 3498, + 0, 3425, 3463, + 0, 3457, 3411, + 0, 3496, 3332, + 0, 3543, 3198, + 0, 3599, 2919, + 0, 3665, 0, + 0, 3741, 0, + 0, 3825, 0, + 0, 3317, 3588, + 0, 3317, 3588, + 0, 3317, 3588, + 0, 3317, 3588, + 0, 3317, 3588, + 0, 3317, 3588, + 0, 3318, 3588, + 0, 3318, 3588, + 0, 3318, 3587, + 0, 3319, 3587, + 0, 3319, 3587, + 0, 3320, 3586, + 0, 3321, 3585, + 0, 3322, 3584, + 0, 3324, 3583, + 0, 3326, 3580, + 0, 3329, 3578, + 0, 3333, 3574, + 0, 3338, 3569, + 0, 3345, 3562, + 0, 3354, 3553, + 0, 3365, 3540, + 0, 3381, 3523, + 0, 3400, 3498, + 0, 3425, 3464, + 0, 3457, 3412, + 0, 3496, 3333, + 0, 3543, 3200, + 0, 3599, 2922, + 0, 3665, 0, + 0, 3741, 0, + 0, 3825, 0, + 0, 3317, 3589, + 0, 3317, 3589, + 0, 3317, 3589, + 0, 3317, 3589, + 0, 3318, 3589, + 0, 3318, 3589, + 0, 3318, 3589, + 0, 3318, 3589, + 0, 3318, 3588, + 0, 3319, 3588, + 0, 3319, 3588, + 0, 3320, 3587, + 0, 3321, 3586, + 0, 3322, 3585, + 0, 3324, 3583, + 0, 3326, 3581, + 0, 3329, 3579, + 0, 3333, 3575, + 0, 3338, 3570, + 0, 3345, 3563, + 0, 3354, 3554, + 0, 3366, 3541, + 0, 3381, 3524, + 0, 3401, 3500, + 0, 3426, 3465, + 0, 3457, 3414, + 0, 3496, 3335, + 0, 3543, 3202, + 0, 3600, 2927, + 0, 3665, 0, + 0, 3741, 0, + 0, 3825, 0, + 0, 3318, 3591, + 0, 3318, 3591, + 0, 3318, 3591, + 0, 3318, 3590, + 0, 3318, 3590, + 0, 3318, 3590, + 0, 3318, 3590, + 0, 3318, 3590, + 0, 3319, 3590, + 0, 3319, 3589, + 0, 3320, 3589, + 0, 3320, 3588, + 0, 3321, 3587, + 0, 3323, 3586, + 0, 3324, 3585, + 0, 3326, 3583, + 0, 3329, 3580, + 0, 3333, 3576, + 0, 3338, 3571, + 0, 3345, 3565, + 0, 3354, 3555, + 0, 3366, 3543, + 0, 3381, 3525, + 0, 3401, 3501, + 0, 3426, 3466, + 0, 3457, 3415, + 0, 3496, 3337, + 0, 3543, 3205, + 0, 3600, 2932, + 0, 3666, 0, + 0, 3741, 0, + 0, 3826, 0, + 0, 3318, 3592, + 0, 3318, 3592, + 0, 3318, 3592, + 0, 3318, 3592, + 0, 3318, 3592, + 0, 3318, 3592, + 0, 3319, 3592, + 0, 3319, 3592, + 0, 3319, 3591, + 0, 3320, 3591, + 0, 3320, 3591, + 0, 3321, 3590, + 0, 3322, 3589, + 0, 3323, 3588, + 0, 3325, 3586, + 0, 3327, 3584, + 0, 3330, 3582, + 0, 3334, 3578, + 0, 3339, 3573, + 0, 3346, 3566, + 0, 3355, 3557, + 0, 3366, 3545, + 0, 3382, 3527, + 0, 3401, 3503, + 0, 3426, 3469, + 0, 3458, 3418, + 0, 3496, 3340, + 0, 3544, 3209, + 0, 3600, 2939, + 0, 3666, 0, + 0, 3741, 0, + 0, 3826, 0, + 0, 3319, 3595, + 0, 3319, 3595, + 0, 3319, 3594, + 0, 3319, 3594, + 0, 3319, 3594, + 0, 3319, 3594, + 0, 3319, 3594, + 0, 3319, 3594, + 0, 3320, 3594, + 0, 3320, 3593, + 0, 3321, 3593, + 0, 3321, 3592, + 0, 3322, 3591, + 0, 3324, 3590, + 0, 3325, 3589, + 0, 3327, 3587, + 0, 3330, 3584, + 0, 3334, 3580, + 0, 3339, 3575, + 0, 3346, 3569, + 0, 3355, 3560, + 0, 3367, 3547, + 0, 3382, 3530, + 0, 3402, 3506, + 0, 3427, 3472, + 0, 3458, 3421, + 0, 3497, 3344, + 0, 3544, 3214, + 0, 3600, 2948, + 0, 3666, 0, + 0, 3741, 0, + 0, 3826, 0, + 0, 3319, 3598, + 0, 3319, 3597, + 0, 3320, 3597, + 0, 3320, 3597, + 0, 3320, 3597, + 0, 3320, 3597, + 0, 3320, 3597, + 0, 3320, 3597, + 0, 3320, 3597, + 0, 3321, 3596, + 0, 3321, 3596, + 0, 3322, 3595, + 0, 3323, 3594, + 0, 3324, 3593, + 0, 3326, 3592, + 0, 3328, 3590, + 0, 3331, 3587, + 0, 3335, 3583, + 0, 3340, 3579, + 0, 3347, 3572, + 0, 3356, 3563, + 0, 3368, 3550, + 0, 3383, 3533, + 0, 3402, 3510, + 0, 3427, 3475, + 0, 3459, 3426, + 0, 3497, 3349, + 0, 3544, 3221, + 0, 3601, 2961, + 0, 3666, 0, + 0, 3742, 0, + 0, 3826, 0, + 0, 3320, 3601, + 0, 3320, 3601, + 0, 3321, 3601, + 0, 3321, 3601, + 0, 3321, 3601, + 0, 3321, 3601, + 0, 3321, 3601, + 0, 3321, 3601, + 0, 3321, 3601, + 0, 3322, 3600, + 0, 3322, 3600, + 0, 3323, 3599, + 0, 3324, 3598, + 0, 3325, 3597, + 0, 3327, 3596, + 0, 3329, 3594, + 0, 3332, 3591, + 0, 3336, 3587, + 0, 3341, 3583, + 0, 3348, 3576, + 0, 3357, 3567, + 0, 3368, 3555, + 0, 3384, 3538, + 0, 3403, 3514, + 0, 3428, 3481, + 0, 3459, 3431, + 0, 3498, 3356, + 0, 3545, 3230, + 0, 3601, 2976, + 0, 3667, 238, + 0, 3742, 0, + 0, 3826, 0, + 0, 3322, 3607, + 0, 3322, 3607, + 0, 3322, 3607, + 0, 3322, 3607, + 0, 3322, 3606, + 0, 3322, 3606, + 0, 3322, 3606, + 0, 3323, 3606, + 0, 3323, 3606, + 0, 3323, 3605, + 0, 3324, 3605, + 0, 3324, 3604, + 0, 3325, 3604, + 0, 3327, 3603, + 0, 3328, 3601, + 0, 3330, 3599, + 0, 3333, 3596, + 0, 3337, 3593, + 0, 3342, 3588, + 0, 3349, 3582, + 0, 3358, 3573, + 0, 3370, 3561, + 0, 3385, 3544, + 0, 3404, 3521, + 0, 3429, 3487, + 0, 3460, 3439, + 0, 3499, 3365, + 0, 3546, 3241, + 0, 3602, 2997, + 0, 3668, 1599, + 0, 3743, 0, + 0, 3827, 0, + 0, 3324, 3614, + 0, 3324, 3614, + 0, 3324, 3614, + 0, 3324, 3613, + 0, 3324, 3613, + 0, 3324, 3613, + 0, 3324, 3613, + 0, 3324, 3613, + 0, 3325, 3613, + 0, 3325, 3612, + 0, 3326, 3612, + 0, 3326, 3611, + 0, 3327, 3611, + 0, 3328, 3609, + 0, 3330, 3608, + 0, 3332, 3606, + 0, 3335, 3603, + 0, 3339, 3600, + 0, 3344, 3595, + 0, 3351, 3589, + 0, 3360, 3580, + 0, 3371, 3568, + 0, 3386, 3552, + 0, 3406, 3529, + 0, 3431, 3496, + 0, 3462, 3449, + 0, 3500, 3376, + 0, 3547, 3257, + 0, 3603, 3023, + 0, 3668, 1971, + 0, 3743, 0, + 0, 3827, 0, + 0, 3326, 3623, + 0, 3326, 3623, + 0, 3326, 3623, + 0, 3326, 3623, + 0, 3326, 3622, + 0, 3326, 3622, + 0, 3327, 3622, + 0, 3327, 3622, + 0, 3327, 3622, + 0, 3327, 3621, + 0, 3328, 3621, + 0, 3329, 3620, + 0, 3330, 3620, + 0, 3331, 3619, + 0, 3332, 3617, + 0, 3335, 3615, + 0, 3337, 3613, + 0, 3341, 3609, + 0, 3346, 3605, + 0, 3353, 3598, + 0, 3362, 3590, + 0, 3374, 3578, + 0, 3388, 3562, + 0, 3408, 3540, + 0, 3432, 3508, + 0, 3463, 3462, + 0, 3502, 3392, + 0, 3548, 3276, + 0, 3604, 3055, + 0, 3669, 2225, + 0, 3744, 0, + 0, 3828, 0, + 0, 3329, 3635, + 0, 3329, 3635, + 0, 3329, 3634, + 0, 3329, 3634, + 0, 3329, 3634, + 0, 3330, 3634, + 0, 3330, 3634, + 0, 3330, 3634, + 0, 3330, 3634, + 0, 3331, 3633, + 0, 3331, 3633, + 0, 3332, 3632, + 0, 3333, 3632, + 0, 3334, 3631, + 0, 3336, 3629, + 0, 3338, 3627, + 0, 3341, 3625, + 0, 3344, 3622, + 0, 3349, 3617, + 0, 3356, 3611, + 0, 3365, 3603, + 0, 3376, 3591, + 0, 3391, 3576, + 0, 3410, 3554, + 0, 3435, 3523, + 0, 3466, 3479, + 0, 3504, 3411, + 0, 3550, 3301, + 0, 3606, 3095, + 0, 3671, 2431, + 0, 3746, 0, + 0, 3829, 0, + 0, 3333, 3650, + 0, 3333, 3650, + 0, 3334, 3650, + 0, 3334, 3650, + 0, 3334, 3650, + 0, 3334, 3650, + 0, 3334, 3649, + 0, 3334, 3649, + 0, 3334, 3649, + 0, 3335, 3649, + 0, 3335, 3648, + 0, 3336, 3648, + 0, 3337, 3647, + 0, 3338, 3646, + 0, 3340, 3645, + 0, 3342, 3643, + 0, 3345, 3641, + 0, 3349, 3637, + 0, 3354, 3633, + 0, 3360, 3627, + 0, 3369, 3619, + 0, 3380, 3608, + 0, 3395, 3593, + 0, 3414, 3572, + 0, 3438, 3543, + 0, 3469, 3500, + 0, 3507, 3436, + 0, 3553, 3333, + 0, 3608, 3144, + 0, 3673, 2611, + 0, 3747, 0, + 0, 3831, 0, + 0, 3339, 3670, + 0, 3339, 3670, + 0, 3339, 3670, + 0, 3339, 3670, + 0, 3339, 3670, + 0, 3339, 3669, + 0, 3340, 3669, + 0, 3340, 3669, + 0, 3340, 3669, + 0, 3340, 3669, + 0, 3341, 3668, + 0, 3342, 3668, + 0, 3343, 3667, + 0, 3344, 3666, + 0, 3345, 3665, + 0, 3347, 3663, + 0, 3350, 3661, + 0, 3354, 3658, + 0, 3359, 3654, + 0, 3365, 3648, + 0, 3374, 3640, + 0, 3385, 3630, + 0, 3400, 3616, + 0, 3419, 3596, + 0, 3443, 3568, + 0, 3473, 3527, + 0, 3511, 3467, + 0, 3556, 3372, + 0, 3611, 3202, + 0, 3676, 2776, + 0, 3750, 0, + 0, 3833, 0, + 1862, 3346, 3695, + 1860, 3347, 3695, + 1858, 3347, 3695, + 1854, 3347, 3695, + 1849, 3347, 3695, + 1842, 3347, 3695, + 1833, 3347, 3695, + 1821, 3347, 3694, + 1803, 3347, 3694, + 1779, 3348, 3694, + 1744, 3348, 3693, + 1694, 3349, 3693, + 1616, 3350, 3692, + 1484, 3351, 3691, + 1214, 3353, 3690, + 0, 3355, 3689, + 0, 3357, 3686, + 0, 3361, 3684, + 0, 3366, 3680, + 0, 3372, 3674, + 0, 3381, 3667, + 0, 3392, 3657, + 0, 3406, 3644, + 0, 3425, 3625, + 0, 3449, 3599, + 0, 3479, 3562, + 0, 3516, 3506, + 0, 3561, 3419, + 0, 3615, 3269, + 0, 3679, 2931, + 0, 3753, 0, + 0, 3835, 0, + 2854, 3356, 3727, + 2854, 3356, 3727, + 2853, 3356, 3726, + 2853, 3356, 3726, + 2853, 3356, 3726, + 2852, 3357, 3726, + 2851, 3357, 3726, + 2849, 3357, 3726, + 2848, 3357, 3726, + 2845, 3358, 3726, + 2842, 3358, 3725, + 2838, 3359, 3725, + 2832, 3360, 3724, + 2824, 3361, 3723, + 2813, 3362, 3722, + 2798, 3364, 3721, + 2778, 3367, 3719, + 2749, 3371, 3716, + 2706, 3375, 3712, + 2643, 3382, 3707, + 2542, 3390, 3701, + 2357, 3401, 3692, + 1850, 3415, 3679, + 0, 3433, 3662, + 0, 3456, 3638, + 0, 3486, 3604, + 0, 3522, 3553, + 0, 3567, 3476, + 0, 3621, 3346, + 0, 3684, 3080, + 0, 3757, 0, + 0, 3838, 0, + 3210, 3369, 3766, + 3209, 3369, 3766, + 3209, 3369, 3766, + 3209, 3369, 3766, + 3209, 3369, 3766, + 3209, 3369, 3765, + 3208, 3369, 3765, + 3207, 3370, 3765, + 3207, 3370, 3765, + 3206, 3370, 3765, + 3204, 3371, 3764, + 3202, 3371, 3764, + 3200, 3372, 3763, + 3196, 3373, 3763, + 3191, 3375, 3762, + 3185, 3377, 3760, + 3176, 3379, 3758, + 3164, 3383, 3756, + 3148, 3387, 3753, + 3125, 3394, 3748, + 3092, 3402, 3742, + 3045, 3412, 3734, + 2972, 3426, 3722, + 2852, 3444, 3707, + 2617, 3467, 3685, + 1537, 3495, 3654, + 0, 3531, 3609, + 0, 3575, 3542, + 0, 3628, 3431, + 0, 3690, 3224, + 0, 3762, 2549, + 0, 3843, 0, + 3457, 3385, 3813, + 3457, 3385, 3813, + 3457, 3385, 3813, + 3457, 3385, 3813, + 3457, 3385, 3813, + 3457, 3386, 3813, + 3457, 3386, 3813, + 3456, 3386, 3813, + 3456, 3386, 3813, + 3455, 3387, 3812, + 3454, 3387, 3812, + 3453, 3388, 3812, + 3452, 3388, 3811, + 3450, 3389, 3811, + 3447, 3391, 3810, + 3443, 3393, 3808, + 3439, 3395, 3807, + 3432, 3399, 3805, + 3423, 3403, 3802, + 3410, 3409, 3797, + 3393, 3417, 3792, + 3369, 3427, 3785, + 3335, 3441, 3774, + 3285, 3458, 3761, + 3208, 3480, 3741, + 3079, 3508, 3714, + 2817, 3543, 3675, + 0, 3586, 3617, + 0, 3637, 3526, + 0, 3698, 3365, + 0, 3769, 2984, + 0, 3849, 0, + 3660, 3406, 3870, + 3660, 3406, 3870, + 3660, 3406, 3870, + 3660, 3406, 3870, + 3660, 3407, 3870, + 3660, 3407, 3870, + 3660, 3407, 3870, + 3660, 3407, 3870, + 3659, 3407, 3869, + 3659, 3408, 3869, + 3658, 3408, 3869, + 3658, 3409, 3869, + 3657, 3409, 3868, + 3655, 3410, 3868, + 3654, 3412, 3867, + 3651, 3414, 3866, + 3648, 3416, 3864, + 3644, 3419, 3862, + 3638, 3424, 3860, + 3631, 3429, 3856, + 3620, 3437, 3851, + 3606, 3446, 3845, + 3586, 3459, 3836, + 3558, 3476, 3824, + 3517, 3497, 3807, + 3456, 3524, 3784, + 3360, 3558, 3750, + 3187, 3599, 3702, + 2750, 3650, 3627, + 0, 3709, 3503, + 0, 3778, 3257, + 0, 3856, 1771, + 3839, 3433, 3936, + 3839, 3433, 3936, + 3839, 3433, 3936, + 3839, 3433, 3936, + 3839, 3433, 3936, + 3839, 3433, 3936, + 3838, 3433, 3936, + 3838, 3434, 3936, + 3838, 3434, 3936, + 3838, 3434, 3936, + 3838, 3435, 3935, + 3837, 3435, 3935, + 3836, 3436, 3935, + 3836, 3437, 3934, + 3834, 3438, 3933, + 3833, 3440, 3932, + 3831, 3442, 3931, + 3828, 3445, 3930, + 3824, 3449, 3927, + 3819, 3455, 3924, + 3812, 3462, 3920, + 3803, 3471, 3914, + 3790, 3483, 3907, + 3772, 3499, 3897, + 3747, 3519, 3882, + 3712, 3545, 3863, + 3659, 3577, 3835, + 3578, 3617, 3795, + 3440, 3665, 3735, + 3149, 3723, 3640, + 0, 3790, 3472, + 0, 3867, 3056, + 4003, 3467, 4012, + 4003, 3467, 4012, + 4003, 3467, 4012, + 4003, 3467, 4012, + 4003, 3467, 4012, + 4003, 3467, 4012, + 4003, 3467, 4012, + 4002, 3467, 4012, + 4002, 3467, 4012, + 4002, 3468, 4011, + 4002, 3468, 4011, + 4002, 3468, 4011, + 4001, 3469, 4011, + 4001, 3470, 4010, + 4000, 3471, 4010, + 3999, 3473, 4009, + 3997, 3475, 4008, + 3995, 3478, 4006, + 3993, 3482, 4004, + 3989, 3487, 4002, + 3984, 3493, 3998, + 3978, 3502, 3994, + 3969, 3513, 3987, + 3957, 3528, 3979, + 3941, 3547, 3967, + 3918, 3571, 3950, + 3886, 3602, 3928, + 3838, 3640, 3895, + 3765, 3686, 3848, + 3646, 3741, 3776, + 3411, 3806, 3657, + 2348, 3880, 3426, + 4095, 3508, 4095, + 4095, 3508, 4095, + 4095, 3508, 4095, + 4095, 3508, 4095, + 4095, 3508, 4095, + 4095, 3508, 4095, + 4095, 3508, 4095, + 4095, 3508, 4095, + 4095, 3508, 4095, + 4095, 3509, 4095, + 4095, 3509, 4095, + 4095, 3509, 4095, + 4095, 3510, 4095, + 4095, 3511, 4095, + 4095, 3512, 4095, + 4095, 3513, 4094, + 4095, 3515, 4093, + 4095, 3518, 4092, + 4095, 3522, 4091, + 4095, 3526, 4088, + 4095, 3532, 4086, + 4095, 3540, 4082, + 4095, 3551, 4076, + 4095, 3564, 4069, + 4095, 3582, 4060, + 4095, 3604, 4046, + 4077, 3633, 4028, + 4046, 3668, 4002, + 4002, 3712, 3965, + 3935, 3764, 3911, + 3826, 3826, 3826, + 3621, 3897, 3679, + 4095, 3558, 4095, + 4095, 3558, 4095, + 4095, 3558, 4095, + 4095, 3558, 4095, + 4095, 3558, 4095, + 4095, 3558, 4095, + 4095, 3558, 4095, + 4095, 3558, 4095, + 4095, 3558, 4095, + 4095, 3558, 4095, + 4095, 3559, 4095, + 4095, 3559, 4095, + 4095, 3560, 4095, + 4095, 3560, 4095, + 4095, 3561, 4095, + 4095, 3563, 4095, + 4095, 3564, 4095, + 4095, 3567, 4095, + 4095, 3570, 4095, + 4095, 3574, 4095, + 4095, 3580, 4095, + 4095, 3587, 4095, + 4095, 3596, 4095, + 4095, 3608, 4095, + 4095, 3624, 4095, + 4095, 3645, 4095, + 4095, 3671, 4095, + 4095, 3704, 4095, + 4095, 3744, 4086, + 4095, 3793, 4045, + 4093, 3851, 3983, + 3990, 3919, 3884, + 0, 3448, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3717, + 0, 3449, 3717, + 0, 3449, 3717, + 0, 3450, 3717, + 0, 3450, 3717, + 0, 3450, 3716, + 0, 3451, 3715, + 0, 3452, 3715, + 0, 3453, 3713, + 0, 3455, 3712, + 0, 3457, 3710, + 0, 3460, 3707, + 0, 3464, 3703, + 0, 3469, 3698, + 0, 3476, 3691, + 0, 3485, 3682, + 0, 3497, 3669, + 0, 3512, 3652, + 0, 3532, 3627, + 0, 3557, 3592, + 0, 3588, 3540, + 0, 3627, 3460, + 0, 3675, 3325, + 0, 3731, 3043, + 0, 3797, 0, + 0, 3873, 0, + 0, 3448, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3717, + 0, 3449, 3717, + 0, 3450, 3717, + 0, 3450, 3717, + 0, 3451, 3716, + 0, 3451, 3715, + 0, 3452, 3715, + 0, 3453, 3713, + 0, 3455, 3712, + 0, 3457, 3710, + 0, 3460, 3707, + 0, 3464, 3703, + 0, 3469, 3698, + 0, 3476, 3692, + 0, 3485, 3682, + 0, 3497, 3670, + 0, 3512, 3652, + 0, 3532, 3627, + 0, 3557, 3592, + 0, 3588, 3540, + 0, 3627, 3460, + 0, 3675, 3325, + 0, 3731, 3043, + 0, 3797, 0, + 0, 3873, 0, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3717, + 0, 3449, 3717, + 0, 3450, 3717, + 0, 3450, 3717, + 0, 3451, 3716, + 0, 3451, 3716, + 0, 3452, 3715, + 0, 3453, 3714, + 0, 3455, 3712, + 0, 3457, 3710, + 0, 3460, 3707, + 0, 3464, 3703, + 0, 3469, 3698, + 0, 3476, 3692, + 0, 3485, 3682, + 0, 3497, 3670, + 0, 3512, 3652, + 0, 3532, 3627, + 0, 3557, 3592, + 0, 3588, 3540, + 0, 3627, 3461, + 0, 3675, 3326, + 0, 3731, 3043, + 0, 3797, 0, + 0, 3873, 0, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3717, + 0, 3450, 3717, + 0, 3450, 3717, + 0, 3451, 3716, + 0, 3451, 3716, + 0, 3452, 3715, + 0, 3453, 3714, + 0, 3455, 3712, + 0, 3457, 3710, + 0, 3460, 3707, + 0, 3464, 3703, + 0, 3469, 3698, + 0, 3476, 3692, + 0, 3485, 3682, + 0, 3497, 3670, + 0, 3512, 3652, + 0, 3532, 3627, + 0, 3557, 3592, + 0, 3588, 3541, + 0, 3627, 3461, + 0, 3675, 3326, + 0, 3731, 3043, + 0, 3797, 0, + 0, 3873, 0, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3717, + 0, 3450, 3717, + 0, 3450, 3717, + 0, 3451, 3716, + 0, 3451, 3716, + 0, 3452, 3715, + 0, 3453, 3714, + 0, 3455, 3712, + 0, 3457, 3710, + 0, 3460, 3707, + 0, 3464, 3704, + 0, 3469, 3699, + 0, 3476, 3692, + 0, 3485, 3682, + 0, 3497, 3670, + 0, 3512, 3652, + 0, 3532, 3628, + 0, 3557, 3592, + 0, 3588, 3541, + 0, 3627, 3461, + 0, 3675, 3326, + 0, 3731, 3044, + 0, 3797, 0, + 0, 3873, 0, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3450, 3717, + 0, 3450, 3717, + 0, 3451, 3716, + 0, 3451, 3716, + 0, 3452, 3715, + 0, 3453, 3714, + 0, 3455, 3712, + 0, 3457, 3710, + 0, 3460, 3707, + 0, 3464, 3704, + 0, 3469, 3699, + 0, 3476, 3692, + 0, 3485, 3683, + 0, 3497, 3670, + 0, 3512, 3652, + 0, 3532, 3628, + 0, 3557, 3593, + 0, 3588, 3541, + 0, 3627, 3461, + 0, 3675, 3326, + 0, 3731, 3044, + 0, 3797, 0, + 0, 3873, 0, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3450, 3717, + 0, 3450, 3717, + 0, 3451, 3717, + 0, 3451, 3716, + 0, 3452, 3715, + 0, 3454, 3714, + 0, 3455, 3712, + 0, 3457, 3710, + 0, 3460, 3708, + 0, 3464, 3704, + 0, 3469, 3699, + 0, 3476, 3692, + 0, 3485, 3683, + 0, 3497, 3670, + 0, 3512, 3653, + 0, 3532, 3628, + 0, 3557, 3593, + 0, 3588, 3541, + 0, 3627, 3461, + 0, 3675, 3327, + 0, 3731, 3045, + 0, 3797, 0, + 0, 3873, 0, + 0, 3449, 3719, + 0, 3449, 3719, + 0, 3449, 3719, + 0, 3449, 3719, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3449, 3718, + 0, 3450, 3718, + 0, 3450, 3717, + 0, 3451, 3717, + 0, 3451, 3716, + 0, 3452, 3715, + 0, 3454, 3714, + 0, 3455, 3713, + 0, 3457, 3711, + 0, 3460, 3708, + 0, 3464, 3704, + 0, 3470, 3699, + 0, 3476, 3692, + 0, 3485, 3683, + 0, 3497, 3670, + 0, 3512, 3653, + 0, 3532, 3628, + 0, 3557, 3593, + 0, 3589, 3541, + 0, 3627, 3462, + 0, 3675, 3327, + 0, 3731, 3046, + 0, 3797, 0, + 0, 3873, 0, + 0, 3449, 3719, + 0, 3449, 3719, + 0, 3449, 3719, + 0, 3449, 3719, + 0, 3449, 3719, + 0, 3449, 3719, + 0, 3449, 3719, + 0, 3449, 3718, + 0, 3450, 3718, + 0, 3450, 3718, + 0, 3450, 3718, + 0, 3451, 3717, + 0, 3451, 3716, + 0, 3452, 3716, + 0, 3454, 3714, + 0, 3455, 3713, + 0, 3458, 3711, + 0, 3460, 3708, + 0, 3464, 3704, + 0, 3470, 3699, + 0, 3476, 3693, + 0, 3485, 3683, + 0, 3497, 3671, + 0, 3512, 3653, + 0, 3532, 3629, + 0, 3557, 3593, + 0, 3589, 3542, + 0, 3627, 3462, + 0, 3675, 3328, + 0, 3731, 3047, + 0, 3797, 0, + 0, 3873, 0, + 0, 3449, 3719, + 0, 3449, 3719, + 0, 3449, 3719, + 0, 3449, 3719, + 0, 3449, 3719, + 0, 3449, 3719, + 0, 3449, 3719, + 0, 3449, 3719, + 0, 3450, 3719, + 0, 3450, 3718, + 0, 3450, 3718, + 0, 3451, 3718, + 0, 3452, 3717, + 0, 3452, 3716, + 0, 3454, 3715, + 0, 3455, 3713, + 0, 3458, 3711, + 0, 3461, 3709, + 0, 3465, 3705, + 0, 3470, 3700, + 0, 3477, 3693, + 0, 3486, 3684, + 0, 3497, 3671, + 0, 3513, 3654, + 0, 3532, 3629, + 0, 3557, 3594, + 0, 3589, 3542, + 0, 3628, 3463, + 0, 3675, 3329, + 0, 3731, 3049, + 0, 3797, 0, + 0, 3873, 0, + 0, 3449, 3720, + 0, 3449, 3720, + 0, 3449, 3720, + 0, 3449, 3720, + 0, 3449, 3720, + 0, 3449, 3720, + 0, 3449, 3719, + 0, 3450, 3719, + 0, 3450, 3719, + 0, 3450, 3719, + 0, 3450, 3719, + 0, 3451, 3718, + 0, 3452, 3717, + 0, 3453, 3717, + 0, 3454, 3715, + 0, 3456, 3714, + 0, 3458, 3712, + 0, 3461, 3709, + 0, 3465, 3705, + 0, 3470, 3700, + 0, 3477, 3694, + 0, 3486, 3684, + 0, 3497, 3672, + 0, 3513, 3654, + 0, 3532, 3630, + 0, 3557, 3595, + 0, 3589, 3543, + 0, 3628, 3464, + 0, 3675, 3330, + 0, 3731, 3051, + 0, 3797, 0, + 0, 3873, 0, + 0, 3449, 3721, + 0, 3449, 3721, + 0, 3449, 3720, + 0, 3449, 3720, + 0, 3449, 3720, + 0, 3449, 3720, + 0, 3450, 3720, + 0, 3450, 3720, + 0, 3450, 3720, + 0, 3450, 3720, + 0, 3451, 3719, + 0, 3451, 3719, + 0, 3452, 3718, + 0, 3453, 3717, + 0, 3454, 3716, + 0, 3456, 3715, + 0, 3458, 3713, + 0, 3461, 3710, + 0, 3465, 3706, + 0, 3470, 3701, + 0, 3477, 3694, + 0, 3486, 3685, + 0, 3498, 3672, + 0, 3513, 3655, + 0, 3532, 3631, + 0, 3557, 3596, + 0, 3589, 3544, + 0, 3628, 3465, + 0, 3675, 3332, + 0, 3731, 3055, + 0, 3797, 0, + 0, 3873, 0, + 0, 3449, 3721, + 0, 3449, 3721, + 0, 3449, 3721, + 0, 3450, 3721, + 0, 3450, 3721, + 0, 3450, 3721, + 0, 3450, 3721, + 0, 3450, 3721, + 0, 3450, 3721, + 0, 3450, 3721, + 0, 3451, 3720, + 0, 3451, 3720, + 0, 3452, 3719, + 0, 3453, 3718, + 0, 3454, 3717, + 0, 3456, 3716, + 0, 3458, 3714, + 0, 3461, 3711, + 0, 3465, 3707, + 0, 3470, 3702, + 0, 3477, 3695, + 0, 3486, 3686, + 0, 3498, 3674, + 0, 3513, 3656, + 0, 3533, 3632, + 0, 3558, 3597, + 0, 3589, 3546, + 0, 3628, 3467, + 0, 3675, 3334, + 0, 3732, 3059, + 0, 3798, 0, + 0, 3873, 0, + 0, 3450, 3723, + 0, 3450, 3723, + 0, 3450, 3723, + 0, 3450, 3723, + 0, 3450, 3723, + 0, 3450, 3723, + 0, 3450, 3722, + 0, 3450, 3722, + 0, 3451, 3722, + 0, 3451, 3722, + 0, 3451, 3721, + 0, 3452, 3721, + 0, 3452, 3720, + 0, 3453, 3719, + 0, 3455, 3718, + 0, 3456, 3717, + 0, 3458, 3715, + 0, 3461, 3712, + 0, 3465, 3708, + 0, 3471, 3703, + 0, 3477, 3697, + 0, 3486, 3687, + 0, 3498, 3675, + 0, 3513, 3658, + 0, 3533, 3633, + 0, 3558, 3599, + 0, 3589, 3548, + 0, 3628, 3469, + 0, 3675, 3337, + 0, 3732, 3064, + 0, 3798, 0, + 0, 3873, 0, + 0, 3450, 3724, + 0, 3450, 3724, + 0, 3450, 3724, + 0, 3450, 3724, + 0, 3450, 3724, + 0, 3450, 3724, + 0, 3451, 3724, + 0, 3451, 3724, + 0, 3451, 3724, + 0, 3451, 3723, + 0, 3452, 3723, + 0, 3452, 3723, + 0, 3453, 3722, + 0, 3454, 3721, + 0, 3455, 3720, + 0, 3457, 3719, + 0, 3459, 3717, + 0, 3462, 3714, + 0, 3466, 3710, + 0, 3471, 3705, + 0, 3478, 3698, + 0, 3487, 3689, + 0, 3498, 3677, + 0, 3514, 3659, + 0, 3533, 3635, + 0, 3558, 3601, + 0, 3590, 3550, + 0, 3628, 3472, + 0, 3676, 3341, + 0, 3732, 3071, + 0, 3798, 0, + 0, 3873, 0, + 0, 3451, 3727, + 0, 3451, 3727, + 0, 3451, 3727, + 0, 3451, 3727, + 0, 3451, 3727, + 0, 3451, 3726, + 0, 3451, 3726, + 0, 3451, 3726, + 0, 3452, 3726, + 0, 3452, 3726, + 0, 3452, 3725, + 0, 3453, 3725, + 0, 3453, 3724, + 0, 3454, 3723, + 0, 3456, 3722, + 0, 3457, 3721, + 0, 3459, 3719, + 0, 3462, 3716, + 0, 3466, 3712, + 0, 3471, 3708, + 0, 3478, 3701, + 0, 3487, 3692, + 0, 3499, 3679, + 0, 3514, 3662, + 0, 3534, 3638, + 0, 3559, 3604, + 0, 3590, 3553, + 0, 3629, 3476, + 0, 3676, 3346, + 0, 3732, 3081, + 0, 3798, 0, + 0, 3873, 0, + 0, 3451, 3730, + 0, 3452, 3730, + 0, 3452, 3730, + 0, 3452, 3730, + 0, 3452, 3729, + 0, 3452, 3729, + 0, 3452, 3729, + 0, 3452, 3729, + 0, 3452, 3729, + 0, 3453, 3729, + 0, 3453, 3728, + 0, 3453, 3728, + 0, 3454, 3727, + 0, 3455, 3726, + 0, 3456, 3725, + 0, 3458, 3724, + 0, 3460, 3722, + 0, 3463, 3719, + 0, 3467, 3716, + 0, 3472, 3711, + 0, 3479, 3704, + 0, 3488, 3695, + 0, 3500, 3683, + 0, 3515, 3666, + 0, 3534, 3642, + 0, 3559, 3608, + 0, 3591, 3558, + 0, 3629, 3481, + 0, 3676, 3353, + 0, 3733, 3093, + 0, 3798, 0, + 0, 3874, 0, + 0, 3453, 3734, + 0, 3453, 3734, + 0, 3453, 3734, + 0, 3453, 3734, + 0, 3453, 3733, + 0, 3453, 3733, + 0, 3453, 3733, + 0, 3453, 3733, + 0, 3453, 3733, + 0, 3454, 3733, + 0, 3454, 3732, + 0, 3454, 3732, + 0, 3455, 3731, + 0, 3456, 3730, + 0, 3457, 3729, + 0, 3459, 3728, + 0, 3461, 3726, + 0, 3464, 3723, + 0, 3468, 3720, + 0, 3473, 3715, + 0, 3480, 3708, + 0, 3489, 3699, + 0, 3501, 3687, + 0, 3516, 3670, + 0, 3535, 3646, + 0, 3560, 3613, + 0, 3591, 3563, + 0, 3630, 3488, + 0, 3677, 3362, + 0, 3733, 3109, + 0, 3799, 370, + 0, 3874, 0, + 0, 3454, 3739, + 0, 3454, 3739, + 0, 3454, 3739, + 0, 3454, 3739, + 0, 3454, 3739, + 0, 3454, 3739, + 0, 3454, 3738, + 0, 3454, 3738, + 0, 3455, 3738, + 0, 3455, 3738, + 0, 3455, 3738, + 0, 3456, 3737, + 0, 3457, 3737, + 0, 3457, 3736, + 0, 3459, 3735, + 0, 3460, 3733, + 0, 3463, 3731, + 0, 3465, 3729, + 0, 3469, 3725, + 0, 3474, 3720, + 0, 3481, 3714, + 0, 3490, 3705, + 0, 3502, 3693, + 0, 3517, 3676, + 0, 3536, 3653, + 0, 3561, 3620, + 0, 3592, 3571, + 0, 3631, 3497, + 0, 3678, 3374, + 0, 3734, 3129, + 0, 3800, 1731, + 0, 3875, 0, + 0, 3456, 3746, + 0, 3456, 3746, + 0, 3456, 3746, + 0, 3456, 3746, + 0, 3456, 3746, + 0, 3456, 3745, + 0, 3456, 3745, + 0, 3456, 3745, + 0, 3456, 3745, + 0, 3457, 3745, + 0, 3457, 3744, + 0, 3458, 3744, + 0, 3458, 3743, + 0, 3459, 3743, + 0, 3460, 3742, + 0, 3462, 3740, + 0, 3464, 3738, + 0, 3467, 3736, + 0, 3471, 3732, + 0, 3476, 3727, + 0, 3483, 3721, + 0, 3492, 3712, + 0, 3503, 3700, + 0, 3518, 3684, + 0, 3538, 3661, + 0, 3563, 3629, + 0, 3594, 3581, + 0, 3632, 3508, + 0, 3679, 3389, + 0, 3735, 3155, + 0, 3800, 2103, + 0, 3875, 0, + 0, 3458, 3755, + 0, 3458, 3755, + 0, 3458, 3755, + 0, 3458, 3755, + 0, 3458, 3755, + 0, 3458, 3755, + 0, 3458, 3754, + 0, 3459, 3754, + 0, 3459, 3754, + 0, 3459, 3754, + 0, 3460, 3754, + 0, 3460, 3753, + 0, 3461, 3753, + 0, 3462, 3752, + 0, 3463, 3751, + 0, 3465, 3749, + 0, 3467, 3747, + 0, 3470, 3745, + 0, 3473, 3741, + 0, 3479, 3737, + 0, 3485, 3731, + 0, 3494, 3722, + 0, 3506, 3710, + 0, 3521, 3694, + 0, 3540, 3672, + 0, 3565, 3640, + 0, 3595, 3594, + 0, 3634, 3524, + 0, 3681, 3409, + 0, 3736, 3187, + 0, 3802, 2357, + 0, 3876, 0, + 0, 3461, 3767, + 0, 3461, 3767, + 0, 3461, 3767, + 0, 3461, 3767, + 0, 3461, 3767, + 0, 3462, 3766, + 0, 3462, 3766, + 0, 3462, 3766, + 0, 3462, 3766, + 0, 3462, 3766, + 0, 3463, 3765, + 0, 3463, 3765, + 0, 3464, 3764, + 0, 3465, 3764, + 0, 3466, 3763, + 0, 3468, 3761, + 0, 3470, 3759, + 0, 3473, 3757, + 0, 3477, 3754, + 0, 3482, 3749, + 0, 3488, 3743, + 0, 3497, 3735, + 0, 3508, 3723, + 0, 3523, 3708, + 0, 3543, 3686, + 0, 3567, 3655, + 0, 3598, 3611, + 0, 3636, 3543, + 0, 3682, 3434, + 0, 3738, 3227, + 0, 3803, 2563, + 0, 3878, 0, + 0, 3466, 3782, + 0, 3466, 3782, + 0, 3466, 3782, + 0, 3466, 3782, + 0, 3466, 3782, + 0, 3466, 3782, + 0, 3466, 3782, + 0, 3466, 3782, + 0, 3466, 3781, + 0, 3467, 3781, + 0, 3467, 3781, + 0, 3467, 3780, + 0, 3468, 3780, + 0, 3469, 3779, + 0, 3470, 3778, + 0, 3472, 3777, + 0, 3474, 3775, + 0, 3477, 3773, + 0, 3481, 3769, + 0, 3486, 3765, + 0, 3492, 3759, + 0, 3501, 3751, + 0, 3512, 3740, + 0, 3527, 3725, + 0, 3546, 3704, + 0, 3570, 3675, + 0, 3601, 3632, + 0, 3639, 3568, + 0, 3685, 3465, + 0, 3740, 3276, + 0, 3805, 2743, + 0, 3879, 0, + 0, 3471, 3802, + 0, 3471, 3802, + 0, 3471, 3802, + 0, 3471, 3802, + 0, 3471, 3802, + 0, 3471, 3802, + 0, 3472, 3802, + 0, 3472, 3801, + 0, 3472, 3801, + 0, 3472, 3801, + 0, 3473, 3801, + 0, 3473, 3800, + 0, 3474, 3800, + 0, 3475, 3799, + 0, 3476, 3798, + 0, 3477, 3797, + 0, 3480, 3795, + 0, 3482, 3793, + 0, 3486, 3790, + 0, 3491, 3786, + 0, 3498, 3780, + 0, 3506, 3772, + 0, 3517, 3762, + 0, 3532, 3748, + 0, 3551, 3728, + 0, 3575, 3700, + 0, 3605, 3660, + 0, 3643, 3599, + 0, 3689, 3504, + 0, 3743, 3334, + 0, 3808, 2908, + 0, 3882, 0, + 1996, 3479, 3827, + 1994, 3479, 3827, + 1992, 3479, 3827, + 1990, 3479, 3827, + 1986, 3479, 3827, + 1981, 3479, 3827, + 1974, 3479, 3827, + 1965, 3479, 3827, + 1953, 3479, 3826, + 1935, 3480, 3826, + 1911, 3480, 3826, + 1877, 3480, 3826, + 1826, 3481, 3825, + 1748, 3482, 3824, + 1616, 3483, 3824, + 1346, 3485, 3822, + 0, 3487, 3821, + 0, 3490, 3819, + 0, 3493, 3816, + 0, 3498, 3812, + 0, 3505, 3806, + 0, 3513, 3799, + 0, 3524, 3789, + 0, 3538, 3776, + 0, 3557, 3757, + 0, 3581, 3731, + 0, 3611, 3694, + 0, 3648, 3638, + 0, 3693, 3551, + 0, 3748, 3401, + 0, 3811, 3063, + 0, 3885, 0, + 2986, 3488, 3859, + 2986, 3488, 3859, + 2986, 3488, 3859, + 2986, 3488, 3859, + 2985, 3488, 3859, + 2985, 3489, 3858, + 2984, 3489, 3858, + 2983, 3489, 3858, + 2982, 3489, 3858, + 2980, 3489, 3858, + 2977, 3490, 3858, + 2974, 3490, 3857, + 2970, 3491, 3857, + 2964, 3492, 3856, + 2956, 3493, 3855, + 2945, 3494, 3854, + 2931, 3496, 3853, + 2910, 3499, 3851, + 2881, 3503, 3848, + 2839, 3507, 3844, + 2775, 3514, 3839, + 2674, 3522, 3833, + 2489, 3533, 3824, + 1982, 3547, 3811, + 0, 3565, 3794, + 0, 3589, 3770, + 0, 3618, 3736, + 0, 3655, 3685, + 0, 3699, 3608, + 0, 3753, 3478, + 0, 3816, 3212, + 0, 3889, 0, + 3342, 3501, 3898, + 3342, 3501, 3898, + 3342, 3501, 3898, + 3341, 3501, 3898, + 3341, 3501, 3898, + 3341, 3501, 3898, + 3341, 3501, 3898, + 3340, 3501, 3897, + 3340, 3502, 3897, + 3339, 3502, 3897, + 3338, 3502, 3897, + 3336, 3503, 3897, + 3334, 3503, 3896, + 3332, 3504, 3896, + 3328, 3505, 3895, + 3323, 3507, 3894, + 3317, 3509, 3892, + 3308, 3511, 3891, + 3296, 3515, 3888, + 3280, 3520, 3885, + 3257, 3526, 3880, + 3224, 3534, 3874, + 3177, 3544, 3866, + 3104, 3558, 3854, + 2984, 3576, 3839, + 2749, 3599, 3817, + 1669, 3628, 3786, + 0, 3663, 3741, + 0, 3707, 3674, + 0, 3760, 3564, + 0, 3822, 3356, + 0, 3894, 2681, + 3590, 3517, 3945, + 3590, 3517, 3945, + 3590, 3517, 3945, + 3589, 3517, 3945, + 3589, 3518, 3945, + 3589, 3518, 3945, + 3589, 3518, 3945, + 3589, 3518, 3945, + 3588, 3518, 3945, + 3588, 3518, 3945, + 3587, 3519, 3945, + 3586, 3519, 3944, + 3585, 3520, 3944, + 3584, 3520, 3943, + 3582, 3522, 3943, + 3579, 3523, 3942, + 3576, 3525, 3941, + 3571, 3527, 3939, + 3564, 3531, 3937, + 3555, 3535, 3934, + 3543, 3541, 3930, + 3525, 3549, 3924, + 3501, 3559, 3917, + 3467, 3573, 3907, + 3417, 3590, 3893, + 3340, 3612, 3873, + 3211, 3640, 3846, + 2949, 3675, 3807, + 0, 3718, 3749, + 0, 3769, 3658, + 0, 3830, 3497, + 0, 3901, 3116, + 3792, 3538, 4002, + 3792, 3538, 4002, + 3792, 3538, 4002, + 3792, 3539, 4002, + 3792, 3539, 4002, + 3792, 3539, 4002, + 3792, 3539, 4002, + 3792, 3539, 4002, + 3792, 3539, 4002, + 3791, 3539, 4002, + 3791, 3540, 4001, + 3790, 3540, 4001, + 3790, 3541, 4001, + 3789, 3541, 4000, + 3787, 3542, 4000, + 3786, 3544, 3999, + 3783, 3546, 3998, + 3780, 3548, 3996, + 3776, 3551, 3994, + 3770, 3556, 3992, + 3763, 3561, 3988, + 3752, 3569, 3983, + 3738, 3579, 3977, + 3718, 3591, 3968, + 3690, 3608, 3956, + 3649, 3629, 3939, + 3588, 3656, 3916, + 3492, 3690, 3882, + 3319, 3731, 3834, + 2882, 3782, 3759, + 0, 3841, 3636, + 0, 3910, 3389, + 3971, 3565, 4068, + 3971, 3565, 4068, + 3971, 3565, 4068, + 3971, 3565, 4068, + 3971, 3565, 4068, + 3971, 3565, 4068, + 3971, 3565, 4068, + 3971, 3566, 4068, + 3970, 3566, 4068, + 3970, 3566, 4068, + 3970, 3566, 4068, + 3970, 3567, 4067, + 3969, 3567, 4067, + 3968, 3568, 4067, + 3968, 3569, 4066, + 3966, 3570, 4066, + 3965, 3572, 4065, + 3963, 3574, 4063, + 3960, 3577, 4062, + 3956, 3581, 4059, + 3951, 3587, 4056, + 3944, 3594, 4052, + 3935, 3603, 4047, + 3922, 3615, 4039, + 3904, 3631, 4029, + 3879, 3651, 4014, + 3844, 3677, 3995, + 3791, 3709, 3967, + 3710, 3749, 3927, + 3572, 3797, 3867, + 3281, 3855, 3772, + 0, 3922, 3604, + 4095, 3599, 4095, + 4095, 3599, 4095, + 4095, 3599, 4095, + 4095, 3599, 4095, + 4095, 3599, 4095, + 4095, 3599, 4095, + 4095, 3599, 4095, + 4095, 3599, 4095, + 4095, 3599, 4095, + 4095, 3599, 4095, + 4095, 3600, 4095, + 4095, 3600, 4095, + 4095, 3601, 4095, + 4095, 3601, 4095, + 4095, 3602, 4095, + 4095, 3603, 4095, + 4095, 3605, 4095, + 4095, 3607, 4095, + 4095, 3610, 4095, + 4095, 3614, 4095, + 4095, 3619, 4095, + 4095, 3625, 4095, + 4095, 3634, 4095, + 4095, 3645, 4095, + 4090, 3660, 4095, + 4073, 3679, 4095, + 4050, 3703, 4083, + 4018, 3734, 4060, + 3970, 3772, 4027, + 3897, 3818, 3980, + 3778, 3873, 3908, + 3543, 3938, 3789, + 4095, 3640, 4095, + 4095, 3640, 4095, + 4095, 3640, 4095, + 4095, 3640, 4095, + 4095, 3640, 4095, + 4095, 3640, 4095, + 4095, 3640, 4095, + 4095, 3640, 4095, + 4095, 3640, 4095, + 4095, 3641, 4095, + 4095, 3641, 4095, + 4095, 3641, 4095, + 4095, 3642, 4095, + 4095, 3642, 4095, + 4095, 3643, 4095, + 4095, 3644, 4095, + 4095, 3646, 4095, + 4095, 3648, 4095, + 4095, 3650, 4095, + 4095, 3654, 4095, + 4095, 3658, 4095, + 4095, 3664, 4095, + 4095, 3672, 4095, + 4095, 3683, 4095, + 4095, 3696, 4095, + 4095, 3714, 4095, + 4095, 3736, 4095, + 4095, 3765, 4095, + 4095, 3800, 4095, + 4095, 3844, 4095, + 4067, 3896, 4043, + 3958, 3958, 3958 +] + } +} diff --git a/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/Test_Grade/test-grade_inv-Log2-48nits_32_LUT.exr b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/Test_Grade/test-grade_inv-Log2-48nits_32_LUT.exr new file mode 100644 index 0000000000..a01efd6e72 --- /dev/null +++ b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/Test_Grade/test-grade_inv-Log2-48nits_32_LUT.exr @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c11862c33eb828f32df7dd1a7dd8843f7553379334553551aae0aaadb2100a01 +size 276701 diff --git a/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/displaymapperpassthrough.dds b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/displaymapperpassthrough.dds new file mode 100644 index 0000000000..42f736064e --- /dev/null +++ b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/displaymapperpassthrough.dds @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:20355376cea9da29e36086debf3d84a6453dcbd8c1616c3c57e5a6c0df0a9e0e +size 15105796 diff --git a/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/displaymapperpassthrough.exr b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/displaymapperpassthrough.exr new file mode 100644 index 0000000000..dd1b951211 --- /dev/null +++ b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/displaymapperpassthrough.exr @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:da5a5fcf9eff8064f27f7f146db353fde7207fc36b10cfde95dc6b45941663bf +size 5046039 diff --git a/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/O3DE_HDR_Nuke_Color_Grading b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/O3DE_HDR_Nuke_Color_Grading new file mode 100644 index 0000000000..eab6fb7d9e --- /dev/null +++ b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/O3DE_HDR_Nuke_Color_Grading @@ -0,0 +1,57 @@ +#! C:/Program Files/Nuke13.0v3/nuke-13.0.3.dll -nx +version 13.0 v3 +define_window_layout_xml { + + + + + + + + + + + + + + + + + + + + + + + + + + + + +} +Root { + inputs 0 + name C:/Depot/o3de-engine/Gems/AtomLyIntegration/CommonFeatures/Tools/ColorGrading/TestData/Nuke/O3DE_HDR_Nuke_Color_Grading + project_directory "\[python \{nuke.script_directory()\}]" + label "This is a Nuke project template used to validate HDR / ACES color grading workflow in Nuke to generate 'Look Modification' (LMT) Luts for Oopen 3D Engine." + format "2048 1556 0 0 2048 1556 1 2K_Super_35(full-ap)" + proxy_type scale + proxy_format "1024 778 0 0 1024 778 1 1K_Super_35(full-ap)" + colorManagement Nuke + workingSpaceLUT linear + monitorLut sRGB + monitorOutLUT rec709 + int8Lut sRGB + int16Lut sRGB + logLut Cineon + floatLut linear +} +Viewer { + inputs 0 + frame 1 + frame_range 1-100 + name Viewer1 + xpos -40 + ypos -9 +} diff --git a/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/O3DE_HDR_Nuke_Color_Grading.autosave b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/O3DE_HDR_Nuke_Color_Grading.autosave new file mode 100644 index 0000000000..00db0cd63d --- /dev/null +++ b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/O3DE_HDR_Nuke_Color_Grading.autosave @@ -0,0 +1,125 @@ +#! C:/Program Files/Nuke13.0v3/nuke-13.0.3.dll -nx +version 13.0 v3 +define_window_layout_xml { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +} +Root { + inputs 0 + name C:/Depot/o3de-engine/Gems/AtomLyIntegration/CommonFeatures/Tools/ColorGrading/TestData/Nuke/O3DE_HDR_Nuke_Color_Grading + project_directory C:/Depot/o3de-engine/Gems/AtomLyIntegration/CommonFeatures/Tools/ColorGrading/TestData/Nuke + label "This is a Nuke project template used to validate HDR / ACES color grading workflow in Nuke to generate 'Look Modification' (LMT) Luts for Oopen 3D Engine." + frame 16 + first_frame 16 + last_frame 32 + lock_range true + format "2048 1556 0 0 2048 1556 1 2K_Super_35(full-ap)" + proxy_type scale + proxy_format "1024 778 0 0 1024 778 1 1K_Super_35(full-ap)" + colorManagement OCIO + OCIOGPUSupport true + OCIO_config aces_1.0.3 + defaultViewerLUT "OCIO LUTs" + workingSpaceLUT scene_linear + monitorLut ACES/sRGB + monitorOutLUT "sRGB (ACES)" + int8Lut matte_paint + int16Lut texture_paint + logLut compositing_log + floatLut scene_linear +} +Read { + inputs 0 + file_type exr + file C:/Depot/o3de-engine/Gems/AtomLyIntegration/CommonFeatures/Tools/ColorGrading/LUTs/linear_lut_32.exr + format "1024 32 0 0 1024 32 1 " + origset true + colorspace scene_linear + name Read3 + xpos -1727 + ypos -81 +} +OCIOFileTransform { + file C:/Depot/o3de-engine/Tools/ColorGrading/OpenColorIO-Configs/aces_1.0.3/luts/Log2_48_nits_Shaper_to_linear.spi1d + working_space scene_linear + name OCIOFileTransform1 + xpos -1587 + ypos -45 +} +Viewer { + frame_range 16-32 + viewerProcess "sRGB (ACES)" + name Viewer3 + xpos -1586 + ypos 10 +} +Read { + inputs 0 + file_type exr + file C:/Depot/o3de-engine/Gems/AtomLyIntegration/CommonFeatures/Tools/ColorGrading/TestData/Nuke/HDR/displaymapperpassthrough.exr + format "1167 1618 0 0 1167 1618 1 " + origset true + colorspace scene_linear + name Read1 + xpos -1719 + ypos -421 +} +Read { + inputs 0 + file_type exr + file C:/Depot/o3de-engine/Gems/AtomLyIntegration/CommonFeatures/Tools/ColorGrading/LUTs/linear_lut_32.exr + format "1024 32 0 0 1024 32 1 " + origset true + colorspace "Utility - Log2 48 nits Shaper - AP1" + name Read2 + xpos -1720 + ypos -311 +} +Merge2 { + inputs 2 + Achannels {rgba.red rgba.green rgba.blue -rgba.alpha} + Bchannels {rgba.red rgba.green rgba.blue -rgba.alpha} + output {rgba.red rgba.green rgba.blue -rgba.alpha} + also_merge all + mix 0 + name Merge1 + selected true + xpos -1495 + ypos -340 +} +Viewer { + frame 16 + frame_range 16-32 + viewerProcess "sRGB (ACES)" + name Viewer2 + xpos -1495 + ypos -272 +} diff --git a/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Photoshop/Log2-48nits/CLT_grade.psd b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Photoshop/Log2-48nits/CLT_grade.psd new file mode 100644 index 0000000000..3718e0facf --- /dev/null +++ b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Photoshop/Log2-48nits/CLT_grade.psd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c0276e1d329cda3514f46a55fd1d3ce90fce617814198ab69d234f2c58c15882 +size 98742272 diff --git a/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Photoshop/Log2-48nits/LUT_layer_composite_hue-sat_grade.psd b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Photoshop/Log2-48nits/LUT_layer_composite_hue-sat_grade.psd new file mode 100644 index 0000000000..82eca8b3cc --- /dev/null +++ b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Photoshop/Log2-48nits/LUT_layer_composite_hue-sat_grade.psd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ce91088eaa54afab608bfcea6ab4009cbb3027cb83c76710a46470144e7d799d +size 98638424 diff --git a/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Photoshop/Log2-48nits/framebuffer_ACEScg_to_sRGB_icc.exr b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Photoshop/Log2-48nits/framebuffer_ACEScg_to_sRGB_icc.exr new file mode 100644 index 0000000000..9daa58f75c --- /dev/null +++ b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Photoshop/Log2-48nits/framebuffer_ACEScg_to_sRGB_icc.exr @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:facad074b84df87a0ab4baaf2bd95552e6eca3fed79a56875c9815f32d885b8a +size 11949493 diff --git a/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Photoshop/Log2-48nits/i_shaped/test_clt_32_LUT.exr b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Photoshop/Log2-48nits/i_shaped/test_clt_32_LUT.exr new file mode 100644 index 0000000000..a8c859147f --- /dev/null +++ b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Photoshop/Log2-48nits/i_shaped/test_clt_32_LUT.exr @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cfdfefb553fffd1a799a62e205fe13ebd88f3327d97d20cb900af6465ecc2dae +size 61384 diff --git a/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Photoshop/Log2-48nits/i_shaped/test_hue-sat_32_LUT.exr b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Photoshop/Log2-48nits/i_shaped/test_hue-sat_32_LUT.exr new file mode 100644 index 0000000000..ed8446a2ad --- /dev/null +++ b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Photoshop/Log2-48nits/i_shaped/test_hue-sat_32_LUT.exr @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dfced5571e7d681cc565a9be07fa199ecfee0d70ad4104ccb47c75a525737445 +size 96548 diff --git a/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Photoshop/Log2-48nits/o_invShaped/Test_3DL_32_LUT.azasset b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Photoshop/Log2-48nits/o_invShaped/Test_3DL_32_LUT.azasset new file mode 100644 index 0000000000..b643955084 --- /dev/null +++ b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Photoshop/Log2-48nits/o_invShaped/Test_3DL_32_LUT.azasset @@ -0,0 +1,4922 @@ +{ + "Type": "JsonSerialization", + "Version": 1, + "ClassName": "LookupTableAsset", + "ClassData": { + "Name": "LookupTable", + "Intervals": [0, 64, 128, 192, 256, 320, 384, 448, 512, 575, 639, 703, 767, 831, 895, 959, 1023], + "Values": [128, 193, 337, +96, 193, 353, +145, 241, 418, +177, 273, 514, +225, 273, 562, +337, 337, 707, +385, 385, 803, +450, 450, 883, +562, 514, 996, +594, 578, 1108, +691, 658, 1220, +739, 723, 1317, +803, 787, 1429, +915, 867, 1574, +980, 915, 1638, +1028, 996, 1766, +1092, 1044, 1847, +257, 353, 401, +289, 353, 434, +305, 369, 514, +273, 385, 594, +321, 385, 642, +353, 466, 771, +434, 482, 835, +498, 562, 964, +562, 594, 1060, +642, 658, 1140, +691, 723, 1253, +755, 787, 1349, +851, 835, 1477, +899, 899, 1574, +947, 964, 1670, +1044, 1044, 1783, +1124, 1076, 1863, +337, 530, 482, +385, 546, 530, +401, 562, 594, +401, 562, 691, +434, 594, 771, +450, 642, 867, +482, 642, 931, +562, 674, 1028, +610, 739, 1108, +658, 771, 1204, +739, 819, 1317, +851, 899, 1445, +867, 915, 1510, +947, 980, 1590, +1012, 1044, 1718, +1060, 1076, 1815, +1140, 1140, 1927, +466, 771, 642, +482, 771, 691, +482, 771, 755, +514, 787, 803, +514, 803, 915, +578, 803, 964, +626, 851, 1044, +658, 867, 1124, +707, 899, 1220, +771, 931, 1301, +787, 947, 1381, +883, 1012, 1477, +931, 1044, 1590, +1012, 1108, 1686, +1044, 1140, 1766, +1140, 1204, 1879, +1188, 1253, 1991, +691, 1012, 755, +674, 1012, 803, +674, 980, 883, +658, 980, 947, +658, 1012, 980, +642, 1012, 1092, +707, 1012, 1156, +755, 1060, 1269, +771, 1060, 1317, +835, 1108, 1397, +931, 1156, 1510, +947, 1156, 1574, +980, 1188, 1654, +1076, 1237, 1783, +1140, 1285, 1863, +1188, 1301, 1911, +1237, 1349, 2023, +851, 1220, 899, +803, 1204, 931, +835, 1204, 996, +819, 1204, 1060, +835, 1204, 1124, +867, 1204, 1156, +883, 1220, 1253, +899, 1237, 1349, +931, 1253, 1429, +996, 1269, 1510, +996, 1317, 1590, +1060, 1349, 1670, +1124, 1349, 1750, +1156, 1397, 1847, +1253, 1429, 1943, +1285, 1461, 2039, +1333, 1477, 2104, +980, 1413, 1012, +980, 1429, 1060, +980, 1413, 1108, +980, 1413, 1172, +996, 1397, 1237, +1012, 1429, 1333, +1044, 1429, 1365, +1076, 1445, 1445, +1044, 1445, 1526, +1124, 1477, 1622, +1140, 1493, 1702, +1156, 1493, 1750, +1188, 1558, 1863, +1285, 1558, 1943, +1349, 1590, 2023, +1381, 1622, 2104, +1461, 1654, 2216, +1156, 1606, 1124, +1140, 1622, 1172, +1140, 1606, 1253, +1172, 1622, 1317, +1188, 1622, 1381, +1172, 1638, 1445, +1188, 1638, 1510, +1220, 1638, 1542, +1237, 1638, 1606, +1301, 1654, 1718, +1333, 1670, 1799, +1365, 1702, 1879, +1397, 1734, 1975, +1429, 1734, 2039, +1477, 1766, 2104, +1526, 1815, 2216, +1558, 1831, 2296, +1317, 1815, 1285, +1285, 1831, 1317, +1301, 1831, 1365, +1317, 1815, 1397, +1333, 1799, 1445, +1349, 1831, 1542, +1381, 1831, 1622, +1381, 1815, 1654, +1413, 1863, 1734, +1461, 1863, 1799, +1477, 1863, 1895, +1510, 1895, 1991, +1542, 1895, 2023, +1638, 1943, 2136, +1670, 1927, 2184, +1670, 1943, 2264, +1734, 1991, 2377, +1542, 2007, 1381, +1510, 2023, 1381, +1526, 2023, 1445, +1542, 2023, 1526, +1542, 2007, 1590, +1574, 2023, 1654, +1558, 2023, 1686, +1606, 2039, 1766, +1606, 2023, 1815, +1654, 2056, 1863, +1686, 2072, 1943, +1718, 2088, 2072, +1734, 2104, 2168, +1766, 2120, 2248, +1847, 2136, 2296, +1927, 2152, 2361, +1975, 2184, 2457, +1734, 2232, 1493, +1766, 2248, 1510, +1734, 2232, 1526, +1766, 2248, 1590, +1766, 2232, 1686, +1815, 2232, 1766, +1799, 2232, 1815, +1847, 2264, 1927, +1831, 2264, 1927, +1879, 2280, 2007, +1895, 2280, 2072, +1911, 2280, 2136, +1959, 2312, 2232, +1975, 2329, 2345, +2023, 2361, 2425, +2072, 2329, 2441, +2104, 2361, 2537, +1975, 2457, 1654, +1943, 2457, 1638, +1959, 2457, 1670, +1975, 2441, 1734, +1991, 2441, 1799, +2007, 2441, 1895, +2023, 2441, 1943, +2023, 2441, 1991, +2023, 2441, 2072, +2072, 2473, 2168, +2104, 2473, 2200, +2120, 2473, 2264, +2184, 2489, 2296, +2216, 2505, 2377, +2200, 2521, 2537, +2248, 2553, 2634, +2264, 2537, 2682, +2152, 2650, 1734, +2168, 2634, 1783, +2120, 2650, 1815, +2136, 2650, 1879, +2168, 2650, 1959, +2200, 2650, 2023, +2216, 2650, 2088, +2200, 2666, 2120, +2248, 2682, 2200, +2232, 2682, 2264, +2248, 2682, 2329, +2280, 2682, 2377, +2312, 2698, 2457, +2345, 2714, 2537, +2361, 2714, 2602, +2393, 2730, 2714, +2425, 2762, 2810, +2312, 2858, 1895, +2329, 2858, 1895, +2329, 2875, 1959, +2296, 2858, 1991, +2329, 2875, 2056, +2345, 2858, 2120, +2377, 2875, 2184, +2377, 2875, 2296, +2393, 2891, 2329, +2409, 2875, 2361, +2473, 2875, 2441, +2441, 2875, 2489, +2489, 2891, 2553, +2521, 2907, 2618, +2537, 2907, 2698, +2585, 2923, 2778, +2618, 2955, 2907, +2553, 3067, 2023, +2537, 3067, 2056, +2489, 3067, 2088, +2521, 3067, 2120, +2537, 3051, 2184, +2537, 3051, 2280, +2585, 3067, 2312, +2602, 3051, 2377, +2602, 3083, 2425, +2602, 3067, 2505, +2618, 3083, 2553, +2634, 3083, 2618, +2666, 3083, 2666, +2698, 3083, 2714, +2730, 3115, 2794, +2746, 3115, 2907, +2778, 3131, 2987, +2714, 3276, 2184, +2714, 3276, 2216, +2682, 3292, 2232, +2698, 3292, 2280, +2698, 3292, 2296, +2746, 3276, 2393, +2730, 3292, 2457, +2762, 3292, 2521, +2762, 3276, 2585, +2778, 3260, 2634, +2746, 3260, 2698, +2810, 3276, 2746, +2842, 3292, 2842, +2826, 3292, 2858, +2858, 3292, 2907, +2875, 3308, 3003, +2923, 3324, 3067, +2891, 3501, 2345, +2891, 3485, 2377, +2875, 3485, 2361, +2842, 3501, 2377, +2858, 3485, 2425, +2907, 3501, 2521, +2907, 3485, 2602, +2939, 3485, 2650, +2939, 3469, 2698, +2955, 3501, 2762, +2955, 3485, 2810, +3035, 3485, 2891, +3019, 3501, 2971, +3067, 3517, 3051, +3067, 3517, 3115, +3115, 3533, 3164, +3099, 3549, 3244, +273, 225, 353, +273, 241, 385, +225, 273, 450, +257, 257, 514, +305, 321, 626, +369, 353, 707, +434, 434, 819, +498, 482, 915, +562, 562, 1028, +594, 594, 1124, +723, 658, 1220, +755, 723, 1333, +819, 819, 1445, +899, 883, 1590, +980, 915, 1638, +1060, 1012, 1750, +1108, 1060, 1863, +337, 353, 401, +337, 369, 450, +321, 401, 546, +337, 401, 594, +369, 434, 707, +418, 466, 771, +466, 514, 867, +546, 578, 996, +578, 626, 1076, +691, 674, 1156, +723, 739, 1269, +755, 803, 1365, +867, 851, 1493, +931, 915, 1558, +996, 980, 1670, +1060, 1044, 1783, +1124, 1076, 1863, +434, 546, 482, +418, 562, 546, +466, 594, 626, +466, 594, 707, +466, 642, 819, +482, 642, 867, +514, 674, 964, +578, 707, 1028, +626, 755, 1140, +707, 787, 1220, +755, 835, 1333, +835, 883, 1429, +915, 931, 1510, +947, 996, 1606, +1028, 1060, 1734, +1076, 1076, 1799, +1140, 1140, 1927, +562, 771, 594, +530, 787, 707, +546, 803, 771, +578, 803, 803, +578, 803, 867, +594, 819, 980, +642, 867, 1076, +658, 883, 1140, +739, 915, 1237, +771, 931, 1301, +787, 980, 1413, +883, 1012, 1493, +947, 1060, 1574, +996, 1108, 1670, +1060, 1140, 1783, +1140, 1204, 1879, +1220, 1237, 1991, +723, 996, 755, +691, 996, 819, +707, 996, 883, +674, 1012, 964, +707, 1012, 996, +723, 1028, 1092, +723, 1044, 1172, +787, 1060, 1253, +819, 1092, 1317, +851, 1124, 1413, +931, 1156, 1510, +964, 1172, 1590, +1012, 1172, 1654, +1076, 1237, 1783, +1140, 1285, 1863, +1220, 1333, 1943, +1285, 1349, 2039, +851, 1220, 867, +835, 1220, 931, +835, 1220, 996, +835, 1220, 1076, +851, 1204, 1140, +867, 1204, 1156, +883, 1220, 1253, +915, 1253, 1381, +980, 1269, 1445, +996, 1285, 1510, +1012, 1317, 1606, +1108, 1349, 1686, +1124, 1365, 1750, +1156, 1381, 1847, +1237, 1413, 1927, +1285, 1445, 2039, +1349, 1493, 2104, +1028, 1413, 996, +996, 1413, 1044, +1012, 1413, 1140, +1028, 1413, 1188, +1044, 1413, 1253, +1012, 1413, 1333, +1060, 1429, 1333, +1076, 1445, 1445, +1060, 1477, 1542, +1108, 1477, 1606, +1140, 1493, 1702, +1172, 1510, 1783, +1220, 1542, 1863, +1285, 1558, 1959, +1349, 1606, 2023, +1413, 1622, 2120, +1477, 1670, 2232, +1188, 1606, 1156, +1140, 1622, 1172, +1156, 1606, 1220, +1156, 1606, 1317, +1172, 1606, 1381, +1188, 1622, 1461, +1220, 1622, 1510, +1237, 1654, 1558, +1253, 1654, 1622, +1285, 1686, 1734, +1333, 1670, 1799, +1381, 1718, 1895, +1397, 1718, 1959, +1429, 1734, 2039, +1477, 1766, 2104, +1526, 1815, 2200, +1558, 1831, 2296, +1333, 1815, 1253, +1349, 1815, 1301, +1317, 1831, 1349, +1333, 1815, 1397, +1365, 1815, 1493, +1365, 1831, 1558, +1365, 1815, 1590, +1397, 1847, 1686, +1429, 1847, 1718, +1461, 1863, 1799, +1477, 1879, 1911, +1493, 1895, 2007, +1574, 1927, 2039, +1670, 1927, 2136, +1686, 1927, 2200, +1670, 1943, 2264, +1718, 1991, 2377, +1558, 2023, 1365, +1542, 2023, 1381, +1542, 2023, 1445, +1558, 2023, 1510, +1574, 2023, 1606, +1574, 2023, 1654, +1622, 2023, 1702, +1606, 2039, 1766, +1622, 2056, 1831, +1654, 2056, 1863, +1686, 2056, 1943, +1718, 2088, 2056, +1718, 2088, 2152, +1766, 2136, 2248, +1879, 2120, 2264, +1927, 2152, 2361, +1975, 2184, 2473, +1799, 2232, 1477, +1783, 2232, 1510, +1766, 2232, 1558, +1783, 2232, 1622, +1799, 2216, 1670, +1815, 2232, 1766, +1815, 2248, 1815, +1847, 2264, 1895, +1879, 2280, 1975, +1879, 2296, 2023, +1911, 2296, 2088, +1911, 2280, 2136, +2007, 2312, 2248, +1975, 2329, 2345, +2056, 2345, 2393, +2072, 2345, 2457, +2120, 2361, 2553, +2007, 2457, 1654, +1991, 2473, 1654, +1959, 2457, 1670, +1975, 2441, 1734, +1991, 2441, 1799, +2007, 2441, 1863, +2039, 2457, 1959, +2072, 2473, 2039, +2039, 2457, 2088, +2072, 2473, 2168, +2120, 2489, 2216, +2120, 2457, 2264, +2168, 2505, 2361, +2200, 2505, 2441, +2216, 2537, 2553, +2232, 2537, 2618, +2248, 2537, 2682, +2168, 2666, 1750, +2168, 2650, 1799, +2120, 2650, 1815, +2168, 2666, 1879, +2168, 2650, 1959, +2184, 2650, 2023, +2216, 2650, 2056, +2216, 2666, 2136, +2216, 2650, 2184, +2248, 2666, 2248, +2248, 2682, 2345, +2280, 2682, 2377, +2312, 2698, 2457, +2329, 2698, 2521, +2377, 2730, 2618, +2393, 2746, 2714, +2425, 2762, 2794, +2345, 2842, 1895, +2329, 2858, 1895, +2296, 2858, 1943, +2312, 2875, 1959, +2329, 2875, 2056, +2345, 2858, 2120, +2377, 2875, 2200, +2393, 2875, 2264, +2425, 2875, 2329, +2409, 2875, 2361, +2473, 2875, 2441, +2489, 2875, 2505, +2505, 2891, 2553, +2505, 2875, 2602, +2553, 2907, 2698, +2585, 2923, 2778, +2602, 2955, 2891, +2537, 3067, 2023, +2569, 3067, 2056, +2505, 3067, 2056, +2521, 3067, 2120, +2537, 3067, 2184, +2569, 3083, 2264, +2585, 3067, 2329, +2585, 3051, 2377, +2602, 3083, 2425, +2602, 3067, 2521, +2634, 3083, 2602, +2618, 3067, 2618, +2666, 3083, 2666, +2698, 3099, 2714, +2730, 3115, 2794, +2778, 3131, 2891, +2778, 3131, 2987, +2714, 3276, 2184, +2746, 3308, 2216, +2698, 3308, 2232, +2714, 3308, 2312, +2714, 3308, 2296, +2730, 3292, 2361, +2730, 3292, 2457, +2778, 3276, 2553, +2778, 3276, 2585, +2778, 3260, 2634, +2762, 3276, 2698, +2794, 3260, 2730, +2826, 3292, 2826, +2810, 3276, 2858, +2842, 3292, 2923, +2875, 3308, 3003, +2939, 3340, 3083, +2891, 3485, 2345, +2875, 3485, 2329, +2875, 3485, 2377, +2842, 3501, 2377, +2891, 3517, 2457, +2907, 3501, 2521, +2907, 3485, 2569, +2907, 3485, 2666, +2939, 3485, 2714, +2971, 3485, 2778, +3019, 3501, 2826, +3035, 3485, 2891, +3035, 3517, 2971, +3051, 3517, 3051, +3083, 3533, 3131, +3099, 3517, 3164, +3148, 3533, 3212, +385, 257, 369, +353, 289, 401, +369, 305, 482, +401, 337, 594, +401, 337, 642, +434, 401, 771, +482, 466, 835, +562, 530, 947, +578, 578, 1060, +674, 626, 1124, +723, 707, 1253, +803, 755, 1349, +883, 835, 1477, +915, 883, 1558, +1044, 947, 1670, +1076, 1012, 1766, +1108, 1060, 1863, +498, 369, 385, +450, 401, 498, +434, 434, 578, +401, 466, 626, +450, 498, 723, +514, 514, 803, +562, 594, 931, +578, 610, 996, +642, 642, 1076, +691, 707, 1188, +755, 771, 1285, +835, 835, 1413, +867, 867, 1477, +964, 915, 1574, +996, 996, 1670, +1108, 1060, 1815, +1140, 1108, 1895, +562, 594, 514, +562, 610, 578, +530, 610, 674, +514, 642, 739, +514, 626, 803, +562, 674, 883, +610, 707, 980, +658, 755, 1076, +674, 771, 1156, +755, 819, 1237, +819, 883, 1365, +851, 915, 1445, +931, 964, 1542, +980, 1012, 1622, +1076, 1076, 1766, +1076, 1092, 1799, +1172, 1172, 1959, +658, 787, 610, +642, 803, 658, +610, 803, 755, +626, 819, 819, +642, 835, 915, +674, 851, 980, +707, 883, 1092, +723, 899, 1172, +771, 947, 1269, +771, 964, 1349, +851, 996, 1445, +915, 1044, 1493, +996, 1092, 1606, +1012, 1108, 1686, +1092, 1172, 1783, +1140, 1220, 1895, +1253, 1269, 1959, +771, 1012, 755, +771, 1012, 803, +723, 1012, 899, +739, 1028, 964, +755, 1028, 1012, +771, 1044, 1108, +787, 1060, 1204, +819, 1092, 1285, +851, 1092, 1333, +915, 1140, 1429, +931, 1156, 1510, +996, 1172, 1590, +1044, 1220, 1702, +1108, 1253, 1783, +1172, 1301, 1847, +1253, 1317, 1959, +1285, 1365, 2023, +883, 1204, 835, +915, 1220, 931, +867, 1220, 1012, +883, 1220, 1060, +899, 1220, 1156, +931, 1220, 1188, +947, 1237, 1285, +947, 1253, 1365, +980, 1269, 1445, +1012, 1285, 1526, +1060, 1333, 1622, +1092, 1333, 1670, +1140, 1381, 1766, +1220, 1397, 1863, +1269, 1445, 1959, +1317, 1477, 2039, +1381, 1477, 2120, +1060, 1413, 996, +1044, 1413, 1028, +1028, 1429, 1124, +1044, 1429, 1172, +1060, 1429, 1269, +1076, 1445, 1333, +1108, 1445, 1365, +1076, 1445, 1445, +1092, 1461, 1542, +1124, 1493, 1622, +1220, 1526, 1734, +1204, 1542, 1799, +1237, 1558, 1879, +1317, 1574, 1943, +1365, 1606, 2039, +1413, 1622, 2120, +1477, 1654, 2200, +1188, 1606, 1108, +1204, 1606, 1188, +1172, 1622, 1253, +1188, 1622, 1301, +1237, 1622, 1397, +1220, 1638, 1429, +1253, 1654, 1526, +1285, 1654, 1574, +1285, 1654, 1622, +1317, 1670, 1734, +1349, 1702, 1815, +1381, 1718, 1895, +1429, 1718, 1959, +1445, 1750, 2023, +1493, 1783, 2120, +1574, 1815, 2216, +1622, 1847, 2312, +1365, 1815, 1253, +1365, 1815, 1285, +1333, 1815, 1365, +1365, 1815, 1397, +1397, 1831, 1477, +1397, 1815, 1558, +1413, 1831, 1622, +1413, 1863, 1702, +1461, 1863, 1750, +1477, 1879, 1815, +1493, 1879, 1911, +1542, 1879, 1975, +1606, 1911, 2039, +1670, 1927, 2136, +1686, 1927, 2200, +1686, 1975, 2280, +1766, 2007, 2361, +1558, 2023, 1365, +1574, 2007, 1381, +1542, 2039, 1461, +1558, 2023, 1510, +1590, 2039, 1590, +1606, 2023, 1654, +1638, 2056, 1718, +1638, 2039, 1766, +1670, 2056, 1847, +1702, 2056, 1879, +1702, 2088, 1991, +1766, 2088, 2072, +1783, 2104, 2152, +1847, 2136, 2216, +1879, 2120, 2264, +1911, 2136, 2345, +1975, 2184, 2473, +1799, 2248, 1477, +1783, 2232, 1477, +1799, 2264, 1558, +1799, 2248, 1638, +1799, 2216, 1670, +1831, 2232, 1750, +1831, 2216, 1799, +1863, 2264, 1895, +1895, 2280, 1943, +1911, 2280, 2023, +1959, 2296, 2072, +1975, 2296, 2120, +2007, 2329, 2248, +2039, 2329, 2329, +2056, 2345, 2393, +2088, 2361, 2473, +2120, 2377, 2553, +2007, 2457, 1654, +2023, 2457, 1622, +1975, 2457, 1638, +2007, 2457, 1718, +2007, 2441, 1799, +2039, 2425, 1879, +2039, 2457, 1927, +2072, 2457, 2039, +2039, 2457, 2088, +2072, 2473, 2136, +2104, 2473, 2200, +2168, 2489, 2232, +2152, 2489, 2345, +2200, 2521, 2441, +2216, 2521, 2537, +2248, 2553, 2634, +2264, 2553, 2698, +2168, 2666, 1750, +2152, 2666, 1783, +2152, 2666, 1815, +2168, 2650, 1863, +2200, 2682, 1943, +2216, 2666, 2007, +2216, 2650, 2056, +2264, 2682, 2152, +2248, 2682, 2216, +2264, 2682, 2264, +2296, 2682, 2345, +2280, 2682, 2377, +2312, 2698, 2457, +2329, 2698, 2521, +2377, 2730, 2618, +2393, 2746, 2730, +2425, 2762, 2794, +2345, 2875, 1911, +2345, 2875, 1911, +2345, 2891, 1943, +2345, 2875, 1991, +2345, 2875, 2039, +2345, 2875, 2120, +2409, 2875, 2232, +2409, 2891, 2280, +2425, 2875, 2329, +2457, 2891, 2377, +2489, 2891, 2441, +2505, 2891, 2521, +2521, 2875, 2537, +2569, 2907, 2634, +2553, 2907, 2698, +2618, 2907, 2778, +2618, 2955, 2907, +2553, 3067, 2039, +2569, 3067, 2056, +2537, 3067, 2072, +2521, 3067, 2120, +2553, 3083, 2200, +2553, 3067, 2248, +2585, 3067, 2312, +2618, 3083, 2409, +2634, 3067, 2457, +2634, 3099, 2505, +2634, 3083, 2585, +2666, 3083, 2634, +2666, 3099, 2682, +2730, 3115, 2746, +2746, 3131, 2810, +2778, 3131, 2891, +2778, 3131, 2971, +2746, 3308, 2200, +2730, 3292, 2200, +2682, 3292, 2216, +2714, 3308, 2296, +2746, 3308, 2345, +2762, 3292, 2393, +2778, 3276, 2457, +2746, 3276, 2521, +2762, 3276, 2569, +2778, 3260, 2634, +2794, 3276, 2714, +2794, 3276, 2746, +2842, 3292, 2794, +2875, 3292, 2875, +2858, 3292, 2907, +2891, 3308, 2987, +2923, 3340, 3099, +2891, 3485, 2345, +2891, 3485, 2345, +2939, 3501, 2361, +2875, 3485, 2409, +2858, 3485, 2425, +2907, 3501, 2489, +2907, 3485, 2569, +2923, 3485, 2634, +2955, 3501, 2714, +2987, 3485, 2746, +3019, 3501, 2842, +3051, 3517, 2923, +3067, 3501, 2971, +3051, 3517, 3051, +3099, 3533, 3131, +3131, 3533, 3180, +3164, 3549, 3228, +594, 321, 466, +530, 369, 498, +498, 401, 562, +530, 418, 658, +562, 450, 707, +546, 482, 787, +594, 562, 915, +642, 594, 996, +707, 626, 1076, +755, 707, 1204, +787, 755, 1285, +851, 803, 1397, +899, 867, 1493, +1012, 915, 1574, +1060, 980, 1670, +1108, 1060, 1815, +1188, 1108, 1895, +658, 450, 466, +610, 450, 546, +546, 482, 594, +578, 514, 674, +562, 562, 771, +594, 594, 867, +594, 610, 931, +642, 642, 1028, +707, 723, 1124, +739, 739, 1204, +803, 803, 1317, +899, 883, 1445, +931, 899, 1510, +996, 947, 1606, +1060, 1012, 1702, +1092, 1076, 1783, +1188, 1140, 1927, +658, 626, 514, +674, 626, 562, +642, 642, 723, +658, 658, 787, +626, 691, 851, +610, 723, 947, +658, 739, 996, +707, 787, 1092, +739, 803, 1172, +803, 867, 1301, +867, 883, 1381, +883, 915, 1445, +947, 980, 1542, +1028, 1028, 1654, +1092, 1092, 1750, +1156, 1124, 1863, +1204, 1188, 1943, +755, 835, 642, +755, 819, 674, +739, 819, 755, +739, 851, 867, +723, 867, 931, +755, 899, 1044, +787, 915, 1108, +819, 947, 1204, +819, 964, 1269, +851, 996, 1349, +899, 1012, 1413, +964, 1076, 1526, +1028, 1092, 1622, +1076, 1140, 1718, +1156, 1188, 1815, +1220, 1237, 1927, +1253, 1269, 1975, +835, 1028, 739, +835, 1012, 787, +819, 1028, 867, +803, 1044, 996, +835, 1060, 1060, +851, 1076, 1156, +883, 1092, 1188, +883, 1108, 1269, +931, 1124, 1381, +964, 1140, 1461, +980, 1172, 1526, +1028, 1204, 1622, +1092, 1253, 1702, +1140, 1285, 1799, +1220, 1301, 1863, +1285, 1349, 1975, +1349, 1397, 2072, +980, 1220, 867, +964, 1220, 915, +964, 1237, 996, +931, 1220, 1076, +947, 1220, 1156, +980, 1237, 1204, +996, 1253, 1301, +1028, 1269, 1381, +1060, 1285, 1461, +1044, 1317, 1558, +1092, 1349, 1622, +1140, 1349, 1686, +1188, 1381, 1783, +1253, 1429, 1863, +1301, 1461, 1959, +1381, 1493, 2056, +1429, 1526, 2120, +1124, 1429, 980, +1108, 1429, 1028, +1124, 1429, 1108, +1108, 1445, 1204, +1124, 1461, 1301, +1124, 1445, 1349, +1108, 1445, 1365, +1156, 1477, 1493, +1172, 1493, 1558, +1188, 1493, 1654, +1204, 1526, 1734, +1220, 1558, 1815, +1269, 1558, 1895, +1365, 1590, 1959, +1397, 1606, 2039, +1445, 1638, 2104, +1510, 1686, 2216, +1237, 1638, 1124, +1269, 1622, 1188, +1285, 1638, 1220, +1253, 1638, 1301, +1285, 1622, 1381, +1269, 1638, 1445, +1285, 1654, 1542, +1349, 1670, 1558, +1349, 1670, 1622, +1365, 1686, 1750, +1397, 1718, 1847, +1413, 1718, 1911, +1461, 1750, 1991, +1461, 1766, 2039, +1558, 1815, 2152, +1574, 1815, 2232, +1638, 1863, 2345, +1413, 1831, 1220, +1429, 1831, 1285, +1445, 1831, 1349, +1397, 1831, 1397, +1429, 1831, 1477, +1445, 1847, 1574, +1429, 1847, 1638, +1477, 1863, 1718, +1493, 1863, 1750, +1526, 1895, 1831, +1542, 1895, 1895, +1574, 1911, 1975, +1654, 1927, 2072, +1686, 1943, 2152, +1718, 1959, 2232, +1766, 1991, 2329, +1783, 1991, 2361, +1622, 2039, 1349, +1638, 2039, 1413, +1654, 2056, 1461, +1606, 2039, 1542, +1638, 2039, 1574, +1654, 2056, 1670, +1670, 2039, 1718, +1686, 2039, 1783, +1702, 2072, 1863, +1718, 2072, 1911, +1750, 2088, 1975, +1750, 2088, 2072, +1831, 2136, 2152, +1831, 2120, 2200, +1895, 2136, 2280, +1959, 2136, 2361, +1991, 2200, 2473, +1847, 2248, 1477, +1847, 2248, 1493, +1831, 2248, 1526, +1815, 2248, 1606, +1831, 2248, 1670, +1863, 2264, 1783, +1879, 2264, 1847, +1911, 2264, 1879, +1927, 2280, 1959, +1927, 2296, 2023, +1975, 2312, 2072, +1991, 2312, 2152, +2007, 2329, 2248, +2056, 2361, 2345, +2056, 2345, 2393, +2136, 2361, 2489, +2136, 2345, 2537, +2023, 2457, 1590, +2072, 2457, 1638, +2039, 2441, 1654, +2007, 2441, 1734, +2056, 2457, 1815, +2056, 2441, 1863, +2104, 2473, 1959, +2072, 2457, 2007, +2104, 2473, 2072, +2120, 2473, 2152, +2152, 2473, 2216, +2168, 2505, 2280, +2184, 2505, 2345, +2184, 2521, 2473, +2216, 2537, 2553, +2264, 2553, 2602, +2329, 2553, 2682, +2200, 2650, 1750, +2232, 2666, 1799, +2216, 2666, 1815, +2184, 2666, 1847, +2216, 2682, 1959, +2232, 2682, 2023, +2264, 2650, 2072, +2280, 2682, 2152, +2280, 2666, 2216, +2280, 2698, 2280, +2296, 2682, 2345, +2345, 2698, 2393, +2361, 2714, 2473, +2409, 2714, 2521, +2425, 2714, 2585, +2409, 2762, 2730, +2441, 2762, 2810, +2393, 2891, 1927, +2393, 2891, 1927, +2393, 2891, 1959, +2361, 2891, 2007, +2377, 2875, 2072, +2409, 2875, 2152, +2425, 2875, 2216, +2441, 2875, 2312, +2473, 2891, 2361, +2489, 2875, 2377, +2473, 2875, 2441, +2505, 2891, 2521, +2553, 2907, 2569, +2553, 2891, 2618, +2585, 2907, 2698, +2634, 2923, 2794, +2634, 2939, 2891, +2553, 3083, 2039, +2569, 3083, 2039, +2585, 3083, 2120, +2553, 3083, 2104, +2553, 3083, 2168, +2569, 3067, 2248, +2585, 3051, 2280, +2618, 3035, 2377, +2634, 3083, 2473, +2634, 3083, 2505, +2650, 3067, 2569, +2682, 3099, 2650, +2730, 3099, 2698, +2714, 3115, 2730, +2762, 3131, 2810, +2794, 3148, 2891, +2794, 3148, 2987, +2778, 3292, 2200, +2746, 3308, 2200, +2762, 3292, 2248, +2730, 3308, 2280, +2746, 3292, 2296, +2762, 3276, 2361, +2778, 3292, 2457, +2794, 3276, 2521, +2810, 3276, 2585, +2778, 3260, 2634, +2826, 3292, 2698, +2826, 3292, 2730, +2842, 3276, 2794, +2875, 3292, 2875, +2907, 3308, 2923, +2955, 3324, 3003, +2939, 3340, 3083, +2955, 3501, 2329, +2891, 3485, 2345, +2923, 3517, 2329, +2939, 3501, 2393, +2907, 3501, 2457, +2923, 3517, 2505, +2923, 3517, 2602, +2955, 3501, 2666, +2987, 3485, 2730, +3019, 3485, 2762, +3051, 3485, 2826, +3051, 3517, 2923, +3067, 3501, 2971, +3099, 3517, 3051, +3083, 3533, 3131, +3115, 3533, 3180, +3164, 3549, 3228, +771, 418, 498, +739, 450, 562, +674, 498, 642, +658, 530, 707, +707, 562, 819, +691, 578, 883, +674, 626, 964, +739, 658, 1028, +755, 707, 1124, +819, 755, 1237, +867, 819, 1333, +931, 867, 1429, +980, 899, 1510, +1076, 964, 1606, +1108, 1028, 1718, +1140, 1060, 1799, +1204, 1124, 1927, +851, 530, 530, +819, 546, 610, +723, 594, 691, +691, 610, 755, +707, 626, 835, +723, 626, 931, +755, 691, 980, +755, 723, 1060, +803, 771, 1172, +867, 819, 1269, +915, 867, 1381, +964, 899, 1461, +1012, 947, 1526, +1044, 996, 1638, +1124, 1060, 1734, +1156, 1092, 1831, +1253, 1188, 1959, +915, 674, 498, +883, 691, 562, +819, 691, 755, +739, 739, 835, +755, 755, 899, +771, 771, 980, +771, 803, 1044, +803, 835, 1140, +851, 867, 1220, +883, 899, 1317, +899, 931, 1413, +980, 980, 1493, +1028, 1044, 1606, +1092, 1076, 1686, +1140, 1108, 1766, +1188, 1172, 1879, +1285, 1220, 1991, +899, 883, 658, +899, 867, 707, +915, 883, 787, +883, 899, 947, +867, 931, 996, +835, 931, 1076, +835, 947, 1124, +867, 980, 1237, +883, 996, 1317, +947, 1044, 1397, +964, 1044, 1461, +1028, 1108, 1574, +1076, 1140, 1638, +1124, 1172, 1734, +1188, 1220, 1847, +1269, 1253, 1911, +1317, 1301, 2007, +964, 1044, 771, +947, 1060, 851, +964, 1044, 899, +947, 1076, 1012, +931, 1076, 1076, +931, 1108, 1156, +947, 1124, 1237, +996, 1156, 1333, +980, 1172, 1397, +1028, 1156, 1445, +1076, 1204, 1558, +1108, 1237, 1638, +1140, 1253, 1718, +1204, 1301, 1799, +1285, 1333, 1879, +1301, 1349, 1959, +1365, 1413, 2088, +1076, 1253, 883, +1060, 1253, 947, +1092, 1253, 996, +1076, 1269, 1092, +1044, 1269, 1172, +1092, 1285, 1269, +1060, 1285, 1349, +1108, 1317, 1429, +1092, 1317, 1493, +1140, 1349, 1558, +1156, 1365, 1622, +1172, 1397, 1702, +1237, 1413, 1799, +1317, 1445, 1895, +1349, 1477, 1975, +1397, 1510, 2088, +1477, 1558, 2136, +1220, 1445, 1012, +1204, 1445, 1028, +1188, 1461, 1124, +1188, 1445, 1204, +1156, 1445, 1269, +1156, 1477, 1381, +1172, 1477, 1397, +1204, 1493, 1510, +1220, 1493, 1574, +1253, 1526, 1654, +1237, 1542, 1750, +1301, 1558, 1847, +1349, 1574, 1847, +1413, 1622, 1975, +1445, 1654, 2056, +1510, 1670, 2152, +1542, 1686, 2232, +1333, 1654, 1092, +1349, 1638, 1156, +1333, 1654, 1204, +1349, 1654, 1301, +1317, 1654, 1381, +1333, 1654, 1477, +1365, 1686, 1542, +1381, 1670, 1574, +1413, 1686, 1686, +1429, 1702, 1750, +1461, 1734, 1879, +1461, 1750, 1911, +1493, 1766, 1991, +1526, 1799, 2072, +1558, 1815, 2168, +1622, 1847, 2232, +1686, 1895, 2312, +1461, 1847, 1220, +1493, 1847, 1269, +1510, 1847, 1333, +1493, 1847, 1397, +1461, 1847, 1461, +1526, 1863, 1574, +1510, 1863, 1638, +1526, 1879, 1702, +1558, 1879, 1750, +1590, 1895, 1783, +1574, 1911, 1927, +1606, 1927, 2007, +1686, 1927, 2072, +1718, 1927, 2152, +1718, 1975, 2232, +1783, 2007, 2312, +1815, 2023, 2393, +1670, 2039, 1333, +1686, 2056, 1381, +1670, 2056, 1445, +1670, 2056, 1493, +1686, 2072, 1574, +1702, 2056, 1686, +1734, 2072, 1766, +1718, 2072, 1815, +1750, 2088, 1879, +1799, 2104, 1943, +1831, 2104, 1975, +1815, 2136, 2088, +1863, 2136, 2152, +1927, 2136, 2232, +1943, 2136, 2296, +2007, 2184, 2409, +2023, 2232, 2505, +1895, 2280, 1461, +1879, 2280, 1493, +1895, 2264, 1558, +1895, 2280, 1622, +1895, 2280, 1702, +1911, 2280, 1815, +1927, 2264, 1863, +1975, 2296, 1911, +1943, 2296, 1975, +1975, 2296, 2039, +2007, 2312, 2088, +2039, 2329, 2168, +2088, 2361, 2296, +2088, 2345, 2345, +2104, 2361, 2409, +2136, 2361, 2489, +2184, 2393, 2585, +2088, 2473, 1622, +2088, 2489, 1622, +2088, 2473, 1654, +2104, 2473, 1718, +2072, 2473, 1799, +2072, 2457, 1895, +2136, 2473, 1991, +2136, 2489, 2039, +2136, 2473, 2088, +2152, 2489, 2136, +2184, 2505, 2216, +2216, 2521, 2264, +2248, 2521, 2329, +2264, 2537, 2473, +2296, 2537, 2505, +2312, 2537, 2585, +2329, 2569, 2698, +2264, 2682, 1750, +2264, 2682, 1783, +2248, 2666, 1799, +2248, 2698, 1879, +2216, 2682, 1927, +2264, 2666, 2023, +2280, 2682, 2088, +2312, 2682, 2152, +2280, 2682, 2216, +2312, 2682, 2280, +2345, 2698, 2377, +2377, 2698, 2409, +2377, 2714, 2489, +2409, 2730, 2569, +2441, 2746, 2650, +2473, 2778, 2762, +2473, 2762, 2778, +2409, 2891, 1911, +2393, 2891, 1927, +2425, 2891, 1927, +2425, 2891, 1991, +2409, 2907, 2072, +2473, 2891, 2136, +2473, 2891, 2232, +2489, 2891, 2296, +2505, 2891, 2361, +2537, 2875, 2393, +2521, 2891, 2457, +2521, 2875, 2505, +2585, 2891, 2569, +2569, 2907, 2634, +2618, 2939, 2730, +2634, 2939, 2810, +2634, 2939, 2891, +2602, 3067, 2007, +2618, 3099, 2056, +2602, 3067, 2072, +2585, 3083, 2120, +2602, 3083, 2216, +2618, 3083, 2280, +2650, 3083, 2312, +2650, 3067, 2361, +2666, 3067, 2473, +2682, 3099, 2521, +2682, 3083, 2569, +2698, 3115, 2666, +2730, 3115, 2714, +2762, 3115, 2746, +2778, 3115, 2810, +2842, 3148, 2923, +2794, 3148, 3003, +2746, 3292, 2168, +2778, 3292, 2216, +2778, 3292, 2216, +2762, 3292, 2264, +2762, 3308, 2312, +2762, 3292, 2361, +2778, 3276, 2425, +2794, 3260, 2489, +2794, 3260, 2569, +2826, 3276, 2650, +2858, 3308, 2682, +2842, 3276, 2762, +2875, 3292, 2842, +2891, 3308, 2891, +2939, 3324, 2939, +2955, 3324, 3019, +2987, 3340, 3083, +2907, 3501, 2329, +2923, 3501, 2329, +2939, 3501, 2361, +2987, 3517, 2409, +2923, 3517, 2473, +2955, 3517, 2537, +2955, 3501, 2585, +3003, 3501, 2634, +3035, 3501, 2746, +3035, 3501, 2778, +3067, 3501, 2842, +3099, 3517, 2923, +3067, 3517, 2987, +3083, 3517, 3051, +3131, 3533, 3131, +3131, 3533, 3180, +3164, 3549, 3228, +996, 514, 562, +947, 546, 626, +819, 578, 723, +803, 626, 771, +803, 642, 851, +819, 674, 947, +819, 707, 1012, +867, 739, 1108, +883, 787, 1188, +947, 819, 1301, +964, 851, 1365, +1012, 899, 1461, +1076, 947, 1542, +1124, 1028, 1654, +1156, 1060, 1734, +1220, 1124, 1863, +1285, 1188, 1959, +1028, 594, 562, +996, 610, 658, +899, 674, 787, +835, 723, 851, +835, 723, 883, +851, 739, 980, +851, 755, 1044, +883, 803, 1140, +883, 835, 1220, +947, 883, 1317, +980, 899, 1397, +1060, 964, 1493, +1076, 1012, 1590, +1108, 1060, 1670, +1172, 1108, 1783, +1253, 1172, 1879, +1317, 1220, 2007, +1092, 723, 514, +1028, 739, 658, +980, 755, 803, +883, 803, 883, +899, 851, 964, +915, 851, 1044, +931, 867, 1140, +931, 899, 1188, +947, 915, 1269, +964, 947, 1349, +1012, 980, 1413, +1044, 1044, 1526, +1092, 1076, 1622, +1140, 1124, 1734, +1204, 1172, 1815, +1269, 1220, 1927, +1349, 1253, 1975, +1076, 899, 642, +1108, 899, 707, +1108, 899, 771, +1028, 931, 980, +931, 947, 1028, +964, 980, 1140, +947, 996, 1204, +964, 1028, 1269, +996, 1044, 1333, +1044, 1076, 1413, +1076, 1108, 1510, +1108, 1124, 1574, +1156, 1172, 1686, +1220, 1204, 1766, +1269, 1269, 1847, +1349, 1301, 1959, +1365, 1333, 2023, +1092, 1092, 787, +1108, 1124, 851, +1108, 1124, 931, +1108, 1092, 964, +1092, 1140, 1156, +1060, 1140, 1172, +1044, 1172, 1269, +1044, 1156, 1317, +1076, 1204, 1413, +1108, 1237, 1493, +1140, 1253, 1574, +1188, 1285, 1670, +1269, 1301, 1734, +1285, 1349, 1831, +1349, 1365, 1927, +1381, 1381, 2007, +1429, 1461, 2104, +1220, 1285, 915, +1204, 1285, 964, +1204, 1301, 1060, +1188, 1285, 1124, +1172, 1301, 1220, +1172, 1333, 1317, +1156, 1333, 1381, +1172, 1333, 1445, +1188, 1365, 1477, +1220, 1397, 1606, +1204, 1397, 1654, +1253, 1413, 1734, +1301, 1445, 1831, +1333, 1477, 1927, +1365, 1493, 2007, +1461, 1542, 2056, +1526, 1590, 2184, +1285, 1477, 1044, +1301, 1477, 1076, +1253, 1477, 1108, +1269, 1477, 1204, +1285, 1477, 1301, +1237, 1493, 1349, +1253, 1510, 1445, +1269, 1526, 1558, +1301, 1542, 1622, +1269, 1542, 1670, +1381, 1574, 1750, +1397, 1590, 1831, +1445, 1622, 1911, +1477, 1654, 2007, +1510, 1670, 2088, +1558, 1702, 2184, +1622, 1734, 2232, +1429, 1686, 1140, +1461, 1670, 1172, +1445, 1686, 1237, +1429, 1686, 1317, +1429, 1686, 1397, +1413, 1702, 1493, +1413, 1702, 1574, +1445, 1702, 1622, +1477, 1718, 1718, +1526, 1750, 1783, +1542, 1750, 1831, +1542, 1766, 1927, +1574, 1799, 1991, +1622, 1815, 2088, +1638, 1831, 2168, +1702, 1863, 2232, +1750, 1879, 2312, +1558, 1863, 1237, +1558, 1879, 1285, +1574, 1879, 1349, +1542, 1863, 1381, +1574, 1863, 1477, +1558, 1895, 1590, +1590, 1879, 1654, +1606, 1895, 1718, +1638, 1911, 1750, +1638, 1911, 1847, +1654, 1927, 1943, +1686, 1927, 2023, +1750, 1943, 2104, +1766, 1991, 2200, +1799, 1991, 2232, +1847, 2023, 2345, +1895, 2039, 2393, +1750, 2088, 1397, +1750, 2088, 1381, +1734, 2088, 1413, +1750, 2072, 1493, +1750, 2072, 1558, +1750, 2088, 1654, +1783, 2072, 1766, +1783, 2088, 1799, +1799, 2088, 1863, +1847, 2104, 1927, +1879, 2120, 1975, +1847, 2136, 2104, +1911, 2136, 2168, +1975, 2152, 2264, +2023, 2184, 2345, +2023, 2216, 2441, +2056, 2232, 2521, +1959, 2312, 1510, +1943, 2296, 1493, +1959, 2296, 1558, +1991, 2296, 1622, +1959, 2296, 1702, +1959, 2280, 1783, +1991, 2280, 1863, +2023, 2296, 1943, +2023, 2329, 2007, +2039, 2329, 2072, +2072, 2345, 2120, +2104, 2345, 2200, +2104, 2329, 2280, +2104, 2361, 2361, +2120, 2361, 2425, +2136, 2377, 2505, +2264, 2393, 2602, +2136, 2473, 1638, +2088, 2473, 1622, +2136, 2489, 1638, +2120, 2489, 1702, +2120, 2473, 1783, +2152, 2489, 1895, +2152, 2473, 1975, +2168, 2489, 2039, +2184, 2473, 2104, +2200, 2505, 2152, +2232, 2505, 2232, +2264, 2521, 2264, +2296, 2521, 2345, +2312, 2537, 2457, +2329, 2537, 2521, +2361, 2553, 2602, +2393, 2585, 2682, +2264, 2682, 1750, +2264, 2682, 1750, +2296, 2682, 1831, +2296, 2666, 1863, +2296, 2682, 1943, +2280, 2682, 2007, +2312, 2682, 2072, +2377, 2714, 2200, +2361, 2698, 2248, +2377, 2698, 2312, +2361, 2714, 2345, +2393, 2714, 2425, +2457, 2746, 2457, +2473, 2746, 2553, +2473, 2746, 2650, +2521, 2762, 2730, +2537, 2778, 2810, +2457, 2891, 1879, +2457, 2907, 1895, +2505, 2907, 1927, +2521, 2907, 1991, +2521, 2891, 2072, +2489, 2907, 2120, +2521, 2891, 2200, +2537, 2891, 2296, +2569, 2891, 2345, +2553, 2891, 2409, +2569, 2907, 2473, +2602, 2907, 2553, +2618, 2923, 2602, +2618, 2923, 2666, +2650, 2923, 2730, +2698, 2955, 2794, +2714, 2971, 2939, +2650, 3083, 2023, +2650, 3083, 2039, +2650, 3083, 2056, +2682, 3099, 2136, +2666, 3099, 2216, +2634, 3099, 2264, +2666, 3099, 2345, +2682, 3099, 2393, +2698, 3083, 2457, +2730, 3099, 2537, +2714, 3115, 2602, +2746, 3115, 2682, +2778, 3115, 2714, +2794, 3148, 2778, +2826, 3148, 2842, +2826, 3148, 2907, +2875, 3180, 3035, +2826, 3292, 2184, +2794, 3308, 2184, +2778, 3292, 2200, +2794, 3276, 2232, +2810, 3276, 2296, +2762, 3276, 2329, +2826, 3292, 2441, +2842, 3292, 2537, +2842, 3276, 2585, +2858, 3292, 2650, +2875, 3292, 2714, +2907, 3292, 2778, +2907, 3308, 2826, +2939, 3324, 2907, +2955, 3308, 2939, +3003, 3340, 3035, +3003, 3356, 3099, +2939, 3517, 2312, +3019, 3517, 2361, +2971, 3517, 2345, +3035, 3517, 2393, +2971, 3517, 2441, +3003, 3517, 2521, +3003, 3501, 2618, +3035, 3501, 2682, +3051, 3501, 2746, +3083, 3501, 2778, +3115, 3517, 2875, +3099, 3517, 2939, +3131, 3533, 3019, +3148, 3517, 3067, +3164, 3549, 3131, +3180, 3549, 3164, +3212, 3549, 3228, +1188, 594, 578, +1124, 642, 674, +1044, 691, 803, +947, 739, 851, +931, 755, 931, +980, 787, 1012, +996, 819, 1092, +1028, 851, 1204, +1044, 867, 1253, +1028, 899, 1349, +1044, 931, 1413, +1108, 996, 1510, +1156, 1044, 1622, +1188, 1060, 1686, +1253, 1124, 1799, +1317, 1188, 1911, +1349, 1220, 1959, +1220, 691, 610, +1204, 691, 691, +1092, 739, 819, +996, 787, 899, +996, 819, 964, +996, 835, 1060, +1028, 883, 1124, +1028, 883, 1204, +1060, 915, 1269, +1060, 947, 1365, +1108, 1012, 1461, +1140, 1028, 1542, +1172, 1060, 1638, +1204, 1108, 1702, +1285, 1156, 1831, +1333, 1204, 1943, +1381, 1237, 1975, +1285, 771, 578, +1237, 803, 739, +1172, 835, 851, +1092, 867, 964, +1044, 899, 1012, +1044, 915, 1076, +1028, 931, 1156, +1076, 947, 1237, +1060, 1012, 1333, +1076, 1044, 1397, +1124, 1076, 1493, +1140, 1092, 1558, +1204, 1140, 1670, +1253, 1172, 1766, +1285, 1220, 1847, +1381, 1253, 1927, +1381, 1285, 2023, +1285, 931, 626, +1301, 931, 674, +1237, 947, 867, +1172, 996, 1044, +1092, 1028, 1076, +1108, 1060, 1156, +1108, 1060, 1237, +1140, 1076, 1301, +1108, 1108, 1381, +1140, 1140, 1461, +1140, 1156, 1542, +1220, 1188, 1638, +1253, 1237, 1734, +1301, 1269, 1815, +1349, 1301, 1895, +1397, 1333, 1959, +1461, 1381, 2072, +1269, 1124, 771, +1285, 1124, 819, +1253, 1124, 883, +1285, 1108, 964, +1220, 1140, 1172, +1172, 1188, 1237, +1188, 1204, 1301, +1172, 1220, 1397, +1172, 1237, 1461, +1220, 1269, 1558, +1237, 1285, 1622, +1253, 1317, 1686, +1333, 1333, 1783, +1365, 1349, 1863, +1413, 1413, 1959, +1461, 1445, 2056, +1526, 1493, 2120, +1301, 1333, 980, +1301, 1333, 980, +1317, 1333, 1028, +1317, 1317, 1108, +1333, 1317, 1188, +1301, 1333, 1317, +1285, 1365, 1381, +1269, 1381, 1461, +1237, 1397, 1526, +1253, 1429, 1606, +1317, 1429, 1686, +1349, 1445, 1766, +1397, 1493, 1863, +1429, 1510, 1943, +1493, 1542, 2023, +1542, 1590, 2120, +1622, 1638, 2200, +1397, 1526, 1076, +1429, 1510, 1108, +1413, 1526, 1156, +1397, 1526, 1253, +1397, 1526, 1333, +1381, 1542, 1413, +1365, 1542, 1493, +1349, 1558, 1558, +1365, 1558, 1622, +1397, 1574, 1686, +1445, 1606, 1766, +1477, 1622, 1879, +1493, 1638, 1943, +1542, 1670, 2039, +1574, 1686, 2120, +1654, 1734, 2184, +1686, 1750, 2264, +1574, 1718, 1204, +1558, 1702, 1220, +1558, 1718, 1253, +1526, 1718, 1333, +1542, 1718, 1413, +1558, 1718, 1510, +1542, 1718, 1590, +1558, 1750, 1654, +1558, 1750, 1734, +1558, 1734, 1783, +1574, 1766, 1863, +1622, 1815, 1975, +1638, 1815, 2023, +1670, 1831, 2120, +1734, 1879, 2200, +1783, 1879, 2264, +1815, 1895, 2345, +1686, 1895, 1285, +1670, 1895, 1285, +1670, 1879, 1333, +1654, 1895, 1397, +1670, 1895, 1493, +1670, 1911, 1558, +1670, 1911, 1686, +1686, 1911, 1734, +1734, 1927, 1799, +1734, 1927, 1879, +1766, 1943, 1959, +1815, 1975, 2023, +1815, 1975, 2088, +1847, 2007, 2168, +1863, 2039, 2264, +1911, 2039, 2345, +1943, 2056, 2425, +1847, 2088, 1349, +1863, 2104, 1397, +1831, 2104, 1413, +1847, 2088, 1493, +1847, 2104, 1574, +1863, 2104, 1670, +1847, 2104, 1783, +1911, 2120, 1831, +1879, 2136, 1895, +1927, 2136, 1943, +1959, 2120, 2023, +1975, 2120, 2088, +2023, 2152, 2184, +2023, 2184, 2296, +2056, 2216, 2393, +2072, 2232, 2441, +2120, 2280, 2537, +2039, 2312, 1493, +2039, 2312, 1526, +2007, 2296, 1542, +2023, 2329, 1622, +2056, 2312, 1702, +2056, 2329, 1783, +2023, 2329, 1863, +2088, 2329, 1975, +2072, 2329, 1991, +2104, 2345, 2104, +2136, 2345, 2136, +2136, 2329, 2168, +2136, 2377, 2312, +2152, 2377, 2377, +2184, 2393, 2457, +2232, 2393, 2537, +2280, 2409, 2634, +2216, 2505, 1606, +2200, 2489, 1606, +2200, 2505, 1670, +2216, 2505, 1734, +2200, 2505, 1783, +2232, 2521, 1895, +2200, 2505, 1943, +2232, 2505, 2072, +2264, 2505, 2120, +2264, 2521, 2184, +2296, 2537, 2264, +2329, 2537, 2312, +2345, 2537, 2377, +2312, 2537, 2457, +2361, 2569, 2553, +2393, 2585, 2634, +2425, 2602, 2714, +2345, 2698, 1718, +2345, 2714, 1766, +2361, 2714, 1815, +2345, 2698, 1879, +2377, 2714, 1943, +2393, 2714, 2007, +2377, 2714, 2104, +2393, 2714, 2184, +2409, 2714, 2232, +2441, 2714, 2312, +2425, 2730, 2377, +2473, 2746, 2441, +2505, 2762, 2473, +2521, 2762, 2569, +2537, 2762, 2666, +2521, 2778, 2746, +2569, 2810, 2842, +2521, 2907, 1879, +2489, 2891, 1895, +2537, 2907, 1943, +2521, 2891, 1959, +2537, 2891, 2023, +2553, 2891, 2120, +2537, 2907, 2216, +2553, 2907, 2280, +2585, 2907, 2329, +2602, 2907, 2425, +2618, 2907, 2489, +2634, 2923, 2537, +2666, 2939, 2618, +2698, 2939, 2666, +2730, 2955, 2746, +2714, 2971, 2842, +2746, 2955, 2907, +2682, 3099, 2023, +2682, 3099, 2023, +2682, 3115, 2056, +2682, 3099, 2104, +2714, 3115, 2184, +2698, 3099, 2248, +2714, 3131, 2296, +2714, 3099, 2409, +2746, 3099, 2473, +2778, 3099, 2553, +2778, 3131, 2634, +2794, 3131, 2698, +2810, 3148, 2746, +2826, 3131, 2778, +2842, 3131, 2842, +2907, 3180, 2939, +2939, 3180, 3003, +2810, 3276, 2136, +2826, 3292, 2152, +2858, 3292, 2232, +2842, 3292, 2264, +2842, 3292, 2248, +2858, 3292, 2361, +2842, 3308, 2457, +2858, 3308, 2521, +2907, 3324, 2602, +2907, 3308, 2666, +2939, 3308, 2698, +2955, 3340, 2794, +2955, 3324, 2858, +2987, 3324, 2923, +3003, 3356, 2987, +3019, 3356, 3051, +3067, 3388, 3148, +3051, 3517, 2329, +3051, 3517, 2361, +3051, 3517, 2361, +3083, 3517, 2393, +3035, 3517, 2425, +3003, 3517, 2489, +3035, 3517, 2569, +3083, 3517, 2666, +3099, 3501, 2762, +3131, 3517, 2810, +3131, 3533, 2891, +3148, 3533, 2955, +3131, 3533, 3003, +3164, 3533, 3067, +3196, 3549, 3131, +3244, 3565, 3180, +3212, 3565, 3244, +1365, 707, 658, +1349, 739, 739, +1237, 787, 883, +1140, 835, 980, +1108, 883, 1028, +1108, 867, 1092, +1124, 899, 1172, +1172, 947, 1269, +1156, 980, 1349, +1204, 996, 1397, +1188, 1044, 1493, +1220, 1060, 1574, +1269, 1092, 1654, +1317, 1156, 1783, +1349, 1204, 1847, +1397, 1237, 1927, +1461, 1285, 2039, +1381, 771, 658, +1397, 771, 739, +1301, 835, 899, +1188, 867, 980, +1140, 899, 1044, +1124, 915, 1108, +1124, 931, 1188, +1156, 980, 1285, +1172, 1012, 1349, +1220, 1044, 1445, +1204, 1076, 1526, +1269, 1092, 1606, +1285, 1140, 1702, +1317, 1188, 1766, +1381, 1237, 1847, +1445, 1285, 1959, +1445, 1301, 2007, +1445, 851, 642, +1413, 867, 755, +1365, 883, 899, +1237, 947, 1028, +1156, 1012, 1092, +1172, 1012, 1156, +1188, 1044, 1237, +1188, 1060, 1301, +1220, 1076, 1381, +1220, 1076, 1477, +1220, 1124, 1542, +1269, 1156, 1622, +1301, 1188, 1718, +1397, 1253, 1815, +1413, 1269, 1895, +1461, 1317, 1975, +1526, 1365, 2088, +1493, 996, 658, +1493, 980, 723, +1413, 1028, 915, +1349, 1060, 1060, +1253, 1092, 1156, +1237, 1108, 1204, +1204, 1124, 1269, +1253, 1140, 1365, +1253, 1172, 1429, +1253, 1188, 1493, +1269, 1237, 1590, +1333, 1269, 1670, +1365, 1301, 1766, +1397, 1317, 1831, +1429, 1333, 1927, +1510, 1397, 2056, +1510, 1413, 2104, +1461, 1140, 755, +1461, 1156, 819, +1510, 1140, 883, +1445, 1188, 1108, +1381, 1204, 1220, +1301, 1253, 1285, +1301, 1269, 1365, +1317, 1285, 1445, +1333, 1301, 1493, +1349, 1333, 1590, +1365, 1333, 1638, +1397, 1365, 1734, +1397, 1381, 1815, +1445, 1413, 1911, +1477, 1445, 1991, +1574, 1493, 2056, +1622, 1526, 2152, +1493, 1365, 931, +1461, 1349, 964, +1510, 1365, 1028, +1510, 1365, 1108, +1510, 1349, 1172, +1429, 1397, 1397, +1397, 1397, 1429, +1397, 1429, 1493, +1333, 1461, 1574, +1413, 1461, 1638, +1461, 1493, 1766, +1477, 1510, 1831, +1510, 1510, 1879, +1542, 1542, 1943, +1590, 1590, 2039, +1638, 1622, 2136, +1686, 1654, 2248, +1526, 1526, 1076, +1542, 1558, 1172, +1477, 1542, 1156, +1493, 1542, 1220, +1526, 1558, 1301, +1574, 1558, 1397, +1510, 1574, 1526, +1526, 1590, 1574, +1526, 1622, 1686, +1542, 1638, 1750, +1526, 1638, 1815, +1574, 1670, 1895, +1606, 1702, 1991, +1654, 1718, 2039, +1686, 1734, 2120, +1734, 1766, 2232, +1766, 1783, 2312, +1686, 1750, 1204, +1670, 1750, 1237, +1654, 1734, 1285, +1670, 1734, 1349, +1654, 1734, 1397, +1670, 1750, 1510, +1670, 1766, 1590, +1638, 1766, 1670, +1654, 1799, 1766, +1638, 1815, 1815, +1670, 1815, 1895, +1702, 1847, 1991, +1750, 1863, 2039, +1766, 1863, 2104, +1815, 1895, 2200, +1863, 1911, 2280, +1911, 1943, 2377, +1815, 1927, 1285, +1799, 1911, 1301, +1799, 1927, 1365, +1766, 1927, 1429, +1799, 1927, 1477, +1815, 1927, 1574, +1815, 1927, 1670, +1799, 1927, 1750, +1847, 1959, 1815, +1799, 1943, 1879, +1847, 1975, 1975, +1847, 2007, 2056, +1863, 1991, 2120, +1911, 2023, 2200, +1959, 2056, 2296, +1991, 2072, 2377, +2023, 2088, 2425, +1959, 2120, 1397, +1943, 2120, 1429, +1943, 2136, 1461, +1959, 2120, 1526, +1943, 2120, 1574, +1927, 2136, 1670, +1943, 2136, 1734, +1943, 2136, 1847, +1991, 2120, 1911, +2007, 2136, 1959, +2023, 2152, 2056, +2072, 2184, 2152, +2088, 2184, 2216, +2120, 2232, 2296, +2104, 2248, 2393, +2120, 2248, 2457, +2168, 2280, 2553, +2136, 2329, 1526, +2152, 2345, 1542, +2136, 2345, 1606, +2120, 2345, 1654, +2136, 2345, 1718, +2120, 2345, 1783, +2168, 2361, 1863, +2152, 2345, 1975, +2168, 2345, 2039, +2152, 2345, 2088, +2200, 2361, 2152, +2200, 2377, 2232, +2232, 2377, 2312, +2232, 2393, 2377, +2296, 2409, 2473, +2329, 2425, 2553, +2329, 2441, 2634, +2296, 2505, 1590, +2264, 2521, 1622, +2296, 2537, 1686, +2264, 2505, 1718, +2280, 2537, 1799, +2280, 2521, 1879, +2329, 2521, 1991, +2296, 2521, 2072, +2345, 2537, 2152, +2329, 2553, 2216, +2345, 2537, 2280, +2393, 2553, 2296, +2425, 2569, 2377, +2377, 2553, 2489, +2425, 2602, 2585, +2473, 2618, 2650, +2489, 2618, 2746, +2441, 2714, 1750, +2441, 2730, 1799, +2425, 2730, 1815, +2409, 2730, 1847, +2409, 2730, 1911, +2441, 2746, 1991, +2457, 2714, 2104, +2473, 2746, 2184, +2473, 2746, 2280, +2505, 2746, 2345, +2505, 2762, 2425, +2537, 2778, 2473, +2569, 2762, 2505, +2553, 2778, 2569, +2569, 2794, 2714, +2569, 2794, 2762, +2634, 2794, 2842, +2553, 2907, 1879, +2602, 2923, 1895, +2602, 2923, 1895, +2602, 2923, 1975, +2602, 2907, 2056, +2618, 2907, 2120, +2618, 2923, 2200, +2602, 2907, 2312, +2634, 2907, 2345, +2666, 2923, 2409, +2698, 2939, 2505, +2666, 2923, 2553, +2714, 2939, 2634, +2746, 2955, 2682, +2778, 2955, 2762, +2746, 2971, 2858, +2794, 2987, 2939, +2746, 3115, 2007, +2714, 3115, 2023, +2746, 3131, 2056, +2762, 3131, 2120, +2778, 3115, 2184, +2778, 3099, 2264, +2746, 3131, 2312, +2778, 3131, 2377, +2794, 3131, 2489, +2842, 3131, 2585, +2842, 3148, 2618, +2858, 3131, 2682, +2858, 3148, 2762, +2891, 3164, 2810, +2907, 3164, 2875, +2955, 3164, 2923, +2955, 3196, 3051, +2875, 3324, 2152, +2858, 3324, 2152, +2875, 3308, 2200, +2875, 3308, 2232, +2923, 3324, 2296, +2875, 3308, 2345, +2875, 3324, 2409, +2907, 3340, 2537, +2939, 3324, 2618, +2955, 3308, 2682, +2987, 3308, 2730, +2971, 3324, 2778, +3019, 3340, 2891, +2987, 3340, 2923, +3051, 3356, 2987, +3099, 3388, 3099, +3099, 3372, 3148, +3083, 3533, 2312, +3083, 3533, 2361, +3083, 3533, 2361, +3115, 3549, 2409, +3083, 3517, 2409, +3115, 3533, 2521, +3131, 3533, 2585, +3131, 3549, 2698, +3131, 3533, 2762, +3180, 3549, 2810, +3196, 3533, 2875, +3212, 3549, 2987, +3196, 3549, 3003, +3212, 3549, 3067, +3228, 3533, 3131, +3244, 3565, 3196, +3276, 3565, 3276, +1558, 771, 691, +1542, 803, 771, +1445, 867, 947, +1349, 931, 1060, +1253, 964, 1108, +1269, 996, 1156, +1253, 1012, 1237, +1253, 1028, 1301, +1285, 1044, 1381, +1301, 1076, 1461, +1333, 1092, 1542, +1349, 1140, 1638, +1381, 1188, 1734, +1445, 1220, 1815, +1461, 1269, 1879, +1510, 1285, 1959, +1542, 1349, 2088, +1574, 835, 691, +1574, 851, 803, +1477, 883, 915, +1365, 964, 1028, +1285, 1028, 1124, +1269, 1028, 1188, +1269, 1044, 1237, +1285, 1060, 1333, +1301, 1092, 1397, +1317, 1092, 1477, +1349, 1140, 1542, +1397, 1172, 1670, +1413, 1220, 1766, +1429, 1269, 1815, +1493, 1285, 1895, +1510, 1317, 1991, +1574, 1365, 2072, +1606, 931, 707, +1590, 931, 803, +1558, 964, 931, +1429, 1012, 1060, +1333, 1076, 1172, +1301, 1076, 1188, +1285, 1092, 1253, +1333, 1124, 1365, +1317, 1124, 1429, +1365, 1156, 1510, +1381, 1204, 1606, +1397, 1237, 1702, +1397, 1253, 1734, +1461, 1301, 1847, +1510, 1333, 1943, +1542, 1397, 2023, +1574, 1413, 2104, +1670, 1028, 674, +1606, 1060, 819, +1590, 1060, 964, +1510, 1076, 1076, +1397, 1156, 1220, +1349, 1188, 1269, +1333, 1204, 1349, +1365, 1220, 1429, +1397, 1220, 1493, +1413, 1253, 1542, +1429, 1269, 1638, +1429, 1317, 1718, +1461, 1349, 1799, +1510, 1365, 1879, +1558, 1413, 1975, +1606, 1445, 2088, +1654, 1493, 2136, +1702, 1204, 755, +1718, 1204, 819, +1702, 1204, 915, +1622, 1220, 1124, +1542, 1253, 1220, +1445, 1301, 1333, +1445, 1317, 1413, +1445, 1349, 1477, +1461, 1333, 1542, +1461, 1365, 1606, +1477, 1413, 1702, +1461, 1413, 1766, +1526, 1461, 1863, +1542, 1461, 1943, +1622, 1526, 2023, +1670, 1558, 2120, +1686, 1590, 2184, +1670, 1397, 931, +1686, 1381, 947, +1686, 1397, 1028, +1718, 1365, 1076, +1654, 1397, 1285, +1590, 1429, 1413, +1493, 1461, 1461, +1510, 1461, 1526, +1510, 1477, 1606, +1526, 1493, 1702, +1558, 1526, 1766, +1558, 1558, 1847, +1590, 1590, 1927, +1638, 1622, 2023, +1686, 1638, 2104, +1718, 1654, 2168, +1750, 1702, 2232, +1686, 1574, 1044, +1702, 1558, 1092, +1702, 1574, 1172, +1702, 1590, 1220, +1750, 1590, 1301, +1750, 1574, 1397, +1670, 1606, 1558, +1638, 1638, 1638, +1638, 1654, 1702, +1638, 1686, 1783, +1638, 1702, 1831, +1654, 1702, 1895, +1686, 1718, 1959, +1750, 1750, 2072, +1799, 1783, 2168, +1815, 1799, 2248, +1879, 1847, 2329, +1799, 1766, 1204, +1766, 1766, 1253, +1783, 1783, 1285, +1766, 1799, 1381, +1750, 1783, 1429, +1766, 1783, 1526, +1783, 1799, 1590, +1766, 1799, 1734, +1750, 1831, 1815, +1766, 1847, 1847, +1783, 1863, 1927, +1799, 1895, 2007, +1831, 1879, 2072, +1863, 1895, 2152, +1927, 1927, 2248, +1943, 1943, 2329, +1991, 1991, 2377, +1927, 1927, 1285, +1927, 1927, 1317, +1911, 1927, 1381, +1927, 1959, 1461, +1927, 1943, 1526, +1911, 1943, 1590, +1943, 1959, 1654, +1927, 1975, 1750, +1911, 1991, 1847, +1895, 1975, 1895, +1911, 2023, 2007, +1943, 2039, 2072, +1975, 2056, 2152, +2007, 2072, 2232, +2039, 2072, 2280, +2072, 2088, 2361, +2120, 2136, 2457, +2072, 2120, 1397, +2088, 2120, 1429, +2088, 2136, 1493, +2088, 2136, 1526, +2072, 2136, 1590, +2088, 2136, 1670, +2072, 2136, 1734, +2056, 2152, 1831, +2072, 2152, 1927, +2120, 2168, 1991, +2104, 2200, 2088, +2152, 2216, 2168, +2136, 2216, 2232, +2168, 2248, 2312, +2184, 2280, 2409, +2216, 2296, 2473, +2248, 2312, 2537, +2248, 2361, 1542, +2232, 2345, 1558, +2232, 2361, 1606, +2216, 2345, 1654, +2216, 2345, 1718, +2216, 2345, 1750, +2216, 2361, 1847, +2216, 2361, 1959, +2216, 2361, 2056, +2248, 2361, 2120, +2248, 2377, 2168, +2264, 2393, 2264, +2329, 2393, 2345, +2345, 2425, 2441, +2361, 2425, 2505, +2361, 2457, 2585, +2393, 2473, 2666, +2409, 2537, 1654, +2377, 2521, 1654, +2393, 2537, 1702, +2377, 2537, 1734, +2377, 2537, 1799, +2393, 2553, 1895, +2377, 2553, 1991, +2377, 2537, 2072, +2377, 2553, 2120, +2425, 2553, 2216, +2409, 2553, 2280, +2457, 2585, 2345, +2473, 2585, 2441, +2505, 2602, 2505, +2489, 2618, 2585, +2521, 2618, 2666, +2569, 2650, 2762, +2505, 2746, 1799, +2505, 2746, 1783, +2489, 2746, 1815, +2505, 2746, 1879, +2505, 2746, 1943, +2521, 2762, 1991, +2537, 2746, 2104, +2537, 2762, 2184, +2553, 2762, 2280, +2553, 2762, 2377, +2553, 2778, 2441, +2569, 2762, 2473, +2618, 2778, 2521, +2650, 2778, 2553, +2618, 2810, 2698, +2666, 2794, 2794, +2682, 2810, 2875, +2666, 2939, 1895, +2682, 2939, 1895, +2682, 2955, 1943, +2682, 2939, 1991, +2682, 2939, 2023, +2666, 2939, 2088, +2698, 2923, 2216, +2714, 2939, 2312, +2714, 2939, 2393, +2730, 2955, 2457, +2746, 2939, 2521, +2730, 2955, 2585, +2778, 2971, 2666, +2794, 2955, 2698, +2826, 2971, 2778, +2810, 2987, 2891, +2842, 3003, 2955, +2826, 3164, 2023, +2794, 3131, 2039, +2794, 3148, 2039, +2794, 3164, 2120, +2810, 3148, 2168, +2826, 3148, 2280, +2875, 3164, 2329, +2875, 3148, 2409, +2842, 3131, 2489, +2875, 3148, 2569, +2875, 3148, 2666, +2923, 3164, 2714, +2939, 3180, 2762, +2939, 3180, 2826, +3003, 3196, 2891, +3003, 3180, 2955, +2987, 3196, 3051, +2923, 3340, 2136, +2971, 3340, 2184, +2955, 3340, 2216, +2923, 3324, 2232, +2907, 3324, 2296, +2955, 3340, 2345, +2971, 3324, 2441, +2971, 3340, 2521, +2987, 3340, 2618, +3003, 3340, 2682, +3067, 3340, 2762, +3019, 3324, 2794, +3067, 3340, 2891, +3067, 3356, 2971, +3115, 3388, 3035, +3131, 3372, 3051, +3164, 3388, 3148, +3131, 3533, 2296, +3148, 3565, 2361, +3148, 3565, 2345, +3164, 3549, 2425, +3164, 3565, 2457, +3148, 3549, 2489, +3164, 3549, 2585, +3148, 3565, 2650, +3164, 3565, 2746, +3212, 3549, 2810, +3244, 3549, 2891, +3244, 3533, 2971, +3244, 3549, 3019, +3276, 3565, 3099, +3260, 3565, 3180, +3308, 3581, 3228, +3340, 3597, 3308, +1734, 883, 755, +1734, 867, 819, +1670, 931, 964, +1510, 996, 1076, +1429, 1028, 1140, +1381, 1060, 1204, +1397, 1108, 1301, +1413, 1124, 1365, +1429, 1140, 1461, +1429, 1156, 1542, +1477, 1188, 1622, +1510, 1237, 1702, +1542, 1253, 1766, +1542, 1301, 1831, +1558, 1333, 1927, +1622, 1381, 2039, +1654, 1397, 2120, +1734, 915, 755, +1750, 915, 819, +1654, 947, 980, +1558, 1012, 1076, +1477, 1076, 1204, +1413, 1124, 1253, +1413, 1140, 1317, +1429, 1140, 1397, +1445, 1172, 1461, +1461, 1188, 1574, +1510, 1220, 1606, +1510, 1253, 1686, +1542, 1269, 1766, +1542, 1333, 1863, +1590, 1365, 1975, +1622, 1397, 2056, +1686, 1429, 2136, +1750, 1012, 771, +1734, 1028, 883, +1718, 1028, 980, +1622, 1076, 1108, +1542, 1124, 1220, +1429, 1172, 1269, +1445, 1204, 1349, +1477, 1220, 1445, +1477, 1237, 1493, +1493, 1237, 1558, +1526, 1285, 1654, +1558, 1301, 1734, +1574, 1333, 1815, +1590, 1381, 1911, +1638, 1413, 2007, +1654, 1445, 2072, +1702, 1493, 2152, +1879, 1092, 739, +1799, 1124, 883, +1783, 1140, 1012, +1718, 1172, 1156, +1606, 1220, 1253, +1510, 1237, 1317, +1510, 1269, 1365, +1510, 1301, 1461, +1542, 1317, 1542, +1542, 1333, 1606, +1574, 1349, 1686, +1606, 1397, 1799, +1590, 1413, 1863, +1590, 1445, 1943, +1654, 1477, 2007, +1702, 1526, 2120, +1750, 1542, 2200, +1863, 1220, 771, +1895, 1237, 835, +1831, 1237, 964, +1783, 1269, 1140, +1718, 1301, 1285, +1606, 1349, 1397, +1558, 1381, 1429, +1558, 1397, 1526, +1590, 1429, 1622, +1606, 1461, 1686, +1622, 1461, 1750, +1654, 1477, 1847, +1654, 1526, 1895, +1686, 1542, 1975, +1734, 1574, 2072, +1750, 1622, 2184, +1799, 1654, 2232, +1863, 1413, 899, +1895, 1413, 931, +1879, 1413, 1028, +1879, 1397, 1124, +1815, 1429, 1317, +1734, 1477, 1461, +1670, 1510, 1526, +1654, 1542, 1574, +1670, 1558, 1670, +1670, 1574, 1750, +1686, 1574, 1815, +1702, 1622, 1895, +1718, 1654, 1991, +1734, 1654, 2039, +1766, 1670, 2104, +1847, 1734, 2232, +1911, 1734, 2312, +1879, 1606, 1028, +1895, 1606, 1092, +1895, 1622, 1156, +1943, 1638, 1237, +1927, 1606, 1301, +1911, 1622, 1477, +1831, 1654, 1590, +1734, 1686, 1638, +1766, 1702, 1750, +1766, 1718, 1783, +1799, 1750, 1895, +1799, 1766, 1975, +1831, 1783, 2056, +1879, 1799, 2120, +1911, 1831, 2200, +1959, 1847, 2296, +1959, 1863, 2329, +1959, 1815, 1220, +1943, 1815, 1237, +1927, 1815, 1269, +1927, 1815, 1365, +1927, 1815, 1445, +2007, 1815, 1493, +2023, 1831, 1590, +1943, 1847, 1783, +1879, 1863, 1815, +1911, 1879, 1895, +1911, 1895, 1959, +1911, 1911, 2023, +1943, 1927, 2072, +1975, 1943, 2168, +2023, 1959, 2248, +2023, 2007, 2329, +2104, 2023, 2441, +2056, 1991, 1365, +2039, 1975, 1381, +2039, 1975, 1413, +2039, 1991, 1445, +2023, 1991, 1526, +2007, 1991, 1590, +2039, 2007, 1702, +2039, 2007, 1783, +2023, 2023, 1911, +2023, 2039, 1975, +2007, 2056, 1991, +2056, 2072, 2104, +2072, 2072, 2152, +2104, 2088, 2232, +2168, 2136, 2345, +2216, 2168, 2441, +2232, 2168, 2505, +2248, 2184, 1461, +2248, 2184, 1445, +2216, 2184, 1510, +2216, 2184, 1558, +2200, 2184, 1622, +2200, 2168, 1702, +2200, 2184, 1799, +2232, 2200, 1895, +2232, 2232, 1959, +2216, 2232, 2039, +2216, 2248, 2120, +2216, 2264, 2200, +2232, 2280, 2264, +2264, 2280, 2345, +2264, 2312, 2425, +2280, 2312, 2489, +2312, 2312, 2553, +2329, 2377, 1574, +2329, 2377, 1574, +2312, 2361, 1606, +2329, 2361, 1686, +2329, 2361, 1718, +2312, 2377, 1783, +2312, 2361, 1863, +2329, 2393, 1991, +2329, 2377, 2039, +2361, 2393, 2152, +2377, 2393, 2216, +2361, 2409, 2312, +2393, 2425, 2393, +2393, 2441, 2457, +2409, 2473, 2553, +2425, 2489, 2634, +2457, 2489, 2666, +2457, 2553, 1638, +2457, 2553, 1670, +2489, 2553, 1718, +2457, 2537, 1750, +2473, 2569, 1847, +2441, 2553, 1895, +2457, 2553, 1991, +2505, 2585, 2072, +2473, 2553, 2104, +2489, 2585, 2248, +2505, 2585, 2312, +2505, 2602, 2361, +2537, 2618, 2473, +2553, 2618, 2537, +2553, 2634, 2618, +2602, 2666, 2714, +2602, 2682, 2794, +2618, 2778, 1799, +2634, 2762, 1831, +2618, 2762, 1847, +2618, 2794, 1911, +2618, 2778, 1959, +2602, 2778, 1991, +2618, 2762, 2072, +2602, 2778, 2184, +2602, 2762, 2248, +2618, 2778, 2377, +2666, 2794, 2409, +2666, 2810, 2489, +2682, 2794, 2521, +2730, 2794, 2618, +2730, 2810, 2698, +2762, 2826, 2778, +2778, 2826, 2842, +2762, 2955, 1895, +2762, 2939, 1895, +2778, 2971, 1943, +2730, 2939, 1975, +2778, 2955, 2056, +2762, 2971, 2136, +2746, 2971, 2184, +2810, 2971, 2296, +2794, 2971, 2361, +2810, 2971, 2473, +2810, 2955, 2537, +2794, 2971, 2618, +2826, 2971, 2682, +2858, 2971, 2730, +2907, 3003, 2778, +2875, 3019, 2923, +2939, 3051, 2987, +2907, 3148, 2039, +2923, 3180, 2056, +2907, 3164, 2088, +2891, 3164, 2104, +2891, 3164, 2184, +2891, 3164, 2264, +2939, 3180, 2312, +2923, 3148, 2393, +2939, 3164, 2505, +2939, 3180, 2618, +2955, 3164, 2666, +2987, 3180, 2714, +2987, 3196, 2794, +3003, 3196, 2858, +3019, 3180, 2891, +3051, 3196, 2971, +3019, 3196, 3051, +3019, 3340, 2168, +3019, 3340, 2168, +3035, 3340, 2200, +3003, 3356, 2232, +3035, 3356, 2312, +3035, 3356, 2345, +3035, 3356, 2441, +3051, 3340, 2505, +3051, 3372, 2650, +3051, 3356, 2714, +3099, 3372, 2762, +3131, 3404, 2875, +3148, 3388, 2939, +3148, 3388, 2971, +3164, 3388, 3035, +3196, 3404, 3099, +3228, 3404, 3164, +3212, 3565, 2345, +3212, 3565, 2345, +3212, 3565, 2345, +3244, 3581, 2425, +3228, 3565, 2441, +3244, 3565, 2521, +3228, 3581, 2585, +3276, 3565, 2682, +3228, 3565, 2730, +3228, 3549, 2794, +3260, 3565, 2875, +3276, 3549, 2971, +3308, 3565, 3051, +3324, 3581, 3115, +3308, 3581, 3180, +3356, 3581, 3228, +3404, 3613, 3292, +1927, 964, 803, +1911, 964, 899, +1847, 1012, 1028, +1766, 1092, 1172, +1654, 1140, 1269, +1574, 1204, 1333, +1574, 1220, 1365, +1558, 1220, 1429, +1574, 1253, 1510, +1606, 1269, 1622, +1606, 1285, 1654, +1638, 1301, 1766, +1670, 1349, 1831, +1702, 1365, 1911, +1686, 1413, 1991, +1766, 1461, 2088, +1783, 1510, 2184, +1959, 1012, 835, +1943, 1012, 899, +1863, 1060, 1028, +1783, 1108, 1172, +1702, 1172, 1253, +1590, 1220, 1317, +1558, 1220, 1349, +1590, 1253, 1461, +1590, 1253, 1510, +1590, 1285, 1590, +1638, 1317, 1686, +1638, 1333, 1766, +1686, 1365, 1847, +1686, 1381, 1927, +1734, 1445, 2007, +1766, 1461, 2088, +1799, 1510, 2200, +1927, 1076, 819, +1911, 1076, 899, +1911, 1092, 1012, +1799, 1140, 1140, +1750, 1220, 1301, +1638, 1253, 1365, +1606, 1301, 1413, +1606, 1301, 1493, +1622, 1333, 1542, +1654, 1349, 1654, +1638, 1349, 1718, +1686, 1381, 1799, +1702, 1413, 1895, +1734, 1429, 1943, +1734, 1493, 2039, +1799, 1526, 2136, +1831, 1574, 2216, +1991, 1156, 803, +1943, 1204, 915, +1927, 1188, 1044, +1879, 1204, 1140, +1799, 1253, 1285, +1702, 1317, 1397, +1638, 1365, 1445, +1638, 1381, 1542, +1654, 1381, 1606, +1670, 1413, 1686, +1686, 1429, 1750, +1702, 1445, 1831, +1750, 1477, 1895, +1766, 1526, 1991, +1783, 1558, 2072, +1847, 1606, 2184, +1847, 1606, 2200, +2088, 1285, 819, +2072, 1285, 883, +1975, 1333, 1092, +1959, 1333, 1220, +1879, 1365, 1349, +1766, 1413, 1461, +1686, 1445, 1510, +1702, 1477, 1590, +1702, 1477, 1622, +1750, 1510, 1718, +1750, 1542, 1799, +1783, 1558, 1879, +1799, 1590, 1959, +1815, 1622, 2056, +1815, 1638, 2088, +1895, 1670, 2200, +1943, 1702, 2280, +2056, 1461, 915, +2088, 1461, 947, +2088, 1461, 1028, +2039, 1477, 1188, +1991, 1493, 1365, +1927, 1526, 1510, +1847, 1574, 1590, +1799, 1622, 1638, +1799, 1638, 1734, +1831, 1638, 1783, +1831, 1654, 1847, +1847, 1654, 1911, +1879, 1686, 2023, +1879, 1734, 2104, +1943, 1750, 2168, +2007, 1783, 2248, +2007, 1799, 2329, +2072, 1654, 1028, +2088, 1638, 1060, +2104, 1638, 1108, +2136, 1638, 1188, +2104, 1638, 1285, +2072, 1670, 1510, +1991, 1702, 1638, +1911, 1734, 1734, +1879, 1766, 1766, +1911, 1783, 1863, +1943, 1799, 1927, +1975, 1815, 1991, +1959, 1847, 2088, +1975, 1847, 2152, +2007, 1863, 2232, +2056, 1895, 2312, +2104, 1927, 2377, +2136, 1847, 1172, +2136, 1847, 1188, +2152, 1847, 1269, +2136, 1831, 1317, +2168, 1847, 1413, +2200, 1815, 1461, +2136, 1847, 1654, +2120, 1879, 1766, +2023, 1911, 1815, +2039, 1911, 1895, +2039, 1927, 1959, +2088, 1975, 2088, +2072, 1991, 2136, +2088, 2023, 2248, +2152, 2007, 2280, +2200, 2039, 2377, +2216, 2072, 2441, +2216, 2007, 1301, +2184, 2023, 1365, +2200, 2007, 1381, +2200, 2039, 1461, +2184, 2039, 1510, +2200, 2023, 1590, +2232, 2039, 1686, +2296, 2023, 1734, +2184, 2056, 1911, +2184, 2072, 1975, +2168, 2072, 2039, +2152, 2120, 2136, +2200, 2152, 2216, +2232, 2152, 2296, +2264, 2184, 2393, +2312, 2200, 2473, +2312, 2232, 2553, +2345, 2216, 1461, +2361, 2216, 1510, +2345, 2216, 1526, +2329, 2216, 1590, +2329, 2232, 1654, +2312, 2232, 1750, +2312, 2248, 1847, +2345, 2248, 1895, +2361, 2264, 1959, +2329, 2264, 2104, +2329, 2296, 2184, +2296, 2296, 2216, +2312, 2312, 2312, +2329, 2312, 2377, +2345, 2312, 2441, +2361, 2345, 2505, +2425, 2361, 2634, +2505, 2393, 1606, +2489, 2377, 1590, +2489, 2377, 1622, +2473, 2393, 1686, +2457, 2377, 1734, +2457, 2393, 1831, +2473, 2393, 1895, +2473, 2409, 2007, +2489, 2409, 2072, +2473, 2425, 2152, +2473, 2441, 2232, +2473, 2457, 2296, +2473, 2489, 2393, +2505, 2489, 2473, +2489, 2505, 2521, +2505, 2505, 2602, +2553, 2537, 2698, +2585, 2569, 1686, +2585, 2569, 1686, +2585, 2585, 1750, +2585, 2585, 1783, +2569, 2585, 1847, +2618, 2618, 1959, +2569, 2585, 2007, +2569, 2602, 2072, +2602, 2618, 2152, +2602, 2634, 2264, +2585, 2618, 2329, +2618, 2634, 2409, +2634, 2666, 2505, +2650, 2666, 2569, +2650, 2666, 2634, +2666, 2714, 2730, +2666, 2698, 2778, +2746, 2778, 1831, +2698, 2778, 1815, +2714, 2810, 1879, +2714, 2794, 1927, +2730, 2794, 1975, +2698, 2794, 2023, +2730, 2794, 2088, +2698, 2794, 2168, +2698, 2810, 2248, +2746, 2810, 2361, +2762, 2810, 2457, +2762, 2794, 2505, +2778, 2810, 2553, +2794, 2826, 2666, +2842, 2858, 2762, +2842, 2842, 2810, +2842, 2858, 2891, +2858, 2971, 1943, +2875, 2971, 1943, +2842, 2955, 1959, +2858, 2987, 2007, +2875, 2971, 2072, +2858, 2971, 2120, +2842, 2971, 2216, +2826, 2987, 2280, +2858, 2987, 2361, +2858, 2987, 2441, +2875, 2987, 2553, +2907, 3003, 2634, +2891, 3003, 2682, +2939, 3003, 2698, +2971, 3019, 2794, +2939, 3035, 2907, +3003, 3067, 3019, +2971, 3180, 2039, +3003, 3180, 2072, +3019, 3196, 2136, +2987, 3180, 2152, +2987, 3196, 2216, +3003, 3180, 2280, +2987, 3180, 2329, +3019, 3196, 2409, +3051, 3196, 2489, +3035, 3180, 2602, +3019, 3196, 2682, +3051, 3196, 2746, +3051, 3180, 2794, +3051, 3196, 2875, +3099, 3196, 2891, +3115, 3196, 2955, +3148, 3228, 3067, +3099, 3372, 2184, +3115, 3356, 2200, +3131, 3388, 2216, +3115, 3372, 2280, +3099, 3372, 2296, +3115, 3388, 2345, +3115, 3388, 2441, +3164, 3404, 2537, +3180, 3404, 2634, +3148, 3388, 2714, +3148, 3388, 2778, +3180, 3404, 2858, +3196, 3388, 2923, +3244, 3404, 3003, +3260, 3404, 3083, +3276, 3404, 3115, +3324, 3421, 3196, +3292, 3565, 2312, +3308, 3581, 2329, +3276, 3565, 2345, +3292, 3581, 2409, +3276, 3581, 2425, +3308, 3581, 2505, +3292, 3581, 2569, +3308, 3581, 2666, +3292, 3581, 2730, +3308, 3581, 2826, +3324, 3581, 2891, +3356, 3581, 2971, +3372, 3597, 3083, +3372, 3581, 3148, +3404, 3613, 3212, +3421, 3613, 3276, +3437, 3613, 3308, +2120, 1060, 867, +2104, 1060, 931, +2056, 1092, 1044, +1943, 1140, 1188, +1831, 1204, 1285, +1750, 1269, 1381, +1718, 1301, 1445, +1702, 1317, 1510, +1734, 1349, 1606, +1750, 1365, 1670, +1750, 1381, 1734, +1766, 1381, 1799, +1815, 1429, 1879, +1831, 1477, 1975, +1879, 1493, 2072, +1911, 1558, 2168, +1927, 1590, 2264, +2088, 1108, 867, +2072, 1092, 947, +2072, 1140, 1076, +1975, 1172, 1188, +1895, 1237, 1301, +1783, 1285, 1413, +1718, 1349, 1445, +1734, 1349, 1542, +1750, 1365, 1622, +1734, 1381, 1686, +1766, 1397, 1766, +1783, 1429, 1815, +1815, 1445, 1927, +1847, 1493, 1991, +1895, 1510, 2088, +1911, 1558, 2184, +1959, 1590, 2248, +2136, 1188, 899, +2120, 1204, 1012, +2104, 1188, 1076, +2023, 1237, 1237, +1927, 1269, 1333, +1831, 1333, 1461, +1750, 1381, 1477, +1766, 1397, 1558, +1750, 1397, 1606, +1783, 1445, 1686, +1799, 1445, 1766, +1815, 1477, 1831, +1847, 1510, 1943, +1879, 1542, 2007, +1895, 1558, 2120, +1959, 1590, 2184, +1991, 1622, 2248, +2168, 1253, 915, +2120, 1253, 996, +2120, 1269, 1108, +2072, 1269, 1188, +1975, 1349, 1381, +1895, 1397, 1477, +1815, 1445, 1526, +1799, 1461, 1590, +1815, 1477, 1654, +1799, 1493, 1718, +1847, 1526, 1815, +1847, 1542, 1879, +1895, 1590, 2007, +1895, 1606, 2056, +1943, 1622, 2104, +1959, 1654, 2200, +2023, 1702, 2312, +2280, 1333, 835, +2232, 1365, 947, +2168, 1381, 1108, +2152, 1397, 1204, +2088, 1445, 1381, +1991, 1461, 1477, +1911, 1542, 1590, +1847, 1558, 1638, +1895, 1590, 1718, +1879, 1606, 1799, +1895, 1622, 1831, +1911, 1622, 1911, +1927, 1654, 1975, +1991, 1670, 2072, +2023, 1702, 2200, +2039, 1750, 2232, +2088, 1783, 2329, +2329, 1493, 931, +2312, 1493, 980, +2296, 1493, 1076, +2184, 1542, 1285, +2200, 1542, 1381, +2120, 1606, 1526, +2023, 1638, 1638, +1943, 1670, 1686, +1943, 1686, 1766, +1959, 1718, 1831, +1975, 1718, 1895, +1991, 1718, 1975, +2072, 1766, 2056, +2088, 1799, 2136, +2072, 1815, 2200, +2072, 1831, 2280, +2120, 1879, 2377, +2329, 1686, 1076, +2345, 1686, 1076, +2361, 1702, 1140, +2377, 1686, 1237, +2312, 1702, 1397, +2264, 1702, 1526, +2168, 1750, 1670, +2120, 1799, 1766, +2072, 1831, 1831, +2056, 1831, 1895, +2104, 1863, 1959, +2104, 1863, 2023, +2136, 1879, 2104, +2136, 1911, 2184, +2152, 1959, 2280, +2184, 1959, 2345, +2232, 1991, 2441, +2345, 1863, 1156, +2312, 1863, 1204, +2345, 1879, 1253, +2345, 1863, 1301, +2377, 1863, 1397, +2377, 1879, 1493, +2312, 1895, 1686, +2280, 1927, 1815, +2184, 1959, 1895, +2152, 1975, 1927, +2184, 1991, 2007, +2216, 2007, 2088, +2248, 2023, 2168, +2216, 2039, 2232, +2264, 2072, 2329, +2312, 2104, 2425, +2361, 2136, 2521, +2393, 2039, 1301, +2393, 2039, 1333, +2409, 2039, 1365, +2409, 2039, 1445, +2441, 2039, 1477, +2425, 2039, 1558, +2473, 2039, 1670, +2425, 2072, 1847, +2361, 2120, 1975, +2312, 2136, 2007, +2329, 2152, 2104, +2345, 2168, 2168, +2361, 2184, 2248, +2329, 2200, 2296, +2393, 2232, 2393, +2393, 2232, 2489, +2425, 2280, 2553, +2489, 2264, 1510, +2489, 2264, 1510, +2489, 2280, 1558, +2505, 2264, 1606, +2457, 2280, 1670, +2473, 2280, 1734, +2457, 2264, 1783, +2521, 2280, 1863, +2553, 2248, 1943, +2425, 2296, 2152, +2425, 2296, 2184, +2425, 2312, 2248, +2473, 2345, 2345, +2457, 2361, 2409, +2489, 2377, 2489, +2505, 2377, 2553, +2537, 2409, 2650, +2634, 2441, 1606, +2618, 2425, 1622, +2602, 2425, 1670, +2602, 2441, 1718, +2618, 2457, 1799, +2569, 2441, 1863, +2569, 2457, 1927, +2585, 2473, 2039, +2585, 2457, 2104, +2618, 2457, 2136, +2569, 2473, 2280, +2585, 2489, 2361, +2569, 2505, 2425, +2569, 2521, 2505, +2602, 2521, 2569, +2634, 2569, 2650, +2666, 2569, 2746, +2698, 2602, 1702, +2714, 2618, 1750, +2746, 2618, 1799, +2714, 2618, 1847, +2730, 2634, 1911, +2714, 2634, 1975, +2698, 2634, 2039, +2714, 2618, 2088, +2714, 2650, 2200, +2746, 2666, 2312, +2730, 2682, 2377, +2714, 2682, 2441, +2714, 2698, 2505, +2714, 2714, 2618, +2714, 2698, 2682, +2730, 2730, 2762, +2746, 2746, 2842, +2842, 2810, 1847, +2842, 2810, 1879, +2858, 2794, 1911, +2875, 2810, 1911, +2858, 2810, 1975, +2842, 2810, 2039, +2842, 2794, 2120, +2826, 2794, 2184, +2858, 2810, 2296, +2858, 2826, 2329, +2858, 2842, 2441, +2858, 2842, 2537, +2875, 2842, 2602, +2875, 2858, 2682, +2907, 2875, 2762, +2907, 2891, 2826, +2907, 2907, 2907, +2971, 3003, 1943, +2971, 2971, 1959, +2987, 2987, 2007, +2939, 2987, 2023, +2971, 2987, 2104, +2955, 2987, 2152, +2939, 3003, 2232, +2987, 3003, 2312, +2955, 3003, 2361, +2987, 3003, 2473, +3003, 3019, 2585, +2987, 3035, 2682, +3019, 3035, 2714, +3019, 3051, 2762, +3035, 3051, 2858, +3067, 3067, 2971, +3051, 3083, 3035, +3115, 3212, 2104, +3115, 3212, 2088, +3115, 3212, 2136, +3083, 3196, 2184, +3083, 3212, 2216, +3083, 3212, 2280, +3099, 3196, 2312, +3083, 3212, 2409, +3099, 3196, 2473, +3067, 3196, 2569, +3099, 3212, 2666, +3115, 3212, 2746, +3148, 3228, 2826, +3131, 3228, 2875, +3164, 3228, 2923, +3196, 3244, 3003, +3212, 3260, 3115, +3228, 3404, 2216, +3244, 3404, 2232, +3212, 3404, 2264, +3228, 3404, 2296, +3212, 3404, 2345, +3196, 3404, 2377, +3212, 3388, 2441, +3212, 3404, 2521, +3228, 3404, 2618, +3228, 3388, 2714, +3324, 3421, 2810, +3292, 3421, 2907, +3292, 3404, 2955, +3340, 3421, 3051, +3324, 3437, 3115, +3372, 3453, 3164, +3388, 3437, 3196, +3388, 3581, 2361, +3421, 3613, 2377, +3404, 3597, 2409, +3388, 3597, 2441, +3388, 3597, 2473, +3372, 3597, 2505, +3356, 3597, 2553, +3388, 3613, 2666, +3388, 3629, 2746, +3372, 3613, 2826, +3421, 3581, 2891, +3421, 3613, 2971, +3453, 3581, 3099, +3469, 3613, 3148, +3469, 3597, 3212, +3485, 3613, 3260, +3517, 3629, 3308, +2296, 1156, 915, +2296, 1156, 1012, +2264, 1172, 1140, +2168, 1237, 1237, +2072, 1301, 1381, +1975, 1333, 1445, +1879, 1397, 1542, +1895, 1429, 1558, +1879, 1445, 1654, +1911, 1461, 1718, +1927, 1493, 1815, +1927, 1510, 1879, +1959, 1526, 1959, +1975, 1558, 2039, +2056, 1574, 2120, +2088, 1622, 2216, +2120, 1654, 2312, +2296, 1172, 931, +2296, 1188, 1012, +2280, 1188, 1124, +2184, 1253, 1285, +2072, 1301, 1381, +1991, 1365, 1445, +1911, 1413, 1526, +1895, 1445, 1574, +1911, 1461, 1654, +1911, 1493, 1750, +1943, 1510, 1831, +1943, 1526, 1911, +1959, 1574, 1991, +2007, 1574, 2039, +2056, 1606, 2104, +2072, 1622, 2216, +2120, 1670, 2280, +2312, 1253, 947, +2329, 1237, 996, +2329, 1253, 1124, +2232, 1285, 1237, +2136, 1365, 1381, +2023, 1413, 1493, +1927, 1461, 1574, +1943, 1510, 1638, +1927, 1526, 1702, +1943, 1526, 1750, +1975, 1574, 1863, +1975, 1574, 1895, +1991, 1590, 1991, +2023, 1606, 2072, +2072, 1622, 2152, +2104, 1670, 2232, +2136, 1702, 2361, +2361, 1317, 947, +2329, 1333, 1060, +2329, 1349, 1140, +2296, 1349, 1269, +2184, 1429, 1413, +2120, 1477, 1542, +2007, 1542, 1622, +1959, 1558, 1638, +1959, 1574, 1718, +1959, 1590, 1783, +1975, 1606, 1847, +1975, 1622, 1927, +2056, 1638, 2023, +2072, 1686, 2104, +2120, 1702, 2200, +2136, 1734, 2248, +2184, 1750, 2345, +2473, 1397, 915, +2425, 1445, 1060, +2361, 1445, 1172, +2345, 1445, 1285, +2296, 1477, 1397, +2200, 1542, 1510, +2088, 1590, 1622, +2023, 1654, 1702, +2023, 1654, 1750, +2039, 1654, 1815, +2056, 1686, 1911, +2088, 1702, 1991, +2120, 1750, 2056, +2152, 1766, 2136, +2152, 1783, 2200, +2200, 1815, 2296, +2168, 1847, 2377, +2537, 1558, 947, +2505, 1526, 996, +2489, 1558, 1140, +2409, 1606, 1349, +2377, 1606, 1445, +2296, 1622, 1574, +2232, 1686, 1670, +2152, 1734, 1766, +2104, 1766, 1799, +2136, 1766, 1879, +2136, 1799, 1943, +2136, 1815, 2007, +2168, 1815, 2088, +2184, 1847, 2168, +2216, 1863, 2232, +2312, 1911, 2377, +2280, 1943, 2425, +2553, 1718, 1012, +2521, 1702, 1060, +2569, 1702, 1140, +2521, 1718, 1237, +2441, 1734, 1429, +2441, 1766, 1590, +2377, 1799, 1670, +2264, 1847, 1815, +2184, 1895, 1847, +2216, 1911, 1943, +2216, 1927, 2007, +2232, 1943, 2088, +2248, 1943, 2152, +2296, 1959, 2264, +2312, 1975, 2280, +2329, 2007, 2361, +2361, 2072, 2473, +2585, 1911, 1156, +2585, 1911, 1188, +2618, 1911, 1237, +2585, 1895, 1317, +2585, 1879, 1381, +2569, 1927, 1590, +2537, 1927, 1718, +2441, 1975, 1847, +2345, 2007, 1943, +2345, 2039, 2007, +2329, 2056, 2072, +2345, 2056, 2136, +2377, 2104, 2232, +2425, 2120, 2296, +2409, 2136, 2393, +2425, 2168, 2473, +2489, 2200, 2553, +2618, 2088, 1285, +2618, 2104, 1317, +2602, 2104, 1381, +2634, 2072, 1413, +2618, 2104, 1510, +2666, 2088, 1606, +2666, 2104, 1702, +2602, 2120, 1863, +2537, 2152, 2023, +2441, 2200, 2088, +2457, 2216, 2136, +2473, 2216, 2232, +2473, 2232, 2296, +2489, 2248, 2361, +2473, 2248, 2441, +2505, 2296, 2537, +2553, 2296, 2602, +2650, 2280, 1445, +2666, 2280, 1477, +2634, 2264, 1526, +2634, 2264, 1558, +2634, 2280, 1622, +2650, 2280, 1686, +2650, 2296, 1783, +2746, 2264, 1863, +2682, 2280, 2023, +2602, 2312, 2184, +2585, 2361, 2216, +2602, 2361, 2264, +2585, 2377, 2393, +2618, 2393, 2489, +2602, 2425, 2537, +2618, 2425, 2602, +2634, 2473, 2698, +2714, 2473, 1622, +2714, 2473, 1654, +2698, 2473, 1670, +2730, 2473, 1718, +2730, 2489, 1783, +2698, 2473, 1831, +2698, 2457, 1911, +2714, 2489, 1991, +2762, 2473, 2056, +2794, 2473, 2136, +2746, 2505, 2329, +2666, 2537, 2393, +2698, 2553, 2457, +2698, 2553, 2537, +2714, 2585, 2618, +2746, 2618, 2714, +2762, 2602, 2762, +2842, 2666, 1783, +2842, 2666, 1783, +2826, 2650, 1799, +2858, 2666, 1879, +2858, 2666, 1943, +2826, 2666, 1959, +2842, 2682, 2072, +2826, 2698, 2168, +2794, 2682, 2216, +2826, 2682, 2296, +2842, 2682, 2361, +2826, 2714, 2489, +2826, 2730, 2569, +2810, 2730, 2634, +2858, 2746, 2682, +2875, 2746, 2746, +2875, 2762, 2826, +2971, 2810, 1879, +2971, 2826, 1895, +2955, 2810, 1911, +2971, 2826, 1927, +2971, 2810, 2007, +2971, 2826, 2088, +2971, 2842, 2152, +2955, 2842, 2248, +2955, 2875, 2329, +2971, 2858, 2393, +3003, 2875, 2489, +2971, 2875, 2553, +2971, 2891, 2666, +2971, 2907, 2730, +2955, 2907, 2794, +2987, 2939, 2891, +2987, 2939, 2955, +3083, 3035, 1991, +3067, 3003, 1975, +3067, 3035, 2023, +3067, 3035, 2072, +3083, 3019, 2120, +3067, 3019, 2184, +3083, 3019, 2280, +3099, 3035, 2329, +3083, 3035, 2377, +3099, 3051, 2489, +3067, 3051, 2569, +3067, 3067, 2650, +3115, 3083, 2746, +3131, 3083, 2810, +3131, 3099, 2891, +3164, 3115, 2971, +3164, 3131, 3035, +3180, 3196, 2072, +3180, 3196, 2104, +3180, 3196, 2136, +3180, 3212, 2168, +3196, 3196, 2232, +3180, 3228, 2280, +3164, 3196, 2329, +3180, 3212, 2409, +3180, 3212, 2505, +3196, 3244, 2585, +3180, 3212, 2666, +3228, 3228, 2746, +3212, 3244, 2858, +3228, 3244, 2923, +3276, 3260, 2971, +3260, 3276, 3083, +3276, 3324, 3180, +3340, 3421, 2232, +3324, 3404, 2264, +3340, 3421, 2296, +3324, 3421, 2329, +3372, 3437, 2377, +3340, 3421, 2393, +3340, 3421, 2473, +3356, 3421, 2569, +3356, 3437, 2650, +3372, 3437, 2698, +3372, 3453, 2778, +3372, 3453, 2875, +3388, 3453, 2971, +3421, 3469, 3099, +3437, 3453, 3131, +3453, 3469, 3180, +3453, 3469, 3244, +3485, 3597, 2393, +3517, 3629, 2409, +3501, 3613, 2409, +3485, 3613, 2473, +3469, 3613, 2489, +3469, 3613, 2537, +3501, 3645, 2602, +3501, 3629, 2682, +3485, 3645, 2746, +3485, 3629, 2842, +3517, 3629, 2907, +3517, 3613, 3003, +3485, 3629, 3099, +3533, 3645, 3196, +3533, 3629, 3244, +3549, 3661, 3308, +3597, 3661, 3356, +2505, 1253, 996, +2537, 1253, 1060, +2473, 1253, 1140, +2377, 1317, 1317, +2296, 1365, 1413, +2184, 1445, 1526, +2104, 1493, 1622, +2039, 1542, 1670, +2072, 1574, 1718, +2039, 1558, 1750, +2056, 1574, 1847, +2104, 1606, 1943, +2120, 1638, 2039, +2152, 1654, 2104, +2184, 1670, 2168, +2232, 1702, 2264, +2232, 1734, 2345, +2521, 1269, 980, +2505, 1301, 1076, +2505, 1285, 1156, +2393, 1333, 1301, +2312, 1381, 1429, +2200, 1461, 1542, +2120, 1510, 1638, +2056, 1574, 1654, +2072, 1574, 1718, +2104, 1590, 1799, +2104, 1606, 1863, +2136, 1622, 1959, +2152, 1654, 2056, +2168, 1686, 2104, +2200, 1702, 2200, +2232, 1734, 2248, +2264, 1750, 2329, +2521, 1333, 1012, +2521, 1349, 1108, +2505, 1349, 1188, +2457, 1381, 1317, +2377, 1429, 1429, +2264, 1477, 1526, +2136, 1542, 1606, +2088, 1606, 1686, +2056, 1606, 1734, +2120, 1638, 1831, +2136, 1638, 1895, +2136, 1638, 1959, +2168, 1670, 2072, +2200, 1702, 2104, +2232, 1718, 2184, +2248, 1766, 2312, +2264, 1783, 2361, +2537, 1397, 1028, +2537, 1413, 1092, +2521, 1413, 1172, +2521, 1429, 1317, +2425, 1493, 1445, +2296, 1542, 1574, +2232, 1590, 1670, +2152, 1638, 1734, +2136, 1670, 1783, +2168, 1686, 1879, +2184, 1718, 1943, +2184, 1718, 2007, +2232, 1750, 2088, +2216, 1750, 2152, +2232, 1783, 2232, +2280, 1815, 2329, +2345, 1815, 2377, +2634, 1477, 1012, +2585, 1510, 1092, +2553, 1542, 1220, +2569, 1526, 1349, +2489, 1558, 1461, +2393, 1622, 1606, +2312, 1654, 1686, +2232, 1702, 1766, +2200, 1750, 1815, +2200, 1766, 1895, +2216, 1766, 1959, +2216, 1783, 2023, +2248, 1815, 2088, +2280, 1831, 2168, +2296, 1863, 2248, +2361, 1879, 2345, +2409, 1911, 2441, +2698, 1590, 980, +2682, 1590, 1028, +2650, 1638, 1188, +2569, 1654, 1317, +2585, 1654, 1461, +2489, 1686, 1590, +2409, 1734, 1718, +2312, 1799, 1799, +2248, 1847, 1847, +2280, 1863, 1927, +2264, 1863, 1975, +2329, 1895, 2072, +2345, 1895, 2136, +2377, 1911, 2248, +2393, 1943, 2312, +2425, 1959, 2345, +2425, 1975, 2441, +2794, 1734, 1044, +2778, 1718, 1092, +2778, 1734, 1172, +2730, 1766, 1285, +2650, 1799, 1477, +2618, 1799, 1606, +2569, 1847, 1734, +2505, 1895, 1847, +2393, 1943, 1927, +2393, 1975, 1975, +2361, 1975, 2023, +2409, 1991, 2104, +2409, 2007, 2184, +2457, 2039, 2280, +2457, 2072, 2361, +2489, 2088, 2441, +2553, 2136, 2569, +2778, 1911, 1140, +2794, 1927, 1188, +2794, 1911, 1237, +2826, 1943, 1333, +2826, 1959, 1429, +2714, 1991, 1654, +2730, 1991, 1766, +2634, 2039, 1879, +2537, 2072, 1959, +2473, 2120, 2039, +2473, 2136, 2104, +2505, 2152, 2184, +2505, 2168, 2248, +2553, 2200, 2361, +2569, 2184, 2409, +2602, 2200, 2489, +2585, 2200, 2553, +2810, 2136, 1317, +2810, 2152, 1349, +2810, 2120, 1365, +2810, 2136, 1429, +2842, 2120, 1493, +2842, 2120, 1590, +2778, 2152, 1799, +2746, 2152, 1895, +2682, 2184, 2056, +2602, 2248, 2152, +2553, 2248, 2184, +2553, 2264, 2248, +2602, 2280, 2345, +2634, 2296, 2425, +2666, 2312, 2489, +2682, 2345, 2553, +2666, 2361, 2666, +2826, 2280, 1429, +2826, 2296, 1477, +2858, 2296, 1526, +2842, 2296, 1574, +2858, 2296, 1606, +2907, 2296, 1686, +2891, 2312, 1783, +2923, 2312, 1879, +2842, 2312, 2072, +2778, 2361, 2200, +2698, 2409, 2280, +2714, 2441, 2361, +2682, 2425, 2409, +2730, 2441, 2489, +2746, 2441, 2553, +2730, 2489, 2650, +2746, 2489, 2714, +2875, 2505, 1622, +2891, 2489, 1622, +2891, 2505, 1654, +2875, 2505, 1718, +2907, 2489, 1750, +2891, 2489, 1847, +2907, 2489, 1943, +2923, 2505, 1975, +2955, 2489, 2039, +2939, 2505, 2232, +2842, 2537, 2377, +2794, 2569, 2425, +2810, 2602, 2505, +2810, 2602, 2602, +2858, 2634, 2698, +2842, 2666, 2746, +2858, 2666, 2810, +2939, 2682, 1799, +2939, 2682, 1799, +2923, 2682, 1815, +2939, 2698, 1895, +2923, 2698, 1927, +2955, 2698, 1991, +2939, 2698, 2056, +2971, 2714, 2136, +2971, 2714, 2200, +3003, 2714, 2296, +3083, 2682, 2361, +2971, 2730, 2553, +2923, 2746, 2569, +2955, 2746, 2650, +2923, 2778, 2730, +2971, 2794, 2810, +3019, 2826, 2907, +3083, 2842, 1911, +3099, 2875, 1927, +3083, 2858, 1943, +3115, 2858, 1991, +3115, 2875, 2072, +3099, 2875, 2120, +3083, 2875, 2216, +3083, 2891, 2280, +3083, 2907, 2329, +3067, 2907, 2409, +3067, 2891, 2457, +3099, 2907, 2569, +3099, 2891, 2698, +3083, 2939, 2794, +3035, 2955, 2810, +3067, 2955, 2891, +3115, 2987, 2987, +3228, 3051, 2023, +3228, 3051, 2023, +3228, 3067, 2088, +3212, 3051, 2120, +3212, 3067, 2184, +3180, 3051, 2232, +3212, 3067, 2312, +3212, 3067, 2345, +3196, 3083, 2441, +3212, 3067, 2505, +3212, 3099, 2618, +3244, 3115, 2698, +3228, 3115, 2762, +3228, 3131, 2875, +3212, 3131, 2939, +3180, 3131, 2987, +3212, 3148, 3067, +3308, 3244, 2136, +3292, 3228, 2152, +3292, 3244, 2168, +3324, 3228, 2232, +3276, 3244, 2248, +3292, 3228, 2329, +3292, 3228, 2345, +3292, 3260, 2457, +3308, 3244, 2521, +3308, 3260, 2634, +3308, 3244, 2682, +3308, 3260, 2762, +3308, 3292, 2842, +3324, 3292, 2939, +3372, 3324, 3035, +3340, 3308, 3099, +3372, 3308, 3164, +3469, 3437, 2280, +3485, 3437, 2280, +3469, 3437, 2312, +3469, 3437, 2345, +3485, 3469, 2425, +3469, 3469, 2425, +3485, 3453, 2521, +3469, 3453, 2585, +3453, 3453, 2634, +3485, 3469, 2762, +3485, 3485, 2810, +3485, 3469, 2891, +3501, 3469, 2987, +3469, 3469, 3067, +3517, 3501, 3180, +3501, 3501, 3212, +3533, 3501, 3324, +3597, 3629, 2409, +3549, 3629, 2425, +3581, 3613, 2425, +3581, 3613, 2457, +3597, 3645, 2489, +3565, 3629, 2521, +3549, 3629, 2585, +3581, 3629, 2698, +3581, 3645, 2746, +3565, 3645, 2842, +3581, 3645, 2875, +3565, 3645, 2971, +3581, 3661, 3083, +3597, 3677, 3228, +3613, 3661, 3292, +3677, 3677, 3324, +3677, 3694, 3356, +2682, 1333, 1028, +2666, 1333, 1108, +2666, 1349, 1188, +2602, 1413, 1333, +2505, 1445, 1461, +2441, 1510, 1574, +2329, 1590, 1702, +2264, 1638, 1766, +2216, 1638, 1783, +2232, 1654, 1831, +2264, 1686, 1943, +2280, 1718, 2023, +2280, 1718, 2056, +2312, 1750, 2184, +2329, 1766, 2232, +2377, 1799, 2329, +2409, 1815, 2409, +2682, 1365, 1044, +2698, 1365, 1092, +2714, 1381, 1220, +2634, 1429, 1349, +2521, 1493, 1493, +2441, 1526, 1590, +2361, 1574, 1686, +2264, 1638, 1766, +2264, 1686, 1799, +2264, 1686, 1863, +2264, 1702, 1927, +2280, 1734, 2007, +2312, 1750, 2120, +2312, 1766, 2168, +2361, 1783, 2248, +2409, 1815, 2312, +2457, 1847, 2441, +2698, 1429, 1076, +2698, 1397, 1108, +2714, 1413, 1220, +2682, 1461, 1365, +2569, 1526, 1493, +2473, 1558, 1590, +2377, 1622, 1686, +2312, 1670, 1783, +2280, 1718, 1831, +2248, 1718, 1879, +2296, 1734, 1943, +2296, 1750, 2023, +2329, 1783, 2088, +2361, 1799, 2168, +2361, 1831, 2248, +2425, 1831, 2329, +2457, 1879, 2441, +2730, 1493, 1092, +2746, 1493, 1156, +2746, 1493, 1237, +2698, 1510, 1333, +2634, 1574, 1493, +2553, 1622, 1590, +2457, 1686, 1718, +2345, 1702, 1783, +2296, 1766, 1831, +2329, 1766, 1863, +2329, 1799, 1975, +2329, 1799, 2007, +2361, 1831, 2136, +2393, 1831, 2200, +2425, 1879, 2264, +2457, 1895, 2377, +2489, 1927, 2409, +2842, 1558, 1044, +2730, 1574, 1156, +2746, 1606, 1269, +2730, 1606, 1365, +2698, 1622, 1477, +2569, 1670, 1606, +2521, 1734, 1718, +2425, 1766, 1799, +2361, 1815, 1863, +2345, 1847, 1927, +2393, 1879, 2023, +2425, 1895, 2104, +2441, 1879, 2168, +2457, 1927, 2216, +2441, 1927, 2280, +2505, 1959, 2377, +2521, 1991, 2473, +2907, 1638, 1012, +2891, 1670, 1140, +2826, 1718, 1269, +2778, 1702, 1349, +2794, 1718, 1510, +2730, 1766, 1638, +2634, 1799, 1766, +2553, 1879, 1847, +2489, 1895, 1927, +2473, 1959, 1991, +2441, 1959, 2039, +2473, 1959, 2104, +2473, 1975, 2200, +2521, 2023, 2280, +2553, 2039, 2361, +2553, 2072, 2457, +2602, 2104, 2537, +2987, 1766, 1044, +2955, 1783, 1108, +2939, 1799, 1204, +2875, 1831, 1365, +2842, 1863, 1493, +2826, 1863, 1638, +2746, 1911, 1783, +2634, 1943, 1879, +2585, 2007, 1975, +2521, 2056, 2007, +2553, 2072, 2088, +2553, 2088, 2152, +2602, 2120, 2248, +2602, 2136, 2329, +2618, 2168, 2409, +2602, 2152, 2489, +2682, 2168, 2553, +3019, 1991, 1204, +3003, 1975, 1237, +3003, 1991, 1269, +3019, 1991, 1365, +2955, 2007, 1526, +2891, 2039, 1670, +2923, 2056, 1815, +2810, 2088, 1943, +2730, 2136, 2039, +2634, 2168, 2120, +2618, 2200, 2168, +2602, 2200, 2232, +2666, 2216, 2312, +2682, 2232, 2393, +2682, 2232, 2441, +2698, 2264, 2537, +2730, 2280, 2618, +3003, 2136, 1285, +2987, 2136, 1301, +3035, 2136, 1349, +3067, 2136, 1429, +3051, 2104, 1493, +3035, 2152, 1638, +2939, 2168, 1831, +2955, 2168, 1959, +2875, 2216, 2088, +2746, 2264, 2200, +2714, 2312, 2200, +2714, 2329, 2280, +2746, 2345, 2361, +2746, 2361, 2473, +2794, 2377, 2521, +2762, 2377, 2602, +2794, 2409, 2698, +3051, 2345, 1461, +3035, 2345, 1477, +3067, 2345, 1526, +3067, 2345, 1558, +3051, 2345, 1606, +3051, 2329, 1686, +3067, 2312, 1783, +3019, 2345, 1991, +3003, 2345, 2072, +2939, 2393, 2216, +2858, 2457, 2345, +2810, 2457, 2361, +2826, 2489, 2457, +2842, 2505, 2537, +2858, 2521, 2618, +2891, 2521, 2682, +2907, 2569, 2778, +3083, 2553, 1622, +3067, 2537, 1638, +3051, 2521, 1622, +3067, 2521, 1686, +3083, 2537, 1766, +3099, 2537, 1831, +3115, 2537, 1927, +3180, 2537, 1991, +3148, 2521, 2056, +3083, 2553, 2264, +3035, 2602, 2441, +2955, 2634, 2473, +2955, 2650, 2505, +2939, 2666, 2602, +2955, 2666, 2714, +2971, 2682, 2730, +2987, 2698, 2875, +3148, 2714, 1783, +3131, 2714, 1799, +3131, 2714, 1831, +3115, 2714, 1863, +3099, 2714, 1911, +3131, 2714, 1959, +3131, 2714, 2023, +3148, 2714, 2088, +3212, 2714, 2200, +3212, 2698, 2248, +3164, 2730, 2457, +3115, 2762, 2569, +3067, 2794, 2618, +3067, 2810, 2698, +3099, 2826, 2778, +3099, 2826, 2842, +3099, 2858, 2923, +3212, 2891, 1911, +3180, 2907, 1943, +3212, 2907, 1975, +3164, 2907, 1991, +3196, 2907, 2072, +3196, 2923, 2136, +3180, 2907, 2200, +3180, 2907, 2248, +3228, 2907, 2296, +3212, 2907, 2361, +3276, 2923, 2473, +3276, 2907, 2537, +3228, 2939, 2698, +3180, 2987, 2778, +3196, 2987, 2891, +3164, 3019, 2955, +3212, 3035, 3051, +3356, 3099, 2056, +3324, 3083, 2072, +3340, 3099, 2104, +3356, 3115, 2152, +3340, 3115, 2216, +3340, 3099, 2280, +3340, 3099, 2296, +3340, 3131, 2425, +3324, 3115, 2473, +3292, 3115, 2553, +3292, 3131, 2634, +3292, 3115, 2682, +3324, 3115, 2762, +3292, 3115, 2875, +3292, 3148, 2955, +3292, 3196, 3035, +3308, 3180, 3083, +3421, 3276, 2152, +3421, 3276, 2184, +3453, 3260, 2216, +3437, 3276, 2248, +3404, 3276, 2312, +3437, 3292, 2361, +3421, 3292, 2425, +3404, 3292, 2489, +3453, 3308, 2585, +3437, 3324, 2682, +3453, 3308, 2778, +3453, 3324, 2810, +3453, 3308, 2891, +3453, 3324, 2971, +3485, 3340, 3083, +3485, 3372, 3164, +3453, 3356, 3228, +3597, 3469, 2329, +3581, 3469, 2329, +3597, 3485, 2377, +3581, 3469, 2393, +3581, 3485, 2425, +3581, 3485, 2473, +3549, 3469, 2521, +3565, 3469, 2618, +3565, 3453, 2682, +3581, 3469, 2746, +3597, 3469, 2826, +3597, 3501, 2907, +3613, 3501, 3019, +3581, 3517, 3067, +3597, 3517, 3180, +3613, 3517, 3244, +3629, 3549, 3340, +3677, 3661, 2425, +3677, 3661, 2457, +3677, 3661, 2441, +3694, 3645, 2473, +3694, 3645, 2505, +3677, 3645, 2537, +3694, 3677, 2634, +3710, 3677, 2730, +3677, 3661, 2778, +3710, 3677, 2907, +3694, 3677, 2923, +3710, 3677, 3019, +3710, 3694, 3115, +3726, 3694, 3212, +3694, 3694, 3308, +3758, 3726, 3404, +3806, 3758, 3517, +2923, 1445, 1108, +2907, 1429, 1156, +2907, 1445, 1285, +2842, 1477, 1381, +2730, 1526, 1510, +2634, 1590, 1606, +2553, 1638, 1718, +2441, 1686, 1799, +2409, 1766, 1847, +2409, 1783, 1911, +2441, 1783, 1975, +2473, 1799, 2056, +2473, 1815, 2120, +2489, 1847, 2216, +2521, 1863, 2280, +2553, 1895, 2361, +2553, 1927, 2441, +2923, 1429, 1076, +2923, 1445, 1156, +2907, 1445, 1237, +2842, 1461, 1349, +2778, 1526, 1493, +2650, 1606, 1622, +2585, 1654, 1718, +2489, 1718, 1783, +2409, 1766, 1831, +2425, 1783, 1911, +2425, 1815, 1991, +2457, 1815, 2072, +2489, 1831, 2152, +2489, 1847, 2216, +2537, 1879, 2329, +2553, 1895, 2361, +2569, 1943, 2441, +2939, 1477, 1108, +2923, 1477, 1188, +2907, 1477, 1269, +2875, 1493, 1365, +2794, 1574, 1526, +2714, 1622, 1638, +2602, 1702, 1734, +2521, 1750, 1815, +2441, 1799, 1863, +2409, 1815, 1927, +2489, 1831, 2023, +2489, 1847, 2104, +2489, 1879, 2168, +2537, 1879, 2216, +2537, 1911, 2296, +2569, 1943, 2393, +2602, 1959, 2473, +2955, 1558, 1156, +2939, 1558, 1204, +2923, 1558, 1285, +2923, 1574, 1397, +2858, 1638, 1526, +2778, 1670, 1622, +2666, 1734, 1766, +2602, 1783, 1831, +2537, 1847, 1927, +2505, 1863, 1959, +2521, 1879, 2007, +2537, 1911, 2088, +2505, 1911, 2136, +2553, 1927, 2264, +2553, 1943, 2296, +2634, 2007, 2425, +2650, 2039, 2521, +2987, 1654, 1172, +2987, 1654, 1204, +2971, 1654, 1253, +2971, 1670, 1381, +2907, 1702, 1526, +2826, 1750, 1686, +2762, 1799, 1750, +2682, 1863, 1879, +2553, 1895, 1943, +2537, 1911, 1975, +2553, 1943, 2072, +2569, 1975, 2136, +2569, 2007, 2232, +2618, 2023, 2312, +2618, 2039, 2393, +2666, 2056, 2473, +2666, 2088, 2553, +3099, 1702, 1092, +3035, 1766, 1220, +3003, 1783, 1333, +2987, 1783, 1413, +2971, 1783, 1526, +2907, 1815, 1670, +2826, 1863, 1783, +2762, 1959, 1927, +2682, 2007, 1991, +2618, 2039, 2023, +2634, 2056, 2104, +2650, 2072, 2184, +2650, 2088, 2248, +2666, 2088, 2312, +2682, 2120, 2393, +2714, 2136, 2505, +2746, 2152, 2569, +3228, 1847, 1124, +3164, 1847, 1156, +3180, 1879, 1269, +3083, 1927, 1445, +3067, 1927, 1590, +3051, 1927, 1702, +2939, 1975, 1831, +2875, 2039, 1959, +2778, 2088, 2056, +2714, 2136, 2120, +2682, 2152, 2152, +2666, 2152, 2200, +2746, 2184, 2345, +2730, 2168, 2361, +2762, 2200, 2473, +2778, 2232, 2569, +2794, 2248, 2618, +3260, 2007, 1172, +3244, 2007, 1204, +3228, 2007, 1285, +3196, 2007, 1365, +3115, 2056, 1590, +3083, 2039, 1686, +3099, 2072, 1815, +2987, 2104, 1959, +2923, 2168, 2088, +2826, 2200, 2168, +2778, 2264, 2232, +2810, 2264, 2264, +2778, 2264, 2361, +2794, 2296, 2441, +2810, 2312, 2553, +2842, 2345, 2602, +2858, 2345, 2698, +3244, 2168, 1285, +3228, 2168, 1317, +3260, 2168, 1349, +3228, 2152, 1429, +3244, 2168, 1542, +3212, 2200, 1702, +3131, 2232, 1879, +3099, 2232, 2007, +3051, 2280, 2152, +2955, 2345, 2248, +2858, 2377, 2296, +2842, 2377, 2312, +2858, 2393, 2409, +2891, 2409, 2521, +2891, 2425, 2553, +2923, 2457, 2682, +2939, 2473, 2730, +3228, 2377, 1461, +3244, 2393, 1510, +3228, 2377, 1493, +3276, 2361, 1526, +3276, 2361, 1606, +3292, 2361, 1686, +3276, 2361, 1815, +3196, 2409, 2023, +3196, 2425, 2168, +3099, 2473, 2312, +2987, 2489, 2377, +2939, 2537, 2425, +2955, 2553, 2505, +2971, 2553, 2585, +2971, 2585, 2666, +3003, 2585, 2730, +3019, 2618, 2826, +3260, 2569, 1590, +3260, 2569, 1622, +3260, 2569, 1654, +3244, 2569, 1718, +3260, 2569, 1766, +3308, 2537, 1799, +3292, 2537, 1895, +3324, 2553, 1975, +3260, 2569, 2152, +3244, 2585, 2345, +3164, 2634, 2441, +3131, 2666, 2537, +3067, 2698, 2585, +3099, 2698, 2650, +3099, 2714, 2730, +3115, 2714, 2794, +3115, 2730, 2875, +3292, 2746, 1766, +3324, 2746, 1783, +3324, 2746, 1815, +3308, 2746, 1879, +3308, 2746, 1911, +3324, 2730, 1927, +3324, 2746, 2039, +3356, 2746, 2104, +3404, 2746, 2184, +3388, 2762, 2312, +3356, 2762, 2457, +3292, 2810, 2618, +3196, 2842, 2682, +3196, 2842, 2714, +3180, 2858, 2794, +3228, 2891, 2907, +3228, 2907, 2955, +3372, 2939, 1927, +3388, 2939, 1927, +3372, 2939, 1959, +3372, 2939, 2023, +3388, 2955, 2072, +3372, 2955, 2120, +3356, 2923, 2200, +3388, 2939, 2248, +3404, 2955, 2312, +3404, 2939, 2377, +3469, 2939, 2457, +3404, 2971, 2682, +3372, 3003, 2778, +3324, 3035, 2826, +3324, 3051, 2907, +3372, 3083, 3003, +3340, 3067, 3051, +3404, 3115, 2072, +3404, 3115, 2072, +3404, 3115, 2104, +3404, 3115, 2136, +3404, 3131, 2216, +3421, 3131, 2280, +3404, 3115, 2296, +3388, 3115, 2361, +3404, 3115, 2425, +3404, 3131, 2537, +3437, 3131, 2618, +3453, 3131, 2682, +3517, 3131, 2714, +3421, 3180, 2955, +3404, 3212, 3003, +3437, 3212, 3067, +3437, 3228, 3148, +3565, 3308, 2216, +3597, 3324, 2232, +3581, 3308, 2248, +3565, 3308, 2280, +3565, 3324, 2345, +3565, 3324, 2393, +3581, 3324, 2457, +3581, 3324, 2521, +3549, 3324, 2618, +3533, 3324, 2666, +3565, 3340, 2762, +3581, 3356, 2842, +3581, 3356, 2891, +3613, 3356, 3003, +3597, 3372, 3148, +3597, 3404, 3228, +3581, 3421, 3276, +3694, 3485, 2329, +3694, 3485, 2361, +3694, 3485, 2361, +3694, 3501, 2409, +3710, 3501, 2489, +3710, 3501, 2489, +3710, 3501, 2553, +3694, 3501, 2650, +3677, 3517, 2714, +3694, 3517, 2778, +3677, 3517, 2875, +3710, 3517, 2955, +3694, 3533, 3019, +3710, 3533, 3131, +3710, 3549, 3196, +3694, 3549, 3260, +3710, 3581, 3356, +3838, 3694, 2473, +3806, 3677, 2457, +3822, 3677, 2505, +3822, 3694, 2553, +3806, 3694, 2569, +3790, 3677, 2602, +3790, 3694, 2666, +3806, 3677, 2730, +3790, 3694, 2842, +3790, 3710, 2907, +3838, 3742, 3003, +3854, 3774, 3131, +3854, 3758, 3196, +3854, 3790, 3340, +3822, 3774, 3388, +3838, 3790, 3533, +3854, 3806, 3645, +3115, 1526, 1172, +3099, 1526, 1253, +3099, 1542, 1285, +3067, 1542, 1413, +2971, 1590, 1542, +2891, 1670, 1670, +2794, 1750, 1783, +2730, 1799, 1847, +2650, 1831, 1943, +2618, 1879, 1991, +2602, 1879, 2039, +2618, 1879, 2104, +2634, 1911, 2184, +2650, 1959, 2280, +2666, 1991, 2361, +2698, 1991, 2441, +2746, 2056, 2553, +3099, 1558, 1172, +3115, 1542, 1204, +3099, 1542, 1285, +3083, 1574, 1445, +2971, 1622, 1558, +2891, 1670, 1670, +2826, 1766, 1783, +2746, 1815, 1863, +2634, 1863, 1959, +2618, 1879, 1959, +2585, 1879, 2023, +2602, 1911, 2120, +2634, 1911, 2184, +2666, 1959, 2280, +2698, 2007, 2393, +2730, 2023, 2473, +2730, 2039, 2553, +3131, 1590, 1172, +3148, 1590, 1220, +3115, 1574, 1301, +3067, 1590, 1413, +3019, 1654, 1574, +2955, 1718, 1686, +2842, 1783, 1799, +2746, 1815, 1879, +2650, 1879, 1943, +2618, 1911, 1975, +2650, 1927, 2056, +2666, 1959, 2136, +2682, 1991, 2248, +2666, 1991, 2312, +2714, 2023, 2409, +2730, 2056, 2489, +2762, 2072, 2569, +3131, 1638, 1172, +3115, 1638, 1253, +3131, 1654, 1317, +3115, 1622, 1413, +3035, 1670, 1542, +2987, 1734, 1654, +2875, 1815, 1799, +2810, 1863, 1895, +2730, 1943, 1975, +2682, 1975, 2007, +2682, 1991, 2072, +2698, 2007, 2152, +2682, 2023, 2216, +2730, 2056, 2345, +2762, 2088, 2409, +2794, 2088, 2473, +2810, 2088, 2537, +3148, 1718, 1237, +3180, 1750, 1301, +3164, 1750, 1349, +3180, 1750, 1477, +3180, 1750, 1574, +3051, 1831, 1702, +2987, 1895, 1863, +2875, 1943, 1927, +2778, 1991, 1991, +2714, 2072, 2072, +2730, 2072, 2152, +2730, 2072, 2200, +2762, 2104, 2296, +2794, 2104, 2361, +2794, 2120, 2441, +2810, 2120, 2505, +2826, 2152, 2585, +3324, 1799, 1204, +3276, 1831, 1285, +3228, 1831, 1365, +3228, 1847, 1477, +3212, 1847, 1590, +3148, 1879, 1734, +3083, 1943, 1831, +2955, 2023, 1975, +2907, 2056, 2072, +2794, 2120, 2136, +2762, 2120, 2152, +2810, 2136, 2248, +2794, 2152, 2312, +2826, 2152, 2377, +2842, 2200, 2473, +2842, 2200, 2537, +2891, 2232, 2634, +3404, 1895, 1188, +3372, 1895, 1204, +3324, 1943, 1349, +3228, 1991, 1526, +3228, 1991, 1654, +3212, 1991, 1734, +3148, 2023, 1847, +3067, 2072, 1991, +2987, 2136, 2088, +2891, 2200, 2184, +2842, 2216, 2216, +2858, 2232, 2296, +2858, 2248, 2361, +2858, 2248, 2425, +2907, 2280, 2553, +2907, 2296, 2618, +2907, 2329, 2666, +3437, 2056, 1204, +3421, 2039, 1253, +3388, 2056, 1317, +3372, 2056, 1397, +3276, 2120, 1638, +3260, 2120, 1766, +3244, 2136, 1911, +3164, 2184, 2039, +3067, 2232, 2152, +3019, 2296, 2232, +2907, 2312, 2280, +2923, 2345, 2329, +2923, 2361, 2393, +2939, 2361, 2489, +2955, 2377, 2553, +2955, 2409, 2618, +3003, 2441, 2746, +3404, 2200, 1301, +3469, 2216, 1365, +3453, 2216, 1397, +3437, 2200, 1461, +3421, 2232, 1574, +3340, 2248, 1734, +3292, 2280, 1927, +3308, 2296, 2056, +3228, 2312, 2136, +3099, 2377, 2280, +3019, 2425, 2345, +2987, 2473, 2409, +3003, 2457, 2489, +3035, 2505, 2569, +3035, 2521, 2634, +3051, 2537, 2746, +3051, 2537, 2778, +3437, 2393, 1445, +3469, 2409, 1461, +3469, 2409, 1493, +3485, 2409, 1574, +3469, 2393, 1622, +3469, 2409, 1750, +3437, 2409, 1895, +3388, 2457, 2088, +3340, 2457, 2200, +3292, 2521, 2345, +3164, 2553, 2457, +3083, 2585, 2473, +3099, 2602, 2521, +3099, 2618, 2602, +3115, 2634, 2714, +3164, 2650, 2762, +3164, 2650, 2891, +3469, 2585, 1590, +3469, 2585, 1606, +3453, 2585, 1654, +3485, 2569, 1686, +3469, 2569, 1750, +3533, 2569, 1847, +3549, 2553, 1927, +3501, 2569, 2007, +3421, 2602, 2216, +3437, 2602, 2345, +3340, 2666, 2489, +3260, 2714, 2585, +3212, 2746, 2634, +3212, 2762, 2698, +3228, 2762, 2762, +3244, 2794, 2858, +3260, 2778, 2907, +3485, 2778, 1750, +3485, 2778, 1799, +3469, 2762, 1815, +3469, 2778, 1847, +3485, 2762, 1895, +3533, 2778, 1959, +3517, 2746, 1991, +3565, 2762, 2088, +3565, 2746, 2168, +3549, 2778, 2345, +3517, 2794, 2505, +3421, 2810, 2634, +3356, 2875, 2714, +3308, 2907, 2762, +3324, 2923, 2875, +3324, 2939, 2939, +3356, 2939, 3019, +3533, 2971, 1895, +3533, 3003, 1943, +3549, 2987, 1927, +3533, 2971, 1991, +3581, 2987, 2039, +3581, 2955, 2088, +3549, 2987, 2184, +3565, 2987, 2264, +3613, 2971, 2329, +3645, 2971, 2361, +3645, 2987, 2505, +3581, 3019, 2730, +3533, 3035, 2810, +3404, 3067, 2875, +3404, 3051, 2923, +3404, 3067, 2971, +3437, 3083, 3083, +3581, 3164, 2056, +3565, 3148, 2072, +3565, 3164, 2120, +3581, 3131, 2136, +3549, 3148, 2216, +3581, 3148, 2248, +3581, 3164, 2329, +3597, 3164, 2377, +3597, 3180, 2457, +3613, 3164, 2521, +3645, 3164, 2602, +3661, 3164, 2698, +3645, 3180, 2858, +3597, 3228, 3003, +3549, 3260, 3051, +3549, 3260, 3115, +3565, 3276, 3196, +3710, 3356, 2248, +3694, 3340, 2280, +3694, 3340, 2280, +3694, 3372, 2361, +3710, 3372, 2393, +3694, 3372, 2425, +3677, 3372, 2489, +3694, 3356, 2537, +3694, 3372, 2618, +3694, 3388, 2682, +3694, 3372, 2794, +3742, 3388, 2826, +3758, 3388, 2907, +3790, 3372, 3003, +3710, 3404, 3196, +3677, 3437, 3244, +3710, 3437, 3308, +3854, 3533, 2409, +3854, 3533, 2409, +3806, 3517, 2393, +3854, 3533, 2473, +3806, 3549, 2505, +3822, 3533, 2537, +3822, 3549, 2602, +3806, 3533, 2666, +3822, 3533, 2730, +3790, 3533, 2810, +3806, 3549, 2858, +3790, 3549, 2955, +3790, 3581, 3051, +3806, 3581, 3148, +3822, 3581, 3212, +3822, 3597, 3324, +3806, 3597, 3388, +3983, 3758, 2553, +3983, 3774, 2602, +3950, 3758, 2618, +3967, 3774, 2634, +3967, 3774, 2698, +3950, 3774, 2762, +3934, 3758, 2746, +3950, 3758, 2891, +3934, 3758, 2955, +3918, 3774, 3019, +3950, 3774, 3131, +3934, 3790, 3196, +3950, 3806, 3340, +3934, 3790, 3404, +3950, 3854, 3613, +3918, 3854, 3661, +3902, 3870, 3806] + } +} \ No newline at end of file diff --git a/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Photoshop/Log2-48nits/o_invShaped/test_clt_32_LUT.3dl b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Photoshop/Log2-48nits/o_invShaped/test_clt_32_LUT.3dl new file mode 100644 index 0000000000..956644638c --- /dev/null +++ b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Photoshop/Log2-48nits/o_invShaped/test_clt_32_LUT.3dl @@ -0,0 +1,32769 @@ +0 33 66 99 132 165 198 231 264 297 330 363 396 429 462 495 528 561 594 627 660 693 726 759 792 825 858 891 924 957 990 1023 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 28 +0 0 152 +0 0 280 +0 0 408 +0 0 537 +0 0 667 +0 0 797 +0 0 928 +0 0 1084 +0 0 1291 +0 0 1472 +0 0 1634 +361 0 1771 +1145 0 1881 +1561 0 2006 +1561 0 2154 +432 987 2341 +1228 621 2470 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 54 +0 0 173 +0 0 295 +0 0 419 +0 0 545 +0 0 673 +0 0 802 +0 0 932 +0 0 1087 +0 0 1293 +0 0 1473 +0 0 1635 +370 0 1772 +1144 0 1882 +1559 0 2006 +1558 0 2154 +428 992 2341 +1232 621 2470 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 87 +0 0 198 +0 0 315 +0 0 434 +0 0 557 +0 0 682 +0 0 809 +0 0 937 +0 0 1091 +0 0 1295 +0 0 1474 +0 0 1635 +381 0 1773 +1143 0 1883 +1556 0 2007 +1554 0 2155 +423 998 2341 +1238 621 2470 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +0 0 0 +0 0 0 +0 0 0 +0 0 31 +0 0 127 +0 0 230 +0 0 340 +0 0 454 +0 0 572 +0 0 693 +0 0 817 +0 0 943 +0 0 1095 +0 0 1298 +0 0 1476 +0 0 1636 +395 0 1774 +1142 0 1883 +1552 0 2008 +1548 0 2156 +416 1005 2342 +1246 621 2470 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +0 0 0 +0 0 0 +0 0 0 +0 0 31 +0 0 176 +0 0 270 +0 0 371 +0 0 478 +0 0 591 +0 0 708 +0 0 828 +0 0 952 +0 0 1101 +0 0 1302 +0 0 1479 +0 0 1637 +414 0 1775 +1140 0 1884 +1547 0 2010 +1540 58 2158 +407 1015 2342 +1257 621 2470 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +0 0 0 +0 0 0 +0 0 0 +0 0 31 +0 7 176 +0 63 318 +0 63 410 +0 63 509 +0 63 615 +0 63 727 +0 63 843 +0 63 963 +0 103 1109 +0 30 1307 +0 30 1482 +0 3 1639 +438 0 1777 +1137 0 1886 +1539 0 2011 +1530 197 2160 +394 1028 2343 +1270 621 2470 +1732 30 2504 +1732 30 2504 +1732 30 2504 +1732 30 2504 +1732 30 2504 +1732 30 2504 +1732 30 2504 +1732 30 2504 +1732 30 2504 +1732 30 2504 +0 4 0 +0 23 0 +0 47 0 +0 77 31 +0 114 176 +0 159 318 +0 214 457 +0 214 548 +0 214 646 +0 214 751 +0 214 862 +0 214 977 +0 243 1120 +0 163 1314 +0 163 1487 +0 142 1641 +468 0 1779 +1134 0 1888 +1530 32 2014 +1515 333 2163 +376 1045 2344 +1287 621 2470 +1732 163 2504 +1732 163 2504 +1732 163 2504 +1732 163 2504 +1732 163 2504 +1732 163 2504 +1732 163 2504 +1732 163 2504 +1732 163 2504 +1732 163 2504 +0 144 0 +0 157 0 +0 175 0 +0 198 31 +0 227 176 +0 262 318 +0 306 457 +0 359 595 +0 359 684 +0 359 782 +0 359 886 +0 359 996 +0 380 1134 +0 295 1323 +0 295 1494 +0 280 1644 +506 122 1783 +1129 0 1891 +1516 164 2017 +1495 469 2167 +352 1066 2345 +1309 621 2470 +1732 295 2505 +1732 295 2505 +1732 295 2505 +1732 295 2505 +1732 295 2505 +1732 295 2505 +1732 295 2505 +1732 295 2505 +1732 295 2505 +1732 295 2505 +0 281 0 +0 291 0 +0 304 0 +0 322 31 +0 344 176 +0 371 318 +0 406 457 +0 449 595 +0 501 730 +0 501 819 +0 501 916 +0 501 1020 +0 516 1151 +0 426 1335 +0 426 1502 +0 415 1648 +552 265 1787 +1123 111 1894 +1498 296 2021 +1467 603 2172 +317 1093 2347 +1348 639 2470 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +0 417 0 +0 424 0 +0 434 0 +0 447 31 +0 464 176 +0 486 318 +0 513 457 +0 547 595 +0 589 730 +0 640 865 +0 640 954 +0 640 1050 +0 651 1174 +0 570 1350 +0 559 1512 +0 550 1653 +556 441 1791 +1115 244 1898 +1471 428 2027 +1426 737 2178 +265 1128 2349 +1396 662 2470 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +0 552 0 +0 557 0 +0 565 0 +0 575 31 +0 587 176 +0 604 318 +0 625 457 +0 652 595 +0 686 730 +0 727 865 +0 777 1000 +0 777 1088 +0 786 1203 +0 726 1370 +0 691 1526 +0 685 1662 +556 606 1796 +1132 422 1904 +1434 560 2035 +1365 871 2187 +186 1169 2352 +1454 691 2470 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +0 686 0 +0 690 0 +0 696 0 +0 703 31 +0 713 176 +0 726 318 +0 742 457 +0 763 595 +0 789 730 +0 823 865 +0 864 1000 +0 913 1133 +0 920 1239 +0 876 1395 +0 823 1544 +0 818 1675 +556 761 1803 +1160 593 1912 +1378 692 2045 +1267 1004 2199 +0 1212 2357 +1520 728 2470 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +0 857 100 +0 857 131 +0 861 202 +0 866 282 +0 873 371 +0 882 468 +0 894 573 +0 909 683 +0 928 797 +0 953 916 +0 984 1038 +0 1023 1162 +0 1061 1287 +0 1030 1430 +0 984 1569 +0 971 1697 +566 941 1817 +1178 799 1926 +1302 849 2057 +1119 1137 2212 +0 1255 2365 +1585 801 2470 +1738 957 2513 +1738 957 2513 +1738 957 2513 +1738 957 2513 +1738 957 2513 +1738 957 2513 +1738 957 2513 +1738 957 2513 +1738 957 2513 +1738 957 2513 +0 1184 1027 +0 1184 1031 +0 1184 1036 +0 1184 1043 +0 1184 1052 +0 1184 1064 +0 1184 1080 +0 1184 1099 +0 1184 1125 +0 1190 1168 +0 1209 1242 +0 1232 1325 +0 1257 1416 +0 1237 1493 +0 1209 1617 +0 1222 1740 +636 1187 1854 +1040 1131 1961 +1243 1131 2080 +1031 1271 2224 +472 1312 2372 +1588 1032 2472 +1765 1144 2512 +1765 1144 2512 +1765 1144 2512 +1765 1144 2512 +1765 1144 2512 +1765 1144 2512 +1765 1144 2512 +1765 1144 2512 +1765 1144 2512 +1765 1144 2512 +0 1421 1377 +0 1421 1379 +0 1421 1382 +0 1421 1385 +0 1421 1389 +0 1421 1395 +0 1421 1402 +0 1421 1412 +0 1421 1425 +0 1421 1442 +0 1421 1463 +0 1421 1491 +0 1432 1546 +0 1418 1604 +0 1399 1673 +0 1412 1786 +636 1404 1895 +1048 1353 1999 +1151 1350 2110 +878 1405 2240 +666 1388 2378 +1601 1209 2473 +1799 1314 2510 +1799 1314 2510 +1799 1314 2510 +1799 1314 2510 +1799 1314 2510 +1799 1314 2510 +1799 1314 2510 +1799 1314 2510 +1799 1314 2510 +1799 1314 2510 +901 1580 1648 +901 1579 1649 +901 1579 1650 +901 1579 1652 +901 1578 1655 +901 1577 1658 +901 1576 1662 +901 1574 1668 +901 1572 1675 +901 1569 1685 +901 1567 1698 +901 1567 1714 +886 1567 1736 +886 1577 1788 +886 1569 1838 +890 1552 1888 +807 1557 1969 +921 1536 2067 +942 1537 2170 +810 1524 2268 +1125 1501 2382 +1680 1435 2473 +1845 1472 2509 +1845 1472 2509 +1845 1472 2509 +1845 1472 2509 +1845 1472 2509 +1845 1472 2509 +1845 1472 2509 +1845 1472 2509 +1845 1472 2509 +1845 1472 2509 +1449 1705 1856 +1448 1705 1856 +1447 1705 1857 +1446 1705 1859 +1444 1705 1860 +1441 1705 1862 +1438 1705 1865 +1433 1705 1868 +1427 1705 1873 +1426 1703 1880 +1426 1700 1888 +1426 1696 1899 +1423 1691 1913 +1400 1685 1931 +1400 1696 1976 +1370 1702 2022 +1371 1685 2062 +1192 1672 2128 +1127 1678 2221 +1173 1647 2295 +1519 1631 2386 +1775 1634 2475 +1894 1629 2511 +1894 1629 2511 +1894 1629 2511 +1894 1629 2511 +1894 1629 2511 +1894 1629 2511 +1894 1629 2511 +1894 1629 2511 +1894 1629 2511 +1894 1629 2511 +1785 1818 1978 +1786 1818 1978 +1786 1818 1979 +1786 1818 1980 +1786 1818 1981 +1787 1818 1982 +1788 1818 1983 +1789 1818 1986 +1790 1818 1988 +1792 1818 1992 +1788 1818 1998 +1781 1818 2007 +1772 1818 2018 +1752 1824 2037 +1733 1818 2052 +1727 1802 2080 +1685 1816 2123 +1705 1809 2166 +1657 1793 2234 +1664 1793 2304 +1754 1797 2389 +1874 1790 2475 +1964 1800 2514 +1964 1800 2514 +1964 1800 2514 +1964 1800 2514 +1964 1800 2514 +1964 1800 2514 +1964 1800 2514 +1964 1800 2514 +1964 1800 2514 +1964 1800 2514 +1958 1958 2028 +1957 1958 2029 +1957 1958 2029 +1957 1958 2030 +1956 1958 2031 +1956 1958 2031 +1956 1958 2033 +1955 1958 2035 +1954 1958 2037 +1953 1958 2041 +1951 1958 2045 +1948 1958 2051 +1946 1958 2058 +1941 1962 2068 +1935 1968 2081 +1927 1969 2115 +1913 1965 2153 +1905 1963 2189 +1920 1969 2243 +1881 1969 2320 +1929 1954 2391 +2032 1964 2481 +2093 1969 2517 +2093 1969 2517 +2093 1969 2517 +2093 1969 2517 +2093 1969 2517 +2093 1969 2517 +2093 1969 2517 +2093 1969 2517 +2093 1969 2517 +2093 1969 2517 +2119 2119 2068 +2119 2119 2068 +2119 2119 2068 +2119 2120 2069 +2119 2120 2069 +2119 2120 2071 +2119 2120 2072 +2119 2121 2073 +2119 2122 2076 +2119 2122 2079 +2119 2124 2083 +2119 2125 2088 +2119 2127 2095 +2119 2127 2101 +2119 2127 2110 +2115 2131 2133 +2108 2133 2164 +2103 2131 2206 +2110 2135 2256 +2119 2135 2316 +2148 2131 2395 +2212 2147 2485 +2261 2159 2524 +2261 2159 2524 +2261 2159 2524 +2261 2159 2524 +2261 2159 2524 +2261 2159 2524 +2261 2159 2524 +2261 2159 2524 +2261 2159 2524 +2261 2159 2524 +2370 2355 2124 +2370 2355 2124 +2370 2355 2124 +2370 2355 2125 +2369 2356 2125 +2369 2356 2126 +2369 2356 2126 +2369 2356 2127 +2369 2357 2129 +2368 2357 2131 +2367 2358 2133 +2368 2359 2137 +2369 2360 2143 +2370 2358 2146 +2369 2356 2148 +2368 2358 2163 +2370 2358 2193 +2369 2358 2226 +2372 2355 2273 +2383 2356 2337 +2410 2367 2405 +2467 2385 2498 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2681 2655 1963 +2681 2655 1963 +2681 2655 1963 +2681 2655 1963 +2681 2654 1964 +2681 2654 1965 +2681 2654 1966 +2681 2654 1968 +2681 2654 1967 +2681 2654 1965 +2680 2653 1964 +2680 2653 1961 +2679 2652 1961 +2678 2653 1968 +2677 2654 1989 +2676 2653 2013 +2675 2649 2032 +2677 2655 2124 +2681 2656 2208 +2687 2661 2306 +2695 2667 2410 +2715 2678 2527 +2722 2684 2575 +2722 2684 2575 +2722 2684 2575 +2722 2684 2575 +2722 2684 2575 +2722 2684 2575 +2722 2684 2575 +2722 2684 2575 +2722 2684 2575 +2722 2684 2575 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2771 2455 +2709 2773 2484 +2714 2773 2520 +2714 2773 2553 +2717 2777 2616 +2722 2785 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2771 2455 +2709 2773 2484 +2714 2773 2520 +2714 2773 2553 +2717 2777 2616 +2722 2785 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2771 2455 +2709 2773 2484 +2714 2773 2520 +2714 2773 2553 +2717 2777 2616 +2722 2785 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2771 2455 +2709 2773 2484 +2714 2773 2520 +2714 2773 2553 +2717 2777 2616 +2722 2785 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2771 2455 +2709 2773 2484 +2714 2773 2520 +2714 2773 2553 +2717 2777 2616 +2722 2785 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2771 2455 +2709 2773 2484 +2714 2773 2520 +2714 2773 2553 +2717 2777 2616 +2722 2785 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2771 2455 +2709 2773 2484 +2714 2773 2520 +2714 2773 2553 +2717 2777 2616 +2722 2785 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2771 2455 +2709 2773 2484 +2714 2773 2520 +2714 2773 2553 +2717 2777 2616 +2722 2785 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2771 2455 +2709 2773 2484 +2714 2773 2520 +2714 2773 2553 +2717 2777 2616 +2722 2785 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2771 2455 +2709 2773 2484 +2714 2773 2520 +2714 2773 2553 +2717 2777 2616 +2722 2785 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 28 +0 0 152 +0 0 280 +0 0 408 +0 0 537 +0 0 667 +0 0 797 +0 0 928 +0 0 1088 +0 0 1293 +0 0 1473 +0 0 1634 +398 0 1772 +1148 0 1882 +1561 0 2006 +1560 0 2154 +428 987 2341 +1231 619 2470 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 36 +0 0 159 +0 0 285 +0 0 412 +0 0 540 +0 0 669 +0 0 799 +0 0 930 +0 0 1089 +0 0 1294 +0 0 1474 +0 0 1635 +378 0 1771 +1147 0 1882 +1561 0 2006 +1559 0 2154 +428 992 2341 +1235 621 2470 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 71 +0 0 186 +0 0 305 +0 0 427 +0 0 551 +0 0 678 +0 0 805 +0 0 935 +0 0 1092 +0 0 1296 +0 0 1475 +0 0 1635 +389 0 1772 +1146 0 1883 +1558 0 2007 +1555 0 2155 +423 998 2341 +1241 621 2470 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +0 0 0 +0 0 0 +0 0 0 +0 0 13 +0 0 112 +0 0 219 +0 0 330 +0 0 446 +0 0 566 +0 0 689 +0 0 814 +0 0 941 +0 0 1097 +0 0 1299 +0 0 1477 +0 0 1636 +403 0 1773 +1145 0 1884 +1554 0 2008 +1549 0 2156 +416 1005 2342 +1249 621 2470 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +0 0 0 +0 0 0 +0 0 0 +0 0 13 +0 0 163 +0 0 259 +0 0 363 +0 0 472 +0 0 586 +0 0 704 +0 0 825 +0 0 949 +0 0 1103 +0 0 1303 +0 0 1480 +0 0 1637 +422 0 1775 +1143 0 1884 +1548 0 2010 +1541 50 2158 +407 1015 2342 +1259 621 2470 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +0 0 0 +0 0 0 +0 0 0 +0 0 13 +0 0 163 +0 38 309 +0 38 402 +0 38 503 +0 38 610 +0 38 723 +0 38 840 +0 38 961 +0 102 1111 +0 30 1308 +0 30 1483 +0 0 1639 +445 0 1776 +1140 0 1886 +1541 0 2011 +1531 190 2160 +394 1028 2343 +1272 621 2470 +1732 30 2504 +1732 30 2504 +1732 30 2504 +1732 30 2504 +1732 30 2504 +1732 30 2504 +1732 30 2504 +1732 30 2504 +1732 30 2504 +1732 30 2504 +0 4 0 +0 0 0 +0 20 0 +0 52 13 +0 91 163 +0 139 309 +0 195 450 +0 195 542 +0 195 641 +0 195 748 +0 195 859 +0 195 975 +0 242 1121 +0 163 1315 +0 163 1488 +0 135 1641 +475 0 1779 +1137 0 1888 +1532 32 2014 +1516 329 2163 +376 1045 2344 +1289 621 2470 +1732 163 2504 +1732 163 2504 +1732 163 2504 +1732 163 2504 +1732 163 2504 +1732 163 2504 +1732 163 2504 +1732 163 2504 +1732 163 2504 +1732 163 2504 +0 144 0 +0 137 0 +0 155 0 +0 179 13 +0 209 163 +0 246 309 +0 291 450 +0 346 589 +0 346 680 +0 346 778 +0 346 883 +0 346 994 +0 380 1135 +0 295 1324 +0 295 1494 +0 274 1644 +512 108 1782 +1133 0 1891 +1518 164 2017 +1496 465 2167 +352 1066 2345 +1311 621 2470 +1732 295 2505 +1732 295 2505 +1732 295 2505 +1732 295 2505 +1732 295 2505 +1732 295 2505 +1732 295 2505 +1732 295 2505 +1732 295 2505 +1732 295 2505 +0 281 0 +0 276 0 +0 289 0 +0 307 13 +0 330 163 +0 359 309 +0 394 450 +0 438 589 +0 491 727 +0 491 816 +0 491 914 +0 491 1018 +0 516 1153 +0 426 1336 +0 426 1502 +0 412 1648 +557 254 1787 +1126 111 1894 +1500 296 2021 +1468 601 2172 +317 1093 2347 +1350 639 2470 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +0 417 0 +0 413 0 +0 423 0 +0 437 13 +0 454 163 +0 476 309 +0 504 450 +0 539 589 +0 581 727 +0 633 862 +0 633 952 +0 633 1049 +0 651 1176 +0 570 1351 +0 559 1513 +0 547 1653 +561 434 1790 +1118 244 1898 +1474 428 2027 +1427 736 2178 +265 1128 2349 +1398 662 2470 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +0 552 0 +0 549 0 +0 557 0 +0 566 13 +0 579 163 +0 596 309 +0 618 450 +0 645 589 +0 679 727 +0 721 862 +0 772 997 +0 772 1086 +0 785 1204 +0 726 1371 +0 691 1527 +0 682 1662 +561 601 1796 +1135 422 1904 +1436 560 2035 +1366 869 2187 +186 1169 2352 +1455 691 2470 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +0 686 0 +0 684 0 +0 690 0 +0 697 13 +0 707 163 +0 720 309 +0 736 450 +0 758 589 +0 784 727 +0 818 862 +0 859 997 +0 909 1132 +0 919 1240 +0 876 1396 +0 823 1545 +0 817 1675 +561 758 1802 +1163 593 1912 +1381 692 2045 +1269 1003 2199 +0 1212 2357 +1522 728 2470 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +0 854 85 +0 854 130 +0 858 201 +0 863 282 +0 870 371 +0 879 468 +0 891 572 +0 906 682 +0 925 797 +0 950 916 +0 981 1038 +0 1020 1162 +0 1060 1288 +0 1029 1430 +0 983 1570 +0 969 1697 +572 942 1817 +1182 800 1926 +1302 849 2057 +1120 1137 2212 +0 1254 2365 +1585 800 2470 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +0 1183 1025 +0 1183 1031 +0 1183 1036 +0 1183 1043 +0 1183 1052 +0 1183 1064 +0 1183 1080 +0 1183 1099 +0 1183 1125 +0 1188 1168 +0 1207 1242 +0 1231 1325 +0 1257 1417 +0 1236 1493 +0 1208 1617 +0 1221 1741 +640 1187 1855 +1045 1132 1961 +1243 1131 2080 +1031 1271 2225 +498 1311 2371 +1589 1031 2471 +1765 1143 2512 +1765 1143 2512 +1765 1143 2512 +1765 1143 2512 +1765 1143 2512 +1765 1143 2512 +1765 1143 2512 +1765 1143 2512 +1765 1143 2512 +1765 1143 2512 +0 1421 1376 +0 1421 1379 +0 1421 1382 +0 1421 1385 +0 1421 1389 +0 1421 1395 +0 1421 1402 +0 1421 1412 +0 1421 1425 +0 1421 1442 +0 1421 1463 +0 1421 1491 +0 1431 1546 +0 1417 1605 +0 1399 1673 +0 1411 1786 +640 1405 1896 +1052 1353 1999 +1151 1350 2110 +878 1405 2240 +684 1387 2378 +1602 1208 2473 +1799 1313 2510 +1799 1313 2510 +1799 1313 2510 +1799 1313 2510 +1799 1313 2510 +1799 1313 2510 +1799 1313 2510 +1799 1313 2510 +1799 1313 2510 +1799 1313 2510 +913 1579 1648 +912 1579 1649 +912 1579 1651 +912 1579 1653 +912 1578 1655 +912 1577 1658 +912 1576 1662 +912 1574 1668 +912 1572 1675 +912 1569 1685 +912 1567 1698 +912 1567 1714 +892 1567 1736 +891 1577 1788 +891 1569 1838 +896 1552 1889 +818 1557 1970 +929 1536 2067 +946 1537 2170 +810 1524 2268 +1128 1500 2382 +1680 1435 2473 +1845 1471 2509 +1845 1471 2509 +1845 1471 2509 +1845 1471 2509 +1845 1471 2509 +1845 1471 2509 +1845 1471 2509 +1845 1471 2509 +1845 1471 2509 +1845 1471 2509 +1450 1705 1856 +1449 1705 1856 +1448 1705 1857 +1446 1705 1859 +1444 1705 1860 +1442 1705 1862 +1439 1705 1865 +1434 1705 1868 +1427 1705 1873 +1427 1703 1880 +1427 1700 1888 +1427 1696 1899 +1424 1691 1913 +1401 1685 1931 +1401 1696 1976 +1370 1701 2022 +1372 1685 2062 +1195 1672 2128 +1129 1678 2221 +1176 1647 2295 +1520 1631 2386 +1776 1634 2475 +1894 1629 2511 +1894 1629 2511 +1894 1629 2511 +1894 1629 2511 +1894 1629 2511 +1894 1629 2511 +1894 1629 2511 +1894 1629 2511 +1894 1629 2511 +1894 1629 2511 +1786 1817 1978 +1786 1817 1978 +1786 1817 1979 +1786 1817 1980 +1787 1817 1981 +1787 1817 1982 +1788 1817 1983 +1789 1817 1986 +1790 1817 1988 +1793 1817 1992 +1789 1817 1998 +1782 1817 2007 +1772 1818 2018 +1753 1824 2036 +1733 1818 2052 +1727 1803 2080 +1686 1816 2123 +1706 1808 2166 +1658 1793 2234 +1664 1793 2304 +1754 1797 2389 +1874 1790 2475 +1964 1800 2514 +1964 1800 2514 +1964 1800 2514 +1964 1800 2514 +1964 1800 2514 +1964 1800 2514 +1964 1800 2514 +1964 1800 2514 +1964 1800 2514 +1964 1800 2514 +1958 1958 2028 +1958 1958 2029 +1957 1958 2029 +1957 1958 2030 +1957 1958 2031 +1956 1958 2031 +1956 1958 2033 +1955 1958 2035 +1954 1958 2037 +1953 1958 2041 +1951 1958 2045 +1948 1958 2051 +1946 1958 2058 +1941 1962 2068 +1936 1968 2081 +1927 1969 2115 +1913 1965 2153 +1905 1963 2189 +1920 1969 2243 +1881 1968 2320 +1929 1954 2392 +2033 1964 2481 +2094 1969 2517 +2094 1969 2517 +2094 1969 2517 +2094 1969 2517 +2094 1969 2517 +2094 1969 2517 +2094 1969 2517 +2094 1969 2517 +2094 1969 2517 +2094 1969 2517 +2120 2119 2068 +2120 2119 2068 +2120 2119 2068 +2120 2120 2069 +2120 2120 2069 +2120 2120 2070 +2120 2120 2072 +2120 2121 2073 +2120 2122 2076 +2120 2122 2079 +2120 2124 2083 +2120 2125 2088 +2119 2127 2095 +2119 2127 2101 +2119 2127 2110 +2115 2131 2133 +2109 2133 2164 +2103 2131 2206 +2111 2135 2256 +2119 2135 2316 +2148 2131 2395 +2212 2147 2485 +2261 2159 2524 +2261 2159 2524 +2261 2159 2524 +2261 2159 2524 +2261 2159 2524 +2261 2159 2524 +2261 2159 2524 +2261 2159 2524 +2261 2159 2524 +2261 2159 2524 +2370 2355 2124 +2370 2355 2124 +2370 2355 2124 +2370 2355 2125 +2370 2356 2125 +2369 2356 2126 +2369 2356 2126 +2369 2356 2127 +2369 2357 2129 +2368 2357 2131 +2367 2358 2133 +2368 2359 2137 +2369 2360 2143 +2370 2358 2146 +2369 2356 2148 +2368 2358 2163 +2370 2358 2193 +2369 2358 2226 +2372 2355 2273 +2383 2356 2337 +2410 2367 2405 +2467 2385 2498 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2681 2655 1963 +2681 2655 1963 +2681 2655 1963 +2681 2655 1964 +2681 2655 1965 +2681 2654 1965 +2681 2654 1966 +2681 2654 1968 +2681 2654 1967 +2681 2654 1966 +2680 2653 1964 +2680 2653 1962 +2679 2652 1962 +2678 2653 1969 +2677 2654 1990 +2676 2653 2014 +2675 2650 2033 +2677 2655 2124 +2681 2656 2208 +2687 2661 2306 +2695 2667 2410 +2715 2678 2527 +2722 2684 2575 +2722 2684 2575 +2722 2684 2575 +2722 2684 2575 +2722 2684 2575 +2722 2684 2575 +2722 2684 2575 +2722 2684 2575 +2722 2684 2575 +2722 2684 2575 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2771 2455 +2709 2773 2484 +2714 2774 2520 +2714 2773 2553 +2717 2777 2616 +2722 2785 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2771 2455 +2709 2773 2484 +2714 2774 2520 +2714 2773 2553 +2717 2777 2616 +2722 2785 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2771 2455 +2709 2773 2484 +2714 2774 2520 +2714 2773 2553 +2717 2777 2616 +2722 2785 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2771 2455 +2709 2773 2484 +2714 2774 2520 +2714 2773 2553 +2717 2777 2616 +2722 2785 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2771 2455 +2709 2773 2484 +2714 2774 2520 +2714 2773 2553 +2717 2777 2616 +2722 2785 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2771 2455 +2709 2773 2484 +2714 2774 2520 +2714 2773 2553 +2717 2777 2616 +2722 2785 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2771 2455 +2709 2773 2484 +2714 2774 2520 +2714 2773 2553 +2717 2777 2616 +2722 2785 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2771 2455 +2709 2773 2484 +2714 2774 2520 +2714 2773 2553 +2717 2777 2616 +2722 2785 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2771 2455 +2709 2773 2484 +2714 2774 2520 +2714 2773 2553 +2717 2777 2616 +2722 2785 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2771 2455 +2709 2773 2484 +2714 2774 2520 +2714 2773 2553 +2717 2777 2616 +2722 2785 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 28 +0 0 152 +0 0 280 +0 0 408 +0 0 537 +0 0 667 +0 0 797 +0 0 928 +0 0 1088 +0 0 1296 +0 0 1475 +0 0 1634 +445 0 1772 +1152 0 1882 +1561 0 2006 +1559 0 2155 +423 987 2341 +1234 615 2470 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 36 +0 0 159 +0 0 285 +0 0 412 +0 0 540 +0 0 669 +0 0 799 +0 0 930 +0 0 1089 +0 0 1297 +0 0 1475 +0 0 1635 +426 0 1772 +1151 0 1882 +1561 0 2007 +1558 0 2155 +423 992 2341 +1238 618 2470 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 48 +0 0 168 +0 0 291 +0 0 417 +0 0 544 +0 0 672 +0 0 801 +0 0 931 +0 0 1090 +0 0 1298 +0 0 1476 +0 0 1635 +400 0 1772 +1150 0 1883 +1560 0 2007 +1556 0 2155 +423 998 2341 +1244 621 2470 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 92 +0 0 203 +0 0 318 +0 0 437 +0 0 559 +0 0 683 +0 0 810 +0 0 938 +0 0 1094 +0 0 1300 +0 0 1478 +0 0 1636 +414 0 1773 +1149 0 1884 +1556 0 2008 +1550 0 2156 +416 1005 2342 +1252 621 2470 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 145 +0 0 245 +0 0 351 +0 0 462 +0 0 579 +0 0 699 +0 0 821 +0 0 946 +0 0 1101 +0 0 1304 +0 0 1481 +0 0 1637 +432 0 1774 +1147 0 1885 +1551 0 2010 +1543 38 2158 +407 1015 2342 +1262 621 2470 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 145 +0 1 295 +0 1 391 +0 1 494 +0 1 604 +0 1 718 +0 1 836 +0 1 958 +0 70 1109 +0 30 1310 +0 30 1484 +0 0 1639 +455 0 1776 +1144 0 1886 +1544 0 2012 +1532 182 2160 +394 1028 2343 +1275 621 2470 +1732 30 2504 +1732 30 2504 +1732 30 2504 +1732 30 2504 +1732 30 2504 +1732 30 2504 +1732 30 2504 +1732 30 2504 +1732 30 2504 +1732 30 2504 +0 4 0 +0 0 0 +0 0 0 +0 16 0 +0 58 145 +0 109 295 +0 170 441 +0 170 534 +0 170 635 +0 170 742 +0 170 855 +0 170 973 +0 218 1119 +0 163 1316 +0 163 1489 +0 126 1641 +484 0 1778 +1141 0 1888 +1534 32 2014 +1518 322 2163 +376 1045 2344 +1292 621 2470 +1732 163 2504 +1732 163 2504 +1732 163 2504 +1732 163 2504 +1732 163 2504 +1732 163 2504 +1732 163 2504 +1732 163 2504 +1732 163 2504 +1732 163 2504 +0 144 0 +0 137 0 +0 127 0 +0 152 0 +0 184 145 +0 223 295 +0 271 441 +0 327 582 +0 327 674 +0 327 773 +0 327 879 +0 327 991 +0 363 1133 +0 295 1325 +0 295 1495 +0 267 1644 +520 87 1782 +1137 0 1891 +1521 164 2017 +1498 461 2167 +352 1066 2345 +1314 621 2470 +1732 295 2505 +1732 295 2505 +1732 295 2505 +1732 295 2505 +1732 295 2505 +1732 295 2505 +1732 295 2505 +1732 295 2505 +1732 295 2505 +1732 295 2505 +0 281 0 +0 276 0 +0 269 0 +0 287 0 +0 311 145 +0 341 295 +0 378 441 +0 423 582 +0 478 721 +0 478 812 +0 478 910 +0 478 1016 +0 503 1151 +0 426 1337 +0 426 1503 +0 406 1648 +565 239 1786 +1131 111 1894 +1503 296 2022 +1470 597 2172 +317 1093 2347 +1353 639 2470 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +0 417 0 +0 413 0 +0 408 0 +0 422 0 +0 439 145 +0 462 295 +0 491 441 +0 527 582 +0 570 721 +0 623 859 +0 623 948 +0 623 1046 +0 642 1174 +0 570 1352 +0 559 1514 +0 544 1653 +569 424 1790 +1123 244 1899 +1477 428 2027 +1429 733 2178 +265 1128 2349 +1400 662 2470 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +0 552 0 +0 549 0 +0 545 0 +0 555 0 +0 568 145 +0 586 295 +0 608 441 +0 636 582 +0 670 721 +0 713 859 +0 765 995 +0 765 1084 +0 778 1202 +0 726 1372 +0 691 1528 +0 680 1662 +569 594 1795 +1139 422 1905 +1440 560 2035 +1368 868 2187 +186 1169 2352 +1457 691 2470 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +0 686 0 +0 684 0 +0 681 0 +0 689 0 +0 699 145 +0 712 295 +0 729 441 +0 750 582 +0 777 721 +0 811 859 +0 854 995 +0 904 1130 +0 914 1238 +0 876 1397 +0 823 1546 +0 815 1675 +569 753 1802 +1167 593 1913 +1385 692 2045 +1272 1002 2199 +0 1212 2357 +1524 728 2470 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +0 854 85 +0 854 130 +0 852 185 +0 857 268 +0 864 360 +0 873 459 +0 885 565 +0 901 676 +0 920 793 +0 946 912 +0 977 1035 +0 1016 1160 +0 1056 1287 +0 1029 1432 +0 983 1571 +0 967 1697 +579 939 1816 +1186 800 1926 +1306 849 2057 +1123 1137 2212 +0 1254 2365 +1587 800 2470 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +0 1181 1022 +0 1181 1028 +0 1181 1036 +0 1181 1043 +0 1181 1052 +0 1181 1064 +0 1181 1080 +0 1181 1099 +0 1181 1125 +0 1186 1168 +0 1205 1242 +0 1229 1325 +0 1255 1417 +0 1235 1494 +0 1207 1618 +0 1219 1741 +647 1188 1855 +1051 1133 1961 +1243 1131 2080 +1031 1271 2225 +532 1310 2371 +1590 1030 2471 +1766 1141 2512 +1766 1141 2512 +1766 1141 2512 +1766 1141 2512 +1766 1141 2512 +1766 1141 2512 +1766 1141 2512 +1766 1141 2512 +1766 1141 2512 +1766 1141 2512 +0 1420 1375 +0 1420 1378 +0 1420 1382 +0 1420 1385 +0 1420 1389 +0 1420 1395 +0 1420 1402 +0 1420 1412 +0 1420 1425 +0 1420 1442 +0 1420 1463 +0 1420 1491 +0 1430 1546 +0 1417 1606 +0 1398 1674 +0 1410 1786 +647 1405 1896 +1059 1354 2000 +1151 1350 2109 +878 1405 2240 +706 1386 2378 +1603 1208 2473 +1800 1311 2510 +1800 1311 2510 +1800 1311 2510 +1800 1311 2510 +1800 1311 2510 +1800 1311 2510 +1800 1311 2510 +1800 1311 2510 +1800 1311 2510 +1800 1311 2510 +929 1579 1649 +928 1579 1650 +926 1579 1651 +926 1579 1653 +926 1578 1655 +926 1577 1658 +926 1576 1663 +926 1574 1668 +926 1572 1676 +926 1569 1685 +926 1567 1698 +926 1567 1715 +906 1567 1736 +898 1576 1787 +898 1569 1837 +906 1552 1889 +833 1557 1970 +939 1536 2067 +950 1537 2170 +810 1524 2268 +1132 1500 2382 +1680 1435 2473 +1845 1471 2509 +1845 1471 2509 +1845 1471 2509 +1845 1471 2509 +1845 1471 2509 +1845 1471 2509 +1845 1471 2509 +1845 1471 2509 +1845 1471 2509 +1845 1471 2509 +1452 1705 1855 +1450 1705 1856 +1449 1705 1857 +1448 1705 1859 +1446 1705 1860 +1443 1705 1862 +1440 1705 1865 +1435 1705 1868 +1429 1705 1873 +1428 1703 1880 +1428 1700 1888 +1428 1696 1899 +1425 1691 1913 +1402 1685 1931 +1402 1696 1977 +1371 1701 2021 +1374 1685 2062 +1200 1672 2128 +1132 1678 2221 +1180 1647 2295 +1520 1631 2386 +1776 1634 2475 +1894 1628 2511 +1894 1628 2511 +1894 1628 2511 +1894 1628 2511 +1894 1628 2511 +1894 1628 2511 +1894 1628 2511 +1894 1628 2511 +1894 1628 2511 +1894 1628 2511 +1787 1817 1978 +1787 1817 1978 +1786 1817 1979 +1786 1817 1980 +1787 1817 1981 +1787 1817 1982 +1788 1817 1983 +1789 1817 1986 +1791 1817 1988 +1793 1817 1992 +1789 1817 1998 +1782 1817 2007 +1772 1818 2018 +1753 1823 2036 +1734 1818 2052 +1728 1803 2080 +1687 1816 2123 +1706 1808 2166 +1658 1793 2234 +1666 1793 2304 +1755 1797 2389 +1874 1790 2475 +1965 1800 2514 +1965 1800 2514 +1965 1800 2514 +1965 1800 2514 +1965 1800 2514 +1965 1800 2514 +1965 1800 2514 +1965 1800 2514 +1965 1800 2514 +1965 1800 2514 +1958 1958 2029 +1958 1958 2029 +1958 1958 2029 +1958 1958 2030 +1957 1958 2031 +1957 1958 2032 +1956 1958 2033 +1955 1958 2035 +1955 1958 2037 +1953 1958 2041 +1951 1958 2045 +1949 1958 2051 +1946 1958 2058 +1941 1962 2068 +1936 1968 2081 +1927 1969 2114 +1914 1966 2153 +1905 1963 2189 +1920 1969 2243 +1882 1968 2320 +1930 1954 2392 +2034 1964 2481 +2094 1969 2517 +2094 1969 2517 +2094 1969 2517 +2094 1969 2517 +2094 1969 2517 +2094 1969 2517 +2094 1969 2517 +2094 1969 2517 +2094 1969 2517 +2094 1969 2517 +2120 2119 2068 +2120 2119 2068 +2120 2119 2068 +2120 2120 2069 +2120 2120 2069 +2120 2120 2070 +2120 2120 2071 +2120 2121 2073 +2120 2122 2076 +2120 2122 2079 +2120 2124 2083 +2120 2125 2088 +2119 2127 2095 +2119 2127 2101 +2119 2127 2110 +2116 2131 2132 +2109 2133 2164 +2103 2131 2206 +2111 2135 2256 +2120 2135 2316 +2148 2131 2395 +2212 2147 2485 +2261 2159 2524 +2261 2159 2524 +2261 2159 2524 +2261 2159 2524 +2261 2159 2524 +2261 2159 2524 +2261 2159 2524 +2261 2159 2524 +2261 2159 2524 +2261 2159 2524 +2370 2355 2124 +2370 2355 2124 +2370 2355 2124 +2370 2355 2125 +2370 2355 2125 +2370 2356 2126 +2369 2356 2126 +2369 2356 2127 +2369 2357 2129 +2368 2357 2131 +2367 2358 2133 +2368 2359 2137 +2369 2360 2143 +2370 2358 2146 +2369 2356 2148 +2368 2358 2163 +2370 2358 2193 +2369 2358 2226 +2372 2355 2273 +2384 2356 2337 +2410 2367 2405 +2467 2385 2498 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2681 2655 1963 +2681 2655 1963 +2681 2655 1964 +2681 2655 1965 +2681 2655 1965 +2681 2655 1966 +2681 2654 1967 +2681 2654 1969 +2681 2654 1968 +2681 2654 1966 +2680 2653 1965 +2680 2653 1962 +2679 2652 1963 +2678 2653 1970 +2677 2655 1992 +2676 2653 2015 +2675 2650 2035 +2677 2655 2124 +2681 2656 2208 +2687 2661 2306 +2695 2666 2409 +2715 2678 2527 +2722 2684 2575 +2722 2684 2575 +2722 2684 2575 +2722 2684 2575 +2722 2684 2575 +2722 2684 2575 +2722 2684 2575 +2722 2684 2575 +2722 2684 2575 +2722 2684 2575 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2771 2455 +2710 2773 2483 +2714 2774 2520 +2714 2773 2553 +2717 2777 2616 +2722 2785 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2771 2455 +2710 2773 2483 +2714 2774 2520 +2714 2773 2553 +2717 2777 2616 +2722 2785 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2771 2455 +2710 2773 2483 +2714 2774 2520 +2714 2773 2553 +2717 2777 2616 +2722 2785 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2771 2455 +2710 2773 2483 +2714 2774 2520 +2714 2773 2553 +2717 2777 2616 +2722 2785 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2771 2455 +2710 2773 2483 +2714 2774 2520 +2714 2773 2553 +2717 2777 2616 +2722 2785 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2771 2455 +2710 2773 2483 +2714 2774 2520 +2714 2773 2553 +2717 2777 2616 +2722 2785 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2771 2455 +2710 2773 2483 +2714 2774 2520 +2714 2773 2553 +2717 2777 2616 +2722 2785 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2771 2455 +2710 2773 2483 +2714 2774 2520 +2714 2773 2553 +2717 2777 2616 +2722 2785 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2771 2455 +2710 2773 2483 +2714 2774 2520 +2714 2773 2553 +2717 2777 2616 +2722 2785 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2771 2455 +2710 2773 2483 +2714 2774 2520 +2714 2773 2553 +2717 2777 2616 +2722 2785 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 28 +0 0 152 +0 0 280 +0 0 408 +0 0 537 +0 0 667 +0 0 797 +0 0 928 +0 0 1088 +0 0 1300 +0 0 1478 +0 0 1634 +499 0 1773 +1157 0 1883 +1561 0 2007 +1557 0 2156 +416 987 2341 +1238 611 2470 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 36 +0 0 159 +0 0 285 +0 0 412 +0 0 540 +0 0 669 +0 0 799 +0 0 930 +0 0 1089 +0 0 1301 +0 0 1478 +0 0 1635 +483 0 1773 +1157 0 1883 +1561 0 2007 +1556 0 2156 +416 992 2341 +1243 614 2470 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 48 +0 0 168 +0 0 291 +0 0 417 +0 0 544 +0 0 672 +0 0 801 +0 0 931 +0 0 1090 +0 0 1302 +0 0 1479 +0 0 1635 +460 0 1772 +1156 0 1884 +1560 0 2008 +1554 0 2156 +416 998 2341 +1249 617 2470 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 63 +0 0 180 +0 0 300 +0 0 424 +0 0 549 +0 0 676 +0 0 804 +0 0 933 +0 0 1091 +0 0 1302 +0 0 1480 +0 0 1636 +427 0 1772 +1154 0 1884 +1560 0 2009 +1552 0 2156 +416 1005 2342 +1256 621 2470 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 120 +0 0 224 +0 0 335 +0 0 450 +0 0 569 +0 0 691 +0 0 816 +0 0 942 +0 0 1097 +0 0 1306 +0 0 1482 +0 0 1637 +445 0 1774 +1153 0 1885 +1554 0 2010 +1544 22 2158 +407 1015 2342 +1266 621 2470 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 120 +0 0 277 +0 0 376 +0 0 483 +0 0 594 +0 0 711 +0 0 831 +0 0 954 +0 23 1106 +0 30 1311 +0 30 1486 +0 0 1639 +467 0 1775 +1150 0 1887 +1547 0 2012 +1534 170 2160 +394 1028 2343 +1279 621 2470 +1732 30 2504 +1732 30 2504 +1732 30 2504 +1732 30 2504 +1732 30 2504 +1732 30 2504 +1732 30 2504 +1732 30 2504 +1732 30 2504 +1732 30 2504 +0 4 0 +0 0 0 +0 0 0 +0 0 0 +0 11 120 +0 67 277 +0 133 427 +0 133 523 +0 133 627 +0 133 736 +0 133 850 +0 133 968 +0 186 1116 +0 163 1318 +0 163 1490 +0 112 1641 +496 0 1778 +1147 0 1888 +1538 32 2014 +1520 314 2163 +376 1045 2344 +1296 621 2470 +1732 163 2504 +1732 163 2504 +1732 163 2504 +1732 163 2504 +1732 163 2504 +1732 163 2504 +1732 163 2504 +1732 163 2504 +1732 163 2504 +1732 163 2504 +0 144 0 +0 137 0 +0 127 0 +0 114 0 +0 148 120 +0 190 277 +0 241 427 +0 302 573 +0 302 666 +0 302 767 +0 302 875 +0 302 987 +0 339 1130 +0 295 1327 +0 295 1496 +0 258 1644 +531 58 1781 +1142 0 1891 +1524 164 2018 +1500 455 2167 +352 1066 2345 +1318 621 2470 +1732 295 2505 +1732 295 2505 +1732 295 2505 +1732 295 2505 +1732 295 2505 +1732 295 2505 +1732 295 2505 +1732 295 2505 +1732 295 2505 +1732 295 2505 +0 281 0 +0 276 0 +0 269 0 +0 259 0 +0 284 120 +0 316 277 +0 355 427 +0 403 573 +0 459 714 +0 459 806 +0 459 906 +0 459 1012 +0 486 1148 +0 426 1339 +0 426 1504 +0 399 1648 +574 219 1786 +1136 111 1894 +1506 296 2022 +1472 593 2172 +317 1093 2347 +1356 639 2470 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +0 417 0 +0 413 0 +0 408 0 +0 401 0 +0 419 120 +0 443 277 +0 473 427 +0 510 573 +0 556 714 +0 610 854 +0 610 944 +0 610 1043 +0 629 1171 +0 570 1354 +0 559 1515 +0 539 1653 +578 410 1789 +1128 244 1899 +1481 428 2028 +1431 730 2178 +265 1128 2349 +1403 662 2470 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +0 552 0 +0 549 0 +0 545 0 +0 540 0 +0 553 120 +0 571 277 +0 594 427 +0 623 573 +0 658 714 +0 702 854 +0 755 991 +0 755 1080 +0 769 1200 +0 726 1374 +0 691 1529 +0 676 1662 +578 585 1795 +1145 422 1905 +1444 560 2035 +1371 865 2187 +186 1169 2352 +1460 691 2470 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +0 686 0 +0 684 0 +0 681 0 +0 677 0 +0 688 120 +0 701 277 +0 718 427 +0 740 573 +0 768 714 +0 803 854 +0 845 991 +0 897 1127 +0 907 1236 +0 876 1399 +0 823 1547 +0 812 1675 +578 746 1801 +1172 593 1913 +1390 692 2045 +1275 1000 2199 +0 1212 2357 +1526 728 2470 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +0 854 85 +0 854 130 +0 852 185 +0 850 248 +0 857 344 +0 866 446 +0 878 555 +0 894 669 +0 914 787 +0 939 908 +0 971 1032 +0 1011 1157 +0 1051 1285 +0 1029 1433 +0 983 1572 +27 965 1697 +589 934 1816 +1190 800 1926 +1312 849 2057 +1127 1135 2212 +0 1254 2365 +1589 800 2470 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +0 1178 1018 +0 1178 1024 +0 1178 1032 +0 1178 1043 +0 1178 1052 +0 1178 1064 +0 1178 1080 +0 1178 1099 +0 1178 1125 +0 1184 1168 +0 1203 1242 +0 1227 1325 +0 1253 1417 +21 1234 1496 +21 1206 1619 +81 1217 1742 +655 1189 1855 +1060 1135 1962 +1243 1131 2080 +1031 1271 2225 +573 1308 2371 +1592 1028 2471 +1767 1138 2512 +1767 1138 2512 +1767 1138 2512 +1767 1138 2512 +1767 1138 2512 +1767 1138 2512 +1767 1138 2512 +1767 1138 2512 +1767 1138 2512 +1767 1138 2512 +0 1418 1374 +0 1418 1376 +0 1418 1380 +0 1418 1385 +0 1418 1389 +0 1418 1395 +0 1418 1402 +0 1418 1412 +0 1418 1425 +0 1418 1442 +0 1418 1463 +0 1418 1491 +0 1429 1546 +21 1416 1607 +21 1397 1675 +81 1409 1787 +655 1406 1896 +1067 1355 2000 +1151 1350 2109 +878 1405 2240 +735 1384 2378 +1605 1206 2473 +1801 1309 2510 +1801 1309 2510 +1801 1309 2510 +1801 1309 2510 +1801 1309 2510 +1801 1309 2510 +1801 1309 2510 +1801 1309 2510 +1801 1309 2510 +1801 1309 2510 +949 1577 1650 +947 1578 1651 +946 1578 1652 +943 1579 1653 +943 1578 1656 +943 1577 1659 +943 1576 1663 +943 1574 1669 +943 1572 1676 +943 1569 1686 +943 1567 1699 +943 1567 1715 +924 1567 1737 +908 1576 1787 +908 1568 1837 +917 1552 1889 +852 1557 1971 +951 1536 2066 +957 1537 2170 +810 1525 2268 +1138 1499 2382 +1680 1435 2473 +1845 1470 2509 +1845 1470 2509 +1845 1470 2509 +1845 1470 2509 +1845 1470 2509 +1845 1470 2509 +1845 1470 2509 +1845 1470 2509 +1845 1470 2509 +1845 1470 2509 +1454 1705 1855 +1453 1705 1856 +1451 1705 1857 +1449 1705 1859 +1447 1705 1860 +1444 1705 1862 +1441 1705 1865 +1436 1705 1868 +1430 1705 1873 +1430 1703 1880 +1430 1700 1888 +1430 1696 1899 +1426 1691 1913 +1403 1685 1931 +1403 1696 1977 +1372 1701 2021 +1375 1686 2063 +1206 1672 2128 +1137 1678 2221 +1185 1647 2295 +1521 1632 2386 +1778 1634 2475 +1894 1628 2511 +1894 1628 2511 +1894 1628 2511 +1894 1628 2511 +1894 1628 2511 +1894 1628 2511 +1894 1628 2511 +1894 1628 2511 +1894 1628 2511 +1894 1628 2511 +1788 1817 1978 +1788 1817 1978 +1787 1817 1979 +1787 1817 1980 +1787 1817 1981 +1788 1817 1982 +1789 1817 1983 +1790 1817 1986 +1791 1817 1988 +1793 1817 1992 +1789 1817 1998 +1782 1817 2007 +1773 1818 2018 +1754 1823 2036 +1735 1818 2051 +1730 1803 2080 +1689 1816 2124 +1707 1808 2166 +1658 1793 2234 +1668 1793 2304 +1756 1797 2389 +1874 1789 2475 +1965 1800 2514 +1965 1800 2514 +1965 1800 2514 +1965 1800 2514 +1965 1800 2514 +1965 1800 2514 +1965 1800 2514 +1965 1800 2514 +1965 1800 2514 +1965 1800 2514 +1959 1958 2029 +1959 1958 2029 +1958 1958 2030 +1958 1958 2030 +1958 1958 2031 +1957 1958 2032 +1957 1958 2033 +1956 1958 2035 +1955 1958 2037 +1954 1958 2041 +1952 1958 2045 +1950 1958 2051 +1946 1958 2058 +1942 1962 2068 +1936 1967 2081 +1928 1969 2114 +1915 1966 2154 +1905 1962 2189 +1920 1968 2243 +1883 1968 2320 +1930 1954 2392 +2035 1964 2481 +2095 1968 2516 +2095 1968 2516 +2095 1968 2516 +2095 1968 2516 +2095 1968 2516 +2095 1968 2516 +2095 1968 2516 +2095 1968 2516 +2095 1968 2516 +2095 1968 2516 +2120 2120 2068 +2120 2120 2068 +2120 2120 2068 +2120 2120 2069 +2120 2120 2069 +2120 2120 2070 +2120 2120 2071 +2120 2121 2073 +2120 2122 2075 +2120 2122 2078 +2120 2124 2082 +2120 2125 2088 +2119 2127 2095 +2119 2127 2101 +2119 2127 2110 +2116 2131 2132 +2110 2133 2165 +2104 2131 2206 +2111 2134 2256 +2120 2135 2316 +2148 2131 2395 +2212 2147 2485 +2261 2159 2523 +2261 2159 2523 +2261 2159 2523 +2261 2159 2523 +2261 2159 2523 +2261 2159 2523 +2261 2159 2523 +2261 2159 2523 +2261 2159 2523 +2261 2159 2523 +2370 2355 2124 +2370 2355 2124 +2370 2355 2124 +2370 2355 2125 +2370 2355 2125 +2370 2356 2126 +2369 2356 2126 +2369 2356 2127 +2369 2357 2129 +2368 2357 2131 +2368 2358 2133 +2368 2359 2137 +2369 2360 2143 +2370 2358 2146 +2369 2356 2148 +2369 2358 2163 +2371 2358 2193 +2369 2358 2226 +2372 2355 2273 +2384 2357 2337 +2410 2367 2405 +2467 2385 2498 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2681 2655 1963 +2681 2655 1963 +2681 2655 1964 +2681 2655 1965 +2681 2655 1966 +2681 2655 1967 +2681 2655 1968 +2681 2655 1969 +2681 2654 1968 +2681 2654 1967 +2680 2654 1965 +2680 2653 1963 +2679 2653 1963 +2678 2654 1973 +2677 2655 1994 +2676 2653 2016 +2675 2650 2036 +2677 2655 2123 +2681 2656 2208 +2687 2661 2306 +2695 2666 2409 +2715 2678 2527 +2723 2684 2575 +2723 2684 2575 +2723 2684 2575 +2723 2684 2575 +2723 2684 2575 +2723 2684 2575 +2723 2684 2575 +2723 2684 2575 +2723 2684 2575 +2723 2684 2575 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2772 2456 +2710 2773 2483 +2714 2774 2520 +2714 2773 2553 +2717 2777 2616 +2722 2785 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2772 2456 +2710 2773 2483 +2714 2774 2520 +2714 2773 2553 +2717 2777 2616 +2722 2785 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2772 2456 +2710 2773 2483 +2714 2774 2520 +2714 2773 2553 +2717 2777 2616 +2722 2785 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2772 2456 +2710 2773 2483 +2714 2774 2520 +2714 2773 2553 +2717 2777 2616 +2722 2785 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2772 2456 +2710 2773 2483 +2714 2774 2520 +2714 2773 2553 +2717 2777 2616 +2722 2785 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2772 2456 +2710 2773 2483 +2714 2774 2520 +2714 2773 2553 +2717 2777 2616 +2722 2785 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2772 2456 +2710 2773 2483 +2714 2774 2520 +2714 2773 2553 +2717 2777 2616 +2722 2785 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2772 2456 +2710 2773 2483 +2714 2774 2520 +2714 2773 2553 +2717 2777 2616 +2722 2785 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2772 2456 +2710 2773 2483 +2714 2774 2520 +2714 2773 2553 +2717 2777 2616 +2722 2785 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2772 2456 +2710 2773 2483 +2714 2774 2520 +2714 2773 2553 +2717 2777 2616 +2722 2785 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +58 0 0 +58 0 0 +58 0 0 +58 0 0 +58 0 28 +58 0 152 +58 0 280 +58 0 408 +58 0 537 +58 0 667 +58 0 797 +58 0 928 +0 0 1088 +0 0 1305 +0 0 1481 +28 0 1634 +564 0 1774 +1165 0 1884 +1561 0 2007 +1555 0 2157 +407 987 2341 +1245 605 2470 +1734 0 2503 +1734 0 2503 +1734 0 2503 +1734 0 2503 +1734 0 2503 +1734 0 2503 +1734 0 2503 +1734 0 2503 +1734 0 2503 +1734 0 2503 +41 0 0 +50 0 0 +50 0 0 +50 0 0 +50 0 36 +50 0 159 +50 0 285 +50 0 412 +50 0 540 +50 0 669 +50 0 799 +50 0 930 +0 0 1089 +0 0 1306 +0 0 1482 +36 0 1635 +550 0 1774 +1164 0 1884 +1561 0 2008 +1554 0 2157 +407 992 2341 +1249 608 2470 +1734 0 2503 +1734 0 2503 +1734 0 2503 +1734 0 2503 +1734 0 2503 +1734 0 2503 +1734 0 2503 +1734 0 2503 +1734 0 2503 +1734 0 2503 +17 0 0 +26 0 0 +38 0 0 +38 0 0 +38 0 48 +38 0 168 +38 0 291 +38 0 417 +38 0 544 +38 0 672 +38 0 801 +38 0 931 +0 0 1090 +0 0 1307 +0 0 1482 +48 0 1635 +530 0 1773 +1163 0 1884 +1560 0 2008 +1552 0 2157 +407 998 2341 +1254 611 2470 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +0 0 0 +0 0 0 +6 0 0 +22 0 0 +22 0 63 +22 0 180 +22 0 300 +22 0 424 +22 0 549 +22 0 676 +22 0 804 +22 0 933 +0 0 1091 +0 0 1308 +0 0 1483 +63 0 1636 +502 0 1773 +1162 0 1885 +1560 0 2009 +1550 0 2158 +407 1005 2342 +1262 615 2470 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 83 +0 0 195 +0 0 312 +0 0 433 +0 0 556 +0 0 681 +0 0 808 +0 0 936 +0 0 1093 +0 0 1309 +0 0 1484 +83 0 1637 +462 0 1772 +1160 0 1885 +1559 0 2010 +1547 0 2158 +407 1015 2342 +1272 621 2470 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +1732 0 2503 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 83 +0 0 251 +0 0 356 +0 0 467 +0 0 582 +0 0 701 +0 0 823 +0 0 948 +0 0 1102 +0 30 1314 +0 30 1487 +83 0 1639 +483 0 1774 +1157 0 1887 +1552 0 2012 +1536 154 2160 +394 1028 2343 +1285 621 2470 +1732 30 2504 +1732 30 2504 +1732 30 2504 +1732 30 2504 +1732 30 2504 +1732 30 2504 +1732 30 2504 +1732 30 2504 +1732 30 2504 +1732 30 2504 +0 4 0 +0 0 0 +0 0 0 +0 0 0 +0 0 83 +0 3 251 +0 78 409 +0 78 509 +0 78 615 +0 78 727 +0 78 843 +0 78 963 +0 137 1112 +0 163 1321 +0 163 1492 +83 94 1641 +511 0 1777 +1154 0 1889 +1542 32 2015 +1522 302 2163 +376 1045 2344 +1302 621 2470 +1732 163 2504 +1732 163 2504 +1732 163 2504 +1732 163 2504 +1732 163 2504 +1732 163 2504 +1732 163 2504 +1732 163 2504 +1732 163 2504 +1732 163 2504 +0 144 0 +0 137 0 +0 127 0 +0 114 0 +0 96 83 +0 143 251 +0 199 409 +0 265 559 +0 265 655 +0 265 759 +0 265 868 +0 265 982 +0 305 1126 +0 295 1330 +0 295 1498 +83 244 1644 +545 15 1780 +1150 0 1891 +1529 164 2018 +1502 446 2167 +352 1066 2345 +1323 621 2470 +1732 295 2505 +1732 295 2505 +1732 295 2505 +1732 295 2505 +1732 295 2505 +1732 295 2505 +1732 295 2505 +1732 295 2505 +1732 295 2505 +1732 295 2505 +0 281 0 +0 276 0 +0 269 0 +0 259 0 +0 246 83 +0 280 251 +0 322 409 +0 373 559 +0 434 705 +0 434 798 +0 434 899 +0 434 1007 +0 462 1144 +0 426 1341 +0 426 1506 +83 390 1648 +587 190 1784 +1144 111 1895 +1511 296 2022 +1474 586 2172 +317 1093 2347 +1361 639 2470 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +0 417 0 +0 413 0 +0 408 0 +0 401 0 +0 391 83 +0 416 251 +0 448 409 +0 487 559 +0 535 705 +0 591 846 +0 591 938 +0 591 1038 +0 611 1167 +0 570 1357 +0 559 1517 +83 531 1653 +591 391 1789 +1136 244 1899 +1486 428 2028 +1434 725 2178 +265 1128 2349 +1407 662 2470 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +0 552 0 +0 549 0 +0 545 0 +0 540 0 +0 533 83 +0 551 251 +0 575 409 +0 605 559 +0 642 705 +0 688 846 +0 742 985 +0 742 1076 +0 756 1197 +0 726 1376 +0 691 1531 +83 670 1662 +591 572 1794 +1152 422 1905 +1450 560 2036 +1374 862 2187 +186 1169 2352 +1464 691 2470 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +0 686 0 +0 684 0 +0 681 0 +0 677 0 +0 672 83 +0 686 251 +0 703 409 +0 726 559 +0 755 705 +0 791 846 +0 835 985 +0 887 1123 +0 898 1233 +0 876 1401 +0 823 1548 +83 808 1675 +591 737 1800 +1179 593 1913 +1396 692 2046 +1279 997 2199 +0 1212 2357 +1529 728 2470 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +0 854 85 +0 854 130 +0 852 185 +0 850 248 +0 846 322 +0 855 429 +0 868 541 +0 884 658 +0 904 778 +0 930 901 +0 963 1027 +0 1003 1154 +69 1044 1282 +0 1029 1435 +0 983 1573 +141 963 1697 +601 928 1815 +1197 800 1927 +1320 849 2058 +1133 1133 2212 +0 1254 2365 +1592 800 2470 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +136 1175 1014 +107 1175 1020 +65 1175 1028 +1 1175 1038 +0 1175 1052 +0 1175 1064 +0 1175 1080 +0 1175 1099 +0 1175 1125 +0 1180 1168 +0 1200 1242 +0 1224 1325 +21 1250 1417 +153 1233 1497 +153 1204 1620 +214 1214 1743 +666 1191 1855 +1071 1137 1962 +1243 1131 2080 +1031 1271 2226 +622 1305 2371 +1594 1025 2471 +1769 1134 2512 +1769 1134 2512 +1769 1134 2512 +1769 1134 2512 +1769 1134 2512 +1769 1134 2512 +1769 1134 2512 +1769 1134 2512 +1769 1134 2512 +1769 1134 2512 +136 1416 1371 +107 1416 1374 +65 1416 1378 +1 1416 1383 +0 1416 1389 +0 1416 1395 +0 1416 1402 +0 1416 1412 +0 1416 1425 +0 1416 1442 +0 1416 1463 +0 1416 1491 +21 1427 1546 +153 1415 1608 +153 1396 1676 +214 1407 1788 +666 1407 1897 +1078 1356 2001 +1151 1350 2109 +878 1405 2241 +770 1382 2378 +1607 1205 2473 +1802 1306 2510 +1802 1306 2510 +1802 1306 2510 +1802 1306 2510 +1802 1306 2510 +1802 1306 2510 +1802 1306 2510 +1802 1306 2510 +1802 1306 2510 +1802 1306 2510 +973 1576 1651 +973 1576 1652 +971 1577 1653 +969 1577 1654 +966 1578 1656 +966 1577 1659 +966 1576 1664 +966 1574 1669 +966 1572 1677 +966 1569 1686 +966 1567 1699 +966 1567 1716 +948 1567 1737 +920 1575 1786 +920 1568 1836 +932 1552 1890 +876 1557 1972 +968 1536 2066 +965 1537 2170 +810 1526 2268 +1145 1498 2382 +1680 1435 2473 +1844 1469 2509 +1844 1469 2509 +1844 1469 2509 +1844 1469 2509 +1844 1469 2509 +1844 1469 2509 +1844 1469 2509 +1844 1469 2509 +1844 1469 2509 +1844 1469 2509 +1457 1704 1855 +1456 1704 1856 +1454 1705 1857 +1452 1705 1858 +1449 1705 1860 +1446 1705 1862 +1443 1705 1865 +1438 1705 1868 +1432 1705 1873 +1431 1703 1880 +1431 1700 1888 +1431 1696 1899 +1428 1691 1913 +1405 1685 1932 +1405 1696 1977 +1373 1700 2021 +1378 1686 2063 +1214 1672 2128 +1142 1679 2221 +1192 1647 2295 +1522 1633 2386 +1779 1634 2475 +1895 1627 2511 +1895 1627 2511 +1895 1627 2511 +1895 1627 2511 +1895 1627 2511 +1895 1627 2511 +1895 1627 2511 +1895 1627 2511 +1895 1627 2511 +1895 1627 2511 +1790 1816 1977 +1790 1816 1978 +1789 1816 1978 +1789 1816 1979 +1788 1816 1981 +1788 1816 1982 +1789 1816 1983 +1790 1816 1986 +1792 1816 1988 +1793 1816 1992 +1790 1816 1998 +1783 1816 2007 +1773 1817 2018 +1755 1823 2036 +1736 1817 2051 +1731 1804 2079 +1691 1816 2124 +1708 1807 2166 +1659 1793 2234 +1670 1794 2305 +1757 1797 2389 +1873 1789 2475 +1966 1800 2514 +1966 1800 2514 +1966 1800 2514 +1966 1800 2514 +1966 1800 2514 +1966 1800 2514 +1966 1800 2514 +1966 1800 2514 +1966 1800 2514 +1966 1800 2514 +1960 1958 2029 +1960 1958 2029 +1959 1958 2030 +1959 1958 2030 +1958 1958 2031 +1958 1958 2032 +1957 1958 2034 +1956 1958 2035 +1956 1958 2038 +1954 1958 2041 +1952 1958 2046 +1950 1958 2051 +1947 1958 2059 +1942 1961 2068 +1936 1967 2081 +1928 1969 2113 +1916 1966 2154 +1905 1962 2189 +1920 1968 2242 +1884 1968 2319 +1930 1954 2392 +2036 1964 2481 +2096 1968 2516 +2096 1968 2516 +2096 1968 2516 +2096 1968 2516 +2096 1968 2516 +2096 1968 2516 +2096 1968 2516 +2096 1968 2516 +2096 1968 2516 +2096 1968 2516 +2120 2120 2068 +2120 2120 2068 +2120 2120 2069 +2120 2120 2069 +2121 2120 2069 +2121 2120 2070 +2121 2120 2071 +2121 2121 2073 +2121 2122 2075 +2121 2122 2078 +2121 2124 2082 +2121 2125 2087 +2120 2127 2094 +2119 2127 2101 +2119 2127 2110 +2116 2131 2132 +2110 2134 2165 +2104 2130 2206 +2111 2134 2256 +2120 2134 2316 +2148 2131 2395 +2213 2146 2485 +2261 2159 2523 +2261 2159 2523 +2261 2159 2523 +2261 2159 2523 +2261 2159 2523 +2261 2159 2523 +2261 2159 2523 +2261 2159 2523 +2261 2159 2523 +2261 2159 2523 +2370 2355 2124 +2370 2355 2124 +2370 2355 2124 +2370 2355 2125 +2370 2355 2125 +2370 2355 2126 +2370 2356 2126 +2369 2356 2127 +2369 2356 2129 +2369 2357 2131 +2368 2357 2133 +2368 2359 2137 +2369 2360 2143 +2370 2358 2146 +2369 2356 2148 +2369 2358 2162 +2371 2358 2193 +2370 2358 2226 +2372 2356 2273 +2384 2357 2337 +2410 2367 2406 +2466 2384 2498 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2681 2655 1963 +2681 2655 1963 +2681 2655 1964 +2681 2655 1965 +2681 2655 1967 +2681 2655 1968 +2681 2655 1969 +2681 2655 1970 +2681 2655 1969 +2681 2654 1968 +2680 2654 1966 +2680 2653 1964 +2679 2653 1964 +2678 2654 1975 +2677 2655 1997 +2676 2654 2018 +2675 2650 2038 +2677 2655 2123 +2681 2656 2208 +2687 2661 2306 +2695 2666 2409 +2715 2678 2527 +2723 2684 2575 +2723 2684 2575 +2723 2684 2575 +2723 2684 2575 +2723 2684 2575 +2723 2684 2575 +2723 2684 2575 +2723 2684 2575 +2723 2684 2575 +2723 2684 2575 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2772 2456 +2710 2773 2483 +2714 2774 2520 +2714 2773 2553 +2717 2777 2616 +2722 2785 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2772 2456 +2710 2773 2483 +2714 2774 2520 +2714 2773 2553 +2717 2777 2616 +2722 2785 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2772 2456 +2710 2773 2483 +2714 2774 2520 +2714 2773 2553 +2717 2777 2616 +2722 2785 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2772 2456 +2710 2773 2483 +2714 2774 2520 +2714 2773 2553 +2717 2777 2616 +2722 2785 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2772 2456 +2710 2773 2483 +2714 2774 2520 +2714 2773 2553 +2717 2777 2616 +2722 2785 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2772 2456 +2710 2773 2483 +2714 2774 2520 +2714 2773 2553 +2717 2777 2616 +2722 2785 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2772 2456 +2710 2773 2483 +2714 2774 2520 +2714 2773 2553 +2717 2777 2616 +2722 2785 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2772 2456 +2710 2773 2483 +2714 2774 2520 +2714 2773 2553 +2717 2777 2616 +2722 2785 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2772 2456 +2710 2773 2483 +2714 2774 2520 +2714 2773 2553 +2717 2777 2616 +2722 2785 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2772 2456 +2710 2773 2483 +2714 2774 2520 +2714 2773 2553 +2717 2777 2616 +2722 2785 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +197 0 0 +197 0 0 +197 0 0 +197 0 0 +197 0 28 +197 0 152 +197 0 280 +197 0 408 +197 0 537 +197 0 667 +197 0 797 +197 0 928 +71 0 1088 +0 0 1312 +0 0 1486 +152 0 1634 +638 0 1775 +1174 0 1884 +1561 0 2008 +1552 0 2159 +394 987 2341 +1252 597 2470 +1735 0 2503 +1735 0 2503 +1735 0 2503 +1735 0 2503 +1735 0 2503 +1735 0 2503 +1735 0 2503 +1735 0 2503 +1735 0 2503 +1735 0 2503 +184 0 0 +190 0 0 +190 0 0 +190 0 0 +190 0 36 +190 0 159 +190 0 285 +190 0 412 +190 0 540 +190 0 669 +190 0 799 +190 0 930 +46 0 1089 +0 0 1313 +0 0 1486 +159 0 1635 +626 0 1775 +1173 0 1885 +1561 0 2008 +1551 0 2159 +394 992 2341 +1257 599 2470 +1734 0 2503 +1734 0 2503 +1734 0 2503 +1734 0 2503 +1734 0 2503 +1734 0 2503 +1734 0 2503 +1734 0 2503 +1734 0 2503 +1734 0 2503 +167 0 0 +173 0 0 +182 0 0 +182 0 0 +182 0 48 +182 0 168 +182 0 291 +182 0 417 +182 0 544 +182 0 672 +182 0 801 +182 0 931 +35 0 1090 +0 0 1313 +0 0 1487 +168 0 1635 +609 0 1775 +1172 0 1885 +1560 0 2009 +1549 0 2159 +394 998 2341 +1262 603 2470 +1734 0 2503 +1734 0 2503 +1734 0 2503 +1734 0 2503 +1734 0 2503 +1734 0 2503 +1734 0 2503 +1734 0 2503 +1734 0 2503 +1734 0 2503 +142 0 0 +149 0 0 +158 0 0 +170 0 0 +170 0 63 +170 0 180 +170 0 300 +170 0 424 +170 0 549 +170 0 676 +170 0 804 +170 0 933 +19 0 1091 +0 0 1315 +0 0 1487 +180 0 1636 +586 0 1774 +1171 0 1886 +1560 0 2010 +1547 0 2159 +394 1005 2342 +1270 608 2470 +1734 0 2503 +1734 0 2503 +1734 0 2503 +1734 0 2503 +1734 0 2503 +1734 0 2503 +1734 0 2503 +1734 0 2503 +1734 0 2503 +1734 0 2503 +107 0 0 +115 0 0 +125 0 0 +138 0 0 +154 0 83 +154 0 195 +154 0 312 +154 0 433 +154 0 556 +154 0 681 +154 0 808 +154 0 936 +0 0 1093 +0 0 1316 +0 0 1489 +195 0 1637 +552 0 1774 +1169 0 1886 +1559 0 2011 +1544 57 2160 +394 1015 2342 +1279 613 2470 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +1733 0 2503 +56 0 0 +65 0 0 +76 0 0 +90 0 0 +108 0 83 +132 0 215 +132 0 327 +132 0 444 +132 0 564 +132 0 688 +132 0 813 +132 0 940 +0 0 1096 +0 30 1317 +0 30 1490 +215 0 1639 +504 0 1773 +1167 0 1887 +1558 0 2012 +1540 132 2160 +394 1028 2343 +1292 621 2470 +1732 30 2504 +1732 30 2504 +1732 30 2504 +1732 30 2504 +1732 30 2504 +1732 30 2504 +1732 30 2504 +1732 30 2504 +1732 30 2504 +1732 30 2504 +56 4 0 +65 0 0 +76 0 0 +90 0 0 +108 0 83 +132 0 215 +132 0 383 +132 0 488 +132 0 599 +132 0 714 +132 0 833 +132 0 955 +0 64 1107 +0 163 1324 +0 163 1494 +215 68 1641 +530 0 1776 +1164 0 1889 +1548 32 2015 +1525 286 2163 +376 1045 2344 +1308 621 2470 +1732 163 2504 +1732 163 2504 +1732 163 2504 +1732 163 2504 +1732 163 2504 +1732 163 2504 +1732 163 2504 +1732 163 2504 +1732 163 2504 +1732 163 2504 +56 144 0 +65 137 0 +76 127 0 +90 114 0 +108 96 83 +132 70 215 +132 135 383 +132 210 541 +132 210 641 +132 210 747 +132 210 859 +132 210 975 +0 255 1121 +0 295 1333 +0 295 1500 +215 226 1644 +563 0 1779 +1159 0 1892 +1536 164 2018 +1506 434 2167 +352 1066 2345 +1329 621 2470 +1732 295 2505 +1732 295 2505 +1732 295 2505 +1732 295 2505 +1732 295 2505 +1732 295 2505 +1732 295 2505 +1732 295 2505 +1732 295 2505 +1732 295 2505 +56 281 0 +65 276 0 +76 269 0 +90 259 0 +108 246 83 +132 227 215 +132 275 383 +132 331 541 +132 397 691 +132 397 787 +132 397 891 +132 397 1000 +0 427 1139 +0 426 1344 +0 426 1508 +215 376 1648 +604 147 1783 +1154 111 1895 +1518 296 2022 +1478 578 2172 +317 1093 2347 +1367 639 2470 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +56 417 0 +65 413 0 +76 408 0 +90 401 0 +108 391 83 +132 378 215 +132 412 383 +132 455 541 +132 505 691 +132 566 837 +132 566 930 +132 566 1032 +0 587 1163 +0 570 1359 +0 559 1519 +215 522 1653 +607 365 1787 +1146 244 1900 +1493 428 2028 +1438 719 2178 +265 1128 2349 +1413 662 2470 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +56 552 0 +65 549 0 +76 545 0 +90 540 0 +108 533 83 +132 523 215 +132 548 383 +132 580 541 +132 619 691 +132 667 837 +132 723 978 +132 723 1071 +0 738 1192 +0 726 1379 +0 691 1532 +215 663 1662 +607 554 1792 +1162 422 1905 +1457 560 2036 +1379 857 2187 +186 1169 2352 +1468 691 2470 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +56 686 0 +65 684 0 +76 681 0 +90 677 0 +108 672 83 +132 665 215 +132 684 383 +132 708 541 +132 737 691 +132 774 837 +132 820 978 +132 874 1118 +0 885 1229 +0 876 1403 +0 823 1550 +215 803 1675 +607 725 1799 +1188 593 1913 +1404 692 2046 +1285 994 2199 +0 1212 2357 +1533 728 2470 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +63 854 85 +31 854 130 +43 852 185 +58 850 248 +78 846 322 +103 841 404 +103 854 522 +103 870 643 +103 892 767 +103 918 893 +103 952 1020 +103 993 1149 +185 1035 1278 +0 1029 1438 +0 983 1575 +259 959 1697 +617 920 1814 +1206 800 1927 +1329 849 2058 +1141 1131 2212 +0 1254 2365 +1596 800 2470 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +289 1170 1007 +268 1170 1013 +239 1170 1021 +196 1170 1032 +132 1170 1046 +30 1170 1064 +30 1170 1080 +30 1170 1099 +30 1170 1125 +30 1176 1168 +30 1195 1242 +30 1220 1325 +125 1246 1417 +285 1231 1499 +285 1202 1622 +345 1210 1744 +680 1193 1856 +1086 1139 1963 +1243 1131 2080 +1031 1271 2226 +681 1302 2370 +1597 1022 2471 +1771 1129 2512 +1771 1129 2512 +1771 1129 2512 +1771 1129 2512 +1771 1129 2512 +1771 1129 2512 +1771 1129 2512 +1771 1129 2512 +1771 1129 2512 +1771 1129 2512 +289 1413 1368 +268 1413 1371 +239 1413 1375 +196 1413 1380 +132 1413 1386 +30 1413 1395 +30 1413 1402 +30 1413 1412 +30 1413 1425 +30 1413 1442 +30 1413 1463 +30 1413 1491 +125 1424 1546 +285 1414 1610 +285 1395 1677 +345 1404 1789 +680 1408 1897 +1092 1358 2001 +1151 1350 2109 +878 1405 2241 +813 1379 2377 +1609 1202 2473 +1804 1303 2510 +1804 1303 2510 +1804 1303 2510 +1804 1303 2510 +1804 1303 2510 +1804 1303 2510 +1804 1303 2510 +1804 1303 2510 +1804 1303 2510 +1804 1303 2510 +1005 1574 1653 +1004 1574 1654 +1003 1575 1655 +1001 1575 1656 +998 1576 1658 +995 1577 1660 +995 1576 1664 +995 1574 1670 +995 1572 1678 +995 1569 1687 +995 1567 1700 +995 1567 1716 +977 1567 1738 +937 1574 1785 +937 1567 1835 +952 1552 1890 +906 1557 1973 +989 1536 2066 +976 1537 2170 +810 1527 2268 +1155 1497 2382 +1680 1435 2473 +1844 1468 2509 +1844 1468 2509 +1844 1468 2509 +1844 1468 2509 +1844 1468 2509 +1844 1468 2509 +1844 1468 2509 +1844 1468 2509 +1844 1468 2509 +1844 1468 2509 +1461 1703 1854 +1459 1704 1855 +1458 1704 1856 +1456 1704 1858 +1453 1705 1859 +1449 1705 1862 +1446 1705 1865 +1441 1705 1868 +1435 1705 1873 +1434 1703 1880 +1434 1700 1888 +1434 1696 1899 +1431 1691 1913 +1408 1685 1932 +1408 1696 1977 +1375 1699 2021 +1380 1687 2064 +1224 1672 2127 +1149 1680 2221 +1200 1647 2295 +1523 1633 2386 +1781 1634 2475 +1896 1626 2511 +1896 1626 2511 +1896 1626 2511 +1896 1626 2511 +1896 1626 2511 +1896 1626 2511 +1896 1626 2511 +1896 1626 2511 +1896 1626 2511 +1896 1626 2511 +1793 1816 1977 +1792 1816 1977 +1792 1816 1978 +1791 1816 1979 +1790 1816 1980 +1789 1816 1982 +1790 1816 1983 +1791 1816 1986 +1792 1816 1988 +1794 1816 1992 +1790 1816 1998 +1783 1816 2007 +1774 1817 2018 +1756 1822 2035 +1737 1817 2051 +1733 1804 2079 +1694 1816 2124 +1710 1807 2166 +1660 1793 2234 +1673 1795 2305 +1759 1797 2389 +1873 1788 2475 +1968 1800 2514 +1968 1800 2514 +1968 1800 2514 +1968 1800 2514 +1968 1800 2514 +1968 1800 2514 +1968 1800 2514 +1968 1800 2514 +1968 1800 2514 +1968 1800 2514 +1961 1958 2029 +1961 1958 2030 +1961 1958 2030 +1960 1958 2031 +1959 1958 2031 +1959 1958 2032 +1958 1958 2034 +1958 1958 2036 +1956 1958 2038 +1955 1958 2042 +1953 1958 2046 +1951 1958 2052 +1948 1958 2059 +1943 1961 2068 +1937 1966 2081 +1930 1968 2112 +1918 1966 2154 +1905 1962 2189 +1920 1968 2242 +1885 1967 2319 +1930 1954 2392 +2038 1964 2481 +2097 1968 2516 +2097 1968 2516 +2097 1968 2516 +2097 1968 2516 +2097 1968 2516 +2097 1968 2516 +2097 1968 2516 +2097 1968 2516 +2097 1968 2516 +2097 1968 2516 +2120 2120 2069 +2120 2120 2069 +2121 2120 2069 +2121 2120 2069 +2121 2120 2069 +2121 2120 2069 +2121 2120 2071 +2121 2121 2073 +2121 2122 2075 +2121 2122 2078 +2121 2124 2082 +2121 2125 2087 +2120 2127 2094 +2119 2127 2101 +2119 2127 2110 +2117 2131 2132 +2111 2134 2166 +2105 2130 2206 +2111 2134 2255 +2121 2134 2316 +2148 2131 2396 +2213 2146 2485 +2261 2159 2523 +2261 2159 2523 +2261 2159 2523 +2261 2159 2523 +2261 2159 2523 +2261 2159 2523 +2261 2159 2523 +2261 2159 2523 +2261 2159 2523 +2261 2159 2523 +2370 2355 2124 +2370 2355 2124 +2370 2355 2124 +2370 2355 2125 +2370 2355 2125 +2370 2355 2126 +2370 2355 2126 +2370 2356 2127 +2369 2356 2129 +2369 2357 2131 +2368 2357 2133 +2369 2358 2137 +2369 2359 2143 +2370 2358 2146 +2369 2356 2148 +2369 2358 2162 +2371 2358 2193 +2370 2358 2226 +2373 2356 2273 +2385 2357 2337 +2411 2367 2406 +2466 2384 2498 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2681 2655 1963 +2681 2655 1963 +2681 2655 1964 +2681 2655 1965 +2681 2655 1967 +2681 2655 1969 +2681 2655 1970 +2681 2655 1971 +2681 2655 1970 +2681 2655 1969 +2680 2654 1968 +2680 2654 1965 +2679 2653 1966 +2679 2654 1979 +2677 2655 2000 +2676 2654 2020 +2675 2650 2041 +2677 2655 2122 +2681 2656 2208 +2688 2661 2306 +2695 2666 2408 +2715 2678 2527 +2723 2684 2575 +2723 2684 2575 +2723 2684 2575 +2723 2684 2575 +2723 2684 2575 +2723 2684 2575 +2723 2684 2575 +2723 2684 2575 +2723 2684 2575 +2723 2684 2575 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2772 2457 +2710 2773 2483 +2714 2774 2520 +2714 2773 2553 +2717 2777 2616 +2722 2784 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2772 2457 +2710 2773 2483 +2714 2774 2520 +2714 2773 2553 +2717 2777 2616 +2722 2784 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2772 2457 +2710 2773 2483 +2714 2774 2520 +2714 2773 2553 +2717 2777 2616 +2722 2784 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2772 2457 +2710 2773 2483 +2714 2774 2520 +2714 2773 2553 +2717 2777 2616 +2722 2784 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2772 2457 +2710 2773 2483 +2714 2774 2520 +2714 2773 2553 +2717 2777 2616 +2722 2784 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2772 2457 +2710 2773 2483 +2714 2774 2520 +2714 2773 2553 +2717 2777 2616 +2722 2784 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2772 2457 +2710 2773 2483 +2714 2774 2520 +2714 2773 2553 +2717 2777 2616 +2722 2784 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2772 2457 +2710 2773 2483 +2714 2774 2520 +2714 2773 2553 +2717 2777 2616 +2722 2784 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2772 2457 +2710 2773 2483 +2714 2774 2520 +2714 2773 2553 +2717 2777 2616 +2722 2784 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2772 2457 +2710 2773 2483 +2714 2774 2520 +2714 2773 2553 +2717 2777 2616 +2722 2784 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +333 0 0 +333 0 0 +333 0 0 +333 0 0 +333 0 28 +333 0 152 +333 0 280 +333 0 408 +333 0 537 +333 0 667 +333 0 797 +333 0 928 +244 0 1088 +0 0 1321 +0 0 1492 +280 0 1634 +721 0 1777 +1186 0 1886 +1561 0 2009 +1548 0 2161 +376 987 2341 +1263 586 2469 +1736 0 2503 +1736 0 2503 +1736 0 2503 +1736 0 2503 +1736 0 2503 +1736 0 2503 +1736 0 2503 +1736 0 2503 +1736 0 2503 +1736 0 2503 +324 0 0 +329 0 0 +329 0 0 +329 0 0 +329 0 36 +329 0 159 +329 0 285 +329 0 412 +329 0 540 +329 0 669 +329 0 799 +329 0 930 +227 0 1089 +0 0 1322 +0 0 1493 +285 0 1635 +711 0 1776 +1185 0 1886 +1561 0 2009 +1547 0 2161 +376 992 2341 +1267 588 2469 +1735 0 2503 +1735 0 2503 +1735 0 2503 +1735 0 2503 +1735 0 2503 +1735 0 2503 +1735 0 2503 +1735 0 2503 +1735 0 2503 +1735 0 2503 +311 0 0 +316 0 0 +322 0 0 +322 0 0 +322 0 48 +322 0 168 +322 0 291 +322 0 417 +322 0 544 +322 0 672 +322 0 801 +322 0 931 +219 0 1090 +0 0 1323 +0 0 1493 +291 0 1635 +697 0 1776 +1184 0 1886 +1560 0 2010 +1545 22 2161 +376 998 2341 +1272 592 2469 +1735 0 2503 +1735 0 2503 +1735 0 2503 +1735 0 2503 +1735 0 2503 +1735 0 2503 +1735 0 2503 +1735 0 2503 +1735 0 2503 +1735 0 2503 +294 0 0 +299 0 0 +305 0 0 +314 0 0 +314 0 63 +314 0 180 +314 0 300 +314 0 424 +314 0 549 +314 0 676 +314 0 804 +314 0 933 +209 0 1091 +0 0 1323 +0 0 1494 +300 0 1636 +678 0 1776 +1183 0 1887 +1560 0 2011 +1543 69 2161 +376 1005 2342 +1280 596 2469 +1735 0 2503 +1735 0 2503 +1735 0 2503 +1735 0 2503 +1735 0 2503 +1735 0 2503 +1735 0 2503 +1735 0 2503 +1735 0 2503 +1735 0 2503 +269 0 0 +274 0 0 +281 0 0 +290 0 0 +302 0 83 +302 0 195 +302 0 312 +302 0 433 +302 0 556 +302 0 681 +302 0 808 +302 0 936 +194 0 1093 +0 0 1325 +0 0 1495 +312 0 1637 +651 0 1776 +1181 0 1887 +1559 0 2012 +1540 124 2162 +376 1015 2342 +1289 603 2469 +1734 0 2504 +1734 0 2504 +1734 0 2504 +1734 0 2504 +1734 0 2504 +1734 0 2504 +1734 0 2504 +1734 0 2504 +1734 0 2504 +1734 0 2504 +234 0 0 +239 0 0 +247 0 0 +257 0 0 +270 0 83 +286 0 215 +286 0 327 +286 0 444 +286 0 564 +286 0 688 +286 0 813 +286 0 940 +173 0 1096 +0 30 1326 +0 30 1496 +327 0 1639 +613 0 1775 +1179 0 1888 +1558 0 2013 +1535 189 2162 +376 1028 2343 +1301 611 2469 +1733 30 2504 +1733 30 2504 +1733 30 2504 +1733 30 2504 +1733 30 2504 +1733 30 2504 +1733 30 2504 +1733 30 2504 +1733 30 2504 +1733 30 2504 +182 4 0 +188 0 0 +197 0 0 +208 0 0 +222 0 83 +241 0 215 +264 0 347 +264 0 459 +264 0 576 +264 0 697 +264 0 820 +264 0 946 +145 0 1100 +0 163 1329 +0 163 1497 +347 32 1641 +555 0 1774 +1176 0 1890 +1557 32 2015 +1530 264 2163 +376 1045 2344 +1318 621 2469 +1732 163 2504 +1732 163 2504 +1732 163 2504 +1732 163 2504 +1732 163 2504 +1732 163 2504 +1732 163 2504 +1732 163 2504 +1732 163 2504 +1732 163 2504 +182 144 0 +188 137 0 +197 127 0 +208 114 0 +222 96 83 +241 70 215 +264 34 347 +264 126 516 +264 126 620 +264 126 731 +264 126 846 +264 126 966 +145 179 1114 +0 295 1337 +0 295 1503 +347 201 1644 +586 0 1777 +1172 0 1892 +1544 164 2019 +1510 418 2167 +352 1066 2345 +1338 621 2469 +1732 295 2505 +1732 295 2505 +1732 295 2505 +1732 295 2505 +1732 295 2505 +1732 295 2505 +1732 295 2505 +1732 295 2505 +1732 295 2505 +1732 295 2505 +182 281 0 +188 276 0 +197 269 0 +208 259 0 +222 246 83 +241 227 215 +264 202 347 +264 267 516 +264 342 673 +264 342 773 +264 342 879 +264 342 991 +145 376 1133 +0 426 1349 +0 426 1511 +347 358 1648 +625 84 1782 +1166 111 1896 +1526 296 2023 +1483 566 2172 +317 1093 2347 +1375 639 2469 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +182 417 0 +188 413 0 +197 408 0 +208 401 0 +222 391 83 +241 378 215 +264 360 347 +264 407 516 +264 463 673 +264 529 824 +264 529 920 +264 529 1023 +145 552 1156 +0 570 1364 +0 559 1522 +347 509 1653 +628 326 1786 +1159 244 1900 +1502 428 2029 +1443 710 2178 +265 1128 2349 +1420 662 2469 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +182 552 0 +188 549 0 +197 545 0 +208 540 0 +222 533 83 +241 523 215 +264 510 347 +264 544 516 +264 586 673 +264 637 824 +264 698 969 +264 698 1063 +145 714 1186 +0 726 1383 +0 691 1535 +347 654 1662 +628 529 1791 +1174 422 1906 +1467 560 2036 +1385 851 2187 +186 1169 2352 +1475 691 2469 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +182 686 0 +188 684 0 +197 681 0 +208 677 0 +222 672 83 +241 665 215 +264 655 347 +264 681 516 +264 712 673 +264 752 824 +264 799 969 +264 856 1111 +145 867 1223 +0 876 1407 +0 823 1553 +347 796 1675 +628 708 1798 +1200 593 1914 +1415 692 2046 +1292 989 2199 +0 1212 2357 +1539 728 2469 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +187 854 85 +163 854 130 +172 852 185 +183 850 248 +198 846 322 +218 841 404 +243 835 496 +243 852 623 +243 874 752 +243 902 881 +243 936 1011 +243 979 1142 +304 1023 1273 +0 1029 1441 +0 983 1578 +380 954 1697 +638 909 1812 +1217 800 1928 +1343 849 2058 +1151 1127 2212 +0 1254 2365 +1600 800 2469 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +436 1164 998 +421 1164 1004 +400 1164 1013 +371 1164 1024 +328 1164 1038 +265 1164 1056 +163 1164 1080 +163 1164 1099 +163 1164 1125 +163 1170 1168 +163 1189 1242 +163 1214 1325 +235 1241 1417 +417 1228 1503 +417 1199 1624 +478 1204 1746 +698 1196 1857 +1104 1142 1964 +1243 1131 2079 +1031 1271 2226 +750 1297 2370 +1600 1018 2470 +1773 1121 2512 +1773 1121 2512 +1773 1121 2512 +1773 1121 2512 +1773 1121 2512 +1773 1121 2512 +1773 1121 2512 +1773 1121 2512 +1773 1121 2512 +1773 1121 2512 +436 1410 1364 +421 1410 1367 +400 1410 1371 +371 1410 1376 +328 1410 1382 +265 1410 1391 +163 1410 1402 +163 1410 1412 +163 1410 1425 +163 1410 1442 +163 1410 1463 +163 1410 1491 +235 1421 1546 +417 1412 1612 +417 1393 1679 +478 1400 1791 +698 1410 1897 +1111 1360 2002 +1151 1350 2108 +878 1405 2242 +865 1375 2377 +1613 1200 2472 +1806 1298 2510 +1806 1298 2510 +1806 1298 2510 +1806 1298 2510 +1806 1298 2510 +1806 1298 2510 +1806 1298 2510 +1806 1298 2510 +1806 1298 2510 +1806 1298 2510 +1044 1572 1655 +1043 1572 1656 +1042 1572 1657 +1040 1573 1658 +1038 1573 1660 +1034 1574 1662 +1030 1576 1666 +1030 1574 1671 +1030 1572 1679 +1030 1569 1688 +1030 1567 1701 +1030 1567 1717 +1014 1567 1739 +958 1573 1783 +958 1565 1833 +977 1552 1891 +944 1557 1974 +1016 1536 2066 +990 1537 2170 +810 1528 2268 +1168 1496 2382 +1680 1435 2473 +1843 1466 2509 +1843 1466 2509 +1843 1466 2509 +1843 1466 2509 +1843 1466 2509 +1843 1466 2509 +1843 1466 2509 +1843 1466 2509 +1843 1466 2509 +1843 1466 2509 +1466 1702 1854 +1464 1703 1855 +1463 1703 1855 +1461 1703 1857 +1458 1704 1859 +1454 1705 1862 +1449 1705 1865 +1444 1705 1868 +1438 1705 1873 +1438 1703 1880 +1438 1700 1888 +1438 1696 1899 +1434 1691 1913 +1412 1685 1932 +1412 1696 1978 +1377 1698 2020 +1384 1688 2065 +1238 1672 2127 +1159 1681 2221 +1212 1647 2296 +1524 1635 2386 +1783 1634 2474 +1897 1625 2511 +1897 1625 2511 +1897 1625 2511 +1897 1625 2511 +1897 1625 2511 +1897 1625 2511 +1897 1625 2511 +1897 1625 2511 +1897 1625 2511 +1897 1625 2511 +1796 1815 1977 +1795 1815 1977 +1795 1815 1978 +1794 1815 1978 +1793 1815 1980 +1792 1815 1981 +1790 1815 1983 +1792 1815 1986 +1793 1815 1988 +1795 1815 1992 +1791 1815 1998 +1784 1815 2007 +1775 1816 2018 +1758 1821 2035 +1739 1816 2051 +1736 1805 2078 +1698 1816 2124 +1712 1806 2166 +1661 1793 2234 +1677 1795 2305 +1762 1797 2390 +1872 1787 2475 +1969 1800 2514 +1969 1800 2514 +1969 1800 2514 +1969 1800 2514 +1969 1800 2514 +1969 1800 2514 +1969 1800 2514 +1969 1800 2514 +1969 1800 2514 +1969 1800 2514 +1963 1958 2030 +1962 1958 2030 +1962 1958 2031 +1962 1958 2031 +1961 1958 2032 +1960 1958 2033 +1959 1958 2034 +1958 1958 2036 +1958 1958 2039 +1956 1958 2042 +1955 1958 2047 +1952 1958 2052 +1949 1958 2059 +1943 1961 2068 +1937 1966 2081 +1930 1968 2111 +1921 1967 2155 +1905 1961 2189 +1920 1967 2241 +1887 1967 2319 +1931 1954 2392 +2040 1964 2481 +2099 1967 2516 +2099 1967 2516 +2099 1967 2516 +2099 1967 2516 +2099 1967 2516 +2099 1967 2516 +2099 1967 2516 +2099 1967 2516 +2099 1967 2516 +2099 1967 2516 +2121 2120 2069 +2121 2120 2069 +2121 2120 2069 +2121 2120 2069 +2121 2120 2070 +2122 2120 2070 +2122 2120 2070 +2122 2121 2072 +2122 2122 2074 +2122 2122 2078 +2122 2124 2082 +2122 2125 2087 +2121 2127 2094 +2119 2127 2101 +2119 2127 2110 +2118 2131 2131 +2112 2134 2166 +2105 2129 2205 +2112 2134 2255 +2122 2134 2316 +2148 2132 2396 +2214 2146 2485 +2261 2159 2523 +2261 2159 2523 +2261 2159 2523 +2261 2159 2523 +2261 2159 2523 +2261 2159 2523 +2261 2159 2523 +2261 2159 2523 +2261 2159 2523 +2261 2159 2523 +2370 2355 2124 +2370 2355 2124 +2370 2355 2124 +2370 2355 2125 +2370 2355 2125 +2370 2355 2126 +2371 2355 2126 +2370 2356 2127 +2370 2356 2129 +2369 2357 2131 +2369 2357 2133 +2369 2358 2137 +2370 2359 2143 +2370 2358 2146 +2369 2356 2148 +2369 2358 2162 +2372 2358 2193 +2371 2358 2226 +2374 2356 2273 +2386 2358 2337 +2411 2367 2406 +2465 2384 2499 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2681 2655 1963 +2681 2655 1963 +2681 2655 1964 +2681 2655 1965 +2681 2655 1967 +2681 2655 1969 +2681 2656 1972 +2681 2656 1973 +2681 2655 1972 +2681 2655 1971 +2680 2655 1969 +2680 2654 1967 +2679 2654 1967 +2679 2655 1983 +2677 2656 2005 +2677 2654 2023 +2675 2651 2045 +2677 2655 2122 +2681 2656 2208 +2688 2660 2305 +2695 2666 2408 +2715 2678 2527 +2723 2684 2576 +2723 2684 2576 +2723 2684 2576 +2723 2684 2576 +2723 2684 2576 +2723 2684 2576 +2723 2684 2576 +2723 2684 2576 +2723 2684 2576 +2723 2684 2576 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2772 2458 +2710 2773 2482 +2714 2774 2521 +2713 2773 2553 +2717 2777 2616 +2722 2784 2693 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2772 2458 +2710 2773 2482 +2714 2774 2521 +2713 2773 2553 +2717 2777 2616 +2722 2784 2693 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2772 2458 +2710 2773 2482 +2714 2774 2521 +2713 2773 2553 +2717 2777 2616 +2722 2784 2693 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2772 2458 +2710 2773 2482 +2714 2774 2521 +2713 2773 2553 +2717 2777 2616 +2722 2784 2693 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2772 2458 +2710 2773 2482 +2714 2774 2521 +2713 2773 2553 +2717 2777 2616 +2722 2784 2693 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2772 2458 +2710 2773 2482 +2714 2774 2521 +2713 2773 2553 +2717 2777 2616 +2722 2784 2693 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2772 2458 +2710 2773 2482 +2714 2774 2521 +2713 2773 2553 +2717 2777 2616 +2722 2784 2693 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2772 2458 +2710 2773 2482 +2714 2774 2521 +2713 2773 2553 +2717 2777 2616 +2722 2784 2693 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2772 2458 +2710 2773 2482 +2714 2774 2521 +2713 2773 2553 +2717 2777 2616 +2722 2784 2693 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2772 2458 +2710 2773 2482 +2714 2774 2521 +2713 2773 2553 +2717 2777 2616 +2722 2784 2693 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +469 0 0 +469 0 0 +469 0 0 +469 0 0 +469 0 28 +469 0 152 +469 0 280 +469 0 408 +469 0 537 +469 0 667 +469 0 797 +469 0 928 +404 0 1088 +100 0 1333 +100 0 1501 +408 0 1634 +813 0 1779 +1202 0 1887 +1561 0 2010 +1542 61 2164 +352 987 2341 +1276 570 2469 +1737 0 2503 +1737 0 2503 +1737 0 2503 +1737 0 2503 +1737 0 2503 +1737 0 2503 +1737 0 2503 +1737 0 2503 +1737 0 2503 +1737 0 2503 +462 0 0 +465 0 0 +465 0 0 +465 0 0 +465 0 36 +465 0 159 +465 0 285 +465 0 412 +465 0 540 +465 0 669 +465 0 799 +465 0 930 +393 0 1089 +76 0 1333 +76 0 1501 +412 0 1635 +805 0 1779 +1201 0 1887 +1561 0 2011 +1541 86 2164 +352 992 2341 +1280 573 2469 +1736 0 2503 +1736 0 2503 +1736 0 2503 +1736 0 2503 +1736 0 2503 +1736 0 2503 +1736 0 2503 +1736 0 2503 +1736 0 2503 +1736 0 2503 +453 0 0 +456 0 0 +461 0 0 +461 0 0 +461 0 48 +461 0 168 +461 0 291 +461 0 417 +461 0 544 +461 0 672 +461 0 801 +461 0 931 +387 0 1090 +43 0 1334 +43 0 1501 +417 0 1635 +793 0 1778 +1200 0 1888 +1560 0 2011 +1539 116 2164 +352 998 2341 +1285 577 2469 +1736 0 2503 +1736 0 2503 +1736 0 2503 +1736 0 2503 +1736 0 2503 +1736 0 2503 +1736 0 2503 +1736 0 2503 +1736 0 2503 +1736 0 2503 +440 0 0 +444 0 0 +448 0 0 +455 0 0 +455 0 63 +455 0 180 +455 0 300 +455 0 424 +455 0 549 +455 0 676 +455 0 804 +455 0 933 +380 0 1091 +0 0 1335 +0 0 1502 +424 0 1636 +778 0 1778 +1199 0 1889 +1560 0 2012 +1537 154 2164 +352 1005 2342 +1292 582 2469 +1736 0 2504 +1736 0 2504 +1736 0 2504 +1736 0 2504 +1736 0 2504 +1736 0 2504 +1736 0 2504 +1736 0 2504 +1736 0 2504 +1736 0 2504 +422 0 0 +426 0 0 +431 0 0 +437 0 0 +446 0 83 +446 0 195 +446 0 312 +446 0 433 +446 0 556 +446 0 681 +446 0 808 +446 0 936 +370 0 1093 +0 0 1336 +0 0 1503 +433 0 1637 +757 0 1778 +1197 0 1889 +1559 0 2013 +1534 201 2165 +352 1015 2342 +1302 588 2469 +1735 0 2504 +1735 0 2504 +1735 0 2504 +1735 0 2504 +1735 0 2504 +1735 0 2504 +1735 0 2504 +1735 0 2504 +1735 0 2504 +1735 0 2504 +397 0 0 +401 0 0 +406 0 0 +413 0 0 +422 0 83 +434 0 215 +434 0 327 +434 0 444 +434 0 564 +434 0 688 +434 0 813 +434 0 940 +356 0 1096 +0 30 1338 +0 30 1504 +444 0 1639 +726 0 1777 +1195 0 1890 +1558 0 2015 +1530 256 2165 +352 1028 2343 +1314 596 2469 +1735 30 2504 +1735 30 2504 +1735 30 2504 +1735 30 2504 +1735 30 2504 +1735 30 2504 +1735 30 2504 +1735 30 2504 +1735 30 2504 +1735 30 2504 +362 4 0 +366 0 0 +371 0 0 +379 0 0 +389 0 83 +402 0 215 +418 0 347 +418 0 459 +418 0 576 +418 0 697 +418 0 820 +418 0 946 +337 0 1100 +0 163 1340 +0 163 1505 +459 32 1641 +682 0 1776 +1192 0 1891 +1557 32 2017 +1524 322 2166 +352 1045 2344 +1329 607 2469 +1734 163 2504 +1734 163 2504 +1734 163 2504 +1734 163 2504 +1734 163 2504 +1734 163 2504 +1734 163 2504 +1734 163 2504 +1734 163 2504 +1734 163 2504 +309 144 0 +314 137 0 +320 127 0 +329 114 0 +340 96 83 +354 70 215 +373 34 347 +396 0 479 +396 0 591 +396 0 708 +396 0 829 +396 0 952 +310 52 1105 +0 295 1343 +0 295 1507 +479 164 1644 +615 0 1775 +1188 0 1893 +1555 164 2019 +1516 396 2167 +352 1066 2345 +1349 621 2469 +1732 295 2505 +1732 295 2505 +1732 295 2505 +1732 295 2505 +1732 295 2505 +1732 295 2505 +1732 295 2505 +1732 295 2505 +1732 295 2505 +1732 295 2505 +309 281 0 +314 276 0 +320 269 0 +329 259 0 +340 246 83 +354 227 215 +373 202 347 +396 166 479 +396 257 648 +396 257 752 +396 257 863 +396 257 978 +310 298 1124 +0 426 1354 +0 426 1515 +479 333 1648 +652 0 1779 +1183 111 1897 +1538 296 2024 +1489 550 2172 +317 1093 2347 +1385 639 2469 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +309 417 0 +314 413 0 +320 408 0 +329 401 0 +340 391 83 +354 378 215 +373 360 347 +396 334 479 +396 399 648 +396 474 805 +396 474 905 +396 474 1011 +310 500 1148 +0 570 1369 +0 559 1526 +479 490 1653 +655 270 1784 +1176 244 1901 +1514 428 2029 +1450 699 2178 +265 1128 2349 +1430 662 2469 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +309 552 0 +314 549 0 +320 545 0 +329 540 0 +340 533 83 +354 523 215 +373 510 347 +396 492 479 +396 539 648 +396 595 805 +396 661 955 +396 661 1052 +310 678 1178 +0 726 1388 +0 691 1539 +479 640 1662 +655 494 1789 +1191 422 1907 +1480 560 2037 +1393 842 2187 +186 1169 2352 +1483 691 2469 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +309 686 0 +314 684 0 +320 681 0 +329 677 0 +340 672 83 +354 665 215 +373 655 347 +396 643 479 +396 677 648 +396 719 805 +396 770 955 +396 830 1101 +310 842 1216 +0 876 1412 +0 823 1557 +479 786 1675 +655 684 1796 +1216 593 1915 +1430 692 2047 +1302 983 2199 +0 1212 2357 +1546 728 2469 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +313 854 85 +295 854 130 +302 852 185 +310 850 248 +322 846 322 +336 841 404 +356 835 496 +380 826 594 +380 849 730 +380 878 865 +380 915 1000 +380 960 1133 +426 1005 1267 +0 1029 1446 +0 983 1581 +504 947 1697 +664 894 1810 +1232 800 1928 +1359 849 2059 +1164 1123 2212 +0 1254 2365 +1607 800 2469 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +579 1156 985 +568 1156 992 +553 1156 1001 +532 1156 1012 +503 1156 1027 +461 1156 1045 +397 1156 1069 +295 1156 1099 +295 1156 1125 +295 1161 1168 +295 1181 1242 +295 1207 1325 +350 1233 1417 +549 1224 1507 +549 1195 1627 +610 1196 1748 +721 1200 1858 +1128 1147 1966 +1243 1131 2078 +1031 1271 2227 +827 1290 2369 +1605 1012 2470 +1776 1112 2512 +1776 1112 2512 +1776 1112 2512 +1776 1112 2512 +1776 1112 2512 +1776 1112 2512 +1776 1112 2512 +1776 1112 2512 +1776 1112 2512 +1776 1112 2512 +579 1405 1359 +568 1405 1361 +553 1405 1365 +532 1405 1370 +503 1405 1377 +461 1405 1386 +397 1405 1397 +295 1405 1412 +295 1405 1425 +295 1405 1442 +295 1405 1463 +295 1405 1491 +350 1416 1546 +549 1410 1615 +549 1390 1682 +610 1395 1793 +721 1413 1898 +1134 1362 2004 +1151 1350 2108 +878 1405 2243 +927 1369 2376 +1617 1196 2472 +1809 1292 2510 +1809 1292 2510 +1809 1292 2510 +1809 1292 2510 +1809 1292 2510 +1809 1292 2510 +1809 1292 2510 +1809 1292 2510 +1809 1292 2510 +1809 1292 2510 +1091 1568 1658 +1091 1569 1659 +1089 1569 1660 +1088 1569 1661 +1086 1570 1663 +1083 1571 1665 +1079 1572 1668 +1074 1574 1673 +1074 1572 1680 +1074 1569 1690 +1074 1567 1702 +1074 1567 1718 +1060 1567 1740 +984 1571 1781 +984 1563 1832 +1008 1552 1891 +990 1557 1977 +1050 1536 2065 +1008 1537 2170 +810 1530 2268 +1184 1494 2382 +1680 1435 2473 +1842 1464 2509 +1842 1464 2509 +1842 1464 2509 +1842 1464 2509 +1842 1464 2509 +1842 1464 2509 +1842 1464 2509 +1842 1464 2509 +1842 1464 2509 +1842 1464 2509 +1472 1701 1853 +1471 1701 1854 +1469 1702 1855 +1467 1702 1856 +1464 1703 1858 +1461 1703 1861 +1456 1704 1864 +1449 1705 1868 +1443 1705 1873 +1442 1703 1880 +1442 1700 1888 +1442 1696 1899 +1439 1691 1913 +1417 1685 1933 +1417 1696 1979 +1379 1697 2020 +1390 1690 2066 +1256 1672 2126 +1172 1682 2221 +1227 1647 2296 +1526 1636 2386 +1786 1634 2474 +1899 1624 2511 +1899 1624 2511 +1899 1624 2511 +1899 1624 2511 +1899 1624 2511 +1899 1624 2511 +1899 1624 2511 +1899 1624 2511 +1899 1624 2511 +1899 1624 2511 +1800 1814 1976 +1800 1814 1976 +1799 1814 1977 +1799 1814 1978 +1797 1814 1979 +1796 1814 1981 +1795 1814 1983 +1793 1814 1986 +1794 1814 1988 +1796 1814 1992 +1792 1814 1998 +1785 1814 2007 +1776 1815 2018 +1760 1821 2034 +1741 1815 2050 +1739 1806 2078 +1704 1816 2125 +1714 1805 2166 +1662 1793 2234 +1683 1796 2305 +1765 1797 2390 +1871 1786 2475 +1971 1800 2514 +1971 1800 2514 +1971 1800 2514 +1971 1800 2514 +1971 1800 2514 +1971 1800 2514 +1971 1800 2514 +1971 1800 2514 +1971 1800 2514 +1971 1800 2514 +1965 1958 2031 +1965 1958 2031 +1964 1958 2031 +1964 1958 2032 +1963 1958 2032 +1962 1958 2034 +1961 1958 2035 +1960 1958 2037 +1959 1958 2039 +1958 1958 2042 +1956 1958 2047 +1953 1958 2053 +1951 1958 2060 +1944 1960 2068 +1938 1965 2081 +1932 1967 2110 +1924 1968 2156 +1905 1961 2189 +1920 1966 2240 +1890 1966 2318 +1932 1954 2393 +2043 1964 2481 +2101 1966 2516 +2101 1966 2516 +2101 1966 2516 +2101 1966 2516 +2101 1966 2516 +2101 1966 2516 +2101 1966 2516 +2101 1966 2516 +2101 1966 2516 +2101 1966 2516 +2121 2121 2069 +2121 2121 2070 +2121 2121 2070 +2122 2121 2070 +2122 2121 2070 +2122 2121 2071 +2122 2121 2071 +2123 2121 2071 +2123 2122 2074 +2123 2122 2077 +2123 2124 2081 +2123 2125 2086 +2122 2127 2093 +2119 2127 2101 +2119 2127 2110 +2119 2131 2131 +2114 2135 2167 +2107 2129 2205 +2112 2133 2255 +2123 2133 2316 +2148 2132 2397 +2215 2145 2485 +2260 2159 2523 +2260 2159 2523 +2260 2159 2523 +2260 2159 2523 +2260 2159 2523 +2260 2159 2523 +2260 2159 2523 +2260 2159 2523 +2260 2159 2523 +2260 2159 2523 +2370 2355 2124 +2370 2355 2124 +2370 2355 2124 +2370 2355 2125 +2370 2355 2125 +2370 2355 2126 +2371 2355 2126 +2371 2355 2127 +2371 2356 2129 +2370 2356 2131 +2369 2357 2133 +2369 2358 2137 +2370 2359 2143 +2370 2358 2146 +2369 2356 2148 +2369 2358 2161 +2372 2358 2193 +2371 2358 2227 +2375 2356 2273 +2387 2359 2337 +2411 2367 2406 +2465 2384 2499 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2496 2391 2531 +2681 2655 1963 +2681 2655 1963 +2681 2655 1964 +2681 2655 1965 +2681 2655 1967 +2681 2655 1969 +2681 2656 1972 +2681 2656 1975 +2681 2656 1974 +2681 2656 1973 +2680 2655 1971 +2680 2655 1969 +2679 2654 1969 +2679 2655 1990 +2678 2657 2010 +2677 2655 2027 +2675 2651 2050 +2677 2656 2121 +2681 2656 2208 +2688 2660 2305 +2695 2665 2407 +2715 2678 2527 +2723 2684 2576 +2723 2684 2576 +2723 2684 2576 +2723 2684 2576 +2723 2684 2576 +2723 2684 2576 +2723 2684 2576 +2723 2684 2576 +2723 2684 2576 +2723 2684 2576 +2713 2771 2431 +2713 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2772 2460 +2711 2773 2482 +2714 2774 2521 +2713 2773 2553 +2717 2777 2616 +2722 2784 2693 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2713 2771 2431 +2713 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2772 2460 +2711 2773 2482 +2714 2774 2521 +2713 2773 2553 +2717 2777 2616 +2722 2784 2693 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2713 2771 2431 +2713 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2772 2460 +2711 2773 2482 +2714 2774 2521 +2713 2773 2553 +2717 2777 2616 +2722 2784 2693 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2713 2771 2431 +2713 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2772 2460 +2711 2773 2482 +2714 2774 2521 +2713 2773 2553 +2717 2777 2616 +2722 2784 2693 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2713 2771 2431 +2713 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2772 2460 +2711 2773 2482 +2714 2774 2521 +2713 2773 2553 +2717 2777 2616 +2722 2784 2693 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2713 2771 2431 +2713 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2772 2460 +2711 2773 2482 +2714 2774 2521 +2713 2773 2553 +2717 2777 2616 +2722 2784 2693 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2713 2771 2431 +2713 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2772 2460 +2711 2773 2482 +2714 2774 2521 +2713 2773 2553 +2717 2777 2616 +2722 2784 2693 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2713 2771 2431 +2713 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2772 2460 +2711 2773 2482 +2714 2774 2521 +2713 2773 2553 +2717 2777 2616 +2722 2784 2693 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2713 2771 2431 +2713 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2772 2460 +2711 2773 2482 +2714 2774 2521 +2713 2773 2553 +2717 2777 2616 +2722 2784 2693 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2713 2771 2431 +2713 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2432 +2715 2770 2435 +2716 2768 2439 +2714 2769 2444 +2711 2772 2460 +2711 2773 2482 +2714 2774 2521 +2713 2773 2553 +2717 2777 2616 +2722 2784 2693 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +603 0 0 +603 0 0 +603 0 0 +603 0 0 +603 0 28 +603 0 152 +603 0 280 +603 0 408 +603 0 537 +603 0 667 +603 0 797 +603 0 928 +556 0 1088 +249 0 1348 +249 0 1511 +537 0 1634 +912 0 1782 +1222 0 1890 +1561 0 2012 +1535 174 2167 +317 987 2341 +1325 528 2469 +1738 0 2504 +1738 0 2504 +1738 0 2504 +1738 0 2504 +1738 0 2504 +1738 0 2504 +1738 0 2504 +1738 0 2504 +1738 0 2504 +1738 0 2504 +598 0 0 +601 0 0 +601 0 0 +601 0 0 +601 0 36 +601 0 159 +601 0 285 +601 0 412 +601 0 540 +601 0 669 +601 0 799 +601 0 930 +548 0 1089 +232 0 1349 +232 0 1511 +540 0 1635 +906 0 1782 +1221 0 1890 +1561 0 2013 +1534 193 2167 +317 992 2341 +1328 531 2469 +1738 0 2504 +1738 0 2504 +1738 0 2504 +1738 0 2504 +1738 0 2504 +1738 0 2504 +1738 0 2504 +1738 0 2504 +1738 0 2504 +1738 0 2504 +591 0 0 +594 0 0 +597 0 0 +597 0 0 +597 0 48 +597 0 168 +597 0 291 +597 0 417 +597 0 544 +597 0 672 +597 0 801 +597 0 931 +544 0 1090 +208 0 1349 +208 0 1512 +544 0 1635 +897 0 1781 +1221 0 1891 +1560 0 2013 +1532 217 2168 +317 998 2341 +1333 535 2469 +1738 0 2504 +1738 0 2504 +1738 0 2504 +1738 0 2504 +1738 0 2504 +1738 0 2504 +1738 0 2504 +1738 0 2504 +1738 0 2504 +1738 0 2504 +582 0 0 +585 0 0 +588 0 0 +593 0 0 +593 0 63 +593 0 180 +593 0 300 +593 0 424 +593 0 549 +593 0 676 +593 0 804 +593 0 933 +539 0 1091 +175 0 1351 +175 0 1512 +549 0 1636 +884 0 1781 +1220 0 1891 +1560 0 2014 +1530 248 2168 +317 1005 2342 +1339 540 2469 +1737 0 2504 +1737 0 2504 +1737 0 2504 +1737 0 2504 +1737 0 2504 +1737 0 2504 +1737 0 2504 +1737 0 2504 +1737 0 2504 +1737 0 2504 +569 0 0 +572 0 0 +575 0 0 +580 0 0 +586 0 83 +586 0 195 +586 0 312 +586 0 433 +586 0 556 +586 0 681 +586 0 808 +586 0 936 +532 0 1093 +125 0 1352 +125 0 1513 +556 0 1637 +867 0 1781 +1218 0 1891 +1559 0 2015 +1526 286 2168 +317 1015 2342 +1348 547 2469 +1737 0 2504 +1737 0 2504 +1737 0 2504 +1737 0 2504 +1737 0 2504 +1737 0 2504 +1737 0 2504 +1737 0 2504 +1737 0 2504 +1737 0 2504 +551 0 0 +554 0 0 +558 0 0 +563 0 0 +569 0 83 +578 0 215 +578 0 327 +578 0 444 +578 0 564 +578 0 688 +578 0 813 +578 0 940 +522 0 1096 +50 30 1353 +50 30 1514 +564 0 1639 +844 0 1780 +1216 0 1893 +1558 0 2017 +1522 333 2169 +317 1028 2343 +1359 556 2469 +1736 30 2504 +1736 30 2504 +1736 30 2504 +1736 30 2504 +1736 30 2504 +1736 30 2504 +1736 30 2504 +1736 30 2504 +1736 30 2504 +1736 30 2504 +526 4 0 +529 0 0 +533 0 0 +538 0 0 +545 0 83 +554 0 215 +566 0 347 +566 0 459 +566 0 576 +566 0 697 +566 0 820 +566 0 946 +509 0 1100 +0 163 1355 +0 163 1516 +576 32 1641 +810 0 1779 +1213 0 1894 +1557 32 2019 +1516 388 2170 +317 1045 2344 +1373 568 2469 +1735 163 2505 +1735 163 2505 +1735 163 2505 +1735 163 2505 +1735 163 2505 +1735 163 2505 +1735 163 2505 +1735 163 2505 +1735 163 2505 +1735 163 2505 +490 144 0 +494 137 0 +498 127 0 +504 114 0 +511 96 83 +521 70 215 +534 34 347 +550 0 479 +550 0 591 +550 0 708 +550 0 829 +550 0 952 +491 52 1105 +0 295 1358 +0 295 1518 +591 164 1644 +761 0 1778 +1209 0 1896 +1555 164 2021 +1508 454 2170 +317 1066 2345 +1391 584 2469 +1734 295 2505 +1734 295 2505 +1734 295 2505 +1734 295 2505 +1734 295 2505 +1734 295 2505 +1734 295 2505 +1734 295 2505 +1734 295 2505 +1734 295 2505 +438 281 0 +441 276 0 +446 269 0 +452 259 0 +461 246 83 +472 227 215 +486 202 347 +505 166 479 +528 111 611 +528 111 723 +528 111 840 +528 111 961 +465 167 1111 +0 426 1362 +0 426 1520 +611 296 1648 +685 0 1777 +1204 111 1898 +1552 296 2024 +1498 528 2172 +317 1093 2347 +1405 655 2469 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +1732 426 2506 +438 417 0 +441 413 0 +446 408 0 +452 401 0 +461 391 83 +472 378 215 +486 360 347 +505 334 479 +528 298 611 +528 390 780 +528 390 884 +528 390 995 +465 420 1136 +0 570 1376 +0 559 1531 +611 465 1653 +688 180 1781 +1197 244 1902 +1529 428 2030 +1459 683 2178 +265 1128 2349 +1448 678 2469 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +438 552 0 +441 549 0 +446 545 0 +452 540 0 +461 533 83 +472 523 215 +486 510 347 +505 492 479 +528 466 611 +528 532 780 +528 606 937 +528 606 1037 +465 626 1167 +0 726 1395 +0 691 1544 +611 622 1662 +688 441 1786 +1211 422 1908 +1496 560 2038 +1403 831 2187 +186 1169 2352 +1499 706 2469 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +438 686 0 +441 684 0 +446 681 0 +452 677 0 +461 672 83 +472 665 215 +486 655 347 +505 643 479 +528 624 611 +528 671 780 +528 728 937 +528 793 1088 +465 806 1206 +0 876 1419 +0 823 1561 +611 773 1675 +688 651 1793 +1235 593 1916 +1448 692 2048 +1314 975 2199 +0 1212 2357 +1560 742 2469 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +441 854 85 +427 854 130 +432 852 185 +438 850 248 +447 846 322 +458 841 404 +473 835 496 +492 826 594 +516 814 700 +516 845 843 +516 884 983 +516 932 1121 +551 980 1257 +0 1029 1452 +0 983 1586 +630 938 1697 +697 873 1807 +1251 800 1930 +1381 849 2060 +1181 1116 2212 +0 1254 2365 +1619 811 2469 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +719 1144 968 +711 1144 975 +700 1144 984 +685 1144 996 +664 1144 1011 +635 1144 1030 +592 1144 1055 +529 1144 1086 +426 1144 1125 +426 1150 1168 +426 1170 1242 +426 1196 1325 +469 1224 1417 +681 1219 1512 +681 1190 1631 +741 1186 1751 +750 1205 1859 +1158 1153 1968 +1243 1131 2078 +1031 1271 2228 +914 1282 2369 +1608 1020 2470 +1781 1099 2512 +1781 1099 2512 +1781 1099 2512 +1781 1099 2512 +1781 1099 2512 +1781 1099 2512 +1781 1099 2512 +1781 1099 2512 +1781 1099 2512 +1781 1099 2512 +719 1398 1351 +711 1398 1354 +700 1398 1358 +685 1398 1363 +664 1398 1370 +635 1398 1379 +592 1398 1390 +529 1398 1406 +426 1398 1425 +426 1398 1442 +426 1398 1463 +426 1398 1491 +469 1409 1546 +681 1406 1619 +681 1387 1686 +741 1388 1796 +750 1416 1900 +1164 1366 2006 +1151 1350 2107 +878 1405 2243 +998 1362 2375 +1620 1201 2472 +1813 1283 2510 +1813 1283 2510 +1813 1283 2510 +1813 1283 2510 +1813 1283 2510 +1813 1283 2510 +1813 1283 2510 +1813 1283 2510 +1813 1283 2510 +1813 1283 2510 +1148 1563 1662 +1147 1564 1663 +1146 1564 1663 +1145 1565 1665 +1143 1565 1667 +1140 1566 1669 +1137 1568 1672 +1133 1569 1676 +1126 1572 1682 +1126 1569 1691 +1126 1567 1704 +1126 1567 1720 +1114 1567 1742 +1017 1569 1778 +1017 1561 1829 +1046 1552 1893 +1045 1557 1979 +1092 1536 2064 +1032 1537 2170 +810 1533 2268 +1205 1491 2382 +1680 1432 2474 +1841 1461 2509 +1841 1461 2509 +1841 1461 2509 +1841 1461 2509 +1841 1461 2509 +1841 1461 2509 +1841 1461 2509 +1841 1461 2509 +1841 1461 2509 +1841 1461 2509 +1481 1699 1851 +1480 1700 1852 +1478 1700 1853 +1476 1700 1855 +1473 1701 1857 +1470 1702 1859 +1465 1703 1863 +1458 1704 1867 +1449 1705 1873 +1448 1703 1880 +1448 1700 1888 +1448 1696 1899 +1445 1691 1913 +1423 1685 1934 +1423 1696 1979 +1383 1695 2019 +1396 1691 2067 +1278 1672 2126 +1188 1684 2221 +1246 1647 2296 +1529 1638 2386 +1793 1636 2474 +1901 1622 2511 +1901 1622 2511 +1901 1622 2511 +1901 1622 2511 +1901 1622 2511 +1901 1622 2511 +1901 1622 2511 +1901 1622 2511 +1901 1622 2511 +1901 1622 2511 +1805 1813 1975 +1805 1813 1975 +1805 1813 1976 +1804 1813 1977 +1803 1813 1978 +1802 1813 1979 +1800 1813 1982 +1798 1813 1984 +1796 1813 1988 +1797 1813 1992 +1793 1813 1998 +1787 1813 2007 +1777 1813 2018 +1763 1819 2033 +1745 1813 2049 +1744 1807 2077 +1710 1816 2126 +1718 1804 2166 +1664 1793 2234 +1690 1798 2306 +1770 1797 2390 +1871 1786 2475 +1974 1800 2514 +1974 1800 2514 +1974 1800 2514 +1974 1800 2514 +1974 1800 2514 +1974 1800 2514 +1974 1800 2514 +1974 1800 2514 +1974 1800 2514 +1974 1800 2514 +1968 1958 2031 +1968 1958 2031 +1967 1958 2032 +1967 1958 2032 +1966 1958 2033 +1965 1958 2034 +1964 1958 2036 +1963 1958 2038 +1961 1958 2040 +1960 1958 2043 +1958 1958 2048 +1955 1958 2054 +1953 1958 2061 +1945 1959 2068 +1939 1964 2081 +1934 1966 2107 +1928 1969 2157 +1905 1959 2189 +1920 1965 2239 +1893 1965 2317 +1933 1954 2393 +2043 1964 2481 +2104 1965 2515 +2104 1965 2515 +2104 1965 2515 +2104 1965 2515 +2104 1965 2515 +2104 1965 2515 +2104 1965 2515 +2104 1965 2515 +2104 1965 2515 +2104 1965 2515 +2122 2122 2070 +2122 2122 2070 +2122 2122 2071 +2122 2122 2071 +2122 2122 2071 +2123 2122 2071 +2123 2122 2072 +2124 2122 2072 +2124 2122 2073 +2124 2122 2076 +2124 2124 2080 +2124 2125 2086 +2124 2127 2093 +2119 2127 2101 +2119 2127 2110 +2120 2131 2130 +2116 2135 2169 +2108 2128 2204 +2113 2132 2254 +2124 2133 2316 +2148 2133 2397 +2216 2146 2485 +2260 2159 2522 +2260 2159 2522 +2260 2159 2522 +2260 2159 2522 +2260 2159 2522 +2260 2159 2522 +2260 2159 2522 +2260 2159 2522 +2260 2159 2522 +2260 2159 2522 +2370 2355 2124 +2370 2355 2124 +2370 2355 2124 +2370 2355 2125 +2370 2355 2125 +2370 2355 2126 +2371 2355 2126 +2371 2355 2127 +2371 2355 2129 +2371 2356 2131 +2370 2357 2133 +2370 2357 2137 +2371 2358 2143 +2370 2358 2146 +2369 2356 2148 +2370 2358 2161 +2373 2358 2193 +2372 2358 2227 +2376 2357 2273 +2388 2360 2337 +2411 2367 2406 +2465 2385 2499 +2496 2392 2532 +2496 2392 2532 +2496 2392 2532 +2496 2392 2532 +2496 2392 2532 +2496 2392 2532 +2496 2392 2532 +2496 2392 2532 +2496 2392 2532 +2496 2392 2532 +2680 2654 1962 +2680 2655 1962 +2681 2655 1963 +2681 2655 1964 +2681 2655 1966 +2681 2655 1968 +2681 2656 1970 +2681 2656 1974 +2681 2656 1972 +2681 2655 1970 +2680 2655 1969 +2680 2654 1966 +2679 2654 1967 +2679 2655 1987 +2677 2657 2008 +2677 2656 2029 +2675 2652 2050 +2677 2656 2121 +2681 2656 2208 +2688 2660 2306 +2695 2665 2407 +2715 2678 2527 +2724 2684 2577 +2724 2684 2577 +2724 2684 2577 +2724 2684 2577 +2724 2684 2577 +2724 2684 2577 +2724 2684 2577 +2724 2684 2577 +2724 2684 2577 +2724 2684 2577 +2713 2771 2430 +2713 2771 2430 +2713 2771 2430 +2714 2771 2430 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2432 +2715 2770 2435 +2716 2769 2439 +2714 2769 2444 +2711 2772 2462 +2711 2773 2481 +2714 2774 2521 +2713 2773 2553 +2717 2777 2616 +2723 2785 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2713 2771 2430 +2713 2771 2430 +2713 2771 2430 +2714 2771 2430 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2432 +2715 2770 2435 +2716 2769 2439 +2714 2769 2444 +2711 2772 2462 +2711 2773 2481 +2714 2774 2521 +2713 2773 2553 +2717 2777 2616 +2723 2785 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2713 2771 2430 +2713 2771 2430 +2713 2771 2430 +2714 2771 2430 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2432 +2715 2770 2435 +2716 2769 2439 +2714 2769 2444 +2711 2772 2462 +2711 2773 2481 +2714 2774 2521 +2713 2773 2553 +2717 2777 2616 +2723 2785 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2713 2771 2430 +2713 2771 2430 +2713 2771 2430 +2714 2771 2430 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2432 +2715 2770 2435 +2716 2769 2439 +2714 2769 2444 +2711 2772 2462 +2711 2773 2481 +2714 2774 2521 +2713 2773 2553 +2717 2777 2616 +2723 2785 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2713 2771 2430 +2713 2771 2430 +2713 2771 2430 +2714 2771 2430 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2432 +2715 2770 2435 +2716 2769 2439 +2714 2769 2444 +2711 2772 2462 +2711 2773 2481 +2714 2774 2521 +2713 2773 2553 +2717 2777 2616 +2723 2785 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2713 2771 2430 +2713 2771 2430 +2713 2771 2430 +2714 2771 2430 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2432 +2715 2770 2435 +2716 2769 2439 +2714 2769 2444 +2711 2772 2462 +2711 2773 2481 +2714 2774 2521 +2713 2773 2553 +2717 2777 2616 +2723 2785 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2713 2771 2430 +2713 2771 2430 +2713 2771 2430 +2714 2771 2430 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2432 +2715 2770 2435 +2716 2769 2439 +2714 2769 2444 +2711 2772 2462 +2711 2773 2481 +2714 2774 2521 +2713 2773 2553 +2717 2777 2616 +2723 2785 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2713 2771 2430 +2713 2771 2430 +2713 2771 2430 +2714 2771 2430 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2432 +2715 2770 2435 +2716 2769 2439 +2714 2769 2444 +2711 2772 2462 +2711 2773 2481 +2714 2774 2521 +2713 2773 2553 +2717 2777 2616 +2723 2785 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2713 2771 2430 +2713 2771 2430 +2713 2771 2430 +2714 2771 2430 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2432 +2715 2770 2435 +2716 2769 2439 +2714 2769 2444 +2711 2772 2462 +2711 2773 2481 +2714 2774 2521 +2713 2773 2553 +2717 2777 2616 +2723 2785 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2713 2771 2430 +2713 2771 2430 +2713 2771 2430 +2714 2771 2430 +2714 2771 2431 +2714 2771 2431 +2714 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2431 +2715 2771 2432 +2715 2770 2435 +2716 2769 2439 +2714 2769 2444 +2711 2772 2462 +2711 2773 2481 +2714 2774 2521 +2713 2773 2553 +2717 2777 2616 +2723 2785 2694 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +737 0 0 +737 0 0 +737 0 0 +737 0 0 +737 0 28 +737 0 152 +737 0 280 +737 0 408 +737 0 537 +737 0 667 +737 0 797 +737 0 928 +703 0 1088 +438 0 1361 +394 0 1525 +667 0 1634 +977 0 1782 +1248 0 1893 +1561 0 2015 +1525 291 2172 +265 987 2341 +1385 462 2468 +1740 0 2504 +1740 0 2504 +1740 0 2504 +1740 0 2504 +1740 0 2504 +1740 0 2504 +1740 0 2504 +1740 0 2504 +1740 0 2504 +1740 0 2504 +734 0 0 +736 0 0 +736 0 0 +736 0 0 +736 0 36 +736 0 159 +736 0 285 +736 0 412 +736 0 540 +736 0 669 +736 0 799 +736 0 930 +697 0 1089 +427 0 1361 +381 0 1525 +669 0 1635 +971 0 1782 +1248 0 1893 +1561 0 2015 +1524 306 2173 +265 992 2341 +1388 465 2468 +1740 0 2504 +1740 0 2504 +1740 0 2504 +1740 0 2504 +1740 0 2504 +1740 0 2504 +1740 0 2504 +1740 0 2504 +1740 0 2504 +1740 0 2504 +729 0 0 +730 0 0 +733 0 0 +733 0 0 +733 0 48 +733 0 168 +733 0 291 +733 0 417 +733 0 544 +733 0 672 +733 0 801 +733 0 931 +694 0 1090 +412 0 1362 +365 0 1526 +672 0 1635 +963 0 1782 +1247 0 1894 +1560 0 2016 +1522 325 2173 +265 998 2341 +1392 470 2468 +1740 0 2504 +1740 0 2504 +1740 0 2504 +1740 0 2504 +1740 0 2504 +1740 0 2504 +1740 0 2504 +1740 0 2504 +1740 0 2504 +1740 0 2504 +722 0 0 +723 0 0 +726 0 0 +730 0 0 +730 0 63 +730 0 180 +730 0 300 +730 0 424 +730 0 549 +730 0 676 +730 0 804 +730 0 933 +690 0 1091 +391 0 1363 +341 0 1526 +676 0 1636 +953 0 1781 +1245 0 1894 +1560 0 2017 +1519 349 2173 +265 1005 2342 +1398 476 2468 +1739 0 2504 +1739 0 2504 +1739 0 2504 +1739 0 2504 +1739 0 2504 +1739 0 2504 +1739 0 2504 +1739 0 2504 +1739 0 2504 +1739 0 2504 +712 0 0 +714 0 0 +717 0 0 +720 0 0 +725 0 83 +725 0 195 +725 0 312 +725 0 433 +725 0 556 +725 0 681 +725 0 808 +725 0 936 +685 0 1093 +361 0 1364 +307 0 1527 +681 0 1637 +939 0 1781 +1244 0 1895 +1559 0 2018 +1516 380 2173 +265 1015 2342 +1405 484 2468 +1739 0 2505 +1739 0 2505 +1739 0 2505 +1739 0 2505 +1739 0 2505 +1739 0 2505 +1739 0 2505 +1739 0 2505 +1739 0 2505 +1739 0 2505 +699 0 0 +701 0 0 +704 0 0 +708 0 0 +712 0 83 +719 0 215 +719 0 327 +719 0 444 +719 0 564 +719 0 688 +719 0 813 +719 0 940 +678 0 1096 +317 30 1365 +258 30 1528 +688 0 1639 +918 0 1780 +1242 0 1896 +1558 0 2019 +1512 419 2174 +265 1028 2343 +1415 494 2468 +1738 30 2505 +1738 30 2505 +1738 30 2505 +1738 30 2505 +1738 30 2505 +1738 30 2505 +1738 30 2505 +1738 30 2505 +1738 30 2505 +1738 30 2505 +681 4 0 +683 0 0 +686 0 0 +690 0 0 +695 0 83 +702 0 215 +710 0 347 +710 0 459 +710 0 576 +710 0 697 +710 0 820 +710 0 946 +669 0 1100 +251 163 1367 +182 163 1530 +697 32 1641 +890 0 1779 +1239 0 1897 +1557 32 2021 +1506 465 2175 +265 1045 2344 +1427 508 2468 +1737 163 2505 +1737 163 2505 +1737 163 2505 +1737 163 2505 +1737 163 2505 +1737 163 2505 +1737 163 2505 +1737 163 2505 +1737 163 2505 +1737 163 2505 +656 144 0 +658 137 0 +661 127 0 +665 114 0 +670 96 83 +678 70 215 +686 34 347 +699 0 479 +699 0 591 +699 0 708 +699 0 829 +699 0 952 +656 52 1105 +145 295 1370 +56 295 1531 +708 164 1644 +849 0 1778 +1236 0 1899 +1555 164 2023 +1498 521 2175 +265 1066 2345 +1443 526 2468 +1736 295 2505 +1736 295 2505 +1736 295 2505 +1736 295 2505 +1736 295 2505 +1736 295 2505 +1736 295 2505 +1736 295 2505 +1736 295 2505 +1736 295 2505 +620 281 0 +623 276 0 +626 269 0 +630 259 0 +636 246 83 +643 227 215 +653 202 347 +666 166 479 +683 111 611 +683 111 723 +683 111 840 +683 111 961 +639 167 1111 +0 426 1374 +0 426 1534 +723 296 1648 +788 0 1777 +1231 111 1901 +1552 296 2027 +1487 586 2177 +265 1093 2347 +1456 606 2469 +1735 426 2506 +1735 426 2506 +1735 426 2506 +1735 426 2506 +1735 426 2506 +1735 426 2506 +1735 426 2506 +1735 426 2506 +1735 426 2506 +1735 426 2506 +567 417 0 +570 413 0 +573 408 0 +578 401 0 +585 391 83 +593 378 215 +604 360 347 +618 334 479 +637 298 611 +660 244 743 +660 244 856 +660 244 973 +614 286 1119 +0 536 1379 +0 559 1537 +743 428 1653 +797 104 1780 +1224 244 1904 +1549 428 2031 +1472 660 2178 +265 1128 2349 +1472 699 2469 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +1732 559 2507 +567 552 0 +570 549 0 +573 545 0 +578 540 0 +585 533 83 +593 523 215 +604 510 347 +618 492 479 +637 466 611 +660 430 743 +660 521 912 +660 521 1017 +614 545 1152 +0 703 1397 +0 691 1550 +743 597 1662 +797 399 1786 +1238 422 1910 +1518 560 2039 +1417 815 2187 +186 1169 2352 +1521 727 2469 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +567 686 0 +570 684 0 +573 681 0 +578 677 0 +585 672 83 +593 665 215 +604 655 347 +618 643 479 +637 624 611 +660 599 743 +660 664 912 +660 739 1070 +614 754 1192 +0 860 1421 +0 823 1568 +743 755 1675 +797 625 1792 +1261 593 1918 +1472 692 2049 +1331 963 2199 +0 1212 2357 +1579 761 2469 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +569 854 85 +559 854 130 +563 852 185 +568 850 248 +574 846 322 +583 841 404 +594 835 496 +608 826 594 +627 814 700 +651 797 811 +651 841 960 +651 893 1104 +678 945 1245 +0 1017 1454 +0 983 1592 +758 925 1697 +804 857 1807 +1275 800 1931 +1408 849 2061 +1203 1108 2212 +0 1254 2365 +1635 828 2469 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +834 1134 954 +827 1134 961 +819 1134 970 +808 1134 982 +792 1134 998 +770 1134 1018 +739 1134 1043 +693 1134 1075 +625 1134 1115 +570 1131 1163 +570 1152 1237 +570 1179 1321 +601 1208 1413 +800 1208 1514 +767 1185 1636 +863 1174 1754 +863 1195 1861 +1192 1157 1970 +1257 1131 2078 +1043 1269 2229 +975 1275 2368 +1616 1030 2470 +1784 1087 2512 +1784 1087 2512 +1784 1087 2512 +1784 1087 2512 +1784 1087 2512 +1784 1087 2512 +1784 1087 2512 +1784 1087 2512 +1784 1087 2512 +1784 1087 2512 +857 1389 1341 +851 1389 1344 +843 1389 1348 +832 1389 1353 +817 1389 1360 +797 1389 1369 +767 1389 1381 +725 1389 1397 +661 1389 1417 +559 1389 1442 +559 1389 1463 +559 1389 1491 +591 1400 1546 +794 1400 1623 +813 1382 1691 +874 1379 1799 +874 1408 1902 +1201 1371 2008 +1151 1350 2106 +878 1405 2245 +1078 1352 2375 +1623 1208 2472 +1819 1270 2510 +1819 1270 2510 +1819 1270 2510 +1819 1270 2510 +1819 1270 2510 +1819 1270 2510 +1819 1270 2510 +1819 1270 2510 +1819 1270 2510 +1819 1270 2510 +1214 1557 1667 +1213 1557 1668 +1212 1558 1669 +1211 1558 1670 +1209 1559 1672 +1207 1560 1674 +1205 1561 1677 +1201 1563 1681 +1195 1565 1686 +1188 1569 1694 +1188 1567 1706 +1188 1567 1722 +1177 1567 1744 +1072 1567 1776 +1057 1558 1825 +1094 1552 1894 +1094 1557 1981 +1142 1536 2063 +1061 1537 2170 +810 1536 2268 +1232 1487 2382 +1680 1427 2474 +1839 1457 2509 +1839 1457 2509 +1839 1457 2509 +1839 1457 2509 +1839 1457 2509 +1839 1457 2509 +1839 1457 2509 +1839 1457 2509 +1839 1457 2509 +1839 1457 2509 +1512 1695 1855 +1511 1695 1855 +1510 1695 1856 +1508 1696 1858 +1505 1696 1860 +1502 1697 1862 +1497 1698 1866 +1491 1699 1870 +1482 1701 1876 +1478 1703 1881 +1478 1700 1889 +1478 1696 1900 +1475 1691 1914 +1446 1684 1934 +1440 1693 1977 +1405 1695 2020 +1418 1691 2069 +1312 1672 2125 +1209 1684 2221 +1248 1649 2296 +1541 1636 2386 +1794 1633 2475 +1900 1619 2511 +1900 1619 2511 +1900 1619 2511 +1900 1619 2511 +1900 1619 2511 +1900 1619 2511 +1900 1619 2511 +1900 1619 2511 +1900 1619 2511 +1900 1619 2511 +1813 1811 1973 +1812 1811 1974 +1812 1811 1975 +1811 1811 1976 +1810 1811 1977 +1809 1811 1978 +1808 1811 1981 +1806 1811 1983 +1803 1811 1987 +1799 1811 1992 +1795 1811 1998 +1789 1811 2007 +1779 1812 2018 +1767 1817 2033 +1749 1812 2048 +1751 1809 2076 +1717 1818 2125 +1722 1802 2166 +1667 1793 2234 +1699 1800 2306 +1776 1797 2391 +1871 1786 2475 +1978 1800 2515 +1978 1800 2515 +1978 1800 2515 +1978 1800 2515 +1978 1800 2515 +1978 1800 2515 +1978 1800 2515 +1978 1800 2515 +1978 1800 2515 +1978 1800 2515 +1972 1958 2032 +1972 1958 2033 +1971 1958 2033 +1971 1958 2034 +1970 1958 2034 +1969 1958 2036 +1968 1958 2037 +1967 1958 2039 +1965 1958 2041 +1962 1958 2045 +1961 1958 2049 +1958 1958 2055 +1955 1958 2062 +1947 1958 2069 +1940 1963 2081 +1937 1965 2105 +1931 1968 2155 +1905 1958 2189 +1920 1964 2238 +1898 1964 2316 +1934 1954 2393 +2043 1964 2481 +2108 1964 2515 +2108 1964 2515 +2108 1964 2515 +2108 1964 2515 +2108 1964 2515 +2108 1964 2515 +2108 1964 2515 +2108 1964 2515 +2108 1964 2515 +2108 1964 2515 +2123 2122 2071 +2123 2122 2071 +2123 2122 2071 +2123 2122 2072 +2124 2122 2072 +2124 2122 2072 +2124 2122 2073 +2125 2122 2073 +2125 2122 2074 +2126 2122 2075 +2126 2124 2079 +2126 2125 2085 +2125 2127 2092 +2119 2127 2101 +2119 2127 2110 +2122 2131 2129 +2118 2135 2168 +2110 2127 2203 +2114 2132 2254 +2126 2132 2316 +2148 2134 2399 +2218 2147 2485 +2259 2159 2522 +2259 2159 2522 +2259 2159 2522 +2259 2159 2522 +2259 2159 2522 +2259 2159 2522 +2259 2159 2522 +2259 2159 2522 +2259 2159 2522 +2259 2159 2522 +2370 2355 2124 +2370 2355 2124 +2370 2355 2124 +2370 2355 2125 +2370 2355 2125 +2370 2355 2126 +2371 2355 2126 +2371 2355 2127 +2371 2355 2129 +2372 2355 2131 +2371 2356 2133 +2372 2357 2137 +2372 2358 2143 +2371 2358 2146 +2369 2356 2148 +2370 2358 2160 +2373 2358 2193 +2373 2358 2228 +2377 2357 2273 +2391 2362 2337 +2412 2367 2407 +2466 2386 2499 +2496 2392 2532 +2496 2392 2532 +2496 2392 2532 +2496 2392 2532 +2496 2392 2532 +2496 2392 2532 +2496 2392 2532 +2496 2392 2532 +2496 2392 2532 +2496 2392 2532 +2680 2654 1961 +2680 2654 1961 +2680 2654 1962 +2680 2654 1963 +2680 2655 1965 +2680 2655 1966 +2681 2655 1969 +2681 2656 1973 +2681 2655 1970 +2680 2654 1966 +2680 2654 1965 +2679 2653 1962 +2679 2653 1963 +2678 2655 1982 +2677 2657 2003 +2678 2657 2033 +2676 2653 2053 +2678 2656 2122 +2681 2656 2208 +2688 2660 2306 +2695 2665 2407 +2715 2678 2527 +2724 2684 2577 +2724 2684 2577 +2724 2684 2577 +2724 2684 2577 +2724 2684 2577 +2724 2684 2577 +2724 2684 2577 +2724 2684 2577 +2724 2684 2577 +2724 2684 2577 +2713 2770 2430 +2713 2770 2430 +2713 2770 2430 +2713 2770 2430 +2713 2770 2430 +2714 2770 2430 +2714 2770 2430 +2714 2770 2431 +2715 2770 2431 +2716 2770 2431 +2716 2770 2431 +2716 2770 2431 +2716 2770 2432 +2715 2770 2435 +2716 2769 2439 +2714 2769 2444 +2711 2772 2462 +2712 2773 2481 +2714 2774 2521 +2713 2773 2553 +2717 2777 2616 +2723 2785 2695 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2713 2770 2430 +2713 2770 2430 +2713 2770 2430 +2713 2770 2430 +2713 2770 2430 +2714 2770 2430 +2714 2770 2430 +2714 2770 2431 +2715 2770 2431 +2716 2770 2431 +2716 2770 2431 +2716 2770 2431 +2716 2770 2432 +2715 2770 2435 +2716 2769 2439 +2714 2769 2444 +2711 2772 2462 +2712 2773 2481 +2714 2774 2521 +2713 2773 2553 +2717 2777 2616 +2723 2785 2695 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2713 2770 2430 +2713 2770 2430 +2713 2770 2430 +2713 2770 2430 +2713 2770 2430 +2714 2770 2430 +2714 2770 2430 +2714 2770 2431 +2715 2770 2431 +2716 2770 2431 +2716 2770 2431 +2716 2770 2431 +2716 2770 2432 +2715 2770 2435 +2716 2769 2439 +2714 2769 2444 +2711 2772 2462 +2712 2773 2481 +2714 2774 2521 +2713 2773 2553 +2717 2777 2616 +2723 2785 2695 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2713 2770 2430 +2713 2770 2430 +2713 2770 2430 +2713 2770 2430 +2713 2770 2430 +2714 2770 2430 +2714 2770 2430 +2714 2770 2431 +2715 2770 2431 +2716 2770 2431 +2716 2770 2431 +2716 2770 2431 +2716 2770 2432 +2715 2770 2435 +2716 2769 2439 +2714 2769 2444 +2711 2772 2462 +2712 2773 2481 +2714 2774 2521 +2713 2773 2553 +2717 2777 2616 +2723 2785 2695 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2713 2770 2430 +2713 2770 2430 +2713 2770 2430 +2713 2770 2430 +2713 2770 2430 +2714 2770 2430 +2714 2770 2430 +2714 2770 2431 +2715 2770 2431 +2716 2770 2431 +2716 2770 2431 +2716 2770 2431 +2716 2770 2432 +2715 2770 2435 +2716 2769 2439 +2714 2769 2444 +2711 2772 2462 +2712 2773 2481 +2714 2774 2521 +2713 2773 2553 +2717 2777 2616 +2723 2785 2695 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2713 2770 2430 +2713 2770 2430 +2713 2770 2430 +2713 2770 2430 +2713 2770 2430 +2714 2770 2430 +2714 2770 2430 +2714 2770 2431 +2715 2770 2431 +2716 2770 2431 +2716 2770 2431 +2716 2770 2431 +2716 2770 2432 +2715 2770 2435 +2716 2769 2439 +2714 2769 2444 +2711 2772 2462 +2712 2773 2481 +2714 2774 2521 +2713 2773 2553 +2717 2777 2616 +2723 2785 2695 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2713 2770 2430 +2713 2770 2430 +2713 2770 2430 +2713 2770 2430 +2713 2770 2430 +2714 2770 2430 +2714 2770 2430 +2714 2770 2431 +2715 2770 2431 +2716 2770 2431 +2716 2770 2431 +2716 2770 2431 +2716 2770 2432 +2715 2770 2435 +2716 2769 2439 +2714 2769 2444 +2711 2772 2462 +2712 2773 2481 +2714 2774 2521 +2713 2773 2553 +2717 2777 2616 +2723 2785 2695 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2713 2770 2430 +2713 2770 2430 +2713 2770 2430 +2713 2770 2430 +2713 2770 2430 +2714 2770 2430 +2714 2770 2430 +2714 2770 2431 +2715 2770 2431 +2716 2770 2431 +2716 2770 2431 +2716 2770 2431 +2716 2770 2432 +2715 2770 2435 +2716 2769 2439 +2714 2769 2444 +2711 2772 2462 +2712 2773 2481 +2714 2774 2521 +2713 2773 2553 +2717 2777 2616 +2723 2785 2695 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2713 2770 2430 +2713 2770 2430 +2713 2770 2430 +2713 2770 2430 +2713 2770 2430 +2714 2770 2430 +2714 2770 2430 +2714 2770 2431 +2715 2770 2431 +2716 2770 2431 +2716 2770 2431 +2716 2770 2431 +2716 2770 2432 +2715 2770 2435 +2716 2769 2439 +2714 2769 2444 +2711 2772 2462 +2712 2773 2481 +2714 2774 2521 +2713 2773 2553 +2717 2777 2616 +2723 2785 2695 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2713 2770 2430 +2713 2770 2430 +2713 2770 2430 +2713 2770 2430 +2713 2770 2430 +2714 2770 2430 +2714 2770 2430 +2714 2770 2431 +2715 2770 2431 +2716 2770 2431 +2716 2770 2431 +2716 2770 2431 +2716 2770 2432 +2715 2770 2435 +2716 2769 2439 +2714 2769 2444 +2711 2772 2462 +2712 2773 2481 +2714 2774 2521 +2713 2773 2553 +2717 2777 2616 +2723 2785 2695 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +871 0 0 +871 0 0 +871 0 0 +871 0 0 +871 0 28 +871 0 152 +871 0 280 +871 0 408 +871 0 537 +871 0 667 +871 0 797 +871 0 928 +845 0 1088 +668 0 1361 +535 0 1543 +769 0 1643 +1048 0 1782 +1313 0 1897 +1561 0 2018 +1511 412 2179 +186 987 2341 +1454 356 2467 +1743 0 2505 +1743 0 2505 +1743 0 2505 +1743 0 2505 +1743 0 2505 +1743 0 2505 +1743 0 2505 +1743 0 2505 +1743 0 2505 +1743 0 2505 +868 0 0 +869 0 0 +869 0 0 +869 0 0 +869 0 36 +869 0 159 +869 0 285 +869 0 412 +869 0 540 +869 0 669 +869 0 799 +869 0 930 +841 0 1089 +662 0 1361 +526 0 1543 +770 0 1643 +1043 0 1782 +1313 0 1897 +1561 0 2018 +1510 423 2179 +186 992 2341 +1457 360 2467 +1743 0 2505 +1743 0 2505 +1743 0 2505 +1743 0 2505 +1743 0 2505 +1743 0 2505 +1743 0 2505 +1743 0 2505 +1743 0 2505 +1743 0 2505 +864 0 0 +866 0 0 +868 0 0 +868 0 0 +868 0 48 +868 0 168 +868 0 291 +868 0 417 +868 0 544 +868 0 672 +868 0 801 +868 0 931 +839 0 1090 +653 0 1362 +513 0 1544 +773 0 1644 +1036 0 1782 +1312 0 1897 +1560 0 2019 +1508 438 2179 +186 998 2341 +1461 366 2467 +1743 0 2505 +1743 0 2505 +1743 0 2505 +1743 0 2505 +1743 0 2505 +1743 0 2505 +1743 0 2505 +1743 0 2505 +1743 0 2505 +1743 0 2505 +859 0 0 +861 0 0 +862 0 0 +865 0 0 +865 0 63 +865 0 180 +865 0 300 +865 0 424 +865 0 549 +865 0 676 +865 0 804 +865 0 933 +836 0 1091 +640 0 1363 +496 0 1544 +776 0 1645 +1027 0 1781 +1311 0 1898 +1560 0 2020 +1505 457 2180 +186 1005 2342 +1465 373 2467 +1742 0 2505 +1742 0 2505 +1742 0 2505 +1742 0 2505 +1742 0 2505 +1742 0 2505 +1742 0 2505 +1742 0 2505 +1742 0 2505 +1742 0 2505 +852 0 0 +854 0 0 +856 0 0 +858 0 0 +862 0 83 +862 0 195 +862 0 312 +862 0 433 +862 0 556 +862 0 681 +862 0 808 +862 0 936 +833 0 1093 +623 0 1364 +473 0 1545 +780 0 1646 +1015 0 1781 +1310 0 1899 +1559 0 2021 +1502 482 2180 +186 1015 2342 +1472 383 2467 +1742 0 2505 +1742 0 2505 +1742 0 2505 +1742 0 2505 +1742 0 2505 +1742 0 2505 +1742 0 2505 +1742 0 2505 +1742 0 2505 +1742 0 2505 +843 0 0 +844 0 0 +846 0 0 +849 0 0 +852 0 83 +857 0 215 +857 0 327 +857 0 444 +857 0 564 +857 0 688 +857 0 813 +857 0 940 +827 0 1096 +599 30 1365 +439 30 1546 +785 0 1648 +998 0 1780 +1308 0 1900 +1558 0 2022 +1497 512 2180 +186 1028 2343 +1480 397 2467 +1741 30 2505 +1741 30 2505 +1741 30 2505 +1741 30 2505 +1741 30 2505 +1741 30 2505 +1741 30 2505 +1741 30 2505 +1741 30 2505 +1741 30 2505 +830 4 0 +831 0 0 +833 0 0 +836 0 0 +839 0 83 +844 0 215 +851 0 347 +851 0 459 +851 0 576 +851 0 697 +851 0 820 +851 0 946 +821 0 1100 +565 163 1367 +390 163 1547 +793 32 1650 +974 0 1779 +1306 0 1901 +1557 32 2024 +1491 551 2181 +186 1045 2344 +1491 413 2467 +1740 163 2506 +1740 163 2506 +1740 163 2506 +1740 163 2506 +1740 163 2506 +1740 163 2506 +1740 163 2506 +1740 163 2506 +1740 163 2506 +1740 163 2506 +812 144 0 +813 137 0 +815 127 0 +818 114 0 +822 96 83 +827 70 215 +834 34 347 +842 0 479 +842 0 591 +842 0 708 +842 0 829 +842 0 952 +812 52 1105 +515 295 1370 +314 295 1549 +802 164 1653 +940 0 1778 +1302 0 1903 +1555 164 2027 +1483 597 2182 +186 1066 2345 +1505 435 2467 +1739 295 2506 +1739 295 2506 +1739 295 2506 +1739 295 2506 +1739 295 2506 +1739 295 2506 +1739 295 2506 +1739 295 2506 +1739 295 2506 +1739 295 2506 +787 281 0 +788 276 0 +790 269 0 +793 259 0 +797 246 83 +803 227 215 +809 202 347 +819 166 479 +831 111 611 +831 111 723 +831 111 840 +831 111 961 +799 167 1111 +438 426 1374 +188 426 1552 +814 296 1657 +891 0 1777 +1298 111 1905 +1552 296 2030 +1472 653 2183 +186 1093 2347 +1516 532 2467 +1738 426 2507 +1738 426 2507 +1738 426 2507 +1738 426 2507 +1738 426 2507 +1738 426 2507 +1738 426 2507 +1738 426 2507 +1738 426 2507 +1738 426 2507 +750 417 0 +752 413 0 +755 408 0 +758 401 0 +762 391 83 +768 378 215 +775 360 347 +785 334 479 +798 298 611 +815 244 743 +815 244 856 +815 244 973 +782 286 1119 +345 536 1379 +0 559 1555 +831 428 1662 +899 104 1780 +1292 244 1908 +1549 428 2034 +1456 718 2185 +186 1128 2349 +1530 640 2468 +1736 559 2508 +1736 559 2508 +1736 559 2508 +1736 559 2508 +1736 559 2508 +1736 559 2508 +1736 559 2508 +1736 559 2508 +1736 559 2508 +1736 559 2508 +697 552 0 +699 549 0 +702 545 0 +705 540 0 +710 533 83 +717 523 215 +725 510 347 +736 492 479 +750 466 611 +769 430 743 +792 376 875 +792 376 988 +758 407 1131 +280 611 1385 +0 691 1559 +799 583 1666 +916 342 1786 +1257 324 1907 +1545 560 2040 +1434 792 2187 +186 1169 2352 +1547 752 2469 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +1732 691 2509 +697 686 0 +699 684 0 +702 681 0 +705 677 0 +710 672 83 +717 665 215 +725 655 347 +736 643 479 +750 624 611 +769 599 743 +792 562 875 +792 654 1044 +758 672 1172 +280 796 1409 +0 823 1576 +799 745 1680 +916 591 1792 +1279 529 1915 +1502 692 2050 +1352 947 2199 +0 1212 2357 +1603 785 2469 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +699 854 85 +691 854 130 +694 852 185 +698 850 248 +702 846 322 +709 841 404 +717 835 496 +728 826 594 +743 814 700 +762 797 811 +786 774 927 +786 834 1081 +805 893 1228 +403 973 1443 +0 983 1599 +812 918 1701 +921 837 1807 +1293 760 1928 +1442 849 2062 +1230 1096 2212 +0 1254 2365 +1657 848 2469 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +910 1134 954 +905 1134 961 +898 1134 970 +889 1134 982 +875 1134 998 +857 1134 1018 +832 1134 1043 +795 1134 1075 +741 1134 1115 +699 1131 1163 +726 1120 1220 +726 1149 1307 +748 1179 1402 +901 1179 1504 +767 1185 1644 +906 1170 1757 +968 1186 1861 +1214 1140 1967 +1304 1131 2079 +1082 1261 2229 +975 1275 2368 +1638 1044 2470 +1784 1087 2512 +1784 1087 2512 +1784 1087 2512 +1784 1087 2512 +1784 1087 2512 +1784 1087 2512 +1784 1087 2512 +1784 1087 2512 +1784 1087 2512 +1784 1087 2512 +993 1376 1327 +989 1376 1330 +983 1376 1334 +975 1376 1340 +964 1376 1347 +949 1376 1356 +928 1376 1368 +899 1376 1385 +857 1376 1405 +793 1376 1431 +691 1376 1463 +691 1376 1491 +715 1388 1546 +877 1388 1623 +945 1376 1697 +997 1370 1804 +1006 1396 1906 +1223 1377 2010 +1151 1350 2105 +878 1405 2247 +1167 1339 2373 +1626 1218 2473 +1826 1254 2510 +1826 1254 2510 +1826 1254 2510 +1826 1254 2510 +1826 1254 2510 +1826 1254 2510 +1826 1254 2510 +1826 1254 2510 +1826 1254 2510 +1826 1254 2510 +1284 1548 1666 +1284 1549 1666 +1283 1549 1667 +1282 1550 1668 +1281 1550 1670 +1279 1551 1673 +1276 1553 1675 +1273 1555 1680 +1269 1557 1685 +1263 1560 1692 +1239 1562 1707 +1239 1562 1723 +1229 1562 1745 +1136 1562 1777 +1127 1554 1826 +1162 1550 1897 +1168 1552 1984 +1181 1539 2065 +1075 1537 2169 +810 1538 2270 +1285 1479 2381 +1681 1429 2475 +1842 1448 2509 +1842 1448 2509 +1842 1448 2509 +1842 1448 2509 +1842 1448 2509 +1842 1448 2509 +1842 1448 2509 +1842 1448 2509 +1842 1448 2509 +1842 1448 2509 +1553 1689 1859 +1552 1689 1860 +1551 1689 1861 +1549 1690 1862 +1547 1690 1864 +1544 1691 1867 +1539 1692 1870 +1534 1693 1874 +1526 1695 1880 +1522 1697 1885 +1517 1700 1891 +1517 1696 1902 +1515 1691 1916 +1488 1684 1935 +1461 1690 1974 +1430 1693 2019 +1446 1691 2070 +1360 1672 2128 +1236 1684 2221 +1248 1653 2296 +1559 1632 2386 +1794 1630 2475 +1898 1615 2511 +1898 1615 2511 +1898 1615 2511 +1898 1615 2511 +1898 1615 2511 +1898 1615 2511 +1898 1615 2511 +1898 1615 2511 +1898 1615 2511 +1898 1615 2511 +1821 1809 1972 +1820 1809 1972 +1820 1809 1973 +1819 1809 1974 +1818 1809 1975 +1817 1809 1977 +1816 1809 1979 +1813 1809 1982 +1811 1809 1986 +1807 1809 1990 +1800 1811 1998 +1793 1811 2007 +1784 1811 2018 +1772 1817 2033 +1754 1811 2049 +1756 1809 2076 +1721 1816 2124 +1728 1804 2168 +1675 1795 2234 +1712 1800 2308 +1779 1799 2391 +1880 1789 2475 +1982 1798 2515 +1982 1798 2515 +1982 1798 2515 +1982 1798 2515 +1982 1798 2515 +1982 1798 2515 +1982 1798 2515 +1982 1798 2515 +1982 1798 2515 +1982 1798 2515 +1977 1958 2034 +1977 1958 2034 +1976 1958 2035 +1976 1958 2035 +1975 1958 2036 +1974 1958 2037 +1973 1958 2038 +1972 1958 2040 +1970 1958 2043 +1968 1958 2046 +1964 1958 2050 +1962 1958 2056 +1959 1958 2063 +1950 1958 2070 +1942 1961 2081 +1940 1963 2103 +1935 1966 2152 +1912 1959 2190 +1920 1962 2236 +1904 1962 2314 +1936 1954 2394 +2043 1964 2481 +2112 1962 2514 +2112 1962 2514 +2112 1962 2514 +2112 1962 2514 +2112 1962 2514 +2112 1962 2514 +2112 1962 2514 +2112 1962 2514 +2112 1962 2514 +2112 1962 2514 +2124 2124 2073 +2124 2124 2073 +2124 2124 2073 +2125 2124 2073 +2125 2124 2073 +2125 2124 2074 +2125 2124 2074 +2126 2124 2075 +2126 2124 2076 +2127 2124 2076 +2129 2124 2078 +2129 2125 2083 +2128 2127 2090 +2122 2127 2100 +2119 2127 2110 +2123 2131 2129 +2120 2135 2167 +2113 2128 2205 +2115 2130 2253 +2128 2131 2316 +2148 2135 2400 +2220 2148 2485 +2258 2159 2521 +2258 2159 2521 +2258 2159 2521 +2258 2159 2521 +2258 2159 2521 +2258 2159 2521 +2258 2159 2521 +2258 2159 2521 +2258 2159 2521 +2258 2159 2521 +2370 2355 2124 +2370 2355 2124 +2370 2355 2124 +2370 2355 2125 +2370 2355 2125 +2370 2355 2126 +2371 2355 2126 +2371 2355 2127 +2371 2355 2129 +2372 2355 2131 +2372 2355 2133 +2373 2356 2137 +2374 2357 2143 +2372 2357 2146 +2369 2356 2148 +2370 2358 2159 +2374 2358 2192 +2374 2358 2228 +2379 2358 2273 +2393 2364 2337 +2413 2367 2408 +2467 2387 2498 +2496 2393 2533 +2496 2393 2533 +2496 2393 2533 +2496 2393 2533 +2496 2393 2533 +2496 2393 2533 +2496 2393 2533 +2496 2393 2533 +2496 2393 2533 +2496 2393 2533 +2680 2654 1959 +2680 2654 1959 +2680 2654 1960 +2680 2654 1961 +2680 2654 1963 +2680 2655 1965 +2680 2655 1968 +2680 2655 1971 +2680 2655 1969 +2680 2654 1965 +2679 2653 1959 +2679 2652 1957 +2678 2652 1958 +2678 2654 1977 +2677 2657 1996 +2678 2657 2031 +2677 2654 2057 +2678 2657 2122 +2682 2656 2208 +2688 2660 2307 +2695 2665 2407 +2715 2678 2527 +2725 2684 2578 +2725 2684 2578 +2725 2684 2578 +2725 2684 2578 +2725 2684 2578 +2725 2684 2578 +2725 2684 2578 +2725 2684 2578 +2725 2684 2578 +2725 2684 2578 +2713 2770 2429 +2713 2770 2429 +2713 2770 2429 +2713 2770 2429 +2713 2770 2430 +2713 2770 2430 +2714 2770 2430 +2714 2770 2430 +2715 2770 2430 +2715 2770 2431 +2716 2770 2431 +2716 2770 2431 +2716 2770 2432 +2716 2770 2435 +2716 2769 2439 +2714 2770 2444 +2711 2772 2462 +2712 2773 2483 +2714 2775 2522 +2712 2773 2553 +2717 2777 2616 +2724 2786 2697 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2713 2770 2429 +2713 2770 2429 +2713 2770 2429 +2713 2770 2429 +2713 2770 2430 +2713 2770 2430 +2714 2770 2430 +2714 2770 2430 +2715 2770 2430 +2715 2770 2431 +2716 2770 2431 +2716 2770 2431 +2716 2770 2432 +2716 2770 2435 +2716 2769 2439 +2714 2770 2444 +2711 2772 2462 +2712 2773 2483 +2714 2775 2522 +2712 2773 2553 +2717 2777 2616 +2724 2786 2697 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2713 2770 2429 +2713 2770 2429 +2713 2770 2429 +2713 2770 2429 +2713 2770 2430 +2713 2770 2430 +2714 2770 2430 +2714 2770 2430 +2715 2770 2430 +2715 2770 2431 +2716 2770 2431 +2716 2770 2431 +2716 2770 2432 +2716 2770 2435 +2716 2769 2439 +2714 2770 2444 +2711 2772 2462 +2712 2773 2483 +2714 2775 2522 +2712 2773 2553 +2717 2777 2616 +2724 2786 2697 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2713 2770 2429 +2713 2770 2429 +2713 2770 2429 +2713 2770 2429 +2713 2770 2430 +2713 2770 2430 +2714 2770 2430 +2714 2770 2430 +2715 2770 2430 +2715 2770 2431 +2716 2770 2431 +2716 2770 2431 +2716 2770 2432 +2716 2770 2435 +2716 2769 2439 +2714 2770 2444 +2711 2772 2462 +2712 2773 2483 +2714 2775 2522 +2712 2773 2553 +2717 2777 2616 +2724 2786 2697 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2713 2770 2429 +2713 2770 2429 +2713 2770 2429 +2713 2770 2429 +2713 2770 2430 +2713 2770 2430 +2714 2770 2430 +2714 2770 2430 +2715 2770 2430 +2715 2770 2431 +2716 2770 2431 +2716 2770 2431 +2716 2770 2432 +2716 2770 2435 +2716 2769 2439 +2714 2770 2444 +2711 2772 2462 +2712 2773 2483 +2714 2775 2522 +2712 2773 2553 +2717 2777 2616 +2724 2786 2697 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2713 2770 2429 +2713 2770 2429 +2713 2770 2429 +2713 2770 2429 +2713 2770 2430 +2713 2770 2430 +2714 2770 2430 +2714 2770 2430 +2715 2770 2430 +2715 2770 2431 +2716 2770 2431 +2716 2770 2431 +2716 2770 2432 +2716 2770 2435 +2716 2769 2439 +2714 2770 2444 +2711 2772 2462 +2712 2773 2483 +2714 2775 2522 +2712 2773 2553 +2717 2777 2616 +2724 2786 2697 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2713 2770 2429 +2713 2770 2429 +2713 2770 2429 +2713 2770 2429 +2713 2770 2430 +2713 2770 2430 +2714 2770 2430 +2714 2770 2430 +2715 2770 2430 +2715 2770 2431 +2716 2770 2431 +2716 2770 2431 +2716 2770 2432 +2716 2770 2435 +2716 2769 2439 +2714 2770 2444 +2711 2772 2462 +2712 2773 2483 +2714 2775 2522 +2712 2773 2553 +2717 2777 2616 +2724 2786 2697 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2713 2770 2429 +2713 2770 2429 +2713 2770 2429 +2713 2770 2429 +2713 2770 2430 +2713 2770 2430 +2714 2770 2430 +2714 2770 2430 +2715 2770 2430 +2715 2770 2431 +2716 2770 2431 +2716 2770 2431 +2716 2770 2432 +2716 2770 2435 +2716 2769 2439 +2714 2770 2444 +2711 2772 2462 +2712 2773 2483 +2714 2775 2522 +2712 2773 2553 +2717 2777 2616 +2724 2786 2697 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2713 2770 2429 +2713 2770 2429 +2713 2770 2429 +2713 2770 2429 +2713 2770 2430 +2713 2770 2430 +2714 2770 2430 +2714 2770 2430 +2715 2770 2430 +2715 2770 2431 +2716 2770 2431 +2716 2770 2431 +2716 2770 2432 +2716 2770 2435 +2716 2769 2439 +2714 2770 2444 +2711 2772 2462 +2712 2773 2483 +2714 2775 2522 +2712 2773 2553 +2717 2777 2616 +2724 2786 2697 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2713 2770 2429 +2713 2770 2429 +2713 2770 2429 +2713 2770 2429 +2713 2770 2430 +2713 2770 2430 +2714 2770 2430 +2714 2770 2430 +2715 2770 2430 +2715 2770 2431 +2716 2770 2431 +2716 2770 2431 +2716 2770 2432 +2716 2770 2435 +2716 2769 2439 +2714 2770 2444 +2711 2772 2462 +2712 2773 2483 +2714 2775 2522 +2712 2773 2553 +2717 2777 2616 +2724 2786 2697 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +1004 0 0 +1004 0 0 +1004 0 0 +1004 0 0 +1004 0 28 +1004 0 152 +1004 0 280 +1004 0 408 +1004 0 537 +1004 0 667 +1004 0 797 +1004 0 928 +985 0 1088 +862 0 1361 +674 0 1566 +856 0 1661 +1128 0 1782 +1394 0 1902 +1561 0 2022 +1491 535 2188 +220 987 2343 +1533 158 2465 +1747 0 2505 +1747 0 2505 +1747 0 2505 +1747 0 2505 +1747 0 2505 +1747 0 2505 +1747 0 2505 +1747 0 2505 +1747 0 2505 +1747 0 2505 +1002 0 0 +1003 0 0 +1003 0 0 +1003 0 0 +1003 0 36 +1003 0 159 +1003 0 285 +1003 0 412 +1003 0 540 +1003 0 669 +1003 0 799 +1003 0 930 +982 0 1089 +858 0 1361 +667 0 1566 +858 0 1662 +1124 0 1782 +1393 0 1903 +1561 0 2022 +1490 544 2188 +220 992 2343 +1536 164 2465 +1747 0 2505 +1747 0 2505 +1747 0 2505 +1747 0 2505 +1747 0 2505 +1747 0 2505 +1747 0 2505 +1747 0 2505 +1747 0 2505 +1747 0 2505 +999 0 0 +1000 0 0 +1002 0 0 +1002 0 0 +1002 0 48 +1002 0 168 +1002 0 291 +1002 0 417 +1002 0 544 +1002 0 672 +1002 0 801 +1002 0 931 +981 0 1090 +852 0 1362 +658 0 1567 +860 0 1662 +1118 0 1782 +1393 0 1903 +1560 0 2023 +1488 556 2188 +220 998 2343 +1539 173 2465 +1747 0 2505 +1747 0 2505 +1747 0 2505 +1747 0 2505 +1747 0 2505 +1747 0 2505 +1747 0 2505 +1747 0 2505 +1747 0 2505 +1747 0 2505 +996 0 0 +996 0 0 +998 0 0 +1000 0 0 +1000 0 63 +1000 0 180 +1000 0 300 +1000 0 424 +1000 0 549 +1000 0 676 +1000 0 804 +1000 0 933 +979 0 1091 +844 0 1363 +645 0 1567 +862 0 1663 +1110 0 1781 +1392 0 1903 +1560 0 2024 +1486 570 2188 +220 1005 2344 +1543 185 2465 +1746 0 2505 +1746 0 2505 +1746 0 2505 +1746 0 2505 +1746 0 2505 +1746 0 2505 +1746 0 2505 +1746 0 2505 +1746 0 2505 +1746 0 2505 +990 0 0 +991 0 0 +993 0 0 +995 0 0 +997 0 83 +997 0 195 +997 0 312 +997 0 433 +997 0 556 +997 0 681 +997 0 808 +997 0 936 +976 0 1093 +833 0 1364 +629 0 1568 +866 0 1664 +1100 0 1781 +1391 0 1904 +1559 0 2025 +1482 590 2189 +220 1015 2344 +1548 200 2465 +1746 0 2506 +1746 0 2506 +1746 0 2506 +1746 0 2506 +1746 0 2506 +1746 0 2506 +1746 0 2506 +1746 0 2506 +1746 0 2506 +1746 0 2506 +983 0 0 +985 0 0 +986 0 0 +988 0 0 +991 0 83 +994 0 215 +994 0 327 +994 0 444 +994 0 564 +994 0 688 +994 0 813 +994 0 940 +973 0 1096 +819 30 1365 +605 30 1569 +871 0 1666 +1086 0 1780 +1390 0 1905 +1558 0 2026 +1477 614 2189 +220 1028 2345 +1555 219 2465 +1745 30 2506 +1745 30 2506 +1745 30 2506 +1745 30 2506 +1745 30 2506 +1745 30 2506 +1745 30 2506 +1745 30 2506 +1745 30 2506 +1745 30 2506 +974 4 0 +975 0 0 +977 0 0 +979 0 0 +981 0 83 +985 0 215 +989 0 347 +989 0 459 +989 0 576 +989 0 697 +989 0 820 +989 0 946 +968 0 1100 +798 163 1367 +571 163 1570 +876 32 1668 +1067 0 1779 +1388 0 1906 +1557 32 2028 +1471 645 2190 +220 1045 2346 +1564 244 2465 +1744 163 2506 +1744 163 2506 +1744 163 2506 +1744 163 2506 +1744 163 2506 +1744 163 2506 +1744 163 2506 +1744 163 2506 +1744 163 2506 +1744 163 2506 +961 144 0 +962 137 0 +963 127 0 +966 114 0 +968 96 83 +972 70 215 +977 34 347 +983 0 479 +983 0 591 +983 0 708 +983 0 829 +983 0 952 +961 52 1105 +769 295 1370 +522 295 1572 +884 164 1671 +1039 0 1778 +1385 0 1908 +1555 164 2031 +1462 683 2191 +220 1066 2347 +1576 275 2465 +1743 295 2507 +1743 295 2507 +1743 295 2507 +1743 295 2507 +1743 295 2507 +1743 295 2507 +1743 295 2507 +1743 295 2507 +1743 295 2507 +1743 295 2507 +943 281 0 +944 276 0 +946 269 0 +948 259 0 +951 246 83 +955 227 215 +959 202 347 +966 166 479 +975 111 611 +975 111 723 +975 111 840 +975 111 961 +952 167 1111 +726 426 1374 +446 426 1574 +895 296 1674 +1000 0 1777 +1382 111 1910 +1552 296 2034 +1450 729 2192 +220 1093 2349 +1586 407 2466 +1741 426 2508 +1741 426 2508 +1741 426 2508 +1741 426 2508 +1741 426 2508 +1741 426 2508 +1741 426 2508 +1741 426 2508 +1741 426 2508 +1741 426 2508 +917 417 0 +919 413 0 +920 408 0 +923 401 0 +926 391 83 +930 378 215 +935 360 347 +942 334 479 +951 298 611 +963 244 743 +963 244 856 +963 244 973 +940 286 1119 +679 536 1379 +320 559 1577 +908 428 1679 +1006 104 1780 +1377 244 1913 +1549 428 2038 +1434 785 2194 +220 1128 2351 +1598 544 2467 +1739 559 2508 +1739 559 2508 +1739 559 2508 +1739 559 2508 +1739 559 2508 +1739 559 2508 +1739 559 2508 +1739 559 2508 +1739 559 2508 +1739 559 2508 +881 552 0 +883 549 0 +884 545 0 +887 540 0 +890 533 83 +894 523 215 +900 510 347 +908 492 479 +917 466 611 +930 430 743 +947 376 875 +947 376 988 +923 407 1131 +649 611 1385 +67 691 1581 +882 583 1684 +1020 342 1786 +1348 324 1912 +1545 560 2044 +1411 850 2196 +220 1169 2354 +1613 680 2468 +1736 691 2509 +1736 691 2509 +1736 691 2509 +1736 691 2509 +1736 691 2509 +1736 691 2509 +1736 691 2509 +1736 691 2509 +1736 691 2509 +1736 691 2509 +828 686 0 +829 684 0 +831 681 0 +834 677 0 +838 672 83 +842 665 215 +849 655 347 +857 643 479 +868 624 611 +883 599 743 +901 562 875 +925 508 1007 +899 532 1145 +605 694 1393 +0 823 1587 +799 745 1688 +1039 540 1792 +1299 403 1909 +1539 692 2052 +1379 925 2199 +0 1212 2357 +1633 815 2469 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +1732 823 2511 +829 854 85 +823 854 130 +825 852 185 +828 850 248 +832 846 322 +837 841 404 +843 835 496 +852 826 594 +863 814 700 +877 797 811 +896 774 927 +920 741 1047 +934 812 1203 +669 906 1428 +0 983 1610 +812 918 1709 +1043 809 1807 +1313 689 1923 +1484 849 2064 +1265 1080 2212 +0 1254 2365 +1683 875 2469 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +996 1134 954 +992 1134 961 +986 1134 970 +979 1134 982 +968 1134 998 +953 1134 1018 +932 1134 1043 +903 1134 1075 +861 1134 1115 +829 1131 1163 +850 1120 1220 +876 1105 1286 +892 1138 1385 +1008 1138 1491 +767 1185 1653 +906 1170 1765 +1078 1173 1861 +1237 1110 1962 +1360 1131 2081 +1129 1250 2229 +975 1275 2368 +1666 1061 2470 +1784 1087 2512 +1784 1087 2512 +1784 1087 2512 +1784 1087 2512 +1784 1087 2512 +1784 1087 2512 +1784 1087 2512 +1784 1087 2512 +1784 1087 2512 +1784 1087 2512 +1129 1359 1308 +1126 1359 1311 +1121 1359 1315 +1115 1359 1321 +1107 1359 1328 +1097 1359 1338 +1082 1359 1351 +1061 1359 1367 +1032 1359 1389 +989 1359 1416 +926 1359 1449 +823 1359 1491 +841 1371 1546 +969 1371 1623 +1077 1367 1705 +1117 1361 1811 +1138 1380 1911 +1246 1386 2012 +1151 1350 2103 +878 1405 2249 +1204 1332 2374 +1631 1230 2474 +1835 1230 2510 +1835 1230 2510 +1835 1230 2510 +1835 1230 2510 +1835 1230 2510 +1835 1230 2510 +1835 1230 2510 +1835 1230 2510 +1835 1230 2510 +1835 1230 2510 +1361 1536 1656 +1360 1537 1657 +1360 1537 1658 +1359 1538 1659 +1358 1539 1661 +1356 1540 1663 +1354 1541 1667 +1351 1543 1671 +1347 1545 1676 +1342 1549 1684 +1323 1550 1699 +1283 1550 1723 +1274 1550 1745 +1190 1550 1777 +1220 1548 1833 +1249 1544 1903 +1265 1540 1988 +1206 1545 2067 +1075 1537 2167 +810 1538 2272 +1313 1474 2382 +1686 1437 2475 +1851 1433 2509 +1851 1433 2509 +1851 1433 2509 +1851 1433 2509 +1851 1433 2509 +1851 1433 2509 +1851 1433 2509 +1851 1433 2509 +1851 1433 2509 +1851 1433 2509 +1603 1680 1865 +1602 1680 1865 +1600 1680 1867 +1599 1681 1868 +1597 1681 1870 +1594 1682 1872 +1590 1683 1876 +1585 1684 1880 +1578 1686 1886 +1575 1689 1891 +1571 1692 1897 +1565 1696 1905 +1563 1691 1919 +1538 1684 1938 +1489 1686 1969 +1460 1689 2014 +1482 1691 2072 +1418 1672 2133 +1270 1684 2221 +1248 1657 2296 +1563 1627 2386 +1794 1625 2476 +1896 1610 2511 +1896 1610 2511 +1896 1610 2511 +1896 1610 2511 +1896 1610 2511 +1896 1610 2511 +1896 1610 2511 +1896 1610 2511 +1896 1610 2511 +1896 1610 2511 +1830 1805 1969 +1830 1805 1970 +1829 1805 1971 +1829 1805 1972 +1828 1805 1973 +1827 1805 1974 +1825 1805 1977 +1823 1805 1979 +1821 1805 1983 +1817 1805 1988 +1810 1807 1996 +1800 1811 2007 +1791 1811 2018 +1779 1817 2033 +1762 1811 2051 +1763 1809 2078 +1725 1813 2122 +1736 1807 2171 +1689 1798 2234 +1727 1800 2309 +1778 1800 2391 +1894 1792 2475 +1986 1795 2515 +1986 1795 2515 +1986 1795 2515 +1986 1795 2515 +1986 1795 2515 +1986 1795 2515 +1986 1795 2515 +1986 1795 2515 +1986 1795 2515 +1986 1795 2515 +1983 1958 2036 +1983 1958 2036 +1983 1958 2037 +1983 1958 2037 +1982 1958 2038 +1981 1958 2039 +1980 1958 2040 +1979 1958 2042 +1977 1958 2045 +1974 1958 2048 +1971 1958 2052 +1966 1958 2058 +1963 1958 2065 +1955 1958 2072 +1945 1959 2081 +1942 1961 2103 +1940 1963 2147 +1922 1962 2193 +1920 1960 2233 +1912 1960 2312 +1943 1954 2394 +2043 1964 2481 +2119 1960 2514 +2119 1960 2514 +2119 1960 2514 +2119 1960 2514 +2119 1960 2514 +2119 1960 2514 +2119 1960 2514 +2119 1960 2514 +2119 1960 2514 +2119 1960 2514 +2126 2125 2075 +2126 2125 2075 +2126 2125 2075 +2126 2125 2075 +2126 2125 2075 +2127 2125 2076 +2127 2125 2076 +2127 2125 2076 +2128 2125 2077 +2129 2125 2078 +2130 2125 2080 +2132 2125 2082 +2131 2127 2089 +2125 2127 2098 +2119 2127 2110 +2123 2131 2129 +2124 2135 2165 +2118 2130 2208 +2117 2129 2251 +2132 2129 2316 +2154 2135 2400 +2222 2149 2485 +2257 2159 2521 +2257 2159 2521 +2257 2159 2521 +2257 2159 2521 +2257 2159 2521 +2257 2159 2521 +2257 2159 2521 +2257 2159 2521 +2257 2159 2521 +2257 2159 2521 +2371 2355 2125 +2371 2355 2125 +2371 2355 2125 +2371 2355 2126 +2372 2355 2126 +2372 2355 2127 +2372 2355 2127 +2372 2355 2128 +2372 2355 2130 +2373 2355 2132 +2374 2355 2134 +2374 2355 2136 +2375 2356 2142 +2373 2356 2145 +2371 2355 2148 +2372 2357 2159 +2375 2358 2191 +2375 2358 2229 +2381 2358 2273 +2396 2366 2336 +2413 2367 2408 +2468 2388 2498 +2497 2394 2532 +2497 2394 2532 +2497 2394 2532 +2497 2394 2532 +2497 2394 2532 +2497 2394 2532 +2497 2394 2532 +2497 2394 2532 +2497 2394 2532 +2497 2394 2532 +2679 2653 1956 +2679 2653 1957 +2679 2653 1958 +2679 2654 1959 +2679 2654 1961 +2680 2654 1962 +2680 2654 1965 +2680 2655 1969 +2680 2654 1966 +2679 2653 1962 +2679 2652 1957 +2678 2651 1950 +2678 2650 1950 +2677 2652 1970 +2676 2657 1988 +2678 2657 2023 +2679 2655 2063 +2679 2657 2122 +2682 2656 2208 +2688 2660 2308 +2695 2665 2407 +2715 2678 2527 +2726 2684 2578 +2726 2684 2578 +2726 2684 2578 +2726 2684 2578 +2726 2684 2578 +2726 2684 2578 +2726 2684 2578 +2726 2684 2578 +2726 2684 2578 +2726 2684 2578 +2712 2770 2428 +2712 2770 2429 +2712 2770 2429 +2712 2770 2429 +2713 2770 2429 +2713 2770 2429 +2713 2770 2429 +2714 2770 2429 +2714 2770 2430 +2715 2770 2430 +2716 2770 2431 +2717 2770 2431 +2717 2770 2432 +2716 2770 2435 +2716 2769 2439 +2714 2770 2444 +2711 2772 2462 +2713 2774 2488 +2714 2775 2522 +2712 2773 2553 +2717 2777 2617 +2724 2787 2699 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2712 2770 2428 +2712 2770 2429 +2712 2770 2429 +2712 2770 2429 +2713 2770 2429 +2713 2770 2429 +2713 2770 2429 +2714 2770 2429 +2714 2770 2430 +2715 2770 2430 +2716 2770 2431 +2717 2770 2431 +2717 2770 2432 +2716 2770 2435 +2716 2769 2439 +2714 2770 2444 +2711 2772 2462 +2713 2774 2488 +2714 2775 2522 +2712 2773 2553 +2717 2777 2617 +2724 2787 2699 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2712 2770 2428 +2712 2770 2429 +2712 2770 2429 +2712 2770 2429 +2713 2770 2429 +2713 2770 2429 +2713 2770 2429 +2714 2770 2429 +2714 2770 2430 +2715 2770 2430 +2716 2770 2431 +2717 2770 2431 +2717 2770 2432 +2716 2770 2435 +2716 2769 2439 +2714 2770 2444 +2711 2772 2462 +2713 2774 2488 +2714 2775 2522 +2712 2773 2553 +2717 2777 2617 +2724 2787 2699 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2712 2770 2428 +2712 2770 2429 +2712 2770 2429 +2712 2770 2429 +2713 2770 2429 +2713 2770 2429 +2713 2770 2429 +2714 2770 2429 +2714 2770 2430 +2715 2770 2430 +2716 2770 2431 +2717 2770 2431 +2717 2770 2432 +2716 2770 2435 +2716 2769 2439 +2714 2770 2444 +2711 2772 2462 +2713 2774 2488 +2714 2775 2522 +2712 2773 2553 +2717 2777 2617 +2724 2787 2699 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2712 2770 2428 +2712 2770 2429 +2712 2770 2429 +2712 2770 2429 +2713 2770 2429 +2713 2770 2429 +2713 2770 2429 +2714 2770 2429 +2714 2770 2430 +2715 2770 2430 +2716 2770 2431 +2717 2770 2431 +2717 2770 2432 +2716 2770 2435 +2716 2769 2439 +2714 2770 2444 +2711 2772 2462 +2713 2774 2488 +2714 2775 2522 +2712 2773 2553 +2717 2777 2617 +2724 2787 2699 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2712 2770 2428 +2712 2770 2429 +2712 2770 2429 +2712 2770 2429 +2713 2770 2429 +2713 2770 2429 +2713 2770 2429 +2714 2770 2429 +2714 2770 2430 +2715 2770 2430 +2716 2770 2431 +2717 2770 2431 +2717 2770 2432 +2716 2770 2435 +2716 2769 2439 +2714 2770 2444 +2711 2772 2462 +2713 2774 2488 +2714 2775 2522 +2712 2773 2553 +2717 2777 2617 +2724 2787 2699 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2712 2770 2428 +2712 2770 2429 +2712 2770 2429 +2712 2770 2429 +2713 2770 2429 +2713 2770 2429 +2713 2770 2429 +2714 2770 2429 +2714 2770 2430 +2715 2770 2430 +2716 2770 2431 +2717 2770 2431 +2717 2770 2432 +2716 2770 2435 +2716 2769 2439 +2714 2770 2444 +2711 2772 2462 +2713 2774 2488 +2714 2775 2522 +2712 2773 2553 +2717 2777 2617 +2724 2787 2699 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2712 2770 2428 +2712 2770 2429 +2712 2770 2429 +2712 2770 2429 +2713 2770 2429 +2713 2770 2429 +2713 2770 2429 +2714 2770 2429 +2714 2770 2430 +2715 2770 2430 +2716 2770 2431 +2717 2770 2431 +2717 2770 2432 +2716 2770 2435 +2716 2769 2439 +2714 2770 2444 +2711 2772 2462 +2713 2774 2488 +2714 2775 2522 +2712 2773 2553 +2717 2777 2617 +2724 2787 2699 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2712 2770 2428 +2712 2770 2429 +2712 2770 2429 +2712 2770 2429 +2713 2770 2429 +2713 2770 2429 +2713 2770 2429 +2714 2770 2429 +2714 2770 2430 +2715 2770 2430 +2716 2770 2431 +2717 2770 2431 +2717 2770 2432 +2716 2770 2435 +2716 2769 2439 +2714 2770 2444 +2711 2772 2462 +2713 2774 2488 +2714 2775 2522 +2712 2773 2553 +2717 2777 2617 +2724 2787 2699 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2712 2770 2428 +2712 2770 2429 +2712 2770 2429 +2712 2770 2429 +2713 2770 2429 +2713 2770 2429 +2713 2770 2429 +2714 2770 2429 +2714 2770 2430 +2715 2770 2430 +2716 2770 2431 +2717 2770 2431 +2717 2770 2432 +2716 2770 2435 +2716 2769 2439 +2714 2770 2444 +2711 2772 2462 +2713 2774 2488 +2714 2775 2522 +2712 2773 2553 +2717 2777 2617 +2724 2787 2699 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +1146 0 0 +1146 0 0 +1146 0 0 +1146 0 46 +1146 0 140 +1146 0 240 +1146 0 347 +1146 0 460 +1146 0 576 +1146 0 697 +1146 0 820 +1146 0 946 +1143 0 1084 +1060 0 1359 +918 0 1574 +981 0 1683 +1223 0 1785 +1476 0 1909 +1569 0 2028 +1478 645 2197 +391 989 2347 +1611 0 2464 +1756 0 2506 +1756 0 2506 +1756 0 2506 +1756 0 2506 +1756 0 2506 +1756 0 2506 +1756 0 2506 +1756 0 2506 +1756 0 2506 +1756 0 2506 +1146 0 0 +1146 0 0 +1146 0 27 +1146 0 101 +1146 0 185 +1146 0 277 +1146 0 376 +1146 0 482 +1146 0 594 +1146 0 710 +1146 0 830 +1146 0 953 +1142 0 1089 +1059 0 1361 +917 0 1576 +981 0 1683 +1223 0 1786 +1476 0 1910 +1569 0 2029 +1477 656 2197 +395 992 2347 +1611 0 2464 +1757 0 2506 +1757 0 2506 +1757 0 2506 +1757 0 2506 +1757 0 2506 +1757 0 2506 +1757 0 2506 +1757 0 2506 +1757 0 2506 +1757 0 2506 +1143 0 0 +1143 0 0 +1144 0 38 +1144 0 111 +1144 0 193 +1144 0 284 +1144 0 382 +1144 0 487 +1144 0 598 +1144 0 713 +1144 0 833 +1144 0 955 +1141 0 1090 +1055 0 1362 +911 0 1576 +982 0 1684 +1219 0 1785 +1475 0 1911 +1568 0 2029 +1475 665 2197 +395 998 2347 +1614 0 2464 +1756 0 2506 +1756 0 2506 +1756 0 2506 +1756 0 2506 +1756 0 2506 +1756 0 2506 +1756 0 2506 +1756 0 2506 +1756 0 2506 +1756 0 2506 +1141 0 0 +1141 0 0 +1142 0 38 +1143 0 124 +1143 0 204 +1143 0 293 +1143 0 389 +1143 0 493 +1143 0 602 +1143 0 717 +1143 0 835 +1143 0 957 +1140 0 1091 +1050 0 1363 +904 0 1577 +984 0 1685 +1213 0 1785 +1474 0 1911 +1568 0 2030 +1472 676 2198 +395 1005 2348 +1617 0 2464 +1756 0 2506 +1756 0 2506 +1756 0 2506 +1756 0 2506 +1756 0 2506 +1756 0 2506 +1756 0 2506 +1756 0 2506 +1756 0 2506 +1756 0 2506 +1137 0 0 +1137 0 0 +1138 0 38 +1139 0 124 +1141 0 219 +1141 0 305 +1141 0 399 +1141 0 501 +1141 0 608 +1141 0 722 +1141 0 839 +1141 0 960 +1138 0 1093 +1043 0 1364 +895 0 1577 +987 0 1686 +1205 0 1784 +1474 0 1912 +1567 0 2031 +1469 692 2198 +395 1015 2348 +1622 0 2464 +1756 0 2506 +1756 0 2506 +1756 0 2506 +1756 0 2506 +1756 0 2506 +1756 0 2506 +1756 0 2506 +1756 0 2506 +1756 0 2506 +1756 0 2506 +1132 0 0 +1132 0 0 +1133 0 38 +1134 0 124 +1136 0 219 +1139 0 320 +1139 0 411 +1139 0 511 +1139 0 616 +1139 0 728 +1139 0 844 +1139 0 963 +1136 0 1096 +1034 0 1365 +882 0 1578 +990 0 1687 +1194 0 1784 +1472 0 1913 +1566 0 2032 +1464 711 2199 +395 1028 2349 +1628 0 2464 +1755 0 2507 +1755 0 2507 +1755 0 2507 +1755 0 2507 +1755 0 2507 +1755 0 2507 +1755 0 2507 +1755 0 2507 +1755 0 2507 +1755 0 2507 +1125 13 0 +1125 0 0 +1126 0 38 +1128 0 124 +1129 0 219 +1132 0 320 +1135 0 428 +1135 0 524 +1135 0 627 +1135 0 736 +1135 0 850 +1135 0 968 +1132 0 1100 +1021 107 1367 +864 107 1579 +995 0 1690 +1178 0 1783 +1471 0 1914 +1565 97 2034 +1457 736 2199 +395 1045 2350 +1636 0 2464 +1754 107 2507 +1754 107 2507 +1754 107 2507 +1754 107 2507 +1754 107 2507 +1754 107 2507 +1754 107 2507 +1754 107 2507 +1754 107 2507 +1754 107 2507 +1116 150 0 +1116 137 0 +1117 127 38 +1118 114 124 +1120 96 219 +1123 70 320 +1126 34 428 +1131 0 541 +1131 0 640 +1131 0 747 +1131 0 858 +1131 0 975 +1128 0 1105 +1003 254 1370 +839 254 1581 +1001 137 1692 +1157 0 1782 +1469 17 1915 +1563 213 2037 +1448 768 2200 +395 1066 2351 +1646 21 2464 +1753 254 2507 +1753 254 2507 +1753 254 2507 +1753 254 2507 +1753 254 2507 +1753 254 2507 +1753 254 2507 +1753 254 2507 +1753 254 2507 +1753 254 2507 +1103 286 0 +1103 276 0 +1104 269 38 +1106 259 124 +1108 246 219 +1110 227 320 +1114 202 428 +1118 166 541 +1125 111 658 +1125 111 760 +1125 111 869 +1125 111 983 +1121 111 1111 +979 396 1374 +803 396 1584 +1009 276 1696 +1127 0 1781 +1466 140 1918 +1560 333 2040 +1436 807 2201 +395 1093 2353 +1654 232 2464 +1751 396 2508 +1751 396 2508 +1751 396 2508 +1751 396 2508 +1751 396 2508 +1751 396 2508 +1751 396 2508 +1751 396 2508 +1751 396 2508 +1751 396 2508 +1085 420 0 +1085 413 0 +1086 408 38 +1088 401 124 +1090 391 219 +1093 378 320 +1097 360 428 +1102 334 541 +1108 298 658 +1116 244 779 +1116 244 884 +1116 244 995 +1113 244 1119 +952 513 1379 +749 536 1587 +1019 413 1700 +1132 186 1784 +1462 265 1920 +1557 456 2044 +1419 854 2202 +395 1128 2355 +1664 421 2465 +1749 536 2509 +1749 536 2509 +1749 536 2509 +1749 536 2509 +1749 536 2509 +1749 536 2509 +1749 536 2509 +1749 536 2509 +1749 536 2509 +1749 536 2509 +1061 554 0 +1061 549 0 +1062 545 38 +1064 540 124 +1066 533 219 +1069 523 320 +1073 510 428 +1078 492 541 +1085 466 658 +1093 430 779 +1105 376 902 +1105 376 1009 +1102 376 1131 +936 591 1385 +666 674 1590 +999 572 1705 +1142 392 1789 +1438 342 1919 +1553 581 2050 +1395 910 2205 +395 1169 2358 +1678 592 2466 +1746 674 2510 +1746 674 2510 +1746 674 2510 +1746 674 2510 +1746 674 2510 +1746 674 2510 +1746 674 2510 +1746 674 2510 +1746 674 2510 +1746 674 2510 +1025 688 0 +1025 684 0 +1027 681 38 +1028 677 124 +1031 672 219 +1034 665 320 +1038 655 428 +1044 643 541 +1051 624 658 +1061 599 779 +1073 562 902 +1089 508 1028 +1086 508 1145 +913 678 1393 +525 811 1596 +936 738 1709 +1157 573 1796 +1399 418 1917 +1547 709 2058 +1361 976 2207 +221 1212 2361 +1695 752 2468 +1742 811 2511 +1742 811 2511 +1742 811 2511 +1742 811 2511 +1742 811 2511 +1742 811 2511 +1742 811 2511 +1742 811 2511 +1742 811 2511 +1742 811 2511 +998 854 247 +999 854 274 +1000 852 314 +1002 850 363 +1005 846 421 +1008 841 488 +1013 835 565 +1018 826 651 +1026 814 746 +1036 797 847 +1050 774 955 +1067 741 1069 +1082 701 1186 +907 818 1417 +458 939 1611 +854 914 1719 +1166 781 1811 +1344 583 1918 +1532 855 2069 +1306 1062 2213 +0 1254 2365 +1713 908 2469 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1738 955 2513 +1120 1134 981 +1120 1134 987 +1116 1134 996 +1110 1134 1007 +1102 1134 1022 +1091 1134 1041 +1076 1134 1065 +1055 1134 1096 +1025 1134 1133 +1003 1131 1180 +1017 1120 1235 +1036 1105 1300 +1052 1087 1374 +1136 1087 1482 +920 1158 1655 +941 1167 1774 +1193 1161 1864 +1274 1071 1958 +1421 1134 2085 +1184 1237 2230 +980 1275 2368 +1697 1083 2471 +1784 1087 2512 +1784 1087 2512 +1784 1087 2512 +1784 1087 2512 +1784 1087 2512 +1784 1087 2512 +1784 1087 2512 +1784 1087 2512 +1784 1087 2512 +1784 1087 2512 +1244 1351 1313 +1244 1351 1315 +1241 1351 1320 +1236 1351 1325 +1230 1351 1332 +1222 1351 1342 +1211 1351 1355 +1195 1351 1371 +1174 1351 1392 +1143 1351 1419 +1099 1351 1452 +1031 1351 1493 +1008 1345 1543 +1101 1345 1620 +1200 1345 1706 +1180 1356 1819 +1250 1368 1917 +1282 1376 2010 +1214 1352 2106 +941 1399 2251 +1206 1332 2375 +1655 1246 2474 +1839 1219 2510 +1839 1219 2510 +1839 1219 2510 +1839 1219 2510 +1839 1219 2510 +1839 1219 2510 +1839 1219 2510 +1839 1219 2510 +1839 1219 2510 +1839 1219 2510 +1442 1522 1648 +1441 1522 1649 +1440 1523 1650 +1440 1523 1651 +1439 1524 1653 +1437 1525 1655 +1436 1526 1658 +1433 1528 1663 +1430 1531 1668 +1426 1534 1676 +1410 1536 1691 +1377 1536 1716 +1335 1537 1749 +1263 1537 1781 +1301 1537 1839 +1339 1536 1910 +1357 1528 1994 +1241 1551 2071 +1105 1537 2167 +883 1536 2275 +1324 1476 2384 +1692 1446 2476 +1866 1416 2509 +1866 1416 2509 +1866 1416 2509 +1866 1416 2509 +1866 1416 2509 +1866 1416 2509 +1866 1416 2509 +1866 1416 2509 +1866 1416 2509 +1866 1416 2509 +1656 1669 1872 +1656 1669 1873 +1655 1669 1874 +1654 1670 1875 +1652 1671 1877 +1650 1671 1879 +1646 1672 1883 +1642 1674 1887 +1636 1675 1893 +1633 1678 1897 +1629 1681 1903 +1624 1685 1911 +1616 1691 1922 +1595 1684 1941 +1542 1684 1969 +1504 1684 2010 +1525 1691 2073 +1483 1671 2138 +1324 1684 2221 +1259 1662 2297 +1564 1621 2385 +1796 1617 2477 +1894 1605 2510 +1894 1605 2510 +1894 1605 2510 +1894 1605 2510 +1894 1605 2510 +1894 1605 2510 +1894 1605 2510 +1894 1605 2510 +1894 1605 2510 +1894 1605 2510 +1843 1802 1967 +1843 1802 1968 +1843 1802 1969 +1842 1802 1969 +1841 1802 1971 +1840 1802 1972 +1839 1802 1974 +1837 1802 1977 +1834 1802 1981 +1831 1802 1986 +1824 1804 1994 +1814 1807 2005 +1802 1811 2018 +1790 1817 2033 +1773 1811 2052 +1772 1809 2081 +1734 1809 2120 +1747 1811 2175 +1708 1801 2234 +1744 1800 2309 +1774 1800 2391 +1911 1796 2475 +1992 1790 2515 +1992 1790 2515 +1992 1790 2515 +1992 1790 2515 +1992 1790 2515 +1992 1790 2515 +1992 1790 2515 +1992 1790 2515 +1992 1790 2515 +1992 1790 2515 +1992 1958 2037 +1992 1958 2037 +1992 1958 2037 +1991 1958 2038 +1991 1958 2038 +1990 1958 2040 +1989 1958 2041 +1988 1958 2043 +1986 1958 2045 +1983 1958 2049 +1980 1958 2053 +1976 1958 2059 +1970 1958 2067 +1962 1958 2074 +1950 1958 2082 +1946 1958 2104 +1947 1962 2142 +1936 1964 2196 +1923 1957 2231 +1922 1958 2310 +1954 1955 2394 +2043 1964 2481 +2127 1958 2514 +2127 1958 2514 +2127 1958 2514 +2127 1958 2514 +2127 1958 2514 +2127 1958 2514 +2127 1958 2514 +2127 1958 2514 +2127 1958 2514 +2127 1958 2514 +2128 2127 2076 +2128 2127 2077 +2129 2127 2077 +2129 2127 2077 +2129 2127 2077 +2129 2127 2078 +2130 2127 2078 +2130 2127 2079 +2131 2127 2080 +2132 2127 2080 +2133 2127 2082 +2135 2127 2084 +2135 2127 2087 +2129 2127 2097 +2122 2127 2109 +2124 2131 2129 +2128 2135 2163 +2124 2132 2210 +2119 2127 2251 +2135 2128 2316 +2164 2135 2400 +2226 2151 2485 +2257 2159 2520 +2257 2159 2520 +2257 2159 2520 +2257 2159 2520 +2257 2159 2520 +2257 2159 2520 +2257 2159 2520 +2257 2159 2520 +2257 2159 2520 +2257 2159 2520 +2374 2355 2126 +2374 2355 2127 +2374 2355 2127 +2374 2355 2127 +2374 2355 2127 +2374 2355 2128 +2374 2355 2129 +2375 2355 2130 +2375 2355 2131 +2375 2355 2133 +2376 2355 2135 +2377 2355 2138 +2376 2355 2140 +2375 2355 2143 +2372 2354 2147 +2374 2356 2159 +2375 2358 2191 +2375 2357 2230 +2381 2358 2275 +2398 2368 2335 +2415 2368 2409 +2469 2388 2498 +2498 2395 2532 +2498 2395 2532 +2498 2395 2532 +2498 2395 2532 +2498 2395 2532 +2498 2395 2532 +2498 2395 2532 +2498 2395 2532 +2498 2395 2532 +2498 2395 2532 +2679 2653 1955 +2679 2653 1955 +2679 2653 1956 +2679 2653 1957 +2679 2653 1958 +2679 2654 1961 +2679 2654 1963 +2679 2654 1967 +2679 2654 1964 +2679 2653 1961 +2678 2652 1955 +2678 2650 1948 +2677 2648 1939 +2677 2650 1960 +2676 2655 1976 +2677 2657 2013 +2680 2657 2068 +2679 2658 2122 +2683 2657 2209 +2688 2661 2310 +2695 2666 2408 +2715 2679 2527 +2727 2684 2579 +2727 2684 2579 +2727 2684 2579 +2727 2684 2579 +2727 2684 2579 +2727 2684 2579 +2727 2684 2579 +2727 2684 2579 +2727 2684 2579 +2727 2684 2579 +2712 2769 2427 +2712 2769 2427 +2712 2769 2427 +2712 2769 2428 +2712 2769 2428 +2712 2769 2428 +2713 2769 2428 +2713 2769 2428 +2714 2769 2429 +2714 2769 2429 +2715 2769 2430 +2717 2769 2431 +2718 2770 2433 +2717 2770 2436 +2716 2770 2440 +2714 2770 2444 +2712 2772 2461 +2714 2774 2492 +2714 2775 2523 +2712 2774 2554 +2717 2778 2620 +2725 2789 2702 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2712 2769 2427 +2712 2769 2427 +2712 2769 2427 +2712 2769 2428 +2712 2769 2428 +2712 2769 2428 +2713 2769 2428 +2713 2769 2428 +2714 2769 2429 +2714 2769 2429 +2715 2769 2430 +2717 2769 2431 +2718 2770 2433 +2717 2770 2436 +2716 2770 2440 +2714 2770 2444 +2712 2772 2461 +2714 2774 2492 +2714 2775 2523 +2712 2774 2554 +2717 2778 2620 +2725 2789 2702 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2712 2769 2427 +2712 2769 2427 +2712 2769 2427 +2712 2769 2428 +2712 2769 2428 +2712 2769 2428 +2713 2769 2428 +2713 2769 2428 +2714 2769 2429 +2714 2769 2429 +2715 2769 2430 +2717 2769 2431 +2718 2770 2433 +2717 2770 2436 +2716 2770 2440 +2714 2770 2444 +2712 2772 2461 +2714 2774 2492 +2714 2775 2523 +2712 2774 2554 +2717 2778 2620 +2725 2789 2702 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2712 2769 2427 +2712 2769 2427 +2712 2769 2427 +2712 2769 2428 +2712 2769 2428 +2712 2769 2428 +2713 2769 2428 +2713 2769 2428 +2714 2769 2429 +2714 2769 2429 +2715 2769 2430 +2717 2769 2431 +2718 2770 2433 +2717 2770 2436 +2716 2770 2440 +2714 2770 2444 +2712 2772 2461 +2714 2774 2492 +2714 2775 2523 +2712 2774 2554 +2717 2778 2620 +2725 2789 2702 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2712 2769 2427 +2712 2769 2427 +2712 2769 2427 +2712 2769 2428 +2712 2769 2428 +2712 2769 2428 +2713 2769 2428 +2713 2769 2428 +2714 2769 2429 +2714 2769 2429 +2715 2769 2430 +2717 2769 2431 +2718 2770 2433 +2717 2770 2436 +2716 2770 2440 +2714 2770 2444 +2712 2772 2461 +2714 2774 2492 +2714 2775 2523 +2712 2774 2554 +2717 2778 2620 +2725 2789 2702 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2712 2769 2427 +2712 2769 2427 +2712 2769 2427 +2712 2769 2428 +2712 2769 2428 +2712 2769 2428 +2713 2769 2428 +2713 2769 2428 +2714 2769 2429 +2714 2769 2429 +2715 2769 2430 +2717 2769 2431 +2718 2770 2433 +2717 2770 2436 +2716 2770 2440 +2714 2770 2444 +2712 2772 2461 +2714 2774 2492 +2714 2775 2523 +2712 2774 2554 +2717 2778 2620 +2725 2789 2702 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2712 2769 2427 +2712 2769 2427 +2712 2769 2427 +2712 2769 2428 +2712 2769 2428 +2712 2769 2428 +2713 2769 2428 +2713 2769 2428 +2714 2769 2429 +2714 2769 2429 +2715 2769 2430 +2717 2769 2431 +2718 2770 2433 +2717 2770 2436 +2716 2770 2440 +2714 2770 2444 +2712 2772 2461 +2714 2774 2492 +2714 2775 2523 +2712 2774 2554 +2717 2778 2620 +2725 2789 2702 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2712 2769 2427 +2712 2769 2427 +2712 2769 2427 +2712 2769 2428 +2712 2769 2428 +2712 2769 2428 +2713 2769 2428 +2713 2769 2428 +2714 2769 2429 +2714 2769 2429 +2715 2769 2430 +2717 2769 2431 +2718 2770 2433 +2717 2770 2436 +2716 2770 2440 +2714 2770 2444 +2712 2772 2461 +2714 2774 2492 +2714 2775 2523 +2712 2774 2554 +2717 2778 2620 +2725 2789 2702 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2712 2769 2427 +2712 2769 2427 +2712 2769 2427 +2712 2769 2428 +2712 2769 2428 +2712 2769 2428 +2713 2769 2428 +2713 2769 2428 +2714 2769 2429 +2714 2769 2429 +2715 2769 2430 +2717 2769 2431 +2718 2770 2433 +2717 2770 2436 +2716 2770 2440 +2714 2770 2444 +2712 2772 2461 +2714 2774 2492 +2714 2775 2523 +2712 2774 2554 +2717 2778 2620 +2725 2789 2702 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2712 2769 2427 +2712 2769 2427 +2712 2769 2427 +2712 2769 2428 +2712 2769 2428 +2712 2769 2428 +2713 2769 2428 +2713 2769 2428 +2714 2769 2429 +2714 2769 2429 +2715 2769 2430 +2717 2769 2431 +2718 2770 2433 +2717 2770 2436 +2716 2770 2440 +2714 2770 2444 +2712 2772 2461 +2714 2774 2492 +2714 2775 2523 +2712 2774 2554 +2717 2778 2620 +2725 2789 2702 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +2729 2789 2727 +1314 0 0 +1314 0 0 +1315 0 0 +1316 0 18 +1317 0 98 +1319 0 188 +1321 0 285 +1324 0 389 +1328 0 499 +1331 0 624 +1331 0 765 +1331 0 904 +1329 0 1054 +1312 0 1291 +1236 0 1533 +1269 0 1690 +1323 0 1781 +1534 0 1909 +1607 0 2039 +1502 645 2197 +677 1023 2352 +1658 0 2466 +1776 0 2506 +1776 0 2506 +1776 0 2506 +1776 0 2506 +1776 0 2506 +1776 0 2506 +1776 0 2506 +1776 0 2506 +1776 0 2506 +1776 0 2506 +1314 0 0 +1314 0 0 +1315 0 17 +1315 0 78 +1316 0 150 +1318 0 230 +1321 0 319 +1324 0 417 +1328 0 521 +1331 0 640 +1331 0 777 +1331 0 914 +1329 0 1059 +1311 0 1294 +1235 0 1535 +1268 0 1691 +1323 0 1782 +1533 0 1910 +1607 0 2039 +1501 656 2197 +679 1026 2352 +1659 0 2466 +1776 0 2506 +1776 0 2506 +1776 0 2506 +1776 0 2506 +1776 0 2506 +1776 0 2506 +1776 0 2506 +1776 0 2506 +1776 0 2506 +1776 0 2506 +1314 0 0 +1314 0 17 +1314 0 97 +1315 0 149 +1316 0 211 +1318 0 282 +1320 0 363 +1323 0 452 +1327 0 549 +1330 0 662 +1330 0 794 +1330 0 926 +1328 0 1068 +1311 0 1298 +1235 0 1537 +1267 0 1692 +1323 0 1783 +1532 0 1911 +1606 0 2040 +1500 671 2198 +682 1030 2352 +1660 0 2466 +1777 0 2506 +1777 0 2506 +1777 0 2506 +1777 0 2506 +1777 0 2506 +1777 0 2506 +1777 0 2506 +1777 0 2506 +1777 0 2506 +1777 0 2506 +1314 0 18 +1314 0 78 +1314 0 149 +1314 0 229 +1315 0 281 +1316 0 343 +1319 0 414 +1322 0 494 +1326 0 584 +1329 0 689 +1329 0 814 +1329 0 941 +1327 0 1079 +1310 0 1302 +1233 0 1540 +1266 0 1693 +1323 0 1784 +1531 0 1912 +1605 0 2041 +1498 690 2198 +686 1035 2353 +1661 0 2466 +1778 0 2506 +1778 0 2506 +1778 0 2506 +1778 0 2506 +1778 0 2506 +1778 0 2506 +1778 0 2506 +1778 0 2506 +1778 0 2506 +1778 0 2506 +1314 0 98 +1314 0 150 +1314 0 211 +1314 0 281 +1314 0 361 +1315 0 413 +1318 0 475 +1321 0 546 +1325 0 627 +1328 0 723 +1328 0 840 +1328 0 961 +1326 0 1094 +1309 0 1309 +1232 0 1544 +1265 0 1695 +1323 0 1787 +1529 0 1914 +1603 0 2042 +1497 714 2199 +691 1042 2353 +1662 0 2466 +1779 0 2506 +1779 0 2506 +1779 0 2506 +1779 0 2506 +1779 0 2506 +1779 0 2506 +1779 0 2506 +1779 0 2506 +1779 0 2506 +1779 0 2506 +1314 0 188 +1314 0 230 +1314 0 282 +1314 0 343 +1314 0 413 +1314 0 493 +1316 0 545 +1319 0 607 +1323 0 678 +1326 0 766 +1326 0 873 +1326 0 986 +1324 0 1113 +1307 0 1317 +1230 0 1549 +1263 0 1697 +1323 30 1790 +1527 0 1916 +1602 132 2043 +1495 745 2200 +698 1051 2354 +1663 0 2466 +1781 0 2506 +1781 0 2506 +1781 0 2506 +1781 0 2506 +1781 0 2506 +1781 0 2506 +1781 0 2506 +1781 0 2506 +1781 0 2506 +1781 0 2506 +1314 121 285 +1314 106 319 +1314 85 363 +1314 56 414 +1314 13 475 +1314 0 545 +1314 0 625 +1317 0 677 +1321 0 739 +1324 0 816 +1324 0 914 +1324 0 1018 +1322 0 1138 +1304 0 1329 +1227 0 1556 +1261 0 1700 +1323 163 1794 +1524 32 1919 +1599 264 2045 +1491 783 2201 +706 1063 2354 +1666 32 2466 +1784 0 2506 +1784 0 2506 +1784 0 2506 +1784 0 2506 +1784 0 2506 +1784 0 2506 +1784 0 2506 +1784 0 2506 +1784 0 2506 +1784 0 2506 +1314 264 389 +1314 253 417 +1314 238 452 +1314 217 494 +1314 188 546 +1314 146 607 +1314 82 677 +1314 0 757 +1318 0 809 +1321 0 876 +1321 0 963 +1321 0 1058 +1319 0 1168 +1302 0 1343 +1223 0 1565 +1257 0 1704 +1323 295 1799 +1520 164 1923 +1596 396 2047 +1487 830 2203 +718 1079 2355 +1668 164 2466 +1787 0 2506 +1787 0 2506 +1787 0 2506 +1787 0 2506 +1787 0 2506 +1787 0 2506 +1787 0 2506 +1787 0 2506 +1787 0 2506 +1787 0 2506 +1314 404 499 +1314 396 521 +1314 385 549 +1314 370 584 +1314 349 627 +1314 320 678 +1314 277 739 +1314 214 809 +1314 111 889 +1317 111 946 +1317 111 1021 +1317 111 1106 +1315 111 1206 +1297 111 1362 +1218 111 1576 +1252 111 1709 +1323 426 1806 +1515 296 1928 +1592 528 2051 +1482 885 2205 +733 1099 2357 +1667 296 2465 +1791 111 2506 +1791 111 2506 +1791 111 2506 +1791 111 2506 +1791 111 2506 +1791 111 2506 +1791 111 2506 +1791 111 2506 +1791 111 2506 +1791 111 2506 +1310 530 574 +1310 524 592 +1310 516 616 +1310 505 646 +1310 490 684 +1310 468 730 +1310 438 784 +1310 394 848 +1310 328 922 +1311 244 1001 +1311 244 1068 +1311 244 1145 +1310 244 1238 +1292 244 1379 +1207 285 1587 +1251 265 1716 +1322 514 1811 +1510 413 1934 +1587 643 2055 +1471 941 2208 +745 1128 2358 +1669 442 2465 +1794 285 2506 +1794 285 2506 +1794 285 2506 +1794 285 2506 +1794 285 2506 +1794 285 2506 +1794 285 2506 +1794 285 2506 +1794 285 2506 +1794 285 2506 +1294 639 574 +1294 634 592 +1294 627 616 +1294 619 646 +1294 607 684 +1294 591 730 +1294 568 784 +1294 535 848 +1294 488 922 +1297 430 1001 +1304 376 1080 +1304 376 1155 +1302 376 1246 +1284 376 1385 +1178 503 1590 +1239 473 1720 +1329 626 1816 +1488 470 1933 +1583 729 2060 +1450 988 2209 +745 1169 2362 +1682 607 2467 +1792 503 2507 +1792 503 2507 +1792 503 2507 +1792 503 2507 +1792 503 2507 +1792 503 2507 +1792 503 2507 +1792 503 2507 +1792 503 2507 +1792 503 2507 +1274 753 574 +1274 749 592 +1274 744 616 +1274 737 646 +1274 728 684 +1274 716 730 +1274 698 784 +1274 674 848 +1274 640 922 +1276 599 1001 +1284 562 1080 +1294 508 1169 +1292 508 1257 +1273 508 1393 +1137 691 1596 +1203 671 1723 +1338 742 1822 +1453 529 1930 +1577 824 2068 +1421 1044 2212 +672 1212 2365 +1699 762 2468 +1788 691 2509 +1788 691 2509 +1788 691 2509 +1788 691 2509 +1788 691 2509 +1788 691 2509 +1788 691 2509 +1788 691 2509 +1788 691 2509 +1788 691 2509 +1258 900 682 +1259 900 693 +1259 896 712 +1259 891 736 +1259 885 767 +1259 876 806 +1259 864 852 +1259 847 908 +1259 824 973 +1261 797 1044 +1269 774 1117 +1280 741 1199 +1289 701 1290 +1270 701 1417 +1120 852 1611 +1159 869 1734 +1344 895 1836 +1405 663 1931 +1563 942 2078 +1372 1118 2218 +602 1254 2368 +1718 915 2470 +1784 871 2510 +1784 871 2510 +1784 871 2510 +1784 871 2510 +1784 871 2510 +1784 871 2510 +1784 871 2510 +1784 871 2510 +1784 871 2510 +1784 871 2510 +1314 1134 1183 +1314 1134 1187 +1315 1134 1191 +1316 1134 1197 +1317 1134 1206 +1319 1134 1216 +1321 1134 1230 +1324 1134 1248 +1328 1134 1271 +1333 1131 1302 +1340 1120 1345 +1349 1105 1396 +1358 1087 1457 +1341 1087 1528 +1216 1158 1687 +1159 1142 1780 +1317 1176 1886 +1360 1041 1962 +1486 1159 2104 +1228 1237 2234 +1015 1275 2368 +1721 1100 2471 +1784 1087 2512 +1784 1087 2512 +1784 1087 2512 +1784 1087 2512 +1784 1087 2512 +1784 1087 2512 +1784 1087 2512 +1784 1087 2512 +1784 1087 2512 +1784 1087 2512 +1399 1351 1421 +1399 1351 1423 +1400 1351 1426 +1400 1351 1429 +1401 1351 1434 +1403 1351 1441 +1405 1351 1449 +1407 1351 1460 +1410 1351 1475 +1407 1351 1495 +1382 1351 1523 +1347 1351 1559 +1336 1345 1602 +1319 1345 1655 +1383 1345 1736 +1321 1339 1825 +1361 1378 1936 +1367 1360 2014 +1313 1367 2124 +1014 1399 2255 +1228 1332 2375 +1681 1258 2475 +1839 1219 2510 +1839 1219 2510 +1839 1219 2510 +1839 1219 2510 +1839 1219 2510 +1839 1219 2510 +1839 1219 2510 +1839 1219 2510 +1839 1219 2510 +1839 1219 2510 +1514 1522 1673 +1514 1522 1673 +1513 1522 1674 +1512 1522 1674 +1510 1522 1676 +1508 1522 1677 +1505 1522 1679 +1501 1522 1682 +1495 1522 1685 +1489 1523 1691 +1475 1525 1706 +1447 1525 1730 +1412 1526 1762 +1397 1537 1811 +1426 1537 1865 +1415 1525 1919 +1395 1535 2005 +1299 1551 2087 +1205 1526 2170 +1197 1525 2279 +1402 1488 2382 +1717 1446 2476 +1900 1416 2509 +1900 1416 2509 +1900 1416 2509 +1900 1416 2509 +1900 1416 2509 +1900 1416 2509 +1900 1416 2509 +1900 1416 2509 +1900 1416 2509 +1900 1416 2509 +1678 1669 1879 +1678 1669 1879 +1678 1669 1880 +1678 1669 1882 +1678 1669 1884 +1678 1669 1886 +1678 1669 1889 +1678 1669 1894 +1678 1669 1900 +1674 1670 1903 +1671 1673 1909 +1667 1678 1917 +1659 1683 1928 +1644 1684 1948 +1597 1684 1976 +1591 1683 2015 +1577 1683 2072 +1536 1664 2140 +1423 1683 2226 +1349 1660 2299 +1619 1615 2384 +1819 1607 2477 +1912 1605 2509 +1912 1605 2509 +1912 1605 2509 +1912 1605 2509 +1912 1605 2509 +1912 1605 2509 +1912 1605 2509 +1912 1605 2509 +1912 1605 2509 +1912 1605 2509 +1848 1802 1967 +1848 1802 1968 +1849 1802 1969 +1849 1803 1970 +1849 1803 1972 +1850 1804 1973 +1851 1805 1976 +1851 1806 1980 +1853 1807 1984 +1853 1808 1990 +1846 1810 1998 +1837 1813 2009 +1825 1817 2022 +1820 1817 2033 +1804 1811 2052 +1785 1809 2084 +1764 1804 2118 +1767 1811 2177 +1736 1801 2237 +1751 1800 2307 +1774 1800 2391 +1919 1797 2474 +2000 1784 2514 +2000 1784 2514 +2000 1784 2514 +2000 1784 2514 +2000 1784 2514 +2000 1784 2514 +2000 1784 2514 +2000 1784 2514 +2000 1784 2514 +2000 1784 2514 +1992 1958 2037 +1992 1958 2037 +1992 1958 2037 +1992 1958 2037 +1992 1958 2037 +1992 1958 2038 +1992 1958 2038 +1992 1958 2039 +1992 1958 2040 +1991 1958 2042 +1988 1958 2046 +1983 1958 2052 +1978 1958 2060 +1974 1962 2077 +1963 1962 2086 +1955 1958 2110 +1955 1962 2141 +1953 1964 2193 +1941 1953 2231 +1931 1953 2310 +1966 1959 2394 +2048 1966 2481 +2129 1963 2515 +2129 1963 2515 +2129 1963 2515 +2129 1963 2515 +2129 1963 2515 +2129 1963 2515 +2129 1963 2515 +2129 1963 2515 +2129 1963 2515 +2129 1963 2515 +2134 2127 2070 +2134 2127 2070 +2134 2127 2071 +2135 2127 2071 +2135 2127 2073 +2135 2127 2074 +2135 2127 2076 +2136 2127 2078 +2137 2127 2081 +2137 2127 2084 +2139 2127 2085 +2140 2127 2087 +2141 2127 2091 +2135 2127 2100 +2127 2127 2112 +2129 2128 2129 +2136 2135 2161 +2130 2135 2208 +2125 2127 2253 +2141 2131 2316 +2170 2132 2397 +2230 2150 2485 +2266 2159 2520 +2266 2159 2520 +2266 2159 2520 +2266 2159 2520 +2266 2159 2520 +2266 2159 2520 +2266 2159 2520 +2266 2159 2520 +2266 2159 2520 +2266 2159 2520 +2377 2355 2126 +2377 2355 2127 +2377 2355 2127 +2377 2355 2127 +2377 2355 2127 +2378 2355 2127 +2378 2355 2128 +2378 2355 2128 +2378 2355 2129 +2379 2355 2130 +2380 2355 2133 +2380 2355 2135 +2380 2355 2137 +2378 2357 2143 +2376 2356 2147 +2376 2354 2159 +2375 2358 2194 +2375 2357 2230 +2381 2357 2273 +2399 2366 2335 +2418 2368 2408 +2472 2387 2495 +2499 2395 2533 +2499 2395 2533 +2499 2395 2533 +2499 2395 2533 +2499 2395 2533 +2499 2395 2533 +2499 2395 2533 +2499 2395 2533 +2499 2395 2533 +2499 2395 2533 +2680 2655 1964 +2680 2655 1964 +2680 2655 1964 +2680 2655 1964 +2680 2655 1964 +2680 2655 1964 +2680 2655 1964 +2680 2655 1964 +2679 2655 1968 +2679 2655 1970 +2679 2654 1965 +2678 2652 1958 +2677 2650 1949 +2677 2648 1945 +2675 2653 1962 +2676 2656 2011 +2680 2657 2064 +2681 2657 2122 +2684 2657 2213 +2688 2662 2314 +2696 2667 2413 +2716 2679 2527 +2727 2684 2578 +2727 2684 2578 +2727 2684 2578 +2727 2684 2578 +2727 2684 2578 +2727 2684 2578 +2727 2684 2578 +2727 2684 2578 +2727 2684 2578 +2727 2684 2578 +2713 2769 2427 +2713 2769 2427 +2713 2769 2427 +2713 2769 2428 +2714 2769 2428 +2714 2769 2428 +2714 2769 2428 +2714 2769 2428 +2714 2769 2429 +2714 2769 2429 +2715 2769 2430 +2717 2769 2431 +2718 2770 2433 +2719 2772 2443 +2718 2772 2447 +2715 2770 2444 +2712 2771 2455 +2714 2774 2492 +2716 2775 2523 +2714 2775 2560 +2719 2781 2625 +2725 2789 2703 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2713 2769 2427 +2713 2769 2427 +2713 2769 2427 +2713 2769 2428 +2714 2769 2428 +2714 2769 2428 +2714 2769 2428 +2714 2769 2428 +2714 2769 2429 +2714 2769 2429 +2715 2769 2430 +2717 2769 2431 +2718 2770 2433 +2719 2772 2443 +2718 2772 2447 +2715 2770 2444 +2712 2771 2455 +2714 2774 2492 +2716 2775 2523 +2714 2775 2560 +2719 2781 2625 +2725 2789 2703 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2713 2769 2427 +2713 2769 2427 +2713 2769 2427 +2713 2769 2428 +2714 2769 2428 +2714 2769 2428 +2714 2769 2428 +2714 2769 2428 +2714 2769 2429 +2714 2769 2429 +2715 2769 2430 +2717 2769 2431 +2718 2770 2433 +2719 2772 2443 +2718 2772 2447 +2715 2770 2444 +2712 2771 2455 +2714 2774 2492 +2716 2775 2523 +2714 2775 2560 +2719 2781 2625 +2725 2789 2703 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2713 2769 2427 +2713 2769 2427 +2713 2769 2427 +2713 2769 2428 +2714 2769 2428 +2714 2769 2428 +2714 2769 2428 +2714 2769 2428 +2714 2769 2429 +2714 2769 2429 +2715 2769 2430 +2717 2769 2431 +2718 2770 2433 +2719 2772 2443 +2718 2772 2447 +2715 2770 2444 +2712 2771 2455 +2714 2774 2492 +2716 2775 2523 +2714 2775 2560 +2719 2781 2625 +2725 2789 2703 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2713 2769 2427 +2713 2769 2427 +2713 2769 2427 +2713 2769 2428 +2714 2769 2428 +2714 2769 2428 +2714 2769 2428 +2714 2769 2428 +2714 2769 2429 +2714 2769 2429 +2715 2769 2430 +2717 2769 2431 +2718 2770 2433 +2719 2772 2443 +2718 2772 2447 +2715 2770 2444 +2712 2771 2455 +2714 2774 2492 +2716 2775 2523 +2714 2775 2560 +2719 2781 2625 +2725 2789 2703 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2713 2769 2427 +2713 2769 2427 +2713 2769 2427 +2713 2769 2428 +2714 2769 2428 +2714 2769 2428 +2714 2769 2428 +2714 2769 2428 +2714 2769 2429 +2714 2769 2429 +2715 2769 2430 +2717 2769 2431 +2718 2770 2433 +2719 2772 2443 +2718 2772 2447 +2715 2770 2444 +2712 2771 2455 +2714 2774 2492 +2716 2775 2523 +2714 2775 2560 +2719 2781 2625 +2725 2789 2703 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2713 2769 2427 +2713 2769 2427 +2713 2769 2427 +2713 2769 2428 +2714 2769 2428 +2714 2769 2428 +2714 2769 2428 +2714 2769 2428 +2714 2769 2429 +2714 2769 2429 +2715 2769 2430 +2717 2769 2431 +2718 2770 2433 +2719 2772 2443 +2718 2772 2447 +2715 2770 2444 +2712 2771 2455 +2714 2774 2492 +2716 2775 2523 +2714 2775 2560 +2719 2781 2625 +2725 2789 2703 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2713 2769 2427 +2713 2769 2427 +2713 2769 2427 +2713 2769 2428 +2714 2769 2428 +2714 2769 2428 +2714 2769 2428 +2714 2769 2428 +2714 2769 2429 +2714 2769 2429 +2715 2769 2430 +2717 2769 2431 +2718 2770 2433 +2719 2772 2443 +2718 2772 2447 +2715 2770 2444 +2712 2771 2455 +2714 2774 2492 +2716 2775 2523 +2714 2775 2560 +2719 2781 2625 +2725 2789 2703 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2713 2769 2427 +2713 2769 2427 +2713 2769 2427 +2713 2769 2428 +2714 2769 2428 +2714 2769 2428 +2714 2769 2428 +2714 2769 2428 +2714 2769 2429 +2714 2769 2429 +2715 2769 2430 +2717 2769 2431 +2718 2770 2433 +2719 2772 2443 +2718 2772 2447 +2715 2770 2444 +2712 2771 2455 +2714 2774 2492 +2716 2775 2523 +2714 2775 2560 +2719 2781 2625 +2725 2789 2703 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2713 2769 2427 +2713 2769 2427 +2713 2769 2427 +2713 2769 2428 +2714 2769 2428 +2714 2769 2428 +2714 2769 2428 +2714 2769 2428 +2714 2769 2429 +2714 2769 2429 +2715 2769 2430 +2717 2769 2431 +2718 2770 2433 +2719 2772 2443 +2718 2772 2447 +2715 2770 2444 +2712 2771 2455 +2714 2774 2492 +2716 2775 2523 +2714 2775 2560 +2719 2781 2625 +2725 2789 2703 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +2729 2791 2730 +1471 0 0 +1471 0 0 +1472 0 0 +1472 0 18 +1473 0 98 +1475 0 188 +1476 0 285 +1478 0 389 +1481 0 499 +1485 0 614 +1490 0 733 +1496 0 855 +1498 0 1011 +1486 0 1266 +1470 0 1472 +1490 0 1659 +1524 0 1789 +1589 0 1904 +1654 0 2053 +1531 645 2197 +923 1046 2356 +1710 0 2469 +1801 0 2506 +1801 0 2506 +1801 0 2506 +1801 0 2506 +1801 0 2506 +1801 0 2506 +1801 0 2506 +1801 0 2506 +1801 0 2506 +1801 0 2506 +1471 0 0 +1471 0 0 +1471 0 17 +1472 0 78 +1473 0 150 +1474 0 230 +1476 0 319 +1478 0 417 +1481 0 521 +1485 0 631 +1489 0 746 +1496 0 865 +1497 0 1017 +1486 0 1269 +1469 0 1474 +1489 0 1660 +1524 0 1790 +1589 0 1905 +1653 0 2053 +1531 656 2197 +924 1049 2356 +1710 0 2469 +1801 0 2506 +1801 0 2506 +1801 0 2506 +1801 0 2506 +1801 0 2506 +1801 0 2506 +1801 0 2506 +1801 0 2506 +1801 0 2506 +1801 0 2506 +1471 0 0 +1471 0 17 +1471 0 97 +1472 0 149 +1472 0 211 +1474 0 282 +1475 0 363 +1477 0 452 +1480 0 549 +1484 0 653 +1489 0 763 +1496 0 878 +1497 0 1026 +1485 0 1273 +1469 0 1476 +1489 0 1661 +1524 0 1791 +1588 0 1905 +1652 0 2054 +1530 671 2198 +926 1053 2357 +1711 0 2469 +1802 0 2506 +1802 0 2506 +1802 0 2506 +1802 0 2506 +1802 0 2506 +1802 0 2506 +1802 0 2506 +1802 0 2506 +1802 0 2506 +1802 0 2506 +1471 0 18 +1471 0 78 +1471 0 149 +1471 0 229 +1472 0 281 +1473 0 343 +1475 0 414 +1477 0 494 +1480 0 584 +1483 0 681 +1488 0 785 +1495 0 895 +1496 0 1039 +1485 0 1278 +1468 0 1480 +1488 0 1662 +1524 0 1793 +1587 0 1907 +1651 0 2054 +1529 690 2198 +928 1058 2357 +1712 0 2469 +1803 0 2506 +1803 0 2506 +1803 0 2506 +1803 0 2506 +1803 0 2506 +1803 0 2506 +1803 0 2506 +1803 0 2506 +1803 0 2506 +1803 0 2506 +1471 0 98 +1471 0 150 +1471 0 211 +1471 0 281 +1471 0 361 +1472 0 413 +1474 0 475 +1476 0 546 +1479 0 627 +1482 0 716 +1487 0 813 +1494 0 917 +1495 0 1055 +1484 0 1285 +1467 0 1484 +1487 0 1664 +1524 0 1795 +1585 0 1908 +1650 0 2055 +1527 714 2199 +931 1065 2357 +1713 0 2469 +1804 0 2506 +1804 0 2506 +1804 0 2506 +1804 0 2506 +1804 0 2506 +1804 0 2506 +1804 0 2506 +1804 0 2506 +1804 0 2506 +1804 0 2506 +1471 0 188 +1471 0 230 +1471 0 282 +1471 0 343 +1471 0 413 +1471 0 493 +1472 0 545 +1475 0 607 +1478 0 678 +1481 0 759 +1486 0 848 +1493 0 946 +1494 0 1075 +1482 0 1294 +1466 0 1490 +1486 0 1667 +1524 30 1798 +1584 0 1911 +1648 132 2057 +1525 745 2200 +935 1074 2358 +1715 0 2469 +1806 0 2506 +1806 0 2506 +1806 0 2506 +1806 0 2506 +1806 0 2506 +1806 0 2506 +1806 0 2506 +1806 0 2506 +1806 0 2506 +1806 0 2506 +1471 121 285 +1471 106 319 +1471 85 363 +1471 56 414 +1471 13 475 +1471 0 545 +1471 0 625 +1473 0 677 +1476 0 739 +1480 0 810 +1485 0 891 +1491 0 980 +1493 0 1102 +1481 0 1306 +1464 0 1497 +1485 0 1670 +1524 163 1802 +1581 32 1914 +1646 264 2058 +1522 783 2201 +940 1085 2358 +1716 32 2469 +1809 0 2506 +1809 0 2506 +1809 0 2506 +1809 0 2506 +1809 0 2506 +1809 0 2506 +1809 0 2506 +1809 0 2506 +1809 0 2506 +1809 0 2506 +1471 264 389 +1471 253 417 +1471 238 452 +1471 217 494 +1471 188 546 +1471 146 607 +1471 82 677 +1471 0 757 +1474 0 809 +1478 0 871 +1483 0 942 +1489 0 1023 +1491 0 1135 +1479 0 1321 +1462 0 1507 +1482 0 1674 +1524 295 1807 +1578 164 1918 +1644 396 2061 +1518 830 2203 +947 1100 2359 +1719 164 2469 +1812 0 2506 +1812 0 2506 +1812 0 2506 +1812 0 2506 +1812 0 2506 +1812 0 2506 +1812 0 2506 +1812 0 2506 +1812 0 2506 +1812 0 2506 +1471 404 499 +1471 396 521 +1471 385 549 +1471 370 584 +1471 349 627 +1471 320 678 +1471 277 739 +1471 214 809 +1471 111 889 +1475 111 942 +1480 111 1003 +1486 111 1075 +1488 111 1176 +1476 111 1340 +1459 111 1520 +1480 111 1680 +1524 426 1814 +1573 296 1923 +1640 528 2064 +1513 885 2205 +956 1119 2361 +1717 296 2469 +1816 111 2506 +1816 111 2506 +1816 111 2506 +1816 111 2506 +1816 111 2506 +1816 111 2506 +1816 111 2506 +1816 111 2506 +1816 111 2506 +1816 111 2506 +1471 542 614 +1471 536 631 +1471 528 653 +1471 517 681 +1471 502 716 +1471 482 759 +1471 452 810 +1471 410 871 +1471 346 942 +1471 244 1021 +1476 244 1074 +1483 244 1135 +1484 244 1225 +1472 244 1369 +1455 244 1537 +1476 244 1687 +1520 502 1820 +1567 428 1930 +1634 660 2068 +1506 950 2208 +968 1143 2362 +1715 428 2469 +1821 244 2506 +1821 244 2506 +1821 244 2506 +1821 244 2506 +1821 244 2506 +1821 244 2506 +1821 244 2506 +1821 244 2506 +1821 244 2506 +1821 244 2506 +1471 678 733 +1471 674 746 +1471 668 763 +1471 660 785 +1471 649 813 +1471 634 848 +1471 613 891 +1471 584 942 +1471 542 1003 +1471 478 1074 +1471 376 1153 +1478 376 1206 +1479 376 1283 +1467 376 1412 +1450 376 1559 +1471 376 1701 +1516 581 1827 +1566 591 1940 +1627 792 2074 +1496 1025 2212 +983 1174 2364 +1712 560 2468 +1828 376 2506 +1828 376 2506 +1828 376 2506 +1828 376 2506 +1828 376 2506 +1828 376 2506 +1828 376 2506 +1828 376 2506 +1828 376 2506 +1828 376 2506 +1471 814 855 +1471 811 865 +1471 806 878 +1471 800 895 +1471 792 917 +1471 782 946 +1471 767 980 +1471 746 1023 +1471 717 1075 +1471 674 1135 +1471 611 1206 +1471 508 1285 +1472 508 1352 +1460 508 1465 +1443 508 1587 +1464 508 1721 +1509 670 1836 +1566 751 1952 +1617 925 2081 +1483 1109 2218 +935 1212 2368 +1708 692 2467 +1838 508 2506 +1838 508 2506 +1838 508 2506 +1838 508 2506 +1838 508 2506 +1838 508 2506 +1838 508 2506 +1838 508 2506 +1838 508 2506 +1838 508 2506 +1467 954 955 +1467 954 960 +1467 951 971 +1467 947 985 +1467 941 1004 +1467 933 1027 +1467 923 1056 +1467 908 1092 +1467 888 1137 +1467 859 1191 +1467 818 1254 +1467 755 1326 +1471 701 1400 +1458 701 1503 +1441 701 1611 +1446 742 1738 +1508 833 1851 +1542 872 1959 +1602 1037 2091 +1448 1185 2224 +886 1254 2372 +1718 855 2468 +1839 727 2507 +1839 727 2507 +1839 727 2507 +1839 727 2507 +1839 727 2507 +1839 727 2507 +1839 727 2507 +1839 727 2507 +1839 727 2507 +1839 727 2507 +1503 1167 1293 +1503 1167 1296 +1504 1167 1299 +1504 1167 1304 +1505 1167 1311 +1506 1167 1319 +1508 1167 1330 +1510 1167 1344 +1512 1167 1363 +1514 1162 1390 +1514 1141 1432 +1514 1111 1482 +1517 1087 1536 +1506 1087 1597 +1491 1087 1687 +1446 1077 1783 +1489 1144 1900 +1509 1144 1988 +1532 1221 2116 +1329 1289 2240 +1151 1275 2372 +1721 1061 2469 +1839 1003 2508 +1839 1003 2508 +1839 1003 2508 +1839 1003 2508 +1839 1003 2508 +1839 1003 2508 +1839 1003 2508 +1839 1003 2508 +1839 1003 2508 +1839 1003 2508 +1547 1351 1534 +1547 1351 1536 +1547 1351 1538 +1548 1351 1541 +1549 1351 1545 +1550 1351 1550 +1551 1351 1556 +1553 1351 1565 +1555 1351 1577 +1558 1351 1592 +1563 1351 1611 +1569 1351 1636 +1573 1345 1671 +1563 1345 1717 +1550 1345 1771 +1498 1335 1850 +1489 1358 1942 +1476 1376 2036 +1418 1388 2147 +1096 1399 2261 +1290 1332 2375 +1730 1258 2473 +1839 1219 2510 +1839 1219 2510 +1839 1219 2510 +1839 1219 2510 +1839 1219 2510 +1839 1219 2510 +1839 1219 2510 +1839 1219 2510 +1839 1219 2510 +1839 1219 2510 +1626 1522 1733 +1625 1522 1734 +1625 1522 1734 +1623 1522 1735 +1622 1522 1736 +1621 1522 1737 +1618 1522 1739 +1615 1522 1742 +1611 1522 1745 +1605 1522 1749 +1605 1522 1760 +1609 1522 1778 +1596 1523 1805 +1587 1534 1850 +1574 1537 1894 +1558 1522 1941 +1509 1521 2012 +1413 1563 2107 +1330 1535 2187 +1296 1523 2285 +1459 1491 2382 +1767 1446 2474 +1910 1416 2509 +1910 1416 2509 +1910 1416 2509 +1910 1416 2509 +1910 1416 2509 +1910 1416 2509 +1910 1416 2509 +1910 1416 2509 +1910 1416 2509 +1910 1416 2509 +1737 1669 1898 +1737 1669 1899 +1737 1669 1900 +1737 1669 1901 +1737 1669 1903 +1737 1669 1905 +1737 1669 1908 +1737 1669 1913 +1737 1669 1918 +1732 1669 1922 +1727 1669 1925 +1719 1669 1930 +1711 1672 1940 +1697 1674 1960 +1687 1684 2003 +1675 1681 2036 +1638 1672 2080 +1565 1674 2153 +1492 1672 2229 +1526 1649 2305 +1680 1621 2385 +1871 1607 2473 +1954 1605 2509 +1954 1605 2509 +1954 1605 2509 +1954 1605 2509 +1954 1605 2509 +1954 1605 2509 +1954 1605 2509 +1954 1605 2509 +1954 1605 2509 +1954 1605 2509 +1862 1802 1972 +1862 1802 1973 +1862 1802 1973 +1862 1803 1975 +1862 1803 1976 +1863 1804 1978 +1864 1805 1981 +1865 1806 1984 +1866 1807 1989 +1868 1809 1995 +1868 1809 2004 +1868 1809 2014 +1861 1811 2027 +1856 1811 2038 +1842 1811 2056 +1824 1809 2088 +1829 1804 2122 +1805 1804 2175 +1793 1801 2242 +1782 1800 2309 +1820 1797 2390 +1940 1796 2477 +2014 1783 2512 +2014 1783 2512 +2014 1783 2512 +2014 1783 2512 +2014 1783 2512 +2014 1783 2512 +2014 1783 2512 +2014 1783 2512 +2014 1783 2512 +2014 1783 2512 +1992 1958 2037 +1992 1958 2037 +1992 1958 2037 +1992 1958 2037 +1992 1958 2037 +1992 1958 2038 +1992 1958 2038 +1992 1958 2039 +1992 1958 2040 +1992 1958 2041 +1992 1958 2042 +1992 1958 2044 +1989 1958 2051 +1984 1962 2068 +1979 1968 2090 +1970 1962 2115 +1966 1962 2148 +1966 1964 2190 +1964 1947 2231 +1943 1947 2310 +1978 1965 2395 +2061 1971 2481 +2133 1968 2516 +2133 1968 2516 +2133 1968 2516 +2133 1968 2516 +2133 1968 2516 +2133 1968 2516 +2133 1968 2516 +2133 1968 2516 +2133 1968 2516 +2133 1968 2516 +2142 2127 2061 +2142 2127 2061 +2142 2127 2062 +2142 2127 2063 +2142 2127 2064 +2143 2127 2065 +2143 2127 2067 +2143 2127 2069 +2144 2127 2072 +2145 2127 2076 +2146 2127 2082 +2148 2127 2089 +2148 2127 2095 +2143 2127 2104 +2135 2127 2116 +2137 2127 2132 +2144 2131 2161 +2141 2135 2204 +2133 2127 2256 +2149 2134 2316 +2174 2130 2395 +2237 2146 2485 +2277 2159 2520 +2277 2159 2520 +2277 2159 2520 +2277 2159 2520 +2277 2159 2520 +2277 2159 2520 +2277 2159 2520 +2277 2159 2520 +2277 2159 2520 +2277 2159 2520 +2379 2355 2126 +2380 2355 2127 +2380 2355 2127 +2380 2355 2127 +2380 2355 2127 +2380 2355 2127 +2380 2355 2128 +2381 2355 2128 +2381 2355 2129 +2381 2355 2130 +2382 2355 2131 +2382 2355 2133 +2382 2355 2135 +2381 2357 2141 +2379 2358 2148 +2379 2355 2161 +2378 2357 2192 +2376 2358 2230 +2382 2354 2270 +2402 2364 2335 +2420 2368 2405 +2473 2383 2495 +2499 2394 2533 +2499 2394 2533 +2499 2394 2533 +2499 2394 2533 +2499 2394 2533 +2499 2394 2533 +2499 2394 2533 +2499 2394 2533 +2499 2394 2533 +2499 2394 2533 +2681 2657 1947 +2681 2657 1947 +2681 2657 1947 +2681 2657 1947 +2681 2657 1947 +2681 2657 1947 +2681 2657 1947 +2681 2657 1947 +2681 2656 1951 +2680 2656 1956 +2680 2656 1963 +2679 2655 1973 +2679 2654 1971 +2678 2651 1967 +2678 2651 1962 +2678 2655 2011 +2679 2657 2064 +2682 2657 2129 +2684 2657 2213 +2688 2661 2311 +2699 2668 2415 +2717 2681 2528 +2726 2683 2577 +2726 2683 2577 +2726 2683 2577 +2726 2683 2577 +2726 2683 2577 +2726 2683 2577 +2726 2683 2577 +2726 2683 2577 +2726 2683 2577 +2726 2683 2577 +2715 2769 2427 +2716 2769 2427 +2716 2769 2427 +2716 2769 2428 +2716 2769 2428 +2716 2769 2428 +2716 2769 2428 +2716 2769 2428 +2716 2769 2429 +2716 2769 2429 +2717 2769 2430 +2717 2769 2431 +2718 2770 2433 +2719 2772 2443 +2720 2775 2457 +2716 2772 2452 +2713 2770 2455 +2714 2773 2485 +2718 2774 2523 +2717 2777 2567 +2721 2782 2627 +2725 2788 2702 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2715 2769 2427 +2716 2769 2427 +2716 2769 2427 +2716 2769 2428 +2716 2769 2428 +2716 2769 2428 +2716 2769 2428 +2716 2769 2428 +2716 2769 2429 +2716 2769 2429 +2717 2769 2430 +2717 2769 2431 +2718 2770 2433 +2719 2772 2443 +2720 2775 2457 +2716 2772 2452 +2713 2770 2455 +2714 2773 2485 +2718 2774 2523 +2717 2777 2567 +2721 2782 2627 +2725 2788 2702 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2715 2769 2427 +2716 2769 2427 +2716 2769 2427 +2716 2769 2428 +2716 2769 2428 +2716 2769 2428 +2716 2769 2428 +2716 2769 2428 +2716 2769 2429 +2716 2769 2429 +2717 2769 2430 +2717 2769 2431 +2718 2770 2433 +2719 2772 2443 +2720 2775 2457 +2716 2772 2452 +2713 2770 2455 +2714 2773 2485 +2718 2774 2523 +2717 2777 2567 +2721 2782 2627 +2725 2788 2702 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2715 2769 2427 +2716 2769 2427 +2716 2769 2427 +2716 2769 2428 +2716 2769 2428 +2716 2769 2428 +2716 2769 2428 +2716 2769 2428 +2716 2769 2429 +2716 2769 2429 +2717 2769 2430 +2717 2769 2431 +2718 2770 2433 +2719 2772 2443 +2720 2775 2457 +2716 2772 2452 +2713 2770 2455 +2714 2773 2485 +2718 2774 2523 +2717 2777 2567 +2721 2782 2627 +2725 2788 2702 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2715 2769 2427 +2716 2769 2427 +2716 2769 2427 +2716 2769 2428 +2716 2769 2428 +2716 2769 2428 +2716 2769 2428 +2716 2769 2428 +2716 2769 2429 +2716 2769 2429 +2717 2769 2430 +2717 2769 2431 +2718 2770 2433 +2719 2772 2443 +2720 2775 2457 +2716 2772 2452 +2713 2770 2455 +2714 2773 2485 +2718 2774 2523 +2717 2777 2567 +2721 2782 2627 +2725 2788 2702 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2715 2769 2427 +2716 2769 2427 +2716 2769 2427 +2716 2769 2428 +2716 2769 2428 +2716 2769 2428 +2716 2769 2428 +2716 2769 2428 +2716 2769 2429 +2716 2769 2429 +2717 2769 2430 +2717 2769 2431 +2718 2770 2433 +2719 2772 2443 +2720 2775 2457 +2716 2772 2452 +2713 2770 2455 +2714 2773 2485 +2718 2774 2523 +2717 2777 2567 +2721 2782 2627 +2725 2788 2702 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2715 2769 2427 +2716 2769 2427 +2716 2769 2427 +2716 2769 2428 +2716 2769 2428 +2716 2769 2428 +2716 2769 2428 +2716 2769 2428 +2716 2769 2429 +2716 2769 2429 +2717 2769 2430 +2717 2769 2431 +2718 2770 2433 +2719 2772 2443 +2720 2775 2457 +2716 2772 2452 +2713 2770 2455 +2714 2773 2485 +2718 2774 2523 +2717 2777 2567 +2721 2782 2627 +2725 2788 2702 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2715 2769 2427 +2716 2769 2427 +2716 2769 2427 +2716 2769 2428 +2716 2769 2428 +2716 2769 2428 +2716 2769 2428 +2716 2769 2428 +2716 2769 2429 +2716 2769 2429 +2717 2769 2430 +2717 2769 2431 +2718 2770 2433 +2719 2772 2443 +2720 2775 2457 +2716 2772 2452 +2713 2770 2455 +2714 2773 2485 +2718 2774 2523 +2717 2777 2567 +2721 2782 2627 +2725 2788 2702 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2715 2769 2427 +2716 2769 2427 +2716 2769 2427 +2716 2769 2428 +2716 2769 2428 +2716 2769 2428 +2716 2769 2428 +2716 2769 2428 +2716 2769 2429 +2716 2769 2429 +2717 2769 2430 +2717 2769 2431 +2718 2770 2433 +2719 2772 2443 +2720 2775 2457 +2716 2772 2452 +2713 2770 2455 +2714 2773 2485 +2718 2774 2523 +2717 2777 2567 +2721 2782 2627 +2725 2788 2702 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2715 2769 2427 +2716 2769 2427 +2716 2769 2427 +2716 2769 2428 +2716 2769 2428 +2716 2769 2428 +2716 2769 2428 +2716 2769 2428 +2716 2769 2429 +2716 2769 2429 +2717 2769 2430 +2717 2769 2431 +2718 2770 2433 +2719 2772 2443 +2720 2775 2457 +2716 2772 2452 +2713 2770 2455 +2714 2773 2485 +2718 2774 2523 +2717 2777 2567 +2721 2782 2627 +2725 2788 2702 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +2729 2794 2733 +1677 0 708 +1676 0 722 +1676 0 740 +1675 0 763 +1674 0 792 +1672 0 829 +1670 0 873 +1667 0 927 +1663 0 989 +1658 0 1062 +1657 0 1123 +1662 0 1179 +1666 0 1250 +1649 0 1372 +1636 0 1533 +1634 0 1672 +1671 0 1828 +1667 0 1929 +1689 355 2079 +1608 810 2211 +1232 994 2359 +1771 0 2470 +1854 0 2508 +1854 0 2508 +1854 0 2508 +1854 0 2508 +1854 0 2508 +1854 0 2508 +1854 0 2508 +1854 0 2508 +1854 0 2508 +1854 0 2508 +1676 0 726 +1676 0 735 +1675 0 753 +1674 0 775 +1673 0 804 +1672 0 839 +1669 0 883 +1667 0 935 +1663 0 997 +1658 0 1068 +1657 0 1129 +1662 0 1184 +1666 0 1253 +1649 0 1375 +1636 0 1535 +1635 0 1673 +1670 0 1829 +1666 0 1930 +1689 372 2079 +1607 814 2211 +1238 995 2359 +1771 0 2470 +1855 0 2508 +1855 0 2508 +1855 0 2508 +1855 0 2508 +1855 0 2508 +1855 0 2508 +1855 0 2508 +1855 0 2508 +1855 0 2508 +1855 0 2508 +1676 0 749 +1675 0 758 +1675 0 770 +1674 0 791 +1673 0 819 +1672 0 853 +1669 0 895 +1666 0 946 +1663 0 1007 +1657 0 1077 +1657 0 1136 +1661 0 1191 +1665 0 1259 +1649 0 1378 +1636 0 1537 +1635 0 1674 +1669 0 1829 +1665 0 1930 +1688 394 2080 +1606 821 2211 +1245 996 2359 +1771 0 2470 +1855 0 2508 +1855 0 2508 +1855 0 2508 +1855 0 2508 +1855 0 2508 +1855 0 2508 +1855 0 2508 +1855 0 2508 +1855 0 2508 +1855 0 2508 +1675 0 777 +1674 0 786 +1674 0 797 +1674 0 812 +1673 0 838 +1671 0 871 +1669 0 912 +1666 0 961 +1662 0 1020 +1657 0 1088 +1656 0 1146 +1661 0 1199 +1665 0 1266 +1649 0 1383 +1636 0 1541 +1636 0 1676 +1668 0 1830 +1663 0 1932 +1687 422 2080 +1605 829 2212 +1255 998 2359 +1772 0 2470 +1855 0 2508 +1855 0 2508 +1855 0 2508 +1855 0 2508 +1855 0 2508 +1855 0 2508 +1855 0 2508 +1855 0 2508 +1855 0 2508 +1855 0 2508 +1674 0 814 +1673 0 822 +1673 0 832 +1673 0 845 +1672 0 863 +1671 0 894 +1668 0 933 +1666 0 980 +1662 0 1036 +1656 0 1102 +1655 0 1159 +1660 0 1210 +1664 0 1276 +1649 0 1390 +1636 0 1545 +1637 0 1679 +1667 0 1831 +1662 0 1934 +1686 457 2081 +1603 840 2212 +1268 1001 2360 +1772 0 2470 +1856 0 2508 +1856 0 2508 +1856 0 2508 +1856 0 2508 +1856 0 2508 +1856 0 2508 +1856 0 2508 +1856 0 2508 +1856 0 2508 +1856 0 2508 +1672 0 858 +1672 0 865 +1672 0 874 +1671 0 887 +1671 0 903 +1670 0 923 +1667 0 960 +1664 0 1004 +1661 0 1058 +1655 0 1121 +1655 0 1175 +1659 0 1225 +1663 0 1289 +1649 0 1398 +1636 0 1551 +1639 0 1683 +1666 0 1832 +1659 132 1936 +1684 500 2083 +1600 854 2213 +1285 1004 2360 +1773 0 2470 +1857 0 2508 +1857 0 2508 +1857 0 2508 +1857 0 2508 +1857 0 2508 +1857 0 2508 +1857 0 2508 +1857 0 2508 +1857 0 2508 +1857 0 2508 +1670 32 911 +1669 32 917 +1669 32 926 +1669 32 937 +1668 32 951 +1667 32 970 +1667 32 993 +1663 32 1035 +1660 32 1085 +1654 32 1144 +1654 32 1196 +1658 32 1244 +1662 0 1305 +1649 0 1410 +1636 0 1560 +1641 32 1688 +1663 32 1833 +1656 264 1939 +1682 551 2084 +1596 873 2214 +1306 1009 2361 +1773 0 2470 +1859 32 2508 +1859 32 2508 +1859 32 2508 +1859 32 2508 +1859 32 2508 +1859 32 2508 +1859 32 2508 +1859 32 2508 +1859 32 2508 +1859 32 2508 +1667 164 973 +1667 164 979 +1666 164 986 +1666 164 996 +1666 164 1009 +1664 164 1025 +1663 164 1046 +1662 164 1073 +1658 164 1119 +1653 164 1174 +1652 164 1223 +1657 164 1268 +1661 137 1326 +1649 0 1424 +1636 0 1570 +1644 164 1695 +1661 164 1835 +1652 396 1943 +1680 612 2086 +1591 896 2215 +1333 1014 2362 +1774 0 2470 +1861 164 2508 +1861 164 2508 +1861 164 2508 +1861 164 2508 +1861 164 2508 +1861 164 2508 +1861 164 2508 +1861 164 2508 +1861 164 2508 +1861 164 2508 +1663 296 1045 +1663 296 1050 +1663 296 1056 +1662 296 1065 +1662 296 1075 +1661 296 1090 +1660 296 1108 +1658 296 1131 +1656 296 1161 +1651 296 1212 +1650 296 1257 +1655 296 1299 +1659 276 1353 +1649 111 1443 +1636 111 1584 +1648 296 1704 +1657 296 1838 +1646 528 1948 +1676 683 2089 +1585 926 2217 +1367 1022 2363 +1772 0 2470 +1863 296 2508 +1863 296 2508 +1863 296 2508 +1863 296 2508 +1863 296 2508 +1863 296 2508 +1863 296 2508 +1863 296 2508 +1863 296 2508 +1863 296 2508 +1658 428 1127 +1658 428 1131 +1657 428 1136 +1657 428 1143 +1656 428 1152 +1655 428 1164 +1654 428 1180 +1653 428 1200 +1651 428 1225 +1648 428 1257 +1648 428 1298 +1653 428 1336 +1657 413 1387 +1648 265 1468 +1636 244 1601 +1653 428 1715 +1661 428 1846 +1638 660 1955 +1671 762 2093 +1576 963 2219 +1408 1032 2365 +1768 91 2470 +1866 428 2508 +1866 428 2508 +1866 428 2508 +1866 428 2508 +1866 428 2508 +1866 428 2508 +1866 428 2508 +1866 428 2508 +1866 428 2508 +1866 428 2508 +1655 583 1188 +1655 583 1191 +1654 583 1196 +1654 583 1202 +1654 583 1210 +1653 583 1221 +1651 583 1234 +1650 583 1252 +1648 583 1275 +1646 583 1304 +1644 536 1348 +1649 536 1383 +1653 524 1429 +1645 413 1503 +1633 376 1622 +1654 536 1730 +1662 536 1854 +1635 766 1962 +1664 863 2099 +1566 1025 2222 +1432 1062 2367 +1764 309 2470 +1872 536 2508 +1872 536 2508 +1872 536 2508 +1872 536 2508 +1872 536 2508 +1872 536 2508 +1872 536 2508 +1872 536 2508 +1872 536 2508 +1872 536 2508 +1655 745 1237 +1655 745 1240 +1654 745 1244 +1654 745 1249 +1654 745 1257 +1653 745 1266 +1651 745 1279 +1650 745 1295 +1648 745 1315 +1646 745 1342 +1644 713 1383 +1644 633 1439 +1648 624 1479 +1640 536 1547 +1628 508 1646 +1649 633 1749 +1657 633 1863 +1635 881 1973 +1655 979 2105 +1554 1109 2228 +1415 1110 2370 +1760 519 2469 +1880 633 2508 +1880 633 2508 +1880 633 2508 +1880 633 2508 +1880 633 2508 +1880 633 2508 +1880 633 2508 +1880 633 2508 +1880 633 2508 +1880 633 2508 +1655 918 1304 +1656 918 1306 +1655 918 1310 +1655 918 1314 +1654 918 1320 +1654 918 1329 +1653 918 1340 +1651 918 1354 +1649 918 1372 +1647 918 1395 +1645 897 1432 +1645 845 1482 +1643 779 1541 +1635 719 1601 +1623 701 1686 +1641 772 1775 +1650 779 1877 +1631 1007 1989 +1643 1092 2115 +1533 1205 2236 +1384 1170 2375 +1758 725 2468 +1889 758 2508 +1889 758 2508 +1889 758 2508 +1889 758 2508 +1889 758 2508 +1889 758 2508 +1889 758 2508 +1889 758 2508 +1889 758 2508 +1889 758 2508 +1647 1170 1441 +1648 1170 1443 +1648 1170 1445 +1648 1170 1448 +1649 1170 1452 +1650 1170 1457 +1651 1170 1463 +1653 1170 1472 +1654 1170 1484 +1655 1170 1500 +1654 1157 1529 +1654 1129 1570 +1651 1095 1619 +1635 1095 1678 +1623 1087 1751 +1615 1062 1817 +1632 1090 1907 +1595 1178 2016 +1626 1217 2123 +1463 1323 2255 +1427 1258 2375 +1780 1002 2468 +1884 986 2506 +1884 986 2506 +1884 986 2506 +1884 986 2506 +1884 986 2506 +1884 986 2506 +1884 986 2506 +1884 986 2506 +1884 986 2506 +1884 986 2506 +1671 1358 1617 +1671 1358 1618 +1672 1358 1619 +1672 1358 1621 +1672 1358 1624 +1673 1358 1628 +1674 1358 1632 +1676 1358 1638 +1678 1358 1646 +1680 1358 1657 +1683 1358 1672 +1687 1358 1694 +1687 1345 1729 +1672 1345 1775 +1659 1345 1825 +1644 1322 1879 +1625 1320 1950 +1565 1390 2060 +1550 1377 2150 +1313 1430 2275 +1491 1332 2378 +1794 1220 2471 +1883 1202 2507 +1883 1202 2507 +1883 1202 2507 +1883 1202 2507 +1883 1202 2507 +1883 1202 2507 +1883 1202 2507 +1883 1202 2507 +1883 1202 2507 +1883 1202 2507 +1720 1522 1779 +1720 1522 1780 +1719 1522 1781 +1718 1522 1782 +1717 1522 1783 +1716 1522 1785 +1714 1522 1787 +1712 1522 1790 +1708 1522 1795 +1704 1522 1800 +1703 1522 1811 +1707 1522 1827 +1711 1522 1847 +1703 1522 1873 +1693 1522 1912 +1668 1522 1965 +1628 1506 2021 +1607 1566 2121 +1540 1536 2191 +1494 1506 2283 +1572 1474 2382 +1813 1446 2473 +1923 1435 2511 +1923 1435 2511 +1923 1435 2511 +1923 1435 2511 +1923 1435 2511 +1923 1435 2511 +1923 1435 2511 +1923 1435 2511 +1923 1435 2511 +1923 1435 2511 +1810 1655 1910 +1809 1655 1911 +1809 1655 1911 +1808 1655 1912 +1807 1656 1913 +1806 1657 1915 +1805 1658 1918 +1802 1659 1921 +1800 1661 1925 +1796 1662 1930 +1791 1662 1934 +1784 1662 1939 +1776 1662 1948 +1775 1662 1972 +1766 1670 2011 +1745 1681 2051 +1732 1662 2087 +1680 1676 2155 +1604 1655 2226 +1644 1643 2305 +1738 1626 2385 +1900 1611 2473 +1984 1617 2510 +1984 1617 2510 +1984 1617 2510 +1984 1617 2510 +1984 1617 2510 +1984 1617 2510 +1984 1617 2510 +1984 1617 2510 +1984 1617 2510 +1984 1617 2510 +1907 1800 1983 +1907 1800 1984 +1907 1800 1984 +1907 1800 1985 +1907 1800 1986 +1907 1800 1987 +1907 1800 1989 +1907 1800 1991 +1907 1800 1994 +1907 1800 1997 +1906 1801 2005 +1906 1801 2015 +1905 1801 2029 +1901 1801 2043 +1890 1801 2062 +1872 1801 2086 +1874 1807 2128 +1850 1801 2174 +1847 1800 2243 +1818 1792 2312 +1871 1797 2387 +1976 1799 2480 +2034 1783 2511 +2034 1783 2511 +2034 1783 2511 +2034 1783 2511 +2034 1783 2511 +2034 1783 2511 +2034 1783 2511 +2034 1783 2511 +2034 1783 2511 +2034 1783 2511 +2034 1958 2033 +2033 1958 2033 +2033 1958 2034 +2032 1958 2034 +2031 1959 2036 +2031 1959 2037 +2029 1960 2039 +2027 1961 2041 +2025 1961 2044 +2021 1963 2049 +2020 1963 2052 +2020 1963 2054 +2020 1963 2059 +2020 1959 2069 +2016 1962 2088 +2004 1969 2111 +1998 1964 2152 +1993 1963 2193 +1987 1952 2238 +1975 1952 2313 +2009 1966 2398 +2073 1966 2481 +2135 1969 2517 +2135 1969 2517 +2135 1969 2517 +2135 1969 2517 +2135 1969 2517 +2135 1969 2517 +2135 1969 2517 +2135 1969 2517 +2135 1969 2517 +2135 1969 2517 +2163 2131 2063 +2163 2131 2063 +2163 2131 2064 +2163 2131 2065 +2163 2131 2065 +2163 2131 2066 +2163 2131 2068 +2163 2131 2069 +2163 2131 2072 +2163 2131 2075 +2164 2131 2080 +2165 2131 2087 +2166 2131 2096 +2164 2131 2105 +2157 2131 2117 +2148 2127 2128 +2154 2127 2154 +2155 2131 2206 +2143 2127 2260 +2159 2135 2315 +2188 2134 2395 +2251 2149 2486 +2283 2159 2520 +2283 2159 2520 +2283 2159 2520 +2283 2159 2520 +2283 2159 2520 +2283 2159 2520 +2283 2159 2520 +2283 2159 2520 +2283 2159 2520 +2283 2159 2520 +2386 2355 2123 +2386 2355 2123 +2386 2356 2123 +2387 2356 2123 +2387 2356 2124 +2387 2356 2124 +2387 2356 2125 +2387 2357 2126 +2388 2357 2127 +2388 2357 2129 +2389 2358 2131 +2389 2358 2133 +2389 2357 2135 +2386 2356 2141 +2384 2356 2148 +2382 2356 2170 +2388 2357 2191 +2386 2356 2226 +2394 2358 2272 +2409 2366 2337 +2431 2373 2403 +2476 2384 2495 +2508 2398 2531 +2508 2398 2531 +2508 2398 2531 +2508 2398 2531 +2508 2398 2531 +2508 2398 2531 +2508 2398 2531 +2508 2398 2531 +2508 2398 2531 +2508 2398 2531 +2684 2656 1957 +2684 2656 1957 +2684 2656 1956 +2684 2656 1956 +2684 2656 1956 +2684 2656 1956 +2684 2656 1955 +2684 2656 1954 +2684 2656 1955 +2684 2656 1956 +2684 2656 1961 +2683 2656 1971 +2683 2655 1982 +2682 2655 1994 +2682 2655 1993 +2681 2656 2011 +2682 2656 2069 +2683 2657 2133 +2686 2657 2216 +2691 2663 2315 +2700 2669 2417 +2719 2681 2533 +2726 2683 2576 +2726 2683 2576 +2726 2683 2576 +2726 2683 2576 +2726 2683 2576 +2726 2683 2576 +2726 2683 2576 +2726 2683 2576 +2726 2683 2576 +2726 2683 2576 +2718 2771 2437 +2718 2771 2437 +2718 2771 2437 +2718 2771 2436 +2718 2771 2436 +2718 2771 2435 +2718 2771 2435 +2717 2770 2434 +2717 2770 2432 +2717 2770 2430 +2717 2769 2430 +2718 2769 2431 +2718 2770 2433 +2719 2771 2443 +2720 2774 2457 +2721 2773 2466 +2716 2771 2466 +2717 2774 2492 +2718 2776 2528 +2718 2777 2569 +2722 2782 2624 +2727 2788 2703 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2718 2771 2437 +2718 2771 2437 +2718 2771 2437 +2718 2771 2436 +2718 2771 2436 +2718 2771 2435 +2718 2771 2435 +2717 2770 2434 +2717 2770 2432 +2717 2770 2430 +2717 2769 2430 +2718 2769 2431 +2718 2770 2433 +2719 2771 2443 +2720 2774 2457 +2721 2773 2466 +2716 2771 2466 +2717 2774 2492 +2718 2776 2528 +2718 2777 2569 +2722 2782 2624 +2727 2788 2703 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2718 2771 2437 +2718 2771 2437 +2718 2771 2437 +2718 2771 2436 +2718 2771 2436 +2718 2771 2435 +2718 2771 2435 +2717 2770 2434 +2717 2770 2432 +2717 2770 2430 +2717 2769 2430 +2718 2769 2431 +2718 2770 2433 +2719 2771 2443 +2720 2774 2457 +2721 2773 2466 +2716 2771 2466 +2717 2774 2492 +2718 2776 2528 +2718 2777 2569 +2722 2782 2624 +2727 2788 2703 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2718 2771 2437 +2718 2771 2437 +2718 2771 2437 +2718 2771 2436 +2718 2771 2436 +2718 2771 2435 +2718 2771 2435 +2717 2770 2434 +2717 2770 2432 +2717 2770 2430 +2717 2769 2430 +2718 2769 2431 +2718 2770 2433 +2719 2771 2443 +2720 2774 2457 +2721 2773 2466 +2716 2771 2466 +2717 2774 2492 +2718 2776 2528 +2718 2777 2569 +2722 2782 2624 +2727 2788 2703 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2718 2771 2437 +2718 2771 2437 +2718 2771 2437 +2718 2771 2436 +2718 2771 2436 +2718 2771 2435 +2718 2771 2435 +2717 2770 2434 +2717 2770 2432 +2717 2770 2430 +2717 2769 2430 +2718 2769 2431 +2718 2770 2433 +2719 2771 2443 +2720 2774 2457 +2721 2773 2466 +2716 2771 2466 +2717 2774 2492 +2718 2776 2528 +2718 2777 2569 +2722 2782 2624 +2727 2788 2703 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2718 2771 2437 +2718 2771 2437 +2718 2771 2437 +2718 2771 2436 +2718 2771 2436 +2718 2771 2435 +2718 2771 2435 +2717 2770 2434 +2717 2770 2432 +2717 2770 2430 +2717 2769 2430 +2718 2769 2431 +2718 2770 2433 +2719 2771 2443 +2720 2774 2457 +2721 2773 2466 +2716 2771 2466 +2717 2774 2492 +2718 2776 2528 +2718 2777 2569 +2722 2782 2624 +2727 2788 2703 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2718 2771 2437 +2718 2771 2437 +2718 2771 2437 +2718 2771 2436 +2718 2771 2436 +2718 2771 2435 +2718 2771 2435 +2717 2770 2434 +2717 2770 2432 +2717 2770 2430 +2717 2769 2430 +2718 2769 2431 +2718 2770 2433 +2719 2771 2443 +2720 2774 2457 +2721 2773 2466 +2716 2771 2466 +2717 2774 2492 +2718 2776 2528 +2718 2777 2569 +2722 2782 2624 +2727 2788 2703 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2718 2771 2437 +2718 2771 2437 +2718 2771 2437 +2718 2771 2436 +2718 2771 2436 +2718 2771 2435 +2718 2771 2435 +2717 2770 2434 +2717 2770 2432 +2717 2770 2430 +2717 2769 2430 +2718 2769 2431 +2718 2770 2433 +2719 2771 2443 +2720 2774 2457 +2721 2773 2466 +2716 2771 2466 +2717 2774 2492 +2718 2776 2528 +2718 2777 2569 +2722 2782 2624 +2727 2788 2703 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2718 2771 2437 +2718 2771 2437 +2718 2771 2437 +2718 2771 2436 +2718 2771 2436 +2718 2771 2435 +2718 2771 2435 +2717 2770 2434 +2717 2770 2432 +2717 2770 2430 +2717 2769 2430 +2718 2769 2431 +2718 2770 2433 +2719 2771 2443 +2720 2774 2457 +2721 2773 2466 +2716 2771 2466 +2717 2774 2492 +2718 2776 2528 +2718 2777 2569 +2722 2782 2624 +2727 2788 2703 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2718 2771 2437 +2718 2771 2437 +2718 2771 2437 +2718 2771 2436 +2718 2771 2436 +2718 2771 2435 +2718 2771 2435 +2717 2770 2434 +2717 2770 2432 +2717 2770 2430 +2717 2769 2430 +2718 2769 2431 +2718 2770 2433 +2719 2771 2443 +2720 2774 2457 +2721 2773 2466 +2716 2771 2466 +2717 2774 2492 +2718 2776 2528 +2718 2777 2569 +2722 2782 2624 +2727 2788 2703 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +2731 2794 2734 +1824 0 1212 +1824 0 1217 +1825 0 1223 +1825 0 1231 +1826 0 1242 +1827 0 1255 +1829 0 1273 +1831 0 1296 +1833 0 1325 +1830 0 1360 +1825 0 1405 +1819 0 1458 +1810 0 1521 +1804 0 1576 +1787 0 1659 +1777 0 1755 +1770 0 1865 +1790 0 1986 +1740 750 2108 +1692 916 2230 +1561 947 2370 +1845 0 2469 +1920 0 2511 +1920 0 2511 +1920 0 2511 +1920 0 2511 +1920 0 2511 +1920 0 2511 +1920 0 2511 +1920 0 2511 +1920 0 2511 +1920 0 2511 +1824 0 1216 +1824 0 1219 +1825 0 1225 +1825 0 1233 +1826 0 1243 +1827 0 1257 +1829 0 1275 +1831 0 1298 +1833 0 1326 +1830 0 1362 +1825 0 1406 +1819 0 1459 +1810 0 1523 +1804 0 1578 +1787 0 1661 +1777 0 1756 +1770 0 1866 +1790 32 1986 +1740 754 2108 +1692 922 2231 +1561 949 2370 +1845 0 2470 +1920 0 2510 +1920 0 2510 +1920 0 2510 +1920 0 2510 +1920 0 2510 +1920 0 2510 +1920 0 2510 +1920 0 2510 +1920 0 2510 +1920 0 2510 +1825 0 1221 +1825 0 1224 +1825 0 1228 +1825 0 1235 +1826 0 1246 +1827 0 1260 +1829 0 1277 +1831 0 1300 +1833 0 1328 +1830 0 1364 +1825 0 1408 +1819 0 1461 +1810 0 1524 +1804 0 1580 +1787 0 1663 +1777 0 1758 +1770 44 1866 +1789 88 1987 +1740 759 2109 +1692 931 2231 +1562 952 2370 +1845 0 2470 +1920 0 2510 +1920 0 2510 +1920 0 2510 +1920 0 2510 +1920 0 2510 +1920 0 2510 +1920 0 2510 +1920 0 2510 +1920 0 2510 +1920 0 2510 +1825 0 1228 +1825 0 1231 +1825 0 1234 +1825 0 1239 +1826 0 1249 +1827 0 1263 +1829 0 1280 +1831 0 1302 +1833 0 1331 +1830 0 1366 +1825 0 1410 +1819 0 1463 +1810 0 1526 +1804 0 1584 +1787 0 1666 +1777 0 1760 +1769 102 1867 +1788 153 1988 +1739 765 2110 +1692 942 2232 +1563 957 2370 +1845 0 2470 +1920 44 2510 +1920 44 2510 +1920 44 2510 +1920 44 2510 +1920 44 2510 +1920 44 2510 +1920 44 2510 +1920 44 2510 +1920 44 2510 +1920 44 2510 +1826 0 1238 +1826 0 1240 +1826 0 1243 +1826 0 1248 +1826 0 1254 +1827 0 1267 +1829 0 1284 +1831 0 1306 +1833 0 1335 +1830 0 1370 +1825 0 1413 +1819 0 1465 +1810 0 1528 +1804 0 1588 +1787 0 1669 +1777 83 1763 +1769 170 1868 +1787 229 1990 +1739 774 2111 +1692 956 2233 +1563 962 2370 +1845 0 2470 +1921 103 2510 +1921 103 2510 +1921 103 2510 +1921 103 2510 +1921 103 2510 +1921 103 2510 +1921 103 2510 +1921 103 2510 +1921 103 2510 +1921 103 2510 +1827 0 1250 +1827 0 1252 +1827 0 1255 +1827 0 1260 +1827 1 1265 +1827 30 1273 +1829 30 1290 +1831 30 1312 +1833 30 1339 +1830 30 1375 +1825 30 1417 +1819 30 1469 +1810 64 1531 +1804 132 1593 +1787 132 1674 +1777 215 1767 +1768 247 1870 +1785 313 1991 +1738 785 2113 +1692 974 2235 +1564 970 2370 +1845 0 2470 +1921 171 2510 +1921 171 2510 +1921 171 2510 +1921 171 2510 +1921 171 2510 +1921 171 2510 +1921 171 2510 +1921 171 2510 +1921 171 2510 +1921 171 2510 +1829 58 1265 +1829 66 1267 +1829 77 1270 +1829 91 1275 +1829 109 1280 +1829 133 1288 +1829 163 1297 +1831 163 1318 +1833 163 1346 +1830 163 1380 +1825 163 1423 +1819 163 1474 +1810 188 1536 +1804 264 1601 +1787 264 1680 +1777 347 1772 +1767 334 1872 +1783 406 1994 +1737 799 2115 +1692 998 2237 +1565 979 2370 +1845 32 2471 +1922 248 2510 +1922 248 2510 +1922 248 2510 +1922 248 2510 +1922 248 2510 +1922 248 2510 +1922 248 2510 +1922 248 2510 +1922 248 2510 +1922 248 2510 +1831 183 1285 +1831 190 1287 +1831 198 1290 +1831 209 1294 +1831 223 1299 +1831 242 1306 +1831 265 1315 +1831 295 1328 +1833 295 1354 +1830 295 1388 +1825 295 1430 +1819 295 1480 +1810 314 1541 +1804 396 1611 +1787 396 1688 +1777 479 1778 +1766 428 1875 +1779 506 1998 +1736 818 2119 +1692 1027 2240 +1567 992 2369 +1845 164 2471 +1922 335 2510 +1922 335 2510 +1922 335 2510 +1922 335 2510 +1922 335 2510 +1922 335 2510 +1922 335 2510 +1922 335 2510 +1922 335 2510 +1922 335 2510 +1833 310 1310 +1833 315 1312 +1833 322 1315 +1833 330 1319 +1833 341 1324 +1833 355 1331 +1833 373 1339 +1833 397 1351 +1833 426 1365 +1830 426 1398 +1825 426 1439 +1819 426 1489 +1810 441 1548 +1804 528 1623 +1787 528 1699 +1777 611 1787 +1765 530 1878 +1775 613 2002 +1734 841 2123 +1692 1064 2244 +1569 1008 2369 +1844 330 2472 +1924 429 2510 +1924 429 2510 +1924 429 2510 +1924 429 2510 +1924 429 2510 +1924 429 2510 +1924 429 2510 +1924 429 2510 +1924 429 2510 +1924 429 2510 +1830 439 1356 +1830 443 1358 +1830 447 1361 +1830 454 1364 +1830 462 1369 +1830 473 1375 +1830 487 1383 +1830 506 1393 +1830 529 1407 +1828 531 1428 +1824 531 1466 +1817 531 1513 +1809 543 1570 +1803 601 1641 +1787 591 1713 +1780 686 1796 +1768 615 1886 +1769 725 2008 +1730 897 2126 +1685 1092 2246 +1595 1019 2371 +1840 422 2472 +1926 531 2509 +1926 531 2509 +1926 531 2509 +1926 531 2509 +1926 531 2509 +1926 531 2509 +1926 531 2509 +1926 531 2509 +1926 531 2509 +1926 531 2509 +1825 568 1412 +1825 571 1414 +1825 575 1417 +1825 579 1420 +1825 586 1424 +1825 594 1429 +1825 605 1436 +1825 619 1445 +1825 638 1457 +1824 640 1476 +1821 640 1501 +1814 640 1545 +1806 648 1598 +1800 695 1664 +1787 658 1731 +1782 751 1810 +1774 707 1896 +1763 805 2012 +1724 965 2131 +1675 1127 2249 +1629 1033 2373 +1836 515 2472 +1930 640 2509 +1930 640 2509 +1930 640 2509 +1930 640 2509 +1930 640 2509 +1930 640 2509 +1930 640 2509 +1930 640 2509 +1930 640 2509 +1930 640 2509 +1819 699 1479 +1819 701 1480 +1819 703 1482 +1819 707 1485 +1819 712 1488 +1819 718 1493 +1819 727 1499 +1819 737 1507 +1819 752 1518 +1817 753 1534 +1814 753 1556 +1811 753 1584 +1803 760 1633 +1797 797 1695 +1787 733 1754 +1782 813 1830 +1781 806 1910 +1756 887 2016 +1716 1042 2138 +1662 1169 2253 +1634 1062 2374 +1829 616 2472 +1935 753 2509 +1935 753 2509 +1935 753 2509 +1935 753 2509 +1935 753 2509 +1935 753 2509 +1935 753 2509 +1935 753 2509 +1935 753 2509 +1935 753 2509 +1811 848 1553 +1811 848 1554 +1811 851 1556 +1811 853 1558 +1811 857 1561 +1811 861 1565 +1811 867 1570 +1811 875 1577 +1811 886 1586 +1809 887 1600 +1807 887 1619 +1804 887 1644 +1799 892 1675 +1793 920 1732 +1785 861 1784 +1781 901 1853 +1789 932 1929 +1748 990 2023 +1706 1137 2147 +1648 1218 2257 +1620 1108 2375 +1824 746 2471 +1942 876 2509 +1942 876 2509 +1942 876 2509 +1942 876 2509 +1942 876 2509 +1942 876 2509 +1942 876 2509 +1942 876 2509 +1942 876 2509 +1942 876 2509 +1820 1109 1630 +1820 1109 1631 +1819 1109 1633 +1819 1109 1635 +1818 1109 1637 +1817 1109 1641 +1815 1109 1645 +1813 1109 1651 +1810 1109 1659 +1810 1109 1670 +1808 1109 1686 +1805 1109 1707 +1800 1112 1734 +1793 1134 1775 +1785 1098 1823 +1767 1090 1881 +1785 1153 1970 +1749 1166 2045 +1704 1267 2165 +1646 1289 2266 +1638 1188 2377 +1843 976 2471 +1948 1035 2509 +1948 1035 2509 +1948 1035 2509 +1948 1035 2509 +1948 1035 2509 +1948 1035 2509 +1948 1035 2509 +1948 1035 2509 +1948 1035 2509 +1948 1035 2509 +1812 1336 1724 +1812 1336 1725 +1811 1336 1727 +1811 1336 1728 +1810 1336 1730 +1809 1336 1733 +1807 1336 1736 +1805 1336 1741 +1802 1336 1748 +1804 1336 1756 +1806 1336 1767 +1810 1336 1781 +1808 1338 1803 +1801 1351 1839 +1785 1351 1887 +1762 1338 1936 +1760 1342 2007 +1728 1366 2073 +1683 1382 2175 +1573 1418 2288 +1713 1264 2379 +1872 1202 2471 +1942 1211 2508 +1942 1211 2508 +1942 1211 2508 +1942 1211 2508 +1942 1211 2508 +1942 1211 2508 +1942 1211 2508 +1942 1211 2508 +1942 1211 2508 +1942 1211 2508 +1832 1511 1838 +1832 1511 1839 +1832 1511 1839 +1832 1511 1840 +1832 1511 1841 +1832 1511 1843 +1832 1511 1845 +1832 1511 1848 +1832 1511 1852 +1829 1511 1857 +1829 1511 1865 +1832 1511 1876 +1834 1511 1891 +1824 1511 1912 +1810 1511 1951 +1783 1522 2002 +1774 1495 2052 +1746 1515 2117 +1708 1501 2192 +1652 1522 2297 +1779 1436 2383 +1898 1422 2472 +1969 1408 2508 +1969 1408 2508 +1969 1408 2508 +1969 1408 2508 +1969 1408 2508 +1969 1408 2508 +1969 1408 2508 +1969 1408 2508 +1969 1408 2508 +1969 1408 2508 +1888 1654 1938 +1888 1654 1938 +1888 1654 1939 +1888 1654 1940 +1888 1654 1940 +1888 1654 1942 +1888 1654 1943 +1888 1654 1946 +1888 1654 1949 +1885 1654 1953 +1881 1654 1958 +1875 1654 1965 +1868 1655 1975 +1863 1662 1991 +1855 1662 2017 +1843 1654 2055 +1817 1654 2107 +1794 1657 2159 +1766 1662 2229 +1800 1621 2303 +1843 1605 2385 +1921 1624 2474 +2007 1630 2511 +2007 1630 2511 +2007 1630 2511 +2007 1630 2511 +2007 1630 2511 +2007 1630 2511 +2007 1630 2511 +2007 1630 2511 +2007 1630 2511 +2007 1630 2511 +1977 1783 1983 +1977 1783 1984 +1977 1783 1984 +1977 1783 1985 +1977 1783 1986 +1978 1783 1987 +1978 1783 1989 +1979 1783 1991 +1980 1783 1994 +1980 1783 1997 +1977 1785 2004 +1973 1788 2012 +1966 1792 2023 +1959 1786 2037 +1958 1786 2064 +1950 1793 2093 +1929 1801 2129 +1939 1792 2174 +1905 1778 2235 +1877 1792 2311 +1920 1800 2389 +2007 1802 2476 +2064 1798 2511 +2064 1798 2511 +2064 1798 2511 +2064 1798 2511 +2064 1798 2511 +2064 1798 2511 +2064 1798 2511 +2064 1798 2511 +2064 1798 2511 +2064 1798 2511 +2083 1958 2032 +2082 1958 2032 +2082 1958 2032 +2082 1958 2033 +2082 1958 2034 +2082 1958 2035 +2081 1958 2036 +2081 1958 2038 +2080 1958 2041 +2077 1959 2045 +2073 1961 2051 +2067 1963 2058 +2061 1965 2068 +2056 1964 2080 +2056 1959 2093 +2052 1959 2114 +2036 1961 2142 +2031 1968 2199 +2019 1953 2244 +2017 1958 2317 +2046 1962 2395 +2106 1970 2483 +2149 1969 2517 +2149 1969 2517 +2149 1969 2517 +2149 1969 2517 +2149 1969 2517 +2149 1969 2517 +2149 1969 2517 +2149 1969 2517 +2149 1969 2517 +2149 1969 2517 +2191 2132 2068 +2191 2132 2068 +2191 2132 2069 +2190 2132 2069 +2190 2132 2070 +2190 2131 2071 +2189 2131 2072 +2188 2130 2074 +2187 2130 2076 +2187 2129 2079 +2187 2129 2083 +2187 2129 2088 +2187 2129 2096 +2184 2129 2105 +2180 2129 2117 +2180 2128 2131 +2170 2124 2154 +2176 2127 2200 +2167 2133 2262 +2179 2135 2315 +2208 2135 2395 +2271 2155 2484 +2291 2159 2521 +2291 2159 2521 +2291 2159 2521 +2291 2159 2521 +2291 2159 2521 +2291 2159 2521 +2291 2159 2521 +2291 2159 2521 +2291 2159 2521 +2291 2159 2521 +2407 2360 2121 +2407 2360 2121 +2407 2360 2121 +2407 2360 2121 +2407 2360 2121 +2407 2359 2122 +2407 2359 2122 +2407 2359 2123 +2407 2358 2123 +2408 2359 2125 +2408 2360 2128 +2409 2360 2131 +2409 2360 2135 +2408 2362 2141 +2405 2359 2147 +2402 2358 2164 +2395 2358 2193 +2399 2361 2228 +2408 2365 2275 +2419 2368 2338 +2446 2373 2402 +2486 2387 2498 +2516 2398 2529 +2516 2398 2529 +2516 2398 2529 +2516 2398 2529 +2516 2398 2529 +2516 2398 2529 +2516 2398 2529 +2516 2398 2529 +2516 2398 2529 +2516 2398 2529 +2687 2656 1984 +2687 2656 1984 +2687 2656 1984 +2687 2656 1984 +2687 2656 1984 +2687 2656 1984 +2687 2656 1984 +2687 2656 1984 +2688 2656 1989 +2688 2656 1991 +2688 2656 1992 +2689 2656 1995 +2690 2656 1999 +2690 2657 2008 +2688 2657 2023 +2688 2657 2054 +2688 2658 2083 +2688 2659 2149 +2689 2659 2227 +2696 2667 2323 +2703 2668 2417 +2722 2681 2534 +2728 2686 2580 +2728 2686 2580 +2728 2686 2580 +2728 2686 2580 +2728 2686 2580 +2728 2686 2580 +2728 2686 2580 +2728 2686 2580 +2728 2686 2580 +2728 2686 2580 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2772 2447 +2721 2772 2444 +2721 2771 2441 +2720 2770 2438 +2721 2771 2443 +2722 2773 2457 +2723 2774 2473 +2723 2774 2481 +2717 2775 2500 +2720 2779 2531 +2720 2778 2569 +2726 2782 2625 +2731 2788 2703 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2772 2447 +2721 2772 2444 +2721 2771 2441 +2720 2770 2438 +2721 2771 2443 +2722 2773 2457 +2723 2774 2473 +2723 2774 2481 +2717 2775 2500 +2720 2779 2531 +2720 2778 2569 +2726 2782 2625 +2731 2788 2703 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2772 2447 +2721 2772 2444 +2721 2771 2441 +2720 2770 2438 +2721 2771 2443 +2722 2773 2457 +2723 2774 2473 +2723 2774 2481 +2717 2775 2500 +2720 2779 2531 +2720 2778 2569 +2726 2782 2625 +2731 2788 2703 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2772 2447 +2721 2772 2444 +2721 2771 2441 +2720 2770 2438 +2721 2771 2443 +2722 2773 2457 +2723 2774 2473 +2723 2774 2481 +2717 2775 2500 +2720 2779 2531 +2720 2778 2569 +2726 2782 2625 +2731 2788 2703 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2772 2447 +2721 2772 2444 +2721 2771 2441 +2720 2770 2438 +2721 2771 2443 +2722 2773 2457 +2723 2774 2473 +2723 2774 2481 +2717 2775 2500 +2720 2779 2531 +2720 2778 2569 +2726 2782 2625 +2731 2788 2703 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2772 2447 +2721 2772 2444 +2721 2771 2441 +2720 2770 2438 +2721 2771 2443 +2722 2773 2457 +2723 2774 2473 +2723 2774 2481 +2717 2775 2500 +2720 2779 2531 +2720 2778 2569 +2726 2782 2625 +2731 2788 2703 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2772 2447 +2721 2772 2444 +2721 2771 2441 +2720 2770 2438 +2721 2771 2443 +2722 2773 2457 +2723 2774 2473 +2723 2774 2481 +2717 2775 2500 +2720 2779 2531 +2720 2778 2569 +2726 2782 2625 +2731 2788 2703 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2772 2447 +2721 2772 2444 +2721 2771 2441 +2720 2770 2438 +2721 2771 2443 +2722 2773 2457 +2723 2774 2473 +2723 2774 2481 +2717 2775 2500 +2720 2779 2531 +2720 2778 2569 +2726 2782 2625 +2731 2788 2703 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2772 2447 +2721 2772 2444 +2721 2771 2441 +2720 2770 2438 +2721 2771 2443 +2722 2773 2457 +2723 2774 2473 +2723 2774 2481 +2717 2775 2500 +2720 2779 2531 +2720 2778 2569 +2726 2782 2625 +2731 2788 2703 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2773 2448 +2722 2772 2447 +2721 2772 2444 +2721 2771 2441 +2720 2770 2438 +2721 2771 2443 +2722 2773 2457 +2723 2774 2473 +2723 2774 2481 +2717 2775 2500 +2720 2779 2531 +2720 2778 2569 +2726 2782 2625 +2731 2788 2703 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +2734 2794 2737 +1906 311 1618 +1906 316 1619 +1906 322 1620 +1906 330 1621 +1905 342 1623 +1905 356 1626 +1905 374 1630 +1904 398 1634 +1903 427 1640 +1901 464 1648 +1904 471 1670 +1909 471 1700 +1914 464 1736 +1910 152 1775 +1903 63 1817 +1900 481 1880 +1885 481 1958 +1866 624 2053 +1837 927 2156 +1786 933 2261 +1818 679 2380 +1933 0 2471 +1989 487 2513 +1989 487 2513 +1989 487 2513 +1989 487 2513 +1989 487 2513 +1989 487 2513 +1989 487 2513 +1989 487 2513 +1989 487 2513 +1989 487 2513 +1906 330 1619 +1907 325 1621 +1906 332 1622 +1906 340 1623 +1906 351 1625 +1905 365 1628 +1905 383 1631 +1904 406 1636 +1903 435 1642 +1901 471 1650 +1904 478 1672 +1910 478 1702 +1915 478 1736 +1910 179 1776 +1903 95 1817 +1900 491 1880 +1885 491 1958 +1866 631 2054 +1837 928 2156 +1786 935 2261 +1818 681 2380 +1933 0 2471 +1989 491 2513 +1989 491 2513 +1989 491 2513 +1989 491 2513 +1989 491 2513 +1989 491 2513 +1989 491 2513 +1989 491 2513 +1989 491 2513 +1989 491 2513 +1906 354 1621 +1907 350 1622 +1907 344 1624 +1907 352 1625 +1906 362 1627 +1906 376 1630 +1905 393 1633 +1904 416 1638 +1903 444 1644 +1902 480 1652 +1905 486 1674 +1910 486 1704 +1915 486 1738 +1910 212 1777 +1904 135 1818 +1900 504 1881 +1885 504 1959 +1866 640 2054 +1837 930 2156 +1787 936 2261 +1819 684 2380 +1933 0 2471 +1990 495 2513 +1990 495 2513 +1990 495 2513 +1990 495 2513 +1990 495 2513 +1990 495 2513 +1990 495 2513 +1990 495 2513 +1990 495 2513 +1990 495 2513 +1906 384 1623 +1907 381 1624 +1907 375 1626 +1907 367 1628 +1907 377 1630 +1906 391 1633 +1905 408 1636 +1905 430 1641 +1904 457 1647 +1902 491 1655 +1905 498 1676 +1911 498 1706 +1915 498 1740 +1910 253 1778 +1904 183 1819 +1900 520 1882 +1885 520 1960 +1866 653 2055 +1838 932 2156 +1787 939 2261 +1819 688 2381 +1933 0 2471 +1990 501 2513 +1990 501 2513 +1990 501 2513 +1990 501 2513 +1990 501 2513 +1990 501 2513 +1990 501 2513 +1990 501 2513 +1990 501 2513 +1990 501 2513 +1906 422 1625 +1907 419 1626 +1907 413 1628 +1907 406 1631 +1908 397 1634 +1907 409 1636 +1906 426 1640 +1905 447 1644 +1904 473 1650 +1903 507 1658 +1906 513 1680 +1911 513 1709 +1916 513 1743 +1911 303 1780 +1904 241 1821 +1899 542 1884 +1886 542 1962 +1866 669 2056 +1838 935 2156 +1788 941 2261 +1820 693 2381 +1933 0 2471 +1991 508 2513 +1991 508 2513 +1991 508 2513 +1991 508 2513 +1991 508 2513 +1991 508 2513 +1991 508 2513 +1991 508 2513 +1991 508 2513 +1991 508 2513 +1906 468 1629 +1907 465 1630 +1907 460 1632 +1907 454 1634 +1908 445 1637 +1908 434 1641 +1907 449 1645 +1906 469 1649 +1905 495 1655 +1904 526 1663 +1907 533 1684 +1912 533 1713 +1917 533 1747 +1911 362 1783 +1905 308 1823 +1899 569 1886 +1886 569 1964 +1866 690 2057 +1839 939 2157 +1789 945 2262 +1821 700 2381 +1933 10 2471 +1993 518 2513 +1993 518 2513 +1993 518 2513 +1993 518 2513 +1993 518 2513 +1993 518 2513 +1993 518 2513 +1993 518 2513 +1993 518 2513 +1993 518 2513 +1906 523 1633 +1907 520 1635 +1907 516 1636 +1907 511 1639 +1908 503 1642 +1908 493 1646 +1908 479 1651 +1908 498 1656 +1907 521 1662 +1905 551 1669 +1908 557 1690 +1913 557 1719 +1918 557 1753 +1912 430 1786 +1905 384 1826 +1898 602 1888 +1887 602 1966 +1866 716 2059 +1839 944 2157 +1791 950 2262 +1823 708 2381 +1933 84 2470 +1994 531 2513 +1994 531 2513 +1994 531 2513 +1994 531 2513 +1994 531 2513 +1994 531 2513 +1994 531 2513 +1994 531 2513 +1994 531 2513 +1994 531 2513 +1906 588 1640 +1907 585 1641 +1907 582 1643 +1907 577 1645 +1908 570 1648 +1908 562 1652 +1908 550 1657 +1909 533 1664 +1908 555 1670 +1907 583 1678 +1910 588 1698 +1915 588 1727 +1920 588 1759 +1913 508 1790 +1906 470 1830 +1897 644 1892 +1888 644 1970 +1866 749 2061 +1840 951 2157 +1793 957 2263 +1825 720 2382 +1933 167 2470 +1996 548 2512 +1996 548 2512 +1996 548 2512 +1996 548 2512 +1996 548 2512 +1996 548 2512 +1996 548 2512 +1996 548 2512 +1996 548 2512 +1996 548 2512 +1906 662 1647 +1907 660 1649 +1907 657 1650 +1907 653 1653 +1908 647 1655 +1908 640 1659 +1908 629 1665 +1909 615 1672 +1911 596 1681 +1909 622 1689 +1912 627 1708 +1917 627 1736 +1922 627 1769 +1913 595 1796 +1907 563 1835 +1896 695 1896 +1889 695 1975 +1866 789 2064 +1841 960 2158 +1796 966 2263 +1827 735 2383 +1933 330 2471 +1999 569 2512 +1999 569 2512 +1999 569 2512 +1999 569 2512 +1999 569 2512 +1999 569 2512 +1999 569 2512 +1999 569 2512 +1999 569 2512 +1999 569 2512 +1906 745 1658 +1907 743 1659 +1907 741 1661 +1907 737 1663 +1908 733 1666 +1908 727 1670 +1908 718 1675 +1909 707 1682 +1911 691 1691 +1912 669 1703 +1915 674 1722 +1920 674 1749 +1925 674 1780 +1915 674 1805 +1909 665 1842 +1894 754 1903 +1887 754 1980 +1866 838 2069 +1843 972 2159 +1800 977 2264 +1831 754 2384 +1933 489 2472 +2002 596 2512 +2002 596 2512 +2002 596 2512 +2002 596 2512 +2002 596 2512 +2002 596 2512 +2002 596 2512 +2002 596 2512 +2002 596 2512 +2002 596 2512 +1910 819 1677 +1910 817 1678 +1910 815 1680 +1911 812 1682 +1911 809 1685 +1911 803 1689 +1912 796 1693 +1913 787 1700 +1914 773 1708 +1915 755 1720 +1915 772 1732 +1921 772 1758 +1925 772 1789 +1916 772 1813 +1909 792 1855 +1894 863 1914 +1887 875 1990 +1865 911 2073 +1841 1000 2165 +1800 1040 2269 +1833 798 2384 +1931 640 2472 +2004 683 2511 +2004 683 2511 +2004 683 2511 +2004 683 2511 +2004 683 2511 +2004 683 2511 +2004 683 2511 +2004 683 2511 +2004 683 2511 +2004 683 2511 +1915 898 1703 +1915 897 1704 +1915 895 1705 +1915 893 1707 +1916 890 1710 +1916 885 1713 +1917 879 1718 +1918 871 1724 +1919 860 1732 +1920 845 1743 +1921 860 1755 +1921 885 1769 +1925 885 1799 +1916 885 1823 +1909 925 1873 +1894 979 1929 +1887 1007 2002 +1862 997 2078 +1838 1037 2174 +1800 1121 2277 +1843 837 2383 +1928 785 2473 +2007 787 2510 +2007 787 2510 +2007 787 2510 +2007 787 2510 +2007 787 2510 +2007 787 2510 +2007 787 2510 +2007 787 2510 +2007 787 2510 +2007 787 2510 +1922 997 1735 +1922 998 1736 +1922 997 1737 +1922 995 1739 +1923 993 1741 +1923 989 1745 +1924 984 1749 +1925 978 1755 +1926 969 1763 +1927 958 1772 +1927 969 1783 +1927 989 1797 +1926 1011 1816 +1917 1011 1839 +1910 1049 1891 +1895 1094 1949 +1888 1137 2019 +1859 1095 2086 +1833 1102 2184 +1802 1203 2287 +1856 905 2383 +1926 942 2474 +2010 902 2509 +2010 902 2509 +2010 902 2509 +2010 902 2509 +2010 902 2509 +2010 902 2509 +2010 902 2509 +2010 902 2509 +2010 902 2509 +2010 902 2509 +1931 1121 1774 +1931 1122 1775 +1931 1123 1776 +1932 1124 1778 +1932 1126 1780 +1932 1129 1783 +1933 1132 1787 +1934 1137 1793 +1935 1143 1800 +1936 1145 1809 +1936 1152 1819 +1936 1166 1832 +1935 1181 1849 +1921 1181 1881 +1914 1207 1928 +1905 1197 1974 +1898 1248 2038 +1870 1219 2099 +1827 1224 2189 +1814 1266 2289 +1856 1137 2381 +1933 1139 2475 +2017 1048 2509 +2017 1048 2509 +2017 1048 2509 +2017 1048 2509 +2017 1048 2509 +2017 1048 2509 +2017 1048 2509 +2017 1048 2509 +2017 1048 2509 +2017 1048 2509 +1943 1312 1836 +1943 1312 1837 +1943 1313 1838 +1943 1314 1839 +1944 1315 1841 +1944 1317 1844 +1945 1319 1847 +1945 1322 1852 +1946 1326 1858 +1948 1331 1866 +1945 1332 1875 +1940 1332 1886 +1936 1339 1902 +1923 1339 1930 +1915 1358 1965 +1906 1343 2006 +1889 1364 2062 +1872 1381 2136 +1826 1367 2210 +1822 1339 2296 +1868 1258 2382 +1955 1262 2478 +2027 1191 2509 +2027 1191 2509 +2027 1191 2509 +2027 1191 2509 +2027 1191 2509 +2027 1191 2509 +2027 1191 2509 +2027 1191 2509 +2027 1191 2509 +2027 1191 2509 +1969 1458 1884 +1969 1458 1884 +1968 1458 1885 +1968 1458 1887 +1968 1458 1888 +1968 1458 1890 +1967 1458 1892 +1966 1458 1896 +1965 1458 1900 +1964 1458 1906 +1962 1458 1913 +1957 1458 1924 +1950 1459 1938 +1941 1472 1960 +1934 1487 1991 +1937 1461 2031 +1908 1472 2078 +1899 1508 2159 +1871 1507 2226 +1869 1459 2304 +1906 1424 2382 +1989 1433 2480 +2031 1414 2509 +2031 1414 2509 +2031 1414 2509 +2031 1414 2509 +2031 1414 2509 +2031 1414 2509 +2031 1414 2509 +2031 1414 2509 +2031 1414 2509 +2031 1414 2509 +1995 1625 1959 +1995 1625 1960 +1995 1625 1961 +1995 1626 1962 +1995 1626 1963 +1994 1627 1965 +1994 1628 1968 +1993 1630 1972 +1992 1632 1976 +1991 1632 1982 +1990 1632 1987 +1990 1632 1993 +1990 1632 2002 +1989 1633 2018 +1978 1635 2038 +1968 1630 2070 +1945 1650 2122 +1941 1635 2175 +1926 1623 2233 +1921 1624 2309 +1947 1613 2388 +2014 1610 2474 +2061 1608 2512 +2061 1608 2512 +2061 1608 2512 +2061 1608 2512 +2061 1608 2512 +2061 1608 2512 +2061 1608 2512 +2061 1608 2512 +2061 1608 2512 +2061 1608 2512 +2048 1766 1996 +2048 1766 1996 +2048 1766 1996 +2048 1766 1997 +2048 1766 1998 +2048 1766 1999 +2048 1766 2000 +2048 1766 2002 +2048 1766 2006 +2048 1766 2009 +2048 1766 2014 +2048 1766 2020 +2048 1767 2029 +2044 1773 2043 +2040 1782 2061 +2029 1792 2098 +2027 1783 2138 +1997 1783 2185 +1996 1799 2243 +1996 1791 2315 +2012 1789 2391 +2075 1804 2478 +2111 1808 2513 +2111 1808 2513 +2111 1808 2513 +2111 1808 2513 +2111 1808 2513 +2111 1808 2513 +2111 1808 2513 +2111 1808 2513 +2111 1808 2513 +2111 1808 2513 +2118 1947 2038 +2118 1947 2038 +2118 1947 2039 +2118 1947 2039 +2118 1948 2040 +2119 1948 2041 +2119 1948 2042 +2120 1949 2044 +2120 1950 2047 +2121 1951 2050 +2120 1952 2054 +2119 1952 2060 +2117 1952 2068 +2111 1952 2078 +2102 1952 2094 +2100 1957 2116 +2094 1953 2146 +2078 1951 2186 +2073 1951 2247 +2076 1958 2318 +2097 1963 2398 +2161 1972 2478 +2191 1974 2517 +2191 1974 2517 +2191 1974 2517 +2191 1974 2517 +2191 1974 2517 +2191 1974 2517 +2191 1974 2517 +2191 1974 2517 +2191 1974 2517 +2191 1974 2517 +2223 2127 2077 +2223 2127 2077 +2223 2127 2077 +2223 2128 2078 +2223 2128 2078 +2223 2128 2078 +2223 2128 2079 +2223 2129 2080 +2223 2130 2082 +2223 2131 2084 +2221 2130 2088 +2219 2128 2093 +2216 2127 2099 +2213 2127 2109 +2210 2127 2121 +2206 2127 2136 +2216 2126 2162 +2212 2127 2204 +2215 2139 2260 +2222 2139 2318 +2237 2143 2401 +2282 2159 2486 +2316 2166 2524 +2316 2166 2524 +2316 2166 2524 +2316 2166 2524 +2316 2166 2524 +2316 2166 2524 +2316 2166 2524 +2316 2166 2524 +2316 2166 2524 +2316 2166 2524 +2426 2364 2124 +2426 2364 2124 +2426 2364 2124 +2426 2364 2125 +2426 2364 2125 +2426 2364 2126 +2426 2364 2126 +2426 2364 2127 +2426 2364 2129 +2426 2364 2131 +2426 2364 2132 +2426 2363 2135 +2427 2362 2138 +2429 2364 2138 +2428 2365 2146 +2427 2363 2161 +2428 2366 2187 +2427 2369 2230 +2430 2369 2278 +2430 2368 2333 +2463 2376 2405 +2502 2392 2495 +2540 2403 2525 +2540 2403 2525 +2540 2403 2525 +2540 2403 2525 +2540 2403 2525 +2540 2403 2525 +2540 2403 2525 +2540 2403 2525 +2540 2403 2525 +2540 2403 2525 +2694 2658 1982 +2694 2658 1982 +2694 2658 1982 +2694 2658 1981 +2694 2658 1981 +2694 2658 1979 +2693 2657 1979 +2693 2657 1977 +2693 2657 1978 +2693 2657 1979 +2693 2658 1988 +2694 2659 2001 +2694 2660 2015 +2696 2660 2021 +2695 2657 2016 +2695 2660 2055 +2697 2662 2117 +2697 2663 2170 +2697 2666 2245 +2701 2667 2320 +2711 2672 2426 +2725 2685 2539 +2731 2689 2588 +2731 2689 2588 +2731 2689 2588 +2731 2689 2588 +2731 2689 2588 +2731 2689 2588 +2731 2689 2588 +2731 2689 2588 +2731 2689 2588 +2731 2689 2588 +2727 2773 2456 +2727 2773 2456 +2727 2773 2456 +2727 2774 2457 +2727 2774 2457 +2727 2774 2457 +2727 2774 2458 +2728 2774 2459 +2728 2775 2460 +2728 2775 2461 +2728 2775 2461 +2728 2775 2461 +2728 2775 2461 +2729 2773 2461 +2729 2774 2466 +2728 2776 2478 +2729 2777 2494 +2725 2779 2509 +2723 2779 2533 +2725 2779 2571 +2728 2783 2631 +2735 2789 2705 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2727 2773 2456 +2727 2773 2456 +2727 2773 2456 +2727 2774 2457 +2727 2774 2457 +2727 2774 2457 +2727 2774 2458 +2728 2774 2459 +2728 2775 2460 +2728 2775 2461 +2728 2775 2461 +2728 2775 2461 +2728 2775 2461 +2729 2773 2461 +2729 2774 2466 +2728 2776 2478 +2729 2777 2494 +2725 2779 2509 +2723 2779 2533 +2725 2779 2571 +2728 2783 2631 +2735 2789 2705 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2727 2773 2456 +2727 2773 2456 +2727 2773 2456 +2727 2774 2457 +2727 2774 2457 +2727 2774 2457 +2727 2774 2458 +2728 2774 2459 +2728 2775 2460 +2728 2775 2461 +2728 2775 2461 +2728 2775 2461 +2728 2775 2461 +2729 2773 2461 +2729 2774 2466 +2728 2776 2478 +2729 2777 2494 +2725 2779 2509 +2723 2779 2533 +2725 2779 2571 +2728 2783 2631 +2735 2789 2705 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2727 2773 2456 +2727 2773 2456 +2727 2773 2456 +2727 2774 2457 +2727 2774 2457 +2727 2774 2457 +2727 2774 2458 +2728 2774 2459 +2728 2775 2460 +2728 2775 2461 +2728 2775 2461 +2728 2775 2461 +2728 2775 2461 +2729 2773 2461 +2729 2774 2466 +2728 2776 2478 +2729 2777 2494 +2725 2779 2509 +2723 2779 2533 +2725 2779 2571 +2728 2783 2631 +2735 2789 2705 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2727 2773 2456 +2727 2773 2456 +2727 2773 2456 +2727 2774 2457 +2727 2774 2457 +2727 2774 2457 +2727 2774 2458 +2728 2774 2459 +2728 2775 2460 +2728 2775 2461 +2728 2775 2461 +2728 2775 2461 +2728 2775 2461 +2729 2773 2461 +2729 2774 2466 +2728 2776 2478 +2729 2777 2494 +2725 2779 2509 +2723 2779 2533 +2725 2779 2571 +2728 2783 2631 +2735 2789 2705 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2727 2773 2456 +2727 2773 2456 +2727 2773 2456 +2727 2774 2457 +2727 2774 2457 +2727 2774 2457 +2727 2774 2458 +2728 2774 2459 +2728 2775 2460 +2728 2775 2461 +2728 2775 2461 +2728 2775 2461 +2728 2775 2461 +2729 2773 2461 +2729 2774 2466 +2728 2776 2478 +2729 2777 2494 +2725 2779 2509 +2723 2779 2533 +2725 2779 2571 +2728 2783 2631 +2735 2789 2705 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2727 2773 2456 +2727 2773 2456 +2727 2773 2456 +2727 2774 2457 +2727 2774 2457 +2727 2774 2457 +2727 2774 2458 +2728 2774 2459 +2728 2775 2460 +2728 2775 2461 +2728 2775 2461 +2728 2775 2461 +2728 2775 2461 +2729 2773 2461 +2729 2774 2466 +2728 2776 2478 +2729 2777 2494 +2725 2779 2509 +2723 2779 2533 +2725 2779 2571 +2728 2783 2631 +2735 2789 2705 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2727 2773 2456 +2727 2773 2456 +2727 2773 2456 +2727 2774 2457 +2727 2774 2457 +2727 2774 2457 +2727 2774 2458 +2728 2774 2459 +2728 2775 2460 +2728 2775 2461 +2728 2775 2461 +2728 2775 2461 +2728 2775 2461 +2729 2773 2461 +2729 2774 2466 +2728 2776 2478 +2729 2777 2494 +2725 2779 2509 +2723 2779 2533 +2725 2779 2571 +2728 2783 2631 +2735 2789 2705 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2727 2773 2456 +2727 2773 2456 +2727 2773 2456 +2727 2774 2457 +2727 2774 2457 +2727 2774 2457 +2727 2774 2458 +2728 2774 2459 +2728 2775 2460 +2728 2775 2461 +2728 2775 2461 +2728 2775 2461 +2728 2775 2461 +2729 2773 2461 +2729 2774 2466 +2728 2776 2478 +2729 2777 2494 +2725 2779 2509 +2723 2779 2533 +2725 2779 2571 +2728 2783 2631 +2735 2789 2705 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2727 2773 2456 +2727 2773 2456 +2727 2773 2456 +2727 2774 2457 +2727 2774 2457 +2727 2774 2457 +2727 2774 2458 +2728 2774 2459 +2728 2775 2460 +2728 2775 2461 +2728 2775 2461 +2728 2775 2461 +2728 2775 2461 +2729 2773 2461 +2729 2774 2466 +2728 2776 2478 +2729 2777 2494 +2725 2779 2509 +2723 2779 2533 +2725 2779 2571 +2728 2783 2631 +2735 2789 2705 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2738 2796 2741 +2036 810 1881 +2036 808 1882 +2036 806 1882 +2036 803 1883 +2037 799 1884 +2037 794 1886 +2037 787 1887 +2038 777 1890 +2039 763 1894 +2040 745 1898 +2042 718 1904 +2043 681 1912 +2044 657 1923 +2037 657 1946 +2028 657 1974 +2025 726 2020 +2019 820 2081 +1994 874 2146 +1993 810 2228 +2002 0 2298 +2010 0 2382 +2069 0 2474 +2108 0 2510 +2108 0 2510 +2108 0 2510 +2108 0 2510 +2108 0 2510 +2108 0 2510 +2108 0 2510 +2108 0 2510 +2108 0 2510 +2108 0 2510 +2036 813 1881 +2036 813 1882 +2036 811 1883 +2036 808 1884 +2037 804 1884 +2037 799 1886 +2037 791 1888 +2038 782 1891 +2039 769 1894 +2040 750 1898 +2042 724 1905 +2043 687 1912 +2044 666 1924 +2037 666 1946 +2028 666 1974 +2024 730 2021 +2019 824 2081 +1994 876 2146 +1994 812 2228 +2002 0 2298 +2010 0 2382 +2069 0 2474 +2108 0 2510 +2108 0 2510 +2108 0 2510 +2108 0 2510 +2108 0 2510 +2108 0 2510 +2108 0 2510 +2108 0 2510 +2108 0 2510 +2108 0 2510 +2037 817 1881 +2036 817 1882 +2036 817 1883 +2036 814 1884 +2037 810 1885 +2037 805 1887 +2037 798 1888 +2038 789 1891 +2039 776 1894 +2040 757 1899 +2042 732 1905 +2043 695 1913 +2044 675 1924 +2037 678 1946 +2028 678 1974 +2024 735 2021 +2019 831 2081 +1994 877 2146 +1994 814 2228 +2002 0 2298 +2010 0 2382 +2069 0 2474 +2108 0 2510 +2108 0 2510 +2108 0 2510 +2108 0 2510 +2108 0 2510 +2108 0 2510 +2108 0 2510 +2108 0 2510 +2108 0 2510 +2108 0 2510 +2037 823 1882 +2037 823 1883 +2037 823 1884 +2036 823 1885 +2037 819 1886 +2037 814 1887 +2037 807 1889 +2038 797 1892 +2039 785 1895 +2040 767 1900 +2042 742 1906 +2043 706 1914 +2044 686 1925 +2038 693 1947 +2028 693 1975 +2024 742 2022 +2020 839 2082 +1995 880 2146 +1995 817 2228 +2003 0 2298 +2010 0 2382 +2069 0 2474 +2107 0 2510 +2107 0 2510 +2107 0 2510 +2107 0 2510 +2107 0 2510 +2107 0 2510 +2107 0 2510 +2107 0 2510 +2107 0 2510 +2107 0 2510 +2037 830 1882 +2037 830 1883 +2037 830 1884 +2037 830 1885 +2037 830 1887 +2037 825 1888 +2037 818 1891 +2038 809 1893 +2039 797 1897 +2040 779 1901 +2042 755 1907 +2043 721 1915 +2044 701 1926 +2038 713 1948 +2029 713 1976 +2024 751 2023 +2020 850 2082 +1995 883 2147 +1996 821 2228 +2004 0 2298 +2011 0 2383 +2069 0 2474 +2107 61 2510 +2107 61 2510 +2107 61 2510 +2107 61 2510 +2107 61 2510 +2107 61 2510 +2107 61 2510 +2107 61 2510 +2107 61 2510 +2107 61 2510 +2038 840 1883 +2038 840 1884 +2038 840 1884 +2037 840 1886 +2037 840 1887 +2037 840 1890 +2037 833 1892 +2038 825 1894 +2039 813 1898 +2040 796 1902 +2042 772 1908 +2043 739 1916 +2044 721 1927 +2038 737 1950 +2029 737 1977 +2023 762 2025 +2021 864 2083 +1996 888 2147 +1997 826 2228 +2005 48 2298 +2011 0 2383 +2069 10 2474 +2105 179 2510 +2105 179 2510 +2105 179 2510 +2105 179 2510 +2105 179 2510 +2105 179 2510 +2105 179 2510 +2105 179 2510 +2105 179 2510 +2105 179 2510 +2039 853 1883 +2039 853 1884 +2039 853 1885 +2038 853 1887 +2038 853 1888 +2038 853 1891 +2037 853 1894 +2038 844 1896 +2039 833 1900 +2040 817 1904 +2042 794 1910 +2043 763 1918 +2044 745 1929 +2039 769 1951 +2029 769 1979 +2023 777 2027 +2022 882 2084 +1997 894 2148 +1998 832 2227 +2006 147 2298 +2011 89 2384 +2069 84 2473 +2104 299 2510 +2104 299 2510 +2104 299 2510 +2104 299 2510 +2104 299 2510 +2104 299 2510 +2104 299 2510 +2104 299 2510 +2104 299 2510 +2104 299 2510 +2040 869 1884 +2040 869 1885 +2040 869 1886 +2040 869 1887 +2039 869 1889 +2039 869 1891 +2039 869 1894 +2038 869 1899 +2039 858 1902 +2040 843 1907 +2042 822 1913 +2043 792 1920 +2044 776 1932 +2039 807 1954 +2030 807 1981 +2022 797 2029 +2023 905 2085 +1998 901 2149 +2000 841 2227 +2007 253 2298 +2012 208 2384 +2069 167 2473 +2103 423 2510 +2103 423 2510 +2103 423 2510 +2103 423 2510 +2103 423 2510 +2103 423 2510 +2103 423 2510 +2103 423 2510 +2103 423 2510 +2103 423 2510 +2042 890 1885 +2042 890 1886 +2042 890 1887 +2041 890 1888 +2041 890 1890 +2041 890 1893 +2040 890 1896 +2040 890 1900 +2039 890 1905 +2040 876 1910 +2042 857 1916 +2043 829 1924 +2044 814 1935 +2040 854 1957 +2031 854 1984 +2021 822 2032 +2025 934 2086 +2000 911 2150 +2003 852 2226 +2009 364 2298 +2013 329 2385 +2069 258 2473 +2101 548 2511 +2101 548 2511 +2101 548 2511 +2101 548 2511 +2101 548 2511 +2101 548 2511 +2101 548 2511 +2101 548 2511 +2101 548 2511 +2101 548 2511 +2044 917 1887 +2044 917 1887 +2044 917 1889 +2043 917 1890 +2043 917 1892 +2043 917 1894 +2042 917 1897 +2042 917 1901 +2041 917 1907 +2040 917 1914 +2042 899 1920 +2043 874 1928 +2044 861 1939 +2041 906 1961 +2032 910 1988 +2020 853 2037 +2024 959 2090 +2002 924 2152 +2007 867 2226 +2011 480 2298 +2014 453 2386 +2069 358 2472 +2098 675 2511 +2098 675 2511 +2098 675 2511 +2098 675 2511 +2098 675 2511 +2098 675 2511 +2098 675 2511 +2098 675 2511 +2098 675 2511 +2098 675 2511 +2047 951 1889 +2047 951 1890 +2047 951 1891 +2047 951 1892 +2046 951 1894 +2046 951 1896 +2045 951 1899 +2045 951 1903 +2044 951 1909 +2043 951 1916 +2042 951 1926 +2043 928 1933 +2044 916 1944 +2041 956 1966 +2033 976 1993 +2021 913 2042 +2022 990 2095 +2006 968 2154 +2012 886 2225 +2014 599 2298 +2016 579 2387 +2069 463 2472 +2094 803 2512 +2094 803 2512 +2094 803 2512 +2094 803 2512 +2094 803 2512 +2094 803 2512 +2094 803 2512 +2094 803 2512 +2094 803 2512 +2094 803 2512 +2051 992 1892 +2051 992 1892 +2051 992 1894 +2050 992 1895 +2050 992 1897 +2050 992 1899 +2049 992 1902 +2049 992 1906 +2048 992 1912 +2047 992 1919 +2045 992 1928 +2043 992 1941 +2044 981 1951 +2041 1016 1973 +2035 1052 1999 +2023 999 2048 +2020 1028 2102 +2010 1027 2157 +2018 910 2223 +2019 722 2298 +2019 682 2389 +2069 575 2471 +2089 933 2513 +2089 933 2513 +2089 933 2513 +2089 933 2513 +2089 933 2513 +2089 933 2513 +2089 933 2513 +2089 933 2513 +2089 933 2513 +2089 933 2513 +2055 1051 1898 +2055 1052 1899 +2055 1052 1900 +2055 1052 1902 +2054 1052 1903 +2054 1052 1905 +2054 1052 1909 +2053 1052 1913 +2052 1052 1918 +2051 1052 1925 +2050 1052 1935 +2048 1052 1947 +2047 1053 1963 +2043 1083 1983 +2038 1120 2010 +2027 1089 2055 +2019 1074 2110 +2016 1091 2162 +2024 958 2224 +2023 859 2299 +2024 795 2391 +2069 729 2471 +2085 1046 2513 +2085 1046 2513 +2085 1046 2513 +2085 1046 2513 +2085 1046 2513 +2085 1046 2513 +2085 1046 2513 +2085 1046 2513 +2085 1046 2513 +2085 1046 2513 +2065 1109 1913 +2065 1110 1913 +2065 1112 1915 +2065 1113 1916 +2064 1115 1918 +2063 1118 1921 +2063 1121 1924 +2061 1126 1929 +2060 1132 1936 +2058 1137 1943 +2057 1137 1952 +2055 1137 1964 +2053 1137 1979 +2053 1164 1999 +2049 1195 2025 +2041 1167 2059 +2028 1112 2110 +2027 1145 2168 +2024 1061 2228 +2023 1050 2301 +2024 973 2387 +2069 983 2473 +2092 1159 2513 +2092 1159 2513 +2092 1159 2513 +2092 1159 2513 +2092 1159 2513 +2092 1159 2513 +2092 1159 2513 +2092 1159 2513 +2092 1159 2513 +2092 1159 2513 +2079 1177 1931 +2078 1178 1932 +2078 1179 1933 +2078 1180 1934 +2077 1182 1936 +2077 1184 1939 +2076 1187 1942 +2075 1191 1947 +2073 1196 1953 +2071 1204 1961 +2068 1213 1971 +2065 1225 1985 +2062 1230 2000 +2062 1252 2020 +2062 1280 2044 +2056 1256 2073 +2047 1209 2114 +2037 1182 2169 +2024 1169 2235 +2023 1221 2303 +2029 1152 2384 +2060 1207 2475 +2100 1275 2513 +2100 1275 2513 +2100 1275 2513 +2100 1275 2513 +2100 1275 2513 +2100 1275 2513 +2100 1275 2513 +2100 1275 2513 +2100 1275 2513 +2100 1275 2513 +2099 1357 1955 +2099 1357 1955 +2099 1357 1955 +2099 1357 1956 +2098 1357 1957 +2098 1357 1958 +2097 1357 1960 +2096 1357 1962 +2094 1357 1965 +2093 1357 1969 +2090 1361 1977 +2086 1370 1990 +2083 1381 2008 +2080 1396 2034 +2079 1416 2059 +2078 1420 2093 +2067 1399 2124 +2059 1381 2174 +2045 1359 2234 +2030 1417 2304 +2051 1393 2388 +2070 1417 2476 +2115 1452 2513 +2115 1452 2513 +2115 1452 2513 +2115 1452 2513 +2115 1452 2513 +2115 1452 2513 +2115 1452 2513 +2115 1452 2513 +2115 1452 2513 +2115 1452 2513 +2118 1561 1978 +2118 1561 1978 +2118 1561 1979 +2118 1561 1980 +2119 1561 1982 +2119 1561 1984 +2119 1561 1986 +2120 1561 1990 +2120 1561 1994 +2119 1561 1998 +2116 1561 2003 +2113 1561 2009 +2109 1560 2018 +2103 1553 2032 +2099 1566 2064 +2098 1570 2096 +2095 1587 2145 +2080 1579 2177 +2077 1562 2236 +2046 1604 2305 +2071 1614 2389 +2114 1600 2477 +2143 1637 2513 +2143 1637 2513 +2143 1637 2513 +2143 1637 2513 +2143 1637 2513 +2143 1637 2513 +2143 1637 2513 +2143 1637 2513 +2143 1637 2513 +2143 1637 2513 +2134 1765 2000 +2134 1765 2001 +2134 1766 2001 +2134 1766 2002 +2134 1767 2003 +2134 1767 2004 +2134 1768 2005 +2134 1769 2007 +2134 1771 2010 +2134 1772 2014 +2135 1773 2021 +2137 1773 2031 +2138 1773 2045 +2138 1767 2062 +2131 1758 2076 +2129 1756 2098 +2124 1756 2137 +2121 1783 2193 +2113 1774 2243 +2086 1783 2307 +2096 1787 2390 +2148 1816 2480 +2194 1817 2514 +2194 1817 2514 +2194 1817 2514 +2194 1817 2514 +2194 1817 2514 +2194 1817 2514 +2194 1817 2514 +2194 1817 2514 +2194 1817 2514 +2194 1817 2514 +2181 1956 2056 +2181 1956 2057 +2181 1956 2057 +2182 1956 2057 +2182 1955 2057 +2182 1955 2057 +2182 1955 2058 +2183 1954 2058 +2183 1953 2059 +2184 1951 2060 +2185 1950 2062 +2187 1947 2063 +2188 1945 2068 +2188 1950 2081 +2188 1955 2098 +2191 1957 2124 +2187 1958 2158 +2166 1958 2197 +2157 1958 2256 +2157 1958 2315 +2170 1965 2391 +2214 1983 2481 +2243 1992 2520 +2243 1992 2520 +2243 1992 2520 +2243 1992 2520 +2243 1992 2520 +2243 1992 2520 +2243 1992 2520 +2243 1992 2520 +2243 1992 2520 +2243 1992 2520 +2280 2135 2094 +2279 2135 2094 +2279 2135 2094 +2279 2135 2093 +2279 2135 2093 +2279 2135 2093 +2278 2135 2093 +2278 2135 2092 +2278 2135 2091 +2277 2135 2090 +2276 2135 2089 +2275 2135 2087 +2273 2135 2088 +2271 2132 2104 +2268 2128 2124 +2265 2127 2141 +2261 2127 2163 +2267 2131 2204 +2267 2143 2274 +2279 2151 2326 +2302 2151 2402 +2336 2169 2486 +2365 2174 2524 +2365 2174 2524 +2365 2174 2524 +2365 2174 2524 +2365 2174 2524 +2365 2174 2524 +2365 2174 2524 +2365 2174 2524 +2365 2174 2524 +2365 2174 2524 +2461 2367 2129 +2461 2367 2129 +2461 2367 2129 +2460 2367 2129 +2460 2367 2129 +2460 2367 2129 +2460 2367 2129 +2459 2367 2129 +2458 2367 2129 +2457 2367 2129 +2456 2367 2129 +2456 2367 2131 +2456 2368 2135 +2457 2370 2144 +2458 2370 2155 +2459 2368 2173 +2458 2367 2191 +2459 2372 2228 +2457 2374 2273 +2469 2375 2338 +2498 2390 2405 +2539 2403 2489 +2561 2413 2521 +2561 2413 2521 +2561 2413 2521 +2561 2413 2521 +2561 2413 2521 +2561 2413 2521 +2561 2413 2521 +2561 2413 2521 +2561 2413 2521 +2561 2413 2521 +2709 2666 2040 +2709 2666 2040 +2709 2665 2040 +2709 2665 2040 +2709 2665 2040 +2709 2665 2040 +2709 2665 2040 +2710 2664 2040 +2710 2664 2039 +2710 2664 2038 +2710 2664 2037 +2710 2663 2035 +2710 2663 2036 +2709 2665 2056 +2708 2668 2074 +2708 2667 2090 +2708 2666 2122 +2710 2669 2190 +2713 2675 2273 +2712 2672 2336 +2722 2681 2446 +2732 2688 2548 +2743 2699 2604 +2743 2699 2604 +2743 2699 2604 +2743 2699 2604 +2743 2699 2604 +2743 2699 2604 +2743 2699 2604 +2743 2699 2604 +2743 2699 2604 +2743 2699 2604 +2736 2777 2472 +2736 2777 2472 +2736 2777 2472 +2736 2777 2473 +2736 2778 2473 +2736 2778 2473 +2736 2778 2473 +2736 2778 2474 +2736 2778 2475 +2736 2778 2475 +2736 2779 2476 +2736 2779 2478 +2736 2779 2480 +2736 2779 2480 +2736 2779 2480 +2737 2778 2487 +2736 2777 2497 +2732 2777 2512 +2731 2783 2550 +2734 2783 2585 +2737 2787 2644 +2741 2798 2718 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2736 2777 2472 +2736 2777 2472 +2736 2777 2472 +2736 2777 2473 +2736 2778 2473 +2736 2778 2473 +2736 2778 2473 +2736 2778 2474 +2736 2778 2475 +2736 2778 2475 +2736 2779 2476 +2736 2779 2478 +2736 2779 2480 +2736 2779 2480 +2736 2779 2480 +2737 2778 2487 +2736 2777 2497 +2732 2777 2512 +2731 2783 2550 +2734 2783 2585 +2737 2787 2644 +2741 2798 2718 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2736 2777 2472 +2736 2777 2472 +2736 2777 2472 +2736 2777 2473 +2736 2778 2473 +2736 2778 2473 +2736 2778 2473 +2736 2778 2474 +2736 2778 2475 +2736 2778 2475 +2736 2779 2476 +2736 2779 2478 +2736 2779 2480 +2736 2779 2480 +2736 2779 2480 +2737 2778 2487 +2736 2777 2497 +2732 2777 2512 +2731 2783 2550 +2734 2783 2585 +2737 2787 2644 +2741 2798 2718 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2736 2777 2472 +2736 2777 2472 +2736 2777 2472 +2736 2777 2473 +2736 2778 2473 +2736 2778 2473 +2736 2778 2473 +2736 2778 2474 +2736 2778 2475 +2736 2778 2475 +2736 2779 2476 +2736 2779 2478 +2736 2779 2480 +2736 2779 2480 +2736 2779 2480 +2737 2778 2487 +2736 2777 2497 +2732 2777 2512 +2731 2783 2550 +2734 2783 2585 +2737 2787 2644 +2741 2798 2718 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2736 2777 2472 +2736 2777 2472 +2736 2777 2472 +2736 2777 2473 +2736 2778 2473 +2736 2778 2473 +2736 2778 2473 +2736 2778 2474 +2736 2778 2475 +2736 2778 2475 +2736 2779 2476 +2736 2779 2478 +2736 2779 2480 +2736 2779 2480 +2736 2779 2480 +2737 2778 2487 +2736 2777 2497 +2732 2777 2512 +2731 2783 2550 +2734 2783 2585 +2737 2787 2644 +2741 2798 2718 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2736 2777 2472 +2736 2777 2472 +2736 2777 2472 +2736 2777 2473 +2736 2778 2473 +2736 2778 2473 +2736 2778 2473 +2736 2778 2474 +2736 2778 2475 +2736 2778 2475 +2736 2779 2476 +2736 2779 2478 +2736 2779 2480 +2736 2779 2480 +2736 2779 2480 +2737 2778 2487 +2736 2777 2497 +2732 2777 2512 +2731 2783 2550 +2734 2783 2585 +2737 2787 2644 +2741 2798 2718 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2736 2777 2472 +2736 2777 2472 +2736 2777 2472 +2736 2777 2473 +2736 2778 2473 +2736 2778 2473 +2736 2778 2473 +2736 2778 2474 +2736 2778 2475 +2736 2778 2475 +2736 2779 2476 +2736 2779 2478 +2736 2779 2480 +2736 2779 2480 +2736 2779 2480 +2737 2778 2487 +2736 2777 2497 +2732 2777 2512 +2731 2783 2550 +2734 2783 2585 +2737 2787 2644 +2741 2798 2718 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2736 2777 2472 +2736 2777 2472 +2736 2777 2472 +2736 2777 2473 +2736 2778 2473 +2736 2778 2473 +2736 2778 2473 +2736 2778 2474 +2736 2778 2475 +2736 2778 2475 +2736 2779 2476 +2736 2779 2478 +2736 2779 2480 +2736 2779 2480 +2736 2779 2480 +2737 2778 2487 +2736 2777 2497 +2732 2777 2512 +2731 2783 2550 +2734 2783 2585 +2737 2787 2644 +2741 2798 2718 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2736 2777 2472 +2736 2777 2472 +2736 2777 2472 +2736 2777 2473 +2736 2778 2473 +2736 2778 2473 +2736 2778 2473 +2736 2778 2474 +2736 2778 2475 +2736 2778 2475 +2736 2779 2476 +2736 2779 2478 +2736 2779 2480 +2736 2779 2480 +2736 2779 2480 +2737 2778 2487 +2736 2777 2497 +2732 2777 2512 +2731 2783 2550 +2734 2783 2585 +2737 2787 2644 +2741 2798 2718 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2736 2777 2472 +2736 2777 2472 +2736 2777 2472 +2736 2777 2473 +2736 2778 2473 +2736 2778 2473 +2736 2778 2473 +2736 2778 2474 +2736 2778 2475 +2736 2778 2475 +2736 2779 2476 +2736 2779 2478 +2736 2779 2480 +2736 2779 2480 +2736 2779 2480 +2737 2778 2487 +2736 2777 2497 +2732 2777 2512 +2731 2783 2550 +2734 2783 2585 +2737 2787 2644 +2741 2798 2718 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2746 2799 2749 +2203 0 1962 +2203 0 1963 +2203 0 1963 +2203 0 1964 +2202 0 1966 +2202 0 1967 +2202 0 1969 +2202 0 1972 +2201 0 1976 +2200 0 1981 +2199 0 1988 +2198 0 1996 +2196 0 2008 +2194 0 2027 +2190 0 2051 +2189 0 2090 +2187 0 2135 +2178 0 2178 +2160 0 2231 +2145 0 2305 +2169 0 2389 +2195 0 2474 +2191 934 2513 +2191 934 2513 +2191 934 2513 +2191 934 2513 +2191 934 2513 +2191 934 2513 +2191 934 2513 +2191 934 2513 +2191 934 2513 +2191 934 2513 +2203 0 1962 +2203 0 1963 +2203 0 1963 +2203 0 1965 +2202 0 1966 +2202 0 1967 +2202 0 1969 +2202 0 1972 +2201 0 1976 +2200 0 1981 +2199 0 1988 +2198 0 1997 +2196 0 2008 +2194 0 2027 +2190 0 2051 +2189 0 2090 +2187 0 2135 +2178 0 2178 +2160 0 2231 +2145 0 2305 +2169 0 2389 +2195 0 2474 +2191 935 2513 +2191 935 2513 +2191 935 2513 +2191 935 2513 +2191 935 2513 +2191 935 2513 +2191 935 2513 +2191 935 2513 +2191 935 2513 +2191 935 2513 +2203 0 1962 +2203 0 1963 +2203 0 1964 +2203 0 1965 +2202 0 1966 +2202 0 1968 +2202 0 1970 +2202 0 1973 +2201 0 1976 +2200 0 1981 +2199 0 1988 +2198 0 1997 +2196 0 2008 +2194 0 2026 +2190 0 2051 +2189 0 2090 +2187 0 2135 +2178 0 2178 +2161 0 2231 +2146 0 2305 +2169 0 2389 +2195 0 2474 +2191 937 2513 +2191 937 2513 +2191 937 2513 +2191 937 2513 +2191 937 2513 +2191 937 2513 +2191 937 2513 +2191 937 2513 +2191 937 2513 +2191 937 2513 +2203 0 1963 +2203 0 1963 +2203 0 1964 +2203 0 1965 +2202 0 1966 +2202 0 1968 +2202 0 1970 +2202 0 1973 +2201 0 1977 +2200 0 1982 +2199 0 1988 +2198 0 1997 +2196 0 2008 +2194 0 2026 +2190 0 2050 +2189 0 2090 +2187 0 2135 +2178 0 2178 +2161 0 2232 +2146 0 2305 +2169 0 2389 +2195 0 2474 +2192 939 2513 +2192 939 2513 +2192 939 2513 +2192 939 2513 +2192 939 2513 +2192 939 2513 +2192 939 2513 +2192 939 2513 +2192 939 2513 +2192 939 2513 +2202 0 1963 +2202 0 1963 +2202 0 1964 +2202 0 1965 +2202 0 1966 +2202 0 1968 +2202 0 1970 +2202 0 1973 +2201 0 1977 +2200 0 1982 +2199 0 1989 +2198 0 1997 +2196 0 2009 +2194 0 2026 +2190 0 2050 +2188 0 2090 +2187 0 2136 +2178 0 2178 +2161 0 2232 +2147 0 2305 +2169 0 2389 +2195 0 2474 +2192 942 2513 +2192 942 2513 +2192 942 2513 +2192 942 2513 +2192 942 2513 +2192 942 2513 +2192 942 2513 +2192 942 2513 +2192 942 2513 +2192 942 2513 +2202 0 1963 +2202 0 1964 +2202 0 1965 +2202 0 1966 +2202 0 1967 +2202 0 1969 +2202 0 1970 +2202 0 1973 +2201 0 1977 +2200 0 1982 +2199 0 1989 +2198 0 1998 +2196 0 2009 +2194 0 2026 +2190 0 2050 +2188 0 2090 +2187 0 2136 +2178 0 2178 +2162 0 2232 +2148 0 2305 +2169 0 2389 +2195 74 2474 +2193 946 2513 +2193 946 2513 +2193 946 2513 +2193 946 2513 +2193 946 2513 +2193 946 2513 +2193 946 2513 +2193 946 2513 +2193 946 2513 +2193 946 2513 +2202 0 1964 +2202 0 1965 +2202 0 1965 +2202 0 1966 +2202 0 1968 +2202 0 1969 +2202 0 1971 +2202 0 1974 +2201 0 1978 +2200 0 1983 +2199 0 1989 +2198 0 1998 +2196 0 2010 +2194 0 2025 +2190 0 2049 +2188 0 2090 +2187 0 2137 +2178 0 2178 +2162 0 2232 +2149 0 2305 +2168 0 2389 +2196 195 2474 +2194 951 2513 +2194 951 2513 +2194 951 2513 +2194 951 2513 +2194 951 2513 +2194 951 2513 +2194 951 2513 +2194 951 2513 +2194 951 2513 +2194 951 2513 +2202 0 1965 +2202 0 1965 +2202 0 1966 +2202 0 1967 +2202 0 1968 +2202 0 1970 +2202 0 1972 +2202 0 1975 +2201 0 1979 +2200 0 1984 +2199 0 1990 +2198 0 1999 +2196 0 2010 +2194 0 2024 +2190 0 2049 +2188 0 2090 +2187 0 2138 +2178 0 2178 +2163 0 2233 +2150 0 2306 +2168 0 2388 +2196 319 2474 +2195 957 2513 +2195 957 2513 +2195 957 2513 +2195 957 2513 +2195 957 2513 +2195 957 2513 +2195 957 2513 +2195 957 2513 +2195 957 2513 +2195 957 2513 +2201 0 1966 +2201 0 1966 +2201 0 1967 +2201 0 1968 +2201 0 1969 +2201 0 1971 +2201 0 1973 +2201 0 1976 +2201 0 1979 +2200 0 1984 +2199 0 1991 +2198 0 2000 +2196 0 2011 +2194 0 2024 +2190 0 2048 +2187 0 2090 +2187 0 2140 +2178 0 2178 +2165 0 2233 +2152 111 2306 +2167 0 2388 +2195 419 2475 +2197 966 2513 +2197 966 2513 +2197 966 2513 +2197 966 2513 +2197 966 2513 +2197 966 2513 +2197 966 2513 +2197 966 2513 +2197 966 2513 +2197 966 2513 +2200 0 1967 +2200 0 1968 +2200 0 1968 +2200 0 1969 +2200 0 1970 +2200 0 1972 +2200 0 1974 +2200 0 1977 +2200 0 1981 +2200 0 1986 +2199 0 1993 +2198 0 2001 +2196 0 2012 +2194 0 2023 +2190 0 2047 +2186 0 2090 +2186 0 2140 +2178 0 2178 +2166 0 2234 +2155 244 2307 +2166 0 2388 +2195 523 2475 +2199 978 2513 +2199 978 2513 +2199 978 2513 +2199 978 2513 +2199 978 2513 +2199 978 2513 +2199 978 2513 +2199 978 2513 +2199 978 2513 +2199 978 2513 +2199 0 1969 +2199 0 1969 +2199 0 1970 +2199 0 1971 +2199 0 1972 +2199 0 1974 +2199 0 1976 +2199 0 1979 +2199 0 1983 +2199 0 1988 +2199 0 1994 +2198 0 2003 +2196 0 2014 +2194 0 2025 +2190 0 2045 +2186 0 2089 +2185 0 2140 +2178 0 2180 +2169 0 2235 +2158 376 2308 +2165 61 2387 +2194 633 2476 +2202 993 2513 +2202 993 2513 +2202 993 2513 +2202 993 2513 +2202 993 2513 +2202 993 2513 +2202 993 2513 +2202 993 2513 +2202 993 2513 +2202 993 2513 +2198 0 1971 +2198 0 1972 +2198 0 1972 +2198 0 1973 +2198 0 1974 +2198 0 1976 +2198 0 1978 +2198 0 1981 +2198 0 1985 +2198 0 1990 +2198 0 1996 +2198 0 2005 +2196 0 2016 +2194 0 2027 +2190 0 2043 +2186 0 2087 +2183 0 2140 +2178 0 2183 +2172 0 2236 +2163 508 2309 +2167 263 2387 +2192 748 2476 +2206 1012 2513 +2206 1012 2513 +2206 1012 2513 +2206 1012 2513 +2206 1012 2513 +2206 1012 2513 +2206 1012 2513 +2206 1012 2513 +2206 1012 2513 +2206 1012 2513 +2197 0 1974 +2197 0 1974 +2197 0 1975 +2197 0 1976 +2197 0 1977 +2197 0 1979 +2197 0 1981 +2197 0 1984 +2197 0 1988 +2197 0 1993 +2197 0 1999 +2197 0 2008 +2196 0 2019 +2194 0 2030 +2190 0 2044 +2186 0 2085 +2183 0 2139 +2179 0 2186 +2175 0 2237 +2168 643 2310 +2170 532 2388 +2192 890 2477 +2211 1054 2513 +2211 1054 2513 +2211 1054 2513 +2211 1054 2513 +2211 1054 2513 +2211 1054 2513 +2211 1054 2513 +2211 1054 2513 +2211 1054 2513 +2211 1054 2513 +2200 621 1974 +2200 621 1974 +2200 621 1976 +2200 621 1977 +2200 621 1978 +2200 621 1980 +2201 621 1983 +2201 621 1986 +2202 621 1991 +2202 621 1997 +2202 621 2003 +2202 621 2012 +2202 617 2022 +2196 529 2033 +2193 529 2047 +2189 621 2082 +2185 627 2133 +2182 413 2189 +2177 708 2240 +2170 828 2310 +2173 948 2390 +2196 1121 2478 +2216 1189 2513 +2216 1189 2513 +2216 1189 2513 +2216 1189 2513 +2216 1189 2513 +2216 1189 2513 +2216 1189 2513 +2216 1189 2513 +2216 1189 2513 +2216 1189 2513 +2203 974 1974 +2203 974 1974 +2203 974 1976 +2203 974 1977 +2203 974 1978 +2204 974 1980 +2204 974 1983 +2204 974 1986 +2205 974 1991 +2206 974 1997 +2207 974 2005 +2208 974 2016 +2208 973 2027 +2203 934 2038 +2196 877 2052 +2192 934 2084 +2188 977 2129 +2185 874 2183 +2181 1059 2243 +2174 996 2310 +2175 1202 2391 +2206 1271 2478 +2222 1322 2513 +2222 1322 2513 +2222 1322 2513 +2222 1322 2513 +2222 1322 2513 +2222 1322 2513 +2222 1322 2513 +2222 1322 2513 +2222 1322 2513 +2222 1322 2513 +2208 1278 1984 +2208 1279 1985 +2208 1279 1986 +2208 1281 1986 +2209 1282 1987 +2209 1284 1988 +2209 1286 1990 +2209 1289 1992 +2210 1294 1995 +2211 1299 1998 +2212 1302 2005 +2213 1302 2016 +2214 1300 2030 +2212 1282 2047 +2206 1256 2063 +2201 1278 2090 +2194 1321 2134 +2193 1308 2182 +2182 1327 2241 +2178 1331 2310 +2182 1416 2391 +2214 1452 2477 +2228 1489 2513 +2228 1489 2513 +2228 1489 2513 +2228 1489 2513 +2228 1489 2513 +2228 1489 2513 +2228 1489 2513 +2228 1489 2513 +2228 1489 2513 +2228 1489 2513 +2220 1531 2004 +2220 1531 2004 +2220 1531 2004 +2220 1532 2005 +2220 1533 2006 +2220 1534 2007 +2220 1535 2008 +2220 1537 2010 +2220 1540 2013 +2221 1543 2017 +2222 1547 2021 +2223 1553 2027 +2224 1559 2037 +2222 1557 2051 +2218 1543 2073 +2214 1535 2102 +2208 1550 2140 +2199 1572 2190 +2195 1558 2240 +2192 1577 2310 +2192 1604 2393 +2223 1653 2476 +2238 1676 2514 +2238 1676 2514 +2238 1676 2514 +2238 1676 2514 +2238 1676 2514 +2238 1676 2514 +2238 1676 2514 +2238 1676 2514 +2238 1676 2514 +2238 1676 2514 +2241 1755 2023 +2241 1755 2023 +2241 1755 2024 +2241 1755 2024 +2241 1755 2025 +2241 1755 2025 +2241 1755 2026 +2241 1755 2028 +2241 1755 2029 +2241 1755 2031 +2241 1758 2036 +2241 1761 2042 +2240 1765 2049 +2240 1765 2063 +2238 1765 2080 +2237 1764 2104 +2229 1762 2147 +2223 1755 2193 +2223 1765 2244 +2223 1774 2315 +2215 1795 2391 +2250 1824 2482 +2262 1849 2517 +2262 1849 2517 +2262 1849 2517 +2262 1849 2517 +2262 1849 2517 +2262 1849 2517 +2262 1849 2517 +2262 1849 2517 +2262 1849 2517 +2262 1849 2517 +2268 1946 2048 +2268 1946 2049 +2269 1946 2049 +2269 1946 2050 +2269 1946 2051 +2269 1946 2051 +2270 1946 2053 +2270 1946 2054 +2270 1946 2057 +2271 1946 2060 +2272 1946 2064 +2273 1946 2070 +2274 1945 2077 +2274 1945 2087 +2274 1945 2099 +2271 1951 2124 +2268 1961 2158 +2265 1963 2203 +2273 1968 2256 +2261 1969 2321 +2271 1965 2394 +2310 1995 2482 +2335 2014 2520 +2335 2014 2520 +2335 2014 2520 +2335 2014 2520 +2335 2014 2520 +2335 2014 2520 +2335 2014 2520 +2335 2014 2520 +2335 2014 2520 +2335 2014 2520 +2351 2143 2087 +2351 2143 2087 +2351 2143 2087 +2351 2143 2088 +2351 2143 2088 +2351 2143 2089 +2351 2143 2091 +2351 2143 2092 +2351 2143 2094 +2351 2143 2097 +2351 2143 2101 +2351 2143 2106 +2351 2143 2112 +2351 2143 2115 +2351 2143 2119 +2351 2143 2141 +2349 2146 2174 +2346 2147 2214 +2351 2143 2263 +2356 2159 2326 +2362 2167 2401 +2402 2189 2492 +2434 2202 2530 +2434 2202 2530 +2434 2202 2530 +2434 2202 2530 +2434 2202 2530 +2434 2202 2530 +2434 2202 2530 +2434 2202 2530 +2434 2202 2530 +2434 2202 2530 +2515 2384 2126 +2514 2384 2127 +2514 2384 2127 +2514 2384 2127 +2514 2383 2127 +2514 2383 2127 +2514 2383 2128 +2514 2383 2128 +2514 2382 2129 +2513 2382 2130 +2513 2381 2131 +2513 2381 2133 +2514 2382 2135 +2515 2384 2141 +2515 2385 2150 +2515 2388 2172 +2515 2388 2195 +2520 2388 2230 +2523 2391 2279 +2523 2395 2342 +2548 2407 2404 +2582 2421 2483 +2607 2433 2514 +2607 2433 2514 +2607 2433 2514 +2607 2433 2514 +2607 2433 2514 +2607 2433 2514 +2607 2433 2514 +2607 2433 2514 +2607 2433 2514 +2607 2433 2514 +2731 2680 2128 +2731 2680 2129 +2731 2680 2129 +2731 2680 2130 +2731 2680 2131 +2731 2681 2132 +2731 2681 2133 +2731 2681 2135 +2731 2681 2136 +2730 2681 2137 +2730 2681 2138 +2729 2680 2140 +2728 2679 2142 +2728 2679 2150 +2730 2679 2164 +2731 2678 2176 +2730 2679 2195 +2730 2680 2243 +2735 2682 2308 +2735 2687 2382 +2739 2689 2468 +2750 2708 2581 +2756 2707 2625 +2756 2707 2625 +2756 2707 2625 +2756 2707 2625 +2756 2707 2625 +2756 2707 2625 +2756 2707 2625 +2756 2707 2625 +2756 2707 2625 +2756 2707 2625 +2755 2784 2495 +2755 2784 2495 +2755 2784 2495 +2755 2784 2496 +2755 2784 2496 +2755 2784 2496 +2755 2784 2497 +2755 2784 2498 +2755 2785 2499 +2755 2785 2501 +2755 2786 2503 +2755 2786 2506 +2755 2787 2509 +2755 2787 2512 +2755 2787 2515 +2754 2787 2520 +2753 2788 2528 +2753 2787 2543 +2751 2785 2569 +2749 2789 2602 +2753 2795 2660 +2755 2801 2726 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2755 2784 2495 +2755 2784 2495 +2755 2784 2495 +2755 2784 2496 +2755 2784 2496 +2755 2784 2496 +2755 2784 2497 +2755 2784 2498 +2755 2785 2499 +2755 2785 2501 +2755 2786 2503 +2755 2786 2506 +2755 2787 2509 +2755 2787 2512 +2755 2787 2515 +2754 2787 2520 +2753 2788 2528 +2753 2787 2543 +2751 2785 2569 +2749 2789 2602 +2753 2795 2660 +2755 2801 2726 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2755 2784 2495 +2755 2784 2495 +2755 2784 2495 +2755 2784 2496 +2755 2784 2496 +2755 2784 2496 +2755 2784 2497 +2755 2784 2498 +2755 2785 2499 +2755 2785 2501 +2755 2786 2503 +2755 2786 2506 +2755 2787 2509 +2755 2787 2512 +2755 2787 2515 +2754 2787 2520 +2753 2788 2528 +2753 2787 2543 +2751 2785 2569 +2749 2789 2602 +2753 2795 2660 +2755 2801 2726 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2755 2784 2495 +2755 2784 2495 +2755 2784 2495 +2755 2784 2496 +2755 2784 2496 +2755 2784 2496 +2755 2784 2497 +2755 2784 2498 +2755 2785 2499 +2755 2785 2501 +2755 2786 2503 +2755 2786 2506 +2755 2787 2509 +2755 2787 2512 +2755 2787 2515 +2754 2787 2520 +2753 2788 2528 +2753 2787 2543 +2751 2785 2569 +2749 2789 2602 +2753 2795 2660 +2755 2801 2726 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2755 2784 2495 +2755 2784 2495 +2755 2784 2495 +2755 2784 2496 +2755 2784 2496 +2755 2784 2496 +2755 2784 2497 +2755 2784 2498 +2755 2785 2499 +2755 2785 2501 +2755 2786 2503 +2755 2786 2506 +2755 2787 2509 +2755 2787 2512 +2755 2787 2515 +2754 2787 2520 +2753 2788 2528 +2753 2787 2543 +2751 2785 2569 +2749 2789 2602 +2753 2795 2660 +2755 2801 2726 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2755 2784 2495 +2755 2784 2495 +2755 2784 2495 +2755 2784 2496 +2755 2784 2496 +2755 2784 2496 +2755 2784 2497 +2755 2784 2498 +2755 2785 2499 +2755 2785 2501 +2755 2786 2503 +2755 2786 2506 +2755 2787 2509 +2755 2787 2512 +2755 2787 2515 +2754 2787 2520 +2753 2788 2528 +2753 2787 2543 +2751 2785 2569 +2749 2789 2602 +2753 2795 2660 +2755 2801 2726 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2755 2784 2495 +2755 2784 2495 +2755 2784 2495 +2755 2784 2496 +2755 2784 2496 +2755 2784 2496 +2755 2784 2497 +2755 2784 2498 +2755 2785 2499 +2755 2785 2501 +2755 2786 2503 +2755 2786 2506 +2755 2787 2509 +2755 2787 2512 +2755 2787 2515 +2754 2787 2520 +2753 2788 2528 +2753 2787 2543 +2751 2785 2569 +2749 2789 2602 +2753 2795 2660 +2755 2801 2726 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2755 2784 2495 +2755 2784 2495 +2755 2784 2495 +2755 2784 2496 +2755 2784 2496 +2755 2784 2496 +2755 2784 2497 +2755 2784 2498 +2755 2785 2499 +2755 2785 2501 +2755 2786 2503 +2755 2786 2506 +2755 2787 2509 +2755 2787 2512 +2755 2787 2515 +2754 2787 2520 +2753 2788 2528 +2753 2787 2543 +2751 2785 2569 +2749 2789 2602 +2753 2795 2660 +2755 2801 2726 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2755 2784 2495 +2755 2784 2495 +2755 2784 2495 +2755 2784 2496 +2755 2784 2496 +2755 2784 2496 +2755 2784 2497 +2755 2784 2498 +2755 2785 2499 +2755 2785 2501 +2755 2786 2503 +2755 2786 2506 +2755 2787 2509 +2755 2787 2512 +2755 2787 2515 +2754 2787 2520 +2753 2788 2528 +2753 2787 2543 +2751 2785 2569 +2749 2789 2602 +2753 2795 2660 +2755 2801 2726 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2755 2784 2495 +2755 2784 2495 +2755 2784 2495 +2755 2784 2496 +2755 2784 2496 +2755 2784 2496 +2755 2784 2497 +2755 2784 2498 +2755 2785 2499 +2755 2785 2501 +2755 2786 2503 +2755 2786 2506 +2755 2787 2509 +2755 2787 2512 +2755 2787 2515 +2754 2787 2520 +2753 2788 2528 +2753 2787 2543 +2751 2785 2569 +2749 2789 2602 +2753 2795 2660 +2755 2801 2726 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2757 2802 2755 +2331 0 2000 +2331 0 2000 +2331 0 2001 +2331 0 2001 +2331 0 2002 +2331 0 2003 +2331 0 2005 +2331 0 2007 +2331 0 2010 +2331 0 2013 +2331 0 2018 +2331 0 2024 +2330 0 2034 +2326 0 2051 +2322 0 2072 +2321 0 2094 +2320 0 2138 +2314 0 2186 +2319 0 2244 +2315 0 2315 +2317 0 2391 +2334 913 2480 +2348 1255 2518 +2348 1255 2518 +2348 1255 2518 +2348 1255 2518 +2348 1255 2518 +2348 1255 2518 +2348 1255 2518 +2348 1255 2518 +2348 1255 2518 +2348 1255 2518 +2331 0 2000 +2331 0 2000 +2331 0 2001 +2331 0 2001 +2331 0 2002 +2331 0 2003 +2331 0 2005 +2331 0 2007 +2331 0 2010 +2331 0 2013 +2331 0 2018 +2331 0 2024 +2330 0 2034 +2326 0 2051 +2322 0 2072 +2321 0 2094 +2320 0 2138 +2315 0 2186 +2319 0 2245 +2315 0 2315 +2317 0 2392 +2334 917 2480 +2348 1256 2518 +2348 1256 2518 +2348 1256 2518 +2348 1256 2518 +2348 1256 2518 +2348 1256 2518 +2348 1256 2518 +2348 1256 2518 +2348 1256 2518 +2348 1256 2518 +2331 0 2000 +2331 0 2000 +2331 0 2001 +2331 0 2001 +2331 0 2002 +2331 0 2003 +2331 0 2005 +2331 0 2007 +2331 0 2010 +2331 0 2013 +2331 0 2018 +2330 0 2024 +2329 0 2034 +2326 0 2051 +2322 0 2072 +2321 0 2095 +2320 0 2138 +2315 0 2186 +2319 0 2245 +2315 0 2315 +2317 0 2392 +2334 922 2479 +2348 1258 2518 +2348 1258 2518 +2348 1258 2518 +2348 1258 2518 +2348 1258 2518 +2348 1258 2518 +2348 1258 2518 +2348 1258 2518 +2348 1258 2518 +2348 1258 2518 +2331 0 2000 +2331 0 2000 +2331 0 2001 +2331 0 2001 +2331 0 2002 +2331 0 2003 +2331 0 2005 +2331 0 2007 +2331 0 2010 +2331 0 2013 +2331 0 2018 +2330 0 2024 +2329 0 2034 +2326 0 2052 +2322 0 2072 +2321 0 2095 +2321 0 2138 +2315 0 2186 +2319 0 2245 +2315 0 2315 +2317 0 2392 +2334 929 2479 +2348 1260 2518 +2348 1260 2518 +2348 1260 2518 +2348 1260 2518 +2348 1260 2518 +2348 1260 2518 +2348 1260 2518 +2348 1260 2518 +2348 1260 2518 +2348 1260 2518 +2331 0 2000 +2331 0 2000 +2331 0 2001 +2331 0 2001 +2331 0 2002 +2331 0 2003 +2331 0 2005 +2331 0 2007 +2331 0 2010 +2331 0 2013 +2331 0 2018 +2330 0 2024 +2329 0 2034 +2326 0 2052 +2322 0 2072 +2321 0 2095 +2321 0 2138 +2315 0 2186 +2319 0 2245 +2315 0 2315 +2317 0 2392 +2334 938 2479 +2349 1263 2518 +2349 1263 2518 +2349 1263 2518 +2349 1263 2518 +2349 1263 2518 +2349 1263 2518 +2349 1263 2518 +2349 1263 2518 +2349 1263 2518 +2349 1263 2518 +2331 0 2000 +2331 0 2000 +2331 0 2001 +2331 0 2001 +2330 0 2002 +2330 0 2003 +2330 0 2005 +2330 0 2007 +2330 0 2010 +2330 0 2013 +2330 0 2018 +2330 0 2024 +2329 0 2034 +2326 0 2052 +2322 0 2073 +2321 0 2095 +2322 0 2138 +2315 0 2186 +2318 0 2245 +2315 30 2315 +2317 0 2392 +2334 949 2479 +2349 1267 2518 +2349 1267 2518 +2349 1267 2518 +2349 1267 2518 +2349 1267 2518 +2349 1267 2518 +2349 1267 2518 +2349 1267 2518 +2349 1267 2518 +2349 1267 2518 +2331 0 2000 +2330 0 2000 +2330 0 2001 +2330 0 2001 +2330 0 2002 +2330 0 2003 +2330 0 2005 +2330 0 2007 +2330 0 2010 +2330 0 2013 +2330 0 2018 +2329 0 2024 +2328 0 2034 +2327 0 2053 +2323 0 2073 +2321 0 2096 +2322 0 2139 +2315 0 2186 +2318 0 2245 +2315 163 2315 +2317 32 2392 +2334 964 2478 +2350 1272 2518 +2350 1272 2518 +2350 1272 2518 +2350 1272 2518 +2350 1272 2518 +2350 1272 2518 +2350 1272 2518 +2350 1272 2518 +2350 1272 2518 +2350 1272 2518 +2330 0 2000 +2330 0 2000 +2330 0 2001 +2330 0 2001 +2330 0 2002 +2330 0 2003 +2329 0 2005 +2329 0 2007 +2329 0 2010 +2329 0 2013 +2329 0 2018 +2328 0 2024 +2327 0 2034 +2327 0 2053 +2323 0 2073 +2321 0 2096 +2323 0 2139 +2316 0 2186 +2318 0 2246 +2315 295 2315 +2317 164 2393 +2334 983 2478 +2351 1279 2518 +2351 1279 2518 +2351 1279 2518 +2351 1279 2518 +2351 1279 2518 +2351 1279 2518 +2351 1279 2518 +2351 1279 2518 +2351 1279 2518 +2351 1279 2518 +2330 0 2000 +2330 0 2000 +2330 0 2001 +2330 0 2001 +2329 0 2002 +2329 0 2003 +2329 0 2005 +2329 0 2007 +2328 0 2010 +2328 0 2013 +2328 0 2018 +2328 0 2024 +2327 0 2034 +2327 0 2054 +2323 0 2074 +2321 0 2097 +2325 0 2140 +2316 0 2186 +2317 111 2246 +2315 426 2315 +2317 296 2393 +2334 993 2478 +2352 1288 2518 +2352 1288 2518 +2352 1288 2518 +2352 1288 2518 +2352 1288 2518 +2352 1288 2518 +2352 1288 2518 +2352 1288 2518 +2352 1288 2518 +2352 1288 2518 +2329 0 2000 +2329 0 2000 +2329 0 2001 +2329 0 2001 +2329 0 2002 +2329 0 2003 +2328 0 2005 +2328 0 2007 +2328 0 2010 +2327 0 2013 +2327 0 2018 +2326 0 2024 +2325 0 2034 +2327 0 2055 +2324 0 2075 +2321 0 2098 +2325 0 2141 +2317 0 2186 +2317 244 2247 +2315 559 2315 +2317 428 2393 +2335 1003 2479 +2354 1300 2518 +2354 1300 2518 +2354 1300 2518 +2354 1300 2518 +2354 1300 2518 +2354 1300 2518 +2354 1300 2518 +2354 1300 2518 +2354 1300 2518 +2354 1300 2518 +2328 0 2000 +2328 0 2000 +2328 0 2001 +2328 0 2001 +2328 0 2002 +2328 0 2003 +2328 0 2005 +2327 0 2007 +2327 0 2010 +2326 0 2013 +2325 0 2018 +2325 0 2024 +2324 0 2034 +2326 0 2055 +2325 61 2077 +2322 0 2099 +2325 0 2142 +2319 0 2187 +2316 376 2248 +2315 691 2315 +2317 560 2394 +2337 1018 2479 +2356 1315 2518 +2356 1315 2518 +2356 1315 2518 +2356 1315 2518 +2356 1315 2518 +2356 1315 2518 +2356 1315 2518 +2356 1315 2518 +2356 1315 2518 +2356 1315 2518 +2328 0 2000 +2328 0 2000 +2328 0 2001 +2328 0 2001 +2328 0 2002 +2327 0 2003 +2327 0 2005 +2327 0 2007 +2326 0 2010 +2326 0 2013 +2325 0 2018 +2325 0 2027 +2324 0 2036 +2326 0 2057 +2327 111 2081 +2323 0 2103 +2324 0 2142 +2322 0 2190 +2315 426 2247 +2315 741 2315 +2319 692 2394 +2338 1091 2481 +2357 1322 2518 +2357 1322 2518 +2357 1322 2518 +2357 1322 2518 +2357 1322 2518 +2357 1322 2518 +2357 1322 2518 +2357 1322 2518 +2357 1322 2518 +2357 1322 2518 +2328 0 2000 +2328 0 2001 +2328 0 2001 +2328 0 2002 +2328 0 2003 +2328 0 2004 +2328 0 2006 +2327 0 2008 +2327 0 2011 +2326 0 2014 +2326 0 2019 +2325 0 2028 +2325 0 2040 +2327 44 2061 +2328 216 2085 +2326 0 2109 +2323 0 2139 +2324 123 2193 +2314 517 2247 +2316 765 2314 +2321 843 2393 +2340 1204 2482 +2357 1332 2518 +2357 1332 2518 +2357 1332 2518 +2357 1332 2518 +2357 1332 2518 +2357 1332 2518 +2357 1332 2518 +2357 1332 2518 +2357 1332 2518 +2357 1332 2518 +2332 614 2005 +2332 614 2005 +2332 614 2006 +2332 614 2007 +2332 614 2008 +2332 614 2009 +2331 614 2011 +2331 614 2014 +2331 614 2017 +2330 614 2021 +2329 614 2026 +2329 614 2035 +2329 614 2047 +2329 614 2057 +2330 670 2082 +2328 727 2109 +2321 757 2137 +2324 709 2196 +2318 901 2249 +2318 868 2316 +2319 1072 2391 +2342 1300 2483 +2357 1409 2519 +2357 1409 2519 +2357 1409 2519 +2357 1409 2519 +2357 1409 2519 +2357 1409 2519 +2357 1409 2519 +2357 1409 2519 +2357 1409 2519 +2357 1409 2519 +2336 924 2012 +2336 924 2013 +2336 924 2013 +2336 924 2014 +2335 924 2015 +2335 924 2017 +2335 924 2019 +2335 924 2021 +2335 924 2024 +2334 924 2029 +2333 924 2035 +2333 924 2042 +2333 924 2052 +2333 924 2063 +2333 971 2080 +2330 1020 2108 +2324 1065 2141 +2325 1052 2197 +2321 1173 2253 +2319 1077 2317 +2317 1227 2391 +2345 1377 2483 +2359 1509 2521 +2359 1509 2521 +2359 1509 2521 +2359 1509 2521 +2359 1509 2521 +2359 1509 2521 +2359 1509 2521 +2359 1509 2521 +2359 1509 2521 +2359 1509 2521 +2339 1291 2020 +2339 1291 2020 +2339 1290 2020 +2339 1289 2020 +2339 1288 2021 +2339 1286 2022 +2338 1283 2023 +2338 1280 2024 +2338 1276 2026 +2337 1270 2028 +2336 1267 2033 +2336 1267 2040 +2336 1269 2048 +2336 1288 2065 +2336 1315 2084 +2334 1351 2116 +2331 1343 2151 +2330 1343 2198 +2326 1378 2257 +2319 1407 2317 +2328 1414 2394 +2350 1546 2482 +2368 1608 2518 +2368 1608 2518 +2368 1608 2518 +2368 1608 2518 +2368 1608 2518 +2368 1608 2518 +2368 1608 2518 +2368 1608 2518 +2368 1608 2518 +2368 1608 2518 +2349 1557 2025 +2349 1557 2025 +2349 1557 2025 +2349 1557 2026 +2348 1557 2026 +2348 1557 2027 +2348 1557 2028 +2348 1557 2029 +2347 1557 2031 +2347 1554 2033 +2346 1550 2036 +2345 1548 2041 +2344 1548 2050 +2344 1550 2067 +2343 1557 2089 +2339 1571 2115 +2337 1566 2150 +2337 1567 2198 +2334 1596 2255 +2334 1620 2319 +2342 1646 2396 +2365 1717 2481 +2382 1733 2518 +2382 1733 2518 +2382 1733 2518 +2382 1733 2518 +2382 1733 2518 +2382 1733 2518 +2382 1733 2518 +2382 1733 2518 +2382 1733 2518 +2382 1733 2518 +2364 1776 2032 +2364 1776 2033 +2364 1776 2033 +2364 1777 2034 +2364 1778 2035 +2364 1779 2037 +2363 1781 2038 +2363 1783 2041 +2363 1786 2044 +2362 1790 2049 +2361 1791 2052 +2360 1789 2057 +2359 1784 2065 +2361 1784 2074 +2360 1788 2094 +2357 1783 2117 +2358 1792 2156 +2361 1806 2207 +2354 1805 2259 +2356 1809 2322 +2365 1822 2394 +2383 1874 2484 +2403 1889 2522 +2403 1889 2522 +2403 1889 2522 +2403 1889 2522 +2403 1889 2522 +2403 1889 2522 +2403 1889 2522 +2403 1889 2522 +2403 1889 2522 +2403 1889 2522 +2391 1976 2073 +2391 1976 2073 +2391 1976 2073 +2391 1976 2073 +2391 1976 2073 +2391 1976 2074 +2391 1976 2074 +2391 1976 2075 +2391 1976 2076 +2391 1976 2077 +2391 1976 2078 +2391 1976 2080 +2392 1977 2084 +2394 1981 2093 +2395 1984 2105 +2395 1984 2134 +2392 1984 2163 +2391 1984 2207 +2387 1995 2266 +2396 1995 2324 +2406 2017 2405 +2425 2038 2488 +2448 2060 2526 +2448 2060 2526 +2448 2060 2526 +2448 2060 2526 +2448 2060 2526 +2448 2060 2526 +2448 2060 2526 +2448 2060 2526 +2448 2060 2526 +2448 2060 2526 +2463 2177 2109 +2463 2177 2109 +2463 2177 2110 +2463 2177 2110 +2463 2177 2110 +2463 2177 2111 +2463 2178 2112 +2463 2178 2113 +2463 2179 2114 +2463 2180 2116 +2463 2181 2119 +2462 2182 2121 +2460 2183 2124 +2459 2181 2126 +2458 2177 2134 +2459 2184 2157 +2463 2186 2183 +2461 2184 2220 +2460 2188 2268 +2468 2189 2340 +2476 2191 2406 +2508 2230 2493 +2527 2237 2533 +2527 2237 2533 +2527 2237 2533 +2527 2237 2533 +2527 2237 2533 +2527 2237 2533 +2527 2237 2533 +2527 2237 2533 +2527 2237 2533 +2527 2237 2533 +2598 2410 2071 +2598 2410 2071 +2599 2411 2071 +2599 2411 2071 +2599 2411 2071 +2600 2412 2070 +2600 2412 2070 +2602 2413 2069 +2603 2414 2069 +2604 2416 2068 +2606 2418 2066 +2607 2419 2068 +2607 2420 2073 +2607 2420 2079 +2607 2420 2088 +2607 2420 2112 +2607 2422 2147 +2606 2422 2181 +2609 2420 2243 +2615 2426 2302 +2628 2437 2380 +2656 2458 2462 +2676 2468 2496 +2676 2468 2496 +2676 2468 2496 +2676 2468 2496 +2676 2468 2496 +2676 2468 2496 +2676 2468 2496 +2676 2468 2496 +2676 2468 2496 +2676 2468 2496 +2763 2702 2255 +2763 2702 2255 +2763 2702 2255 +2762 2701 2255 +2762 2701 2255 +2762 2701 2255 +2762 2701 2255 +2762 2701 2255 +2762 2701 2255 +2763 2701 2256 +2763 2701 2257 +2764 2701 2260 +2765 2701 2267 +2765 2701 2274 +2763 2702 2284 +2762 2704 2300 +2763 2706 2316 +2764 2703 2348 +2764 2703 2388 +2768 2710 2455 +2769 2717 2538 +2774 2727 2626 +2777 2731 2667 +2777 2731 2667 +2777 2731 2667 +2777 2731 2667 +2777 2731 2667 +2777 2731 2667 +2777 2731 2667 +2777 2731 2667 +2777 2731 2667 +2777 2731 2667 +2781 2797 2548 +2781 2798 2548 +2781 2798 2548 +2781 2798 2548 +2781 2798 2548 +2781 2798 2548 +2781 2798 2549 +2781 2798 2550 +2781 2799 2550 +2781 2799 2551 +2781 2800 2553 +2782 2800 2555 +2782 2801 2558 +2781 2801 2560 +2780 2800 2559 +2782 2800 2561 +2781 2802 2573 +2781 2801 2584 +2780 2801 2606 +2777 2799 2640 +2775 2801 2677 +2779 2810 2744 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2797 2548 +2781 2798 2548 +2781 2798 2548 +2781 2798 2548 +2781 2798 2548 +2781 2798 2548 +2781 2798 2549 +2781 2798 2550 +2781 2799 2550 +2781 2799 2551 +2781 2800 2553 +2782 2800 2555 +2782 2801 2558 +2781 2801 2560 +2780 2800 2559 +2782 2800 2561 +2781 2802 2573 +2781 2801 2584 +2780 2801 2606 +2777 2799 2640 +2775 2801 2677 +2779 2810 2744 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2797 2548 +2781 2798 2548 +2781 2798 2548 +2781 2798 2548 +2781 2798 2548 +2781 2798 2548 +2781 2798 2549 +2781 2798 2550 +2781 2799 2550 +2781 2799 2551 +2781 2800 2553 +2782 2800 2555 +2782 2801 2558 +2781 2801 2560 +2780 2800 2559 +2782 2800 2561 +2781 2802 2573 +2781 2801 2584 +2780 2801 2606 +2777 2799 2640 +2775 2801 2677 +2779 2810 2744 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2797 2548 +2781 2798 2548 +2781 2798 2548 +2781 2798 2548 +2781 2798 2548 +2781 2798 2548 +2781 2798 2549 +2781 2798 2550 +2781 2799 2550 +2781 2799 2551 +2781 2800 2553 +2782 2800 2555 +2782 2801 2558 +2781 2801 2560 +2780 2800 2559 +2782 2800 2561 +2781 2802 2573 +2781 2801 2584 +2780 2801 2606 +2777 2799 2640 +2775 2801 2677 +2779 2810 2744 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2797 2548 +2781 2798 2548 +2781 2798 2548 +2781 2798 2548 +2781 2798 2548 +2781 2798 2548 +2781 2798 2549 +2781 2798 2550 +2781 2799 2550 +2781 2799 2551 +2781 2800 2553 +2782 2800 2555 +2782 2801 2558 +2781 2801 2560 +2780 2800 2559 +2782 2800 2561 +2781 2802 2573 +2781 2801 2584 +2780 2801 2606 +2777 2799 2640 +2775 2801 2677 +2779 2810 2744 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2797 2548 +2781 2798 2548 +2781 2798 2548 +2781 2798 2548 +2781 2798 2548 +2781 2798 2548 +2781 2798 2549 +2781 2798 2550 +2781 2799 2550 +2781 2799 2551 +2781 2800 2553 +2782 2800 2555 +2782 2801 2558 +2781 2801 2560 +2780 2800 2559 +2782 2800 2561 +2781 2802 2573 +2781 2801 2584 +2780 2801 2606 +2777 2799 2640 +2775 2801 2677 +2779 2810 2744 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2797 2548 +2781 2798 2548 +2781 2798 2548 +2781 2798 2548 +2781 2798 2548 +2781 2798 2548 +2781 2798 2549 +2781 2798 2550 +2781 2799 2550 +2781 2799 2551 +2781 2800 2553 +2782 2800 2555 +2782 2801 2558 +2781 2801 2560 +2780 2800 2559 +2782 2800 2561 +2781 2802 2573 +2781 2801 2584 +2780 2801 2606 +2777 2799 2640 +2775 2801 2677 +2779 2810 2744 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2797 2548 +2781 2798 2548 +2781 2798 2548 +2781 2798 2548 +2781 2798 2548 +2781 2798 2548 +2781 2798 2549 +2781 2798 2550 +2781 2799 2550 +2781 2799 2551 +2781 2800 2553 +2782 2800 2555 +2782 2801 2558 +2781 2801 2560 +2780 2800 2559 +2782 2800 2561 +2781 2802 2573 +2781 2801 2584 +2780 2801 2606 +2777 2799 2640 +2775 2801 2677 +2779 2810 2744 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2797 2548 +2781 2798 2548 +2781 2798 2548 +2781 2798 2548 +2781 2798 2548 +2781 2798 2548 +2781 2798 2549 +2781 2798 2550 +2781 2799 2550 +2781 2799 2551 +2781 2800 2553 +2782 2800 2555 +2782 2801 2558 +2781 2801 2560 +2780 2800 2559 +2782 2800 2561 +2781 2802 2573 +2781 2801 2584 +2780 2801 2606 +2777 2799 2640 +2775 2801 2677 +2779 2810 2744 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2797 2548 +2781 2798 2548 +2781 2798 2548 +2781 2798 2548 +2781 2798 2548 +2781 2798 2548 +2781 2798 2549 +2781 2798 2550 +2781 2799 2550 +2781 2799 2551 +2781 2800 2553 +2782 2800 2555 +2782 2801 2558 +2781 2801 2560 +2780 2800 2559 +2782 2800 2561 +2781 2802 2573 +2781 2801 2584 +2780 2801 2606 +2777 2799 2640 +2775 2801 2677 +2779 2810 2744 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2781 2810 2772 +2481 974 2044 +2481 973 2044 +2481 971 2044 +2481 969 2045 +2480 967 2045 +2480 963 2046 +2480 958 2047 +2480 951 2048 +2480 951 2051 +2480 951 2054 +2480 951 2058 +2480 951 2063 +2480 955 2072 +2479 992 2087 +2477 1037 2103 +2476 1071 2127 +2475 1132 2163 +2475 1219 2209 +2476 1370 2267 +2478 1392 2329 +2488 1469 2402 +2504 1610 2488 +2519 1697 2526 +2519 1697 2526 +2519 1697 2526 +2519 1697 2526 +2519 1697 2526 +2519 1697 2526 +2519 1697 2526 +2519 1697 2526 +2519 1697 2526 +2519 1697 2526 +2481 977 2044 +2481 977 2044 +2481 976 2044 +2480 974 2045 +2480 971 2045 +2480 968 2046 +2480 963 2047 +2480 956 2048 +2480 955 2051 +2480 955 2054 +2480 955 2058 +2480 955 2063 +2480 960 2072 +2479 996 2087 +2477 1041 2103 +2476 1074 2127 +2476 1133 2163 +2475 1220 2209 +2476 1373 2267 +2478 1394 2329 +2488 1469 2402 +2504 1611 2488 +2519 1697 2526 +2519 1697 2526 +2519 1697 2526 +2519 1697 2526 +2519 1697 2526 +2519 1697 2526 +2519 1697 2526 +2519 1697 2526 +2519 1697 2526 +2519 1697 2526 +2481 982 2044 +2481 982 2044 +2480 982 2044 +2480 980 2045 +2480 977 2045 +2480 974 2046 +2480 969 2047 +2480 962 2048 +2480 962 2051 +2480 962 2054 +2480 962 2058 +2480 962 2063 +2480 966 2072 +2479 1002 2087 +2477 1046 2103 +2476 1079 2127 +2476 1136 2162 +2475 1221 2209 +2476 1377 2267 +2478 1397 2329 +2488 1469 2402 +2504 1611 2488 +2519 1697 2526 +2519 1697 2526 +2519 1697 2526 +2519 1697 2526 +2519 1697 2526 +2519 1697 2526 +2519 1697 2526 +2519 1697 2526 +2519 1697 2526 +2519 1697 2526 +2481 988 2044 +2480 988 2044 +2480 988 2044 +2480 988 2045 +2480 985 2045 +2480 981 2046 +2480 977 2047 +2480 970 2048 +2480 970 2051 +2480 970 2054 +2480 970 2058 +2480 970 2063 +2480 974 2072 +2479 1010 2087 +2477 1053 2103 +2476 1085 2127 +2476 1138 2162 +2475 1222 2209 +2476 1382 2267 +2478 1400 2329 +2488 1469 2402 +2504 1612 2488 +2519 1697 2526 +2519 1697 2526 +2519 1697 2526 +2519 1697 2526 +2519 1697 2526 +2519 1697 2526 +2519 1697 2526 +2519 1697 2526 +2519 1697 2526 +2519 1697 2526 +2480 996 2044 +2480 996 2044 +2480 996 2044 +2480 996 2045 +2480 996 2045 +2480 992 2046 +2480 987 2047 +2480 981 2048 +2480 981 2051 +2480 981 2054 +2480 981 2058 +2480 981 2063 +2480 985 2072 +2479 1020 2087 +2477 1062 2103 +2476 1094 2127 +2476 1142 2162 +2476 1223 2208 +2476 1388 2268 +2478 1404 2329 +2488 1469 2402 +2504 1614 2487 +2519 1697 2526 +2519 1697 2526 +2519 1697 2526 +2519 1697 2526 +2519 1697 2526 +2519 1697 2526 +2519 1697 2526 +2519 1697 2526 +2519 1697 2526 +2519 1697 2526 +2480 1006 2044 +2480 1006 2044 +2480 1006 2044 +2480 1006 2045 +2480 1006 2045 +2480 1006 2046 +2480 1001 2047 +2479 995 2048 +2479 995 2051 +2479 995 2054 +2479 995 2058 +2479 995 2063 +2479 999 2072 +2479 1032 2087 +2477 1074 2103 +2476 1105 2127 +2476 1147 2162 +2476 1225 2208 +2476 1397 2268 +2478 1409 2329 +2488 1469 2401 +2503 1615 2487 +2519 1697 2526 +2519 1697 2526 +2519 1697 2526 +2519 1697 2526 +2519 1697 2526 +2519 1697 2526 +2519 1697 2526 +2519 1697 2526 +2519 1697 2526 +2519 1697 2526 +2480 1019 2044 +2480 1019 2044 +2480 1019 2044 +2480 1019 2045 +2480 1019 2045 +2480 1019 2046 +2479 1019 2047 +2479 1013 2048 +2479 1013 2051 +2479 1013 2054 +2479 1013 2058 +2479 1013 2063 +2479 1017 2072 +2479 1049 2087 +2477 1089 2103 +2475 1119 2127 +2476 1154 2161 +2476 1228 2208 +2477 1408 2268 +2477 1417 2329 +2488 1469 2401 +2503 1618 2486 +2518 1697 2526 +2518 1697 2526 +2518 1697 2526 +2518 1697 2526 +2518 1697 2526 +2518 1697 2526 +2518 1697 2526 +2518 1697 2526 +2518 1697 2526 +2518 1697 2526 +2480 1036 2044 +2480 1036 2044 +2480 1036 2044 +2480 1036 2045 +2480 1036 2045 +2479 1036 2046 +2479 1036 2047 +2479 1036 2048 +2479 1036 2051 +2479 1036 2054 +2479 1036 2058 +2479 1036 2063 +2479 1039 2072 +2478 1070 2087 +2476 1108 2103 +2475 1137 2127 +2477 1162 2161 +2476 1232 2207 +2477 1423 2268 +2477 1426 2329 +2488 1469 2401 +2503 1621 2486 +2518 1697 2526 +2518 1697 2526 +2518 1697 2526 +2518 1697 2526 +2518 1697 2526 +2518 1697 2526 +2518 1697 2526 +2518 1697 2526 +2518 1697 2526 +2518 1697 2526 +2480 1071 2044 +2480 1071 2044 +2480 1071 2044 +2480 1071 2045 +2480 1071 2045 +2479 1071 2046 +2479 1071 2047 +2479 1071 2048 +2479 1044 2051 +2479 1044 2054 +2479 1044 2058 +2479 1044 2063 +2479 1048 2072 +2479 1085 2087 +2477 1122 2103 +2476 1149 2126 +2478 1179 2161 +2476 1241 2208 +2477 1424 2268 +2478 1436 2329 +2488 1480 2401 +2504 1627 2485 +2519 1702 2526 +2519 1702 2526 +2519 1702 2526 +2519 1702 2526 +2519 1702 2526 +2519 1702 2526 +2519 1702 2526 +2519 1702 2526 +2519 1702 2526 +2519 1702 2526 +2480 1115 2044 +2480 1115 2044 +2480 1115 2044 +2480 1115 2045 +2480 1115 2045 +2479 1115 2046 +2479 1115 2047 +2479 1115 2048 +2479 1091 2051 +2479 1054 2054 +2479 1054 2058 +2479 1054 2063 +2479 1058 2072 +2479 1099 2087 +2478 1138 2103 +2476 1165 2125 +2478 1193 2160 +2477 1254 2209 +2477 1424 2266 +2479 1448 2329 +2488 1495 2401 +2504 1635 2485 +2521 1708 2526 +2521 1708 2526 +2521 1708 2526 +2521 1708 2526 +2521 1708 2526 +2521 1708 2526 +2521 1708 2526 +2521 1708 2526 +2521 1708 2526 +2521 1708 2526 +2480 1169 2044 +2480 1169 2044 +2480 1169 2044 +2480 1169 2045 +2480 1169 2045 +2479 1169 2046 +2479 1169 2047 +2479 1169 2048 +2479 1147 2051 +2479 1114 2054 +2479 1067 2058 +2479 1067 2063 +2479 1070 2072 +2479 1111 2087 +2479 1159 2103 +2478 1185 2125 +2480 1212 2159 +2478 1278 2209 +2477 1424 2264 +2480 1464 2329 +2488 1514 2402 +2505 1646 2485 +2523 1718 2525 +2523 1718 2525 +2523 1718 2525 +2523 1718 2525 +2523 1718 2525 +2523 1718 2525 +2523 1718 2525 +2523 1718 2525 +2523 1718 2525 +2523 1718 2525 +2480 1231 2044 +2480 1231 2044 +2480 1231 2044 +2480 1231 2045 +2480 1231 2045 +2479 1231 2046 +2479 1231 2047 +2479 1231 2048 +2479 1212 2051 +2479 1184 2054 +2479 1144 2058 +2479 1083 2063 +2479 1087 2072 +2479 1126 2087 +2481 1186 2103 +2479 1210 2125 +2481 1236 2158 +2479 1308 2209 +2477 1424 2262 +2481 1485 2329 +2488 1542 2402 +2507 1660 2485 +2526 1729 2524 +2526 1729 2524 +2526 1729 2524 +2526 1729 2524 +2526 1729 2524 +2526 1729 2524 +2526 1729 2524 +2526 1729 2524 +2526 1729 2524 +2526 1729 2524 +2480 1299 2045 +2480 1299 2045 +2480 1299 2045 +2480 1299 2046 +2480 1299 2046 +2480 1299 2047 +2480 1299 2048 +2479 1299 2049 +2479 1283 2051 +2479 1259 2054 +2479 1225 2059 +2479 1174 2064 +2479 1114 2072 +2480 1151 2087 +2481 1213 2103 +2481 1244 2125 +2483 1268 2156 +2481 1346 2209 +2477 1430 2260 +2483 1511 2329 +2489 1583 2403 +2509 1680 2486 +2529 1745 2524 +2529 1745 2524 +2529 1745 2524 +2529 1745 2524 +2529 1745 2524 +2529 1745 2524 +2529 1745 2524 +2529 1745 2524 +2529 1745 2524 +2529 1745 2524 +2482 1385 2049 +2482 1385 2049 +2482 1384 2049 +2482 1384 2050 +2482 1382 2050 +2482 1381 2051 +2482 1379 2052 +2481 1376 2053 +2482 1366 2055 +2482 1349 2058 +2482 1321 2063 +2482 1281 2068 +2482 1235 2076 +2482 1263 2087 +2484 1312 2103 +2484 1330 2127 +2485 1346 2157 +2483 1386 2211 +2480 1472 2262 +2483 1568 2328 +2492 1634 2404 +2509 1714 2486 +2531 1767 2524 +2531 1767 2524 +2531 1767 2524 +2531 1767 2524 +2531 1767 2524 +2531 1767 2524 +2531 1767 2524 +2531 1767 2524 +2531 1767 2524 +2531 1767 2524 +2484 1508 2049 +2484 1507 2049 +2484 1507 2049 +2484 1506 2050 +2484 1506 2050 +2484 1504 2051 +2483 1503 2052 +2483 1501 2053 +2483 1493 2055 +2484 1482 2058 +2485 1467 2063 +2485 1445 2068 +2485 1416 2076 +2486 1436 2087 +2488 1470 2103 +2487 1479 2127 +2487 1478 2157 +2484 1484 2208 +2487 1547 2268 +2485 1642 2328 +2495 1671 2406 +2509 1751 2486 +2531 1801 2522 +2531 1801 2522 +2531 1801 2522 +2531 1801 2522 +2531 1801 2522 +2531 1801 2522 +2531 1801 2522 +2531 1801 2522 +2531 1801 2522 +2531 1801 2522 +2490 1632 2052 +2490 1632 2052 +2490 1632 2053 +2490 1632 2054 +2490 1632 2054 +2490 1632 2056 +2490 1632 2057 +2490 1632 2060 +2490 1628 2062 +2491 1623 2066 +2491 1613 2070 +2492 1598 2075 +2493 1580 2082 +2492 1580 2091 +2493 1600 2105 +2492 1613 2131 +2491 1631 2162 +2489 1632 2206 +2493 1658 2265 +2493 1730 2328 +2499 1742 2404 +2518 1813 2489 +2537 1864 2526 +2537 1864 2526 +2537 1864 2526 +2537 1864 2526 +2537 1864 2526 +2537 1864 2526 +2537 1864 2526 +2537 1864 2526 +2537 1864 2526 +2537 1864 2526 +2502 1784 2071 +2502 1784 2071 +2502 1784 2071 +2502 1784 2072 +2502 1784 2073 +2502 1784 2073 +2502 1784 2075 +2502 1784 2077 +2502 1779 2078 +2502 1774 2081 +2503 1769 2085 +2503 1762 2090 +2504 1754 2098 +2504 1757 2107 +2503 1757 2115 +2502 1754 2140 +2499 1757 2175 +2500 1778 2215 +2501 1806 2266 +2500 1817 2326 +2509 1832 2402 +2528 1891 2490 +2547 1940 2532 +2547 1940 2532 +2547 1940 2532 +2547 1940 2532 +2547 1940 2532 +2547 1940 2532 +2547 1940 2532 +2547 1940 2532 +2547 1940 2532 +2547 1940 2532 +2516 1927 2075 +2516 1928 2075 +2516 1928 2075 +2516 1928 2076 +2516 1928 2076 +2517 1929 2077 +2517 1929 2078 +2517 1930 2079 +2517 1930 2081 +2516 1930 2084 +2516 1924 2087 +2515 1913 2090 +2514 1901 2096 +2516 1900 2105 +2517 1912 2120 +2515 1910 2143 +2514 1921 2180 +2513 1918 2218 +2516 1938 2272 +2518 1938 2333 +2528 1977 2406 +2552 2008 2491 +2567 2036 2526 +2567 2036 2526 +2567 2036 2526 +2567 2036 2526 +2567 2036 2526 +2567 2036 2526 +2567 2036 2526 +2567 2036 2526 +2567 2036 2526 +2567 2036 2526 +2547 2073 2093 +2547 2073 2093 +2547 2073 2093 +2546 2073 2093 +2546 2073 2094 +2546 2073 2094 +2545 2073 2095 +2545 2073 2096 +2545 2073 2098 +2545 2073 2100 +2545 2073 2102 +2545 2073 2106 +2545 2073 2111 +2545 2075 2119 +2543 2075 2127 +2543 2078 2149 +2543 2075 2180 +2546 2089 2222 +2546 2091 2274 +2551 2098 2337 +2558 2115 2411 +2588 2155 2491 +2598 2168 2529 +2598 2168 2529 +2598 2168 2529 +2598 2168 2529 +2598 2168 2529 +2598 2168 2529 +2598 2168 2529 +2598 2168 2529 +2598 2168 2529 +2598 2168 2529 +2602 2259 2099 +2602 2258 2099 +2602 2258 2099 +2602 2258 2099 +2602 2258 2099 +2601 2258 2099 +2600 2258 2099 +2600 2257 2099 +2600 2257 2101 +2600 2257 2104 +2600 2257 2108 +2600 2257 2113 +2600 2257 2120 +2603 2257 2132 +2606 2257 2144 +2606 2263 2161 +2611 2270 2190 +2606 2266 2226 +2612 2277 2289 +2615 2277 2347 +2621 2290 2414 +2651 2318 2497 +2668 2333 2527 +2668 2333 2527 +2668 2333 2527 +2668 2333 2527 +2668 2333 2527 +2668 2333 2527 +2668 2333 2527 +2668 2333 2527 +2668 2333 2527 +2668 2333 2527 +2722 2488 1839 +2722 2488 1839 +2722 2488 1841 +2722 2488 1843 +2723 2488 1845 +2723 2489 1848 +2724 2489 1852 +2724 2489 1858 +2724 2489 1862 +2724 2489 1867 +2724 2488 1873 +2723 2488 1876 +2723 2488 1878 +2722 2488 1891 +2722 2486 1913 +2722 2485 1956 +2723 2487 2015 +2723 2486 2070 +2727 2489 2159 +2732 2495 2242 +2745 2509 2352 +2763 2528 2453 +2772 2539 2499 +2772 2539 2499 +2772 2539 2499 +2772 2539 2499 +2772 2539 2499 +2772 2539 2499 +2772 2539 2499 +2772 2539 2499 +2772 2539 2499 +2772 2539 2499 +2811 2738 2425 +2811 2738 2425 +2811 2738 2426 +2811 2738 2426 +2811 2738 2426 +2811 2738 2426 +2811 2738 2427 +2811 2738 2427 +2811 2739 2428 +2811 2739 2430 +2811 2739 2431 +2811 2740 2434 +2811 2740 2437 +2811 2740 2440 +2810 2740 2444 +2810 2740 2448 +2811 2742 2464 +2810 2743 2483 +2810 2745 2522 +2810 2748 2564 +2811 2752 2623 +2810 2762 2701 +2813 2763 2731 +2813 2763 2731 +2813 2763 2731 +2813 2763 2731 +2813 2763 2731 +2813 2763 2731 +2813 2763 2731 +2813 2763 2731 +2813 2763 2731 +2813 2763 2731 +2820 2813 2591 +2820 2813 2591 +2820 2813 2591 +2820 2813 2591 +2820 2813 2590 +2820 2813 2590 +2820 2813 2589 +2820 2812 2589 +2820 2813 2590 +2820 2813 2591 +2820 2813 2592 +2820 2813 2593 +2820 2814 2596 +2819 2814 2598 +2818 2813 2599 +2820 2813 2604 +2822 2813 2612 +2820 2813 2623 +2820 2815 2643 +2818 2815 2670 +2818 2817 2713 +2813 2819 2768 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2820 2813 2591 +2820 2813 2591 +2820 2813 2591 +2820 2813 2591 +2820 2813 2590 +2820 2813 2590 +2820 2813 2589 +2820 2812 2589 +2820 2813 2590 +2820 2813 2591 +2820 2813 2592 +2820 2813 2593 +2820 2814 2596 +2819 2814 2598 +2818 2813 2599 +2820 2813 2604 +2822 2813 2612 +2820 2813 2623 +2820 2815 2643 +2818 2815 2670 +2818 2817 2713 +2813 2819 2768 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2820 2813 2591 +2820 2813 2591 +2820 2813 2591 +2820 2813 2591 +2820 2813 2590 +2820 2813 2590 +2820 2813 2589 +2820 2812 2589 +2820 2813 2590 +2820 2813 2591 +2820 2813 2592 +2820 2813 2593 +2820 2814 2596 +2819 2814 2598 +2818 2813 2599 +2820 2813 2604 +2822 2813 2612 +2820 2813 2623 +2820 2815 2643 +2818 2815 2670 +2818 2817 2713 +2813 2819 2768 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2820 2813 2591 +2820 2813 2591 +2820 2813 2591 +2820 2813 2591 +2820 2813 2590 +2820 2813 2590 +2820 2813 2589 +2820 2812 2589 +2820 2813 2590 +2820 2813 2591 +2820 2813 2592 +2820 2813 2593 +2820 2814 2596 +2819 2814 2598 +2818 2813 2599 +2820 2813 2604 +2822 2813 2612 +2820 2813 2623 +2820 2815 2643 +2818 2815 2670 +2818 2817 2713 +2813 2819 2768 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2820 2813 2591 +2820 2813 2591 +2820 2813 2591 +2820 2813 2591 +2820 2813 2590 +2820 2813 2590 +2820 2813 2589 +2820 2812 2589 +2820 2813 2590 +2820 2813 2591 +2820 2813 2592 +2820 2813 2593 +2820 2814 2596 +2819 2814 2598 +2818 2813 2599 +2820 2813 2604 +2822 2813 2612 +2820 2813 2623 +2820 2815 2643 +2818 2815 2670 +2818 2817 2713 +2813 2819 2768 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2820 2813 2591 +2820 2813 2591 +2820 2813 2591 +2820 2813 2591 +2820 2813 2590 +2820 2813 2590 +2820 2813 2589 +2820 2812 2589 +2820 2813 2590 +2820 2813 2591 +2820 2813 2592 +2820 2813 2593 +2820 2814 2596 +2819 2814 2598 +2818 2813 2599 +2820 2813 2604 +2822 2813 2612 +2820 2813 2623 +2820 2815 2643 +2818 2815 2670 +2818 2817 2713 +2813 2819 2768 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2820 2813 2591 +2820 2813 2591 +2820 2813 2591 +2820 2813 2591 +2820 2813 2590 +2820 2813 2590 +2820 2813 2589 +2820 2812 2589 +2820 2813 2590 +2820 2813 2591 +2820 2813 2592 +2820 2813 2593 +2820 2814 2596 +2819 2814 2598 +2818 2813 2599 +2820 2813 2604 +2822 2813 2612 +2820 2813 2623 +2820 2815 2643 +2818 2815 2670 +2818 2817 2713 +2813 2819 2768 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2820 2813 2591 +2820 2813 2591 +2820 2813 2591 +2820 2813 2591 +2820 2813 2590 +2820 2813 2590 +2820 2813 2589 +2820 2812 2589 +2820 2813 2590 +2820 2813 2591 +2820 2813 2592 +2820 2813 2593 +2820 2814 2596 +2819 2814 2598 +2818 2813 2599 +2820 2813 2604 +2822 2813 2612 +2820 2813 2623 +2820 2815 2643 +2818 2815 2670 +2818 2817 2713 +2813 2819 2768 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2820 2813 2591 +2820 2813 2591 +2820 2813 2591 +2820 2813 2591 +2820 2813 2590 +2820 2813 2590 +2820 2813 2589 +2820 2812 2589 +2820 2813 2590 +2820 2813 2591 +2820 2813 2592 +2820 2813 2593 +2820 2814 2596 +2819 2814 2598 +2818 2813 2599 +2820 2813 2604 +2822 2813 2612 +2820 2813 2623 +2820 2815 2643 +2818 2815 2670 +2818 2817 2713 +2813 2819 2768 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2820 2813 2591 +2820 2813 2591 +2820 2813 2591 +2820 2813 2591 +2820 2813 2590 +2820 2813 2590 +2820 2813 2589 +2820 2812 2589 +2820 2813 2590 +2820 2813 2591 +2820 2813 2592 +2820 2813 2593 +2820 2814 2596 +2819 2814 2598 +2818 2813 2599 +2820 2813 2604 +2822 2813 2612 +2820 2813 2623 +2820 2815 2643 +2818 2815 2670 +2818 2817 2713 +2813 2819 2768 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2814 2823 2799 +2554 1623 2059 +2554 1623 2059 +2554 1623 2060 +2554 1623 2060 +2554 1623 2061 +2554 1623 2063 +2554 1623 2065 +2554 1623 2067 +2554 1623 2070 +2554 1623 2074 +2554 1623 2080 +2554 1623 2087 +2554 1621 2096 +2554 1621 2102 +2554 1621 2110 +2555 1588 2133 +2556 1555 2169 +2555 1608 2217 +2557 1691 2269 +2563 1692 2342 +2564 1761 2409 +2587 1838 2491 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2554 1625 2059 +2554 1624 2059 +2554 1624 2060 +2554 1624 2060 +2554 1624 2061 +2554 1624 2063 +2554 1624 2064 +2554 1624 2067 +2554 1624 2070 +2554 1624 2074 +2554 1624 2080 +2554 1624 2087 +2554 1621 2096 +2554 1621 2102 +2554 1621 2110 +2556 1590 2134 +2556 1556 2169 +2555 1609 2217 +2557 1691 2269 +2563 1692 2342 +2564 1762 2409 +2587 1839 2492 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2554 1627 2059 +2554 1626 2059 +2554 1625 2060 +2554 1625 2060 +2554 1625 2061 +2554 1625 2063 +2554 1625 2064 +2554 1625 2067 +2554 1625 2070 +2554 1625 2074 +2554 1625 2079 +2554 1625 2086 +2554 1622 2096 +2554 1621 2102 +2554 1621 2110 +2556 1592 2134 +2556 1559 2169 +2555 1610 2217 +2557 1691 2269 +2564 1693 2342 +2564 1764 2409 +2587 1840 2492 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2554 1630 2060 +2554 1629 2060 +2554 1627 2060 +2554 1625 2060 +2554 1625 2061 +2554 1625 2062 +2554 1625 2064 +2554 1625 2066 +2554 1625 2070 +2554 1625 2074 +2554 1625 2079 +2554 1625 2086 +2554 1623 2095 +2554 1621 2102 +2554 1621 2110 +2556 1595 2134 +2556 1562 2169 +2555 1611 2217 +2557 1691 2270 +2564 1694 2342 +2564 1765 2409 +2587 1842 2492 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2554 1633 2060 +2554 1632 2060 +2554 1631 2060 +2554 1629 2060 +2554 1626 2061 +2554 1626 2062 +2554 1626 2064 +2554 1626 2066 +2554 1626 2069 +2554 1626 2073 +2554 1626 2079 +2554 1626 2086 +2554 1625 2095 +2554 1621 2102 +2554 1621 2110 +2556 1599 2135 +2556 1567 2169 +2555 1613 2217 +2557 1692 2270 +2564 1695 2342 +2565 1768 2409 +2587 1844 2492 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2554 1638 2061 +2554 1638 2061 +2554 1636 2061 +2554 1634 2061 +2554 1631 2061 +2554 1628 2062 +2554 1628 2063 +2554 1628 2066 +2554 1628 2069 +2554 1628 2073 +2554 1628 2079 +2554 1628 2086 +2554 1626 2095 +2554 1621 2102 +2554 1621 2110 +2556 1605 2135 +2556 1572 2169 +2555 1616 2217 +2557 1693 2270 +2564 1696 2342 +2565 1771 2409 +2587 1847 2492 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2555 1645 2062 +2555 1644 2062 +2555 1643 2062 +2555 1641 2062 +2555 1638 2062 +2555 1635 2063 +2555 1631 2063 +2555 1631 2066 +2555 1631 2069 +2555 1631 2073 +2555 1631 2078 +2555 1631 2085 +2555 1628 2094 +2554 1621 2102 +2554 1621 2110 +2556 1612 2136 +2556 1580 2169 +2554 1619 2217 +2558 1694 2270 +2564 1698 2342 +2565 1775 2409 +2587 1852 2492 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2555 1654 2063 +2555 1653 2063 +2555 1651 2063 +2555 1650 2063 +2555 1647 2063 +2555 1644 2064 +2555 1640 2064 +2555 1633 2065 +2555 1633 2068 +2555 1633 2072 +2555 1633 2078 +2555 1633 2085 +2555 1631 2094 +2554 1621 2102 +2554 1621 2110 +2556 1621 2137 +2557 1590 2169 +2554 1624 2217 +2558 1695 2270 +2564 1701 2342 +2565 1781 2409 +2588 1857 2493 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2556 1665 2064 +2556 1664 2065 +2556 1663 2065 +2556 1661 2065 +2556 1659 2065 +2556 1655 2066 +2556 1651 2066 +2556 1646 2066 +2556 1638 2067 +2556 1638 2071 +2556 1638 2077 +2556 1638 2084 +2556 1636 2093 +2554 1621 2102 +2554 1621 2110 +2556 1633 2138 +2557 1603 2169 +2554 1630 2217 +2558 1697 2271 +2564 1704 2342 +2565 1788 2409 +2588 1860 2493 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2556 1680 2066 +2556 1679 2067 +2556 1678 2067 +2556 1676 2067 +2556 1674 2067 +2556 1671 2068 +2556 1667 2068 +2556 1661 2069 +2556 1653 2069 +2556 1643 2070 +2556 1643 2076 +2556 1643 2083 +2556 1641 2092 +2554 1624 2101 +2554 1621 2110 +2557 1649 2140 +2557 1620 2170 +2554 1638 2217 +2558 1699 2271 +2565 1709 2342 +2566 1798 2409 +2589 1863 2493 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2558 1699 2069 +2558 1698 2069 +2558 1697 2070 +2558 1695 2070 +2558 1693 2070 +2558 1690 2070 +2558 1686 2071 +2558 1681 2071 +2558 1674 2072 +2558 1663 2073 +2558 1650 2074 +2558 1650 2082 +2557 1648 2091 +2555 1631 2100 +2554 1621 2110 +2557 1657 2141 +2558 1642 2173 +2554 1658 2217 +2559 1702 2273 +2565 1715 2342 +2566 1810 2409 +2589 1868 2493 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2559 1723 2073 +2559 1723 2073 +2559 1722 2073 +2559 1720 2073 +2559 1718 2074 +2559 1715 2074 +2559 1711 2074 +2559 1706 2075 +2559 1699 2076 +2559 1690 2077 +2559 1677 2078 +2559 1659 2080 +2558 1657 2089 +2556 1641 2098 +2554 1621 2110 +2557 1657 2141 +2558 1669 2176 +2555 1684 2217 +2560 1706 2274 +2566 1723 2342 +2567 1816 2409 +2591 1873 2493 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2560 1754 2078 +2560 1754 2078 +2560 1753 2078 +2560 1752 2079 +2560 1750 2079 +2560 1747 2079 +2560 1744 2080 +2560 1739 2080 +2560 1732 2081 +2560 1724 2082 +2560 1712 2083 +2560 1695 2085 +2560 1674 2088 +2558 1658 2097 +2555 1635 2110 +2557 1661 2141 +2559 1703 2179 +2556 1716 2217 +2560 1716 2275 +2566 1739 2342 +2568 1818 2408 +2592 1880 2493 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2562 1761 2078 +2562 1761 2078 +2562 1761 2079 +2562 1762 2080 +2562 1763 2080 +2562 1765 2082 +2562 1766 2084 +2562 1769 2086 +2562 1772 2089 +2563 1771 2091 +2563 1760 2093 +2563 1745 2094 +2562 1727 2097 +2561 1712 2103 +2558 1692 2116 +2556 1693 2138 +2560 1738 2181 +2560 1744 2217 +2561 1744 2275 +2566 1785 2340 +2571 1835 2406 +2592 1893 2492 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2563 1769 2078 +2563 1769 2078 +2563 1770 2079 +2563 1771 2080 +2563 1772 2080 +2563 1773 2082 +2564 1775 2084 +2564 1777 2086 +2564 1780 2089 +2564 1784 2093 +2565 1789 2098 +2565 1796 2105 +2566 1789 2110 +2564 1776 2116 +2563 1758 2124 +2559 1753 2143 +2558 1773 2177 +2563 1787 2220 +2563 1779 2275 +2566 1840 2337 +2576 1860 2406 +2591 1925 2491 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2566 1822 2077 +2566 1822 2078 +2566 1822 2078 +2566 1822 2078 +2566 1822 2079 +2566 1822 2079 +2566 1822 2080 +2566 1822 2081 +2566 1822 2083 +2566 1822 2085 +2567 1824 2089 +2568 1831 2096 +2568 1839 2106 +2570 1844 2121 +2568 1834 2131 +2568 1813 2145 +2564 1813 2176 +2565 1838 2221 +2568 1838 2272 +2573 1888 2337 +2580 1896 2406 +2599 1967 2492 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2573 1894 2080 +2573 1894 2081 +2573 1895 2081 +2573 1896 2081 +2573 1897 2082 +2574 1898 2082 +2574 1900 2083 +2575 1903 2084 +2575 1906 2086 +2575 1906 2088 +2575 1906 2090 +2575 1906 2094 +2575 1906 2099 +2575 1907 2109 +2576 1913 2129 +2577 1915 2152 +2578 1893 2171 +2576 1899 2221 +2578 1919 2273 +2580 1949 2338 +2587 1961 2408 +2611 2008 2495 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2588 1996 2083 +2588 1997 2083 +2588 1997 2084 +2588 1997 2085 +2588 1997 2086 +2588 1998 2087 +2588 1998 2088 +2588 1999 2091 +2588 2000 2093 +2588 2001 2098 +2588 2005 2100 +2589 2012 2104 +2591 2018 2108 +2588 2010 2114 +2588 2009 2126 +2589 2014 2149 +2590 2016 2184 +2591 2003 2214 +2591 2019 2275 +2595 2044 2342 +2604 2072 2411 +2625 2108 2494 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2625 2149 2111 +2624 2149 2111 +2624 2149 2111 +2624 2149 2111 +2624 2148 2111 +2624 2148 2111 +2623 2147 2111 +2623 2146 2111 +2622 2145 2111 +2621 2143 2111 +2620 2141 2111 +2618 2137 2111 +2617 2136 2114 +2617 2144 2126 +2617 2155 2141 +2619 2157 2164 +2623 2160 2195 +2624 2165 2231 +2619 2165 2275 +2633 2187 2352 +2638 2190 2417 +2660 2223 2503 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2670 2315 2112 +2671 2315 2112 +2671 2315 2112 +2671 2315 2111 +2671 2316 2111 +2672 2316 2111 +2672 2316 2111 +2673 2317 2110 +2674 2318 2109 +2675 2319 2108 +2677 2321 2107 +2680 2323 2105 +2682 2325 2106 +2681 2325 2118 +2680 2325 2133 +2678 2328 2149 +2677 2328 2176 +2677 2325 2215 +2687 2335 2275 +2689 2335 2316 +2695 2346 2391 +2724 2369 2462 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2775 2531 1744 +2775 2531 1745 +2775 2531 1747 +2775 2531 1750 +2776 2532 1753 +2776 2532 1758 +2776 2533 1764 +2776 2533 1772 +2777 2534 1782 +2778 2535 1796 +2778 2536 1813 +2778 2537 1825 +2777 2535 1833 +2776 2530 1839 +2776 2528 1859 +2778 2535 1929 +2779 2534 1991 +2780 2535 2071 +2782 2538 2158 +2784 2536 2248 +2791 2552 2360 +2803 2569 2485 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2826 2762 2506 +2826 2762 2506 +2826 2762 2505 +2826 2762 2505 +2826 2762 2505 +2826 2762 2505 +2826 2761 2505 +2826 2761 2505 +2826 2761 2505 +2826 2761 2506 +2826 2761 2507 +2826 2761 2509 +2826 2761 2510 +2826 2760 2508 +2826 2760 2508 +2826 2762 2520 +2826 2764 2535 +2826 2763 2548 +2826 2763 2571 +2826 2767 2613 +2826 2769 2662 +2826 2779 2732 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2554 1623 2059 +2554 1623 2059 +2554 1623 2060 +2554 1623 2060 +2554 1623 2061 +2554 1623 2063 +2554 1623 2065 +2554 1623 2067 +2554 1623 2070 +2554 1623 2074 +2554 1623 2080 +2554 1623 2087 +2554 1621 2096 +2554 1621 2102 +2554 1621 2110 +2555 1588 2133 +2556 1555 2169 +2555 1608 2217 +2557 1691 2269 +2563 1692 2342 +2564 1761 2409 +2587 1838 2491 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2554 1625 2059 +2554 1624 2059 +2554 1624 2060 +2554 1624 2060 +2554 1624 2061 +2554 1624 2063 +2554 1624 2064 +2554 1624 2067 +2554 1624 2070 +2554 1624 2074 +2554 1624 2080 +2554 1624 2087 +2554 1621 2096 +2554 1621 2102 +2554 1621 2110 +2556 1590 2134 +2556 1556 2169 +2555 1609 2217 +2557 1691 2269 +2563 1692 2342 +2564 1762 2409 +2587 1839 2492 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2554 1627 2059 +2554 1626 2059 +2554 1625 2060 +2554 1625 2060 +2554 1625 2061 +2554 1625 2063 +2554 1625 2064 +2554 1625 2067 +2554 1625 2070 +2554 1625 2074 +2554 1625 2079 +2554 1625 2086 +2554 1622 2096 +2554 1621 2102 +2554 1621 2110 +2556 1592 2134 +2556 1559 2169 +2555 1610 2217 +2557 1691 2269 +2564 1693 2342 +2564 1764 2409 +2587 1840 2492 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2554 1630 2060 +2554 1629 2060 +2554 1627 2060 +2554 1625 2060 +2554 1625 2061 +2554 1625 2062 +2554 1625 2064 +2554 1625 2066 +2554 1625 2070 +2554 1625 2074 +2554 1625 2079 +2554 1625 2086 +2554 1623 2095 +2554 1621 2102 +2554 1621 2110 +2556 1595 2134 +2556 1562 2169 +2555 1611 2217 +2557 1691 2270 +2564 1694 2342 +2564 1765 2409 +2587 1842 2492 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2554 1633 2060 +2554 1632 2060 +2554 1631 2060 +2554 1629 2060 +2554 1626 2061 +2554 1626 2062 +2554 1626 2064 +2554 1626 2066 +2554 1626 2069 +2554 1626 2073 +2554 1626 2079 +2554 1626 2086 +2554 1625 2095 +2554 1621 2102 +2554 1621 2110 +2556 1599 2135 +2556 1567 2169 +2555 1613 2217 +2557 1692 2270 +2564 1695 2342 +2565 1768 2409 +2587 1844 2492 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2554 1638 2061 +2554 1638 2061 +2554 1636 2061 +2554 1634 2061 +2554 1631 2061 +2554 1628 2062 +2554 1628 2063 +2554 1628 2066 +2554 1628 2069 +2554 1628 2073 +2554 1628 2079 +2554 1628 2086 +2554 1626 2095 +2554 1621 2102 +2554 1621 2110 +2556 1605 2135 +2556 1572 2169 +2555 1616 2217 +2557 1693 2270 +2564 1696 2342 +2565 1771 2409 +2587 1847 2492 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2555 1645 2062 +2555 1644 2062 +2555 1643 2062 +2555 1641 2062 +2555 1638 2062 +2555 1635 2063 +2555 1631 2063 +2555 1631 2066 +2555 1631 2069 +2555 1631 2073 +2555 1631 2078 +2555 1631 2085 +2555 1628 2094 +2554 1621 2102 +2554 1621 2110 +2556 1612 2136 +2556 1580 2169 +2554 1619 2217 +2558 1694 2270 +2564 1698 2342 +2565 1775 2409 +2587 1852 2492 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2555 1654 2063 +2555 1653 2063 +2555 1651 2063 +2555 1650 2063 +2555 1647 2063 +2555 1644 2064 +2555 1640 2064 +2555 1633 2065 +2555 1633 2068 +2555 1633 2072 +2555 1633 2078 +2555 1633 2085 +2555 1631 2094 +2554 1621 2102 +2554 1621 2110 +2556 1621 2137 +2557 1590 2169 +2554 1624 2217 +2558 1695 2270 +2564 1701 2342 +2565 1781 2409 +2588 1857 2493 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2556 1665 2064 +2556 1664 2065 +2556 1663 2065 +2556 1661 2065 +2556 1659 2065 +2556 1655 2066 +2556 1651 2066 +2556 1646 2066 +2556 1638 2067 +2556 1638 2071 +2556 1638 2077 +2556 1638 2084 +2556 1636 2093 +2554 1621 2102 +2554 1621 2110 +2556 1633 2138 +2557 1603 2169 +2554 1630 2217 +2558 1697 2271 +2564 1704 2342 +2565 1788 2409 +2588 1860 2493 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2556 1680 2066 +2556 1679 2067 +2556 1678 2067 +2556 1676 2067 +2556 1674 2067 +2556 1671 2068 +2556 1667 2068 +2556 1661 2069 +2556 1653 2069 +2556 1643 2070 +2556 1643 2076 +2556 1643 2083 +2556 1641 2092 +2554 1624 2101 +2554 1621 2110 +2557 1649 2140 +2557 1620 2170 +2554 1638 2217 +2558 1699 2271 +2565 1709 2342 +2566 1798 2409 +2589 1863 2493 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2558 1699 2069 +2558 1698 2069 +2558 1697 2070 +2558 1695 2070 +2558 1693 2070 +2558 1690 2070 +2558 1686 2071 +2558 1681 2071 +2558 1674 2072 +2558 1663 2073 +2558 1650 2074 +2558 1650 2082 +2557 1648 2091 +2555 1631 2100 +2554 1621 2110 +2557 1657 2141 +2558 1642 2173 +2554 1658 2217 +2559 1702 2273 +2565 1715 2342 +2566 1810 2409 +2589 1868 2493 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2559 1723 2073 +2559 1723 2073 +2559 1722 2073 +2559 1720 2073 +2559 1718 2074 +2559 1715 2074 +2559 1711 2074 +2559 1706 2075 +2559 1699 2076 +2559 1690 2077 +2559 1677 2078 +2559 1659 2080 +2558 1657 2089 +2556 1641 2098 +2554 1621 2110 +2557 1657 2141 +2558 1669 2176 +2555 1684 2217 +2560 1706 2274 +2566 1723 2342 +2567 1816 2409 +2591 1873 2493 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2560 1754 2078 +2560 1754 2078 +2560 1753 2078 +2560 1752 2079 +2560 1750 2079 +2560 1747 2079 +2560 1744 2080 +2560 1739 2080 +2560 1732 2081 +2560 1724 2082 +2560 1712 2083 +2560 1695 2085 +2560 1674 2088 +2558 1658 2097 +2555 1635 2110 +2557 1661 2141 +2559 1703 2179 +2556 1716 2217 +2560 1716 2275 +2566 1739 2342 +2568 1818 2408 +2592 1880 2493 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2562 1761 2078 +2562 1761 2078 +2562 1761 2079 +2562 1762 2080 +2562 1763 2080 +2562 1765 2082 +2562 1766 2084 +2562 1769 2086 +2562 1772 2089 +2563 1771 2091 +2563 1760 2093 +2563 1745 2094 +2562 1727 2097 +2561 1712 2103 +2558 1692 2116 +2556 1693 2138 +2560 1738 2181 +2560 1744 2217 +2561 1744 2275 +2566 1785 2340 +2571 1835 2406 +2592 1893 2492 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2563 1769 2078 +2563 1769 2078 +2563 1770 2079 +2563 1771 2080 +2563 1772 2080 +2563 1773 2082 +2564 1775 2084 +2564 1777 2086 +2564 1780 2089 +2564 1784 2093 +2565 1789 2098 +2565 1796 2105 +2566 1789 2110 +2564 1776 2116 +2563 1758 2124 +2559 1753 2143 +2558 1773 2177 +2563 1787 2220 +2563 1779 2275 +2566 1840 2337 +2576 1860 2406 +2591 1925 2491 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2566 1822 2077 +2566 1822 2078 +2566 1822 2078 +2566 1822 2078 +2566 1822 2079 +2566 1822 2079 +2566 1822 2080 +2566 1822 2081 +2566 1822 2083 +2566 1822 2085 +2567 1824 2089 +2568 1831 2096 +2568 1839 2106 +2570 1844 2121 +2568 1834 2131 +2568 1813 2145 +2564 1813 2176 +2565 1838 2221 +2568 1838 2272 +2573 1888 2337 +2580 1896 2406 +2599 1967 2492 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2573 1894 2080 +2573 1894 2081 +2573 1895 2081 +2573 1896 2081 +2573 1897 2082 +2574 1898 2082 +2574 1900 2083 +2575 1903 2084 +2575 1906 2086 +2575 1906 2088 +2575 1906 2090 +2575 1906 2094 +2575 1906 2099 +2575 1907 2109 +2576 1913 2129 +2577 1915 2152 +2578 1893 2171 +2576 1899 2221 +2578 1919 2273 +2580 1949 2338 +2587 1961 2408 +2611 2008 2495 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2588 1996 2083 +2588 1997 2083 +2588 1997 2084 +2588 1997 2085 +2588 1997 2086 +2588 1998 2087 +2588 1998 2088 +2588 1999 2091 +2588 2000 2093 +2588 2001 2098 +2588 2005 2100 +2589 2012 2104 +2591 2018 2108 +2588 2010 2114 +2588 2009 2126 +2589 2014 2149 +2590 2016 2184 +2591 2003 2214 +2591 2019 2275 +2595 2044 2342 +2604 2072 2411 +2625 2108 2494 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2625 2149 2111 +2624 2149 2111 +2624 2149 2111 +2624 2149 2111 +2624 2148 2111 +2624 2148 2111 +2623 2147 2111 +2623 2146 2111 +2622 2145 2111 +2621 2143 2111 +2620 2141 2111 +2618 2137 2111 +2617 2136 2114 +2617 2144 2126 +2617 2155 2141 +2619 2157 2164 +2623 2160 2195 +2624 2165 2231 +2619 2165 2275 +2633 2187 2352 +2638 2190 2417 +2660 2223 2503 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2670 2315 2112 +2671 2315 2112 +2671 2315 2112 +2671 2315 2111 +2671 2316 2111 +2672 2316 2111 +2672 2316 2111 +2673 2317 2110 +2674 2318 2109 +2675 2319 2108 +2677 2321 2107 +2680 2323 2105 +2682 2325 2106 +2681 2325 2118 +2680 2325 2133 +2678 2328 2149 +2677 2328 2176 +2677 2325 2215 +2687 2335 2275 +2689 2335 2316 +2695 2346 2391 +2724 2369 2462 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2775 2531 1744 +2775 2531 1745 +2775 2531 1747 +2775 2531 1750 +2776 2532 1753 +2776 2532 1758 +2776 2533 1764 +2776 2533 1772 +2777 2534 1782 +2778 2535 1796 +2778 2536 1813 +2778 2537 1825 +2777 2535 1833 +2776 2530 1839 +2776 2528 1859 +2778 2535 1929 +2779 2534 1991 +2780 2535 2071 +2782 2538 2158 +2784 2536 2248 +2791 2552 2360 +2803 2569 2485 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2826 2762 2506 +2826 2762 2506 +2826 2762 2505 +2826 2762 2505 +2826 2762 2505 +2826 2762 2505 +2826 2761 2505 +2826 2761 2505 +2826 2761 2505 +2826 2761 2506 +2826 2761 2507 +2826 2761 2509 +2826 2761 2510 +2826 2760 2508 +2826 2760 2508 +2826 2762 2520 +2826 2764 2535 +2826 2763 2548 +2826 2763 2571 +2826 2767 2613 +2826 2769 2662 +2826 2779 2732 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2554 1623 2059 +2554 1623 2059 +2554 1623 2060 +2554 1623 2060 +2554 1623 2061 +2554 1623 2063 +2554 1623 2065 +2554 1623 2067 +2554 1623 2070 +2554 1623 2074 +2554 1623 2080 +2554 1623 2087 +2554 1621 2096 +2554 1621 2102 +2554 1621 2110 +2555 1588 2133 +2556 1555 2169 +2555 1608 2217 +2557 1691 2269 +2563 1692 2342 +2564 1761 2409 +2587 1838 2491 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2554 1625 2059 +2554 1624 2059 +2554 1624 2060 +2554 1624 2060 +2554 1624 2061 +2554 1624 2063 +2554 1624 2064 +2554 1624 2067 +2554 1624 2070 +2554 1624 2074 +2554 1624 2080 +2554 1624 2087 +2554 1621 2096 +2554 1621 2102 +2554 1621 2110 +2556 1590 2134 +2556 1556 2169 +2555 1609 2217 +2557 1691 2269 +2563 1692 2342 +2564 1762 2409 +2587 1839 2492 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2554 1627 2059 +2554 1626 2059 +2554 1625 2060 +2554 1625 2060 +2554 1625 2061 +2554 1625 2063 +2554 1625 2064 +2554 1625 2067 +2554 1625 2070 +2554 1625 2074 +2554 1625 2079 +2554 1625 2086 +2554 1622 2096 +2554 1621 2102 +2554 1621 2110 +2556 1592 2134 +2556 1559 2169 +2555 1610 2217 +2557 1691 2269 +2564 1693 2342 +2564 1764 2409 +2587 1840 2492 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2554 1630 2060 +2554 1629 2060 +2554 1627 2060 +2554 1625 2060 +2554 1625 2061 +2554 1625 2062 +2554 1625 2064 +2554 1625 2066 +2554 1625 2070 +2554 1625 2074 +2554 1625 2079 +2554 1625 2086 +2554 1623 2095 +2554 1621 2102 +2554 1621 2110 +2556 1595 2134 +2556 1562 2169 +2555 1611 2217 +2557 1691 2270 +2564 1694 2342 +2564 1765 2409 +2587 1842 2492 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2554 1633 2060 +2554 1632 2060 +2554 1631 2060 +2554 1629 2060 +2554 1626 2061 +2554 1626 2062 +2554 1626 2064 +2554 1626 2066 +2554 1626 2069 +2554 1626 2073 +2554 1626 2079 +2554 1626 2086 +2554 1625 2095 +2554 1621 2102 +2554 1621 2110 +2556 1599 2135 +2556 1567 2169 +2555 1613 2217 +2557 1692 2270 +2564 1695 2342 +2565 1768 2409 +2587 1844 2492 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2554 1638 2061 +2554 1638 2061 +2554 1636 2061 +2554 1634 2061 +2554 1631 2061 +2554 1628 2062 +2554 1628 2063 +2554 1628 2066 +2554 1628 2069 +2554 1628 2073 +2554 1628 2079 +2554 1628 2086 +2554 1626 2095 +2554 1621 2102 +2554 1621 2110 +2556 1605 2135 +2556 1572 2169 +2555 1616 2217 +2557 1693 2270 +2564 1696 2342 +2565 1771 2409 +2587 1847 2492 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2555 1645 2062 +2555 1644 2062 +2555 1643 2062 +2555 1641 2062 +2555 1638 2062 +2555 1635 2063 +2555 1631 2063 +2555 1631 2066 +2555 1631 2069 +2555 1631 2073 +2555 1631 2078 +2555 1631 2085 +2555 1628 2094 +2554 1621 2102 +2554 1621 2110 +2556 1612 2136 +2556 1580 2169 +2554 1619 2217 +2558 1694 2270 +2564 1698 2342 +2565 1775 2409 +2587 1852 2492 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2555 1654 2063 +2555 1653 2063 +2555 1651 2063 +2555 1650 2063 +2555 1647 2063 +2555 1644 2064 +2555 1640 2064 +2555 1633 2065 +2555 1633 2068 +2555 1633 2072 +2555 1633 2078 +2555 1633 2085 +2555 1631 2094 +2554 1621 2102 +2554 1621 2110 +2556 1621 2137 +2557 1590 2169 +2554 1624 2217 +2558 1695 2270 +2564 1701 2342 +2565 1781 2409 +2588 1857 2493 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2556 1665 2064 +2556 1664 2065 +2556 1663 2065 +2556 1661 2065 +2556 1659 2065 +2556 1655 2066 +2556 1651 2066 +2556 1646 2066 +2556 1638 2067 +2556 1638 2071 +2556 1638 2077 +2556 1638 2084 +2556 1636 2093 +2554 1621 2102 +2554 1621 2110 +2556 1633 2138 +2557 1603 2169 +2554 1630 2217 +2558 1697 2271 +2564 1704 2342 +2565 1788 2409 +2588 1860 2493 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2556 1680 2066 +2556 1679 2067 +2556 1678 2067 +2556 1676 2067 +2556 1674 2067 +2556 1671 2068 +2556 1667 2068 +2556 1661 2069 +2556 1653 2069 +2556 1643 2070 +2556 1643 2076 +2556 1643 2083 +2556 1641 2092 +2554 1624 2101 +2554 1621 2110 +2557 1649 2140 +2557 1620 2170 +2554 1638 2217 +2558 1699 2271 +2565 1709 2342 +2566 1798 2409 +2589 1863 2493 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2558 1699 2069 +2558 1698 2069 +2558 1697 2070 +2558 1695 2070 +2558 1693 2070 +2558 1690 2070 +2558 1686 2071 +2558 1681 2071 +2558 1674 2072 +2558 1663 2073 +2558 1650 2074 +2558 1650 2082 +2557 1648 2091 +2555 1631 2100 +2554 1621 2110 +2557 1657 2141 +2558 1642 2173 +2554 1658 2217 +2559 1702 2273 +2565 1715 2342 +2566 1810 2409 +2589 1868 2493 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2559 1723 2073 +2559 1723 2073 +2559 1722 2073 +2559 1720 2073 +2559 1718 2074 +2559 1715 2074 +2559 1711 2074 +2559 1706 2075 +2559 1699 2076 +2559 1690 2077 +2559 1677 2078 +2559 1659 2080 +2558 1657 2089 +2556 1641 2098 +2554 1621 2110 +2557 1657 2141 +2558 1669 2176 +2555 1684 2217 +2560 1706 2274 +2566 1723 2342 +2567 1816 2409 +2591 1873 2493 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2560 1754 2078 +2560 1754 2078 +2560 1753 2078 +2560 1752 2079 +2560 1750 2079 +2560 1747 2079 +2560 1744 2080 +2560 1739 2080 +2560 1732 2081 +2560 1724 2082 +2560 1712 2083 +2560 1695 2085 +2560 1674 2088 +2558 1658 2097 +2555 1635 2110 +2557 1661 2141 +2559 1703 2179 +2556 1716 2217 +2560 1716 2275 +2566 1739 2342 +2568 1818 2408 +2592 1880 2493 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2562 1761 2078 +2562 1761 2078 +2562 1761 2079 +2562 1762 2080 +2562 1763 2080 +2562 1765 2082 +2562 1766 2084 +2562 1769 2086 +2562 1772 2089 +2563 1771 2091 +2563 1760 2093 +2563 1745 2094 +2562 1727 2097 +2561 1712 2103 +2558 1692 2116 +2556 1693 2138 +2560 1738 2181 +2560 1744 2217 +2561 1744 2275 +2566 1785 2340 +2571 1835 2406 +2592 1893 2492 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2563 1769 2078 +2563 1769 2078 +2563 1770 2079 +2563 1771 2080 +2563 1772 2080 +2563 1773 2082 +2564 1775 2084 +2564 1777 2086 +2564 1780 2089 +2564 1784 2093 +2565 1789 2098 +2565 1796 2105 +2566 1789 2110 +2564 1776 2116 +2563 1758 2124 +2559 1753 2143 +2558 1773 2177 +2563 1787 2220 +2563 1779 2275 +2566 1840 2337 +2576 1860 2406 +2591 1925 2491 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2566 1822 2077 +2566 1822 2078 +2566 1822 2078 +2566 1822 2078 +2566 1822 2079 +2566 1822 2079 +2566 1822 2080 +2566 1822 2081 +2566 1822 2083 +2566 1822 2085 +2567 1824 2089 +2568 1831 2096 +2568 1839 2106 +2570 1844 2121 +2568 1834 2131 +2568 1813 2145 +2564 1813 2176 +2565 1838 2221 +2568 1838 2272 +2573 1888 2337 +2580 1896 2406 +2599 1967 2492 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2573 1894 2080 +2573 1894 2081 +2573 1895 2081 +2573 1896 2081 +2573 1897 2082 +2574 1898 2082 +2574 1900 2083 +2575 1903 2084 +2575 1906 2086 +2575 1906 2088 +2575 1906 2090 +2575 1906 2094 +2575 1906 2099 +2575 1907 2109 +2576 1913 2129 +2577 1915 2152 +2578 1893 2171 +2576 1899 2221 +2578 1919 2273 +2580 1949 2338 +2587 1961 2408 +2611 2008 2495 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2588 1996 2083 +2588 1997 2083 +2588 1997 2084 +2588 1997 2085 +2588 1997 2086 +2588 1998 2087 +2588 1998 2088 +2588 1999 2091 +2588 2000 2093 +2588 2001 2098 +2588 2005 2100 +2589 2012 2104 +2591 2018 2108 +2588 2010 2114 +2588 2009 2126 +2589 2014 2149 +2590 2016 2184 +2591 2003 2214 +2591 2019 2275 +2595 2044 2342 +2604 2072 2411 +2625 2108 2494 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2625 2149 2111 +2624 2149 2111 +2624 2149 2111 +2624 2149 2111 +2624 2148 2111 +2624 2148 2111 +2623 2147 2111 +2623 2146 2111 +2622 2145 2111 +2621 2143 2111 +2620 2141 2111 +2618 2137 2111 +2617 2136 2114 +2617 2144 2126 +2617 2155 2141 +2619 2157 2164 +2623 2160 2195 +2624 2165 2231 +2619 2165 2275 +2633 2187 2352 +2638 2190 2417 +2660 2223 2503 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2670 2315 2112 +2671 2315 2112 +2671 2315 2112 +2671 2315 2111 +2671 2316 2111 +2672 2316 2111 +2672 2316 2111 +2673 2317 2110 +2674 2318 2109 +2675 2319 2108 +2677 2321 2107 +2680 2323 2105 +2682 2325 2106 +2681 2325 2118 +2680 2325 2133 +2678 2328 2149 +2677 2328 2176 +2677 2325 2215 +2687 2335 2275 +2689 2335 2316 +2695 2346 2391 +2724 2369 2462 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2775 2531 1744 +2775 2531 1745 +2775 2531 1747 +2775 2531 1750 +2776 2532 1753 +2776 2532 1758 +2776 2533 1764 +2776 2533 1772 +2777 2534 1782 +2778 2535 1796 +2778 2536 1813 +2778 2537 1825 +2777 2535 1833 +2776 2530 1839 +2776 2528 1859 +2778 2535 1929 +2779 2534 1991 +2780 2535 2071 +2782 2538 2158 +2784 2536 2248 +2791 2552 2360 +2803 2569 2485 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2826 2762 2506 +2826 2762 2506 +2826 2762 2505 +2826 2762 2505 +2826 2762 2505 +2826 2762 2505 +2826 2761 2505 +2826 2761 2505 +2826 2761 2505 +2826 2761 2506 +2826 2761 2507 +2826 2761 2509 +2826 2761 2510 +2826 2760 2508 +2826 2760 2508 +2826 2762 2520 +2826 2764 2535 +2826 2763 2548 +2826 2763 2571 +2826 2767 2613 +2826 2769 2662 +2826 2779 2732 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2554 1623 2059 +2554 1623 2059 +2554 1623 2060 +2554 1623 2060 +2554 1623 2061 +2554 1623 2063 +2554 1623 2065 +2554 1623 2067 +2554 1623 2070 +2554 1623 2074 +2554 1623 2080 +2554 1623 2087 +2554 1621 2096 +2554 1621 2102 +2554 1621 2110 +2555 1588 2133 +2556 1555 2169 +2555 1608 2217 +2557 1691 2269 +2563 1692 2342 +2564 1761 2409 +2587 1838 2491 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2554 1625 2059 +2554 1624 2059 +2554 1624 2060 +2554 1624 2060 +2554 1624 2061 +2554 1624 2063 +2554 1624 2064 +2554 1624 2067 +2554 1624 2070 +2554 1624 2074 +2554 1624 2080 +2554 1624 2087 +2554 1621 2096 +2554 1621 2102 +2554 1621 2110 +2556 1590 2134 +2556 1556 2169 +2555 1609 2217 +2557 1691 2269 +2563 1692 2342 +2564 1762 2409 +2587 1839 2492 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2554 1627 2059 +2554 1626 2059 +2554 1625 2060 +2554 1625 2060 +2554 1625 2061 +2554 1625 2063 +2554 1625 2064 +2554 1625 2067 +2554 1625 2070 +2554 1625 2074 +2554 1625 2079 +2554 1625 2086 +2554 1622 2096 +2554 1621 2102 +2554 1621 2110 +2556 1592 2134 +2556 1559 2169 +2555 1610 2217 +2557 1691 2269 +2564 1693 2342 +2564 1764 2409 +2587 1840 2492 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2554 1630 2060 +2554 1629 2060 +2554 1627 2060 +2554 1625 2060 +2554 1625 2061 +2554 1625 2062 +2554 1625 2064 +2554 1625 2066 +2554 1625 2070 +2554 1625 2074 +2554 1625 2079 +2554 1625 2086 +2554 1623 2095 +2554 1621 2102 +2554 1621 2110 +2556 1595 2134 +2556 1562 2169 +2555 1611 2217 +2557 1691 2270 +2564 1694 2342 +2564 1765 2409 +2587 1842 2492 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2554 1633 2060 +2554 1632 2060 +2554 1631 2060 +2554 1629 2060 +2554 1626 2061 +2554 1626 2062 +2554 1626 2064 +2554 1626 2066 +2554 1626 2069 +2554 1626 2073 +2554 1626 2079 +2554 1626 2086 +2554 1625 2095 +2554 1621 2102 +2554 1621 2110 +2556 1599 2135 +2556 1567 2169 +2555 1613 2217 +2557 1692 2270 +2564 1695 2342 +2565 1768 2409 +2587 1844 2492 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2554 1638 2061 +2554 1638 2061 +2554 1636 2061 +2554 1634 2061 +2554 1631 2061 +2554 1628 2062 +2554 1628 2063 +2554 1628 2066 +2554 1628 2069 +2554 1628 2073 +2554 1628 2079 +2554 1628 2086 +2554 1626 2095 +2554 1621 2102 +2554 1621 2110 +2556 1605 2135 +2556 1572 2169 +2555 1616 2217 +2557 1693 2270 +2564 1696 2342 +2565 1771 2409 +2587 1847 2492 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2555 1645 2062 +2555 1644 2062 +2555 1643 2062 +2555 1641 2062 +2555 1638 2062 +2555 1635 2063 +2555 1631 2063 +2555 1631 2066 +2555 1631 2069 +2555 1631 2073 +2555 1631 2078 +2555 1631 2085 +2555 1628 2094 +2554 1621 2102 +2554 1621 2110 +2556 1612 2136 +2556 1580 2169 +2554 1619 2217 +2558 1694 2270 +2564 1698 2342 +2565 1775 2409 +2587 1852 2492 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2555 1654 2063 +2555 1653 2063 +2555 1651 2063 +2555 1650 2063 +2555 1647 2063 +2555 1644 2064 +2555 1640 2064 +2555 1633 2065 +2555 1633 2068 +2555 1633 2072 +2555 1633 2078 +2555 1633 2085 +2555 1631 2094 +2554 1621 2102 +2554 1621 2110 +2556 1621 2137 +2557 1590 2169 +2554 1624 2217 +2558 1695 2270 +2564 1701 2342 +2565 1781 2409 +2588 1857 2493 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2556 1665 2064 +2556 1664 2065 +2556 1663 2065 +2556 1661 2065 +2556 1659 2065 +2556 1655 2066 +2556 1651 2066 +2556 1646 2066 +2556 1638 2067 +2556 1638 2071 +2556 1638 2077 +2556 1638 2084 +2556 1636 2093 +2554 1621 2102 +2554 1621 2110 +2556 1633 2138 +2557 1603 2169 +2554 1630 2217 +2558 1697 2271 +2564 1704 2342 +2565 1788 2409 +2588 1860 2493 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2556 1680 2066 +2556 1679 2067 +2556 1678 2067 +2556 1676 2067 +2556 1674 2067 +2556 1671 2068 +2556 1667 2068 +2556 1661 2069 +2556 1653 2069 +2556 1643 2070 +2556 1643 2076 +2556 1643 2083 +2556 1641 2092 +2554 1624 2101 +2554 1621 2110 +2557 1649 2140 +2557 1620 2170 +2554 1638 2217 +2558 1699 2271 +2565 1709 2342 +2566 1798 2409 +2589 1863 2493 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2558 1699 2069 +2558 1698 2069 +2558 1697 2070 +2558 1695 2070 +2558 1693 2070 +2558 1690 2070 +2558 1686 2071 +2558 1681 2071 +2558 1674 2072 +2558 1663 2073 +2558 1650 2074 +2558 1650 2082 +2557 1648 2091 +2555 1631 2100 +2554 1621 2110 +2557 1657 2141 +2558 1642 2173 +2554 1658 2217 +2559 1702 2273 +2565 1715 2342 +2566 1810 2409 +2589 1868 2493 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2559 1723 2073 +2559 1723 2073 +2559 1722 2073 +2559 1720 2073 +2559 1718 2074 +2559 1715 2074 +2559 1711 2074 +2559 1706 2075 +2559 1699 2076 +2559 1690 2077 +2559 1677 2078 +2559 1659 2080 +2558 1657 2089 +2556 1641 2098 +2554 1621 2110 +2557 1657 2141 +2558 1669 2176 +2555 1684 2217 +2560 1706 2274 +2566 1723 2342 +2567 1816 2409 +2591 1873 2493 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2560 1754 2078 +2560 1754 2078 +2560 1753 2078 +2560 1752 2079 +2560 1750 2079 +2560 1747 2079 +2560 1744 2080 +2560 1739 2080 +2560 1732 2081 +2560 1724 2082 +2560 1712 2083 +2560 1695 2085 +2560 1674 2088 +2558 1658 2097 +2555 1635 2110 +2557 1661 2141 +2559 1703 2179 +2556 1716 2217 +2560 1716 2275 +2566 1739 2342 +2568 1818 2408 +2592 1880 2493 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2562 1761 2078 +2562 1761 2078 +2562 1761 2079 +2562 1762 2080 +2562 1763 2080 +2562 1765 2082 +2562 1766 2084 +2562 1769 2086 +2562 1772 2089 +2563 1771 2091 +2563 1760 2093 +2563 1745 2094 +2562 1727 2097 +2561 1712 2103 +2558 1692 2116 +2556 1693 2138 +2560 1738 2181 +2560 1744 2217 +2561 1744 2275 +2566 1785 2340 +2571 1835 2406 +2592 1893 2492 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2563 1769 2078 +2563 1769 2078 +2563 1770 2079 +2563 1771 2080 +2563 1772 2080 +2563 1773 2082 +2564 1775 2084 +2564 1777 2086 +2564 1780 2089 +2564 1784 2093 +2565 1789 2098 +2565 1796 2105 +2566 1789 2110 +2564 1776 2116 +2563 1758 2124 +2559 1753 2143 +2558 1773 2177 +2563 1787 2220 +2563 1779 2275 +2566 1840 2337 +2576 1860 2406 +2591 1925 2491 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2566 1822 2077 +2566 1822 2078 +2566 1822 2078 +2566 1822 2078 +2566 1822 2079 +2566 1822 2079 +2566 1822 2080 +2566 1822 2081 +2566 1822 2083 +2566 1822 2085 +2567 1824 2089 +2568 1831 2096 +2568 1839 2106 +2570 1844 2121 +2568 1834 2131 +2568 1813 2145 +2564 1813 2176 +2565 1838 2221 +2568 1838 2272 +2573 1888 2337 +2580 1896 2406 +2599 1967 2492 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2573 1894 2080 +2573 1894 2081 +2573 1895 2081 +2573 1896 2081 +2573 1897 2082 +2574 1898 2082 +2574 1900 2083 +2575 1903 2084 +2575 1906 2086 +2575 1906 2088 +2575 1906 2090 +2575 1906 2094 +2575 1906 2099 +2575 1907 2109 +2576 1913 2129 +2577 1915 2152 +2578 1893 2171 +2576 1899 2221 +2578 1919 2273 +2580 1949 2338 +2587 1961 2408 +2611 2008 2495 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2588 1996 2083 +2588 1997 2083 +2588 1997 2084 +2588 1997 2085 +2588 1997 2086 +2588 1998 2087 +2588 1998 2088 +2588 1999 2091 +2588 2000 2093 +2588 2001 2098 +2588 2005 2100 +2589 2012 2104 +2591 2018 2108 +2588 2010 2114 +2588 2009 2126 +2589 2014 2149 +2590 2016 2184 +2591 2003 2214 +2591 2019 2275 +2595 2044 2342 +2604 2072 2411 +2625 2108 2494 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2625 2149 2111 +2624 2149 2111 +2624 2149 2111 +2624 2149 2111 +2624 2148 2111 +2624 2148 2111 +2623 2147 2111 +2623 2146 2111 +2622 2145 2111 +2621 2143 2111 +2620 2141 2111 +2618 2137 2111 +2617 2136 2114 +2617 2144 2126 +2617 2155 2141 +2619 2157 2164 +2623 2160 2195 +2624 2165 2231 +2619 2165 2275 +2633 2187 2352 +2638 2190 2417 +2660 2223 2503 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2670 2315 2112 +2671 2315 2112 +2671 2315 2112 +2671 2315 2111 +2671 2316 2111 +2672 2316 2111 +2672 2316 2111 +2673 2317 2110 +2674 2318 2109 +2675 2319 2108 +2677 2321 2107 +2680 2323 2105 +2682 2325 2106 +2681 2325 2118 +2680 2325 2133 +2678 2328 2149 +2677 2328 2176 +2677 2325 2215 +2687 2335 2275 +2689 2335 2316 +2695 2346 2391 +2724 2369 2462 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2775 2531 1744 +2775 2531 1745 +2775 2531 1747 +2775 2531 1750 +2776 2532 1753 +2776 2532 1758 +2776 2533 1764 +2776 2533 1772 +2777 2534 1782 +2778 2535 1796 +2778 2536 1813 +2778 2537 1825 +2777 2535 1833 +2776 2530 1839 +2776 2528 1859 +2778 2535 1929 +2779 2534 1991 +2780 2535 2071 +2782 2538 2158 +2784 2536 2248 +2791 2552 2360 +2803 2569 2485 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2826 2762 2506 +2826 2762 2506 +2826 2762 2505 +2826 2762 2505 +2826 2762 2505 +2826 2762 2505 +2826 2761 2505 +2826 2761 2505 +2826 2761 2505 +2826 2761 2506 +2826 2761 2507 +2826 2761 2509 +2826 2761 2510 +2826 2760 2508 +2826 2760 2508 +2826 2762 2520 +2826 2764 2535 +2826 2763 2548 +2826 2763 2571 +2826 2767 2613 +2826 2769 2662 +2826 2779 2732 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2554 1623 2059 +2554 1623 2059 +2554 1623 2060 +2554 1623 2060 +2554 1623 2061 +2554 1623 2063 +2554 1623 2065 +2554 1623 2067 +2554 1623 2070 +2554 1623 2074 +2554 1623 2080 +2554 1623 2087 +2554 1621 2096 +2554 1621 2102 +2554 1621 2110 +2555 1588 2133 +2556 1555 2169 +2555 1608 2217 +2557 1691 2269 +2563 1692 2342 +2564 1761 2409 +2587 1838 2491 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2554 1625 2059 +2554 1624 2059 +2554 1624 2060 +2554 1624 2060 +2554 1624 2061 +2554 1624 2063 +2554 1624 2064 +2554 1624 2067 +2554 1624 2070 +2554 1624 2074 +2554 1624 2080 +2554 1624 2087 +2554 1621 2096 +2554 1621 2102 +2554 1621 2110 +2556 1590 2134 +2556 1556 2169 +2555 1609 2217 +2557 1691 2269 +2563 1692 2342 +2564 1762 2409 +2587 1839 2492 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2554 1627 2059 +2554 1626 2059 +2554 1625 2060 +2554 1625 2060 +2554 1625 2061 +2554 1625 2063 +2554 1625 2064 +2554 1625 2067 +2554 1625 2070 +2554 1625 2074 +2554 1625 2079 +2554 1625 2086 +2554 1622 2096 +2554 1621 2102 +2554 1621 2110 +2556 1592 2134 +2556 1559 2169 +2555 1610 2217 +2557 1691 2269 +2564 1693 2342 +2564 1764 2409 +2587 1840 2492 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2554 1630 2060 +2554 1629 2060 +2554 1627 2060 +2554 1625 2060 +2554 1625 2061 +2554 1625 2062 +2554 1625 2064 +2554 1625 2066 +2554 1625 2070 +2554 1625 2074 +2554 1625 2079 +2554 1625 2086 +2554 1623 2095 +2554 1621 2102 +2554 1621 2110 +2556 1595 2134 +2556 1562 2169 +2555 1611 2217 +2557 1691 2270 +2564 1694 2342 +2564 1765 2409 +2587 1842 2492 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2554 1633 2060 +2554 1632 2060 +2554 1631 2060 +2554 1629 2060 +2554 1626 2061 +2554 1626 2062 +2554 1626 2064 +2554 1626 2066 +2554 1626 2069 +2554 1626 2073 +2554 1626 2079 +2554 1626 2086 +2554 1625 2095 +2554 1621 2102 +2554 1621 2110 +2556 1599 2135 +2556 1567 2169 +2555 1613 2217 +2557 1692 2270 +2564 1695 2342 +2565 1768 2409 +2587 1844 2492 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2554 1638 2061 +2554 1638 2061 +2554 1636 2061 +2554 1634 2061 +2554 1631 2061 +2554 1628 2062 +2554 1628 2063 +2554 1628 2066 +2554 1628 2069 +2554 1628 2073 +2554 1628 2079 +2554 1628 2086 +2554 1626 2095 +2554 1621 2102 +2554 1621 2110 +2556 1605 2135 +2556 1572 2169 +2555 1616 2217 +2557 1693 2270 +2564 1696 2342 +2565 1771 2409 +2587 1847 2492 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2555 1645 2062 +2555 1644 2062 +2555 1643 2062 +2555 1641 2062 +2555 1638 2062 +2555 1635 2063 +2555 1631 2063 +2555 1631 2066 +2555 1631 2069 +2555 1631 2073 +2555 1631 2078 +2555 1631 2085 +2555 1628 2094 +2554 1621 2102 +2554 1621 2110 +2556 1612 2136 +2556 1580 2169 +2554 1619 2217 +2558 1694 2270 +2564 1698 2342 +2565 1775 2409 +2587 1852 2492 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2555 1654 2063 +2555 1653 2063 +2555 1651 2063 +2555 1650 2063 +2555 1647 2063 +2555 1644 2064 +2555 1640 2064 +2555 1633 2065 +2555 1633 2068 +2555 1633 2072 +2555 1633 2078 +2555 1633 2085 +2555 1631 2094 +2554 1621 2102 +2554 1621 2110 +2556 1621 2137 +2557 1590 2169 +2554 1624 2217 +2558 1695 2270 +2564 1701 2342 +2565 1781 2409 +2588 1857 2493 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2556 1665 2064 +2556 1664 2065 +2556 1663 2065 +2556 1661 2065 +2556 1659 2065 +2556 1655 2066 +2556 1651 2066 +2556 1646 2066 +2556 1638 2067 +2556 1638 2071 +2556 1638 2077 +2556 1638 2084 +2556 1636 2093 +2554 1621 2102 +2554 1621 2110 +2556 1633 2138 +2557 1603 2169 +2554 1630 2217 +2558 1697 2271 +2564 1704 2342 +2565 1788 2409 +2588 1860 2493 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2556 1680 2066 +2556 1679 2067 +2556 1678 2067 +2556 1676 2067 +2556 1674 2067 +2556 1671 2068 +2556 1667 2068 +2556 1661 2069 +2556 1653 2069 +2556 1643 2070 +2556 1643 2076 +2556 1643 2083 +2556 1641 2092 +2554 1624 2101 +2554 1621 2110 +2557 1649 2140 +2557 1620 2170 +2554 1638 2217 +2558 1699 2271 +2565 1709 2342 +2566 1798 2409 +2589 1863 2493 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2558 1699 2069 +2558 1698 2069 +2558 1697 2070 +2558 1695 2070 +2558 1693 2070 +2558 1690 2070 +2558 1686 2071 +2558 1681 2071 +2558 1674 2072 +2558 1663 2073 +2558 1650 2074 +2558 1650 2082 +2557 1648 2091 +2555 1631 2100 +2554 1621 2110 +2557 1657 2141 +2558 1642 2173 +2554 1658 2217 +2559 1702 2273 +2565 1715 2342 +2566 1810 2409 +2589 1868 2493 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2559 1723 2073 +2559 1723 2073 +2559 1722 2073 +2559 1720 2073 +2559 1718 2074 +2559 1715 2074 +2559 1711 2074 +2559 1706 2075 +2559 1699 2076 +2559 1690 2077 +2559 1677 2078 +2559 1659 2080 +2558 1657 2089 +2556 1641 2098 +2554 1621 2110 +2557 1657 2141 +2558 1669 2176 +2555 1684 2217 +2560 1706 2274 +2566 1723 2342 +2567 1816 2409 +2591 1873 2493 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2560 1754 2078 +2560 1754 2078 +2560 1753 2078 +2560 1752 2079 +2560 1750 2079 +2560 1747 2079 +2560 1744 2080 +2560 1739 2080 +2560 1732 2081 +2560 1724 2082 +2560 1712 2083 +2560 1695 2085 +2560 1674 2088 +2558 1658 2097 +2555 1635 2110 +2557 1661 2141 +2559 1703 2179 +2556 1716 2217 +2560 1716 2275 +2566 1739 2342 +2568 1818 2408 +2592 1880 2493 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2562 1761 2078 +2562 1761 2078 +2562 1761 2079 +2562 1762 2080 +2562 1763 2080 +2562 1765 2082 +2562 1766 2084 +2562 1769 2086 +2562 1772 2089 +2563 1771 2091 +2563 1760 2093 +2563 1745 2094 +2562 1727 2097 +2561 1712 2103 +2558 1692 2116 +2556 1693 2138 +2560 1738 2181 +2560 1744 2217 +2561 1744 2275 +2566 1785 2340 +2571 1835 2406 +2592 1893 2492 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2563 1769 2078 +2563 1769 2078 +2563 1770 2079 +2563 1771 2080 +2563 1772 2080 +2563 1773 2082 +2564 1775 2084 +2564 1777 2086 +2564 1780 2089 +2564 1784 2093 +2565 1789 2098 +2565 1796 2105 +2566 1789 2110 +2564 1776 2116 +2563 1758 2124 +2559 1753 2143 +2558 1773 2177 +2563 1787 2220 +2563 1779 2275 +2566 1840 2337 +2576 1860 2406 +2591 1925 2491 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2566 1822 2077 +2566 1822 2078 +2566 1822 2078 +2566 1822 2078 +2566 1822 2079 +2566 1822 2079 +2566 1822 2080 +2566 1822 2081 +2566 1822 2083 +2566 1822 2085 +2567 1824 2089 +2568 1831 2096 +2568 1839 2106 +2570 1844 2121 +2568 1834 2131 +2568 1813 2145 +2564 1813 2176 +2565 1838 2221 +2568 1838 2272 +2573 1888 2337 +2580 1896 2406 +2599 1967 2492 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2573 1894 2080 +2573 1894 2081 +2573 1895 2081 +2573 1896 2081 +2573 1897 2082 +2574 1898 2082 +2574 1900 2083 +2575 1903 2084 +2575 1906 2086 +2575 1906 2088 +2575 1906 2090 +2575 1906 2094 +2575 1906 2099 +2575 1907 2109 +2576 1913 2129 +2577 1915 2152 +2578 1893 2171 +2576 1899 2221 +2578 1919 2273 +2580 1949 2338 +2587 1961 2408 +2611 2008 2495 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2588 1996 2083 +2588 1997 2083 +2588 1997 2084 +2588 1997 2085 +2588 1997 2086 +2588 1998 2087 +2588 1998 2088 +2588 1999 2091 +2588 2000 2093 +2588 2001 2098 +2588 2005 2100 +2589 2012 2104 +2591 2018 2108 +2588 2010 2114 +2588 2009 2126 +2589 2014 2149 +2590 2016 2184 +2591 2003 2214 +2591 2019 2275 +2595 2044 2342 +2604 2072 2411 +2625 2108 2494 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2625 2149 2111 +2624 2149 2111 +2624 2149 2111 +2624 2149 2111 +2624 2148 2111 +2624 2148 2111 +2623 2147 2111 +2623 2146 2111 +2622 2145 2111 +2621 2143 2111 +2620 2141 2111 +2618 2137 2111 +2617 2136 2114 +2617 2144 2126 +2617 2155 2141 +2619 2157 2164 +2623 2160 2195 +2624 2165 2231 +2619 2165 2275 +2633 2187 2352 +2638 2190 2417 +2660 2223 2503 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2670 2315 2112 +2671 2315 2112 +2671 2315 2112 +2671 2315 2111 +2671 2316 2111 +2672 2316 2111 +2672 2316 2111 +2673 2317 2110 +2674 2318 2109 +2675 2319 2108 +2677 2321 2107 +2680 2323 2105 +2682 2325 2106 +2681 2325 2118 +2680 2325 2133 +2678 2328 2149 +2677 2328 2176 +2677 2325 2215 +2687 2335 2275 +2689 2335 2316 +2695 2346 2391 +2724 2369 2462 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2775 2531 1744 +2775 2531 1745 +2775 2531 1747 +2775 2531 1750 +2776 2532 1753 +2776 2532 1758 +2776 2533 1764 +2776 2533 1772 +2777 2534 1782 +2778 2535 1796 +2778 2536 1813 +2778 2537 1825 +2777 2535 1833 +2776 2530 1839 +2776 2528 1859 +2778 2535 1929 +2779 2534 1991 +2780 2535 2071 +2782 2538 2158 +2784 2536 2248 +2791 2552 2360 +2803 2569 2485 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2826 2762 2506 +2826 2762 2506 +2826 2762 2505 +2826 2762 2505 +2826 2762 2505 +2826 2762 2505 +2826 2761 2505 +2826 2761 2505 +2826 2761 2505 +2826 2761 2506 +2826 2761 2507 +2826 2761 2509 +2826 2761 2510 +2826 2760 2508 +2826 2760 2508 +2826 2762 2520 +2826 2764 2535 +2826 2763 2548 +2826 2763 2571 +2826 2767 2613 +2826 2769 2662 +2826 2779 2732 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2554 1623 2059 +2554 1623 2059 +2554 1623 2060 +2554 1623 2060 +2554 1623 2061 +2554 1623 2063 +2554 1623 2065 +2554 1623 2067 +2554 1623 2070 +2554 1623 2074 +2554 1623 2080 +2554 1623 2087 +2554 1621 2096 +2554 1621 2102 +2554 1621 2110 +2555 1588 2133 +2556 1555 2169 +2555 1608 2217 +2557 1691 2269 +2563 1692 2342 +2564 1761 2409 +2587 1838 2491 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2554 1625 2059 +2554 1624 2059 +2554 1624 2060 +2554 1624 2060 +2554 1624 2061 +2554 1624 2063 +2554 1624 2064 +2554 1624 2067 +2554 1624 2070 +2554 1624 2074 +2554 1624 2080 +2554 1624 2087 +2554 1621 2096 +2554 1621 2102 +2554 1621 2110 +2556 1590 2134 +2556 1556 2169 +2555 1609 2217 +2557 1691 2269 +2563 1692 2342 +2564 1762 2409 +2587 1839 2492 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2554 1627 2059 +2554 1626 2059 +2554 1625 2060 +2554 1625 2060 +2554 1625 2061 +2554 1625 2063 +2554 1625 2064 +2554 1625 2067 +2554 1625 2070 +2554 1625 2074 +2554 1625 2079 +2554 1625 2086 +2554 1622 2096 +2554 1621 2102 +2554 1621 2110 +2556 1592 2134 +2556 1559 2169 +2555 1610 2217 +2557 1691 2269 +2564 1693 2342 +2564 1764 2409 +2587 1840 2492 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2554 1630 2060 +2554 1629 2060 +2554 1627 2060 +2554 1625 2060 +2554 1625 2061 +2554 1625 2062 +2554 1625 2064 +2554 1625 2066 +2554 1625 2070 +2554 1625 2074 +2554 1625 2079 +2554 1625 2086 +2554 1623 2095 +2554 1621 2102 +2554 1621 2110 +2556 1595 2134 +2556 1562 2169 +2555 1611 2217 +2557 1691 2270 +2564 1694 2342 +2564 1765 2409 +2587 1842 2492 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2554 1633 2060 +2554 1632 2060 +2554 1631 2060 +2554 1629 2060 +2554 1626 2061 +2554 1626 2062 +2554 1626 2064 +2554 1626 2066 +2554 1626 2069 +2554 1626 2073 +2554 1626 2079 +2554 1626 2086 +2554 1625 2095 +2554 1621 2102 +2554 1621 2110 +2556 1599 2135 +2556 1567 2169 +2555 1613 2217 +2557 1692 2270 +2564 1695 2342 +2565 1768 2409 +2587 1844 2492 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2554 1638 2061 +2554 1638 2061 +2554 1636 2061 +2554 1634 2061 +2554 1631 2061 +2554 1628 2062 +2554 1628 2063 +2554 1628 2066 +2554 1628 2069 +2554 1628 2073 +2554 1628 2079 +2554 1628 2086 +2554 1626 2095 +2554 1621 2102 +2554 1621 2110 +2556 1605 2135 +2556 1572 2169 +2555 1616 2217 +2557 1693 2270 +2564 1696 2342 +2565 1771 2409 +2587 1847 2492 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2555 1645 2062 +2555 1644 2062 +2555 1643 2062 +2555 1641 2062 +2555 1638 2062 +2555 1635 2063 +2555 1631 2063 +2555 1631 2066 +2555 1631 2069 +2555 1631 2073 +2555 1631 2078 +2555 1631 2085 +2555 1628 2094 +2554 1621 2102 +2554 1621 2110 +2556 1612 2136 +2556 1580 2169 +2554 1619 2217 +2558 1694 2270 +2564 1698 2342 +2565 1775 2409 +2587 1852 2492 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2555 1654 2063 +2555 1653 2063 +2555 1651 2063 +2555 1650 2063 +2555 1647 2063 +2555 1644 2064 +2555 1640 2064 +2555 1633 2065 +2555 1633 2068 +2555 1633 2072 +2555 1633 2078 +2555 1633 2085 +2555 1631 2094 +2554 1621 2102 +2554 1621 2110 +2556 1621 2137 +2557 1590 2169 +2554 1624 2217 +2558 1695 2270 +2564 1701 2342 +2565 1781 2409 +2588 1857 2493 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2556 1665 2064 +2556 1664 2065 +2556 1663 2065 +2556 1661 2065 +2556 1659 2065 +2556 1655 2066 +2556 1651 2066 +2556 1646 2066 +2556 1638 2067 +2556 1638 2071 +2556 1638 2077 +2556 1638 2084 +2556 1636 2093 +2554 1621 2102 +2554 1621 2110 +2556 1633 2138 +2557 1603 2169 +2554 1630 2217 +2558 1697 2271 +2564 1704 2342 +2565 1788 2409 +2588 1860 2493 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2556 1680 2066 +2556 1679 2067 +2556 1678 2067 +2556 1676 2067 +2556 1674 2067 +2556 1671 2068 +2556 1667 2068 +2556 1661 2069 +2556 1653 2069 +2556 1643 2070 +2556 1643 2076 +2556 1643 2083 +2556 1641 2092 +2554 1624 2101 +2554 1621 2110 +2557 1649 2140 +2557 1620 2170 +2554 1638 2217 +2558 1699 2271 +2565 1709 2342 +2566 1798 2409 +2589 1863 2493 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2558 1699 2069 +2558 1698 2069 +2558 1697 2070 +2558 1695 2070 +2558 1693 2070 +2558 1690 2070 +2558 1686 2071 +2558 1681 2071 +2558 1674 2072 +2558 1663 2073 +2558 1650 2074 +2558 1650 2082 +2557 1648 2091 +2555 1631 2100 +2554 1621 2110 +2557 1657 2141 +2558 1642 2173 +2554 1658 2217 +2559 1702 2273 +2565 1715 2342 +2566 1810 2409 +2589 1868 2493 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2559 1723 2073 +2559 1723 2073 +2559 1722 2073 +2559 1720 2073 +2559 1718 2074 +2559 1715 2074 +2559 1711 2074 +2559 1706 2075 +2559 1699 2076 +2559 1690 2077 +2559 1677 2078 +2559 1659 2080 +2558 1657 2089 +2556 1641 2098 +2554 1621 2110 +2557 1657 2141 +2558 1669 2176 +2555 1684 2217 +2560 1706 2274 +2566 1723 2342 +2567 1816 2409 +2591 1873 2493 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2560 1754 2078 +2560 1754 2078 +2560 1753 2078 +2560 1752 2079 +2560 1750 2079 +2560 1747 2079 +2560 1744 2080 +2560 1739 2080 +2560 1732 2081 +2560 1724 2082 +2560 1712 2083 +2560 1695 2085 +2560 1674 2088 +2558 1658 2097 +2555 1635 2110 +2557 1661 2141 +2559 1703 2179 +2556 1716 2217 +2560 1716 2275 +2566 1739 2342 +2568 1818 2408 +2592 1880 2493 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2562 1761 2078 +2562 1761 2078 +2562 1761 2079 +2562 1762 2080 +2562 1763 2080 +2562 1765 2082 +2562 1766 2084 +2562 1769 2086 +2562 1772 2089 +2563 1771 2091 +2563 1760 2093 +2563 1745 2094 +2562 1727 2097 +2561 1712 2103 +2558 1692 2116 +2556 1693 2138 +2560 1738 2181 +2560 1744 2217 +2561 1744 2275 +2566 1785 2340 +2571 1835 2406 +2592 1893 2492 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2563 1769 2078 +2563 1769 2078 +2563 1770 2079 +2563 1771 2080 +2563 1772 2080 +2563 1773 2082 +2564 1775 2084 +2564 1777 2086 +2564 1780 2089 +2564 1784 2093 +2565 1789 2098 +2565 1796 2105 +2566 1789 2110 +2564 1776 2116 +2563 1758 2124 +2559 1753 2143 +2558 1773 2177 +2563 1787 2220 +2563 1779 2275 +2566 1840 2337 +2576 1860 2406 +2591 1925 2491 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2566 1822 2077 +2566 1822 2078 +2566 1822 2078 +2566 1822 2078 +2566 1822 2079 +2566 1822 2079 +2566 1822 2080 +2566 1822 2081 +2566 1822 2083 +2566 1822 2085 +2567 1824 2089 +2568 1831 2096 +2568 1839 2106 +2570 1844 2121 +2568 1834 2131 +2568 1813 2145 +2564 1813 2176 +2565 1838 2221 +2568 1838 2272 +2573 1888 2337 +2580 1896 2406 +2599 1967 2492 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2573 1894 2080 +2573 1894 2081 +2573 1895 2081 +2573 1896 2081 +2573 1897 2082 +2574 1898 2082 +2574 1900 2083 +2575 1903 2084 +2575 1906 2086 +2575 1906 2088 +2575 1906 2090 +2575 1906 2094 +2575 1906 2099 +2575 1907 2109 +2576 1913 2129 +2577 1915 2152 +2578 1893 2171 +2576 1899 2221 +2578 1919 2273 +2580 1949 2338 +2587 1961 2408 +2611 2008 2495 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2588 1996 2083 +2588 1997 2083 +2588 1997 2084 +2588 1997 2085 +2588 1997 2086 +2588 1998 2087 +2588 1998 2088 +2588 1999 2091 +2588 2000 2093 +2588 2001 2098 +2588 2005 2100 +2589 2012 2104 +2591 2018 2108 +2588 2010 2114 +2588 2009 2126 +2589 2014 2149 +2590 2016 2184 +2591 2003 2214 +2591 2019 2275 +2595 2044 2342 +2604 2072 2411 +2625 2108 2494 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2625 2149 2111 +2624 2149 2111 +2624 2149 2111 +2624 2149 2111 +2624 2148 2111 +2624 2148 2111 +2623 2147 2111 +2623 2146 2111 +2622 2145 2111 +2621 2143 2111 +2620 2141 2111 +2618 2137 2111 +2617 2136 2114 +2617 2144 2126 +2617 2155 2141 +2619 2157 2164 +2623 2160 2195 +2624 2165 2231 +2619 2165 2275 +2633 2187 2352 +2638 2190 2417 +2660 2223 2503 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2670 2315 2112 +2671 2315 2112 +2671 2315 2112 +2671 2315 2111 +2671 2316 2111 +2672 2316 2111 +2672 2316 2111 +2673 2317 2110 +2674 2318 2109 +2675 2319 2108 +2677 2321 2107 +2680 2323 2105 +2682 2325 2106 +2681 2325 2118 +2680 2325 2133 +2678 2328 2149 +2677 2328 2176 +2677 2325 2215 +2687 2335 2275 +2689 2335 2316 +2695 2346 2391 +2724 2369 2462 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2775 2531 1744 +2775 2531 1745 +2775 2531 1747 +2775 2531 1750 +2776 2532 1753 +2776 2532 1758 +2776 2533 1764 +2776 2533 1772 +2777 2534 1782 +2778 2535 1796 +2778 2536 1813 +2778 2537 1825 +2777 2535 1833 +2776 2530 1839 +2776 2528 1859 +2778 2535 1929 +2779 2534 1991 +2780 2535 2071 +2782 2538 2158 +2784 2536 2248 +2791 2552 2360 +2803 2569 2485 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2826 2762 2506 +2826 2762 2506 +2826 2762 2505 +2826 2762 2505 +2826 2762 2505 +2826 2762 2505 +2826 2761 2505 +2826 2761 2505 +2826 2761 2505 +2826 2761 2506 +2826 2761 2507 +2826 2761 2509 +2826 2761 2510 +2826 2760 2508 +2826 2760 2508 +2826 2762 2520 +2826 2764 2535 +2826 2763 2548 +2826 2763 2571 +2826 2767 2613 +2826 2769 2662 +2826 2779 2732 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2554 1623 2059 +2554 1623 2059 +2554 1623 2060 +2554 1623 2060 +2554 1623 2061 +2554 1623 2063 +2554 1623 2065 +2554 1623 2067 +2554 1623 2070 +2554 1623 2074 +2554 1623 2080 +2554 1623 2087 +2554 1621 2096 +2554 1621 2102 +2554 1621 2110 +2555 1588 2133 +2556 1555 2169 +2555 1608 2217 +2557 1691 2269 +2563 1692 2342 +2564 1761 2409 +2587 1838 2491 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2554 1625 2059 +2554 1624 2059 +2554 1624 2060 +2554 1624 2060 +2554 1624 2061 +2554 1624 2063 +2554 1624 2064 +2554 1624 2067 +2554 1624 2070 +2554 1624 2074 +2554 1624 2080 +2554 1624 2087 +2554 1621 2096 +2554 1621 2102 +2554 1621 2110 +2556 1590 2134 +2556 1556 2169 +2555 1609 2217 +2557 1691 2269 +2563 1692 2342 +2564 1762 2409 +2587 1839 2492 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2554 1627 2059 +2554 1626 2059 +2554 1625 2060 +2554 1625 2060 +2554 1625 2061 +2554 1625 2063 +2554 1625 2064 +2554 1625 2067 +2554 1625 2070 +2554 1625 2074 +2554 1625 2079 +2554 1625 2086 +2554 1622 2096 +2554 1621 2102 +2554 1621 2110 +2556 1592 2134 +2556 1559 2169 +2555 1610 2217 +2557 1691 2269 +2564 1693 2342 +2564 1764 2409 +2587 1840 2492 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2554 1630 2060 +2554 1629 2060 +2554 1627 2060 +2554 1625 2060 +2554 1625 2061 +2554 1625 2062 +2554 1625 2064 +2554 1625 2066 +2554 1625 2070 +2554 1625 2074 +2554 1625 2079 +2554 1625 2086 +2554 1623 2095 +2554 1621 2102 +2554 1621 2110 +2556 1595 2134 +2556 1562 2169 +2555 1611 2217 +2557 1691 2270 +2564 1694 2342 +2564 1765 2409 +2587 1842 2492 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2554 1633 2060 +2554 1632 2060 +2554 1631 2060 +2554 1629 2060 +2554 1626 2061 +2554 1626 2062 +2554 1626 2064 +2554 1626 2066 +2554 1626 2069 +2554 1626 2073 +2554 1626 2079 +2554 1626 2086 +2554 1625 2095 +2554 1621 2102 +2554 1621 2110 +2556 1599 2135 +2556 1567 2169 +2555 1613 2217 +2557 1692 2270 +2564 1695 2342 +2565 1768 2409 +2587 1844 2492 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2554 1638 2061 +2554 1638 2061 +2554 1636 2061 +2554 1634 2061 +2554 1631 2061 +2554 1628 2062 +2554 1628 2063 +2554 1628 2066 +2554 1628 2069 +2554 1628 2073 +2554 1628 2079 +2554 1628 2086 +2554 1626 2095 +2554 1621 2102 +2554 1621 2110 +2556 1605 2135 +2556 1572 2169 +2555 1616 2217 +2557 1693 2270 +2564 1696 2342 +2565 1771 2409 +2587 1847 2492 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2555 1645 2062 +2555 1644 2062 +2555 1643 2062 +2555 1641 2062 +2555 1638 2062 +2555 1635 2063 +2555 1631 2063 +2555 1631 2066 +2555 1631 2069 +2555 1631 2073 +2555 1631 2078 +2555 1631 2085 +2555 1628 2094 +2554 1621 2102 +2554 1621 2110 +2556 1612 2136 +2556 1580 2169 +2554 1619 2217 +2558 1694 2270 +2564 1698 2342 +2565 1775 2409 +2587 1852 2492 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2555 1654 2063 +2555 1653 2063 +2555 1651 2063 +2555 1650 2063 +2555 1647 2063 +2555 1644 2064 +2555 1640 2064 +2555 1633 2065 +2555 1633 2068 +2555 1633 2072 +2555 1633 2078 +2555 1633 2085 +2555 1631 2094 +2554 1621 2102 +2554 1621 2110 +2556 1621 2137 +2557 1590 2169 +2554 1624 2217 +2558 1695 2270 +2564 1701 2342 +2565 1781 2409 +2588 1857 2493 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2556 1665 2064 +2556 1664 2065 +2556 1663 2065 +2556 1661 2065 +2556 1659 2065 +2556 1655 2066 +2556 1651 2066 +2556 1646 2066 +2556 1638 2067 +2556 1638 2071 +2556 1638 2077 +2556 1638 2084 +2556 1636 2093 +2554 1621 2102 +2554 1621 2110 +2556 1633 2138 +2557 1603 2169 +2554 1630 2217 +2558 1697 2271 +2564 1704 2342 +2565 1788 2409 +2588 1860 2493 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2556 1680 2066 +2556 1679 2067 +2556 1678 2067 +2556 1676 2067 +2556 1674 2067 +2556 1671 2068 +2556 1667 2068 +2556 1661 2069 +2556 1653 2069 +2556 1643 2070 +2556 1643 2076 +2556 1643 2083 +2556 1641 2092 +2554 1624 2101 +2554 1621 2110 +2557 1649 2140 +2557 1620 2170 +2554 1638 2217 +2558 1699 2271 +2565 1709 2342 +2566 1798 2409 +2589 1863 2493 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2558 1699 2069 +2558 1698 2069 +2558 1697 2070 +2558 1695 2070 +2558 1693 2070 +2558 1690 2070 +2558 1686 2071 +2558 1681 2071 +2558 1674 2072 +2558 1663 2073 +2558 1650 2074 +2558 1650 2082 +2557 1648 2091 +2555 1631 2100 +2554 1621 2110 +2557 1657 2141 +2558 1642 2173 +2554 1658 2217 +2559 1702 2273 +2565 1715 2342 +2566 1810 2409 +2589 1868 2493 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2559 1723 2073 +2559 1723 2073 +2559 1722 2073 +2559 1720 2073 +2559 1718 2074 +2559 1715 2074 +2559 1711 2074 +2559 1706 2075 +2559 1699 2076 +2559 1690 2077 +2559 1677 2078 +2559 1659 2080 +2558 1657 2089 +2556 1641 2098 +2554 1621 2110 +2557 1657 2141 +2558 1669 2176 +2555 1684 2217 +2560 1706 2274 +2566 1723 2342 +2567 1816 2409 +2591 1873 2493 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2560 1754 2078 +2560 1754 2078 +2560 1753 2078 +2560 1752 2079 +2560 1750 2079 +2560 1747 2079 +2560 1744 2080 +2560 1739 2080 +2560 1732 2081 +2560 1724 2082 +2560 1712 2083 +2560 1695 2085 +2560 1674 2088 +2558 1658 2097 +2555 1635 2110 +2557 1661 2141 +2559 1703 2179 +2556 1716 2217 +2560 1716 2275 +2566 1739 2342 +2568 1818 2408 +2592 1880 2493 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2562 1761 2078 +2562 1761 2078 +2562 1761 2079 +2562 1762 2080 +2562 1763 2080 +2562 1765 2082 +2562 1766 2084 +2562 1769 2086 +2562 1772 2089 +2563 1771 2091 +2563 1760 2093 +2563 1745 2094 +2562 1727 2097 +2561 1712 2103 +2558 1692 2116 +2556 1693 2138 +2560 1738 2181 +2560 1744 2217 +2561 1744 2275 +2566 1785 2340 +2571 1835 2406 +2592 1893 2492 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2563 1769 2078 +2563 1769 2078 +2563 1770 2079 +2563 1771 2080 +2563 1772 2080 +2563 1773 2082 +2564 1775 2084 +2564 1777 2086 +2564 1780 2089 +2564 1784 2093 +2565 1789 2098 +2565 1796 2105 +2566 1789 2110 +2564 1776 2116 +2563 1758 2124 +2559 1753 2143 +2558 1773 2177 +2563 1787 2220 +2563 1779 2275 +2566 1840 2337 +2576 1860 2406 +2591 1925 2491 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2566 1822 2077 +2566 1822 2078 +2566 1822 2078 +2566 1822 2078 +2566 1822 2079 +2566 1822 2079 +2566 1822 2080 +2566 1822 2081 +2566 1822 2083 +2566 1822 2085 +2567 1824 2089 +2568 1831 2096 +2568 1839 2106 +2570 1844 2121 +2568 1834 2131 +2568 1813 2145 +2564 1813 2176 +2565 1838 2221 +2568 1838 2272 +2573 1888 2337 +2580 1896 2406 +2599 1967 2492 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2573 1894 2080 +2573 1894 2081 +2573 1895 2081 +2573 1896 2081 +2573 1897 2082 +2574 1898 2082 +2574 1900 2083 +2575 1903 2084 +2575 1906 2086 +2575 1906 2088 +2575 1906 2090 +2575 1906 2094 +2575 1906 2099 +2575 1907 2109 +2576 1913 2129 +2577 1915 2152 +2578 1893 2171 +2576 1899 2221 +2578 1919 2273 +2580 1949 2338 +2587 1961 2408 +2611 2008 2495 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2588 1996 2083 +2588 1997 2083 +2588 1997 2084 +2588 1997 2085 +2588 1997 2086 +2588 1998 2087 +2588 1998 2088 +2588 1999 2091 +2588 2000 2093 +2588 2001 2098 +2588 2005 2100 +2589 2012 2104 +2591 2018 2108 +2588 2010 2114 +2588 2009 2126 +2589 2014 2149 +2590 2016 2184 +2591 2003 2214 +2591 2019 2275 +2595 2044 2342 +2604 2072 2411 +2625 2108 2494 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2625 2149 2111 +2624 2149 2111 +2624 2149 2111 +2624 2149 2111 +2624 2148 2111 +2624 2148 2111 +2623 2147 2111 +2623 2146 2111 +2622 2145 2111 +2621 2143 2111 +2620 2141 2111 +2618 2137 2111 +2617 2136 2114 +2617 2144 2126 +2617 2155 2141 +2619 2157 2164 +2623 2160 2195 +2624 2165 2231 +2619 2165 2275 +2633 2187 2352 +2638 2190 2417 +2660 2223 2503 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2670 2315 2112 +2671 2315 2112 +2671 2315 2112 +2671 2315 2111 +2671 2316 2111 +2672 2316 2111 +2672 2316 2111 +2673 2317 2110 +2674 2318 2109 +2675 2319 2108 +2677 2321 2107 +2680 2323 2105 +2682 2325 2106 +2681 2325 2118 +2680 2325 2133 +2678 2328 2149 +2677 2328 2176 +2677 2325 2215 +2687 2335 2275 +2689 2335 2316 +2695 2346 2391 +2724 2369 2462 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2775 2531 1744 +2775 2531 1745 +2775 2531 1747 +2775 2531 1750 +2776 2532 1753 +2776 2532 1758 +2776 2533 1764 +2776 2533 1772 +2777 2534 1782 +2778 2535 1796 +2778 2536 1813 +2778 2537 1825 +2777 2535 1833 +2776 2530 1839 +2776 2528 1859 +2778 2535 1929 +2779 2534 1991 +2780 2535 2071 +2782 2538 2158 +2784 2536 2248 +2791 2552 2360 +2803 2569 2485 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2826 2762 2506 +2826 2762 2506 +2826 2762 2505 +2826 2762 2505 +2826 2762 2505 +2826 2762 2505 +2826 2761 2505 +2826 2761 2505 +2826 2761 2505 +2826 2761 2506 +2826 2761 2507 +2826 2761 2509 +2826 2761 2510 +2826 2760 2508 +2826 2760 2508 +2826 2762 2520 +2826 2764 2535 +2826 2763 2548 +2826 2763 2571 +2826 2767 2613 +2826 2769 2662 +2826 2779 2732 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2554 1623 2059 +2554 1623 2059 +2554 1623 2060 +2554 1623 2060 +2554 1623 2061 +2554 1623 2063 +2554 1623 2065 +2554 1623 2067 +2554 1623 2070 +2554 1623 2074 +2554 1623 2080 +2554 1623 2087 +2554 1621 2096 +2554 1621 2102 +2554 1621 2110 +2555 1588 2133 +2556 1555 2169 +2555 1608 2217 +2557 1691 2269 +2563 1692 2342 +2564 1761 2409 +2587 1838 2491 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2554 1625 2059 +2554 1624 2059 +2554 1624 2060 +2554 1624 2060 +2554 1624 2061 +2554 1624 2063 +2554 1624 2064 +2554 1624 2067 +2554 1624 2070 +2554 1624 2074 +2554 1624 2080 +2554 1624 2087 +2554 1621 2096 +2554 1621 2102 +2554 1621 2110 +2556 1590 2134 +2556 1556 2169 +2555 1609 2217 +2557 1691 2269 +2563 1692 2342 +2564 1762 2409 +2587 1839 2492 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2554 1627 2059 +2554 1626 2059 +2554 1625 2060 +2554 1625 2060 +2554 1625 2061 +2554 1625 2063 +2554 1625 2064 +2554 1625 2067 +2554 1625 2070 +2554 1625 2074 +2554 1625 2079 +2554 1625 2086 +2554 1622 2096 +2554 1621 2102 +2554 1621 2110 +2556 1592 2134 +2556 1559 2169 +2555 1610 2217 +2557 1691 2269 +2564 1693 2342 +2564 1764 2409 +2587 1840 2492 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2554 1630 2060 +2554 1629 2060 +2554 1627 2060 +2554 1625 2060 +2554 1625 2061 +2554 1625 2062 +2554 1625 2064 +2554 1625 2066 +2554 1625 2070 +2554 1625 2074 +2554 1625 2079 +2554 1625 2086 +2554 1623 2095 +2554 1621 2102 +2554 1621 2110 +2556 1595 2134 +2556 1562 2169 +2555 1611 2217 +2557 1691 2270 +2564 1694 2342 +2564 1765 2409 +2587 1842 2492 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2554 1633 2060 +2554 1632 2060 +2554 1631 2060 +2554 1629 2060 +2554 1626 2061 +2554 1626 2062 +2554 1626 2064 +2554 1626 2066 +2554 1626 2069 +2554 1626 2073 +2554 1626 2079 +2554 1626 2086 +2554 1625 2095 +2554 1621 2102 +2554 1621 2110 +2556 1599 2135 +2556 1567 2169 +2555 1613 2217 +2557 1692 2270 +2564 1695 2342 +2565 1768 2409 +2587 1844 2492 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2554 1638 2061 +2554 1638 2061 +2554 1636 2061 +2554 1634 2061 +2554 1631 2061 +2554 1628 2062 +2554 1628 2063 +2554 1628 2066 +2554 1628 2069 +2554 1628 2073 +2554 1628 2079 +2554 1628 2086 +2554 1626 2095 +2554 1621 2102 +2554 1621 2110 +2556 1605 2135 +2556 1572 2169 +2555 1616 2217 +2557 1693 2270 +2564 1696 2342 +2565 1771 2409 +2587 1847 2492 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2555 1645 2062 +2555 1644 2062 +2555 1643 2062 +2555 1641 2062 +2555 1638 2062 +2555 1635 2063 +2555 1631 2063 +2555 1631 2066 +2555 1631 2069 +2555 1631 2073 +2555 1631 2078 +2555 1631 2085 +2555 1628 2094 +2554 1621 2102 +2554 1621 2110 +2556 1612 2136 +2556 1580 2169 +2554 1619 2217 +2558 1694 2270 +2564 1698 2342 +2565 1775 2409 +2587 1852 2492 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2555 1654 2063 +2555 1653 2063 +2555 1651 2063 +2555 1650 2063 +2555 1647 2063 +2555 1644 2064 +2555 1640 2064 +2555 1633 2065 +2555 1633 2068 +2555 1633 2072 +2555 1633 2078 +2555 1633 2085 +2555 1631 2094 +2554 1621 2102 +2554 1621 2110 +2556 1621 2137 +2557 1590 2169 +2554 1624 2217 +2558 1695 2270 +2564 1701 2342 +2565 1781 2409 +2588 1857 2493 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2556 1665 2064 +2556 1664 2065 +2556 1663 2065 +2556 1661 2065 +2556 1659 2065 +2556 1655 2066 +2556 1651 2066 +2556 1646 2066 +2556 1638 2067 +2556 1638 2071 +2556 1638 2077 +2556 1638 2084 +2556 1636 2093 +2554 1621 2102 +2554 1621 2110 +2556 1633 2138 +2557 1603 2169 +2554 1630 2217 +2558 1697 2271 +2564 1704 2342 +2565 1788 2409 +2588 1860 2493 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2556 1680 2066 +2556 1679 2067 +2556 1678 2067 +2556 1676 2067 +2556 1674 2067 +2556 1671 2068 +2556 1667 2068 +2556 1661 2069 +2556 1653 2069 +2556 1643 2070 +2556 1643 2076 +2556 1643 2083 +2556 1641 2092 +2554 1624 2101 +2554 1621 2110 +2557 1649 2140 +2557 1620 2170 +2554 1638 2217 +2558 1699 2271 +2565 1709 2342 +2566 1798 2409 +2589 1863 2493 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2558 1699 2069 +2558 1698 2069 +2558 1697 2070 +2558 1695 2070 +2558 1693 2070 +2558 1690 2070 +2558 1686 2071 +2558 1681 2071 +2558 1674 2072 +2558 1663 2073 +2558 1650 2074 +2558 1650 2082 +2557 1648 2091 +2555 1631 2100 +2554 1621 2110 +2557 1657 2141 +2558 1642 2173 +2554 1658 2217 +2559 1702 2273 +2565 1715 2342 +2566 1810 2409 +2589 1868 2493 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2559 1723 2073 +2559 1723 2073 +2559 1722 2073 +2559 1720 2073 +2559 1718 2074 +2559 1715 2074 +2559 1711 2074 +2559 1706 2075 +2559 1699 2076 +2559 1690 2077 +2559 1677 2078 +2559 1659 2080 +2558 1657 2089 +2556 1641 2098 +2554 1621 2110 +2557 1657 2141 +2558 1669 2176 +2555 1684 2217 +2560 1706 2274 +2566 1723 2342 +2567 1816 2409 +2591 1873 2493 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2560 1754 2078 +2560 1754 2078 +2560 1753 2078 +2560 1752 2079 +2560 1750 2079 +2560 1747 2079 +2560 1744 2080 +2560 1739 2080 +2560 1732 2081 +2560 1724 2082 +2560 1712 2083 +2560 1695 2085 +2560 1674 2088 +2558 1658 2097 +2555 1635 2110 +2557 1661 2141 +2559 1703 2179 +2556 1716 2217 +2560 1716 2275 +2566 1739 2342 +2568 1818 2408 +2592 1880 2493 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2562 1761 2078 +2562 1761 2078 +2562 1761 2079 +2562 1762 2080 +2562 1763 2080 +2562 1765 2082 +2562 1766 2084 +2562 1769 2086 +2562 1772 2089 +2563 1771 2091 +2563 1760 2093 +2563 1745 2094 +2562 1727 2097 +2561 1712 2103 +2558 1692 2116 +2556 1693 2138 +2560 1738 2181 +2560 1744 2217 +2561 1744 2275 +2566 1785 2340 +2571 1835 2406 +2592 1893 2492 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2563 1769 2078 +2563 1769 2078 +2563 1770 2079 +2563 1771 2080 +2563 1772 2080 +2563 1773 2082 +2564 1775 2084 +2564 1777 2086 +2564 1780 2089 +2564 1784 2093 +2565 1789 2098 +2565 1796 2105 +2566 1789 2110 +2564 1776 2116 +2563 1758 2124 +2559 1753 2143 +2558 1773 2177 +2563 1787 2220 +2563 1779 2275 +2566 1840 2337 +2576 1860 2406 +2591 1925 2491 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2566 1822 2077 +2566 1822 2078 +2566 1822 2078 +2566 1822 2078 +2566 1822 2079 +2566 1822 2079 +2566 1822 2080 +2566 1822 2081 +2566 1822 2083 +2566 1822 2085 +2567 1824 2089 +2568 1831 2096 +2568 1839 2106 +2570 1844 2121 +2568 1834 2131 +2568 1813 2145 +2564 1813 2176 +2565 1838 2221 +2568 1838 2272 +2573 1888 2337 +2580 1896 2406 +2599 1967 2492 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2573 1894 2080 +2573 1894 2081 +2573 1895 2081 +2573 1896 2081 +2573 1897 2082 +2574 1898 2082 +2574 1900 2083 +2575 1903 2084 +2575 1906 2086 +2575 1906 2088 +2575 1906 2090 +2575 1906 2094 +2575 1906 2099 +2575 1907 2109 +2576 1913 2129 +2577 1915 2152 +2578 1893 2171 +2576 1899 2221 +2578 1919 2273 +2580 1949 2338 +2587 1961 2408 +2611 2008 2495 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2588 1996 2083 +2588 1997 2083 +2588 1997 2084 +2588 1997 2085 +2588 1997 2086 +2588 1998 2087 +2588 1998 2088 +2588 1999 2091 +2588 2000 2093 +2588 2001 2098 +2588 2005 2100 +2589 2012 2104 +2591 2018 2108 +2588 2010 2114 +2588 2009 2126 +2589 2014 2149 +2590 2016 2184 +2591 2003 2214 +2591 2019 2275 +2595 2044 2342 +2604 2072 2411 +2625 2108 2494 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2625 2149 2111 +2624 2149 2111 +2624 2149 2111 +2624 2149 2111 +2624 2148 2111 +2624 2148 2111 +2623 2147 2111 +2623 2146 2111 +2622 2145 2111 +2621 2143 2111 +2620 2141 2111 +2618 2137 2111 +2617 2136 2114 +2617 2144 2126 +2617 2155 2141 +2619 2157 2164 +2623 2160 2195 +2624 2165 2231 +2619 2165 2275 +2633 2187 2352 +2638 2190 2417 +2660 2223 2503 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2670 2315 2112 +2671 2315 2112 +2671 2315 2112 +2671 2315 2111 +2671 2316 2111 +2672 2316 2111 +2672 2316 2111 +2673 2317 2110 +2674 2318 2109 +2675 2319 2108 +2677 2321 2107 +2680 2323 2105 +2682 2325 2106 +2681 2325 2118 +2680 2325 2133 +2678 2328 2149 +2677 2328 2176 +2677 2325 2215 +2687 2335 2275 +2689 2335 2316 +2695 2346 2391 +2724 2369 2462 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2775 2531 1744 +2775 2531 1745 +2775 2531 1747 +2775 2531 1750 +2776 2532 1753 +2776 2532 1758 +2776 2533 1764 +2776 2533 1772 +2777 2534 1782 +2778 2535 1796 +2778 2536 1813 +2778 2537 1825 +2777 2535 1833 +2776 2530 1839 +2776 2528 1859 +2778 2535 1929 +2779 2534 1991 +2780 2535 2071 +2782 2538 2158 +2784 2536 2248 +2791 2552 2360 +2803 2569 2485 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2826 2762 2506 +2826 2762 2506 +2826 2762 2505 +2826 2762 2505 +2826 2762 2505 +2826 2762 2505 +2826 2761 2505 +2826 2761 2505 +2826 2761 2505 +2826 2761 2506 +2826 2761 2507 +2826 2761 2509 +2826 2761 2510 +2826 2760 2508 +2826 2760 2508 +2826 2762 2520 +2826 2764 2535 +2826 2763 2548 +2826 2763 2571 +2826 2767 2613 +2826 2769 2662 +2826 2779 2732 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2554 1623 2059 +2554 1623 2059 +2554 1623 2060 +2554 1623 2060 +2554 1623 2061 +2554 1623 2063 +2554 1623 2065 +2554 1623 2067 +2554 1623 2070 +2554 1623 2074 +2554 1623 2080 +2554 1623 2087 +2554 1621 2096 +2554 1621 2102 +2554 1621 2110 +2555 1588 2133 +2556 1555 2169 +2555 1608 2217 +2557 1691 2269 +2563 1692 2342 +2564 1761 2409 +2587 1838 2491 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2554 1625 2059 +2554 1624 2059 +2554 1624 2060 +2554 1624 2060 +2554 1624 2061 +2554 1624 2063 +2554 1624 2064 +2554 1624 2067 +2554 1624 2070 +2554 1624 2074 +2554 1624 2080 +2554 1624 2087 +2554 1621 2096 +2554 1621 2102 +2554 1621 2110 +2556 1590 2134 +2556 1556 2169 +2555 1609 2217 +2557 1691 2269 +2563 1692 2342 +2564 1762 2409 +2587 1839 2492 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2554 1627 2059 +2554 1626 2059 +2554 1625 2060 +2554 1625 2060 +2554 1625 2061 +2554 1625 2063 +2554 1625 2064 +2554 1625 2067 +2554 1625 2070 +2554 1625 2074 +2554 1625 2079 +2554 1625 2086 +2554 1622 2096 +2554 1621 2102 +2554 1621 2110 +2556 1592 2134 +2556 1559 2169 +2555 1610 2217 +2557 1691 2269 +2564 1693 2342 +2564 1764 2409 +2587 1840 2492 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2554 1630 2060 +2554 1629 2060 +2554 1627 2060 +2554 1625 2060 +2554 1625 2061 +2554 1625 2062 +2554 1625 2064 +2554 1625 2066 +2554 1625 2070 +2554 1625 2074 +2554 1625 2079 +2554 1625 2086 +2554 1623 2095 +2554 1621 2102 +2554 1621 2110 +2556 1595 2134 +2556 1562 2169 +2555 1611 2217 +2557 1691 2270 +2564 1694 2342 +2564 1765 2409 +2587 1842 2492 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2554 1633 2060 +2554 1632 2060 +2554 1631 2060 +2554 1629 2060 +2554 1626 2061 +2554 1626 2062 +2554 1626 2064 +2554 1626 2066 +2554 1626 2069 +2554 1626 2073 +2554 1626 2079 +2554 1626 2086 +2554 1625 2095 +2554 1621 2102 +2554 1621 2110 +2556 1599 2135 +2556 1567 2169 +2555 1613 2217 +2557 1692 2270 +2564 1695 2342 +2565 1768 2409 +2587 1844 2492 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2554 1638 2061 +2554 1638 2061 +2554 1636 2061 +2554 1634 2061 +2554 1631 2061 +2554 1628 2062 +2554 1628 2063 +2554 1628 2066 +2554 1628 2069 +2554 1628 2073 +2554 1628 2079 +2554 1628 2086 +2554 1626 2095 +2554 1621 2102 +2554 1621 2110 +2556 1605 2135 +2556 1572 2169 +2555 1616 2217 +2557 1693 2270 +2564 1696 2342 +2565 1771 2409 +2587 1847 2492 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2555 1645 2062 +2555 1644 2062 +2555 1643 2062 +2555 1641 2062 +2555 1638 2062 +2555 1635 2063 +2555 1631 2063 +2555 1631 2066 +2555 1631 2069 +2555 1631 2073 +2555 1631 2078 +2555 1631 2085 +2555 1628 2094 +2554 1621 2102 +2554 1621 2110 +2556 1612 2136 +2556 1580 2169 +2554 1619 2217 +2558 1694 2270 +2564 1698 2342 +2565 1775 2409 +2587 1852 2492 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2555 1654 2063 +2555 1653 2063 +2555 1651 2063 +2555 1650 2063 +2555 1647 2063 +2555 1644 2064 +2555 1640 2064 +2555 1633 2065 +2555 1633 2068 +2555 1633 2072 +2555 1633 2078 +2555 1633 2085 +2555 1631 2094 +2554 1621 2102 +2554 1621 2110 +2556 1621 2137 +2557 1590 2169 +2554 1624 2217 +2558 1695 2270 +2564 1701 2342 +2565 1781 2409 +2588 1857 2493 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2556 1665 2064 +2556 1664 2065 +2556 1663 2065 +2556 1661 2065 +2556 1659 2065 +2556 1655 2066 +2556 1651 2066 +2556 1646 2066 +2556 1638 2067 +2556 1638 2071 +2556 1638 2077 +2556 1638 2084 +2556 1636 2093 +2554 1621 2102 +2554 1621 2110 +2556 1633 2138 +2557 1603 2169 +2554 1630 2217 +2558 1697 2271 +2564 1704 2342 +2565 1788 2409 +2588 1860 2493 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2556 1680 2066 +2556 1679 2067 +2556 1678 2067 +2556 1676 2067 +2556 1674 2067 +2556 1671 2068 +2556 1667 2068 +2556 1661 2069 +2556 1653 2069 +2556 1643 2070 +2556 1643 2076 +2556 1643 2083 +2556 1641 2092 +2554 1624 2101 +2554 1621 2110 +2557 1649 2140 +2557 1620 2170 +2554 1638 2217 +2558 1699 2271 +2565 1709 2342 +2566 1798 2409 +2589 1863 2493 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2558 1699 2069 +2558 1698 2069 +2558 1697 2070 +2558 1695 2070 +2558 1693 2070 +2558 1690 2070 +2558 1686 2071 +2558 1681 2071 +2558 1674 2072 +2558 1663 2073 +2558 1650 2074 +2558 1650 2082 +2557 1648 2091 +2555 1631 2100 +2554 1621 2110 +2557 1657 2141 +2558 1642 2173 +2554 1658 2217 +2559 1702 2273 +2565 1715 2342 +2566 1810 2409 +2589 1868 2493 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2559 1723 2073 +2559 1723 2073 +2559 1722 2073 +2559 1720 2073 +2559 1718 2074 +2559 1715 2074 +2559 1711 2074 +2559 1706 2075 +2559 1699 2076 +2559 1690 2077 +2559 1677 2078 +2559 1659 2080 +2558 1657 2089 +2556 1641 2098 +2554 1621 2110 +2557 1657 2141 +2558 1669 2176 +2555 1684 2217 +2560 1706 2274 +2566 1723 2342 +2567 1816 2409 +2591 1873 2493 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2560 1754 2078 +2560 1754 2078 +2560 1753 2078 +2560 1752 2079 +2560 1750 2079 +2560 1747 2079 +2560 1744 2080 +2560 1739 2080 +2560 1732 2081 +2560 1724 2082 +2560 1712 2083 +2560 1695 2085 +2560 1674 2088 +2558 1658 2097 +2555 1635 2110 +2557 1661 2141 +2559 1703 2179 +2556 1716 2217 +2560 1716 2275 +2566 1739 2342 +2568 1818 2408 +2592 1880 2493 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2562 1761 2078 +2562 1761 2078 +2562 1761 2079 +2562 1762 2080 +2562 1763 2080 +2562 1765 2082 +2562 1766 2084 +2562 1769 2086 +2562 1772 2089 +2563 1771 2091 +2563 1760 2093 +2563 1745 2094 +2562 1727 2097 +2561 1712 2103 +2558 1692 2116 +2556 1693 2138 +2560 1738 2181 +2560 1744 2217 +2561 1744 2275 +2566 1785 2340 +2571 1835 2406 +2592 1893 2492 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2563 1769 2078 +2563 1769 2078 +2563 1770 2079 +2563 1771 2080 +2563 1772 2080 +2563 1773 2082 +2564 1775 2084 +2564 1777 2086 +2564 1780 2089 +2564 1784 2093 +2565 1789 2098 +2565 1796 2105 +2566 1789 2110 +2564 1776 2116 +2563 1758 2124 +2559 1753 2143 +2558 1773 2177 +2563 1787 2220 +2563 1779 2275 +2566 1840 2337 +2576 1860 2406 +2591 1925 2491 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2566 1822 2077 +2566 1822 2078 +2566 1822 2078 +2566 1822 2078 +2566 1822 2079 +2566 1822 2079 +2566 1822 2080 +2566 1822 2081 +2566 1822 2083 +2566 1822 2085 +2567 1824 2089 +2568 1831 2096 +2568 1839 2106 +2570 1844 2121 +2568 1834 2131 +2568 1813 2145 +2564 1813 2176 +2565 1838 2221 +2568 1838 2272 +2573 1888 2337 +2580 1896 2406 +2599 1967 2492 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2573 1894 2080 +2573 1894 2081 +2573 1895 2081 +2573 1896 2081 +2573 1897 2082 +2574 1898 2082 +2574 1900 2083 +2575 1903 2084 +2575 1906 2086 +2575 1906 2088 +2575 1906 2090 +2575 1906 2094 +2575 1906 2099 +2575 1907 2109 +2576 1913 2129 +2577 1915 2152 +2578 1893 2171 +2576 1899 2221 +2578 1919 2273 +2580 1949 2338 +2587 1961 2408 +2611 2008 2495 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2588 1996 2083 +2588 1997 2083 +2588 1997 2084 +2588 1997 2085 +2588 1997 2086 +2588 1998 2087 +2588 1998 2088 +2588 1999 2091 +2588 2000 2093 +2588 2001 2098 +2588 2005 2100 +2589 2012 2104 +2591 2018 2108 +2588 2010 2114 +2588 2009 2126 +2589 2014 2149 +2590 2016 2184 +2591 2003 2214 +2591 2019 2275 +2595 2044 2342 +2604 2072 2411 +2625 2108 2494 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2625 2149 2111 +2624 2149 2111 +2624 2149 2111 +2624 2149 2111 +2624 2148 2111 +2624 2148 2111 +2623 2147 2111 +2623 2146 2111 +2622 2145 2111 +2621 2143 2111 +2620 2141 2111 +2618 2137 2111 +2617 2136 2114 +2617 2144 2126 +2617 2155 2141 +2619 2157 2164 +2623 2160 2195 +2624 2165 2231 +2619 2165 2275 +2633 2187 2352 +2638 2190 2417 +2660 2223 2503 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2670 2315 2112 +2671 2315 2112 +2671 2315 2112 +2671 2315 2111 +2671 2316 2111 +2672 2316 2111 +2672 2316 2111 +2673 2317 2110 +2674 2318 2109 +2675 2319 2108 +2677 2321 2107 +2680 2323 2105 +2682 2325 2106 +2681 2325 2118 +2680 2325 2133 +2678 2328 2149 +2677 2328 2176 +2677 2325 2215 +2687 2335 2275 +2689 2335 2316 +2695 2346 2391 +2724 2369 2462 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2775 2531 1744 +2775 2531 1745 +2775 2531 1747 +2775 2531 1750 +2776 2532 1753 +2776 2532 1758 +2776 2533 1764 +2776 2533 1772 +2777 2534 1782 +2778 2535 1796 +2778 2536 1813 +2778 2537 1825 +2777 2535 1833 +2776 2530 1839 +2776 2528 1859 +2778 2535 1929 +2779 2534 1991 +2780 2535 2071 +2782 2538 2158 +2784 2536 2248 +2791 2552 2360 +2803 2569 2485 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2826 2762 2506 +2826 2762 2506 +2826 2762 2505 +2826 2762 2505 +2826 2762 2505 +2826 2762 2505 +2826 2761 2505 +2826 2761 2505 +2826 2761 2505 +2826 2761 2506 +2826 2761 2507 +2826 2761 2509 +2826 2761 2510 +2826 2760 2508 +2826 2760 2508 +2826 2762 2520 +2826 2764 2535 +2826 2763 2548 +2826 2763 2571 +2826 2767 2613 +2826 2769 2662 +2826 2779 2732 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2554 1623 2059 +2554 1623 2059 +2554 1623 2060 +2554 1623 2060 +2554 1623 2061 +2554 1623 2063 +2554 1623 2065 +2554 1623 2067 +2554 1623 2070 +2554 1623 2074 +2554 1623 2080 +2554 1623 2087 +2554 1621 2096 +2554 1621 2102 +2554 1621 2110 +2555 1588 2133 +2556 1555 2169 +2555 1608 2217 +2557 1691 2269 +2563 1692 2342 +2564 1761 2409 +2587 1838 2491 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2554 1625 2059 +2554 1624 2059 +2554 1624 2060 +2554 1624 2060 +2554 1624 2061 +2554 1624 2063 +2554 1624 2064 +2554 1624 2067 +2554 1624 2070 +2554 1624 2074 +2554 1624 2080 +2554 1624 2087 +2554 1621 2096 +2554 1621 2102 +2554 1621 2110 +2556 1590 2134 +2556 1556 2169 +2555 1609 2217 +2557 1691 2269 +2563 1692 2342 +2564 1762 2409 +2587 1839 2492 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2554 1627 2059 +2554 1626 2059 +2554 1625 2060 +2554 1625 2060 +2554 1625 2061 +2554 1625 2063 +2554 1625 2064 +2554 1625 2067 +2554 1625 2070 +2554 1625 2074 +2554 1625 2079 +2554 1625 2086 +2554 1622 2096 +2554 1621 2102 +2554 1621 2110 +2556 1592 2134 +2556 1559 2169 +2555 1610 2217 +2557 1691 2269 +2564 1693 2342 +2564 1764 2409 +2587 1840 2492 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2554 1630 2060 +2554 1629 2060 +2554 1627 2060 +2554 1625 2060 +2554 1625 2061 +2554 1625 2062 +2554 1625 2064 +2554 1625 2066 +2554 1625 2070 +2554 1625 2074 +2554 1625 2079 +2554 1625 2086 +2554 1623 2095 +2554 1621 2102 +2554 1621 2110 +2556 1595 2134 +2556 1562 2169 +2555 1611 2217 +2557 1691 2270 +2564 1694 2342 +2564 1765 2409 +2587 1842 2492 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2554 1633 2060 +2554 1632 2060 +2554 1631 2060 +2554 1629 2060 +2554 1626 2061 +2554 1626 2062 +2554 1626 2064 +2554 1626 2066 +2554 1626 2069 +2554 1626 2073 +2554 1626 2079 +2554 1626 2086 +2554 1625 2095 +2554 1621 2102 +2554 1621 2110 +2556 1599 2135 +2556 1567 2169 +2555 1613 2217 +2557 1692 2270 +2564 1695 2342 +2565 1768 2409 +2587 1844 2492 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2554 1638 2061 +2554 1638 2061 +2554 1636 2061 +2554 1634 2061 +2554 1631 2061 +2554 1628 2062 +2554 1628 2063 +2554 1628 2066 +2554 1628 2069 +2554 1628 2073 +2554 1628 2079 +2554 1628 2086 +2554 1626 2095 +2554 1621 2102 +2554 1621 2110 +2556 1605 2135 +2556 1572 2169 +2555 1616 2217 +2557 1693 2270 +2564 1696 2342 +2565 1771 2409 +2587 1847 2492 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2597 1897 2530 +2555 1645 2062 +2555 1644 2062 +2555 1643 2062 +2555 1641 2062 +2555 1638 2062 +2555 1635 2063 +2555 1631 2063 +2555 1631 2066 +2555 1631 2069 +2555 1631 2073 +2555 1631 2078 +2555 1631 2085 +2555 1628 2094 +2554 1621 2102 +2554 1621 2110 +2556 1612 2136 +2556 1580 2169 +2554 1619 2217 +2558 1694 2270 +2564 1698 2342 +2565 1775 2409 +2587 1852 2492 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2555 1654 2063 +2555 1653 2063 +2555 1651 2063 +2555 1650 2063 +2555 1647 2063 +2555 1644 2064 +2555 1640 2064 +2555 1633 2065 +2555 1633 2068 +2555 1633 2072 +2555 1633 2078 +2555 1633 2085 +2555 1631 2094 +2554 1621 2102 +2554 1621 2110 +2556 1621 2137 +2557 1590 2169 +2554 1624 2217 +2558 1695 2270 +2564 1701 2342 +2565 1781 2409 +2588 1857 2493 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2597 1897 2529 +2556 1665 2064 +2556 1664 2065 +2556 1663 2065 +2556 1661 2065 +2556 1659 2065 +2556 1655 2066 +2556 1651 2066 +2556 1646 2066 +2556 1638 2067 +2556 1638 2071 +2556 1638 2077 +2556 1638 2084 +2556 1636 2093 +2554 1621 2102 +2554 1621 2110 +2556 1633 2138 +2557 1603 2169 +2554 1630 2217 +2558 1697 2271 +2564 1704 2342 +2565 1788 2409 +2588 1860 2493 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2597 1897 2528 +2556 1680 2066 +2556 1679 2067 +2556 1678 2067 +2556 1676 2067 +2556 1674 2067 +2556 1671 2068 +2556 1667 2068 +2556 1661 2069 +2556 1653 2069 +2556 1643 2070 +2556 1643 2076 +2556 1643 2083 +2556 1641 2092 +2554 1624 2101 +2554 1621 2110 +2557 1649 2140 +2557 1620 2170 +2554 1638 2217 +2558 1699 2271 +2565 1709 2342 +2566 1798 2409 +2589 1863 2493 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2558 1699 2069 +2558 1698 2069 +2558 1697 2070 +2558 1695 2070 +2558 1693 2070 +2558 1690 2070 +2558 1686 2071 +2558 1681 2071 +2558 1674 2072 +2558 1663 2073 +2558 1650 2074 +2558 1650 2082 +2557 1648 2091 +2555 1631 2100 +2554 1621 2110 +2557 1657 2141 +2558 1642 2173 +2554 1658 2217 +2559 1702 2273 +2565 1715 2342 +2566 1810 2409 +2589 1868 2493 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2597 1897 2527 +2559 1723 2073 +2559 1723 2073 +2559 1722 2073 +2559 1720 2073 +2559 1718 2074 +2559 1715 2074 +2559 1711 2074 +2559 1706 2075 +2559 1699 2076 +2559 1690 2077 +2559 1677 2078 +2559 1659 2080 +2558 1657 2089 +2556 1641 2098 +2554 1621 2110 +2557 1657 2141 +2558 1669 2176 +2555 1684 2217 +2560 1706 2274 +2566 1723 2342 +2567 1816 2409 +2591 1873 2493 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2597 1897 2525 +2560 1754 2078 +2560 1754 2078 +2560 1753 2078 +2560 1752 2079 +2560 1750 2079 +2560 1747 2079 +2560 1744 2080 +2560 1739 2080 +2560 1732 2081 +2560 1724 2082 +2560 1712 2083 +2560 1695 2085 +2560 1674 2088 +2558 1658 2097 +2555 1635 2110 +2557 1661 2141 +2559 1703 2179 +2556 1716 2217 +2560 1716 2275 +2566 1739 2342 +2568 1818 2408 +2592 1880 2493 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2597 1898 2524 +2562 1761 2078 +2562 1761 2078 +2562 1761 2079 +2562 1762 2080 +2562 1763 2080 +2562 1765 2082 +2562 1766 2084 +2562 1769 2086 +2562 1772 2089 +2563 1771 2091 +2563 1760 2093 +2563 1745 2094 +2562 1727 2097 +2561 1712 2103 +2558 1692 2116 +2556 1693 2138 +2560 1738 2181 +2560 1744 2217 +2561 1744 2275 +2566 1785 2340 +2571 1835 2406 +2592 1893 2492 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2599 1908 2527 +2563 1769 2078 +2563 1769 2078 +2563 1770 2079 +2563 1771 2080 +2563 1772 2080 +2563 1773 2082 +2564 1775 2084 +2564 1777 2086 +2564 1780 2089 +2564 1784 2093 +2565 1789 2098 +2565 1796 2105 +2566 1789 2110 +2564 1776 2116 +2563 1758 2124 +2559 1753 2143 +2558 1773 2177 +2563 1787 2220 +2563 1779 2275 +2566 1840 2337 +2576 1860 2406 +2591 1925 2491 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2602 1920 2530 +2566 1822 2077 +2566 1822 2078 +2566 1822 2078 +2566 1822 2078 +2566 1822 2079 +2566 1822 2079 +2566 1822 2080 +2566 1822 2081 +2566 1822 2083 +2566 1822 2085 +2567 1824 2089 +2568 1831 2096 +2568 1839 2106 +2570 1844 2121 +2568 1834 2131 +2568 1813 2145 +2564 1813 2176 +2565 1838 2221 +2568 1838 2272 +2573 1888 2337 +2580 1896 2406 +2599 1967 2492 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2609 1966 2529 +2573 1894 2080 +2573 1894 2081 +2573 1895 2081 +2573 1896 2081 +2573 1897 2082 +2574 1898 2082 +2574 1900 2083 +2575 1903 2084 +2575 1906 2086 +2575 1906 2088 +2575 1906 2090 +2575 1906 2094 +2575 1906 2099 +2575 1907 2109 +2576 1913 2129 +2577 1915 2152 +2578 1893 2171 +2576 1899 2221 +2578 1919 2273 +2580 1949 2338 +2587 1961 2408 +2611 2008 2495 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2623 2041 2528 +2588 1996 2083 +2588 1997 2083 +2588 1997 2084 +2588 1997 2085 +2588 1997 2086 +2588 1998 2087 +2588 1998 2088 +2588 1999 2091 +2588 2000 2093 +2588 2001 2098 +2588 2005 2100 +2589 2012 2104 +2591 2018 2108 +2588 2010 2114 +2588 2009 2126 +2589 2014 2149 +2590 2016 2184 +2591 2003 2214 +2591 2019 2275 +2595 2044 2342 +2604 2072 2411 +2625 2108 2494 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2644 2138 2530 +2625 2149 2111 +2624 2149 2111 +2624 2149 2111 +2624 2149 2111 +2624 2148 2111 +2624 2148 2111 +2623 2147 2111 +2623 2146 2111 +2622 2145 2111 +2621 2143 2111 +2620 2141 2111 +2618 2137 2111 +2617 2136 2114 +2617 2144 2126 +2617 2155 2141 +2619 2157 2164 +2623 2160 2195 +2624 2165 2231 +2619 2165 2275 +2633 2187 2352 +2638 2190 2417 +2660 2223 2503 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2672 2249 2537 +2670 2315 2112 +2671 2315 2112 +2671 2315 2112 +2671 2315 2111 +2671 2316 2111 +2672 2316 2111 +2672 2316 2111 +2673 2317 2110 +2674 2318 2109 +2675 2319 2108 +2677 2321 2107 +2680 2323 2105 +2682 2325 2106 +2681 2325 2118 +2680 2325 2133 +2678 2328 2149 +2677 2328 2176 +2677 2325 2215 +2687 2335 2275 +2689 2335 2316 +2695 2346 2391 +2724 2369 2462 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2735 2385 2488 +2775 2531 1744 +2775 2531 1745 +2775 2531 1747 +2775 2531 1750 +2776 2532 1753 +2776 2532 1758 +2776 2533 1764 +2776 2533 1772 +2777 2534 1782 +2778 2535 1796 +2778 2536 1813 +2778 2537 1825 +2777 2535 1833 +2776 2530 1839 +2776 2528 1859 +2778 2535 1929 +2779 2534 1991 +2780 2535 2071 +2782 2538 2158 +2784 2536 2248 +2791 2552 2360 +2803 2569 2485 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2813 2581 2533 +2826 2762 2506 +2826 2762 2506 +2826 2762 2505 +2826 2762 2505 +2826 2762 2505 +2826 2762 2505 +2826 2761 2505 +2826 2761 2505 +2826 2761 2505 +2826 2761 2506 +2826 2761 2507 +2826 2761 2509 +2826 2761 2510 +2826 2760 2508 +2826 2760 2508 +2826 2762 2520 +2826 2764 2535 +2826 2763 2548 +2826 2763 2571 +2826 2767 2613 +2826 2769 2662 +2826 2779 2732 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2784 2763 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2623 +2826 2823 2625 +2826 2823 2628 +2826 2822 2631 +2826 2821 2638 +2826 2822 2651 +2826 2823 2668 +2826 2819 2690 +2826 2823 2740 +2826 2825 2794 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 +2826 2826 2819 diff --git a/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Photoshop/Log2-48nits/o_invShaped/test_clt_32_LUT.azasset b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Photoshop/Log2-48nits/o_invShaped/test_clt_32_LUT.azasset new file mode 100644 index 0000000000..92f5a49363 --- /dev/null +++ b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Photoshop/Log2-48nits/o_invShaped/test_clt_32_LUT.azasset @@ -0,0 +1,32777 @@ +{ + "Type": "JsonSerialization", + "Version": 1, + "ClassName": "LookupTableAsset", + "ClassData": { + "Name": "LookupTable", + "Intervals": [0, 33, 66, 99, 132, 165, 198, 231, 264, 297, 330, 363, 396, 429, 462, 495, 528, 561, 594, 627, 660, 693, 726, 759, 792, 825, 858, 891, 924, 957, 990, 1023], + "Values": [0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 28, +0, 0, 152, +0, 0, 280, +0, 0, 408, +0, 0, 537, +0, 0, 667, +0, 0, 797, +0, 0, 928, +0, 0, 1084, +0, 0, 1291, +0, 0, 1472, +0, 0, 1634, +361, 0, 1771, +1145, 0, 1881, +1561, 0, 2006, +1561, 0, 2154, +432, 987, 2341, +1228, 621, 2470, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 54, +0, 0, 173, +0, 0, 295, +0, 0, 419, +0, 0, 545, +0, 0, 673, +0, 0, 802, +0, 0, 932, +0, 0, 1087, +0, 0, 1293, +0, 0, 1473, +0, 0, 1635, +370, 0, 1772, +1144, 0, 1882, +1559, 0, 2006, +1558, 0, 2154, +428, 992, 2341, +1232, 621, 2470, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 87, +0, 0, 198, +0, 0, 315, +0, 0, 434, +0, 0, 557, +0, 0, 682, +0, 0, 809, +0, 0, 937, +0, 0, 1091, +0, 0, 1295, +0, 0, 1474, +0, 0, 1635, +381, 0, 1773, +1143, 0, 1883, +1556, 0, 2007, +1554, 0, 2155, +423, 998, 2341, +1238, 621, 2470, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 31, +0, 0, 127, +0, 0, 230, +0, 0, 340, +0, 0, 454, +0, 0, 572, +0, 0, 693, +0, 0, 817, +0, 0, 943, +0, 0, 1095, +0, 0, 1298, +0, 0, 1476, +0, 0, 1636, +395, 0, 1774, +1142, 0, 1883, +1552, 0, 2008, +1548, 0, 2156, +416, 1005, 2342, +1246, 621, 2470, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 31, +0, 0, 176, +0, 0, 270, +0, 0, 371, +0, 0, 478, +0, 0, 591, +0, 0, 708, +0, 0, 828, +0, 0, 952, +0, 0, 1101, +0, 0, 1302, +0, 0, 1479, +0, 0, 1637, +414, 0, 1775, +1140, 0, 1884, +1547, 0, 2010, +1540, 58, 2158, +407, 1015, 2342, +1257, 621, 2470, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 31, +0, 7, 176, +0, 63, 318, +0, 63, 410, +0, 63, 509, +0, 63, 615, +0, 63, 727, +0, 63, 843, +0, 63, 963, +0, 103, 1109, +0, 30, 1307, +0, 30, 1482, +0, 3, 1639, +438, 0, 1777, +1137, 0, 1886, +1539, 0, 2011, +1530, 197, 2160, +394, 1028, 2343, +1270, 621, 2470, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +0, 4, 0, +0, 23, 0, +0, 47, 0, +0, 77, 31, +0, 114, 176, +0, 159, 318, +0, 214, 457, +0, 214, 548, +0, 214, 646, +0, 214, 751, +0, 214, 862, +0, 214, 977, +0, 243, 1120, +0, 163, 1314, +0, 163, 1487, +0, 142, 1641, +468, 0, 1779, +1134, 0, 1888, +1530, 32, 2014, +1515, 333, 2163, +376, 1045, 2344, +1287, 621, 2470, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +0, 144, 0, +0, 157, 0, +0, 175, 0, +0, 198, 31, +0, 227, 176, +0, 262, 318, +0, 306, 457, +0, 359, 595, +0, 359, 684, +0, 359, 782, +0, 359, 886, +0, 359, 996, +0, 380, 1134, +0, 295, 1323, +0, 295, 1494, +0, 280, 1644, +506, 122, 1783, +1129, 0, 1891, +1516, 164, 2017, +1495, 469, 2167, +352, 1066, 2345, +1309, 621, 2470, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +0, 281, 0, +0, 291, 0, +0, 304, 0, +0, 322, 31, +0, 344, 176, +0, 371, 318, +0, 406, 457, +0, 449, 595, +0, 501, 730, +0, 501, 819, +0, 501, 916, +0, 501, 1020, +0, 516, 1151, +0, 426, 1335, +0, 426, 1502, +0, 415, 1648, +552, 265, 1787, +1123, 111, 1894, +1498, 296, 2021, +1467, 603, 2172, +317, 1093, 2347, +1348, 639, 2470, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +0, 417, 0, +0, 424, 0, +0, 434, 0, +0, 447, 31, +0, 464, 176, +0, 486, 318, +0, 513, 457, +0, 547, 595, +0, 589, 730, +0, 640, 865, +0, 640, 954, +0, 640, 1050, +0, 651, 1174, +0, 570, 1350, +0, 559, 1512, +0, 550, 1653, +556, 441, 1791, +1115, 244, 1898, +1471, 428, 2027, +1426, 737, 2178, +265, 1128, 2349, +1396, 662, 2470, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +0, 552, 0, +0, 557, 0, +0, 565, 0, +0, 575, 31, +0, 587, 176, +0, 604, 318, +0, 625, 457, +0, 652, 595, +0, 686, 730, +0, 727, 865, +0, 777, 1000, +0, 777, 1088, +0, 786, 1203, +0, 726, 1370, +0, 691, 1526, +0, 685, 1662, +556, 606, 1796, +1132, 422, 1904, +1434, 560, 2035, +1365, 871, 2187, +186, 1169, 2352, +1454, 691, 2470, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +0, 686, 0, +0, 690, 0, +0, 696, 0, +0, 703, 31, +0, 713, 176, +0, 726, 318, +0, 742, 457, +0, 763, 595, +0, 789, 730, +0, 823, 865, +0, 864, 1000, +0, 913, 1133, +0, 920, 1239, +0, 876, 1395, +0, 823, 1544, +0, 818, 1675, +556, 761, 1803, +1160, 593, 1912, +1378, 692, 2045, +1267, 1004, 2199, +0, 1212, 2357, +1520, 728, 2470, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +0, 857, 100, +0, 857, 131, +0, 861, 202, +0, 866, 282, +0, 873, 371, +0, 882, 468, +0, 894, 573, +0, 909, 683, +0, 928, 797, +0, 953, 916, +0, 984, 1038, +0, 1023, 1162, +0, 1061, 1287, +0, 1030, 1430, +0, 984, 1569, +0, 971, 1697, +566, 941, 1817, +1178, 799, 1926, +1302, 849, 2057, +1119, 1137, 2212, +0, 1255, 2365, +1585, 801, 2470, +1738, 957, 2513, +1738, 957, 2513, +1738, 957, 2513, +1738, 957, 2513, +1738, 957, 2513, +1738, 957, 2513, +1738, 957, 2513, +1738, 957, 2513, +1738, 957, 2513, +1738, 957, 2513, +0, 1184, 1027, +0, 1184, 1031, +0, 1184, 1036, +0, 1184, 1043, +0, 1184, 1052, +0, 1184, 1064, +0, 1184, 1080, +0, 1184, 1099, +0, 1184, 1125, +0, 1190, 1168, +0, 1209, 1242, +0, 1232, 1325, +0, 1257, 1416, +0, 1237, 1493, +0, 1209, 1617, +0, 1222, 1740, +636, 1187, 1854, +1040, 1131, 1961, +1243, 1131, 2080, +1031, 1271, 2224, +472, 1312, 2372, +1588, 1032, 2472, +1765, 1144, 2512, +1765, 1144, 2512, +1765, 1144, 2512, +1765, 1144, 2512, +1765, 1144, 2512, +1765, 1144, 2512, +1765, 1144, 2512, +1765, 1144, 2512, +1765, 1144, 2512, +1765, 1144, 2512, +0, 1421, 1377, +0, 1421, 1379, +0, 1421, 1382, +0, 1421, 1385, +0, 1421, 1389, +0, 1421, 1395, +0, 1421, 1402, +0, 1421, 1412, +0, 1421, 1425, +0, 1421, 1442, +0, 1421, 1463, +0, 1421, 1491, +0, 1432, 1546, +0, 1418, 1604, +0, 1399, 1673, +0, 1412, 1786, +636, 1404, 1895, +1048, 1353, 1999, +1151, 1350, 2110, +878, 1405, 2240, +666, 1388, 2378, +1601, 1209, 2473, +1799, 1314, 2510, +1799, 1314, 2510, +1799, 1314, 2510, +1799, 1314, 2510, +1799, 1314, 2510, +1799, 1314, 2510, +1799, 1314, 2510, +1799, 1314, 2510, +1799, 1314, 2510, +1799, 1314, 2510, +901, 1580, 1648, +901, 1579, 1649, +901, 1579, 1650, +901, 1579, 1652, +901, 1578, 1655, +901, 1577, 1658, +901, 1576, 1662, +901, 1574, 1668, +901, 1572, 1675, +901, 1569, 1685, +901, 1567, 1698, +901, 1567, 1714, +886, 1567, 1736, +886, 1577, 1788, +886, 1569, 1838, +890, 1552, 1888, +807, 1557, 1969, +921, 1536, 2067, +942, 1537, 2170, +810, 1524, 2268, +1125, 1501, 2382, +1680, 1435, 2473, +1845, 1472, 2509, +1845, 1472, 2509, +1845, 1472, 2509, +1845, 1472, 2509, +1845, 1472, 2509, +1845, 1472, 2509, +1845, 1472, 2509, +1845, 1472, 2509, +1845, 1472, 2509, +1845, 1472, 2509, +1449, 1705, 1856, +1448, 1705, 1856, +1447, 1705, 1857, +1446, 1705, 1859, +1444, 1705, 1860, +1441, 1705, 1862, +1438, 1705, 1865, +1433, 1705, 1868, +1427, 1705, 1873, +1426, 1703, 1880, +1426, 1700, 1888, +1426, 1696, 1899, +1423, 1691, 1913, +1400, 1685, 1931, +1400, 1696, 1976, +1370, 1702, 2022, +1371, 1685, 2062, +1192, 1672, 2128, +1127, 1678, 2221, +1173, 1647, 2295, +1519, 1631, 2386, +1775, 1634, 2475, +1894, 1629, 2511, +1894, 1629, 2511, +1894, 1629, 2511, +1894, 1629, 2511, +1894, 1629, 2511, +1894, 1629, 2511, +1894, 1629, 2511, +1894, 1629, 2511, +1894, 1629, 2511, +1894, 1629, 2511, +1785, 1818, 1978, +1786, 1818, 1978, +1786, 1818, 1979, +1786, 1818, 1980, +1786, 1818, 1981, +1787, 1818, 1982, +1788, 1818, 1983, +1789, 1818, 1986, +1790, 1818, 1988, +1792, 1818, 1992, +1788, 1818, 1998, +1781, 1818, 2007, +1772, 1818, 2018, +1752, 1824, 2037, +1733, 1818, 2052, +1727, 1802, 2080, +1685, 1816, 2123, +1705, 1809, 2166, +1657, 1793, 2234, +1664, 1793, 2304, +1754, 1797, 2389, +1874, 1790, 2475, +1964, 1800, 2514, +1964, 1800, 2514, +1964, 1800, 2514, +1964, 1800, 2514, +1964, 1800, 2514, +1964, 1800, 2514, +1964, 1800, 2514, +1964, 1800, 2514, +1964, 1800, 2514, +1964, 1800, 2514, +1958, 1958, 2028, +1957, 1958, 2029, +1957, 1958, 2029, +1957, 1958, 2030, +1956, 1958, 2031, +1956, 1958, 2031, +1956, 1958, 2033, +1955, 1958, 2035, +1954, 1958, 2037, +1953, 1958, 2041, +1951, 1958, 2045, +1948, 1958, 2051, +1946, 1958, 2058, +1941, 1962, 2068, +1935, 1968, 2081, +1927, 1969, 2115, +1913, 1965, 2153, +1905, 1963, 2189, +1920, 1969, 2243, +1881, 1969, 2320, +1929, 1954, 2391, +2032, 1964, 2481, +2093, 1969, 2517, +2093, 1969, 2517, +2093, 1969, 2517, +2093, 1969, 2517, +2093, 1969, 2517, +2093, 1969, 2517, +2093, 1969, 2517, +2093, 1969, 2517, +2093, 1969, 2517, +2093, 1969, 2517, +2119, 2119, 2068, +2119, 2119, 2068, +2119, 2119, 2068, +2119, 2120, 2069, +2119, 2120, 2069, +2119, 2120, 2071, +2119, 2120, 2072, +2119, 2121, 2073, +2119, 2122, 2076, +2119, 2122, 2079, +2119, 2124, 2083, +2119, 2125, 2088, +2119, 2127, 2095, +2119, 2127, 2101, +2119, 2127, 2110, +2115, 2131, 2133, +2108, 2133, 2164, +2103, 2131, 2206, +2110, 2135, 2256, +2119, 2135, 2316, +2148, 2131, 2395, +2212, 2147, 2485, +2261, 2159, 2524, +2261, 2159, 2524, +2261, 2159, 2524, +2261, 2159, 2524, +2261, 2159, 2524, +2261, 2159, 2524, +2261, 2159, 2524, +2261, 2159, 2524, +2261, 2159, 2524, +2261, 2159, 2524, +2370, 2355, 2124, +2370, 2355, 2124, +2370, 2355, 2124, +2370, 2355, 2125, +2369, 2356, 2125, +2369, 2356, 2126, +2369, 2356, 2126, +2369, 2356, 2127, +2369, 2357, 2129, +2368, 2357, 2131, +2367, 2358, 2133, +2368, 2359, 2137, +2369, 2360, 2143, +2370, 2358, 2146, +2369, 2356, 2148, +2368, 2358, 2163, +2370, 2358, 2193, +2369, 2358, 2226, +2372, 2355, 2273, +2383, 2356, 2337, +2410, 2367, 2405, +2467, 2385, 2498, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2681, 2655, 1963, +2681, 2655, 1963, +2681, 2655, 1963, +2681, 2655, 1963, +2681, 2654, 1964, +2681, 2654, 1965, +2681, 2654, 1966, +2681, 2654, 1968, +2681, 2654, 1967, +2681, 2654, 1965, +2680, 2653, 1964, +2680, 2653, 1961, +2679, 2652, 1961, +2678, 2653, 1968, +2677, 2654, 1989, +2676, 2653, 2013, +2675, 2649, 2032, +2677, 2655, 2124, +2681, 2656, 2208, +2687, 2661, 2306, +2695, 2667, 2410, +2715, 2678, 2527, +2722, 2684, 2575, +2722, 2684, 2575, +2722, 2684, 2575, +2722, 2684, 2575, +2722, 2684, 2575, +2722, 2684, 2575, +2722, 2684, 2575, +2722, 2684, 2575, +2722, 2684, 2575, +2722, 2684, 2575, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2771, 2455, +2709, 2773, 2484, +2714, 2773, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2771, 2455, +2709, 2773, 2484, +2714, 2773, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2771, 2455, +2709, 2773, 2484, +2714, 2773, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2771, 2455, +2709, 2773, 2484, +2714, 2773, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2771, 2455, +2709, 2773, 2484, +2714, 2773, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2771, 2455, +2709, 2773, 2484, +2714, 2773, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2771, 2455, +2709, 2773, 2484, +2714, 2773, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2771, 2455, +2709, 2773, 2484, +2714, 2773, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2771, 2455, +2709, 2773, 2484, +2714, 2773, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2771, 2455, +2709, 2773, 2484, +2714, 2773, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 28, +0, 0, 152, +0, 0, 280, +0, 0, 408, +0, 0, 537, +0, 0, 667, +0, 0, 797, +0, 0, 928, +0, 0, 1088, +0, 0, 1293, +0, 0, 1473, +0, 0, 1634, +398, 0, 1772, +1148, 0, 1882, +1561, 0, 2006, +1560, 0, 2154, +428, 987, 2341, +1231, 619, 2470, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 36, +0, 0, 159, +0, 0, 285, +0, 0, 412, +0, 0, 540, +0, 0, 669, +0, 0, 799, +0, 0, 930, +0, 0, 1089, +0, 0, 1294, +0, 0, 1474, +0, 0, 1635, +378, 0, 1771, +1147, 0, 1882, +1561, 0, 2006, +1559, 0, 2154, +428, 992, 2341, +1235, 621, 2470, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 71, +0, 0, 186, +0, 0, 305, +0, 0, 427, +0, 0, 551, +0, 0, 678, +0, 0, 805, +0, 0, 935, +0, 0, 1092, +0, 0, 1296, +0, 0, 1475, +0, 0, 1635, +389, 0, 1772, +1146, 0, 1883, +1558, 0, 2007, +1555, 0, 2155, +423, 998, 2341, +1241, 621, 2470, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 13, +0, 0, 112, +0, 0, 219, +0, 0, 330, +0, 0, 446, +0, 0, 566, +0, 0, 689, +0, 0, 814, +0, 0, 941, +0, 0, 1097, +0, 0, 1299, +0, 0, 1477, +0, 0, 1636, +403, 0, 1773, +1145, 0, 1884, +1554, 0, 2008, +1549, 0, 2156, +416, 1005, 2342, +1249, 621, 2470, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 13, +0, 0, 163, +0, 0, 259, +0, 0, 363, +0, 0, 472, +0, 0, 586, +0, 0, 704, +0, 0, 825, +0, 0, 949, +0, 0, 1103, +0, 0, 1303, +0, 0, 1480, +0, 0, 1637, +422, 0, 1775, +1143, 0, 1884, +1548, 0, 2010, +1541, 50, 2158, +407, 1015, 2342, +1259, 621, 2470, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 13, +0, 0, 163, +0, 38, 309, +0, 38, 402, +0, 38, 503, +0, 38, 610, +0, 38, 723, +0, 38, 840, +0, 38, 961, +0, 102, 1111, +0, 30, 1308, +0, 30, 1483, +0, 0, 1639, +445, 0, 1776, +1140, 0, 1886, +1541, 0, 2011, +1531, 190, 2160, +394, 1028, 2343, +1272, 621, 2470, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +0, 4, 0, +0, 0, 0, +0, 20, 0, +0, 52, 13, +0, 91, 163, +0, 139, 309, +0, 195, 450, +0, 195, 542, +0, 195, 641, +0, 195, 748, +0, 195, 859, +0, 195, 975, +0, 242, 1121, +0, 163, 1315, +0, 163, 1488, +0, 135, 1641, +475, 0, 1779, +1137, 0, 1888, +1532, 32, 2014, +1516, 329, 2163, +376, 1045, 2344, +1289, 621, 2470, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +0, 144, 0, +0, 137, 0, +0, 155, 0, +0, 179, 13, +0, 209, 163, +0, 246, 309, +0, 291, 450, +0, 346, 589, +0, 346, 680, +0, 346, 778, +0, 346, 883, +0, 346, 994, +0, 380, 1135, +0, 295, 1324, +0, 295, 1494, +0, 274, 1644, +512, 108, 1782, +1133, 0, 1891, +1518, 164, 2017, +1496, 465, 2167, +352, 1066, 2345, +1311, 621, 2470, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +0, 281, 0, +0, 276, 0, +0, 289, 0, +0, 307, 13, +0, 330, 163, +0, 359, 309, +0, 394, 450, +0, 438, 589, +0, 491, 727, +0, 491, 816, +0, 491, 914, +0, 491, 1018, +0, 516, 1153, +0, 426, 1336, +0, 426, 1502, +0, 412, 1648, +557, 254, 1787, +1126, 111, 1894, +1500, 296, 2021, +1468, 601, 2172, +317, 1093, 2347, +1350, 639, 2470, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +0, 417, 0, +0, 413, 0, +0, 423, 0, +0, 437, 13, +0, 454, 163, +0, 476, 309, +0, 504, 450, +0, 539, 589, +0, 581, 727, +0, 633, 862, +0, 633, 952, +0, 633, 1049, +0, 651, 1176, +0, 570, 1351, +0, 559, 1513, +0, 547, 1653, +561, 434, 1790, +1118, 244, 1898, +1474, 428, 2027, +1427, 736, 2178, +265, 1128, 2349, +1398, 662, 2470, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +0, 552, 0, +0, 549, 0, +0, 557, 0, +0, 566, 13, +0, 579, 163, +0, 596, 309, +0, 618, 450, +0, 645, 589, +0, 679, 727, +0, 721, 862, +0, 772, 997, +0, 772, 1086, +0, 785, 1204, +0, 726, 1371, +0, 691, 1527, +0, 682, 1662, +561, 601, 1796, +1135, 422, 1904, +1436, 560, 2035, +1366, 869, 2187, +186, 1169, 2352, +1455, 691, 2470, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +0, 686, 0, +0, 684, 0, +0, 690, 0, +0, 697, 13, +0, 707, 163, +0, 720, 309, +0, 736, 450, +0, 758, 589, +0, 784, 727, +0, 818, 862, +0, 859, 997, +0, 909, 1132, +0, 919, 1240, +0, 876, 1396, +0, 823, 1545, +0, 817, 1675, +561, 758, 1802, +1163, 593, 1912, +1381, 692, 2045, +1269, 1003, 2199, +0, 1212, 2357, +1522, 728, 2470, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +0, 854, 85, +0, 854, 130, +0, 858, 201, +0, 863, 282, +0, 870, 371, +0, 879, 468, +0, 891, 572, +0, 906, 682, +0, 925, 797, +0, 950, 916, +0, 981, 1038, +0, 1020, 1162, +0, 1060, 1288, +0, 1029, 1430, +0, 983, 1570, +0, 969, 1697, +572, 942, 1817, +1182, 800, 1926, +1302, 849, 2057, +1120, 1137, 2212, +0, 1254, 2365, +1585, 800, 2470, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +0, 1183, 1025, +0, 1183, 1031, +0, 1183, 1036, +0, 1183, 1043, +0, 1183, 1052, +0, 1183, 1064, +0, 1183, 1080, +0, 1183, 1099, +0, 1183, 1125, +0, 1188, 1168, +0, 1207, 1242, +0, 1231, 1325, +0, 1257, 1417, +0, 1236, 1493, +0, 1208, 1617, +0, 1221, 1741, +640, 1187, 1855, +1045, 1132, 1961, +1243, 1131, 2080, +1031, 1271, 2225, +498, 1311, 2371, +1589, 1031, 2471, +1765, 1143, 2512, +1765, 1143, 2512, +1765, 1143, 2512, +1765, 1143, 2512, +1765, 1143, 2512, +1765, 1143, 2512, +1765, 1143, 2512, +1765, 1143, 2512, +1765, 1143, 2512, +1765, 1143, 2512, +0, 1421, 1376, +0, 1421, 1379, +0, 1421, 1382, +0, 1421, 1385, +0, 1421, 1389, +0, 1421, 1395, +0, 1421, 1402, +0, 1421, 1412, +0, 1421, 1425, +0, 1421, 1442, +0, 1421, 1463, +0, 1421, 1491, +0, 1431, 1546, +0, 1417, 1605, +0, 1399, 1673, +0, 1411, 1786, +640, 1405, 1896, +1052, 1353, 1999, +1151, 1350, 2110, +878, 1405, 2240, +684, 1387, 2378, +1602, 1208, 2473, +1799, 1313, 2510, +1799, 1313, 2510, +1799, 1313, 2510, +1799, 1313, 2510, +1799, 1313, 2510, +1799, 1313, 2510, +1799, 1313, 2510, +1799, 1313, 2510, +1799, 1313, 2510, +1799, 1313, 2510, +913, 1579, 1648, +912, 1579, 1649, +912, 1579, 1651, +912, 1579, 1653, +912, 1578, 1655, +912, 1577, 1658, +912, 1576, 1662, +912, 1574, 1668, +912, 1572, 1675, +912, 1569, 1685, +912, 1567, 1698, +912, 1567, 1714, +892, 1567, 1736, +891, 1577, 1788, +891, 1569, 1838, +896, 1552, 1889, +818, 1557, 1970, +929, 1536, 2067, +946, 1537, 2170, +810, 1524, 2268, +1128, 1500, 2382, +1680, 1435, 2473, +1845, 1471, 2509, +1845, 1471, 2509, +1845, 1471, 2509, +1845, 1471, 2509, +1845, 1471, 2509, +1845, 1471, 2509, +1845, 1471, 2509, +1845, 1471, 2509, +1845, 1471, 2509, +1845, 1471, 2509, +1450, 1705, 1856, +1449, 1705, 1856, +1448, 1705, 1857, +1446, 1705, 1859, +1444, 1705, 1860, +1442, 1705, 1862, +1439, 1705, 1865, +1434, 1705, 1868, +1427, 1705, 1873, +1427, 1703, 1880, +1427, 1700, 1888, +1427, 1696, 1899, +1424, 1691, 1913, +1401, 1685, 1931, +1401, 1696, 1976, +1370, 1701, 2022, +1372, 1685, 2062, +1195, 1672, 2128, +1129, 1678, 2221, +1176, 1647, 2295, +1520, 1631, 2386, +1776, 1634, 2475, +1894, 1629, 2511, +1894, 1629, 2511, +1894, 1629, 2511, +1894, 1629, 2511, +1894, 1629, 2511, +1894, 1629, 2511, +1894, 1629, 2511, +1894, 1629, 2511, +1894, 1629, 2511, +1894, 1629, 2511, +1786, 1817, 1978, +1786, 1817, 1978, +1786, 1817, 1979, +1786, 1817, 1980, +1787, 1817, 1981, +1787, 1817, 1982, +1788, 1817, 1983, +1789, 1817, 1986, +1790, 1817, 1988, +1793, 1817, 1992, +1789, 1817, 1998, +1782, 1817, 2007, +1772, 1818, 2018, +1753, 1824, 2036, +1733, 1818, 2052, +1727, 1803, 2080, +1686, 1816, 2123, +1706, 1808, 2166, +1658, 1793, 2234, +1664, 1793, 2304, +1754, 1797, 2389, +1874, 1790, 2475, +1964, 1800, 2514, +1964, 1800, 2514, +1964, 1800, 2514, +1964, 1800, 2514, +1964, 1800, 2514, +1964, 1800, 2514, +1964, 1800, 2514, +1964, 1800, 2514, +1964, 1800, 2514, +1964, 1800, 2514, +1958, 1958, 2028, +1958, 1958, 2029, +1957, 1958, 2029, +1957, 1958, 2030, +1957, 1958, 2031, +1956, 1958, 2031, +1956, 1958, 2033, +1955, 1958, 2035, +1954, 1958, 2037, +1953, 1958, 2041, +1951, 1958, 2045, +1948, 1958, 2051, +1946, 1958, 2058, +1941, 1962, 2068, +1936, 1968, 2081, +1927, 1969, 2115, +1913, 1965, 2153, +1905, 1963, 2189, +1920, 1969, 2243, +1881, 1968, 2320, +1929, 1954, 2392, +2033, 1964, 2481, +2094, 1969, 2517, +2094, 1969, 2517, +2094, 1969, 2517, +2094, 1969, 2517, +2094, 1969, 2517, +2094, 1969, 2517, +2094, 1969, 2517, +2094, 1969, 2517, +2094, 1969, 2517, +2094, 1969, 2517, +2120, 2119, 2068, +2120, 2119, 2068, +2120, 2119, 2068, +2120, 2120, 2069, +2120, 2120, 2069, +2120, 2120, 2070, +2120, 2120, 2072, +2120, 2121, 2073, +2120, 2122, 2076, +2120, 2122, 2079, +2120, 2124, 2083, +2120, 2125, 2088, +2119, 2127, 2095, +2119, 2127, 2101, +2119, 2127, 2110, +2115, 2131, 2133, +2109, 2133, 2164, +2103, 2131, 2206, +2111, 2135, 2256, +2119, 2135, 2316, +2148, 2131, 2395, +2212, 2147, 2485, +2261, 2159, 2524, +2261, 2159, 2524, +2261, 2159, 2524, +2261, 2159, 2524, +2261, 2159, 2524, +2261, 2159, 2524, +2261, 2159, 2524, +2261, 2159, 2524, +2261, 2159, 2524, +2261, 2159, 2524, +2370, 2355, 2124, +2370, 2355, 2124, +2370, 2355, 2124, +2370, 2355, 2125, +2370, 2356, 2125, +2369, 2356, 2126, +2369, 2356, 2126, +2369, 2356, 2127, +2369, 2357, 2129, +2368, 2357, 2131, +2367, 2358, 2133, +2368, 2359, 2137, +2369, 2360, 2143, +2370, 2358, 2146, +2369, 2356, 2148, +2368, 2358, 2163, +2370, 2358, 2193, +2369, 2358, 2226, +2372, 2355, 2273, +2383, 2356, 2337, +2410, 2367, 2405, +2467, 2385, 2498, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2681, 2655, 1963, +2681, 2655, 1963, +2681, 2655, 1963, +2681, 2655, 1964, +2681, 2655, 1965, +2681, 2654, 1965, +2681, 2654, 1966, +2681, 2654, 1968, +2681, 2654, 1967, +2681, 2654, 1966, +2680, 2653, 1964, +2680, 2653, 1962, +2679, 2652, 1962, +2678, 2653, 1969, +2677, 2654, 1990, +2676, 2653, 2014, +2675, 2650, 2033, +2677, 2655, 2124, +2681, 2656, 2208, +2687, 2661, 2306, +2695, 2667, 2410, +2715, 2678, 2527, +2722, 2684, 2575, +2722, 2684, 2575, +2722, 2684, 2575, +2722, 2684, 2575, +2722, 2684, 2575, +2722, 2684, 2575, +2722, 2684, 2575, +2722, 2684, 2575, +2722, 2684, 2575, +2722, 2684, 2575, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2771, 2455, +2709, 2773, 2484, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2771, 2455, +2709, 2773, 2484, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2771, 2455, +2709, 2773, 2484, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2771, 2455, +2709, 2773, 2484, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2771, 2455, +2709, 2773, 2484, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2771, 2455, +2709, 2773, 2484, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2771, 2455, +2709, 2773, 2484, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2771, 2455, +2709, 2773, 2484, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2771, 2455, +2709, 2773, 2484, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2771, 2455, +2709, 2773, 2484, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 28, +0, 0, 152, +0, 0, 280, +0, 0, 408, +0, 0, 537, +0, 0, 667, +0, 0, 797, +0, 0, 928, +0, 0, 1088, +0, 0, 1296, +0, 0, 1475, +0, 0, 1634, +445, 0, 1772, +1152, 0, 1882, +1561, 0, 2006, +1559, 0, 2155, +423, 987, 2341, +1234, 615, 2470, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 36, +0, 0, 159, +0, 0, 285, +0, 0, 412, +0, 0, 540, +0, 0, 669, +0, 0, 799, +0, 0, 930, +0, 0, 1089, +0, 0, 1297, +0, 0, 1475, +0, 0, 1635, +426, 0, 1772, +1151, 0, 1882, +1561, 0, 2007, +1558, 0, 2155, +423, 992, 2341, +1238, 618, 2470, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 48, +0, 0, 168, +0, 0, 291, +0, 0, 417, +0, 0, 544, +0, 0, 672, +0, 0, 801, +0, 0, 931, +0, 0, 1090, +0, 0, 1298, +0, 0, 1476, +0, 0, 1635, +400, 0, 1772, +1150, 0, 1883, +1560, 0, 2007, +1556, 0, 2155, +423, 998, 2341, +1244, 621, 2470, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 92, +0, 0, 203, +0, 0, 318, +0, 0, 437, +0, 0, 559, +0, 0, 683, +0, 0, 810, +0, 0, 938, +0, 0, 1094, +0, 0, 1300, +0, 0, 1478, +0, 0, 1636, +414, 0, 1773, +1149, 0, 1884, +1556, 0, 2008, +1550, 0, 2156, +416, 1005, 2342, +1252, 621, 2470, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 145, +0, 0, 245, +0, 0, 351, +0, 0, 462, +0, 0, 579, +0, 0, 699, +0, 0, 821, +0, 0, 946, +0, 0, 1101, +0, 0, 1304, +0, 0, 1481, +0, 0, 1637, +432, 0, 1774, +1147, 0, 1885, +1551, 0, 2010, +1543, 38, 2158, +407, 1015, 2342, +1262, 621, 2470, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 145, +0, 1, 295, +0, 1, 391, +0, 1, 494, +0, 1, 604, +0, 1, 718, +0, 1, 836, +0, 1, 958, +0, 70, 1109, +0, 30, 1310, +0, 30, 1484, +0, 0, 1639, +455, 0, 1776, +1144, 0, 1886, +1544, 0, 2012, +1532, 182, 2160, +394, 1028, 2343, +1275, 621, 2470, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +0, 4, 0, +0, 0, 0, +0, 0, 0, +0, 16, 0, +0, 58, 145, +0, 109, 295, +0, 170, 441, +0, 170, 534, +0, 170, 635, +0, 170, 742, +0, 170, 855, +0, 170, 973, +0, 218, 1119, +0, 163, 1316, +0, 163, 1489, +0, 126, 1641, +484, 0, 1778, +1141, 0, 1888, +1534, 32, 2014, +1518, 322, 2163, +376, 1045, 2344, +1292, 621, 2470, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +0, 144, 0, +0, 137, 0, +0, 127, 0, +0, 152, 0, +0, 184, 145, +0, 223, 295, +0, 271, 441, +0, 327, 582, +0, 327, 674, +0, 327, 773, +0, 327, 879, +0, 327, 991, +0, 363, 1133, +0, 295, 1325, +0, 295, 1495, +0, 267, 1644, +520, 87, 1782, +1137, 0, 1891, +1521, 164, 2017, +1498, 461, 2167, +352, 1066, 2345, +1314, 621, 2470, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +0, 281, 0, +0, 276, 0, +0, 269, 0, +0, 287, 0, +0, 311, 145, +0, 341, 295, +0, 378, 441, +0, 423, 582, +0, 478, 721, +0, 478, 812, +0, 478, 910, +0, 478, 1016, +0, 503, 1151, +0, 426, 1337, +0, 426, 1503, +0, 406, 1648, +565, 239, 1786, +1131, 111, 1894, +1503, 296, 2022, +1470, 597, 2172, +317, 1093, 2347, +1353, 639, 2470, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +0, 417, 0, +0, 413, 0, +0, 408, 0, +0, 422, 0, +0, 439, 145, +0, 462, 295, +0, 491, 441, +0, 527, 582, +0, 570, 721, +0, 623, 859, +0, 623, 948, +0, 623, 1046, +0, 642, 1174, +0, 570, 1352, +0, 559, 1514, +0, 544, 1653, +569, 424, 1790, +1123, 244, 1899, +1477, 428, 2027, +1429, 733, 2178, +265, 1128, 2349, +1400, 662, 2470, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +0, 552, 0, +0, 549, 0, +0, 545, 0, +0, 555, 0, +0, 568, 145, +0, 586, 295, +0, 608, 441, +0, 636, 582, +0, 670, 721, +0, 713, 859, +0, 765, 995, +0, 765, 1084, +0, 778, 1202, +0, 726, 1372, +0, 691, 1528, +0, 680, 1662, +569, 594, 1795, +1139, 422, 1905, +1440, 560, 2035, +1368, 868, 2187, +186, 1169, 2352, +1457, 691, 2470, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +0, 686, 0, +0, 684, 0, +0, 681, 0, +0, 689, 0, +0, 699, 145, +0, 712, 295, +0, 729, 441, +0, 750, 582, +0, 777, 721, +0, 811, 859, +0, 854, 995, +0, 904, 1130, +0, 914, 1238, +0, 876, 1397, +0, 823, 1546, +0, 815, 1675, +569, 753, 1802, +1167, 593, 1913, +1385, 692, 2045, +1272, 1002, 2199, +0, 1212, 2357, +1524, 728, 2470, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +0, 854, 85, +0, 854, 130, +0, 852, 185, +0, 857, 268, +0, 864, 360, +0, 873, 459, +0, 885, 565, +0, 901, 676, +0, 920, 793, +0, 946, 912, +0, 977, 1035, +0, 1016, 1160, +0, 1056, 1287, +0, 1029, 1432, +0, 983, 1571, +0, 967, 1697, +579, 939, 1816, +1186, 800, 1926, +1306, 849, 2057, +1123, 1137, 2212, +0, 1254, 2365, +1587, 800, 2470, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +0, 1181, 1022, +0, 1181, 1028, +0, 1181, 1036, +0, 1181, 1043, +0, 1181, 1052, +0, 1181, 1064, +0, 1181, 1080, +0, 1181, 1099, +0, 1181, 1125, +0, 1186, 1168, +0, 1205, 1242, +0, 1229, 1325, +0, 1255, 1417, +0, 1235, 1494, +0, 1207, 1618, +0, 1219, 1741, +647, 1188, 1855, +1051, 1133, 1961, +1243, 1131, 2080, +1031, 1271, 2225, +532, 1310, 2371, +1590, 1030, 2471, +1766, 1141, 2512, +1766, 1141, 2512, +1766, 1141, 2512, +1766, 1141, 2512, +1766, 1141, 2512, +1766, 1141, 2512, +1766, 1141, 2512, +1766, 1141, 2512, +1766, 1141, 2512, +1766, 1141, 2512, +0, 1420, 1375, +0, 1420, 1378, +0, 1420, 1382, +0, 1420, 1385, +0, 1420, 1389, +0, 1420, 1395, +0, 1420, 1402, +0, 1420, 1412, +0, 1420, 1425, +0, 1420, 1442, +0, 1420, 1463, +0, 1420, 1491, +0, 1430, 1546, +0, 1417, 1606, +0, 1398, 1674, +0, 1410, 1786, +647, 1405, 1896, +1059, 1354, 2000, +1151, 1350, 2109, +878, 1405, 2240, +706, 1386, 2378, +1603, 1208, 2473, +1800, 1311, 2510, +1800, 1311, 2510, +1800, 1311, 2510, +1800, 1311, 2510, +1800, 1311, 2510, +1800, 1311, 2510, +1800, 1311, 2510, +1800, 1311, 2510, +1800, 1311, 2510, +1800, 1311, 2510, +929, 1579, 1649, +928, 1579, 1650, +926, 1579, 1651, +926, 1579, 1653, +926, 1578, 1655, +926, 1577, 1658, +926, 1576, 1663, +926, 1574, 1668, +926, 1572, 1676, +926, 1569, 1685, +926, 1567, 1698, +926, 1567, 1715, +906, 1567, 1736, +898, 1576, 1787, +898, 1569, 1837, +906, 1552, 1889, +833, 1557, 1970, +939, 1536, 2067, +950, 1537, 2170, +810, 1524, 2268, +1132, 1500, 2382, +1680, 1435, 2473, +1845, 1471, 2509, +1845, 1471, 2509, +1845, 1471, 2509, +1845, 1471, 2509, +1845, 1471, 2509, +1845, 1471, 2509, +1845, 1471, 2509, +1845, 1471, 2509, +1845, 1471, 2509, +1845, 1471, 2509, +1452, 1705, 1855, +1450, 1705, 1856, +1449, 1705, 1857, +1448, 1705, 1859, +1446, 1705, 1860, +1443, 1705, 1862, +1440, 1705, 1865, +1435, 1705, 1868, +1429, 1705, 1873, +1428, 1703, 1880, +1428, 1700, 1888, +1428, 1696, 1899, +1425, 1691, 1913, +1402, 1685, 1931, +1402, 1696, 1977, +1371, 1701, 2021, +1374, 1685, 2062, +1200, 1672, 2128, +1132, 1678, 2221, +1180, 1647, 2295, +1520, 1631, 2386, +1776, 1634, 2475, +1894, 1628, 2511, +1894, 1628, 2511, +1894, 1628, 2511, +1894, 1628, 2511, +1894, 1628, 2511, +1894, 1628, 2511, +1894, 1628, 2511, +1894, 1628, 2511, +1894, 1628, 2511, +1894, 1628, 2511, +1787, 1817, 1978, +1787, 1817, 1978, +1786, 1817, 1979, +1786, 1817, 1980, +1787, 1817, 1981, +1787, 1817, 1982, +1788, 1817, 1983, +1789, 1817, 1986, +1791, 1817, 1988, +1793, 1817, 1992, +1789, 1817, 1998, +1782, 1817, 2007, +1772, 1818, 2018, +1753, 1823, 2036, +1734, 1818, 2052, +1728, 1803, 2080, +1687, 1816, 2123, +1706, 1808, 2166, +1658, 1793, 2234, +1666, 1793, 2304, +1755, 1797, 2389, +1874, 1790, 2475, +1965, 1800, 2514, +1965, 1800, 2514, +1965, 1800, 2514, +1965, 1800, 2514, +1965, 1800, 2514, +1965, 1800, 2514, +1965, 1800, 2514, +1965, 1800, 2514, +1965, 1800, 2514, +1965, 1800, 2514, +1958, 1958, 2029, +1958, 1958, 2029, +1958, 1958, 2029, +1958, 1958, 2030, +1957, 1958, 2031, +1957, 1958, 2032, +1956, 1958, 2033, +1955, 1958, 2035, +1955, 1958, 2037, +1953, 1958, 2041, +1951, 1958, 2045, +1949, 1958, 2051, +1946, 1958, 2058, +1941, 1962, 2068, +1936, 1968, 2081, +1927, 1969, 2114, +1914, 1966, 2153, +1905, 1963, 2189, +1920, 1969, 2243, +1882, 1968, 2320, +1930, 1954, 2392, +2034, 1964, 2481, +2094, 1969, 2517, +2094, 1969, 2517, +2094, 1969, 2517, +2094, 1969, 2517, +2094, 1969, 2517, +2094, 1969, 2517, +2094, 1969, 2517, +2094, 1969, 2517, +2094, 1969, 2517, +2094, 1969, 2517, +2120, 2119, 2068, +2120, 2119, 2068, +2120, 2119, 2068, +2120, 2120, 2069, +2120, 2120, 2069, +2120, 2120, 2070, +2120, 2120, 2071, +2120, 2121, 2073, +2120, 2122, 2076, +2120, 2122, 2079, +2120, 2124, 2083, +2120, 2125, 2088, +2119, 2127, 2095, +2119, 2127, 2101, +2119, 2127, 2110, +2116, 2131, 2132, +2109, 2133, 2164, +2103, 2131, 2206, +2111, 2135, 2256, +2120, 2135, 2316, +2148, 2131, 2395, +2212, 2147, 2485, +2261, 2159, 2524, +2261, 2159, 2524, +2261, 2159, 2524, +2261, 2159, 2524, +2261, 2159, 2524, +2261, 2159, 2524, +2261, 2159, 2524, +2261, 2159, 2524, +2261, 2159, 2524, +2261, 2159, 2524, +2370, 2355, 2124, +2370, 2355, 2124, +2370, 2355, 2124, +2370, 2355, 2125, +2370, 2355, 2125, +2370, 2356, 2126, +2369, 2356, 2126, +2369, 2356, 2127, +2369, 2357, 2129, +2368, 2357, 2131, +2367, 2358, 2133, +2368, 2359, 2137, +2369, 2360, 2143, +2370, 2358, 2146, +2369, 2356, 2148, +2368, 2358, 2163, +2370, 2358, 2193, +2369, 2358, 2226, +2372, 2355, 2273, +2384, 2356, 2337, +2410, 2367, 2405, +2467, 2385, 2498, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2681, 2655, 1963, +2681, 2655, 1963, +2681, 2655, 1964, +2681, 2655, 1965, +2681, 2655, 1965, +2681, 2655, 1966, +2681, 2654, 1967, +2681, 2654, 1969, +2681, 2654, 1968, +2681, 2654, 1966, +2680, 2653, 1965, +2680, 2653, 1962, +2679, 2652, 1963, +2678, 2653, 1970, +2677, 2655, 1992, +2676, 2653, 2015, +2675, 2650, 2035, +2677, 2655, 2124, +2681, 2656, 2208, +2687, 2661, 2306, +2695, 2666, 2409, +2715, 2678, 2527, +2722, 2684, 2575, +2722, 2684, 2575, +2722, 2684, 2575, +2722, 2684, 2575, +2722, 2684, 2575, +2722, 2684, 2575, +2722, 2684, 2575, +2722, 2684, 2575, +2722, 2684, 2575, +2722, 2684, 2575, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2771, 2455, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2771, 2455, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2771, 2455, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2771, 2455, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2771, 2455, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2771, 2455, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2771, 2455, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2771, 2455, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2771, 2455, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2771, 2455, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 28, +0, 0, 152, +0, 0, 280, +0, 0, 408, +0, 0, 537, +0, 0, 667, +0, 0, 797, +0, 0, 928, +0, 0, 1088, +0, 0, 1300, +0, 0, 1478, +0, 0, 1634, +499, 0, 1773, +1157, 0, 1883, +1561, 0, 2007, +1557, 0, 2156, +416, 987, 2341, +1238, 611, 2470, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 36, +0, 0, 159, +0, 0, 285, +0, 0, 412, +0, 0, 540, +0, 0, 669, +0, 0, 799, +0, 0, 930, +0, 0, 1089, +0, 0, 1301, +0, 0, 1478, +0, 0, 1635, +483, 0, 1773, +1157, 0, 1883, +1561, 0, 2007, +1556, 0, 2156, +416, 992, 2341, +1243, 614, 2470, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 48, +0, 0, 168, +0, 0, 291, +0, 0, 417, +0, 0, 544, +0, 0, 672, +0, 0, 801, +0, 0, 931, +0, 0, 1090, +0, 0, 1302, +0, 0, 1479, +0, 0, 1635, +460, 0, 1772, +1156, 0, 1884, +1560, 0, 2008, +1554, 0, 2156, +416, 998, 2341, +1249, 617, 2470, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 63, +0, 0, 180, +0, 0, 300, +0, 0, 424, +0, 0, 549, +0, 0, 676, +0, 0, 804, +0, 0, 933, +0, 0, 1091, +0, 0, 1302, +0, 0, 1480, +0, 0, 1636, +427, 0, 1772, +1154, 0, 1884, +1560, 0, 2009, +1552, 0, 2156, +416, 1005, 2342, +1256, 621, 2470, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 120, +0, 0, 224, +0, 0, 335, +0, 0, 450, +0, 0, 569, +0, 0, 691, +0, 0, 816, +0, 0, 942, +0, 0, 1097, +0, 0, 1306, +0, 0, 1482, +0, 0, 1637, +445, 0, 1774, +1153, 0, 1885, +1554, 0, 2010, +1544, 22, 2158, +407, 1015, 2342, +1266, 621, 2470, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 120, +0, 0, 277, +0, 0, 376, +0, 0, 483, +0, 0, 594, +0, 0, 711, +0, 0, 831, +0, 0, 954, +0, 23, 1106, +0, 30, 1311, +0, 30, 1486, +0, 0, 1639, +467, 0, 1775, +1150, 0, 1887, +1547, 0, 2012, +1534, 170, 2160, +394, 1028, 2343, +1279, 621, 2470, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +0, 4, 0, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 11, 120, +0, 67, 277, +0, 133, 427, +0, 133, 523, +0, 133, 627, +0, 133, 736, +0, 133, 850, +0, 133, 968, +0, 186, 1116, +0, 163, 1318, +0, 163, 1490, +0, 112, 1641, +496, 0, 1778, +1147, 0, 1888, +1538, 32, 2014, +1520, 314, 2163, +376, 1045, 2344, +1296, 621, 2470, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +0, 144, 0, +0, 137, 0, +0, 127, 0, +0, 114, 0, +0, 148, 120, +0, 190, 277, +0, 241, 427, +0, 302, 573, +0, 302, 666, +0, 302, 767, +0, 302, 875, +0, 302, 987, +0, 339, 1130, +0, 295, 1327, +0, 295, 1496, +0, 258, 1644, +531, 58, 1781, +1142, 0, 1891, +1524, 164, 2018, +1500, 455, 2167, +352, 1066, 2345, +1318, 621, 2470, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +0, 281, 0, +0, 276, 0, +0, 269, 0, +0, 259, 0, +0, 284, 120, +0, 316, 277, +0, 355, 427, +0, 403, 573, +0, 459, 714, +0, 459, 806, +0, 459, 906, +0, 459, 1012, +0, 486, 1148, +0, 426, 1339, +0, 426, 1504, +0, 399, 1648, +574, 219, 1786, +1136, 111, 1894, +1506, 296, 2022, +1472, 593, 2172, +317, 1093, 2347, +1356, 639, 2470, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +0, 417, 0, +0, 413, 0, +0, 408, 0, +0, 401, 0, +0, 419, 120, +0, 443, 277, +0, 473, 427, +0, 510, 573, +0, 556, 714, +0, 610, 854, +0, 610, 944, +0, 610, 1043, +0, 629, 1171, +0, 570, 1354, +0, 559, 1515, +0, 539, 1653, +578, 410, 1789, +1128, 244, 1899, +1481, 428, 2028, +1431, 730, 2178, +265, 1128, 2349, +1403, 662, 2470, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +0, 552, 0, +0, 549, 0, +0, 545, 0, +0, 540, 0, +0, 553, 120, +0, 571, 277, +0, 594, 427, +0, 623, 573, +0, 658, 714, +0, 702, 854, +0, 755, 991, +0, 755, 1080, +0, 769, 1200, +0, 726, 1374, +0, 691, 1529, +0, 676, 1662, +578, 585, 1795, +1145, 422, 1905, +1444, 560, 2035, +1371, 865, 2187, +186, 1169, 2352, +1460, 691, 2470, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +0, 686, 0, +0, 684, 0, +0, 681, 0, +0, 677, 0, +0, 688, 120, +0, 701, 277, +0, 718, 427, +0, 740, 573, +0, 768, 714, +0, 803, 854, +0, 845, 991, +0, 897, 1127, +0, 907, 1236, +0, 876, 1399, +0, 823, 1547, +0, 812, 1675, +578, 746, 1801, +1172, 593, 1913, +1390, 692, 2045, +1275, 1000, 2199, +0, 1212, 2357, +1526, 728, 2470, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +0, 854, 85, +0, 854, 130, +0, 852, 185, +0, 850, 248, +0, 857, 344, +0, 866, 446, +0, 878, 555, +0, 894, 669, +0, 914, 787, +0, 939, 908, +0, 971, 1032, +0, 1011, 1157, +0, 1051, 1285, +0, 1029, 1433, +0, 983, 1572, +27, 965, 1697, +589, 934, 1816, +1190, 800, 1926, +1312, 849, 2057, +1127, 1135, 2212, +0, 1254, 2365, +1589, 800, 2470, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +0, 1178, 1018, +0, 1178, 1024, +0, 1178, 1032, +0, 1178, 1043, +0, 1178, 1052, +0, 1178, 1064, +0, 1178, 1080, +0, 1178, 1099, +0, 1178, 1125, +0, 1184, 1168, +0, 1203, 1242, +0, 1227, 1325, +0, 1253, 1417, +21, 1234, 1496, +21, 1206, 1619, +81, 1217, 1742, +655, 1189, 1855, +1060, 1135, 1962, +1243, 1131, 2080, +1031, 1271, 2225, +573, 1308, 2371, +1592, 1028, 2471, +1767, 1138, 2512, +1767, 1138, 2512, +1767, 1138, 2512, +1767, 1138, 2512, +1767, 1138, 2512, +1767, 1138, 2512, +1767, 1138, 2512, +1767, 1138, 2512, +1767, 1138, 2512, +1767, 1138, 2512, +0, 1418, 1374, +0, 1418, 1376, +0, 1418, 1380, +0, 1418, 1385, +0, 1418, 1389, +0, 1418, 1395, +0, 1418, 1402, +0, 1418, 1412, +0, 1418, 1425, +0, 1418, 1442, +0, 1418, 1463, +0, 1418, 1491, +0, 1429, 1546, +21, 1416, 1607, +21, 1397, 1675, +81, 1409, 1787, +655, 1406, 1896, +1067, 1355, 2000, +1151, 1350, 2109, +878, 1405, 2240, +735, 1384, 2378, +1605, 1206, 2473, +1801, 1309, 2510, +1801, 1309, 2510, +1801, 1309, 2510, +1801, 1309, 2510, +1801, 1309, 2510, +1801, 1309, 2510, +1801, 1309, 2510, +1801, 1309, 2510, +1801, 1309, 2510, +1801, 1309, 2510, +949, 1577, 1650, +947, 1578, 1651, +946, 1578, 1652, +943, 1579, 1653, +943, 1578, 1656, +943, 1577, 1659, +943, 1576, 1663, +943, 1574, 1669, +943, 1572, 1676, +943, 1569, 1686, +943, 1567, 1699, +943, 1567, 1715, +924, 1567, 1737, +908, 1576, 1787, +908, 1568, 1837, +917, 1552, 1889, +852, 1557, 1971, +951, 1536, 2066, +957, 1537, 2170, +810, 1525, 2268, +1138, 1499, 2382, +1680, 1435, 2473, +1845, 1470, 2509, +1845, 1470, 2509, +1845, 1470, 2509, +1845, 1470, 2509, +1845, 1470, 2509, +1845, 1470, 2509, +1845, 1470, 2509, +1845, 1470, 2509, +1845, 1470, 2509, +1845, 1470, 2509, +1454, 1705, 1855, +1453, 1705, 1856, +1451, 1705, 1857, +1449, 1705, 1859, +1447, 1705, 1860, +1444, 1705, 1862, +1441, 1705, 1865, +1436, 1705, 1868, +1430, 1705, 1873, +1430, 1703, 1880, +1430, 1700, 1888, +1430, 1696, 1899, +1426, 1691, 1913, +1403, 1685, 1931, +1403, 1696, 1977, +1372, 1701, 2021, +1375, 1686, 2063, +1206, 1672, 2128, +1137, 1678, 2221, +1185, 1647, 2295, +1521, 1632, 2386, +1778, 1634, 2475, +1894, 1628, 2511, +1894, 1628, 2511, +1894, 1628, 2511, +1894, 1628, 2511, +1894, 1628, 2511, +1894, 1628, 2511, +1894, 1628, 2511, +1894, 1628, 2511, +1894, 1628, 2511, +1894, 1628, 2511, +1788, 1817, 1978, +1788, 1817, 1978, +1787, 1817, 1979, +1787, 1817, 1980, +1787, 1817, 1981, +1788, 1817, 1982, +1789, 1817, 1983, +1790, 1817, 1986, +1791, 1817, 1988, +1793, 1817, 1992, +1789, 1817, 1998, +1782, 1817, 2007, +1773, 1818, 2018, +1754, 1823, 2036, +1735, 1818, 2051, +1730, 1803, 2080, +1689, 1816, 2124, +1707, 1808, 2166, +1658, 1793, 2234, +1668, 1793, 2304, +1756, 1797, 2389, +1874, 1789, 2475, +1965, 1800, 2514, +1965, 1800, 2514, +1965, 1800, 2514, +1965, 1800, 2514, +1965, 1800, 2514, +1965, 1800, 2514, +1965, 1800, 2514, +1965, 1800, 2514, +1965, 1800, 2514, +1965, 1800, 2514, +1959, 1958, 2029, +1959, 1958, 2029, +1958, 1958, 2030, +1958, 1958, 2030, +1958, 1958, 2031, +1957, 1958, 2032, +1957, 1958, 2033, +1956, 1958, 2035, +1955, 1958, 2037, +1954, 1958, 2041, +1952, 1958, 2045, +1950, 1958, 2051, +1946, 1958, 2058, +1942, 1962, 2068, +1936, 1967, 2081, +1928, 1969, 2114, +1915, 1966, 2154, +1905, 1962, 2189, +1920, 1968, 2243, +1883, 1968, 2320, +1930, 1954, 2392, +2035, 1964, 2481, +2095, 1968, 2516, +2095, 1968, 2516, +2095, 1968, 2516, +2095, 1968, 2516, +2095, 1968, 2516, +2095, 1968, 2516, +2095, 1968, 2516, +2095, 1968, 2516, +2095, 1968, 2516, +2095, 1968, 2516, +2120, 2120, 2068, +2120, 2120, 2068, +2120, 2120, 2068, +2120, 2120, 2069, +2120, 2120, 2069, +2120, 2120, 2070, +2120, 2120, 2071, +2120, 2121, 2073, +2120, 2122, 2075, +2120, 2122, 2078, +2120, 2124, 2082, +2120, 2125, 2088, +2119, 2127, 2095, +2119, 2127, 2101, +2119, 2127, 2110, +2116, 2131, 2132, +2110, 2133, 2165, +2104, 2131, 2206, +2111, 2134, 2256, +2120, 2135, 2316, +2148, 2131, 2395, +2212, 2147, 2485, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2370, 2355, 2124, +2370, 2355, 2124, +2370, 2355, 2124, +2370, 2355, 2125, +2370, 2355, 2125, +2370, 2356, 2126, +2369, 2356, 2126, +2369, 2356, 2127, +2369, 2357, 2129, +2368, 2357, 2131, +2368, 2358, 2133, +2368, 2359, 2137, +2369, 2360, 2143, +2370, 2358, 2146, +2369, 2356, 2148, +2369, 2358, 2163, +2371, 2358, 2193, +2369, 2358, 2226, +2372, 2355, 2273, +2384, 2357, 2337, +2410, 2367, 2405, +2467, 2385, 2498, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2681, 2655, 1963, +2681, 2655, 1963, +2681, 2655, 1964, +2681, 2655, 1965, +2681, 2655, 1966, +2681, 2655, 1967, +2681, 2655, 1968, +2681, 2655, 1969, +2681, 2654, 1968, +2681, 2654, 1967, +2680, 2654, 1965, +2680, 2653, 1963, +2679, 2653, 1963, +2678, 2654, 1973, +2677, 2655, 1994, +2676, 2653, 2016, +2675, 2650, 2036, +2677, 2655, 2123, +2681, 2656, 2208, +2687, 2661, 2306, +2695, 2666, 2409, +2715, 2678, 2527, +2723, 2684, 2575, +2723, 2684, 2575, +2723, 2684, 2575, +2723, 2684, 2575, +2723, 2684, 2575, +2723, 2684, 2575, +2723, 2684, 2575, +2723, 2684, 2575, +2723, 2684, 2575, +2723, 2684, 2575, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2456, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2456, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2456, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2456, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2456, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2456, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2456, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2456, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2456, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2456, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +58, 0, 0, +58, 0, 0, +58, 0, 0, +58, 0, 0, +58, 0, 28, +58, 0, 152, +58, 0, 280, +58, 0, 408, +58, 0, 537, +58, 0, 667, +58, 0, 797, +58, 0, 928, +0, 0, 1088, +0, 0, 1305, +0, 0, 1481, +28, 0, 1634, +564, 0, 1774, +1165, 0, 1884, +1561, 0, 2007, +1555, 0, 2157, +407, 987, 2341, +1245, 605, 2470, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +41, 0, 0, +50, 0, 0, +50, 0, 0, +50, 0, 0, +50, 0, 36, +50, 0, 159, +50, 0, 285, +50, 0, 412, +50, 0, 540, +50, 0, 669, +50, 0, 799, +50, 0, 930, +0, 0, 1089, +0, 0, 1306, +0, 0, 1482, +36, 0, 1635, +550, 0, 1774, +1164, 0, 1884, +1561, 0, 2008, +1554, 0, 2157, +407, 992, 2341, +1249, 608, 2470, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +17, 0, 0, +26, 0, 0, +38, 0, 0, +38, 0, 0, +38, 0, 48, +38, 0, 168, +38, 0, 291, +38, 0, 417, +38, 0, 544, +38, 0, 672, +38, 0, 801, +38, 0, 931, +0, 0, 1090, +0, 0, 1307, +0, 0, 1482, +48, 0, 1635, +530, 0, 1773, +1163, 0, 1884, +1560, 0, 2008, +1552, 0, 2157, +407, 998, 2341, +1254, 611, 2470, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +0, 0, 0, +0, 0, 0, +6, 0, 0, +22, 0, 0, +22, 0, 63, +22, 0, 180, +22, 0, 300, +22, 0, 424, +22, 0, 549, +22, 0, 676, +22, 0, 804, +22, 0, 933, +0, 0, 1091, +0, 0, 1308, +0, 0, 1483, +63, 0, 1636, +502, 0, 1773, +1162, 0, 1885, +1560, 0, 2009, +1550, 0, 2158, +407, 1005, 2342, +1262, 615, 2470, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 83, +0, 0, 195, +0, 0, 312, +0, 0, 433, +0, 0, 556, +0, 0, 681, +0, 0, 808, +0, 0, 936, +0, 0, 1093, +0, 0, 1309, +0, 0, 1484, +83, 0, 1637, +462, 0, 1772, +1160, 0, 1885, +1559, 0, 2010, +1547, 0, 2158, +407, 1015, 2342, +1272, 621, 2470, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +1732, 0, 2503, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 83, +0, 0, 251, +0, 0, 356, +0, 0, 467, +0, 0, 582, +0, 0, 701, +0, 0, 823, +0, 0, 948, +0, 0, 1102, +0, 30, 1314, +0, 30, 1487, +83, 0, 1639, +483, 0, 1774, +1157, 0, 1887, +1552, 0, 2012, +1536, 154, 2160, +394, 1028, 2343, +1285, 621, 2470, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +0, 4, 0, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 83, +0, 3, 251, +0, 78, 409, +0, 78, 509, +0, 78, 615, +0, 78, 727, +0, 78, 843, +0, 78, 963, +0, 137, 1112, +0, 163, 1321, +0, 163, 1492, +83, 94, 1641, +511, 0, 1777, +1154, 0, 1889, +1542, 32, 2015, +1522, 302, 2163, +376, 1045, 2344, +1302, 621, 2470, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +0, 144, 0, +0, 137, 0, +0, 127, 0, +0, 114, 0, +0, 96, 83, +0, 143, 251, +0, 199, 409, +0, 265, 559, +0, 265, 655, +0, 265, 759, +0, 265, 868, +0, 265, 982, +0, 305, 1126, +0, 295, 1330, +0, 295, 1498, +83, 244, 1644, +545, 15, 1780, +1150, 0, 1891, +1529, 164, 2018, +1502, 446, 2167, +352, 1066, 2345, +1323, 621, 2470, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +0, 281, 0, +0, 276, 0, +0, 269, 0, +0, 259, 0, +0, 246, 83, +0, 280, 251, +0, 322, 409, +0, 373, 559, +0, 434, 705, +0, 434, 798, +0, 434, 899, +0, 434, 1007, +0, 462, 1144, +0, 426, 1341, +0, 426, 1506, +83, 390, 1648, +587, 190, 1784, +1144, 111, 1895, +1511, 296, 2022, +1474, 586, 2172, +317, 1093, 2347, +1361, 639, 2470, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +0, 417, 0, +0, 413, 0, +0, 408, 0, +0, 401, 0, +0, 391, 83, +0, 416, 251, +0, 448, 409, +0, 487, 559, +0, 535, 705, +0, 591, 846, +0, 591, 938, +0, 591, 1038, +0, 611, 1167, +0, 570, 1357, +0, 559, 1517, +83, 531, 1653, +591, 391, 1789, +1136, 244, 1899, +1486, 428, 2028, +1434, 725, 2178, +265, 1128, 2349, +1407, 662, 2470, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +0, 552, 0, +0, 549, 0, +0, 545, 0, +0, 540, 0, +0, 533, 83, +0, 551, 251, +0, 575, 409, +0, 605, 559, +0, 642, 705, +0, 688, 846, +0, 742, 985, +0, 742, 1076, +0, 756, 1197, +0, 726, 1376, +0, 691, 1531, +83, 670, 1662, +591, 572, 1794, +1152, 422, 1905, +1450, 560, 2036, +1374, 862, 2187, +186, 1169, 2352, +1464, 691, 2470, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +0, 686, 0, +0, 684, 0, +0, 681, 0, +0, 677, 0, +0, 672, 83, +0, 686, 251, +0, 703, 409, +0, 726, 559, +0, 755, 705, +0, 791, 846, +0, 835, 985, +0, 887, 1123, +0, 898, 1233, +0, 876, 1401, +0, 823, 1548, +83, 808, 1675, +591, 737, 1800, +1179, 593, 1913, +1396, 692, 2046, +1279, 997, 2199, +0, 1212, 2357, +1529, 728, 2470, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +0, 854, 85, +0, 854, 130, +0, 852, 185, +0, 850, 248, +0, 846, 322, +0, 855, 429, +0, 868, 541, +0, 884, 658, +0, 904, 778, +0, 930, 901, +0, 963, 1027, +0, 1003, 1154, +69, 1044, 1282, +0, 1029, 1435, +0, 983, 1573, +141, 963, 1697, +601, 928, 1815, +1197, 800, 1927, +1320, 849, 2058, +1133, 1133, 2212, +0, 1254, 2365, +1592, 800, 2470, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +136, 1175, 1014, +107, 1175, 1020, +65, 1175, 1028, +1, 1175, 1038, +0, 1175, 1052, +0, 1175, 1064, +0, 1175, 1080, +0, 1175, 1099, +0, 1175, 1125, +0, 1180, 1168, +0, 1200, 1242, +0, 1224, 1325, +21, 1250, 1417, +153, 1233, 1497, +153, 1204, 1620, +214, 1214, 1743, +666, 1191, 1855, +1071, 1137, 1962, +1243, 1131, 2080, +1031, 1271, 2226, +622, 1305, 2371, +1594, 1025, 2471, +1769, 1134, 2512, +1769, 1134, 2512, +1769, 1134, 2512, +1769, 1134, 2512, +1769, 1134, 2512, +1769, 1134, 2512, +1769, 1134, 2512, +1769, 1134, 2512, +1769, 1134, 2512, +1769, 1134, 2512, +136, 1416, 1371, +107, 1416, 1374, +65, 1416, 1378, +1, 1416, 1383, +0, 1416, 1389, +0, 1416, 1395, +0, 1416, 1402, +0, 1416, 1412, +0, 1416, 1425, +0, 1416, 1442, +0, 1416, 1463, +0, 1416, 1491, +21, 1427, 1546, +153, 1415, 1608, +153, 1396, 1676, +214, 1407, 1788, +666, 1407, 1897, +1078, 1356, 2001, +1151, 1350, 2109, +878, 1405, 2241, +770, 1382, 2378, +1607, 1205, 2473, +1802, 1306, 2510, +1802, 1306, 2510, +1802, 1306, 2510, +1802, 1306, 2510, +1802, 1306, 2510, +1802, 1306, 2510, +1802, 1306, 2510, +1802, 1306, 2510, +1802, 1306, 2510, +1802, 1306, 2510, +973, 1576, 1651, +973, 1576, 1652, +971, 1577, 1653, +969, 1577, 1654, +966, 1578, 1656, +966, 1577, 1659, +966, 1576, 1664, +966, 1574, 1669, +966, 1572, 1677, +966, 1569, 1686, +966, 1567, 1699, +966, 1567, 1716, +948, 1567, 1737, +920, 1575, 1786, +920, 1568, 1836, +932, 1552, 1890, +876, 1557, 1972, +968, 1536, 2066, +965, 1537, 2170, +810, 1526, 2268, +1145, 1498, 2382, +1680, 1435, 2473, +1844, 1469, 2509, +1844, 1469, 2509, +1844, 1469, 2509, +1844, 1469, 2509, +1844, 1469, 2509, +1844, 1469, 2509, +1844, 1469, 2509, +1844, 1469, 2509, +1844, 1469, 2509, +1844, 1469, 2509, +1457, 1704, 1855, +1456, 1704, 1856, +1454, 1705, 1857, +1452, 1705, 1858, +1449, 1705, 1860, +1446, 1705, 1862, +1443, 1705, 1865, +1438, 1705, 1868, +1432, 1705, 1873, +1431, 1703, 1880, +1431, 1700, 1888, +1431, 1696, 1899, +1428, 1691, 1913, +1405, 1685, 1932, +1405, 1696, 1977, +1373, 1700, 2021, +1378, 1686, 2063, +1214, 1672, 2128, +1142, 1679, 2221, +1192, 1647, 2295, +1522, 1633, 2386, +1779, 1634, 2475, +1895, 1627, 2511, +1895, 1627, 2511, +1895, 1627, 2511, +1895, 1627, 2511, +1895, 1627, 2511, +1895, 1627, 2511, +1895, 1627, 2511, +1895, 1627, 2511, +1895, 1627, 2511, +1895, 1627, 2511, +1790, 1816, 1977, +1790, 1816, 1978, +1789, 1816, 1978, +1789, 1816, 1979, +1788, 1816, 1981, +1788, 1816, 1982, +1789, 1816, 1983, +1790, 1816, 1986, +1792, 1816, 1988, +1793, 1816, 1992, +1790, 1816, 1998, +1783, 1816, 2007, +1773, 1817, 2018, +1755, 1823, 2036, +1736, 1817, 2051, +1731, 1804, 2079, +1691, 1816, 2124, +1708, 1807, 2166, +1659, 1793, 2234, +1670, 1794, 2305, +1757, 1797, 2389, +1873, 1789, 2475, +1966, 1800, 2514, +1966, 1800, 2514, +1966, 1800, 2514, +1966, 1800, 2514, +1966, 1800, 2514, +1966, 1800, 2514, +1966, 1800, 2514, +1966, 1800, 2514, +1966, 1800, 2514, +1966, 1800, 2514, +1960, 1958, 2029, +1960, 1958, 2029, +1959, 1958, 2030, +1959, 1958, 2030, +1958, 1958, 2031, +1958, 1958, 2032, +1957, 1958, 2034, +1956, 1958, 2035, +1956, 1958, 2038, +1954, 1958, 2041, +1952, 1958, 2046, +1950, 1958, 2051, +1947, 1958, 2059, +1942, 1961, 2068, +1936, 1967, 2081, +1928, 1969, 2113, +1916, 1966, 2154, +1905, 1962, 2189, +1920, 1968, 2242, +1884, 1968, 2319, +1930, 1954, 2392, +2036, 1964, 2481, +2096, 1968, 2516, +2096, 1968, 2516, +2096, 1968, 2516, +2096, 1968, 2516, +2096, 1968, 2516, +2096, 1968, 2516, +2096, 1968, 2516, +2096, 1968, 2516, +2096, 1968, 2516, +2096, 1968, 2516, +2120, 2120, 2068, +2120, 2120, 2068, +2120, 2120, 2069, +2120, 2120, 2069, +2121, 2120, 2069, +2121, 2120, 2070, +2121, 2120, 2071, +2121, 2121, 2073, +2121, 2122, 2075, +2121, 2122, 2078, +2121, 2124, 2082, +2121, 2125, 2087, +2120, 2127, 2094, +2119, 2127, 2101, +2119, 2127, 2110, +2116, 2131, 2132, +2110, 2134, 2165, +2104, 2130, 2206, +2111, 2134, 2256, +2120, 2134, 2316, +2148, 2131, 2395, +2213, 2146, 2485, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2370, 2355, 2124, +2370, 2355, 2124, +2370, 2355, 2124, +2370, 2355, 2125, +2370, 2355, 2125, +2370, 2355, 2126, +2370, 2356, 2126, +2369, 2356, 2127, +2369, 2356, 2129, +2369, 2357, 2131, +2368, 2357, 2133, +2368, 2359, 2137, +2369, 2360, 2143, +2370, 2358, 2146, +2369, 2356, 2148, +2369, 2358, 2162, +2371, 2358, 2193, +2370, 2358, 2226, +2372, 2356, 2273, +2384, 2357, 2337, +2410, 2367, 2406, +2466, 2384, 2498, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2681, 2655, 1963, +2681, 2655, 1963, +2681, 2655, 1964, +2681, 2655, 1965, +2681, 2655, 1967, +2681, 2655, 1968, +2681, 2655, 1969, +2681, 2655, 1970, +2681, 2655, 1969, +2681, 2654, 1968, +2680, 2654, 1966, +2680, 2653, 1964, +2679, 2653, 1964, +2678, 2654, 1975, +2677, 2655, 1997, +2676, 2654, 2018, +2675, 2650, 2038, +2677, 2655, 2123, +2681, 2656, 2208, +2687, 2661, 2306, +2695, 2666, 2409, +2715, 2678, 2527, +2723, 2684, 2575, +2723, 2684, 2575, +2723, 2684, 2575, +2723, 2684, 2575, +2723, 2684, 2575, +2723, 2684, 2575, +2723, 2684, 2575, +2723, 2684, 2575, +2723, 2684, 2575, +2723, 2684, 2575, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2456, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2456, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2456, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2456, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2456, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2456, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2456, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2456, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2456, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2456, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +197, 0, 0, +197, 0, 0, +197, 0, 0, +197, 0, 0, +197, 0, 28, +197, 0, 152, +197, 0, 280, +197, 0, 408, +197, 0, 537, +197, 0, 667, +197, 0, 797, +197, 0, 928, +71, 0, 1088, +0, 0, 1312, +0, 0, 1486, +152, 0, 1634, +638, 0, 1775, +1174, 0, 1884, +1561, 0, 2008, +1552, 0, 2159, +394, 987, 2341, +1252, 597, 2470, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +184, 0, 0, +190, 0, 0, +190, 0, 0, +190, 0, 0, +190, 0, 36, +190, 0, 159, +190, 0, 285, +190, 0, 412, +190, 0, 540, +190, 0, 669, +190, 0, 799, +190, 0, 930, +46, 0, 1089, +0, 0, 1313, +0, 0, 1486, +159, 0, 1635, +626, 0, 1775, +1173, 0, 1885, +1561, 0, 2008, +1551, 0, 2159, +394, 992, 2341, +1257, 599, 2470, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +167, 0, 0, +173, 0, 0, +182, 0, 0, +182, 0, 0, +182, 0, 48, +182, 0, 168, +182, 0, 291, +182, 0, 417, +182, 0, 544, +182, 0, 672, +182, 0, 801, +182, 0, 931, +35, 0, 1090, +0, 0, 1313, +0, 0, 1487, +168, 0, 1635, +609, 0, 1775, +1172, 0, 1885, +1560, 0, 2009, +1549, 0, 2159, +394, 998, 2341, +1262, 603, 2470, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +142, 0, 0, +149, 0, 0, +158, 0, 0, +170, 0, 0, +170, 0, 63, +170, 0, 180, +170, 0, 300, +170, 0, 424, +170, 0, 549, +170, 0, 676, +170, 0, 804, +170, 0, 933, +19, 0, 1091, +0, 0, 1315, +0, 0, 1487, +180, 0, 1636, +586, 0, 1774, +1171, 0, 1886, +1560, 0, 2010, +1547, 0, 2159, +394, 1005, 2342, +1270, 608, 2470, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +1734, 0, 2503, +107, 0, 0, +115, 0, 0, +125, 0, 0, +138, 0, 0, +154, 0, 83, +154, 0, 195, +154, 0, 312, +154, 0, 433, +154, 0, 556, +154, 0, 681, +154, 0, 808, +154, 0, 936, +0, 0, 1093, +0, 0, 1316, +0, 0, 1489, +195, 0, 1637, +552, 0, 1774, +1169, 0, 1886, +1559, 0, 2011, +1544, 57, 2160, +394, 1015, 2342, +1279, 613, 2470, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +1733, 0, 2503, +56, 0, 0, +65, 0, 0, +76, 0, 0, +90, 0, 0, +108, 0, 83, +132, 0, 215, +132, 0, 327, +132, 0, 444, +132, 0, 564, +132, 0, 688, +132, 0, 813, +132, 0, 940, +0, 0, 1096, +0, 30, 1317, +0, 30, 1490, +215, 0, 1639, +504, 0, 1773, +1167, 0, 1887, +1558, 0, 2012, +1540, 132, 2160, +394, 1028, 2343, +1292, 621, 2470, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +1732, 30, 2504, +56, 4, 0, +65, 0, 0, +76, 0, 0, +90, 0, 0, +108, 0, 83, +132, 0, 215, +132, 0, 383, +132, 0, 488, +132, 0, 599, +132, 0, 714, +132, 0, 833, +132, 0, 955, +0, 64, 1107, +0, 163, 1324, +0, 163, 1494, +215, 68, 1641, +530, 0, 1776, +1164, 0, 1889, +1548, 32, 2015, +1525, 286, 2163, +376, 1045, 2344, +1308, 621, 2470, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +56, 144, 0, +65, 137, 0, +76, 127, 0, +90, 114, 0, +108, 96, 83, +132, 70, 215, +132, 135, 383, +132, 210, 541, +132, 210, 641, +132, 210, 747, +132, 210, 859, +132, 210, 975, +0, 255, 1121, +0, 295, 1333, +0, 295, 1500, +215, 226, 1644, +563, 0, 1779, +1159, 0, 1892, +1536, 164, 2018, +1506, 434, 2167, +352, 1066, 2345, +1329, 621, 2470, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +56, 281, 0, +65, 276, 0, +76, 269, 0, +90, 259, 0, +108, 246, 83, +132, 227, 215, +132, 275, 383, +132, 331, 541, +132, 397, 691, +132, 397, 787, +132, 397, 891, +132, 397, 1000, +0, 427, 1139, +0, 426, 1344, +0, 426, 1508, +215, 376, 1648, +604, 147, 1783, +1154, 111, 1895, +1518, 296, 2022, +1478, 578, 2172, +317, 1093, 2347, +1367, 639, 2470, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +56, 417, 0, +65, 413, 0, +76, 408, 0, +90, 401, 0, +108, 391, 83, +132, 378, 215, +132, 412, 383, +132, 455, 541, +132, 505, 691, +132, 566, 837, +132, 566, 930, +132, 566, 1032, +0, 587, 1163, +0, 570, 1359, +0, 559, 1519, +215, 522, 1653, +607, 365, 1787, +1146, 244, 1900, +1493, 428, 2028, +1438, 719, 2178, +265, 1128, 2349, +1413, 662, 2470, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +56, 552, 0, +65, 549, 0, +76, 545, 0, +90, 540, 0, +108, 533, 83, +132, 523, 215, +132, 548, 383, +132, 580, 541, +132, 619, 691, +132, 667, 837, +132, 723, 978, +132, 723, 1071, +0, 738, 1192, +0, 726, 1379, +0, 691, 1532, +215, 663, 1662, +607, 554, 1792, +1162, 422, 1905, +1457, 560, 2036, +1379, 857, 2187, +186, 1169, 2352, +1468, 691, 2470, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +56, 686, 0, +65, 684, 0, +76, 681, 0, +90, 677, 0, +108, 672, 83, +132, 665, 215, +132, 684, 383, +132, 708, 541, +132, 737, 691, +132, 774, 837, +132, 820, 978, +132, 874, 1118, +0, 885, 1229, +0, 876, 1403, +0, 823, 1550, +215, 803, 1675, +607, 725, 1799, +1188, 593, 1913, +1404, 692, 2046, +1285, 994, 2199, +0, 1212, 2357, +1533, 728, 2470, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +63, 854, 85, +31, 854, 130, +43, 852, 185, +58, 850, 248, +78, 846, 322, +103, 841, 404, +103, 854, 522, +103, 870, 643, +103, 892, 767, +103, 918, 893, +103, 952, 1020, +103, 993, 1149, +185, 1035, 1278, +0, 1029, 1438, +0, 983, 1575, +259, 959, 1697, +617, 920, 1814, +1206, 800, 1927, +1329, 849, 2058, +1141, 1131, 2212, +0, 1254, 2365, +1596, 800, 2470, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +289, 1170, 1007, +268, 1170, 1013, +239, 1170, 1021, +196, 1170, 1032, +132, 1170, 1046, +30, 1170, 1064, +30, 1170, 1080, +30, 1170, 1099, +30, 1170, 1125, +30, 1176, 1168, +30, 1195, 1242, +30, 1220, 1325, +125, 1246, 1417, +285, 1231, 1499, +285, 1202, 1622, +345, 1210, 1744, +680, 1193, 1856, +1086, 1139, 1963, +1243, 1131, 2080, +1031, 1271, 2226, +681, 1302, 2370, +1597, 1022, 2471, +1771, 1129, 2512, +1771, 1129, 2512, +1771, 1129, 2512, +1771, 1129, 2512, +1771, 1129, 2512, +1771, 1129, 2512, +1771, 1129, 2512, +1771, 1129, 2512, +1771, 1129, 2512, +1771, 1129, 2512, +289, 1413, 1368, +268, 1413, 1371, +239, 1413, 1375, +196, 1413, 1380, +132, 1413, 1386, +30, 1413, 1395, +30, 1413, 1402, +30, 1413, 1412, +30, 1413, 1425, +30, 1413, 1442, +30, 1413, 1463, +30, 1413, 1491, +125, 1424, 1546, +285, 1414, 1610, +285, 1395, 1677, +345, 1404, 1789, +680, 1408, 1897, +1092, 1358, 2001, +1151, 1350, 2109, +878, 1405, 2241, +813, 1379, 2377, +1609, 1202, 2473, +1804, 1303, 2510, +1804, 1303, 2510, +1804, 1303, 2510, +1804, 1303, 2510, +1804, 1303, 2510, +1804, 1303, 2510, +1804, 1303, 2510, +1804, 1303, 2510, +1804, 1303, 2510, +1804, 1303, 2510, +1005, 1574, 1653, +1004, 1574, 1654, +1003, 1575, 1655, +1001, 1575, 1656, +998, 1576, 1658, +995, 1577, 1660, +995, 1576, 1664, +995, 1574, 1670, +995, 1572, 1678, +995, 1569, 1687, +995, 1567, 1700, +995, 1567, 1716, +977, 1567, 1738, +937, 1574, 1785, +937, 1567, 1835, +952, 1552, 1890, +906, 1557, 1973, +989, 1536, 2066, +976, 1537, 2170, +810, 1527, 2268, +1155, 1497, 2382, +1680, 1435, 2473, +1844, 1468, 2509, +1844, 1468, 2509, +1844, 1468, 2509, +1844, 1468, 2509, +1844, 1468, 2509, +1844, 1468, 2509, +1844, 1468, 2509, +1844, 1468, 2509, +1844, 1468, 2509, +1844, 1468, 2509, +1461, 1703, 1854, +1459, 1704, 1855, +1458, 1704, 1856, +1456, 1704, 1858, +1453, 1705, 1859, +1449, 1705, 1862, +1446, 1705, 1865, +1441, 1705, 1868, +1435, 1705, 1873, +1434, 1703, 1880, +1434, 1700, 1888, +1434, 1696, 1899, +1431, 1691, 1913, +1408, 1685, 1932, +1408, 1696, 1977, +1375, 1699, 2021, +1380, 1687, 2064, +1224, 1672, 2127, +1149, 1680, 2221, +1200, 1647, 2295, +1523, 1633, 2386, +1781, 1634, 2475, +1896, 1626, 2511, +1896, 1626, 2511, +1896, 1626, 2511, +1896, 1626, 2511, +1896, 1626, 2511, +1896, 1626, 2511, +1896, 1626, 2511, +1896, 1626, 2511, +1896, 1626, 2511, +1896, 1626, 2511, +1793, 1816, 1977, +1792, 1816, 1977, +1792, 1816, 1978, +1791, 1816, 1979, +1790, 1816, 1980, +1789, 1816, 1982, +1790, 1816, 1983, +1791, 1816, 1986, +1792, 1816, 1988, +1794, 1816, 1992, +1790, 1816, 1998, +1783, 1816, 2007, +1774, 1817, 2018, +1756, 1822, 2035, +1737, 1817, 2051, +1733, 1804, 2079, +1694, 1816, 2124, +1710, 1807, 2166, +1660, 1793, 2234, +1673, 1795, 2305, +1759, 1797, 2389, +1873, 1788, 2475, +1968, 1800, 2514, +1968, 1800, 2514, +1968, 1800, 2514, +1968, 1800, 2514, +1968, 1800, 2514, +1968, 1800, 2514, +1968, 1800, 2514, +1968, 1800, 2514, +1968, 1800, 2514, +1968, 1800, 2514, +1961, 1958, 2029, +1961, 1958, 2030, +1961, 1958, 2030, +1960, 1958, 2031, +1959, 1958, 2031, +1959, 1958, 2032, +1958, 1958, 2034, +1958, 1958, 2036, +1956, 1958, 2038, +1955, 1958, 2042, +1953, 1958, 2046, +1951, 1958, 2052, +1948, 1958, 2059, +1943, 1961, 2068, +1937, 1966, 2081, +1930, 1968, 2112, +1918, 1966, 2154, +1905, 1962, 2189, +1920, 1968, 2242, +1885, 1967, 2319, +1930, 1954, 2392, +2038, 1964, 2481, +2097, 1968, 2516, +2097, 1968, 2516, +2097, 1968, 2516, +2097, 1968, 2516, +2097, 1968, 2516, +2097, 1968, 2516, +2097, 1968, 2516, +2097, 1968, 2516, +2097, 1968, 2516, +2097, 1968, 2516, +2120, 2120, 2069, +2120, 2120, 2069, +2121, 2120, 2069, +2121, 2120, 2069, +2121, 2120, 2069, +2121, 2120, 2069, +2121, 2120, 2071, +2121, 2121, 2073, +2121, 2122, 2075, +2121, 2122, 2078, +2121, 2124, 2082, +2121, 2125, 2087, +2120, 2127, 2094, +2119, 2127, 2101, +2119, 2127, 2110, +2117, 2131, 2132, +2111, 2134, 2166, +2105, 2130, 2206, +2111, 2134, 2255, +2121, 2134, 2316, +2148, 2131, 2396, +2213, 2146, 2485, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2370, 2355, 2124, +2370, 2355, 2124, +2370, 2355, 2124, +2370, 2355, 2125, +2370, 2355, 2125, +2370, 2355, 2126, +2370, 2355, 2126, +2370, 2356, 2127, +2369, 2356, 2129, +2369, 2357, 2131, +2368, 2357, 2133, +2369, 2358, 2137, +2369, 2359, 2143, +2370, 2358, 2146, +2369, 2356, 2148, +2369, 2358, 2162, +2371, 2358, 2193, +2370, 2358, 2226, +2373, 2356, 2273, +2385, 2357, 2337, +2411, 2367, 2406, +2466, 2384, 2498, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2681, 2655, 1963, +2681, 2655, 1963, +2681, 2655, 1964, +2681, 2655, 1965, +2681, 2655, 1967, +2681, 2655, 1969, +2681, 2655, 1970, +2681, 2655, 1971, +2681, 2655, 1970, +2681, 2655, 1969, +2680, 2654, 1968, +2680, 2654, 1965, +2679, 2653, 1966, +2679, 2654, 1979, +2677, 2655, 2000, +2676, 2654, 2020, +2675, 2650, 2041, +2677, 2655, 2122, +2681, 2656, 2208, +2688, 2661, 2306, +2695, 2666, 2408, +2715, 2678, 2527, +2723, 2684, 2575, +2723, 2684, 2575, +2723, 2684, 2575, +2723, 2684, 2575, +2723, 2684, 2575, +2723, 2684, 2575, +2723, 2684, 2575, +2723, 2684, 2575, +2723, 2684, 2575, +2723, 2684, 2575, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2457, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2784, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2457, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2784, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2457, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2784, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2457, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2784, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2457, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2784, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2457, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2784, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2457, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2784, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2457, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2784, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2457, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2784, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2457, +2710, 2773, 2483, +2714, 2774, 2520, +2714, 2773, 2553, +2717, 2777, 2616, +2722, 2784, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +333, 0, 0, +333, 0, 0, +333, 0, 0, +333, 0, 0, +333, 0, 28, +333, 0, 152, +333, 0, 280, +333, 0, 408, +333, 0, 537, +333, 0, 667, +333, 0, 797, +333, 0, 928, +244, 0, 1088, +0, 0, 1321, +0, 0, 1492, +280, 0, 1634, +721, 0, 1777, +1186, 0, 1886, +1561, 0, 2009, +1548, 0, 2161, +376, 987, 2341, +1263, 586, 2469, +1736, 0, 2503, +1736, 0, 2503, +1736, 0, 2503, +1736, 0, 2503, +1736, 0, 2503, +1736, 0, 2503, +1736, 0, 2503, +1736, 0, 2503, +1736, 0, 2503, +1736, 0, 2503, +324, 0, 0, +329, 0, 0, +329, 0, 0, +329, 0, 0, +329, 0, 36, +329, 0, 159, +329, 0, 285, +329, 0, 412, +329, 0, 540, +329, 0, 669, +329, 0, 799, +329, 0, 930, +227, 0, 1089, +0, 0, 1322, +0, 0, 1493, +285, 0, 1635, +711, 0, 1776, +1185, 0, 1886, +1561, 0, 2009, +1547, 0, 2161, +376, 992, 2341, +1267, 588, 2469, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +311, 0, 0, +316, 0, 0, +322, 0, 0, +322, 0, 0, +322, 0, 48, +322, 0, 168, +322, 0, 291, +322, 0, 417, +322, 0, 544, +322, 0, 672, +322, 0, 801, +322, 0, 931, +219, 0, 1090, +0, 0, 1323, +0, 0, 1493, +291, 0, 1635, +697, 0, 1776, +1184, 0, 1886, +1560, 0, 2010, +1545, 22, 2161, +376, 998, 2341, +1272, 592, 2469, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +294, 0, 0, +299, 0, 0, +305, 0, 0, +314, 0, 0, +314, 0, 63, +314, 0, 180, +314, 0, 300, +314, 0, 424, +314, 0, 549, +314, 0, 676, +314, 0, 804, +314, 0, 933, +209, 0, 1091, +0, 0, 1323, +0, 0, 1494, +300, 0, 1636, +678, 0, 1776, +1183, 0, 1887, +1560, 0, 2011, +1543, 69, 2161, +376, 1005, 2342, +1280, 596, 2469, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +1735, 0, 2503, +269, 0, 0, +274, 0, 0, +281, 0, 0, +290, 0, 0, +302, 0, 83, +302, 0, 195, +302, 0, 312, +302, 0, 433, +302, 0, 556, +302, 0, 681, +302, 0, 808, +302, 0, 936, +194, 0, 1093, +0, 0, 1325, +0, 0, 1495, +312, 0, 1637, +651, 0, 1776, +1181, 0, 1887, +1559, 0, 2012, +1540, 124, 2162, +376, 1015, 2342, +1289, 603, 2469, +1734, 0, 2504, +1734, 0, 2504, +1734, 0, 2504, +1734, 0, 2504, +1734, 0, 2504, +1734, 0, 2504, +1734, 0, 2504, +1734, 0, 2504, +1734, 0, 2504, +1734, 0, 2504, +234, 0, 0, +239, 0, 0, +247, 0, 0, +257, 0, 0, +270, 0, 83, +286, 0, 215, +286, 0, 327, +286, 0, 444, +286, 0, 564, +286, 0, 688, +286, 0, 813, +286, 0, 940, +173, 0, 1096, +0, 30, 1326, +0, 30, 1496, +327, 0, 1639, +613, 0, 1775, +1179, 0, 1888, +1558, 0, 2013, +1535, 189, 2162, +376, 1028, 2343, +1301, 611, 2469, +1733, 30, 2504, +1733, 30, 2504, +1733, 30, 2504, +1733, 30, 2504, +1733, 30, 2504, +1733, 30, 2504, +1733, 30, 2504, +1733, 30, 2504, +1733, 30, 2504, +1733, 30, 2504, +182, 4, 0, +188, 0, 0, +197, 0, 0, +208, 0, 0, +222, 0, 83, +241, 0, 215, +264, 0, 347, +264, 0, 459, +264, 0, 576, +264, 0, 697, +264, 0, 820, +264, 0, 946, +145, 0, 1100, +0, 163, 1329, +0, 163, 1497, +347, 32, 1641, +555, 0, 1774, +1176, 0, 1890, +1557, 32, 2015, +1530, 264, 2163, +376, 1045, 2344, +1318, 621, 2469, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +1732, 163, 2504, +182, 144, 0, +188, 137, 0, +197, 127, 0, +208, 114, 0, +222, 96, 83, +241, 70, 215, +264, 34, 347, +264, 126, 516, +264, 126, 620, +264, 126, 731, +264, 126, 846, +264, 126, 966, +145, 179, 1114, +0, 295, 1337, +0, 295, 1503, +347, 201, 1644, +586, 0, 1777, +1172, 0, 1892, +1544, 164, 2019, +1510, 418, 2167, +352, 1066, 2345, +1338, 621, 2469, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +182, 281, 0, +188, 276, 0, +197, 269, 0, +208, 259, 0, +222, 246, 83, +241, 227, 215, +264, 202, 347, +264, 267, 516, +264, 342, 673, +264, 342, 773, +264, 342, 879, +264, 342, 991, +145, 376, 1133, +0, 426, 1349, +0, 426, 1511, +347, 358, 1648, +625, 84, 1782, +1166, 111, 1896, +1526, 296, 2023, +1483, 566, 2172, +317, 1093, 2347, +1375, 639, 2469, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +182, 417, 0, +188, 413, 0, +197, 408, 0, +208, 401, 0, +222, 391, 83, +241, 378, 215, +264, 360, 347, +264, 407, 516, +264, 463, 673, +264, 529, 824, +264, 529, 920, +264, 529, 1023, +145, 552, 1156, +0, 570, 1364, +0, 559, 1522, +347, 509, 1653, +628, 326, 1786, +1159, 244, 1900, +1502, 428, 2029, +1443, 710, 2178, +265, 1128, 2349, +1420, 662, 2469, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +182, 552, 0, +188, 549, 0, +197, 545, 0, +208, 540, 0, +222, 533, 83, +241, 523, 215, +264, 510, 347, +264, 544, 516, +264, 586, 673, +264, 637, 824, +264, 698, 969, +264, 698, 1063, +145, 714, 1186, +0, 726, 1383, +0, 691, 1535, +347, 654, 1662, +628, 529, 1791, +1174, 422, 1906, +1467, 560, 2036, +1385, 851, 2187, +186, 1169, 2352, +1475, 691, 2469, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +182, 686, 0, +188, 684, 0, +197, 681, 0, +208, 677, 0, +222, 672, 83, +241, 665, 215, +264, 655, 347, +264, 681, 516, +264, 712, 673, +264, 752, 824, +264, 799, 969, +264, 856, 1111, +145, 867, 1223, +0, 876, 1407, +0, 823, 1553, +347, 796, 1675, +628, 708, 1798, +1200, 593, 1914, +1415, 692, 2046, +1292, 989, 2199, +0, 1212, 2357, +1539, 728, 2469, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +187, 854, 85, +163, 854, 130, +172, 852, 185, +183, 850, 248, +198, 846, 322, +218, 841, 404, +243, 835, 496, +243, 852, 623, +243, 874, 752, +243, 902, 881, +243, 936, 1011, +243, 979, 1142, +304, 1023, 1273, +0, 1029, 1441, +0, 983, 1578, +380, 954, 1697, +638, 909, 1812, +1217, 800, 1928, +1343, 849, 2058, +1151, 1127, 2212, +0, 1254, 2365, +1600, 800, 2469, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +436, 1164, 998, +421, 1164, 1004, +400, 1164, 1013, +371, 1164, 1024, +328, 1164, 1038, +265, 1164, 1056, +163, 1164, 1080, +163, 1164, 1099, +163, 1164, 1125, +163, 1170, 1168, +163, 1189, 1242, +163, 1214, 1325, +235, 1241, 1417, +417, 1228, 1503, +417, 1199, 1624, +478, 1204, 1746, +698, 1196, 1857, +1104, 1142, 1964, +1243, 1131, 2079, +1031, 1271, 2226, +750, 1297, 2370, +1600, 1018, 2470, +1773, 1121, 2512, +1773, 1121, 2512, +1773, 1121, 2512, +1773, 1121, 2512, +1773, 1121, 2512, +1773, 1121, 2512, +1773, 1121, 2512, +1773, 1121, 2512, +1773, 1121, 2512, +1773, 1121, 2512, +436, 1410, 1364, +421, 1410, 1367, +400, 1410, 1371, +371, 1410, 1376, +328, 1410, 1382, +265, 1410, 1391, +163, 1410, 1402, +163, 1410, 1412, +163, 1410, 1425, +163, 1410, 1442, +163, 1410, 1463, +163, 1410, 1491, +235, 1421, 1546, +417, 1412, 1612, +417, 1393, 1679, +478, 1400, 1791, +698, 1410, 1897, +1111, 1360, 2002, +1151, 1350, 2108, +878, 1405, 2242, +865, 1375, 2377, +1613, 1200, 2472, +1806, 1298, 2510, +1806, 1298, 2510, +1806, 1298, 2510, +1806, 1298, 2510, +1806, 1298, 2510, +1806, 1298, 2510, +1806, 1298, 2510, +1806, 1298, 2510, +1806, 1298, 2510, +1806, 1298, 2510, +1044, 1572, 1655, +1043, 1572, 1656, +1042, 1572, 1657, +1040, 1573, 1658, +1038, 1573, 1660, +1034, 1574, 1662, +1030, 1576, 1666, +1030, 1574, 1671, +1030, 1572, 1679, +1030, 1569, 1688, +1030, 1567, 1701, +1030, 1567, 1717, +1014, 1567, 1739, +958, 1573, 1783, +958, 1565, 1833, +977, 1552, 1891, +944, 1557, 1974, +1016, 1536, 2066, +990, 1537, 2170, +810, 1528, 2268, +1168, 1496, 2382, +1680, 1435, 2473, +1843, 1466, 2509, +1843, 1466, 2509, +1843, 1466, 2509, +1843, 1466, 2509, +1843, 1466, 2509, +1843, 1466, 2509, +1843, 1466, 2509, +1843, 1466, 2509, +1843, 1466, 2509, +1843, 1466, 2509, +1466, 1702, 1854, +1464, 1703, 1855, +1463, 1703, 1855, +1461, 1703, 1857, +1458, 1704, 1859, +1454, 1705, 1862, +1449, 1705, 1865, +1444, 1705, 1868, +1438, 1705, 1873, +1438, 1703, 1880, +1438, 1700, 1888, +1438, 1696, 1899, +1434, 1691, 1913, +1412, 1685, 1932, +1412, 1696, 1978, +1377, 1698, 2020, +1384, 1688, 2065, +1238, 1672, 2127, +1159, 1681, 2221, +1212, 1647, 2296, +1524, 1635, 2386, +1783, 1634, 2474, +1897, 1625, 2511, +1897, 1625, 2511, +1897, 1625, 2511, +1897, 1625, 2511, +1897, 1625, 2511, +1897, 1625, 2511, +1897, 1625, 2511, +1897, 1625, 2511, +1897, 1625, 2511, +1897, 1625, 2511, +1796, 1815, 1977, +1795, 1815, 1977, +1795, 1815, 1978, +1794, 1815, 1978, +1793, 1815, 1980, +1792, 1815, 1981, +1790, 1815, 1983, +1792, 1815, 1986, +1793, 1815, 1988, +1795, 1815, 1992, +1791, 1815, 1998, +1784, 1815, 2007, +1775, 1816, 2018, +1758, 1821, 2035, +1739, 1816, 2051, +1736, 1805, 2078, +1698, 1816, 2124, +1712, 1806, 2166, +1661, 1793, 2234, +1677, 1795, 2305, +1762, 1797, 2390, +1872, 1787, 2475, +1969, 1800, 2514, +1969, 1800, 2514, +1969, 1800, 2514, +1969, 1800, 2514, +1969, 1800, 2514, +1969, 1800, 2514, +1969, 1800, 2514, +1969, 1800, 2514, +1969, 1800, 2514, +1969, 1800, 2514, +1963, 1958, 2030, +1962, 1958, 2030, +1962, 1958, 2031, +1962, 1958, 2031, +1961, 1958, 2032, +1960, 1958, 2033, +1959, 1958, 2034, +1958, 1958, 2036, +1958, 1958, 2039, +1956, 1958, 2042, +1955, 1958, 2047, +1952, 1958, 2052, +1949, 1958, 2059, +1943, 1961, 2068, +1937, 1966, 2081, +1930, 1968, 2111, +1921, 1967, 2155, +1905, 1961, 2189, +1920, 1967, 2241, +1887, 1967, 2319, +1931, 1954, 2392, +2040, 1964, 2481, +2099, 1967, 2516, +2099, 1967, 2516, +2099, 1967, 2516, +2099, 1967, 2516, +2099, 1967, 2516, +2099, 1967, 2516, +2099, 1967, 2516, +2099, 1967, 2516, +2099, 1967, 2516, +2099, 1967, 2516, +2121, 2120, 2069, +2121, 2120, 2069, +2121, 2120, 2069, +2121, 2120, 2069, +2121, 2120, 2070, +2122, 2120, 2070, +2122, 2120, 2070, +2122, 2121, 2072, +2122, 2122, 2074, +2122, 2122, 2078, +2122, 2124, 2082, +2122, 2125, 2087, +2121, 2127, 2094, +2119, 2127, 2101, +2119, 2127, 2110, +2118, 2131, 2131, +2112, 2134, 2166, +2105, 2129, 2205, +2112, 2134, 2255, +2122, 2134, 2316, +2148, 2132, 2396, +2214, 2146, 2485, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2261, 2159, 2523, +2370, 2355, 2124, +2370, 2355, 2124, +2370, 2355, 2124, +2370, 2355, 2125, +2370, 2355, 2125, +2370, 2355, 2126, +2371, 2355, 2126, +2370, 2356, 2127, +2370, 2356, 2129, +2369, 2357, 2131, +2369, 2357, 2133, +2369, 2358, 2137, +2370, 2359, 2143, +2370, 2358, 2146, +2369, 2356, 2148, +2369, 2358, 2162, +2372, 2358, 2193, +2371, 2358, 2226, +2374, 2356, 2273, +2386, 2358, 2337, +2411, 2367, 2406, +2465, 2384, 2499, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2681, 2655, 1963, +2681, 2655, 1963, +2681, 2655, 1964, +2681, 2655, 1965, +2681, 2655, 1967, +2681, 2655, 1969, +2681, 2656, 1972, +2681, 2656, 1973, +2681, 2655, 1972, +2681, 2655, 1971, +2680, 2655, 1969, +2680, 2654, 1967, +2679, 2654, 1967, +2679, 2655, 1983, +2677, 2656, 2005, +2677, 2654, 2023, +2675, 2651, 2045, +2677, 2655, 2122, +2681, 2656, 2208, +2688, 2660, 2305, +2695, 2666, 2408, +2715, 2678, 2527, +2723, 2684, 2576, +2723, 2684, 2576, +2723, 2684, 2576, +2723, 2684, 2576, +2723, 2684, 2576, +2723, 2684, 2576, +2723, 2684, 2576, +2723, 2684, 2576, +2723, 2684, 2576, +2723, 2684, 2576, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2458, +2710, 2773, 2482, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2722, 2784, 2693, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2458, +2710, 2773, 2482, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2722, 2784, 2693, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2458, +2710, 2773, 2482, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2722, 2784, 2693, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2458, +2710, 2773, 2482, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2722, 2784, 2693, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2458, +2710, 2773, 2482, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2722, 2784, 2693, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2458, +2710, 2773, 2482, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2722, 2784, 2693, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2458, +2710, 2773, 2482, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2722, 2784, 2693, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2458, +2710, 2773, 2482, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2722, 2784, 2693, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2458, +2710, 2773, 2482, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2722, 2784, 2693, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2458, +2710, 2773, 2482, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2722, 2784, 2693, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +469, 0, 0, +469, 0, 0, +469, 0, 0, +469, 0, 0, +469, 0, 28, +469, 0, 152, +469, 0, 280, +469, 0, 408, +469, 0, 537, +469, 0, 667, +469, 0, 797, +469, 0, 928, +404, 0, 1088, +100, 0, 1333, +100, 0, 1501, +408, 0, 1634, +813, 0, 1779, +1202, 0, 1887, +1561, 0, 2010, +1542, 61, 2164, +352, 987, 2341, +1276, 570, 2469, +1737, 0, 2503, +1737, 0, 2503, +1737, 0, 2503, +1737, 0, 2503, +1737, 0, 2503, +1737, 0, 2503, +1737, 0, 2503, +1737, 0, 2503, +1737, 0, 2503, +1737, 0, 2503, +462, 0, 0, +465, 0, 0, +465, 0, 0, +465, 0, 0, +465, 0, 36, +465, 0, 159, +465, 0, 285, +465, 0, 412, +465, 0, 540, +465, 0, 669, +465, 0, 799, +465, 0, 930, +393, 0, 1089, +76, 0, 1333, +76, 0, 1501, +412, 0, 1635, +805, 0, 1779, +1201, 0, 1887, +1561, 0, 2011, +1541, 86, 2164, +352, 992, 2341, +1280, 573, 2469, +1736, 0, 2503, +1736, 0, 2503, +1736, 0, 2503, +1736, 0, 2503, +1736, 0, 2503, +1736, 0, 2503, +1736, 0, 2503, +1736, 0, 2503, +1736, 0, 2503, +1736, 0, 2503, +453, 0, 0, +456, 0, 0, +461, 0, 0, +461, 0, 0, +461, 0, 48, +461, 0, 168, +461, 0, 291, +461, 0, 417, +461, 0, 544, +461, 0, 672, +461, 0, 801, +461, 0, 931, +387, 0, 1090, +43, 0, 1334, +43, 0, 1501, +417, 0, 1635, +793, 0, 1778, +1200, 0, 1888, +1560, 0, 2011, +1539, 116, 2164, +352, 998, 2341, +1285, 577, 2469, +1736, 0, 2503, +1736, 0, 2503, +1736, 0, 2503, +1736, 0, 2503, +1736, 0, 2503, +1736, 0, 2503, +1736, 0, 2503, +1736, 0, 2503, +1736, 0, 2503, +1736, 0, 2503, +440, 0, 0, +444, 0, 0, +448, 0, 0, +455, 0, 0, +455, 0, 63, +455, 0, 180, +455, 0, 300, +455, 0, 424, +455, 0, 549, +455, 0, 676, +455, 0, 804, +455, 0, 933, +380, 0, 1091, +0, 0, 1335, +0, 0, 1502, +424, 0, 1636, +778, 0, 1778, +1199, 0, 1889, +1560, 0, 2012, +1537, 154, 2164, +352, 1005, 2342, +1292, 582, 2469, +1736, 0, 2504, +1736, 0, 2504, +1736, 0, 2504, +1736, 0, 2504, +1736, 0, 2504, +1736, 0, 2504, +1736, 0, 2504, +1736, 0, 2504, +1736, 0, 2504, +1736, 0, 2504, +422, 0, 0, +426, 0, 0, +431, 0, 0, +437, 0, 0, +446, 0, 83, +446, 0, 195, +446, 0, 312, +446, 0, 433, +446, 0, 556, +446, 0, 681, +446, 0, 808, +446, 0, 936, +370, 0, 1093, +0, 0, 1336, +0, 0, 1503, +433, 0, 1637, +757, 0, 1778, +1197, 0, 1889, +1559, 0, 2013, +1534, 201, 2165, +352, 1015, 2342, +1302, 588, 2469, +1735, 0, 2504, +1735, 0, 2504, +1735, 0, 2504, +1735, 0, 2504, +1735, 0, 2504, +1735, 0, 2504, +1735, 0, 2504, +1735, 0, 2504, +1735, 0, 2504, +1735, 0, 2504, +397, 0, 0, +401, 0, 0, +406, 0, 0, +413, 0, 0, +422, 0, 83, +434, 0, 215, +434, 0, 327, +434, 0, 444, +434, 0, 564, +434, 0, 688, +434, 0, 813, +434, 0, 940, +356, 0, 1096, +0, 30, 1338, +0, 30, 1504, +444, 0, 1639, +726, 0, 1777, +1195, 0, 1890, +1558, 0, 2015, +1530, 256, 2165, +352, 1028, 2343, +1314, 596, 2469, +1735, 30, 2504, +1735, 30, 2504, +1735, 30, 2504, +1735, 30, 2504, +1735, 30, 2504, +1735, 30, 2504, +1735, 30, 2504, +1735, 30, 2504, +1735, 30, 2504, +1735, 30, 2504, +362, 4, 0, +366, 0, 0, +371, 0, 0, +379, 0, 0, +389, 0, 83, +402, 0, 215, +418, 0, 347, +418, 0, 459, +418, 0, 576, +418, 0, 697, +418, 0, 820, +418, 0, 946, +337, 0, 1100, +0, 163, 1340, +0, 163, 1505, +459, 32, 1641, +682, 0, 1776, +1192, 0, 1891, +1557, 32, 2017, +1524, 322, 2166, +352, 1045, 2344, +1329, 607, 2469, +1734, 163, 2504, +1734, 163, 2504, +1734, 163, 2504, +1734, 163, 2504, +1734, 163, 2504, +1734, 163, 2504, +1734, 163, 2504, +1734, 163, 2504, +1734, 163, 2504, +1734, 163, 2504, +309, 144, 0, +314, 137, 0, +320, 127, 0, +329, 114, 0, +340, 96, 83, +354, 70, 215, +373, 34, 347, +396, 0, 479, +396, 0, 591, +396, 0, 708, +396, 0, 829, +396, 0, 952, +310, 52, 1105, +0, 295, 1343, +0, 295, 1507, +479, 164, 1644, +615, 0, 1775, +1188, 0, 1893, +1555, 164, 2019, +1516, 396, 2167, +352, 1066, 2345, +1349, 621, 2469, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +1732, 295, 2505, +309, 281, 0, +314, 276, 0, +320, 269, 0, +329, 259, 0, +340, 246, 83, +354, 227, 215, +373, 202, 347, +396, 166, 479, +396, 257, 648, +396, 257, 752, +396, 257, 863, +396, 257, 978, +310, 298, 1124, +0, 426, 1354, +0, 426, 1515, +479, 333, 1648, +652, 0, 1779, +1183, 111, 1897, +1538, 296, 2024, +1489, 550, 2172, +317, 1093, 2347, +1385, 639, 2469, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +309, 417, 0, +314, 413, 0, +320, 408, 0, +329, 401, 0, +340, 391, 83, +354, 378, 215, +373, 360, 347, +396, 334, 479, +396, 399, 648, +396, 474, 805, +396, 474, 905, +396, 474, 1011, +310, 500, 1148, +0, 570, 1369, +0, 559, 1526, +479, 490, 1653, +655, 270, 1784, +1176, 244, 1901, +1514, 428, 2029, +1450, 699, 2178, +265, 1128, 2349, +1430, 662, 2469, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +309, 552, 0, +314, 549, 0, +320, 545, 0, +329, 540, 0, +340, 533, 83, +354, 523, 215, +373, 510, 347, +396, 492, 479, +396, 539, 648, +396, 595, 805, +396, 661, 955, +396, 661, 1052, +310, 678, 1178, +0, 726, 1388, +0, 691, 1539, +479, 640, 1662, +655, 494, 1789, +1191, 422, 1907, +1480, 560, 2037, +1393, 842, 2187, +186, 1169, 2352, +1483, 691, 2469, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +309, 686, 0, +314, 684, 0, +320, 681, 0, +329, 677, 0, +340, 672, 83, +354, 665, 215, +373, 655, 347, +396, 643, 479, +396, 677, 648, +396, 719, 805, +396, 770, 955, +396, 830, 1101, +310, 842, 1216, +0, 876, 1412, +0, 823, 1557, +479, 786, 1675, +655, 684, 1796, +1216, 593, 1915, +1430, 692, 2047, +1302, 983, 2199, +0, 1212, 2357, +1546, 728, 2469, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +313, 854, 85, +295, 854, 130, +302, 852, 185, +310, 850, 248, +322, 846, 322, +336, 841, 404, +356, 835, 496, +380, 826, 594, +380, 849, 730, +380, 878, 865, +380, 915, 1000, +380, 960, 1133, +426, 1005, 1267, +0, 1029, 1446, +0, 983, 1581, +504, 947, 1697, +664, 894, 1810, +1232, 800, 1928, +1359, 849, 2059, +1164, 1123, 2212, +0, 1254, 2365, +1607, 800, 2469, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +579, 1156, 985, +568, 1156, 992, +553, 1156, 1001, +532, 1156, 1012, +503, 1156, 1027, +461, 1156, 1045, +397, 1156, 1069, +295, 1156, 1099, +295, 1156, 1125, +295, 1161, 1168, +295, 1181, 1242, +295, 1207, 1325, +350, 1233, 1417, +549, 1224, 1507, +549, 1195, 1627, +610, 1196, 1748, +721, 1200, 1858, +1128, 1147, 1966, +1243, 1131, 2078, +1031, 1271, 2227, +827, 1290, 2369, +1605, 1012, 2470, +1776, 1112, 2512, +1776, 1112, 2512, +1776, 1112, 2512, +1776, 1112, 2512, +1776, 1112, 2512, +1776, 1112, 2512, +1776, 1112, 2512, +1776, 1112, 2512, +1776, 1112, 2512, +1776, 1112, 2512, +579, 1405, 1359, +568, 1405, 1361, +553, 1405, 1365, +532, 1405, 1370, +503, 1405, 1377, +461, 1405, 1386, +397, 1405, 1397, +295, 1405, 1412, +295, 1405, 1425, +295, 1405, 1442, +295, 1405, 1463, +295, 1405, 1491, +350, 1416, 1546, +549, 1410, 1615, +549, 1390, 1682, +610, 1395, 1793, +721, 1413, 1898, +1134, 1362, 2004, +1151, 1350, 2108, +878, 1405, 2243, +927, 1369, 2376, +1617, 1196, 2472, +1809, 1292, 2510, +1809, 1292, 2510, +1809, 1292, 2510, +1809, 1292, 2510, +1809, 1292, 2510, +1809, 1292, 2510, +1809, 1292, 2510, +1809, 1292, 2510, +1809, 1292, 2510, +1809, 1292, 2510, +1091, 1568, 1658, +1091, 1569, 1659, +1089, 1569, 1660, +1088, 1569, 1661, +1086, 1570, 1663, +1083, 1571, 1665, +1079, 1572, 1668, +1074, 1574, 1673, +1074, 1572, 1680, +1074, 1569, 1690, +1074, 1567, 1702, +1074, 1567, 1718, +1060, 1567, 1740, +984, 1571, 1781, +984, 1563, 1832, +1008, 1552, 1891, +990, 1557, 1977, +1050, 1536, 2065, +1008, 1537, 2170, +810, 1530, 2268, +1184, 1494, 2382, +1680, 1435, 2473, +1842, 1464, 2509, +1842, 1464, 2509, +1842, 1464, 2509, +1842, 1464, 2509, +1842, 1464, 2509, +1842, 1464, 2509, +1842, 1464, 2509, +1842, 1464, 2509, +1842, 1464, 2509, +1842, 1464, 2509, +1472, 1701, 1853, +1471, 1701, 1854, +1469, 1702, 1855, +1467, 1702, 1856, +1464, 1703, 1858, +1461, 1703, 1861, +1456, 1704, 1864, +1449, 1705, 1868, +1443, 1705, 1873, +1442, 1703, 1880, +1442, 1700, 1888, +1442, 1696, 1899, +1439, 1691, 1913, +1417, 1685, 1933, +1417, 1696, 1979, +1379, 1697, 2020, +1390, 1690, 2066, +1256, 1672, 2126, +1172, 1682, 2221, +1227, 1647, 2296, +1526, 1636, 2386, +1786, 1634, 2474, +1899, 1624, 2511, +1899, 1624, 2511, +1899, 1624, 2511, +1899, 1624, 2511, +1899, 1624, 2511, +1899, 1624, 2511, +1899, 1624, 2511, +1899, 1624, 2511, +1899, 1624, 2511, +1899, 1624, 2511, +1800, 1814, 1976, +1800, 1814, 1976, +1799, 1814, 1977, +1799, 1814, 1978, +1797, 1814, 1979, +1796, 1814, 1981, +1795, 1814, 1983, +1793, 1814, 1986, +1794, 1814, 1988, +1796, 1814, 1992, +1792, 1814, 1998, +1785, 1814, 2007, +1776, 1815, 2018, +1760, 1821, 2034, +1741, 1815, 2050, +1739, 1806, 2078, +1704, 1816, 2125, +1714, 1805, 2166, +1662, 1793, 2234, +1683, 1796, 2305, +1765, 1797, 2390, +1871, 1786, 2475, +1971, 1800, 2514, +1971, 1800, 2514, +1971, 1800, 2514, +1971, 1800, 2514, +1971, 1800, 2514, +1971, 1800, 2514, +1971, 1800, 2514, +1971, 1800, 2514, +1971, 1800, 2514, +1971, 1800, 2514, +1965, 1958, 2031, +1965, 1958, 2031, +1964, 1958, 2031, +1964, 1958, 2032, +1963, 1958, 2032, +1962, 1958, 2034, +1961, 1958, 2035, +1960, 1958, 2037, +1959, 1958, 2039, +1958, 1958, 2042, +1956, 1958, 2047, +1953, 1958, 2053, +1951, 1958, 2060, +1944, 1960, 2068, +1938, 1965, 2081, +1932, 1967, 2110, +1924, 1968, 2156, +1905, 1961, 2189, +1920, 1966, 2240, +1890, 1966, 2318, +1932, 1954, 2393, +2043, 1964, 2481, +2101, 1966, 2516, +2101, 1966, 2516, +2101, 1966, 2516, +2101, 1966, 2516, +2101, 1966, 2516, +2101, 1966, 2516, +2101, 1966, 2516, +2101, 1966, 2516, +2101, 1966, 2516, +2101, 1966, 2516, +2121, 2121, 2069, +2121, 2121, 2070, +2121, 2121, 2070, +2122, 2121, 2070, +2122, 2121, 2070, +2122, 2121, 2071, +2122, 2121, 2071, +2123, 2121, 2071, +2123, 2122, 2074, +2123, 2122, 2077, +2123, 2124, 2081, +2123, 2125, 2086, +2122, 2127, 2093, +2119, 2127, 2101, +2119, 2127, 2110, +2119, 2131, 2131, +2114, 2135, 2167, +2107, 2129, 2205, +2112, 2133, 2255, +2123, 2133, 2316, +2148, 2132, 2397, +2215, 2145, 2485, +2260, 2159, 2523, +2260, 2159, 2523, +2260, 2159, 2523, +2260, 2159, 2523, +2260, 2159, 2523, +2260, 2159, 2523, +2260, 2159, 2523, +2260, 2159, 2523, +2260, 2159, 2523, +2260, 2159, 2523, +2370, 2355, 2124, +2370, 2355, 2124, +2370, 2355, 2124, +2370, 2355, 2125, +2370, 2355, 2125, +2370, 2355, 2126, +2371, 2355, 2126, +2371, 2355, 2127, +2371, 2356, 2129, +2370, 2356, 2131, +2369, 2357, 2133, +2369, 2358, 2137, +2370, 2359, 2143, +2370, 2358, 2146, +2369, 2356, 2148, +2369, 2358, 2161, +2372, 2358, 2193, +2371, 2358, 2227, +2375, 2356, 2273, +2387, 2359, 2337, +2411, 2367, 2406, +2465, 2384, 2499, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2496, 2391, 2531, +2681, 2655, 1963, +2681, 2655, 1963, +2681, 2655, 1964, +2681, 2655, 1965, +2681, 2655, 1967, +2681, 2655, 1969, +2681, 2656, 1972, +2681, 2656, 1975, +2681, 2656, 1974, +2681, 2656, 1973, +2680, 2655, 1971, +2680, 2655, 1969, +2679, 2654, 1969, +2679, 2655, 1990, +2678, 2657, 2010, +2677, 2655, 2027, +2675, 2651, 2050, +2677, 2656, 2121, +2681, 2656, 2208, +2688, 2660, 2305, +2695, 2665, 2407, +2715, 2678, 2527, +2723, 2684, 2576, +2723, 2684, 2576, +2723, 2684, 2576, +2723, 2684, 2576, +2723, 2684, 2576, +2723, 2684, 2576, +2723, 2684, 2576, +2723, 2684, 2576, +2723, 2684, 2576, +2723, 2684, 2576, +2713, 2771, 2431, +2713, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2460, +2711, 2773, 2482, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2722, 2784, 2693, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2771, 2431, +2713, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2460, +2711, 2773, 2482, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2722, 2784, 2693, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2771, 2431, +2713, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2460, +2711, 2773, 2482, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2722, 2784, 2693, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2771, 2431, +2713, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2460, +2711, 2773, 2482, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2722, 2784, 2693, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2771, 2431, +2713, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2460, +2711, 2773, 2482, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2722, 2784, 2693, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2771, 2431, +2713, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2460, +2711, 2773, 2482, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2722, 2784, 2693, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2771, 2431, +2713, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2460, +2711, 2773, 2482, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2722, 2784, 2693, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2771, 2431, +2713, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2460, +2711, 2773, 2482, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2722, 2784, 2693, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2771, 2431, +2713, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2460, +2711, 2773, 2482, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2722, 2784, 2693, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2771, 2431, +2713, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2432, +2715, 2770, 2435, +2716, 2768, 2439, +2714, 2769, 2444, +2711, 2772, 2460, +2711, 2773, 2482, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2722, 2784, 2693, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +603, 0, 0, +603, 0, 0, +603, 0, 0, +603, 0, 0, +603, 0, 28, +603, 0, 152, +603, 0, 280, +603, 0, 408, +603, 0, 537, +603, 0, 667, +603, 0, 797, +603, 0, 928, +556, 0, 1088, +249, 0, 1348, +249, 0, 1511, +537, 0, 1634, +912, 0, 1782, +1222, 0, 1890, +1561, 0, 2012, +1535, 174, 2167, +317, 987, 2341, +1325, 528, 2469, +1738, 0, 2504, +1738, 0, 2504, +1738, 0, 2504, +1738, 0, 2504, +1738, 0, 2504, +1738, 0, 2504, +1738, 0, 2504, +1738, 0, 2504, +1738, 0, 2504, +1738, 0, 2504, +598, 0, 0, +601, 0, 0, +601, 0, 0, +601, 0, 0, +601, 0, 36, +601, 0, 159, +601, 0, 285, +601, 0, 412, +601, 0, 540, +601, 0, 669, +601, 0, 799, +601, 0, 930, +548, 0, 1089, +232, 0, 1349, +232, 0, 1511, +540, 0, 1635, +906, 0, 1782, +1221, 0, 1890, +1561, 0, 2013, +1534, 193, 2167, +317, 992, 2341, +1328, 531, 2469, +1738, 0, 2504, +1738, 0, 2504, +1738, 0, 2504, +1738, 0, 2504, +1738, 0, 2504, +1738, 0, 2504, +1738, 0, 2504, +1738, 0, 2504, +1738, 0, 2504, +1738, 0, 2504, +591, 0, 0, +594, 0, 0, +597, 0, 0, +597, 0, 0, +597, 0, 48, +597, 0, 168, +597, 0, 291, +597, 0, 417, +597, 0, 544, +597, 0, 672, +597, 0, 801, +597, 0, 931, +544, 0, 1090, +208, 0, 1349, +208, 0, 1512, +544, 0, 1635, +897, 0, 1781, +1221, 0, 1891, +1560, 0, 2013, +1532, 217, 2168, +317, 998, 2341, +1333, 535, 2469, +1738, 0, 2504, +1738, 0, 2504, +1738, 0, 2504, +1738, 0, 2504, +1738, 0, 2504, +1738, 0, 2504, +1738, 0, 2504, +1738, 0, 2504, +1738, 0, 2504, +1738, 0, 2504, +582, 0, 0, +585, 0, 0, +588, 0, 0, +593, 0, 0, +593, 0, 63, +593, 0, 180, +593, 0, 300, +593, 0, 424, +593, 0, 549, +593, 0, 676, +593, 0, 804, +593, 0, 933, +539, 0, 1091, +175, 0, 1351, +175, 0, 1512, +549, 0, 1636, +884, 0, 1781, +1220, 0, 1891, +1560, 0, 2014, +1530, 248, 2168, +317, 1005, 2342, +1339, 540, 2469, +1737, 0, 2504, +1737, 0, 2504, +1737, 0, 2504, +1737, 0, 2504, +1737, 0, 2504, +1737, 0, 2504, +1737, 0, 2504, +1737, 0, 2504, +1737, 0, 2504, +1737, 0, 2504, +569, 0, 0, +572, 0, 0, +575, 0, 0, +580, 0, 0, +586, 0, 83, +586, 0, 195, +586, 0, 312, +586, 0, 433, +586, 0, 556, +586, 0, 681, +586, 0, 808, +586, 0, 936, +532, 0, 1093, +125, 0, 1352, +125, 0, 1513, +556, 0, 1637, +867, 0, 1781, +1218, 0, 1891, +1559, 0, 2015, +1526, 286, 2168, +317, 1015, 2342, +1348, 547, 2469, +1737, 0, 2504, +1737, 0, 2504, +1737, 0, 2504, +1737, 0, 2504, +1737, 0, 2504, +1737, 0, 2504, +1737, 0, 2504, +1737, 0, 2504, +1737, 0, 2504, +1737, 0, 2504, +551, 0, 0, +554, 0, 0, +558, 0, 0, +563, 0, 0, +569, 0, 83, +578, 0, 215, +578, 0, 327, +578, 0, 444, +578, 0, 564, +578, 0, 688, +578, 0, 813, +578, 0, 940, +522, 0, 1096, +50, 30, 1353, +50, 30, 1514, +564, 0, 1639, +844, 0, 1780, +1216, 0, 1893, +1558, 0, 2017, +1522, 333, 2169, +317, 1028, 2343, +1359, 556, 2469, +1736, 30, 2504, +1736, 30, 2504, +1736, 30, 2504, +1736, 30, 2504, +1736, 30, 2504, +1736, 30, 2504, +1736, 30, 2504, +1736, 30, 2504, +1736, 30, 2504, +1736, 30, 2504, +526, 4, 0, +529, 0, 0, +533, 0, 0, +538, 0, 0, +545, 0, 83, +554, 0, 215, +566, 0, 347, +566, 0, 459, +566, 0, 576, +566, 0, 697, +566, 0, 820, +566, 0, 946, +509, 0, 1100, +0, 163, 1355, +0, 163, 1516, +576, 32, 1641, +810, 0, 1779, +1213, 0, 1894, +1557, 32, 2019, +1516, 388, 2170, +317, 1045, 2344, +1373, 568, 2469, +1735, 163, 2505, +1735, 163, 2505, +1735, 163, 2505, +1735, 163, 2505, +1735, 163, 2505, +1735, 163, 2505, +1735, 163, 2505, +1735, 163, 2505, +1735, 163, 2505, +1735, 163, 2505, +490, 144, 0, +494, 137, 0, +498, 127, 0, +504, 114, 0, +511, 96, 83, +521, 70, 215, +534, 34, 347, +550, 0, 479, +550, 0, 591, +550, 0, 708, +550, 0, 829, +550, 0, 952, +491, 52, 1105, +0, 295, 1358, +0, 295, 1518, +591, 164, 1644, +761, 0, 1778, +1209, 0, 1896, +1555, 164, 2021, +1508, 454, 2170, +317, 1066, 2345, +1391, 584, 2469, +1734, 295, 2505, +1734, 295, 2505, +1734, 295, 2505, +1734, 295, 2505, +1734, 295, 2505, +1734, 295, 2505, +1734, 295, 2505, +1734, 295, 2505, +1734, 295, 2505, +1734, 295, 2505, +438, 281, 0, +441, 276, 0, +446, 269, 0, +452, 259, 0, +461, 246, 83, +472, 227, 215, +486, 202, 347, +505, 166, 479, +528, 111, 611, +528, 111, 723, +528, 111, 840, +528, 111, 961, +465, 167, 1111, +0, 426, 1362, +0, 426, 1520, +611, 296, 1648, +685, 0, 1777, +1204, 111, 1898, +1552, 296, 2024, +1498, 528, 2172, +317, 1093, 2347, +1405, 655, 2469, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +1732, 426, 2506, +438, 417, 0, +441, 413, 0, +446, 408, 0, +452, 401, 0, +461, 391, 83, +472, 378, 215, +486, 360, 347, +505, 334, 479, +528, 298, 611, +528, 390, 780, +528, 390, 884, +528, 390, 995, +465, 420, 1136, +0, 570, 1376, +0, 559, 1531, +611, 465, 1653, +688, 180, 1781, +1197, 244, 1902, +1529, 428, 2030, +1459, 683, 2178, +265, 1128, 2349, +1448, 678, 2469, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +438, 552, 0, +441, 549, 0, +446, 545, 0, +452, 540, 0, +461, 533, 83, +472, 523, 215, +486, 510, 347, +505, 492, 479, +528, 466, 611, +528, 532, 780, +528, 606, 937, +528, 606, 1037, +465, 626, 1167, +0, 726, 1395, +0, 691, 1544, +611, 622, 1662, +688, 441, 1786, +1211, 422, 1908, +1496, 560, 2038, +1403, 831, 2187, +186, 1169, 2352, +1499, 706, 2469, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +438, 686, 0, +441, 684, 0, +446, 681, 0, +452, 677, 0, +461, 672, 83, +472, 665, 215, +486, 655, 347, +505, 643, 479, +528, 624, 611, +528, 671, 780, +528, 728, 937, +528, 793, 1088, +465, 806, 1206, +0, 876, 1419, +0, 823, 1561, +611, 773, 1675, +688, 651, 1793, +1235, 593, 1916, +1448, 692, 2048, +1314, 975, 2199, +0, 1212, 2357, +1560, 742, 2469, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +441, 854, 85, +427, 854, 130, +432, 852, 185, +438, 850, 248, +447, 846, 322, +458, 841, 404, +473, 835, 496, +492, 826, 594, +516, 814, 700, +516, 845, 843, +516, 884, 983, +516, 932, 1121, +551, 980, 1257, +0, 1029, 1452, +0, 983, 1586, +630, 938, 1697, +697, 873, 1807, +1251, 800, 1930, +1381, 849, 2060, +1181, 1116, 2212, +0, 1254, 2365, +1619, 811, 2469, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +719, 1144, 968, +711, 1144, 975, +700, 1144, 984, +685, 1144, 996, +664, 1144, 1011, +635, 1144, 1030, +592, 1144, 1055, +529, 1144, 1086, +426, 1144, 1125, +426, 1150, 1168, +426, 1170, 1242, +426, 1196, 1325, +469, 1224, 1417, +681, 1219, 1512, +681, 1190, 1631, +741, 1186, 1751, +750, 1205, 1859, +1158, 1153, 1968, +1243, 1131, 2078, +1031, 1271, 2228, +914, 1282, 2369, +1608, 1020, 2470, +1781, 1099, 2512, +1781, 1099, 2512, +1781, 1099, 2512, +1781, 1099, 2512, +1781, 1099, 2512, +1781, 1099, 2512, +1781, 1099, 2512, +1781, 1099, 2512, +1781, 1099, 2512, +1781, 1099, 2512, +719, 1398, 1351, +711, 1398, 1354, +700, 1398, 1358, +685, 1398, 1363, +664, 1398, 1370, +635, 1398, 1379, +592, 1398, 1390, +529, 1398, 1406, +426, 1398, 1425, +426, 1398, 1442, +426, 1398, 1463, +426, 1398, 1491, +469, 1409, 1546, +681, 1406, 1619, +681, 1387, 1686, +741, 1388, 1796, +750, 1416, 1900, +1164, 1366, 2006, +1151, 1350, 2107, +878, 1405, 2243, +998, 1362, 2375, +1620, 1201, 2472, +1813, 1283, 2510, +1813, 1283, 2510, +1813, 1283, 2510, +1813, 1283, 2510, +1813, 1283, 2510, +1813, 1283, 2510, +1813, 1283, 2510, +1813, 1283, 2510, +1813, 1283, 2510, +1813, 1283, 2510, +1148, 1563, 1662, +1147, 1564, 1663, +1146, 1564, 1663, +1145, 1565, 1665, +1143, 1565, 1667, +1140, 1566, 1669, +1137, 1568, 1672, +1133, 1569, 1676, +1126, 1572, 1682, +1126, 1569, 1691, +1126, 1567, 1704, +1126, 1567, 1720, +1114, 1567, 1742, +1017, 1569, 1778, +1017, 1561, 1829, +1046, 1552, 1893, +1045, 1557, 1979, +1092, 1536, 2064, +1032, 1537, 2170, +810, 1533, 2268, +1205, 1491, 2382, +1680, 1432, 2474, +1841, 1461, 2509, +1841, 1461, 2509, +1841, 1461, 2509, +1841, 1461, 2509, +1841, 1461, 2509, +1841, 1461, 2509, +1841, 1461, 2509, +1841, 1461, 2509, +1841, 1461, 2509, +1841, 1461, 2509, +1481, 1699, 1851, +1480, 1700, 1852, +1478, 1700, 1853, +1476, 1700, 1855, +1473, 1701, 1857, +1470, 1702, 1859, +1465, 1703, 1863, +1458, 1704, 1867, +1449, 1705, 1873, +1448, 1703, 1880, +1448, 1700, 1888, +1448, 1696, 1899, +1445, 1691, 1913, +1423, 1685, 1934, +1423, 1696, 1979, +1383, 1695, 2019, +1396, 1691, 2067, +1278, 1672, 2126, +1188, 1684, 2221, +1246, 1647, 2296, +1529, 1638, 2386, +1793, 1636, 2474, +1901, 1622, 2511, +1901, 1622, 2511, +1901, 1622, 2511, +1901, 1622, 2511, +1901, 1622, 2511, +1901, 1622, 2511, +1901, 1622, 2511, +1901, 1622, 2511, +1901, 1622, 2511, +1901, 1622, 2511, +1805, 1813, 1975, +1805, 1813, 1975, +1805, 1813, 1976, +1804, 1813, 1977, +1803, 1813, 1978, +1802, 1813, 1979, +1800, 1813, 1982, +1798, 1813, 1984, +1796, 1813, 1988, +1797, 1813, 1992, +1793, 1813, 1998, +1787, 1813, 2007, +1777, 1813, 2018, +1763, 1819, 2033, +1745, 1813, 2049, +1744, 1807, 2077, +1710, 1816, 2126, +1718, 1804, 2166, +1664, 1793, 2234, +1690, 1798, 2306, +1770, 1797, 2390, +1871, 1786, 2475, +1974, 1800, 2514, +1974, 1800, 2514, +1974, 1800, 2514, +1974, 1800, 2514, +1974, 1800, 2514, +1974, 1800, 2514, +1974, 1800, 2514, +1974, 1800, 2514, +1974, 1800, 2514, +1974, 1800, 2514, +1968, 1958, 2031, +1968, 1958, 2031, +1967, 1958, 2032, +1967, 1958, 2032, +1966, 1958, 2033, +1965, 1958, 2034, +1964, 1958, 2036, +1963, 1958, 2038, +1961, 1958, 2040, +1960, 1958, 2043, +1958, 1958, 2048, +1955, 1958, 2054, +1953, 1958, 2061, +1945, 1959, 2068, +1939, 1964, 2081, +1934, 1966, 2107, +1928, 1969, 2157, +1905, 1959, 2189, +1920, 1965, 2239, +1893, 1965, 2317, +1933, 1954, 2393, +2043, 1964, 2481, +2104, 1965, 2515, +2104, 1965, 2515, +2104, 1965, 2515, +2104, 1965, 2515, +2104, 1965, 2515, +2104, 1965, 2515, +2104, 1965, 2515, +2104, 1965, 2515, +2104, 1965, 2515, +2104, 1965, 2515, +2122, 2122, 2070, +2122, 2122, 2070, +2122, 2122, 2071, +2122, 2122, 2071, +2122, 2122, 2071, +2123, 2122, 2071, +2123, 2122, 2072, +2124, 2122, 2072, +2124, 2122, 2073, +2124, 2122, 2076, +2124, 2124, 2080, +2124, 2125, 2086, +2124, 2127, 2093, +2119, 2127, 2101, +2119, 2127, 2110, +2120, 2131, 2130, +2116, 2135, 2169, +2108, 2128, 2204, +2113, 2132, 2254, +2124, 2133, 2316, +2148, 2133, 2397, +2216, 2146, 2485, +2260, 2159, 2522, +2260, 2159, 2522, +2260, 2159, 2522, +2260, 2159, 2522, +2260, 2159, 2522, +2260, 2159, 2522, +2260, 2159, 2522, +2260, 2159, 2522, +2260, 2159, 2522, +2260, 2159, 2522, +2370, 2355, 2124, +2370, 2355, 2124, +2370, 2355, 2124, +2370, 2355, 2125, +2370, 2355, 2125, +2370, 2355, 2126, +2371, 2355, 2126, +2371, 2355, 2127, +2371, 2355, 2129, +2371, 2356, 2131, +2370, 2357, 2133, +2370, 2357, 2137, +2371, 2358, 2143, +2370, 2358, 2146, +2369, 2356, 2148, +2370, 2358, 2161, +2373, 2358, 2193, +2372, 2358, 2227, +2376, 2357, 2273, +2388, 2360, 2337, +2411, 2367, 2406, +2465, 2385, 2499, +2496, 2392, 2532, +2496, 2392, 2532, +2496, 2392, 2532, +2496, 2392, 2532, +2496, 2392, 2532, +2496, 2392, 2532, +2496, 2392, 2532, +2496, 2392, 2532, +2496, 2392, 2532, +2496, 2392, 2532, +2680, 2654, 1962, +2680, 2655, 1962, +2681, 2655, 1963, +2681, 2655, 1964, +2681, 2655, 1966, +2681, 2655, 1968, +2681, 2656, 1970, +2681, 2656, 1974, +2681, 2656, 1972, +2681, 2655, 1970, +2680, 2655, 1969, +2680, 2654, 1966, +2679, 2654, 1967, +2679, 2655, 1987, +2677, 2657, 2008, +2677, 2656, 2029, +2675, 2652, 2050, +2677, 2656, 2121, +2681, 2656, 2208, +2688, 2660, 2306, +2695, 2665, 2407, +2715, 2678, 2527, +2724, 2684, 2577, +2724, 2684, 2577, +2724, 2684, 2577, +2724, 2684, 2577, +2724, 2684, 2577, +2724, 2684, 2577, +2724, 2684, 2577, +2724, 2684, 2577, +2724, 2684, 2577, +2724, 2684, 2577, +2713, 2771, 2430, +2713, 2771, 2430, +2713, 2771, 2430, +2714, 2771, 2430, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2432, +2715, 2770, 2435, +2716, 2769, 2439, +2714, 2769, 2444, +2711, 2772, 2462, +2711, 2773, 2481, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2723, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2771, 2430, +2713, 2771, 2430, +2713, 2771, 2430, +2714, 2771, 2430, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2432, +2715, 2770, 2435, +2716, 2769, 2439, +2714, 2769, 2444, +2711, 2772, 2462, +2711, 2773, 2481, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2723, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2771, 2430, +2713, 2771, 2430, +2713, 2771, 2430, +2714, 2771, 2430, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2432, +2715, 2770, 2435, +2716, 2769, 2439, +2714, 2769, 2444, +2711, 2772, 2462, +2711, 2773, 2481, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2723, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2771, 2430, +2713, 2771, 2430, +2713, 2771, 2430, +2714, 2771, 2430, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2432, +2715, 2770, 2435, +2716, 2769, 2439, +2714, 2769, 2444, +2711, 2772, 2462, +2711, 2773, 2481, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2723, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2771, 2430, +2713, 2771, 2430, +2713, 2771, 2430, +2714, 2771, 2430, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2432, +2715, 2770, 2435, +2716, 2769, 2439, +2714, 2769, 2444, +2711, 2772, 2462, +2711, 2773, 2481, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2723, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2771, 2430, +2713, 2771, 2430, +2713, 2771, 2430, +2714, 2771, 2430, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2432, +2715, 2770, 2435, +2716, 2769, 2439, +2714, 2769, 2444, +2711, 2772, 2462, +2711, 2773, 2481, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2723, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2771, 2430, +2713, 2771, 2430, +2713, 2771, 2430, +2714, 2771, 2430, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2432, +2715, 2770, 2435, +2716, 2769, 2439, +2714, 2769, 2444, +2711, 2772, 2462, +2711, 2773, 2481, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2723, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2771, 2430, +2713, 2771, 2430, +2713, 2771, 2430, +2714, 2771, 2430, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2432, +2715, 2770, 2435, +2716, 2769, 2439, +2714, 2769, 2444, +2711, 2772, 2462, +2711, 2773, 2481, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2723, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2771, 2430, +2713, 2771, 2430, +2713, 2771, 2430, +2714, 2771, 2430, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2432, +2715, 2770, 2435, +2716, 2769, 2439, +2714, 2769, 2444, +2711, 2772, 2462, +2711, 2773, 2481, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2723, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2771, 2430, +2713, 2771, 2430, +2713, 2771, 2430, +2714, 2771, 2430, +2714, 2771, 2431, +2714, 2771, 2431, +2714, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2431, +2715, 2771, 2432, +2715, 2770, 2435, +2716, 2769, 2439, +2714, 2769, 2444, +2711, 2772, 2462, +2711, 2773, 2481, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2723, 2785, 2694, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +737, 0, 0, +737, 0, 0, +737, 0, 0, +737, 0, 0, +737, 0, 28, +737, 0, 152, +737, 0, 280, +737, 0, 408, +737, 0, 537, +737, 0, 667, +737, 0, 797, +737, 0, 928, +703, 0, 1088, +438, 0, 1361, +394, 0, 1525, +667, 0, 1634, +977, 0, 1782, +1248, 0, 1893, +1561, 0, 2015, +1525, 291, 2172, +265, 987, 2341, +1385, 462, 2468, +1740, 0, 2504, +1740, 0, 2504, +1740, 0, 2504, +1740, 0, 2504, +1740, 0, 2504, +1740, 0, 2504, +1740, 0, 2504, +1740, 0, 2504, +1740, 0, 2504, +1740, 0, 2504, +734, 0, 0, +736, 0, 0, +736, 0, 0, +736, 0, 0, +736, 0, 36, +736, 0, 159, +736, 0, 285, +736, 0, 412, +736, 0, 540, +736, 0, 669, +736, 0, 799, +736, 0, 930, +697, 0, 1089, +427, 0, 1361, +381, 0, 1525, +669, 0, 1635, +971, 0, 1782, +1248, 0, 1893, +1561, 0, 2015, +1524, 306, 2173, +265, 992, 2341, +1388, 465, 2468, +1740, 0, 2504, +1740, 0, 2504, +1740, 0, 2504, +1740, 0, 2504, +1740, 0, 2504, +1740, 0, 2504, +1740, 0, 2504, +1740, 0, 2504, +1740, 0, 2504, +1740, 0, 2504, +729, 0, 0, +730, 0, 0, +733, 0, 0, +733, 0, 0, +733, 0, 48, +733, 0, 168, +733, 0, 291, +733, 0, 417, +733, 0, 544, +733, 0, 672, +733, 0, 801, +733, 0, 931, +694, 0, 1090, +412, 0, 1362, +365, 0, 1526, +672, 0, 1635, +963, 0, 1782, +1247, 0, 1894, +1560, 0, 2016, +1522, 325, 2173, +265, 998, 2341, +1392, 470, 2468, +1740, 0, 2504, +1740, 0, 2504, +1740, 0, 2504, +1740, 0, 2504, +1740, 0, 2504, +1740, 0, 2504, +1740, 0, 2504, +1740, 0, 2504, +1740, 0, 2504, +1740, 0, 2504, +722, 0, 0, +723, 0, 0, +726, 0, 0, +730, 0, 0, +730, 0, 63, +730, 0, 180, +730, 0, 300, +730, 0, 424, +730, 0, 549, +730, 0, 676, +730, 0, 804, +730, 0, 933, +690, 0, 1091, +391, 0, 1363, +341, 0, 1526, +676, 0, 1636, +953, 0, 1781, +1245, 0, 1894, +1560, 0, 2017, +1519, 349, 2173, +265, 1005, 2342, +1398, 476, 2468, +1739, 0, 2504, +1739, 0, 2504, +1739, 0, 2504, +1739, 0, 2504, +1739, 0, 2504, +1739, 0, 2504, +1739, 0, 2504, +1739, 0, 2504, +1739, 0, 2504, +1739, 0, 2504, +712, 0, 0, +714, 0, 0, +717, 0, 0, +720, 0, 0, +725, 0, 83, +725, 0, 195, +725, 0, 312, +725, 0, 433, +725, 0, 556, +725, 0, 681, +725, 0, 808, +725, 0, 936, +685, 0, 1093, +361, 0, 1364, +307, 0, 1527, +681, 0, 1637, +939, 0, 1781, +1244, 0, 1895, +1559, 0, 2018, +1516, 380, 2173, +265, 1015, 2342, +1405, 484, 2468, +1739, 0, 2505, +1739, 0, 2505, +1739, 0, 2505, +1739, 0, 2505, +1739, 0, 2505, +1739, 0, 2505, +1739, 0, 2505, +1739, 0, 2505, +1739, 0, 2505, +1739, 0, 2505, +699, 0, 0, +701, 0, 0, +704, 0, 0, +708, 0, 0, +712, 0, 83, +719, 0, 215, +719, 0, 327, +719, 0, 444, +719, 0, 564, +719, 0, 688, +719, 0, 813, +719, 0, 940, +678, 0, 1096, +317, 30, 1365, +258, 30, 1528, +688, 0, 1639, +918, 0, 1780, +1242, 0, 1896, +1558, 0, 2019, +1512, 419, 2174, +265, 1028, 2343, +1415, 494, 2468, +1738, 30, 2505, +1738, 30, 2505, +1738, 30, 2505, +1738, 30, 2505, +1738, 30, 2505, +1738, 30, 2505, +1738, 30, 2505, +1738, 30, 2505, +1738, 30, 2505, +1738, 30, 2505, +681, 4, 0, +683, 0, 0, +686, 0, 0, +690, 0, 0, +695, 0, 83, +702, 0, 215, +710, 0, 347, +710, 0, 459, +710, 0, 576, +710, 0, 697, +710, 0, 820, +710, 0, 946, +669, 0, 1100, +251, 163, 1367, +182, 163, 1530, +697, 32, 1641, +890, 0, 1779, +1239, 0, 1897, +1557, 32, 2021, +1506, 465, 2175, +265, 1045, 2344, +1427, 508, 2468, +1737, 163, 2505, +1737, 163, 2505, +1737, 163, 2505, +1737, 163, 2505, +1737, 163, 2505, +1737, 163, 2505, +1737, 163, 2505, +1737, 163, 2505, +1737, 163, 2505, +1737, 163, 2505, +656, 144, 0, +658, 137, 0, +661, 127, 0, +665, 114, 0, +670, 96, 83, +678, 70, 215, +686, 34, 347, +699, 0, 479, +699, 0, 591, +699, 0, 708, +699, 0, 829, +699, 0, 952, +656, 52, 1105, +145, 295, 1370, +56, 295, 1531, +708, 164, 1644, +849, 0, 1778, +1236, 0, 1899, +1555, 164, 2023, +1498, 521, 2175, +265, 1066, 2345, +1443, 526, 2468, +1736, 295, 2505, +1736, 295, 2505, +1736, 295, 2505, +1736, 295, 2505, +1736, 295, 2505, +1736, 295, 2505, +1736, 295, 2505, +1736, 295, 2505, +1736, 295, 2505, +1736, 295, 2505, +620, 281, 0, +623, 276, 0, +626, 269, 0, +630, 259, 0, +636, 246, 83, +643, 227, 215, +653, 202, 347, +666, 166, 479, +683, 111, 611, +683, 111, 723, +683, 111, 840, +683, 111, 961, +639, 167, 1111, +0, 426, 1374, +0, 426, 1534, +723, 296, 1648, +788, 0, 1777, +1231, 111, 1901, +1552, 296, 2027, +1487, 586, 2177, +265, 1093, 2347, +1456, 606, 2469, +1735, 426, 2506, +1735, 426, 2506, +1735, 426, 2506, +1735, 426, 2506, +1735, 426, 2506, +1735, 426, 2506, +1735, 426, 2506, +1735, 426, 2506, +1735, 426, 2506, +1735, 426, 2506, +567, 417, 0, +570, 413, 0, +573, 408, 0, +578, 401, 0, +585, 391, 83, +593, 378, 215, +604, 360, 347, +618, 334, 479, +637, 298, 611, +660, 244, 743, +660, 244, 856, +660, 244, 973, +614, 286, 1119, +0, 536, 1379, +0, 559, 1537, +743, 428, 1653, +797, 104, 1780, +1224, 244, 1904, +1549, 428, 2031, +1472, 660, 2178, +265, 1128, 2349, +1472, 699, 2469, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +1732, 559, 2507, +567, 552, 0, +570, 549, 0, +573, 545, 0, +578, 540, 0, +585, 533, 83, +593, 523, 215, +604, 510, 347, +618, 492, 479, +637, 466, 611, +660, 430, 743, +660, 521, 912, +660, 521, 1017, +614, 545, 1152, +0, 703, 1397, +0, 691, 1550, +743, 597, 1662, +797, 399, 1786, +1238, 422, 1910, +1518, 560, 2039, +1417, 815, 2187, +186, 1169, 2352, +1521, 727, 2469, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +567, 686, 0, +570, 684, 0, +573, 681, 0, +578, 677, 0, +585, 672, 83, +593, 665, 215, +604, 655, 347, +618, 643, 479, +637, 624, 611, +660, 599, 743, +660, 664, 912, +660, 739, 1070, +614, 754, 1192, +0, 860, 1421, +0, 823, 1568, +743, 755, 1675, +797, 625, 1792, +1261, 593, 1918, +1472, 692, 2049, +1331, 963, 2199, +0, 1212, 2357, +1579, 761, 2469, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +569, 854, 85, +559, 854, 130, +563, 852, 185, +568, 850, 248, +574, 846, 322, +583, 841, 404, +594, 835, 496, +608, 826, 594, +627, 814, 700, +651, 797, 811, +651, 841, 960, +651, 893, 1104, +678, 945, 1245, +0, 1017, 1454, +0, 983, 1592, +758, 925, 1697, +804, 857, 1807, +1275, 800, 1931, +1408, 849, 2061, +1203, 1108, 2212, +0, 1254, 2365, +1635, 828, 2469, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +834, 1134, 954, +827, 1134, 961, +819, 1134, 970, +808, 1134, 982, +792, 1134, 998, +770, 1134, 1018, +739, 1134, 1043, +693, 1134, 1075, +625, 1134, 1115, +570, 1131, 1163, +570, 1152, 1237, +570, 1179, 1321, +601, 1208, 1413, +800, 1208, 1514, +767, 1185, 1636, +863, 1174, 1754, +863, 1195, 1861, +1192, 1157, 1970, +1257, 1131, 2078, +1043, 1269, 2229, +975, 1275, 2368, +1616, 1030, 2470, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +857, 1389, 1341, +851, 1389, 1344, +843, 1389, 1348, +832, 1389, 1353, +817, 1389, 1360, +797, 1389, 1369, +767, 1389, 1381, +725, 1389, 1397, +661, 1389, 1417, +559, 1389, 1442, +559, 1389, 1463, +559, 1389, 1491, +591, 1400, 1546, +794, 1400, 1623, +813, 1382, 1691, +874, 1379, 1799, +874, 1408, 1902, +1201, 1371, 2008, +1151, 1350, 2106, +878, 1405, 2245, +1078, 1352, 2375, +1623, 1208, 2472, +1819, 1270, 2510, +1819, 1270, 2510, +1819, 1270, 2510, +1819, 1270, 2510, +1819, 1270, 2510, +1819, 1270, 2510, +1819, 1270, 2510, +1819, 1270, 2510, +1819, 1270, 2510, +1819, 1270, 2510, +1214, 1557, 1667, +1213, 1557, 1668, +1212, 1558, 1669, +1211, 1558, 1670, +1209, 1559, 1672, +1207, 1560, 1674, +1205, 1561, 1677, +1201, 1563, 1681, +1195, 1565, 1686, +1188, 1569, 1694, +1188, 1567, 1706, +1188, 1567, 1722, +1177, 1567, 1744, +1072, 1567, 1776, +1057, 1558, 1825, +1094, 1552, 1894, +1094, 1557, 1981, +1142, 1536, 2063, +1061, 1537, 2170, +810, 1536, 2268, +1232, 1487, 2382, +1680, 1427, 2474, +1839, 1457, 2509, +1839, 1457, 2509, +1839, 1457, 2509, +1839, 1457, 2509, +1839, 1457, 2509, +1839, 1457, 2509, +1839, 1457, 2509, +1839, 1457, 2509, +1839, 1457, 2509, +1839, 1457, 2509, +1512, 1695, 1855, +1511, 1695, 1855, +1510, 1695, 1856, +1508, 1696, 1858, +1505, 1696, 1860, +1502, 1697, 1862, +1497, 1698, 1866, +1491, 1699, 1870, +1482, 1701, 1876, +1478, 1703, 1881, +1478, 1700, 1889, +1478, 1696, 1900, +1475, 1691, 1914, +1446, 1684, 1934, +1440, 1693, 1977, +1405, 1695, 2020, +1418, 1691, 2069, +1312, 1672, 2125, +1209, 1684, 2221, +1248, 1649, 2296, +1541, 1636, 2386, +1794, 1633, 2475, +1900, 1619, 2511, +1900, 1619, 2511, +1900, 1619, 2511, +1900, 1619, 2511, +1900, 1619, 2511, +1900, 1619, 2511, +1900, 1619, 2511, +1900, 1619, 2511, +1900, 1619, 2511, +1900, 1619, 2511, +1813, 1811, 1973, +1812, 1811, 1974, +1812, 1811, 1975, +1811, 1811, 1976, +1810, 1811, 1977, +1809, 1811, 1978, +1808, 1811, 1981, +1806, 1811, 1983, +1803, 1811, 1987, +1799, 1811, 1992, +1795, 1811, 1998, +1789, 1811, 2007, +1779, 1812, 2018, +1767, 1817, 2033, +1749, 1812, 2048, +1751, 1809, 2076, +1717, 1818, 2125, +1722, 1802, 2166, +1667, 1793, 2234, +1699, 1800, 2306, +1776, 1797, 2391, +1871, 1786, 2475, +1978, 1800, 2515, +1978, 1800, 2515, +1978, 1800, 2515, +1978, 1800, 2515, +1978, 1800, 2515, +1978, 1800, 2515, +1978, 1800, 2515, +1978, 1800, 2515, +1978, 1800, 2515, +1978, 1800, 2515, +1972, 1958, 2032, +1972, 1958, 2033, +1971, 1958, 2033, +1971, 1958, 2034, +1970, 1958, 2034, +1969, 1958, 2036, +1968, 1958, 2037, +1967, 1958, 2039, +1965, 1958, 2041, +1962, 1958, 2045, +1961, 1958, 2049, +1958, 1958, 2055, +1955, 1958, 2062, +1947, 1958, 2069, +1940, 1963, 2081, +1937, 1965, 2105, +1931, 1968, 2155, +1905, 1958, 2189, +1920, 1964, 2238, +1898, 1964, 2316, +1934, 1954, 2393, +2043, 1964, 2481, +2108, 1964, 2515, +2108, 1964, 2515, +2108, 1964, 2515, +2108, 1964, 2515, +2108, 1964, 2515, +2108, 1964, 2515, +2108, 1964, 2515, +2108, 1964, 2515, +2108, 1964, 2515, +2108, 1964, 2515, +2123, 2122, 2071, +2123, 2122, 2071, +2123, 2122, 2071, +2123, 2122, 2072, +2124, 2122, 2072, +2124, 2122, 2072, +2124, 2122, 2073, +2125, 2122, 2073, +2125, 2122, 2074, +2126, 2122, 2075, +2126, 2124, 2079, +2126, 2125, 2085, +2125, 2127, 2092, +2119, 2127, 2101, +2119, 2127, 2110, +2122, 2131, 2129, +2118, 2135, 2168, +2110, 2127, 2203, +2114, 2132, 2254, +2126, 2132, 2316, +2148, 2134, 2399, +2218, 2147, 2485, +2259, 2159, 2522, +2259, 2159, 2522, +2259, 2159, 2522, +2259, 2159, 2522, +2259, 2159, 2522, +2259, 2159, 2522, +2259, 2159, 2522, +2259, 2159, 2522, +2259, 2159, 2522, +2259, 2159, 2522, +2370, 2355, 2124, +2370, 2355, 2124, +2370, 2355, 2124, +2370, 2355, 2125, +2370, 2355, 2125, +2370, 2355, 2126, +2371, 2355, 2126, +2371, 2355, 2127, +2371, 2355, 2129, +2372, 2355, 2131, +2371, 2356, 2133, +2372, 2357, 2137, +2372, 2358, 2143, +2371, 2358, 2146, +2369, 2356, 2148, +2370, 2358, 2160, +2373, 2358, 2193, +2373, 2358, 2228, +2377, 2357, 2273, +2391, 2362, 2337, +2412, 2367, 2407, +2466, 2386, 2499, +2496, 2392, 2532, +2496, 2392, 2532, +2496, 2392, 2532, +2496, 2392, 2532, +2496, 2392, 2532, +2496, 2392, 2532, +2496, 2392, 2532, +2496, 2392, 2532, +2496, 2392, 2532, +2496, 2392, 2532, +2680, 2654, 1961, +2680, 2654, 1961, +2680, 2654, 1962, +2680, 2654, 1963, +2680, 2655, 1965, +2680, 2655, 1966, +2681, 2655, 1969, +2681, 2656, 1973, +2681, 2655, 1970, +2680, 2654, 1966, +2680, 2654, 1965, +2679, 2653, 1962, +2679, 2653, 1963, +2678, 2655, 1982, +2677, 2657, 2003, +2678, 2657, 2033, +2676, 2653, 2053, +2678, 2656, 2122, +2681, 2656, 2208, +2688, 2660, 2306, +2695, 2665, 2407, +2715, 2678, 2527, +2724, 2684, 2577, +2724, 2684, 2577, +2724, 2684, 2577, +2724, 2684, 2577, +2724, 2684, 2577, +2724, 2684, 2577, +2724, 2684, 2577, +2724, 2684, 2577, +2724, 2684, 2577, +2724, 2684, 2577, +2713, 2770, 2430, +2713, 2770, 2430, +2713, 2770, 2430, +2713, 2770, 2430, +2713, 2770, 2430, +2714, 2770, 2430, +2714, 2770, 2430, +2714, 2770, 2431, +2715, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2432, +2715, 2770, 2435, +2716, 2769, 2439, +2714, 2769, 2444, +2711, 2772, 2462, +2712, 2773, 2481, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2723, 2785, 2695, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2770, 2430, +2713, 2770, 2430, +2713, 2770, 2430, +2713, 2770, 2430, +2713, 2770, 2430, +2714, 2770, 2430, +2714, 2770, 2430, +2714, 2770, 2431, +2715, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2432, +2715, 2770, 2435, +2716, 2769, 2439, +2714, 2769, 2444, +2711, 2772, 2462, +2712, 2773, 2481, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2723, 2785, 2695, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2770, 2430, +2713, 2770, 2430, +2713, 2770, 2430, +2713, 2770, 2430, +2713, 2770, 2430, +2714, 2770, 2430, +2714, 2770, 2430, +2714, 2770, 2431, +2715, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2432, +2715, 2770, 2435, +2716, 2769, 2439, +2714, 2769, 2444, +2711, 2772, 2462, +2712, 2773, 2481, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2723, 2785, 2695, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2770, 2430, +2713, 2770, 2430, +2713, 2770, 2430, +2713, 2770, 2430, +2713, 2770, 2430, +2714, 2770, 2430, +2714, 2770, 2430, +2714, 2770, 2431, +2715, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2432, +2715, 2770, 2435, +2716, 2769, 2439, +2714, 2769, 2444, +2711, 2772, 2462, +2712, 2773, 2481, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2723, 2785, 2695, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2770, 2430, +2713, 2770, 2430, +2713, 2770, 2430, +2713, 2770, 2430, +2713, 2770, 2430, +2714, 2770, 2430, +2714, 2770, 2430, +2714, 2770, 2431, +2715, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2432, +2715, 2770, 2435, +2716, 2769, 2439, +2714, 2769, 2444, +2711, 2772, 2462, +2712, 2773, 2481, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2723, 2785, 2695, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2770, 2430, +2713, 2770, 2430, +2713, 2770, 2430, +2713, 2770, 2430, +2713, 2770, 2430, +2714, 2770, 2430, +2714, 2770, 2430, +2714, 2770, 2431, +2715, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2432, +2715, 2770, 2435, +2716, 2769, 2439, +2714, 2769, 2444, +2711, 2772, 2462, +2712, 2773, 2481, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2723, 2785, 2695, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2770, 2430, +2713, 2770, 2430, +2713, 2770, 2430, +2713, 2770, 2430, +2713, 2770, 2430, +2714, 2770, 2430, +2714, 2770, 2430, +2714, 2770, 2431, +2715, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2432, +2715, 2770, 2435, +2716, 2769, 2439, +2714, 2769, 2444, +2711, 2772, 2462, +2712, 2773, 2481, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2723, 2785, 2695, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2770, 2430, +2713, 2770, 2430, +2713, 2770, 2430, +2713, 2770, 2430, +2713, 2770, 2430, +2714, 2770, 2430, +2714, 2770, 2430, +2714, 2770, 2431, +2715, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2432, +2715, 2770, 2435, +2716, 2769, 2439, +2714, 2769, 2444, +2711, 2772, 2462, +2712, 2773, 2481, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2723, 2785, 2695, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2770, 2430, +2713, 2770, 2430, +2713, 2770, 2430, +2713, 2770, 2430, +2713, 2770, 2430, +2714, 2770, 2430, +2714, 2770, 2430, +2714, 2770, 2431, +2715, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2432, +2715, 2770, 2435, +2716, 2769, 2439, +2714, 2769, 2444, +2711, 2772, 2462, +2712, 2773, 2481, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2723, 2785, 2695, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2770, 2430, +2713, 2770, 2430, +2713, 2770, 2430, +2713, 2770, 2430, +2713, 2770, 2430, +2714, 2770, 2430, +2714, 2770, 2430, +2714, 2770, 2431, +2715, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2432, +2715, 2770, 2435, +2716, 2769, 2439, +2714, 2769, 2444, +2711, 2772, 2462, +2712, 2773, 2481, +2714, 2774, 2521, +2713, 2773, 2553, +2717, 2777, 2616, +2723, 2785, 2695, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +871, 0, 0, +871, 0, 0, +871, 0, 0, +871, 0, 0, +871, 0, 28, +871, 0, 152, +871, 0, 280, +871, 0, 408, +871, 0, 537, +871, 0, 667, +871, 0, 797, +871, 0, 928, +845, 0, 1088, +668, 0, 1361, +535, 0, 1543, +769, 0, 1643, +1048, 0, 1782, +1313, 0, 1897, +1561, 0, 2018, +1511, 412, 2179, +186, 987, 2341, +1454, 356, 2467, +1743, 0, 2505, +1743, 0, 2505, +1743, 0, 2505, +1743, 0, 2505, +1743, 0, 2505, +1743, 0, 2505, +1743, 0, 2505, +1743, 0, 2505, +1743, 0, 2505, +1743, 0, 2505, +868, 0, 0, +869, 0, 0, +869, 0, 0, +869, 0, 0, +869, 0, 36, +869, 0, 159, +869, 0, 285, +869, 0, 412, +869, 0, 540, +869, 0, 669, +869, 0, 799, +869, 0, 930, +841, 0, 1089, +662, 0, 1361, +526, 0, 1543, +770, 0, 1643, +1043, 0, 1782, +1313, 0, 1897, +1561, 0, 2018, +1510, 423, 2179, +186, 992, 2341, +1457, 360, 2467, +1743, 0, 2505, +1743, 0, 2505, +1743, 0, 2505, +1743, 0, 2505, +1743, 0, 2505, +1743, 0, 2505, +1743, 0, 2505, +1743, 0, 2505, +1743, 0, 2505, +1743, 0, 2505, +864, 0, 0, +866, 0, 0, +868, 0, 0, +868, 0, 0, +868, 0, 48, +868, 0, 168, +868, 0, 291, +868, 0, 417, +868, 0, 544, +868, 0, 672, +868, 0, 801, +868, 0, 931, +839, 0, 1090, +653, 0, 1362, +513, 0, 1544, +773, 0, 1644, +1036, 0, 1782, +1312, 0, 1897, +1560, 0, 2019, +1508, 438, 2179, +186, 998, 2341, +1461, 366, 2467, +1743, 0, 2505, +1743, 0, 2505, +1743, 0, 2505, +1743, 0, 2505, +1743, 0, 2505, +1743, 0, 2505, +1743, 0, 2505, +1743, 0, 2505, +1743, 0, 2505, +1743, 0, 2505, +859, 0, 0, +861, 0, 0, +862, 0, 0, +865, 0, 0, +865, 0, 63, +865, 0, 180, +865, 0, 300, +865, 0, 424, +865, 0, 549, +865, 0, 676, +865, 0, 804, +865, 0, 933, +836, 0, 1091, +640, 0, 1363, +496, 0, 1544, +776, 0, 1645, +1027, 0, 1781, +1311, 0, 1898, +1560, 0, 2020, +1505, 457, 2180, +186, 1005, 2342, +1465, 373, 2467, +1742, 0, 2505, +1742, 0, 2505, +1742, 0, 2505, +1742, 0, 2505, +1742, 0, 2505, +1742, 0, 2505, +1742, 0, 2505, +1742, 0, 2505, +1742, 0, 2505, +1742, 0, 2505, +852, 0, 0, +854, 0, 0, +856, 0, 0, +858, 0, 0, +862, 0, 83, +862, 0, 195, +862, 0, 312, +862, 0, 433, +862, 0, 556, +862, 0, 681, +862, 0, 808, +862, 0, 936, +833, 0, 1093, +623, 0, 1364, +473, 0, 1545, +780, 0, 1646, +1015, 0, 1781, +1310, 0, 1899, +1559, 0, 2021, +1502, 482, 2180, +186, 1015, 2342, +1472, 383, 2467, +1742, 0, 2505, +1742, 0, 2505, +1742, 0, 2505, +1742, 0, 2505, +1742, 0, 2505, +1742, 0, 2505, +1742, 0, 2505, +1742, 0, 2505, +1742, 0, 2505, +1742, 0, 2505, +843, 0, 0, +844, 0, 0, +846, 0, 0, +849, 0, 0, +852, 0, 83, +857, 0, 215, +857, 0, 327, +857, 0, 444, +857, 0, 564, +857, 0, 688, +857, 0, 813, +857, 0, 940, +827, 0, 1096, +599, 30, 1365, +439, 30, 1546, +785, 0, 1648, +998, 0, 1780, +1308, 0, 1900, +1558, 0, 2022, +1497, 512, 2180, +186, 1028, 2343, +1480, 397, 2467, +1741, 30, 2505, +1741, 30, 2505, +1741, 30, 2505, +1741, 30, 2505, +1741, 30, 2505, +1741, 30, 2505, +1741, 30, 2505, +1741, 30, 2505, +1741, 30, 2505, +1741, 30, 2505, +830, 4, 0, +831, 0, 0, +833, 0, 0, +836, 0, 0, +839, 0, 83, +844, 0, 215, +851, 0, 347, +851, 0, 459, +851, 0, 576, +851, 0, 697, +851, 0, 820, +851, 0, 946, +821, 0, 1100, +565, 163, 1367, +390, 163, 1547, +793, 32, 1650, +974, 0, 1779, +1306, 0, 1901, +1557, 32, 2024, +1491, 551, 2181, +186, 1045, 2344, +1491, 413, 2467, +1740, 163, 2506, +1740, 163, 2506, +1740, 163, 2506, +1740, 163, 2506, +1740, 163, 2506, +1740, 163, 2506, +1740, 163, 2506, +1740, 163, 2506, +1740, 163, 2506, +1740, 163, 2506, +812, 144, 0, +813, 137, 0, +815, 127, 0, +818, 114, 0, +822, 96, 83, +827, 70, 215, +834, 34, 347, +842, 0, 479, +842, 0, 591, +842, 0, 708, +842, 0, 829, +842, 0, 952, +812, 52, 1105, +515, 295, 1370, +314, 295, 1549, +802, 164, 1653, +940, 0, 1778, +1302, 0, 1903, +1555, 164, 2027, +1483, 597, 2182, +186, 1066, 2345, +1505, 435, 2467, +1739, 295, 2506, +1739, 295, 2506, +1739, 295, 2506, +1739, 295, 2506, +1739, 295, 2506, +1739, 295, 2506, +1739, 295, 2506, +1739, 295, 2506, +1739, 295, 2506, +1739, 295, 2506, +787, 281, 0, +788, 276, 0, +790, 269, 0, +793, 259, 0, +797, 246, 83, +803, 227, 215, +809, 202, 347, +819, 166, 479, +831, 111, 611, +831, 111, 723, +831, 111, 840, +831, 111, 961, +799, 167, 1111, +438, 426, 1374, +188, 426, 1552, +814, 296, 1657, +891, 0, 1777, +1298, 111, 1905, +1552, 296, 2030, +1472, 653, 2183, +186, 1093, 2347, +1516, 532, 2467, +1738, 426, 2507, +1738, 426, 2507, +1738, 426, 2507, +1738, 426, 2507, +1738, 426, 2507, +1738, 426, 2507, +1738, 426, 2507, +1738, 426, 2507, +1738, 426, 2507, +1738, 426, 2507, +750, 417, 0, +752, 413, 0, +755, 408, 0, +758, 401, 0, +762, 391, 83, +768, 378, 215, +775, 360, 347, +785, 334, 479, +798, 298, 611, +815, 244, 743, +815, 244, 856, +815, 244, 973, +782, 286, 1119, +345, 536, 1379, +0, 559, 1555, +831, 428, 1662, +899, 104, 1780, +1292, 244, 1908, +1549, 428, 2034, +1456, 718, 2185, +186, 1128, 2349, +1530, 640, 2468, +1736, 559, 2508, +1736, 559, 2508, +1736, 559, 2508, +1736, 559, 2508, +1736, 559, 2508, +1736, 559, 2508, +1736, 559, 2508, +1736, 559, 2508, +1736, 559, 2508, +1736, 559, 2508, +697, 552, 0, +699, 549, 0, +702, 545, 0, +705, 540, 0, +710, 533, 83, +717, 523, 215, +725, 510, 347, +736, 492, 479, +750, 466, 611, +769, 430, 743, +792, 376, 875, +792, 376, 988, +758, 407, 1131, +280, 611, 1385, +0, 691, 1559, +799, 583, 1666, +916, 342, 1786, +1257, 324, 1907, +1545, 560, 2040, +1434, 792, 2187, +186, 1169, 2352, +1547, 752, 2469, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +1732, 691, 2509, +697, 686, 0, +699, 684, 0, +702, 681, 0, +705, 677, 0, +710, 672, 83, +717, 665, 215, +725, 655, 347, +736, 643, 479, +750, 624, 611, +769, 599, 743, +792, 562, 875, +792, 654, 1044, +758, 672, 1172, +280, 796, 1409, +0, 823, 1576, +799, 745, 1680, +916, 591, 1792, +1279, 529, 1915, +1502, 692, 2050, +1352, 947, 2199, +0, 1212, 2357, +1603, 785, 2469, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +699, 854, 85, +691, 854, 130, +694, 852, 185, +698, 850, 248, +702, 846, 322, +709, 841, 404, +717, 835, 496, +728, 826, 594, +743, 814, 700, +762, 797, 811, +786, 774, 927, +786, 834, 1081, +805, 893, 1228, +403, 973, 1443, +0, 983, 1599, +812, 918, 1701, +921, 837, 1807, +1293, 760, 1928, +1442, 849, 2062, +1230, 1096, 2212, +0, 1254, 2365, +1657, 848, 2469, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +910, 1134, 954, +905, 1134, 961, +898, 1134, 970, +889, 1134, 982, +875, 1134, 998, +857, 1134, 1018, +832, 1134, 1043, +795, 1134, 1075, +741, 1134, 1115, +699, 1131, 1163, +726, 1120, 1220, +726, 1149, 1307, +748, 1179, 1402, +901, 1179, 1504, +767, 1185, 1644, +906, 1170, 1757, +968, 1186, 1861, +1214, 1140, 1967, +1304, 1131, 2079, +1082, 1261, 2229, +975, 1275, 2368, +1638, 1044, 2470, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +993, 1376, 1327, +989, 1376, 1330, +983, 1376, 1334, +975, 1376, 1340, +964, 1376, 1347, +949, 1376, 1356, +928, 1376, 1368, +899, 1376, 1385, +857, 1376, 1405, +793, 1376, 1431, +691, 1376, 1463, +691, 1376, 1491, +715, 1388, 1546, +877, 1388, 1623, +945, 1376, 1697, +997, 1370, 1804, +1006, 1396, 1906, +1223, 1377, 2010, +1151, 1350, 2105, +878, 1405, 2247, +1167, 1339, 2373, +1626, 1218, 2473, +1826, 1254, 2510, +1826, 1254, 2510, +1826, 1254, 2510, +1826, 1254, 2510, +1826, 1254, 2510, +1826, 1254, 2510, +1826, 1254, 2510, +1826, 1254, 2510, +1826, 1254, 2510, +1826, 1254, 2510, +1284, 1548, 1666, +1284, 1549, 1666, +1283, 1549, 1667, +1282, 1550, 1668, +1281, 1550, 1670, +1279, 1551, 1673, +1276, 1553, 1675, +1273, 1555, 1680, +1269, 1557, 1685, +1263, 1560, 1692, +1239, 1562, 1707, +1239, 1562, 1723, +1229, 1562, 1745, +1136, 1562, 1777, +1127, 1554, 1826, +1162, 1550, 1897, +1168, 1552, 1984, +1181, 1539, 2065, +1075, 1537, 2169, +810, 1538, 2270, +1285, 1479, 2381, +1681, 1429, 2475, +1842, 1448, 2509, +1842, 1448, 2509, +1842, 1448, 2509, +1842, 1448, 2509, +1842, 1448, 2509, +1842, 1448, 2509, +1842, 1448, 2509, +1842, 1448, 2509, +1842, 1448, 2509, +1842, 1448, 2509, +1553, 1689, 1859, +1552, 1689, 1860, +1551, 1689, 1861, +1549, 1690, 1862, +1547, 1690, 1864, +1544, 1691, 1867, +1539, 1692, 1870, +1534, 1693, 1874, +1526, 1695, 1880, +1522, 1697, 1885, +1517, 1700, 1891, +1517, 1696, 1902, +1515, 1691, 1916, +1488, 1684, 1935, +1461, 1690, 1974, +1430, 1693, 2019, +1446, 1691, 2070, +1360, 1672, 2128, +1236, 1684, 2221, +1248, 1653, 2296, +1559, 1632, 2386, +1794, 1630, 2475, +1898, 1615, 2511, +1898, 1615, 2511, +1898, 1615, 2511, +1898, 1615, 2511, +1898, 1615, 2511, +1898, 1615, 2511, +1898, 1615, 2511, +1898, 1615, 2511, +1898, 1615, 2511, +1898, 1615, 2511, +1821, 1809, 1972, +1820, 1809, 1972, +1820, 1809, 1973, +1819, 1809, 1974, +1818, 1809, 1975, +1817, 1809, 1977, +1816, 1809, 1979, +1813, 1809, 1982, +1811, 1809, 1986, +1807, 1809, 1990, +1800, 1811, 1998, +1793, 1811, 2007, +1784, 1811, 2018, +1772, 1817, 2033, +1754, 1811, 2049, +1756, 1809, 2076, +1721, 1816, 2124, +1728, 1804, 2168, +1675, 1795, 2234, +1712, 1800, 2308, +1779, 1799, 2391, +1880, 1789, 2475, +1982, 1798, 2515, +1982, 1798, 2515, +1982, 1798, 2515, +1982, 1798, 2515, +1982, 1798, 2515, +1982, 1798, 2515, +1982, 1798, 2515, +1982, 1798, 2515, +1982, 1798, 2515, +1982, 1798, 2515, +1977, 1958, 2034, +1977, 1958, 2034, +1976, 1958, 2035, +1976, 1958, 2035, +1975, 1958, 2036, +1974, 1958, 2037, +1973, 1958, 2038, +1972, 1958, 2040, +1970, 1958, 2043, +1968, 1958, 2046, +1964, 1958, 2050, +1962, 1958, 2056, +1959, 1958, 2063, +1950, 1958, 2070, +1942, 1961, 2081, +1940, 1963, 2103, +1935, 1966, 2152, +1912, 1959, 2190, +1920, 1962, 2236, +1904, 1962, 2314, +1936, 1954, 2394, +2043, 1964, 2481, +2112, 1962, 2514, +2112, 1962, 2514, +2112, 1962, 2514, +2112, 1962, 2514, +2112, 1962, 2514, +2112, 1962, 2514, +2112, 1962, 2514, +2112, 1962, 2514, +2112, 1962, 2514, +2112, 1962, 2514, +2124, 2124, 2073, +2124, 2124, 2073, +2124, 2124, 2073, +2125, 2124, 2073, +2125, 2124, 2073, +2125, 2124, 2074, +2125, 2124, 2074, +2126, 2124, 2075, +2126, 2124, 2076, +2127, 2124, 2076, +2129, 2124, 2078, +2129, 2125, 2083, +2128, 2127, 2090, +2122, 2127, 2100, +2119, 2127, 2110, +2123, 2131, 2129, +2120, 2135, 2167, +2113, 2128, 2205, +2115, 2130, 2253, +2128, 2131, 2316, +2148, 2135, 2400, +2220, 2148, 2485, +2258, 2159, 2521, +2258, 2159, 2521, +2258, 2159, 2521, +2258, 2159, 2521, +2258, 2159, 2521, +2258, 2159, 2521, +2258, 2159, 2521, +2258, 2159, 2521, +2258, 2159, 2521, +2258, 2159, 2521, +2370, 2355, 2124, +2370, 2355, 2124, +2370, 2355, 2124, +2370, 2355, 2125, +2370, 2355, 2125, +2370, 2355, 2126, +2371, 2355, 2126, +2371, 2355, 2127, +2371, 2355, 2129, +2372, 2355, 2131, +2372, 2355, 2133, +2373, 2356, 2137, +2374, 2357, 2143, +2372, 2357, 2146, +2369, 2356, 2148, +2370, 2358, 2159, +2374, 2358, 2192, +2374, 2358, 2228, +2379, 2358, 2273, +2393, 2364, 2337, +2413, 2367, 2408, +2467, 2387, 2498, +2496, 2393, 2533, +2496, 2393, 2533, +2496, 2393, 2533, +2496, 2393, 2533, +2496, 2393, 2533, +2496, 2393, 2533, +2496, 2393, 2533, +2496, 2393, 2533, +2496, 2393, 2533, +2496, 2393, 2533, +2680, 2654, 1959, +2680, 2654, 1959, +2680, 2654, 1960, +2680, 2654, 1961, +2680, 2654, 1963, +2680, 2655, 1965, +2680, 2655, 1968, +2680, 2655, 1971, +2680, 2655, 1969, +2680, 2654, 1965, +2679, 2653, 1959, +2679, 2652, 1957, +2678, 2652, 1958, +2678, 2654, 1977, +2677, 2657, 1996, +2678, 2657, 2031, +2677, 2654, 2057, +2678, 2657, 2122, +2682, 2656, 2208, +2688, 2660, 2307, +2695, 2665, 2407, +2715, 2678, 2527, +2725, 2684, 2578, +2725, 2684, 2578, +2725, 2684, 2578, +2725, 2684, 2578, +2725, 2684, 2578, +2725, 2684, 2578, +2725, 2684, 2578, +2725, 2684, 2578, +2725, 2684, 2578, +2725, 2684, 2578, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2430, +2713, 2770, 2430, +2714, 2770, 2430, +2714, 2770, 2430, +2715, 2770, 2430, +2715, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2432, +2716, 2770, 2435, +2716, 2769, 2439, +2714, 2770, 2444, +2711, 2772, 2462, +2712, 2773, 2483, +2714, 2775, 2522, +2712, 2773, 2553, +2717, 2777, 2616, +2724, 2786, 2697, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2430, +2713, 2770, 2430, +2714, 2770, 2430, +2714, 2770, 2430, +2715, 2770, 2430, +2715, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2432, +2716, 2770, 2435, +2716, 2769, 2439, +2714, 2770, 2444, +2711, 2772, 2462, +2712, 2773, 2483, +2714, 2775, 2522, +2712, 2773, 2553, +2717, 2777, 2616, +2724, 2786, 2697, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2430, +2713, 2770, 2430, +2714, 2770, 2430, +2714, 2770, 2430, +2715, 2770, 2430, +2715, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2432, +2716, 2770, 2435, +2716, 2769, 2439, +2714, 2770, 2444, +2711, 2772, 2462, +2712, 2773, 2483, +2714, 2775, 2522, +2712, 2773, 2553, +2717, 2777, 2616, +2724, 2786, 2697, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2430, +2713, 2770, 2430, +2714, 2770, 2430, +2714, 2770, 2430, +2715, 2770, 2430, +2715, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2432, +2716, 2770, 2435, +2716, 2769, 2439, +2714, 2770, 2444, +2711, 2772, 2462, +2712, 2773, 2483, +2714, 2775, 2522, +2712, 2773, 2553, +2717, 2777, 2616, +2724, 2786, 2697, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2430, +2713, 2770, 2430, +2714, 2770, 2430, +2714, 2770, 2430, +2715, 2770, 2430, +2715, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2432, +2716, 2770, 2435, +2716, 2769, 2439, +2714, 2770, 2444, +2711, 2772, 2462, +2712, 2773, 2483, +2714, 2775, 2522, +2712, 2773, 2553, +2717, 2777, 2616, +2724, 2786, 2697, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2430, +2713, 2770, 2430, +2714, 2770, 2430, +2714, 2770, 2430, +2715, 2770, 2430, +2715, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2432, +2716, 2770, 2435, +2716, 2769, 2439, +2714, 2770, 2444, +2711, 2772, 2462, +2712, 2773, 2483, +2714, 2775, 2522, +2712, 2773, 2553, +2717, 2777, 2616, +2724, 2786, 2697, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2430, +2713, 2770, 2430, +2714, 2770, 2430, +2714, 2770, 2430, +2715, 2770, 2430, +2715, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2432, +2716, 2770, 2435, +2716, 2769, 2439, +2714, 2770, 2444, +2711, 2772, 2462, +2712, 2773, 2483, +2714, 2775, 2522, +2712, 2773, 2553, +2717, 2777, 2616, +2724, 2786, 2697, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2430, +2713, 2770, 2430, +2714, 2770, 2430, +2714, 2770, 2430, +2715, 2770, 2430, +2715, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2432, +2716, 2770, 2435, +2716, 2769, 2439, +2714, 2770, 2444, +2711, 2772, 2462, +2712, 2773, 2483, +2714, 2775, 2522, +2712, 2773, 2553, +2717, 2777, 2616, +2724, 2786, 2697, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2430, +2713, 2770, 2430, +2714, 2770, 2430, +2714, 2770, 2430, +2715, 2770, 2430, +2715, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2432, +2716, 2770, 2435, +2716, 2769, 2439, +2714, 2770, 2444, +2711, 2772, 2462, +2712, 2773, 2483, +2714, 2775, 2522, +2712, 2773, 2553, +2717, 2777, 2616, +2724, 2786, 2697, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2430, +2713, 2770, 2430, +2714, 2770, 2430, +2714, 2770, 2430, +2715, 2770, 2430, +2715, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2431, +2716, 2770, 2432, +2716, 2770, 2435, +2716, 2769, 2439, +2714, 2770, 2444, +2711, 2772, 2462, +2712, 2773, 2483, +2714, 2775, 2522, +2712, 2773, 2553, +2717, 2777, 2616, +2724, 2786, 2697, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +1004, 0, 0, +1004, 0, 0, +1004, 0, 0, +1004, 0, 0, +1004, 0, 28, +1004, 0, 152, +1004, 0, 280, +1004, 0, 408, +1004, 0, 537, +1004, 0, 667, +1004, 0, 797, +1004, 0, 928, +985, 0, 1088, +862, 0, 1361, +674, 0, 1566, +856, 0, 1661, +1128, 0, 1782, +1394, 0, 1902, +1561, 0, 2022, +1491, 535, 2188, +220, 987, 2343, +1533, 158, 2465, +1747, 0, 2505, +1747, 0, 2505, +1747, 0, 2505, +1747, 0, 2505, +1747, 0, 2505, +1747, 0, 2505, +1747, 0, 2505, +1747, 0, 2505, +1747, 0, 2505, +1747, 0, 2505, +1002, 0, 0, +1003, 0, 0, +1003, 0, 0, +1003, 0, 0, +1003, 0, 36, +1003, 0, 159, +1003, 0, 285, +1003, 0, 412, +1003, 0, 540, +1003, 0, 669, +1003, 0, 799, +1003, 0, 930, +982, 0, 1089, +858, 0, 1361, +667, 0, 1566, +858, 0, 1662, +1124, 0, 1782, +1393, 0, 1903, +1561, 0, 2022, +1490, 544, 2188, +220, 992, 2343, +1536, 164, 2465, +1747, 0, 2505, +1747, 0, 2505, +1747, 0, 2505, +1747, 0, 2505, +1747, 0, 2505, +1747, 0, 2505, +1747, 0, 2505, +1747, 0, 2505, +1747, 0, 2505, +1747, 0, 2505, +999, 0, 0, +1000, 0, 0, +1002, 0, 0, +1002, 0, 0, +1002, 0, 48, +1002, 0, 168, +1002, 0, 291, +1002, 0, 417, +1002, 0, 544, +1002, 0, 672, +1002, 0, 801, +1002, 0, 931, +981, 0, 1090, +852, 0, 1362, +658, 0, 1567, +860, 0, 1662, +1118, 0, 1782, +1393, 0, 1903, +1560, 0, 2023, +1488, 556, 2188, +220, 998, 2343, +1539, 173, 2465, +1747, 0, 2505, +1747, 0, 2505, +1747, 0, 2505, +1747, 0, 2505, +1747, 0, 2505, +1747, 0, 2505, +1747, 0, 2505, +1747, 0, 2505, +1747, 0, 2505, +1747, 0, 2505, +996, 0, 0, +996, 0, 0, +998, 0, 0, +1000, 0, 0, +1000, 0, 63, +1000, 0, 180, +1000, 0, 300, +1000, 0, 424, +1000, 0, 549, +1000, 0, 676, +1000, 0, 804, +1000, 0, 933, +979, 0, 1091, +844, 0, 1363, +645, 0, 1567, +862, 0, 1663, +1110, 0, 1781, +1392, 0, 1903, +1560, 0, 2024, +1486, 570, 2188, +220, 1005, 2344, +1543, 185, 2465, +1746, 0, 2505, +1746, 0, 2505, +1746, 0, 2505, +1746, 0, 2505, +1746, 0, 2505, +1746, 0, 2505, +1746, 0, 2505, +1746, 0, 2505, +1746, 0, 2505, +1746, 0, 2505, +990, 0, 0, +991, 0, 0, +993, 0, 0, +995, 0, 0, +997, 0, 83, +997, 0, 195, +997, 0, 312, +997, 0, 433, +997, 0, 556, +997, 0, 681, +997, 0, 808, +997, 0, 936, +976, 0, 1093, +833, 0, 1364, +629, 0, 1568, +866, 0, 1664, +1100, 0, 1781, +1391, 0, 1904, +1559, 0, 2025, +1482, 590, 2189, +220, 1015, 2344, +1548, 200, 2465, +1746, 0, 2506, +1746, 0, 2506, +1746, 0, 2506, +1746, 0, 2506, +1746, 0, 2506, +1746, 0, 2506, +1746, 0, 2506, +1746, 0, 2506, +1746, 0, 2506, +1746, 0, 2506, +983, 0, 0, +985, 0, 0, +986, 0, 0, +988, 0, 0, +991, 0, 83, +994, 0, 215, +994, 0, 327, +994, 0, 444, +994, 0, 564, +994, 0, 688, +994, 0, 813, +994, 0, 940, +973, 0, 1096, +819, 30, 1365, +605, 30, 1569, +871, 0, 1666, +1086, 0, 1780, +1390, 0, 1905, +1558, 0, 2026, +1477, 614, 2189, +220, 1028, 2345, +1555, 219, 2465, +1745, 30, 2506, +1745, 30, 2506, +1745, 30, 2506, +1745, 30, 2506, +1745, 30, 2506, +1745, 30, 2506, +1745, 30, 2506, +1745, 30, 2506, +1745, 30, 2506, +1745, 30, 2506, +974, 4, 0, +975, 0, 0, +977, 0, 0, +979, 0, 0, +981, 0, 83, +985, 0, 215, +989, 0, 347, +989, 0, 459, +989, 0, 576, +989, 0, 697, +989, 0, 820, +989, 0, 946, +968, 0, 1100, +798, 163, 1367, +571, 163, 1570, +876, 32, 1668, +1067, 0, 1779, +1388, 0, 1906, +1557, 32, 2028, +1471, 645, 2190, +220, 1045, 2346, +1564, 244, 2465, +1744, 163, 2506, +1744, 163, 2506, +1744, 163, 2506, +1744, 163, 2506, +1744, 163, 2506, +1744, 163, 2506, +1744, 163, 2506, +1744, 163, 2506, +1744, 163, 2506, +1744, 163, 2506, +961, 144, 0, +962, 137, 0, +963, 127, 0, +966, 114, 0, +968, 96, 83, +972, 70, 215, +977, 34, 347, +983, 0, 479, +983, 0, 591, +983, 0, 708, +983, 0, 829, +983, 0, 952, +961, 52, 1105, +769, 295, 1370, +522, 295, 1572, +884, 164, 1671, +1039, 0, 1778, +1385, 0, 1908, +1555, 164, 2031, +1462, 683, 2191, +220, 1066, 2347, +1576, 275, 2465, +1743, 295, 2507, +1743, 295, 2507, +1743, 295, 2507, +1743, 295, 2507, +1743, 295, 2507, +1743, 295, 2507, +1743, 295, 2507, +1743, 295, 2507, +1743, 295, 2507, +1743, 295, 2507, +943, 281, 0, +944, 276, 0, +946, 269, 0, +948, 259, 0, +951, 246, 83, +955, 227, 215, +959, 202, 347, +966, 166, 479, +975, 111, 611, +975, 111, 723, +975, 111, 840, +975, 111, 961, +952, 167, 1111, +726, 426, 1374, +446, 426, 1574, +895, 296, 1674, +1000, 0, 1777, +1382, 111, 1910, +1552, 296, 2034, +1450, 729, 2192, +220, 1093, 2349, +1586, 407, 2466, +1741, 426, 2508, +1741, 426, 2508, +1741, 426, 2508, +1741, 426, 2508, +1741, 426, 2508, +1741, 426, 2508, +1741, 426, 2508, +1741, 426, 2508, +1741, 426, 2508, +1741, 426, 2508, +917, 417, 0, +919, 413, 0, +920, 408, 0, +923, 401, 0, +926, 391, 83, +930, 378, 215, +935, 360, 347, +942, 334, 479, +951, 298, 611, +963, 244, 743, +963, 244, 856, +963, 244, 973, +940, 286, 1119, +679, 536, 1379, +320, 559, 1577, +908, 428, 1679, +1006, 104, 1780, +1377, 244, 1913, +1549, 428, 2038, +1434, 785, 2194, +220, 1128, 2351, +1598, 544, 2467, +1739, 559, 2508, +1739, 559, 2508, +1739, 559, 2508, +1739, 559, 2508, +1739, 559, 2508, +1739, 559, 2508, +1739, 559, 2508, +1739, 559, 2508, +1739, 559, 2508, +1739, 559, 2508, +881, 552, 0, +883, 549, 0, +884, 545, 0, +887, 540, 0, +890, 533, 83, +894, 523, 215, +900, 510, 347, +908, 492, 479, +917, 466, 611, +930, 430, 743, +947, 376, 875, +947, 376, 988, +923, 407, 1131, +649, 611, 1385, +67, 691, 1581, +882, 583, 1684, +1020, 342, 1786, +1348, 324, 1912, +1545, 560, 2044, +1411, 850, 2196, +220, 1169, 2354, +1613, 680, 2468, +1736, 691, 2509, +1736, 691, 2509, +1736, 691, 2509, +1736, 691, 2509, +1736, 691, 2509, +1736, 691, 2509, +1736, 691, 2509, +1736, 691, 2509, +1736, 691, 2509, +1736, 691, 2509, +828, 686, 0, +829, 684, 0, +831, 681, 0, +834, 677, 0, +838, 672, 83, +842, 665, 215, +849, 655, 347, +857, 643, 479, +868, 624, 611, +883, 599, 743, +901, 562, 875, +925, 508, 1007, +899, 532, 1145, +605, 694, 1393, +0, 823, 1587, +799, 745, 1688, +1039, 540, 1792, +1299, 403, 1909, +1539, 692, 2052, +1379, 925, 2199, +0, 1212, 2357, +1633, 815, 2469, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +1732, 823, 2511, +829, 854, 85, +823, 854, 130, +825, 852, 185, +828, 850, 248, +832, 846, 322, +837, 841, 404, +843, 835, 496, +852, 826, 594, +863, 814, 700, +877, 797, 811, +896, 774, 927, +920, 741, 1047, +934, 812, 1203, +669, 906, 1428, +0, 983, 1610, +812, 918, 1709, +1043, 809, 1807, +1313, 689, 1923, +1484, 849, 2064, +1265, 1080, 2212, +0, 1254, 2365, +1683, 875, 2469, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +996, 1134, 954, +992, 1134, 961, +986, 1134, 970, +979, 1134, 982, +968, 1134, 998, +953, 1134, 1018, +932, 1134, 1043, +903, 1134, 1075, +861, 1134, 1115, +829, 1131, 1163, +850, 1120, 1220, +876, 1105, 1286, +892, 1138, 1385, +1008, 1138, 1491, +767, 1185, 1653, +906, 1170, 1765, +1078, 1173, 1861, +1237, 1110, 1962, +1360, 1131, 2081, +1129, 1250, 2229, +975, 1275, 2368, +1666, 1061, 2470, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1129, 1359, 1308, +1126, 1359, 1311, +1121, 1359, 1315, +1115, 1359, 1321, +1107, 1359, 1328, +1097, 1359, 1338, +1082, 1359, 1351, +1061, 1359, 1367, +1032, 1359, 1389, +989, 1359, 1416, +926, 1359, 1449, +823, 1359, 1491, +841, 1371, 1546, +969, 1371, 1623, +1077, 1367, 1705, +1117, 1361, 1811, +1138, 1380, 1911, +1246, 1386, 2012, +1151, 1350, 2103, +878, 1405, 2249, +1204, 1332, 2374, +1631, 1230, 2474, +1835, 1230, 2510, +1835, 1230, 2510, +1835, 1230, 2510, +1835, 1230, 2510, +1835, 1230, 2510, +1835, 1230, 2510, +1835, 1230, 2510, +1835, 1230, 2510, +1835, 1230, 2510, +1835, 1230, 2510, +1361, 1536, 1656, +1360, 1537, 1657, +1360, 1537, 1658, +1359, 1538, 1659, +1358, 1539, 1661, +1356, 1540, 1663, +1354, 1541, 1667, +1351, 1543, 1671, +1347, 1545, 1676, +1342, 1549, 1684, +1323, 1550, 1699, +1283, 1550, 1723, +1274, 1550, 1745, +1190, 1550, 1777, +1220, 1548, 1833, +1249, 1544, 1903, +1265, 1540, 1988, +1206, 1545, 2067, +1075, 1537, 2167, +810, 1538, 2272, +1313, 1474, 2382, +1686, 1437, 2475, +1851, 1433, 2509, +1851, 1433, 2509, +1851, 1433, 2509, +1851, 1433, 2509, +1851, 1433, 2509, +1851, 1433, 2509, +1851, 1433, 2509, +1851, 1433, 2509, +1851, 1433, 2509, +1851, 1433, 2509, +1603, 1680, 1865, +1602, 1680, 1865, +1600, 1680, 1867, +1599, 1681, 1868, +1597, 1681, 1870, +1594, 1682, 1872, +1590, 1683, 1876, +1585, 1684, 1880, +1578, 1686, 1886, +1575, 1689, 1891, +1571, 1692, 1897, +1565, 1696, 1905, +1563, 1691, 1919, +1538, 1684, 1938, +1489, 1686, 1969, +1460, 1689, 2014, +1482, 1691, 2072, +1418, 1672, 2133, +1270, 1684, 2221, +1248, 1657, 2296, +1563, 1627, 2386, +1794, 1625, 2476, +1896, 1610, 2511, +1896, 1610, 2511, +1896, 1610, 2511, +1896, 1610, 2511, +1896, 1610, 2511, +1896, 1610, 2511, +1896, 1610, 2511, +1896, 1610, 2511, +1896, 1610, 2511, +1896, 1610, 2511, +1830, 1805, 1969, +1830, 1805, 1970, +1829, 1805, 1971, +1829, 1805, 1972, +1828, 1805, 1973, +1827, 1805, 1974, +1825, 1805, 1977, +1823, 1805, 1979, +1821, 1805, 1983, +1817, 1805, 1988, +1810, 1807, 1996, +1800, 1811, 2007, +1791, 1811, 2018, +1779, 1817, 2033, +1762, 1811, 2051, +1763, 1809, 2078, +1725, 1813, 2122, +1736, 1807, 2171, +1689, 1798, 2234, +1727, 1800, 2309, +1778, 1800, 2391, +1894, 1792, 2475, +1986, 1795, 2515, +1986, 1795, 2515, +1986, 1795, 2515, +1986, 1795, 2515, +1986, 1795, 2515, +1986, 1795, 2515, +1986, 1795, 2515, +1986, 1795, 2515, +1986, 1795, 2515, +1986, 1795, 2515, +1983, 1958, 2036, +1983, 1958, 2036, +1983, 1958, 2037, +1983, 1958, 2037, +1982, 1958, 2038, +1981, 1958, 2039, +1980, 1958, 2040, +1979, 1958, 2042, +1977, 1958, 2045, +1974, 1958, 2048, +1971, 1958, 2052, +1966, 1958, 2058, +1963, 1958, 2065, +1955, 1958, 2072, +1945, 1959, 2081, +1942, 1961, 2103, +1940, 1963, 2147, +1922, 1962, 2193, +1920, 1960, 2233, +1912, 1960, 2312, +1943, 1954, 2394, +2043, 1964, 2481, +2119, 1960, 2514, +2119, 1960, 2514, +2119, 1960, 2514, +2119, 1960, 2514, +2119, 1960, 2514, +2119, 1960, 2514, +2119, 1960, 2514, +2119, 1960, 2514, +2119, 1960, 2514, +2119, 1960, 2514, +2126, 2125, 2075, +2126, 2125, 2075, +2126, 2125, 2075, +2126, 2125, 2075, +2126, 2125, 2075, +2127, 2125, 2076, +2127, 2125, 2076, +2127, 2125, 2076, +2128, 2125, 2077, +2129, 2125, 2078, +2130, 2125, 2080, +2132, 2125, 2082, +2131, 2127, 2089, +2125, 2127, 2098, +2119, 2127, 2110, +2123, 2131, 2129, +2124, 2135, 2165, +2118, 2130, 2208, +2117, 2129, 2251, +2132, 2129, 2316, +2154, 2135, 2400, +2222, 2149, 2485, +2257, 2159, 2521, +2257, 2159, 2521, +2257, 2159, 2521, +2257, 2159, 2521, +2257, 2159, 2521, +2257, 2159, 2521, +2257, 2159, 2521, +2257, 2159, 2521, +2257, 2159, 2521, +2257, 2159, 2521, +2371, 2355, 2125, +2371, 2355, 2125, +2371, 2355, 2125, +2371, 2355, 2126, +2372, 2355, 2126, +2372, 2355, 2127, +2372, 2355, 2127, +2372, 2355, 2128, +2372, 2355, 2130, +2373, 2355, 2132, +2374, 2355, 2134, +2374, 2355, 2136, +2375, 2356, 2142, +2373, 2356, 2145, +2371, 2355, 2148, +2372, 2357, 2159, +2375, 2358, 2191, +2375, 2358, 2229, +2381, 2358, 2273, +2396, 2366, 2336, +2413, 2367, 2408, +2468, 2388, 2498, +2497, 2394, 2532, +2497, 2394, 2532, +2497, 2394, 2532, +2497, 2394, 2532, +2497, 2394, 2532, +2497, 2394, 2532, +2497, 2394, 2532, +2497, 2394, 2532, +2497, 2394, 2532, +2497, 2394, 2532, +2679, 2653, 1956, +2679, 2653, 1957, +2679, 2653, 1958, +2679, 2654, 1959, +2679, 2654, 1961, +2680, 2654, 1962, +2680, 2654, 1965, +2680, 2655, 1969, +2680, 2654, 1966, +2679, 2653, 1962, +2679, 2652, 1957, +2678, 2651, 1950, +2678, 2650, 1950, +2677, 2652, 1970, +2676, 2657, 1988, +2678, 2657, 2023, +2679, 2655, 2063, +2679, 2657, 2122, +2682, 2656, 2208, +2688, 2660, 2308, +2695, 2665, 2407, +2715, 2678, 2527, +2726, 2684, 2578, +2726, 2684, 2578, +2726, 2684, 2578, +2726, 2684, 2578, +2726, 2684, 2578, +2726, 2684, 2578, +2726, 2684, 2578, +2726, 2684, 2578, +2726, 2684, 2578, +2726, 2684, 2578, +2712, 2770, 2428, +2712, 2770, 2429, +2712, 2770, 2429, +2712, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2714, 2770, 2429, +2714, 2770, 2430, +2715, 2770, 2430, +2716, 2770, 2431, +2717, 2770, 2431, +2717, 2770, 2432, +2716, 2770, 2435, +2716, 2769, 2439, +2714, 2770, 2444, +2711, 2772, 2462, +2713, 2774, 2488, +2714, 2775, 2522, +2712, 2773, 2553, +2717, 2777, 2617, +2724, 2787, 2699, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2712, 2770, 2428, +2712, 2770, 2429, +2712, 2770, 2429, +2712, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2714, 2770, 2429, +2714, 2770, 2430, +2715, 2770, 2430, +2716, 2770, 2431, +2717, 2770, 2431, +2717, 2770, 2432, +2716, 2770, 2435, +2716, 2769, 2439, +2714, 2770, 2444, +2711, 2772, 2462, +2713, 2774, 2488, +2714, 2775, 2522, +2712, 2773, 2553, +2717, 2777, 2617, +2724, 2787, 2699, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2712, 2770, 2428, +2712, 2770, 2429, +2712, 2770, 2429, +2712, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2714, 2770, 2429, +2714, 2770, 2430, +2715, 2770, 2430, +2716, 2770, 2431, +2717, 2770, 2431, +2717, 2770, 2432, +2716, 2770, 2435, +2716, 2769, 2439, +2714, 2770, 2444, +2711, 2772, 2462, +2713, 2774, 2488, +2714, 2775, 2522, +2712, 2773, 2553, +2717, 2777, 2617, +2724, 2787, 2699, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2712, 2770, 2428, +2712, 2770, 2429, +2712, 2770, 2429, +2712, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2714, 2770, 2429, +2714, 2770, 2430, +2715, 2770, 2430, +2716, 2770, 2431, +2717, 2770, 2431, +2717, 2770, 2432, +2716, 2770, 2435, +2716, 2769, 2439, +2714, 2770, 2444, +2711, 2772, 2462, +2713, 2774, 2488, +2714, 2775, 2522, +2712, 2773, 2553, +2717, 2777, 2617, +2724, 2787, 2699, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2712, 2770, 2428, +2712, 2770, 2429, +2712, 2770, 2429, +2712, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2714, 2770, 2429, +2714, 2770, 2430, +2715, 2770, 2430, +2716, 2770, 2431, +2717, 2770, 2431, +2717, 2770, 2432, +2716, 2770, 2435, +2716, 2769, 2439, +2714, 2770, 2444, +2711, 2772, 2462, +2713, 2774, 2488, +2714, 2775, 2522, +2712, 2773, 2553, +2717, 2777, 2617, +2724, 2787, 2699, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2712, 2770, 2428, +2712, 2770, 2429, +2712, 2770, 2429, +2712, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2714, 2770, 2429, +2714, 2770, 2430, +2715, 2770, 2430, +2716, 2770, 2431, +2717, 2770, 2431, +2717, 2770, 2432, +2716, 2770, 2435, +2716, 2769, 2439, +2714, 2770, 2444, +2711, 2772, 2462, +2713, 2774, 2488, +2714, 2775, 2522, +2712, 2773, 2553, +2717, 2777, 2617, +2724, 2787, 2699, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2712, 2770, 2428, +2712, 2770, 2429, +2712, 2770, 2429, +2712, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2714, 2770, 2429, +2714, 2770, 2430, +2715, 2770, 2430, +2716, 2770, 2431, +2717, 2770, 2431, +2717, 2770, 2432, +2716, 2770, 2435, +2716, 2769, 2439, +2714, 2770, 2444, +2711, 2772, 2462, +2713, 2774, 2488, +2714, 2775, 2522, +2712, 2773, 2553, +2717, 2777, 2617, +2724, 2787, 2699, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2712, 2770, 2428, +2712, 2770, 2429, +2712, 2770, 2429, +2712, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2714, 2770, 2429, +2714, 2770, 2430, +2715, 2770, 2430, +2716, 2770, 2431, +2717, 2770, 2431, +2717, 2770, 2432, +2716, 2770, 2435, +2716, 2769, 2439, +2714, 2770, 2444, +2711, 2772, 2462, +2713, 2774, 2488, +2714, 2775, 2522, +2712, 2773, 2553, +2717, 2777, 2617, +2724, 2787, 2699, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2712, 2770, 2428, +2712, 2770, 2429, +2712, 2770, 2429, +2712, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2714, 2770, 2429, +2714, 2770, 2430, +2715, 2770, 2430, +2716, 2770, 2431, +2717, 2770, 2431, +2717, 2770, 2432, +2716, 2770, 2435, +2716, 2769, 2439, +2714, 2770, 2444, +2711, 2772, 2462, +2713, 2774, 2488, +2714, 2775, 2522, +2712, 2773, 2553, +2717, 2777, 2617, +2724, 2787, 2699, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2712, 2770, 2428, +2712, 2770, 2429, +2712, 2770, 2429, +2712, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2713, 2770, 2429, +2714, 2770, 2429, +2714, 2770, 2430, +2715, 2770, 2430, +2716, 2770, 2431, +2717, 2770, 2431, +2717, 2770, 2432, +2716, 2770, 2435, +2716, 2769, 2439, +2714, 2770, 2444, +2711, 2772, 2462, +2713, 2774, 2488, +2714, 2775, 2522, +2712, 2773, 2553, +2717, 2777, 2617, +2724, 2787, 2699, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +1146, 0, 0, +1146, 0, 0, +1146, 0, 0, +1146, 0, 46, +1146, 0, 140, +1146, 0, 240, +1146, 0, 347, +1146, 0, 460, +1146, 0, 576, +1146, 0, 697, +1146, 0, 820, +1146, 0, 946, +1143, 0, 1084, +1060, 0, 1359, +918, 0, 1574, +981, 0, 1683, +1223, 0, 1785, +1476, 0, 1909, +1569, 0, 2028, +1478, 645, 2197, +391, 989, 2347, +1611, 0, 2464, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1146, 0, 0, +1146, 0, 0, +1146, 0, 27, +1146, 0, 101, +1146, 0, 185, +1146, 0, 277, +1146, 0, 376, +1146, 0, 482, +1146, 0, 594, +1146, 0, 710, +1146, 0, 830, +1146, 0, 953, +1142, 0, 1089, +1059, 0, 1361, +917, 0, 1576, +981, 0, 1683, +1223, 0, 1786, +1476, 0, 1910, +1569, 0, 2029, +1477, 656, 2197, +395, 992, 2347, +1611, 0, 2464, +1757, 0, 2506, +1757, 0, 2506, +1757, 0, 2506, +1757, 0, 2506, +1757, 0, 2506, +1757, 0, 2506, +1757, 0, 2506, +1757, 0, 2506, +1757, 0, 2506, +1757, 0, 2506, +1143, 0, 0, +1143, 0, 0, +1144, 0, 38, +1144, 0, 111, +1144, 0, 193, +1144, 0, 284, +1144, 0, 382, +1144, 0, 487, +1144, 0, 598, +1144, 0, 713, +1144, 0, 833, +1144, 0, 955, +1141, 0, 1090, +1055, 0, 1362, +911, 0, 1576, +982, 0, 1684, +1219, 0, 1785, +1475, 0, 1911, +1568, 0, 2029, +1475, 665, 2197, +395, 998, 2347, +1614, 0, 2464, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1141, 0, 0, +1141, 0, 0, +1142, 0, 38, +1143, 0, 124, +1143, 0, 204, +1143, 0, 293, +1143, 0, 389, +1143, 0, 493, +1143, 0, 602, +1143, 0, 717, +1143, 0, 835, +1143, 0, 957, +1140, 0, 1091, +1050, 0, 1363, +904, 0, 1577, +984, 0, 1685, +1213, 0, 1785, +1474, 0, 1911, +1568, 0, 2030, +1472, 676, 2198, +395, 1005, 2348, +1617, 0, 2464, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1137, 0, 0, +1137, 0, 0, +1138, 0, 38, +1139, 0, 124, +1141, 0, 219, +1141, 0, 305, +1141, 0, 399, +1141, 0, 501, +1141, 0, 608, +1141, 0, 722, +1141, 0, 839, +1141, 0, 960, +1138, 0, 1093, +1043, 0, 1364, +895, 0, 1577, +987, 0, 1686, +1205, 0, 1784, +1474, 0, 1912, +1567, 0, 2031, +1469, 692, 2198, +395, 1015, 2348, +1622, 0, 2464, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1756, 0, 2506, +1132, 0, 0, +1132, 0, 0, +1133, 0, 38, +1134, 0, 124, +1136, 0, 219, +1139, 0, 320, +1139, 0, 411, +1139, 0, 511, +1139, 0, 616, +1139, 0, 728, +1139, 0, 844, +1139, 0, 963, +1136, 0, 1096, +1034, 0, 1365, +882, 0, 1578, +990, 0, 1687, +1194, 0, 1784, +1472, 0, 1913, +1566, 0, 2032, +1464, 711, 2199, +395, 1028, 2349, +1628, 0, 2464, +1755, 0, 2507, +1755, 0, 2507, +1755, 0, 2507, +1755, 0, 2507, +1755, 0, 2507, +1755, 0, 2507, +1755, 0, 2507, +1755, 0, 2507, +1755, 0, 2507, +1755, 0, 2507, +1125, 13, 0, +1125, 0, 0, +1126, 0, 38, +1128, 0, 124, +1129, 0, 219, +1132, 0, 320, +1135, 0, 428, +1135, 0, 524, +1135, 0, 627, +1135, 0, 736, +1135, 0, 850, +1135, 0, 968, +1132, 0, 1100, +1021, 107, 1367, +864, 107, 1579, +995, 0, 1690, +1178, 0, 1783, +1471, 0, 1914, +1565, 97, 2034, +1457, 736, 2199, +395, 1045, 2350, +1636, 0, 2464, +1754, 107, 2507, +1754, 107, 2507, +1754, 107, 2507, +1754, 107, 2507, +1754, 107, 2507, +1754, 107, 2507, +1754, 107, 2507, +1754, 107, 2507, +1754, 107, 2507, +1754, 107, 2507, +1116, 150, 0, +1116, 137, 0, +1117, 127, 38, +1118, 114, 124, +1120, 96, 219, +1123, 70, 320, +1126, 34, 428, +1131, 0, 541, +1131, 0, 640, +1131, 0, 747, +1131, 0, 858, +1131, 0, 975, +1128, 0, 1105, +1003, 254, 1370, +839, 254, 1581, +1001, 137, 1692, +1157, 0, 1782, +1469, 17, 1915, +1563, 213, 2037, +1448, 768, 2200, +395, 1066, 2351, +1646, 21, 2464, +1753, 254, 2507, +1753, 254, 2507, +1753, 254, 2507, +1753, 254, 2507, +1753, 254, 2507, +1753, 254, 2507, +1753, 254, 2507, +1753, 254, 2507, +1753, 254, 2507, +1753, 254, 2507, +1103, 286, 0, +1103, 276, 0, +1104, 269, 38, +1106, 259, 124, +1108, 246, 219, +1110, 227, 320, +1114, 202, 428, +1118, 166, 541, +1125, 111, 658, +1125, 111, 760, +1125, 111, 869, +1125, 111, 983, +1121, 111, 1111, +979, 396, 1374, +803, 396, 1584, +1009, 276, 1696, +1127, 0, 1781, +1466, 140, 1918, +1560, 333, 2040, +1436, 807, 2201, +395, 1093, 2353, +1654, 232, 2464, +1751, 396, 2508, +1751, 396, 2508, +1751, 396, 2508, +1751, 396, 2508, +1751, 396, 2508, +1751, 396, 2508, +1751, 396, 2508, +1751, 396, 2508, +1751, 396, 2508, +1751, 396, 2508, +1085, 420, 0, +1085, 413, 0, +1086, 408, 38, +1088, 401, 124, +1090, 391, 219, +1093, 378, 320, +1097, 360, 428, +1102, 334, 541, +1108, 298, 658, +1116, 244, 779, +1116, 244, 884, +1116, 244, 995, +1113, 244, 1119, +952, 513, 1379, +749, 536, 1587, +1019, 413, 1700, +1132, 186, 1784, +1462, 265, 1920, +1557, 456, 2044, +1419, 854, 2202, +395, 1128, 2355, +1664, 421, 2465, +1749, 536, 2509, +1749, 536, 2509, +1749, 536, 2509, +1749, 536, 2509, +1749, 536, 2509, +1749, 536, 2509, +1749, 536, 2509, +1749, 536, 2509, +1749, 536, 2509, +1749, 536, 2509, +1061, 554, 0, +1061, 549, 0, +1062, 545, 38, +1064, 540, 124, +1066, 533, 219, +1069, 523, 320, +1073, 510, 428, +1078, 492, 541, +1085, 466, 658, +1093, 430, 779, +1105, 376, 902, +1105, 376, 1009, +1102, 376, 1131, +936, 591, 1385, +666, 674, 1590, +999, 572, 1705, +1142, 392, 1789, +1438, 342, 1919, +1553, 581, 2050, +1395, 910, 2205, +395, 1169, 2358, +1678, 592, 2466, +1746, 674, 2510, +1746, 674, 2510, +1746, 674, 2510, +1746, 674, 2510, +1746, 674, 2510, +1746, 674, 2510, +1746, 674, 2510, +1746, 674, 2510, +1746, 674, 2510, +1746, 674, 2510, +1025, 688, 0, +1025, 684, 0, +1027, 681, 38, +1028, 677, 124, +1031, 672, 219, +1034, 665, 320, +1038, 655, 428, +1044, 643, 541, +1051, 624, 658, +1061, 599, 779, +1073, 562, 902, +1089, 508, 1028, +1086, 508, 1145, +913, 678, 1393, +525, 811, 1596, +936, 738, 1709, +1157, 573, 1796, +1399, 418, 1917, +1547, 709, 2058, +1361, 976, 2207, +221, 1212, 2361, +1695, 752, 2468, +1742, 811, 2511, +1742, 811, 2511, +1742, 811, 2511, +1742, 811, 2511, +1742, 811, 2511, +1742, 811, 2511, +1742, 811, 2511, +1742, 811, 2511, +1742, 811, 2511, +1742, 811, 2511, +998, 854, 247, +999, 854, 274, +1000, 852, 314, +1002, 850, 363, +1005, 846, 421, +1008, 841, 488, +1013, 835, 565, +1018, 826, 651, +1026, 814, 746, +1036, 797, 847, +1050, 774, 955, +1067, 741, 1069, +1082, 701, 1186, +907, 818, 1417, +458, 939, 1611, +854, 914, 1719, +1166, 781, 1811, +1344, 583, 1918, +1532, 855, 2069, +1306, 1062, 2213, +0, 1254, 2365, +1713, 908, 2469, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1738, 955, 2513, +1120, 1134, 981, +1120, 1134, 987, +1116, 1134, 996, +1110, 1134, 1007, +1102, 1134, 1022, +1091, 1134, 1041, +1076, 1134, 1065, +1055, 1134, 1096, +1025, 1134, 1133, +1003, 1131, 1180, +1017, 1120, 1235, +1036, 1105, 1300, +1052, 1087, 1374, +1136, 1087, 1482, +920, 1158, 1655, +941, 1167, 1774, +1193, 1161, 1864, +1274, 1071, 1958, +1421, 1134, 2085, +1184, 1237, 2230, +980, 1275, 2368, +1697, 1083, 2471, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1244, 1351, 1313, +1244, 1351, 1315, +1241, 1351, 1320, +1236, 1351, 1325, +1230, 1351, 1332, +1222, 1351, 1342, +1211, 1351, 1355, +1195, 1351, 1371, +1174, 1351, 1392, +1143, 1351, 1419, +1099, 1351, 1452, +1031, 1351, 1493, +1008, 1345, 1543, +1101, 1345, 1620, +1200, 1345, 1706, +1180, 1356, 1819, +1250, 1368, 1917, +1282, 1376, 2010, +1214, 1352, 2106, +941, 1399, 2251, +1206, 1332, 2375, +1655, 1246, 2474, +1839, 1219, 2510, +1839, 1219, 2510, +1839, 1219, 2510, +1839, 1219, 2510, +1839, 1219, 2510, +1839, 1219, 2510, +1839, 1219, 2510, +1839, 1219, 2510, +1839, 1219, 2510, +1839, 1219, 2510, +1442, 1522, 1648, +1441, 1522, 1649, +1440, 1523, 1650, +1440, 1523, 1651, +1439, 1524, 1653, +1437, 1525, 1655, +1436, 1526, 1658, +1433, 1528, 1663, +1430, 1531, 1668, +1426, 1534, 1676, +1410, 1536, 1691, +1377, 1536, 1716, +1335, 1537, 1749, +1263, 1537, 1781, +1301, 1537, 1839, +1339, 1536, 1910, +1357, 1528, 1994, +1241, 1551, 2071, +1105, 1537, 2167, +883, 1536, 2275, +1324, 1476, 2384, +1692, 1446, 2476, +1866, 1416, 2509, +1866, 1416, 2509, +1866, 1416, 2509, +1866, 1416, 2509, +1866, 1416, 2509, +1866, 1416, 2509, +1866, 1416, 2509, +1866, 1416, 2509, +1866, 1416, 2509, +1866, 1416, 2509, +1656, 1669, 1872, +1656, 1669, 1873, +1655, 1669, 1874, +1654, 1670, 1875, +1652, 1671, 1877, +1650, 1671, 1879, +1646, 1672, 1883, +1642, 1674, 1887, +1636, 1675, 1893, +1633, 1678, 1897, +1629, 1681, 1903, +1624, 1685, 1911, +1616, 1691, 1922, +1595, 1684, 1941, +1542, 1684, 1969, +1504, 1684, 2010, +1525, 1691, 2073, +1483, 1671, 2138, +1324, 1684, 2221, +1259, 1662, 2297, +1564, 1621, 2385, +1796, 1617, 2477, +1894, 1605, 2510, +1894, 1605, 2510, +1894, 1605, 2510, +1894, 1605, 2510, +1894, 1605, 2510, +1894, 1605, 2510, +1894, 1605, 2510, +1894, 1605, 2510, +1894, 1605, 2510, +1894, 1605, 2510, +1843, 1802, 1967, +1843, 1802, 1968, +1843, 1802, 1969, +1842, 1802, 1969, +1841, 1802, 1971, +1840, 1802, 1972, +1839, 1802, 1974, +1837, 1802, 1977, +1834, 1802, 1981, +1831, 1802, 1986, +1824, 1804, 1994, +1814, 1807, 2005, +1802, 1811, 2018, +1790, 1817, 2033, +1773, 1811, 2052, +1772, 1809, 2081, +1734, 1809, 2120, +1747, 1811, 2175, +1708, 1801, 2234, +1744, 1800, 2309, +1774, 1800, 2391, +1911, 1796, 2475, +1992, 1790, 2515, +1992, 1790, 2515, +1992, 1790, 2515, +1992, 1790, 2515, +1992, 1790, 2515, +1992, 1790, 2515, +1992, 1790, 2515, +1992, 1790, 2515, +1992, 1790, 2515, +1992, 1790, 2515, +1992, 1958, 2037, +1992, 1958, 2037, +1992, 1958, 2037, +1991, 1958, 2038, +1991, 1958, 2038, +1990, 1958, 2040, +1989, 1958, 2041, +1988, 1958, 2043, +1986, 1958, 2045, +1983, 1958, 2049, +1980, 1958, 2053, +1976, 1958, 2059, +1970, 1958, 2067, +1962, 1958, 2074, +1950, 1958, 2082, +1946, 1958, 2104, +1947, 1962, 2142, +1936, 1964, 2196, +1923, 1957, 2231, +1922, 1958, 2310, +1954, 1955, 2394, +2043, 1964, 2481, +2127, 1958, 2514, +2127, 1958, 2514, +2127, 1958, 2514, +2127, 1958, 2514, +2127, 1958, 2514, +2127, 1958, 2514, +2127, 1958, 2514, +2127, 1958, 2514, +2127, 1958, 2514, +2127, 1958, 2514, +2128, 2127, 2076, +2128, 2127, 2077, +2129, 2127, 2077, +2129, 2127, 2077, +2129, 2127, 2077, +2129, 2127, 2078, +2130, 2127, 2078, +2130, 2127, 2079, +2131, 2127, 2080, +2132, 2127, 2080, +2133, 2127, 2082, +2135, 2127, 2084, +2135, 2127, 2087, +2129, 2127, 2097, +2122, 2127, 2109, +2124, 2131, 2129, +2128, 2135, 2163, +2124, 2132, 2210, +2119, 2127, 2251, +2135, 2128, 2316, +2164, 2135, 2400, +2226, 2151, 2485, +2257, 2159, 2520, +2257, 2159, 2520, +2257, 2159, 2520, +2257, 2159, 2520, +2257, 2159, 2520, +2257, 2159, 2520, +2257, 2159, 2520, +2257, 2159, 2520, +2257, 2159, 2520, +2257, 2159, 2520, +2374, 2355, 2126, +2374, 2355, 2127, +2374, 2355, 2127, +2374, 2355, 2127, +2374, 2355, 2127, +2374, 2355, 2128, +2374, 2355, 2129, +2375, 2355, 2130, +2375, 2355, 2131, +2375, 2355, 2133, +2376, 2355, 2135, +2377, 2355, 2138, +2376, 2355, 2140, +2375, 2355, 2143, +2372, 2354, 2147, +2374, 2356, 2159, +2375, 2358, 2191, +2375, 2357, 2230, +2381, 2358, 2275, +2398, 2368, 2335, +2415, 2368, 2409, +2469, 2388, 2498, +2498, 2395, 2532, +2498, 2395, 2532, +2498, 2395, 2532, +2498, 2395, 2532, +2498, 2395, 2532, +2498, 2395, 2532, +2498, 2395, 2532, +2498, 2395, 2532, +2498, 2395, 2532, +2498, 2395, 2532, +2679, 2653, 1955, +2679, 2653, 1955, +2679, 2653, 1956, +2679, 2653, 1957, +2679, 2653, 1958, +2679, 2654, 1961, +2679, 2654, 1963, +2679, 2654, 1967, +2679, 2654, 1964, +2679, 2653, 1961, +2678, 2652, 1955, +2678, 2650, 1948, +2677, 2648, 1939, +2677, 2650, 1960, +2676, 2655, 1976, +2677, 2657, 2013, +2680, 2657, 2068, +2679, 2658, 2122, +2683, 2657, 2209, +2688, 2661, 2310, +2695, 2666, 2408, +2715, 2679, 2527, +2727, 2684, 2579, +2727, 2684, 2579, +2727, 2684, 2579, +2727, 2684, 2579, +2727, 2684, 2579, +2727, 2684, 2579, +2727, 2684, 2579, +2727, 2684, 2579, +2727, 2684, 2579, +2727, 2684, 2579, +2712, 2769, 2427, +2712, 2769, 2427, +2712, 2769, 2427, +2712, 2769, 2428, +2712, 2769, 2428, +2712, 2769, 2428, +2713, 2769, 2428, +2713, 2769, 2428, +2714, 2769, 2429, +2714, 2769, 2429, +2715, 2769, 2430, +2717, 2769, 2431, +2718, 2770, 2433, +2717, 2770, 2436, +2716, 2770, 2440, +2714, 2770, 2444, +2712, 2772, 2461, +2714, 2774, 2492, +2714, 2775, 2523, +2712, 2774, 2554, +2717, 2778, 2620, +2725, 2789, 2702, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2712, 2769, 2427, +2712, 2769, 2427, +2712, 2769, 2427, +2712, 2769, 2428, +2712, 2769, 2428, +2712, 2769, 2428, +2713, 2769, 2428, +2713, 2769, 2428, +2714, 2769, 2429, +2714, 2769, 2429, +2715, 2769, 2430, +2717, 2769, 2431, +2718, 2770, 2433, +2717, 2770, 2436, +2716, 2770, 2440, +2714, 2770, 2444, +2712, 2772, 2461, +2714, 2774, 2492, +2714, 2775, 2523, +2712, 2774, 2554, +2717, 2778, 2620, +2725, 2789, 2702, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2712, 2769, 2427, +2712, 2769, 2427, +2712, 2769, 2427, +2712, 2769, 2428, +2712, 2769, 2428, +2712, 2769, 2428, +2713, 2769, 2428, +2713, 2769, 2428, +2714, 2769, 2429, +2714, 2769, 2429, +2715, 2769, 2430, +2717, 2769, 2431, +2718, 2770, 2433, +2717, 2770, 2436, +2716, 2770, 2440, +2714, 2770, 2444, +2712, 2772, 2461, +2714, 2774, 2492, +2714, 2775, 2523, +2712, 2774, 2554, +2717, 2778, 2620, +2725, 2789, 2702, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2712, 2769, 2427, +2712, 2769, 2427, +2712, 2769, 2427, +2712, 2769, 2428, +2712, 2769, 2428, +2712, 2769, 2428, +2713, 2769, 2428, +2713, 2769, 2428, +2714, 2769, 2429, +2714, 2769, 2429, +2715, 2769, 2430, +2717, 2769, 2431, +2718, 2770, 2433, +2717, 2770, 2436, +2716, 2770, 2440, +2714, 2770, 2444, +2712, 2772, 2461, +2714, 2774, 2492, +2714, 2775, 2523, +2712, 2774, 2554, +2717, 2778, 2620, +2725, 2789, 2702, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2712, 2769, 2427, +2712, 2769, 2427, +2712, 2769, 2427, +2712, 2769, 2428, +2712, 2769, 2428, +2712, 2769, 2428, +2713, 2769, 2428, +2713, 2769, 2428, +2714, 2769, 2429, +2714, 2769, 2429, +2715, 2769, 2430, +2717, 2769, 2431, +2718, 2770, 2433, +2717, 2770, 2436, +2716, 2770, 2440, +2714, 2770, 2444, +2712, 2772, 2461, +2714, 2774, 2492, +2714, 2775, 2523, +2712, 2774, 2554, +2717, 2778, 2620, +2725, 2789, 2702, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2712, 2769, 2427, +2712, 2769, 2427, +2712, 2769, 2427, +2712, 2769, 2428, +2712, 2769, 2428, +2712, 2769, 2428, +2713, 2769, 2428, +2713, 2769, 2428, +2714, 2769, 2429, +2714, 2769, 2429, +2715, 2769, 2430, +2717, 2769, 2431, +2718, 2770, 2433, +2717, 2770, 2436, +2716, 2770, 2440, +2714, 2770, 2444, +2712, 2772, 2461, +2714, 2774, 2492, +2714, 2775, 2523, +2712, 2774, 2554, +2717, 2778, 2620, +2725, 2789, 2702, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2712, 2769, 2427, +2712, 2769, 2427, +2712, 2769, 2427, +2712, 2769, 2428, +2712, 2769, 2428, +2712, 2769, 2428, +2713, 2769, 2428, +2713, 2769, 2428, +2714, 2769, 2429, +2714, 2769, 2429, +2715, 2769, 2430, +2717, 2769, 2431, +2718, 2770, 2433, +2717, 2770, 2436, +2716, 2770, 2440, +2714, 2770, 2444, +2712, 2772, 2461, +2714, 2774, 2492, +2714, 2775, 2523, +2712, 2774, 2554, +2717, 2778, 2620, +2725, 2789, 2702, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2712, 2769, 2427, +2712, 2769, 2427, +2712, 2769, 2427, +2712, 2769, 2428, +2712, 2769, 2428, +2712, 2769, 2428, +2713, 2769, 2428, +2713, 2769, 2428, +2714, 2769, 2429, +2714, 2769, 2429, +2715, 2769, 2430, +2717, 2769, 2431, +2718, 2770, 2433, +2717, 2770, 2436, +2716, 2770, 2440, +2714, 2770, 2444, +2712, 2772, 2461, +2714, 2774, 2492, +2714, 2775, 2523, +2712, 2774, 2554, +2717, 2778, 2620, +2725, 2789, 2702, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2712, 2769, 2427, +2712, 2769, 2427, +2712, 2769, 2427, +2712, 2769, 2428, +2712, 2769, 2428, +2712, 2769, 2428, +2713, 2769, 2428, +2713, 2769, 2428, +2714, 2769, 2429, +2714, 2769, 2429, +2715, 2769, 2430, +2717, 2769, 2431, +2718, 2770, 2433, +2717, 2770, 2436, +2716, 2770, 2440, +2714, 2770, 2444, +2712, 2772, 2461, +2714, 2774, 2492, +2714, 2775, 2523, +2712, 2774, 2554, +2717, 2778, 2620, +2725, 2789, 2702, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2712, 2769, 2427, +2712, 2769, 2427, +2712, 2769, 2427, +2712, 2769, 2428, +2712, 2769, 2428, +2712, 2769, 2428, +2713, 2769, 2428, +2713, 2769, 2428, +2714, 2769, 2429, +2714, 2769, 2429, +2715, 2769, 2430, +2717, 2769, 2431, +2718, 2770, 2433, +2717, 2770, 2436, +2716, 2770, 2440, +2714, 2770, 2444, +2712, 2772, 2461, +2714, 2774, 2492, +2714, 2775, 2523, +2712, 2774, 2554, +2717, 2778, 2620, +2725, 2789, 2702, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +2729, 2789, 2727, +1314, 0, 0, +1314, 0, 0, +1315, 0, 0, +1316, 0, 18, +1317, 0, 98, +1319, 0, 188, +1321, 0, 285, +1324, 0, 389, +1328, 0, 499, +1331, 0, 624, +1331, 0, 765, +1331, 0, 904, +1329, 0, 1054, +1312, 0, 1291, +1236, 0, 1533, +1269, 0, 1690, +1323, 0, 1781, +1534, 0, 1909, +1607, 0, 2039, +1502, 645, 2197, +677, 1023, 2352, +1658, 0, 2466, +1776, 0, 2506, +1776, 0, 2506, +1776, 0, 2506, +1776, 0, 2506, +1776, 0, 2506, +1776, 0, 2506, +1776, 0, 2506, +1776, 0, 2506, +1776, 0, 2506, +1776, 0, 2506, +1314, 0, 0, +1314, 0, 0, +1315, 0, 17, +1315, 0, 78, +1316, 0, 150, +1318, 0, 230, +1321, 0, 319, +1324, 0, 417, +1328, 0, 521, +1331, 0, 640, +1331, 0, 777, +1331, 0, 914, +1329, 0, 1059, +1311, 0, 1294, +1235, 0, 1535, +1268, 0, 1691, +1323, 0, 1782, +1533, 0, 1910, +1607, 0, 2039, +1501, 656, 2197, +679, 1026, 2352, +1659, 0, 2466, +1776, 0, 2506, +1776, 0, 2506, +1776, 0, 2506, +1776, 0, 2506, +1776, 0, 2506, +1776, 0, 2506, +1776, 0, 2506, +1776, 0, 2506, +1776, 0, 2506, +1776, 0, 2506, +1314, 0, 0, +1314, 0, 17, +1314, 0, 97, +1315, 0, 149, +1316, 0, 211, +1318, 0, 282, +1320, 0, 363, +1323, 0, 452, +1327, 0, 549, +1330, 0, 662, +1330, 0, 794, +1330, 0, 926, +1328, 0, 1068, +1311, 0, 1298, +1235, 0, 1537, +1267, 0, 1692, +1323, 0, 1783, +1532, 0, 1911, +1606, 0, 2040, +1500, 671, 2198, +682, 1030, 2352, +1660, 0, 2466, +1777, 0, 2506, +1777, 0, 2506, +1777, 0, 2506, +1777, 0, 2506, +1777, 0, 2506, +1777, 0, 2506, +1777, 0, 2506, +1777, 0, 2506, +1777, 0, 2506, +1777, 0, 2506, +1314, 0, 18, +1314, 0, 78, +1314, 0, 149, +1314, 0, 229, +1315, 0, 281, +1316, 0, 343, +1319, 0, 414, +1322, 0, 494, +1326, 0, 584, +1329, 0, 689, +1329, 0, 814, +1329, 0, 941, +1327, 0, 1079, +1310, 0, 1302, +1233, 0, 1540, +1266, 0, 1693, +1323, 0, 1784, +1531, 0, 1912, +1605, 0, 2041, +1498, 690, 2198, +686, 1035, 2353, +1661, 0, 2466, +1778, 0, 2506, +1778, 0, 2506, +1778, 0, 2506, +1778, 0, 2506, +1778, 0, 2506, +1778, 0, 2506, +1778, 0, 2506, +1778, 0, 2506, +1778, 0, 2506, +1778, 0, 2506, +1314, 0, 98, +1314, 0, 150, +1314, 0, 211, +1314, 0, 281, +1314, 0, 361, +1315, 0, 413, +1318, 0, 475, +1321, 0, 546, +1325, 0, 627, +1328, 0, 723, +1328, 0, 840, +1328, 0, 961, +1326, 0, 1094, +1309, 0, 1309, +1232, 0, 1544, +1265, 0, 1695, +1323, 0, 1787, +1529, 0, 1914, +1603, 0, 2042, +1497, 714, 2199, +691, 1042, 2353, +1662, 0, 2466, +1779, 0, 2506, +1779, 0, 2506, +1779, 0, 2506, +1779, 0, 2506, +1779, 0, 2506, +1779, 0, 2506, +1779, 0, 2506, +1779, 0, 2506, +1779, 0, 2506, +1779, 0, 2506, +1314, 0, 188, +1314, 0, 230, +1314, 0, 282, +1314, 0, 343, +1314, 0, 413, +1314, 0, 493, +1316, 0, 545, +1319, 0, 607, +1323, 0, 678, +1326, 0, 766, +1326, 0, 873, +1326, 0, 986, +1324, 0, 1113, +1307, 0, 1317, +1230, 0, 1549, +1263, 0, 1697, +1323, 30, 1790, +1527, 0, 1916, +1602, 132, 2043, +1495, 745, 2200, +698, 1051, 2354, +1663, 0, 2466, +1781, 0, 2506, +1781, 0, 2506, +1781, 0, 2506, +1781, 0, 2506, +1781, 0, 2506, +1781, 0, 2506, +1781, 0, 2506, +1781, 0, 2506, +1781, 0, 2506, +1781, 0, 2506, +1314, 121, 285, +1314, 106, 319, +1314, 85, 363, +1314, 56, 414, +1314, 13, 475, +1314, 0, 545, +1314, 0, 625, +1317, 0, 677, +1321, 0, 739, +1324, 0, 816, +1324, 0, 914, +1324, 0, 1018, +1322, 0, 1138, +1304, 0, 1329, +1227, 0, 1556, +1261, 0, 1700, +1323, 163, 1794, +1524, 32, 1919, +1599, 264, 2045, +1491, 783, 2201, +706, 1063, 2354, +1666, 32, 2466, +1784, 0, 2506, +1784, 0, 2506, +1784, 0, 2506, +1784, 0, 2506, +1784, 0, 2506, +1784, 0, 2506, +1784, 0, 2506, +1784, 0, 2506, +1784, 0, 2506, +1784, 0, 2506, +1314, 264, 389, +1314, 253, 417, +1314, 238, 452, +1314, 217, 494, +1314, 188, 546, +1314, 146, 607, +1314, 82, 677, +1314, 0, 757, +1318, 0, 809, +1321, 0, 876, +1321, 0, 963, +1321, 0, 1058, +1319, 0, 1168, +1302, 0, 1343, +1223, 0, 1565, +1257, 0, 1704, +1323, 295, 1799, +1520, 164, 1923, +1596, 396, 2047, +1487, 830, 2203, +718, 1079, 2355, +1668, 164, 2466, +1787, 0, 2506, +1787, 0, 2506, +1787, 0, 2506, +1787, 0, 2506, +1787, 0, 2506, +1787, 0, 2506, +1787, 0, 2506, +1787, 0, 2506, +1787, 0, 2506, +1787, 0, 2506, +1314, 404, 499, +1314, 396, 521, +1314, 385, 549, +1314, 370, 584, +1314, 349, 627, +1314, 320, 678, +1314, 277, 739, +1314, 214, 809, +1314, 111, 889, +1317, 111, 946, +1317, 111, 1021, +1317, 111, 1106, +1315, 111, 1206, +1297, 111, 1362, +1218, 111, 1576, +1252, 111, 1709, +1323, 426, 1806, +1515, 296, 1928, +1592, 528, 2051, +1482, 885, 2205, +733, 1099, 2357, +1667, 296, 2465, +1791, 111, 2506, +1791, 111, 2506, +1791, 111, 2506, +1791, 111, 2506, +1791, 111, 2506, +1791, 111, 2506, +1791, 111, 2506, +1791, 111, 2506, +1791, 111, 2506, +1791, 111, 2506, +1310, 530, 574, +1310, 524, 592, +1310, 516, 616, +1310, 505, 646, +1310, 490, 684, +1310, 468, 730, +1310, 438, 784, +1310, 394, 848, +1310, 328, 922, +1311, 244, 1001, +1311, 244, 1068, +1311, 244, 1145, +1310, 244, 1238, +1292, 244, 1379, +1207, 285, 1587, +1251, 265, 1716, +1322, 514, 1811, +1510, 413, 1934, +1587, 643, 2055, +1471, 941, 2208, +745, 1128, 2358, +1669, 442, 2465, +1794, 285, 2506, +1794, 285, 2506, +1794, 285, 2506, +1794, 285, 2506, +1794, 285, 2506, +1794, 285, 2506, +1794, 285, 2506, +1794, 285, 2506, +1794, 285, 2506, +1794, 285, 2506, +1294, 639, 574, +1294, 634, 592, +1294, 627, 616, +1294, 619, 646, +1294, 607, 684, +1294, 591, 730, +1294, 568, 784, +1294, 535, 848, +1294, 488, 922, +1297, 430, 1001, +1304, 376, 1080, +1304, 376, 1155, +1302, 376, 1246, +1284, 376, 1385, +1178, 503, 1590, +1239, 473, 1720, +1329, 626, 1816, +1488, 470, 1933, +1583, 729, 2060, +1450, 988, 2209, +745, 1169, 2362, +1682, 607, 2467, +1792, 503, 2507, +1792, 503, 2507, +1792, 503, 2507, +1792, 503, 2507, +1792, 503, 2507, +1792, 503, 2507, +1792, 503, 2507, +1792, 503, 2507, +1792, 503, 2507, +1792, 503, 2507, +1274, 753, 574, +1274, 749, 592, +1274, 744, 616, +1274, 737, 646, +1274, 728, 684, +1274, 716, 730, +1274, 698, 784, +1274, 674, 848, +1274, 640, 922, +1276, 599, 1001, +1284, 562, 1080, +1294, 508, 1169, +1292, 508, 1257, +1273, 508, 1393, +1137, 691, 1596, +1203, 671, 1723, +1338, 742, 1822, +1453, 529, 1930, +1577, 824, 2068, +1421, 1044, 2212, +672, 1212, 2365, +1699, 762, 2468, +1788, 691, 2509, +1788, 691, 2509, +1788, 691, 2509, +1788, 691, 2509, +1788, 691, 2509, +1788, 691, 2509, +1788, 691, 2509, +1788, 691, 2509, +1788, 691, 2509, +1788, 691, 2509, +1258, 900, 682, +1259, 900, 693, +1259, 896, 712, +1259, 891, 736, +1259, 885, 767, +1259, 876, 806, +1259, 864, 852, +1259, 847, 908, +1259, 824, 973, +1261, 797, 1044, +1269, 774, 1117, +1280, 741, 1199, +1289, 701, 1290, +1270, 701, 1417, +1120, 852, 1611, +1159, 869, 1734, +1344, 895, 1836, +1405, 663, 1931, +1563, 942, 2078, +1372, 1118, 2218, +602, 1254, 2368, +1718, 915, 2470, +1784, 871, 2510, +1784, 871, 2510, +1784, 871, 2510, +1784, 871, 2510, +1784, 871, 2510, +1784, 871, 2510, +1784, 871, 2510, +1784, 871, 2510, +1784, 871, 2510, +1784, 871, 2510, +1314, 1134, 1183, +1314, 1134, 1187, +1315, 1134, 1191, +1316, 1134, 1197, +1317, 1134, 1206, +1319, 1134, 1216, +1321, 1134, 1230, +1324, 1134, 1248, +1328, 1134, 1271, +1333, 1131, 1302, +1340, 1120, 1345, +1349, 1105, 1396, +1358, 1087, 1457, +1341, 1087, 1528, +1216, 1158, 1687, +1159, 1142, 1780, +1317, 1176, 1886, +1360, 1041, 1962, +1486, 1159, 2104, +1228, 1237, 2234, +1015, 1275, 2368, +1721, 1100, 2471, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1784, 1087, 2512, +1399, 1351, 1421, +1399, 1351, 1423, +1400, 1351, 1426, +1400, 1351, 1429, +1401, 1351, 1434, +1403, 1351, 1441, +1405, 1351, 1449, +1407, 1351, 1460, +1410, 1351, 1475, +1407, 1351, 1495, +1382, 1351, 1523, +1347, 1351, 1559, +1336, 1345, 1602, +1319, 1345, 1655, +1383, 1345, 1736, +1321, 1339, 1825, +1361, 1378, 1936, +1367, 1360, 2014, +1313, 1367, 2124, +1014, 1399, 2255, +1228, 1332, 2375, +1681, 1258, 2475, +1839, 1219, 2510, +1839, 1219, 2510, +1839, 1219, 2510, +1839, 1219, 2510, +1839, 1219, 2510, +1839, 1219, 2510, +1839, 1219, 2510, +1839, 1219, 2510, +1839, 1219, 2510, +1839, 1219, 2510, +1514, 1522, 1673, +1514, 1522, 1673, +1513, 1522, 1674, +1512, 1522, 1674, +1510, 1522, 1676, +1508, 1522, 1677, +1505, 1522, 1679, +1501, 1522, 1682, +1495, 1522, 1685, +1489, 1523, 1691, +1475, 1525, 1706, +1447, 1525, 1730, +1412, 1526, 1762, +1397, 1537, 1811, +1426, 1537, 1865, +1415, 1525, 1919, +1395, 1535, 2005, +1299, 1551, 2087, +1205, 1526, 2170, +1197, 1525, 2279, +1402, 1488, 2382, +1717, 1446, 2476, +1900, 1416, 2509, +1900, 1416, 2509, +1900, 1416, 2509, +1900, 1416, 2509, +1900, 1416, 2509, +1900, 1416, 2509, +1900, 1416, 2509, +1900, 1416, 2509, +1900, 1416, 2509, +1900, 1416, 2509, +1678, 1669, 1879, +1678, 1669, 1879, +1678, 1669, 1880, +1678, 1669, 1882, +1678, 1669, 1884, +1678, 1669, 1886, +1678, 1669, 1889, +1678, 1669, 1894, +1678, 1669, 1900, +1674, 1670, 1903, +1671, 1673, 1909, +1667, 1678, 1917, +1659, 1683, 1928, +1644, 1684, 1948, +1597, 1684, 1976, +1591, 1683, 2015, +1577, 1683, 2072, +1536, 1664, 2140, +1423, 1683, 2226, +1349, 1660, 2299, +1619, 1615, 2384, +1819, 1607, 2477, +1912, 1605, 2509, +1912, 1605, 2509, +1912, 1605, 2509, +1912, 1605, 2509, +1912, 1605, 2509, +1912, 1605, 2509, +1912, 1605, 2509, +1912, 1605, 2509, +1912, 1605, 2509, +1912, 1605, 2509, +1848, 1802, 1967, +1848, 1802, 1968, +1849, 1802, 1969, +1849, 1803, 1970, +1849, 1803, 1972, +1850, 1804, 1973, +1851, 1805, 1976, +1851, 1806, 1980, +1853, 1807, 1984, +1853, 1808, 1990, +1846, 1810, 1998, +1837, 1813, 2009, +1825, 1817, 2022, +1820, 1817, 2033, +1804, 1811, 2052, +1785, 1809, 2084, +1764, 1804, 2118, +1767, 1811, 2177, +1736, 1801, 2237, +1751, 1800, 2307, +1774, 1800, 2391, +1919, 1797, 2474, +2000, 1784, 2514, +2000, 1784, 2514, +2000, 1784, 2514, +2000, 1784, 2514, +2000, 1784, 2514, +2000, 1784, 2514, +2000, 1784, 2514, +2000, 1784, 2514, +2000, 1784, 2514, +2000, 1784, 2514, +1992, 1958, 2037, +1992, 1958, 2037, +1992, 1958, 2037, +1992, 1958, 2037, +1992, 1958, 2037, +1992, 1958, 2038, +1992, 1958, 2038, +1992, 1958, 2039, +1992, 1958, 2040, +1991, 1958, 2042, +1988, 1958, 2046, +1983, 1958, 2052, +1978, 1958, 2060, +1974, 1962, 2077, +1963, 1962, 2086, +1955, 1958, 2110, +1955, 1962, 2141, +1953, 1964, 2193, +1941, 1953, 2231, +1931, 1953, 2310, +1966, 1959, 2394, +2048, 1966, 2481, +2129, 1963, 2515, +2129, 1963, 2515, +2129, 1963, 2515, +2129, 1963, 2515, +2129, 1963, 2515, +2129, 1963, 2515, +2129, 1963, 2515, +2129, 1963, 2515, +2129, 1963, 2515, +2129, 1963, 2515, +2134, 2127, 2070, +2134, 2127, 2070, +2134, 2127, 2071, +2135, 2127, 2071, +2135, 2127, 2073, +2135, 2127, 2074, +2135, 2127, 2076, +2136, 2127, 2078, +2137, 2127, 2081, +2137, 2127, 2084, +2139, 2127, 2085, +2140, 2127, 2087, +2141, 2127, 2091, +2135, 2127, 2100, +2127, 2127, 2112, +2129, 2128, 2129, +2136, 2135, 2161, +2130, 2135, 2208, +2125, 2127, 2253, +2141, 2131, 2316, +2170, 2132, 2397, +2230, 2150, 2485, +2266, 2159, 2520, +2266, 2159, 2520, +2266, 2159, 2520, +2266, 2159, 2520, +2266, 2159, 2520, +2266, 2159, 2520, +2266, 2159, 2520, +2266, 2159, 2520, +2266, 2159, 2520, +2266, 2159, 2520, +2377, 2355, 2126, +2377, 2355, 2127, +2377, 2355, 2127, +2377, 2355, 2127, +2377, 2355, 2127, +2378, 2355, 2127, +2378, 2355, 2128, +2378, 2355, 2128, +2378, 2355, 2129, +2379, 2355, 2130, +2380, 2355, 2133, +2380, 2355, 2135, +2380, 2355, 2137, +2378, 2357, 2143, +2376, 2356, 2147, +2376, 2354, 2159, +2375, 2358, 2194, +2375, 2357, 2230, +2381, 2357, 2273, +2399, 2366, 2335, +2418, 2368, 2408, +2472, 2387, 2495, +2499, 2395, 2533, +2499, 2395, 2533, +2499, 2395, 2533, +2499, 2395, 2533, +2499, 2395, 2533, +2499, 2395, 2533, +2499, 2395, 2533, +2499, 2395, 2533, +2499, 2395, 2533, +2499, 2395, 2533, +2680, 2655, 1964, +2680, 2655, 1964, +2680, 2655, 1964, +2680, 2655, 1964, +2680, 2655, 1964, +2680, 2655, 1964, +2680, 2655, 1964, +2680, 2655, 1964, +2679, 2655, 1968, +2679, 2655, 1970, +2679, 2654, 1965, +2678, 2652, 1958, +2677, 2650, 1949, +2677, 2648, 1945, +2675, 2653, 1962, +2676, 2656, 2011, +2680, 2657, 2064, +2681, 2657, 2122, +2684, 2657, 2213, +2688, 2662, 2314, +2696, 2667, 2413, +2716, 2679, 2527, +2727, 2684, 2578, +2727, 2684, 2578, +2727, 2684, 2578, +2727, 2684, 2578, +2727, 2684, 2578, +2727, 2684, 2578, +2727, 2684, 2578, +2727, 2684, 2578, +2727, 2684, 2578, +2727, 2684, 2578, +2713, 2769, 2427, +2713, 2769, 2427, +2713, 2769, 2427, +2713, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2429, +2714, 2769, 2429, +2715, 2769, 2430, +2717, 2769, 2431, +2718, 2770, 2433, +2719, 2772, 2443, +2718, 2772, 2447, +2715, 2770, 2444, +2712, 2771, 2455, +2714, 2774, 2492, +2716, 2775, 2523, +2714, 2775, 2560, +2719, 2781, 2625, +2725, 2789, 2703, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2713, 2769, 2427, +2713, 2769, 2427, +2713, 2769, 2427, +2713, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2429, +2714, 2769, 2429, +2715, 2769, 2430, +2717, 2769, 2431, +2718, 2770, 2433, +2719, 2772, 2443, +2718, 2772, 2447, +2715, 2770, 2444, +2712, 2771, 2455, +2714, 2774, 2492, +2716, 2775, 2523, +2714, 2775, 2560, +2719, 2781, 2625, +2725, 2789, 2703, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2713, 2769, 2427, +2713, 2769, 2427, +2713, 2769, 2427, +2713, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2429, +2714, 2769, 2429, +2715, 2769, 2430, +2717, 2769, 2431, +2718, 2770, 2433, +2719, 2772, 2443, +2718, 2772, 2447, +2715, 2770, 2444, +2712, 2771, 2455, +2714, 2774, 2492, +2716, 2775, 2523, +2714, 2775, 2560, +2719, 2781, 2625, +2725, 2789, 2703, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2713, 2769, 2427, +2713, 2769, 2427, +2713, 2769, 2427, +2713, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2429, +2714, 2769, 2429, +2715, 2769, 2430, +2717, 2769, 2431, +2718, 2770, 2433, +2719, 2772, 2443, +2718, 2772, 2447, +2715, 2770, 2444, +2712, 2771, 2455, +2714, 2774, 2492, +2716, 2775, 2523, +2714, 2775, 2560, +2719, 2781, 2625, +2725, 2789, 2703, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2713, 2769, 2427, +2713, 2769, 2427, +2713, 2769, 2427, +2713, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2429, +2714, 2769, 2429, +2715, 2769, 2430, +2717, 2769, 2431, +2718, 2770, 2433, +2719, 2772, 2443, +2718, 2772, 2447, +2715, 2770, 2444, +2712, 2771, 2455, +2714, 2774, 2492, +2716, 2775, 2523, +2714, 2775, 2560, +2719, 2781, 2625, +2725, 2789, 2703, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2713, 2769, 2427, +2713, 2769, 2427, +2713, 2769, 2427, +2713, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2429, +2714, 2769, 2429, +2715, 2769, 2430, +2717, 2769, 2431, +2718, 2770, 2433, +2719, 2772, 2443, +2718, 2772, 2447, +2715, 2770, 2444, +2712, 2771, 2455, +2714, 2774, 2492, +2716, 2775, 2523, +2714, 2775, 2560, +2719, 2781, 2625, +2725, 2789, 2703, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2713, 2769, 2427, +2713, 2769, 2427, +2713, 2769, 2427, +2713, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2429, +2714, 2769, 2429, +2715, 2769, 2430, +2717, 2769, 2431, +2718, 2770, 2433, +2719, 2772, 2443, +2718, 2772, 2447, +2715, 2770, 2444, +2712, 2771, 2455, +2714, 2774, 2492, +2716, 2775, 2523, +2714, 2775, 2560, +2719, 2781, 2625, +2725, 2789, 2703, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2713, 2769, 2427, +2713, 2769, 2427, +2713, 2769, 2427, +2713, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2429, +2714, 2769, 2429, +2715, 2769, 2430, +2717, 2769, 2431, +2718, 2770, 2433, +2719, 2772, 2443, +2718, 2772, 2447, +2715, 2770, 2444, +2712, 2771, 2455, +2714, 2774, 2492, +2716, 2775, 2523, +2714, 2775, 2560, +2719, 2781, 2625, +2725, 2789, 2703, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2713, 2769, 2427, +2713, 2769, 2427, +2713, 2769, 2427, +2713, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2429, +2714, 2769, 2429, +2715, 2769, 2430, +2717, 2769, 2431, +2718, 2770, 2433, +2719, 2772, 2443, +2718, 2772, 2447, +2715, 2770, 2444, +2712, 2771, 2455, +2714, 2774, 2492, +2716, 2775, 2523, +2714, 2775, 2560, +2719, 2781, 2625, +2725, 2789, 2703, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2713, 2769, 2427, +2713, 2769, 2427, +2713, 2769, 2427, +2713, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2428, +2714, 2769, 2429, +2714, 2769, 2429, +2715, 2769, 2430, +2717, 2769, 2431, +2718, 2770, 2433, +2719, 2772, 2443, +2718, 2772, 2447, +2715, 2770, 2444, +2712, 2771, 2455, +2714, 2774, 2492, +2716, 2775, 2523, +2714, 2775, 2560, +2719, 2781, 2625, +2725, 2789, 2703, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +2729, 2791, 2730, +1471, 0, 0, +1471, 0, 0, +1472, 0, 0, +1472, 0, 18, +1473, 0, 98, +1475, 0, 188, +1476, 0, 285, +1478, 0, 389, +1481, 0, 499, +1485, 0, 614, +1490, 0, 733, +1496, 0, 855, +1498, 0, 1011, +1486, 0, 1266, +1470, 0, 1472, +1490, 0, 1659, +1524, 0, 1789, +1589, 0, 1904, +1654, 0, 2053, +1531, 645, 2197, +923, 1046, 2356, +1710, 0, 2469, +1801, 0, 2506, +1801, 0, 2506, +1801, 0, 2506, +1801, 0, 2506, +1801, 0, 2506, +1801, 0, 2506, +1801, 0, 2506, +1801, 0, 2506, +1801, 0, 2506, +1801, 0, 2506, +1471, 0, 0, +1471, 0, 0, +1471, 0, 17, +1472, 0, 78, +1473, 0, 150, +1474, 0, 230, +1476, 0, 319, +1478, 0, 417, +1481, 0, 521, +1485, 0, 631, +1489, 0, 746, +1496, 0, 865, +1497, 0, 1017, +1486, 0, 1269, +1469, 0, 1474, +1489, 0, 1660, +1524, 0, 1790, +1589, 0, 1905, +1653, 0, 2053, +1531, 656, 2197, +924, 1049, 2356, +1710, 0, 2469, +1801, 0, 2506, +1801, 0, 2506, +1801, 0, 2506, +1801, 0, 2506, +1801, 0, 2506, +1801, 0, 2506, +1801, 0, 2506, +1801, 0, 2506, +1801, 0, 2506, +1801, 0, 2506, +1471, 0, 0, +1471, 0, 17, +1471, 0, 97, +1472, 0, 149, +1472, 0, 211, +1474, 0, 282, +1475, 0, 363, +1477, 0, 452, +1480, 0, 549, +1484, 0, 653, +1489, 0, 763, +1496, 0, 878, +1497, 0, 1026, +1485, 0, 1273, +1469, 0, 1476, +1489, 0, 1661, +1524, 0, 1791, +1588, 0, 1905, +1652, 0, 2054, +1530, 671, 2198, +926, 1053, 2357, +1711, 0, 2469, +1802, 0, 2506, +1802, 0, 2506, +1802, 0, 2506, +1802, 0, 2506, +1802, 0, 2506, +1802, 0, 2506, +1802, 0, 2506, +1802, 0, 2506, +1802, 0, 2506, +1802, 0, 2506, +1471, 0, 18, +1471, 0, 78, +1471, 0, 149, +1471, 0, 229, +1472, 0, 281, +1473, 0, 343, +1475, 0, 414, +1477, 0, 494, +1480, 0, 584, +1483, 0, 681, +1488, 0, 785, +1495, 0, 895, +1496, 0, 1039, +1485, 0, 1278, +1468, 0, 1480, +1488, 0, 1662, +1524, 0, 1793, +1587, 0, 1907, +1651, 0, 2054, +1529, 690, 2198, +928, 1058, 2357, +1712, 0, 2469, +1803, 0, 2506, +1803, 0, 2506, +1803, 0, 2506, +1803, 0, 2506, +1803, 0, 2506, +1803, 0, 2506, +1803, 0, 2506, +1803, 0, 2506, +1803, 0, 2506, +1803, 0, 2506, +1471, 0, 98, +1471, 0, 150, +1471, 0, 211, +1471, 0, 281, +1471, 0, 361, +1472, 0, 413, +1474, 0, 475, +1476, 0, 546, +1479, 0, 627, +1482, 0, 716, +1487, 0, 813, +1494, 0, 917, +1495, 0, 1055, +1484, 0, 1285, +1467, 0, 1484, +1487, 0, 1664, +1524, 0, 1795, +1585, 0, 1908, +1650, 0, 2055, +1527, 714, 2199, +931, 1065, 2357, +1713, 0, 2469, +1804, 0, 2506, +1804, 0, 2506, +1804, 0, 2506, +1804, 0, 2506, +1804, 0, 2506, +1804, 0, 2506, +1804, 0, 2506, +1804, 0, 2506, +1804, 0, 2506, +1804, 0, 2506, +1471, 0, 188, +1471, 0, 230, +1471, 0, 282, +1471, 0, 343, +1471, 0, 413, +1471, 0, 493, +1472, 0, 545, +1475, 0, 607, +1478, 0, 678, +1481, 0, 759, +1486, 0, 848, +1493, 0, 946, +1494, 0, 1075, +1482, 0, 1294, +1466, 0, 1490, +1486, 0, 1667, +1524, 30, 1798, +1584, 0, 1911, +1648, 132, 2057, +1525, 745, 2200, +935, 1074, 2358, +1715, 0, 2469, +1806, 0, 2506, +1806, 0, 2506, +1806, 0, 2506, +1806, 0, 2506, +1806, 0, 2506, +1806, 0, 2506, +1806, 0, 2506, +1806, 0, 2506, +1806, 0, 2506, +1806, 0, 2506, +1471, 121, 285, +1471, 106, 319, +1471, 85, 363, +1471, 56, 414, +1471, 13, 475, +1471, 0, 545, +1471, 0, 625, +1473, 0, 677, +1476, 0, 739, +1480, 0, 810, +1485, 0, 891, +1491, 0, 980, +1493, 0, 1102, +1481, 0, 1306, +1464, 0, 1497, +1485, 0, 1670, +1524, 163, 1802, +1581, 32, 1914, +1646, 264, 2058, +1522, 783, 2201, +940, 1085, 2358, +1716, 32, 2469, +1809, 0, 2506, +1809, 0, 2506, +1809, 0, 2506, +1809, 0, 2506, +1809, 0, 2506, +1809, 0, 2506, +1809, 0, 2506, +1809, 0, 2506, +1809, 0, 2506, +1809, 0, 2506, +1471, 264, 389, +1471, 253, 417, +1471, 238, 452, +1471, 217, 494, +1471, 188, 546, +1471, 146, 607, +1471, 82, 677, +1471, 0, 757, +1474, 0, 809, +1478, 0, 871, +1483, 0, 942, +1489, 0, 1023, +1491, 0, 1135, +1479, 0, 1321, +1462, 0, 1507, +1482, 0, 1674, +1524, 295, 1807, +1578, 164, 1918, +1644, 396, 2061, +1518, 830, 2203, +947, 1100, 2359, +1719, 164, 2469, +1812, 0, 2506, +1812, 0, 2506, +1812, 0, 2506, +1812, 0, 2506, +1812, 0, 2506, +1812, 0, 2506, +1812, 0, 2506, +1812, 0, 2506, +1812, 0, 2506, +1812, 0, 2506, +1471, 404, 499, +1471, 396, 521, +1471, 385, 549, +1471, 370, 584, +1471, 349, 627, +1471, 320, 678, +1471, 277, 739, +1471, 214, 809, +1471, 111, 889, +1475, 111, 942, +1480, 111, 1003, +1486, 111, 1075, +1488, 111, 1176, +1476, 111, 1340, +1459, 111, 1520, +1480, 111, 1680, +1524, 426, 1814, +1573, 296, 1923, +1640, 528, 2064, +1513, 885, 2205, +956, 1119, 2361, +1717, 296, 2469, +1816, 111, 2506, +1816, 111, 2506, +1816, 111, 2506, +1816, 111, 2506, +1816, 111, 2506, +1816, 111, 2506, +1816, 111, 2506, +1816, 111, 2506, +1816, 111, 2506, +1816, 111, 2506, +1471, 542, 614, +1471, 536, 631, +1471, 528, 653, +1471, 517, 681, +1471, 502, 716, +1471, 482, 759, +1471, 452, 810, +1471, 410, 871, +1471, 346, 942, +1471, 244, 1021, +1476, 244, 1074, +1483, 244, 1135, +1484, 244, 1225, +1472, 244, 1369, +1455, 244, 1537, +1476, 244, 1687, +1520, 502, 1820, +1567, 428, 1930, +1634, 660, 2068, +1506, 950, 2208, +968, 1143, 2362, +1715, 428, 2469, +1821, 244, 2506, +1821, 244, 2506, +1821, 244, 2506, +1821, 244, 2506, +1821, 244, 2506, +1821, 244, 2506, +1821, 244, 2506, +1821, 244, 2506, +1821, 244, 2506, +1821, 244, 2506, +1471, 678, 733, +1471, 674, 746, +1471, 668, 763, +1471, 660, 785, +1471, 649, 813, +1471, 634, 848, +1471, 613, 891, +1471, 584, 942, +1471, 542, 1003, +1471, 478, 1074, +1471, 376, 1153, +1478, 376, 1206, +1479, 376, 1283, +1467, 376, 1412, +1450, 376, 1559, +1471, 376, 1701, +1516, 581, 1827, +1566, 591, 1940, +1627, 792, 2074, +1496, 1025, 2212, +983, 1174, 2364, +1712, 560, 2468, +1828, 376, 2506, +1828, 376, 2506, +1828, 376, 2506, +1828, 376, 2506, +1828, 376, 2506, +1828, 376, 2506, +1828, 376, 2506, +1828, 376, 2506, +1828, 376, 2506, +1828, 376, 2506, +1471, 814, 855, +1471, 811, 865, +1471, 806, 878, +1471, 800, 895, +1471, 792, 917, +1471, 782, 946, +1471, 767, 980, +1471, 746, 1023, +1471, 717, 1075, +1471, 674, 1135, +1471, 611, 1206, +1471, 508, 1285, +1472, 508, 1352, +1460, 508, 1465, +1443, 508, 1587, +1464, 508, 1721, +1509, 670, 1836, +1566, 751, 1952, +1617, 925, 2081, +1483, 1109, 2218, +935, 1212, 2368, +1708, 692, 2467, +1838, 508, 2506, +1838, 508, 2506, +1838, 508, 2506, +1838, 508, 2506, +1838, 508, 2506, +1838, 508, 2506, +1838, 508, 2506, +1838, 508, 2506, +1838, 508, 2506, +1838, 508, 2506, +1467, 954, 955, +1467, 954, 960, +1467, 951, 971, +1467, 947, 985, +1467, 941, 1004, +1467, 933, 1027, +1467, 923, 1056, +1467, 908, 1092, +1467, 888, 1137, +1467, 859, 1191, +1467, 818, 1254, +1467, 755, 1326, +1471, 701, 1400, +1458, 701, 1503, +1441, 701, 1611, +1446, 742, 1738, +1508, 833, 1851, +1542, 872, 1959, +1602, 1037, 2091, +1448, 1185, 2224, +886, 1254, 2372, +1718, 855, 2468, +1839, 727, 2507, +1839, 727, 2507, +1839, 727, 2507, +1839, 727, 2507, +1839, 727, 2507, +1839, 727, 2507, +1839, 727, 2507, +1839, 727, 2507, +1839, 727, 2507, +1839, 727, 2507, +1503, 1167, 1293, +1503, 1167, 1296, +1504, 1167, 1299, +1504, 1167, 1304, +1505, 1167, 1311, +1506, 1167, 1319, +1508, 1167, 1330, +1510, 1167, 1344, +1512, 1167, 1363, +1514, 1162, 1390, +1514, 1141, 1432, +1514, 1111, 1482, +1517, 1087, 1536, +1506, 1087, 1597, +1491, 1087, 1687, +1446, 1077, 1783, +1489, 1144, 1900, +1509, 1144, 1988, +1532, 1221, 2116, +1329, 1289, 2240, +1151, 1275, 2372, +1721, 1061, 2469, +1839, 1003, 2508, +1839, 1003, 2508, +1839, 1003, 2508, +1839, 1003, 2508, +1839, 1003, 2508, +1839, 1003, 2508, +1839, 1003, 2508, +1839, 1003, 2508, +1839, 1003, 2508, +1839, 1003, 2508, +1547, 1351, 1534, +1547, 1351, 1536, +1547, 1351, 1538, +1548, 1351, 1541, +1549, 1351, 1545, +1550, 1351, 1550, +1551, 1351, 1556, +1553, 1351, 1565, +1555, 1351, 1577, +1558, 1351, 1592, +1563, 1351, 1611, +1569, 1351, 1636, +1573, 1345, 1671, +1563, 1345, 1717, +1550, 1345, 1771, +1498, 1335, 1850, +1489, 1358, 1942, +1476, 1376, 2036, +1418, 1388, 2147, +1096, 1399, 2261, +1290, 1332, 2375, +1730, 1258, 2473, +1839, 1219, 2510, +1839, 1219, 2510, +1839, 1219, 2510, +1839, 1219, 2510, +1839, 1219, 2510, +1839, 1219, 2510, +1839, 1219, 2510, +1839, 1219, 2510, +1839, 1219, 2510, +1839, 1219, 2510, +1626, 1522, 1733, +1625, 1522, 1734, +1625, 1522, 1734, +1623, 1522, 1735, +1622, 1522, 1736, +1621, 1522, 1737, +1618, 1522, 1739, +1615, 1522, 1742, +1611, 1522, 1745, +1605, 1522, 1749, +1605, 1522, 1760, +1609, 1522, 1778, +1596, 1523, 1805, +1587, 1534, 1850, +1574, 1537, 1894, +1558, 1522, 1941, +1509, 1521, 2012, +1413, 1563, 2107, +1330, 1535, 2187, +1296, 1523, 2285, +1459, 1491, 2382, +1767, 1446, 2474, +1910, 1416, 2509, +1910, 1416, 2509, +1910, 1416, 2509, +1910, 1416, 2509, +1910, 1416, 2509, +1910, 1416, 2509, +1910, 1416, 2509, +1910, 1416, 2509, +1910, 1416, 2509, +1910, 1416, 2509, +1737, 1669, 1898, +1737, 1669, 1899, +1737, 1669, 1900, +1737, 1669, 1901, +1737, 1669, 1903, +1737, 1669, 1905, +1737, 1669, 1908, +1737, 1669, 1913, +1737, 1669, 1918, +1732, 1669, 1922, +1727, 1669, 1925, +1719, 1669, 1930, +1711, 1672, 1940, +1697, 1674, 1960, +1687, 1684, 2003, +1675, 1681, 2036, +1638, 1672, 2080, +1565, 1674, 2153, +1492, 1672, 2229, +1526, 1649, 2305, +1680, 1621, 2385, +1871, 1607, 2473, +1954, 1605, 2509, +1954, 1605, 2509, +1954, 1605, 2509, +1954, 1605, 2509, +1954, 1605, 2509, +1954, 1605, 2509, +1954, 1605, 2509, +1954, 1605, 2509, +1954, 1605, 2509, +1954, 1605, 2509, +1862, 1802, 1972, +1862, 1802, 1973, +1862, 1802, 1973, +1862, 1803, 1975, +1862, 1803, 1976, +1863, 1804, 1978, +1864, 1805, 1981, +1865, 1806, 1984, +1866, 1807, 1989, +1868, 1809, 1995, +1868, 1809, 2004, +1868, 1809, 2014, +1861, 1811, 2027, +1856, 1811, 2038, +1842, 1811, 2056, +1824, 1809, 2088, +1829, 1804, 2122, +1805, 1804, 2175, +1793, 1801, 2242, +1782, 1800, 2309, +1820, 1797, 2390, +1940, 1796, 2477, +2014, 1783, 2512, +2014, 1783, 2512, +2014, 1783, 2512, +2014, 1783, 2512, +2014, 1783, 2512, +2014, 1783, 2512, +2014, 1783, 2512, +2014, 1783, 2512, +2014, 1783, 2512, +2014, 1783, 2512, +1992, 1958, 2037, +1992, 1958, 2037, +1992, 1958, 2037, +1992, 1958, 2037, +1992, 1958, 2037, +1992, 1958, 2038, +1992, 1958, 2038, +1992, 1958, 2039, +1992, 1958, 2040, +1992, 1958, 2041, +1992, 1958, 2042, +1992, 1958, 2044, +1989, 1958, 2051, +1984, 1962, 2068, +1979, 1968, 2090, +1970, 1962, 2115, +1966, 1962, 2148, +1966, 1964, 2190, +1964, 1947, 2231, +1943, 1947, 2310, +1978, 1965, 2395, +2061, 1971, 2481, +2133, 1968, 2516, +2133, 1968, 2516, +2133, 1968, 2516, +2133, 1968, 2516, +2133, 1968, 2516, +2133, 1968, 2516, +2133, 1968, 2516, +2133, 1968, 2516, +2133, 1968, 2516, +2133, 1968, 2516, +2142, 2127, 2061, +2142, 2127, 2061, +2142, 2127, 2062, +2142, 2127, 2063, +2142, 2127, 2064, +2143, 2127, 2065, +2143, 2127, 2067, +2143, 2127, 2069, +2144, 2127, 2072, +2145, 2127, 2076, +2146, 2127, 2082, +2148, 2127, 2089, +2148, 2127, 2095, +2143, 2127, 2104, +2135, 2127, 2116, +2137, 2127, 2132, +2144, 2131, 2161, +2141, 2135, 2204, +2133, 2127, 2256, +2149, 2134, 2316, +2174, 2130, 2395, +2237, 2146, 2485, +2277, 2159, 2520, +2277, 2159, 2520, +2277, 2159, 2520, +2277, 2159, 2520, +2277, 2159, 2520, +2277, 2159, 2520, +2277, 2159, 2520, +2277, 2159, 2520, +2277, 2159, 2520, +2277, 2159, 2520, +2379, 2355, 2126, +2380, 2355, 2127, +2380, 2355, 2127, +2380, 2355, 2127, +2380, 2355, 2127, +2380, 2355, 2127, +2380, 2355, 2128, +2381, 2355, 2128, +2381, 2355, 2129, +2381, 2355, 2130, +2382, 2355, 2131, +2382, 2355, 2133, +2382, 2355, 2135, +2381, 2357, 2141, +2379, 2358, 2148, +2379, 2355, 2161, +2378, 2357, 2192, +2376, 2358, 2230, +2382, 2354, 2270, +2402, 2364, 2335, +2420, 2368, 2405, +2473, 2383, 2495, +2499, 2394, 2533, +2499, 2394, 2533, +2499, 2394, 2533, +2499, 2394, 2533, +2499, 2394, 2533, +2499, 2394, 2533, +2499, 2394, 2533, +2499, 2394, 2533, +2499, 2394, 2533, +2499, 2394, 2533, +2681, 2657, 1947, +2681, 2657, 1947, +2681, 2657, 1947, +2681, 2657, 1947, +2681, 2657, 1947, +2681, 2657, 1947, +2681, 2657, 1947, +2681, 2657, 1947, +2681, 2656, 1951, +2680, 2656, 1956, +2680, 2656, 1963, +2679, 2655, 1973, +2679, 2654, 1971, +2678, 2651, 1967, +2678, 2651, 1962, +2678, 2655, 2011, +2679, 2657, 2064, +2682, 2657, 2129, +2684, 2657, 2213, +2688, 2661, 2311, +2699, 2668, 2415, +2717, 2681, 2528, +2726, 2683, 2577, +2726, 2683, 2577, +2726, 2683, 2577, +2726, 2683, 2577, +2726, 2683, 2577, +2726, 2683, 2577, +2726, 2683, 2577, +2726, 2683, 2577, +2726, 2683, 2577, +2726, 2683, 2577, +2715, 2769, 2427, +2716, 2769, 2427, +2716, 2769, 2427, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2429, +2716, 2769, 2429, +2717, 2769, 2430, +2717, 2769, 2431, +2718, 2770, 2433, +2719, 2772, 2443, +2720, 2775, 2457, +2716, 2772, 2452, +2713, 2770, 2455, +2714, 2773, 2485, +2718, 2774, 2523, +2717, 2777, 2567, +2721, 2782, 2627, +2725, 2788, 2702, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2715, 2769, 2427, +2716, 2769, 2427, +2716, 2769, 2427, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2429, +2716, 2769, 2429, +2717, 2769, 2430, +2717, 2769, 2431, +2718, 2770, 2433, +2719, 2772, 2443, +2720, 2775, 2457, +2716, 2772, 2452, +2713, 2770, 2455, +2714, 2773, 2485, +2718, 2774, 2523, +2717, 2777, 2567, +2721, 2782, 2627, +2725, 2788, 2702, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2715, 2769, 2427, +2716, 2769, 2427, +2716, 2769, 2427, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2429, +2716, 2769, 2429, +2717, 2769, 2430, +2717, 2769, 2431, +2718, 2770, 2433, +2719, 2772, 2443, +2720, 2775, 2457, +2716, 2772, 2452, +2713, 2770, 2455, +2714, 2773, 2485, +2718, 2774, 2523, +2717, 2777, 2567, +2721, 2782, 2627, +2725, 2788, 2702, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2715, 2769, 2427, +2716, 2769, 2427, +2716, 2769, 2427, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2429, +2716, 2769, 2429, +2717, 2769, 2430, +2717, 2769, 2431, +2718, 2770, 2433, +2719, 2772, 2443, +2720, 2775, 2457, +2716, 2772, 2452, +2713, 2770, 2455, +2714, 2773, 2485, +2718, 2774, 2523, +2717, 2777, 2567, +2721, 2782, 2627, +2725, 2788, 2702, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2715, 2769, 2427, +2716, 2769, 2427, +2716, 2769, 2427, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2429, +2716, 2769, 2429, +2717, 2769, 2430, +2717, 2769, 2431, +2718, 2770, 2433, +2719, 2772, 2443, +2720, 2775, 2457, +2716, 2772, 2452, +2713, 2770, 2455, +2714, 2773, 2485, +2718, 2774, 2523, +2717, 2777, 2567, +2721, 2782, 2627, +2725, 2788, 2702, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2715, 2769, 2427, +2716, 2769, 2427, +2716, 2769, 2427, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2429, +2716, 2769, 2429, +2717, 2769, 2430, +2717, 2769, 2431, +2718, 2770, 2433, +2719, 2772, 2443, +2720, 2775, 2457, +2716, 2772, 2452, +2713, 2770, 2455, +2714, 2773, 2485, +2718, 2774, 2523, +2717, 2777, 2567, +2721, 2782, 2627, +2725, 2788, 2702, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2715, 2769, 2427, +2716, 2769, 2427, +2716, 2769, 2427, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2429, +2716, 2769, 2429, +2717, 2769, 2430, +2717, 2769, 2431, +2718, 2770, 2433, +2719, 2772, 2443, +2720, 2775, 2457, +2716, 2772, 2452, +2713, 2770, 2455, +2714, 2773, 2485, +2718, 2774, 2523, +2717, 2777, 2567, +2721, 2782, 2627, +2725, 2788, 2702, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2715, 2769, 2427, +2716, 2769, 2427, +2716, 2769, 2427, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2429, +2716, 2769, 2429, +2717, 2769, 2430, +2717, 2769, 2431, +2718, 2770, 2433, +2719, 2772, 2443, +2720, 2775, 2457, +2716, 2772, 2452, +2713, 2770, 2455, +2714, 2773, 2485, +2718, 2774, 2523, +2717, 2777, 2567, +2721, 2782, 2627, +2725, 2788, 2702, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2715, 2769, 2427, +2716, 2769, 2427, +2716, 2769, 2427, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2429, +2716, 2769, 2429, +2717, 2769, 2430, +2717, 2769, 2431, +2718, 2770, 2433, +2719, 2772, 2443, +2720, 2775, 2457, +2716, 2772, 2452, +2713, 2770, 2455, +2714, 2773, 2485, +2718, 2774, 2523, +2717, 2777, 2567, +2721, 2782, 2627, +2725, 2788, 2702, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2715, 2769, 2427, +2716, 2769, 2427, +2716, 2769, 2427, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2428, +2716, 2769, 2429, +2716, 2769, 2429, +2717, 2769, 2430, +2717, 2769, 2431, +2718, 2770, 2433, +2719, 2772, 2443, +2720, 2775, 2457, +2716, 2772, 2452, +2713, 2770, 2455, +2714, 2773, 2485, +2718, 2774, 2523, +2717, 2777, 2567, +2721, 2782, 2627, +2725, 2788, 2702, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +2729, 2794, 2733, +1677, 0, 708, +1676, 0, 722, +1676, 0, 740, +1675, 0, 763, +1674, 0, 792, +1672, 0, 829, +1670, 0, 873, +1667, 0, 927, +1663, 0, 989, +1658, 0, 1062, +1657, 0, 1123, +1662, 0, 1179, +1666, 0, 1250, +1649, 0, 1372, +1636, 0, 1533, +1634, 0, 1672, +1671, 0, 1828, +1667, 0, 1929, +1689, 355, 2079, +1608, 810, 2211, +1232, 994, 2359, +1771, 0, 2470, +1854, 0, 2508, +1854, 0, 2508, +1854, 0, 2508, +1854, 0, 2508, +1854, 0, 2508, +1854, 0, 2508, +1854, 0, 2508, +1854, 0, 2508, +1854, 0, 2508, +1854, 0, 2508, +1676, 0, 726, +1676, 0, 735, +1675, 0, 753, +1674, 0, 775, +1673, 0, 804, +1672, 0, 839, +1669, 0, 883, +1667, 0, 935, +1663, 0, 997, +1658, 0, 1068, +1657, 0, 1129, +1662, 0, 1184, +1666, 0, 1253, +1649, 0, 1375, +1636, 0, 1535, +1635, 0, 1673, +1670, 0, 1829, +1666, 0, 1930, +1689, 372, 2079, +1607, 814, 2211, +1238, 995, 2359, +1771, 0, 2470, +1855, 0, 2508, +1855, 0, 2508, +1855, 0, 2508, +1855, 0, 2508, +1855, 0, 2508, +1855, 0, 2508, +1855, 0, 2508, +1855, 0, 2508, +1855, 0, 2508, +1855, 0, 2508, +1676, 0, 749, +1675, 0, 758, +1675, 0, 770, +1674, 0, 791, +1673, 0, 819, +1672, 0, 853, +1669, 0, 895, +1666, 0, 946, +1663, 0, 1007, +1657, 0, 1077, +1657, 0, 1136, +1661, 0, 1191, +1665, 0, 1259, +1649, 0, 1378, +1636, 0, 1537, +1635, 0, 1674, +1669, 0, 1829, +1665, 0, 1930, +1688, 394, 2080, +1606, 821, 2211, +1245, 996, 2359, +1771, 0, 2470, +1855, 0, 2508, +1855, 0, 2508, +1855, 0, 2508, +1855, 0, 2508, +1855, 0, 2508, +1855, 0, 2508, +1855, 0, 2508, +1855, 0, 2508, +1855, 0, 2508, +1855, 0, 2508, +1675, 0, 777, +1674, 0, 786, +1674, 0, 797, +1674, 0, 812, +1673, 0, 838, +1671, 0, 871, +1669, 0, 912, +1666, 0, 961, +1662, 0, 1020, +1657, 0, 1088, +1656, 0, 1146, +1661, 0, 1199, +1665, 0, 1266, +1649, 0, 1383, +1636, 0, 1541, +1636, 0, 1676, +1668, 0, 1830, +1663, 0, 1932, +1687, 422, 2080, +1605, 829, 2212, +1255, 998, 2359, +1772, 0, 2470, +1855, 0, 2508, +1855, 0, 2508, +1855, 0, 2508, +1855, 0, 2508, +1855, 0, 2508, +1855, 0, 2508, +1855, 0, 2508, +1855, 0, 2508, +1855, 0, 2508, +1855, 0, 2508, +1674, 0, 814, +1673, 0, 822, +1673, 0, 832, +1673, 0, 845, +1672, 0, 863, +1671, 0, 894, +1668, 0, 933, +1666, 0, 980, +1662, 0, 1036, +1656, 0, 1102, +1655, 0, 1159, +1660, 0, 1210, +1664, 0, 1276, +1649, 0, 1390, +1636, 0, 1545, +1637, 0, 1679, +1667, 0, 1831, +1662, 0, 1934, +1686, 457, 2081, +1603, 840, 2212, +1268, 1001, 2360, +1772, 0, 2470, +1856, 0, 2508, +1856, 0, 2508, +1856, 0, 2508, +1856, 0, 2508, +1856, 0, 2508, +1856, 0, 2508, +1856, 0, 2508, +1856, 0, 2508, +1856, 0, 2508, +1856, 0, 2508, +1672, 0, 858, +1672, 0, 865, +1672, 0, 874, +1671, 0, 887, +1671, 0, 903, +1670, 0, 923, +1667, 0, 960, +1664, 0, 1004, +1661, 0, 1058, +1655, 0, 1121, +1655, 0, 1175, +1659, 0, 1225, +1663, 0, 1289, +1649, 0, 1398, +1636, 0, 1551, +1639, 0, 1683, +1666, 0, 1832, +1659, 132, 1936, +1684, 500, 2083, +1600, 854, 2213, +1285, 1004, 2360, +1773, 0, 2470, +1857, 0, 2508, +1857, 0, 2508, +1857, 0, 2508, +1857, 0, 2508, +1857, 0, 2508, +1857, 0, 2508, +1857, 0, 2508, +1857, 0, 2508, +1857, 0, 2508, +1857, 0, 2508, +1670, 32, 911, +1669, 32, 917, +1669, 32, 926, +1669, 32, 937, +1668, 32, 951, +1667, 32, 970, +1667, 32, 993, +1663, 32, 1035, +1660, 32, 1085, +1654, 32, 1144, +1654, 32, 1196, +1658, 32, 1244, +1662, 0, 1305, +1649, 0, 1410, +1636, 0, 1560, +1641, 32, 1688, +1663, 32, 1833, +1656, 264, 1939, +1682, 551, 2084, +1596, 873, 2214, +1306, 1009, 2361, +1773, 0, 2470, +1859, 32, 2508, +1859, 32, 2508, +1859, 32, 2508, +1859, 32, 2508, +1859, 32, 2508, +1859, 32, 2508, +1859, 32, 2508, +1859, 32, 2508, +1859, 32, 2508, +1859, 32, 2508, +1667, 164, 973, +1667, 164, 979, +1666, 164, 986, +1666, 164, 996, +1666, 164, 1009, +1664, 164, 1025, +1663, 164, 1046, +1662, 164, 1073, +1658, 164, 1119, +1653, 164, 1174, +1652, 164, 1223, +1657, 164, 1268, +1661, 137, 1326, +1649, 0, 1424, +1636, 0, 1570, +1644, 164, 1695, +1661, 164, 1835, +1652, 396, 1943, +1680, 612, 2086, +1591, 896, 2215, +1333, 1014, 2362, +1774, 0, 2470, +1861, 164, 2508, +1861, 164, 2508, +1861, 164, 2508, +1861, 164, 2508, +1861, 164, 2508, +1861, 164, 2508, +1861, 164, 2508, +1861, 164, 2508, +1861, 164, 2508, +1861, 164, 2508, +1663, 296, 1045, +1663, 296, 1050, +1663, 296, 1056, +1662, 296, 1065, +1662, 296, 1075, +1661, 296, 1090, +1660, 296, 1108, +1658, 296, 1131, +1656, 296, 1161, +1651, 296, 1212, +1650, 296, 1257, +1655, 296, 1299, +1659, 276, 1353, +1649, 111, 1443, +1636, 111, 1584, +1648, 296, 1704, +1657, 296, 1838, +1646, 528, 1948, +1676, 683, 2089, +1585, 926, 2217, +1367, 1022, 2363, +1772, 0, 2470, +1863, 296, 2508, +1863, 296, 2508, +1863, 296, 2508, +1863, 296, 2508, +1863, 296, 2508, +1863, 296, 2508, +1863, 296, 2508, +1863, 296, 2508, +1863, 296, 2508, +1863, 296, 2508, +1658, 428, 1127, +1658, 428, 1131, +1657, 428, 1136, +1657, 428, 1143, +1656, 428, 1152, +1655, 428, 1164, +1654, 428, 1180, +1653, 428, 1200, +1651, 428, 1225, +1648, 428, 1257, +1648, 428, 1298, +1653, 428, 1336, +1657, 413, 1387, +1648, 265, 1468, +1636, 244, 1601, +1653, 428, 1715, +1661, 428, 1846, +1638, 660, 1955, +1671, 762, 2093, +1576, 963, 2219, +1408, 1032, 2365, +1768, 91, 2470, +1866, 428, 2508, +1866, 428, 2508, +1866, 428, 2508, +1866, 428, 2508, +1866, 428, 2508, +1866, 428, 2508, +1866, 428, 2508, +1866, 428, 2508, +1866, 428, 2508, +1866, 428, 2508, +1655, 583, 1188, +1655, 583, 1191, +1654, 583, 1196, +1654, 583, 1202, +1654, 583, 1210, +1653, 583, 1221, +1651, 583, 1234, +1650, 583, 1252, +1648, 583, 1275, +1646, 583, 1304, +1644, 536, 1348, +1649, 536, 1383, +1653, 524, 1429, +1645, 413, 1503, +1633, 376, 1622, +1654, 536, 1730, +1662, 536, 1854, +1635, 766, 1962, +1664, 863, 2099, +1566, 1025, 2222, +1432, 1062, 2367, +1764, 309, 2470, +1872, 536, 2508, +1872, 536, 2508, +1872, 536, 2508, +1872, 536, 2508, +1872, 536, 2508, +1872, 536, 2508, +1872, 536, 2508, +1872, 536, 2508, +1872, 536, 2508, +1872, 536, 2508, +1655, 745, 1237, +1655, 745, 1240, +1654, 745, 1244, +1654, 745, 1249, +1654, 745, 1257, +1653, 745, 1266, +1651, 745, 1279, +1650, 745, 1295, +1648, 745, 1315, +1646, 745, 1342, +1644, 713, 1383, +1644, 633, 1439, +1648, 624, 1479, +1640, 536, 1547, +1628, 508, 1646, +1649, 633, 1749, +1657, 633, 1863, +1635, 881, 1973, +1655, 979, 2105, +1554, 1109, 2228, +1415, 1110, 2370, +1760, 519, 2469, +1880, 633, 2508, +1880, 633, 2508, +1880, 633, 2508, +1880, 633, 2508, +1880, 633, 2508, +1880, 633, 2508, +1880, 633, 2508, +1880, 633, 2508, +1880, 633, 2508, +1880, 633, 2508, +1655, 918, 1304, +1656, 918, 1306, +1655, 918, 1310, +1655, 918, 1314, +1654, 918, 1320, +1654, 918, 1329, +1653, 918, 1340, +1651, 918, 1354, +1649, 918, 1372, +1647, 918, 1395, +1645, 897, 1432, +1645, 845, 1482, +1643, 779, 1541, +1635, 719, 1601, +1623, 701, 1686, +1641, 772, 1775, +1650, 779, 1877, +1631, 1007, 1989, +1643, 1092, 2115, +1533, 1205, 2236, +1384, 1170, 2375, +1758, 725, 2468, +1889, 758, 2508, +1889, 758, 2508, +1889, 758, 2508, +1889, 758, 2508, +1889, 758, 2508, +1889, 758, 2508, +1889, 758, 2508, +1889, 758, 2508, +1889, 758, 2508, +1889, 758, 2508, +1647, 1170, 1441, +1648, 1170, 1443, +1648, 1170, 1445, +1648, 1170, 1448, +1649, 1170, 1452, +1650, 1170, 1457, +1651, 1170, 1463, +1653, 1170, 1472, +1654, 1170, 1484, +1655, 1170, 1500, +1654, 1157, 1529, +1654, 1129, 1570, +1651, 1095, 1619, +1635, 1095, 1678, +1623, 1087, 1751, +1615, 1062, 1817, +1632, 1090, 1907, +1595, 1178, 2016, +1626, 1217, 2123, +1463, 1323, 2255, +1427, 1258, 2375, +1780, 1002, 2468, +1884, 986, 2506, +1884, 986, 2506, +1884, 986, 2506, +1884, 986, 2506, +1884, 986, 2506, +1884, 986, 2506, +1884, 986, 2506, +1884, 986, 2506, +1884, 986, 2506, +1884, 986, 2506, +1671, 1358, 1617, +1671, 1358, 1618, +1672, 1358, 1619, +1672, 1358, 1621, +1672, 1358, 1624, +1673, 1358, 1628, +1674, 1358, 1632, +1676, 1358, 1638, +1678, 1358, 1646, +1680, 1358, 1657, +1683, 1358, 1672, +1687, 1358, 1694, +1687, 1345, 1729, +1672, 1345, 1775, +1659, 1345, 1825, +1644, 1322, 1879, +1625, 1320, 1950, +1565, 1390, 2060, +1550, 1377, 2150, +1313, 1430, 2275, +1491, 1332, 2378, +1794, 1220, 2471, +1883, 1202, 2507, +1883, 1202, 2507, +1883, 1202, 2507, +1883, 1202, 2507, +1883, 1202, 2507, +1883, 1202, 2507, +1883, 1202, 2507, +1883, 1202, 2507, +1883, 1202, 2507, +1883, 1202, 2507, +1720, 1522, 1779, +1720, 1522, 1780, +1719, 1522, 1781, +1718, 1522, 1782, +1717, 1522, 1783, +1716, 1522, 1785, +1714, 1522, 1787, +1712, 1522, 1790, +1708, 1522, 1795, +1704, 1522, 1800, +1703, 1522, 1811, +1707, 1522, 1827, +1711, 1522, 1847, +1703, 1522, 1873, +1693, 1522, 1912, +1668, 1522, 1965, +1628, 1506, 2021, +1607, 1566, 2121, +1540, 1536, 2191, +1494, 1506, 2283, +1572, 1474, 2382, +1813, 1446, 2473, +1923, 1435, 2511, +1923, 1435, 2511, +1923, 1435, 2511, +1923, 1435, 2511, +1923, 1435, 2511, +1923, 1435, 2511, +1923, 1435, 2511, +1923, 1435, 2511, +1923, 1435, 2511, +1923, 1435, 2511, +1810, 1655, 1910, +1809, 1655, 1911, +1809, 1655, 1911, +1808, 1655, 1912, +1807, 1656, 1913, +1806, 1657, 1915, +1805, 1658, 1918, +1802, 1659, 1921, +1800, 1661, 1925, +1796, 1662, 1930, +1791, 1662, 1934, +1784, 1662, 1939, +1776, 1662, 1948, +1775, 1662, 1972, +1766, 1670, 2011, +1745, 1681, 2051, +1732, 1662, 2087, +1680, 1676, 2155, +1604, 1655, 2226, +1644, 1643, 2305, +1738, 1626, 2385, +1900, 1611, 2473, +1984, 1617, 2510, +1984, 1617, 2510, +1984, 1617, 2510, +1984, 1617, 2510, +1984, 1617, 2510, +1984, 1617, 2510, +1984, 1617, 2510, +1984, 1617, 2510, +1984, 1617, 2510, +1984, 1617, 2510, +1907, 1800, 1983, +1907, 1800, 1984, +1907, 1800, 1984, +1907, 1800, 1985, +1907, 1800, 1986, +1907, 1800, 1987, +1907, 1800, 1989, +1907, 1800, 1991, +1907, 1800, 1994, +1907, 1800, 1997, +1906, 1801, 2005, +1906, 1801, 2015, +1905, 1801, 2029, +1901, 1801, 2043, +1890, 1801, 2062, +1872, 1801, 2086, +1874, 1807, 2128, +1850, 1801, 2174, +1847, 1800, 2243, +1818, 1792, 2312, +1871, 1797, 2387, +1976, 1799, 2480, +2034, 1783, 2511, +2034, 1783, 2511, +2034, 1783, 2511, +2034, 1783, 2511, +2034, 1783, 2511, +2034, 1783, 2511, +2034, 1783, 2511, +2034, 1783, 2511, +2034, 1783, 2511, +2034, 1783, 2511, +2034, 1958, 2033, +2033, 1958, 2033, +2033, 1958, 2034, +2032, 1958, 2034, +2031, 1959, 2036, +2031, 1959, 2037, +2029, 1960, 2039, +2027, 1961, 2041, +2025, 1961, 2044, +2021, 1963, 2049, +2020, 1963, 2052, +2020, 1963, 2054, +2020, 1963, 2059, +2020, 1959, 2069, +2016, 1962, 2088, +2004, 1969, 2111, +1998, 1964, 2152, +1993, 1963, 2193, +1987, 1952, 2238, +1975, 1952, 2313, +2009, 1966, 2398, +2073, 1966, 2481, +2135, 1969, 2517, +2135, 1969, 2517, +2135, 1969, 2517, +2135, 1969, 2517, +2135, 1969, 2517, +2135, 1969, 2517, +2135, 1969, 2517, +2135, 1969, 2517, +2135, 1969, 2517, +2135, 1969, 2517, +2163, 2131, 2063, +2163, 2131, 2063, +2163, 2131, 2064, +2163, 2131, 2065, +2163, 2131, 2065, +2163, 2131, 2066, +2163, 2131, 2068, +2163, 2131, 2069, +2163, 2131, 2072, +2163, 2131, 2075, +2164, 2131, 2080, +2165, 2131, 2087, +2166, 2131, 2096, +2164, 2131, 2105, +2157, 2131, 2117, +2148, 2127, 2128, +2154, 2127, 2154, +2155, 2131, 2206, +2143, 2127, 2260, +2159, 2135, 2315, +2188, 2134, 2395, +2251, 2149, 2486, +2283, 2159, 2520, +2283, 2159, 2520, +2283, 2159, 2520, +2283, 2159, 2520, +2283, 2159, 2520, +2283, 2159, 2520, +2283, 2159, 2520, +2283, 2159, 2520, +2283, 2159, 2520, +2283, 2159, 2520, +2386, 2355, 2123, +2386, 2355, 2123, +2386, 2356, 2123, +2387, 2356, 2123, +2387, 2356, 2124, +2387, 2356, 2124, +2387, 2356, 2125, +2387, 2357, 2126, +2388, 2357, 2127, +2388, 2357, 2129, +2389, 2358, 2131, +2389, 2358, 2133, +2389, 2357, 2135, +2386, 2356, 2141, +2384, 2356, 2148, +2382, 2356, 2170, +2388, 2357, 2191, +2386, 2356, 2226, +2394, 2358, 2272, +2409, 2366, 2337, +2431, 2373, 2403, +2476, 2384, 2495, +2508, 2398, 2531, +2508, 2398, 2531, +2508, 2398, 2531, +2508, 2398, 2531, +2508, 2398, 2531, +2508, 2398, 2531, +2508, 2398, 2531, +2508, 2398, 2531, +2508, 2398, 2531, +2508, 2398, 2531, +2684, 2656, 1957, +2684, 2656, 1957, +2684, 2656, 1956, +2684, 2656, 1956, +2684, 2656, 1956, +2684, 2656, 1956, +2684, 2656, 1955, +2684, 2656, 1954, +2684, 2656, 1955, +2684, 2656, 1956, +2684, 2656, 1961, +2683, 2656, 1971, +2683, 2655, 1982, +2682, 2655, 1994, +2682, 2655, 1993, +2681, 2656, 2011, +2682, 2656, 2069, +2683, 2657, 2133, +2686, 2657, 2216, +2691, 2663, 2315, +2700, 2669, 2417, +2719, 2681, 2533, +2726, 2683, 2576, +2726, 2683, 2576, +2726, 2683, 2576, +2726, 2683, 2576, +2726, 2683, 2576, +2726, 2683, 2576, +2726, 2683, 2576, +2726, 2683, 2576, +2726, 2683, 2576, +2726, 2683, 2576, +2718, 2771, 2437, +2718, 2771, 2437, +2718, 2771, 2437, +2718, 2771, 2436, +2718, 2771, 2436, +2718, 2771, 2435, +2718, 2771, 2435, +2717, 2770, 2434, +2717, 2770, 2432, +2717, 2770, 2430, +2717, 2769, 2430, +2718, 2769, 2431, +2718, 2770, 2433, +2719, 2771, 2443, +2720, 2774, 2457, +2721, 2773, 2466, +2716, 2771, 2466, +2717, 2774, 2492, +2718, 2776, 2528, +2718, 2777, 2569, +2722, 2782, 2624, +2727, 2788, 2703, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2718, 2771, 2437, +2718, 2771, 2437, +2718, 2771, 2437, +2718, 2771, 2436, +2718, 2771, 2436, +2718, 2771, 2435, +2718, 2771, 2435, +2717, 2770, 2434, +2717, 2770, 2432, +2717, 2770, 2430, +2717, 2769, 2430, +2718, 2769, 2431, +2718, 2770, 2433, +2719, 2771, 2443, +2720, 2774, 2457, +2721, 2773, 2466, +2716, 2771, 2466, +2717, 2774, 2492, +2718, 2776, 2528, +2718, 2777, 2569, +2722, 2782, 2624, +2727, 2788, 2703, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2718, 2771, 2437, +2718, 2771, 2437, +2718, 2771, 2437, +2718, 2771, 2436, +2718, 2771, 2436, +2718, 2771, 2435, +2718, 2771, 2435, +2717, 2770, 2434, +2717, 2770, 2432, +2717, 2770, 2430, +2717, 2769, 2430, +2718, 2769, 2431, +2718, 2770, 2433, +2719, 2771, 2443, +2720, 2774, 2457, +2721, 2773, 2466, +2716, 2771, 2466, +2717, 2774, 2492, +2718, 2776, 2528, +2718, 2777, 2569, +2722, 2782, 2624, +2727, 2788, 2703, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2718, 2771, 2437, +2718, 2771, 2437, +2718, 2771, 2437, +2718, 2771, 2436, +2718, 2771, 2436, +2718, 2771, 2435, +2718, 2771, 2435, +2717, 2770, 2434, +2717, 2770, 2432, +2717, 2770, 2430, +2717, 2769, 2430, +2718, 2769, 2431, +2718, 2770, 2433, +2719, 2771, 2443, +2720, 2774, 2457, +2721, 2773, 2466, +2716, 2771, 2466, +2717, 2774, 2492, +2718, 2776, 2528, +2718, 2777, 2569, +2722, 2782, 2624, +2727, 2788, 2703, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2718, 2771, 2437, +2718, 2771, 2437, +2718, 2771, 2437, +2718, 2771, 2436, +2718, 2771, 2436, +2718, 2771, 2435, +2718, 2771, 2435, +2717, 2770, 2434, +2717, 2770, 2432, +2717, 2770, 2430, +2717, 2769, 2430, +2718, 2769, 2431, +2718, 2770, 2433, +2719, 2771, 2443, +2720, 2774, 2457, +2721, 2773, 2466, +2716, 2771, 2466, +2717, 2774, 2492, +2718, 2776, 2528, +2718, 2777, 2569, +2722, 2782, 2624, +2727, 2788, 2703, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2718, 2771, 2437, +2718, 2771, 2437, +2718, 2771, 2437, +2718, 2771, 2436, +2718, 2771, 2436, +2718, 2771, 2435, +2718, 2771, 2435, +2717, 2770, 2434, +2717, 2770, 2432, +2717, 2770, 2430, +2717, 2769, 2430, +2718, 2769, 2431, +2718, 2770, 2433, +2719, 2771, 2443, +2720, 2774, 2457, +2721, 2773, 2466, +2716, 2771, 2466, +2717, 2774, 2492, +2718, 2776, 2528, +2718, 2777, 2569, +2722, 2782, 2624, +2727, 2788, 2703, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2718, 2771, 2437, +2718, 2771, 2437, +2718, 2771, 2437, +2718, 2771, 2436, +2718, 2771, 2436, +2718, 2771, 2435, +2718, 2771, 2435, +2717, 2770, 2434, +2717, 2770, 2432, +2717, 2770, 2430, +2717, 2769, 2430, +2718, 2769, 2431, +2718, 2770, 2433, +2719, 2771, 2443, +2720, 2774, 2457, +2721, 2773, 2466, +2716, 2771, 2466, +2717, 2774, 2492, +2718, 2776, 2528, +2718, 2777, 2569, +2722, 2782, 2624, +2727, 2788, 2703, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2718, 2771, 2437, +2718, 2771, 2437, +2718, 2771, 2437, +2718, 2771, 2436, +2718, 2771, 2436, +2718, 2771, 2435, +2718, 2771, 2435, +2717, 2770, 2434, +2717, 2770, 2432, +2717, 2770, 2430, +2717, 2769, 2430, +2718, 2769, 2431, +2718, 2770, 2433, +2719, 2771, 2443, +2720, 2774, 2457, +2721, 2773, 2466, +2716, 2771, 2466, +2717, 2774, 2492, +2718, 2776, 2528, +2718, 2777, 2569, +2722, 2782, 2624, +2727, 2788, 2703, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2718, 2771, 2437, +2718, 2771, 2437, +2718, 2771, 2437, +2718, 2771, 2436, +2718, 2771, 2436, +2718, 2771, 2435, +2718, 2771, 2435, +2717, 2770, 2434, +2717, 2770, 2432, +2717, 2770, 2430, +2717, 2769, 2430, +2718, 2769, 2431, +2718, 2770, 2433, +2719, 2771, 2443, +2720, 2774, 2457, +2721, 2773, 2466, +2716, 2771, 2466, +2717, 2774, 2492, +2718, 2776, 2528, +2718, 2777, 2569, +2722, 2782, 2624, +2727, 2788, 2703, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2718, 2771, 2437, +2718, 2771, 2437, +2718, 2771, 2437, +2718, 2771, 2436, +2718, 2771, 2436, +2718, 2771, 2435, +2718, 2771, 2435, +2717, 2770, 2434, +2717, 2770, 2432, +2717, 2770, 2430, +2717, 2769, 2430, +2718, 2769, 2431, +2718, 2770, 2433, +2719, 2771, 2443, +2720, 2774, 2457, +2721, 2773, 2466, +2716, 2771, 2466, +2717, 2774, 2492, +2718, 2776, 2528, +2718, 2777, 2569, +2722, 2782, 2624, +2727, 2788, 2703, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +2731, 2794, 2734, +1824, 0, 1212, +1824, 0, 1217, +1825, 0, 1223, +1825, 0, 1231, +1826, 0, 1242, +1827, 0, 1255, +1829, 0, 1273, +1831, 0, 1296, +1833, 0, 1325, +1830, 0, 1360, +1825, 0, 1405, +1819, 0, 1458, +1810, 0, 1521, +1804, 0, 1576, +1787, 0, 1659, +1777, 0, 1755, +1770, 0, 1865, +1790, 0, 1986, +1740, 750, 2108, +1692, 916, 2230, +1561, 947, 2370, +1845, 0, 2469, +1920, 0, 2511, +1920, 0, 2511, +1920, 0, 2511, +1920, 0, 2511, +1920, 0, 2511, +1920, 0, 2511, +1920, 0, 2511, +1920, 0, 2511, +1920, 0, 2511, +1920, 0, 2511, +1824, 0, 1216, +1824, 0, 1219, +1825, 0, 1225, +1825, 0, 1233, +1826, 0, 1243, +1827, 0, 1257, +1829, 0, 1275, +1831, 0, 1298, +1833, 0, 1326, +1830, 0, 1362, +1825, 0, 1406, +1819, 0, 1459, +1810, 0, 1523, +1804, 0, 1578, +1787, 0, 1661, +1777, 0, 1756, +1770, 0, 1866, +1790, 32, 1986, +1740, 754, 2108, +1692, 922, 2231, +1561, 949, 2370, +1845, 0, 2470, +1920, 0, 2510, +1920, 0, 2510, +1920, 0, 2510, +1920, 0, 2510, +1920, 0, 2510, +1920, 0, 2510, +1920, 0, 2510, +1920, 0, 2510, +1920, 0, 2510, +1920, 0, 2510, +1825, 0, 1221, +1825, 0, 1224, +1825, 0, 1228, +1825, 0, 1235, +1826, 0, 1246, +1827, 0, 1260, +1829, 0, 1277, +1831, 0, 1300, +1833, 0, 1328, +1830, 0, 1364, +1825, 0, 1408, +1819, 0, 1461, +1810, 0, 1524, +1804, 0, 1580, +1787, 0, 1663, +1777, 0, 1758, +1770, 44, 1866, +1789, 88, 1987, +1740, 759, 2109, +1692, 931, 2231, +1562, 952, 2370, +1845, 0, 2470, +1920, 0, 2510, +1920, 0, 2510, +1920, 0, 2510, +1920, 0, 2510, +1920, 0, 2510, +1920, 0, 2510, +1920, 0, 2510, +1920, 0, 2510, +1920, 0, 2510, +1920, 0, 2510, +1825, 0, 1228, +1825, 0, 1231, +1825, 0, 1234, +1825, 0, 1239, +1826, 0, 1249, +1827, 0, 1263, +1829, 0, 1280, +1831, 0, 1302, +1833, 0, 1331, +1830, 0, 1366, +1825, 0, 1410, +1819, 0, 1463, +1810, 0, 1526, +1804, 0, 1584, +1787, 0, 1666, +1777, 0, 1760, +1769, 102, 1867, +1788, 153, 1988, +1739, 765, 2110, +1692, 942, 2232, +1563, 957, 2370, +1845, 0, 2470, +1920, 44, 2510, +1920, 44, 2510, +1920, 44, 2510, +1920, 44, 2510, +1920, 44, 2510, +1920, 44, 2510, +1920, 44, 2510, +1920, 44, 2510, +1920, 44, 2510, +1920, 44, 2510, +1826, 0, 1238, +1826, 0, 1240, +1826, 0, 1243, +1826, 0, 1248, +1826, 0, 1254, +1827, 0, 1267, +1829, 0, 1284, +1831, 0, 1306, +1833, 0, 1335, +1830, 0, 1370, +1825, 0, 1413, +1819, 0, 1465, +1810, 0, 1528, +1804, 0, 1588, +1787, 0, 1669, +1777, 83, 1763, +1769, 170, 1868, +1787, 229, 1990, +1739, 774, 2111, +1692, 956, 2233, +1563, 962, 2370, +1845, 0, 2470, +1921, 103, 2510, +1921, 103, 2510, +1921, 103, 2510, +1921, 103, 2510, +1921, 103, 2510, +1921, 103, 2510, +1921, 103, 2510, +1921, 103, 2510, +1921, 103, 2510, +1921, 103, 2510, +1827, 0, 1250, +1827, 0, 1252, +1827, 0, 1255, +1827, 0, 1260, +1827, 1, 1265, +1827, 30, 1273, +1829, 30, 1290, +1831, 30, 1312, +1833, 30, 1339, +1830, 30, 1375, +1825, 30, 1417, +1819, 30, 1469, +1810, 64, 1531, +1804, 132, 1593, +1787, 132, 1674, +1777, 215, 1767, +1768, 247, 1870, +1785, 313, 1991, +1738, 785, 2113, +1692, 974, 2235, +1564, 970, 2370, +1845, 0, 2470, +1921, 171, 2510, +1921, 171, 2510, +1921, 171, 2510, +1921, 171, 2510, +1921, 171, 2510, +1921, 171, 2510, +1921, 171, 2510, +1921, 171, 2510, +1921, 171, 2510, +1921, 171, 2510, +1829, 58, 1265, +1829, 66, 1267, +1829, 77, 1270, +1829, 91, 1275, +1829, 109, 1280, +1829, 133, 1288, +1829, 163, 1297, +1831, 163, 1318, +1833, 163, 1346, +1830, 163, 1380, +1825, 163, 1423, +1819, 163, 1474, +1810, 188, 1536, +1804, 264, 1601, +1787, 264, 1680, +1777, 347, 1772, +1767, 334, 1872, +1783, 406, 1994, +1737, 799, 2115, +1692, 998, 2237, +1565, 979, 2370, +1845, 32, 2471, +1922, 248, 2510, +1922, 248, 2510, +1922, 248, 2510, +1922, 248, 2510, +1922, 248, 2510, +1922, 248, 2510, +1922, 248, 2510, +1922, 248, 2510, +1922, 248, 2510, +1922, 248, 2510, +1831, 183, 1285, +1831, 190, 1287, +1831, 198, 1290, +1831, 209, 1294, +1831, 223, 1299, +1831, 242, 1306, +1831, 265, 1315, +1831, 295, 1328, +1833, 295, 1354, +1830, 295, 1388, +1825, 295, 1430, +1819, 295, 1480, +1810, 314, 1541, +1804, 396, 1611, +1787, 396, 1688, +1777, 479, 1778, +1766, 428, 1875, +1779, 506, 1998, +1736, 818, 2119, +1692, 1027, 2240, +1567, 992, 2369, +1845, 164, 2471, +1922, 335, 2510, +1922, 335, 2510, +1922, 335, 2510, +1922, 335, 2510, +1922, 335, 2510, +1922, 335, 2510, +1922, 335, 2510, +1922, 335, 2510, +1922, 335, 2510, +1922, 335, 2510, +1833, 310, 1310, +1833, 315, 1312, +1833, 322, 1315, +1833, 330, 1319, +1833, 341, 1324, +1833, 355, 1331, +1833, 373, 1339, +1833, 397, 1351, +1833, 426, 1365, +1830, 426, 1398, +1825, 426, 1439, +1819, 426, 1489, +1810, 441, 1548, +1804, 528, 1623, +1787, 528, 1699, +1777, 611, 1787, +1765, 530, 1878, +1775, 613, 2002, +1734, 841, 2123, +1692, 1064, 2244, +1569, 1008, 2369, +1844, 330, 2472, +1924, 429, 2510, +1924, 429, 2510, +1924, 429, 2510, +1924, 429, 2510, +1924, 429, 2510, +1924, 429, 2510, +1924, 429, 2510, +1924, 429, 2510, +1924, 429, 2510, +1924, 429, 2510, +1830, 439, 1356, +1830, 443, 1358, +1830, 447, 1361, +1830, 454, 1364, +1830, 462, 1369, +1830, 473, 1375, +1830, 487, 1383, +1830, 506, 1393, +1830, 529, 1407, +1828, 531, 1428, +1824, 531, 1466, +1817, 531, 1513, +1809, 543, 1570, +1803, 601, 1641, +1787, 591, 1713, +1780, 686, 1796, +1768, 615, 1886, +1769, 725, 2008, +1730, 897, 2126, +1685, 1092, 2246, +1595, 1019, 2371, +1840, 422, 2472, +1926, 531, 2509, +1926, 531, 2509, +1926, 531, 2509, +1926, 531, 2509, +1926, 531, 2509, +1926, 531, 2509, +1926, 531, 2509, +1926, 531, 2509, +1926, 531, 2509, +1926, 531, 2509, +1825, 568, 1412, +1825, 571, 1414, +1825, 575, 1417, +1825, 579, 1420, +1825, 586, 1424, +1825, 594, 1429, +1825, 605, 1436, +1825, 619, 1445, +1825, 638, 1457, +1824, 640, 1476, +1821, 640, 1501, +1814, 640, 1545, +1806, 648, 1598, +1800, 695, 1664, +1787, 658, 1731, +1782, 751, 1810, +1774, 707, 1896, +1763, 805, 2012, +1724, 965, 2131, +1675, 1127, 2249, +1629, 1033, 2373, +1836, 515, 2472, +1930, 640, 2509, +1930, 640, 2509, +1930, 640, 2509, +1930, 640, 2509, +1930, 640, 2509, +1930, 640, 2509, +1930, 640, 2509, +1930, 640, 2509, +1930, 640, 2509, +1930, 640, 2509, +1819, 699, 1479, +1819, 701, 1480, +1819, 703, 1482, +1819, 707, 1485, +1819, 712, 1488, +1819, 718, 1493, +1819, 727, 1499, +1819, 737, 1507, +1819, 752, 1518, +1817, 753, 1534, +1814, 753, 1556, +1811, 753, 1584, +1803, 760, 1633, +1797, 797, 1695, +1787, 733, 1754, +1782, 813, 1830, +1781, 806, 1910, +1756, 887, 2016, +1716, 1042, 2138, +1662, 1169, 2253, +1634, 1062, 2374, +1829, 616, 2472, +1935, 753, 2509, +1935, 753, 2509, +1935, 753, 2509, +1935, 753, 2509, +1935, 753, 2509, +1935, 753, 2509, +1935, 753, 2509, +1935, 753, 2509, +1935, 753, 2509, +1935, 753, 2509, +1811, 848, 1553, +1811, 848, 1554, +1811, 851, 1556, +1811, 853, 1558, +1811, 857, 1561, +1811, 861, 1565, +1811, 867, 1570, +1811, 875, 1577, +1811, 886, 1586, +1809, 887, 1600, +1807, 887, 1619, +1804, 887, 1644, +1799, 892, 1675, +1793, 920, 1732, +1785, 861, 1784, +1781, 901, 1853, +1789, 932, 1929, +1748, 990, 2023, +1706, 1137, 2147, +1648, 1218, 2257, +1620, 1108, 2375, +1824, 746, 2471, +1942, 876, 2509, +1942, 876, 2509, +1942, 876, 2509, +1942, 876, 2509, +1942, 876, 2509, +1942, 876, 2509, +1942, 876, 2509, +1942, 876, 2509, +1942, 876, 2509, +1942, 876, 2509, +1820, 1109, 1630, +1820, 1109, 1631, +1819, 1109, 1633, +1819, 1109, 1635, +1818, 1109, 1637, +1817, 1109, 1641, +1815, 1109, 1645, +1813, 1109, 1651, +1810, 1109, 1659, +1810, 1109, 1670, +1808, 1109, 1686, +1805, 1109, 1707, +1800, 1112, 1734, +1793, 1134, 1775, +1785, 1098, 1823, +1767, 1090, 1881, +1785, 1153, 1970, +1749, 1166, 2045, +1704, 1267, 2165, +1646, 1289, 2266, +1638, 1188, 2377, +1843, 976, 2471, +1948, 1035, 2509, +1948, 1035, 2509, +1948, 1035, 2509, +1948, 1035, 2509, +1948, 1035, 2509, +1948, 1035, 2509, +1948, 1035, 2509, +1948, 1035, 2509, +1948, 1035, 2509, +1948, 1035, 2509, +1812, 1336, 1724, +1812, 1336, 1725, +1811, 1336, 1727, +1811, 1336, 1728, +1810, 1336, 1730, +1809, 1336, 1733, +1807, 1336, 1736, +1805, 1336, 1741, +1802, 1336, 1748, +1804, 1336, 1756, +1806, 1336, 1767, +1810, 1336, 1781, +1808, 1338, 1803, +1801, 1351, 1839, +1785, 1351, 1887, +1762, 1338, 1936, +1760, 1342, 2007, +1728, 1366, 2073, +1683, 1382, 2175, +1573, 1418, 2288, +1713, 1264, 2379, +1872, 1202, 2471, +1942, 1211, 2508, +1942, 1211, 2508, +1942, 1211, 2508, +1942, 1211, 2508, +1942, 1211, 2508, +1942, 1211, 2508, +1942, 1211, 2508, +1942, 1211, 2508, +1942, 1211, 2508, +1942, 1211, 2508, +1832, 1511, 1838, +1832, 1511, 1839, +1832, 1511, 1839, +1832, 1511, 1840, +1832, 1511, 1841, +1832, 1511, 1843, +1832, 1511, 1845, +1832, 1511, 1848, +1832, 1511, 1852, +1829, 1511, 1857, +1829, 1511, 1865, +1832, 1511, 1876, +1834, 1511, 1891, +1824, 1511, 1912, +1810, 1511, 1951, +1783, 1522, 2002, +1774, 1495, 2052, +1746, 1515, 2117, +1708, 1501, 2192, +1652, 1522, 2297, +1779, 1436, 2383, +1898, 1422, 2472, +1969, 1408, 2508, +1969, 1408, 2508, +1969, 1408, 2508, +1969, 1408, 2508, +1969, 1408, 2508, +1969, 1408, 2508, +1969, 1408, 2508, +1969, 1408, 2508, +1969, 1408, 2508, +1969, 1408, 2508, +1888, 1654, 1938, +1888, 1654, 1938, +1888, 1654, 1939, +1888, 1654, 1940, +1888, 1654, 1940, +1888, 1654, 1942, +1888, 1654, 1943, +1888, 1654, 1946, +1888, 1654, 1949, +1885, 1654, 1953, +1881, 1654, 1958, +1875, 1654, 1965, +1868, 1655, 1975, +1863, 1662, 1991, +1855, 1662, 2017, +1843, 1654, 2055, +1817, 1654, 2107, +1794, 1657, 2159, +1766, 1662, 2229, +1800, 1621, 2303, +1843, 1605, 2385, +1921, 1624, 2474, +2007, 1630, 2511, +2007, 1630, 2511, +2007, 1630, 2511, +2007, 1630, 2511, +2007, 1630, 2511, +2007, 1630, 2511, +2007, 1630, 2511, +2007, 1630, 2511, +2007, 1630, 2511, +2007, 1630, 2511, +1977, 1783, 1983, +1977, 1783, 1984, +1977, 1783, 1984, +1977, 1783, 1985, +1977, 1783, 1986, +1978, 1783, 1987, +1978, 1783, 1989, +1979, 1783, 1991, +1980, 1783, 1994, +1980, 1783, 1997, +1977, 1785, 2004, +1973, 1788, 2012, +1966, 1792, 2023, +1959, 1786, 2037, +1958, 1786, 2064, +1950, 1793, 2093, +1929, 1801, 2129, +1939, 1792, 2174, +1905, 1778, 2235, +1877, 1792, 2311, +1920, 1800, 2389, +2007, 1802, 2476, +2064, 1798, 2511, +2064, 1798, 2511, +2064, 1798, 2511, +2064, 1798, 2511, +2064, 1798, 2511, +2064, 1798, 2511, +2064, 1798, 2511, +2064, 1798, 2511, +2064, 1798, 2511, +2064, 1798, 2511, +2083, 1958, 2032, +2082, 1958, 2032, +2082, 1958, 2032, +2082, 1958, 2033, +2082, 1958, 2034, +2082, 1958, 2035, +2081, 1958, 2036, +2081, 1958, 2038, +2080, 1958, 2041, +2077, 1959, 2045, +2073, 1961, 2051, +2067, 1963, 2058, +2061, 1965, 2068, +2056, 1964, 2080, +2056, 1959, 2093, +2052, 1959, 2114, +2036, 1961, 2142, +2031, 1968, 2199, +2019, 1953, 2244, +2017, 1958, 2317, +2046, 1962, 2395, +2106, 1970, 2483, +2149, 1969, 2517, +2149, 1969, 2517, +2149, 1969, 2517, +2149, 1969, 2517, +2149, 1969, 2517, +2149, 1969, 2517, +2149, 1969, 2517, +2149, 1969, 2517, +2149, 1969, 2517, +2149, 1969, 2517, +2191, 2132, 2068, +2191, 2132, 2068, +2191, 2132, 2069, +2190, 2132, 2069, +2190, 2132, 2070, +2190, 2131, 2071, +2189, 2131, 2072, +2188, 2130, 2074, +2187, 2130, 2076, +2187, 2129, 2079, +2187, 2129, 2083, +2187, 2129, 2088, +2187, 2129, 2096, +2184, 2129, 2105, +2180, 2129, 2117, +2180, 2128, 2131, +2170, 2124, 2154, +2176, 2127, 2200, +2167, 2133, 2262, +2179, 2135, 2315, +2208, 2135, 2395, +2271, 2155, 2484, +2291, 2159, 2521, +2291, 2159, 2521, +2291, 2159, 2521, +2291, 2159, 2521, +2291, 2159, 2521, +2291, 2159, 2521, +2291, 2159, 2521, +2291, 2159, 2521, +2291, 2159, 2521, +2291, 2159, 2521, +2407, 2360, 2121, +2407, 2360, 2121, +2407, 2360, 2121, +2407, 2360, 2121, +2407, 2360, 2121, +2407, 2359, 2122, +2407, 2359, 2122, +2407, 2359, 2123, +2407, 2358, 2123, +2408, 2359, 2125, +2408, 2360, 2128, +2409, 2360, 2131, +2409, 2360, 2135, +2408, 2362, 2141, +2405, 2359, 2147, +2402, 2358, 2164, +2395, 2358, 2193, +2399, 2361, 2228, +2408, 2365, 2275, +2419, 2368, 2338, +2446, 2373, 2402, +2486, 2387, 2498, +2516, 2398, 2529, +2516, 2398, 2529, +2516, 2398, 2529, +2516, 2398, 2529, +2516, 2398, 2529, +2516, 2398, 2529, +2516, 2398, 2529, +2516, 2398, 2529, +2516, 2398, 2529, +2516, 2398, 2529, +2687, 2656, 1984, +2687, 2656, 1984, +2687, 2656, 1984, +2687, 2656, 1984, +2687, 2656, 1984, +2687, 2656, 1984, +2687, 2656, 1984, +2687, 2656, 1984, +2688, 2656, 1989, +2688, 2656, 1991, +2688, 2656, 1992, +2689, 2656, 1995, +2690, 2656, 1999, +2690, 2657, 2008, +2688, 2657, 2023, +2688, 2657, 2054, +2688, 2658, 2083, +2688, 2659, 2149, +2689, 2659, 2227, +2696, 2667, 2323, +2703, 2668, 2417, +2722, 2681, 2534, +2728, 2686, 2580, +2728, 2686, 2580, +2728, 2686, 2580, +2728, 2686, 2580, +2728, 2686, 2580, +2728, 2686, 2580, +2728, 2686, 2580, +2728, 2686, 2580, +2728, 2686, 2580, +2728, 2686, 2580, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2772, 2447, +2721, 2772, 2444, +2721, 2771, 2441, +2720, 2770, 2438, +2721, 2771, 2443, +2722, 2773, 2457, +2723, 2774, 2473, +2723, 2774, 2481, +2717, 2775, 2500, +2720, 2779, 2531, +2720, 2778, 2569, +2726, 2782, 2625, +2731, 2788, 2703, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2772, 2447, +2721, 2772, 2444, +2721, 2771, 2441, +2720, 2770, 2438, +2721, 2771, 2443, +2722, 2773, 2457, +2723, 2774, 2473, +2723, 2774, 2481, +2717, 2775, 2500, +2720, 2779, 2531, +2720, 2778, 2569, +2726, 2782, 2625, +2731, 2788, 2703, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2772, 2447, +2721, 2772, 2444, +2721, 2771, 2441, +2720, 2770, 2438, +2721, 2771, 2443, +2722, 2773, 2457, +2723, 2774, 2473, +2723, 2774, 2481, +2717, 2775, 2500, +2720, 2779, 2531, +2720, 2778, 2569, +2726, 2782, 2625, +2731, 2788, 2703, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2772, 2447, +2721, 2772, 2444, +2721, 2771, 2441, +2720, 2770, 2438, +2721, 2771, 2443, +2722, 2773, 2457, +2723, 2774, 2473, +2723, 2774, 2481, +2717, 2775, 2500, +2720, 2779, 2531, +2720, 2778, 2569, +2726, 2782, 2625, +2731, 2788, 2703, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2772, 2447, +2721, 2772, 2444, +2721, 2771, 2441, +2720, 2770, 2438, +2721, 2771, 2443, +2722, 2773, 2457, +2723, 2774, 2473, +2723, 2774, 2481, +2717, 2775, 2500, +2720, 2779, 2531, +2720, 2778, 2569, +2726, 2782, 2625, +2731, 2788, 2703, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2772, 2447, +2721, 2772, 2444, +2721, 2771, 2441, +2720, 2770, 2438, +2721, 2771, 2443, +2722, 2773, 2457, +2723, 2774, 2473, +2723, 2774, 2481, +2717, 2775, 2500, +2720, 2779, 2531, +2720, 2778, 2569, +2726, 2782, 2625, +2731, 2788, 2703, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2772, 2447, +2721, 2772, 2444, +2721, 2771, 2441, +2720, 2770, 2438, +2721, 2771, 2443, +2722, 2773, 2457, +2723, 2774, 2473, +2723, 2774, 2481, +2717, 2775, 2500, +2720, 2779, 2531, +2720, 2778, 2569, +2726, 2782, 2625, +2731, 2788, 2703, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2772, 2447, +2721, 2772, 2444, +2721, 2771, 2441, +2720, 2770, 2438, +2721, 2771, 2443, +2722, 2773, 2457, +2723, 2774, 2473, +2723, 2774, 2481, +2717, 2775, 2500, +2720, 2779, 2531, +2720, 2778, 2569, +2726, 2782, 2625, +2731, 2788, 2703, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2772, 2447, +2721, 2772, 2444, +2721, 2771, 2441, +2720, 2770, 2438, +2721, 2771, 2443, +2722, 2773, 2457, +2723, 2774, 2473, +2723, 2774, 2481, +2717, 2775, 2500, +2720, 2779, 2531, +2720, 2778, 2569, +2726, 2782, 2625, +2731, 2788, 2703, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2773, 2448, +2722, 2772, 2447, +2721, 2772, 2444, +2721, 2771, 2441, +2720, 2770, 2438, +2721, 2771, 2443, +2722, 2773, 2457, +2723, 2774, 2473, +2723, 2774, 2481, +2717, 2775, 2500, +2720, 2779, 2531, +2720, 2778, 2569, +2726, 2782, 2625, +2731, 2788, 2703, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +2734, 2794, 2737, +1906, 311, 1618, +1906, 316, 1619, +1906, 322, 1620, +1906, 330, 1621, +1905, 342, 1623, +1905, 356, 1626, +1905, 374, 1630, +1904, 398, 1634, +1903, 427, 1640, +1901, 464, 1648, +1904, 471, 1670, +1909, 471, 1700, +1914, 464, 1736, +1910, 152, 1775, +1903, 63, 1817, +1900, 481, 1880, +1885, 481, 1958, +1866, 624, 2053, +1837, 927, 2156, +1786, 933, 2261, +1818, 679, 2380, +1933, 0, 2471, +1989, 487, 2513, +1989, 487, 2513, +1989, 487, 2513, +1989, 487, 2513, +1989, 487, 2513, +1989, 487, 2513, +1989, 487, 2513, +1989, 487, 2513, +1989, 487, 2513, +1989, 487, 2513, +1906, 330, 1619, +1907, 325, 1621, +1906, 332, 1622, +1906, 340, 1623, +1906, 351, 1625, +1905, 365, 1628, +1905, 383, 1631, +1904, 406, 1636, +1903, 435, 1642, +1901, 471, 1650, +1904, 478, 1672, +1910, 478, 1702, +1915, 478, 1736, +1910, 179, 1776, +1903, 95, 1817, +1900, 491, 1880, +1885, 491, 1958, +1866, 631, 2054, +1837, 928, 2156, +1786, 935, 2261, +1818, 681, 2380, +1933, 0, 2471, +1989, 491, 2513, +1989, 491, 2513, +1989, 491, 2513, +1989, 491, 2513, +1989, 491, 2513, +1989, 491, 2513, +1989, 491, 2513, +1989, 491, 2513, +1989, 491, 2513, +1989, 491, 2513, +1906, 354, 1621, +1907, 350, 1622, +1907, 344, 1624, +1907, 352, 1625, +1906, 362, 1627, +1906, 376, 1630, +1905, 393, 1633, +1904, 416, 1638, +1903, 444, 1644, +1902, 480, 1652, +1905, 486, 1674, +1910, 486, 1704, +1915, 486, 1738, +1910, 212, 1777, +1904, 135, 1818, +1900, 504, 1881, +1885, 504, 1959, +1866, 640, 2054, +1837, 930, 2156, +1787, 936, 2261, +1819, 684, 2380, +1933, 0, 2471, +1990, 495, 2513, +1990, 495, 2513, +1990, 495, 2513, +1990, 495, 2513, +1990, 495, 2513, +1990, 495, 2513, +1990, 495, 2513, +1990, 495, 2513, +1990, 495, 2513, +1990, 495, 2513, +1906, 384, 1623, +1907, 381, 1624, +1907, 375, 1626, +1907, 367, 1628, +1907, 377, 1630, +1906, 391, 1633, +1905, 408, 1636, +1905, 430, 1641, +1904, 457, 1647, +1902, 491, 1655, +1905, 498, 1676, +1911, 498, 1706, +1915, 498, 1740, +1910, 253, 1778, +1904, 183, 1819, +1900, 520, 1882, +1885, 520, 1960, +1866, 653, 2055, +1838, 932, 2156, +1787, 939, 2261, +1819, 688, 2381, +1933, 0, 2471, +1990, 501, 2513, +1990, 501, 2513, +1990, 501, 2513, +1990, 501, 2513, +1990, 501, 2513, +1990, 501, 2513, +1990, 501, 2513, +1990, 501, 2513, +1990, 501, 2513, +1990, 501, 2513, +1906, 422, 1625, +1907, 419, 1626, +1907, 413, 1628, +1907, 406, 1631, +1908, 397, 1634, +1907, 409, 1636, +1906, 426, 1640, +1905, 447, 1644, +1904, 473, 1650, +1903, 507, 1658, +1906, 513, 1680, +1911, 513, 1709, +1916, 513, 1743, +1911, 303, 1780, +1904, 241, 1821, +1899, 542, 1884, +1886, 542, 1962, +1866, 669, 2056, +1838, 935, 2156, +1788, 941, 2261, +1820, 693, 2381, +1933, 0, 2471, +1991, 508, 2513, +1991, 508, 2513, +1991, 508, 2513, +1991, 508, 2513, +1991, 508, 2513, +1991, 508, 2513, +1991, 508, 2513, +1991, 508, 2513, +1991, 508, 2513, +1991, 508, 2513, +1906, 468, 1629, +1907, 465, 1630, +1907, 460, 1632, +1907, 454, 1634, +1908, 445, 1637, +1908, 434, 1641, +1907, 449, 1645, +1906, 469, 1649, +1905, 495, 1655, +1904, 526, 1663, +1907, 533, 1684, +1912, 533, 1713, +1917, 533, 1747, +1911, 362, 1783, +1905, 308, 1823, +1899, 569, 1886, +1886, 569, 1964, +1866, 690, 2057, +1839, 939, 2157, +1789, 945, 2262, +1821, 700, 2381, +1933, 10, 2471, +1993, 518, 2513, +1993, 518, 2513, +1993, 518, 2513, +1993, 518, 2513, +1993, 518, 2513, +1993, 518, 2513, +1993, 518, 2513, +1993, 518, 2513, +1993, 518, 2513, +1993, 518, 2513, +1906, 523, 1633, +1907, 520, 1635, +1907, 516, 1636, +1907, 511, 1639, +1908, 503, 1642, +1908, 493, 1646, +1908, 479, 1651, +1908, 498, 1656, +1907, 521, 1662, +1905, 551, 1669, +1908, 557, 1690, +1913, 557, 1719, +1918, 557, 1753, +1912, 430, 1786, +1905, 384, 1826, +1898, 602, 1888, +1887, 602, 1966, +1866, 716, 2059, +1839, 944, 2157, +1791, 950, 2262, +1823, 708, 2381, +1933, 84, 2470, +1994, 531, 2513, +1994, 531, 2513, +1994, 531, 2513, +1994, 531, 2513, +1994, 531, 2513, +1994, 531, 2513, +1994, 531, 2513, +1994, 531, 2513, +1994, 531, 2513, +1994, 531, 2513, +1906, 588, 1640, +1907, 585, 1641, +1907, 582, 1643, +1907, 577, 1645, +1908, 570, 1648, +1908, 562, 1652, +1908, 550, 1657, +1909, 533, 1664, +1908, 555, 1670, +1907, 583, 1678, +1910, 588, 1698, +1915, 588, 1727, +1920, 588, 1759, +1913, 508, 1790, +1906, 470, 1830, +1897, 644, 1892, +1888, 644, 1970, +1866, 749, 2061, +1840, 951, 2157, +1793, 957, 2263, +1825, 720, 2382, +1933, 167, 2470, +1996, 548, 2512, +1996, 548, 2512, +1996, 548, 2512, +1996, 548, 2512, +1996, 548, 2512, +1996, 548, 2512, +1996, 548, 2512, +1996, 548, 2512, +1996, 548, 2512, +1996, 548, 2512, +1906, 662, 1647, +1907, 660, 1649, +1907, 657, 1650, +1907, 653, 1653, +1908, 647, 1655, +1908, 640, 1659, +1908, 629, 1665, +1909, 615, 1672, +1911, 596, 1681, +1909, 622, 1689, +1912, 627, 1708, +1917, 627, 1736, +1922, 627, 1769, +1913, 595, 1796, +1907, 563, 1835, +1896, 695, 1896, +1889, 695, 1975, +1866, 789, 2064, +1841, 960, 2158, +1796, 966, 2263, +1827, 735, 2383, +1933, 330, 2471, +1999, 569, 2512, +1999, 569, 2512, +1999, 569, 2512, +1999, 569, 2512, +1999, 569, 2512, +1999, 569, 2512, +1999, 569, 2512, +1999, 569, 2512, +1999, 569, 2512, +1999, 569, 2512, +1906, 745, 1658, +1907, 743, 1659, +1907, 741, 1661, +1907, 737, 1663, +1908, 733, 1666, +1908, 727, 1670, +1908, 718, 1675, +1909, 707, 1682, +1911, 691, 1691, +1912, 669, 1703, +1915, 674, 1722, +1920, 674, 1749, +1925, 674, 1780, +1915, 674, 1805, +1909, 665, 1842, +1894, 754, 1903, +1887, 754, 1980, +1866, 838, 2069, +1843, 972, 2159, +1800, 977, 2264, +1831, 754, 2384, +1933, 489, 2472, +2002, 596, 2512, +2002, 596, 2512, +2002, 596, 2512, +2002, 596, 2512, +2002, 596, 2512, +2002, 596, 2512, +2002, 596, 2512, +2002, 596, 2512, +2002, 596, 2512, +2002, 596, 2512, +1910, 819, 1677, +1910, 817, 1678, +1910, 815, 1680, +1911, 812, 1682, +1911, 809, 1685, +1911, 803, 1689, +1912, 796, 1693, +1913, 787, 1700, +1914, 773, 1708, +1915, 755, 1720, +1915, 772, 1732, +1921, 772, 1758, +1925, 772, 1789, +1916, 772, 1813, +1909, 792, 1855, +1894, 863, 1914, +1887, 875, 1990, +1865, 911, 2073, +1841, 1000, 2165, +1800, 1040, 2269, +1833, 798, 2384, +1931, 640, 2472, +2004, 683, 2511, +2004, 683, 2511, +2004, 683, 2511, +2004, 683, 2511, +2004, 683, 2511, +2004, 683, 2511, +2004, 683, 2511, +2004, 683, 2511, +2004, 683, 2511, +2004, 683, 2511, +1915, 898, 1703, +1915, 897, 1704, +1915, 895, 1705, +1915, 893, 1707, +1916, 890, 1710, +1916, 885, 1713, +1917, 879, 1718, +1918, 871, 1724, +1919, 860, 1732, +1920, 845, 1743, +1921, 860, 1755, +1921, 885, 1769, +1925, 885, 1799, +1916, 885, 1823, +1909, 925, 1873, +1894, 979, 1929, +1887, 1007, 2002, +1862, 997, 2078, +1838, 1037, 2174, +1800, 1121, 2277, +1843, 837, 2383, +1928, 785, 2473, +2007, 787, 2510, +2007, 787, 2510, +2007, 787, 2510, +2007, 787, 2510, +2007, 787, 2510, +2007, 787, 2510, +2007, 787, 2510, +2007, 787, 2510, +2007, 787, 2510, +2007, 787, 2510, +1922, 997, 1735, +1922, 998, 1736, +1922, 997, 1737, +1922, 995, 1739, +1923, 993, 1741, +1923, 989, 1745, +1924, 984, 1749, +1925, 978, 1755, +1926, 969, 1763, +1927, 958, 1772, +1927, 969, 1783, +1927, 989, 1797, +1926, 1011, 1816, +1917, 1011, 1839, +1910, 1049, 1891, +1895, 1094, 1949, +1888, 1137, 2019, +1859, 1095, 2086, +1833, 1102, 2184, +1802, 1203, 2287, +1856, 905, 2383, +1926, 942, 2474, +2010, 902, 2509, +2010, 902, 2509, +2010, 902, 2509, +2010, 902, 2509, +2010, 902, 2509, +2010, 902, 2509, +2010, 902, 2509, +2010, 902, 2509, +2010, 902, 2509, +2010, 902, 2509, +1931, 1121, 1774, +1931, 1122, 1775, +1931, 1123, 1776, +1932, 1124, 1778, +1932, 1126, 1780, +1932, 1129, 1783, +1933, 1132, 1787, +1934, 1137, 1793, +1935, 1143, 1800, +1936, 1145, 1809, +1936, 1152, 1819, +1936, 1166, 1832, +1935, 1181, 1849, +1921, 1181, 1881, +1914, 1207, 1928, +1905, 1197, 1974, +1898, 1248, 2038, +1870, 1219, 2099, +1827, 1224, 2189, +1814, 1266, 2289, +1856, 1137, 2381, +1933, 1139, 2475, +2017, 1048, 2509, +2017, 1048, 2509, +2017, 1048, 2509, +2017, 1048, 2509, +2017, 1048, 2509, +2017, 1048, 2509, +2017, 1048, 2509, +2017, 1048, 2509, +2017, 1048, 2509, +2017, 1048, 2509, +1943, 1312, 1836, +1943, 1312, 1837, +1943, 1313, 1838, +1943, 1314, 1839, +1944, 1315, 1841, +1944, 1317, 1844, +1945, 1319, 1847, +1945, 1322, 1852, +1946, 1326, 1858, +1948, 1331, 1866, +1945, 1332, 1875, +1940, 1332, 1886, +1936, 1339, 1902, +1923, 1339, 1930, +1915, 1358, 1965, +1906, 1343, 2006, +1889, 1364, 2062, +1872, 1381, 2136, +1826, 1367, 2210, +1822, 1339, 2296, +1868, 1258, 2382, +1955, 1262, 2478, +2027, 1191, 2509, +2027, 1191, 2509, +2027, 1191, 2509, +2027, 1191, 2509, +2027, 1191, 2509, +2027, 1191, 2509, +2027, 1191, 2509, +2027, 1191, 2509, +2027, 1191, 2509, +2027, 1191, 2509, +1969, 1458, 1884, +1969, 1458, 1884, +1968, 1458, 1885, +1968, 1458, 1887, +1968, 1458, 1888, +1968, 1458, 1890, +1967, 1458, 1892, +1966, 1458, 1896, +1965, 1458, 1900, +1964, 1458, 1906, +1962, 1458, 1913, +1957, 1458, 1924, +1950, 1459, 1938, +1941, 1472, 1960, +1934, 1487, 1991, +1937, 1461, 2031, +1908, 1472, 2078, +1899, 1508, 2159, +1871, 1507, 2226, +1869, 1459, 2304, +1906, 1424, 2382, +1989, 1433, 2480, +2031, 1414, 2509, +2031, 1414, 2509, +2031, 1414, 2509, +2031, 1414, 2509, +2031, 1414, 2509, +2031, 1414, 2509, +2031, 1414, 2509, +2031, 1414, 2509, +2031, 1414, 2509, +2031, 1414, 2509, +1995, 1625, 1959, +1995, 1625, 1960, +1995, 1625, 1961, +1995, 1626, 1962, +1995, 1626, 1963, +1994, 1627, 1965, +1994, 1628, 1968, +1993, 1630, 1972, +1992, 1632, 1976, +1991, 1632, 1982, +1990, 1632, 1987, +1990, 1632, 1993, +1990, 1632, 2002, +1989, 1633, 2018, +1978, 1635, 2038, +1968, 1630, 2070, +1945, 1650, 2122, +1941, 1635, 2175, +1926, 1623, 2233, +1921, 1624, 2309, +1947, 1613, 2388, +2014, 1610, 2474, +2061, 1608, 2512, +2061, 1608, 2512, +2061, 1608, 2512, +2061, 1608, 2512, +2061, 1608, 2512, +2061, 1608, 2512, +2061, 1608, 2512, +2061, 1608, 2512, +2061, 1608, 2512, +2061, 1608, 2512, +2048, 1766, 1996, +2048, 1766, 1996, +2048, 1766, 1996, +2048, 1766, 1997, +2048, 1766, 1998, +2048, 1766, 1999, +2048, 1766, 2000, +2048, 1766, 2002, +2048, 1766, 2006, +2048, 1766, 2009, +2048, 1766, 2014, +2048, 1766, 2020, +2048, 1767, 2029, +2044, 1773, 2043, +2040, 1782, 2061, +2029, 1792, 2098, +2027, 1783, 2138, +1997, 1783, 2185, +1996, 1799, 2243, +1996, 1791, 2315, +2012, 1789, 2391, +2075, 1804, 2478, +2111, 1808, 2513, +2111, 1808, 2513, +2111, 1808, 2513, +2111, 1808, 2513, +2111, 1808, 2513, +2111, 1808, 2513, +2111, 1808, 2513, +2111, 1808, 2513, +2111, 1808, 2513, +2111, 1808, 2513, +2118, 1947, 2038, +2118, 1947, 2038, +2118, 1947, 2039, +2118, 1947, 2039, +2118, 1948, 2040, +2119, 1948, 2041, +2119, 1948, 2042, +2120, 1949, 2044, +2120, 1950, 2047, +2121, 1951, 2050, +2120, 1952, 2054, +2119, 1952, 2060, +2117, 1952, 2068, +2111, 1952, 2078, +2102, 1952, 2094, +2100, 1957, 2116, +2094, 1953, 2146, +2078, 1951, 2186, +2073, 1951, 2247, +2076, 1958, 2318, +2097, 1963, 2398, +2161, 1972, 2478, +2191, 1974, 2517, +2191, 1974, 2517, +2191, 1974, 2517, +2191, 1974, 2517, +2191, 1974, 2517, +2191, 1974, 2517, +2191, 1974, 2517, +2191, 1974, 2517, +2191, 1974, 2517, +2191, 1974, 2517, +2223, 2127, 2077, +2223, 2127, 2077, +2223, 2127, 2077, +2223, 2128, 2078, +2223, 2128, 2078, +2223, 2128, 2078, +2223, 2128, 2079, +2223, 2129, 2080, +2223, 2130, 2082, +2223, 2131, 2084, +2221, 2130, 2088, +2219, 2128, 2093, +2216, 2127, 2099, +2213, 2127, 2109, +2210, 2127, 2121, +2206, 2127, 2136, +2216, 2126, 2162, +2212, 2127, 2204, +2215, 2139, 2260, +2222, 2139, 2318, +2237, 2143, 2401, +2282, 2159, 2486, +2316, 2166, 2524, +2316, 2166, 2524, +2316, 2166, 2524, +2316, 2166, 2524, +2316, 2166, 2524, +2316, 2166, 2524, +2316, 2166, 2524, +2316, 2166, 2524, +2316, 2166, 2524, +2316, 2166, 2524, +2426, 2364, 2124, +2426, 2364, 2124, +2426, 2364, 2124, +2426, 2364, 2125, +2426, 2364, 2125, +2426, 2364, 2126, +2426, 2364, 2126, +2426, 2364, 2127, +2426, 2364, 2129, +2426, 2364, 2131, +2426, 2364, 2132, +2426, 2363, 2135, +2427, 2362, 2138, +2429, 2364, 2138, +2428, 2365, 2146, +2427, 2363, 2161, +2428, 2366, 2187, +2427, 2369, 2230, +2430, 2369, 2278, +2430, 2368, 2333, +2463, 2376, 2405, +2502, 2392, 2495, +2540, 2403, 2525, +2540, 2403, 2525, +2540, 2403, 2525, +2540, 2403, 2525, +2540, 2403, 2525, +2540, 2403, 2525, +2540, 2403, 2525, +2540, 2403, 2525, +2540, 2403, 2525, +2540, 2403, 2525, +2694, 2658, 1982, +2694, 2658, 1982, +2694, 2658, 1982, +2694, 2658, 1981, +2694, 2658, 1981, +2694, 2658, 1979, +2693, 2657, 1979, +2693, 2657, 1977, +2693, 2657, 1978, +2693, 2657, 1979, +2693, 2658, 1988, +2694, 2659, 2001, +2694, 2660, 2015, +2696, 2660, 2021, +2695, 2657, 2016, +2695, 2660, 2055, +2697, 2662, 2117, +2697, 2663, 2170, +2697, 2666, 2245, +2701, 2667, 2320, +2711, 2672, 2426, +2725, 2685, 2539, +2731, 2689, 2588, +2731, 2689, 2588, +2731, 2689, 2588, +2731, 2689, 2588, +2731, 2689, 2588, +2731, 2689, 2588, +2731, 2689, 2588, +2731, 2689, 2588, +2731, 2689, 2588, +2731, 2689, 2588, +2727, 2773, 2456, +2727, 2773, 2456, +2727, 2773, 2456, +2727, 2774, 2457, +2727, 2774, 2457, +2727, 2774, 2457, +2727, 2774, 2458, +2728, 2774, 2459, +2728, 2775, 2460, +2728, 2775, 2461, +2728, 2775, 2461, +2728, 2775, 2461, +2728, 2775, 2461, +2729, 2773, 2461, +2729, 2774, 2466, +2728, 2776, 2478, +2729, 2777, 2494, +2725, 2779, 2509, +2723, 2779, 2533, +2725, 2779, 2571, +2728, 2783, 2631, +2735, 2789, 2705, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2727, 2773, 2456, +2727, 2773, 2456, +2727, 2773, 2456, +2727, 2774, 2457, +2727, 2774, 2457, +2727, 2774, 2457, +2727, 2774, 2458, +2728, 2774, 2459, +2728, 2775, 2460, +2728, 2775, 2461, +2728, 2775, 2461, +2728, 2775, 2461, +2728, 2775, 2461, +2729, 2773, 2461, +2729, 2774, 2466, +2728, 2776, 2478, +2729, 2777, 2494, +2725, 2779, 2509, +2723, 2779, 2533, +2725, 2779, 2571, +2728, 2783, 2631, +2735, 2789, 2705, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2727, 2773, 2456, +2727, 2773, 2456, +2727, 2773, 2456, +2727, 2774, 2457, +2727, 2774, 2457, +2727, 2774, 2457, +2727, 2774, 2458, +2728, 2774, 2459, +2728, 2775, 2460, +2728, 2775, 2461, +2728, 2775, 2461, +2728, 2775, 2461, +2728, 2775, 2461, +2729, 2773, 2461, +2729, 2774, 2466, +2728, 2776, 2478, +2729, 2777, 2494, +2725, 2779, 2509, +2723, 2779, 2533, +2725, 2779, 2571, +2728, 2783, 2631, +2735, 2789, 2705, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2727, 2773, 2456, +2727, 2773, 2456, +2727, 2773, 2456, +2727, 2774, 2457, +2727, 2774, 2457, +2727, 2774, 2457, +2727, 2774, 2458, +2728, 2774, 2459, +2728, 2775, 2460, +2728, 2775, 2461, +2728, 2775, 2461, +2728, 2775, 2461, +2728, 2775, 2461, +2729, 2773, 2461, +2729, 2774, 2466, +2728, 2776, 2478, +2729, 2777, 2494, +2725, 2779, 2509, +2723, 2779, 2533, +2725, 2779, 2571, +2728, 2783, 2631, +2735, 2789, 2705, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2727, 2773, 2456, +2727, 2773, 2456, +2727, 2773, 2456, +2727, 2774, 2457, +2727, 2774, 2457, +2727, 2774, 2457, +2727, 2774, 2458, +2728, 2774, 2459, +2728, 2775, 2460, +2728, 2775, 2461, +2728, 2775, 2461, +2728, 2775, 2461, +2728, 2775, 2461, +2729, 2773, 2461, +2729, 2774, 2466, +2728, 2776, 2478, +2729, 2777, 2494, +2725, 2779, 2509, +2723, 2779, 2533, +2725, 2779, 2571, +2728, 2783, 2631, +2735, 2789, 2705, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2727, 2773, 2456, +2727, 2773, 2456, +2727, 2773, 2456, +2727, 2774, 2457, +2727, 2774, 2457, +2727, 2774, 2457, +2727, 2774, 2458, +2728, 2774, 2459, +2728, 2775, 2460, +2728, 2775, 2461, +2728, 2775, 2461, +2728, 2775, 2461, +2728, 2775, 2461, +2729, 2773, 2461, +2729, 2774, 2466, +2728, 2776, 2478, +2729, 2777, 2494, +2725, 2779, 2509, +2723, 2779, 2533, +2725, 2779, 2571, +2728, 2783, 2631, +2735, 2789, 2705, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2727, 2773, 2456, +2727, 2773, 2456, +2727, 2773, 2456, +2727, 2774, 2457, +2727, 2774, 2457, +2727, 2774, 2457, +2727, 2774, 2458, +2728, 2774, 2459, +2728, 2775, 2460, +2728, 2775, 2461, +2728, 2775, 2461, +2728, 2775, 2461, +2728, 2775, 2461, +2729, 2773, 2461, +2729, 2774, 2466, +2728, 2776, 2478, +2729, 2777, 2494, +2725, 2779, 2509, +2723, 2779, 2533, +2725, 2779, 2571, +2728, 2783, 2631, +2735, 2789, 2705, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2727, 2773, 2456, +2727, 2773, 2456, +2727, 2773, 2456, +2727, 2774, 2457, +2727, 2774, 2457, +2727, 2774, 2457, +2727, 2774, 2458, +2728, 2774, 2459, +2728, 2775, 2460, +2728, 2775, 2461, +2728, 2775, 2461, +2728, 2775, 2461, +2728, 2775, 2461, +2729, 2773, 2461, +2729, 2774, 2466, +2728, 2776, 2478, +2729, 2777, 2494, +2725, 2779, 2509, +2723, 2779, 2533, +2725, 2779, 2571, +2728, 2783, 2631, +2735, 2789, 2705, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2727, 2773, 2456, +2727, 2773, 2456, +2727, 2773, 2456, +2727, 2774, 2457, +2727, 2774, 2457, +2727, 2774, 2457, +2727, 2774, 2458, +2728, 2774, 2459, +2728, 2775, 2460, +2728, 2775, 2461, +2728, 2775, 2461, +2728, 2775, 2461, +2728, 2775, 2461, +2729, 2773, 2461, +2729, 2774, 2466, +2728, 2776, 2478, +2729, 2777, 2494, +2725, 2779, 2509, +2723, 2779, 2533, +2725, 2779, 2571, +2728, 2783, 2631, +2735, 2789, 2705, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2727, 2773, 2456, +2727, 2773, 2456, +2727, 2773, 2456, +2727, 2774, 2457, +2727, 2774, 2457, +2727, 2774, 2457, +2727, 2774, 2458, +2728, 2774, 2459, +2728, 2775, 2460, +2728, 2775, 2461, +2728, 2775, 2461, +2728, 2775, 2461, +2728, 2775, 2461, +2729, 2773, 2461, +2729, 2774, 2466, +2728, 2776, 2478, +2729, 2777, 2494, +2725, 2779, 2509, +2723, 2779, 2533, +2725, 2779, 2571, +2728, 2783, 2631, +2735, 2789, 2705, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2738, 2796, 2741, +2036, 810, 1881, +2036, 808, 1882, +2036, 806, 1882, +2036, 803, 1883, +2037, 799, 1884, +2037, 794, 1886, +2037, 787, 1887, +2038, 777, 1890, +2039, 763, 1894, +2040, 745, 1898, +2042, 718, 1904, +2043, 681, 1912, +2044, 657, 1923, +2037, 657, 1946, +2028, 657, 1974, +2025, 726, 2020, +2019, 820, 2081, +1994, 874, 2146, +1993, 810, 2228, +2002, 0, 2298, +2010, 0, 2382, +2069, 0, 2474, +2108, 0, 2510, +2108, 0, 2510, +2108, 0, 2510, +2108, 0, 2510, +2108, 0, 2510, +2108, 0, 2510, +2108, 0, 2510, +2108, 0, 2510, +2108, 0, 2510, +2108, 0, 2510, +2036, 813, 1881, +2036, 813, 1882, +2036, 811, 1883, +2036, 808, 1884, +2037, 804, 1884, +2037, 799, 1886, +2037, 791, 1888, +2038, 782, 1891, +2039, 769, 1894, +2040, 750, 1898, +2042, 724, 1905, +2043, 687, 1912, +2044, 666, 1924, +2037, 666, 1946, +2028, 666, 1974, +2024, 730, 2021, +2019, 824, 2081, +1994, 876, 2146, +1994, 812, 2228, +2002, 0, 2298, +2010, 0, 2382, +2069, 0, 2474, +2108, 0, 2510, +2108, 0, 2510, +2108, 0, 2510, +2108, 0, 2510, +2108, 0, 2510, +2108, 0, 2510, +2108, 0, 2510, +2108, 0, 2510, +2108, 0, 2510, +2108, 0, 2510, +2037, 817, 1881, +2036, 817, 1882, +2036, 817, 1883, +2036, 814, 1884, +2037, 810, 1885, +2037, 805, 1887, +2037, 798, 1888, +2038, 789, 1891, +2039, 776, 1894, +2040, 757, 1899, +2042, 732, 1905, +2043, 695, 1913, +2044, 675, 1924, +2037, 678, 1946, +2028, 678, 1974, +2024, 735, 2021, +2019, 831, 2081, +1994, 877, 2146, +1994, 814, 2228, +2002, 0, 2298, +2010, 0, 2382, +2069, 0, 2474, +2108, 0, 2510, +2108, 0, 2510, +2108, 0, 2510, +2108, 0, 2510, +2108, 0, 2510, +2108, 0, 2510, +2108, 0, 2510, +2108, 0, 2510, +2108, 0, 2510, +2108, 0, 2510, +2037, 823, 1882, +2037, 823, 1883, +2037, 823, 1884, +2036, 823, 1885, +2037, 819, 1886, +2037, 814, 1887, +2037, 807, 1889, +2038, 797, 1892, +2039, 785, 1895, +2040, 767, 1900, +2042, 742, 1906, +2043, 706, 1914, +2044, 686, 1925, +2038, 693, 1947, +2028, 693, 1975, +2024, 742, 2022, +2020, 839, 2082, +1995, 880, 2146, +1995, 817, 2228, +2003, 0, 2298, +2010, 0, 2382, +2069, 0, 2474, +2107, 0, 2510, +2107, 0, 2510, +2107, 0, 2510, +2107, 0, 2510, +2107, 0, 2510, +2107, 0, 2510, +2107, 0, 2510, +2107, 0, 2510, +2107, 0, 2510, +2107, 0, 2510, +2037, 830, 1882, +2037, 830, 1883, +2037, 830, 1884, +2037, 830, 1885, +2037, 830, 1887, +2037, 825, 1888, +2037, 818, 1891, +2038, 809, 1893, +2039, 797, 1897, +2040, 779, 1901, +2042, 755, 1907, +2043, 721, 1915, +2044, 701, 1926, +2038, 713, 1948, +2029, 713, 1976, +2024, 751, 2023, +2020, 850, 2082, +1995, 883, 2147, +1996, 821, 2228, +2004, 0, 2298, +2011, 0, 2383, +2069, 0, 2474, +2107, 61, 2510, +2107, 61, 2510, +2107, 61, 2510, +2107, 61, 2510, +2107, 61, 2510, +2107, 61, 2510, +2107, 61, 2510, +2107, 61, 2510, +2107, 61, 2510, +2107, 61, 2510, +2038, 840, 1883, +2038, 840, 1884, +2038, 840, 1884, +2037, 840, 1886, +2037, 840, 1887, +2037, 840, 1890, +2037, 833, 1892, +2038, 825, 1894, +2039, 813, 1898, +2040, 796, 1902, +2042, 772, 1908, +2043, 739, 1916, +2044, 721, 1927, +2038, 737, 1950, +2029, 737, 1977, +2023, 762, 2025, +2021, 864, 2083, +1996, 888, 2147, +1997, 826, 2228, +2005, 48, 2298, +2011, 0, 2383, +2069, 10, 2474, +2105, 179, 2510, +2105, 179, 2510, +2105, 179, 2510, +2105, 179, 2510, +2105, 179, 2510, +2105, 179, 2510, +2105, 179, 2510, +2105, 179, 2510, +2105, 179, 2510, +2105, 179, 2510, +2039, 853, 1883, +2039, 853, 1884, +2039, 853, 1885, +2038, 853, 1887, +2038, 853, 1888, +2038, 853, 1891, +2037, 853, 1894, +2038, 844, 1896, +2039, 833, 1900, +2040, 817, 1904, +2042, 794, 1910, +2043, 763, 1918, +2044, 745, 1929, +2039, 769, 1951, +2029, 769, 1979, +2023, 777, 2027, +2022, 882, 2084, +1997, 894, 2148, +1998, 832, 2227, +2006, 147, 2298, +2011, 89, 2384, +2069, 84, 2473, +2104, 299, 2510, +2104, 299, 2510, +2104, 299, 2510, +2104, 299, 2510, +2104, 299, 2510, +2104, 299, 2510, +2104, 299, 2510, +2104, 299, 2510, +2104, 299, 2510, +2104, 299, 2510, +2040, 869, 1884, +2040, 869, 1885, +2040, 869, 1886, +2040, 869, 1887, +2039, 869, 1889, +2039, 869, 1891, +2039, 869, 1894, +2038, 869, 1899, +2039, 858, 1902, +2040, 843, 1907, +2042, 822, 1913, +2043, 792, 1920, +2044, 776, 1932, +2039, 807, 1954, +2030, 807, 1981, +2022, 797, 2029, +2023, 905, 2085, +1998, 901, 2149, +2000, 841, 2227, +2007, 253, 2298, +2012, 208, 2384, +2069, 167, 2473, +2103, 423, 2510, +2103, 423, 2510, +2103, 423, 2510, +2103, 423, 2510, +2103, 423, 2510, +2103, 423, 2510, +2103, 423, 2510, +2103, 423, 2510, +2103, 423, 2510, +2103, 423, 2510, +2042, 890, 1885, +2042, 890, 1886, +2042, 890, 1887, +2041, 890, 1888, +2041, 890, 1890, +2041, 890, 1893, +2040, 890, 1896, +2040, 890, 1900, +2039, 890, 1905, +2040, 876, 1910, +2042, 857, 1916, +2043, 829, 1924, +2044, 814, 1935, +2040, 854, 1957, +2031, 854, 1984, +2021, 822, 2032, +2025, 934, 2086, +2000, 911, 2150, +2003, 852, 2226, +2009, 364, 2298, +2013, 329, 2385, +2069, 258, 2473, +2101, 548, 2511, +2101, 548, 2511, +2101, 548, 2511, +2101, 548, 2511, +2101, 548, 2511, +2101, 548, 2511, +2101, 548, 2511, +2101, 548, 2511, +2101, 548, 2511, +2101, 548, 2511, +2044, 917, 1887, +2044, 917, 1887, +2044, 917, 1889, +2043, 917, 1890, +2043, 917, 1892, +2043, 917, 1894, +2042, 917, 1897, +2042, 917, 1901, +2041, 917, 1907, +2040, 917, 1914, +2042, 899, 1920, +2043, 874, 1928, +2044, 861, 1939, +2041, 906, 1961, +2032, 910, 1988, +2020, 853, 2037, +2024, 959, 2090, +2002, 924, 2152, +2007, 867, 2226, +2011, 480, 2298, +2014, 453, 2386, +2069, 358, 2472, +2098, 675, 2511, +2098, 675, 2511, +2098, 675, 2511, +2098, 675, 2511, +2098, 675, 2511, +2098, 675, 2511, +2098, 675, 2511, +2098, 675, 2511, +2098, 675, 2511, +2098, 675, 2511, +2047, 951, 1889, +2047, 951, 1890, +2047, 951, 1891, +2047, 951, 1892, +2046, 951, 1894, +2046, 951, 1896, +2045, 951, 1899, +2045, 951, 1903, +2044, 951, 1909, +2043, 951, 1916, +2042, 951, 1926, +2043, 928, 1933, +2044, 916, 1944, +2041, 956, 1966, +2033, 976, 1993, +2021, 913, 2042, +2022, 990, 2095, +2006, 968, 2154, +2012, 886, 2225, +2014, 599, 2298, +2016, 579, 2387, +2069, 463, 2472, +2094, 803, 2512, +2094, 803, 2512, +2094, 803, 2512, +2094, 803, 2512, +2094, 803, 2512, +2094, 803, 2512, +2094, 803, 2512, +2094, 803, 2512, +2094, 803, 2512, +2094, 803, 2512, +2051, 992, 1892, +2051, 992, 1892, +2051, 992, 1894, +2050, 992, 1895, +2050, 992, 1897, +2050, 992, 1899, +2049, 992, 1902, +2049, 992, 1906, +2048, 992, 1912, +2047, 992, 1919, +2045, 992, 1928, +2043, 992, 1941, +2044, 981, 1951, +2041, 1016, 1973, +2035, 1052, 1999, +2023, 999, 2048, +2020, 1028, 2102, +2010, 1027, 2157, +2018, 910, 2223, +2019, 722, 2298, +2019, 682, 2389, +2069, 575, 2471, +2089, 933, 2513, +2089, 933, 2513, +2089, 933, 2513, +2089, 933, 2513, +2089, 933, 2513, +2089, 933, 2513, +2089, 933, 2513, +2089, 933, 2513, +2089, 933, 2513, +2089, 933, 2513, +2055, 1051, 1898, +2055, 1052, 1899, +2055, 1052, 1900, +2055, 1052, 1902, +2054, 1052, 1903, +2054, 1052, 1905, +2054, 1052, 1909, +2053, 1052, 1913, +2052, 1052, 1918, +2051, 1052, 1925, +2050, 1052, 1935, +2048, 1052, 1947, +2047, 1053, 1963, +2043, 1083, 1983, +2038, 1120, 2010, +2027, 1089, 2055, +2019, 1074, 2110, +2016, 1091, 2162, +2024, 958, 2224, +2023, 859, 2299, +2024, 795, 2391, +2069, 729, 2471, +2085, 1046, 2513, +2085, 1046, 2513, +2085, 1046, 2513, +2085, 1046, 2513, +2085, 1046, 2513, +2085, 1046, 2513, +2085, 1046, 2513, +2085, 1046, 2513, +2085, 1046, 2513, +2085, 1046, 2513, +2065, 1109, 1913, +2065, 1110, 1913, +2065, 1112, 1915, +2065, 1113, 1916, +2064, 1115, 1918, +2063, 1118, 1921, +2063, 1121, 1924, +2061, 1126, 1929, +2060, 1132, 1936, +2058, 1137, 1943, +2057, 1137, 1952, +2055, 1137, 1964, +2053, 1137, 1979, +2053, 1164, 1999, +2049, 1195, 2025, +2041, 1167, 2059, +2028, 1112, 2110, +2027, 1145, 2168, +2024, 1061, 2228, +2023, 1050, 2301, +2024, 973, 2387, +2069, 983, 2473, +2092, 1159, 2513, +2092, 1159, 2513, +2092, 1159, 2513, +2092, 1159, 2513, +2092, 1159, 2513, +2092, 1159, 2513, +2092, 1159, 2513, +2092, 1159, 2513, +2092, 1159, 2513, +2092, 1159, 2513, +2079, 1177, 1931, +2078, 1178, 1932, +2078, 1179, 1933, +2078, 1180, 1934, +2077, 1182, 1936, +2077, 1184, 1939, +2076, 1187, 1942, +2075, 1191, 1947, +2073, 1196, 1953, +2071, 1204, 1961, +2068, 1213, 1971, +2065, 1225, 1985, +2062, 1230, 2000, +2062, 1252, 2020, +2062, 1280, 2044, +2056, 1256, 2073, +2047, 1209, 2114, +2037, 1182, 2169, +2024, 1169, 2235, +2023, 1221, 2303, +2029, 1152, 2384, +2060, 1207, 2475, +2100, 1275, 2513, +2100, 1275, 2513, +2100, 1275, 2513, +2100, 1275, 2513, +2100, 1275, 2513, +2100, 1275, 2513, +2100, 1275, 2513, +2100, 1275, 2513, +2100, 1275, 2513, +2100, 1275, 2513, +2099, 1357, 1955, +2099, 1357, 1955, +2099, 1357, 1955, +2099, 1357, 1956, +2098, 1357, 1957, +2098, 1357, 1958, +2097, 1357, 1960, +2096, 1357, 1962, +2094, 1357, 1965, +2093, 1357, 1969, +2090, 1361, 1977, +2086, 1370, 1990, +2083, 1381, 2008, +2080, 1396, 2034, +2079, 1416, 2059, +2078, 1420, 2093, +2067, 1399, 2124, +2059, 1381, 2174, +2045, 1359, 2234, +2030, 1417, 2304, +2051, 1393, 2388, +2070, 1417, 2476, +2115, 1452, 2513, +2115, 1452, 2513, +2115, 1452, 2513, +2115, 1452, 2513, +2115, 1452, 2513, +2115, 1452, 2513, +2115, 1452, 2513, +2115, 1452, 2513, +2115, 1452, 2513, +2115, 1452, 2513, +2118, 1561, 1978, +2118, 1561, 1978, +2118, 1561, 1979, +2118, 1561, 1980, +2119, 1561, 1982, +2119, 1561, 1984, +2119, 1561, 1986, +2120, 1561, 1990, +2120, 1561, 1994, +2119, 1561, 1998, +2116, 1561, 2003, +2113, 1561, 2009, +2109, 1560, 2018, +2103, 1553, 2032, +2099, 1566, 2064, +2098, 1570, 2096, +2095, 1587, 2145, +2080, 1579, 2177, +2077, 1562, 2236, +2046, 1604, 2305, +2071, 1614, 2389, +2114, 1600, 2477, +2143, 1637, 2513, +2143, 1637, 2513, +2143, 1637, 2513, +2143, 1637, 2513, +2143, 1637, 2513, +2143, 1637, 2513, +2143, 1637, 2513, +2143, 1637, 2513, +2143, 1637, 2513, +2143, 1637, 2513, +2134, 1765, 2000, +2134, 1765, 2001, +2134, 1766, 2001, +2134, 1766, 2002, +2134, 1767, 2003, +2134, 1767, 2004, +2134, 1768, 2005, +2134, 1769, 2007, +2134, 1771, 2010, +2134, 1772, 2014, +2135, 1773, 2021, +2137, 1773, 2031, +2138, 1773, 2045, +2138, 1767, 2062, +2131, 1758, 2076, +2129, 1756, 2098, +2124, 1756, 2137, +2121, 1783, 2193, +2113, 1774, 2243, +2086, 1783, 2307, +2096, 1787, 2390, +2148, 1816, 2480, +2194, 1817, 2514, +2194, 1817, 2514, +2194, 1817, 2514, +2194, 1817, 2514, +2194, 1817, 2514, +2194, 1817, 2514, +2194, 1817, 2514, +2194, 1817, 2514, +2194, 1817, 2514, +2194, 1817, 2514, +2181, 1956, 2056, +2181, 1956, 2057, +2181, 1956, 2057, +2182, 1956, 2057, +2182, 1955, 2057, +2182, 1955, 2057, +2182, 1955, 2058, +2183, 1954, 2058, +2183, 1953, 2059, +2184, 1951, 2060, +2185, 1950, 2062, +2187, 1947, 2063, +2188, 1945, 2068, +2188, 1950, 2081, +2188, 1955, 2098, +2191, 1957, 2124, +2187, 1958, 2158, +2166, 1958, 2197, +2157, 1958, 2256, +2157, 1958, 2315, +2170, 1965, 2391, +2214, 1983, 2481, +2243, 1992, 2520, +2243, 1992, 2520, +2243, 1992, 2520, +2243, 1992, 2520, +2243, 1992, 2520, +2243, 1992, 2520, +2243, 1992, 2520, +2243, 1992, 2520, +2243, 1992, 2520, +2243, 1992, 2520, +2280, 2135, 2094, +2279, 2135, 2094, +2279, 2135, 2094, +2279, 2135, 2093, +2279, 2135, 2093, +2279, 2135, 2093, +2278, 2135, 2093, +2278, 2135, 2092, +2278, 2135, 2091, +2277, 2135, 2090, +2276, 2135, 2089, +2275, 2135, 2087, +2273, 2135, 2088, +2271, 2132, 2104, +2268, 2128, 2124, +2265, 2127, 2141, +2261, 2127, 2163, +2267, 2131, 2204, +2267, 2143, 2274, +2279, 2151, 2326, +2302, 2151, 2402, +2336, 2169, 2486, +2365, 2174, 2524, +2365, 2174, 2524, +2365, 2174, 2524, +2365, 2174, 2524, +2365, 2174, 2524, +2365, 2174, 2524, +2365, 2174, 2524, +2365, 2174, 2524, +2365, 2174, 2524, +2365, 2174, 2524, +2461, 2367, 2129, +2461, 2367, 2129, +2461, 2367, 2129, +2460, 2367, 2129, +2460, 2367, 2129, +2460, 2367, 2129, +2460, 2367, 2129, +2459, 2367, 2129, +2458, 2367, 2129, +2457, 2367, 2129, +2456, 2367, 2129, +2456, 2367, 2131, +2456, 2368, 2135, +2457, 2370, 2144, +2458, 2370, 2155, +2459, 2368, 2173, +2458, 2367, 2191, +2459, 2372, 2228, +2457, 2374, 2273, +2469, 2375, 2338, +2498, 2390, 2405, +2539, 2403, 2489, +2561, 2413, 2521, +2561, 2413, 2521, +2561, 2413, 2521, +2561, 2413, 2521, +2561, 2413, 2521, +2561, 2413, 2521, +2561, 2413, 2521, +2561, 2413, 2521, +2561, 2413, 2521, +2561, 2413, 2521, +2709, 2666, 2040, +2709, 2666, 2040, +2709, 2665, 2040, +2709, 2665, 2040, +2709, 2665, 2040, +2709, 2665, 2040, +2709, 2665, 2040, +2710, 2664, 2040, +2710, 2664, 2039, +2710, 2664, 2038, +2710, 2664, 2037, +2710, 2663, 2035, +2710, 2663, 2036, +2709, 2665, 2056, +2708, 2668, 2074, +2708, 2667, 2090, +2708, 2666, 2122, +2710, 2669, 2190, +2713, 2675, 2273, +2712, 2672, 2336, +2722, 2681, 2446, +2732, 2688, 2548, +2743, 2699, 2604, +2743, 2699, 2604, +2743, 2699, 2604, +2743, 2699, 2604, +2743, 2699, 2604, +2743, 2699, 2604, +2743, 2699, 2604, +2743, 2699, 2604, +2743, 2699, 2604, +2743, 2699, 2604, +2736, 2777, 2472, +2736, 2777, 2472, +2736, 2777, 2472, +2736, 2777, 2473, +2736, 2778, 2473, +2736, 2778, 2473, +2736, 2778, 2473, +2736, 2778, 2474, +2736, 2778, 2475, +2736, 2778, 2475, +2736, 2779, 2476, +2736, 2779, 2478, +2736, 2779, 2480, +2736, 2779, 2480, +2736, 2779, 2480, +2737, 2778, 2487, +2736, 2777, 2497, +2732, 2777, 2512, +2731, 2783, 2550, +2734, 2783, 2585, +2737, 2787, 2644, +2741, 2798, 2718, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2736, 2777, 2472, +2736, 2777, 2472, +2736, 2777, 2472, +2736, 2777, 2473, +2736, 2778, 2473, +2736, 2778, 2473, +2736, 2778, 2473, +2736, 2778, 2474, +2736, 2778, 2475, +2736, 2778, 2475, +2736, 2779, 2476, +2736, 2779, 2478, +2736, 2779, 2480, +2736, 2779, 2480, +2736, 2779, 2480, +2737, 2778, 2487, +2736, 2777, 2497, +2732, 2777, 2512, +2731, 2783, 2550, +2734, 2783, 2585, +2737, 2787, 2644, +2741, 2798, 2718, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2736, 2777, 2472, +2736, 2777, 2472, +2736, 2777, 2472, +2736, 2777, 2473, +2736, 2778, 2473, +2736, 2778, 2473, +2736, 2778, 2473, +2736, 2778, 2474, +2736, 2778, 2475, +2736, 2778, 2475, +2736, 2779, 2476, +2736, 2779, 2478, +2736, 2779, 2480, +2736, 2779, 2480, +2736, 2779, 2480, +2737, 2778, 2487, +2736, 2777, 2497, +2732, 2777, 2512, +2731, 2783, 2550, +2734, 2783, 2585, +2737, 2787, 2644, +2741, 2798, 2718, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2736, 2777, 2472, +2736, 2777, 2472, +2736, 2777, 2472, +2736, 2777, 2473, +2736, 2778, 2473, +2736, 2778, 2473, +2736, 2778, 2473, +2736, 2778, 2474, +2736, 2778, 2475, +2736, 2778, 2475, +2736, 2779, 2476, +2736, 2779, 2478, +2736, 2779, 2480, +2736, 2779, 2480, +2736, 2779, 2480, +2737, 2778, 2487, +2736, 2777, 2497, +2732, 2777, 2512, +2731, 2783, 2550, +2734, 2783, 2585, +2737, 2787, 2644, +2741, 2798, 2718, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2736, 2777, 2472, +2736, 2777, 2472, +2736, 2777, 2472, +2736, 2777, 2473, +2736, 2778, 2473, +2736, 2778, 2473, +2736, 2778, 2473, +2736, 2778, 2474, +2736, 2778, 2475, +2736, 2778, 2475, +2736, 2779, 2476, +2736, 2779, 2478, +2736, 2779, 2480, +2736, 2779, 2480, +2736, 2779, 2480, +2737, 2778, 2487, +2736, 2777, 2497, +2732, 2777, 2512, +2731, 2783, 2550, +2734, 2783, 2585, +2737, 2787, 2644, +2741, 2798, 2718, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2736, 2777, 2472, +2736, 2777, 2472, +2736, 2777, 2472, +2736, 2777, 2473, +2736, 2778, 2473, +2736, 2778, 2473, +2736, 2778, 2473, +2736, 2778, 2474, +2736, 2778, 2475, +2736, 2778, 2475, +2736, 2779, 2476, +2736, 2779, 2478, +2736, 2779, 2480, +2736, 2779, 2480, +2736, 2779, 2480, +2737, 2778, 2487, +2736, 2777, 2497, +2732, 2777, 2512, +2731, 2783, 2550, +2734, 2783, 2585, +2737, 2787, 2644, +2741, 2798, 2718, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2736, 2777, 2472, +2736, 2777, 2472, +2736, 2777, 2472, +2736, 2777, 2473, +2736, 2778, 2473, +2736, 2778, 2473, +2736, 2778, 2473, +2736, 2778, 2474, +2736, 2778, 2475, +2736, 2778, 2475, +2736, 2779, 2476, +2736, 2779, 2478, +2736, 2779, 2480, +2736, 2779, 2480, +2736, 2779, 2480, +2737, 2778, 2487, +2736, 2777, 2497, +2732, 2777, 2512, +2731, 2783, 2550, +2734, 2783, 2585, +2737, 2787, 2644, +2741, 2798, 2718, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2736, 2777, 2472, +2736, 2777, 2472, +2736, 2777, 2472, +2736, 2777, 2473, +2736, 2778, 2473, +2736, 2778, 2473, +2736, 2778, 2473, +2736, 2778, 2474, +2736, 2778, 2475, +2736, 2778, 2475, +2736, 2779, 2476, +2736, 2779, 2478, +2736, 2779, 2480, +2736, 2779, 2480, +2736, 2779, 2480, +2737, 2778, 2487, +2736, 2777, 2497, +2732, 2777, 2512, +2731, 2783, 2550, +2734, 2783, 2585, +2737, 2787, 2644, +2741, 2798, 2718, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2736, 2777, 2472, +2736, 2777, 2472, +2736, 2777, 2472, +2736, 2777, 2473, +2736, 2778, 2473, +2736, 2778, 2473, +2736, 2778, 2473, +2736, 2778, 2474, +2736, 2778, 2475, +2736, 2778, 2475, +2736, 2779, 2476, +2736, 2779, 2478, +2736, 2779, 2480, +2736, 2779, 2480, +2736, 2779, 2480, +2737, 2778, 2487, +2736, 2777, 2497, +2732, 2777, 2512, +2731, 2783, 2550, +2734, 2783, 2585, +2737, 2787, 2644, +2741, 2798, 2718, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2736, 2777, 2472, +2736, 2777, 2472, +2736, 2777, 2472, +2736, 2777, 2473, +2736, 2778, 2473, +2736, 2778, 2473, +2736, 2778, 2473, +2736, 2778, 2474, +2736, 2778, 2475, +2736, 2778, 2475, +2736, 2779, 2476, +2736, 2779, 2478, +2736, 2779, 2480, +2736, 2779, 2480, +2736, 2779, 2480, +2737, 2778, 2487, +2736, 2777, 2497, +2732, 2777, 2512, +2731, 2783, 2550, +2734, 2783, 2585, +2737, 2787, 2644, +2741, 2798, 2718, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2746, 2799, 2749, +2203, 0, 1962, +2203, 0, 1963, +2203, 0, 1963, +2203, 0, 1964, +2202, 0, 1966, +2202, 0, 1967, +2202, 0, 1969, +2202, 0, 1972, +2201, 0, 1976, +2200, 0, 1981, +2199, 0, 1988, +2198, 0, 1996, +2196, 0, 2008, +2194, 0, 2027, +2190, 0, 2051, +2189, 0, 2090, +2187, 0, 2135, +2178, 0, 2178, +2160, 0, 2231, +2145, 0, 2305, +2169, 0, 2389, +2195, 0, 2474, +2191, 934, 2513, +2191, 934, 2513, +2191, 934, 2513, +2191, 934, 2513, +2191, 934, 2513, +2191, 934, 2513, +2191, 934, 2513, +2191, 934, 2513, +2191, 934, 2513, +2191, 934, 2513, +2203, 0, 1962, +2203, 0, 1963, +2203, 0, 1963, +2203, 0, 1965, +2202, 0, 1966, +2202, 0, 1967, +2202, 0, 1969, +2202, 0, 1972, +2201, 0, 1976, +2200, 0, 1981, +2199, 0, 1988, +2198, 0, 1997, +2196, 0, 2008, +2194, 0, 2027, +2190, 0, 2051, +2189, 0, 2090, +2187, 0, 2135, +2178, 0, 2178, +2160, 0, 2231, +2145, 0, 2305, +2169, 0, 2389, +2195, 0, 2474, +2191, 935, 2513, +2191, 935, 2513, +2191, 935, 2513, +2191, 935, 2513, +2191, 935, 2513, +2191, 935, 2513, +2191, 935, 2513, +2191, 935, 2513, +2191, 935, 2513, +2191, 935, 2513, +2203, 0, 1962, +2203, 0, 1963, +2203, 0, 1964, +2203, 0, 1965, +2202, 0, 1966, +2202, 0, 1968, +2202, 0, 1970, +2202, 0, 1973, +2201, 0, 1976, +2200, 0, 1981, +2199, 0, 1988, +2198, 0, 1997, +2196, 0, 2008, +2194, 0, 2026, +2190, 0, 2051, +2189, 0, 2090, +2187, 0, 2135, +2178, 0, 2178, +2161, 0, 2231, +2146, 0, 2305, +2169, 0, 2389, +2195, 0, 2474, +2191, 937, 2513, +2191, 937, 2513, +2191, 937, 2513, +2191, 937, 2513, +2191, 937, 2513, +2191, 937, 2513, +2191, 937, 2513, +2191, 937, 2513, +2191, 937, 2513, +2191, 937, 2513, +2203, 0, 1963, +2203, 0, 1963, +2203, 0, 1964, +2203, 0, 1965, +2202, 0, 1966, +2202, 0, 1968, +2202, 0, 1970, +2202, 0, 1973, +2201, 0, 1977, +2200, 0, 1982, +2199, 0, 1988, +2198, 0, 1997, +2196, 0, 2008, +2194, 0, 2026, +2190, 0, 2050, +2189, 0, 2090, +2187, 0, 2135, +2178, 0, 2178, +2161, 0, 2232, +2146, 0, 2305, +2169, 0, 2389, +2195, 0, 2474, +2192, 939, 2513, +2192, 939, 2513, +2192, 939, 2513, +2192, 939, 2513, +2192, 939, 2513, +2192, 939, 2513, +2192, 939, 2513, +2192, 939, 2513, +2192, 939, 2513, +2192, 939, 2513, +2202, 0, 1963, +2202, 0, 1963, +2202, 0, 1964, +2202, 0, 1965, +2202, 0, 1966, +2202, 0, 1968, +2202, 0, 1970, +2202, 0, 1973, +2201, 0, 1977, +2200, 0, 1982, +2199, 0, 1989, +2198, 0, 1997, +2196, 0, 2009, +2194, 0, 2026, +2190, 0, 2050, +2188, 0, 2090, +2187, 0, 2136, +2178, 0, 2178, +2161, 0, 2232, +2147, 0, 2305, +2169, 0, 2389, +2195, 0, 2474, +2192, 942, 2513, +2192, 942, 2513, +2192, 942, 2513, +2192, 942, 2513, +2192, 942, 2513, +2192, 942, 2513, +2192, 942, 2513, +2192, 942, 2513, +2192, 942, 2513, +2192, 942, 2513, +2202, 0, 1963, +2202, 0, 1964, +2202, 0, 1965, +2202, 0, 1966, +2202, 0, 1967, +2202, 0, 1969, +2202, 0, 1970, +2202, 0, 1973, +2201, 0, 1977, +2200, 0, 1982, +2199, 0, 1989, +2198, 0, 1998, +2196, 0, 2009, +2194, 0, 2026, +2190, 0, 2050, +2188, 0, 2090, +2187, 0, 2136, +2178, 0, 2178, +2162, 0, 2232, +2148, 0, 2305, +2169, 0, 2389, +2195, 74, 2474, +2193, 946, 2513, +2193, 946, 2513, +2193, 946, 2513, +2193, 946, 2513, +2193, 946, 2513, +2193, 946, 2513, +2193, 946, 2513, +2193, 946, 2513, +2193, 946, 2513, +2193, 946, 2513, +2202, 0, 1964, +2202, 0, 1965, +2202, 0, 1965, +2202, 0, 1966, +2202, 0, 1968, +2202, 0, 1969, +2202, 0, 1971, +2202, 0, 1974, +2201, 0, 1978, +2200, 0, 1983, +2199, 0, 1989, +2198, 0, 1998, +2196, 0, 2010, +2194, 0, 2025, +2190, 0, 2049, +2188, 0, 2090, +2187, 0, 2137, +2178, 0, 2178, +2162, 0, 2232, +2149, 0, 2305, +2168, 0, 2389, +2196, 195, 2474, +2194, 951, 2513, +2194, 951, 2513, +2194, 951, 2513, +2194, 951, 2513, +2194, 951, 2513, +2194, 951, 2513, +2194, 951, 2513, +2194, 951, 2513, +2194, 951, 2513, +2194, 951, 2513, +2202, 0, 1965, +2202, 0, 1965, +2202, 0, 1966, +2202, 0, 1967, +2202, 0, 1968, +2202, 0, 1970, +2202, 0, 1972, +2202, 0, 1975, +2201, 0, 1979, +2200, 0, 1984, +2199, 0, 1990, +2198, 0, 1999, +2196, 0, 2010, +2194, 0, 2024, +2190, 0, 2049, +2188, 0, 2090, +2187, 0, 2138, +2178, 0, 2178, +2163, 0, 2233, +2150, 0, 2306, +2168, 0, 2388, +2196, 319, 2474, +2195, 957, 2513, +2195, 957, 2513, +2195, 957, 2513, +2195, 957, 2513, +2195, 957, 2513, +2195, 957, 2513, +2195, 957, 2513, +2195, 957, 2513, +2195, 957, 2513, +2195, 957, 2513, +2201, 0, 1966, +2201, 0, 1966, +2201, 0, 1967, +2201, 0, 1968, +2201, 0, 1969, +2201, 0, 1971, +2201, 0, 1973, +2201, 0, 1976, +2201, 0, 1979, +2200, 0, 1984, +2199, 0, 1991, +2198, 0, 2000, +2196, 0, 2011, +2194, 0, 2024, +2190, 0, 2048, +2187, 0, 2090, +2187, 0, 2140, +2178, 0, 2178, +2165, 0, 2233, +2152, 111, 2306, +2167, 0, 2388, +2195, 419, 2475, +2197, 966, 2513, +2197, 966, 2513, +2197, 966, 2513, +2197, 966, 2513, +2197, 966, 2513, +2197, 966, 2513, +2197, 966, 2513, +2197, 966, 2513, +2197, 966, 2513, +2197, 966, 2513, +2200, 0, 1967, +2200, 0, 1968, +2200, 0, 1968, +2200, 0, 1969, +2200, 0, 1970, +2200, 0, 1972, +2200, 0, 1974, +2200, 0, 1977, +2200, 0, 1981, +2200, 0, 1986, +2199, 0, 1993, +2198, 0, 2001, +2196, 0, 2012, +2194, 0, 2023, +2190, 0, 2047, +2186, 0, 2090, +2186, 0, 2140, +2178, 0, 2178, +2166, 0, 2234, +2155, 244, 2307, +2166, 0, 2388, +2195, 523, 2475, +2199, 978, 2513, +2199, 978, 2513, +2199, 978, 2513, +2199, 978, 2513, +2199, 978, 2513, +2199, 978, 2513, +2199, 978, 2513, +2199, 978, 2513, +2199, 978, 2513, +2199, 978, 2513, +2199, 0, 1969, +2199, 0, 1969, +2199, 0, 1970, +2199, 0, 1971, +2199, 0, 1972, +2199, 0, 1974, +2199, 0, 1976, +2199, 0, 1979, +2199, 0, 1983, +2199, 0, 1988, +2199, 0, 1994, +2198, 0, 2003, +2196, 0, 2014, +2194, 0, 2025, +2190, 0, 2045, +2186, 0, 2089, +2185, 0, 2140, +2178, 0, 2180, +2169, 0, 2235, +2158, 376, 2308, +2165, 61, 2387, +2194, 633, 2476, +2202, 993, 2513, +2202, 993, 2513, +2202, 993, 2513, +2202, 993, 2513, +2202, 993, 2513, +2202, 993, 2513, +2202, 993, 2513, +2202, 993, 2513, +2202, 993, 2513, +2202, 993, 2513, +2198, 0, 1971, +2198, 0, 1972, +2198, 0, 1972, +2198, 0, 1973, +2198, 0, 1974, +2198, 0, 1976, +2198, 0, 1978, +2198, 0, 1981, +2198, 0, 1985, +2198, 0, 1990, +2198, 0, 1996, +2198, 0, 2005, +2196, 0, 2016, +2194, 0, 2027, +2190, 0, 2043, +2186, 0, 2087, +2183, 0, 2140, +2178, 0, 2183, +2172, 0, 2236, +2163, 508, 2309, +2167, 263, 2387, +2192, 748, 2476, +2206, 1012, 2513, +2206, 1012, 2513, +2206, 1012, 2513, +2206, 1012, 2513, +2206, 1012, 2513, +2206, 1012, 2513, +2206, 1012, 2513, +2206, 1012, 2513, +2206, 1012, 2513, +2206, 1012, 2513, +2197, 0, 1974, +2197, 0, 1974, +2197, 0, 1975, +2197, 0, 1976, +2197, 0, 1977, +2197, 0, 1979, +2197, 0, 1981, +2197, 0, 1984, +2197, 0, 1988, +2197, 0, 1993, +2197, 0, 1999, +2197, 0, 2008, +2196, 0, 2019, +2194, 0, 2030, +2190, 0, 2044, +2186, 0, 2085, +2183, 0, 2139, +2179, 0, 2186, +2175, 0, 2237, +2168, 643, 2310, +2170, 532, 2388, +2192, 890, 2477, +2211, 1054, 2513, +2211, 1054, 2513, +2211, 1054, 2513, +2211, 1054, 2513, +2211, 1054, 2513, +2211, 1054, 2513, +2211, 1054, 2513, +2211, 1054, 2513, +2211, 1054, 2513, +2211, 1054, 2513, +2200, 621, 1974, +2200, 621, 1974, +2200, 621, 1976, +2200, 621, 1977, +2200, 621, 1978, +2200, 621, 1980, +2201, 621, 1983, +2201, 621, 1986, +2202, 621, 1991, +2202, 621, 1997, +2202, 621, 2003, +2202, 621, 2012, +2202, 617, 2022, +2196, 529, 2033, +2193, 529, 2047, +2189, 621, 2082, +2185, 627, 2133, +2182, 413, 2189, +2177, 708, 2240, +2170, 828, 2310, +2173, 948, 2390, +2196, 1121, 2478, +2216, 1189, 2513, +2216, 1189, 2513, +2216, 1189, 2513, +2216, 1189, 2513, +2216, 1189, 2513, +2216, 1189, 2513, +2216, 1189, 2513, +2216, 1189, 2513, +2216, 1189, 2513, +2216, 1189, 2513, +2203, 974, 1974, +2203, 974, 1974, +2203, 974, 1976, +2203, 974, 1977, +2203, 974, 1978, +2204, 974, 1980, +2204, 974, 1983, +2204, 974, 1986, +2205, 974, 1991, +2206, 974, 1997, +2207, 974, 2005, +2208, 974, 2016, +2208, 973, 2027, +2203, 934, 2038, +2196, 877, 2052, +2192, 934, 2084, +2188, 977, 2129, +2185, 874, 2183, +2181, 1059, 2243, +2174, 996, 2310, +2175, 1202, 2391, +2206, 1271, 2478, +2222, 1322, 2513, +2222, 1322, 2513, +2222, 1322, 2513, +2222, 1322, 2513, +2222, 1322, 2513, +2222, 1322, 2513, +2222, 1322, 2513, +2222, 1322, 2513, +2222, 1322, 2513, +2222, 1322, 2513, +2208, 1278, 1984, +2208, 1279, 1985, +2208, 1279, 1986, +2208, 1281, 1986, +2209, 1282, 1987, +2209, 1284, 1988, +2209, 1286, 1990, +2209, 1289, 1992, +2210, 1294, 1995, +2211, 1299, 1998, +2212, 1302, 2005, +2213, 1302, 2016, +2214, 1300, 2030, +2212, 1282, 2047, +2206, 1256, 2063, +2201, 1278, 2090, +2194, 1321, 2134, +2193, 1308, 2182, +2182, 1327, 2241, +2178, 1331, 2310, +2182, 1416, 2391, +2214, 1452, 2477, +2228, 1489, 2513, +2228, 1489, 2513, +2228, 1489, 2513, +2228, 1489, 2513, +2228, 1489, 2513, +2228, 1489, 2513, +2228, 1489, 2513, +2228, 1489, 2513, +2228, 1489, 2513, +2228, 1489, 2513, +2220, 1531, 2004, +2220, 1531, 2004, +2220, 1531, 2004, +2220, 1532, 2005, +2220, 1533, 2006, +2220, 1534, 2007, +2220, 1535, 2008, +2220, 1537, 2010, +2220, 1540, 2013, +2221, 1543, 2017, +2222, 1547, 2021, +2223, 1553, 2027, +2224, 1559, 2037, +2222, 1557, 2051, +2218, 1543, 2073, +2214, 1535, 2102, +2208, 1550, 2140, +2199, 1572, 2190, +2195, 1558, 2240, +2192, 1577, 2310, +2192, 1604, 2393, +2223, 1653, 2476, +2238, 1676, 2514, +2238, 1676, 2514, +2238, 1676, 2514, +2238, 1676, 2514, +2238, 1676, 2514, +2238, 1676, 2514, +2238, 1676, 2514, +2238, 1676, 2514, +2238, 1676, 2514, +2238, 1676, 2514, +2241, 1755, 2023, +2241, 1755, 2023, +2241, 1755, 2024, +2241, 1755, 2024, +2241, 1755, 2025, +2241, 1755, 2025, +2241, 1755, 2026, +2241, 1755, 2028, +2241, 1755, 2029, +2241, 1755, 2031, +2241, 1758, 2036, +2241, 1761, 2042, +2240, 1765, 2049, +2240, 1765, 2063, +2238, 1765, 2080, +2237, 1764, 2104, +2229, 1762, 2147, +2223, 1755, 2193, +2223, 1765, 2244, +2223, 1774, 2315, +2215, 1795, 2391, +2250, 1824, 2482, +2262, 1849, 2517, +2262, 1849, 2517, +2262, 1849, 2517, +2262, 1849, 2517, +2262, 1849, 2517, +2262, 1849, 2517, +2262, 1849, 2517, +2262, 1849, 2517, +2262, 1849, 2517, +2262, 1849, 2517, +2268, 1946, 2048, +2268, 1946, 2049, +2269, 1946, 2049, +2269, 1946, 2050, +2269, 1946, 2051, +2269, 1946, 2051, +2270, 1946, 2053, +2270, 1946, 2054, +2270, 1946, 2057, +2271, 1946, 2060, +2272, 1946, 2064, +2273, 1946, 2070, +2274, 1945, 2077, +2274, 1945, 2087, +2274, 1945, 2099, +2271, 1951, 2124, +2268, 1961, 2158, +2265, 1963, 2203, +2273, 1968, 2256, +2261, 1969, 2321, +2271, 1965, 2394, +2310, 1995, 2482, +2335, 2014, 2520, +2335, 2014, 2520, +2335, 2014, 2520, +2335, 2014, 2520, +2335, 2014, 2520, +2335, 2014, 2520, +2335, 2014, 2520, +2335, 2014, 2520, +2335, 2014, 2520, +2335, 2014, 2520, +2351, 2143, 2087, +2351, 2143, 2087, +2351, 2143, 2087, +2351, 2143, 2088, +2351, 2143, 2088, +2351, 2143, 2089, +2351, 2143, 2091, +2351, 2143, 2092, +2351, 2143, 2094, +2351, 2143, 2097, +2351, 2143, 2101, +2351, 2143, 2106, +2351, 2143, 2112, +2351, 2143, 2115, +2351, 2143, 2119, +2351, 2143, 2141, +2349, 2146, 2174, +2346, 2147, 2214, +2351, 2143, 2263, +2356, 2159, 2326, +2362, 2167, 2401, +2402, 2189, 2492, +2434, 2202, 2530, +2434, 2202, 2530, +2434, 2202, 2530, +2434, 2202, 2530, +2434, 2202, 2530, +2434, 2202, 2530, +2434, 2202, 2530, +2434, 2202, 2530, +2434, 2202, 2530, +2434, 2202, 2530, +2515, 2384, 2126, +2514, 2384, 2127, +2514, 2384, 2127, +2514, 2384, 2127, +2514, 2383, 2127, +2514, 2383, 2127, +2514, 2383, 2128, +2514, 2383, 2128, +2514, 2382, 2129, +2513, 2382, 2130, +2513, 2381, 2131, +2513, 2381, 2133, +2514, 2382, 2135, +2515, 2384, 2141, +2515, 2385, 2150, +2515, 2388, 2172, +2515, 2388, 2195, +2520, 2388, 2230, +2523, 2391, 2279, +2523, 2395, 2342, +2548, 2407, 2404, +2582, 2421, 2483, +2607, 2433, 2514, +2607, 2433, 2514, +2607, 2433, 2514, +2607, 2433, 2514, +2607, 2433, 2514, +2607, 2433, 2514, +2607, 2433, 2514, +2607, 2433, 2514, +2607, 2433, 2514, +2607, 2433, 2514, +2731, 2680, 2128, +2731, 2680, 2129, +2731, 2680, 2129, +2731, 2680, 2130, +2731, 2680, 2131, +2731, 2681, 2132, +2731, 2681, 2133, +2731, 2681, 2135, +2731, 2681, 2136, +2730, 2681, 2137, +2730, 2681, 2138, +2729, 2680, 2140, +2728, 2679, 2142, +2728, 2679, 2150, +2730, 2679, 2164, +2731, 2678, 2176, +2730, 2679, 2195, +2730, 2680, 2243, +2735, 2682, 2308, +2735, 2687, 2382, +2739, 2689, 2468, +2750, 2708, 2581, +2756, 2707, 2625, +2756, 2707, 2625, +2756, 2707, 2625, +2756, 2707, 2625, +2756, 2707, 2625, +2756, 2707, 2625, +2756, 2707, 2625, +2756, 2707, 2625, +2756, 2707, 2625, +2756, 2707, 2625, +2755, 2784, 2495, +2755, 2784, 2495, +2755, 2784, 2495, +2755, 2784, 2496, +2755, 2784, 2496, +2755, 2784, 2496, +2755, 2784, 2497, +2755, 2784, 2498, +2755, 2785, 2499, +2755, 2785, 2501, +2755, 2786, 2503, +2755, 2786, 2506, +2755, 2787, 2509, +2755, 2787, 2512, +2755, 2787, 2515, +2754, 2787, 2520, +2753, 2788, 2528, +2753, 2787, 2543, +2751, 2785, 2569, +2749, 2789, 2602, +2753, 2795, 2660, +2755, 2801, 2726, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2755, 2784, 2495, +2755, 2784, 2495, +2755, 2784, 2495, +2755, 2784, 2496, +2755, 2784, 2496, +2755, 2784, 2496, +2755, 2784, 2497, +2755, 2784, 2498, +2755, 2785, 2499, +2755, 2785, 2501, +2755, 2786, 2503, +2755, 2786, 2506, +2755, 2787, 2509, +2755, 2787, 2512, +2755, 2787, 2515, +2754, 2787, 2520, +2753, 2788, 2528, +2753, 2787, 2543, +2751, 2785, 2569, +2749, 2789, 2602, +2753, 2795, 2660, +2755, 2801, 2726, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2755, 2784, 2495, +2755, 2784, 2495, +2755, 2784, 2495, +2755, 2784, 2496, +2755, 2784, 2496, +2755, 2784, 2496, +2755, 2784, 2497, +2755, 2784, 2498, +2755, 2785, 2499, +2755, 2785, 2501, +2755, 2786, 2503, +2755, 2786, 2506, +2755, 2787, 2509, +2755, 2787, 2512, +2755, 2787, 2515, +2754, 2787, 2520, +2753, 2788, 2528, +2753, 2787, 2543, +2751, 2785, 2569, +2749, 2789, 2602, +2753, 2795, 2660, +2755, 2801, 2726, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2755, 2784, 2495, +2755, 2784, 2495, +2755, 2784, 2495, +2755, 2784, 2496, +2755, 2784, 2496, +2755, 2784, 2496, +2755, 2784, 2497, +2755, 2784, 2498, +2755, 2785, 2499, +2755, 2785, 2501, +2755, 2786, 2503, +2755, 2786, 2506, +2755, 2787, 2509, +2755, 2787, 2512, +2755, 2787, 2515, +2754, 2787, 2520, +2753, 2788, 2528, +2753, 2787, 2543, +2751, 2785, 2569, +2749, 2789, 2602, +2753, 2795, 2660, +2755, 2801, 2726, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2755, 2784, 2495, +2755, 2784, 2495, +2755, 2784, 2495, +2755, 2784, 2496, +2755, 2784, 2496, +2755, 2784, 2496, +2755, 2784, 2497, +2755, 2784, 2498, +2755, 2785, 2499, +2755, 2785, 2501, +2755, 2786, 2503, +2755, 2786, 2506, +2755, 2787, 2509, +2755, 2787, 2512, +2755, 2787, 2515, +2754, 2787, 2520, +2753, 2788, 2528, +2753, 2787, 2543, +2751, 2785, 2569, +2749, 2789, 2602, +2753, 2795, 2660, +2755, 2801, 2726, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2755, 2784, 2495, +2755, 2784, 2495, +2755, 2784, 2495, +2755, 2784, 2496, +2755, 2784, 2496, +2755, 2784, 2496, +2755, 2784, 2497, +2755, 2784, 2498, +2755, 2785, 2499, +2755, 2785, 2501, +2755, 2786, 2503, +2755, 2786, 2506, +2755, 2787, 2509, +2755, 2787, 2512, +2755, 2787, 2515, +2754, 2787, 2520, +2753, 2788, 2528, +2753, 2787, 2543, +2751, 2785, 2569, +2749, 2789, 2602, +2753, 2795, 2660, +2755, 2801, 2726, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2755, 2784, 2495, +2755, 2784, 2495, +2755, 2784, 2495, +2755, 2784, 2496, +2755, 2784, 2496, +2755, 2784, 2496, +2755, 2784, 2497, +2755, 2784, 2498, +2755, 2785, 2499, +2755, 2785, 2501, +2755, 2786, 2503, +2755, 2786, 2506, +2755, 2787, 2509, +2755, 2787, 2512, +2755, 2787, 2515, +2754, 2787, 2520, +2753, 2788, 2528, +2753, 2787, 2543, +2751, 2785, 2569, +2749, 2789, 2602, +2753, 2795, 2660, +2755, 2801, 2726, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2755, 2784, 2495, +2755, 2784, 2495, +2755, 2784, 2495, +2755, 2784, 2496, +2755, 2784, 2496, +2755, 2784, 2496, +2755, 2784, 2497, +2755, 2784, 2498, +2755, 2785, 2499, +2755, 2785, 2501, +2755, 2786, 2503, +2755, 2786, 2506, +2755, 2787, 2509, +2755, 2787, 2512, +2755, 2787, 2515, +2754, 2787, 2520, +2753, 2788, 2528, +2753, 2787, 2543, +2751, 2785, 2569, +2749, 2789, 2602, +2753, 2795, 2660, +2755, 2801, 2726, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2755, 2784, 2495, +2755, 2784, 2495, +2755, 2784, 2495, +2755, 2784, 2496, +2755, 2784, 2496, +2755, 2784, 2496, +2755, 2784, 2497, +2755, 2784, 2498, +2755, 2785, 2499, +2755, 2785, 2501, +2755, 2786, 2503, +2755, 2786, 2506, +2755, 2787, 2509, +2755, 2787, 2512, +2755, 2787, 2515, +2754, 2787, 2520, +2753, 2788, 2528, +2753, 2787, 2543, +2751, 2785, 2569, +2749, 2789, 2602, +2753, 2795, 2660, +2755, 2801, 2726, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2755, 2784, 2495, +2755, 2784, 2495, +2755, 2784, 2495, +2755, 2784, 2496, +2755, 2784, 2496, +2755, 2784, 2496, +2755, 2784, 2497, +2755, 2784, 2498, +2755, 2785, 2499, +2755, 2785, 2501, +2755, 2786, 2503, +2755, 2786, 2506, +2755, 2787, 2509, +2755, 2787, 2512, +2755, 2787, 2515, +2754, 2787, 2520, +2753, 2788, 2528, +2753, 2787, 2543, +2751, 2785, 2569, +2749, 2789, 2602, +2753, 2795, 2660, +2755, 2801, 2726, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2757, 2802, 2755, +2331, 0, 2000, +2331, 0, 2000, +2331, 0, 2001, +2331, 0, 2001, +2331, 0, 2002, +2331, 0, 2003, +2331, 0, 2005, +2331, 0, 2007, +2331, 0, 2010, +2331, 0, 2013, +2331, 0, 2018, +2331, 0, 2024, +2330, 0, 2034, +2326, 0, 2051, +2322, 0, 2072, +2321, 0, 2094, +2320, 0, 2138, +2314, 0, 2186, +2319, 0, 2244, +2315, 0, 2315, +2317, 0, 2391, +2334, 913, 2480, +2348, 1255, 2518, +2348, 1255, 2518, +2348, 1255, 2518, +2348, 1255, 2518, +2348, 1255, 2518, +2348, 1255, 2518, +2348, 1255, 2518, +2348, 1255, 2518, +2348, 1255, 2518, +2348, 1255, 2518, +2331, 0, 2000, +2331, 0, 2000, +2331, 0, 2001, +2331, 0, 2001, +2331, 0, 2002, +2331, 0, 2003, +2331, 0, 2005, +2331, 0, 2007, +2331, 0, 2010, +2331, 0, 2013, +2331, 0, 2018, +2331, 0, 2024, +2330, 0, 2034, +2326, 0, 2051, +2322, 0, 2072, +2321, 0, 2094, +2320, 0, 2138, +2315, 0, 2186, +2319, 0, 2245, +2315, 0, 2315, +2317, 0, 2392, +2334, 917, 2480, +2348, 1256, 2518, +2348, 1256, 2518, +2348, 1256, 2518, +2348, 1256, 2518, +2348, 1256, 2518, +2348, 1256, 2518, +2348, 1256, 2518, +2348, 1256, 2518, +2348, 1256, 2518, +2348, 1256, 2518, +2331, 0, 2000, +2331, 0, 2000, +2331, 0, 2001, +2331, 0, 2001, +2331, 0, 2002, +2331, 0, 2003, +2331, 0, 2005, +2331, 0, 2007, +2331, 0, 2010, +2331, 0, 2013, +2331, 0, 2018, +2330, 0, 2024, +2329, 0, 2034, +2326, 0, 2051, +2322, 0, 2072, +2321, 0, 2095, +2320, 0, 2138, +2315, 0, 2186, +2319, 0, 2245, +2315, 0, 2315, +2317, 0, 2392, +2334, 922, 2479, +2348, 1258, 2518, +2348, 1258, 2518, +2348, 1258, 2518, +2348, 1258, 2518, +2348, 1258, 2518, +2348, 1258, 2518, +2348, 1258, 2518, +2348, 1258, 2518, +2348, 1258, 2518, +2348, 1258, 2518, +2331, 0, 2000, +2331, 0, 2000, +2331, 0, 2001, +2331, 0, 2001, +2331, 0, 2002, +2331, 0, 2003, +2331, 0, 2005, +2331, 0, 2007, +2331, 0, 2010, +2331, 0, 2013, +2331, 0, 2018, +2330, 0, 2024, +2329, 0, 2034, +2326, 0, 2052, +2322, 0, 2072, +2321, 0, 2095, +2321, 0, 2138, +2315, 0, 2186, +2319, 0, 2245, +2315, 0, 2315, +2317, 0, 2392, +2334, 929, 2479, +2348, 1260, 2518, +2348, 1260, 2518, +2348, 1260, 2518, +2348, 1260, 2518, +2348, 1260, 2518, +2348, 1260, 2518, +2348, 1260, 2518, +2348, 1260, 2518, +2348, 1260, 2518, +2348, 1260, 2518, +2331, 0, 2000, +2331, 0, 2000, +2331, 0, 2001, +2331, 0, 2001, +2331, 0, 2002, +2331, 0, 2003, +2331, 0, 2005, +2331, 0, 2007, +2331, 0, 2010, +2331, 0, 2013, +2331, 0, 2018, +2330, 0, 2024, +2329, 0, 2034, +2326, 0, 2052, +2322, 0, 2072, +2321, 0, 2095, +2321, 0, 2138, +2315, 0, 2186, +2319, 0, 2245, +2315, 0, 2315, +2317, 0, 2392, +2334, 938, 2479, +2349, 1263, 2518, +2349, 1263, 2518, +2349, 1263, 2518, +2349, 1263, 2518, +2349, 1263, 2518, +2349, 1263, 2518, +2349, 1263, 2518, +2349, 1263, 2518, +2349, 1263, 2518, +2349, 1263, 2518, +2331, 0, 2000, +2331, 0, 2000, +2331, 0, 2001, +2331, 0, 2001, +2330, 0, 2002, +2330, 0, 2003, +2330, 0, 2005, +2330, 0, 2007, +2330, 0, 2010, +2330, 0, 2013, +2330, 0, 2018, +2330, 0, 2024, +2329, 0, 2034, +2326, 0, 2052, +2322, 0, 2073, +2321, 0, 2095, +2322, 0, 2138, +2315, 0, 2186, +2318, 0, 2245, +2315, 30, 2315, +2317, 0, 2392, +2334, 949, 2479, +2349, 1267, 2518, +2349, 1267, 2518, +2349, 1267, 2518, +2349, 1267, 2518, +2349, 1267, 2518, +2349, 1267, 2518, +2349, 1267, 2518, +2349, 1267, 2518, +2349, 1267, 2518, +2349, 1267, 2518, +2331, 0, 2000, +2330, 0, 2000, +2330, 0, 2001, +2330, 0, 2001, +2330, 0, 2002, +2330, 0, 2003, +2330, 0, 2005, +2330, 0, 2007, +2330, 0, 2010, +2330, 0, 2013, +2330, 0, 2018, +2329, 0, 2024, +2328, 0, 2034, +2327, 0, 2053, +2323, 0, 2073, +2321, 0, 2096, +2322, 0, 2139, +2315, 0, 2186, +2318, 0, 2245, +2315, 163, 2315, +2317, 32, 2392, +2334, 964, 2478, +2350, 1272, 2518, +2350, 1272, 2518, +2350, 1272, 2518, +2350, 1272, 2518, +2350, 1272, 2518, +2350, 1272, 2518, +2350, 1272, 2518, +2350, 1272, 2518, +2350, 1272, 2518, +2350, 1272, 2518, +2330, 0, 2000, +2330, 0, 2000, +2330, 0, 2001, +2330, 0, 2001, +2330, 0, 2002, +2330, 0, 2003, +2329, 0, 2005, +2329, 0, 2007, +2329, 0, 2010, +2329, 0, 2013, +2329, 0, 2018, +2328, 0, 2024, +2327, 0, 2034, +2327, 0, 2053, +2323, 0, 2073, +2321, 0, 2096, +2323, 0, 2139, +2316, 0, 2186, +2318, 0, 2246, +2315, 295, 2315, +2317, 164, 2393, +2334, 983, 2478, +2351, 1279, 2518, +2351, 1279, 2518, +2351, 1279, 2518, +2351, 1279, 2518, +2351, 1279, 2518, +2351, 1279, 2518, +2351, 1279, 2518, +2351, 1279, 2518, +2351, 1279, 2518, +2351, 1279, 2518, +2330, 0, 2000, +2330, 0, 2000, +2330, 0, 2001, +2330, 0, 2001, +2329, 0, 2002, +2329, 0, 2003, +2329, 0, 2005, +2329, 0, 2007, +2328, 0, 2010, +2328, 0, 2013, +2328, 0, 2018, +2328, 0, 2024, +2327, 0, 2034, +2327, 0, 2054, +2323, 0, 2074, +2321, 0, 2097, +2325, 0, 2140, +2316, 0, 2186, +2317, 111, 2246, +2315, 426, 2315, +2317, 296, 2393, +2334, 993, 2478, +2352, 1288, 2518, +2352, 1288, 2518, +2352, 1288, 2518, +2352, 1288, 2518, +2352, 1288, 2518, +2352, 1288, 2518, +2352, 1288, 2518, +2352, 1288, 2518, +2352, 1288, 2518, +2352, 1288, 2518, +2329, 0, 2000, +2329, 0, 2000, +2329, 0, 2001, +2329, 0, 2001, +2329, 0, 2002, +2329, 0, 2003, +2328, 0, 2005, +2328, 0, 2007, +2328, 0, 2010, +2327, 0, 2013, +2327, 0, 2018, +2326, 0, 2024, +2325, 0, 2034, +2327, 0, 2055, +2324, 0, 2075, +2321, 0, 2098, +2325, 0, 2141, +2317, 0, 2186, +2317, 244, 2247, +2315, 559, 2315, +2317, 428, 2393, +2335, 1003, 2479, +2354, 1300, 2518, +2354, 1300, 2518, +2354, 1300, 2518, +2354, 1300, 2518, +2354, 1300, 2518, +2354, 1300, 2518, +2354, 1300, 2518, +2354, 1300, 2518, +2354, 1300, 2518, +2354, 1300, 2518, +2328, 0, 2000, +2328, 0, 2000, +2328, 0, 2001, +2328, 0, 2001, +2328, 0, 2002, +2328, 0, 2003, +2328, 0, 2005, +2327, 0, 2007, +2327, 0, 2010, +2326, 0, 2013, +2325, 0, 2018, +2325, 0, 2024, +2324, 0, 2034, +2326, 0, 2055, +2325, 61, 2077, +2322, 0, 2099, +2325, 0, 2142, +2319, 0, 2187, +2316, 376, 2248, +2315, 691, 2315, +2317, 560, 2394, +2337, 1018, 2479, +2356, 1315, 2518, +2356, 1315, 2518, +2356, 1315, 2518, +2356, 1315, 2518, +2356, 1315, 2518, +2356, 1315, 2518, +2356, 1315, 2518, +2356, 1315, 2518, +2356, 1315, 2518, +2356, 1315, 2518, +2328, 0, 2000, +2328, 0, 2000, +2328, 0, 2001, +2328, 0, 2001, +2328, 0, 2002, +2327, 0, 2003, +2327, 0, 2005, +2327, 0, 2007, +2326, 0, 2010, +2326, 0, 2013, +2325, 0, 2018, +2325, 0, 2027, +2324, 0, 2036, +2326, 0, 2057, +2327, 111, 2081, +2323, 0, 2103, +2324, 0, 2142, +2322, 0, 2190, +2315, 426, 2247, +2315, 741, 2315, +2319, 692, 2394, +2338, 1091, 2481, +2357, 1322, 2518, +2357, 1322, 2518, +2357, 1322, 2518, +2357, 1322, 2518, +2357, 1322, 2518, +2357, 1322, 2518, +2357, 1322, 2518, +2357, 1322, 2518, +2357, 1322, 2518, +2357, 1322, 2518, +2328, 0, 2000, +2328, 0, 2001, +2328, 0, 2001, +2328, 0, 2002, +2328, 0, 2003, +2328, 0, 2004, +2328, 0, 2006, +2327, 0, 2008, +2327, 0, 2011, +2326, 0, 2014, +2326, 0, 2019, +2325, 0, 2028, +2325, 0, 2040, +2327, 44, 2061, +2328, 216, 2085, +2326, 0, 2109, +2323, 0, 2139, +2324, 123, 2193, +2314, 517, 2247, +2316, 765, 2314, +2321, 843, 2393, +2340, 1204, 2482, +2357, 1332, 2518, +2357, 1332, 2518, +2357, 1332, 2518, +2357, 1332, 2518, +2357, 1332, 2518, +2357, 1332, 2518, +2357, 1332, 2518, +2357, 1332, 2518, +2357, 1332, 2518, +2357, 1332, 2518, +2332, 614, 2005, +2332, 614, 2005, +2332, 614, 2006, +2332, 614, 2007, +2332, 614, 2008, +2332, 614, 2009, +2331, 614, 2011, +2331, 614, 2014, +2331, 614, 2017, +2330, 614, 2021, +2329, 614, 2026, +2329, 614, 2035, +2329, 614, 2047, +2329, 614, 2057, +2330, 670, 2082, +2328, 727, 2109, +2321, 757, 2137, +2324, 709, 2196, +2318, 901, 2249, +2318, 868, 2316, +2319, 1072, 2391, +2342, 1300, 2483, +2357, 1409, 2519, +2357, 1409, 2519, +2357, 1409, 2519, +2357, 1409, 2519, +2357, 1409, 2519, +2357, 1409, 2519, +2357, 1409, 2519, +2357, 1409, 2519, +2357, 1409, 2519, +2357, 1409, 2519, +2336, 924, 2012, +2336, 924, 2013, +2336, 924, 2013, +2336, 924, 2014, +2335, 924, 2015, +2335, 924, 2017, +2335, 924, 2019, +2335, 924, 2021, +2335, 924, 2024, +2334, 924, 2029, +2333, 924, 2035, +2333, 924, 2042, +2333, 924, 2052, +2333, 924, 2063, +2333, 971, 2080, +2330, 1020, 2108, +2324, 1065, 2141, +2325, 1052, 2197, +2321, 1173, 2253, +2319, 1077, 2317, +2317, 1227, 2391, +2345, 1377, 2483, +2359, 1509, 2521, +2359, 1509, 2521, +2359, 1509, 2521, +2359, 1509, 2521, +2359, 1509, 2521, +2359, 1509, 2521, +2359, 1509, 2521, +2359, 1509, 2521, +2359, 1509, 2521, +2359, 1509, 2521, +2339, 1291, 2020, +2339, 1291, 2020, +2339, 1290, 2020, +2339, 1289, 2020, +2339, 1288, 2021, +2339, 1286, 2022, +2338, 1283, 2023, +2338, 1280, 2024, +2338, 1276, 2026, +2337, 1270, 2028, +2336, 1267, 2033, +2336, 1267, 2040, +2336, 1269, 2048, +2336, 1288, 2065, +2336, 1315, 2084, +2334, 1351, 2116, +2331, 1343, 2151, +2330, 1343, 2198, +2326, 1378, 2257, +2319, 1407, 2317, +2328, 1414, 2394, +2350, 1546, 2482, +2368, 1608, 2518, +2368, 1608, 2518, +2368, 1608, 2518, +2368, 1608, 2518, +2368, 1608, 2518, +2368, 1608, 2518, +2368, 1608, 2518, +2368, 1608, 2518, +2368, 1608, 2518, +2368, 1608, 2518, +2349, 1557, 2025, +2349, 1557, 2025, +2349, 1557, 2025, +2349, 1557, 2026, +2348, 1557, 2026, +2348, 1557, 2027, +2348, 1557, 2028, +2348, 1557, 2029, +2347, 1557, 2031, +2347, 1554, 2033, +2346, 1550, 2036, +2345, 1548, 2041, +2344, 1548, 2050, +2344, 1550, 2067, +2343, 1557, 2089, +2339, 1571, 2115, +2337, 1566, 2150, +2337, 1567, 2198, +2334, 1596, 2255, +2334, 1620, 2319, +2342, 1646, 2396, +2365, 1717, 2481, +2382, 1733, 2518, +2382, 1733, 2518, +2382, 1733, 2518, +2382, 1733, 2518, +2382, 1733, 2518, +2382, 1733, 2518, +2382, 1733, 2518, +2382, 1733, 2518, +2382, 1733, 2518, +2382, 1733, 2518, +2364, 1776, 2032, +2364, 1776, 2033, +2364, 1776, 2033, +2364, 1777, 2034, +2364, 1778, 2035, +2364, 1779, 2037, +2363, 1781, 2038, +2363, 1783, 2041, +2363, 1786, 2044, +2362, 1790, 2049, +2361, 1791, 2052, +2360, 1789, 2057, +2359, 1784, 2065, +2361, 1784, 2074, +2360, 1788, 2094, +2357, 1783, 2117, +2358, 1792, 2156, +2361, 1806, 2207, +2354, 1805, 2259, +2356, 1809, 2322, +2365, 1822, 2394, +2383, 1874, 2484, +2403, 1889, 2522, +2403, 1889, 2522, +2403, 1889, 2522, +2403, 1889, 2522, +2403, 1889, 2522, +2403, 1889, 2522, +2403, 1889, 2522, +2403, 1889, 2522, +2403, 1889, 2522, +2403, 1889, 2522, +2391, 1976, 2073, +2391, 1976, 2073, +2391, 1976, 2073, +2391, 1976, 2073, +2391, 1976, 2073, +2391, 1976, 2074, +2391, 1976, 2074, +2391, 1976, 2075, +2391, 1976, 2076, +2391, 1976, 2077, +2391, 1976, 2078, +2391, 1976, 2080, +2392, 1977, 2084, +2394, 1981, 2093, +2395, 1984, 2105, +2395, 1984, 2134, +2392, 1984, 2163, +2391, 1984, 2207, +2387, 1995, 2266, +2396, 1995, 2324, +2406, 2017, 2405, +2425, 2038, 2488, +2448, 2060, 2526, +2448, 2060, 2526, +2448, 2060, 2526, +2448, 2060, 2526, +2448, 2060, 2526, +2448, 2060, 2526, +2448, 2060, 2526, +2448, 2060, 2526, +2448, 2060, 2526, +2448, 2060, 2526, +2463, 2177, 2109, +2463, 2177, 2109, +2463, 2177, 2110, +2463, 2177, 2110, +2463, 2177, 2110, +2463, 2177, 2111, +2463, 2178, 2112, +2463, 2178, 2113, +2463, 2179, 2114, +2463, 2180, 2116, +2463, 2181, 2119, +2462, 2182, 2121, +2460, 2183, 2124, +2459, 2181, 2126, +2458, 2177, 2134, +2459, 2184, 2157, +2463, 2186, 2183, +2461, 2184, 2220, +2460, 2188, 2268, +2468, 2189, 2340, +2476, 2191, 2406, +2508, 2230, 2493, +2527, 2237, 2533, +2527, 2237, 2533, +2527, 2237, 2533, +2527, 2237, 2533, +2527, 2237, 2533, +2527, 2237, 2533, +2527, 2237, 2533, +2527, 2237, 2533, +2527, 2237, 2533, +2527, 2237, 2533, +2598, 2410, 2071, +2598, 2410, 2071, +2599, 2411, 2071, +2599, 2411, 2071, +2599, 2411, 2071, +2600, 2412, 2070, +2600, 2412, 2070, +2602, 2413, 2069, +2603, 2414, 2069, +2604, 2416, 2068, +2606, 2418, 2066, +2607, 2419, 2068, +2607, 2420, 2073, +2607, 2420, 2079, +2607, 2420, 2088, +2607, 2420, 2112, +2607, 2422, 2147, +2606, 2422, 2181, +2609, 2420, 2243, +2615, 2426, 2302, +2628, 2437, 2380, +2656, 2458, 2462, +2676, 2468, 2496, +2676, 2468, 2496, +2676, 2468, 2496, +2676, 2468, 2496, +2676, 2468, 2496, +2676, 2468, 2496, +2676, 2468, 2496, +2676, 2468, 2496, +2676, 2468, 2496, +2676, 2468, 2496, +2763, 2702, 2255, +2763, 2702, 2255, +2763, 2702, 2255, +2762, 2701, 2255, +2762, 2701, 2255, +2762, 2701, 2255, +2762, 2701, 2255, +2762, 2701, 2255, +2762, 2701, 2255, +2763, 2701, 2256, +2763, 2701, 2257, +2764, 2701, 2260, +2765, 2701, 2267, +2765, 2701, 2274, +2763, 2702, 2284, +2762, 2704, 2300, +2763, 2706, 2316, +2764, 2703, 2348, +2764, 2703, 2388, +2768, 2710, 2455, +2769, 2717, 2538, +2774, 2727, 2626, +2777, 2731, 2667, +2777, 2731, 2667, +2777, 2731, 2667, +2777, 2731, 2667, +2777, 2731, 2667, +2777, 2731, 2667, +2777, 2731, 2667, +2777, 2731, 2667, +2777, 2731, 2667, +2777, 2731, 2667, +2781, 2797, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2549, +2781, 2798, 2550, +2781, 2799, 2550, +2781, 2799, 2551, +2781, 2800, 2553, +2782, 2800, 2555, +2782, 2801, 2558, +2781, 2801, 2560, +2780, 2800, 2559, +2782, 2800, 2561, +2781, 2802, 2573, +2781, 2801, 2584, +2780, 2801, 2606, +2777, 2799, 2640, +2775, 2801, 2677, +2779, 2810, 2744, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2797, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2549, +2781, 2798, 2550, +2781, 2799, 2550, +2781, 2799, 2551, +2781, 2800, 2553, +2782, 2800, 2555, +2782, 2801, 2558, +2781, 2801, 2560, +2780, 2800, 2559, +2782, 2800, 2561, +2781, 2802, 2573, +2781, 2801, 2584, +2780, 2801, 2606, +2777, 2799, 2640, +2775, 2801, 2677, +2779, 2810, 2744, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2797, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2549, +2781, 2798, 2550, +2781, 2799, 2550, +2781, 2799, 2551, +2781, 2800, 2553, +2782, 2800, 2555, +2782, 2801, 2558, +2781, 2801, 2560, +2780, 2800, 2559, +2782, 2800, 2561, +2781, 2802, 2573, +2781, 2801, 2584, +2780, 2801, 2606, +2777, 2799, 2640, +2775, 2801, 2677, +2779, 2810, 2744, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2797, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2549, +2781, 2798, 2550, +2781, 2799, 2550, +2781, 2799, 2551, +2781, 2800, 2553, +2782, 2800, 2555, +2782, 2801, 2558, +2781, 2801, 2560, +2780, 2800, 2559, +2782, 2800, 2561, +2781, 2802, 2573, +2781, 2801, 2584, +2780, 2801, 2606, +2777, 2799, 2640, +2775, 2801, 2677, +2779, 2810, 2744, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2797, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2549, +2781, 2798, 2550, +2781, 2799, 2550, +2781, 2799, 2551, +2781, 2800, 2553, +2782, 2800, 2555, +2782, 2801, 2558, +2781, 2801, 2560, +2780, 2800, 2559, +2782, 2800, 2561, +2781, 2802, 2573, +2781, 2801, 2584, +2780, 2801, 2606, +2777, 2799, 2640, +2775, 2801, 2677, +2779, 2810, 2744, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2797, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2549, +2781, 2798, 2550, +2781, 2799, 2550, +2781, 2799, 2551, +2781, 2800, 2553, +2782, 2800, 2555, +2782, 2801, 2558, +2781, 2801, 2560, +2780, 2800, 2559, +2782, 2800, 2561, +2781, 2802, 2573, +2781, 2801, 2584, +2780, 2801, 2606, +2777, 2799, 2640, +2775, 2801, 2677, +2779, 2810, 2744, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2797, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2549, +2781, 2798, 2550, +2781, 2799, 2550, +2781, 2799, 2551, +2781, 2800, 2553, +2782, 2800, 2555, +2782, 2801, 2558, +2781, 2801, 2560, +2780, 2800, 2559, +2782, 2800, 2561, +2781, 2802, 2573, +2781, 2801, 2584, +2780, 2801, 2606, +2777, 2799, 2640, +2775, 2801, 2677, +2779, 2810, 2744, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2797, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2549, +2781, 2798, 2550, +2781, 2799, 2550, +2781, 2799, 2551, +2781, 2800, 2553, +2782, 2800, 2555, +2782, 2801, 2558, +2781, 2801, 2560, +2780, 2800, 2559, +2782, 2800, 2561, +2781, 2802, 2573, +2781, 2801, 2584, +2780, 2801, 2606, +2777, 2799, 2640, +2775, 2801, 2677, +2779, 2810, 2744, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2797, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2549, +2781, 2798, 2550, +2781, 2799, 2550, +2781, 2799, 2551, +2781, 2800, 2553, +2782, 2800, 2555, +2782, 2801, 2558, +2781, 2801, 2560, +2780, 2800, 2559, +2782, 2800, 2561, +2781, 2802, 2573, +2781, 2801, 2584, +2780, 2801, 2606, +2777, 2799, 2640, +2775, 2801, 2677, +2779, 2810, 2744, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2797, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2548, +2781, 2798, 2549, +2781, 2798, 2550, +2781, 2799, 2550, +2781, 2799, 2551, +2781, 2800, 2553, +2782, 2800, 2555, +2782, 2801, 2558, +2781, 2801, 2560, +2780, 2800, 2559, +2782, 2800, 2561, +2781, 2802, 2573, +2781, 2801, 2584, +2780, 2801, 2606, +2777, 2799, 2640, +2775, 2801, 2677, +2779, 2810, 2744, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2781, 2810, 2772, +2481, 974, 2044, +2481, 973, 2044, +2481, 971, 2044, +2481, 969, 2045, +2480, 967, 2045, +2480, 963, 2046, +2480, 958, 2047, +2480, 951, 2048, +2480, 951, 2051, +2480, 951, 2054, +2480, 951, 2058, +2480, 951, 2063, +2480, 955, 2072, +2479, 992, 2087, +2477, 1037, 2103, +2476, 1071, 2127, +2475, 1132, 2163, +2475, 1219, 2209, +2476, 1370, 2267, +2478, 1392, 2329, +2488, 1469, 2402, +2504, 1610, 2488, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2481, 977, 2044, +2481, 977, 2044, +2481, 976, 2044, +2480, 974, 2045, +2480, 971, 2045, +2480, 968, 2046, +2480, 963, 2047, +2480, 956, 2048, +2480, 955, 2051, +2480, 955, 2054, +2480, 955, 2058, +2480, 955, 2063, +2480, 960, 2072, +2479, 996, 2087, +2477, 1041, 2103, +2476, 1074, 2127, +2476, 1133, 2163, +2475, 1220, 2209, +2476, 1373, 2267, +2478, 1394, 2329, +2488, 1469, 2402, +2504, 1611, 2488, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2481, 982, 2044, +2481, 982, 2044, +2480, 982, 2044, +2480, 980, 2045, +2480, 977, 2045, +2480, 974, 2046, +2480, 969, 2047, +2480, 962, 2048, +2480, 962, 2051, +2480, 962, 2054, +2480, 962, 2058, +2480, 962, 2063, +2480, 966, 2072, +2479, 1002, 2087, +2477, 1046, 2103, +2476, 1079, 2127, +2476, 1136, 2162, +2475, 1221, 2209, +2476, 1377, 2267, +2478, 1397, 2329, +2488, 1469, 2402, +2504, 1611, 2488, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2481, 988, 2044, +2480, 988, 2044, +2480, 988, 2044, +2480, 988, 2045, +2480, 985, 2045, +2480, 981, 2046, +2480, 977, 2047, +2480, 970, 2048, +2480, 970, 2051, +2480, 970, 2054, +2480, 970, 2058, +2480, 970, 2063, +2480, 974, 2072, +2479, 1010, 2087, +2477, 1053, 2103, +2476, 1085, 2127, +2476, 1138, 2162, +2475, 1222, 2209, +2476, 1382, 2267, +2478, 1400, 2329, +2488, 1469, 2402, +2504, 1612, 2488, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2480, 996, 2044, +2480, 996, 2044, +2480, 996, 2044, +2480, 996, 2045, +2480, 996, 2045, +2480, 992, 2046, +2480, 987, 2047, +2480, 981, 2048, +2480, 981, 2051, +2480, 981, 2054, +2480, 981, 2058, +2480, 981, 2063, +2480, 985, 2072, +2479, 1020, 2087, +2477, 1062, 2103, +2476, 1094, 2127, +2476, 1142, 2162, +2476, 1223, 2208, +2476, 1388, 2268, +2478, 1404, 2329, +2488, 1469, 2402, +2504, 1614, 2487, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2480, 1006, 2044, +2480, 1006, 2044, +2480, 1006, 2044, +2480, 1006, 2045, +2480, 1006, 2045, +2480, 1006, 2046, +2480, 1001, 2047, +2479, 995, 2048, +2479, 995, 2051, +2479, 995, 2054, +2479, 995, 2058, +2479, 995, 2063, +2479, 999, 2072, +2479, 1032, 2087, +2477, 1074, 2103, +2476, 1105, 2127, +2476, 1147, 2162, +2476, 1225, 2208, +2476, 1397, 2268, +2478, 1409, 2329, +2488, 1469, 2401, +2503, 1615, 2487, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2519, 1697, 2526, +2480, 1019, 2044, +2480, 1019, 2044, +2480, 1019, 2044, +2480, 1019, 2045, +2480, 1019, 2045, +2480, 1019, 2046, +2479, 1019, 2047, +2479, 1013, 2048, +2479, 1013, 2051, +2479, 1013, 2054, +2479, 1013, 2058, +2479, 1013, 2063, +2479, 1017, 2072, +2479, 1049, 2087, +2477, 1089, 2103, +2475, 1119, 2127, +2476, 1154, 2161, +2476, 1228, 2208, +2477, 1408, 2268, +2477, 1417, 2329, +2488, 1469, 2401, +2503, 1618, 2486, +2518, 1697, 2526, +2518, 1697, 2526, +2518, 1697, 2526, +2518, 1697, 2526, +2518, 1697, 2526, +2518, 1697, 2526, +2518, 1697, 2526, +2518, 1697, 2526, +2518, 1697, 2526, +2518, 1697, 2526, +2480, 1036, 2044, +2480, 1036, 2044, +2480, 1036, 2044, +2480, 1036, 2045, +2480, 1036, 2045, +2479, 1036, 2046, +2479, 1036, 2047, +2479, 1036, 2048, +2479, 1036, 2051, +2479, 1036, 2054, +2479, 1036, 2058, +2479, 1036, 2063, +2479, 1039, 2072, +2478, 1070, 2087, +2476, 1108, 2103, +2475, 1137, 2127, +2477, 1162, 2161, +2476, 1232, 2207, +2477, 1423, 2268, +2477, 1426, 2329, +2488, 1469, 2401, +2503, 1621, 2486, +2518, 1697, 2526, +2518, 1697, 2526, +2518, 1697, 2526, +2518, 1697, 2526, +2518, 1697, 2526, +2518, 1697, 2526, +2518, 1697, 2526, +2518, 1697, 2526, +2518, 1697, 2526, +2518, 1697, 2526, +2480, 1071, 2044, +2480, 1071, 2044, +2480, 1071, 2044, +2480, 1071, 2045, +2480, 1071, 2045, +2479, 1071, 2046, +2479, 1071, 2047, +2479, 1071, 2048, +2479, 1044, 2051, +2479, 1044, 2054, +2479, 1044, 2058, +2479, 1044, 2063, +2479, 1048, 2072, +2479, 1085, 2087, +2477, 1122, 2103, +2476, 1149, 2126, +2478, 1179, 2161, +2476, 1241, 2208, +2477, 1424, 2268, +2478, 1436, 2329, +2488, 1480, 2401, +2504, 1627, 2485, +2519, 1702, 2526, +2519, 1702, 2526, +2519, 1702, 2526, +2519, 1702, 2526, +2519, 1702, 2526, +2519, 1702, 2526, +2519, 1702, 2526, +2519, 1702, 2526, +2519, 1702, 2526, +2519, 1702, 2526, +2480, 1115, 2044, +2480, 1115, 2044, +2480, 1115, 2044, +2480, 1115, 2045, +2480, 1115, 2045, +2479, 1115, 2046, +2479, 1115, 2047, +2479, 1115, 2048, +2479, 1091, 2051, +2479, 1054, 2054, +2479, 1054, 2058, +2479, 1054, 2063, +2479, 1058, 2072, +2479, 1099, 2087, +2478, 1138, 2103, +2476, 1165, 2125, +2478, 1193, 2160, +2477, 1254, 2209, +2477, 1424, 2266, +2479, 1448, 2329, +2488, 1495, 2401, +2504, 1635, 2485, +2521, 1708, 2526, +2521, 1708, 2526, +2521, 1708, 2526, +2521, 1708, 2526, +2521, 1708, 2526, +2521, 1708, 2526, +2521, 1708, 2526, +2521, 1708, 2526, +2521, 1708, 2526, +2521, 1708, 2526, +2480, 1169, 2044, +2480, 1169, 2044, +2480, 1169, 2044, +2480, 1169, 2045, +2480, 1169, 2045, +2479, 1169, 2046, +2479, 1169, 2047, +2479, 1169, 2048, +2479, 1147, 2051, +2479, 1114, 2054, +2479, 1067, 2058, +2479, 1067, 2063, +2479, 1070, 2072, +2479, 1111, 2087, +2479, 1159, 2103, +2478, 1185, 2125, +2480, 1212, 2159, +2478, 1278, 2209, +2477, 1424, 2264, +2480, 1464, 2329, +2488, 1514, 2402, +2505, 1646, 2485, +2523, 1718, 2525, +2523, 1718, 2525, +2523, 1718, 2525, +2523, 1718, 2525, +2523, 1718, 2525, +2523, 1718, 2525, +2523, 1718, 2525, +2523, 1718, 2525, +2523, 1718, 2525, +2523, 1718, 2525, +2480, 1231, 2044, +2480, 1231, 2044, +2480, 1231, 2044, +2480, 1231, 2045, +2480, 1231, 2045, +2479, 1231, 2046, +2479, 1231, 2047, +2479, 1231, 2048, +2479, 1212, 2051, +2479, 1184, 2054, +2479, 1144, 2058, +2479, 1083, 2063, +2479, 1087, 2072, +2479, 1126, 2087, +2481, 1186, 2103, +2479, 1210, 2125, +2481, 1236, 2158, +2479, 1308, 2209, +2477, 1424, 2262, +2481, 1485, 2329, +2488, 1542, 2402, +2507, 1660, 2485, +2526, 1729, 2524, +2526, 1729, 2524, +2526, 1729, 2524, +2526, 1729, 2524, +2526, 1729, 2524, +2526, 1729, 2524, +2526, 1729, 2524, +2526, 1729, 2524, +2526, 1729, 2524, +2526, 1729, 2524, +2480, 1299, 2045, +2480, 1299, 2045, +2480, 1299, 2045, +2480, 1299, 2046, +2480, 1299, 2046, +2480, 1299, 2047, +2480, 1299, 2048, +2479, 1299, 2049, +2479, 1283, 2051, +2479, 1259, 2054, +2479, 1225, 2059, +2479, 1174, 2064, +2479, 1114, 2072, +2480, 1151, 2087, +2481, 1213, 2103, +2481, 1244, 2125, +2483, 1268, 2156, +2481, 1346, 2209, +2477, 1430, 2260, +2483, 1511, 2329, +2489, 1583, 2403, +2509, 1680, 2486, +2529, 1745, 2524, +2529, 1745, 2524, +2529, 1745, 2524, +2529, 1745, 2524, +2529, 1745, 2524, +2529, 1745, 2524, +2529, 1745, 2524, +2529, 1745, 2524, +2529, 1745, 2524, +2529, 1745, 2524, +2482, 1385, 2049, +2482, 1385, 2049, +2482, 1384, 2049, +2482, 1384, 2050, +2482, 1382, 2050, +2482, 1381, 2051, +2482, 1379, 2052, +2481, 1376, 2053, +2482, 1366, 2055, +2482, 1349, 2058, +2482, 1321, 2063, +2482, 1281, 2068, +2482, 1235, 2076, +2482, 1263, 2087, +2484, 1312, 2103, +2484, 1330, 2127, +2485, 1346, 2157, +2483, 1386, 2211, +2480, 1472, 2262, +2483, 1568, 2328, +2492, 1634, 2404, +2509, 1714, 2486, +2531, 1767, 2524, +2531, 1767, 2524, +2531, 1767, 2524, +2531, 1767, 2524, +2531, 1767, 2524, +2531, 1767, 2524, +2531, 1767, 2524, +2531, 1767, 2524, +2531, 1767, 2524, +2531, 1767, 2524, +2484, 1508, 2049, +2484, 1507, 2049, +2484, 1507, 2049, +2484, 1506, 2050, +2484, 1506, 2050, +2484, 1504, 2051, +2483, 1503, 2052, +2483, 1501, 2053, +2483, 1493, 2055, +2484, 1482, 2058, +2485, 1467, 2063, +2485, 1445, 2068, +2485, 1416, 2076, +2486, 1436, 2087, +2488, 1470, 2103, +2487, 1479, 2127, +2487, 1478, 2157, +2484, 1484, 2208, +2487, 1547, 2268, +2485, 1642, 2328, +2495, 1671, 2406, +2509, 1751, 2486, +2531, 1801, 2522, +2531, 1801, 2522, +2531, 1801, 2522, +2531, 1801, 2522, +2531, 1801, 2522, +2531, 1801, 2522, +2531, 1801, 2522, +2531, 1801, 2522, +2531, 1801, 2522, +2531, 1801, 2522, +2490, 1632, 2052, +2490, 1632, 2052, +2490, 1632, 2053, +2490, 1632, 2054, +2490, 1632, 2054, +2490, 1632, 2056, +2490, 1632, 2057, +2490, 1632, 2060, +2490, 1628, 2062, +2491, 1623, 2066, +2491, 1613, 2070, +2492, 1598, 2075, +2493, 1580, 2082, +2492, 1580, 2091, +2493, 1600, 2105, +2492, 1613, 2131, +2491, 1631, 2162, +2489, 1632, 2206, +2493, 1658, 2265, +2493, 1730, 2328, +2499, 1742, 2404, +2518, 1813, 2489, +2537, 1864, 2526, +2537, 1864, 2526, +2537, 1864, 2526, +2537, 1864, 2526, +2537, 1864, 2526, +2537, 1864, 2526, +2537, 1864, 2526, +2537, 1864, 2526, +2537, 1864, 2526, +2537, 1864, 2526, +2502, 1784, 2071, +2502, 1784, 2071, +2502, 1784, 2071, +2502, 1784, 2072, +2502, 1784, 2073, +2502, 1784, 2073, +2502, 1784, 2075, +2502, 1784, 2077, +2502, 1779, 2078, +2502, 1774, 2081, +2503, 1769, 2085, +2503, 1762, 2090, +2504, 1754, 2098, +2504, 1757, 2107, +2503, 1757, 2115, +2502, 1754, 2140, +2499, 1757, 2175, +2500, 1778, 2215, +2501, 1806, 2266, +2500, 1817, 2326, +2509, 1832, 2402, +2528, 1891, 2490, +2547, 1940, 2532, +2547, 1940, 2532, +2547, 1940, 2532, +2547, 1940, 2532, +2547, 1940, 2532, +2547, 1940, 2532, +2547, 1940, 2532, +2547, 1940, 2532, +2547, 1940, 2532, +2547, 1940, 2532, +2516, 1927, 2075, +2516, 1928, 2075, +2516, 1928, 2075, +2516, 1928, 2076, +2516, 1928, 2076, +2517, 1929, 2077, +2517, 1929, 2078, +2517, 1930, 2079, +2517, 1930, 2081, +2516, 1930, 2084, +2516, 1924, 2087, +2515, 1913, 2090, +2514, 1901, 2096, +2516, 1900, 2105, +2517, 1912, 2120, +2515, 1910, 2143, +2514, 1921, 2180, +2513, 1918, 2218, +2516, 1938, 2272, +2518, 1938, 2333, +2528, 1977, 2406, +2552, 2008, 2491, +2567, 2036, 2526, +2567, 2036, 2526, +2567, 2036, 2526, +2567, 2036, 2526, +2567, 2036, 2526, +2567, 2036, 2526, +2567, 2036, 2526, +2567, 2036, 2526, +2567, 2036, 2526, +2567, 2036, 2526, +2547, 2073, 2093, +2547, 2073, 2093, +2547, 2073, 2093, +2546, 2073, 2093, +2546, 2073, 2094, +2546, 2073, 2094, +2545, 2073, 2095, +2545, 2073, 2096, +2545, 2073, 2098, +2545, 2073, 2100, +2545, 2073, 2102, +2545, 2073, 2106, +2545, 2073, 2111, +2545, 2075, 2119, +2543, 2075, 2127, +2543, 2078, 2149, +2543, 2075, 2180, +2546, 2089, 2222, +2546, 2091, 2274, +2551, 2098, 2337, +2558, 2115, 2411, +2588, 2155, 2491, +2598, 2168, 2529, +2598, 2168, 2529, +2598, 2168, 2529, +2598, 2168, 2529, +2598, 2168, 2529, +2598, 2168, 2529, +2598, 2168, 2529, +2598, 2168, 2529, +2598, 2168, 2529, +2598, 2168, 2529, +2602, 2259, 2099, +2602, 2258, 2099, +2602, 2258, 2099, +2602, 2258, 2099, +2602, 2258, 2099, +2601, 2258, 2099, +2600, 2258, 2099, +2600, 2257, 2099, +2600, 2257, 2101, +2600, 2257, 2104, +2600, 2257, 2108, +2600, 2257, 2113, +2600, 2257, 2120, +2603, 2257, 2132, +2606, 2257, 2144, +2606, 2263, 2161, +2611, 2270, 2190, +2606, 2266, 2226, +2612, 2277, 2289, +2615, 2277, 2347, +2621, 2290, 2414, +2651, 2318, 2497, +2668, 2333, 2527, +2668, 2333, 2527, +2668, 2333, 2527, +2668, 2333, 2527, +2668, 2333, 2527, +2668, 2333, 2527, +2668, 2333, 2527, +2668, 2333, 2527, +2668, 2333, 2527, +2668, 2333, 2527, +2722, 2488, 1839, +2722, 2488, 1839, +2722, 2488, 1841, +2722, 2488, 1843, +2723, 2488, 1845, +2723, 2489, 1848, +2724, 2489, 1852, +2724, 2489, 1858, +2724, 2489, 1862, +2724, 2489, 1867, +2724, 2488, 1873, +2723, 2488, 1876, +2723, 2488, 1878, +2722, 2488, 1891, +2722, 2486, 1913, +2722, 2485, 1956, +2723, 2487, 2015, +2723, 2486, 2070, +2727, 2489, 2159, +2732, 2495, 2242, +2745, 2509, 2352, +2763, 2528, 2453, +2772, 2539, 2499, +2772, 2539, 2499, +2772, 2539, 2499, +2772, 2539, 2499, +2772, 2539, 2499, +2772, 2539, 2499, +2772, 2539, 2499, +2772, 2539, 2499, +2772, 2539, 2499, +2772, 2539, 2499, +2811, 2738, 2425, +2811, 2738, 2425, +2811, 2738, 2426, +2811, 2738, 2426, +2811, 2738, 2426, +2811, 2738, 2426, +2811, 2738, 2427, +2811, 2738, 2427, +2811, 2739, 2428, +2811, 2739, 2430, +2811, 2739, 2431, +2811, 2740, 2434, +2811, 2740, 2437, +2811, 2740, 2440, +2810, 2740, 2444, +2810, 2740, 2448, +2811, 2742, 2464, +2810, 2743, 2483, +2810, 2745, 2522, +2810, 2748, 2564, +2811, 2752, 2623, +2810, 2762, 2701, +2813, 2763, 2731, +2813, 2763, 2731, +2813, 2763, 2731, +2813, 2763, 2731, +2813, 2763, 2731, +2813, 2763, 2731, +2813, 2763, 2731, +2813, 2763, 2731, +2813, 2763, 2731, +2813, 2763, 2731, +2820, 2813, 2591, +2820, 2813, 2591, +2820, 2813, 2591, +2820, 2813, 2591, +2820, 2813, 2590, +2820, 2813, 2590, +2820, 2813, 2589, +2820, 2812, 2589, +2820, 2813, 2590, +2820, 2813, 2591, +2820, 2813, 2592, +2820, 2813, 2593, +2820, 2814, 2596, +2819, 2814, 2598, +2818, 2813, 2599, +2820, 2813, 2604, +2822, 2813, 2612, +2820, 2813, 2623, +2820, 2815, 2643, +2818, 2815, 2670, +2818, 2817, 2713, +2813, 2819, 2768, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2820, 2813, 2591, +2820, 2813, 2591, +2820, 2813, 2591, +2820, 2813, 2591, +2820, 2813, 2590, +2820, 2813, 2590, +2820, 2813, 2589, +2820, 2812, 2589, +2820, 2813, 2590, +2820, 2813, 2591, +2820, 2813, 2592, +2820, 2813, 2593, +2820, 2814, 2596, +2819, 2814, 2598, +2818, 2813, 2599, +2820, 2813, 2604, +2822, 2813, 2612, +2820, 2813, 2623, +2820, 2815, 2643, +2818, 2815, 2670, +2818, 2817, 2713, +2813, 2819, 2768, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2820, 2813, 2591, +2820, 2813, 2591, +2820, 2813, 2591, +2820, 2813, 2591, +2820, 2813, 2590, +2820, 2813, 2590, +2820, 2813, 2589, +2820, 2812, 2589, +2820, 2813, 2590, +2820, 2813, 2591, +2820, 2813, 2592, +2820, 2813, 2593, +2820, 2814, 2596, +2819, 2814, 2598, +2818, 2813, 2599, +2820, 2813, 2604, +2822, 2813, 2612, +2820, 2813, 2623, +2820, 2815, 2643, +2818, 2815, 2670, +2818, 2817, 2713, +2813, 2819, 2768, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2820, 2813, 2591, +2820, 2813, 2591, +2820, 2813, 2591, +2820, 2813, 2591, +2820, 2813, 2590, +2820, 2813, 2590, +2820, 2813, 2589, +2820, 2812, 2589, +2820, 2813, 2590, +2820, 2813, 2591, +2820, 2813, 2592, +2820, 2813, 2593, +2820, 2814, 2596, +2819, 2814, 2598, +2818, 2813, 2599, +2820, 2813, 2604, +2822, 2813, 2612, +2820, 2813, 2623, +2820, 2815, 2643, +2818, 2815, 2670, +2818, 2817, 2713, +2813, 2819, 2768, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2820, 2813, 2591, +2820, 2813, 2591, +2820, 2813, 2591, +2820, 2813, 2591, +2820, 2813, 2590, +2820, 2813, 2590, +2820, 2813, 2589, +2820, 2812, 2589, +2820, 2813, 2590, +2820, 2813, 2591, +2820, 2813, 2592, +2820, 2813, 2593, +2820, 2814, 2596, +2819, 2814, 2598, +2818, 2813, 2599, +2820, 2813, 2604, +2822, 2813, 2612, +2820, 2813, 2623, +2820, 2815, 2643, +2818, 2815, 2670, +2818, 2817, 2713, +2813, 2819, 2768, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2820, 2813, 2591, +2820, 2813, 2591, +2820, 2813, 2591, +2820, 2813, 2591, +2820, 2813, 2590, +2820, 2813, 2590, +2820, 2813, 2589, +2820, 2812, 2589, +2820, 2813, 2590, +2820, 2813, 2591, +2820, 2813, 2592, +2820, 2813, 2593, +2820, 2814, 2596, +2819, 2814, 2598, +2818, 2813, 2599, +2820, 2813, 2604, +2822, 2813, 2612, +2820, 2813, 2623, +2820, 2815, 2643, +2818, 2815, 2670, +2818, 2817, 2713, +2813, 2819, 2768, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2820, 2813, 2591, +2820, 2813, 2591, +2820, 2813, 2591, +2820, 2813, 2591, +2820, 2813, 2590, +2820, 2813, 2590, +2820, 2813, 2589, +2820, 2812, 2589, +2820, 2813, 2590, +2820, 2813, 2591, +2820, 2813, 2592, +2820, 2813, 2593, +2820, 2814, 2596, +2819, 2814, 2598, +2818, 2813, 2599, +2820, 2813, 2604, +2822, 2813, 2612, +2820, 2813, 2623, +2820, 2815, 2643, +2818, 2815, 2670, +2818, 2817, 2713, +2813, 2819, 2768, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2820, 2813, 2591, +2820, 2813, 2591, +2820, 2813, 2591, +2820, 2813, 2591, +2820, 2813, 2590, +2820, 2813, 2590, +2820, 2813, 2589, +2820, 2812, 2589, +2820, 2813, 2590, +2820, 2813, 2591, +2820, 2813, 2592, +2820, 2813, 2593, +2820, 2814, 2596, +2819, 2814, 2598, +2818, 2813, 2599, +2820, 2813, 2604, +2822, 2813, 2612, +2820, 2813, 2623, +2820, 2815, 2643, +2818, 2815, 2670, +2818, 2817, 2713, +2813, 2819, 2768, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2820, 2813, 2591, +2820, 2813, 2591, +2820, 2813, 2591, +2820, 2813, 2591, +2820, 2813, 2590, +2820, 2813, 2590, +2820, 2813, 2589, +2820, 2812, 2589, +2820, 2813, 2590, +2820, 2813, 2591, +2820, 2813, 2592, +2820, 2813, 2593, +2820, 2814, 2596, +2819, 2814, 2598, +2818, 2813, 2599, +2820, 2813, 2604, +2822, 2813, 2612, +2820, 2813, 2623, +2820, 2815, 2643, +2818, 2815, 2670, +2818, 2817, 2713, +2813, 2819, 2768, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2820, 2813, 2591, +2820, 2813, 2591, +2820, 2813, 2591, +2820, 2813, 2591, +2820, 2813, 2590, +2820, 2813, 2590, +2820, 2813, 2589, +2820, 2812, 2589, +2820, 2813, 2590, +2820, 2813, 2591, +2820, 2813, 2592, +2820, 2813, 2593, +2820, 2814, 2596, +2819, 2814, 2598, +2818, 2813, 2599, +2820, 2813, 2604, +2822, 2813, 2612, +2820, 2813, 2623, +2820, 2815, 2643, +2818, 2815, 2670, +2818, 2817, 2713, +2813, 2819, 2768, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2814, 2823, 2799, +2554, 1623, 2059, +2554, 1623, 2059, +2554, 1623, 2060, +2554, 1623, 2060, +2554, 1623, 2061, +2554, 1623, 2063, +2554, 1623, 2065, +2554, 1623, 2067, +2554, 1623, 2070, +2554, 1623, 2074, +2554, 1623, 2080, +2554, 1623, 2087, +2554, 1621, 2096, +2554, 1621, 2102, +2554, 1621, 2110, +2555, 1588, 2133, +2556, 1555, 2169, +2555, 1608, 2217, +2557, 1691, 2269, +2563, 1692, 2342, +2564, 1761, 2409, +2587, 1838, 2491, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1625, 2059, +2554, 1624, 2059, +2554, 1624, 2060, +2554, 1624, 2060, +2554, 1624, 2061, +2554, 1624, 2063, +2554, 1624, 2064, +2554, 1624, 2067, +2554, 1624, 2070, +2554, 1624, 2074, +2554, 1624, 2080, +2554, 1624, 2087, +2554, 1621, 2096, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1590, 2134, +2556, 1556, 2169, +2555, 1609, 2217, +2557, 1691, 2269, +2563, 1692, 2342, +2564, 1762, 2409, +2587, 1839, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1627, 2059, +2554, 1626, 2059, +2554, 1625, 2060, +2554, 1625, 2060, +2554, 1625, 2061, +2554, 1625, 2063, +2554, 1625, 2064, +2554, 1625, 2067, +2554, 1625, 2070, +2554, 1625, 2074, +2554, 1625, 2079, +2554, 1625, 2086, +2554, 1622, 2096, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1592, 2134, +2556, 1559, 2169, +2555, 1610, 2217, +2557, 1691, 2269, +2564, 1693, 2342, +2564, 1764, 2409, +2587, 1840, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1630, 2060, +2554, 1629, 2060, +2554, 1627, 2060, +2554, 1625, 2060, +2554, 1625, 2061, +2554, 1625, 2062, +2554, 1625, 2064, +2554, 1625, 2066, +2554, 1625, 2070, +2554, 1625, 2074, +2554, 1625, 2079, +2554, 1625, 2086, +2554, 1623, 2095, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1595, 2134, +2556, 1562, 2169, +2555, 1611, 2217, +2557, 1691, 2270, +2564, 1694, 2342, +2564, 1765, 2409, +2587, 1842, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1633, 2060, +2554, 1632, 2060, +2554, 1631, 2060, +2554, 1629, 2060, +2554, 1626, 2061, +2554, 1626, 2062, +2554, 1626, 2064, +2554, 1626, 2066, +2554, 1626, 2069, +2554, 1626, 2073, +2554, 1626, 2079, +2554, 1626, 2086, +2554, 1625, 2095, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1599, 2135, +2556, 1567, 2169, +2555, 1613, 2217, +2557, 1692, 2270, +2564, 1695, 2342, +2565, 1768, 2409, +2587, 1844, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1638, 2061, +2554, 1638, 2061, +2554, 1636, 2061, +2554, 1634, 2061, +2554, 1631, 2061, +2554, 1628, 2062, +2554, 1628, 2063, +2554, 1628, 2066, +2554, 1628, 2069, +2554, 1628, 2073, +2554, 1628, 2079, +2554, 1628, 2086, +2554, 1626, 2095, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1605, 2135, +2556, 1572, 2169, +2555, 1616, 2217, +2557, 1693, 2270, +2564, 1696, 2342, +2565, 1771, 2409, +2587, 1847, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2555, 1645, 2062, +2555, 1644, 2062, +2555, 1643, 2062, +2555, 1641, 2062, +2555, 1638, 2062, +2555, 1635, 2063, +2555, 1631, 2063, +2555, 1631, 2066, +2555, 1631, 2069, +2555, 1631, 2073, +2555, 1631, 2078, +2555, 1631, 2085, +2555, 1628, 2094, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1612, 2136, +2556, 1580, 2169, +2554, 1619, 2217, +2558, 1694, 2270, +2564, 1698, 2342, +2565, 1775, 2409, +2587, 1852, 2492, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2555, 1654, 2063, +2555, 1653, 2063, +2555, 1651, 2063, +2555, 1650, 2063, +2555, 1647, 2063, +2555, 1644, 2064, +2555, 1640, 2064, +2555, 1633, 2065, +2555, 1633, 2068, +2555, 1633, 2072, +2555, 1633, 2078, +2555, 1633, 2085, +2555, 1631, 2094, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1621, 2137, +2557, 1590, 2169, +2554, 1624, 2217, +2558, 1695, 2270, +2564, 1701, 2342, +2565, 1781, 2409, +2588, 1857, 2493, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2556, 1665, 2064, +2556, 1664, 2065, +2556, 1663, 2065, +2556, 1661, 2065, +2556, 1659, 2065, +2556, 1655, 2066, +2556, 1651, 2066, +2556, 1646, 2066, +2556, 1638, 2067, +2556, 1638, 2071, +2556, 1638, 2077, +2556, 1638, 2084, +2556, 1636, 2093, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1633, 2138, +2557, 1603, 2169, +2554, 1630, 2217, +2558, 1697, 2271, +2564, 1704, 2342, +2565, 1788, 2409, +2588, 1860, 2493, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2556, 1680, 2066, +2556, 1679, 2067, +2556, 1678, 2067, +2556, 1676, 2067, +2556, 1674, 2067, +2556, 1671, 2068, +2556, 1667, 2068, +2556, 1661, 2069, +2556, 1653, 2069, +2556, 1643, 2070, +2556, 1643, 2076, +2556, 1643, 2083, +2556, 1641, 2092, +2554, 1624, 2101, +2554, 1621, 2110, +2557, 1649, 2140, +2557, 1620, 2170, +2554, 1638, 2217, +2558, 1699, 2271, +2565, 1709, 2342, +2566, 1798, 2409, +2589, 1863, 2493, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2558, 1699, 2069, +2558, 1698, 2069, +2558, 1697, 2070, +2558, 1695, 2070, +2558, 1693, 2070, +2558, 1690, 2070, +2558, 1686, 2071, +2558, 1681, 2071, +2558, 1674, 2072, +2558, 1663, 2073, +2558, 1650, 2074, +2558, 1650, 2082, +2557, 1648, 2091, +2555, 1631, 2100, +2554, 1621, 2110, +2557, 1657, 2141, +2558, 1642, 2173, +2554, 1658, 2217, +2559, 1702, 2273, +2565, 1715, 2342, +2566, 1810, 2409, +2589, 1868, 2493, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2559, 1723, 2073, +2559, 1723, 2073, +2559, 1722, 2073, +2559, 1720, 2073, +2559, 1718, 2074, +2559, 1715, 2074, +2559, 1711, 2074, +2559, 1706, 2075, +2559, 1699, 2076, +2559, 1690, 2077, +2559, 1677, 2078, +2559, 1659, 2080, +2558, 1657, 2089, +2556, 1641, 2098, +2554, 1621, 2110, +2557, 1657, 2141, +2558, 1669, 2176, +2555, 1684, 2217, +2560, 1706, 2274, +2566, 1723, 2342, +2567, 1816, 2409, +2591, 1873, 2493, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2560, 1754, 2078, +2560, 1754, 2078, +2560, 1753, 2078, +2560, 1752, 2079, +2560, 1750, 2079, +2560, 1747, 2079, +2560, 1744, 2080, +2560, 1739, 2080, +2560, 1732, 2081, +2560, 1724, 2082, +2560, 1712, 2083, +2560, 1695, 2085, +2560, 1674, 2088, +2558, 1658, 2097, +2555, 1635, 2110, +2557, 1661, 2141, +2559, 1703, 2179, +2556, 1716, 2217, +2560, 1716, 2275, +2566, 1739, 2342, +2568, 1818, 2408, +2592, 1880, 2493, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2562, 1761, 2078, +2562, 1761, 2078, +2562, 1761, 2079, +2562, 1762, 2080, +2562, 1763, 2080, +2562, 1765, 2082, +2562, 1766, 2084, +2562, 1769, 2086, +2562, 1772, 2089, +2563, 1771, 2091, +2563, 1760, 2093, +2563, 1745, 2094, +2562, 1727, 2097, +2561, 1712, 2103, +2558, 1692, 2116, +2556, 1693, 2138, +2560, 1738, 2181, +2560, 1744, 2217, +2561, 1744, 2275, +2566, 1785, 2340, +2571, 1835, 2406, +2592, 1893, 2492, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2563, 1769, 2078, +2563, 1769, 2078, +2563, 1770, 2079, +2563, 1771, 2080, +2563, 1772, 2080, +2563, 1773, 2082, +2564, 1775, 2084, +2564, 1777, 2086, +2564, 1780, 2089, +2564, 1784, 2093, +2565, 1789, 2098, +2565, 1796, 2105, +2566, 1789, 2110, +2564, 1776, 2116, +2563, 1758, 2124, +2559, 1753, 2143, +2558, 1773, 2177, +2563, 1787, 2220, +2563, 1779, 2275, +2566, 1840, 2337, +2576, 1860, 2406, +2591, 1925, 2491, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2566, 1822, 2077, +2566, 1822, 2078, +2566, 1822, 2078, +2566, 1822, 2078, +2566, 1822, 2079, +2566, 1822, 2079, +2566, 1822, 2080, +2566, 1822, 2081, +2566, 1822, 2083, +2566, 1822, 2085, +2567, 1824, 2089, +2568, 1831, 2096, +2568, 1839, 2106, +2570, 1844, 2121, +2568, 1834, 2131, +2568, 1813, 2145, +2564, 1813, 2176, +2565, 1838, 2221, +2568, 1838, 2272, +2573, 1888, 2337, +2580, 1896, 2406, +2599, 1967, 2492, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2573, 1894, 2080, +2573, 1894, 2081, +2573, 1895, 2081, +2573, 1896, 2081, +2573, 1897, 2082, +2574, 1898, 2082, +2574, 1900, 2083, +2575, 1903, 2084, +2575, 1906, 2086, +2575, 1906, 2088, +2575, 1906, 2090, +2575, 1906, 2094, +2575, 1906, 2099, +2575, 1907, 2109, +2576, 1913, 2129, +2577, 1915, 2152, +2578, 1893, 2171, +2576, 1899, 2221, +2578, 1919, 2273, +2580, 1949, 2338, +2587, 1961, 2408, +2611, 2008, 2495, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2588, 1996, 2083, +2588, 1997, 2083, +2588, 1997, 2084, +2588, 1997, 2085, +2588, 1997, 2086, +2588, 1998, 2087, +2588, 1998, 2088, +2588, 1999, 2091, +2588, 2000, 2093, +2588, 2001, 2098, +2588, 2005, 2100, +2589, 2012, 2104, +2591, 2018, 2108, +2588, 2010, 2114, +2588, 2009, 2126, +2589, 2014, 2149, +2590, 2016, 2184, +2591, 2003, 2214, +2591, 2019, 2275, +2595, 2044, 2342, +2604, 2072, 2411, +2625, 2108, 2494, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2625, 2149, 2111, +2624, 2149, 2111, +2624, 2149, 2111, +2624, 2149, 2111, +2624, 2148, 2111, +2624, 2148, 2111, +2623, 2147, 2111, +2623, 2146, 2111, +2622, 2145, 2111, +2621, 2143, 2111, +2620, 2141, 2111, +2618, 2137, 2111, +2617, 2136, 2114, +2617, 2144, 2126, +2617, 2155, 2141, +2619, 2157, 2164, +2623, 2160, 2195, +2624, 2165, 2231, +2619, 2165, 2275, +2633, 2187, 2352, +2638, 2190, 2417, +2660, 2223, 2503, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2670, 2315, 2112, +2671, 2315, 2112, +2671, 2315, 2112, +2671, 2315, 2111, +2671, 2316, 2111, +2672, 2316, 2111, +2672, 2316, 2111, +2673, 2317, 2110, +2674, 2318, 2109, +2675, 2319, 2108, +2677, 2321, 2107, +2680, 2323, 2105, +2682, 2325, 2106, +2681, 2325, 2118, +2680, 2325, 2133, +2678, 2328, 2149, +2677, 2328, 2176, +2677, 2325, 2215, +2687, 2335, 2275, +2689, 2335, 2316, +2695, 2346, 2391, +2724, 2369, 2462, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2775, 2531, 1744, +2775, 2531, 1745, +2775, 2531, 1747, +2775, 2531, 1750, +2776, 2532, 1753, +2776, 2532, 1758, +2776, 2533, 1764, +2776, 2533, 1772, +2777, 2534, 1782, +2778, 2535, 1796, +2778, 2536, 1813, +2778, 2537, 1825, +2777, 2535, 1833, +2776, 2530, 1839, +2776, 2528, 1859, +2778, 2535, 1929, +2779, 2534, 1991, +2780, 2535, 2071, +2782, 2538, 2158, +2784, 2536, 2248, +2791, 2552, 2360, +2803, 2569, 2485, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2826, 2762, 2506, +2826, 2762, 2506, +2826, 2762, 2505, +2826, 2762, 2505, +2826, 2762, 2505, +2826, 2762, 2505, +2826, 2761, 2505, +2826, 2761, 2505, +2826, 2761, 2505, +2826, 2761, 2506, +2826, 2761, 2507, +2826, 2761, 2509, +2826, 2761, 2510, +2826, 2760, 2508, +2826, 2760, 2508, +2826, 2762, 2520, +2826, 2764, 2535, +2826, 2763, 2548, +2826, 2763, 2571, +2826, 2767, 2613, +2826, 2769, 2662, +2826, 2779, 2732, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2554, 1623, 2059, +2554, 1623, 2059, +2554, 1623, 2060, +2554, 1623, 2060, +2554, 1623, 2061, +2554, 1623, 2063, +2554, 1623, 2065, +2554, 1623, 2067, +2554, 1623, 2070, +2554, 1623, 2074, +2554, 1623, 2080, +2554, 1623, 2087, +2554, 1621, 2096, +2554, 1621, 2102, +2554, 1621, 2110, +2555, 1588, 2133, +2556, 1555, 2169, +2555, 1608, 2217, +2557, 1691, 2269, +2563, 1692, 2342, +2564, 1761, 2409, +2587, 1838, 2491, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1625, 2059, +2554, 1624, 2059, +2554, 1624, 2060, +2554, 1624, 2060, +2554, 1624, 2061, +2554, 1624, 2063, +2554, 1624, 2064, +2554, 1624, 2067, +2554, 1624, 2070, +2554, 1624, 2074, +2554, 1624, 2080, +2554, 1624, 2087, +2554, 1621, 2096, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1590, 2134, +2556, 1556, 2169, +2555, 1609, 2217, +2557, 1691, 2269, +2563, 1692, 2342, +2564, 1762, 2409, +2587, 1839, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1627, 2059, +2554, 1626, 2059, +2554, 1625, 2060, +2554, 1625, 2060, +2554, 1625, 2061, +2554, 1625, 2063, +2554, 1625, 2064, +2554, 1625, 2067, +2554, 1625, 2070, +2554, 1625, 2074, +2554, 1625, 2079, +2554, 1625, 2086, +2554, 1622, 2096, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1592, 2134, +2556, 1559, 2169, +2555, 1610, 2217, +2557, 1691, 2269, +2564, 1693, 2342, +2564, 1764, 2409, +2587, 1840, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1630, 2060, +2554, 1629, 2060, +2554, 1627, 2060, +2554, 1625, 2060, +2554, 1625, 2061, +2554, 1625, 2062, +2554, 1625, 2064, +2554, 1625, 2066, +2554, 1625, 2070, +2554, 1625, 2074, +2554, 1625, 2079, +2554, 1625, 2086, +2554, 1623, 2095, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1595, 2134, +2556, 1562, 2169, +2555, 1611, 2217, +2557, 1691, 2270, +2564, 1694, 2342, +2564, 1765, 2409, +2587, 1842, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1633, 2060, +2554, 1632, 2060, +2554, 1631, 2060, +2554, 1629, 2060, +2554, 1626, 2061, +2554, 1626, 2062, +2554, 1626, 2064, +2554, 1626, 2066, +2554, 1626, 2069, +2554, 1626, 2073, +2554, 1626, 2079, +2554, 1626, 2086, +2554, 1625, 2095, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1599, 2135, +2556, 1567, 2169, +2555, 1613, 2217, +2557, 1692, 2270, +2564, 1695, 2342, +2565, 1768, 2409, +2587, 1844, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1638, 2061, +2554, 1638, 2061, +2554, 1636, 2061, +2554, 1634, 2061, +2554, 1631, 2061, +2554, 1628, 2062, +2554, 1628, 2063, +2554, 1628, 2066, +2554, 1628, 2069, +2554, 1628, 2073, +2554, 1628, 2079, +2554, 1628, 2086, +2554, 1626, 2095, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1605, 2135, +2556, 1572, 2169, +2555, 1616, 2217, +2557, 1693, 2270, +2564, 1696, 2342, +2565, 1771, 2409, +2587, 1847, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2555, 1645, 2062, +2555, 1644, 2062, +2555, 1643, 2062, +2555, 1641, 2062, +2555, 1638, 2062, +2555, 1635, 2063, +2555, 1631, 2063, +2555, 1631, 2066, +2555, 1631, 2069, +2555, 1631, 2073, +2555, 1631, 2078, +2555, 1631, 2085, +2555, 1628, 2094, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1612, 2136, +2556, 1580, 2169, +2554, 1619, 2217, +2558, 1694, 2270, +2564, 1698, 2342, +2565, 1775, 2409, +2587, 1852, 2492, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2555, 1654, 2063, +2555, 1653, 2063, +2555, 1651, 2063, +2555, 1650, 2063, +2555, 1647, 2063, +2555, 1644, 2064, +2555, 1640, 2064, +2555, 1633, 2065, +2555, 1633, 2068, +2555, 1633, 2072, +2555, 1633, 2078, +2555, 1633, 2085, +2555, 1631, 2094, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1621, 2137, +2557, 1590, 2169, +2554, 1624, 2217, +2558, 1695, 2270, +2564, 1701, 2342, +2565, 1781, 2409, +2588, 1857, 2493, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2556, 1665, 2064, +2556, 1664, 2065, +2556, 1663, 2065, +2556, 1661, 2065, +2556, 1659, 2065, +2556, 1655, 2066, +2556, 1651, 2066, +2556, 1646, 2066, +2556, 1638, 2067, +2556, 1638, 2071, +2556, 1638, 2077, +2556, 1638, 2084, +2556, 1636, 2093, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1633, 2138, +2557, 1603, 2169, +2554, 1630, 2217, +2558, 1697, 2271, +2564, 1704, 2342, +2565, 1788, 2409, +2588, 1860, 2493, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2556, 1680, 2066, +2556, 1679, 2067, +2556, 1678, 2067, +2556, 1676, 2067, +2556, 1674, 2067, +2556, 1671, 2068, +2556, 1667, 2068, +2556, 1661, 2069, +2556, 1653, 2069, +2556, 1643, 2070, +2556, 1643, 2076, +2556, 1643, 2083, +2556, 1641, 2092, +2554, 1624, 2101, +2554, 1621, 2110, +2557, 1649, 2140, +2557, 1620, 2170, +2554, 1638, 2217, +2558, 1699, 2271, +2565, 1709, 2342, +2566, 1798, 2409, +2589, 1863, 2493, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2558, 1699, 2069, +2558, 1698, 2069, +2558, 1697, 2070, +2558, 1695, 2070, +2558, 1693, 2070, +2558, 1690, 2070, +2558, 1686, 2071, +2558, 1681, 2071, +2558, 1674, 2072, +2558, 1663, 2073, +2558, 1650, 2074, +2558, 1650, 2082, +2557, 1648, 2091, +2555, 1631, 2100, +2554, 1621, 2110, +2557, 1657, 2141, +2558, 1642, 2173, +2554, 1658, 2217, +2559, 1702, 2273, +2565, 1715, 2342, +2566, 1810, 2409, +2589, 1868, 2493, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2559, 1723, 2073, +2559, 1723, 2073, +2559, 1722, 2073, +2559, 1720, 2073, +2559, 1718, 2074, +2559, 1715, 2074, +2559, 1711, 2074, +2559, 1706, 2075, +2559, 1699, 2076, +2559, 1690, 2077, +2559, 1677, 2078, +2559, 1659, 2080, +2558, 1657, 2089, +2556, 1641, 2098, +2554, 1621, 2110, +2557, 1657, 2141, +2558, 1669, 2176, +2555, 1684, 2217, +2560, 1706, 2274, +2566, 1723, 2342, +2567, 1816, 2409, +2591, 1873, 2493, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2560, 1754, 2078, +2560, 1754, 2078, +2560, 1753, 2078, +2560, 1752, 2079, +2560, 1750, 2079, +2560, 1747, 2079, +2560, 1744, 2080, +2560, 1739, 2080, +2560, 1732, 2081, +2560, 1724, 2082, +2560, 1712, 2083, +2560, 1695, 2085, +2560, 1674, 2088, +2558, 1658, 2097, +2555, 1635, 2110, +2557, 1661, 2141, +2559, 1703, 2179, +2556, 1716, 2217, +2560, 1716, 2275, +2566, 1739, 2342, +2568, 1818, 2408, +2592, 1880, 2493, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2562, 1761, 2078, +2562, 1761, 2078, +2562, 1761, 2079, +2562, 1762, 2080, +2562, 1763, 2080, +2562, 1765, 2082, +2562, 1766, 2084, +2562, 1769, 2086, +2562, 1772, 2089, +2563, 1771, 2091, +2563, 1760, 2093, +2563, 1745, 2094, +2562, 1727, 2097, +2561, 1712, 2103, +2558, 1692, 2116, +2556, 1693, 2138, +2560, 1738, 2181, +2560, 1744, 2217, +2561, 1744, 2275, +2566, 1785, 2340, +2571, 1835, 2406, +2592, 1893, 2492, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2563, 1769, 2078, +2563, 1769, 2078, +2563, 1770, 2079, +2563, 1771, 2080, +2563, 1772, 2080, +2563, 1773, 2082, +2564, 1775, 2084, +2564, 1777, 2086, +2564, 1780, 2089, +2564, 1784, 2093, +2565, 1789, 2098, +2565, 1796, 2105, +2566, 1789, 2110, +2564, 1776, 2116, +2563, 1758, 2124, +2559, 1753, 2143, +2558, 1773, 2177, +2563, 1787, 2220, +2563, 1779, 2275, +2566, 1840, 2337, +2576, 1860, 2406, +2591, 1925, 2491, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2566, 1822, 2077, +2566, 1822, 2078, +2566, 1822, 2078, +2566, 1822, 2078, +2566, 1822, 2079, +2566, 1822, 2079, +2566, 1822, 2080, +2566, 1822, 2081, +2566, 1822, 2083, +2566, 1822, 2085, +2567, 1824, 2089, +2568, 1831, 2096, +2568, 1839, 2106, +2570, 1844, 2121, +2568, 1834, 2131, +2568, 1813, 2145, +2564, 1813, 2176, +2565, 1838, 2221, +2568, 1838, 2272, +2573, 1888, 2337, +2580, 1896, 2406, +2599, 1967, 2492, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2573, 1894, 2080, +2573, 1894, 2081, +2573, 1895, 2081, +2573, 1896, 2081, +2573, 1897, 2082, +2574, 1898, 2082, +2574, 1900, 2083, +2575, 1903, 2084, +2575, 1906, 2086, +2575, 1906, 2088, +2575, 1906, 2090, +2575, 1906, 2094, +2575, 1906, 2099, +2575, 1907, 2109, +2576, 1913, 2129, +2577, 1915, 2152, +2578, 1893, 2171, +2576, 1899, 2221, +2578, 1919, 2273, +2580, 1949, 2338, +2587, 1961, 2408, +2611, 2008, 2495, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2588, 1996, 2083, +2588, 1997, 2083, +2588, 1997, 2084, +2588, 1997, 2085, +2588, 1997, 2086, +2588, 1998, 2087, +2588, 1998, 2088, +2588, 1999, 2091, +2588, 2000, 2093, +2588, 2001, 2098, +2588, 2005, 2100, +2589, 2012, 2104, +2591, 2018, 2108, +2588, 2010, 2114, +2588, 2009, 2126, +2589, 2014, 2149, +2590, 2016, 2184, +2591, 2003, 2214, +2591, 2019, 2275, +2595, 2044, 2342, +2604, 2072, 2411, +2625, 2108, 2494, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2625, 2149, 2111, +2624, 2149, 2111, +2624, 2149, 2111, +2624, 2149, 2111, +2624, 2148, 2111, +2624, 2148, 2111, +2623, 2147, 2111, +2623, 2146, 2111, +2622, 2145, 2111, +2621, 2143, 2111, +2620, 2141, 2111, +2618, 2137, 2111, +2617, 2136, 2114, +2617, 2144, 2126, +2617, 2155, 2141, +2619, 2157, 2164, +2623, 2160, 2195, +2624, 2165, 2231, +2619, 2165, 2275, +2633, 2187, 2352, +2638, 2190, 2417, +2660, 2223, 2503, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2670, 2315, 2112, +2671, 2315, 2112, +2671, 2315, 2112, +2671, 2315, 2111, +2671, 2316, 2111, +2672, 2316, 2111, +2672, 2316, 2111, +2673, 2317, 2110, +2674, 2318, 2109, +2675, 2319, 2108, +2677, 2321, 2107, +2680, 2323, 2105, +2682, 2325, 2106, +2681, 2325, 2118, +2680, 2325, 2133, +2678, 2328, 2149, +2677, 2328, 2176, +2677, 2325, 2215, +2687, 2335, 2275, +2689, 2335, 2316, +2695, 2346, 2391, +2724, 2369, 2462, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2775, 2531, 1744, +2775, 2531, 1745, +2775, 2531, 1747, +2775, 2531, 1750, +2776, 2532, 1753, +2776, 2532, 1758, +2776, 2533, 1764, +2776, 2533, 1772, +2777, 2534, 1782, +2778, 2535, 1796, +2778, 2536, 1813, +2778, 2537, 1825, +2777, 2535, 1833, +2776, 2530, 1839, +2776, 2528, 1859, +2778, 2535, 1929, +2779, 2534, 1991, +2780, 2535, 2071, +2782, 2538, 2158, +2784, 2536, 2248, +2791, 2552, 2360, +2803, 2569, 2485, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2826, 2762, 2506, +2826, 2762, 2506, +2826, 2762, 2505, +2826, 2762, 2505, +2826, 2762, 2505, +2826, 2762, 2505, +2826, 2761, 2505, +2826, 2761, 2505, +2826, 2761, 2505, +2826, 2761, 2506, +2826, 2761, 2507, +2826, 2761, 2509, +2826, 2761, 2510, +2826, 2760, 2508, +2826, 2760, 2508, +2826, 2762, 2520, +2826, 2764, 2535, +2826, 2763, 2548, +2826, 2763, 2571, +2826, 2767, 2613, +2826, 2769, 2662, +2826, 2779, 2732, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2554, 1623, 2059, +2554, 1623, 2059, +2554, 1623, 2060, +2554, 1623, 2060, +2554, 1623, 2061, +2554, 1623, 2063, +2554, 1623, 2065, +2554, 1623, 2067, +2554, 1623, 2070, +2554, 1623, 2074, +2554, 1623, 2080, +2554, 1623, 2087, +2554, 1621, 2096, +2554, 1621, 2102, +2554, 1621, 2110, +2555, 1588, 2133, +2556, 1555, 2169, +2555, 1608, 2217, +2557, 1691, 2269, +2563, 1692, 2342, +2564, 1761, 2409, +2587, 1838, 2491, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1625, 2059, +2554, 1624, 2059, +2554, 1624, 2060, +2554, 1624, 2060, +2554, 1624, 2061, +2554, 1624, 2063, +2554, 1624, 2064, +2554, 1624, 2067, +2554, 1624, 2070, +2554, 1624, 2074, +2554, 1624, 2080, +2554, 1624, 2087, +2554, 1621, 2096, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1590, 2134, +2556, 1556, 2169, +2555, 1609, 2217, +2557, 1691, 2269, +2563, 1692, 2342, +2564, 1762, 2409, +2587, 1839, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1627, 2059, +2554, 1626, 2059, +2554, 1625, 2060, +2554, 1625, 2060, +2554, 1625, 2061, +2554, 1625, 2063, +2554, 1625, 2064, +2554, 1625, 2067, +2554, 1625, 2070, +2554, 1625, 2074, +2554, 1625, 2079, +2554, 1625, 2086, +2554, 1622, 2096, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1592, 2134, +2556, 1559, 2169, +2555, 1610, 2217, +2557, 1691, 2269, +2564, 1693, 2342, +2564, 1764, 2409, +2587, 1840, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1630, 2060, +2554, 1629, 2060, +2554, 1627, 2060, +2554, 1625, 2060, +2554, 1625, 2061, +2554, 1625, 2062, +2554, 1625, 2064, +2554, 1625, 2066, +2554, 1625, 2070, +2554, 1625, 2074, +2554, 1625, 2079, +2554, 1625, 2086, +2554, 1623, 2095, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1595, 2134, +2556, 1562, 2169, +2555, 1611, 2217, +2557, 1691, 2270, +2564, 1694, 2342, +2564, 1765, 2409, +2587, 1842, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1633, 2060, +2554, 1632, 2060, +2554, 1631, 2060, +2554, 1629, 2060, +2554, 1626, 2061, +2554, 1626, 2062, +2554, 1626, 2064, +2554, 1626, 2066, +2554, 1626, 2069, +2554, 1626, 2073, +2554, 1626, 2079, +2554, 1626, 2086, +2554, 1625, 2095, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1599, 2135, +2556, 1567, 2169, +2555, 1613, 2217, +2557, 1692, 2270, +2564, 1695, 2342, +2565, 1768, 2409, +2587, 1844, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1638, 2061, +2554, 1638, 2061, +2554, 1636, 2061, +2554, 1634, 2061, +2554, 1631, 2061, +2554, 1628, 2062, +2554, 1628, 2063, +2554, 1628, 2066, +2554, 1628, 2069, +2554, 1628, 2073, +2554, 1628, 2079, +2554, 1628, 2086, +2554, 1626, 2095, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1605, 2135, +2556, 1572, 2169, +2555, 1616, 2217, +2557, 1693, 2270, +2564, 1696, 2342, +2565, 1771, 2409, +2587, 1847, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2555, 1645, 2062, +2555, 1644, 2062, +2555, 1643, 2062, +2555, 1641, 2062, +2555, 1638, 2062, +2555, 1635, 2063, +2555, 1631, 2063, +2555, 1631, 2066, +2555, 1631, 2069, +2555, 1631, 2073, +2555, 1631, 2078, +2555, 1631, 2085, +2555, 1628, 2094, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1612, 2136, +2556, 1580, 2169, +2554, 1619, 2217, +2558, 1694, 2270, +2564, 1698, 2342, +2565, 1775, 2409, +2587, 1852, 2492, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2555, 1654, 2063, +2555, 1653, 2063, +2555, 1651, 2063, +2555, 1650, 2063, +2555, 1647, 2063, +2555, 1644, 2064, +2555, 1640, 2064, +2555, 1633, 2065, +2555, 1633, 2068, +2555, 1633, 2072, +2555, 1633, 2078, +2555, 1633, 2085, +2555, 1631, 2094, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1621, 2137, +2557, 1590, 2169, +2554, 1624, 2217, +2558, 1695, 2270, +2564, 1701, 2342, +2565, 1781, 2409, +2588, 1857, 2493, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2556, 1665, 2064, +2556, 1664, 2065, +2556, 1663, 2065, +2556, 1661, 2065, +2556, 1659, 2065, +2556, 1655, 2066, +2556, 1651, 2066, +2556, 1646, 2066, +2556, 1638, 2067, +2556, 1638, 2071, +2556, 1638, 2077, +2556, 1638, 2084, +2556, 1636, 2093, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1633, 2138, +2557, 1603, 2169, +2554, 1630, 2217, +2558, 1697, 2271, +2564, 1704, 2342, +2565, 1788, 2409, +2588, 1860, 2493, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2556, 1680, 2066, +2556, 1679, 2067, +2556, 1678, 2067, +2556, 1676, 2067, +2556, 1674, 2067, +2556, 1671, 2068, +2556, 1667, 2068, +2556, 1661, 2069, +2556, 1653, 2069, +2556, 1643, 2070, +2556, 1643, 2076, +2556, 1643, 2083, +2556, 1641, 2092, +2554, 1624, 2101, +2554, 1621, 2110, +2557, 1649, 2140, +2557, 1620, 2170, +2554, 1638, 2217, +2558, 1699, 2271, +2565, 1709, 2342, +2566, 1798, 2409, +2589, 1863, 2493, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2558, 1699, 2069, +2558, 1698, 2069, +2558, 1697, 2070, +2558, 1695, 2070, +2558, 1693, 2070, +2558, 1690, 2070, +2558, 1686, 2071, +2558, 1681, 2071, +2558, 1674, 2072, +2558, 1663, 2073, +2558, 1650, 2074, +2558, 1650, 2082, +2557, 1648, 2091, +2555, 1631, 2100, +2554, 1621, 2110, +2557, 1657, 2141, +2558, 1642, 2173, +2554, 1658, 2217, +2559, 1702, 2273, +2565, 1715, 2342, +2566, 1810, 2409, +2589, 1868, 2493, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2559, 1723, 2073, +2559, 1723, 2073, +2559, 1722, 2073, +2559, 1720, 2073, +2559, 1718, 2074, +2559, 1715, 2074, +2559, 1711, 2074, +2559, 1706, 2075, +2559, 1699, 2076, +2559, 1690, 2077, +2559, 1677, 2078, +2559, 1659, 2080, +2558, 1657, 2089, +2556, 1641, 2098, +2554, 1621, 2110, +2557, 1657, 2141, +2558, 1669, 2176, +2555, 1684, 2217, +2560, 1706, 2274, +2566, 1723, 2342, +2567, 1816, 2409, +2591, 1873, 2493, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2560, 1754, 2078, +2560, 1754, 2078, +2560, 1753, 2078, +2560, 1752, 2079, +2560, 1750, 2079, +2560, 1747, 2079, +2560, 1744, 2080, +2560, 1739, 2080, +2560, 1732, 2081, +2560, 1724, 2082, +2560, 1712, 2083, +2560, 1695, 2085, +2560, 1674, 2088, +2558, 1658, 2097, +2555, 1635, 2110, +2557, 1661, 2141, +2559, 1703, 2179, +2556, 1716, 2217, +2560, 1716, 2275, +2566, 1739, 2342, +2568, 1818, 2408, +2592, 1880, 2493, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2562, 1761, 2078, +2562, 1761, 2078, +2562, 1761, 2079, +2562, 1762, 2080, +2562, 1763, 2080, +2562, 1765, 2082, +2562, 1766, 2084, +2562, 1769, 2086, +2562, 1772, 2089, +2563, 1771, 2091, +2563, 1760, 2093, +2563, 1745, 2094, +2562, 1727, 2097, +2561, 1712, 2103, +2558, 1692, 2116, +2556, 1693, 2138, +2560, 1738, 2181, +2560, 1744, 2217, +2561, 1744, 2275, +2566, 1785, 2340, +2571, 1835, 2406, +2592, 1893, 2492, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2563, 1769, 2078, +2563, 1769, 2078, +2563, 1770, 2079, +2563, 1771, 2080, +2563, 1772, 2080, +2563, 1773, 2082, +2564, 1775, 2084, +2564, 1777, 2086, +2564, 1780, 2089, +2564, 1784, 2093, +2565, 1789, 2098, +2565, 1796, 2105, +2566, 1789, 2110, +2564, 1776, 2116, +2563, 1758, 2124, +2559, 1753, 2143, +2558, 1773, 2177, +2563, 1787, 2220, +2563, 1779, 2275, +2566, 1840, 2337, +2576, 1860, 2406, +2591, 1925, 2491, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2566, 1822, 2077, +2566, 1822, 2078, +2566, 1822, 2078, +2566, 1822, 2078, +2566, 1822, 2079, +2566, 1822, 2079, +2566, 1822, 2080, +2566, 1822, 2081, +2566, 1822, 2083, +2566, 1822, 2085, +2567, 1824, 2089, +2568, 1831, 2096, +2568, 1839, 2106, +2570, 1844, 2121, +2568, 1834, 2131, +2568, 1813, 2145, +2564, 1813, 2176, +2565, 1838, 2221, +2568, 1838, 2272, +2573, 1888, 2337, +2580, 1896, 2406, +2599, 1967, 2492, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2573, 1894, 2080, +2573, 1894, 2081, +2573, 1895, 2081, +2573, 1896, 2081, +2573, 1897, 2082, +2574, 1898, 2082, +2574, 1900, 2083, +2575, 1903, 2084, +2575, 1906, 2086, +2575, 1906, 2088, +2575, 1906, 2090, +2575, 1906, 2094, +2575, 1906, 2099, +2575, 1907, 2109, +2576, 1913, 2129, +2577, 1915, 2152, +2578, 1893, 2171, +2576, 1899, 2221, +2578, 1919, 2273, +2580, 1949, 2338, +2587, 1961, 2408, +2611, 2008, 2495, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2588, 1996, 2083, +2588, 1997, 2083, +2588, 1997, 2084, +2588, 1997, 2085, +2588, 1997, 2086, +2588, 1998, 2087, +2588, 1998, 2088, +2588, 1999, 2091, +2588, 2000, 2093, +2588, 2001, 2098, +2588, 2005, 2100, +2589, 2012, 2104, +2591, 2018, 2108, +2588, 2010, 2114, +2588, 2009, 2126, +2589, 2014, 2149, +2590, 2016, 2184, +2591, 2003, 2214, +2591, 2019, 2275, +2595, 2044, 2342, +2604, 2072, 2411, +2625, 2108, 2494, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2625, 2149, 2111, +2624, 2149, 2111, +2624, 2149, 2111, +2624, 2149, 2111, +2624, 2148, 2111, +2624, 2148, 2111, +2623, 2147, 2111, +2623, 2146, 2111, +2622, 2145, 2111, +2621, 2143, 2111, +2620, 2141, 2111, +2618, 2137, 2111, +2617, 2136, 2114, +2617, 2144, 2126, +2617, 2155, 2141, +2619, 2157, 2164, +2623, 2160, 2195, +2624, 2165, 2231, +2619, 2165, 2275, +2633, 2187, 2352, +2638, 2190, 2417, +2660, 2223, 2503, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2670, 2315, 2112, +2671, 2315, 2112, +2671, 2315, 2112, +2671, 2315, 2111, +2671, 2316, 2111, +2672, 2316, 2111, +2672, 2316, 2111, +2673, 2317, 2110, +2674, 2318, 2109, +2675, 2319, 2108, +2677, 2321, 2107, +2680, 2323, 2105, +2682, 2325, 2106, +2681, 2325, 2118, +2680, 2325, 2133, +2678, 2328, 2149, +2677, 2328, 2176, +2677, 2325, 2215, +2687, 2335, 2275, +2689, 2335, 2316, +2695, 2346, 2391, +2724, 2369, 2462, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2775, 2531, 1744, +2775, 2531, 1745, +2775, 2531, 1747, +2775, 2531, 1750, +2776, 2532, 1753, +2776, 2532, 1758, +2776, 2533, 1764, +2776, 2533, 1772, +2777, 2534, 1782, +2778, 2535, 1796, +2778, 2536, 1813, +2778, 2537, 1825, +2777, 2535, 1833, +2776, 2530, 1839, +2776, 2528, 1859, +2778, 2535, 1929, +2779, 2534, 1991, +2780, 2535, 2071, +2782, 2538, 2158, +2784, 2536, 2248, +2791, 2552, 2360, +2803, 2569, 2485, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2826, 2762, 2506, +2826, 2762, 2506, +2826, 2762, 2505, +2826, 2762, 2505, +2826, 2762, 2505, +2826, 2762, 2505, +2826, 2761, 2505, +2826, 2761, 2505, +2826, 2761, 2505, +2826, 2761, 2506, +2826, 2761, 2507, +2826, 2761, 2509, +2826, 2761, 2510, +2826, 2760, 2508, +2826, 2760, 2508, +2826, 2762, 2520, +2826, 2764, 2535, +2826, 2763, 2548, +2826, 2763, 2571, +2826, 2767, 2613, +2826, 2769, 2662, +2826, 2779, 2732, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2554, 1623, 2059, +2554, 1623, 2059, +2554, 1623, 2060, +2554, 1623, 2060, +2554, 1623, 2061, +2554, 1623, 2063, +2554, 1623, 2065, +2554, 1623, 2067, +2554, 1623, 2070, +2554, 1623, 2074, +2554, 1623, 2080, +2554, 1623, 2087, +2554, 1621, 2096, +2554, 1621, 2102, +2554, 1621, 2110, +2555, 1588, 2133, +2556, 1555, 2169, +2555, 1608, 2217, +2557, 1691, 2269, +2563, 1692, 2342, +2564, 1761, 2409, +2587, 1838, 2491, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1625, 2059, +2554, 1624, 2059, +2554, 1624, 2060, +2554, 1624, 2060, +2554, 1624, 2061, +2554, 1624, 2063, +2554, 1624, 2064, +2554, 1624, 2067, +2554, 1624, 2070, +2554, 1624, 2074, +2554, 1624, 2080, +2554, 1624, 2087, +2554, 1621, 2096, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1590, 2134, +2556, 1556, 2169, +2555, 1609, 2217, +2557, 1691, 2269, +2563, 1692, 2342, +2564, 1762, 2409, +2587, 1839, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1627, 2059, +2554, 1626, 2059, +2554, 1625, 2060, +2554, 1625, 2060, +2554, 1625, 2061, +2554, 1625, 2063, +2554, 1625, 2064, +2554, 1625, 2067, +2554, 1625, 2070, +2554, 1625, 2074, +2554, 1625, 2079, +2554, 1625, 2086, +2554, 1622, 2096, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1592, 2134, +2556, 1559, 2169, +2555, 1610, 2217, +2557, 1691, 2269, +2564, 1693, 2342, +2564, 1764, 2409, +2587, 1840, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1630, 2060, +2554, 1629, 2060, +2554, 1627, 2060, +2554, 1625, 2060, +2554, 1625, 2061, +2554, 1625, 2062, +2554, 1625, 2064, +2554, 1625, 2066, +2554, 1625, 2070, +2554, 1625, 2074, +2554, 1625, 2079, +2554, 1625, 2086, +2554, 1623, 2095, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1595, 2134, +2556, 1562, 2169, +2555, 1611, 2217, +2557, 1691, 2270, +2564, 1694, 2342, +2564, 1765, 2409, +2587, 1842, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1633, 2060, +2554, 1632, 2060, +2554, 1631, 2060, +2554, 1629, 2060, +2554, 1626, 2061, +2554, 1626, 2062, +2554, 1626, 2064, +2554, 1626, 2066, +2554, 1626, 2069, +2554, 1626, 2073, +2554, 1626, 2079, +2554, 1626, 2086, +2554, 1625, 2095, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1599, 2135, +2556, 1567, 2169, +2555, 1613, 2217, +2557, 1692, 2270, +2564, 1695, 2342, +2565, 1768, 2409, +2587, 1844, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1638, 2061, +2554, 1638, 2061, +2554, 1636, 2061, +2554, 1634, 2061, +2554, 1631, 2061, +2554, 1628, 2062, +2554, 1628, 2063, +2554, 1628, 2066, +2554, 1628, 2069, +2554, 1628, 2073, +2554, 1628, 2079, +2554, 1628, 2086, +2554, 1626, 2095, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1605, 2135, +2556, 1572, 2169, +2555, 1616, 2217, +2557, 1693, 2270, +2564, 1696, 2342, +2565, 1771, 2409, +2587, 1847, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2555, 1645, 2062, +2555, 1644, 2062, +2555, 1643, 2062, +2555, 1641, 2062, +2555, 1638, 2062, +2555, 1635, 2063, +2555, 1631, 2063, +2555, 1631, 2066, +2555, 1631, 2069, +2555, 1631, 2073, +2555, 1631, 2078, +2555, 1631, 2085, +2555, 1628, 2094, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1612, 2136, +2556, 1580, 2169, +2554, 1619, 2217, +2558, 1694, 2270, +2564, 1698, 2342, +2565, 1775, 2409, +2587, 1852, 2492, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2555, 1654, 2063, +2555, 1653, 2063, +2555, 1651, 2063, +2555, 1650, 2063, +2555, 1647, 2063, +2555, 1644, 2064, +2555, 1640, 2064, +2555, 1633, 2065, +2555, 1633, 2068, +2555, 1633, 2072, +2555, 1633, 2078, +2555, 1633, 2085, +2555, 1631, 2094, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1621, 2137, +2557, 1590, 2169, +2554, 1624, 2217, +2558, 1695, 2270, +2564, 1701, 2342, +2565, 1781, 2409, +2588, 1857, 2493, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2556, 1665, 2064, +2556, 1664, 2065, +2556, 1663, 2065, +2556, 1661, 2065, +2556, 1659, 2065, +2556, 1655, 2066, +2556, 1651, 2066, +2556, 1646, 2066, +2556, 1638, 2067, +2556, 1638, 2071, +2556, 1638, 2077, +2556, 1638, 2084, +2556, 1636, 2093, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1633, 2138, +2557, 1603, 2169, +2554, 1630, 2217, +2558, 1697, 2271, +2564, 1704, 2342, +2565, 1788, 2409, +2588, 1860, 2493, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2556, 1680, 2066, +2556, 1679, 2067, +2556, 1678, 2067, +2556, 1676, 2067, +2556, 1674, 2067, +2556, 1671, 2068, +2556, 1667, 2068, +2556, 1661, 2069, +2556, 1653, 2069, +2556, 1643, 2070, +2556, 1643, 2076, +2556, 1643, 2083, +2556, 1641, 2092, +2554, 1624, 2101, +2554, 1621, 2110, +2557, 1649, 2140, +2557, 1620, 2170, +2554, 1638, 2217, +2558, 1699, 2271, +2565, 1709, 2342, +2566, 1798, 2409, +2589, 1863, 2493, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2558, 1699, 2069, +2558, 1698, 2069, +2558, 1697, 2070, +2558, 1695, 2070, +2558, 1693, 2070, +2558, 1690, 2070, +2558, 1686, 2071, +2558, 1681, 2071, +2558, 1674, 2072, +2558, 1663, 2073, +2558, 1650, 2074, +2558, 1650, 2082, +2557, 1648, 2091, +2555, 1631, 2100, +2554, 1621, 2110, +2557, 1657, 2141, +2558, 1642, 2173, +2554, 1658, 2217, +2559, 1702, 2273, +2565, 1715, 2342, +2566, 1810, 2409, +2589, 1868, 2493, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2559, 1723, 2073, +2559, 1723, 2073, +2559, 1722, 2073, +2559, 1720, 2073, +2559, 1718, 2074, +2559, 1715, 2074, +2559, 1711, 2074, +2559, 1706, 2075, +2559, 1699, 2076, +2559, 1690, 2077, +2559, 1677, 2078, +2559, 1659, 2080, +2558, 1657, 2089, +2556, 1641, 2098, +2554, 1621, 2110, +2557, 1657, 2141, +2558, 1669, 2176, +2555, 1684, 2217, +2560, 1706, 2274, +2566, 1723, 2342, +2567, 1816, 2409, +2591, 1873, 2493, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2560, 1754, 2078, +2560, 1754, 2078, +2560, 1753, 2078, +2560, 1752, 2079, +2560, 1750, 2079, +2560, 1747, 2079, +2560, 1744, 2080, +2560, 1739, 2080, +2560, 1732, 2081, +2560, 1724, 2082, +2560, 1712, 2083, +2560, 1695, 2085, +2560, 1674, 2088, +2558, 1658, 2097, +2555, 1635, 2110, +2557, 1661, 2141, +2559, 1703, 2179, +2556, 1716, 2217, +2560, 1716, 2275, +2566, 1739, 2342, +2568, 1818, 2408, +2592, 1880, 2493, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2562, 1761, 2078, +2562, 1761, 2078, +2562, 1761, 2079, +2562, 1762, 2080, +2562, 1763, 2080, +2562, 1765, 2082, +2562, 1766, 2084, +2562, 1769, 2086, +2562, 1772, 2089, +2563, 1771, 2091, +2563, 1760, 2093, +2563, 1745, 2094, +2562, 1727, 2097, +2561, 1712, 2103, +2558, 1692, 2116, +2556, 1693, 2138, +2560, 1738, 2181, +2560, 1744, 2217, +2561, 1744, 2275, +2566, 1785, 2340, +2571, 1835, 2406, +2592, 1893, 2492, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2563, 1769, 2078, +2563, 1769, 2078, +2563, 1770, 2079, +2563, 1771, 2080, +2563, 1772, 2080, +2563, 1773, 2082, +2564, 1775, 2084, +2564, 1777, 2086, +2564, 1780, 2089, +2564, 1784, 2093, +2565, 1789, 2098, +2565, 1796, 2105, +2566, 1789, 2110, +2564, 1776, 2116, +2563, 1758, 2124, +2559, 1753, 2143, +2558, 1773, 2177, +2563, 1787, 2220, +2563, 1779, 2275, +2566, 1840, 2337, +2576, 1860, 2406, +2591, 1925, 2491, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2566, 1822, 2077, +2566, 1822, 2078, +2566, 1822, 2078, +2566, 1822, 2078, +2566, 1822, 2079, +2566, 1822, 2079, +2566, 1822, 2080, +2566, 1822, 2081, +2566, 1822, 2083, +2566, 1822, 2085, +2567, 1824, 2089, +2568, 1831, 2096, +2568, 1839, 2106, +2570, 1844, 2121, +2568, 1834, 2131, +2568, 1813, 2145, +2564, 1813, 2176, +2565, 1838, 2221, +2568, 1838, 2272, +2573, 1888, 2337, +2580, 1896, 2406, +2599, 1967, 2492, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2573, 1894, 2080, +2573, 1894, 2081, +2573, 1895, 2081, +2573, 1896, 2081, +2573, 1897, 2082, +2574, 1898, 2082, +2574, 1900, 2083, +2575, 1903, 2084, +2575, 1906, 2086, +2575, 1906, 2088, +2575, 1906, 2090, +2575, 1906, 2094, +2575, 1906, 2099, +2575, 1907, 2109, +2576, 1913, 2129, +2577, 1915, 2152, +2578, 1893, 2171, +2576, 1899, 2221, +2578, 1919, 2273, +2580, 1949, 2338, +2587, 1961, 2408, +2611, 2008, 2495, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2588, 1996, 2083, +2588, 1997, 2083, +2588, 1997, 2084, +2588, 1997, 2085, +2588, 1997, 2086, +2588, 1998, 2087, +2588, 1998, 2088, +2588, 1999, 2091, +2588, 2000, 2093, +2588, 2001, 2098, +2588, 2005, 2100, +2589, 2012, 2104, +2591, 2018, 2108, +2588, 2010, 2114, +2588, 2009, 2126, +2589, 2014, 2149, +2590, 2016, 2184, +2591, 2003, 2214, +2591, 2019, 2275, +2595, 2044, 2342, +2604, 2072, 2411, +2625, 2108, 2494, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2625, 2149, 2111, +2624, 2149, 2111, +2624, 2149, 2111, +2624, 2149, 2111, +2624, 2148, 2111, +2624, 2148, 2111, +2623, 2147, 2111, +2623, 2146, 2111, +2622, 2145, 2111, +2621, 2143, 2111, +2620, 2141, 2111, +2618, 2137, 2111, +2617, 2136, 2114, +2617, 2144, 2126, +2617, 2155, 2141, +2619, 2157, 2164, +2623, 2160, 2195, +2624, 2165, 2231, +2619, 2165, 2275, +2633, 2187, 2352, +2638, 2190, 2417, +2660, 2223, 2503, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2670, 2315, 2112, +2671, 2315, 2112, +2671, 2315, 2112, +2671, 2315, 2111, +2671, 2316, 2111, +2672, 2316, 2111, +2672, 2316, 2111, +2673, 2317, 2110, +2674, 2318, 2109, +2675, 2319, 2108, +2677, 2321, 2107, +2680, 2323, 2105, +2682, 2325, 2106, +2681, 2325, 2118, +2680, 2325, 2133, +2678, 2328, 2149, +2677, 2328, 2176, +2677, 2325, 2215, +2687, 2335, 2275, +2689, 2335, 2316, +2695, 2346, 2391, +2724, 2369, 2462, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2775, 2531, 1744, +2775, 2531, 1745, +2775, 2531, 1747, +2775, 2531, 1750, +2776, 2532, 1753, +2776, 2532, 1758, +2776, 2533, 1764, +2776, 2533, 1772, +2777, 2534, 1782, +2778, 2535, 1796, +2778, 2536, 1813, +2778, 2537, 1825, +2777, 2535, 1833, +2776, 2530, 1839, +2776, 2528, 1859, +2778, 2535, 1929, +2779, 2534, 1991, +2780, 2535, 2071, +2782, 2538, 2158, +2784, 2536, 2248, +2791, 2552, 2360, +2803, 2569, 2485, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2826, 2762, 2506, +2826, 2762, 2506, +2826, 2762, 2505, +2826, 2762, 2505, +2826, 2762, 2505, +2826, 2762, 2505, +2826, 2761, 2505, +2826, 2761, 2505, +2826, 2761, 2505, +2826, 2761, 2506, +2826, 2761, 2507, +2826, 2761, 2509, +2826, 2761, 2510, +2826, 2760, 2508, +2826, 2760, 2508, +2826, 2762, 2520, +2826, 2764, 2535, +2826, 2763, 2548, +2826, 2763, 2571, +2826, 2767, 2613, +2826, 2769, 2662, +2826, 2779, 2732, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2554, 1623, 2059, +2554, 1623, 2059, +2554, 1623, 2060, +2554, 1623, 2060, +2554, 1623, 2061, +2554, 1623, 2063, +2554, 1623, 2065, +2554, 1623, 2067, +2554, 1623, 2070, +2554, 1623, 2074, +2554, 1623, 2080, +2554, 1623, 2087, +2554, 1621, 2096, +2554, 1621, 2102, +2554, 1621, 2110, +2555, 1588, 2133, +2556, 1555, 2169, +2555, 1608, 2217, +2557, 1691, 2269, +2563, 1692, 2342, +2564, 1761, 2409, +2587, 1838, 2491, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1625, 2059, +2554, 1624, 2059, +2554, 1624, 2060, +2554, 1624, 2060, +2554, 1624, 2061, +2554, 1624, 2063, +2554, 1624, 2064, +2554, 1624, 2067, +2554, 1624, 2070, +2554, 1624, 2074, +2554, 1624, 2080, +2554, 1624, 2087, +2554, 1621, 2096, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1590, 2134, +2556, 1556, 2169, +2555, 1609, 2217, +2557, 1691, 2269, +2563, 1692, 2342, +2564, 1762, 2409, +2587, 1839, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1627, 2059, +2554, 1626, 2059, +2554, 1625, 2060, +2554, 1625, 2060, +2554, 1625, 2061, +2554, 1625, 2063, +2554, 1625, 2064, +2554, 1625, 2067, +2554, 1625, 2070, +2554, 1625, 2074, +2554, 1625, 2079, +2554, 1625, 2086, +2554, 1622, 2096, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1592, 2134, +2556, 1559, 2169, +2555, 1610, 2217, +2557, 1691, 2269, +2564, 1693, 2342, +2564, 1764, 2409, +2587, 1840, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1630, 2060, +2554, 1629, 2060, +2554, 1627, 2060, +2554, 1625, 2060, +2554, 1625, 2061, +2554, 1625, 2062, +2554, 1625, 2064, +2554, 1625, 2066, +2554, 1625, 2070, +2554, 1625, 2074, +2554, 1625, 2079, +2554, 1625, 2086, +2554, 1623, 2095, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1595, 2134, +2556, 1562, 2169, +2555, 1611, 2217, +2557, 1691, 2270, +2564, 1694, 2342, +2564, 1765, 2409, +2587, 1842, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1633, 2060, +2554, 1632, 2060, +2554, 1631, 2060, +2554, 1629, 2060, +2554, 1626, 2061, +2554, 1626, 2062, +2554, 1626, 2064, +2554, 1626, 2066, +2554, 1626, 2069, +2554, 1626, 2073, +2554, 1626, 2079, +2554, 1626, 2086, +2554, 1625, 2095, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1599, 2135, +2556, 1567, 2169, +2555, 1613, 2217, +2557, 1692, 2270, +2564, 1695, 2342, +2565, 1768, 2409, +2587, 1844, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1638, 2061, +2554, 1638, 2061, +2554, 1636, 2061, +2554, 1634, 2061, +2554, 1631, 2061, +2554, 1628, 2062, +2554, 1628, 2063, +2554, 1628, 2066, +2554, 1628, 2069, +2554, 1628, 2073, +2554, 1628, 2079, +2554, 1628, 2086, +2554, 1626, 2095, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1605, 2135, +2556, 1572, 2169, +2555, 1616, 2217, +2557, 1693, 2270, +2564, 1696, 2342, +2565, 1771, 2409, +2587, 1847, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2555, 1645, 2062, +2555, 1644, 2062, +2555, 1643, 2062, +2555, 1641, 2062, +2555, 1638, 2062, +2555, 1635, 2063, +2555, 1631, 2063, +2555, 1631, 2066, +2555, 1631, 2069, +2555, 1631, 2073, +2555, 1631, 2078, +2555, 1631, 2085, +2555, 1628, 2094, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1612, 2136, +2556, 1580, 2169, +2554, 1619, 2217, +2558, 1694, 2270, +2564, 1698, 2342, +2565, 1775, 2409, +2587, 1852, 2492, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2555, 1654, 2063, +2555, 1653, 2063, +2555, 1651, 2063, +2555, 1650, 2063, +2555, 1647, 2063, +2555, 1644, 2064, +2555, 1640, 2064, +2555, 1633, 2065, +2555, 1633, 2068, +2555, 1633, 2072, +2555, 1633, 2078, +2555, 1633, 2085, +2555, 1631, 2094, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1621, 2137, +2557, 1590, 2169, +2554, 1624, 2217, +2558, 1695, 2270, +2564, 1701, 2342, +2565, 1781, 2409, +2588, 1857, 2493, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2556, 1665, 2064, +2556, 1664, 2065, +2556, 1663, 2065, +2556, 1661, 2065, +2556, 1659, 2065, +2556, 1655, 2066, +2556, 1651, 2066, +2556, 1646, 2066, +2556, 1638, 2067, +2556, 1638, 2071, +2556, 1638, 2077, +2556, 1638, 2084, +2556, 1636, 2093, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1633, 2138, +2557, 1603, 2169, +2554, 1630, 2217, +2558, 1697, 2271, +2564, 1704, 2342, +2565, 1788, 2409, +2588, 1860, 2493, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2556, 1680, 2066, +2556, 1679, 2067, +2556, 1678, 2067, +2556, 1676, 2067, +2556, 1674, 2067, +2556, 1671, 2068, +2556, 1667, 2068, +2556, 1661, 2069, +2556, 1653, 2069, +2556, 1643, 2070, +2556, 1643, 2076, +2556, 1643, 2083, +2556, 1641, 2092, +2554, 1624, 2101, +2554, 1621, 2110, +2557, 1649, 2140, +2557, 1620, 2170, +2554, 1638, 2217, +2558, 1699, 2271, +2565, 1709, 2342, +2566, 1798, 2409, +2589, 1863, 2493, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2558, 1699, 2069, +2558, 1698, 2069, +2558, 1697, 2070, +2558, 1695, 2070, +2558, 1693, 2070, +2558, 1690, 2070, +2558, 1686, 2071, +2558, 1681, 2071, +2558, 1674, 2072, +2558, 1663, 2073, +2558, 1650, 2074, +2558, 1650, 2082, +2557, 1648, 2091, +2555, 1631, 2100, +2554, 1621, 2110, +2557, 1657, 2141, +2558, 1642, 2173, +2554, 1658, 2217, +2559, 1702, 2273, +2565, 1715, 2342, +2566, 1810, 2409, +2589, 1868, 2493, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2559, 1723, 2073, +2559, 1723, 2073, +2559, 1722, 2073, +2559, 1720, 2073, +2559, 1718, 2074, +2559, 1715, 2074, +2559, 1711, 2074, +2559, 1706, 2075, +2559, 1699, 2076, +2559, 1690, 2077, +2559, 1677, 2078, +2559, 1659, 2080, +2558, 1657, 2089, +2556, 1641, 2098, +2554, 1621, 2110, +2557, 1657, 2141, +2558, 1669, 2176, +2555, 1684, 2217, +2560, 1706, 2274, +2566, 1723, 2342, +2567, 1816, 2409, +2591, 1873, 2493, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2560, 1754, 2078, +2560, 1754, 2078, +2560, 1753, 2078, +2560, 1752, 2079, +2560, 1750, 2079, +2560, 1747, 2079, +2560, 1744, 2080, +2560, 1739, 2080, +2560, 1732, 2081, +2560, 1724, 2082, +2560, 1712, 2083, +2560, 1695, 2085, +2560, 1674, 2088, +2558, 1658, 2097, +2555, 1635, 2110, +2557, 1661, 2141, +2559, 1703, 2179, +2556, 1716, 2217, +2560, 1716, 2275, +2566, 1739, 2342, +2568, 1818, 2408, +2592, 1880, 2493, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2562, 1761, 2078, +2562, 1761, 2078, +2562, 1761, 2079, +2562, 1762, 2080, +2562, 1763, 2080, +2562, 1765, 2082, +2562, 1766, 2084, +2562, 1769, 2086, +2562, 1772, 2089, +2563, 1771, 2091, +2563, 1760, 2093, +2563, 1745, 2094, +2562, 1727, 2097, +2561, 1712, 2103, +2558, 1692, 2116, +2556, 1693, 2138, +2560, 1738, 2181, +2560, 1744, 2217, +2561, 1744, 2275, +2566, 1785, 2340, +2571, 1835, 2406, +2592, 1893, 2492, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2563, 1769, 2078, +2563, 1769, 2078, +2563, 1770, 2079, +2563, 1771, 2080, +2563, 1772, 2080, +2563, 1773, 2082, +2564, 1775, 2084, +2564, 1777, 2086, +2564, 1780, 2089, +2564, 1784, 2093, +2565, 1789, 2098, +2565, 1796, 2105, +2566, 1789, 2110, +2564, 1776, 2116, +2563, 1758, 2124, +2559, 1753, 2143, +2558, 1773, 2177, +2563, 1787, 2220, +2563, 1779, 2275, +2566, 1840, 2337, +2576, 1860, 2406, +2591, 1925, 2491, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2566, 1822, 2077, +2566, 1822, 2078, +2566, 1822, 2078, +2566, 1822, 2078, +2566, 1822, 2079, +2566, 1822, 2079, +2566, 1822, 2080, +2566, 1822, 2081, +2566, 1822, 2083, +2566, 1822, 2085, +2567, 1824, 2089, +2568, 1831, 2096, +2568, 1839, 2106, +2570, 1844, 2121, +2568, 1834, 2131, +2568, 1813, 2145, +2564, 1813, 2176, +2565, 1838, 2221, +2568, 1838, 2272, +2573, 1888, 2337, +2580, 1896, 2406, +2599, 1967, 2492, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2573, 1894, 2080, +2573, 1894, 2081, +2573, 1895, 2081, +2573, 1896, 2081, +2573, 1897, 2082, +2574, 1898, 2082, +2574, 1900, 2083, +2575, 1903, 2084, +2575, 1906, 2086, +2575, 1906, 2088, +2575, 1906, 2090, +2575, 1906, 2094, +2575, 1906, 2099, +2575, 1907, 2109, +2576, 1913, 2129, +2577, 1915, 2152, +2578, 1893, 2171, +2576, 1899, 2221, +2578, 1919, 2273, +2580, 1949, 2338, +2587, 1961, 2408, +2611, 2008, 2495, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2588, 1996, 2083, +2588, 1997, 2083, +2588, 1997, 2084, +2588, 1997, 2085, +2588, 1997, 2086, +2588, 1998, 2087, +2588, 1998, 2088, +2588, 1999, 2091, +2588, 2000, 2093, +2588, 2001, 2098, +2588, 2005, 2100, +2589, 2012, 2104, +2591, 2018, 2108, +2588, 2010, 2114, +2588, 2009, 2126, +2589, 2014, 2149, +2590, 2016, 2184, +2591, 2003, 2214, +2591, 2019, 2275, +2595, 2044, 2342, +2604, 2072, 2411, +2625, 2108, 2494, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2625, 2149, 2111, +2624, 2149, 2111, +2624, 2149, 2111, +2624, 2149, 2111, +2624, 2148, 2111, +2624, 2148, 2111, +2623, 2147, 2111, +2623, 2146, 2111, +2622, 2145, 2111, +2621, 2143, 2111, +2620, 2141, 2111, +2618, 2137, 2111, +2617, 2136, 2114, +2617, 2144, 2126, +2617, 2155, 2141, +2619, 2157, 2164, +2623, 2160, 2195, +2624, 2165, 2231, +2619, 2165, 2275, +2633, 2187, 2352, +2638, 2190, 2417, +2660, 2223, 2503, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2670, 2315, 2112, +2671, 2315, 2112, +2671, 2315, 2112, +2671, 2315, 2111, +2671, 2316, 2111, +2672, 2316, 2111, +2672, 2316, 2111, +2673, 2317, 2110, +2674, 2318, 2109, +2675, 2319, 2108, +2677, 2321, 2107, +2680, 2323, 2105, +2682, 2325, 2106, +2681, 2325, 2118, +2680, 2325, 2133, +2678, 2328, 2149, +2677, 2328, 2176, +2677, 2325, 2215, +2687, 2335, 2275, +2689, 2335, 2316, +2695, 2346, 2391, +2724, 2369, 2462, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2775, 2531, 1744, +2775, 2531, 1745, +2775, 2531, 1747, +2775, 2531, 1750, +2776, 2532, 1753, +2776, 2532, 1758, +2776, 2533, 1764, +2776, 2533, 1772, +2777, 2534, 1782, +2778, 2535, 1796, +2778, 2536, 1813, +2778, 2537, 1825, +2777, 2535, 1833, +2776, 2530, 1839, +2776, 2528, 1859, +2778, 2535, 1929, +2779, 2534, 1991, +2780, 2535, 2071, +2782, 2538, 2158, +2784, 2536, 2248, +2791, 2552, 2360, +2803, 2569, 2485, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2826, 2762, 2506, +2826, 2762, 2506, +2826, 2762, 2505, +2826, 2762, 2505, +2826, 2762, 2505, +2826, 2762, 2505, +2826, 2761, 2505, +2826, 2761, 2505, +2826, 2761, 2505, +2826, 2761, 2506, +2826, 2761, 2507, +2826, 2761, 2509, +2826, 2761, 2510, +2826, 2760, 2508, +2826, 2760, 2508, +2826, 2762, 2520, +2826, 2764, 2535, +2826, 2763, 2548, +2826, 2763, 2571, +2826, 2767, 2613, +2826, 2769, 2662, +2826, 2779, 2732, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2554, 1623, 2059, +2554, 1623, 2059, +2554, 1623, 2060, +2554, 1623, 2060, +2554, 1623, 2061, +2554, 1623, 2063, +2554, 1623, 2065, +2554, 1623, 2067, +2554, 1623, 2070, +2554, 1623, 2074, +2554, 1623, 2080, +2554, 1623, 2087, +2554, 1621, 2096, +2554, 1621, 2102, +2554, 1621, 2110, +2555, 1588, 2133, +2556, 1555, 2169, +2555, 1608, 2217, +2557, 1691, 2269, +2563, 1692, 2342, +2564, 1761, 2409, +2587, 1838, 2491, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1625, 2059, +2554, 1624, 2059, +2554, 1624, 2060, +2554, 1624, 2060, +2554, 1624, 2061, +2554, 1624, 2063, +2554, 1624, 2064, +2554, 1624, 2067, +2554, 1624, 2070, +2554, 1624, 2074, +2554, 1624, 2080, +2554, 1624, 2087, +2554, 1621, 2096, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1590, 2134, +2556, 1556, 2169, +2555, 1609, 2217, +2557, 1691, 2269, +2563, 1692, 2342, +2564, 1762, 2409, +2587, 1839, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1627, 2059, +2554, 1626, 2059, +2554, 1625, 2060, +2554, 1625, 2060, +2554, 1625, 2061, +2554, 1625, 2063, +2554, 1625, 2064, +2554, 1625, 2067, +2554, 1625, 2070, +2554, 1625, 2074, +2554, 1625, 2079, +2554, 1625, 2086, +2554, 1622, 2096, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1592, 2134, +2556, 1559, 2169, +2555, 1610, 2217, +2557, 1691, 2269, +2564, 1693, 2342, +2564, 1764, 2409, +2587, 1840, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1630, 2060, +2554, 1629, 2060, +2554, 1627, 2060, +2554, 1625, 2060, +2554, 1625, 2061, +2554, 1625, 2062, +2554, 1625, 2064, +2554, 1625, 2066, +2554, 1625, 2070, +2554, 1625, 2074, +2554, 1625, 2079, +2554, 1625, 2086, +2554, 1623, 2095, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1595, 2134, +2556, 1562, 2169, +2555, 1611, 2217, +2557, 1691, 2270, +2564, 1694, 2342, +2564, 1765, 2409, +2587, 1842, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1633, 2060, +2554, 1632, 2060, +2554, 1631, 2060, +2554, 1629, 2060, +2554, 1626, 2061, +2554, 1626, 2062, +2554, 1626, 2064, +2554, 1626, 2066, +2554, 1626, 2069, +2554, 1626, 2073, +2554, 1626, 2079, +2554, 1626, 2086, +2554, 1625, 2095, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1599, 2135, +2556, 1567, 2169, +2555, 1613, 2217, +2557, 1692, 2270, +2564, 1695, 2342, +2565, 1768, 2409, +2587, 1844, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1638, 2061, +2554, 1638, 2061, +2554, 1636, 2061, +2554, 1634, 2061, +2554, 1631, 2061, +2554, 1628, 2062, +2554, 1628, 2063, +2554, 1628, 2066, +2554, 1628, 2069, +2554, 1628, 2073, +2554, 1628, 2079, +2554, 1628, 2086, +2554, 1626, 2095, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1605, 2135, +2556, 1572, 2169, +2555, 1616, 2217, +2557, 1693, 2270, +2564, 1696, 2342, +2565, 1771, 2409, +2587, 1847, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2555, 1645, 2062, +2555, 1644, 2062, +2555, 1643, 2062, +2555, 1641, 2062, +2555, 1638, 2062, +2555, 1635, 2063, +2555, 1631, 2063, +2555, 1631, 2066, +2555, 1631, 2069, +2555, 1631, 2073, +2555, 1631, 2078, +2555, 1631, 2085, +2555, 1628, 2094, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1612, 2136, +2556, 1580, 2169, +2554, 1619, 2217, +2558, 1694, 2270, +2564, 1698, 2342, +2565, 1775, 2409, +2587, 1852, 2492, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2555, 1654, 2063, +2555, 1653, 2063, +2555, 1651, 2063, +2555, 1650, 2063, +2555, 1647, 2063, +2555, 1644, 2064, +2555, 1640, 2064, +2555, 1633, 2065, +2555, 1633, 2068, +2555, 1633, 2072, +2555, 1633, 2078, +2555, 1633, 2085, +2555, 1631, 2094, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1621, 2137, +2557, 1590, 2169, +2554, 1624, 2217, +2558, 1695, 2270, +2564, 1701, 2342, +2565, 1781, 2409, +2588, 1857, 2493, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2556, 1665, 2064, +2556, 1664, 2065, +2556, 1663, 2065, +2556, 1661, 2065, +2556, 1659, 2065, +2556, 1655, 2066, +2556, 1651, 2066, +2556, 1646, 2066, +2556, 1638, 2067, +2556, 1638, 2071, +2556, 1638, 2077, +2556, 1638, 2084, +2556, 1636, 2093, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1633, 2138, +2557, 1603, 2169, +2554, 1630, 2217, +2558, 1697, 2271, +2564, 1704, 2342, +2565, 1788, 2409, +2588, 1860, 2493, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2556, 1680, 2066, +2556, 1679, 2067, +2556, 1678, 2067, +2556, 1676, 2067, +2556, 1674, 2067, +2556, 1671, 2068, +2556, 1667, 2068, +2556, 1661, 2069, +2556, 1653, 2069, +2556, 1643, 2070, +2556, 1643, 2076, +2556, 1643, 2083, +2556, 1641, 2092, +2554, 1624, 2101, +2554, 1621, 2110, +2557, 1649, 2140, +2557, 1620, 2170, +2554, 1638, 2217, +2558, 1699, 2271, +2565, 1709, 2342, +2566, 1798, 2409, +2589, 1863, 2493, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2558, 1699, 2069, +2558, 1698, 2069, +2558, 1697, 2070, +2558, 1695, 2070, +2558, 1693, 2070, +2558, 1690, 2070, +2558, 1686, 2071, +2558, 1681, 2071, +2558, 1674, 2072, +2558, 1663, 2073, +2558, 1650, 2074, +2558, 1650, 2082, +2557, 1648, 2091, +2555, 1631, 2100, +2554, 1621, 2110, +2557, 1657, 2141, +2558, 1642, 2173, +2554, 1658, 2217, +2559, 1702, 2273, +2565, 1715, 2342, +2566, 1810, 2409, +2589, 1868, 2493, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2559, 1723, 2073, +2559, 1723, 2073, +2559, 1722, 2073, +2559, 1720, 2073, +2559, 1718, 2074, +2559, 1715, 2074, +2559, 1711, 2074, +2559, 1706, 2075, +2559, 1699, 2076, +2559, 1690, 2077, +2559, 1677, 2078, +2559, 1659, 2080, +2558, 1657, 2089, +2556, 1641, 2098, +2554, 1621, 2110, +2557, 1657, 2141, +2558, 1669, 2176, +2555, 1684, 2217, +2560, 1706, 2274, +2566, 1723, 2342, +2567, 1816, 2409, +2591, 1873, 2493, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2560, 1754, 2078, +2560, 1754, 2078, +2560, 1753, 2078, +2560, 1752, 2079, +2560, 1750, 2079, +2560, 1747, 2079, +2560, 1744, 2080, +2560, 1739, 2080, +2560, 1732, 2081, +2560, 1724, 2082, +2560, 1712, 2083, +2560, 1695, 2085, +2560, 1674, 2088, +2558, 1658, 2097, +2555, 1635, 2110, +2557, 1661, 2141, +2559, 1703, 2179, +2556, 1716, 2217, +2560, 1716, 2275, +2566, 1739, 2342, +2568, 1818, 2408, +2592, 1880, 2493, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2562, 1761, 2078, +2562, 1761, 2078, +2562, 1761, 2079, +2562, 1762, 2080, +2562, 1763, 2080, +2562, 1765, 2082, +2562, 1766, 2084, +2562, 1769, 2086, +2562, 1772, 2089, +2563, 1771, 2091, +2563, 1760, 2093, +2563, 1745, 2094, +2562, 1727, 2097, +2561, 1712, 2103, +2558, 1692, 2116, +2556, 1693, 2138, +2560, 1738, 2181, +2560, 1744, 2217, +2561, 1744, 2275, +2566, 1785, 2340, +2571, 1835, 2406, +2592, 1893, 2492, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2563, 1769, 2078, +2563, 1769, 2078, +2563, 1770, 2079, +2563, 1771, 2080, +2563, 1772, 2080, +2563, 1773, 2082, +2564, 1775, 2084, +2564, 1777, 2086, +2564, 1780, 2089, +2564, 1784, 2093, +2565, 1789, 2098, +2565, 1796, 2105, +2566, 1789, 2110, +2564, 1776, 2116, +2563, 1758, 2124, +2559, 1753, 2143, +2558, 1773, 2177, +2563, 1787, 2220, +2563, 1779, 2275, +2566, 1840, 2337, +2576, 1860, 2406, +2591, 1925, 2491, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2566, 1822, 2077, +2566, 1822, 2078, +2566, 1822, 2078, +2566, 1822, 2078, +2566, 1822, 2079, +2566, 1822, 2079, +2566, 1822, 2080, +2566, 1822, 2081, +2566, 1822, 2083, +2566, 1822, 2085, +2567, 1824, 2089, +2568, 1831, 2096, +2568, 1839, 2106, +2570, 1844, 2121, +2568, 1834, 2131, +2568, 1813, 2145, +2564, 1813, 2176, +2565, 1838, 2221, +2568, 1838, 2272, +2573, 1888, 2337, +2580, 1896, 2406, +2599, 1967, 2492, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2573, 1894, 2080, +2573, 1894, 2081, +2573, 1895, 2081, +2573, 1896, 2081, +2573, 1897, 2082, +2574, 1898, 2082, +2574, 1900, 2083, +2575, 1903, 2084, +2575, 1906, 2086, +2575, 1906, 2088, +2575, 1906, 2090, +2575, 1906, 2094, +2575, 1906, 2099, +2575, 1907, 2109, +2576, 1913, 2129, +2577, 1915, 2152, +2578, 1893, 2171, +2576, 1899, 2221, +2578, 1919, 2273, +2580, 1949, 2338, +2587, 1961, 2408, +2611, 2008, 2495, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2588, 1996, 2083, +2588, 1997, 2083, +2588, 1997, 2084, +2588, 1997, 2085, +2588, 1997, 2086, +2588, 1998, 2087, +2588, 1998, 2088, +2588, 1999, 2091, +2588, 2000, 2093, +2588, 2001, 2098, +2588, 2005, 2100, +2589, 2012, 2104, +2591, 2018, 2108, +2588, 2010, 2114, +2588, 2009, 2126, +2589, 2014, 2149, +2590, 2016, 2184, +2591, 2003, 2214, +2591, 2019, 2275, +2595, 2044, 2342, +2604, 2072, 2411, +2625, 2108, 2494, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2625, 2149, 2111, +2624, 2149, 2111, +2624, 2149, 2111, +2624, 2149, 2111, +2624, 2148, 2111, +2624, 2148, 2111, +2623, 2147, 2111, +2623, 2146, 2111, +2622, 2145, 2111, +2621, 2143, 2111, +2620, 2141, 2111, +2618, 2137, 2111, +2617, 2136, 2114, +2617, 2144, 2126, +2617, 2155, 2141, +2619, 2157, 2164, +2623, 2160, 2195, +2624, 2165, 2231, +2619, 2165, 2275, +2633, 2187, 2352, +2638, 2190, 2417, +2660, 2223, 2503, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2670, 2315, 2112, +2671, 2315, 2112, +2671, 2315, 2112, +2671, 2315, 2111, +2671, 2316, 2111, +2672, 2316, 2111, +2672, 2316, 2111, +2673, 2317, 2110, +2674, 2318, 2109, +2675, 2319, 2108, +2677, 2321, 2107, +2680, 2323, 2105, +2682, 2325, 2106, +2681, 2325, 2118, +2680, 2325, 2133, +2678, 2328, 2149, +2677, 2328, 2176, +2677, 2325, 2215, +2687, 2335, 2275, +2689, 2335, 2316, +2695, 2346, 2391, +2724, 2369, 2462, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2775, 2531, 1744, +2775, 2531, 1745, +2775, 2531, 1747, +2775, 2531, 1750, +2776, 2532, 1753, +2776, 2532, 1758, +2776, 2533, 1764, +2776, 2533, 1772, +2777, 2534, 1782, +2778, 2535, 1796, +2778, 2536, 1813, +2778, 2537, 1825, +2777, 2535, 1833, +2776, 2530, 1839, +2776, 2528, 1859, +2778, 2535, 1929, +2779, 2534, 1991, +2780, 2535, 2071, +2782, 2538, 2158, +2784, 2536, 2248, +2791, 2552, 2360, +2803, 2569, 2485, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2826, 2762, 2506, +2826, 2762, 2506, +2826, 2762, 2505, +2826, 2762, 2505, +2826, 2762, 2505, +2826, 2762, 2505, +2826, 2761, 2505, +2826, 2761, 2505, +2826, 2761, 2505, +2826, 2761, 2506, +2826, 2761, 2507, +2826, 2761, 2509, +2826, 2761, 2510, +2826, 2760, 2508, +2826, 2760, 2508, +2826, 2762, 2520, +2826, 2764, 2535, +2826, 2763, 2548, +2826, 2763, 2571, +2826, 2767, 2613, +2826, 2769, 2662, +2826, 2779, 2732, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2554, 1623, 2059, +2554, 1623, 2059, +2554, 1623, 2060, +2554, 1623, 2060, +2554, 1623, 2061, +2554, 1623, 2063, +2554, 1623, 2065, +2554, 1623, 2067, +2554, 1623, 2070, +2554, 1623, 2074, +2554, 1623, 2080, +2554, 1623, 2087, +2554, 1621, 2096, +2554, 1621, 2102, +2554, 1621, 2110, +2555, 1588, 2133, +2556, 1555, 2169, +2555, 1608, 2217, +2557, 1691, 2269, +2563, 1692, 2342, +2564, 1761, 2409, +2587, 1838, 2491, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1625, 2059, +2554, 1624, 2059, +2554, 1624, 2060, +2554, 1624, 2060, +2554, 1624, 2061, +2554, 1624, 2063, +2554, 1624, 2064, +2554, 1624, 2067, +2554, 1624, 2070, +2554, 1624, 2074, +2554, 1624, 2080, +2554, 1624, 2087, +2554, 1621, 2096, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1590, 2134, +2556, 1556, 2169, +2555, 1609, 2217, +2557, 1691, 2269, +2563, 1692, 2342, +2564, 1762, 2409, +2587, 1839, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1627, 2059, +2554, 1626, 2059, +2554, 1625, 2060, +2554, 1625, 2060, +2554, 1625, 2061, +2554, 1625, 2063, +2554, 1625, 2064, +2554, 1625, 2067, +2554, 1625, 2070, +2554, 1625, 2074, +2554, 1625, 2079, +2554, 1625, 2086, +2554, 1622, 2096, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1592, 2134, +2556, 1559, 2169, +2555, 1610, 2217, +2557, 1691, 2269, +2564, 1693, 2342, +2564, 1764, 2409, +2587, 1840, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1630, 2060, +2554, 1629, 2060, +2554, 1627, 2060, +2554, 1625, 2060, +2554, 1625, 2061, +2554, 1625, 2062, +2554, 1625, 2064, +2554, 1625, 2066, +2554, 1625, 2070, +2554, 1625, 2074, +2554, 1625, 2079, +2554, 1625, 2086, +2554, 1623, 2095, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1595, 2134, +2556, 1562, 2169, +2555, 1611, 2217, +2557, 1691, 2270, +2564, 1694, 2342, +2564, 1765, 2409, +2587, 1842, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1633, 2060, +2554, 1632, 2060, +2554, 1631, 2060, +2554, 1629, 2060, +2554, 1626, 2061, +2554, 1626, 2062, +2554, 1626, 2064, +2554, 1626, 2066, +2554, 1626, 2069, +2554, 1626, 2073, +2554, 1626, 2079, +2554, 1626, 2086, +2554, 1625, 2095, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1599, 2135, +2556, 1567, 2169, +2555, 1613, 2217, +2557, 1692, 2270, +2564, 1695, 2342, +2565, 1768, 2409, +2587, 1844, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1638, 2061, +2554, 1638, 2061, +2554, 1636, 2061, +2554, 1634, 2061, +2554, 1631, 2061, +2554, 1628, 2062, +2554, 1628, 2063, +2554, 1628, 2066, +2554, 1628, 2069, +2554, 1628, 2073, +2554, 1628, 2079, +2554, 1628, 2086, +2554, 1626, 2095, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1605, 2135, +2556, 1572, 2169, +2555, 1616, 2217, +2557, 1693, 2270, +2564, 1696, 2342, +2565, 1771, 2409, +2587, 1847, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2555, 1645, 2062, +2555, 1644, 2062, +2555, 1643, 2062, +2555, 1641, 2062, +2555, 1638, 2062, +2555, 1635, 2063, +2555, 1631, 2063, +2555, 1631, 2066, +2555, 1631, 2069, +2555, 1631, 2073, +2555, 1631, 2078, +2555, 1631, 2085, +2555, 1628, 2094, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1612, 2136, +2556, 1580, 2169, +2554, 1619, 2217, +2558, 1694, 2270, +2564, 1698, 2342, +2565, 1775, 2409, +2587, 1852, 2492, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2555, 1654, 2063, +2555, 1653, 2063, +2555, 1651, 2063, +2555, 1650, 2063, +2555, 1647, 2063, +2555, 1644, 2064, +2555, 1640, 2064, +2555, 1633, 2065, +2555, 1633, 2068, +2555, 1633, 2072, +2555, 1633, 2078, +2555, 1633, 2085, +2555, 1631, 2094, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1621, 2137, +2557, 1590, 2169, +2554, 1624, 2217, +2558, 1695, 2270, +2564, 1701, 2342, +2565, 1781, 2409, +2588, 1857, 2493, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2556, 1665, 2064, +2556, 1664, 2065, +2556, 1663, 2065, +2556, 1661, 2065, +2556, 1659, 2065, +2556, 1655, 2066, +2556, 1651, 2066, +2556, 1646, 2066, +2556, 1638, 2067, +2556, 1638, 2071, +2556, 1638, 2077, +2556, 1638, 2084, +2556, 1636, 2093, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1633, 2138, +2557, 1603, 2169, +2554, 1630, 2217, +2558, 1697, 2271, +2564, 1704, 2342, +2565, 1788, 2409, +2588, 1860, 2493, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2556, 1680, 2066, +2556, 1679, 2067, +2556, 1678, 2067, +2556, 1676, 2067, +2556, 1674, 2067, +2556, 1671, 2068, +2556, 1667, 2068, +2556, 1661, 2069, +2556, 1653, 2069, +2556, 1643, 2070, +2556, 1643, 2076, +2556, 1643, 2083, +2556, 1641, 2092, +2554, 1624, 2101, +2554, 1621, 2110, +2557, 1649, 2140, +2557, 1620, 2170, +2554, 1638, 2217, +2558, 1699, 2271, +2565, 1709, 2342, +2566, 1798, 2409, +2589, 1863, 2493, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2558, 1699, 2069, +2558, 1698, 2069, +2558, 1697, 2070, +2558, 1695, 2070, +2558, 1693, 2070, +2558, 1690, 2070, +2558, 1686, 2071, +2558, 1681, 2071, +2558, 1674, 2072, +2558, 1663, 2073, +2558, 1650, 2074, +2558, 1650, 2082, +2557, 1648, 2091, +2555, 1631, 2100, +2554, 1621, 2110, +2557, 1657, 2141, +2558, 1642, 2173, +2554, 1658, 2217, +2559, 1702, 2273, +2565, 1715, 2342, +2566, 1810, 2409, +2589, 1868, 2493, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2559, 1723, 2073, +2559, 1723, 2073, +2559, 1722, 2073, +2559, 1720, 2073, +2559, 1718, 2074, +2559, 1715, 2074, +2559, 1711, 2074, +2559, 1706, 2075, +2559, 1699, 2076, +2559, 1690, 2077, +2559, 1677, 2078, +2559, 1659, 2080, +2558, 1657, 2089, +2556, 1641, 2098, +2554, 1621, 2110, +2557, 1657, 2141, +2558, 1669, 2176, +2555, 1684, 2217, +2560, 1706, 2274, +2566, 1723, 2342, +2567, 1816, 2409, +2591, 1873, 2493, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2560, 1754, 2078, +2560, 1754, 2078, +2560, 1753, 2078, +2560, 1752, 2079, +2560, 1750, 2079, +2560, 1747, 2079, +2560, 1744, 2080, +2560, 1739, 2080, +2560, 1732, 2081, +2560, 1724, 2082, +2560, 1712, 2083, +2560, 1695, 2085, +2560, 1674, 2088, +2558, 1658, 2097, +2555, 1635, 2110, +2557, 1661, 2141, +2559, 1703, 2179, +2556, 1716, 2217, +2560, 1716, 2275, +2566, 1739, 2342, +2568, 1818, 2408, +2592, 1880, 2493, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2562, 1761, 2078, +2562, 1761, 2078, +2562, 1761, 2079, +2562, 1762, 2080, +2562, 1763, 2080, +2562, 1765, 2082, +2562, 1766, 2084, +2562, 1769, 2086, +2562, 1772, 2089, +2563, 1771, 2091, +2563, 1760, 2093, +2563, 1745, 2094, +2562, 1727, 2097, +2561, 1712, 2103, +2558, 1692, 2116, +2556, 1693, 2138, +2560, 1738, 2181, +2560, 1744, 2217, +2561, 1744, 2275, +2566, 1785, 2340, +2571, 1835, 2406, +2592, 1893, 2492, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2563, 1769, 2078, +2563, 1769, 2078, +2563, 1770, 2079, +2563, 1771, 2080, +2563, 1772, 2080, +2563, 1773, 2082, +2564, 1775, 2084, +2564, 1777, 2086, +2564, 1780, 2089, +2564, 1784, 2093, +2565, 1789, 2098, +2565, 1796, 2105, +2566, 1789, 2110, +2564, 1776, 2116, +2563, 1758, 2124, +2559, 1753, 2143, +2558, 1773, 2177, +2563, 1787, 2220, +2563, 1779, 2275, +2566, 1840, 2337, +2576, 1860, 2406, +2591, 1925, 2491, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2566, 1822, 2077, +2566, 1822, 2078, +2566, 1822, 2078, +2566, 1822, 2078, +2566, 1822, 2079, +2566, 1822, 2079, +2566, 1822, 2080, +2566, 1822, 2081, +2566, 1822, 2083, +2566, 1822, 2085, +2567, 1824, 2089, +2568, 1831, 2096, +2568, 1839, 2106, +2570, 1844, 2121, +2568, 1834, 2131, +2568, 1813, 2145, +2564, 1813, 2176, +2565, 1838, 2221, +2568, 1838, 2272, +2573, 1888, 2337, +2580, 1896, 2406, +2599, 1967, 2492, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2573, 1894, 2080, +2573, 1894, 2081, +2573, 1895, 2081, +2573, 1896, 2081, +2573, 1897, 2082, +2574, 1898, 2082, +2574, 1900, 2083, +2575, 1903, 2084, +2575, 1906, 2086, +2575, 1906, 2088, +2575, 1906, 2090, +2575, 1906, 2094, +2575, 1906, 2099, +2575, 1907, 2109, +2576, 1913, 2129, +2577, 1915, 2152, +2578, 1893, 2171, +2576, 1899, 2221, +2578, 1919, 2273, +2580, 1949, 2338, +2587, 1961, 2408, +2611, 2008, 2495, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2588, 1996, 2083, +2588, 1997, 2083, +2588, 1997, 2084, +2588, 1997, 2085, +2588, 1997, 2086, +2588, 1998, 2087, +2588, 1998, 2088, +2588, 1999, 2091, +2588, 2000, 2093, +2588, 2001, 2098, +2588, 2005, 2100, +2589, 2012, 2104, +2591, 2018, 2108, +2588, 2010, 2114, +2588, 2009, 2126, +2589, 2014, 2149, +2590, 2016, 2184, +2591, 2003, 2214, +2591, 2019, 2275, +2595, 2044, 2342, +2604, 2072, 2411, +2625, 2108, 2494, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2625, 2149, 2111, +2624, 2149, 2111, +2624, 2149, 2111, +2624, 2149, 2111, +2624, 2148, 2111, +2624, 2148, 2111, +2623, 2147, 2111, +2623, 2146, 2111, +2622, 2145, 2111, +2621, 2143, 2111, +2620, 2141, 2111, +2618, 2137, 2111, +2617, 2136, 2114, +2617, 2144, 2126, +2617, 2155, 2141, +2619, 2157, 2164, +2623, 2160, 2195, +2624, 2165, 2231, +2619, 2165, 2275, +2633, 2187, 2352, +2638, 2190, 2417, +2660, 2223, 2503, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2670, 2315, 2112, +2671, 2315, 2112, +2671, 2315, 2112, +2671, 2315, 2111, +2671, 2316, 2111, +2672, 2316, 2111, +2672, 2316, 2111, +2673, 2317, 2110, +2674, 2318, 2109, +2675, 2319, 2108, +2677, 2321, 2107, +2680, 2323, 2105, +2682, 2325, 2106, +2681, 2325, 2118, +2680, 2325, 2133, +2678, 2328, 2149, +2677, 2328, 2176, +2677, 2325, 2215, +2687, 2335, 2275, +2689, 2335, 2316, +2695, 2346, 2391, +2724, 2369, 2462, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2775, 2531, 1744, +2775, 2531, 1745, +2775, 2531, 1747, +2775, 2531, 1750, +2776, 2532, 1753, +2776, 2532, 1758, +2776, 2533, 1764, +2776, 2533, 1772, +2777, 2534, 1782, +2778, 2535, 1796, +2778, 2536, 1813, +2778, 2537, 1825, +2777, 2535, 1833, +2776, 2530, 1839, +2776, 2528, 1859, +2778, 2535, 1929, +2779, 2534, 1991, +2780, 2535, 2071, +2782, 2538, 2158, +2784, 2536, 2248, +2791, 2552, 2360, +2803, 2569, 2485, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2826, 2762, 2506, +2826, 2762, 2506, +2826, 2762, 2505, +2826, 2762, 2505, +2826, 2762, 2505, +2826, 2762, 2505, +2826, 2761, 2505, +2826, 2761, 2505, +2826, 2761, 2505, +2826, 2761, 2506, +2826, 2761, 2507, +2826, 2761, 2509, +2826, 2761, 2510, +2826, 2760, 2508, +2826, 2760, 2508, +2826, 2762, 2520, +2826, 2764, 2535, +2826, 2763, 2548, +2826, 2763, 2571, +2826, 2767, 2613, +2826, 2769, 2662, +2826, 2779, 2732, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2554, 1623, 2059, +2554, 1623, 2059, +2554, 1623, 2060, +2554, 1623, 2060, +2554, 1623, 2061, +2554, 1623, 2063, +2554, 1623, 2065, +2554, 1623, 2067, +2554, 1623, 2070, +2554, 1623, 2074, +2554, 1623, 2080, +2554, 1623, 2087, +2554, 1621, 2096, +2554, 1621, 2102, +2554, 1621, 2110, +2555, 1588, 2133, +2556, 1555, 2169, +2555, 1608, 2217, +2557, 1691, 2269, +2563, 1692, 2342, +2564, 1761, 2409, +2587, 1838, 2491, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1625, 2059, +2554, 1624, 2059, +2554, 1624, 2060, +2554, 1624, 2060, +2554, 1624, 2061, +2554, 1624, 2063, +2554, 1624, 2064, +2554, 1624, 2067, +2554, 1624, 2070, +2554, 1624, 2074, +2554, 1624, 2080, +2554, 1624, 2087, +2554, 1621, 2096, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1590, 2134, +2556, 1556, 2169, +2555, 1609, 2217, +2557, 1691, 2269, +2563, 1692, 2342, +2564, 1762, 2409, +2587, 1839, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1627, 2059, +2554, 1626, 2059, +2554, 1625, 2060, +2554, 1625, 2060, +2554, 1625, 2061, +2554, 1625, 2063, +2554, 1625, 2064, +2554, 1625, 2067, +2554, 1625, 2070, +2554, 1625, 2074, +2554, 1625, 2079, +2554, 1625, 2086, +2554, 1622, 2096, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1592, 2134, +2556, 1559, 2169, +2555, 1610, 2217, +2557, 1691, 2269, +2564, 1693, 2342, +2564, 1764, 2409, +2587, 1840, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1630, 2060, +2554, 1629, 2060, +2554, 1627, 2060, +2554, 1625, 2060, +2554, 1625, 2061, +2554, 1625, 2062, +2554, 1625, 2064, +2554, 1625, 2066, +2554, 1625, 2070, +2554, 1625, 2074, +2554, 1625, 2079, +2554, 1625, 2086, +2554, 1623, 2095, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1595, 2134, +2556, 1562, 2169, +2555, 1611, 2217, +2557, 1691, 2270, +2564, 1694, 2342, +2564, 1765, 2409, +2587, 1842, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1633, 2060, +2554, 1632, 2060, +2554, 1631, 2060, +2554, 1629, 2060, +2554, 1626, 2061, +2554, 1626, 2062, +2554, 1626, 2064, +2554, 1626, 2066, +2554, 1626, 2069, +2554, 1626, 2073, +2554, 1626, 2079, +2554, 1626, 2086, +2554, 1625, 2095, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1599, 2135, +2556, 1567, 2169, +2555, 1613, 2217, +2557, 1692, 2270, +2564, 1695, 2342, +2565, 1768, 2409, +2587, 1844, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1638, 2061, +2554, 1638, 2061, +2554, 1636, 2061, +2554, 1634, 2061, +2554, 1631, 2061, +2554, 1628, 2062, +2554, 1628, 2063, +2554, 1628, 2066, +2554, 1628, 2069, +2554, 1628, 2073, +2554, 1628, 2079, +2554, 1628, 2086, +2554, 1626, 2095, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1605, 2135, +2556, 1572, 2169, +2555, 1616, 2217, +2557, 1693, 2270, +2564, 1696, 2342, +2565, 1771, 2409, +2587, 1847, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2555, 1645, 2062, +2555, 1644, 2062, +2555, 1643, 2062, +2555, 1641, 2062, +2555, 1638, 2062, +2555, 1635, 2063, +2555, 1631, 2063, +2555, 1631, 2066, +2555, 1631, 2069, +2555, 1631, 2073, +2555, 1631, 2078, +2555, 1631, 2085, +2555, 1628, 2094, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1612, 2136, +2556, 1580, 2169, +2554, 1619, 2217, +2558, 1694, 2270, +2564, 1698, 2342, +2565, 1775, 2409, +2587, 1852, 2492, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2555, 1654, 2063, +2555, 1653, 2063, +2555, 1651, 2063, +2555, 1650, 2063, +2555, 1647, 2063, +2555, 1644, 2064, +2555, 1640, 2064, +2555, 1633, 2065, +2555, 1633, 2068, +2555, 1633, 2072, +2555, 1633, 2078, +2555, 1633, 2085, +2555, 1631, 2094, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1621, 2137, +2557, 1590, 2169, +2554, 1624, 2217, +2558, 1695, 2270, +2564, 1701, 2342, +2565, 1781, 2409, +2588, 1857, 2493, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2556, 1665, 2064, +2556, 1664, 2065, +2556, 1663, 2065, +2556, 1661, 2065, +2556, 1659, 2065, +2556, 1655, 2066, +2556, 1651, 2066, +2556, 1646, 2066, +2556, 1638, 2067, +2556, 1638, 2071, +2556, 1638, 2077, +2556, 1638, 2084, +2556, 1636, 2093, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1633, 2138, +2557, 1603, 2169, +2554, 1630, 2217, +2558, 1697, 2271, +2564, 1704, 2342, +2565, 1788, 2409, +2588, 1860, 2493, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2556, 1680, 2066, +2556, 1679, 2067, +2556, 1678, 2067, +2556, 1676, 2067, +2556, 1674, 2067, +2556, 1671, 2068, +2556, 1667, 2068, +2556, 1661, 2069, +2556, 1653, 2069, +2556, 1643, 2070, +2556, 1643, 2076, +2556, 1643, 2083, +2556, 1641, 2092, +2554, 1624, 2101, +2554, 1621, 2110, +2557, 1649, 2140, +2557, 1620, 2170, +2554, 1638, 2217, +2558, 1699, 2271, +2565, 1709, 2342, +2566, 1798, 2409, +2589, 1863, 2493, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2558, 1699, 2069, +2558, 1698, 2069, +2558, 1697, 2070, +2558, 1695, 2070, +2558, 1693, 2070, +2558, 1690, 2070, +2558, 1686, 2071, +2558, 1681, 2071, +2558, 1674, 2072, +2558, 1663, 2073, +2558, 1650, 2074, +2558, 1650, 2082, +2557, 1648, 2091, +2555, 1631, 2100, +2554, 1621, 2110, +2557, 1657, 2141, +2558, 1642, 2173, +2554, 1658, 2217, +2559, 1702, 2273, +2565, 1715, 2342, +2566, 1810, 2409, +2589, 1868, 2493, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2559, 1723, 2073, +2559, 1723, 2073, +2559, 1722, 2073, +2559, 1720, 2073, +2559, 1718, 2074, +2559, 1715, 2074, +2559, 1711, 2074, +2559, 1706, 2075, +2559, 1699, 2076, +2559, 1690, 2077, +2559, 1677, 2078, +2559, 1659, 2080, +2558, 1657, 2089, +2556, 1641, 2098, +2554, 1621, 2110, +2557, 1657, 2141, +2558, 1669, 2176, +2555, 1684, 2217, +2560, 1706, 2274, +2566, 1723, 2342, +2567, 1816, 2409, +2591, 1873, 2493, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2560, 1754, 2078, +2560, 1754, 2078, +2560, 1753, 2078, +2560, 1752, 2079, +2560, 1750, 2079, +2560, 1747, 2079, +2560, 1744, 2080, +2560, 1739, 2080, +2560, 1732, 2081, +2560, 1724, 2082, +2560, 1712, 2083, +2560, 1695, 2085, +2560, 1674, 2088, +2558, 1658, 2097, +2555, 1635, 2110, +2557, 1661, 2141, +2559, 1703, 2179, +2556, 1716, 2217, +2560, 1716, 2275, +2566, 1739, 2342, +2568, 1818, 2408, +2592, 1880, 2493, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2562, 1761, 2078, +2562, 1761, 2078, +2562, 1761, 2079, +2562, 1762, 2080, +2562, 1763, 2080, +2562, 1765, 2082, +2562, 1766, 2084, +2562, 1769, 2086, +2562, 1772, 2089, +2563, 1771, 2091, +2563, 1760, 2093, +2563, 1745, 2094, +2562, 1727, 2097, +2561, 1712, 2103, +2558, 1692, 2116, +2556, 1693, 2138, +2560, 1738, 2181, +2560, 1744, 2217, +2561, 1744, 2275, +2566, 1785, 2340, +2571, 1835, 2406, +2592, 1893, 2492, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2563, 1769, 2078, +2563, 1769, 2078, +2563, 1770, 2079, +2563, 1771, 2080, +2563, 1772, 2080, +2563, 1773, 2082, +2564, 1775, 2084, +2564, 1777, 2086, +2564, 1780, 2089, +2564, 1784, 2093, +2565, 1789, 2098, +2565, 1796, 2105, +2566, 1789, 2110, +2564, 1776, 2116, +2563, 1758, 2124, +2559, 1753, 2143, +2558, 1773, 2177, +2563, 1787, 2220, +2563, 1779, 2275, +2566, 1840, 2337, +2576, 1860, 2406, +2591, 1925, 2491, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2566, 1822, 2077, +2566, 1822, 2078, +2566, 1822, 2078, +2566, 1822, 2078, +2566, 1822, 2079, +2566, 1822, 2079, +2566, 1822, 2080, +2566, 1822, 2081, +2566, 1822, 2083, +2566, 1822, 2085, +2567, 1824, 2089, +2568, 1831, 2096, +2568, 1839, 2106, +2570, 1844, 2121, +2568, 1834, 2131, +2568, 1813, 2145, +2564, 1813, 2176, +2565, 1838, 2221, +2568, 1838, 2272, +2573, 1888, 2337, +2580, 1896, 2406, +2599, 1967, 2492, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2573, 1894, 2080, +2573, 1894, 2081, +2573, 1895, 2081, +2573, 1896, 2081, +2573, 1897, 2082, +2574, 1898, 2082, +2574, 1900, 2083, +2575, 1903, 2084, +2575, 1906, 2086, +2575, 1906, 2088, +2575, 1906, 2090, +2575, 1906, 2094, +2575, 1906, 2099, +2575, 1907, 2109, +2576, 1913, 2129, +2577, 1915, 2152, +2578, 1893, 2171, +2576, 1899, 2221, +2578, 1919, 2273, +2580, 1949, 2338, +2587, 1961, 2408, +2611, 2008, 2495, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2588, 1996, 2083, +2588, 1997, 2083, +2588, 1997, 2084, +2588, 1997, 2085, +2588, 1997, 2086, +2588, 1998, 2087, +2588, 1998, 2088, +2588, 1999, 2091, +2588, 2000, 2093, +2588, 2001, 2098, +2588, 2005, 2100, +2589, 2012, 2104, +2591, 2018, 2108, +2588, 2010, 2114, +2588, 2009, 2126, +2589, 2014, 2149, +2590, 2016, 2184, +2591, 2003, 2214, +2591, 2019, 2275, +2595, 2044, 2342, +2604, 2072, 2411, +2625, 2108, 2494, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2625, 2149, 2111, +2624, 2149, 2111, +2624, 2149, 2111, +2624, 2149, 2111, +2624, 2148, 2111, +2624, 2148, 2111, +2623, 2147, 2111, +2623, 2146, 2111, +2622, 2145, 2111, +2621, 2143, 2111, +2620, 2141, 2111, +2618, 2137, 2111, +2617, 2136, 2114, +2617, 2144, 2126, +2617, 2155, 2141, +2619, 2157, 2164, +2623, 2160, 2195, +2624, 2165, 2231, +2619, 2165, 2275, +2633, 2187, 2352, +2638, 2190, 2417, +2660, 2223, 2503, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2670, 2315, 2112, +2671, 2315, 2112, +2671, 2315, 2112, +2671, 2315, 2111, +2671, 2316, 2111, +2672, 2316, 2111, +2672, 2316, 2111, +2673, 2317, 2110, +2674, 2318, 2109, +2675, 2319, 2108, +2677, 2321, 2107, +2680, 2323, 2105, +2682, 2325, 2106, +2681, 2325, 2118, +2680, 2325, 2133, +2678, 2328, 2149, +2677, 2328, 2176, +2677, 2325, 2215, +2687, 2335, 2275, +2689, 2335, 2316, +2695, 2346, 2391, +2724, 2369, 2462, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2775, 2531, 1744, +2775, 2531, 1745, +2775, 2531, 1747, +2775, 2531, 1750, +2776, 2532, 1753, +2776, 2532, 1758, +2776, 2533, 1764, +2776, 2533, 1772, +2777, 2534, 1782, +2778, 2535, 1796, +2778, 2536, 1813, +2778, 2537, 1825, +2777, 2535, 1833, +2776, 2530, 1839, +2776, 2528, 1859, +2778, 2535, 1929, +2779, 2534, 1991, +2780, 2535, 2071, +2782, 2538, 2158, +2784, 2536, 2248, +2791, 2552, 2360, +2803, 2569, 2485, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2826, 2762, 2506, +2826, 2762, 2506, +2826, 2762, 2505, +2826, 2762, 2505, +2826, 2762, 2505, +2826, 2762, 2505, +2826, 2761, 2505, +2826, 2761, 2505, +2826, 2761, 2505, +2826, 2761, 2506, +2826, 2761, 2507, +2826, 2761, 2509, +2826, 2761, 2510, +2826, 2760, 2508, +2826, 2760, 2508, +2826, 2762, 2520, +2826, 2764, 2535, +2826, 2763, 2548, +2826, 2763, 2571, +2826, 2767, 2613, +2826, 2769, 2662, +2826, 2779, 2732, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2554, 1623, 2059, +2554, 1623, 2059, +2554, 1623, 2060, +2554, 1623, 2060, +2554, 1623, 2061, +2554, 1623, 2063, +2554, 1623, 2065, +2554, 1623, 2067, +2554, 1623, 2070, +2554, 1623, 2074, +2554, 1623, 2080, +2554, 1623, 2087, +2554, 1621, 2096, +2554, 1621, 2102, +2554, 1621, 2110, +2555, 1588, 2133, +2556, 1555, 2169, +2555, 1608, 2217, +2557, 1691, 2269, +2563, 1692, 2342, +2564, 1761, 2409, +2587, 1838, 2491, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1625, 2059, +2554, 1624, 2059, +2554, 1624, 2060, +2554, 1624, 2060, +2554, 1624, 2061, +2554, 1624, 2063, +2554, 1624, 2064, +2554, 1624, 2067, +2554, 1624, 2070, +2554, 1624, 2074, +2554, 1624, 2080, +2554, 1624, 2087, +2554, 1621, 2096, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1590, 2134, +2556, 1556, 2169, +2555, 1609, 2217, +2557, 1691, 2269, +2563, 1692, 2342, +2564, 1762, 2409, +2587, 1839, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1627, 2059, +2554, 1626, 2059, +2554, 1625, 2060, +2554, 1625, 2060, +2554, 1625, 2061, +2554, 1625, 2063, +2554, 1625, 2064, +2554, 1625, 2067, +2554, 1625, 2070, +2554, 1625, 2074, +2554, 1625, 2079, +2554, 1625, 2086, +2554, 1622, 2096, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1592, 2134, +2556, 1559, 2169, +2555, 1610, 2217, +2557, 1691, 2269, +2564, 1693, 2342, +2564, 1764, 2409, +2587, 1840, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1630, 2060, +2554, 1629, 2060, +2554, 1627, 2060, +2554, 1625, 2060, +2554, 1625, 2061, +2554, 1625, 2062, +2554, 1625, 2064, +2554, 1625, 2066, +2554, 1625, 2070, +2554, 1625, 2074, +2554, 1625, 2079, +2554, 1625, 2086, +2554, 1623, 2095, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1595, 2134, +2556, 1562, 2169, +2555, 1611, 2217, +2557, 1691, 2270, +2564, 1694, 2342, +2564, 1765, 2409, +2587, 1842, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1633, 2060, +2554, 1632, 2060, +2554, 1631, 2060, +2554, 1629, 2060, +2554, 1626, 2061, +2554, 1626, 2062, +2554, 1626, 2064, +2554, 1626, 2066, +2554, 1626, 2069, +2554, 1626, 2073, +2554, 1626, 2079, +2554, 1626, 2086, +2554, 1625, 2095, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1599, 2135, +2556, 1567, 2169, +2555, 1613, 2217, +2557, 1692, 2270, +2564, 1695, 2342, +2565, 1768, 2409, +2587, 1844, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1638, 2061, +2554, 1638, 2061, +2554, 1636, 2061, +2554, 1634, 2061, +2554, 1631, 2061, +2554, 1628, 2062, +2554, 1628, 2063, +2554, 1628, 2066, +2554, 1628, 2069, +2554, 1628, 2073, +2554, 1628, 2079, +2554, 1628, 2086, +2554, 1626, 2095, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1605, 2135, +2556, 1572, 2169, +2555, 1616, 2217, +2557, 1693, 2270, +2564, 1696, 2342, +2565, 1771, 2409, +2587, 1847, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2555, 1645, 2062, +2555, 1644, 2062, +2555, 1643, 2062, +2555, 1641, 2062, +2555, 1638, 2062, +2555, 1635, 2063, +2555, 1631, 2063, +2555, 1631, 2066, +2555, 1631, 2069, +2555, 1631, 2073, +2555, 1631, 2078, +2555, 1631, 2085, +2555, 1628, 2094, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1612, 2136, +2556, 1580, 2169, +2554, 1619, 2217, +2558, 1694, 2270, +2564, 1698, 2342, +2565, 1775, 2409, +2587, 1852, 2492, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2555, 1654, 2063, +2555, 1653, 2063, +2555, 1651, 2063, +2555, 1650, 2063, +2555, 1647, 2063, +2555, 1644, 2064, +2555, 1640, 2064, +2555, 1633, 2065, +2555, 1633, 2068, +2555, 1633, 2072, +2555, 1633, 2078, +2555, 1633, 2085, +2555, 1631, 2094, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1621, 2137, +2557, 1590, 2169, +2554, 1624, 2217, +2558, 1695, 2270, +2564, 1701, 2342, +2565, 1781, 2409, +2588, 1857, 2493, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2556, 1665, 2064, +2556, 1664, 2065, +2556, 1663, 2065, +2556, 1661, 2065, +2556, 1659, 2065, +2556, 1655, 2066, +2556, 1651, 2066, +2556, 1646, 2066, +2556, 1638, 2067, +2556, 1638, 2071, +2556, 1638, 2077, +2556, 1638, 2084, +2556, 1636, 2093, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1633, 2138, +2557, 1603, 2169, +2554, 1630, 2217, +2558, 1697, 2271, +2564, 1704, 2342, +2565, 1788, 2409, +2588, 1860, 2493, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2556, 1680, 2066, +2556, 1679, 2067, +2556, 1678, 2067, +2556, 1676, 2067, +2556, 1674, 2067, +2556, 1671, 2068, +2556, 1667, 2068, +2556, 1661, 2069, +2556, 1653, 2069, +2556, 1643, 2070, +2556, 1643, 2076, +2556, 1643, 2083, +2556, 1641, 2092, +2554, 1624, 2101, +2554, 1621, 2110, +2557, 1649, 2140, +2557, 1620, 2170, +2554, 1638, 2217, +2558, 1699, 2271, +2565, 1709, 2342, +2566, 1798, 2409, +2589, 1863, 2493, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2558, 1699, 2069, +2558, 1698, 2069, +2558, 1697, 2070, +2558, 1695, 2070, +2558, 1693, 2070, +2558, 1690, 2070, +2558, 1686, 2071, +2558, 1681, 2071, +2558, 1674, 2072, +2558, 1663, 2073, +2558, 1650, 2074, +2558, 1650, 2082, +2557, 1648, 2091, +2555, 1631, 2100, +2554, 1621, 2110, +2557, 1657, 2141, +2558, 1642, 2173, +2554, 1658, 2217, +2559, 1702, 2273, +2565, 1715, 2342, +2566, 1810, 2409, +2589, 1868, 2493, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2559, 1723, 2073, +2559, 1723, 2073, +2559, 1722, 2073, +2559, 1720, 2073, +2559, 1718, 2074, +2559, 1715, 2074, +2559, 1711, 2074, +2559, 1706, 2075, +2559, 1699, 2076, +2559, 1690, 2077, +2559, 1677, 2078, +2559, 1659, 2080, +2558, 1657, 2089, +2556, 1641, 2098, +2554, 1621, 2110, +2557, 1657, 2141, +2558, 1669, 2176, +2555, 1684, 2217, +2560, 1706, 2274, +2566, 1723, 2342, +2567, 1816, 2409, +2591, 1873, 2493, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2560, 1754, 2078, +2560, 1754, 2078, +2560, 1753, 2078, +2560, 1752, 2079, +2560, 1750, 2079, +2560, 1747, 2079, +2560, 1744, 2080, +2560, 1739, 2080, +2560, 1732, 2081, +2560, 1724, 2082, +2560, 1712, 2083, +2560, 1695, 2085, +2560, 1674, 2088, +2558, 1658, 2097, +2555, 1635, 2110, +2557, 1661, 2141, +2559, 1703, 2179, +2556, 1716, 2217, +2560, 1716, 2275, +2566, 1739, 2342, +2568, 1818, 2408, +2592, 1880, 2493, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2562, 1761, 2078, +2562, 1761, 2078, +2562, 1761, 2079, +2562, 1762, 2080, +2562, 1763, 2080, +2562, 1765, 2082, +2562, 1766, 2084, +2562, 1769, 2086, +2562, 1772, 2089, +2563, 1771, 2091, +2563, 1760, 2093, +2563, 1745, 2094, +2562, 1727, 2097, +2561, 1712, 2103, +2558, 1692, 2116, +2556, 1693, 2138, +2560, 1738, 2181, +2560, 1744, 2217, +2561, 1744, 2275, +2566, 1785, 2340, +2571, 1835, 2406, +2592, 1893, 2492, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2563, 1769, 2078, +2563, 1769, 2078, +2563, 1770, 2079, +2563, 1771, 2080, +2563, 1772, 2080, +2563, 1773, 2082, +2564, 1775, 2084, +2564, 1777, 2086, +2564, 1780, 2089, +2564, 1784, 2093, +2565, 1789, 2098, +2565, 1796, 2105, +2566, 1789, 2110, +2564, 1776, 2116, +2563, 1758, 2124, +2559, 1753, 2143, +2558, 1773, 2177, +2563, 1787, 2220, +2563, 1779, 2275, +2566, 1840, 2337, +2576, 1860, 2406, +2591, 1925, 2491, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2566, 1822, 2077, +2566, 1822, 2078, +2566, 1822, 2078, +2566, 1822, 2078, +2566, 1822, 2079, +2566, 1822, 2079, +2566, 1822, 2080, +2566, 1822, 2081, +2566, 1822, 2083, +2566, 1822, 2085, +2567, 1824, 2089, +2568, 1831, 2096, +2568, 1839, 2106, +2570, 1844, 2121, +2568, 1834, 2131, +2568, 1813, 2145, +2564, 1813, 2176, +2565, 1838, 2221, +2568, 1838, 2272, +2573, 1888, 2337, +2580, 1896, 2406, +2599, 1967, 2492, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2573, 1894, 2080, +2573, 1894, 2081, +2573, 1895, 2081, +2573, 1896, 2081, +2573, 1897, 2082, +2574, 1898, 2082, +2574, 1900, 2083, +2575, 1903, 2084, +2575, 1906, 2086, +2575, 1906, 2088, +2575, 1906, 2090, +2575, 1906, 2094, +2575, 1906, 2099, +2575, 1907, 2109, +2576, 1913, 2129, +2577, 1915, 2152, +2578, 1893, 2171, +2576, 1899, 2221, +2578, 1919, 2273, +2580, 1949, 2338, +2587, 1961, 2408, +2611, 2008, 2495, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2588, 1996, 2083, +2588, 1997, 2083, +2588, 1997, 2084, +2588, 1997, 2085, +2588, 1997, 2086, +2588, 1998, 2087, +2588, 1998, 2088, +2588, 1999, 2091, +2588, 2000, 2093, +2588, 2001, 2098, +2588, 2005, 2100, +2589, 2012, 2104, +2591, 2018, 2108, +2588, 2010, 2114, +2588, 2009, 2126, +2589, 2014, 2149, +2590, 2016, 2184, +2591, 2003, 2214, +2591, 2019, 2275, +2595, 2044, 2342, +2604, 2072, 2411, +2625, 2108, 2494, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2625, 2149, 2111, +2624, 2149, 2111, +2624, 2149, 2111, +2624, 2149, 2111, +2624, 2148, 2111, +2624, 2148, 2111, +2623, 2147, 2111, +2623, 2146, 2111, +2622, 2145, 2111, +2621, 2143, 2111, +2620, 2141, 2111, +2618, 2137, 2111, +2617, 2136, 2114, +2617, 2144, 2126, +2617, 2155, 2141, +2619, 2157, 2164, +2623, 2160, 2195, +2624, 2165, 2231, +2619, 2165, 2275, +2633, 2187, 2352, +2638, 2190, 2417, +2660, 2223, 2503, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2670, 2315, 2112, +2671, 2315, 2112, +2671, 2315, 2112, +2671, 2315, 2111, +2671, 2316, 2111, +2672, 2316, 2111, +2672, 2316, 2111, +2673, 2317, 2110, +2674, 2318, 2109, +2675, 2319, 2108, +2677, 2321, 2107, +2680, 2323, 2105, +2682, 2325, 2106, +2681, 2325, 2118, +2680, 2325, 2133, +2678, 2328, 2149, +2677, 2328, 2176, +2677, 2325, 2215, +2687, 2335, 2275, +2689, 2335, 2316, +2695, 2346, 2391, +2724, 2369, 2462, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2775, 2531, 1744, +2775, 2531, 1745, +2775, 2531, 1747, +2775, 2531, 1750, +2776, 2532, 1753, +2776, 2532, 1758, +2776, 2533, 1764, +2776, 2533, 1772, +2777, 2534, 1782, +2778, 2535, 1796, +2778, 2536, 1813, +2778, 2537, 1825, +2777, 2535, 1833, +2776, 2530, 1839, +2776, 2528, 1859, +2778, 2535, 1929, +2779, 2534, 1991, +2780, 2535, 2071, +2782, 2538, 2158, +2784, 2536, 2248, +2791, 2552, 2360, +2803, 2569, 2485, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2826, 2762, 2506, +2826, 2762, 2506, +2826, 2762, 2505, +2826, 2762, 2505, +2826, 2762, 2505, +2826, 2762, 2505, +2826, 2761, 2505, +2826, 2761, 2505, +2826, 2761, 2505, +2826, 2761, 2506, +2826, 2761, 2507, +2826, 2761, 2509, +2826, 2761, 2510, +2826, 2760, 2508, +2826, 2760, 2508, +2826, 2762, 2520, +2826, 2764, 2535, +2826, 2763, 2548, +2826, 2763, 2571, +2826, 2767, 2613, +2826, 2769, 2662, +2826, 2779, 2732, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2554, 1623, 2059, +2554, 1623, 2059, +2554, 1623, 2060, +2554, 1623, 2060, +2554, 1623, 2061, +2554, 1623, 2063, +2554, 1623, 2065, +2554, 1623, 2067, +2554, 1623, 2070, +2554, 1623, 2074, +2554, 1623, 2080, +2554, 1623, 2087, +2554, 1621, 2096, +2554, 1621, 2102, +2554, 1621, 2110, +2555, 1588, 2133, +2556, 1555, 2169, +2555, 1608, 2217, +2557, 1691, 2269, +2563, 1692, 2342, +2564, 1761, 2409, +2587, 1838, 2491, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1625, 2059, +2554, 1624, 2059, +2554, 1624, 2060, +2554, 1624, 2060, +2554, 1624, 2061, +2554, 1624, 2063, +2554, 1624, 2064, +2554, 1624, 2067, +2554, 1624, 2070, +2554, 1624, 2074, +2554, 1624, 2080, +2554, 1624, 2087, +2554, 1621, 2096, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1590, 2134, +2556, 1556, 2169, +2555, 1609, 2217, +2557, 1691, 2269, +2563, 1692, 2342, +2564, 1762, 2409, +2587, 1839, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1627, 2059, +2554, 1626, 2059, +2554, 1625, 2060, +2554, 1625, 2060, +2554, 1625, 2061, +2554, 1625, 2063, +2554, 1625, 2064, +2554, 1625, 2067, +2554, 1625, 2070, +2554, 1625, 2074, +2554, 1625, 2079, +2554, 1625, 2086, +2554, 1622, 2096, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1592, 2134, +2556, 1559, 2169, +2555, 1610, 2217, +2557, 1691, 2269, +2564, 1693, 2342, +2564, 1764, 2409, +2587, 1840, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1630, 2060, +2554, 1629, 2060, +2554, 1627, 2060, +2554, 1625, 2060, +2554, 1625, 2061, +2554, 1625, 2062, +2554, 1625, 2064, +2554, 1625, 2066, +2554, 1625, 2070, +2554, 1625, 2074, +2554, 1625, 2079, +2554, 1625, 2086, +2554, 1623, 2095, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1595, 2134, +2556, 1562, 2169, +2555, 1611, 2217, +2557, 1691, 2270, +2564, 1694, 2342, +2564, 1765, 2409, +2587, 1842, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1633, 2060, +2554, 1632, 2060, +2554, 1631, 2060, +2554, 1629, 2060, +2554, 1626, 2061, +2554, 1626, 2062, +2554, 1626, 2064, +2554, 1626, 2066, +2554, 1626, 2069, +2554, 1626, 2073, +2554, 1626, 2079, +2554, 1626, 2086, +2554, 1625, 2095, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1599, 2135, +2556, 1567, 2169, +2555, 1613, 2217, +2557, 1692, 2270, +2564, 1695, 2342, +2565, 1768, 2409, +2587, 1844, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2554, 1638, 2061, +2554, 1638, 2061, +2554, 1636, 2061, +2554, 1634, 2061, +2554, 1631, 2061, +2554, 1628, 2062, +2554, 1628, 2063, +2554, 1628, 2066, +2554, 1628, 2069, +2554, 1628, 2073, +2554, 1628, 2079, +2554, 1628, 2086, +2554, 1626, 2095, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1605, 2135, +2556, 1572, 2169, +2555, 1616, 2217, +2557, 1693, 2270, +2564, 1696, 2342, +2565, 1771, 2409, +2587, 1847, 2492, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2597, 1897, 2530, +2555, 1645, 2062, +2555, 1644, 2062, +2555, 1643, 2062, +2555, 1641, 2062, +2555, 1638, 2062, +2555, 1635, 2063, +2555, 1631, 2063, +2555, 1631, 2066, +2555, 1631, 2069, +2555, 1631, 2073, +2555, 1631, 2078, +2555, 1631, 2085, +2555, 1628, 2094, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1612, 2136, +2556, 1580, 2169, +2554, 1619, 2217, +2558, 1694, 2270, +2564, 1698, 2342, +2565, 1775, 2409, +2587, 1852, 2492, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2555, 1654, 2063, +2555, 1653, 2063, +2555, 1651, 2063, +2555, 1650, 2063, +2555, 1647, 2063, +2555, 1644, 2064, +2555, 1640, 2064, +2555, 1633, 2065, +2555, 1633, 2068, +2555, 1633, 2072, +2555, 1633, 2078, +2555, 1633, 2085, +2555, 1631, 2094, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1621, 2137, +2557, 1590, 2169, +2554, 1624, 2217, +2558, 1695, 2270, +2564, 1701, 2342, +2565, 1781, 2409, +2588, 1857, 2493, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2597, 1897, 2529, +2556, 1665, 2064, +2556, 1664, 2065, +2556, 1663, 2065, +2556, 1661, 2065, +2556, 1659, 2065, +2556, 1655, 2066, +2556, 1651, 2066, +2556, 1646, 2066, +2556, 1638, 2067, +2556, 1638, 2071, +2556, 1638, 2077, +2556, 1638, 2084, +2556, 1636, 2093, +2554, 1621, 2102, +2554, 1621, 2110, +2556, 1633, 2138, +2557, 1603, 2169, +2554, 1630, 2217, +2558, 1697, 2271, +2564, 1704, 2342, +2565, 1788, 2409, +2588, 1860, 2493, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2597, 1897, 2528, +2556, 1680, 2066, +2556, 1679, 2067, +2556, 1678, 2067, +2556, 1676, 2067, +2556, 1674, 2067, +2556, 1671, 2068, +2556, 1667, 2068, +2556, 1661, 2069, +2556, 1653, 2069, +2556, 1643, 2070, +2556, 1643, 2076, +2556, 1643, 2083, +2556, 1641, 2092, +2554, 1624, 2101, +2554, 1621, 2110, +2557, 1649, 2140, +2557, 1620, 2170, +2554, 1638, 2217, +2558, 1699, 2271, +2565, 1709, 2342, +2566, 1798, 2409, +2589, 1863, 2493, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2558, 1699, 2069, +2558, 1698, 2069, +2558, 1697, 2070, +2558, 1695, 2070, +2558, 1693, 2070, +2558, 1690, 2070, +2558, 1686, 2071, +2558, 1681, 2071, +2558, 1674, 2072, +2558, 1663, 2073, +2558, 1650, 2074, +2558, 1650, 2082, +2557, 1648, 2091, +2555, 1631, 2100, +2554, 1621, 2110, +2557, 1657, 2141, +2558, 1642, 2173, +2554, 1658, 2217, +2559, 1702, 2273, +2565, 1715, 2342, +2566, 1810, 2409, +2589, 1868, 2493, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2597, 1897, 2527, +2559, 1723, 2073, +2559, 1723, 2073, +2559, 1722, 2073, +2559, 1720, 2073, +2559, 1718, 2074, +2559, 1715, 2074, +2559, 1711, 2074, +2559, 1706, 2075, +2559, 1699, 2076, +2559, 1690, 2077, +2559, 1677, 2078, +2559, 1659, 2080, +2558, 1657, 2089, +2556, 1641, 2098, +2554, 1621, 2110, +2557, 1657, 2141, +2558, 1669, 2176, +2555, 1684, 2217, +2560, 1706, 2274, +2566, 1723, 2342, +2567, 1816, 2409, +2591, 1873, 2493, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2597, 1897, 2525, +2560, 1754, 2078, +2560, 1754, 2078, +2560, 1753, 2078, +2560, 1752, 2079, +2560, 1750, 2079, +2560, 1747, 2079, +2560, 1744, 2080, +2560, 1739, 2080, +2560, 1732, 2081, +2560, 1724, 2082, +2560, 1712, 2083, +2560, 1695, 2085, +2560, 1674, 2088, +2558, 1658, 2097, +2555, 1635, 2110, +2557, 1661, 2141, +2559, 1703, 2179, +2556, 1716, 2217, +2560, 1716, 2275, +2566, 1739, 2342, +2568, 1818, 2408, +2592, 1880, 2493, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2597, 1898, 2524, +2562, 1761, 2078, +2562, 1761, 2078, +2562, 1761, 2079, +2562, 1762, 2080, +2562, 1763, 2080, +2562, 1765, 2082, +2562, 1766, 2084, +2562, 1769, 2086, +2562, 1772, 2089, +2563, 1771, 2091, +2563, 1760, 2093, +2563, 1745, 2094, +2562, 1727, 2097, +2561, 1712, 2103, +2558, 1692, 2116, +2556, 1693, 2138, +2560, 1738, 2181, +2560, 1744, 2217, +2561, 1744, 2275, +2566, 1785, 2340, +2571, 1835, 2406, +2592, 1893, 2492, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2599, 1908, 2527, +2563, 1769, 2078, +2563, 1769, 2078, +2563, 1770, 2079, +2563, 1771, 2080, +2563, 1772, 2080, +2563, 1773, 2082, +2564, 1775, 2084, +2564, 1777, 2086, +2564, 1780, 2089, +2564, 1784, 2093, +2565, 1789, 2098, +2565, 1796, 2105, +2566, 1789, 2110, +2564, 1776, 2116, +2563, 1758, 2124, +2559, 1753, 2143, +2558, 1773, 2177, +2563, 1787, 2220, +2563, 1779, 2275, +2566, 1840, 2337, +2576, 1860, 2406, +2591, 1925, 2491, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2602, 1920, 2530, +2566, 1822, 2077, +2566, 1822, 2078, +2566, 1822, 2078, +2566, 1822, 2078, +2566, 1822, 2079, +2566, 1822, 2079, +2566, 1822, 2080, +2566, 1822, 2081, +2566, 1822, 2083, +2566, 1822, 2085, +2567, 1824, 2089, +2568, 1831, 2096, +2568, 1839, 2106, +2570, 1844, 2121, +2568, 1834, 2131, +2568, 1813, 2145, +2564, 1813, 2176, +2565, 1838, 2221, +2568, 1838, 2272, +2573, 1888, 2337, +2580, 1896, 2406, +2599, 1967, 2492, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2609, 1966, 2529, +2573, 1894, 2080, +2573, 1894, 2081, +2573, 1895, 2081, +2573, 1896, 2081, +2573, 1897, 2082, +2574, 1898, 2082, +2574, 1900, 2083, +2575, 1903, 2084, +2575, 1906, 2086, +2575, 1906, 2088, +2575, 1906, 2090, +2575, 1906, 2094, +2575, 1906, 2099, +2575, 1907, 2109, +2576, 1913, 2129, +2577, 1915, 2152, +2578, 1893, 2171, +2576, 1899, 2221, +2578, 1919, 2273, +2580, 1949, 2338, +2587, 1961, 2408, +2611, 2008, 2495, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2623, 2041, 2528, +2588, 1996, 2083, +2588, 1997, 2083, +2588, 1997, 2084, +2588, 1997, 2085, +2588, 1997, 2086, +2588, 1998, 2087, +2588, 1998, 2088, +2588, 1999, 2091, +2588, 2000, 2093, +2588, 2001, 2098, +2588, 2005, 2100, +2589, 2012, 2104, +2591, 2018, 2108, +2588, 2010, 2114, +2588, 2009, 2126, +2589, 2014, 2149, +2590, 2016, 2184, +2591, 2003, 2214, +2591, 2019, 2275, +2595, 2044, 2342, +2604, 2072, 2411, +2625, 2108, 2494, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2644, 2138, 2530, +2625, 2149, 2111, +2624, 2149, 2111, +2624, 2149, 2111, +2624, 2149, 2111, +2624, 2148, 2111, +2624, 2148, 2111, +2623, 2147, 2111, +2623, 2146, 2111, +2622, 2145, 2111, +2621, 2143, 2111, +2620, 2141, 2111, +2618, 2137, 2111, +2617, 2136, 2114, +2617, 2144, 2126, +2617, 2155, 2141, +2619, 2157, 2164, +2623, 2160, 2195, +2624, 2165, 2231, +2619, 2165, 2275, +2633, 2187, 2352, +2638, 2190, 2417, +2660, 2223, 2503, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2672, 2249, 2537, +2670, 2315, 2112, +2671, 2315, 2112, +2671, 2315, 2112, +2671, 2315, 2111, +2671, 2316, 2111, +2672, 2316, 2111, +2672, 2316, 2111, +2673, 2317, 2110, +2674, 2318, 2109, +2675, 2319, 2108, +2677, 2321, 2107, +2680, 2323, 2105, +2682, 2325, 2106, +2681, 2325, 2118, +2680, 2325, 2133, +2678, 2328, 2149, +2677, 2328, 2176, +2677, 2325, 2215, +2687, 2335, 2275, +2689, 2335, 2316, +2695, 2346, 2391, +2724, 2369, 2462, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2735, 2385, 2488, +2775, 2531, 1744, +2775, 2531, 1745, +2775, 2531, 1747, +2775, 2531, 1750, +2776, 2532, 1753, +2776, 2532, 1758, +2776, 2533, 1764, +2776, 2533, 1772, +2777, 2534, 1782, +2778, 2535, 1796, +2778, 2536, 1813, +2778, 2537, 1825, +2777, 2535, 1833, +2776, 2530, 1839, +2776, 2528, 1859, +2778, 2535, 1929, +2779, 2534, 1991, +2780, 2535, 2071, +2782, 2538, 2158, +2784, 2536, 2248, +2791, 2552, 2360, +2803, 2569, 2485, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2813, 2581, 2533, +2826, 2762, 2506, +2826, 2762, 2506, +2826, 2762, 2505, +2826, 2762, 2505, +2826, 2762, 2505, +2826, 2762, 2505, +2826, 2761, 2505, +2826, 2761, 2505, +2826, 2761, 2505, +2826, 2761, 2506, +2826, 2761, 2507, +2826, 2761, 2509, +2826, 2761, 2510, +2826, 2760, 2508, +2826, 2760, 2508, +2826, 2762, 2520, +2826, 2764, 2535, +2826, 2763, 2548, +2826, 2763, 2571, +2826, 2767, 2613, +2826, 2769, 2662, +2826, 2779, 2732, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2784, 2763, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2623, +2826, 2823, 2625, +2826, 2823, 2628, +2826, 2822, 2631, +2826, 2821, 2638, +2826, 2822, 2651, +2826, 2823, 2668, +2826, 2819, 2690, +2826, 2823, 2740, +2826, 2825, 2794, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819, +2826, 2826, 2819] + } +} \ No newline at end of file diff --git a/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Photoshop/Log2-48nits/o_invShaped/test_hue-sat_32_LUT.3dl b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Photoshop/Log2-48nits/o_invShaped/test_hue-sat_32_LUT.3dl new file mode 100644 index 0000000000..7d112117cd --- /dev/null +++ b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Photoshop/Log2-48nits/o_invShaped/test_hue-sat_32_LUT.3dl @@ -0,0 +1,32769 @@ +0 33 66 99 132 165 198 231 264 297 330 363 396 429 462 495 528 561 594 627 660 693 726 759 792 825 858 891 924 957 990 1023 +0 0 0 +97 163 0 +201 318 0 +312 466 0 +427 609 0 +545 750 0 +667 888 0 +792 1025 0 +918 1160 0 +1046 1295 0 +1174 1429 0 +1304 1563 0 +1434 1696 0 +1565 1828 0 +1696 1961 0 +1827 2094 0 +1959 2226 0 +2090 2358 0 +2222 2491 0 +2354 2623 0 +2486 2755 0 +2618 2887 0 +2750 3019 0 +2882 3152 0 +3014 3284 0 +3146 3416 0 +3278 3548 0 +3410 3680 0 +3542 3812 0 +3674 3944 0 +3806 4076 0 +3939 4095 0 +163 0 97 +163 42 0 +318 300 0 +419 466 0 +512 609 0 +613 750 0 +719 888 0 +832 1025 0 +949 1160 0 +1069 1295 0 +1192 1429 0 +1318 1563 0 +1444 1696 0 +1572 1828 0 +1702 1961 0 +1831 2094 0 +1962 2226 0 +2093 2358 0 +2224 2491 0 +2355 2623 0 +2487 2755 0 +2619 2887 0 +2750 3019 0 +2883 3152 0 +3014 3284 0 +3146 3416 0 +3278 3548 0 +3410 3680 0 +3542 3812 0 +3674 3944 0 +3806 4076 0 +3939 4095 0 +318 0 201 +318 0 13 +318 93 0 +466 388 0 +606 609 0 +689 750 0 +781 888 0 +881 1025 0 +987 1160 0 +1099 1295 0 +1215 1429 0 +1335 1563 0 +1457 1696 0 +1582 1828 0 +1709 1961 0 +1837 2094 0 +1966 2226 0 +2096 2358 0 +2226 2491 0 +2357 2623 0 +2488 2755 0 +2620 2887 0 +2751 3019 0 +2883 3152 0 +3014 3284 0 +3147 3416 0 +3279 3548 0 +3410 3680 0 +3543 3812 0 +3674 3944 0 +3806 4076 0 +3939 4095 0 +466 0 312 +466 0 171 +466 0 0 +466 154 0 +609 485 0 +750 723 0 +852 888 0 +939 1025 0 +1033 1160 0 +1135 1295 0 +1244 1429 0 +1357 1563 0 +1475 1696 0 +1596 1828 0 +1719 1961 0 +1845 2094 0 +1972 2226 0 +2100 2358 0 +2230 2491 0 +2359 2623 0 +2490 2755 0 +2621 2887 0 +2752 3019 0 +2884 3152 0 +3015 3284 0 +3147 3416 0 +3279 3548 0 +3411 3680 0 +3543 3812 0 +3674 3944 0 +3806 4076 0 +3939 4095 0 +609 0 427 +609 0 322 +609 0 127 +609 0 0 +609 224 0 +750 587 0 +888 838 0 +1006 1025 0 +1089 1160 0 +1181 1295 0 +1280 1429 0 +1385 1563 0 +1496 1696 0 +1612 1828 0 +1732 1961 0 +1855 2094 0 +1979 2226 0 +2106 2358 0 +2234 2491 0 +2363 2623 0 +2493 2755 0 +2623 2887 0 +2754 3019 0 +2885 3152 0 +3016 3284 0 +3147 3416 0 +3279 3548 0 +3411 3680 0 +3543 3812 0 +3675 3944 0 +3807 4076 0 +3939 4095 0 +750 0 545 +750 0 467 +750 0 334 +750 0 59 +750 0 0 +750 304 0 +888 697 0 +1025 957 0 +1154 1160 0 +1234 1295 0 +1323 1429 0 +1421 1563 0 +1524 1696 0 +1634 1828 0 +1749 1961 0 +1867 2094 0 +1989 2226 0 +2113 2358 0 +2239 2491 0 +2367 2623 0 +2496 2755 0 +2625 2887 0 +2755 3019 0 +2886 3152 0 +3017 3284 0 +3148 3416 0 +3280 3548 0 +3411 3680 0 +3543 3812 0 +3675 3944 0 +3807 4076 0 +3939 4095 0 +888 0 667 +888 0 608 +888 0 515 +888 0 350 +888 0 0 +888 0 0 +888 392 0 +1025 811 0 +1160 1079 0 +1295 1292 0 +1376 1429 0 +1463 1563 0 +1559 1696 0 +1661 1828 0 +1770 1961 0 +1884 2094 0 +2002 2226 0 +2123 2358 0 +2247 2491 0 +2372 2623 0 +2500 2755 0 +2628 2887 0 +2758 3019 0 +2888 3152 0 +3018 3284 0 +3149 3416 0 +3280 3548 0 +3412 3680 0 +3544 3812 0 +3675 3944 0 +3807 4076 0 +3939 4095 0 +1025 0 792 +1025 0 748 +1025 0 681 +1025 0 573 +1025 0 371 +1025 0 0 +1025 0 0 +1025 488 0 +1160 929 0 +1295 1204 0 +1429 1419 0 +1515 1563 0 +1601 1696 0 +1696 1828 0 +1797 1961 0 +1905 2094 0 +2018 2226 0 +2136 2358 0 +2256 2491 0 +2380 2623 0 +2505 2755 0 +2633 2887 0 +2761 3019 0 +2890 3152 0 +3020 3284 0 +3151 3416 0 +3281 3548 0 +3413 3680 0 +3544 3812 0 +3676 3944 0 +3808 4076 0 +3939 4095 0 +1160 0 918 +1160 0 885 +1160 0 836 +1160 0 762 +1160 0 640 +1160 0 397 +1160 0 0 +1160 0 0 +1160 592 0 +1295 1051 0 +1429 1330 0 +1563 1548 0 +1653 1696 0 +1738 1828 0 +1831 1961 0 +1932 2094 0 +2039 2226 0 +2152 2358 0 +2269 2491 0 +2390 2623 0 +2513 2755 0 +2638 2887 0 +2765 3019 0 +2893 3152 0 +3022 3284 0 +3152 3416 0 +3283 3548 0 +3414 3680 0 +3545 3812 0 +3676 3944 0 +3808 4076 0 +3940 4095 0 +1295 0 1046 +1295 0 1021 +1295 0 985 +1295 0 934 +1295 0 853 +1295 0 717 +1295 0 431 +1295 0 0 +1295 0 0 +1295 702 0 +1429 1174 0 +1563 1458 0 +1696 1677 0 +1789 1828 0 +1873 1961 0 +1966 2094 0 +2066 2226 0 +2173 2358 0 +2285 2491 0 +2402 2623 0 +2523 2755 0 +2646 2887 0 +2771 3019 0 +2898 3152 0 +3025 3284 0 +3155 3416 0 +3285 3548 0 +3415 3680 0 +3546 3812 0 +3677 3944 0 +3808 4076 0 +3940 4095 0 +1429 0 1174 +1429 0 1156 +1429 0 1130 +1429 0 1092 +1429 0 1037 +1429 0 951 +1429 0 803 +1429 0 471 +1429 0 0 +1429 0 0 +1429 816 0 +1563 1301 0 +1696 1587 0 +1828 1807 0 +1923 1961 0 +2007 2094 0 +2100 2226 0 +2200 2358 0 +2306 2491 0 +2419 2623 0 +2535 2755 0 +2655 2887 0 +2778 3019 0 +2903 3152 0 +3030 3284 0 +3158 3416 0 +3287 3548 0 +3417 3680 0 +3547 3812 0 +3678 3944 0 +3809 4076 0 +3941 4095 0 +1563 0 1304 +1563 0 1290 +1563 0 1271 +1563 0 1244 +1563 0 1205 +1563 0 1148 +1563 0 1057 +1563 0 897 +1563 0 523 +1563 0 0 +1563 0 0 +1563 934 0 +1696 1427 0 +1828 1716 0 +1961 1938 0 +2058 2094 0 +2141 2226 0 +2233 2358 0 +2333 2491 0 +2440 2623 0 +2552 2755 0 +2668 2887 0 +2788 3019 0 +2911 3152 0 +3035 3284 0 +3162 3416 0 +3290 3548 0 +3419 3680 0 +3549 3812 0 +3679 3944 0 +3810 4076 0 +3941 4095 0 +1696 0 1434 +1696 0 1424 +1696 0 1410 +1696 0 1390 +1696 0 1362 +1696 0 1322 +1696 0 1262 +1696 0 1167 +1696 0 998 +1696 0 580 +1696 0 0 +1696 0 0 +1696 1056 0 +1828 1557 0 +1961 1847 0 +2094 2069 0 +2191 2226 0 +2275 2358 0 +2367 2491 0 +2466 2623 0 +2573 2755 0 +2684 2887 0 +2800 3019 0 +2920 3152 0 +3043 3284 0 +3168 3416 0 +3294 3548 0 +3422 3680 0 +3552 3812 0 +3681 3944 0 +3812 4076 0 +3942 4095 0 +1828 0 1565 +1828 0 1557 +1828 0 1547 +1828 0 1532 +1828 0 1512 +1828 0 1484 +1828 0 1442 +1828 0 1381 +1828 0 1283 +1828 0 1106 +1828 0 650 +1828 0 0 +1828 0 0 +1828 1180 0 +1961 1686 0 +2094 1977 0 +2226 2200 0 +2325 2358 0 +2408 2491 0 +2500 2623 0 +2599 2755 0 +2705 2887 0 +2816 3019 0 +2933 3152 0 +3052 3284 0 +3175 3416 0 +3300 3548 0 +3427 3680 0 +3554 3812 0 +3683 3944 0 +3813 4076 0 +3944 4095 0 +1961 0 1696 +1961 0 1690 +1961 0 1682 +1961 0 1672 +1961 0 1657 +1961 0 1636 +1961 0 1607 +1961 0 1565 +1961 0 1503 +1961 0 1402 +1961 0 1220 +1961 0 726 +1961 0 0 +1961 0 0 +1961 1306 0 +2094 1816 0 +2226 2108 0 +2358 2332 0 +2458 2491 0 +2541 2623 0 +2632 2755 0 +2732 2887 0 +2837 3019 0 +2949 3152 0 +3065 3284 0 +3184 3416 0 +3307 3548 0 +3432 3680 0 +3559 3812 0 +3687 3944 0 +3816 4076 0 +3946 4095 0 +2094 0 1827 +2094 0 1823 +2094 0 1817 +2094 0 1809 +2094 0 1798 +2094 0 1783 +2094 0 1763 +2094 0 1733 +2094 0 1691 +2094 0 1626 +2094 0 1524 +2094 0 1336 +2094 0 814 +2094 0 0 +2094 0 0 +2094 1433 0 +2226 1946 0 +2358 2239 0 +2491 2463 0 +2590 2623 0 +2673 2755 0 +2765 2887 0 +2864 3019 0 +2970 3152 0 +3081 3284 0 +3197 3416 0 +3317 3548 0 +3440 3680 0 +3564 3812 0 +3691 3944 0 +3819 4076 0 +3948 4095 0 +2226 0 1959 +2226 0 1956 +2226 0 1951 +2226 0 1945 +2226 0 1937 +2226 0 1926 +2226 0 1911 +2226 0 1890 +2226 0 1860 +2226 0 1817 +2226 0 1753 +2226 0 1648 +2226 0 1457 +2226 0 907 +2226 0 0 +2226 0 0 +2226 1562 0 +2358 2078 0 +2491 2371 0 +2623 2595 0 +2723 2755 0 +2806 2887 0 +2897 3019 0 +2996 3152 0 +3102 3284 0 +3213 3416 0 +3329 3548 0 +3449 3680 0 +3572 3812 0 +3696 3944 0 +3823 4076 0 +3951 4095 0 +2358 0 2090 +2358 0 2088 +2358 0 2085 +2358 0 2080 +2358 0 2074 +2358 0 2066 +2358 0 2055 +2358 0 2040 +2358 0 2019 +2358 0 1989 +2358 0 1946 +2358 0 1880 +2358 0 1775 +2358 0 1580 +2358 0 1009 +2358 0 0 +2358 0 0 +2358 1692 0 +2491 2209 0 +2623 2503 0 +2755 2727 0 +2856 2887 0 +2938 3019 0 +3030 3152 0 +3128 3284 0 +3234 3416 0 +3346 3548 0 +3462 3680 0 +3581 3812 0 +3704 3944 0 +3828 4076 0 +3955 4095 0 +2491 0 2222 +2491 0 2220 +2491 0 2218 +2491 0 2215 +2491 0 2210 +2491 0 2204 +2491 0 2196 +2491 0 2185 +2491 0 2170 +2491 0 2149 +2491 0 2119 +2491 0 2075 +2491 0 2009 +2491 0 1903 +2491 0 1706 +2491 0 1120 +2491 0 0 +2491 0 0 +2491 1822 0 +2623 2340 0 +2755 2635 0 +2887 2859 0 +2988 3019 0 +3071 3152 0 +3162 3284 0 +3261 3416 0 +3367 3548 0 +3478 3680 0 +3594 3812 0 +3713 3944 0 +3836 4076 0 +3961 4095 0 +2623 0 2354 +2623 0 2352 +2623 0 2351 +2623 0 2348 +2623 0 2345 +2623 0 2341 +2623 0 2335 +2623 0 2327 +2623 0 2315 +2623 0 2300 +2623 0 2278 +2623 0 2248 +2623 0 2205 +2623 0 2138 +2623 0 2032 +2623 0 1833 +2623 0 1232 +2623 0 0 +2623 0 0 +2623 1952 0 +2755 2473 0 +2887 2767 0 +3019 2991 0 +3120 3152 0 +3203 3284 0 +3294 3416 0 +3393 3548 0 +3499 3680 0 +3610 3812 0 +3726 3944 0 +3846 4076 0 +3968 4095 0 +2755 0 2486 +2755 0 2485 +2755 0 2484 +2755 0 2482 +2755 0 2479 +2755 0 2476 +2755 0 2472 +2755 0 2466 +2755 0 2457 +2755 0 2446 +2755 0 2431 +2755 0 2409 +2755 0 2379 +2755 0 2335 +2755 0 2269 +2755 0 2162 +2755 0 1962 +2755 0 1353 +2755 0 0 +2755 0 0 +2755 2083 0 +2887 2604 0 +3019 2898 0 +3152 3123 0 +3252 3284 0 +3335 3416 0 +3426 3548 0 +3525 3680 0 +3631 3812 0 +3742 3944 0 +3858 4076 0 +3978 4095 0 +2887 0 2618 +2887 0 2617 +2887 0 2616 +2887 0 2615 +2887 0 2613 +2887 0 2611 +2887 0 2607 +2887 0 2603 +2887 0 2597 +2887 0 2589 +2887 0 2577 +2887 0 2562 +2887 0 2541 +2887 0 2510 +2887 0 2466 +2887 0 2400 +2887 0 2292 +2887 0 2091 +2887 0 1472 +2887 0 0 +2887 0 0 +2887 2215 0 +3019 2735 0 +3152 3031 0 +3284 3254 0 +3385 3416 0 +3467 3548 0 +3558 3680 0 +3657 3812 0 +3763 3944 0 +3874 4076 0 +3990 4095 0 +3019 0 2750 +3019 0 2749 +3019 0 2748 +3019 0 2747 +3019 0 2746 +3019 0 2744 +3019 0 2742 +3019 0 2738 +3019 0 2734 +3019 0 2728 +3019 0 2720 +3019 0 2708 +3019 0 2693 +3019 0 2672 +3019 0 2641 +3019 0 2597 +3019 0 2530 +3019 0 2422 +3019 0 2220 +3019 0 1594 +3019 0 0 +3019 0 0 +3019 2346 0 +3152 2868 0 +3284 3162 0 +3416 3387 0 +3516 3548 0 +3599 3680 0 +3691 3812 0 +3790 3944 0 +3895 4076 0 +4007 4095 0 +3152 0 2882 +3152 0 2881 +3152 0 2881 +3152 0 2880 +3152 0 2879 +3152 0 2878 +3152 0 2876 +3152 0 2873 +3152 0 2870 +3152 0 2866 +3152 0 2860 +3152 0 2851 +3152 0 2840 +3152 0 2825 +3152 0 2803 +3152 0 2773 +3152 0 2729 +3152 0 2662 +3152 0 2554 +3152 0 2352 +3152 0 1720 +3152 0 0 +3152 0 0 +3152 2478 0 +3284 2999 0 +3416 3294 0 +3548 3519 0 +3649 3680 0 +3732 3812 0 +3823 3944 0 +3922 4076 0 +4027 4095 0 +3284 0 3014 +3284 0 3014 +3284 0 3013 +3284 0 3012 +3284 0 3012 +3284 0 3011 +3284 0 3009 +3284 0 3008 +3284 0 3005 +3284 0 3002 +3284 0 2997 +3284 0 2991 +3284 0 2983 +3284 0 2972 +3284 0 2956 +3284 0 2935 +3284 0 2904 +3284 0 2860 +3284 0 2793 +3284 0 2684 +3284 0 2481 +3284 0 1844 +3284 0 0 +3284 0 0 +3284 2609 0 +3416 3132 0 +3548 3426 0 +3680 3651 0 +3781 3812 0 +3864 3944 0 +3955 4076 0 +4054 4095 0 +3416 0 3146 +3416 0 3146 +3416 0 3145 +3416 0 3145 +3416 0 3144 +3416 0 3144 +3416 0 3143 +3416 0 3141 +3416 0 3139 +3416 0 3137 +3416 0 3134 +3416 0 3129 +3416 0 3123 +3416 0 3115 +3416 0 3104 +3416 0 3088 +3416 0 3067 +3416 0 3036 +3416 0 2992 +3416 0 2925 +3416 0 2816 +3416 0 2613 +3416 0 1977 +3416 0 0 +3416 0 0 +3416 2741 0 +3548 3264 0 +3680 3558 0 +3812 3783 0 +3913 3944 0 +3996 4076 0 +4087 4095 0 +3548 0 3278 +3548 0 3278 +3548 0 3278 +3548 0 3277 +3548 0 3277 +3548 0 3276 +3548 0 3276 +3548 0 3275 +3548 0 3273 +3548 0 3271 +3548 0 3269 +3548 0 3266 +3548 0 3261 +3548 0 3255 +3548 0 3247 +3548 0 3236 +3548 0 3220 +3548 0 3198 +3548 0 3168 +3548 0 3124 +3548 0 3056 +3548 0 2948 +3548 0 2745 +3548 0 2104 +3548 0 0 +3548 0 0 +3548 2873 0 +3680 3396 0 +3812 3691 0 +3944 3915 0 +4045 4076 0 +4095 4095 0 +3680 0 3410 +3680 0 3410 +3680 0 3410 +3680 0 3410 +3680 0 3409 +3680 0 3409 +3680 0 3408 +3680 0 3408 +3680 0 3406 +3680 0 3405 +3680 0 3403 +3680 0 3401 +3680 0 3398 +3680 0 3393 +3680 0 3387 +3680 0 3379 +3680 0 3367 +3680 0 3352 +3680 0 3330 +3680 0 3300 +3680 0 3255 +3680 0 3188 +3680 0 3080 +3680 0 2876 +3680 0 2237 +3680 0 0 +3680 0 0 +3680 3005 0 +3812 3528 0 +3944 3822 0 +4076 4047 0 +4095 4095 0 +3812 0 3542 +3812 0 3542 +3812 0 3542 +3812 0 3542 +3812 0 3541 +3812 0 3541 +3812 0 3541 +3812 0 3540 +3812 0 3540 +3812 0 3538 +3812 0 3537 +3812 0 3535 +3812 0 3533 +3812 0 3530 +3812 0 3525 +3812 0 3519 +3812 0 3511 +3812 0 3499 +3812 0 3484 +3812 0 3462 +3812 0 3432 +3812 0 3387 +3812 0 3320 +3812 0 3211 +3812 0 3008 +3812 0 2367 +3812 0 0 +3812 0 0 +3812 3137 0 +3944 3660 0 +4076 3954 0 +4095 4095 0 +3944 0 3674 +3944 0 3674 +3944 0 3674 +3944 0 3674 +3944 0 3674 +3944 0 3674 +3944 0 3673 +3944 0 3673 +3944 0 3672 +3944 0 3671 +3944 0 3670 +3944 0 3669 +3944 0 3667 +3944 0 3665 +3944 0 3661 +3944 0 3657 +3944 0 3651 +3944 0 3643 +3944 0 3631 +3944 0 3616 +3944 0 3594 +3944 0 3564 +3944 0 3520 +3944 0 3452 +3944 0 3344 +3944 0 3140 +3944 0 2497 +3944 0 0 +3944 0 0 +3944 3269 0 +4076 3791 0 +4095 4087 0 +4076 0 3806 +4076 0 3806 +4076 0 3806 +4076 0 3806 +4076 0 3806 +4076 0 3806 +4076 0 3805 +4076 0 3805 +4076 0 3805 +4076 0 3804 +4076 0 3803 +4076 0 3803 +4076 0 3801 +4076 0 3799 +4076 0 3797 +4076 0 3793 +4076 0 3789 +4076 0 3783 +4076 0 3774 +4076 0 3763 +4076 0 3748 +4076 0 3726 +4076 0 3696 +4076 0 3651 +4076 0 3584 +4076 0 3475 +4076 0 3271 +4076 0 2626 +4076 0 0 +4076 0 0 +4076 3401 0 +4095 3924 0 +4095 0 3939 +4095 0 3939 +4095 0 3938 +4095 0 3938 +4095 0 3938 +4095 0 3938 +4095 0 3938 +4095 0 3938 +4095 0 3937 +4095 0 3937 +4095 0 3937 +4095 0 3936 +4095 0 3935 +4095 0 3933 +4095 0 3932 +4095 0 3929 +4095 0 3926 +4095 0 3921 +4095 0 3915 +4095 0 3907 +4095 0 3896 +4095 0 3880 +4095 0 3859 +4095 0 3828 +4095 0 3784 +4095 0 3716 +4095 0 3608 +4095 0 3404 +4095 0 2761 +4095 0 0 +4095 0 0 +4095 3533 0 +0 97 163 +0 163 42 +13 318 0 +171 466 0 +322 609 0 +467 750 0 +608 888 0 +748 1025 0 +885 1160 0 +1021 1295 0 +1156 1429 0 +1290 1563 0 +1424 1696 0 +1557 1828 0 +1690 1961 0 +1823 2094 0 +1956 2226 0 +2088 2358 0 +2220 2491 0 +2352 2623 0 +2485 2755 0 +2617 2887 0 +2749 3019 0 +2881 3152 0 +3014 3284 0 +3146 3416 0 +3278 3548 0 +3410 3680 0 +3542 3812 0 +3674 3944 0 +3806 4076 0 +3939 4095 0 +42 0 163 +131 131 131 +229 295 86 +333 450 15 +444 598 0 +559 741 0 +678 882 0 +800 1020 0 +924 1157 0 +1050 1292 0 +1178 1427 0 +1307 1561 0 +1436 1695 0 +1566 1828 0 +1697 1961 0 +1828 2093 0 +1959 2226 0 +2091 2358 0 +2223 2491 0 +2354 2623 0 +2486 2755 0 +2618 2887 0 +2750 3019 0 +2882 3152 0 +3014 3283 0 +3146 3416 0 +3278 3548 0 +3410 3680 0 +3542 3812 0 +3674 3944 0 +3806 4076 0 +3939 4095 0 +300 0 318 +295 86 229 +295 174 86 +450 432 15 +551 598 0 +644 741 0 +745 882 0 +852 1020 0 +964 1157 0 +1081 1292 0 +1201 1427 0 +1325 1561 0 +1450 1695 0 +1576 1828 0 +1705 1961 0 +1834 2093 0 +1963 2226 0 +2094 2358 0 +2225 2491 0 +2356 2623 0 +2488 2755 0 +2619 2887 0 +2751 3019 0 +2883 3152 0 +3014 3283 0 +3146 3416 0 +3278 3548 0 +3410 3680 0 +3543 3812 0 +3674 3944 0 +3806 4076 0 +3939 4095 0 +466 0 419 +450 15 333 +450 15 145 +450 225 15 +598 520 0 +738 741 0 +822 882 0 +914 1020 0 +1013 1157 0 +1119 1292 0 +1231 1427 0 +1347 1561 0 +1467 1695 0 +1590 1828 0 +1715 1961 0 +1841 2093 0 +1969 2226 0 +2098 2358 0 +2228 2491 0 +2358 2623 0 +2489 2755 0 +2620 2887 0 +2752 3019 0 +2883 3152 0 +3015 3283 0 +3147 3416 0 +3279 3548 0 +3411 3680 0 +3543 3812 0 +3674 3944 0 +3806 4076 0 +3939 4095 0 +609 0 512 +598 0 444 +598 0 303 +598 0 0 +598 286 0 +741 616 0 +882 855 0 +985 1020 0 +1071 1157 0 +1166 1292 0 +1267 1427 0 +1376 1561 0 +1489 1695 0 +1607 1828 0 +1728 1961 0 +1851 2093 0 +1977 2226 0 +2104 2358 0 +2233 2491 0 +2362 2623 0 +2492 2755 0 +2622 2887 0 +2753 3019 0 +2885 3152 0 +3016 3283 0 +3147 3416 0 +3279 3548 0 +3411 3680 0 +3543 3812 0 +3675 3944 0 +3807 4076 0 +3939 4095 0 +750 0 613 +741 0 559 +741 0 453 +741 0 258 +741 0 0 +741 356 0 +882 719 0 +1020 970 0 +1139 1157 0 +1221 1292 0 +1313 1427 0 +1412 1561 0 +1517 1695 0 +1629 1828 0 +1745 1961 0 +1864 2093 0 +1987 2226 0 +2111 2358 0 +2238 2491 0 +2366 2623 0 +2495 2755 0 +2625 2887 0 +2755 3019 0 +2886 3152 0 +3017 3283 0 +3148 3416 0 +3280 3548 0 +3411 3680 0 +3543 3812 0 +3675 3944 0 +3807 4076 0 +3939 4095 0 +888 0 719 +882 0 678 +882 0 599 +882 0 466 +882 0 190 +882 0 0 +882 436 0 +1020 829 0 +1157 1089 0 +1286 1292 0 +1366 1427 0 +1456 1561 0 +1552 1695 0 +1656 1828 0 +1766 1961 0 +1881 2093 0 +1999 2226 0 +2121 2358 0 +2245 2491 0 +2372 2623 0 +2499 2755 0 +2628 2887 0 +2757 3019 0 +2888 3152 0 +3018 3283 0 +3149 3416 0 +3280 3548 0 +3412 3680 0 +3544 3812 0 +3675 3944 0 +3807 4076 0 +3939 4095 0 +1025 0 832 +1020 0 800 +1020 0 740 +1020 0 647 +1020 0 482 +1020 0 81 +1020 0 0 +1020 524 0 +1157 943 0 +1292 1211 0 +1427 1424 0 +1508 1561 0 +1596 1695 0 +1691 1828 0 +1793 1961 0 +1902 2093 0 +2016 2226 0 +2134 2358 0 +2255 2491 0 +2379 2623 0 +2505 2755 0 +2632 2887 0 +2760 3019 0 +2890 3152 0 +3020 3283 0 +3151 3416 0 +3281 3548 0 +3413 3680 0 +3544 3812 0 +3676 3944 0 +3807 4076 0 +3939 4095 0 +1160 0 949 +1157 0 924 +1157 0 879 +1157 0 813 +1157 0 705 +1157 0 503 +1157 0 0 +1157 0 0 +1157 620 0 +1292 1062 0 +1427 1336 0 +1561 1552 0 +1647 1695 0 +1733 1828 0 +1828 1961 0 +1929 2093 0 +2037 2226 0 +2150 2358 0 +2268 2491 0 +2388 2623 0 +2512 2755 0 +2638 2887 0 +2765 3019 0 +2893 3152 0 +3022 3283 0 +3152 3416 0 +3283 3548 0 +3414 3680 0 +3545 3812 0 +3676 3944 0 +3808 4076 0 +3940 4095 0 +1295 0 1069 +1292 0 1050 +1292 0 1017 +1292 0 968 +1292 0 894 +1292 0 772 +1292 0 529 +1292 0 0 +1292 0 0 +1292 724 0 +1427 1182 0 +1561 1463 0 +1695 1680 0 +1785 1828 0 +1870 1961 0 +1963 2093 0 +2064 2226 0 +2171 2358 0 +2284 2491 0 +2401 2623 0 +2522 2755 0 +2645 2887 0 +2770 3019 0 +2897 3152 0 +3025 3283 0 +3154 3416 0 +3284 3548 0 +3415 3680 0 +3546 3812 0 +3677 3944 0 +3808 4076 0 +3940 4095 0 +1429 0 1192 +1427 0 1178 +1427 0 1153 +1427 0 1118 +1427 0 1065 +1427 0 985 +1427 0 849 +1427 0 562 +1427 0 0 +1427 0 0 +1427 833 0 +1561 1307 0 +1695 1590 0 +1828 1810 0 +1920 1961 0 +2005 2093 0 +2098 2226 0 +2199 2358 0 +2305 2491 0 +2417 2623 0 +2535 2755 0 +2655 2887 0 +2777 3019 0 +2903 3152 0 +3029 3283 0 +3158 3416 0 +3287 3548 0 +3417 3680 0 +3547 3812 0 +3678 3944 0 +3809 4076 0 +3941 4095 0 +1563 0 1318 +1561 0 1307 +1561 0 1288 +1561 0 1262 +1561 0 1225 +1561 0 1170 +1561 0 1084 +1561 0 935 +1561 0 605 +1561 0 0 +1561 0 0 +1561 948 0 +1695 1432 0 +1828 1719 0 +1961 1940 0 +2056 2093 0 +2140 2226 0 +2232 2358 0 +2332 2491 0 +2439 2623 0 +2551 2755 0 +2667 2887 0 +2787 3019 0 +2910 3152 0 +3035 3283 0 +3162 3416 0 +3290 3548 0 +3419 3680 0 +3549 3812 0 +3679 3944 0 +3810 4076 0 +3941 4095 0 +1696 0 1444 +1695 0 1436 +1695 0 1422 +1695 0 1403 +1695 0 1376 +1695 0 1337 +1695 0 1279 +1695 0 1188 +1695 0 1029 +1695 0 653 +1695 0 0 +1695 0 0 +1695 1066 0 +1828 1560 0 +1961 1849 0 +2093 2070 0 +2190 2226 0 +2273 2358 0 +2366 2491 0 +2465 2623 0 +2572 2755 0 +2684 2887 0 +2800 3019 0 +2920 3152 0 +3042 3283 0 +3168 3416 0 +3294 3548 0 +3422 3680 0 +3551 3812 0 +3681 3944 0 +3811 4076 0 +3942 4095 0 +1828 0 1572 +1828 0 1566 +1828 0 1556 +1828 0 1542 +1828 0 1522 +1828 0 1494 +1828 0 1454 +1828 0 1394 +1828 0 1300 +1828 0 1131 +1828 0 713 +1828 0 0 +1828 0 0 +1828 1188 0 +1961 1689 0 +2093 1979 0 +2226 2201 0 +2324 2358 0 +2407 2491 0 +2499 2623 0 +2598 2755 0 +2705 2887 0 +2816 3019 0 +2932 3152 0 +3052 3283 0 +3175 3416 0 +3300 3548 0 +3426 3680 0 +3554 3812 0 +3683 3944 0 +3813 4076 0 +3944 4095 0 +1961 0 1702 +1961 0 1697 +1961 0 1689 +1961 0 1679 +1961 0 1664 +1961 0 1644 +1961 0 1615 +1961 0 1574 +1961 0 1513 +1961 0 1415 +1961 0 1238 +1961 0 780 +1961 0 0 +1961 0 0 +1961 1312 0 +2093 1818 0 +2226 2109 0 +2358 2332 0 +2457 2491 0 +2540 2623 0 +2632 2755 0 +2731 2887 0 +2837 3019 0 +2949 3152 0 +3065 3283 0 +3184 3416 0 +3307 3548 0 +3432 3680 0 +3559 3812 0 +3687 3944 0 +3816 4076 0 +3946 4095 0 +2094 0 1831 +2093 0 1828 +2093 0 1822 +2093 0 1814 +2093 0 1804 +2093 0 1789 +2093 0 1768 +2093 0 1739 +2093 0 1698 +2093 0 1635 +2093 0 1534 +2093 0 1351 +2093 0 859 +2093 0 0 +2093 0 0 +2093 1438 0 +2226 1948 0 +2358 2240 0 +2491 2464 0 +2590 2623 0 +2673 2755 0 +2764 2887 0 +2863 3019 0 +2970 3152 0 +3081 3283 0 +3197 3416 0 +3317 3548 0 +3439 3680 0 +3564 3812 0 +3691 3944 0 +3819 4076 0 +3948 4095 0 +2226 0 1962 +2226 0 1959 +2226 0 1955 +2226 0 1949 +2226 0 1941 +2226 0 1930 +2226 0 1915 +2226 0 1894 +2226 0 1865 +2226 0 1823 +2226 0 1759 +2226 0 1656 +2226 0 1469 +2226 0 944 +2226 0 0 +2226 0 0 +2226 1565 0 +2358 2079 0 +2491 2372 0 +2623 2595 0 +2723 2755 0 +2805 2887 0 +2897 3019 0 +2996 3152 0 +3102 3283 0 +3213 3416 0 +3329 3548 0 +3449 3680 0 +3572 3812 0 +3696 3944 0 +3823 4076 0 +3951 4095 0 +2358 0 2093 +2358 0 2091 +2358 0 2087 +2358 0 2083 +2358 0 2077 +2358 0 2069 +2358 0 2058 +2358 0 2043 +2358 0 2022 +2358 0 1993 +2358 0 1950 +2358 0 1885 +2358 0 1781 +2358 0 1589 +2358 0 1039 +2358 0 0 +2358 0 0 +2358 1694 0 +2491 2210 0 +2623 2503 0 +2755 2727 0 +2855 2887 0 +2938 3019 0 +3029 3152 0 +3128 3283 0 +3234 3416 0 +3346 3548 0 +3462 3680 0 +3581 3812 0 +3704 3944 0 +3828 4076 0 +3955 4095 0 +2491 0 2224 +2491 0 2223 +2491 0 2220 +2491 0 2217 +2491 0 2212 +2491 0 2206 +2491 0 2199 +2491 0 2187 +2491 0 2172 +2491 0 2151 +2491 0 2121 +2491 0 2078 +2491 0 2013 +2491 0 1907 +2491 0 1713 +2491 0 1143 +2491 0 0 +2491 0 0 +2491 1824 0 +2623 2341 0 +2755 2635 0 +2887 2859 0 +2987 3019 0 +3070 3152 0 +3162 3283 0 +3261 3416 0 +3367 3548 0 +3478 3680 0 +3594 3812 0 +3713 3944 0 +3836 4076 0 +3961 4095 0 +2623 0 2355 +2623 0 2354 +2623 0 2352 +2623 0 2350 +2623 0 2347 +2623 0 2342 +2623 0 2336 +2623 0 2328 +2623 0 2317 +2623 0 2302 +2623 0 2281 +2623 0 2250 +2623 0 2207 +2623 0 2141 +2623 0 2035 +2623 0 1838 +2623 0 1251 +2623 0 0 +2623 0 0 +2623 1954 0 +2755 2473 0 +2887 2767 0 +3019 2991 0 +3120 3152 0 +3203 3283 0 +3294 3416 0 +3393 3548 0 +3499 3680 0 +3610 3812 0 +3726 3944 0 +3845 4076 0 +3968 4095 0 +2755 0 2487 +2755 0 2486 +2755 0 2485 +2755 0 2483 +2755 0 2481 +2755 0 2477 +2755 0 2473 +2755 0 2467 +2755 0 2459 +2755 0 2448 +2755 0 2432 +2755 0 2411 +2755 0 2381 +2755 0 2337 +2755 0 2271 +2755 0 2164 +2755 0 1966 +2755 0 1367 +2755 0 0 +2755 0 0 +2755 2084 0 +2887 2604 0 +3019 2898 0 +3152 3123 0 +3252 3283 0 +3335 3416 0 +3426 3548 0 +3525 3680 0 +3631 3812 0 +3742 3944 0 +3858 4076 0 +3978 4095 0 +2887 0 2619 +2887 0 2618 +2887 0 2617 +2887 0 2616 +2887 0 2614 +2887 0 2612 +2887 0 2608 +2887 0 2604 +2887 0 2598 +2887 0 2589 +2887 0 2578 +2887 0 2563 +2887 0 2542 +2887 0 2511 +2887 0 2467 +2887 0 2401 +2887 0 2294 +2887 0 2094 +2887 0 1483 +2887 0 0 +2887 0 0 +2887 2215 0 +3019 2735 0 +3152 3031 0 +3283 3254 0 +3385 3416 0 +3467 3548 0 +3558 3680 0 +3657 3812 0 +3763 3944 0 +3874 4076 0 +3990 4095 0 +3019 0 2750 +3019 0 2750 +3019 0 2749 +3019 0 2748 +3019 0 2747 +3019 0 2745 +3019 0 2742 +3019 0 2739 +3019 0 2735 +3019 0 2729 +3019 0 2720 +3019 0 2709 +3019 0 2694 +3019 0 2672 +3019 0 2642 +3019 0 2598 +3019 0 2531 +3019 0 2424 +3019 0 2222 +3019 0 1602 +3019 0 0 +3019 0 0 +3019 2346 0 +3152 2868 0 +3283 3162 0 +3416 3387 0 +3516 3548 0 +3599 3680 0 +3691 3812 0 +3790 3944 0 +3895 4076 0 +4006 4095 0 +3152 0 2883 +3152 0 2882 +3152 0 2881 +3152 0 2881 +3152 0 2880 +3152 0 2878 +3152 0 2877 +3152 0 2874 +3152 0 2871 +3152 0 2866 +3152 0 2860 +3152 0 2852 +3152 0 2841 +3152 0 2825 +3152 0 2804 +3152 0 2773 +3152 0 2729 +3152 0 2663 +3152 0 2555 +3152 0 2353 +3152 0 1726 +3152 0 0 +3152 0 0 +3152 2478 0 +3283 2999 0 +3416 3294 0 +3548 3519 0 +3649 3680 0 +3731 3812 0 +3823 3944 0 +3922 4076 0 +4027 4095 0 +3284 0 3014 +3283 0 3014 +3283 0 3014 +3283 0 3013 +3283 0 3012 +3283 0 3011 +3283 0 3010 +3283 0 3008 +3283 0 3005 +3283 0 3002 +3283 0 2998 +3283 0 2992 +3283 0 2983 +3283 0 2972 +3283 0 2957 +3283 0 2935 +3283 0 2905 +3283 0 2860 +3283 0 2793 +3283 0 2685 +3283 0 2482 +3283 0 1849 +3283 0 0 +3283 0 0 +3283 2609 0 +3416 3132 0 +3548 3426 0 +3680 3651 0 +3781 3812 0 +3864 3944 0 +3955 4076 0 +4054 4095 0 +3416 0 3146 +3416 0 3146 +3416 0 3146 +3416 0 3145 +3416 0 3145 +3416 0 3144 +3416 0 3143 +3416 0 3141 +3416 0 3140 +3416 0 3137 +3416 0 3134 +3416 0 3129 +3416 0 3123 +3416 0 3115 +3416 0 3104 +3416 0 3088 +3416 0 3067 +3416 0 3036 +3416 0 2992 +3416 0 2925 +3416 0 2817 +3416 0 2614 +3416 0 1981 +3416 0 0 +3416 0 0 +3416 2741 0 +3548 3264 0 +3680 3558 0 +3812 3783 0 +3913 3944 0 +3996 4076 0 +4087 4095 0 +3548 0 3278 +3548 0 3278 +3548 0 3278 +3548 0 3278 +3548 0 3277 +3548 0 3277 +3548 0 3276 +3548 0 3275 +3548 0 3273 +3548 0 3272 +3548 0 3269 +3548 0 3266 +3548 0 3261 +3548 0 3255 +3548 0 3247 +3548 0 3236 +3548 0 3220 +3548 0 3199 +3548 0 3168 +3548 0 3124 +3548 0 3057 +3548 0 2948 +3548 0 2745 +3548 0 2107 +3548 0 0 +3548 0 0 +3548 2873 0 +3680 3396 0 +3812 3691 0 +3944 3915 0 +4045 4076 0 +4095 4095 0 +3680 0 3410 +3680 0 3410 +3680 0 3410 +3680 0 3410 +3680 0 3409 +3680 0 3409 +3680 0 3408 +3680 0 3408 +3680 0 3407 +3680 0 3405 +3680 0 3403 +3680 0 3401 +3680 0 3398 +3680 0 3393 +3680 0 3387 +3680 0 3379 +3680 0 3368 +3680 0 3352 +3680 0 3331 +3680 0 3300 +3680 0 3256 +3680 0 3188 +3680 0 3080 +3680 0 2877 +3680 0 2239 +3680 0 0 +3680 0 0 +3680 3005 0 +3812 3528 0 +3944 3822 0 +4076 4047 0 +4095 4095 0 +3812 0 3542 +3812 0 3542 +3812 0 3542 +3812 0 3542 +3812 0 3542 +3812 0 3541 +3812 0 3541 +3812 0 3540 +3812 0 3540 +3812 0 3538 +3812 0 3537 +3812 0 3536 +3812 0 3533 +3812 0 3530 +3812 0 3525 +3812 0 3519 +3812 0 3511 +3812 0 3499 +3812 0 3484 +3812 0 3462 +3812 0 3432 +3812 0 3388 +3812 0 3321 +3812 0 3212 +3812 0 3009 +3812 0 2369 +3812 0 0 +3812 0 0 +3812 3137 0 +3944 3660 0 +4076 3954 0 +4095 4095 0 +3944 0 3674 +3944 0 3674 +3944 0 3674 +3944 0 3674 +3944 0 3674 +3944 0 3674 +3944 0 3673 +3944 0 3673 +3944 0 3672 +3944 0 3671 +3944 0 3671 +3944 0 3669 +3944 0 3667 +3944 0 3665 +3944 0 3662 +3944 0 3657 +3944 0 3651 +3944 0 3643 +3944 0 3632 +3944 0 3616 +3944 0 3595 +3944 0 3564 +3944 0 3520 +3944 0 3452 +3944 0 3344 +3944 0 3140 +3944 0 2498 +3944 0 0 +3944 0 0 +3944 3269 0 +4076 3792 0 +4095 4087 0 +4076 0 3806 +4076 0 3806 +4076 0 3806 +4076 0 3806 +4076 0 3806 +4076 0 3806 +4076 0 3805 +4076 0 3805 +4076 0 3805 +4076 0 3804 +4076 0 3803 +4076 0 3803 +4076 0 3801 +4076 0 3799 +4076 0 3797 +4076 0 3793 +4076 0 3789 +4076 0 3783 +4076 0 3775 +4076 0 3763 +4076 0 3748 +4076 0 3726 +4076 0 3696 +4076 0 3651 +4076 0 3584 +4076 0 3475 +4076 0 3272 +4076 0 2627 +4076 0 0 +4076 0 0 +4076 3401 0 +4095 3924 0 +4095 0 3939 +4095 0 3939 +4095 0 3939 +4095 0 3938 +4095 0 3938 +4095 0 3938 +4095 0 3938 +4095 0 3938 +4095 0 3937 +4095 0 3937 +4095 0 3937 +4095 0 3936 +4095 0 3935 +4095 0 3933 +4095 0 3932 +4095 0 3929 +4095 0 3926 +4095 0 3921 +4095 0 3915 +4095 0 3907 +4095 0 3896 +4095 0 3880 +4095 0 3859 +4095 0 3828 +4095 0 3784 +4095 0 3717 +4095 0 3608 +4095 0 3404 +4095 0 2762 +4095 0 0 +4095 0 0 +4095 3533 0 +0 201 318 +0 318 300 +0 318 93 +0 466 0 +127 609 0 +334 750 0 +515 888 0 +681 1025 0 +836 1160 0 +985 1295 0 +1130 1429 0 +1271 1563 0 +1410 1696 0 +1547 1828 0 +1682 1961 0 +1817 2094 0 +1951 2226 0 +2085 2358 0 +2218 2491 0 +2351 2623 0 +2484 2755 0 +2616 2887 0 +2748 3019 0 +2881 3152 0 +3013 3284 0 +3145 3416 0 +3278 3548 0 +3410 3680 0 +3542 3812 0 +3674 3944 0 +3806 4076 0 +3938 4095 0 +0 13 318 +86 229 295 +86 295 174 +145 450 15 +303 598 0 +453 741 0 +599 882 0 +740 1020 0 +879 1157 0 +1017 1292 0 +1153 1427 0 +1288 1561 0 +1422 1695 0 +1556 1828 0 +1689 1961 0 +1822 2093 0 +1955 2226 0 +2087 2358 0 +2220 2491 0 +2352 2623 0 +2485 2755 0 +2617 2887 0 +2749 3019 0 +2881 3152 0 +3014 3283 0 +3146 3416 0 +3278 3548 0 +3410 3680 0 +3542 3812 0 +3674 3944 0 +3806 4076 0 +3939 4095 0 +93 0 318 +174 86 295 +264 264 264 +361 427 218 +466 582 148 +576 730 34 +691 873 0 +810 1014 0 +932 1152 0 +1056 1289 0 +1182 1424 0 +1310 1559 0 +1439 1693 0 +1568 1827 0 +1699 1960 0 +1829 2093 0 +1960 2225 0 +2091 2358 0 +2223 2490 0 +2355 2623 0 +2486 2755 0 +2618 2887 0 +2750 3019 0 +2882 3152 0 +3014 3283 0 +3146 3416 0 +3278 3548 0 +3410 3680 0 +3542 3812 0 +3674 3944 0 +3806 4076 0 +3939 4095 0 +388 0 466 +432 15 450 +427 218 361 +427 306 218 +582 564 148 +683 730 34 +776 873 0 +877 1014 0 +984 1152 0 +1096 1289 0 +1213 1424 0 +1333 1559 0 +1456 1693 0 +1582 1827 0 +1708 1960 0 +1837 2093 0 +1966 2225 0 +2096 2358 0 +2226 2490 0 +2357 2623 0 +2488 2755 0 +2620 2887 0 +2751 3019 0 +2883 3152 0 +3014 3283 0 +3147 3416 0 +3279 3548 0 +3410 3680 0 +3543 3812 0 +3674 3944 0 +3806 4076 0 +3939 4095 0 +609 0 606 +598 0 551 +582 148 466 +582 148 277 +582 357 148 +730 652 34 +870 873 0 +954 1014 0 +1045 1152 0 +1145 1289 0 +1251 1424 0 +1363 1559 0 +1479 1693 0 +1599 1827 0 +1722 1960 0 +1847 2093 0 +1973 2225 0 +2101 2358 0 +2230 2490 0 +2360 2623 0 +2491 2755 0 +2621 2887 0 +2752 3019 0 +2884 3152 0 +3015 3283 0 +3147 3416 0 +3279 3548 0 +3411 3680 0 +3543 3812 0 +3675 3944 0 +3807 4076 0 +3939 4095 0 +750 0 689 +741 0 644 +730 34 576 +730 34 435 +730 34 132 +730 418 34 +873 749 0 +1014 987 0 +1117 1152 0 +1203 1289 0 +1298 1424 0 +1400 1559 0 +1508 1693 0 +1621 1827 0 +1739 1960 0 +1860 2093 0 +1983 2225 0 +2109 2358 0 +2236 2490 0 +2364 2623 0 +2494 2755 0 +2624 2887 0 +2754 3019 0 +2885 3152 0 +3016 3283 0 +3148 3416 0 +3280 3548 0 +3411 3680 0 +3543 3812 0 +3675 3944 0 +3807 4076 0 +3939 4095 0 +888 0 781 +882 0 745 +873 0 691 +873 0 585 +873 0 390 +873 0 0 +873 488 0 +1014 852 0 +1152 1102 0 +1271 1289 0 +1353 1424 0 +1445 1559 0 +1544 1693 0 +1650 1827 0 +1761 1960 0 +1877 2093 0 +1996 2225 0 +2119 2358 0 +2243 2490 0 +2370 2623 0 +2498 2755 0 +2627 2887 0 +2757 3019 0 +2887 3152 0 +3018 3283 0 +3149 3416 0 +3280 3548 0 +3412 3680 0 +3543 3812 0 +3675 3944 0 +3807 4076 0 +3939 4095 0 +1025 0 881 +1020 0 852 +1014 0 810 +1014 0 731 +1014 0 598 +1014 0 323 +1014 0 0 +1014 568 0 +1152 960 0 +1289 1221 0 +1418 1424 0 +1499 1559 0 +1588 1693 0 +1684 1827 0 +1789 1960 0 +1898 2093 0 +2013 2225 0 +2132 2358 0 +2253 2490 0 +2378 2623 0 +2504 2755 0 +2631 2887 0 +2760 3019 0 +2890 3152 0 +3019 3283 0 +3150 3416 0 +3281 3548 0 +3413 3680 0 +3544 3812 0 +3676 3944 0 +3807 4076 0 +3939 4095 0 +1160 0 987 +1157 0 964 +1152 0 932 +1152 0 873 +1152 0 779 +1152 0 614 +1152 0 214 +1152 0 0 +1152 656 0 +1289 1075 0 +1424 1343 0 +1559 1556 0 +1640 1693 0 +1727 1827 0 +1823 1960 0 +1926 2093 0 +2034 2225 0 +2148 2358 0 +2266 2490 0 +2387 2623 0 +2511 2755 0 +2637 2887 0 +2764 3019 0 +2893 3152 0 +3022 3283 0 +3152 3416 0 +3282 3548 0 +3414 3680 0 +3545 3812 0 +3676 3944 0 +3808 4076 0 +3940 4095 0 +1295 0 1099 +1292 0 1081 +1289 0 1056 +1289 0 1012 +1289 0 945 +1289 0 837 +1289 0 635 +1289 0 9 +1289 0 0 +1289 753 0 +1424 1193 0 +1559 1468 0 +1693 1683 0 +1779 1827 0 +1865 1960 0 +1960 2093 0 +2061 2225 0 +2169 2358 0 +2283 2490 0 +2400 2623 0 +2521 2755 0 +2644 2887 0 +2770 3019 0 +2897 3152 0 +3025 3283 0 +3154 3416 0 +3284 3548 0 +3415 3680 0 +3546 3812 0 +3677 3944 0 +3808 4076 0 +3940 4095 0 +1429 0 1215 +1427 0 1201 +1424 0 1182 +1424 0 1149 +1424 0 1101 +1424 0 1027 +1424 0 904 +1424 0 662 +1424 0 0 +1424 0 0 +1424 856 0 +1559 1315 0 +1693 1594 0 +1827 1812 0 +1917 1960 0 +2002 2093 0 +2095 2225 0 +2196 2358 0 +2304 2490 0 +2416 2623 0 +2533 2755 0 +2654 2887 0 +2777 3019 0 +2903 3152 0 +3029 3283 0 +3157 3416 0 +3287 3548 0 +3417 3680 0 +3547 3812 0 +3678 3944 0 +3809 4076 0 +3941 4095 0 +1563 0 1335 +1561 0 1325 +1559 0 1310 +1559 0 1285 +1559 0 1250 +1559 0 1198 +1559 0 1118 +1559 0 981 +1559 0 696 +1559 0 0 +1559 0 0 +1559 966 0 +1693 1439 0 +1827 1722 0 +1960 1941 0 +2053 2093 0 +2137 2225 0 +2230 2358 0 +2331 2490 0 +2437 2623 0 +2550 2755 0 +2667 2887 0 +2787 3019 0 +2910 3152 0 +3035 3283 0 +3162 3416 0 +3290 3548 0 +3419 3680 0 +3549 3812 0 +3679 3944 0 +3810 4076 0 +3941 4095 0 +1696 0 1457 +1695 0 1450 +1693 0 1439 +1693 0 1420 +1693 0 1394 +1693 0 1357 +1693 0 1302 +1693 0 1216 +1693 0 1067 +1693 0 736 +1693 0 0 +1693 0 0 +1693 1080 0 +1827 1565 0 +1960 1851 0 +2093 2071 0 +2188 2225 0 +2271 2358 0 +2364 2490 0 +2464 2623 0 +2571 2755 0 +2683 2887 0 +2799 3019 0 +2919 3152 0 +3042 3283 0 +3167 3416 0 +3294 3548 0 +3422 3680 0 +3551 3812 0 +3681 3944 0 +3811 4076 0 +3942 4095 0 +1828 0 1582 +1828 0 1576 +1827 0 1568 +1827 0 1554 +1827 0 1535 +1827 0 1508 +1827 0 1469 +1827 0 1412 +1827 0 1321 +1827 0 1161 +1827 0 786 +1827 0 0 +1827 0 0 +1827 1198 0 +1960 1692 0 +2093 1981 0 +2225 2202 0 +2322 2358 0 +2406 2490 0 +2498 2623 0 +2598 2755 0 +2704 2887 0 +2816 3019 0 +2932 3152 0 +3052 3283 0 +3175 3416 0 +3300 3548 0 +3426 3680 0 +3554 3812 0 +3683 3944 0 +3813 4076 0 +3944 4095 0 +1961 0 1709 +1961 0 1705 +1960 0 1699 +1960 0 1688 +1960 0 1674 +1960 0 1654 +1960 0 1626 +1960 0 1586 +1960 0 1526 +1960 0 1431 +1960 0 1263 +1960 0 844 +1960 0 0 +1960 0 0 +1960 1320 0 +2093 1821 0 +2225 2111 0 +2358 2333 0 +2456 2490 0 +2539 2623 0 +2631 2755 0 +2731 2887 0 +2836 3019 0 +2948 3152 0 +3064 3283 0 +3184 3416 0 +3307 3548 0 +3432 3680 0 +3559 3812 0 +3687 3944 0 +3816 4076 0 +3945 4095 0 +2094 0 1837 +2093 0 1834 +2093 0 1829 +2093 0 1821 +2093 0 1811 +2093 0 1796 +2093 0 1776 +2093 0 1748 +2093 0 1706 +2093 0 1645 +2093 0 1547 +2093 0 1370 +2093 0 913 +2093 0 0 +2093 0 0 +2093 1444 0 +2225 1950 0 +2358 2241 0 +2490 2464 0 +2589 2623 0 +2672 2755 0 +2764 2887 0 +2863 3019 0 +2969 3152 0 +3081 3283 0 +3197 3416 0 +3317 3548 0 +3439 3680 0 +3564 3812 0 +3691 3944 0 +3819 4076 0 +3948 4095 0 +2226 0 1966 +2226 0 1963 +2225 0 1960 +2225 0 1954 +2225 0 1946 +2225 0 1936 +2225 0 1921 +2225 0 1900 +2225 0 1871 +2225 0 1829 +2225 0 1767 +2225 0 1666 +2225 0 1484 +2225 0 990 +2225 0 0 +2225 0 0 +2225 1570 0 +2358 2080 0 +2490 2373 0 +2623 2596 0 +2722 2755 0 +2805 2887 0 +2896 3019 0 +2996 3152 0 +3101 3283 0 +3213 3416 0 +3329 3548 0 +3449 3680 0 +3572 3812 0 +3696 3944 0 +3823 4076 0 +3951 4095 0 +2358 0 2096 +2358 0 2094 +2358 0 2091 +2358 0 2087 +2358 0 2081 +2358 0 2073 +2358 0 2062 +2358 0 2047 +2358 0 2027 +2358 0 1997 +2358 0 1955 +2358 0 1891 +2358 0 1788 +2358 0 1600 +2358 0 1076 +2358 0 0 +2358 0 0 +2358 1698 0 +2490 2211 0 +2623 2504 0 +2755 2728 0 +2855 2887 0 +2938 3019 0 +3029 3152 0 +3128 3283 0 +3234 3416 0 +3346 3548 0 +3462 3680 0 +3581 3812 0 +3704 3944 0 +3828 4076 0 +3955 4095 0 +2491 0 2226 +2491 0 2225 +2490 0 2223 +2490 0 2220 +2490 0 2215 +2490 0 2209 +2490 0 2202 +2490 0 2190 +2490 0 2175 +2490 0 2154 +2490 0 2125 +2490 0 2082 +2490 0 2017 +2490 0 1913 +2490 0 1722 +2490 0 1173 +2490 0 0 +2490 0 0 +2490 1826 0 +2623 2342 0 +2755 2636 0 +2887 2859 0 +2987 3019 0 +3070 3152 0 +3161 3283 0 +3260 3416 0 +3366 3548 0 +3478 3680 0 +3594 3812 0 +3713 3944 0 +3836 4076 0 +3961 4095 0 +2623 0 2357 +2623 0 2356 +2623 0 2355 +2623 0 2352 +2623 0 2349 +2623 0 2345 +2623 0 2338 +2623 0 2331 +2623 0 2320 +2623 0 2304 +2623 0 2283 +2623 0 2253 +2623 0 2210 +2623 0 2144 +2623 0 2039 +2623 0 1845 +2623 0 1275 +2623 0 0 +2623 0 0 +2623 1956 0 +2755 2474 0 +2887 2767 0 +3019 2991 0 +3120 3152 0 +3202 3283 0 +3294 3416 0 +3393 3548 0 +3499 3680 0 +3610 3812 0 +3726 3944 0 +3845 4076 0 +3968 4095 0 +2755 0 2488 +2755 0 2488 +2755 0 2486 +2755 0 2485 +2755 0 2482 +2755 0 2479 +2755 0 2475 +2755 0 2469 +2755 0 2460 +2755 0 2449 +2755 0 2434 +2755 0 2413 +2755 0 2383 +2755 0 2339 +2755 0 2274 +2755 0 2167 +2755 0 1971 +2755 0 1386 +2755 0 0 +2755 0 0 +2755 2086 0 +2887 2605 0 +3019 2898 0 +3152 3123 0 +3252 3283 0 +3335 3416 0 +3426 3548 0 +3525 3680 0 +3631 3812 0 +3742 3944 0 +3858 4076 0 +3978 4095 0 +2887 0 2620 +2887 0 2619 +2887 0 2618 +2887 0 2617 +2887 0 2615 +2887 0 2613 +2887 0 2609 +2887 0 2605 +2887 0 2599 +2887 0 2591 +2887 0 2580 +2887 0 2564 +2887 0 2543 +2887 0 2513 +2887 0 2469 +2887 0 2403 +2887 0 2296 +2887 0 2098 +2887 0 1497 +2887 0 0 +2887 0 0 +2887 2217 0 +3019 2736 0 +3152 3031 0 +3283 3255 0 +3384 3416 0 +3467 3548 0 +3558 3680 0 +3657 3812 0 +3763 3944 0 +3874 4076 0 +3990 4095 0 +3019 0 2751 +3019 0 2751 +3019 0 2750 +3019 0 2749 +3019 0 2747 +3019 0 2746 +3019 0 2743 +3019 0 2740 +3019 0 2735 +3019 0 2729 +3019 0 2721 +3019 0 2710 +3019 0 2695 +3019 0 2673 +3019 0 2643 +3019 0 2599 +3019 0 2533 +3019 0 2426 +3019 0 2225 +3019 0 1613 +3019 0 0 +3019 0 0 +3019 2347 0 +3152 2869 0 +3283 3163 0 +3416 3387 0 +3516 3548 0 +3599 3680 0 +3690 3812 0 +3790 3944 0 +3895 4076 0 +4006 4095 0 +3152 0 2883 +3152 0 2883 +3152 0 2882 +3152 0 2881 +3152 0 2880 +3152 0 2879 +3152 0 2877 +3152 0 2875 +3152 0 2871 +3152 0 2867 +3152 0 2861 +3152 0 2853 +3152 0 2842 +3152 0 2826 +3152 0 2805 +3152 0 2774 +3152 0 2730 +3152 0 2664 +3152 0 2556 +3152 0 2355 +3152 0 1735 +3152 0 0 +3152 0 0 +3152 2479 0 +3283 2999 0 +3416 3294 0 +3548 3519 0 +3649 3680 0 +3731 3812 0 +3823 3944 0 +3921 4076 0 +4027 4095 0 +3284 0 3014 +3283 0 3014 +3283 0 3014 +3283 0 3013 +3283 0 3013 +3283 0 3011 +3283 0 3010 +3283 0 3008 +3283 0 3006 +3283 0 3002 +3283 0 2998 +3283 0 2992 +3283 0 2984 +3283 0 2973 +3283 0 2957 +3283 0 2936 +3283 0 2905 +3283 0 2861 +3283 0 2794 +3283 0 2686 +3283 0 2484 +3283 0 1856 +3283 0 0 +3283 0 0 +3283 2610 0 +3416 3132 0 +3548 3427 0 +3680 3651 0 +3781 3812 0 +3863 3944 0 +3955 4076 0 +4054 4095 0 +3416 0 3147 +3416 0 3146 +3416 0 3146 +3416 0 3146 +3416 0 3145 +3416 0 3144 +3416 0 3143 +3416 0 3142 +3416 0 3140 +3416 0 3138 +3416 0 3134 +3416 0 3130 +3416 0 3124 +3416 0 3115 +3416 0 3104 +3416 0 3089 +3416 0 3067 +3416 0 3037 +3416 0 2992 +3416 0 2926 +3416 0 2817 +3416 0 2615 +3416 0 1986 +3416 0 0 +3416 0 0 +3416 2742 0 +3548 3264 0 +3680 3559 0 +3812 3783 0 +3913 3944 0 +3996 4076 0 +4087 4095 0 +3548 0 3279 +3548 0 3278 +3548 0 3278 +3548 0 3278 +3548 0 3277 +3548 0 3277 +3548 0 3276 +3548 0 3275 +3548 0 3274 +3548 0 3272 +3548 0 3269 +3548 0 3266 +3548 0 3261 +3548 0 3256 +3548 0 3247 +3548 0 3236 +3548 0 3221 +3548 0 3199 +3548 0 3168 +3548 0 3124 +3548 0 3057 +3548 0 2949 +3548 0 2746 +3548 0 2111 +3548 0 0 +3548 0 0 +3548 2873 0 +3680 3396 0 +3812 3691 0 +3944 3915 0 +4045 4076 0 +4095 4095 0 +3680 0 3410 +3680 0 3410 +3680 0 3410 +3680 0 3410 +3680 0 3410 +3680 0 3409 +3680 0 3409 +3680 0 3408 +3680 0 3407 +3680 0 3405 +3680 0 3404 +3680 0 3401 +3680 0 3398 +3680 0 3393 +3680 0 3387 +3680 0 3379 +3680 0 3368 +3680 0 3353 +3680 0 3331 +3680 0 3300 +3680 0 3256 +3680 0 3189 +3680 0 3081 +3680 0 2877 +3680 0 2242 +3680 0 0 +3680 0 0 +3680 3005 0 +3812 3528 0 +3944 3822 0 +4076 4047 0 +4095 4095 0 +3812 0 3543 +3812 0 3543 +3812 0 3542 +3812 0 3542 +3812 0 3542 +3812 0 3541 +3812 0 3541 +3812 0 3541 +3812 0 3540 +3812 0 3539 +3812 0 3537 +3812 0 3536 +3812 0 3533 +3812 0 3530 +3812 0 3525 +3812 0 3519 +3812 0 3511 +3812 0 3500 +3812 0 3484 +3812 0 3463 +3812 0 3432 +3812 0 3388 +3812 0 3321 +3812 0 3212 +3812 0 3009 +3812 0 2371 +3812 0 0 +3812 0 0 +3812 3137 0 +3944 3660 0 +4076 3954 0 +4095 4095 0 +3944 0 3674 +3944 0 3674 +3944 0 3674 +3944 0 3674 +3944 0 3674 +3944 0 3674 +3944 0 3673 +3944 0 3673 +3944 0 3673 +3944 0 3672 +3944 0 3671 +3944 0 3669 +3944 0 3668 +3944 0 3665 +3944 0 3662 +3944 0 3657 +3944 0 3651 +3944 0 3643 +3944 0 3632 +3944 0 3616 +3944 0 3595 +3944 0 3564 +3944 0 3520 +3944 0 3453 +3944 0 3344 +3944 0 3140 +3944 0 2500 +3944 0 0 +3944 0 0 +3944 3269 0 +4076 3792 0 +4095 4087 0 +4076 0 3806 +4076 0 3806 +4076 0 3806 +4076 0 3806 +4076 0 3806 +4076 0 3806 +4076 0 3805 +4076 0 3805 +4076 0 3805 +4076 0 3804 +4076 0 3803 +4076 0 3803 +4076 0 3801 +4076 0 3799 +4076 0 3797 +4076 0 3793 +4076 0 3789 +4076 0 3783 +4076 0 3775 +4076 0 3763 +4076 0 3748 +4076 0 3726 +4076 0 3696 +4076 0 3651 +4076 0 3585 +4076 0 3476 +4076 0 3272 +4076 0 2628 +4076 0 0 +4076 0 0 +4076 3401 0 +4095 3924 0 +4095 0 3939 +4095 0 3939 +4095 0 3939 +4095 0 3939 +4095 0 3938 +4095 0 3938 +4095 0 3938 +4095 0 3938 +4095 0 3937 +4095 0 3937 +4095 0 3937 +4095 0 3936 +4095 0 3935 +4095 0 3933 +4095 0 3932 +4095 0 3929 +4095 0 3926 +4095 0 3921 +4095 0 3915 +4095 0 3907 +4095 0 3896 +4095 0 3880 +4095 0 3859 +4095 0 3828 +4095 0 3784 +4095 0 3717 +4095 0 3608 +4095 0 3404 +4095 0 2762 +4095 0 0 +4095 0 0 +4095 3533 0 +0 312 466 +0 419 466 +0 466 388 +0 466 154 +0 609 0 +59 750 0 +350 888 0 +573 1025 0 +762 1160 0 +934 1295 0 +1092 1429 0 +1244 1563 0 +1390 1696 0 +1532 1828 0 +1672 1961 0 +1809 2094 0 +1945 2226 0 +2080 2358 0 +2215 2491 0 +2348 2623 0 +2482 2755 0 +2615 2887 0 +2747 3019 0 +2880 3152 0 +3012 3284 0 +3145 3416 0 +3277 3548 0 +3410 3680 0 +3542 3812 0 +3674 3944 0 +3806 4076 0 +3938 4095 0 +0 171 466 +15 333 450 +15 450 432 +15 450 225 +0 598 0 +258 741 0 +466 882 0 +647 1020 0 +813 1157 0 +968 1292 0 +1118 1427 0 +1262 1561 0 +1403 1695 0 +1542 1828 0 +1679 1961 0 +1814 2093 0 +1949 2226 0 +2083 2358 0 +2217 2491 0 +2350 2623 0 +2483 2755 0 +2616 2887 0 +2748 3019 0 +2881 3152 0 +3013 3283 0 +3145 3416 0 +3278 3548 0 +3410 3680 0 +3542 3812 0 +3674 3944 0 +3806 4076 0 +3938 4095 0 +0 0 466 +15 145 450 +218 361 427 +218 427 306 +277 582 148 +435 730 34 +585 873 0 +731 1014 0 +873 1152 0 +1012 1289 0 +1149 1424 0 +1285 1559 0 +1420 1693 0 +1554 1827 0 +1688 1960 0 +1821 2093 0 +1954 2225 0 +2087 2358 0 +2220 2490 0 +2352 2623 0 +2485 2755 0 +2617 2887 0 +2749 3019 0 +2881 3152 0 +3013 3283 0 +3146 3416 0 +3278 3548 0 +3410 3680 0 +3542 3812 0 +3674 3944 0 +3806 4076 0 +3939 4095 0 +154 0 466 +225 15 450 +306 218 427 +396 396 396 +494 560 350 +598 714 280 +708 862 166 +823 1005 0 +942 1146 0 +1064 1284 0 +1188 1421 0 +1315 1557 0 +1442 1691 0 +1571 1825 0 +1700 1959 0 +1830 2092 0 +1961 2225 0 +2092 2357 0 +2223 2490 0 +2355 2622 0 +2487 2755 0 +2619 2887 0 +2750 3019 0 +2882 3151 0 +3014 3283 0 +3146 3416 0 +3278 3548 0 +3410 3680 0 +3542 3812 0 +3674 3944 0 +3806 4076 0 +3939 4095 0 +485 0 609 +520 0 598 +564 148 582 +560 350 494 +560 438 350 +714 696 280 +815 862 166 +908 1005 0 +1009 1146 0 +1116 1284 0 +1228 1421 0 +1345 1557 0 +1465 1691 0 +1588 1825 0 +1714 1959 0 +1841 2092 0 +1969 2225 0 +2098 2357 0 +2228 2490 0 +2358 2622 0 +2489 2755 0 +2620 2887 0 +2751 3019 0 +2883 3151 0 +3015 3283 0 +3147 3416 0 +3279 3548 0 +3411 3680 0 +3543 3812 0 +3674 3944 0 +3806 4076 0 +3939 4095 0 +723 0 750 +741 0 738 +730 34 683 +714 280 598 +714 280 409 +714 490 280 +862 784 166 +1002 1005 0 +1086 1146 0 +1177 1284 0 +1277 1421 0 +1384 1557 0 +1495 1691 0 +1611 1825 0 +1731 1959 0 +1854 2092 0 +1979 2225 0 +2105 2357 0 +2234 2490 0 +2362 2622 0 +2492 2755 0 +2623 2887 0 +2753 3019 0 +2885 3151 0 +3016 3283 0 +3147 3416 0 +3279 3548 0 +3411 3680 0 +3543 3812 0 +3675 3944 0 +3807 4076 0 +3939 4095 0 +888 0 852 +882 0 822 +873 0 776 +862 166 708 +862 166 567 +862 166 264 +862 550 166 +1005 881 0 +1146 1119 0 +1249 1284 0 +1335 1421 0 +1430 1557 0 +1532 1691 0 +1640 1825 0 +1754 1959 0 +1871 2092 0 +1992 2225 0 +2115 2357 0 +2241 2490 0 +2368 2622 0 +2497 2755 0 +2626 2887 0 +2756 3019 0 +2886 3151 0 +3017 3283 0 +3148 3416 0 +3280 3548 0 +3412 3680 0 +3543 3812 0 +3675 3944 0 +3807 4076 0 +3939 4095 0 +1025 0 939 +1020 0 914 +1014 0 877 +1005 0 823 +1005 0 717 +1005 0 523 +1005 0 0 +1005 620 0 +1146 983 0 +1284 1235 0 +1403 1421 0 +1486 1557 0 +1577 1691 0 +1676 1825 0 +1781 1959 0 +1893 2092 0 +2009 2225 0 +2128 2357 0 +2251 2490 0 +2375 2622 0 +2502 2755 0 +2630 2887 0 +2759 3019 0 +2889 3151 0 +3019 3283 0 +3150 3416 0 +3281 3548 0 +3412 3680 0 +3544 3812 0 +3676 3944 0 +3807 4076 0 +3939 4095 0 +1160 0 1033 +1157 0 1013 +1152 0 984 +1146 0 942 +1146 0 863 +1146 0 730 +1146 0 455 +1146 0 0 +1146 700 0 +1284 1093 0 +1421 1353 0 +1551 1557 0 +1631 1691 0 +1720 1825 0 +1817 1959 0 +1920 2092 0 +2030 2225 0 +2145 2357 0 +2264 2490 0 +2385 2622 0 +2510 2755 0 +2636 2887 0 +2763 3019 0 +2892 3151 0 +3021 3283 0 +3151 3416 0 +3282 3548 0 +3413 3680 0 +3545 3812 0 +3676 3944 0 +3808 4076 0 +3940 4095 0 +1295 0 1135 +1292 0 1119 +1289 0 1096 +1284 0 1064 +1284 0 1005 +1284 0 911 +1284 0 746 +1284 0 346 +1284 0 0 +1284 788 0 +1421 1207 0 +1557 1476 0 +1691 1688 0 +1772 1825 0 +1860 1959 0 +1955 2092 0 +2058 2225 0 +2166 2357 0 +2280 2490 0 +2398 2622 0 +2520 2755 0 +2643 2887 0 +2769 3019 0 +2896 3151 0 +3025 3283 0 +3154 3416 0 +3284 3548 0 +3415 3680 0 +3545 3812 0 +3677 3944 0 +3808 4076 0 +3940 4095 0 +1429 0 1244 +1427 0 1231 +1424 0 1213 +1421 0 1188 +1421 0 1144 +1421 0 1077 +1421 0 969 +1421 0 767 +1421 0 141 +1421 0 0 +1421 885 0 +1557 1326 0 +1691 1600 0 +1825 1816 0 +1911 1959 0 +1997 2092 0 +2092 2225 0 +2193 2357 0 +2302 2490 0 +2414 2622 0 +2532 2755 0 +2653 2887 0 +2776 3019 0 +2902 3151 0 +3029 3283 0 +3157 3416 0 +3286 3548 0 +3416 3680 0 +3547 3812 0 +3678 3944 0 +3809 4076 0 +3941 4095 0 +1563 0 1357 +1561 0 1347 +1559 0 1333 +1557 0 1315 +1557 0 1281 +1557 0 1233 +1557 0 1159 +1557 0 1037 +1557 0 794 +1557 0 0 +1557 0 0 +1557 988 0 +1691 1447 0 +1825 1727 0 +1959 1944 0 +2049 2092 0 +2134 2225 0 +2228 2357 0 +2329 2490 0 +2436 2622 0 +2549 2755 0 +2666 2887 0 +2786 3019 0 +2909 3151 0 +3034 3283 0 +3161 3416 0 +3290 3548 0 +3419 3680 0 +3549 3812 0 +3679 3944 0 +3810 4076 0 +3941 4095 0 +1696 0 1475 +1695 0 1467 +1693 0 1456 +1691 0 1442 +1691 0 1417 +1691 0 1382 +1691 0 1330 +1691 0 1249 +1691 0 1113 +1691 0 827 +1691 0 0 +1691 0 0 +1691 1098 0 +1825 1571 0 +1959 1854 0 +2092 2073 0 +2185 2225 0 +2269 2357 0 +2362 2490 0 +2463 2622 0 +2570 2755 0 +2682 2887 0 +2798 3019 0 +2919 3151 0 +3042 3283 0 +3167 3416 0 +3294 3548 0 +3422 3680 0 +3551 3812 0 +3681 3944 0 +3811 4076 0 +3942 4095 0 +1828 0 1596 +1828 0 1590 +1827 0 1582 +1825 0 1571 +1825 0 1552 +1825 0 1526 +1825 0 1489 +1825 0 1434 +1825 0 1348 +1825 0 1199 +1825 0 869 +1825 0 0 +1825 0 0 +1825 1212 0 +1959 1697 0 +2092 1983 0 +2225 2203 0 +2320 2357 0 +2404 2490 0 +2496 2622 0 +2596 2755 0 +2703 2887 0 +2815 3019 0 +2932 3151 0 +3051 3283 0 +3174 3416 0 +3299 3548 0 +3426 3680 0 +3554 3812 0 +3683 3944 0 +3813 4076 0 +3944 4095 0 +1961 0 1719 +1961 0 1715 +1960 0 1708 +1959 0 1700 +1959 0 1686 +1959 0 1667 +1959 0 1640 +1959 0 1601 +1959 0 1544 +1959 0 1453 +1959 0 1294 +1959 0 917 +1959 0 0 +1959 0 0 +1959 1331 0 +2092 1824 0 +2225 2112 0 +2357 2334 0 +2454 2490 0 +2538 2622 0 +2630 2755 0 +2730 2887 0 +2836 3019 0 +2948 3151 0 +3064 3283 0 +3184 3416 0 +3307 3548 0 +3432 3680 0 +3558 3812 0 +3686 3944 0 +3815 4076 0 +3945 4095 0 +2094 0 1845 +2093 0 1841 +2093 0 1837 +2092 0 1830 +2092 0 1820 +2092 0 1806 +2092 0 1786 +2092 0 1758 +2092 0 1718 +2092 0 1658 +2092 0 1564 +2092 0 1394 +2092 0 977 +2092 0 0 +2092 0 0 +2092 1452 0 +2225 1953 0 +2357 2243 0 +2490 2465 0 +2588 2622 0 +2671 2755 0 +2763 2887 0 +2863 3019 0 +2969 3151 0 +3080 3283 0 +3196 3416 0 +3316 3548 0 +3439 3680 0 +3564 3812 0 +3691 3944 0 +3818 4076 0 +3948 4095 0 +2226 0 1972 +2226 0 1969 +2225 0 1966 +2225 0 1961 +2225 0 1953 +2225 0 1943 +2225 0 1928 +2225 0 1908 +2225 0 1880 +2225 0 1839 +2225 0 1777 +2225 0 1679 +2225 0 1503 +2225 0 1044 +2225 0 0 +2225 0 0 +2225 1576 0 +2357 2082 0 +2490 2374 0 +2622 2596 0 +2721 2755 0 +2804 2887 0 +2896 3019 0 +2995 3151 0 +3101 3283 0 +3213 3416 0 +3329 3548 0 +3449 3680 0 +3571 3812 0 +3696 3944 0 +3823 4076 0 +3951 4095 0 +2358 0 2100 +2358 0 2098 +2358 0 2096 +2357 0 2092 +2357 0 2086 +2357 0 2078 +2357 0 2068 +2357 0 2053 +2357 0 2032 +2357 0 2004 +2357 0 1962 +2357 0 1899 +2357 0 1798 +2357 0 1615 +2357 0 1122 +2357 0 0 +2357 0 0 +2357 1702 0 +2490 2213 0 +2622 2505 0 +2755 2728 0 +2854 2887 0 +2937 3019 0 +3029 3151 0 +3128 3283 0 +3234 3416 0 +3345 3548 0 +3461 3680 0 +3581 3812 0 +3703 3944 0 +3828 4076 0 +3955 4095 0 +2491 0 2230 +2491 0 2228 +2490 0 2226 +2490 0 2223 +2490 0 2219 +2490 0 2213 +2490 0 2206 +2490 0 2195 +2490 0 2180 +2490 0 2159 +2490 0 2129 +2490 0 2087 +2490 0 2023 +2490 0 1920 +2490 0 1733 +2490 0 1210 +2490 0 0 +2490 0 0 +2490 1830 0 +2622 2343 0 +2755 2636 0 +2887 2860 0 +2987 3019 0 +3070 3151 0 +3161 3283 0 +3260 3416 0 +3366 3548 0 +3478 3680 0 +3594 3812 0 +3713 3944 0 +3836 4076 0 +3961 4095 0 +2623 0 2359 +2623 0 2358 +2623 0 2357 +2622 0 2355 +2622 0 2352 +2622 0 2347 +2622 0 2341 +2622 0 2334 +2622 0 2323 +2622 0 2308 +2622 0 2287 +2622 0 2256 +2622 0 2214 +2622 0 2149 +2622 0 2045 +2622 0 1853 +2622 0 1304 +2622 0 0 +2622 0 0 +2622 1958 0 +2755 2475 0 +2887 2768 0 +3019 2991 0 +3119 3151 0 +3202 3283 0 +3293 3416 0 +3393 3548 0 +3499 3680 0 +3610 3812 0 +3726 3944 0 +3845 4076 0 +3968 4095 0 +2755 0 2490 +2755 0 2489 +2755 0 2488 +2755 0 2487 +2755 0 2484 +2755 0 2481 +2755 0 2477 +2755 0 2471 +2755 0 2463 +2755 0 2452 +2755 0 2436 +2755 0 2415 +2755 0 2386 +2755 0 2342 +2755 0 2277 +2755 0 2172 +2755 0 1977 +2755 0 1409 +2755 0 0 +2755 0 0 +2755 2088 0 +2887 2605 0 +3019 2899 0 +3151 3123 0 +3252 3283 0 +3335 3416 0 +3426 3548 0 +3525 3680 0 +3631 3812 0 +3742 3944 0 +3858 4076 0 +3978 4095 0 +2887 0 2621 +2887 0 2620 +2887 0 2620 +2887 0 2619 +2887 0 2617 +2887 0 2614 +2887 0 2611 +2887 0 2607 +2887 0 2601 +2887 0 2592 +2887 0 2581 +2887 0 2566 +2887 0 2545 +2887 0 2515 +2887 0 2471 +2887 0 2406 +2887 0 2299 +2887 0 2103 +2887 0 1516 +2887 0 0 +2887 0 0 +2887 2218 0 +3019 2736 0 +3151 3031 0 +3283 3255 0 +3384 3416 0 +3467 3548 0 +3558 3680 0 +3657 3812 0 +3763 3944 0 +3874 4076 0 +3990 4095 0 +3019 0 2752 +3019 0 2752 +3019 0 2751 +3019 0 2750 +3019 0 2749 +3019 0 2747 +3019 0 2745 +3019 0 2741 +3019 0 2737 +3019 0 2731 +3019 0 2723 +3019 0 2712 +3019 0 2696 +3019 0 2675 +3019 0 2645 +3019 0 2601 +3019 0 2535 +3019 0 2428 +3019 0 2229 +3019 0 1628 +3019 0 0 +3019 0 0 +3019 2348 0 +3151 2869 0 +3283 3163 0 +3416 3387 0 +3516 3548 0 +3599 3680 0 +3690 3812 0 +3790 3944 0 +3895 4076 0 +4006 4095 0 +3152 0 2884 +3152 0 2883 +3152 0 2883 +3151 0 2882 +3151 0 2881 +3151 0 2880 +3151 0 2878 +3151 0 2876 +3151 0 2872 +3151 0 2868 +3151 0 2862 +3151 0 2854 +3151 0 2842 +3151 0 2827 +3151 0 2806 +3151 0 2775 +3151 0 2732 +3151 0 2665 +3151 0 2558 +3151 0 2358 +3151 0 1746 +3151 0 0 +3151 0 0 +3151 2480 0 +3283 2999 0 +3416 3294 0 +3548 3519 0 +3649 3680 0 +3731 3812 0 +3822 3944 0 +3921 4076 0 +4027 4095 0 +3284 0 3015 +3283 0 3015 +3283 0 3014 +3283 0 3014 +3283 0 3013 +3283 0 3012 +3283 0 3011 +3283 0 3009 +3283 0 3007 +3283 0 3003 +3283 0 2999 +3283 0 2993 +3283 0 2985 +3283 0 2973 +3283 0 2958 +3283 0 2936 +3283 0 2906 +3283 0 2862 +3283 0 2795 +3283 0 2688 +3283 0 2486 +3283 0 1864 +3283 0 0 +3283 0 0 +3283 2611 0 +3416 3132 0 +3548 3427 0 +3680 3651 0 +3781 3812 0 +3863 3944 0 +3955 4076 0 +4054 4095 0 +3416 0 3147 +3416 0 3147 +3416 0 3147 +3416 0 3146 +3416 0 3146 +3416 0 3145 +3416 0 3144 +3416 0 3142 +3416 0 3141 +3416 0 3138 +3416 0 3135 +3416 0 3130 +3416 0 3124 +3416 0 3116 +3416 0 3105 +3416 0 3089 +3416 0 3068 +3416 0 3038 +3416 0 2993 +3416 0 2927 +3416 0 2818 +3416 0 2617 +3416 0 1992 +3416 0 0 +3416 0 0 +3416 2742 0 +3548 3264 0 +3680 3559 0 +3812 3783 0 +3913 3944 0 +3995 4076 0 +4087 4095 0 +3548 0 3279 +3548 0 3279 +3548 0 3279 +3548 0 3278 +3548 0 3278 +3548 0 3277 +3548 0 3277 +3548 0 3275 +3548 0 3274 +3548 0 3272 +3548 0 3270 +3548 0 3267 +3548 0 3262 +3548 0 3256 +3548 0 3248 +3548 0 3237 +3548 0 3221 +3548 0 3200 +3548 0 3169 +3548 0 3125 +3548 0 3058 +3548 0 2950 +3548 0 2747 +3548 0 2115 +3548 0 0 +3548 0 0 +3548 2874 0 +3680 3396 0 +3812 3691 0 +3944 3915 0 +4045 4076 0 +4095 4095 0 +3680 0 3411 +3680 0 3411 +3680 0 3410 +3680 0 3410 +3680 0 3410 +3680 0 3410 +3680 0 3409 +3680 0 3408 +3680 0 3407 +3680 0 3406 +3680 0 3404 +3680 0 3401 +3680 0 3398 +3680 0 3394 +3680 0 3388 +3680 0 3379 +3680 0 3368 +3680 0 3353 +3680 0 3331 +3680 0 3301 +3680 0 3256 +3680 0 3189 +3680 0 3081 +3680 0 2878 +3680 0 2246 +3680 0 0 +3680 0 0 +3680 3006 0 +3812 3528 0 +3944 3823 0 +4076 4047 0 +4095 4095 0 +3812 0 3543 +3812 0 3543 +3812 0 3543 +3812 0 3542 +3812 0 3542 +3812 0 3542 +3812 0 3541 +3812 0 3541 +3812 0 3540 +3812 0 3539 +3812 0 3538 +3812 0 3536 +3812 0 3533 +3812 0 3530 +3812 0 3526 +3812 0 3520 +3812 0 3511 +3812 0 3500 +3812 0 3485 +3812 0 3463 +3812 0 3432 +3812 0 3388 +3812 0 3321 +3812 0 3213 +3812 0 3010 +3812 0 2374 +3812 0 0 +3812 0 0 +3812 3138 0 +3944 3660 0 +4076 3954 0 +4095 4095 0 +3944 0 3674 +3944 0 3674 +3944 0 3674 +3944 0 3674 +3944 0 3674 +3944 0 3674 +3944 0 3674 +3944 0 3673 +3944 0 3673 +3944 0 3672 +3944 0 3671 +3944 0 3669 +3944 0 3668 +3944 0 3665 +3944 0 3662 +3944 0 3657 +3944 0 3651 +3944 0 3643 +3944 0 3632 +3944 0 3616 +3944 0 3595 +3944 0 3564 +3944 0 3520 +3944 0 3453 +3944 0 3344 +3944 0 3141 +3944 0 2502 +3944 0 0 +3944 0 0 +3944 3269 0 +4076 3792 0 +4095 4087 0 +4076 0 3806 +4076 0 3806 +4076 0 3806 +4076 0 3806 +4076 0 3806 +4076 0 3806 +4076 0 3806 +4076 0 3805 +4076 0 3805 +4076 0 3805 +4076 0 3804 +4076 0 3803 +4076 0 3801 +4076 0 3799 +4076 0 3797 +4076 0 3794 +4076 0 3789 +4076 0 3783 +4076 0 3775 +4076 0 3764 +4076 0 3748 +4076 0 3727 +4076 0 3696 +4076 0 3652 +4076 0 3585 +4076 0 3476 +4076 0 3272 +4076 0 2630 +4076 0 0 +4076 0 0 +4076 3401 0 +4095 3924 0 +4095 0 3939 +4095 0 3939 +4095 0 3939 +4095 0 3939 +4095 0 3939 +4095 0 3938 +4095 0 3938 +4095 0 3938 +4095 0 3938 +4095 0 3937 +4095 0 3937 +4095 0 3936 +4095 0 3935 +4095 0 3933 +4095 0 3932 +4095 0 3929 +4095 0 3926 +4095 0 3921 +4095 0 3915 +4095 0 3907 +4095 0 3896 +4095 0 3880 +4095 0 3859 +4095 0 3828 +4095 0 3784 +4095 0 3717 +4095 0 3608 +4095 0 3405 +4095 0 2764 +4095 0 0 +4095 0 0 +4095 3534 0 +0 427 609 +0 512 609 +0 606 609 +0 609 485 +0 609 224 +0 750 0 +0 888 0 +371 1025 0 +640 1160 0 +853 1295 0 +1037 1429 0 +1205 1563 0 +1362 1696 0 +1512 1828 0 +1657 1961 0 +1798 2094 0 +1937 2226 0 +2074 2358 0 +2210 2491 0 +2345 2623 0 +2479 2755 0 +2613 2887 0 +2746 3019 0 +2879 3152 0 +3012 3284 0 +3144 3416 0 +3277 3548 0 +3409 3680 0 +3541 3812 0 +3674 3944 0 +3806 4076 0 +3938 4095 0 +0 322 609 +0 444 598 +0 551 598 +0 598 520 +0 598 286 +0 741 0 +190 882 0 +482 1020 0 +705 1157 0 +894 1292 0 +1065 1427 0 +1225 1561 0 +1376 1695 0 +1522 1828 0 +1664 1961 0 +1804 2093 0 +1941 2226 0 +2077 2358 0 +2212 2491 0 +2347 2623 0 +2481 2755 0 +2614 2887 0 +2747 3019 0 +2880 3152 0 +3012 3283 0 +3145 3416 0 +3277 3548 0 +3409 3680 0 +3542 3812 0 +3674 3944 0 +3806 4076 0 +3938 4095 0 +0 127 609 +0 303 598 +148 466 582 +148 582 564 +148 582 357 +132 730 34 +390 873 0 +598 1014 0 +779 1152 0 +945 1289 0 +1101 1424 0 +1250 1559 0 +1394 1693 0 +1535 1827 0 +1674 1960 0 +1811 2093 0 +1946 2225 0 +2081 2358 0 +2215 2490 0 +2349 2623 0 +2482 2755 0 +2615 2887 0 +2747 3019 0 +2880 3152 0 +3013 3283 0 +3145 3416 0 +3277 3548 0 +3410 3680 0 +3542 3812 0 +3674 3944 0 +3806 4076 0 +3938 4095 0 +0 0 609 +0 0 598 +148 277 582 +350 494 560 +350 560 438 +409 714 280 +567 862 166 +717 1005 0 +863 1146 0 +1005 1284 0 +1144 1421 0 +1281 1557 0 +1417 1691 0 +1552 1825 0 +1686 1959 0 +1820 2092 0 +1953 2225 0 +2086 2357 0 +2219 2490 0 +2352 2622 0 +2484 2755 0 +2617 2887 0 +2749 3019 0 +2881 3151 0 +3013 3283 0 +3146 3416 0 +3278 3548 0 +3410 3680 0 +3542 3812 0 +3674 3944 0 +3806 4076 0 +3939 4095 0 +224 0 609 +286 0 598 +357 148 582 +438 350 560 +528 528 528 +625 691 482 +730 846 412 +840 994 298 +955 1137 80 +1074 1278 0 +1196 1416 0 +1320 1553 0 +1446 1689 0 +1574 1823 0 +1703 1958 0 +1832 2091 0 +1963 2224 0 +2093 2357 0 +2224 2489 0 +2356 2622 0 +2487 2755 0 +2619 2887 0 +2750 3019 0 +2883 3151 0 +3014 3283 0 +3146 3416 0 +3278 3548 0 +3410 3680 0 +3543 3812 0 +3674 3944 0 +3806 4076 0 +3939 4095 0 +587 0 750 +616 0 741 +652 34 730 +696 280 714 +691 482 625 +691 570 482 +846 828 412 +947 994 298 +1040 1137 80 +1141 1278 0 +1248 1416 0 +1360 1553 0 +1477 1689 0 +1598 1823 0 +1721 1958 0 +1846 2091 0 +1973 2224 0 +2101 2357 0 +2230 2489 0 +2360 2622 0 +2490 2755 0 +2621 2887 0 +2752 3019 0 +2884 3151 0 +3015 3283 0 +3147 3416 0 +3279 3548 0 +3411 3680 0 +3543 3812 0 +3674 3944 0 +3807 4076 0 +3939 4095 0 +838 0 888 +855 0 882 +873 0 870 +862 166 815 +846 412 730 +846 412 541 +846 622 412 +994 917 298 +1134 1137 80 +1218 1278 0 +1310 1416 0 +1409 1553 0 +1515 1689 0 +1627 1823 0 +1743 1958 0 +1863 2091 0 +1986 2224 0 +2111 2357 0 +2238 2489 0 +2366 2622 0 +2495 2755 0 +2625 2887 0 +2755 3019 0 +2886 3151 0 +3016 3283 0 +3148 3416 0 +3280 3548 0 +3411 3680 0 +3543 3812 0 +3675 3944 0 +3807 4076 0 +3939 4095 0 +1025 0 1006 +1020 0 985 +1014 0 954 +1005 0 908 +994 298 840 +994 298 699 +994 298 397 +994 682 298 +1137 1013 80 +1278 1251 0 +1381 1416 0 +1467 1553 0 +1562 1689 0 +1664 1823 0 +1772 1958 0 +1885 2091 0 +2003 2224 0 +2124 2357 0 +2247 2489 0 +2373 2622 0 +2501 2755 0 +2629 2887 0 +2758 3019 0 +2888 3151 0 +3018 3283 0 +3149 3416 0 +3280 3548 0 +3412 3680 0 +3544 3812 0 +3675 3944 0 +3807 4076 0 +3939 4095 0 +1160 0 1089 +1157 0 1071 +1152 0 1045 +1146 0 1009 +1137 80 955 +1137 80 850 +1137 80 655 +1137 80 81 +1137 753 80 +1278 1116 0 +1416 1367 0 +1535 1553 0 +1617 1689 0 +1709 1823 0 +1808 1958 0 +1913 2091 0 +2025 2224 0 +2141 2357 0 +2260 2489 0 +2383 2622 0 +2508 2755 0 +2635 2887 0 +2762 3019 0 +2891 3151 0 +3021 3283 0 +3151 3416 0 +3282 3548 0 +3413 3680 0 +3544 3812 0 +3676 3944 0 +3808 4076 0 +3940 4095 0 +1295 0 1181 +1292 0 1166 +1289 0 1145 +1284 0 1116 +1278 0 1074 +1278 0 995 +1278 0 862 +1278 0 587 +1278 0 0 +1278 832 0 +1416 1225 0 +1553 1486 0 +1683 1689 0 +1763 1823 0 +1852 1958 0 +1949 2091 0 +2053 2224 0 +2162 2357 0 +2277 2489 0 +2396 2622 0 +2517 2755 0 +2642 2887 0 +2768 3019 0 +2895 3151 0 +3024 3283 0 +3154 3416 0 +3284 3548 0 +3414 3680 0 +3545 3812 0 +3677 3944 0 +3808 4076 0 +3940 4095 0 +1429 0 1280 +1427 0 1267 +1424 0 1251 +1421 0 1228 +1416 0 1196 +1416 0 1137 +1416 0 1043 +1416 0 878 +1416 0 478 +1416 0 0 +1416 920 0 +1553 1340 0 +1689 1608 0 +1823 1821 0 +1905 1958 0 +1992 2091 0 +2087 2224 0 +2190 2357 0 +2298 2489 0 +2412 2622 0 +2530 2755 0 +2651 2887 0 +2775 3019 0 +2901 3151 0 +3028 3283 0 +3157 3416 0 +3286 3548 0 +3416 3680 0 +3547 3812 0 +3678 3944 0 +3809 4076 0 +3941 4095 0 +1563 0 1385 +1561 0 1376 +1559 0 1363 +1557 0 1345 +1553 0 1320 +1553 0 1276 +1553 0 1209 +1553 0 1102 +1553 0 900 +1553 0 275 +1553 0 0 +1553 1017 0 +1689 1457 0 +1823 1732 0 +1958 1948 0 +2044 2091 0 +2130 2224 0 +2224 2357 0 +2326 2489 0 +2434 2622 0 +2547 2755 0 +2664 2887 0 +2785 3019 0 +2908 3151 0 +3034 3283 0 +3161 3416 0 +3289 3548 0 +3419 3680 0 +3549 3812 0 +3679 3944 0 +3810 4076 0 +3941 4095 0 +1696 0 1496 +1695 0 1489 +1693 0 1479 +1691 0 1465 +1689 0 1446 +1689 0 1413 +1689 0 1365 +1689 0 1291 +1689 0 1169 +1689 0 926 +1689 0 0 +1689 0 0 +1689 1120 0 +1823 1579 0 +1958 1859 0 +2091 2076 0 +2181 2224 0 +2266 2357 0 +2360 2489 0 +2460 2622 0 +2568 2755 0 +2681 2887 0 +2797 3019 0 +2918 3151 0 +3041 3283 0 +3166 3416 0 +3293 3548 0 +3422 3680 0 +3551 3812 0 +3681 3944 0 +3811 4076 0 +3942 4095 0 +1828 0 1612 +1828 0 1607 +1827 0 1599 +1825 0 1588 +1823 0 1574 +1823 0 1549 +1823 0 1514 +1823 0 1462 +1823 0 1382 +1823 0 1245 +1823 0 960 +1823 0 0 +1823 0 0 +1823 1230 0 +1958 1703 0 +2091 1986 0 +2224 2206 0 +2317 2357 0 +2401 2489 0 +2494 2622 0 +2595 2755 0 +2702 2887 0 +2814 3019 0 +2931 3151 0 +3051 3283 0 +3174 3416 0 +3299 3548 0 +3426 3680 0 +3554 3812 0 +3683 3944 0 +3813 4076 0 +3944 4095 0 +1961 0 1732 +1961 0 1728 +1960 0 1722 +1959 0 1714 +1958 0 1703 +1958 0 1684 +1958 0 1658 +1958 0 1621 +1958 0 1566 +1958 0 1480 +1958 0 1332 +1958 0 1000 +1958 0 0 +1958 0 0 +1958 1344 0 +2091 1829 0 +2224 2115 0 +2357 2335 0 +2452 2489 0 +2536 2622 0 +2628 2755 0 +2728 2887 0 +2835 3019 0 +2947 3151 0 +3063 3283 0 +3184 3416 0 +3307 3548 0 +3431 3680 0 +3558 3812 0 +3686 3944 0 +3815 4076 0 +3945 4095 0 +2094 0 1855 +2093 0 1851 +2093 0 1847 +2092 0 1841 +2091 0 1832 +2091 0 1819 +2091 0 1799 +2091 0 1772 +2091 0 1733 +2091 0 1676 +2091 0 1585 +2091 0 1425 +2091 0 1050 +2091 0 0 +2091 0 0 +2091 1463 0 +2224 1956 0 +2357 2245 0 +2489 2466 0 +2586 2622 0 +2670 2755 0 +2762 2887 0 +2862 3019 0 +2968 3151 0 +3080 3283 0 +3196 3416 0 +3316 3548 0 +3439 3680 0 +3564 3812 0 +3691 3944 0 +3818 4076 0 +3948 4095 0 +2226 0 1979 +2226 0 1977 +2225 0 1973 +2225 0 1969 +2224 0 1963 +2224 0 1952 +2224 0 1938 +2224 0 1918 +2224 0 1891 +2224 0 1850 +2224 0 1790 +2224 0 1695 +2224 0 1527 +2224 0 1108 +2224 0 0 +2224 0 0 +2224 1584 0 +2357 2085 0 +2489 2375 0 +2622 2597 0 +2720 2755 0 +2803 2887 0 +2895 3019 0 +2995 3151 0 +3101 3283 0 +3212 3416 0 +3329 3548 0 +3448 3680 0 +3571 3812 0 +3696 3944 0 +3823 4076 0 +3951 4095 0 +2358 0 2106 +2358 0 2104 +2358 0 2101 +2357 0 2098 +2357 0 2093 +2357 0 2086 +2357 0 2075 +2357 0 2060 +2357 0 2040 +2357 0 2012 +2357 0 1970 +2357 0 1909 +2357 0 1811 +2357 0 1634 +2357 0 1176 +2357 0 0 +2357 0 0 +2357 1708 0 +2489 2215 0 +2622 2506 0 +2755 2729 0 +2853 2887 0 +2936 3019 0 +3028 3151 0 +3127 3283 0 +3233 3416 0 +3345 3548 0 +3461 3680 0 +3581 3812 0 +3703 3944 0 +3828 4076 0 +3955 4095 0 +2491 0 2234 +2491 0 2233 +2490 0 2230 +2490 0 2228 +2489 0 2224 +2489 0 2219 +2489 0 2211 +2489 0 2200 +2489 0 2185 +2489 0 2165 +2489 0 2136 +2489 0 2094 +2489 0 2031 +2489 0 1930 +2489 0 1748 +2489 0 1255 +2489 0 0 +2489 0 0 +2489 1834 0 +2622 2344 0 +2755 2637 0 +2887 2860 0 +2986 3019 0 +3069 3151 0 +3160 3283 0 +3260 3416 0 +3366 3548 0 +3478 3680 0 +3594 3812 0 +3713 3944 0 +3836 4076 0 +3961 4095 0 +2623 0 2363 +2623 0 2362 +2623 0 2360 +2622 0 2358 +2622 0 2356 +2622 0 2351 +2622 0 2346 +2622 0 2337 +2622 0 2327 +2622 0 2312 +2622 0 2291 +2622 0 2261 +2622 0 2219 +2622 0 2155 +2622 0 2052 +2622 0 1865 +2622 0 1342 +2622 0 0 +2622 0 0 +2622 1962 0 +2755 2476 0 +2887 2768 0 +3019 2992 0 +3119 3151 0 +3201 3283 0 +3293 3416 0 +3392 3548 0 +3498 3680 0 +3610 3812 0 +3726 3944 0 +3845 4076 0 +3968 4095 0 +2755 0 2493 +2755 0 2492 +2755 0 2491 +2755 0 2489 +2755 0 2487 +2755 0 2484 +2755 0 2480 +2755 0 2474 +2755 0 2466 +2755 0 2455 +2755 0 2440 +2755 0 2419 +2755 0 2389 +2755 0 2346 +2755 0 2281 +2755 0 2177 +2755 0 1986 +2755 0 1439 +2755 0 0 +2755 0 0 +2755 2091 0 +2887 2606 0 +3019 2899 0 +3151 3123 0 +3251 3283 0 +3334 3416 0 +3426 3548 0 +3525 3680 0 +3631 3812 0 +3742 3944 0 +3858 4076 0 +3977 4095 0 +2887 0 2623 +2887 0 2622 +2887 0 2621 +2887 0 2620 +2887 0 2619 +2887 0 2617 +2887 0 2613 +2887 0 2609 +2887 0 2603 +2887 0 2595 +2887 0 2584 +2887 0 2569 +2887 0 2548 +2887 0 2517 +2887 0 2474 +2887 0 2409 +2887 0 2304 +2887 0 2110 +2887 0 1540 +2887 0 0 +2887 0 0 +2887 2220 0 +3019 2737 0 +3151 3031 0 +3283 3255 0 +3384 3416 0 +3467 3548 0 +3558 3680 0 +3657 3812 0 +3763 3944 0 +3874 4076 0 +3990 4095 0 +3019 0 2754 +3019 0 2753 +3019 0 2752 +3019 0 2751 +3019 0 2750 +3019 0 2749 +3019 0 2746 +3019 0 2743 +3019 0 2738 +3019 0 2732 +3019 0 2724 +3019 0 2713 +3019 0 2698 +3019 0 2677 +3019 0 2647 +3019 0 2603 +3019 0 2537 +3019 0 2431 +3019 0 2234 +3019 0 1646 +3019 0 0 +3019 0 0 +3019 2350 0 +3151 2869 0 +3283 3163 0 +3416 3387 0 +3516 3548 0 +3599 3680 0 +3690 3812 0 +3789 3944 0 +3895 4076 0 +4006 4095 0 +3152 0 2885 +3152 0 2885 +3152 0 2884 +3151 0 2883 +3151 0 2883 +3151 0 2881 +3151 0 2879 +3151 0 2877 +3151 0 2873 +3151 0 2869 +3151 0 2863 +3151 0 2855 +3151 0 2844 +3151 0 2829 +3151 0 2807 +3151 0 2777 +3151 0 2733 +3151 0 2667 +3151 0 2560 +3151 0 2362 +3151 0 1760 +3151 0 0 +3151 0 0 +3151 2481 0 +3283 3000 0 +3416 3295 0 +3548 3519 0 +3648 3680 0 +3731 3812 0 +3822 3944 0 +3921 4076 0 +4027 4095 0 +3284 0 3016 +3283 0 3016 +3283 0 3015 +3283 0 3015 +3283 0 3014 +3283 0 3013 +3283 0 3012 +3283 0 3010 +3283 0 3008 +3283 0 3004 +3283 0 3000 +3283 0 2994 +3283 0 2986 +3283 0 2974 +3283 0 2959 +3283 0 2938 +3283 0 2907 +3283 0 2863 +3283 0 2797 +3283 0 2690 +3283 0 2489 +3283 0 1875 +3283 0 0 +3283 0 0 +3283 2612 0 +3416 3132 0 +3548 3427 0 +3680 3651 0 +3781 3812 0 +3863 3944 0 +3955 4076 0 +4054 4095 0 +3416 0 3147 +3416 0 3147 +3416 0 3147 +3416 0 3147 +3416 0 3146 +3416 0 3145 +3416 0 3144 +3416 0 3143 +3416 0 3141 +3416 0 3139 +3416 0 3135 +3416 0 3131 +3416 0 3125 +3416 0 3117 +3416 0 3106 +3416 0 3090 +3416 0 3069 +3416 0 3038 +3416 0 2994 +3416 0 2928 +3416 0 2820 +3416 0 2619 +3416 0 2000 +3416 0 0 +3416 0 0 +3416 2743 0 +3548 3264 0 +3680 3559 0 +3812 3783 0 +3913 3944 0 +3995 4076 0 +4087 4095 0 +3548 0 3279 +3548 0 3279 +3548 0 3279 +3548 0 3279 +3548 0 3278 +3548 0 3278 +3548 0 3277 +3548 0 3276 +3548 0 3275 +3548 0 3273 +3548 0 3270 +3548 0 3267 +3548 0 3262 +3548 0 3256 +3548 0 3248 +3548 0 3237 +3548 0 3222 +3548 0 3200 +3548 0 3170 +3548 0 3125 +3548 0 3059 +3548 0 2951 +3548 0 2749 +3548 0 2122 +3548 0 0 +3548 0 0 +3548 2874 0 +3680 3396 0 +3812 3691 0 +3944 3915 0 +4045 4076 0 +4095 4095 0 +3680 0 3411 +3680 0 3411 +3680 0 3411 +3680 0 3411 +3680 0 3410 +3680 0 3410 +3680 0 3409 +3680 0 3409 +3680 0 3408 +3680 0 3406 +3680 0 3404 +3680 0 3402 +3680 0 3399 +3680 0 3394 +3680 0 3388 +3680 0 3380 +3680 0 3369 +3680 0 3353 +3680 0 3332 +3680 0 3301 +3680 0 3257 +3680 0 3190 +3680 0 3082 +3680 0 2879 +3680 0 2251 +3680 0 0 +3680 0 0 +3680 3006 0 +3812 3528 0 +3944 3823 0 +4076 4047 0 +4095 4095 0 +3812 0 3543 +3812 0 3543 +3812 0 3543 +3812 0 3543 +3812 0 3543 +3812 0 3542 +3812 0 3542 +3812 0 3541 +3812 0 3540 +3812 0 3539 +3812 0 3538 +3812 0 3536 +3812 0 3534 +3812 0 3530 +3812 0 3526 +3812 0 3520 +3812 0 3511 +3812 0 3500 +3812 0 3485 +3812 0 3463 +3812 0 3433 +3812 0 3388 +3812 0 3322 +3812 0 3213 +3812 0 3011 +3812 0 2377 +3812 0 0 +3812 0 0 +3812 3138 0 +3944 3660 0 +4076 3955 0 +4095 4095 0 +3944 0 3675 +3944 0 3675 +3944 0 3675 +3944 0 3674 +3944 0 3674 +3944 0 3674 +3944 0 3674 +3944 0 3673 +3944 0 3673 +3944 0 3672 +3944 0 3671 +3944 0 3670 +3944 0 3668 +3944 0 3665 +3944 0 3662 +3944 0 3658 +3944 0 3652 +3944 0 3643 +3944 0 3632 +3944 0 3617 +3944 0 3595 +3944 0 3564 +3944 0 3520 +3944 0 3453 +3944 0 3345 +3944 0 3142 +3944 0 2505 +3944 0 0 +3944 0 0 +3944 3270 0 +4076 3792 0 +4095 4087 0 +4076 0 3807 +4076 0 3807 +4076 0 3807 +4076 0 3806 +4076 0 3806 +4076 0 3806 +4076 0 3806 +4076 0 3805 +4076 0 3805 +4076 0 3805 +4076 0 3804 +4076 0 3803 +4076 0 3801 +4076 0 3800 +4076 0 3797 +4076 0 3794 +4076 0 3790 +4076 0 3783 +4076 0 3775 +4076 0 3764 +4076 0 3748 +4076 0 3727 +4076 0 3696 +4076 0 3652 +4076 0 3585 +4076 0 3476 +4076 0 3273 +4076 0 2632 +4076 0 0 +4076 0 0 +4076 3401 0 +4095 3924 0 +4095 0 3939 +4095 0 3939 +4095 0 3939 +4095 0 3939 +4095 0 3939 +4095 0 3938 +4095 0 3938 +4095 0 3938 +4095 0 3938 +4095 0 3937 +4095 0 3937 +4095 0 3936 +4095 0 3935 +4095 0 3934 +4095 0 3932 +4095 0 3929 +4095 0 3926 +4095 0 3921 +4095 0 3915 +4095 0 3907 +4095 0 3896 +4095 0 3880 +4095 0 3859 +4095 0 3828 +4095 0 3784 +4095 0 3717 +4095 0 3608 +4095 0 3405 +4095 0 2765 +4095 0 0 +4095 0 0 +4095 3534 0 +0 545 750 +0 613 750 +0 689 750 +0 750 723 +0 750 587 +0 750 304 +0 888 0 +0 1025 0 +397 1160 0 +717 1295 0 +951 1429 0 +1148 1563 0 +1322 1696 0 +1484 1828 0 +1636 1961 0 +1783 2094 0 +1926 2226 0 +2066 2358 0 +2204 2491 0 +2341 2623 0 +2476 2755 0 +2611 2887 0 +2744 3019 0 +2878 3152 0 +3011 3284 0 +3144 3416 0 +3276 3548 0 +3409 3680 0 +3541 3812 0 +3674 3944 0 +3806 4076 0 +3938 4095 0 +0 467 750 +0 559 741 +0 644 741 +0 738 741 +0 741 616 +0 741 356 +0 882 0 +81 1020 0 +503 1157 0 +772 1292 0 +985 1427 0 +1170 1561 0 +1337 1695 0 +1494 1828 0 +1644 1961 0 +1789 2093 0 +1930 2226 0 +2069 2358 0 +2206 2491 0 +2342 2623 0 +2477 2755 0 +2612 2887 0 +2745 3019 0 +2878 3152 0 +3011 3283 0 +3144 3416 0 +3277 3548 0 +3409 3680 0 +3541 3812 0 +3674 3944 0 +3806 4076 0 +3938 4095 0 +0 334 750 +0 453 741 +34 576 730 +34 683 730 +34 730 652 +34 730 418 +0 873 0 +323 1014 0 +614 1152 0 +837 1289 0 +1027 1424 0 +1198 1559 0 +1357 1693 0 +1508 1827 0 +1654 1960 0 +1796 2093 0 +1936 2225 0 +2073 2358 0 +2209 2490 0 +2345 2623 0 +2479 2755 0 +2613 2887 0 +2746 3019 0 +2879 3152 0 +3011 3283 0 +3144 3416 0 +3277 3548 0 +3409 3680 0 +3541 3812 0 +3674 3944 0 +3806 4076 0 +3938 4095 0 +0 59 750 +0 258 741 +34 435 730 +280 598 714 +280 714 696 +280 714 490 +264 862 166 +523 1005 0 +730 1146 0 +911 1284 0 +1077 1421 0 +1233 1557 0 +1382 1691 0 +1526 1825 0 +1667 1959 0 +1806 2092 0 +1943 2225 0 +2078 2357 0 +2213 2490 0 +2347 2622 0 +2481 2755 0 +2614 2887 0 +2747 3019 0 +2880 3151 0 +3012 3283 0 +3145 3416 0 +3277 3548 0 +3410 3680 0 +3542 3812 0 +3674 3944 0 +3806 4076 0 +3938 4095 0 +0 0 750 +0 0 741 +34 132 730 +280 409 714 +482 625 691 +482 691 570 +541 846 412 +699 994 298 +850 1137 80 +995 1278 0 +1137 1416 0 +1276 1553 0 +1413 1689 0 +1549 1823 0 +1684 1958 0 +1819 2091 0 +1952 2224 0 +2086 2357 0 +2219 2489 0 +2351 2622 0 +2484 2755 0 +2617 2887 0 +2749 3019 0 +2881 3151 0 +3013 3283 0 +3145 3416 0 +3278 3548 0 +3410 3680 0 +3542 3812 0 +3674 3944 0 +3806 4076 0 +3938 4095 0 +304 0 750 +356 0 741 +418 34 730 +490 280 714 +570 482 691 +660 660 660 +758 824 614 +862 978 544 +972 1126 430 +1087 1270 212 +1206 1410 0 +1328 1549 0 +1452 1685 0 +1579 1821 0 +1706 1956 0 +1835 2089 0 +1965 2223 0 +2095 2356 0 +2226 2489 0 +2356 2621 0 +2488 2754 0 +2619 2887 0 +2751 3019 0 +2883 3151 0 +3014 3283 0 +3146 3416 0 +3278 3548 0 +3410 3680 0 +3543 3812 0 +3674 3944 0 +3806 4076 0 +3939 4095 0 +697 0 888 +719 0 882 +749 0 873 +784 166 862 +828 412 846 +824 614 758 +824 702 614 +978 960 544 +1079 1126 430 +1172 1270 212 +1273 1410 0 +1380 1549 0 +1492 1685 0 +1609 1821 0 +1730 1956 0 +1853 2089 0 +1978 2223 0 +2105 2356 0 +2233 2489 0 +2362 2621 0 +2492 2754 0 +2623 2887 0 +2753 3019 0 +2885 3151 0 +3016 3283 0 +3147 3416 0 +3279 3548 0 +3411 3680 0 +3543 3812 0 +3675 3944 0 +3807 4076 0 +3939 4095 0 +957 0 1025 +970 0 1020 +987 0 1014 +1005 0 1002 +994 298 947 +978 544 862 +978 544 673 +978 754 544 +1126 1049 430 +1266 1270 212 +1350 1410 0 +1442 1549 0 +1541 1685 0 +1648 1821 0 +1759 1956 0 +1875 2089 0 +1995 2223 0 +2118 2356 0 +2243 2489 0 +2370 2621 0 +2498 2754 0 +2627 2887 0 +2756 3019 0 +2887 3151 0 +3018 3283 0 +3149 3416 0 +3280 3548 0 +3412 3680 0 +3543 3812 0 +3675 3944 0 +3807 4076 0 +3939 4095 0 +1160 0 1154 +1157 0 1139 +1152 0 1117 +1146 0 1086 +1137 80 1040 +1126 430 972 +1126 430 831 +1126 430 529 +1126 814 430 +1270 1145 212 +1410 1383 0 +1513 1549 0 +1599 1685 0 +1694 1821 0 +1796 1956 0 +1904 2089 0 +2018 2223 0 +2135 2356 0 +2256 2489 0 +2380 2621 0 +2505 2754 0 +2632 2887 0 +2761 3019 0 +2890 3151 0 +3020 3283 0 +3151 3416 0 +3281 3548 0 +3413 3680 0 +3544 3812 0 +3676 3944 0 +3808 4076 0 +3939 4095 0 +1295 0 1234 +1292 0 1221 +1289 0 1203 +1284 0 1177 +1278 0 1141 +1270 212 1087 +1270 212 982 +1270 212 787 +1270 212 214 +1270 884 212 +1410 1248 0 +1549 1499 0 +1667 1685 0 +1750 1821 0 +1841 1956 0 +1940 2089 0 +2046 2223 0 +2157 2356 0 +2273 2489 0 +2393 2621 0 +2515 2754 0 +2640 2887 0 +2766 3019 0 +2895 3151 0 +3023 3283 0 +3153 3416 0 +3283 3548 0 +3414 3680 0 +3545 3812 0 +3676 3944 0 +3808 4076 0 +3940 4095 0 +1429 0 1323 +1427 0 1313 +1424 0 1298 +1421 0 1277 +1416 0 1248 +1410 0 1206 +1410 0 1127 +1410 0 994 +1410 0 719 +1410 47 0 +1410 964 0 +1549 1358 0 +1685 1618 0 +1815 1821 0 +1895 1956 0 +1984 2089 0 +2081 2223 0 +2185 2356 0 +2294 2489 0 +2409 2621 0 +2528 2754 0 +2650 2887 0 +2774 3019 0 +2900 3151 0 +3027 3283 0 +3156 3416 0 +3286 3548 0 +3416 3680 0 +3547 3812 0 +3677 3944 0 +3809 4076 0 +3941 4095 0 +1563 0 1421 +1561 0 1412 +1559 0 1400 +1557 0 1384 +1553 0 1360 +1549 0 1328 +1549 0 1269 +1549 0 1176 +1549 0 1011 +1549 0 611 +1549 0 0 +1549 1053 0 +1685 1471 0 +1821 1740 0 +1956 1953 0 +2037 2089 0 +2124 2223 0 +2219 2356 0 +2322 2489 0 +2431 2621 0 +2545 2754 0 +2662 2887 0 +2784 3019 0 +2907 3151 0 +3033 3283 0 +3160 3416 0 +3289 3548 0 +3418 3680 0 +3548 3812 0 +3679 3944 0 +3810 4076 0 +3941 4095 0 +1696 0 1524 +1695 0 1517 +1693 0 1508 +1691 0 1495 +1689 0 1477 +1685 0 1452 +1685 0 1408 +1685 0 1341 +1685 0 1233 +1685 0 1031 +1685 0 406 +1685 0 0 +1685 1149 0 +1821 1590 0 +1956 1865 0 +2089 2080 0 +2176 2223 0 +2262 2356 0 +2356 2489 0 +2458 2621 0 +2566 2754 0 +2679 2887 0 +2796 3019 0 +2917 3151 0 +3040 3283 0 +3166 3416 0 +3293 3548 0 +3421 3680 0 +3551 3812 0 +3681 3944 0 +3811 4076 0 +3942 4095 0 +1828 0 1634 +1828 0 1629 +1827 0 1621 +1825 0 1611 +1823 0 1598 +1821 0 1579 +1821 0 1545 +1821 0 1497 +1821 0 1423 +1821 0 1301 +1821 0 1059 +1821 0 0 +1821 0 0 +1821 1253 0 +1956 1711 0 +2089 1991 0 +2223 2208 0 +2313 2356 0 +2398 2489 0 +2492 2621 0 +2593 2754 0 +2700 2887 0 +2813 3019 0 +2930 3151 0 +3050 3283 0 +3173 3416 0 +3299 3548 0 +3426 3680 0 +3554 3812 0 +3683 3944 0 +3813 4076 0 +3944 4095 0 +1961 0 1749 +1961 0 1745 +1960 0 1739 +1959 0 1731 +1958 0 1721 +1956 0 1706 +1956 0 1681 +1956 0 1646 +1956 0 1594 +1956 0 1514 +1956 0 1378 +1956 0 1091 +1956 0 0 +1956 0 0 +1956 1362 0 +2089 1835 0 +2223 2118 0 +2356 2338 0 +2449 2489 0 +2533 2621 0 +2627 2754 0 +2727 2887 0 +2834 3019 0 +2946 3151 0 +3062 3283 0 +3183 3416 0 +3306 3548 0 +3431 3680 0 +3558 3812 0 +3686 3944 0 +3815 4076 0 +3945 4095 0 +2094 0 1867 +2093 0 1864 +2093 0 1860 +2092 0 1854 +2091 0 1846 +2089 0 1835 +2089 0 1816 +2089 0 1790 +2089 0 1753 +2089 0 1698 +2089 0 1612 +2089 0 1463 +2089 0 1133 +2089 0 0 +2089 0 0 +2089 1476 0 +2223 1961 0 +2356 2247 0 +2489 2468 0 +2584 2621 0 +2668 2754 0 +2761 2887 0 +2860 3019 0 +2967 3151 0 +3079 3283 0 +3196 3416 0 +3316 3548 0 +3438 3680 0 +3564 3812 0 +3690 3944 0 +3818 4076 0 +3948 4095 0 +2226 0 1989 +2226 0 1987 +2225 0 1983 +2225 0 1979 +2224 0 1973 +2223 0 1965 +2223 0 1951 +2223 0 1931 +2223 0 1904 +2223 0 1865 +2223 0 1808 +2223 0 1717 +2223 0 1557 +2223 0 1181 +2223 0 0 +2223 0 0 +2223 1595 0 +2356 2088 0 +2489 2377 0 +2621 2598 0 +2718 2754 0 +2802 2887 0 +2894 3019 0 +2994 3151 0 +3100 3283 0 +3212 3416 0 +3328 3548 0 +3448 3680 0 +3571 3812 0 +3696 3944 0 +3822 4076 0 +3951 4095 0 +2358 0 2113 +2358 0 2111 +2358 0 2109 +2357 0 2105 +2357 0 2101 +2356 0 2095 +2356 0 2084 +2356 0 2070 +2356 0 2050 +2356 0 2022 +2356 0 1982 +2356 0 1922 +2356 0 1828 +2356 0 1659 +2356 0 1240 +2356 0 0 +2356 0 0 +2356 1716 0 +2489 2218 0 +2621 2507 0 +2754 2730 0 +2852 2887 0 +2935 3019 0 +3027 3151 0 +3127 3283 0 +3233 3416 0 +3344 3548 0 +3461 3680 0 +3581 3812 0 +3703 3944 0 +3828 4076 0 +3955 4095 0 +2491 0 2239 +2491 0 2238 +2490 0 2236 +2490 0 2234 +2489 0 2230 +2489 0 2226 +2489 0 2218 +2489 0 2207 +2489 0 2193 +2489 0 2172 +2489 0 2144 +2489 0 2103 +2489 0 2041 +2489 0 1943 +2489 0 1767 +2489 0 1310 +2489 0 0 +2489 0 0 +2489 1840 0 +2621 2346 0 +2754 2638 0 +2887 2861 0 +2985 3019 0 +3068 3151 0 +3160 3283 0 +3259 3416 0 +3365 3548 0 +3477 3680 0 +3593 3812 0 +3713 3944 0 +3835 4076 0 +3961 4095 0 +2623 0 2367 +2623 0 2366 +2623 0 2364 +2622 0 2362 +2622 0 2360 +2621 0 2356 +2621 0 2351 +2621 0 2343 +2621 0 2332 +2621 0 2317 +2621 0 2297 +2621 0 2268 +2621 0 2226 +2621 0 2163 +2621 0 2062 +2621 0 1880 +2621 0 1387 +2621 0 0 +2621 0 0 +2621 1966 0 +2754 2477 0 +2887 2769 0 +3019 2992 0 +3118 3151 0 +3201 3283 0 +3293 3416 0 +3392 3548 0 +3498 3680 0 +3609 3812 0 +3725 3944 0 +3845 4076 0 +3968 4095 0 +2755 0 2496 +2755 0 2495 +2755 0 2494 +2755 0 2492 +2755 0 2490 +2754 0 2488 +2754 0 2484 +2754 0 2478 +2754 0 2470 +2754 0 2459 +2754 0 2444 +2754 0 2423 +2754 0 2394 +2754 0 2351 +2754 0 2287 +2754 0 2185 +2754 0 1997 +2754 0 1476 +2754 0 0 +2754 0 0 +2754 2094 0 +2887 2607 0 +3019 2900 0 +3151 3124 0 +3251 3283 0 +3334 3416 0 +3425 3548 0 +3525 3680 0 +3630 3812 0 +3742 3944 0 +3858 4076 0 +3977 4095 0 +2887 0 2625 +2887 0 2625 +2887 0 2624 +2887 0 2623 +2887 0 2621 +2887 0 2619 +2887 0 2616 +2887 0 2612 +2887 0 2606 +2887 0 2598 +2887 0 2587 +2887 0 2572 +2887 0 2551 +2887 0 2521 +2887 0 2478 +2887 0 2413 +2887 0 2310 +2887 0 2118 +2887 0 1569 +2887 0 0 +2887 0 0 +2887 2223 0 +3019 2738 0 +3151 3032 0 +3283 3255 0 +3384 3416 0 +3466 3548 0 +3558 3680 0 +3657 3812 0 +3763 3944 0 +3874 4076 0 +3990 4095 0 +3019 0 2755 +3019 0 2755 +3019 0 2754 +3019 0 2753 +3019 0 2752 +3019 0 2751 +3019 0 2748 +3019 0 2745 +3019 0 2741 +3019 0 2735 +3019 0 2727 +3019 0 2716 +3019 0 2701 +3019 0 2679 +3019 0 2649 +3019 0 2606 +3019 0 2541 +3019 0 2435 +3019 0 2241 +3019 0 1670 +3019 0 0 +3019 0 0 +3019 2352 0 +3151 2870 0 +3283 3163 0 +3416 3387 0 +3516 3548 0 +3599 3680 0 +3690 3812 0 +3789 3944 0 +3895 4076 0 +4006 4095 0 +3152 0 2886 +3152 0 2886 +3152 0 2885 +3151 0 2885 +3151 0 2884 +3151 0 2883 +3151 0 2881 +3151 0 2879 +3151 0 2875 +3151 0 2871 +3151 0 2865 +3151 0 2857 +3151 0 2845 +3151 0 2830 +3151 0 2809 +3151 0 2779 +3151 0 2735 +3151 0 2670 +3151 0 2564 +3151 0 2367 +3151 0 1779 +3151 0 0 +3151 0 0 +3151 2482 0 +3283 3000 0 +3416 3295 0 +3548 3519 0 +3648 3680 0 +3731 3812 0 +3822 3944 0 +3921 4076 0 +4027 4095 0 +3284 0 3017 +3283 0 3017 +3283 0 3016 +3283 0 3016 +3283 0 3015 +3283 0 3014 +3283 0 3013 +3283 0 3011 +3283 0 3009 +3283 0 3005 +3283 0 3001 +3283 0 2995 +3283 0 2987 +3283 0 2976 +3283 0 2960 +3283 0 2939 +3283 0 2909 +3283 0 2865 +3283 0 2799 +3283 0 2692 +3283 0 2493 +3283 0 1890 +3283 0 0 +3283 0 0 +3283 2613 0 +3416 3133 0 +3548 3427 0 +3680 3651 0 +3781 3812 0 +3863 3944 0 +3954 4076 0 +4054 4095 0 +3416 0 3148 +3416 0 3148 +3416 0 3148 +3416 0 3147 +3416 0 3147 +3416 0 3146 +3416 0 3145 +3416 0 3144 +3416 0 3142 +3416 0 3140 +3416 0 3136 +3416 0 3132 +3416 0 3126 +3416 0 3118 +3416 0 3106 +3416 0 3091 +3416 0 3070 +3416 0 3039 +3416 0 2996 +3416 0 2929 +3416 0 2822 +3416 0 2621 +3416 0 2011 +3416 0 0 +3416 0 0 +3416 2744 0 +3548 3265 0 +3680 3559 0 +3812 3783 0 +3913 3944 0 +3995 4076 0 +4087 4095 0 +3548 0 3280 +3548 0 3280 +3548 0 3280 +3548 0 3279 +3548 0 3279 +3548 0 3278 +3548 0 3278 +3548 0 3277 +3548 0 3275 +3548 0 3273 +3548 0 3271 +3548 0 3268 +3548 0 3263 +3548 0 3257 +3548 0 3249 +3548 0 3238 +3548 0 3222 +3548 0 3201 +3548 0 3171 +3548 0 3126 +3548 0 3060 +3548 0 2952 +3548 0 2751 +3548 0 2130 +3548 0 0 +3548 0 0 +3548 2875 0 +3680 3396 0 +3812 3691 0 +3944 3915 0 +4045 4076 0 +4095 4095 0 +3680 0 3411 +3680 0 3411 +3680 0 3411 +3680 0 3411 +3680 0 3411 +3680 0 3410 +3680 0 3410 +3680 0 3409 +3680 0 3408 +3680 0 3407 +3680 0 3405 +3680 0 3402 +3680 0 3399 +3680 0 3395 +3680 0 3388 +3680 0 3380 +3680 0 3369 +3680 0 3354 +3680 0 3332 +3680 0 3302 +3680 0 3258 +3680 0 3191 +3680 0 3083 +3680 0 2881 +3680 0 2257 +3680 0 0 +3680 0 0 +3680 3006 0 +3812 3528 0 +3944 3823 0 +4076 4047 0 +4095 4095 0 +3812 0 3543 +3812 0 3543 +3812 0 3543 +3812 0 3543 +3812 0 3543 +3812 0 3543 +3812 0 3542 +3812 0 3541 +3812 0 3541 +3812 0 3540 +3812 0 3538 +3812 0 3537 +3812 0 3534 +3812 0 3531 +3812 0 3526 +3812 0 3520 +3812 0 3512 +3812 0 3501 +3812 0 3485 +3812 0 3464 +3812 0 3433 +3812 0 3389 +3812 0 3322 +3812 0 3214 +3812 0 3012 +3812 0 2382 +3812 0 0 +3812 0 0 +3812 3138 0 +3944 3660 0 +4076 3955 0 +4095 4095 0 +3944 0 3675 +3944 0 3675 +3944 0 3675 +3944 0 3675 +3944 0 3674 +3944 0 3674 +3944 0 3674 +3944 0 3674 +3944 0 3673 +3944 0 3672 +3944 0 3671 +3944 0 3670 +3944 0 3668 +3944 0 3666 +3944 0 3662 +3944 0 3658 +3944 0 3652 +3944 0 3644 +3944 0 3632 +3944 0 3617 +3944 0 3595 +3944 0 3565 +3944 0 3521 +3944 0 3454 +3944 0 3346 +3944 0 3143 +3944 0 2508 +3944 0 0 +3944 0 0 +3944 3270 0 +4076 3792 0 +4095 4087 0 +4076 0 3807 +4076 0 3807 +4076 0 3807 +4076 0 3807 +4076 0 3807 +4076 0 3806 +4076 0 3806 +4076 0 3806 +4076 0 3805 +4076 0 3805 +4076 0 3804 +4076 0 3803 +4076 0 3802 +4076 0 3800 +4076 0 3797 +4076 0 3794 +4076 0 3790 +4076 0 3784 +4076 0 3775 +4076 0 3764 +4076 0 3749 +4076 0 3727 +4076 0 3696 +4076 0 3652 +4076 0 3585 +4076 0 3477 +4076 0 3273 +4076 0 2635 +4076 0 0 +4076 0 0 +4076 3402 0 +4095 3925 0 +4095 0 3939 +4095 0 3939 +4095 0 3939 +4095 0 3939 +4095 0 3939 +4095 0 3939 +4095 0 3938 +4095 0 3938 +4095 0 3938 +4095 0 3937 +4095 0 3937 +4095 0 3936 +4095 0 3935 +4095 0 3934 +4095 0 3932 +4095 0 3929 +4095 0 3926 +4095 0 3922 +4095 0 3916 +4095 0 3908 +4095 0 3896 +4095 0 3881 +4095 0 3859 +4095 0 3829 +4095 0 3784 +4095 0 3717 +4095 0 3609 +4095 0 3405 +4095 0 2767 +4095 0 0 +4095 0 0 +4095 3534 0 +0 667 888 +0 719 888 +0 781 888 +0 852 888 +0 888 838 +0 888 697 +0 888 392 +0 1025 0 +0 1160 0 +431 1295 0 +803 1429 0 +1057 1563 0 +1262 1696 0 +1442 1828 0 +1607 1961 0 +1763 2094 0 +1911 2226 0 +2055 2358 0 +2196 2491 0 +2335 2623 0 +2472 2755 0 +2607 2887 0 +2742 3019 0 +2876 3152 0 +3009 3284 0 +3143 3416 0 +3276 3548 0 +3408 3680 0 +3541 3812 0 +3673 3944 0 +3805 4076 0 +3938 4095 0 +0 608 888 +0 678 882 +0 745 882 +0 822 882 +0 882 855 +0 882 719 +0 882 436 +0 1020 0 +0 1157 0 +529 1292 0 +849 1427 0 +1084 1561 0 +1279 1695 0 +1454 1828 0 +1615 1961 0 +1768 2093 0 +1915 2226 0 +2058 2358 0 +2199 2491 0 +2336 2623 0 +2473 2755 0 +2608 2887 0 +2742 3019 0 +2877 3152 0 +3010 3283 0 +3143 3416 0 +3276 3548 0 +3408 3680 0 +3541 3812 0 +3673 3944 0 +3805 4076 0 +3938 4095 0 +0 515 888 +0 599 882 +0 691 873 +0 776 873 +0 870 873 +0 873 749 +0 873 488 +0 1014 0 +214 1152 0 +635 1289 0 +904 1424 0 +1118 1559 0 +1302 1693 0 +1469 1827 0 +1626 1960 0 +1776 2093 0 +1921 2225 0 +2062 2358 0 +2202 2490 0 +2338 2623 0 +2475 2755 0 +2609 2887 0 +2743 3019 0 +2877 3152 0 +3010 3283 0 +3143 3416 0 +3276 3548 0 +3409 3680 0 +3541 3812 0 +3673 3944 0 +3805 4076 0 +3938 4095 0 +0 350 888 +0 466 882 +0 585 873 +166 708 862 +166 815 862 +166 862 784 +166 862 550 +0 1005 0 +455 1146 0 +746 1284 0 +969 1421 0 +1159 1557 0 +1330 1691 0 +1489 1825 0 +1640 1959 0 +1786 2092 0 +1928 2225 0 +2068 2357 0 +2206 2490 0 +2341 2622 0 +2477 2755 0 +2611 2887 0 +2745 3019 0 +2878 3151 0 +3011 3283 0 +3144 3416 0 +3277 3548 0 +3409 3680 0 +3541 3812 0 +3674 3944 0 +3806 4076 0 +3938 4095 0 +0 0 888 +0 190 882 +0 390 873 +166 567 862 +412 730 846 +412 846 828 +412 846 622 +397 994 298 +655 1137 80 +862 1278 0 +1043 1416 0 +1209 1553 0 +1365 1689 0 +1514 1823 0 +1658 1958 0 +1799 2091 0 +1938 2224 0 +2075 2357 0 +2211 2489 0 +2346 2622 0 +2480 2755 0 +2613 2887 0 +2746 3019 0 +2879 3151 0 +3012 3283 0 +3144 3416 0 +3277 3548 0 +3409 3680 0 +3542 3812 0 +3674 3944 0 +3806 4076 0 +3938 4095 0 +0 0 888 +0 0 882 +0 0 873 +166 264 862 +412 541 846 +614 758 824 +614 824 702 +673 978 544 +831 1126 430 +982 1270 212 +1127 1410 0 +1269 1549 0 +1408 1685 0 +1545 1821 0 +1681 1956 0 +1816 2089 0 +1951 2223 0 +2084 2356 0 +2218 2489 0 +2351 2621 0 +2484 2754 0 +2616 2887 0 +2748 3019 0 +2881 3151 0 +3013 3283 0 +3145 3416 0 +3278 3548 0 +3410 3680 0 +3542 3812 0 +3674 3944 0 +3806 4076 0 +3938 4095 0 +392 0 888 +436 0 882 +488 0 873 +550 166 862 +622 412 846 +702 614 824 +792 792 792 +890 956 746 +994 1110 676 +1104 1258 562 +1219 1402 344 +1338 1543 0 +1460 1681 0 +1585 1817 0 +1711 1953 0 +1838 2087 0 +1967 2221 0 +2096 2355 0 +2227 2488 0 +2357 2621 0 +2489 2754 0 +2620 2886 0 +2751 3018 0 +2883 3151 0 +3015 3283 0 +3147 3415 0 +3279 3548 0 +3411 3680 0 +3543 3812 0 +3674 3944 0 +3806 4076 0 +3939 4095 0 +811 0 1025 +829 0 1020 +852 0 1014 +881 0 1005 +917 298 994 +960 544 978 +956 746 890 +956 834 746 +1110 1092 676 +1211 1258 562 +1304 1402 344 +1405 1543 0 +1512 1681 0 +1625 1817 0 +1742 1953 0 +1862 2087 0 +1985 2221 0 +2110 2355 0 +2237 2488 0 +2365 2621 0 +2494 2754 0 +2624 2886 0 +2754 3018 0 +2885 3151 0 +3016 3283 0 +3148 3415 0 +3280 3548 0 +3411 3680 0 +3543 3812 0 +3675 3944 0 +3807 4076 0 +3939 4095 0 +1079 0 1160 +1089 0 1157 +1102 0 1152 +1119 0 1146 +1137 80 1134 +1126 430 1079 +1110 676 994 +1110 676 805 +1110 886 676 +1258 1181 562 +1398 1402 344 +1482 1543 0 +1574 1681 0 +1673 1817 0 +1779 1953 0 +1891 2087 0 +2008 2221 0 +2127 2355 0 +2250 2488 0 +2375 2621 0 +2502 2754 0 +2630 2886 0 +2759 3018 0 +2889 3151 0 +3019 3283 0 +3150 3415 0 +3281 3548 0 +3412 3680 0 +3544 3812 0 +3676 3944 0 +3807 4076 0 +3939 4095 0 +1292 0 1295 +1292 0 1286 +1289 0 1271 +1284 0 1249 +1278 0 1218 +1270 212 1172 +1258 562 1104 +1258 562 963 +1258 562 661 +1258 946 562 +1402 1277 344 +1543 1516 0 +1645 1681 0 +1732 1817 0 +1826 1953 0 +1928 2087 0 +2036 2221 0 +2150 2355 0 +2267 2488 0 +2388 2621 0 +2512 2754 0 +2637 2886 0 +2764 3018 0 +2893 3151 0 +3022 3283 0 +3152 3415 0 +3283 3548 0 +3414 3680 0 +3545 3812 0 +3676 3944 0 +3808 4076 0 +3940 4095 0 +1429 0 1376 +1427 0 1366 +1424 0 1353 +1421 0 1335 +1416 0 1310 +1410 0 1273 +1402 344 1219 +1402 344 1114 +1402 344 919 +1402 344 345 +1402 1017 344 +1543 1381 0 +1681 1631 0 +1799 1817 0 +1882 1953 0 +1973 2087 0 +2072 2221 0 +2178 2355 0 +2289 2488 0 +2405 2621 0 +2525 2754 0 +2647 2886 0 +2772 3018 0 +2898 3151 0 +3026 3283 0 +3155 3415 0 +3285 3548 0 +3415 3680 0 +3546 3812 0 +3677 3944 0 +3808 4076 0 +3940 4095 0 +1563 0 1463 +1561 0 1456 +1559 0 1445 +1557 0 1430 +1553 0 1409 +1549 0 1380 +1543 0 1338 +1543 0 1259 +1543 0 1127 +1543 0 852 +1543 172 0 +1543 1096 0 +1681 1489 0 +1817 1750 0 +1947 1953 0 +2027 2087 0 +2116 2221 0 +2213 2355 0 +2317 2488 0 +2427 2621 0 +2541 2754 0 +2660 2886 0 +2782 3018 0 +2906 3151 0 +3032 3283 0 +3160 3415 0 +3288 3548 0 +3418 3680 0 +3548 3812 0 +3679 3944 0 +3810 4076 0 +3941 4095 0 +1696 0 1559 +1695 0 1552 +1693 0 1544 +1691 0 1532 +1689 0 1515 +1685 0 1492 +1681 0 1460 +1681 0 1401 +1681 0 1308 +1681 0 1142 +1681 0 742 +1681 0 0 +1681 1184 0 +1817 1604 0 +1953 1872 0 +2087 2085 0 +2169 2221 0 +2256 2355 0 +2352 2488 0 +2454 2621 0 +2563 2754 0 +2677 2886 0 +2794 3018 0 +2916 3151 0 +3039 3283 0 +3165 3415 0 +3292 3548 0 +3421 3680 0 +3550 3812 0 +3680 3944 0 +3811 4076 0 +3942 4095 0 +1828 0 1661 +1828 0 1656 +1827 0 1650 +1825 0 1640 +1823 0 1627 +1821 0 1609 +1817 0 1585 +1817 0 1540 +1817 0 1474 +1817 0 1366 +1817 0 1164 +1817 0 536 +1817 0 0 +1817 1281 0 +1953 1722 0 +2087 1996 0 +2221 2212 0 +2308 2355 0 +2394 2488 0 +2488 2621 0 +2590 2754 0 +2698 2886 0 +2811 3018 0 +2928 3151 0 +3049 3283 0 +3173 3415 0 +3298 3548 0 +3425 3680 0 +3553 3812 0 +3683 3944 0 +3812 4076 0 +3943 4095 0 +1961 0 1770 +1961 0 1766 +1960 0 1761 +1959 0 1754 +1958 0 1743 +1956 0 1730 +1953 0 1711 +1953 0 1678 +1953 0 1629 +1953 0 1555 +1953 0 1433 +1953 0 1190 +1953 0 0 +1953 0 0 +1953 1385 0 +2087 1843 0 +2221 2123 0 +2355 2340 0 +2445 2488 0 +2530 2621 0 +2624 2754 0 +2725 2886 0 +2832 3018 0 +2945 3151 0 +3062 3283 0 +3182 3415 0 +3305 3548 0 +3431 3680 0 +3558 3812 0 +3686 3944 0 +3815 4076 0 +3945 4095 0 +2094 0 1884 +2093 0 1881 +2093 0 1877 +2092 0 1871 +2091 0 1863 +2089 0 1853 +2087 0 1838 +2087 0 1813 +2087 0 1778 +2087 0 1726 +2087 0 1646 +2087 0 1509 +2087 0 1224 +2087 0 0 +2087 0 0 +2087 1494 0 +2221 1967 0 +2355 2251 0 +2488 2470 0 +2581 2621 0 +2666 2754 0 +2759 2886 0 +2859 3018 0 +2966 3151 0 +3078 3283 0 +3195 3415 0 +3315 3548 0 +3438 3680 0 +3563 3812 0 +3690 3944 0 +3818 4076 0 +3947 4095 0 +2226 0 2002 +2226 0 1999 +2225 0 1996 +2225 0 1992 +2224 0 1986 +2223 0 1978 +2221 0 1967 +2221 0 1948 +2221 0 1922 +2221 0 1885 +2221 0 1830 +2221 0 1744 +2221 0 1596 +2221 0 1264 +2221 0 0 +2221 0 0 +2221 1608 0 +2355 2093 0 +2488 2379 0 +2621 2600 0 +2716 2754 0 +2800 2886 0 +2892 3018 0 +2993 3151 0 +3099 3283 0 +3211 3415 0 +3328 3548 0 +3448 3680 0 +3571 3812 0 +3696 3944 0 +3822 4076 0 +3951 4095 0 +2358 0 2123 +2358 0 2121 +2358 0 2119 +2357 0 2115 +2357 0 2111 +2356 0 2105 +2355 0 2096 +2355 0 2083 +2355 0 2063 +2355 0 2037 +2355 0 1998 +2355 0 1940 +2355 0 1849 +2355 0 1689 +2355 0 1313 +2355 0 0 +2355 0 0 +2355 1727 0 +2488 2221 0 +2621 2509 0 +2754 2731 0 +2850 2886 0 +2934 3018 0 +3026 3151 0 +3126 3283 0 +3232 3415 0 +3344 3548 0 +3460 3680 0 +3580 3812 0 +3703 3944 0 +3828 4076 0 +3955 4095 0 +2491 0 2247 +2491 0 2245 +2490 0 2243 +2490 0 2241 +2489 0 2238 +2489 0 2233 +2488 0 2227 +2488 0 2217 +2488 0 2202 +2488 0 2183 +2488 0 2155 +2488 0 2115 +2488 0 2055 +2488 0 1960 +2488 0 1791 +2488 0 1373 +2488 0 0 +2488 0 0 +2488 1848 0 +2621 2349 0 +2754 2640 0 +2886 2862 0 +2984 3018 0 +3067 3151 0 +3159 3283 0 +3259 3415 0 +3365 3548 0 +3477 3680 0 +3593 3812 0 +3713 3944 0 +3835 4076 0 +3961 4095 0 +2623 0 2372 +2623 0 2372 +2623 0 2370 +2622 0 2368 +2622 0 2366 +2621 0 2362 +2621 0 2357 +2621 0 2350 +2621 0 2339 +2621 0 2325 +2621 0 2304 +2621 0 2276 +2621 0 2235 +2621 0 2173 +2621 0 2075 +2621 0 1899 +2621 0 1441 +2621 0 0 +2621 0 0 +2621 1972 0 +2754 2479 0 +2886 2770 0 +3018 2992 0 +3117 3151 0 +3200 3283 0 +3292 3415 0 +3392 3548 0 +3497 3680 0 +3609 3812 0 +3725 3944 0 +3845 4076 0 +3968 4095 0 +2755 0 2500 +2755 0 2499 +2755 0 2498 +2755 0 2497 +2755 0 2495 +2754 0 2492 +2754 0 2489 +2754 0 2483 +2754 0 2475 +2754 0 2464 +2754 0 2450 +2754 0 2429 +2754 0 2400 +2754 0 2358 +2754 0 2295 +2754 0 2195 +2754 0 2012 +2754 0 1521 +2754 0 0 +2754 0 0 +2754 2099 0 +2886 2609 0 +3018 2901 0 +3151 3124 0 +3250 3283 0 +3333 3415 0 +3425 3548 0 +3524 3680 0 +3630 3812 0 +3741 3944 0 +3858 4076 0 +3977 4095 0 +2887 0 2628 +2887 0 2628 +2887 0 2627 +2887 0 2626 +2887 0 2625 +2887 0 2623 +2886 0 2620 +2886 0 2616 +2886 0 2610 +2886 0 2602 +2886 0 2591 +2886 0 2576 +2886 0 2555 +2886 0 2526 +2886 0 2483 +2886 0 2419 +2886 0 2317 +2886 0 2129 +2886 0 1606 +2886 0 0 +2886 0 0 +2886 2226 0 +3018 2739 0 +3151 3032 0 +3283 3256 0 +3383 3415 0 +3466 3548 0 +3557 3680 0 +3657 3812 0 +3762 3944 0 +3874 4076 0 +3990 4095 0 +3019 0 2758 +3019 0 2757 +3019 0 2757 +3019 0 2756 +3019 0 2755 +3019 0 2753 +3018 0 2751 +3018 0 2748 +3018 0 2744 +3018 0 2738 +3018 0 2730 +3018 0 2719 +3018 0 2703 +3018 0 2683 +3018 0 2653 +3018 0 2610 +3018 0 2545 +3018 0 2441 +3018 0 2249 +3018 0 1700 +3018 0 0 +3018 0 0 +3018 2354 0 +3151 2871 0 +3283 3164 0 +3415 3387 0 +3515 3548 0 +3598 3680 0 +3690 3812 0 +3789 3944 0 +3895 4076 0 +4006 4095 0 +3152 0 2888 +3152 0 2888 +3152 0 2887 +3151 0 2886 +3151 0 2886 +3151 0 2885 +3151 0 2883 +3151 0 2881 +3151 0 2877 +3151 0 2873 +3151 0 2867 +3151 0 2859 +3151 0 2848 +3151 0 2833 +3151 0 2812 +3151 0 2782 +3151 0 2738 +3151 0 2673 +3151 0 2568 +3151 0 2373 +3151 0 1802 +3151 0 0 +3151 0 0 +3151 2484 0 +3283 3001 0 +3415 3295 0 +3548 3519 0 +3648 3680 0 +3731 3812 0 +3822 3944 0 +3921 4076 0 +4027 4095 0 +3284 0 3018 +3283 0 3018 +3283 0 3018 +3283 0 3017 +3283 0 3016 +3283 0 3016 +3283 0 3015 +3283 0 3013 +3283 0 3010 +3283 0 3007 +3283 0 3003 +3283 0 2997 +3283 0 2988 +3283 0 2977 +3283 0 2962 +3283 0 2941 +3283 0 2911 +3283 0 2867 +3283 0 2801 +3283 0 2695 +3283 0 2498 +3283 0 1908 +3283 0 0 +3283 0 0 +3283 2614 0 +3415 3133 0 +3548 3427 0 +3680 3651 0 +3781 3812 0 +3863 3944 0 +3954 4076 0 +4054 4095 0 +3416 0 3149 +3416 0 3149 +3416 0 3149 +3416 0 3148 +3416 0 3148 +3416 0 3147 +3415 0 3147 +3415 0 3145 +3415 0 3144 +3415 0 3141 +3415 0 3138 +3415 0 3133 +3415 0 3127 +3415 0 3119 +3415 0 3108 +3415 0 3093 +3415 0 3071 +3415 0 3041 +3415 0 2997 +3415 0 2931 +3415 0 2824 +3415 0 2625 +3415 0 2026 +3415 0 0 +3415 0 0 +3415 2745 0 +3548 3265 0 +3680 3559 0 +3812 3783 0 +3913 3944 0 +3995 4076 0 +4087 4095 0 +3548 0 3280 +3548 0 3280 +3548 0 3280 +3548 0 3280 +3548 0 3280 +3548 0 3279 +3548 0 3279 +3548 0 3278 +3548 0 3276 +3548 0 3274 +3548 0 3272 +3548 0 3269 +3548 0 3264 +3548 0 3258 +3548 0 3250 +3548 0 3239 +3548 0 3223 +3548 0 3202 +3548 0 3172 +3548 0 3128 +3548 0 3061 +3548 0 2954 +3548 0 2754 +3548 0 2141 +3548 0 0 +3548 0 0 +3548 2876 0 +3680 3396 0 +3812 3691 0 +3944 3915 0 +4045 4076 0 +4095 4095 0 +3680 0 3412 +3680 0 3412 +3680 0 3412 +3680 0 3412 +3680 0 3411 +3680 0 3411 +3680 0 3411 +3680 0 3410 +3680 0 3409 +3680 0 3407 +3680 0 3406 +3680 0 3403 +3680 0 3400 +3680 0 3395 +3680 0 3389 +3680 0 3381 +3680 0 3370 +3680 0 3354 +3680 0 3333 +3680 0 3303 +3680 0 3258 +3680 0 3192 +3680 0 3084 +3680 0 2883 +3680 0 2266 +3680 0 0 +3680 0 0 +3680 3007 0 +3812 3528 0 +3944 3823 0 +4076 4047 0 +4095 4095 0 +3812 0 3544 +3812 0 3544 +3812 0 3543 +3812 0 3543 +3812 0 3543 +3812 0 3543 +3812 0 3543 +3812 0 3542 +3812 0 3541 +3812 0 3540 +3812 0 3539 +3812 0 3537 +3812 0 3534 +3812 0 3531 +3812 0 3527 +3812 0 3521 +3812 0 3513 +3812 0 3501 +3812 0 3486 +3812 0 3464 +3812 0 3434 +3812 0 3390 +3812 0 3323 +3812 0 3215 +3812 0 3014 +3812 0 2389 +3812 0 0 +3812 0 0 +3812 3139 0 +3944 3660 0 +4076 3955 0 +4095 4095 0 +3944 0 3675 +3944 0 3675 +3944 0 3675 +3944 0 3675 +3944 0 3675 +3944 0 3675 +3944 0 3674 +3944 0 3674 +3944 0 3673 +3944 0 3673 +3944 0 3672 +3944 0 3670 +3944 0 3668 +3944 0 3666 +3944 0 3663 +3944 0 3658 +3944 0 3652 +3944 0 3644 +3944 0 3633 +3944 0 3617 +3944 0 3596 +3944 0 3565 +3944 0 3521 +3944 0 3454 +3944 0 3346 +3944 0 3144 +3944 0 2513 +3944 0 0 +3944 0 0 +3944 3270 0 +4076 3792 0 +4095 4087 0 +4076 0 3807 +4076 0 3807 +4076 0 3807 +4076 0 3807 +4076 0 3807 +4076 0 3807 +4076 0 3806 +4076 0 3806 +4076 0 3805 +4076 0 3805 +4076 0 3804 +4076 0 3803 +4076 0 3802 +4076 0 3800 +4076 0 3798 +4076 0 3794 +4076 0 3790 +4076 0 3784 +4076 0 3776 +4076 0 3764 +4076 0 3749 +4076 0 3727 +4076 0 3697 +4076 0 3653 +4076 0 3586 +4076 0 3477 +4076 0 3274 +4076 0 2639 +4076 0 0 +4076 0 0 +4076 3402 0 +4095 3925 0 +4095 0 3939 +4095 0 3939 +4095 0 3939 +4095 0 3939 +4095 0 3939 +4095 0 3939 +4095 0 3939 +4095 0 3938 +4095 0 3938 +4095 0 3938 +4095 0 3937 +4095 0 3937 +4095 0 3935 +4095 0 3934 +4095 0 3932 +4095 0 3930 +4095 0 3927 +4095 0 3922 +4095 0 3916 +4095 0 3908 +4095 0 3896 +4095 0 3881 +4095 0 3859 +4095 0 3829 +4095 0 3784 +4095 0 3718 +4095 0 3609 +4095 0 3406 +4095 0 2770 +4095 0 0 +4095 0 0 +4095 3534 0 +0 792 1025 +0 832 1025 +0 881 1025 +0 939 1025 +0 1006 1025 +0 1025 957 +0 1025 811 +0 1025 488 +0 1160 0 +0 1295 0 +471 1429 0 +897 1563 0 +1167 1696 0 +1381 1828 0 +1565 1961 0 +1733 2094 0 +1890 2226 0 +2040 2358 0 +2185 2491 0 +2327 2623 0 +2466 2755 0 +2603 2887 0 +2738 3019 0 +2873 3152 0 +3008 3284 0 +3141 3416 0 +3275 3548 0 +3408 3680 0 +3540 3812 0 +3673 3944 0 +3805 4076 0 +3938 4095 0 +0 748 1025 +0 800 1020 +0 852 1020 +0 914 1020 +0 985 1020 +0 1020 970 +0 1020 829 +0 1020 524 +0 1157 0 +0 1292 0 +562 1427 0 +935 1561 0 +1188 1695 0 +1394 1828 0 +1574 1961 0 +1739 2093 0 +1894 2226 0 +2043 2358 0 +2187 2491 0 +2328 2623 0 +2467 2755 0 +2604 2887 0 +2739 3019 0 +2874 3152 0 +3008 3283 0 +3141 3416 0 +3275 3548 0 +3408 3680 0 +3540 3812 0 +3673 3944 0 +3805 4076 0 +3938 4095 0 +0 681 1025 +0 740 1020 +0 810 1014 +0 877 1014 +0 954 1014 +0 1014 987 +0 1014 852 +0 1014 568 +0 1152 0 +9 1289 0 +662 1424 0 +981 1559 0 +1216 1693 0 +1412 1827 0 +1586 1960 0 +1748 2093 0 +1900 2225 0 +2047 2358 0 +2190 2490 0 +2331 2623 0 +2469 2755 0 +2605 2887 0 +2740 3019 0 +2875 3152 0 +3008 3283 0 +3142 3416 0 +3275 3548 0 +3408 3680 0 +3541 3812 0 +3673 3944 0 +3805 4076 0 +3938 4095 0 +0 573 1025 +0 647 1020 +0 731 1014 +0 823 1005 +0 908 1005 +0 1002 1005 +0 1005 881 +0 1005 620 +0 1146 0 +346 1284 0 +767 1421 0 +1037 1557 0 +1249 1691 0 +1434 1825 0 +1601 1959 0 +1758 2092 0 +1908 2225 0 +2053 2357 0 +2195 2490 0 +2334 2622 0 +2471 2755 0 +2607 2887 0 +2741 3019 0 +2876 3151 0 +3009 3283 0 +3142 3416 0 +3275 3548 0 +3408 3680 0 +3541 3812 0 +3673 3944 0 +3805 4076 0 +3938 4095 0 +0 371 1025 +0 482 1020 +0 598 1014 +0 717 1005 +298 840 994 +298 947 994 +298 994 917 +298 994 682 +81 1137 80 +587 1278 0 +878 1416 0 +1102 1553 0 +1291 1689 0 +1462 1823 0 +1621 1958 0 +1772 2091 0 +1918 2224 0 +2060 2357 0 +2200 2489 0 +2337 2622 0 +2474 2755 0 +2609 2887 0 +2743 3019 0 +2877 3151 0 +3010 3283 0 +3143 3416 0 +3276 3548 0 +3409 3680 0 +3541 3812 0 +3673 3944 0 +3805 4076 0 +3938 4095 0 +0 0 1025 +0 81 1020 +0 323 1014 +0 523 1005 +298 699 994 +544 862 978 +544 978 960 +544 978 754 +529 1126 430 +787 1270 212 +994 1410 0 +1176 1549 0 +1341 1685 0 +1497 1821 0 +1646 1956 0 +1790 2089 0 +1931 2223 0 +2070 2356 0 +2207 2489 0 +2343 2621 0 +2478 2754 0 +2612 2887 0 +2745 3019 0 +2879 3151 0 +3011 3283 0 +3144 3416 0 +3277 3548 0 +3409 3680 0 +3541 3812 0 +3674 3944 0 +3806 4076 0 +3938 4095 0 +0 0 1025 +0 0 1020 +0 0 1014 +0 0 1005 +298 397 994 +544 673 978 +746 890 956 +746 956 834 +805 1110 676 +963 1258 562 +1114 1402 344 +1259 1543 0 +1401 1681 0 +1540 1817 0 +1678 1953 0 +1813 2087 0 +1948 2221 0 +2083 2355 0 +2217 2488 0 +2350 2621 0 +2483 2754 0 +2616 2886 0 +2748 3018 0 +2881 3151 0 +3013 3283 0 +3145 3415 0 +3278 3548 0 +3410 3680 0 +3542 3812 0 +3674 3944 0 +3806 4076 0 +3938 4095 0 +488 0 1025 +524 0 1020 +568 0 1014 +620 0 1005 +682 298 994 +754 544 978 +834 746 956 +924 924 924 +1021 1088 878 +1126 1242 809 +1236 1390 695 +1351 1534 476 +1470 1674 0 +1592 1813 0 +1716 1950 0 +1843 2085 0 +1970 2220 0 +2099 2353 0 +2229 2487 0 +2359 2620 0 +2490 2753 0 +2621 2886 0 +2752 3018 0 +2883 3151 0 +3015 3283 0 +3147 3415 0 +3279 3548 0 +3411 3680 0 +3543 3812 0 +3674 3944 0 +3806 4076 0 +3939 4095 0 +929 0 1160 +943 0 1157 +960 0 1152 +983 0 1146 +1013 80 1137 +1049 430 1126 +1092 676 1110 +1088 878 1021 +1088 967 878 +1242 1225 809 +1343 1390 695 +1437 1534 476 +1537 1674 0 +1644 1813 0 +1757 1950 0 +1873 2085 0 +1994 2220 0 +2117 2353 0 +2242 2487 0 +2369 2620 0 +2497 2753 0 +2626 2886 0 +2756 3018 0 +2887 3151 0 +3017 3283 0 +3149 3415 0 +3280 3548 0 +3412 3680 0 +3543 3812 0 +3675 3944 0 +3807 4076 0 +3939 4095 0 +1204 0 1295 +1211 0 1292 +1221 0 1289 +1235 0 1284 +1251 0 1278 +1270 212 1266 +1258 562 1211 +1242 809 1126 +1242 809 938 +1242 1018 809 +1390 1313 695 +1531 1534 476 +1614 1674 0 +1706 1813 0 +1806 1950 0 +1912 2085 0 +2023 2220 0 +2140 2353 0 +2260 2487 0 +2382 2620 0 +2507 2753 0 +2634 2886 0 +2762 3018 0 +2891 3151 0 +3021 3283 0 +3151 3415 0 +3282 3548 0 +3413 3680 0 +3544 3812 0 +3676 3944 0 +3808 4076 0 +3940 4095 0 +1419 0 1429 +1424 0 1427 +1424 0 1418 +1421 0 1403 +1416 0 1381 +1410 0 1350 +1402 344 1304 +1390 695 1236 +1390 695 1095 +1390 695 793 +1390 1078 695 +1534 1409 476 +1674 1648 0 +1777 1813 0 +1864 1950 0 +1958 2085 0 +2060 2220 0 +2168 2353 0 +2282 2487 0 +2399 2620 0 +2521 2753 0 +2644 2886 0 +2769 3018 0 +2896 3151 0 +3025 3283 0 +3154 3415 0 +3284 3548 0 +3415 3680 0 +3546 3812 0 +3677 3944 0 +3808 4076 0 +3940 4095 0 +1563 0 1515 +1561 0 1508 +1559 0 1499 +1557 0 1486 +1553 0 1467 +1549 0 1442 +1543 0 1405 +1534 476 1351 +1534 476 1246 +1534 476 1051 +1534 476 479 +1534 1149 476 +1674 1512 0 +1813 1763 0 +1931 1950 0 +2014 2085 0 +2105 2220 0 +2204 2353 0 +2310 2487 0 +2421 2620 0 +2537 2753 0 +2657 2886 0 +2779 3018 0 +2904 3151 0 +3031 3283 0 +3158 3415 0 +3287 3548 0 +3417 3680 0 +3548 3812 0 +3678 3944 0 +3809 4076 0 +3941 4095 0 +1696 0 1601 +1695 0 1596 +1693 0 1588 +1691 0 1577 +1689 0 1562 +1685 0 1541 +1681 0 1512 +1674 0 1470 +1674 0 1391 +1674 0 1258 +1674 0 983 +1674 313 0 +1674 1228 0 +1813 1622 0 +1950 1882 0 +2079 2085 0 +2159 2220 0 +2248 2353 0 +2345 2487 0 +2449 2620 0 +2559 2753 0 +2673 2886 0 +2792 3018 0 +2914 3151 0 +3038 3283 0 +3164 3415 0 +3292 3548 0 +3420 3680 0 +3550 3812 0 +3680 3944 0 +3810 4076 0 +3942 4095 0 +1828 0 1696 +1828 0 1691 +1827 0 1684 +1825 0 1676 +1823 0 1664 +1821 0 1648 +1817 0 1625 +1813 0 1592 +1813 0 1533 +1813 0 1440 +1813 0 1275 +1813 0 874 +1813 0 0 +1813 1317 0 +1950 1736 0 +2085 2004 0 +2220 2217 0 +2301 2353 0 +2388 2487 0 +2483 2620 0 +2586 2753 0 +2695 2886 0 +2808 3018 0 +2927 3151 0 +3047 3283 0 +3171 3415 0 +3297 3548 0 +3425 3680 0 +3553 3812 0 +3682 3944 0 +3812 4076 0 +3943 4095 0 +1961 0 1797 +1961 0 1793 +1960 0 1789 +1959 0 1781 +1958 0 1772 +1956 0 1759 +1953 0 1742 +1950 0 1716 +1950 0 1672 +1950 0 1606 +1950 0 1498 +1950 0 1295 +1950 0 670 +1950 0 0 +1950 1413 0 +2085 1854 0 +2220 2128 0 +2353 2344 0 +2440 2487 0 +2526 2620 0 +2620 2753 0 +2722 2886 0 +2830 3018 0 +2943 3151 0 +3060 3283 0 +3181 3415 0 +3305 3548 0 +3430 3680 0 +3557 3812 0 +3686 3944 0 +3815 4076 0 +3945 4095 0 +2094 0 1905 +2093 0 1902 +2093 0 1898 +2092 0 1893 +2091 0 1885 +2089 0 1875 +2087 0 1862 +2085 0 1843 +2085 0 1810 +2085 0 1761 +2085 0 1687 +2085 0 1565 +2085 0 1322 +2085 0 10 +2085 0 0 +2085 1517 0 +2220 1975 0 +2353 2255 0 +2487 2473 0 +2577 2620 0 +2662 2753 0 +2756 2886 0 +2857 3018 0 +2964 3151 0 +3077 3283 0 +3194 3415 0 +3314 3548 0 +3437 3680 0 +3563 3812 0 +3690 3944 0 +3818 4076 0 +3947 4095 0 +2226 0 2018 +2226 0 2016 +2225 0 2013 +2225 0 2009 +2224 0 2003 +2223 0 1995 +2221 0 1985 +2220 0 1970 +2220 0 1946 +2220 0 1910 +2220 0 1858 +2220 0 1778 +2220 0 1642 +2220 0 1355 +2220 0 0 +2220 0 0 +2220 1626 0 +2353 2099 0 +2487 2383 0 +2620 2602 0 +2713 2753 0 +2798 2886 0 +2890 3018 0 +2991 3151 0 +3098 3283 0 +3210 3415 0 +3327 3548 0 +3447 3680 0 +3570 3812 0 +3695 3944 0 +3822 4076 0 +3950 4095 0 +2358 0 2136 +2358 0 2134 +2358 0 2132 +2357 0 2128 +2357 0 2124 +2356 0 2118 +2355 0 2110 +2353 0 2099 +2353 0 2081 +2353 0 2054 +2353 0 2017 +2353 0 1962 +2353 0 1876 +2353 0 1727 +2353 0 1396 +2353 0 0 +2353 0 0 +2353 1740 0 +2487 2226 0 +2620 2511 0 +2753 2732 0 +2848 2886 0 +2932 3018 0 +3025 3151 0 +3125 3283 0 +3231 3415 0 +3343 3548 0 +3460 3680 0 +3580 3812 0 +3703 3944 0 +3828 4076 0 +3955 4095 0 +2491 0 2256 +2491 0 2255 +2490 0 2253 +2490 0 2251 +2489 0 2247 +2489 0 2243 +2488 0 2237 +2487 0 2229 +2487 0 2215 +2487 0 2196 +2487 0 2169 +2487 0 2130 +2487 0 2072 +2487 0 1981 +2487 0 1822 +2487 0 1446 +2487 0 0 +2487 0 0 +2487 1859 0 +2620 2352 0 +2753 2641 0 +2886 2863 0 +2982 3018 0 +3066 3151 0 +3158 3283 0 +3258 3415 0 +3364 3548 0 +3476 3680 0 +3593 3812 0 +3712 3944 0 +3835 4076 0 +3960 4095 0 +2623 0 2380 +2623 0 2379 +2623 0 2378 +2622 0 2375 +2622 0 2373 +2621 0 2370 +2621 0 2365 +2620 0 2359 +2620 0 2348 +2620 0 2334 +2620 0 2314 +2620 0 2287 +2620 0 2247 +2620 0 2187 +2620 0 2092 +2620 0 1923 +2620 0 1505 +2620 0 0 +2620 0 0 +2620 1981 0 +2753 2482 0 +2886 2772 0 +3018 2993 0 +3116 3151 0 +3199 3283 0 +3291 3415 0 +3391 3548 0 +3497 3680 0 +3609 3812 0 +3725 3944 0 +3845 4076 0 +3968 4095 0 +2755 0 2505 +2755 0 2505 +2755 0 2504 +2755 0 2502 +2755 0 2501 +2754 0 2498 +2754 0 2494 +2753 0 2490 +2753 0 2482 +2753 0 2471 +2753 0 2457 +2753 0 2437 +2753 0 2408 +2753 0 2367 +2753 0 2305 +2753 0 2208 +2753 0 2031 +2753 0 1575 +2753 0 0 +2753 0 0 +2753 2105 0 +2886 2611 0 +3018 2902 0 +3151 3125 0 +3249 3283 0 +3333 3415 0 +3424 3548 0 +3524 3680 0 +3630 3812 0 +3741 3944 0 +3857 4076 0 +3977 4095 0 +2887 0 2633 +2887 0 2632 +2887 0 2631 +2887 0 2630 +2887 0 2629 +2887 0 2627 +2886 0 2624 +2886 0 2621 +2886 0 2615 +2886 0 2607 +2886 0 2596 +2886 0 2581 +2886 0 2561 +2886 0 2532 +2886 0 2490 +2886 0 2427 +2886 0 2327 +2886 0 2144 +2886 0 1651 +2886 0 0 +2886 0 0 +2886 2231 0 +3018 2740 0 +3151 3033 0 +3283 3256 0 +3382 3415 0 +3466 3548 0 +3557 3680 0 +3656 3812 0 +3762 3944 0 +3873 4076 0 +3990 4095 0 +3019 0 2761 +3019 0 2760 +3019 0 2760 +3019 0 2759 +3019 0 2758 +3019 0 2756 +3018 0 2754 +3018 0 2752 +3018 0 2747 +3018 0 2742 +3018 0 2734 +3018 0 2723 +3018 0 2708 +3018 0 2687 +3018 0 2658 +3018 0 2615 +3018 0 2551 +3018 0 2449 +3018 0 2261 +3018 0 1737 +3018 0 0 +3018 0 0 +3018 2358 0 +3151 2872 0 +3283 3164 0 +3415 3388 0 +3515 3548 0 +3598 3680 0 +3690 3812 0 +3789 3944 0 +3895 4076 0 +4006 4095 0 +3152 0 2890 +3152 0 2890 +3152 0 2890 +3151 0 2889 +3151 0 2888 +3151 0 2887 +3151 0 2885 +3151 0 2883 +3151 0 2880 +3151 0 2876 +3151 0 2870 +3151 0 2862 +3151 0 2851 +3151 0 2836 +3151 0 2815 +3151 0 2785 +3151 0 2742 +3151 0 2678 +3151 0 2573 +3151 0 2382 +3151 0 1832 +3151 0 0 +3151 0 0 +3151 2487 0 +3283 3002 0 +3415 3296 0 +3548 3520 0 +3648 3680 0 +3730 3812 0 +3822 3944 0 +3921 4076 0 +4027 4095 0 +3284 0 3020 +3283 0 3020 +3283 0 3019 +3283 0 3019 +3283 0 3018 +3283 0 3018 +3283 0 3016 +3283 0 3015 +3283 0 3013 +3283 0 3009 +3283 0 3005 +3283 0 2999 +3283 0 2991 +3283 0 2980 +3283 0 2965 +3283 0 2943 +3283 0 2914 +3283 0 2870 +3283 0 2805 +3283 0 2700 +3283 0 2504 +3283 0 1932 +3283 0 0 +3283 0 0 +3283 2616 0 +3415 3134 0 +3548 3428 0 +3680 3652 0 +3780 3812 0 +3863 3944 0 +3954 4076 0 +4053 4095 0 +3416 0 3151 +3416 0 3151 +3416 0 3150 +3416 0 3150 +3416 0 3149 +3416 0 3149 +3415 0 3148 +3415 0 3147 +3415 0 3145 +3415 0 3143 +3415 0 3139 +3415 0 3135 +3415 0 3129 +3415 0 3121 +3415 0 3110 +3415 0 3094 +3415 0 3073 +3415 0 3043 +3415 0 2999 +3415 0 2934 +3415 0 2827 +3415 0 2630 +3415 0 2044 +3415 0 0 +3415 0 0 +3415 2746 0 +3548 3265 0 +3680 3559 0 +3812 3784 0 +3912 3944 0 +3995 4076 0 +4087 4095 0 +3548 0 3281 +3548 0 3281 +3548 0 3281 +3548 0 3281 +3548 0 3280 +3548 0 3280 +3548 0 3280 +3548 0 3279 +3548 0 3277 +3548 0 3276 +3548 0 3273 +3548 0 3270 +3548 0 3265 +3548 0 3259 +3548 0 3251 +3548 0 3240 +3548 0 3225 +3548 0 3203 +3548 0 3173 +3548 0 3129 +3548 0 3063 +3548 0 2956 +3548 0 2758 +3548 0 2156 +3548 0 0 +3548 0 0 +3548 2877 0 +3680 3397 0 +3812 3691 0 +3944 3915 0 +4045 4076 0 +4095 4095 0 +3680 0 3413 +3680 0 3413 +3680 0 3413 +3680 0 3412 +3680 0 3412 +3680 0 3412 +3680 0 3411 +3680 0 3411 +3680 0 3410 +3680 0 3408 +3680 0 3406 +3680 0 3404 +3680 0 3401 +3680 0 3396 +3680 0 3390 +3680 0 3382 +3680 0 3371 +3680 0 3356 +3680 0 3334 +3680 0 3304 +3680 0 3260 +3680 0 3193 +3680 0 3086 +3680 0 2886 +3680 0 2277 +3680 0 0 +3680 0 0 +3680 3008 0 +3812 3529 0 +3944 3823 0 +4076 4047 0 +4095 4095 0 +3812 0 3544 +3812 0 3544 +3812 0 3544 +3812 0 3544 +3812 0 3544 +3812 0 3543 +3812 0 3543 +3812 0 3543 +3812 0 3542 +3812 0 3541 +3812 0 3540 +3812 0 3538 +3812 0 3535 +3812 0 3532 +3812 0 3528 +3812 0 3521 +3812 0 3513 +3812 0 3502 +3812 0 3487 +3812 0 3465 +3812 0 3435 +3812 0 3391 +3812 0 3324 +3812 0 3216 +3812 0 3016 +3812 0 2397 +3812 0 0 +3812 0 0 +3812 3139 0 +3944 3660 0 +4076 3955 0 +4095 4095 0 +3944 0 3676 +3944 0 3676 +3944 0 3676 +3944 0 3676 +3944 0 3675 +3944 0 3675 +3944 0 3675 +3944 0 3674 +3944 0 3674 +3944 0 3673 +3944 0 3672 +3944 0 3671 +3944 0 3669 +3944 0 3666 +3944 0 3663 +3944 0 3659 +3944 0 3653 +3944 0 3645 +3944 0 3633 +3944 0 3618 +3944 0 3596 +3944 0 3566 +3944 0 3522 +3944 0 3455 +3944 0 3347 +3944 0 3145 +3944 0 2520 +3944 0 0 +3944 0 0 +3944 3271 0 +4076 3792 0 +4095 4087 0 +4076 0 3808 +4076 0 3807 +4076 0 3807 +4076 0 3807 +4076 0 3807 +4076 0 3807 +4076 0 3807 +4076 0 3806 +4076 0 3806 +4076 0 3805 +4076 0 3805 +4076 0 3804 +4076 0 3802 +4076 0 3801 +4076 0 3798 +4076 0 3795 +4076 0 3790 +4076 0 3784 +4076 0 3776 +4076 0 3765 +4076 0 3749 +4076 0 3728 +4076 0 3697 +4076 0 3653 +4076 0 3586 +4076 0 3478 +4076 0 3276 +4076 0 2644 +4076 0 0 +4076 0 0 +4076 3402 0 +4095 3925 0 +4095 0 3939 +4095 0 3939 +4095 0 3939 +4095 0 3939 +4095 0 3939 +4095 0 3939 +4095 0 3939 +4095 0 3939 +4095 0 3938 +4095 0 3938 +4095 0 3937 +4095 0 3937 +4095 0 3936 +4095 0 3934 +4095 0 3932 +4095 0 3930 +4095 0 3927 +4095 0 3922 +4095 0 3916 +4095 0 3908 +4095 0 3897 +4095 0 3881 +4095 0 3860 +4095 0 3829 +4095 0 3785 +4095 0 3718 +4095 0 3610 +4095 0 3407 +4095 0 2773 +4095 0 0 +4095 0 0 +4095 3534 0 +0 918 1160 +0 949 1160 +0 987 1160 +0 1033 1160 +0 1089 1160 +0 1154 1160 +0 1160 1079 +0 1160 929 +0 1160 592 +0 1295 0 +0 1429 0 +523 1563 0 +998 1696 0 +1283 1828 0 +1503 1961 0 +1691 2094 0 +1860 2226 0 +2019 2358 0 +2170 2491 0 +2315 2623 0 +2457 2755 0 +2597 2887 0 +2734 3019 0 +2870 3152 0 +3005 3284 0 +3139 3416 0 +3273 3548 0 +3406 3680 0 +3540 3812 0 +3672 3944 0 +3805 4076 0 +3937 4095 0 +0 885 1160 +0 924 1157 +0 964 1157 +0 1013 1157 +0 1071 1157 +0 1139 1157 +0 1157 1089 +0 1157 943 +0 1157 620 +0 1292 0 +0 1427 0 +605 1561 0 +1029 1695 0 +1300 1828 0 +1513 1961 0 +1698 2093 0 +1865 2226 0 +2022 2358 0 +2172 2491 0 +2317 2623 0 +2459 2755 0 +2598 2887 0 +2735 3019 0 +2871 3152 0 +3005 3283 0 +3140 3416 0 +3273 3548 0 +3407 3680 0 +3540 3812 0 +3672 3944 0 +3805 4076 0 +3937 4095 0 +0 836 1160 +0 879 1157 +0 932 1152 +0 984 1152 +0 1045 1152 +0 1117 1152 +0 1152 1102 +0 1152 960 +0 1152 656 +0 1289 0 +0 1424 0 +696 1559 0 +1067 1693 0 +1321 1827 0 +1526 1960 0 +1706 2093 0 +1871 2225 0 +2027 2358 0 +2175 2490 0 +2320 2623 0 +2460 2755 0 +2599 2887 0 +2735 3019 0 +2871 3152 0 +3006 3283 0 +3140 3416 0 +3274 3548 0 +3407 3680 0 +3540 3812 0 +3673 3944 0 +3805 4076 0 +3937 4095 0 +0 762 1160 +0 813 1157 +0 873 1152 +0 942 1146 +0 1009 1146 +0 1086 1146 +0 1146 1119 +0 1146 983 +0 1146 700 +0 1284 0 +141 1421 0 +794 1557 0 +1113 1691 0 +1348 1825 0 +1544 1959 0 +1718 2092 0 +1880 2225 0 +2032 2357 0 +2180 2490 0 +2323 2622 0 +2463 2755 0 +2601 2887 0 +2737 3019 0 +2872 3151 0 +3007 3283 0 +3141 3416 0 +3274 3548 0 +3407 3680 0 +3540 3812 0 +3673 3944 0 +3805 4076 0 +3938 4095 0 +0 640 1160 +0 705 1157 +0 779 1152 +0 863 1146 +80 955 1137 +80 1040 1137 +80 1134 1137 +80 1137 1013 +80 1137 753 +0 1278 0 +478 1416 0 +900 1553 0 +1169 1689 0 +1382 1823 0 +1566 1958 0 +1733 2091 0 +1891 2224 0 +2040 2357 0 +2185 2489 0 +2327 2622 0 +2466 2755 0 +2603 2887 0 +2738 3019 0 +2873 3151 0 +3008 3283 0 +3141 3416 0 +3275 3548 0 +3408 3680 0 +3540 3812 0 +3673 3944 0 +3805 4076 0 +3938 4095 0 +0 397 1160 +0 503 1157 +0 614 1152 +0 730 1146 +80 850 1137 +430 972 1126 +430 1079 1126 +430 1126 1049 +430 1126 814 +214 1270 212 +719 1410 0 +1011 1549 0 +1233 1685 0 +1423 1821 0 +1594 1956 0 +1753 2089 0 +1904 2223 0 +2050 2356 0 +2193 2489 0 +2332 2621 0 +2470 2754 0 +2606 2887 0 +2741 3019 0 +2875 3151 0 +3009 3283 0 +3142 3416 0 +3275 3548 0 +3408 3680 0 +3541 3812 0 +3673 3944 0 +3805 4076 0 +3938 4095 0 +0 0 1160 +0 0 1157 +0 214 1152 +0 455 1146 +80 655 1137 +430 831 1126 +676 994 1110 +676 1110 1092 +676 1110 886 +661 1258 562 +919 1402 344 +1127 1543 0 +1308 1681 0 +1474 1817 0 +1629 1953 0 +1778 2087 0 +1922 2221 0 +2063 2355 0 +2202 2488 0 +2339 2621 0 +2475 2754 0 +2610 2886 0 +2744 3018 0 +2877 3151 0 +3010 3283 0 +3144 3415 0 +3276 3548 0 +3409 3680 0 +3541 3812 0 +3673 3944 0 +3805 4076 0 +3938 4095 0 +0 0 1160 +0 0 1157 +0 0 1152 +0 0 1146 +80 81 1137 +430 529 1126 +676 805 1110 +878 1021 1088 +878 1088 967 +938 1242 809 +1095 1390 695 +1246 1534 476 +1391 1674 0 +1533 1813 0 +1672 1950 0 +1810 2085 0 +1946 2220 0 +2081 2353 0 +2215 2487 0 +2348 2620 0 +2482 2753 0 +2615 2886 0 +2747 3018 0 +2880 3151 0 +3013 3283 0 +3145 3415 0 +3277 3548 0 +3410 3680 0 +3542 3812 0 +3674 3944 0 +3806 4076 0 +3938 4095 0 +592 0 1160 +620 0 1157 +656 0 1152 +700 0 1146 +753 80 1137 +814 430 1126 +886 676 1110 +967 878 1088 +1056 1056 1056 +1154 1220 1010 +1258 1374 940 +1368 1523 826 +1483 1666 608 +1602 1807 0 +1724 1945 0 +1849 2082 0 +1975 2217 0 +2102 2352 0 +2231 2486 0 +2361 2619 0 +2491 2752 0 +2622 2885 0 +2752 3018 0 +2884 3151 0 +3015 3283 0 +3147 3415 0 +3279 3548 0 +3411 3680 0 +3543 3812 0 +3675 3944 0 +3807 4076 0 +3939 4095 0 +1051 0 1295 +1062 0 1292 +1075 0 1289 +1093 0 1284 +1116 0 1278 +1145 212 1270 +1181 562 1258 +1225 809 1242 +1220 1010 1154 +1220 1099 1010 +1374 1357 940 +1476 1523 826 +1569 1666 608 +1669 1807 0 +1776 1945 0 +1889 2082 0 +2006 2217 0 +2126 2352 0 +2249 2486 0 +2374 2619 0 +2501 2752 0 +2629 2885 0 +2758 3018 0 +2888 3151 0 +3018 3283 0 +3150 3415 0 +3281 3548 0 +3412 3680 0 +3544 3812 0 +3675 3944 0 +3807 4076 0 +3939 4095 0 +1330 0 1429 +1336 0 1427 +1343 0 1424 +1353 0 1421 +1367 0 1416 +1383 0 1410 +1402 344 1398 +1390 695 1343 +1374 940 1258 +1374 940 1069 +1374 1150 940 +1523 1445 826 +1663 1666 608 +1746 1807 0 +1838 1945 0 +1938 2082 0 +2044 2217 0 +2155 2352 0 +2272 2486 0 +2392 2619 0 +2514 2752 0 +2639 2885 0 +2766 3018 0 +2894 3151 0 +3023 3283 0 +3153 3415 0 +3283 3548 0 +3414 3680 0 +3545 3812 0 +3676 3944 0 +3808 4076 0 +3940 4095 0 +1548 0 1563 +1552 0 1561 +1556 0 1559 +1557 0 1551 +1553 0 1535 +1549 0 1513 +1543 0 1482 +1534 476 1437 +1523 826 1368 +1523 826 1228 +1523 826 926 +1523 1211 826 +1666 1541 608 +1807 1780 0 +1909 1945 0 +1996 2082 0 +2090 2217 0 +2192 2352 0 +2301 2486 0 +2414 2619 0 +2532 2752 0 +2652 2885 0 +2776 3018 0 +2902 3151 0 +3029 3283 0 +3157 3415 0 +3286 3548 0 +3416 3680 0 +3547 3812 0 +3678 3944 0 +3809 4076 0 +3941 4095 0 +1696 0 1653 +1695 0 1647 +1693 0 1640 +1691 0 1631 +1689 0 1617 +1685 0 1599 +1681 0 1574 +1674 0 1537 +1666 608 1483 +1666 608 1378 +1666 608 1183 +1666 609 608 +1666 1281 608 +1807 1644 0 +1945 1895 0 +2063 2082 0 +2146 2217 0 +2237 2352 0 +2336 2486 0 +2442 2619 0 +2553 2752 0 +2669 2885 0 +2789 3018 0 +2911 3151 0 +3036 3283 0 +3163 3415 0 +3291 3548 0 +3420 3680 0 +3549 3812 0 +3680 3944 0 +3810 4076 0 +3941 4095 0 +1828 0 1738 +1828 0 1733 +1827 0 1727 +1825 0 1720 +1823 0 1709 +1821 0 1694 +1817 0 1673 +1813 0 1644 +1807 0 1602 +1807 0 1523 +1807 0 1391 +1807 0 1115 +1807 438 0 +1807 1360 0 +1945 1754 0 +2082 2014 0 +2211 2217 0 +2291 2352 0 +2380 2486 0 +2477 2619 0 +2581 2752 0 +2691 2885 0 +2805 3018 0 +2924 3151 0 +3046 3283 0 +3170 3415 0 +3296 3548 0 +3424 3680 0 +3552 3812 0 +3682 3944 0 +3812 4076 0 +3943 4095 0 +1961 0 1831 +1961 0 1828 +1960 0 1823 +1959 0 1817 +1958 0 1808 +1956 0 1796 +1953 0 1779 +1950 0 1757 +1945 0 1724 +1945 0 1665 +1945 0 1572 +1945 0 1407 +1945 0 1007 +1945 37 0 +1945 1449 0 +2082 1868 0 +2217 2136 0 +2352 2349 0 +2433 2486 0 +2520 2619 0 +2616 2752 0 +2718 2885 0 +2827 3018 0 +2941 3151 0 +3059 3283 0 +3180 3415 0 +3303 3548 0 +3429 3680 0 +3557 3812 0 +3685 3944 0 +3814 4076 0 +3945 4095 0 +2094 0 1932 +2093 0 1929 +2093 0 1926 +2092 0 1920 +2091 0 1913 +2089 0 1904 +2087 0 1891 +2085 0 1873 +2082 0 1849 +2082 0 1804 +2082 0 1738 +2082 0 1630 +2082 0 1428 +2082 0 800 +2082 0 0 +2082 1545 0 +2217 1986 0 +2352 2261 0 +2486 2476 0 +2572 2619 0 +2658 2752 0 +2752 2885 0 +2854 3018 0 +2962 3151 0 +3075 3283 0 +3192 3415 0 +3313 3548 0 +3437 3680 0 +3562 3812 0 +3689 3944 0 +3818 4076 0 +3947 4095 0 +2226 0 2039 +2226 0 2037 +2225 0 2034 +2225 0 2030 +2224 0 2025 +2223 0 2018 +2221 0 2008 +2220 0 1994 +2217 0 1975 +2217 0 1941 +2217 0 1894 +2217 0 1819 +2217 0 1697 +2217 0 1454 +2217 0 140 +2217 0 0 +2217 1649 0 +2352 2107 0 +2486 2387 0 +2619 2604 0 +2710 2752 0 +2795 2885 0 +2888 3018 0 +2989 3151 0 +3096 3283 0 +3209 3415 0 +3326 3548 0 +3446 3680 0 +3570 3812 0 +3695 3944 0 +3822 4076 0 +3950 4095 0 +2358 0 2152 +2358 0 2150 +2358 0 2148 +2357 0 2145 +2357 0 2141 +2356 0 2135 +2355 0 2127 +2353 0 2117 +2352 0 2102 +2352 0 2078 +2352 0 2042 +2352 0 1990 +2352 0 1910 +2352 0 1773 +2352 0 1487 +2352 0 0 +2352 0 0 +2352 1758 0 +2486 2232 0 +2619 2515 0 +2752 2734 0 +2845 2885 0 +2930 3018 0 +3023 3151 0 +3123 3283 0 +3230 3415 0 +3342 3548 0 +3459 3680 0 +3579 3812 0 +3702 3944 0 +3827 4076 0 +3954 4095 0 +2491 0 2269 +2491 0 2268 +2490 0 2266 +2490 0 2264 +2489 0 2260 +2489 0 2256 +2488 0 2250 +2487 0 2242 +2486 0 2231 +2486 0 2213 +2486 0 2187 +2486 0 2149 +2486 0 2094 +2486 0 2008 +2486 0 1859 +2486 0 1529 +2486 0 0 +2486 0 0 +2486 1873 0 +2619 2357 0 +2752 2644 0 +2885 2864 0 +2980 3018 0 +3064 3151 0 +3157 3283 0 +3257 3415 0 +3363 3548 0 +3475 3680 0 +3592 3812 0 +3712 3944 0 +3835 4076 0 +3960 4095 0 +2623 0 2390 +2623 0 2388 +2623 0 2387 +2622 0 2385 +2622 0 2383 +2621 0 2380 +2621 0 2375 +2620 0 2369 +2619 0 2361 +2619 0 2347 +2619 0 2328 +2619 0 2301 +2619 0 2262 +2619 0 2204 +2619 0 2113 +2619 0 1954 +2619 0 1578 +2619 0 0 +2619 0 0 +2619 1991 0 +2752 2485 0 +2885 2773 0 +3018 2995 0 +3115 3151 0 +3198 3283 0 +3290 3415 0 +3390 3548 0 +3496 3680 0 +3608 3812 0 +3725 3944 0 +3845 4076 0 +3967 4095 0 +2755 0 2513 +2755 0 2512 +2755 0 2511 +2755 0 2510 +2755 0 2508 +2754 0 2505 +2754 0 2502 +2753 0 2497 +2752 0 2491 +2752 0 2481 +2752 0 2467 +2752 0 2447 +2752 0 2419 +2752 0 2379 +2752 0 2319 +2752 0 2224 +2752 0 2056 +2752 0 1638 +2752 0 0 +2752 0 0 +2752 2113 0 +2885 2613 0 +3018 2903 0 +3151 3126 0 +3248 3283 0 +3331 3415 0 +3423 3548 0 +3523 3680 0 +3629 3812 0 +3741 3944 0 +3857 4076 0 +3977 4095 0 +2887 0 2638 +2887 0 2638 +2887 0 2637 +2887 0 2636 +2887 0 2635 +2887 0 2632 +2886 0 2630 +2886 0 2626 +2885 0 2622 +2885 0 2614 +2885 0 2603 +2885 0 2589 +2885 0 2569 +2885 0 2540 +2885 0 2499 +2885 0 2438 +2885 0 2340 +2885 0 2163 +2885 0 1706 +2885 0 0 +2885 0 0 +2885 2237 0 +3018 2742 0 +3151 3034 0 +3283 3257 0 +3381 3415 0 +3465 3548 0 +3556 3680 0 +3656 3812 0 +3762 3944 0 +3873 4076 0 +3989 4095 0 +3019 0 2765 +3019 0 2765 +3019 0 2764 +3019 0 2763 +3019 0 2762 +3019 0 2761 +3018 0 2759 +3018 0 2756 +3018 0 2752 +3018 0 2747 +3018 0 2739 +3018 0 2728 +3018 0 2714 +3018 0 2693 +3018 0 2664 +3018 0 2622 +3018 0 2559 +3018 0 2459 +3018 0 2276 +3018 0 1782 +3018 0 0 +3018 0 0 +3018 2362 0 +3151 2873 0 +3283 3165 0 +3415 3388 0 +3514 3548 0 +3597 3680 0 +3689 3812 0 +3788 3944 0 +3894 4076 0 +4006 4095 0 +3152 0 2893 +3152 0 2893 +3152 0 2893 +3151 0 2892 +3151 0 2891 +3151 0 2890 +3151 0 2889 +3151 0 2887 +3151 0 2884 +3151 0 2880 +3151 0 2874 +3151 0 2866 +3151 0 2855 +3151 0 2840 +3151 0 2819 +3151 0 2790 +3151 0 2747 +3151 0 2684 +3151 0 2581 +3151 0 2394 +3151 0 1869 +3151 0 0 +3151 0 0 +3151 2490 0 +3283 3003 0 +3415 3296 0 +3548 3520 0 +3647 3680 0 +3730 3812 0 +3822 3944 0 +3921 4076 0 +4027 4095 0 +3284 0 3022 +3283 0 3022 +3283 0 3022 +3283 0 3021 +3283 0 3021 +3283 0 3020 +3283 0 3019 +3283 0 3017 +3283 0 3015 +3283 0 3012 +3283 0 3008 +3283 0 3002 +3283 0 2994 +3283 0 2983 +3283 0 2968 +3283 0 2947 +3283 0 2917 +3283 0 2874 +3283 0 2809 +3283 0 2705 +3283 0 2513 +3283 0 1962 +3283 0 0 +3283 0 0 +3283 2619 0 +3415 3135 0 +3548 3428 0 +3680 3652 0 +3780 3812 0 +3863 3944 0 +3954 4076 0 +4053 4095 0 +3416 0 3152 +3416 0 3152 +3416 0 3152 +3416 0 3151 +3416 0 3151 +3416 0 3151 +3415 0 3150 +3415 0 3149 +3415 0 3147 +3415 0 3145 +3415 0 3141 +3415 0 3137 +3415 0 3131 +3415 0 3123 +3415 0 3112 +3415 0 3097 +3415 0 3076 +3415 0 3046 +3415 0 3002 +3415 0 2937 +3415 0 2832 +3415 0 2637 +3415 0 2068 +3415 0 0 +3415 0 0 +3415 2748 0 +3548 3266 0 +3680 3560 0 +3812 3784 0 +3912 3944 0 +3995 4076 0 +4086 4095 0 +3548 0 3283 +3548 0 3283 +3548 0 3282 +3548 0 3282 +3548 0 3282 +3548 0 3281 +3548 0 3281 +3548 0 3280 +3548 0 3279 +3548 0 3277 +3548 0 3275 +3548 0 3271 +3548 0 3267 +3548 0 3261 +3548 0 3253 +3548 0 3242 +3548 0 3226 +3548 0 3205 +3548 0 3175 +3548 0 3132 +3548 0 3066 +3548 0 2960 +3548 0 2763 +3548 0 2174 +3548 0 0 +3548 0 0 +3548 2878 0 +3680 3397 0 +3812 3691 0 +3944 3915 0 +4044 4076 0 +4095 4095 0 +3680 0 3414 +3680 0 3414 +3680 0 3414 +3680 0 3413 +3680 0 3413 +3680 0 3413 +3680 0 3412 +3680 0 3412 +3680 0 3411 +3680 0 3409 +3680 0 3408 +3680 0 3405 +3680 0 3402 +3680 0 3397 +3680 0 3392 +3680 0 3383 +3680 0 3372 +3680 0 3357 +3680 0 3336 +3680 0 3305 +3680 0 3261 +3680 0 3195 +3680 0 3089 +3680 0 2890 +3680 0 2291 +3680 0 0 +3680 0 0 +3680 3009 0 +3812 3529 0 +3944 3823 0 +4076 4047 0 +4095 4095 0 +3812 0 3545 +3812 0 3545 +3812 0 3545 +3812 0 3545 +3812 0 3544 +3812 0 3544 +3812 0 3544 +3812 0 3543 +3812 0 3543 +3812 0 3542 +3812 0 3540 +3812 0 3538 +3812 0 3536 +3812 0 3533 +3812 0 3528 +3812 0 3522 +3812 0 3514 +3812 0 3503 +3812 0 3488 +3812 0 3466 +3812 0 3436 +3812 0 3392 +3812 0 3326 +3812 0 3218 +3812 0 3019 +3812 0 2408 +3812 0 0 +3812 0 0 +3812 3140 0 +3944 3661 0 +4076 3955 0 +4095 4095 0 +3944 0 3676 +3944 0 3676 +3944 0 3676 +3944 0 3676 +3944 0 3676 +3944 0 3676 +3944 0 3676 +3944 0 3675 +3944 0 3675 +3944 0 3674 +3944 0 3673 +3944 0 3671 +3944 0 3670 +3944 0 3667 +3944 0 3664 +3944 0 3659 +3944 0 3653 +3944 0 3645 +3944 0 3634 +3944 0 3619 +3944 0 3597 +3944 0 3567 +3944 0 3523 +3944 0 3456 +3944 0 3349 +3944 0 3147 +3944 0 2528 +3944 0 0 +3944 0 0 +3944 3271 0 +4076 3792 0 +4095 4087 0 +4076 0 3808 +4076 0 3808 +4076 0 3808 +4076 0 3808 +4076 0 3808 +4076 0 3808 +4076 0 3807 +4076 0 3807 +4076 0 3807 +4076 0 3806 +4076 0 3805 +4076 0 3804 +4076 0 3803 +4076 0 3801 +4076 0 3798 +4076 0 3795 +4076 0 3791 +4076 0 3785 +4076 0 3777 +4076 0 3765 +4076 0 3750 +4076 0 3728 +4076 0 3698 +4076 0 3654 +4076 0 3587 +4076 0 3479 +4076 0 3277 +4076 0 2650 +4076 0 0 +4076 0 0 +4076 3403 0 +4095 3925 0 +4095 0 3940 +4095 0 3940 +4095 0 3940 +4095 0 3940 +4095 0 3940 +4095 0 3939 +4095 0 3939 +4095 0 3939 +4095 0 3939 +4095 0 3938 +4095 0 3938 +4095 0 3937 +4095 0 3936 +4095 0 3935 +4095 0 3933 +4095 0 3930 +4095 0 3927 +4095 0 3923 +4095 0 3917 +4095 0 3908 +4095 0 3897 +4095 0 3881 +4095 0 3860 +4095 0 3830 +4095 0 3786 +4095 0 3719 +4095 0 3611 +4095 0 3408 +4095 0 2778 +4095 0 0 +4095 0 0 +4095 3534 0 +0 1046 1295 +0 1069 1295 +0 1099 1295 +0 1135 1295 +0 1181 1295 +0 1234 1295 +0 1295 1292 +0 1295 1204 +0 1295 1051 +0 1295 702 +0 1429 0 +0 1563 0 +580 1696 0 +1106 1828 0 +1402 1961 0 +1626 2094 0 +1817 2226 0 +1989 2358 0 +2149 2491 0 +2300 2623 0 +2446 2755 0 +2589 2887 0 +2728 3019 0 +2866 3152 0 +3002 3284 0 +3137 3416 0 +3271 3548 0 +3405 3680 0 +3538 3812 0 +3671 3944 0 +3804 4076 0 +3937 4095 0 +0 1021 1295 +0 1050 1292 +0 1081 1292 +0 1119 1292 +0 1166 1292 +0 1221 1292 +0 1286 1292 +0 1292 1211 +0 1292 1062 +0 1292 724 +0 1427 0 +0 1561 0 +653 1695 0 +1131 1828 0 +1415 1961 0 +1635 2093 0 +1823 2226 0 +1993 2358 0 +2151 2491 0 +2302 2623 0 +2448 2755 0 +2589 2887 0 +2729 3019 0 +2866 3152 0 +3002 3283 0 +3137 3416 0 +3272 3548 0 +3405 3680 0 +3538 3812 0 +3671 3944 0 +3804 4076 0 +3937 4095 0 +0 985 1295 +0 1017 1292 +0 1056 1289 +0 1096 1289 +0 1145 1289 +0 1203 1289 +0 1271 1289 +0 1289 1221 +0 1289 1075 +0 1289 753 +0 1424 0 +0 1559 0 +736 1693 0 +1161 1827 0 +1431 1960 0 +1645 2093 0 +1829 2225 0 +1997 2358 0 +2154 2490 0 +2304 2623 0 +2449 2755 0 +2591 2887 0 +2729 3019 0 +2867 3152 0 +3002 3283 0 +3138 3416 0 +3272 3548 0 +3405 3680 0 +3539 3812 0 +3672 3944 0 +3804 4076 0 +3937 4095 0 +0 934 1295 +0 968 1292 +0 1012 1289 +0 1064 1284 +0 1116 1284 +0 1177 1284 +0 1249 1284 +0 1284 1235 +0 1284 1093 +0 1284 788 +0 1421 0 +0 1557 0 +827 1691 0 +1199 1825 0 +1453 1959 0 +1658 2092 0 +1839 2225 0 +2004 2357 0 +2159 2490 0 +2308 2622 0 +2452 2755 0 +2592 2887 0 +2731 3019 0 +2868 3151 0 +3003 3283 0 +3138 3416 0 +3272 3548 0 +3406 3680 0 +3539 3812 0 +3672 3944 0 +3805 4076 0 +3937 4095 0 +0 853 1295 +0 894 1292 +0 945 1289 +0 1005 1284 +0 1074 1278 +0 1141 1278 +0 1218 1278 +0 1278 1251 +0 1278 1116 +0 1278 832 +0 1416 0 +275 1553 0 +926 1689 0 +1245 1823 0 +1480 1958 0 +1676 2091 0 +1850 2224 0 +2012 2357 0 +2165 2489 0 +2312 2622 0 +2455 2755 0 +2595 2887 0 +2732 3019 0 +2869 3151 0 +3004 3283 0 +3139 3416 0 +3273 3548 0 +3406 3680 0 +3539 3812 0 +3672 3944 0 +3805 4076 0 +3937 4095 0 +0 717 1295 +0 772 1292 +0 837 1289 +0 911 1284 +0 995 1278 +212 1087 1270 +212 1172 1270 +212 1266 1270 +212 1270 1145 +212 1270 884 +0 1410 47 +611 1549 0 +1031 1685 0 +1301 1821 0 +1514 1956 0 +1698 2089 0 +1865 2223 0 +2022 2356 0 +2172 2489 0 +2317 2621 0 +2459 2754 0 +2598 2887 0 +2735 3019 0 +2871 3151 0 +3005 3283 0 +3140 3416 0 +3273 3548 0 +3407 3680 0 +3540 3812 0 +3672 3944 0 +3805 4076 0 +3937 4095 0 +0 431 1295 +0 529 1292 +0 635 1289 +0 746 1284 +0 862 1278 +212 982 1270 +562 1104 1258 +562 1211 1258 +562 1258 1181 +562 1258 946 +345 1402 344 +852 1543 0 +1142 1681 0 +1366 1817 0 +1555 1953 0 +1726 2087 0 +1885 2221 0 +2037 2355 0 +2183 2488 0 +2325 2621 0 +2464 2754 0 +2602 2886 0 +2738 3018 0 +2873 3151 0 +3007 3283 0 +3141 3415 0 +3274 3548 0 +3407 3680 0 +3540 3812 0 +3673 3944 0 +3805 4076 0 +3938 4095 0 +0 0 1295 +0 0 1292 +0 9 1289 +0 346 1284 +0 587 1278 +212 787 1270 +562 963 1258 +809 1126 1242 +809 1242 1225 +809 1242 1018 +793 1390 695 +1051 1534 476 +1258 1674 0 +1440 1813 0 +1606 1950 0 +1761 2085 0 +1910 2220 0 +2054 2353 0 +2196 2487 0 +2334 2620 0 +2471 2753 0 +2607 2886 0 +2742 3018 0 +2876 3151 0 +3009 3283 0 +3143 3415 0 +3276 3548 0 +3408 3680 0 +3541 3812 0 +3673 3944 0 +3805 4076 0 +3938 4095 0 +0 0 1295 +0 0 1292 +0 0 1289 +0 0 1284 +0 0 1278 +212 214 1270 +562 661 1258 +809 938 1242 +1010 1154 1220 +1010 1220 1099 +1069 1374 940 +1228 1523 826 +1378 1666 608 +1523 1807 0 +1665 1945 0 +1804 2082 0 +1942 2217 0 +2078 2352 0 +2213 2486 0 +2347 2619 0 +2481 2752 0 +2614 2885 0 +2747 3018 0 +2880 3151 0 +3012 3283 0 +3145 3415 0 +3277 3548 0 +3409 3680 0 +3542 3812 0 +3674 3944 0 +3806 4076 0 +3938 4095 0 +702 0 1295 +724 0 1292 +753 0 1289 +788 0 1284 +832 0 1278 +884 212 1270 +946 562 1258 +1018 809 1242 +1099 1010 1220 +1188 1188 1188 +1286 1352 1142 +1390 1507 1073 +1500 1654 959 +1615 1798 740 +1734 1939 0 +1856 2077 0 +1981 2214 0 +2107 2349 0 +2235 2484 0 +2363 2618 0 +2493 2751 0 +2623 2885 0 +2754 3017 0 +2885 3150 0 +3016 3282 0 +3147 3415 0 +3279 3547 0 +3411 3680 0 +3543 3812 0 +3675 3944 0 +3807 4076 0 +3939 4095 0 +1174 0 1429 +1182 0 1427 +1193 0 1424 +1207 0 1421 +1225 0 1416 +1248 0 1410 +1277 344 1402 +1313 695 1390 +1357 940 1374 +1352 1142 1286 +1352 1231 1142 +1507 1489 1073 +1608 1654 959 +1701 1798 740 +1801 1939 0 +1908 2077 0 +2021 2214 0 +2138 2349 0 +2258 2484 0 +2381 2618 0 +2506 2751 0 +2633 2885 0 +2761 3017 0 +2891 3150 0 +3020 3282 0 +3151 3415 0 +3282 3547 0 +3413 3680 0 +3544 3812 0 +3676 3944 0 +3808 4076 0 +3940 4095 0 +1458 0 1563 +1463 0 1561 +1468 0 1559 +1476 0 1557 +1486 0 1553 +1499 0 1549 +1516 0 1543 +1534 476 1531 +1523 826 1476 +1507 1073 1390 +1507 1073 1202 +1507 1282 1073 +1654 1577 959 +1795 1798 740 +1878 1939 0 +1970 2077 0 +2070 2214 0 +2176 2349 0 +2288 2484 0 +2404 2618 0 +2524 2751 0 +2647 2885 0 +2771 3017 0 +2898 3150 0 +3026 3282 0 +3155 3415 0 +3285 3547 0 +3415 3680 0 +3546 3812 0 +3677 3944 0 +3808 4076 0 +3940 4095 0 +1677 0 1696 +1680 0 1695 +1683 0 1693 +1688 0 1691 +1689 0 1683 +1685 0 1667 +1681 0 1645 +1674 0 1614 +1666 608 1569 +1654 959 1500 +1654 959 1360 +1654 959 1056 +1654 1343 959 +1798 1673 740 +1939 1912 0 +2041 2077 0 +2128 2214 0 +2223 2349 0 +2325 2484 0 +2432 2618 0 +2546 2751 0 +2664 2885 0 +2784 3017 0 +2908 3150 0 +3033 3282 0 +3161 3415 0 +3289 3547 0 +3418 3680 0 +3548 3812 0 +3679 3944 0 +3810 4076 0 +3941 4095 0 +1828 0 1789 +1828 0 1785 +1827 0 1779 +1825 0 1772 +1823 0 1763 +1821 0 1750 +1817 0 1732 +1813 0 1706 +1807 0 1669 +1798 740 1615 +1798 740 1510 +1798 740 1315 +1798 740 742 +1798 1413 740 +1939 1776 0 +2077 2027 0 +2195 2214 0 +2278 2349 0 +2369 2484 0 +2469 2618 0 +2574 2751 0 +2685 2885 0 +2801 3017 0 +2921 3150 0 +3043 3282 0 +3168 3415 0 +3295 3547 0 +3423 3680 0 +3552 3812 0 +3681 3944 0 +3812 4076 0 +3943 4095 0 +1961 0 1873 +1961 0 1870 +1960 0 1865 +1959 0 1860 +1958 0 1852 +1956 0 1841 +1953 0 1826 +1950 0 1806 +1945 0 1776 +1939 0 1734 +1939 0 1655 +1939 0 1523 +1939 0 1248 +1939 573 0 +1939 1492 0 +2077 1886 0 +2214 2146 0 +2343 2349 0 +2423 2484 0 +2512 2618 0 +2609 2751 0 +2713 2885 0 +2823 3017 0 +2938 3150 0 +3056 3282 0 +3178 3415 0 +3302 3547 0 +3428 3680 0 +3556 3812 0 +3685 3944 0 +3814 4076 0 +3944 4095 0 +2094 0 1966 +2093 0 1963 +2093 0 1960 +2092 0 1955 +2091 0 1949 +2089 0 1940 +2087 0 1928 +2085 0 1912 +2082 0 1889 +2077 0 1856 +2077 0 1797 +2077 0 1704 +2077 0 1539 +2077 0 1138 +2077 173 0 +2077 1581 0 +2214 2000 0 +2349 2268 0 +2484 2481 0 +2565 2618 0 +2652 2751 0 +2748 2885 0 +2850 3017 0 +2959 3150 0 +3073 3282 0 +3191 3415 0 +3312 3547 0 +3436 3680 0 +3562 3812 0 +3689 3944 0 +3817 4076 0 +3947 4095 0 +2226 0 2066 +2226 0 2064 +2225 0 2061 +2225 0 2058 +2224 0 2053 +2223 0 2046 +2221 0 2036 +2220 0 2023 +2217 0 2006 +2214 0 1981 +2214 0 1936 +2214 0 1870 +2214 0 1762 +2214 0 1560 +2214 0 932 +2214 0 0 +2214 1677 0 +2349 2118 0 +2484 2393 0 +2618 2608 0 +2704 2751 0 +2790 2885 0 +2885 3017 0 +2986 3150 0 +3094 3282 0 +3207 3415 0 +3325 3547 0 +3445 3680 0 +3569 3812 0 +3694 3944 0 +3821 4076 0 +3950 4095 0 +2358 0 2173 +2358 0 2171 +2358 0 2169 +2357 0 2166 +2357 0 2162 +2356 0 2157 +2355 0 2150 +2353 0 2140 +2352 0 2126 +2349 0 2107 +2349 0 2074 +2349 0 2025 +2349 0 1951 +2349 0 1829 +2349 0 1586 +2349 0 275 +2349 0 0 +2349 1781 0 +2484 2240 0 +2618 2519 0 +2751 2737 0 +2842 2885 0 +2927 3017 0 +3020 3150 0 +3121 3282 0 +3228 3415 0 +3341 3547 0 +3458 3680 0 +3579 3812 0 +3702 3944 0 +3827 4076 0 +3954 4095 0 +2491 0 2285 +2491 0 2284 +2490 0 2283 +2490 0 2280 +2489 0 2277 +2489 0 2273 +2488 0 2267 +2487 0 2260 +2486 0 2249 +2484 0 2235 +2484 0 2210 +2484 0 2174 +2484 0 2122 +2484 0 2042 +2484 0 1906 +2484 0 1620 +2484 0 0 +2484 0 0 +2484 1891 0 +2618 2363 0 +2751 2647 0 +2885 2866 0 +2977 3017 0 +3062 3150 0 +3155 3282 0 +3255 3415 0 +3362 3547 0 +3475 3680 0 +3591 3812 0 +3711 3944 0 +3834 4076 0 +3960 4095 0 +2623 0 2402 +2623 0 2401 +2623 0 2400 +2622 0 2398 +2622 0 2396 +2621 0 2393 +2621 0 2388 +2620 0 2382 +2619 0 2374 +2618 0 2363 +2618 0 2345 +2618 0 2319 +2618 0 2281 +2618 0 2226 +2618 0 2140 +2618 0 1991 +2618 0 1661 +2618 0 0 +2618 0 0 +2618 2005 0 +2751 2490 0 +2885 2776 0 +3017 2996 0 +3112 3150 0 +3196 3282 0 +3289 3415 0 +3389 3547 0 +3495 3680 0 +3607 3812 0 +3724 3944 0 +3844 4076 0 +3967 4095 0 +2755 0 2523 +2755 0 2522 +2755 0 2521 +2755 0 2520 +2755 0 2517 +2754 0 2515 +2754 0 2512 +2753 0 2507 +2752 0 2501 +2751 0 2493 +2751 0 2479 +2751 0 2460 +2751 0 2433 +2751 0 2394 +2751 0 2336 +2751 0 2245 +2751 0 2086 +2751 0 1711 +2751 0 0 +2751 0 0 +2751 2123 0 +2885 2617 0 +3017 2905 0 +3150 3127 0 +3247 3282 0 +3330 3415 0 +3422 3547 0 +3522 3680 0 +3629 3812 0 +3740 3944 0 +3856 4076 0 +3977 4095 0 +2887 0 2646 +2887 0 2645 +2887 0 2644 +2887 0 2643 +2887 0 2642 +2887 0 2640 +2886 0 2637 +2886 0 2634 +2885 0 2629 +2885 0 2623 +2885 0 2613 +2885 0 2599 +2885 0 2579 +2885 0 2551 +2885 0 2511 +2885 0 2451 +2885 0 2356 +2885 0 2188 +2885 0 1769 +2885 0 0 +2885 0 0 +2885 2245 0 +3017 2745 0 +3150 3036 0 +3282 3257 0 +3380 3415 0 +3464 3547 0 +3556 3680 0 +3655 3812 0 +3761 3944 0 +3873 4076 0 +3989 4095 0 +3019 0 2771 +3019 0 2770 +3019 0 2770 +3019 0 2769 +3019 0 2768 +3019 0 2766 +3018 0 2764 +3018 0 2762 +3018 0 2758 +3017 0 2754 +3017 0 2746 +3017 0 2735 +3017 0 2721 +3017 0 2701 +3017 0 2672 +3017 0 2631 +3017 0 2570 +3017 0 2471 +3017 0 2294 +3017 0 1837 +3017 0 0 +3017 0 0 +3017 2369 0 +3150 2875 0 +3282 3166 0 +3415 3389 0 +3513 3547 0 +3597 3680 0 +3689 3812 0 +3788 3944 0 +3894 4076 0 +4005 4095 0 +3152 0 2898 +3152 0 2897 +3152 0 2897 +3151 0 2896 +3151 0 2895 +3151 0 2895 +3151 0 2893 +3151 0 2891 +3151 0 2888 +3150 0 2885 +3150 0 2879 +3150 0 2871 +3150 0 2860 +3150 0 2846 +3150 0 2825 +3150 0 2796 +3150 0 2754 +3150 0 2691 +3150 0 2591 +3150 0 2408 +3150 0 1915 +3150 0 0 +3150 0 0 +3150 2495 0 +3282 3005 0 +3415 3297 0 +3547 3520 0 +3646 3680 0 +3729 3812 0 +3821 3944 0 +3921 4076 0 +4026 4095 0 +3284 0 3025 +3283 0 3025 +3283 0 3025 +3283 0 3025 +3283 0 3024 +3283 0 3023 +3283 0 3022 +3283 0 3021 +3283 0 3018 +3282 0 3016 +3282 0 3012 +3282 0 3006 +3282 0 2998 +3282 0 2987 +3282 0 2972 +3282 0 2951 +3282 0 2922 +3282 0 2879 +3282 0 2815 +3282 0 2713 +3282 0 2524 +3282 0 1999 +3282 0 0 +3282 0 0 +3282 2622 0 +3415 3136 0 +3547 3429 0 +3680 3652 0 +3779 3812 0 +3862 3944 0 +3953 4076 0 +4053 4095 0 +3416 0 3155 +3416 0 3154 +3416 0 3154 +3416 0 3154 +3416 0 3154 +3416 0 3153 +3415 0 3152 +3415 0 3151 +3415 0 3150 +3415 0 3147 +3415 0 3144 +3415 0 3140 +3415 0 3134 +3415 0 3126 +3415 0 3115 +3415 0 3100 +3415 0 3079 +3415 0 3049 +3415 0 3006 +3415 0 2942 +3415 0 2837 +3415 0 2646 +3415 0 2098 +3415 0 0 +3415 0 0 +3415 2751 0 +3547 3267 0 +3680 3560 0 +3812 3784 0 +3912 3944 0 +3995 4076 0 +4086 4095 0 +3548 0 3285 +3548 0 3284 +3548 0 3284 +3548 0 3284 +3548 0 3284 +3548 0 3283 +3548 0 3283 +3548 0 3282 +3548 0 3281 +3547 0 3279 +3547 0 3277 +3547 0 3274 +3547 0 3269 +3547 0 3263 +3547 0 3255 +3547 0 3244 +3547 0 3229 +3547 0 3208 +3547 0 3178 +3547 0 3135 +3547 0 3069 +3547 0 2964 +3547 0 2770 +3547 0 2198 +3547 0 0 +3547 0 0 +3547 2880 0 +3680 3398 0 +3812 3692 0 +3944 3916 0 +4044 4076 0 +4095 4095 0 +3680 0 3415 +3680 0 3415 +3680 0 3415 +3680 0 3415 +3680 0 3414 +3680 0 3414 +3680 0 3414 +3680 0 3413 +3680 0 3412 +3680 0 3411 +3680 0 3409 +3680 0 3407 +3680 0 3404 +3680 0 3399 +3680 0 3393 +3680 0 3385 +3680 0 3374 +3680 0 3359 +3680 0 3337 +3680 0 3307 +3680 0 3264 +3680 0 3198 +3680 0 3092 +3680 0 2895 +3680 0 2310 +3680 0 0 +3680 0 0 +3680 3011 0 +3812 3530 0 +3944 3824 0 +4076 4047 0 +4095 4095 0 +3812 0 3546 +3812 0 3546 +3812 0 3546 +3812 0 3545 +3812 0 3545 +3812 0 3545 +3812 0 3545 +3812 0 3544 +3812 0 3544 +3812 0 3543 +3812 0 3541 +3812 0 3540 +3812 0 3537 +3812 0 3534 +3812 0 3530 +3812 0 3523 +3812 0 3515 +3812 0 3504 +3812 0 3489 +3812 0 3468 +3812 0 3437 +3812 0 3394 +3812 0 3328 +3812 0 3221 +3812 0 3023 +3812 0 2422 +3812 0 0 +3812 0 0 +3812 3141 0 +3944 3661 0 +4076 3955 0 +4095 4095 0 +3944 0 3677 +3944 0 3677 +3944 0 3677 +3944 0 3677 +3944 0 3677 +3944 0 3676 +3944 0 3676 +3944 0 3676 +3944 0 3675 +3944 0 3675 +3944 0 3674 +3944 0 3673 +3944 0 3671 +3944 0 3668 +3944 0 3665 +3944 0 3661 +3944 0 3654 +3944 0 3646 +3944 0 3635 +3944 0 3620 +3944 0 3598 +3944 0 3568 +3944 0 3524 +3944 0 3458 +3944 0 3351 +3944 0 3151 +3944 0 2539 +3944 0 0 +3944 0 0 +3944 3272 0 +4076 3793 0 +4095 4088 0 +4076 0 3808 +4076 0 3808 +4076 0 3808 +4076 0 3808 +4076 0 3808 +4076 0 3808 +4076 0 3808 +4076 0 3808 +4076 0 3807 +4076 0 3807 +4076 0 3806 +4076 0 3805 +4076 0 3803 +4076 0 3802 +4076 0 3799 +4076 0 3796 +4076 0 3791 +4076 0 3785 +4076 0 3777 +4076 0 3766 +4076 0 3751 +4076 0 3729 +4076 0 3699 +4076 0 3655 +4076 0 3588 +4076 0 3480 +4076 0 3279 +4076 0 2659 +4076 0 0 +4076 0 0 +4076 3403 0 +4095 3925 0 +4095 0 3940 +4095 0 3940 +4095 0 3940 +4095 0 3940 +4095 0 3940 +4095 0 3940 +4095 0 3940 +4095 0 3940 +4095 0 3939 +4095 0 3939 +4095 0 3938 +4095 0 3937 +4095 0 3937 +4095 0 3935 +4095 0 3933 +4095 0 3931 +4095 0 3927 +4095 0 3923 +4095 0 3917 +4095 0 3909 +4095 0 3898 +4095 0 3882 +4095 0 3861 +4095 0 3830 +4095 0 3786 +4095 0 3720 +4095 0 3612 +4095 0 3410 +4095 0 2785 +4095 0 0 +4095 0 0 +4095 3535 0 +0 1174 1429 +0 1192 1429 +0 1215 1429 +0 1244 1429 +0 1280 1429 +0 1323 1429 +0 1376 1429 +0 1429 1419 +0 1429 1330 +0 1429 1174 +0 1429 816 +0 1563 0 +0 1696 0 +650 1828 0 +1220 1961 0 +1524 2094 0 +1753 2226 0 +1946 2358 0 +2119 2491 0 +2278 2623 0 +2431 2755 0 +2577 2887 0 +2720 3019 0 +2860 3152 0 +2997 3284 0 +3134 3416 0 +3269 3548 0 +3403 3680 0 +3537 3812 0 +3670 3944 0 +3803 4076 0 +3937 4095 0 +0 1156 1429 +0 1178 1427 +0 1201 1427 +0 1231 1427 +0 1267 1427 +0 1313 1427 +0 1366 1427 +0 1427 1424 +0 1427 1336 +0 1427 1182 +0 1427 833 +0 1561 0 +0 1695 0 +713 1828 0 +1238 1961 0 +1534 2093 0 +1759 2226 0 +1950 2358 0 +2121 2491 0 +2281 2623 0 +2432 2755 0 +2578 2887 0 +2720 3019 0 +2860 3152 0 +2998 3283 0 +3134 3416 0 +3269 3548 0 +3403 3680 0 +3537 3812 0 +3671 3944 0 +3803 4076 0 +3937 4095 0 +0 1130 1429 +0 1153 1427 +0 1182 1424 +0 1213 1424 +0 1251 1424 +0 1298 1424 +0 1353 1424 +0 1418 1424 +0 1424 1343 +0 1424 1193 +0 1424 856 +0 1559 0 +0 1693 0 +786 1827 0 +1263 1960 0 +1547 2093 0 +1767 2225 0 +1955 2358 0 +2125 2490 0 +2283 2623 0 +2434 2755 0 +2580 2887 0 +2721 3019 0 +2861 3152 0 +2998 3283 0 +3134 3416 0 +3269 3548 0 +3404 3680 0 +3537 3812 0 +3671 3944 0 +3803 4076 0 +3937 4095 0 +0 1092 1429 +0 1118 1427 +0 1149 1424 +0 1188 1421 +0 1228 1421 +0 1277 1421 +0 1335 1421 +0 1403 1421 +0 1421 1353 +0 1421 1207 +0 1421 885 +0 1557 0 +0 1691 0 +869 1825 0 +1294 1959 0 +1564 2092 0 +1777 2225 0 +1962 2357 0 +2129 2490 0 +2287 2622 0 +2436 2755 0 +2581 2887 0 +2723 3019 0 +2862 3151 0 +2999 3283 0 +3135 3416 0 +3270 3548 0 +3404 3680 0 +3538 3812 0 +3671 3944 0 +3804 4076 0 +3937 4095 0 +0 1037 1429 +0 1065 1427 +0 1101 1424 +0 1144 1421 +0 1196 1416 +0 1248 1416 +0 1310 1416 +0 1381 1416 +0 1416 1367 +0 1416 1225 +0 1416 920 +0 1553 0 +0 1689 0 +960 1823 0 +1332 1958 0 +1585 2091 0 +1790 2224 0 +1970 2357 0 +2136 2489 0 +2291 2622 0 +2440 2755 0 +2584 2887 0 +2724 3019 0 +2863 3151 0 +3000 3283 0 +3135 3416 0 +3270 3548 0 +3404 3680 0 +3538 3812 0 +3671 3944 0 +3804 4076 0 +3937 4095 0 +0 951 1429 +0 985 1427 +0 1027 1424 +0 1077 1421 +0 1137 1416 +0 1206 1410 +0 1273 1410 +0 1350 1410 +0 1410 1383 +0 1410 1248 +0 1410 964 +0 1549 0 +406 1685 0 +1059 1821 0 +1378 1956 0 +1612 2089 0 +1808 2223 0 +1982 2356 0 +2144 2489 0 +2297 2621 0 +2444 2754 0 +2587 2887 0 +2727 3019 0 +2865 3151 0 +3001 3283 0 +3136 3416 0 +3271 3548 0 +3405 3680 0 +3538 3812 0 +3671 3944 0 +3804 4076 0 +3937 4095 0 +0 803 1429 +0 849 1427 +0 904 1424 +0 969 1421 +0 1043 1416 +0 1127 1410 +344 1219 1402 +344 1304 1402 +344 1398 1402 +344 1402 1277 +344 1402 1017 +0 1543 172 +742 1681 0 +1164 1817 0 +1433 1953 0 +1646 2087 0 +1830 2221 0 +1998 2355 0 +2155 2488 0 +2304 2621 0 +2450 2754 0 +2591 2886 0 +2730 3018 0 +2867 3151 0 +3003 3283 0 +3138 3415 0 +3272 3548 0 +3406 3680 0 +3539 3812 0 +3672 3944 0 +3804 4076 0 +3937 4095 0 +0 471 1429 +0 562 1427 +0 662 1424 +0 767 1421 +0 878 1416 +0 994 1410 +344 1114 1402 +695 1236 1390 +695 1343 1390 +695 1390 1313 +695 1390 1078 +479 1534 476 +983 1674 0 +1275 1813 0 +1498 1950 0 +1687 2085 0 +1858 2220 0 +2017 2353 0 +2169 2487 0 +2314 2620 0 +2457 2753 0 +2596 2886 0 +2734 3018 0 +2870 3151 0 +3005 3283 0 +3139 3415 0 +3273 3548 0 +3406 3680 0 +3540 3812 0 +3672 3944 0 +3805 4076 0 +3937 4095 0 +0 0 1429 +0 0 1427 +0 0 1424 +0 141 1421 +0 478 1416 +0 719 1410 +344 919 1402 +695 1095 1390 +940 1258 1374 +940 1374 1357 +940 1374 1150 +926 1523 826 +1183 1666 608 +1391 1807 0 +1572 1945 0 +1738 2082 0 +1894 2217 0 +2042 2352 0 +2187 2486 0 +2328 2619 0 +2467 2752 0 +2603 2885 0 +2739 3018 0 +2874 3151 0 +3008 3283 0 +3141 3415 0 +3275 3548 0 +3408 3680 0 +3540 3812 0 +3673 3944 0 +3805 4076 0 +3938 4095 0 +0 0 1429 +0 0 1427 +0 0 1424 +0 0 1421 +0 0 1416 +47 0 1410 +344 345 1402 +695 793 1390 +940 1069 1374 +1142 1286 1352 +1142 1352 1231 +1202 1507 1073 +1360 1654 959 +1510 1798 740 +1655 1939 0 +1797 2077 0 +1936 2214 0 +2074 2349 0 +2210 2484 0 +2345 2618 0 +2479 2751 0 +2613 2885 0 +2746 3017 0 +2879 3150 0 +3012 3282 0 +3144 3415 0 +3277 3547 0 +3409 3680 0 +3541 3812 0 +3674 3944 0 +3806 4076 0 +3938 4095 0 +816 0 1429 +833 0 1427 +856 0 1424 +885 0 1421 +920 0 1416 +964 0 1410 +1017 344 1402 +1078 695 1390 +1150 940 1374 +1231 1142 1352 +1320 1320 1320 +1418 1484 1274 +1522 1638 1205 +1633 1787 1090 +1748 1930 872 +1866 2071 79 +1988 2209 0 +2113 2346 0 +2239 2481 0 +2367 2616 0 +2495 2750 0 +2625 2883 0 +2755 3016 0 +2886 3150 0 +3017 3282 0 +3148 3414 0 +3280 3547 0 +3411 3679 0 +3543 3812 0 +3675 3944 0 +3807 4076 0 +3939 4095 0 +1301 0 1563 +1307 0 1561 +1315 0 1559 +1326 0 1557 +1340 0 1553 +1358 0 1549 +1381 0 1543 +1409 476 1534 +1445 826 1523 +1489 1073 1507 +1484 1274 1418 +1484 1363 1274 +1638 1621 1205 +1740 1787 1090 +1833 1930 872 +1934 2071 79 +2041 2209 0 +2153 2346 0 +2270 2481 0 +2390 2616 0 +2514 2750 0 +2639 2883 0 +2765 3016 0 +2894 3150 0 +3023 3282 0 +3152 3414 0 +3283 3547 0 +3414 3679 0 +3545 3812 0 +3676 3944 0 +3808 4076 0 +3940 4095 0 +1587 0 1696 +1590 0 1695 +1594 0 1693 +1600 0 1691 +1608 0 1689 +1618 0 1685 +1631 0 1681 +1648 0 1674 +1666 608 1663 +1654 959 1608 +1638 1205 1522 +1638 1205 1333 +1638 1414 1205 +1787 1709 1090 +1927 1930 872 +2010 2071 79 +2102 2209 0 +2202 2346 0 +2308 2481 0 +2420 2616 0 +2536 2750 0 +2656 2883 0 +2778 3016 0 +2904 3150 0 +3030 3282 0 +3158 3414 0 +3287 3547 0 +3417 3679 0 +3547 3812 0 +3678 3944 0 +3809 4076 0 +3941 4095 0 +1807 0 1828 +1810 0 1828 +1812 0 1827 +1816 0 1825 +1821 0 1823 +1821 0 1815 +1817 0 1799 +1813 0 1777 +1807 0 1746 +1798 740 1701 +1787 1090 1633 +1787 1090 1491 +1787 1090 1189 +1787 1475 1090 +1930 1805 872 +2071 2044 79 +2174 2209 0 +2260 2346 0 +2355 2481 0 +2456 2616 0 +2565 2750 0 +2678 2883 0 +2796 3016 0 +2917 3150 0 +3040 3282 0 +3165 3414 0 +3293 3547 0 +3421 3679 0 +3551 3812 0 +3680 3944 0 +3811 4076 0 +3942 4095 0 +1961 0 1923 +1961 0 1920 +1960 0 1917 +1959 0 1911 +1958 0 1905 +1956 0 1895 +1953 0 1882 +1950 0 1864 +1945 0 1838 +1939 0 1801 +1930 872 1748 +1930 872 1642 +1930 872 1447 +1930 872 873 +1930 1545 872 +2071 1908 79 +2209 2159 0 +2328 2346 0 +2410 2481 0 +2501 2616 0 +2601 2750 0 +2706 2883 0 +2817 3016 0 +2933 3150 0 +3053 3282 0 +3175 3414 0 +3300 3547 0 +3427 3679 0 +3555 3812 0 +3684 3944 0 +3813 4076 0 +3944 4095 0 +2094 0 2007 +2093 0 2005 +2093 0 2002 +2092 0 1997 +2091 0 1992 +2089 0 1984 +2087 0 1973 +2085 0 1958 +2082 0 1938 +2077 0 1908 +2071 79 1866 +2071 79 1787 +2071 79 1655 +2071 79 1379 +2071 706 79 +2071 1625 79 +2209 2018 0 +2346 2278 0 +2475 2481 0 +2555 2616 0 +2645 2750 0 +2741 2883 0 +2845 3016 0 +2955 3150 0 +3070 3282 0 +3188 3414 0 +3310 3547 0 +3434 3679 0 +3561 3812 0 +3688 3944 0 +3816 4076 0 +3946 4095 0 +2226 0 2100 +2226 0 2098 +2225 0 2095 +2225 0 2092 +2224 0 2087 +2223 0 2081 +2221 0 2072 +2220 0 2060 +2217 0 2044 +2214 0 2021 +2209 0 1988 +2209 0 1929 +2209 0 1836 +2209 0 1671 +2209 0 1270 +2209 303 0 +2209 1713 0 +2346 2132 0 +2481 2401 0 +2616 2613 0 +2697 2750 0 +2784 2883 0 +2880 3016 0 +2982 3150 0 +3091 3282 0 +3205 3414 0 +3323 3547 0 +3444 3679 0 +3568 3812 0 +3694 3944 0 +3821 4076 0 +3950 4095 0 +2358 0 2200 +2358 0 2199 +2358 0 2196 +2357 0 2193 +2357 0 2190 +2356 0 2185 +2355 0 2178 +2353 0 2168 +2352 0 2155 +2349 0 2138 +2346 0 2113 +2346 0 2069 +2346 0 2002 +2346 0 1894 +2346 0 1692 +2346 0 1064 +2346 0 0 +2346 1809 0 +2481 2251 0 +2616 2525 0 +2750 2741 0 +2836 2883 0 +2922 3016 0 +3017 3150 0 +3118 3282 0 +3226 3414 0 +3339 3547 0 +3457 3679 0 +3577 3812 0 +3701 3944 0 +3826 4076 0 +3954 4095 0 +2491 0 2306 +2491 0 2305 +2490 0 2304 +2490 0 2302 +2489 0 2298 +2489 0 2294 +2488 0 2289 +2487 0 2282 +2486 0 2272 +2484 0 2258 +2481 0 2239 +2481 0 2206 +2481 0 2158 +2481 0 2084 +2481 0 1961 +2481 0 1719 +2481 0 415 +2481 0 0 +2481 1913 0 +2616 2372 0 +2750 2651 0 +2883 2869 0 +2974 3016 0 +3059 3150 0 +3152 3282 0 +3253 3414 0 +3361 3547 0 +3473 3679 0 +3590 3812 0 +3711 3944 0 +3834 4076 0 +3959 4095 0 +2623 0 2419 +2623 0 2417 +2623 0 2416 +2622 0 2414 +2622 0 2412 +2621 0 2409 +2621 0 2405 +2620 0 2399 +2619 0 2392 +2618 0 2381 +2616 0 2367 +2616 0 2342 +2616 0 2306 +2616 0 2255 +2616 0 2174 +2616 0 2038 +2616 0 1752 +2616 0 0 +2616 0 0 +2616 2022 0 +2750 2496 0 +2883 2779 0 +3016 2998 0 +3110 3150 0 +3194 3282 0 +3287 3414 0 +3387 3547 0 +3494 3679 0 +3606 3812 0 +3723 3944 0 +3843 4076 0 +3967 4095 0 +2755 0 2535 +2755 0 2535 +2755 0 2533 +2755 0 2532 +2755 0 2530 +2754 0 2528 +2754 0 2525 +2753 0 2521 +2752 0 2514 +2751 0 2506 +2750 0 2495 +2750 0 2477 +2750 0 2451 +2750 0 2414 +2750 0 2359 +2750 0 2273 +2750 0 2124 +2750 0 1794 +2750 0 0 +2750 0 0 +2750 2137 0 +2883 2621 0 +3016 2907 0 +3150 3128 0 +3244 3282 0 +3329 3414 0 +3421 3547 0 +3521 3679 0 +3628 3812 0 +3740 3944 0 +3856 4076 0 +3976 4095 0 +2887 0 2655 +2887 0 2655 +2887 0 2654 +2887 0 2653 +2887 0 2651 +2887 0 2650 +2886 0 2647 +2886 0 2644 +2885 0 2639 +2885 0 2633 +2883 0 2625 +2883 0 2611 +2883 0 2592 +2883 0 2565 +2883 0 2526 +2883 0 2469 +2883 0 2378 +2883 0 2218 +2883 0 1843 +2883 0 0 +2883 0 0 +2883 2255 0 +3016 2749 0 +3150 3038 0 +3282 3259 0 +3379 3414 0 +3462 3547 0 +3554 3679 0 +3654 3812 0 +3761 3944 0 +3872 4076 0 +3989 4095 0 +3019 0 2778 +3019 0 2777 +3019 0 2777 +3019 0 2776 +3019 0 2775 +3019 0 2774 +3018 0 2772 +3018 0 2769 +3018 0 2766 +3017 0 2761 +3016 0 2755 +3016 0 2745 +3016 0 2731 +3016 0 2711 +3016 0 2683 +3016 0 2643 +3016 0 2583 +3016 0 2488 +3016 0 2319 +3016 0 1900 +3016 0 0 +3016 0 0 +3016 2377 0 +3150 2878 0 +3282 3168 0 +3414 3390 0 +3512 3547 0 +3596 3679 0 +3688 3812 0 +3787 3944 0 +3893 4076 0 +4005 4095 0 +3152 0 2903 +3152 0 2903 +3152 0 2903 +3151 0 2902 +3151 0 2901 +3151 0 2900 +3151 0 2898 +3151 0 2896 +3151 0 2894 +3150 0 2891 +3150 0 2886 +3150 0 2878 +3150 0 2868 +3150 0 2853 +3150 0 2833 +3150 0 2804 +3150 0 2763 +3150 0 2702 +3150 0 2604 +3150 0 2427 +3150 0 1969 +3150 0 0 +3150 0 0 +3150 2501 0 +3282 3006 0 +3414 3298 0 +3547 3521 0 +3646 3679 0 +3729 3812 0 +3820 3944 0 +3920 4076 0 +4026 4095 0 +3284 0 3030 +3283 0 3029 +3283 0 3029 +3283 0 3029 +3283 0 3028 +3283 0 3027 +3283 0 3026 +3283 0 3025 +3283 0 3023 +3282 0 3020 +3282 0 3017 +3282 0 3011 +3282 0 3003 +3282 0 2992 +3282 0 2977 +3282 0 2957 +3282 0 2928 +3282 0 2886 +3282 0 2823 +3282 0 2723 +3282 0 2539 +3282 0 2045 +3282 0 0 +3282 0 0 +3282 2627 0 +3414 3137 0 +3547 3429 0 +3679 3653 0 +3778 3812 0 +3862 3944 0 +3953 4076 0 +4053 4095 0 +3416 0 3158 +3416 0 3158 +3416 0 3157 +3416 0 3157 +3416 0 3157 +3416 0 3156 +3415 0 3155 +3415 0 3154 +3415 0 3153 +3415 0 3151 +3414 0 3148 +3414 0 3144 +3414 0 3138 +3414 0 3130 +3414 0 3119 +3414 0 3104 +3414 0 3083 +3414 0 3054 +3414 0 3011 +3414 0 2947 +3414 0 2845 +3414 0 2657 +3414 0 2135 +3414 0 0 +3414 0 0 +3414 2754 0 +3547 3268 0 +3679 3561 0 +3812 3784 0 +3911 3944 0 +3994 4076 0 +4086 4095 0 +3548 0 3287 +3548 0 3287 +3548 0 3287 +3548 0 3286 +3548 0 3286 +3548 0 3286 +3548 0 3285 +3548 0 3284 +3548 0 3283 +3547 0 3282 +3547 0 3280 +3547 0 3277 +3547 0 3272 +3547 0 3266 +3547 0 3258 +3547 0 3247 +3547 0 3232 +3547 0 3211 +3547 0 3181 +3547 0 3138 +3547 0 3074 +3547 0 2970 +3547 0 2778 +3547 0 2228 +3547 0 0 +3547 0 0 +3547 2883 0 +3679 3399 0 +3812 3692 0 +3944 3916 0 +4044 4076 0 +4095 4095 0 +3680 0 3417 +3680 0 3417 +3680 0 3417 +3680 0 3416 +3680 0 3416 +3680 0 3416 +3680 0 3415 +3680 0 3415 +3680 0 3414 +3680 0 3413 +3679 0 3411 +3679 0 3409 +3679 0 3406 +3679 0 3401 +3679 0 3395 +3679 0 3387 +3679 0 3376 +3679 0 3361 +3679 0 3340 +3679 0 3310 +3679 0 3267 +3679 0 3201 +3679 0 3096 +3679 0 2901 +3679 0 2333 +3679 0 0 +3679 0 0 +3679 3013 0 +3812 3530 0 +3944 3824 0 +4076 4048 0 +4095 4095 0 +3812 0 3547 +3812 0 3547 +3812 0 3547 +3812 0 3547 +3812 0 3547 +3812 0 3547 +3812 0 3546 +3812 0 3546 +3812 0 3545 +3812 0 3544 +3812 0 3543 +3812 0 3541 +3812 0 3539 +3812 0 3536 +3812 0 3531 +3812 0 3525 +3812 0 3517 +3812 0 3506 +3812 0 3491 +3812 0 3469 +3812 0 3439 +3812 0 3396 +3812 0 3330 +3812 0 3224 +3812 0 3027 +3812 0 2441 +3812 0 0 +3812 0 0 +3812 3143 0 +3944 3661 0 +4076 3955 0 +4095 4095 0 +3944 0 3678 +3944 0 3678 +3944 0 3678 +3944 0 3678 +3944 0 3678 +3944 0 3677 +3944 0 3677 +3944 0 3677 +3944 0 3676 +3944 0 3676 +3944 0 3675 +3944 0 3674 +3944 0 3672 +3944 0 3669 +3944 0 3666 +3944 0 3662 +3944 0 3656 +3944 0 3648 +3944 0 3636 +3944 0 3621 +3944 0 3600 +3944 0 3569 +3944 0 3526 +3944 0 3459 +3944 0 3353 +3944 0 3154 +3944 0 2553 +3944 0 0 +3944 0 0 +3944 3273 0 +4076 3793 0 +4095 4088 0 +4076 0 3809 +4076 0 3809 +4076 0 3809 +4076 0 3809 +4076 0 3809 +4076 0 3809 +4076 0 3808 +4076 0 3808 +4076 0 3808 +4076 0 3808 +4076 0 3807 +4076 0 3806 +4076 0 3804 +4076 0 3803 +4076 0 3800 +4076 0 3797 +4076 0 3793 +4076 0 3787 +4076 0 3778 +4076 0 3767 +4076 0 3752 +4076 0 3730 +4076 0 3700 +4076 0 3656 +4076 0 3590 +4076 0 3482 +4076 0 3282 +4076 0 2670 +4076 0 0 +4076 0 0 +4076 3404 0 +4095 3925 0 +4095 0 3941 +4095 0 3941 +4095 0 3941 +4095 0 3941 +4095 0 3941 +4095 0 3941 +4095 0 3940 +4095 0 3940 +4095 0 3940 +4095 0 3940 +4095 0 3939 +4095 0 3938 +4095 0 3937 +4095 0 3936 +4095 0 3934 +4095 0 3932 +4095 0 3928 +4095 0 3924 +4095 0 3918 +4095 0 3910 +4095 0 3898 +4095 0 3883 +4095 0 3862 +4095 0 3831 +4095 0 3787 +4095 0 3721 +4095 0 3613 +4095 0 3412 +4095 0 2793 +4095 0 0 +4095 0 0 +4095 3536 0 +0 1304 1563 +0 1318 1563 +0 1335 1563 +0 1357 1563 +0 1385 1563 +0 1421 1563 +0 1463 1563 +0 1515 1563 +0 1563 1548 +0 1563 1458 +0 1563 1301 +0 1563 934 +0 1696 0 +0 1828 0 +726 1961 0 +1336 2094 0 +1648 2226 0 +1880 2358 0 +2075 2491 0 +2248 2623 0 +2409 2755 0 +2562 2887 0 +2708 3019 0 +2851 3152 0 +2991 3284 0 +3129 3416 0 +3266 3548 0 +3401 3680 0 +3535 3812 0 +3669 3944 0 +3803 4076 0 +3936 4095 0 +0 1290 1563 +0 1307 1561 +0 1325 1561 +0 1347 1561 +0 1376 1561 +0 1412 1561 +0 1456 1561 +0 1508 1561 +0 1561 1552 +0 1561 1463 +0 1561 1307 +0 1561 948 +0 1695 0 +0 1828 0 +780 1961 0 +1351 2093 0 +1656 2226 0 +1885 2358 0 +2078 2491 0 +2250 2623 0 +2411 2755 0 +2563 2887 0 +2709 3019 0 +2852 3152 0 +2992 3283 0 +3129 3416 0 +3266 3548 0 +3401 3680 0 +3536 3812 0 +3669 3944 0 +3803 4076 0 +3936 4095 0 +0 1271 1563 +0 1288 1561 +0 1310 1559 +0 1333 1559 +0 1363 1559 +0 1400 1559 +0 1445 1559 +0 1499 1559 +0 1559 1556 +0 1559 1468 +0 1559 1315 +0 1559 966 +0 1693 0 +0 1827 0 +844 1960 0 +1370 2093 0 +1666 2225 0 +1891 2358 0 +2082 2490 0 +2253 2623 0 +2413 2755 0 +2564 2887 0 +2710 3019 0 +2853 3152 0 +2992 3283 0 +3130 3416 0 +3266 3548 0 +3401 3680 0 +3536 3812 0 +3669 3944 0 +3803 4076 0 +3936 4095 0 +0 1244 1563 +0 1262 1561 +0 1285 1559 +0 1315 1557 +0 1345 1557 +0 1384 1557 +0 1430 1557 +0 1486 1557 +0 1551 1557 +0 1557 1476 +0 1557 1326 +0 1557 988 +0 1691 0 +0 1825 0 +917 1959 0 +1394 2092 0 +1679 2225 0 +1899 2357 0 +2087 2490 0 +2256 2622 0 +2415 2755 0 +2566 2887 0 +2712 3019 0 +2854 3151 0 +2993 3283 0 +3130 3416 0 +3267 3548 0 +3401 3680 0 +3536 3812 0 +3669 3944 0 +3803 4076 0 +3936 4095 0 +0 1205 1563 +0 1225 1561 +0 1250 1559 +0 1281 1557 +0 1320 1553 +0 1360 1553 +0 1409 1553 +0 1467 1553 +0 1535 1553 +0 1553 1486 +0 1553 1340 +0 1553 1017 +0 1689 0 +0 1823 0 +1000 1958 0 +1425 2091 0 +1695 2224 0 +1909 2357 0 +2094 2489 0 +2261 2622 0 +2419 2755 0 +2569 2887 0 +2713 3019 0 +2855 3151 0 +2994 3283 0 +3131 3416 0 +3267 3548 0 +3402 3680 0 +3536 3812 0 +3670 3944 0 +3803 4076 0 +3936 4095 0 +0 1148 1563 +0 1170 1561 +0 1198 1559 +0 1233 1557 +0 1276 1553 +0 1328 1549 +0 1380 1549 +0 1442 1549 +0 1513 1549 +0 1549 1499 +0 1549 1358 +0 1549 1053 +0 1685 0 +0 1821 0 +1091 1956 0 +1463 2089 0 +1717 2223 0 +1922 2356 0 +2103 2489 0 +2268 2621 0 +2423 2754 0 +2572 2887 0 +2716 3019 0 +2857 3151 0 +2995 3283 0 +3132 3416 0 +3268 3548 0 +3402 3680 0 +3537 3812 0 +3670 3944 0 +3803 4076 0 +3936 4095 0 +0 1057 1563 +0 1084 1561 +0 1118 1559 +0 1159 1557 +0 1209 1553 +0 1269 1549 +0 1338 1543 +0 1405 1543 +0 1482 1543 +0 1543 1516 +0 1543 1381 +0 1543 1096 +0 1681 0 +536 1817 0 +1190 1953 0 +1509 2087 0 +1744 2221 0 +1940 2355 0 +2115 2488 0 +2276 2621 0 +2429 2754 0 +2576 2886 0 +2719 3018 0 +2859 3151 0 +2997 3283 0 +3133 3415 0 +3269 3548 0 +3403 3680 0 +3537 3812 0 +3670 3944 0 +3803 4076 0 +3937 4095 0 +0 897 1563 +0 935 1561 +0 981 1559 +0 1037 1557 +0 1102 1553 +0 1176 1549 +0 1259 1543 +476 1351 1534 +476 1437 1534 +476 1531 1534 +476 1534 1409 +476 1534 1149 +0 1674 313 +874 1813 0 +1295 1950 0 +1565 2085 0 +1778 2220 0 +1962 2353 0 +2130 2487 0 +2287 2620 0 +2437 2753 0 +2581 2886 0 +2723 3018 0 +2862 3151 0 +2999 3283 0 +3135 3415 0 +3270 3548 0 +3404 3680 0 +3538 3812 0 +3671 3944 0 +3804 4076 0 +3937 4095 0 +0 523 1563 +0 605 1561 +0 696 1559 +0 794 1557 +0 900 1553 +0 1011 1549 +0 1127 1543 +476 1246 1534 +826 1368 1523 +826 1476 1523 +826 1523 1445 +826 1523 1211 +608 1666 609 +1115 1807 0 +1407 1945 0 +1630 2082 0 +1819 2217 0 +1990 2352 0 +2149 2486 0 +2301 2619 0 +2447 2752 0 +2589 2885 0 +2728 3018 0 +2866 3151 0 +3002 3283 0 +3137 3415 0 +3271 3548 0 +3405 3680 0 +3538 3812 0 +3671 3944 0 +3804 4076 0 +3937 4095 0 +0 0 1563 +0 0 1561 +0 0 1559 +0 0 1557 +0 275 1553 +0 611 1549 +0 852 1543 +476 1051 1534 +826 1228 1523 +1073 1390 1507 +1073 1507 1489 +1073 1507 1282 +1056 1654 959 +1315 1798 740 +1523 1939 0 +1704 2077 0 +1870 2214 0 +2025 2349 0 +2174 2484 0 +2319 2618 0 +2460 2751 0 +2599 2885 0 +2735 3017 0 +2871 3150 0 +3006 3282 0 +3140 3415 0 +3274 3547 0 +3407 3680 0 +3540 3812 0 +3673 3944 0 +3805 4076 0 +3937 4095 0 +0 0 1563 +0 0 1561 +0 0 1559 +0 0 1557 +0 0 1553 +0 0 1549 +172 0 1543 +476 479 1534 +826 926 1523 +1073 1202 1507 +1274 1418 1484 +1274 1484 1363 +1333 1638 1205 +1491 1787 1090 +1642 1930 872 +1787 2071 79 +1929 2209 0 +2069 2346 0 +2206 2481 0 +2342 2616 0 +2477 2750 0 +2611 2883 0 +2745 3016 0 +2878 3150 0 +3011 3282 0 +3144 3414 0 +3277 3547 0 +3409 3679 0 +3541 3812 0 +3674 3944 0 +3806 4076 0 +3938 4095 0 +934 0 1563 +948 0 1561 +966 0 1559 +988 0 1557 +1017 0 1553 +1053 0 1549 +1096 0 1543 +1149 476 1534 +1211 826 1523 +1282 1073 1507 +1363 1274 1484 +1453 1453 1453 +1550 1616 1407 +1654 1771 1337 +1765 1919 1223 +1880 2062 1005 +1998 2203 217 +2120 2341 0 +2245 2478 0 +2371 2613 0 +2499 2748 0 +2628 2882 0 +2757 3015 0 +2887 3149 0 +3018 3281 0 +3149 3414 0 +3280 3547 0 +3412 3679 0 +3544 3812 0 +3675 3944 0 +3807 4076 0 +3939 4095 0 +1427 0 1696 +1432 0 1695 +1439 0 1693 +1447 0 1691 +1457 0 1689 +1471 0 1685 +1489 0 1681 +1512 0 1674 +1541 608 1666 +1577 959 1654 +1621 1205 1638 +1616 1407 1550 +1616 1495 1407 +1771 1754 1337 +1872 1919 1223 +1965 2062 1005 +2066 2203 217 +2173 2341 0 +2285 2478 0 +2402 2613 0 +2522 2748 0 +2645 2882 0 +2770 3015 0 +2898 3149 0 +3025 3281 0 +3155 3414 0 +3285 3547 0 +3415 3679 0 +3546 3812 0 +3677 3944 0 +3808 4076 0 +3940 4095 0 +1716 0 1828 +1719 0 1828 +1722 0 1827 +1727 0 1825 +1732 0 1823 +1740 0 1821 +1750 0 1817 +1763 0 1813 +1780 0 1807 +1798 740 1795 +1787 1090 1740 +1771 1337 1654 +1771 1337 1466 +1771 1546 1337 +1919 1841 1223 +2059 2062 1005 +2142 2203 217 +2234 2341 0 +2334 2478 0 +2440 2613 0 +2552 2748 0 +2668 2882 0 +2788 3015 0 +2911 3149 0 +3035 3281 0 +3162 3414 0 +3290 3547 0 +3419 3679 0 +3549 3812 0 +3679 3944 0 +3810 4076 0 +3941 4095 0 +1938 0 1961 +1940 0 1961 +1941 0 1960 +1944 0 1959 +1948 0 1958 +1953 0 1956 +1953 0 1947 +1950 0 1931 +1945 0 1909 +1939 0 1878 +1930 872 1833 +1919 1223 1765 +1919 1223 1624 +1919 1223 1321 +1919 1607 1223 +2062 1937 1005 +2203 2176 217 +2305 2341 0 +2392 2478 0 +2487 2613 0 +2589 2748 0 +2697 2882 0 +2810 3015 0 +2928 3149 0 +3049 3281 0 +3172 3414 0 +3298 3547 0 +3425 3679 0 +3553 3812 0 +3683 3944 0 +3812 4076 0 +3943 4095 0 +2094 0 2058 +2093 0 2056 +2093 0 2053 +2092 0 2049 +2091 0 2044 +2089 0 2037 +2087 0 2027 +2085 0 2014 +2082 0 1996 +2077 0 1970 +2071 79 1934 +2062 1005 1880 +2062 1005 1774 +2062 1005 1579 +2062 1005 1006 +2062 1677 1005 +2203 2041 217 +2341 2291 0 +2460 2478 0 +2542 2613 0 +2634 2748 0 +2733 2882 0 +2838 3015 0 +2950 3149 0 +3065 3281 0 +3185 3414 0 +3307 3547 0 +3432 3679 0 +3559 3812 0 +3687 3944 0 +3816 4076 0 +3946 4095 0 +2226 0 2141 +2226 0 2140 +2225 0 2137 +2225 0 2134 +2224 0 2130 +2223 0 2124 +2221 0 2116 +2220 0 2105 +2217 0 2090 +2214 0 2070 +2209 0 2041 +2203 217 1998 +2203 217 1920 +2203 217 1787 +2203 217 1512 +2203 838 217 +2203 1757 217 +2341 2150 0 +2478 2411 0 +2607 2613 0 +2687 2748 0 +2777 2882 0 +2873 3015 0 +2977 3149 0 +3087 3281 0 +3202 3414 0 +3320 3547 0 +3442 3679 0 +3566 3812 0 +3692 3944 0 +3820 4076 0 +3949 4095 0 +2358 0 2233 +2358 0 2232 +2358 0 2230 +2357 0 2228 +2357 0 2224 +2356 0 2219 +2355 0 2213 +2353 0 2204 +2352 0 2192 +2349 0 2176 +2346 0 2153 +2341 0 2120 +2341 0 2061 +2341 0 1968 +2341 0 1803 +2341 0 1403 +2341 437 0 +2341 1845 0 +2478 2264 0 +2613 2533 0 +2748 2745 0 +2829 2882 0 +2916 3015 0 +3012 3149 0 +3114 3281 0 +3223 3414 0 +3337 3547 0 +3455 3679 0 +3576 3812 0 +3700 3944 0 +3826 4076 0 +3953 4095 0 +2491 0 2333 +2491 0 2332 +2490 0 2331 +2490 0 2329 +2489 0 2326 +2489 0 2322 +2488 0 2317 +2487 0 2310 +2486 0 2301 +2484 0 2288 +2481 0 2270 +2478 0 2245 +2478 0 2201 +2478 0 2134 +2478 0 2026 +2478 0 1824 +2478 0 1199 +2478 0 0 +2478 1941 0 +2613 2382 0 +2748 2657 0 +2882 2873 0 +2968 3015 0 +3055 3149 0 +3149 3281 0 +3250 3414 0 +3358 3547 0 +3472 3679 0 +3589 3812 0 +3710 3944 0 +3833 4076 0 +3959 4095 0 +2623 0 2440 +2623 0 2439 +2623 0 2437 +2622 0 2436 +2622 0 2434 +2621 0 2431 +2621 0 2427 +2620 0 2421 +2619 0 2414 +2618 0 2404 +2616 0 2390 +2613 0 2371 +2613 0 2338 +2613 0 2290 +2613 0 2216 +2613 0 2093 +2613 0 1851 +2613 0 547 +2613 0 0 +2613 2045 0 +2748 2504 0 +2882 2784 0 +3015 3001 0 +3106 3149 0 +3191 3281 0 +3284 3414 0 +3385 3547 0 +3493 3679 0 +3605 3812 0 +3722 3944 0 +3843 4076 0 +3966 4095 0 +2755 0 2552 +2755 0 2551 +2755 0 2550 +2755 0 2549 +2755 0 2547 +2754 0 2545 +2754 0 2541 +2753 0 2537 +2752 0 2532 +2751 0 2524 +2750 0 2514 +2748 0 2499 +2748 0 2474 +2748 0 2439 +2748 0 2387 +2748 0 2306 +2748 0 2170 +2748 0 1885 +2748 0 0 +2748 0 0 +2748 2155 0 +2882 2628 0 +3015 2911 0 +3149 3131 0 +3242 3281 0 +3326 3414 0 +3419 3547 0 +3520 3679 0 +3626 3812 0 +3739 3944 0 +3855 4076 0 +3976 4095 0 +2887 0 2668 +2887 0 2667 +2887 0 2667 +2887 0 2666 +2887 0 2664 +2887 0 2662 +2886 0 2660 +2886 0 2657 +2885 0 2652 +2885 0 2647 +2883 0 2639 +2882 0 2628 +2882 0 2609 +2882 0 2583 +2882 0 2546 +2882 0 2491 +2882 0 2405 +2882 0 2256 +2882 0 1925 +2882 0 0 +2882 0 0 +2882 2269 0 +3015 2753 0 +3149 3040 0 +3281 3260 0 +3376 3414 0 +3461 3547 0 +3553 3679 0 +3653 3812 0 +3760 3944 0 +3872 4076 0 +3988 4095 0 +3019 0 2788 +3019 0 2787 +3019 0 2787 +3019 0 2786 +3019 0 2785 +3019 0 2784 +3018 0 2782 +3018 0 2779 +3018 0 2776 +3017 0 2771 +3016 0 2765 +3015 0 2757 +3015 0 2743 +3015 0 2724 +3015 0 2697 +3015 0 2658 +3015 0 2600 +3015 0 2510 +3015 0 2350 +3015 0 1974 +3015 0 0 +3015 0 0 +3015 2387 0 +3149 2881 0 +3281 3169 0 +3414 3391 0 +3511 3547 0 +3595 3679 0 +3687 3812 0 +3786 3944 0 +3892 4076 0 +4005 4095 0 +3152 0 2911 +3152 0 2910 +3152 0 2910 +3151 0 2909 +3151 0 2908 +3151 0 2907 +3151 0 2906 +3151 0 2904 +3151 0 2902 +3150 0 2898 +3150 0 2894 +3149 0 2887 +3149 0 2877 +3149 0 2863 +3149 0 2843 +3149 0 2815 +3149 0 2775 +3149 0 2715 +3149 0 2620 +3149 0 2452 +3149 0 2033 +3149 0 0 +3149 0 0 +3149 2509 0 +3281 3009 0 +3414 3299 0 +3547 3522 0 +3644 3679 0 +3728 3812 0 +3820 3944 0 +3919 4076 0 +4026 4095 0 +3284 0 3035 +3283 0 3035 +3283 0 3035 +3283 0 3034 +3283 0 3034 +3283 0 3033 +3283 0 3032 +3283 0 3031 +3283 0 3029 +3282 0 3026 +3282 0 3023 +3281 0 3018 +3281 0 3010 +3281 0 2999 +3281 0 2985 +3281 0 2965 +3281 0 2936 +3281 0 2895 +3281 0 2833 +3281 0 2735 +3281 0 2558 +3281 0 2100 +3281 0 0 +3281 0 0 +3281 2633 0 +3414 3139 0 +3547 3430 0 +3679 3653 0 +3777 3812 0 +3861 3944 0 +3953 4076 0 +4052 4095 0 +3416 0 3162 +3416 0 3162 +3416 0 3162 +3416 0 3161 +3416 0 3161 +3416 0 3160 +3415 0 3160 +3415 0 3158 +3415 0 3157 +3415 0 3155 +3414 0 3152 +3414 0 3149 +3414 0 3143 +3414 0 3135 +3414 0 3125 +3414 0 3110 +3414 0 3089 +3414 0 3060 +3414 0 3018 +3414 0 2956 +3414 0 2855 +3414 0 2672 +3414 0 2180 +3414 0 0 +3414 0 0 +3414 2759 0 +3547 3269 0 +3679 3562 0 +3812 3785 0 +3910 3944 0 +3994 4076 0 +4085 4095 0 +3548 0 3290 +3548 0 3290 +3548 0 3290 +3548 0 3290 +3548 0 3289 +3548 0 3289 +3548 0 3288 +3548 0 3287 +3548 0 3286 +3547 0 3285 +3547 0 3283 +3547 0 3280 +3547 0 3276 +3547 0 3270 +3547 0 3262 +3547 0 3251 +3547 0 3236 +3547 0 3216 +3547 0 3186 +3547 0 3144 +3547 0 3080 +3547 0 2977 +3547 0 2790 +3547 0 2265 +3547 0 0 +3547 0 0 +3547 2886 0 +3679 3400 0 +3812 3693 0 +3944 3916 0 +4043 4076 0 +4095 4095 0 +3680 0 3419 +3680 0 3419 +3680 0 3419 +3680 0 3419 +3680 0 3419 +3680 0 3418 +3680 0 3418 +3680 0 3417 +3680 0 3416 +3680 0 3415 +3679 0 3414 +3679 0 3412 +3679 0 3409 +3679 0 3404 +3679 0 3398 +3679 0 3390 +3679 0 3379 +3679 0 3364 +3679 0 3343 +3679 0 3314 +3679 0 3271 +3679 0 3206 +3679 0 3102 +3679 0 2910 +3679 0 2363 +3679 0 0 +3679 0 0 +3679 3015 0 +3812 3531 0 +3944 3824 0 +4076 4048 0 +4095 4095 0 +3812 0 3549 +3812 0 3549 +3812 0 3549 +3812 0 3549 +3812 0 3549 +3812 0 3548 +3812 0 3548 +3812 0 3548 +3812 0 3547 +3812 0 3546 +3812 0 3545 +3812 0 3544 +3812 0 3541 +3812 0 3538 +3812 0 3533 +3812 0 3528 +3812 0 3520 +3812 0 3508 +3812 0 3493 +3812 0 3472 +3812 0 3442 +3812 0 3399 +3812 0 3333 +3812 0 3228 +3812 0 3034 +3812 0 2465 +3812 0 0 +3812 0 0 +3812 3145 0 +3944 3662 0 +4076 3956 0 +4095 4095 0 +3944 0 3679 +3944 0 3679 +3944 0 3679 +3944 0 3679 +3944 0 3679 +3944 0 3679 +3944 0 3679 +3944 0 3678 +3944 0 3678 +3944 0 3677 +3944 0 3676 +3944 0 3675 +3944 0 3673 +3944 0 3671 +3944 0 3668 +3944 0 3663 +3944 0 3657 +3944 0 3649 +3944 0 3638 +3944 0 3623 +3944 0 3602 +3944 0 3571 +3944 0 3528 +3944 0 3462 +3944 0 3356 +3944 0 3159 +3944 0 2572 +3944 0 0 +3944 0 0 +3944 3275 0 +4076 3793 0 +4095 4088 0 +4076 0 3810 +4076 0 3810 +4076 0 3810 +4076 0 3810 +4076 0 3810 +4076 0 3810 +4076 0 3810 +4076 0 3809 +4076 0 3809 +4076 0 3808 +4076 0 3808 +4076 0 3807 +4076 0 3805 +4076 0 3804 +4076 0 3801 +4076 0 3798 +4076 0 3794 +4076 0 3787 +4076 0 3780 +4076 0 3768 +4076 0 3753 +4076 0 3732 +4076 0 3701 +4076 0 3658 +4076 0 3592 +4076 0 3485 +4076 0 3286 +4076 0 2684 +4076 0 0 +4076 0 0 +4076 3405 0 +4095 3926 0 +4095 0 3941 +4095 0 3941 +4095 0 3941 +4095 0 3941 +4095 0 3941 +4095 0 3941 +4095 0 3941 +4095 0 3941 +4095 0 3941 +4095 0 3940 +4095 0 3940 +4095 0 3939 +4095 0 3938 +4095 0 3937 +4095 0 3935 +4095 0 3932 +4095 0 3929 +4095 0 3925 +4095 0 3919 +4095 0 3910 +4095 0 3899 +4095 0 3884 +4095 0 3863 +4095 0 3832 +4095 0 3788 +4095 0 3722 +4095 0 3615 +4095 0 3415 +4095 0 2804 +4095 0 0 +4095 0 0 +4095 3537 0 +0 1434 1696 +0 1444 1696 +0 1457 1696 +0 1475 1696 +0 1496 1696 +0 1524 1696 +0 1559 1696 +0 1601 1696 +0 1653 1696 +0 1696 1677 +0 1696 1587 +0 1696 1427 +0 1696 1056 +0 1828 0 +0 1961 0 +814 2094 0 +1457 2226 0 +1775 2358 0 +2009 2491 0 +2205 2623 0 +2379 2755 0 +2541 2887 0 +2693 3019 0 +2840 3152 0 +2983 3284 0 +3123 3416 0 +3261 3548 0 +3398 3680 0 +3533 3812 0 +3667 3944 0 +3801 4076 0 +3935 4095 0 +0 1424 1696 +0 1436 1695 +0 1450 1695 +0 1467 1695 +0 1489 1695 +0 1517 1695 +0 1552 1695 +0 1596 1695 +0 1647 1695 +0 1695 1680 +0 1695 1590 +0 1695 1432 +0 1695 1066 +0 1828 0 +0 1961 0 +859 2093 0 +1469 2226 0 +1781 2358 0 +2013 2491 0 +2207 2623 0 +2381 2755 0 +2542 2887 0 +2694 3019 0 +2841 3152 0 +2983 3283 0 +3123 3416 0 +3261 3548 0 +3398 3680 0 +3533 3812 0 +3667 3944 0 +3801 4076 0 +3935 4095 0 +0 1410 1696 +0 1422 1695 +0 1439 1693 +0 1456 1693 +0 1479 1693 +0 1508 1693 +0 1544 1693 +0 1588 1693 +0 1640 1693 +0 1693 1683 +0 1693 1594 +0 1693 1439 +0 1693 1080 +0 1827 0 +0 1960 0 +913 2093 0 +1484 2225 0 +1788 2358 0 +2017 2490 0 +2210 2623 0 +2383 2755 0 +2543 2887 0 +2695 3019 0 +2842 3152 0 +2984 3283 0 +3124 3416 0 +3261 3548 0 +3398 3680 0 +3533 3812 0 +3668 3944 0 +3801 4076 0 +3935 4095 0 +0 1390 1696 +0 1403 1695 +0 1420 1693 +0 1442 1691 +0 1465 1691 +0 1495 1691 +0 1532 1691 +0 1577 1691 +0 1631 1691 +0 1691 1688 +0 1691 1600 +0 1691 1447 +0 1691 1098 +0 1825 0 +0 1959 0 +977 2092 0 +1503 2225 0 +1798 2357 0 +2023 2490 0 +2214 2622 0 +2386 2755 0 +2545 2887 0 +2696 3019 0 +2842 3151 0 +2985 3283 0 +3124 3416 0 +3262 3548 0 +3398 3680 0 +3533 3812 0 +3668 3944 0 +3801 4076 0 +3935 4095 0 +0 1362 1696 +0 1376 1695 +0 1394 1693 +0 1417 1691 +0 1446 1689 +0 1477 1689 +0 1515 1689 +0 1562 1689 +0 1617 1689 +0 1683 1689 +0 1689 1608 +0 1689 1457 +0 1689 1120 +0 1823 0 +0 1958 0 +1050 2091 0 +1527 2224 0 +1811 2357 0 +2031 2489 0 +2219 2622 0 +2389 2755 0 +2548 2887 0 +2698 3019 0 +2844 3151 0 +2986 3283 0 +3125 3416 0 +3262 3548 0 +3399 3680 0 +3534 3812 0 +3668 3944 0 +3801 4076 0 +3935 4095 0 +0 1322 1696 +0 1337 1695 +0 1357 1693 +0 1382 1691 +0 1413 1689 +0 1452 1685 +0 1492 1685 +0 1541 1685 +0 1599 1685 +0 1667 1685 +0 1685 1618 +0 1685 1471 +0 1685 1149 +0 1821 0 +0 1956 0 +1133 2089 0 +1557 2223 0 +1828 2356 0 +2041 2489 0 +2226 2621 0 +2394 2754 0 +2551 2887 0 +2701 3019 0 +2845 3151 0 +2987 3283 0 +3126 3416 0 +3263 3548 0 +3399 3680 0 +3534 3812 0 +3668 3944 0 +3802 4076 0 +3935 4095 0 +0 1262 1696 +0 1279 1695 +0 1302 1693 +0 1330 1691 +0 1365 1689 +0 1408 1685 +0 1460 1681 +0 1512 1681 +0 1574 1681 +0 1645 1681 +0 1681 1631 +0 1681 1489 +0 1681 1184 +0 1817 0 +0 1953 0 +1224 2087 0 +1596 2221 0 +1849 2355 0 +2055 2488 0 +2235 2621 0 +2400 2754 0 +2555 2886 0 +2703 3018 0 +2848 3151 0 +2988 3283 0 +3127 3415 0 +3264 3548 0 +3400 3680 0 +3534 3812 0 +3668 3944 0 +3802 4076 0 +3935 4095 0 +0 1167 1696 +0 1188 1695 +0 1216 1693 +0 1249 1691 +0 1291 1689 +0 1341 1685 +0 1401 1681 +0 1470 1674 +0 1537 1674 +0 1614 1674 +0 1674 1648 +0 1674 1512 +0 1674 1228 +0 1813 0 +670 1950 0 +1322 2085 0 +1642 2220 0 +1876 2353 0 +2072 2487 0 +2247 2620 0 +2408 2753 0 +2561 2886 0 +2708 3018 0 +2851 3151 0 +2991 3283 0 +3129 3415 0 +3265 3548 0 +3401 3680 0 +3535 3812 0 +3669 3944 0 +3802 4076 0 +3936 4095 0 +0 998 1696 +0 1029 1695 +0 1067 1693 +0 1113 1691 +0 1169 1689 +0 1233 1685 +0 1308 1681 +0 1391 1674 +608 1483 1666 +608 1569 1666 +608 1663 1666 +608 1666 1541 +608 1666 1281 +0 1807 438 +1007 1945 0 +1428 2082 0 +1697 2217 0 +1910 2352 0 +2094 2486 0 +2262 2619 0 +2419 2752 0 +2569 2885 0 +2714 3018 0 +2855 3151 0 +2994 3283 0 +3131 3415 0 +3267 3548 0 +3402 3680 0 +3536 3812 0 +3670 3944 0 +3803 4076 0 +3936 4095 0 +0 580 1696 +0 653 1695 +0 736 1693 +0 827 1691 +0 926 1689 +0 1031 1685 +0 1142 1681 +0 1258 1674 +608 1378 1666 +959 1500 1654 +959 1608 1654 +959 1654 1577 +959 1654 1343 +742 1798 740 +1248 1939 0 +1539 2077 0 +1762 2214 0 +1951 2349 0 +2122 2484 0 +2281 2618 0 +2433 2751 0 +2579 2885 0 +2721 3017 0 +2860 3150 0 +2998 3282 0 +3134 3415 0 +3269 3547 0 +3404 3680 0 +3537 3812 0 +3671 3944 0 +3803 4076 0 +3937 4095 0 +0 0 1696 +0 0 1695 +0 0 1693 +0 0 1691 +0 0 1689 +0 406 1685 +0 742 1681 +0 983 1674 +608 1183 1666 +959 1360 1654 +1205 1522 1638 +1205 1638 1621 +1205 1638 1414 +1189 1787 1090 +1447 1930 872 +1655 2071 79 +1836 2209 0 +2002 2346 0 +2158 2481 0 +2306 2616 0 +2451 2750 0 +2592 2883 0 +2731 3016 0 +2868 3150 0 +3003 3282 0 +3138 3414 0 +3272 3547 0 +3406 3679 0 +3539 3812 0 +3672 3944 0 +3804 4076 0 +3937 4095 0 +0 0 1696 +0 0 1695 +0 0 1693 +0 0 1691 +0 0 1689 +0 0 1685 +0 0 1681 +313 0 1674 +609 608 1666 +959 1056 1654 +1205 1333 1638 +1407 1550 1616 +1407 1616 1495 +1466 1771 1337 +1624 1919 1223 +1774 2062 1005 +1920 2203 217 +2061 2341 0 +2201 2478 0 +2338 2613 0 +2474 2748 0 +2609 2882 0 +2743 3015 0 +2877 3149 0 +3010 3281 0 +3143 3414 0 +3276 3547 0 +3409 3679 0 +3541 3812 0 +3673 3944 0 +3805 4076 0 +3938 4095 0 +1056 0 1696 +1066 0 1695 +1080 0 1693 +1098 0 1691 +1120 0 1689 +1149 0 1685 +1184 0 1681 +1228 0 1674 +1281 608 1666 +1343 959 1654 +1414 1205 1638 +1495 1407 1616 +1585 1585 1585 +1682 1748 1539 +1787 1903 1469 +1897 2051 1355 +2012 2194 1136 +2131 2335 345 +2253 2473 0 +2377 2610 0 +2503 2746 0 +2631 2880 0 +2759 3014 0 +2889 3148 0 +3019 3280 0 +3150 3414 0 +3281 3546 0 +3413 3679 0 +3544 3811 0 +3676 3944 0 +3807 4076 0 +3939 4095 0 +1557 0 1828 +1560 0 1828 +1565 0 1827 +1571 0 1825 +1579 0 1823 +1590 0 1821 +1604 0 1817 +1622 0 1813 +1644 0 1807 +1673 740 1798 +1709 1090 1787 +1754 1337 1771 +1748 1539 1682 +1748 1627 1539 +1903 1885 1469 +2004 2051 1355 +2097 2194 1136 +2198 2335 345 +2305 2473 0 +2417 2610 0 +2534 2746 0 +2654 2880 0 +2777 3014 0 +2903 3148 0 +3029 3280 0 +3158 3414 0 +3287 3546 0 +3417 3679 0 +3547 3811 0 +3678 3944 0 +3809 4076 0 +3941 4095 0 +1847 0 1961 +1849 0 1961 +1851 0 1960 +1854 0 1959 +1859 0 1958 +1865 0 1956 +1872 0 1953 +1882 0 1950 +1895 0 1945 +1912 0 1939 +1930 872 1927 +1919 1223 1872 +1903 1469 1787 +1903 1469 1598 +1903 1678 1469 +2051 1973 1355 +2191 2194 1136 +2274 2335 345 +2366 2473 0 +2466 2610 0 +2572 2746 0 +2684 2880 0 +2800 3014 0 +2920 3148 0 +3043 3280 0 +3168 3414 0 +3294 3546 0 +3422 3679 0 +3552 3811 0 +3681 3944 0 +3812 4076 0 +3942 4095 0 +2069 0 2094 +2070 0 2093 +2071 0 2093 +2073 0 2092 +2076 0 2091 +2080 0 2089 +2085 0 2087 +2085 0 2079 +2082 0 2063 +2077 0 2041 +2071 79 2010 +2062 1005 1965 +2051 1355 1897 +2051 1355 1756 +2051 1355 1453 +2051 1739 1355 +2194 2069 1136 +2335 2308 345 +2438 2473 0 +2524 2610 0 +2619 2746 0 +2721 2880 0 +2829 3014 0 +2942 3148 0 +3060 3280 0 +3181 3414 0 +3304 3546 0 +3430 3679 0 +3557 3811 0 +3685 3944 0 +3814 4076 0 +3945 4095 0 +2226 0 2191 +2226 0 2190 +2225 0 2188 +2225 0 2185 +2224 0 2181 +2223 0 2176 +2221 0 2169 +2220 0 2159 +2217 0 2146 +2214 0 2128 +2209 0 2102 +2203 217 2066 +2194 1136 2012 +2194 1136 1906 +2194 1136 1711 +2194 1136 1137 +2194 1809 1136 +2335 2173 345 +2473 2423 0 +2592 2610 0 +2674 2746 0 +2766 2880 0 +2865 3014 0 +2970 3148 0 +3082 3280 0 +3198 3414 0 +3317 3546 0 +3440 3679 0 +3564 3811 0 +3691 3944 0 +3819 4076 0 +3948 4095 0 +2358 0 2275 +2358 0 2273 +2358 0 2271 +2357 0 2269 +2357 0 2266 +2356 0 2262 +2355 0 2256 +2353 0 2248 +2352 0 2237 +2349 0 2223 +2346 0 2202 +2341 0 2173 +2335 345 2131 +2335 345 2052 +2335 345 1919 +2335 345 1644 +2335 970 345 +2335 1889 345 +2473 2282 0 +2610 2543 0 +2740 2746 0 +2820 2880 0 +2908 3014 0 +3005 3148 0 +3109 3280 0 +3219 3414 0 +3334 3546 0 +3453 3679 0 +3574 3811 0 +3699 3944 0 +3824 4076 0 +3952 4095 0 +2491 0 2367 +2491 0 2366 +2490 0 2364 +2490 0 2362 +2489 0 2360 +2489 0 2356 +2488 0 2352 +2487 0 2345 +2486 0 2336 +2484 0 2325 +2481 0 2308 +2478 0 2285 +2473 0 2253 +2473 0 2194 +2473 0 2100 +2473 0 1935 +2473 0 1535 +2473 557 0 +2473 1977 0 +2610 2396 0 +2746 2665 0 +2880 2877 0 +2961 3014 0 +3049 3148 0 +3144 3280 0 +3247 3414 0 +3355 3546 0 +3469 3679 0 +3587 3811 0 +3708 3944 0 +3832 4076 0 +3958 4095 0 +2623 0 2466 +2623 0 2465 +2623 0 2464 +2622 0 2463 +2622 0 2460 +2621 0 2458 +2621 0 2454 +2620 0 2449 +2619 0 2442 +2618 0 2432 +2616 0 2420 +2613 0 2402 +2610 0 2377 +2610 0 2333 +2610 0 2266 +2610 0 2158 +2610 0 1956 +2610 0 1330 +2610 0 0 +2610 2073 0 +2746 2515 0 +2880 2789 0 +3014 3004 0 +3100 3148 0 +3186 3280 0 +3281 3414 0 +3382 3546 0 +3490 3679 0 +3604 3811 0 +3721 3944 0 +3841 4076 0 +3965 4095 0 +2755 0 2573 +2755 0 2572 +2755 0 2571 +2755 0 2570 +2755 0 2568 +2754 0 2566 +2754 0 2563 +2753 0 2559 +2752 0 2553 +2751 0 2546 +2750 0 2536 +2748 0 2522 +2746 0 2503 +2746 0 2470 +2746 0 2422 +2746 0 2348 +2746 0 2226 +2746 0 1983 +2746 0 678 +2746 0 0 +2746 2177 0 +2880 2636 0 +3014 2915 0 +3148 3133 0 +3238 3280 0 +3323 3414 0 +3416 3546 0 +3517 3679 0 +3625 3811 0 +3737 3944 0 +3854 4076 0 +3975 4095 0 +2887 0 2684 +2887 0 2684 +2887 0 2683 +2887 0 2682 +2887 0 2681 +2887 0 2679 +2886 0 2677 +2886 0 2673 +2885 0 2669 +2885 0 2664 +2883 0 2656 +2882 0 2645 +2880 0 2631 +2880 0 2606 +2880 0 2571 +2880 0 2519 +2880 0 2439 +2880 0 2302 +2880 0 2016 +2880 0 0 +2880 0 0 +2880 2287 0 +3014 2759 0 +3148 3043 0 +3280 3262 0 +3374 3414 0 +3458 3546 0 +3551 3679 0 +3652 3811 0 +3758 3944 0 +3871 4076 0 +3988 4095 0 +3019 0 2800 +3019 0 2800 +3019 0 2799 +3019 0 2798 +3019 0 2797 +3019 0 2796 +3018 0 2794 +3018 0 2792 +3018 0 2789 +3017 0 2784 +3016 0 2778 +3015 0 2770 +3014 0 2759 +3014 0 2741 +3014 0 2715 +3014 0 2678 +3014 0 2623 +3014 0 2536 +3014 0 2388 +3014 0 2056 +3014 0 0 +3014 0 0 +3014 2401 0 +3148 2886 0 +3280 3172 0 +3414 3393 0 +3509 3546 0 +3593 3679 0 +3685 3811 0 +3785 3944 0 +3891 4076 0 +4004 4095 0 +3152 0 2920 +3152 0 2920 +3152 0 2919 +3151 0 2919 +3151 0 2918 +3151 0 2917 +3151 0 2916 +3151 0 2914 +3151 0 2911 +3150 0 2908 +3150 0 2904 +3149 0 2898 +3148 0 2889 +3148 0 2875 +3148 0 2856 +3148 0 2829 +3148 0 2790 +3148 0 2733 +3148 0 2642 +3148 0 2482 +3148 0 2106 +3148 0 0 +3148 0 0 +3148 2520 0 +3280 3013 0 +3414 3301 0 +3546 3523 0 +3643 3679 0 +3727 3811 0 +3819 3944 0 +3918 4076 0 +4025 4095 0 +3284 0 3043 +3283 0 3042 +3283 0 3042 +3283 0 3042 +3283 0 3041 +3283 0 3040 +3283 0 3039 +3283 0 3038 +3283 0 3036 +3282 0 3033 +3282 0 3030 +3281 0 3025 +3280 0 3019 +3280 0 3009 +3280 0 2995 +3280 0 2975 +3280 0 2947 +3280 0 2907 +3280 0 2847 +3280 0 2752 +3280 0 2583 +3280 0 2164 +3280 0 0 +3280 0 0 +3280 2641 0 +3414 3142 0 +3546 3432 0 +3679 3654 0 +3777 3811 0 +3860 3944 0 +3952 4076 0 +4051 4095 0 +3416 0 3168 +3416 0 3168 +3416 0 3167 +3416 0 3167 +3416 0 3166 +3416 0 3166 +3415 0 3165 +3415 0 3164 +3415 0 3163 +3415 0 3161 +3414 0 3158 +3414 0 3155 +3414 0 3150 +3414 0 3142 +3414 0 3132 +3414 0 3117 +3414 0 3097 +3414 0 3069 +3414 0 3027 +3414 0 2966 +3414 0 2867 +3414 0 2691 +3414 0 2234 +3414 0 0 +3414 0 0 +3414 2765 0 +3546 3271 0 +3679 3563 0 +3811 3785 0 +3910 3944 0 +3993 4076 0 +4085 4095 0 +3548 0 3294 +3548 0 3294 +3548 0 3294 +3548 0 3294 +3548 0 3293 +3548 0 3293 +3548 0 3292 +3548 0 3292 +3548 0 3291 +3547 0 3289 +3547 0 3287 +3547 0 3285 +3546 0 3281 +3546 0 3275 +3546 0 3268 +3546 0 3257 +3546 0 3242 +3546 0 3221 +3546 0 3192 +3546 0 3151 +3546 0 3087 +3546 0 2987 +3546 0 2804 +3546 0 2311 +3546 0 0 +3546 0 0 +3546 2891 0 +3679 3401 0 +3811 3694 0 +3944 3917 0 +4043 4076 0 +4095 4095 0 +3680 0 3422 +3680 0 3422 +3680 0 3422 +3680 0 3422 +3680 0 3422 +3680 0 3421 +3680 0 3421 +3680 0 3420 +3680 0 3420 +3680 0 3418 +3679 0 3417 +3679 0 3415 +3679 0 3413 +3679 0 3408 +3679 0 3402 +3679 0 3394 +3679 0 3384 +3679 0 3368 +3679 0 3348 +3679 0 3318 +3679 0 3276 +3679 0 3212 +3679 0 3110 +3679 0 2922 +3679 0 2400 +3679 0 0 +3679 0 0 +3679 3018 0 +3811 3532 0 +3944 3825 0 +4076 4048 0 +4095 4095 0 +3812 0 3552 +3812 0 3551 +3812 0 3551 +3812 0 3551 +3812 0 3551 +3812 0 3551 +3812 0 3550 +3812 0 3550 +3812 0 3549 +3812 0 3548 +3812 0 3547 +3812 0 3546 +3811 0 3544 +3811 0 3541 +3811 0 3536 +3811 0 3530 +3811 0 3522 +3811 0 3511 +3811 0 3496 +3811 0 3475 +3811 0 3446 +3811 0 3403 +3811 0 3338 +3811 0 3234 +3811 0 3043 +3811 0 2494 +3811 0 0 +3811 0 0 +3811 3147 0 +3944 3663 0 +4076 3956 0 +4095 4095 0 +3944 0 3681 +3944 0 3681 +3944 0 3681 +3944 0 3681 +3944 0 3681 +3944 0 3681 +3944 0 3680 +3944 0 3680 +3944 0 3680 +3944 0 3679 +3944 0 3678 +3944 0 3677 +3944 0 3676 +3944 0 3673 +3944 0 3670 +3944 0 3666 +3944 0 3659 +3944 0 3651 +3944 0 3640 +3944 0 3625 +3944 0 3604 +3944 0 3574 +3944 0 3531 +3944 0 3466 +3944 0 3361 +3944 0 3166 +3944 0 2596 +3944 0 0 +3944 0 0 +3944 3277 0 +4076 3794 0 +4095 4088 0 +4076 0 3812 +4076 0 3811 +4076 0 3811 +4076 0 3811 +4076 0 3811 +4076 0 3811 +4076 0 3811 +4076 0 3810 +4076 0 3810 +4076 0 3810 +4076 0 3809 +4076 0 3808 +4076 0 3807 +4076 0 3805 +4076 0 3803 +4076 0 3800 +4076 0 3795 +4076 0 3789 +4076 0 3781 +4076 0 3770 +4076 0 3755 +4076 0 3734 +4076 0 3703 +4076 0 3660 +4076 0 3594 +4076 0 3488 +4076 0 3291 +4076 0 2703 +4076 0 0 +4076 0 0 +4076 3407 0 +4095 3926 0 +4095 0 3942 +4095 0 3942 +4095 0 3942 +4095 0 3942 +4095 0 3942 +4095 0 3942 +4095 0 3942 +4095 0 3942 +4095 0 3941 +4095 0 3941 +4095 0 3941 +4095 0 3940 +4095 0 3939 +4095 0 3938 +4095 0 3936 +4095 0 3934 +4095 0 3930 +4095 0 3926 +4095 0 3920 +4095 0 3912 +4095 0 3901 +4095 0 3885 +4095 0 3864 +4095 0 3834 +4095 0 3790 +4095 0 3724 +4095 0 3617 +4095 0 3419 +4095 0 2818 +4095 0 0 +4095 0 0 +4095 3538 0 +0 1565 1828 +0 1572 1828 +0 1582 1828 +0 1596 1828 +0 1612 1828 +0 1634 1828 +0 1661 1828 +0 1696 1828 +0 1738 1828 +0 1789 1828 +0 1828 1807 +0 1828 1716 +0 1828 1557 +0 1828 1180 +0 1961 0 +0 2094 0 +907 2226 0 +1580 2358 0 +1903 2491 0 +2138 2623 0 +2335 2755 0 +2510 2887 0 +2672 3019 0 +2825 3152 0 +2972 3284 0 +3115 3416 0 +3255 3548 0 +3393 3680 0 +3530 3812 0 +3665 3944 0 +3799 4076 0 +3933 4095 0 +0 1557 1828 +0 1566 1828 +0 1576 1828 +0 1590 1828 +0 1607 1828 +0 1629 1828 +0 1656 1828 +0 1691 1828 +0 1733 1828 +0 1785 1828 +0 1828 1810 +0 1828 1719 +0 1828 1560 +0 1828 1188 +0 1961 0 +0 2093 0 +944 2226 0 +1589 2358 0 +1907 2491 0 +2141 2623 0 +2337 2755 0 +2511 2887 0 +2672 3019 0 +2825 3152 0 +2972 3283 0 +3115 3416 0 +3255 3548 0 +3393 3680 0 +3530 3812 0 +3665 3944 0 +3799 4076 0 +3933 4095 0 +0 1547 1828 +0 1556 1828 +0 1568 1827 +0 1582 1827 +0 1599 1827 +0 1621 1827 +0 1650 1827 +0 1684 1827 +0 1727 1827 +0 1779 1827 +0 1827 1812 +0 1827 1722 +0 1827 1565 +0 1827 1198 +0 1960 0 +0 2093 0 +990 2225 0 +1600 2358 0 +1913 2490 0 +2144 2623 0 +2339 2755 0 +2513 2887 0 +2673 3019 0 +2826 3152 0 +2973 3283 0 +3115 3416 0 +3256 3548 0 +3393 3680 0 +3530 3812 0 +3665 3944 0 +3799 4076 0 +3933 4095 0 +0 1532 1828 +0 1542 1828 +0 1554 1827 +0 1571 1825 +0 1588 1825 +0 1611 1825 +0 1640 1825 +0 1676 1825 +0 1720 1825 +0 1772 1825 +0 1825 1816 +0 1825 1727 +0 1825 1571 +0 1825 1212 +0 1959 0 +0 2092 0 +1044 2225 0 +1615 2357 0 +1920 2490 0 +2149 2622 0 +2342 2755 0 +2515 2887 0 +2675 3019 0 +2827 3151 0 +2973 3283 0 +3116 3416 0 +3256 3548 0 +3394 3680 0 +3530 3812 0 +3665 3944 0 +3799 4076 0 +3933 4095 0 +0 1512 1828 +0 1522 1828 +0 1535 1827 +0 1552 1825 +0 1574 1823 +0 1598 1823 +0 1627 1823 +0 1664 1823 +0 1709 1823 +0 1763 1823 +0 1823 1821 +0 1823 1732 +0 1823 1579 +0 1823 1230 +0 1958 0 +0 2091 0 +1108 2224 0 +1634 2357 0 +1930 2489 0 +2155 2622 0 +2346 2755 0 +2517 2887 0 +2677 3019 0 +2829 3151 0 +2974 3283 0 +3117 3416 0 +3256 3548 0 +3394 3680 0 +3530 3812 0 +3665 3944 0 +3800 4076 0 +3934 4095 0 +0 1484 1828 +0 1494 1828 +0 1508 1827 +0 1526 1825 +0 1549 1823 +0 1579 1821 +0 1609 1821 +0 1648 1821 +0 1694 1821 +0 1750 1821 +0 1815 1821 +0 1821 1740 +0 1821 1590 +0 1821 1253 +0 1956 0 +0 2089 0 +1181 2223 0 +1659 2356 0 +1943 2489 0 +2163 2621 0 +2351 2754 0 +2521 2887 0 +2679 3019 0 +2830 3151 0 +2976 3283 0 +3118 3416 0 +3257 3548 0 +3395 3680 0 +3531 3812 0 +3666 3944 0 +3800 4076 0 +3934 4095 0 +0 1442 1828 +0 1454 1828 +0 1469 1827 +0 1489 1825 +0 1514 1823 +0 1545 1821 +0 1585 1817 +0 1625 1817 +0 1673 1817 +0 1732 1817 +0 1799 1817 +0 1817 1750 +0 1817 1604 +0 1817 1281 +0 1953 0 +0 2087 0 +1264 2221 0 +1689 2355 0 +1960 2488 0 +2173 2621 0 +2358 2754 0 +2526 2886 0 +2683 3018 0 +2833 3151 0 +2977 3283 0 +3119 3415 0 +3258 3548 0 +3395 3680 0 +3531 3812 0 +3666 3944 0 +3800 4076 0 +3934 4095 0 +0 1381 1828 +0 1394 1828 +0 1412 1827 +0 1434 1825 +0 1462 1823 +0 1497 1821 +0 1540 1817 +0 1592 1813 +0 1644 1813 +0 1706 1813 +0 1777 1813 +0 1813 1763 +0 1813 1622 +0 1813 1317 +0 1950 0 +10 2085 0 +1355 2220 0 +1727 2353 0 +1981 2487 0 +2187 2620 0 +2367 2753 0 +2532 2886 0 +2687 3018 0 +2836 3151 0 +2980 3283 0 +3121 3415 0 +3259 3548 0 +3396 3680 0 +3532 3812 0 +3666 3944 0 +3801 4076 0 +3934 4095 0 +0 1283 1828 +0 1300 1828 +0 1321 1827 +0 1348 1825 +0 1382 1823 +0 1423 1821 +0 1474 1817 +0 1533 1813 +0 1602 1807 +0 1669 1807 +0 1746 1807 +0 1807 1780 +0 1807 1644 +0 1807 1360 +0 1945 37 +800 2082 0 +1454 2217 0 +1773 2352 0 +2008 2486 0 +2204 2619 0 +2379 2752 0 +2540 2885 0 +2693 3018 0 +2840 3151 0 +2983 3283 0 +3123 3415 0 +3261 3548 0 +3397 3680 0 +3533 3812 0 +3667 3944 0 +3801 4076 0 +3935 4095 0 +0 1106 1828 +0 1131 1828 +0 1161 1827 +0 1199 1825 +0 1245 1823 +0 1301 1821 +0 1366 1817 +0 1440 1813 +0 1523 1807 +740 1615 1798 +740 1701 1798 +740 1795 1798 +740 1798 1673 +740 1798 1413 +0 1939 573 +1138 2077 0 +1560 2214 0 +1829 2349 0 +2042 2484 0 +2226 2618 0 +2394 2751 0 +2551 2885 0 +2701 3017 0 +2846 3150 0 +2987 3282 0 +3126 3415 0 +3263 3547 0 +3399 3680 0 +3534 3812 0 +3668 3944 0 +3802 4076 0 +3935 4095 0 +0 650 1828 +0 713 1828 +0 786 1827 +0 869 1825 +0 960 1823 +0 1059 1821 +0 1164 1817 +0 1275 1813 +0 1391 1807 +740 1510 1798 +1090 1633 1787 +1090 1740 1787 +1090 1787 1709 +1090 1787 1475 +873 1930 872 +1379 2071 79 +1671 2209 0 +1894 2346 0 +2084 2481 0 +2255 2616 0 +2414 2750 0 +2565 2883 0 +2711 3016 0 +2853 3150 0 +2992 3282 0 +3130 3414 0 +3266 3547 0 +3401 3679 0 +3536 3812 0 +3669 3944 0 +3803 4076 0 +3936 4095 0 +0 0 1828 +0 0 1828 +0 0 1827 +0 0 1825 +0 0 1823 +0 0 1821 +0 536 1817 +0 874 1813 +0 1115 1807 +740 1315 1798 +1090 1491 1787 +1337 1654 1771 +1337 1771 1754 +1337 1771 1546 +1321 1919 1223 +1579 2062 1005 +1787 2203 217 +1968 2341 0 +2134 2478 0 +2290 2613 0 +2439 2748 0 +2583 2882 0 +2724 3015 0 +2863 3149 0 +2999 3281 0 +3135 3414 0 +3270 3547 0 +3404 3679 0 +3538 3812 0 +3671 3944 0 +3804 4076 0 +3937 4095 0 +0 0 1828 +0 0 1828 +0 0 1827 +0 0 1825 +0 0 1823 +0 0 1821 +0 0 1817 +0 0 1813 +438 0 1807 +740 742 1798 +1090 1189 1787 +1337 1466 1771 +1539 1682 1748 +1539 1748 1627 +1598 1903 1469 +1756 2051 1355 +1906 2194 1136 +2052 2335 345 +2194 2473 0 +2333 2610 0 +2470 2746 0 +2606 2880 0 +2741 3014 0 +2875 3148 0 +3009 3280 0 +3142 3414 0 +3275 3546 0 +3408 3679 0 +3541 3811 0 +3673 3944 0 +3805 4076 0 +3938 4095 0 +1180 0 1828 +1188 0 1828 +1198 0 1827 +1212 0 1825 +1230 0 1823 +1253 0 1821 +1281 0 1817 +1317 0 1813 +1360 0 1807 +1413 740 1798 +1475 1090 1787 +1546 1337 1771 +1627 1539 1748 +1717 1717 1717 +1814 1880 1671 +1919 2035 1601 +2029 2183 1487 +2144 2326 1269 +2263 2467 477 +2385 2605 0 +2509 2742 0 +2636 2878 0 +2763 3012 0 +2892 3146 0 +3021 3280 0 +3151 3413 0 +3282 3546 0 +3413 3678 0 +3545 3811 0 +3676 3943 0 +3808 4076 0 +3940 4095 0 +1686 0 1961 +1689 0 1961 +1692 0 1960 +1697 0 1959 +1703 0 1958 +1711 0 1956 +1722 0 1953 +1736 0 1950 +1754 0 1945 +1776 0 1939 +1805 872 1930 +1841 1223 1919 +1885 1469 1903 +1880 1671 1814 +1880 1759 1671 +2035 2017 1601 +2136 2183 1487 +2229 2326 1269 +2330 2467 477 +2437 2605 0 +2550 2742 0 +2666 2878 0 +2786 3012 0 +2910 3146 0 +3034 3280 0 +3162 3413 0 +3290 3546 0 +3419 3678 0 +3549 3811 0 +3679 3943 0 +3810 4076 0 +3941 4095 0 +1977 0 2094 +1979 0 2093 +1981 0 2093 +1983 0 2092 +1986 0 2091 +1991 0 2089 +1996 0 2087 +2004 0 2085 +2014 0 2082 +2027 0 2077 +2044 79 2071 +2062 1005 2059 +2051 1355 2004 +2035 1601 1919 +2035 1601 1730 +2035 1811 1601 +2183 2105 1487 +2323 2326 1269 +2407 2467 477 +2498 2605 0 +2598 2742 0 +2704 2878 0 +2816 3012 0 +2932 3146 0 +3052 3280 0 +3175 3413 0 +3300 3546 0 +3426 3678 0 +3554 3811 0 +3683 3943 0 +3813 4076 0 +3944 4095 0 +2200 0 2226 +2201 0 2226 +2202 0 2225 +2203 0 2225 +2206 0 2224 +2208 0 2223 +2212 0 2221 +2217 0 2220 +2217 0 2211 +2214 0 2195 +2209 0 2174 +2203 217 2142 +2194 1136 2097 +2183 1487 2029 +2183 1487 1888 +2183 1487 1585 +2183 1871 1487 +2326 2202 1269 +2467 2440 477 +2570 2605 0 +2656 2742 0 +2751 2878 0 +2853 3012 0 +2961 3146 0 +3074 3280 0 +3192 3413 0 +3313 3546 0 +3436 3678 0 +3562 3811 0 +3689 3943 0 +3817 4076 0 +3947 4095 0 +2358 0 2325 +2358 0 2324 +2358 0 2322 +2357 0 2320 +2357 0 2317 +2356 0 2313 +2355 0 2308 +2353 0 2301 +2352 0 2291 +2349 0 2278 +2346 0 2260 +2341 0 2234 +2335 345 2198 +2326 1269 2144 +2326 1269 2038 +2326 1269 1843 +2326 1269 1270 +2326 1941 1269 +2467 2305 477 +2605 2556 0 +2724 2742 0 +2807 2878 0 +2898 3012 0 +2997 3146 0 +3102 3280 0 +3214 3413 0 +3330 3546 0 +3449 3678 0 +3572 3811 0 +3697 3943 0 +3823 4076 0 +3951 4095 0 +2491 0 2408 +2491 0 2407 +2490 0 2406 +2490 0 2404 +2489 0 2401 +2489 0 2398 +2488 0 2394 +2487 0 2388 +2486 0 2380 +2484 0 2369 +2481 0 2355 +2478 0 2334 +2473 0 2305 +2467 477 2263 +2467 477 2184 +2467 477 2051 +2467 477 1776 +2467 1099 477 +2467 2021 477 +2605 2414 0 +2742 2675 0 +2872 2878 0 +2952 3012 0 +3041 3146 0 +3138 3280 0 +3242 3413 0 +3351 3546 0 +3466 3678 0 +3585 3811 0 +3706 3943 0 +3830 4076 0 +3957 4095 0 +2623 0 2500 +2623 0 2499 +2623 0 2498 +2622 0 2496 +2622 0 2494 +2621 0 2492 +2621 0 2488 +2620 0 2483 +2619 0 2477 +2618 0 2469 +2616 0 2456 +2613 0 2440 +2610 0 2417 +2605 0 2385 +2605 0 2326 +2605 0 2233 +2605 0 2067 +2605 0 1667 +2605 705 0 +2605 2109 0 +2742 2529 0 +2878 2797 0 +3012 3009 0 +3093 3146 0 +3180 3280 0 +3276 3413 0 +3379 3546 0 +3488 3678 0 +3601 3811 0 +3719 3943 0 +3840 4076 0 +3964 4095 0 +2755 0 2599 +2755 0 2598 +2755 0 2598 +2755 0 2596 +2755 0 2595 +2754 0 2593 +2754 0 2590 +2753 0 2586 +2752 0 2581 +2751 0 2574 +2750 0 2565 +2748 0 2552 +2746 0 2534 +2742 0 2509 +2742 0 2465 +2742 0 2398 +2742 0 2291 +2742 0 2089 +2742 0 1463 +2742 0 0 +2742 2206 0 +2878 2647 0 +3012 2921 0 +3146 3137 0 +3233 3280 0 +3319 3413 0 +3413 3546 0 +3515 3678 0 +3622 3811 0 +3736 3943 0 +3853 4076 0 +3974 4095 0 +2887 0 2705 +2887 0 2705 +2887 0 2704 +2887 0 2703 +2887 0 2702 +2887 0 2700 +2886 0 2698 +2886 0 2695 +2885 0 2691 +2885 0 2685 +2883 0 2678 +2882 0 2668 +2880 0 2654 +2878 0 2636 +2878 0 2602 +2878 0 2554 +2878 0 2480 +2878 0 2358 +2878 0 2115 +2878 0 817 +2878 0 0 +2878 2309 0 +3012 2767 0 +3146 3047 0 +3280 3265 0 +3370 3413 0 +3455 3546 0 +3548 3678 0 +3650 3811 0 +3757 3943 0 +3869 4076 0 +3986 4095 0 +3019 0 2816 +3019 0 2816 +3019 0 2816 +3019 0 2815 +3019 0 2814 +3019 0 2813 +3018 0 2811 +3018 0 2808 +3018 0 2805 +3017 0 2801 +3016 0 2796 +3015 0 2788 +3014 0 2777 +3012 0 2763 +3012 0 2738 +3012 0 2703 +3012 0 2651 +3012 0 2570 +3012 0 2434 +3012 0 2148 +3012 0 0 +3012 0 0 +3012 2419 0 +3146 2892 0 +3280 3175 0 +3413 3395 0 +3506 3546 0 +3590 3678 0 +3683 3811 0 +3784 3943 0 +3890 4076 0 +4003 4095 0 +3152 0 2933 +3152 0 2932 +3152 0 2932 +3151 0 2932 +3151 0 2931 +3151 0 2930 +3151 0 2928 +3151 0 2927 +3151 0 2924 +3150 0 2921 +3150 0 2917 +3149 0 2911 +3148 0 2903 +3146 0 2892 +3146 0 2873 +3146 0 2847 +3146 0 2810 +3146 0 2755 +3146 0 2669 +3146 0 2521 +3146 0 2189 +3146 0 0 +3146 0 0 +3146 2533 0 +3280 3017 0 +3413 3304 0 +3546 3525 0 +3641 3678 0 +3725 3811 0 +3817 3943 0 +3917 4076 0 +4024 4095 0 +3284 0 3052 +3283 0 3052 +3283 0 3052 +3283 0 3051 +3283 0 3051 +3283 0 3050 +3283 0 3049 +3283 0 3047 +3283 0 3046 +3282 0 3043 +3282 0 3040 +3281 0 3035 +3280 0 3029 +3280 0 3021 +3280 0 3007 +3280 0 2988 +3280 0 2961 +3280 0 2922 +3280 0 2865 +3280 0 2773 +3280 0 2613 +3280 0 2237 +3280 0 0 +3280 0 0 +3280 2651 0 +3413 3145 0 +3546 3434 0 +3678 3655 0 +3775 3811 0 +3859 3943 0 +3950 4076 0 +4051 4095 0 +3416 0 3175 +3416 0 3175 +3416 0 3175 +3416 0 3174 +3416 0 3174 +3416 0 3173 +3415 0 3173 +3415 0 3171 +3415 0 3170 +3415 0 3168 +3414 0 3165 +3414 0 3162 +3414 0 3158 +3413 0 3151 +3413 0 3141 +3413 0 3127 +3413 0 3107 +3413 0 3079 +3413 0 3039 +3413 0 2979 +3413 0 2884 +3413 0 2715 +3413 0 2298 +3413 0 0 +3413 0 0 +3413 2773 0 +3546 3274 0 +3678 3564 0 +3811 3786 0 +3909 3943 0 +3992 4076 0 +4084 4095 0 +3548 0 3300 +3548 0 3300 +3548 0 3300 +3548 0 3299 +3548 0 3299 +3548 0 3299 +3548 0 3298 +3548 0 3297 +3548 0 3296 +3547 0 3295 +3547 0 3293 +3547 0 3290 +3546 0 3287 +3546 0 3282 +3546 0 3275 +3546 0 3264 +3546 0 3249 +3546 0 3229 +3546 0 3201 +3546 0 3160 +3546 0 3098 +3546 0 3000 +3546 0 2824 +3546 0 2365 +3546 0 0 +3546 0 0 +3546 2897 0 +3678 3403 0 +3811 3695 0 +3943 3917 0 +4042 4076 0 +4095 4095 0 +3680 0 3427 +3680 0 3426 +3680 0 3426 +3680 0 3426 +3680 0 3426 +3680 0 3426 +3680 0 3425 +3680 0 3425 +3680 0 3424 +3680 0 3423 +3679 0 3421 +3679 0 3419 +3679 0 3417 +3678 0 3413 +3678 0 3407 +3678 0 3400 +3678 0 3389 +3678 0 3374 +3678 0 3354 +3678 0 3325 +3678 0 3282 +3678 0 3220 +3678 0 3119 +3678 0 2936 +3678 0 2445 +3678 0 0 +3678 0 0 +3678 3023 0 +3811 3534 0 +3943 3826 0 +4076 4049 0 +4095 4095 0 +3812 0 3554 +3812 0 3554 +3812 0 3554 +3812 0 3554 +3812 0 3554 +3812 0 3554 +3812 0 3553 +3812 0 3553 +3812 0 3552 +3812 0 3552 +3812 0 3551 +3812 0 3549 +3811 0 3547 +3811 0 3545 +3811 0 3540 +3811 0 3534 +3811 0 3526 +3811 0 3516 +3811 0 3501 +3811 0 3480 +3811 0 3450 +3811 0 3408 +3811 0 3344 +3811 0 3241 +3811 0 3054 +3811 0 2531 +3811 0 0 +3811 0 0 +3811 3151 0 +3943 3664 0 +4076 3957 0 +4095 4095 0 +3944 0 3683 +3944 0 3683 +3944 0 3683 +3944 0 3683 +3944 0 3683 +3944 0 3683 +3944 0 3683 +3944 0 3682 +3944 0 3682 +3944 0 3681 +3944 0 3680 +3944 0 3679 +3944 0 3678 +3943 0 3676 +3943 0 3673 +3943 0 3668 +3943 0 3662 +3943 0 3655 +3943 0 3644 +3943 0 3628 +3943 0 3607 +3943 0 3578 +3943 0 3535 +3943 0 3470 +3943 0 3366 +3943 0 3175 +3943 0 2625 +3943 0 0 +3943 0 0 +3943 3279 0 +4076 3795 0 +4095 4089 0 +4076 0 3813 +4076 0 3813 +4076 0 3813 +4076 0 3813 +4076 0 3813 +4076 0 3813 +4076 0 3812 +4076 0 3812 +4076 0 3812 +4076 0 3812 +4076 0 3811 +4076 0 3810 +4076 0 3809 +4076 0 3808 +4076 0 3805 +4076 0 3802 +4076 0 3798 +4076 0 3792 +4076 0 3784 +4076 0 3773 +4076 0 3757 +4076 0 3736 +4076 0 3706 +4076 0 3663 +4076 0 3597 +4076 0 3492 +4076 0 3297 +4076 0 2726 +4076 0 0 +4076 0 0 +4076 3409 0 +4095 3927 0 +4095 0 3944 +4095 0 3944 +4095 0 3944 +4095 0 3944 +4095 0 3944 +4095 0 3944 +4095 0 3943 +4095 0 3943 +4095 0 3943 +4095 0 3943 +4095 0 3942 +4095 0 3941 +4095 0 3941 +4095 0 3940 +4095 0 3938 +4095 0 3935 +4095 0 3932 +4095 0 3927 +4095 0 3922 +4095 0 3913 +4095 0 3903 +4095 0 3887 +4095 0 3866 +4095 0 3836 +4095 0 3792 +4095 0 3727 +4095 0 3621 +4095 0 3424 +4095 0 2837 +4095 0 0 +4095 0 0 +4095 3539 0 +0 1696 1961 +0 1702 1961 +0 1709 1961 +0 1719 1961 +0 1732 1961 +0 1749 1961 +0 1770 1961 +0 1797 1961 +0 1831 1961 +0 1873 1961 +0 1923 1961 +0 1961 1938 +0 1961 1847 +0 1961 1686 +0 1961 1306 +0 2094 0 +0 2226 0 +1009 2358 0 +1706 2491 0 +2032 2623 0 +2269 2755 0 +2466 2887 0 +2641 3019 0 +2803 3152 0 +2956 3284 0 +3104 3416 0 +3247 3548 0 +3387 3680 0 +3525 3812 0 +3661 3944 0 +3797 4076 0 +3932 4095 0 +0 1690 1961 +0 1697 1961 +0 1705 1961 +0 1715 1961 +0 1728 1961 +0 1745 1961 +0 1766 1961 +0 1793 1961 +0 1828 1961 +0 1870 1961 +0 1920 1961 +0 1961 1940 +0 1961 1849 +0 1961 1689 +0 1961 1312 +0 2093 0 +0 2226 0 +1039 2358 0 +1713 2491 0 +2035 2623 0 +2271 2755 0 +2467 2887 0 +2642 3019 0 +2804 3152 0 +2957 3283 0 +3104 3416 0 +3247 3548 0 +3387 3680 0 +3525 3812 0 +3662 3944 0 +3797 4076 0 +3932 4095 0 +0 1682 1961 +0 1689 1961 +0 1699 1960 +0 1708 1960 +0 1722 1960 +0 1739 1960 +0 1761 1960 +0 1789 1960 +0 1823 1960 +0 1865 1960 +0 1917 1960 +0 1960 1941 +0 1960 1851 +0 1960 1692 +0 1960 1320 +0 2093 0 +0 2225 0 +1076 2358 0 +1722 2490 0 +2039 2623 0 +2274 2755 0 +2469 2887 0 +2643 3019 0 +2805 3152 0 +2957 3283 0 +3104 3416 0 +3247 3548 0 +3387 3680 0 +3525 3812 0 +3662 3944 0 +3797 4076 0 +3932 4095 0 +0 1672 1961 +0 1679 1961 +0 1688 1960 +0 1700 1959 +0 1714 1959 +0 1731 1959 +0 1754 1959 +0 1781 1959 +0 1817 1959 +0 1860 1959 +0 1911 1959 +0 1959 1944 +0 1959 1854 +0 1959 1697 +0 1959 1331 +0 2092 0 +0 2225 0 +1122 2357 0 +1733 2490 0 +2045 2622 0 +2277 2755 0 +2471 2887 0 +2645 3019 0 +2806 3151 0 +2958 3283 0 +3105 3416 0 +3248 3548 0 +3388 3680 0 +3526 3812 0 +3662 3944 0 +3797 4076 0 +3932 4095 0 +0 1657 1961 +0 1664 1961 +0 1674 1960 +0 1686 1959 +0 1703 1958 +0 1721 1958 +0 1743 1958 +0 1772 1958 +0 1808 1958 +0 1852 1958 +0 1905 1958 +0 1958 1948 +0 1958 1859 +0 1958 1703 +0 1958 1344 +0 2091 0 +0 2224 0 +1176 2357 0 +1748 2489 0 +2052 2622 0 +2281 2755 0 +2474 2887 0 +2647 3019 0 +2807 3151 0 +2959 3283 0 +3106 3416 0 +3248 3548 0 +3388 3680 0 +3526 3812 0 +3662 3944 0 +3797 4076 0 +3932 4095 0 +0 1636 1961 +0 1644 1961 +0 1654 1960 +0 1667 1959 +0 1684 1958 +0 1706 1956 +0 1730 1956 +0 1759 1956 +0 1796 1956 +0 1841 1956 +0 1895 1956 +0 1956 1953 +0 1956 1865 +0 1956 1711 +0 1956 1362 +0 2089 0 +0 2223 0 +1240 2356 0 +1767 2489 0 +2062 2621 0 +2287 2754 0 +2478 2887 0 +2649 3019 0 +2809 3151 0 +2960 3283 0 +3106 3416 0 +3249 3548 0 +3388 3680 0 +3526 3812 0 +3662 3944 0 +3797 4076 0 +3932 4095 0 +0 1607 1961 +0 1615 1961 +0 1626 1960 +0 1640 1959 +0 1658 1958 +0 1681 1956 +0 1711 1953 +0 1742 1953 +0 1779 1953 +0 1826 1953 +0 1882 1953 +0 1947 1953 +0 1953 1872 +0 1953 1722 +0 1953 1385 +0 2087 0 +0 2221 0 +1313 2355 0 +1791 2488 0 +2075 2621 0 +2295 2754 0 +2483 2886 0 +2653 3018 0 +2812 3151 0 +2962 3283 0 +3108 3415 0 +3250 3548 0 +3389 3680 0 +3527 3812 0 +3663 3944 0 +3798 4076 0 +3932 4095 0 +0 1565 1961 +0 1574 1961 +0 1586 1960 +0 1601 1959 +0 1621 1958 +0 1646 1956 +0 1678 1953 +0 1716 1950 +0 1757 1950 +0 1806 1950 +0 1864 1950 +0 1931 1950 +0 1950 1882 +0 1950 1736 +0 1950 1413 +0 2085 0 +0 2220 0 +1396 2353 0 +1822 2487 0 +2092 2620 0 +2305 2753 0 +2490 2886 0 +2658 3018 0 +2815 3151 0 +2965 3283 0 +3110 3415 0 +3251 3548 0 +3390 3680 0 +3528 3812 0 +3663 3944 0 +3798 4076 0 +3932 4095 0 +0 1503 1961 +0 1513 1961 +0 1526 1960 +0 1544 1959 +0 1566 1958 +0 1594 1956 +0 1629 1953 +0 1672 1950 +0 1724 1945 +0 1776 1945 +0 1838 1945 +0 1909 1945 +0 1945 1895 +0 1945 1754 +0 1945 1449 +0 2082 0 +140 2217 0 +1487 2352 0 +1859 2486 0 +2113 2619 0 +2319 2752 0 +2499 2885 0 +2664 3018 0 +2819 3151 0 +2968 3283 0 +3112 3415 0 +3253 3548 0 +3392 3680 0 +3528 3812 0 +3664 3944 0 +3798 4076 0 +3933 4095 0 +0 1402 1961 +0 1415 1961 +0 1431 1960 +0 1453 1959 +0 1480 1958 +0 1514 1956 +0 1555 1953 +0 1606 1950 +0 1665 1945 +0 1734 1939 +0 1801 1939 +0 1878 1939 +0 1939 1912 +0 1939 1776 +0 1939 1492 +0 2077 173 +932 2214 0 +1586 2349 0 +1906 2484 0 +2140 2618 0 +2336 2751 0 +2511 2885 0 +2672 3017 0 +2825 3150 0 +2972 3282 0 +3115 3415 0 +3255 3547 0 +3393 3680 0 +3530 3812 0 +3665 3944 0 +3799 4076 0 +3933 4095 0 +0 1220 1961 +0 1238 1961 +0 1263 1960 +0 1294 1959 +0 1332 1958 +0 1378 1956 +0 1433 1953 +0 1498 1950 +0 1572 1945 +0 1655 1939 +872 1748 1930 +872 1833 1930 +872 1927 1930 +872 1930 1805 +872 1930 1545 +79 2071 706 +1270 2209 0 +1692 2346 0 +1961 2481 0 +2174 2616 0 +2359 2750 0 +2526 2883 0 +2683 3016 0 +2833 3150 0 +2977 3282 0 +3119 3414 0 +3258 3547 0 +3395 3679 0 +3531 3812 0 +3666 3944 0 +3800 4076 0 +3934 4095 0 +0 726 1961 +0 780 1961 +0 844 1960 +0 917 1959 +0 1000 1958 +0 1091 1956 +0 1190 1953 +0 1295 1950 +0 1407 1945 +0 1523 1939 +872 1642 1930 +1223 1765 1919 +1223 1872 1919 +1223 1919 1841 +1223 1919 1607 +1006 2062 1005 +1512 2203 217 +1803 2341 0 +2026 2478 0 +2216 2613 0 +2387 2748 0 +2546 2882 0 +2697 3015 0 +2843 3149 0 +2985 3281 0 +3125 3414 0 +3262 3547 0 +3398 3679 0 +3533 3812 0 +3668 3944 0 +3801 4076 0 +3935 4095 0 +0 0 1961 +0 0 1961 +0 0 1960 +0 0 1959 +0 0 1958 +0 0 1956 +0 0 1953 +0 670 1950 +0 1007 1945 +0 1248 1939 +872 1447 1930 +1223 1624 1919 +1469 1787 1903 +1469 1903 1885 +1469 1903 1678 +1453 2051 1355 +1711 2194 1136 +1919 2335 345 +2100 2473 0 +2266 2610 0 +2422 2746 0 +2571 2880 0 +2715 3014 0 +2856 3148 0 +2995 3280 0 +3132 3414 0 +3268 3546 0 +3402 3679 0 +3536 3811 0 +3670 3944 0 +3803 4076 0 +3936 4095 0 +0 0 1961 +0 0 1961 +0 0 1960 +0 0 1959 +0 0 1958 +0 0 1956 +0 0 1953 +0 0 1950 +37 0 1945 +573 0 1939 +872 873 1930 +1223 1321 1919 +1469 1598 1903 +1671 1814 1880 +1671 1880 1759 +1730 2035 1601 +1888 2183 1487 +2038 2326 1269 +2184 2467 477 +2326 2605 0 +2465 2742 0 +2602 2878 0 +2738 3012 0 +2873 3146 0 +3007 3280 0 +3141 3413 0 +3275 3546 0 +3407 3678 0 +3540 3811 0 +3673 3943 0 +3805 4076 0 +3938 4095 0 +1306 0 1961 +1312 0 1961 +1320 0 1960 +1331 0 1959 +1344 0 1958 +1362 0 1956 +1385 0 1953 +1413 0 1950 +1449 0 1945 +1492 0 1939 +1545 872 1930 +1607 1223 1919 +1678 1469 1903 +1759 1671 1880 +1849 1849 1849 +1946 2013 1803 +2051 2167 1733 +2161 2315 1619 +2276 2459 1401 +2395 2599 611 +2517 2738 0 +2641 2874 0 +2767 3010 0 +2895 3144 0 +3024 3278 0 +3154 3412 0 +3284 3545 0 +3414 3678 0 +3545 3810 0 +3677 3943 0 +3808 4075 0 +3940 4095 0 +1816 0 2094 +1818 0 2093 +1821 0 2093 +1824 0 2092 +1829 0 2091 +1835 0 2089 +1843 0 2087 +1854 0 2085 +1868 0 2082 +1886 0 2077 +1908 79 2071 +1937 1005 2062 +1973 1355 2051 +2017 1601 2035 +2013 1803 1946 +2013 1891 1803 +2167 2149 1733 +2268 2315 1619 +2362 2459 1401 +2462 2599 611 +2569 2738 0 +2681 2874 0 +2798 3010 0 +2919 3144 0 +3041 3278 0 +3167 3412 0 +3294 3545 0 +3422 3678 0 +3551 3810 0 +3681 3943 0 +3811 4075 0 +3942 4095 0 +2108 0 2226 +2109 0 2226 +2111 0 2225 +2112 0 2225 +2115 0 2224 +2118 0 2223 +2123 0 2221 +2128 0 2220 +2136 0 2217 +2146 0 2214 +2159 0 2209 +2176 217 2203 +2194 1136 2191 +2183 1487 2136 +2167 1733 2051 +2167 1733 1862 +2167 1943 1733 +2315 2237 1619 +2455 2459 1401 +2538 2599 611 +2631 2738 0 +2730 2874 0 +2836 3010 0 +2948 3144 0 +3064 3278 0 +3184 3412 0 +3307 3545 0 +3432 3678 0 +3559 3810 0 +3687 3943 0 +3816 4075 0 +3945 4095 0 +2332 0 2358 +2332 0 2358 +2333 0 2358 +2334 0 2357 +2335 0 2357 +2338 0 2356 +2340 0 2355 +2344 0 2353 +2349 0 2352 +2349 0 2343 +2346 0 2328 +2341 0 2305 +2335 345 2274 +2326 1269 2229 +2315 1619 2161 +2315 1619 2020 +2315 1619 1718 +2315 2003 1619 +2459 2334 1401 +2599 2572 611 +2702 2738 0 +2788 2874 0 +2883 3010 0 +2985 3144 0 +3093 3278 0 +3206 3412 0 +3324 3545 0 +3445 3678 0 +3569 3810 0 +3694 3943 0 +3821 4075 0 +3950 4095 0 +2491 0 2458 +2491 0 2457 +2490 0 2456 +2490 0 2454 +2489 0 2452 +2489 0 2449 +2488 0 2445 +2487 0 2440 +2486 0 2433 +2484 0 2423 +2481 0 2410 +2478 0 2392 +2473 0 2366 +2467 477 2330 +2459 1401 2276 +2459 1401 2171 +2459 1401 1976 +2459 1401 1403 +2459 2073 1401 +2599 2437 611 +2738 2688 0 +2856 2874 0 +2939 3010 0 +3030 3144 0 +3129 3278 0 +3234 3412 0 +3346 3545 0 +3462 3678 0 +3582 3810 0 +3704 3943 0 +3829 4075 0 +3955 4095 0 +2623 0 2541 +2623 0 2540 +2623 0 2539 +2622 0 2538 +2622 0 2536 +2621 0 2533 +2621 0 2530 +2620 0 2526 +2619 0 2520 +2618 0 2512 +2616 0 2501 +2613 0 2487 +2610 0 2466 +2605 0 2437 +2599 611 2395 +2599 611 2316 +2599 611 2183 +2599 611 1908 +2599 1236 611 +2599 2153 611 +2738 2547 0 +2874 2807 0 +3004 3010 0 +3084 3144 0 +3173 3278 0 +3270 3412 0 +3374 3545 0 +3483 3678 0 +3598 3810 0 +3717 3943 0 +3838 4075 0 +3963 4095 0 +2755 0 2632 +2755 0 2632 +2755 0 2631 +2755 0 2630 +2755 0 2628 +2754 0 2627 +2754 0 2624 +2753 0 2620 +2752 0 2616 +2751 0 2609 +2750 0 2601 +2748 0 2589 +2746 0 2572 +2742 0 2550 +2738 0 2517 +2738 0 2458 +2738 0 2365 +2738 0 2200 +2738 0 1799 +2738 817 0 +2738 2241 0 +2874 2661 0 +3010 2928 0 +3144 3141 0 +3225 3278 0 +3313 3412 0 +3408 3545 0 +3511 3678 0 +3620 3810 0 +3733 3943 0 +3851 4075 0 +3972 4095 0 +2887 0 2732 +2887 0 2731 +2887 0 2731 +2887 0 2730 +2887 0 2728 +2887 0 2727 +2886 0 2725 +2886 0 2722 +2885 0 2718 +2885 0 2713 +2883 0 2706 +2882 0 2697 +2880 0 2684 +2878 0 2666 +2874 0 2641 +2874 0 2597 +2874 0 2530 +2874 0 2423 +2874 0 2220 +2874 0 1596 +2874 0 0 +2874 2338 0 +3010 2778 0 +3144 3053 0 +3278 3269 0 +3365 3412 0 +3451 3545 0 +3545 3678 0 +3647 3810 0 +3755 3943 0 +3868 4075 0 +3985 4095 0 +3019 0 2837 +3019 0 2837 +3019 0 2836 +3019 0 2836 +3019 0 2835 +3019 0 2834 +3018 0 2832 +3018 0 2830 +3018 0 2827 +3017 0 2823 +3016 0 2817 +3015 0 2810 +3014 0 2800 +3012 0 2786 +3010 0 2767 +3010 0 2734 +3010 0 2686 +3010 0 2612 +3010 0 2489 +3010 0 2247 +3010 0 922 +3010 0 0 +3010 2441 0 +3144 2901 0 +3278 3180 0 +3412 3397 0 +3502 3545 0 +3587 3678 0 +3680 3810 0 +3781 3943 0 +3889 4075 0 +4002 4095 0 +3152 0 2949 +3152 0 2949 +3152 0 2948 +3151 0 2948 +3151 0 2947 +3151 0 2946 +3151 0 2945 +3151 0 2943 +3151 0 2941 +3150 0 2938 +3150 0 2933 +3149 0 2928 +3148 0 2920 +3146 0 2910 +3144 0 2895 +3144 0 2870 +3144 0 2835 +3144 0 2783 +3144 0 2703 +3144 0 2566 +3144 0 2280 +3144 0 0 +3144 0 0 +3144 2551 0 +3278 3023 0 +3412 3307 0 +3545 3526 0 +3638 3678 0 +3722 3810 0 +3815 3943 0 +3916 4075 0 +4023 4095 0 +3284 0 3065 +3283 0 3065 +3283 0 3064 +3283 0 3064 +3283 0 3063 +3283 0 3062 +3283 0 3062 +3283 0 3060 +3283 0 3059 +3282 0 3056 +3282 0 3053 +3281 0 3049 +3280 0 3043 +3280 0 3034 +3278 0 3024 +3278 0 3005 +3278 0 2979 +3278 0 2942 +3278 0 2886 +3278 0 2800 +3278 0 2651 +3278 0 2320 +3278 0 0 +3278 0 0 +3278 2665 0 +3412 3150 0 +3545 3436 0 +3678 3657 0 +3773 3810 0 +3857 3943 0 +3949 4075 0 +4049 4095 0 +3416 0 3184 +3416 0 3184 +3416 0 3184 +3416 0 3184 +3416 0 3184 +3416 0 3183 +3415 0 3182 +3415 0 3181 +3415 0 3180 +3415 0 3178 +3414 0 3175 +3414 0 3172 +3414 0 3168 +3413 0 3162 +3412 0 3154 +3412 0 3140 +3412 0 3120 +3412 0 3093 +3412 0 3055 +3412 0 2997 +3412 0 2906 +3412 0 2746 +3412 0 2371 +3412 0 0 +3412 0 0 +3412 2784 0 +3545 3278 0 +3678 3566 0 +3810 3787 0 +3907 3943 0 +3991 4075 0 +4083 4095 0 +3548 0 3307 +3548 0 3307 +3548 0 3307 +3548 0 3307 +3548 0 3307 +3548 0 3306 +3548 0 3305 +3548 0 3305 +3548 0 3303 +3547 0 3302 +3547 0 3300 +3547 0 3298 +3546 0 3294 +3546 0 3290 +3545 0 3284 +3545 0 3273 +3545 0 3259 +3545 0 3239 +3545 0 3211 +3545 0 3171 +3545 0 3111 +3545 0 3016 +3545 0 2848 +3545 0 2429 +3545 0 0 +3545 0 0 +3545 2905 0 +3678 3406 0 +3810 3696 0 +3943 3918 0 +4041 4075 0 +4095 4095 0 +3680 0 3432 +3680 0 3432 +3680 0 3432 +3680 0 3432 +3680 0 3431 +3680 0 3431 +3680 0 3431 +3680 0 3430 +3680 0 3429 +3680 0 3428 +3679 0 3427 +3679 0 3425 +3679 0 3422 +3678 0 3419 +3678 0 3414 +3678 0 3407 +3678 0 3396 +3678 0 3381 +3678 0 3361 +3678 0 3333 +3678 0 3291 +3678 0 3230 +3678 0 3132 +3678 0 2955 +3678 0 2499 +3678 0 0 +3678 0 0 +3678 3029 0 +3810 3536 0 +3943 3827 0 +4075 4049 0 +4095 4095 0 +3812 0 3559 +3812 0 3559 +3812 0 3559 +3812 0 3558 +3812 0 3558 +3812 0 3558 +3812 0 3558 +3812 0 3557 +3812 0 3557 +3812 0 3556 +3812 0 3555 +3812 0 3553 +3811 0 3552 +3811 0 3549 +3810 0 3545 +3810 0 3540 +3810 0 3532 +3810 0 3521 +3810 0 3506 +3810 0 3486 +3810 0 3457 +3810 0 3415 +3810 0 3352 +3810 0 3251 +3810 0 3069 +3810 0 2576 +3810 0 0 +3810 0 0 +3810 3155 0 +3943 3665 0 +4075 3958 0 +4095 4095 0 +3944 0 3687 +3944 0 3687 +3944 0 3687 +3944 0 3686 +3944 0 3686 +3944 0 3686 +3944 0 3686 +3944 0 3686 +3944 0 3685 +3944 0 3685 +3944 0 3684 +3944 0 3683 +3944 0 3681 +3943 0 3679 +3943 0 3677 +3943 0 3672 +3943 0 3666 +3943 0 3659 +3943 0 3648 +3943 0 3632 +3943 0 3612 +3943 0 3583 +3943 0 3540 +3943 0 3476 +3943 0 3374 +3943 0 3186 +3943 0 2662 +3943 0 0 +3943 0 0 +3943 3283 0 +4075 3796 0 +4095 4089 0 +4076 0 3816 +4076 0 3816 +4076 0 3816 +4076 0 3815 +4076 0 3815 +4076 0 3815 +4076 0 3815 +4076 0 3815 +4076 0 3814 +4076 0 3814 +4076 0 3813 +4076 0 3812 +4076 0 3812 +4076 0 3810 +4075 0 3808 +4075 0 3805 +4075 0 3801 +4075 0 3795 +4075 0 3787 +4075 0 3776 +4075 0 3760 +4075 0 3739 +4075 0 3710 +4075 0 3667 +4075 0 3602 +4075 0 3498 +4075 0 3306 +4075 0 2756 +4075 0 0 +4075 0 0 +4075 3411 0 +4095 3927 0 +4095 0 3946 +4095 0 3946 +4095 0 3945 +4095 0 3945 +4095 0 3945 +4095 0 3945 +4095 0 3945 +4095 0 3945 +4095 0 3945 +4095 0 3944 +4095 0 3944 +4095 0 3943 +4095 0 3942 +4095 0 3941 +4095 0 3940 +4095 0 3937 +4095 0 3934 +4095 0 3930 +4095 0 3924 +4095 0 3916 +4095 0 3905 +4095 0 3889 +4095 0 3868 +4095 0 3838 +4095 0 3795 +4095 0 3730 +4095 0 3625 +4095 0 3430 +4095 0 2861 +4095 0 0 +4095 0 0 +4095 3541 0 +0 1827 2094 +0 1831 2094 +0 1837 2094 +0 1845 2094 +0 1855 2094 +0 1867 2094 +0 1884 2094 +0 1905 2094 +0 1932 2094 +0 1966 2094 +0 2007 2094 +0 2058 2094 +0 2094 2069 +0 2094 1977 +0 2094 1816 +0 2094 1433 +0 2226 0 +0 2358 0 +1120 2491 0 +1833 2623 0 +2162 2755 0 +2400 2887 0 +2597 3019 0 +2773 3152 0 +2935 3284 0 +3088 3416 0 +3236 3548 0 +3379 3680 0 +3519 3812 0 +3657 3944 0 +3793 4076 0 +3929 4095 0 +0 1823 2094 +0 1828 2093 +0 1834 2093 +0 1841 2093 +0 1851 2093 +0 1864 2093 +0 1881 2093 +0 1902 2093 +0 1929 2093 +0 1963 2093 +0 2005 2093 +0 2056 2093 +0 2093 2070 +0 2093 1979 +0 2093 1818 +0 2093 1438 +0 2226 0 +0 2358 0 +1143 2491 0 +1838 2623 0 +2164 2755 0 +2401 2887 0 +2598 3019 0 +2773 3152 0 +2935 3283 0 +3088 3416 0 +3236 3548 0 +3379 3680 0 +3519 3812 0 +3657 3944 0 +3793 4076 0 +3929 4095 0 +0 1817 2094 +0 1822 2093 +0 1829 2093 +0 1837 2093 +0 1847 2093 +0 1860 2093 +0 1877 2093 +0 1898 2093 +0 1926 2093 +0 1960 2093 +0 2002 2093 +0 2053 2093 +0 2093 2071 +0 2093 1981 +0 2093 1821 +0 2093 1444 +0 2225 0 +0 2358 0 +1173 2490 0 +1845 2623 0 +2167 2755 0 +2403 2887 0 +2599 3019 0 +2774 3152 0 +2936 3283 0 +3089 3416 0 +3236 3548 0 +3379 3680 0 +3519 3812 0 +3657 3944 0 +3793 4076 0 +3929 4095 0 +0 1809 2094 +0 1814 2093 +0 1821 2093 +0 1830 2092 +0 1841 2092 +0 1854 2092 +0 1871 2092 +0 1893 2092 +0 1920 2092 +0 1955 2092 +0 1997 2092 +0 2049 2092 +0 2092 2073 +0 2092 1983 +0 2092 1824 +0 2092 1452 +0 2225 0 +0 2357 0 +1210 2490 0 +1853 2622 0 +2172 2755 0 +2406 2887 0 +2601 3019 0 +2775 3151 0 +2936 3283 0 +3089 3416 0 +3237 3548 0 +3379 3680 0 +3520 3812 0 +3657 3944 0 +3794 4076 0 +3929 4095 0 +0 1798 2094 +0 1804 2093 +0 1811 2093 +0 1820 2092 +0 1832 2091 +0 1846 2091 +0 1863 2091 +0 1885 2091 +0 1913 2091 +0 1949 2091 +0 1992 2091 +0 2044 2091 +0 2091 2076 +0 2091 1986 +0 2091 1829 +0 2091 1463 +0 2224 0 +0 2357 0 +1255 2489 0 +1865 2622 0 +2177 2755 0 +2409 2887 0 +2603 3019 0 +2777 3151 0 +2938 3283 0 +3090 3416 0 +3237 3548 0 +3380 3680 0 +3520 3812 0 +3658 3944 0 +3794 4076 0 +3929 4095 0 +0 1783 2094 +0 1789 2093 +0 1796 2093 +0 1806 2092 +0 1819 2091 +0 1835 2089 +0 1853 2089 +0 1875 2089 +0 1904 2089 +0 1940 2089 +0 1984 2089 +0 2037 2089 +0 2089 2080 +0 2089 1991 +0 2089 1835 +0 2089 1476 +0 2223 0 +0 2356 0 +1310 2489 0 +1880 2621 0 +2185 2754 0 +2413 2887 0 +2606 3019 0 +2779 3151 0 +2939 3283 0 +3091 3416 0 +3238 3548 0 +3380 3680 0 +3520 3812 0 +3658 3944 0 +3794 4076 0 +3929 4095 0 +0 1763 2094 +0 1768 2093 +0 1776 2093 +0 1786 2092 +0 1799 2091 +0 1816 2089 +0 1838 2087 +0 1862 2087 +0 1891 2087 +0 1928 2087 +0 1973 2087 +0 2027 2087 +0 2087 2085 +0 2087 1996 +0 2087 1843 +0 2087 1494 +0 2221 0 +0 2355 0 +1373 2488 0 +1899 2621 0 +2195 2754 0 +2419 2886 0 +2610 3018 0 +2782 3151 0 +2941 3283 0 +3093 3415 0 +3239 3548 0 +3381 3680 0 +3521 3812 0 +3658 3944 0 +3794 4076 0 +3930 4095 0 +0 1733 2094 +0 1739 2093 +0 1748 2093 +0 1758 2092 +0 1772 2091 +0 1790 2089 +0 1813 2087 +0 1843 2085 +0 1873 2085 +0 1912 2085 +0 1958 2085 +0 2014 2085 +0 2079 2085 +0 2085 2004 +0 2085 1854 +0 2085 1517 +0 2220 0 +0 2353 0 +1446 2487 0 +1923 2620 0 +2208 2753 0 +2427 2886 0 +2615 3018 0 +2785 3151 0 +2943 3283 0 +3094 3415 0 +3240 3548 0 +3382 3680 0 +3521 3812 0 +3659 3944 0 +3795 4076 0 +3930 4095 0 +0 1691 2094 +0 1698 2093 +0 1706 2093 +0 1718 2092 +0 1733 2091 +0 1753 2089 +0 1778 2087 +0 1810 2085 +0 1849 2082 +0 1889 2082 +0 1938 2082 +0 1996 2082 +0 2063 2082 +0 2082 2014 +0 2082 1868 +0 2082 1545 +0 2217 0 +0 2352 0 +1529 2486 0 +1954 2619 0 +2224 2752 0 +2438 2885 0 +2622 3018 0 +2790 3151 0 +2947 3283 0 +3097 3415 0 +3242 3548 0 +3383 3680 0 +3522 3812 0 +3659 3944 0 +3795 4076 0 +3930 4095 0 +0 1626 2094 +0 1635 2093 +0 1645 2093 +0 1658 2092 +0 1676 2091 +0 1698 2089 +0 1726 2087 +0 1761 2085 +0 1804 2082 +0 1856 2077 +0 1908 2077 +0 1970 2077 +0 2041 2077 +0 2077 2027 +0 2077 1886 +0 2077 1581 +0 2214 0 +275 2349 0 +1620 2484 0 +1991 2618 0 +2245 2751 0 +2451 2885 0 +2631 3017 0 +2796 3150 0 +2951 3282 0 +3100 3415 0 +3244 3547 0 +3385 3680 0 +3523 3812 0 +3661 3944 0 +3796 4076 0 +3931 4095 0 +0 1524 2094 +0 1534 2093 +0 1547 2093 +0 1564 2092 +0 1585 2091 +0 1612 2089 +0 1646 2087 +0 1687 2085 +0 1738 2082 +0 1797 2077 +79 1866 2071 +79 1934 2071 +79 2010 2071 +79 2071 2044 +79 2071 1908 +79 2071 1625 +0 2209 303 +1064 2346 0 +1719 2481 0 +2038 2616 0 +2273 2750 0 +2469 2883 0 +2643 3016 0 +2804 3150 0 +2957 3282 0 +3104 3414 0 +3247 3547 0 +3387 3679 0 +3525 3812 0 +3662 3944 0 +3797 4076 0 +3932 4095 0 +0 1336 2094 +0 1351 2093 +0 1370 2093 +0 1394 2092 +0 1425 2091 +0 1463 2089 +0 1509 2087 +0 1565 2085 +0 1630 2082 +0 1704 2077 +79 1787 2071 +1005 1880 2062 +1005 1965 2062 +1005 2059 2062 +1005 2062 1937 +1005 2062 1677 +217 2203 838 +1403 2341 0 +1824 2478 0 +2093 2613 0 +2306 2748 0 +2491 2882 0 +2658 3015 0 +2815 3149 0 +2965 3281 0 +3110 3414 0 +3251 3547 0 +3390 3679 0 +3528 3812 0 +3663 3944 0 +3798 4076 0 +3932 4095 0 +0 814 2094 +0 859 2093 +0 913 2093 +0 977 2092 +0 1050 2091 +0 1133 2089 +0 1224 2087 +0 1322 2085 +0 1428 2082 +0 1539 2077 +79 1655 2071 +1005 1774 2062 +1355 1897 2051 +1355 2004 2051 +1355 2051 1973 +1355 2051 1739 +1137 2194 1136 +1644 2335 345 +1935 2473 0 +2158 2610 0 +2348 2746 0 +2519 2880 0 +2678 3014 0 +2829 3148 0 +2975 3280 0 +3117 3414 0 +3257 3546 0 +3394 3679 0 +3530 3811 0 +3666 3944 0 +3800 4076 0 +3934 4095 0 +0 0 2094 +0 0 2093 +0 0 2093 +0 0 2092 +0 0 2091 +0 0 2089 +0 0 2087 +0 10 2085 +0 800 2082 +0 1138 2077 +79 1379 2071 +1005 1579 2062 +1355 1756 2051 +1601 1919 2035 +1601 2035 2017 +1601 2035 1811 +1585 2183 1487 +1843 2326 1269 +2051 2467 477 +2233 2605 0 +2398 2742 0 +2554 2878 0 +2703 3012 0 +2847 3146 0 +2988 3280 0 +3127 3413 0 +3264 3546 0 +3400 3678 0 +3534 3811 0 +3668 3943 0 +3802 4076 0 +3935 4095 0 +0 0 2094 +0 0 2093 +0 0 2093 +0 0 2092 +0 0 2091 +0 0 2089 +0 0 2087 +0 0 2085 +0 0 2082 +173 0 2077 +706 79 2071 +1005 1006 2062 +1355 1453 2051 +1601 1730 2035 +1803 1946 2013 +1803 2013 1891 +1862 2167 1733 +2020 2315 1619 +2171 2459 1401 +2316 2599 611 +2458 2738 0 +2597 2874 0 +2734 3010 0 +2870 3144 0 +3005 3278 0 +3140 3412 0 +3273 3545 0 +3407 3678 0 +3540 3810 0 +3672 3943 0 +3805 4075 0 +3937 4095 0 +1433 0 2094 +1438 0 2093 +1444 0 2093 +1452 0 2092 +1463 0 2091 +1476 0 2089 +1494 0 2087 +1517 0 2085 +1545 0 2082 +1581 0 2077 +1625 79 2071 +1677 1005 2062 +1739 1355 2051 +1811 1601 2035 +1891 1803 2013 +1981 1981 1981 +2078 2145 1935 +2183 2299 1865 +2293 2447 1751 +2408 2591 1533 +2527 2731 738 +2649 2870 0 +2773 3006 0 +2900 3142 0 +3027 3276 0 +3156 3410 0 +3285 3544 0 +3416 3677 0 +3547 3810 0 +3677 3943 0 +3809 4075 0 +3940 4095 0 +1946 0 2226 +1948 0 2226 +1950 0 2225 +1953 0 2225 +1956 0 2224 +1961 0 2223 +1967 0 2221 +1975 0 2220 +1986 0 2217 +2000 0 2214 +2018 0 2209 +2041 217 2203 +2069 1136 2194 +2105 1487 2183 +2149 1733 2167 +2145 1935 2078 +2145 2023 1935 +2299 2281 1865 +2401 2447 1751 +2493 2591 1533 +2594 2731 738 +2701 2870 0 +2813 3006 0 +2931 3142 0 +3050 3276 0 +3174 3410 0 +3299 3544 0 +3426 3677 0 +3554 3810 0 +3683 3943 0 +3813 4075 0 +3944 4095 0 +2239 0 2358 +2240 0 2358 +2241 0 2358 +2243 0 2357 +2245 0 2357 +2247 0 2356 +2251 0 2355 +2255 0 2353 +2261 0 2352 +2268 0 2349 +2278 0 2346 +2291 0 2341 +2308 345 2335 +2326 1269 2323 +2315 1619 2268 +2299 1865 2183 +2299 1865 1994 +2299 2075 1865 +2447 2370 1751 +2587 2591 1533 +2671 2731 738 +2763 2870 0 +2862 3006 0 +2969 3142 0 +3080 3276 0 +3196 3410 0 +3316 3544 0 +3439 3677 0 +3564 3810 0 +3691 3943 0 +3818 4075 0 +3948 4095 0 +2463 0 2491 +2464 0 2491 +2464 0 2490 +2465 0 2490 +2466 0 2489 +2468 0 2489 +2470 0 2488 +2473 0 2487 +2476 0 2486 +2481 0 2484 +2481 0 2475 +2478 0 2460 +2473 0 2438 +2467 477 2407 +2459 1401 2362 +2447 1751 2293 +2447 1751 2152 +2447 1751 1850 +2447 2135 1751 +2591 2466 1533 +2731 2705 738 +2834 2870 0 +2920 3006 0 +3015 3142 0 +3117 3276 0 +3225 3410 0 +3339 3544 0 +3456 3677 0 +3577 3810 0 +3701 3943 0 +3826 4075 0 +3953 4095 0 +2623 0 2590 +2623 0 2590 +2623 0 2589 +2622 0 2588 +2622 0 2586 +2621 0 2584 +2621 0 2581 +2620 0 2577 +2619 0 2572 +2618 0 2565 +2616 0 2555 +2613 0 2542 +2610 0 2524 +2605 0 2498 +2599 611 2462 +2591 1533 2408 +2591 1533 2303 +2591 1533 2108 +2591 1533 1533 +2591 2206 1533 +2731 2570 738 +2870 2820 0 +2988 3006 0 +3071 3142 0 +3162 3276 0 +3261 3410 0 +3367 3544 0 +3478 3677 0 +3594 3810 0 +3713 3943 0 +3836 4075 0 +3961 4095 0 +2755 0 2673 +2755 0 2673 +2755 0 2672 +2755 0 2671 +2755 0 2670 +2754 0 2668 +2754 0 2666 +2753 0 2662 +2752 0 2658 +2751 0 2652 +2750 0 2645 +2748 0 2634 +2746 0 2619 +2742 0 2598 +2738 0 2569 +2731 738 2527 +2731 738 2448 +2731 738 2315 +2731 738 2040 +2731 1362 738 +2731 2285 738 +2870 2678 0 +3006 2939 0 +3136 3142 0 +3216 3276 0 +3305 3410 0 +3402 3544 0 +3506 3677 0 +3616 3810 0 +3730 3943 0 +3849 4075 0 +3971 4095 0 +2887 0 2765 +2887 0 2764 +2887 0 2764 +2887 0 2763 +2887 0 2762 +2887 0 2761 +2886 0 2759 +2886 0 2756 +2885 0 2752 +2885 0 2748 +2883 0 2741 +2882 0 2733 +2880 0 2721 +2878 0 2704 +2874 0 2681 +2870 0 2649 +2870 0 2590 +2870 0 2497 +2870 0 2332 +2870 0 1932 +2870 963 0 +2870 2374 0 +3006 2792 0 +3142 3061 0 +3276 3273 0 +3358 3410 0 +3445 3544 0 +3540 3677 0 +3643 3810 0 +3752 3943 0 +3865 4075 0 +3983 4095 0 +3019 0 2864 +3019 0 2863 +3019 0 2863 +3019 0 2863 +3019 0 2862 +3019 0 2860 +3018 0 2859 +3018 0 2857 +3018 0 2854 +3017 0 2850 +3016 0 2845 +3015 0 2838 +3014 0 2829 +3012 0 2816 +3010 0 2798 +3006 0 2773 +3006 0 2729 +3006 0 2662 +3006 0 2554 +3006 0 2352 +3006 0 1723 +3006 0 0 +3006 2470 0 +3142 2911 0 +3276 3185 0 +3410 3401 0 +3497 3544 0 +3583 3677 0 +3677 3810 0 +3779 3943 0 +3887 4075 0 +4000 4095 0 +3152 0 2970 +3152 0 2970 +3152 0 2969 +3151 0 2969 +3151 0 2968 +3151 0 2967 +3151 0 2966 +3151 0 2964 +3151 0 2962 +3150 0 2959 +3150 0 2955 +3149 0 2950 +3148 0 2942 +3146 0 2932 +3144 0 2919 +3142 0 2900 +3142 0 2867 +3142 0 2818 +3142 0 2744 +3142 0 2622 +3142 0 2379 +3142 0 1068 +3142 0 0 +3142 2573 0 +3276 3032 0 +3410 3311 0 +3544 3529 0 +3634 3677 0 +3719 3810 0 +3813 3943 0 +3913 4075 0 +4021 4095 0 +3284 0 3081 +3283 0 3081 +3283 0 3081 +3283 0 3080 +3283 0 3080 +3283 0 3079 +3283 0 3078 +3283 0 3077 +3283 0 3075 +3282 0 3073 +3282 0 3070 +3281 0 3065 +3280 0 3060 +3280 0 3052 +3278 0 3041 +3276 0 3027 +3276 0 3002 +3276 0 2967 +3276 0 2915 +3276 0 2834 +3276 0 2698 +3276 0 2411 +3276 0 0 +3276 0 0 +3276 2683 0 +3410 3156 0 +3544 3440 0 +3677 3659 0 +3770 3810 0 +3854 3943 0 +3947 4075 0 +4048 4095 0 +3416 0 3197 +3416 0 3197 +3416 0 3197 +3416 0 3196 +3416 0 3196 +3416 0 3196 +3415 0 3195 +3415 0 3194 +3415 0 3192 +3415 0 3191 +3414 0 3188 +3414 0 3185 +3414 0 3181 +3413 0 3175 +3412 0 3167 +3410 0 3156 +3410 0 3137 +3410 0 3111 +3410 0 3074 +3410 0 3019 +3410 0 2933 +3410 0 2784 +3410 0 2453 +3410 0 0 +3410 0 0 +3410 2797 0 +3544 3282 0 +3677 3568 0 +3810 3789 0 +3905 3943 0 +3989 4075 0 +4082 4095 0 +3548 0 3317 +3548 0 3317 +3548 0 3317 +3548 0 3316 +3548 0 3316 +3548 0 3316 +3548 0 3315 +3548 0 3314 +3548 0 3313 +3547 0 3312 +3547 0 3310 +3547 0 3307 +3546 0 3304 +3546 0 3300 +3545 0 3294 +3544 0 3285 +3544 0 3272 +3544 0 3253 +3544 0 3225 +3544 0 3186 +3544 0 3129 +3544 0 3038 +3544 0 2879 +3544 0 2502 +3544 0 0 +3544 0 0 +3544 2916 0 +3677 3410 0 +3810 3698 0 +3943 3920 0 +4039 4075 0 +4095 4095 0 +3680 0 3440 +3680 0 3439 +3680 0 3439 +3680 0 3439 +3680 0 3439 +3680 0 3438 +3680 0 3438 +3680 0 3437 +3680 0 3437 +3680 0 3436 +3679 0 3434 +3679 0 3432 +3679 0 3430 +3678 0 3426 +3678 0 3422 +3677 0 3416 +3677 0 3405 +3677 0 3391 +3677 0 3371 +3677 0 3344 +3677 0 3303 +3677 0 3243 +3677 0 3149 +3677 0 2980 +3677 0 2562 +3677 0 0 +3677 0 0 +3677 3037 0 +3810 3538 0 +3943 3828 0 +4075 4050 0 +4095 4095 0 +3812 0 3564 +3812 0 3564 +3812 0 3564 +3812 0 3564 +3812 0 3564 +3812 0 3564 +3812 0 3563 +3812 0 3563 +3812 0 3562 +3812 0 3562 +3812 0 3561 +3812 0 3559 +3811 0 3557 +3811 0 3554 +3810 0 3551 +3810 0 3547 +3810 0 3539 +3810 0 3528 +3810 0 3514 +3810 0 3493 +3810 0 3465 +3810 0 3424 +3810 0 3362 +3810 0 3264 +3810 0 3088 +3810 0 2631 +3810 0 0 +3810 0 0 +3810 3161 0 +3943 3667 0 +4075 3959 0 +4095 4095 0 +3944 0 3691 +3944 0 3691 +3944 0 3691 +3944 0 3691 +3944 0 3691 +3944 0 3690 +3944 0 3690 +3944 0 3690 +3944 0 3689 +3944 0 3689 +3944 0 3688 +3944 0 3687 +3944 0 3685 +3943 0 3683 +3943 0 3681 +3943 0 3677 +3943 0 3672 +3943 0 3664 +3943 0 3653 +3943 0 3638 +3943 0 3618 +3943 0 3589 +3943 0 3547 +3943 0 3484 +3943 0 3384 +3943 0 3201 +3943 0 2708 +3943 0 0 +3943 0 0 +3943 3287 0 +4075 3797 0 +4095 4090 0 +4076 0 3819 +4076 0 3819 +4076 0 3819 +4076 0 3818 +4076 0 3818 +4076 0 3818 +4076 0 3818 +4076 0 3818 +4076 0 3818 +4076 0 3817 +4076 0 3816 +4076 0 3816 +4076 0 3814 +4076 0 3813 +4075 0 3811 +4075 0 3809 +4075 0 3804 +4075 0 3798 +4075 0 3790 +4075 0 3780 +4075 0 3765 +4075 0 3744 +4075 0 3714 +4075 0 3672 +4075 0 3608 +4075 0 3505 +4075 0 3318 +4075 0 2793 +4075 0 0 +4075 0 0 +4075 3415 0 +4095 3929 0 +4095 0 3948 +4095 0 3948 +4095 0 3948 +4095 0 3948 +4095 0 3948 +4095 0 3948 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3947 +4095 0 3946 +4095 0 3946 +4095 0 3945 +4095 0 3944 +4095 0 3942 +4095 0 3940 +4095 0 3937 +4095 0 3933 +4095 0 3927 +4095 0 3919 +4095 0 3908 +4095 0 3893 +4095 0 3872 +4095 0 3842 +4095 0 3799 +4095 0 3735 +4095 0 3630 +4095 0 3439 +4095 0 2890 +4095 0 0 +4095 0 0 +4095 3544 0 +0 1959 2226 +0 1962 2226 +0 1966 2226 +0 1972 2226 +0 1979 2226 +0 1989 2226 +0 2002 2226 +0 2018 2226 +0 2039 2226 +0 2066 2226 +0 2100 2226 +0 2141 2226 +0 2191 2226 +0 2226 2200 +0 2226 2108 +0 2226 1946 +0 2226 1562 +0 2358 0 +0 2491 0 +1232 2623 0 +1962 2755 0 +2292 2887 0 +2530 3019 0 +2729 3152 0 +2904 3284 0 +3067 3416 0 +3220 3548 0 +3367 3680 0 +3511 3812 0 +3651 3944 0 +3789 4076 0 +3926 4095 0 +0 1956 2226 +0 1959 2226 +0 1963 2226 +0 1969 2226 +0 1977 2226 +0 1987 2226 +0 1999 2226 +0 2016 2226 +0 2037 2226 +0 2064 2226 +0 2098 2226 +0 2140 2226 +0 2190 2226 +0 2226 2201 +0 2226 2109 +0 2226 1948 +0 2226 1565 +0 2358 0 +0 2491 0 +1251 2623 0 +1966 2755 0 +2294 2887 0 +2531 3019 0 +2729 3152 0 +2905 3283 0 +3067 3416 0 +3220 3548 0 +3368 3680 0 +3511 3812 0 +3651 3944 0 +3789 4076 0 +3926 4095 0 +0 1951 2226 +0 1955 2226 +0 1960 2225 +0 1966 2225 +0 1973 2225 +0 1983 2225 +0 1996 2225 +0 2013 2225 +0 2034 2225 +0 2061 2225 +0 2095 2225 +0 2137 2225 +0 2188 2225 +0 2225 2202 +0 2225 2111 +0 2225 1950 +0 2225 1570 +0 2358 0 +0 2490 0 +1275 2623 0 +1971 2755 0 +2296 2887 0 +2533 3019 0 +2730 3152 0 +2905 3283 0 +3067 3416 0 +3221 3548 0 +3368 3680 0 +3511 3812 0 +3651 3944 0 +3789 4076 0 +3926 4095 0 +0 1945 2226 +0 1949 2226 +0 1954 2225 +0 1961 2225 +0 1969 2225 +0 1979 2225 +0 1992 2225 +0 2009 2225 +0 2030 2225 +0 2058 2225 +0 2092 2225 +0 2134 2225 +0 2185 2225 +0 2225 2203 +0 2225 2112 +0 2225 1953 +0 2225 1576 +0 2357 0 +0 2490 0 +1304 2622 0 +1977 2755 0 +2299 2887 0 +2535 3019 0 +2732 3151 0 +2906 3283 0 +3068 3416 0 +3221 3548 0 +3368 3680 0 +3511 3812 0 +3651 3944 0 +3789 4076 0 +3926 4095 0 +0 1937 2226 +0 1941 2226 +0 1946 2225 +0 1953 2225 +0 1963 2224 +0 1973 2224 +0 1986 2224 +0 2003 2224 +0 2025 2224 +0 2053 2224 +0 2087 2224 +0 2130 2224 +0 2181 2224 +0 2224 2206 +0 2224 2115 +0 2224 1956 +0 2224 1584 +0 2357 0 +0 2489 0 +1342 2622 0 +1986 2755 0 +2304 2887 0 +2537 3019 0 +2733 3151 0 +2907 3283 0 +3069 3416 0 +3222 3548 0 +3369 3680 0 +3511 3812 0 +3652 3944 0 +3790 4076 0 +3926 4095 0 +0 1926 2226 +0 1930 2226 +0 1936 2225 +0 1943 2225 +0 1952 2224 +0 1965 2223 +0 1978 2223 +0 1995 2223 +0 2018 2223 +0 2046 2223 +0 2081 2223 +0 2124 2223 +0 2176 2223 +0 2223 2208 +0 2223 2118 +0 2223 1961 +0 2223 1595 +0 2356 0 +0 2489 0 +1387 2621 0 +1997 2754 0 +2310 2887 0 +2541 3019 0 +2735 3151 0 +2909 3283 0 +3070 3416 0 +3222 3548 0 +3369 3680 0 +3512 3812 0 +3652 3944 0 +3790 4076 0 +3926 4095 0 +0 1911 2226 +0 1915 2226 +0 1921 2225 +0 1928 2225 +0 1938 2224 +0 1951 2223 +0 1967 2221 +0 1985 2221 +0 2008 2221 +0 2036 2221 +0 2072 2221 +0 2116 2221 +0 2169 2221 +0 2221 2212 +0 2221 2123 +0 2221 1967 +0 2221 1608 +0 2355 0 +0 2488 0 +1441 2621 0 +2012 2754 0 +2317 2886 0 +2545 3018 0 +2738 3151 0 +2911 3283 0 +3071 3415 0 +3223 3548 0 +3370 3680 0 +3513 3812 0 +3652 3944 0 +3790 4076 0 +3927 4095 0 +0 1890 2226 +0 1894 2226 +0 1900 2225 +0 1908 2225 +0 1918 2224 +0 1931 2223 +0 1948 2221 +0 1970 2220 +0 1994 2220 +0 2023 2220 +0 2060 2220 +0 2105 2220 +0 2159 2220 +0 2220 2217 +0 2220 2128 +0 2220 1975 +0 2220 1626 +0 2353 0 +0 2487 0 +1505 2620 0 +2031 2753 0 +2327 2886 0 +2551 3018 0 +2742 3151 0 +2914 3283 0 +3073 3415 0 +3225 3548 0 +3371 3680 0 +3513 3812 0 +3653 3944 0 +3790 4076 0 +3927 4095 0 +0 1860 2226 +0 1865 2226 +0 1871 2225 +0 1880 2225 +0 1891 2224 +0 1904 2223 +0 1922 2221 +0 1946 2220 +0 1975 2217 +0 2006 2217 +0 2044 2217 +0 2090 2217 +0 2146 2217 +0 2211 2217 +0 2217 2136 +0 2217 1986 +0 2217 1649 +0 2352 0 +0 2486 0 +1578 2619 0 +2056 2752 0 +2340 2885 0 +2559 3018 0 +2747 3151 0 +2917 3283 0 +3076 3415 0 +3226 3548 0 +3372 3680 0 +3514 3812 0 +3653 3944 0 +3791 4076 0 +3927 4095 0 +0 1817 2226 +0 1823 2226 +0 1829 2225 +0 1839 2225 +0 1850 2224 +0 1865 2223 +0 1885 2221 +0 1910 2220 +0 1942 2217 +0 1981 2214 +0 2021 2214 +0 2070 2214 +0 2128 2214 +0 2195 2214 +0 2214 2146 +0 2214 2000 +0 2214 1677 +0 2349 0 +0 2484 0 +1661 2618 0 +2086 2751 0 +2356 2885 0 +2570 3017 0 +2754 3150 0 +2922 3282 0 +3079 3415 0 +3229 3547 0 +3374 3680 0 +3515 3812 0 +3654 3944 0 +3791 4076 0 +3927 4095 0 +0 1753 2226 +0 1759 2226 +0 1767 2225 +0 1777 2225 +0 1790 2224 +0 1808 2223 +0 1830 2221 +0 1858 2220 +0 1894 2217 +0 1936 2214 +0 1988 2209 +0 2041 2209 +0 2102 2209 +0 2174 2209 +0 2209 2159 +0 2209 2018 +0 2209 1713 +0 2346 0 +415 2481 0 +1752 2616 0 +2124 2750 0 +2378 2883 0 +2583 3016 0 +2763 3150 0 +2928 3282 0 +3083 3414 0 +3232 3547 0 +3376 3679 0 +3517 3812 0 +3656 3944 0 +3793 4076 0 +3928 4095 0 +0 1648 2226 +0 1656 2226 +0 1666 2225 +0 1679 2225 +0 1695 2224 +0 1717 2223 +0 1744 2221 +0 1778 2220 +0 1819 2217 +0 1870 2214 +0 1929 2209 +217 1998 2203 +217 2066 2203 +217 2142 2203 +217 2203 2176 +217 2203 2041 +217 2203 1757 +0 2341 437 +1199 2478 0 +1851 2613 0 +2170 2748 0 +2405 2882 0 +2600 3015 0 +2775 3149 0 +2936 3281 0 +3089 3414 0 +3236 3547 0 +3379 3679 0 +3520 3812 0 +3657 3944 0 +3794 4076 0 +3929 4095 0 +0 1457 2226 +0 1469 2226 +0 1484 2225 +0 1503 2225 +0 1527 2224 +0 1557 2223 +0 1596 2221 +0 1642 2220 +0 1697 2217 +0 1762 2214 +0 1836 2209 +217 1920 2203 +1136 2012 2194 +1136 2097 2194 +1136 2191 2194 +1136 2194 2069 +1136 2194 1809 +345 2335 970 +1535 2473 0 +1956 2610 0 +2226 2746 0 +2439 2880 0 +2623 3014 0 +2790 3148 0 +2947 3280 0 +3097 3414 0 +3242 3546 0 +3384 3679 0 +3522 3811 0 +3659 3944 0 +3795 4076 0 +3930 4095 0 +0 907 2226 +0 944 2226 +0 990 2225 +0 1044 2225 +0 1108 2224 +0 1181 2223 +0 1264 2221 +0 1355 2220 +0 1454 2217 +0 1560 2214 +0 1671 2209 +217 1787 2203 +1136 1906 2194 +1487 2029 2183 +1487 2136 2183 +1487 2183 2105 +1487 2183 1871 +1270 2326 1269 +1776 2467 477 +2067 2605 0 +2291 2742 0 +2480 2878 0 +2651 3012 0 +2810 3146 0 +2961 3280 0 +3107 3413 0 +3249 3546 0 +3389 3678 0 +3526 3811 0 +3662 3943 0 +3798 4076 0 +3932 4095 0 +0 0 2226 +0 0 2226 +0 0 2225 +0 0 2225 +0 0 2224 +0 0 2223 +0 0 2221 +0 0 2220 +0 140 2217 +0 932 2214 +0 1270 2209 +217 1512 2203 +1136 1711 2194 +1487 1888 2183 +1733 2051 2167 +1733 2167 2149 +1733 2167 1943 +1718 2315 1619 +1976 2459 1401 +2183 2599 611 +2365 2738 0 +2530 2874 0 +2686 3010 0 +2835 3144 0 +2979 3278 0 +3120 3412 0 +3259 3545 0 +3396 3678 0 +3532 3810 0 +3666 3943 0 +3801 4075 0 +3934 4095 0 +0 0 2226 +0 0 2226 +0 0 2225 +0 0 2225 +0 0 2224 +0 0 2223 +0 0 2221 +0 0 2220 +0 0 2217 +0 0 2214 +303 0 2209 +838 217 2203 +1136 1137 2194 +1487 1585 2183 +1733 1862 2167 +1935 2078 2145 +1935 2145 2023 +1994 2299 1865 +2152 2447 1751 +2303 2591 1533 +2448 2731 738 +2590 2870 0 +2729 3006 0 +2867 3142 0 +3002 3276 0 +3137 3410 0 +3272 3544 0 +3405 3677 0 +3539 3810 0 +3672 3943 0 +3804 4075 0 +3937 4095 0 +1562 0 2226 +1565 0 2226 +1570 0 2225 +1576 0 2225 +1584 0 2224 +1595 0 2223 +1608 0 2221 +1626 0 2220 +1649 0 2217 +1677 0 2214 +1713 0 2209 +1757 217 2203 +1809 1136 2194 +1871 1487 2183 +1943 1733 2167 +2023 1935 2145 +2113 2113 2113 +2210 2277 2067 +2315 2431 1997 +2425 2579 1883 +2540 2723 1664 +2659 2863 870 +2781 3002 0 +2906 3138 0 +3031 3274 0 +3159 3408 0 +3288 3543 0 +3418 3676 0 +3548 3809 0 +3679 3942 0 +3810 4075 0 +3941 4095 0 +2078 0 2358 +2079 0 2358 +2080 0 2358 +2082 0 2357 +2085 0 2357 +2088 0 2356 +2093 0 2355 +2099 0 2353 +2107 0 2352 +2118 0 2349 +2132 0 2346 +2150 0 2341 +2173 345 2335 +2202 1269 2326 +2237 1619 2315 +2281 1865 2299 +2277 2067 2210 +2277 2155 2067 +2431 2414 1997 +2533 2579 1883 +2626 2723 1664 +2726 2863 870 +2833 3002 0 +2946 3138 0 +3062 3274 0 +3183 3408 0 +3306 3543 0 +3431 3676 0 +3558 3809 0 +3686 3942 0 +3815 4075 0 +3945 4095 0 +2371 0 2491 +2372 0 2491 +2373 0 2490 +2374 0 2490 +2375 0 2489 +2377 0 2489 +2379 0 2488 +2383 0 2487 +2387 0 2486 +2393 0 2484 +2401 0 2481 +2411 0 2478 +2423 0 2473 +2440 477 2467 +2459 1401 2455 +2447 1751 2401 +2431 1997 2315 +2431 1997 2126 +2431 2207 1997 +2579 2502 1883 +2719 2723 1664 +2803 2863 870 +2895 3002 0 +2995 3138 0 +3100 3274 0 +3212 3408 0 +3329 3543 0 +3448 3676 0 +3571 3809 0 +3696 3942 0 +3823 4075 0 +3951 4095 0 +2595 0 2623 +2595 0 2623 +2596 0 2623 +2596 0 2622 +2597 0 2622 +2598 0 2621 +2600 0 2621 +2602 0 2620 +2604 0 2619 +2608 0 2618 +2613 0 2616 +2613 0 2607 +2610 0 2592 +2605 0 2570 +2599 611 2538 +2591 1533 2493 +2579 1883 2425 +2579 1883 2284 +2579 1883 1981 +2579 2267 1883 +2723 2598 1664 +2863 2837 870 +2966 3002 0 +3053 3138 0 +3147 3274 0 +3249 3408 0 +3357 3543 0 +3471 3676 0 +3588 3809 0 +3709 3942 0 +3833 4075 0 +3959 4095 0 +2755 0 2723 +2755 0 2723 +2755 0 2722 +2755 0 2721 +2755 0 2720 +2754 0 2718 +2754 0 2716 +2753 0 2713 +2752 0 2710 +2751 0 2704 +2750 0 2697 +2748 0 2687 +2746 0 2674 +2742 0 2656 +2738 0 2631 +2731 738 2594 +2723 1664 2540 +2723 1664 2435 +2723 1664 2240 +2723 1664 1667 +2723 2338 1664 +2863 2701 870 +3002 2952 0 +3120 3138 0 +3203 3274 0 +3294 3408 0 +3393 3543 0 +3499 3676 0 +3610 3809 0 +3726 3942 0 +3846 4075 0 +3968 4095 0 +2887 0 2806 +2887 0 2805 +2887 0 2805 +2887 0 2804 +2887 0 2803 +2887 0 2802 +2886 0 2800 +2886 0 2798 +2885 0 2795 +2885 0 2790 +2883 0 2784 +2882 0 2777 +2880 0 2766 +2878 0 2751 +2874 0 2730 +2870 0 2701 +2863 870 2659 +2863 870 2580 +2863 870 2447 +2863 870 2173 +2863 1498 870 +2863 2417 870 +3002 2810 0 +3138 3071 0 +3268 3274 0 +3348 3408 0 +3437 3543 0 +3534 3676 0 +3638 3809 0 +3748 3942 0 +3862 4075 0 +3981 4095 0 +3019 0 2897 +3019 0 2897 +3019 0 2896 +3019 0 2896 +3019 0 2895 +3019 0 2894 +3018 0 2892 +3018 0 2890 +3018 0 2888 +3017 0 2885 +3016 0 2880 +3015 0 2873 +3014 0 2865 +3012 0 2853 +3010 0 2836 +3006 0 2813 +3002 0 2781 +3002 0 2722 +3002 0 2628 +3002 0 2463 +3002 0 2062 +3002 1109 0 +3002 2505 0 +3138 2925 0 +3274 3193 0 +3408 3406 0 +3490 3543 0 +3577 3676 0 +3672 3809 0 +3775 3942 0 +3884 4075 0 +3998 4095 0 +3152 0 2996 +3152 0 2996 +3152 0 2996 +3151 0 2995 +3151 0 2995 +3151 0 2994 +3151 0 2993 +3151 0 2991 +3151 0 2989 +3150 0 2986 +3150 0 2982 +3149 0 2977 +3148 0 2970 +3146 0 2961 +3144 0 2948 +3142 0 2931 +3138 0 2906 +3138 0 2861 +3138 0 2795 +3138 0 2687 +3138 0 2484 +3138 0 1857 +3138 0 0 +3138 2602 0 +3274 3042 0 +3408 3317 0 +3543 3533 0 +3629 3676 0 +3715 3809 0 +3809 3942 0 +3911 4075 0 +4019 4095 0 +3284 0 3102 +3283 0 3102 +3283 0 3101 +3283 0 3101 +3283 0 3101 +3283 0 3100 +3283 0 3099 +3283 0 3098 +3283 0 3096 +3282 0 3094 +3282 0 3091 +3281 0 3087 +3280 0 3082 +3280 0 3074 +3278 0 3064 +3276 0 3050 +3274 0 3031 +3274 0 2998 +3274 0 2950 +3274 0 2876 +3274 0 2753 +3274 0 2510 +3274 0 1202 +3274 0 0 +3274 2706 0 +3408 3164 0 +3543 3444 0 +3676 3662 0 +3766 3809 0 +3851 3942 0 +3945 4075 0 +4046 4095 0 +3416 0 3213 +3416 0 3213 +3416 0 3213 +3416 0 3213 +3416 0 3212 +3416 0 3212 +3415 0 3211 +3415 0 3210 +3415 0 3209 +3415 0 3207 +3414 0 3205 +3414 0 3202 +3414 0 3198 +3413 0 3192 +3412 0 3184 +3410 0 3174 +3408 0 3159 +3408 0 3134 +3408 0 3099 +3408 0 3047 +3408 0 2966 +3408 0 2830 +3408 0 2545 +3408 0 0 +3408 0 0 +3408 2815 0 +3543 3288 0 +3676 3572 0 +3809 3791 0 +3902 3942 0 +3986 4075 0 +4080 4095 0 +3548 0 3329 +3548 0 3329 +3548 0 3329 +3548 0 3329 +3548 0 3329 +3548 0 3328 +3548 0 3328 +3548 0 3327 +3548 0 3326 +3547 0 3325 +3547 0 3323 +3547 0 3320 +3546 0 3317 +3546 0 3313 +3545 0 3307 +3544 0 3299 +3543 0 3288 +3543 0 3270 +3543 0 3243 +3543 0 3206 +3543 0 3151 +3543 0 3065 +3543 0 2917 +3543 0 2585 +3543 0 0 +3543 0 0 +3543 2929 0 +3676 3414 0 +3809 3700 0 +3942 3921 0 +4037 4075 0 +4095 4095 0 +3680 0 3449 +3680 0 3449 +3680 0 3449 +3680 0 3449 +3680 0 3448 +3680 0 3448 +3680 0 3448 +3680 0 3447 +3680 0 3446 +3680 0 3445 +3679 0 3444 +3679 0 3442 +3679 0 3440 +3678 0 3436 +3678 0 3432 +3677 0 3426 +3676 0 3418 +3676 0 3404 +3676 0 3385 +3676 0 3358 +3676 0 3319 +3676 0 3261 +3676 0 3170 +3676 0 3010 +3676 0 2636 +3676 0 0 +3676 0 0 +3676 3048 0 +3809 3542 0 +3942 3830 0 +4075 4051 0 +4095 4095 0 +3812 0 3572 +3812 0 3572 +3812 0 3572 +3812 0 3571 +3812 0 3571 +3812 0 3571 +3812 0 3571 +3812 0 3570 +3812 0 3570 +3812 0 3569 +3812 0 3568 +3812 0 3566 +3811 0 3564 +3811 0 3562 +3810 0 3559 +3810 0 3554 +3809 0 3548 +3809 0 3537 +3809 0 3523 +3809 0 3503 +3809 0 3475 +3809 0 3435 +3809 0 3376 +3809 0 3281 +3809 0 3112 +3809 0 2694 +3809 0 0 +3809 0 0 +3809 3169 0 +3942 3670 0 +4075 3960 0 +4095 4095 0 +3944 0 3696 +3944 0 3696 +3944 0 3696 +3944 0 3696 +3944 0 3696 +3944 0 3696 +3944 0 3696 +3944 0 3695 +3944 0 3695 +3944 0 3694 +3944 0 3694 +3944 0 3692 +3944 0 3691 +3943 0 3689 +3943 0 3687 +3943 0 3683 +3942 0 3679 +3942 0 3671 +3942 0 3660 +3942 0 3646 +3942 0 3626 +3942 0 3597 +3942 0 3556 +3942 0 3494 +3942 0 3396 +3942 0 3220 +3942 0 2762 +3942 0 0 +3942 0 0 +3942 3293 0 +4075 3799 0 +4095 4091 0 +4076 0 3823 +4076 0 3823 +4076 0 3823 +4076 0 3823 +4076 0 3823 +4076 0 3822 +4076 0 3822 +4076 0 3822 +4076 0 3822 +4076 0 3821 +4076 0 3821 +4076 0 3820 +4076 0 3819 +4076 0 3817 +4075 0 3816 +4075 0 3813 +4075 0 3810 +4075 0 3803 +4075 0 3796 +4075 0 3785 +4075 0 3770 +4075 0 3750 +4075 0 3721 +4075 0 3679 +4075 0 3616 +4075 0 3515 +4075 0 3333 +4075 0 2839 +4075 0 0 +4075 0 0 +4075 3419 0 +4095 3930 0 +4095 0 3951 +4095 0 3951 +4095 0 3951 +4095 0 3951 +4095 0 3951 +4095 0 3951 +4095 0 3951 +4095 0 3950 +4095 0 3950 +4095 0 3950 +4095 0 3950 +4095 0 3949 +4095 0 3948 +4095 0 3947 +4095 0 3945 +4095 0 3944 +4095 0 3941 +4095 0 3937 +4095 0 3931 +4095 0 3923 +4095 0 3912 +4095 0 3897 +4095 0 3876 +4095 0 3847 +4095 0 3804 +4095 0 3741 +4095 0 3638 +4095 0 3450 +4095 0 2927 +4095 0 0 +4095 0 0 +4095 3547 0 +0 2090 2358 +0 2093 2358 +0 2096 2358 +0 2100 2358 +0 2106 2358 +0 2113 2358 +0 2123 2358 +0 2136 2358 +0 2152 2358 +0 2173 2358 +0 2200 2358 +0 2233 2358 +0 2275 2358 +0 2325 2358 +0 2358 2332 +0 2358 2239 +0 2358 2078 +0 2358 1692 +0 2491 0 +0 2623 0 +1353 2755 0 +2091 2887 0 +2422 3019 0 +2662 3152 0 +2860 3284 0 +3036 3416 0 +3198 3548 0 +3352 3680 0 +3499 3812 0 +3643 3944 0 +3783 4076 0 +3921 4095 0 +0 2088 2358 +0 2091 2358 +0 2094 2358 +0 2098 2358 +0 2104 2358 +0 2111 2358 +0 2121 2358 +0 2134 2358 +0 2150 2358 +0 2171 2358 +0 2199 2358 +0 2232 2358 +0 2273 2358 +0 2324 2358 +0 2358 2332 +0 2358 2240 +0 2358 2079 +0 2358 1694 +0 2491 0 +0 2623 0 +1367 2755 0 +2094 2887 0 +2424 3019 0 +2663 3152 0 +2860 3283 0 +3036 3416 0 +3199 3548 0 +3352 3680 0 +3499 3812 0 +3643 3944 0 +3783 4076 0 +3921 4095 0 +0 2085 2358 +0 2087 2358 +0 2091 2358 +0 2096 2358 +0 2101 2358 +0 2109 2358 +0 2119 2358 +0 2132 2358 +0 2148 2358 +0 2169 2358 +0 2196 2358 +0 2230 2358 +0 2271 2358 +0 2322 2358 +0 2358 2333 +0 2358 2241 +0 2358 2080 +0 2358 1698 +0 2490 0 +0 2623 0 +1386 2755 0 +2098 2887 0 +2426 3019 0 +2664 3152 0 +2861 3283 0 +3037 3416 0 +3199 3548 0 +3353 3680 0 +3500 3812 0 +3643 3944 0 +3783 4076 0 +3921 4095 0 +0 2080 2358 +0 2083 2358 +0 2087 2358 +0 2092 2357 +0 2098 2357 +0 2105 2357 +0 2115 2357 +0 2128 2357 +0 2145 2357 +0 2166 2357 +0 2193 2357 +0 2228 2357 +0 2269 2357 +0 2320 2357 +0 2357 2334 +0 2357 2243 +0 2357 2082 +0 2357 1702 +0 2490 0 +0 2622 0 +1409 2755 0 +2103 2887 0 +2428 3019 0 +2665 3151 0 +2862 3283 0 +3038 3416 0 +3200 3548 0 +3353 3680 0 +3500 3812 0 +3643 3944 0 +3783 4076 0 +3921 4095 0 +0 2074 2358 +0 2077 2358 +0 2081 2358 +0 2086 2357 +0 2093 2357 +0 2101 2357 +0 2111 2357 +0 2124 2357 +0 2141 2357 +0 2162 2357 +0 2190 2357 +0 2224 2357 +0 2266 2357 +0 2317 2357 +0 2357 2335 +0 2357 2245 +0 2357 2085 +0 2357 1708 +0 2489 0 +0 2622 0 +1439 2755 0 +2110 2887 0 +2431 3019 0 +2667 3151 0 +2863 3283 0 +3038 3416 0 +3200 3548 0 +3353 3680 0 +3500 3812 0 +3643 3944 0 +3783 4076 0 +3921 4095 0 +0 2066 2358 +0 2069 2358 +0 2073 2358 +0 2078 2357 +0 2086 2357 +0 2095 2356 +0 2105 2356 +0 2118 2356 +0 2135 2356 +0 2157 2356 +0 2185 2356 +0 2219 2356 +0 2262 2356 +0 2313 2356 +0 2356 2338 +0 2356 2247 +0 2356 2088 +0 2356 1716 +0 2489 0 +0 2621 0 +1476 2754 0 +2118 2887 0 +2435 3019 0 +2670 3151 0 +2865 3283 0 +3039 3416 0 +3201 3548 0 +3354 3680 0 +3501 3812 0 +3644 3944 0 +3784 4076 0 +3922 4095 0 +0 2055 2358 +0 2058 2358 +0 2062 2358 +0 2068 2357 +0 2075 2357 +0 2084 2356 +0 2096 2355 +0 2110 2355 +0 2127 2355 +0 2150 2355 +0 2178 2355 +0 2213 2355 +0 2256 2355 +0 2308 2355 +0 2355 2340 +0 2355 2251 +0 2355 2093 +0 2355 1727 +0 2488 0 +0 2621 0 +1521 2754 0 +2129 2886 0 +2441 3018 0 +2673 3151 0 +2867 3283 0 +3041 3415 0 +3202 3548 0 +3354 3680 0 +3501 3812 0 +3644 3944 0 +3784 4076 0 +3922 4095 0 +0 2040 2358 +0 2043 2358 +0 2047 2358 +0 2053 2357 +0 2060 2357 +0 2070 2356 +0 2083 2355 +0 2099 2353 +0 2117 2353 +0 2140 2353 +0 2168 2353 +0 2204 2353 +0 2248 2353 +0 2301 2353 +0 2353 2344 +0 2353 2255 +0 2353 2099 +0 2353 1740 +0 2487 0 +0 2620 0 +1575 2753 0 +2144 2886 0 +2449 3018 0 +2678 3151 0 +2870 3283 0 +3043 3415 0 +3203 3548 0 +3356 3680 0 +3502 3812 0 +3645 3944 0 +3784 4076 0 +3922 4095 0 +0 2019 2358 +0 2022 2358 +0 2027 2358 +0 2032 2357 +0 2040 2357 +0 2050 2356 +0 2063 2355 +0 2081 2353 +0 2102 2352 +0 2126 2352 +0 2155 2352 +0 2192 2352 +0 2237 2352 +0 2291 2352 +0 2352 2349 +0 2352 2261 +0 2352 2107 +0 2352 1758 +0 2486 0 +0 2619 0 +1638 2752 0 +2163 2885 0 +2459 3018 0 +2684 3151 0 +2874 3283 0 +3046 3415 0 +3205 3548 0 +3357 3680 0 +3503 3812 0 +3645 3944 0 +3785 4076 0 +3923 4095 0 +0 1989 2358 +0 1993 2358 +0 1997 2358 +0 2004 2357 +0 2012 2357 +0 2022 2356 +0 2037 2355 +0 2054 2353 +0 2078 2352 +0 2107 2349 +0 2138 2349 +0 2176 2349 +0 2223 2349 +0 2278 2349 +0 2343 2349 +0 2349 2268 +0 2349 2118 +0 2349 1781 +0 2484 0 +0 2618 0 +1711 2751 0 +2188 2885 0 +2471 3017 0 +2691 3150 0 +2879 3282 0 +3049 3415 0 +3208 3547 0 +3359 3680 0 +3504 3812 0 +3646 3944 0 +3785 4076 0 +3923 4095 0 +0 1946 2358 +0 1950 2358 +0 1955 2358 +0 1962 2357 +0 1970 2357 +0 1982 2356 +0 1998 2355 +0 2017 2353 +0 2042 2352 +0 2074 2349 +0 2113 2346 +0 2153 2346 +0 2202 2346 +0 2260 2346 +0 2328 2346 +0 2346 2278 +0 2346 2132 +0 2346 1809 +0 2481 0 +0 2616 0 +1794 2750 0 +2218 2883 0 +2488 3016 0 +2702 3150 0 +2886 3282 0 +3054 3414 0 +3211 3547 0 +3361 3679 0 +3506 3812 0 +3648 3944 0 +3787 4076 0 +3924 4095 0 +0 1880 2358 +0 1885 2358 +0 1891 2358 +0 1899 2357 +0 1909 2357 +0 1922 2356 +0 1940 2355 +0 1962 2353 +0 1990 2352 +0 2025 2349 +0 2069 2346 +0 2120 2341 +0 2173 2341 +0 2234 2341 +0 2305 2341 +0 2341 2291 +0 2341 2150 +0 2341 1845 +0 2478 0 +547 2613 0 +1885 2748 0 +2256 2882 0 +2510 3015 0 +2715 3149 0 +2895 3281 0 +3060 3414 0 +3216 3547 0 +3364 3679 0 +3508 3812 0 +3649 3944 0 +3787 4076 0 +3925 4095 0 +0 1775 2358 +0 1781 2358 +0 1788 2358 +0 1798 2357 +0 1811 2357 +0 1828 2356 +0 1849 2355 +0 1876 2353 +0 1910 2352 +0 1951 2349 +0 2002 2346 +0 2061 2341 +345 2131 2335 +345 2198 2335 +345 2274 2335 +345 2335 2308 +345 2335 2173 +345 2335 1889 +0 2473 557 +1330 2610 0 +1983 2746 0 +2302 2880 0 +2536 3014 0 +2733 3148 0 +2907 3280 0 +3069 3414 0 +3221 3546 0 +3368 3679 0 +3511 3811 0 +3651 3944 0 +3789 4076 0 +3926 4095 0 +0 1580 2358 +0 1589 2358 +0 1600 2358 +0 1615 2357 +0 1634 2357 +0 1659 2356 +0 1689 2355 +0 1727 2353 +0 1773 2352 +0 1829 2349 +0 1894 2346 +0 1968 2341 +345 2052 2335 +1269 2144 2326 +1269 2229 2326 +1269 2323 2326 +1269 2326 2202 +1269 2326 1941 +477 2467 1099 +1667 2605 0 +2089 2742 0 +2358 2878 0 +2570 3012 0 +2755 3146 0 +2922 3280 0 +3079 3413 0 +3229 3546 0 +3374 3678 0 +3516 3811 0 +3655 3943 0 +3792 4076 0 +3927 4095 0 +0 1009 2358 +0 1039 2358 +0 1076 2358 +0 1122 2357 +0 1176 2357 +0 1240 2356 +0 1313 2355 +0 1396 2353 +0 1487 2352 +0 1586 2349 +0 1692 2346 +0 1803 2341 +345 1919 2335 +1269 2038 2326 +1619 2161 2315 +1619 2268 2315 +1619 2315 2237 +1619 2315 2003 +1403 2459 1401 +1908 2599 611 +2200 2738 0 +2423 2874 0 +2612 3010 0 +2783 3144 0 +2942 3278 0 +3093 3412 0 +3239 3545 0 +3381 3678 0 +3521 3810 0 +3659 3943 0 +3795 4075 0 +3930 4095 0 +0 0 2358 +0 0 2358 +0 0 2358 +0 0 2357 +0 0 2357 +0 0 2356 +0 0 2355 +0 0 2353 +0 0 2352 +0 275 2349 +0 1064 2346 +0 1403 2341 +345 1644 2335 +1269 1843 2326 +1619 2020 2315 +1865 2183 2299 +1865 2299 2281 +1865 2299 2075 +1850 2447 1751 +2108 2591 1533 +2315 2731 738 +2497 2870 0 +2662 3006 0 +2818 3142 0 +2967 3276 0 +3111 3410 0 +3253 3544 0 +3391 3677 0 +3528 3810 0 +3664 3943 0 +3798 4075 0 +3933 4095 0 +0 0 2358 +0 0 2358 +0 0 2358 +0 0 2357 +0 0 2357 +0 0 2356 +0 0 2355 +0 0 2353 +0 0 2352 +0 0 2349 +0 0 2346 +437 0 2341 +970 345 2335 +1269 1270 2326 +1619 1718 2315 +1865 1994 2299 +2067 2210 2277 +2067 2277 2155 +2126 2431 1997 +2284 2579 1883 +2435 2723 1664 +2580 2863 870 +2722 3002 0 +2861 3138 0 +2998 3274 0 +3134 3408 0 +3270 3543 0 +3404 3676 0 +3537 3809 0 +3671 3942 0 +3803 4075 0 +3937 4095 0 +1692 0 2358 +1694 0 2358 +1698 0 2358 +1702 0 2357 +1708 0 2357 +1716 0 2356 +1727 0 2355 +1740 0 2353 +1758 0 2352 +1781 0 2349 +1809 0 2346 +1845 0 2341 +1889 345 2335 +1941 1269 2326 +2003 1619 2315 +2075 1865 2299 +2155 2067 2277 +2245 2245 2245 +2343 2409 2199 +2447 2563 2129 +2557 2711 2015 +2672 2855 1796 +2791 2995 1006 +2913 3134 0 +3037 3270 0 +3164 3406 0 +3291 3541 0 +3420 3675 0 +3550 3808 0 +3680 3941 0 +3810 4074 0 +3942 4095 0 +2209 0 2491 +2210 0 2491 +2211 0 2490 +2213 0 2490 +2215 0 2489 +2218 0 2489 +2221 0 2488 +2226 0 2487 +2232 0 2486 +2240 0 2484 +2251 0 2481 +2264 0 2478 +2282 0 2473 +2305 477 2467 +2334 1401 2459 +2370 1751 2447 +2414 1997 2431 +2409 2199 2343 +2409 2288 2199 +2563 2545 2129 +2665 2711 2015 +2758 2855 1796 +2858 2995 1006 +2965 3134 0 +3078 3270 0 +3194 3406 0 +3315 3541 0 +3438 3675 0 +3563 3808 0 +3690 3941 0 +3818 4074 0 +3947 4095 0 +2503 0 2623 +2503 0 2623 +2504 0 2623 +2505 0 2622 +2506 0 2622 +2507 0 2621 +2509 0 2621 +2511 0 2620 +2515 0 2619 +2519 0 2618 +2525 0 2616 +2533 0 2613 +2543 0 2610 +2556 0 2605 +2572 611 2599 +2591 1533 2587 +2579 1883 2533 +2563 2129 2447 +2563 2129 2258 +2563 2339 2129 +2711 2634 2015 +2852 2855 1796 +2935 2995 1006 +3027 3134 0 +3126 3270 0 +3233 3406 0 +3344 3541 0 +3461 3675 0 +3581 3808 0 +3703 3941 0 +3828 4074 0 +3955 4095 0 +2727 0 2755 +2727 0 2755 +2728 0 2755 +2728 0 2755 +2729 0 2755 +2730 0 2754 +2731 0 2754 +2732 0 2753 +2734 0 2752 +2737 0 2751 +2741 0 2750 +2745 0 2748 +2746 0 2740 +2742 0 2724 +2738 0 2702 +2731 738 2671 +2723 1664 2626 +2711 2015 2557 +2711 2015 2416 +2711 2015 2114 +2711 2400 2015 +2855 2730 1796 +2995 2968 1006 +3098 3134 0 +3184 3270 0 +3279 3406 0 +3381 3541 0 +3490 3675 0 +3603 3808 0 +3720 3941 0 +3841 4074 0 +3965 4095 0 +2887 0 2856 +2887 0 2855 +2887 0 2855 +2887 0 2854 +2887 0 2853 +2887 0 2852 +2886 0 2850 +2886 0 2848 +2885 0 2845 +2885 0 2842 +2883 0 2836 +2882 0 2829 +2880 0 2820 +2878 0 2807 +2874 0 2788 +2870 0 2763 +2863 870 2726 +2855 1796 2672 +2855 1796 2567 +2855 1796 2372 +2855 1796 1797 +2855 2470 1796 +2995 2833 1006 +3134 3084 0 +3252 3270 0 +3335 3406 0 +3426 3541 0 +3525 3675 0 +3631 3808 0 +3742 3941 0 +3858 4074 0 +3978 4095 0 +3019 0 2938 +3019 0 2938 +3019 0 2938 +3019 0 2937 +3019 0 2936 +3019 0 2935 +3018 0 2934 +3018 0 2932 +3018 0 2930 +3017 0 2927 +3016 0 2922 +3015 0 2916 +3014 0 2908 +3012 0 2898 +3010 0 2883 +3006 0 2862 +3002 0 2833 +2995 1006 2791 +2995 1006 2712 +2995 1006 2579 +2995 1006 2303 +2995 1635 1006 +2995 2549 1006 +3134 2943 0 +3270 3203 0 +3400 3406 0 +3480 3541 0 +3569 3675 0 +3666 3808 0 +3770 3941 0 +3880 4074 0 +3994 4095 0 +3152 0 3030 +3152 0 3029 +3152 0 3029 +3151 0 3029 +3151 0 3028 +3151 0 3027 +3151 0 3026 +3151 0 3025 +3151 0 3023 +3150 0 3020 +3150 0 3017 +3149 0 3012 +3148 0 3005 +3146 0 2997 +3144 0 2985 +3142 0 2969 +3138 0 2946 +3134 0 2913 +3134 0 2854 +3134 0 2761 +3134 0 2596 +3134 0 2195 +3134 1211 0 +3134 2638 0 +3270 3056 0 +3406 3325 0 +3541 3538 0 +3622 3675 0 +3709 3808 0 +3805 3941 0 +3907 4074 0 +4016 4095 0 +3284 0 3128 +3283 0 3128 +3283 0 3128 +3283 0 3128 +3283 0 3127 +3283 0 3127 +3283 0 3126 +3283 0 3125 +3283 0 3123 +3282 0 3121 +3282 0 3118 +3281 0 3114 +3280 0 3109 +3280 0 3102 +3278 0 3093 +3276 0 3080 +3274 0 3062 +3270 0 3037 +3270 0 2993 +3270 0 2926 +3270 0 2818 +3270 0 2616 +3270 0 1990 +3270 0 0 +3270 2734 0 +3406 3175 0 +3541 3450 0 +3675 3665 0 +3761 3808 0 +3847 3941 0 +3941 4074 0 +4043 4095 0 +3416 0 3234 +3416 0 3234 +3416 0 3234 +3416 0 3234 +3416 0 3233 +3416 0 3233 +3415 0 3232 +3415 0 3231 +3415 0 3230 +3415 0 3228 +3414 0 3226 +3414 0 3223 +3414 0 3219 +3413 0 3214 +3412 0 3206 +3410 0 3196 +3408 0 3183 +3406 0 3164 +3406 0 3131 +3406 0 3082 +3406 0 3008 +3406 0 2886 +3406 0 2643 +3406 0 1325 +3406 0 0 +3406 2838 0 +3541 3296 0 +3675 3576 0 +3808 3794 0 +3898 3941 0 +3983 4074 0 +4077 4095 0 +3548 0 3346 +3548 0 3346 +3548 0 3346 +3548 0 3345 +3548 0 3345 +3548 0 3344 +3548 0 3344 +3548 0 3343 +3548 0 3342 +3547 0 3341 +3547 0 3339 +3547 0 3337 +3546 0 3334 +3546 0 3330 +3545 0 3324 +3544 0 3316 +3543 0 3306 +3541 0 3291 +3541 0 3267 +3541 0 3231 +3541 0 3179 +3541 0 3099 +3541 0 2963 +3541 0 2676 +3541 0 0 +3541 0 0 +3541 2947 0 +3675 3420 0 +3808 3704 0 +3941 3923 0 +4034 4074 0 +4095 4095 0 +3680 0 3462 +3680 0 3462 +3680 0 3462 +3680 0 3461 +3680 0 3461 +3680 0 3461 +3680 0 3460 +3680 0 3460 +3680 0 3459 +3680 0 3458 +3679 0 3457 +3679 0 3455 +3679 0 3453 +3678 0 3449 +3678 0 3445 +3677 0 3439 +3676 0 3431 +3675 0 3420 +3675 0 3402 +3675 0 3376 +3675 0 3338 +3675 0 3283 +3675 0 3197 +3675 0 3048 +3675 0 2718 +3675 0 0 +3675 0 0 +3675 3061 0 +3808 3546 0 +3941 3832 0 +4074 4053 0 +4095 4095 0 +3812 0 3581 +3812 0 3581 +3812 0 3581 +3812 0 3581 +3812 0 3581 +3812 0 3581 +3812 0 3580 +3812 0 3580 +3812 0 3579 +3812 0 3579 +3812 0 3577 +3812 0 3576 +3811 0 3574 +3811 0 3572 +3810 0 3569 +3810 0 3564 +3809 0 3558 +3808 0 3550 +3808 0 3536 +3808 0 3517 +3808 0 3490 +3808 0 3451 +3808 0 3393 +3808 0 3302 +3808 0 3143 +3808 0 2767 +3808 0 0 +3808 0 0 +3808 3180 0 +3941 3674 0 +4074 3962 0 +4095 4095 0 +3944 0 3704 +3944 0 3704 +3944 0 3704 +3944 0 3703 +3944 0 3703 +3944 0 3703 +3944 0 3703 +3944 0 3703 +3944 0 3702 +3944 0 3702 +3944 0 3701 +3944 0 3700 +3944 0 3699 +3943 0 3697 +3943 0 3694 +3943 0 3691 +3942 0 3686 +3941 0 3680 +3941 0 3669 +3941 0 3655 +3941 0 3635 +3941 0 3608 +3941 0 3568 +3941 0 3507 +3941 0 3413 +3941 0 3244 +3941 0 2826 +3941 0 0 +3941 0 0 +3941 3302 0 +4074 3802 0 +4095 4092 0 +4076 0 3828 +4076 0 3828 +4076 0 3828 +4076 0 3828 +4076 0 3828 +4076 0 3828 +4076 0 3828 +4076 0 3828 +4076 0 3827 +4076 0 3827 +4076 0 3826 +4076 0 3826 +4076 0 3824 +4076 0 3823 +4075 0 3821 +4075 0 3818 +4075 0 3815 +4074 0 3810 +4074 0 3803 +4074 0 3792 +4074 0 3777 +4074 0 3757 +4074 0 3729 +4074 0 3688 +4074 0 3626 +4074 0 3528 +4074 0 3351 +4074 0 2893 +4074 0 0 +4074 0 0 +4074 3426 0 +4095 3932 0 +4095 0 3955 +4095 0 3955 +4095 0 3955 +4095 0 3955 +4095 0 3955 +4095 0 3955 +4095 0 3955 +4095 0 3955 +4095 0 3954 +4095 0 3954 +4095 0 3954 +4095 0 3953 +4095 0 3952 +4095 0 3951 +4095 0 3950 +4095 0 3948 +4095 0 3945 +4095 0 3942 +4095 0 3936 +4095 0 3928 +4095 0 3917 +4095 0 3903 +4095 0 3882 +4095 0 3853 +4095 0 3811 +4095 0 3748 +4095 0 3648 +4095 0 3465 +4095 0 2973 +4095 0 0 +4095 0 0 +4095 3552 0 +0 2222 2491 +0 2224 2491 +0 2226 2491 +0 2230 2491 +0 2234 2491 +0 2239 2491 +0 2247 2491 +0 2256 2491 +0 2269 2491 +0 2285 2491 +0 2306 2491 +0 2333 2491 +0 2367 2491 +0 2408 2491 +0 2458 2491 +0 2491 2463 +0 2491 2371 +0 2491 2209 +0 2491 1822 +0 2623 0 +0 2755 0 +1472 2887 0 +2220 3019 0 +2554 3152 0 +2793 3284 0 +2992 3416 0 +3168 3548 0 +3330 3680 0 +3484 3812 0 +3631 3944 0 +3774 4076 0 +3915 4095 0 +0 2220 2491 +0 2223 2491 +0 2225 2491 +0 2228 2491 +0 2233 2491 +0 2238 2491 +0 2245 2491 +0 2255 2491 +0 2268 2491 +0 2284 2491 +0 2305 2491 +0 2332 2491 +0 2366 2491 +0 2407 2491 +0 2457 2491 +0 2491 2464 +0 2491 2372 +0 2491 2210 +0 2491 1824 +0 2623 0 +0 2755 0 +1483 2887 0 +2222 3019 0 +2555 3152 0 +2793 3283 0 +2992 3416 0 +3168 3548 0 +3331 3680 0 +3484 3812 0 +3632 3944 0 +3775 4076 0 +3915 4095 0 +0 2218 2491 +0 2220 2491 +0 2223 2490 +0 2226 2490 +0 2230 2490 +0 2236 2490 +0 2243 2490 +0 2253 2490 +0 2266 2490 +0 2283 2490 +0 2304 2490 +0 2331 2490 +0 2364 2490 +0 2406 2490 +0 2456 2490 +0 2490 2464 +0 2490 2373 +0 2490 2211 +0 2490 1826 +0 2623 0 +0 2755 0 +1497 2887 0 +2225 3019 0 +2556 3152 0 +2794 3283 0 +2992 3416 0 +3168 3548 0 +3331 3680 0 +3484 3812 0 +3632 3944 0 +3775 4076 0 +3915 4095 0 +0 2215 2491 +0 2217 2491 +0 2220 2490 +0 2223 2490 +0 2228 2490 +0 2234 2490 +0 2241 2490 +0 2251 2490 +0 2264 2490 +0 2280 2490 +0 2302 2490 +0 2329 2490 +0 2362 2490 +0 2404 2490 +0 2454 2490 +0 2490 2465 +0 2490 2374 +0 2490 2213 +0 2490 1830 +0 2622 0 +0 2755 0 +1516 2887 0 +2229 3019 0 +2558 3151 0 +2795 3283 0 +2993 3416 0 +3169 3548 0 +3331 3680 0 +3485 3812 0 +3632 3944 0 +3775 4076 0 +3915 4095 0 +0 2210 2491 +0 2212 2491 +0 2215 2490 +0 2219 2490 +0 2224 2489 +0 2230 2489 +0 2238 2489 +0 2247 2489 +0 2260 2489 +0 2277 2489 +0 2298 2489 +0 2326 2489 +0 2360 2489 +0 2401 2489 +0 2452 2489 +0 2489 2466 +0 2489 2375 +0 2489 2215 +0 2489 1834 +0 2622 0 +0 2755 0 +1540 2887 0 +2234 3019 0 +2560 3151 0 +2797 3283 0 +2994 3416 0 +3170 3548 0 +3332 3680 0 +3485 3812 0 +3632 3944 0 +3775 4076 0 +3915 4095 0 +0 2204 2491 +0 2206 2491 +0 2209 2490 +0 2213 2490 +0 2219 2489 +0 2226 2489 +0 2233 2489 +0 2243 2489 +0 2256 2489 +0 2273 2489 +0 2294 2489 +0 2322 2489 +0 2356 2489 +0 2398 2489 +0 2449 2489 +0 2489 2468 +0 2489 2377 +0 2489 2218 +0 2489 1840 +0 2621 0 +0 2754 0 +1569 2887 0 +2241 3019 0 +2564 3151 0 +2799 3283 0 +2996 3416 0 +3171 3548 0 +3332 3680 0 +3485 3812 0 +3632 3944 0 +3775 4076 0 +3916 4095 0 +0 2196 2491 +0 2199 2491 +0 2202 2490 +0 2206 2490 +0 2211 2489 +0 2218 2489 +0 2227 2488 +0 2237 2488 +0 2250 2488 +0 2267 2488 +0 2289 2488 +0 2317 2488 +0 2352 2488 +0 2394 2488 +0 2445 2488 +0 2488 2470 +0 2488 2379 +0 2488 2221 +0 2488 1848 +0 2621 0 +0 2754 0 +1606 2886 0 +2249 3018 0 +2568 3151 0 +2801 3283 0 +2997 3415 0 +3172 3548 0 +3333 3680 0 +3486 3812 0 +3633 3944 0 +3776 4076 0 +3916 4095 0 +0 2185 2491 +0 2187 2491 +0 2190 2490 +0 2195 2490 +0 2200 2489 +0 2207 2489 +0 2217 2488 +0 2229 2487 +0 2242 2487 +0 2260 2487 +0 2282 2487 +0 2310 2487 +0 2345 2487 +0 2388 2487 +0 2440 2487 +0 2487 2473 +0 2487 2383 +0 2487 2226 +0 2487 1859 +0 2620 0 +0 2753 0 +1651 2886 0 +2261 3018 0 +2573 3151 0 +2805 3283 0 +2999 3415 0 +3173 3548 0 +3334 3680 0 +3487 3812 0 +3633 3944 0 +3776 4076 0 +3916 4095 0 +0 2170 2491 +0 2172 2491 +0 2175 2490 +0 2180 2490 +0 2185 2489 +0 2193 2489 +0 2202 2488 +0 2215 2487 +0 2231 2486 +0 2249 2486 +0 2272 2486 +0 2301 2486 +0 2336 2486 +0 2380 2486 +0 2433 2486 +0 2486 2476 +0 2486 2387 +0 2486 2232 +0 2486 1873 +0 2619 0 +0 2752 0 +1706 2885 0 +2276 3018 0 +2581 3151 0 +2809 3283 0 +3002 3415 0 +3175 3548 0 +3336 3680 0 +3488 3812 0 +3634 3944 0 +3777 4076 0 +3917 4095 0 +0 2149 2491 +0 2151 2491 +0 2154 2490 +0 2159 2490 +0 2165 2489 +0 2172 2489 +0 2183 2488 +0 2196 2487 +0 2213 2486 +0 2235 2484 +0 2258 2484 +0 2288 2484 +0 2325 2484 +0 2369 2484 +0 2423 2484 +0 2484 2481 +0 2484 2393 +0 2484 2240 +0 2484 1891 +0 2618 0 +0 2751 0 +1769 2885 0 +2294 3017 0 +2591 3150 0 +2815 3282 0 +3006 3415 0 +3178 3547 0 +3337 3680 0 +3489 3812 0 +3635 3944 0 +3777 4076 0 +3917 4095 0 +0 2119 2491 +0 2121 2491 +0 2125 2490 +0 2129 2490 +0 2136 2489 +0 2144 2489 +0 2155 2488 +0 2169 2487 +0 2187 2486 +0 2210 2484 +0 2239 2481 +0 2270 2481 +0 2308 2481 +0 2355 2481 +0 2410 2481 +0 2475 2481 +0 2481 2401 +0 2481 2251 +0 2481 1913 +0 2616 0 +0 2750 0 +1843 2883 0 +2319 3016 0 +2604 3150 0 +2823 3282 0 +3011 3414 0 +3182 3547 0 +3340 3679 0 +3491 3812 0 +3636 3944 0 +3778 4076 0 +3918 4095 0 +0 2075 2491 +0 2078 2491 +0 2082 2490 +0 2087 2490 +0 2094 2489 +0 2103 2489 +0 2115 2488 +0 2130 2487 +0 2149 2486 +0 2174 2484 +0 2206 2481 +0 2245 2478 +0 2285 2478 +0 2334 2478 +0 2392 2478 +0 2460 2478 +0 2478 2411 +0 2478 2264 +0 2478 1941 +0 2613 0 +0 2748 0 +1925 2882 0 +2350 3015 0 +2620 3149 0 +2833 3281 0 +3018 3414 0 +3186 3547 0 +3343 3679 0 +3493 3812 0 +3638 3944 0 +3780 4076 0 +3919 4095 0 +0 2009 2491 +0 2013 2491 +0 2017 2490 +0 2023 2490 +0 2031 2489 +0 2041 2489 +0 2055 2488 +0 2072 2487 +0 2094 2486 +0 2122 2484 +0 2158 2481 +0 2201 2478 +0 2253 2473 +0 2305 2473 +0 2366 2473 +0 2438 2473 +0 2473 2423 +0 2473 2282 +0 2473 1977 +0 2610 0 +678 2746 0 +2016 2880 0 +2388 3014 0 +2642 3148 0 +2847 3280 0 +3027 3414 0 +3192 3546 0 +3348 3679 0 +3496 3811 0 +3640 3944 0 +3781 4076 0 +3920 4095 0 +0 1903 2491 +0 1907 2491 +0 1913 2490 +0 1920 2490 +0 1930 2489 +0 1943 2489 +0 1960 2488 +0 1981 2487 +0 2008 2486 +0 2042 2484 +0 2084 2481 +0 2134 2478 +0 2194 2473 +477 2263 2467 +477 2330 2467 +477 2407 2467 +477 2467 2440 +477 2467 2305 +477 2467 2021 +0 2605 705 +1463 2742 0 +2115 2878 0 +2434 3012 0 +2669 3146 0 +2865 3280 0 +3039 3413 0 +3201 3546 0 +3354 3678 0 +3501 3811 0 +3644 3943 0 +3784 4076 0 +3922 4095 0 +0 1706 2491 +0 1713 2491 +0 1722 2490 +0 1733 2490 +0 1748 2489 +0 1767 2489 +0 1791 2488 +0 1822 2487 +0 1859 2486 +0 1906 2484 +0 1961 2481 +0 2026 2478 +0 2100 2473 +477 2184 2467 +1401 2276 2459 +1401 2362 2459 +1401 2455 2459 +1401 2459 2334 +1401 2459 2073 +611 2599 1236 +1799 2738 0 +2220 2874 0 +2489 3010 0 +2703 3144 0 +2886 3278 0 +3055 3412 0 +3211 3545 0 +3361 3678 0 +3506 3810 0 +3648 3943 0 +3787 4075 0 +3924 4095 0 +0 1120 2491 +0 1143 2491 +0 1173 2490 +0 1210 2490 +0 1255 2489 +0 1310 2489 +0 1373 2488 +0 1446 2487 +0 1529 2486 +0 1620 2484 +0 1719 2481 +0 1824 2478 +0 1935 2473 +477 2051 2467 +1401 2171 2459 +1751 2293 2447 +1751 2401 2447 +1751 2447 2370 +1751 2447 2135 +1533 2591 1533 +2040 2731 738 +2332 2870 0 +2554 3006 0 +2744 3142 0 +2915 3276 0 +3074 3410 0 +3225 3544 0 +3371 3677 0 +3514 3810 0 +3653 3943 0 +3790 4075 0 +3927 4095 0 +0 0 2491 +0 0 2491 +0 0 2490 +0 0 2490 +0 0 2489 +0 0 2489 +0 0 2488 +0 0 2487 +0 0 2486 +0 0 2484 +0 415 2481 +0 1199 2478 +0 1535 2473 +477 1776 2467 +1401 1976 2459 +1751 2152 2447 +1997 2315 2431 +1997 2431 2414 +1997 2431 2207 +1981 2579 1883 +2240 2723 1664 +2447 2863 870 +2628 3002 0 +2795 3138 0 +2950 3274 0 +3099 3408 0 +3243 3543 0 +3385 3676 0 +3523 3809 0 +3660 3942 0 +3796 4075 0 +3931 4095 0 +0 0 2491 +0 0 2491 +0 0 2490 +0 0 2490 +0 0 2489 +0 0 2489 +0 0 2488 +0 0 2487 +0 0 2486 +0 0 2484 +0 0 2481 +0 0 2478 +557 0 2473 +1099 477 2467 +1401 1403 2459 +1751 1850 2447 +1997 2126 2431 +2199 2343 2409 +2199 2409 2288 +2258 2563 2129 +2416 2711 2015 +2567 2855 1796 +2712 2995 1006 +2854 3134 0 +2993 3270 0 +3131 3406 0 +3267 3541 0 +3402 3675 0 +3536 3808 0 +3669 3941 0 +3803 4074 0 +3936 4095 0 +1822 0 2491 +1824 0 2491 +1826 0 2490 +1830 0 2490 +1834 0 2489 +1840 0 2489 +1848 0 2488 +1859 0 2487 +1873 0 2486 +1891 0 2484 +1913 0 2481 +1941 0 2478 +1977 0 2473 +2021 477 2467 +2073 1401 2459 +2135 1751 2447 +2207 1997 2431 +2288 2199 2409 +2377 2377 2377 +2475 2541 2331 +2579 2696 2261 +2689 2843 2147 +2804 2987 1930 +2923 3128 1137 +3045 3266 0 +3170 3402 0 +3296 3538 0 +3423 3673 0 +3552 3807 0 +3682 3940 0 +3812 4073 0 +3943 4095 0 +2340 0 2623 +2341 0 2623 +2342 0 2623 +2343 0 2622 +2344 0 2622 +2346 0 2621 +2349 0 2621 +2352 0 2620 +2357 0 2619 +2363 0 2618 +2372 0 2616 +2382 0 2613 +2396 0 2610 +2414 0 2605 +2437 611 2599 +2466 1533 2591 +2502 1883 2579 +2545 2129 2563 +2541 2331 2475 +2541 2420 2331 +2696 2678 2261 +2797 2843 2147 +2890 2987 1930 +2991 3128 1137 +3097 3266 0 +3210 3402 0 +3326 3538 0 +3447 3673 0 +3570 3807 0 +3695 3940 0 +3822 4073 0 +3950 4095 0 +2635 0 2755 +2635 0 2755 +2636 0 2755 +2636 0 2755 +2637 0 2755 +2638 0 2754 +2640 0 2754 +2641 0 2753 +2644 0 2752 +2647 0 2751 +2651 0 2750 +2657 0 2748 +2665 0 2746 +2675 0 2742 +2688 0 2738 +2705 738 2731 +2723 1664 2719 +2711 2015 2665 +2696 2261 2579 +2696 2261 2391 +2696 2471 2261 +2843 2766 2147 +2984 2987 1930 +3067 3128 1137 +3159 3266 0 +3259 3402 0 +3365 3538 0 +3477 3673 0 +3593 3807 0 +3713 3940 0 +3835 4073 0 +3961 4095 0 +2859 0 2887 +2859 0 2887 +2859 0 2887 +2860 0 2887 +2860 0 2887 +2861 0 2887 +2862 0 2886 +2863 0 2886 +2864 0 2885 +2866 0 2885 +2869 0 2883 +2873 0 2882 +2877 0 2880 +2878 0 2872 +2874 0 2856 +2870 0 2834 +2863 870 2803 +2855 1796 2758 +2843 2147 2689 +2843 2147 2549 +2843 2147 2246 +2843 2532 2147 +2987 2862 1930 +3128 3101 1137 +3230 3266 0 +3317 3402 0 +3411 3538 0 +3513 3673 0 +3622 3807 0 +3735 3940 0 +3852 4073 0 +3974 4095 0 +3019 0 2988 +3019 0 2987 +3019 0 2987 +3019 0 2987 +3019 0 2986 +3019 0 2985 +3018 0 2984 +3018 0 2982 +3018 0 2980 +3017 0 2977 +3016 0 2974 +3015 0 2968 +3014 0 2961 +3012 0 2952 +3010 0 2939 +3006 0 2920 +3002 0 2895 +2995 1006 2858 +2987 1930 2804 +2987 1930 2699 +2987 1930 2503 +2987 1930 1930 +2987 2602 1930 +3128 2965 1137 +3266 3216 0 +3384 3402 0 +3467 3538 0 +3558 3673 0 +3657 3807 0 +3763 3940 0 +3874 4073 0 +3990 4095 0 +3152 0 3071 +3152 0 3070 +3152 0 3070 +3151 0 3070 +3151 0 3069 +3151 0 3068 +3151 0 3067 +3151 0 3066 +3151 0 3064 +3150 0 3062 +3150 0 3059 +3149 0 3055 +3148 0 3049 +3146 0 3041 +3144 0 3030 +3142 0 3015 +3138 0 2995 +3134 0 2965 +3128 1137 2923 +3128 1137 2845 +3128 1137 2712 +3128 1137 2436 +3128 1758 1137 +3128 2681 1137 +3266 3074 0 +3402 3335 0 +3532 3538 0 +3612 3673 0 +3701 3807 0 +3798 3940 0 +3902 4073 0 +4012 4095 0 +3284 0 3162 +3283 0 3162 +3283 0 3161 +3283 0 3161 +3283 0 3160 +3283 0 3160 +3283 0 3159 +3283 0 3158 +3283 0 3157 +3282 0 3155 +3282 0 3152 +3281 0 3149 +3280 0 3144 +3280 0 3138 +3278 0 3129 +3276 0 3117 +3274 0 3100 +3270 0 3078 +3266 0 3045 +3266 0 2986 +3266 0 2893 +3266 0 2727 +3266 0 2327 +3266 1375 0 +3266 2770 0 +3402 3189 0 +3538 3457 0 +3673 3670 0 +3754 3807 0 +3841 3940 0 +3937 4073 0 +4039 4095 0 +3416 0 3261 +3416 0 3261 +3416 0 3260 +3416 0 3260 +3416 0 3260 +3416 0 3259 +3415 0 3259 +3415 0 3258 +3415 0 3257 +3415 0 3255 +3414 0 3253 +3414 0 3250 +3414 0 3247 +3413 0 3242 +3412 0 3234 +3410 0 3225 +3408 0 3212 +3406 0 3194 +3402 0 3170 +3402 0 3125 +3402 0 3059 +3402 0 2951 +3402 0 2749 +3402 0 2121 +3402 0 0 +3402 2866 0 +3538 3307 0 +3673 3582 0 +3807 3797 0 +3893 3940 0 +3979 4073 0 +4073 4095 0 +3548 0 3367 +3548 0 3367 +3548 0 3366 +3548 0 3366 +3548 0 3366 +3548 0 3365 +3548 0 3365 +3548 0 3364 +3548 0 3363 +3547 0 3362 +3547 0 3361 +3547 0 3358 +3546 0 3355 +3546 0 3351 +3545 0 3346 +3544 0 3339 +3543 0 3329 +3541 0 3315 +3538 0 3296 +3538 0 3263 +3538 0 3214 +3538 0 3140 +3538 0 3018 +3538 0 2775 +3538 0 1477 +3538 0 0 +3538 2970 0 +3673 3429 0 +3807 3708 0 +3940 3926 0 +4030 4073 0 +4095 4095 0 +3680 0 3478 +3680 0 3478 +3680 0 3478 +3680 0 3478 +3680 0 3478 +3680 0 3477 +3680 0 3477 +3680 0 3476 +3680 0 3475 +3680 0 3475 +3679 0 3473 +3679 0 3472 +3679 0 3469 +3678 0 3466 +3678 0 3462 +3677 0 3456 +3676 0 3448 +3675 0 3438 +3673 0 3423 +3673 0 3399 +3673 0 3363 +3673 0 3311 +3673 0 3231 +3673 0 3095 +3673 0 2809 +3673 0 0 +3673 0 0 +3673 3079 0 +3807 3552 0 +3940 3836 0 +4073 4055 0 +4095 4095 0 +3812 0 3594 +3812 0 3594 +3812 0 3594 +3812 0 3594 +3812 0 3594 +3812 0 3593 +3812 0 3593 +3812 0 3593 +3812 0 3592 +3812 0 3591 +3812 0 3590 +3812 0 3589 +3811 0 3587 +3811 0 3585 +3810 0 3582 +3810 0 3577 +3809 0 3571 +3808 0 3563 +3807 0 3552 +3807 0 3534 +3807 0 3508 +3807 0 3470 +3807 0 3415 +3807 0 3329 +3807 0 3181 +3807 0 2850 +3807 0 0 +3807 0 0 +3807 3194 0 +3940 3678 0 +4073 3964 0 +4095 4095 0 +3944 0 3713 +3944 0 3713 +3944 0 3713 +3944 0 3713 +3944 0 3713 +3944 0 3713 +3944 0 3713 +3944 0 3712 +3944 0 3712 +3944 0 3711 +3944 0 3711 +3944 0 3710 +3944 0 3708 +3943 0 3706 +3943 0 3704 +3943 0 3701 +3942 0 3696 +3941 0 3690 +3940 0 3682 +3940 0 3668 +3940 0 3649 +3940 0 3622 +3940 0 3583 +3940 0 3525 +3940 0 3434 +3940 0 3275 +3940 0 2899 +3940 0 0 +3940 0 0 +3940 3312 0 +4073 3805 0 +4095 4094 0 +4076 0 3836 +4076 0 3836 +4076 0 3836 +4076 0 3836 +4076 0 3836 +4076 0 3835 +4076 0 3835 +4076 0 3835 +4076 0 3835 +4076 0 3834 +4076 0 3834 +4076 0 3833 +4076 0 3832 +4076 0 3830 +4075 0 3829 +4075 0 3826 +4075 0 3823 +4074 0 3818 +4073 0 3812 +4073 0 3801 +4073 0 3787 +4073 0 3768 +4073 0 3740 +4073 0 3700 +4073 0 3640 +4073 0 3545 +4073 0 3376 +4073 0 2957 +4073 0 0 +4073 0 0 +4073 3434 0 +4095 3935 0 +4095 0 3961 +4095 0 3961 +4095 0 3961 +4095 0 3961 +4095 0 3961 +4095 0 3961 +4095 0 3961 +4095 0 3960 +4095 0 3960 +4095 0 3960 +4095 0 3959 +4095 0 3959 +4095 0 3958 +4095 0 3957 +4095 0 3955 +4095 0 3953 +4095 0 3951 +4095 0 3947 +4095 0 3943 +4095 0 3935 +4095 0 3924 +4095 0 3910 +4095 0 3890 +4095 0 3861 +4095 0 3820 +4095 0 3759 +4095 0 3661 +4095 0 3484 +4095 0 3027 +4095 0 0 +4095 0 0 +4095 3558 0 +0 2354 2623 +0 2355 2623 +0 2357 2623 +0 2359 2623 +0 2363 2623 +0 2367 2623 +0 2372 2623 +0 2380 2623 +0 2390 2623 +0 2402 2623 +0 2419 2623 +0 2440 2623 +0 2466 2623 +0 2500 2623 +0 2541 2623 +0 2590 2623 +0 2623 2595 +0 2623 2503 +0 2623 2340 +0 2623 1952 +0 2755 0 +0 2887 0 +1594 3019 0 +2352 3152 0 +2684 3284 0 +2925 3416 0 +3124 3548 0 +3300 3680 0 +3462 3812 0 +3616 3944 0 +3763 4076 0 +3907 4095 0 +0 2352 2623 +0 2354 2623 +0 2356 2623 +0 2358 2623 +0 2362 2623 +0 2366 2623 +0 2372 2623 +0 2379 2623 +0 2388 2623 +0 2401 2623 +0 2417 2623 +0 2439 2623 +0 2465 2623 +0 2499 2623 +0 2540 2623 +0 2590 2623 +0 2623 2595 +0 2623 2503 +0 2623 2341 +0 2623 1954 +0 2755 0 +0 2887 0 +1602 3019 0 +2353 3152 0 +2685 3283 0 +2925 3416 0 +3124 3548 0 +3300 3680 0 +3462 3812 0 +3616 3944 0 +3763 4076 0 +3907 4095 0 +0 2351 2623 +0 2352 2623 +0 2355 2623 +0 2357 2623 +0 2360 2623 +0 2364 2623 +0 2370 2623 +0 2378 2623 +0 2387 2623 +0 2400 2623 +0 2416 2623 +0 2437 2623 +0 2464 2623 +0 2498 2623 +0 2539 2623 +0 2589 2623 +0 2623 2596 +0 2623 2504 +0 2623 2342 +0 2623 1956 +0 2755 0 +0 2887 0 +1613 3019 0 +2355 3152 0 +2686 3283 0 +2926 3416 0 +3124 3548 0 +3300 3680 0 +3463 3812 0 +3616 3944 0 +3763 4076 0 +3907 4095 0 +0 2348 2623 +0 2350 2623 +0 2352 2623 +0 2355 2622 +0 2358 2622 +0 2362 2622 +0 2368 2622 +0 2375 2622 +0 2385 2622 +0 2398 2622 +0 2414 2622 +0 2436 2622 +0 2463 2622 +0 2496 2622 +0 2538 2622 +0 2588 2622 +0 2622 2596 +0 2622 2505 +0 2622 2343 +0 2622 1958 +0 2755 0 +0 2887 0 +1628 3019 0 +2358 3151 0 +2688 3283 0 +2927 3416 0 +3125 3548 0 +3301 3680 0 +3463 3812 0 +3616 3944 0 +3764 4076 0 +3907 4095 0 +0 2345 2623 +0 2347 2623 +0 2349 2623 +0 2352 2622 +0 2356 2622 +0 2360 2622 +0 2366 2622 +0 2373 2622 +0 2383 2622 +0 2396 2622 +0 2412 2622 +0 2434 2622 +0 2460 2622 +0 2494 2622 +0 2536 2622 +0 2586 2622 +0 2622 2597 +0 2622 2506 +0 2622 2344 +0 2622 1962 +0 2755 0 +0 2887 0 +1646 3019 0 +2362 3151 0 +2690 3283 0 +2928 3416 0 +3125 3548 0 +3301 3680 0 +3463 3812 0 +3617 3944 0 +3764 4076 0 +3907 4095 0 +0 2341 2623 +0 2342 2623 +0 2345 2623 +0 2347 2622 +0 2351 2622 +0 2356 2621 +0 2362 2621 +0 2370 2621 +0 2380 2621 +0 2393 2621 +0 2409 2621 +0 2431 2621 +0 2458 2621 +0 2492 2621 +0 2533 2621 +0 2584 2621 +0 2621 2598 +0 2621 2507 +0 2621 2346 +0 2621 1966 +0 2754 0 +0 2887 0 +1670 3019 0 +2367 3151 0 +2692 3283 0 +2929 3416 0 +3126 3548 0 +3302 3680 0 +3464 3812 0 +3617 3944 0 +3764 4076 0 +3908 4095 0 +0 2335 2623 +0 2336 2623 +0 2338 2623 +0 2341 2622 +0 2346 2622 +0 2351 2621 +0 2357 2621 +0 2365 2621 +0 2375 2621 +0 2388 2621 +0 2405 2621 +0 2427 2621 +0 2454 2621 +0 2488 2621 +0 2530 2621 +0 2581 2621 +0 2621 2600 +0 2621 2509 +0 2621 2349 +0 2621 1972 +0 2754 0 +0 2886 0 +1700 3018 0 +2373 3151 0 +2695 3283 0 +2931 3415 0 +3128 3548 0 +3303 3680 0 +3464 3812 0 +3617 3944 0 +3764 4076 0 +3908 4095 0 +0 2327 2623 +0 2328 2623 +0 2331 2623 +0 2334 2622 +0 2337 2622 +0 2343 2621 +0 2350 2621 +0 2359 2620 +0 2369 2620 +0 2382 2620 +0 2399 2620 +0 2421 2620 +0 2449 2620 +0 2483 2620 +0 2526 2620 +0 2577 2620 +0 2620 2602 +0 2620 2511 +0 2620 2352 +0 2620 1981 +0 2753 0 +0 2886 0 +1737 3018 0 +2382 3151 0 +2700 3283 0 +2934 3415 0 +3129 3548 0 +3304 3680 0 +3465 3812 0 +3618 3944 0 +3765 4076 0 +3908 4095 0 +0 2315 2623 +0 2317 2623 +0 2320 2623 +0 2323 2622 +0 2327 2622 +0 2332 2621 +0 2339 2621 +0 2348 2620 +0 2361 2619 +0 2374 2619 +0 2392 2619 +0 2414 2619 +0 2442 2619 +0 2477 2619 +0 2520 2619 +0 2572 2619 +0 2619 2604 +0 2619 2515 +0 2619 2357 +0 2619 1991 +0 2752 0 +0 2885 0 +1782 3018 0 +2394 3151 0 +2705 3283 0 +2937 3415 0 +3132 3548 0 +3305 3680 0 +3466 3812 0 +3619 3944 0 +3765 4076 0 +3908 4095 0 +0 2300 2623 +0 2302 2623 +0 2304 2623 +0 2308 2622 +0 2312 2622 +0 2317 2621 +0 2325 2621 +0 2334 2620 +0 2347 2619 +0 2363 2618 +0 2381 2618 +0 2404 2618 +0 2432 2618 +0 2469 2618 +0 2512 2618 +0 2565 2618 +0 2618 2608 +0 2618 2519 +0 2618 2363 +0 2618 2005 +0 2751 0 +0 2885 0 +1837 3017 0 +2408 3150 0 +2713 3282 0 +2942 3415 0 +3135 3547 0 +3307 3680 0 +3468 3812 0 +3620 3944 0 +3766 4076 0 +3909 4095 0 +0 2278 2623 +0 2281 2623 +0 2283 2623 +0 2287 2622 +0 2291 2622 +0 2297 2621 +0 2304 2621 +0 2314 2620 +0 2328 2619 +0 2345 2618 +0 2367 2616 +0 2390 2616 +0 2420 2616 +0 2456 2616 +0 2501 2616 +0 2555 2616 +0 2616 2613 +0 2616 2525 +0 2616 2372 +0 2616 2022 +0 2750 0 +0 2883 0 +1900 3016 0 +2427 3150 0 +2723 3282 0 +2947 3414 0 +3138 3547 0 +3310 3679 0 +3469 3812 0 +3621 3944 0 +3767 4076 0 +3910 4095 0 +0 2248 2623 +0 2250 2623 +0 2253 2623 +0 2256 2622 +0 2261 2622 +0 2268 2621 +0 2276 2621 +0 2287 2620 +0 2301 2619 +0 2319 2618 +0 2342 2616 +0 2371 2613 +0 2402 2613 +0 2440 2613 +0 2487 2613 +0 2542 2613 +0 2607 2613 +0 2613 2533 +0 2613 2382 +0 2613 2045 +0 2748 0 +0 2882 0 +1974 3015 0 +2452 3149 0 +2735 3281 0 +2956 3414 0 +3144 3547 0 +3314 3679 0 +3472 3812 0 +3623 3944 0 +3768 4076 0 +3910 4095 0 +0 2205 2623 +0 2207 2623 +0 2210 2623 +0 2214 2622 +0 2219 2622 +0 2226 2621 +0 2235 2621 +0 2247 2620 +0 2262 2619 +0 2281 2618 +0 2306 2616 +0 2338 2613 +0 2377 2610 +0 2417 2610 +0 2466 2610 +0 2524 2610 +0 2592 2610 +0 2610 2543 +0 2610 2396 +0 2610 2073 +0 2746 0 +0 2880 0 +2056 3014 0 +2482 3148 0 +2752 3280 0 +2966 3414 0 +3151 3546 0 +3318 3679 0 +3475 3811 0 +3625 3944 0 +3770 4076 0 +3912 4095 0 +0 2138 2623 +0 2141 2623 +0 2144 2623 +0 2149 2622 +0 2155 2622 +0 2163 2621 +0 2173 2621 +0 2187 2620 +0 2204 2619 +0 2226 2618 +0 2255 2616 +0 2290 2613 +0 2333 2610 +0 2385 2605 +0 2437 2605 +0 2498 2605 +0 2570 2605 +0 2605 2556 +0 2605 2414 +0 2605 2109 +0 2742 0 +817 2878 0 +2148 3012 0 +2521 3146 0 +2773 3280 0 +2979 3413 0 +3160 3546 0 +3325 3678 0 +3480 3811 0 +3628 3943 0 +3773 4076 0 +3913 4095 0 +0 2032 2623 +0 2035 2623 +0 2039 2623 +0 2045 2622 +0 2052 2622 +0 2062 2621 +0 2075 2621 +0 2092 2620 +0 2113 2619 +0 2140 2618 +0 2174 2616 +0 2216 2613 +0 2266 2610 +0 2326 2605 +611 2395 2599 +611 2462 2599 +611 2538 2599 +611 2599 2572 +611 2599 2437 +611 2599 2153 +0 2738 817 +1596 2874 0 +2247 3010 0 +2566 3144 0 +2800 3278 0 +2997 3412 0 +3171 3545 0 +3333 3678 0 +3486 3810 0 +3632 3943 0 +3776 4075 0 +3916 4095 0 +0 1833 2623 +0 1838 2623 +0 1845 2623 +0 1853 2622 +0 1865 2622 +0 1880 2621 +0 1899 2621 +0 1923 2620 +0 1954 2619 +0 1991 2618 +0 2038 2616 +0 2093 2613 +0 2158 2610 +0 2233 2605 +611 2316 2599 +1533 2408 2591 +1533 2493 2591 +1533 2587 2591 +1533 2591 2466 +1533 2591 2206 +738 2731 1362 +1932 2870 0 +2352 3006 0 +2622 3142 0 +2834 3276 0 +3019 3410 0 +3186 3544 0 +3344 3677 0 +3493 3810 0 +3638 3943 0 +3780 4075 0 +3919 4095 0 +0 1232 2623 +0 1251 2623 +0 1275 2623 +0 1304 2622 +0 1342 2622 +0 1387 2621 +0 1441 2621 +0 1505 2620 +0 1578 2619 +0 1661 2618 +0 1752 2616 +0 1851 2613 +0 1956 2610 +0 2067 2605 +611 2183 2599 +1533 2303 2591 +1883 2425 2579 +1883 2533 2579 +1883 2579 2502 +1883 2579 2267 +1667 2723 1664 +2173 2863 870 +2463 3002 0 +2687 3138 0 +2876 3274 0 +3047 3408 0 +3206 3543 0 +3358 3676 0 +3503 3809 0 +3646 3942 0 +3785 4075 0 +3923 4095 0 +0 0 2623 +0 0 2623 +0 0 2623 +0 0 2622 +0 0 2622 +0 0 2621 +0 0 2621 +0 0 2620 +0 0 2619 +0 0 2618 +0 0 2616 +0 547 2613 +0 1330 2610 +0 1667 2605 +611 1908 2599 +1533 2108 2591 +1883 2284 2579 +2129 2447 2563 +2129 2563 2545 +2129 2563 2339 +2114 2711 2015 +2372 2855 1796 +2579 2995 1006 +2761 3134 0 +2926 3270 0 +3082 3406 0 +3231 3541 0 +3376 3675 0 +3517 3808 0 +3655 3941 0 +3792 4074 0 +3928 4095 0 +0 0 2623 +0 0 2623 +0 0 2623 +0 0 2622 +0 0 2622 +0 0 2621 +0 0 2621 +0 0 2620 +0 0 2619 +0 0 2618 +0 0 2616 +0 0 2613 +0 0 2610 +705 0 2605 +1236 611 2599 +1533 1533 2591 +1883 1981 2579 +2129 2258 2563 +2331 2475 2541 +2331 2541 2420 +2391 2696 2261 +2549 2843 2147 +2699 2987 1930 +2845 3128 1137 +2986 3266 0 +3125 3402 0 +3263 3538 0 +3399 3673 0 +3534 3807 0 +3668 3940 0 +3801 4073 0 +3935 4095 0 +1952 0 2623 +1954 0 2623 +1956 0 2623 +1958 0 2622 +1962 0 2622 +1966 0 2621 +1972 0 2621 +1981 0 2620 +1991 0 2619 +2005 0 2618 +2022 0 2616 +2045 0 2613 +2073 0 2610 +2109 0 2605 +2153 611 2599 +2206 1533 2591 +2267 1883 2579 +2339 2129 2563 +2420 2331 2541 +2509 2509 2509 +2607 2673 2463 +2711 2828 2393 +2821 2975 2280 +2936 3119 2061 +3055 3259 1272 +3177 3398 0 +3302 3535 0 +3428 3670 0 +3556 3805 0 +3684 3939 0 +3814 4072 0 +3944 4095 0 +2473 0 2755 +2473 0 2755 +2474 0 2755 +2475 0 2755 +2476 0 2755 +2477 0 2754 +2479 0 2754 +2482 0 2753 +2485 0 2752 +2490 0 2751 +2496 0 2750 +2504 0 2748 +2515 0 2746 +2529 0 2742 +2547 0 2738 +2570 738 2731 +2598 1664 2723 +2634 2015 2711 +2678 2261 2696 +2673 2463 2607 +2673 2552 2463 +2828 2810 2393 +2929 2975 2280 +3022 3119 2061 +3122 3259 1272 +3230 3398 0 +3342 3535 0 +3459 3670 0 +3579 3805 0 +3702 3939 0 +3827 4072 0 +3954 4095 0 +2767 0 2887 +2767 0 2887 +2767 0 2887 +2768 0 2887 +2768 0 2887 +2769 0 2887 +2770 0 2886 +2772 0 2886 +2773 0 2885 +2776 0 2885 +2779 0 2883 +2784 0 2882 +2789 0 2880 +2797 0 2878 +2807 0 2874 +2820 0 2870 +2837 870 2863 +2855 1796 2852 +2843 2147 2797 +2828 2393 2711 +2828 2393 2522 +2828 2603 2393 +2975 2898 2280 +3116 3119 2061 +3199 3259 1272 +3291 3398 0 +3391 3535 0 +3497 3670 0 +3609 3805 0 +3725 3939 0 +3845 4072 0 +3968 4095 0 +2991 0 3019 +2991 0 3019 +2991 0 3019 +2991 0 3019 +2992 0 3019 +2992 0 3019 +2992 0 3018 +2993 0 3018 +2995 0 3018 +2996 0 3017 +2998 0 3016 +3001 0 3015 +3004 0 3014 +3009 0 3012 +3010 0 3004 +3006 0 2988 +3002 0 2966 +2995 1006 2935 +2987 1930 2890 +2975 2280 2821 +2975 2280 2680 +2975 2280 2377 +2975 2664 2280 +3119 2995 2061 +3259 3233 1272 +3362 3398 0 +3449 3535 0 +3543 3670 0 +3646 3805 0 +3754 3939 0 +3867 4072 0 +3984 4095 0 +3152 0 3120 +3152 0 3120 +3152 0 3120 +3151 0 3119 +3151 0 3119 +3151 0 3118 +3151 0 3117 +3151 0 3116 +3151 0 3115 +3150 0 3112 +3150 0 3110 +3149 0 3106 +3148 0 3100 +3146 0 3093 +3144 0 3084 +3142 0 3071 +3138 0 3053 +3134 0 3027 +3128 1137 2991 +3119 2061 2936 +3119 2061 2831 +3119 2061 2636 +3119 2061 2064 +3119 2734 2061 +3259 3097 1272 +3398 3348 0 +3516 3535 0 +3599 3670 0 +3690 3805 0 +3790 3939 0 +3895 4072 0 +4006 4095 0 +3284 0 3203 +3283 0 3203 +3283 0 3202 +3283 0 3202 +3283 0 3201 +3283 0 3201 +3283 0 3200 +3283 0 3199 +3283 0 3198 +3282 0 3196 +3282 0 3194 +3281 0 3191 +3280 0 3186 +3280 0 3180 +3278 0 3173 +3276 0 3162 +3274 0 3147 +3270 0 3126 +3266 0 3097 +3259 1272 3055 +3259 1272 2976 +3259 1272 2843 +3259 1272 2569 +3259 1899 1272 +3259 2813 1272 +3398 3206 0 +3535 3467 0 +3664 3670 0 +3744 3805 0 +3833 3939 0 +3930 4072 0 +4034 4095 0 +3416 0 3294 +3416 0 3294 +3416 0 3294 +3416 0 3293 +3416 0 3293 +3416 0 3293 +3415 0 3292 +3415 0 3291 +3415 0 3290 +3415 0 3289 +3414 0 3287 +3414 0 3284 +3414 0 3281 +3413 0 3276 +3412 0 3270 +3410 0 3261 +3408 0 3249 +3406 0 3233 +3402 0 3210 +3398 0 3177 +3398 0 3118 +3398 0 3025 +3398 0 2860 +3398 0 2458 +3398 1484 0 +3398 2902 0 +3535 3321 0 +3670 3589 0 +3805 3802 0 +3886 3939 0 +3973 4072 0 +4069 4095 0 +3548 0 3393 +3548 0 3393 +3548 0 3393 +3548 0 3393 +3548 0 3392 +3548 0 3392 +3548 0 3392 +3548 0 3391 +3548 0 3390 +3547 0 3389 +3547 0 3387 +3547 0 3385 +3546 0 3382 +3546 0 3379 +3545 0 3374 +3544 0 3367 +3543 0 3357 +3541 0 3344 +3538 0 3326 +3535 0 3302 +3535 0 3257 +3535 0 3190 +3535 0 3083 +3535 0 2881 +3535 0 2256 +3535 0 0 +3535 2998 0 +3670 3439 0 +3805 3714 0 +3939 3929 0 +4025 4072 0 +4095 4095 0 +3680 0 3499 +3680 0 3499 +3680 0 3499 +3680 0 3499 +3680 0 3498 +3680 0 3498 +3680 0 3497 +3680 0 3497 +3680 0 3496 +3680 0 3495 +3679 0 3494 +3679 0 3493 +3679 0 3490 +3678 0 3488 +3678 0 3483 +3677 0 3478 +3676 0 3471 +3675 0 3461 +3673 0 3447 +3670 0 3428 +3670 0 3395 +3670 0 3346 +3670 0 3273 +3670 0 3150 +3670 0 2908 +3670 0 1603 +3670 0 0 +3670 3102 0 +3805 3561 0 +3939 3840 0 +4072 4058 0 +4095 4095 0 +3812 0 3610 +3812 0 3610 +3812 0 3610 +3812 0 3610 +3812 0 3610 +3812 0 3609 +3812 0 3609 +3812 0 3609 +3812 0 3608 +3812 0 3607 +3812 0 3606 +3812 0 3605 +3811 0 3604 +3811 0 3601 +3810 0 3598 +3810 0 3594 +3809 0 3588 +3808 0 3581 +3807 0 3570 +3805 0 3556 +3805 0 3531 +3805 0 3495 +3805 0 3443 +3805 0 3363 +3805 0 3227 +3805 0 2941 +3805 0 0 +3805 0 0 +3805 3211 0 +3939 3685 0 +4072 3968 0 +4095 4095 0 +3944 0 3726 +3944 0 3726 +3944 0 3726 +3944 0 3726 +3944 0 3726 +3944 0 3725 +3944 0 3725 +3944 0 3725 +3944 0 3725 +3944 0 3724 +3944 0 3723 +3944 0 3722 +3944 0 3721 +3943 0 3719 +3943 0 3717 +3943 0 3713 +3942 0 3709 +3941 0 3703 +3940 0 3695 +3939 0 3684 +3939 0 3666 +3939 0 3640 +3939 0 3603 +3939 0 3547 +3939 0 3461 +3939 0 3313 +3939 0 2982 +3939 0 0 +3939 0 0 +3939 3326 0 +4072 3810 0 +4095 4095 0 +4076 0 3846 +4076 0 3845 +4076 0 3845 +4076 0 3845 +4076 0 3845 +4076 0 3845 +4076 0 3845 +4076 0 3845 +4076 0 3845 +4076 0 3844 +4076 0 3843 +4076 0 3843 +4076 0 3841 +4076 0 3840 +4075 0 3838 +4075 0 3836 +4075 0 3833 +4074 0 3828 +4073 0 3822 +4072 0 3814 +4072 0 3800 +4072 0 3781 +4072 0 3754 +4072 0 3715 +4072 0 3657 +4072 0 3566 +4072 0 3407 +4072 0 3031 +4072 0 0 +4072 0 0 +4072 3444 0 +4095 3938 0 +4095 0 3968 +4095 0 3968 +4095 0 3968 +4095 0 3968 +4095 0 3968 +4095 0 3968 +4095 0 3968 +4095 0 3968 +4095 0 3967 +4095 0 3967 +4095 0 3967 +4095 0 3966 +4095 0 3965 +4095 0 3964 +4095 0 3963 +4095 0 3961 +4095 0 3959 +4095 0 3955 +4095 0 3950 +4095 0 3944 +4095 0 3934 +4095 0 3920 +4095 0 3900 +4095 0 3872 +4095 0 3832 +4095 0 3772 +4095 0 3677 +4095 0 3509 +4095 0 3090 +4095 0 0 +4095 0 0 +4095 3566 0 +0 2486 2755 +0 2487 2755 +0 2488 2755 +0 2490 2755 +0 2493 2755 +0 2496 2755 +0 2500 2755 +0 2505 2755 +0 2513 2755 +0 2523 2755 +0 2535 2755 +0 2552 2755 +0 2573 2755 +0 2599 2755 +0 2632 2755 +0 2673 2755 +0 2723 2755 +0 2755 2727 +0 2755 2635 +0 2755 2473 +0 2755 2083 +0 2887 0 +0 3019 0 +1720 3152 0 +2481 3284 0 +2816 3416 0 +3056 3548 0 +3255 3680 0 +3432 3812 0 +3594 3944 0 +3748 4076 0 +3896 4095 0 +0 2485 2755 +0 2486 2755 +0 2488 2755 +0 2489 2755 +0 2492 2755 +0 2495 2755 +0 2499 2755 +0 2505 2755 +0 2512 2755 +0 2522 2755 +0 2535 2755 +0 2551 2755 +0 2572 2755 +0 2598 2755 +0 2632 2755 +0 2673 2755 +0 2723 2755 +0 2755 2727 +0 2755 2635 +0 2755 2473 +0 2755 2084 +0 2887 0 +0 3019 0 +1726 3152 0 +2482 3283 0 +2817 3416 0 +3057 3548 0 +3256 3680 0 +3432 3812 0 +3595 3944 0 +3748 4076 0 +3896 4095 0 +0 2484 2755 +0 2485 2755 +0 2486 2755 +0 2488 2755 +0 2491 2755 +0 2494 2755 +0 2498 2755 +0 2504 2755 +0 2511 2755 +0 2521 2755 +0 2533 2755 +0 2550 2755 +0 2571 2755 +0 2598 2755 +0 2631 2755 +0 2672 2755 +0 2722 2755 +0 2755 2728 +0 2755 2636 +0 2755 2474 +0 2755 2086 +0 2887 0 +0 3019 0 +1735 3152 0 +2484 3283 0 +2817 3416 0 +3057 3548 0 +3256 3680 0 +3432 3812 0 +3595 3944 0 +3748 4076 0 +3896 4095 0 +0 2482 2755 +0 2483 2755 +0 2485 2755 +0 2487 2755 +0 2489 2755 +0 2492 2755 +0 2497 2755 +0 2502 2755 +0 2510 2755 +0 2520 2755 +0 2532 2755 +0 2549 2755 +0 2570 2755 +0 2596 2755 +0 2630 2755 +0 2671 2755 +0 2721 2755 +0 2755 2728 +0 2755 2636 +0 2755 2475 +0 2755 2088 +0 2887 0 +0 3019 0 +1746 3151 0 +2486 3283 0 +2818 3416 0 +3058 3548 0 +3256 3680 0 +3432 3812 0 +3595 3944 0 +3748 4076 0 +3896 4095 0 +0 2479 2755 +0 2481 2755 +0 2482 2755 +0 2484 2755 +0 2487 2755 +0 2490 2755 +0 2495 2755 +0 2501 2755 +0 2508 2755 +0 2517 2755 +0 2530 2755 +0 2547 2755 +0 2568 2755 +0 2595 2755 +0 2628 2755 +0 2670 2755 +0 2720 2755 +0 2755 2729 +0 2755 2637 +0 2755 2476 +0 2755 2091 +0 2887 0 +0 3019 0 +1760 3151 0 +2489 3283 0 +2820 3416 0 +3059 3548 0 +3257 3680 0 +3433 3812 0 +3595 3944 0 +3748 4076 0 +3896 4095 0 +0 2476 2755 +0 2477 2755 +0 2479 2755 +0 2481 2755 +0 2484 2755 +0 2488 2754 +0 2492 2754 +0 2498 2754 +0 2505 2754 +0 2515 2754 +0 2528 2754 +0 2545 2754 +0 2566 2754 +0 2593 2754 +0 2627 2754 +0 2668 2754 +0 2718 2754 +0 2754 2730 +0 2754 2638 +0 2754 2477 +0 2754 2094 +0 2887 0 +0 3019 0 +1779 3151 0 +2493 3283 0 +2822 3416 0 +3060 3548 0 +3258 3680 0 +3433 3812 0 +3595 3944 0 +3749 4076 0 +3896 4095 0 +0 2472 2755 +0 2473 2755 +0 2475 2755 +0 2477 2755 +0 2480 2755 +0 2484 2754 +0 2489 2754 +0 2494 2754 +0 2502 2754 +0 2512 2754 +0 2525 2754 +0 2541 2754 +0 2563 2754 +0 2590 2754 +0 2624 2754 +0 2666 2754 +0 2716 2754 +0 2754 2731 +0 2754 2640 +0 2754 2479 +0 2754 2099 +0 2886 0 +0 3018 0 +1802 3151 0 +2498 3283 0 +2824 3415 0 +3061 3548 0 +3258 3680 0 +3434 3812 0 +3596 3944 0 +3749 4076 0 +3896 4095 0 +0 2466 2755 +0 2467 2755 +0 2469 2755 +0 2471 2755 +0 2474 2755 +0 2478 2754 +0 2483 2754 +0 2490 2753 +0 2497 2753 +0 2507 2753 +0 2521 2753 +0 2537 2753 +0 2559 2753 +0 2586 2753 +0 2620 2753 +0 2662 2753 +0 2713 2753 +0 2753 2732 +0 2753 2641 +0 2753 2482 +0 2753 2105 +0 2886 0 +0 3018 0 +1832 3151 0 +2504 3283 0 +2827 3415 0 +3063 3548 0 +3260 3680 0 +3435 3812 0 +3596 3944 0 +3749 4076 0 +3897 4095 0 +0 2457 2755 +0 2459 2755 +0 2460 2755 +0 2463 2755 +0 2466 2755 +0 2470 2754 +0 2475 2754 +0 2482 2753 +0 2491 2752 +0 2501 2752 +0 2514 2752 +0 2532 2752 +0 2553 2752 +0 2581 2752 +0 2616 2752 +0 2658 2752 +0 2710 2752 +0 2752 2734 +0 2752 2644 +0 2752 2485 +0 2752 2113 +0 2885 0 +0 3018 0 +1869 3151 0 +2513 3283 0 +2832 3415 0 +3066 3548 0 +3261 3680 0 +3436 3812 0 +3597 3944 0 +3750 4076 0 +3897 4095 0 +0 2446 2755 +0 2448 2755 +0 2449 2755 +0 2452 2755 +0 2455 2755 +0 2459 2754 +0 2464 2754 +0 2471 2753 +0 2481 2752 +0 2493 2751 +0 2506 2751 +0 2524 2751 +0 2546 2751 +0 2574 2751 +0 2609 2751 +0 2652 2751 +0 2704 2751 +0 2751 2737 +0 2751 2647 +0 2751 2490 +0 2751 2123 +0 2885 0 +0 3017 0 +1915 3150 0 +2524 3282 0 +2837 3415 0 +3069 3547 0 +3264 3680 0 +3437 3812 0 +3598 3944 0 +3751 4076 0 +3898 4095 0 +0 2431 2755 +0 2432 2755 +0 2434 2755 +0 2436 2755 +0 2440 2755 +0 2444 2754 +0 2450 2754 +0 2457 2753 +0 2467 2752 +0 2479 2751 +0 2495 2750 +0 2514 2750 +0 2536 2750 +0 2565 2750 +0 2601 2750 +0 2645 2750 +0 2697 2750 +0 2750 2741 +0 2750 2651 +0 2750 2496 +0 2750 2137 +0 2883 0 +0 3016 0 +1969 3150 0 +2539 3282 0 +2845 3414 0 +3074 3547 0 +3267 3679 0 +3439 3812 0 +3600 3944 0 +3752 4076 0 +3898 4095 0 +0 2409 2755 +0 2411 2755 +0 2413 2755 +0 2415 2755 +0 2419 2755 +0 2423 2754 +0 2429 2754 +0 2437 2753 +0 2447 2752 +0 2460 2751 +0 2477 2750 +0 2499 2748 +0 2522 2748 +0 2552 2748 +0 2589 2748 +0 2634 2748 +0 2687 2748 +0 2748 2745 +0 2748 2657 +0 2748 2504 +0 2748 2155 +0 2882 0 +0 3015 0 +2033 3149 0 +2558 3281 0 +2855 3414 0 +3080 3547 0 +3271 3679 0 +3442 3812 0 +3602 3944 0 +3753 4076 0 +3899 4095 0 +0 2379 2755 +0 2381 2755 +0 2383 2755 +0 2386 2755 +0 2389 2755 +0 2394 2754 +0 2400 2754 +0 2408 2753 +0 2419 2752 +0 2433 2751 +0 2451 2750 +0 2474 2748 +0 2503 2746 +0 2534 2746 +0 2572 2746 +0 2619 2746 +0 2674 2746 +0 2740 2746 +0 2746 2665 +0 2746 2515 +0 2746 2177 +0 2880 0 +0 3014 0 +2106 3148 0 +2583 3280 0 +2867 3414 0 +3087 3546 0 +3276 3679 0 +3446 3811 0 +3604 3944 0 +3755 4076 0 +3901 4095 0 +0 2335 2755 +0 2337 2755 +0 2339 2755 +0 2342 2755 +0 2346 2755 +0 2351 2754 +0 2358 2754 +0 2367 2753 +0 2379 2752 +0 2394 2751 +0 2414 2750 +0 2439 2748 +0 2470 2746 +0 2509 2742 +0 2550 2742 +0 2598 2742 +0 2656 2742 +0 2724 2742 +0 2742 2675 +0 2742 2529 +0 2742 2206 +0 2878 0 +0 3012 0 +2189 3146 0 +2613 3280 0 +2884 3413 0 +3098 3546 0 +3282 3678 0 +3450 3811 0 +3607 3943 0 +3757 4076 0 +3903 4095 0 +0 2269 2755 +0 2271 2755 +0 2274 2755 +0 2277 2755 +0 2281 2755 +0 2287 2754 +0 2295 2754 +0 2305 2753 +0 2319 2752 +0 2336 2751 +0 2359 2750 +0 2387 2748 +0 2422 2746 +0 2465 2742 +0 2517 2738 +0 2569 2738 +0 2631 2738 +0 2702 2738 +0 2738 2688 +0 2738 2547 +0 2738 2241 +0 2874 0 +922 3010 0 +2280 3144 0 +2651 3278 0 +2906 3412 0 +3111 3545 0 +3291 3678 0 +3457 3810 0 +3612 3943 0 +3760 4075 0 +3905 4095 0 +0 2162 2755 +0 2164 2755 +0 2167 2755 +0 2172 2755 +0 2177 2755 +0 2185 2754 +0 2195 2754 +0 2208 2753 +0 2224 2752 +0 2245 2751 +0 2273 2750 +0 2306 2748 +0 2348 2746 +0 2398 2742 +0 2458 2738 +738 2527 2731 +738 2594 2731 +738 2671 2731 +738 2731 2705 +738 2731 2570 +738 2731 2285 +0 2870 963 +1723 3006 0 +2379 3142 0 +2698 3276 0 +2933 3410 0 +3129 3544 0 +3303 3677 0 +3465 3810 0 +3618 3943 0 +3765 4075 0 +3908 4095 0 +0 1962 2755 +0 1966 2755 +0 1971 2755 +0 1977 2755 +0 1986 2755 +0 1997 2754 +0 2012 2754 +0 2031 2753 +0 2056 2752 +0 2086 2751 +0 2124 2750 +0 2170 2748 +0 2226 2746 +0 2291 2742 +0 2365 2738 +738 2448 2731 +1664 2540 2723 +1664 2626 2723 +1664 2719 2723 +1664 2723 2598 +1664 2723 2338 +870 2863 1498 +2062 3002 0 +2484 3138 0 +2753 3274 0 +2966 3408 0 +3151 3543 0 +3319 3676 0 +3475 3809 0 +3626 3942 0 +3770 4075 0 +3912 4095 0 +0 1353 2755 +0 1367 2755 +0 1386 2755 +0 1409 2755 +0 1439 2755 +0 1476 2754 +0 1521 2754 +0 1575 2753 +0 1638 2752 +0 1711 2751 +0 1794 2750 +0 1885 2748 +0 1983 2746 +0 2089 2742 +0 2200 2738 +738 2315 2731 +1664 2435 2723 +2015 2557 2711 +2015 2665 2711 +2015 2711 2634 +2015 2711 2400 +1797 2855 1796 +2303 2995 1006 +2596 3134 0 +2818 3270 0 +3008 3406 0 +3179 3541 0 +3338 3675 0 +3490 3808 0 +3635 3941 0 +3777 4074 0 +3917 4095 0 +0 0 2755 +0 0 2755 +0 0 2755 +0 0 2755 +0 0 2755 +0 0 2754 +0 0 2754 +0 0 2753 +0 0 2752 +0 0 2751 +0 0 2750 +0 0 2748 +0 678 2746 +0 1463 2742 +0 1799 2738 +738 2040 2731 +1664 2240 2723 +2015 2416 2711 +2261 2579 2696 +2261 2696 2678 +2261 2696 2471 +2246 2843 2147 +2503 2987 1930 +2712 3128 1137 +2893 3266 0 +3059 3402 0 +3214 3538 0 +3363 3673 0 +3508 3807 0 +3649 3940 0 +3787 4073 0 +3924 4095 0 +0 0 2755 +0 0 2755 +0 0 2755 +0 0 2755 +0 0 2755 +0 0 2754 +0 0 2754 +0 0 2753 +0 0 2752 +0 0 2751 +0 0 2750 +0 0 2748 +0 0 2746 +0 0 2742 +817 0 2738 +1362 738 2731 +1664 1667 2723 +2015 2114 2711 +2261 2391 2696 +2463 2607 2673 +2463 2673 2552 +2522 2828 2393 +2680 2975 2280 +2831 3119 2061 +2976 3259 1272 +3118 3398 0 +3257 3535 0 +3395 3670 0 +3531 3805 0 +3666 3939 0 +3800 4072 0 +3934 4095 0 +2083 0 2755 +2084 0 2755 +2086 0 2755 +2088 0 2755 +2091 0 2755 +2094 0 2754 +2099 0 2754 +2105 0 2753 +2113 0 2752 +2123 0 2751 +2137 0 2750 +2155 0 2748 +2177 0 2746 +2206 0 2742 +2241 0 2738 +2285 738 2731 +2338 1664 2723 +2400 2015 2711 +2471 2261 2696 +2552 2463 2673 +2642 2642 2642 +2739 2805 2596 +2843 2959 2526 +2954 3108 2412 +3069 3251 2194 +3187 3392 1406 +3309 3530 0 +3434 3667 0 +3560 3802 0 +3688 3937 0 +3816 4071 0 +3946 4095 0 +2604 0 2887 +2604 0 2887 +2605 0 2887 +2605 0 2887 +2606 0 2887 +2607 0 2887 +2609 0 2886 +2611 0 2886 +2613 0 2885 +2617 0 2885 +2621 0 2883 +2628 0 2882 +2636 0 2880 +2647 0 2878 +2661 0 2874 +2678 0 2870 +2701 870 2863 +2730 1796 2855 +2766 2147 2843 +2810 2393 2828 +2805 2596 2739 +2805 2684 2596 +2959 2942 2526 +3061 3108 2412 +3154 3251 2194 +3255 3392 1406 +3362 3530 0 +3474 3667 0 +3591 3802 0 +3711 3937 0 +3834 4071 0 +3960 4095 0 +2898 0 3019 +2898 0 3019 +2898 0 3019 +2899 0 3019 +2899 0 3019 +2900 0 3019 +2901 0 3018 +2902 0 3018 +2903 0 3018 +2905 0 3017 +2907 0 3016 +2911 0 3015 +2915 0 3014 +2921 0 3012 +2928 0 3010 +2939 0 3006 +2952 0 3002 +2968 1006 2995 +2987 1930 2984 +2975 2280 2929 +2959 2526 2843 +2959 2526 2654 +2959 2735 2526 +3108 3031 2412 +3248 3251 2194 +3331 3392 1406 +3423 3530 0 +3523 3667 0 +3629 3802 0 +3741 3937 0 +3857 4071 0 +3977 4095 0 +3123 0 3152 +3123 0 3152 +3123 0 3152 +3123 0 3151 +3123 0 3151 +3124 0 3151 +3124 0 3151 +3125 0 3151 +3126 0 3151 +3127 0 3150 +3128 0 3150 +3131 0 3149 +3133 0 3148 +3137 0 3146 +3141 0 3144 +3142 0 3136 +3138 0 3120 +3134 0 3098 +3128 1137 3067 +3119 2061 3022 +3108 2412 2954 +3108 2412 2813 +3108 2412 2511 +3108 2796 2412 +3251 3126 2194 +3392 3365 1406 +3495 3530 0 +3581 3667 0 +3676 3802 0 +3777 3937 0 +3886 4071 0 +3999 4095 0 +3284 0 3252 +3283 0 3252 +3283 0 3252 +3283 0 3252 +3283 0 3251 +3283 0 3251 +3283 0 3250 +3283 0 3249 +3283 0 3248 +3282 0 3247 +3282 0 3244 +3281 0 3242 +3280 0 3238 +3280 0 3233 +3278 0 3225 +3276 0 3216 +3274 0 3203 +3270 0 3184 +3266 0 3159 +3259 1272 3122 +3251 2194 3069 +3251 2194 2963 +3251 2194 2768 +3251 2195 2194 +3251 2866 2194 +3392 3230 1406 +3530 3480 0 +3648 3667 0 +3731 3802 0 +3822 3937 0 +3921 4071 0 +4027 4095 0 +3416 0 3335 +3416 0 3335 +3416 0 3335 +3416 0 3335 +3416 0 3334 +3416 0 3334 +3415 0 3333 +3415 0 3333 +3415 0 3331 +3415 0 3330 +3414 0 3329 +3414 0 3326 +3414 0 3323 +3413 0 3319 +3412 0 3313 +3410 0 3305 +3408 0 3294 +3406 0 3279 +3402 0 3259 +3398 0 3230 +3392 1406 3187 +3392 1406 3108 +3392 1406 2976 +3392 1406 2701 +3392 2025 1406 +3392 2945 1406 +3530 3339 0 +3667 3599 0 +3796 3802 0 +3876 3937 0 +3965 4071 0 +4062 4095 0 +3548 0 3426 +3548 0 3426 +3548 0 3426 +3548 0 3426 +3548 0 3426 +3548 0 3425 +3548 0 3425 +3548 0 3424 +3548 0 3423 +3547 0 3422 +3547 0 3421 +3547 0 3419 +3546 0 3416 +3546 0 3413 +3545 0 3408 +3544 0 3402 +3543 0 3393 +3541 0 3381 +3538 0 3365 +3535 0 3342 +3530 0 3309 +3530 0 3250 +3530 0 3157 +3530 0 2992 +3530 0 2593 +3530 1621 0 +3530 3034 0 +3667 3453 0 +3802 3721 0 +3937 3934 0 +4018 4071 0 +4095 4095 0 +3680 0 3525 +3680 0 3525 +3680 0 3525 +3680 0 3525 +3680 0 3525 +3680 0 3525 +3680 0 3524 +3680 0 3524 +3680 0 3523 +3680 0 3522 +3679 0 3521 +3679 0 3520 +3679 0 3517 +3678 0 3515 +3678 0 3511 +3677 0 3506 +3676 0 3499 +3675 0 3490 +3673 0 3477 +3670 0 3459 +3667 0 3434 +3667 0 3389 +3667 0 3323 +3667 0 3215 +3667 0 3014 +3667 0 2388 +3667 0 0 +3667 3131 0 +3802 3571 0 +3937 3846 0 +4071 4061 0 +4095 4095 0 +3812 0 3631 +3812 0 3631 +3812 0 3631 +3812 0 3631 +3812 0 3631 +3812 0 3630 +3812 0 3630 +3812 0 3630 +3812 0 3629 +3812 0 3629 +3812 0 3628 +3812 0 3626 +3811 0 3625 +3811 0 3622 +3810 0 3620 +3810 0 3616 +3809 0 3610 +3808 0 3603 +3807 0 3593 +3805 0 3579 +3802 0 3560 +3802 0 3527 +3802 0 3479 +3802 0 3405 +3802 0 3282 +3802 0 3040 +3802 0 1737 +3802 0 0 +3802 3234 0 +3937 3692 0 +4071 3972 0 +4095 4095 0 +3944 0 3742 +3944 0 3742 +3944 0 3742 +3944 0 3742 +3944 0 3742 +3944 0 3742 +3944 0 3741 +3944 0 3741 +3944 0 3741 +3944 0 3740 +3944 0 3740 +3944 0 3739 +3944 0 3737 +3943 0 3736 +3943 0 3733 +3943 0 3730 +3942 0 3726 +3941 0 3720 +3940 0 3713 +3939 0 3702 +3937 0 3688 +3937 0 3663 +3937 0 3628 +3937 0 3575 +3937 0 3495 +3937 0 3359 +3937 0 3073 +3937 0 0 +3937 0 0 +3937 3344 0 +4071 3816 0 +4095 4095 0 +4076 0 3858 +4076 0 3858 +4076 0 3858 +4076 0 3858 +4076 0 3858 +4076 0 3858 +4076 0 3858 +4076 0 3857 +4076 0 3857 +4076 0 3856 +4076 0 3856 +4076 0 3855 +4076 0 3854 +4076 0 3853 +4075 0 3851 +4075 0 3849 +4075 0 3846 +4074 0 3841 +4073 0 3835 +4072 0 3827 +4071 0 3816 +4071 0 3798 +4071 0 3772 +4071 0 3735 +4071 0 3679 +4071 0 3593 +4071 0 3445 +4071 0 3113 +4071 0 0 +4071 0 0 +4071 3458 0 +4095 3943 0 +4095 0 3978 +4095 0 3978 +4095 0 3978 +4095 0 3978 +4095 0 3977 +4095 0 3977 +4095 0 3977 +4095 0 3977 +4095 0 3977 +4095 0 3977 +4095 0 3976 +4095 0 3976 +4095 0 3975 +4095 0 3974 +4095 0 3972 +4095 0 3971 +4095 0 3968 +4095 0 3965 +4095 0 3961 +4095 0 3954 +4095 0 3946 +4095 0 3932 +4095 0 3913 +4095 0 3886 +4095 0 3847 +4095 0 3790 +4095 0 3699 +4095 0 3539 +4095 0 3164 +4095 0 0 +4095 0 0 +4095 3576 0 +0 2618 2887 +0 2619 2887 +0 2620 2887 +0 2621 2887 +0 2623 2887 +0 2625 2887 +0 2628 2887 +0 2633 2887 +0 2638 2887 +0 2646 2887 +0 2655 2887 +0 2668 2887 +0 2684 2887 +0 2705 2887 +0 2732 2887 +0 2765 2887 +0 2806 2887 +0 2856 2887 +0 2887 2859 +0 2887 2767 +0 2887 2604 +0 2887 2215 +0 3019 0 +0 3152 0 +1844 3284 0 +2613 3416 0 +2948 3548 0 +3188 3680 0 +3387 3812 0 +3564 3944 0 +3726 4076 0 +3880 4095 0 +0 2617 2887 +0 2618 2887 +0 2619 2887 +0 2620 2887 +0 2622 2887 +0 2625 2887 +0 2628 2887 +0 2632 2887 +0 2638 2887 +0 2645 2887 +0 2655 2887 +0 2667 2887 +0 2684 2887 +0 2705 2887 +0 2731 2887 +0 2764 2887 +0 2805 2887 +0 2855 2887 +0 2887 2859 +0 2887 2767 +0 2887 2604 +0 2887 2215 +0 3019 0 +0 3152 0 +1849 3283 0 +2614 3416 0 +2948 3548 0 +3188 3680 0 +3388 3812 0 +3564 3944 0 +3726 4076 0 +3880 4095 0 +0 2616 2887 +0 2617 2887 +0 2618 2887 +0 2620 2887 +0 2621 2887 +0 2624 2887 +0 2627 2887 +0 2631 2887 +0 2637 2887 +0 2644 2887 +0 2654 2887 +0 2667 2887 +0 2683 2887 +0 2704 2887 +0 2731 2887 +0 2764 2887 +0 2805 2887 +0 2855 2887 +0 2887 2859 +0 2887 2767 +0 2887 2605 +0 2887 2217 +0 3019 0 +0 3152 0 +1856 3283 0 +2615 3416 0 +2949 3548 0 +3189 3680 0 +3388 3812 0 +3564 3944 0 +3726 4076 0 +3880 4095 0 +0 2615 2887 +0 2616 2887 +0 2617 2887 +0 2619 2887 +0 2620 2887 +0 2623 2887 +0 2626 2887 +0 2630 2887 +0 2636 2887 +0 2643 2887 +0 2653 2887 +0 2666 2887 +0 2682 2887 +0 2703 2887 +0 2730 2887 +0 2763 2887 +0 2804 2887 +0 2854 2887 +0 2887 2860 +0 2887 2768 +0 2887 2605 +0 2887 2218 +0 3019 0 +0 3151 0 +1864 3283 0 +2617 3416 0 +2950 3548 0 +3189 3680 0 +3388 3812 0 +3564 3944 0 +3727 4076 0 +3880 4095 0 +0 2613 2887 +0 2614 2887 +0 2615 2887 +0 2617 2887 +0 2619 2887 +0 2621 2887 +0 2625 2887 +0 2629 2887 +0 2635 2887 +0 2642 2887 +0 2651 2887 +0 2664 2887 +0 2681 2887 +0 2702 2887 +0 2728 2887 +0 2762 2887 +0 2803 2887 +0 2853 2887 +0 2887 2860 +0 2887 2768 +0 2887 2606 +0 2887 2220 +0 3019 0 +0 3151 0 +1875 3283 0 +2619 3416 0 +2951 3548 0 +3190 3680 0 +3388 3812 0 +3564 3944 0 +3727 4076 0 +3880 4095 0 +0 2611 2887 +0 2612 2887 +0 2613 2887 +0 2614 2887 +0 2617 2887 +0 2619 2887 +0 2623 2887 +0 2627 2887 +0 2632 2887 +0 2640 2887 +0 2650 2887 +0 2662 2887 +0 2679 2887 +0 2700 2887 +0 2727 2887 +0 2761 2887 +0 2802 2887 +0 2852 2887 +0 2887 2861 +0 2887 2769 +0 2887 2607 +0 2887 2223 +0 3019 0 +0 3151 0 +1890 3283 0 +2621 3416 0 +2952 3548 0 +3191 3680 0 +3389 3812 0 +3565 3944 0 +3727 4076 0 +3881 4095 0 +0 2607 2887 +0 2608 2887 +0 2609 2887 +0 2611 2887 +0 2613 2887 +0 2616 2887 +0 2620 2886 +0 2624 2886 +0 2630 2886 +0 2637 2886 +0 2647 2886 +0 2660 2886 +0 2677 2886 +0 2698 2886 +0 2725 2886 +0 2759 2886 +0 2800 2886 +0 2850 2886 +0 2886 2862 +0 2886 2770 +0 2886 2609 +0 2886 2226 +0 3018 0 +0 3151 0 +1908 3283 0 +2625 3415 0 +2954 3548 0 +3192 3680 0 +3390 3812 0 +3565 3944 0 +3727 4076 0 +3881 4095 0 +0 2603 2887 +0 2604 2887 +0 2605 2887 +0 2607 2887 +0 2609 2887 +0 2612 2887 +0 2616 2886 +0 2621 2886 +0 2626 2886 +0 2634 2886 +0 2644 2886 +0 2657 2886 +0 2673 2886 +0 2695 2886 +0 2722 2886 +0 2756 2886 +0 2798 2886 +0 2848 2886 +0 2886 2863 +0 2886 2772 +0 2886 2611 +0 2886 2231 +0 3018 0 +0 3151 0 +1932 3283 0 +2630 3415 0 +2956 3548 0 +3193 3680 0 +3391 3812 0 +3566 3944 0 +3728 4076 0 +3881 4095 0 +0 2597 2887 +0 2598 2887 +0 2599 2887 +0 2601 2887 +0 2603 2887 +0 2606 2887 +0 2610 2886 +0 2615 2886 +0 2622 2885 +0 2629 2885 +0 2639 2885 +0 2652 2885 +0 2669 2885 +0 2691 2885 +0 2718 2885 +0 2752 2885 +0 2795 2885 +0 2845 2885 +0 2885 2864 +0 2885 2773 +0 2885 2613 +0 2885 2237 +0 3018 0 +0 3151 0 +1962 3283 0 +2637 3415 0 +2960 3548 0 +3195 3680 0 +3392 3812 0 +3567 3944 0 +3728 4076 0 +3881 4095 0 +0 2589 2887 +0 2589 2887 +0 2591 2887 +0 2592 2887 +0 2595 2887 +0 2598 2887 +0 2602 2886 +0 2607 2886 +0 2614 2885 +0 2623 2885 +0 2633 2885 +0 2647 2885 +0 2664 2885 +0 2685 2885 +0 2713 2885 +0 2748 2885 +0 2790 2885 +0 2842 2885 +0 2885 2866 +0 2885 2776 +0 2885 2617 +0 2885 2245 +0 3017 0 +0 3150 0 +1999 3282 0 +2646 3415 0 +2964 3547 0 +3198 3680 0 +3394 3812 0 +3568 3944 0 +3729 4076 0 +3882 4095 0 +0 2577 2887 +0 2578 2887 +0 2580 2887 +0 2581 2887 +0 2584 2887 +0 2587 2887 +0 2591 2886 +0 2596 2886 +0 2603 2885 +0 2613 2885 +0 2625 2883 +0 2639 2883 +0 2656 2883 +0 2678 2883 +0 2706 2883 +0 2741 2883 +0 2784 2883 +0 2836 2883 +0 2883 2869 +0 2883 2779 +0 2883 2621 +0 2883 2255 +0 3016 0 +0 3150 0 +2045 3282 0 +2657 3414 0 +2970 3547 0 +3201 3679 0 +3396 3812 0 +3569 3944 0 +3730 4076 0 +3883 4095 0 +0 2562 2887 +0 2563 2887 +0 2564 2887 +0 2566 2887 +0 2569 2887 +0 2572 2887 +0 2576 2886 +0 2581 2886 +0 2589 2885 +0 2599 2885 +0 2611 2883 +0 2628 2882 +0 2645 2882 +0 2668 2882 +0 2697 2882 +0 2733 2882 +0 2777 2882 +0 2829 2882 +0 2882 2873 +0 2882 2784 +0 2882 2628 +0 2882 2269 +0 3015 0 +0 3149 0 +2100 3281 0 +2672 3414 0 +2977 3547 0 +3206 3679 0 +3399 3812 0 +3571 3944 0 +3732 4076 0 +3884 4095 0 +0 2541 2887 +0 2542 2887 +0 2543 2887 +0 2545 2887 +0 2548 2887 +0 2551 2887 +0 2555 2886 +0 2561 2886 +0 2569 2885 +0 2579 2885 +0 2592 2883 +0 2609 2882 +0 2631 2880 +0 2654 2880 +0 2684 2880 +0 2721 2880 +0 2766 2880 +0 2820 2880 +0 2880 2877 +0 2880 2789 +0 2880 2636 +0 2880 2287 +0 3014 0 +0 3148 0 +2164 3280 0 +2691 3414 0 +2987 3546 0 +3212 3679 0 +3403 3811 0 +3574 3944 0 +3734 4076 0 +3885 4095 0 +0 2510 2887 +0 2511 2887 +0 2513 2887 +0 2515 2887 +0 2517 2887 +0 2521 2887 +0 2526 2886 +0 2532 2886 +0 2540 2885 +0 2551 2885 +0 2565 2883 +0 2583 2882 +0 2606 2880 +0 2636 2878 +0 2666 2878 +0 2704 2878 +0 2751 2878 +0 2807 2878 +0 2872 2878 +0 2878 2797 +0 2878 2647 +0 2878 2309 +0 3012 0 +0 3146 0 +2237 3280 0 +2715 3413 0 +3000 3546 0 +3220 3678 0 +3408 3811 0 +3578 3943 0 +3736 4076 0 +3887 4095 0 +0 2466 2887 +0 2467 2887 +0 2469 2887 +0 2471 2887 +0 2474 2887 +0 2478 2887 +0 2483 2886 +0 2490 2886 +0 2499 2885 +0 2511 2885 +0 2526 2883 +0 2546 2882 +0 2571 2880 +0 2602 2878 +0 2641 2874 +0 2681 2874 +0 2730 2874 +0 2788 2874 +0 2856 2874 +0 2874 2807 +0 2874 2661 +0 2874 2338 +0 3010 0 +0 3144 0 +2320 3278 0 +2746 3412 0 +3016 3545 0 +3230 3678 0 +3415 3810 0 +3583 3943 0 +3739 4075 0 +3889 4095 0 +0 2400 2887 +0 2401 2887 +0 2403 2887 +0 2406 2887 +0 2409 2887 +0 2413 2887 +0 2419 2886 +0 2427 2886 +0 2438 2885 +0 2451 2885 +0 2469 2883 +0 2491 2882 +0 2519 2880 +0 2554 2878 +0 2597 2874 +0 2649 2870 +0 2701 2870 +0 2763 2870 +0 2834 2870 +0 2870 2820 +0 2870 2678 +0 2870 2374 +0 3006 0 +1068 3142 0 +2411 3276 0 +2784 3410 0 +3038 3544 0 +3243 3677 0 +3424 3810 0 +3589 3943 0 +3744 4075 0 +3893 4095 0 +0 2292 2887 +0 2294 2887 +0 2296 2887 +0 2299 2887 +0 2304 2887 +0 2310 2887 +0 2317 2886 +0 2327 2886 +0 2340 2885 +0 2356 2885 +0 2378 2883 +0 2405 2882 +0 2439 2880 +0 2480 2878 +0 2530 2874 +0 2590 2870 +870 2659 2863 +870 2726 2863 +870 2803 2863 +870 2863 2837 +870 2863 2701 +870 2863 2417 +0 3002 1109 +1857 3138 0 +2510 3274 0 +2830 3408 0 +3065 3543 0 +3261 3676 0 +3435 3809 0 +3597 3942 0 +3750 4075 0 +3897 4095 0 +0 2091 2887 +0 2094 2887 +0 2098 2887 +0 2103 2887 +0 2110 2887 +0 2118 2887 +0 2129 2886 +0 2144 2886 +0 2163 2885 +0 2188 2885 +0 2218 2883 +0 2256 2882 +0 2302 2880 +0 2358 2878 +0 2423 2874 +0 2497 2870 +870 2580 2863 +1796 2672 2855 +1796 2758 2855 +1796 2852 2855 +1796 2855 2730 +1796 2855 2470 +1006 2995 1635 +2195 3134 0 +2616 3270 0 +2886 3406 0 +3099 3541 0 +3283 3675 0 +3451 3808 0 +3608 3941 0 +3757 4074 0 +3903 4095 0 +0 1472 2887 +0 1483 2887 +0 1497 2887 +0 1516 2887 +0 1540 2887 +0 1569 2887 +0 1606 2886 +0 1651 2886 +0 1706 2885 +0 1769 2885 +0 1843 2883 +0 1925 2882 +0 2016 2880 +0 2115 2878 +0 2220 2874 +0 2332 2870 +870 2447 2863 +1796 2567 2855 +2147 2689 2843 +2147 2797 2843 +2147 2843 2766 +2147 2843 2532 +1930 2987 1930 +2436 3128 1137 +2727 3266 0 +2951 3402 0 +3140 3538 0 +3311 3673 0 +3470 3807 0 +3622 3940 0 +3768 4073 0 +3910 4095 0 +0 0 2887 +0 0 2887 +0 0 2887 +0 0 2887 +0 0 2887 +0 0 2887 +0 0 2886 +0 0 2886 +0 0 2885 +0 0 2885 +0 0 2883 +0 0 2882 +0 0 2880 +0 817 2878 +0 1596 2874 +0 1932 2870 +870 2173 2863 +1796 2372 2855 +2147 2549 2843 +2393 2711 2828 +2393 2828 2810 +2393 2828 2603 +2377 2975 2280 +2636 3119 2061 +2843 3259 1272 +3025 3398 0 +3190 3535 0 +3346 3670 0 +3495 3805 0 +3640 3939 0 +3781 4072 0 +3920 4095 0 +0 0 2887 +0 0 2887 +0 0 2887 +0 0 2887 +0 0 2887 +0 0 2887 +0 0 2886 +0 0 2886 +0 0 2885 +0 0 2885 +0 0 2883 +0 0 2882 +0 0 2880 +0 0 2878 +0 0 2874 +963 0 2870 +1498 870 2863 +1796 1797 2855 +2147 2246 2843 +2393 2522 2828 +2596 2739 2805 +2596 2805 2684 +2654 2959 2526 +2813 3108 2412 +2963 3251 2194 +3108 3392 1406 +3250 3530 0 +3389 3667 0 +3527 3802 0 +3663 3937 0 +3798 4071 0 +3932 4095 0 +2215 0 2887 +2215 0 2887 +2217 0 2887 +2218 0 2887 +2220 0 2887 +2223 0 2887 +2226 0 2886 +2231 0 2886 +2237 0 2885 +2245 0 2885 +2255 0 2883 +2269 0 2882 +2287 0 2880 +2309 0 2878 +2338 0 2874 +2374 0 2870 +2417 870 2863 +2470 1796 2855 +2532 2147 2843 +2603 2393 2828 +2684 2596 2805 +2774 2774 2774 +2871 2937 2728 +2976 3092 2658 +3085 3239 2544 +3201 3383 2326 +3320 3524 1536 +3441 3662 0 +3566 3799 0 +3692 3934 0 +3820 4069 0 +3949 4095 0 +2735 0 3019 +2735 0 3019 +2736 0 3019 +2736 0 3019 +2737 0 3019 +2738 0 3019 +2739 0 3018 +2740 0 3018 +2742 0 3018 +2745 0 3017 +2749 0 3016 +2753 0 3015 +2759 0 3014 +2767 0 3012 +2778 0 3010 +2792 0 3006 +2810 0 3002 +2833 1006 2995 +2862 1930 2987 +2898 2280 2975 +2942 2526 2959 +2937 2728 2871 +2937 2816 2728 +3092 3074 2658 +3193 3239 2544 +3286 3383 2326 +3387 3524 1536 +3494 3662 0 +3606 3799 0 +3723 3934 0 +3843 4069 0 +3966 4095 0 +3031 0 3152 +3031 0 3152 +3031 0 3152 +3031 0 3151 +3031 0 3151 +3032 0 3151 +3032 0 3151 +3033 0 3151 +3034 0 3151 +3036 0 3150 +3038 0 3150 +3040 0 3149 +3043 0 3148 +3047 0 3146 +3053 0 3144 +3061 0 3142 +3071 0 3138 +3084 0 3134 +3101 1137 3128 +3119 2061 3116 +3108 2412 3061 +3092 2658 2976 +3092 2658 2787 +3092 2867 2658 +3239 3162 2544 +3380 3383 2326 +3463 3524 1536 +3555 3662 0 +3655 3799 0 +3761 3934 0 +3873 4069 0 +3989 4095 0 +3254 0 3284 +3254 0 3283 +3255 0 3283 +3255 0 3283 +3255 0 3283 +3255 0 3283 +3256 0 3283 +3256 0 3283 +3257 0 3283 +3257 0 3282 +3259 0 3282 +3260 0 3281 +3262 0 3280 +3265 0 3280 +3269 0 3278 +3273 0 3276 +3274 0 3268 +3270 0 3252 +3266 0 3230 +3259 1272 3199 +3251 2194 3154 +3239 2544 3085 +3239 2544 2945 +3239 2544 2642 +3239 2928 2544 +3383 3258 2326 +3524 3497 1536 +3626 3662 0 +3713 3799 0 +3808 3934 0 +3910 4069 0 +4018 4095 0 +3416 0 3385 +3416 0 3385 +3416 0 3384 +3416 0 3384 +3416 0 3384 +3416 0 3384 +3415 0 3383 +3415 0 3382 +3415 0 3381 +3415 0 3380 +3414 0 3379 +3414 0 3376 +3414 0 3374 +3413 0 3370 +3412 0 3365 +3410 0 3358 +3408 0 3348 +3406 0 3335 +3402 0 3317 +3398 0 3291 +3392 1406 3255 +3383 2326 3201 +3383 2326 3095 +3383 2326 2900 +3383 2326 2328 +3383 2998 2326 +3524 3362 1536 +3662 3612 0 +3781 3799 0 +3863 3934 0 +3954 4069 0 +4054 4095 0 +3548 0 3467 +3548 0 3467 +3548 0 3467 +3548 0 3467 +3548 0 3467 +3548 0 3466 +3548 0 3466 +3548 0 3466 +3548 0 3465 +3547 0 3464 +3547 0 3462 +3547 0 3461 +3546 0 3458 +3546 0 3455 +3545 0 3451 +3544 0 3445 +3543 0 3437 +3541 0 3426 +3538 0 3411 +3535 0 3391 +3530 0 3362 +3524 1536 3320 +3524 1536 3241 +3524 1536 3108 +3524 1536 2833 +3524 2158 1536 +3524 3078 1536 +3662 3471 0 +3799 3731 0 +3928 3934 0 +4008 4069 0 +4095 4095 0 +3680 0 3558 +3680 0 3558 +3680 0 3558 +3680 0 3558 +3680 0 3558 +3680 0 3558 +3680 0 3557 +3680 0 3557 +3680 0 3556 +3680 0 3556 +3679 0 3554 +3679 0 3553 +3679 0 3551 +3678 0 3548 +3678 0 3545 +3677 0 3540 +3676 0 3534 +3675 0 3525 +3673 0 3513 +3670 0 3497 +3667 0 3474 +3662 0 3441 +3662 0 3382 +3662 0 3289 +3662 0 3125 +3662 0 2724 +3662 1753 0 +3662 3166 0 +3799 3585 0 +3934 3853 0 +4069 4066 0 +4095 4095 0 +3812 0 3657 +3812 0 3657 +3812 0 3657 +3812 0 3657 +3812 0 3657 +3812 0 3657 +3812 0 3657 +3812 0 3656 +3812 0 3656 +3812 0 3655 +3812 0 3654 +3812 0 3653 +3811 0 3652 +3811 0 3650 +3810 0 3647 +3810 0 3643 +3809 0 3638 +3808 0 3631 +3807 0 3622 +3805 0 3609 +3802 0 3591 +3799 0 3566 +3799 0 3522 +3799 0 3455 +3799 0 3347 +3799 0 3145 +3799 0 2519 +3799 0 0 +3799 3262 0 +3934 3703 0 +4069 3978 0 +4095 4095 0 +3944 0 3763 +3944 0 3763 +3944 0 3763 +3944 0 3763 +3944 0 3763 +3944 0 3763 +3944 0 3762 +3944 0 3762 +3944 0 3762 +3944 0 3761 +3944 0 3761 +3944 0 3760 +3944 0 3758 +3943 0 3757 +3943 0 3755 +3943 0 3752 +3942 0 3748 +3941 0 3742 +3940 0 3735 +3939 0 3725 +3937 0 3711 +3934 0 3692 +3934 0 3659 +3934 0 3611 +3934 0 3537 +3934 0 3414 +3934 0 3172 +3934 0 1863 +3934 0 0 +3934 3366 0 +4069 3824 0 +4095 4095 0 +4076 0 3874 +4076 0 3874 +4076 0 3874 +4076 0 3874 +4076 0 3874 +4076 0 3874 +4076 0 3874 +4076 0 3873 +4076 0 3873 +4076 0 3873 +4076 0 3872 +4076 0 3872 +4076 0 3871 +4076 0 3869 +4075 0 3868 +4075 0 3865 +4075 0 3862 +4074 0 3858 +4073 0 3852 +4072 0 3845 +4071 0 3834 +4069 0 3820 +4069 0 3795 +4069 0 3760 +4069 0 3708 +4069 0 3627 +4069 0 3491 +4069 0 3205 +4069 0 0 +4069 0 0 +4069 3475 0 +4095 3949 0 +4095 0 3990 +4095 0 3990 +4095 0 3990 +4095 0 3990 +4095 0 3990 +4095 0 3990 +4095 0 3990 +4095 0 3990 +4095 0 3989 +4095 0 3989 +4095 0 3989 +4095 0 3988 +4095 0 3988 +4095 0 3986 +4095 0 3985 +4095 0 3983 +4095 0 3981 +4095 0 3978 +4095 0 3974 +4095 0 3968 +4095 0 3960 +4095 0 3949 +4095 0 3930 +4095 0 3904 +4095 0 3867 +4095 0 3812 +4095 0 3726 +4095 0 3577 +4095 0 3246 +4095 0 0 +4095 0 0 +4095 3590 0 +0 2750 3019 +0 2750 3019 +0 2751 3019 +0 2752 3019 +0 2754 3019 +0 2755 3019 +0 2758 3019 +0 2761 3019 +0 2765 3019 +0 2771 3019 +0 2778 3019 +0 2788 3019 +0 2800 3019 +0 2816 3019 +0 2837 3019 +0 2864 3019 +0 2897 3019 +0 2938 3019 +0 2988 3019 +0 3019 2991 +0 3019 2898 +0 3019 2735 +0 3019 2346 +0 3152 0 +0 3284 0 +1977 3416 0 +2745 3548 0 +3080 3680 0 +3320 3812 0 +3520 3944 0 +3696 4076 0 +3859 4095 0 +0 2749 3019 +0 2750 3019 +0 2751 3019 +0 2752 3019 +0 2753 3019 +0 2755 3019 +0 2757 3019 +0 2760 3019 +0 2765 3019 +0 2770 3019 +0 2777 3019 +0 2787 3019 +0 2800 3019 +0 2816 3019 +0 2837 3019 +0 2863 3019 +0 2897 3019 +0 2938 3019 +0 2987 3019 +0 3019 2991 +0 3019 2898 +0 3019 2735 +0 3019 2346 +0 3152 0 +0 3283 0 +1981 3416 0 +2745 3548 0 +3080 3680 0 +3321 3812 0 +3520 3944 0 +3696 4076 0 +3859 4095 0 +0 2748 3019 +0 2749 3019 +0 2750 3019 +0 2751 3019 +0 2752 3019 +0 2754 3019 +0 2757 3019 +0 2760 3019 +0 2764 3019 +0 2770 3019 +0 2777 3019 +0 2787 3019 +0 2799 3019 +0 2816 3019 +0 2836 3019 +0 2863 3019 +0 2896 3019 +0 2938 3019 +0 2987 3019 +0 3019 2991 +0 3019 2898 +0 3019 2736 +0 3019 2347 +0 3152 0 +0 3283 0 +1986 3416 0 +2746 3548 0 +3081 3680 0 +3321 3812 0 +3520 3944 0 +3696 4076 0 +3859 4095 0 +0 2747 3019 +0 2748 3019 +0 2749 3019 +0 2750 3019 +0 2751 3019 +0 2753 3019 +0 2756 3019 +0 2759 3019 +0 2763 3019 +0 2769 3019 +0 2776 3019 +0 2786 3019 +0 2798 3019 +0 2815 3019 +0 2836 3019 +0 2863 3019 +0 2896 3019 +0 2937 3019 +0 2987 3019 +0 3019 2991 +0 3019 2899 +0 3019 2736 +0 3019 2348 +0 3151 0 +0 3283 0 +1992 3416 0 +2747 3548 0 +3081 3680 0 +3321 3812 0 +3520 3944 0 +3696 4076 0 +3859 4095 0 +0 2746 3019 +0 2747 3019 +0 2747 3019 +0 2749 3019 +0 2750 3019 +0 2752 3019 +0 2755 3019 +0 2758 3019 +0 2762 3019 +0 2768 3019 +0 2775 3019 +0 2785 3019 +0 2797 3019 +0 2814 3019 +0 2835 3019 +0 2862 3019 +0 2895 3019 +0 2936 3019 +0 2986 3019 +0 3019 2992 +0 3019 2899 +0 3019 2737 +0 3019 2350 +0 3151 0 +0 3283 0 +2000 3416 0 +2749 3548 0 +3082 3680 0 +3322 3812 0 +3520 3944 0 +3696 4076 0 +3859 4095 0 +0 2744 3019 +0 2745 3019 +0 2746 3019 +0 2747 3019 +0 2749 3019 +0 2751 3019 +0 2753 3019 +0 2756 3019 +0 2761 3019 +0 2766 3019 +0 2774 3019 +0 2784 3019 +0 2796 3019 +0 2813 3019 +0 2834 3019 +0 2860 3019 +0 2894 3019 +0 2935 3019 +0 2985 3019 +0 3019 2992 +0 3019 2900 +0 3019 2738 +0 3019 2352 +0 3151 0 +0 3283 0 +2011 3416 0 +2751 3548 0 +3083 3680 0 +3322 3812 0 +3521 3944 0 +3696 4076 0 +3859 4095 0 +0 2742 3019 +0 2742 3019 +0 2743 3019 +0 2745 3019 +0 2746 3019 +0 2748 3019 +0 2751 3018 +0 2754 3018 +0 2759 3018 +0 2764 3018 +0 2772 3018 +0 2782 3018 +0 2794 3018 +0 2811 3018 +0 2832 3018 +0 2859 3018 +0 2892 3018 +0 2934 3018 +0 2984 3018 +0 3018 2992 +0 3018 2901 +0 3018 2739 +0 3018 2354 +0 3151 0 +0 3283 0 +2026 3415 0 +2754 3548 0 +3084 3680 0 +3323 3812 0 +3521 3944 0 +3697 4076 0 +3859 4095 0 +0 2738 3019 +0 2739 3019 +0 2740 3019 +0 2741 3019 +0 2743 3019 +0 2745 3019 +0 2748 3018 +0 2752 3018 +0 2756 3018 +0 2762 3018 +0 2769 3018 +0 2779 3018 +0 2792 3018 +0 2808 3018 +0 2830 3018 +0 2857 3018 +0 2890 3018 +0 2932 3018 +0 2982 3018 +0 3018 2993 +0 3018 2902 +0 3018 2740 +0 3018 2358 +0 3151 0 +0 3283 0 +2044 3415 0 +2758 3548 0 +3086 3680 0 +3324 3812 0 +3522 3944 0 +3697 4076 0 +3860 4095 0 +0 2734 3019 +0 2735 3019 +0 2735 3019 +0 2737 3019 +0 2738 3019 +0 2741 3019 +0 2744 3018 +0 2747 3018 +0 2752 3018 +0 2758 3018 +0 2766 3018 +0 2776 3018 +0 2789 3018 +0 2805 3018 +0 2827 3018 +0 2854 3018 +0 2888 3018 +0 2930 3018 +0 2980 3018 +0 3018 2995 +0 3018 2903 +0 3018 2742 +0 3018 2362 +0 3151 0 +0 3283 0 +2068 3415 0 +2763 3548 0 +3089 3680 0 +3326 3812 0 +3523 3944 0 +3698 4076 0 +3860 4095 0 +0 2728 3019 +0 2729 3019 +0 2729 3019 +0 2731 3019 +0 2732 3019 +0 2735 3019 +0 2738 3018 +0 2742 3018 +0 2747 3018 +0 2754 3017 +0 2761 3017 +0 2771 3017 +0 2784 3017 +0 2801 3017 +0 2823 3017 +0 2850 3017 +0 2885 3017 +0 2927 3017 +0 2977 3017 +0 3017 2996 +0 3017 2905 +0 3017 2745 +0 3017 2369 +0 3150 0 +0 3282 0 +2098 3415 0 +2770 3547 0 +3092 3680 0 +3328 3812 0 +3524 3944 0 +3699 4076 0 +3861 4095 0 +0 2720 3019 +0 2720 3019 +0 2721 3019 +0 2723 3019 +0 2724 3019 +0 2727 3019 +0 2730 3018 +0 2734 3018 +0 2739 3018 +0 2746 3017 +0 2755 3016 +0 2765 3016 +0 2778 3016 +0 2796 3016 +0 2817 3016 +0 2845 3016 +0 2880 3016 +0 2922 3016 +0 2974 3016 +0 3016 2998 +0 3016 2907 +0 3016 2749 +0 3016 2377 +0 3150 0 +0 3282 0 +2135 3414 0 +2778 3547 0 +3096 3679 0 +3330 3812 0 +3526 3944 0 +3700 4076 0 +3862 4095 0 +0 2708 3019 +0 2709 3019 +0 2710 3019 +0 2712 3019 +0 2713 3019 +0 2716 3019 +0 2719 3018 +0 2723 3018 +0 2728 3018 +0 2735 3017 +0 2745 3016 +0 2757 3015 +0 2770 3015 +0 2788 3015 +0 2810 3015 +0 2838 3015 +0 2873 3015 +0 2916 3015 +0 2968 3015 +0 3015 3001 +0 3015 2911 +0 3015 2753 +0 3015 2387 +0 3149 0 +0 3281 0 +2180 3414 0 +2790 3547 0 +3102 3679 0 +3333 3812 0 +3528 3944 0 +3701 4076 0 +3863 4095 0 +0 2693 3019 +0 2694 3019 +0 2695 3019 +0 2696 3019 +0 2698 3019 +0 2701 3019 +0 2703 3018 +0 2708 3018 +0 2714 3018 +0 2721 3017 +0 2731 3016 +0 2743 3015 +0 2759 3014 +0 2777 3014 +0 2800 3014 +0 2829 3014 +0 2865 3014 +0 2908 3014 +0 2961 3014 +0 3014 3004 +0 3014 2915 +0 3014 2759 +0 3014 2401 +0 3148 0 +0 3280 0 +2234 3414 0 +2804 3546 0 +3110 3679 0 +3338 3811 0 +3531 3944 0 +3703 4076 0 +3864 4095 0 +0 2672 3019 +0 2672 3019 +0 2673 3019 +0 2675 3019 +0 2677 3019 +0 2679 3019 +0 2683 3018 +0 2687 3018 +0 2693 3018 +0 2701 3017 +0 2711 3016 +0 2724 3015 +0 2741 3014 +0 2763 3012 +0 2786 3012 +0 2816 3012 +0 2853 3012 +0 2898 3012 +0 2952 3012 +0 3012 3009 +0 3012 2921 +0 3012 2767 +0 3012 2419 +0 3146 0 +0 3280 0 +2298 3413 0 +2824 3546 0 +3119 3678 0 +3344 3811 0 +3535 3943 0 +3706 4076 0 +3866 4095 0 +0 2641 3019 +0 2642 3019 +0 2643 3019 +0 2645 3019 +0 2647 3019 +0 2649 3019 +0 2653 3018 +0 2658 3018 +0 2664 3018 +0 2672 3017 +0 2683 3016 +0 2697 3015 +0 2715 3014 +0 2738 3012 +0 2767 3010 +0 2798 3010 +0 2836 3010 +0 2883 3010 +0 2939 3010 +0 3004 3010 +0 3010 2928 +0 3010 2778 +0 3010 2441 +0 3144 0 +0 3278 0 +2371 3412 0 +2848 3545 0 +3132 3678 0 +3352 3810 0 +3540 3943 0 +3710 4075 0 +3868 4095 0 +0 2597 3019 +0 2598 3019 +0 2599 3019 +0 2601 3019 +0 2603 3019 +0 2606 3019 +0 2610 3018 +0 2615 3018 +0 2622 3018 +0 2631 3017 +0 2643 3016 +0 2658 3015 +0 2678 3014 +0 2703 3012 +0 2734 3010 +0 2773 3006 +0 2813 3006 +0 2862 3006 +0 2920 3006 +0 2988 3006 +0 3006 2939 +0 3006 2792 +0 3006 2470 +0 3142 0 +0 3276 0 +2453 3410 0 +2879 3544 0 +3149 3677 0 +3362 3810 0 +3547 3943 0 +3714 4075 0 +3872 4095 0 +0 2530 3019 +0 2531 3019 +0 2533 3019 +0 2535 3019 +0 2537 3019 +0 2541 3019 +0 2545 3018 +0 2551 3018 +0 2559 3018 +0 2570 3017 +0 2583 3016 +0 2600 3015 +0 2623 3014 +0 2651 3012 +0 2686 3010 +0 2729 3006 +0 2781 3002 +0 2833 3002 +0 2895 3002 +0 2966 3002 +0 3002 2952 +0 3002 2810 +0 3002 2505 +0 3138 0 +1202 3274 0 +2545 3408 0 +2917 3543 0 +3170 3676 0 +3376 3809 0 +3556 3942 0 +3721 4075 0 +3876 4095 0 +0 2422 3019 +0 2424 3019 +0 2426 3019 +0 2428 3019 +0 2431 3019 +0 2435 3019 +0 2441 3018 +0 2449 3018 +0 2459 3018 +0 2471 3017 +0 2488 3016 +0 2510 3015 +0 2536 3014 +0 2570 3012 +0 2612 3010 +0 2662 3006 +0 2722 3002 +1006 2791 2995 +1006 2858 2995 +1006 2935 2995 +1006 2995 2968 +1006 2995 2833 +1006 2995 2549 +0 3134 1211 +1990 3270 0 +2643 3406 0 +2963 3541 0 +3197 3675 0 +3393 3808 0 +3568 3941 0 +3729 4074 0 +3882 4095 0 +0 2220 3019 +0 2222 3019 +0 2225 3019 +0 2229 3019 +0 2234 3019 +0 2241 3019 +0 2249 3018 +0 2261 3018 +0 2276 3018 +0 2294 3017 +0 2319 3016 +0 2350 3015 +0 2388 3014 +0 2434 3012 +0 2489 3010 +0 2554 3006 +0 2628 3002 +1006 2712 2995 +1930 2804 2987 +1930 2890 2987 +1930 2984 2987 +1930 2987 2862 +1930 2987 2602 +1137 3128 1758 +2327 3266 0 +2749 3402 0 +3018 3538 0 +3231 3673 0 +3415 3807 0 +3583 3940 0 +3740 4073 0 +3890 4095 0 +0 1594 3019 +0 1602 3019 +0 1613 3019 +0 1628 3019 +0 1646 3019 +0 1670 3019 +0 1700 3018 +0 1737 3018 +0 1782 3018 +0 1837 3017 +0 1900 3016 +0 1974 3015 +0 2056 3014 +0 2148 3012 +0 2247 3010 +0 2352 3006 +0 2463 3002 +1006 2579 2995 +1930 2699 2987 +2280 2821 2975 +2280 2929 2975 +2280 2975 2898 +2280 2975 2664 +2064 3119 2061 +2569 3259 1272 +2860 3398 0 +3083 3535 0 +3273 3670 0 +3443 3805 0 +3603 3939 0 +3754 4072 0 +3900 4095 0 +0 0 3019 +0 0 3019 +0 0 3019 +0 0 3019 +0 0 3019 +0 0 3019 +0 0 3018 +0 0 3018 +0 0 3018 +0 0 3017 +0 0 3016 +0 0 3015 +0 0 3014 +0 0 3012 +0 922 3010 +0 1723 3006 +0 2062 3002 +1006 2303 2995 +1930 2503 2987 +2280 2680 2975 +2526 2843 2959 +2526 2959 2942 +2526 2959 2735 +2511 3108 2412 +2768 3251 2194 +2976 3392 1406 +3157 3530 0 +3323 3667 0 +3479 3802 0 +3628 3937 0 +3772 4071 0 +3913 4095 0 +0 0 3019 +0 0 3019 +0 0 3019 +0 0 3019 +0 0 3019 +0 0 3019 +0 0 3018 +0 0 3018 +0 0 3018 +0 0 3017 +0 0 3016 +0 0 3015 +0 0 3014 +0 0 3012 +0 0 3010 +0 0 3006 +1109 0 3002 +1635 1006 2995 +1930 1930 2987 +2280 2377 2975 +2526 2654 2959 +2728 2871 2937 +2728 2937 2816 +2787 3092 2658 +2945 3239 2544 +3095 3383 2326 +3241 3524 1536 +3382 3662 0 +3522 3799 0 +3659 3934 0 +3795 4069 0 +3930 4095 0 +2346 0 3019 +2346 0 3019 +2347 0 3019 +2348 0 3019 +2350 0 3019 +2352 0 3019 +2354 0 3018 +2358 0 3018 +2362 0 3018 +2369 0 3017 +2377 0 3016 +2387 0 3015 +2401 0 3014 +2419 0 3012 +2441 0 3010 +2470 0 3006 +2505 0 3002 +2549 1006 2995 +2602 1930 2987 +2664 2280 2975 +2735 2526 2959 +2816 2728 2937 +2906 2906 2906 +3003 3069 2860 +3107 3223 2790 +3218 3372 2676 +3333 3515 2457 +3452 3656 1663 +3574 3794 0 +3698 3931 0 +3824 4066 0 +3952 4095 0 +2868 0 3152 +2868 0 3152 +2869 0 3152 +2869 0 3151 +2869 0 3151 +2870 0 3151 +2871 0 3151 +2872 0 3151 +2873 0 3151 +2875 0 3150 +2878 0 3150 +2881 0 3149 +2886 0 3148 +2892 0 3146 +2901 0 3144 +2911 0 3142 +2925 0 3138 +2943 0 3134 +2965 1137 3128 +2995 2061 3119 +3031 2412 3108 +3074 2658 3092 +3069 2860 3003 +3069 2948 2860 +3223 3206 2790 +3325 3372 2676 +3418 3515 2457 +3519 3656 1663 +3626 3794 0 +3738 3931 0 +3855 4066 0 +3976 4095 0 +3162 0 3284 +3162 0 3283 +3163 0 3283 +3163 0 3283 +3163 0 3283 +3163 0 3283 +3164 0 3283 +3164 0 3283 +3165 0 3283 +3166 0 3282 +3168 0 3282 +3169 0 3281 +3172 0 3280 +3175 0 3280 +3180 0 3278 +3185 0 3276 +3193 0 3274 +3203 0 3270 +3216 0 3266 +3233 1272 3259 +3251 2194 3248 +3239 2544 3193 +3223 2790 3107 +3223 2790 2918 +3223 2999 2790 +3372 3294 2676 +3512 3515 2457 +3595 3656 1663 +3687 3794 0 +3787 3931 0 +3893 4066 0 +4005 4095 0 +3387 0 3416 +3387 0 3416 +3387 0 3416 +3387 0 3416 +3387 0 3416 +3387 0 3416 +3387 0 3415 +3388 0 3415 +3388 0 3415 +3389 0 3415 +3390 0 3414 +3391 0 3414 +3393 0 3414 +3395 0 3413 +3397 0 3412 +3401 0 3410 +3406 0 3408 +3406 0 3400 +3402 0 3384 +3398 0 3362 +3392 1406 3331 +3383 2326 3286 +3372 2676 3218 +3372 2676 3077 +3372 2676 2774 +3372 3060 2676 +3515 3391 2457 +3656 3629 1663 +3759 3794 0 +3845 3931 0 +3940 4066 0 +4042 4095 0 +3548 0 3516 +3548 0 3516 +3548 0 3516 +3548 0 3516 +3548 0 3516 +3548 0 3516 +3548 0 3515 +3548 0 3515 +3548 0 3514 +3547 0 3513 +3547 0 3512 +3547 0 3511 +3546 0 3509 +3546 0 3506 +3545 0 3502 +3544 0 3497 +3543 0 3490 +3541 0 3480 +3538 0 3467 +3535 0 3449 +3530 0 3423 +3524 1536 3387 +3515 2457 3333 +3515 2457 3227 +3515 2457 3032 +3515 2457 2459 +3515 3130 2457 +3656 3494 1663 +3794 3745 0 +3913 3931 0 +3995 4066 0 +4087 4095 0 +3680 0 3599 +3680 0 3599 +3680 0 3599 +3680 0 3599 +3680 0 3599 +3680 0 3599 +3680 0 3598 +3680 0 3598 +3680 0 3597 +3680 0 3597 +3679 0 3596 +3679 0 3595 +3679 0 3593 +3678 0 3590 +3678 0 3587 +3677 0 3583 +3676 0 3577 +3675 0 3569 +3673 0 3558 +3670 0 3543 +3667 0 3523 +3662 0 3494 +3656 1663 3452 +3656 1663 3373 +3656 1663 3240 +3656 1663 2965 +3656 2289 1663 +3656 3210 1663 +3794 3603 0 +3931 3863 0 +4060 4066 0 +4095 4095 0 +3812 0 3691 +3812 0 3691 +3812 0 3690 +3812 0 3690 +3812 0 3690 +3812 0 3690 +3812 0 3690 +3812 0 3690 +3812 0 3689 +3812 0 3689 +3812 0 3688 +3812 0 3687 +3811 0 3685 +3811 0 3683 +3810 0 3680 +3810 0 3677 +3809 0 3672 +3808 0 3666 +3807 0 3657 +3805 0 3646 +3802 0 3629 +3799 0 3606 +3794 0 3574 +3794 0 3515 +3794 0 3421 +3794 0 3256 +3794 0 2856 +3794 1884 0 +3794 3298 0 +3931 3717 0 +4066 3985 0 +4095 4095 0 +3944 0 3790 +3944 0 3790 +3944 0 3790 +3944 0 3790 +3944 0 3789 +3944 0 3789 +3944 0 3789 +3944 0 3789 +3944 0 3788 +3944 0 3788 +3944 0 3787 +3944 0 3786 +3944 0 3785 +3943 0 3784 +3943 0 3781 +3943 0 3779 +3942 0 3775 +3941 0 3770 +3940 0 3763 +3939 0 3754 +3937 0 3741 +3934 0 3723 +3931 0 3698 +3931 0 3654 +3931 0 3587 +3931 0 3479 +3931 0 3277 +3931 0 2650 +3931 0 0 +3931 3395 0 +4066 3835 0 +4095 4095 0 +4076 0 3895 +4076 0 3895 +4076 0 3895 +4076 0 3895 +4076 0 3895 +4076 0 3895 +4076 0 3895 +4076 0 3895 +4076 0 3894 +4076 0 3894 +4076 0 3893 +4076 0 3892 +4076 0 3891 +4076 0 3890 +4075 0 3889 +4075 0 3887 +4075 0 3884 +4074 0 3880 +4073 0 3874 +4072 0 3867 +4071 0 3857 +4069 0 3843 +4066 0 3824 +4066 0 3791 +4066 0 3743 +4066 0 3669 +4066 0 3546 +4066 0 3303 +4066 0 1985 +4066 0 0 +4066 3498 0 +4095 3957 0 +4095 0 4007 +4095 0 4006 +4095 0 4006 +4095 0 4006 +4095 0 4006 +4095 0 4006 +4095 0 4006 +4095 0 4006 +4095 0 4006 +4095 0 4005 +4095 0 4005 +4095 0 4005 +4095 0 4004 +4095 0 4003 +4095 0 4002 +4095 0 4000 +4095 0 3998 +4095 0 3994 +4095 0 3990 +4095 0 3984 +4095 0 3977 +4095 0 3966 +4095 0 3952 +4095 0 3927 +4095 0 3892 +4095 0 3840 +4095 0 3759 +4095 0 3623 +4095 0 3337 +4095 0 0 +4095 0 0 +4095 3608 0 +0 2882 3152 +0 2883 3152 +0 2883 3152 +0 2884 3152 +0 2885 3152 +0 2886 3152 +0 2888 3152 +0 2890 3152 +0 2893 3152 +0 2898 3152 +0 2903 3152 +0 2911 3152 +0 2920 3152 +0 2933 3152 +0 2949 3152 +0 2970 3152 +0 2996 3152 +0 3030 3152 +0 3071 3152 +0 3120 3152 +0 3152 3123 +0 3152 3031 +0 3152 2868 +0 3152 2478 +0 3284 0 +0 3416 0 +2104 3548 0 +2876 3680 0 +3211 3812 0 +3452 3944 0 +3651 4076 0 +3828 4095 0 +0 2881 3152 +0 2882 3152 +0 2883 3152 +0 2883 3152 +0 2885 3152 +0 2886 3152 +0 2888 3152 +0 2890 3152 +0 2893 3152 +0 2897 3152 +0 2903 3152 +0 2910 3152 +0 2920 3152 +0 2932 3152 +0 2949 3152 +0 2970 3152 +0 2996 3152 +0 3029 3152 +0 3070 3152 +0 3120 3152 +0 3152 3123 +0 3152 3031 +0 3152 2868 +0 3152 2478 +0 3283 0 +0 3416 0 +2107 3548 0 +2877 3680 0 +3212 3812 0 +3452 3944 0 +3651 4076 0 +3828 4095 0 +0 2881 3152 +0 2881 3152 +0 2882 3152 +0 2883 3152 +0 2884 3152 +0 2885 3152 +0 2887 3152 +0 2890 3152 +0 2893 3152 +0 2897 3152 +0 2903 3152 +0 2910 3152 +0 2919 3152 +0 2932 3152 +0 2948 3152 +0 2969 3152 +0 2996 3152 +0 3029 3152 +0 3070 3152 +0 3120 3152 +0 3152 3123 +0 3152 3031 +0 3152 2869 +0 3152 2479 +0 3283 0 +0 3416 0 +2111 3548 0 +2877 3680 0 +3212 3812 0 +3453 3944 0 +3651 4076 0 +3828 4095 0 +0 2880 3152 +0 2881 3152 +0 2881 3152 +0 2882 3151 +0 2883 3151 +0 2885 3151 +0 2886 3151 +0 2889 3151 +0 2892 3151 +0 2896 3151 +0 2902 3151 +0 2909 3151 +0 2919 3151 +0 2932 3151 +0 2948 3151 +0 2969 3151 +0 2995 3151 +0 3029 3151 +0 3070 3151 +0 3119 3151 +0 3151 3123 +0 3151 3031 +0 3151 2869 +0 3151 2480 +0 3283 0 +0 3416 0 +2115 3548 0 +2878 3680 0 +3213 3812 0 +3453 3944 0 +3652 4076 0 +3828 4095 0 +0 2879 3152 +0 2880 3152 +0 2880 3152 +0 2881 3151 +0 2883 3151 +0 2884 3151 +0 2886 3151 +0 2888 3151 +0 2891 3151 +0 2895 3151 +0 2901 3151 +0 2908 3151 +0 2918 3151 +0 2931 3151 +0 2947 3151 +0 2968 3151 +0 2995 3151 +0 3028 3151 +0 3069 3151 +0 3119 3151 +0 3151 3123 +0 3151 3031 +0 3151 2869 +0 3151 2481 +0 3283 0 +0 3416 0 +2122 3548 0 +2879 3680 0 +3213 3812 0 +3453 3944 0 +3652 4076 0 +3828 4095 0 +0 2878 3152 +0 2878 3152 +0 2879 3152 +0 2880 3151 +0 2881 3151 +0 2883 3151 +0 2885 3151 +0 2887 3151 +0 2890 3151 +0 2895 3151 +0 2900 3151 +0 2907 3151 +0 2917 3151 +0 2930 3151 +0 2946 3151 +0 2967 3151 +0 2994 3151 +0 3027 3151 +0 3068 3151 +0 3118 3151 +0 3151 3124 +0 3151 3032 +0 3151 2870 +0 3151 2482 +0 3283 0 +0 3416 0 +2130 3548 0 +2881 3680 0 +3214 3812 0 +3454 3944 0 +3652 4076 0 +3829 4095 0 +0 2876 3152 +0 2877 3152 +0 2877 3152 +0 2878 3151 +0 2879 3151 +0 2881 3151 +0 2883 3151 +0 2885 3151 +0 2889 3151 +0 2893 3151 +0 2898 3151 +0 2906 3151 +0 2916 3151 +0 2928 3151 +0 2945 3151 +0 2966 3151 +0 2993 3151 +0 3026 3151 +0 3067 3151 +0 3117 3151 +0 3151 3124 +0 3151 3032 +0 3151 2871 +0 3151 2484 +0 3283 0 +0 3415 0 +2141 3548 0 +2883 3680 0 +3215 3812 0 +3454 3944 0 +3653 4076 0 +3829 4095 0 +0 2873 3152 +0 2874 3152 +0 2875 3152 +0 2876 3151 +0 2877 3151 +0 2879 3151 +0 2881 3151 +0 2883 3151 +0 2887 3151 +0 2891 3151 +0 2896 3151 +0 2904 3151 +0 2914 3151 +0 2927 3151 +0 2943 3151 +0 2964 3151 +0 2991 3151 +0 3025 3151 +0 3066 3151 +0 3116 3151 +0 3151 3125 +0 3151 3033 +0 3151 2872 +0 3151 2487 +0 3283 0 +0 3415 0 +2156 3548 0 +2886 3680 0 +3216 3812 0 +3455 3944 0 +3653 4076 0 +3829 4095 0 +0 2870 3152 +0 2871 3152 +0 2871 3152 +0 2872 3151 +0 2873 3151 +0 2875 3151 +0 2877 3151 +0 2880 3151 +0 2884 3151 +0 2888 3151 +0 2894 3151 +0 2902 3151 +0 2911 3151 +0 2924 3151 +0 2941 3151 +0 2962 3151 +0 2989 3151 +0 3023 3151 +0 3064 3151 +0 3115 3151 +0 3151 3126 +0 3151 3034 +0 3151 2873 +0 3151 2490 +0 3283 0 +0 3415 0 +2174 3548 0 +2890 3680 0 +3218 3812 0 +3456 3944 0 +3654 4076 0 +3830 4095 0 +0 2866 3152 +0 2866 3152 +0 2867 3152 +0 2868 3151 +0 2869 3151 +0 2871 3151 +0 2873 3151 +0 2876 3151 +0 2880 3151 +0 2885 3150 +0 2891 3150 +0 2898 3150 +0 2908 3150 +0 2921 3150 +0 2938 3150 +0 2959 3150 +0 2986 3150 +0 3020 3150 +0 3062 3150 +0 3112 3150 +0 3150 3127 +0 3150 3036 +0 3150 2875 +0 3150 2495 +0 3282 0 +0 3415 0 +2198 3547 0 +2895 3680 0 +3221 3812 0 +3458 3944 0 +3655 4076 0 +3830 4095 0 +0 2860 3152 +0 2860 3152 +0 2861 3152 +0 2862 3151 +0 2863 3151 +0 2865 3151 +0 2867 3151 +0 2870 3151 +0 2874 3151 +0 2879 3150 +0 2886 3150 +0 2894 3150 +0 2904 3150 +0 2917 3150 +0 2933 3150 +0 2955 3150 +0 2982 3150 +0 3017 3150 +0 3059 3150 +0 3110 3150 +0 3150 3128 +0 3150 3038 +0 3150 2878 +0 3150 2501 +0 3282 0 +0 3414 0 +2228 3547 0 +2901 3679 0 +3224 3812 0 +3459 3944 0 +3656 4076 0 +3831 4095 0 +0 2851 3152 +0 2852 3152 +0 2853 3152 +0 2854 3151 +0 2855 3151 +0 2857 3151 +0 2859 3151 +0 2862 3151 +0 2866 3151 +0 2871 3150 +0 2878 3150 +0 2887 3149 +0 2898 3149 +0 2911 3149 +0 2928 3149 +0 2950 3149 +0 2977 3149 +0 3012 3149 +0 3055 3149 +0 3106 3149 +0 3149 3131 +0 3149 3040 +0 3149 2881 +0 3149 2509 +0 3281 0 +0 3414 0 +2265 3547 0 +2910 3679 0 +3228 3812 0 +3462 3944 0 +3658 4076 0 +3832 4095 0 +0 2840 3152 +0 2841 3152 +0 2842 3152 +0 2842 3151 +0 2844 3151 +0 2845 3151 +0 2848 3151 +0 2851 3151 +0 2855 3151 +0 2860 3150 +0 2868 3150 +0 2877 3149 +0 2889 3148 +0 2903 3148 +0 2920 3148 +0 2942 3148 +0 2970 3148 +0 3005 3148 +0 3049 3148 +0 3100 3148 +0 3148 3133 +0 3148 3043 +0 3148 2886 +0 3148 2520 +0 3280 0 +0 3414 0 +2311 3546 0 +2922 3679 0 +3234 3811 0 +3466 3944 0 +3660 4076 0 +3834 4095 0 +0 2825 3152 +0 2825 3152 +0 2826 3152 +0 2827 3151 +0 2829 3151 +0 2830 3151 +0 2833 3151 +0 2836 3151 +0 2840 3151 +0 2846 3150 +0 2853 3150 +0 2863 3149 +0 2875 3148 +0 2892 3146 +0 2910 3146 +0 2932 3146 +0 2961 3146 +0 2997 3146 +0 3041 3146 +0 3093 3146 +0 3146 3137 +0 3146 3047 +0 3146 2892 +0 3146 2533 +0 3280 0 +0 3413 0 +2365 3546 0 +2936 3678 0 +3241 3811 0 +3470 3943 0 +3663 4076 0 +3836 4095 0 +0 2803 3152 +0 2804 3152 +0 2805 3152 +0 2806 3151 +0 2807 3151 +0 2809 3151 +0 2812 3151 +0 2815 3151 +0 2819 3151 +0 2825 3150 +0 2833 3150 +0 2843 3149 +0 2856 3148 +0 2873 3146 +0 2895 3144 +0 2919 3144 +0 2948 3144 +0 2985 3144 +0 3030 3144 +0 3084 3144 +0 3144 3141 +0 3144 3053 +0 3144 2901 +0 3144 2551 +0 3278 0 +0 3412 0 +2429 3545 0 +2955 3678 0 +3251 3810 0 +3476 3943 0 +3667 4075 0 +3838 4095 0 +0 2773 3152 +0 2773 3152 +0 2774 3152 +0 2775 3151 +0 2777 3151 +0 2779 3151 +0 2782 3151 +0 2785 3151 +0 2790 3151 +0 2796 3150 +0 2804 3150 +0 2815 3149 +0 2829 3148 +0 2847 3146 +0 2870 3144 +0 2900 3142 +0 2931 3142 +0 2969 3142 +0 3015 3142 +0 3071 3142 +0 3136 3142 +0 3142 3061 +0 3142 2911 +0 3142 2573 +0 3276 0 +0 3410 0 +2502 3544 0 +2980 3677 0 +3264 3810 0 +3484 3943 0 +3672 4075 0 +3842 4095 0 +0 2729 3152 +0 2729 3152 +0 2730 3152 +0 2732 3151 +0 2733 3151 +0 2735 3151 +0 2738 3151 +0 2742 3151 +0 2747 3151 +0 2754 3150 +0 2763 3150 +0 2775 3149 +0 2790 3148 +0 2810 3146 +0 2835 3144 +0 2867 3142 +0 2906 3138 +0 2946 3138 +0 2995 3138 +0 3053 3138 +0 3120 3138 +0 3138 3071 +0 3138 2925 +0 3138 2602 +0 3274 0 +0 3408 0 +2585 3543 0 +3010 3676 0 +3281 3809 0 +3494 3942 0 +3679 4075 0 +3847 4095 0 +0 2662 3152 +0 2663 3152 +0 2664 3152 +0 2665 3151 +0 2667 3151 +0 2670 3151 +0 2673 3151 +0 2678 3151 +0 2684 3151 +0 2691 3150 +0 2702 3150 +0 2715 3149 +0 2733 3148 +0 2755 3146 +0 2783 3144 +0 2818 3142 +0 2861 3138 +0 2913 3134 +0 2965 3134 +0 3027 3134 +0 3098 3134 +0 3134 3084 +0 3134 2943 +0 3134 2638 +0 3270 0 +1325 3406 0 +2676 3541 0 +3048 3675 0 +3302 3808 0 +3507 3941 0 +3688 4074 0 +3853 4095 0 +0 2554 3152 +0 2555 3152 +0 2556 3152 +0 2558 3151 +0 2560 3151 +0 2564 3151 +0 2568 3151 +0 2573 3151 +0 2581 3151 +0 2591 3150 +0 2604 3150 +0 2620 3149 +0 2642 3148 +0 2669 3146 +0 2703 3144 +0 2744 3142 +0 2795 3138 +0 2854 3134 +1137 2923 3128 +1137 2991 3128 +1137 3067 3128 +1137 3128 3101 +1137 3128 2965 +1137 3128 2681 +0 3266 1375 +2121 3402 0 +2775 3538 0 +3095 3673 0 +3329 3807 0 +3525 3940 0 +3700 4073 0 +3861 4095 0 +0 2352 3152 +0 2353 3152 +0 2355 3152 +0 2358 3151 +0 2362 3151 +0 2367 3151 +0 2373 3151 +0 2382 3151 +0 2394 3151 +0 2408 3150 +0 2427 3150 +0 2452 3149 +0 2482 3148 +0 2521 3146 +0 2566 3144 +0 2622 3142 +0 2687 3138 +0 2761 3134 +1137 2845 3128 +2061 2936 3119 +2061 3022 3119 +2061 3116 3119 +2061 3119 2995 +2061 3119 2734 +1272 3259 1899 +2458 3398 0 +2881 3535 0 +3150 3670 0 +3363 3805 0 +3547 3939 0 +3715 4072 0 +3872 4095 0 +0 1720 3152 +0 1726 3152 +0 1735 3152 +0 1746 3151 +0 1760 3151 +0 1779 3151 +0 1802 3151 +0 1832 3151 +0 1869 3151 +0 1915 3150 +0 1969 3150 +0 2033 3149 +0 2106 3148 +0 2189 3146 +0 2280 3144 +0 2379 3142 +0 2484 3138 +0 2596 3134 +1137 2712 3128 +2061 2831 3119 +2412 2954 3108 +2412 3061 3108 +2412 3108 3031 +2412 3108 2796 +2194 3251 2195 +2701 3392 1406 +2992 3530 0 +3215 3667 0 +3405 3802 0 +3575 3937 0 +3735 4071 0 +3886 4095 0 +0 0 3152 +0 0 3152 +0 0 3152 +0 0 3151 +0 0 3151 +0 0 3151 +0 0 3151 +0 0 3151 +0 0 3151 +0 0 3150 +0 0 3150 +0 0 3149 +0 0 3148 +0 0 3146 +0 0 3144 +0 1068 3142 +0 1857 3138 +0 2195 3134 +1137 2436 3128 +2061 2636 3119 +2412 2813 3108 +2658 2976 3092 +2658 3092 3074 +2658 3092 2867 +2642 3239 2544 +2900 3383 2326 +3108 3524 1536 +3289 3662 0 +3455 3799 0 +3611 3934 0 +3760 4069 0 +3904 4095 0 +0 0 3152 +0 0 3152 +0 0 3152 +0 0 3151 +0 0 3151 +0 0 3151 +0 0 3151 +0 0 3151 +0 0 3151 +0 0 3150 +0 0 3150 +0 0 3149 +0 0 3148 +0 0 3146 +0 0 3144 +0 0 3142 +0 0 3138 +1211 0 3134 +1758 1137 3128 +2061 2064 3119 +2412 2511 3108 +2658 2787 3092 +2860 3003 3069 +2860 3069 2948 +2918 3223 2790 +3077 3372 2676 +3227 3515 2457 +3373 3656 1663 +3515 3794 0 +3654 3931 0 +3791 4066 0 +3927 4095 0 +2478 0 3152 +2478 0 3152 +2479 0 3152 +2480 0 3151 +2481 0 3151 +2482 0 3151 +2484 0 3151 +2487 0 3151 +2490 0 3151 +2495 0 3150 +2501 0 3150 +2509 0 3149 +2520 0 3148 +2533 0 3146 +2551 0 3144 +2573 0 3142 +2602 0 3138 +2638 0 3134 +2681 1137 3128 +2734 2061 3119 +2796 2412 3108 +2867 2658 3092 +2948 2860 3069 +3038 3038 3038 +3135 3201 2992 +3239 3356 2922 +3350 3504 2808 +3465 3648 2590 +3584 3788 1799 +3706 3926 0 +3830 4063 0 +3956 4095 0 +2999 0 3284 +2999 0 3283 +2999 0 3283 +2999 0 3283 +3000 0 3283 +3000 0 3283 +3001 0 3283 +3002 0 3283 +3003 0 3283 +3005 0 3282 +3006 0 3282 +3009 0 3281 +3013 0 3280 +3017 0 3280 +3023 0 3278 +3032 0 3276 +3042 0 3274 +3056 0 3270 +3074 0 3266 +3097 1272 3259 +3126 2194 3251 +3162 2544 3239 +3206 2790 3223 +3201 2992 3135 +3201 3080 2992 +3356 3338 2922 +3457 3504 2808 +3550 3648 2590 +3651 3788 1799 +3758 3926 0 +3870 4063 0 +3987 4095 0 +3294 0 3416 +3294 0 3416 +3294 0 3416 +3294 0 3416 +3295 0 3416 +3295 0 3416 +3295 0 3415 +3296 0 3415 +3296 0 3415 +3297 0 3415 +3298 0 3414 +3299 0 3414 +3301 0 3414 +3304 0 3413 +3307 0 3412 +3311 0 3410 +3317 0 3408 +3325 0 3406 +3335 0 3402 +3348 0 3398 +3365 1406 3392 +3383 2326 3380 +3372 2676 3325 +3356 2922 3239 +3356 2922 3051 +3356 3132 2922 +3504 3426 2808 +3644 3648 2590 +3728 3788 1799 +3820 3926 0 +3919 4063 0 +4025 4095 0 +3519 0 3548 +3519 0 3548 +3519 0 3548 +3519 0 3548 +3519 0 3548 +3519 0 3548 +3519 0 3548 +3520 0 3548 +3520 0 3548 +3520 0 3547 +3521 0 3547 +3522 0 3547 +3523 0 3546 +3525 0 3546 +3526 0 3545 +3529 0 3544 +3533 0 3543 +3538 0 3541 +3538 0 3532 +3535 0 3516 +3530 0 3495 +3524 1536 3463 +3515 2457 3418 +3504 2808 3350 +3504 2808 3209 +3504 2808 2907 +3504 3192 2808 +3648 3523 2590 +3788 3761 1799 +3891 3926 0 +3977 4063 0 +4072 4095 0 +3680 0 3649 +3680 0 3649 +3680 0 3649 +3680 0 3649 +3680 0 3648 +3680 0 3648 +3680 0 3648 +3680 0 3648 +3680 0 3647 +3680 0 3646 +3679 0 3646 +3679 0 3644 +3679 0 3643 +3678 0 3641 +3678 0 3638 +3677 0 3634 +3676 0 3629 +3675 0 3622 +3673 0 3612 +3670 0 3599 +3667 0 3581 +3662 0 3555 +3656 1663 3519 +3648 2590 3465 +3648 2590 3360 +3648 2590 3165 +3648 2590 2592 +3648 3262 2590 +3788 3626 1799 +3926 3877 0 +4045 4063 0 +4095 4095 0 +3812 0 3732 +3812 0 3731 +3812 0 3731 +3812 0 3731 +3812 0 3731 +3812 0 3731 +3812 0 3731 +3812 0 3730 +3812 0 3730 +3812 0 3729 +3812 0 3729 +3812 0 3728 +3811 0 3727 +3811 0 3725 +3810 0 3722 +3810 0 3719 +3809 0 3715 +3808 0 3709 +3807 0 3701 +3805 0 3690 +3802 0 3676 +3799 0 3655 +3794 0 3626 +3788 1799 3584 +3788 1799 3505 +3788 1799 3372 +3788 1799 3097 +3788 2422 1799 +3788 3342 1799 +3926 3735 0 +4063 3995 0 +4095 4095 0 +3944 0 3823 +3944 0 3823 +3944 0 3823 +3944 0 3822 +3944 0 3822 +3944 0 3822 +3944 0 3822 +3944 0 3822 +3944 0 3822 +3944 0 3821 +3944 0 3820 +3944 0 3820 +3944 0 3819 +3943 0 3817 +3943 0 3815 +3943 0 3813 +3942 0 3809 +3941 0 3805 +3940 0 3798 +3939 0 3790 +3937 0 3777 +3934 0 3761 +3931 0 3738 +3926 0 3706 +3926 0 3647 +3926 0 3553 +3926 0 3388 +3926 0 2988 +3926 2023 0 +3926 3430 0 +4063 3849 0 +4095 4095 0 +4076 0 3922 +4076 0 3922 +4076 0 3921 +4076 0 3921 +4076 0 3921 +4076 0 3921 +4076 0 3921 +4076 0 3921 +4076 0 3921 +4076 0 3921 +4076 0 3920 +4076 0 3919 +4076 0 3918 +4076 0 3917 +4075 0 3916 +4075 0 3913 +4075 0 3911 +4074 0 3907 +4073 0 3902 +4072 0 3895 +4071 0 3886 +4069 0 3873 +4066 0 3855 +4063 0 3830 +4063 0 3786 +4063 0 3719 +4063 0 3611 +4063 0 3409 +4063 0 2781 +4063 0 0 +4063 3527 0 +4095 3968 0 +4095 0 4027 +4095 0 4027 +4095 0 4027 +4095 0 4027 +4095 0 4027 +4095 0 4027 +4095 0 4027 +4095 0 4027 +4095 0 4027 +4095 0 4026 +4095 0 4026 +4095 0 4026 +4095 0 4025 +4095 0 4024 +4095 0 4023 +4095 0 4021 +4095 0 4019 +4095 0 4016 +4095 0 4012 +4095 0 4006 +4095 0 3999 +4095 0 3989 +4095 0 3976 +4095 0 3956 +4095 0 3923 +4095 0 3875 +4095 0 3801 +4095 0 3679 +4095 0 3436 +4095 0 2137 +4095 0 0 +4095 3630 0 +0 3014 3284 +0 3014 3284 +0 3014 3284 +0 3015 3284 +0 3016 3284 +0 3017 3284 +0 3018 3284 +0 3020 3284 +0 3022 3284 +0 3025 3284 +0 3030 3284 +0 3035 3284 +0 3043 3284 +0 3052 3284 +0 3065 3284 +0 3081 3284 +0 3102 3284 +0 3128 3284 +0 3162 3284 +0 3203 3284 +0 3252 3284 +0 3284 3254 +0 3284 3162 +0 3284 2999 +0 3284 2609 +0 3416 0 +0 3548 0 +2237 3680 0 +3008 3812 0 +3344 3944 0 +3584 4076 0 +3784 4095 0 +0 3014 3284 +0 3014 3283 +0 3014 3283 +0 3015 3283 +0 3016 3283 +0 3017 3283 +0 3018 3283 +0 3020 3283 +0 3022 3283 +0 3025 3283 +0 3029 3283 +0 3035 3283 +0 3042 3283 +0 3052 3283 +0 3065 3283 +0 3081 3283 +0 3102 3283 +0 3128 3283 +0 3162 3283 +0 3203 3283 +0 3252 3283 +0 3283 3254 +0 3283 3162 +0 3283 2999 +0 3283 2609 +0 3416 0 +0 3548 0 +2239 3680 0 +3009 3812 0 +3344 3944 0 +3584 4076 0 +3784 4095 0 +0 3013 3284 +0 3014 3283 +0 3014 3283 +0 3014 3283 +0 3015 3283 +0 3016 3283 +0 3018 3283 +0 3019 3283 +0 3022 3283 +0 3025 3283 +0 3029 3283 +0 3035 3283 +0 3042 3283 +0 3052 3283 +0 3064 3283 +0 3081 3283 +0 3101 3283 +0 3128 3283 +0 3161 3283 +0 3202 3283 +0 3252 3283 +0 3283 3255 +0 3283 3163 +0 3283 2999 +0 3283 2610 +0 3416 0 +0 3548 0 +2242 3680 0 +3009 3812 0 +3344 3944 0 +3585 4076 0 +3784 4095 0 +0 3012 3284 +0 3013 3283 +0 3013 3283 +0 3014 3283 +0 3015 3283 +0 3016 3283 +0 3017 3283 +0 3019 3283 +0 3021 3283 +0 3025 3283 +0 3029 3283 +0 3034 3283 +0 3042 3283 +0 3051 3283 +0 3064 3283 +0 3080 3283 +0 3101 3283 +0 3128 3283 +0 3161 3283 +0 3202 3283 +0 3252 3283 +0 3283 3255 +0 3283 3163 +0 3283 2999 +0 3283 2611 +0 3416 0 +0 3548 0 +2246 3680 0 +3010 3812 0 +3344 3944 0 +3585 4076 0 +3784 4095 0 +0 3012 3284 +0 3012 3283 +0 3013 3283 +0 3013 3283 +0 3014 3283 +0 3015 3283 +0 3016 3283 +0 3018 3283 +0 3021 3283 +0 3024 3283 +0 3028 3283 +0 3034 3283 +0 3041 3283 +0 3051 3283 +0 3063 3283 +0 3080 3283 +0 3101 3283 +0 3127 3283 +0 3160 3283 +0 3201 3283 +0 3251 3283 +0 3283 3255 +0 3283 3163 +0 3283 3000 +0 3283 2612 +0 3416 0 +0 3548 0 +2251 3680 0 +3011 3812 0 +3345 3944 0 +3585 4076 0 +3784 4095 0 +0 3011 3284 +0 3011 3283 +0 3011 3283 +0 3012 3283 +0 3013 3283 +0 3014 3283 +0 3016 3283 +0 3018 3283 +0 3020 3283 +0 3023 3283 +0 3027 3283 +0 3033 3283 +0 3040 3283 +0 3050 3283 +0 3062 3283 +0 3079 3283 +0 3100 3283 +0 3127 3283 +0 3160 3283 +0 3201 3283 +0 3251 3283 +0 3283 3255 +0 3283 3163 +0 3283 3000 +0 3283 2613 +0 3416 0 +0 3548 0 +2257 3680 0 +3012 3812 0 +3346 3944 0 +3585 4076 0 +3784 4095 0 +0 3009 3284 +0 3010 3283 +0 3010 3283 +0 3011 3283 +0 3012 3283 +0 3013 3283 +0 3015 3283 +0 3016 3283 +0 3019 3283 +0 3022 3283 +0 3026 3283 +0 3032 3283 +0 3039 3283 +0 3049 3283 +0 3062 3283 +0 3078 3283 +0 3099 3283 +0 3126 3283 +0 3159 3283 +0 3200 3283 +0 3250 3283 +0 3283 3256 +0 3283 3164 +0 3283 3001 +0 3283 2614 +0 3415 0 +0 3548 0 +2266 3680 0 +3014 3812 0 +3346 3944 0 +3586 4076 0 +3784 4095 0 +0 3008 3284 +0 3008 3283 +0 3008 3283 +0 3009 3283 +0 3010 3283 +0 3011 3283 +0 3013 3283 +0 3015 3283 +0 3017 3283 +0 3021 3283 +0 3025 3283 +0 3031 3283 +0 3038 3283 +0 3047 3283 +0 3060 3283 +0 3077 3283 +0 3098 3283 +0 3125 3283 +0 3158 3283 +0 3199 3283 +0 3249 3283 +0 3283 3256 +0 3283 3164 +0 3283 3002 +0 3283 2616 +0 3415 0 +0 3548 0 +2277 3680 0 +3016 3812 0 +3347 3944 0 +3586 4076 0 +3785 4095 0 +0 3005 3284 +0 3005 3283 +0 3006 3283 +0 3007 3283 +0 3008 3283 +0 3009 3283 +0 3010 3283 +0 3013 3283 +0 3015 3283 +0 3018 3283 +0 3023 3283 +0 3029 3283 +0 3036 3283 +0 3046 3283 +0 3059 3283 +0 3075 3283 +0 3096 3283 +0 3123 3283 +0 3157 3283 +0 3198 3283 +0 3248 3283 +0 3283 3257 +0 3283 3165 +0 3283 3003 +0 3283 2619 +0 3415 0 +0 3548 0 +2291 3680 0 +3019 3812 0 +3349 3944 0 +3587 4076 0 +3786 4095 0 +0 3002 3284 +0 3002 3283 +0 3002 3283 +0 3003 3283 +0 3004 3283 +0 3005 3283 +0 3007 3283 +0 3009 3283 +0 3012 3283 +0 3016 3282 +0 3020 3282 +0 3026 3282 +0 3033 3282 +0 3043 3282 +0 3056 3282 +0 3073 3282 +0 3094 3282 +0 3121 3282 +0 3155 3282 +0 3196 3282 +0 3247 3282 +0 3282 3257 +0 3282 3166 +0 3282 3005 +0 3282 2622 +0 3415 0 +0 3547 0 +2310 3680 0 +3023 3812 0 +3351 3944 0 +3588 4076 0 +3786 4095 0 +0 2997 3284 +0 2998 3283 +0 2998 3283 +0 2999 3283 +0 3000 3283 +0 3001 3283 +0 3003 3283 +0 3005 3283 +0 3008 3283 +0 3012 3282 +0 3017 3282 +0 3023 3282 +0 3030 3282 +0 3040 3282 +0 3053 3282 +0 3070 3282 +0 3091 3282 +0 3118 3282 +0 3152 3282 +0 3194 3282 +0 3244 3282 +0 3282 3259 +0 3282 3168 +0 3282 3006 +0 3282 2627 +0 3414 0 +0 3547 0 +2333 3679 0 +3027 3812 0 +3353 3944 0 +3590 4076 0 +3787 4095 0 +0 2991 3284 +0 2992 3283 +0 2992 3283 +0 2993 3283 +0 2994 3283 +0 2995 3283 +0 2997 3283 +0 2999 3283 +0 3002 3283 +0 3006 3282 +0 3011 3282 +0 3018 3281 +0 3025 3281 +0 3035 3281 +0 3049 3281 +0 3065 3281 +0 3087 3281 +0 3114 3281 +0 3149 3281 +0 3191 3281 +0 3242 3281 +0 3281 3260 +0 3281 3169 +0 3281 3009 +0 3281 2633 +0 3414 0 +0 3547 0 +2363 3679 0 +3034 3812 0 +3356 3944 0 +3592 4076 0 +3788 4095 0 +0 2983 3284 +0 2983 3283 +0 2984 3283 +0 2985 3283 +0 2986 3283 +0 2987 3283 +0 2988 3283 +0 2991 3283 +0 2994 3283 +0 2998 3282 +0 3003 3282 +0 3010 3281 +0 3019 3280 +0 3029 3280 +0 3043 3280 +0 3060 3280 +0 3082 3280 +0 3109 3280 +0 3144 3280 +0 3186 3280 +0 3238 3280 +0 3280 3262 +0 3280 3172 +0 3280 3013 +0 3280 2641 +0 3414 0 +0 3546 0 +2400 3679 0 +3043 3811 0 +3361 3944 0 +3594 4076 0 +3790 4095 0 +0 2972 3284 +0 2972 3283 +0 2973 3283 +0 2973 3283 +0 2974 3283 +0 2976 3283 +0 2977 3283 +0 2980 3283 +0 2983 3283 +0 2987 3282 +0 2992 3282 +0 2999 3281 +0 3009 3280 +0 3021 3280 +0 3034 3280 +0 3052 3280 +0 3074 3280 +0 3102 3280 +0 3138 3280 +0 3180 3280 +0 3233 3280 +0 3280 3265 +0 3280 3175 +0 3280 3017 +0 3280 2651 +0 3413 0 +0 3546 0 +2445 3678 0 +3054 3811 0 +3366 3943 0 +3597 4076 0 +3792 4095 0 +0 2956 3284 +0 2957 3283 +0 2957 3283 +0 2958 3283 +0 2959 3283 +0 2960 3283 +0 2962 3283 +0 2965 3283 +0 2968 3283 +0 2972 3282 +0 2977 3282 +0 2985 3281 +0 2995 3280 +0 3007 3280 +0 3024 3278 +0 3041 3278 +0 3064 3278 +0 3093 3278 +0 3129 3278 +0 3173 3278 +0 3225 3278 +0 3278 3269 +0 3278 3180 +0 3278 3023 +0 3278 2665 +0 3412 0 +0 3545 0 +2499 3678 0 +3069 3810 0 +3374 3943 0 +3602 4075 0 +3795 4095 0 +0 2935 3284 +0 2935 3283 +0 2936 3283 +0 2936 3283 +0 2938 3283 +0 2939 3283 +0 2941 3283 +0 2943 3283 +0 2947 3283 +0 2951 3282 +0 2957 3282 +0 2965 3281 +0 2975 3280 +0 2988 3280 +0 3005 3278 +0 3027 3276 +0 3050 3276 +0 3080 3276 +0 3117 3276 +0 3162 3276 +0 3216 3276 +0 3276 3273 +0 3276 3185 +0 3276 3032 +0 3276 2683 +0 3410 0 +0 3544 0 +2562 3677 0 +3088 3810 0 +3384 3943 0 +3608 4075 0 +3799 4095 0 +0 2904 3284 +0 2905 3283 +0 2905 3283 +0 2906 3283 +0 2907 3283 +0 2909 3283 +0 2911 3283 +0 2914 3283 +0 2917 3283 +0 2922 3282 +0 2928 3282 +0 2936 3281 +0 2947 3280 +0 2961 3280 +0 2979 3278 +0 3002 3276 +0 3031 3274 +0 3062 3274 +0 3100 3274 +0 3147 3274 +0 3203 3274 +0 3268 3274 +0 3274 3193 +0 3274 3042 +0 3274 2706 +0 3408 0 +0 3543 0 +2636 3676 0 +3112 3809 0 +3396 3942 0 +3616 4075 0 +3804 4095 0 +0 2860 3284 +0 2860 3283 +0 2861 3283 +0 2862 3283 +0 2863 3283 +0 2865 3283 +0 2867 3283 +0 2870 3283 +0 2874 3283 +0 2879 3282 +0 2886 3282 +0 2895 3281 +0 2907 3280 +0 2922 3280 +0 2942 3278 +0 2967 3276 +0 2998 3274 +0 3037 3270 +0 3078 3270 +0 3126 3270 +0 3184 3270 +0 3252 3270 +0 3270 3203 +0 3270 3056 +0 3270 2734 +0 3406 0 +0 3541 0 +2718 3675 0 +3143 3808 0 +3413 3941 0 +3626 4074 0 +3811 4095 0 +0 2793 3284 +0 2793 3283 +0 2794 3283 +0 2795 3283 +0 2797 3283 +0 2799 3283 +0 2801 3283 +0 2805 3283 +0 2809 3283 +0 2815 3282 +0 2823 3282 +0 2833 3281 +0 2847 3280 +0 2865 3280 +0 2886 3278 +0 2915 3276 +0 2950 3274 +0 2993 3270 +0 3045 3266 +0 3097 3266 +0 3159 3266 +0 3230 3266 +0 3266 3216 +0 3266 3074 +0 3266 2770 +0 3402 0 +1477 3538 0 +2809 3673 0 +3181 3807 0 +3434 3940 0 +3640 4073 0 +3820 4095 0 +0 2684 3284 +0 2685 3283 +0 2686 3283 +0 2688 3283 +0 2690 3283 +0 2692 3283 +0 2695 3283 +0 2700 3283 +0 2705 3283 +0 2713 3282 +0 2723 3282 +0 2735 3281 +0 2752 3280 +0 2773 3280 +0 2800 3278 +0 2834 3276 +0 2876 3274 +0 2926 3270 +0 2986 3266 +1272 3055 3259 +1272 3122 3259 +1272 3199 3259 +1272 3259 3233 +1272 3259 3097 +1272 3259 2813 +0 3398 1484 +2256 3535 0 +2908 3670 0 +3227 3805 0 +3461 3939 0 +3657 4072 0 +3832 4095 0 +0 2481 3284 +0 2482 3283 +0 2484 3283 +0 2486 3283 +0 2489 3283 +0 2493 3283 +0 2498 3283 +0 2504 3283 +0 2513 3283 +0 2524 3282 +0 2539 3282 +0 2558 3281 +0 2583 3280 +0 2613 3280 +0 2651 3278 +0 2698 3276 +0 2753 3274 +0 2818 3270 +0 2893 3266 +1272 2976 3259 +2194 3069 3251 +2194 3154 3251 +2194 3248 3251 +2194 3251 3126 +2194 3251 2866 +1406 3392 2025 +2593 3530 0 +3014 3667 0 +3282 3802 0 +3495 3937 0 +3679 4071 0 +3847 4095 0 +0 1844 3284 +0 1849 3283 +0 1856 3283 +0 1864 3283 +0 1875 3283 +0 1890 3283 +0 1908 3283 +0 1932 3283 +0 1962 3283 +0 1999 3282 +0 2045 3282 +0 2100 3281 +0 2164 3280 +0 2237 3280 +0 2320 3278 +0 2411 3276 +0 2510 3274 +0 2616 3270 +0 2727 3266 +1272 2843 3259 +2194 2963 3251 +2544 3085 3239 +2544 3193 3239 +2544 3239 3162 +2544 3239 2928 +2328 3383 2326 +2833 3524 1536 +3125 3662 0 +3347 3799 0 +3537 3934 0 +3708 4069 0 +3867 4095 0 +0 0 3284 +0 0 3283 +0 0 3283 +0 0 3283 +0 0 3283 +0 0 3283 +0 0 3283 +0 0 3283 +0 0 3283 +0 0 3282 +0 0 3282 +0 0 3281 +0 0 3280 +0 0 3280 +0 0 3278 +0 0 3276 +0 1202 3274 +0 1990 3270 +0 2327 3266 +1272 2569 3259 +2194 2768 3251 +2544 2945 3239 +2790 3107 3223 +2790 3223 3206 +2790 3223 2999 +2774 3372 2676 +3032 3515 2457 +3240 3656 1663 +3421 3794 0 +3587 3931 0 +3743 4066 0 +3892 4095 0 +0 0 3284 +0 0 3283 +0 0 3283 +0 0 3283 +0 0 3283 +0 0 3283 +0 0 3283 +0 0 3283 +0 0 3283 +0 0 3282 +0 0 3282 +0 0 3281 +0 0 3280 +0 0 3280 +0 0 3278 +0 0 3276 +0 0 3274 +0 0 3270 +1375 0 3266 +1899 1272 3259 +2195 2194 3251 +2544 2642 3239 +2790 2918 3223 +2992 3135 3201 +2992 3201 3080 +3051 3356 2922 +3209 3504 2808 +3360 3648 2590 +3505 3788 1799 +3647 3926 0 +3786 4063 0 +3923 4095 0 +2609 0 3284 +2609 0 3283 +2610 0 3283 +2611 0 3283 +2612 0 3283 +2613 0 3283 +2614 0 3283 +2616 0 3283 +2619 0 3283 +2622 0 3282 +2627 0 3282 +2633 0 3281 +2641 0 3280 +2651 0 3280 +2665 0 3278 +2683 0 3276 +2706 0 3274 +2734 0 3270 +2770 0 3266 +2813 1272 3259 +2866 2194 3251 +2928 2544 3239 +2999 2790 3223 +3080 2992 3201 +3170 3170 3170 +3267 3333 3124 +3372 3488 3054 +3482 3636 2940 +3597 3780 2721 +3716 3920 1928 +3838 4058 0 +3962 4095 0 +3132 0 3416 +3132 0 3416 +3132 0 3416 +3132 0 3416 +3132 0 3416 +3133 0 3416 +3133 0 3415 +3134 0 3415 +3135 0 3415 +3136 0 3415 +3137 0 3414 +3139 0 3414 +3142 0 3414 +3145 0 3413 +3150 0 3412 +3156 0 3410 +3164 0 3408 +3175 0 3406 +3189 0 3402 +3206 0 3398 +3230 1406 3392 +3258 2326 3383 +3294 2676 3372 +3338 2922 3356 +3333 3124 3267 +3333 3212 3124 +3488 3470 3054 +3589 3636 2940 +3682 3780 2721 +3783 3920 1928 +3890 4058 0 +4002 4095 0 +3426 0 3548 +3426 0 3548 +3427 0 3548 +3427 0 3548 +3427 0 3548 +3427 0 3548 +3427 0 3548 +3428 0 3548 +3428 0 3548 +3429 0 3547 +3429 0 3547 +3430 0 3547 +3432 0 3546 +3434 0 3546 +3436 0 3545 +3440 0 3544 +3444 0 3543 +3450 0 3541 +3457 0 3538 +3467 0 3535 +3480 0 3530 +3497 1536 3524 +3515 2457 3512 +3504 2808 3457 +3488 3054 3372 +3488 3054 3183 +3488 3264 3054 +3636 3558 2940 +3776 3780 2721 +3860 3920 1928 +3952 4058 0 +4051 4095 0 +3651 0 3680 +3651 0 3680 +3651 0 3680 +3651 0 3680 +3651 0 3680 +3651 0 3680 +3651 0 3680 +3652 0 3680 +3652 0 3680 +3652 0 3680 +3653 0 3679 +3653 0 3679 +3654 0 3679 +3655 0 3678 +3657 0 3678 +3659 0 3677 +3662 0 3676 +3665 0 3675 +3670 0 3673 +3670 0 3664 +3667 0 3648 +3662 0 3626 +3656 1663 3595 +3648 2590 3550 +3636 2940 3482 +3636 2940 3341 +3636 2940 3038 +3636 3324 2940 +3780 3655 2721 +3920 3893 1928 +4023 4058 0 +4095 4095 0 +3812 0 3781 +3812 0 3781 +3812 0 3781 +3812 0 3781 +3812 0 3781 +3812 0 3781 +3812 0 3781 +3812 0 3780 +3812 0 3780 +3812 0 3779 +3812 0 3778 +3812 0 3777 +3811 0 3777 +3811 0 3775 +3810 0 3773 +3810 0 3770 +3809 0 3766 +3808 0 3761 +3807 0 3754 +3805 0 3744 +3802 0 3731 +3799 0 3713 +3794 0 3687 +3788 1799 3651 +3780 2721 3597 +3780 2721 3492 +3780 2721 3296 +3780 2721 2722 +3780 3394 2721 +3920 3758 1928 +4058 4008 0 +4095 4095 0 +3944 0 3864 +3944 0 3864 +3944 0 3863 +3944 0 3863 +3944 0 3863 +3944 0 3863 +3944 0 3863 +3944 0 3863 +3944 0 3863 +3944 0 3862 +3944 0 3862 +3944 0 3861 +3944 0 3860 +3943 0 3859 +3943 0 3857 +3943 0 3854 +3942 0 3851 +3941 0 3847 +3940 0 3841 +3939 0 3833 +3937 0 3822 +3934 0 3808 +3931 0 3787 +3926 0 3758 +3920 1928 3716 +3920 1928 3637 +3920 1928 3504 +3920 1928 3229 +3920 2556 1928 +3920 3474 1928 +4058 3867 0 +4095 4095 0 +4076 0 3955 +4076 0 3955 +4076 0 3955 +4076 0 3955 +4076 0 3955 +4076 0 3954 +4076 0 3954 +4076 0 3954 +4076 0 3954 +4076 0 3953 +4076 0 3953 +4076 0 3953 +4076 0 3952 +4076 0 3950 +4075 0 3949 +4075 0 3947 +4075 0 3945 +4074 0 3941 +4073 0 3937 +4072 0 3930 +4071 0 3921 +4069 0 3910 +4066 0 3893 +4063 0 3870 +4058 0 3838 +4058 0 3779 +4058 0 3685 +4058 0 3520 +4058 0 3119 +4058 2157 0 +4058 3562 0 +4095 3982 0 +4095 0 4054 +4095 0 4054 +4095 0 4054 +4095 0 4054 +4095 0 4054 +4095 0 4054 +4095 0 4054 +4095 0 4053 +4095 0 4053 +4095 0 4053 +4095 0 4053 +4095 0 4052 +4095 0 4051 +4095 0 4051 +4095 0 4049 +4095 0 4048 +4095 0 4046 +4095 0 4043 +4095 0 4039 +4095 0 4034 +4095 0 4027 +4095 0 4018 +4095 0 4005 +4095 0 3987 +4095 0 3962 +4095 0 3918 +4095 0 3851 +4095 0 3743 +4095 0 3541 +4095 0 2915 +4095 0 0 +4095 3659 0 +0 3146 3416 +0 3146 3416 +0 3147 3416 +0 3147 3416 +0 3147 3416 +0 3148 3416 +0 3149 3416 +0 3151 3416 +0 3152 3416 +0 3155 3416 +0 3158 3416 +0 3162 3416 +0 3168 3416 +0 3175 3416 +0 3184 3416 +0 3197 3416 +0 3213 3416 +0 3234 3416 +0 3261 3416 +0 3294 3416 +0 3335 3416 +0 3385 3416 +0 3416 3387 +0 3416 3294 +0 3416 3132 +0 3416 2741 +0 3548 0 +0 3680 0 +2367 3812 0 +3140 3944 0 +3475 4076 0 +3716 4095 0 +0 3146 3416 +0 3146 3416 +0 3146 3416 +0 3147 3416 +0 3147 3416 +0 3148 3416 +0 3149 3416 +0 3151 3416 +0 3152 3416 +0 3154 3416 +0 3158 3416 +0 3162 3416 +0 3168 3416 +0 3175 3416 +0 3184 3416 +0 3197 3416 +0 3213 3416 +0 3234 3416 +0 3261 3416 +0 3294 3416 +0 3335 3416 +0 3385 3416 +0 3416 3387 +0 3416 3294 +0 3416 3132 +0 3416 2741 +0 3548 0 +0 3680 0 +2369 3812 0 +3140 3944 0 +3475 4076 0 +3717 4095 0 +0 3145 3416 +0 3146 3416 +0 3146 3416 +0 3147 3416 +0 3147 3416 +0 3148 3416 +0 3149 3416 +0 3150 3416 +0 3152 3416 +0 3154 3416 +0 3157 3416 +0 3162 3416 +0 3167 3416 +0 3175 3416 +0 3184 3416 +0 3197 3416 +0 3213 3416 +0 3234 3416 +0 3260 3416 +0 3294 3416 +0 3335 3416 +0 3384 3416 +0 3416 3387 +0 3416 3294 +0 3416 3132 +0 3416 2742 +0 3548 0 +0 3680 0 +2371 3812 0 +3140 3944 0 +3476 4076 0 +3717 4095 0 +0 3145 3416 +0 3145 3416 +0 3146 3416 +0 3146 3416 +0 3147 3416 +0 3147 3416 +0 3148 3416 +0 3150 3416 +0 3151 3416 +0 3154 3416 +0 3157 3416 +0 3161 3416 +0 3167 3416 +0 3174 3416 +0 3184 3416 +0 3196 3416 +0 3213 3416 +0 3234 3416 +0 3260 3416 +0 3293 3416 +0 3335 3416 +0 3384 3416 +0 3416 3387 +0 3416 3294 +0 3416 3132 +0 3416 2742 +0 3548 0 +0 3680 0 +2374 3812 0 +3141 3944 0 +3476 4076 0 +3717 4095 0 +0 3144 3416 +0 3145 3416 +0 3145 3416 +0 3146 3416 +0 3146 3416 +0 3147 3416 +0 3148 3416 +0 3149 3416 +0 3151 3416 +0 3154 3416 +0 3157 3416 +0 3161 3416 +0 3166 3416 +0 3174 3416 +0 3184 3416 +0 3196 3416 +0 3212 3416 +0 3233 3416 +0 3260 3416 +0 3293 3416 +0 3334 3416 +0 3384 3416 +0 3416 3387 +0 3416 3295 +0 3416 3132 +0 3416 2743 +0 3548 0 +0 3680 0 +2377 3812 0 +3142 3944 0 +3476 4076 0 +3717 4095 0 +0 3144 3416 +0 3144 3416 +0 3144 3416 +0 3145 3416 +0 3145 3416 +0 3146 3416 +0 3147 3416 +0 3149 3416 +0 3151 3416 +0 3153 3416 +0 3156 3416 +0 3160 3416 +0 3166 3416 +0 3173 3416 +0 3183 3416 +0 3196 3416 +0 3212 3416 +0 3233 3416 +0 3259 3416 +0 3293 3416 +0 3334 3416 +0 3384 3416 +0 3416 3387 +0 3416 3295 +0 3416 3133 +0 3416 2744 +0 3548 0 +0 3680 0 +2382 3812 0 +3143 3944 0 +3477 4076 0 +3717 4095 0 +0 3143 3416 +0 3143 3416 +0 3143 3416 +0 3144 3416 +0 3144 3416 +0 3145 3416 +0 3147 3415 +0 3148 3415 +0 3150 3415 +0 3152 3415 +0 3155 3415 +0 3160 3415 +0 3165 3415 +0 3173 3415 +0 3182 3415 +0 3195 3415 +0 3211 3415 +0 3232 3415 +0 3259 3415 +0 3292 3415 +0 3333 3415 +0 3383 3415 +0 3415 3387 +0 3415 3295 +0 3415 3133 +0 3415 2745 +0 3548 0 +0 3680 0 +2389 3812 0 +3144 3944 0 +3477 4076 0 +3718 4095 0 +0 3141 3416 +0 3141 3416 +0 3142 3416 +0 3142 3416 +0 3143 3416 +0 3144 3416 +0 3145 3415 +0 3147 3415 +0 3149 3415 +0 3151 3415 +0 3154 3415 +0 3158 3415 +0 3164 3415 +0 3171 3415 +0 3181 3415 +0 3194 3415 +0 3210 3415 +0 3231 3415 +0 3258 3415 +0 3291 3415 +0 3333 3415 +0 3382 3415 +0 3415 3388 +0 3415 3296 +0 3415 3134 +0 3415 2746 +0 3548 0 +0 3680 0 +2397 3812 0 +3145 3944 0 +3478 4076 0 +3718 4095 0 +0 3139 3416 +0 3140 3416 +0 3140 3416 +0 3141 3416 +0 3141 3416 +0 3142 3416 +0 3144 3415 +0 3145 3415 +0 3147 3415 +0 3150 3415 +0 3153 3415 +0 3157 3415 +0 3163 3415 +0 3170 3415 +0 3180 3415 +0 3192 3415 +0 3209 3415 +0 3230 3415 +0 3257 3415 +0 3290 3415 +0 3331 3415 +0 3381 3415 +0 3415 3388 +0 3415 3296 +0 3415 3135 +0 3415 2748 +0 3548 0 +0 3680 0 +2408 3812 0 +3147 3944 0 +3479 4076 0 +3719 4095 0 +0 3137 3416 +0 3137 3416 +0 3138 3416 +0 3138 3416 +0 3139 3416 +0 3140 3416 +0 3141 3415 +0 3143 3415 +0 3145 3415 +0 3147 3415 +0 3151 3415 +0 3155 3415 +0 3161 3415 +0 3168 3415 +0 3178 3415 +0 3191 3415 +0 3207 3415 +0 3228 3415 +0 3255 3415 +0 3289 3415 +0 3330 3415 +0 3380 3415 +0 3415 3389 +0 3415 3297 +0 3415 3136 +0 3415 2751 +0 3547 0 +0 3680 0 +2422 3812 0 +3151 3944 0 +3480 4076 0 +3720 4095 0 +0 3134 3416 +0 3134 3416 +0 3134 3416 +0 3135 3416 +0 3135 3416 +0 3136 3416 +0 3138 3415 +0 3139 3415 +0 3141 3415 +0 3144 3415 +0 3148 3414 +0 3152 3414 +0 3158 3414 +0 3165 3414 +0 3175 3414 +0 3188 3414 +0 3205 3414 +0 3226 3414 +0 3253 3414 +0 3287 3414 +0 3329 3414 +0 3379 3414 +0 3414 3390 +0 3414 3298 +0 3414 3137 +0 3414 2754 +0 3547 0 +0 3679 0 +2441 3812 0 +3154 3944 0 +3482 4076 0 +3721 4095 0 +0 3129 3416 +0 3129 3416 +0 3130 3416 +0 3130 3416 +0 3131 3416 +0 3132 3416 +0 3133 3415 +0 3135 3415 +0 3137 3415 +0 3140 3415 +0 3144 3414 +0 3149 3414 +0 3155 3414 +0 3162 3414 +0 3172 3414 +0 3185 3414 +0 3202 3414 +0 3223 3414 +0 3250 3414 +0 3284 3414 +0 3326 3414 +0 3376 3414 +0 3414 3391 +0 3414 3299 +0 3414 3139 +0 3414 2759 +0 3547 0 +0 3679 0 +2465 3812 0 +3159 3944 0 +3485 4076 0 +3722 4095 0 +0 3123 3416 +0 3123 3416 +0 3124 3416 +0 3124 3416 +0 3125 3416 +0 3126 3416 +0 3127 3415 +0 3129 3415 +0 3131 3415 +0 3134 3415 +0 3138 3414 +0 3143 3414 +0 3150 3414 +0 3158 3414 +0 3168 3414 +0 3181 3414 +0 3198 3414 +0 3219 3414 +0 3247 3414 +0 3281 3414 +0 3323 3414 +0 3374 3414 +0 3414 3393 +0 3414 3301 +0 3414 3142 +0 3414 2765 +0 3546 0 +0 3679 0 +2494 3811 0 +3166 3944 0 +3488 4076 0 +3724 4095 0 +0 3115 3416 +0 3115 3416 +0 3115 3416 +0 3116 3416 +0 3117 3416 +0 3118 3416 +0 3119 3415 +0 3121 3415 +0 3123 3415 +0 3126 3415 +0 3130 3414 +0 3135 3414 +0 3142 3414 +0 3151 3413 +0 3162 3413 +0 3175 3413 +0 3192 3413 +0 3214 3413 +0 3242 3413 +0 3276 3413 +0 3319 3413 +0 3370 3413 +0 3413 3395 +0 3413 3304 +0 3413 3145 +0 3413 2773 +0 3546 0 +0 3678 0 +2531 3811 0 +3175 3943 0 +3492 4076 0 +3727 4095 0 +0 3104 3416 +0 3104 3416 +0 3104 3416 +0 3105 3416 +0 3106 3416 +0 3106 3416 +0 3108 3415 +0 3110 3415 +0 3112 3415 +0 3115 3415 +0 3119 3414 +0 3125 3414 +0 3132 3414 +0 3141 3413 +0 3154 3412 +0 3167 3412 +0 3184 3412 +0 3206 3412 +0 3234 3412 +0 3270 3412 +0 3313 3412 +0 3365 3412 +0 3412 3397 +0 3412 3307 +0 3412 3150 +0 3412 2784 +0 3545 0 +0 3678 0 +2576 3810 0 +3186 3943 0 +3498 4075 0 +3730 4095 0 +0 3088 3416 +0 3088 3416 +0 3089 3416 +0 3089 3416 +0 3090 3416 +0 3091 3416 +0 3093 3415 +0 3094 3415 +0 3097 3415 +0 3100 3415 +0 3104 3414 +0 3110 3414 +0 3117 3414 +0 3127 3413 +0 3140 3412 +0 3156 3410 +0 3174 3410 +0 3196 3410 +0 3225 3410 +0 3261 3410 +0 3305 3410 +0 3358 3410 +0 3410 3401 +0 3410 3311 +0 3410 3156 +0 3410 2797 +0 3544 0 +0 3677 0 +2631 3810 0 +3201 3943 0 +3505 4075 0 +3735 4095 0 +0 3067 3416 +0 3067 3416 +0 3067 3416 +0 3068 3416 +0 3069 3416 +0 3070 3416 +0 3071 3415 +0 3073 3415 +0 3076 3415 +0 3079 3415 +0 3083 3414 +0 3089 3414 +0 3097 3414 +0 3107 3413 +0 3120 3412 +0 3137 3410 +0 3159 3408 +0 3183 3408 +0 3212 3408 +0 3249 3408 +0 3294 3408 +0 3348 3408 +0 3408 3406 +0 3408 3317 +0 3408 3164 +0 3408 2815 +0 3543 0 +0 3676 0 +2694 3809 0 +3220 3942 0 +3515 4075 0 +3741 4095 0 +0 3036 3416 +0 3036 3416 +0 3037 3416 +0 3038 3416 +0 3038 3416 +0 3039 3416 +0 3041 3415 +0 3043 3415 +0 3046 3415 +0 3049 3415 +0 3054 3414 +0 3060 3414 +0 3069 3414 +0 3079 3413 +0 3093 3412 +0 3111 3410 +0 3134 3408 +0 3164 3406 +0 3194 3406 +0 3233 3406 +0 3279 3406 +0 3335 3406 +0 3400 3406 +0 3406 3325 +0 3406 3175 +0 3406 2838 +0 3541 0 +0 3675 0 +2767 3808 0 +3244 3941 0 +3528 4074 0 +3748 4095 0 +0 2992 3416 +0 2992 3416 +0 2992 3416 +0 2993 3416 +0 2994 3416 +0 2996 3416 +0 2997 3415 +0 2999 3415 +0 3002 3415 +0 3006 3415 +0 3011 3414 +0 3018 3414 +0 3027 3414 +0 3039 3413 +0 3055 3412 +0 3074 3410 +0 3099 3408 +0 3131 3406 +0 3170 3402 +0 3210 3402 +0 3259 3402 +0 3317 3402 +0 3384 3402 +0 3402 3335 +0 3402 3189 +0 3402 2866 +0 3538 0 +0 3673 0 +2850 3807 0 +3275 3940 0 +3545 4073 0 +3759 4095 0 +0 2925 3416 +0 2925 3416 +0 2926 3416 +0 2927 3416 +0 2928 3416 +0 2929 3416 +0 2931 3415 +0 2934 3415 +0 2937 3415 +0 2942 3415 +0 2947 3414 +0 2956 3414 +0 2966 3414 +0 2979 3413 +0 2997 3412 +0 3019 3410 +0 3047 3408 +0 3082 3406 +0 3125 3402 +0 3177 3398 +0 3230 3398 +0 3291 3398 +0 3362 3398 +0 3398 3348 +0 3398 3206 +0 3398 2902 +0 3535 0 +1603 3670 0 +2941 3805 0 +3313 3939 0 +3566 4072 0 +3772 4095 0 +0 2816 3416 +0 2817 3416 +0 2817 3416 +0 2818 3416 +0 2820 3416 +0 2822 3416 +0 2824 3415 +0 2827 3415 +0 2832 3415 +0 2837 3415 +0 2845 3414 +0 2855 3414 +0 2867 3414 +0 2884 3413 +0 2906 3412 +0 2933 3410 +0 2966 3408 +0 3008 3406 +0 3059 3402 +0 3118 3398 +1406 3187 3392 +1406 3255 3392 +1406 3331 3392 +1406 3392 3365 +1406 3392 3230 +1406 3392 2945 +0 3530 1621 +2388 3667 0 +3040 3802 0 +3359 3937 0 +3593 4071 0 +3790 4095 0 +0 2613 3416 +0 2614 3416 +0 2615 3416 +0 2617 3416 +0 2619 3416 +0 2621 3416 +0 2625 3415 +0 2630 3415 +0 2637 3415 +0 2646 3415 +0 2657 3414 +0 2672 3414 +0 2691 3414 +0 2715 3413 +0 2746 3412 +0 2784 3410 +0 2830 3408 +0 2886 3406 +0 2951 3402 +0 3025 3398 +1406 3108 3392 +2326 3201 3383 +2326 3286 3383 +2326 3380 3383 +2326 3383 3258 +2326 3383 2998 +1536 3524 2158 +2724 3662 0 +3145 3799 0 +3414 3934 0 +3627 4069 0 +3812 4095 0 +0 1977 3416 +0 1981 3416 +0 1986 3416 +0 1992 3416 +0 2000 3416 +0 2011 3416 +0 2026 3415 +0 2044 3415 +0 2068 3415 +0 2098 3415 +0 2135 3414 +0 2180 3414 +0 2234 3414 +0 2298 3413 +0 2371 3412 +0 2453 3410 +0 2545 3408 +0 2643 3406 +0 2749 3402 +0 2860 3398 +1406 2976 3392 +2326 3095 3383 +2676 3218 3372 +2676 3325 3372 +2676 3372 3294 +2676 3372 3060 +2459 3515 2457 +2965 3656 1663 +3256 3794 0 +3479 3931 0 +3669 4066 0 +3840 4095 0 +0 0 3416 +0 0 3416 +0 0 3416 +0 0 3416 +0 0 3416 +0 0 3416 +0 0 3415 +0 0 3415 +0 0 3415 +0 0 3415 +0 0 3414 +0 0 3414 +0 0 3414 +0 0 3413 +0 0 3412 +0 0 3410 +0 0 3408 +0 1325 3406 +0 2121 3402 +0 2458 3398 +1406 2701 3392 +2326 2900 3383 +2676 3077 3372 +2922 3239 3356 +2922 3356 3338 +2922 3356 3132 +2907 3504 2808 +3165 3648 2590 +3372 3788 1799 +3553 3926 0 +3719 4063 0 +3875 4095 0 +0 0 3416 +0 0 3416 +0 0 3416 +0 0 3416 +0 0 3416 +0 0 3416 +0 0 3415 +0 0 3415 +0 0 3415 +0 0 3415 +0 0 3414 +0 0 3414 +0 0 3414 +0 0 3413 +0 0 3412 +0 0 3410 +0 0 3408 +0 0 3406 +0 0 3402 +1484 0 3398 +2025 1406 3392 +2326 2328 3383 +2676 2774 3372 +2922 3051 3356 +3124 3267 3333 +3124 3333 3212 +3183 3488 3054 +3341 3636 2940 +3492 3780 2721 +3637 3920 1928 +3779 4058 0 +3918 4095 0 +2741 0 3416 +2741 0 3416 +2742 0 3416 +2742 0 3416 +2743 0 3416 +2744 0 3416 +2745 0 3415 +2746 0 3415 +2748 0 3415 +2751 0 3415 +2754 0 3414 +2759 0 3414 +2765 0 3414 +2773 0 3413 +2784 0 3412 +2797 0 3410 +2815 0 3408 +2838 0 3406 +2866 0 3402 +2902 0 3398 +2945 1406 3392 +2998 2326 3383 +3060 2676 3372 +3132 2922 3356 +3212 3124 3333 +3302 3302 3302 +3399 3466 3256 +3504 3620 3186 +3614 3768 3072 +3729 3912 2854 +3848 4052 2063 +3970 4095 0 +3264 0 3548 +3264 0 3548 +3264 0 3548 +3264 0 3548 +3264 0 3548 +3265 0 3548 +3265 0 3548 +3265 0 3548 +3266 0 3548 +3267 0 3547 +3268 0 3547 +3269 0 3547 +3271 0 3546 +3274 0 3546 +3278 0 3545 +3282 0 3544 +3288 0 3543 +3296 0 3541 +3307 0 3538 +3321 0 3535 +3339 0 3530 +3362 1536 3524 +3391 2457 3515 +3426 2808 3504 +3470 3054 3488 +3466 3256 3399 +3466 3344 3256 +3620 3603 3186 +3721 3768 3072 +3814 3912 2854 +3915 4052 2063 +4022 4095 0 +3558 0 3680 +3558 0 3680 +3559 0 3680 +3559 0 3680 +3559 0 3680 +3559 0 3680 +3559 0 3680 +3559 0 3680 +3560 0 3680 +3560 0 3680 +3561 0 3679 +3562 0 3679 +3563 0 3679 +3564 0 3678 +3566 0 3678 +3568 0 3677 +3572 0 3676 +3576 0 3675 +3582 0 3673 +3589 0 3670 +3599 0 3667 +3612 0 3662 +3629 1663 3656 +3648 2590 3644 +3636 2940 3589 +3620 3186 3504 +3620 3186 3315 +3620 3396 3186 +3768 3691 3072 +3908 3912 2854 +3992 4052 2063 +4084 4095 0 +3783 0 3812 +3783 0 3812 +3783 0 3812 +3783 0 3812 +3783 0 3812 +3783 0 3812 +3783 0 3812 +3784 0 3812 +3784 0 3812 +3784 0 3812 +3784 0 3812 +3785 0 3812 +3785 0 3811 +3786 0 3811 +3787 0 3810 +3789 0 3810 +3791 0 3809 +3794 0 3808 +3797 0 3807 +3802 0 3805 +3802 0 3796 +3799 0 3781 +3794 0 3759 +3788 1799 3728 +3780 2721 3682 +3768 3072 3614 +3768 3072 3473 +3768 3072 3171 +3768 3456 3072 +3912 3787 2854 +4052 4025 2063 +4095 4095 0 +3944 0 3913 +3944 0 3913 +3944 0 3913 +3944 0 3913 +3944 0 3913 +3944 0 3913 +3944 0 3913 +3944 0 3912 +3944 0 3912 +3944 0 3912 +3944 0 3911 +3944 0 3910 +3944 0 3910 +3943 0 3909 +3943 0 3907 +3943 0 3905 +3942 0 3902 +3941 0 3898 +3940 0 3893 +3939 0 3886 +3937 0 3876 +3934 0 3863 +3931 0 3845 +3926 0 3820 +3920 1928 3783 +3912 2854 3729 +3912 2854 3624 +3912 2854 3428 +3912 2854 2854 +3912 3526 2854 +4052 3890 2063 +4095 4095 0 +4076 0 3996 +4076 0 3996 +4076 0 3996 +4076 0 3995 +4076 0 3995 +4076 0 3995 +4076 0 3995 +4076 0 3995 +4076 0 3995 +4076 0 3995 +4076 0 3994 +4076 0 3994 +4076 0 3993 +4076 0 3992 +4075 0 3991 +4075 0 3989 +4075 0 3986 +4074 0 3983 +4073 0 3979 +4072 0 3973 +4071 0 3965 +4069 0 3954 +4066 0 3940 +4063 0 3919 +4058 0 3890 +4052 2063 3848 +4052 2063 3769 +4052 2063 3636 +4052 2063 3361 +4052 2689 2063 +4052 3606 2063 +4095 4000 0 +4095 0 4087 +4095 0 4087 +4095 0 4087 +4095 0 4087 +4095 0 4087 +4095 0 4087 +4095 0 4087 +4095 0 4087 +4095 0 4086 +4095 0 4086 +4095 0 4086 +4095 0 4085 +4095 0 4085 +4095 0 4084 +4095 0 4083 +4095 0 4082 +4095 0 4080 +4095 0 4077 +4095 0 4073 +4095 0 4069 +4095 0 4062 +4095 0 4054 +4095 0 4042 +4095 0 4025 +4095 0 4002 +4095 0 3970 +4095 0 3911 +4095 0 3818 +4095 0 3653 +4095 0 3253 +4095 2266 0 +4095 3695 0 +0 3278 3548 +0 3278 3548 +0 3279 3548 +0 3279 3548 +0 3279 3548 +0 3280 3548 +0 3280 3548 +0 3281 3548 +0 3283 3548 +0 3285 3548 +0 3287 3548 +0 3290 3548 +0 3294 3548 +0 3300 3548 +0 3307 3548 +0 3317 3548 +0 3329 3548 +0 3346 3548 +0 3367 3548 +0 3393 3548 +0 3426 3548 +0 3467 3548 +0 3516 3548 +0 3548 3519 +0 3548 3426 +0 3548 3264 +0 3548 2873 +0 3680 0 +0 3812 0 +2497 3944 0 +3271 4076 0 +3608 4095 0 +0 3278 3548 +0 3278 3548 +0 3278 3548 +0 3279 3548 +0 3279 3548 +0 3280 3548 +0 3280 3548 +0 3281 3548 +0 3283 3548 +0 3284 3548 +0 3287 3548 +0 3290 3548 +0 3294 3548 +0 3300 3548 +0 3307 3548 +0 3317 3548 +0 3329 3548 +0 3346 3548 +0 3367 3548 +0 3393 3548 +0 3426 3548 +0 3467 3548 +0 3516 3548 +0 3548 3519 +0 3548 3426 +0 3548 3264 +0 3548 2873 +0 3680 0 +0 3812 0 +2498 3944 0 +3272 4076 0 +3608 4095 0 +0 3278 3548 +0 3278 3548 +0 3278 3548 +0 3279 3548 +0 3279 3548 +0 3280 3548 +0 3280 3548 +0 3281 3548 +0 3282 3548 +0 3284 3548 +0 3287 3548 +0 3290 3548 +0 3294 3548 +0 3300 3548 +0 3307 3548 +0 3317 3548 +0 3329 3548 +0 3346 3548 +0 3366 3548 +0 3393 3548 +0 3426 3548 +0 3467 3548 +0 3516 3548 +0 3548 3519 +0 3548 3427 +0 3548 3264 +0 3548 2873 +0 3680 0 +0 3812 0 +2500 3944 0 +3272 4076 0 +3608 4095 0 +0 3277 3548 +0 3278 3548 +0 3278 3548 +0 3278 3548 +0 3279 3548 +0 3279 3548 +0 3280 3548 +0 3281 3548 +0 3282 3548 +0 3284 3548 +0 3286 3548 +0 3290 3548 +0 3294 3548 +0 3299 3548 +0 3307 3548 +0 3316 3548 +0 3329 3548 +0 3345 3548 +0 3366 3548 +0 3393 3548 +0 3426 3548 +0 3467 3548 +0 3516 3548 +0 3548 3519 +0 3548 3427 +0 3548 3264 +0 3548 2874 +0 3680 0 +0 3812 0 +2502 3944 0 +3272 4076 0 +3608 4095 0 +0 3277 3548 +0 3277 3548 +0 3277 3548 +0 3278 3548 +0 3278 3548 +0 3279 3548 +0 3280 3548 +0 3280 3548 +0 3282 3548 +0 3284 3548 +0 3286 3548 +0 3289 3548 +0 3293 3548 +0 3299 3548 +0 3307 3548 +0 3316 3548 +0 3329 3548 +0 3345 3548 +0 3366 3548 +0 3392 3548 +0 3426 3548 +0 3467 3548 +0 3516 3548 +0 3548 3519 +0 3548 3427 +0 3548 3264 +0 3548 2874 +0 3680 0 +0 3812 0 +2505 3944 0 +3273 4076 0 +3608 4095 0 +0 3276 3548 +0 3277 3548 +0 3277 3548 +0 3277 3548 +0 3278 3548 +0 3278 3548 +0 3279 3548 +0 3280 3548 +0 3281 3548 +0 3283 3548 +0 3286 3548 +0 3289 3548 +0 3293 3548 +0 3299 3548 +0 3306 3548 +0 3316 3548 +0 3328 3548 +0 3344 3548 +0 3365 3548 +0 3392 3548 +0 3425 3548 +0 3466 3548 +0 3516 3548 +0 3548 3519 +0 3548 3427 +0 3548 3265 +0 3548 2875 +0 3680 0 +0 3812 0 +2508 3944 0 +3273 4076 0 +3609 4095 0 +0 3276 3548 +0 3276 3548 +0 3276 3548 +0 3277 3548 +0 3277 3548 +0 3278 3548 +0 3279 3548 +0 3280 3548 +0 3281 3548 +0 3283 3548 +0 3285 3548 +0 3288 3548 +0 3292 3548 +0 3298 3548 +0 3305 3548 +0 3315 3548 +0 3328 3548 +0 3344 3548 +0 3365 3548 +0 3392 3548 +0 3425 3548 +0 3466 3548 +0 3515 3548 +0 3548 3519 +0 3548 3427 +0 3548 3265 +0 3548 2876 +0 3680 0 +0 3812 0 +2513 3944 0 +3274 4076 0 +3609 4095 0 +0 3275 3548 +0 3275 3548 +0 3275 3548 +0 3275 3548 +0 3276 3548 +0 3277 3548 +0 3278 3548 +0 3279 3548 +0 3280 3548 +0 3282 3548 +0 3284 3548 +0 3287 3548 +0 3292 3548 +0 3297 3548 +0 3305 3548 +0 3314 3548 +0 3327 3548 +0 3343 3548 +0 3364 3548 +0 3391 3548 +0 3424 3548 +0 3466 3548 +0 3515 3548 +0 3548 3520 +0 3548 3428 +0 3548 3265 +0 3548 2877 +0 3680 0 +0 3812 0 +2520 3944 0 +3276 4076 0 +3610 4095 0 +0 3273 3548 +0 3273 3548 +0 3274 3548 +0 3274 3548 +0 3275 3548 +0 3275 3548 +0 3276 3548 +0 3277 3548 +0 3279 3548 +0 3281 3548 +0 3283 3548 +0 3286 3548 +0 3291 3548 +0 3296 3548 +0 3303 3548 +0 3313 3548 +0 3326 3548 +0 3342 3548 +0 3363 3548 +0 3390 3548 +0 3423 3548 +0 3465 3548 +0 3514 3548 +0 3548 3520 +0 3548 3428 +0 3548 3266 +0 3548 2878 +0 3680 0 +0 3812 0 +2528 3944 0 +3277 4076 0 +3611 4095 0 +0 3271 3548 +0 3272 3548 +0 3272 3548 +0 3272 3548 +0 3273 3548 +0 3273 3548 +0 3274 3548 +0 3276 3548 +0 3277 3548 +0 3279 3547 +0 3282 3547 +0 3285 3547 +0 3289 3547 +0 3295 3547 +0 3302 3547 +0 3312 3547 +0 3325 3547 +0 3341 3547 +0 3362 3547 +0 3389 3547 +0 3422 3547 +0 3464 3547 +0 3513 3547 +0 3547 3520 +0 3547 3429 +0 3547 3267 +0 3547 2880 +0 3680 0 +0 3812 0 +2539 3944 0 +3279 4076 0 +3612 4095 0 +0 3269 3548 +0 3269 3548 +0 3269 3548 +0 3270 3548 +0 3270 3548 +0 3271 3548 +0 3272 3548 +0 3273 3548 +0 3275 3548 +0 3277 3547 +0 3280 3547 +0 3283 3547 +0 3287 3547 +0 3293 3547 +0 3300 3547 +0 3310 3547 +0 3323 3547 +0 3339 3547 +0 3361 3547 +0 3387 3547 +0 3421 3547 +0 3462 3547 +0 3512 3547 +0 3547 3521 +0 3547 3429 +0 3547 3268 +0 3547 2883 +0 3679 0 +0 3812 0 +2553 3944 0 +3282 4076 0 +3613 4095 0 +0 3266 3548 +0 3266 3548 +0 3266 3548 +0 3267 3548 +0 3267 3548 +0 3268 3548 +0 3269 3548 +0 3270 3548 +0 3271 3548 +0 3274 3547 +0 3277 3547 +0 3280 3547 +0 3285 3547 +0 3290 3547 +0 3298 3547 +0 3307 3547 +0 3320 3547 +0 3337 3547 +0 3358 3547 +0 3385 3547 +0 3419 3547 +0 3461 3547 +0 3511 3547 +0 3547 3522 +0 3547 3430 +0 3547 3269 +0 3547 2886 +0 3679 0 +0 3812 0 +2572 3944 0 +3286 4076 0 +3615 4095 0 +0 3261 3548 +0 3261 3548 +0 3261 3548 +0 3262 3548 +0 3262 3548 +0 3263 3548 +0 3264 3548 +0 3265 3548 +0 3267 3548 +0 3269 3547 +0 3272 3547 +0 3276 3547 +0 3281 3546 +0 3287 3546 +0 3294 3546 +0 3304 3546 +0 3317 3546 +0 3334 3546 +0 3355 3546 +0 3382 3546 +0 3416 3546 +0 3458 3546 +0 3509 3546 +0 3546 3523 +0 3546 3432 +0 3546 3271 +0 3546 2891 +0 3679 0 +0 3811 0 +2596 3944 0 +3291 4076 0 +3617 4095 0 +0 3255 3548 +0 3255 3548 +0 3256 3548 +0 3256 3548 +0 3256 3548 +0 3257 3548 +0 3258 3548 +0 3259 3548 +0 3261 3548 +0 3263 3547 +0 3266 3547 +0 3270 3547 +0 3275 3546 +0 3282 3546 +0 3290 3546 +0 3300 3546 +0 3313 3546 +0 3330 3546 +0 3351 3546 +0 3379 3546 +0 3413 3546 +0 3455 3546 +0 3506 3546 +0 3546 3525 +0 3546 3434 +0 3546 3274 +0 3546 2897 +0 3678 0 +0 3811 0 +2625 3943 0 +3297 4076 0 +3621 4095 0 +0 3247 3548 +0 3247 3548 +0 3247 3548 +0 3248 3548 +0 3248 3548 +0 3249 3548 +0 3250 3548 +0 3251 3548 +0 3253 3548 +0 3255 3547 +0 3258 3547 +0 3262 3547 +0 3268 3546 +0 3275 3546 +0 3284 3545 +0 3294 3545 +0 3307 3545 +0 3324 3545 +0 3346 3545 +0 3374 3545 +0 3408 3545 +0 3451 3545 +0 3502 3545 +0 3545 3526 +0 3545 3436 +0 3545 3278 +0 3545 2905 +0 3678 0 +0 3810 0 +2662 3943 0 +3306 4075 0 +3625 4095 0 +0 3236 3548 +0 3236 3548 +0 3236 3548 +0 3237 3548 +0 3237 3548 +0 3238 3548 +0 3239 3548 +0 3240 3548 +0 3242 3548 +0 3244 3547 +0 3247 3547 +0 3251 3547 +0 3257 3546 +0 3264 3546 +0 3273 3545 +0 3285 3544 +0 3299 3544 +0 3316 3544 +0 3339 3544 +0 3367 3544 +0 3402 3544 +0 3445 3544 +0 3497 3544 +0 3544 3529 +0 3544 3440 +0 3544 3282 +0 3544 2916 +0 3677 0 +0 3810 0 +2708 3943 0 +3318 4075 0 +3630 4095 0 +0 3220 3548 +0 3220 3548 +0 3221 3548 +0 3221 3548 +0 3222 3548 +0 3222 3548 +0 3223 3548 +0 3225 3548 +0 3226 3548 +0 3229 3547 +0 3232 3547 +0 3236 3547 +0 3242 3546 +0 3249 3546 +0 3259 3545 +0 3272 3544 +0 3288 3543 +0 3306 3543 +0 3329 3543 +0 3357 3543 +0 3393 3543 +0 3437 3543 +0 3490 3543 +0 3543 3533 +0 3543 3444 +0 3543 3288 +0 3543 2929 +0 3676 0 +0 3809 0 +2762 3942 0 +3333 4075 0 +3638 4095 0 +0 3198 3548 +0 3199 3548 +0 3199 3548 +0 3200 3548 +0 3200 3548 +0 3201 3548 +0 3202 3548 +0 3203 3548 +0 3205 3548 +0 3208 3547 +0 3211 3547 +0 3216 3547 +0 3221 3546 +0 3229 3546 +0 3239 3545 +0 3253 3544 +0 3270 3543 +0 3291 3541 +0 3315 3541 +0 3344 3541 +0 3381 3541 +0 3426 3541 +0 3480 3541 +0 3541 3538 +0 3541 3450 +0 3541 3296 +0 3541 2947 +0 3675 0 +0 3808 0 +2826 3941 0 +3351 4074 0 +3648 4095 0 +0 3168 3548 +0 3168 3548 +0 3168 3548 +0 3169 3548 +0 3170 3548 +0 3171 3548 +0 3172 3548 +0 3173 3548 +0 3175 3548 +0 3178 3547 +0 3182 3547 +0 3186 3547 +0 3192 3546 +0 3201 3546 +0 3211 3545 +0 3225 3544 +0 3243 3543 +0 3267 3541 +0 3296 3538 +0 3326 3538 +0 3365 3538 +0 3411 3538 +0 3467 3538 +0 3532 3538 +0 3538 3457 +0 3538 3307 +0 3538 2970 +0 3673 0 +0 3807 0 +2899 3940 0 +3376 4073 0 +3661 4095 0 +0 3124 3548 +0 3124 3548 +0 3124 3548 +0 3125 3548 +0 3125 3548 +0 3126 3548 +0 3128 3548 +0 3129 3548 +0 3132 3548 +0 3135 3547 +0 3138 3547 +0 3144 3547 +0 3151 3546 +0 3160 3546 +0 3171 3545 +0 3186 3544 +0 3206 3543 +0 3231 3541 +0 3263 3538 +0 3302 3535 +0 3342 3535 +0 3391 3535 +0 3449 3535 +0 3516 3535 +0 3535 3467 +0 3535 3321 +0 3535 2998 +0 3670 0 +0 3805 0 +2982 3939 0 +3407 4072 0 +3677 4095 0 +0 3056 3548 +0 3057 3548 +0 3057 3548 +0 3058 3548 +0 3059 3548 +0 3060 3548 +0 3061 3548 +0 3063 3548 +0 3066 3548 +0 3069 3547 +0 3074 3547 +0 3080 3547 +0 3087 3546 +0 3098 3546 +0 3111 3545 +0 3129 3544 +0 3151 3543 +0 3179 3541 +0 3214 3538 +0 3257 3535 +0 3309 3530 +0 3362 3530 +0 3423 3530 +0 3495 3530 +0 3530 3480 +0 3530 3339 +0 3530 3034 +0 3667 0 +1737 3802 0 +3073 3937 0 +3445 4071 0 +3699 4095 0 +0 2948 3548 +0 2948 3548 +0 2949 3548 +0 2950 3548 +0 2951 3548 +0 2952 3548 +0 2954 3548 +0 2956 3548 +0 2960 3548 +0 2964 3547 +0 2970 3547 +0 2977 3547 +0 2987 3546 +0 3000 3546 +0 3016 3545 +0 3038 3544 +0 3065 3543 +0 3099 3541 +0 3140 3538 +0 3190 3535 +0 3250 3530 +1536 3320 3524 +1536 3387 3524 +1536 3463 3524 +1536 3524 3497 +1536 3524 3362 +1536 3524 3078 +0 3662 1753 +2519 3799 0 +3172 3934 0 +3491 4069 0 +3726 4095 0 +0 2745 3548 +0 2745 3548 +0 2746 3548 +0 2747 3548 +0 2749 3548 +0 2751 3548 +0 2754 3548 +0 2758 3548 +0 2763 3548 +0 2770 3547 +0 2778 3547 +0 2790 3547 +0 2804 3546 +0 2824 3546 +0 2848 3545 +0 2879 3544 +0 2917 3543 +0 2963 3541 +0 3018 3538 +0 3083 3535 +0 3157 3530 +1536 3241 3524 +2457 3333 3515 +2457 3418 3515 +2457 3512 3515 +2457 3515 3391 +2457 3515 3130 +1663 3656 2289 +2856 3794 0 +3277 3931 0 +3546 4066 0 +3759 4095 0 +0 2104 3548 +0 2107 3548 +0 2111 3548 +0 2115 3548 +0 2122 3548 +0 2130 3548 +0 2141 3548 +0 2156 3548 +0 2174 3548 +0 2198 3547 +0 2228 3547 +0 2265 3547 +0 2311 3546 +0 2365 3546 +0 2429 3545 +0 2502 3544 +0 2585 3543 +0 2676 3541 +0 2775 3538 +0 2881 3535 +0 2992 3530 +1536 3108 3524 +2457 3227 3515 +2808 3350 3504 +2808 3457 3504 +2808 3504 3426 +2808 3504 3192 +2592 3648 2590 +3097 3788 1799 +3388 3926 0 +3611 4063 0 +3801 4095 0 +0 0 3548 +0 0 3548 +0 0 3548 +0 0 3548 +0 0 3548 +0 0 3548 +0 0 3548 +0 0 3548 +0 0 3548 +0 0 3547 +0 0 3547 +0 0 3547 +0 0 3546 +0 0 3546 +0 0 3545 +0 0 3544 +0 0 3543 +0 0 3541 +0 1477 3538 +0 2256 3535 +0 2593 3530 +1536 2833 3524 +2457 3032 3515 +2808 3209 3504 +3054 3372 3488 +3054 3488 3470 +3054 3488 3264 +3038 3636 2940 +3296 3780 2721 +3504 3920 1928 +3685 4058 0 +3851 4095 0 +0 0 3548 +0 0 3548 +0 0 3548 +0 0 3548 +0 0 3548 +0 0 3548 +0 0 3548 +0 0 3548 +0 0 3548 +0 0 3547 +0 0 3547 +0 0 3547 +0 0 3546 +0 0 3546 +0 0 3545 +0 0 3544 +0 0 3543 +0 0 3541 +0 0 3538 +0 0 3535 +1621 0 3530 +2158 1536 3524 +2457 2459 3515 +2808 2907 3504 +3054 3183 3488 +3256 3399 3466 +3256 3466 3344 +3315 3620 3186 +3473 3768 3072 +3624 3912 2854 +3769 4052 2063 +3911 4095 0 +2873 0 3548 +2873 0 3548 +2873 0 3548 +2874 0 3548 +2874 0 3548 +2875 0 3548 +2876 0 3548 +2877 0 3548 +2878 0 3548 +2880 0 3547 +2883 0 3547 +2886 0 3547 +2891 0 3546 +2897 0 3546 +2905 0 3545 +2916 0 3544 +2929 0 3543 +2947 0 3541 +2970 0 3538 +2998 0 3535 +3034 0 3530 +3078 1536 3524 +3130 2457 3515 +3192 2808 3504 +3264 3054 3488 +3344 3256 3466 +3434 3434 3434 +3531 3598 3388 +3636 3752 3318 +3746 3900 3204 +3861 4044 2986 +3980 4095 2192 +3396 0 3680 +3396 0 3680 +3396 0 3680 +3396 0 3680 +3396 0 3680 +3396 0 3680 +3396 0 3680 +3397 0 3680 +3397 0 3680 +3398 0 3680 +3399 0 3679 +3400 0 3679 +3401 0 3679 +3403 0 3678 +3406 0 3678 +3410 0 3677 +3414 0 3676 +3420 0 3675 +3429 0 3673 +3439 0 3670 +3453 0 3667 +3471 0 3662 +3494 1663 3656 +3523 2590 3648 +3558 2940 3636 +3603 3186 3620 +3598 3388 3531 +3598 3477 3388 +3752 3735 3318 +3853 3900 3204 +3947 4044 2986 +4047 4095 2192 +3691 0 3812 +3691 0 3812 +3691 0 3812 +3691 0 3812 +3691 0 3812 +3691 0 3812 +3691 0 3812 +3691 0 3812 +3691 0 3812 +3692 0 3812 +3692 0 3812 +3693 0 3812 +3694 0 3811 +3695 0 3811 +3696 0 3810 +3698 0 3810 +3700 0 3809 +3704 0 3808 +3708 0 3807 +3714 0 3805 +3721 0 3802 +3731 0 3799 +3745 0 3794 +3761 1799 3788 +3780 2721 3776 +3768 3072 3721 +3752 3318 3636 +3752 3318 3447 +3752 3528 3318 +3900 3822 3204 +4040 4044 2986 +4095 4095 2192 +3915 0 3944 +3915 0 3944 +3915 0 3944 +3915 0 3944 +3915 0 3944 +3915 0 3944 +3915 0 3944 +3915 0 3944 +3915 0 3944 +3916 0 3944 +3916 0 3944 +3916 0 3944 +3917 0 3944 +3917 0 3943 +3918 0 3943 +3920 0 3943 +3921 0 3942 +3923 0 3941 +3926 0 3940 +3929 0 3939 +3934 0 3937 +3934 0 3928 +3931 0 3913 +3926 0 3891 +3920 1928 3860 +3912 2854 3814 +3900 3204 3746 +3900 3204 3605 +3900 3204 3302 +3900 3588 3204 +4044 3919 2986 +4095 4095 2192 +4076 0 4045 +4076 0 4045 +4076 0 4045 +4076 0 4045 +4076 0 4045 +4076 0 4045 +4076 0 4045 +4076 0 4045 +4076 0 4044 +4076 0 4044 +4076 0 4044 +4076 0 4043 +4076 0 4043 +4076 0 4042 +4075 0 4041 +4075 0 4039 +4075 0 4037 +4074 0 4034 +4073 0 4030 +4072 0 4025 +4071 0 4018 +4069 0 4008 +4066 0 3995 +4063 0 3977 +4058 0 3952 +4052 2063 3915 +4044 2986 3861 +4044 2986 3755 +4044 2986 3561 +4044 2986 2987 +4044 3659 2986 +4095 4023 2192 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4087 +4095 0 4072 +4095 0 4051 +4095 0 4022 +4095 2192 3980 +4095 2192 3901 +4095 2192 3768 +4095 2192 3494 +4095 2814 2192 +4095 3738 2192 +0 3410 3680 +0 3410 3680 +0 3410 3680 +0 3411 3680 +0 3411 3680 +0 3411 3680 +0 3412 3680 +0 3413 3680 +0 3414 3680 +0 3415 3680 +0 3417 3680 +0 3419 3680 +0 3422 3680 +0 3427 3680 +0 3432 3680 +0 3440 3680 +0 3449 3680 +0 3462 3680 +0 3478 3680 +0 3499 3680 +0 3525 3680 +0 3558 3680 +0 3599 3680 +0 3649 3680 +0 3680 3651 +0 3680 3558 +0 3680 3396 +0 3680 3005 +0 3812 0 +0 3944 0 +2626 4076 0 +3404 4095 0 +0 3410 3680 +0 3410 3680 +0 3410 3680 +0 3411 3680 +0 3411 3680 +0 3411 3680 +0 3412 3680 +0 3413 3680 +0 3414 3680 +0 3415 3680 +0 3417 3680 +0 3419 3680 +0 3422 3680 +0 3426 3680 +0 3432 3680 +0 3439 3680 +0 3449 3680 +0 3462 3680 +0 3478 3680 +0 3499 3680 +0 3525 3680 +0 3558 3680 +0 3599 3680 +0 3649 3680 +0 3680 3651 +0 3680 3558 +0 3680 3396 +0 3680 3005 +0 3812 0 +0 3944 0 +2627 4076 0 +3404 4095 0 +0 3410 3680 +0 3410 3680 +0 3410 3680 +0 3410 3680 +0 3411 3680 +0 3411 3680 +0 3412 3680 +0 3413 3680 +0 3414 3680 +0 3415 3680 +0 3417 3680 +0 3419 3680 +0 3422 3680 +0 3426 3680 +0 3432 3680 +0 3439 3680 +0 3449 3680 +0 3462 3680 +0 3478 3680 +0 3499 3680 +0 3525 3680 +0 3558 3680 +0 3599 3680 +0 3649 3680 +0 3680 3651 +0 3680 3559 +0 3680 3396 +0 3680 3005 +0 3812 0 +0 3944 0 +2628 4076 0 +3404 4095 0 +0 3410 3680 +0 3410 3680 +0 3410 3680 +0 3410 3680 +0 3411 3680 +0 3411 3680 +0 3412 3680 +0 3412 3680 +0 3413 3680 +0 3415 3680 +0 3416 3680 +0 3419 3680 +0 3422 3680 +0 3426 3680 +0 3432 3680 +0 3439 3680 +0 3449 3680 +0 3461 3680 +0 3478 3680 +0 3499 3680 +0 3525 3680 +0 3558 3680 +0 3599 3680 +0 3649 3680 +0 3680 3651 +0 3680 3559 +0 3680 3396 +0 3680 3006 +0 3812 0 +0 3944 0 +2630 4076 0 +3405 4095 0 +0 3409 3680 +0 3409 3680 +0 3410 3680 +0 3410 3680 +0 3410 3680 +0 3411 3680 +0 3411 3680 +0 3412 3680 +0 3413 3680 +0 3414 3680 +0 3416 3680 +0 3419 3680 +0 3422 3680 +0 3426 3680 +0 3431 3680 +0 3439 3680 +0 3448 3680 +0 3461 3680 +0 3478 3680 +0 3498 3680 +0 3525 3680 +0 3558 3680 +0 3599 3680 +0 3648 3680 +0 3680 3651 +0 3680 3559 +0 3680 3396 +0 3680 3006 +0 3812 0 +0 3944 0 +2632 4076 0 +3405 4095 0 +0 3409 3680 +0 3409 3680 +0 3409 3680 +0 3410 3680 +0 3410 3680 +0 3410 3680 +0 3411 3680 +0 3412 3680 +0 3413 3680 +0 3414 3680 +0 3416 3680 +0 3418 3680 +0 3421 3680 +0 3426 3680 +0 3431 3680 +0 3438 3680 +0 3448 3680 +0 3461 3680 +0 3477 3680 +0 3498 3680 +0 3525 3680 +0 3558 3680 +0 3599 3680 +0 3648 3680 +0 3680 3651 +0 3680 3559 +0 3680 3396 +0 3680 3006 +0 3812 0 +0 3944 0 +2635 4076 0 +3405 4095 0 +0 3408 3680 +0 3408 3680 +0 3409 3680 +0 3409 3680 +0 3409 3680 +0 3410 3680 +0 3411 3680 +0 3411 3680 +0 3412 3680 +0 3414 3680 +0 3415 3680 +0 3418 3680 +0 3421 3680 +0 3425 3680 +0 3431 3680 +0 3438 3680 +0 3448 3680 +0 3460 3680 +0 3477 3680 +0 3497 3680 +0 3524 3680 +0 3557 3680 +0 3598 3680 +0 3648 3680 +0 3680 3651 +0 3680 3559 +0 3680 3396 +0 3680 3007 +0 3812 0 +0 3944 0 +2639 4076 0 +3406 4095 0 +0 3408 3680 +0 3408 3680 +0 3408 3680 +0 3408 3680 +0 3409 3680 +0 3409 3680 +0 3410 3680 +0 3411 3680 +0 3412 3680 +0 3413 3680 +0 3415 3680 +0 3417 3680 +0 3420 3680 +0 3425 3680 +0 3430 3680 +0 3437 3680 +0 3447 3680 +0 3460 3680 +0 3476 3680 +0 3497 3680 +0 3524 3680 +0 3557 3680 +0 3598 3680 +0 3648 3680 +0 3680 3652 +0 3680 3559 +0 3680 3397 +0 3680 3008 +0 3812 0 +0 3944 0 +2644 4076 0 +3407 4095 0 +0 3406 3680 +0 3407 3680 +0 3407 3680 +0 3407 3680 +0 3408 3680 +0 3408 3680 +0 3409 3680 +0 3410 3680 +0 3411 3680 +0 3412 3680 +0 3414 3680 +0 3416 3680 +0 3420 3680 +0 3424 3680 +0 3429 3680 +0 3437 3680 +0 3446 3680 +0 3459 3680 +0 3475 3680 +0 3496 3680 +0 3523 3680 +0 3556 3680 +0 3597 3680 +0 3647 3680 +0 3680 3652 +0 3680 3560 +0 3680 3397 +0 3680 3009 +0 3812 0 +0 3944 0 +2650 4076 0 +3408 4095 0 +0 3405 3680 +0 3405 3680 +0 3405 3680 +0 3406 3680 +0 3406 3680 +0 3407 3680 +0 3407 3680 +0 3408 3680 +0 3409 3680 +0 3411 3680 +0 3413 3680 +0 3415 3680 +0 3418 3680 +0 3423 3680 +0 3428 3680 +0 3436 3680 +0 3445 3680 +0 3458 3680 +0 3475 3680 +0 3495 3680 +0 3522 3680 +0 3556 3680 +0 3597 3680 +0 3646 3680 +0 3680 3652 +0 3680 3560 +0 3680 3398 +0 3680 3011 +0 3812 0 +0 3944 0 +2659 4076 0 +3410 4095 0 +0 3403 3680 +0 3403 3680 +0 3404 3680 +0 3404 3680 +0 3404 3680 +0 3405 3680 +0 3406 3680 +0 3406 3680 +0 3408 3680 +0 3409 3680 +0 3411 3679 +0 3414 3679 +0 3417 3679 +0 3421 3679 +0 3427 3679 +0 3434 3679 +0 3444 3679 +0 3457 3679 +0 3473 3679 +0 3494 3679 +0 3521 3679 +0 3554 3679 +0 3596 3679 +0 3646 3679 +0 3679 3653 +0 3679 3561 +0 3679 3399 +0 3679 3013 +0 3812 0 +0 3944 0 +2670 4076 0 +3412 4095 0 +0 3401 3680 +0 3401 3680 +0 3401 3680 +0 3401 3680 +0 3402 3680 +0 3402 3680 +0 3403 3680 +0 3404 3680 +0 3405 3680 +0 3407 3680 +0 3409 3679 +0 3412 3679 +0 3415 3679 +0 3419 3679 +0 3425 3679 +0 3432 3679 +0 3442 3679 +0 3455 3679 +0 3472 3679 +0 3493 3679 +0 3520 3679 +0 3553 3679 +0 3595 3679 +0 3644 3679 +0 3679 3653 +0 3679 3562 +0 3679 3400 +0 3679 3015 +0 3812 0 +0 3944 0 +2684 4076 0 +3415 4095 0 +0 3398 3680 +0 3398 3680 +0 3398 3680 +0 3398 3680 +0 3399 3680 +0 3399 3680 +0 3400 3680 +0 3401 3680 +0 3402 3680 +0 3404 3680 +0 3406 3679 +0 3409 3679 +0 3413 3679 +0 3417 3679 +0 3422 3679 +0 3430 3679 +0 3440 3679 +0 3453 3679 +0 3469 3679 +0 3490 3679 +0 3517 3679 +0 3551 3679 +0 3593 3679 +0 3643 3679 +0 3679 3654 +0 3679 3563 +0 3679 3401 +0 3679 3018 +0 3811 0 +0 3944 0 +2703 4076 0 +3419 4095 0 +0 3393 3680 +0 3393 3680 +0 3393 3680 +0 3394 3680 +0 3394 3680 +0 3395 3680 +0 3395 3680 +0 3396 3680 +0 3397 3680 +0 3399 3680 +0 3401 3679 +0 3404 3679 +0 3408 3679 +0 3413 3678 +0 3419 3678 +0 3426 3678 +0 3436 3678 +0 3449 3678 +0 3466 3678 +0 3488 3678 +0 3515 3678 +0 3548 3678 +0 3590 3678 +0 3641 3678 +0 3678 3655 +0 3678 3564 +0 3678 3403 +0 3678 3023 +0 3811 0 +0 3943 0 +2726 4076 0 +3424 4095 0 +0 3387 3680 +0 3387 3680 +0 3387 3680 +0 3388 3680 +0 3388 3680 +0 3388 3680 +0 3389 3680 +0 3390 3680 +0 3392 3680 +0 3393 3680 +0 3395 3679 +0 3398 3679 +0 3402 3679 +0 3407 3678 +0 3414 3678 +0 3422 3678 +0 3432 3678 +0 3445 3678 +0 3462 3678 +0 3483 3678 +0 3511 3678 +0 3545 3678 +0 3587 3678 +0 3638 3678 +0 3678 3657 +0 3678 3566 +0 3678 3406 +0 3678 3029 +0 3810 0 +0 3943 0 +2756 4075 0 +3430 4095 0 +0 3379 3680 +0 3379 3680 +0 3379 3680 +0 3379 3680 +0 3380 3680 +0 3380 3680 +0 3381 3680 +0 3382 3680 +0 3383 3680 +0 3385 3680 +0 3387 3679 +0 3390 3679 +0 3394 3679 +0 3400 3678 +0 3407 3678 +0 3416 3677 +0 3426 3677 +0 3439 3677 +0 3456 3677 +0 3478 3677 +0 3506 3677 +0 3540 3677 +0 3583 3677 +0 3634 3677 +0 3677 3659 +0 3677 3568 +0 3677 3410 +0 3677 3037 +0 3810 0 +0 3943 0 +2793 4075 0 +3439 4095 0 +0 3367 3680 +0 3368 3680 +0 3368 3680 +0 3368 3680 +0 3369 3680 +0 3369 3680 +0 3370 3680 +0 3371 3680 +0 3372 3680 +0 3374 3680 +0 3376 3679 +0 3379 3679 +0 3384 3679 +0 3389 3678 +0 3396 3678 +0 3405 3677 +0 3418 3676 +0 3431 3676 +0 3448 3676 +0 3471 3676 +0 3499 3676 +0 3534 3676 +0 3577 3676 +0 3629 3676 +0 3676 3662 +0 3676 3572 +0 3676 3414 +0 3676 3048 +0 3809 0 +0 3942 0 +2839 4075 0 +3450 4095 0 +0 3352 3680 +0 3352 3680 +0 3353 3680 +0 3353 3680 +0 3353 3680 +0 3354 3680 +0 3354 3680 +0 3356 3680 +0 3357 3680 +0 3359 3680 +0 3361 3679 +0 3364 3679 +0 3368 3679 +0 3374 3678 +0 3381 3678 +0 3391 3677 +0 3404 3676 +0 3420 3675 +0 3438 3675 +0 3461 3675 +0 3490 3675 +0 3525 3675 +0 3569 3675 +0 3622 3675 +0 3675 3665 +0 3675 3576 +0 3675 3420 +0 3675 3061 +0 3808 0 +0 3941 0 +2893 4074 0 +3465 4095 0 +0 3330 3680 +0 3331 3680 +0 3331 3680 +0 3331 3680 +0 3332 3680 +0 3332 3680 +0 3333 3680 +0 3334 3680 +0 3336 3680 +0 3337 3680 +0 3340 3679 +0 3343 3679 +0 3348 3679 +0 3354 3678 +0 3361 3678 +0 3371 3677 +0 3385 3676 +0 3402 3675 +0 3423 3673 +0 3447 3673 +0 3477 3673 +0 3513 3673 +0 3558 3673 +0 3612 3673 +0 3673 3670 +0 3673 3582 +0 3673 3429 +0 3673 3079 +0 3807 0 +0 3940 0 +2957 4073 0 +3484 4095 0 +0 3300 3680 +0 3300 3680 +0 3300 3680 +0 3301 3680 +0 3301 3680 +0 3302 3680 +0 3303 3680 +0 3304 3680 +0 3305 3680 +0 3307 3680 +0 3310 3679 +0 3314 3679 +0 3318 3679 +0 3325 3678 +0 3333 3678 +0 3344 3677 +0 3358 3676 +0 3376 3675 +0 3399 3673 +0 3428 3670 +0 3459 3670 +0 3497 3670 +0 3543 3670 +0 3599 3670 +0 3664 3670 +0 3670 3589 +0 3670 3439 +0 3670 3102 +0 3805 0 +0 3939 0 +3031 4072 0 +3509 4095 0 +0 3255 3680 +0 3256 3680 +0 3256 3680 +0 3256 3680 +0 3257 3680 +0 3258 3680 +0 3258 3680 +0 3260 3680 +0 3261 3680 +0 3264 3680 +0 3267 3679 +0 3271 3679 +0 3276 3679 +0 3282 3678 +0 3291 3678 +0 3303 3677 +0 3319 3676 +0 3338 3675 +0 3363 3673 +0 3395 3670 +0 3434 3667 +0 3474 3667 +0 3523 3667 +0 3581 3667 +0 3648 3667 +0 3667 3599 +0 3667 3453 +0 3667 3131 +0 3802 0 +0 3937 0 +3113 4071 0 +3539 4095 0 +0 3188 3680 +0 3188 3680 +0 3189 3680 +0 3189 3680 +0 3190 3680 +0 3191 3680 +0 3192 3680 +0 3193 3680 +0 3195 3680 +0 3198 3680 +0 3201 3679 +0 3206 3679 +0 3212 3679 +0 3220 3678 +0 3230 3678 +0 3243 3677 +0 3261 3676 +0 3283 3675 +0 3311 3673 +0 3346 3670 +0 3389 3667 +0 3441 3662 +0 3494 3662 +0 3555 3662 +0 3626 3662 +0 3662 3612 +0 3662 3471 +0 3662 3166 +0 3799 0 +1863 3934 0 +3205 4069 0 +3577 4095 0 +0 3080 3680 +0 3080 3680 +0 3081 3680 +0 3081 3680 +0 3082 3680 +0 3083 3680 +0 3084 3680 +0 3086 3680 +0 3089 3680 +0 3092 3680 +0 3096 3679 +0 3102 3679 +0 3110 3679 +0 3119 3678 +0 3132 3678 +0 3149 3677 +0 3170 3676 +0 3197 3675 +0 3231 3673 +0 3273 3670 +0 3323 3667 +0 3382 3662 +1663 3452 3656 +1663 3519 3656 +1663 3595 3656 +1663 3656 3629 +1663 3656 3494 +1663 3656 3210 +0 3794 1884 +2650 3931 0 +3303 4066 0 +3623 4095 0 +0 2876 3680 +0 2877 3680 +0 2877 3680 +0 2878 3680 +0 2879 3680 +0 2881 3680 +0 2883 3680 +0 2886 3680 +0 2890 3680 +0 2895 3680 +0 2901 3679 +0 2910 3679 +0 2922 3679 +0 2936 3678 +0 2955 3678 +0 2980 3677 +0 3010 3676 +0 3048 3675 +0 3095 3673 +0 3150 3670 +0 3215 3667 +0 3289 3662 +1663 3373 3656 +2590 3465 3648 +2590 3550 3648 +2590 3644 3648 +2590 3648 3523 +2590 3648 3262 +1799 3788 2422 +2988 3926 0 +3409 4063 0 +3679 4095 0 +0 2237 3680 +0 2239 3680 +0 2242 3680 +0 2246 3680 +0 2251 3680 +0 2257 3680 +0 2266 3680 +0 2277 3680 +0 2291 3680 +0 2310 3680 +0 2333 3679 +0 2363 3679 +0 2400 3679 +0 2445 3678 +0 2499 3678 +0 2562 3677 +0 2636 3676 +0 2718 3675 +0 2809 3673 +0 2908 3670 +0 3014 3667 +0 3125 3662 +1663 3240 3656 +2590 3360 3648 +2940 3482 3636 +2940 3589 3636 +2940 3636 3558 +2940 3636 3324 +2722 3780 2721 +3229 3920 1928 +3520 4058 0 +3743 4095 0 +0 0 3680 +0 0 3680 +0 0 3680 +0 0 3680 +0 0 3680 +0 0 3680 +0 0 3680 +0 0 3680 +0 0 3680 +0 0 3680 +0 0 3679 +0 0 3679 +0 0 3679 +0 0 3678 +0 0 3678 +0 0 3677 +0 0 3676 +0 0 3675 +0 0 3673 +0 1603 3670 +0 2388 3667 +0 2724 3662 +1663 2965 3656 +2590 3165 3648 +2940 3341 3636 +3186 3504 3620 +3186 3620 3603 +3186 3620 3396 +3171 3768 3072 +3428 3912 2854 +3636 4052 2063 +3818 4095 0 +0 0 3680 +0 0 3680 +0 0 3680 +0 0 3680 +0 0 3680 +0 0 3680 +0 0 3680 +0 0 3680 +0 0 3680 +0 0 3680 +0 0 3679 +0 0 3679 +0 0 3679 +0 0 3678 +0 0 3678 +0 0 3677 +0 0 3676 +0 0 3675 +0 0 3673 +0 0 3670 +0 0 3667 +1753 0 3662 +2289 1663 3656 +2590 2592 3648 +2940 3038 3636 +3186 3315 3620 +3388 3531 3598 +3388 3598 3477 +3447 3752 3318 +3605 3900 3204 +3755 4044 2986 +3901 4095 2192 +3005 0 3680 +3005 0 3680 +3005 0 3680 +3006 0 3680 +3006 0 3680 +3006 0 3680 +3007 0 3680 +3008 0 3680 +3009 0 3680 +3011 0 3680 +3013 0 3679 +3015 0 3679 +3018 0 3679 +3023 0 3678 +3029 0 3678 +3037 0 3677 +3048 0 3676 +3061 0 3675 +3079 0 3673 +3102 0 3670 +3131 0 3667 +3166 0 3662 +3210 1663 3656 +3262 2590 3648 +3324 2940 3636 +3396 3186 3620 +3477 3388 3598 +3566 3566 3566 +3664 3730 3520 +3768 3884 3450 +3878 4032 3336 +3993 4095 3118 +3528 0 3812 +3528 0 3812 +3528 0 3812 +3528 0 3812 +3528 0 3812 +3528 0 3812 +3528 0 3812 +3529 0 3812 +3529 0 3812 +3530 0 3812 +3530 0 3812 +3531 0 3812 +3532 0 3811 +3534 0 3811 +3536 0 3810 +3538 0 3810 +3542 0 3809 +3546 0 3808 +3552 0 3807 +3561 0 3805 +3571 0 3802 +3585 0 3799 +3603 0 3794 +3626 1799 3788 +3655 2721 3780 +3691 3072 3768 +3735 3318 3752 +3730 3520 3664 +3730 3609 3520 +3884 3867 3450 +3986 4032 3336 +4079 4095 3118 +3822 0 3944 +3822 0 3944 +3822 0 3944 +3823 0 3944 +3823 0 3944 +3823 0 3944 +3823 0 3944 +3823 0 3944 +3823 0 3944 +3824 0 3944 +3824 0 3944 +3824 0 3944 +3825 0 3944 +3826 0 3943 +3827 0 3943 +3828 0 3943 +3830 0 3942 +3832 0 3941 +3836 0 3940 +3840 0 3939 +3846 0 3937 +3853 0 3934 +3863 0 3931 +3877 0 3926 +3893 1928 3920 +3912 2854 3908 +3900 3204 3853 +3884 3450 3768 +3884 3450 3579 +3884 3660 3450 +4032 3955 3336 +4095 4095 3118 +4047 0 4076 +4047 0 4076 +4047 0 4076 +4047 0 4076 +4047 0 4076 +4047 0 4076 +4047 0 4076 +4047 0 4076 +4047 0 4076 +4047 0 4076 +4048 0 4076 +4048 0 4076 +4048 0 4076 +4049 0 4076 +4049 0 4075 +4050 0 4075 +4051 0 4075 +4053 0 4074 +4055 0 4073 +4058 0 4072 +4061 0 4071 +4066 0 4069 +4066 0 4060 +4063 0 4045 +4058 0 4023 +4052 2063 3992 +4044 2986 3947 +4032 3336 3878 +4032 3336 3737 +4032 3336 3435 +4032 3720 3336 +4095 4051 3118 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4084 +4095 2192 4047 +4095 3118 3993 +4095 3118 3888 +4095 3118 3693 +4095 3118 3121 +4095 3791 3118 +0 3542 3812 +0 3542 3812 +0 3543 3812 +0 3543 3812 +0 3543 3812 +0 3543 3812 +0 3544 3812 +0 3544 3812 +0 3545 3812 +0 3546 3812 +0 3547 3812 +0 3549 3812 +0 3552 3812 +0 3554 3812 +0 3559 3812 +0 3564 3812 +0 3572 3812 +0 3581 3812 +0 3594 3812 +0 3610 3812 +0 3631 3812 +0 3657 3812 +0 3691 3812 +0 3732 3812 +0 3781 3812 +0 3812 3783 +0 3812 3691 +0 3812 3528 +0 3812 3137 +0 3944 0 +0 4076 0 +2761 4095 0 +0 3542 3812 +0 3542 3812 +0 3543 3812 +0 3543 3812 +0 3543 3812 +0 3543 3812 +0 3544 3812 +0 3544 3812 +0 3545 3812 +0 3546 3812 +0 3547 3812 +0 3549 3812 +0 3551 3812 +0 3554 3812 +0 3559 3812 +0 3564 3812 +0 3572 3812 +0 3581 3812 +0 3594 3812 +0 3610 3812 +0 3631 3812 +0 3657 3812 +0 3691 3812 +0 3731 3812 +0 3781 3812 +0 3812 3783 +0 3812 3691 +0 3812 3528 +0 3812 3137 +0 3944 0 +0 4076 0 +2762 4095 0 +0 3542 3812 +0 3542 3812 +0 3542 3812 +0 3543 3812 +0 3543 3812 +0 3543 3812 +0 3543 3812 +0 3544 3812 +0 3545 3812 +0 3546 3812 +0 3547 3812 +0 3549 3812 +0 3551 3812 +0 3554 3812 +0 3559 3812 +0 3564 3812 +0 3572 3812 +0 3581 3812 +0 3594 3812 +0 3610 3812 +0 3631 3812 +0 3657 3812 +0 3690 3812 +0 3731 3812 +0 3781 3812 +0 3812 3783 +0 3812 3691 +0 3812 3528 +0 3812 3137 +0 3944 0 +0 4076 0 +2762 4095 0 +0 3542 3812 +0 3542 3812 +0 3542 3812 +0 3542 3812 +0 3543 3812 +0 3543 3812 +0 3543 3812 +0 3544 3812 +0 3545 3812 +0 3545 3812 +0 3547 3812 +0 3549 3812 +0 3551 3812 +0 3554 3812 +0 3558 3812 +0 3564 3812 +0 3571 3812 +0 3581 3812 +0 3594 3812 +0 3610 3812 +0 3631 3812 +0 3657 3812 +0 3690 3812 +0 3731 3812 +0 3781 3812 +0 3812 3783 +0 3812 3691 +0 3812 3528 +0 3812 3138 +0 3944 0 +0 4076 0 +2764 4095 0 +0 3541 3812 +0 3542 3812 +0 3542 3812 +0 3542 3812 +0 3543 3812 +0 3543 3812 +0 3543 3812 +0 3544 3812 +0 3544 3812 +0 3545 3812 +0 3547 3812 +0 3549 3812 +0 3551 3812 +0 3554 3812 +0 3558 3812 +0 3564 3812 +0 3571 3812 +0 3581 3812 +0 3594 3812 +0 3610 3812 +0 3631 3812 +0 3657 3812 +0 3690 3812 +0 3731 3812 +0 3781 3812 +0 3812 3783 +0 3812 3691 +0 3812 3528 +0 3812 3138 +0 3944 0 +0 4076 0 +2765 4095 0 +0 3541 3812 +0 3541 3812 +0 3541 3812 +0 3542 3812 +0 3542 3812 +0 3543 3812 +0 3543 3812 +0 3543 3812 +0 3544 3812 +0 3545 3812 +0 3547 3812 +0 3548 3812 +0 3551 3812 +0 3554 3812 +0 3558 3812 +0 3564 3812 +0 3571 3812 +0 3581 3812 +0 3593 3812 +0 3609 3812 +0 3630 3812 +0 3657 3812 +0 3690 3812 +0 3731 3812 +0 3781 3812 +0 3812 3783 +0 3812 3691 +0 3812 3528 +0 3812 3138 +0 3944 0 +0 4076 0 +2767 4095 0 +0 3541 3812 +0 3541 3812 +0 3541 3812 +0 3541 3812 +0 3542 3812 +0 3542 3812 +0 3543 3812 +0 3543 3812 +0 3544 3812 +0 3545 3812 +0 3546 3812 +0 3548 3812 +0 3550 3812 +0 3553 3812 +0 3558 3812 +0 3563 3812 +0 3571 3812 +0 3580 3812 +0 3593 3812 +0 3609 3812 +0 3630 3812 +0 3657 3812 +0 3690 3812 +0 3731 3812 +0 3781 3812 +0 3812 3783 +0 3812 3691 +0 3812 3528 +0 3812 3139 +0 3944 0 +0 4076 0 +2770 4095 0 +0 3540 3812 +0 3540 3812 +0 3541 3812 +0 3541 3812 +0 3541 3812 +0 3541 3812 +0 3542 3812 +0 3543 3812 +0 3543 3812 +0 3544 3812 +0 3546 3812 +0 3548 3812 +0 3550 3812 +0 3553 3812 +0 3557 3812 +0 3563 3812 +0 3570 3812 +0 3580 3812 +0 3593 3812 +0 3609 3812 +0 3630 3812 +0 3656 3812 +0 3690 3812 +0 3730 3812 +0 3780 3812 +0 3812 3784 +0 3812 3691 +0 3812 3529 +0 3812 3139 +0 3944 0 +0 4076 0 +2773 4095 0 +0 3540 3812 +0 3540 3812 +0 3540 3812 +0 3540 3812 +0 3540 3812 +0 3541 3812 +0 3541 3812 +0 3542 3812 +0 3543 3812 +0 3544 3812 +0 3545 3812 +0 3547 3812 +0 3549 3812 +0 3552 3812 +0 3557 3812 +0 3562 3812 +0 3570 3812 +0 3579 3812 +0 3592 3812 +0 3608 3812 +0 3629 3812 +0 3656 3812 +0 3689 3812 +0 3730 3812 +0 3780 3812 +0 3812 3784 +0 3812 3691 +0 3812 3529 +0 3812 3140 +0 3944 0 +0 4076 0 +2778 4095 0 +0 3538 3812 +0 3538 3812 +0 3539 3812 +0 3539 3812 +0 3539 3812 +0 3540 3812 +0 3540 3812 +0 3541 3812 +0 3542 3812 +0 3543 3812 +0 3544 3812 +0 3546 3812 +0 3548 3812 +0 3552 3812 +0 3556 3812 +0 3562 3812 +0 3569 3812 +0 3579 3812 +0 3591 3812 +0 3607 3812 +0 3629 3812 +0 3655 3812 +0 3689 3812 +0 3729 3812 +0 3779 3812 +0 3812 3784 +0 3812 3692 +0 3812 3530 +0 3812 3141 +0 3944 0 +0 4076 0 +2785 4095 0 +0 3537 3812 +0 3537 3812 +0 3537 3812 +0 3538 3812 +0 3538 3812 +0 3538 3812 +0 3539 3812 +0 3540 3812 +0 3540 3812 +0 3541 3812 +0 3543 3812 +0 3545 3812 +0 3547 3812 +0 3551 3812 +0 3555 3812 +0 3561 3812 +0 3568 3812 +0 3577 3812 +0 3590 3812 +0 3606 3812 +0 3628 3812 +0 3654 3812 +0 3688 3812 +0 3729 3812 +0 3778 3812 +0 3812 3784 +0 3812 3692 +0 3812 3530 +0 3812 3143 +0 3944 0 +0 4076 0 +2793 4095 0 +0 3535 3812 +0 3536 3812 +0 3536 3812 +0 3536 3812 +0 3536 3812 +0 3537 3812 +0 3537 3812 +0 3538 3812 +0 3538 3812 +0 3540 3812 +0 3541 3812 +0 3544 3812 +0 3546 3812 +0 3549 3812 +0 3553 3812 +0 3559 3812 +0 3566 3812 +0 3576 3812 +0 3589 3812 +0 3605 3812 +0 3626 3812 +0 3653 3812 +0 3687 3812 +0 3728 3812 +0 3777 3812 +0 3812 3785 +0 3812 3693 +0 3812 3531 +0 3812 3145 +0 3944 0 +0 4076 0 +2804 4095 0 +0 3533 3812 +0 3533 3812 +0 3533 3812 +0 3533 3812 +0 3534 3812 +0 3534 3812 +0 3534 3812 +0 3535 3812 +0 3536 3812 +0 3537 3812 +0 3539 3812 +0 3541 3812 +0 3544 3811 +0 3547 3811 +0 3552 3811 +0 3557 3811 +0 3564 3811 +0 3574 3811 +0 3587 3811 +0 3604 3811 +0 3625 3811 +0 3652 3811 +0 3685 3811 +0 3727 3811 +0 3777 3811 +0 3811 3785 +0 3811 3694 +0 3811 3532 +0 3811 3147 +0 3944 0 +0 4076 0 +2818 4095 0 +0 3530 3812 +0 3530 3812 +0 3530 3812 +0 3530 3812 +0 3530 3812 +0 3531 3812 +0 3531 3812 +0 3532 3812 +0 3533 3812 +0 3534 3812 +0 3536 3812 +0 3538 3812 +0 3541 3811 +0 3545 3811 +0 3549 3811 +0 3554 3811 +0 3562 3811 +0 3572 3811 +0 3585 3811 +0 3601 3811 +0 3622 3811 +0 3650 3811 +0 3683 3811 +0 3725 3811 +0 3775 3811 +0 3811 3786 +0 3811 3695 +0 3811 3534 +0 3811 3151 +0 3943 0 +0 4076 0 +2837 4095 0 +0 3525 3812 +0 3525 3812 +0 3525 3812 +0 3526 3812 +0 3526 3812 +0 3526 3812 +0 3527 3812 +0 3528 3812 +0 3528 3812 +0 3530 3812 +0 3531 3812 +0 3533 3812 +0 3536 3811 +0 3540 3811 +0 3545 3810 +0 3551 3810 +0 3559 3810 +0 3569 3810 +0 3582 3810 +0 3598 3810 +0 3620 3810 +0 3647 3810 +0 3680 3810 +0 3722 3810 +0 3773 3810 +0 3810 3787 +0 3810 3696 +0 3810 3536 +0 3810 3155 +0 3943 0 +0 4075 0 +2861 4095 0 +0 3519 3812 +0 3519 3812 +0 3519 3812 +0 3520 3812 +0 3520 3812 +0 3520 3812 +0 3521 3812 +0 3521 3812 +0 3522 3812 +0 3523 3812 +0 3525 3812 +0 3528 3812 +0 3530 3811 +0 3534 3811 +0 3540 3810 +0 3547 3810 +0 3554 3810 +0 3564 3810 +0 3577 3810 +0 3594 3810 +0 3616 3810 +0 3643 3810 +0 3677 3810 +0 3719 3810 +0 3770 3810 +0 3810 3789 +0 3810 3698 +0 3810 3538 +0 3810 3161 +0 3943 0 +0 4075 0 +2890 4095 0 +0 3511 3812 +0 3511 3812 +0 3511 3812 +0 3511 3812 +0 3511 3812 +0 3512 3812 +0 3513 3812 +0 3513 3812 +0 3514 3812 +0 3515 3812 +0 3517 3812 +0 3520 3812 +0 3522 3811 +0 3526 3811 +0 3532 3810 +0 3539 3810 +0 3548 3809 +0 3558 3809 +0 3571 3809 +0 3588 3809 +0 3610 3809 +0 3638 3809 +0 3672 3809 +0 3715 3809 +0 3766 3809 +0 3809 3791 +0 3809 3700 +0 3809 3542 +0 3809 3169 +0 3942 0 +0 4075 0 +2927 4095 0 +0 3499 3812 +0 3499 3812 +0 3500 3812 +0 3500 3812 +0 3500 3812 +0 3501 3812 +0 3501 3812 +0 3502 3812 +0 3503 3812 +0 3504 3812 +0 3506 3812 +0 3508 3812 +0 3511 3811 +0 3516 3811 +0 3521 3810 +0 3528 3810 +0 3537 3809 +0 3550 3808 +0 3563 3808 +0 3581 3808 +0 3603 3808 +0 3631 3808 +0 3666 3808 +0 3709 3808 +0 3761 3808 +0 3808 3794 +0 3808 3704 +0 3808 3546 +0 3808 3180 +0 3941 0 +0 4074 0 +2973 4095 0 +0 3484 3812 +0 3484 3812 +0 3484 3812 +0 3485 3812 +0 3485 3812 +0 3485 3812 +0 3486 3812 +0 3487 3812 +0 3488 3812 +0 3489 3812 +0 3491 3812 +0 3493 3812 +0 3496 3811 +0 3501 3811 +0 3506 3810 +0 3514 3810 +0 3523 3809 +0 3536 3808 +0 3552 3807 +0 3570 3807 +0 3593 3807 +0 3622 3807 +0 3657 3807 +0 3701 3807 +0 3754 3807 +0 3807 3797 +0 3807 3708 +0 3807 3552 +0 3807 3194 +0 3940 0 +0 4073 0 +3027 4095 0 +0 3462 3812 +0 3462 3812 +0 3463 3812 +0 3463 3812 +0 3463 3812 +0 3464 3812 +0 3464 3812 +0 3465 3812 +0 3466 3812 +0 3468 3812 +0 3469 3812 +0 3472 3812 +0 3475 3811 +0 3480 3811 +0 3486 3810 +0 3493 3810 +0 3503 3809 +0 3517 3808 +0 3534 3807 +0 3556 3805 +0 3579 3805 +0 3609 3805 +0 3646 3805 +0 3690 3805 +0 3744 3805 +0 3805 3802 +0 3805 3714 +0 3805 3561 +0 3805 3211 +0 3939 0 +0 4072 0 +3090 4095 0 +0 3432 3812 +0 3432 3812 +0 3432 3812 +0 3432 3812 +0 3433 3812 +0 3433 3812 +0 3434 3812 +0 3435 3812 +0 3436 3812 +0 3437 3812 +0 3439 3812 +0 3442 3812 +0 3446 3811 +0 3450 3811 +0 3457 3810 +0 3465 3810 +0 3475 3809 +0 3490 3808 +0 3508 3807 +0 3531 3805 +0 3560 3802 +0 3591 3802 +0 3629 3802 +0 3676 3802 +0 3731 3802 +0 3796 3802 +0 3802 3721 +0 3802 3571 +0 3802 3234 +0 3937 0 +0 4071 0 +3164 4095 0 +0 3387 3812 +0 3388 3812 +0 3388 3812 +0 3388 3812 +0 3388 3812 +0 3389 3812 +0 3390 3812 +0 3391 3812 +0 3392 3812 +0 3394 3812 +0 3396 3812 +0 3399 3812 +0 3403 3811 +0 3408 3811 +0 3415 3810 +0 3424 3810 +0 3435 3809 +0 3451 3808 +0 3470 3807 +0 3495 3805 +0 3527 3802 +0 3566 3799 +0 3606 3799 +0 3655 3799 +0 3713 3799 +0 3781 3799 +0 3799 3731 +0 3799 3585 +0 3799 3262 +0 3934 0 +0 4069 0 +3246 4095 0 +0 3320 3812 +0 3321 3812 +0 3321 3812 +0 3321 3812 +0 3322 3812 +0 3322 3812 +0 3323 3812 +0 3324 3812 +0 3326 3812 +0 3328 3812 +0 3330 3812 +0 3333 3812 +0 3338 3811 +0 3344 3811 +0 3352 3810 +0 3362 3810 +0 3376 3809 +0 3393 3808 +0 3415 3807 +0 3443 3805 +0 3479 3802 +0 3522 3799 +0 3574 3794 +0 3626 3794 +0 3687 3794 +0 3759 3794 +0 3794 3745 +0 3794 3603 +0 3794 3298 +0 3931 0 +1985 4066 0 +3337 4095 0 +0 3211 3812 +0 3212 3812 +0 3212 3812 +0 3213 3812 +0 3213 3812 +0 3214 3812 +0 3215 3812 +0 3216 3812 +0 3218 3812 +0 3221 3812 +0 3224 3812 +0 3228 3812 +0 3234 3811 +0 3241 3811 +0 3251 3810 +0 3264 3810 +0 3281 3809 +0 3302 3808 +0 3329 3807 +0 3363 3805 +0 3405 3802 +0 3455 3799 +0 3515 3794 +1799 3584 3788 +1799 3651 3788 +1799 3728 3788 +1799 3788 3761 +1799 3788 3626 +1799 3788 3342 +0 3926 2023 +2781 4063 0 +3436 4095 0 +0 3008 3812 +0 3009 3812 +0 3009 3812 +0 3010 3812 +0 3011 3812 +0 3012 3812 +0 3014 3812 +0 3016 3812 +0 3019 3812 +0 3023 3812 +0 3027 3812 +0 3034 3812 +0 3043 3811 +0 3054 3811 +0 3069 3810 +0 3088 3810 +0 3112 3809 +0 3143 3808 +0 3181 3807 +0 3227 3805 +0 3282 3802 +0 3347 3799 +0 3421 3794 +1799 3505 3788 +2721 3597 3780 +2721 3682 3780 +2721 3776 3780 +2721 3780 3655 +2721 3780 3394 +1928 3920 2556 +3119 4058 0 +3541 4095 0 +0 2367 3812 +0 2369 3812 +0 2371 3812 +0 2374 3812 +0 2377 3812 +0 2382 3812 +0 2389 3812 +0 2397 3812 +0 2408 3812 +0 2422 3812 +0 2441 3812 +0 2465 3812 +0 2494 3811 +0 2531 3811 +0 2576 3810 +0 2631 3810 +0 2694 3809 +0 2767 3808 +0 2850 3807 +0 2941 3805 +0 3040 3802 +0 3145 3799 +0 3256 3794 +1799 3372 3788 +2721 3492 3780 +3072 3614 3768 +3072 3721 3768 +3072 3768 3691 +3072 3768 3456 +2854 3912 2854 +3361 4052 2063 +3653 4095 0 +0 0 3812 +0 0 3812 +0 0 3812 +0 0 3812 +0 0 3812 +0 0 3812 +0 0 3812 +0 0 3812 +0 0 3812 +0 0 3812 +0 0 3812 +0 0 3812 +0 0 3811 +0 0 3811 +0 0 3810 +0 0 3810 +0 0 3809 +0 0 3808 +0 0 3807 +0 0 3805 +0 1737 3802 +0 2519 3799 +0 2856 3794 +1799 3097 3788 +2721 3296 3780 +3072 3473 3768 +3318 3636 3752 +3318 3752 3735 +3318 3752 3528 +3302 3900 3204 +3561 4044 2986 +3768 4095 2192 +0 0 3812 +0 0 3812 +0 0 3812 +0 0 3812 +0 0 3812 +0 0 3812 +0 0 3812 +0 0 3812 +0 0 3812 +0 0 3812 +0 0 3812 +0 0 3812 +0 0 3811 +0 0 3811 +0 0 3810 +0 0 3810 +0 0 3809 +0 0 3808 +0 0 3807 +0 0 3805 +0 0 3802 +0 0 3799 +1884 0 3794 +2422 1799 3788 +2721 2722 3780 +3072 3171 3768 +3318 3447 3752 +3520 3664 3730 +3520 3730 3609 +3579 3884 3450 +3737 4032 3336 +3888 4095 3118 +3137 0 3812 +3137 0 3812 +3137 0 3812 +3138 0 3812 +3138 0 3812 +3138 0 3812 +3139 0 3812 +3139 0 3812 +3140 0 3812 +3141 0 3812 +3143 0 3812 +3145 0 3812 +3147 0 3811 +3151 0 3811 +3155 0 3810 +3161 0 3810 +3169 0 3809 +3180 0 3808 +3194 0 3807 +3211 0 3805 +3234 0 3802 +3262 0 3799 +3298 0 3794 +3342 1799 3788 +3394 2721 3780 +3456 3072 3768 +3528 3318 3752 +3609 3520 3730 +3698 3698 3698 +3796 3862 3652 +3900 4016 3583 +4010 4095 3469 +3660 0 3944 +3660 0 3944 +3660 0 3944 +3660 0 3944 +3660 0 3944 +3660 0 3944 +3660 0 3944 +3660 0 3944 +3661 0 3944 +3661 0 3944 +3661 0 3944 +3662 0 3944 +3663 0 3944 +3664 0 3943 +3665 0 3943 +3667 0 3943 +3670 0 3942 +3674 0 3941 +3678 0 3940 +3685 0 3939 +3692 0 3937 +3703 0 3934 +3717 0 3931 +3735 0 3926 +3758 1928 3920 +3787 2854 3912 +3822 3204 3900 +3867 3450 3884 +3862 3652 3796 +3862 3741 3652 +4016 3999 3583 +4095 4095 3469 +3954 0 4076 +3954 0 4076 +3954 0 4076 +3954 0 4076 +3955 0 4076 +3955 0 4076 +3955 0 4076 +3955 0 4076 +3955 0 4076 +3955 0 4076 +3955 0 4076 +3956 0 4076 +3956 0 4076 +3957 0 4076 +3958 0 4075 +3959 0 4075 +3960 0 4075 +3962 0 4074 +3964 0 4073 +3968 0 4072 +3972 0 4071 +3978 0 4069 +3985 0 4066 +3995 0 4063 +4008 0 4058 +4025 2063 4052 +4044 2986 4040 +4032 3336 3986 +4016 3583 3900 +4016 3583 3711 +4016 3792 3583 +4095 4087 3469 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 2192 4095 +4095 3118 4079 +4095 3469 4010 +4095 3469 3869 +4095 3469 3568 +4095 3853 3469 +0 3674 3944 +0 3674 3944 +0 3674 3944 +0 3674 3944 +0 3675 3944 +0 3675 3944 +0 3675 3944 +0 3676 3944 +0 3676 3944 +0 3677 3944 +0 3678 3944 +0 3679 3944 +0 3681 3944 +0 3683 3944 +0 3687 3944 +0 3691 3944 +0 3696 3944 +0 3704 3944 +0 3713 3944 +0 3726 3944 +0 3742 3944 +0 3763 3944 +0 3790 3944 +0 3823 3944 +0 3864 3944 +0 3913 3944 +0 3944 3915 +0 3944 3822 +0 3944 3660 +0 3944 3269 +0 4076 0 +0 4095 0 +0 3674 3944 +0 3674 3944 +0 3674 3944 +0 3674 3944 +0 3675 3944 +0 3675 3944 +0 3675 3944 +0 3676 3944 +0 3676 3944 +0 3677 3944 +0 3678 3944 +0 3679 3944 +0 3681 3944 +0 3683 3944 +0 3687 3944 +0 3691 3944 +0 3696 3944 +0 3704 3944 +0 3713 3944 +0 3726 3944 +0 3742 3944 +0 3763 3944 +0 3790 3944 +0 3823 3944 +0 3864 3944 +0 3913 3944 +0 3944 3915 +0 3944 3822 +0 3944 3660 +0 3944 3269 +0 4076 0 +0 4095 0 +0 3674 3944 +0 3674 3944 +0 3674 3944 +0 3674 3944 +0 3675 3944 +0 3675 3944 +0 3675 3944 +0 3676 3944 +0 3676 3944 +0 3677 3944 +0 3678 3944 +0 3679 3944 +0 3681 3944 +0 3683 3944 +0 3687 3944 +0 3691 3944 +0 3696 3944 +0 3704 3944 +0 3713 3944 +0 3726 3944 +0 3742 3944 +0 3763 3944 +0 3790 3944 +0 3823 3944 +0 3863 3944 +0 3913 3944 +0 3944 3915 +0 3944 3822 +0 3944 3660 +0 3944 3269 +0 4076 0 +0 4095 0 +0 3674 3944 +0 3674 3944 +0 3674 3944 +0 3674 3944 +0 3674 3944 +0 3675 3944 +0 3675 3944 +0 3676 3944 +0 3676 3944 +0 3677 3944 +0 3678 3944 +0 3679 3944 +0 3681 3944 +0 3683 3944 +0 3686 3944 +0 3691 3944 +0 3696 3944 +0 3703 3944 +0 3713 3944 +0 3726 3944 +0 3742 3944 +0 3763 3944 +0 3790 3944 +0 3822 3944 +0 3863 3944 +0 3913 3944 +0 3944 3915 +0 3944 3823 +0 3944 3660 +0 3944 3269 +0 4076 0 +0 4095 0 +0 3674 3944 +0 3674 3944 +0 3674 3944 +0 3674 3944 +0 3674 3944 +0 3674 3944 +0 3675 3944 +0 3675 3944 +0 3676 3944 +0 3677 3944 +0 3678 3944 +0 3679 3944 +0 3681 3944 +0 3683 3944 +0 3686 3944 +0 3691 3944 +0 3696 3944 +0 3703 3944 +0 3713 3944 +0 3726 3944 +0 3742 3944 +0 3763 3944 +0 3789 3944 +0 3822 3944 +0 3863 3944 +0 3913 3944 +0 3944 3915 +0 3944 3823 +0 3944 3660 +0 3944 3270 +0 4076 0 +0 4095 0 +0 3674 3944 +0 3674 3944 +0 3674 3944 +0 3674 3944 +0 3674 3944 +0 3674 3944 +0 3675 3944 +0 3675 3944 +0 3676 3944 +0 3676 3944 +0 3677 3944 +0 3679 3944 +0 3681 3944 +0 3683 3944 +0 3686 3944 +0 3690 3944 +0 3696 3944 +0 3703 3944 +0 3713 3944 +0 3725 3944 +0 3742 3944 +0 3763 3944 +0 3789 3944 +0 3822 3944 +0 3863 3944 +0 3913 3944 +0 3944 3915 +0 3944 3823 +0 3944 3660 +0 3944 3270 +0 4076 0 +0 4095 0 +0 3673 3944 +0 3673 3944 +0 3673 3944 +0 3674 3944 +0 3674 3944 +0 3674 3944 +0 3674 3944 +0 3675 3944 +0 3676 3944 +0 3676 3944 +0 3677 3944 +0 3679 3944 +0 3680 3944 +0 3683 3944 +0 3686 3944 +0 3690 3944 +0 3696 3944 +0 3703 3944 +0 3713 3944 +0 3725 3944 +0 3741 3944 +0 3762 3944 +0 3789 3944 +0 3822 3944 +0 3863 3944 +0 3913 3944 +0 3944 3915 +0 3944 3823 +0 3944 3660 +0 3944 3270 +0 4076 0 +0 4095 0 +0 3673 3944 +0 3673 3944 +0 3673 3944 +0 3673 3944 +0 3673 3944 +0 3674 3944 +0 3674 3944 +0 3674 3944 +0 3675 3944 +0 3676 3944 +0 3677 3944 +0 3678 3944 +0 3680 3944 +0 3682 3944 +0 3686 3944 +0 3690 3944 +0 3695 3944 +0 3703 3944 +0 3712 3944 +0 3725 3944 +0 3741 3944 +0 3762 3944 +0 3789 3944 +0 3822 3944 +0 3863 3944 +0 3912 3944 +0 3944 3915 +0 3944 3823 +0 3944 3660 +0 3944 3271 +0 4076 0 +0 4095 0 +0 3672 3944 +0 3672 3944 +0 3673 3944 +0 3673 3944 +0 3673 3944 +0 3673 3944 +0 3673 3944 +0 3674 3944 +0 3675 3944 +0 3675 3944 +0 3676 3944 +0 3678 3944 +0 3680 3944 +0 3682 3944 +0 3685 3944 +0 3689 3944 +0 3695 3944 +0 3702 3944 +0 3712 3944 +0 3725 3944 +0 3741 3944 +0 3762 3944 +0 3788 3944 +0 3822 3944 +0 3863 3944 +0 3912 3944 +0 3944 3915 +0 3944 3823 +0 3944 3661 +0 3944 3271 +0 4076 0 +0 4095 0 +0 3671 3944 +0 3671 3944 +0 3672 3944 +0 3672 3944 +0 3672 3944 +0 3672 3944 +0 3673 3944 +0 3673 3944 +0 3674 3944 +0 3675 3944 +0 3676 3944 +0 3677 3944 +0 3679 3944 +0 3681 3944 +0 3685 3944 +0 3689 3944 +0 3694 3944 +0 3702 3944 +0 3711 3944 +0 3724 3944 +0 3740 3944 +0 3761 3944 +0 3788 3944 +0 3821 3944 +0 3862 3944 +0 3912 3944 +0 3944 3916 +0 3944 3824 +0 3944 3661 +0 3944 3272 +0 4076 0 +0 4095 0 +0 3670 3944 +0 3671 3944 +0 3671 3944 +0 3671 3944 +0 3671 3944 +0 3671 3944 +0 3672 3944 +0 3672 3944 +0 3673 3944 +0 3674 3944 +0 3675 3944 +0 3676 3944 +0 3678 3944 +0 3680 3944 +0 3684 3944 +0 3688 3944 +0 3694 3944 +0 3701 3944 +0 3711 3944 +0 3723 3944 +0 3740 3944 +0 3761 3944 +0 3787 3944 +0 3820 3944 +0 3862 3944 +0 3911 3944 +0 3944 3916 +0 3944 3824 +0 3944 3661 +0 3944 3273 +0 4076 0 +0 4095 0 +0 3669 3944 +0 3669 3944 +0 3669 3944 +0 3669 3944 +0 3670 3944 +0 3670 3944 +0 3670 3944 +0 3671 3944 +0 3671 3944 +0 3673 3944 +0 3674 3944 +0 3675 3944 +0 3677 3944 +0 3679 3944 +0 3683 3944 +0 3687 3944 +0 3692 3944 +0 3700 3944 +0 3710 3944 +0 3722 3944 +0 3739 3944 +0 3760 3944 +0 3786 3944 +0 3820 3944 +0 3861 3944 +0 3910 3944 +0 3944 3916 +0 3944 3824 +0 3944 3662 +0 3944 3275 +0 4076 0 +0 4095 0 +0 3667 3944 +0 3667 3944 +0 3668 3944 +0 3668 3944 +0 3668 3944 +0 3668 3944 +0 3668 3944 +0 3669 3944 +0 3670 3944 +0 3671 3944 +0 3672 3944 +0 3673 3944 +0 3676 3944 +0 3678 3944 +0 3681 3944 +0 3685 3944 +0 3691 3944 +0 3699 3944 +0 3708 3944 +0 3721 3944 +0 3737 3944 +0 3758 3944 +0 3785 3944 +0 3819 3944 +0 3860 3944 +0 3910 3944 +0 3944 3917 +0 3944 3825 +0 3944 3663 +0 3944 3277 +0 4076 0 +0 4095 0 +0 3665 3944 +0 3665 3944 +0 3665 3944 +0 3665 3944 +0 3665 3944 +0 3666 3944 +0 3666 3944 +0 3666 3944 +0 3667 3944 +0 3668 3944 +0 3669 3944 +0 3671 3944 +0 3673 3944 +0 3676 3943 +0 3679 3943 +0 3683 3943 +0 3689 3943 +0 3697 3943 +0 3706 3943 +0 3719 3943 +0 3736 3943 +0 3757 3943 +0 3784 3943 +0 3817 3943 +0 3859 3943 +0 3909 3943 +0 3943 3917 +0 3943 3826 +0 3943 3664 +0 3943 3279 +0 4076 0 +0 4095 0 +0 3661 3944 +0 3662 3944 +0 3662 3944 +0 3662 3944 +0 3662 3944 +0 3662 3944 +0 3663 3944 +0 3663 3944 +0 3664 3944 +0 3665 3944 +0 3666 3944 +0 3668 3944 +0 3670 3944 +0 3673 3943 +0 3677 3943 +0 3681 3943 +0 3687 3943 +0 3694 3943 +0 3704 3943 +0 3717 3943 +0 3733 3943 +0 3755 3943 +0 3781 3943 +0 3815 3943 +0 3857 3943 +0 3907 3943 +0 3943 3918 +0 3943 3827 +0 3943 3665 +0 3943 3283 +0 4075 0 +0 4095 0 +0 3657 3944 +0 3657 3944 +0 3657 3944 +0 3657 3944 +0 3658 3944 +0 3658 3944 +0 3658 3944 +0 3659 3944 +0 3659 3944 +0 3661 3944 +0 3662 3944 +0 3663 3944 +0 3666 3944 +0 3668 3943 +0 3672 3943 +0 3677 3943 +0 3683 3943 +0 3691 3943 +0 3701 3943 +0 3713 3943 +0 3730 3943 +0 3752 3943 +0 3779 3943 +0 3813 3943 +0 3854 3943 +0 3905 3943 +0 3943 3920 +0 3943 3828 +0 3943 3667 +0 3943 3287 +0 4075 0 +0 4095 0 +0 3651 3944 +0 3651 3944 +0 3651 3944 +0 3651 3944 +0 3652 3944 +0 3652 3944 +0 3652 3944 +0 3653 3944 +0 3653 3944 +0 3654 3944 +0 3656 3944 +0 3657 3944 +0 3659 3944 +0 3662 3943 +0 3666 3943 +0 3672 3943 +0 3679 3942 +0 3686 3942 +0 3696 3942 +0 3709 3942 +0 3726 3942 +0 3748 3942 +0 3775 3942 +0 3809 3942 +0 3851 3942 +0 3902 3942 +0 3942 3921 +0 3942 3830 +0 3942 3670 +0 3942 3293 +0 4075 0 +0 4095 0 +0 3643 3944 +0 3643 3944 +0 3643 3944 +0 3643 3944 +0 3643 3944 +0 3644 3944 +0 3644 3944 +0 3645 3944 +0 3645 3944 +0 3646 3944 +0 3648 3944 +0 3649 3944 +0 3651 3944 +0 3655 3943 +0 3659 3943 +0 3664 3943 +0 3671 3942 +0 3680 3941 +0 3690 3941 +0 3703 3941 +0 3720 3941 +0 3742 3941 +0 3770 3941 +0 3805 3941 +0 3847 3941 +0 3898 3941 +0 3941 3923 +0 3941 3832 +0 3941 3674 +0 3941 3302 +0 4074 0 +0 4095 0 +0 3631 3944 +0 3632 3944 +0 3632 3944 +0 3632 3944 +0 3632 3944 +0 3632 3944 +0 3633 3944 +0 3633 3944 +0 3634 3944 +0 3635 3944 +0 3636 3944 +0 3638 3944 +0 3640 3944 +0 3644 3943 +0 3648 3943 +0 3653 3943 +0 3660 3942 +0 3669 3941 +0 3682 3940 +0 3695 3940 +0 3713 3940 +0 3735 3940 +0 3763 3940 +0 3798 3940 +0 3841 3940 +0 3893 3940 +0 3940 3926 +0 3940 3836 +0 3940 3678 +0 3940 3312 +0 4073 0 +0 4095 0 +0 3616 3944 +0 3616 3944 +0 3616 3944 +0 3616 3944 +0 3617 3944 +0 3617 3944 +0 3617 3944 +0 3618 3944 +0 3619 3944 +0 3620 3944 +0 3621 3944 +0 3623 3944 +0 3625 3944 +0 3628 3943 +0 3632 3943 +0 3638 3943 +0 3646 3942 +0 3655 3941 +0 3668 3940 +0 3684 3939 +0 3702 3939 +0 3725 3939 +0 3754 3939 +0 3790 3939 +0 3833 3939 +0 3886 3939 +0 3939 3929 +0 3939 3840 +0 3939 3685 +0 3939 3326 +0 4072 0 +0 4095 0 +0 3594 3944 +0 3595 3944 +0 3595 3944 +0 3595 3944 +0 3595 3944 +0 3595 3944 +0 3596 3944 +0 3596 3944 +0 3597 3944 +0 3598 3944 +0 3600 3944 +0 3602 3944 +0 3604 3944 +0 3607 3943 +0 3612 3943 +0 3618 3943 +0 3626 3942 +0 3635 3941 +0 3649 3940 +0 3666 3939 +0 3688 3937 +0 3711 3937 +0 3741 3937 +0 3777 3937 +0 3822 3937 +0 3876 3937 +0 3937 3934 +0 3937 3846 +0 3937 3692 +0 3937 3344 +0 4071 0 +0 4095 0 +0 3564 3944 +0 3564 3944 +0 3564 3944 +0 3564 3944 +0 3564 3944 +0 3565 3944 +0 3565 3944 +0 3566 3944 +0 3567 3944 +0 3568 3944 +0 3569 3944 +0 3571 3944 +0 3574 3944 +0 3578 3943 +0 3583 3943 +0 3589 3943 +0 3597 3942 +0 3608 3941 +0 3622 3940 +0 3640 3939 +0 3663 3937 +0 3692 3934 +0 3723 3934 +0 3761 3934 +0 3808 3934 +0 3863 3934 +0 3928 3934 +0 3934 3853 +0 3934 3703 +0 3934 3366 +0 4069 0 +0 4095 0 +0 3520 3944 +0 3520 3944 +0 3520 3944 +0 3520 3944 +0 3520 3944 +0 3521 3944 +0 3521 3944 +0 3522 3944 +0 3523 3944 +0 3524 3944 +0 3526 3944 +0 3528 3944 +0 3531 3944 +0 3535 3943 +0 3540 3943 +0 3547 3943 +0 3556 3942 +0 3568 3941 +0 3583 3940 +0 3603 3939 +0 3628 3937 +0 3659 3934 +0 3698 3931 +0 3738 3931 +0 3787 3931 +0 3845 3931 +0 3913 3931 +0 3931 3863 +0 3931 3717 +0 3931 3395 +0 4066 0 +0 4095 0 +0 3452 3944 +0 3452 3944 +0 3453 3944 +0 3453 3944 +0 3453 3944 +0 3454 3944 +0 3454 3944 +0 3455 3944 +0 3456 3944 +0 3458 3944 +0 3459 3944 +0 3462 3944 +0 3466 3944 +0 3470 3943 +0 3476 3943 +0 3484 3943 +0 3494 3942 +0 3507 3941 +0 3525 3940 +0 3547 3939 +0 3575 3937 +0 3611 3934 +0 3654 3931 +0 3706 3926 +0 3758 3926 +0 3820 3926 +0 3891 3926 +0 3926 3877 +0 3926 3735 +0 3926 3430 +0 4063 0 +2137 4095 0 +0 3344 3944 +0 3344 3944 +0 3344 3944 +0 3344 3944 +0 3345 3944 +0 3346 3944 +0 3346 3944 +0 3347 3944 +0 3349 3944 +0 3351 3944 +0 3353 3944 +0 3356 3944 +0 3361 3944 +0 3366 3943 +0 3374 3943 +0 3384 3943 +0 3396 3942 +0 3413 3941 +0 3434 3940 +0 3461 3939 +0 3495 3937 +0 3537 3934 +0 3587 3931 +0 3647 3926 +1928 3716 3920 +1928 3783 3920 +1928 3860 3920 +1928 3920 3893 +1928 3920 3758 +1928 3920 3474 +0 4058 2157 +2915 4095 0 +0 3140 3944 +0 3140 3944 +0 3140 3944 +0 3141 3944 +0 3142 3944 +0 3143 3944 +0 3144 3944 +0 3145 3944 +0 3147 3944 +0 3151 3944 +0 3154 3944 +0 3159 3944 +0 3166 3944 +0 3175 3943 +0 3186 3943 +0 3201 3943 +0 3220 3942 +0 3244 3941 +0 3275 3940 +0 3313 3939 +0 3359 3937 +0 3414 3934 +0 3479 3931 +0 3553 3926 +1928 3637 3920 +2854 3729 3912 +2854 3814 3912 +2854 3908 3912 +2854 3912 3787 +2854 3912 3526 +2063 4052 2689 +3253 4095 0 +0 2497 3944 +0 2498 3944 +0 2500 3944 +0 2502 3944 +0 2505 3944 +0 2508 3944 +0 2513 3944 +0 2520 3944 +0 2528 3944 +0 2539 3944 +0 2553 3944 +0 2572 3944 +0 2596 3944 +0 2625 3943 +0 2662 3943 +0 2708 3943 +0 2762 3942 +0 2826 3941 +0 2899 3940 +0 2982 3939 +0 3073 3937 +0 3172 3934 +0 3277 3931 +0 3388 3926 +1928 3504 3920 +2854 3624 3912 +3204 3746 3900 +3204 3853 3900 +3204 3900 3822 +3204 3900 3588 +2987 4044 2986 +3494 4095 2192 +0 0 3944 +0 0 3944 +0 0 3944 +0 0 3944 +0 0 3944 +0 0 3944 +0 0 3944 +0 0 3944 +0 0 3944 +0 0 3944 +0 0 3944 +0 0 3944 +0 0 3944 +0 0 3943 +0 0 3943 +0 0 3943 +0 0 3942 +0 0 3941 +0 0 3940 +0 0 3939 +0 0 3937 +0 1863 3934 +0 2650 3931 +0 2988 3926 +1928 3229 3920 +2854 3428 3912 +3204 3605 3900 +3450 3768 3884 +3450 3884 3867 +3450 3884 3660 +3435 4032 3336 +3693 4095 3118 +0 0 3944 +0 0 3944 +0 0 3944 +0 0 3944 +0 0 3944 +0 0 3944 +0 0 3944 +0 0 3944 +0 0 3944 +0 0 3944 +0 0 3944 +0 0 3944 +0 0 3944 +0 0 3943 +0 0 3943 +0 0 3943 +0 0 3942 +0 0 3941 +0 0 3940 +0 0 3939 +0 0 3937 +0 0 3934 +0 0 3931 +2023 0 3926 +2556 1928 3920 +2854 2854 3912 +3204 3302 3900 +3450 3579 3884 +3652 3796 3862 +3652 3862 3741 +3711 4016 3583 +3869 4095 3469 +3269 0 3944 +3269 0 3944 +3269 0 3944 +3269 0 3944 +3270 0 3944 +3270 0 3944 +3270 0 3944 +3271 0 3944 +3271 0 3944 +3272 0 3944 +3273 0 3944 +3275 0 3944 +3277 0 3944 +3279 0 3943 +3283 0 3943 +3287 0 3943 +3293 0 3942 +3302 0 3941 +3312 0 3940 +3326 0 3939 +3344 0 3937 +3366 0 3934 +3395 0 3931 +3430 0 3926 +3474 1928 3920 +3526 2854 3912 +3588 3204 3900 +3660 3450 3884 +3741 3652 3862 +3830 3830 3830 +3928 3994 3784 +4032 4095 3714 +3791 0 4076 +3792 0 4076 +3792 0 4076 +3792 0 4076 +3792 0 4076 +3792 0 4076 +3792 0 4076 +3792 0 4076 +3792 0 4076 +3793 0 4076 +3793 0 4076 +3793 0 4076 +3794 0 4076 +3795 0 4076 +3796 0 4075 +3797 0 4075 +3799 0 4075 +3802 0 4074 +3805 0 4073 +3810 0 4072 +3816 0 4071 +3824 0 4069 +3835 0 4066 +3849 0 4063 +3867 0 4058 +3890 2063 4052 +3919 2986 4044 +3955 3336 4032 +3999 3583 4016 +3994 3784 3928 +3994 3873 3784 +4095 4095 3714 +4087 0 4095 +4087 0 4095 +4087 0 4095 +4087 0 4095 +4087 0 4095 +4087 0 4095 +4087 0 4095 +4087 0 4095 +4087 0 4095 +4088 0 4095 +4088 0 4095 +4088 0 4095 +4088 0 4095 +4089 0 4095 +4089 0 4095 +4090 0 4095 +4091 0 4095 +4092 0 4095 +4094 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 0 4095 +4095 2192 4095 +4095 3118 4095 +4095 3469 4095 +4095 3714 4032 +4095 3714 3844 +4095 3924 3714 +0 3806 4076 +0 3806 4076 +0 3806 4076 +0 3806 4076 +0 3807 4076 +0 3807 4076 +0 3807 4076 +0 3808 4076 +0 3808 4076 +0 3808 4076 +0 3809 4076 +0 3810 4076 +0 3812 4076 +0 3813 4076 +0 3816 4076 +0 3819 4076 +0 3823 4076 +0 3828 4076 +0 3836 4076 +0 3846 4076 +0 3858 4076 +0 3874 4076 +0 3895 4076 +0 3922 4076 +0 3955 4076 +0 3996 4076 +0 4045 4076 +0 4076 4047 +0 4076 3954 +0 4076 3791 +0 4076 3401 +0 4095 0 +0 3806 4076 +0 3806 4076 +0 3806 4076 +0 3806 4076 +0 3807 4076 +0 3807 4076 +0 3807 4076 +0 3807 4076 +0 3808 4076 +0 3808 4076 +0 3809 4076 +0 3810 4076 +0 3811 4076 +0 3813 4076 +0 3816 4076 +0 3819 4076 +0 3823 4076 +0 3828 4076 +0 3836 4076 +0 3845 4076 +0 3858 4076 +0 3874 4076 +0 3895 4076 +0 3922 4076 +0 3955 4076 +0 3996 4076 +0 4045 4076 +0 4076 4047 +0 4076 3954 +0 4076 3792 +0 4076 3401 +0 4095 0 +0 3806 4076 +0 3806 4076 +0 3806 4076 +0 3806 4076 +0 3807 4076 +0 3807 4076 +0 3807 4076 +0 3807 4076 +0 3808 4076 +0 3808 4076 +0 3809 4076 +0 3810 4076 +0 3811 4076 +0 3813 4076 +0 3816 4076 +0 3819 4076 +0 3823 4076 +0 3828 4076 +0 3836 4076 +0 3845 4076 +0 3858 4076 +0 3874 4076 +0 3895 4076 +0 3921 4076 +0 3955 4076 +0 3996 4076 +0 4045 4076 +0 4076 4047 +0 4076 3954 +0 4076 3792 +0 4076 3401 +0 4095 0 +0 3806 4076 +0 3806 4076 +0 3806 4076 +0 3806 4076 +0 3806 4076 +0 3807 4076 +0 3807 4076 +0 3807 4076 +0 3808 4076 +0 3808 4076 +0 3809 4076 +0 3810 4076 +0 3811 4076 +0 3813 4076 +0 3815 4076 +0 3818 4076 +0 3823 4076 +0 3828 4076 +0 3836 4076 +0 3845 4076 +0 3858 4076 +0 3874 4076 +0 3895 4076 +0 3921 4076 +0 3955 4076 +0 3995 4076 +0 4045 4076 +0 4076 4047 +0 4076 3954 +0 4076 3792 +0 4076 3401 +0 4095 0 +0 3806 4076 +0 3806 4076 +0 3806 4076 +0 3806 4076 +0 3806 4076 +0 3807 4076 +0 3807 4076 +0 3807 4076 +0 3808 4076 +0 3808 4076 +0 3809 4076 +0 3810 4076 +0 3811 4076 +0 3813 4076 +0 3815 4076 +0 3818 4076 +0 3823 4076 +0 3828 4076 +0 3836 4076 +0 3845 4076 +0 3858 4076 +0 3874 4076 +0 3895 4076 +0 3921 4076 +0 3955 4076 +0 3995 4076 +0 4045 4076 +0 4076 4047 +0 4076 3955 +0 4076 3792 +0 4076 3401 +0 4095 0 +0 3806 4076 +0 3806 4076 +0 3806 4076 +0 3806 4076 +0 3806 4076 +0 3806 4076 +0 3807 4076 +0 3807 4076 +0 3808 4076 +0 3808 4076 +0 3809 4076 +0 3810 4076 +0 3811 4076 +0 3813 4076 +0 3815 4076 +0 3818 4076 +0 3822 4076 +0 3828 4076 +0 3835 4076 +0 3845 4076 +0 3858 4076 +0 3874 4076 +0 3895 4076 +0 3921 4076 +0 3954 4076 +0 3995 4076 +0 4045 4076 +0 4076 4047 +0 4076 3955 +0 4076 3792 +0 4076 3402 +0 4095 0 +0 3805 4076 +0 3805 4076 +0 3805 4076 +0 3806 4076 +0 3806 4076 +0 3806 4076 +0 3806 4076 +0 3807 4076 +0 3807 4076 +0 3808 4076 +0 3808 4076 +0 3810 4076 +0 3811 4076 +0 3812 4076 +0 3815 4076 +0 3818 4076 +0 3822 4076 +0 3828 4076 +0 3835 4076 +0 3845 4076 +0 3858 4076 +0 3874 4076 +0 3895 4076 +0 3921 4076 +0 3954 4076 +0 3995 4076 +0 4045 4076 +0 4076 4047 +0 4076 3955 +0 4076 3792 +0 4076 3402 +0 4095 0 +0 3805 4076 +0 3805 4076 +0 3805 4076 +0 3805 4076 +0 3805 4076 +0 3806 4076 +0 3806 4076 +0 3806 4076 +0 3807 4076 +0 3808 4076 +0 3808 4076 +0 3809 4076 +0 3810 4076 +0 3812 4076 +0 3815 4076 +0 3818 4076 +0 3822 4076 +0 3828 4076 +0 3835 4076 +0 3845 4076 +0 3857 4076 +0 3873 4076 +0 3895 4076 +0 3921 4076 +0 3954 4076 +0 3995 4076 +0 4045 4076 +0 4076 4047 +0 4076 3955 +0 4076 3792 +0 4076 3402 +0 4095 0 +0 3805 4076 +0 3805 4076 +0 3805 4076 +0 3805 4076 +0 3805 4076 +0 3805 4076 +0 3805 4076 +0 3806 4076 +0 3807 4076 +0 3807 4076 +0 3808 4076 +0 3809 4076 +0 3810 4076 +0 3812 4076 +0 3814 4076 +0 3818 4076 +0 3822 4076 +0 3827 4076 +0 3835 4076 +0 3845 4076 +0 3857 4076 +0 3873 4076 +0 3894 4076 +0 3921 4076 +0 3954 4076 +0 3995 4076 +0 4044 4076 +0 4076 4047 +0 4076 3955 +0 4076 3792 +0 4076 3403 +0 4095 0 +0 3804 4076 +0 3804 4076 +0 3804 4076 +0 3805 4076 +0 3805 4076 +0 3805 4076 +0 3805 4076 +0 3805 4076 +0 3806 4076 +0 3807 4076 +0 3808 4076 +0 3808 4076 +0 3810 4076 +0 3812 4076 +0 3814 4076 +0 3817 4076 +0 3821 4076 +0 3827 4076 +0 3834 4076 +0 3844 4076 +0 3856 4076 +0 3873 4076 +0 3894 4076 +0 3921 4076 +0 3953 4076 +0 3995 4076 +0 4044 4076 +0 4076 4047 +0 4076 3955 +0 4076 3793 +0 4076 3403 +0 4095 0 +0 3803 4076 +0 3803 4076 +0 3803 4076 +0 3804 4076 +0 3804 4076 +0 3804 4076 +0 3804 4076 +0 3805 4076 +0 3805 4076 +0 3806 4076 +0 3807 4076 +0 3808 4076 +0 3809 4076 +0 3811 4076 +0 3813 4076 +0 3816 4076 +0 3821 4076 +0 3826 4076 +0 3834 4076 +0 3843 4076 +0 3856 4076 +0 3872 4076 +0 3893 4076 +0 3920 4076 +0 3953 4076 +0 3994 4076 +0 4044 4076 +0 4076 4048 +0 4076 3955 +0 4076 3793 +0 4076 3404 +0 4095 0 +0 3803 4076 +0 3803 4076 +0 3803 4076 +0 3803 4076 +0 3803 4076 +0 3803 4076 +0 3803 4076 +0 3804 4076 +0 3804 4076 +0 3805 4076 +0 3806 4076 +0 3807 4076 +0 3808 4076 +0 3810 4076 +0 3812 4076 +0 3816 4076 +0 3820 4076 +0 3826 4076 +0 3833 4076 +0 3843 4076 +0 3855 4076 +0 3872 4076 +0 3892 4076 +0 3919 4076 +0 3953 4076 +0 3994 4076 +0 4043 4076 +0 4076 4048 +0 4076 3956 +0 4076 3793 +0 4076 3405 +0 4095 0 +0 3801 4076 +0 3801 4076 +0 3801 4076 +0 3801 4076 +0 3801 4076 +0 3802 4076 +0 3802 4076 +0 3802 4076 +0 3803 4076 +0 3803 4076 +0 3804 4076 +0 3805 4076 +0 3807 4076 +0 3809 4076 +0 3812 4076 +0 3814 4076 +0 3819 4076 +0 3824 4076 +0 3832 4076 +0 3841 4076 +0 3854 4076 +0 3871 4076 +0 3891 4076 +0 3918 4076 +0 3952 4076 +0 3993 4076 +0 4043 4076 +0 4076 4048 +0 4076 3956 +0 4076 3794 +0 4076 3407 +0 4095 0 +0 3799 4076 +0 3799 4076 +0 3799 4076 +0 3799 4076 +0 3800 4076 +0 3800 4076 +0 3800 4076 +0 3801 4076 +0 3801 4076 +0 3802 4076 +0 3803 4076 +0 3804 4076 +0 3805 4076 +0 3808 4076 +0 3810 4076 +0 3813 4076 +0 3817 4076 +0 3823 4076 +0 3830 4076 +0 3840 4076 +0 3853 4076 +0 3869 4076 +0 3890 4076 +0 3917 4076 +0 3950 4076 +0 3992 4076 +0 4042 4076 +0 4076 4049 +0 4076 3957 +0 4076 3795 +0 4076 3409 +0 4095 0 +0 3797 4076 +0 3797 4076 +0 3797 4076 +0 3797 4076 +0 3797 4076 +0 3797 4076 +0 3798 4076 +0 3798 4076 +0 3798 4076 +0 3799 4076 +0 3800 4076 +0 3801 4076 +0 3803 4076 +0 3805 4076 +0 3808 4075 +0 3811 4075 +0 3816 4075 +0 3821 4075 +0 3829 4075 +0 3838 4075 +0 3851 4075 +0 3868 4075 +0 3889 4075 +0 3916 4075 +0 3949 4075 +0 3991 4075 +0 4041 4075 +0 4075 4049 +0 4075 3958 +0 4075 3796 +0 4075 3411 +0 4095 0 +0 3793 4076 +0 3793 4076 +0 3793 4076 +0 3794 4076 +0 3794 4076 +0 3794 4076 +0 3794 4076 +0 3795 4076 +0 3795 4076 +0 3796 4076 +0 3797 4076 +0 3798 4076 +0 3800 4076 +0 3802 4076 +0 3805 4075 +0 3809 4075 +0 3813 4075 +0 3818 4075 +0 3826 4075 +0 3836 4075 +0 3849 4075 +0 3865 4075 +0 3887 4075 +0 3913 4075 +0 3947 4075 +0 3989 4075 +0 4039 4075 +0 4075 4050 +0 4075 3959 +0 4075 3797 +0 4075 3415 +0 4095 0 +0 3789 4076 +0 3789 4076 +0 3789 4076 +0 3789 4076 +0 3790 4076 +0 3790 4076 +0 3790 4076 +0 3790 4076 +0 3791 4076 +0 3791 4076 +0 3793 4076 +0 3794 4076 +0 3795 4076 +0 3798 4076 +0 3801 4075 +0 3804 4075 +0 3810 4075 +0 3815 4075 +0 3823 4075 +0 3833 4075 +0 3846 4075 +0 3862 4075 +0 3884 4075 +0 3911 4075 +0 3945 4075 +0 3986 4075 +0 4037 4075 +0 4075 4051 +0 4075 3960 +0 4075 3799 +0 4075 3419 +0 4095 0 +0 3783 4076 +0 3783 4076 +0 3783 4076 +0 3783 4076 +0 3783 4076 +0 3784 4076 +0 3784 4076 +0 3784 4076 +0 3785 4076 +0 3785 4076 +0 3787 4076 +0 3787 4076 +0 3789 4076 +0 3792 4076 +0 3795 4075 +0 3798 4075 +0 3803 4075 +0 3810 4074 +0 3818 4074 +0 3828 4074 +0 3841 4074 +0 3858 4074 +0 3880 4074 +0 3907 4074 +0 3941 4074 +0 3983 4074 +0 4034 4074 +0 4074 4053 +0 4074 3962 +0 4074 3802 +0 4074 3426 +0 4095 0 +0 3774 4076 +0 3775 4076 +0 3775 4076 +0 3775 4076 +0 3775 4076 +0 3775 4076 +0 3776 4076 +0 3776 4076 +0 3777 4076 +0 3777 4076 +0 3778 4076 +0 3780 4076 +0 3781 4076 +0 3784 4076 +0 3787 4075 +0 3790 4075 +0 3796 4075 +0 3803 4074 +0 3812 4073 +0 3822 4073 +0 3835 4073 +0 3852 4073 +0 3874 4073 +0 3902 4073 +0 3937 4073 +0 3979 4073 +0 4030 4073 +0 4073 4055 +0 4073 3964 +0 4073 3805 +0 4073 3434 +0 4095 0 +0 3763 4076 +0 3763 4076 +0 3763 4076 +0 3764 4076 +0 3764 4076 +0 3764 4076 +0 3764 4076 +0 3765 4076 +0 3765 4076 +0 3766 4076 +0 3767 4076 +0 3768 4076 +0 3770 4076 +0 3773 4076 +0 3776 4075 +0 3780 4075 +0 3785 4075 +0 3792 4074 +0 3801 4073 +0 3814 4072 +0 3827 4072 +0 3845 4072 +0 3867 4072 +0 3895 4072 +0 3930 4072 +0 3973 4072 +0 4025 4072 +0 4072 4058 +0 4072 3968 +0 4072 3810 +0 4072 3444 +0 4095 0 +0 3748 4076 +0 3748 4076 +0 3748 4076 +0 3748 4076 +0 3748 4076 +0 3749 4076 +0 3749 4076 +0 3749 4076 +0 3750 4076 +0 3751 4076 +0 3752 4076 +0 3753 4076 +0 3755 4076 +0 3757 4076 +0 3760 4075 +0 3765 4075 +0 3770 4075 +0 3777 4074 +0 3787 4073 +0 3800 4072 +0 3816 4071 +0 3834 4071 +0 3857 4071 +0 3886 4071 +0 3921 4071 +0 3965 4071 +0 4018 4071 +0 4071 4061 +0 4071 3972 +0 4071 3816 +0 4071 3458 +0 4095 0 +0 3726 4076 +0 3726 4076 +0 3726 4076 +0 3727 4076 +0 3727 4076 +0 3727 4076 +0 3727 4076 +0 3728 4076 +0 3728 4076 +0 3729 4076 +0 3730 4076 +0 3732 4076 +0 3734 4076 +0 3736 4076 +0 3739 4075 +0 3744 4075 +0 3750 4075 +0 3757 4074 +0 3768 4073 +0 3781 4072 +0 3798 4071 +0 3820 4069 +0 3843 4069 +0 3873 4069 +0 3910 4069 +0 3954 4069 +0 4008 4069 +0 4069 4066 +0 4069 3978 +0 4069 3824 +0 4069 3475 +0 4095 0 +0 3696 4076 +0 3696 4076 +0 3696 4076 +0 3696 4076 +0 3696 4076 +0 3696 4076 +0 3697 4076 +0 3697 4076 +0 3698 4076 +0 3699 4076 +0 3700 4076 +0 3701 4076 +0 3703 4076 +0 3706 4076 +0 3710 4075 +0 3714 4075 +0 3721 4075 +0 3729 4074 +0 3740 4073 +0 3754 4072 +0 3772 4071 +0 3795 4069 +0 3824 4066 +0 3855 4066 +0 3893 4066 +0 3940 4066 +0 3995 4066 +0 4060 4066 +0 4066 3985 +0 4066 3835 +0 4066 3498 +0 4095 0 +0 3651 4076 +0 3651 4076 +0 3651 4076 +0 3652 4076 +0 3652 4076 +0 3652 4076 +0 3653 4076 +0 3653 4076 +0 3654 4076 +0 3655 4076 +0 3656 4076 +0 3658 4076 +0 3660 4076 +0 3663 4076 +0 3667 4075 +0 3672 4075 +0 3679 4075 +0 3688 4074 +0 3700 4073 +0 3715 4072 +0 3735 4071 +0 3760 4069 +0 3791 4066 +0 3830 4063 +0 3870 4063 +0 3919 4063 +0 3977 4063 +0 4045 4063 +0 4063 3995 +0 4063 3849 +0 4063 3527 +0 4095 0 +0 3584 4076 +0 3584 4076 +0 3585 4076 +0 3585 4076 +0 3585 4076 +0 3585 4076 +0 3586 4076 +0 3586 4076 +0 3587 4076 +0 3588 4076 +0 3590 4076 +0 3592 4076 +0 3594 4076 +0 3597 4076 +0 3602 4075 +0 3608 4075 +0 3616 4075 +0 3626 4074 +0 3640 4073 +0 3657 4072 +0 3679 4071 +0 3708 4069 +0 3743 4066 +0 3786 4063 +0 3838 4058 +0 3890 4058 +0 3952 4058 +0 4023 4058 +0 4058 4008 +0 4058 3867 +0 4058 3562 +0 4095 0 +0 3475 4076 +0 3475 4076 +0 3476 4076 +0 3476 4076 +0 3476 4076 +0 3477 4076 +0 3477 4076 +0 3478 4076 +0 3479 4076 +0 3480 4076 +0 3482 4076 +0 3485 4076 +0 3488 4076 +0 3492 4076 +0 3498 4075 +0 3505 4075 +0 3515 4075 +0 3528 4074 +0 3545 4073 +0 3566 4072 +0 3593 4071 +0 3627 4069 +0 3669 4066 +0 3719 4063 +0 3779 4058 +2063 3848 4052 +2063 3915 4052 +2063 3992 4052 +2063 4052 4025 +2063 4052 3890 +2063 4052 3606 +0 4095 2266 +0 3271 4076 +0 3272 4076 +0 3272 4076 +0 3272 4076 +0 3273 4076 +0 3273 4076 +0 3274 4076 +0 3276 4076 +0 3277 4076 +0 3279 4076 +0 3282 4076 +0 3286 4076 +0 3291 4076 +0 3297 4076 +0 3306 4075 +0 3318 4075 +0 3333 4075 +0 3351 4074 +0 3376 4073 +0 3407 4072 +0 3445 4071 +0 3491 4069 +0 3546 4066 +0 3611 4063 +0 3685 4058 +2063 3769 4052 +2986 3861 4044 +2986 3947 4044 +2986 4040 4044 +2986 4044 3919 +2986 4044 3659 +2192 4095 2814 +0 2626 4076 +0 2627 4076 +0 2628 4076 +0 2630 4076 +0 2632 4076 +0 2635 4076 +0 2639 4076 +0 2644 4076 +0 2650 4076 +0 2659 4076 +0 2670 4076 +0 2684 4076 +0 2703 4076 +0 2726 4076 +0 2756 4075 +0 2793 4075 +0 2839 4075 +0 2893 4074 +0 2957 4073 +0 3031 4072 +0 3113 4071 +0 3205 4069 +0 3303 4066 +0 3409 4063 +0 3520 4058 +2063 3636 4052 +2986 3755 4044 +3336 3878 4032 +3336 3986 4032 +3336 4032 3955 +3336 4032 3720 +3121 4095 3118 +0 0 4076 +0 0 4076 +0 0 4076 +0 0 4076 +0 0 4076 +0 0 4076 +0 0 4076 +0 0 4076 +0 0 4076 +0 0 4076 +0 0 4076 +0 0 4076 +0 0 4076 +0 0 4076 +0 0 4075 +0 0 4075 +0 0 4075 +0 0 4074 +0 0 4073 +0 0 4072 +0 0 4071 +0 0 4069 +0 1985 4066 +0 2781 4063 +0 3119 4058 +2063 3361 4052 +2986 3561 4044 +3336 3737 4032 +3583 3900 4016 +3583 4016 3999 +3583 4016 3792 +3568 4095 3469 +0 0 4076 +0 0 4076 +0 0 4076 +0 0 4076 +0 0 4076 +0 0 4076 +0 0 4076 +0 0 4076 +0 0 4076 +0 0 4076 +0 0 4076 +0 0 4076 +0 0 4076 +0 0 4076 +0 0 4075 +0 0 4075 +0 0 4075 +0 0 4074 +0 0 4073 +0 0 4072 +0 0 4071 +0 0 4069 +0 0 4066 +0 0 4063 +2157 0 4058 +2689 2063 4052 +2986 2987 4044 +3336 3435 4032 +3583 3711 4016 +3784 3928 3994 +3784 3994 3873 +3844 4095 3714 +3401 0 4076 +3401 0 4076 +3401 0 4076 +3401 0 4076 +3401 0 4076 +3402 0 4076 +3402 0 4076 +3402 0 4076 +3403 0 4076 +3403 0 4076 +3404 0 4076 +3405 0 4076 +3407 0 4076 +3409 0 4076 +3411 0 4075 +3415 0 4075 +3419 0 4075 +3426 0 4074 +3434 0 4073 +3444 0 4072 +3458 0 4071 +3475 0 4069 +3498 0 4066 +3527 0 4063 +3562 0 4058 +3606 2063 4052 +3659 2986 4044 +3720 3336 4032 +3792 3583 4016 +3873 3784 3994 +3962 3962 3962 +4060 4095 3916 +3924 0 4095 +3924 0 4095 +3924 0 4095 +3924 0 4095 +3924 0 4095 +3925 0 4095 +3925 0 4095 +3925 0 4095 +3925 0 4095 +3925 0 4095 +3925 0 4095 +3926 0 4095 +3926 0 4095 +3927 0 4095 +3927 0 4095 +3929 0 4095 +3930 0 4095 +3932 0 4095 +3935 0 4095 +3938 0 4095 +3943 0 4095 +3949 0 4095 +3957 0 4095 +3968 0 4095 +3982 0 4095 +4000 0 4095 +4023 2192 4095 +4051 3118 4095 +4087 3469 4095 +4095 3714 4095 +4095 3916 4060 +4095 4005 3916 +0 3939 4095 +0 3939 4095 +0 3939 4095 +0 3939 4095 +0 3939 4095 +0 3939 4095 +0 3939 4095 +0 3939 4095 +0 3940 4095 +0 3940 4095 +0 3941 4095 +0 3941 4095 +0 3942 4095 +0 3944 4095 +0 3946 4095 +0 3948 4095 +0 3951 4095 +0 3955 4095 +0 3961 4095 +0 3968 4095 +0 3978 4095 +0 3990 4095 +0 4007 4095 +0 4027 4095 +0 4054 4095 +0 4087 4095 +0 4095 4095 +0 4095 4095 +0 4095 4095 +0 4095 4087 +0 4095 3924 +0 4095 3533 +0 3939 4095 +0 3939 4095 +0 3939 4095 +0 3939 4095 +0 3939 4095 +0 3939 4095 +0 3939 4095 +0 3939 4095 +0 3940 4095 +0 3940 4095 +0 3941 4095 +0 3941 4095 +0 3942 4095 +0 3944 4095 +0 3946 4095 +0 3948 4095 +0 3951 4095 +0 3955 4095 +0 3961 4095 +0 3968 4095 +0 3978 4095 +0 3990 4095 +0 4006 4095 +0 4027 4095 +0 4054 4095 +0 4087 4095 +0 4095 4095 +0 4095 4095 +0 4095 4095 +0 4095 4087 +0 4095 3924 +0 4095 3533 +0 3938 4095 +0 3939 4095 +0 3939 4095 +0 3939 4095 +0 3939 4095 +0 3939 4095 +0 3939 4095 +0 3939 4095 +0 3940 4095 +0 3940 4095 +0 3941 4095 +0 3941 4095 +0 3942 4095 +0 3944 4095 +0 3945 4095 +0 3948 4095 +0 3951 4095 +0 3955 4095 +0 3961 4095 +0 3968 4095 +0 3978 4095 +0 3990 4095 +0 4006 4095 +0 4027 4095 +0 4054 4095 +0 4087 4095 +0 4095 4095 +0 4095 4095 +0 4095 4095 +0 4095 4087 +0 4095 3924 +0 4095 3533 +0 3938 4095 +0 3938 4095 +0 3939 4095 +0 3939 4095 +0 3939 4095 +0 3939 4095 +0 3939 4095 +0 3939 4095 +0 3940 4095 +0 3940 4095 +0 3941 4095 +0 3941 4095 +0 3942 4095 +0 3944 4095 +0 3945 4095 +0 3948 4095 +0 3951 4095 +0 3955 4095 +0 3961 4095 +0 3968 4095 +0 3978 4095 +0 3990 4095 +0 4006 4095 +0 4027 4095 +0 4054 4095 +0 4087 4095 +0 4095 4095 +0 4095 4095 +0 4095 4095 +0 4095 4087 +0 4095 3924 +0 4095 3534 +0 3938 4095 +0 3938 4095 +0 3938 4095 +0 3939 4095 +0 3939 4095 +0 3939 4095 +0 3939 4095 +0 3939 4095 +0 3940 4095 +0 3940 4095 +0 3941 4095 +0 3941 4095 +0 3942 4095 +0 3944 4095 +0 3945 4095 +0 3948 4095 +0 3951 4095 +0 3955 4095 +0 3961 4095 +0 3968 4095 +0 3977 4095 +0 3990 4095 +0 4006 4095 +0 4027 4095 +0 4054 4095 +0 4087 4095 +0 4095 4095 +0 4095 4095 +0 4095 4095 +0 4095 4087 +0 4095 3924 +0 4095 3534 +0 3938 4095 +0 3938 4095 +0 3938 4095 +0 3938 4095 +0 3938 4095 +0 3939 4095 +0 3939 4095 +0 3939 4095 +0 3939 4095 +0 3940 4095 +0 3941 4095 +0 3941 4095 +0 3942 4095 +0 3944 4095 +0 3945 4095 +0 3948 4095 +0 3951 4095 +0 3955 4095 +0 3961 4095 +0 3968 4095 +0 3977 4095 +0 3990 4095 +0 4006 4095 +0 4027 4095 +0 4054 4095 +0 4087 4095 +0 4095 4095 +0 4095 4095 +0 4095 4095 +0 4095 4087 +0 4095 3925 +0 4095 3534 +0 3938 4095 +0 3938 4095 +0 3938 4095 +0 3938 4095 +0 3938 4095 +0 3938 4095 +0 3939 4095 +0 3939 4095 +0 3939 4095 +0 3940 4095 +0 3940 4095 +0 3941 4095 +0 3942 4095 +0 3943 4095 +0 3945 4095 +0 3947 4095 +0 3951 4095 +0 3955 4095 +0 3961 4095 +0 3968 4095 +0 3977 4095 +0 3990 4095 +0 4006 4095 +0 4027 4095 +0 4054 4095 +0 4087 4095 +0 4095 4095 +0 4095 4095 +0 4095 4095 +0 4095 4087 +0 4095 3925 +0 4095 3534 +0 3938 4095 +0 3938 4095 +0 3938 4095 +0 3938 4095 +0 3938 4095 +0 3938 4095 +0 3938 4095 +0 3939 4095 +0 3939 4095 +0 3940 4095 +0 3940 4095 +0 3941 4095 +0 3942 4095 +0 3943 4095 +0 3945 4095 +0 3947 4095 +0 3950 4095 +0 3955 4095 +0 3960 4095 +0 3968 4095 +0 3977 4095 +0 3990 4095 +0 4006 4095 +0 4027 4095 +0 4053 4095 +0 4087 4095 +0 4095 4095 +0 4095 4095 +0 4095 4095 +0 4095 4087 +0 4095 3925 +0 4095 3534 +0 3937 4095 +0 3937 4095 +0 3937 4095 +0 3938 4095 +0 3938 4095 +0 3938 4095 +0 3938 4095 +0 3938 4095 +0 3939 4095 +0 3939 4095 +0 3940 4095 +0 3941 4095 +0 3941 4095 +0 3943 4095 +0 3945 4095 +0 3947 4095 +0 3950 4095 +0 3954 4095 +0 3960 4095 +0 3967 4095 +0 3977 4095 +0 3989 4095 +0 4006 4095 +0 4027 4095 +0 4053 4095 +0 4086 4095 +0 4095 4095 +0 4095 4095 +0 4095 4095 +0 4095 4087 +0 4095 3925 +0 4095 3534 +0 3937 4095 +0 3937 4095 +0 3937 4095 +0 3937 4095 +0 3937 4095 +0 3937 4095 +0 3938 4095 +0 3938 4095 +0 3938 4095 +0 3939 4095 +0 3940 4095 +0 3940 4095 +0 3941 4095 +0 3943 4095 +0 3944 4095 +0 3947 4095 +0 3950 4095 +0 3954 4095 +0 3960 4095 +0 3967 4095 +0 3977 4095 +0 3989 4095 +0 4005 4095 +0 4026 4095 +0 4053 4095 +0 4086 4095 +0 4095 4095 +0 4095 4095 +0 4095 4095 +0 4095 4088 +0 4095 3925 +0 4095 3535 +0 3937 4095 +0 3937 4095 +0 3937 4095 +0 3937 4095 +0 3937 4095 +0 3937 4095 +0 3937 4095 +0 3937 4095 +0 3938 4095 +0 3938 4095 +0 3939 4095 +0 3940 4095 +0 3941 4095 +0 3942 4095 +0 3944 4095 +0 3946 4095 +0 3950 4095 +0 3954 4095 +0 3959 4095 +0 3967 4095 +0 3976 4095 +0 3989 4095 +0 4005 4095 +0 4026 4095 +0 4053 4095 +0 4086 4095 +0 4095 4095 +0 4095 4095 +0 4095 4095 +0 4095 4088 +0 4095 3925 +0 4095 3536 +0 3936 4095 +0 3936 4095 +0 3936 4095 +0 3936 4095 +0 3936 4095 +0 3936 4095 +0 3937 4095 +0 3937 4095 +0 3937 4095 +0 3937 4095 +0 3938 4095 +0 3939 4095 +0 3940 4095 +0 3941 4095 +0 3943 4095 +0 3946 4095 +0 3949 4095 +0 3953 4095 +0 3959 4095 +0 3966 4095 +0 3976 4095 +0 3988 4095 +0 4005 4095 +0 4026 4095 +0 4052 4095 +0 4085 4095 +0 4095 4095 +0 4095 4095 +0 4095 4095 +0 4095 4088 +0 4095 3926 +0 4095 3537 +0 3935 4095 +0 3935 4095 +0 3935 4095 +0 3935 4095 +0 3935 4095 +0 3935 4095 +0 3935 4095 +0 3936 4095 +0 3936 4095 +0 3937 4095 +0 3937 4095 +0 3938 4095 +0 3939 4095 +0 3941 4095 +0 3942 4095 +0 3945 4095 +0 3948 4095 +0 3952 4095 +0 3958 4095 +0 3965 4095 +0 3975 4095 +0 3988 4095 +0 4004 4095 +0 4025 4095 +0 4051 4095 +0 4085 4095 +0 4095 4095 +0 4095 4095 +0 4095 4095 +0 4095 4088 +0 4095 3926 +0 4095 3538 +0 3933 4095 +0 3933 4095 +0 3933 4095 +0 3933 4095 +0 3934 4095 +0 3934 4095 +0 3934 4095 +0 3934 4095 +0 3935 4095 +0 3935 4095 +0 3936 4095 +0 3937 4095 +0 3938 4095 +0 3940 4095 +0 3941 4095 +0 3944 4095 +0 3947 4095 +0 3951 4095 +0 3957 4095 +0 3964 4095 +0 3974 4095 +0 3986 4095 +0 4003 4095 +0 4024 4095 +0 4051 4095 +0 4084 4095 +0 4095 4095 +0 4095 4095 +0 4095 4095 +0 4095 4089 +0 4095 3927 +0 4095 3539 +0 3932 4095 +0 3932 4095 +0 3932 4095 +0 3932 4095 +0 3932 4095 +0 3932 4095 +0 3932 4095 +0 3932 4095 +0 3933 4095 +0 3933 4095 +0 3934 4095 +0 3935 4095 +0 3936 4095 +0 3938 4095 +0 3940 4095 +0 3942 4095 +0 3945 4095 +0 3950 4095 +0 3955 4095 +0 3963 4095 +0 3972 4095 +0 3985 4095 +0 4002 4095 +0 4023 4095 +0 4049 4095 +0 4083 4095 +0 4095 4095 +0 4095 4095 +0 4095 4095 +0 4095 4089 +0 4095 3927 +0 4095 3541 +0 3929 4095 +0 3929 4095 +0 3929 4095 +0 3929 4095 +0 3929 4095 +0 3929 4095 +0 3930 4095 +0 3930 4095 +0 3930 4095 +0 3931 4095 +0 3932 4095 +0 3932 4095 +0 3934 4095 +0 3935 4095 +0 3937 4095 +0 3940 4095 +0 3944 4095 +0 3948 4095 +0 3953 4095 +0 3961 4095 +0 3971 4095 +0 3983 4095 +0 4000 4095 +0 4021 4095 +0 4048 4095 +0 4082 4095 +0 4095 4095 +0 4095 4095 +0 4095 4095 +0 4095 4090 +0 4095 3929 +0 4095 3544 +0 3926 4095 +0 3926 4095 +0 3926 4095 +0 3926 4095 +0 3926 4095 +0 3926 4095 +0 3927 4095 +0 3927 4095 +0 3927 4095 +0 3927 4095 +0 3928 4095 +0 3929 4095 +0 3930 4095 +0 3932 4095 +0 3934 4095 +0 3937 4095 +0 3941 4095 +0 3945 4095 +0 3951 4095 +0 3959 4095 +0 3968 4095 +0 3981 4095 +0 3998 4095 +0 4019 4095 +0 4046 4095 +0 4080 4095 +0 4095 4095 +0 4095 4095 +0 4095 4095 +0 4095 4091 +0 4095 3930 +0 4095 3547 +0 3921 4095 +0 3921 4095 +0 3921 4095 +0 3921 4095 +0 3921 4095 +0 3922 4095 +0 3922 4095 +0 3922 4095 +0 3923 4095 +0 3923 4095 +0 3924 4095 +0 3925 4095 +0 3926 4095 +0 3927 4095 +0 3930 4095 +0 3933 4095 +0 3937 4095 +0 3942 4095 +0 3947 4095 +0 3955 4095 +0 3965 4095 +0 3978 4095 +0 3994 4095 +0 4016 4095 +0 4043 4095 +0 4077 4095 +0 4095 4095 +0 4095 4095 +0 4095 4095 +0 4095 4092 +0 4095 3932 +0 4095 3552 +0 3915 4095 +0 3915 4095 +0 3915 4095 +0 3915 4095 +0 3915 4095 +0 3916 4095 +0 3916 4095 +0 3916 4095 +0 3917 4095 +0 3917 4095 +0 3918 4095 +0 3919 4095 +0 3920 4095 +0 3922 4095 +0 3924 4095 +0 3927 4095 +0 3931 4095 +0 3936 4095 +0 3943 4095 +0 3950 4095 +0 3961 4095 +0 3974 4095 +0 3990 4095 +0 4012 4095 +0 4039 4095 +0 4073 4095 +0 4095 4095 +0 4095 4095 +0 4095 4095 +0 4095 4094 +0 4095 3935 +0 4095 3558 +0 3907 4095 +0 3907 4095 +0 3907 4095 +0 3907 4095 +0 3907 4095 +0 3908 4095 +0 3908 4095 +0 3908 4095 +0 3908 4095 +0 3909 4095 +0 3910 4095 +0 3910 4095 +0 3912 4095 +0 3913 4095 +0 3916 4095 +0 3919 4095 +0 3923 4095 +0 3928 4095 +0 3935 4095 +0 3944 4095 +0 3954 4095 +0 3968 4095 +0 3984 4095 +0 4006 4095 +0 4034 4095 +0 4069 4095 +0 4095 4095 +0 4095 4095 +0 4095 4095 +0 4095 4095 +0 4095 3938 +0 4095 3566 +0 3896 4095 +0 3896 4095 +0 3896 4095 +0 3896 4095 +0 3896 4095 +0 3896 4095 +0 3896 4095 +0 3897 4095 +0 3897 4095 +0 3898 4095 +0 3898 4095 +0 3899 4095 +0 3901 4095 +0 3903 4095 +0 3905 4095 +0 3908 4095 +0 3912 4095 +0 3917 4095 +0 3924 4095 +0 3934 4095 +0 3946 4095 +0 3960 4095 +0 3977 4095 +0 3999 4095 +0 4027 4095 +0 4062 4095 +0 4095 4095 +0 4095 4095 +0 4095 4095 +0 4095 4095 +0 4095 3943 +0 4095 3576 +0 3880 4095 +0 3880 4095 +0 3880 4095 +0 3880 4095 +0 3880 4095 +0 3881 4095 +0 3881 4095 +0 3881 4095 +0 3881 4095 +0 3882 4095 +0 3883 4095 +0 3884 4095 +0 3885 4095 +0 3887 4095 +0 3889 4095 +0 3893 4095 +0 3897 4095 +0 3903 4095 +0 3910 4095 +0 3920 4095 +0 3932 4095 +0 3949 4095 +0 3966 4095 +0 3989 4095 +0 4018 4095 +0 4054 4095 +0 4095 4095 +0 4095 4095 +0 4095 4095 +0 4095 4095 +0 4095 3949 +0 4095 3590 +0 3859 4095 +0 3859 4095 +0 3859 4095 +0 3859 4095 +0 3859 4095 +0 3859 4095 +0 3859 4095 +0 3860 4095 +0 3860 4095 +0 3861 4095 +0 3862 4095 +0 3863 4095 +0 3864 4095 +0 3866 4095 +0 3868 4095 +0 3872 4095 +0 3876 4095 +0 3882 4095 +0 3890 4095 +0 3900 4095 +0 3913 4095 +0 3930 4095 +0 3952 4095 +0 3976 4095 +0 4005 4095 +0 4042 4095 +0 4087 4095 +0 4095 4095 +0 4095 4095 +0 4095 4095 +0 4095 3957 +0 4095 3608 +0 3828 4095 +0 3828 4095 +0 3828 4095 +0 3828 4095 +0 3828 4095 +0 3829 4095 +0 3829 4095 +0 3829 4095 +0 3830 4095 +0 3830 4095 +0 3831 4095 +0 3832 4095 +0 3834 4095 +0 3836 4095 +0 3838 4095 +0 3842 4095 +0 3847 4095 +0 3853 4095 +0 3861 4095 +0 3872 4095 +0 3886 4095 +0 3904 4095 +0 3927 4095 +0 3956 4095 +0 3987 4095 +0 4025 4095 +0 4072 4095 +0 4095 4095 +0 4095 4095 +0 4095 4095 +0 4095 3968 +0 4095 3630 +0 3784 4095 +0 3784 4095 +0 3784 4095 +0 3784 4095 +0 3784 4095 +0 3784 4095 +0 3784 4095 +0 3785 4095 +0 3786 4095 +0 3786 4095 +0 3787 4095 +0 3788 4095 +0 3790 4095 +0 3792 4095 +0 3795 4095 +0 3799 4095 +0 3804 4095 +0 3811 4095 +0 3820 4095 +0 3832 4095 +0 3847 4095 +0 3867 4095 +0 3892 4095 +0 3923 4095 +0 3962 4095 +0 4002 4095 +0 4051 4095 +0 4095 4095 +0 4095 4095 +0 4095 4095 +0 4095 3982 +0 4095 3659 +0 3716 4095 +0 3717 4095 +0 3717 4095 +0 3717 4095 +0 3717 4095 +0 3717 4095 +0 3718 4095 +0 3718 4095 +0 3719 4095 +0 3720 4095 +0 3721 4095 +0 3722 4095 +0 3724 4095 +0 3727 4095 +0 3730 4095 +0 3735 4095 +0 3741 4095 +0 3748 4095 +0 3759 4095 +0 3772 4095 +0 3790 4095 +0 3812 4095 +0 3840 4095 +0 3875 4095 +0 3918 4095 +0 3970 4095 +0 4022 4095 +0 4084 4095 +0 4095 4095 +0 4095 4095 +0 4095 4000 +0 4095 3695 +0 3608 4095 +0 3608 4095 +0 3608 4095 +0 3608 4095 +0 3608 4095 +0 3609 4095 +0 3609 4095 +0 3610 4095 +0 3611 4095 +0 3612 4095 +0 3613 4095 +0 3615 4095 +0 3617 4095 +0 3621 4095 +0 3625 4095 +0 3630 4095 +0 3638 4095 +0 3648 4095 +0 3661 4095 +0 3677 4095 +0 3699 4095 +0 3726 4095 +0 3759 4095 +0 3801 4095 +0 3851 4095 +0 3911 4095 +2192 3980 4095 +2192 4047 4095 +2192 4095 4095 +2192 4095 4095 +2192 4095 4023 +2192 4095 3738 +0 3404 4095 +0 3404 4095 +0 3404 4095 +0 3405 4095 +0 3405 4095 +0 3405 4095 +0 3406 4095 +0 3407 4095 +0 3408 4095 +0 3410 4095 +0 3412 4095 +0 3415 4095 +0 3419 4095 +0 3424 4095 +0 3430 4095 +0 3439 4095 +0 3450 4095 +0 3465 4095 +0 3484 4095 +0 3509 4095 +0 3539 4095 +0 3577 4095 +0 3623 4095 +0 3679 4095 +0 3743 4095 +0 3818 4095 +2192 3901 4095 +3118 3993 4095 +3118 4079 4095 +3118 4095 4095 +3118 4095 4051 +3118 4095 3791 +0 2761 4095 +0 2762 4095 +0 2762 4095 +0 2764 4095 +0 2765 4095 +0 2767 4095 +0 2770 4095 +0 2773 4095 +0 2778 4095 +0 2785 4095 +0 2793 4095 +0 2804 4095 +0 2818 4095 +0 2837 4095 +0 2861 4095 +0 2890 4095 +0 2927 4095 +0 2973 4095 +0 3027 4095 +0 3090 4095 +0 3164 4095 +0 3246 4095 +0 3337 4095 +0 3436 4095 +0 3541 4095 +0 3653 4095 +2192 3768 4095 +3118 3888 4095 +3469 4010 4095 +3469 4095 4095 +3469 4095 4087 +3469 4095 3853 +0 0 4095 +0 0 4095 +0 0 4095 +0 0 4095 +0 0 4095 +0 0 4095 +0 0 4095 +0 0 4095 +0 0 4095 +0 0 4095 +0 0 4095 +0 0 4095 +0 0 4095 +0 0 4095 +0 0 4095 +0 0 4095 +0 0 4095 +0 0 4095 +0 0 4095 +0 0 4095 +0 0 4095 +0 0 4095 +0 0 4095 +0 2137 4095 +0 2915 4095 +0 3253 4095 +2192 3494 4095 +3118 3693 4095 +3469 3869 4095 +3714 4032 4095 +3714 4095 4095 +3714 4095 3924 +0 0 4095 +0 0 4095 +0 0 4095 +0 0 4095 +0 0 4095 +0 0 4095 +0 0 4095 +0 0 4095 +0 0 4095 +0 0 4095 +0 0 4095 +0 0 4095 +0 0 4095 +0 0 4095 +0 0 4095 +0 0 4095 +0 0 4095 +0 0 4095 +0 0 4095 +0 0 4095 +0 0 4095 +0 0 4095 +0 0 4095 +0 0 4095 +0 0 4095 +2266 0 4095 +2814 2192 4095 +3118 3121 4095 +3469 3568 4095 +3714 3844 4095 +3916 4060 4095 +3916 4095 4005 +3533 0 4095 +3533 0 4095 +3533 0 4095 +3534 0 4095 +3534 0 4095 +3534 0 4095 +3534 0 4095 +3534 0 4095 +3534 0 4095 +3535 0 4095 +3536 0 4095 +3537 0 4095 +3538 0 4095 +3539 0 4095 +3541 0 4095 +3544 0 4095 +3547 0 4095 +3552 0 4095 +3558 0 4095 +3566 0 4095 +3576 0 4095 +3590 0 4095 +3608 0 4095 +3630 0 4095 +3659 0 4095 +3695 0 4095 +3738 2192 4095 +3791 3118 4095 +3853 3469 4095 +3924 3714 4095 +4005 3916 4095 +4095 4095 4095 diff --git a/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Photoshop/Log2-48nits/o_invShaped/test_hue-sat_32_LUT.azasset b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Photoshop/Log2-48nits/o_invShaped/test_hue-sat_32_LUT.azasset new file mode 100644 index 0000000000..82fbee2eee --- /dev/null +++ b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Photoshop/Log2-48nits/o_invShaped/test_hue-sat_32_LUT.azasset @@ -0,0 +1,32777 @@ +{ + "Type": "JsonSerialization", + "Version": 1, + "ClassName": "LookupTableAsset", + "ClassData": { + "Name": "LookupTable", + "Intervals": [0, 33, 66, 99, 132, 165, 198, 231, 264, 297, 330, 363, 396, 429, 462, 495, 528, 561, 594, 627, 660, 693, 726, 759, 792, 825, 858, 891, 924, 957, 990, 1023], + "Values": [0, 0, 0, +97, 163, 0, +201, 318, 0, +312, 466, 0, +427, 609, 0, +545, 750, 0, +667, 888, 0, +792, 1025, 0, +918, 1160, 0, +1046, 1295, 0, +1174, 1429, 0, +1304, 1563, 0, +1434, 1696, 0, +1565, 1828, 0, +1696, 1961, 0, +1827, 2094, 0, +1959, 2226, 0, +2090, 2358, 0, +2222, 2491, 0, +2354, 2623, 0, +2486, 2755, 0, +2618, 2887, 0, +2750, 3019, 0, +2882, 3152, 0, +3014, 3284, 0, +3146, 3416, 0, +3278, 3548, 0, +3410, 3680, 0, +3542, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3939, 4095, 0, +163, 0, 97, +163, 42, 0, +318, 300, 0, +419, 466, 0, +512, 609, 0, +613, 750, 0, +719, 888, 0, +832, 1025, 0, +949, 1160, 0, +1069, 1295, 0, +1192, 1429, 0, +1318, 1563, 0, +1444, 1696, 0, +1572, 1828, 0, +1702, 1961, 0, +1831, 2094, 0, +1962, 2226, 0, +2093, 2358, 0, +2224, 2491, 0, +2355, 2623, 0, +2487, 2755, 0, +2619, 2887, 0, +2750, 3019, 0, +2883, 3152, 0, +3014, 3284, 0, +3146, 3416, 0, +3278, 3548, 0, +3410, 3680, 0, +3542, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3939, 4095, 0, +318, 0, 201, +318, 0, 13, +318, 93, 0, +466, 388, 0, +606, 609, 0, +689, 750, 0, +781, 888, 0, +881, 1025, 0, +987, 1160, 0, +1099, 1295, 0, +1215, 1429, 0, +1335, 1563, 0, +1457, 1696, 0, +1582, 1828, 0, +1709, 1961, 0, +1837, 2094, 0, +1966, 2226, 0, +2096, 2358, 0, +2226, 2491, 0, +2357, 2623, 0, +2488, 2755, 0, +2620, 2887, 0, +2751, 3019, 0, +2883, 3152, 0, +3014, 3284, 0, +3147, 3416, 0, +3279, 3548, 0, +3410, 3680, 0, +3543, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3939, 4095, 0, +466, 0, 312, +466, 0, 171, +466, 0, 0, +466, 154, 0, +609, 485, 0, +750, 723, 0, +852, 888, 0, +939, 1025, 0, +1033, 1160, 0, +1135, 1295, 0, +1244, 1429, 0, +1357, 1563, 0, +1475, 1696, 0, +1596, 1828, 0, +1719, 1961, 0, +1845, 2094, 0, +1972, 2226, 0, +2100, 2358, 0, +2230, 2491, 0, +2359, 2623, 0, +2490, 2755, 0, +2621, 2887, 0, +2752, 3019, 0, +2884, 3152, 0, +3015, 3284, 0, +3147, 3416, 0, +3279, 3548, 0, +3411, 3680, 0, +3543, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3939, 4095, 0, +609, 0, 427, +609, 0, 322, +609, 0, 127, +609, 0, 0, +609, 224, 0, +750, 587, 0, +888, 838, 0, +1006, 1025, 0, +1089, 1160, 0, +1181, 1295, 0, +1280, 1429, 0, +1385, 1563, 0, +1496, 1696, 0, +1612, 1828, 0, +1732, 1961, 0, +1855, 2094, 0, +1979, 2226, 0, +2106, 2358, 0, +2234, 2491, 0, +2363, 2623, 0, +2493, 2755, 0, +2623, 2887, 0, +2754, 3019, 0, +2885, 3152, 0, +3016, 3284, 0, +3147, 3416, 0, +3279, 3548, 0, +3411, 3680, 0, +3543, 3812, 0, +3675, 3944, 0, +3807, 4076, 0, +3939, 4095, 0, +750, 0, 545, +750, 0, 467, +750, 0, 334, +750, 0, 59, +750, 0, 0, +750, 304, 0, +888, 697, 0, +1025, 957, 0, +1154, 1160, 0, +1234, 1295, 0, +1323, 1429, 0, +1421, 1563, 0, +1524, 1696, 0, +1634, 1828, 0, +1749, 1961, 0, +1867, 2094, 0, +1989, 2226, 0, +2113, 2358, 0, +2239, 2491, 0, +2367, 2623, 0, +2496, 2755, 0, +2625, 2887, 0, +2755, 3019, 0, +2886, 3152, 0, +3017, 3284, 0, +3148, 3416, 0, +3280, 3548, 0, +3411, 3680, 0, +3543, 3812, 0, +3675, 3944, 0, +3807, 4076, 0, +3939, 4095, 0, +888, 0, 667, +888, 0, 608, +888, 0, 515, +888, 0, 350, +888, 0, 0, +888, 0, 0, +888, 392, 0, +1025, 811, 0, +1160, 1079, 0, +1295, 1292, 0, +1376, 1429, 0, +1463, 1563, 0, +1559, 1696, 0, +1661, 1828, 0, +1770, 1961, 0, +1884, 2094, 0, +2002, 2226, 0, +2123, 2358, 0, +2247, 2491, 0, +2372, 2623, 0, +2500, 2755, 0, +2628, 2887, 0, +2758, 3019, 0, +2888, 3152, 0, +3018, 3284, 0, +3149, 3416, 0, +3280, 3548, 0, +3412, 3680, 0, +3544, 3812, 0, +3675, 3944, 0, +3807, 4076, 0, +3939, 4095, 0, +1025, 0, 792, +1025, 0, 748, +1025, 0, 681, +1025, 0, 573, +1025, 0, 371, +1025, 0, 0, +1025, 0, 0, +1025, 488, 0, +1160, 929, 0, +1295, 1204, 0, +1429, 1419, 0, +1515, 1563, 0, +1601, 1696, 0, +1696, 1828, 0, +1797, 1961, 0, +1905, 2094, 0, +2018, 2226, 0, +2136, 2358, 0, +2256, 2491, 0, +2380, 2623, 0, +2505, 2755, 0, +2633, 2887, 0, +2761, 3019, 0, +2890, 3152, 0, +3020, 3284, 0, +3151, 3416, 0, +3281, 3548, 0, +3413, 3680, 0, +3544, 3812, 0, +3676, 3944, 0, +3808, 4076, 0, +3939, 4095, 0, +1160, 0, 918, +1160, 0, 885, +1160, 0, 836, +1160, 0, 762, +1160, 0, 640, +1160, 0, 397, +1160, 0, 0, +1160, 0, 0, +1160, 592, 0, +1295, 1051, 0, +1429, 1330, 0, +1563, 1548, 0, +1653, 1696, 0, +1738, 1828, 0, +1831, 1961, 0, +1932, 2094, 0, +2039, 2226, 0, +2152, 2358, 0, +2269, 2491, 0, +2390, 2623, 0, +2513, 2755, 0, +2638, 2887, 0, +2765, 3019, 0, +2893, 3152, 0, +3022, 3284, 0, +3152, 3416, 0, +3283, 3548, 0, +3414, 3680, 0, +3545, 3812, 0, +3676, 3944, 0, +3808, 4076, 0, +3940, 4095, 0, +1295, 0, 1046, +1295, 0, 1021, +1295, 0, 985, +1295, 0, 934, +1295, 0, 853, +1295, 0, 717, +1295, 0, 431, +1295, 0, 0, +1295, 0, 0, +1295, 702, 0, +1429, 1174, 0, +1563, 1458, 0, +1696, 1677, 0, +1789, 1828, 0, +1873, 1961, 0, +1966, 2094, 0, +2066, 2226, 0, +2173, 2358, 0, +2285, 2491, 0, +2402, 2623, 0, +2523, 2755, 0, +2646, 2887, 0, +2771, 3019, 0, +2898, 3152, 0, +3025, 3284, 0, +3155, 3416, 0, +3285, 3548, 0, +3415, 3680, 0, +3546, 3812, 0, +3677, 3944, 0, +3808, 4076, 0, +3940, 4095, 0, +1429, 0, 1174, +1429, 0, 1156, +1429, 0, 1130, +1429, 0, 1092, +1429, 0, 1037, +1429, 0, 951, +1429, 0, 803, +1429, 0, 471, +1429, 0, 0, +1429, 0, 0, +1429, 816, 0, +1563, 1301, 0, +1696, 1587, 0, +1828, 1807, 0, +1923, 1961, 0, +2007, 2094, 0, +2100, 2226, 0, +2200, 2358, 0, +2306, 2491, 0, +2419, 2623, 0, +2535, 2755, 0, +2655, 2887, 0, +2778, 3019, 0, +2903, 3152, 0, +3030, 3284, 0, +3158, 3416, 0, +3287, 3548, 0, +3417, 3680, 0, +3547, 3812, 0, +3678, 3944, 0, +3809, 4076, 0, +3941, 4095, 0, +1563, 0, 1304, +1563, 0, 1290, +1563, 0, 1271, +1563, 0, 1244, +1563, 0, 1205, +1563, 0, 1148, +1563, 0, 1057, +1563, 0, 897, +1563, 0, 523, +1563, 0, 0, +1563, 0, 0, +1563, 934, 0, +1696, 1427, 0, +1828, 1716, 0, +1961, 1938, 0, +2058, 2094, 0, +2141, 2226, 0, +2233, 2358, 0, +2333, 2491, 0, +2440, 2623, 0, +2552, 2755, 0, +2668, 2887, 0, +2788, 3019, 0, +2911, 3152, 0, +3035, 3284, 0, +3162, 3416, 0, +3290, 3548, 0, +3419, 3680, 0, +3549, 3812, 0, +3679, 3944, 0, +3810, 4076, 0, +3941, 4095, 0, +1696, 0, 1434, +1696, 0, 1424, +1696, 0, 1410, +1696, 0, 1390, +1696, 0, 1362, +1696, 0, 1322, +1696, 0, 1262, +1696, 0, 1167, +1696, 0, 998, +1696, 0, 580, +1696, 0, 0, +1696, 0, 0, +1696, 1056, 0, +1828, 1557, 0, +1961, 1847, 0, +2094, 2069, 0, +2191, 2226, 0, +2275, 2358, 0, +2367, 2491, 0, +2466, 2623, 0, +2573, 2755, 0, +2684, 2887, 0, +2800, 3019, 0, +2920, 3152, 0, +3043, 3284, 0, +3168, 3416, 0, +3294, 3548, 0, +3422, 3680, 0, +3552, 3812, 0, +3681, 3944, 0, +3812, 4076, 0, +3942, 4095, 0, +1828, 0, 1565, +1828, 0, 1557, +1828, 0, 1547, +1828, 0, 1532, +1828, 0, 1512, +1828, 0, 1484, +1828, 0, 1442, +1828, 0, 1381, +1828, 0, 1283, +1828, 0, 1106, +1828, 0, 650, +1828, 0, 0, +1828, 0, 0, +1828, 1180, 0, +1961, 1686, 0, +2094, 1977, 0, +2226, 2200, 0, +2325, 2358, 0, +2408, 2491, 0, +2500, 2623, 0, +2599, 2755, 0, +2705, 2887, 0, +2816, 3019, 0, +2933, 3152, 0, +3052, 3284, 0, +3175, 3416, 0, +3300, 3548, 0, +3427, 3680, 0, +3554, 3812, 0, +3683, 3944, 0, +3813, 4076, 0, +3944, 4095, 0, +1961, 0, 1696, +1961, 0, 1690, +1961, 0, 1682, +1961, 0, 1672, +1961, 0, 1657, +1961, 0, 1636, +1961, 0, 1607, +1961, 0, 1565, +1961, 0, 1503, +1961, 0, 1402, +1961, 0, 1220, +1961, 0, 726, +1961, 0, 0, +1961, 0, 0, +1961, 1306, 0, +2094, 1816, 0, +2226, 2108, 0, +2358, 2332, 0, +2458, 2491, 0, +2541, 2623, 0, +2632, 2755, 0, +2732, 2887, 0, +2837, 3019, 0, +2949, 3152, 0, +3065, 3284, 0, +3184, 3416, 0, +3307, 3548, 0, +3432, 3680, 0, +3559, 3812, 0, +3687, 3944, 0, +3816, 4076, 0, +3946, 4095, 0, +2094, 0, 1827, +2094, 0, 1823, +2094, 0, 1817, +2094, 0, 1809, +2094, 0, 1798, +2094, 0, 1783, +2094, 0, 1763, +2094, 0, 1733, +2094, 0, 1691, +2094, 0, 1626, +2094, 0, 1524, +2094, 0, 1336, +2094, 0, 814, +2094, 0, 0, +2094, 0, 0, +2094, 1433, 0, +2226, 1946, 0, +2358, 2239, 0, +2491, 2463, 0, +2590, 2623, 0, +2673, 2755, 0, +2765, 2887, 0, +2864, 3019, 0, +2970, 3152, 0, +3081, 3284, 0, +3197, 3416, 0, +3317, 3548, 0, +3440, 3680, 0, +3564, 3812, 0, +3691, 3944, 0, +3819, 4076, 0, +3948, 4095, 0, +2226, 0, 1959, +2226, 0, 1956, +2226, 0, 1951, +2226, 0, 1945, +2226, 0, 1937, +2226, 0, 1926, +2226, 0, 1911, +2226, 0, 1890, +2226, 0, 1860, +2226, 0, 1817, +2226, 0, 1753, +2226, 0, 1648, +2226, 0, 1457, +2226, 0, 907, +2226, 0, 0, +2226, 0, 0, +2226, 1562, 0, +2358, 2078, 0, +2491, 2371, 0, +2623, 2595, 0, +2723, 2755, 0, +2806, 2887, 0, +2897, 3019, 0, +2996, 3152, 0, +3102, 3284, 0, +3213, 3416, 0, +3329, 3548, 0, +3449, 3680, 0, +3572, 3812, 0, +3696, 3944, 0, +3823, 4076, 0, +3951, 4095, 0, +2358, 0, 2090, +2358, 0, 2088, +2358, 0, 2085, +2358, 0, 2080, +2358, 0, 2074, +2358, 0, 2066, +2358, 0, 2055, +2358, 0, 2040, +2358, 0, 2019, +2358, 0, 1989, +2358, 0, 1946, +2358, 0, 1880, +2358, 0, 1775, +2358, 0, 1580, +2358, 0, 1009, +2358, 0, 0, +2358, 0, 0, +2358, 1692, 0, +2491, 2209, 0, +2623, 2503, 0, +2755, 2727, 0, +2856, 2887, 0, +2938, 3019, 0, +3030, 3152, 0, +3128, 3284, 0, +3234, 3416, 0, +3346, 3548, 0, +3462, 3680, 0, +3581, 3812, 0, +3704, 3944, 0, +3828, 4076, 0, +3955, 4095, 0, +2491, 0, 2222, +2491, 0, 2220, +2491, 0, 2218, +2491, 0, 2215, +2491, 0, 2210, +2491, 0, 2204, +2491, 0, 2196, +2491, 0, 2185, +2491, 0, 2170, +2491, 0, 2149, +2491, 0, 2119, +2491, 0, 2075, +2491, 0, 2009, +2491, 0, 1903, +2491, 0, 1706, +2491, 0, 1120, +2491, 0, 0, +2491, 0, 0, +2491, 1822, 0, +2623, 2340, 0, +2755, 2635, 0, +2887, 2859, 0, +2988, 3019, 0, +3071, 3152, 0, +3162, 3284, 0, +3261, 3416, 0, +3367, 3548, 0, +3478, 3680, 0, +3594, 3812, 0, +3713, 3944, 0, +3836, 4076, 0, +3961, 4095, 0, +2623, 0, 2354, +2623, 0, 2352, +2623, 0, 2351, +2623, 0, 2348, +2623, 0, 2345, +2623, 0, 2341, +2623, 0, 2335, +2623, 0, 2327, +2623, 0, 2315, +2623, 0, 2300, +2623, 0, 2278, +2623, 0, 2248, +2623, 0, 2205, +2623, 0, 2138, +2623, 0, 2032, +2623, 0, 1833, +2623, 0, 1232, +2623, 0, 0, +2623, 0, 0, +2623, 1952, 0, +2755, 2473, 0, +2887, 2767, 0, +3019, 2991, 0, +3120, 3152, 0, +3203, 3284, 0, +3294, 3416, 0, +3393, 3548, 0, +3499, 3680, 0, +3610, 3812, 0, +3726, 3944, 0, +3846, 4076, 0, +3968, 4095, 0, +2755, 0, 2486, +2755, 0, 2485, +2755, 0, 2484, +2755, 0, 2482, +2755, 0, 2479, +2755, 0, 2476, +2755, 0, 2472, +2755, 0, 2466, +2755, 0, 2457, +2755, 0, 2446, +2755, 0, 2431, +2755, 0, 2409, +2755, 0, 2379, +2755, 0, 2335, +2755, 0, 2269, +2755, 0, 2162, +2755, 0, 1962, +2755, 0, 1353, +2755, 0, 0, +2755, 0, 0, +2755, 2083, 0, +2887, 2604, 0, +3019, 2898, 0, +3152, 3123, 0, +3252, 3284, 0, +3335, 3416, 0, +3426, 3548, 0, +3525, 3680, 0, +3631, 3812, 0, +3742, 3944, 0, +3858, 4076, 0, +3978, 4095, 0, +2887, 0, 2618, +2887, 0, 2617, +2887, 0, 2616, +2887, 0, 2615, +2887, 0, 2613, +2887, 0, 2611, +2887, 0, 2607, +2887, 0, 2603, +2887, 0, 2597, +2887, 0, 2589, +2887, 0, 2577, +2887, 0, 2562, +2887, 0, 2541, +2887, 0, 2510, +2887, 0, 2466, +2887, 0, 2400, +2887, 0, 2292, +2887, 0, 2091, +2887, 0, 1472, +2887, 0, 0, +2887, 0, 0, +2887, 2215, 0, +3019, 2735, 0, +3152, 3031, 0, +3284, 3254, 0, +3385, 3416, 0, +3467, 3548, 0, +3558, 3680, 0, +3657, 3812, 0, +3763, 3944, 0, +3874, 4076, 0, +3990, 4095, 0, +3019, 0, 2750, +3019, 0, 2749, +3019, 0, 2748, +3019, 0, 2747, +3019, 0, 2746, +3019, 0, 2744, +3019, 0, 2742, +3019, 0, 2738, +3019, 0, 2734, +3019, 0, 2728, +3019, 0, 2720, +3019, 0, 2708, +3019, 0, 2693, +3019, 0, 2672, +3019, 0, 2641, +3019, 0, 2597, +3019, 0, 2530, +3019, 0, 2422, +3019, 0, 2220, +3019, 0, 1594, +3019, 0, 0, +3019, 0, 0, +3019, 2346, 0, +3152, 2868, 0, +3284, 3162, 0, +3416, 3387, 0, +3516, 3548, 0, +3599, 3680, 0, +3691, 3812, 0, +3790, 3944, 0, +3895, 4076, 0, +4007, 4095, 0, +3152, 0, 2882, +3152, 0, 2881, +3152, 0, 2881, +3152, 0, 2880, +3152, 0, 2879, +3152, 0, 2878, +3152, 0, 2876, +3152, 0, 2873, +3152, 0, 2870, +3152, 0, 2866, +3152, 0, 2860, +3152, 0, 2851, +3152, 0, 2840, +3152, 0, 2825, +3152, 0, 2803, +3152, 0, 2773, +3152, 0, 2729, +3152, 0, 2662, +3152, 0, 2554, +3152, 0, 2352, +3152, 0, 1720, +3152, 0, 0, +3152, 0, 0, +3152, 2478, 0, +3284, 2999, 0, +3416, 3294, 0, +3548, 3519, 0, +3649, 3680, 0, +3732, 3812, 0, +3823, 3944, 0, +3922, 4076, 0, +4027, 4095, 0, +3284, 0, 3014, +3284, 0, 3014, +3284, 0, 3013, +3284, 0, 3012, +3284, 0, 3012, +3284, 0, 3011, +3284, 0, 3009, +3284, 0, 3008, +3284, 0, 3005, +3284, 0, 3002, +3284, 0, 2997, +3284, 0, 2991, +3284, 0, 2983, +3284, 0, 2972, +3284, 0, 2956, +3284, 0, 2935, +3284, 0, 2904, +3284, 0, 2860, +3284, 0, 2793, +3284, 0, 2684, +3284, 0, 2481, +3284, 0, 1844, +3284, 0, 0, +3284, 0, 0, +3284, 2609, 0, +3416, 3132, 0, +3548, 3426, 0, +3680, 3651, 0, +3781, 3812, 0, +3864, 3944, 0, +3955, 4076, 0, +4054, 4095, 0, +3416, 0, 3146, +3416, 0, 3146, +3416, 0, 3145, +3416, 0, 3145, +3416, 0, 3144, +3416, 0, 3144, +3416, 0, 3143, +3416, 0, 3141, +3416, 0, 3139, +3416, 0, 3137, +3416, 0, 3134, +3416, 0, 3129, +3416, 0, 3123, +3416, 0, 3115, +3416, 0, 3104, +3416, 0, 3088, +3416, 0, 3067, +3416, 0, 3036, +3416, 0, 2992, +3416, 0, 2925, +3416, 0, 2816, +3416, 0, 2613, +3416, 0, 1977, +3416, 0, 0, +3416, 0, 0, +3416, 2741, 0, +3548, 3264, 0, +3680, 3558, 0, +3812, 3783, 0, +3913, 3944, 0, +3996, 4076, 0, +4087, 4095, 0, +3548, 0, 3278, +3548, 0, 3278, +3548, 0, 3278, +3548, 0, 3277, +3548, 0, 3277, +3548, 0, 3276, +3548, 0, 3276, +3548, 0, 3275, +3548, 0, 3273, +3548, 0, 3271, +3548, 0, 3269, +3548, 0, 3266, +3548, 0, 3261, +3548, 0, 3255, +3548, 0, 3247, +3548, 0, 3236, +3548, 0, 3220, +3548, 0, 3198, +3548, 0, 3168, +3548, 0, 3124, +3548, 0, 3056, +3548, 0, 2948, +3548, 0, 2745, +3548, 0, 2104, +3548, 0, 0, +3548, 0, 0, +3548, 2873, 0, +3680, 3396, 0, +3812, 3691, 0, +3944, 3915, 0, +4045, 4076, 0, +4095, 4095, 0, +3680, 0, 3410, +3680, 0, 3410, +3680, 0, 3410, +3680, 0, 3410, +3680, 0, 3409, +3680, 0, 3409, +3680, 0, 3408, +3680, 0, 3408, +3680, 0, 3406, +3680, 0, 3405, +3680, 0, 3403, +3680, 0, 3401, +3680, 0, 3398, +3680, 0, 3393, +3680, 0, 3387, +3680, 0, 3379, +3680, 0, 3367, +3680, 0, 3352, +3680, 0, 3330, +3680, 0, 3300, +3680, 0, 3255, +3680, 0, 3188, +3680, 0, 3080, +3680, 0, 2876, +3680, 0, 2237, +3680, 0, 0, +3680, 0, 0, +3680, 3005, 0, +3812, 3528, 0, +3944, 3822, 0, +4076, 4047, 0, +4095, 4095, 0, +3812, 0, 3542, +3812, 0, 3542, +3812, 0, 3542, +3812, 0, 3542, +3812, 0, 3541, +3812, 0, 3541, +3812, 0, 3541, +3812, 0, 3540, +3812, 0, 3540, +3812, 0, 3538, +3812, 0, 3537, +3812, 0, 3535, +3812, 0, 3533, +3812, 0, 3530, +3812, 0, 3525, +3812, 0, 3519, +3812, 0, 3511, +3812, 0, 3499, +3812, 0, 3484, +3812, 0, 3462, +3812, 0, 3432, +3812, 0, 3387, +3812, 0, 3320, +3812, 0, 3211, +3812, 0, 3008, +3812, 0, 2367, +3812, 0, 0, +3812, 0, 0, +3812, 3137, 0, +3944, 3660, 0, +4076, 3954, 0, +4095, 4095, 0, +3944, 0, 3674, +3944, 0, 3674, +3944, 0, 3674, +3944, 0, 3674, +3944, 0, 3674, +3944, 0, 3674, +3944, 0, 3673, +3944, 0, 3673, +3944, 0, 3672, +3944, 0, 3671, +3944, 0, 3670, +3944, 0, 3669, +3944, 0, 3667, +3944, 0, 3665, +3944, 0, 3661, +3944, 0, 3657, +3944, 0, 3651, +3944, 0, 3643, +3944, 0, 3631, +3944, 0, 3616, +3944, 0, 3594, +3944, 0, 3564, +3944, 0, 3520, +3944, 0, 3452, +3944, 0, 3344, +3944, 0, 3140, +3944, 0, 2497, +3944, 0, 0, +3944, 0, 0, +3944, 3269, 0, +4076, 3791, 0, +4095, 4087, 0, +4076, 0, 3806, +4076, 0, 3806, +4076, 0, 3806, +4076, 0, 3806, +4076, 0, 3806, +4076, 0, 3806, +4076, 0, 3805, +4076, 0, 3805, +4076, 0, 3805, +4076, 0, 3804, +4076, 0, 3803, +4076, 0, 3803, +4076, 0, 3801, +4076, 0, 3799, +4076, 0, 3797, +4076, 0, 3793, +4076, 0, 3789, +4076, 0, 3783, +4076, 0, 3774, +4076, 0, 3763, +4076, 0, 3748, +4076, 0, 3726, +4076, 0, 3696, +4076, 0, 3651, +4076, 0, 3584, +4076, 0, 3475, +4076, 0, 3271, +4076, 0, 2626, +4076, 0, 0, +4076, 0, 0, +4076, 3401, 0, +4095, 3924, 0, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3938, +4095, 0, 3938, +4095, 0, 3938, +4095, 0, 3938, +4095, 0, 3938, +4095, 0, 3938, +4095, 0, 3937, +4095, 0, 3937, +4095, 0, 3937, +4095, 0, 3936, +4095, 0, 3935, +4095, 0, 3933, +4095, 0, 3932, +4095, 0, 3929, +4095, 0, 3926, +4095, 0, 3921, +4095, 0, 3915, +4095, 0, 3907, +4095, 0, 3896, +4095, 0, 3880, +4095, 0, 3859, +4095, 0, 3828, +4095, 0, 3784, +4095, 0, 3716, +4095, 0, 3608, +4095, 0, 3404, +4095, 0, 2761, +4095, 0, 0, +4095, 0, 0, +4095, 3533, 0, +0, 97, 163, +0, 163, 42, +13, 318, 0, +171, 466, 0, +322, 609, 0, +467, 750, 0, +608, 888, 0, +748, 1025, 0, +885, 1160, 0, +1021, 1295, 0, +1156, 1429, 0, +1290, 1563, 0, +1424, 1696, 0, +1557, 1828, 0, +1690, 1961, 0, +1823, 2094, 0, +1956, 2226, 0, +2088, 2358, 0, +2220, 2491, 0, +2352, 2623, 0, +2485, 2755, 0, +2617, 2887, 0, +2749, 3019, 0, +2881, 3152, 0, +3014, 3284, 0, +3146, 3416, 0, +3278, 3548, 0, +3410, 3680, 0, +3542, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3939, 4095, 0, +42, 0, 163, +131, 131, 131, +229, 295, 86, +333, 450, 15, +444, 598, 0, +559, 741, 0, +678, 882, 0, +800, 1020, 0, +924, 1157, 0, +1050, 1292, 0, +1178, 1427, 0, +1307, 1561, 0, +1436, 1695, 0, +1566, 1828, 0, +1697, 1961, 0, +1828, 2093, 0, +1959, 2226, 0, +2091, 2358, 0, +2223, 2491, 0, +2354, 2623, 0, +2486, 2755, 0, +2618, 2887, 0, +2750, 3019, 0, +2882, 3152, 0, +3014, 3283, 0, +3146, 3416, 0, +3278, 3548, 0, +3410, 3680, 0, +3542, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3939, 4095, 0, +300, 0, 318, +295, 86, 229, +295, 174, 86, +450, 432, 15, +551, 598, 0, +644, 741, 0, +745, 882, 0, +852, 1020, 0, +964, 1157, 0, +1081, 1292, 0, +1201, 1427, 0, +1325, 1561, 0, +1450, 1695, 0, +1576, 1828, 0, +1705, 1961, 0, +1834, 2093, 0, +1963, 2226, 0, +2094, 2358, 0, +2225, 2491, 0, +2356, 2623, 0, +2488, 2755, 0, +2619, 2887, 0, +2751, 3019, 0, +2883, 3152, 0, +3014, 3283, 0, +3146, 3416, 0, +3278, 3548, 0, +3410, 3680, 0, +3543, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3939, 4095, 0, +466, 0, 419, +450, 15, 333, +450, 15, 145, +450, 225, 15, +598, 520, 0, +738, 741, 0, +822, 882, 0, +914, 1020, 0, +1013, 1157, 0, +1119, 1292, 0, +1231, 1427, 0, +1347, 1561, 0, +1467, 1695, 0, +1590, 1828, 0, +1715, 1961, 0, +1841, 2093, 0, +1969, 2226, 0, +2098, 2358, 0, +2228, 2491, 0, +2358, 2623, 0, +2489, 2755, 0, +2620, 2887, 0, +2752, 3019, 0, +2883, 3152, 0, +3015, 3283, 0, +3147, 3416, 0, +3279, 3548, 0, +3411, 3680, 0, +3543, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3939, 4095, 0, +609, 0, 512, +598, 0, 444, +598, 0, 303, +598, 0, 0, +598, 286, 0, +741, 616, 0, +882, 855, 0, +985, 1020, 0, +1071, 1157, 0, +1166, 1292, 0, +1267, 1427, 0, +1376, 1561, 0, +1489, 1695, 0, +1607, 1828, 0, +1728, 1961, 0, +1851, 2093, 0, +1977, 2226, 0, +2104, 2358, 0, +2233, 2491, 0, +2362, 2623, 0, +2492, 2755, 0, +2622, 2887, 0, +2753, 3019, 0, +2885, 3152, 0, +3016, 3283, 0, +3147, 3416, 0, +3279, 3548, 0, +3411, 3680, 0, +3543, 3812, 0, +3675, 3944, 0, +3807, 4076, 0, +3939, 4095, 0, +750, 0, 613, +741, 0, 559, +741, 0, 453, +741, 0, 258, +741, 0, 0, +741, 356, 0, +882, 719, 0, +1020, 970, 0, +1139, 1157, 0, +1221, 1292, 0, +1313, 1427, 0, +1412, 1561, 0, +1517, 1695, 0, +1629, 1828, 0, +1745, 1961, 0, +1864, 2093, 0, +1987, 2226, 0, +2111, 2358, 0, +2238, 2491, 0, +2366, 2623, 0, +2495, 2755, 0, +2625, 2887, 0, +2755, 3019, 0, +2886, 3152, 0, +3017, 3283, 0, +3148, 3416, 0, +3280, 3548, 0, +3411, 3680, 0, +3543, 3812, 0, +3675, 3944, 0, +3807, 4076, 0, +3939, 4095, 0, +888, 0, 719, +882, 0, 678, +882, 0, 599, +882, 0, 466, +882, 0, 190, +882, 0, 0, +882, 436, 0, +1020, 829, 0, +1157, 1089, 0, +1286, 1292, 0, +1366, 1427, 0, +1456, 1561, 0, +1552, 1695, 0, +1656, 1828, 0, +1766, 1961, 0, +1881, 2093, 0, +1999, 2226, 0, +2121, 2358, 0, +2245, 2491, 0, +2372, 2623, 0, +2499, 2755, 0, +2628, 2887, 0, +2757, 3019, 0, +2888, 3152, 0, +3018, 3283, 0, +3149, 3416, 0, +3280, 3548, 0, +3412, 3680, 0, +3544, 3812, 0, +3675, 3944, 0, +3807, 4076, 0, +3939, 4095, 0, +1025, 0, 832, +1020, 0, 800, +1020, 0, 740, +1020, 0, 647, +1020, 0, 482, +1020, 0, 81, +1020, 0, 0, +1020, 524, 0, +1157, 943, 0, +1292, 1211, 0, +1427, 1424, 0, +1508, 1561, 0, +1596, 1695, 0, +1691, 1828, 0, +1793, 1961, 0, +1902, 2093, 0, +2016, 2226, 0, +2134, 2358, 0, +2255, 2491, 0, +2379, 2623, 0, +2505, 2755, 0, +2632, 2887, 0, +2760, 3019, 0, +2890, 3152, 0, +3020, 3283, 0, +3151, 3416, 0, +3281, 3548, 0, +3413, 3680, 0, +3544, 3812, 0, +3676, 3944, 0, +3807, 4076, 0, +3939, 4095, 0, +1160, 0, 949, +1157, 0, 924, +1157, 0, 879, +1157, 0, 813, +1157, 0, 705, +1157, 0, 503, +1157, 0, 0, +1157, 0, 0, +1157, 620, 0, +1292, 1062, 0, +1427, 1336, 0, +1561, 1552, 0, +1647, 1695, 0, +1733, 1828, 0, +1828, 1961, 0, +1929, 2093, 0, +2037, 2226, 0, +2150, 2358, 0, +2268, 2491, 0, +2388, 2623, 0, +2512, 2755, 0, +2638, 2887, 0, +2765, 3019, 0, +2893, 3152, 0, +3022, 3283, 0, +3152, 3416, 0, +3283, 3548, 0, +3414, 3680, 0, +3545, 3812, 0, +3676, 3944, 0, +3808, 4076, 0, +3940, 4095, 0, +1295, 0, 1069, +1292, 0, 1050, +1292, 0, 1017, +1292, 0, 968, +1292, 0, 894, +1292, 0, 772, +1292, 0, 529, +1292, 0, 0, +1292, 0, 0, +1292, 724, 0, +1427, 1182, 0, +1561, 1463, 0, +1695, 1680, 0, +1785, 1828, 0, +1870, 1961, 0, +1963, 2093, 0, +2064, 2226, 0, +2171, 2358, 0, +2284, 2491, 0, +2401, 2623, 0, +2522, 2755, 0, +2645, 2887, 0, +2770, 3019, 0, +2897, 3152, 0, +3025, 3283, 0, +3154, 3416, 0, +3284, 3548, 0, +3415, 3680, 0, +3546, 3812, 0, +3677, 3944, 0, +3808, 4076, 0, +3940, 4095, 0, +1429, 0, 1192, +1427, 0, 1178, +1427, 0, 1153, +1427, 0, 1118, +1427, 0, 1065, +1427, 0, 985, +1427, 0, 849, +1427, 0, 562, +1427, 0, 0, +1427, 0, 0, +1427, 833, 0, +1561, 1307, 0, +1695, 1590, 0, +1828, 1810, 0, +1920, 1961, 0, +2005, 2093, 0, +2098, 2226, 0, +2199, 2358, 0, +2305, 2491, 0, +2417, 2623, 0, +2535, 2755, 0, +2655, 2887, 0, +2777, 3019, 0, +2903, 3152, 0, +3029, 3283, 0, +3158, 3416, 0, +3287, 3548, 0, +3417, 3680, 0, +3547, 3812, 0, +3678, 3944, 0, +3809, 4076, 0, +3941, 4095, 0, +1563, 0, 1318, +1561, 0, 1307, +1561, 0, 1288, +1561, 0, 1262, +1561, 0, 1225, +1561, 0, 1170, +1561, 0, 1084, +1561, 0, 935, +1561, 0, 605, +1561, 0, 0, +1561, 0, 0, +1561, 948, 0, +1695, 1432, 0, +1828, 1719, 0, +1961, 1940, 0, +2056, 2093, 0, +2140, 2226, 0, +2232, 2358, 0, +2332, 2491, 0, +2439, 2623, 0, +2551, 2755, 0, +2667, 2887, 0, +2787, 3019, 0, +2910, 3152, 0, +3035, 3283, 0, +3162, 3416, 0, +3290, 3548, 0, +3419, 3680, 0, +3549, 3812, 0, +3679, 3944, 0, +3810, 4076, 0, +3941, 4095, 0, +1696, 0, 1444, +1695, 0, 1436, +1695, 0, 1422, +1695, 0, 1403, +1695, 0, 1376, +1695, 0, 1337, +1695, 0, 1279, +1695, 0, 1188, +1695, 0, 1029, +1695, 0, 653, +1695, 0, 0, +1695, 0, 0, +1695, 1066, 0, +1828, 1560, 0, +1961, 1849, 0, +2093, 2070, 0, +2190, 2226, 0, +2273, 2358, 0, +2366, 2491, 0, +2465, 2623, 0, +2572, 2755, 0, +2684, 2887, 0, +2800, 3019, 0, +2920, 3152, 0, +3042, 3283, 0, +3168, 3416, 0, +3294, 3548, 0, +3422, 3680, 0, +3551, 3812, 0, +3681, 3944, 0, +3811, 4076, 0, +3942, 4095, 0, +1828, 0, 1572, +1828, 0, 1566, +1828, 0, 1556, +1828, 0, 1542, +1828, 0, 1522, +1828, 0, 1494, +1828, 0, 1454, +1828, 0, 1394, +1828, 0, 1300, +1828, 0, 1131, +1828, 0, 713, +1828, 0, 0, +1828, 0, 0, +1828, 1188, 0, +1961, 1689, 0, +2093, 1979, 0, +2226, 2201, 0, +2324, 2358, 0, +2407, 2491, 0, +2499, 2623, 0, +2598, 2755, 0, +2705, 2887, 0, +2816, 3019, 0, +2932, 3152, 0, +3052, 3283, 0, +3175, 3416, 0, +3300, 3548, 0, +3426, 3680, 0, +3554, 3812, 0, +3683, 3944, 0, +3813, 4076, 0, +3944, 4095, 0, +1961, 0, 1702, +1961, 0, 1697, +1961, 0, 1689, +1961, 0, 1679, +1961, 0, 1664, +1961, 0, 1644, +1961, 0, 1615, +1961, 0, 1574, +1961, 0, 1513, +1961, 0, 1415, +1961, 0, 1238, +1961, 0, 780, +1961, 0, 0, +1961, 0, 0, +1961, 1312, 0, +2093, 1818, 0, +2226, 2109, 0, +2358, 2332, 0, +2457, 2491, 0, +2540, 2623, 0, +2632, 2755, 0, +2731, 2887, 0, +2837, 3019, 0, +2949, 3152, 0, +3065, 3283, 0, +3184, 3416, 0, +3307, 3548, 0, +3432, 3680, 0, +3559, 3812, 0, +3687, 3944, 0, +3816, 4076, 0, +3946, 4095, 0, +2094, 0, 1831, +2093, 0, 1828, +2093, 0, 1822, +2093, 0, 1814, +2093, 0, 1804, +2093, 0, 1789, +2093, 0, 1768, +2093, 0, 1739, +2093, 0, 1698, +2093, 0, 1635, +2093, 0, 1534, +2093, 0, 1351, +2093, 0, 859, +2093, 0, 0, +2093, 0, 0, +2093, 1438, 0, +2226, 1948, 0, +2358, 2240, 0, +2491, 2464, 0, +2590, 2623, 0, +2673, 2755, 0, +2764, 2887, 0, +2863, 3019, 0, +2970, 3152, 0, +3081, 3283, 0, +3197, 3416, 0, +3317, 3548, 0, +3439, 3680, 0, +3564, 3812, 0, +3691, 3944, 0, +3819, 4076, 0, +3948, 4095, 0, +2226, 0, 1962, +2226, 0, 1959, +2226, 0, 1955, +2226, 0, 1949, +2226, 0, 1941, +2226, 0, 1930, +2226, 0, 1915, +2226, 0, 1894, +2226, 0, 1865, +2226, 0, 1823, +2226, 0, 1759, +2226, 0, 1656, +2226, 0, 1469, +2226, 0, 944, +2226, 0, 0, +2226, 0, 0, +2226, 1565, 0, +2358, 2079, 0, +2491, 2372, 0, +2623, 2595, 0, +2723, 2755, 0, +2805, 2887, 0, +2897, 3019, 0, +2996, 3152, 0, +3102, 3283, 0, +3213, 3416, 0, +3329, 3548, 0, +3449, 3680, 0, +3572, 3812, 0, +3696, 3944, 0, +3823, 4076, 0, +3951, 4095, 0, +2358, 0, 2093, +2358, 0, 2091, +2358, 0, 2087, +2358, 0, 2083, +2358, 0, 2077, +2358, 0, 2069, +2358, 0, 2058, +2358, 0, 2043, +2358, 0, 2022, +2358, 0, 1993, +2358, 0, 1950, +2358, 0, 1885, +2358, 0, 1781, +2358, 0, 1589, +2358, 0, 1039, +2358, 0, 0, +2358, 0, 0, +2358, 1694, 0, +2491, 2210, 0, +2623, 2503, 0, +2755, 2727, 0, +2855, 2887, 0, +2938, 3019, 0, +3029, 3152, 0, +3128, 3283, 0, +3234, 3416, 0, +3346, 3548, 0, +3462, 3680, 0, +3581, 3812, 0, +3704, 3944, 0, +3828, 4076, 0, +3955, 4095, 0, +2491, 0, 2224, +2491, 0, 2223, +2491, 0, 2220, +2491, 0, 2217, +2491, 0, 2212, +2491, 0, 2206, +2491, 0, 2199, +2491, 0, 2187, +2491, 0, 2172, +2491, 0, 2151, +2491, 0, 2121, +2491, 0, 2078, +2491, 0, 2013, +2491, 0, 1907, +2491, 0, 1713, +2491, 0, 1143, +2491, 0, 0, +2491, 0, 0, +2491, 1824, 0, +2623, 2341, 0, +2755, 2635, 0, +2887, 2859, 0, +2987, 3019, 0, +3070, 3152, 0, +3162, 3283, 0, +3261, 3416, 0, +3367, 3548, 0, +3478, 3680, 0, +3594, 3812, 0, +3713, 3944, 0, +3836, 4076, 0, +3961, 4095, 0, +2623, 0, 2355, +2623, 0, 2354, +2623, 0, 2352, +2623, 0, 2350, +2623, 0, 2347, +2623, 0, 2342, +2623, 0, 2336, +2623, 0, 2328, +2623, 0, 2317, +2623, 0, 2302, +2623, 0, 2281, +2623, 0, 2250, +2623, 0, 2207, +2623, 0, 2141, +2623, 0, 2035, +2623, 0, 1838, +2623, 0, 1251, +2623, 0, 0, +2623, 0, 0, +2623, 1954, 0, +2755, 2473, 0, +2887, 2767, 0, +3019, 2991, 0, +3120, 3152, 0, +3203, 3283, 0, +3294, 3416, 0, +3393, 3548, 0, +3499, 3680, 0, +3610, 3812, 0, +3726, 3944, 0, +3845, 4076, 0, +3968, 4095, 0, +2755, 0, 2487, +2755, 0, 2486, +2755, 0, 2485, +2755, 0, 2483, +2755, 0, 2481, +2755, 0, 2477, +2755, 0, 2473, +2755, 0, 2467, +2755, 0, 2459, +2755, 0, 2448, +2755, 0, 2432, +2755, 0, 2411, +2755, 0, 2381, +2755, 0, 2337, +2755, 0, 2271, +2755, 0, 2164, +2755, 0, 1966, +2755, 0, 1367, +2755, 0, 0, +2755, 0, 0, +2755, 2084, 0, +2887, 2604, 0, +3019, 2898, 0, +3152, 3123, 0, +3252, 3283, 0, +3335, 3416, 0, +3426, 3548, 0, +3525, 3680, 0, +3631, 3812, 0, +3742, 3944, 0, +3858, 4076, 0, +3978, 4095, 0, +2887, 0, 2619, +2887, 0, 2618, +2887, 0, 2617, +2887, 0, 2616, +2887, 0, 2614, +2887, 0, 2612, +2887, 0, 2608, +2887, 0, 2604, +2887, 0, 2598, +2887, 0, 2589, +2887, 0, 2578, +2887, 0, 2563, +2887, 0, 2542, +2887, 0, 2511, +2887, 0, 2467, +2887, 0, 2401, +2887, 0, 2294, +2887, 0, 2094, +2887, 0, 1483, +2887, 0, 0, +2887, 0, 0, +2887, 2215, 0, +3019, 2735, 0, +3152, 3031, 0, +3283, 3254, 0, +3385, 3416, 0, +3467, 3548, 0, +3558, 3680, 0, +3657, 3812, 0, +3763, 3944, 0, +3874, 4076, 0, +3990, 4095, 0, +3019, 0, 2750, +3019, 0, 2750, +3019, 0, 2749, +3019, 0, 2748, +3019, 0, 2747, +3019, 0, 2745, +3019, 0, 2742, +3019, 0, 2739, +3019, 0, 2735, +3019, 0, 2729, +3019, 0, 2720, +3019, 0, 2709, +3019, 0, 2694, +3019, 0, 2672, +3019, 0, 2642, +3019, 0, 2598, +3019, 0, 2531, +3019, 0, 2424, +3019, 0, 2222, +3019, 0, 1602, +3019, 0, 0, +3019, 0, 0, +3019, 2346, 0, +3152, 2868, 0, +3283, 3162, 0, +3416, 3387, 0, +3516, 3548, 0, +3599, 3680, 0, +3691, 3812, 0, +3790, 3944, 0, +3895, 4076, 0, +4006, 4095, 0, +3152, 0, 2883, +3152, 0, 2882, +3152, 0, 2881, +3152, 0, 2881, +3152, 0, 2880, +3152, 0, 2878, +3152, 0, 2877, +3152, 0, 2874, +3152, 0, 2871, +3152, 0, 2866, +3152, 0, 2860, +3152, 0, 2852, +3152, 0, 2841, +3152, 0, 2825, +3152, 0, 2804, +3152, 0, 2773, +3152, 0, 2729, +3152, 0, 2663, +3152, 0, 2555, +3152, 0, 2353, +3152, 0, 1726, +3152, 0, 0, +3152, 0, 0, +3152, 2478, 0, +3283, 2999, 0, +3416, 3294, 0, +3548, 3519, 0, +3649, 3680, 0, +3731, 3812, 0, +3823, 3944, 0, +3922, 4076, 0, +4027, 4095, 0, +3284, 0, 3014, +3283, 0, 3014, +3283, 0, 3014, +3283, 0, 3013, +3283, 0, 3012, +3283, 0, 3011, +3283, 0, 3010, +3283, 0, 3008, +3283, 0, 3005, +3283, 0, 3002, +3283, 0, 2998, +3283, 0, 2992, +3283, 0, 2983, +3283, 0, 2972, +3283, 0, 2957, +3283, 0, 2935, +3283, 0, 2905, +3283, 0, 2860, +3283, 0, 2793, +3283, 0, 2685, +3283, 0, 2482, +3283, 0, 1849, +3283, 0, 0, +3283, 0, 0, +3283, 2609, 0, +3416, 3132, 0, +3548, 3426, 0, +3680, 3651, 0, +3781, 3812, 0, +3864, 3944, 0, +3955, 4076, 0, +4054, 4095, 0, +3416, 0, 3146, +3416, 0, 3146, +3416, 0, 3146, +3416, 0, 3145, +3416, 0, 3145, +3416, 0, 3144, +3416, 0, 3143, +3416, 0, 3141, +3416, 0, 3140, +3416, 0, 3137, +3416, 0, 3134, +3416, 0, 3129, +3416, 0, 3123, +3416, 0, 3115, +3416, 0, 3104, +3416, 0, 3088, +3416, 0, 3067, +3416, 0, 3036, +3416, 0, 2992, +3416, 0, 2925, +3416, 0, 2817, +3416, 0, 2614, +3416, 0, 1981, +3416, 0, 0, +3416, 0, 0, +3416, 2741, 0, +3548, 3264, 0, +3680, 3558, 0, +3812, 3783, 0, +3913, 3944, 0, +3996, 4076, 0, +4087, 4095, 0, +3548, 0, 3278, +3548, 0, 3278, +3548, 0, 3278, +3548, 0, 3278, +3548, 0, 3277, +3548, 0, 3277, +3548, 0, 3276, +3548, 0, 3275, +3548, 0, 3273, +3548, 0, 3272, +3548, 0, 3269, +3548, 0, 3266, +3548, 0, 3261, +3548, 0, 3255, +3548, 0, 3247, +3548, 0, 3236, +3548, 0, 3220, +3548, 0, 3199, +3548, 0, 3168, +3548, 0, 3124, +3548, 0, 3057, +3548, 0, 2948, +3548, 0, 2745, +3548, 0, 2107, +3548, 0, 0, +3548, 0, 0, +3548, 2873, 0, +3680, 3396, 0, +3812, 3691, 0, +3944, 3915, 0, +4045, 4076, 0, +4095, 4095, 0, +3680, 0, 3410, +3680, 0, 3410, +3680, 0, 3410, +3680, 0, 3410, +3680, 0, 3409, +3680, 0, 3409, +3680, 0, 3408, +3680, 0, 3408, +3680, 0, 3407, +3680, 0, 3405, +3680, 0, 3403, +3680, 0, 3401, +3680, 0, 3398, +3680, 0, 3393, +3680, 0, 3387, +3680, 0, 3379, +3680, 0, 3368, +3680, 0, 3352, +3680, 0, 3331, +3680, 0, 3300, +3680, 0, 3256, +3680, 0, 3188, +3680, 0, 3080, +3680, 0, 2877, +3680, 0, 2239, +3680, 0, 0, +3680, 0, 0, +3680, 3005, 0, +3812, 3528, 0, +3944, 3822, 0, +4076, 4047, 0, +4095, 4095, 0, +3812, 0, 3542, +3812, 0, 3542, +3812, 0, 3542, +3812, 0, 3542, +3812, 0, 3542, +3812, 0, 3541, +3812, 0, 3541, +3812, 0, 3540, +3812, 0, 3540, +3812, 0, 3538, +3812, 0, 3537, +3812, 0, 3536, +3812, 0, 3533, +3812, 0, 3530, +3812, 0, 3525, +3812, 0, 3519, +3812, 0, 3511, +3812, 0, 3499, +3812, 0, 3484, +3812, 0, 3462, +3812, 0, 3432, +3812, 0, 3388, +3812, 0, 3321, +3812, 0, 3212, +3812, 0, 3009, +3812, 0, 2369, +3812, 0, 0, +3812, 0, 0, +3812, 3137, 0, +3944, 3660, 0, +4076, 3954, 0, +4095, 4095, 0, +3944, 0, 3674, +3944, 0, 3674, +3944, 0, 3674, +3944, 0, 3674, +3944, 0, 3674, +3944, 0, 3674, +3944, 0, 3673, +3944, 0, 3673, +3944, 0, 3672, +3944, 0, 3671, +3944, 0, 3671, +3944, 0, 3669, +3944, 0, 3667, +3944, 0, 3665, +3944, 0, 3662, +3944, 0, 3657, +3944, 0, 3651, +3944, 0, 3643, +3944, 0, 3632, +3944, 0, 3616, +3944, 0, 3595, +3944, 0, 3564, +3944, 0, 3520, +3944, 0, 3452, +3944, 0, 3344, +3944, 0, 3140, +3944, 0, 2498, +3944, 0, 0, +3944, 0, 0, +3944, 3269, 0, +4076, 3792, 0, +4095, 4087, 0, +4076, 0, 3806, +4076, 0, 3806, +4076, 0, 3806, +4076, 0, 3806, +4076, 0, 3806, +4076, 0, 3806, +4076, 0, 3805, +4076, 0, 3805, +4076, 0, 3805, +4076, 0, 3804, +4076, 0, 3803, +4076, 0, 3803, +4076, 0, 3801, +4076, 0, 3799, +4076, 0, 3797, +4076, 0, 3793, +4076, 0, 3789, +4076, 0, 3783, +4076, 0, 3775, +4076, 0, 3763, +4076, 0, 3748, +4076, 0, 3726, +4076, 0, 3696, +4076, 0, 3651, +4076, 0, 3584, +4076, 0, 3475, +4076, 0, 3272, +4076, 0, 2627, +4076, 0, 0, +4076, 0, 0, +4076, 3401, 0, +4095, 3924, 0, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3938, +4095, 0, 3938, +4095, 0, 3938, +4095, 0, 3938, +4095, 0, 3938, +4095, 0, 3937, +4095, 0, 3937, +4095, 0, 3937, +4095, 0, 3936, +4095, 0, 3935, +4095, 0, 3933, +4095, 0, 3932, +4095, 0, 3929, +4095, 0, 3926, +4095, 0, 3921, +4095, 0, 3915, +4095, 0, 3907, +4095, 0, 3896, +4095, 0, 3880, +4095, 0, 3859, +4095, 0, 3828, +4095, 0, 3784, +4095, 0, 3717, +4095, 0, 3608, +4095, 0, 3404, +4095, 0, 2762, +4095, 0, 0, +4095, 0, 0, +4095, 3533, 0, +0, 201, 318, +0, 318, 300, +0, 318, 93, +0, 466, 0, +127, 609, 0, +334, 750, 0, +515, 888, 0, +681, 1025, 0, +836, 1160, 0, +985, 1295, 0, +1130, 1429, 0, +1271, 1563, 0, +1410, 1696, 0, +1547, 1828, 0, +1682, 1961, 0, +1817, 2094, 0, +1951, 2226, 0, +2085, 2358, 0, +2218, 2491, 0, +2351, 2623, 0, +2484, 2755, 0, +2616, 2887, 0, +2748, 3019, 0, +2881, 3152, 0, +3013, 3284, 0, +3145, 3416, 0, +3278, 3548, 0, +3410, 3680, 0, +3542, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3938, 4095, 0, +0, 13, 318, +86, 229, 295, +86, 295, 174, +145, 450, 15, +303, 598, 0, +453, 741, 0, +599, 882, 0, +740, 1020, 0, +879, 1157, 0, +1017, 1292, 0, +1153, 1427, 0, +1288, 1561, 0, +1422, 1695, 0, +1556, 1828, 0, +1689, 1961, 0, +1822, 2093, 0, +1955, 2226, 0, +2087, 2358, 0, +2220, 2491, 0, +2352, 2623, 0, +2485, 2755, 0, +2617, 2887, 0, +2749, 3019, 0, +2881, 3152, 0, +3014, 3283, 0, +3146, 3416, 0, +3278, 3548, 0, +3410, 3680, 0, +3542, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3939, 4095, 0, +93, 0, 318, +174, 86, 295, +264, 264, 264, +361, 427, 218, +466, 582, 148, +576, 730, 34, +691, 873, 0, +810, 1014, 0, +932, 1152, 0, +1056, 1289, 0, +1182, 1424, 0, +1310, 1559, 0, +1439, 1693, 0, +1568, 1827, 0, +1699, 1960, 0, +1829, 2093, 0, +1960, 2225, 0, +2091, 2358, 0, +2223, 2490, 0, +2355, 2623, 0, +2486, 2755, 0, +2618, 2887, 0, +2750, 3019, 0, +2882, 3152, 0, +3014, 3283, 0, +3146, 3416, 0, +3278, 3548, 0, +3410, 3680, 0, +3542, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3939, 4095, 0, +388, 0, 466, +432, 15, 450, +427, 218, 361, +427, 306, 218, +582, 564, 148, +683, 730, 34, +776, 873, 0, +877, 1014, 0, +984, 1152, 0, +1096, 1289, 0, +1213, 1424, 0, +1333, 1559, 0, +1456, 1693, 0, +1582, 1827, 0, +1708, 1960, 0, +1837, 2093, 0, +1966, 2225, 0, +2096, 2358, 0, +2226, 2490, 0, +2357, 2623, 0, +2488, 2755, 0, +2620, 2887, 0, +2751, 3019, 0, +2883, 3152, 0, +3014, 3283, 0, +3147, 3416, 0, +3279, 3548, 0, +3410, 3680, 0, +3543, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3939, 4095, 0, +609, 0, 606, +598, 0, 551, +582, 148, 466, +582, 148, 277, +582, 357, 148, +730, 652, 34, +870, 873, 0, +954, 1014, 0, +1045, 1152, 0, +1145, 1289, 0, +1251, 1424, 0, +1363, 1559, 0, +1479, 1693, 0, +1599, 1827, 0, +1722, 1960, 0, +1847, 2093, 0, +1973, 2225, 0, +2101, 2358, 0, +2230, 2490, 0, +2360, 2623, 0, +2491, 2755, 0, +2621, 2887, 0, +2752, 3019, 0, +2884, 3152, 0, +3015, 3283, 0, +3147, 3416, 0, +3279, 3548, 0, +3411, 3680, 0, +3543, 3812, 0, +3675, 3944, 0, +3807, 4076, 0, +3939, 4095, 0, +750, 0, 689, +741, 0, 644, +730, 34, 576, +730, 34, 435, +730, 34, 132, +730, 418, 34, +873, 749, 0, +1014, 987, 0, +1117, 1152, 0, +1203, 1289, 0, +1298, 1424, 0, +1400, 1559, 0, +1508, 1693, 0, +1621, 1827, 0, +1739, 1960, 0, +1860, 2093, 0, +1983, 2225, 0, +2109, 2358, 0, +2236, 2490, 0, +2364, 2623, 0, +2494, 2755, 0, +2624, 2887, 0, +2754, 3019, 0, +2885, 3152, 0, +3016, 3283, 0, +3148, 3416, 0, +3280, 3548, 0, +3411, 3680, 0, +3543, 3812, 0, +3675, 3944, 0, +3807, 4076, 0, +3939, 4095, 0, +888, 0, 781, +882, 0, 745, +873, 0, 691, +873, 0, 585, +873, 0, 390, +873, 0, 0, +873, 488, 0, +1014, 852, 0, +1152, 1102, 0, +1271, 1289, 0, +1353, 1424, 0, +1445, 1559, 0, +1544, 1693, 0, +1650, 1827, 0, +1761, 1960, 0, +1877, 2093, 0, +1996, 2225, 0, +2119, 2358, 0, +2243, 2490, 0, +2370, 2623, 0, +2498, 2755, 0, +2627, 2887, 0, +2757, 3019, 0, +2887, 3152, 0, +3018, 3283, 0, +3149, 3416, 0, +3280, 3548, 0, +3412, 3680, 0, +3543, 3812, 0, +3675, 3944, 0, +3807, 4076, 0, +3939, 4095, 0, +1025, 0, 881, +1020, 0, 852, +1014, 0, 810, +1014, 0, 731, +1014, 0, 598, +1014, 0, 323, +1014, 0, 0, +1014, 568, 0, +1152, 960, 0, +1289, 1221, 0, +1418, 1424, 0, +1499, 1559, 0, +1588, 1693, 0, +1684, 1827, 0, +1789, 1960, 0, +1898, 2093, 0, +2013, 2225, 0, +2132, 2358, 0, +2253, 2490, 0, +2378, 2623, 0, +2504, 2755, 0, +2631, 2887, 0, +2760, 3019, 0, +2890, 3152, 0, +3019, 3283, 0, +3150, 3416, 0, +3281, 3548, 0, +3413, 3680, 0, +3544, 3812, 0, +3676, 3944, 0, +3807, 4076, 0, +3939, 4095, 0, +1160, 0, 987, +1157, 0, 964, +1152, 0, 932, +1152, 0, 873, +1152, 0, 779, +1152, 0, 614, +1152, 0, 214, +1152, 0, 0, +1152, 656, 0, +1289, 1075, 0, +1424, 1343, 0, +1559, 1556, 0, +1640, 1693, 0, +1727, 1827, 0, +1823, 1960, 0, +1926, 2093, 0, +2034, 2225, 0, +2148, 2358, 0, +2266, 2490, 0, +2387, 2623, 0, +2511, 2755, 0, +2637, 2887, 0, +2764, 3019, 0, +2893, 3152, 0, +3022, 3283, 0, +3152, 3416, 0, +3282, 3548, 0, +3414, 3680, 0, +3545, 3812, 0, +3676, 3944, 0, +3808, 4076, 0, +3940, 4095, 0, +1295, 0, 1099, +1292, 0, 1081, +1289, 0, 1056, +1289, 0, 1012, +1289, 0, 945, +1289, 0, 837, +1289, 0, 635, +1289, 0, 9, +1289, 0, 0, +1289, 753, 0, +1424, 1193, 0, +1559, 1468, 0, +1693, 1683, 0, +1779, 1827, 0, +1865, 1960, 0, +1960, 2093, 0, +2061, 2225, 0, +2169, 2358, 0, +2283, 2490, 0, +2400, 2623, 0, +2521, 2755, 0, +2644, 2887, 0, +2770, 3019, 0, +2897, 3152, 0, +3025, 3283, 0, +3154, 3416, 0, +3284, 3548, 0, +3415, 3680, 0, +3546, 3812, 0, +3677, 3944, 0, +3808, 4076, 0, +3940, 4095, 0, +1429, 0, 1215, +1427, 0, 1201, +1424, 0, 1182, +1424, 0, 1149, +1424, 0, 1101, +1424, 0, 1027, +1424, 0, 904, +1424, 0, 662, +1424, 0, 0, +1424, 0, 0, +1424, 856, 0, +1559, 1315, 0, +1693, 1594, 0, +1827, 1812, 0, +1917, 1960, 0, +2002, 2093, 0, +2095, 2225, 0, +2196, 2358, 0, +2304, 2490, 0, +2416, 2623, 0, +2533, 2755, 0, +2654, 2887, 0, +2777, 3019, 0, +2903, 3152, 0, +3029, 3283, 0, +3157, 3416, 0, +3287, 3548, 0, +3417, 3680, 0, +3547, 3812, 0, +3678, 3944, 0, +3809, 4076, 0, +3941, 4095, 0, +1563, 0, 1335, +1561, 0, 1325, +1559, 0, 1310, +1559, 0, 1285, +1559, 0, 1250, +1559, 0, 1198, +1559, 0, 1118, +1559, 0, 981, +1559, 0, 696, +1559, 0, 0, +1559, 0, 0, +1559, 966, 0, +1693, 1439, 0, +1827, 1722, 0, +1960, 1941, 0, +2053, 2093, 0, +2137, 2225, 0, +2230, 2358, 0, +2331, 2490, 0, +2437, 2623, 0, +2550, 2755, 0, +2667, 2887, 0, +2787, 3019, 0, +2910, 3152, 0, +3035, 3283, 0, +3162, 3416, 0, +3290, 3548, 0, +3419, 3680, 0, +3549, 3812, 0, +3679, 3944, 0, +3810, 4076, 0, +3941, 4095, 0, +1696, 0, 1457, +1695, 0, 1450, +1693, 0, 1439, +1693, 0, 1420, +1693, 0, 1394, +1693, 0, 1357, +1693, 0, 1302, +1693, 0, 1216, +1693, 0, 1067, +1693, 0, 736, +1693, 0, 0, +1693, 0, 0, +1693, 1080, 0, +1827, 1565, 0, +1960, 1851, 0, +2093, 2071, 0, +2188, 2225, 0, +2271, 2358, 0, +2364, 2490, 0, +2464, 2623, 0, +2571, 2755, 0, +2683, 2887, 0, +2799, 3019, 0, +2919, 3152, 0, +3042, 3283, 0, +3167, 3416, 0, +3294, 3548, 0, +3422, 3680, 0, +3551, 3812, 0, +3681, 3944, 0, +3811, 4076, 0, +3942, 4095, 0, +1828, 0, 1582, +1828, 0, 1576, +1827, 0, 1568, +1827, 0, 1554, +1827, 0, 1535, +1827, 0, 1508, +1827, 0, 1469, +1827, 0, 1412, +1827, 0, 1321, +1827, 0, 1161, +1827, 0, 786, +1827, 0, 0, +1827, 0, 0, +1827, 1198, 0, +1960, 1692, 0, +2093, 1981, 0, +2225, 2202, 0, +2322, 2358, 0, +2406, 2490, 0, +2498, 2623, 0, +2598, 2755, 0, +2704, 2887, 0, +2816, 3019, 0, +2932, 3152, 0, +3052, 3283, 0, +3175, 3416, 0, +3300, 3548, 0, +3426, 3680, 0, +3554, 3812, 0, +3683, 3944, 0, +3813, 4076, 0, +3944, 4095, 0, +1961, 0, 1709, +1961, 0, 1705, +1960, 0, 1699, +1960, 0, 1688, +1960, 0, 1674, +1960, 0, 1654, +1960, 0, 1626, +1960, 0, 1586, +1960, 0, 1526, +1960, 0, 1431, +1960, 0, 1263, +1960, 0, 844, +1960, 0, 0, +1960, 0, 0, +1960, 1320, 0, +2093, 1821, 0, +2225, 2111, 0, +2358, 2333, 0, +2456, 2490, 0, +2539, 2623, 0, +2631, 2755, 0, +2731, 2887, 0, +2836, 3019, 0, +2948, 3152, 0, +3064, 3283, 0, +3184, 3416, 0, +3307, 3548, 0, +3432, 3680, 0, +3559, 3812, 0, +3687, 3944, 0, +3816, 4076, 0, +3945, 4095, 0, +2094, 0, 1837, +2093, 0, 1834, +2093, 0, 1829, +2093, 0, 1821, +2093, 0, 1811, +2093, 0, 1796, +2093, 0, 1776, +2093, 0, 1748, +2093, 0, 1706, +2093, 0, 1645, +2093, 0, 1547, +2093, 0, 1370, +2093, 0, 913, +2093, 0, 0, +2093, 0, 0, +2093, 1444, 0, +2225, 1950, 0, +2358, 2241, 0, +2490, 2464, 0, +2589, 2623, 0, +2672, 2755, 0, +2764, 2887, 0, +2863, 3019, 0, +2969, 3152, 0, +3081, 3283, 0, +3197, 3416, 0, +3317, 3548, 0, +3439, 3680, 0, +3564, 3812, 0, +3691, 3944, 0, +3819, 4076, 0, +3948, 4095, 0, +2226, 0, 1966, +2226, 0, 1963, +2225, 0, 1960, +2225, 0, 1954, +2225, 0, 1946, +2225, 0, 1936, +2225, 0, 1921, +2225, 0, 1900, +2225, 0, 1871, +2225, 0, 1829, +2225, 0, 1767, +2225, 0, 1666, +2225, 0, 1484, +2225, 0, 990, +2225, 0, 0, +2225, 0, 0, +2225, 1570, 0, +2358, 2080, 0, +2490, 2373, 0, +2623, 2596, 0, +2722, 2755, 0, +2805, 2887, 0, +2896, 3019, 0, +2996, 3152, 0, +3101, 3283, 0, +3213, 3416, 0, +3329, 3548, 0, +3449, 3680, 0, +3572, 3812, 0, +3696, 3944, 0, +3823, 4076, 0, +3951, 4095, 0, +2358, 0, 2096, +2358, 0, 2094, +2358, 0, 2091, +2358, 0, 2087, +2358, 0, 2081, +2358, 0, 2073, +2358, 0, 2062, +2358, 0, 2047, +2358, 0, 2027, +2358, 0, 1997, +2358, 0, 1955, +2358, 0, 1891, +2358, 0, 1788, +2358, 0, 1600, +2358, 0, 1076, +2358, 0, 0, +2358, 0, 0, +2358, 1698, 0, +2490, 2211, 0, +2623, 2504, 0, +2755, 2728, 0, +2855, 2887, 0, +2938, 3019, 0, +3029, 3152, 0, +3128, 3283, 0, +3234, 3416, 0, +3346, 3548, 0, +3462, 3680, 0, +3581, 3812, 0, +3704, 3944, 0, +3828, 4076, 0, +3955, 4095, 0, +2491, 0, 2226, +2491, 0, 2225, +2490, 0, 2223, +2490, 0, 2220, +2490, 0, 2215, +2490, 0, 2209, +2490, 0, 2202, +2490, 0, 2190, +2490, 0, 2175, +2490, 0, 2154, +2490, 0, 2125, +2490, 0, 2082, +2490, 0, 2017, +2490, 0, 1913, +2490, 0, 1722, +2490, 0, 1173, +2490, 0, 0, +2490, 0, 0, +2490, 1826, 0, +2623, 2342, 0, +2755, 2636, 0, +2887, 2859, 0, +2987, 3019, 0, +3070, 3152, 0, +3161, 3283, 0, +3260, 3416, 0, +3366, 3548, 0, +3478, 3680, 0, +3594, 3812, 0, +3713, 3944, 0, +3836, 4076, 0, +3961, 4095, 0, +2623, 0, 2357, +2623, 0, 2356, +2623, 0, 2355, +2623, 0, 2352, +2623, 0, 2349, +2623, 0, 2345, +2623, 0, 2338, +2623, 0, 2331, +2623, 0, 2320, +2623, 0, 2304, +2623, 0, 2283, +2623, 0, 2253, +2623, 0, 2210, +2623, 0, 2144, +2623, 0, 2039, +2623, 0, 1845, +2623, 0, 1275, +2623, 0, 0, +2623, 0, 0, +2623, 1956, 0, +2755, 2474, 0, +2887, 2767, 0, +3019, 2991, 0, +3120, 3152, 0, +3202, 3283, 0, +3294, 3416, 0, +3393, 3548, 0, +3499, 3680, 0, +3610, 3812, 0, +3726, 3944, 0, +3845, 4076, 0, +3968, 4095, 0, +2755, 0, 2488, +2755, 0, 2488, +2755, 0, 2486, +2755, 0, 2485, +2755, 0, 2482, +2755, 0, 2479, +2755, 0, 2475, +2755, 0, 2469, +2755, 0, 2460, +2755, 0, 2449, +2755, 0, 2434, +2755, 0, 2413, +2755, 0, 2383, +2755, 0, 2339, +2755, 0, 2274, +2755, 0, 2167, +2755, 0, 1971, +2755, 0, 1386, +2755, 0, 0, +2755, 0, 0, +2755, 2086, 0, +2887, 2605, 0, +3019, 2898, 0, +3152, 3123, 0, +3252, 3283, 0, +3335, 3416, 0, +3426, 3548, 0, +3525, 3680, 0, +3631, 3812, 0, +3742, 3944, 0, +3858, 4076, 0, +3978, 4095, 0, +2887, 0, 2620, +2887, 0, 2619, +2887, 0, 2618, +2887, 0, 2617, +2887, 0, 2615, +2887, 0, 2613, +2887, 0, 2609, +2887, 0, 2605, +2887, 0, 2599, +2887, 0, 2591, +2887, 0, 2580, +2887, 0, 2564, +2887, 0, 2543, +2887, 0, 2513, +2887, 0, 2469, +2887, 0, 2403, +2887, 0, 2296, +2887, 0, 2098, +2887, 0, 1497, +2887, 0, 0, +2887, 0, 0, +2887, 2217, 0, +3019, 2736, 0, +3152, 3031, 0, +3283, 3255, 0, +3384, 3416, 0, +3467, 3548, 0, +3558, 3680, 0, +3657, 3812, 0, +3763, 3944, 0, +3874, 4076, 0, +3990, 4095, 0, +3019, 0, 2751, +3019, 0, 2751, +3019, 0, 2750, +3019, 0, 2749, +3019, 0, 2747, +3019, 0, 2746, +3019, 0, 2743, +3019, 0, 2740, +3019, 0, 2735, +3019, 0, 2729, +3019, 0, 2721, +3019, 0, 2710, +3019, 0, 2695, +3019, 0, 2673, +3019, 0, 2643, +3019, 0, 2599, +3019, 0, 2533, +3019, 0, 2426, +3019, 0, 2225, +3019, 0, 1613, +3019, 0, 0, +3019, 0, 0, +3019, 2347, 0, +3152, 2869, 0, +3283, 3163, 0, +3416, 3387, 0, +3516, 3548, 0, +3599, 3680, 0, +3690, 3812, 0, +3790, 3944, 0, +3895, 4076, 0, +4006, 4095, 0, +3152, 0, 2883, +3152, 0, 2883, +3152, 0, 2882, +3152, 0, 2881, +3152, 0, 2880, +3152, 0, 2879, +3152, 0, 2877, +3152, 0, 2875, +3152, 0, 2871, +3152, 0, 2867, +3152, 0, 2861, +3152, 0, 2853, +3152, 0, 2842, +3152, 0, 2826, +3152, 0, 2805, +3152, 0, 2774, +3152, 0, 2730, +3152, 0, 2664, +3152, 0, 2556, +3152, 0, 2355, +3152, 0, 1735, +3152, 0, 0, +3152, 0, 0, +3152, 2479, 0, +3283, 2999, 0, +3416, 3294, 0, +3548, 3519, 0, +3649, 3680, 0, +3731, 3812, 0, +3823, 3944, 0, +3921, 4076, 0, +4027, 4095, 0, +3284, 0, 3014, +3283, 0, 3014, +3283, 0, 3014, +3283, 0, 3013, +3283, 0, 3013, +3283, 0, 3011, +3283, 0, 3010, +3283, 0, 3008, +3283, 0, 3006, +3283, 0, 3002, +3283, 0, 2998, +3283, 0, 2992, +3283, 0, 2984, +3283, 0, 2973, +3283, 0, 2957, +3283, 0, 2936, +3283, 0, 2905, +3283, 0, 2861, +3283, 0, 2794, +3283, 0, 2686, +3283, 0, 2484, +3283, 0, 1856, +3283, 0, 0, +3283, 0, 0, +3283, 2610, 0, +3416, 3132, 0, +3548, 3427, 0, +3680, 3651, 0, +3781, 3812, 0, +3863, 3944, 0, +3955, 4076, 0, +4054, 4095, 0, +3416, 0, 3147, +3416, 0, 3146, +3416, 0, 3146, +3416, 0, 3146, +3416, 0, 3145, +3416, 0, 3144, +3416, 0, 3143, +3416, 0, 3142, +3416, 0, 3140, +3416, 0, 3138, +3416, 0, 3134, +3416, 0, 3130, +3416, 0, 3124, +3416, 0, 3115, +3416, 0, 3104, +3416, 0, 3089, +3416, 0, 3067, +3416, 0, 3037, +3416, 0, 2992, +3416, 0, 2926, +3416, 0, 2817, +3416, 0, 2615, +3416, 0, 1986, +3416, 0, 0, +3416, 0, 0, +3416, 2742, 0, +3548, 3264, 0, +3680, 3559, 0, +3812, 3783, 0, +3913, 3944, 0, +3996, 4076, 0, +4087, 4095, 0, +3548, 0, 3279, +3548, 0, 3278, +3548, 0, 3278, +3548, 0, 3278, +3548, 0, 3277, +3548, 0, 3277, +3548, 0, 3276, +3548, 0, 3275, +3548, 0, 3274, +3548, 0, 3272, +3548, 0, 3269, +3548, 0, 3266, +3548, 0, 3261, +3548, 0, 3256, +3548, 0, 3247, +3548, 0, 3236, +3548, 0, 3221, +3548, 0, 3199, +3548, 0, 3168, +3548, 0, 3124, +3548, 0, 3057, +3548, 0, 2949, +3548, 0, 2746, +3548, 0, 2111, +3548, 0, 0, +3548, 0, 0, +3548, 2873, 0, +3680, 3396, 0, +3812, 3691, 0, +3944, 3915, 0, +4045, 4076, 0, +4095, 4095, 0, +3680, 0, 3410, +3680, 0, 3410, +3680, 0, 3410, +3680, 0, 3410, +3680, 0, 3410, +3680, 0, 3409, +3680, 0, 3409, +3680, 0, 3408, +3680, 0, 3407, +3680, 0, 3405, +3680, 0, 3404, +3680, 0, 3401, +3680, 0, 3398, +3680, 0, 3393, +3680, 0, 3387, +3680, 0, 3379, +3680, 0, 3368, +3680, 0, 3353, +3680, 0, 3331, +3680, 0, 3300, +3680, 0, 3256, +3680, 0, 3189, +3680, 0, 3081, +3680, 0, 2877, +3680, 0, 2242, +3680, 0, 0, +3680, 0, 0, +3680, 3005, 0, +3812, 3528, 0, +3944, 3822, 0, +4076, 4047, 0, +4095, 4095, 0, +3812, 0, 3543, +3812, 0, 3543, +3812, 0, 3542, +3812, 0, 3542, +3812, 0, 3542, +3812, 0, 3541, +3812, 0, 3541, +3812, 0, 3541, +3812, 0, 3540, +3812, 0, 3539, +3812, 0, 3537, +3812, 0, 3536, +3812, 0, 3533, +3812, 0, 3530, +3812, 0, 3525, +3812, 0, 3519, +3812, 0, 3511, +3812, 0, 3500, +3812, 0, 3484, +3812, 0, 3463, +3812, 0, 3432, +3812, 0, 3388, +3812, 0, 3321, +3812, 0, 3212, +3812, 0, 3009, +3812, 0, 2371, +3812, 0, 0, +3812, 0, 0, +3812, 3137, 0, +3944, 3660, 0, +4076, 3954, 0, +4095, 4095, 0, +3944, 0, 3674, +3944, 0, 3674, +3944, 0, 3674, +3944, 0, 3674, +3944, 0, 3674, +3944, 0, 3674, +3944, 0, 3673, +3944, 0, 3673, +3944, 0, 3673, +3944, 0, 3672, +3944, 0, 3671, +3944, 0, 3669, +3944, 0, 3668, +3944, 0, 3665, +3944, 0, 3662, +3944, 0, 3657, +3944, 0, 3651, +3944, 0, 3643, +3944, 0, 3632, +3944, 0, 3616, +3944, 0, 3595, +3944, 0, 3564, +3944, 0, 3520, +3944, 0, 3453, +3944, 0, 3344, +3944, 0, 3140, +3944, 0, 2500, +3944, 0, 0, +3944, 0, 0, +3944, 3269, 0, +4076, 3792, 0, +4095, 4087, 0, +4076, 0, 3806, +4076, 0, 3806, +4076, 0, 3806, +4076, 0, 3806, +4076, 0, 3806, +4076, 0, 3806, +4076, 0, 3805, +4076, 0, 3805, +4076, 0, 3805, +4076, 0, 3804, +4076, 0, 3803, +4076, 0, 3803, +4076, 0, 3801, +4076, 0, 3799, +4076, 0, 3797, +4076, 0, 3793, +4076, 0, 3789, +4076, 0, 3783, +4076, 0, 3775, +4076, 0, 3763, +4076, 0, 3748, +4076, 0, 3726, +4076, 0, 3696, +4076, 0, 3651, +4076, 0, 3585, +4076, 0, 3476, +4076, 0, 3272, +4076, 0, 2628, +4076, 0, 0, +4076, 0, 0, +4076, 3401, 0, +4095, 3924, 0, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3938, +4095, 0, 3938, +4095, 0, 3938, +4095, 0, 3938, +4095, 0, 3937, +4095, 0, 3937, +4095, 0, 3937, +4095, 0, 3936, +4095, 0, 3935, +4095, 0, 3933, +4095, 0, 3932, +4095, 0, 3929, +4095, 0, 3926, +4095, 0, 3921, +4095, 0, 3915, +4095, 0, 3907, +4095, 0, 3896, +4095, 0, 3880, +4095, 0, 3859, +4095, 0, 3828, +4095, 0, 3784, +4095, 0, 3717, +4095, 0, 3608, +4095, 0, 3404, +4095, 0, 2762, +4095, 0, 0, +4095, 0, 0, +4095, 3533, 0, +0, 312, 466, +0, 419, 466, +0, 466, 388, +0, 466, 154, +0, 609, 0, +59, 750, 0, +350, 888, 0, +573, 1025, 0, +762, 1160, 0, +934, 1295, 0, +1092, 1429, 0, +1244, 1563, 0, +1390, 1696, 0, +1532, 1828, 0, +1672, 1961, 0, +1809, 2094, 0, +1945, 2226, 0, +2080, 2358, 0, +2215, 2491, 0, +2348, 2623, 0, +2482, 2755, 0, +2615, 2887, 0, +2747, 3019, 0, +2880, 3152, 0, +3012, 3284, 0, +3145, 3416, 0, +3277, 3548, 0, +3410, 3680, 0, +3542, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3938, 4095, 0, +0, 171, 466, +15, 333, 450, +15, 450, 432, +15, 450, 225, +0, 598, 0, +258, 741, 0, +466, 882, 0, +647, 1020, 0, +813, 1157, 0, +968, 1292, 0, +1118, 1427, 0, +1262, 1561, 0, +1403, 1695, 0, +1542, 1828, 0, +1679, 1961, 0, +1814, 2093, 0, +1949, 2226, 0, +2083, 2358, 0, +2217, 2491, 0, +2350, 2623, 0, +2483, 2755, 0, +2616, 2887, 0, +2748, 3019, 0, +2881, 3152, 0, +3013, 3283, 0, +3145, 3416, 0, +3278, 3548, 0, +3410, 3680, 0, +3542, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3938, 4095, 0, +0, 0, 466, +15, 145, 450, +218, 361, 427, +218, 427, 306, +277, 582, 148, +435, 730, 34, +585, 873, 0, +731, 1014, 0, +873, 1152, 0, +1012, 1289, 0, +1149, 1424, 0, +1285, 1559, 0, +1420, 1693, 0, +1554, 1827, 0, +1688, 1960, 0, +1821, 2093, 0, +1954, 2225, 0, +2087, 2358, 0, +2220, 2490, 0, +2352, 2623, 0, +2485, 2755, 0, +2617, 2887, 0, +2749, 3019, 0, +2881, 3152, 0, +3013, 3283, 0, +3146, 3416, 0, +3278, 3548, 0, +3410, 3680, 0, +3542, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3939, 4095, 0, +154, 0, 466, +225, 15, 450, +306, 218, 427, +396, 396, 396, +494, 560, 350, +598, 714, 280, +708, 862, 166, +823, 1005, 0, +942, 1146, 0, +1064, 1284, 0, +1188, 1421, 0, +1315, 1557, 0, +1442, 1691, 0, +1571, 1825, 0, +1700, 1959, 0, +1830, 2092, 0, +1961, 2225, 0, +2092, 2357, 0, +2223, 2490, 0, +2355, 2622, 0, +2487, 2755, 0, +2619, 2887, 0, +2750, 3019, 0, +2882, 3151, 0, +3014, 3283, 0, +3146, 3416, 0, +3278, 3548, 0, +3410, 3680, 0, +3542, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3939, 4095, 0, +485, 0, 609, +520, 0, 598, +564, 148, 582, +560, 350, 494, +560, 438, 350, +714, 696, 280, +815, 862, 166, +908, 1005, 0, +1009, 1146, 0, +1116, 1284, 0, +1228, 1421, 0, +1345, 1557, 0, +1465, 1691, 0, +1588, 1825, 0, +1714, 1959, 0, +1841, 2092, 0, +1969, 2225, 0, +2098, 2357, 0, +2228, 2490, 0, +2358, 2622, 0, +2489, 2755, 0, +2620, 2887, 0, +2751, 3019, 0, +2883, 3151, 0, +3015, 3283, 0, +3147, 3416, 0, +3279, 3548, 0, +3411, 3680, 0, +3543, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3939, 4095, 0, +723, 0, 750, +741, 0, 738, +730, 34, 683, +714, 280, 598, +714, 280, 409, +714, 490, 280, +862, 784, 166, +1002, 1005, 0, +1086, 1146, 0, +1177, 1284, 0, +1277, 1421, 0, +1384, 1557, 0, +1495, 1691, 0, +1611, 1825, 0, +1731, 1959, 0, +1854, 2092, 0, +1979, 2225, 0, +2105, 2357, 0, +2234, 2490, 0, +2362, 2622, 0, +2492, 2755, 0, +2623, 2887, 0, +2753, 3019, 0, +2885, 3151, 0, +3016, 3283, 0, +3147, 3416, 0, +3279, 3548, 0, +3411, 3680, 0, +3543, 3812, 0, +3675, 3944, 0, +3807, 4076, 0, +3939, 4095, 0, +888, 0, 852, +882, 0, 822, +873, 0, 776, +862, 166, 708, +862, 166, 567, +862, 166, 264, +862, 550, 166, +1005, 881, 0, +1146, 1119, 0, +1249, 1284, 0, +1335, 1421, 0, +1430, 1557, 0, +1532, 1691, 0, +1640, 1825, 0, +1754, 1959, 0, +1871, 2092, 0, +1992, 2225, 0, +2115, 2357, 0, +2241, 2490, 0, +2368, 2622, 0, +2497, 2755, 0, +2626, 2887, 0, +2756, 3019, 0, +2886, 3151, 0, +3017, 3283, 0, +3148, 3416, 0, +3280, 3548, 0, +3412, 3680, 0, +3543, 3812, 0, +3675, 3944, 0, +3807, 4076, 0, +3939, 4095, 0, +1025, 0, 939, +1020, 0, 914, +1014, 0, 877, +1005, 0, 823, +1005, 0, 717, +1005, 0, 523, +1005, 0, 0, +1005, 620, 0, +1146, 983, 0, +1284, 1235, 0, +1403, 1421, 0, +1486, 1557, 0, +1577, 1691, 0, +1676, 1825, 0, +1781, 1959, 0, +1893, 2092, 0, +2009, 2225, 0, +2128, 2357, 0, +2251, 2490, 0, +2375, 2622, 0, +2502, 2755, 0, +2630, 2887, 0, +2759, 3019, 0, +2889, 3151, 0, +3019, 3283, 0, +3150, 3416, 0, +3281, 3548, 0, +3412, 3680, 0, +3544, 3812, 0, +3676, 3944, 0, +3807, 4076, 0, +3939, 4095, 0, +1160, 0, 1033, +1157, 0, 1013, +1152, 0, 984, +1146, 0, 942, +1146, 0, 863, +1146, 0, 730, +1146, 0, 455, +1146, 0, 0, +1146, 700, 0, +1284, 1093, 0, +1421, 1353, 0, +1551, 1557, 0, +1631, 1691, 0, +1720, 1825, 0, +1817, 1959, 0, +1920, 2092, 0, +2030, 2225, 0, +2145, 2357, 0, +2264, 2490, 0, +2385, 2622, 0, +2510, 2755, 0, +2636, 2887, 0, +2763, 3019, 0, +2892, 3151, 0, +3021, 3283, 0, +3151, 3416, 0, +3282, 3548, 0, +3413, 3680, 0, +3545, 3812, 0, +3676, 3944, 0, +3808, 4076, 0, +3940, 4095, 0, +1295, 0, 1135, +1292, 0, 1119, +1289, 0, 1096, +1284, 0, 1064, +1284, 0, 1005, +1284, 0, 911, +1284, 0, 746, +1284, 0, 346, +1284, 0, 0, +1284, 788, 0, +1421, 1207, 0, +1557, 1476, 0, +1691, 1688, 0, +1772, 1825, 0, +1860, 1959, 0, +1955, 2092, 0, +2058, 2225, 0, +2166, 2357, 0, +2280, 2490, 0, +2398, 2622, 0, +2520, 2755, 0, +2643, 2887, 0, +2769, 3019, 0, +2896, 3151, 0, +3025, 3283, 0, +3154, 3416, 0, +3284, 3548, 0, +3415, 3680, 0, +3545, 3812, 0, +3677, 3944, 0, +3808, 4076, 0, +3940, 4095, 0, +1429, 0, 1244, +1427, 0, 1231, +1424, 0, 1213, +1421, 0, 1188, +1421, 0, 1144, +1421, 0, 1077, +1421, 0, 969, +1421, 0, 767, +1421, 0, 141, +1421, 0, 0, +1421, 885, 0, +1557, 1326, 0, +1691, 1600, 0, +1825, 1816, 0, +1911, 1959, 0, +1997, 2092, 0, +2092, 2225, 0, +2193, 2357, 0, +2302, 2490, 0, +2414, 2622, 0, +2532, 2755, 0, +2653, 2887, 0, +2776, 3019, 0, +2902, 3151, 0, +3029, 3283, 0, +3157, 3416, 0, +3286, 3548, 0, +3416, 3680, 0, +3547, 3812, 0, +3678, 3944, 0, +3809, 4076, 0, +3941, 4095, 0, +1563, 0, 1357, +1561, 0, 1347, +1559, 0, 1333, +1557, 0, 1315, +1557, 0, 1281, +1557, 0, 1233, +1557, 0, 1159, +1557, 0, 1037, +1557, 0, 794, +1557, 0, 0, +1557, 0, 0, +1557, 988, 0, +1691, 1447, 0, +1825, 1727, 0, +1959, 1944, 0, +2049, 2092, 0, +2134, 2225, 0, +2228, 2357, 0, +2329, 2490, 0, +2436, 2622, 0, +2549, 2755, 0, +2666, 2887, 0, +2786, 3019, 0, +2909, 3151, 0, +3034, 3283, 0, +3161, 3416, 0, +3290, 3548, 0, +3419, 3680, 0, +3549, 3812, 0, +3679, 3944, 0, +3810, 4076, 0, +3941, 4095, 0, +1696, 0, 1475, +1695, 0, 1467, +1693, 0, 1456, +1691, 0, 1442, +1691, 0, 1417, +1691, 0, 1382, +1691, 0, 1330, +1691, 0, 1249, +1691, 0, 1113, +1691, 0, 827, +1691, 0, 0, +1691, 0, 0, +1691, 1098, 0, +1825, 1571, 0, +1959, 1854, 0, +2092, 2073, 0, +2185, 2225, 0, +2269, 2357, 0, +2362, 2490, 0, +2463, 2622, 0, +2570, 2755, 0, +2682, 2887, 0, +2798, 3019, 0, +2919, 3151, 0, +3042, 3283, 0, +3167, 3416, 0, +3294, 3548, 0, +3422, 3680, 0, +3551, 3812, 0, +3681, 3944, 0, +3811, 4076, 0, +3942, 4095, 0, +1828, 0, 1596, +1828, 0, 1590, +1827, 0, 1582, +1825, 0, 1571, +1825, 0, 1552, +1825, 0, 1526, +1825, 0, 1489, +1825, 0, 1434, +1825, 0, 1348, +1825, 0, 1199, +1825, 0, 869, +1825, 0, 0, +1825, 0, 0, +1825, 1212, 0, +1959, 1697, 0, +2092, 1983, 0, +2225, 2203, 0, +2320, 2357, 0, +2404, 2490, 0, +2496, 2622, 0, +2596, 2755, 0, +2703, 2887, 0, +2815, 3019, 0, +2932, 3151, 0, +3051, 3283, 0, +3174, 3416, 0, +3299, 3548, 0, +3426, 3680, 0, +3554, 3812, 0, +3683, 3944, 0, +3813, 4076, 0, +3944, 4095, 0, +1961, 0, 1719, +1961, 0, 1715, +1960, 0, 1708, +1959, 0, 1700, +1959, 0, 1686, +1959, 0, 1667, +1959, 0, 1640, +1959, 0, 1601, +1959, 0, 1544, +1959, 0, 1453, +1959, 0, 1294, +1959, 0, 917, +1959, 0, 0, +1959, 0, 0, +1959, 1331, 0, +2092, 1824, 0, +2225, 2112, 0, +2357, 2334, 0, +2454, 2490, 0, +2538, 2622, 0, +2630, 2755, 0, +2730, 2887, 0, +2836, 3019, 0, +2948, 3151, 0, +3064, 3283, 0, +3184, 3416, 0, +3307, 3548, 0, +3432, 3680, 0, +3558, 3812, 0, +3686, 3944, 0, +3815, 4076, 0, +3945, 4095, 0, +2094, 0, 1845, +2093, 0, 1841, +2093, 0, 1837, +2092, 0, 1830, +2092, 0, 1820, +2092, 0, 1806, +2092, 0, 1786, +2092, 0, 1758, +2092, 0, 1718, +2092, 0, 1658, +2092, 0, 1564, +2092, 0, 1394, +2092, 0, 977, +2092, 0, 0, +2092, 0, 0, +2092, 1452, 0, +2225, 1953, 0, +2357, 2243, 0, +2490, 2465, 0, +2588, 2622, 0, +2671, 2755, 0, +2763, 2887, 0, +2863, 3019, 0, +2969, 3151, 0, +3080, 3283, 0, +3196, 3416, 0, +3316, 3548, 0, +3439, 3680, 0, +3564, 3812, 0, +3691, 3944, 0, +3818, 4076, 0, +3948, 4095, 0, +2226, 0, 1972, +2226, 0, 1969, +2225, 0, 1966, +2225, 0, 1961, +2225, 0, 1953, +2225, 0, 1943, +2225, 0, 1928, +2225, 0, 1908, +2225, 0, 1880, +2225, 0, 1839, +2225, 0, 1777, +2225, 0, 1679, +2225, 0, 1503, +2225, 0, 1044, +2225, 0, 0, +2225, 0, 0, +2225, 1576, 0, +2357, 2082, 0, +2490, 2374, 0, +2622, 2596, 0, +2721, 2755, 0, +2804, 2887, 0, +2896, 3019, 0, +2995, 3151, 0, +3101, 3283, 0, +3213, 3416, 0, +3329, 3548, 0, +3449, 3680, 0, +3571, 3812, 0, +3696, 3944, 0, +3823, 4076, 0, +3951, 4095, 0, +2358, 0, 2100, +2358, 0, 2098, +2358, 0, 2096, +2357, 0, 2092, +2357, 0, 2086, +2357, 0, 2078, +2357, 0, 2068, +2357, 0, 2053, +2357, 0, 2032, +2357, 0, 2004, +2357, 0, 1962, +2357, 0, 1899, +2357, 0, 1798, +2357, 0, 1615, +2357, 0, 1122, +2357, 0, 0, +2357, 0, 0, +2357, 1702, 0, +2490, 2213, 0, +2622, 2505, 0, +2755, 2728, 0, +2854, 2887, 0, +2937, 3019, 0, +3029, 3151, 0, +3128, 3283, 0, +3234, 3416, 0, +3345, 3548, 0, +3461, 3680, 0, +3581, 3812, 0, +3703, 3944, 0, +3828, 4076, 0, +3955, 4095, 0, +2491, 0, 2230, +2491, 0, 2228, +2490, 0, 2226, +2490, 0, 2223, +2490, 0, 2219, +2490, 0, 2213, +2490, 0, 2206, +2490, 0, 2195, +2490, 0, 2180, +2490, 0, 2159, +2490, 0, 2129, +2490, 0, 2087, +2490, 0, 2023, +2490, 0, 1920, +2490, 0, 1733, +2490, 0, 1210, +2490, 0, 0, +2490, 0, 0, +2490, 1830, 0, +2622, 2343, 0, +2755, 2636, 0, +2887, 2860, 0, +2987, 3019, 0, +3070, 3151, 0, +3161, 3283, 0, +3260, 3416, 0, +3366, 3548, 0, +3478, 3680, 0, +3594, 3812, 0, +3713, 3944, 0, +3836, 4076, 0, +3961, 4095, 0, +2623, 0, 2359, +2623, 0, 2358, +2623, 0, 2357, +2622, 0, 2355, +2622, 0, 2352, +2622, 0, 2347, +2622, 0, 2341, +2622, 0, 2334, +2622, 0, 2323, +2622, 0, 2308, +2622, 0, 2287, +2622, 0, 2256, +2622, 0, 2214, +2622, 0, 2149, +2622, 0, 2045, +2622, 0, 1853, +2622, 0, 1304, +2622, 0, 0, +2622, 0, 0, +2622, 1958, 0, +2755, 2475, 0, +2887, 2768, 0, +3019, 2991, 0, +3119, 3151, 0, +3202, 3283, 0, +3293, 3416, 0, +3393, 3548, 0, +3499, 3680, 0, +3610, 3812, 0, +3726, 3944, 0, +3845, 4076, 0, +3968, 4095, 0, +2755, 0, 2490, +2755, 0, 2489, +2755, 0, 2488, +2755, 0, 2487, +2755, 0, 2484, +2755, 0, 2481, +2755, 0, 2477, +2755, 0, 2471, +2755, 0, 2463, +2755, 0, 2452, +2755, 0, 2436, +2755, 0, 2415, +2755, 0, 2386, +2755, 0, 2342, +2755, 0, 2277, +2755, 0, 2172, +2755, 0, 1977, +2755, 0, 1409, +2755, 0, 0, +2755, 0, 0, +2755, 2088, 0, +2887, 2605, 0, +3019, 2899, 0, +3151, 3123, 0, +3252, 3283, 0, +3335, 3416, 0, +3426, 3548, 0, +3525, 3680, 0, +3631, 3812, 0, +3742, 3944, 0, +3858, 4076, 0, +3978, 4095, 0, +2887, 0, 2621, +2887, 0, 2620, +2887, 0, 2620, +2887, 0, 2619, +2887, 0, 2617, +2887, 0, 2614, +2887, 0, 2611, +2887, 0, 2607, +2887, 0, 2601, +2887, 0, 2592, +2887, 0, 2581, +2887, 0, 2566, +2887, 0, 2545, +2887, 0, 2515, +2887, 0, 2471, +2887, 0, 2406, +2887, 0, 2299, +2887, 0, 2103, +2887, 0, 1516, +2887, 0, 0, +2887, 0, 0, +2887, 2218, 0, +3019, 2736, 0, +3151, 3031, 0, +3283, 3255, 0, +3384, 3416, 0, +3467, 3548, 0, +3558, 3680, 0, +3657, 3812, 0, +3763, 3944, 0, +3874, 4076, 0, +3990, 4095, 0, +3019, 0, 2752, +3019, 0, 2752, +3019, 0, 2751, +3019, 0, 2750, +3019, 0, 2749, +3019, 0, 2747, +3019, 0, 2745, +3019, 0, 2741, +3019, 0, 2737, +3019, 0, 2731, +3019, 0, 2723, +3019, 0, 2712, +3019, 0, 2696, +3019, 0, 2675, +3019, 0, 2645, +3019, 0, 2601, +3019, 0, 2535, +3019, 0, 2428, +3019, 0, 2229, +3019, 0, 1628, +3019, 0, 0, +3019, 0, 0, +3019, 2348, 0, +3151, 2869, 0, +3283, 3163, 0, +3416, 3387, 0, +3516, 3548, 0, +3599, 3680, 0, +3690, 3812, 0, +3790, 3944, 0, +3895, 4076, 0, +4006, 4095, 0, +3152, 0, 2884, +3152, 0, 2883, +3152, 0, 2883, +3151, 0, 2882, +3151, 0, 2881, +3151, 0, 2880, +3151, 0, 2878, +3151, 0, 2876, +3151, 0, 2872, +3151, 0, 2868, +3151, 0, 2862, +3151, 0, 2854, +3151, 0, 2842, +3151, 0, 2827, +3151, 0, 2806, +3151, 0, 2775, +3151, 0, 2732, +3151, 0, 2665, +3151, 0, 2558, +3151, 0, 2358, +3151, 0, 1746, +3151, 0, 0, +3151, 0, 0, +3151, 2480, 0, +3283, 2999, 0, +3416, 3294, 0, +3548, 3519, 0, +3649, 3680, 0, +3731, 3812, 0, +3822, 3944, 0, +3921, 4076, 0, +4027, 4095, 0, +3284, 0, 3015, +3283, 0, 3015, +3283, 0, 3014, +3283, 0, 3014, +3283, 0, 3013, +3283, 0, 3012, +3283, 0, 3011, +3283, 0, 3009, +3283, 0, 3007, +3283, 0, 3003, +3283, 0, 2999, +3283, 0, 2993, +3283, 0, 2985, +3283, 0, 2973, +3283, 0, 2958, +3283, 0, 2936, +3283, 0, 2906, +3283, 0, 2862, +3283, 0, 2795, +3283, 0, 2688, +3283, 0, 2486, +3283, 0, 1864, +3283, 0, 0, +3283, 0, 0, +3283, 2611, 0, +3416, 3132, 0, +3548, 3427, 0, +3680, 3651, 0, +3781, 3812, 0, +3863, 3944, 0, +3955, 4076, 0, +4054, 4095, 0, +3416, 0, 3147, +3416, 0, 3147, +3416, 0, 3147, +3416, 0, 3146, +3416, 0, 3146, +3416, 0, 3145, +3416, 0, 3144, +3416, 0, 3142, +3416, 0, 3141, +3416, 0, 3138, +3416, 0, 3135, +3416, 0, 3130, +3416, 0, 3124, +3416, 0, 3116, +3416, 0, 3105, +3416, 0, 3089, +3416, 0, 3068, +3416, 0, 3038, +3416, 0, 2993, +3416, 0, 2927, +3416, 0, 2818, +3416, 0, 2617, +3416, 0, 1992, +3416, 0, 0, +3416, 0, 0, +3416, 2742, 0, +3548, 3264, 0, +3680, 3559, 0, +3812, 3783, 0, +3913, 3944, 0, +3995, 4076, 0, +4087, 4095, 0, +3548, 0, 3279, +3548, 0, 3279, +3548, 0, 3279, +3548, 0, 3278, +3548, 0, 3278, +3548, 0, 3277, +3548, 0, 3277, +3548, 0, 3275, +3548, 0, 3274, +3548, 0, 3272, +3548, 0, 3270, +3548, 0, 3267, +3548, 0, 3262, +3548, 0, 3256, +3548, 0, 3248, +3548, 0, 3237, +3548, 0, 3221, +3548, 0, 3200, +3548, 0, 3169, +3548, 0, 3125, +3548, 0, 3058, +3548, 0, 2950, +3548, 0, 2747, +3548, 0, 2115, +3548, 0, 0, +3548, 0, 0, +3548, 2874, 0, +3680, 3396, 0, +3812, 3691, 0, +3944, 3915, 0, +4045, 4076, 0, +4095, 4095, 0, +3680, 0, 3411, +3680, 0, 3411, +3680, 0, 3410, +3680, 0, 3410, +3680, 0, 3410, +3680, 0, 3410, +3680, 0, 3409, +3680, 0, 3408, +3680, 0, 3407, +3680, 0, 3406, +3680, 0, 3404, +3680, 0, 3401, +3680, 0, 3398, +3680, 0, 3394, +3680, 0, 3388, +3680, 0, 3379, +3680, 0, 3368, +3680, 0, 3353, +3680, 0, 3331, +3680, 0, 3301, +3680, 0, 3256, +3680, 0, 3189, +3680, 0, 3081, +3680, 0, 2878, +3680, 0, 2246, +3680, 0, 0, +3680, 0, 0, +3680, 3006, 0, +3812, 3528, 0, +3944, 3823, 0, +4076, 4047, 0, +4095, 4095, 0, +3812, 0, 3543, +3812, 0, 3543, +3812, 0, 3543, +3812, 0, 3542, +3812, 0, 3542, +3812, 0, 3542, +3812, 0, 3541, +3812, 0, 3541, +3812, 0, 3540, +3812, 0, 3539, +3812, 0, 3538, +3812, 0, 3536, +3812, 0, 3533, +3812, 0, 3530, +3812, 0, 3526, +3812, 0, 3520, +3812, 0, 3511, +3812, 0, 3500, +3812, 0, 3485, +3812, 0, 3463, +3812, 0, 3432, +3812, 0, 3388, +3812, 0, 3321, +3812, 0, 3213, +3812, 0, 3010, +3812, 0, 2374, +3812, 0, 0, +3812, 0, 0, +3812, 3138, 0, +3944, 3660, 0, +4076, 3954, 0, +4095, 4095, 0, +3944, 0, 3674, +3944, 0, 3674, +3944, 0, 3674, +3944, 0, 3674, +3944, 0, 3674, +3944, 0, 3674, +3944, 0, 3674, +3944, 0, 3673, +3944, 0, 3673, +3944, 0, 3672, +3944, 0, 3671, +3944, 0, 3669, +3944, 0, 3668, +3944, 0, 3665, +3944, 0, 3662, +3944, 0, 3657, +3944, 0, 3651, +3944, 0, 3643, +3944, 0, 3632, +3944, 0, 3616, +3944, 0, 3595, +3944, 0, 3564, +3944, 0, 3520, +3944, 0, 3453, +3944, 0, 3344, +3944, 0, 3141, +3944, 0, 2502, +3944, 0, 0, +3944, 0, 0, +3944, 3269, 0, +4076, 3792, 0, +4095, 4087, 0, +4076, 0, 3806, +4076, 0, 3806, +4076, 0, 3806, +4076, 0, 3806, +4076, 0, 3806, +4076, 0, 3806, +4076, 0, 3806, +4076, 0, 3805, +4076, 0, 3805, +4076, 0, 3805, +4076, 0, 3804, +4076, 0, 3803, +4076, 0, 3801, +4076, 0, 3799, +4076, 0, 3797, +4076, 0, 3794, +4076, 0, 3789, +4076, 0, 3783, +4076, 0, 3775, +4076, 0, 3764, +4076, 0, 3748, +4076, 0, 3727, +4076, 0, 3696, +4076, 0, 3652, +4076, 0, 3585, +4076, 0, 3476, +4076, 0, 3272, +4076, 0, 2630, +4076, 0, 0, +4076, 0, 0, +4076, 3401, 0, +4095, 3924, 0, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3938, +4095, 0, 3938, +4095, 0, 3938, +4095, 0, 3938, +4095, 0, 3937, +4095, 0, 3937, +4095, 0, 3936, +4095, 0, 3935, +4095, 0, 3933, +4095, 0, 3932, +4095, 0, 3929, +4095, 0, 3926, +4095, 0, 3921, +4095, 0, 3915, +4095, 0, 3907, +4095, 0, 3896, +4095, 0, 3880, +4095, 0, 3859, +4095, 0, 3828, +4095, 0, 3784, +4095, 0, 3717, +4095, 0, 3608, +4095, 0, 3405, +4095, 0, 2764, +4095, 0, 0, +4095, 0, 0, +4095, 3534, 0, +0, 427, 609, +0, 512, 609, +0, 606, 609, +0, 609, 485, +0, 609, 224, +0, 750, 0, +0, 888, 0, +371, 1025, 0, +640, 1160, 0, +853, 1295, 0, +1037, 1429, 0, +1205, 1563, 0, +1362, 1696, 0, +1512, 1828, 0, +1657, 1961, 0, +1798, 2094, 0, +1937, 2226, 0, +2074, 2358, 0, +2210, 2491, 0, +2345, 2623, 0, +2479, 2755, 0, +2613, 2887, 0, +2746, 3019, 0, +2879, 3152, 0, +3012, 3284, 0, +3144, 3416, 0, +3277, 3548, 0, +3409, 3680, 0, +3541, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3938, 4095, 0, +0, 322, 609, +0, 444, 598, +0, 551, 598, +0, 598, 520, +0, 598, 286, +0, 741, 0, +190, 882, 0, +482, 1020, 0, +705, 1157, 0, +894, 1292, 0, +1065, 1427, 0, +1225, 1561, 0, +1376, 1695, 0, +1522, 1828, 0, +1664, 1961, 0, +1804, 2093, 0, +1941, 2226, 0, +2077, 2358, 0, +2212, 2491, 0, +2347, 2623, 0, +2481, 2755, 0, +2614, 2887, 0, +2747, 3019, 0, +2880, 3152, 0, +3012, 3283, 0, +3145, 3416, 0, +3277, 3548, 0, +3409, 3680, 0, +3542, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3938, 4095, 0, +0, 127, 609, +0, 303, 598, +148, 466, 582, +148, 582, 564, +148, 582, 357, +132, 730, 34, +390, 873, 0, +598, 1014, 0, +779, 1152, 0, +945, 1289, 0, +1101, 1424, 0, +1250, 1559, 0, +1394, 1693, 0, +1535, 1827, 0, +1674, 1960, 0, +1811, 2093, 0, +1946, 2225, 0, +2081, 2358, 0, +2215, 2490, 0, +2349, 2623, 0, +2482, 2755, 0, +2615, 2887, 0, +2747, 3019, 0, +2880, 3152, 0, +3013, 3283, 0, +3145, 3416, 0, +3277, 3548, 0, +3410, 3680, 0, +3542, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3938, 4095, 0, +0, 0, 609, +0, 0, 598, +148, 277, 582, +350, 494, 560, +350, 560, 438, +409, 714, 280, +567, 862, 166, +717, 1005, 0, +863, 1146, 0, +1005, 1284, 0, +1144, 1421, 0, +1281, 1557, 0, +1417, 1691, 0, +1552, 1825, 0, +1686, 1959, 0, +1820, 2092, 0, +1953, 2225, 0, +2086, 2357, 0, +2219, 2490, 0, +2352, 2622, 0, +2484, 2755, 0, +2617, 2887, 0, +2749, 3019, 0, +2881, 3151, 0, +3013, 3283, 0, +3146, 3416, 0, +3278, 3548, 0, +3410, 3680, 0, +3542, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3939, 4095, 0, +224, 0, 609, +286, 0, 598, +357, 148, 582, +438, 350, 560, +528, 528, 528, +625, 691, 482, +730, 846, 412, +840, 994, 298, +955, 1137, 80, +1074, 1278, 0, +1196, 1416, 0, +1320, 1553, 0, +1446, 1689, 0, +1574, 1823, 0, +1703, 1958, 0, +1832, 2091, 0, +1963, 2224, 0, +2093, 2357, 0, +2224, 2489, 0, +2356, 2622, 0, +2487, 2755, 0, +2619, 2887, 0, +2750, 3019, 0, +2883, 3151, 0, +3014, 3283, 0, +3146, 3416, 0, +3278, 3548, 0, +3410, 3680, 0, +3543, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3939, 4095, 0, +587, 0, 750, +616, 0, 741, +652, 34, 730, +696, 280, 714, +691, 482, 625, +691, 570, 482, +846, 828, 412, +947, 994, 298, +1040, 1137, 80, +1141, 1278, 0, +1248, 1416, 0, +1360, 1553, 0, +1477, 1689, 0, +1598, 1823, 0, +1721, 1958, 0, +1846, 2091, 0, +1973, 2224, 0, +2101, 2357, 0, +2230, 2489, 0, +2360, 2622, 0, +2490, 2755, 0, +2621, 2887, 0, +2752, 3019, 0, +2884, 3151, 0, +3015, 3283, 0, +3147, 3416, 0, +3279, 3548, 0, +3411, 3680, 0, +3543, 3812, 0, +3674, 3944, 0, +3807, 4076, 0, +3939, 4095, 0, +838, 0, 888, +855, 0, 882, +873, 0, 870, +862, 166, 815, +846, 412, 730, +846, 412, 541, +846, 622, 412, +994, 917, 298, +1134, 1137, 80, +1218, 1278, 0, +1310, 1416, 0, +1409, 1553, 0, +1515, 1689, 0, +1627, 1823, 0, +1743, 1958, 0, +1863, 2091, 0, +1986, 2224, 0, +2111, 2357, 0, +2238, 2489, 0, +2366, 2622, 0, +2495, 2755, 0, +2625, 2887, 0, +2755, 3019, 0, +2886, 3151, 0, +3016, 3283, 0, +3148, 3416, 0, +3280, 3548, 0, +3411, 3680, 0, +3543, 3812, 0, +3675, 3944, 0, +3807, 4076, 0, +3939, 4095, 0, +1025, 0, 1006, +1020, 0, 985, +1014, 0, 954, +1005, 0, 908, +994, 298, 840, +994, 298, 699, +994, 298, 397, +994, 682, 298, +1137, 1013, 80, +1278, 1251, 0, +1381, 1416, 0, +1467, 1553, 0, +1562, 1689, 0, +1664, 1823, 0, +1772, 1958, 0, +1885, 2091, 0, +2003, 2224, 0, +2124, 2357, 0, +2247, 2489, 0, +2373, 2622, 0, +2501, 2755, 0, +2629, 2887, 0, +2758, 3019, 0, +2888, 3151, 0, +3018, 3283, 0, +3149, 3416, 0, +3280, 3548, 0, +3412, 3680, 0, +3544, 3812, 0, +3675, 3944, 0, +3807, 4076, 0, +3939, 4095, 0, +1160, 0, 1089, +1157, 0, 1071, +1152, 0, 1045, +1146, 0, 1009, +1137, 80, 955, +1137, 80, 850, +1137, 80, 655, +1137, 80, 81, +1137, 753, 80, +1278, 1116, 0, +1416, 1367, 0, +1535, 1553, 0, +1617, 1689, 0, +1709, 1823, 0, +1808, 1958, 0, +1913, 2091, 0, +2025, 2224, 0, +2141, 2357, 0, +2260, 2489, 0, +2383, 2622, 0, +2508, 2755, 0, +2635, 2887, 0, +2762, 3019, 0, +2891, 3151, 0, +3021, 3283, 0, +3151, 3416, 0, +3282, 3548, 0, +3413, 3680, 0, +3544, 3812, 0, +3676, 3944, 0, +3808, 4076, 0, +3940, 4095, 0, +1295, 0, 1181, +1292, 0, 1166, +1289, 0, 1145, +1284, 0, 1116, +1278, 0, 1074, +1278, 0, 995, +1278, 0, 862, +1278, 0, 587, +1278, 0, 0, +1278, 832, 0, +1416, 1225, 0, +1553, 1486, 0, +1683, 1689, 0, +1763, 1823, 0, +1852, 1958, 0, +1949, 2091, 0, +2053, 2224, 0, +2162, 2357, 0, +2277, 2489, 0, +2396, 2622, 0, +2517, 2755, 0, +2642, 2887, 0, +2768, 3019, 0, +2895, 3151, 0, +3024, 3283, 0, +3154, 3416, 0, +3284, 3548, 0, +3414, 3680, 0, +3545, 3812, 0, +3677, 3944, 0, +3808, 4076, 0, +3940, 4095, 0, +1429, 0, 1280, +1427, 0, 1267, +1424, 0, 1251, +1421, 0, 1228, +1416, 0, 1196, +1416, 0, 1137, +1416, 0, 1043, +1416, 0, 878, +1416, 0, 478, +1416, 0, 0, +1416, 920, 0, +1553, 1340, 0, +1689, 1608, 0, +1823, 1821, 0, +1905, 1958, 0, +1992, 2091, 0, +2087, 2224, 0, +2190, 2357, 0, +2298, 2489, 0, +2412, 2622, 0, +2530, 2755, 0, +2651, 2887, 0, +2775, 3019, 0, +2901, 3151, 0, +3028, 3283, 0, +3157, 3416, 0, +3286, 3548, 0, +3416, 3680, 0, +3547, 3812, 0, +3678, 3944, 0, +3809, 4076, 0, +3941, 4095, 0, +1563, 0, 1385, +1561, 0, 1376, +1559, 0, 1363, +1557, 0, 1345, +1553, 0, 1320, +1553, 0, 1276, +1553, 0, 1209, +1553, 0, 1102, +1553, 0, 900, +1553, 0, 275, +1553, 0, 0, +1553, 1017, 0, +1689, 1457, 0, +1823, 1732, 0, +1958, 1948, 0, +2044, 2091, 0, +2130, 2224, 0, +2224, 2357, 0, +2326, 2489, 0, +2434, 2622, 0, +2547, 2755, 0, +2664, 2887, 0, +2785, 3019, 0, +2908, 3151, 0, +3034, 3283, 0, +3161, 3416, 0, +3289, 3548, 0, +3419, 3680, 0, +3549, 3812, 0, +3679, 3944, 0, +3810, 4076, 0, +3941, 4095, 0, +1696, 0, 1496, +1695, 0, 1489, +1693, 0, 1479, +1691, 0, 1465, +1689, 0, 1446, +1689, 0, 1413, +1689, 0, 1365, +1689, 0, 1291, +1689, 0, 1169, +1689, 0, 926, +1689, 0, 0, +1689, 0, 0, +1689, 1120, 0, +1823, 1579, 0, +1958, 1859, 0, +2091, 2076, 0, +2181, 2224, 0, +2266, 2357, 0, +2360, 2489, 0, +2460, 2622, 0, +2568, 2755, 0, +2681, 2887, 0, +2797, 3019, 0, +2918, 3151, 0, +3041, 3283, 0, +3166, 3416, 0, +3293, 3548, 0, +3422, 3680, 0, +3551, 3812, 0, +3681, 3944, 0, +3811, 4076, 0, +3942, 4095, 0, +1828, 0, 1612, +1828, 0, 1607, +1827, 0, 1599, +1825, 0, 1588, +1823, 0, 1574, +1823, 0, 1549, +1823, 0, 1514, +1823, 0, 1462, +1823, 0, 1382, +1823, 0, 1245, +1823, 0, 960, +1823, 0, 0, +1823, 0, 0, +1823, 1230, 0, +1958, 1703, 0, +2091, 1986, 0, +2224, 2206, 0, +2317, 2357, 0, +2401, 2489, 0, +2494, 2622, 0, +2595, 2755, 0, +2702, 2887, 0, +2814, 3019, 0, +2931, 3151, 0, +3051, 3283, 0, +3174, 3416, 0, +3299, 3548, 0, +3426, 3680, 0, +3554, 3812, 0, +3683, 3944, 0, +3813, 4076, 0, +3944, 4095, 0, +1961, 0, 1732, +1961, 0, 1728, +1960, 0, 1722, +1959, 0, 1714, +1958, 0, 1703, +1958, 0, 1684, +1958, 0, 1658, +1958, 0, 1621, +1958, 0, 1566, +1958, 0, 1480, +1958, 0, 1332, +1958, 0, 1000, +1958, 0, 0, +1958, 0, 0, +1958, 1344, 0, +2091, 1829, 0, +2224, 2115, 0, +2357, 2335, 0, +2452, 2489, 0, +2536, 2622, 0, +2628, 2755, 0, +2728, 2887, 0, +2835, 3019, 0, +2947, 3151, 0, +3063, 3283, 0, +3184, 3416, 0, +3307, 3548, 0, +3431, 3680, 0, +3558, 3812, 0, +3686, 3944, 0, +3815, 4076, 0, +3945, 4095, 0, +2094, 0, 1855, +2093, 0, 1851, +2093, 0, 1847, +2092, 0, 1841, +2091, 0, 1832, +2091, 0, 1819, +2091, 0, 1799, +2091, 0, 1772, +2091, 0, 1733, +2091, 0, 1676, +2091, 0, 1585, +2091, 0, 1425, +2091, 0, 1050, +2091, 0, 0, +2091, 0, 0, +2091, 1463, 0, +2224, 1956, 0, +2357, 2245, 0, +2489, 2466, 0, +2586, 2622, 0, +2670, 2755, 0, +2762, 2887, 0, +2862, 3019, 0, +2968, 3151, 0, +3080, 3283, 0, +3196, 3416, 0, +3316, 3548, 0, +3439, 3680, 0, +3564, 3812, 0, +3691, 3944, 0, +3818, 4076, 0, +3948, 4095, 0, +2226, 0, 1979, +2226, 0, 1977, +2225, 0, 1973, +2225, 0, 1969, +2224, 0, 1963, +2224, 0, 1952, +2224, 0, 1938, +2224, 0, 1918, +2224, 0, 1891, +2224, 0, 1850, +2224, 0, 1790, +2224, 0, 1695, +2224, 0, 1527, +2224, 0, 1108, +2224, 0, 0, +2224, 0, 0, +2224, 1584, 0, +2357, 2085, 0, +2489, 2375, 0, +2622, 2597, 0, +2720, 2755, 0, +2803, 2887, 0, +2895, 3019, 0, +2995, 3151, 0, +3101, 3283, 0, +3212, 3416, 0, +3329, 3548, 0, +3448, 3680, 0, +3571, 3812, 0, +3696, 3944, 0, +3823, 4076, 0, +3951, 4095, 0, +2358, 0, 2106, +2358, 0, 2104, +2358, 0, 2101, +2357, 0, 2098, +2357, 0, 2093, +2357, 0, 2086, +2357, 0, 2075, +2357, 0, 2060, +2357, 0, 2040, +2357, 0, 2012, +2357, 0, 1970, +2357, 0, 1909, +2357, 0, 1811, +2357, 0, 1634, +2357, 0, 1176, +2357, 0, 0, +2357, 0, 0, +2357, 1708, 0, +2489, 2215, 0, +2622, 2506, 0, +2755, 2729, 0, +2853, 2887, 0, +2936, 3019, 0, +3028, 3151, 0, +3127, 3283, 0, +3233, 3416, 0, +3345, 3548, 0, +3461, 3680, 0, +3581, 3812, 0, +3703, 3944, 0, +3828, 4076, 0, +3955, 4095, 0, +2491, 0, 2234, +2491, 0, 2233, +2490, 0, 2230, +2490, 0, 2228, +2489, 0, 2224, +2489, 0, 2219, +2489, 0, 2211, +2489, 0, 2200, +2489, 0, 2185, +2489, 0, 2165, +2489, 0, 2136, +2489, 0, 2094, +2489, 0, 2031, +2489, 0, 1930, +2489, 0, 1748, +2489, 0, 1255, +2489, 0, 0, +2489, 0, 0, +2489, 1834, 0, +2622, 2344, 0, +2755, 2637, 0, +2887, 2860, 0, +2986, 3019, 0, +3069, 3151, 0, +3160, 3283, 0, +3260, 3416, 0, +3366, 3548, 0, +3478, 3680, 0, +3594, 3812, 0, +3713, 3944, 0, +3836, 4076, 0, +3961, 4095, 0, +2623, 0, 2363, +2623, 0, 2362, +2623, 0, 2360, +2622, 0, 2358, +2622, 0, 2356, +2622, 0, 2351, +2622, 0, 2346, +2622, 0, 2337, +2622, 0, 2327, +2622, 0, 2312, +2622, 0, 2291, +2622, 0, 2261, +2622, 0, 2219, +2622, 0, 2155, +2622, 0, 2052, +2622, 0, 1865, +2622, 0, 1342, +2622, 0, 0, +2622, 0, 0, +2622, 1962, 0, +2755, 2476, 0, +2887, 2768, 0, +3019, 2992, 0, +3119, 3151, 0, +3201, 3283, 0, +3293, 3416, 0, +3392, 3548, 0, +3498, 3680, 0, +3610, 3812, 0, +3726, 3944, 0, +3845, 4076, 0, +3968, 4095, 0, +2755, 0, 2493, +2755, 0, 2492, +2755, 0, 2491, +2755, 0, 2489, +2755, 0, 2487, +2755, 0, 2484, +2755, 0, 2480, +2755, 0, 2474, +2755, 0, 2466, +2755, 0, 2455, +2755, 0, 2440, +2755, 0, 2419, +2755, 0, 2389, +2755, 0, 2346, +2755, 0, 2281, +2755, 0, 2177, +2755, 0, 1986, +2755, 0, 1439, +2755, 0, 0, +2755, 0, 0, +2755, 2091, 0, +2887, 2606, 0, +3019, 2899, 0, +3151, 3123, 0, +3251, 3283, 0, +3334, 3416, 0, +3426, 3548, 0, +3525, 3680, 0, +3631, 3812, 0, +3742, 3944, 0, +3858, 4076, 0, +3977, 4095, 0, +2887, 0, 2623, +2887, 0, 2622, +2887, 0, 2621, +2887, 0, 2620, +2887, 0, 2619, +2887, 0, 2617, +2887, 0, 2613, +2887, 0, 2609, +2887, 0, 2603, +2887, 0, 2595, +2887, 0, 2584, +2887, 0, 2569, +2887, 0, 2548, +2887, 0, 2517, +2887, 0, 2474, +2887, 0, 2409, +2887, 0, 2304, +2887, 0, 2110, +2887, 0, 1540, +2887, 0, 0, +2887, 0, 0, +2887, 2220, 0, +3019, 2737, 0, +3151, 3031, 0, +3283, 3255, 0, +3384, 3416, 0, +3467, 3548, 0, +3558, 3680, 0, +3657, 3812, 0, +3763, 3944, 0, +3874, 4076, 0, +3990, 4095, 0, +3019, 0, 2754, +3019, 0, 2753, +3019, 0, 2752, +3019, 0, 2751, +3019, 0, 2750, +3019, 0, 2749, +3019, 0, 2746, +3019, 0, 2743, +3019, 0, 2738, +3019, 0, 2732, +3019, 0, 2724, +3019, 0, 2713, +3019, 0, 2698, +3019, 0, 2677, +3019, 0, 2647, +3019, 0, 2603, +3019, 0, 2537, +3019, 0, 2431, +3019, 0, 2234, +3019, 0, 1646, +3019, 0, 0, +3019, 0, 0, +3019, 2350, 0, +3151, 2869, 0, +3283, 3163, 0, +3416, 3387, 0, +3516, 3548, 0, +3599, 3680, 0, +3690, 3812, 0, +3789, 3944, 0, +3895, 4076, 0, +4006, 4095, 0, +3152, 0, 2885, +3152, 0, 2885, +3152, 0, 2884, +3151, 0, 2883, +3151, 0, 2883, +3151, 0, 2881, +3151, 0, 2879, +3151, 0, 2877, +3151, 0, 2873, +3151, 0, 2869, +3151, 0, 2863, +3151, 0, 2855, +3151, 0, 2844, +3151, 0, 2829, +3151, 0, 2807, +3151, 0, 2777, +3151, 0, 2733, +3151, 0, 2667, +3151, 0, 2560, +3151, 0, 2362, +3151, 0, 1760, +3151, 0, 0, +3151, 0, 0, +3151, 2481, 0, +3283, 3000, 0, +3416, 3295, 0, +3548, 3519, 0, +3648, 3680, 0, +3731, 3812, 0, +3822, 3944, 0, +3921, 4076, 0, +4027, 4095, 0, +3284, 0, 3016, +3283, 0, 3016, +3283, 0, 3015, +3283, 0, 3015, +3283, 0, 3014, +3283, 0, 3013, +3283, 0, 3012, +3283, 0, 3010, +3283, 0, 3008, +3283, 0, 3004, +3283, 0, 3000, +3283, 0, 2994, +3283, 0, 2986, +3283, 0, 2974, +3283, 0, 2959, +3283, 0, 2938, +3283, 0, 2907, +3283, 0, 2863, +3283, 0, 2797, +3283, 0, 2690, +3283, 0, 2489, +3283, 0, 1875, +3283, 0, 0, +3283, 0, 0, +3283, 2612, 0, +3416, 3132, 0, +3548, 3427, 0, +3680, 3651, 0, +3781, 3812, 0, +3863, 3944, 0, +3955, 4076, 0, +4054, 4095, 0, +3416, 0, 3147, +3416, 0, 3147, +3416, 0, 3147, +3416, 0, 3147, +3416, 0, 3146, +3416, 0, 3145, +3416, 0, 3144, +3416, 0, 3143, +3416, 0, 3141, +3416, 0, 3139, +3416, 0, 3135, +3416, 0, 3131, +3416, 0, 3125, +3416, 0, 3117, +3416, 0, 3106, +3416, 0, 3090, +3416, 0, 3069, +3416, 0, 3038, +3416, 0, 2994, +3416, 0, 2928, +3416, 0, 2820, +3416, 0, 2619, +3416, 0, 2000, +3416, 0, 0, +3416, 0, 0, +3416, 2743, 0, +3548, 3264, 0, +3680, 3559, 0, +3812, 3783, 0, +3913, 3944, 0, +3995, 4076, 0, +4087, 4095, 0, +3548, 0, 3279, +3548, 0, 3279, +3548, 0, 3279, +3548, 0, 3279, +3548, 0, 3278, +3548, 0, 3278, +3548, 0, 3277, +3548, 0, 3276, +3548, 0, 3275, +3548, 0, 3273, +3548, 0, 3270, +3548, 0, 3267, +3548, 0, 3262, +3548, 0, 3256, +3548, 0, 3248, +3548, 0, 3237, +3548, 0, 3222, +3548, 0, 3200, +3548, 0, 3170, +3548, 0, 3125, +3548, 0, 3059, +3548, 0, 2951, +3548, 0, 2749, +3548, 0, 2122, +3548, 0, 0, +3548, 0, 0, +3548, 2874, 0, +3680, 3396, 0, +3812, 3691, 0, +3944, 3915, 0, +4045, 4076, 0, +4095, 4095, 0, +3680, 0, 3411, +3680, 0, 3411, +3680, 0, 3411, +3680, 0, 3411, +3680, 0, 3410, +3680, 0, 3410, +3680, 0, 3409, +3680, 0, 3409, +3680, 0, 3408, +3680, 0, 3406, +3680, 0, 3404, +3680, 0, 3402, +3680, 0, 3399, +3680, 0, 3394, +3680, 0, 3388, +3680, 0, 3380, +3680, 0, 3369, +3680, 0, 3353, +3680, 0, 3332, +3680, 0, 3301, +3680, 0, 3257, +3680, 0, 3190, +3680, 0, 3082, +3680, 0, 2879, +3680, 0, 2251, +3680, 0, 0, +3680, 0, 0, +3680, 3006, 0, +3812, 3528, 0, +3944, 3823, 0, +4076, 4047, 0, +4095, 4095, 0, +3812, 0, 3543, +3812, 0, 3543, +3812, 0, 3543, +3812, 0, 3543, +3812, 0, 3543, +3812, 0, 3542, +3812, 0, 3542, +3812, 0, 3541, +3812, 0, 3540, +3812, 0, 3539, +3812, 0, 3538, +3812, 0, 3536, +3812, 0, 3534, +3812, 0, 3530, +3812, 0, 3526, +3812, 0, 3520, +3812, 0, 3511, +3812, 0, 3500, +3812, 0, 3485, +3812, 0, 3463, +3812, 0, 3433, +3812, 0, 3388, +3812, 0, 3322, +3812, 0, 3213, +3812, 0, 3011, +3812, 0, 2377, +3812, 0, 0, +3812, 0, 0, +3812, 3138, 0, +3944, 3660, 0, +4076, 3955, 0, +4095, 4095, 0, +3944, 0, 3675, +3944, 0, 3675, +3944, 0, 3675, +3944, 0, 3674, +3944, 0, 3674, +3944, 0, 3674, +3944, 0, 3674, +3944, 0, 3673, +3944, 0, 3673, +3944, 0, 3672, +3944, 0, 3671, +3944, 0, 3670, +3944, 0, 3668, +3944, 0, 3665, +3944, 0, 3662, +3944, 0, 3658, +3944, 0, 3652, +3944, 0, 3643, +3944, 0, 3632, +3944, 0, 3617, +3944, 0, 3595, +3944, 0, 3564, +3944, 0, 3520, +3944, 0, 3453, +3944, 0, 3345, +3944, 0, 3142, +3944, 0, 2505, +3944, 0, 0, +3944, 0, 0, +3944, 3270, 0, +4076, 3792, 0, +4095, 4087, 0, +4076, 0, 3807, +4076, 0, 3807, +4076, 0, 3807, +4076, 0, 3806, +4076, 0, 3806, +4076, 0, 3806, +4076, 0, 3806, +4076, 0, 3805, +4076, 0, 3805, +4076, 0, 3805, +4076, 0, 3804, +4076, 0, 3803, +4076, 0, 3801, +4076, 0, 3800, +4076, 0, 3797, +4076, 0, 3794, +4076, 0, 3790, +4076, 0, 3783, +4076, 0, 3775, +4076, 0, 3764, +4076, 0, 3748, +4076, 0, 3727, +4076, 0, 3696, +4076, 0, 3652, +4076, 0, 3585, +4076, 0, 3476, +4076, 0, 3273, +4076, 0, 2632, +4076, 0, 0, +4076, 0, 0, +4076, 3401, 0, +4095, 3924, 0, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3938, +4095, 0, 3938, +4095, 0, 3938, +4095, 0, 3938, +4095, 0, 3937, +4095, 0, 3937, +4095, 0, 3936, +4095, 0, 3935, +4095, 0, 3934, +4095, 0, 3932, +4095, 0, 3929, +4095, 0, 3926, +4095, 0, 3921, +4095, 0, 3915, +4095, 0, 3907, +4095, 0, 3896, +4095, 0, 3880, +4095, 0, 3859, +4095, 0, 3828, +4095, 0, 3784, +4095, 0, 3717, +4095, 0, 3608, +4095, 0, 3405, +4095, 0, 2765, +4095, 0, 0, +4095, 0, 0, +4095, 3534, 0, +0, 545, 750, +0, 613, 750, +0, 689, 750, +0, 750, 723, +0, 750, 587, +0, 750, 304, +0, 888, 0, +0, 1025, 0, +397, 1160, 0, +717, 1295, 0, +951, 1429, 0, +1148, 1563, 0, +1322, 1696, 0, +1484, 1828, 0, +1636, 1961, 0, +1783, 2094, 0, +1926, 2226, 0, +2066, 2358, 0, +2204, 2491, 0, +2341, 2623, 0, +2476, 2755, 0, +2611, 2887, 0, +2744, 3019, 0, +2878, 3152, 0, +3011, 3284, 0, +3144, 3416, 0, +3276, 3548, 0, +3409, 3680, 0, +3541, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3938, 4095, 0, +0, 467, 750, +0, 559, 741, +0, 644, 741, +0, 738, 741, +0, 741, 616, +0, 741, 356, +0, 882, 0, +81, 1020, 0, +503, 1157, 0, +772, 1292, 0, +985, 1427, 0, +1170, 1561, 0, +1337, 1695, 0, +1494, 1828, 0, +1644, 1961, 0, +1789, 2093, 0, +1930, 2226, 0, +2069, 2358, 0, +2206, 2491, 0, +2342, 2623, 0, +2477, 2755, 0, +2612, 2887, 0, +2745, 3019, 0, +2878, 3152, 0, +3011, 3283, 0, +3144, 3416, 0, +3277, 3548, 0, +3409, 3680, 0, +3541, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3938, 4095, 0, +0, 334, 750, +0, 453, 741, +34, 576, 730, +34, 683, 730, +34, 730, 652, +34, 730, 418, +0, 873, 0, +323, 1014, 0, +614, 1152, 0, +837, 1289, 0, +1027, 1424, 0, +1198, 1559, 0, +1357, 1693, 0, +1508, 1827, 0, +1654, 1960, 0, +1796, 2093, 0, +1936, 2225, 0, +2073, 2358, 0, +2209, 2490, 0, +2345, 2623, 0, +2479, 2755, 0, +2613, 2887, 0, +2746, 3019, 0, +2879, 3152, 0, +3011, 3283, 0, +3144, 3416, 0, +3277, 3548, 0, +3409, 3680, 0, +3541, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3938, 4095, 0, +0, 59, 750, +0, 258, 741, +34, 435, 730, +280, 598, 714, +280, 714, 696, +280, 714, 490, +264, 862, 166, +523, 1005, 0, +730, 1146, 0, +911, 1284, 0, +1077, 1421, 0, +1233, 1557, 0, +1382, 1691, 0, +1526, 1825, 0, +1667, 1959, 0, +1806, 2092, 0, +1943, 2225, 0, +2078, 2357, 0, +2213, 2490, 0, +2347, 2622, 0, +2481, 2755, 0, +2614, 2887, 0, +2747, 3019, 0, +2880, 3151, 0, +3012, 3283, 0, +3145, 3416, 0, +3277, 3548, 0, +3410, 3680, 0, +3542, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3938, 4095, 0, +0, 0, 750, +0, 0, 741, +34, 132, 730, +280, 409, 714, +482, 625, 691, +482, 691, 570, +541, 846, 412, +699, 994, 298, +850, 1137, 80, +995, 1278, 0, +1137, 1416, 0, +1276, 1553, 0, +1413, 1689, 0, +1549, 1823, 0, +1684, 1958, 0, +1819, 2091, 0, +1952, 2224, 0, +2086, 2357, 0, +2219, 2489, 0, +2351, 2622, 0, +2484, 2755, 0, +2617, 2887, 0, +2749, 3019, 0, +2881, 3151, 0, +3013, 3283, 0, +3145, 3416, 0, +3278, 3548, 0, +3410, 3680, 0, +3542, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3938, 4095, 0, +304, 0, 750, +356, 0, 741, +418, 34, 730, +490, 280, 714, +570, 482, 691, +660, 660, 660, +758, 824, 614, +862, 978, 544, +972, 1126, 430, +1087, 1270, 212, +1206, 1410, 0, +1328, 1549, 0, +1452, 1685, 0, +1579, 1821, 0, +1706, 1956, 0, +1835, 2089, 0, +1965, 2223, 0, +2095, 2356, 0, +2226, 2489, 0, +2356, 2621, 0, +2488, 2754, 0, +2619, 2887, 0, +2751, 3019, 0, +2883, 3151, 0, +3014, 3283, 0, +3146, 3416, 0, +3278, 3548, 0, +3410, 3680, 0, +3543, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3939, 4095, 0, +697, 0, 888, +719, 0, 882, +749, 0, 873, +784, 166, 862, +828, 412, 846, +824, 614, 758, +824, 702, 614, +978, 960, 544, +1079, 1126, 430, +1172, 1270, 212, +1273, 1410, 0, +1380, 1549, 0, +1492, 1685, 0, +1609, 1821, 0, +1730, 1956, 0, +1853, 2089, 0, +1978, 2223, 0, +2105, 2356, 0, +2233, 2489, 0, +2362, 2621, 0, +2492, 2754, 0, +2623, 2887, 0, +2753, 3019, 0, +2885, 3151, 0, +3016, 3283, 0, +3147, 3416, 0, +3279, 3548, 0, +3411, 3680, 0, +3543, 3812, 0, +3675, 3944, 0, +3807, 4076, 0, +3939, 4095, 0, +957, 0, 1025, +970, 0, 1020, +987, 0, 1014, +1005, 0, 1002, +994, 298, 947, +978, 544, 862, +978, 544, 673, +978, 754, 544, +1126, 1049, 430, +1266, 1270, 212, +1350, 1410, 0, +1442, 1549, 0, +1541, 1685, 0, +1648, 1821, 0, +1759, 1956, 0, +1875, 2089, 0, +1995, 2223, 0, +2118, 2356, 0, +2243, 2489, 0, +2370, 2621, 0, +2498, 2754, 0, +2627, 2887, 0, +2756, 3019, 0, +2887, 3151, 0, +3018, 3283, 0, +3149, 3416, 0, +3280, 3548, 0, +3412, 3680, 0, +3543, 3812, 0, +3675, 3944, 0, +3807, 4076, 0, +3939, 4095, 0, +1160, 0, 1154, +1157, 0, 1139, +1152, 0, 1117, +1146, 0, 1086, +1137, 80, 1040, +1126, 430, 972, +1126, 430, 831, +1126, 430, 529, +1126, 814, 430, +1270, 1145, 212, +1410, 1383, 0, +1513, 1549, 0, +1599, 1685, 0, +1694, 1821, 0, +1796, 1956, 0, +1904, 2089, 0, +2018, 2223, 0, +2135, 2356, 0, +2256, 2489, 0, +2380, 2621, 0, +2505, 2754, 0, +2632, 2887, 0, +2761, 3019, 0, +2890, 3151, 0, +3020, 3283, 0, +3151, 3416, 0, +3281, 3548, 0, +3413, 3680, 0, +3544, 3812, 0, +3676, 3944, 0, +3808, 4076, 0, +3939, 4095, 0, +1295, 0, 1234, +1292, 0, 1221, +1289, 0, 1203, +1284, 0, 1177, +1278, 0, 1141, +1270, 212, 1087, +1270, 212, 982, +1270, 212, 787, +1270, 212, 214, +1270, 884, 212, +1410, 1248, 0, +1549, 1499, 0, +1667, 1685, 0, +1750, 1821, 0, +1841, 1956, 0, +1940, 2089, 0, +2046, 2223, 0, +2157, 2356, 0, +2273, 2489, 0, +2393, 2621, 0, +2515, 2754, 0, +2640, 2887, 0, +2766, 3019, 0, +2895, 3151, 0, +3023, 3283, 0, +3153, 3416, 0, +3283, 3548, 0, +3414, 3680, 0, +3545, 3812, 0, +3676, 3944, 0, +3808, 4076, 0, +3940, 4095, 0, +1429, 0, 1323, +1427, 0, 1313, +1424, 0, 1298, +1421, 0, 1277, +1416, 0, 1248, +1410, 0, 1206, +1410, 0, 1127, +1410, 0, 994, +1410, 0, 719, +1410, 47, 0, +1410, 964, 0, +1549, 1358, 0, +1685, 1618, 0, +1815, 1821, 0, +1895, 1956, 0, +1984, 2089, 0, +2081, 2223, 0, +2185, 2356, 0, +2294, 2489, 0, +2409, 2621, 0, +2528, 2754, 0, +2650, 2887, 0, +2774, 3019, 0, +2900, 3151, 0, +3027, 3283, 0, +3156, 3416, 0, +3286, 3548, 0, +3416, 3680, 0, +3547, 3812, 0, +3677, 3944, 0, +3809, 4076, 0, +3941, 4095, 0, +1563, 0, 1421, +1561, 0, 1412, +1559, 0, 1400, +1557, 0, 1384, +1553, 0, 1360, +1549, 0, 1328, +1549, 0, 1269, +1549, 0, 1176, +1549, 0, 1011, +1549, 0, 611, +1549, 0, 0, +1549, 1053, 0, +1685, 1471, 0, +1821, 1740, 0, +1956, 1953, 0, +2037, 2089, 0, +2124, 2223, 0, +2219, 2356, 0, +2322, 2489, 0, +2431, 2621, 0, +2545, 2754, 0, +2662, 2887, 0, +2784, 3019, 0, +2907, 3151, 0, +3033, 3283, 0, +3160, 3416, 0, +3289, 3548, 0, +3418, 3680, 0, +3548, 3812, 0, +3679, 3944, 0, +3810, 4076, 0, +3941, 4095, 0, +1696, 0, 1524, +1695, 0, 1517, +1693, 0, 1508, +1691, 0, 1495, +1689, 0, 1477, +1685, 0, 1452, +1685, 0, 1408, +1685, 0, 1341, +1685, 0, 1233, +1685, 0, 1031, +1685, 0, 406, +1685, 0, 0, +1685, 1149, 0, +1821, 1590, 0, +1956, 1865, 0, +2089, 2080, 0, +2176, 2223, 0, +2262, 2356, 0, +2356, 2489, 0, +2458, 2621, 0, +2566, 2754, 0, +2679, 2887, 0, +2796, 3019, 0, +2917, 3151, 0, +3040, 3283, 0, +3166, 3416, 0, +3293, 3548, 0, +3421, 3680, 0, +3551, 3812, 0, +3681, 3944, 0, +3811, 4076, 0, +3942, 4095, 0, +1828, 0, 1634, +1828, 0, 1629, +1827, 0, 1621, +1825, 0, 1611, +1823, 0, 1598, +1821, 0, 1579, +1821, 0, 1545, +1821, 0, 1497, +1821, 0, 1423, +1821, 0, 1301, +1821, 0, 1059, +1821, 0, 0, +1821, 0, 0, +1821, 1253, 0, +1956, 1711, 0, +2089, 1991, 0, +2223, 2208, 0, +2313, 2356, 0, +2398, 2489, 0, +2492, 2621, 0, +2593, 2754, 0, +2700, 2887, 0, +2813, 3019, 0, +2930, 3151, 0, +3050, 3283, 0, +3173, 3416, 0, +3299, 3548, 0, +3426, 3680, 0, +3554, 3812, 0, +3683, 3944, 0, +3813, 4076, 0, +3944, 4095, 0, +1961, 0, 1749, +1961, 0, 1745, +1960, 0, 1739, +1959, 0, 1731, +1958, 0, 1721, +1956, 0, 1706, +1956, 0, 1681, +1956, 0, 1646, +1956, 0, 1594, +1956, 0, 1514, +1956, 0, 1378, +1956, 0, 1091, +1956, 0, 0, +1956, 0, 0, +1956, 1362, 0, +2089, 1835, 0, +2223, 2118, 0, +2356, 2338, 0, +2449, 2489, 0, +2533, 2621, 0, +2627, 2754, 0, +2727, 2887, 0, +2834, 3019, 0, +2946, 3151, 0, +3062, 3283, 0, +3183, 3416, 0, +3306, 3548, 0, +3431, 3680, 0, +3558, 3812, 0, +3686, 3944, 0, +3815, 4076, 0, +3945, 4095, 0, +2094, 0, 1867, +2093, 0, 1864, +2093, 0, 1860, +2092, 0, 1854, +2091, 0, 1846, +2089, 0, 1835, +2089, 0, 1816, +2089, 0, 1790, +2089, 0, 1753, +2089, 0, 1698, +2089, 0, 1612, +2089, 0, 1463, +2089, 0, 1133, +2089, 0, 0, +2089, 0, 0, +2089, 1476, 0, +2223, 1961, 0, +2356, 2247, 0, +2489, 2468, 0, +2584, 2621, 0, +2668, 2754, 0, +2761, 2887, 0, +2860, 3019, 0, +2967, 3151, 0, +3079, 3283, 0, +3196, 3416, 0, +3316, 3548, 0, +3438, 3680, 0, +3564, 3812, 0, +3690, 3944, 0, +3818, 4076, 0, +3948, 4095, 0, +2226, 0, 1989, +2226, 0, 1987, +2225, 0, 1983, +2225, 0, 1979, +2224, 0, 1973, +2223, 0, 1965, +2223, 0, 1951, +2223, 0, 1931, +2223, 0, 1904, +2223, 0, 1865, +2223, 0, 1808, +2223, 0, 1717, +2223, 0, 1557, +2223, 0, 1181, +2223, 0, 0, +2223, 0, 0, +2223, 1595, 0, +2356, 2088, 0, +2489, 2377, 0, +2621, 2598, 0, +2718, 2754, 0, +2802, 2887, 0, +2894, 3019, 0, +2994, 3151, 0, +3100, 3283, 0, +3212, 3416, 0, +3328, 3548, 0, +3448, 3680, 0, +3571, 3812, 0, +3696, 3944, 0, +3822, 4076, 0, +3951, 4095, 0, +2358, 0, 2113, +2358, 0, 2111, +2358, 0, 2109, +2357, 0, 2105, +2357, 0, 2101, +2356, 0, 2095, +2356, 0, 2084, +2356, 0, 2070, +2356, 0, 2050, +2356, 0, 2022, +2356, 0, 1982, +2356, 0, 1922, +2356, 0, 1828, +2356, 0, 1659, +2356, 0, 1240, +2356, 0, 0, +2356, 0, 0, +2356, 1716, 0, +2489, 2218, 0, +2621, 2507, 0, +2754, 2730, 0, +2852, 2887, 0, +2935, 3019, 0, +3027, 3151, 0, +3127, 3283, 0, +3233, 3416, 0, +3344, 3548, 0, +3461, 3680, 0, +3581, 3812, 0, +3703, 3944, 0, +3828, 4076, 0, +3955, 4095, 0, +2491, 0, 2239, +2491, 0, 2238, +2490, 0, 2236, +2490, 0, 2234, +2489, 0, 2230, +2489, 0, 2226, +2489, 0, 2218, +2489, 0, 2207, +2489, 0, 2193, +2489, 0, 2172, +2489, 0, 2144, +2489, 0, 2103, +2489, 0, 2041, +2489, 0, 1943, +2489, 0, 1767, +2489, 0, 1310, +2489, 0, 0, +2489, 0, 0, +2489, 1840, 0, +2621, 2346, 0, +2754, 2638, 0, +2887, 2861, 0, +2985, 3019, 0, +3068, 3151, 0, +3160, 3283, 0, +3259, 3416, 0, +3365, 3548, 0, +3477, 3680, 0, +3593, 3812, 0, +3713, 3944, 0, +3835, 4076, 0, +3961, 4095, 0, +2623, 0, 2367, +2623, 0, 2366, +2623, 0, 2364, +2622, 0, 2362, +2622, 0, 2360, +2621, 0, 2356, +2621, 0, 2351, +2621, 0, 2343, +2621, 0, 2332, +2621, 0, 2317, +2621, 0, 2297, +2621, 0, 2268, +2621, 0, 2226, +2621, 0, 2163, +2621, 0, 2062, +2621, 0, 1880, +2621, 0, 1387, +2621, 0, 0, +2621, 0, 0, +2621, 1966, 0, +2754, 2477, 0, +2887, 2769, 0, +3019, 2992, 0, +3118, 3151, 0, +3201, 3283, 0, +3293, 3416, 0, +3392, 3548, 0, +3498, 3680, 0, +3609, 3812, 0, +3725, 3944, 0, +3845, 4076, 0, +3968, 4095, 0, +2755, 0, 2496, +2755, 0, 2495, +2755, 0, 2494, +2755, 0, 2492, +2755, 0, 2490, +2754, 0, 2488, +2754, 0, 2484, +2754, 0, 2478, +2754, 0, 2470, +2754, 0, 2459, +2754, 0, 2444, +2754, 0, 2423, +2754, 0, 2394, +2754, 0, 2351, +2754, 0, 2287, +2754, 0, 2185, +2754, 0, 1997, +2754, 0, 1476, +2754, 0, 0, +2754, 0, 0, +2754, 2094, 0, +2887, 2607, 0, +3019, 2900, 0, +3151, 3124, 0, +3251, 3283, 0, +3334, 3416, 0, +3425, 3548, 0, +3525, 3680, 0, +3630, 3812, 0, +3742, 3944, 0, +3858, 4076, 0, +3977, 4095, 0, +2887, 0, 2625, +2887, 0, 2625, +2887, 0, 2624, +2887, 0, 2623, +2887, 0, 2621, +2887, 0, 2619, +2887, 0, 2616, +2887, 0, 2612, +2887, 0, 2606, +2887, 0, 2598, +2887, 0, 2587, +2887, 0, 2572, +2887, 0, 2551, +2887, 0, 2521, +2887, 0, 2478, +2887, 0, 2413, +2887, 0, 2310, +2887, 0, 2118, +2887, 0, 1569, +2887, 0, 0, +2887, 0, 0, +2887, 2223, 0, +3019, 2738, 0, +3151, 3032, 0, +3283, 3255, 0, +3384, 3416, 0, +3466, 3548, 0, +3558, 3680, 0, +3657, 3812, 0, +3763, 3944, 0, +3874, 4076, 0, +3990, 4095, 0, +3019, 0, 2755, +3019, 0, 2755, +3019, 0, 2754, +3019, 0, 2753, +3019, 0, 2752, +3019, 0, 2751, +3019, 0, 2748, +3019, 0, 2745, +3019, 0, 2741, +3019, 0, 2735, +3019, 0, 2727, +3019, 0, 2716, +3019, 0, 2701, +3019, 0, 2679, +3019, 0, 2649, +3019, 0, 2606, +3019, 0, 2541, +3019, 0, 2435, +3019, 0, 2241, +3019, 0, 1670, +3019, 0, 0, +3019, 0, 0, +3019, 2352, 0, +3151, 2870, 0, +3283, 3163, 0, +3416, 3387, 0, +3516, 3548, 0, +3599, 3680, 0, +3690, 3812, 0, +3789, 3944, 0, +3895, 4076, 0, +4006, 4095, 0, +3152, 0, 2886, +3152, 0, 2886, +3152, 0, 2885, +3151, 0, 2885, +3151, 0, 2884, +3151, 0, 2883, +3151, 0, 2881, +3151, 0, 2879, +3151, 0, 2875, +3151, 0, 2871, +3151, 0, 2865, +3151, 0, 2857, +3151, 0, 2845, +3151, 0, 2830, +3151, 0, 2809, +3151, 0, 2779, +3151, 0, 2735, +3151, 0, 2670, +3151, 0, 2564, +3151, 0, 2367, +3151, 0, 1779, +3151, 0, 0, +3151, 0, 0, +3151, 2482, 0, +3283, 3000, 0, +3416, 3295, 0, +3548, 3519, 0, +3648, 3680, 0, +3731, 3812, 0, +3822, 3944, 0, +3921, 4076, 0, +4027, 4095, 0, +3284, 0, 3017, +3283, 0, 3017, +3283, 0, 3016, +3283, 0, 3016, +3283, 0, 3015, +3283, 0, 3014, +3283, 0, 3013, +3283, 0, 3011, +3283, 0, 3009, +3283, 0, 3005, +3283, 0, 3001, +3283, 0, 2995, +3283, 0, 2987, +3283, 0, 2976, +3283, 0, 2960, +3283, 0, 2939, +3283, 0, 2909, +3283, 0, 2865, +3283, 0, 2799, +3283, 0, 2692, +3283, 0, 2493, +3283, 0, 1890, +3283, 0, 0, +3283, 0, 0, +3283, 2613, 0, +3416, 3133, 0, +3548, 3427, 0, +3680, 3651, 0, +3781, 3812, 0, +3863, 3944, 0, +3954, 4076, 0, +4054, 4095, 0, +3416, 0, 3148, +3416, 0, 3148, +3416, 0, 3148, +3416, 0, 3147, +3416, 0, 3147, +3416, 0, 3146, +3416, 0, 3145, +3416, 0, 3144, +3416, 0, 3142, +3416, 0, 3140, +3416, 0, 3136, +3416, 0, 3132, +3416, 0, 3126, +3416, 0, 3118, +3416, 0, 3106, +3416, 0, 3091, +3416, 0, 3070, +3416, 0, 3039, +3416, 0, 2996, +3416, 0, 2929, +3416, 0, 2822, +3416, 0, 2621, +3416, 0, 2011, +3416, 0, 0, +3416, 0, 0, +3416, 2744, 0, +3548, 3265, 0, +3680, 3559, 0, +3812, 3783, 0, +3913, 3944, 0, +3995, 4076, 0, +4087, 4095, 0, +3548, 0, 3280, +3548, 0, 3280, +3548, 0, 3280, +3548, 0, 3279, +3548, 0, 3279, +3548, 0, 3278, +3548, 0, 3278, +3548, 0, 3277, +3548, 0, 3275, +3548, 0, 3273, +3548, 0, 3271, +3548, 0, 3268, +3548, 0, 3263, +3548, 0, 3257, +3548, 0, 3249, +3548, 0, 3238, +3548, 0, 3222, +3548, 0, 3201, +3548, 0, 3171, +3548, 0, 3126, +3548, 0, 3060, +3548, 0, 2952, +3548, 0, 2751, +3548, 0, 2130, +3548, 0, 0, +3548, 0, 0, +3548, 2875, 0, +3680, 3396, 0, +3812, 3691, 0, +3944, 3915, 0, +4045, 4076, 0, +4095, 4095, 0, +3680, 0, 3411, +3680, 0, 3411, +3680, 0, 3411, +3680, 0, 3411, +3680, 0, 3411, +3680, 0, 3410, +3680, 0, 3410, +3680, 0, 3409, +3680, 0, 3408, +3680, 0, 3407, +3680, 0, 3405, +3680, 0, 3402, +3680, 0, 3399, +3680, 0, 3395, +3680, 0, 3388, +3680, 0, 3380, +3680, 0, 3369, +3680, 0, 3354, +3680, 0, 3332, +3680, 0, 3302, +3680, 0, 3258, +3680, 0, 3191, +3680, 0, 3083, +3680, 0, 2881, +3680, 0, 2257, +3680, 0, 0, +3680, 0, 0, +3680, 3006, 0, +3812, 3528, 0, +3944, 3823, 0, +4076, 4047, 0, +4095, 4095, 0, +3812, 0, 3543, +3812, 0, 3543, +3812, 0, 3543, +3812, 0, 3543, +3812, 0, 3543, +3812, 0, 3543, +3812, 0, 3542, +3812, 0, 3541, +3812, 0, 3541, +3812, 0, 3540, +3812, 0, 3538, +3812, 0, 3537, +3812, 0, 3534, +3812, 0, 3531, +3812, 0, 3526, +3812, 0, 3520, +3812, 0, 3512, +3812, 0, 3501, +3812, 0, 3485, +3812, 0, 3464, +3812, 0, 3433, +3812, 0, 3389, +3812, 0, 3322, +3812, 0, 3214, +3812, 0, 3012, +3812, 0, 2382, +3812, 0, 0, +3812, 0, 0, +3812, 3138, 0, +3944, 3660, 0, +4076, 3955, 0, +4095, 4095, 0, +3944, 0, 3675, +3944, 0, 3675, +3944, 0, 3675, +3944, 0, 3675, +3944, 0, 3674, +3944, 0, 3674, +3944, 0, 3674, +3944, 0, 3674, +3944, 0, 3673, +3944, 0, 3672, +3944, 0, 3671, +3944, 0, 3670, +3944, 0, 3668, +3944, 0, 3666, +3944, 0, 3662, +3944, 0, 3658, +3944, 0, 3652, +3944, 0, 3644, +3944, 0, 3632, +3944, 0, 3617, +3944, 0, 3595, +3944, 0, 3565, +3944, 0, 3521, +3944, 0, 3454, +3944, 0, 3346, +3944, 0, 3143, +3944, 0, 2508, +3944, 0, 0, +3944, 0, 0, +3944, 3270, 0, +4076, 3792, 0, +4095, 4087, 0, +4076, 0, 3807, +4076, 0, 3807, +4076, 0, 3807, +4076, 0, 3807, +4076, 0, 3807, +4076, 0, 3806, +4076, 0, 3806, +4076, 0, 3806, +4076, 0, 3805, +4076, 0, 3805, +4076, 0, 3804, +4076, 0, 3803, +4076, 0, 3802, +4076, 0, 3800, +4076, 0, 3797, +4076, 0, 3794, +4076, 0, 3790, +4076, 0, 3784, +4076, 0, 3775, +4076, 0, 3764, +4076, 0, 3749, +4076, 0, 3727, +4076, 0, 3696, +4076, 0, 3652, +4076, 0, 3585, +4076, 0, 3477, +4076, 0, 3273, +4076, 0, 2635, +4076, 0, 0, +4076, 0, 0, +4076, 3402, 0, +4095, 3925, 0, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3938, +4095, 0, 3938, +4095, 0, 3938, +4095, 0, 3937, +4095, 0, 3937, +4095, 0, 3936, +4095, 0, 3935, +4095, 0, 3934, +4095, 0, 3932, +4095, 0, 3929, +4095, 0, 3926, +4095, 0, 3922, +4095, 0, 3916, +4095, 0, 3908, +4095, 0, 3896, +4095, 0, 3881, +4095, 0, 3859, +4095, 0, 3829, +4095, 0, 3784, +4095, 0, 3717, +4095, 0, 3609, +4095, 0, 3405, +4095, 0, 2767, +4095, 0, 0, +4095, 0, 0, +4095, 3534, 0, +0, 667, 888, +0, 719, 888, +0, 781, 888, +0, 852, 888, +0, 888, 838, +0, 888, 697, +0, 888, 392, +0, 1025, 0, +0, 1160, 0, +431, 1295, 0, +803, 1429, 0, +1057, 1563, 0, +1262, 1696, 0, +1442, 1828, 0, +1607, 1961, 0, +1763, 2094, 0, +1911, 2226, 0, +2055, 2358, 0, +2196, 2491, 0, +2335, 2623, 0, +2472, 2755, 0, +2607, 2887, 0, +2742, 3019, 0, +2876, 3152, 0, +3009, 3284, 0, +3143, 3416, 0, +3276, 3548, 0, +3408, 3680, 0, +3541, 3812, 0, +3673, 3944, 0, +3805, 4076, 0, +3938, 4095, 0, +0, 608, 888, +0, 678, 882, +0, 745, 882, +0, 822, 882, +0, 882, 855, +0, 882, 719, +0, 882, 436, +0, 1020, 0, +0, 1157, 0, +529, 1292, 0, +849, 1427, 0, +1084, 1561, 0, +1279, 1695, 0, +1454, 1828, 0, +1615, 1961, 0, +1768, 2093, 0, +1915, 2226, 0, +2058, 2358, 0, +2199, 2491, 0, +2336, 2623, 0, +2473, 2755, 0, +2608, 2887, 0, +2742, 3019, 0, +2877, 3152, 0, +3010, 3283, 0, +3143, 3416, 0, +3276, 3548, 0, +3408, 3680, 0, +3541, 3812, 0, +3673, 3944, 0, +3805, 4076, 0, +3938, 4095, 0, +0, 515, 888, +0, 599, 882, +0, 691, 873, +0, 776, 873, +0, 870, 873, +0, 873, 749, +0, 873, 488, +0, 1014, 0, +214, 1152, 0, +635, 1289, 0, +904, 1424, 0, +1118, 1559, 0, +1302, 1693, 0, +1469, 1827, 0, +1626, 1960, 0, +1776, 2093, 0, +1921, 2225, 0, +2062, 2358, 0, +2202, 2490, 0, +2338, 2623, 0, +2475, 2755, 0, +2609, 2887, 0, +2743, 3019, 0, +2877, 3152, 0, +3010, 3283, 0, +3143, 3416, 0, +3276, 3548, 0, +3409, 3680, 0, +3541, 3812, 0, +3673, 3944, 0, +3805, 4076, 0, +3938, 4095, 0, +0, 350, 888, +0, 466, 882, +0, 585, 873, +166, 708, 862, +166, 815, 862, +166, 862, 784, +166, 862, 550, +0, 1005, 0, +455, 1146, 0, +746, 1284, 0, +969, 1421, 0, +1159, 1557, 0, +1330, 1691, 0, +1489, 1825, 0, +1640, 1959, 0, +1786, 2092, 0, +1928, 2225, 0, +2068, 2357, 0, +2206, 2490, 0, +2341, 2622, 0, +2477, 2755, 0, +2611, 2887, 0, +2745, 3019, 0, +2878, 3151, 0, +3011, 3283, 0, +3144, 3416, 0, +3277, 3548, 0, +3409, 3680, 0, +3541, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3938, 4095, 0, +0, 0, 888, +0, 190, 882, +0, 390, 873, +166, 567, 862, +412, 730, 846, +412, 846, 828, +412, 846, 622, +397, 994, 298, +655, 1137, 80, +862, 1278, 0, +1043, 1416, 0, +1209, 1553, 0, +1365, 1689, 0, +1514, 1823, 0, +1658, 1958, 0, +1799, 2091, 0, +1938, 2224, 0, +2075, 2357, 0, +2211, 2489, 0, +2346, 2622, 0, +2480, 2755, 0, +2613, 2887, 0, +2746, 3019, 0, +2879, 3151, 0, +3012, 3283, 0, +3144, 3416, 0, +3277, 3548, 0, +3409, 3680, 0, +3542, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3938, 4095, 0, +0, 0, 888, +0, 0, 882, +0, 0, 873, +166, 264, 862, +412, 541, 846, +614, 758, 824, +614, 824, 702, +673, 978, 544, +831, 1126, 430, +982, 1270, 212, +1127, 1410, 0, +1269, 1549, 0, +1408, 1685, 0, +1545, 1821, 0, +1681, 1956, 0, +1816, 2089, 0, +1951, 2223, 0, +2084, 2356, 0, +2218, 2489, 0, +2351, 2621, 0, +2484, 2754, 0, +2616, 2887, 0, +2748, 3019, 0, +2881, 3151, 0, +3013, 3283, 0, +3145, 3416, 0, +3278, 3548, 0, +3410, 3680, 0, +3542, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3938, 4095, 0, +392, 0, 888, +436, 0, 882, +488, 0, 873, +550, 166, 862, +622, 412, 846, +702, 614, 824, +792, 792, 792, +890, 956, 746, +994, 1110, 676, +1104, 1258, 562, +1219, 1402, 344, +1338, 1543, 0, +1460, 1681, 0, +1585, 1817, 0, +1711, 1953, 0, +1838, 2087, 0, +1967, 2221, 0, +2096, 2355, 0, +2227, 2488, 0, +2357, 2621, 0, +2489, 2754, 0, +2620, 2886, 0, +2751, 3018, 0, +2883, 3151, 0, +3015, 3283, 0, +3147, 3415, 0, +3279, 3548, 0, +3411, 3680, 0, +3543, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3939, 4095, 0, +811, 0, 1025, +829, 0, 1020, +852, 0, 1014, +881, 0, 1005, +917, 298, 994, +960, 544, 978, +956, 746, 890, +956, 834, 746, +1110, 1092, 676, +1211, 1258, 562, +1304, 1402, 344, +1405, 1543, 0, +1512, 1681, 0, +1625, 1817, 0, +1742, 1953, 0, +1862, 2087, 0, +1985, 2221, 0, +2110, 2355, 0, +2237, 2488, 0, +2365, 2621, 0, +2494, 2754, 0, +2624, 2886, 0, +2754, 3018, 0, +2885, 3151, 0, +3016, 3283, 0, +3148, 3415, 0, +3280, 3548, 0, +3411, 3680, 0, +3543, 3812, 0, +3675, 3944, 0, +3807, 4076, 0, +3939, 4095, 0, +1079, 0, 1160, +1089, 0, 1157, +1102, 0, 1152, +1119, 0, 1146, +1137, 80, 1134, +1126, 430, 1079, +1110, 676, 994, +1110, 676, 805, +1110, 886, 676, +1258, 1181, 562, +1398, 1402, 344, +1482, 1543, 0, +1574, 1681, 0, +1673, 1817, 0, +1779, 1953, 0, +1891, 2087, 0, +2008, 2221, 0, +2127, 2355, 0, +2250, 2488, 0, +2375, 2621, 0, +2502, 2754, 0, +2630, 2886, 0, +2759, 3018, 0, +2889, 3151, 0, +3019, 3283, 0, +3150, 3415, 0, +3281, 3548, 0, +3412, 3680, 0, +3544, 3812, 0, +3676, 3944, 0, +3807, 4076, 0, +3939, 4095, 0, +1292, 0, 1295, +1292, 0, 1286, +1289, 0, 1271, +1284, 0, 1249, +1278, 0, 1218, +1270, 212, 1172, +1258, 562, 1104, +1258, 562, 963, +1258, 562, 661, +1258, 946, 562, +1402, 1277, 344, +1543, 1516, 0, +1645, 1681, 0, +1732, 1817, 0, +1826, 1953, 0, +1928, 2087, 0, +2036, 2221, 0, +2150, 2355, 0, +2267, 2488, 0, +2388, 2621, 0, +2512, 2754, 0, +2637, 2886, 0, +2764, 3018, 0, +2893, 3151, 0, +3022, 3283, 0, +3152, 3415, 0, +3283, 3548, 0, +3414, 3680, 0, +3545, 3812, 0, +3676, 3944, 0, +3808, 4076, 0, +3940, 4095, 0, +1429, 0, 1376, +1427, 0, 1366, +1424, 0, 1353, +1421, 0, 1335, +1416, 0, 1310, +1410, 0, 1273, +1402, 344, 1219, +1402, 344, 1114, +1402, 344, 919, +1402, 344, 345, +1402, 1017, 344, +1543, 1381, 0, +1681, 1631, 0, +1799, 1817, 0, +1882, 1953, 0, +1973, 2087, 0, +2072, 2221, 0, +2178, 2355, 0, +2289, 2488, 0, +2405, 2621, 0, +2525, 2754, 0, +2647, 2886, 0, +2772, 3018, 0, +2898, 3151, 0, +3026, 3283, 0, +3155, 3415, 0, +3285, 3548, 0, +3415, 3680, 0, +3546, 3812, 0, +3677, 3944, 0, +3808, 4076, 0, +3940, 4095, 0, +1563, 0, 1463, +1561, 0, 1456, +1559, 0, 1445, +1557, 0, 1430, +1553, 0, 1409, +1549, 0, 1380, +1543, 0, 1338, +1543, 0, 1259, +1543, 0, 1127, +1543, 0, 852, +1543, 172, 0, +1543, 1096, 0, +1681, 1489, 0, +1817, 1750, 0, +1947, 1953, 0, +2027, 2087, 0, +2116, 2221, 0, +2213, 2355, 0, +2317, 2488, 0, +2427, 2621, 0, +2541, 2754, 0, +2660, 2886, 0, +2782, 3018, 0, +2906, 3151, 0, +3032, 3283, 0, +3160, 3415, 0, +3288, 3548, 0, +3418, 3680, 0, +3548, 3812, 0, +3679, 3944, 0, +3810, 4076, 0, +3941, 4095, 0, +1696, 0, 1559, +1695, 0, 1552, +1693, 0, 1544, +1691, 0, 1532, +1689, 0, 1515, +1685, 0, 1492, +1681, 0, 1460, +1681, 0, 1401, +1681, 0, 1308, +1681, 0, 1142, +1681, 0, 742, +1681, 0, 0, +1681, 1184, 0, +1817, 1604, 0, +1953, 1872, 0, +2087, 2085, 0, +2169, 2221, 0, +2256, 2355, 0, +2352, 2488, 0, +2454, 2621, 0, +2563, 2754, 0, +2677, 2886, 0, +2794, 3018, 0, +2916, 3151, 0, +3039, 3283, 0, +3165, 3415, 0, +3292, 3548, 0, +3421, 3680, 0, +3550, 3812, 0, +3680, 3944, 0, +3811, 4076, 0, +3942, 4095, 0, +1828, 0, 1661, +1828, 0, 1656, +1827, 0, 1650, +1825, 0, 1640, +1823, 0, 1627, +1821, 0, 1609, +1817, 0, 1585, +1817, 0, 1540, +1817, 0, 1474, +1817, 0, 1366, +1817, 0, 1164, +1817, 0, 536, +1817, 0, 0, +1817, 1281, 0, +1953, 1722, 0, +2087, 1996, 0, +2221, 2212, 0, +2308, 2355, 0, +2394, 2488, 0, +2488, 2621, 0, +2590, 2754, 0, +2698, 2886, 0, +2811, 3018, 0, +2928, 3151, 0, +3049, 3283, 0, +3173, 3415, 0, +3298, 3548, 0, +3425, 3680, 0, +3553, 3812, 0, +3683, 3944, 0, +3812, 4076, 0, +3943, 4095, 0, +1961, 0, 1770, +1961, 0, 1766, +1960, 0, 1761, +1959, 0, 1754, +1958, 0, 1743, +1956, 0, 1730, +1953, 0, 1711, +1953, 0, 1678, +1953, 0, 1629, +1953, 0, 1555, +1953, 0, 1433, +1953, 0, 1190, +1953, 0, 0, +1953, 0, 0, +1953, 1385, 0, +2087, 1843, 0, +2221, 2123, 0, +2355, 2340, 0, +2445, 2488, 0, +2530, 2621, 0, +2624, 2754, 0, +2725, 2886, 0, +2832, 3018, 0, +2945, 3151, 0, +3062, 3283, 0, +3182, 3415, 0, +3305, 3548, 0, +3431, 3680, 0, +3558, 3812, 0, +3686, 3944, 0, +3815, 4076, 0, +3945, 4095, 0, +2094, 0, 1884, +2093, 0, 1881, +2093, 0, 1877, +2092, 0, 1871, +2091, 0, 1863, +2089, 0, 1853, +2087, 0, 1838, +2087, 0, 1813, +2087, 0, 1778, +2087, 0, 1726, +2087, 0, 1646, +2087, 0, 1509, +2087, 0, 1224, +2087, 0, 0, +2087, 0, 0, +2087, 1494, 0, +2221, 1967, 0, +2355, 2251, 0, +2488, 2470, 0, +2581, 2621, 0, +2666, 2754, 0, +2759, 2886, 0, +2859, 3018, 0, +2966, 3151, 0, +3078, 3283, 0, +3195, 3415, 0, +3315, 3548, 0, +3438, 3680, 0, +3563, 3812, 0, +3690, 3944, 0, +3818, 4076, 0, +3947, 4095, 0, +2226, 0, 2002, +2226, 0, 1999, +2225, 0, 1996, +2225, 0, 1992, +2224, 0, 1986, +2223, 0, 1978, +2221, 0, 1967, +2221, 0, 1948, +2221, 0, 1922, +2221, 0, 1885, +2221, 0, 1830, +2221, 0, 1744, +2221, 0, 1596, +2221, 0, 1264, +2221, 0, 0, +2221, 0, 0, +2221, 1608, 0, +2355, 2093, 0, +2488, 2379, 0, +2621, 2600, 0, +2716, 2754, 0, +2800, 2886, 0, +2892, 3018, 0, +2993, 3151, 0, +3099, 3283, 0, +3211, 3415, 0, +3328, 3548, 0, +3448, 3680, 0, +3571, 3812, 0, +3696, 3944, 0, +3822, 4076, 0, +3951, 4095, 0, +2358, 0, 2123, +2358, 0, 2121, +2358, 0, 2119, +2357, 0, 2115, +2357, 0, 2111, +2356, 0, 2105, +2355, 0, 2096, +2355, 0, 2083, +2355, 0, 2063, +2355, 0, 2037, +2355, 0, 1998, +2355, 0, 1940, +2355, 0, 1849, +2355, 0, 1689, +2355, 0, 1313, +2355, 0, 0, +2355, 0, 0, +2355, 1727, 0, +2488, 2221, 0, +2621, 2509, 0, +2754, 2731, 0, +2850, 2886, 0, +2934, 3018, 0, +3026, 3151, 0, +3126, 3283, 0, +3232, 3415, 0, +3344, 3548, 0, +3460, 3680, 0, +3580, 3812, 0, +3703, 3944, 0, +3828, 4076, 0, +3955, 4095, 0, +2491, 0, 2247, +2491, 0, 2245, +2490, 0, 2243, +2490, 0, 2241, +2489, 0, 2238, +2489, 0, 2233, +2488, 0, 2227, +2488, 0, 2217, +2488, 0, 2202, +2488, 0, 2183, +2488, 0, 2155, +2488, 0, 2115, +2488, 0, 2055, +2488, 0, 1960, +2488, 0, 1791, +2488, 0, 1373, +2488, 0, 0, +2488, 0, 0, +2488, 1848, 0, +2621, 2349, 0, +2754, 2640, 0, +2886, 2862, 0, +2984, 3018, 0, +3067, 3151, 0, +3159, 3283, 0, +3259, 3415, 0, +3365, 3548, 0, +3477, 3680, 0, +3593, 3812, 0, +3713, 3944, 0, +3835, 4076, 0, +3961, 4095, 0, +2623, 0, 2372, +2623, 0, 2372, +2623, 0, 2370, +2622, 0, 2368, +2622, 0, 2366, +2621, 0, 2362, +2621, 0, 2357, +2621, 0, 2350, +2621, 0, 2339, +2621, 0, 2325, +2621, 0, 2304, +2621, 0, 2276, +2621, 0, 2235, +2621, 0, 2173, +2621, 0, 2075, +2621, 0, 1899, +2621, 0, 1441, +2621, 0, 0, +2621, 0, 0, +2621, 1972, 0, +2754, 2479, 0, +2886, 2770, 0, +3018, 2992, 0, +3117, 3151, 0, +3200, 3283, 0, +3292, 3415, 0, +3392, 3548, 0, +3497, 3680, 0, +3609, 3812, 0, +3725, 3944, 0, +3845, 4076, 0, +3968, 4095, 0, +2755, 0, 2500, +2755, 0, 2499, +2755, 0, 2498, +2755, 0, 2497, +2755, 0, 2495, +2754, 0, 2492, +2754, 0, 2489, +2754, 0, 2483, +2754, 0, 2475, +2754, 0, 2464, +2754, 0, 2450, +2754, 0, 2429, +2754, 0, 2400, +2754, 0, 2358, +2754, 0, 2295, +2754, 0, 2195, +2754, 0, 2012, +2754, 0, 1521, +2754, 0, 0, +2754, 0, 0, +2754, 2099, 0, +2886, 2609, 0, +3018, 2901, 0, +3151, 3124, 0, +3250, 3283, 0, +3333, 3415, 0, +3425, 3548, 0, +3524, 3680, 0, +3630, 3812, 0, +3741, 3944, 0, +3858, 4076, 0, +3977, 4095, 0, +2887, 0, 2628, +2887, 0, 2628, +2887, 0, 2627, +2887, 0, 2626, +2887, 0, 2625, +2887, 0, 2623, +2886, 0, 2620, +2886, 0, 2616, +2886, 0, 2610, +2886, 0, 2602, +2886, 0, 2591, +2886, 0, 2576, +2886, 0, 2555, +2886, 0, 2526, +2886, 0, 2483, +2886, 0, 2419, +2886, 0, 2317, +2886, 0, 2129, +2886, 0, 1606, +2886, 0, 0, +2886, 0, 0, +2886, 2226, 0, +3018, 2739, 0, +3151, 3032, 0, +3283, 3256, 0, +3383, 3415, 0, +3466, 3548, 0, +3557, 3680, 0, +3657, 3812, 0, +3762, 3944, 0, +3874, 4076, 0, +3990, 4095, 0, +3019, 0, 2758, +3019, 0, 2757, +3019, 0, 2757, +3019, 0, 2756, +3019, 0, 2755, +3019, 0, 2753, +3018, 0, 2751, +3018, 0, 2748, +3018, 0, 2744, +3018, 0, 2738, +3018, 0, 2730, +3018, 0, 2719, +3018, 0, 2703, +3018, 0, 2683, +3018, 0, 2653, +3018, 0, 2610, +3018, 0, 2545, +3018, 0, 2441, +3018, 0, 2249, +3018, 0, 1700, +3018, 0, 0, +3018, 0, 0, +3018, 2354, 0, +3151, 2871, 0, +3283, 3164, 0, +3415, 3387, 0, +3515, 3548, 0, +3598, 3680, 0, +3690, 3812, 0, +3789, 3944, 0, +3895, 4076, 0, +4006, 4095, 0, +3152, 0, 2888, +3152, 0, 2888, +3152, 0, 2887, +3151, 0, 2886, +3151, 0, 2886, +3151, 0, 2885, +3151, 0, 2883, +3151, 0, 2881, +3151, 0, 2877, +3151, 0, 2873, +3151, 0, 2867, +3151, 0, 2859, +3151, 0, 2848, +3151, 0, 2833, +3151, 0, 2812, +3151, 0, 2782, +3151, 0, 2738, +3151, 0, 2673, +3151, 0, 2568, +3151, 0, 2373, +3151, 0, 1802, +3151, 0, 0, +3151, 0, 0, +3151, 2484, 0, +3283, 3001, 0, +3415, 3295, 0, +3548, 3519, 0, +3648, 3680, 0, +3731, 3812, 0, +3822, 3944, 0, +3921, 4076, 0, +4027, 4095, 0, +3284, 0, 3018, +3283, 0, 3018, +3283, 0, 3018, +3283, 0, 3017, +3283, 0, 3016, +3283, 0, 3016, +3283, 0, 3015, +3283, 0, 3013, +3283, 0, 3010, +3283, 0, 3007, +3283, 0, 3003, +3283, 0, 2997, +3283, 0, 2988, +3283, 0, 2977, +3283, 0, 2962, +3283, 0, 2941, +3283, 0, 2911, +3283, 0, 2867, +3283, 0, 2801, +3283, 0, 2695, +3283, 0, 2498, +3283, 0, 1908, +3283, 0, 0, +3283, 0, 0, +3283, 2614, 0, +3415, 3133, 0, +3548, 3427, 0, +3680, 3651, 0, +3781, 3812, 0, +3863, 3944, 0, +3954, 4076, 0, +4054, 4095, 0, +3416, 0, 3149, +3416, 0, 3149, +3416, 0, 3149, +3416, 0, 3148, +3416, 0, 3148, +3416, 0, 3147, +3415, 0, 3147, +3415, 0, 3145, +3415, 0, 3144, +3415, 0, 3141, +3415, 0, 3138, +3415, 0, 3133, +3415, 0, 3127, +3415, 0, 3119, +3415, 0, 3108, +3415, 0, 3093, +3415, 0, 3071, +3415, 0, 3041, +3415, 0, 2997, +3415, 0, 2931, +3415, 0, 2824, +3415, 0, 2625, +3415, 0, 2026, +3415, 0, 0, +3415, 0, 0, +3415, 2745, 0, +3548, 3265, 0, +3680, 3559, 0, +3812, 3783, 0, +3913, 3944, 0, +3995, 4076, 0, +4087, 4095, 0, +3548, 0, 3280, +3548, 0, 3280, +3548, 0, 3280, +3548, 0, 3280, +3548, 0, 3280, +3548, 0, 3279, +3548, 0, 3279, +3548, 0, 3278, +3548, 0, 3276, +3548, 0, 3274, +3548, 0, 3272, +3548, 0, 3269, +3548, 0, 3264, +3548, 0, 3258, +3548, 0, 3250, +3548, 0, 3239, +3548, 0, 3223, +3548, 0, 3202, +3548, 0, 3172, +3548, 0, 3128, +3548, 0, 3061, +3548, 0, 2954, +3548, 0, 2754, +3548, 0, 2141, +3548, 0, 0, +3548, 0, 0, +3548, 2876, 0, +3680, 3396, 0, +3812, 3691, 0, +3944, 3915, 0, +4045, 4076, 0, +4095, 4095, 0, +3680, 0, 3412, +3680, 0, 3412, +3680, 0, 3412, +3680, 0, 3412, +3680, 0, 3411, +3680, 0, 3411, +3680, 0, 3411, +3680, 0, 3410, +3680, 0, 3409, +3680, 0, 3407, +3680, 0, 3406, +3680, 0, 3403, +3680, 0, 3400, +3680, 0, 3395, +3680, 0, 3389, +3680, 0, 3381, +3680, 0, 3370, +3680, 0, 3354, +3680, 0, 3333, +3680, 0, 3303, +3680, 0, 3258, +3680, 0, 3192, +3680, 0, 3084, +3680, 0, 2883, +3680, 0, 2266, +3680, 0, 0, +3680, 0, 0, +3680, 3007, 0, +3812, 3528, 0, +3944, 3823, 0, +4076, 4047, 0, +4095, 4095, 0, +3812, 0, 3544, +3812, 0, 3544, +3812, 0, 3543, +3812, 0, 3543, +3812, 0, 3543, +3812, 0, 3543, +3812, 0, 3543, +3812, 0, 3542, +3812, 0, 3541, +3812, 0, 3540, +3812, 0, 3539, +3812, 0, 3537, +3812, 0, 3534, +3812, 0, 3531, +3812, 0, 3527, +3812, 0, 3521, +3812, 0, 3513, +3812, 0, 3501, +3812, 0, 3486, +3812, 0, 3464, +3812, 0, 3434, +3812, 0, 3390, +3812, 0, 3323, +3812, 0, 3215, +3812, 0, 3014, +3812, 0, 2389, +3812, 0, 0, +3812, 0, 0, +3812, 3139, 0, +3944, 3660, 0, +4076, 3955, 0, +4095, 4095, 0, +3944, 0, 3675, +3944, 0, 3675, +3944, 0, 3675, +3944, 0, 3675, +3944, 0, 3675, +3944, 0, 3675, +3944, 0, 3674, +3944, 0, 3674, +3944, 0, 3673, +3944, 0, 3673, +3944, 0, 3672, +3944, 0, 3670, +3944, 0, 3668, +3944, 0, 3666, +3944, 0, 3663, +3944, 0, 3658, +3944, 0, 3652, +3944, 0, 3644, +3944, 0, 3633, +3944, 0, 3617, +3944, 0, 3596, +3944, 0, 3565, +3944, 0, 3521, +3944, 0, 3454, +3944, 0, 3346, +3944, 0, 3144, +3944, 0, 2513, +3944, 0, 0, +3944, 0, 0, +3944, 3270, 0, +4076, 3792, 0, +4095, 4087, 0, +4076, 0, 3807, +4076, 0, 3807, +4076, 0, 3807, +4076, 0, 3807, +4076, 0, 3807, +4076, 0, 3807, +4076, 0, 3806, +4076, 0, 3806, +4076, 0, 3805, +4076, 0, 3805, +4076, 0, 3804, +4076, 0, 3803, +4076, 0, 3802, +4076, 0, 3800, +4076, 0, 3798, +4076, 0, 3794, +4076, 0, 3790, +4076, 0, 3784, +4076, 0, 3776, +4076, 0, 3764, +4076, 0, 3749, +4076, 0, 3727, +4076, 0, 3697, +4076, 0, 3653, +4076, 0, 3586, +4076, 0, 3477, +4076, 0, 3274, +4076, 0, 2639, +4076, 0, 0, +4076, 0, 0, +4076, 3402, 0, +4095, 3925, 0, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3938, +4095, 0, 3938, +4095, 0, 3938, +4095, 0, 3937, +4095, 0, 3937, +4095, 0, 3935, +4095, 0, 3934, +4095, 0, 3932, +4095, 0, 3930, +4095, 0, 3927, +4095, 0, 3922, +4095, 0, 3916, +4095, 0, 3908, +4095, 0, 3896, +4095, 0, 3881, +4095, 0, 3859, +4095, 0, 3829, +4095, 0, 3784, +4095, 0, 3718, +4095, 0, 3609, +4095, 0, 3406, +4095, 0, 2770, +4095, 0, 0, +4095, 0, 0, +4095, 3534, 0, +0, 792, 1025, +0, 832, 1025, +0, 881, 1025, +0, 939, 1025, +0, 1006, 1025, +0, 1025, 957, +0, 1025, 811, +0, 1025, 488, +0, 1160, 0, +0, 1295, 0, +471, 1429, 0, +897, 1563, 0, +1167, 1696, 0, +1381, 1828, 0, +1565, 1961, 0, +1733, 2094, 0, +1890, 2226, 0, +2040, 2358, 0, +2185, 2491, 0, +2327, 2623, 0, +2466, 2755, 0, +2603, 2887, 0, +2738, 3019, 0, +2873, 3152, 0, +3008, 3284, 0, +3141, 3416, 0, +3275, 3548, 0, +3408, 3680, 0, +3540, 3812, 0, +3673, 3944, 0, +3805, 4076, 0, +3938, 4095, 0, +0, 748, 1025, +0, 800, 1020, +0, 852, 1020, +0, 914, 1020, +0, 985, 1020, +0, 1020, 970, +0, 1020, 829, +0, 1020, 524, +0, 1157, 0, +0, 1292, 0, +562, 1427, 0, +935, 1561, 0, +1188, 1695, 0, +1394, 1828, 0, +1574, 1961, 0, +1739, 2093, 0, +1894, 2226, 0, +2043, 2358, 0, +2187, 2491, 0, +2328, 2623, 0, +2467, 2755, 0, +2604, 2887, 0, +2739, 3019, 0, +2874, 3152, 0, +3008, 3283, 0, +3141, 3416, 0, +3275, 3548, 0, +3408, 3680, 0, +3540, 3812, 0, +3673, 3944, 0, +3805, 4076, 0, +3938, 4095, 0, +0, 681, 1025, +0, 740, 1020, +0, 810, 1014, +0, 877, 1014, +0, 954, 1014, +0, 1014, 987, +0, 1014, 852, +0, 1014, 568, +0, 1152, 0, +9, 1289, 0, +662, 1424, 0, +981, 1559, 0, +1216, 1693, 0, +1412, 1827, 0, +1586, 1960, 0, +1748, 2093, 0, +1900, 2225, 0, +2047, 2358, 0, +2190, 2490, 0, +2331, 2623, 0, +2469, 2755, 0, +2605, 2887, 0, +2740, 3019, 0, +2875, 3152, 0, +3008, 3283, 0, +3142, 3416, 0, +3275, 3548, 0, +3408, 3680, 0, +3541, 3812, 0, +3673, 3944, 0, +3805, 4076, 0, +3938, 4095, 0, +0, 573, 1025, +0, 647, 1020, +0, 731, 1014, +0, 823, 1005, +0, 908, 1005, +0, 1002, 1005, +0, 1005, 881, +0, 1005, 620, +0, 1146, 0, +346, 1284, 0, +767, 1421, 0, +1037, 1557, 0, +1249, 1691, 0, +1434, 1825, 0, +1601, 1959, 0, +1758, 2092, 0, +1908, 2225, 0, +2053, 2357, 0, +2195, 2490, 0, +2334, 2622, 0, +2471, 2755, 0, +2607, 2887, 0, +2741, 3019, 0, +2876, 3151, 0, +3009, 3283, 0, +3142, 3416, 0, +3275, 3548, 0, +3408, 3680, 0, +3541, 3812, 0, +3673, 3944, 0, +3805, 4076, 0, +3938, 4095, 0, +0, 371, 1025, +0, 482, 1020, +0, 598, 1014, +0, 717, 1005, +298, 840, 994, +298, 947, 994, +298, 994, 917, +298, 994, 682, +81, 1137, 80, +587, 1278, 0, +878, 1416, 0, +1102, 1553, 0, +1291, 1689, 0, +1462, 1823, 0, +1621, 1958, 0, +1772, 2091, 0, +1918, 2224, 0, +2060, 2357, 0, +2200, 2489, 0, +2337, 2622, 0, +2474, 2755, 0, +2609, 2887, 0, +2743, 3019, 0, +2877, 3151, 0, +3010, 3283, 0, +3143, 3416, 0, +3276, 3548, 0, +3409, 3680, 0, +3541, 3812, 0, +3673, 3944, 0, +3805, 4076, 0, +3938, 4095, 0, +0, 0, 1025, +0, 81, 1020, +0, 323, 1014, +0, 523, 1005, +298, 699, 994, +544, 862, 978, +544, 978, 960, +544, 978, 754, +529, 1126, 430, +787, 1270, 212, +994, 1410, 0, +1176, 1549, 0, +1341, 1685, 0, +1497, 1821, 0, +1646, 1956, 0, +1790, 2089, 0, +1931, 2223, 0, +2070, 2356, 0, +2207, 2489, 0, +2343, 2621, 0, +2478, 2754, 0, +2612, 2887, 0, +2745, 3019, 0, +2879, 3151, 0, +3011, 3283, 0, +3144, 3416, 0, +3277, 3548, 0, +3409, 3680, 0, +3541, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3938, 4095, 0, +0, 0, 1025, +0, 0, 1020, +0, 0, 1014, +0, 0, 1005, +298, 397, 994, +544, 673, 978, +746, 890, 956, +746, 956, 834, +805, 1110, 676, +963, 1258, 562, +1114, 1402, 344, +1259, 1543, 0, +1401, 1681, 0, +1540, 1817, 0, +1678, 1953, 0, +1813, 2087, 0, +1948, 2221, 0, +2083, 2355, 0, +2217, 2488, 0, +2350, 2621, 0, +2483, 2754, 0, +2616, 2886, 0, +2748, 3018, 0, +2881, 3151, 0, +3013, 3283, 0, +3145, 3415, 0, +3278, 3548, 0, +3410, 3680, 0, +3542, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3938, 4095, 0, +488, 0, 1025, +524, 0, 1020, +568, 0, 1014, +620, 0, 1005, +682, 298, 994, +754, 544, 978, +834, 746, 956, +924, 924, 924, +1021, 1088, 878, +1126, 1242, 809, +1236, 1390, 695, +1351, 1534, 476, +1470, 1674, 0, +1592, 1813, 0, +1716, 1950, 0, +1843, 2085, 0, +1970, 2220, 0, +2099, 2353, 0, +2229, 2487, 0, +2359, 2620, 0, +2490, 2753, 0, +2621, 2886, 0, +2752, 3018, 0, +2883, 3151, 0, +3015, 3283, 0, +3147, 3415, 0, +3279, 3548, 0, +3411, 3680, 0, +3543, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3939, 4095, 0, +929, 0, 1160, +943, 0, 1157, +960, 0, 1152, +983, 0, 1146, +1013, 80, 1137, +1049, 430, 1126, +1092, 676, 1110, +1088, 878, 1021, +1088, 967, 878, +1242, 1225, 809, +1343, 1390, 695, +1437, 1534, 476, +1537, 1674, 0, +1644, 1813, 0, +1757, 1950, 0, +1873, 2085, 0, +1994, 2220, 0, +2117, 2353, 0, +2242, 2487, 0, +2369, 2620, 0, +2497, 2753, 0, +2626, 2886, 0, +2756, 3018, 0, +2887, 3151, 0, +3017, 3283, 0, +3149, 3415, 0, +3280, 3548, 0, +3412, 3680, 0, +3543, 3812, 0, +3675, 3944, 0, +3807, 4076, 0, +3939, 4095, 0, +1204, 0, 1295, +1211, 0, 1292, +1221, 0, 1289, +1235, 0, 1284, +1251, 0, 1278, +1270, 212, 1266, +1258, 562, 1211, +1242, 809, 1126, +1242, 809, 938, +1242, 1018, 809, +1390, 1313, 695, +1531, 1534, 476, +1614, 1674, 0, +1706, 1813, 0, +1806, 1950, 0, +1912, 2085, 0, +2023, 2220, 0, +2140, 2353, 0, +2260, 2487, 0, +2382, 2620, 0, +2507, 2753, 0, +2634, 2886, 0, +2762, 3018, 0, +2891, 3151, 0, +3021, 3283, 0, +3151, 3415, 0, +3282, 3548, 0, +3413, 3680, 0, +3544, 3812, 0, +3676, 3944, 0, +3808, 4076, 0, +3940, 4095, 0, +1419, 0, 1429, +1424, 0, 1427, +1424, 0, 1418, +1421, 0, 1403, +1416, 0, 1381, +1410, 0, 1350, +1402, 344, 1304, +1390, 695, 1236, +1390, 695, 1095, +1390, 695, 793, +1390, 1078, 695, +1534, 1409, 476, +1674, 1648, 0, +1777, 1813, 0, +1864, 1950, 0, +1958, 2085, 0, +2060, 2220, 0, +2168, 2353, 0, +2282, 2487, 0, +2399, 2620, 0, +2521, 2753, 0, +2644, 2886, 0, +2769, 3018, 0, +2896, 3151, 0, +3025, 3283, 0, +3154, 3415, 0, +3284, 3548, 0, +3415, 3680, 0, +3546, 3812, 0, +3677, 3944, 0, +3808, 4076, 0, +3940, 4095, 0, +1563, 0, 1515, +1561, 0, 1508, +1559, 0, 1499, +1557, 0, 1486, +1553, 0, 1467, +1549, 0, 1442, +1543, 0, 1405, +1534, 476, 1351, +1534, 476, 1246, +1534, 476, 1051, +1534, 476, 479, +1534, 1149, 476, +1674, 1512, 0, +1813, 1763, 0, +1931, 1950, 0, +2014, 2085, 0, +2105, 2220, 0, +2204, 2353, 0, +2310, 2487, 0, +2421, 2620, 0, +2537, 2753, 0, +2657, 2886, 0, +2779, 3018, 0, +2904, 3151, 0, +3031, 3283, 0, +3158, 3415, 0, +3287, 3548, 0, +3417, 3680, 0, +3548, 3812, 0, +3678, 3944, 0, +3809, 4076, 0, +3941, 4095, 0, +1696, 0, 1601, +1695, 0, 1596, +1693, 0, 1588, +1691, 0, 1577, +1689, 0, 1562, +1685, 0, 1541, +1681, 0, 1512, +1674, 0, 1470, +1674, 0, 1391, +1674, 0, 1258, +1674, 0, 983, +1674, 313, 0, +1674, 1228, 0, +1813, 1622, 0, +1950, 1882, 0, +2079, 2085, 0, +2159, 2220, 0, +2248, 2353, 0, +2345, 2487, 0, +2449, 2620, 0, +2559, 2753, 0, +2673, 2886, 0, +2792, 3018, 0, +2914, 3151, 0, +3038, 3283, 0, +3164, 3415, 0, +3292, 3548, 0, +3420, 3680, 0, +3550, 3812, 0, +3680, 3944, 0, +3810, 4076, 0, +3942, 4095, 0, +1828, 0, 1696, +1828, 0, 1691, +1827, 0, 1684, +1825, 0, 1676, +1823, 0, 1664, +1821, 0, 1648, +1817, 0, 1625, +1813, 0, 1592, +1813, 0, 1533, +1813, 0, 1440, +1813, 0, 1275, +1813, 0, 874, +1813, 0, 0, +1813, 1317, 0, +1950, 1736, 0, +2085, 2004, 0, +2220, 2217, 0, +2301, 2353, 0, +2388, 2487, 0, +2483, 2620, 0, +2586, 2753, 0, +2695, 2886, 0, +2808, 3018, 0, +2927, 3151, 0, +3047, 3283, 0, +3171, 3415, 0, +3297, 3548, 0, +3425, 3680, 0, +3553, 3812, 0, +3682, 3944, 0, +3812, 4076, 0, +3943, 4095, 0, +1961, 0, 1797, +1961, 0, 1793, +1960, 0, 1789, +1959, 0, 1781, +1958, 0, 1772, +1956, 0, 1759, +1953, 0, 1742, +1950, 0, 1716, +1950, 0, 1672, +1950, 0, 1606, +1950, 0, 1498, +1950, 0, 1295, +1950, 0, 670, +1950, 0, 0, +1950, 1413, 0, +2085, 1854, 0, +2220, 2128, 0, +2353, 2344, 0, +2440, 2487, 0, +2526, 2620, 0, +2620, 2753, 0, +2722, 2886, 0, +2830, 3018, 0, +2943, 3151, 0, +3060, 3283, 0, +3181, 3415, 0, +3305, 3548, 0, +3430, 3680, 0, +3557, 3812, 0, +3686, 3944, 0, +3815, 4076, 0, +3945, 4095, 0, +2094, 0, 1905, +2093, 0, 1902, +2093, 0, 1898, +2092, 0, 1893, +2091, 0, 1885, +2089, 0, 1875, +2087, 0, 1862, +2085, 0, 1843, +2085, 0, 1810, +2085, 0, 1761, +2085, 0, 1687, +2085, 0, 1565, +2085, 0, 1322, +2085, 0, 10, +2085, 0, 0, +2085, 1517, 0, +2220, 1975, 0, +2353, 2255, 0, +2487, 2473, 0, +2577, 2620, 0, +2662, 2753, 0, +2756, 2886, 0, +2857, 3018, 0, +2964, 3151, 0, +3077, 3283, 0, +3194, 3415, 0, +3314, 3548, 0, +3437, 3680, 0, +3563, 3812, 0, +3690, 3944, 0, +3818, 4076, 0, +3947, 4095, 0, +2226, 0, 2018, +2226, 0, 2016, +2225, 0, 2013, +2225, 0, 2009, +2224, 0, 2003, +2223, 0, 1995, +2221, 0, 1985, +2220, 0, 1970, +2220, 0, 1946, +2220, 0, 1910, +2220, 0, 1858, +2220, 0, 1778, +2220, 0, 1642, +2220, 0, 1355, +2220, 0, 0, +2220, 0, 0, +2220, 1626, 0, +2353, 2099, 0, +2487, 2383, 0, +2620, 2602, 0, +2713, 2753, 0, +2798, 2886, 0, +2890, 3018, 0, +2991, 3151, 0, +3098, 3283, 0, +3210, 3415, 0, +3327, 3548, 0, +3447, 3680, 0, +3570, 3812, 0, +3695, 3944, 0, +3822, 4076, 0, +3950, 4095, 0, +2358, 0, 2136, +2358, 0, 2134, +2358, 0, 2132, +2357, 0, 2128, +2357, 0, 2124, +2356, 0, 2118, +2355, 0, 2110, +2353, 0, 2099, +2353, 0, 2081, +2353, 0, 2054, +2353, 0, 2017, +2353, 0, 1962, +2353, 0, 1876, +2353, 0, 1727, +2353, 0, 1396, +2353, 0, 0, +2353, 0, 0, +2353, 1740, 0, +2487, 2226, 0, +2620, 2511, 0, +2753, 2732, 0, +2848, 2886, 0, +2932, 3018, 0, +3025, 3151, 0, +3125, 3283, 0, +3231, 3415, 0, +3343, 3548, 0, +3460, 3680, 0, +3580, 3812, 0, +3703, 3944, 0, +3828, 4076, 0, +3955, 4095, 0, +2491, 0, 2256, +2491, 0, 2255, +2490, 0, 2253, +2490, 0, 2251, +2489, 0, 2247, +2489, 0, 2243, +2488, 0, 2237, +2487, 0, 2229, +2487, 0, 2215, +2487, 0, 2196, +2487, 0, 2169, +2487, 0, 2130, +2487, 0, 2072, +2487, 0, 1981, +2487, 0, 1822, +2487, 0, 1446, +2487, 0, 0, +2487, 0, 0, +2487, 1859, 0, +2620, 2352, 0, +2753, 2641, 0, +2886, 2863, 0, +2982, 3018, 0, +3066, 3151, 0, +3158, 3283, 0, +3258, 3415, 0, +3364, 3548, 0, +3476, 3680, 0, +3593, 3812, 0, +3712, 3944, 0, +3835, 4076, 0, +3960, 4095, 0, +2623, 0, 2380, +2623, 0, 2379, +2623, 0, 2378, +2622, 0, 2375, +2622, 0, 2373, +2621, 0, 2370, +2621, 0, 2365, +2620, 0, 2359, +2620, 0, 2348, +2620, 0, 2334, +2620, 0, 2314, +2620, 0, 2287, +2620, 0, 2247, +2620, 0, 2187, +2620, 0, 2092, +2620, 0, 1923, +2620, 0, 1505, +2620, 0, 0, +2620, 0, 0, +2620, 1981, 0, +2753, 2482, 0, +2886, 2772, 0, +3018, 2993, 0, +3116, 3151, 0, +3199, 3283, 0, +3291, 3415, 0, +3391, 3548, 0, +3497, 3680, 0, +3609, 3812, 0, +3725, 3944, 0, +3845, 4076, 0, +3968, 4095, 0, +2755, 0, 2505, +2755, 0, 2505, +2755, 0, 2504, +2755, 0, 2502, +2755, 0, 2501, +2754, 0, 2498, +2754, 0, 2494, +2753, 0, 2490, +2753, 0, 2482, +2753, 0, 2471, +2753, 0, 2457, +2753, 0, 2437, +2753, 0, 2408, +2753, 0, 2367, +2753, 0, 2305, +2753, 0, 2208, +2753, 0, 2031, +2753, 0, 1575, +2753, 0, 0, +2753, 0, 0, +2753, 2105, 0, +2886, 2611, 0, +3018, 2902, 0, +3151, 3125, 0, +3249, 3283, 0, +3333, 3415, 0, +3424, 3548, 0, +3524, 3680, 0, +3630, 3812, 0, +3741, 3944, 0, +3857, 4076, 0, +3977, 4095, 0, +2887, 0, 2633, +2887, 0, 2632, +2887, 0, 2631, +2887, 0, 2630, +2887, 0, 2629, +2887, 0, 2627, +2886, 0, 2624, +2886, 0, 2621, +2886, 0, 2615, +2886, 0, 2607, +2886, 0, 2596, +2886, 0, 2581, +2886, 0, 2561, +2886, 0, 2532, +2886, 0, 2490, +2886, 0, 2427, +2886, 0, 2327, +2886, 0, 2144, +2886, 0, 1651, +2886, 0, 0, +2886, 0, 0, +2886, 2231, 0, +3018, 2740, 0, +3151, 3033, 0, +3283, 3256, 0, +3382, 3415, 0, +3466, 3548, 0, +3557, 3680, 0, +3656, 3812, 0, +3762, 3944, 0, +3873, 4076, 0, +3990, 4095, 0, +3019, 0, 2761, +3019, 0, 2760, +3019, 0, 2760, +3019, 0, 2759, +3019, 0, 2758, +3019, 0, 2756, +3018, 0, 2754, +3018, 0, 2752, +3018, 0, 2747, +3018, 0, 2742, +3018, 0, 2734, +3018, 0, 2723, +3018, 0, 2708, +3018, 0, 2687, +3018, 0, 2658, +3018, 0, 2615, +3018, 0, 2551, +3018, 0, 2449, +3018, 0, 2261, +3018, 0, 1737, +3018, 0, 0, +3018, 0, 0, +3018, 2358, 0, +3151, 2872, 0, +3283, 3164, 0, +3415, 3388, 0, +3515, 3548, 0, +3598, 3680, 0, +3690, 3812, 0, +3789, 3944, 0, +3895, 4076, 0, +4006, 4095, 0, +3152, 0, 2890, +3152, 0, 2890, +3152, 0, 2890, +3151, 0, 2889, +3151, 0, 2888, +3151, 0, 2887, +3151, 0, 2885, +3151, 0, 2883, +3151, 0, 2880, +3151, 0, 2876, +3151, 0, 2870, +3151, 0, 2862, +3151, 0, 2851, +3151, 0, 2836, +3151, 0, 2815, +3151, 0, 2785, +3151, 0, 2742, +3151, 0, 2678, +3151, 0, 2573, +3151, 0, 2382, +3151, 0, 1832, +3151, 0, 0, +3151, 0, 0, +3151, 2487, 0, +3283, 3002, 0, +3415, 3296, 0, +3548, 3520, 0, +3648, 3680, 0, +3730, 3812, 0, +3822, 3944, 0, +3921, 4076, 0, +4027, 4095, 0, +3284, 0, 3020, +3283, 0, 3020, +3283, 0, 3019, +3283, 0, 3019, +3283, 0, 3018, +3283, 0, 3018, +3283, 0, 3016, +3283, 0, 3015, +3283, 0, 3013, +3283, 0, 3009, +3283, 0, 3005, +3283, 0, 2999, +3283, 0, 2991, +3283, 0, 2980, +3283, 0, 2965, +3283, 0, 2943, +3283, 0, 2914, +3283, 0, 2870, +3283, 0, 2805, +3283, 0, 2700, +3283, 0, 2504, +3283, 0, 1932, +3283, 0, 0, +3283, 0, 0, +3283, 2616, 0, +3415, 3134, 0, +3548, 3428, 0, +3680, 3652, 0, +3780, 3812, 0, +3863, 3944, 0, +3954, 4076, 0, +4053, 4095, 0, +3416, 0, 3151, +3416, 0, 3151, +3416, 0, 3150, +3416, 0, 3150, +3416, 0, 3149, +3416, 0, 3149, +3415, 0, 3148, +3415, 0, 3147, +3415, 0, 3145, +3415, 0, 3143, +3415, 0, 3139, +3415, 0, 3135, +3415, 0, 3129, +3415, 0, 3121, +3415, 0, 3110, +3415, 0, 3094, +3415, 0, 3073, +3415, 0, 3043, +3415, 0, 2999, +3415, 0, 2934, +3415, 0, 2827, +3415, 0, 2630, +3415, 0, 2044, +3415, 0, 0, +3415, 0, 0, +3415, 2746, 0, +3548, 3265, 0, +3680, 3559, 0, +3812, 3784, 0, +3912, 3944, 0, +3995, 4076, 0, +4087, 4095, 0, +3548, 0, 3281, +3548, 0, 3281, +3548, 0, 3281, +3548, 0, 3281, +3548, 0, 3280, +3548, 0, 3280, +3548, 0, 3280, +3548, 0, 3279, +3548, 0, 3277, +3548, 0, 3276, +3548, 0, 3273, +3548, 0, 3270, +3548, 0, 3265, +3548, 0, 3259, +3548, 0, 3251, +3548, 0, 3240, +3548, 0, 3225, +3548, 0, 3203, +3548, 0, 3173, +3548, 0, 3129, +3548, 0, 3063, +3548, 0, 2956, +3548, 0, 2758, +3548, 0, 2156, +3548, 0, 0, +3548, 0, 0, +3548, 2877, 0, +3680, 3397, 0, +3812, 3691, 0, +3944, 3915, 0, +4045, 4076, 0, +4095, 4095, 0, +3680, 0, 3413, +3680, 0, 3413, +3680, 0, 3413, +3680, 0, 3412, +3680, 0, 3412, +3680, 0, 3412, +3680, 0, 3411, +3680, 0, 3411, +3680, 0, 3410, +3680, 0, 3408, +3680, 0, 3406, +3680, 0, 3404, +3680, 0, 3401, +3680, 0, 3396, +3680, 0, 3390, +3680, 0, 3382, +3680, 0, 3371, +3680, 0, 3356, +3680, 0, 3334, +3680, 0, 3304, +3680, 0, 3260, +3680, 0, 3193, +3680, 0, 3086, +3680, 0, 2886, +3680, 0, 2277, +3680, 0, 0, +3680, 0, 0, +3680, 3008, 0, +3812, 3529, 0, +3944, 3823, 0, +4076, 4047, 0, +4095, 4095, 0, +3812, 0, 3544, +3812, 0, 3544, +3812, 0, 3544, +3812, 0, 3544, +3812, 0, 3544, +3812, 0, 3543, +3812, 0, 3543, +3812, 0, 3543, +3812, 0, 3542, +3812, 0, 3541, +3812, 0, 3540, +3812, 0, 3538, +3812, 0, 3535, +3812, 0, 3532, +3812, 0, 3528, +3812, 0, 3521, +3812, 0, 3513, +3812, 0, 3502, +3812, 0, 3487, +3812, 0, 3465, +3812, 0, 3435, +3812, 0, 3391, +3812, 0, 3324, +3812, 0, 3216, +3812, 0, 3016, +3812, 0, 2397, +3812, 0, 0, +3812, 0, 0, +3812, 3139, 0, +3944, 3660, 0, +4076, 3955, 0, +4095, 4095, 0, +3944, 0, 3676, +3944, 0, 3676, +3944, 0, 3676, +3944, 0, 3676, +3944, 0, 3675, +3944, 0, 3675, +3944, 0, 3675, +3944, 0, 3674, +3944, 0, 3674, +3944, 0, 3673, +3944, 0, 3672, +3944, 0, 3671, +3944, 0, 3669, +3944, 0, 3666, +3944, 0, 3663, +3944, 0, 3659, +3944, 0, 3653, +3944, 0, 3645, +3944, 0, 3633, +3944, 0, 3618, +3944, 0, 3596, +3944, 0, 3566, +3944, 0, 3522, +3944, 0, 3455, +3944, 0, 3347, +3944, 0, 3145, +3944, 0, 2520, +3944, 0, 0, +3944, 0, 0, +3944, 3271, 0, +4076, 3792, 0, +4095, 4087, 0, +4076, 0, 3808, +4076, 0, 3807, +4076, 0, 3807, +4076, 0, 3807, +4076, 0, 3807, +4076, 0, 3807, +4076, 0, 3807, +4076, 0, 3806, +4076, 0, 3806, +4076, 0, 3805, +4076, 0, 3805, +4076, 0, 3804, +4076, 0, 3802, +4076, 0, 3801, +4076, 0, 3798, +4076, 0, 3795, +4076, 0, 3790, +4076, 0, 3784, +4076, 0, 3776, +4076, 0, 3765, +4076, 0, 3749, +4076, 0, 3728, +4076, 0, 3697, +4076, 0, 3653, +4076, 0, 3586, +4076, 0, 3478, +4076, 0, 3276, +4076, 0, 2644, +4076, 0, 0, +4076, 0, 0, +4076, 3402, 0, +4095, 3925, 0, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3938, +4095, 0, 3938, +4095, 0, 3937, +4095, 0, 3937, +4095, 0, 3936, +4095, 0, 3934, +4095, 0, 3932, +4095, 0, 3930, +4095, 0, 3927, +4095, 0, 3922, +4095, 0, 3916, +4095, 0, 3908, +4095, 0, 3897, +4095, 0, 3881, +4095, 0, 3860, +4095, 0, 3829, +4095, 0, 3785, +4095, 0, 3718, +4095, 0, 3610, +4095, 0, 3407, +4095, 0, 2773, +4095, 0, 0, +4095, 0, 0, +4095, 3534, 0, +0, 918, 1160, +0, 949, 1160, +0, 987, 1160, +0, 1033, 1160, +0, 1089, 1160, +0, 1154, 1160, +0, 1160, 1079, +0, 1160, 929, +0, 1160, 592, +0, 1295, 0, +0, 1429, 0, +523, 1563, 0, +998, 1696, 0, +1283, 1828, 0, +1503, 1961, 0, +1691, 2094, 0, +1860, 2226, 0, +2019, 2358, 0, +2170, 2491, 0, +2315, 2623, 0, +2457, 2755, 0, +2597, 2887, 0, +2734, 3019, 0, +2870, 3152, 0, +3005, 3284, 0, +3139, 3416, 0, +3273, 3548, 0, +3406, 3680, 0, +3540, 3812, 0, +3672, 3944, 0, +3805, 4076, 0, +3937, 4095, 0, +0, 885, 1160, +0, 924, 1157, +0, 964, 1157, +0, 1013, 1157, +0, 1071, 1157, +0, 1139, 1157, +0, 1157, 1089, +0, 1157, 943, +0, 1157, 620, +0, 1292, 0, +0, 1427, 0, +605, 1561, 0, +1029, 1695, 0, +1300, 1828, 0, +1513, 1961, 0, +1698, 2093, 0, +1865, 2226, 0, +2022, 2358, 0, +2172, 2491, 0, +2317, 2623, 0, +2459, 2755, 0, +2598, 2887, 0, +2735, 3019, 0, +2871, 3152, 0, +3005, 3283, 0, +3140, 3416, 0, +3273, 3548, 0, +3407, 3680, 0, +3540, 3812, 0, +3672, 3944, 0, +3805, 4076, 0, +3937, 4095, 0, +0, 836, 1160, +0, 879, 1157, +0, 932, 1152, +0, 984, 1152, +0, 1045, 1152, +0, 1117, 1152, +0, 1152, 1102, +0, 1152, 960, +0, 1152, 656, +0, 1289, 0, +0, 1424, 0, +696, 1559, 0, +1067, 1693, 0, +1321, 1827, 0, +1526, 1960, 0, +1706, 2093, 0, +1871, 2225, 0, +2027, 2358, 0, +2175, 2490, 0, +2320, 2623, 0, +2460, 2755, 0, +2599, 2887, 0, +2735, 3019, 0, +2871, 3152, 0, +3006, 3283, 0, +3140, 3416, 0, +3274, 3548, 0, +3407, 3680, 0, +3540, 3812, 0, +3673, 3944, 0, +3805, 4076, 0, +3937, 4095, 0, +0, 762, 1160, +0, 813, 1157, +0, 873, 1152, +0, 942, 1146, +0, 1009, 1146, +0, 1086, 1146, +0, 1146, 1119, +0, 1146, 983, +0, 1146, 700, +0, 1284, 0, +141, 1421, 0, +794, 1557, 0, +1113, 1691, 0, +1348, 1825, 0, +1544, 1959, 0, +1718, 2092, 0, +1880, 2225, 0, +2032, 2357, 0, +2180, 2490, 0, +2323, 2622, 0, +2463, 2755, 0, +2601, 2887, 0, +2737, 3019, 0, +2872, 3151, 0, +3007, 3283, 0, +3141, 3416, 0, +3274, 3548, 0, +3407, 3680, 0, +3540, 3812, 0, +3673, 3944, 0, +3805, 4076, 0, +3938, 4095, 0, +0, 640, 1160, +0, 705, 1157, +0, 779, 1152, +0, 863, 1146, +80, 955, 1137, +80, 1040, 1137, +80, 1134, 1137, +80, 1137, 1013, +80, 1137, 753, +0, 1278, 0, +478, 1416, 0, +900, 1553, 0, +1169, 1689, 0, +1382, 1823, 0, +1566, 1958, 0, +1733, 2091, 0, +1891, 2224, 0, +2040, 2357, 0, +2185, 2489, 0, +2327, 2622, 0, +2466, 2755, 0, +2603, 2887, 0, +2738, 3019, 0, +2873, 3151, 0, +3008, 3283, 0, +3141, 3416, 0, +3275, 3548, 0, +3408, 3680, 0, +3540, 3812, 0, +3673, 3944, 0, +3805, 4076, 0, +3938, 4095, 0, +0, 397, 1160, +0, 503, 1157, +0, 614, 1152, +0, 730, 1146, +80, 850, 1137, +430, 972, 1126, +430, 1079, 1126, +430, 1126, 1049, +430, 1126, 814, +214, 1270, 212, +719, 1410, 0, +1011, 1549, 0, +1233, 1685, 0, +1423, 1821, 0, +1594, 1956, 0, +1753, 2089, 0, +1904, 2223, 0, +2050, 2356, 0, +2193, 2489, 0, +2332, 2621, 0, +2470, 2754, 0, +2606, 2887, 0, +2741, 3019, 0, +2875, 3151, 0, +3009, 3283, 0, +3142, 3416, 0, +3275, 3548, 0, +3408, 3680, 0, +3541, 3812, 0, +3673, 3944, 0, +3805, 4076, 0, +3938, 4095, 0, +0, 0, 1160, +0, 0, 1157, +0, 214, 1152, +0, 455, 1146, +80, 655, 1137, +430, 831, 1126, +676, 994, 1110, +676, 1110, 1092, +676, 1110, 886, +661, 1258, 562, +919, 1402, 344, +1127, 1543, 0, +1308, 1681, 0, +1474, 1817, 0, +1629, 1953, 0, +1778, 2087, 0, +1922, 2221, 0, +2063, 2355, 0, +2202, 2488, 0, +2339, 2621, 0, +2475, 2754, 0, +2610, 2886, 0, +2744, 3018, 0, +2877, 3151, 0, +3010, 3283, 0, +3144, 3415, 0, +3276, 3548, 0, +3409, 3680, 0, +3541, 3812, 0, +3673, 3944, 0, +3805, 4076, 0, +3938, 4095, 0, +0, 0, 1160, +0, 0, 1157, +0, 0, 1152, +0, 0, 1146, +80, 81, 1137, +430, 529, 1126, +676, 805, 1110, +878, 1021, 1088, +878, 1088, 967, +938, 1242, 809, +1095, 1390, 695, +1246, 1534, 476, +1391, 1674, 0, +1533, 1813, 0, +1672, 1950, 0, +1810, 2085, 0, +1946, 2220, 0, +2081, 2353, 0, +2215, 2487, 0, +2348, 2620, 0, +2482, 2753, 0, +2615, 2886, 0, +2747, 3018, 0, +2880, 3151, 0, +3013, 3283, 0, +3145, 3415, 0, +3277, 3548, 0, +3410, 3680, 0, +3542, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3938, 4095, 0, +592, 0, 1160, +620, 0, 1157, +656, 0, 1152, +700, 0, 1146, +753, 80, 1137, +814, 430, 1126, +886, 676, 1110, +967, 878, 1088, +1056, 1056, 1056, +1154, 1220, 1010, +1258, 1374, 940, +1368, 1523, 826, +1483, 1666, 608, +1602, 1807, 0, +1724, 1945, 0, +1849, 2082, 0, +1975, 2217, 0, +2102, 2352, 0, +2231, 2486, 0, +2361, 2619, 0, +2491, 2752, 0, +2622, 2885, 0, +2752, 3018, 0, +2884, 3151, 0, +3015, 3283, 0, +3147, 3415, 0, +3279, 3548, 0, +3411, 3680, 0, +3543, 3812, 0, +3675, 3944, 0, +3807, 4076, 0, +3939, 4095, 0, +1051, 0, 1295, +1062, 0, 1292, +1075, 0, 1289, +1093, 0, 1284, +1116, 0, 1278, +1145, 212, 1270, +1181, 562, 1258, +1225, 809, 1242, +1220, 1010, 1154, +1220, 1099, 1010, +1374, 1357, 940, +1476, 1523, 826, +1569, 1666, 608, +1669, 1807, 0, +1776, 1945, 0, +1889, 2082, 0, +2006, 2217, 0, +2126, 2352, 0, +2249, 2486, 0, +2374, 2619, 0, +2501, 2752, 0, +2629, 2885, 0, +2758, 3018, 0, +2888, 3151, 0, +3018, 3283, 0, +3150, 3415, 0, +3281, 3548, 0, +3412, 3680, 0, +3544, 3812, 0, +3675, 3944, 0, +3807, 4076, 0, +3939, 4095, 0, +1330, 0, 1429, +1336, 0, 1427, +1343, 0, 1424, +1353, 0, 1421, +1367, 0, 1416, +1383, 0, 1410, +1402, 344, 1398, +1390, 695, 1343, +1374, 940, 1258, +1374, 940, 1069, +1374, 1150, 940, +1523, 1445, 826, +1663, 1666, 608, +1746, 1807, 0, +1838, 1945, 0, +1938, 2082, 0, +2044, 2217, 0, +2155, 2352, 0, +2272, 2486, 0, +2392, 2619, 0, +2514, 2752, 0, +2639, 2885, 0, +2766, 3018, 0, +2894, 3151, 0, +3023, 3283, 0, +3153, 3415, 0, +3283, 3548, 0, +3414, 3680, 0, +3545, 3812, 0, +3676, 3944, 0, +3808, 4076, 0, +3940, 4095, 0, +1548, 0, 1563, +1552, 0, 1561, +1556, 0, 1559, +1557, 0, 1551, +1553, 0, 1535, +1549, 0, 1513, +1543, 0, 1482, +1534, 476, 1437, +1523, 826, 1368, +1523, 826, 1228, +1523, 826, 926, +1523, 1211, 826, +1666, 1541, 608, +1807, 1780, 0, +1909, 1945, 0, +1996, 2082, 0, +2090, 2217, 0, +2192, 2352, 0, +2301, 2486, 0, +2414, 2619, 0, +2532, 2752, 0, +2652, 2885, 0, +2776, 3018, 0, +2902, 3151, 0, +3029, 3283, 0, +3157, 3415, 0, +3286, 3548, 0, +3416, 3680, 0, +3547, 3812, 0, +3678, 3944, 0, +3809, 4076, 0, +3941, 4095, 0, +1696, 0, 1653, +1695, 0, 1647, +1693, 0, 1640, +1691, 0, 1631, +1689, 0, 1617, +1685, 0, 1599, +1681, 0, 1574, +1674, 0, 1537, +1666, 608, 1483, +1666, 608, 1378, +1666, 608, 1183, +1666, 609, 608, +1666, 1281, 608, +1807, 1644, 0, +1945, 1895, 0, +2063, 2082, 0, +2146, 2217, 0, +2237, 2352, 0, +2336, 2486, 0, +2442, 2619, 0, +2553, 2752, 0, +2669, 2885, 0, +2789, 3018, 0, +2911, 3151, 0, +3036, 3283, 0, +3163, 3415, 0, +3291, 3548, 0, +3420, 3680, 0, +3549, 3812, 0, +3680, 3944, 0, +3810, 4076, 0, +3941, 4095, 0, +1828, 0, 1738, +1828, 0, 1733, +1827, 0, 1727, +1825, 0, 1720, +1823, 0, 1709, +1821, 0, 1694, +1817, 0, 1673, +1813, 0, 1644, +1807, 0, 1602, +1807, 0, 1523, +1807, 0, 1391, +1807, 0, 1115, +1807, 438, 0, +1807, 1360, 0, +1945, 1754, 0, +2082, 2014, 0, +2211, 2217, 0, +2291, 2352, 0, +2380, 2486, 0, +2477, 2619, 0, +2581, 2752, 0, +2691, 2885, 0, +2805, 3018, 0, +2924, 3151, 0, +3046, 3283, 0, +3170, 3415, 0, +3296, 3548, 0, +3424, 3680, 0, +3552, 3812, 0, +3682, 3944, 0, +3812, 4076, 0, +3943, 4095, 0, +1961, 0, 1831, +1961, 0, 1828, +1960, 0, 1823, +1959, 0, 1817, +1958, 0, 1808, +1956, 0, 1796, +1953, 0, 1779, +1950, 0, 1757, +1945, 0, 1724, +1945, 0, 1665, +1945, 0, 1572, +1945, 0, 1407, +1945, 0, 1007, +1945, 37, 0, +1945, 1449, 0, +2082, 1868, 0, +2217, 2136, 0, +2352, 2349, 0, +2433, 2486, 0, +2520, 2619, 0, +2616, 2752, 0, +2718, 2885, 0, +2827, 3018, 0, +2941, 3151, 0, +3059, 3283, 0, +3180, 3415, 0, +3303, 3548, 0, +3429, 3680, 0, +3557, 3812, 0, +3685, 3944, 0, +3814, 4076, 0, +3945, 4095, 0, +2094, 0, 1932, +2093, 0, 1929, +2093, 0, 1926, +2092, 0, 1920, +2091, 0, 1913, +2089, 0, 1904, +2087, 0, 1891, +2085, 0, 1873, +2082, 0, 1849, +2082, 0, 1804, +2082, 0, 1738, +2082, 0, 1630, +2082, 0, 1428, +2082, 0, 800, +2082, 0, 0, +2082, 1545, 0, +2217, 1986, 0, +2352, 2261, 0, +2486, 2476, 0, +2572, 2619, 0, +2658, 2752, 0, +2752, 2885, 0, +2854, 3018, 0, +2962, 3151, 0, +3075, 3283, 0, +3192, 3415, 0, +3313, 3548, 0, +3437, 3680, 0, +3562, 3812, 0, +3689, 3944, 0, +3818, 4076, 0, +3947, 4095, 0, +2226, 0, 2039, +2226, 0, 2037, +2225, 0, 2034, +2225, 0, 2030, +2224, 0, 2025, +2223, 0, 2018, +2221, 0, 2008, +2220, 0, 1994, +2217, 0, 1975, +2217, 0, 1941, +2217, 0, 1894, +2217, 0, 1819, +2217, 0, 1697, +2217, 0, 1454, +2217, 0, 140, +2217, 0, 0, +2217, 1649, 0, +2352, 2107, 0, +2486, 2387, 0, +2619, 2604, 0, +2710, 2752, 0, +2795, 2885, 0, +2888, 3018, 0, +2989, 3151, 0, +3096, 3283, 0, +3209, 3415, 0, +3326, 3548, 0, +3446, 3680, 0, +3570, 3812, 0, +3695, 3944, 0, +3822, 4076, 0, +3950, 4095, 0, +2358, 0, 2152, +2358, 0, 2150, +2358, 0, 2148, +2357, 0, 2145, +2357, 0, 2141, +2356, 0, 2135, +2355, 0, 2127, +2353, 0, 2117, +2352, 0, 2102, +2352, 0, 2078, +2352, 0, 2042, +2352, 0, 1990, +2352, 0, 1910, +2352, 0, 1773, +2352, 0, 1487, +2352, 0, 0, +2352, 0, 0, +2352, 1758, 0, +2486, 2232, 0, +2619, 2515, 0, +2752, 2734, 0, +2845, 2885, 0, +2930, 3018, 0, +3023, 3151, 0, +3123, 3283, 0, +3230, 3415, 0, +3342, 3548, 0, +3459, 3680, 0, +3579, 3812, 0, +3702, 3944, 0, +3827, 4076, 0, +3954, 4095, 0, +2491, 0, 2269, +2491, 0, 2268, +2490, 0, 2266, +2490, 0, 2264, +2489, 0, 2260, +2489, 0, 2256, +2488, 0, 2250, +2487, 0, 2242, +2486, 0, 2231, +2486, 0, 2213, +2486, 0, 2187, +2486, 0, 2149, +2486, 0, 2094, +2486, 0, 2008, +2486, 0, 1859, +2486, 0, 1529, +2486, 0, 0, +2486, 0, 0, +2486, 1873, 0, +2619, 2357, 0, +2752, 2644, 0, +2885, 2864, 0, +2980, 3018, 0, +3064, 3151, 0, +3157, 3283, 0, +3257, 3415, 0, +3363, 3548, 0, +3475, 3680, 0, +3592, 3812, 0, +3712, 3944, 0, +3835, 4076, 0, +3960, 4095, 0, +2623, 0, 2390, +2623, 0, 2388, +2623, 0, 2387, +2622, 0, 2385, +2622, 0, 2383, +2621, 0, 2380, +2621, 0, 2375, +2620, 0, 2369, +2619, 0, 2361, +2619, 0, 2347, +2619, 0, 2328, +2619, 0, 2301, +2619, 0, 2262, +2619, 0, 2204, +2619, 0, 2113, +2619, 0, 1954, +2619, 0, 1578, +2619, 0, 0, +2619, 0, 0, +2619, 1991, 0, +2752, 2485, 0, +2885, 2773, 0, +3018, 2995, 0, +3115, 3151, 0, +3198, 3283, 0, +3290, 3415, 0, +3390, 3548, 0, +3496, 3680, 0, +3608, 3812, 0, +3725, 3944, 0, +3845, 4076, 0, +3967, 4095, 0, +2755, 0, 2513, +2755, 0, 2512, +2755, 0, 2511, +2755, 0, 2510, +2755, 0, 2508, +2754, 0, 2505, +2754, 0, 2502, +2753, 0, 2497, +2752, 0, 2491, +2752, 0, 2481, +2752, 0, 2467, +2752, 0, 2447, +2752, 0, 2419, +2752, 0, 2379, +2752, 0, 2319, +2752, 0, 2224, +2752, 0, 2056, +2752, 0, 1638, +2752, 0, 0, +2752, 0, 0, +2752, 2113, 0, +2885, 2613, 0, +3018, 2903, 0, +3151, 3126, 0, +3248, 3283, 0, +3331, 3415, 0, +3423, 3548, 0, +3523, 3680, 0, +3629, 3812, 0, +3741, 3944, 0, +3857, 4076, 0, +3977, 4095, 0, +2887, 0, 2638, +2887, 0, 2638, +2887, 0, 2637, +2887, 0, 2636, +2887, 0, 2635, +2887, 0, 2632, +2886, 0, 2630, +2886, 0, 2626, +2885, 0, 2622, +2885, 0, 2614, +2885, 0, 2603, +2885, 0, 2589, +2885, 0, 2569, +2885, 0, 2540, +2885, 0, 2499, +2885, 0, 2438, +2885, 0, 2340, +2885, 0, 2163, +2885, 0, 1706, +2885, 0, 0, +2885, 0, 0, +2885, 2237, 0, +3018, 2742, 0, +3151, 3034, 0, +3283, 3257, 0, +3381, 3415, 0, +3465, 3548, 0, +3556, 3680, 0, +3656, 3812, 0, +3762, 3944, 0, +3873, 4076, 0, +3989, 4095, 0, +3019, 0, 2765, +3019, 0, 2765, +3019, 0, 2764, +3019, 0, 2763, +3019, 0, 2762, +3019, 0, 2761, +3018, 0, 2759, +3018, 0, 2756, +3018, 0, 2752, +3018, 0, 2747, +3018, 0, 2739, +3018, 0, 2728, +3018, 0, 2714, +3018, 0, 2693, +3018, 0, 2664, +3018, 0, 2622, +3018, 0, 2559, +3018, 0, 2459, +3018, 0, 2276, +3018, 0, 1782, +3018, 0, 0, +3018, 0, 0, +3018, 2362, 0, +3151, 2873, 0, +3283, 3165, 0, +3415, 3388, 0, +3514, 3548, 0, +3597, 3680, 0, +3689, 3812, 0, +3788, 3944, 0, +3894, 4076, 0, +4006, 4095, 0, +3152, 0, 2893, +3152, 0, 2893, +3152, 0, 2893, +3151, 0, 2892, +3151, 0, 2891, +3151, 0, 2890, +3151, 0, 2889, +3151, 0, 2887, +3151, 0, 2884, +3151, 0, 2880, +3151, 0, 2874, +3151, 0, 2866, +3151, 0, 2855, +3151, 0, 2840, +3151, 0, 2819, +3151, 0, 2790, +3151, 0, 2747, +3151, 0, 2684, +3151, 0, 2581, +3151, 0, 2394, +3151, 0, 1869, +3151, 0, 0, +3151, 0, 0, +3151, 2490, 0, +3283, 3003, 0, +3415, 3296, 0, +3548, 3520, 0, +3647, 3680, 0, +3730, 3812, 0, +3822, 3944, 0, +3921, 4076, 0, +4027, 4095, 0, +3284, 0, 3022, +3283, 0, 3022, +3283, 0, 3022, +3283, 0, 3021, +3283, 0, 3021, +3283, 0, 3020, +3283, 0, 3019, +3283, 0, 3017, +3283, 0, 3015, +3283, 0, 3012, +3283, 0, 3008, +3283, 0, 3002, +3283, 0, 2994, +3283, 0, 2983, +3283, 0, 2968, +3283, 0, 2947, +3283, 0, 2917, +3283, 0, 2874, +3283, 0, 2809, +3283, 0, 2705, +3283, 0, 2513, +3283, 0, 1962, +3283, 0, 0, +3283, 0, 0, +3283, 2619, 0, +3415, 3135, 0, +3548, 3428, 0, +3680, 3652, 0, +3780, 3812, 0, +3863, 3944, 0, +3954, 4076, 0, +4053, 4095, 0, +3416, 0, 3152, +3416, 0, 3152, +3416, 0, 3152, +3416, 0, 3151, +3416, 0, 3151, +3416, 0, 3151, +3415, 0, 3150, +3415, 0, 3149, +3415, 0, 3147, +3415, 0, 3145, +3415, 0, 3141, +3415, 0, 3137, +3415, 0, 3131, +3415, 0, 3123, +3415, 0, 3112, +3415, 0, 3097, +3415, 0, 3076, +3415, 0, 3046, +3415, 0, 3002, +3415, 0, 2937, +3415, 0, 2832, +3415, 0, 2637, +3415, 0, 2068, +3415, 0, 0, +3415, 0, 0, +3415, 2748, 0, +3548, 3266, 0, +3680, 3560, 0, +3812, 3784, 0, +3912, 3944, 0, +3995, 4076, 0, +4086, 4095, 0, +3548, 0, 3283, +3548, 0, 3283, +3548, 0, 3282, +3548, 0, 3282, +3548, 0, 3282, +3548, 0, 3281, +3548, 0, 3281, +3548, 0, 3280, +3548, 0, 3279, +3548, 0, 3277, +3548, 0, 3275, +3548, 0, 3271, +3548, 0, 3267, +3548, 0, 3261, +3548, 0, 3253, +3548, 0, 3242, +3548, 0, 3226, +3548, 0, 3205, +3548, 0, 3175, +3548, 0, 3132, +3548, 0, 3066, +3548, 0, 2960, +3548, 0, 2763, +3548, 0, 2174, +3548, 0, 0, +3548, 0, 0, +3548, 2878, 0, +3680, 3397, 0, +3812, 3691, 0, +3944, 3915, 0, +4044, 4076, 0, +4095, 4095, 0, +3680, 0, 3414, +3680, 0, 3414, +3680, 0, 3414, +3680, 0, 3413, +3680, 0, 3413, +3680, 0, 3413, +3680, 0, 3412, +3680, 0, 3412, +3680, 0, 3411, +3680, 0, 3409, +3680, 0, 3408, +3680, 0, 3405, +3680, 0, 3402, +3680, 0, 3397, +3680, 0, 3392, +3680, 0, 3383, +3680, 0, 3372, +3680, 0, 3357, +3680, 0, 3336, +3680, 0, 3305, +3680, 0, 3261, +3680, 0, 3195, +3680, 0, 3089, +3680, 0, 2890, +3680, 0, 2291, +3680, 0, 0, +3680, 0, 0, +3680, 3009, 0, +3812, 3529, 0, +3944, 3823, 0, +4076, 4047, 0, +4095, 4095, 0, +3812, 0, 3545, +3812, 0, 3545, +3812, 0, 3545, +3812, 0, 3545, +3812, 0, 3544, +3812, 0, 3544, +3812, 0, 3544, +3812, 0, 3543, +3812, 0, 3543, +3812, 0, 3542, +3812, 0, 3540, +3812, 0, 3538, +3812, 0, 3536, +3812, 0, 3533, +3812, 0, 3528, +3812, 0, 3522, +3812, 0, 3514, +3812, 0, 3503, +3812, 0, 3488, +3812, 0, 3466, +3812, 0, 3436, +3812, 0, 3392, +3812, 0, 3326, +3812, 0, 3218, +3812, 0, 3019, +3812, 0, 2408, +3812, 0, 0, +3812, 0, 0, +3812, 3140, 0, +3944, 3661, 0, +4076, 3955, 0, +4095, 4095, 0, +3944, 0, 3676, +3944, 0, 3676, +3944, 0, 3676, +3944, 0, 3676, +3944, 0, 3676, +3944, 0, 3676, +3944, 0, 3676, +3944, 0, 3675, +3944, 0, 3675, +3944, 0, 3674, +3944, 0, 3673, +3944, 0, 3671, +3944, 0, 3670, +3944, 0, 3667, +3944, 0, 3664, +3944, 0, 3659, +3944, 0, 3653, +3944, 0, 3645, +3944, 0, 3634, +3944, 0, 3619, +3944, 0, 3597, +3944, 0, 3567, +3944, 0, 3523, +3944, 0, 3456, +3944, 0, 3349, +3944, 0, 3147, +3944, 0, 2528, +3944, 0, 0, +3944, 0, 0, +3944, 3271, 0, +4076, 3792, 0, +4095, 4087, 0, +4076, 0, 3808, +4076, 0, 3808, +4076, 0, 3808, +4076, 0, 3808, +4076, 0, 3808, +4076, 0, 3808, +4076, 0, 3807, +4076, 0, 3807, +4076, 0, 3807, +4076, 0, 3806, +4076, 0, 3805, +4076, 0, 3804, +4076, 0, 3803, +4076, 0, 3801, +4076, 0, 3798, +4076, 0, 3795, +4076, 0, 3791, +4076, 0, 3785, +4076, 0, 3777, +4076, 0, 3765, +4076, 0, 3750, +4076, 0, 3728, +4076, 0, 3698, +4076, 0, 3654, +4076, 0, 3587, +4076, 0, 3479, +4076, 0, 3277, +4076, 0, 2650, +4076, 0, 0, +4076, 0, 0, +4076, 3403, 0, +4095, 3925, 0, +4095, 0, 3940, +4095, 0, 3940, +4095, 0, 3940, +4095, 0, 3940, +4095, 0, 3940, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3938, +4095, 0, 3938, +4095, 0, 3937, +4095, 0, 3936, +4095, 0, 3935, +4095, 0, 3933, +4095, 0, 3930, +4095, 0, 3927, +4095, 0, 3923, +4095, 0, 3917, +4095, 0, 3908, +4095, 0, 3897, +4095, 0, 3881, +4095, 0, 3860, +4095, 0, 3830, +4095, 0, 3786, +4095, 0, 3719, +4095, 0, 3611, +4095, 0, 3408, +4095, 0, 2778, +4095, 0, 0, +4095, 0, 0, +4095, 3534, 0, +0, 1046, 1295, +0, 1069, 1295, +0, 1099, 1295, +0, 1135, 1295, +0, 1181, 1295, +0, 1234, 1295, +0, 1295, 1292, +0, 1295, 1204, +0, 1295, 1051, +0, 1295, 702, +0, 1429, 0, +0, 1563, 0, +580, 1696, 0, +1106, 1828, 0, +1402, 1961, 0, +1626, 2094, 0, +1817, 2226, 0, +1989, 2358, 0, +2149, 2491, 0, +2300, 2623, 0, +2446, 2755, 0, +2589, 2887, 0, +2728, 3019, 0, +2866, 3152, 0, +3002, 3284, 0, +3137, 3416, 0, +3271, 3548, 0, +3405, 3680, 0, +3538, 3812, 0, +3671, 3944, 0, +3804, 4076, 0, +3937, 4095, 0, +0, 1021, 1295, +0, 1050, 1292, +0, 1081, 1292, +0, 1119, 1292, +0, 1166, 1292, +0, 1221, 1292, +0, 1286, 1292, +0, 1292, 1211, +0, 1292, 1062, +0, 1292, 724, +0, 1427, 0, +0, 1561, 0, +653, 1695, 0, +1131, 1828, 0, +1415, 1961, 0, +1635, 2093, 0, +1823, 2226, 0, +1993, 2358, 0, +2151, 2491, 0, +2302, 2623, 0, +2448, 2755, 0, +2589, 2887, 0, +2729, 3019, 0, +2866, 3152, 0, +3002, 3283, 0, +3137, 3416, 0, +3272, 3548, 0, +3405, 3680, 0, +3538, 3812, 0, +3671, 3944, 0, +3804, 4076, 0, +3937, 4095, 0, +0, 985, 1295, +0, 1017, 1292, +0, 1056, 1289, +0, 1096, 1289, +0, 1145, 1289, +0, 1203, 1289, +0, 1271, 1289, +0, 1289, 1221, +0, 1289, 1075, +0, 1289, 753, +0, 1424, 0, +0, 1559, 0, +736, 1693, 0, +1161, 1827, 0, +1431, 1960, 0, +1645, 2093, 0, +1829, 2225, 0, +1997, 2358, 0, +2154, 2490, 0, +2304, 2623, 0, +2449, 2755, 0, +2591, 2887, 0, +2729, 3019, 0, +2867, 3152, 0, +3002, 3283, 0, +3138, 3416, 0, +3272, 3548, 0, +3405, 3680, 0, +3539, 3812, 0, +3672, 3944, 0, +3804, 4076, 0, +3937, 4095, 0, +0, 934, 1295, +0, 968, 1292, +0, 1012, 1289, +0, 1064, 1284, +0, 1116, 1284, +0, 1177, 1284, +0, 1249, 1284, +0, 1284, 1235, +0, 1284, 1093, +0, 1284, 788, +0, 1421, 0, +0, 1557, 0, +827, 1691, 0, +1199, 1825, 0, +1453, 1959, 0, +1658, 2092, 0, +1839, 2225, 0, +2004, 2357, 0, +2159, 2490, 0, +2308, 2622, 0, +2452, 2755, 0, +2592, 2887, 0, +2731, 3019, 0, +2868, 3151, 0, +3003, 3283, 0, +3138, 3416, 0, +3272, 3548, 0, +3406, 3680, 0, +3539, 3812, 0, +3672, 3944, 0, +3805, 4076, 0, +3937, 4095, 0, +0, 853, 1295, +0, 894, 1292, +0, 945, 1289, +0, 1005, 1284, +0, 1074, 1278, +0, 1141, 1278, +0, 1218, 1278, +0, 1278, 1251, +0, 1278, 1116, +0, 1278, 832, +0, 1416, 0, +275, 1553, 0, +926, 1689, 0, +1245, 1823, 0, +1480, 1958, 0, +1676, 2091, 0, +1850, 2224, 0, +2012, 2357, 0, +2165, 2489, 0, +2312, 2622, 0, +2455, 2755, 0, +2595, 2887, 0, +2732, 3019, 0, +2869, 3151, 0, +3004, 3283, 0, +3139, 3416, 0, +3273, 3548, 0, +3406, 3680, 0, +3539, 3812, 0, +3672, 3944, 0, +3805, 4076, 0, +3937, 4095, 0, +0, 717, 1295, +0, 772, 1292, +0, 837, 1289, +0, 911, 1284, +0, 995, 1278, +212, 1087, 1270, +212, 1172, 1270, +212, 1266, 1270, +212, 1270, 1145, +212, 1270, 884, +0, 1410, 47, +611, 1549, 0, +1031, 1685, 0, +1301, 1821, 0, +1514, 1956, 0, +1698, 2089, 0, +1865, 2223, 0, +2022, 2356, 0, +2172, 2489, 0, +2317, 2621, 0, +2459, 2754, 0, +2598, 2887, 0, +2735, 3019, 0, +2871, 3151, 0, +3005, 3283, 0, +3140, 3416, 0, +3273, 3548, 0, +3407, 3680, 0, +3540, 3812, 0, +3672, 3944, 0, +3805, 4076, 0, +3937, 4095, 0, +0, 431, 1295, +0, 529, 1292, +0, 635, 1289, +0, 746, 1284, +0, 862, 1278, +212, 982, 1270, +562, 1104, 1258, +562, 1211, 1258, +562, 1258, 1181, +562, 1258, 946, +345, 1402, 344, +852, 1543, 0, +1142, 1681, 0, +1366, 1817, 0, +1555, 1953, 0, +1726, 2087, 0, +1885, 2221, 0, +2037, 2355, 0, +2183, 2488, 0, +2325, 2621, 0, +2464, 2754, 0, +2602, 2886, 0, +2738, 3018, 0, +2873, 3151, 0, +3007, 3283, 0, +3141, 3415, 0, +3274, 3548, 0, +3407, 3680, 0, +3540, 3812, 0, +3673, 3944, 0, +3805, 4076, 0, +3938, 4095, 0, +0, 0, 1295, +0, 0, 1292, +0, 9, 1289, +0, 346, 1284, +0, 587, 1278, +212, 787, 1270, +562, 963, 1258, +809, 1126, 1242, +809, 1242, 1225, +809, 1242, 1018, +793, 1390, 695, +1051, 1534, 476, +1258, 1674, 0, +1440, 1813, 0, +1606, 1950, 0, +1761, 2085, 0, +1910, 2220, 0, +2054, 2353, 0, +2196, 2487, 0, +2334, 2620, 0, +2471, 2753, 0, +2607, 2886, 0, +2742, 3018, 0, +2876, 3151, 0, +3009, 3283, 0, +3143, 3415, 0, +3276, 3548, 0, +3408, 3680, 0, +3541, 3812, 0, +3673, 3944, 0, +3805, 4076, 0, +3938, 4095, 0, +0, 0, 1295, +0, 0, 1292, +0, 0, 1289, +0, 0, 1284, +0, 0, 1278, +212, 214, 1270, +562, 661, 1258, +809, 938, 1242, +1010, 1154, 1220, +1010, 1220, 1099, +1069, 1374, 940, +1228, 1523, 826, +1378, 1666, 608, +1523, 1807, 0, +1665, 1945, 0, +1804, 2082, 0, +1942, 2217, 0, +2078, 2352, 0, +2213, 2486, 0, +2347, 2619, 0, +2481, 2752, 0, +2614, 2885, 0, +2747, 3018, 0, +2880, 3151, 0, +3012, 3283, 0, +3145, 3415, 0, +3277, 3548, 0, +3409, 3680, 0, +3542, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3938, 4095, 0, +702, 0, 1295, +724, 0, 1292, +753, 0, 1289, +788, 0, 1284, +832, 0, 1278, +884, 212, 1270, +946, 562, 1258, +1018, 809, 1242, +1099, 1010, 1220, +1188, 1188, 1188, +1286, 1352, 1142, +1390, 1507, 1073, +1500, 1654, 959, +1615, 1798, 740, +1734, 1939, 0, +1856, 2077, 0, +1981, 2214, 0, +2107, 2349, 0, +2235, 2484, 0, +2363, 2618, 0, +2493, 2751, 0, +2623, 2885, 0, +2754, 3017, 0, +2885, 3150, 0, +3016, 3282, 0, +3147, 3415, 0, +3279, 3547, 0, +3411, 3680, 0, +3543, 3812, 0, +3675, 3944, 0, +3807, 4076, 0, +3939, 4095, 0, +1174, 0, 1429, +1182, 0, 1427, +1193, 0, 1424, +1207, 0, 1421, +1225, 0, 1416, +1248, 0, 1410, +1277, 344, 1402, +1313, 695, 1390, +1357, 940, 1374, +1352, 1142, 1286, +1352, 1231, 1142, +1507, 1489, 1073, +1608, 1654, 959, +1701, 1798, 740, +1801, 1939, 0, +1908, 2077, 0, +2021, 2214, 0, +2138, 2349, 0, +2258, 2484, 0, +2381, 2618, 0, +2506, 2751, 0, +2633, 2885, 0, +2761, 3017, 0, +2891, 3150, 0, +3020, 3282, 0, +3151, 3415, 0, +3282, 3547, 0, +3413, 3680, 0, +3544, 3812, 0, +3676, 3944, 0, +3808, 4076, 0, +3940, 4095, 0, +1458, 0, 1563, +1463, 0, 1561, +1468, 0, 1559, +1476, 0, 1557, +1486, 0, 1553, +1499, 0, 1549, +1516, 0, 1543, +1534, 476, 1531, +1523, 826, 1476, +1507, 1073, 1390, +1507, 1073, 1202, +1507, 1282, 1073, +1654, 1577, 959, +1795, 1798, 740, +1878, 1939, 0, +1970, 2077, 0, +2070, 2214, 0, +2176, 2349, 0, +2288, 2484, 0, +2404, 2618, 0, +2524, 2751, 0, +2647, 2885, 0, +2771, 3017, 0, +2898, 3150, 0, +3026, 3282, 0, +3155, 3415, 0, +3285, 3547, 0, +3415, 3680, 0, +3546, 3812, 0, +3677, 3944, 0, +3808, 4076, 0, +3940, 4095, 0, +1677, 0, 1696, +1680, 0, 1695, +1683, 0, 1693, +1688, 0, 1691, +1689, 0, 1683, +1685, 0, 1667, +1681, 0, 1645, +1674, 0, 1614, +1666, 608, 1569, +1654, 959, 1500, +1654, 959, 1360, +1654, 959, 1056, +1654, 1343, 959, +1798, 1673, 740, +1939, 1912, 0, +2041, 2077, 0, +2128, 2214, 0, +2223, 2349, 0, +2325, 2484, 0, +2432, 2618, 0, +2546, 2751, 0, +2664, 2885, 0, +2784, 3017, 0, +2908, 3150, 0, +3033, 3282, 0, +3161, 3415, 0, +3289, 3547, 0, +3418, 3680, 0, +3548, 3812, 0, +3679, 3944, 0, +3810, 4076, 0, +3941, 4095, 0, +1828, 0, 1789, +1828, 0, 1785, +1827, 0, 1779, +1825, 0, 1772, +1823, 0, 1763, +1821, 0, 1750, +1817, 0, 1732, +1813, 0, 1706, +1807, 0, 1669, +1798, 740, 1615, +1798, 740, 1510, +1798, 740, 1315, +1798, 740, 742, +1798, 1413, 740, +1939, 1776, 0, +2077, 2027, 0, +2195, 2214, 0, +2278, 2349, 0, +2369, 2484, 0, +2469, 2618, 0, +2574, 2751, 0, +2685, 2885, 0, +2801, 3017, 0, +2921, 3150, 0, +3043, 3282, 0, +3168, 3415, 0, +3295, 3547, 0, +3423, 3680, 0, +3552, 3812, 0, +3681, 3944, 0, +3812, 4076, 0, +3943, 4095, 0, +1961, 0, 1873, +1961, 0, 1870, +1960, 0, 1865, +1959, 0, 1860, +1958, 0, 1852, +1956, 0, 1841, +1953, 0, 1826, +1950, 0, 1806, +1945, 0, 1776, +1939, 0, 1734, +1939, 0, 1655, +1939, 0, 1523, +1939, 0, 1248, +1939, 573, 0, +1939, 1492, 0, +2077, 1886, 0, +2214, 2146, 0, +2343, 2349, 0, +2423, 2484, 0, +2512, 2618, 0, +2609, 2751, 0, +2713, 2885, 0, +2823, 3017, 0, +2938, 3150, 0, +3056, 3282, 0, +3178, 3415, 0, +3302, 3547, 0, +3428, 3680, 0, +3556, 3812, 0, +3685, 3944, 0, +3814, 4076, 0, +3944, 4095, 0, +2094, 0, 1966, +2093, 0, 1963, +2093, 0, 1960, +2092, 0, 1955, +2091, 0, 1949, +2089, 0, 1940, +2087, 0, 1928, +2085, 0, 1912, +2082, 0, 1889, +2077, 0, 1856, +2077, 0, 1797, +2077, 0, 1704, +2077, 0, 1539, +2077, 0, 1138, +2077, 173, 0, +2077, 1581, 0, +2214, 2000, 0, +2349, 2268, 0, +2484, 2481, 0, +2565, 2618, 0, +2652, 2751, 0, +2748, 2885, 0, +2850, 3017, 0, +2959, 3150, 0, +3073, 3282, 0, +3191, 3415, 0, +3312, 3547, 0, +3436, 3680, 0, +3562, 3812, 0, +3689, 3944, 0, +3817, 4076, 0, +3947, 4095, 0, +2226, 0, 2066, +2226, 0, 2064, +2225, 0, 2061, +2225, 0, 2058, +2224, 0, 2053, +2223, 0, 2046, +2221, 0, 2036, +2220, 0, 2023, +2217, 0, 2006, +2214, 0, 1981, +2214, 0, 1936, +2214, 0, 1870, +2214, 0, 1762, +2214, 0, 1560, +2214, 0, 932, +2214, 0, 0, +2214, 1677, 0, +2349, 2118, 0, +2484, 2393, 0, +2618, 2608, 0, +2704, 2751, 0, +2790, 2885, 0, +2885, 3017, 0, +2986, 3150, 0, +3094, 3282, 0, +3207, 3415, 0, +3325, 3547, 0, +3445, 3680, 0, +3569, 3812, 0, +3694, 3944, 0, +3821, 4076, 0, +3950, 4095, 0, +2358, 0, 2173, +2358, 0, 2171, +2358, 0, 2169, +2357, 0, 2166, +2357, 0, 2162, +2356, 0, 2157, +2355, 0, 2150, +2353, 0, 2140, +2352, 0, 2126, +2349, 0, 2107, +2349, 0, 2074, +2349, 0, 2025, +2349, 0, 1951, +2349, 0, 1829, +2349, 0, 1586, +2349, 0, 275, +2349, 0, 0, +2349, 1781, 0, +2484, 2240, 0, +2618, 2519, 0, +2751, 2737, 0, +2842, 2885, 0, +2927, 3017, 0, +3020, 3150, 0, +3121, 3282, 0, +3228, 3415, 0, +3341, 3547, 0, +3458, 3680, 0, +3579, 3812, 0, +3702, 3944, 0, +3827, 4076, 0, +3954, 4095, 0, +2491, 0, 2285, +2491, 0, 2284, +2490, 0, 2283, +2490, 0, 2280, +2489, 0, 2277, +2489, 0, 2273, +2488, 0, 2267, +2487, 0, 2260, +2486, 0, 2249, +2484, 0, 2235, +2484, 0, 2210, +2484, 0, 2174, +2484, 0, 2122, +2484, 0, 2042, +2484, 0, 1906, +2484, 0, 1620, +2484, 0, 0, +2484, 0, 0, +2484, 1891, 0, +2618, 2363, 0, +2751, 2647, 0, +2885, 2866, 0, +2977, 3017, 0, +3062, 3150, 0, +3155, 3282, 0, +3255, 3415, 0, +3362, 3547, 0, +3475, 3680, 0, +3591, 3812, 0, +3711, 3944, 0, +3834, 4076, 0, +3960, 4095, 0, +2623, 0, 2402, +2623, 0, 2401, +2623, 0, 2400, +2622, 0, 2398, +2622, 0, 2396, +2621, 0, 2393, +2621, 0, 2388, +2620, 0, 2382, +2619, 0, 2374, +2618, 0, 2363, +2618, 0, 2345, +2618, 0, 2319, +2618, 0, 2281, +2618, 0, 2226, +2618, 0, 2140, +2618, 0, 1991, +2618, 0, 1661, +2618, 0, 0, +2618, 0, 0, +2618, 2005, 0, +2751, 2490, 0, +2885, 2776, 0, +3017, 2996, 0, +3112, 3150, 0, +3196, 3282, 0, +3289, 3415, 0, +3389, 3547, 0, +3495, 3680, 0, +3607, 3812, 0, +3724, 3944, 0, +3844, 4076, 0, +3967, 4095, 0, +2755, 0, 2523, +2755, 0, 2522, +2755, 0, 2521, +2755, 0, 2520, +2755, 0, 2517, +2754, 0, 2515, +2754, 0, 2512, +2753, 0, 2507, +2752, 0, 2501, +2751, 0, 2493, +2751, 0, 2479, +2751, 0, 2460, +2751, 0, 2433, +2751, 0, 2394, +2751, 0, 2336, +2751, 0, 2245, +2751, 0, 2086, +2751, 0, 1711, +2751, 0, 0, +2751, 0, 0, +2751, 2123, 0, +2885, 2617, 0, +3017, 2905, 0, +3150, 3127, 0, +3247, 3282, 0, +3330, 3415, 0, +3422, 3547, 0, +3522, 3680, 0, +3629, 3812, 0, +3740, 3944, 0, +3856, 4076, 0, +3977, 4095, 0, +2887, 0, 2646, +2887, 0, 2645, +2887, 0, 2644, +2887, 0, 2643, +2887, 0, 2642, +2887, 0, 2640, +2886, 0, 2637, +2886, 0, 2634, +2885, 0, 2629, +2885, 0, 2623, +2885, 0, 2613, +2885, 0, 2599, +2885, 0, 2579, +2885, 0, 2551, +2885, 0, 2511, +2885, 0, 2451, +2885, 0, 2356, +2885, 0, 2188, +2885, 0, 1769, +2885, 0, 0, +2885, 0, 0, +2885, 2245, 0, +3017, 2745, 0, +3150, 3036, 0, +3282, 3257, 0, +3380, 3415, 0, +3464, 3547, 0, +3556, 3680, 0, +3655, 3812, 0, +3761, 3944, 0, +3873, 4076, 0, +3989, 4095, 0, +3019, 0, 2771, +3019, 0, 2770, +3019, 0, 2770, +3019, 0, 2769, +3019, 0, 2768, +3019, 0, 2766, +3018, 0, 2764, +3018, 0, 2762, +3018, 0, 2758, +3017, 0, 2754, +3017, 0, 2746, +3017, 0, 2735, +3017, 0, 2721, +3017, 0, 2701, +3017, 0, 2672, +3017, 0, 2631, +3017, 0, 2570, +3017, 0, 2471, +3017, 0, 2294, +3017, 0, 1837, +3017, 0, 0, +3017, 0, 0, +3017, 2369, 0, +3150, 2875, 0, +3282, 3166, 0, +3415, 3389, 0, +3513, 3547, 0, +3597, 3680, 0, +3689, 3812, 0, +3788, 3944, 0, +3894, 4076, 0, +4005, 4095, 0, +3152, 0, 2898, +3152, 0, 2897, +3152, 0, 2897, +3151, 0, 2896, +3151, 0, 2895, +3151, 0, 2895, +3151, 0, 2893, +3151, 0, 2891, +3151, 0, 2888, +3150, 0, 2885, +3150, 0, 2879, +3150, 0, 2871, +3150, 0, 2860, +3150, 0, 2846, +3150, 0, 2825, +3150, 0, 2796, +3150, 0, 2754, +3150, 0, 2691, +3150, 0, 2591, +3150, 0, 2408, +3150, 0, 1915, +3150, 0, 0, +3150, 0, 0, +3150, 2495, 0, +3282, 3005, 0, +3415, 3297, 0, +3547, 3520, 0, +3646, 3680, 0, +3729, 3812, 0, +3821, 3944, 0, +3921, 4076, 0, +4026, 4095, 0, +3284, 0, 3025, +3283, 0, 3025, +3283, 0, 3025, +3283, 0, 3025, +3283, 0, 3024, +3283, 0, 3023, +3283, 0, 3022, +3283, 0, 3021, +3283, 0, 3018, +3282, 0, 3016, +3282, 0, 3012, +3282, 0, 3006, +3282, 0, 2998, +3282, 0, 2987, +3282, 0, 2972, +3282, 0, 2951, +3282, 0, 2922, +3282, 0, 2879, +3282, 0, 2815, +3282, 0, 2713, +3282, 0, 2524, +3282, 0, 1999, +3282, 0, 0, +3282, 0, 0, +3282, 2622, 0, +3415, 3136, 0, +3547, 3429, 0, +3680, 3652, 0, +3779, 3812, 0, +3862, 3944, 0, +3953, 4076, 0, +4053, 4095, 0, +3416, 0, 3155, +3416, 0, 3154, +3416, 0, 3154, +3416, 0, 3154, +3416, 0, 3154, +3416, 0, 3153, +3415, 0, 3152, +3415, 0, 3151, +3415, 0, 3150, +3415, 0, 3147, +3415, 0, 3144, +3415, 0, 3140, +3415, 0, 3134, +3415, 0, 3126, +3415, 0, 3115, +3415, 0, 3100, +3415, 0, 3079, +3415, 0, 3049, +3415, 0, 3006, +3415, 0, 2942, +3415, 0, 2837, +3415, 0, 2646, +3415, 0, 2098, +3415, 0, 0, +3415, 0, 0, +3415, 2751, 0, +3547, 3267, 0, +3680, 3560, 0, +3812, 3784, 0, +3912, 3944, 0, +3995, 4076, 0, +4086, 4095, 0, +3548, 0, 3285, +3548, 0, 3284, +3548, 0, 3284, +3548, 0, 3284, +3548, 0, 3284, +3548, 0, 3283, +3548, 0, 3283, +3548, 0, 3282, +3548, 0, 3281, +3547, 0, 3279, +3547, 0, 3277, +3547, 0, 3274, +3547, 0, 3269, +3547, 0, 3263, +3547, 0, 3255, +3547, 0, 3244, +3547, 0, 3229, +3547, 0, 3208, +3547, 0, 3178, +3547, 0, 3135, +3547, 0, 3069, +3547, 0, 2964, +3547, 0, 2770, +3547, 0, 2198, +3547, 0, 0, +3547, 0, 0, +3547, 2880, 0, +3680, 3398, 0, +3812, 3692, 0, +3944, 3916, 0, +4044, 4076, 0, +4095, 4095, 0, +3680, 0, 3415, +3680, 0, 3415, +3680, 0, 3415, +3680, 0, 3415, +3680, 0, 3414, +3680, 0, 3414, +3680, 0, 3414, +3680, 0, 3413, +3680, 0, 3412, +3680, 0, 3411, +3680, 0, 3409, +3680, 0, 3407, +3680, 0, 3404, +3680, 0, 3399, +3680, 0, 3393, +3680, 0, 3385, +3680, 0, 3374, +3680, 0, 3359, +3680, 0, 3337, +3680, 0, 3307, +3680, 0, 3264, +3680, 0, 3198, +3680, 0, 3092, +3680, 0, 2895, +3680, 0, 2310, +3680, 0, 0, +3680, 0, 0, +3680, 3011, 0, +3812, 3530, 0, +3944, 3824, 0, +4076, 4047, 0, +4095, 4095, 0, +3812, 0, 3546, +3812, 0, 3546, +3812, 0, 3546, +3812, 0, 3545, +3812, 0, 3545, +3812, 0, 3545, +3812, 0, 3545, +3812, 0, 3544, +3812, 0, 3544, +3812, 0, 3543, +3812, 0, 3541, +3812, 0, 3540, +3812, 0, 3537, +3812, 0, 3534, +3812, 0, 3530, +3812, 0, 3523, +3812, 0, 3515, +3812, 0, 3504, +3812, 0, 3489, +3812, 0, 3468, +3812, 0, 3437, +3812, 0, 3394, +3812, 0, 3328, +3812, 0, 3221, +3812, 0, 3023, +3812, 0, 2422, +3812, 0, 0, +3812, 0, 0, +3812, 3141, 0, +3944, 3661, 0, +4076, 3955, 0, +4095, 4095, 0, +3944, 0, 3677, +3944, 0, 3677, +3944, 0, 3677, +3944, 0, 3677, +3944, 0, 3677, +3944, 0, 3676, +3944, 0, 3676, +3944, 0, 3676, +3944, 0, 3675, +3944, 0, 3675, +3944, 0, 3674, +3944, 0, 3673, +3944, 0, 3671, +3944, 0, 3668, +3944, 0, 3665, +3944, 0, 3661, +3944, 0, 3654, +3944, 0, 3646, +3944, 0, 3635, +3944, 0, 3620, +3944, 0, 3598, +3944, 0, 3568, +3944, 0, 3524, +3944, 0, 3458, +3944, 0, 3351, +3944, 0, 3151, +3944, 0, 2539, +3944, 0, 0, +3944, 0, 0, +3944, 3272, 0, +4076, 3793, 0, +4095, 4088, 0, +4076, 0, 3808, +4076, 0, 3808, +4076, 0, 3808, +4076, 0, 3808, +4076, 0, 3808, +4076, 0, 3808, +4076, 0, 3808, +4076, 0, 3808, +4076, 0, 3807, +4076, 0, 3807, +4076, 0, 3806, +4076, 0, 3805, +4076, 0, 3803, +4076, 0, 3802, +4076, 0, 3799, +4076, 0, 3796, +4076, 0, 3791, +4076, 0, 3785, +4076, 0, 3777, +4076, 0, 3766, +4076, 0, 3751, +4076, 0, 3729, +4076, 0, 3699, +4076, 0, 3655, +4076, 0, 3588, +4076, 0, 3480, +4076, 0, 3279, +4076, 0, 2659, +4076, 0, 0, +4076, 0, 0, +4076, 3403, 0, +4095, 3925, 0, +4095, 0, 3940, +4095, 0, 3940, +4095, 0, 3940, +4095, 0, 3940, +4095, 0, 3940, +4095, 0, 3940, +4095, 0, 3940, +4095, 0, 3940, +4095, 0, 3939, +4095, 0, 3939, +4095, 0, 3938, +4095, 0, 3937, +4095, 0, 3937, +4095, 0, 3935, +4095, 0, 3933, +4095, 0, 3931, +4095, 0, 3927, +4095, 0, 3923, +4095, 0, 3917, +4095, 0, 3909, +4095, 0, 3898, +4095, 0, 3882, +4095, 0, 3861, +4095, 0, 3830, +4095, 0, 3786, +4095, 0, 3720, +4095, 0, 3612, +4095, 0, 3410, +4095, 0, 2785, +4095, 0, 0, +4095, 0, 0, +4095, 3535, 0, +0, 1174, 1429, +0, 1192, 1429, +0, 1215, 1429, +0, 1244, 1429, +0, 1280, 1429, +0, 1323, 1429, +0, 1376, 1429, +0, 1429, 1419, +0, 1429, 1330, +0, 1429, 1174, +0, 1429, 816, +0, 1563, 0, +0, 1696, 0, +650, 1828, 0, +1220, 1961, 0, +1524, 2094, 0, +1753, 2226, 0, +1946, 2358, 0, +2119, 2491, 0, +2278, 2623, 0, +2431, 2755, 0, +2577, 2887, 0, +2720, 3019, 0, +2860, 3152, 0, +2997, 3284, 0, +3134, 3416, 0, +3269, 3548, 0, +3403, 3680, 0, +3537, 3812, 0, +3670, 3944, 0, +3803, 4076, 0, +3937, 4095, 0, +0, 1156, 1429, +0, 1178, 1427, +0, 1201, 1427, +0, 1231, 1427, +0, 1267, 1427, +0, 1313, 1427, +0, 1366, 1427, +0, 1427, 1424, +0, 1427, 1336, +0, 1427, 1182, +0, 1427, 833, +0, 1561, 0, +0, 1695, 0, +713, 1828, 0, +1238, 1961, 0, +1534, 2093, 0, +1759, 2226, 0, +1950, 2358, 0, +2121, 2491, 0, +2281, 2623, 0, +2432, 2755, 0, +2578, 2887, 0, +2720, 3019, 0, +2860, 3152, 0, +2998, 3283, 0, +3134, 3416, 0, +3269, 3548, 0, +3403, 3680, 0, +3537, 3812, 0, +3671, 3944, 0, +3803, 4076, 0, +3937, 4095, 0, +0, 1130, 1429, +0, 1153, 1427, +0, 1182, 1424, +0, 1213, 1424, +0, 1251, 1424, +0, 1298, 1424, +0, 1353, 1424, +0, 1418, 1424, +0, 1424, 1343, +0, 1424, 1193, +0, 1424, 856, +0, 1559, 0, +0, 1693, 0, +786, 1827, 0, +1263, 1960, 0, +1547, 2093, 0, +1767, 2225, 0, +1955, 2358, 0, +2125, 2490, 0, +2283, 2623, 0, +2434, 2755, 0, +2580, 2887, 0, +2721, 3019, 0, +2861, 3152, 0, +2998, 3283, 0, +3134, 3416, 0, +3269, 3548, 0, +3404, 3680, 0, +3537, 3812, 0, +3671, 3944, 0, +3803, 4076, 0, +3937, 4095, 0, +0, 1092, 1429, +0, 1118, 1427, +0, 1149, 1424, +0, 1188, 1421, +0, 1228, 1421, +0, 1277, 1421, +0, 1335, 1421, +0, 1403, 1421, +0, 1421, 1353, +0, 1421, 1207, +0, 1421, 885, +0, 1557, 0, +0, 1691, 0, +869, 1825, 0, +1294, 1959, 0, +1564, 2092, 0, +1777, 2225, 0, +1962, 2357, 0, +2129, 2490, 0, +2287, 2622, 0, +2436, 2755, 0, +2581, 2887, 0, +2723, 3019, 0, +2862, 3151, 0, +2999, 3283, 0, +3135, 3416, 0, +3270, 3548, 0, +3404, 3680, 0, +3538, 3812, 0, +3671, 3944, 0, +3804, 4076, 0, +3937, 4095, 0, +0, 1037, 1429, +0, 1065, 1427, +0, 1101, 1424, +0, 1144, 1421, +0, 1196, 1416, +0, 1248, 1416, +0, 1310, 1416, +0, 1381, 1416, +0, 1416, 1367, +0, 1416, 1225, +0, 1416, 920, +0, 1553, 0, +0, 1689, 0, +960, 1823, 0, +1332, 1958, 0, +1585, 2091, 0, +1790, 2224, 0, +1970, 2357, 0, +2136, 2489, 0, +2291, 2622, 0, +2440, 2755, 0, +2584, 2887, 0, +2724, 3019, 0, +2863, 3151, 0, +3000, 3283, 0, +3135, 3416, 0, +3270, 3548, 0, +3404, 3680, 0, +3538, 3812, 0, +3671, 3944, 0, +3804, 4076, 0, +3937, 4095, 0, +0, 951, 1429, +0, 985, 1427, +0, 1027, 1424, +0, 1077, 1421, +0, 1137, 1416, +0, 1206, 1410, +0, 1273, 1410, +0, 1350, 1410, +0, 1410, 1383, +0, 1410, 1248, +0, 1410, 964, +0, 1549, 0, +406, 1685, 0, +1059, 1821, 0, +1378, 1956, 0, +1612, 2089, 0, +1808, 2223, 0, +1982, 2356, 0, +2144, 2489, 0, +2297, 2621, 0, +2444, 2754, 0, +2587, 2887, 0, +2727, 3019, 0, +2865, 3151, 0, +3001, 3283, 0, +3136, 3416, 0, +3271, 3548, 0, +3405, 3680, 0, +3538, 3812, 0, +3671, 3944, 0, +3804, 4076, 0, +3937, 4095, 0, +0, 803, 1429, +0, 849, 1427, +0, 904, 1424, +0, 969, 1421, +0, 1043, 1416, +0, 1127, 1410, +344, 1219, 1402, +344, 1304, 1402, +344, 1398, 1402, +344, 1402, 1277, +344, 1402, 1017, +0, 1543, 172, +742, 1681, 0, +1164, 1817, 0, +1433, 1953, 0, +1646, 2087, 0, +1830, 2221, 0, +1998, 2355, 0, +2155, 2488, 0, +2304, 2621, 0, +2450, 2754, 0, +2591, 2886, 0, +2730, 3018, 0, +2867, 3151, 0, +3003, 3283, 0, +3138, 3415, 0, +3272, 3548, 0, +3406, 3680, 0, +3539, 3812, 0, +3672, 3944, 0, +3804, 4076, 0, +3937, 4095, 0, +0, 471, 1429, +0, 562, 1427, +0, 662, 1424, +0, 767, 1421, +0, 878, 1416, +0, 994, 1410, +344, 1114, 1402, +695, 1236, 1390, +695, 1343, 1390, +695, 1390, 1313, +695, 1390, 1078, +479, 1534, 476, +983, 1674, 0, +1275, 1813, 0, +1498, 1950, 0, +1687, 2085, 0, +1858, 2220, 0, +2017, 2353, 0, +2169, 2487, 0, +2314, 2620, 0, +2457, 2753, 0, +2596, 2886, 0, +2734, 3018, 0, +2870, 3151, 0, +3005, 3283, 0, +3139, 3415, 0, +3273, 3548, 0, +3406, 3680, 0, +3540, 3812, 0, +3672, 3944, 0, +3805, 4076, 0, +3937, 4095, 0, +0, 0, 1429, +0, 0, 1427, +0, 0, 1424, +0, 141, 1421, +0, 478, 1416, +0, 719, 1410, +344, 919, 1402, +695, 1095, 1390, +940, 1258, 1374, +940, 1374, 1357, +940, 1374, 1150, +926, 1523, 826, +1183, 1666, 608, +1391, 1807, 0, +1572, 1945, 0, +1738, 2082, 0, +1894, 2217, 0, +2042, 2352, 0, +2187, 2486, 0, +2328, 2619, 0, +2467, 2752, 0, +2603, 2885, 0, +2739, 3018, 0, +2874, 3151, 0, +3008, 3283, 0, +3141, 3415, 0, +3275, 3548, 0, +3408, 3680, 0, +3540, 3812, 0, +3673, 3944, 0, +3805, 4076, 0, +3938, 4095, 0, +0, 0, 1429, +0, 0, 1427, +0, 0, 1424, +0, 0, 1421, +0, 0, 1416, +47, 0, 1410, +344, 345, 1402, +695, 793, 1390, +940, 1069, 1374, +1142, 1286, 1352, +1142, 1352, 1231, +1202, 1507, 1073, +1360, 1654, 959, +1510, 1798, 740, +1655, 1939, 0, +1797, 2077, 0, +1936, 2214, 0, +2074, 2349, 0, +2210, 2484, 0, +2345, 2618, 0, +2479, 2751, 0, +2613, 2885, 0, +2746, 3017, 0, +2879, 3150, 0, +3012, 3282, 0, +3144, 3415, 0, +3277, 3547, 0, +3409, 3680, 0, +3541, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3938, 4095, 0, +816, 0, 1429, +833, 0, 1427, +856, 0, 1424, +885, 0, 1421, +920, 0, 1416, +964, 0, 1410, +1017, 344, 1402, +1078, 695, 1390, +1150, 940, 1374, +1231, 1142, 1352, +1320, 1320, 1320, +1418, 1484, 1274, +1522, 1638, 1205, +1633, 1787, 1090, +1748, 1930, 872, +1866, 2071, 79, +1988, 2209, 0, +2113, 2346, 0, +2239, 2481, 0, +2367, 2616, 0, +2495, 2750, 0, +2625, 2883, 0, +2755, 3016, 0, +2886, 3150, 0, +3017, 3282, 0, +3148, 3414, 0, +3280, 3547, 0, +3411, 3679, 0, +3543, 3812, 0, +3675, 3944, 0, +3807, 4076, 0, +3939, 4095, 0, +1301, 0, 1563, +1307, 0, 1561, +1315, 0, 1559, +1326, 0, 1557, +1340, 0, 1553, +1358, 0, 1549, +1381, 0, 1543, +1409, 476, 1534, +1445, 826, 1523, +1489, 1073, 1507, +1484, 1274, 1418, +1484, 1363, 1274, +1638, 1621, 1205, +1740, 1787, 1090, +1833, 1930, 872, +1934, 2071, 79, +2041, 2209, 0, +2153, 2346, 0, +2270, 2481, 0, +2390, 2616, 0, +2514, 2750, 0, +2639, 2883, 0, +2765, 3016, 0, +2894, 3150, 0, +3023, 3282, 0, +3152, 3414, 0, +3283, 3547, 0, +3414, 3679, 0, +3545, 3812, 0, +3676, 3944, 0, +3808, 4076, 0, +3940, 4095, 0, +1587, 0, 1696, +1590, 0, 1695, +1594, 0, 1693, +1600, 0, 1691, +1608, 0, 1689, +1618, 0, 1685, +1631, 0, 1681, +1648, 0, 1674, +1666, 608, 1663, +1654, 959, 1608, +1638, 1205, 1522, +1638, 1205, 1333, +1638, 1414, 1205, +1787, 1709, 1090, +1927, 1930, 872, +2010, 2071, 79, +2102, 2209, 0, +2202, 2346, 0, +2308, 2481, 0, +2420, 2616, 0, +2536, 2750, 0, +2656, 2883, 0, +2778, 3016, 0, +2904, 3150, 0, +3030, 3282, 0, +3158, 3414, 0, +3287, 3547, 0, +3417, 3679, 0, +3547, 3812, 0, +3678, 3944, 0, +3809, 4076, 0, +3941, 4095, 0, +1807, 0, 1828, +1810, 0, 1828, +1812, 0, 1827, +1816, 0, 1825, +1821, 0, 1823, +1821, 0, 1815, +1817, 0, 1799, +1813, 0, 1777, +1807, 0, 1746, +1798, 740, 1701, +1787, 1090, 1633, +1787, 1090, 1491, +1787, 1090, 1189, +1787, 1475, 1090, +1930, 1805, 872, +2071, 2044, 79, +2174, 2209, 0, +2260, 2346, 0, +2355, 2481, 0, +2456, 2616, 0, +2565, 2750, 0, +2678, 2883, 0, +2796, 3016, 0, +2917, 3150, 0, +3040, 3282, 0, +3165, 3414, 0, +3293, 3547, 0, +3421, 3679, 0, +3551, 3812, 0, +3680, 3944, 0, +3811, 4076, 0, +3942, 4095, 0, +1961, 0, 1923, +1961, 0, 1920, +1960, 0, 1917, +1959, 0, 1911, +1958, 0, 1905, +1956, 0, 1895, +1953, 0, 1882, +1950, 0, 1864, +1945, 0, 1838, +1939, 0, 1801, +1930, 872, 1748, +1930, 872, 1642, +1930, 872, 1447, +1930, 872, 873, +1930, 1545, 872, +2071, 1908, 79, +2209, 2159, 0, +2328, 2346, 0, +2410, 2481, 0, +2501, 2616, 0, +2601, 2750, 0, +2706, 2883, 0, +2817, 3016, 0, +2933, 3150, 0, +3053, 3282, 0, +3175, 3414, 0, +3300, 3547, 0, +3427, 3679, 0, +3555, 3812, 0, +3684, 3944, 0, +3813, 4076, 0, +3944, 4095, 0, +2094, 0, 2007, +2093, 0, 2005, +2093, 0, 2002, +2092, 0, 1997, +2091, 0, 1992, +2089, 0, 1984, +2087, 0, 1973, +2085, 0, 1958, +2082, 0, 1938, +2077, 0, 1908, +2071, 79, 1866, +2071, 79, 1787, +2071, 79, 1655, +2071, 79, 1379, +2071, 706, 79, +2071, 1625, 79, +2209, 2018, 0, +2346, 2278, 0, +2475, 2481, 0, +2555, 2616, 0, +2645, 2750, 0, +2741, 2883, 0, +2845, 3016, 0, +2955, 3150, 0, +3070, 3282, 0, +3188, 3414, 0, +3310, 3547, 0, +3434, 3679, 0, +3561, 3812, 0, +3688, 3944, 0, +3816, 4076, 0, +3946, 4095, 0, +2226, 0, 2100, +2226, 0, 2098, +2225, 0, 2095, +2225, 0, 2092, +2224, 0, 2087, +2223, 0, 2081, +2221, 0, 2072, +2220, 0, 2060, +2217, 0, 2044, +2214, 0, 2021, +2209, 0, 1988, +2209, 0, 1929, +2209, 0, 1836, +2209, 0, 1671, +2209, 0, 1270, +2209, 303, 0, +2209, 1713, 0, +2346, 2132, 0, +2481, 2401, 0, +2616, 2613, 0, +2697, 2750, 0, +2784, 2883, 0, +2880, 3016, 0, +2982, 3150, 0, +3091, 3282, 0, +3205, 3414, 0, +3323, 3547, 0, +3444, 3679, 0, +3568, 3812, 0, +3694, 3944, 0, +3821, 4076, 0, +3950, 4095, 0, +2358, 0, 2200, +2358, 0, 2199, +2358, 0, 2196, +2357, 0, 2193, +2357, 0, 2190, +2356, 0, 2185, +2355, 0, 2178, +2353, 0, 2168, +2352, 0, 2155, +2349, 0, 2138, +2346, 0, 2113, +2346, 0, 2069, +2346, 0, 2002, +2346, 0, 1894, +2346, 0, 1692, +2346, 0, 1064, +2346, 0, 0, +2346, 1809, 0, +2481, 2251, 0, +2616, 2525, 0, +2750, 2741, 0, +2836, 2883, 0, +2922, 3016, 0, +3017, 3150, 0, +3118, 3282, 0, +3226, 3414, 0, +3339, 3547, 0, +3457, 3679, 0, +3577, 3812, 0, +3701, 3944, 0, +3826, 4076, 0, +3954, 4095, 0, +2491, 0, 2306, +2491, 0, 2305, +2490, 0, 2304, +2490, 0, 2302, +2489, 0, 2298, +2489, 0, 2294, +2488, 0, 2289, +2487, 0, 2282, +2486, 0, 2272, +2484, 0, 2258, +2481, 0, 2239, +2481, 0, 2206, +2481, 0, 2158, +2481, 0, 2084, +2481, 0, 1961, +2481, 0, 1719, +2481, 0, 415, +2481, 0, 0, +2481, 1913, 0, +2616, 2372, 0, +2750, 2651, 0, +2883, 2869, 0, +2974, 3016, 0, +3059, 3150, 0, +3152, 3282, 0, +3253, 3414, 0, +3361, 3547, 0, +3473, 3679, 0, +3590, 3812, 0, +3711, 3944, 0, +3834, 4076, 0, +3959, 4095, 0, +2623, 0, 2419, +2623, 0, 2417, +2623, 0, 2416, +2622, 0, 2414, +2622, 0, 2412, +2621, 0, 2409, +2621, 0, 2405, +2620, 0, 2399, +2619, 0, 2392, +2618, 0, 2381, +2616, 0, 2367, +2616, 0, 2342, +2616, 0, 2306, +2616, 0, 2255, +2616, 0, 2174, +2616, 0, 2038, +2616, 0, 1752, +2616, 0, 0, +2616, 0, 0, +2616, 2022, 0, +2750, 2496, 0, +2883, 2779, 0, +3016, 2998, 0, +3110, 3150, 0, +3194, 3282, 0, +3287, 3414, 0, +3387, 3547, 0, +3494, 3679, 0, +3606, 3812, 0, +3723, 3944, 0, +3843, 4076, 0, +3967, 4095, 0, +2755, 0, 2535, +2755, 0, 2535, +2755, 0, 2533, +2755, 0, 2532, +2755, 0, 2530, +2754, 0, 2528, +2754, 0, 2525, +2753, 0, 2521, +2752, 0, 2514, +2751, 0, 2506, +2750, 0, 2495, +2750, 0, 2477, +2750, 0, 2451, +2750, 0, 2414, +2750, 0, 2359, +2750, 0, 2273, +2750, 0, 2124, +2750, 0, 1794, +2750, 0, 0, +2750, 0, 0, +2750, 2137, 0, +2883, 2621, 0, +3016, 2907, 0, +3150, 3128, 0, +3244, 3282, 0, +3329, 3414, 0, +3421, 3547, 0, +3521, 3679, 0, +3628, 3812, 0, +3740, 3944, 0, +3856, 4076, 0, +3976, 4095, 0, +2887, 0, 2655, +2887, 0, 2655, +2887, 0, 2654, +2887, 0, 2653, +2887, 0, 2651, +2887, 0, 2650, +2886, 0, 2647, +2886, 0, 2644, +2885, 0, 2639, +2885, 0, 2633, +2883, 0, 2625, +2883, 0, 2611, +2883, 0, 2592, +2883, 0, 2565, +2883, 0, 2526, +2883, 0, 2469, +2883, 0, 2378, +2883, 0, 2218, +2883, 0, 1843, +2883, 0, 0, +2883, 0, 0, +2883, 2255, 0, +3016, 2749, 0, +3150, 3038, 0, +3282, 3259, 0, +3379, 3414, 0, +3462, 3547, 0, +3554, 3679, 0, +3654, 3812, 0, +3761, 3944, 0, +3872, 4076, 0, +3989, 4095, 0, +3019, 0, 2778, +3019, 0, 2777, +3019, 0, 2777, +3019, 0, 2776, +3019, 0, 2775, +3019, 0, 2774, +3018, 0, 2772, +3018, 0, 2769, +3018, 0, 2766, +3017, 0, 2761, +3016, 0, 2755, +3016, 0, 2745, +3016, 0, 2731, +3016, 0, 2711, +3016, 0, 2683, +3016, 0, 2643, +3016, 0, 2583, +3016, 0, 2488, +3016, 0, 2319, +3016, 0, 1900, +3016, 0, 0, +3016, 0, 0, +3016, 2377, 0, +3150, 2878, 0, +3282, 3168, 0, +3414, 3390, 0, +3512, 3547, 0, +3596, 3679, 0, +3688, 3812, 0, +3787, 3944, 0, +3893, 4076, 0, +4005, 4095, 0, +3152, 0, 2903, +3152, 0, 2903, +3152, 0, 2903, +3151, 0, 2902, +3151, 0, 2901, +3151, 0, 2900, +3151, 0, 2898, +3151, 0, 2896, +3151, 0, 2894, +3150, 0, 2891, +3150, 0, 2886, +3150, 0, 2878, +3150, 0, 2868, +3150, 0, 2853, +3150, 0, 2833, +3150, 0, 2804, +3150, 0, 2763, +3150, 0, 2702, +3150, 0, 2604, +3150, 0, 2427, +3150, 0, 1969, +3150, 0, 0, +3150, 0, 0, +3150, 2501, 0, +3282, 3006, 0, +3414, 3298, 0, +3547, 3521, 0, +3646, 3679, 0, +3729, 3812, 0, +3820, 3944, 0, +3920, 4076, 0, +4026, 4095, 0, +3284, 0, 3030, +3283, 0, 3029, +3283, 0, 3029, +3283, 0, 3029, +3283, 0, 3028, +3283, 0, 3027, +3283, 0, 3026, +3283, 0, 3025, +3283, 0, 3023, +3282, 0, 3020, +3282, 0, 3017, +3282, 0, 3011, +3282, 0, 3003, +3282, 0, 2992, +3282, 0, 2977, +3282, 0, 2957, +3282, 0, 2928, +3282, 0, 2886, +3282, 0, 2823, +3282, 0, 2723, +3282, 0, 2539, +3282, 0, 2045, +3282, 0, 0, +3282, 0, 0, +3282, 2627, 0, +3414, 3137, 0, +3547, 3429, 0, +3679, 3653, 0, +3778, 3812, 0, +3862, 3944, 0, +3953, 4076, 0, +4053, 4095, 0, +3416, 0, 3158, +3416, 0, 3158, +3416, 0, 3157, +3416, 0, 3157, +3416, 0, 3157, +3416, 0, 3156, +3415, 0, 3155, +3415, 0, 3154, +3415, 0, 3153, +3415, 0, 3151, +3414, 0, 3148, +3414, 0, 3144, +3414, 0, 3138, +3414, 0, 3130, +3414, 0, 3119, +3414, 0, 3104, +3414, 0, 3083, +3414, 0, 3054, +3414, 0, 3011, +3414, 0, 2947, +3414, 0, 2845, +3414, 0, 2657, +3414, 0, 2135, +3414, 0, 0, +3414, 0, 0, +3414, 2754, 0, +3547, 3268, 0, +3679, 3561, 0, +3812, 3784, 0, +3911, 3944, 0, +3994, 4076, 0, +4086, 4095, 0, +3548, 0, 3287, +3548, 0, 3287, +3548, 0, 3287, +3548, 0, 3286, +3548, 0, 3286, +3548, 0, 3286, +3548, 0, 3285, +3548, 0, 3284, +3548, 0, 3283, +3547, 0, 3282, +3547, 0, 3280, +3547, 0, 3277, +3547, 0, 3272, +3547, 0, 3266, +3547, 0, 3258, +3547, 0, 3247, +3547, 0, 3232, +3547, 0, 3211, +3547, 0, 3181, +3547, 0, 3138, +3547, 0, 3074, +3547, 0, 2970, +3547, 0, 2778, +3547, 0, 2228, +3547, 0, 0, +3547, 0, 0, +3547, 2883, 0, +3679, 3399, 0, +3812, 3692, 0, +3944, 3916, 0, +4044, 4076, 0, +4095, 4095, 0, +3680, 0, 3417, +3680, 0, 3417, +3680, 0, 3417, +3680, 0, 3416, +3680, 0, 3416, +3680, 0, 3416, +3680, 0, 3415, +3680, 0, 3415, +3680, 0, 3414, +3680, 0, 3413, +3679, 0, 3411, +3679, 0, 3409, +3679, 0, 3406, +3679, 0, 3401, +3679, 0, 3395, +3679, 0, 3387, +3679, 0, 3376, +3679, 0, 3361, +3679, 0, 3340, +3679, 0, 3310, +3679, 0, 3267, +3679, 0, 3201, +3679, 0, 3096, +3679, 0, 2901, +3679, 0, 2333, +3679, 0, 0, +3679, 0, 0, +3679, 3013, 0, +3812, 3530, 0, +3944, 3824, 0, +4076, 4048, 0, +4095, 4095, 0, +3812, 0, 3547, +3812, 0, 3547, +3812, 0, 3547, +3812, 0, 3547, +3812, 0, 3547, +3812, 0, 3547, +3812, 0, 3546, +3812, 0, 3546, +3812, 0, 3545, +3812, 0, 3544, +3812, 0, 3543, +3812, 0, 3541, +3812, 0, 3539, +3812, 0, 3536, +3812, 0, 3531, +3812, 0, 3525, +3812, 0, 3517, +3812, 0, 3506, +3812, 0, 3491, +3812, 0, 3469, +3812, 0, 3439, +3812, 0, 3396, +3812, 0, 3330, +3812, 0, 3224, +3812, 0, 3027, +3812, 0, 2441, +3812, 0, 0, +3812, 0, 0, +3812, 3143, 0, +3944, 3661, 0, +4076, 3955, 0, +4095, 4095, 0, +3944, 0, 3678, +3944, 0, 3678, +3944, 0, 3678, +3944, 0, 3678, +3944, 0, 3678, +3944, 0, 3677, +3944, 0, 3677, +3944, 0, 3677, +3944, 0, 3676, +3944, 0, 3676, +3944, 0, 3675, +3944, 0, 3674, +3944, 0, 3672, +3944, 0, 3669, +3944, 0, 3666, +3944, 0, 3662, +3944, 0, 3656, +3944, 0, 3648, +3944, 0, 3636, +3944, 0, 3621, +3944, 0, 3600, +3944, 0, 3569, +3944, 0, 3526, +3944, 0, 3459, +3944, 0, 3353, +3944, 0, 3154, +3944, 0, 2553, +3944, 0, 0, +3944, 0, 0, +3944, 3273, 0, +4076, 3793, 0, +4095, 4088, 0, +4076, 0, 3809, +4076, 0, 3809, +4076, 0, 3809, +4076, 0, 3809, +4076, 0, 3809, +4076, 0, 3809, +4076, 0, 3808, +4076, 0, 3808, +4076, 0, 3808, +4076, 0, 3808, +4076, 0, 3807, +4076, 0, 3806, +4076, 0, 3804, +4076, 0, 3803, +4076, 0, 3800, +4076, 0, 3797, +4076, 0, 3793, +4076, 0, 3787, +4076, 0, 3778, +4076, 0, 3767, +4076, 0, 3752, +4076, 0, 3730, +4076, 0, 3700, +4076, 0, 3656, +4076, 0, 3590, +4076, 0, 3482, +4076, 0, 3282, +4076, 0, 2670, +4076, 0, 0, +4076, 0, 0, +4076, 3404, 0, +4095, 3925, 0, +4095, 0, 3941, +4095, 0, 3941, +4095, 0, 3941, +4095, 0, 3941, +4095, 0, 3941, +4095, 0, 3941, +4095, 0, 3940, +4095, 0, 3940, +4095, 0, 3940, +4095, 0, 3940, +4095, 0, 3939, +4095, 0, 3938, +4095, 0, 3937, +4095, 0, 3936, +4095, 0, 3934, +4095, 0, 3932, +4095, 0, 3928, +4095, 0, 3924, +4095, 0, 3918, +4095, 0, 3910, +4095, 0, 3898, +4095, 0, 3883, +4095, 0, 3862, +4095, 0, 3831, +4095, 0, 3787, +4095, 0, 3721, +4095, 0, 3613, +4095, 0, 3412, +4095, 0, 2793, +4095, 0, 0, +4095, 0, 0, +4095, 3536, 0, +0, 1304, 1563, +0, 1318, 1563, +0, 1335, 1563, +0, 1357, 1563, +0, 1385, 1563, +0, 1421, 1563, +0, 1463, 1563, +0, 1515, 1563, +0, 1563, 1548, +0, 1563, 1458, +0, 1563, 1301, +0, 1563, 934, +0, 1696, 0, +0, 1828, 0, +726, 1961, 0, +1336, 2094, 0, +1648, 2226, 0, +1880, 2358, 0, +2075, 2491, 0, +2248, 2623, 0, +2409, 2755, 0, +2562, 2887, 0, +2708, 3019, 0, +2851, 3152, 0, +2991, 3284, 0, +3129, 3416, 0, +3266, 3548, 0, +3401, 3680, 0, +3535, 3812, 0, +3669, 3944, 0, +3803, 4076, 0, +3936, 4095, 0, +0, 1290, 1563, +0, 1307, 1561, +0, 1325, 1561, +0, 1347, 1561, +0, 1376, 1561, +0, 1412, 1561, +0, 1456, 1561, +0, 1508, 1561, +0, 1561, 1552, +0, 1561, 1463, +0, 1561, 1307, +0, 1561, 948, +0, 1695, 0, +0, 1828, 0, +780, 1961, 0, +1351, 2093, 0, +1656, 2226, 0, +1885, 2358, 0, +2078, 2491, 0, +2250, 2623, 0, +2411, 2755, 0, +2563, 2887, 0, +2709, 3019, 0, +2852, 3152, 0, +2992, 3283, 0, +3129, 3416, 0, +3266, 3548, 0, +3401, 3680, 0, +3536, 3812, 0, +3669, 3944, 0, +3803, 4076, 0, +3936, 4095, 0, +0, 1271, 1563, +0, 1288, 1561, +0, 1310, 1559, +0, 1333, 1559, +0, 1363, 1559, +0, 1400, 1559, +0, 1445, 1559, +0, 1499, 1559, +0, 1559, 1556, +0, 1559, 1468, +0, 1559, 1315, +0, 1559, 966, +0, 1693, 0, +0, 1827, 0, +844, 1960, 0, +1370, 2093, 0, +1666, 2225, 0, +1891, 2358, 0, +2082, 2490, 0, +2253, 2623, 0, +2413, 2755, 0, +2564, 2887, 0, +2710, 3019, 0, +2853, 3152, 0, +2992, 3283, 0, +3130, 3416, 0, +3266, 3548, 0, +3401, 3680, 0, +3536, 3812, 0, +3669, 3944, 0, +3803, 4076, 0, +3936, 4095, 0, +0, 1244, 1563, +0, 1262, 1561, +0, 1285, 1559, +0, 1315, 1557, +0, 1345, 1557, +0, 1384, 1557, +0, 1430, 1557, +0, 1486, 1557, +0, 1551, 1557, +0, 1557, 1476, +0, 1557, 1326, +0, 1557, 988, +0, 1691, 0, +0, 1825, 0, +917, 1959, 0, +1394, 2092, 0, +1679, 2225, 0, +1899, 2357, 0, +2087, 2490, 0, +2256, 2622, 0, +2415, 2755, 0, +2566, 2887, 0, +2712, 3019, 0, +2854, 3151, 0, +2993, 3283, 0, +3130, 3416, 0, +3267, 3548, 0, +3401, 3680, 0, +3536, 3812, 0, +3669, 3944, 0, +3803, 4076, 0, +3936, 4095, 0, +0, 1205, 1563, +0, 1225, 1561, +0, 1250, 1559, +0, 1281, 1557, +0, 1320, 1553, +0, 1360, 1553, +0, 1409, 1553, +0, 1467, 1553, +0, 1535, 1553, +0, 1553, 1486, +0, 1553, 1340, +0, 1553, 1017, +0, 1689, 0, +0, 1823, 0, +1000, 1958, 0, +1425, 2091, 0, +1695, 2224, 0, +1909, 2357, 0, +2094, 2489, 0, +2261, 2622, 0, +2419, 2755, 0, +2569, 2887, 0, +2713, 3019, 0, +2855, 3151, 0, +2994, 3283, 0, +3131, 3416, 0, +3267, 3548, 0, +3402, 3680, 0, +3536, 3812, 0, +3670, 3944, 0, +3803, 4076, 0, +3936, 4095, 0, +0, 1148, 1563, +0, 1170, 1561, +0, 1198, 1559, +0, 1233, 1557, +0, 1276, 1553, +0, 1328, 1549, +0, 1380, 1549, +0, 1442, 1549, +0, 1513, 1549, +0, 1549, 1499, +0, 1549, 1358, +0, 1549, 1053, +0, 1685, 0, +0, 1821, 0, +1091, 1956, 0, +1463, 2089, 0, +1717, 2223, 0, +1922, 2356, 0, +2103, 2489, 0, +2268, 2621, 0, +2423, 2754, 0, +2572, 2887, 0, +2716, 3019, 0, +2857, 3151, 0, +2995, 3283, 0, +3132, 3416, 0, +3268, 3548, 0, +3402, 3680, 0, +3537, 3812, 0, +3670, 3944, 0, +3803, 4076, 0, +3936, 4095, 0, +0, 1057, 1563, +0, 1084, 1561, +0, 1118, 1559, +0, 1159, 1557, +0, 1209, 1553, +0, 1269, 1549, +0, 1338, 1543, +0, 1405, 1543, +0, 1482, 1543, +0, 1543, 1516, +0, 1543, 1381, +0, 1543, 1096, +0, 1681, 0, +536, 1817, 0, +1190, 1953, 0, +1509, 2087, 0, +1744, 2221, 0, +1940, 2355, 0, +2115, 2488, 0, +2276, 2621, 0, +2429, 2754, 0, +2576, 2886, 0, +2719, 3018, 0, +2859, 3151, 0, +2997, 3283, 0, +3133, 3415, 0, +3269, 3548, 0, +3403, 3680, 0, +3537, 3812, 0, +3670, 3944, 0, +3803, 4076, 0, +3937, 4095, 0, +0, 897, 1563, +0, 935, 1561, +0, 981, 1559, +0, 1037, 1557, +0, 1102, 1553, +0, 1176, 1549, +0, 1259, 1543, +476, 1351, 1534, +476, 1437, 1534, +476, 1531, 1534, +476, 1534, 1409, +476, 1534, 1149, +0, 1674, 313, +874, 1813, 0, +1295, 1950, 0, +1565, 2085, 0, +1778, 2220, 0, +1962, 2353, 0, +2130, 2487, 0, +2287, 2620, 0, +2437, 2753, 0, +2581, 2886, 0, +2723, 3018, 0, +2862, 3151, 0, +2999, 3283, 0, +3135, 3415, 0, +3270, 3548, 0, +3404, 3680, 0, +3538, 3812, 0, +3671, 3944, 0, +3804, 4076, 0, +3937, 4095, 0, +0, 523, 1563, +0, 605, 1561, +0, 696, 1559, +0, 794, 1557, +0, 900, 1553, +0, 1011, 1549, +0, 1127, 1543, +476, 1246, 1534, +826, 1368, 1523, +826, 1476, 1523, +826, 1523, 1445, +826, 1523, 1211, +608, 1666, 609, +1115, 1807, 0, +1407, 1945, 0, +1630, 2082, 0, +1819, 2217, 0, +1990, 2352, 0, +2149, 2486, 0, +2301, 2619, 0, +2447, 2752, 0, +2589, 2885, 0, +2728, 3018, 0, +2866, 3151, 0, +3002, 3283, 0, +3137, 3415, 0, +3271, 3548, 0, +3405, 3680, 0, +3538, 3812, 0, +3671, 3944, 0, +3804, 4076, 0, +3937, 4095, 0, +0, 0, 1563, +0, 0, 1561, +0, 0, 1559, +0, 0, 1557, +0, 275, 1553, +0, 611, 1549, +0, 852, 1543, +476, 1051, 1534, +826, 1228, 1523, +1073, 1390, 1507, +1073, 1507, 1489, +1073, 1507, 1282, +1056, 1654, 959, +1315, 1798, 740, +1523, 1939, 0, +1704, 2077, 0, +1870, 2214, 0, +2025, 2349, 0, +2174, 2484, 0, +2319, 2618, 0, +2460, 2751, 0, +2599, 2885, 0, +2735, 3017, 0, +2871, 3150, 0, +3006, 3282, 0, +3140, 3415, 0, +3274, 3547, 0, +3407, 3680, 0, +3540, 3812, 0, +3673, 3944, 0, +3805, 4076, 0, +3937, 4095, 0, +0, 0, 1563, +0, 0, 1561, +0, 0, 1559, +0, 0, 1557, +0, 0, 1553, +0, 0, 1549, +172, 0, 1543, +476, 479, 1534, +826, 926, 1523, +1073, 1202, 1507, +1274, 1418, 1484, +1274, 1484, 1363, +1333, 1638, 1205, +1491, 1787, 1090, +1642, 1930, 872, +1787, 2071, 79, +1929, 2209, 0, +2069, 2346, 0, +2206, 2481, 0, +2342, 2616, 0, +2477, 2750, 0, +2611, 2883, 0, +2745, 3016, 0, +2878, 3150, 0, +3011, 3282, 0, +3144, 3414, 0, +3277, 3547, 0, +3409, 3679, 0, +3541, 3812, 0, +3674, 3944, 0, +3806, 4076, 0, +3938, 4095, 0, +934, 0, 1563, +948, 0, 1561, +966, 0, 1559, +988, 0, 1557, +1017, 0, 1553, +1053, 0, 1549, +1096, 0, 1543, +1149, 476, 1534, +1211, 826, 1523, +1282, 1073, 1507, +1363, 1274, 1484, +1453, 1453, 1453, +1550, 1616, 1407, +1654, 1771, 1337, +1765, 1919, 1223, +1880, 2062, 1005, +1998, 2203, 217, +2120, 2341, 0, +2245, 2478, 0, +2371, 2613, 0, +2499, 2748, 0, +2628, 2882, 0, +2757, 3015, 0, +2887, 3149, 0, +3018, 3281, 0, +3149, 3414, 0, +3280, 3547, 0, +3412, 3679, 0, +3544, 3812, 0, +3675, 3944, 0, +3807, 4076, 0, +3939, 4095, 0, +1427, 0, 1696, +1432, 0, 1695, +1439, 0, 1693, +1447, 0, 1691, +1457, 0, 1689, +1471, 0, 1685, +1489, 0, 1681, +1512, 0, 1674, +1541, 608, 1666, +1577, 959, 1654, +1621, 1205, 1638, +1616, 1407, 1550, +1616, 1495, 1407, +1771, 1754, 1337, +1872, 1919, 1223, +1965, 2062, 1005, +2066, 2203, 217, +2173, 2341, 0, +2285, 2478, 0, +2402, 2613, 0, +2522, 2748, 0, +2645, 2882, 0, +2770, 3015, 0, +2898, 3149, 0, +3025, 3281, 0, +3155, 3414, 0, +3285, 3547, 0, +3415, 3679, 0, +3546, 3812, 0, +3677, 3944, 0, +3808, 4076, 0, +3940, 4095, 0, +1716, 0, 1828, +1719, 0, 1828, +1722, 0, 1827, +1727, 0, 1825, +1732, 0, 1823, +1740, 0, 1821, +1750, 0, 1817, +1763, 0, 1813, +1780, 0, 1807, +1798, 740, 1795, +1787, 1090, 1740, +1771, 1337, 1654, +1771, 1337, 1466, +1771, 1546, 1337, +1919, 1841, 1223, +2059, 2062, 1005, +2142, 2203, 217, +2234, 2341, 0, +2334, 2478, 0, +2440, 2613, 0, +2552, 2748, 0, +2668, 2882, 0, +2788, 3015, 0, +2911, 3149, 0, +3035, 3281, 0, +3162, 3414, 0, +3290, 3547, 0, +3419, 3679, 0, +3549, 3812, 0, +3679, 3944, 0, +3810, 4076, 0, +3941, 4095, 0, +1938, 0, 1961, +1940, 0, 1961, +1941, 0, 1960, +1944, 0, 1959, +1948, 0, 1958, +1953, 0, 1956, +1953, 0, 1947, +1950, 0, 1931, +1945, 0, 1909, +1939, 0, 1878, +1930, 872, 1833, +1919, 1223, 1765, +1919, 1223, 1624, +1919, 1223, 1321, +1919, 1607, 1223, +2062, 1937, 1005, +2203, 2176, 217, +2305, 2341, 0, +2392, 2478, 0, +2487, 2613, 0, +2589, 2748, 0, +2697, 2882, 0, +2810, 3015, 0, +2928, 3149, 0, +3049, 3281, 0, +3172, 3414, 0, +3298, 3547, 0, +3425, 3679, 0, +3553, 3812, 0, +3683, 3944, 0, +3812, 4076, 0, +3943, 4095, 0, +2094, 0, 2058, +2093, 0, 2056, +2093, 0, 2053, +2092, 0, 2049, +2091, 0, 2044, +2089, 0, 2037, +2087, 0, 2027, +2085, 0, 2014, +2082, 0, 1996, +2077, 0, 1970, +2071, 79, 1934, +2062, 1005, 1880, +2062, 1005, 1774, +2062, 1005, 1579, +2062, 1005, 1006, +2062, 1677, 1005, +2203, 2041, 217, +2341, 2291, 0, +2460, 2478, 0, +2542, 2613, 0, +2634, 2748, 0, +2733, 2882, 0, +2838, 3015, 0, +2950, 3149, 0, +3065, 3281, 0, +3185, 3414, 0, +3307, 3547, 0, +3432, 3679, 0, +3559, 3812, 0, +3687, 3944, 0, +3816, 4076, 0, +3946, 4095, 0, +2226, 0, 2141, +2226, 0, 2140, +2225, 0, 2137, +2225, 0, 2134, +2224, 0, 2130, +2223, 0, 2124, +2221, 0, 2116, +2220, 0, 2105, +2217, 0, 2090, +2214, 0, 2070, +2209, 0, 2041, +2203, 217, 1998, +2203, 217, 1920, +2203, 217, 1787, +2203, 217, 1512, +2203, 838, 217, +2203, 1757, 217, +2341, 2150, 0, +2478, 2411, 0, +2607, 2613, 0, +2687, 2748, 0, +2777, 2882, 0, +2873, 3015, 0, +2977, 3149, 0, +3087, 3281, 0, +3202, 3414, 0, +3320, 3547, 0, +3442, 3679, 0, +3566, 3812, 0, +3692, 3944, 0, +3820, 4076, 0, +3949, 4095, 0, +2358, 0, 2233, +2358, 0, 2232, +2358, 0, 2230, +2357, 0, 2228, +2357, 0, 2224, +2356, 0, 2219, +2355, 0, 2213, +2353, 0, 2204, +2352, 0, 2192, +2349, 0, 2176, +2346, 0, 2153, +2341, 0, 2120, +2341, 0, 2061, +2341, 0, 1968, +2341, 0, 1803, +2341, 0, 1403, +2341, 437, 0, +2341, 1845, 0, +2478, 2264, 0, +2613, 2533, 0, +2748, 2745, 0, +2829, 2882, 0, +2916, 3015, 0, +3012, 3149, 0, +3114, 3281, 0, +3223, 3414, 0, +3337, 3547, 0, +3455, 3679, 0, +3576, 3812, 0, +3700, 3944, 0, +3826, 4076, 0, +3953, 4095, 0, +2491, 0, 2333, +2491, 0, 2332, +2490, 0, 2331, +2490, 0, 2329, +2489, 0, 2326, +2489, 0, 2322, +2488, 0, 2317, +2487, 0, 2310, +2486, 0, 2301, +2484, 0, 2288, +2481, 0, 2270, +2478, 0, 2245, +2478, 0, 2201, +2478, 0, 2134, +2478, 0, 2026, +2478, 0, 1824, +2478, 0, 1199, +2478, 0, 0, +2478, 1941, 0, +2613, 2382, 0, +2748, 2657, 0, +2882, 2873, 0, +2968, 3015, 0, +3055, 3149, 0, +3149, 3281, 0, +3250, 3414, 0, +3358, 3547, 0, +3472, 3679, 0, +3589, 3812, 0, +3710, 3944, 0, +3833, 4076, 0, +3959, 4095, 0, +2623, 0, 2440, +2623, 0, 2439, +2623, 0, 2437, +2622, 0, 2436, +2622, 0, 2434, +2621, 0, 2431, +2621, 0, 2427, +2620, 0, 2421, +2619, 0, 2414, +2618, 0, 2404, +2616, 0, 2390, +2613, 0, 2371, +2613, 0, 2338, +2613, 0, 2290, +2613, 0, 2216, +2613, 0, 2093, +2613, 0, 1851, +2613, 0, 547, +2613, 0, 0, +2613, 2045, 0, +2748, 2504, 0, +2882, 2784, 0, +3015, 3001, 0, +3106, 3149, 0, +3191, 3281, 0, +3284, 3414, 0, +3385, 3547, 0, +3493, 3679, 0, +3605, 3812, 0, +3722, 3944, 0, +3843, 4076, 0, +3966, 4095, 0, +2755, 0, 2552, +2755, 0, 2551, +2755, 0, 2550, +2755, 0, 2549, +2755, 0, 2547, +2754, 0, 2545, +2754, 0, 2541, +2753, 0, 2537, +2752, 0, 2532, +2751, 0, 2524, +2750, 0, 2514, +2748, 0, 2499, +2748, 0, 2474, +2748, 0, 2439, +2748, 0, 2387, +2748, 0, 2306, +2748, 0, 2170, +2748, 0, 1885, +2748, 0, 0, +2748, 0, 0, +2748, 2155, 0, +2882, 2628, 0, +3015, 2911, 0, +3149, 3131, 0, +3242, 3281, 0, +3326, 3414, 0, +3419, 3547, 0, +3520, 3679, 0, +3626, 3812, 0, +3739, 3944, 0, +3855, 4076, 0, +3976, 4095, 0, +2887, 0, 2668, +2887, 0, 2667, +2887, 0, 2667, +2887, 0, 2666, +2887, 0, 2664, +2887, 0, 2662, +2886, 0, 2660, +2886, 0, 2657, +2885, 0, 2652, +2885, 0, 2647, +2883, 0, 2639, +2882, 0, 2628, +2882, 0, 2609, +2882, 0, 2583, +2882, 0, 2546, +2882, 0, 2491, +2882, 0, 2405, +2882, 0, 2256, +2882, 0, 1925, +2882, 0, 0, +2882, 0, 0, +2882, 2269, 0, +3015, 2753, 0, +3149, 3040, 0, +3281, 3260, 0, +3376, 3414, 0, +3461, 3547, 0, +3553, 3679, 0, +3653, 3812, 0, +3760, 3944, 0, +3872, 4076, 0, +3988, 4095, 0, +3019, 0, 2788, +3019, 0, 2787, +3019, 0, 2787, +3019, 0, 2786, +3019, 0, 2785, +3019, 0, 2784, +3018, 0, 2782, +3018, 0, 2779, +3018, 0, 2776, +3017, 0, 2771, +3016, 0, 2765, +3015, 0, 2757, +3015, 0, 2743, +3015, 0, 2724, +3015, 0, 2697, +3015, 0, 2658, +3015, 0, 2600, +3015, 0, 2510, +3015, 0, 2350, +3015, 0, 1974, +3015, 0, 0, +3015, 0, 0, +3015, 2387, 0, +3149, 2881, 0, +3281, 3169, 0, +3414, 3391, 0, +3511, 3547, 0, +3595, 3679, 0, +3687, 3812, 0, +3786, 3944, 0, +3892, 4076, 0, +4005, 4095, 0, +3152, 0, 2911, +3152, 0, 2910, +3152, 0, 2910, +3151, 0, 2909, +3151, 0, 2908, +3151, 0, 2907, +3151, 0, 2906, +3151, 0, 2904, +3151, 0, 2902, +3150, 0, 2898, +3150, 0, 2894, +3149, 0, 2887, +3149, 0, 2877, +3149, 0, 2863, +3149, 0, 2843, +3149, 0, 2815, +3149, 0, 2775, +3149, 0, 2715, +3149, 0, 2620, +3149, 0, 2452, +3149, 0, 2033, +3149, 0, 0, +3149, 0, 0, +3149, 2509, 0, +3281, 3009, 0, +3414, 3299, 0, +3547, 3522, 0, +3644, 3679, 0, +3728, 3812, 0, +3820, 3944, 0, +3919, 4076, 0, +4026, 4095, 0, +3284, 0, 3035, +3283, 0, 3035, +3283, 0, 3035, +3283, 0, 3034, +3283, 0, 3034, +3283, 0, 3033, +3283, 0, 3032, +3283, 0, 3031, +3283, 0, 3029, +3282, 0, 3026, +3282, 0, 3023, +3281, 0, 3018, +3281, 0, 3010, +3281, 0, 2999, +3281, 0, 2985, +3281, 0, 2965, +3281, 0, 2936, +3281, 0, 2895, +3281, 0, 2833, +3281, 0, 2735, +3281, 0, 2558, +3281, 0, 2100, +3281, 0, 0, +3281, 0, 0, +3281, 2633, 0, +3414, 3139, 0, +3547, 3430, 0, +3679, 3653, 0, +3777, 3812, 0, +3861, 3944, 0, +3953, 4076, 0, +4052, 4095, 0, +3416, 0, 3162, +3416, 0, 3162, +3416, 0, 3162, +3416, 0, 3161, +3416, 0, 3161, +3416, 0, 3160, +3415, 0, 3160, +3415, 0, 3158, +3415, 0, 3157, +3415, 0, 3155, +3414, 0, 3152, +3414, 0, 3149, +3414, 0, 3143, +3414, 0, 3135, +3414, 0, 3125, +3414, 0, 3110, +3414, 0, 3089, +3414, 0, 3060, +3414, 0, 3018, +3414, 0, 2956, +3414, 0, 2855, +3414, 0, 2672, +3414, 0, 2180, +3414, 0, 0, +3414, 0, 0, +3414, 2759, 0, +3547, 3269, 0, +3679, 3562, 0, +3812, 3785, 0, +3910, 3944, 0, +3994, 4076, 0, +4085, 4095, 0, +3548, 0, 3290, +3548, 0, 3290, +3548, 0, 3290, +3548, 0, 3290, +3548, 0, 3289, +3548, 0, 3289, +3548, 0, 3288, +3548, 0, 3287, +3548, 0, 3286, +3547, 0, 3285, +3547, 0, 3283, +3547, 0, 3280, +3547, 0, 3276, +3547, 0, 3270, +3547, 0, 3262, +3547, 0, 3251, +3547, 0, 3236, +3547, 0, 3216, +3547, 0, 3186, +3547, 0, 3144, +3547, 0, 3080, +3547, 0, 2977, +3547, 0, 2790, +3547, 0, 2265, +3547, 0, 0, +3547, 0, 0, +3547, 2886, 0, +3679, 3400, 0, +3812, 3693, 0, +3944, 3916, 0, +4043, 4076, 0, +4095, 4095, 0, +3680, 0, 3419, +3680, 0, 3419, +3680, 0, 3419, +3680, 0, 3419, +3680, 0, 3419, +3680, 0, 3418, +3680, 0, 3418, +3680, 0, 3417, +3680, 0, 3416, +3680, 0, 3415, +3679, 0, 3414, +3679, 0, 3412, +3679, 0, 3409, +3679, 0, 3404, +3679, 0, 3398, +3679, 0, 3390, +3679, 0, 3379, +3679, 0, 3364, +3679, 0, 3343, +3679, 0, 3314, +3679, 0, 3271, +3679, 0, 3206, +3679, 0, 3102, +3679, 0, 2910, +3679, 0, 2363, +3679, 0, 0, +3679, 0, 0, +3679, 3015, 0, +3812, 3531, 0, +3944, 3824, 0, +4076, 4048, 0, +4095, 4095, 0, +3812, 0, 3549, +3812, 0, 3549, +3812, 0, 3549, +3812, 0, 3549, +3812, 0, 3549, +3812, 0, 3548, +3812, 0, 3548, +3812, 0, 3548, +3812, 0, 3547, +3812, 0, 3546, +3812, 0, 3545, +3812, 0, 3544, +3812, 0, 3541, +3812, 0, 3538, +3812, 0, 3533, +3812, 0, 3528, +3812, 0, 3520, +3812, 0, 3508, +3812, 0, 3493, +3812, 0, 3472, +3812, 0, 3442, +3812, 0, 3399, +3812, 0, 3333, +3812, 0, 3228, +3812, 0, 3034, +3812, 0, 2465, +3812, 0, 0, +3812, 0, 0, +3812, 3145, 0, +3944, 3662, 0, +4076, 3956, 0, +4095, 4095, 0, +3944, 0, 3679, +3944, 0, 3679, +3944, 0, 3679, +3944, 0, 3679, +3944, 0, 3679, +3944, 0, 3679, +3944, 0, 3679, +3944, 0, 3678, +3944, 0, 3678, +3944, 0, 3677, +3944, 0, 3676, +3944, 0, 3675, +3944, 0, 3673, +3944, 0, 3671, +3944, 0, 3668, +3944, 0, 3663, +3944, 0, 3657, +3944, 0, 3649, +3944, 0, 3638, +3944, 0, 3623, +3944, 0, 3602, +3944, 0, 3571, +3944, 0, 3528, +3944, 0, 3462, +3944, 0, 3356, +3944, 0, 3159, +3944, 0, 2572, +3944, 0, 0, +3944, 0, 0, +3944, 3275, 0, +4076, 3793, 0, +4095, 4088, 0, +4076, 0, 3810, +4076, 0, 3810, +4076, 0, 3810, +4076, 0, 3810, +4076, 0, 3810, +4076, 0, 3810, +4076, 0, 3810, +4076, 0, 3809, +4076, 0, 3809, +4076, 0, 3808, +4076, 0, 3808, +4076, 0, 3807, +4076, 0, 3805, +4076, 0, 3804, +4076, 0, 3801, +4076, 0, 3798, +4076, 0, 3794, +4076, 0, 3787, +4076, 0, 3780, +4076, 0, 3768, +4076, 0, 3753, +4076, 0, 3732, +4076, 0, 3701, +4076, 0, 3658, +4076, 0, 3592, +4076, 0, 3485, +4076, 0, 3286, +4076, 0, 2684, +4076, 0, 0, +4076, 0, 0, +4076, 3405, 0, +4095, 3926, 0, +4095, 0, 3941, +4095, 0, 3941, +4095, 0, 3941, +4095, 0, 3941, +4095, 0, 3941, +4095, 0, 3941, +4095, 0, 3941, +4095, 0, 3941, +4095, 0, 3941, +4095, 0, 3940, +4095, 0, 3940, +4095, 0, 3939, +4095, 0, 3938, +4095, 0, 3937, +4095, 0, 3935, +4095, 0, 3932, +4095, 0, 3929, +4095, 0, 3925, +4095, 0, 3919, +4095, 0, 3910, +4095, 0, 3899, +4095, 0, 3884, +4095, 0, 3863, +4095, 0, 3832, +4095, 0, 3788, +4095, 0, 3722, +4095, 0, 3615, +4095, 0, 3415, +4095, 0, 2804, +4095, 0, 0, +4095, 0, 0, +4095, 3537, 0, +0, 1434, 1696, +0, 1444, 1696, +0, 1457, 1696, +0, 1475, 1696, +0, 1496, 1696, +0, 1524, 1696, +0, 1559, 1696, +0, 1601, 1696, +0, 1653, 1696, +0, 1696, 1677, +0, 1696, 1587, +0, 1696, 1427, +0, 1696, 1056, +0, 1828, 0, +0, 1961, 0, +814, 2094, 0, +1457, 2226, 0, +1775, 2358, 0, +2009, 2491, 0, +2205, 2623, 0, +2379, 2755, 0, +2541, 2887, 0, +2693, 3019, 0, +2840, 3152, 0, +2983, 3284, 0, +3123, 3416, 0, +3261, 3548, 0, +3398, 3680, 0, +3533, 3812, 0, +3667, 3944, 0, +3801, 4076, 0, +3935, 4095, 0, +0, 1424, 1696, +0, 1436, 1695, +0, 1450, 1695, +0, 1467, 1695, +0, 1489, 1695, +0, 1517, 1695, +0, 1552, 1695, +0, 1596, 1695, +0, 1647, 1695, +0, 1695, 1680, +0, 1695, 1590, +0, 1695, 1432, +0, 1695, 1066, +0, 1828, 0, +0, 1961, 0, +859, 2093, 0, +1469, 2226, 0, +1781, 2358, 0, +2013, 2491, 0, +2207, 2623, 0, +2381, 2755, 0, +2542, 2887, 0, +2694, 3019, 0, +2841, 3152, 0, +2983, 3283, 0, +3123, 3416, 0, +3261, 3548, 0, +3398, 3680, 0, +3533, 3812, 0, +3667, 3944, 0, +3801, 4076, 0, +3935, 4095, 0, +0, 1410, 1696, +0, 1422, 1695, +0, 1439, 1693, +0, 1456, 1693, +0, 1479, 1693, +0, 1508, 1693, +0, 1544, 1693, +0, 1588, 1693, +0, 1640, 1693, +0, 1693, 1683, +0, 1693, 1594, +0, 1693, 1439, +0, 1693, 1080, +0, 1827, 0, +0, 1960, 0, +913, 2093, 0, +1484, 2225, 0, +1788, 2358, 0, +2017, 2490, 0, +2210, 2623, 0, +2383, 2755, 0, +2543, 2887, 0, +2695, 3019, 0, +2842, 3152, 0, +2984, 3283, 0, +3124, 3416, 0, +3261, 3548, 0, +3398, 3680, 0, +3533, 3812, 0, +3668, 3944, 0, +3801, 4076, 0, +3935, 4095, 0, +0, 1390, 1696, +0, 1403, 1695, +0, 1420, 1693, +0, 1442, 1691, +0, 1465, 1691, +0, 1495, 1691, +0, 1532, 1691, +0, 1577, 1691, +0, 1631, 1691, +0, 1691, 1688, +0, 1691, 1600, +0, 1691, 1447, +0, 1691, 1098, +0, 1825, 0, +0, 1959, 0, +977, 2092, 0, +1503, 2225, 0, +1798, 2357, 0, +2023, 2490, 0, +2214, 2622, 0, +2386, 2755, 0, +2545, 2887, 0, +2696, 3019, 0, +2842, 3151, 0, +2985, 3283, 0, +3124, 3416, 0, +3262, 3548, 0, +3398, 3680, 0, +3533, 3812, 0, +3668, 3944, 0, +3801, 4076, 0, +3935, 4095, 0, +0, 1362, 1696, +0, 1376, 1695, +0, 1394, 1693, +0, 1417, 1691, +0, 1446, 1689, +0, 1477, 1689, +0, 1515, 1689, +0, 1562, 1689, +0, 1617, 1689, +0, 1683, 1689, +0, 1689, 1608, +0, 1689, 1457, +0, 1689, 1120, +0, 1823, 0, +0, 1958, 0, +1050, 2091, 0, +1527, 2224, 0, +1811, 2357, 0, +2031, 2489, 0, +2219, 2622, 0, +2389, 2755, 0, +2548, 2887, 0, +2698, 3019, 0, +2844, 3151, 0, +2986, 3283, 0, +3125, 3416, 0, +3262, 3548, 0, +3399, 3680, 0, +3534, 3812, 0, +3668, 3944, 0, +3801, 4076, 0, +3935, 4095, 0, +0, 1322, 1696, +0, 1337, 1695, +0, 1357, 1693, +0, 1382, 1691, +0, 1413, 1689, +0, 1452, 1685, +0, 1492, 1685, +0, 1541, 1685, +0, 1599, 1685, +0, 1667, 1685, +0, 1685, 1618, +0, 1685, 1471, +0, 1685, 1149, +0, 1821, 0, +0, 1956, 0, +1133, 2089, 0, +1557, 2223, 0, +1828, 2356, 0, +2041, 2489, 0, +2226, 2621, 0, +2394, 2754, 0, +2551, 2887, 0, +2701, 3019, 0, +2845, 3151, 0, +2987, 3283, 0, +3126, 3416, 0, +3263, 3548, 0, +3399, 3680, 0, +3534, 3812, 0, +3668, 3944, 0, +3802, 4076, 0, +3935, 4095, 0, +0, 1262, 1696, +0, 1279, 1695, +0, 1302, 1693, +0, 1330, 1691, +0, 1365, 1689, +0, 1408, 1685, +0, 1460, 1681, +0, 1512, 1681, +0, 1574, 1681, +0, 1645, 1681, +0, 1681, 1631, +0, 1681, 1489, +0, 1681, 1184, +0, 1817, 0, +0, 1953, 0, +1224, 2087, 0, +1596, 2221, 0, +1849, 2355, 0, +2055, 2488, 0, +2235, 2621, 0, +2400, 2754, 0, +2555, 2886, 0, +2703, 3018, 0, +2848, 3151, 0, +2988, 3283, 0, +3127, 3415, 0, +3264, 3548, 0, +3400, 3680, 0, +3534, 3812, 0, +3668, 3944, 0, +3802, 4076, 0, +3935, 4095, 0, +0, 1167, 1696, +0, 1188, 1695, +0, 1216, 1693, +0, 1249, 1691, +0, 1291, 1689, +0, 1341, 1685, +0, 1401, 1681, +0, 1470, 1674, +0, 1537, 1674, +0, 1614, 1674, +0, 1674, 1648, +0, 1674, 1512, +0, 1674, 1228, +0, 1813, 0, +670, 1950, 0, +1322, 2085, 0, +1642, 2220, 0, +1876, 2353, 0, +2072, 2487, 0, +2247, 2620, 0, +2408, 2753, 0, +2561, 2886, 0, +2708, 3018, 0, +2851, 3151, 0, +2991, 3283, 0, +3129, 3415, 0, +3265, 3548, 0, +3401, 3680, 0, +3535, 3812, 0, +3669, 3944, 0, +3802, 4076, 0, +3936, 4095, 0, +0, 998, 1696, +0, 1029, 1695, +0, 1067, 1693, +0, 1113, 1691, +0, 1169, 1689, +0, 1233, 1685, +0, 1308, 1681, +0, 1391, 1674, +608, 1483, 1666, +608, 1569, 1666, +608, 1663, 1666, +608, 1666, 1541, +608, 1666, 1281, +0, 1807, 438, +1007, 1945, 0, +1428, 2082, 0, +1697, 2217, 0, +1910, 2352, 0, +2094, 2486, 0, +2262, 2619, 0, +2419, 2752, 0, +2569, 2885, 0, +2714, 3018, 0, +2855, 3151, 0, +2994, 3283, 0, +3131, 3415, 0, +3267, 3548, 0, +3402, 3680, 0, +3536, 3812, 0, +3670, 3944, 0, +3803, 4076, 0, +3936, 4095, 0, +0, 580, 1696, +0, 653, 1695, +0, 736, 1693, +0, 827, 1691, +0, 926, 1689, +0, 1031, 1685, +0, 1142, 1681, +0, 1258, 1674, +608, 1378, 1666, +959, 1500, 1654, +959, 1608, 1654, +959, 1654, 1577, +959, 1654, 1343, +742, 1798, 740, +1248, 1939, 0, +1539, 2077, 0, +1762, 2214, 0, +1951, 2349, 0, +2122, 2484, 0, +2281, 2618, 0, +2433, 2751, 0, +2579, 2885, 0, +2721, 3017, 0, +2860, 3150, 0, +2998, 3282, 0, +3134, 3415, 0, +3269, 3547, 0, +3404, 3680, 0, +3537, 3812, 0, +3671, 3944, 0, +3803, 4076, 0, +3937, 4095, 0, +0, 0, 1696, +0, 0, 1695, +0, 0, 1693, +0, 0, 1691, +0, 0, 1689, +0, 406, 1685, +0, 742, 1681, +0, 983, 1674, +608, 1183, 1666, +959, 1360, 1654, +1205, 1522, 1638, +1205, 1638, 1621, +1205, 1638, 1414, +1189, 1787, 1090, +1447, 1930, 872, +1655, 2071, 79, +1836, 2209, 0, +2002, 2346, 0, +2158, 2481, 0, +2306, 2616, 0, +2451, 2750, 0, +2592, 2883, 0, +2731, 3016, 0, +2868, 3150, 0, +3003, 3282, 0, +3138, 3414, 0, +3272, 3547, 0, +3406, 3679, 0, +3539, 3812, 0, +3672, 3944, 0, +3804, 4076, 0, +3937, 4095, 0, +0, 0, 1696, +0, 0, 1695, +0, 0, 1693, +0, 0, 1691, +0, 0, 1689, +0, 0, 1685, +0, 0, 1681, +313, 0, 1674, +609, 608, 1666, +959, 1056, 1654, +1205, 1333, 1638, +1407, 1550, 1616, +1407, 1616, 1495, +1466, 1771, 1337, +1624, 1919, 1223, +1774, 2062, 1005, +1920, 2203, 217, +2061, 2341, 0, +2201, 2478, 0, +2338, 2613, 0, +2474, 2748, 0, +2609, 2882, 0, +2743, 3015, 0, +2877, 3149, 0, +3010, 3281, 0, +3143, 3414, 0, +3276, 3547, 0, +3409, 3679, 0, +3541, 3812, 0, +3673, 3944, 0, +3805, 4076, 0, +3938, 4095, 0, +1056, 0, 1696, +1066, 0, 1695, +1080, 0, 1693, +1098, 0, 1691, +1120, 0, 1689, +1149, 0, 1685, +1184, 0, 1681, +1228, 0, 1674, +1281, 608, 1666, +1343, 959, 1654, +1414, 1205, 1638, +1495, 1407, 1616, +1585, 1585, 1585, +1682, 1748, 1539, +1787, 1903, 1469, +1897, 2051, 1355, +2012, 2194, 1136, +2131, 2335, 345, +2253, 2473, 0, +2377, 2610, 0, +2503, 2746, 0, +2631, 2880, 0, +2759, 3014, 0, +2889, 3148, 0, +3019, 3280, 0, +3150, 3414, 0, +3281, 3546, 0, +3413, 3679, 0, +3544, 3811, 0, +3676, 3944, 0, +3807, 4076, 0, +3939, 4095, 0, +1557, 0, 1828, +1560, 0, 1828, +1565, 0, 1827, +1571, 0, 1825, +1579, 0, 1823, +1590, 0, 1821, +1604, 0, 1817, +1622, 0, 1813, +1644, 0, 1807, +1673, 740, 1798, +1709, 1090, 1787, +1754, 1337, 1771, +1748, 1539, 1682, +1748, 1627, 1539, +1903, 1885, 1469, +2004, 2051, 1355, +2097, 2194, 1136, +2198, 2335, 345, +2305, 2473, 0, +2417, 2610, 0, +2534, 2746, 0, +2654, 2880, 0, +2777, 3014, 0, +2903, 3148, 0, +3029, 3280, 0, +3158, 3414, 0, +3287, 3546, 0, +3417, 3679, 0, +3547, 3811, 0, +3678, 3944, 0, +3809, 4076, 0, +3941, 4095, 0, +1847, 0, 1961, +1849, 0, 1961, +1851, 0, 1960, +1854, 0, 1959, +1859, 0, 1958, +1865, 0, 1956, +1872, 0, 1953, +1882, 0, 1950, +1895, 0, 1945, +1912, 0, 1939, +1930, 872, 1927, +1919, 1223, 1872, +1903, 1469, 1787, +1903, 1469, 1598, +1903, 1678, 1469, +2051, 1973, 1355, +2191, 2194, 1136, +2274, 2335, 345, +2366, 2473, 0, +2466, 2610, 0, +2572, 2746, 0, +2684, 2880, 0, +2800, 3014, 0, +2920, 3148, 0, +3043, 3280, 0, +3168, 3414, 0, +3294, 3546, 0, +3422, 3679, 0, +3552, 3811, 0, +3681, 3944, 0, +3812, 4076, 0, +3942, 4095, 0, +2069, 0, 2094, +2070, 0, 2093, +2071, 0, 2093, +2073, 0, 2092, +2076, 0, 2091, +2080, 0, 2089, +2085, 0, 2087, +2085, 0, 2079, +2082, 0, 2063, +2077, 0, 2041, +2071, 79, 2010, +2062, 1005, 1965, +2051, 1355, 1897, +2051, 1355, 1756, +2051, 1355, 1453, +2051, 1739, 1355, +2194, 2069, 1136, +2335, 2308, 345, +2438, 2473, 0, +2524, 2610, 0, +2619, 2746, 0, +2721, 2880, 0, +2829, 3014, 0, +2942, 3148, 0, +3060, 3280, 0, +3181, 3414, 0, +3304, 3546, 0, +3430, 3679, 0, +3557, 3811, 0, +3685, 3944, 0, +3814, 4076, 0, +3945, 4095, 0, +2226, 0, 2191, +2226, 0, 2190, +2225, 0, 2188, +2225, 0, 2185, +2224, 0, 2181, +2223, 0, 2176, +2221, 0, 2169, +2220, 0, 2159, +2217, 0, 2146, +2214, 0, 2128, +2209, 0, 2102, +2203, 217, 2066, +2194, 1136, 2012, +2194, 1136, 1906, +2194, 1136, 1711, +2194, 1136, 1137, +2194, 1809, 1136, +2335, 2173, 345, +2473, 2423, 0, +2592, 2610, 0, +2674, 2746, 0, +2766, 2880, 0, +2865, 3014, 0, +2970, 3148, 0, +3082, 3280, 0, +3198, 3414, 0, +3317, 3546, 0, +3440, 3679, 0, +3564, 3811, 0, +3691, 3944, 0, +3819, 4076, 0, +3948, 4095, 0, +2358, 0, 2275, +2358, 0, 2273, +2358, 0, 2271, +2357, 0, 2269, +2357, 0, 2266, +2356, 0, 2262, +2355, 0, 2256, +2353, 0, 2248, +2352, 0, 2237, +2349, 0, 2223, +2346, 0, 2202, +2341, 0, 2173, +2335, 345, 2131, +2335, 345, 2052, +2335, 345, 1919, +2335, 345, 1644, +2335, 970, 345, +2335, 1889, 345, +2473, 2282, 0, +2610, 2543, 0, +2740, 2746, 0, +2820, 2880, 0, +2908, 3014, 0, +3005, 3148, 0, +3109, 3280, 0, +3219, 3414, 0, +3334, 3546, 0, +3453, 3679, 0, +3574, 3811, 0, +3699, 3944, 0, +3824, 4076, 0, +3952, 4095, 0, +2491, 0, 2367, +2491, 0, 2366, +2490, 0, 2364, +2490, 0, 2362, +2489, 0, 2360, +2489, 0, 2356, +2488, 0, 2352, +2487, 0, 2345, +2486, 0, 2336, +2484, 0, 2325, +2481, 0, 2308, +2478, 0, 2285, +2473, 0, 2253, +2473, 0, 2194, +2473, 0, 2100, +2473, 0, 1935, +2473, 0, 1535, +2473, 557, 0, +2473, 1977, 0, +2610, 2396, 0, +2746, 2665, 0, +2880, 2877, 0, +2961, 3014, 0, +3049, 3148, 0, +3144, 3280, 0, +3247, 3414, 0, +3355, 3546, 0, +3469, 3679, 0, +3587, 3811, 0, +3708, 3944, 0, +3832, 4076, 0, +3958, 4095, 0, +2623, 0, 2466, +2623, 0, 2465, +2623, 0, 2464, +2622, 0, 2463, +2622, 0, 2460, +2621, 0, 2458, +2621, 0, 2454, +2620, 0, 2449, +2619, 0, 2442, +2618, 0, 2432, +2616, 0, 2420, +2613, 0, 2402, +2610, 0, 2377, +2610, 0, 2333, +2610, 0, 2266, +2610, 0, 2158, +2610, 0, 1956, +2610, 0, 1330, +2610, 0, 0, +2610, 2073, 0, +2746, 2515, 0, +2880, 2789, 0, +3014, 3004, 0, +3100, 3148, 0, +3186, 3280, 0, +3281, 3414, 0, +3382, 3546, 0, +3490, 3679, 0, +3604, 3811, 0, +3721, 3944, 0, +3841, 4076, 0, +3965, 4095, 0, +2755, 0, 2573, +2755, 0, 2572, +2755, 0, 2571, +2755, 0, 2570, +2755, 0, 2568, +2754, 0, 2566, +2754, 0, 2563, +2753, 0, 2559, +2752, 0, 2553, +2751, 0, 2546, +2750, 0, 2536, +2748, 0, 2522, +2746, 0, 2503, +2746, 0, 2470, +2746, 0, 2422, +2746, 0, 2348, +2746, 0, 2226, +2746, 0, 1983, +2746, 0, 678, +2746, 0, 0, +2746, 2177, 0, +2880, 2636, 0, +3014, 2915, 0, +3148, 3133, 0, +3238, 3280, 0, +3323, 3414, 0, +3416, 3546, 0, +3517, 3679, 0, +3625, 3811, 0, +3737, 3944, 0, +3854, 4076, 0, +3975, 4095, 0, +2887, 0, 2684, +2887, 0, 2684, +2887, 0, 2683, +2887, 0, 2682, +2887, 0, 2681, +2887, 0, 2679, +2886, 0, 2677, +2886, 0, 2673, +2885, 0, 2669, +2885, 0, 2664, +2883, 0, 2656, +2882, 0, 2645, +2880, 0, 2631, +2880, 0, 2606, +2880, 0, 2571, +2880, 0, 2519, +2880, 0, 2439, +2880, 0, 2302, +2880, 0, 2016, +2880, 0, 0, +2880, 0, 0, +2880, 2287, 0, +3014, 2759, 0, +3148, 3043, 0, +3280, 3262, 0, +3374, 3414, 0, +3458, 3546, 0, +3551, 3679, 0, +3652, 3811, 0, +3758, 3944, 0, +3871, 4076, 0, +3988, 4095, 0, +3019, 0, 2800, +3019, 0, 2800, +3019, 0, 2799, +3019, 0, 2798, +3019, 0, 2797, +3019, 0, 2796, +3018, 0, 2794, +3018, 0, 2792, +3018, 0, 2789, +3017, 0, 2784, +3016, 0, 2778, +3015, 0, 2770, +3014, 0, 2759, +3014, 0, 2741, +3014, 0, 2715, +3014, 0, 2678, +3014, 0, 2623, +3014, 0, 2536, +3014, 0, 2388, +3014, 0, 2056, +3014, 0, 0, +3014, 0, 0, +3014, 2401, 0, +3148, 2886, 0, +3280, 3172, 0, +3414, 3393, 0, +3509, 3546, 0, +3593, 3679, 0, +3685, 3811, 0, +3785, 3944, 0, +3891, 4076, 0, +4004, 4095, 0, +3152, 0, 2920, +3152, 0, 2920, +3152, 0, 2919, +3151, 0, 2919, +3151, 0, 2918, +3151, 0, 2917, +3151, 0, 2916, +3151, 0, 2914, +3151, 0, 2911, +3150, 0, 2908, +3150, 0, 2904, +3149, 0, 2898, +3148, 0, 2889, +3148, 0, 2875, +3148, 0, 2856, +3148, 0, 2829, +3148, 0, 2790, +3148, 0, 2733, +3148, 0, 2642, +3148, 0, 2482, +3148, 0, 2106, +3148, 0, 0, +3148, 0, 0, +3148, 2520, 0, +3280, 3013, 0, +3414, 3301, 0, +3546, 3523, 0, +3643, 3679, 0, +3727, 3811, 0, +3819, 3944, 0, +3918, 4076, 0, +4025, 4095, 0, +3284, 0, 3043, +3283, 0, 3042, +3283, 0, 3042, +3283, 0, 3042, +3283, 0, 3041, +3283, 0, 3040, +3283, 0, 3039, +3283, 0, 3038, +3283, 0, 3036, +3282, 0, 3033, +3282, 0, 3030, +3281, 0, 3025, +3280, 0, 3019, +3280, 0, 3009, +3280, 0, 2995, +3280, 0, 2975, +3280, 0, 2947, +3280, 0, 2907, +3280, 0, 2847, +3280, 0, 2752, +3280, 0, 2583, +3280, 0, 2164, +3280, 0, 0, +3280, 0, 0, +3280, 2641, 0, +3414, 3142, 0, +3546, 3432, 0, +3679, 3654, 0, +3777, 3811, 0, +3860, 3944, 0, +3952, 4076, 0, +4051, 4095, 0, +3416, 0, 3168, +3416, 0, 3168, +3416, 0, 3167, +3416, 0, 3167, +3416, 0, 3166, +3416, 0, 3166, +3415, 0, 3165, +3415, 0, 3164, +3415, 0, 3163, +3415, 0, 3161, +3414, 0, 3158, +3414, 0, 3155, +3414, 0, 3150, +3414, 0, 3142, +3414, 0, 3132, +3414, 0, 3117, +3414, 0, 3097, +3414, 0, 3069, +3414, 0, 3027, +3414, 0, 2966, +3414, 0, 2867, +3414, 0, 2691, +3414, 0, 2234, +3414, 0, 0, +3414, 0, 0, +3414, 2765, 0, +3546, 3271, 0, +3679, 3563, 0, +3811, 3785, 0, +3910, 3944, 0, +3993, 4076, 0, +4085, 4095, 0, +3548, 0, 3294, +3548, 0, 3294, +3548, 0, 3294, +3548, 0, 3294, +3548, 0, 3293, +3548, 0, 3293, +3548, 0, 3292, +3548, 0, 3292, +3548, 0, 3291, +3547, 0, 3289, +3547, 0, 3287, +3547, 0, 3285, +3546, 0, 3281, +3546, 0, 3275, +3546, 0, 3268, +3546, 0, 3257, +3546, 0, 3242, +3546, 0, 3221, +3546, 0, 3192, +3546, 0, 3151, +3546, 0, 3087, +3546, 0, 2987, +3546, 0, 2804, +3546, 0, 2311, +3546, 0, 0, +3546, 0, 0, +3546, 2891, 0, +3679, 3401, 0, +3811, 3694, 0, +3944, 3917, 0, +4043, 4076, 0, +4095, 4095, 0, +3680, 0, 3422, +3680, 0, 3422, +3680, 0, 3422, +3680, 0, 3422, +3680, 0, 3422, +3680, 0, 3421, +3680, 0, 3421, +3680, 0, 3420, +3680, 0, 3420, +3680, 0, 3418, +3679, 0, 3417, +3679, 0, 3415, +3679, 0, 3413, +3679, 0, 3408, +3679, 0, 3402, +3679, 0, 3394, +3679, 0, 3384, +3679, 0, 3368, +3679, 0, 3348, +3679, 0, 3318, +3679, 0, 3276, +3679, 0, 3212, +3679, 0, 3110, +3679, 0, 2922, +3679, 0, 2400, +3679, 0, 0, +3679, 0, 0, +3679, 3018, 0, +3811, 3532, 0, +3944, 3825, 0, +4076, 4048, 0, +4095, 4095, 0, +3812, 0, 3552, +3812, 0, 3551, +3812, 0, 3551, +3812, 0, 3551, +3812, 0, 3551, +3812, 0, 3551, +3812, 0, 3550, +3812, 0, 3550, +3812, 0, 3549, +3812, 0, 3548, +3812, 0, 3547, +3812, 0, 3546, +3811, 0, 3544, +3811, 0, 3541, +3811, 0, 3536, +3811, 0, 3530, +3811, 0, 3522, +3811, 0, 3511, +3811, 0, 3496, +3811, 0, 3475, +3811, 0, 3446, +3811, 0, 3403, +3811, 0, 3338, +3811, 0, 3234, +3811, 0, 3043, +3811, 0, 2494, +3811, 0, 0, +3811, 0, 0, +3811, 3147, 0, +3944, 3663, 0, +4076, 3956, 0, +4095, 4095, 0, +3944, 0, 3681, +3944, 0, 3681, +3944, 0, 3681, +3944, 0, 3681, +3944, 0, 3681, +3944, 0, 3681, +3944, 0, 3680, +3944, 0, 3680, +3944, 0, 3680, +3944, 0, 3679, +3944, 0, 3678, +3944, 0, 3677, +3944, 0, 3676, +3944, 0, 3673, +3944, 0, 3670, +3944, 0, 3666, +3944, 0, 3659, +3944, 0, 3651, +3944, 0, 3640, +3944, 0, 3625, +3944, 0, 3604, +3944, 0, 3574, +3944, 0, 3531, +3944, 0, 3466, +3944, 0, 3361, +3944, 0, 3166, +3944, 0, 2596, +3944, 0, 0, +3944, 0, 0, +3944, 3277, 0, +4076, 3794, 0, +4095, 4088, 0, +4076, 0, 3812, +4076, 0, 3811, +4076, 0, 3811, +4076, 0, 3811, +4076, 0, 3811, +4076, 0, 3811, +4076, 0, 3811, +4076, 0, 3810, +4076, 0, 3810, +4076, 0, 3810, +4076, 0, 3809, +4076, 0, 3808, +4076, 0, 3807, +4076, 0, 3805, +4076, 0, 3803, +4076, 0, 3800, +4076, 0, 3795, +4076, 0, 3789, +4076, 0, 3781, +4076, 0, 3770, +4076, 0, 3755, +4076, 0, 3734, +4076, 0, 3703, +4076, 0, 3660, +4076, 0, 3594, +4076, 0, 3488, +4076, 0, 3291, +4076, 0, 2703, +4076, 0, 0, +4076, 0, 0, +4076, 3407, 0, +4095, 3926, 0, +4095, 0, 3942, +4095, 0, 3942, +4095, 0, 3942, +4095, 0, 3942, +4095, 0, 3942, +4095, 0, 3942, +4095, 0, 3942, +4095, 0, 3942, +4095, 0, 3941, +4095, 0, 3941, +4095, 0, 3941, +4095, 0, 3940, +4095, 0, 3939, +4095, 0, 3938, +4095, 0, 3936, +4095, 0, 3934, +4095, 0, 3930, +4095, 0, 3926, +4095, 0, 3920, +4095, 0, 3912, +4095, 0, 3901, +4095, 0, 3885, +4095, 0, 3864, +4095, 0, 3834, +4095, 0, 3790, +4095, 0, 3724, +4095, 0, 3617, +4095, 0, 3419, +4095, 0, 2818, +4095, 0, 0, +4095, 0, 0, +4095, 3538, 0, +0, 1565, 1828, +0, 1572, 1828, +0, 1582, 1828, +0, 1596, 1828, +0, 1612, 1828, +0, 1634, 1828, +0, 1661, 1828, +0, 1696, 1828, +0, 1738, 1828, +0, 1789, 1828, +0, 1828, 1807, +0, 1828, 1716, +0, 1828, 1557, +0, 1828, 1180, +0, 1961, 0, +0, 2094, 0, +907, 2226, 0, +1580, 2358, 0, +1903, 2491, 0, +2138, 2623, 0, +2335, 2755, 0, +2510, 2887, 0, +2672, 3019, 0, +2825, 3152, 0, +2972, 3284, 0, +3115, 3416, 0, +3255, 3548, 0, +3393, 3680, 0, +3530, 3812, 0, +3665, 3944, 0, +3799, 4076, 0, +3933, 4095, 0, +0, 1557, 1828, +0, 1566, 1828, +0, 1576, 1828, +0, 1590, 1828, +0, 1607, 1828, +0, 1629, 1828, +0, 1656, 1828, +0, 1691, 1828, +0, 1733, 1828, +0, 1785, 1828, +0, 1828, 1810, +0, 1828, 1719, +0, 1828, 1560, +0, 1828, 1188, +0, 1961, 0, +0, 2093, 0, +944, 2226, 0, +1589, 2358, 0, +1907, 2491, 0, +2141, 2623, 0, +2337, 2755, 0, +2511, 2887, 0, +2672, 3019, 0, +2825, 3152, 0, +2972, 3283, 0, +3115, 3416, 0, +3255, 3548, 0, +3393, 3680, 0, +3530, 3812, 0, +3665, 3944, 0, +3799, 4076, 0, +3933, 4095, 0, +0, 1547, 1828, +0, 1556, 1828, +0, 1568, 1827, +0, 1582, 1827, +0, 1599, 1827, +0, 1621, 1827, +0, 1650, 1827, +0, 1684, 1827, +0, 1727, 1827, +0, 1779, 1827, +0, 1827, 1812, +0, 1827, 1722, +0, 1827, 1565, +0, 1827, 1198, +0, 1960, 0, +0, 2093, 0, +990, 2225, 0, +1600, 2358, 0, +1913, 2490, 0, +2144, 2623, 0, +2339, 2755, 0, +2513, 2887, 0, +2673, 3019, 0, +2826, 3152, 0, +2973, 3283, 0, +3115, 3416, 0, +3256, 3548, 0, +3393, 3680, 0, +3530, 3812, 0, +3665, 3944, 0, +3799, 4076, 0, +3933, 4095, 0, +0, 1532, 1828, +0, 1542, 1828, +0, 1554, 1827, +0, 1571, 1825, +0, 1588, 1825, +0, 1611, 1825, +0, 1640, 1825, +0, 1676, 1825, +0, 1720, 1825, +0, 1772, 1825, +0, 1825, 1816, +0, 1825, 1727, +0, 1825, 1571, +0, 1825, 1212, +0, 1959, 0, +0, 2092, 0, +1044, 2225, 0, +1615, 2357, 0, +1920, 2490, 0, +2149, 2622, 0, +2342, 2755, 0, +2515, 2887, 0, +2675, 3019, 0, +2827, 3151, 0, +2973, 3283, 0, +3116, 3416, 0, +3256, 3548, 0, +3394, 3680, 0, +3530, 3812, 0, +3665, 3944, 0, +3799, 4076, 0, +3933, 4095, 0, +0, 1512, 1828, +0, 1522, 1828, +0, 1535, 1827, +0, 1552, 1825, +0, 1574, 1823, +0, 1598, 1823, +0, 1627, 1823, +0, 1664, 1823, +0, 1709, 1823, +0, 1763, 1823, +0, 1823, 1821, +0, 1823, 1732, +0, 1823, 1579, +0, 1823, 1230, +0, 1958, 0, +0, 2091, 0, +1108, 2224, 0, +1634, 2357, 0, +1930, 2489, 0, +2155, 2622, 0, +2346, 2755, 0, +2517, 2887, 0, +2677, 3019, 0, +2829, 3151, 0, +2974, 3283, 0, +3117, 3416, 0, +3256, 3548, 0, +3394, 3680, 0, +3530, 3812, 0, +3665, 3944, 0, +3800, 4076, 0, +3934, 4095, 0, +0, 1484, 1828, +0, 1494, 1828, +0, 1508, 1827, +0, 1526, 1825, +0, 1549, 1823, +0, 1579, 1821, +0, 1609, 1821, +0, 1648, 1821, +0, 1694, 1821, +0, 1750, 1821, +0, 1815, 1821, +0, 1821, 1740, +0, 1821, 1590, +0, 1821, 1253, +0, 1956, 0, +0, 2089, 0, +1181, 2223, 0, +1659, 2356, 0, +1943, 2489, 0, +2163, 2621, 0, +2351, 2754, 0, +2521, 2887, 0, +2679, 3019, 0, +2830, 3151, 0, +2976, 3283, 0, +3118, 3416, 0, +3257, 3548, 0, +3395, 3680, 0, +3531, 3812, 0, +3666, 3944, 0, +3800, 4076, 0, +3934, 4095, 0, +0, 1442, 1828, +0, 1454, 1828, +0, 1469, 1827, +0, 1489, 1825, +0, 1514, 1823, +0, 1545, 1821, +0, 1585, 1817, +0, 1625, 1817, +0, 1673, 1817, +0, 1732, 1817, +0, 1799, 1817, +0, 1817, 1750, +0, 1817, 1604, +0, 1817, 1281, +0, 1953, 0, +0, 2087, 0, +1264, 2221, 0, +1689, 2355, 0, +1960, 2488, 0, +2173, 2621, 0, +2358, 2754, 0, +2526, 2886, 0, +2683, 3018, 0, +2833, 3151, 0, +2977, 3283, 0, +3119, 3415, 0, +3258, 3548, 0, +3395, 3680, 0, +3531, 3812, 0, +3666, 3944, 0, +3800, 4076, 0, +3934, 4095, 0, +0, 1381, 1828, +0, 1394, 1828, +0, 1412, 1827, +0, 1434, 1825, +0, 1462, 1823, +0, 1497, 1821, +0, 1540, 1817, +0, 1592, 1813, +0, 1644, 1813, +0, 1706, 1813, +0, 1777, 1813, +0, 1813, 1763, +0, 1813, 1622, +0, 1813, 1317, +0, 1950, 0, +10, 2085, 0, +1355, 2220, 0, +1727, 2353, 0, +1981, 2487, 0, +2187, 2620, 0, +2367, 2753, 0, +2532, 2886, 0, +2687, 3018, 0, +2836, 3151, 0, +2980, 3283, 0, +3121, 3415, 0, +3259, 3548, 0, +3396, 3680, 0, +3532, 3812, 0, +3666, 3944, 0, +3801, 4076, 0, +3934, 4095, 0, +0, 1283, 1828, +0, 1300, 1828, +0, 1321, 1827, +0, 1348, 1825, +0, 1382, 1823, +0, 1423, 1821, +0, 1474, 1817, +0, 1533, 1813, +0, 1602, 1807, +0, 1669, 1807, +0, 1746, 1807, +0, 1807, 1780, +0, 1807, 1644, +0, 1807, 1360, +0, 1945, 37, +800, 2082, 0, +1454, 2217, 0, +1773, 2352, 0, +2008, 2486, 0, +2204, 2619, 0, +2379, 2752, 0, +2540, 2885, 0, +2693, 3018, 0, +2840, 3151, 0, +2983, 3283, 0, +3123, 3415, 0, +3261, 3548, 0, +3397, 3680, 0, +3533, 3812, 0, +3667, 3944, 0, +3801, 4076, 0, +3935, 4095, 0, +0, 1106, 1828, +0, 1131, 1828, +0, 1161, 1827, +0, 1199, 1825, +0, 1245, 1823, +0, 1301, 1821, +0, 1366, 1817, +0, 1440, 1813, +0, 1523, 1807, +740, 1615, 1798, +740, 1701, 1798, +740, 1795, 1798, +740, 1798, 1673, +740, 1798, 1413, +0, 1939, 573, +1138, 2077, 0, +1560, 2214, 0, +1829, 2349, 0, +2042, 2484, 0, +2226, 2618, 0, +2394, 2751, 0, +2551, 2885, 0, +2701, 3017, 0, +2846, 3150, 0, +2987, 3282, 0, +3126, 3415, 0, +3263, 3547, 0, +3399, 3680, 0, +3534, 3812, 0, +3668, 3944, 0, +3802, 4076, 0, +3935, 4095, 0, +0, 650, 1828, +0, 713, 1828, +0, 786, 1827, +0, 869, 1825, +0, 960, 1823, +0, 1059, 1821, +0, 1164, 1817, +0, 1275, 1813, +0, 1391, 1807, +740, 1510, 1798, +1090, 1633, 1787, +1090, 1740, 1787, +1090, 1787, 1709, +1090, 1787, 1475, +873, 1930, 872, +1379, 2071, 79, +1671, 2209, 0, +1894, 2346, 0, +2084, 2481, 0, +2255, 2616, 0, +2414, 2750, 0, +2565, 2883, 0, +2711, 3016, 0, +2853, 3150, 0, +2992, 3282, 0, +3130, 3414, 0, +3266, 3547, 0, +3401, 3679, 0, +3536, 3812, 0, +3669, 3944, 0, +3803, 4076, 0, +3936, 4095, 0, +0, 0, 1828, +0, 0, 1828, +0, 0, 1827, +0, 0, 1825, +0, 0, 1823, +0, 0, 1821, +0, 536, 1817, +0, 874, 1813, +0, 1115, 1807, +740, 1315, 1798, +1090, 1491, 1787, +1337, 1654, 1771, +1337, 1771, 1754, +1337, 1771, 1546, +1321, 1919, 1223, +1579, 2062, 1005, +1787, 2203, 217, +1968, 2341, 0, +2134, 2478, 0, +2290, 2613, 0, +2439, 2748, 0, +2583, 2882, 0, +2724, 3015, 0, +2863, 3149, 0, +2999, 3281, 0, +3135, 3414, 0, +3270, 3547, 0, +3404, 3679, 0, +3538, 3812, 0, +3671, 3944, 0, +3804, 4076, 0, +3937, 4095, 0, +0, 0, 1828, +0, 0, 1828, +0, 0, 1827, +0, 0, 1825, +0, 0, 1823, +0, 0, 1821, +0, 0, 1817, +0, 0, 1813, +438, 0, 1807, +740, 742, 1798, +1090, 1189, 1787, +1337, 1466, 1771, +1539, 1682, 1748, +1539, 1748, 1627, +1598, 1903, 1469, +1756, 2051, 1355, +1906, 2194, 1136, +2052, 2335, 345, +2194, 2473, 0, +2333, 2610, 0, +2470, 2746, 0, +2606, 2880, 0, +2741, 3014, 0, +2875, 3148, 0, +3009, 3280, 0, +3142, 3414, 0, +3275, 3546, 0, +3408, 3679, 0, +3541, 3811, 0, +3673, 3944, 0, +3805, 4076, 0, +3938, 4095, 0, +1180, 0, 1828, +1188, 0, 1828, +1198, 0, 1827, +1212, 0, 1825, +1230, 0, 1823, +1253, 0, 1821, +1281, 0, 1817, +1317, 0, 1813, +1360, 0, 1807, +1413, 740, 1798, +1475, 1090, 1787, +1546, 1337, 1771, +1627, 1539, 1748, +1717, 1717, 1717, +1814, 1880, 1671, +1919, 2035, 1601, +2029, 2183, 1487, +2144, 2326, 1269, +2263, 2467, 477, +2385, 2605, 0, +2509, 2742, 0, +2636, 2878, 0, +2763, 3012, 0, +2892, 3146, 0, +3021, 3280, 0, +3151, 3413, 0, +3282, 3546, 0, +3413, 3678, 0, +3545, 3811, 0, +3676, 3943, 0, +3808, 4076, 0, +3940, 4095, 0, +1686, 0, 1961, +1689, 0, 1961, +1692, 0, 1960, +1697, 0, 1959, +1703, 0, 1958, +1711, 0, 1956, +1722, 0, 1953, +1736, 0, 1950, +1754, 0, 1945, +1776, 0, 1939, +1805, 872, 1930, +1841, 1223, 1919, +1885, 1469, 1903, +1880, 1671, 1814, +1880, 1759, 1671, +2035, 2017, 1601, +2136, 2183, 1487, +2229, 2326, 1269, +2330, 2467, 477, +2437, 2605, 0, +2550, 2742, 0, +2666, 2878, 0, +2786, 3012, 0, +2910, 3146, 0, +3034, 3280, 0, +3162, 3413, 0, +3290, 3546, 0, +3419, 3678, 0, +3549, 3811, 0, +3679, 3943, 0, +3810, 4076, 0, +3941, 4095, 0, +1977, 0, 2094, +1979, 0, 2093, +1981, 0, 2093, +1983, 0, 2092, +1986, 0, 2091, +1991, 0, 2089, +1996, 0, 2087, +2004, 0, 2085, +2014, 0, 2082, +2027, 0, 2077, +2044, 79, 2071, +2062, 1005, 2059, +2051, 1355, 2004, +2035, 1601, 1919, +2035, 1601, 1730, +2035, 1811, 1601, +2183, 2105, 1487, +2323, 2326, 1269, +2407, 2467, 477, +2498, 2605, 0, +2598, 2742, 0, +2704, 2878, 0, +2816, 3012, 0, +2932, 3146, 0, +3052, 3280, 0, +3175, 3413, 0, +3300, 3546, 0, +3426, 3678, 0, +3554, 3811, 0, +3683, 3943, 0, +3813, 4076, 0, +3944, 4095, 0, +2200, 0, 2226, +2201, 0, 2226, +2202, 0, 2225, +2203, 0, 2225, +2206, 0, 2224, +2208, 0, 2223, +2212, 0, 2221, +2217, 0, 2220, +2217, 0, 2211, +2214, 0, 2195, +2209, 0, 2174, +2203, 217, 2142, +2194, 1136, 2097, +2183, 1487, 2029, +2183, 1487, 1888, +2183, 1487, 1585, +2183, 1871, 1487, +2326, 2202, 1269, +2467, 2440, 477, +2570, 2605, 0, +2656, 2742, 0, +2751, 2878, 0, +2853, 3012, 0, +2961, 3146, 0, +3074, 3280, 0, +3192, 3413, 0, +3313, 3546, 0, +3436, 3678, 0, +3562, 3811, 0, +3689, 3943, 0, +3817, 4076, 0, +3947, 4095, 0, +2358, 0, 2325, +2358, 0, 2324, +2358, 0, 2322, +2357, 0, 2320, +2357, 0, 2317, +2356, 0, 2313, +2355, 0, 2308, +2353, 0, 2301, +2352, 0, 2291, +2349, 0, 2278, +2346, 0, 2260, +2341, 0, 2234, +2335, 345, 2198, +2326, 1269, 2144, +2326, 1269, 2038, +2326, 1269, 1843, +2326, 1269, 1270, +2326, 1941, 1269, +2467, 2305, 477, +2605, 2556, 0, +2724, 2742, 0, +2807, 2878, 0, +2898, 3012, 0, +2997, 3146, 0, +3102, 3280, 0, +3214, 3413, 0, +3330, 3546, 0, +3449, 3678, 0, +3572, 3811, 0, +3697, 3943, 0, +3823, 4076, 0, +3951, 4095, 0, +2491, 0, 2408, +2491, 0, 2407, +2490, 0, 2406, +2490, 0, 2404, +2489, 0, 2401, +2489, 0, 2398, +2488, 0, 2394, +2487, 0, 2388, +2486, 0, 2380, +2484, 0, 2369, +2481, 0, 2355, +2478, 0, 2334, +2473, 0, 2305, +2467, 477, 2263, +2467, 477, 2184, +2467, 477, 2051, +2467, 477, 1776, +2467, 1099, 477, +2467, 2021, 477, +2605, 2414, 0, +2742, 2675, 0, +2872, 2878, 0, +2952, 3012, 0, +3041, 3146, 0, +3138, 3280, 0, +3242, 3413, 0, +3351, 3546, 0, +3466, 3678, 0, +3585, 3811, 0, +3706, 3943, 0, +3830, 4076, 0, +3957, 4095, 0, +2623, 0, 2500, +2623, 0, 2499, +2623, 0, 2498, +2622, 0, 2496, +2622, 0, 2494, +2621, 0, 2492, +2621, 0, 2488, +2620, 0, 2483, +2619, 0, 2477, +2618, 0, 2469, +2616, 0, 2456, +2613, 0, 2440, +2610, 0, 2417, +2605, 0, 2385, +2605, 0, 2326, +2605, 0, 2233, +2605, 0, 2067, +2605, 0, 1667, +2605, 705, 0, +2605, 2109, 0, +2742, 2529, 0, +2878, 2797, 0, +3012, 3009, 0, +3093, 3146, 0, +3180, 3280, 0, +3276, 3413, 0, +3379, 3546, 0, +3488, 3678, 0, +3601, 3811, 0, +3719, 3943, 0, +3840, 4076, 0, +3964, 4095, 0, +2755, 0, 2599, +2755, 0, 2598, +2755, 0, 2598, +2755, 0, 2596, +2755, 0, 2595, +2754, 0, 2593, +2754, 0, 2590, +2753, 0, 2586, +2752, 0, 2581, +2751, 0, 2574, +2750, 0, 2565, +2748, 0, 2552, +2746, 0, 2534, +2742, 0, 2509, +2742, 0, 2465, +2742, 0, 2398, +2742, 0, 2291, +2742, 0, 2089, +2742, 0, 1463, +2742, 0, 0, +2742, 2206, 0, +2878, 2647, 0, +3012, 2921, 0, +3146, 3137, 0, +3233, 3280, 0, +3319, 3413, 0, +3413, 3546, 0, +3515, 3678, 0, +3622, 3811, 0, +3736, 3943, 0, +3853, 4076, 0, +3974, 4095, 0, +2887, 0, 2705, +2887, 0, 2705, +2887, 0, 2704, +2887, 0, 2703, +2887, 0, 2702, +2887, 0, 2700, +2886, 0, 2698, +2886, 0, 2695, +2885, 0, 2691, +2885, 0, 2685, +2883, 0, 2678, +2882, 0, 2668, +2880, 0, 2654, +2878, 0, 2636, +2878, 0, 2602, +2878, 0, 2554, +2878, 0, 2480, +2878, 0, 2358, +2878, 0, 2115, +2878, 0, 817, +2878, 0, 0, +2878, 2309, 0, +3012, 2767, 0, +3146, 3047, 0, +3280, 3265, 0, +3370, 3413, 0, +3455, 3546, 0, +3548, 3678, 0, +3650, 3811, 0, +3757, 3943, 0, +3869, 4076, 0, +3986, 4095, 0, +3019, 0, 2816, +3019, 0, 2816, +3019, 0, 2816, +3019, 0, 2815, +3019, 0, 2814, +3019, 0, 2813, +3018, 0, 2811, +3018, 0, 2808, +3018, 0, 2805, +3017, 0, 2801, +3016, 0, 2796, +3015, 0, 2788, +3014, 0, 2777, +3012, 0, 2763, +3012, 0, 2738, +3012, 0, 2703, +3012, 0, 2651, +3012, 0, 2570, +3012, 0, 2434, +3012, 0, 2148, +3012, 0, 0, +3012, 0, 0, +3012, 2419, 0, +3146, 2892, 0, +3280, 3175, 0, +3413, 3395, 0, +3506, 3546, 0, +3590, 3678, 0, +3683, 3811, 0, +3784, 3943, 0, +3890, 4076, 0, +4003, 4095, 0, +3152, 0, 2933, +3152, 0, 2932, +3152, 0, 2932, +3151, 0, 2932, +3151, 0, 2931, +3151, 0, 2930, +3151, 0, 2928, +3151, 0, 2927, +3151, 0, 2924, +3150, 0, 2921, +3150, 0, 2917, +3149, 0, 2911, +3148, 0, 2903, +3146, 0, 2892, +3146, 0, 2873, +3146, 0, 2847, +3146, 0, 2810, +3146, 0, 2755, +3146, 0, 2669, +3146, 0, 2521, +3146, 0, 2189, +3146, 0, 0, +3146, 0, 0, +3146, 2533, 0, +3280, 3017, 0, +3413, 3304, 0, +3546, 3525, 0, +3641, 3678, 0, +3725, 3811, 0, +3817, 3943, 0, +3917, 4076, 0, +4024, 4095, 0, +3284, 0, 3052, +3283, 0, 3052, +3283, 0, 3052, +3283, 0, 3051, +3283, 0, 3051, +3283, 0, 3050, +3283, 0, 3049, +3283, 0, 3047, +3283, 0, 3046, +3282, 0, 3043, +3282, 0, 3040, +3281, 0, 3035, +3280, 0, 3029, +3280, 0, 3021, +3280, 0, 3007, +3280, 0, 2988, +3280, 0, 2961, +3280, 0, 2922, +3280, 0, 2865, +3280, 0, 2773, +3280, 0, 2613, +3280, 0, 2237, +3280, 0, 0, +3280, 0, 0, +3280, 2651, 0, +3413, 3145, 0, +3546, 3434, 0, +3678, 3655, 0, +3775, 3811, 0, +3859, 3943, 0, +3950, 4076, 0, +4051, 4095, 0, +3416, 0, 3175, +3416, 0, 3175, +3416, 0, 3175, +3416, 0, 3174, +3416, 0, 3174, +3416, 0, 3173, +3415, 0, 3173, +3415, 0, 3171, +3415, 0, 3170, +3415, 0, 3168, +3414, 0, 3165, +3414, 0, 3162, +3414, 0, 3158, +3413, 0, 3151, +3413, 0, 3141, +3413, 0, 3127, +3413, 0, 3107, +3413, 0, 3079, +3413, 0, 3039, +3413, 0, 2979, +3413, 0, 2884, +3413, 0, 2715, +3413, 0, 2298, +3413, 0, 0, +3413, 0, 0, +3413, 2773, 0, +3546, 3274, 0, +3678, 3564, 0, +3811, 3786, 0, +3909, 3943, 0, +3992, 4076, 0, +4084, 4095, 0, +3548, 0, 3300, +3548, 0, 3300, +3548, 0, 3300, +3548, 0, 3299, +3548, 0, 3299, +3548, 0, 3299, +3548, 0, 3298, +3548, 0, 3297, +3548, 0, 3296, +3547, 0, 3295, +3547, 0, 3293, +3547, 0, 3290, +3546, 0, 3287, +3546, 0, 3282, +3546, 0, 3275, +3546, 0, 3264, +3546, 0, 3249, +3546, 0, 3229, +3546, 0, 3201, +3546, 0, 3160, +3546, 0, 3098, +3546, 0, 3000, +3546, 0, 2824, +3546, 0, 2365, +3546, 0, 0, +3546, 0, 0, +3546, 2897, 0, +3678, 3403, 0, +3811, 3695, 0, +3943, 3917, 0, +4042, 4076, 0, +4095, 4095, 0, +3680, 0, 3427, +3680, 0, 3426, +3680, 0, 3426, +3680, 0, 3426, +3680, 0, 3426, +3680, 0, 3426, +3680, 0, 3425, +3680, 0, 3425, +3680, 0, 3424, +3680, 0, 3423, +3679, 0, 3421, +3679, 0, 3419, +3679, 0, 3417, +3678, 0, 3413, +3678, 0, 3407, +3678, 0, 3400, +3678, 0, 3389, +3678, 0, 3374, +3678, 0, 3354, +3678, 0, 3325, +3678, 0, 3282, +3678, 0, 3220, +3678, 0, 3119, +3678, 0, 2936, +3678, 0, 2445, +3678, 0, 0, +3678, 0, 0, +3678, 3023, 0, +3811, 3534, 0, +3943, 3826, 0, +4076, 4049, 0, +4095, 4095, 0, +3812, 0, 3554, +3812, 0, 3554, +3812, 0, 3554, +3812, 0, 3554, +3812, 0, 3554, +3812, 0, 3554, +3812, 0, 3553, +3812, 0, 3553, +3812, 0, 3552, +3812, 0, 3552, +3812, 0, 3551, +3812, 0, 3549, +3811, 0, 3547, +3811, 0, 3545, +3811, 0, 3540, +3811, 0, 3534, +3811, 0, 3526, +3811, 0, 3516, +3811, 0, 3501, +3811, 0, 3480, +3811, 0, 3450, +3811, 0, 3408, +3811, 0, 3344, +3811, 0, 3241, +3811, 0, 3054, +3811, 0, 2531, +3811, 0, 0, +3811, 0, 0, +3811, 3151, 0, +3943, 3664, 0, +4076, 3957, 0, +4095, 4095, 0, +3944, 0, 3683, +3944, 0, 3683, +3944, 0, 3683, +3944, 0, 3683, +3944, 0, 3683, +3944, 0, 3683, +3944, 0, 3683, +3944, 0, 3682, +3944, 0, 3682, +3944, 0, 3681, +3944, 0, 3680, +3944, 0, 3679, +3944, 0, 3678, +3943, 0, 3676, +3943, 0, 3673, +3943, 0, 3668, +3943, 0, 3662, +3943, 0, 3655, +3943, 0, 3644, +3943, 0, 3628, +3943, 0, 3607, +3943, 0, 3578, +3943, 0, 3535, +3943, 0, 3470, +3943, 0, 3366, +3943, 0, 3175, +3943, 0, 2625, +3943, 0, 0, +3943, 0, 0, +3943, 3279, 0, +4076, 3795, 0, +4095, 4089, 0, +4076, 0, 3813, +4076, 0, 3813, +4076, 0, 3813, +4076, 0, 3813, +4076, 0, 3813, +4076, 0, 3813, +4076, 0, 3812, +4076, 0, 3812, +4076, 0, 3812, +4076, 0, 3812, +4076, 0, 3811, +4076, 0, 3810, +4076, 0, 3809, +4076, 0, 3808, +4076, 0, 3805, +4076, 0, 3802, +4076, 0, 3798, +4076, 0, 3792, +4076, 0, 3784, +4076, 0, 3773, +4076, 0, 3757, +4076, 0, 3736, +4076, 0, 3706, +4076, 0, 3663, +4076, 0, 3597, +4076, 0, 3492, +4076, 0, 3297, +4076, 0, 2726, +4076, 0, 0, +4076, 0, 0, +4076, 3409, 0, +4095, 3927, 0, +4095, 0, 3944, +4095, 0, 3944, +4095, 0, 3944, +4095, 0, 3944, +4095, 0, 3944, +4095, 0, 3944, +4095, 0, 3943, +4095, 0, 3943, +4095, 0, 3943, +4095, 0, 3943, +4095, 0, 3942, +4095, 0, 3941, +4095, 0, 3941, +4095, 0, 3940, +4095, 0, 3938, +4095, 0, 3935, +4095, 0, 3932, +4095, 0, 3927, +4095, 0, 3922, +4095, 0, 3913, +4095, 0, 3903, +4095, 0, 3887, +4095, 0, 3866, +4095, 0, 3836, +4095, 0, 3792, +4095, 0, 3727, +4095, 0, 3621, +4095, 0, 3424, +4095, 0, 2837, +4095, 0, 0, +4095, 0, 0, +4095, 3539, 0, +0, 1696, 1961, +0, 1702, 1961, +0, 1709, 1961, +0, 1719, 1961, +0, 1732, 1961, +0, 1749, 1961, +0, 1770, 1961, +0, 1797, 1961, +0, 1831, 1961, +0, 1873, 1961, +0, 1923, 1961, +0, 1961, 1938, +0, 1961, 1847, +0, 1961, 1686, +0, 1961, 1306, +0, 2094, 0, +0, 2226, 0, +1009, 2358, 0, +1706, 2491, 0, +2032, 2623, 0, +2269, 2755, 0, +2466, 2887, 0, +2641, 3019, 0, +2803, 3152, 0, +2956, 3284, 0, +3104, 3416, 0, +3247, 3548, 0, +3387, 3680, 0, +3525, 3812, 0, +3661, 3944, 0, +3797, 4076, 0, +3932, 4095, 0, +0, 1690, 1961, +0, 1697, 1961, +0, 1705, 1961, +0, 1715, 1961, +0, 1728, 1961, +0, 1745, 1961, +0, 1766, 1961, +0, 1793, 1961, +0, 1828, 1961, +0, 1870, 1961, +0, 1920, 1961, +0, 1961, 1940, +0, 1961, 1849, +0, 1961, 1689, +0, 1961, 1312, +0, 2093, 0, +0, 2226, 0, +1039, 2358, 0, +1713, 2491, 0, +2035, 2623, 0, +2271, 2755, 0, +2467, 2887, 0, +2642, 3019, 0, +2804, 3152, 0, +2957, 3283, 0, +3104, 3416, 0, +3247, 3548, 0, +3387, 3680, 0, +3525, 3812, 0, +3662, 3944, 0, +3797, 4076, 0, +3932, 4095, 0, +0, 1682, 1961, +0, 1689, 1961, +0, 1699, 1960, +0, 1708, 1960, +0, 1722, 1960, +0, 1739, 1960, +0, 1761, 1960, +0, 1789, 1960, +0, 1823, 1960, +0, 1865, 1960, +0, 1917, 1960, +0, 1960, 1941, +0, 1960, 1851, +0, 1960, 1692, +0, 1960, 1320, +0, 2093, 0, +0, 2225, 0, +1076, 2358, 0, +1722, 2490, 0, +2039, 2623, 0, +2274, 2755, 0, +2469, 2887, 0, +2643, 3019, 0, +2805, 3152, 0, +2957, 3283, 0, +3104, 3416, 0, +3247, 3548, 0, +3387, 3680, 0, +3525, 3812, 0, +3662, 3944, 0, +3797, 4076, 0, +3932, 4095, 0, +0, 1672, 1961, +0, 1679, 1961, +0, 1688, 1960, +0, 1700, 1959, +0, 1714, 1959, +0, 1731, 1959, +0, 1754, 1959, +0, 1781, 1959, +0, 1817, 1959, +0, 1860, 1959, +0, 1911, 1959, +0, 1959, 1944, +0, 1959, 1854, +0, 1959, 1697, +0, 1959, 1331, +0, 2092, 0, +0, 2225, 0, +1122, 2357, 0, +1733, 2490, 0, +2045, 2622, 0, +2277, 2755, 0, +2471, 2887, 0, +2645, 3019, 0, +2806, 3151, 0, +2958, 3283, 0, +3105, 3416, 0, +3248, 3548, 0, +3388, 3680, 0, +3526, 3812, 0, +3662, 3944, 0, +3797, 4076, 0, +3932, 4095, 0, +0, 1657, 1961, +0, 1664, 1961, +0, 1674, 1960, +0, 1686, 1959, +0, 1703, 1958, +0, 1721, 1958, +0, 1743, 1958, +0, 1772, 1958, +0, 1808, 1958, +0, 1852, 1958, +0, 1905, 1958, +0, 1958, 1948, +0, 1958, 1859, +0, 1958, 1703, +0, 1958, 1344, +0, 2091, 0, +0, 2224, 0, +1176, 2357, 0, +1748, 2489, 0, +2052, 2622, 0, +2281, 2755, 0, +2474, 2887, 0, +2647, 3019, 0, +2807, 3151, 0, +2959, 3283, 0, +3106, 3416, 0, +3248, 3548, 0, +3388, 3680, 0, +3526, 3812, 0, +3662, 3944, 0, +3797, 4076, 0, +3932, 4095, 0, +0, 1636, 1961, +0, 1644, 1961, +0, 1654, 1960, +0, 1667, 1959, +0, 1684, 1958, +0, 1706, 1956, +0, 1730, 1956, +0, 1759, 1956, +0, 1796, 1956, +0, 1841, 1956, +0, 1895, 1956, +0, 1956, 1953, +0, 1956, 1865, +0, 1956, 1711, +0, 1956, 1362, +0, 2089, 0, +0, 2223, 0, +1240, 2356, 0, +1767, 2489, 0, +2062, 2621, 0, +2287, 2754, 0, +2478, 2887, 0, +2649, 3019, 0, +2809, 3151, 0, +2960, 3283, 0, +3106, 3416, 0, +3249, 3548, 0, +3388, 3680, 0, +3526, 3812, 0, +3662, 3944, 0, +3797, 4076, 0, +3932, 4095, 0, +0, 1607, 1961, +0, 1615, 1961, +0, 1626, 1960, +0, 1640, 1959, +0, 1658, 1958, +0, 1681, 1956, +0, 1711, 1953, +0, 1742, 1953, +0, 1779, 1953, +0, 1826, 1953, +0, 1882, 1953, +0, 1947, 1953, +0, 1953, 1872, +0, 1953, 1722, +0, 1953, 1385, +0, 2087, 0, +0, 2221, 0, +1313, 2355, 0, +1791, 2488, 0, +2075, 2621, 0, +2295, 2754, 0, +2483, 2886, 0, +2653, 3018, 0, +2812, 3151, 0, +2962, 3283, 0, +3108, 3415, 0, +3250, 3548, 0, +3389, 3680, 0, +3527, 3812, 0, +3663, 3944, 0, +3798, 4076, 0, +3932, 4095, 0, +0, 1565, 1961, +0, 1574, 1961, +0, 1586, 1960, +0, 1601, 1959, +0, 1621, 1958, +0, 1646, 1956, +0, 1678, 1953, +0, 1716, 1950, +0, 1757, 1950, +0, 1806, 1950, +0, 1864, 1950, +0, 1931, 1950, +0, 1950, 1882, +0, 1950, 1736, +0, 1950, 1413, +0, 2085, 0, +0, 2220, 0, +1396, 2353, 0, +1822, 2487, 0, +2092, 2620, 0, +2305, 2753, 0, +2490, 2886, 0, +2658, 3018, 0, +2815, 3151, 0, +2965, 3283, 0, +3110, 3415, 0, +3251, 3548, 0, +3390, 3680, 0, +3528, 3812, 0, +3663, 3944, 0, +3798, 4076, 0, +3932, 4095, 0, +0, 1503, 1961, +0, 1513, 1961, +0, 1526, 1960, +0, 1544, 1959, +0, 1566, 1958, +0, 1594, 1956, +0, 1629, 1953, +0, 1672, 1950, +0, 1724, 1945, +0, 1776, 1945, +0, 1838, 1945, +0, 1909, 1945, +0, 1945, 1895, +0, 1945, 1754, +0, 1945, 1449, +0, 2082, 0, +140, 2217, 0, +1487, 2352, 0, +1859, 2486, 0, +2113, 2619, 0, +2319, 2752, 0, +2499, 2885, 0, +2664, 3018, 0, +2819, 3151, 0, +2968, 3283, 0, +3112, 3415, 0, +3253, 3548, 0, +3392, 3680, 0, +3528, 3812, 0, +3664, 3944, 0, +3798, 4076, 0, +3933, 4095, 0, +0, 1402, 1961, +0, 1415, 1961, +0, 1431, 1960, +0, 1453, 1959, +0, 1480, 1958, +0, 1514, 1956, +0, 1555, 1953, +0, 1606, 1950, +0, 1665, 1945, +0, 1734, 1939, +0, 1801, 1939, +0, 1878, 1939, +0, 1939, 1912, +0, 1939, 1776, +0, 1939, 1492, +0, 2077, 173, +932, 2214, 0, +1586, 2349, 0, +1906, 2484, 0, +2140, 2618, 0, +2336, 2751, 0, +2511, 2885, 0, +2672, 3017, 0, +2825, 3150, 0, +2972, 3282, 0, +3115, 3415, 0, +3255, 3547, 0, +3393, 3680, 0, +3530, 3812, 0, +3665, 3944, 0, +3799, 4076, 0, +3933, 4095, 0, +0, 1220, 1961, +0, 1238, 1961, +0, 1263, 1960, +0, 1294, 1959, +0, 1332, 1958, +0, 1378, 1956, +0, 1433, 1953, +0, 1498, 1950, +0, 1572, 1945, +0, 1655, 1939, +872, 1748, 1930, +872, 1833, 1930, +872, 1927, 1930, +872, 1930, 1805, +872, 1930, 1545, +79, 2071, 706, +1270, 2209, 0, +1692, 2346, 0, +1961, 2481, 0, +2174, 2616, 0, +2359, 2750, 0, +2526, 2883, 0, +2683, 3016, 0, +2833, 3150, 0, +2977, 3282, 0, +3119, 3414, 0, +3258, 3547, 0, +3395, 3679, 0, +3531, 3812, 0, +3666, 3944, 0, +3800, 4076, 0, +3934, 4095, 0, +0, 726, 1961, +0, 780, 1961, +0, 844, 1960, +0, 917, 1959, +0, 1000, 1958, +0, 1091, 1956, +0, 1190, 1953, +0, 1295, 1950, +0, 1407, 1945, +0, 1523, 1939, +872, 1642, 1930, +1223, 1765, 1919, +1223, 1872, 1919, +1223, 1919, 1841, +1223, 1919, 1607, +1006, 2062, 1005, +1512, 2203, 217, +1803, 2341, 0, +2026, 2478, 0, +2216, 2613, 0, +2387, 2748, 0, +2546, 2882, 0, +2697, 3015, 0, +2843, 3149, 0, +2985, 3281, 0, +3125, 3414, 0, +3262, 3547, 0, +3398, 3679, 0, +3533, 3812, 0, +3668, 3944, 0, +3801, 4076, 0, +3935, 4095, 0, +0, 0, 1961, +0, 0, 1961, +0, 0, 1960, +0, 0, 1959, +0, 0, 1958, +0, 0, 1956, +0, 0, 1953, +0, 670, 1950, +0, 1007, 1945, +0, 1248, 1939, +872, 1447, 1930, +1223, 1624, 1919, +1469, 1787, 1903, +1469, 1903, 1885, +1469, 1903, 1678, +1453, 2051, 1355, +1711, 2194, 1136, +1919, 2335, 345, +2100, 2473, 0, +2266, 2610, 0, +2422, 2746, 0, +2571, 2880, 0, +2715, 3014, 0, +2856, 3148, 0, +2995, 3280, 0, +3132, 3414, 0, +3268, 3546, 0, +3402, 3679, 0, +3536, 3811, 0, +3670, 3944, 0, +3803, 4076, 0, +3936, 4095, 0, +0, 0, 1961, +0, 0, 1961, +0, 0, 1960, +0, 0, 1959, +0, 0, 1958, +0, 0, 1956, +0, 0, 1953, +0, 0, 1950, +37, 0, 1945, +573, 0, 1939, +872, 873, 1930, +1223, 1321, 1919, +1469, 1598, 1903, +1671, 1814, 1880, +1671, 1880, 1759, +1730, 2035, 1601, +1888, 2183, 1487, +2038, 2326, 1269, +2184, 2467, 477, +2326, 2605, 0, +2465, 2742, 0, +2602, 2878, 0, +2738, 3012, 0, +2873, 3146, 0, +3007, 3280, 0, +3141, 3413, 0, +3275, 3546, 0, +3407, 3678, 0, +3540, 3811, 0, +3673, 3943, 0, +3805, 4076, 0, +3938, 4095, 0, +1306, 0, 1961, +1312, 0, 1961, +1320, 0, 1960, +1331, 0, 1959, +1344, 0, 1958, +1362, 0, 1956, +1385, 0, 1953, +1413, 0, 1950, +1449, 0, 1945, +1492, 0, 1939, +1545, 872, 1930, +1607, 1223, 1919, +1678, 1469, 1903, +1759, 1671, 1880, +1849, 1849, 1849, +1946, 2013, 1803, +2051, 2167, 1733, +2161, 2315, 1619, +2276, 2459, 1401, +2395, 2599, 611, +2517, 2738, 0, +2641, 2874, 0, +2767, 3010, 0, +2895, 3144, 0, +3024, 3278, 0, +3154, 3412, 0, +3284, 3545, 0, +3414, 3678, 0, +3545, 3810, 0, +3677, 3943, 0, +3808, 4075, 0, +3940, 4095, 0, +1816, 0, 2094, +1818, 0, 2093, +1821, 0, 2093, +1824, 0, 2092, +1829, 0, 2091, +1835, 0, 2089, +1843, 0, 2087, +1854, 0, 2085, +1868, 0, 2082, +1886, 0, 2077, +1908, 79, 2071, +1937, 1005, 2062, +1973, 1355, 2051, +2017, 1601, 2035, +2013, 1803, 1946, +2013, 1891, 1803, +2167, 2149, 1733, +2268, 2315, 1619, +2362, 2459, 1401, +2462, 2599, 611, +2569, 2738, 0, +2681, 2874, 0, +2798, 3010, 0, +2919, 3144, 0, +3041, 3278, 0, +3167, 3412, 0, +3294, 3545, 0, +3422, 3678, 0, +3551, 3810, 0, +3681, 3943, 0, +3811, 4075, 0, +3942, 4095, 0, +2108, 0, 2226, +2109, 0, 2226, +2111, 0, 2225, +2112, 0, 2225, +2115, 0, 2224, +2118, 0, 2223, +2123, 0, 2221, +2128, 0, 2220, +2136, 0, 2217, +2146, 0, 2214, +2159, 0, 2209, +2176, 217, 2203, +2194, 1136, 2191, +2183, 1487, 2136, +2167, 1733, 2051, +2167, 1733, 1862, +2167, 1943, 1733, +2315, 2237, 1619, +2455, 2459, 1401, +2538, 2599, 611, +2631, 2738, 0, +2730, 2874, 0, +2836, 3010, 0, +2948, 3144, 0, +3064, 3278, 0, +3184, 3412, 0, +3307, 3545, 0, +3432, 3678, 0, +3559, 3810, 0, +3687, 3943, 0, +3816, 4075, 0, +3945, 4095, 0, +2332, 0, 2358, +2332, 0, 2358, +2333, 0, 2358, +2334, 0, 2357, +2335, 0, 2357, +2338, 0, 2356, +2340, 0, 2355, +2344, 0, 2353, +2349, 0, 2352, +2349, 0, 2343, +2346, 0, 2328, +2341, 0, 2305, +2335, 345, 2274, +2326, 1269, 2229, +2315, 1619, 2161, +2315, 1619, 2020, +2315, 1619, 1718, +2315, 2003, 1619, +2459, 2334, 1401, +2599, 2572, 611, +2702, 2738, 0, +2788, 2874, 0, +2883, 3010, 0, +2985, 3144, 0, +3093, 3278, 0, +3206, 3412, 0, +3324, 3545, 0, +3445, 3678, 0, +3569, 3810, 0, +3694, 3943, 0, +3821, 4075, 0, +3950, 4095, 0, +2491, 0, 2458, +2491, 0, 2457, +2490, 0, 2456, +2490, 0, 2454, +2489, 0, 2452, +2489, 0, 2449, +2488, 0, 2445, +2487, 0, 2440, +2486, 0, 2433, +2484, 0, 2423, +2481, 0, 2410, +2478, 0, 2392, +2473, 0, 2366, +2467, 477, 2330, +2459, 1401, 2276, +2459, 1401, 2171, +2459, 1401, 1976, +2459, 1401, 1403, +2459, 2073, 1401, +2599, 2437, 611, +2738, 2688, 0, +2856, 2874, 0, +2939, 3010, 0, +3030, 3144, 0, +3129, 3278, 0, +3234, 3412, 0, +3346, 3545, 0, +3462, 3678, 0, +3582, 3810, 0, +3704, 3943, 0, +3829, 4075, 0, +3955, 4095, 0, +2623, 0, 2541, +2623, 0, 2540, +2623, 0, 2539, +2622, 0, 2538, +2622, 0, 2536, +2621, 0, 2533, +2621, 0, 2530, +2620, 0, 2526, +2619, 0, 2520, +2618, 0, 2512, +2616, 0, 2501, +2613, 0, 2487, +2610, 0, 2466, +2605, 0, 2437, +2599, 611, 2395, +2599, 611, 2316, +2599, 611, 2183, +2599, 611, 1908, +2599, 1236, 611, +2599, 2153, 611, +2738, 2547, 0, +2874, 2807, 0, +3004, 3010, 0, +3084, 3144, 0, +3173, 3278, 0, +3270, 3412, 0, +3374, 3545, 0, +3483, 3678, 0, +3598, 3810, 0, +3717, 3943, 0, +3838, 4075, 0, +3963, 4095, 0, +2755, 0, 2632, +2755, 0, 2632, +2755, 0, 2631, +2755, 0, 2630, +2755, 0, 2628, +2754, 0, 2627, +2754, 0, 2624, +2753, 0, 2620, +2752, 0, 2616, +2751, 0, 2609, +2750, 0, 2601, +2748, 0, 2589, +2746, 0, 2572, +2742, 0, 2550, +2738, 0, 2517, +2738, 0, 2458, +2738, 0, 2365, +2738, 0, 2200, +2738, 0, 1799, +2738, 817, 0, +2738, 2241, 0, +2874, 2661, 0, +3010, 2928, 0, +3144, 3141, 0, +3225, 3278, 0, +3313, 3412, 0, +3408, 3545, 0, +3511, 3678, 0, +3620, 3810, 0, +3733, 3943, 0, +3851, 4075, 0, +3972, 4095, 0, +2887, 0, 2732, +2887, 0, 2731, +2887, 0, 2731, +2887, 0, 2730, +2887, 0, 2728, +2887, 0, 2727, +2886, 0, 2725, +2886, 0, 2722, +2885, 0, 2718, +2885, 0, 2713, +2883, 0, 2706, +2882, 0, 2697, +2880, 0, 2684, +2878, 0, 2666, +2874, 0, 2641, +2874, 0, 2597, +2874, 0, 2530, +2874, 0, 2423, +2874, 0, 2220, +2874, 0, 1596, +2874, 0, 0, +2874, 2338, 0, +3010, 2778, 0, +3144, 3053, 0, +3278, 3269, 0, +3365, 3412, 0, +3451, 3545, 0, +3545, 3678, 0, +3647, 3810, 0, +3755, 3943, 0, +3868, 4075, 0, +3985, 4095, 0, +3019, 0, 2837, +3019, 0, 2837, +3019, 0, 2836, +3019, 0, 2836, +3019, 0, 2835, +3019, 0, 2834, +3018, 0, 2832, +3018, 0, 2830, +3018, 0, 2827, +3017, 0, 2823, +3016, 0, 2817, +3015, 0, 2810, +3014, 0, 2800, +3012, 0, 2786, +3010, 0, 2767, +3010, 0, 2734, +3010, 0, 2686, +3010, 0, 2612, +3010, 0, 2489, +3010, 0, 2247, +3010, 0, 922, +3010, 0, 0, +3010, 2441, 0, +3144, 2901, 0, +3278, 3180, 0, +3412, 3397, 0, +3502, 3545, 0, +3587, 3678, 0, +3680, 3810, 0, +3781, 3943, 0, +3889, 4075, 0, +4002, 4095, 0, +3152, 0, 2949, +3152, 0, 2949, +3152, 0, 2948, +3151, 0, 2948, +3151, 0, 2947, +3151, 0, 2946, +3151, 0, 2945, +3151, 0, 2943, +3151, 0, 2941, +3150, 0, 2938, +3150, 0, 2933, +3149, 0, 2928, +3148, 0, 2920, +3146, 0, 2910, +3144, 0, 2895, +3144, 0, 2870, +3144, 0, 2835, +3144, 0, 2783, +3144, 0, 2703, +3144, 0, 2566, +3144, 0, 2280, +3144, 0, 0, +3144, 0, 0, +3144, 2551, 0, +3278, 3023, 0, +3412, 3307, 0, +3545, 3526, 0, +3638, 3678, 0, +3722, 3810, 0, +3815, 3943, 0, +3916, 4075, 0, +4023, 4095, 0, +3284, 0, 3065, +3283, 0, 3065, +3283, 0, 3064, +3283, 0, 3064, +3283, 0, 3063, +3283, 0, 3062, +3283, 0, 3062, +3283, 0, 3060, +3283, 0, 3059, +3282, 0, 3056, +3282, 0, 3053, +3281, 0, 3049, +3280, 0, 3043, +3280, 0, 3034, +3278, 0, 3024, +3278, 0, 3005, +3278, 0, 2979, +3278, 0, 2942, +3278, 0, 2886, +3278, 0, 2800, +3278, 0, 2651, +3278, 0, 2320, +3278, 0, 0, +3278, 0, 0, +3278, 2665, 0, +3412, 3150, 0, +3545, 3436, 0, +3678, 3657, 0, +3773, 3810, 0, +3857, 3943, 0, +3949, 4075, 0, +4049, 4095, 0, +3416, 0, 3184, +3416, 0, 3184, +3416, 0, 3184, +3416, 0, 3184, +3416, 0, 3184, +3416, 0, 3183, +3415, 0, 3182, +3415, 0, 3181, +3415, 0, 3180, +3415, 0, 3178, +3414, 0, 3175, +3414, 0, 3172, +3414, 0, 3168, +3413, 0, 3162, +3412, 0, 3154, +3412, 0, 3140, +3412, 0, 3120, +3412, 0, 3093, +3412, 0, 3055, +3412, 0, 2997, +3412, 0, 2906, +3412, 0, 2746, +3412, 0, 2371, +3412, 0, 0, +3412, 0, 0, +3412, 2784, 0, +3545, 3278, 0, +3678, 3566, 0, +3810, 3787, 0, +3907, 3943, 0, +3991, 4075, 0, +4083, 4095, 0, +3548, 0, 3307, +3548, 0, 3307, +3548, 0, 3307, +3548, 0, 3307, +3548, 0, 3307, +3548, 0, 3306, +3548, 0, 3305, +3548, 0, 3305, +3548, 0, 3303, +3547, 0, 3302, +3547, 0, 3300, +3547, 0, 3298, +3546, 0, 3294, +3546, 0, 3290, +3545, 0, 3284, +3545, 0, 3273, +3545, 0, 3259, +3545, 0, 3239, +3545, 0, 3211, +3545, 0, 3171, +3545, 0, 3111, +3545, 0, 3016, +3545, 0, 2848, +3545, 0, 2429, +3545, 0, 0, +3545, 0, 0, +3545, 2905, 0, +3678, 3406, 0, +3810, 3696, 0, +3943, 3918, 0, +4041, 4075, 0, +4095, 4095, 0, +3680, 0, 3432, +3680, 0, 3432, +3680, 0, 3432, +3680, 0, 3432, +3680, 0, 3431, +3680, 0, 3431, +3680, 0, 3431, +3680, 0, 3430, +3680, 0, 3429, +3680, 0, 3428, +3679, 0, 3427, +3679, 0, 3425, +3679, 0, 3422, +3678, 0, 3419, +3678, 0, 3414, +3678, 0, 3407, +3678, 0, 3396, +3678, 0, 3381, +3678, 0, 3361, +3678, 0, 3333, +3678, 0, 3291, +3678, 0, 3230, +3678, 0, 3132, +3678, 0, 2955, +3678, 0, 2499, +3678, 0, 0, +3678, 0, 0, +3678, 3029, 0, +3810, 3536, 0, +3943, 3827, 0, +4075, 4049, 0, +4095, 4095, 0, +3812, 0, 3559, +3812, 0, 3559, +3812, 0, 3559, +3812, 0, 3558, +3812, 0, 3558, +3812, 0, 3558, +3812, 0, 3558, +3812, 0, 3557, +3812, 0, 3557, +3812, 0, 3556, +3812, 0, 3555, +3812, 0, 3553, +3811, 0, 3552, +3811, 0, 3549, +3810, 0, 3545, +3810, 0, 3540, +3810, 0, 3532, +3810, 0, 3521, +3810, 0, 3506, +3810, 0, 3486, +3810, 0, 3457, +3810, 0, 3415, +3810, 0, 3352, +3810, 0, 3251, +3810, 0, 3069, +3810, 0, 2576, +3810, 0, 0, +3810, 0, 0, +3810, 3155, 0, +3943, 3665, 0, +4075, 3958, 0, +4095, 4095, 0, +3944, 0, 3687, +3944, 0, 3687, +3944, 0, 3687, +3944, 0, 3686, +3944, 0, 3686, +3944, 0, 3686, +3944, 0, 3686, +3944, 0, 3686, +3944, 0, 3685, +3944, 0, 3685, +3944, 0, 3684, +3944, 0, 3683, +3944, 0, 3681, +3943, 0, 3679, +3943, 0, 3677, +3943, 0, 3672, +3943, 0, 3666, +3943, 0, 3659, +3943, 0, 3648, +3943, 0, 3632, +3943, 0, 3612, +3943, 0, 3583, +3943, 0, 3540, +3943, 0, 3476, +3943, 0, 3374, +3943, 0, 3186, +3943, 0, 2662, +3943, 0, 0, +3943, 0, 0, +3943, 3283, 0, +4075, 3796, 0, +4095, 4089, 0, +4076, 0, 3816, +4076, 0, 3816, +4076, 0, 3816, +4076, 0, 3815, +4076, 0, 3815, +4076, 0, 3815, +4076, 0, 3815, +4076, 0, 3815, +4076, 0, 3814, +4076, 0, 3814, +4076, 0, 3813, +4076, 0, 3812, +4076, 0, 3812, +4076, 0, 3810, +4075, 0, 3808, +4075, 0, 3805, +4075, 0, 3801, +4075, 0, 3795, +4075, 0, 3787, +4075, 0, 3776, +4075, 0, 3760, +4075, 0, 3739, +4075, 0, 3710, +4075, 0, 3667, +4075, 0, 3602, +4075, 0, 3498, +4075, 0, 3306, +4075, 0, 2756, +4075, 0, 0, +4075, 0, 0, +4075, 3411, 0, +4095, 3927, 0, +4095, 0, 3946, +4095, 0, 3946, +4095, 0, 3945, +4095, 0, 3945, +4095, 0, 3945, +4095, 0, 3945, +4095, 0, 3945, +4095, 0, 3945, +4095, 0, 3945, +4095, 0, 3944, +4095, 0, 3944, +4095, 0, 3943, +4095, 0, 3942, +4095, 0, 3941, +4095, 0, 3940, +4095, 0, 3937, +4095, 0, 3934, +4095, 0, 3930, +4095, 0, 3924, +4095, 0, 3916, +4095, 0, 3905, +4095, 0, 3889, +4095, 0, 3868, +4095, 0, 3838, +4095, 0, 3795, +4095, 0, 3730, +4095, 0, 3625, +4095, 0, 3430, +4095, 0, 2861, +4095, 0, 0, +4095, 0, 0, +4095, 3541, 0, +0, 1827, 2094, +0, 1831, 2094, +0, 1837, 2094, +0, 1845, 2094, +0, 1855, 2094, +0, 1867, 2094, +0, 1884, 2094, +0, 1905, 2094, +0, 1932, 2094, +0, 1966, 2094, +0, 2007, 2094, +0, 2058, 2094, +0, 2094, 2069, +0, 2094, 1977, +0, 2094, 1816, +0, 2094, 1433, +0, 2226, 0, +0, 2358, 0, +1120, 2491, 0, +1833, 2623, 0, +2162, 2755, 0, +2400, 2887, 0, +2597, 3019, 0, +2773, 3152, 0, +2935, 3284, 0, +3088, 3416, 0, +3236, 3548, 0, +3379, 3680, 0, +3519, 3812, 0, +3657, 3944, 0, +3793, 4076, 0, +3929, 4095, 0, +0, 1823, 2094, +0, 1828, 2093, +0, 1834, 2093, +0, 1841, 2093, +0, 1851, 2093, +0, 1864, 2093, +0, 1881, 2093, +0, 1902, 2093, +0, 1929, 2093, +0, 1963, 2093, +0, 2005, 2093, +0, 2056, 2093, +0, 2093, 2070, +0, 2093, 1979, +0, 2093, 1818, +0, 2093, 1438, +0, 2226, 0, +0, 2358, 0, +1143, 2491, 0, +1838, 2623, 0, +2164, 2755, 0, +2401, 2887, 0, +2598, 3019, 0, +2773, 3152, 0, +2935, 3283, 0, +3088, 3416, 0, +3236, 3548, 0, +3379, 3680, 0, +3519, 3812, 0, +3657, 3944, 0, +3793, 4076, 0, +3929, 4095, 0, +0, 1817, 2094, +0, 1822, 2093, +0, 1829, 2093, +0, 1837, 2093, +0, 1847, 2093, +0, 1860, 2093, +0, 1877, 2093, +0, 1898, 2093, +0, 1926, 2093, +0, 1960, 2093, +0, 2002, 2093, +0, 2053, 2093, +0, 2093, 2071, +0, 2093, 1981, +0, 2093, 1821, +0, 2093, 1444, +0, 2225, 0, +0, 2358, 0, +1173, 2490, 0, +1845, 2623, 0, +2167, 2755, 0, +2403, 2887, 0, +2599, 3019, 0, +2774, 3152, 0, +2936, 3283, 0, +3089, 3416, 0, +3236, 3548, 0, +3379, 3680, 0, +3519, 3812, 0, +3657, 3944, 0, +3793, 4076, 0, +3929, 4095, 0, +0, 1809, 2094, +0, 1814, 2093, +0, 1821, 2093, +0, 1830, 2092, +0, 1841, 2092, +0, 1854, 2092, +0, 1871, 2092, +0, 1893, 2092, +0, 1920, 2092, +0, 1955, 2092, +0, 1997, 2092, +0, 2049, 2092, +0, 2092, 2073, +0, 2092, 1983, +0, 2092, 1824, +0, 2092, 1452, +0, 2225, 0, +0, 2357, 0, +1210, 2490, 0, +1853, 2622, 0, +2172, 2755, 0, +2406, 2887, 0, +2601, 3019, 0, +2775, 3151, 0, +2936, 3283, 0, +3089, 3416, 0, +3237, 3548, 0, +3379, 3680, 0, +3520, 3812, 0, +3657, 3944, 0, +3794, 4076, 0, +3929, 4095, 0, +0, 1798, 2094, +0, 1804, 2093, +0, 1811, 2093, +0, 1820, 2092, +0, 1832, 2091, +0, 1846, 2091, +0, 1863, 2091, +0, 1885, 2091, +0, 1913, 2091, +0, 1949, 2091, +0, 1992, 2091, +0, 2044, 2091, +0, 2091, 2076, +0, 2091, 1986, +0, 2091, 1829, +0, 2091, 1463, +0, 2224, 0, +0, 2357, 0, +1255, 2489, 0, +1865, 2622, 0, +2177, 2755, 0, +2409, 2887, 0, +2603, 3019, 0, +2777, 3151, 0, +2938, 3283, 0, +3090, 3416, 0, +3237, 3548, 0, +3380, 3680, 0, +3520, 3812, 0, +3658, 3944, 0, +3794, 4076, 0, +3929, 4095, 0, +0, 1783, 2094, +0, 1789, 2093, +0, 1796, 2093, +0, 1806, 2092, +0, 1819, 2091, +0, 1835, 2089, +0, 1853, 2089, +0, 1875, 2089, +0, 1904, 2089, +0, 1940, 2089, +0, 1984, 2089, +0, 2037, 2089, +0, 2089, 2080, +0, 2089, 1991, +0, 2089, 1835, +0, 2089, 1476, +0, 2223, 0, +0, 2356, 0, +1310, 2489, 0, +1880, 2621, 0, +2185, 2754, 0, +2413, 2887, 0, +2606, 3019, 0, +2779, 3151, 0, +2939, 3283, 0, +3091, 3416, 0, +3238, 3548, 0, +3380, 3680, 0, +3520, 3812, 0, +3658, 3944, 0, +3794, 4076, 0, +3929, 4095, 0, +0, 1763, 2094, +0, 1768, 2093, +0, 1776, 2093, +0, 1786, 2092, +0, 1799, 2091, +0, 1816, 2089, +0, 1838, 2087, +0, 1862, 2087, +0, 1891, 2087, +0, 1928, 2087, +0, 1973, 2087, +0, 2027, 2087, +0, 2087, 2085, +0, 2087, 1996, +0, 2087, 1843, +0, 2087, 1494, +0, 2221, 0, +0, 2355, 0, +1373, 2488, 0, +1899, 2621, 0, +2195, 2754, 0, +2419, 2886, 0, +2610, 3018, 0, +2782, 3151, 0, +2941, 3283, 0, +3093, 3415, 0, +3239, 3548, 0, +3381, 3680, 0, +3521, 3812, 0, +3658, 3944, 0, +3794, 4076, 0, +3930, 4095, 0, +0, 1733, 2094, +0, 1739, 2093, +0, 1748, 2093, +0, 1758, 2092, +0, 1772, 2091, +0, 1790, 2089, +0, 1813, 2087, +0, 1843, 2085, +0, 1873, 2085, +0, 1912, 2085, +0, 1958, 2085, +0, 2014, 2085, +0, 2079, 2085, +0, 2085, 2004, +0, 2085, 1854, +0, 2085, 1517, +0, 2220, 0, +0, 2353, 0, +1446, 2487, 0, +1923, 2620, 0, +2208, 2753, 0, +2427, 2886, 0, +2615, 3018, 0, +2785, 3151, 0, +2943, 3283, 0, +3094, 3415, 0, +3240, 3548, 0, +3382, 3680, 0, +3521, 3812, 0, +3659, 3944, 0, +3795, 4076, 0, +3930, 4095, 0, +0, 1691, 2094, +0, 1698, 2093, +0, 1706, 2093, +0, 1718, 2092, +0, 1733, 2091, +0, 1753, 2089, +0, 1778, 2087, +0, 1810, 2085, +0, 1849, 2082, +0, 1889, 2082, +0, 1938, 2082, +0, 1996, 2082, +0, 2063, 2082, +0, 2082, 2014, +0, 2082, 1868, +0, 2082, 1545, +0, 2217, 0, +0, 2352, 0, +1529, 2486, 0, +1954, 2619, 0, +2224, 2752, 0, +2438, 2885, 0, +2622, 3018, 0, +2790, 3151, 0, +2947, 3283, 0, +3097, 3415, 0, +3242, 3548, 0, +3383, 3680, 0, +3522, 3812, 0, +3659, 3944, 0, +3795, 4076, 0, +3930, 4095, 0, +0, 1626, 2094, +0, 1635, 2093, +0, 1645, 2093, +0, 1658, 2092, +0, 1676, 2091, +0, 1698, 2089, +0, 1726, 2087, +0, 1761, 2085, +0, 1804, 2082, +0, 1856, 2077, +0, 1908, 2077, +0, 1970, 2077, +0, 2041, 2077, +0, 2077, 2027, +0, 2077, 1886, +0, 2077, 1581, +0, 2214, 0, +275, 2349, 0, +1620, 2484, 0, +1991, 2618, 0, +2245, 2751, 0, +2451, 2885, 0, +2631, 3017, 0, +2796, 3150, 0, +2951, 3282, 0, +3100, 3415, 0, +3244, 3547, 0, +3385, 3680, 0, +3523, 3812, 0, +3661, 3944, 0, +3796, 4076, 0, +3931, 4095, 0, +0, 1524, 2094, +0, 1534, 2093, +0, 1547, 2093, +0, 1564, 2092, +0, 1585, 2091, +0, 1612, 2089, +0, 1646, 2087, +0, 1687, 2085, +0, 1738, 2082, +0, 1797, 2077, +79, 1866, 2071, +79, 1934, 2071, +79, 2010, 2071, +79, 2071, 2044, +79, 2071, 1908, +79, 2071, 1625, +0, 2209, 303, +1064, 2346, 0, +1719, 2481, 0, +2038, 2616, 0, +2273, 2750, 0, +2469, 2883, 0, +2643, 3016, 0, +2804, 3150, 0, +2957, 3282, 0, +3104, 3414, 0, +3247, 3547, 0, +3387, 3679, 0, +3525, 3812, 0, +3662, 3944, 0, +3797, 4076, 0, +3932, 4095, 0, +0, 1336, 2094, +0, 1351, 2093, +0, 1370, 2093, +0, 1394, 2092, +0, 1425, 2091, +0, 1463, 2089, +0, 1509, 2087, +0, 1565, 2085, +0, 1630, 2082, +0, 1704, 2077, +79, 1787, 2071, +1005, 1880, 2062, +1005, 1965, 2062, +1005, 2059, 2062, +1005, 2062, 1937, +1005, 2062, 1677, +217, 2203, 838, +1403, 2341, 0, +1824, 2478, 0, +2093, 2613, 0, +2306, 2748, 0, +2491, 2882, 0, +2658, 3015, 0, +2815, 3149, 0, +2965, 3281, 0, +3110, 3414, 0, +3251, 3547, 0, +3390, 3679, 0, +3528, 3812, 0, +3663, 3944, 0, +3798, 4076, 0, +3932, 4095, 0, +0, 814, 2094, +0, 859, 2093, +0, 913, 2093, +0, 977, 2092, +0, 1050, 2091, +0, 1133, 2089, +0, 1224, 2087, +0, 1322, 2085, +0, 1428, 2082, +0, 1539, 2077, +79, 1655, 2071, +1005, 1774, 2062, +1355, 1897, 2051, +1355, 2004, 2051, +1355, 2051, 1973, +1355, 2051, 1739, +1137, 2194, 1136, +1644, 2335, 345, +1935, 2473, 0, +2158, 2610, 0, +2348, 2746, 0, +2519, 2880, 0, +2678, 3014, 0, +2829, 3148, 0, +2975, 3280, 0, +3117, 3414, 0, +3257, 3546, 0, +3394, 3679, 0, +3530, 3811, 0, +3666, 3944, 0, +3800, 4076, 0, +3934, 4095, 0, +0, 0, 2094, +0, 0, 2093, +0, 0, 2093, +0, 0, 2092, +0, 0, 2091, +0, 0, 2089, +0, 0, 2087, +0, 10, 2085, +0, 800, 2082, +0, 1138, 2077, +79, 1379, 2071, +1005, 1579, 2062, +1355, 1756, 2051, +1601, 1919, 2035, +1601, 2035, 2017, +1601, 2035, 1811, +1585, 2183, 1487, +1843, 2326, 1269, +2051, 2467, 477, +2233, 2605, 0, +2398, 2742, 0, +2554, 2878, 0, +2703, 3012, 0, +2847, 3146, 0, +2988, 3280, 0, +3127, 3413, 0, +3264, 3546, 0, +3400, 3678, 0, +3534, 3811, 0, +3668, 3943, 0, +3802, 4076, 0, +3935, 4095, 0, +0, 0, 2094, +0, 0, 2093, +0, 0, 2093, +0, 0, 2092, +0, 0, 2091, +0, 0, 2089, +0, 0, 2087, +0, 0, 2085, +0, 0, 2082, +173, 0, 2077, +706, 79, 2071, +1005, 1006, 2062, +1355, 1453, 2051, +1601, 1730, 2035, +1803, 1946, 2013, +1803, 2013, 1891, +1862, 2167, 1733, +2020, 2315, 1619, +2171, 2459, 1401, +2316, 2599, 611, +2458, 2738, 0, +2597, 2874, 0, +2734, 3010, 0, +2870, 3144, 0, +3005, 3278, 0, +3140, 3412, 0, +3273, 3545, 0, +3407, 3678, 0, +3540, 3810, 0, +3672, 3943, 0, +3805, 4075, 0, +3937, 4095, 0, +1433, 0, 2094, +1438, 0, 2093, +1444, 0, 2093, +1452, 0, 2092, +1463, 0, 2091, +1476, 0, 2089, +1494, 0, 2087, +1517, 0, 2085, +1545, 0, 2082, +1581, 0, 2077, +1625, 79, 2071, +1677, 1005, 2062, +1739, 1355, 2051, +1811, 1601, 2035, +1891, 1803, 2013, +1981, 1981, 1981, +2078, 2145, 1935, +2183, 2299, 1865, +2293, 2447, 1751, +2408, 2591, 1533, +2527, 2731, 738, +2649, 2870, 0, +2773, 3006, 0, +2900, 3142, 0, +3027, 3276, 0, +3156, 3410, 0, +3285, 3544, 0, +3416, 3677, 0, +3547, 3810, 0, +3677, 3943, 0, +3809, 4075, 0, +3940, 4095, 0, +1946, 0, 2226, +1948, 0, 2226, +1950, 0, 2225, +1953, 0, 2225, +1956, 0, 2224, +1961, 0, 2223, +1967, 0, 2221, +1975, 0, 2220, +1986, 0, 2217, +2000, 0, 2214, +2018, 0, 2209, +2041, 217, 2203, +2069, 1136, 2194, +2105, 1487, 2183, +2149, 1733, 2167, +2145, 1935, 2078, +2145, 2023, 1935, +2299, 2281, 1865, +2401, 2447, 1751, +2493, 2591, 1533, +2594, 2731, 738, +2701, 2870, 0, +2813, 3006, 0, +2931, 3142, 0, +3050, 3276, 0, +3174, 3410, 0, +3299, 3544, 0, +3426, 3677, 0, +3554, 3810, 0, +3683, 3943, 0, +3813, 4075, 0, +3944, 4095, 0, +2239, 0, 2358, +2240, 0, 2358, +2241, 0, 2358, +2243, 0, 2357, +2245, 0, 2357, +2247, 0, 2356, +2251, 0, 2355, +2255, 0, 2353, +2261, 0, 2352, +2268, 0, 2349, +2278, 0, 2346, +2291, 0, 2341, +2308, 345, 2335, +2326, 1269, 2323, +2315, 1619, 2268, +2299, 1865, 2183, +2299, 1865, 1994, +2299, 2075, 1865, +2447, 2370, 1751, +2587, 2591, 1533, +2671, 2731, 738, +2763, 2870, 0, +2862, 3006, 0, +2969, 3142, 0, +3080, 3276, 0, +3196, 3410, 0, +3316, 3544, 0, +3439, 3677, 0, +3564, 3810, 0, +3691, 3943, 0, +3818, 4075, 0, +3948, 4095, 0, +2463, 0, 2491, +2464, 0, 2491, +2464, 0, 2490, +2465, 0, 2490, +2466, 0, 2489, +2468, 0, 2489, +2470, 0, 2488, +2473, 0, 2487, +2476, 0, 2486, +2481, 0, 2484, +2481, 0, 2475, +2478, 0, 2460, +2473, 0, 2438, +2467, 477, 2407, +2459, 1401, 2362, +2447, 1751, 2293, +2447, 1751, 2152, +2447, 1751, 1850, +2447, 2135, 1751, +2591, 2466, 1533, +2731, 2705, 738, +2834, 2870, 0, +2920, 3006, 0, +3015, 3142, 0, +3117, 3276, 0, +3225, 3410, 0, +3339, 3544, 0, +3456, 3677, 0, +3577, 3810, 0, +3701, 3943, 0, +3826, 4075, 0, +3953, 4095, 0, +2623, 0, 2590, +2623, 0, 2590, +2623, 0, 2589, +2622, 0, 2588, +2622, 0, 2586, +2621, 0, 2584, +2621, 0, 2581, +2620, 0, 2577, +2619, 0, 2572, +2618, 0, 2565, +2616, 0, 2555, +2613, 0, 2542, +2610, 0, 2524, +2605, 0, 2498, +2599, 611, 2462, +2591, 1533, 2408, +2591, 1533, 2303, +2591, 1533, 2108, +2591, 1533, 1533, +2591, 2206, 1533, +2731, 2570, 738, +2870, 2820, 0, +2988, 3006, 0, +3071, 3142, 0, +3162, 3276, 0, +3261, 3410, 0, +3367, 3544, 0, +3478, 3677, 0, +3594, 3810, 0, +3713, 3943, 0, +3836, 4075, 0, +3961, 4095, 0, +2755, 0, 2673, +2755, 0, 2673, +2755, 0, 2672, +2755, 0, 2671, +2755, 0, 2670, +2754, 0, 2668, +2754, 0, 2666, +2753, 0, 2662, +2752, 0, 2658, +2751, 0, 2652, +2750, 0, 2645, +2748, 0, 2634, +2746, 0, 2619, +2742, 0, 2598, +2738, 0, 2569, +2731, 738, 2527, +2731, 738, 2448, +2731, 738, 2315, +2731, 738, 2040, +2731, 1362, 738, +2731, 2285, 738, +2870, 2678, 0, +3006, 2939, 0, +3136, 3142, 0, +3216, 3276, 0, +3305, 3410, 0, +3402, 3544, 0, +3506, 3677, 0, +3616, 3810, 0, +3730, 3943, 0, +3849, 4075, 0, +3971, 4095, 0, +2887, 0, 2765, +2887, 0, 2764, +2887, 0, 2764, +2887, 0, 2763, +2887, 0, 2762, +2887, 0, 2761, +2886, 0, 2759, +2886, 0, 2756, +2885, 0, 2752, +2885, 0, 2748, +2883, 0, 2741, +2882, 0, 2733, +2880, 0, 2721, +2878, 0, 2704, +2874, 0, 2681, +2870, 0, 2649, +2870, 0, 2590, +2870, 0, 2497, +2870, 0, 2332, +2870, 0, 1932, +2870, 963, 0, +2870, 2374, 0, +3006, 2792, 0, +3142, 3061, 0, +3276, 3273, 0, +3358, 3410, 0, +3445, 3544, 0, +3540, 3677, 0, +3643, 3810, 0, +3752, 3943, 0, +3865, 4075, 0, +3983, 4095, 0, +3019, 0, 2864, +3019, 0, 2863, +3019, 0, 2863, +3019, 0, 2863, +3019, 0, 2862, +3019, 0, 2860, +3018, 0, 2859, +3018, 0, 2857, +3018, 0, 2854, +3017, 0, 2850, +3016, 0, 2845, +3015, 0, 2838, +3014, 0, 2829, +3012, 0, 2816, +3010, 0, 2798, +3006, 0, 2773, +3006, 0, 2729, +3006, 0, 2662, +3006, 0, 2554, +3006, 0, 2352, +3006, 0, 1723, +3006, 0, 0, +3006, 2470, 0, +3142, 2911, 0, +3276, 3185, 0, +3410, 3401, 0, +3497, 3544, 0, +3583, 3677, 0, +3677, 3810, 0, +3779, 3943, 0, +3887, 4075, 0, +4000, 4095, 0, +3152, 0, 2970, +3152, 0, 2970, +3152, 0, 2969, +3151, 0, 2969, +3151, 0, 2968, +3151, 0, 2967, +3151, 0, 2966, +3151, 0, 2964, +3151, 0, 2962, +3150, 0, 2959, +3150, 0, 2955, +3149, 0, 2950, +3148, 0, 2942, +3146, 0, 2932, +3144, 0, 2919, +3142, 0, 2900, +3142, 0, 2867, +3142, 0, 2818, +3142, 0, 2744, +3142, 0, 2622, +3142, 0, 2379, +3142, 0, 1068, +3142, 0, 0, +3142, 2573, 0, +3276, 3032, 0, +3410, 3311, 0, +3544, 3529, 0, +3634, 3677, 0, +3719, 3810, 0, +3813, 3943, 0, +3913, 4075, 0, +4021, 4095, 0, +3284, 0, 3081, +3283, 0, 3081, +3283, 0, 3081, +3283, 0, 3080, +3283, 0, 3080, +3283, 0, 3079, +3283, 0, 3078, +3283, 0, 3077, +3283, 0, 3075, +3282, 0, 3073, +3282, 0, 3070, +3281, 0, 3065, +3280, 0, 3060, +3280, 0, 3052, +3278, 0, 3041, +3276, 0, 3027, +3276, 0, 3002, +3276, 0, 2967, +3276, 0, 2915, +3276, 0, 2834, +3276, 0, 2698, +3276, 0, 2411, +3276, 0, 0, +3276, 0, 0, +3276, 2683, 0, +3410, 3156, 0, +3544, 3440, 0, +3677, 3659, 0, +3770, 3810, 0, +3854, 3943, 0, +3947, 4075, 0, +4048, 4095, 0, +3416, 0, 3197, +3416, 0, 3197, +3416, 0, 3197, +3416, 0, 3196, +3416, 0, 3196, +3416, 0, 3196, +3415, 0, 3195, +3415, 0, 3194, +3415, 0, 3192, +3415, 0, 3191, +3414, 0, 3188, +3414, 0, 3185, +3414, 0, 3181, +3413, 0, 3175, +3412, 0, 3167, +3410, 0, 3156, +3410, 0, 3137, +3410, 0, 3111, +3410, 0, 3074, +3410, 0, 3019, +3410, 0, 2933, +3410, 0, 2784, +3410, 0, 2453, +3410, 0, 0, +3410, 0, 0, +3410, 2797, 0, +3544, 3282, 0, +3677, 3568, 0, +3810, 3789, 0, +3905, 3943, 0, +3989, 4075, 0, +4082, 4095, 0, +3548, 0, 3317, +3548, 0, 3317, +3548, 0, 3317, +3548, 0, 3316, +3548, 0, 3316, +3548, 0, 3316, +3548, 0, 3315, +3548, 0, 3314, +3548, 0, 3313, +3547, 0, 3312, +3547, 0, 3310, +3547, 0, 3307, +3546, 0, 3304, +3546, 0, 3300, +3545, 0, 3294, +3544, 0, 3285, +3544, 0, 3272, +3544, 0, 3253, +3544, 0, 3225, +3544, 0, 3186, +3544, 0, 3129, +3544, 0, 3038, +3544, 0, 2879, +3544, 0, 2502, +3544, 0, 0, +3544, 0, 0, +3544, 2916, 0, +3677, 3410, 0, +3810, 3698, 0, +3943, 3920, 0, +4039, 4075, 0, +4095, 4095, 0, +3680, 0, 3440, +3680, 0, 3439, +3680, 0, 3439, +3680, 0, 3439, +3680, 0, 3439, +3680, 0, 3438, +3680, 0, 3438, +3680, 0, 3437, +3680, 0, 3437, +3680, 0, 3436, +3679, 0, 3434, +3679, 0, 3432, +3679, 0, 3430, +3678, 0, 3426, +3678, 0, 3422, +3677, 0, 3416, +3677, 0, 3405, +3677, 0, 3391, +3677, 0, 3371, +3677, 0, 3344, +3677, 0, 3303, +3677, 0, 3243, +3677, 0, 3149, +3677, 0, 2980, +3677, 0, 2562, +3677, 0, 0, +3677, 0, 0, +3677, 3037, 0, +3810, 3538, 0, +3943, 3828, 0, +4075, 4050, 0, +4095, 4095, 0, +3812, 0, 3564, +3812, 0, 3564, +3812, 0, 3564, +3812, 0, 3564, +3812, 0, 3564, +3812, 0, 3564, +3812, 0, 3563, +3812, 0, 3563, +3812, 0, 3562, +3812, 0, 3562, +3812, 0, 3561, +3812, 0, 3559, +3811, 0, 3557, +3811, 0, 3554, +3810, 0, 3551, +3810, 0, 3547, +3810, 0, 3539, +3810, 0, 3528, +3810, 0, 3514, +3810, 0, 3493, +3810, 0, 3465, +3810, 0, 3424, +3810, 0, 3362, +3810, 0, 3264, +3810, 0, 3088, +3810, 0, 2631, +3810, 0, 0, +3810, 0, 0, +3810, 3161, 0, +3943, 3667, 0, +4075, 3959, 0, +4095, 4095, 0, +3944, 0, 3691, +3944, 0, 3691, +3944, 0, 3691, +3944, 0, 3691, +3944, 0, 3691, +3944, 0, 3690, +3944, 0, 3690, +3944, 0, 3690, +3944, 0, 3689, +3944, 0, 3689, +3944, 0, 3688, +3944, 0, 3687, +3944, 0, 3685, +3943, 0, 3683, +3943, 0, 3681, +3943, 0, 3677, +3943, 0, 3672, +3943, 0, 3664, +3943, 0, 3653, +3943, 0, 3638, +3943, 0, 3618, +3943, 0, 3589, +3943, 0, 3547, +3943, 0, 3484, +3943, 0, 3384, +3943, 0, 3201, +3943, 0, 2708, +3943, 0, 0, +3943, 0, 0, +3943, 3287, 0, +4075, 3797, 0, +4095, 4090, 0, +4076, 0, 3819, +4076, 0, 3819, +4076, 0, 3819, +4076, 0, 3818, +4076, 0, 3818, +4076, 0, 3818, +4076, 0, 3818, +4076, 0, 3818, +4076, 0, 3818, +4076, 0, 3817, +4076, 0, 3816, +4076, 0, 3816, +4076, 0, 3814, +4076, 0, 3813, +4075, 0, 3811, +4075, 0, 3809, +4075, 0, 3804, +4075, 0, 3798, +4075, 0, 3790, +4075, 0, 3780, +4075, 0, 3765, +4075, 0, 3744, +4075, 0, 3714, +4075, 0, 3672, +4075, 0, 3608, +4075, 0, 3505, +4075, 0, 3318, +4075, 0, 2793, +4075, 0, 0, +4075, 0, 0, +4075, 3415, 0, +4095, 3929, 0, +4095, 0, 3948, +4095, 0, 3948, +4095, 0, 3948, +4095, 0, 3948, +4095, 0, 3948, +4095, 0, 3948, +4095, 0, 3947, +4095, 0, 3947, +4095, 0, 3947, +4095, 0, 3947, +4095, 0, 3946, +4095, 0, 3946, +4095, 0, 3945, +4095, 0, 3944, +4095, 0, 3942, +4095, 0, 3940, +4095, 0, 3937, +4095, 0, 3933, +4095, 0, 3927, +4095, 0, 3919, +4095, 0, 3908, +4095, 0, 3893, +4095, 0, 3872, +4095, 0, 3842, +4095, 0, 3799, +4095, 0, 3735, +4095, 0, 3630, +4095, 0, 3439, +4095, 0, 2890, +4095, 0, 0, +4095, 0, 0, +4095, 3544, 0, +0, 1959, 2226, +0, 1962, 2226, +0, 1966, 2226, +0, 1972, 2226, +0, 1979, 2226, +0, 1989, 2226, +0, 2002, 2226, +0, 2018, 2226, +0, 2039, 2226, +0, 2066, 2226, +0, 2100, 2226, +0, 2141, 2226, +0, 2191, 2226, +0, 2226, 2200, +0, 2226, 2108, +0, 2226, 1946, +0, 2226, 1562, +0, 2358, 0, +0, 2491, 0, +1232, 2623, 0, +1962, 2755, 0, +2292, 2887, 0, +2530, 3019, 0, +2729, 3152, 0, +2904, 3284, 0, +3067, 3416, 0, +3220, 3548, 0, +3367, 3680, 0, +3511, 3812, 0, +3651, 3944, 0, +3789, 4076, 0, +3926, 4095, 0, +0, 1956, 2226, +0, 1959, 2226, +0, 1963, 2226, +0, 1969, 2226, +0, 1977, 2226, +0, 1987, 2226, +0, 1999, 2226, +0, 2016, 2226, +0, 2037, 2226, +0, 2064, 2226, +0, 2098, 2226, +0, 2140, 2226, +0, 2190, 2226, +0, 2226, 2201, +0, 2226, 2109, +0, 2226, 1948, +0, 2226, 1565, +0, 2358, 0, +0, 2491, 0, +1251, 2623, 0, +1966, 2755, 0, +2294, 2887, 0, +2531, 3019, 0, +2729, 3152, 0, +2905, 3283, 0, +3067, 3416, 0, +3220, 3548, 0, +3368, 3680, 0, +3511, 3812, 0, +3651, 3944, 0, +3789, 4076, 0, +3926, 4095, 0, +0, 1951, 2226, +0, 1955, 2226, +0, 1960, 2225, +0, 1966, 2225, +0, 1973, 2225, +0, 1983, 2225, +0, 1996, 2225, +0, 2013, 2225, +0, 2034, 2225, +0, 2061, 2225, +0, 2095, 2225, +0, 2137, 2225, +0, 2188, 2225, +0, 2225, 2202, +0, 2225, 2111, +0, 2225, 1950, +0, 2225, 1570, +0, 2358, 0, +0, 2490, 0, +1275, 2623, 0, +1971, 2755, 0, +2296, 2887, 0, +2533, 3019, 0, +2730, 3152, 0, +2905, 3283, 0, +3067, 3416, 0, +3221, 3548, 0, +3368, 3680, 0, +3511, 3812, 0, +3651, 3944, 0, +3789, 4076, 0, +3926, 4095, 0, +0, 1945, 2226, +0, 1949, 2226, +0, 1954, 2225, +0, 1961, 2225, +0, 1969, 2225, +0, 1979, 2225, +0, 1992, 2225, +0, 2009, 2225, +0, 2030, 2225, +0, 2058, 2225, +0, 2092, 2225, +0, 2134, 2225, +0, 2185, 2225, +0, 2225, 2203, +0, 2225, 2112, +0, 2225, 1953, +0, 2225, 1576, +0, 2357, 0, +0, 2490, 0, +1304, 2622, 0, +1977, 2755, 0, +2299, 2887, 0, +2535, 3019, 0, +2732, 3151, 0, +2906, 3283, 0, +3068, 3416, 0, +3221, 3548, 0, +3368, 3680, 0, +3511, 3812, 0, +3651, 3944, 0, +3789, 4076, 0, +3926, 4095, 0, +0, 1937, 2226, +0, 1941, 2226, +0, 1946, 2225, +0, 1953, 2225, +0, 1963, 2224, +0, 1973, 2224, +0, 1986, 2224, +0, 2003, 2224, +0, 2025, 2224, +0, 2053, 2224, +0, 2087, 2224, +0, 2130, 2224, +0, 2181, 2224, +0, 2224, 2206, +0, 2224, 2115, +0, 2224, 1956, +0, 2224, 1584, +0, 2357, 0, +0, 2489, 0, +1342, 2622, 0, +1986, 2755, 0, +2304, 2887, 0, +2537, 3019, 0, +2733, 3151, 0, +2907, 3283, 0, +3069, 3416, 0, +3222, 3548, 0, +3369, 3680, 0, +3511, 3812, 0, +3652, 3944, 0, +3790, 4076, 0, +3926, 4095, 0, +0, 1926, 2226, +0, 1930, 2226, +0, 1936, 2225, +0, 1943, 2225, +0, 1952, 2224, +0, 1965, 2223, +0, 1978, 2223, +0, 1995, 2223, +0, 2018, 2223, +0, 2046, 2223, +0, 2081, 2223, +0, 2124, 2223, +0, 2176, 2223, +0, 2223, 2208, +0, 2223, 2118, +0, 2223, 1961, +0, 2223, 1595, +0, 2356, 0, +0, 2489, 0, +1387, 2621, 0, +1997, 2754, 0, +2310, 2887, 0, +2541, 3019, 0, +2735, 3151, 0, +2909, 3283, 0, +3070, 3416, 0, +3222, 3548, 0, +3369, 3680, 0, +3512, 3812, 0, +3652, 3944, 0, +3790, 4076, 0, +3926, 4095, 0, +0, 1911, 2226, +0, 1915, 2226, +0, 1921, 2225, +0, 1928, 2225, +0, 1938, 2224, +0, 1951, 2223, +0, 1967, 2221, +0, 1985, 2221, +0, 2008, 2221, +0, 2036, 2221, +0, 2072, 2221, +0, 2116, 2221, +0, 2169, 2221, +0, 2221, 2212, +0, 2221, 2123, +0, 2221, 1967, +0, 2221, 1608, +0, 2355, 0, +0, 2488, 0, +1441, 2621, 0, +2012, 2754, 0, +2317, 2886, 0, +2545, 3018, 0, +2738, 3151, 0, +2911, 3283, 0, +3071, 3415, 0, +3223, 3548, 0, +3370, 3680, 0, +3513, 3812, 0, +3652, 3944, 0, +3790, 4076, 0, +3927, 4095, 0, +0, 1890, 2226, +0, 1894, 2226, +0, 1900, 2225, +0, 1908, 2225, +0, 1918, 2224, +0, 1931, 2223, +0, 1948, 2221, +0, 1970, 2220, +0, 1994, 2220, +0, 2023, 2220, +0, 2060, 2220, +0, 2105, 2220, +0, 2159, 2220, +0, 2220, 2217, +0, 2220, 2128, +0, 2220, 1975, +0, 2220, 1626, +0, 2353, 0, +0, 2487, 0, +1505, 2620, 0, +2031, 2753, 0, +2327, 2886, 0, +2551, 3018, 0, +2742, 3151, 0, +2914, 3283, 0, +3073, 3415, 0, +3225, 3548, 0, +3371, 3680, 0, +3513, 3812, 0, +3653, 3944, 0, +3790, 4076, 0, +3927, 4095, 0, +0, 1860, 2226, +0, 1865, 2226, +0, 1871, 2225, +0, 1880, 2225, +0, 1891, 2224, +0, 1904, 2223, +0, 1922, 2221, +0, 1946, 2220, +0, 1975, 2217, +0, 2006, 2217, +0, 2044, 2217, +0, 2090, 2217, +0, 2146, 2217, +0, 2211, 2217, +0, 2217, 2136, +0, 2217, 1986, +0, 2217, 1649, +0, 2352, 0, +0, 2486, 0, +1578, 2619, 0, +2056, 2752, 0, +2340, 2885, 0, +2559, 3018, 0, +2747, 3151, 0, +2917, 3283, 0, +3076, 3415, 0, +3226, 3548, 0, +3372, 3680, 0, +3514, 3812, 0, +3653, 3944, 0, +3791, 4076, 0, +3927, 4095, 0, +0, 1817, 2226, +0, 1823, 2226, +0, 1829, 2225, +0, 1839, 2225, +0, 1850, 2224, +0, 1865, 2223, +0, 1885, 2221, +0, 1910, 2220, +0, 1942, 2217, +0, 1981, 2214, +0, 2021, 2214, +0, 2070, 2214, +0, 2128, 2214, +0, 2195, 2214, +0, 2214, 2146, +0, 2214, 2000, +0, 2214, 1677, +0, 2349, 0, +0, 2484, 0, +1661, 2618, 0, +2086, 2751, 0, +2356, 2885, 0, +2570, 3017, 0, +2754, 3150, 0, +2922, 3282, 0, +3079, 3415, 0, +3229, 3547, 0, +3374, 3680, 0, +3515, 3812, 0, +3654, 3944, 0, +3791, 4076, 0, +3927, 4095, 0, +0, 1753, 2226, +0, 1759, 2226, +0, 1767, 2225, +0, 1777, 2225, +0, 1790, 2224, +0, 1808, 2223, +0, 1830, 2221, +0, 1858, 2220, +0, 1894, 2217, +0, 1936, 2214, +0, 1988, 2209, +0, 2041, 2209, +0, 2102, 2209, +0, 2174, 2209, +0, 2209, 2159, +0, 2209, 2018, +0, 2209, 1713, +0, 2346, 0, +415, 2481, 0, +1752, 2616, 0, +2124, 2750, 0, +2378, 2883, 0, +2583, 3016, 0, +2763, 3150, 0, +2928, 3282, 0, +3083, 3414, 0, +3232, 3547, 0, +3376, 3679, 0, +3517, 3812, 0, +3656, 3944, 0, +3793, 4076, 0, +3928, 4095, 0, +0, 1648, 2226, +0, 1656, 2226, +0, 1666, 2225, +0, 1679, 2225, +0, 1695, 2224, +0, 1717, 2223, +0, 1744, 2221, +0, 1778, 2220, +0, 1819, 2217, +0, 1870, 2214, +0, 1929, 2209, +217, 1998, 2203, +217, 2066, 2203, +217, 2142, 2203, +217, 2203, 2176, +217, 2203, 2041, +217, 2203, 1757, +0, 2341, 437, +1199, 2478, 0, +1851, 2613, 0, +2170, 2748, 0, +2405, 2882, 0, +2600, 3015, 0, +2775, 3149, 0, +2936, 3281, 0, +3089, 3414, 0, +3236, 3547, 0, +3379, 3679, 0, +3520, 3812, 0, +3657, 3944, 0, +3794, 4076, 0, +3929, 4095, 0, +0, 1457, 2226, +0, 1469, 2226, +0, 1484, 2225, +0, 1503, 2225, +0, 1527, 2224, +0, 1557, 2223, +0, 1596, 2221, +0, 1642, 2220, +0, 1697, 2217, +0, 1762, 2214, +0, 1836, 2209, +217, 1920, 2203, +1136, 2012, 2194, +1136, 2097, 2194, +1136, 2191, 2194, +1136, 2194, 2069, +1136, 2194, 1809, +345, 2335, 970, +1535, 2473, 0, +1956, 2610, 0, +2226, 2746, 0, +2439, 2880, 0, +2623, 3014, 0, +2790, 3148, 0, +2947, 3280, 0, +3097, 3414, 0, +3242, 3546, 0, +3384, 3679, 0, +3522, 3811, 0, +3659, 3944, 0, +3795, 4076, 0, +3930, 4095, 0, +0, 907, 2226, +0, 944, 2226, +0, 990, 2225, +0, 1044, 2225, +0, 1108, 2224, +0, 1181, 2223, +0, 1264, 2221, +0, 1355, 2220, +0, 1454, 2217, +0, 1560, 2214, +0, 1671, 2209, +217, 1787, 2203, +1136, 1906, 2194, +1487, 2029, 2183, +1487, 2136, 2183, +1487, 2183, 2105, +1487, 2183, 1871, +1270, 2326, 1269, +1776, 2467, 477, +2067, 2605, 0, +2291, 2742, 0, +2480, 2878, 0, +2651, 3012, 0, +2810, 3146, 0, +2961, 3280, 0, +3107, 3413, 0, +3249, 3546, 0, +3389, 3678, 0, +3526, 3811, 0, +3662, 3943, 0, +3798, 4076, 0, +3932, 4095, 0, +0, 0, 2226, +0, 0, 2226, +0, 0, 2225, +0, 0, 2225, +0, 0, 2224, +0, 0, 2223, +0, 0, 2221, +0, 0, 2220, +0, 140, 2217, +0, 932, 2214, +0, 1270, 2209, +217, 1512, 2203, +1136, 1711, 2194, +1487, 1888, 2183, +1733, 2051, 2167, +1733, 2167, 2149, +1733, 2167, 1943, +1718, 2315, 1619, +1976, 2459, 1401, +2183, 2599, 611, +2365, 2738, 0, +2530, 2874, 0, +2686, 3010, 0, +2835, 3144, 0, +2979, 3278, 0, +3120, 3412, 0, +3259, 3545, 0, +3396, 3678, 0, +3532, 3810, 0, +3666, 3943, 0, +3801, 4075, 0, +3934, 4095, 0, +0, 0, 2226, +0, 0, 2226, +0, 0, 2225, +0, 0, 2225, +0, 0, 2224, +0, 0, 2223, +0, 0, 2221, +0, 0, 2220, +0, 0, 2217, +0, 0, 2214, +303, 0, 2209, +838, 217, 2203, +1136, 1137, 2194, +1487, 1585, 2183, +1733, 1862, 2167, +1935, 2078, 2145, +1935, 2145, 2023, +1994, 2299, 1865, +2152, 2447, 1751, +2303, 2591, 1533, +2448, 2731, 738, +2590, 2870, 0, +2729, 3006, 0, +2867, 3142, 0, +3002, 3276, 0, +3137, 3410, 0, +3272, 3544, 0, +3405, 3677, 0, +3539, 3810, 0, +3672, 3943, 0, +3804, 4075, 0, +3937, 4095, 0, +1562, 0, 2226, +1565, 0, 2226, +1570, 0, 2225, +1576, 0, 2225, +1584, 0, 2224, +1595, 0, 2223, +1608, 0, 2221, +1626, 0, 2220, +1649, 0, 2217, +1677, 0, 2214, +1713, 0, 2209, +1757, 217, 2203, +1809, 1136, 2194, +1871, 1487, 2183, +1943, 1733, 2167, +2023, 1935, 2145, +2113, 2113, 2113, +2210, 2277, 2067, +2315, 2431, 1997, +2425, 2579, 1883, +2540, 2723, 1664, +2659, 2863, 870, +2781, 3002, 0, +2906, 3138, 0, +3031, 3274, 0, +3159, 3408, 0, +3288, 3543, 0, +3418, 3676, 0, +3548, 3809, 0, +3679, 3942, 0, +3810, 4075, 0, +3941, 4095, 0, +2078, 0, 2358, +2079, 0, 2358, +2080, 0, 2358, +2082, 0, 2357, +2085, 0, 2357, +2088, 0, 2356, +2093, 0, 2355, +2099, 0, 2353, +2107, 0, 2352, +2118, 0, 2349, +2132, 0, 2346, +2150, 0, 2341, +2173, 345, 2335, +2202, 1269, 2326, +2237, 1619, 2315, +2281, 1865, 2299, +2277, 2067, 2210, +2277, 2155, 2067, +2431, 2414, 1997, +2533, 2579, 1883, +2626, 2723, 1664, +2726, 2863, 870, +2833, 3002, 0, +2946, 3138, 0, +3062, 3274, 0, +3183, 3408, 0, +3306, 3543, 0, +3431, 3676, 0, +3558, 3809, 0, +3686, 3942, 0, +3815, 4075, 0, +3945, 4095, 0, +2371, 0, 2491, +2372, 0, 2491, +2373, 0, 2490, +2374, 0, 2490, +2375, 0, 2489, +2377, 0, 2489, +2379, 0, 2488, +2383, 0, 2487, +2387, 0, 2486, +2393, 0, 2484, +2401, 0, 2481, +2411, 0, 2478, +2423, 0, 2473, +2440, 477, 2467, +2459, 1401, 2455, +2447, 1751, 2401, +2431, 1997, 2315, +2431, 1997, 2126, +2431, 2207, 1997, +2579, 2502, 1883, +2719, 2723, 1664, +2803, 2863, 870, +2895, 3002, 0, +2995, 3138, 0, +3100, 3274, 0, +3212, 3408, 0, +3329, 3543, 0, +3448, 3676, 0, +3571, 3809, 0, +3696, 3942, 0, +3823, 4075, 0, +3951, 4095, 0, +2595, 0, 2623, +2595, 0, 2623, +2596, 0, 2623, +2596, 0, 2622, +2597, 0, 2622, +2598, 0, 2621, +2600, 0, 2621, +2602, 0, 2620, +2604, 0, 2619, +2608, 0, 2618, +2613, 0, 2616, +2613, 0, 2607, +2610, 0, 2592, +2605, 0, 2570, +2599, 611, 2538, +2591, 1533, 2493, +2579, 1883, 2425, +2579, 1883, 2284, +2579, 1883, 1981, +2579, 2267, 1883, +2723, 2598, 1664, +2863, 2837, 870, +2966, 3002, 0, +3053, 3138, 0, +3147, 3274, 0, +3249, 3408, 0, +3357, 3543, 0, +3471, 3676, 0, +3588, 3809, 0, +3709, 3942, 0, +3833, 4075, 0, +3959, 4095, 0, +2755, 0, 2723, +2755, 0, 2723, +2755, 0, 2722, +2755, 0, 2721, +2755, 0, 2720, +2754, 0, 2718, +2754, 0, 2716, +2753, 0, 2713, +2752, 0, 2710, +2751, 0, 2704, +2750, 0, 2697, +2748, 0, 2687, +2746, 0, 2674, +2742, 0, 2656, +2738, 0, 2631, +2731, 738, 2594, +2723, 1664, 2540, +2723, 1664, 2435, +2723, 1664, 2240, +2723, 1664, 1667, +2723, 2338, 1664, +2863, 2701, 870, +3002, 2952, 0, +3120, 3138, 0, +3203, 3274, 0, +3294, 3408, 0, +3393, 3543, 0, +3499, 3676, 0, +3610, 3809, 0, +3726, 3942, 0, +3846, 4075, 0, +3968, 4095, 0, +2887, 0, 2806, +2887, 0, 2805, +2887, 0, 2805, +2887, 0, 2804, +2887, 0, 2803, +2887, 0, 2802, +2886, 0, 2800, +2886, 0, 2798, +2885, 0, 2795, +2885, 0, 2790, +2883, 0, 2784, +2882, 0, 2777, +2880, 0, 2766, +2878, 0, 2751, +2874, 0, 2730, +2870, 0, 2701, +2863, 870, 2659, +2863, 870, 2580, +2863, 870, 2447, +2863, 870, 2173, +2863, 1498, 870, +2863, 2417, 870, +3002, 2810, 0, +3138, 3071, 0, +3268, 3274, 0, +3348, 3408, 0, +3437, 3543, 0, +3534, 3676, 0, +3638, 3809, 0, +3748, 3942, 0, +3862, 4075, 0, +3981, 4095, 0, +3019, 0, 2897, +3019, 0, 2897, +3019, 0, 2896, +3019, 0, 2896, +3019, 0, 2895, +3019, 0, 2894, +3018, 0, 2892, +3018, 0, 2890, +3018, 0, 2888, +3017, 0, 2885, +3016, 0, 2880, +3015, 0, 2873, +3014, 0, 2865, +3012, 0, 2853, +3010, 0, 2836, +3006, 0, 2813, +3002, 0, 2781, +3002, 0, 2722, +3002, 0, 2628, +3002, 0, 2463, +3002, 0, 2062, +3002, 1109, 0, +3002, 2505, 0, +3138, 2925, 0, +3274, 3193, 0, +3408, 3406, 0, +3490, 3543, 0, +3577, 3676, 0, +3672, 3809, 0, +3775, 3942, 0, +3884, 4075, 0, +3998, 4095, 0, +3152, 0, 2996, +3152, 0, 2996, +3152, 0, 2996, +3151, 0, 2995, +3151, 0, 2995, +3151, 0, 2994, +3151, 0, 2993, +3151, 0, 2991, +3151, 0, 2989, +3150, 0, 2986, +3150, 0, 2982, +3149, 0, 2977, +3148, 0, 2970, +3146, 0, 2961, +3144, 0, 2948, +3142, 0, 2931, +3138, 0, 2906, +3138, 0, 2861, +3138, 0, 2795, +3138, 0, 2687, +3138, 0, 2484, +3138, 0, 1857, +3138, 0, 0, +3138, 2602, 0, +3274, 3042, 0, +3408, 3317, 0, +3543, 3533, 0, +3629, 3676, 0, +3715, 3809, 0, +3809, 3942, 0, +3911, 4075, 0, +4019, 4095, 0, +3284, 0, 3102, +3283, 0, 3102, +3283, 0, 3101, +3283, 0, 3101, +3283, 0, 3101, +3283, 0, 3100, +3283, 0, 3099, +3283, 0, 3098, +3283, 0, 3096, +3282, 0, 3094, +3282, 0, 3091, +3281, 0, 3087, +3280, 0, 3082, +3280, 0, 3074, +3278, 0, 3064, +3276, 0, 3050, +3274, 0, 3031, +3274, 0, 2998, +3274, 0, 2950, +3274, 0, 2876, +3274, 0, 2753, +3274, 0, 2510, +3274, 0, 1202, +3274, 0, 0, +3274, 2706, 0, +3408, 3164, 0, +3543, 3444, 0, +3676, 3662, 0, +3766, 3809, 0, +3851, 3942, 0, +3945, 4075, 0, +4046, 4095, 0, +3416, 0, 3213, +3416, 0, 3213, +3416, 0, 3213, +3416, 0, 3213, +3416, 0, 3212, +3416, 0, 3212, +3415, 0, 3211, +3415, 0, 3210, +3415, 0, 3209, +3415, 0, 3207, +3414, 0, 3205, +3414, 0, 3202, +3414, 0, 3198, +3413, 0, 3192, +3412, 0, 3184, +3410, 0, 3174, +3408, 0, 3159, +3408, 0, 3134, +3408, 0, 3099, +3408, 0, 3047, +3408, 0, 2966, +3408, 0, 2830, +3408, 0, 2545, +3408, 0, 0, +3408, 0, 0, +3408, 2815, 0, +3543, 3288, 0, +3676, 3572, 0, +3809, 3791, 0, +3902, 3942, 0, +3986, 4075, 0, +4080, 4095, 0, +3548, 0, 3329, +3548, 0, 3329, +3548, 0, 3329, +3548, 0, 3329, +3548, 0, 3329, +3548, 0, 3328, +3548, 0, 3328, +3548, 0, 3327, +3548, 0, 3326, +3547, 0, 3325, +3547, 0, 3323, +3547, 0, 3320, +3546, 0, 3317, +3546, 0, 3313, +3545, 0, 3307, +3544, 0, 3299, +3543, 0, 3288, +3543, 0, 3270, +3543, 0, 3243, +3543, 0, 3206, +3543, 0, 3151, +3543, 0, 3065, +3543, 0, 2917, +3543, 0, 2585, +3543, 0, 0, +3543, 0, 0, +3543, 2929, 0, +3676, 3414, 0, +3809, 3700, 0, +3942, 3921, 0, +4037, 4075, 0, +4095, 4095, 0, +3680, 0, 3449, +3680, 0, 3449, +3680, 0, 3449, +3680, 0, 3449, +3680, 0, 3448, +3680, 0, 3448, +3680, 0, 3448, +3680, 0, 3447, +3680, 0, 3446, +3680, 0, 3445, +3679, 0, 3444, +3679, 0, 3442, +3679, 0, 3440, +3678, 0, 3436, +3678, 0, 3432, +3677, 0, 3426, +3676, 0, 3418, +3676, 0, 3404, +3676, 0, 3385, +3676, 0, 3358, +3676, 0, 3319, +3676, 0, 3261, +3676, 0, 3170, +3676, 0, 3010, +3676, 0, 2636, +3676, 0, 0, +3676, 0, 0, +3676, 3048, 0, +3809, 3542, 0, +3942, 3830, 0, +4075, 4051, 0, +4095, 4095, 0, +3812, 0, 3572, +3812, 0, 3572, +3812, 0, 3572, +3812, 0, 3571, +3812, 0, 3571, +3812, 0, 3571, +3812, 0, 3571, +3812, 0, 3570, +3812, 0, 3570, +3812, 0, 3569, +3812, 0, 3568, +3812, 0, 3566, +3811, 0, 3564, +3811, 0, 3562, +3810, 0, 3559, +3810, 0, 3554, +3809, 0, 3548, +3809, 0, 3537, +3809, 0, 3523, +3809, 0, 3503, +3809, 0, 3475, +3809, 0, 3435, +3809, 0, 3376, +3809, 0, 3281, +3809, 0, 3112, +3809, 0, 2694, +3809, 0, 0, +3809, 0, 0, +3809, 3169, 0, +3942, 3670, 0, +4075, 3960, 0, +4095, 4095, 0, +3944, 0, 3696, +3944, 0, 3696, +3944, 0, 3696, +3944, 0, 3696, +3944, 0, 3696, +3944, 0, 3696, +3944, 0, 3696, +3944, 0, 3695, +3944, 0, 3695, +3944, 0, 3694, +3944, 0, 3694, +3944, 0, 3692, +3944, 0, 3691, +3943, 0, 3689, +3943, 0, 3687, +3943, 0, 3683, +3942, 0, 3679, +3942, 0, 3671, +3942, 0, 3660, +3942, 0, 3646, +3942, 0, 3626, +3942, 0, 3597, +3942, 0, 3556, +3942, 0, 3494, +3942, 0, 3396, +3942, 0, 3220, +3942, 0, 2762, +3942, 0, 0, +3942, 0, 0, +3942, 3293, 0, +4075, 3799, 0, +4095, 4091, 0, +4076, 0, 3823, +4076, 0, 3823, +4076, 0, 3823, +4076, 0, 3823, +4076, 0, 3823, +4076, 0, 3822, +4076, 0, 3822, +4076, 0, 3822, +4076, 0, 3822, +4076, 0, 3821, +4076, 0, 3821, +4076, 0, 3820, +4076, 0, 3819, +4076, 0, 3817, +4075, 0, 3816, +4075, 0, 3813, +4075, 0, 3810, +4075, 0, 3803, +4075, 0, 3796, +4075, 0, 3785, +4075, 0, 3770, +4075, 0, 3750, +4075, 0, 3721, +4075, 0, 3679, +4075, 0, 3616, +4075, 0, 3515, +4075, 0, 3333, +4075, 0, 2839, +4075, 0, 0, +4075, 0, 0, +4075, 3419, 0, +4095, 3930, 0, +4095, 0, 3951, +4095, 0, 3951, +4095, 0, 3951, +4095, 0, 3951, +4095, 0, 3951, +4095, 0, 3951, +4095, 0, 3951, +4095, 0, 3950, +4095, 0, 3950, +4095, 0, 3950, +4095, 0, 3950, +4095, 0, 3949, +4095, 0, 3948, +4095, 0, 3947, +4095, 0, 3945, +4095, 0, 3944, +4095, 0, 3941, +4095, 0, 3937, +4095, 0, 3931, +4095, 0, 3923, +4095, 0, 3912, +4095, 0, 3897, +4095, 0, 3876, +4095, 0, 3847, +4095, 0, 3804, +4095, 0, 3741, +4095, 0, 3638, +4095, 0, 3450, +4095, 0, 2927, +4095, 0, 0, +4095, 0, 0, +4095, 3547, 0, +0, 2090, 2358, +0, 2093, 2358, +0, 2096, 2358, +0, 2100, 2358, +0, 2106, 2358, +0, 2113, 2358, +0, 2123, 2358, +0, 2136, 2358, +0, 2152, 2358, +0, 2173, 2358, +0, 2200, 2358, +0, 2233, 2358, +0, 2275, 2358, +0, 2325, 2358, +0, 2358, 2332, +0, 2358, 2239, +0, 2358, 2078, +0, 2358, 1692, +0, 2491, 0, +0, 2623, 0, +1353, 2755, 0, +2091, 2887, 0, +2422, 3019, 0, +2662, 3152, 0, +2860, 3284, 0, +3036, 3416, 0, +3198, 3548, 0, +3352, 3680, 0, +3499, 3812, 0, +3643, 3944, 0, +3783, 4076, 0, +3921, 4095, 0, +0, 2088, 2358, +0, 2091, 2358, +0, 2094, 2358, +0, 2098, 2358, +0, 2104, 2358, +0, 2111, 2358, +0, 2121, 2358, +0, 2134, 2358, +0, 2150, 2358, +0, 2171, 2358, +0, 2199, 2358, +0, 2232, 2358, +0, 2273, 2358, +0, 2324, 2358, +0, 2358, 2332, +0, 2358, 2240, +0, 2358, 2079, +0, 2358, 1694, +0, 2491, 0, +0, 2623, 0, +1367, 2755, 0, +2094, 2887, 0, +2424, 3019, 0, +2663, 3152, 0, +2860, 3283, 0, +3036, 3416, 0, +3199, 3548, 0, +3352, 3680, 0, +3499, 3812, 0, +3643, 3944, 0, +3783, 4076, 0, +3921, 4095, 0, +0, 2085, 2358, +0, 2087, 2358, +0, 2091, 2358, +0, 2096, 2358, +0, 2101, 2358, +0, 2109, 2358, +0, 2119, 2358, +0, 2132, 2358, +0, 2148, 2358, +0, 2169, 2358, +0, 2196, 2358, +0, 2230, 2358, +0, 2271, 2358, +0, 2322, 2358, +0, 2358, 2333, +0, 2358, 2241, +0, 2358, 2080, +0, 2358, 1698, +0, 2490, 0, +0, 2623, 0, +1386, 2755, 0, +2098, 2887, 0, +2426, 3019, 0, +2664, 3152, 0, +2861, 3283, 0, +3037, 3416, 0, +3199, 3548, 0, +3353, 3680, 0, +3500, 3812, 0, +3643, 3944, 0, +3783, 4076, 0, +3921, 4095, 0, +0, 2080, 2358, +0, 2083, 2358, +0, 2087, 2358, +0, 2092, 2357, +0, 2098, 2357, +0, 2105, 2357, +0, 2115, 2357, +0, 2128, 2357, +0, 2145, 2357, +0, 2166, 2357, +0, 2193, 2357, +0, 2228, 2357, +0, 2269, 2357, +0, 2320, 2357, +0, 2357, 2334, +0, 2357, 2243, +0, 2357, 2082, +0, 2357, 1702, +0, 2490, 0, +0, 2622, 0, +1409, 2755, 0, +2103, 2887, 0, +2428, 3019, 0, +2665, 3151, 0, +2862, 3283, 0, +3038, 3416, 0, +3200, 3548, 0, +3353, 3680, 0, +3500, 3812, 0, +3643, 3944, 0, +3783, 4076, 0, +3921, 4095, 0, +0, 2074, 2358, +0, 2077, 2358, +0, 2081, 2358, +0, 2086, 2357, +0, 2093, 2357, +0, 2101, 2357, +0, 2111, 2357, +0, 2124, 2357, +0, 2141, 2357, +0, 2162, 2357, +0, 2190, 2357, +0, 2224, 2357, +0, 2266, 2357, +0, 2317, 2357, +0, 2357, 2335, +0, 2357, 2245, +0, 2357, 2085, +0, 2357, 1708, +0, 2489, 0, +0, 2622, 0, +1439, 2755, 0, +2110, 2887, 0, +2431, 3019, 0, +2667, 3151, 0, +2863, 3283, 0, +3038, 3416, 0, +3200, 3548, 0, +3353, 3680, 0, +3500, 3812, 0, +3643, 3944, 0, +3783, 4076, 0, +3921, 4095, 0, +0, 2066, 2358, +0, 2069, 2358, +0, 2073, 2358, +0, 2078, 2357, +0, 2086, 2357, +0, 2095, 2356, +0, 2105, 2356, +0, 2118, 2356, +0, 2135, 2356, +0, 2157, 2356, +0, 2185, 2356, +0, 2219, 2356, +0, 2262, 2356, +0, 2313, 2356, +0, 2356, 2338, +0, 2356, 2247, +0, 2356, 2088, +0, 2356, 1716, +0, 2489, 0, +0, 2621, 0, +1476, 2754, 0, +2118, 2887, 0, +2435, 3019, 0, +2670, 3151, 0, +2865, 3283, 0, +3039, 3416, 0, +3201, 3548, 0, +3354, 3680, 0, +3501, 3812, 0, +3644, 3944, 0, +3784, 4076, 0, +3922, 4095, 0, +0, 2055, 2358, +0, 2058, 2358, +0, 2062, 2358, +0, 2068, 2357, +0, 2075, 2357, +0, 2084, 2356, +0, 2096, 2355, +0, 2110, 2355, +0, 2127, 2355, +0, 2150, 2355, +0, 2178, 2355, +0, 2213, 2355, +0, 2256, 2355, +0, 2308, 2355, +0, 2355, 2340, +0, 2355, 2251, +0, 2355, 2093, +0, 2355, 1727, +0, 2488, 0, +0, 2621, 0, +1521, 2754, 0, +2129, 2886, 0, +2441, 3018, 0, +2673, 3151, 0, +2867, 3283, 0, +3041, 3415, 0, +3202, 3548, 0, +3354, 3680, 0, +3501, 3812, 0, +3644, 3944, 0, +3784, 4076, 0, +3922, 4095, 0, +0, 2040, 2358, +0, 2043, 2358, +0, 2047, 2358, +0, 2053, 2357, +0, 2060, 2357, +0, 2070, 2356, +0, 2083, 2355, +0, 2099, 2353, +0, 2117, 2353, +0, 2140, 2353, +0, 2168, 2353, +0, 2204, 2353, +0, 2248, 2353, +0, 2301, 2353, +0, 2353, 2344, +0, 2353, 2255, +0, 2353, 2099, +0, 2353, 1740, +0, 2487, 0, +0, 2620, 0, +1575, 2753, 0, +2144, 2886, 0, +2449, 3018, 0, +2678, 3151, 0, +2870, 3283, 0, +3043, 3415, 0, +3203, 3548, 0, +3356, 3680, 0, +3502, 3812, 0, +3645, 3944, 0, +3784, 4076, 0, +3922, 4095, 0, +0, 2019, 2358, +0, 2022, 2358, +0, 2027, 2358, +0, 2032, 2357, +0, 2040, 2357, +0, 2050, 2356, +0, 2063, 2355, +0, 2081, 2353, +0, 2102, 2352, +0, 2126, 2352, +0, 2155, 2352, +0, 2192, 2352, +0, 2237, 2352, +0, 2291, 2352, +0, 2352, 2349, +0, 2352, 2261, +0, 2352, 2107, +0, 2352, 1758, +0, 2486, 0, +0, 2619, 0, +1638, 2752, 0, +2163, 2885, 0, +2459, 3018, 0, +2684, 3151, 0, +2874, 3283, 0, +3046, 3415, 0, +3205, 3548, 0, +3357, 3680, 0, +3503, 3812, 0, +3645, 3944, 0, +3785, 4076, 0, +3923, 4095, 0, +0, 1989, 2358, +0, 1993, 2358, +0, 1997, 2358, +0, 2004, 2357, +0, 2012, 2357, +0, 2022, 2356, +0, 2037, 2355, +0, 2054, 2353, +0, 2078, 2352, +0, 2107, 2349, +0, 2138, 2349, +0, 2176, 2349, +0, 2223, 2349, +0, 2278, 2349, +0, 2343, 2349, +0, 2349, 2268, +0, 2349, 2118, +0, 2349, 1781, +0, 2484, 0, +0, 2618, 0, +1711, 2751, 0, +2188, 2885, 0, +2471, 3017, 0, +2691, 3150, 0, +2879, 3282, 0, +3049, 3415, 0, +3208, 3547, 0, +3359, 3680, 0, +3504, 3812, 0, +3646, 3944, 0, +3785, 4076, 0, +3923, 4095, 0, +0, 1946, 2358, +0, 1950, 2358, +0, 1955, 2358, +0, 1962, 2357, +0, 1970, 2357, +0, 1982, 2356, +0, 1998, 2355, +0, 2017, 2353, +0, 2042, 2352, +0, 2074, 2349, +0, 2113, 2346, +0, 2153, 2346, +0, 2202, 2346, +0, 2260, 2346, +0, 2328, 2346, +0, 2346, 2278, +0, 2346, 2132, +0, 2346, 1809, +0, 2481, 0, +0, 2616, 0, +1794, 2750, 0, +2218, 2883, 0, +2488, 3016, 0, +2702, 3150, 0, +2886, 3282, 0, +3054, 3414, 0, +3211, 3547, 0, +3361, 3679, 0, +3506, 3812, 0, +3648, 3944, 0, +3787, 4076, 0, +3924, 4095, 0, +0, 1880, 2358, +0, 1885, 2358, +0, 1891, 2358, +0, 1899, 2357, +0, 1909, 2357, +0, 1922, 2356, +0, 1940, 2355, +0, 1962, 2353, +0, 1990, 2352, +0, 2025, 2349, +0, 2069, 2346, +0, 2120, 2341, +0, 2173, 2341, +0, 2234, 2341, +0, 2305, 2341, +0, 2341, 2291, +0, 2341, 2150, +0, 2341, 1845, +0, 2478, 0, +547, 2613, 0, +1885, 2748, 0, +2256, 2882, 0, +2510, 3015, 0, +2715, 3149, 0, +2895, 3281, 0, +3060, 3414, 0, +3216, 3547, 0, +3364, 3679, 0, +3508, 3812, 0, +3649, 3944, 0, +3787, 4076, 0, +3925, 4095, 0, +0, 1775, 2358, +0, 1781, 2358, +0, 1788, 2358, +0, 1798, 2357, +0, 1811, 2357, +0, 1828, 2356, +0, 1849, 2355, +0, 1876, 2353, +0, 1910, 2352, +0, 1951, 2349, +0, 2002, 2346, +0, 2061, 2341, +345, 2131, 2335, +345, 2198, 2335, +345, 2274, 2335, +345, 2335, 2308, +345, 2335, 2173, +345, 2335, 1889, +0, 2473, 557, +1330, 2610, 0, +1983, 2746, 0, +2302, 2880, 0, +2536, 3014, 0, +2733, 3148, 0, +2907, 3280, 0, +3069, 3414, 0, +3221, 3546, 0, +3368, 3679, 0, +3511, 3811, 0, +3651, 3944, 0, +3789, 4076, 0, +3926, 4095, 0, +0, 1580, 2358, +0, 1589, 2358, +0, 1600, 2358, +0, 1615, 2357, +0, 1634, 2357, +0, 1659, 2356, +0, 1689, 2355, +0, 1727, 2353, +0, 1773, 2352, +0, 1829, 2349, +0, 1894, 2346, +0, 1968, 2341, +345, 2052, 2335, +1269, 2144, 2326, +1269, 2229, 2326, +1269, 2323, 2326, +1269, 2326, 2202, +1269, 2326, 1941, +477, 2467, 1099, +1667, 2605, 0, +2089, 2742, 0, +2358, 2878, 0, +2570, 3012, 0, +2755, 3146, 0, +2922, 3280, 0, +3079, 3413, 0, +3229, 3546, 0, +3374, 3678, 0, +3516, 3811, 0, +3655, 3943, 0, +3792, 4076, 0, +3927, 4095, 0, +0, 1009, 2358, +0, 1039, 2358, +0, 1076, 2358, +0, 1122, 2357, +0, 1176, 2357, +0, 1240, 2356, +0, 1313, 2355, +0, 1396, 2353, +0, 1487, 2352, +0, 1586, 2349, +0, 1692, 2346, +0, 1803, 2341, +345, 1919, 2335, +1269, 2038, 2326, +1619, 2161, 2315, +1619, 2268, 2315, +1619, 2315, 2237, +1619, 2315, 2003, +1403, 2459, 1401, +1908, 2599, 611, +2200, 2738, 0, +2423, 2874, 0, +2612, 3010, 0, +2783, 3144, 0, +2942, 3278, 0, +3093, 3412, 0, +3239, 3545, 0, +3381, 3678, 0, +3521, 3810, 0, +3659, 3943, 0, +3795, 4075, 0, +3930, 4095, 0, +0, 0, 2358, +0, 0, 2358, +0, 0, 2358, +0, 0, 2357, +0, 0, 2357, +0, 0, 2356, +0, 0, 2355, +0, 0, 2353, +0, 0, 2352, +0, 275, 2349, +0, 1064, 2346, +0, 1403, 2341, +345, 1644, 2335, +1269, 1843, 2326, +1619, 2020, 2315, +1865, 2183, 2299, +1865, 2299, 2281, +1865, 2299, 2075, +1850, 2447, 1751, +2108, 2591, 1533, +2315, 2731, 738, +2497, 2870, 0, +2662, 3006, 0, +2818, 3142, 0, +2967, 3276, 0, +3111, 3410, 0, +3253, 3544, 0, +3391, 3677, 0, +3528, 3810, 0, +3664, 3943, 0, +3798, 4075, 0, +3933, 4095, 0, +0, 0, 2358, +0, 0, 2358, +0, 0, 2358, +0, 0, 2357, +0, 0, 2357, +0, 0, 2356, +0, 0, 2355, +0, 0, 2353, +0, 0, 2352, +0, 0, 2349, +0, 0, 2346, +437, 0, 2341, +970, 345, 2335, +1269, 1270, 2326, +1619, 1718, 2315, +1865, 1994, 2299, +2067, 2210, 2277, +2067, 2277, 2155, +2126, 2431, 1997, +2284, 2579, 1883, +2435, 2723, 1664, +2580, 2863, 870, +2722, 3002, 0, +2861, 3138, 0, +2998, 3274, 0, +3134, 3408, 0, +3270, 3543, 0, +3404, 3676, 0, +3537, 3809, 0, +3671, 3942, 0, +3803, 4075, 0, +3937, 4095, 0, +1692, 0, 2358, +1694, 0, 2358, +1698, 0, 2358, +1702, 0, 2357, +1708, 0, 2357, +1716, 0, 2356, +1727, 0, 2355, +1740, 0, 2353, +1758, 0, 2352, +1781, 0, 2349, +1809, 0, 2346, +1845, 0, 2341, +1889, 345, 2335, +1941, 1269, 2326, +2003, 1619, 2315, +2075, 1865, 2299, +2155, 2067, 2277, +2245, 2245, 2245, +2343, 2409, 2199, +2447, 2563, 2129, +2557, 2711, 2015, +2672, 2855, 1796, +2791, 2995, 1006, +2913, 3134, 0, +3037, 3270, 0, +3164, 3406, 0, +3291, 3541, 0, +3420, 3675, 0, +3550, 3808, 0, +3680, 3941, 0, +3810, 4074, 0, +3942, 4095, 0, +2209, 0, 2491, +2210, 0, 2491, +2211, 0, 2490, +2213, 0, 2490, +2215, 0, 2489, +2218, 0, 2489, +2221, 0, 2488, +2226, 0, 2487, +2232, 0, 2486, +2240, 0, 2484, +2251, 0, 2481, +2264, 0, 2478, +2282, 0, 2473, +2305, 477, 2467, +2334, 1401, 2459, +2370, 1751, 2447, +2414, 1997, 2431, +2409, 2199, 2343, +2409, 2288, 2199, +2563, 2545, 2129, +2665, 2711, 2015, +2758, 2855, 1796, +2858, 2995, 1006, +2965, 3134, 0, +3078, 3270, 0, +3194, 3406, 0, +3315, 3541, 0, +3438, 3675, 0, +3563, 3808, 0, +3690, 3941, 0, +3818, 4074, 0, +3947, 4095, 0, +2503, 0, 2623, +2503, 0, 2623, +2504, 0, 2623, +2505, 0, 2622, +2506, 0, 2622, +2507, 0, 2621, +2509, 0, 2621, +2511, 0, 2620, +2515, 0, 2619, +2519, 0, 2618, +2525, 0, 2616, +2533, 0, 2613, +2543, 0, 2610, +2556, 0, 2605, +2572, 611, 2599, +2591, 1533, 2587, +2579, 1883, 2533, +2563, 2129, 2447, +2563, 2129, 2258, +2563, 2339, 2129, +2711, 2634, 2015, +2852, 2855, 1796, +2935, 2995, 1006, +3027, 3134, 0, +3126, 3270, 0, +3233, 3406, 0, +3344, 3541, 0, +3461, 3675, 0, +3581, 3808, 0, +3703, 3941, 0, +3828, 4074, 0, +3955, 4095, 0, +2727, 0, 2755, +2727, 0, 2755, +2728, 0, 2755, +2728, 0, 2755, +2729, 0, 2755, +2730, 0, 2754, +2731, 0, 2754, +2732, 0, 2753, +2734, 0, 2752, +2737, 0, 2751, +2741, 0, 2750, +2745, 0, 2748, +2746, 0, 2740, +2742, 0, 2724, +2738, 0, 2702, +2731, 738, 2671, +2723, 1664, 2626, +2711, 2015, 2557, +2711, 2015, 2416, +2711, 2015, 2114, +2711, 2400, 2015, +2855, 2730, 1796, +2995, 2968, 1006, +3098, 3134, 0, +3184, 3270, 0, +3279, 3406, 0, +3381, 3541, 0, +3490, 3675, 0, +3603, 3808, 0, +3720, 3941, 0, +3841, 4074, 0, +3965, 4095, 0, +2887, 0, 2856, +2887, 0, 2855, +2887, 0, 2855, +2887, 0, 2854, +2887, 0, 2853, +2887, 0, 2852, +2886, 0, 2850, +2886, 0, 2848, +2885, 0, 2845, +2885, 0, 2842, +2883, 0, 2836, +2882, 0, 2829, +2880, 0, 2820, +2878, 0, 2807, +2874, 0, 2788, +2870, 0, 2763, +2863, 870, 2726, +2855, 1796, 2672, +2855, 1796, 2567, +2855, 1796, 2372, +2855, 1796, 1797, +2855, 2470, 1796, +2995, 2833, 1006, +3134, 3084, 0, +3252, 3270, 0, +3335, 3406, 0, +3426, 3541, 0, +3525, 3675, 0, +3631, 3808, 0, +3742, 3941, 0, +3858, 4074, 0, +3978, 4095, 0, +3019, 0, 2938, +3019, 0, 2938, +3019, 0, 2938, +3019, 0, 2937, +3019, 0, 2936, +3019, 0, 2935, +3018, 0, 2934, +3018, 0, 2932, +3018, 0, 2930, +3017, 0, 2927, +3016, 0, 2922, +3015, 0, 2916, +3014, 0, 2908, +3012, 0, 2898, +3010, 0, 2883, +3006, 0, 2862, +3002, 0, 2833, +2995, 1006, 2791, +2995, 1006, 2712, +2995, 1006, 2579, +2995, 1006, 2303, +2995, 1635, 1006, +2995, 2549, 1006, +3134, 2943, 0, +3270, 3203, 0, +3400, 3406, 0, +3480, 3541, 0, +3569, 3675, 0, +3666, 3808, 0, +3770, 3941, 0, +3880, 4074, 0, +3994, 4095, 0, +3152, 0, 3030, +3152, 0, 3029, +3152, 0, 3029, +3151, 0, 3029, +3151, 0, 3028, +3151, 0, 3027, +3151, 0, 3026, +3151, 0, 3025, +3151, 0, 3023, +3150, 0, 3020, +3150, 0, 3017, +3149, 0, 3012, +3148, 0, 3005, +3146, 0, 2997, +3144, 0, 2985, +3142, 0, 2969, +3138, 0, 2946, +3134, 0, 2913, +3134, 0, 2854, +3134, 0, 2761, +3134, 0, 2596, +3134, 0, 2195, +3134, 1211, 0, +3134, 2638, 0, +3270, 3056, 0, +3406, 3325, 0, +3541, 3538, 0, +3622, 3675, 0, +3709, 3808, 0, +3805, 3941, 0, +3907, 4074, 0, +4016, 4095, 0, +3284, 0, 3128, +3283, 0, 3128, +3283, 0, 3128, +3283, 0, 3128, +3283, 0, 3127, +3283, 0, 3127, +3283, 0, 3126, +3283, 0, 3125, +3283, 0, 3123, +3282, 0, 3121, +3282, 0, 3118, +3281, 0, 3114, +3280, 0, 3109, +3280, 0, 3102, +3278, 0, 3093, +3276, 0, 3080, +3274, 0, 3062, +3270, 0, 3037, +3270, 0, 2993, +3270, 0, 2926, +3270, 0, 2818, +3270, 0, 2616, +3270, 0, 1990, +3270, 0, 0, +3270, 2734, 0, +3406, 3175, 0, +3541, 3450, 0, +3675, 3665, 0, +3761, 3808, 0, +3847, 3941, 0, +3941, 4074, 0, +4043, 4095, 0, +3416, 0, 3234, +3416, 0, 3234, +3416, 0, 3234, +3416, 0, 3234, +3416, 0, 3233, +3416, 0, 3233, +3415, 0, 3232, +3415, 0, 3231, +3415, 0, 3230, +3415, 0, 3228, +3414, 0, 3226, +3414, 0, 3223, +3414, 0, 3219, +3413, 0, 3214, +3412, 0, 3206, +3410, 0, 3196, +3408, 0, 3183, +3406, 0, 3164, +3406, 0, 3131, +3406, 0, 3082, +3406, 0, 3008, +3406, 0, 2886, +3406, 0, 2643, +3406, 0, 1325, +3406, 0, 0, +3406, 2838, 0, +3541, 3296, 0, +3675, 3576, 0, +3808, 3794, 0, +3898, 3941, 0, +3983, 4074, 0, +4077, 4095, 0, +3548, 0, 3346, +3548, 0, 3346, +3548, 0, 3346, +3548, 0, 3345, +3548, 0, 3345, +3548, 0, 3344, +3548, 0, 3344, +3548, 0, 3343, +3548, 0, 3342, +3547, 0, 3341, +3547, 0, 3339, +3547, 0, 3337, +3546, 0, 3334, +3546, 0, 3330, +3545, 0, 3324, +3544, 0, 3316, +3543, 0, 3306, +3541, 0, 3291, +3541, 0, 3267, +3541, 0, 3231, +3541, 0, 3179, +3541, 0, 3099, +3541, 0, 2963, +3541, 0, 2676, +3541, 0, 0, +3541, 0, 0, +3541, 2947, 0, +3675, 3420, 0, +3808, 3704, 0, +3941, 3923, 0, +4034, 4074, 0, +4095, 4095, 0, +3680, 0, 3462, +3680, 0, 3462, +3680, 0, 3462, +3680, 0, 3461, +3680, 0, 3461, +3680, 0, 3461, +3680, 0, 3460, +3680, 0, 3460, +3680, 0, 3459, +3680, 0, 3458, +3679, 0, 3457, +3679, 0, 3455, +3679, 0, 3453, +3678, 0, 3449, +3678, 0, 3445, +3677, 0, 3439, +3676, 0, 3431, +3675, 0, 3420, +3675, 0, 3402, +3675, 0, 3376, +3675, 0, 3338, +3675, 0, 3283, +3675, 0, 3197, +3675, 0, 3048, +3675, 0, 2718, +3675, 0, 0, +3675, 0, 0, +3675, 3061, 0, +3808, 3546, 0, +3941, 3832, 0, +4074, 4053, 0, +4095, 4095, 0, +3812, 0, 3581, +3812, 0, 3581, +3812, 0, 3581, +3812, 0, 3581, +3812, 0, 3581, +3812, 0, 3581, +3812, 0, 3580, +3812, 0, 3580, +3812, 0, 3579, +3812, 0, 3579, +3812, 0, 3577, +3812, 0, 3576, +3811, 0, 3574, +3811, 0, 3572, +3810, 0, 3569, +3810, 0, 3564, +3809, 0, 3558, +3808, 0, 3550, +3808, 0, 3536, +3808, 0, 3517, +3808, 0, 3490, +3808, 0, 3451, +3808, 0, 3393, +3808, 0, 3302, +3808, 0, 3143, +3808, 0, 2767, +3808, 0, 0, +3808, 0, 0, +3808, 3180, 0, +3941, 3674, 0, +4074, 3962, 0, +4095, 4095, 0, +3944, 0, 3704, +3944, 0, 3704, +3944, 0, 3704, +3944, 0, 3703, +3944, 0, 3703, +3944, 0, 3703, +3944, 0, 3703, +3944, 0, 3703, +3944, 0, 3702, +3944, 0, 3702, +3944, 0, 3701, +3944, 0, 3700, +3944, 0, 3699, +3943, 0, 3697, +3943, 0, 3694, +3943, 0, 3691, +3942, 0, 3686, +3941, 0, 3680, +3941, 0, 3669, +3941, 0, 3655, +3941, 0, 3635, +3941, 0, 3608, +3941, 0, 3568, +3941, 0, 3507, +3941, 0, 3413, +3941, 0, 3244, +3941, 0, 2826, +3941, 0, 0, +3941, 0, 0, +3941, 3302, 0, +4074, 3802, 0, +4095, 4092, 0, +4076, 0, 3828, +4076, 0, 3828, +4076, 0, 3828, +4076, 0, 3828, +4076, 0, 3828, +4076, 0, 3828, +4076, 0, 3828, +4076, 0, 3828, +4076, 0, 3827, +4076, 0, 3827, +4076, 0, 3826, +4076, 0, 3826, +4076, 0, 3824, +4076, 0, 3823, +4075, 0, 3821, +4075, 0, 3818, +4075, 0, 3815, +4074, 0, 3810, +4074, 0, 3803, +4074, 0, 3792, +4074, 0, 3777, +4074, 0, 3757, +4074, 0, 3729, +4074, 0, 3688, +4074, 0, 3626, +4074, 0, 3528, +4074, 0, 3351, +4074, 0, 2893, +4074, 0, 0, +4074, 0, 0, +4074, 3426, 0, +4095, 3932, 0, +4095, 0, 3955, +4095, 0, 3955, +4095, 0, 3955, +4095, 0, 3955, +4095, 0, 3955, +4095, 0, 3955, +4095, 0, 3955, +4095, 0, 3955, +4095, 0, 3954, +4095, 0, 3954, +4095, 0, 3954, +4095, 0, 3953, +4095, 0, 3952, +4095, 0, 3951, +4095, 0, 3950, +4095, 0, 3948, +4095, 0, 3945, +4095, 0, 3942, +4095, 0, 3936, +4095, 0, 3928, +4095, 0, 3917, +4095, 0, 3903, +4095, 0, 3882, +4095, 0, 3853, +4095, 0, 3811, +4095, 0, 3748, +4095, 0, 3648, +4095, 0, 3465, +4095, 0, 2973, +4095, 0, 0, +4095, 0, 0, +4095, 3552, 0, +0, 2222, 2491, +0, 2224, 2491, +0, 2226, 2491, +0, 2230, 2491, +0, 2234, 2491, +0, 2239, 2491, +0, 2247, 2491, +0, 2256, 2491, +0, 2269, 2491, +0, 2285, 2491, +0, 2306, 2491, +0, 2333, 2491, +0, 2367, 2491, +0, 2408, 2491, +0, 2458, 2491, +0, 2491, 2463, +0, 2491, 2371, +0, 2491, 2209, +0, 2491, 1822, +0, 2623, 0, +0, 2755, 0, +1472, 2887, 0, +2220, 3019, 0, +2554, 3152, 0, +2793, 3284, 0, +2992, 3416, 0, +3168, 3548, 0, +3330, 3680, 0, +3484, 3812, 0, +3631, 3944, 0, +3774, 4076, 0, +3915, 4095, 0, +0, 2220, 2491, +0, 2223, 2491, +0, 2225, 2491, +0, 2228, 2491, +0, 2233, 2491, +0, 2238, 2491, +0, 2245, 2491, +0, 2255, 2491, +0, 2268, 2491, +0, 2284, 2491, +0, 2305, 2491, +0, 2332, 2491, +0, 2366, 2491, +0, 2407, 2491, +0, 2457, 2491, +0, 2491, 2464, +0, 2491, 2372, +0, 2491, 2210, +0, 2491, 1824, +0, 2623, 0, +0, 2755, 0, +1483, 2887, 0, +2222, 3019, 0, +2555, 3152, 0, +2793, 3283, 0, +2992, 3416, 0, +3168, 3548, 0, +3331, 3680, 0, +3484, 3812, 0, +3632, 3944, 0, +3775, 4076, 0, +3915, 4095, 0, +0, 2218, 2491, +0, 2220, 2491, +0, 2223, 2490, +0, 2226, 2490, +0, 2230, 2490, +0, 2236, 2490, +0, 2243, 2490, +0, 2253, 2490, +0, 2266, 2490, +0, 2283, 2490, +0, 2304, 2490, +0, 2331, 2490, +0, 2364, 2490, +0, 2406, 2490, +0, 2456, 2490, +0, 2490, 2464, +0, 2490, 2373, +0, 2490, 2211, +0, 2490, 1826, +0, 2623, 0, +0, 2755, 0, +1497, 2887, 0, +2225, 3019, 0, +2556, 3152, 0, +2794, 3283, 0, +2992, 3416, 0, +3168, 3548, 0, +3331, 3680, 0, +3484, 3812, 0, +3632, 3944, 0, +3775, 4076, 0, +3915, 4095, 0, +0, 2215, 2491, +0, 2217, 2491, +0, 2220, 2490, +0, 2223, 2490, +0, 2228, 2490, +0, 2234, 2490, +0, 2241, 2490, +0, 2251, 2490, +0, 2264, 2490, +0, 2280, 2490, +0, 2302, 2490, +0, 2329, 2490, +0, 2362, 2490, +0, 2404, 2490, +0, 2454, 2490, +0, 2490, 2465, +0, 2490, 2374, +0, 2490, 2213, +0, 2490, 1830, +0, 2622, 0, +0, 2755, 0, +1516, 2887, 0, +2229, 3019, 0, +2558, 3151, 0, +2795, 3283, 0, +2993, 3416, 0, +3169, 3548, 0, +3331, 3680, 0, +3485, 3812, 0, +3632, 3944, 0, +3775, 4076, 0, +3915, 4095, 0, +0, 2210, 2491, +0, 2212, 2491, +0, 2215, 2490, +0, 2219, 2490, +0, 2224, 2489, +0, 2230, 2489, +0, 2238, 2489, +0, 2247, 2489, +0, 2260, 2489, +0, 2277, 2489, +0, 2298, 2489, +0, 2326, 2489, +0, 2360, 2489, +0, 2401, 2489, +0, 2452, 2489, +0, 2489, 2466, +0, 2489, 2375, +0, 2489, 2215, +0, 2489, 1834, +0, 2622, 0, +0, 2755, 0, +1540, 2887, 0, +2234, 3019, 0, +2560, 3151, 0, +2797, 3283, 0, +2994, 3416, 0, +3170, 3548, 0, +3332, 3680, 0, +3485, 3812, 0, +3632, 3944, 0, +3775, 4076, 0, +3915, 4095, 0, +0, 2204, 2491, +0, 2206, 2491, +0, 2209, 2490, +0, 2213, 2490, +0, 2219, 2489, +0, 2226, 2489, +0, 2233, 2489, +0, 2243, 2489, +0, 2256, 2489, +0, 2273, 2489, +0, 2294, 2489, +0, 2322, 2489, +0, 2356, 2489, +0, 2398, 2489, +0, 2449, 2489, +0, 2489, 2468, +0, 2489, 2377, +0, 2489, 2218, +0, 2489, 1840, +0, 2621, 0, +0, 2754, 0, +1569, 2887, 0, +2241, 3019, 0, +2564, 3151, 0, +2799, 3283, 0, +2996, 3416, 0, +3171, 3548, 0, +3332, 3680, 0, +3485, 3812, 0, +3632, 3944, 0, +3775, 4076, 0, +3916, 4095, 0, +0, 2196, 2491, +0, 2199, 2491, +0, 2202, 2490, +0, 2206, 2490, +0, 2211, 2489, +0, 2218, 2489, +0, 2227, 2488, +0, 2237, 2488, +0, 2250, 2488, +0, 2267, 2488, +0, 2289, 2488, +0, 2317, 2488, +0, 2352, 2488, +0, 2394, 2488, +0, 2445, 2488, +0, 2488, 2470, +0, 2488, 2379, +0, 2488, 2221, +0, 2488, 1848, +0, 2621, 0, +0, 2754, 0, +1606, 2886, 0, +2249, 3018, 0, +2568, 3151, 0, +2801, 3283, 0, +2997, 3415, 0, +3172, 3548, 0, +3333, 3680, 0, +3486, 3812, 0, +3633, 3944, 0, +3776, 4076, 0, +3916, 4095, 0, +0, 2185, 2491, +0, 2187, 2491, +0, 2190, 2490, +0, 2195, 2490, +0, 2200, 2489, +0, 2207, 2489, +0, 2217, 2488, +0, 2229, 2487, +0, 2242, 2487, +0, 2260, 2487, +0, 2282, 2487, +0, 2310, 2487, +0, 2345, 2487, +0, 2388, 2487, +0, 2440, 2487, +0, 2487, 2473, +0, 2487, 2383, +0, 2487, 2226, +0, 2487, 1859, +0, 2620, 0, +0, 2753, 0, +1651, 2886, 0, +2261, 3018, 0, +2573, 3151, 0, +2805, 3283, 0, +2999, 3415, 0, +3173, 3548, 0, +3334, 3680, 0, +3487, 3812, 0, +3633, 3944, 0, +3776, 4076, 0, +3916, 4095, 0, +0, 2170, 2491, +0, 2172, 2491, +0, 2175, 2490, +0, 2180, 2490, +0, 2185, 2489, +0, 2193, 2489, +0, 2202, 2488, +0, 2215, 2487, +0, 2231, 2486, +0, 2249, 2486, +0, 2272, 2486, +0, 2301, 2486, +0, 2336, 2486, +0, 2380, 2486, +0, 2433, 2486, +0, 2486, 2476, +0, 2486, 2387, +0, 2486, 2232, +0, 2486, 1873, +0, 2619, 0, +0, 2752, 0, +1706, 2885, 0, +2276, 3018, 0, +2581, 3151, 0, +2809, 3283, 0, +3002, 3415, 0, +3175, 3548, 0, +3336, 3680, 0, +3488, 3812, 0, +3634, 3944, 0, +3777, 4076, 0, +3917, 4095, 0, +0, 2149, 2491, +0, 2151, 2491, +0, 2154, 2490, +0, 2159, 2490, +0, 2165, 2489, +0, 2172, 2489, +0, 2183, 2488, +0, 2196, 2487, +0, 2213, 2486, +0, 2235, 2484, +0, 2258, 2484, +0, 2288, 2484, +0, 2325, 2484, +0, 2369, 2484, +0, 2423, 2484, +0, 2484, 2481, +0, 2484, 2393, +0, 2484, 2240, +0, 2484, 1891, +0, 2618, 0, +0, 2751, 0, +1769, 2885, 0, +2294, 3017, 0, +2591, 3150, 0, +2815, 3282, 0, +3006, 3415, 0, +3178, 3547, 0, +3337, 3680, 0, +3489, 3812, 0, +3635, 3944, 0, +3777, 4076, 0, +3917, 4095, 0, +0, 2119, 2491, +0, 2121, 2491, +0, 2125, 2490, +0, 2129, 2490, +0, 2136, 2489, +0, 2144, 2489, +0, 2155, 2488, +0, 2169, 2487, +0, 2187, 2486, +0, 2210, 2484, +0, 2239, 2481, +0, 2270, 2481, +0, 2308, 2481, +0, 2355, 2481, +0, 2410, 2481, +0, 2475, 2481, +0, 2481, 2401, +0, 2481, 2251, +0, 2481, 1913, +0, 2616, 0, +0, 2750, 0, +1843, 2883, 0, +2319, 3016, 0, +2604, 3150, 0, +2823, 3282, 0, +3011, 3414, 0, +3182, 3547, 0, +3340, 3679, 0, +3491, 3812, 0, +3636, 3944, 0, +3778, 4076, 0, +3918, 4095, 0, +0, 2075, 2491, +0, 2078, 2491, +0, 2082, 2490, +0, 2087, 2490, +0, 2094, 2489, +0, 2103, 2489, +0, 2115, 2488, +0, 2130, 2487, +0, 2149, 2486, +0, 2174, 2484, +0, 2206, 2481, +0, 2245, 2478, +0, 2285, 2478, +0, 2334, 2478, +0, 2392, 2478, +0, 2460, 2478, +0, 2478, 2411, +0, 2478, 2264, +0, 2478, 1941, +0, 2613, 0, +0, 2748, 0, +1925, 2882, 0, +2350, 3015, 0, +2620, 3149, 0, +2833, 3281, 0, +3018, 3414, 0, +3186, 3547, 0, +3343, 3679, 0, +3493, 3812, 0, +3638, 3944, 0, +3780, 4076, 0, +3919, 4095, 0, +0, 2009, 2491, +0, 2013, 2491, +0, 2017, 2490, +0, 2023, 2490, +0, 2031, 2489, +0, 2041, 2489, +0, 2055, 2488, +0, 2072, 2487, +0, 2094, 2486, +0, 2122, 2484, +0, 2158, 2481, +0, 2201, 2478, +0, 2253, 2473, +0, 2305, 2473, +0, 2366, 2473, +0, 2438, 2473, +0, 2473, 2423, +0, 2473, 2282, +0, 2473, 1977, +0, 2610, 0, +678, 2746, 0, +2016, 2880, 0, +2388, 3014, 0, +2642, 3148, 0, +2847, 3280, 0, +3027, 3414, 0, +3192, 3546, 0, +3348, 3679, 0, +3496, 3811, 0, +3640, 3944, 0, +3781, 4076, 0, +3920, 4095, 0, +0, 1903, 2491, +0, 1907, 2491, +0, 1913, 2490, +0, 1920, 2490, +0, 1930, 2489, +0, 1943, 2489, +0, 1960, 2488, +0, 1981, 2487, +0, 2008, 2486, +0, 2042, 2484, +0, 2084, 2481, +0, 2134, 2478, +0, 2194, 2473, +477, 2263, 2467, +477, 2330, 2467, +477, 2407, 2467, +477, 2467, 2440, +477, 2467, 2305, +477, 2467, 2021, +0, 2605, 705, +1463, 2742, 0, +2115, 2878, 0, +2434, 3012, 0, +2669, 3146, 0, +2865, 3280, 0, +3039, 3413, 0, +3201, 3546, 0, +3354, 3678, 0, +3501, 3811, 0, +3644, 3943, 0, +3784, 4076, 0, +3922, 4095, 0, +0, 1706, 2491, +0, 1713, 2491, +0, 1722, 2490, +0, 1733, 2490, +0, 1748, 2489, +0, 1767, 2489, +0, 1791, 2488, +0, 1822, 2487, +0, 1859, 2486, +0, 1906, 2484, +0, 1961, 2481, +0, 2026, 2478, +0, 2100, 2473, +477, 2184, 2467, +1401, 2276, 2459, +1401, 2362, 2459, +1401, 2455, 2459, +1401, 2459, 2334, +1401, 2459, 2073, +611, 2599, 1236, +1799, 2738, 0, +2220, 2874, 0, +2489, 3010, 0, +2703, 3144, 0, +2886, 3278, 0, +3055, 3412, 0, +3211, 3545, 0, +3361, 3678, 0, +3506, 3810, 0, +3648, 3943, 0, +3787, 4075, 0, +3924, 4095, 0, +0, 1120, 2491, +0, 1143, 2491, +0, 1173, 2490, +0, 1210, 2490, +0, 1255, 2489, +0, 1310, 2489, +0, 1373, 2488, +0, 1446, 2487, +0, 1529, 2486, +0, 1620, 2484, +0, 1719, 2481, +0, 1824, 2478, +0, 1935, 2473, +477, 2051, 2467, +1401, 2171, 2459, +1751, 2293, 2447, +1751, 2401, 2447, +1751, 2447, 2370, +1751, 2447, 2135, +1533, 2591, 1533, +2040, 2731, 738, +2332, 2870, 0, +2554, 3006, 0, +2744, 3142, 0, +2915, 3276, 0, +3074, 3410, 0, +3225, 3544, 0, +3371, 3677, 0, +3514, 3810, 0, +3653, 3943, 0, +3790, 4075, 0, +3927, 4095, 0, +0, 0, 2491, +0, 0, 2491, +0, 0, 2490, +0, 0, 2490, +0, 0, 2489, +0, 0, 2489, +0, 0, 2488, +0, 0, 2487, +0, 0, 2486, +0, 0, 2484, +0, 415, 2481, +0, 1199, 2478, +0, 1535, 2473, +477, 1776, 2467, +1401, 1976, 2459, +1751, 2152, 2447, +1997, 2315, 2431, +1997, 2431, 2414, +1997, 2431, 2207, +1981, 2579, 1883, +2240, 2723, 1664, +2447, 2863, 870, +2628, 3002, 0, +2795, 3138, 0, +2950, 3274, 0, +3099, 3408, 0, +3243, 3543, 0, +3385, 3676, 0, +3523, 3809, 0, +3660, 3942, 0, +3796, 4075, 0, +3931, 4095, 0, +0, 0, 2491, +0, 0, 2491, +0, 0, 2490, +0, 0, 2490, +0, 0, 2489, +0, 0, 2489, +0, 0, 2488, +0, 0, 2487, +0, 0, 2486, +0, 0, 2484, +0, 0, 2481, +0, 0, 2478, +557, 0, 2473, +1099, 477, 2467, +1401, 1403, 2459, +1751, 1850, 2447, +1997, 2126, 2431, +2199, 2343, 2409, +2199, 2409, 2288, +2258, 2563, 2129, +2416, 2711, 2015, +2567, 2855, 1796, +2712, 2995, 1006, +2854, 3134, 0, +2993, 3270, 0, +3131, 3406, 0, +3267, 3541, 0, +3402, 3675, 0, +3536, 3808, 0, +3669, 3941, 0, +3803, 4074, 0, +3936, 4095, 0, +1822, 0, 2491, +1824, 0, 2491, +1826, 0, 2490, +1830, 0, 2490, +1834, 0, 2489, +1840, 0, 2489, +1848, 0, 2488, +1859, 0, 2487, +1873, 0, 2486, +1891, 0, 2484, +1913, 0, 2481, +1941, 0, 2478, +1977, 0, 2473, +2021, 477, 2467, +2073, 1401, 2459, +2135, 1751, 2447, +2207, 1997, 2431, +2288, 2199, 2409, +2377, 2377, 2377, +2475, 2541, 2331, +2579, 2696, 2261, +2689, 2843, 2147, +2804, 2987, 1930, +2923, 3128, 1137, +3045, 3266, 0, +3170, 3402, 0, +3296, 3538, 0, +3423, 3673, 0, +3552, 3807, 0, +3682, 3940, 0, +3812, 4073, 0, +3943, 4095, 0, +2340, 0, 2623, +2341, 0, 2623, +2342, 0, 2623, +2343, 0, 2622, +2344, 0, 2622, +2346, 0, 2621, +2349, 0, 2621, +2352, 0, 2620, +2357, 0, 2619, +2363, 0, 2618, +2372, 0, 2616, +2382, 0, 2613, +2396, 0, 2610, +2414, 0, 2605, +2437, 611, 2599, +2466, 1533, 2591, +2502, 1883, 2579, +2545, 2129, 2563, +2541, 2331, 2475, +2541, 2420, 2331, +2696, 2678, 2261, +2797, 2843, 2147, +2890, 2987, 1930, +2991, 3128, 1137, +3097, 3266, 0, +3210, 3402, 0, +3326, 3538, 0, +3447, 3673, 0, +3570, 3807, 0, +3695, 3940, 0, +3822, 4073, 0, +3950, 4095, 0, +2635, 0, 2755, +2635, 0, 2755, +2636, 0, 2755, +2636, 0, 2755, +2637, 0, 2755, +2638, 0, 2754, +2640, 0, 2754, +2641, 0, 2753, +2644, 0, 2752, +2647, 0, 2751, +2651, 0, 2750, +2657, 0, 2748, +2665, 0, 2746, +2675, 0, 2742, +2688, 0, 2738, +2705, 738, 2731, +2723, 1664, 2719, +2711, 2015, 2665, +2696, 2261, 2579, +2696, 2261, 2391, +2696, 2471, 2261, +2843, 2766, 2147, +2984, 2987, 1930, +3067, 3128, 1137, +3159, 3266, 0, +3259, 3402, 0, +3365, 3538, 0, +3477, 3673, 0, +3593, 3807, 0, +3713, 3940, 0, +3835, 4073, 0, +3961, 4095, 0, +2859, 0, 2887, +2859, 0, 2887, +2859, 0, 2887, +2860, 0, 2887, +2860, 0, 2887, +2861, 0, 2887, +2862, 0, 2886, +2863, 0, 2886, +2864, 0, 2885, +2866, 0, 2885, +2869, 0, 2883, +2873, 0, 2882, +2877, 0, 2880, +2878, 0, 2872, +2874, 0, 2856, +2870, 0, 2834, +2863, 870, 2803, +2855, 1796, 2758, +2843, 2147, 2689, +2843, 2147, 2549, +2843, 2147, 2246, +2843, 2532, 2147, +2987, 2862, 1930, +3128, 3101, 1137, +3230, 3266, 0, +3317, 3402, 0, +3411, 3538, 0, +3513, 3673, 0, +3622, 3807, 0, +3735, 3940, 0, +3852, 4073, 0, +3974, 4095, 0, +3019, 0, 2988, +3019, 0, 2987, +3019, 0, 2987, +3019, 0, 2987, +3019, 0, 2986, +3019, 0, 2985, +3018, 0, 2984, +3018, 0, 2982, +3018, 0, 2980, +3017, 0, 2977, +3016, 0, 2974, +3015, 0, 2968, +3014, 0, 2961, +3012, 0, 2952, +3010, 0, 2939, +3006, 0, 2920, +3002, 0, 2895, +2995, 1006, 2858, +2987, 1930, 2804, +2987, 1930, 2699, +2987, 1930, 2503, +2987, 1930, 1930, +2987, 2602, 1930, +3128, 2965, 1137, +3266, 3216, 0, +3384, 3402, 0, +3467, 3538, 0, +3558, 3673, 0, +3657, 3807, 0, +3763, 3940, 0, +3874, 4073, 0, +3990, 4095, 0, +3152, 0, 3071, +3152, 0, 3070, +3152, 0, 3070, +3151, 0, 3070, +3151, 0, 3069, +3151, 0, 3068, +3151, 0, 3067, +3151, 0, 3066, +3151, 0, 3064, +3150, 0, 3062, +3150, 0, 3059, +3149, 0, 3055, +3148, 0, 3049, +3146, 0, 3041, +3144, 0, 3030, +3142, 0, 3015, +3138, 0, 2995, +3134, 0, 2965, +3128, 1137, 2923, +3128, 1137, 2845, +3128, 1137, 2712, +3128, 1137, 2436, +3128, 1758, 1137, +3128, 2681, 1137, +3266, 3074, 0, +3402, 3335, 0, +3532, 3538, 0, +3612, 3673, 0, +3701, 3807, 0, +3798, 3940, 0, +3902, 4073, 0, +4012, 4095, 0, +3284, 0, 3162, +3283, 0, 3162, +3283, 0, 3161, +3283, 0, 3161, +3283, 0, 3160, +3283, 0, 3160, +3283, 0, 3159, +3283, 0, 3158, +3283, 0, 3157, +3282, 0, 3155, +3282, 0, 3152, +3281, 0, 3149, +3280, 0, 3144, +3280, 0, 3138, +3278, 0, 3129, +3276, 0, 3117, +3274, 0, 3100, +3270, 0, 3078, +3266, 0, 3045, +3266, 0, 2986, +3266, 0, 2893, +3266, 0, 2727, +3266, 0, 2327, +3266, 1375, 0, +3266, 2770, 0, +3402, 3189, 0, +3538, 3457, 0, +3673, 3670, 0, +3754, 3807, 0, +3841, 3940, 0, +3937, 4073, 0, +4039, 4095, 0, +3416, 0, 3261, +3416, 0, 3261, +3416, 0, 3260, +3416, 0, 3260, +3416, 0, 3260, +3416, 0, 3259, +3415, 0, 3259, +3415, 0, 3258, +3415, 0, 3257, +3415, 0, 3255, +3414, 0, 3253, +3414, 0, 3250, +3414, 0, 3247, +3413, 0, 3242, +3412, 0, 3234, +3410, 0, 3225, +3408, 0, 3212, +3406, 0, 3194, +3402, 0, 3170, +3402, 0, 3125, +3402, 0, 3059, +3402, 0, 2951, +3402, 0, 2749, +3402, 0, 2121, +3402, 0, 0, +3402, 2866, 0, +3538, 3307, 0, +3673, 3582, 0, +3807, 3797, 0, +3893, 3940, 0, +3979, 4073, 0, +4073, 4095, 0, +3548, 0, 3367, +3548, 0, 3367, +3548, 0, 3366, +3548, 0, 3366, +3548, 0, 3366, +3548, 0, 3365, +3548, 0, 3365, +3548, 0, 3364, +3548, 0, 3363, +3547, 0, 3362, +3547, 0, 3361, +3547, 0, 3358, +3546, 0, 3355, +3546, 0, 3351, +3545, 0, 3346, +3544, 0, 3339, +3543, 0, 3329, +3541, 0, 3315, +3538, 0, 3296, +3538, 0, 3263, +3538, 0, 3214, +3538, 0, 3140, +3538, 0, 3018, +3538, 0, 2775, +3538, 0, 1477, +3538, 0, 0, +3538, 2970, 0, +3673, 3429, 0, +3807, 3708, 0, +3940, 3926, 0, +4030, 4073, 0, +4095, 4095, 0, +3680, 0, 3478, +3680, 0, 3478, +3680, 0, 3478, +3680, 0, 3478, +3680, 0, 3478, +3680, 0, 3477, +3680, 0, 3477, +3680, 0, 3476, +3680, 0, 3475, +3680, 0, 3475, +3679, 0, 3473, +3679, 0, 3472, +3679, 0, 3469, +3678, 0, 3466, +3678, 0, 3462, +3677, 0, 3456, +3676, 0, 3448, +3675, 0, 3438, +3673, 0, 3423, +3673, 0, 3399, +3673, 0, 3363, +3673, 0, 3311, +3673, 0, 3231, +3673, 0, 3095, +3673, 0, 2809, +3673, 0, 0, +3673, 0, 0, +3673, 3079, 0, +3807, 3552, 0, +3940, 3836, 0, +4073, 4055, 0, +4095, 4095, 0, +3812, 0, 3594, +3812, 0, 3594, +3812, 0, 3594, +3812, 0, 3594, +3812, 0, 3594, +3812, 0, 3593, +3812, 0, 3593, +3812, 0, 3593, +3812, 0, 3592, +3812, 0, 3591, +3812, 0, 3590, +3812, 0, 3589, +3811, 0, 3587, +3811, 0, 3585, +3810, 0, 3582, +3810, 0, 3577, +3809, 0, 3571, +3808, 0, 3563, +3807, 0, 3552, +3807, 0, 3534, +3807, 0, 3508, +3807, 0, 3470, +3807, 0, 3415, +3807, 0, 3329, +3807, 0, 3181, +3807, 0, 2850, +3807, 0, 0, +3807, 0, 0, +3807, 3194, 0, +3940, 3678, 0, +4073, 3964, 0, +4095, 4095, 0, +3944, 0, 3713, +3944, 0, 3713, +3944, 0, 3713, +3944, 0, 3713, +3944, 0, 3713, +3944, 0, 3713, +3944, 0, 3713, +3944, 0, 3712, +3944, 0, 3712, +3944, 0, 3711, +3944, 0, 3711, +3944, 0, 3710, +3944, 0, 3708, +3943, 0, 3706, +3943, 0, 3704, +3943, 0, 3701, +3942, 0, 3696, +3941, 0, 3690, +3940, 0, 3682, +3940, 0, 3668, +3940, 0, 3649, +3940, 0, 3622, +3940, 0, 3583, +3940, 0, 3525, +3940, 0, 3434, +3940, 0, 3275, +3940, 0, 2899, +3940, 0, 0, +3940, 0, 0, +3940, 3312, 0, +4073, 3805, 0, +4095, 4094, 0, +4076, 0, 3836, +4076, 0, 3836, +4076, 0, 3836, +4076, 0, 3836, +4076, 0, 3836, +4076, 0, 3835, +4076, 0, 3835, +4076, 0, 3835, +4076, 0, 3835, +4076, 0, 3834, +4076, 0, 3834, +4076, 0, 3833, +4076, 0, 3832, +4076, 0, 3830, +4075, 0, 3829, +4075, 0, 3826, +4075, 0, 3823, +4074, 0, 3818, +4073, 0, 3812, +4073, 0, 3801, +4073, 0, 3787, +4073, 0, 3768, +4073, 0, 3740, +4073, 0, 3700, +4073, 0, 3640, +4073, 0, 3545, +4073, 0, 3376, +4073, 0, 2957, +4073, 0, 0, +4073, 0, 0, +4073, 3434, 0, +4095, 3935, 0, +4095, 0, 3961, +4095, 0, 3961, +4095, 0, 3961, +4095, 0, 3961, +4095, 0, 3961, +4095, 0, 3961, +4095, 0, 3961, +4095, 0, 3960, +4095, 0, 3960, +4095, 0, 3960, +4095, 0, 3959, +4095, 0, 3959, +4095, 0, 3958, +4095, 0, 3957, +4095, 0, 3955, +4095, 0, 3953, +4095, 0, 3951, +4095, 0, 3947, +4095, 0, 3943, +4095, 0, 3935, +4095, 0, 3924, +4095, 0, 3910, +4095, 0, 3890, +4095, 0, 3861, +4095, 0, 3820, +4095, 0, 3759, +4095, 0, 3661, +4095, 0, 3484, +4095, 0, 3027, +4095, 0, 0, +4095, 0, 0, +4095, 3558, 0, +0, 2354, 2623, +0, 2355, 2623, +0, 2357, 2623, +0, 2359, 2623, +0, 2363, 2623, +0, 2367, 2623, +0, 2372, 2623, +0, 2380, 2623, +0, 2390, 2623, +0, 2402, 2623, +0, 2419, 2623, +0, 2440, 2623, +0, 2466, 2623, +0, 2500, 2623, +0, 2541, 2623, +0, 2590, 2623, +0, 2623, 2595, +0, 2623, 2503, +0, 2623, 2340, +0, 2623, 1952, +0, 2755, 0, +0, 2887, 0, +1594, 3019, 0, +2352, 3152, 0, +2684, 3284, 0, +2925, 3416, 0, +3124, 3548, 0, +3300, 3680, 0, +3462, 3812, 0, +3616, 3944, 0, +3763, 4076, 0, +3907, 4095, 0, +0, 2352, 2623, +0, 2354, 2623, +0, 2356, 2623, +0, 2358, 2623, +0, 2362, 2623, +0, 2366, 2623, +0, 2372, 2623, +0, 2379, 2623, +0, 2388, 2623, +0, 2401, 2623, +0, 2417, 2623, +0, 2439, 2623, +0, 2465, 2623, +0, 2499, 2623, +0, 2540, 2623, +0, 2590, 2623, +0, 2623, 2595, +0, 2623, 2503, +0, 2623, 2341, +0, 2623, 1954, +0, 2755, 0, +0, 2887, 0, +1602, 3019, 0, +2353, 3152, 0, +2685, 3283, 0, +2925, 3416, 0, +3124, 3548, 0, +3300, 3680, 0, +3462, 3812, 0, +3616, 3944, 0, +3763, 4076, 0, +3907, 4095, 0, +0, 2351, 2623, +0, 2352, 2623, +0, 2355, 2623, +0, 2357, 2623, +0, 2360, 2623, +0, 2364, 2623, +0, 2370, 2623, +0, 2378, 2623, +0, 2387, 2623, +0, 2400, 2623, +0, 2416, 2623, +0, 2437, 2623, +0, 2464, 2623, +0, 2498, 2623, +0, 2539, 2623, +0, 2589, 2623, +0, 2623, 2596, +0, 2623, 2504, +0, 2623, 2342, +0, 2623, 1956, +0, 2755, 0, +0, 2887, 0, +1613, 3019, 0, +2355, 3152, 0, +2686, 3283, 0, +2926, 3416, 0, +3124, 3548, 0, +3300, 3680, 0, +3463, 3812, 0, +3616, 3944, 0, +3763, 4076, 0, +3907, 4095, 0, +0, 2348, 2623, +0, 2350, 2623, +0, 2352, 2623, +0, 2355, 2622, +0, 2358, 2622, +0, 2362, 2622, +0, 2368, 2622, +0, 2375, 2622, +0, 2385, 2622, +0, 2398, 2622, +0, 2414, 2622, +0, 2436, 2622, +0, 2463, 2622, +0, 2496, 2622, +0, 2538, 2622, +0, 2588, 2622, +0, 2622, 2596, +0, 2622, 2505, +0, 2622, 2343, +0, 2622, 1958, +0, 2755, 0, +0, 2887, 0, +1628, 3019, 0, +2358, 3151, 0, +2688, 3283, 0, +2927, 3416, 0, +3125, 3548, 0, +3301, 3680, 0, +3463, 3812, 0, +3616, 3944, 0, +3764, 4076, 0, +3907, 4095, 0, +0, 2345, 2623, +0, 2347, 2623, +0, 2349, 2623, +0, 2352, 2622, +0, 2356, 2622, +0, 2360, 2622, +0, 2366, 2622, +0, 2373, 2622, +0, 2383, 2622, +0, 2396, 2622, +0, 2412, 2622, +0, 2434, 2622, +0, 2460, 2622, +0, 2494, 2622, +0, 2536, 2622, +0, 2586, 2622, +0, 2622, 2597, +0, 2622, 2506, +0, 2622, 2344, +0, 2622, 1962, +0, 2755, 0, +0, 2887, 0, +1646, 3019, 0, +2362, 3151, 0, +2690, 3283, 0, +2928, 3416, 0, +3125, 3548, 0, +3301, 3680, 0, +3463, 3812, 0, +3617, 3944, 0, +3764, 4076, 0, +3907, 4095, 0, +0, 2341, 2623, +0, 2342, 2623, +0, 2345, 2623, +0, 2347, 2622, +0, 2351, 2622, +0, 2356, 2621, +0, 2362, 2621, +0, 2370, 2621, +0, 2380, 2621, +0, 2393, 2621, +0, 2409, 2621, +0, 2431, 2621, +0, 2458, 2621, +0, 2492, 2621, +0, 2533, 2621, +0, 2584, 2621, +0, 2621, 2598, +0, 2621, 2507, +0, 2621, 2346, +0, 2621, 1966, +0, 2754, 0, +0, 2887, 0, +1670, 3019, 0, +2367, 3151, 0, +2692, 3283, 0, +2929, 3416, 0, +3126, 3548, 0, +3302, 3680, 0, +3464, 3812, 0, +3617, 3944, 0, +3764, 4076, 0, +3908, 4095, 0, +0, 2335, 2623, +0, 2336, 2623, +0, 2338, 2623, +0, 2341, 2622, +0, 2346, 2622, +0, 2351, 2621, +0, 2357, 2621, +0, 2365, 2621, +0, 2375, 2621, +0, 2388, 2621, +0, 2405, 2621, +0, 2427, 2621, +0, 2454, 2621, +0, 2488, 2621, +0, 2530, 2621, +0, 2581, 2621, +0, 2621, 2600, +0, 2621, 2509, +0, 2621, 2349, +0, 2621, 1972, +0, 2754, 0, +0, 2886, 0, +1700, 3018, 0, +2373, 3151, 0, +2695, 3283, 0, +2931, 3415, 0, +3128, 3548, 0, +3303, 3680, 0, +3464, 3812, 0, +3617, 3944, 0, +3764, 4076, 0, +3908, 4095, 0, +0, 2327, 2623, +0, 2328, 2623, +0, 2331, 2623, +0, 2334, 2622, +0, 2337, 2622, +0, 2343, 2621, +0, 2350, 2621, +0, 2359, 2620, +0, 2369, 2620, +0, 2382, 2620, +0, 2399, 2620, +0, 2421, 2620, +0, 2449, 2620, +0, 2483, 2620, +0, 2526, 2620, +0, 2577, 2620, +0, 2620, 2602, +0, 2620, 2511, +0, 2620, 2352, +0, 2620, 1981, +0, 2753, 0, +0, 2886, 0, +1737, 3018, 0, +2382, 3151, 0, +2700, 3283, 0, +2934, 3415, 0, +3129, 3548, 0, +3304, 3680, 0, +3465, 3812, 0, +3618, 3944, 0, +3765, 4076, 0, +3908, 4095, 0, +0, 2315, 2623, +0, 2317, 2623, +0, 2320, 2623, +0, 2323, 2622, +0, 2327, 2622, +0, 2332, 2621, +0, 2339, 2621, +0, 2348, 2620, +0, 2361, 2619, +0, 2374, 2619, +0, 2392, 2619, +0, 2414, 2619, +0, 2442, 2619, +0, 2477, 2619, +0, 2520, 2619, +0, 2572, 2619, +0, 2619, 2604, +0, 2619, 2515, +0, 2619, 2357, +0, 2619, 1991, +0, 2752, 0, +0, 2885, 0, +1782, 3018, 0, +2394, 3151, 0, +2705, 3283, 0, +2937, 3415, 0, +3132, 3548, 0, +3305, 3680, 0, +3466, 3812, 0, +3619, 3944, 0, +3765, 4076, 0, +3908, 4095, 0, +0, 2300, 2623, +0, 2302, 2623, +0, 2304, 2623, +0, 2308, 2622, +0, 2312, 2622, +0, 2317, 2621, +0, 2325, 2621, +0, 2334, 2620, +0, 2347, 2619, +0, 2363, 2618, +0, 2381, 2618, +0, 2404, 2618, +0, 2432, 2618, +0, 2469, 2618, +0, 2512, 2618, +0, 2565, 2618, +0, 2618, 2608, +0, 2618, 2519, +0, 2618, 2363, +0, 2618, 2005, +0, 2751, 0, +0, 2885, 0, +1837, 3017, 0, +2408, 3150, 0, +2713, 3282, 0, +2942, 3415, 0, +3135, 3547, 0, +3307, 3680, 0, +3468, 3812, 0, +3620, 3944, 0, +3766, 4076, 0, +3909, 4095, 0, +0, 2278, 2623, +0, 2281, 2623, +0, 2283, 2623, +0, 2287, 2622, +0, 2291, 2622, +0, 2297, 2621, +0, 2304, 2621, +0, 2314, 2620, +0, 2328, 2619, +0, 2345, 2618, +0, 2367, 2616, +0, 2390, 2616, +0, 2420, 2616, +0, 2456, 2616, +0, 2501, 2616, +0, 2555, 2616, +0, 2616, 2613, +0, 2616, 2525, +0, 2616, 2372, +0, 2616, 2022, +0, 2750, 0, +0, 2883, 0, +1900, 3016, 0, +2427, 3150, 0, +2723, 3282, 0, +2947, 3414, 0, +3138, 3547, 0, +3310, 3679, 0, +3469, 3812, 0, +3621, 3944, 0, +3767, 4076, 0, +3910, 4095, 0, +0, 2248, 2623, +0, 2250, 2623, +0, 2253, 2623, +0, 2256, 2622, +0, 2261, 2622, +0, 2268, 2621, +0, 2276, 2621, +0, 2287, 2620, +0, 2301, 2619, +0, 2319, 2618, +0, 2342, 2616, +0, 2371, 2613, +0, 2402, 2613, +0, 2440, 2613, +0, 2487, 2613, +0, 2542, 2613, +0, 2607, 2613, +0, 2613, 2533, +0, 2613, 2382, +0, 2613, 2045, +0, 2748, 0, +0, 2882, 0, +1974, 3015, 0, +2452, 3149, 0, +2735, 3281, 0, +2956, 3414, 0, +3144, 3547, 0, +3314, 3679, 0, +3472, 3812, 0, +3623, 3944, 0, +3768, 4076, 0, +3910, 4095, 0, +0, 2205, 2623, +0, 2207, 2623, +0, 2210, 2623, +0, 2214, 2622, +0, 2219, 2622, +0, 2226, 2621, +0, 2235, 2621, +0, 2247, 2620, +0, 2262, 2619, +0, 2281, 2618, +0, 2306, 2616, +0, 2338, 2613, +0, 2377, 2610, +0, 2417, 2610, +0, 2466, 2610, +0, 2524, 2610, +0, 2592, 2610, +0, 2610, 2543, +0, 2610, 2396, +0, 2610, 2073, +0, 2746, 0, +0, 2880, 0, +2056, 3014, 0, +2482, 3148, 0, +2752, 3280, 0, +2966, 3414, 0, +3151, 3546, 0, +3318, 3679, 0, +3475, 3811, 0, +3625, 3944, 0, +3770, 4076, 0, +3912, 4095, 0, +0, 2138, 2623, +0, 2141, 2623, +0, 2144, 2623, +0, 2149, 2622, +0, 2155, 2622, +0, 2163, 2621, +0, 2173, 2621, +0, 2187, 2620, +0, 2204, 2619, +0, 2226, 2618, +0, 2255, 2616, +0, 2290, 2613, +0, 2333, 2610, +0, 2385, 2605, +0, 2437, 2605, +0, 2498, 2605, +0, 2570, 2605, +0, 2605, 2556, +0, 2605, 2414, +0, 2605, 2109, +0, 2742, 0, +817, 2878, 0, +2148, 3012, 0, +2521, 3146, 0, +2773, 3280, 0, +2979, 3413, 0, +3160, 3546, 0, +3325, 3678, 0, +3480, 3811, 0, +3628, 3943, 0, +3773, 4076, 0, +3913, 4095, 0, +0, 2032, 2623, +0, 2035, 2623, +0, 2039, 2623, +0, 2045, 2622, +0, 2052, 2622, +0, 2062, 2621, +0, 2075, 2621, +0, 2092, 2620, +0, 2113, 2619, +0, 2140, 2618, +0, 2174, 2616, +0, 2216, 2613, +0, 2266, 2610, +0, 2326, 2605, +611, 2395, 2599, +611, 2462, 2599, +611, 2538, 2599, +611, 2599, 2572, +611, 2599, 2437, +611, 2599, 2153, +0, 2738, 817, +1596, 2874, 0, +2247, 3010, 0, +2566, 3144, 0, +2800, 3278, 0, +2997, 3412, 0, +3171, 3545, 0, +3333, 3678, 0, +3486, 3810, 0, +3632, 3943, 0, +3776, 4075, 0, +3916, 4095, 0, +0, 1833, 2623, +0, 1838, 2623, +0, 1845, 2623, +0, 1853, 2622, +0, 1865, 2622, +0, 1880, 2621, +0, 1899, 2621, +0, 1923, 2620, +0, 1954, 2619, +0, 1991, 2618, +0, 2038, 2616, +0, 2093, 2613, +0, 2158, 2610, +0, 2233, 2605, +611, 2316, 2599, +1533, 2408, 2591, +1533, 2493, 2591, +1533, 2587, 2591, +1533, 2591, 2466, +1533, 2591, 2206, +738, 2731, 1362, +1932, 2870, 0, +2352, 3006, 0, +2622, 3142, 0, +2834, 3276, 0, +3019, 3410, 0, +3186, 3544, 0, +3344, 3677, 0, +3493, 3810, 0, +3638, 3943, 0, +3780, 4075, 0, +3919, 4095, 0, +0, 1232, 2623, +0, 1251, 2623, +0, 1275, 2623, +0, 1304, 2622, +0, 1342, 2622, +0, 1387, 2621, +0, 1441, 2621, +0, 1505, 2620, +0, 1578, 2619, +0, 1661, 2618, +0, 1752, 2616, +0, 1851, 2613, +0, 1956, 2610, +0, 2067, 2605, +611, 2183, 2599, +1533, 2303, 2591, +1883, 2425, 2579, +1883, 2533, 2579, +1883, 2579, 2502, +1883, 2579, 2267, +1667, 2723, 1664, +2173, 2863, 870, +2463, 3002, 0, +2687, 3138, 0, +2876, 3274, 0, +3047, 3408, 0, +3206, 3543, 0, +3358, 3676, 0, +3503, 3809, 0, +3646, 3942, 0, +3785, 4075, 0, +3923, 4095, 0, +0, 0, 2623, +0, 0, 2623, +0, 0, 2623, +0, 0, 2622, +0, 0, 2622, +0, 0, 2621, +0, 0, 2621, +0, 0, 2620, +0, 0, 2619, +0, 0, 2618, +0, 0, 2616, +0, 547, 2613, +0, 1330, 2610, +0, 1667, 2605, +611, 1908, 2599, +1533, 2108, 2591, +1883, 2284, 2579, +2129, 2447, 2563, +2129, 2563, 2545, +2129, 2563, 2339, +2114, 2711, 2015, +2372, 2855, 1796, +2579, 2995, 1006, +2761, 3134, 0, +2926, 3270, 0, +3082, 3406, 0, +3231, 3541, 0, +3376, 3675, 0, +3517, 3808, 0, +3655, 3941, 0, +3792, 4074, 0, +3928, 4095, 0, +0, 0, 2623, +0, 0, 2623, +0, 0, 2623, +0, 0, 2622, +0, 0, 2622, +0, 0, 2621, +0, 0, 2621, +0, 0, 2620, +0, 0, 2619, +0, 0, 2618, +0, 0, 2616, +0, 0, 2613, +0, 0, 2610, +705, 0, 2605, +1236, 611, 2599, +1533, 1533, 2591, +1883, 1981, 2579, +2129, 2258, 2563, +2331, 2475, 2541, +2331, 2541, 2420, +2391, 2696, 2261, +2549, 2843, 2147, +2699, 2987, 1930, +2845, 3128, 1137, +2986, 3266, 0, +3125, 3402, 0, +3263, 3538, 0, +3399, 3673, 0, +3534, 3807, 0, +3668, 3940, 0, +3801, 4073, 0, +3935, 4095, 0, +1952, 0, 2623, +1954, 0, 2623, +1956, 0, 2623, +1958, 0, 2622, +1962, 0, 2622, +1966, 0, 2621, +1972, 0, 2621, +1981, 0, 2620, +1991, 0, 2619, +2005, 0, 2618, +2022, 0, 2616, +2045, 0, 2613, +2073, 0, 2610, +2109, 0, 2605, +2153, 611, 2599, +2206, 1533, 2591, +2267, 1883, 2579, +2339, 2129, 2563, +2420, 2331, 2541, +2509, 2509, 2509, +2607, 2673, 2463, +2711, 2828, 2393, +2821, 2975, 2280, +2936, 3119, 2061, +3055, 3259, 1272, +3177, 3398, 0, +3302, 3535, 0, +3428, 3670, 0, +3556, 3805, 0, +3684, 3939, 0, +3814, 4072, 0, +3944, 4095, 0, +2473, 0, 2755, +2473, 0, 2755, +2474, 0, 2755, +2475, 0, 2755, +2476, 0, 2755, +2477, 0, 2754, +2479, 0, 2754, +2482, 0, 2753, +2485, 0, 2752, +2490, 0, 2751, +2496, 0, 2750, +2504, 0, 2748, +2515, 0, 2746, +2529, 0, 2742, +2547, 0, 2738, +2570, 738, 2731, +2598, 1664, 2723, +2634, 2015, 2711, +2678, 2261, 2696, +2673, 2463, 2607, +2673, 2552, 2463, +2828, 2810, 2393, +2929, 2975, 2280, +3022, 3119, 2061, +3122, 3259, 1272, +3230, 3398, 0, +3342, 3535, 0, +3459, 3670, 0, +3579, 3805, 0, +3702, 3939, 0, +3827, 4072, 0, +3954, 4095, 0, +2767, 0, 2887, +2767, 0, 2887, +2767, 0, 2887, +2768, 0, 2887, +2768, 0, 2887, +2769, 0, 2887, +2770, 0, 2886, +2772, 0, 2886, +2773, 0, 2885, +2776, 0, 2885, +2779, 0, 2883, +2784, 0, 2882, +2789, 0, 2880, +2797, 0, 2878, +2807, 0, 2874, +2820, 0, 2870, +2837, 870, 2863, +2855, 1796, 2852, +2843, 2147, 2797, +2828, 2393, 2711, +2828, 2393, 2522, +2828, 2603, 2393, +2975, 2898, 2280, +3116, 3119, 2061, +3199, 3259, 1272, +3291, 3398, 0, +3391, 3535, 0, +3497, 3670, 0, +3609, 3805, 0, +3725, 3939, 0, +3845, 4072, 0, +3968, 4095, 0, +2991, 0, 3019, +2991, 0, 3019, +2991, 0, 3019, +2991, 0, 3019, +2992, 0, 3019, +2992, 0, 3019, +2992, 0, 3018, +2993, 0, 3018, +2995, 0, 3018, +2996, 0, 3017, +2998, 0, 3016, +3001, 0, 3015, +3004, 0, 3014, +3009, 0, 3012, +3010, 0, 3004, +3006, 0, 2988, +3002, 0, 2966, +2995, 1006, 2935, +2987, 1930, 2890, +2975, 2280, 2821, +2975, 2280, 2680, +2975, 2280, 2377, +2975, 2664, 2280, +3119, 2995, 2061, +3259, 3233, 1272, +3362, 3398, 0, +3449, 3535, 0, +3543, 3670, 0, +3646, 3805, 0, +3754, 3939, 0, +3867, 4072, 0, +3984, 4095, 0, +3152, 0, 3120, +3152, 0, 3120, +3152, 0, 3120, +3151, 0, 3119, +3151, 0, 3119, +3151, 0, 3118, +3151, 0, 3117, +3151, 0, 3116, +3151, 0, 3115, +3150, 0, 3112, +3150, 0, 3110, +3149, 0, 3106, +3148, 0, 3100, +3146, 0, 3093, +3144, 0, 3084, +3142, 0, 3071, +3138, 0, 3053, +3134, 0, 3027, +3128, 1137, 2991, +3119, 2061, 2936, +3119, 2061, 2831, +3119, 2061, 2636, +3119, 2061, 2064, +3119, 2734, 2061, +3259, 3097, 1272, +3398, 3348, 0, +3516, 3535, 0, +3599, 3670, 0, +3690, 3805, 0, +3790, 3939, 0, +3895, 4072, 0, +4006, 4095, 0, +3284, 0, 3203, +3283, 0, 3203, +3283, 0, 3202, +3283, 0, 3202, +3283, 0, 3201, +3283, 0, 3201, +3283, 0, 3200, +3283, 0, 3199, +3283, 0, 3198, +3282, 0, 3196, +3282, 0, 3194, +3281, 0, 3191, +3280, 0, 3186, +3280, 0, 3180, +3278, 0, 3173, +3276, 0, 3162, +3274, 0, 3147, +3270, 0, 3126, +3266, 0, 3097, +3259, 1272, 3055, +3259, 1272, 2976, +3259, 1272, 2843, +3259, 1272, 2569, +3259, 1899, 1272, +3259, 2813, 1272, +3398, 3206, 0, +3535, 3467, 0, +3664, 3670, 0, +3744, 3805, 0, +3833, 3939, 0, +3930, 4072, 0, +4034, 4095, 0, +3416, 0, 3294, +3416, 0, 3294, +3416, 0, 3294, +3416, 0, 3293, +3416, 0, 3293, +3416, 0, 3293, +3415, 0, 3292, +3415, 0, 3291, +3415, 0, 3290, +3415, 0, 3289, +3414, 0, 3287, +3414, 0, 3284, +3414, 0, 3281, +3413, 0, 3276, +3412, 0, 3270, +3410, 0, 3261, +3408, 0, 3249, +3406, 0, 3233, +3402, 0, 3210, +3398, 0, 3177, +3398, 0, 3118, +3398, 0, 3025, +3398, 0, 2860, +3398, 0, 2458, +3398, 1484, 0, +3398, 2902, 0, +3535, 3321, 0, +3670, 3589, 0, +3805, 3802, 0, +3886, 3939, 0, +3973, 4072, 0, +4069, 4095, 0, +3548, 0, 3393, +3548, 0, 3393, +3548, 0, 3393, +3548, 0, 3393, +3548, 0, 3392, +3548, 0, 3392, +3548, 0, 3392, +3548, 0, 3391, +3548, 0, 3390, +3547, 0, 3389, +3547, 0, 3387, +3547, 0, 3385, +3546, 0, 3382, +3546, 0, 3379, +3545, 0, 3374, +3544, 0, 3367, +3543, 0, 3357, +3541, 0, 3344, +3538, 0, 3326, +3535, 0, 3302, +3535, 0, 3257, +3535, 0, 3190, +3535, 0, 3083, +3535, 0, 2881, +3535, 0, 2256, +3535, 0, 0, +3535, 2998, 0, +3670, 3439, 0, +3805, 3714, 0, +3939, 3929, 0, +4025, 4072, 0, +4095, 4095, 0, +3680, 0, 3499, +3680, 0, 3499, +3680, 0, 3499, +3680, 0, 3499, +3680, 0, 3498, +3680, 0, 3498, +3680, 0, 3497, +3680, 0, 3497, +3680, 0, 3496, +3680, 0, 3495, +3679, 0, 3494, +3679, 0, 3493, +3679, 0, 3490, +3678, 0, 3488, +3678, 0, 3483, +3677, 0, 3478, +3676, 0, 3471, +3675, 0, 3461, +3673, 0, 3447, +3670, 0, 3428, +3670, 0, 3395, +3670, 0, 3346, +3670, 0, 3273, +3670, 0, 3150, +3670, 0, 2908, +3670, 0, 1603, +3670, 0, 0, +3670, 3102, 0, +3805, 3561, 0, +3939, 3840, 0, +4072, 4058, 0, +4095, 4095, 0, +3812, 0, 3610, +3812, 0, 3610, +3812, 0, 3610, +3812, 0, 3610, +3812, 0, 3610, +3812, 0, 3609, +3812, 0, 3609, +3812, 0, 3609, +3812, 0, 3608, +3812, 0, 3607, +3812, 0, 3606, +3812, 0, 3605, +3811, 0, 3604, +3811, 0, 3601, +3810, 0, 3598, +3810, 0, 3594, +3809, 0, 3588, +3808, 0, 3581, +3807, 0, 3570, +3805, 0, 3556, +3805, 0, 3531, +3805, 0, 3495, +3805, 0, 3443, +3805, 0, 3363, +3805, 0, 3227, +3805, 0, 2941, +3805, 0, 0, +3805, 0, 0, +3805, 3211, 0, +3939, 3685, 0, +4072, 3968, 0, +4095, 4095, 0, +3944, 0, 3726, +3944, 0, 3726, +3944, 0, 3726, +3944, 0, 3726, +3944, 0, 3726, +3944, 0, 3725, +3944, 0, 3725, +3944, 0, 3725, +3944, 0, 3725, +3944, 0, 3724, +3944, 0, 3723, +3944, 0, 3722, +3944, 0, 3721, +3943, 0, 3719, +3943, 0, 3717, +3943, 0, 3713, +3942, 0, 3709, +3941, 0, 3703, +3940, 0, 3695, +3939, 0, 3684, +3939, 0, 3666, +3939, 0, 3640, +3939, 0, 3603, +3939, 0, 3547, +3939, 0, 3461, +3939, 0, 3313, +3939, 0, 2982, +3939, 0, 0, +3939, 0, 0, +3939, 3326, 0, +4072, 3810, 0, +4095, 4095, 0, +4076, 0, 3846, +4076, 0, 3845, +4076, 0, 3845, +4076, 0, 3845, +4076, 0, 3845, +4076, 0, 3845, +4076, 0, 3845, +4076, 0, 3845, +4076, 0, 3845, +4076, 0, 3844, +4076, 0, 3843, +4076, 0, 3843, +4076, 0, 3841, +4076, 0, 3840, +4075, 0, 3838, +4075, 0, 3836, +4075, 0, 3833, +4074, 0, 3828, +4073, 0, 3822, +4072, 0, 3814, +4072, 0, 3800, +4072, 0, 3781, +4072, 0, 3754, +4072, 0, 3715, +4072, 0, 3657, +4072, 0, 3566, +4072, 0, 3407, +4072, 0, 3031, +4072, 0, 0, +4072, 0, 0, +4072, 3444, 0, +4095, 3938, 0, +4095, 0, 3968, +4095, 0, 3968, +4095, 0, 3968, +4095, 0, 3968, +4095, 0, 3968, +4095, 0, 3968, +4095, 0, 3968, +4095, 0, 3968, +4095, 0, 3967, +4095, 0, 3967, +4095, 0, 3967, +4095, 0, 3966, +4095, 0, 3965, +4095, 0, 3964, +4095, 0, 3963, +4095, 0, 3961, +4095, 0, 3959, +4095, 0, 3955, +4095, 0, 3950, +4095, 0, 3944, +4095, 0, 3934, +4095, 0, 3920, +4095, 0, 3900, +4095, 0, 3872, +4095, 0, 3832, +4095, 0, 3772, +4095, 0, 3677, +4095, 0, 3509, +4095, 0, 3090, +4095, 0, 0, +4095, 0, 0, +4095, 3566, 0, +0, 2486, 2755, +0, 2487, 2755, +0, 2488, 2755, +0, 2490, 2755, +0, 2493, 2755, +0, 2496, 2755, +0, 2500, 2755, +0, 2505, 2755, +0, 2513, 2755, +0, 2523, 2755, +0, 2535, 2755, +0, 2552, 2755, +0, 2573, 2755, +0, 2599, 2755, +0, 2632, 2755, +0, 2673, 2755, +0, 2723, 2755, +0, 2755, 2727, +0, 2755, 2635, +0, 2755, 2473, +0, 2755, 2083, +0, 2887, 0, +0, 3019, 0, +1720, 3152, 0, +2481, 3284, 0, +2816, 3416, 0, +3056, 3548, 0, +3255, 3680, 0, +3432, 3812, 0, +3594, 3944, 0, +3748, 4076, 0, +3896, 4095, 0, +0, 2485, 2755, +0, 2486, 2755, +0, 2488, 2755, +0, 2489, 2755, +0, 2492, 2755, +0, 2495, 2755, +0, 2499, 2755, +0, 2505, 2755, +0, 2512, 2755, +0, 2522, 2755, +0, 2535, 2755, +0, 2551, 2755, +0, 2572, 2755, +0, 2598, 2755, +0, 2632, 2755, +0, 2673, 2755, +0, 2723, 2755, +0, 2755, 2727, +0, 2755, 2635, +0, 2755, 2473, +0, 2755, 2084, +0, 2887, 0, +0, 3019, 0, +1726, 3152, 0, +2482, 3283, 0, +2817, 3416, 0, +3057, 3548, 0, +3256, 3680, 0, +3432, 3812, 0, +3595, 3944, 0, +3748, 4076, 0, +3896, 4095, 0, +0, 2484, 2755, +0, 2485, 2755, +0, 2486, 2755, +0, 2488, 2755, +0, 2491, 2755, +0, 2494, 2755, +0, 2498, 2755, +0, 2504, 2755, +0, 2511, 2755, +0, 2521, 2755, +0, 2533, 2755, +0, 2550, 2755, +0, 2571, 2755, +0, 2598, 2755, +0, 2631, 2755, +0, 2672, 2755, +0, 2722, 2755, +0, 2755, 2728, +0, 2755, 2636, +0, 2755, 2474, +0, 2755, 2086, +0, 2887, 0, +0, 3019, 0, +1735, 3152, 0, +2484, 3283, 0, +2817, 3416, 0, +3057, 3548, 0, +3256, 3680, 0, +3432, 3812, 0, +3595, 3944, 0, +3748, 4076, 0, +3896, 4095, 0, +0, 2482, 2755, +0, 2483, 2755, +0, 2485, 2755, +0, 2487, 2755, +0, 2489, 2755, +0, 2492, 2755, +0, 2497, 2755, +0, 2502, 2755, +0, 2510, 2755, +0, 2520, 2755, +0, 2532, 2755, +0, 2549, 2755, +0, 2570, 2755, +0, 2596, 2755, +0, 2630, 2755, +0, 2671, 2755, +0, 2721, 2755, +0, 2755, 2728, +0, 2755, 2636, +0, 2755, 2475, +0, 2755, 2088, +0, 2887, 0, +0, 3019, 0, +1746, 3151, 0, +2486, 3283, 0, +2818, 3416, 0, +3058, 3548, 0, +3256, 3680, 0, +3432, 3812, 0, +3595, 3944, 0, +3748, 4076, 0, +3896, 4095, 0, +0, 2479, 2755, +0, 2481, 2755, +0, 2482, 2755, +0, 2484, 2755, +0, 2487, 2755, +0, 2490, 2755, +0, 2495, 2755, +0, 2501, 2755, +0, 2508, 2755, +0, 2517, 2755, +0, 2530, 2755, +0, 2547, 2755, +0, 2568, 2755, +0, 2595, 2755, +0, 2628, 2755, +0, 2670, 2755, +0, 2720, 2755, +0, 2755, 2729, +0, 2755, 2637, +0, 2755, 2476, +0, 2755, 2091, +0, 2887, 0, +0, 3019, 0, +1760, 3151, 0, +2489, 3283, 0, +2820, 3416, 0, +3059, 3548, 0, +3257, 3680, 0, +3433, 3812, 0, +3595, 3944, 0, +3748, 4076, 0, +3896, 4095, 0, +0, 2476, 2755, +0, 2477, 2755, +0, 2479, 2755, +0, 2481, 2755, +0, 2484, 2755, +0, 2488, 2754, +0, 2492, 2754, +0, 2498, 2754, +0, 2505, 2754, +0, 2515, 2754, +0, 2528, 2754, +0, 2545, 2754, +0, 2566, 2754, +0, 2593, 2754, +0, 2627, 2754, +0, 2668, 2754, +0, 2718, 2754, +0, 2754, 2730, +0, 2754, 2638, +0, 2754, 2477, +0, 2754, 2094, +0, 2887, 0, +0, 3019, 0, +1779, 3151, 0, +2493, 3283, 0, +2822, 3416, 0, +3060, 3548, 0, +3258, 3680, 0, +3433, 3812, 0, +3595, 3944, 0, +3749, 4076, 0, +3896, 4095, 0, +0, 2472, 2755, +0, 2473, 2755, +0, 2475, 2755, +0, 2477, 2755, +0, 2480, 2755, +0, 2484, 2754, +0, 2489, 2754, +0, 2494, 2754, +0, 2502, 2754, +0, 2512, 2754, +0, 2525, 2754, +0, 2541, 2754, +0, 2563, 2754, +0, 2590, 2754, +0, 2624, 2754, +0, 2666, 2754, +0, 2716, 2754, +0, 2754, 2731, +0, 2754, 2640, +0, 2754, 2479, +0, 2754, 2099, +0, 2886, 0, +0, 3018, 0, +1802, 3151, 0, +2498, 3283, 0, +2824, 3415, 0, +3061, 3548, 0, +3258, 3680, 0, +3434, 3812, 0, +3596, 3944, 0, +3749, 4076, 0, +3896, 4095, 0, +0, 2466, 2755, +0, 2467, 2755, +0, 2469, 2755, +0, 2471, 2755, +0, 2474, 2755, +0, 2478, 2754, +0, 2483, 2754, +0, 2490, 2753, +0, 2497, 2753, +0, 2507, 2753, +0, 2521, 2753, +0, 2537, 2753, +0, 2559, 2753, +0, 2586, 2753, +0, 2620, 2753, +0, 2662, 2753, +0, 2713, 2753, +0, 2753, 2732, +0, 2753, 2641, +0, 2753, 2482, +0, 2753, 2105, +0, 2886, 0, +0, 3018, 0, +1832, 3151, 0, +2504, 3283, 0, +2827, 3415, 0, +3063, 3548, 0, +3260, 3680, 0, +3435, 3812, 0, +3596, 3944, 0, +3749, 4076, 0, +3897, 4095, 0, +0, 2457, 2755, +0, 2459, 2755, +0, 2460, 2755, +0, 2463, 2755, +0, 2466, 2755, +0, 2470, 2754, +0, 2475, 2754, +0, 2482, 2753, +0, 2491, 2752, +0, 2501, 2752, +0, 2514, 2752, +0, 2532, 2752, +0, 2553, 2752, +0, 2581, 2752, +0, 2616, 2752, +0, 2658, 2752, +0, 2710, 2752, +0, 2752, 2734, +0, 2752, 2644, +0, 2752, 2485, +0, 2752, 2113, +0, 2885, 0, +0, 3018, 0, +1869, 3151, 0, +2513, 3283, 0, +2832, 3415, 0, +3066, 3548, 0, +3261, 3680, 0, +3436, 3812, 0, +3597, 3944, 0, +3750, 4076, 0, +3897, 4095, 0, +0, 2446, 2755, +0, 2448, 2755, +0, 2449, 2755, +0, 2452, 2755, +0, 2455, 2755, +0, 2459, 2754, +0, 2464, 2754, +0, 2471, 2753, +0, 2481, 2752, +0, 2493, 2751, +0, 2506, 2751, +0, 2524, 2751, +0, 2546, 2751, +0, 2574, 2751, +0, 2609, 2751, +0, 2652, 2751, +0, 2704, 2751, +0, 2751, 2737, +0, 2751, 2647, +0, 2751, 2490, +0, 2751, 2123, +0, 2885, 0, +0, 3017, 0, +1915, 3150, 0, +2524, 3282, 0, +2837, 3415, 0, +3069, 3547, 0, +3264, 3680, 0, +3437, 3812, 0, +3598, 3944, 0, +3751, 4076, 0, +3898, 4095, 0, +0, 2431, 2755, +0, 2432, 2755, +0, 2434, 2755, +0, 2436, 2755, +0, 2440, 2755, +0, 2444, 2754, +0, 2450, 2754, +0, 2457, 2753, +0, 2467, 2752, +0, 2479, 2751, +0, 2495, 2750, +0, 2514, 2750, +0, 2536, 2750, +0, 2565, 2750, +0, 2601, 2750, +0, 2645, 2750, +0, 2697, 2750, +0, 2750, 2741, +0, 2750, 2651, +0, 2750, 2496, +0, 2750, 2137, +0, 2883, 0, +0, 3016, 0, +1969, 3150, 0, +2539, 3282, 0, +2845, 3414, 0, +3074, 3547, 0, +3267, 3679, 0, +3439, 3812, 0, +3600, 3944, 0, +3752, 4076, 0, +3898, 4095, 0, +0, 2409, 2755, +0, 2411, 2755, +0, 2413, 2755, +0, 2415, 2755, +0, 2419, 2755, +0, 2423, 2754, +0, 2429, 2754, +0, 2437, 2753, +0, 2447, 2752, +0, 2460, 2751, +0, 2477, 2750, +0, 2499, 2748, +0, 2522, 2748, +0, 2552, 2748, +0, 2589, 2748, +0, 2634, 2748, +0, 2687, 2748, +0, 2748, 2745, +0, 2748, 2657, +0, 2748, 2504, +0, 2748, 2155, +0, 2882, 0, +0, 3015, 0, +2033, 3149, 0, +2558, 3281, 0, +2855, 3414, 0, +3080, 3547, 0, +3271, 3679, 0, +3442, 3812, 0, +3602, 3944, 0, +3753, 4076, 0, +3899, 4095, 0, +0, 2379, 2755, +0, 2381, 2755, +0, 2383, 2755, +0, 2386, 2755, +0, 2389, 2755, +0, 2394, 2754, +0, 2400, 2754, +0, 2408, 2753, +0, 2419, 2752, +0, 2433, 2751, +0, 2451, 2750, +0, 2474, 2748, +0, 2503, 2746, +0, 2534, 2746, +0, 2572, 2746, +0, 2619, 2746, +0, 2674, 2746, +0, 2740, 2746, +0, 2746, 2665, +0, 2746, 2515, +0, 2746, 2177, +0, 2880, 0, +0, 3014, 0, +2106, 3148, 0, +2583, 3280, 0, +2867, 3414, 0, +3087, 3546, 0, +3276, 3679, 0, +3446, 3811, 0, +3604, 3944, 0, +3755, 4076, 0, +3901, 4095, 0, +0, 2335, 2755, +0, 2337, 2755, +0, 2339, 2755, +0, 2342, 2755, +0, 2346, 2755, +0, 2351, 2754, +0, 2358, 2754, +0, 2367, 2753, +0, 2379, 2752, +0, 2394, 2751, +0, 2414, 2750, +0, 2439, 2748, +0, 2470, 2746, +0, 2509, 2742, +0, 2550, 2742, +0, 2598, 2742, +0, 2656, 2742, +0, 2724, 2742, +0, 2742, 2675, +0, 2742, 2529, +0, 2742, 2206, +0, 2878, 0, +0, 3012, 0, +2189, 3146, 0, +2613, 3280, 0, +2884, 3413, 0, +3098, 3546, 0, +3282, 3678, 0, +3450, 3811, 0, +3607, 3943, 0, +3757, 4076, 0, +3903, 4095, 0, +0, 2269, 2755, +0, 2271, 2755, +0, 2274, 2755, +0, 2277, 2755, +0, 2281, 2755, +0, 2287, 2754, +0, 2295, 2754, +0, 2305, 2753, +0, 2319, 2752, +0, 2336, 2751, +0, 2359, 2750, +0, 2387, 2748, +0, 2422, 2746, +0, 2465, 2742, +0, 2517, 2738, +0, 2569, 2738, +0, 2631, 2738, +0, 2702, 2738, +0, 2738, 2688, +0, 2738, 2547, +0, 2738, 2241, +0, 2874, 0, +922, 3010, 0, +2280, 3144, 0, +2651, 3278, 0, +2906, 3412, 0, +3111, 3545, 0, +3291, 3678, 0, +3457, 3810, 0, +3612, 3943, 0, +3760, 4075, 0, +3905, 4095, 0, +0, 2162, 2755, +0, 2164, 2755, +0, 2167, 2755, +0, 2172, 2755, +0, 2177, 2755, +0, 2185, 2754, +0, 2195, 2754, +0, 2208, 2753, +0, 2224, 2752, +0, 2245, 2751, +0, 2273, 2750, +0, 2306, 2748, +0, 2348, 2746, +0, 2398, 2742, +0, 2458, 2738, +738, 2527, 2731, +738, 2594, 2731, +738, 2671, 2731, +738, 2731, 2705, +738, 2731, 2570, +738, 2731, 2285, +0, 2870, 963, +1723, 3006, 0, +2379, 3142, 0, +2698, 3276, 0, +2933, 3410, 0, +3129, 3544, 0, +3303, 3677, 0, +3465, 3810, 0, +3618, 3943, 0, +3765, 4075, 0, +3908, 4095, 0, +0, 1962, 2755, +0, 1966, 2755, +0, 1971, 2755, +0, 1977, 2755, +0, 1986, 2755, +0, 1997, 2754, +0, 2012, 2754, +0, 2031, 2753, +0, 2056, 2752, +0, 2086, 2751, +0, 2124, 2750, +0, 2170, 2748, +0, 2226, 2746, +0, 2291, 2742, +0, 2365, 2738, +738, 2448, 2731, +1664, 2540, 2723, +1664, 2626, 2723, +1664, 2719, 2723, +1664, 2723, 2598, +1664, 2723, 2338, +870, 2863, 1498, +2062, 3002, 0, +2484, 3138, 0, +2753, 3274, 0, +2966, 3408, 0, +3151, 3543, 0, +3319, 3676, 0, +3475, 3809, 0, +3626, 3942, 0, +3770, 4075, 0, +3912, 4095, 0, +0, 1353, 2755, +0, 1367, 2755, +0, 1386, 2755, +0, 1409, 2755, +0, 1439, 2755, +0, 1476, 2754, +0, 1521, 2754, +0, 1575, 2753, +0, 1638, 2752, +0, 1711, 2751, +0, 1794, 2750, +0, 1885, 2748, +0, 1983, 2746, +0, 2089, 2742, +0, 2200, 2738, +738, 2315, 2731, +1664, 2435, 2723, +2015, 2557, 2711, +2015, 2665, 2711, +2015, 2711, 2634, +2015, 2711, 2400, +1797, 2855, 1796, +2303, 2995, 1006, +2596, 3134, 0, +2818, 3270, 0, +3008, 3406, 0, +3179, 3541, 0, +3338, 3675, 0, +3490, 3808, 0, +3635, 3941, 0, +3777, 4074, 0, +3917, 4095, 0, +0, 0, 2755, +0, 0, 2755, +0, 0, 2755, +0, 0, 2755, +0, 0, 2755, +0, 0, 2754, +0, 0, 2754, +0, 0, 2753, +0, 0, 2752, +0, 0, 2751, +0, 0, 2750, +0, 0, 2748, +0, 678, 2746, +0, 1463, 2742, +0, 1799, 2738, +738, 2040, 2731, +1664, 2240, 2723, +2015, 2416, 2711, +2261, 2579, 2696, +2261, 2696, 2678, +2261, 2696, 2471, +2246, 2843, 2147, +2503, 2987, 1930, +2712, 3128, 1137, +2893, 3266, 0, +3059, 3402, 0, +3214, 3538, 0, +3363, 3673, 0, +3508, 3807, 0, +3649, 3940, 0, +3787, 4073, 0, +3924, 4095, 0, +0, 0, 2755, +0, 0, 2755, +0, 0, 2755, +0, 0, 2755, +0, 0, 2755, +0, 0, 2754, +0, 0, 2754, +0, 0, 2753, +0, 0, 2752, +0, 0, 2751, +0, 0, 2750, +0, 0, 2748, +0, 0, 2746, +0, 0, 2742, +817, 0, 2738, +1362, 738, 2731, +1664, 1667, 2723, +2015, 2114, 2711, +2261, 2391, 2696, +2463, 2607, 2673, +2463, 2673, 2552, +2522, 2828, 2393, +2680, 2975, 2280, +2831, 3119, 2061, +2976, 3259, 1272, +3118, 3398, 0, +3257, 3535, 0, +3395, 3670, 0, +3531, 3805, 0, +3666, 3939, 0, +3800, 4072, 0, +3934, 4095, 0, +2083, 0, 2755, +2084, 0, 2755, +2086, 0, 2755, +2088, 0, 2755, +2091, 0, 2755, +2094, 0, 2754, +2099, 0, 2754, +2105, 0, 2753, +2113, 0, 2752, +2123, 0, 2751, +2137, 0, 2750, +2155, 0, 2748, +2177, 0, 2746, +2206, 0, 2742, +2241, 0, 2738, +2285, 738, 2731, +2338, 1664, 2723, +2400, 2015, 2711, +2471, 2261, 2696, +2552, 2463, 2673, +2642, 2642, 2642, +2739, 2805, 2596, +2843, 2959, 2526, +2954, 3108, 2412, +3069, 3251, 2194, +3187, 3392, 1406, +3309, 3530, 0, +3434, 3667, 0, +3560, 3802, 0, +3688, 3937, 0, +3816, 4071, 0, +3946, 4095, 0, +2604, 0, 2887, +2604, 0, 2887, +2605, 0, 2887, +2605, 0, 2887, +2606, 0, 2887, +2607, 0, 2887, +2609, 0, 2886, +2611, 0, 2886, +2613, 0, 2885, +2617, 0, 2885, +2621, 0, 2883, +2628, 0, 2882, +2636, 0, 2880, +2647, 0, 2878, +2661, 0, 2874, +2678, 0, 2870, +2701, 870, 2863, +2730, 1796, 2855, +2766, 2147, 2843, +2810, 2393, 2828, +2805, 2596, 2739, +2805, 2684, 2596, +2959, 2942, 2526, +3061, 3108, 2412, +3154, 3251, 2194, +3255, 3392, 1406, +3362, 3530, 0, +3474, 3667, 0, +3591, 3802, 0, +3711, 3937, 0, +3834, 4071, 0, +3960, 4095, 0, +2898, 0, 3019, +2898, 0, 3019, +2898, 0, 3019, +2899, 0, 3019, +2899, 0, 3019, +2900, 0, 3019, +2901, 0, 3018, +2902, 0, 3018, +2903, 0, 3018, +2905, 0, 3017, +2907, 0, 3016, +2911, 0, 3015, +2915, 0, 3014, +2921, 0, 3012, +2928, 0, 3010, +2939, 0, 3006, +2952, 0, 3002, +2968, 1006, 2995, +2987, 1930, 2984, +2975, 2280, 2929, +2959, 2526, 2843, +2959, 2526, 2654, +2959, 2735, 2526, +3108, 3031, 2412, +3248, 3251, 2194, +3331, 3392, 1406, +3423, 3530, 0, +3523, 3667, 0, +3629, 3802, 0, +3741, 3937, 0, +3857, 4071, 0, +3977, 4095, 0, +3123, 0, 3152, +3123, 0, 3152, +3123, 0, 3152, +3123, 0, 3151, +3123, 0, 3151, +3124, 0, 3151, +3124, 0, 3151, +3125, 0, 3151, +3126, 0, 3151, +3127, 0, 3150, +3128, 0, 3150, +3131, 0, 3149, +3133, 0, 3148, +3137, 0, 3146, +3141, 0, 3144, +3142, 0, 3136, +3138, 0, 3120, +3134, 0, 3098, +3128, 1137, 3067, +3119, 2061, 3022, +3108, 2412, 2954, +3108, 2412, 2813, +3108, 2412, 2511, +3108, 2796, 2412, +3251, 3126, 2194, +3392, 3365, 1406, +3495, 3530, 0, +3581, 3667, 0, +3676, 3802, 0, +3777, 3937, 0, +3886, 4071, 0, +3999, 4095, 0, +3284, 0, 3252, +3283, 0, 3252, +3283, 0, 3252, +3283, 0, 3252, +3283, 0, 3251, +3283, 0, 3251, +3283, 0, 3250, +3283, 0, 3249, +3283, 0, 3248, +3282, 0, 3247, +3282, 0, 3244, +3281, 0, 3242, +3280, 0, 3238, +3280, 0, 3233, +3278, 0, 3225, +3276, 0, 3216, +3274, 0, 3203, +3270, 0, 3184, +3266, 0, 3159, +3259, 1272, 3122, +3251, 2194, 3069, +3251, 2194, 2963, +3251, 2194, 2768, +3251, 2195, 2194, +3251, 2866, 2194, +3392, 3230, 1406, +3530, 3480, 0, +3648, 3667, 0, +3731, 3802, 0, +3822, 3937, 0, +3921, 4071, 0, +4027, 4095, 0, +3416, 0, 3335, +3416, 0, 3335, +3416, 0, 3335, +3416, 0, 3335, +3416, 0, 3334, +3416, 0, 3334, +3415, 0, 3333, +3415, 0, 3333, +3415, 0, 3331, +3415, 0, 3330, +3414, 0, 3329, +3414, 0, 3326, +3414, 0, 3323, +3413, 0, 3319, +3412, 0, 3313, +3410, 0, 3305, +3408, 0, 3294, +3406, 0, 3279, +3402, 0, 3259, +3398, 0, 3230, +3392, 1406, 3187, +3392, 1406, 3108, +3392, 1406, 2976, +3392, 1406, 2701, +3392, 2025, 1406, +3392, 2945, 1406, +3530, 3339, 0, +3667, 3599, 0, +3796, 3802, 0, +3876, 3937, 0, +3965, 4071, 0, +4062, 4095, 0, +3548, 0, 3426, +3548, 0, 3426, +3548, 0, 3426, +3548, 0, 3426, +3548, 0, 3426, +3548, 0, 3425, +3548, 0, 3425, +3548, 0, 3424, +3548, 0, 3423, +3547, 0, 3422, +3547, 0, 3421, +3547, 0, 3419, +3546, 0, 3416, +3546, 0, 3413, +3545, 0, 3408, +3544, 0, 3402, +3543, 0, 3393, +3541, 0, 3381, +3538, 0, 3365, +3535, 0, 3342, +3530, 0, 3309, +3530, 0, 3250, +3530, 0, 3157, +3530, 0, 2992, +3530, 0, 2593, +3530, 1621, 0, +3530, 3034, 0, +3667, 3453, 0, +3802, 3721, 0, +3937, 3934, 0, +4018, 4071, 0, +4095, 4095, 0, +3680, 0, 3525, +3680, 0, 3525, +3680, 0, 3525, +3680, 0, 3525, +3680, 0, 3525, +3680, 0, 3525, +3680, 0, 3524, +3680, 0, 3524, +3680, 0, 3523, +3680, 0, 3522, +3679, 0, 3521, +3679, 0, 3520, +3679, 0, 3517, +3678, 0, 3515, +3678, 0, 3511, +3677, 0, 3506, +3676, 0, 3499, +3675, 0, 3490, +3673, 0, 3477, +3670, 0, 3459, +3667, 0, 3434, +3667, 0, 3389, +3667, 0, 3323, +3667, 0, 3215, +3667, 0, 3014, +3667, 0, 2388, +3667, 0, 0, +3667, 3131, 0, +3802, 3571, 0, +3937, 3846, 0, +4071, 4061, 0, +4095, 4095, 0, +3812, 0, 3631, +3812, 0, 3631, +3812, 0, 3631, +3812, 0, 3631, +3812, 0, 3631, +3812, 0, 3630, +3812, 0, 3630, +3812, 0, 3630, +3812, 0, 3629, +3812, 0, 3629, +3812, 0, 3628, +3812, 0, 3626, +3811, 0, 3625, +3811, 0, 3622, +3810, 0, 3620, +3810, 0, 3616, +3809, 0, 3610, +3808, 0, 3603, +3807, 0, 3593, +3805, 0, 3579, +3802, 0, 3560, +3802, 0, 3527, +3802, 0, 3479, +3802, 0, 3405, +3802, 0, 3282, +3802, 0, 3040, +3802, 0, 1737, +3802, 0, 0, +3802, 3234, 0, +3937, 3692, 0, +4071, 3972, 0, +4095, 4095, 0, +3944, 0, 3742, +3944, 0, 3742, +3944, 0, 3742, +3944, 0, 3742, +3944, 0, 3742, +3944, 0, 3742, +3944, 0, 3741, +3944, 0, 3741, +3944, 0, 3741, +3944, 0, 3740, +3944, 0, 3740, +3944, 0, 3739, +3944, 0, 3737, +3943, 0, 3736, +3943, 0, 3733, +3943, 0, 3730, +3942, 0, 3726, +3941, 0, 3720, +3940, 0, 3713, +3939, 0, 3702, +3937, 0, 3688, +3937, 0, 3663, +3937, 0, 3628, +3937, 0, 3575, +3937, 0, 3495, +3937, 0, 3359, +3937, 0, 3073, +3937, 0, 0, +3937, 0, 0, +3937, 3344, 0, +4071, 3816, 0, +4095, 4095, 0, +4076, 0, 3858, +4076, 0, 3858, +4076, 0, 3858, +4076, 0, 3858, +4076, 0, 3858, +4076, 0, 3858, +4076, 0, 3858, +4076, 0, 3857, +4076, 0, 3857, +4076, 0, 3856, +4076, 0, 3856, +4076, 0, 3855, +4076, 0, 3854, +4076, 0, 3853, +4075, 0, 3851, +4075, 0, 3849, +4075, 0, 3846, +4074, 0, 3841, +4073, 0, 3835, +4072, 0, 3827, +4071, 0, 3816, +4071, 0, 3798, +4071, 0, 3772, +4071, 0, 3735, +4071, 0, 3679, +4071, 0, 3593, +4071, 0, 3445, +4071, 0, 3113, +4071, 0, 0, +4071, 0, 0, +4071, 3458, 0, +4095, 3943, 0, +4095, 0, 3978, +4095, 0, 3978, +4095, 0, 3978, +4095, 0, 3978, +4095, 0, 3977, +4095, 0, 3977, +4095, 0, 3977, +4095, 0, 3977, +4095, 0, 3977, +4095, 0, 3977, +4095, 0, 3976, +4095, 0, 3976, +4095, 0, 3975, +4095, 0, 3974, +4095, 0, 3972, +4095, 0, 3971, +4095, 0, 3968, +4095, 0, 3965, +4095, 0, 3961, +4095, 0, 3954, +4095, 0, 3946, +4095, 0, 3932, +4095, 0, 3913, +4095, 0, 3886, +4095, 0, 3847, +4095, 0, 3790, +4095, 0, 3699, +4095, 0, 3539, +4095, 0, 3164, +4095, 0, 0, +4095, 0, 0, +4095, 3576, 0, +0, 2618, 2887, +0, 2619, 2887, +0, 2620, 2887, +0, 2621, 2887, +0, 2623, 2887, +0, 2625, 2887, +0, 2628, 2887, +0, 2633, 2887, +0, 2638, 2887, +0, 2646, 2887, +0, 2655, 2887, +0, 2668, 2887, +0, 2684, 2887, +0, 2705, 2887, +0, 2732, 2887, +0, 2765, 2887, +0, 2806, 2887, +0, 2856, 2887, +0, 2887, 2859, +0, 2887, 2767, +0, 2887, 2604, +0, 2887, 2215, +0, 3019, 0, +0, 3152, 0, +1844, 3284, 0, +2613, 3416, 0, +2948, 3548, 0, +3188, 3680, 0, +3387, 3812, 0, +3564, 3944, 0, +3726, 4076, 0, +3880, 4095, 0, +0, 2617, 2887, +0, 2618, 2887, +0, 2619, 2887, +0, 2620, 2887, +0, 2622, 2887, +0, 2625, 2887, +0, 2628, 2887, +0, 2632, 2887, +0, 2638, 2887, +0, 2645, 2887, +0, 2655, 2887, +0, 2667, 2887, +0, 2684, 2887, +0, 2705, 2887, +0, 2731, 2887, +0, 2764, 2887, +0, 2805, 2887, +0, 2855, 2887, +0, 2887, 2859, +0, 2887, 2767, +0, 2887, 2604, +0, 2887, 2215, +0, 3019, 0, +0, 3152, 0, +1849, 3283, 0, +2614, 3416, 0, +2948, 3548, 0, +3188, 3680, 0, +3388, 3812, 0, +3564, 3944, 0, +3726, 4076, 0, +3880, 4095, 0, +0, 2616, 2887, +0, 2617, 2887, +0, 2618, 2887, +0, 2620, 2887, +0, 2621, 2887, +0, 2624, 2887, +0, 2627, 2887, +0, 2631, 2887, +0, 2637, 2887, +0, 2644, 2887, +0, 2654, 2887, +0, 2667, 2887, +0, 2683, 2887, +0, 2704, 2887, +0, 2731, 2887, +0, 2764, 2887, +0, 2805, 2887, +0, 2855, 2887, +0, 2887, 2859, +0, 2887, 2767, +0, 2887, 2605, +0, 2887, 2217, +0, 3019, 0, +0, 3152, 0, +1856, 3283, 0, +2615, 3416, 0, +2949, 3548, 0, +3189, 3680, 0, +3388, 3812, 0, +3564, 3944, 0, +3726, 4076, 0, +3880, 4095, 0, +0, 2615, 2887, +0, 2616, 2887, +0, 2617, 2887, +0, 2619, 2887, +0, 2620, 2887, +0, 2623, 2887, +0, 2626, 2887, +0, 2630, 2887, +0, 2636, 2887, +0, 2643, 2887, +0, 2653, 2887, +0, 2666, 2887, +0, 2682, 2887, +0, 2703, 2887, +0, 2730, 2887, +0, 2763, 2887, +0, 2804, 2887, +0, 2854, 2887, +0, 2887, 2860, +0, 2887, 2768, +0, 2887, 2605, +0, 2887, 2218, +0, 3019, 0, +0, 3151, 0, +1864, 3283, 0, +2617, 3416, 0, +2950, 3548, 0, +3189, 3680, 0, +3388, 3812, 0, +3564, 3944, 0, +3727, 4076, 0, +3880, 4095, 0, +0, 2613, 2887, +0, 2614, 2887, +0, 2615, 2887, +0, 2617, 2887, +0, 2619, 2887, +0, 2621, 2887, +0, 2625, 2887, +0, 2629, 2887, +0, 2635, 2887, +0, 2642, 2887, +0, 2651, 2887, +0, 2664, 2887, +0, 2681, 2887, +0, 2702, 2887, +0, 2728, 2887, +0, 2762, 2887, +0, 2803, 2887, +0, 2853, 2887, +0, 2887, 2860, +0, 2887, 2768, +0, 2887, 2606, +0, 2887, 2220, +0, 3019, 0, +0, 3151, 0, +1875, 3283, 0, +2619, 3416, 0, +2951, 3548, 0, +3190, 3680, 0, +3388, 3812, 0, +3564, 3944, 0, +3727, 4076, 0, +3880, 4095, 0, +0, 2611, 2887, +0, 2612, 2887, +0, 2613, 2887, +0, 2614, 2887, +0, 2617, 2887, +0, 2619, 2887, +0, 2623, 2887, +0, 2627, 2887, +0, 2632, 2887, +0, 2640, 2887, +0, 2650, 2887, +0, 2662, 2887, +0, 2679, 2887, +0, 2700, 2887, +0, 2727, 2887, +0, 2761, 2887, +0, 2802, 2887, +0, 2852, 2887, +0, 2887, 2861, +0, 2887, 2769, +0, 2887, 2607, +0, 2887, 2223, +0, 3019, 0, +0, 3151, 0, +1890, 3283, 0, +2621, 3416, 0, +2952, 3548, 0, +3191, 3680, 0, +3389, 3812, 0, +3565, 3944, 0, +3727, 4076, 0, +3881, 4095, 0, +0, 2607, 2887, +0, 2608, 2887, +0, 2609, 2887, +0, 2611, 2887, +0, 2613, 2887, +0, 2616, 2887, +0, 2620, 2886, +0, 2624, 2886, +0, 2630, 2886, +0, 2637, 2886, +0, 2647, 2886, +0, 2660, 2886, +0, 2677, 2886, +0, 2698, 2886, +0, 2725, 2886, +0, 2759, 2886, +0, 2800, 2886, +0, 2850, 2886, +0, 2886, 2862, +0, 2886, 2770, +0, 2886, 2609, +0, 2886, 2226, +0, 3018, 0, +0, 3151, 0, +1908, 3283, 0, +2625, 3415, 0, +2954, 3548, 0, +3192, 3680, 0, +3390, 3812, 0, +3565, 3944, 0, +3727, 4076, 0, +3881, 4095, 0, +0, 2603, 2887, +0, 2604, 2887, +0, 2605, 2887, +0, 2607, 2887, +0, 2609, 2887, +0, 2612, 2887, +0, 2616, 2886, +0, 2621, 2886, +0, 2626, 2886, +0, 2634, 2886, +0, 2644, 2886, +0, 2657, 2886, +0, 2673, 2886, +0, 2695, 2886, +0, 2722, 2886, +0, 2756, 2886, +0, 2798, 2886, +0, 2848, 2886, +0, 2886, 2863, +0, 2886, 2772, +0, 2886, 2611, +0, 2886, 2231, +0, 3018, 0, +0, 3151, 0, +1932, 3283, 0, +2630, 3415, 0, +2956, 3548, 0, +3193, 3680, 0, +3391, 3812, 0, +3566, 3944, 0, +3728, 4076, 0, +3881, 4095, 0, +0, 2597, 2887, +0, 2598, 2887, +0, 2599, 2887, +0, 2601, 2887, +0, 2603, 2887, +0, 2606, 2887, +0, 2610, 2886, +0, 2615, 2886, +0, 2622, 2885, +0, 2629, 2885, +0, 2639, 2885, +0, 2652, 2885, +0, 2669, 2885, +0, 2691, 2885, +0, 2718, 2885, +0, 2752, 2885, +0, 2795, 2885, +0, 2845, 2885, +0, 2885, 2864, +0, 2885, 2773, +0, 2885, 2613, +0, 2885, 2237, +0, 3018, 0, +0, 3151, 0, +1962, 3283, 0, +2637, 3415, 0, +2960, 3548, 0, +3195, 3680, 0, +3392, 3812, 0, +3567, 3944, 0, +3728, 4076, 0, +3881, 4095, 0, +0, 2589, 2887, +0, 2589, 2887, +0, 2591, 2887, +0, 2592, 2887, +0, 2595, 2887, +0, 2598, 2887, +0, 2602, 2886, +0, 2607, 2886, +0, 2614, 2885, +0, 2623, 2885, +0, 2633, 2885, +0, 2647, 2885, +0, 2664, 2885, +0, 2685, 2885, +0, 2713, 2885, +0, 2748, 2885, +0, 2790, 2885, +0, 2842, 2885, +0, 2885, 2866, +0, 2885, 2776, +0, 2885, 2617, +0, 2885, 2245, +0, 3017, 0, +0, 3150, 0, +1999, 3282, 0, +2646, 3415, 0, +2964, 3547, 0, +3198, 3680, 0, +3394, 3812, 0, +3568, 3944, 0, +3729, 4076, 0, +3882, 4095, 0, +0, 2577, 2887, +0, 2578, 2887, +0, 2580, 2887, +0, 2581, 2887, +0, 2584, 2887, +0, 2587, 2887, +0, 2591, 2886, +0, 2596, 2886, +0, 2603, 2885, +0, 2613, 2885, +0, 2625, 2883, +0, 2639, 2883, +0, 2656, 2883, +0, 2678, 2883, +0, 2706, 2883, +0, 2741, 2883, +0, 2784, 2883, +0, 2836, 2883, +0, 2883, 2869, +0, 2883, 2779, +0, 2883, 2621, +0, 2883, 2255, +0, 3016, 0, +0, 3150, 0, +2045, 3282, 0, +2657, 3414, 0, +2970, 3547, 0, +3201, 3679, 0, +3396, 3812, 0, +3569, 3944, 0, +3730, 4076, 0, +3883, 4095, 0, +0, 2562, 2887, +0, 2563, 2887, +0, 2564, 2887, +0, 2566, 2887, +0, 2569, 2887, +0, 2572, 2887, +0, 2576, 2886, +0, 2581, 2886, +0, 2589, 2885, +0, 2599, 2885, +0, 2611, 2883, +0, 2628, 2882, +0, 2645, 2882, +0, 2668, 2882, +0, 2697, 2882, +0, 2733, 2882, +0, 2777, 2882, +0, 2829, 2882, +0, 2882, 2873, +0, 2882, 2784, +0, 2882, 2628, +0, 2882, 2269, +0, 3015, 0, +0, 3149, 0, +2100, 3281, 0, +2672, 3414, 0, +2977, 3547, 0, +3206, 3679, 0, +3399, 3812, 0, +3571, 3944, 0, +3732, 4076, 0, +3884, 4095, 0, +0, 2541, 2887, +0, 2542, 2887, +0, 2543, 2887, +0, 2545, 2887, +0, 2548, 2887, +0, 2551, 2887, +0, 2555, 2886, +0, 2561, 2886, +0, 2569, 2885, +0, 2579, 2885, +0, 2592, 2883, +0, 2609, 2882, +0, 2631, 2880, +0, 2654, 2880, +0, 2684, 2880, +0, 2721, 2880, +0, 2766, 2880, +0, 2820, 2880, +0, 2880, 2877, +0, 2880, 2789, +0, 2880, 2636, +0, 2880, 2287, +0, 3014, 0, +0, 3148, 0, +2164, 3280, 0, +2691, 3414, 0, +2987, 3546, 0, +3212, 3679, 0, +3403, 3811, 0, +3574, 3944, 0, +3734, 4076, 0, +3885, 4095, 0, +0, 2510, 2887, +0, 2511, 2887, +0, 2513, 2887, +0, 2515, 2887, +0, 2517, 2887, +0, 2521, 2887, +0, 2526, 2886, +0, 2532, 2886, +0, 2540, 2885, +0, 2551, 2885, +0, 2565, 2883, +0, 2583, 2882, +0, 2606, 2880, +0, 2636, 2878, +0, 2666, 2878, +0, 2704, 2878, +0, 2751, 2878, +0, 2807, 2878, +0, 2872, 2878, +0, 2878, 2797, +0, 2878, 2647, +0, 2878, 2309, +0, 3012, 0, +0, 3146, 0, +2237, 3280, 0, +2715, 3413, 0, +3000, 3546, 0, +3220, 3678, 0, +3408, 3811, 0, +3578, 3943, 0, +3736, 4076, 0, +3887, 4095, 0, +0, 2466, 2887, +0, 2467, 2887, +0, 2469, 2887, +0, 2471, 2887, +0, 2474, 2887, +0, 2478, 2887, +0, 2483, 2886, +0, 2490, 2886, +0, 2499, 2885, +0, 2511, 2885, +0, 2526, 2883, +0, 2546, 2882, +0, 2571, 2880, +0, 2602, 2878, +0, 2641, 2874, +0, 2681, 2874, +0, 2730, 2874, +0, 2788, 2874, +0, 2856, 2874, +0, 2874, 2807, +0, 2874, 2661, +0, 2874, 2338, +0, 3010, 0, +0, 3144, 0, +2320, 3278, 0, +2746, 3412, 0, +3016, 3545, 0, +3230, 3678, 0, +3415, 3810, 0, +3583, 3943, 0, +3739, 4075, 0, +3889, 4095, 0, +0, 2400, 2887, +0, 2401, 2887, +0, 2403, 2887, +0, 2406, 2887, +0, 2409, 2887, +0, 2413, 2887, +0, 2419, 2886, +0, 2427, 2886, +0, 2438, 2885, +0, 2451, 2885, +0, 2469, 2883, +0, 2491, 2882, +0, 2519, 2880, +0, 2554, 2878, +0, 2597, 2874, +0, 2649, 2870, +0, 2701, 2870, +0, 2763, 2870, +0, 2834, 2870, +0, 2870, 2820, +0, 2870, 2678, +0, 2870, 2374, +0, 3006, 0, +1068, 3142, 0, +2411, 3276, 0, +2784, 3410, 0, +3038, 3544, 0, +3243, 3677, 0, +3424, 3810, 0, +3589, 3943, 0, +3744, 4075, 0, +3893, 4095, 0, +0, 2292, 2887, +0, 2294, 2887, +0, 2296, 2887, +0, 2299, 2887, +0, 2304, 2887, +0, 2310, 2887, +0, 2317, 2886, +0, 2327, 2886, +0, 2340, 2885, +0, 2356, 2885, +0, 2378, 2883, +0, 2405, 2882, +0, 2439, 2880, +0, 2480, 2878, +0, 2530, 2874, +0, 2590, 2870, +870, 2659, 2863, +870, 2726, 2863, +870, 2803, 2863, +870, 2863, 2837, +870, 2863, 2701, +870, 2863, 2417, +0, 3002, 1109, +1857, 3138, 0, +2510, 3274, 0, +2830, 3408, 0, +3065, 3543, 0, +3261, 3676, 0, +3435, 3809, 0, +3597, 3942, 0, +3750, 4075, 0, +3897, 4095, 0, +0, 2091, 2887, +0, 2094, 2887, +0, 2098, 2887, +0, 2103, 2887, +0, 2110, 2887, +0, 2118, 2887, +0, 2129, 2886, +0, 2144, 2886, +0, 2163, 2885, +0, 2188, 2885, +0, 2218, 2883, +0, 2256, 2882, +0, 2302, 2880, +0, 2358, 2878, +0, 2423, 2874, +0, 2497, 2870, +870, 2580, 2863, +1796, 2672, 2855, +1796, 2758, 2855, +1796, 2852, 2855, +1796, 2855, 2730, +1796, 2855, 2470, +1006, 2995, 1635, +2195, 3134, 0, +2616, 3270, 0, +2886, 3406, 0, +3099, 3541, 0, +3283, 3675, 0, +3451, 3808, 0, +3608, 3941, 0, +3757, 4074, 0, +3903, 4095, 0, +0, 1472, 2887, +0, 1483, 2887, +0, 1497, 2887, +0, 1516, 2887, +0, 1540, 2887, +0, 1569, 2887, +0, 1606, 2886, +0, 1651, 2886, +0, 1706, 2885, +0, 1769, 2885, +0, 1843, 2883, +0, 1925, 2882, +0, 2016, 2880, +0, 2115, 2878, +0, 2220, 2874, +0, 2332, 2870, +870, 2447, 2863, +1796, 2567, 2855, +2147, 2689, 2843, +2147, 2797, 2843, +2147, 2843, 2766, +2147, 2843, 2532, +1930, 2987, 1930, +2436, 3128, 1137, +2727, 3266, 0, +2951, 3402, 0, +3140, 3538, 0, +3311, 3673, 0, +3470, 3807, 0, +3622, 3940, 0, +3768, 4073, 0, +3910, 4095, 0, +0, 0, 2887, +0, 0, 2887, +0, 0, 2887, +0, 0, 2887, +0, 0, 2887, +0, 0, 2887, +0, 0, 2886, +0, 0, 2886, +0, 0, 2885, +0, 0, 2885, +0, 0, 2883, +0, 0, 2882, +0, 0, 2880, +0, 817, 2878, +0, 1596, 2874, +0, 1932, 2870, +870, 2173, 2863, +1796, 2372, 2855, +2147, 2549, 2843, +2393, 2711, 2828, +2393, 2828, 2810, +2393, 2828, 2603, +2377, 2975, 2280, +2636, 3119, 2061, +2843, 3259, 1272, +3025, 3398, 0, +3190, 3535, 0, +3346, 3670, 0, +3495, 3805, 0, +3640, 3939, 0, +3781, 4072, 0, +3920, 4095, 0, +0, 0, 2887, +0, 0, 2887, +0, 0, 2887, +0, 0, 2887, +0, 0, 2887, +0, 0, 2887, +0, 0, 2886, +0, 0, 2886, +0, 0, 2885, +0, 0, 2885, +0, 0, 2883, +0, 0, 2882, +0, 0, 2880, +0, 0, 2878, +0, 0, 2874, +963, 0, 2870, +1498, 870, 2863, +1796, 1797, 2855, +2147, 2246, 2843, +2393, 2522, 2828, +2596, 2739, 2805, +2596, 2805, 2684, +2654, 2959, 2526, +2813, 3108, 2412, +2963, 3251, 2194, +3108, 3392, 1406, +3250, 3530, 0, +3389, 3667, 0, +3527, 3802, 0, +3663, 3937, 0, +3798, 4071, 0, +3932, 4095, 0, +2215, 0, 2887, +2215, 0, 2887, +2217, 0, 2887, +2218, 0, 2887, +2220, 0, 2887, +2223, 0, 2887, +2226, 0, 2886, +2231, 0, 2886, +2237, 0, 2885, +2245, 0, 2885, +2255, 0, 2883, +2269, 0, 2882, +2287, 0, 2880, +2309, 0, 2878, +2338, 0, 2874, +2374, 0, 2870, +2417, 870, 2863, +2470, 1796, 2855, +2532, 2147, 2843, +2603, 2393, 2828, +2684, 2596, 2805, +2774, 2774, 2774, +2871, 2937, 2728, +2976, 3092, 2658, +3085, 3239, 2544, +3201, 3383, 2326, +3320, 3524, 1536, +3441, 3662, 0, +3566, 3799, 0, +3692, 3934, 0, +3820, 4069, 0, +3949, 4095, 0, +2735, 0, 3019, +2735, 0, 3019, +2736, 0, 3019, +2736, 0, 3019, +2737, 0, 3019, +2738, 0, 3019, +2739, 0, 3018, +2740, 0, 3018, +2742, 0, 3018, +2745, 0, 3017, +2749, 0, 3016, +2753, 0, 3015, +2759, 0, 3014, +2767, 0, 3012, +2778, 0, 3010, +2792, 0, 3006, +2810, 0, 3002, +2833, 1006, 2995, +2862, 1930, 2987, +2898, 2280, 2975, +2942, 2526, 2959, +2937, 2728, 2871, +2937, 2816, 2728, +3092, 3074, 2658, +3193, 3239, 2544, +3286, 3383, 2326, +3387, 3524, 1536, +3494, 3662, 0, +3606, 3799, 0, +3723, 3934, 0, +3843, 4069, 0, +3966, 4095, 0, +3031, 0, 3152, +3031, 0, 3152, +3031, 0, 3152, +3031, 0, 3151, +3031, 0, 3151, +3032, 0, 3151, +3032, 0, 3151, +3033, 0, 3151, +3034, 0, 3151, +3036, 0, 3150, +3038, 0, 3150, +3040, 0, 3149, +3043, 0, 3148, +3047, 0, 3146, +3053, 0, 3144, +3061, 0, 3142, +3071, 0, 3138, +3084, 0, 3134, +3101, 1137, 3128, +3119, 2061, 3116, +3108, 2412, 3061, +3092, 2658, 2976, +3092, 2658, 2787, +3092, 2867, 2658, +3239, 3162, 2544, +3380, 3383, 2326, +3463, 3524, 1536, +3555, 3662, 0, +3655, 3799, 0, +3761, 3934, 0, +3873, 4069, 0, +3989, 4095, 0, +3254, 0, 3284, +3254, 0, 3283, +3255, 0, 3283, +3255, 0, 3283, +3255, 0, 3283, +3255, 0, 3283, +3256, 0, 3283, +3256, 0, 3283, +3257, 0, 3283, +3257, 0, 3282, +3259, 0, 3282, +3260, 0, 3281, +3262, 0, 3280, +3265, 0, 3280, +3269, 0, 3278, +3273, 0, 3276, +3274, 0, 3268, +3270, 0, 3252, +3266, 0, 3230, +3259, 1272, 3199, +3251, 2194, 3154, +3239, 2544, 3085, +3239, 2544, 2945, +3239, 2544, 2642, +3239, 2928, 2544, +3383, 3258, 2326, +3524, 3497, 1536, +3626, 3662, 0, +3713, 3799, 0, +3808, 3934, 0, +3910, 4069, 0, +4018, 4095, 0, +3416, 0, 3385, +3416, 0, 3385, +3416, 0, 3384, +3416, 0, 3384, +3416, 0, 3384, +3416, 0, 3384, +3415, 0, 3383, +3415, 0, 3382, +3415, 0, 3381, +3415, 0, 3380, +3414, 0, 3379, +3414, 0, 3376, +3414, 0, 3374, +3413, 0, 3370, +3412, 0, 3365, +3410, 0, 3358, +3408, 0, 3348, +3406, 0, 3335, +3402, 0, 3317, +3398, 0, 3291, +3392, 1406, 3255, +3383, 2326, 3201, +3383, 2326, 3095, +3383, 2326, 2900, +3383, 2326, 2328, +3383, 2998, 2326, +3524, 3362, 1536, +3662, 3612, 0, +3781, 3799, 0, +3863, 3934, 0, +3954, 4069, 0, +4054, 4095, 0, +3548, 0, 3467, +3548, 0, 3467, +3548, 0, 3467, +3548, 0, 3467, +3548, 0, 3467, +3548, 0, 3466, +3548, 0, 3466, +3548, 0, 3466, +3548, 0, 3465, +3547, 0, 3464, +3547, 0, 3462, +3547, 0, 3461, +3546, 0, 3458, +3546, 0, 3455, +3545, 0, 3451, +3544, 0, 3445, +3543, 0, 3437, +3541, 0, 3426, +3538, 0, 3411, +3535, 0, 3391, +3530, 0, 3362, +3524, 1536, 3320, +3524, 1536, 3241, +3524, 1536, 3108, +3524, 1536, 2833, +3524, 2158, 1536, +3524, 3078, 1536, +3662, 3471, 0, +3799, 3731, 0, +3928, 3934, 0, +4008, 4069, 0, +4095, 4095, 0, +3680, 0, 3558, +3680, 0, 3558, +3680, 0, 3558, +3680, 0, 3558, +3680, 0, 3558, +3680, 0, 3558, +3680, 0, 3557, +3680, 0, 3557, +3680, 0, 3556, +3680, 0, 3556, +3679, 0, 3554, +3679, 0, 3553, +3679, 0, 3551, +3678, 0, 3548, +3678, 0, 3545, +3677, 0, 3540, +3676, 0, 3534, +3675, 0, 3525, +3673, 0, 3513, +3670, 0, 3497, +3667, 0, 3474, +3662, 0, 3441, +3662, 0, 3382, +3662, 0, 3289, +3662, 0, 3125, +3662, 0, 2724, +3662, 1753, 0, +3662, 3166, 0, +3799, 3585, 0, +3934, 3853, 0, +4069, 4066, 0, +4095, 4095, 0, +3812, 0, 3657, +3812, 0, 3657, +3812, 0, 3657, +3812, 0, 3657, +3812, 0, 3657, +3812, 0, 3657, +3812, 0, 3657, +3812, 0, 3656, +3812, 0, 3656, +3812, 0, 3655, +3812, 0, 3654, +3812, 0, 3653, +3811, 0, 3652, +3811, 0, 3650, +3810, 0, 3647, +3810, 0, 3643, +3809, 0, 3638, +3808, 0, 3631, +3807, 0, 3622, +3805, 0, 3609, +3802, 0, 3591, +3799, 0, 3566, +3799, 0, 3522, +3799, 0, 3455, +3799, 0, 3347, +3799, 0, 3145, +3799, 0, 2519, +3799, 0, 0, +3799, 3262, 0, +3934, 3703, 0, +4069, 3978, 0, +4095, 4095, 0, +3944, 0, 3763, +3944, 0, 3763, +3944, 0, 3763, +3944, 0, 3763, +3944, 0, 3763, +3944, 0, 3763, +3944, 0, 3762, +3944, 0, 3762, +3944, 0, 3762, +3944, 0, 3761, +3944, 0, 3761, +3944, 0, 3760, +3944, 0, 3758, +3943, 0, 3757, +3943, 0, 3755, +3943, 0, 3752, +3942, 0, 3748, +3941, 0, 3742, +3940, 0, 3735, +3939, 0, 3725, +3937, 0, 3711, +3934, 0, 3692, +3934, 0, 3659, +3934, 0, 3611, +3934, 0, 3537, +3934, 0, 3414, +3934, 0, 3172, +3934, 0, 1863, +3934, 0, 0, +3934, 3366, 0, +4069, 3824, 0, +4095, 4095, 0, +4076, 0, 3874, +4076, 0, 3874, +4076, 0, 3874, +4076, 0, 3874, +4076, 0, 3874, +4076, 0, 3874, +4076, 0, 3874, +4076, 0, 3873, +4076, 0, 3873, +4076, 0, 3873, +4076, 0, 3872, +4076, 0, 3872, +4076, 0, 3871, +4076, 0, 3869, +4075, 0, 3868, +4075, 0, 3865, +4075, 0, 3862, +4074, 0, 3858, +4073, 0, 3852, +4072, 0, 3845, +4071, 0, 3834, +4069, 0, 3820, +4069, 0, 3795, +4069, 0, 3760, +4069, 0, 3708, +4069, 0, 3627, +4069, 0, 3491, +4069, 0, 3205, +4069, 0, 0, +4069, 0, 0, +4069, 3475, 0, +4095, 3949, 0, +4095, 0, 3990, +4095, 0, 3990, +4095, 0, 3990, +4095, 0, 3990, +4095, 0, 3990, +4095, 0, 3990, +4095, 0, 3990, +4095, 0, 3990, +4095, 0, 3989, +4095, 0, 3989, +4095, 0, 3989, +4095, 0, 3988, +4095, 0, 3988, +4095, 0, 3986, +4095, 0, 3985, +4095, 0, 3983, +4095, 0, 3981, +4095, 0, 3978, +4095, 0, 3974, +4095, 0, 3968, +4095, 0, 3960, +4095, 0, 3949, +4095, 0, 3930, +4095, 0, 3904, +4095, 0, 3867, +4095, 0, 3812, +4095, 0, 3726, +4095, 0, 3577, +4095, 0, 3246, +4095, 0, 0, +4095, 0, 0, +4095, 3590, 0, +0, 2750, 3019, +0, 2750, 3019, +0, 2751, 3019, +0, 2752, 3019, +0, 2754, 3019, +0, 2755, 3019, +0, 2758, 3019, +0, 2761, 3019, +0, 2765, 3019, +0, 2771, 3019, +0, 2778, 3019, +0, 2788, 3019, +0, 2800, 3019, +0, 2816, 3019, +0, 2837, 3019, +0, 2864, 3019, +0, 2897, 3019, +0, 2938, 3019, +0, 2988, 3019, +0, 3019, 2991, +0, 3019, 2898, +0, 3019, 2735, +0, 3019, 2346, +0, 3152, 0, +0, 3284, 0, +1977, 3416, 0, +2745, 3548, 0, +3080, 3680, 0, +3320, 3812, 0, +3520, 3944, 0, +3696, 4076, 0, +3859, 4095, 0, +0, 2749, 3019, +0, 2750, 3019, +0, 2751, 3019, +0, 2752, 3019, +0, 2753, 3019, +0, 2755, 3019, +0, 2757, 3019, +0, 2760, 3019, +0, 2765, 3019, +0, 2770, 3019, +0, 2777, 3019, +0, 2787, 3019, +0, 2800, 3019, +0, 2816, 3019, +0, 2837, 3019, +0, 2863, 3019, +0, 2897, 3019, +0, 2938, 3019, +0, 2987, 3019, +0, 3019, 2991, +0, 3019, 2898, +0, 3019, 2735, +0, 3019, 2346, +0, 3152, 0, +0, 3283, 0, +1981, 3416, 0, +2745, 3548, 0, +3080, 3680, 0, +3321, 3812, 0, +3520, 3944, 0, +3696, 4076, 0, +3859, 4095, 0, +0, 2748, 3019, +0, 2749, 3019, +0, 2750, 3019, +0, 2751, 3019, +0, 2752, 3019, +0, 2754, 3019, +0, 2757, 3019, +0, 2760, 3019, +0, 2764, 3019, +0, 2770, 3019, +0, 2777, 3019, +0, 2787, 3019, +0, 2799, 3019, +0, 2816, 3019, +0, 2836, 3019, +0, 2863, 3019, +0, 2896, 3019, +0, 2938, 3019, +0, 2987, 3019, +0, 3019, 2991, +0, 3019, 2898, +0, 3019, 2736, +0, 3019, 2347, +0, 3152, 0, +0, 3283, 0, +1986, 3416, 0, +2746, 3548, 0, +3081, 3680, 0, +3321, 3812, 0, +3520, 3944, 0, +3696, 4076, 0, +3859, 4095, 0, +0, 2747, 3019, +0, 2748, 3019, +0, 2749, 3019, +0, 2750, 3019, +0, 2751, 3019, +0, 2753, 3019, +0, 2756, 3019, +0, 2759, 3019, +0, 2763, 3019, +0, 2769, 3019, +0, 2776, 3019, +0, 2786, 3019, +0, 2798, 3019, +0, 2815, 3019, +0, 2836, 3019, +0, 2863, 3019, +0, 2896, 3019, +0, 2937, 3019, +0, 2987, 3019, +0, 3019, 2991, +0, 3019, 2899, +0, 3019, 2736, +0, 3019, 2348, +0, 3151, 0, +0, 3283, 0, +1992, 3416, 0, +2747, 3548, 0, +3081, 3680, 0, +3321, 3812, 0, +3520, 3944, 0, +3696, 4076, 0, +3859, 4095, 0, +0, 2746, 3019, +0, 2747, 3019, +0, 2747, 3019, +0, 2749, 3019, +0, 2750, 3019, +0, 2752, 3019, +0, 2755, 3019, +0, 2758, 3019, +0, 2762, 3019, +0, 2768, 3019, +0, 2775, 3019, +0, 2785, 3019, +0, 2797, 3019, +0, 2814, 3019, +0, 2835, 3019, +0, 2862, 3019, +0, 2895, 3019, +0, 2936, 3019, +0, 2986, 3019, +0, 3019, 2992, +0, 3019, 2899, +0, 3019, 2737, +0, 3019, 2350, +0, 3151, 0, +0, 3283, 0, +2000, 3416, 0, +2749, 3548, 0, +3082, 3680, 0, +3322, 3812, 0, +3520, 3944, 0, +3696, 4076, 0, +3859, 4095, 0, +0, 2744, 3019, +0, 2745, 3019, +0, 2746, 3019, +0, 2747, 3019, +0, 2749, 3019, +0, 2751, 3019, +0, 2753, 3019, +0, 2756, 3019, +0, 2761, 3019, +0, 2766, 3019, +0, 2774, 3019, +0, 2784, 3019, +0, 2796, 3019, +0, 2813, 3019, +0, 2834, 3019, +0, 2860, 3019, +0, 2894, 3019, +0, 2935, 3019, +0, 2985, 3019, +0, 3019, 2992, +0, 3019, 2900, +0, 3019, 2738, +0, 3019, 2352, +0, 3151, 0, +0, 3283, 0, +2011, 3416, 0, +2751, 3548, 0, +3083, 3680, 0, +3322, 3812, 0, +3521, 3944, 0, +3696, 4076, 0, +3859, 4095, 0, +0, 2742, 3019, +0, 2742, 3019, +0, 2743, 3019, +0, 2745, 3019, +0, 2746, 3019, +0, 2748, 3019, +0, 2751, 3018, +0, 2754, 3018, +0, 2759, 3018, +0, 2764, 3018, +0, 2772, 3018, +0, 2782, 3018, +0, 2794, 3018, +0, 2811, 3018, +0, 2832, 3018, +0, 2859, 3018, +0, 2892, 3018, +0, 2934, 3018, +0, 2984, 3018, +0, 3018, 2992, +0, 3018, 2901, +0, 3018, 2739, +0, 3018, 2354, +0, 3151, 0, +0, 3283, 0, +2026, 3415, 0, +2754, 3548, 0, +3084, 3680, 0, +3323, 3812, 0, +3521, 3944, 0, +3697, 4076, 0, +3859, 4095, 0, +0, 2738, 3019, +0, 2739, 3019, +0, 2740, 3019, +0, 2741, 3019, +0, 2743, 3019, +0, 2745, 3019, +0, 2748, 3018, +0, 2752, 3018, +0, 2756, 3018, +0, 2762, 3018, +0, 2769, 3018, +0, 2779, 3018, +0, 2792, 3018, +0, 2808, 3018, +0, 2830, 3018, +0, 2857, 3018, +0, 2890, 3018, +0, 2932, 3018, +0, 2982, 3018, +0, 3018, 2993, +0, 3018, 2902, +0, 3018, 2740, +0, 3018, 2358, +0, 3151, 0, +0, 3283, 0, +2044, 3415, 0, +2758, 3548, 0, +3086, 3680, 0, +3324, 3812, 0, +3522, 3944, 0, +3697, 4076, 0, +3860, 4095, 0, +0, 2734, 3019, +0, 2735, 3019, +0, 2735, 3019, +0, 2737, 3019, +0, 2738, 3019, +0, 2741, 3019, +0, 2744, 3018, +0, 2747, 3018, +0, 2752, 3018, +0, 2758, 3018, +0, 2766, 3018, +0, 2776, 3018, +0, 2789, 3018, +0, 2805, 3018, +0, 2827, 3018, +0, 2854, 3018, +0, 2888, 3018, +0, 2930, 3018, +0, 2980, 3018, +0, 3018, 2995, +0, 3018, 2903, +0, 3018, 2742, +0, 3018, 2362, +0, 3151, 0, +0, 3283, 0, +2068, 3415, 0, +2763, 3548, 0, +3089, 3680, 0, +3326, 3812, 0, +3523, 3944, 0, +3698, 4076, 0, +3860, 4095, 0, +0, 2728, 3019, +0, 2729, 3019, +0, 2729, 3019, +0, 2731, 3019, +0, 2732, 3019, +0, 2735, 3019, +0, 2738, 3018, +0, 2742, 3018, +0, 2747, 3018, +0, 2754, 3017, +0, 2761, 3017, +0, 2771, 3017, +0, 2784, 3017, +0, 2801, 3017, +0, 2823, 3017, +0, 2850, 3017, +0, 2885, 3017, +0, 2927, 3017, +0, 2977, 3017, +0, 3017, 2996, +0, 3017, 2905, +0, 3017, 2745, +0, 3017, 2369, +0, 3150, 0, +0, 3282, 0, +2098, 3415, 0, +2770, 3547, 0, +3092, 3680, 0, +3328, 3812, 0, +3524, 3944, 0, +3699, 4076, 0, +3861, 4095, 0, +0, 2720, 3019, +0, 2720, 3019, +0, 2721, 3019, +0, 2723, 3019, +0, 2724, 3019, +0, 2727, 3019, +0, 2730, 3018, +0, 2734, 3018, +0, 2739, 3018, +0, 2746, 3017, +0, 2755, 3016, +0, 2765, 3016, +0, 2778, 3016, +0, 2796, 3016, +0, 2817, 3016, +0, 2845, 3016, +0, 2880, 3016, +0, 2922, 3016, +0, 2974, 3016, +0, 3016, 2998, +0, 3016, 2907, +0, 3016, 2749, +0, 3016, 2377, +0, 3150, 0, +0, 3282, 0, +2135, 3414, 0, +2778, 3547, 0, +3096, 3679, 0, +3330, 3812, 0, +3526, 3944, 0, +3700, 4076, 0, +3862, 4095, 0, +0, 2708, 3019, +0, 2709, 3019, +0, 2710, 3019, +0, 2712, 3019, +0, 2713, 3019, +0, 2716, 3019, +0, 2719, 3018, +0, 2723, 3018, +0, 2728, 3018, +0, 2735, 3017, +0, 2745, 3016, +0, 2757, 3015, +0, 2770, 3015, +0, 2788, 3015, +0, 2810, 3015, +0, 2838, 3015, +0, 2873, 3015, +0, 2916, 3015, +0, 2968, 3015, +0, 3015, 3001, +0, 3015, 2911, +0, 3015, 2753, +0, 3015, 2387, +0, 3149, 0, +0, 3281, 0, +2180, 3414, 0, +2790, 3547, 0, +3102, 3679, 0, +3333, 3812, 0, +3528, 3944, 0, +3701, 4076, 0, +3863, 4095, 0, +0, 2693, 3019, +0, 2694, 3019, +0, 2695, 3019, +0, 2696, 3019, +0, 2698, 3019, +0, 2701, 3019, +0, 2703, 3018, +0, 2708, 3018, +0, 2714, 3018, +0, 2721, 3017, +0, 2731, 3016, +0, 2743, 3015, +0, 2759, 3014, +0, 2777, 3014, +0, 2800, 3014, +0, 2829, 3014, +0, 2865, 3014, +0, 2908, 3014, +0, 2961, 3014, +0, 3014, 3004, +0, 3014, 2915, +0, 3014, 2759, +0, 3014, 2401, +0, 3148, 0, +0, 3280, 0, +2234, 3414, 0, +2804, 3546, 0, +3110, 3679, 0, +3338, 3811, 0, +3531, 3944, 0, +3703, 4076, 0, +3864, 4095, 0, +0, 2672, 3019, +0, 2672, 3019, +0, 2673, 3019, +0, 2675, 3019, +0, 2677, 3019, +0, 2679, 3019, +0, 2683, 3018, +0, 2687, 3018, +0, 2693, 3018, +0, 2701, 3017, +0, 2711, 3016, +0, 2724, 3015, +0, 2741, 3014, +0, 2763, 3012, +0, 2786, 3012, +0, 2816, 3012, +0, 2853, 3012, +0, 2898, 3012, +0, 2952, 3012, +0, 3012, 3009, +0, 3012, 2921, +0, 3012, 2767, +0, 3012, 2419, +0, 3146, 0, +0, 3280, 0, +2298, 3413, 0, +2824, 3546, 0, +3119, 3678, 0, +3344, 3811, 0, +3535, 3943, 0, +3706, 4076, 0, +3866, 4095, 0, +0, 2641, 3019, +0, 2642, 3019, +0, 2643, 3019, +0, 2645, 3019, +0, 2647, 3019, +0, 2649, 3019, +0, 2653, 3018, +0, 2658, 3018, +0, 2664, 3018, +0, 2672, 3017, +0, 2683, 3016, +0, 2697, 3015, +0, 2715, 3014, +0, 2738, 3012, +0, 2767, 3010, +0, 2798, 3010, +0, 2836, 3010, +0, 2883, 3010, +0, 2939, 3010, +0, 3004, 3010, +0, 3010, 2928, +0, 3010, 2778, +0, 3010, 2441, +0, 3144, 0, +0, 3278, 0, +2371, 3412, 0, +2848, 3545, 0, +3132, 3678, 0, +3352, 3810, 0, +3540, 3943, 0, +3710, 4075, 0, +3868, 4095, 0, +0, 2597, 3019, +0, 2598, 3019, +0, 2599, 3019, +0, 2601, 3019, +0, 2603, 3019, +0, 2606, 3019, +0, 2610, 3018, +0, 2615, 3018, +0, 2622, 3018, +0, 2631, 3017, +0, 2643, 3016, +0, 2658, 3015, +0, 2678, 3014, +0, 2703, 3012, +0, 2734, 3010, +0, 2773, 3006, +0, 2813, 3006, +0, 2862, 3006, +0, 2920, 3006, +0, 2988, 3006, +0, 3006, 2939, +0, 3006, 2792, +0, 3006, 2470, +0, 3142, 0, +0, 3276, 0, +2453, 3410, 0, +2879, 3544, 0, +3149, 3677, 0, +3362, 3810, 0, +3547, 3943, 0, +3714, 4075, 0, +3872, 4095, 0, +0, 2530, 3019, +0, 2531, 3019, +0, 2533, 3019, +0, 2535, 3019, +0, 2537, 3019, +0, 2541, 3019, +0, 2545, 3018, +0, 2551, 3018, +0, 2559, 3018, +0, 2570, 3017, +0, 2583, 3016, +0, 2600, 3015, +0, 2623, 3014, +0, 2651, 3012, +0, 2686, 3010, +0, 2729, 3006, +0, 2781, 3002, +0, 2833, 3002, +0, 2895, 3002, +0, 2966, 3002, +0, 3002, 2952, +0, 3002, 2810, +0, 3002, 2505, +0, 3138, 0, +1202, 3274, 0, +2545, 3408, 0, +2917, 3543, 0, +3170, 3676, 0, +3376, 3809, 0, +3556, 3942, 0, +3721, 4075, 0, +3876, 4095, 0, +0, 2422, 3019, +0, 2424, 3019, +0, 2426, 3019, +0, 2428, 3019, +0, 2431, 3019, +0, 2435, 3019, +0, 2441, 3018, +0, 2449, 3018, +0, 2459, 3018, +0, 2471, 3017, +0, 2488, 3016, +0, 2510, 3015, +0, 2536, 3014, +0, 2570, 3012, +0, 2612, 3010, +0, 2662, 3006, +0, 2722, 3002, +1006, 2791, 2995, +1006, 2858, 2995, +1006, 2935, 2995, +1006, 2995, 2968, +1006, 2995, 2833, +1006, 2995, 2549, +0, 3134, 1211, +1990, 3270, 0, +2643, 3406, 0, +2963, 3541, 0, +3197, 3675, 0, +3393, 3808, 0, +3568, 3941, 0, +3729, 4074, 0, +3882, 4095, 0, +0, 2220, 3019, +0, 2222, 3019, +0, 2225, 3019, +0, 2229, 3019, +0, 2234, 3019, +0, 2241, 3019, +0, 2249, 3018, +0, 2261, 3018, +0, 2276, 3018, +0, 2294, 3017, +0, 2319, 3016, +0, 2350, 3015, +0, 2388, 3014, +0, 2434, 3012, +0, 2489, 3010, +0, 2554, 3006, +0, 2628, 3002, +1006, 2712, 2995, +1930, 2804, 2987, +1930, 2890, 2987, +1930, 2984, 2987, +1930, 2987, 2862, +1930, 2987, 2602, +1137, 3128, 1758, +2327, 3266, 0, +2749, 3402, 0, +3018, 3538, 0, +3231, 3673, 0, +3415, 3807, 0, +3583, 3940, 0, +3740, 4073, 0, +3890, 4095, 0, +0, 1594, 3019, +0, 1602, 3019, +0, 1613, 3019, +0, 1628, 3019, +0, 1646, 3019, +0, 1670, 3019, +0, 1700, 3018, +0, 1737, 3018, +0, 1782, 3018, +0, 1837, 3017, +0, 1900, 3016, +0, 1974, 3015, +0, 2056, 3014, +0, 2148, 3012, +0, 2247, 3010, +0, 2352, 3006, +0, 2463, 3002, +1006, 2579, 2995, +1930, 2699, 2987, +2280, 2821, 2975, +2280, 2929, 2975, +2280, 2975, 2898, +2280, 2975, 2664, +2064, 3119, 2061, +2569, 3259, 1272, +2860, 3398, 0, +3083, 3535, 0, +3273, 3670, 0, +3443, 3805, 0, +3603, 3939, 0, +3754, 4072, 0, +3900, 4095, 0, +0, 0, 3019, +0, 0, 3019, +0, 0, 3019, +0, 0, 3019, +0, 0, 3019, +0, 0, 3019, +0, 0, 3018, +0, 0, 3018, +0, 0, 3018, +0, 0, 3017, +0, 0, 3016, +0, 0, 3015, +0, 0, 3014, +0, 0, 3012, +0, 922, 3010, +0, 1723, 3006, +0, 2062, 3002, +1006, 2303, 2995, +1930, 2503, 2987, +2280, 2680, 2975, +2526, 2843, 2959, +2526, 2959, 2942, +2526, 2959, 2735, +2511, 3108, 2412, +2768, 3251, 2194, +2976, 3392, 1406, +3157, 3530, 0, +3323, 3667, 0, +3479, 3802, 0, +3628, 3937, 0, +3772, 4071, 0, +3913, 4095, 0, +0, 0, 3019, +0, 0, 3019, +0, 0, 3019, +0, 0, 3019, +0, 0, 3019, +0, 0, 3019, +0, 0, 3018, +0, 0, 3018, +0, 0, 3018, +0, 0, 3017, +0, 0, 3016, +0, 0, 3015, +0, 0, 3014, +0, 0, 3012, +0, 0, 3010, +0, 0, 3006, +1109, 0, 3002, +1635, 1006, 2995, +1930, 1930, 2987, +2280, 2377, 2975, +2526, 2654, 2959, +2728, 2871, 2937, +2728, 2937, 2816, +2787, 3092, 2658, +2945, 3239, 2544, +3095, 3383, 2326, +3241, 3524, 1536, +3382, 3662, 0, +3522, 3799, 0, +3659, 3934, 0, +3795, 4069, 0, +3930, 4095, 0, +2346, 0, 3019, +2346, 0, 3019, +2347, 0, 3019, +2348, 0, 3019, +2350, 0, 3019, +2352, 0, 3019, +2354, 0, 3018, +2358, 0, 3018, +2362, 0, 3018, +2369, 0, 3017, +2377, 0, 3016, +2387, 0, 3015, +2401, 0, 3014, +2419, 0, 3012, +2441, 0, 3010, +2470, 0, 3006, +2505, 0, 3002, +2549, 1006, 2995, +2602, 1930, 2987, +2664, 2280, 2975, +2735, 2526, 2959, +2816, 2728, 2937, +2906, 2906, 2906, +3003, 3069, 2860, +3107, 3223, 2790, +3218, 3372, 2676, +3333, 3515, 2457, +3452, 3656, 1663, +3574, 3794, 0, +3698, 3931, 0, +3824, 4066, 0, +3952, 4095, 0, +2868, 0, 3152, +2868, 0, 3152, +2869, 0, 3152, +2869, 0, 3151, +2869, 0, 3151, +2870, 0, 3151, +2871, 0, 3151, +2872, 0, 3151, +2873, 0, 3151, +2875, 0, 3150, +2878, 0, 3150, +2881, 0, 3149, +2886, 0, 3148, +2892, 0, 3146, +2901, 0, 3144, +2911, 0, 3142, +2925, 0, 3138, +2943, 0, 3134, +2965, 1137, 3128, +2995, 2061, 3119, +3031, 2412, 3108, +3074, 2658, 3092, +3069, 2860, 3003, +3069, 2948, 2860, +3223, 3206, 2790, +3325, 3372, 2676, +3418, 3515, 2457, +3519, 3656, 1663, +3626, 3794, 0, +3738, 3931, 0, +3855, 4066, 0, +3976, 4095, 0, +3162, 0, 3284, +3162, 0, 3283, +3163, 0, 3283, +3163, 0, 3283, +3163, 0, 3283, +3163, 0, 3283, +3164, 0, 3283, +3164, 0, 3283, +3165, 0, 3283, +3166, 0, 3282, +3168, 0, 3282, +3169, 0, 3281, +3172, 0, 3280, +3175, 0, 3280, +3180, 0, 3278, +3185, 0, 3276, +3193, 0, 3274, +3203, 0, 3270, +3216, 0, 3266, +3233, 1272, 3259, +3251, 2194, 3248, +3239, 2544, 3193, +3223, 2790, 3107, +3223, 2790, 2918, +3223, 2999, 2790, +3372, 3294, 2676, +3512, 3515, 2457, +3595, 3656, 1663, +3687, 3794, 0, +3787, 3931, 0, +3893, 4066, 0, +4005, 4095, 0, +3387, 0, 3416, +3387, 0, 3416, +3387, 0, 3416, +3387, 0, 3416, +3387, 0, 3416, +3387, 0, 3416, +3387, 0, 3415, +3388, 0, 3415, +3388, 0, 3415, +3389, 0, 3415, +3390, 0, 3414, +3391, 0, 3414, +3393, 0, 3414, +3395, 0, 3413, +3397, 0, 3412, +3401, 0, 3410, +3406, 0, 3408, +3406, 0, 3400, +3402, 0, 3384, +3398, 0, 3362, +3392, 1406, 3331, +3383, 2326, 3286, +3372, 2676, 3218, +3372, 2676, 3077, +3372, 2676, 2774, +3372, 3060, 2676, +3515, 3391, 2457, +3656, 3629, 1663, +3759, 3794, 0, +3845, 3931, 0, +3940, 4066, 0, +4042, 4095, 0, +3548, 0, 3516, +3548, 0, 3516, +3548, 0, 3516, +3548, 0, 3516, +3548, 0, 3516, +3548, 0, 3516, +3548, 0, 3515, +3548, 0, 3515, +3548, 0, 3514, +3547, 0, 3513, +3547, 0, 3512, +3547, 0, 3511, +3546, 0, 3509, +3546, 0, 3506, +3545, 0, 3502, +3544, 0, 3497, +3543, 0, 3490, +3541, 0, 3480, +3538, 0, 3467, +3535, 0, 3449, +3530, 0, 3423, +3524, 1536, 3387, +3515, 2457, 3333, +3515, 2457, 3227, +3515, 2457, 3032, +3515, 2457, 2459, +3515, 3130, 2457, +3656, 3494, 1663, +3794, 3745, 0, +3913, 3931, 0, +3995, 4066, 0, +4087, 4095, 0, +3680, 0, 3599, +3680, 0, 3599, +3680, 0, 3599, +3680, 0, 3599, +3680, 0, 3599, +3680, 0, 3599, +3680, 0, 3598, +3680, 0, 3598, +3680, 0, 3597, +3680, 0, 3597, +3679, 0, 3596, +3679, 0, 3595, +3679, 0, 3593, +3678, 0, 3590, +3678, 0, 3587, +3677, 0, 3583, +3676, 0, 3577, +3675, 0, 3569, +3673, 0, 3558, +3670, 0, 3543, +3667, 0, 3523, +3662, 0, 3494, +3656, 1663, 3452, +3656, 1663, 3373, +3656, 1663, 3240, +3656, 1663, 2965, +3656, 2289, 1663, +3656, 3210, 1663, +3794, 3603, 0, +3931, 3863, 0, +4060, 4066, 0, +4095, 4095, 0, +3812, 0, 3691, +3812, 0, 3691, +3812, 0, 3690, +3812, 0, 3690, +3812, 0, 3690, +3812, 0, 3690, +3812, 0, 3690, +3812, 0, 3690, +3812, 0, 3689, +3812, 0, 3689, +3812, 0, 3688, +3812, 0, 3687, +3811, 0, 3685, +3811, 0, 3683, +3810, 0, 3680, +3810, 0, 3677, +3809, 0, 3672, +3808, 0, 3666, +3807, 0, 3657, +3805, 0, 3646, +3802, 0, 3629, +3799, 0, 3606, +3794, 0, 3574, +3794, 0, 3515, +3794, 0, 3421, +3794, 0, 3256, +3794, 0, 2856, +3794, 1884, 0, +3794, 3298, 0, +3931, 3717, 0, +4066, 3985, 0, +4095, 4095, 0, +3944, 0, 3790, +3944, 0, 3790, +3944, 0, 3790, +3944, 0, 3790, +3944, 0, 3789, +3944, 0, 3789, +3944, 0, 3789, +3944, 0, 3789, +3944, 0, 3788, +3944, 0, 3788, +3944, 0, 3787, +3944, 0, 3786, +3944, 0, 3785, +3943, 0, 3784, +3943, 0, 3781, +3943, 0, 3779, +3942, 0, 3775, +3941, 0, 3770, +3940, 0, 3763, +3939, 0, 3754, +3937, 0, 3741, +3934, 0, 3723, +3931, 0, 3698, +3931, 0, 3654, +3931, 0, 3587, +3931, 0, 3479, +3931, 0, 3277, +3931, 0, 2650, +3931, 0, 0, +3931, 3395, 0, +4066, 3835, 0, +4095, 4095, 0, +4076, 0, 3895, +4076, 0, 3895, +4076, 0, 3895, +4076, 0, 3895, +4076, 0, 3895, +4076, 0, 3895, +4076, 0, 3895, +4076, 0, 3895, +4076, 0, 3894, +4076, 0, 3894, +4076, 0, 3893, +4076, 0, 3892, +4076, 0, 3891, +4076, 0, 3890, +4075, 0, 3889, +4075, 0, 3887, +4075, 0, 3884, +4074, 0, 3880, +4073, 0, 3874, +4072, 0, 3867, +4071, 0, 3857, +4069, 0, 3843, +4066, 0, 3824, +4066, 0, 3791, +4066, 0, 3743, +4066, 0, 3669, +4066, 0, 3546, +4066, 0, 3303, +4066, 0, 1985, +4066, 0, 0, +4066, 3498, 0, +4095, 3957, 0, +4095, 0, 4007, +4095, 0, 4006, +4095, 0, 4006, +4095, 0, 4006, +4095, 0, 4006, +4095, 0, 4006, +4095, 0, 4006, +4095, 0, 4006, +4095, 0, 4006, +4095, 0, 4005, +4095, 0, 4005, +4095, 0, 4005, +4095, 0, 4004, +4095, 0, 4003, +4095, 0, 4002, +4095, 0, 4000, +4095, 0, 3998, +4095, 0, 3994, +4095, 0, 3990, +4095, 0, 3984, +4095, 0, 3977, +4095, 0, 3966, +4095, 0, 3952, +4095, 0, 3927, +4095, 0, 3892, +4095, 0, 3840, +4095, 0, 3759, +4095, 0, 3623, +4095, 0, 3337, +4095, 0, 0, +4095, 0, 0, +4095, 3608, 0, +0, 2882, 3152, +0, 2883, 3152, +0, 2883, 3152, +0, 2884, 3152, +0, 2885, 3152, +0, 2886, 3152, +0, 2888, 3152, +0, 2890, 3152, +0, 2893, 3152, +0, 2898, 3152, +0, 2903, 3152, +0, 2911, 3152, +0, 2920, 3152, +0, 2933, 3152, +0, 2949, 3152, +0, 2970, 3152, +0, 2996, 3152, +0, 3030, 3152, +0, 3071, 3152, +0, 3120, 3152, +0, 3152, 3123, +0, 3152, 3031, +0, 3152, 2868, +0, 3152, 2478, +0, 3284, 0, +0, 3416, 0, +2104, 3548, 0, +2876, 3680, 0, +3211, 3812, 0, +3452, 3944, 0, +3651, 4076, 0, +3828, 4095, 0, +0, 2881, 3152, +0, 2882, 3152, +0, 2883, 3152, +0, 2883, 3152, +0, 2885, 3152, +0, 2886, 3152, +0, 2888, 3152, +0, 2890, 3152, +0, 2893, 3152, +0, 2897, 3152, +0, 2903, 3152, +0, 2910, 3152, +0, 2920, 3152, +0, 2932, 3152, +0, 2949, 3152, +0, 2970, 3152, +0, 2996, 3152, +0, 3029, 3152, +0, 3070, 3152, +0, 3120, 3152, +0, 3152, 3123, +0, 3152, 3031, +0, 3152, 2868, +0, 3152, 2478, +0, 3283, 0, +0, 3416, 0, +2107, 3548, 0, +2877, 3680, 0, +3212, 3812, 0, +3452, 3944, 0, +3651, 4076, 0, +3828, 4095, 0, +0, 2881, 3152, +0, 2881, 3152, +0, 2882, 3152, +0, 2883, 3152, +0, 2884, 3152, +0, 2885, 3152, +0, 2887, 3152, +0, 2890, 3152, +0, 2893, 3152, +0, 2897, 3152, +0, 2903, 3152, +0, 2910, 3152, +0, 2919, 3152, +0, 2932, 3152, +0, 2948, 3152, +0, 2969, 3152, +0, 2996, 3152, +0, 3029, 3152, +0, 3070, 3152, +0, 3120, 3152, +0, 3152, 3123, +0, 3152, 3031, +0, 3152, 2869, +0, 3152, 2479, +0, 3283, 0, +0, 3416, 0, +2111, 3548, 0, +2877, 3680, 0, +3212, 3812, 0, +3453, 3944, 0, +3651, 4076, 0, +3828, 4095, 0, +0, 2880, 3152, +0, 2881, 3152, +0, 2881, 3152, +0, 2882, 3151, +0, 2883, 3151, +0, 2885, 3151, +0, 2886, 3151, +0, 2889, 3151, +0, 2892, 3151, +0, 2896, 3151, +0, 2902, 3151, +0, 2909, 3151, +0, 2919, 3151, +0, 2932, 3151, +0, 2948, 3151, +0, 2969, 3151, +0, 2995, 3151, +0, 3029, 3151, +0, 3070, 3151, +0, 3119, 3151, +0, 3151, 3123, +0, 3151, 3031, +0, 3151, 2869, +0, 3151, 2480, +0, 3283, 0, +0, 3416, 0, +2115, 3548, 0, +2878, 3680, 0, +3213, 3812, 0, +3453, 3944, 0, +3652, 4076, 0, +3828, 4095, 0, +0, 2879, 3152, +0, 2880, 3152, +0, 2880, 3152, +0, 2881, 3151, +0, 2883, 3151, +0, 2884, 3151, +0, 2886, 3151, +0, 2888, 3151, +0, 2891, 3151, +0, 2895, 3151, +0, 2901, 3151, +0, 2908, 3151, +0, 2918, 3151, +0, 2931, 3151, +0, 2947, 3151, +0, 2968, 3151, +0, 2995, 3151, +0, 3028, 3151, +0, 3069, 3151, +0, 3119, 3151, +0, 3151, 3123, +0, 3151, 3031, +0, 3151, 2869, +0, 3151, 2481, +0, 3283, 0, +0, 3416, 0, +2122, 3548, 0, +2879, 3680, 0, +3213, 3812, 0, +3453, 3944, 0, +3652, 4076, 0, +3828, 4095, 0, +0, 2878, 3152, +0, 2878, 3152, +0, 2879, 3152, +0, 2880, 3151, +0, 2881, 3151, +0, 2883, 3151, +0, 2885, 3151, +0, 2887, 3151, +0, 2890, 3151, +0, 2895, 3151, +0, 2900, 3151, +0, 2907, 3151, +0, 2917, 3151, +0, 2930, 3151, +0, 2946, 3151, +0, 2967, 3151, +0, 2994, 3151, +0, 3027, 3151, +0, 3068, 3151, +0, 3118, 3151, +0, 3151, 3124, +0, 3151, 3032, +0, 3151, 2870, +0, 3151, 2482, +0, 3283, 0, +0, 3416, 0, +2130, 3548, 0, +2881, 3680, 0, +3214, 3812, 0, +3454, 3944, 0, +3652, 4076, 0, +3829, 4095, 0, +0, 2876, 3152, +0, 2877, 3152, +0, 2877, 3152, +0, 2878, 3151, +0, 2879, 3151, +0, 2881, 3151, +0, 2883, 3151, +0, 2885, 3151, +0, 2889, 3151, +0, 2893, 3151, +0, 2898, 3151, +0, 2906, 3151, +0, 2916, 3151, +0, 2928, 3151, +0, 2945, 3151, +0, 2966, 3151, +0, 2993, 3151, +0, 3026, 3151, +0, 3067, 3151, +0, 3117, 3151, +0, 3151, 3124, +0, 3151, 3032, +0, 3151, 2871, +0, 3151, 2484, +0, 3283, 0, +0, 3415, 0, +2141, 3548, 0, +2883, 3680, 0, +3215, 3812, 0, +3454, 3944, 0, +3653, 4076, 0, +3829, 4095, 0, +0, 2873, 3152, +0, 2874, 3152, +0, 2875, 3152, +0, 2876, 3151, +0, 2877, 3151, +0, 2879, 3151, +0, 2881, 3151, +0, 2883, 3151, +0, 2887, 3151, +0, 2891, 3151, +0, 2896, 3151, +0, 2904, 3151, +0, 2914, 3151, +0, 2927, 3151, +0, 2943, 3151, +0, 2964, 3151, +0, 2991, 3151, +0, 3025, 3151, +0, 3066, 3151, +0, 3116, 3151, +0, 3151, 3125, +0, 3151, 3033, +0, 3151, 2872, +0, 3151, 2487, +0, 3283, 0, +0, 3415, 0, +2156, 3548, 0, +2886, 3680, 0, +3216, 3812, 0, +3455, 3944, 0, +3653, 4076, 0, +3829, 4095, 0, +0, 2870, 3152, +0, 2871, 3152, +0, 2871, 3152, +0, 2872, 3151, +0, 2873, 3151, +0, 2875, 3151, +0, 2877, 3151, +0, 2880, 3151, +0, 2884, 3151, +0, 2888, 3151, +0, 2894, 3151, +0, 2902, 3151, +0, 2911, 3151, +0, 2924, 3151, +0, 2941, 3151, +0, 2962, 3151, +0, 2989, 3151, +0, 3023, 3151, +0, 3064, 3151, +0, 3115, 3151, +0, 3151, 3126, +0, 3151, 3034, +0, 3151, 2873, +0, 3151, 2490, +0, 3283, 0, +0, 3415, 0, +2174, 3548, 0, +2890, 3680, 0, +3218, 3812, 0, +3456, 3944, 0, +3654, 4076, 0, +3830, 4095, 0, +0, 2866, 3152, +0, 2866, 3152, +0, 2867, 3152, +0, 2868, 3151, +0, 2869, 3151, +0, 2871, 3151, +0, 2873, 3151, +0, 2876, 3151, +0, 2880, 3151, +0, 2885, 3150, +0, 2891, 3150, +0, 2898, 3150, +0, 2908, 3150, +0, 2921, 3150, +0, 2938, 3150, +0, 2959, 3150, +0, 2986, 3150, +0, 3020, 3150, +0, 3062, 3150, +0, 3112, 3150, +0, 3150, 3127, +0, 3150, 3036, +0, 3150, 2875, +0, 3150, 2495, +0, 3282, 0, +0, 3415, 0, +2198, 3547, 0, +2895, 3680, 0, +3221, 3812, 0, +3458, 3944, 0, +3655, 4076, 0, +3830, 4095, 0, +0, 2860, 3152, +0, 2860, 3152, +0, 2861, 3152, +0, 2862, 3151, +0, 2863, 3151, +0, 2865, 3151, +0, 2867, 3151, +0, 2870, 3151, +0, 2874, 3151, +0, 2879, 3150, +0, 2886, 3150, +0, 2894, 3150, +0, 2904, 3150, +0, 2917, 3150, +0, 2933, 3150, +0, 2955, 3150, +0, 2982, 3150, +0, 3017, 3150, +0, 3059, 3150, +0, 3110, 3150, +0, 3150, 3128, +0, 3150, 3038, +0, 3150, 2878, +0, 3150, 2501, +0, 3282, 0, +0, 3414, 0, +2228, 3547, 0, +2901, 3679, 0, +3224, 3812, 0, +3459, 3944, 0, +3656, 4076, 0, +3831, 4095, 0, +0, 2851, 3152, +0, 2852, 3152, +0, 2853, 3152, +0, 2854, 3151, +0, 2855, 3151, +0, 2857, 3151, +0, 2859, 3151, +0, 2862, 3151, +0, 2866, 3151, +0, 2871, 3150, +0, 2878, 3150, +0, 2887, 3149, +0, 2898, 3149, +0, 2911, 3149, +0, 2928, 3149, +0, 2950, 3149, +0, 2977, 3149, +0, 3012, 3149, +0, 3055, 3149, +0, 3106, 3149, +0, 3149, 3131, +0, 3149, 3040, +0, 3149, 2881, +0, 3149, 2509, +0, 3281, 0, +0, 3414, 0, +2265, 3547, 0, +2910, 3679, 0, +3228, 3812, 0, +3462, 3944, 0, +3658, 4076, 0, +3832, 4095, 0, +0, 2840, 3152, +0, 2841, 3152, +0, 2842, 3152, +0, 2842, 3151, +0, 2844, 3151, +0, 2845, 3151, +0, 2848, 3151, +0, 2851, 3151, +0, 2855, 3151, +0, 2860, 3150, +0, 2868, 3150, +0, 2877, 3149, +0, 2889, 3148, +0, 2903, 3148, +0, 2920, 3148, +0, 2942, 3148, +0, 2970, 3148, +0, 3005, 3148, +0, 3049, 3148, +0, 3100, 3148, +0, 3148, 3133, +0, 3148, 3043, +0, 3148, 2886, +0, 3148, 2520, +0, 3280, 0, +0, 3414, 0, +2311, 3546, 0, +2922, 3679, 0, +3234, 3811, 0, +3466, 3944, 0, +3660, 4076, 0, +3834, 4095, 0, +0, 2825, 3152, +0, 2825, 3152, +0, 2826, 3152, +0, 2827, 3151, +0, 2829, 3151, +0, 2830, 3151, +0, 2833, 3151, +0, 2836, 3151, +0, 2840, 3151, +0, 2846, 3150, +0, 2853, 3150, +0, 2863, 3149, +0, 2875, 3148, +0, 2892, 3146, +0, 2910, 3146, +0, 2932, 3146, +0, 2961, 3146, +0, 2997, 3146, +0, 3041, 3146, +0, 3093, 3146, +0, 3146, 3137, +0, 3146, 3047, +0, 3146, 2892, +0, 3146, 2533, +0, 3280, 0, +0, 3413, 0, +2365, 3546, 0, +2936, 3678, 0, +3241, 3811, 0, +3470, 3943, 0, +3663, 4076, 0, +3836, 4095, 0, +0, 2803, 3152, +0, 2804, 3152, +0, 2805, 3152, +0, 2806, 3151, +0, 2807, 3151, +0, 2809, 3151, +0, 2812, 3151, +0, 2815, 3151, +0, 2819, 3151, +0, 2825, 3150, +0, 2833, 3150, +0, 2843, 3149, +0, 2856, 3148, +0, 2873, 3146, +0, 2895, 3144, +0, 2919, 3144, +0, 2948, 3144, +0, 2985, 3144, +0, 3030, 3144, +0, 3084, 3144, +0, 3144, 3141, +0, 3144, 3053, +0, 3144, 2901, +0, 3144, 2551, +0, 3278, 0, +0, 3412, 0, +2429, 3545, 0, +2955, 3678, 0, +3251, 3810, 0, +3476, 3943, 0, +3667, 4075, 0, +3838, 4095, 0, +0, 2773, 3152, +0, 2773, 3152, +0, 2774, 3152, +0, 2775, 3151, +0, 2777, 3151, +0, 2779, 3151, +0, 2782, 3151, +0, 2785, 3151, +0, 2790, 3151, +0, 2796, 3150, +0, 2804, 3150, +0, 2815, 3149, +0, 2829, 3148, +0, 2847, 3146, +0, 2870, 3144, +0, 2900, 3142, +0, 2931, 3142, +0, 2969, 3142, +0, 3015, 3142, +0, 3071, 3142, +0, 3136, 3142, +0, 3142, 3061, +0, 3142, 2911, +0, 3142, 2573, +0, 3276, 0, +0, 3410, 0, +2502, 3544, 0, +2980, 3677, 0, +3264, 3810, 0, +3484, 3943, 0, +3672, 4075, 0, +3842, 4095, 0, +0, 2729, 3152, +0, 2729, 3152, +0, 2730, 3152, +0, 2732, 3151, +0, 2733, 3151, +0, 2735, 3151, +0, 2738, 3151, +0, 2742, 3151, +0, 2747, 3151, +0, 2754, 3150, +0, 2763, 3150, +0, 2775, 3149, +0, 2790, 3148, +0, 2810, 3146, +0, 2835, 3144, +0, 2867, 3142, +0, 2906, 3138, +0, 2946, 3138, +0, 2995, 3138, +0, 3053, 3138, +0, 3120, 3138, +0, 3138, 3071, +0, 3138, 2925, +0, 3138, 2602, +0, 3274, 0, +0, 3408, 0, +2585, 3543, 0, +3010, 3676, 0, +3281, 3809, 0, +3494, 3942, 0, +3679, 4075, 0, +3847, 4095, 0, +0, 2662, 3152, +0, 2663, 3152, +0, 2664, 3152, +0, 2665, 3151, +0, 2667, 3151, +0, 2670, 3151, +0, 2673, 3151, +0, 2678, 3151, +0, 2684, 3151, +0, 2691, 3150, +0, 2702, 3150, +0, 2715, 3149, +0, 2733, 3148, +0, 2755, 3146, +0, 2783, 3144, +0, 2818, 3142, +0, 2861, 3138, +0, 2913, 3134, +0, 2965, 3134, +0, 3027, 3134, +0, 3098, 3134, +0, 3134, 3084, +0, 3134, 2943, +0, 3134, 2638, +0, 3270, 0, +1325, 3406, 0, +2676, 3541, 0, +3048, 3675, 0, +3302, 3808, 0, +3507, 3941, 0, +3688, 4074, 0, +3853, 4095, 0, +0, 2554, 3152, +0, 2555, 3152, +0, 2556, 3152, +0, 2558, 3151, +0, 2560, 3151, +0, 2564, 3151, +0, 2568, 3151, +0, 2573, 3151, +0, 2581, 3151, +0, 2591, 3150, +0, 2604, 3150, +0, 2620, 3149, +0, 2642, 3148, +0, 2669, 3146, +0, 2703, 3144, +0, 2744, 3142, +0, 2795, 3138, +0, 2854, 3134, +1137, 2923, 3128, +1137, 2991, 3128, +1137, 3067, 3128, +1137, 3128, 3101, +1137, 3128, 2965, +1137, 3128, 2681, +0, 3266, 1375, +2121, 3402, 0, +2775, 3538, 0, +3095, 3673, 0, +3329, 3807, 0, +3525, 3940, 0, +3700, 4073, 0, +3861, 4095, 0, +0, 2352, 3152, +0, 2353, 3152, +0, 2355, 3152, +0, 2358, 3151, +0, 2362, 3151, +0, 2367, 3151, +0, 2373, 3151, +0, 2382, 3151, +0, 2394, 3151, +0, 2408, 3150, +0, 2427, 3150, +0, 2452, 3149, +0, 2482, 3148, +0, 2521, 3146, +0, 2566, 3144, +0, 2622, 3142, +0, 2687, 3138, +0, 2761, 3134, +1137, 2845, 3128, +2061, 2936, 3119, +2061, 3022, 3119, +2061, 3116, 3119, +2061, 3119, 2995, +2061, 3119, 2734, +1272, 3259, 1899, +2458, 3398, 0, +2881, 3535, 0, +3150, 3670, 0, +3363, 3805, 0, +3547, 3939, 0, +3715, 4072, 0, +3872, 4095, 0, +0, 1720, 3152, +0, 1726, 3152, +0, 1735, 3152, +0, 1746, 3151, +0, 1760, 3151, +0, 1779, 3151, +0, 1802, 3151, +0, 1832, 3151, +0, 1869, 3151, +0, 1915, 3150, +0, 1969, 3150, +0, 2033, 3149, +0, 2106, 3148, +0, 2189, 3146, +0, 2280, 3144, +0, 2379, 3142, +0, 2484, 3138, +0, 2596, 3134, +1137, 2712, 3128, +2061, 2831, 3119, +2412, 2954, 3108, +2412, 3061, 3108, +2412, 3108, 3031, +2412, 3108, 2796, +2194, 3251, 2195, +2701, 3392, 1406, +2992, 3530, 0, +3215, 3667, 0, +3405, 3802, 0, +3575, 3937, 0, +3735, 4071, 0, +3886, 4095, 0, +0, 0, 3152, +0, 0, 3152, +0, 0, 3152, +0, 0, 3151, +0, 0, 3151, +0, 0, 3151, +0, 0, 3151, +0, 0, 3151, +0, 0, 3151, +0, 0, 3150, +0, 0, 3150, +0, 0, 3149, +0, 0, 3148, +0, 0, 3146, +0, 0, 3144, +0, 1068, 3142, +0, 1857, 3138, +0, 2195, 3134, +1137, 2436, 3128, +2061, 2636, 3119, +2412, 2813, 3108, +2658, 2976, 3092, +2658, 3092, 3074, +2658, 3092, 2867, +2642, 3239, 2544, +2900, 3383, 2326, +3108, 3524, 1536, +3289, 3662, 0, +3455, 3799, 0, +3611, 3934, 0, +3760, 4069, 0, +3904, 4095, 0, +0, 0, 3152, +0, 0, 3152, +0, 0, 3152, +0, 0, 3151, +0, 0, 3151, +0, 0, 3151, +0, 0, 3151, +0, 0, 3151, +0, 0, 3151, +0, 0, 3150, +0, 0, 3150, +0, 0, 3149, +0, 0, 3148, +0, 0, 3146, +0, 0, 3144, +0, 0, 3142, +0, 0, 3138, +1211, 0, 3134, +1758, 1137, 3128, +2061, 2064, 3119, +2412, 2511, 3108, +2658, 2787, 3092, +2860, 3003, 3069, +2860, 3069, 2948, +2918, 3223, 2790, +3077, 3372, 2676, +3227, 3515, 2457, +3373, 3656, 1663, +3515, 3794, 0, +3654, 3931, 0, +3791, 4066, 0, +3927, 4095, 0, +2478, 0, 3152, +2478, 0, 3152, +2479, 0, 3152, +2480, 0, 3151, +2481, 0, 3151, +2482, 0, 3151, +2484, 0, 3151, +2487, 0, 3151, +2490, 0, 3151, +2495, 0, 3150, +2501, 0, 3150, +2509, 0, 3149, +2520, 0, 3148, +2533, 0, 3146, +2551, 0, 3144, +2573, 0, 3142, +2602, 0, 3138, +2638, 0, 3134, +2681, 1137, 3128, +2734, 2061, 3119, +2796, 2412, 3108, +2867, 2658, 3092, +2948, 2860, 3069, +3038, 3038, 3038, +3135, 3201, 2992, +3239, 3356, 2922, +3350, 3504, 2808, +3465, 3648, 2590, +3584, 3788, 1799, +3706, 3926, 0, +3830, 4063, 0, +3956, 4095, 0, +2999, 0, 3284, +2999, 0, 3283, +2999, 0, 3283, +2999, 0, 3283, +3000, 0, 3283, +3000, 0, 3283, +3001, 0, 3283, +3002, 0, 3283, +3003, 0, 3283, +3005, 0, 3282, +3006, 0, 3282, +3009, 0, 3281, +3013, 0, 3280, +3017, 0, 3280, +3023, 0, 3278, +3032, 0, 3276, +3042, 0, 3274, +3056, 0, 3270, +3074, 0, 3266, +3097, 1272, 3259, +3126, 2194, 3251, +3162, 2544, 3239, +3206, 2790, 3223, +3201, 2992, 3135, +3201, 3080, 2992, +3356, 3338, 2922, +3457, 3504, 2808, +3550, 3648, 2590, +3651, 3788, 1799, +3758, 3926, 0, +3870, 4063, 0, +3987, 4095, 0, +3294, 0, 3416, +3294, 0, 3416, +3294, 0, 3416, +3294, 0, 3416, +3295, 0, 3416, +3295, 0, 3416, +3295, 0, 3415, +3296, 0, 3415, +3296, 0, 3415, +3297, 0, 3415, +3298, 0, 3414, +3299, 0, 3414, +3301, 0, 3414, +3304, 0, 3413, +3307, 0, 3412, +3311, 0, 3410, +3317, 0, 3408, +3325, 0, 3406, +3335, 0, 3402, +3348, 0, 3398, +3365, 1406, 3392, +3383, 2326, 3380, +3372, 2676, 3325, +3356, 2922, 3239, +3356, 2922, 3051, +3356, 3132, 2922, +3504, 3426, 2808, +3644, 3648, 2590, +3728, 3788, 1799, +3820, 3926, 0, +3919, 4063, 0, +4025, 4095, 0, +3519, 0, 3548, +3519, 0, 3548, +3519, 0, 3548, +3519, 0, 3548, +3519, 0, 3548, +3519, 0, 3548, +3519, 0, 3548, +3520, 0, 3548, +3520, 0, 3548, +3520, 0, 3547, +3521, 0, 3547, +3522, 0, 3547, +3523, 0, 3546, +3525, 0, 3546, +3526, 0, 3545, +3529, 0, 3544, +3533, 0, 3543, +3538, 0, 3541, +3538, 0, 3532, +3535, 0, 3516, +3530, 0, 3495, +3524, 1536, 3463, +3515, 2457, 3418, +3504, 2808, 3350, +3504, 2808, 3209, +3504, 2808, 2907, +3504, 3192, 2808, +3648, 3523, 2590, +3788, 3761, 1799, +3891, 3926, 0, +3977, 4063, 0, +4072, 4095, 0, +3680, 0, 3649, +3680, 0, 3649, +3680, 0, 3649, +3680, 0, 3649, +3680, 0, 3648, +3680, 0, 3648, +3680, 0, 3648, +3680, 0, 3648, +3680, 0, 3647, +3680, 0, 3646, +3679, 0, 3646, +3679, 0, 3644, +3679, 0, 3643, +3678, 0, 3641, +3678, 0, 3638, +3677, 0, 3634, +3676, 0, 3629, +3675, 0, 3622, +3673, 0, 3612, +3670, 0, 3599, +3667, 0, 3581, +3662, 0, 3555, +3656, 1663, 3519, +3648, 2590, 3465, +3648, 2590, 3360, +3648, 2590, 3165, +3648, 2590, 2592, +3648, 3262, 2590, +3788, 3626, 1799, +3926, 3877, 0, +4045, 4063, 0, +4095, 4095, 0, +3812, 0, 3732, +3812, 0, 3731, +3812, 0, 3731, +3812, 0, 3731, +3812, 0, 3731, +3812, 0, 3731, +3812, 0, 3731, +3812, 0, 3730, +3812, 0, 3730, +3812, 0, 3729, +3812, 0, 3729, +3812, 0, 3728, +3811, 0, 3727, +3811, 0, 3725, +3810, 0, 3722, +3810, 0, 3719, +3809, 0, 3715, +3808, 0, 3709, +3807, 0, 3701, +3805, 0, 3690, +3802, 0, 3676, +3799, 0, 3655, +3794, 0, 3626, +3788, 1799, 3584, +3788, 1799, 3505, +3788, 1799, 3372, +3788, 1799, 3097, +3788, 2422, 1799, +3788, 3342, 1799, +3926, 3735, 0, +4063, 3995, 0, +4095, 4095, 0, +3944, 0, 3823, +3944, 0, 3823, +3944, 0, 3823, +3944, 0, 3822, +3944, 0, 3822, +3944, 0, 3822, +3944, 0, 3822, +3944, 0, 3822, +3944, 0, 3822, +3944, 0, 3821, +3944, 0, 3820, +3944, 0, 3820, +3944, 0, 3819, +3943, 0, 3817, +3943, 0, 3815, +3943, 0, 3813, +3942, 0, 3809, +3941, 0, 3805, +3940, 0, 3798, +3939, 0, 3790, +3937, 0, 3777, +3934, 0, 3761, +3931, 0, 3738, +3926, 0, 3706, +3926, 0, 3647, +3926, 0, 3553, +3926, 0, 3388, +3926, 0, 2988, +3926, 2023, 0, +3926, 3430, 0, +4063, 3849, 0, +4095, 4095, 0, +4076, 0, 3922, +4076, 0, 3922, +4076, 0, 3921, +4076, 0, 3921, +4076, 0, 3921, +4076, 0, 3921, +4076, 0, 3921, +4076, 0, 3921, +4076, 0, 3921, +4076, 0, 3921, +4076, 0, 3920, +4076, 0, 3919, +4076, 0, 3918, +4076, 0, 3917, +4075, 0, 3916, +4075, 0, 3913, +4075, 0, 3911, +4074, 0, 3907, +4073, 0, 3902, +4072, 0, 3895, +4071, 0, 3886, +4069, 0, 3873, +4066, 0, 3855, +4063, 0, 3830, +4063, 0, 3786, +4063, 0, 3719, +4063, 0, 3611, +4063, 0, 3409, +4063, 0, 2781, +4063, 0, 0, +4063, 3527, 0, +4095, 3968, 0, +4095, 0, 4027, +4095, 0, 4027, +4095, 0, 4027, +4095, 0, 4027, +4095, 0, 4027, +4095, 0, 4027, +4095, 0, 4027, +4095, 0, 4027, +4095, 0, 4027, +4095, 0, 4026, +4095, 0, 4026, +4095, 0, 4026, +4095, 0, 4025, +4095, 0, 4024, +4095, 0, 4023, +4095, 0, 4021, +4095, 0, 4019, +4095, 0, 4016, +4095, 0, 4012, +4095, 0, 4006, +4095, 0, 3999, +4095, 0, 3989, +4095, 0, 3976, +4095, 0, 3956, +4095, 0, 3923, +4095, 0, 3875, +4095, 0, 3801, +4095, 0, 3679, +4095, 0, 3436, +4095, 0, 2137, +4095, 0, 0, +4095, 3630, 0, +0, 3014, 3284, +0, 3014, 3284, +0, 3014, 3284, +0, 3015, 3284, +0, 3016, 3284, +0, 3017, 3284, +0, 3018, 3284, +0, 3020, 3284, +0, 3022, 3284, +0, 3025, 3284, +0, 3030, 3284, +0, 3035, 3284, +0, 3043, 3284, +0, 3052, 3284, +0, 3065, 3284, +0, 3081, 3284, +0, 3102, 3284, +0, 3128, 3284, +0, 3162, 3284, +0, 3203, 3284, +0, 3252, 3284, +0, 3284, 3254, +0, 3284, 3162, +0, 3284, 2999, +0, 3284, 2609, +0, 3416, 0, +0, 3548, 0, +2237, 3680, 0, +3008, 3812, 0, +3344, 3944, 0, +3584, 4076, 0, +3784, 4095, 0, +0, 3014, 3284, +0, 3014, 3283, +0, 3014, 3283, +0, 3015, 3283, +0, 3016, 3283, +0, 3017, 3283, +0, 3018, 3283, +0, 3020, 3283, +0, 3022, 3283, +0, 3025, 3283, +0, 3029, 3283, +0, 3035, 3283, +0, 3042, 3283, +0, 3052, 3283, +0, 3065, 3283, +0, 3081, 3283, +0, 3102, 3283, +0, 3128, 3283, +0, 3162, 3283, +0, 3203, 3283, +0, 3252, 3283, +0, 3283, 3254, +0, 3283, 3162, +0, 3283, 2999, +0, 3283, 2609, +0, 3416, 0, +0, 3548, 0, +2239, 3680, 0, +3009, 3812, 0, +3344, 3944, 0, +3584, 4076, 0, +3784, 4095, 0, +0, 3013, 3284, +0, 3014, 3283, +0, 3014, 3283, +0, 3014, 3283, +0, 3015, 3283, +0, 3016, 3283, +0, 3018, 3283, +0, 3019, 3283, +0, 3022, 3283, +0, 3025, 3283, +0, 3029, 3283, +0, 3035, 3283, +0, 3042, 3283, +0, 3052, 3283, +0, 3064, 3283, +0, 3081, 3283, +0, 3101, 3283, +0, 3128, 3283, +0, 3161, 3283, +0, 3202, 3283, +0, 3252, 3283, +0, 3283, 3255, +0, 3283, 3163, +0, 3283, 2999, +0, 3283, 2610, +0, 3416, 0, +0, 3548, 0, +2242, 3680, 0, +3009, 3812, 0, +3344, 3944, 0, +3585, 4076, 0, +3784, 4095, 0, +0, 3012, 3284, +0, 3013, 3283, +0, 3013, 3283, +0, 3014, 3283, +0, 3015, 3283, +0, 3016, 3283, +0, 3017, 3283, +0, 3019, 3283, +0, 3021, 3283, +0, 3025, 3283, +0, 3029, 3283, +0, 3034, 3283, +0, 3042, 3283, +0, 3051, 3283, +0, 3064, 3283, +0, 3080, 3283, +0, 3101, 3283, +0, 3128, 3283, +0, 3161, 3283, +0, 3202, 3283, +0, 3252, 3283, +0, 3283, 3255, +0, 3283, 3163, +0, 3283, 2999, +0, 3283, 2611, +0, 3416, 0, +0, 3548, 0, +2246, 3680, 0, +3010, 3812, 0, +3344, 3944, 0, +3585, 4076, 0, +3784, 4095, 0, +0, 3012, 3284, +0, 3012, 3283, +0, 3013, 3283, +0, 3013, 3283, +0, 3014, 3283, +0, 3015, 3283, +0, 3016, 3283, +0, 3018, 3283, +0, 3021, 3283, +0, 3024, 3283, +0, 3028, 3283, +0, 3034, 3283, +0, 3041, 3283, +0, 3051, 3283, +0, 3063, 3283, +0, 3080, 3283, +0, 3101, 3283, +0, 3127, 3283, +0, 3160, 3283, +0, 3201, 3283, +0, 3251, 3283, +0, 3283, 3255, +0, 3283, 3163, +0, 3283, 3000, +0, 3283, 2612, +0, 3416, 0, +0, 3548, 0, +2251, 3680, 0, +3011, 3812, 0, +3345, 3944, 0, +3585, 4076, 0, +3784, 4095, 0, +0, 3011, 3284, +0, 3011, 3283, +0, 3011, 3283, +0, 3012, 3283, +0, 3013, 3283, +0, 3014, 3283, +0, 3016, 3283, +0, 3018, 3283, +0, 3020, 3283, +0, 3023, 3283, +0, 3027, 3283, +0, 3033, 3283, +0, 3040, 3283, +0, 3050, 3283, +0, 3062, 3283, +0, 3079, 3283, +0, 3100, 3283, +0, 3127, 3283, +0, 3160, 3283, +0, 3201, 3283, +0, 3251, 3283, +0, 3283, 3255, +0, 3283, 3163, +0, 3283, 3000, +0, 3283, 2613, +0, 3416, 0, +0, 3548, 0, +2257, 3680, 0, +3012, 3812, 0, +3346, 3944, 0, +3585, 4076, 0, +3784, 4095, 0, +0, 3009, 3284, +0, 3010, 3283, +0, 3010, 3283, +0, 3011, 3283, +0, 3012, 3283, +0, 3013, 3283, +0, 3015, 3283, +0, 3016, 3283, +0, 3019, 3283, +0, 3022, 3283, +0, 3026, 3283, +0, 3032, 3283, +0, 3039, 3283, +0, 3049, 3283, +0, 3062, 3283, +0, 3078, 3283, +0, 3099, 3283, +0, 3126, 3283, +0, 3159, 3283, +0, 3200, 3283, +0, 3250, 3283, +0, 3283, 3256, +0, 3283, 3164, +0, 3283, 3001, +0, 3283, 2614, +0, 3415, 0, +0, 3548, 0, +2266, 3680, 0, +3014, 3812, 0, +3346, 3944, 0, +3586, 4076, 0, +3784, 4095, 0, +0, 3008, 3284, +0, 3008, 3283, +0, 3008, 3283, +0, 3009, 3283, +0, 3010, 3283, +0, 3011, 3283, +0, 3013, 3283, +0, 3015, 3283, +0, 3017, 3283, +0, 3021, 3283, +0, 3025, 3283, +0, 3031, 3283, +0, 3038, 3283, +0, 3047, 3283, +0, 3060, 3283, +0, 3077, 3283, +0, 3098, 3283, +0, 3125, 3283, +0, 3158, 3283, +0, 3199, 3283, +0, 3249, 3283, +0, 3283, 3256, +0, 3283, 3164, +0, 3283, 3002, +0, 3283, 2616, +0, 3415, 0, +0, 3548, 0, +2277, 3680, 0, +3016, 3812, 0, +3347, 3944, 0, +3586, 4076, 0, +3785, 4095, 0, +0, 3005, 3284, +0, 3005, 3283, +0, 3006, 3283, +0, 3007, 3283, +0, 3008, 3283, +0, 3009, 3283, +0, 3010, 3283, +0, 3013, 3283, +0, 3015, 3283, +0, 3018, 3283, +0, 3023, 3283, +0, 3029, 3283, +0, 3036, 3283, +0, 3046, 3283, +0, 3059, 3283, +0, 3075, 3283, +0, 3096, 3283, +0, 3123, 3283, +0, 3157, 3283, +0, 3198, 3283, +0, 3248, 3283, +0, 3283, 3257, +0, 3283, 3165, +0, 3283, 3003, +0, 3283, 2619, +0, 3415, 0, +0, 3548, 0, +2291, 3680, 0, +3019, 3812, 0, +3349, 3944, 0, +3587, 4076, 0, +3786, 4095, 0, +0, 3002, 3284, +0, 3002, 3283, +0, 3002, 3283, +0, 3003, 3283, +0, 3004, 3283, +0, 3005, 3283, +0, 3007, 3283, +0, 3009, 3283, +0, 3012, 3283, +0, 3016, 3282, +0, 3020, 3282, +0, 3026, 3282, +0, 3033, 3282, +0, 3043, 3282, +0, 3056, 3282, +0, 3073, 3282, +0, 3094, 3282, +0, 3121, 3282, +0, 3155, 3282, +0, 3196, 3282, +0, 3247, 3282, +0, 3282, 3257, +0, 3282, 3166, +0, 3282, 3005, +0, 3282, 2622, +0, 3415, 0, +0, 3547, 0, +2310, 3680, 0, +3023, 3812, 0, +3351, 3944, 0, +3588, 4076, 0, +3786, 4095, 0, +0, 2997, 3284, +0, 2998, 3283, +0, 2998, 3283, +0, 2999, 3283, +0, 3000, 3283, +0, 3001, 3283, +0, 3003, 3283, +0, 3005, 3283, +0, 3008, 3283, +0, 3012, 3282, +0, 3017, 3282, +0, 3023, 3282, +0, 3030, 3282, +0, 3040, 3282, +0, 3053, 3282, +0, 3070, 3282, +0, 3091, 3282, +0, 3118, 3282, +0, 3152, 3282, +0, 3194, 3282, +0, 3244, 3282, +0, 3282, 3259, +0, 3282, 3168, +0, 3282, 3006, +0, 3282, 2627, +0, 3414, 0, +0, 3547, 0, +2333, 3679, 0, +3027, 3812, 0, +3353, 3944, 0, +3590, 4076, 0, +3787, 4095, 0, +0, 2991, 3284, +0, 2992, 3283, +0, 2992, 3283, +0, 2993, 3283, +0, 2994, 3283, +0, 2995, 3283, +0, 2997, 3283, +0, 2999, 3283, +0, 3002, 3283, +0, 3006, 3282, +0, 3011, 3282, +0, 3018, 3281, +0, 3025, 3281, +0, 3035, 3281, +0, 3049, 3281, +0, 3065, 3281, +0, 3087, 3281, +0, 3114, 3281, +0, 3149, 3281, +0, 3191, 3281, +0, 3242, 3281, +0, 3281, 3260, +0, 3281, 3169, +0, 3281, 3009, +0, 3281, 2633, +0, 3414, 0, +0, 3547, 0, +2363, 3679, 0, +3034, 3812, 0, +3356, 3944, 0, +3592, 4076, 0, +3788, 4095, 0, +0, 2983, 3284, +0, 2983, 3283, +0, 2984, 3283, +0, 2985, 3283, +0, 2986, 3283, +0, 2987, 3283, +0, 2988, 3283, +0, 2991, 3283, +0, 2994, 3283, +0, 2998, 3282, +0, 3003, 3282, +0, 3010, 3281, +0, 3019, 3280, +0, 3029, 3280, +0, 3043, 3280, +0, 3060, 3280, +0, 3082, 3280, +0, 3109, 3280, +0, 3144, 3280, +0, 3186, 3280, +0, 3238, 3280, +0, 3280, 3262, +0, 3280, 3172, +0, 3280, 3013, +0, 3280, 2641, +0, 3414, 0, +0, 3546, 0, +2400, 3679, 0, +3043, 3811, 0, +3361, 3944, 0, +3594, 4076, 0, +3790, 4095, 0, +0, 2972, 3284, +0, 2972, 3283, +0, 2973, 3283, +0, 2973, 3283, +0, 2974, 3283, +0, 2976, 3283, +0, 2977, 3283, +0, 2980, 3283, +0, 2983, 3283, +0, 2987, 3282, +0, 2992, 3282, +0, 2999, 3281, +0, 3009, 3280, +0, 3021, 3280, +0, 3034, 3280, +0, 3052, 3280, +0, 3074, 3280, +0, 3102, 3280, +0, 3138, 3280, +0, 3180, 3280, +0, 3233, 3280, +0, 3280, 3265, +0, 3280, 3175, +0, 3280, 3017, +0, 3280, 2651, +0, 3413, 0, +0, 3546, 0, +2445, 3678, 0, +3054, 3811, 0, +3366, 3943, 0, +3597, 4076, 0, +3792, 4095, 0, +0, 2956, 3284, +0, 2957, 3283, +0, 2957, 3283, +0, 2958, 3283, +0, 2959, 3283, +0, 2960, 3283, +0, 2962, 3283, +0, 2965, 3283, +0, 2968, 3283, +0, 2972, 3282, +0, 2977, 3282, +0, 2985, 3281, +0, 2995, 3280, +0, 3007, 3280, +0, 3024, 3278, +0, 3041, 3278, +0, 3064, 3278, +0, 3093, 3278, +0, 3129, 3278, +0, 3173, 3278, +0, 3225, 3278, +0, 3278, 3269, +0, 3278, 3180, +0, 3278, 3023, +0, 3278, 2665, +0, 3412, 0, +0, 3545, 0, +2499, 3678, 0, +3069, 3810, 0, +3374, 3943, 0, +3602, 4075, 0, +3795, 4095, 0, +0, 2935, 3284, +0, 2935, 3283, +0, 2936, 3283, +0, 2936, 3283, +0, 2938, 3283, +0, 2939, 3283, +0, 2941, 3283, +0, 2943, 3283, +0, 2947, 3283, +0, 2951, 3282, +0, 2957, 3282, +0, 2965, 3281, +0, 2975, 3280, +0, 2988, 3280, +0, 3005, 3278, +0, 3027, 3276, +0, 3050, 3276, +0, 3080, 3276, +0, 3117, 3276, +0, 3162, 3276, +0, 3216, 3276, +0, 3276, 3273, +0, 3276, 3185, +0, 3276, 3032, +0, 3276, 2683, +0, 3410, 0, +0, 3544, 0, +2562, 3677, 0, +3088, 3810, 0, +3384, 3943, 0, +3608, 4075, 0, +3799, 4095, 0, +0, 2904, 3284, +0, 2905, 3283, +0, 2905, 3283, +0, 2906, 3283, +0, 2907, 3283, +0, 2909, 3283, +0, 2911, 3283, +0, 2914, 3283, +0, 2917, 3283, +0, 2922, 3282, +0, 2928, 3282, +0, 2936, 3281, +0, 2947, 3280, +0, 2961, 3280, +0, 2979, 3278, +0, 3002, 3276, +0, 3031, 3274, +0, 3062, 3274, +0, 3100, 3274, +0, 3147, 3274, +0, 3203, 3274, +0, 3268, 3274, +0, 3274, 3193, +0, 3274, 3042, +0, 3274, 2706, +0, 3408, 0, +0, 3543, 0, +2636, 3676, 0, +3112, 3809, 0, +3396, 3942, 0, +3616, 4075, 0, +3804, 4095, 0, +0, 2860, 3284, +0, 2860, 3283, +0, 2861, 3283, +0, 2862, 3283, +0, 2863, 3283, +0, 2865, 3283, +0, 2867, 3283, +0, 2870, 3283, +0, 2874, 3283, +0, 2879, 3282, +0, 2886, 3282, +0, 2895, 3281, +0, 2907, 3280, +0, 2922, 3280, +0, 2942, 3278, +0, 2967, 3276, +0, 2998, 3274, +0, 3037, 3270, +0, 3078, 3270, +0, 3126, 3270, +0, 3184, 3270, +0, 3252, 3270, +0, 3270, 3203, +0, 3270, 3056, +0, 3270, 2734, +0, 3406, 0, +0, 3541, 0, +2718, 3675, 0, +3143, 3808, 0, +3413, 3941, 0, +3626, 4074, 0, +3811, 4095, 0, +0, 2793, 3284, +0, 2793, 3283, +0, 2794, 3283, +0, 2795, 3283, +0, 2797, 3283, +0, 2799, 3283, +0, 2801, 3283, +0, 2805, 3283, +0, 2809, 3283, +0, 2815, 3282, +0, 2823, 3282, +0, 2833, 3281, +0, 2847, 3280, +0, 2865, 3280, +0, 2886, 3278, +0, 2915, 3276, +0, 2950, 3274, +0, 2993, 3270, +0, 3045, 3266, +0, 3097, 3266, +0, 3159, 3266, +0, 3230, 3266, +0, 3266, 3216, +0, 3266, 3074, +0, 3266, 2770, +0, 3402, 0, +1477, 3538, 0, +2809, 3673, 0, +3181, 3807, 0, +3434, 3940, 0, +3640, 4073, 0, +3820, 4095, 0, +0, 2684, 3284, +0, 2685, 3283, +0, 2686, 3283, +0, 2688, 3283, +0, 2690, 3283, +0, 2692, 3283, +0, 2695, 3283, +0, 2700, 3283, +0, 2705, 3283, +0, 2713, 3282, +0, 2723, 3282, +0, 2735, 3281, +0, 2752, 3280, +0, 2773, 3280, +0, 2800, 3278, +0, 2834, 3276, +0, 2876, 3274, +0, 2926, 3270, +0, 2986, 3266, +1272, 3055, 3259, +1272, 3122, 3259, +1272, 3199, 3259, +1272, 3259, 3233, +1272, 3259, 3097, +1272, 3259, 2813, +0, 3398, 1484, +2256, 3535, 0, +2908, 3670, 0, +3227, 3805, 0, +3461, 3939, 0, +3657, 4072, 0, +3832, 4095, 0, +0, 2481, 3284, +0, 2482, 3283, +0, 2484, 3283, +0, 2486, 3283, +0, 2489, 3283, +0, 2493, 3283, +0, 2498, 3283, +0, 2504, 3283, +0, 2513, 3283, +0, 2524, 3282, +0, 2539, 3282, +0, 2558, 3281, +0, 2583, 3280, +0, 2613, 3280, +0, 2651, 3278, +0, 2698, 3276, +0, 2753, 3274, +0, 2818, 3270, +0, 2893, 3266, +1272, 2976, 3259, +2194, 3069, 3251, +2194, 3154, 3251, +2194, 3248, 3251, +2194, 3251, 3126, +2194, 3251, 2866, +1406, 3392, 2025, +2593, 3530, 0, +3014, 3667, 0, +3282, 3802, 0, +3495, 3937, 0, +3679, 4071, 0, +3847, 4095, 0, +0, 1844, 3284, +0, 1849, 3283, +0, 1856, 3283, +0, 1864, 3283, +0, 1875, 3283, +0, 1890, 3283, +0, 1908, 3283, +0, 1932, 3283, +0, 1962, 3283, +0, 1999, 3282, +0, 2045, 3282, +0, 2100, 3281, +0, 2164, 3280, +0, 2237, 3280, +0, 2320, 3278, +0, 2411, 3276, +0, 2510, 3274, +0, 2616, 3270, +0, 2727, 3266, +1272, 2843, 3259, +2194, 2963, 3251, +2544, 3085, 3239, +2544, 3193, 3239, +2544, 3239, 3162, +2544, 3239, 2928, +2328, 3383, 2326, +2833, 3524, 1536, +3125, 3662, 0, +3347, 3799, 0, +3537, 3934, 0, +3708, 4069, 0, +3867, 4095, 0, +0, 0, 3284, +0, 0, 3283, +0, 0, 3283, +0, 0, 3283, +0, 0, 3283, +0, 0, 3283, +0, 0, 3283, +0, 0, 3283, +0, 0, 3283, +0, 0, 3282, +0, 0, 3282, +0, 0, 3281, +0, 0, 3280, +0, 0, 3280, +0, 0, 3278, +0, 0, 3276, +0, 1202, 3274, +0, 1990, 3270, +0, 2327, 3266, +1272, 2569, 3259, +2194, 2768, 3251, +2544, 2945, 3239, +2790, 3107, 3223, +2790, 3223, 3206, +2790, 3223, 2999, +2774, 3372, 2676, +3032, 3515, 2457, +3240, 3656, 1663, +3421, 3794, 0, +3587, 3931, 0, +3743, 4066, 0, +3892, 4095, 0, +0, 0, 3284, +0, 0, 3283, +0, 0, 3283, +0, 0, 3283, +0, 0, 3283, +0, 0, 3283, +0, 0, 3283, +0, 0, 3283, +0, 0, 3283, +0, 0, 3282, +0, 0, 3282, +0, 0, 3281, +0, 0, 3280, +0, 0, 3280, +0, 0, 3278, +0, 0, 3276, +0, 0, 3274, +0, 0, 3270, +1375, 0, 3266, +1899, 1272, 3259, +2195, 2194, 3251, +2544, 2642, 3239, +2790, 2918, 3223, +2992, 3135, 3201, +2992, 3201, 3080, +3051, 3356, 2922, +3209, 3504, 2808, +3360, 3648, 2590, +3505, 3788, 1799, +3647, 3926, 0, +3786, 4063, 0, +3923, 4095, 0, +2609, 0, 3284, +2609, 0, 3283, +2610, 0, 3283, +2611, 0, 3283, +2612, 0, 3283, +2613, 0, 3283, +2614, 0, 3283, +2616, 0, 3283, +2619, 0, 3283, +2622, 0, 3282, +2627, 0, 3282, +2633, 0, 3281, +2641, 0, 3280, +2651, 0, 3280, +2665, 0, 3278, +2683, 0, 3276, +2706, 0, 3274, +2734, 0, 3270, +2770, 0, 3266, +2813, 1272, 3259, +2866, 2194, 3251, +2928, 2544, 3239, +2999, 2790, 3223, +3080, 2992, 3201, +3170, 3170, 3170, +3267, 3333, 3124, +3372, 3488, 3054, +3482, 3636, 2940, +3597, 3780, 2721, +3716, 3920, 1928, +3838, 4058, 0, +3962, 4095, 0, +3132, 0, 3416, +3132, 0, 3416, +3132, 0, 3416, +3132, 0, 3416, +3132, 0, 3416, +3133, 0, 3416, +3133, 0, 3415, +3134, 0, 3415, +3135, 0, 3415, +3136, 0, 3415, +3137, 0, 3414, +3139, 0, 3414, +3142, 0, 3414, +3145, 0, 3413, +3150, 0, 3412, +3156, 0, 3410, +3164, 0, 3408, +3175, 0, 3406, +3189, 0, 3402, +3206, 0, 3398, +3230, 1406, 3392, +3258, 2326, 3383, +3294, 2676, 3372, +3338, 2922, 3356, +3333, 3124, 3267, +3333, 3212, 3124, +3488, 3470, 3054, +3589, 3636, 2940, +3682, 3780, 2721, +3783, 3920, 1928, +3890, 4058, 0, +4002, 4095, 0, +3426, 0, 3548, +3426, 0, 3548, +3427, 0, 3548, +3427, 0, 3548, +3427, 0, 3548, +3427, 0, 3548, +3427, 0, 3548, +3428, 0, 3548, +3428, 0, 3548, +3429, 0, 3547, +3429, 0, 3547, +3430, 0, 3547, +3432, 0, 3546, +3434, 0, 3546, +3436, 0, 3545, +3440, 0, 3544, +3444, 0, 3543, +3450, 0, 3541, +3457, 0, 3538, +3467, 0, 3535, +3480, 0, 3530, +3497, 1536, 3524, +3515, 2457, 3512, +3504, 2808, 3457, +3488, 3054, 3372, +3488, 3054, 3183, +3488, 3264, 3054, +3636, 3558, 2940, +3776, 3780, 2721, +3860, 3920, 1928, +3952, 4058, 0, +4051, 4095, 0, +3651, 0, 3680, +3651, 0, 3680, +3651, 0, 3680, +3651, 0, 3680, +3651, 0, 3680, +3651, 0, 3680, +3651, 0, 3680, +3652, 0, 3680, +3652, 0, 3680, +3652, 0, 3680, +3653, 0, 3679, +3653, 0, 3679, +3654, 0, 3679, +3655, 0, 3678, +3657, 0, 3678, +3659, 0, 3677, +3662, 0, 3676, +3665, 0, 3675, +3670, 0, 3673, +3670, 0, 3664, +3667, 0, 3648, +3662, 0, 3626, +3656, 1663, 3595, +3648, 2590, 3550, +3636, 2940, 3482, +3636, 2940, 3341, +3636, 2940, 3038, +3636, 3324, 2940, +3780, 3655, 2721, +3920, 3893, 1928, +4023, 4058, 0, +4095, 4095, 0, +3812, 0, 3781, +3812, 0, 3781, +3812, 0, 3781, +3812, 0, 3781, +3812, 0, 3781, +3812, 0, 3781, +3812, 0, 3781, +3812, 0, 3780, +3812, 0, 3780, +3812, 0, 3779, +3812, 0, 3778, +3812, 0, 3777, +3811, 0, 3777, +3811, 0, 3775, +3810, 0, 3773, +3810, 0, 3770, +3809, 0, 3766, +3808, 0, 3761, +3807, 0, 3754, +3805, 0, 3744, +3802, 0, 3731, +3799, 0, 3713, +3794, 0, 3687, +3788, 1799, 3651, +3780, 2721, 3597, +3780, 2721, 3492, +3780, 2721, 3296, +3780, 2721, 2722, +3780, 3394, 2721, +3920, 3758, 1928, +4058, 4008, 0, +4095, 4095, 0, +3944, 0, 3864, +3944, 0, 3864, +3944, 0, 3863, +3944, 0, 3863, +3944, 0, 3863, +3944, 0, 3863, +3944, 0, 3863, +3944, 0, 3863, +3944, 0, 3863, +3944, 0, 3862, +3944, 0, 3862, +3944, 0, 3861, +3944, 0, 3860, +3943, 0, 3859, +3943, 0, 3857, +3943, 0, 3854, +3942, 0, 3851, +3941, 0, 3847, +3940, 0, 3841, +3939, 0, 3833, +3937, 0, 3822, +3934, 0, 3808, +3931, 0, 3787, +3926, 0, 3758, +3920, 1928, 3716, +3920, 1928, 3637, +3920, 1928, 3504, +3920, 1928, 3229, +3920, 2556, 1928, +3920, 3474, 1928, +4058, 3867, 0, +4095, 4095, 0, +4076, 0, 3955, +4076, 0, 3955, +4076, 0, 3955, +4076, 0, 3955, +4076, 0, 3955, +4076, 0, 3954, +4076, 0, 3954, +4076, 0, 3954, +4076, 0, 3954, +4076, 0, 3953, +4076, 0, 3953, +4076, 0, 3953, +4076, 0, 3952, +4076, 0, 3950, +4075, 0, 3949, +4075, 0, 3947, +4075, 0, 3945, +4074, 0, 3941, +4073, 0, 3937, +4072, 0, 3930, +4071, 0, 3921, +4069, 0, 3910, +4066, 0, 3893, +4063, 0, 3870, +4058, 0, 3838, +4058, 0, 3779, +4058, 0, 3685, +4058, 0, 3520, +4058, 0, 3119, +4058, 2157, 0, +4058, 3562, 0, +4095, 3982, 0, +4095, 0, 4054, +4095, 0, 4054, +4095, 0, 4054, +4095, 0, 4054, +4095, 0, 4054, +4095, 0, 4054, +4095, 0, 4054, +4095, 0, 4053, +4095, 0, 4053, +4095, 0, 4053, +4095, 0, 4053, +4095, 0, 4052, +4095, 0, 4051, +4095, 0, 4051, +4095, 0, 4049, +4095, 0, 4048, +4095, 0, 4046, +4095, 0, 4043, +4095, 0, 4039, +4095, 0, 4034, +4095, 0, 4027, +4095, 0, 4018, +4095, 0, 4005, +4095, 0, 3987, +4095, 0, 3962, +4095, 0, 3918, +4095, 0, 3851, +4095, 0, 3743, +4095, 0, 3541, +4095, 0, 2915, +4095, 0, 0, +4095, 3659, 0, +0, 3146, 3416, +0, 3146, 3416, +0, 3147, 3416, +0, 3147, 3416, +0, 3147, 3416, +0, 3148, 3416, +0, 3149, 3416, +0, 3151, 3416, +0, 3152, 3416, +0, 3155, 3416, +0, 3158, 3416, +0, 3162, 3416, +0, 3168, 3416, +0, 3175, 3416, +0, 3184, 3416, +0, 3197, 3416, +0, 3213, 3416, +0, 3234, 3416, +0, 3261, 3416, +0, 3294, 3416, +0, 3335, 3416, +0, 3385, 3416, +0, 3416, 3387, +0, 3416, 3294, +0, 3416, 3132, +0, 3416, 2741, +0, 3548, 0, +0, 3680, 0, +2367, 3812, 0, +3140, 3944, 0, +3475, 4076, 0, +3716, 4095, 0, +0, 3146, 3416, +0, 3146, 3416, +0, 3146, 3416, +0, 3147, 3416, +0, 3147, 3416, +0, 3148, 3416, +0, 3149, 3416, +0, 3151, 3416, +0, 3152, 3416, +0, 3154, 3416, +0, 3158, 3416, +0, 3162, 3416, +0, 3168, 3416, +0, 3175, 3416, +0, 3184, 3416, +0, 3197, 3416, +0, 3213, 3416, +0, 3234, 3416, +0, 3261, 3416, +0, 3294, 3416, +0, 3335, 3416, +0, 3385, 3416, +0, 3416, 3387, +0, 3416, 3294, +0, 3416, 3132, +0, 3416, 2741, +0, 3548, 0, +0, 3680, 0, +2369, 3812, 0, +3140, 3944, 0, +3475, 4076, 0, +3717, 4095, 0, +0, 3145, 3416, +0, 3146, 3416, +0, 3146, 3416, +0, 3147, 3416, +0, 3147, 3416, +0, 3148, 3416, +0, 3149, 3416, +0, 3150, 3416, +0, 3152, 3416, +0, 3154, 3416, +0, 3157, 3416, +0, 3162, 3416, +0, 3167, 3416, +0, 3175, 3416, +0, 3184, 3416, +0, 3197, 3416, +0, 3213, 3416, +0, 3234, 3416, +0, 3260, 3416, +0, 3294, 3416, +0, 3335, 3416, +0, 3384, 3416, +0, 3416, 3387, +0, 3416, 3294, +0, 3416, 3132, +0, 3416, 2742, +0, 3548, 0, +0, 3680, 0, +2371, 3812, 0, +3140, 3944, 0, +3476, 4076, 0, +3717, 4095, 0, +0, 3145, 3416, +0, 3145, 3416, +0, 3146, 3416, +0, 3146, 3416, +0, 3147, 3416, +0, 3147, 3416, +0, 3148, 3416, +0, 3150, 3416, +0, 3151, 3416, +0, 3154, 3416, +0, 3157, 3416, +0, 3161, 3416, +0, 3167, 3416, +0, 3174, 3416, +0, 3184, 3416, +0, 3196, 3416, +0, 3213, 3416, +0, 3234, 3416, +0, 3260, 3416, +0, 3293, 3416, +0, 3335, 3416, +0, 3384, 3416, +0, 3416, 3387, +0, 3416, 3294, +0, 3416, 3132, +0, 3416, 2742, +0, 3548, 0, +0, 3680, 0, +2374, 3812, 0, +3141, 3944, 0, +3476, 4076, 0, +3717, 4095, 0, +0, 3144, 3416, +0, 3145, 3416, +0, 3145, 3416, +0, 3146, 3416, +0, 3146, 3416, +0, 3147, 3416, +0, 3148, 3416, +0, 3149, 3416, +0, 3151, 3416, +0, 3154, 3416, +0, 3157, 3416, +0, 3161, 3416, +0, 3166, 3416, +0, 3174, 3416, +0, 3184, 3416, +0, 3196, 3416, +0, 3212, 3416, +0, 3233, 3416, +0, 3260, 3416, +0, 3293, 3416, +0, 3334, 3416, +0, 3384, 3416, +0, 3416, 3387, +0, 3416, 3295, +0, 3416, 3132, +0, 3416, 2743, +0, 3548, 0, +0, 3680, 0, +2377, 3812, 0, +3142, 3944, 0, +3476, 4076, 0, +3717, 4095, 0, +0, 3144, 3416, +0, 3144, 3416, +0, 3144, 3416, +0, 3145, 3416, +0, 3145, 3416, +0, 3146, 3416, +0, 3147, 3416, +0, 3149, 3416, +0, 3151, 3416, +0, 3153, 3416, +0, 3156, 3416, +0, 3160, 3416, +0, 3166, 3416, +0, 3173, 3416, +0, 3183, 3416, +0, 3196, 3416, +0, 3212, 3416, +0, 3233, 3416, +0, 3259, 3416, +0, 3293, 3416, +0, 3334, 3416, +0, 3384, 3416, +0, 3416, 3387, +0, 3416, 3295, +0, 3416, 3133, +0, 3416, 2744, +0, 3548, 0, +0, 3680, 0, +2382, 3812, 0, +3143, 3944, 0, +3477, 4076, 0, +3717, 4095, 0, +0, 3143, 3416, +0, 3143, 3416, +0, 3143, 3416, +0, 3144, 3416, +0, 3144, 3416, +0, 3145, 3416, +0, 3147, 3415, +0, 3148, 3415, +0, 3150, 3415, +0, 3152, 3415, +0, 3155, 3415, +0, 3160, 3415, +0, 3165, 3415, +0, 3173, 3415, +0, 3182, 3415, +0, 3195, 3415, +0, 3211, 3415, +0, 3232, 3415, +0, 3259, 3415, +0, 3292, 3415, +0, 3333, 3415, +0, 3383, 3415, +0, 3415, 3387, +0, 3415, 3295, +0, 3415, 3133, +0, 3415, 2745, +0, 3548, 0, +0, 3680, 0, +2389, 3812, 0, +3144, 3944, 0, +3477, 4076, 0, +3718, 4095, 0, +0, 3141, 3416, +0, 3141, 3416, +0, 3142, 3416, +0, 3142, 3416, +0, 3143, 3416, +0, 3144, 3416, +0, 3145, 3415, +0, 3147, 3415, +0, 3149, 3415, +0, 3151, 3415, +0, 3154, 3415, +0, 3158, 3415, +0, 3164, 3415, +0, 3171, 3415, +0, 3181, 3415, +0, 3194, 3415, +0, 3210, 3415, +0, 3231, 3415, +0, 3258, 3415, +0, 3291, 3415, +0, 3333, 3415, +0, 3382, 3415, +0, 3415, 3388, +0, 3415, 3296, +0, 3415, 3134, +0, 3415, 2746, +0, 3548, 0, +0, 3680, 0, +2397, 3812, 0, +3145, 3944, 0, +3478, 4076, 0, +3718, 4095, 0, +0, 3139, 3416, +0, 3140, 3416, +0, 3140, 3416, +0, 3141, 3416, +0, 3141, 3416, +0, 3142, 3416, +0, 3144, 3415, +0, 3145, 3415, +0, 3147, 3415, +0, 3150, 3415, +0, 3153, 3415, +0, 3157, 3415, +0, 3163, 3415, +0, 3170, 3415, +0, 3180, 3415, +0, 3192, 3415, +0, 3209, 3415, +0, 3230, 3415, +0, 3257, 3415, +0, 3290, 3415, +0, 3331, 3415, +0, 3381, 3415, +0, 3415, 3388, +0, 3415, 3296, +0, 3415, 3135, +0, 3415, 2748, +0, 3548, 0, +0, 3680, 0, +2408, 3812, 0, +3147, 3944, 0, +3479, 4076, 0, +3719, 4095, 0, +0, 3137, 3416, +0, 3137, 3416, +0, 3138, 3416, +0, 3138, 3416, +0, 3139, 3416, +0, 3140, 3416, +0, 3141, 3415, +0, 3143, 3415, +0, 3145, 3415, +0, 3147, 3415, +0, 3151, 3415, +0, 3155, 3415, +0, 3161, 3415, +0, 3168, 3415, +0, 3178, 3415, +0, 3191, 3415, +0, 3207, 3415, +0, 3228, 3415, +0, 3255, 3415, +0, 3289, 3415, +0, 3330, 3415, +0, 3380, 3415, +0, 3415, 3389, +0, 3415, 3297, +0, 3415, 3136, +0, 3415, 2751, +0, 3547, 0, +0, 3680, 0, +2422, 3812, 0, +3151, 3944, 0, +3480, 4076, 0, +3720, 4095, 0, +0, 3134, 3416, +0, 3134, 3416, +0, 3134, 3416, +0, 3135, 3416, +0, 3135, 3416, +0, 3136, 3416, +0, 3138, 3415, +0, 3139, 3415, +0, 3141, 3415, +0, 3144, 3415, +0, 3148, 3414, +0, 3152, 3414, +0, 3158, 3414, +0, 3165, 3414, +0, 3175, 3414, +0, 3188, 3414, +0, 3205, 3414, +0, 3226, 3414, +0, 3253, 3414, +0, 3287, 3414, +0, 3329, 3414, +0, 3379, 3414, +0, 3414, 3390, +0, 3414, 3298, +0, 3414, 3137, +0, 3414, 2754, +0, 3547, 0, +0, 3679, 0, +2441, 3812, 0, +3154, 3944, 0, +3482, 4076, 0, +3721, 4095, 0, +0, 3129, 3416, +0, 3129, 3416, +0, 3130, 3416, +0, 3130, 3416, +0, 3131, 3416, +0, 3132, 3416, +0, 3133, 3415, +0, 3135, 3415, +0, 3137, 3415, +0, 3140, 3415, +0, 3144, 3414, +0, 3149, 3414, +0, 3155, 3414, +0, 3162, 3414, +0, 3172, 3414, +0, 3185, 3414, +0, 3202, 3414, +0, 3223, 3414, +0, 3250, 3414, +0, 3284, 3414, +0, 3326, 3414, +0, 3376, 3414, +0, 3414, 3391, +0, 3414, 3299, +0, 3414, 3139, +0, 3414, 2759, +0, 3547, 0, +0, 3679, 0, +2465, 3812, 0, +3159, 3944, 0, +3485, 4076, 0, +3722, 4095, 0, +0, 3123, 3416, +0, 3123, 3416, +0, 3124, 3416, +0, 3124, 3416, +0, 3125, 3416, +0, 3126, 3416, +0, 3127, 3415, +0, 3129, 3415, +0, 3131, 3415, +0, 3134, 3415, +0, 3138, 3414, +0, 3143, 3414, +0, 3150, 3414, +0, 3158, 3414, +0, 3168, 3414, +0, 3181, 3414, +0, 3198, 3414, +0, 3219, 3414, +0, 3247, 3414, +0, 3281, 3414, +0, 3323, 3414, +0, 3374, 3414, +0, 3414, 3393, +0, 3414, 3301, +0, 3414, 3142, +0, 3414, 2765, +0, 3546, 0, +0, 3679, 0, +2494, 3811, 0, +3166, 3944, 0, +3488, 4076, 0, +3724, 4095, 0, +0, 3115, 3416, +0, 3115, 3416, +0, 3115, 3416, +0, 3116, 3416, +0, 3117, 3416, +0, 3118, 3416, +0, 3119, 3415, +0, 3121, 3415, +0, 3123, 3415, +0, 3126, 3415, +0, 3130, 3414, +0, 3135, 3414, +0, 3142, 3414, +0, 3151, 3413, +0, 3162, 3413, +0, 3175, 3413, +0, 3192, 3413, +0, 3214, 3413, +0, 3242, 3413, +0, 3276, 3413, +0, 3319, 3413, +0, 3370, 3413, +0, 3413, 3395, +0, 3413, 3304, +0, 3413, 3145, +0, 3413, 2773, +0, 3546, 0, +0, 3678, 0, +2531, 3811, 0, +3175, 3943, 0, +3492, 4076, 0, +3727, 4095, 0, +0, 3104, 3416, +0, 3104, 3416, +0, 3104, 3416, +0, 3105, 3416, +0, 3106, 3416, +0, 3106, 3416, +0, 3108, 3415, +0, 3110, 3415, +0, 3112, 3415, +0, 3115, 3415, +0, 3119, 3414, +0, 3125, 3414, +0, 3132, 3414, +0, 3141, 3413, +0, 3154, 3412, +0, 3167, 3412, +0, 3184, 3412, +0, 3206, 3412, +0, 3234, 3412, +0, 3270, 3412, +0, 3313, 3412, +0, 3365, 3412, +0, 3412, 3397, +0, 3412, 3307, +0, 3412, 3150, +0, 3412, 2784, +0, 3545, 0, +0, 3678, 0, +2576, 3810, 0, +3186, 3943, 0, +3498, 4075, 0, +3730, 4095, 0, +0, 3088, 3416, +0, 3088, 3416, +0, 3089, 3416, +0, 3089, 3416, +0, 3090, 3416, +0, 3091, 3416, +0, 3093, 3415, +0, 3094, 3415, +0, 3097, 3415, +0, 3100, 3415, +0, 3104, 3414, +0, 3110, 3414, +0, 3117, 3414, +0, 3127, 3413, +0, 3140, 3412, +0, 3156, 3410, +0, 3174, 3410, +0, 3196, 3410, +0, 3225, 3410, +0, 3261, 3410, +0, 3305, 3410, +0, 3358, 3410, +0, 3410, 3401, +0, 3410, 3311, +0, 3410, 3156, +0, 3410, 2797, +0, 3544, 0, +0, 3677, 0, +2631, 3810, 0, +3201, 3943, 0, +3505, 4075, 0, +3735, 4095, 0, +0, 3067, 3416, +0, 3067, 3416, +0, 3067, 3416, +0, 3068, 3416, +0, 3069, 3416, +0, 3070, 3416, +0, 3071, 3415, +0, 3073, 3415, +0, 3076, 3415, +0, 3079, 3415, +0, 3083, 3414, +0, 3089, 3414, +0, 3097, 3414, +0, 3107, 3413, +0, 3120, 3412, +0, 3137, 3410, +0, 3159, 3408, +0, 3183, 3408, +0, 3212, 3408, +0, 3249, 3408, +0, 3294, 3408, +0, 3348, 3408, +0, 3408, 3406, +0, 3408, 3317, +0, 3408, 3164, +0, 3408, 2815, +0, 3543, 0, +0, 3676, 0, +2694, 3809, 0, +3220, 3942, 0, +3515, 4075, 0, +3741, 4095, 0, +0, 3036, 3416, +0, 3036, 3416, +0, 3037, 3416, +0, 3038, 3416, +0, 3038, 3416, +0, 3039, 3416, +0, 3041, 3415, +0, 3043, 3415, +0, 3046, 3415, +0, 3049, 3415, +0, 3054, 3414, +0, 3060, 3414, +0, 3069, 3414, +0, 3079, 3413, +0, 3093, 3412, +0, 3111, 3410, +0, 3134, 3408, +0, 3164, 3406, +0, 3194, 3406, +0, 3233, 3406, +0, 3279, 3406, +0, 3335, 3406, +0, 3400, 3406, +0, 3406, 3325, +0, 3406, 3175, +0, 3406, 2838, +0, 3541, 0, +0, 3675, 0, +2767, 3808, 0, +3244, 3941, 0, +3528, 4074, 0, +3748, 4095, 0, +0, 2992, 3416, +0, 2992, 3416, +0, 2992, 3416, +0, 2993, 3416, +0, 2994, 3416, +0, 2996, 3416, +0, 2997, 3415, +0, 2999, 3415, +0, 3002, 3415, +0, 3006, 3415, +0, 3011, 3414, +0, 3018, 3414, +0, 3027, 3414, +0, 3039, 3413, +0, 3055, 3412, +0, 3074, 3410, +0, 3099, 3408, +0, 3131, 3406, +0, 3170, 3402, +0, 3210, 3402, +0, 3259, 3402, +0, 3317, 3402, +0, 3384, 3402, +0, 3402, 3335, +0, 3402, 3189, +0, 3402, 2866, +0, 3538, 0, +0, 3673, 0, +2850, 3807, 0, +3275, 3940, 0, +3545, 4073, 0, +3759, 4095, 0, +0, 2925, 3416, +0, 2925, 3416, +0, 2926, 3416, +0, 2927, 3416, +0, 2928, 3416, +0, 2929, 3416, +0, 2931, 3415, +0, 2934, 3415, +0, 2937, 3415, +0, 2942, 3415, +0, 2947, 3414, +0, 2956, 3414, +0, 2966, 3414, +0, 2979, 3413, +0, 2997, 3412, +0, 3019, 3410, +0, 3047, 3408, +0, 3082, 3406, +0, 3125, 3402, +0, 3177, 3398, +0, 3230, 3398, +0, 3291, 3398, +0, 3362, 3398, +0, 3398, 3348, +0, 3398, 3206, +0, 3398, 2902, +0, 3535, 0, +1603, 3670, 0, +2941, 3805, 0, +3313, 3939, 0, +3566, 4072, 0, +3772, 4095, 0, +0, 2816, 3416, +0, 2817, 3416, +0, 2817, 3416, +0, 2818, 3416, +0, 2820, 3416, +0, 2822, 3416, +0, 2824, 3415, +0, 2827, 3415, +0, 2832, 3415, +0, 2837, 3415, +0, 2845, 3414, +0, 2855, 3414, +0, 2867, 3414, +0, 2884, 3413, +0, 2906, 3412, +0, 2933, 3410, +0, 2966, 3408, +0, 3008, 3406, +0, 3059, 3402, +0, 3118, 3398, +1406, 3187, 3392, +1406, 3255, 3392, +1406, 3331, 3392, +1406, 3392, 3365, +1406, 3392, 3230, +1406, 3392, 2945, +0, 3530, 1621, +2388, 3667, 0, +3040, 3802, 0, +3359, 3937, 0, +3593, 4071, 0, +3790, 4095, 0, +0, 2613, 3416, +0, 2614, 3416, +0, 2615, 3416, +0, 2617, 3416, +0, 2619, 3416, +0, 2621, 3416, +0, 2625, 3415, +0, 2630, 3415, +0, 2637, 3415, +0, 2646, 3415, +0, 2657, 3414, +0, 2672, 3414, +0, 2691, 3414, +0, 2715, 3413, +0, 2746, 3412, +0, 2784, 3410, +0, 2830, 3408, +0, 2886, 3406, +0, 2951, 3402, +0, 3025, 3398, +1406, 3108, 3392, +2326, 3201, 3383, +2326, 3286, 3383, +2326, 3380, 3383, +2326, 3383, 3258, +2326, 3383, 2998, +1536, 3524, 2158, +2724, 3662, 0, +3145, 3799, 0, +3414, 3934, 0, +3627, 4069, 0, +3812, 4095, 0, +0, 1977, 3416, +0, 1981, 3416, +0, 1986, 3416, +0, 1992, 3416, +0, 2000, 3416, +0, 2011, 3416, +0, 2026, 3415, +0, 2044, 3415, +0, 2068, 3415, +0, 2098, 3415, +0, 2135, 3414, +0, 2180, 3414, +0, 2234, 3414, +0, 2298, 3413, +0, 2371, 3412, +0, 2453, 3410, +0, 2545, 3408, +0, 2643, 3406, +0, 2749, 3402, +0, 2860, 3398, +1406, 2976, 3392, +2326, 3095, 3383, +2676, 3218, 3372, +2676, 3325, 3372, +2676, 3372, 3294, +2676, 3372, 3060, +2459, 3515, 2457, +2965, 3656, 1663, +3256, 3794, 0, +3479, 3931, 0, +3669, 4066, 0, +3840, 4095, 0, +0, 0, 3416, +0, 0, 3416, +0, 0, 3416, +0, 0, 3416, +0, 0, 3416, +0, 0, 3416, +0, 0, 3415, +0, 0, 3415, +0, 0, 3415, +0, 0, 3415, +0, 0, 3414, +0, 0, 3414, +0, 0, 3414, +0, 0, 3413, +0, 0, 3412, +0, 0, 3410, +0, 0, 3408, +0, 1325, 3406, +0, 2121, 3402, +0, 2458, 3398, +1406, 2701, 3392, +2326, 2900, 3383, +2676, 3077, 3372, +2922, 3239, 3356, +2922, 3356, 3338, +2922, 3356, 3132, +2907, 3504, 2808, +3165, 3648, 2590, +3372, 3788, 1799, +3553, 3926, 0, +3719, 4063, 0, +3875, 4095, 0, +0, 0, 3416, +0, 0, 3416, +0, 0, 3416, +0, 0, 3416, +0, 0, 3416, +0, 0, 3416, +0, 0, 3415, +0, 0, 3415, +0, 0, 3415, +0, 0, 3415, +0, 0, 3414, +0, 0, 3414, +0, 0, 3414, +0, 0, 3413, +0, 0, 3412, +0, 0, 3410, +0, 0, 3408, +0, 0, 3406, +0, 0, 3402, +1484, 0, 3398, +2025, 1406, 3392, +2326, 2328, 3383, +2676, 2774, 3372, +2922, 3051, 3356, +3124, 3267, 3333, +3124, 3333, 3212, +3183, 3488, 3054, +3341, 3636, 2940, +3492, 3780, 2721, +3637, 3920, 1928, +3779, 4058, 0, +3918, 4095, 0, +2741, 0, 3416, +2741, 0, 3416, +2742, 0, 3416, +2742, 0, 3416, +2743, 0, 3416, +2744, 0, 3416, +2745, 0, 3415, +2746, 0, 3415, +2748, 0, 3415, +2751, 0, 3415, +2754, 0, 3414, +2759, 0, 3414, +2765, 0, 3414, +2773, 0, 3413, +2784, 0, 3412, +2797, 0, 3410, +2815, 0, 3408, +2838, 0, 3406, +2866, 0, 3402, +2902, 0, 3398, +2945, 1406, 3392, +2998, 2326, 3383, +3060, 2676, 3372, +3132, 2922, 3356, +3212, 3124, 3333, +3302, 3302, 3302, +3399, 3466, 3256, +3504, 3620, 3186, +3614, 3768, 3072, +3729, 3912, 2854, +3848, 4052, 2063, +3970, 4095, 0, +3264, 0, 3548, +3264, 0, 3548, +3264, 0, 3548, +3264, 0, 3548, +3264, 0, 3548, +3265, 0, 3548, +3265, 0, 3548, +3265, 0, 3548, +3266, 0, 3548, +3267, 0, 3547, +3268, 0, 3547, +3269, 0, 3547, +3271, 0, 3546, +3274, 0, 3546, +3278, 0, 3545, +3282, 0, 3544, +3288, 0, 3543, +3296, 0, 3541, +3307, 0, 3538, +3321, 0, 3535, +3339, 0, 3530, +3362, 1536, 3524, +3391, 2457, 3515, +3426, 2808, 3504, +3470, 3054, 3488, +3466, 3256, 3399, +3466, 3344, 3256, +3620, 3603, 3186, +3721, 3768, 3072, +3814, 3912, 2854, +3915, 4052, 2063, +4022, 4095, 0, +3558, 0, 3680, +3558, 0, 3680, +3559, 0, 3680, +3559, 0, 3680, +3559, 0, 3680, +3559, 0, 3680, +3559, 0, 3680, +3559, 0, 3680, +3560, 0, 3680, +3560, 0, 3680, +3561, 0, 3679, +3562, 0, 3679, +3563, 0, 3679, +3564, 0, 3678, +3566, 0, 3678, +3568, 0, 3677, +3572, 0, 3676, +3576, 0, 3675, +3582, 0, 3673, +3589, 0, 3670, +3599, 0, 3667, +3612, 0, 3662, +3629, 1663, 3656, +3648, 2590, 3644, +3636, 2940, 3589, +3620, 3186, 3504, +3620, 3186, 3315, +3620, 3396, 3186, +3768, 3691, 3072, +3908, 3912, 2854, +3992, 4052, 2063, +4084, 4095, 0, +3783, 0, 3812, +3783, 0, 3812, +3783, 0, 3812, +3783, 0, 3812, +3783, 0, 3812, +3783, 0, 3812, +3783, 0, 3812, +3784, 0, 3812, +3784, 0, 3812, +3784, 0, 3812, +3784, 0, 3812, +3785, 0, 3812, +3785, 0, 3811, +3786, 0, 3811, +3787, 0, 3810, +3789, 0, 3810, +3791, 0, 3809, +3794, 0, 3808, +3797, 0, 3807, +3802, 0, 3805, +3802, 0, 3796, +3799, 0, 3781, +3794, 0, 3759, +3788, 1799, 3728, +3780, 2721, 3682, +3768, 3072, 3614, +3768, 3072, 3473, +3768, 3072, 3171, +3768, 3456, 3072, +3912, 3787, 2854, +4052, 4025, 2063, +4095, 4095, 0, +3944, 0, 3913, +3944, 0, 3913, +3944, 0, 3913, +3944, 0, 3913, +3944, 0, 3913, +3944, 0, 3913, +3944, 0, 3913, +3944, 0, 3912, +3944, 0, 3912, +3944, 0, 3912, +3944, 0, 3911, +3944, 0, 3910, +3944, 0, 3910, +3943, 0, 3909, +3943, 0, 3907, +3943, 0, 3905, +3942, 0, 3902, +3941, 0, 3898, +3940, 0, 3893, +3939, 0, 3886, +3937, 0, 3876, +3934, 0, 3863, +3931, 0, 3845, +3926, 0, 3820, +3920, 1928, 3783, +3912, 2854, 3729, +3912, 2854, 3624, +3912, 2854, 3428, +3912, 2854, 2854, +3912, 3526, 2854, +4052, 3890, 2063, +4095, 4095, 0, +4076, 0, 3996, +4076, 0, 3996, +4076, 0, 3996, +4076, 0, 3995, +4076, 0, 3995, +4076, 0, 3995, +4076, 0, 3995, +4076, 0, 3995, +4076, 0, 3995, +4076, 0, 3995, +4076, 0, 3994, +4076, 0, 3994, +4076, 0, 3993, +4076, 0, 3992, +4075, 0, 3991, +4075, 0, 3989, +4075, 0, 3986, +4074, 0, 3983, +4073, 0, 3979, +4072, 0, 3973, +4071, 0, 3965, +4069, 0, 3954, +4066, 0, 3940, +4063, 0, 3919, +4058, 0, 3890, +4052, 2063, 3848, +4052, 2063, 3769, +4052, 2063, 3636, +4052, 2063, 3361, +4052, 2689, 2063, +4052, 3606, 2063, +4095, 4000, 0, +4095, 0, 4087, +4095, 0, 4087, +4095, 0, 4087, +4095, 0, 4087, +4095, 0, 4087, +4095, 0, 4087, +4095, 0, 4087, +4095, 0, 4087, +4095, 0, 4086, +4095, 0, 4086, +4095, 0, 4086, +4095, 0, 4085, +4095, 0, 4085, +4095, 0, 4084, +4095, 0, 4083, +4095, 0, 4082, +4095, 0, 4080, +4095, 0, 4077, +4095, 0, 4073, +4095, 0, 4069, +4095, 0, 4062, +4095, 0, 4054, +4095, 0, 4042, +4095, 0, 4025, +4095, 0, 4002, +4095, 0, 3970, +4095, 0, 3911, +4095, 0, 3818, +4095, 0, 3653, +4095, 0, 3253, +4095, 2266, 0, +4095, 3695, 0, +0, 3278, 3548, +0, 3278, 3548, +0, 3279, 3548, +0, 3279, 3548, +0, 3279, 3548, +0, 3280, 3548, +0, 3280, 3548, +0, 3281, 3548, +0, 3283, 3548, +0, 3285, 3548, +0, 3287, 3548, +0, 3290, 3548, +0, 3294, 3548, +0, 3300, 3548, +0, 3307, 3548, +0, 3317, 3548, +0, 3329, 3548, +0, 3346, 3548, +0, 3367, 3548, +0, 3393, 3548, +0, 3426, 3548, +0, 3467, 3548, +0, 3516, 3548, +0, 3548, 3519, +0, 3548, 3426, +0, 3548, 3264, +0, 3548, 2873, +0, 3680, 0, +0, 3812, 0, +2497, 3944, 0, +3271, 4076, 0, +3608, 4095, 0, +0, 3278, 3548, +0, 3278, 3548, +0, 3278, 3548, +0, 3279, 3548, +0, 3279, 3548, +0, 3280, 3548, +0, 3280, 3548, +0, 3281, 3548, +0, 3283, 3548, +0, 3284, 3548, +0, 3287, 3548, +0, 3290, 3548, +0, 3294, 3548, +0, 3300, 3548, +0, 3307, 3548, +0, 3317, 3548, +0, 3329, 3548, +0, 3346, 3548, +0, 3367, 3548, +0, 3393, 3548, +0, 3426, 3548, +0, 3467, 3548, +0, 3516, 3548, +0, 3548, 3519, +0, 3548, 3426, +0, 3548, 3264, +0, 3548, 2873, +0, 3680, 0, +0, 3812, 0, +2498, 3944, 0, +3272, 4076, 0, +3608, 4095, 0, +0, 3278, 3548, +0, 3278, 3548, +0, 3278, 3548, +0, 3279, 3548, +0, 3279, 3548, +0, 3280, 3548, +0, 3280, 3548, +0, 3281, 3548, +0, 3282, 3548, +0, 3284, 3548, +0, 3287, 3548, +0, 3290, 3548, +0, 3294, 3548, +0, 3300, 3548, +0, 3307, 3548, +0, 3317, 3548, +0, 3329, 3548, +0, 3346, 3548, +0, 3366, 3548, +0, 3393, 3548, +0, 3426, 3548, +0, 3467, 3548, +0, 3516, 3548, +0, 3548, 3519, +0, 3548, 3427, +0, 3548, 3264, +0, 3548, 2873, +0, 3680, 0, +0, 3812, 0, +2500, 3944, 0, +3272, 4076, 0, +3608, 4095, 0, +0, 3277, 3548, +0, 3278, 3548, +0, 3278, 3548, +0, 3278, 3548, +0, 3279, 3548, +0, 3279, 3548, +0, 3280, 3548, +0, 3281, 3548, +0, 3282, 3548, +0, 3284, 3548, +0, 3286, 3548, +0, 3290, 3548, +0, 3294, 3548, +0, 3299, 3548, +0, 3307, 3548, +0, 3316, 3548, +0, 3329, 3548, +0, 3345, 3548, +0, 3366, 3548, +0, 3393, 3548, +0, 3426, 3548, +0, 3467, 3548, +0, 3516, 3548, +0, 3548, 3519, +0, 3548, 3427, +0, 3548, 3264, +0, 3548, 2874, +0, 3680, 0, +0, 3812, 0, +2502, 3944, 0, +3272, 4076, 0, +3608, 4095, 0, +0, 3277, 3548, +0, 3277, 3548, +0, 3277, 3548, +0, 3278, 3548, +0, 3278, 3548, +0, 3279, 3548, +0, 3280, 3548, +0, 3280, 3548, +0, 3282, 3548, +0, 3284, 3548, +0, 3286, 3548, +0, 3289, 3548, +0, 3293, 3548, +0, 3299, 3548, +0, 3307, 3548, +0, 3316, 3548, +0, 3329, 3548, +0, 3345, 3548, +0, 3366, 3548, +0, 3392, 3548, +0, 3426, 3548, +0, 3467, 3548, +0, 3516, 3548, +0, 3548, 3519, +0, 3548, 3427, +0, 3548, 3264, +0, 3548, 2874, +0, 3680, 0, +0, 3812, 0, +2505, 3944, 0, +3273, 4076, 0, +3608, 4095, 0, +0, 3276, 3548, +0, 3277, 3548, +0, 3277, 3548, +0, 3277, 3548, +0, 3278, 3548, +0, 3278, 3548, +0, 3279, 3548, +0, 3280, 3548, +0, 3281, 3548, +0, 3283, 3548, +0, 3286, 3548, +0, 3289, 3548, +0, 3293, 3548, +0, 3299, 3548, +0, 3306, 3548, +0, 3316, 3548, +0, 3328, 3548, +0, 3344, 3548, +0, 3365, 3548, +0, 3392, 3548, +0, 3425, 3548, +0, 3466, 3548, +0, 3516, 3548, +0, 3548, 3519, +0, 3548, 3427, +0, 3548, 3265, +0, 3548, 2875, +0, 3680, 0, +0, 3812, 0, +2508, 3944, 0, +3273, 4076, 0, +3609, 4095, 0, +0, 3276, 3548, +0, 3276, 3548, +0, 3276, 3548, +0, 3277, 3548, +0, 3277, 3548, +0, 3278, 3548, +0, 3279, 3548, +0, 3280, 3548, +0, 3281, 3548, +0, 3283, 3548, +0, 3285, 3548, +0, 3288, 3548, +0, 3292, 3548, +0, 3298, 3548, +0, 3305, 3548, +0, 3315, 3548, +0, 3328, 3548, +0, 3344, 3548, +0, 3365, 3548, +0, 3392, 3548, +0, 3425, 3548, +0, 3466, 3548, +0, 3515, 3548, +0, 3548, 3519, +0, 3548, 3427, +0, 3548, 3265, +0, 3548, 2876, +0, 3680, 0, +0, 3812, 0, +2513, 3944, 0, +3274, 4076, 0, +3609, 4095, 0, +0, 3275, 3548, +0, 3275, 3548, +0, 3275, 3548, +0, 3275, 3548, +0, 3276, 3548, +0, 3277, 3548, +0, 3278, 3548, +0, 3279, 3548, +0, 3280, 3548, +0, 3282, 3548, +0, 3284, 3548, +0, 3287, 3548, +0, 3292, 3548, +0, 3297, 3548, +0, 3305, 3548, +0, 3314, 3548, +0, 3327, 3548, +0, 3343, 3548, +0, 3364, 3548, +0, 3391, 3548, +0, 3424, 3548, +0, 3466, 3548, +0, 3515, 3548, +0, 3548, 3520, +0, 3548, 3428, +0, 3548, 3265, +0, 3548, 2877, +0, 3680, 0, +0, 3812, 0, +2520, 3944, 0, +3276, 4076, 0, +3610, 4095, 0, +0, 3273, 3548, +0, 3273, 3548, +0, 3274, 3548, +0, 3274, 3548, +0, 3275, 3548, +0, 3275, 3548, +0, 3276, 3548, +0, 3277, 3548, +0, 3279, 3548, +0, 3281, 3548, +0, 3283, 3548, +0, 3286, 3548, +0, 3291, 3548, +0, 3296, 3548, +0, 3303, 3548, +0, 3313, 3548, +0, 3326, 3548, +0, 3342, 3548, +0, 3363, 3548, +0, 3390, 3548, +0, 3423, 3548, +0, 3465, 3548, +0, 3514, 3548, +0, 3548, 3520, +0, 3548, 3428, +0, 3548, 3266, +0, 3548, 2878, +0, 3680, 0, +0, 3812, 0, +2528, 3944, 0, +3277, 4076, 0, +3611, 4095, 0, +0, 3271, 3548, +0, 3272, 3548, +0, 3272, 3548, +0, 3272, 3548, +0, 3273, 3548, +0, 3273, 3548, +0, 3274, 3548, +0, 3276, 3548, +0, 3277, 3548, +0, 3279, 3547, +0, 3282, 3547, +0, 3285, 3547, +0, 3289, 3547, +0, 3295, 3547, +0, 3302, 3547, +0, 3312, 3547, +0, 3325, 3547, +0, 3341, 3547, +0, 3362, 3547, +0, 3389, 3547, +0, 3422, 3547, +0, 3464, 3547, +0, 3513, 3547, +0, 3547, 3520, +0, 3547, 3429, +0, 3547, 3267, +0, 3547, 2880, +0, 3680, 0, +0, 3812, 0, +2539, 3944, 0, +3279, 4076, 0, +3612, 4095, 0, +0, 3269, 3548, +0, 3269, 3548, +0, 3269, 3548, +0, 3270, 3548, +0, 3270, 3548, +0, 3271, 3548, +0, 3272, 3548, +0, 3273, 3548, +0, 3275, 3548, +0, 3277, 3547, +0, 3280, 3547, +0, 3283, 3547, +0, 3287, 3547, +0, 3293, 3547, +0, 3300, 3547, +0, 3310, 3547, +0, 3323, 3547, +0, 3339, 3547, +0, 3361, 3547, +0, 3387, 3547, +0, 3421, 3547, +0, 3462, 3547, +0, 3512, 3547, +0, 3547, 3521, +0, 3547, 3429, +0, 3547, 3268, +0, 3547, 2883, +0, 3679, 0, +0, 3812, 0, +2553, 3944, 0, +3282, 4076, 0, +3613, 4095, 0, +0, 3266, 3548, +0, 3266, 3548, +0, 3266, 3548, +0, 3267, 3548, +0, 3267, 3548, +0, 3268, 3548, +0, 3269, 3548, +0, 3270, 3548, +0, 3271, 3548, +0, 3274, 3547, +0, 3277, 3547, +0, 3280, 3547, +0, 3285, 3547, +0, 3290, 3547, +0, 3298, 3547, +0, 3307, 3547, +0, 3320, 3547, +0, 3337, 3547, +0, 3358, 3547, +0, 3385, 3547, +0, 3419, 3547, +0, 3461, 3547, +0, 3511, 3547, +0, 3547, 3522, +0, 3547, 3430, +0, 3547, 3269, +0, 3547, 2886, +0, 3679, 0, +0, 3812, 0, +2572, 3944, 0, +3286, 4076, 0, +3615, 4095, 0, +0, 3261, 3548, +0, 3261, 3548, +0, 3261, 3548, +0, 3262, 3548, +0, 3262, 3548, +0, 3263, 3548, +0, 3264, 3548, +0, 3265, 3548, +0, 3267, 3548, +0, 3269, 3547, +0, 3272, 3547, +0, 3276, 3547, +0, 3281, 3546, +0, 3287, 3546, +0, 3294, 3546, +0, 3304, 3546, +0, 3317, 3546, +0, 3334, 3546, +0, 3355, 3546, +0, 3382, 3546, +0, 3416, 3546, +0, 3458, 3546, +0, 3509, 3546, +0, 3546, 3523, +0, 3546, 3432, +0, 3546, 3271, +0, 3546, 2891, +0, 3679, 0, +0, 3811, 0, +2596, 3944, 0, +3291, 4076, 0, +3617, 4095, 0, +0, 3255, 3548, +0, 3255, 3548, +0, 3256, 3548, +0, 3256, 3548, +0, 3256, 3548, +0, 3257, 3548, +0, 3258, 3548, +0, 3259, 3548, +0, 3261, 3548, +0, 3263, 3547, +0, 3266, 3547, +0, 3270, 3547, +0, 3275, 3546, +0, 3282, 3546, +0, 3290, 3546, +0, 3300, 3546, +0, 3313, 3546, +0, 3330, 3546, +0, 3351, 3546, +0, 3379, 3546, +0, 3413, 3546, +0, 3455, 3546, +0, 3506, 3546, +0, 3546, 3525, +0, 3546, 3434, +0, 3546, 3274, +0, 3546, 2897, +0, 3678, 0, +0, 3811, 0, +2625, 3943, 0, +3297, 4076, 0, +3621, 4095, 0, +0, 3247, 3548, +0, 3247, 3548, +0, 3247, 3548, +0, 3248, 3548, +0, 3248, 3548, +0, 3249, 3548, +0, 3250, 3548, +0, 3251, 3548, +0, 3253, 3548, +0, 3255, 3547, +0, 3258, 3547, +0, 3262, 3547, +0, 3268, 3546, +0, 3275, 3546, +0, 3284, 3545, +0, 3294, 3545, +0, 3307, 3545, +0, 3324, 3545, +0, 3346, 3545, +0, 3374, 3545, +0, 3408, 3545, +0, 3451, 3545, +0, 3502, 3545, +0, 3545, 3526, +0, 3545, 3436, +0, 3545, 3278, +0, 3545, 2905, +0, 3678, 0, +0, 3810, 0, +2662, 3943, 0, +3306, 4075, 0, +3625, 4095, 0, +0, 3236, 3548, +0, 3236, 3548, +0, 3236, 3548, +0, 3237, 3548, +0, 3237, 3548, +0, 3238, 3548, +0, 3239, 3548, +0, 3240, 3548, +0, 3242, 3548, +0, 3244, 3547, +0, 3247, 3547, +0, 3251, 3547, +0, 3257, 3546, +0, 3264, 3546, +0, 3273, 3545, +0, 3285, 3544, +0, 3299, 3544, +0, 3316, 3544, +0, 3339, 3544, +0, 3367, 3544, +0, 3402, 3544, +0, 3445, 3544, +0, 3497, 3544, +0, 3544, 3529, +0, 3544, 3440, +0, 3544, 3282, +0, 3544, 2916, +0, 3677, 0, +0, 3810, 0, +2708, 3943, 0, +3318, 4075, 0, +3630, 4095, 0, +0, 3220, 3548, +0, 3220, 3548, +0, 3221, 3548, +0, 3221, 3548, +0, 3222, 3548, +0, 3222, 3548, +0, 3223, 3548, +0, 3225, 3548, +0, 3226, 3548, +0, 3229, 3547, +0, 3232, 3547, +0, 3236, 3547, +0, 3242, 3546, +0, 3249, 3546, +0, 3259, 3545, +0, 3272, 3544, +0, 3288, 3543, +0, 3306, 3543, +0, 3329, 3543, +0, 3357, 3543, +0, 3393, 3543, +0, 3437, 3543, +0, 3490, 3543, +0, 3543, 3533, +0, 3543, 3444, +0, 3543, 3288, +0, 3543, 2929, +0, 3676, 0, +0, 3809, 0, +2762, 3942, 0, +3333, 4075, 0, +3638, 4095, 0, +0, 3198, 3548, +0, 3199, 3548, +0, 3199, 3548, +0, 3200, 3548, +0, 3200, 3548, +0, 3201, 3548, +0, 3202, 3548, +0, 3203, 3548, +0, 3205, 3548, +0, 3208, 3547, +0, 3211, 3547, +0, 3216, 3547, +0, 3221, 3546, +0, 3229, 3546, +0, 3239, 3545, +0, 3253, 3544, +0, 3270, 3543, +0, 3291, 3541, +0, 3315, 3541, +0, 3344, 3541, +0, 3381, 3541, +0, 3426, 3541, +0, 3480, 3541, +0, 3541, 3538, +0, 3541, 3450, +0, 3541, 3296, +0, 3541, 2947, +0, 3675, 0, +0, 3808, 0, +2826, 3941, 0, +3351, 4074, 0, +3648, 4095, 0, +0, 3168, 3548, +0, 3168, 3548, +0, 3168, 3548, +0, 3169, 3548, +0, 3170, 3548, +0, 3171, 3548, +0, 3172, 3548, +0, 3173, 3548, +0, 3175, 3548, +0, 3178, 3547, +0, 3182, 3547, +0, 3186, 3547, +0, 3192, 3546, +0, 3201, 3546, +0, 3211, 3545, +0, 3225, 3544, +0, 3243, 3543, +0, 3267, 3541, +0, 3296, 3538, +0, 3326, 3538, +0, 3365, 3538, +0, 3411, 3538, +0, 3467, 3538, +0, 3532, 3538, +0, 3538, 3457, +0, 3538, 3307, +0, 3538, 2970, +0, 3673, 0, +0, 3807, 0, +2899, 3940, 0, +3376, 4073, 0, +3661, 4095, 0, +0, 3124, 3548, +0, 3124, 3548, +0, 3124, 3548, +0, 3125, 3548, +0, 3125, 3548, +0, 3126, 3548, +0, 3128, 3548, +0, 3129, 3548, +0, 3132, 3548, +0, 3135, 3547, +0, 3138, 3547, +0, 3144, 3547, +0, 3151, 3546, +0, 3160, 3546, +0, 3171, 3545, +0, 3186, 3544, +0, 3206, 3543, +0, 3231, 3541, +0, 3263, 3538, +0, 3302, 3535, +0, 3342, 3535, +0, 3391, 3535, +0, 3449, 3535, +0, 3516, 3535, +0, 3535, 3467, +0, 3535, 3321, +0, 3535, 2998, +0, 3670, 0, +0, 3805, 0, +2982, 3939, 0, +3407, 4072, 0, +3677, 4095, 0, +0, 3056, 3548, +0, 3057, 3548, +0, 3057, 3548, +0, 3058, 3548, +0, 3059, 3548, +0, 3060, 3548, +0, 3061, 3548, +0, 3063, 3548, +0, 3066, 3548, +0, 3069, 3547, +0, 3074, 3547, +0, 3080, 3547, +0, 3087, 3546, +0, 3098, 3546, +0, 3111, 3545, +0, 3129, 3544, +0, 3151, 3543, +0, 3179, 3541, +0, 3214, 3538, +0, 3257, 3535, +0, 3309, 3530, +0, 3362, 3530, +0, 3423, 3530, +0, 3495, 3530, +0, 3530, 3480, +0, 3530, 3339, +0, 3530, 3034, +0, 3667, 0, +1737, 3802, 0, +3073, 3937, 0, +3445, 4071, 0, +3699, 4095, 0, +0, 2948, 3548, +0, 2948, 3548, +0, 2949, 3548, +0, 2950, 3548, +0, 2951, 3548, +0, 2952, 3548, +0, 2954, 3548, +0, 2956, 3548, +0, 2960, 3548, +0, 2964, 3547, +0, 2970, 3547, +0, 2977, 3547, +0, 2987, 3546, +0, 3000, 3546, +0, 3016, 3545, +0, 3038, 3544, +0, 3065, 3543, +0, 3099, 3541, +0, 3140, 3538, +0, 3190, 3535, +0, 3250, 3530, +1536, 3320, 3524, +1536, 3387, 3524, +1536, 3463, 3524, +1536, 3524, 3497, +1536, 3524, 3362, +1536, 3524, 3078, +0, 3662, 1753, +2519, 3799, 0, +3172, 3934, 0, +3491, 4069, 0, +3726, 4095, 0, +0, 2745, 3548, +0, 2745, 3548, +0, 2746, 3548, +0, 2747, 3548, +0, 2749, 3548, +0, 2751, 3548, +0, 2754, 3548, +0, 2758, 3548, +0, 2763, 3548, +0, 2770, 3547, +0, 2778, 3547, +0, 2790, 3547, +0, 2804, 3546, +0, 2824, 3546, +0, 2848, 3545, +0, 2879, 3544, +0, 2917, 3543, +0, 2963, 3541, +0, 3018, 3538, +0, 3083, 3535, +0, 3157, 3530, +1536, 3241, 3524, +2457, 3333, 3515, +2457, 3418, 3515, +2457, 3512, 3515, +2457, 3515, 3391, +2457, 3515, 3130, +1663, 3656, 2289, +2856, 3794, 0, +3277, 3931, 0, +3546, 4066, 0, +3759, 4095, 0, +0, 2104, 3548, +0, 2107, 3548, +0, 2111, 3548, +0, 2115, 3548, +0, 2122, 3548, +0, 2130, 3548, +0, 2141, 3548, +0, 2156, 3548, +0, 2174, 3548, +0, 2198, 3547, +0, 2228, 3547, +0, 2265, 3547, +0, 2311, 3546, +0, 2365, 3546, +0, 2429, 3545, +0, 2502, 3544, +0, 2585, 3543, +0, 2676, 3541, +0, 2775, 3538, +0, 2881, 3535, +0, 2992, 3530, +1536, 3108, 3524, +2457, 3227, 3515, +2808, 3350, 3504, +2808, 3457, 3504, +2808, 3504, 3426, +2808, 3504, 3192, +2592, 3648, 2590, +3097, 3788, 1799, +3388, 3926, 0, +3611, 4063, 0, +3801, 4095, 0, +0, 0, 3548, +0, 0, 3548, +0, 0, 3548, +0, 0, 3548, +0, 0, 3548, +0, 0, 3548, +0, 0, 3548, +0, 0, 3548, +0, 0, 3548, +0, 0, 3547, +0, 0, 3547, +0, 0, 3547, +0, 0, 3546, +0, 0, 3546, +0, 0, 3545, +0, 0, 3544, +0, 0, 3543, +0, 0, 3541, +0, 1477, 3538, +0, 2256, 3535, +0, 2593, 3530, +1536, 2833, 3524, +2457, 3032, 3515, +2808, 3209, 3504, +3054, 3372, 3488, +3054, 3488, 3470, +3054, 3488, 3264, +3038, 3636, 2940, +3296, 3780, 2721, +3504, 3920, 1928, +3685, 4058, 0, +3851, 4095, 0, +0, 0, 3548, +0, 0, 3548, +0, 0, 3548, +0, 0, 3548, +0, 0, 3548, +0, 0, 3548, +0, 0, 3548, +0, 0, 3548, +0, 0, 3548, +0, 0, 3547, +0, 0, 3547, +0, 0, 3547, +0, 0, 3546, +0, 0, 3546, +0, 0, 3545, +0, 0, 3544, +0, 0, 3543, +0, 0, 3541, +0, 0, 3538, +0, 0, 3535, +1621, 0, 3530, +2158, 1536, 3524, +2457, 2459, 3515, +2808, 2907, 3504, +3054, 3183, 3488, +3256, 3399, 3466, +3256, 3466, 3344, +3315, 3620, 3186, +3473, 3768, 3072, +3624, 3912, 2854, +3769, 4052, 2063, +3911, 4095, 0, +2873, 0, 3548, +2873, 0, 3548, +2873, 0, 3548, +2874, 0, 3548, +2874, 0, 3548, +2875, 0, 3548, +2876, 0, 3548, +2877, 0, 3548, +2878, 0, 3548, +2880, 0, 3547, +2883, 0, 3547, +2886, 0, 3547, +2891, 0, 3546, +2897, 0, 3546, +2905, 0, 3545, +2916, 0, 3544, +2929, 0, 3543, +2947, 0, 3541, +2970, 0, 3538, +2998, 0, 3535, +3034, 0, 3530, +3078, 1536, 3524, +3130, 2457, 3515, +3192, 2808, 3504, +3264, 3054, 3488, +3344, 3256, 3466, +3434, 3434, 3434, +3531, 3598, 3388, +3636, 3752, 3318, +3746, 3900, 3204, +3861, 4044, 2986, +3980, 4095, 2192, +3396, 0, 3680, +3396, 0, 3680, +3396, 0, 3680, +3396, 0, 3680, +3396, 0, 3680, +3396, 0, 3680, +3396, 0, 3680, +3397, 0, 3680, +3397, 0, 3680, +3398, 0, 3680, +3399, 0, 3679, +3400, 0, 3679, +3401, 0, 3679, +3403, 0, 3678, +3406, 0, 3678, +3410, 0, 3677, +3414, 0, 3676, +3420, 0, 3675, +3429, 0, 3673, +3439, 0, 3670, +3453, 0, 3667, +3471, 0, 3662, +3494, 1663, 3656, +3523, 2590, 3648, +3558, 2940, 3636, +3603, 3186, 3620, +3598, 3388, 3531, +3598, 3477, 3388, +3752, 3735, 3318, +3853, 3900, 3204, +3947, 4044, 2986, +4047, 4095, 2192, +3691, 0, 3812, +3691, 0, 3812, +3691, 0, 3812, +3691, 0, 3812, +3691, 0, 3812, +3691, 0, 3812, +3691, 0, 3812, +3691, 0, 3812, +3691, 0, 3812, +3692, 0, 3812, +3692, 0, 3812, +3693, 0, 3812, +3694, 0, 3811, +3695, 0, 3811, +3696, 0, 3810, +3698, 0, 3810, +3700, 0, 3809, +3704, 0, 3808, +3708, 0, 3807, +3714, 0, 3805, +3721, 0, 3802, +3731, 0, 3799, +3745, 0, 3794, +3761, 1799, 3788, +3780, 2721, 3776, +3768, 3072, 3721, +3752, 3318, 3636, +3752, 3318, 3447, +3752, 3528, 3318, +3900, 3822, 3204, +4040, 4044, 2986, +4095, 4095, 2192, +3915, 0, 3944, +3915, 0, 3944, +3915, 0, 3944, +3915, 0, 3944, +3915, 0, 3944, +3915, 0, 3944, +3915, 0, 3944, +3915, 0, 3944, +3915, 0, 3944, +3916, 0, 3944, +3916, 0, 3944, +3916, 0, 3944, +3917, 0, 3944, +3917, 0, 3943, +3918, 0, 3943, +3920, 0, 3943, +3921, 0, 3942, +3923, 0, 3941, +3926, 0, 3940, +3929, 0, 3939, +3934, 0, 3937, +3934, 0, 3928, +3931, 0, 3913, +3926, 0, 3891, +3920, 1928, 3860, +3912, 2854, 3814, +3900, 3204, 3746, +3900, 3204, 3605, +3900, 3204, 3302, +3900, 3588, 3204, +4044, 3919, 2986, +4095, 4095, 2192, +4076, 0, 4045, +4076, 0, 4045, +4076, 0, 4045, +4076, 0, 4045, +4076, 0, 4045, +4076, 0, 4045, +4076, 0, 4045, +4076, 0, 4045, +4076, 0, 4044, +4076, 0, 4044, +4076, 0, 4044, +4076, 0, 4043, +4076, 0, 4043, +4076, 0, 4042, +4075, 0, 4041, +4075, 0, 4039, +4075, 0, 4037, +4074, 0, 4034, +4073, 0, 4030, +4072, 0, 4025, +4071, 0, 4018, +4069, 0, 4008, +4066, 0, 3995, +4063, 0, 3977, +4058, 0, 3952, +4052, 2063, 3915, +4044, 2986, 3861, +4044, 2986, 3755, +4044, 2986, 3561, +4044, 2986, 2987, +4044, 3659, 2986, +4095, 4023, 2192, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4087, +4095, 0, 4072, +4095, 0, 4051, +4095, 0, 4022, +4095, 2192, 3980, +4095, 2192, 3901, +4095, 2192, 3768, +4095, 2192, 3494, +4095, 2814, 2192, +4095, 3738, 2192, +0, 3410, 3680, +0, 3410, 3680, +0, 3410, 3680, +0, 3411, 3680, +0, 3411, 3680, +0, 3411, 3680, +0, 3412, 3680, +0, 3413, 3680, +0, 3414, 3680, +0, 3415, 3680, +0, 3417, 3680, +0, 3419, 3680, +0, 3422, 3680, +0, 3427, 3680, +0, 3432, 3680, +0, 3440, 3680, +0, 3449, 3680, +0, 3462, 3680, +0, 3478, 3680, +0, 3499, 3680, +0, 3525, 3680, +0, 3558, 3680, +0, 3599, 3680, +0, 3649, 3680, +0, 3680, 3651, +0, 3680, 3558, +0, 3680, 3396, +0, 3680, 3005, +0, 3812, 0, +0, 3944, 0, +2626, 4076, 0, +3404, 4095, 0, +0, 3410, 3680, +0, 3410, 3680, +0, 3410, 3680, +0, 3411, 3680, +0, 3411, 3680, +0, 3411, 3680, +0, 3412, 3680, +0, 3413, 3680, +0, 3414, 3680, +0, 3415, 3680, +0, 3417, 3680, +0, 3419, 3680, +0, 3422, 3680, +0, 3426, 3680, +0, 3432, 3680, +0, 3439, 3680, +0, 3449, 3680, +0, 3462, 3680, +0, 3478, 3680, +0, 3499, 3680, +0, 3525, 3680, +0, 3558, 3680, +0, 3599, 3680, +0, 3649, 3680, +0, 3680, 3651, +0, 3680, 3558, +0, 3680, 3396, +0, 3680, 3005, +0, 3812, 0, +0, 3944, 0, +2627, 4076, 0, +3404, 4095, 0, +0, 3410, 3680, +0, 3410, 3680, +0, 3410, 3680, +0, 3410, 3680, +0, 3411, 3680, +0, 3411, 3680, +0, 3412, 3680, +0, 3413, 3680, +0, 3414, 3680, +0, 3415, 3680, +0, 3417, 3680, +0, 3419, 3680, +0, 3422, 3680, +0, 3426, 3680, +0, 3432, 3680, +0, 3439, 3680, +0, 3449, 3680, +0, 3462, 3680, +0, 3478, 3680, +0, 3499, 3680, +0, 3525, 3680, +0, 3558, 3680, +0, 3599, 3680, +0, 3649, 3680, +0, 3680, 3651, +0, 3680, 3559, +0, 3680, 3396, +0, 3680, 3005, +0, 3812, 0, +0, 3944, 0, +2628, 4076, 0, +3404, 4095, 0, +0, 3410, 3680, +0, 3410, 3680, +0, 3410, 3680, +0, 3410, 3680, +0, 3411, 3680, +0, 3411, 3680, +0, 3412, 3680, +0, 3412, 3680, +0, 3413, 3680, +0, 3415, 3680, +0, 3416, 3680, +0, 3419, 3680, +0, 3422, 3680, +0, 3426, 3680, +0, 3432, 3680, +0, 3439, 3680, +0, 3449, 3680, +0, 3461, 3680, +0, 3478, 3680, +0, 3499, 3680, +0, 3525, 3680, +0, 3558, 3680, +0, 3599, 3680, +0, 3649, 3680, +0, 3680, 3651, +0, 3680, 3559, +0, 3680, 3396, +0, 3680, 3006, +0, 3812, 0, +0, 3944, 0, +2630, 4076, 0, +3405, 4095, 0, +0, 3409, 3680, +0, 3409, 3680, +0, 3410, 3680, +0, 3410, 3680, +0, 3410, 3680, +0, 3411, 3680, +0, 3411, 3680, +0, 3412, 3680, +0, 3413, 3680, +0, 3414, 3680, +0, 3416, 3680, +0, 3419, 3680, +0, 3422, 3680, +0, 3426, 3680, +0, 3431, 3680, +0, 3439, 3680, +0, 3448, 3680, +0, 3461, 3680, +0, 3478, 3680, +0, 3498, 3680, +0, 3525, 3680, +0, 3558, 3680, +0, 3599, 3680, +0, 3648, 3680, +0, 3680, 3651, +0, 3680, 3559, +0, 3680, 3396, +0, 3680, 3006, +0, 3812, 0, +0, 3944, 0, +2632, 4076, 0, +3405, 4095, 0, +0, 3409, 3680, +0, 3409, 3680, +0, 3409, 3680, +0, 3410, 3680, +0, 3410, 3680, +0, 3410, 3680, +0, 3411, 3680, +0, 3412, 3680, +0, 3413, 3680, +0, 3414, 3680, +0, 3416, 3680, +0, 3418, 3680, +0, 3421, 3680, +0, 3426, 3680, +0, 3431, 3680, +0, 3438, 3680, +0, 3448, 3680, +0, 3461, 3680, +0, 3477, 3680, +0, 3498, 3680, +0, 3525, 3680, +0, 3558, 3680, +0, 3599, 3680, +0, 3648, 3680, +0, 3680, 3651, +0, 3680, 3559, +0, 3680, 3396, +0, 3680, 3006, +0, 3812, 0, +0, 3944, 0, +2635, 4076, 0, +3405, 4095, 0, +0, 3408, 3680, +0, 3408, 3680, +0, 3409, 3680, +0, 3409, 3680, +0, 3409, 3680, +0, 3410, 3680, +0, 3411, 3680, +0, 3411, 3680, +0, 3412, 3680, +0, 3414, 3680, +0, 3415, 3680, +0, 3418, 3680, +0, 3421, 3680, +0, 3425, 3680, +0, 3431, 3680, +0, 3438, 3680, +0, 3448, 3680, +0, 3460, 3680, +0, 3477, 3680, +0, 3497, 3680, +0, 3524, 3680, +0, 3557, 3680, +0, 3598, 3680, +0, 3648, 3680, +0, 3680, 3651, +0, 3680, 3559, +0, 3680, 3396, +0, 3680, 3007, +0, 3812, 0, +0, 3944, 0, +2639, 4076, 0, +3406, 4095, 0, +0, 3408, 3680, +0, 3408, 3680, +0, 3408, 3680, +0, 3408, 3680, +0, 3409, 3680, +0, 3409, 3680, +0, 3410, 3680, +0, 3411, 3680, +0, 3412, 3680, +0, 3413, 3680, +0, 3415, 3680, +0, 3417, 3680, +0, 3420, 3680, +0, 3425, 3680, +0, 3430, 3680, +0, 3437, 3680, +0, 3447, 3680, +0, 3460, 3680, +0, 3476, 3680, +0, 3497, 3680, +0, 3524, 3680, +0, 3557, 3680, +0, 3598, 3680, +0, 3648, 3680, +0, 3680, 3652, +0, 3680, 3559, +0, 3680, 3397, +0, 3680, 3008, +0, 3812, 0, +0, 3944, 0, +2644, 4076, 0, +3407, 4095, 0, +0, 3406, 3680, +0, 3407, 3680, +0, 3407, 3680, +0, 3407, 3680, +0, 3408, 3680, +0, 3408, 3680, +0, 3409, 3680, +0, 3410, 3680, +0, 3411, 3680, +0, 3412, 3680, +0, 3414, 3680, +0, 3416, 3680, +0, 3420, 3680, +0, 3424, 3680, +0, 3429, 3680, +0, 3437, 3680, +0, 3446, 3680, +0, 3459, 3680, +0, 3475, 3680, +0, 3496, 3680, +0, 3523, 3680, +0, 3556, 3680, +0, 3597, 3680, +0, 3647, 3680, +0, 3680, 3652, +0, 3680, 3560, +0, 3680, 3397, +0, 3680, 3009, +0, 3812, 0, +0, 3944, 0, +2650, 4076, 0, +3408, 4095, 0, +0, 3405, 3680, +0, 3405, 3680, +0, 3405, 3680, +0, 3406, 3680, +0, 3406, 3680, +0, 3407, 3680, +0, 3407, 3680, +0, 3408, 3680, +0, 3409, 3680, +0, 3411, 3680, +0, 3413, 3680, +0, 3415, 3680, +0, 3418, 3680, +0, 3423, 3680, +0, 3428, 3680, +0, 3436, 3680, +0, 3445, 3680, +0, 3458, 3680, +0, 3475, 3680, +0, 3495, 3680, +0, 3522, 3680, +0, 3556, 3680, +0, 3597, 3680, +0, 3646, 3680, +0, 3680, 3652, +0, 3680, 3560, +0, 3680, 3398, +0, 3680, 3011, +0, 3812, 0, +0, 3944, 0, +2659, 4076, 0, +3410, 4095, 0, +0, 3403, 3680, +0, 3403, 3680, +0, 3404, 3680, +0, 3404, 3680, +0, 3404, 3680, +0, 3405, 3680, +0, 3406, 3680, +0, 3406, 3680, +0, 3408, 3680, +0, 3409, 3680, +0, 3411, 3679, +0, 3414, 3679, +0, 3417, 3679, +0, 3421, 3679, +0, 3427, 3679, +0, 3434, 3679, +0, 3444, 3679, +0, 3457, 3679, +0, 3473, 3679, +0, 3494, 3679, +0, 3521, 3679, +0, 3554, 3679, +0, 3596, 3679, +0, 3646, 3679, +0, 3679, 3653, +0, 3679, 3561, +0, 3679, 3399, +0, 3679, 3013, +0, 3812, 0, +0, 3944, 0, +2670, 4076, 0, +3412, 4095, 0, +0, 3401, 3680, +0, 3401, 3680, +0, 3401, 3680, +0, 3401, 3680, +0, 3402, 3680, +0, 3402, 3680, +0, 3403, 3680, +0, 3404, 3680, +0, 3405, 3680, +0, 3407, 3680, +0, 3409, 3679, +0, 3412, 3679, +0, 3415, 3679, +0, 3419, 3679, +0, 3425, 3679, +0, 3432, 3679, +0, 3442, 3679, +0, 3455, 3679, +0, 3472, 3679, +0, 3493, 3679, +0, 3520, 3679, +0, 3553, 3679, +0, 3595, 3679, +0, 3644, 3679, +0, 3679, 3653, +0, 3679, 3562, +0, 3679, 3400, +0, 3679, 3015, +0, 3812, 0, +0, 3944, 0, +2684, 4076, 0, +3415, 4095, 0, +0, 3398, 3680, +0, 3398, 3680, +0, 3398, 3680, +0, 3398, 3680, +0, 3399, 3680, +0, 3399, 3680, +0, 3400, 3680, +0, 3401, 3680, +0, 3402, 3680, +0, 3404, 3680, +0, 3406, 3679, +0, 3409, 3679, +0, 3413, 3679, +0, 3417, 3679, +0, 3422, 3679, +0, 3430, 3679, +0, 3440, 3679, +0, 3453, 3679, +0, 3469, 3679, +0, 3490, 3679, +0, 3517, 3679, +0, 3551, 3679, +0, 3593, 3679, +0, 3643, 3679, +0, 3679, 3654, +0, 3679, 3563, +0, 3679, 3401, +0, 3679, 3018, +0, 3811, 0, +0, 3944, 0, +2703, 4076, 0, +3419, 4095, 0, +0, 3393, 3680, +0, 3393, 3680, +0, 3393, 3680, +0, 3394, 3680, +0, 3394, 3680, +0, 3395, 3680, +0, 3395, 3680, +0, 3396, 3680, +0, 3397, 3680, +0, 3399, 3680, +0, 3401, 3679, +0, 3404, 3679, +0, 3408, 3679, +0, 3413, 3678, +0, 3419, 3678, +0, 3426, 3678, +0, 3436, 3678, +0, 3449, 3678, +0, 3466, 3678, +0, 3488, 3678, +0, 3515, 3678, +0, 3548, 3678, +0, 3590, 3678, +0, 3641, 3678, +0, 3678, 3655, +0, 3678, 3564, +0, 3678, 3403, +0, 3678, 3023, +0, 3811, 0, +0, 3943, 0, +2726, 4076, 0, +3424, 4095, 0, +0, 3387, 3680, +0, 3387, 3680, +0, 3387, 3680, +0, 3388, 3680, +0, 3388, 3680, +0, 3388, 3680, +0, 3389, 3680, +0, 3390, 3680, +0, 3392, 3680, +0, 3393, 3680, +0, 3395, 3679, +0, 3398, 3679, +0, 3402, 3679, +0, 3407, 3678, +0, 3414, 3678, +0, 3422, 3678, +0, 3432, 3678, +0, 3445, 3678, +0, 3462, 3678, +0, 3483, 3678, +0, 3511, 3678, +0, 3545, 3678, +0, 3587, 3678, +0, 3638, 3678, +0, 3678, 3657, +0, 3678, 3566, +0, 3678, 3406, +0, 3678, 3029, +0, 3810, 0, +0, 3943, 0, +2756, 4075, 0, +3430, 4095, 0, +0, 3379, 3680, +0, 3379, 3680, +0, 3379, 3680, +0, 3379, 3680, +0, 3380, 3680, +0, 3380, 3680, +0, 3381, 3680, +0, 3382, 3680, +0, 3383, 3680, +0, 3385, 3680, +0, 3387, 3679, +0, 3390, 3679, +0, 3394, 3679, +0, 3400, 3678, +0, 3407, 3678, +0, 3416, 3677, +0, 3426, 3677, +0, 3439, 3677, +0, 3456, 3677, +0, 3478, 3677, +0, 3506, 3677, +0, 3540, 3677, +0, 3583, 3677, +0, 3634, 3677, +0, 3677, 3659, +0, 3677, 3568, +0, 3677, 3410, +0, 3677, 3037, +0, 3810, 0, +0, 3943, 0, +2793, 4075, 0, +3439, 4095, 0, +0, 3367, 3680, +0, 3368, 3680, +0, 3368, 3680, +0, 3368, 3680, +0, 3369, 3680, +0, 3369, 3680, +0, 3370, 3680, +0, 3371, 3680, +0, 3372, 3680, +0, 3374, 3680, +0, 3376, 3679, +0, 3379, 3679, +0, 3384, 3679, +0, 3389, 3678, +0, 3396, 3678, +0, 3405, 3677, +0, 3418, 3676, +0, 3431, 3676, +0, 3448, 3676, +0, 3471, 3676, +0, 3499, 3676, +0, 3534, 3676, +0, 3577, 3676, +0, 3629, 3676, +0, 3676, 3662, +0, 3676, 3572, +0, 3676, 3414, +0, 3676, 3048, +0, 3809, 0, +0, 3942, 0, +2839, 4075, 0, +3450, 4095, 0, +0, 3352, 3680, +0, 3352, 3680, +0, 3353, 3680, +0, 3353, 3680, +0, 3353, 3680, +0, 3354, 3680, +0, 3354, 3680, +0, 3356, 3680, +0, 3357, 3680, +0, 3359, 3680, +0, 3361, 3679, +0, 3364, 3679, +0, 3368, 3679, +0, 3374, 3678, +0, 3381, 3678, +0, 3391, 3677, +0, 3404, 3676, +0, 3420, 3675, +0, 3438, 3675, +0, 3461, 3675, +0, 3490, 3675, +0, 3525, 3675, +0, 3569, 3675, +0, 3622, 3675, +0, 3675, 3665, +0, 3675, 3576, +0, 3675, 3420, +0, 3675, 3061, +0, 3808, 0, +0, 3941, 0, +2893, 4074, 0, +3465, 4095, 0, +0, 3330, 3680, +0, 3331, 3680, +0, 3331, 3680, +0, 3331, 3680, +0, 3332, 3680, +0, 3332, 3680, +0, 3333, 3680, +0, 3334, 3680, +0, 3336, 3680, +0, 3337, 3680, +0, 3340, 3679, +0, 3343, 3679, +0, 3348, 3679, +0, 3354, 3678, +0, 3361, 3678, +0, 3371, 3677, +0, 3385, 3676, +0, 3402, 3675, +0, 3423, 3673, +0, 3447, 3673, +0, 3477, 3673, +0, 3513, 3673, +0, 3558, 3673, +0, 3612, 3673, +0, 3673, 3670, +0, 3673, 3582, +0, 3673, 3429, +0, 3673, 3079, +0, 3807, 0, +0, 3940, 0, +2957, 4073, 0, +3484, 4095, 0, +0, 3300, 3680, +0, 3300, 3680, +0, 3300, 3680, +0, 3301, 3680, +0, 3301, 3680, +0, 3302, 3680, +0, 3303, 3680, +0, 3304, 3680, +0, 3305, 3680, +0, 3307, 3680, +0, 3310, 3679, +0, 3314, 3679, +0, 3318, 3679, +0, 3325, 3678, +0, 3333, 3678, +0, 3344, 3677, +0, 3358, 3676, +0, 3376, 3675, +0, 3399, 3673, +0, 3428, 3670, +0, 3459, 3670, +0, 3497, 3670, +0, 3543, 3670, +0, 3599, 3670, +0, 3664, 3670, +0, 3670, 3589, +0, 3670, 3439, +0, 3670, 3102, +0, 3805, 0, +0, 3939, 0, +3031, 4072, 0, +3509, 4095, 0, +0, 3255, 3680, +0, 3256, 3680, +0, 3256, 3680, +0, 3256, 3680, +0, 3257, 3680, +0, 3258, 3680, +0, 3258, 3680, +0, 3260, 3680, +0, 3261, 3680, +0, 3264, 3680, +0, 3267, 3679, +0, 3271, 3679, +0, 3276, 3679, +0, 3282, 3678, +0, 3291, 3678, +0, 3303, 3677, +0, 3319, 3676, +0, 3338, 3675, +0, 3363, 3673, +0, 3395, 3670, +0, 3434, 3667, +0, 3474, 3667, +0, 3523, 3667, +0, 3581, 3667, +0, 3648, 3667, +0, 3667, 3599, +0, 3667, 3453, +0, 3667, 3131, +0, 3802, 0, +0, 3937, 0, +3113, 4071, 0, +3539, 4095, 0, +0, 3188, 3680, +0, 3188, 3680, +0, 3189, 3680, +0, 3189, 3680, +0, 3190, 3680, +0, 3191, 3680, +0, 3192, 3680, +0, 3193, 3680, +0, 3195, 3680, +0, 3198, 3680, +0, 3201, 3679, +0, 3206, 3679, +0, 3212, 3679, +0, 3220, 3678, +0, 3230, 3678, +0, 3243, 3677, +0, 3261, 3676, +0, 3283, 3675, +0, 3311, 3673, +0, 3346, 3670, +0, 3389, 3667, +0, 3441, 3662, +0, 3494, 3662, +0, 3555, 3662, +0, 3626, 3662, +0, 3662, 3612, +0, 3662, 3471, +0, 3662, 3166, +0, 3799, 0, +1863, 3934, 0, +3205, 4069, 0, +3577, 4095, 0, +0, 3080, 3680, +0, 3080, 3680, +0, 3081, 3680, +0, 3081, 3680, +0, 3082, 3680, +0, 3083, 3680, +0, 3084, 3680, +0, 3086, 3680, +0, 3089, 3680, +0, 3092, 3680, +0, 3096, 3679, +0, 3102, 3679, +0, 3110, 3679, +0, 3119, 3678, +0, 3132, 3678, +0, 3149, 3677, +0, 3170, 3676, +0, 3197, 3675, +0, 3231, 3673, +0, 3273, 3670, +0, 3323, 3667, +0, 3382, 3662, +1663, 3452, 3656, +1663, 3519, 3656, +1663, 3595, 3656, +1663, 3656, 3629, +1663, 3656, 3494, +1663, 3656, 3210, +0, 3794, 1884, +2650, 3931, 0, +3303, 4066, 0, +3623, 4095, 0, +0, 2876, 3680, +0, 2877, 3680, +0, 2877, 3680, +0, 2878, 3680, +0, 2879, 3680, +0, 2881, 3680, +0, 2883, 3680, +0, 2886, 3680, +0, 2890, 3680, +0, 2895, 3680, +0, 2901, 3679, +0, 2910, 3679, +0, 2922, 3679, +0, 2936, 3678, +0, 2955, 3678, +0, 2980, 3677, +0, 3010, 3676, +0, 3048, 3675, +0, 3095, 3673, +0, 3150, 3670, +0, 3215, 3667, +0, 3289, 3662, +1663, 3373, 3656, +2590, 3465, 3648, +2590, 3550, 3648, +2590, 3644, 3648, +2590, 3648, 3523, +2590, 3648, 3262, +1799, 3788, 2422, +2988, 3926, 0, +3409, 4063, 0, +3679, 4095, 0, +0, 2237, 3680, +0, 2239, 3680, +0, 2242, 3680, +0, 2246, 3680, +0, 2251, 3680, +0, 2257, 3680, +0, 2266, 3680, +0, 2277, 3680, +0, 2291, 3680, +0, 2310, 3680, +0, 2333, 3679, +0, 2363, 3679, +0, 2400, 3679, +0, 2445, 3678, +0, 2499, 3678, +0, 2562, 3677, +0, 2636, 3676, +0, 2718, 3675, +0, 2809, 3673, +0, 2908, 3670, +0, 3014, 3667, +0, 3125, 3662, +1663, 3240, 3656, +2590, 3360, 3648, +2940, 3482, 3636, +2940, 3589, 3636, +2940, 3636, 3558, +2940, 3636, 3324, +2722, 3780, 2721, +3229, 3920, 1928, +3520, 4058, 0, +3743, 4095, 0, +0, 0, 3680, +0, 0, 3680, +0, 0, 3680, +0, 0, 3680, +0, 0, 3680, +0, 0, 3680, +0, 0, 3680, +0, 0, 3680, +0, 0, 3680, +0, 0, 3680, +0, 0, 3679, +0, 0, 3679, +0, 0, 3679, +0, 0, 3678, +0, 0, 3678, +0, 0, 3677, +0, 0, 3676, +0, 0, 3675, +0, 0, 3673, +0, 1603, 3670, +0, 2388, 3667, +0, 2724, 3662, +1663, 2965, 3656, +2590, 3165, 3648, +2940, 3341, 3636, +3186, 3504, 3620, +3186, 3620, 3603, +3186, 3620, 3396, +3171, 3768, 3072, +3428, 3912, 2854, +3636, 4052, 2063, +3818, 4095, 0, +0, 0, 3680, +0, 0, 3680, +0, 0, 3680, +0, 0, 3680, +0, 0, 3680, +0, 0, 3680, +0, 0, 3680, +0, 0, 3680, +0, 0, 3680, +0, 0, 3680, +0, 0, 3679, +0, 0, 3679, +0, 0, 3679, +0, 0, 3678, +0, 0, 3678, +0, 0, 3677, +0, 0, 3676, +0, 0, 3675, +0, 0, 3673, +0, 0, 3670, +0, 0, 3667, +1753, 0, 3662, +2289, 1663, 3656, +2590, 2592, 3648, +2940, 3038, 3636, +3186, 3315, 3620, +3388, 3531, 3598, +3388, 3598, 3477, +3447, 3752, 3318, +3605, 3900, 3204, +3755, 4044, 2986, +3901, 4095, 2192, +3005, 0, 3680, +3005, 0, 3680, +3005, 0, 3680, +3006, 0, 3680, +3006, 0, 3680, +3006, 0, 3680, +3007, 0, 3680, +3008, 0, 3680, +3009, 0, 3680, +3011, 0, 3680, +3013, 0, 3679, +3015, 0, 3679, +3018, 0, 3679, +3023, 0, 3678, +3029, 0, 3678, +3037, 0, 3677, +3048, 0, 3676, +3061, 0, 3675, +3079, 0, 3673, +3102, 0, 3670, +3131, 0, 3667, +3166, 0, 3662, +3210, 1663, 3656, +3262, 2590, 3648, +3324, 2940, 3636, +3396, 3186, 3620, +3477, 3388, 3598, +3566, 3566, 3566, +3664, 3730, 3520, +3768, 3884, 3450, +3878, 4032, 3336, +3993, 4095, 3118, +3528, 0, 3812, +3528, 0, 3812, +3528, 0, 3812, +3528, 0, 3812, +3528, 0, 3812, +3528, 0, 3812, +3528, 0, 3812, +3529, 0, 3812, +3529, 0, 3812, +3530, 0, 3812, +3530, 0, 3812, +3531, 0, 3812, +3532, 0, 3811, +3534, 0, 3811, +3536, 0, 3810, +3538, 0, 3810, +3542, 0, 3809, +3546, 0, 3808, +3552, 0, 3807, +3561, 0, 3805, +3571, 0, 3802, +3585, 0, 3799, +3603, 0, 3794, +3626, 1799, 3788, +3655, 2721, 3780, +3691, 3072, 3768, +3735, 3318, 3752, +3730, 3520, 3664, +3730, 3609, 3520, +3884, 3867, 3450, +3986, 4032, 3336, +4079, 4095, 3118, +3822, 0, 3944, +3822, 0, 3944, +3822, 0, 3944, +3823, 0, 3944, +3823, 0, 3944, +3823, 0, 3944, +3823, 0, 3944, +3823, 0, 3944, +3823, 0, 3944, +3824, 0, 3944, +3824, 0, 3944, +3824, 0, 3944, +3825, 0, 3944, +3826, 0, 3943, +3827, 0, 3943, +3828, 0, 3943, +3830, 0, 3942, +3832, 0, 3941, +3836, 0, 3940, +3840, 0, 3939, +3846, 0, 3937, +3853, 0, 3934, +3863, 0, 3931, +3877, 0, 3926, +3893, 1928, 3920, +3912, 2854, 3908, +3900, 3204, 3853, +3884, 3450, 3768, +3884, 3450, 3579, +3884, 3660, 3450, +4032, 3955, 3336, +4095, 4095, 3118, +4047, 0, 4076, +4047, 0, 4076, +4047, 0, 4076, +4047, 0, 4076, +4047, 0, 4076, +4047, 0, 4076, +4047, 0, 4076, +4047, 0, 4076, +4047, 0, 4076, +4047, 0, 4076, +4048, 0, 4076, +4048, 0, 4076, +4048, 0, 4076, +4049, 0, 4076, +4049, 0, 4075, +4050, 0, 4075, +4051, 0, 4075, +4053, 0, 4074, +4055, 0, 4073, +4058, 0, 4072, +4061, 0, 4071, +4066, 0, 4069, +4066, 0, 4060, +4063, 0, 4045, +4058, 0, 4023, +4052, 2063, 3992, +4044, 2986, 3947, +4032, 3336, 3878, +4032, 3336, 3737, +4032, 3336, 3435, +4032, 3720, 3336, +4095, 4051, 3118, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4084, +4095, 2192, 4047, +4095, 3118, 3993, +4095, 3118, 3888, +4095, 3118, 3693, +4095, 3118, 3121, +4095, 3791, 3118, +0, 3542, 3812, +0, 3542, 3812, +0, 3543, 3812, +0, 3543, 3812, +0, 3543, 3812, +0, 3543, 3812, +0, 3544, 3812, +0, 3544, 3812, +0, 3545, 3812, +0, 3546, 3812, +0, 3547, 3812, +0, 3549, 3812, +0, 3552, 3812, +0, 3554, 3812, +0, 3559, 3812, +0, 3564, 3812, +0, 3572, 3812, +0, 3581, 3812, +0, 3594, 3812, +0, 3610, 3812, +0, 3631, 3812, +0, 3657, 3812, +0, 3691, 3812, +0, 3732, 3812, +0, 3781, 3812, +0, 3812, 3783, +0, 3812, 3691, +0, 3812, 3528, +0, 3812, 3137, +0, 3944, 0, +0, 4076, 0, +2761, 4095, 0, +0, 3542, 3812, +0, 3542, 3812, +0, 3543, 3812, +0, 3543, 3812, +0, 3543, 3812, +0, 3543, 3812, +0, 3544, 3812, +0, 3544, 3812, +0, 3545, 3812, +0, 3546, 3812, +0, 3547, 3812, +0, 3549, 3812, +0, 3551, 3812, +0, 3554, 3812, +0, 3559, 3812, +0, 3564, 3812, +0, 3572, 3812, +0, 3581, 3812, +0, 3594, 3812, +0, 3610, 3812, +0, 3631, 3812, +0, 3657, 3812, +0, 3691, 3812, +0, 3731, 3812, +0, 3781, 3812, +0, 3812, 3783, +0, 3812, 3691, +0, 3812, 3528, +0, 3812, 3137, +0, 3944, 0, +0, 4076, 0, +2762, 4095, 0, +0, 3542, 3812, +0, 3542, 3812, +0, 3542, 3812, +0, 3543, 3812, +0, 3543, 3812, +0, 3543, 3812, +0, 3543, 3812, +0, 3544, 3812, +0, 3545, 3812, +0, 3546, 3812, +0, 3547, 3812, +0, 3549, 3812, +0, 3551, 3812, +0, 3554, 3812, +0, 3559, 3812, +0, 3564, 3812, +0, 3572, 3812, +0, 3581, 3812, +0, 3594, 3812, +0, 3610, 3812, +0, 3631, 3812, +0, 3657, 3812, +0, 3690, 3812, +0, 3731, 3812, +0, 3781, 3812, +0, 3812, 3783, +0, 3812, 3691, +0, 3812, 3528, +0, 3812, 3137, +0, 3944, 0, +0, 4076, 0, +2762, 4095, 0, +0, 3542, 3812, +0, 3542, 3812, +0, 3542, 3812, +0, 3542, 3812, +0, 3543, 3812, +0, 3543, 3812, +0, 3543, 3812, +0, 3544, 3812, +0, 3545, 3812, +0, 3545, 3812, +0, 3547, 3812, +0, 3549, 3812, +0, 3551, 3812, +0, 3554, 3812, +0, 3558, 3812, +0, 3564, 3812, +0, 3571, 3812, +0, 3581, 3812, +0, 3594, 3812, +0, 3610, 3812, +0, 3631, 3812, +0, 3657, 3812, +0, 3690, 3812, +0, 3731, 3812, +0, 3781, 3812, +0, 3812, 3783, +0, 3812, 3691, +0, 3812, 3528, +0, 3812, 3138, +0, 3944, 0, +0, 4076, 0, +2764, 4095, 0, +0, 3541, 3812, +0, 3542, 3812, +0, 3542, 3812, +0, 3542, 3812, +0, 3543, 3812, +0, 3543, 3812, +0, 3543, 3812, +0, 3544, 3812, +0, 3544, 3812, +0, 3545, 3812, +0, 3547, 3812, +0, 3549, 3812, +0, 3551, 3812, +0, 3554, 3812, +0, 3558, 3812, +0, 3564, 3812, +0, 3571, 3812, +0, 3581, 3812, +0, 3594, 3812, +0, 3610, 3812, +0, 3631, 3812, +0, 3657, 3812, +0, 3690, 3812, +0, 3731, 3812, +0, 3781, 3812, +0, 3812, 3783, +0, 3812, 3691, +0, 3812, 3528, +0, 3812, 3138, +0, 3944, 0, +0, 4076, 0, +2765, 4095, 0, +0, 3541, 3812, +0, 3541, 3812, +0, 3541, 3812, +0, 3542, 3812, +0, 3542, 3812, +0, 3543, 3812, +0, 3543, 3812, +0, 3543, 3812, +0, 3544, 3812, +0, 3545, 3812, +0, 3547, 3812, +0, 3548, 3812, +0, 3551, 3812, +0, 3554, 3812, +0, 3558, 3812, +0, 3564, 3812, +0, 3571, 3812, +0, 3581, 3812, +0, 3593, 3812, +0, 3609, 3812, +0, 3630, 3812, +0, 3657, 3812, +0, 3690, 3812, +0, 3731, 3812, +0, 3781, 3812, +0, 3812, 3783, +0, 3812, 3691, +0, 3812, 3528, +0, 3812, 3138, +0, 3944, 0, +0, 4076, 0, +2767, 4095, 0, +0, 3541, 3812, +0, 3541, 3812, +0, 3541, 3812, +0, 3541, 3812, +0, 3542, 3812, +0, 3542, 3812, +0, 3543, 3812, +0, 3543, 3812, +0, 3544, 3812, +0, 3545, 3812, +0, 3546, 3812, +0, 3548, 3812, +0, 3550, 3812, +0, 3553, 3812, +0, 3558, 3812, +0, 3563, 3812, +0, 3571, 3812, +0, 3580, 3812, +0, 3593, 3812, +0, 3609, 3812, +0, 3630, 3812, +0, 3657, 3812, +0, 3690, 3812, +0, 3731, 3812, +0, 3781, 3812, +0, 3812, 3783, +0, 3812, 3691, +0, 3812, 3528, +0, 3812, 3139, +0, 3944, 0, +0, 4076, 0, +2770, 4095, 0, +0, 3540, 3812, +0, 3540, 3812, +0, 3541, 3812, +0, 3541, 3812, +0, 3541, 3812, +0, 3541, 3812, +0, 3542, 3812, +0, 3543, 3812, +0, 3543, 3812, +0, 3544, 3812, +0, 3546, 3812, +0, 3548, 3812, +0, 3550, 3812, +0, 3553, 3812, +0, 3557, 3812, +0, 3563, 3812, +0, 3570, 3812, +0, 3580, 3812, +0, 3593, 3812, +0, 3609, 3812, +0, 3630, 3812, +0, 3656, 3812, +0, 3690, 3812, +0, 3730, 3812, +0, 3780, 3812, +0, 3812, 3784, +0, 3812, 3691, +0, 3812, 3529, +0, 3812, 3139, +0, 3944, 0, +0, 4076, 0, +2773, 4095, 0, +0, 3540, 3812, +0, 3540, 3812, +0, 3540, 3812, +0, 3540, 3812, +0, 3540, 3812, +0, 3541, 3812, +0, 3541, 3812, +0, 3542, 3812, +0, 3543, 3812, +0, 3544, 3812, +0, 3545, 3812, +0, 3547, 3812, +0, 3549, 3812, +0, 3552, 3812, +0, 3557, 3812, +0, 3562, 3812, +0, 3570, 3812, +0, 3579, 3812, +0, 3592, 3812, +0, 3608, 3812, +0, 3629, 3812, +0, 3656, 3812, +0, 3689, 3812, +0, 3730, 3812, +0, 3780, 3812, +0, 3812, 3784, +0, 3812, 3691, +0, 3812, 3529, +0, 3812, 3140, +0, 3944, 0, +0, 4076, 0, +2778, 4095, 0, +0, 3538, 3812, +0, 3538, 3812, +0, 3539, 3812, +0, 3539, 3812, +0, 3539, 3812, +0, 3540, 3812, +0, 3540, 3812, +0, 3541, 3812, +0, 3542, 3812, +0, 3543, 3812, +0, 3544, 3812, +0, 3546, 3812, +0, 3548, 3812, +0, 3552, 3812, +0, 3556, 3812, +0, 3562, 3812, +0, 3569, 3812, +0, 3579, 3812, +0, 3591, 3812, +0, 3607, 3812, +0, 3629, 3812, +0, 3655, 3812, +0, 3689, 3812, +0, 3729, 3812, +0, 3779, 3812, +0, 3812, 3784, +0, 3812, 3692, +0, 3812, 3530, +0, 3812, 3141, +0, 3944, 0, +0, 4076, 0, +2785, 4095, 0, +0, 3537, 3812, +0, 3537, 3812, +0, 3537, 3812, +0, 3538, 3812, +0, 3538, 3812, +0, 3538, 3812, +0, 3539, 3812, +0, 3540, 3812, +0, 3540, 3812, +0, 3541, 3812, +0, 3543, 3812, +0, 3545, 3812, +0, 3547, 3812, +0, 3551, 3812, +0, 3555, 3812, +0, 3561, 3812, +0, 3568, 3812, +0, 3577, 3812, +0, 3590, 3812, +0, 3606, 3812, +0, 3628, 3812, +0, 3654, 3812, +0, 3688, 3812, +0, 3729, 3812, +0, 3778, 3812, +0, 3812, 3784, +0, 3812, 3692, +0, 3812, 3530, +0, 3812, 3143, +0, 3944, 0, +0, 4076, 0, +2793, 4095, 0, +0, 3535, 3812, +0, 3536, 3812, +0, 3536, 3812, +0, 3536, 3812, +0, 3536, 3812, +0, 3537, 3812, +0, 3537, 3812, +0, 3538, 3812, +0, 3538, 3812, +0, 3540, 3812, +0, 3541, 3812, +0, 3544, 3812, +0, 3546, 3812, +0, 3549, 3812, +0, 3553, 3812, +0, 3559, 3812, +0, 3566, 3812, +0, 3576, 3812, +0, 3589, 3812, +0, 3605, 3812, +0, 3626, 3812, +0, 3653, 3812, +0, 3687, 3812, +0, 3728, 3812, +0, 3777, 3812, +0, 3812, 3785, +0, 3812, 3693, +0, 3812, 3531, +0, 3812, 3145, +0, 3944, 0, +0, 4076, 0, +2804, 4095, 0, +0, 3533, 3812, +0, 3533, 3812, +0, 3533, 3812, +0, 3533, 3812, +0, 3534, 3812, +0, 3534, 3812, +0, 3534, 3812, +0, 3535, 3812, +0, 3536, 3812, +0, 3537, 3812, +0, 3539, 3812, +0, 3541, 3812, +0, 3544, 3811, +0, 3547, 3811, +0, 3552, 3811, +0, 3557, 3811, +0, 3564, 3811, +0, 3574, 3811, +0, 3587, 3811, +0, 3604, 3811, +0, 3625, 3811, +0, 3652, 3811, +0, 3685, 3811, +0, 3727, 3811, +0, 3777, 3811, +0, 3811, 3785, +0, 3811, 3694, +0, 3811, 3532, +0, 3811, 3147, +0, 3944, 0, +0, 4076, 0, +2818, 4095, 0, +0, 3530, 3812, +0, 3530, 3812, +0, 3530, 3812, +0, 3530, 3812, +0, 3530, 3812, +0, 3531, 3812, +0, 3531, 3812, +0, 3532, 3812, +0, 3533, 3812, +0, 3534, 3812, +0, 3536, 3812, +0, 3538, 3812, +0, 3541, 3811, +0, 3545, 3811, +0, 3549, 3811, +0, 3554, 3811, +0, 3562, 3811, +0, 3572, 3811, +0, 3585, 3811, +0, 3601, 3811, +0, 3622, 3811, +0, 3650, 3811, +0, 3683, 3811, +0, 3725, 3811, +0, 3775, 3811, +0, 3811, 3786, +0, 3811, 3695, +0, 3811, 3534, +0, 3811, 3151, +0, 3943, 0, +0, 4076, 0, +2837, 4095, 0, +0, 3525, 3812, +0, 3525, 3812, +0, 3525, 3812, +0, 3526, 3812, +0, 3526, 3812, +0, 3526, 3812, +0, 3527, 3812, +0, 3528, 3812, +0, 3528, 3812, +0, 3530, 3812, +0, 3531, 3812, +0, 3533, 3812, +0, 3536, 3811, +0, 3540, 3811, +0, 3545, 3810, +0, 3551, 3810, +0, 3559, 3810, +0, 3569, 3810, +0, 3582, 3810, +0, 3598, 3810, +0, 3620, 3810, +0, 3647, 3810, +0, 3680, 3810, +0, 3722, 3810, +0, 3773, 3810, +0, 3810, 3787, +0, 3810, 3696, +0, 3810, 3536, +0, 3810, 3155, +0, 3943, 0, +0, 4075, 0, +2861, 4095, 0, +0, 3519, 3812, +0, 3519, 3812, +0, 3519, 3812, +0, 3520, 3812, +0, 3520, 3812, +0, 3520, 3812, +0, 3521, 3812, +0, 3521, 3812, +0, 3522, 3812, +0, 3523, 3812, +0, 3525, 3812, +0, 3528, 3812, +0, 3530, 3811, +0, 3534, 3811, +0, 3540, 3810, +0, 3547, 3810, +0, 3554, 3810, +0, 3564, 3810, +0, 3577, 3810, +0, 3594, 3810, +0, 3616, 3810, +0, 3643, 3810, +0, 3677, 3810, +0, 3719, 3810, +0, 3770, 3810, +0, 3810, 3789, +0, 3810, 3698, +0, 3810, 3538, +0, 3810, 3161, +0, 3943, 0, +0, 4075, 0, +2890, 4095, 0, +0, 3511, 3812, +0, 3511, 3812, +0, 3511, 3812, +0, 3511, 3812, +0, 3511, 3812, +0, 3512, 3812, +0, 3513, 3812, +0, 3513, 3812, +0, 3514, 3812, +0, 3515, 3812, +0, 3517, 3812, +0, 3520, 3812, +0, 3522, 3811, +0, 3526, 3811, +0, 3532, 3810, +0, 3539, 3810, +0, 3548, 3809, +0, 3558, 3809, +0, 3571, 3809, +0, 3588, 3809, +0, 3610, 3809, +0, 3638, 3809, +0, 3672, 3809, +0, 3715, 3809, +0, 3766, 3809, +0, 3809, 3791, +0, 3809, 3700, +0, 3809, 3542, +0, 3809, 3169, +0, 3942, 0, +0, 4075, 0, +2927, 4095, 0, +0, 3499, 3812, +0, 3499, 3812, +0, 3500, 3812, +0, 3500, 3812, +0, 3500, 3812, +0, 3501, 3812, +0, 3501, 3812, +0, 3502, 3812, +0, 3503, 3812, +0, 3504, 3812, +0, 3506, 3812, +0, 3508, 3812, +0, 3511, 3811, +0, 3516, 3811, +0, 3521, 3810, +0, 3528, 3810, +0, 3537, 3809, +0, 3550, 3808, +0, 3563, 3808, +0, 3581, 3808, +0, 3603, 3808, +0, 3631, 3808, +0, 3666, 3808, +0, 3709, 3808, +0, 3761, 3808, +0, 3808, 3794, +0, 3808, 3704, +0, 3808, 3546, +0, 3808, 3180, +0, 3941, 0, +0, 4074, 0, +2973, 4095, 0, +0, 3484, 3812, +0, 3484, 3812, +0, 3484, 3812, +0, 3485, 3812, +0, 3485, 3812, +0, 3485, 3812, +0, 3486, 3812, +0, 3487, 3812, +0, 3488, 3812, +0, 3489, 3812, +0, 3491, 3812, +0, 3493, 3812, +0, 3496, 3811, +0, 3501, 3811, +0, 3506, 3810, +0, 3514, 3810, +0, 3523, 3809, +0, 3536, 3808, +0, 3552, 3807, +0, 3570, 3807, +0, 3593, 3807, +0, 3622, 3807, +0, 3657, 3807, +0, 3701, 3807, +0, 3754, 3807, +0, 3807, 3797, +0, 3807, 3708, +0, 3807, 3552, +0, 3807, 3194, +0, 3940, 0, +0, 4073, 0, +3027, 4095, 0, +0, 3462, 3812, +0, 3462, 3812, +0, 3463, 3812, +0, 3463, 3812, +0, 3463, 3812, +0, 3464, 3812, +0, 3464, 3812, +0, 3465, 3812, +0, 3466, 3812, +0, 3468, 3812, +0, 3469, 3812, +0, 3472, 3812, +0, 3475, 3811, +0, 3480, 3811, +0, 3486, 3810, +0, 3493, 3810, +0, 3503, 3809, +0, 3517, 3808, +0, 3534, 3807, +0, 3556, 3805, +0, 3579, 3805, +0, 3609, 3805, +0, 3646, 3805, +0, 3690, 3805, +0, 3744, 3805, +0, 3805, 3802, +0, 3805, 3714, +0, 3805, 3561, +0, 3805, 3211, +0, 3939, 0, +0, 4072, 0, +3090, 4095, 0, +0, 3432, 3812, +0, 3432, 3812, +0, 3432, 3812, +0, 3432, 3812, +0, 3433, 3812, +0, 3433, 3812, +0, 3434, 3812, +0, 3435, 3812, +0, 3436, 3812, +0, 3437, 3812, +0, 3439, 3812, +0, 3442, 3812, +0, 3446, 3811, +0, 3450, 3811, +0, 3457, 3810, +0, 3465, 3810, +0, 3475, 3809, +0, 3490, 3808, +0, 3508, 3807, +0, 3531, 3805, +0, 3560, 3802, +0, 3591, 3802, +0, 3629, 3802, +0, 3676, 3802, +0, 3731, 3802, +0, 3796, 3802, +0, 3802, 3721, +0, 3802, 3571, +0, 3802, 3234, +0, 3937, 0, +0, 4071, 0, +3164, 4095, 0, +0, 3387, 3812, +0, 3388, 3812, +0, 3388, 3812, +0, 3388, 3812, +0, 3388, 3812, +0, 3389, 3812, +0, 3390, 3812, +0, 3391, 3812, +0, 3392, 3812, +0, 3394, 3812, +0, 3396, 3812, +0, 3399, 3812, +0, 3403, 3811, +0, 3408, 3811, +0, 3415, 3810, +0, 3424, 3810, +0, 3435, 3809, +0, 3451, 3808, +0, 3470, 3807, +0, 3495, 3805, +0, 3527, 3802, +0, 3566, 3799, +0, 3606, 3799, +0, 3655, 3799, +0, 3713, 3799, +0, 3781, 3799, +0, 3799, 3731, +0, 3799, 3585, +0, 3799, 3262, +0, 3934, 0, +0, 4069, 0, +3246, 4095, 0, +0, 3320, 3812, +0, 3321, 3812, +0, 3321, 3812, +0, 3321, 3812, +0, 3322, 3812, +0, 3322, 3812, +0, 3323, 3812, +0, 3324, 3812, +0, 3326, 3812, +0, 3328, 3812, +0, 3330, 3812, +0, 3333, 3812, +0, 3338, 3811, +0, 3344, 3811, +0, 3352, 3810, +0, 3362, 3810, +0, 3376, 3809, +0, 3393, 3808, +0, 3415, 3807, +0, 3443, 3805, +0, 3479, 3802, +0, 3522, 3799, +0, 3574, 3794, +0, 3626, 3794, +0, 3687, 3794, +0, 3759, 3794, +0, 3794, 3745, +0, 3794, 3603, +0, 3794, 3298, +0, 3931, 0, +1985, 4066, 0, +3337, 4095, 0, +0, 3211, 3812, +0, 3212, 3812, +0, 3212, 3812, +0, 3213, 3812, +0, 3213, 3812, +0, 3214, 3812, +0, 3215, 3812, +0, 3216, 3812, +0, 3218, 3812, +0, 3221, 3812, +0, 3224, 3812, +0, 3228, 3812, +0, 3234, 3811, +0, 3241, 3811, +0, 3251, 3810, +0, 3264, 3810, +0, 3281, 3809, +0, 3302, 3808, +0, 3329, 3807, +0, 3363, 3805, +0, 3405, 3802, +0, 3455, 3799, +0, 3515, 3794, +1799, 3584, 3788, +1799, 3651, 3788, +1799, 3728, 3788, +1799, 3788, 3761, +1799, 3788, 3626, +1799, 3788, 3342, +0, 3926, 2023, +2781, 4063, 0, +3436, 4095, 0, +0, 3008, 3812, +0, 3009, 3812, +0, 3009, 3812, +0, 3010, 3812, +0, 3011, 3812, +0, 3012, 3812, +0, 3014, 3812, +0, 3016, 3812, +0, 3019, 3812, +0, 3023, 3812, +0, 3027, 3812, +0, 3034, 3812, +0, 3043, 3811, +0, 3054, 3811, +0, 3069, 3810, +0, 3088, 3810, +0, 3112, 3809, +0, 3143, 3808, +0, 3181, 3807, +0, 3227, 3805, +0, 3282, 3802, +0, 3347, 3799, +0, 3421, 3794, +1799, 3505, 3788, +2721, 3597, 3780, +2721, 3682, 3780, +2721, 3776, 3780, +2721, 3780, 3655, +2721, 3780, 3394, +1928, 3920, 2556, +3119, 4058, 0, +3541, 4095, 0, +0, 2367, 3812, +0, 2369, 3812, +0, 2371, 3812, +0, 2374, 3812, +0, 2377, 3812, +0, 2382, 3812, +0, 2389, 3812, +0, 2397, 3812, +0, 2408, 3812, +0, 2422, 3812, +0, 2441, 3812, +0, 2465, 3812, +0, 2494, 3811, +0, 2531, 3811, +0, 2576, 3810, +0, 2631, 3810, +0, 2694, 3809, +0, 2767, 3808, +0, 2850, 3807, +0, 2941, 3805, +0, 3040, 3802, +0, 3145, 3799, +0, 3256, 3794, +1799, 3372, 3788, +2721, 3492, 3780, +3072, 3614, 3768, +3072, 3721, 3768, +3072, 3768, 3691, +3072, 3768, 3456, +2854, 3912, 2854, +3361, 4052, 2063, +3653, 4095, 0, +0, 0, 3812, +0, 0, 3812, +0, 0, 3812, +0, 0, 3812, +0, 0, 3812, +0, 0, 3812, +0, 0, 3812, +0, 0, 3812, +0, 0, 3812, +0, 0, 3812, +0, 0, 3812, +0, 0, 3812, +0, 0, 3811, +0, 0, 3811, +0, 0, 3810, +0, 0, 3810, +0, 0, 3809, +0, 0, 3808, +0, 0, 3807, +0, 0, 3805, +0, 1737, 3802, +0, 2519, 3799, +0, 2856, 3794, +1799, 3097, 3788, +2721, 3296, 3780, +3072, 3473, 3768, +3318, 3636, 3752, +3318, 3752, 3735, +3318, 3752, 3528, +3302, 3900, 3204, +3561, 4044, 2986, +3768, 4095, 2192, +0, 0, 3812, +0, 0, 3812, +0, 0, 3812, +0, 0, 3812, +0, 0, 3812, +0, 0, 3812, +0, 0, 3812, +0, 0, 3812, +0, 0, 3812, +0, 0, 3812, +0, 0, 3812, +0, 0, 3812, +0, 0, 3811, +0, 0, 3811, +0, 0, 3810, +0, 0, 3810, +0, 0, 3809, +0, 0, 3808, +0, 0, 3807, +0, 0, 3805, +0, 0, 3802, +0, 0, 3799, +1884, 0, 3794, +2422, 1799, 3788, +2721, 2722, 3780, +3072, 3171, 3768, +3318, 3447, 3752, +3520, 3664, 3730, +3520, 3730, 3609, +3579, 3884, 3450, +3737, 4032, 3336, +3888, 4095, 3118, +3137, 0, 3812, +3137, 0, 3812, +3137, 0, 3812, +3138, 0, 3812, +3138, 0, 3812, +3138, 0, 3812, +3139, 0, 3812, +3139, 0, 3812, +3140, 0, 3812, +3141, 0, 3812, +3143, 0, 3812, +3145, 0, 3812, +3147, 0, 3811, +3151, 0, 3811, +3155, 0, 3810, +3161, 0, 3810, +3169, 0, 3809, +3180, 0, 3808, +3194, 0, 3807, +3211, 0, 3805, +3234, 0, 3802, +3262, 0, 3799, +3298, 0, 3794, +3342, 1799, 3788, +3394, 2721, 3780, +3456, 3072, 3768, +3528, 3318, 3752, +3609, 3520, 3730, +3698, 3698, 3698, +3796, 3862, 3652, +3900, 4016, 3583, +4010, 4095, 3469, +3660, 0, 3944, +3660, 0, 3944, +3660, 0, 3944, +3660, 0, 3944, +3660, 0, 3944, +3660, 0, 3944, +3660, 0, 3944, +3660, 0, 3944, +3661, 0, 3944, +3661, 0, 3944, +3661, 0, 3944, +3662, 0, 3944, +3663, 0, 3944, +3664, 0, 3943, +3665, 0, 3943, +3667, 0, 3943, +3670, 0, 3942, +3674, 0, 3941, +3678, 0, 3940, +3685, 0, 3939, +3692, 0, 3937, +3703, 0, 3934, +3717, 0, 3931, +3735, 0, 3926, +3758, 1928, 3920, +3787, 2854, 3912, +3822, 3204, 3900, +3867, 3450, 3884, +3862, 3652, 3796, +3862, 3741, 3652, +4016, 3999, 3583, +4095, 4095, 3469, +3954, 0, 4076, +3954, 0, 4076, +3954, 0, 4076, +3954, 0, 4076, +3955, 0, 4076, +3955, 0, 4076, +3955, 0, 4076, +3955, 0, 4076, +3955, 0, 4076, +3955, 0, 4076, +3955, 0, 4076, +3956, 0, 4076, +3956, 0, 4076, +3957, 0, 4076, +3958, 0, 4075, +3959, 0, 4075, +3960, 0, 4075, +3962, 0, 4074, +3964, 0, 4073, +3968, 0, 4072, +3972, 0, 4071, +3978, 0, 4069, +3985, 0, 4066, +3995, 0, 4063, +4008, 0, 4058, +4025, 2063, 4052, +4044, 2986, 4040, +4032, 3336, 3986, +4016, 3583, 3900, +4016, 3583, 3711, +4016, 3792, 3583, +4095, 4087, 3469, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 2192, 4095, +4095, 3118, 4079, +4095, 3469, 4010, +4095, 3469, 3869, +4095, 3469, 3568, +4095, 3853, 3469, +0, 3674, 3944, +0, 3674, 3944, +0, 3674, 3944, +0, 3674, 3944, +0, 3675, 3944, +0, 3675, 3944, +0, 3675, 3944, +0, 3676, 3944, +0, 3676, 3944, +0, 3677, 3944, +0, 3678, 3944, +0, 3679, 3944, +0, 3681, 3944, +0, 3683, 3944, +0, 3687, 3944, +0, 3691, 3944, +0, 3696, 3944, +0, 3704, 3944, +0, 3713, 3944, +0, 3726, 3944, +0, 3742, 3944, +0, 3763, 3944, +0, 3790, 3944, +0, 3823, 3944, +0, 3864, 3944, +0, 3913, 3944, +0, 3944, 3915, +0, 3944, 3822, +0, 3944, 3660, +0, 3944, 3269, +0, 4076, 0, +0, 4095, 0, +0, 3674, 3944, +0, 3674, 3944, +0, 3674, 3944, +0, 3674, 3944, +0, 3675, 3944, +0, 3675, 3944, +0, 3675, 3944, +0, 3676, 3944, +0, 3676, 3944, +0, 3677, 3944, +0, 3678, 3944, +0, 3679, 3944, +0, 3681, 3944, +0, 3683, 3944, +0, 3687, 3944, +0, 3691, 3944, +0, 3696, 3944, +0, 3704, 3944, +0, 3713, 3944, +0, 3726, 3944, +0, 3742, 3944, +0, 3763, 3944, +0, 3790, 3944, +0, 3823, 3944, +0, 3864, 3944, +0, 3913, 3944, +0, 3944, 3915, +0, 3944, 3822, +0, 3944, 3660, +0, 3944, 3269, +0, 4076, 0, +0, 4095, 0, +0, 3674, 3944, +0, 3674, 3944, +0, 3674, 3944, +0, 3674, 3944, +0, 3675, 3944, +0, 3675, 3944, +0, 3675, 3944, +0, 3676, 3944, +0, 3676, 3944, +0, 3677, 3944, +0, 3678, 3944, +0, 3679, 3944, +0, 3681, 3944, +0, 3683, 3944, +0, 3687, 3944, +0, 3691, 3944, +0, 3696, 3944, +0, 3704, 3944, +0, 3713, 3944, +0, 3726, 3944, +0, 3742, 3944, +0, 3763, 3944, +0, 3790, 3944, +0, 3823, 3944, +0, 3863, 3944, +0, 3913, 3944, +0, 3944, 3915, +0, 3944, 3822, +0, 3944, 3660, +0, 3944, 3269, +0, 4076, 0, +0, 4095, 0, +0, 3674, 3944, +0, 3674, 3944, +0, 3674, 3944, +0, 3674, 3944, +0, 3674, 3944, +0, 3675, 3944, +0, 3675, 3944, +0, 3676, 3944, +0, 3676, 3944, +0, 3677, 3944, +0, 3678, 3944, +0, 3679, 3944, +0, 3681, 3944, +0, 3683, 3944, +0, 3686, 3944, +0, 3691, 3944, +0, 3696, 3944, +0, 3703, 3944, +0, 3713, 3944, +0, 3726, 3944, +0, 3742, 3944, +0, 3763, 3944, +0, 3790, 3944, +0, 3822, 3944, +0, 3863, 3944, +0, 3913, 3944, +0, 3944, 3915, +0, 3944, 3823, +0, 3944, 3660, +0, 3944, 3269, +0, 4076, 0, +0, 4095, 0, +0, 3674, 3944, +0, 3674, 3944, +0, 3674, 3944, +0, 3674, 3944, +0, 3674, 3944, +0, 3674, 3944, +0, 3675, 3944, +0, 3675, 3944, +0, 3676, 3944, +0, 3677, 3944, +0, 3678, 3944, +0, 3679, 3944, +0, 3681, 3944, +0, 3683, 3944, +0, 3686, 3944, +0, 3691, 3944, +0, 3696, 3944, +0, 3703, 3944, +0, 3713, 3944, +0, 3726, 3944, +0, 3742, 3944, +0, 3763, 3944, +0, 3789, 3944, +0, 3822, 3944, +0, 3863, 3944, +0, 3913, 3944, +0, 3944, 3915, +0, 3944, 3823, +0, 3944, 3660, +0, 3944, 3270, +0, 4076, 0, +0, 4095, 0, +0, 3674, 3944, +0, 3674, 3944, +0, 3674, 3944, +0, 3674, 3944, +0, 3674, 3944, +0, 3674, 3944, +0, 3675, 3944, +0, 3675, 3944, +0, 3676, 3944, +0, 3676, 3944, +0, 3677, 3944, +0, 3679, 3944, +0, 3681, 3944, +0, 3683, 3944, +0, 3686, 3944, +0, 3690, 3944, +0, 3696, 3944, +0, 3703, 3944, +0, 3713, 3944, +0, 3725, 3944, +0, 3742, 3944, +0, 3763, 3944, +0, 3789, 3944, +0, 3822, 3944, +0, 3863, 3944, +0, 3913, 3944, +0, 3944, 3915, +0, 3944, 3823, +0, 3944, 3660, +0, 3944, 3270, +0, 4076, 0, +0, 4095, 0, +0, 3673, 3944, +0, 3673, 3944, +0, 3673, 3944, +0, 3674, 3944, +0, 3674, 3944, +0, 3674, 3944, +0, 3674, 3944, +0, 3675, 3944, +0, 3676, 3944, +0, 3676, 3944, +0, 3677, 3944, +0, 3679, 3944, +0, 3680, 3944, +0, 3683, 3944, +0, 3686, 3944, +0, 3690, 3944, +0, 3696, 3944, +0, 3703, 3944, +0, 3713, 3944, +0, 3725, 3944, +0, 3741, 3944, +0, 3762, 3944, +0, 3789, 3944, +0, 3822, 3944, +0, 3863, 3944, +0, 3913, 3944, +0, 3944, 3915, +0, 3944, 3823, +0, 3944, 3660, +0, 3944, 3270, +0, 4076, 0, +0, 4095, 0, +0, 3673, 3944, +0, 3673, 3944, +0, 3673, 3944, +0, 3673, 3944, +0, 3673, 3944, +0, 3674, 3944, +0, 3674, 3944, +0, 3674, 3944, +0, 3675, 3944, +0, 3676, 3944, +0, 3677, 3944, +0, 3678, 3944, +0, 3680, 3944, +0, 3682, 3944, +0, 3686, 3944, +0, 3690, 3944, +0, 3695, 3944, +0, 3703, 3944, +0, 3712, 3944, +0, 3725, 3944, +0, 3741, 3944, +0, 3762, 3944, +0, 3789, 3944, +0, 3822, 3944, +0, 3863, 3944, +0, 3912, 3944, +0, 3944, 3915, +0, 3944, 3823, +0, 3944, 3660, +0, 3944, 3271, +0, 4076, 0, +0, 4095, 0, +0, 3672, 3944, +0, 3672, 3944, +0, 3673, 3944, +0, 3673, 3944, +0, 3673, 3944, +0, 3673, 3944, +0, 3673, 3944, +0, 3674, 3944, +0, 3675, 3944, +0, 3675, 3944, +0, 3676, 3944, +0, 3678, 3944, +0, 3680, 3944, +0, 3682, 3944, +0, 3685, 3944, +0, 3689, 3944, +0, 3695, 3944, +0, 3702, 3944, +0, 3712, 3944, +0, 3725, 3944, +0, 3741, 3944, +0, 3762, 3944, +0, 3788, 3944, +0, 3822, 3944, +0, 3863, 3944, +0, 3912, 3944, +0, 3944, 3915, +0, 3944, 3823, +0, 3944, 3661, +0, 3944, 3271, +0, 4076, 0, +0, 4095, 0, +0, 3671, 3944, +0, 3671, 3944, +0, 3672, 3944, +0, 3672, 3944, +0, 3672, 3944, +0, 3672, 3944, +0, 3673, 3944, +0, 3673, 3944, +0, 3674, 3944, +0, 3675, 3944, +0, 3676, 3944, +0, 3677, 3944, +0, 3679, 3944, +0, 3681, 3944, +0, 3685, 3944, +0, 3689, 3944, +0, 3694, 3944, +0, 3702, 3944, +0, 3711, 3944, +0, 3724, 3944, +0, 3740, 3944, +0, 3761, 3944, +0, 3788, 3944, +0, 3821, 3944, +0, 3862, 3944, +0, 3912, 3944, +0, 3944, 3916, +0, 3944, 3824, +0, 3944, 3661, +0, 3944, 3272, +0, 4076, 0, +0, 4095, 0, +0, 3670, 3944, +0, 3671, 3944, +0, 3671, 3944, +0, 3671, 3944, +0, 3671, 3944, +0, 3671, 3944, +0, 3672, 3944, +0, 3672, 3944, +0, 3673, 3944, +0, 3674, 3944, +0, 3675, 3944, +0, 3676, 3944, +0, 3678, 3944, +0, 3680, 3944, +0, 3684, 3944, +0, 3688, 3944, +0, 3694, 3944, +0, 3701, 3944, +0, 3711, 3944, +0, 3723, 3944, +0, 3740, 3944, +0, 3761, 3944, +0, 3787, 3944, +0, 3820, 3944, +0, 3862, 3944, +0, 3911, 3944, +0, 3944, 3916, +0, 3944, 3824, +0, 3944, 3661, +0, 3944, 3273, +0, 4076, 0, +0, 4095, 0, +0, 3669, 3944, +0, 3669, 3944, +0, 3669, 3944, +0, 3669, 3944, +0, 3670, 3944, +0, 3670, 3944, +0, 3670, 3944, +0, 3671, 3944, +0, 3671, 3944, +0, 3673, 3944, +0, 3674, 3944, +0, 3675, 3944, +0, 3677, 3944, +0, 3679, 3944, +0, 3683, 3944, +0, 3687, 3944, +0, 3692, 3944, +0, 3700, 3944, +0, 3710, 3944, +0, 3722, 3944, +0, 3739, 3944, +0, 3760, 3944, +0, 3786, 3944, +0, 3820, 3944, +0, 3861, 3944, +0, 3910, 3944, +0, 3944, 3916, +0, 3944, 3824, +0, 3944, 3662, +0, 3944, 3275, +0, 4076, 0, +0, 4095, 0, +0, 3667, 3944, +0, 3667, 3944, +0, 3668, 3944, +0, 3668, 3944, +0, 3668, 3944, +0, 3668, 3944, +0, 3668, 3944, +0, 3669, 3944, +0, 3670, 3944, +0, 3671, 3944, +0, 3672, 3944, +0, 3673, 3944, +0, 3676, 3944, +0, 3678, 3944, +0, 3681, 3944, +0, 3685, 3944, +0, 3691, 3944, +0, 3699, 3944, +0, 3708, 3944, +0, 3721, 3944, +0, 3737, 3944, +0, 3758, 3944, +0, 3785, 3944, +0, 3819, 3944, +0, 3860, 3944, +0, 3910, 3944, +0, 3944, 3917, +0, 3944, 3825, +0, 3944, 3663, +0, 3944, 3277, +0, 4076, 0, +0, 4095, 0, +0, 3665, 3944, +0, 3665, 3944, +0, 3665, 3944, +0, 3665, 3944, +0, 3665, 3944, +0, 3666, 3944, +0, 3666, 3944, +0, 3666, 3944, +0, 3667, 3944, +0, 3668, 3944, +0, 3669, 3944, +0, 3671, 3944, +0, 3673, 3944, +0, 3676, 3943, +0, 3679, 3943, +0, 3683, 3943, +0, 3689, 3943, +0, 3697, 3943, +0, 3706, 3943, +0, 3719, 3943, +0, 3736, 3943, +0, 3757, 3943, +0, 3784, 3943, +0, 3817, 3943, +0, 3859, 3943, +0, 3909, 3943, +0, 3943, 3917, +0, 3943, 3826, +0, 3943, 3664, +0, 3943, 3279, +0, 4076, 0, +0, 4095, 0, +0, 3661, 3944, +0, 3662, 3944, +0, 3662, 3944, +0, 3662, 3944, +0, 3662, 3944, +0, 3662, 3944, +0, 3663, 3944, +0, 3663, 3944, +0, 3664, 3944, +0, 3665, 3944, +0, 3666, 3944, +0, 3668, 3944, +0, 3670, 3944, +0, 3673, 3943, +0, 3677, 3943, +0, 3681, 3943, +0, 3687, 3943, +0, 3694, 3943, +0, 3704, 3943, +0, 3717, 3943, +0, 3733, 3943, +0, 3755, 3943, +0, 3781, 3943, +0, 3815, 3943, +0, 3857, 3943, +0, 3907, 3943, +0, 3943, 3918, +0, 3943, 3827, +0, 3943, 3665, +0, 3943, 3283, +0, 4075, 0, +0, 4095, 0, +0, 3657, 3944, +0, 3657, 3944, +0, 3657, 3944, +0, 3657, 3944, +0, 3658, 3944, +0, 3658, 3944, +0, 3658, 3944, +0, 3659, 3944, +0, 3659, 3944, +0, 3661, 3944, +0, 3662, 3944, +0, 3663, 3944, +0, 3666, 3944, +0, 3668, 3943, +0, 3672, 3943, +0, 3677, 3943, +0, 3683, 3943, +0, 3691, 3943, +0, 3701, 3943, +0, 3713, 3943, +0, 3730, 3943, +0, 3752, 3943, +0, 3779, 3943, +0, 3813, 3943, +0, 3854, 3943, +0, 3905, 3943, +0, 3943, 3920, +0, 3943, 3828, +0, 3943, 3667, +0, 3943, 3287, +0, 4075, 0, +0, 4095, 0, +0, 3651, 3944, +0, 3651, 3944, +0, 3651, 3944, +0, 3651, 3944, +0, 3652, 3944, +0, 3652, 3944, +0, 3652, 3944, +0, 3653, 3944, +0, 3653, 3944, +0, 3654, 3944, +0, 3656, 3944, +0, 3657, 3944, +0, 3659, 3944, +0, 3662, 3943, +0, 3666, 3943, +0, 3672, 3943, +0, 3679, 3942, +0, 3686, 3942, +0, 3696, 3942, +0, 3709, 3942, +0, 3726, 3942, +0, 3748, 3942, +0, 3775, 3942, +0, 3809, 3942, +0, 3851, 3942, +0, 3902, 3942, +0, 3942, 3921, +0, 3942, 3830, +0, 3942, 3670, +0, 3942, 3293, +0, 4075, 0, +0, 4095, 0, +0, 3643, 3944, +0, 3643, 3944, +0, 3643, 3944, +0, 3643, 3944, +0, 3643, 3944, +0, 3644, 3944, +0, 3644, 3944, +0, 3645, 3944, +0, 3645, 3944, +0, 3646, 3944, +0, 3648, 3944, +0, 3649, 3944, +0, 3651, 3944, +0, 3655, 3943, +0, 3659, 3943, +0, 3664, 3943, +0, 3671, 3942, +0, 3680, 3941, +0, 3690, 3941, +0, 3703, 3941, +0, 3720, 3941, +0, 3742, 3941, +0, 3770, 3941, +0, 3805, 3941, +0, 3847, 3941, +0, 3898, 3941, +0, 3941, 3923, +0, 3941, 3832, +0, 3941, 3674, +0, 3941, 3302, +0, 4074, 0, +0, 4095, 0, +0, 3631, 3944, +0, 3632, 3944, +0, 3632, 3944, +0, 3632, 3944, +0, 3632, 3944, +0, 3632, 3944, +0, 3633, 3944, +0, 3633, 3944, +0, 3634, 3944, +0, 3635, 3944, +0, 3636, 3944, +0, 3638, 3944, +0, 3640, 3944, +0, 3644, 3943, +0, 3648, 3943, +0, 3653, 3943, +0, 3660, 3942, +0, 3669, 3941, +0, 3682, 3940, +0, 3695, 3940, +0, 3713, 3940, +0, 3735, 3940, +0, 3763, 3940, +0, 3798, 3940, +0, 3841, 3940, +0, 3893, 3940, +0, 3940, 3926, +0, 3940, 3836, +0, 3940, 3678, +0, 3940, 3312, +0, 4073, 0, +0, 4095, 0, +0, 3616, 3944, +0, 3616, 3944, +0, 3616, 3944, +0, 3616, 3944, +0, 3617, 3944, +0, 3617, 3944, +0, 3617, 3944, +0, 3618, 3944, +0, 3619, 3944, +0, 3620, 3944, +0, 3621, 3944, +0, 3623, 3944, +0, 3625, 3944, +0, 3628, 3943, +0, 3632, 3943, +0, 3638, 3943, +0, 3646, 3942, +0, 3655, 3941, +0, 3668, 3940, +0, 3684, 3939, +0, 3702, 3939, +0, 3725, 3939, +0, 3754, 3939, +0, 3790, 3939, +0, 3833, 3939, +0, 3886, 3939, +0, 3939, 3929, +0, 3939, 3840, +0, 3939, 3685, +0, 3939, 3326, +0, 4072, 0, +0, 4095, 0, +0, 3594, 3944, +0, 3595, 3944, +0, 3595, 3944, +0, 3595, 3944, +0, 3595, 3944, +0, 3595, 3944, +0, 3596, 3944, +0, 3596, 3944, +0, 3597, 3944, +0, 3598, 3944, +0, 3600, 3944, +0, 3602, 3944, +0, 3604, 3944, +0, 3607, 3943, +0, 3612, 3943, +0, 3618, 3943, +0, 3626, 3942, +0, 3635, 3941, +0, 3649, 3940, +0, 3666, 3939, +0, 3688, 3937, +0, 3711, 3937, +0, 3741, 3937, +0, 3777, 3937, +0, 3822, 3937, +0, 3876, 3937, +0, 3937, 3934, +0, 3937, 3846, +0, 3937, 3692, +0, 3937, 3344, +0, 4071, 0, +0, 4095, 0, +0, 3564, 3944, +0, 3564, 3944, +0, 3564, 3944, +0, 3564, 3944, +0, 3564, 3944, +0, 3565, 3944, +0, 3565, 3944, +0, 3566, 3944, +0, 3567, 3944, +0, 3568, 3944, +0, 3569, 3944, +0, 3571, 3944, +0, 3574, 3944, +0, 3578, 3943, +0, 3583, 3943, +0, 3589, 3943, +0, 3597, 3942, +0, 3608, 3941, +0, 3622, 3940, +0, 3640, 3939, +0, 3663, 3937, +0, 3692, 3934, +0, 3723, 3934, +0, 3761, 3934, +0, 3808, 3934, +0, 3863, 3934, +0, 3928, 3934, +0, 3934, 3853, +0, 3934, 3703, +0, 3934, 3366, +0, 4069, 0, +0, 4095, 0, +0, 3520, 3944, +0, 3520, 3944, +0, 3520, 3944, +0, 3520, 3944, +0, 3520, 3944, +0, 3521, 3944, +0, 3521, 3944, +0, 3522, 3944, +0, 3523, 3944, +0, 3524, 3944, +0, 3526, 3944, +0, 3528, 3944, +0, 3531, 3944, +0, 3535, 3943, +0, 3540, 3943, +0, 3547, 3943, +0, 3556, 3942, +0, 3568, 3941, +0, 3583, 3940, +0, 3603, 3939, +0, 3628, 3937, +0, 3659, 3934, +0, 3698, 3931, +0, 3738, 3931, +0, 3787, 3931, +0, 3845, 3931, +0, 3913, 3931, +0, 3931, 3863, +0, 3931, 3717, +0, 3931, 3395, +0, 4066, 0, +0, 4095, 0, +0, 3452, 3944, +0, 3452, 3944, +0, 3453, 3944, +0, 3453, 3944, +0, 3453, 3944, +0, 3454, 3944, +0, 3454, 3944, +0, 3455, 3944, +0, 3456, 3944, +0, 3458, 3944, +0, 3459, 3944, +0, 3462, 3944, +0, 3466, 3944, +0, 3470, 3943, +0, 3476, 3943, +0, 3484, 3943, +0, 3494, 3942, +0, 3507, 3941, +0, 3525, 3940, +0, 3547, 3939, +0, 3575, 3937, +0, 3611, 3934, +0, 3654, 3931, +0, 3706, 3926, +0, 3758, 3926, +0, 3820, 3926, +0, 3891, 3926, +0, 3926, 3877, +0, 3926, 3735, +0, 3926, 3430, +0, 4063, 0, +2137, 4095, 0, +0, 3344, 3944, +0, 3344, 3944, +0, 3344, 3944, +0, 3344, 3944, +0, 3345, 3944, +0, 3346, 3944, +0, 3346, 3944, +0, 3347, 3944, +0, 3349, 3944, +0, 3351, 3944, +0, 3353, 3944, +0, 3356, 3944, +0, 3361, 3944, +0, 3366, 3943, +0, 3374, 3943, +0, 3384, 3943, +0, 3396, 3942, +0, 3413, 3941, +0, 3434, 3940, +0, 3461, 3939, +0, 3495, 3937, +0, 3537, 3934, +0, 3587, 3931, +0, 3647, 3926, +1928, 3716, 3920, +1928, 3783, 3920, +1928, 3860, 3920, +1928, 3920, 3893, +1928, 3920, 3758, +1928, 3920, 3474, +0, 4058, 2157, +2915, 4095, 0, +0, 3140, 3944, +0, 3140, 3944, +0, 3140, 3944, +0, 3141, 3944, +0, 3142, 3944, +0, 3143, 3944, +0, 3144, 3944, +0, 3145, 3944, +0, 3147, 3944, +0, 3151, 3944, +0, 3154, 3944, +0, 3159, 3944, +0, 3166, 3944, +0, 3175, 3943, +0, 3186, 3943, +0, 3201, 3943, +0, 3220, 3942, +0, 3244, 3941, +0, 3275, 3940, +0, 3313, 3939, +0, 3359, 3937, +0, 3414, 3934, +0, 3479, 3931, +0, 3553, 3926, +1928, 3637, 3920, +2854, 3729, 3912, +2854, 3814, 3912, +2854, 3908, 3912, +2854, 3912, 3787, +2854, 3912, 3526, +2063, 4052, 2689, +3253, 4095, 0, +0, 2497, 3944, +0, 2498, 3944, +0, 2500, 3944, +0, 2502, 3944, +0, 2505, 3944, +0, 2508, 3944, +0, 2513, 3944, +0, 2520, 3944, +0, 2528, 3944, +0, 2539, 3944, +0, 2553, 3944, +0, 2572, 3944, +0, 2596, 3944, +0, 2625, 3943, +0, 2662, 3943, +0, 2708, 3943, +0, 2762, 3942, +0, 2826, 3941, +0, 2899, 3940, +0, 2982, 3939, +0, 3073, 3937, +0, 3172, 3934, +0, 3277, 3931, +0, 3388, 3926, +1928, 3504, 3920, +2854, 3624, 3912, +3204, 3746, 3900, +3204, 3853, 3900, +3204, 3900, 3822, +3204, 3900, 3588, +2987, 4044, 2986, +3494, 4095, 2192, +0, 0, 3944, +0, 0, 3944, +0, 0, 3944, +0, 0, 3944, +0, 0, 3944, +0, 0, 3944, +0, 0, 3944, +0, 0, 3944, +0, 0, 3944, +0, 0, 3944, +0, 0, 3944, +0, 0, 3944, +0, 0, 3944, +0, 0, 3943, +0, 0, 3943, +0, 0, 3943, +0, 0, 3942, +0, 0, 3941, +0, 0, 3940, +0, 0, 3939, +0, 0, 3937, +0, 1863, 3934, +0, 2650, 3931, +0, 2988, 3926, +1928, 3229, 3920, +2854, 3428, 3912, +3204, 3605, 3900, +3450, 3768, 3884, +3450, 3884, 3867, +3450, 3884, 3660, +3435, 4032, 3336, +3693, 4095, 3118, +0, 0, 3944, +0, 0, 3944, +0, 0, 3944, +0, 0, 3944, +0, 0, 3944, +0, 0, 3944, +0, 0, 3944, +0, 0, 3944, +0, 0, 3944, +0, 0, 3944, +0, 0, 3944, +0, 0, 3944, +0, 0, 3944, +0, 0, 3943, +0, 0, 3943, +0, 0, 3943, +0, 0, 3942, +0, 0, 3941, +0, 0, 3940, +0, 0, 3939, +0, 0, 3937, +0, 0, 3934, +0, 0, 3931, +2023, 0, 3926, +2556, 1928, 3920, +2854, 2854, 3912, +3204, 3302, 3900, +3450, 3579, 3884, +3652, 3796, 3862, +3652, 3862, 3741, +3711, 4016, 3583, +3869, 4095, 3469, +3269, 0, 3944, +3269, 0, 3944, +3269, 0, 3944, +3269, 0, 3944, +3270, 0, 3944, +3270, 0, 3944, +3270, 0, 3944, +3271, 0, 3944, +3271, 0, 3944, +3272, 0, 3944, +3273, 0, 3944, +3275, 0, 3944, +3277, 0, 3944, +3279, 0, 3943, +3283, 0, 3943, +3287, 0, 3943, +3293, 0, 3942, +3302, 0, 3941, +3312, 0, 3940, +3326, 0, 3939, +3344, 0, 3937, +3366, 0, 3934, +3395, 0, 3931, +3430, 0, 3926, +3474, 1928, 3920, +3526, 2854, 3912, +3588, 3204, 3900, +3660, 3450, 3884, +3741, 3652, 3862, +3830, 3830, 3830, +3928, 3994, 3784, +4032, 4095, 3714, +3791, 0, 4076, +3792, 0, 4076, +3792, 0, 4076, +3792, 0, 4076, +3792, 0, 4076, +3792, 0, 4076, +3792, 0, 4076, +3792, 0, 4076, +3792, 0, 4076, +3793, 0, 4076, +3793, 0, 4076, +3793, 0, 4076, +3794, 0, 4076, +3795, 0, 4076, +3796, 0, 4075, +3797, 0, 4075, +3799, 0, 4075, +3802, 0, 4074, +3805, 0, 4073, +3810, 0, 4072, +3816, 0, 4071, +3824, 0, 4069, +3835, 0, 4066, +3849, 0, 4063, +3867, 0, 4058, +3890, 2063, 4052, +3919, 2986, 4044, +3955, 3336, 4032, +3999, 3583, 4016, +3994, 3784, 3928, +3994, 3873, 3784, +4095, 4095, 3714, +4087, 0, 4095, +4087, 0, 4095, +4087, 0, 4095, +4087, 0, 4095, +4087, 0, 4095, +4087, 0, 4095, +4087, 0, 4095, +4087, 0, 4095, +4087, 0, 4095, +4088, 0, 4095, +4088, 0, 4095, +4088, 0, 4095, +4088, 0, 4095, +4089, 0, 4095, +4089, 0, 4095, +4090, 0, 4095, +4091, 0, 4095, +4092, 0, 4095, +4094, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 0, 4095, +4095, 2192, 4095, +4095, 3118, 4095, +4095, 3469, 4095, +4095, 3714, 4032, +4095, 3714, 3844, +4095, 3924, 3714, +0, 3806, 4076, +0, 3806, 4076, +0, 3806, 4076, +0, 3806, 4076, +0, 3807, 4076, +0, 3807, 4076, +0, 3807, 4076, +0, 3808, 4076, +0, 3808, 4076, +0, 3808, 4076, +0, 3809, 4076, +0, 3810, 4076, +0, 3812, 4076, +0, 3813, 4076, +0, 3816, 4076, +0, 3819, 4076, +0, 3823, 4076, +0, 3828, 4076, +0, 3836, 4076, +0, 3846, 4076, +0, 3858, 4076, +0, 3874, 4076, +0, 3895, 4076, +0, 3922, 4076, +0, 3955, 4076, +0, 3996, 4076, +0, 4045, 4076, +0, 4076, 4047, +0, 4076, 3954, +0, 4076, 3791, +0, 4076, 3401, +0, 4095, 0, +0, 3806, 4076, +0, 3806, 4076, +0, 3806, 4076, +0, 3806, 4076, +0, 3807, 4076, +0, 3807, 4076, +0, 3807, 4076, +0, 3807, 4076, +0, 3808, 4076, +0, 3808, 4076, +0, 3809, 4076, +0, 3810, 4076, +0, 3811, 4076, +0, 3813, 4076, +0, 3816, 4076, +0, 3819, 4076, +0, 3823, 4076, +0, 3828, 4076, +0, 3836, 4076, +0, 3845, 4076, +0, 3858, 4076, +0, 3874, 4076, +0, 3895, 4076, +0, 3922, 4076, +0, 3955, 4076, +0, 3996, 4076, +0, 4045, 4076, +0, 4076, 4047, +0, 4076, 3954, +0, 4076, 3792, +0, 4076, 3401, +0, 4095, 0, +0, 3806, 4076, +0, 3806, 4076, +0, 3806, 4076, +0, 3806, 4076, +0, 3807, 4076, +0, 3807, 4076, +0, 3807, 4076, +0, 3807, 4076, +0, 3808, 4076, +0, 3808, 4076, +0, 3809, 4076, +0, 3810, 4076, +0, 3811, 4076, +0, 3813, 4076, +0, 3816, 4076, +0, 3819, 4076, +0, 3823, 4076, +0, 3828, 4076, +0, 3836, 4076, +0, 3845, 4076, +0, 3858, 4076, +0, 3874, 4076, +0, 3895, 4076, +0, 3921, 4076, +0, 3955, 4076, +0, 3996, 4076, +0, 4045, 4076, +0, 4076, 4047, +0, 4076, 3954, +0, 4076, 3792, +0, 4076, 3401, +0, 4095, 0, +0, 3806, 4076, +0, 3806, 4076, +0, 3806, 4076, +0, 3806, 4076, +0, 3806, 4076, +0, 3807, 4076, +0, 3807, 4076, +0, 3807, 4076, +0, 3808, 4076, +0, 3808, 4076, +0, 3809, 4076, +0, 3810, 4076, +0, 3811, 4076, +0, 3813, 4076, +0, 3815, 4076, +0, 3818, 4076, +0, 3823, 4076, +0, 3828, 4076, +0, 3836, 4076, +0, 3845, 4076, +0, 3858, 4076, +0, 3874, 4076, +0, 3895, 4076, +0, 3921, 4076, +0, 3955, 4076, +0, 3995, 4076, +0, 4045, 4076, +0, 4076, 4047, +0, 4076, 3954, +0, 4076, 3792, +0, 4076, 3401, +0, 4095, 0, +0, 3806, 4076, +0, 3806, 4076, +0, 3806, 4076, +0, 3806, 4076, +0, 3806, 4076, +0, 3807, 4076, +0, 3807, 4076, +0, 3807, 4076, +0, 3808, 4076, +0, 3808, 4076, +0, 3809, 4076, +0, 3810, 4076, +0, 3811, 4076, +0, 3813, 4076, +0, 3815, 4076, +0, 3818, 4076, +0, 3823, 4076, +0, 3828, 4076, +0, 3836, 4076, +0, 3845, 4076, +0, 3858, 4076, +0, 3874, 4076, +0, 3895, 4076, +0, 3921, 4076, +0, 3955, 4076, +0, 3995, 4076, +0, 4045, 4076, +0, 4076, 4047, +0, 4076, 3955, +0, 4076, 3792, +0, 4076, 3401, +0, 4095, 0, +0, 3806, 4076, +0, 3806, 4076, +0, 3806, 4076, +0, 3806, 4076, +0, 3806, 4076, +0, 3806, 4076, +0, 3807, 4076, +0, 3807, 4076, +0, 3808, 4076, +0, 3808, 4076, +0, 3809, 4076, +0, 3810, 4076, +0, 3811, 4076, +0, 3813, 4076, +0, 3815, 4076, +0, 3818, 4076, +0, 3822, 4076, +0, 3828, 4076, +0, 3835, 4076, +0, 3845, 4076, +0, 3858, 4076, +0, 3874, 4076, +0, 3895, 4076, +0, 3921, 4076, +0, 3954, 4076, +0, 3995, 4076, +0, 4045, 4076, +0, 4076, 4047, +0, 4076, 3955, +0, 4076, 3792, +0, 4076, 3402, +0, 4095, 0, +0, 3805, 4076, +0, 3805, 4076, +0, 3805, 4076, +0, 3806, 4076, +0, 3806, 4076, +0, 3806, 4076, +0, 3806, 4076, +0, 3807, 4076, +0, 3807, 4076, +0, 3808, 4076, +0, 3808, 4076, +0, 3810, 4076, +0, 3811, 4076, +0, 3812, 4076, +0, 3815, 4076, +0, 3818, 4076, +0, 3822, 4076, +0, 3828, 4076, +0, 3835, 4076, +0, 3845, 4076, +0, 3858, 4076, +0, 3874, 4076, +0, 3895, 4076, +0, 3921, 4076, +0, 3954, 4076, +0, 3995, 4076, +0, 4045, 4076, +0, 4076, 4047, +0, 4076, 3955, +0, 4076, 3792, +0, 4076, 3402, +0, 4095, 0, +0, 3805, 4076, +0, 3805, 4076, +0, 3805, 4076, +0, 3805, 4076, +0, 3805, 4076, +0, 3806, 4076, +0, 3806, 4076, +0, 3806, 4076, +0, 3807, 4076, +0, 3808, 4076, +0, 3808, 4076, +0, 3809, 4076, +0, 3810, 4076, +0, 3812, 4076, +0, 3815, 4076, +0, 3818, 4076, +0, 3822, 4076, +0, 3828, 4076, +0, 3835, 4076, +0, 3845, 4076, +0, 3857, 4076, +0, 3873, 4076, +0, 3895, 4076, +0, 3921, 4076, +0, 3954, 4076, +0, 3995, 4076, +0, 4045, 4076, +0, 4076, 4047, +0, 4076, 3955, +0, 4076, 3792, +0, 4076, 3402, +0, 4095, 0, +0, 3805, 4076, +0, 3805, 4076, +0, 3805, 4076, +0, 3805, 4076, +0, 3805, 4076, +0, 3805, 4076, +0, 3805, 4076, +0, 3806, 4076, +0, 3807, 4076, +0, 3807, 4076, +0, 3808, 4076, +0, 3809, 4076, +0, 3810, 4076, +0, 3812, 4076, +0, 3814, 4076, +0, 3818, 4076, +0, 3822, 4076, +0, 3827, 4076, +0, 3835, 4076, +0, 3845, 4076, +0, 3857, 4076, +0, 3873, 4076, +0, 3894, 4076, +0, 3921, 4076, +0, 3954, 4076, +0, 3995, 4076, +0, 4044, 4076, +0, 4076, 4047, +0, 4076, 3955, +0, 4076, 3792, +0, 4076, 3403, +0, 4095, 0, +0, 3804, 4076, +0, 3804, 4076, +0, 3804, 4076, +0, 3805, 4076, +0, 3805, 4076, +0, 3805, 4076, +0, 3805, 4076, +0, 3805, 4076, +0, 3806, 4076, +0, 3807, 4076, +0, 3808, 4076, +0, 3808, 4076, +0, 3810, 4076, +0, 3812, 4076, +0, 3814, 4076, +0, 3817, 4076, +0, 3821, 4076, +0, 3827, 4076, +0, 3834, 4076, +0, 3844, 4076, +0, 3856, 4076, +0, 3873, 4076, +0, 3894, 4076, +0, 3921, 4076, +0, 3953, 4076, +0, 3995, 4076, +0, 4044, 4076, +0, 4076, 4047, +0, 4076, 3955, +0, 4076, 3793, +0, 4076, 3403, +0, 4095, 0, +0, 3803, 4076, +0, 3803, 4076, +0, 3803, 4076, +0, 3804, 4076, +0, 3804, 4076, +0, 3804, 4076, +0, 3804, 4076, +0, 3805, 4076, +0, 3805, 4076, +0, 3806, 4076, +0, 3807, 4076, +0, 3808, 4076, +0, 3809, 4076, +0, 3811, 4076, +0, 3813, 4076, +0, 3816, 4076, +0, 3821, 4076, +0, 3826, 4076, +0, 3834, 4076, +0, 3843, 4076, +0, 3856, 4076, +0, 3872, 4076, +0, 3893, 4076, +0, 3920, 4076, +0, 3953, 4076, +0, 3994, 4076, +0, 4044, 4076, +0, 4076, 4048, +0, 4076, 3955, +0, 4076, 3793, +0, 4076, 3404, +0, 4095, 0, +0, 3803, 4076, +0, 3803, 4076, +0, 3803, 4076, +0, 3803, 4076, +0, 3803, 4076, +0, 3803, 4076, +0, 3803, 4076, +0, 3804, 4076, +0, 3804, 4076, +0, 3805, 4076, +0, 3806, 4076, +0, 3807, 4076, +0, 3808, 4076, +0, 3810, 4076, +0, 3812, 4076, +0, 3816, 4076, +0, 3820, 4076, +0, 3826, 4076, +0, 3833, 4076, +0, 3843, 4076, +0, 3855, 4076, +0, 3872, 4076, +0, 3892, 4076, +0, 3919, 4076, +0, 3953, 4076, +0, 3994, 4076, +0, 4043, 4076, +0, 4076, 4048, +0, 4076, 3956, +0, 4076, 3793, +0, 4076, 3405, +0, 4095, 0, +0, 3801, 4076, +0, 3801, 4076, +0, 3801, 4076, +0, 3801, 4076, +0, 3801, 4076, +0, 3802, 4076, +0, 3802, 4076, +0, 3802, 4076, +0, 3803, 4076, +0, 3803, 4076, +0, 3804, 4076, +0, 3805, 4076, +0, 3807, 4076, +0, 3809, 4076, +0, 3812, 4076, +0, 3814, 4076, +0, 3819, 4076, +0, 3824, 4076, +0, 3832, 4076, +0, 3841, 4076, +0, 3854, 4076, +0, 3871, 4076, +0, 3891, 4076, +0, 3918, 4076, +0, 3952, 4076, +0, 3993, 4076, +0, 4043, 4076, +0, 4076, 4048, +0, 4076, 3956, +0, 4076, 3794, +0, 4076, 3407, +0, 4095, 0, +0, 3799, 4076, +0, 3799, 4076, +0, 3799, 4076, +0, 3799, 4076, +0, 3800, 4076, +0, 3800, 4076, +0, 3800, 4076, +0, 3801, 4076, +0, 3801, 4076, +0, 3802, 4076, +0, 3803, 4076, +0, 3804, 4076, +0, 3805, 4076, +0, 3808, 4076, +0, 3810, 4076, +0, 3813, 4076, +0, 3817, 4076, +0, 3823, 4076, +0, 3830, 4076, +0, 3840, 4076, +0, 3853, 4076, +0, 3869, 4076, +0, 3890, 4076, +0, 3917, 4076, +0, 3950, 4076, +0, 3992, 4076, +0, 4042, 4076, +0, 4076, 4049, +0, 4076, 3957, +0, 4076, 3795, +0, 4076, 3409, +0, 4095, 0, +0, 3797, 4076, +0, 3797, 4076, +0, 3797, 4076, +0, 3797, 4076, +0, 3797, 4076, +0, 3797, 4076, +0, 3798, 4076, +0, 3798, 4076, +0, 3798, 4076, +0, 3799, 4076, +0, 3800, 4076, +0, 3801, 4076, +0, 3803, 4076, +0, 3805, 4076, +0, 3808, 4075, +0, 3811, 4075, +0, 3816, 4075, +0, 3821, 4075, +0, 3829, 4075, +0, 3838, 4075, +0, 3851, 4075, +0, 3868, 4075, +0, 3889, 4075, +0, 3916, 4075, +0, 3949, 4075, +0, 3991, 4075, +0, 4041, 4075, +0, 4075, 4049, +0, 4075, 3958, +0, 4075, 3796, +0, 4075, 3411, +0, 4095, 0, +0, 3793, 4076, +0, 3793, 4076, +0, 3793, 4076, +0, 3794, 4076, +0, 3794, 4076, +0, 3794, 4076, +0, 3794, 4076, +0, 3795, 4076, +0, 3795, 4076, +0, 3796, 4076, +0, 3797, 4076, +0, 3798, 4076, +0, 3800, 4076, +0, 3802, 4076, +0, 3805, 4075, +0, 3809, 4075, +0, 3813, 4075, +0, 3818, 4075, +0, 3826, 4075, +0, 3836, 4075, +0, 3849, 4075, +0, 3865, 4075, +0, 3887, 4075, +0, 3913, 4075, +0, 3947, 4075, +0, 3989, 4075, +0, 4039, 4075, +0, 4075, 4050, +0, 4075, 3959, +0, 4075, 3797, +0, 4075, 3415, +0, 4095, 0, +0, 3789, 4076, +0, 3789, 4076, +0, 3789, 4076, +0, 3789, 4076, +0, 3790, 4076, +0, 3790, 4076, +0, 3790, 4076, +0, 3790, 4076, +0, 3791, 4076, +0, 3791, 4076, +0, 3793, 4076, +0, 3794, 4076, +0, 3795, 4076, +0, 3798, 4076, +0, 3801, 4075, +0, 3804, 4075, +0, 3810, 4075, +0, 3815, 4075, +0, 3823, 4075, +0, 3833, 4075, +0, 3846, 4075, +0, 3862, 4075, +0, 3884, 4075, +0, 3911, 4075, +0, 3945, 4075, +0, 3986, 4075, +0, 4037, 4075, +0, 4075, 4051, +0, 4075, 3960, +0, 4075, 3799, +0, 4075, 3419, +0, 4095, 0, +0, 3783, 4076, +0, 3783, 4076, +0, 3783, 4076, +0, 3783, 4076, +0, 3783, 4076, +0, 3784, 4076, +0, 3784, 4076, +0, 3784, 4076, +0, 3785, 4076, +0, 3785, 4076, +0, 3787, 4076, +0, 3787, 4076, +0, 3789, 4076, +0, 3792, 4076, +0, 3795, 4075, +0, 3798, 4075, +0, 3803, 4075, +0, 3810, 4074, +0, 3818, 4074, +0, 3828, 4074, +0, 3841, 4074, +0, 3858, 4074, +0, 3880, 4074, +0, 3907, 4074, +0, 3941, 4074, +0, 3983, 4074, +0, 4034, 4074, +0, 4074, 4053, +0, 4074, 3962, +0, 4074, 3802, +0, 4074, 3426, +0, 4095, 0, +0, 3774, 4076, +0, 3775, 4076, +0, 3775, 4076, +0, 3775, 4076, +0, 3775, 4076, +0, 3775, 4076, +0, 3776, 4076, +0, 3776, 4076, +0, 3777, 4076, +0, 3777, 4076, +0, 3778, 4076, +0, 3780, 4076, +0, 3781, 4076, +0, 3784, 4076, +0, 3787, 4075, +0, 3790, 4075, +0, 3796, 4075, +0, 3803, 4074, +0, 3812, 4073, +0, 3822, 4073, +0, 3835, 4073, +0, 3852, 4073, +0, 3874, 4073, +0, 3902, 4073, +0, 3937, 4073, +0, 3979, 4073, +0, 4030, 4073, +0, 4073, 4055, +0, 4073, 3964, +0, 4073, 3805, +0, 4073, 3434, +0, 4095, 0, +0, 3763, 4076, +0, 3763, 4076, +0, 3763, 4076, +0, 3764, 4076, +0, 3764, 4076, +0, 3764, 4076, +0, 3764, 4076, +0, 3765, 4076, +0, 3765, 4076, +0, 3766, 4076, +0, 3767, 4076, +0, 3768, 4076, +0, 3770, 4076, +0, 3773, 4076, +0, 3776, 4075, +0, 3780, 4075, +0, 3785, 4075, +0, 3792, 4074, +0, 3801, 4073, +0, 3814, 4072, +0, 3827, 4072, +0, 3845, 4072, +0, 3867, 4072, +0, 3895, 4072, +0, 3930, 4072, +0, 3973, 4072, +0, 4025, 4072, +0, 4072, 4058, +0, 4072, 3968, +0, 4072, 3810, +0, 4072, 3444, +0, 4095, 0, +0, 3748, 4076, +0, 3748, 4076, +0, 3748, 4076, +0, 3748, 4076, +0, 3748, 4076, +0, 3749, 4076, +0, 3749, 4076, +0, 3749, 4076, +0, 3750, 4076, +0, 3751, 4076, +0, 3752, 4076, +0, 3753, 4076, +0, 3755, 4076, +0, 3757, 4076, +0, 3760, 4075, +0, 3765, 4075, +0, 3770, 4075, +0, 3777, 4074, +0, 3787, 4073, +0, 3800, 4072, +0, 3816, 4071, +0, 3834, 4071, +0, 3857, 4071, +0, 3886, 4071, +0, 3921, 4071, +0, 3965, 4071, +0, 4018, 4071, +0, 4071, 4061, +0, 4071, 3972, +0, 4071, 3816, +0, 4071, 3458, +0, 4095, 0, +0, 3726, 4076, +0, 3726, 4076, +0, 3726, 4076, +0, 3727, 4076, +0, 3727, 4076, +0, 3727, 4076, +0, 3727, 4076, +0, 3728, 4076, +0, 3728, 4076, +0, 3729, 4076, +0, 3730, 4076, +0, 3732, 4076, +0, 3734, 4076, +0, 3736, 4076, +0, 3739, 4075, +0, 3744, 4075, +0, 3750, 4075, +0, 3757, 4074, +0, 3768, 4073, +0, 3781, 4072, +0, 3798, 4071, +0, 3820, 4069, +0, 3843, 4069, +0, 3873, 4069, +0, 3910, 4069, +0, 3954, 4069, +0, 4008, 4069, +0, 4069, 4066, +0, 4069, 3978, +0, 4069, 3824, +0, 4069, 3475, +0, 4095, 0, +0, 3696, 4076, +0, 3696, 4076, +0, 3696, 4076, +0, 3696, 4076, +0, 3696, 4076, +0, 3696, 4076, +0, 3697, 4076, +0, 3697, 4076, +0, 3698, 4076, +0, 3699, 4076, +0, 3700, 4076, +0, 3701, 4076, +0, 3703, 4076, +0, 3706, 4076, +0, 3710, 4075, +0, 3714, 4075, +0, 3721, 4075, +0, 3729, 4074, +0, 3740, 4073, +0, 3754, 4072, +0, 3772, 4071, +0, 3795, 4069, +0, 3824, 4066, +0, 3855, 4066, +0, 3893, 4066, +0, 3940, 4066, +0, 3995, 4066, +0, 4060, 4066, +0, 4066, 3985, +0, 4066, 3835, +0, 4066, 3498, +0, 4095, 0, +0, 3651, 4076, +0, 3651, 4076, +0, 3651, 4076, +0, 3652, 4076, +0, 3652, 4076, +0, 3652, 4076, +0, 3653, 4076, +0, 3653, 4076, +0, 3654, 4076, +0, 3655, 4076, +0, 3656, 4076, +0, 3658, 4076, +0, 3660, 4076, +0, 3663, 4076, +0, 3667, 4075, +0, 3672, 4075, +0, 3679, 4075, +0, 3688, 4074, +0, 3700, 4073, +0, 3715, 4072, +0, 3735, 4071, +0, 3760, 4069, +0, 3791, 4066, +0, 3830, 4063, +0, 3870, 4063, +0, 3919, 4063, +0, 3977, 4063, +0, 4045, 4063, +0, 4063, 3995, +0, 4063, 3849, +0, 4063, 3527, +0, 4095, 0, +0, 3584, 4076, +0, 3584, 4076, +0, 3585, 4076, +0, 3585, 4076, +0, 3585, 4076, +0, 3585, 4076, +0, 3586, 4076, +0, 3586, 4076, +0, 3587, 4076, +0, 3588, 4076, +0, 3590, 4076, +0, 3592, 4076, +0, 3594, 4076, +0, 3597, 4076, +0, 3602, 4075, +0, 3608, 4075, +0, 3616, 4075, +0, 3626, 4074, +0, 3640, 4073, +0, 3657, 4072, +0, 3679, 4071, +0, 3708, 4069, +0, 3743, 4066, +0, 3786, 4063, +0, 3838, 4058, +0, 3890, 4058, +0, 3952, 4058, +0, 4023, 4058, +0, 4058, 4008, +0, 4058, 3867, +0, 4058, 3562, +0, 4095, 0, +0, 3475, 4076, +0, 3475, 4076, +0, 3476, 4076, +0, 3476, 4076, +0, 3476, 4076, +0, 3477, 4076, +0, 3477, 4076, +0, 3478, 4076, +0, 3479, 4076, +0, 3480, 4076, +0, 3482, 4076, +0, 3485, 4076, +0, 3488, 4076, +0, 3492, 4076, +0, 3498, 4075, +0, 3505, 4075, +0, 3515, 4075, +0, 3528, 4074, +0, 3545, 4073, +0, 3566, 4072, +0, 3593, 4071, +0, 3627, 4069, +0, 3669, 4066, +0, 3719, 4063, +0, 3779, 4058, +2063, 3848, 4052, +2063, 3915, 4052, +2063, 3992, 4052, +2063, 4052, 4025, +2063, 4052, 3890, +2063, 4052, 3606, +0, 4095, 2266, +0, 3271, 4076, +0, 3272, 4076, +0, 3272, 4076, +0, 3272, 4076, +0, 3273, 4076, +0, 3273, 4076, +0, 3274, 4076, +0, 3276, 4076, +0, 3277, 4076, +0, 3279, 4076, +0, 3282, 4076, +0, 3286, 4076, +0, 3291, 4076, +0, 3297, 4076, +0, 3306, 4075, +0, 3318, 4075, +0, 3333, 4075, +0, 3351, 4074, +0, 3376, 4073, +0, 3407, 4072, +0, 3445, 4071, +0, 3491, 4069, +0, 3546, 4066, +0, 3611, 4063, +0, 3685, 4058, +2063, 3769, 4052, +2986, 3861, 4044, +2986, 3947, 4044, +2986, 4040, 4044, +2986, 4044, 3919, +2986, 4044, 3659, +2192, 4095, 2814, +0, 2626, 4076, +0, 2627, 4076, +0, 2628, 4076, +0, 2630, 4076, +0, 2632, 4076, +0, 2635, 4076, +0, 2639, 4076, +0, 2644, 4076, +0, 2650, 4076, +0, 2659, 4076, +0, 2670, 4076, +0, 2684, 4076, +0, 2703, 4076, +0, 2726, 4076, +0, 2756, 4075, +0, 2793, 4075, +0, 2839, 4075, +0, 2893, 4074, +0, 2957, 4073, +0, 3031, 4072, +0, 3113, 4071, +0, 3205, 4069, +0, 3303, 4066, +0, 3409, 4063, +0, 3520, 4058, +2063, 3636, 4052, +2986, 3755, 4044, +3336, 3878, 4032, +3336, 3986, 4032, +3336, 4032, 3955, +3336, 4032, 3720, +3121, 4095, 3118, +0, 0, 4076, +0, 0, 4076, +0, 0, 4076, +0, 0, 4076, +0, 0, 4076, +0, 0, 4076, +0, 0, 4076, +0, 0, 4076, +0, 0, 4076, +0, 0, 4076, +0, 0, 4076, +0, 0, 4076, +0, 0, 4076, +0, 0, 4076, +0, 0, 4075, +0, 0, 4075, +0, 0, 4075, +0, 0, 4074, +0, 0, 4073, +0, 0, 4072, +0, 0, 4071, +0, 0, 4069, +0, 1985, 4066, +0, 2781, 4063, +0, 3119, 4058, +2063, 3361, 4052, +2986, 3561, 4044, +3336, 3737, 4032, +3583, 3900, 4016, +3583, 4016, 3999, +3583, 4016, 3792, +3568, 4095, 3469, +0, 0, 4076, +0, 0, 4076, +0, 0, 4076, +0, 0, 4076, +0, 0, 4076, +0, 0, 4076, +0, 0, 4076, +0, 0, 4076, +0, 0, 4076, +0, 0, 4076, +0, 0, 4076, +0, 0, 4076, +0, 0, 4076, +0, 0, 4076, +0, 0, 4075, +0, 0, 4075, +0, 0, 4075, +0, 0, 4074, +0, 0, 4073, +0, 0, 4072, +0, 0, 4071, +0, 0, 4069, +0, 0, 4066, +0, 0, 4063, +2157, 0, 4058, +2689, 2063, 4052, +2986, 2987, 4044, +3336, 3435, 4032, +3583, 3711, 4016, +3784, 3928, 3994, +3784, 3994, 3873, +3844, 4095, 3714, +3401, 0, 4076, +3401, 0, 4076, +3401, 0, 4076, +3401, 0, 4076, +3401, 0, 4076, +3402, 0, 4076, +3402, 0, 4076, +3402, 0, 4076, +3403, 0, 4076, +3403, 0, 4076, +3404, 0, 4076, +3405, 0, 4076, +3407, 0, 4076, +3409, 0, 4076, +3411, 0, 4075, +3415, 0, 4075, +3419, 0, 4075, +3426, 0, 4074, +3434, 0, 4073, +3444, 0, 4072, +3458, 0, 4071, +3475, 0, 4069, +3498, 0, 4066, +3527, 0, 4063, +3562, 0, 4058, +3606, 2063, 4052, +3659, 2986, 4044, +3720, 3336, 4032, +3792, 3583, 4016, +3873, 3784, 3994, +3962, 3962, 3962, +4060, 4095, 3916, +3924, 0, 4095, +3924, 0, 4095, +3924, 0, 4095, +3924, 0, 4095, +3924, 0, 4095, +3925, 0, 4095, +3925, 0, 4095, +3925, 0, 4095, +3925, 0, 4095, +3925, 0, 4095, +3925, 0, 4095, +3926, 0, 4095, +3926, 0, 4095, +3927, 0, 4095, +3927, 0, 4095, +3929, 0, 4095, +3930, 0, 4095, +3932, 0, 4095, +3935, 0, 4095, +3938, 0, 4095, +3943, 0, 4095, +3949, 0, 4095, +3957, 0, 4095, +3968, 0, 4095, +3982, 0, 4095, +4000, 0, 4095, +4023, 2192, 4095, +4051, 3118, 4095, +4087, 3469, 4095, +4095, 3714, 4095, +4095, 3916, 4060, +4095, 4005, 3916, +0, 3939, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3940, 4095, +0, 3940, 4095, +0, 3941, 4095, +0, 3941, 4095, +0, 3942, 4095, +0, 3944, 4095, +0, 3946, 4095, +0, 3948, 4095, +0, 3951, 4095, +0, 3955, 4095, +0, 3961, 4095, +0, 3968, 4095, +0, 3978, 4095, +0, 3990, 4095, +0, 4007, 4095, +0, 4027, 4095, +0, 4054, 4095, +0, 4087, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4087, +0, 4095, 3924, +0, 4095, 3533, +0, 3939, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3940, 4095, +0, 3940, 4095, +0, 3941, 4095, +0, 3941, 4095, +0, 3942, 4095, +0, 3944, 4095, +0, 3946, 4095, +0, 3948, 4095, +0, 3951, 4095, +0, 3955, 4095, +0, 3961, 4095, +0, 3968, 4095, +0, 3978, 4095, +0, 3990, 4095, +0, 4006, 4095, +0, 4027, 4095, +0, 4054, 4095, +0, 4087, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4087, +0, 4095, 3924, +0, 4095, 3533, +0, 3938, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3940, 4095, +0, 3940, 4095, +0, 3941, 4095, +0, 3941, 4095, +0, 3942, 4095, +0, 3944, 4095, +0, 3945, 4095, +0, 3948, 4095, +0, 3951, 4095, +0, 3955, 4095, +0, 3961, 4095, +0, 3968, 4095, +0, 3978, 4095, +0, 3990, 4095, +0, 4006, 4095, +0, 4027, 4095, +0, 4054, 4095, +0, 4087, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4087, +0, 4095, 3924, +0, 4095, 3533, +0, 3938, 4095, +0, 3938, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3940, 4095, +0, 3940, 4095, +0, 3941, 4095, +0, 3941, 4095, +0, 3942, 4095, +0, 3944, 4095, +0, 3945, 4095, +0, 3948, 4095, +0, 3951, 4095, +0, 3955, 4095, +0, 3961, 4095, +0, 3968, 4095, +0, 3978, 4095, +0, 3990, 4095, +0, 4006, 4095, +0, 4027, 4095, +0, 4054, 4095, +0, 4087, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4087, +0, 4095, 3924, +0, 4095, 3534, +0, 3938, 4095, +0, 3938, 4095, +0, 3938, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3940, 4095, +0, 3940, 4095, +0, 3941, 4095, +0, 3941, 4095, +0, 3942, 4095, +0, 3944, 4095, +0, 3945, 4095, +0, 3948, 4095, +0, 3951, 4095, +0, 3955, 4095, +0, 3961, 4095, +0, 3968, 4095, +0, 3977, 4095, +0, 3990, 4095, +0, 4006, 4095, +0, 4027, 4095, +0, 4054, 4095, +0, 4087, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4087, +0, 4095, 3924, +0, 4095, 3534, +0, 3938, 4095, +0, 3938, 4095, +0, 3938, 4095, +0, 3938, 4095, +0, 3938, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3940, 4095, +0, 3941, 4095, +0, 3941, 4095, +0, 3942, 4095, +0, 3944, 4095, +0, 3945, 4095, +0, 3948, 4095, +0, 3951, 4095, +0, 3955, 4095, +0, 3961, 4095, +0, 3968, 4095, +0, 3977, 4095, +0, 3990, 4095, +0, 4006, 4095, +0, 4027, 4095, +0, 4054, 4095, +0, 4087, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4087, +0, 4095, 3925, +0, 4095, 3534, +0, 3938, 4095, +0, 3938, 4095, +0, 3938, 4095, +0, 3938, 4095, +0, 3938, 4095, +0, 3938, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3940, 4095, +0, 3940, 4095, +0, 3941, 4095, +0, 3942, 4095, +0, 3943, 4095, +0, 3945, 4095, +0, 3947, 4095, +0, 3951, 4095, +0, 3955, 4095, +0, 3961, 4095, +0, 3968, 4095, +0, 3977, 4095, +0, 3990, 4095, +0, 4006, 4095, +0, 4027, 4095, +0, 4054, 4095, +0, 4087, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4087, +0, 4095, 3925, +0, 4095, 3534, +0, 3938, 4095, +0, 3938, 4095, +0, 3938, 4095, +0, 3938, 4095, +0, 3938, 4095, +0, 3938, 4095, +0, 3938, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3940, 4095, +0, 3940, 4095, +0, 3941, 4095, +0, 3942, 4095, +0, 3943, 4095, +0, 3945, 4095, +0, 3947, 4095, +0, 3950, 4095, +0, 3955, 4095, +0, 3960, 4095, +0, 3968, 4095, +0, 3977, 4095, +0, 3990, 4095, +0, 4006, 4095, +0, 4027, 4095, +0, 4053, 4095, +0, 4087, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4087, +0, 4095, 3925, +0, 4095, 3534, +0, 3937, 4095, +0, 3937, 4095, +0, 3937, 4095, +0, 3938, 4095, +0, 3938, 4095, +0, 3938, 4095, +0, 3938, 4095, +0, 3938, 4095, +0, 3939, 4095, +0, 3939, 4095, +0, 3940, 4095, +0, 3941, 4095, +0, 3941, 4095, +0, 3943, 4095, +0, 3945, 4095, +0, 3947, 4095, +0, 3950, 4095, +0, 3954, 4095, +0, 3960, 4095, +0, 3967, 4095, +0, 3977, 4095, +0, 3989, 4095, +0, 4006, 4095, +0, 4027, 4095, +0, 4053, 4095, +0, 4086, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4087, +0, 4095, 3925, +0, 4095, 3534, +0, 3937, 4095, +0, 3937, 4095, +0, 3937, 4095, +0, 3937, 4095, +0, 3937, 4095, +0, 3937, 4095, +0, 3938, 4095, +0, 3938, 4095, +0, 3938, 4095, +0, 3939, 4095, +0, 3940, 4095, +0, 3940, 4095, +0, 3941, 4095, +0, 3943, 4095, +0, 3944, 4095, +0, 3947, 4095, +0, 3950, 4095, +0, 3954, 4095, +0, 3960, 4095, +0, 3967, 4095, +0, 3977, 4095, +0, 3989, 4095, +0, 4005, 4095, +0, 4026, 4095, +0, 4053, 4095, +0, 4086, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4088, +0, 4095, 3925, +0, 4095, 3535, +0, 3937, 4095, +0, 3937, 4095, +0, 3937, 4095, +0, 3937, 4095, +0, 3937, 4095, +0, 3937, 4095, +0, 3937, 4095, +0, 3937, 4095, +0, 3938, 4095, +0, 3938, 4095, +0, 3939, 4095, +0, 3940, 4095, +0, 3941, 4095, +0, 3942, 4095, +0, 3944, 4095, +0, 3946, 4095, +0, 3950, 4095, +0, 3954, 4095, +0, 3959, 4095, +0, 3967, 4095, +0, 3976, 4095, +0, 3989, 4095, +0, 4005, 4095, +0, 4026, 4095, +0, 4053, 4095, +0, 4086, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4088, +0, 4095, 3925, +0, 4095, 3536, +0, 3936, 4095, +0, 3936, 4095, +0, 3936, 4095, +0, 3936, 4095, +0, 3936, 4095, +0, 3936, 4095, +0, 3937, 4095, +0, 3937, 4095, +0, 3937, 4095, +0, 3937, 4095, +0, 3938, 4095, +0, 3939, 4095, +0, 3940, 4095, +0, 3941, 4095, +0, 3943, 4095, +0, 3946, 4095, +0, 3949, 4095, +0, 3953, 4095, +0, 3959, 4095, +0, 3966, 4095, +0, 3976, 4095, +0, 3988, 4095, +0, 4005, 4095, +0, 4026, 4095, +0, 4052, 4095, +0, 4085, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4088, +0, 4095, 3926, +0, 4095, 3537, +0, 3935, 4095, +0, 3935, 4095, +0, 3935, 4095, +0, 3935, 4095, +0, 3935, 4095, +0, 3935, 4095, +0, 3935, 4095, +0, 3936, 4095, +0, 3936, 4095, +0, 3937, 4095, +0, 3937, 4095, +0, 3938, 4095, +0, 3939, 4095, +0, 3941, 4095, +0, 3942, 4095, +0, 3945, 4095, +0, 3948, 4095, +0, 3952, 4095, +0, 3958, 4095, +0, 3965, 4095, +0, 3975, 4095, +0, 3988, 4095, +0, 4004, 4095, +0, 4025, 4095, +0, 4051, 4095, +0, 4085, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4088, +0, 4095, 3926, +0, 4095, 3538, +0, 3933, 4095, +0, 3933, 4095, +0, 3933, 4095, +0, 3933, 4095, +0, 3934, 4095, +0, 3934, 4095, +0, 3934, 4095, +0, 3934, 4095, +0, 3935, 4095, +0, 3935, 4095, +0, 3936, 4095, +0, 3937, 4095, +0, 3938, 4095, +0, 3940, 4095, +0, 3941, 4095, +0, 3944, 4095, +0, 3947, 4095, +0, 3951, 4095, +0, 3957, 4095, +0, 3964, 4095, +0, 3974, 4095, +0, 3986, 4095, +0, 4003, 4095, +0, 4024, 4095, +0, 4051, 4095, +0, 4084, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4089, +0, 4095, 3927, +0, 4095, 3539, +0, 3932, 4095, +0, 3932, 4095, +0, 3932, 4095, +0, 3932, 4095, +0, 3932, 4095, +0, 3932, 4095, +0, 3932, 4095, +0, 3932, 4095, +0, 3933, 4095, +0, 3933, 4095, +0, 3934, 4095, +0, 3935, 4095, +0, 3936, 4095, +0, 3938, 4095, +0, 3940, 4095, +0, 3942, 4095, +0, 3945, 4095, +0, 3950, 4095, +0, 3955, 4095, +0, 3963, 4095, +0, 3972, 4095, +0, 3985, 4095, +0, 4002, 4095, +0, 4023, 4095, +0, 4049, 4095, +0, 4083, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4089, +0, 4095, 3927, +0, 4095, 3541, +0, 3929, 4095, +0, 3929, 4095, +0, 3929, 4095, +0, 3929, 4095, +0, 3929, 4095, +0, 3929, 4095, +0, 3930, 4095, +0, 3930, 4095, +0, 3930, 4095, +0, 3931, 4095, +0, 3932, 4095, +0, 3932, 4095, +0, 3934, 4095, +0, 3935, 4095, +0, 3937, 4095, +0, 3940, 4095, +0, 3944, 4095, +0, 3948, 4095, +0, 3953, 4095, +0, 3961, 4095, +0, 3971, 4095, +0, 3983, 4095, +0, 4000, 4095, +0, 4021, 4095, +0, 4048, 4095, +0, 4082, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4090, +0, 4095, 3929, +0, 4095, 3544, +0, 3926, 4095, +0, 3926, 4095, +0, 3926, 4095, +0, 3926, 4095, +0, 3926, 4095, +0, 3926, 4095, +0, 3927, 4095, +0, 3927, 4095, +0, 3927, 4095, +0, 3927, 4095, +0, 3928, 4095, +0, 3929, 4095, +0, 3930, 4095, +0, 3932, 4095, +0, 3934, 4095, +0, 3937, 4095, +0, 3941, 4095, +0, 3945, 4095, +0, 3951, 4095, +0, 3959, 4095, +0, 3968, 4095, +0, 3981, 4095, +0, 3998, 4095, +0, 4019, 4095, +0, 4046, 4095, +0, 4080, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4091, +0, 4095, 3930, +0, 4095, 3547, +0, 3921, 4095, +0, 3921, 4095, +0, 3921, 4095, +0, 3921, 4095, +0, 3921, 4095, +0, 3922, 4095, +0, 3922, 4095, +0, 3922, 4095, +0, 3923, 4095, +0, 3923, 4095, +0, 3924, 4095, +0, 3925, 4095, +0, 3926, 4095, +0, 3927, 4095, +0, 3930, 4095, +0, 3933, 4095, +0, 3937, 4095, +0, 3942, 4095, +0, 3947, 4095, +0, 3955, 4095, +0, 3965, 4095, +0, 3978, 4095, +0, 3994, 4095, +0, 4016, 4095, +0, 4043, 4095, +0, 4077, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4092, +0, 4095, 3932, +0, 4095, 3552, +0, 3915, 4095, +0, 3915, 4095, +0, 3915, 4095, +0, 3915, 4095, +0, 3915, 4095, +0, 3916, 4095, +0, 3916, 4095, +0, 3916, 4095, +0, 3917, 4095, +0, 3917, 4095, +0, 3918, 4095, +0, 3919, 4095, +0, 3920, 4095, +0, 3922, 4095, +0, 3924, 4095, +0, 3927, 4095, +0, 3931, 4095, +0, 3936, 4095, +0, 3943, 4095, +0, 3950, 4095, +0, 3961, 4095, +0, 3974, 4095, +0, 3990, 4095, +0, 4012, 4095, +0, 4039, 4095, +0, 4073, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4094, +0, 4095, 3935, +0, 4095, 3558, +0, 3907, 4095, +0, 3907, 4095, +0, 3907, 4095, +0, 3907, 4095, +0, 3907, 4095, +0, 3908, 4095, +0, 3908, 4095, +0, 3908, 4095, +0, 3908, 4095, +0, 3909, 4095, +0, 3910, 4095, +0, 3910, 4095, +0, 3912, 4095, +0, 3913, 4095, +0, 3916, 4095, +0, 3919, 4095, +0, 3923, 4095, +0, 3928, 4095, +0, 3935, 4095, +0, 3944, 4095, +0, 3954, 4095, +0, 3968, 4095, +0, 3984, 4095, +0, 4006, 4095, +0, 4034, 4095, +0, 4069, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 3938, +0, 4095, 3566, +0, 3896, 4095, +0, 3896, 4095, +0, 3896, 4095, +0, 3896, 4095, +0, 3896, 4095, +0, 3896, 4095, +0, 3896, 4095, +0, 3897, 4095, +0, 3897, 4095, +0, 3898, 4095, +0, 3898, 4095, +0, 3899, 4095, +0, 3901, 4095, +0, 3903, 4095, +0, 3905, 4095, +0, 3908, 4095, +0, 3912, 4095, +0, 3917, 4095, +0, 3924, 4095, +0, 3934, 4095, +0, 3946, 4095, +0, 3960, 4095, +0, 3977, 4095, +0, 3999, 4095, +0, 4027, 4095, +0, 4062, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 3943, +0, 4095, 3576, +0, 3880, 4095, +0, 3880, 4095, +0, 3880, 4095, +0, 3880, 4095, +0, 3880, 4095, +0, 3881, 4095, +0, 3881, 4095, +0, 3881, 4095, +0, 3881, 4095, +0, 3882, 4095, +0, 3883, 4095, +0, 3884, 4095, +0, 3885, 4095, +0, 3887, 4095, +0, 3889, 4095, +0, 3893, 4095, +0, 3897, 4095, +0, 3903, 4095, +0, 3910, 4095, +0, 3920, 4095, +0, 3932, 4095, +0, 3949, 4095, +0, 3966, 4095, +0, 3989, 4095, +0, 4018, 4095, +0, 4054, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 3949, +0, 4095, 3590, +0, 3859, 4095, +0, 3859, 4095, +0, 3859, 4095, +0, 3859, 4095, +0, 3859, 4095, +0, 3859, 4095, +0, 3859, 4095, +0, 3860, 4095, +0, 3860, 4095, +0, 3861, 4095, +0, 3862, 4095, +0, 3863, 4095, +0, 3864, 4095, +0, 3866, 4095, +0, 3868, 4095, +0, 3872, 4095, +0, 3876, 4095, +0, 3882, 4095, +0, 3890, 4095, +0, 3900, 4095, +0, 3913, 4095, +0, 3930, 4095, +0, 3952, 4095, +0, 3976, 4095, +0, 4005, 4095, +0, 4042, 4095, +0, 4087, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 3957, +0, 4095, 3608, +0, 3828, 4095, +0, 3828, 4095, +0, 3828, 4095, +0, 3828, 4095, +0, 3828, 4095, +0, 3829, 4095, +0, 3829, 4095, +0, 3829, 4095, +0, 3830, 4095, +0, 3830, 4095, +0, 3831, 4095, +0, 3832, 4095, +0, 3834, 4095, +0, 3836, 4095, +0, 3838, 4095, +0, 3842, 4095, +0, 3847, 4095, +0, 3853, 4095, +0, 3861, 4095, +0, 3872, 4095, +0, 3886, 4095, +0, 3904, 4095, +0, 3927, 4095, +0, 3956, 4095, +0, 3987, 4095, +0, 4025, 4095, +0, 4072, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 3968, +0, 4095, 3630, +0, 3784, 4095, +0, 3784, 4095, +0, 3784, 4095, +0, 3784, 4095, +0, 3784, 4095, +0, 3784, 4095, +0, 3784, 4095, +0, 3785, 4095, +0, 3786, 4095, +0, 3786, 4095, +0, 3787, 4095, +0, 3788, 4095, +0, 3790, 4095, +0, 3792, 4095, +0, 3795, 4095, +0, 3799, 4095, +0, 3804, 4095, +0, 3811, 4095, +0, 3820, 4095, +0, 3832, 4095, +0, 3847, 4095, +0, 3867, 4095, +0, 3892, 4095, +0, 3923, 4095, +0, 3962, 4095, +0, 4002, 4095, +0, 4051, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 3982, +0, 4095, 3659, +0, 3716, 4095, +0, 3717, 4095, +0, 3717, 4095, +0, 3717, 4095, +0, 3717, 4095, +0, 3717, 4095, +0, 3718, 4095, +0, 3718, 4095, +0, 3719, 4095, +0, 3720, 4095, +0, 3721, 4095, +0, 3722, 4095, +0, 3724, 4095, +0, 3727, 4095, +0, 3730, 4095, +0, 3735, 4095, +0, 3741, 4095, +0, 3748, 4095, +0, 3759, 4095, +0, 3772, 4095, +0, 3790, 4095, +0, 3812, 4095, +0, 3840, 4095, +0, 3875, 4095, +0, 3918, 4095, +0, 3970, 4095, +0, 4022, 4095, +0, 4084, 4095, +0, 4095, 4095, +0, 4095, 4095, +0, 4095, 4000, +0, 4095, 3695, +0, 3608, 4095, +0, 3608, 4095, +0, 3608, 4095, +0, 3608, 4095, +0, 3608, 4095, +0, 3609, 4095, +0, 3609, 4095, +0, 3610, 4095, +0, 3611, 4095, +0, 3612, 4095, +0, 3613, 4095, +0, 3615, 4095, +0, 3617, 4095, +0, 3621, 4095, +0, 3625, 4095, +0, 3630, 4095, +0, 3638, 4095, +0, 3648, 4095, +0, 3661, 4095, +0, 3677, 4095, +0, 3699, 4095, +0, 3726, 4095, +0, 3759, 4095, +0, 3801, 4095, +0, 3851, 4095, +0, 3911, 4095, +2192, 3980, 4095, +2192, 4047, 4095, +2192, 4095, 4095, +2192, 4095, 4095, +2192, 4095, 4023, +2192, 4095, 3738, +0, 3404, 4095, +0, 3404, 4095, +0, 3404, 4095, +0, 3405, 4095, +0, 3405, 4095, +0, 3405, 4095, +0, 3406, 4095, +0, 3407, 4095, +0, 3408, 4095, +0, 3410, 4095, +0, 3412, 4095, +0, 3415, 4095, +0, 3419, 4095, +0, 3424, 4095, +0, 3430, 4095, +0, 3439, 4095, +0, 3450, 4095, +0, 3465, 4095, +0, 3484, 4095, +0, 3509, 4095, +0, 3539, 4095, +0, 3577, 4095, +0, 3623, 4095, +0, 3679, 4095, +0, 3743, 4095, +0, 3818, 4095, +2192, 3901, 4095, +3118, 3993, 4095, +3118, 4079, 4095, +3118, 4095, 4095, +3118, 4095, 4051, +3118, 4095, 3791, +0, 2761, 4095, +0, 2762, 4095, +0, 2762, 4095, +0, 2764, 4095, +0, 2765, 4095, +0, 2767, 4095, +0, 2770, 4095, +0, 2773, 4095, +0, 2778, 4095, +0, 2785, 4095, +0, 2793, 4095, +0, 2804, 4095, +0, 2818, 4095, +0, 2837, 4095, +0, 2861, 4095, +0, 2890, 4095, +0, 2927, 4095, +0, 2973, 4095, +0, 3027, 4095, +0, 3090, 4095, +0, 3164, 4095, +0, 3246, 4095, +0, 3337, 4095, +0, 3436, 4095, +0, 3541, 4095, +0, 3653, 4095, +2192, 3768, 4095, +3118, 3888, 4095, +3469, 4010, 4095, +3469, 4095, 4095, +3469, 4095, 4087, +3469, 4095, 3853, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 2137, 4095, +0, 2915, 4095, +0, 3253, 4095, +2192, 3494, 4095, +3118, 3693, 4095, +3469, 3869, 4095, +3714, 4032, 4095, +3714, 4095, 4095, +3714, 4095, 3924, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +0, 0, 4095, +2266, 0, 4095, +2814, 2192, 4095, +3118, 3121, 4095, +3469, 3568, 4095, +3714, 3844, 4095, +3916, 4060, 4095, +3916, 4095, 4005, +3533, 0, 4095, +3533, 0, 4095, +3533, 0, 4095, +3534, 0, 4095, +3534, 0, 4095, +3534, 0, 4095, +3534, 0, 4095, +3534, 0, 4095, +3534, 0, 4095, +3535, 0, 4095, +3536, 0, 4095, +3537, 0, 4095, +3538, 0, 4095, +3539, 0, 4095, +3541, 0, 4095, +3544, 0, 4095, +3547, 0, 4095, +3552, 0, 4095, +3558, 0, 4095, +3566, 0, 4095, +3576, 0, 4095, +3590, 0, 4095, +3608, 0, 4095, +3630, 0, 4095, +3659, 0, 4095, +3695, 0, 4095, +3738, 2192, 4095, +3791, 3118, 4095, +3853, 3469, 4095, +3924, 3714, 4095, +4005, 3916, 4095, +4095, 4095, 4095] + } +} \ No newline at end of file diff --git a/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/displaymapperpassthrough.dds b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/displaymapperpassthrough.dds new file mode 100644 index 0000000000..d48a60e5cf --- /dev/null +++ b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/displaymapperpassthrough.dds @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bd3fe7e7f016c1a3b2c3e8db5fbd23efbc8d8717c01fac4cf39b1ae7b3ae9325 +size 41559412 diff --git a/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/displaymapperpassthrough.exr b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/displaymapperpassthrough.exr new file mode 100644 index 0000000000..9daa58f75c --- /dev/null +++ b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/displaymapperpassthrough.exr @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:facad074b84df87a0ab4baaf2bd95552e6eca3fed79a56875c9815f32d885b8a +size 11949493 diff --git a/Gems/Atom/Feature/Common/Tools/ColorGrading/cmdline/.gitignore b/Gems/Atom/Feature/Common/Tools/ColorGrading/cmdline/.gitignore new file mode 100644 index 0000000000..fd2792f73e --- /dev/null +++ b/Gems/Atom/Feature/Common/Tools/ColorGrading/cmdline/.gitignore @@ -0,0 +1 @@ +User_Env.bat \ No newline at end of file diff --git a/Gems/Atom/Feature/Common/Tools/ColorGrading/cmdline/CMD_ColorGradingTools.bat b/Gems/Atom/Feature/Common/Tools/ColorGrading/cmdline/CMD_ColorGradingTools.bat new file mode 100644 index 0000000000..2c5809ec15 --- /dev/null +++ b/Gems/Atom/Feature/Common/Tools/ColorGrading/cmdline/CMD_ColorGradingTools.bat @@ -0,0 +1,52 @@ +@echo off + +REM +REM Copyright (c) Contributors to the Open 3D Engine Project +REM +REM SPDX-License-Identifier: Apache-2.0 OR MIT +REM For complete copyright and license terms please see the LICENSE at the root of this distribution. +REM +REM + +:: Set up and run O3DE Python CMD prompt +:: Sets up the DccScriptingInterface_Env, +:: Puts you in the CMD within the dev environment + +:: Set up window +TITLE O3DE Color Grading CMD +:: Use obvious color to prevent confusion (Grey with Yellow Text) +COLOR 8E + +%~d0 +cd %~dp0 +PUSHD %~dp0 + +SETLOCAL ENABLEDELAYEDEXPANSION + +:: if the user has set up a custom env call it +IF EXIST "%~dp0User_env.bat" CALL %~dp0User_env.bat + +:: Initialize env +CALL %~dp0\Env_Core.bat +CALL %~dp0\Env_Python.bat +CALL %~dp0\Env_Tools.bat + +echo. +echo _____________________________________________________________________ +echo. +echo ~ O3DE Color Grading Python CMD ... +echo _____________________________________________________________________ +echo. + +:: Change to root dir +CD /D .. + +:: Create command prompt with environment +CALL %windir%\system32\cmd.exe + +ENDLOCAL + +:: Return to starting directory +POPD + +:END_OF_FILE diff --git a/Gems/Atom/Feature/Common/Tools/ColorGrading/cmdline/Env_Core.bat b/Gems/Atom/Feature/Common/Tools/ColorGrading/cmdline/Env_Core.bat new file mode 100644 index 0000000000..730170dce7 --- /dev/null +++ b/Gems/Atom/Feature/Common/Tools/ColorGrading/cmdline/Env_Core.bat @@ -0,0 +1,129 @@ +@echo off + +REM +REM Copyright (c) Contributors to the Open 3D Engine Project +REM +REM SPDX-License-Identifier: Apache-2.0 OR MIT +REM For complete copyright and license terms please see the LICENSE at the root of this distribution. +REM +REM + +:: Sets up environment for O3DE DCC tools and code access + +:: Set up window +TITLE O3DE Color Grading Env Core +:: Use obvious color to prevent confusion (Grey with Yellow Text) +COLOR 8E + +:: Skip initialization if already completed +IF "%O3DE_ENV_INIT%"=="1" GOTO :END_OF_FILE + +:: Store current dir +%~d0 +cd %~dp0 +PUSHD %~dp0 + +::SETLOCAL ENABLEDELAYEDEXPANSION + +echo. +echo _____________________________________________________________________ +echo. +echo ~ O3DE Color Grading Core Env ... +echo _____________________________________________________________________ +echo. + +IF "%CMD_LAUNCHERS%"=="" (set CMD_LAUNCHERS=%~dp0) +echo CMD_LAUNCHERS = %CMD_LAUNCHERS% + +:: add to the PATH +SET PATH=%CMD_LAUNCHERS%;%PATH% + +:: Constant Vars (Global) +:: global debug flag (propogates) +:: The intent here is to set and globally enter a debug mode +IF "%DCCSI_GDEBUG%"=="" (set DCCSI_GDEBUG=false) +echo DCCSI_GDEBUG = %DCCSI_GDEBUG% +:: initiates earliest debugger connection +:: we support attaching to WingIDE... PyCharm and VScode in the future +IF "%DCCSI_DEV_MODE%"=="" (set DCCSI_DEV_MODE=false) +echo DCCSI_DEV_MODE = %DCCSI_DEV_MODE% +:: sets debugger, options: WING, PYCHARM +IF "%DCCSI_GDEBUGGER%"=="" (set DCCSI_GDEBUGGER=WING) +echo DCCSI_GDEBUGGER = %DCCSI_GDEBUGGER% +:: Default level logger will handle +:: Override this to control the setting +:: CRITICAL:50 +:: ERROR:40 +:: WARNING:30 +:: INFO:20 +:: DEBUG:10 +:: NOTSET:0 +IF "%DCCSI_LOGLEVEL%"=="" (set DCCSI_LOGLEVEL=20) +echo DCCSI_LOGLEVEL = %DCCSI_LOGLEVEL% + +:: This maps up to the \Dev folder +IF "%DEV_REL_PATH%"=="" (set DEV_REL_PATH=..\..\..\..\..\..) +echo DEV_REL_PATH = %DEV_REL_PATH% + +:: You can define the project name +IF "%O3DE_PROJECT_NAME%"=="" ( + for %%a in (%CD%..\..) do set O3DE_PROJECT_NAME=%%~na + ) +echo O3DE_PROJECT_NAME = %O3DE_PROJECT_NAME% + +CD /D ..\ +IF "%O3DE_PROJECT_PATH%"=="" (set O3DE_PROJECT_PATH=%CD%) +echo O3DE_PROJECT_PATH = %O3DE_PROJECT_PATH% + +IF "%ABS_PATH%"=="" (set ABS_PATH=%CD%) +echo ABS_PATH = %ABS_PATH% + +:: Save current directory and change to target directory +pushd %ABS_PATH% + +:: Change to root Lumberyard dev dir +CD /d %DEV_REL_PATH% +IF "%O3DE_DEV%"=="" (set O3DE_DEV=%CD%) +echo O3DE_DEV = %O3DE_DEV% +:: Restore original directory +popd + +:: dcc scripting interface gem path +:: currently know relative path to this gem +set DCCSIG_PATH=%O3DE_DEV%\Gems\AtomLyIntegration\TechnicalArt\DccScriptingInterface +echo DCCSIG_PATH = %DCCSIG_PATH% + +:: Change to DCCsi root dir +CD /D %DCCSIG_PATH% + +:: per-dcc sdk path +set DCCSI_SDK_PATH=%DCCSIG_PATH%\SDK +echo DCCSI_SDK_PATH = %DCCSI_SDK_PATH% + +:: temp log location specific to this gem +set DCCSI_LOG_PATH=%DCCSIG_PATH%\.temp\logs +echo DCCSI_LOG_PATH = %DCCSI_LOG_PATH% + +:: O3DE build path +IF "%TAG_O3DE_BUILD_PATH%"=="" (set TAG_O3DE_BUILD_PATH=build) +echo TAG_O3DE_BUILD_PATH = %TAG_O3DE_BUILD_PATH% + +IF "%O3DE_BUILD_PATH%"=="" (set O3DE_BUILD_PATH=%O3DE_DEV%\%TAG_O3DE_BUILD_PATH%) +echo O3DE_BUILD_PATH = %O3DE_BUILD_PATH% + +IF "%O3DE_BIN_PATH%"=="" (set O3DE_BIN_PATH=%O3DE_BUILD_PATH%\bin\profile) +echo O3DE_BIN_PATH = %O3DE_BIN_PATH% + +:: add to the PATH +SET PATH=%O3DE_BUILD_PATH%;%DCCSIG_PATH%;%DCCSI_AZPY_PATH%;%PATH% + +::ENDLOCAL + +:: Set flag so we don't initialize dccsi environment twice +SET O3DE_ENV_INIT=1 +GOTO END_OF_FILE + +:: Return to starting directory +POPD + +:END_OF_FILE diff --git a/Gems/Atom/Feature/Common/Tools/ColorGrading/cmdline/Env_Python.bat b/Gems/Atom/Feature/Common/Tools/ColorGrading/cmdline/Env_Python.bat new file mode 100644 index 0000000000..83b7382dc6 --- /dev/null +++ b/Gems/Atom/Feature/Common/Tools/ColorGrading/cmdline/Env_Python.bat @@ -0,0 +1,102 @@ +@echo off + +REM +REM Copyright (c) Contributors to the Open 3D Engine Project +REM +REM SPDX-License-Identifier: Apache-2.0 OR MIT +REM For complete copyright and license terms please see the LICENSE at the root of this distribution. +REM +REM + +:: Sets up extended environment for O3DE and DCCsi python + +:: Skip initialization if already completed +IF "%O3DE_ENV_PY_INIT%"=="1" GOTO :END_OF_FILE + +:: Store current dir +%~d0 +cd %~dp0 +PUSHD %~dp0 + +CALL %~dp0\Env_Core.bat + +::SETLOCAL ENABLEDELAYEDEXPANSION + +echo. +echo _____________________________________________________________________ +echo. +echo ~ O3DE Color Grading Python Env ... +echo _____________________________________________________________________ +echo. + +:: Python Version +:: Ideally these are set to match the O3DE python distribution +:: \python\runtime +IF "%DCCSI_PY_VERSION_MAJOR%"=="" (set DCCSI_PY_VERSION_MAJOR=3) +echo DCCSI_PY_VERSION_MAJOR = %DCCSI_PY_VERSION_MAJOR% + +:: PY version Major +IF "%DCCSI_PY_VERSION_MINOR%"=="" (set DCCSI_PY_VERSION_MINOR=7) +echo DCCSI_PY_VERSION_MINOR = %DCCSI_PY_VERSION_MINOR% + +IF "%DCCSI_PY_VERSION_RELEASE%"=="" (set DCCSI_PY_VERSION_RELEASE=10) +echo DCCSI_PY_VERSION_RELEASE = %DCCSI_PY_VERSION_RELEASE% + +:: shared location for 64bit python 3.7 DEV location +:: this defines a DCCsi sandbox for lib site-packages by version +:: \Gems\AtomLyIntegration\TechnicalArt\DccScriptingInterface\3rdParty\Python\Lib +set DCCSI_PYTHON_PATH=%DCCSIG_PATH%\3rdParty\Python +echo DCCSI_PYTHON_PATH = %DCCSI_PYTHON_PATH% + +:: add access to a Lib location that matches the py version (example: 3.7.x) +:: switch this for other python versions like maya (2.7.x) +IF "%DCCSI_PYTHON_LIB_PATH%"=="" (set DCCSI_PYTHON_LIB_PATH=%DCCSI_PYTHON_PATH%\Lib\%DCCSI_PY_VERSION_MAJOR%.x\%DCCSI_PY_VERSION_MAJOR%.%DCCSI_PY_VERSION_MINOR%.x\site-packages) +echo DCCSI_PYTHON_LIB_PATH = %DCCSI_PYTHON_LIB_PATH% + +:: add to the PATH +SET PATH=%DCCSI_PYTHON_LIB_PATH%;%PATH% + +:: shared location for default O3DE python location +set DCCSI_PYTHON_INSTALL=%O3DE_DEV%\Python +echo DCCSI_PYTHON_INSTALL = %DCCSI_PYTHON_INSTALL% + +:: location for O3DE python 3.7 location +set DCCSI_PY_BASE=%DCCSI_PYTHON_INSTALL%\python.cmd +echo DCCSI_PY_BASE = %DCCSI_PY_BASE% + +:: ide and debugger plug +set DCCSI_PY_DEFAULT=%DCCSI_PY_BASE% + +set DCCSI_PY_IDE=%DCCSI_PYTHON_INSTALL%\runtime\python-3.7.10-rev1-windows\python +echo DCCSI_PY_IDE = %DCCSI_PY_IDE% + +:: Wing and other IDEs probably prefer access directly to the python.exe +set DCCSI_PY_EXE=%DCCSI_PYTHON_INSTALL%\runtime\python-3.7.10-rev1-windows\python\python.exe +echo DCCSI_PY_EXE = %DCCSI_PY_EXE% + +set DCCSI_PY_IDE_PACKAGES=%DCCSI_PY_IDE%\Lib\site-packages +echo DCCSI_PY_IDE_PACKAGES = %DCCSI_PY_IDE_PACKAGES% + +set DCCSI_FEATURECOMMON_SCRIPTS=%O3DE_DEV%\Gems\Atom\Feature\Common\Editor\Scripts +echo DCCSI_FEATURECOMMON_SCRIPTS = %DCCSI_FEATURECOMMON_SCRIPTS% + +set DCCSI_COLORGRADING_SCRIPTS=%DCCSI_FEATURECOMMON_SCRIPTS%\ColorGrading +echo DCCSI_COLORGRADING_SCRIPTS = %DCCSI_COLORGRADING_SCRIPTS% + +:: add to the PATH +SET PATH=%DCCSI_PYTHON_INSTALL%;%DCCSI_PY_IDE%;%DCCSI_PY_IDE_PACKAGES%;%DCCSI_PY_EXE%;%DCCSI_COLORGRADING_SCRIPTS%;%PATH% + +:: add all python related paths to PYTHONPATH for package imports +set PYTHONPATH=%DCCSIG_PATH%;%DCCSI_PYTHON_LIB_PATH%;%O3DE_BIN_PATH%;%DCCSI_COLORGRADING_SCRIPTS%;%DCCSI_FEATURECOMMON_SCRIPTS%;%PYTHONPATH% +echo PYTHONPATH = %PYTHONPATH% + +::ENDLOCAL + +:: Set flag so we don't initialize dccsi environment twice +SET O3DE_ENV_PY_INIT=1 +GOTO END_OF_FILE + +:: Return to starting directory +POPD + +:END_OF_FILE diff --git a/Gems/Atom/Feature/Common/Tools/ColorGrading/cmdline/Env_Tools.bat b/Gems/Atom/Feature/Common/Tools/ColorGrading/cmdline/Env_Tools.bat new file mode 100644 index 0000000000..27c8960ca3 --- /dev/null +++ b/Gems/Atom/Feature/Common/Tools/ColorGrading/cmdline/Env_Tools.bat @@ -0,0 +1,88 @@ +@echo off + +REM +REM Copyright (c) Contributors to the Open 3D Engine Project +REM +REM SPDX-License-Identifier: Apache-2.0 OR MIT +REM For complete copyright and license terms please see the LICENSE at the root of this distribution. +REM +REM + + +:: Sets ocio and oiio tools for O3DE Color Grading + +:: Skip initialization if already completed +IF "%O3DE_ENV_TOOLS_INIT%"=="1" GOTO :END_OF_FILE + +:: Store current dir +%~d0 +cd %~dp0 +PUSHD %~dp0 + +:: Initialize env +CALL %~dp0\Env_Core.bat +CALL %~dp0\Env_Python.bat + +::SETLOCAL ENABLEDELAYEDEXPANSION + +echo. +echo _____________________________________________________________________ +echo. +echo ~ O3DE Color Grading Tools Env ... +echo _____________________________________________________________________ +echo. + +::SET oiio_bin=%O3DE_PROJECT_PATH%\Tools\oiio\build\bin\Release +::SET oiiotool=%oiio_bin%\oiiotool.exe + +:: Libs that ocio uses +SET vcpkg_bin=%O3DE_DEV%\Tools\ColorGrading\vcpkg\installed\x64-windows\bin +:: add to path +SET PATH=%PATH%;%vcpkg_bin% + +SET ocio_bin=%O3DE_DEV%\Tools\ColorGrading\ocio\build\src\OpenColorIO\Release +echo ocio_bin = %ocio_bin% +:: add to the PATH +SET PATH=%PATH%;%ocio_bin% + +IF "%OCIO_APPS%"=="" (set OCIO_APPS=%O3DE_DEV%\Tools\ColorGrading\ocio\build\src\apps) +echo OCIO_APPS = %OCIO_APPS% + +SET ociobakelut=%OCIO_APPS%\ociobakelut\Release +echo ociobakelut = %ociobakelut% +SET PATH=%PATH%;%ociobakelut% + +SET ociocheck=%OCIO_APPS%\ociocheck\Release +SET PATH=%PATH%;%ociocheck% + +SET ociochecklut=%OCIO_APPS%\ociochecklut\Release +SET PATH=%PATH%;%ociochecklut% + +SET ocioconvert=%OCIO_APPS%\ocioconvert\Release +SET PATH=%PATH%;%ocioconvert% + +SET ociodisplay=%OCIO_APPS%\ociodisplay\Release +SET PATH=%PATH%;%ociodisplay% + +SET ociolutimage=%OCIO_APPS%\ociolutimage\Release +SET PATH=%PATH%;%ociolutimage% + +SET ociomakeclf=%OCIO_APPS%\ociomakeclf\Release +SET PATH=%PATH%;%ociomakeclf% + +SET ocioperf=%OCIO_APPS%\ocioperf\Release +SET PATH=%PATH%;%ocioperf% + +SET ociowrite=%OCIO_APPS%\ociowrite\Release +SET PATH=%PATH%;%ociowrite% + +::ENDLOCAL + +:: Set flag so we don't initialize this environment twice +SET O3DE_ENV_TOOLS_INIT=1 +GOTO END_OF_FILE + +:: Return to starting directory +POPD + +:END_OF_FILE \ No newline at end of file diff --git a/Gems/Atom/Feature/Common/Tools/ColorGrading/cmdline/Env_WingIDE.bat b/Gems/Atom/Feature/Common/Tools/ColorGrading/cmdline/Env_WingIDE.bat new file mode 100644 index 0000000000..4c297f53a9 --- /dev/null +++ b/Gems/Atom/Feature/Common/Tools/ColorGrading/cmdline/Env_WingIDE.bat @@ -0,0 +1,67 @@ +@echo off + +REM +REM Copyright (c) Contributors to the Open 3D Engine Project +REM +REM SPDX-License-Identifier: Apache-2.0 OR MIT +REM For complete copyright and license terms please see the LICENSE at the root of this distribution. +REM +REM + +:: Sets up environment for Lumberyard DCC tools and code access + +:: Skip initialization if already completed +IF "%DCCSI_ENV_WINGIDE_INIT%"=="1" GOTO :END_OF_FILE + +:: Store current dir +%~d0 +cd %~dp0 +PUSHD %~dp0 + +:: WingIDE version Major +IF "%DCCSI_WING_VERSION_MAJOR%"=="" (set DCCSI_WING_VERSION_MAJOR=7) +:: WingIDE version Major +IF "%DCCSI_WING_VERSION_MINOR%"=="" (set DCCSI_WING_VERSION_MINOR=1) + +:: Initialize env +CALL %~dp0\Env_Core.bat +CALL %~dp0\Env_Python.bat + +:: Wing and other IDEs probably prefer access directly to the python.exe +set DCCSI_PY_IDE = %DCCSI_PYTHON_INSTALL%\runtime\python-3.7.10-rev1-windows\python +echo DCCSI_PY_IDE = %DCCSI_PY_IDE% + +:: ide and debugger plug +set DCCSI_PY_DEFAULT=%DCCSI_PY_IDE%\python.exe + +:: put project env variables/paths here +set WINGHOME=%PROGRAMFILES(X86)%\Wing Pro %DCCSI_WING_VERSION_MAJOR%.%DCCSI_WING_VERSION_MINOR% +IF "%WING_PROJ%"=="" (set WING_PROJ=%O3DE_PROJECT_PATH%\.solutions\.wing\o3de_color_grading_%DCCSI_WING_VERSION_MAJOR%x.wpr) + +::SETLOCAL ENABLEDELAYEDEXPANSION + +echo. +echo _____________________________________________________________________ +echo. +echo ~ O3DE Color Grading Environment ... +echo _____________________________________________________________________ +echo. + +echo DCCSI_WING_VERSION_MAJOR = %DCCSI_WING_VERSION_MAJOR% +echo DCCSI_WING_VERSION_MINOR = %DCCSI_WING_VERSION_MINOR% +echo WINGHOME = %WINGHOME% +echo WING_PROJ = %WING_PROJ% + +:: add to the PATH +SET PATH=%WINGHOME%;%PATH% + +::ENDLOCAL + +:: Set flag so we don't initialize dccsi environment twice +SET DCCSI_ENV_WINGIDE_INIT=1 +GOTO END_OF_FILE + +:: Return to starting directory +POPD + +:END_OF_FILE diff --git a/Gems/Atom/Feature/Common/Tools/ColorGrading/cmdline/Launch_WingIDE-7-1.bat b/Gems/Atom/Feature/Common/Tools/ColorGrading/cmdline/Launch_WingIDE-7-1.bat new file mode 100644 index 0000000000..93f5fb7fa6 --- /dev/null +++ b/Gems/Atom/Feature/Common/Tools/ColorGrading/cmdline/Launch_WingIDE-7-1.bat @@ -0,0 +1,99 @@ +@echo off + +REM +REM Copyright (c) Contributors to the Open 3D Engine Project +REM +REM SPDX-License-Identifier: Apache-2.0 OR MIT +REM For complete copyright and license terms please see the LICENSE at the root of this distribution. +REM +REM + +:: Launches Wing IDE and the O3de Color Grading project files + +:: Set up window +TITLE O3DE Color Grading Launch WingIDE 7x +:: Use obvious color to prevent confusion (Grey with Yellow Text) +COLOR 8E + +:: Store current dir +%~d0 +cd %~dp0 +PUSHD %~dp0 + +:: if the user has set up a custom env call it +IF EXIST "%~dp0User_env.bat" CALL %~dp0User_env.bat + +:: Constant Vars (Global) +:: global debug (propogates) +IF "%DCCSI_GDEBUG%"=="" (set DCCSI_GDEBUG=True) +echo DCCSI_GDEBUG = %DCCSI_GDEBUG% +:: initiates debugger connection +IF "%DCCSI_DEV_MODE%"=="" (set DCCSI_DEV_MODE=True) +echo DCCSI_DEV_MODE = %DCCSI_DEV_MODE% +:: sets debugger, options: WING, PYCHARM +IF "%DCCSI_GDEBUGGER%"=="" (set DCCSI_GDEBUGGER=WING) +echo DCCSI_GDEBUGGER = %DCCSI_GDEBUGGER% +:: Default level logger will handle +:: CRITICAL:50 +:: ERROR:40 +:: WARNING:30 +:: INFO:20 +:: DEBUG:10 +:: NOTSET:0 +IF "%DCCSI_LOGLEVEL%"=="" (set DCCSI_LOGLEVEL=10) +echo DCCSI_LOGLEVEL = %DCCSI_LOGLEVEL% + +:: Initialize env +CALL %~dp0\Env_Core.bat +CALL %~dp0\Env_Python.bat +CALL %~dp0\Env_WingIDE.bat +echo. +echo _____________________________________________________________________ +echo. +echo ~ WingIDE Version %DCCSI_WING_VERSION_MAJOR%.%DCCSI_WING_VERSION_MINOR% +echo ~ Launching O3DE %LY_PROJECT% project in WingIDE %DCCSI_WING_VERSION_MAJOR%.%DCCSI_WING_VERSION_MINOR% ... +echo _____________________________________________________________________ +echo. + +echo LY_DEV = %LY_DEV% + +:: shared location for default O3DE python location +set DCCSI_PYTHON_INSTALL=%LY_DEV%\Python +echo DCCSI_PYTHON_INSTALL = %DCCSI_PYTHON_INSTALL% + +:: Wing and other IDEs probably prefer access directly to the python.exe +set DCCSI_PY_IDE = %DCCSI_PYTHON_INSTALL%\runtime\python-3.7.10-rev1-windows\python +echo DCCSI_PY_IDE = %DCCSI_PY_IDE% + +:: ide and debugger plug +set DCCSI_PY_BASE=%DCCSI_PY_IDE%\python.exe +echo DCCSI_PY_BASE = %DCCSI_PY_BASE% + +:: ide and debugger plug +set DCCSI_PY_DEFAULT=%DCCSI_PY_BASE% +echo DCCSI_PY_DEFAULT = %DCCSI_PY_DEFAULT% + +:: if the user has set up a custom env call it +IF EXIST "%~dp0User_Dev.bat" CALL %~dp0User_Dev.bat + +echo. + +:: Change to root dir +CD /D %O3DE_PROJECT_PATH% + +IF EXIST "%WINGHOME%\bin\wing.exe" ( + start "" "%WINGHOME%\bin\wing.exe" "%WING_PROJ%" +) ELSE ( + Where wing.exe 2> NUL + IF ERRORLEVEL 1 ( + echo wing.exe could not be found + pause + ) ELSE ( + start "" wing.exe "%WING_PROJ%" + ) +) + +:: Return to starting directory +POPD + +:END_OF_FILE diff --git a/Gems/Atom/Feature/Common/Tools/ColorGrading/cmdline/README.txt b/Gems/Atom/Feature/Common/Tools/ColorGrading/cmdline/README.txt new file mode 100644 index 0000000000..d876dd671d --- /dev/null +++ b/Gems/Atom/Feature/Common/Tools/ColorGrading/cmdline/README.txt @@ -0,0 +1,26 @@ +# +# +# Copyright (c) Contributors to the Open 3D Engine Project. +# For complete copyright and license terms please see the LICENSE at the root of this distribution. +# +# SPDX-License-Identifier: Apache-2.0 OR MIT +# +# + +These are commandline tools for color grading workflow and authoring LUTs externally. +Note: may require OpenColorIO (ocio) and/or OpenImageIO (oiio) to be set up properly. + +CMD_ColorGradingTools.bat :: opens a configured window env context in CMD +Env_Core.bat :: core O3DE env hooks (any envars DCCSI_ shares some overlay with DccScriptingInterface Gem) +Env_Python.bat :: sets up access and configures env for O3DE python (to run externally) +Env_Tools.bat :: hooks for ocio and oiio + :: note: currently you must build coio tools/apps yourself (we used vcpkg and cmake gui) + :: note: oiio, it's .pyd and oiiotool should build in O3DE (if you have troubel issue a ticket to investigate) +Env_WingIDE.bat :: hooks for WingIDE (a python IDE and debugger) + :: note: feel free to configure a different IDE, user choice. +Launch_WingIDE-7-1.bat :: this will launch WingIDE with envar hooks and access to O3DE python (for authroing, debugging) + :: note: you will need to make sure wingstub.py is configured correctly + :: note: you will need to create the wing project file/path (see Env_WingIDE.bat) +User_Env.bat.template :: this is an example of overriding or extending the envar hooks (set local engine root, or branch path, etc.) + :: note: to use, copy and rename to User_Env.bat + :: bote: we use this to primarily enable the debugging related envar hooks \ No newline at end of file diff --git a/Gems/Atom/Feature/Common/Tools/ColorGrading/cmdline/User_Env.bat.template b/Gems/Atom/Feature/Common/Tools/ColorGrading/cmdline/User_Env.bat.template new file mode 100644 index 0000000000..558505f80f --- /dev/null +++ b/Gems/Atom/Feature/Common/Tools/ColorGrading/cmdline/User_Env.bat.template @@ -0,0 +1,41 @@ +@echo off + +REM +REM Copyright (c) Contributors to the Open 3D Engine Project +REM +REM SPDX-License-Identifier: Apache-2.0 OR MIT +REM For complete copyright and license terms please see the LICENSE at the root of this distribution. +REM +REM + +:: copy this file, rename to User_Env.bat (remove .template) +:: use this file to override any local properties that differ from base + +:: Skip initialization if already completed +IF "%O3DE_USER_ENV_INIT%"=="1" GOTO :END_OF_FILE + +:: Store current dir +%~d0 +cd %~dp0 +PUSHD %~dp0 + +SETLOCAL ENABLEDELAYEDEXPANSION + +SET O3DE_DEV=C:\Depot\o3de-engine +::SET OCIO_APPS=C:\Depot\o3de-engine\Tools\ColorGrading\ocio\build\src\apps +SET TAG_LY_BUILD_PATH=build +SET DCCSI_GDEBUG=True +SET DCCSI_DEV_MODE=True + +SET WING_PROJ=%O3DE_PROJECT_PATH%\.solutions\.wing\o3de_color_grading_%DCCSI_WING_VERSION_MAJOR%x.wpr + +::ENDLOCAL + +:: Set flag so we don't initialize dccsi environment twice +SET O3DE_USER_ENV_INIT=1 +GOTO END_OF_FILE + +:: Return to starting directory +POPD + +:END_OF_FILE \ No newline at end of file diff --git a/Gems/Atom/Feature/Common/Tools/ColorGrading/readme.txt b/Gems/Atom/Feature/Common/Tools/ColorGrading/readme.txt new file mode 100644 index 0000000000..ffa6e9d9e5 --- /dev/null +++ b/Gems/Atom/Feature/Common/Tools/ColorGrading/readme.txt @@ -0,0 +1,98 @@ +################################ +# create identity LUT +ociolutimage --generate --cubesize 16 --output C:\Depot\o3de\Gems\Atom\Feature\Common\Tools\ColorGrading\Resources\LUTs\linear_16_LUT.exr + +NOTE: ociolutimage is a OpenColorIO (ocio) app. O3DE does NOT currently build these, however you can build them yourself. + for example, we used vcpkg and cmake gui to build them locally. + we intend to add a fully built integration of ocio in the future. + for now, we have provided all of the LUTs below so that most users will not need the ocio tools. + +################################ +# create base 16x16x16 LUT shaped for grading in 48-nits (LDR), in 1000-nits (HDR), 2000nits, 4000-nits +python %DCCSI_COLORGRADING_SCRIPTS%\lut_helper.py --i C:\Depot\o3de\Gems\Atom\Feature\Common\Tools\ColorGrading\Resources\LUTs\linear_16_LUT.exr --op pre-grading --shaper Log2-48nits --o C:\Depot\o3de\Gems\Atom\Feature\Common\Tools\ColorGrading\Resources\LUTs\base_Log2-48nits_16_LUT.exr + +python %DCCSI_COLORGRADING_SCRIPTS%\lut_helper.py --i C:\Depot\o3de\Gems\Atom\Feature\Common\Tools\ColorGrading\Resources\LUTs\linear_16_LUT.exr --op pre-grading --shaper Log2-1000nits --o C:\Depot\o3de\Gems\Atom\Feature\Common\Tools\ColorGrading\Resources\LUTs\base_Log2-1000nits_16_LUT.exr + +python %DCCSI_COLORGRADING_SCRIPTS%\lut_helper.py --i C:\Depot\o3de\Gems\Atom\Feature\Common\Tools\ColorGrading\Resources\LUTs\linear_16_LUT.exr --op pre-grading --shaper Log2-2000nits --o C:\Depot\o3de\Gems\Atom\Feature\Common\Tools\ColorGrading\Resources\LUTs\base_Log2-2000nits_16_LUT.exr + +python %DCCSI_COLORGRADING_SCRIPTS%\lut_helper.py --i C:\Depot\o3de\Gems\Atom\Feature\Common\Tools\ColorGrading\Resources\LUTs\linear_16_LUT.exr --op pre-grading --shaper Log2-4000nits --o C:\Depot\o3de\Gems\Atom\Feature\Common\Tools\ColorGrading\Resources\LUTs\base_Log2-4000nits_16_LUT.exr + + +################################ +# create base 32x32x32 LUT shaped for grading in 48-nits (LDR), in 1000-nits (HDR), 2000nits, 4000-nits +ociolutimage --generate --cubesize 32 --output C:\Depot\o3de\Gems\Atom\Feature\Common\Tools\ColorGrading\Resources\LUTs\linear_32_LUT.exr + +python %DCCSI_COLORGRADING_SCRIPTS%\lut_helper.py --i C:\Depot\o3de\Gems\Atom\Feature\Common\Tools\ColorGrading\Resources\LUTs\linear_32_LUT.exr --op pre-grading --shaper Log2-48nits --o C:\Depot\o3de\Gems\Atom\Feature\Common\Tools\ColorGrading\Resources\LUTs\base_Log2-48nits_32_LUT.exr + +python %DCCSI_COLORGRADING_SCRIPTS%\lut_helper.py --i C:\Depot\o3de\Gems\Atom\Feature\Common\Tools\ColorGrading\Resources\LUTs\linear_32_LUT.exr --op pre-grading --shaper Log2-1000nits --o C:\Depot\o3de\Gems\Atom\Feature\Common\Tools\ColorGrading\Resources\LUTs\base_Log2-1000nits_32_LUT.exr + +python %DCCSI_COLORGRADING_SCRIPTS%\lut_helper.py --i C:\Depot\o3de\Gems\Atom\Feature\Common\Tools\ColorGrading\Resources\LUTs\linear_32_LUT.exr --op pre-grading --shaper Log2-2000nits --o C:\Depot\o3de\Gems\Atom\Feature\Common\Tools\ColorGrading\Resources\LUTs\base_Log2-2000nits_32_LUT.exr + +python %DCCSI_COLORGRADING_SCRIPTS%\lut_helper.py --i C:\Depot\o3de\Gems\Atom\Feature\Common\Tools\ColorGrading\Resources\LUTs\linear_32_LUT.exr --op pre-grading --shaper Log2-4000nits --o C:\Depot\o3de\Gems\Atom\Feature\Common\Tools\ColorGrading\Resources\LUTs\base_Log2-4000nits_32_LUT.exr + + +################################ +# create base 64x64x64 LUT shaped for grading in 48-nits (LDR), in 1000-nits (HDR), 2000nits, 4000-nits +# LUT size 64 broken output without --maxwidth 4096!!! +ociolutimage --generate --cubesize 64 --maxwidth 4096 --output C:\Depot\o3de\Gems\Atom\Feature\Common\Tools\ColorGrading\Resources\LUTs\linear_64_LUT.exr + +python %DCCSI_COLORGRADING_SCRIPTS%\lut_helper.py --i C:\Depot\o3de\Gems\Atom\Feature\Common\Tools\ColorGrading\Resources\LUTs\linear_64_LUT.exr --op pre-grading --shaper Log2-48nits --o C:\Depot\o3de\Gems\Atom\Feature\Common\Tools\ColorGrading\Resources\LUTs\base_Log2-48nits_64_LUT.exr + +python %DCCSI_COLORGRADING_SCRIPTS%\lut_helper.py --i C:\Depot\o3de\Gems\Atom\Feature\Common\Tools\ColorGrading\Resources\LUTs\linear_64_LUT.exr --op pre-grading --shaper Log2-1000nits --o C:\Depot\o3de\Gems\Atom\Feature\Common\Tools\ColorGrading\Resources\LUTs\base_Log2-1000nits_64_LUT.exr + +python %DCCSI_COLORGRADING_SCRIPTS%\lut_helper.py --i C:\Depot\o3de\Gems\Atom\Feature\Common\Tools\ColorGrading\Resources\LUTs\linear_64_LUT.exr --op pre-grading --shaper Log2-2000nits --o C:\Depot\o3de\Gems\Atom\Feature\Common\Tools\ColorGrading\Resources\LUTs\base_Log2-2000nits_64_LUT.exr + +python %DCCSI_COLORGRADING_SCRIPTS%\lut_helper.py --i C:\Depot\o3de\Gems\Atom\Feature\Common\Tools\ColorGrading\Resources\LUTs\linear_64_LUT.exr --op pre-grading --shaper Log2-4000nits --o C:\Depot\o3de\Gems\Atom\Feature\Common\Tools\ColorGrading\Resources\LUTs\base_Log2-4000nits_64_LUT.exr + + +################################ +# Photoshop, Basics +Examples: C:\Depot\o3de-engine\Gems\Atom\Feature\Common\Tools\ColorGrading\Resources\TestData\Photoshop\ + HDR_in_LDR_Log2-48nits\LUT_PreShaped_Composite\* + + 1. This must be installed (righ-click) before launching photoshop: + Gems\Atom\Feature\Common\Tools\ColorGrading\Resources\LUTs\from_ACEScg_to_sRGB.icc + ^ this is to be used as 'custom color proof' (ACES view transform) + + 2. This is the O3DE 'displaymapper passthrough' capture, re-saved as a .exr: + "ColorGrading\Resources\TestData\Photoshop\Log2-48nits\framebuffer_ACEScg_to_sRGB_icc.exr" + ^ open in photoshop, color proof with the above .icc + the image should proof such that it looks the same as camera in O3DE viewport + with the Displaymapper set to ACES + + 3. Composite this base LUT in a layer on top: + "Gems\Atom\Feature\Common\Tools\ColorGrading\Resources\LUTs\base_Log2-48nits_32_LUT.exr" + ^ this is a pre-shaped 32x32x32 LUT we generated above + + 4. Color Grade using adjustment layers (and hope for the best, some photoshop grades may cause values to clip) + + 5. Select/crop just the LUT, 'Copy Merged' into a new document, save into a folder such as: + "ColorGrading\Resources\TestData\Photoshop\Log2-48nits\i_shaped\test_hue-sat_32_LUT.exr" + ^ this lut is post-grade BUT still shaped (need to inv shape back to normailzed 0-1 values) + + 6. Use the provided cmd/python tools, we need to inverse shape: + + Run: "Gems\Atom\Feature\Common\Tools\ColorGrading\cmdline\CMD_ColorGradingTools.bat" + + C:\Depot\o3de-engine\Gems\Atom\Feature\Common\Tools\ColorGrading>> + + python %DCCSI_COLORGRADING_SCRIPTS%\lut_helper.py --i "Resources\TestData\TestData\Photoshop\Log2-48nits\i_shaped\test_hue-sat_32_LUT.exr" --op post-grading --shaper Log2-48nits --o Resources\TestData\Photoshop\Log2-48nits\o_invShaped\test_hue-sat_32_LUT -l -a + + ^ this will inv-shaped LUT (3DL's are normalized in 0-1 space, values may clip!!!) + ^ -e generates LUT as .exr + ^ -l generates a .3DL version + ^ -a generates a .azasset version <-- this copies/moves to an asset folder + +Using LUTs In-engine: + Only the .azasset needs to be copied to a O3DE project assets folder to use in engine, example: + "C:\Depot\o3de-engine\Gems\Atom\Feature\Common\Assets\ColorGrading\TestData\Photoshop\inv-Log2-48nits\test_hue-sat_32_LUT.azasset" + ^ this is just an example path within the engine folder + + The .azasset can be loaded into a 'Look Modification Component' + + If there are multiple properly configured 'Look Modification Components' you can blend LUTs/Looks (in world space, in a cinematic, etc.) + + By default LUTs utilize linear sampling, but you can use the following CVAR to improve quality for 'any difficult lut': + r_lutSampleQuality=0, linear + r_lutSampleQuality=1, b-spline 7 taps + r_lutSampleQuality=2, b-spline 19 taps (highest quality) \ No newline at end of file From e15634a86775703d898a09487f5ab1e9f9b76b50 Mon Sep 17 00:00:00 2001 From: mrieggeramzn <61609885+mrieggeramzn@users.noreply.github.com> Date: Mon, 30 Aug 2021 21:16:54 +0000 Subject: [PATCH 788/803] Adding receiver plane bias to directional shadows (#3305) * Adding receiver plane bias to directional shadows * fixing whitespace issue * Slight spelling change --- .../Features/Shadow/BicubicPcfFilters.azsli | 89 +++++++++++-------- .../Shadow/DirectionalLightShadow.azsli | 18 +++- .../Shadow/ReceiverPlaneDepthBias.azsli | 38 ++++++++ ...irectionalLightFeatureProcessorInterface.h | 4 + .../DirectionalLightFeatureProcessor.cpp | 5 ++ .../DirectionalLightFeatureProcessor.h | 6 ++ .../CoreLights/DirectionalLightBus.h | 8 ++ .../DirectionalLightComponentConfig.h | 4 + .../DirectionalLightComponentConfig.cpp | 4 +- .../DirectionalLightComponentController.cpp | 19 +++- .../DirectionalLightComponentController.h | 2 + .../EditorDirectionalLightComponent.cpp | 10 ++- 12 files changed, 163 insertions(+), 44 deletions(-) create mode 100644 Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/ReceiverPlaneDepthBias.azsli diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/BicubicPcfFilters.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/BicubicPcfFilters.azsli index 37e8634543..65cbeb5874 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/BicubicPcfFilters.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/BicubicPcfFilters.azsli @@ -8,6 +8,8 @@ #pragma once +#include "ReceiverPlaneDepthBias.azsli" + // Pcf filtering taken from legacy Cry/Lumberyard ShadowCommon.cfi. // // Approximate an expensive but smooth bicubic filter by taking multiple bilinear samples and then weighting the samples appropriately. @@ -28,8 +30,12 @@ struct SampleShadowMapBicubicParameters float invShadowMapSize; SamplerComparisonState samplerState; float comparisonValue; + + // Optionally pass in a non-zero value into the receiverPlaneDepthBias to reduce shadow acne with large Pcf kernels + float2 receiverPlaneDepthBias; }; + float SampleShadowMapBicubic_4Tap(SampleShadowMapBicubicParameters param) { // Compute the shadow map UV and fractionals. @@ -47,13 +53,19 @@ float SampleShadowMapBicubic_4Tap(SampleShadowMapBicubicParameters param) float2 uv1 = (fractionalUV / weights1) + 1.0; // Accumulate the shadow results and return the resolve value. - float shadow; + float shadow = 0; + + const float2 uvOffsets[4] = {float2(uv0.x, uv0.y), float2(uv1.x, uv0.y), float2(uv0.x, uv1.y), float2(uv1.x, uv1.y)}; + const float weights[4] = {weights0.x * weights0.y, weights1.x * weights0.y, weights0.x * weights1.y, weights1.x * weights1.y}; + + [unroll] + for(int i = 0 ; i < 4; ++i) + { + const float2 texCoordOffset = uvOffsets[i] * param.invShadowMapSize; + const float fragmentDistance = param.comparisonValue + ApplyReceiverPlaneDepthBias(param.receiverPlaneDepthBias, texCoordOffset); + shadow += weights[i] * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + texCoordOffset, param.shadowPos.z), fragmentDistance); + } - shadow = weights0.x * weights0.y * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + float2(uv0.x, uv0.y) * param.invShadowMapSize, param.shadowPos.z), param.comparisonValue); - shadow += weights1.x * weights0.y * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + float2(uv1.x, uv0.y) * param.invShadowMapSize, param.shadowPos.z), param.comparisonValue); - shadow += weights0.x * weights1.y * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + float2(uv0.x, uv1.y) * param.invShadowMapSize, param.shadowPos.z), param.comparisonValue); - shadow += weights1.x * weights1.y * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + float2(uv1.x, uv1.y) * param.invShadowMapSize, param.shadowPos.z), param.comparisonValue); - shadow /= 16.0; return shadow * shadow; } @@ -80,20 +92,26 @@ float SampleShadowMapBicubic_9Tap(SampleShadowMapBicubicParameters param) float2 uv1 = (3.0 + fractionalUV) / weights1; float2 uv2 = (fractionalUV / weights2) + 2.0; + + const float2 uvOffsets[9] = {float2(uv0.x, uv0.y), float2(uv1.x, uv0.y), float2(uv2.x, uv0.y), + float2(uv0.x, uv1.y), float2(uv1.x, uv1.y), float2(uv2.x, uv1.y), + float2(uv0.x, uv2.y), float2(uv1.x, uv2.y), float2(uv2.x, uv2.y) }; + + const float weights[9] = {weights0.x * weights0.y, weights1.x * weights0.y, weights2.x * weights0.y, + weights0.x * weights1.y, weights1.x * weights1.y, weights2.x * weights1.y, + weights0.x * weights2.y, weights1.x * weights2.y, weights2.x * weights2.y}; + // Accumulate the shadow results and return the resolve value. - float shadowResult; - - shadowResult = weights0.x * weights0.y * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + float2(uv0.x, uv0.y) * param.invShadowMapSize, param.shadowPos.z), param.comparisonValue); - shadowResult += weights1.x * weights0.y * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + float2(uv1.x, uv0.y) * param.invShadowMapSize, param.shadowPos.z), param.comparisonValue); - shadowResult += weights2.x * weights0.y * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + float2(uv2.x, uv0.y) * param.invShadowMapSize, param.shadowPos.z), param.comparisonValue); + float shadowResult = 0; - shadowResult += weights0.x * weights1.y * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + float2(uv0.x, uv1.y) * param.invShadowMapSize, param.shadowPos.z), param.comparisonValue); - shadowResult += weights1.x * weights1.y * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + float2(uv1.x, uv1.y) * param.invShadowMapSize, param.shadowPos.z), param.comparisonValue); - shadowResult += weights2.x * weights1.y * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + float2(uv2.x, uv1.y) * param.invShadowMapSize, param.shadowPos.z), param.comparisonValue); - - shadowResult += weights0.x * weights2.y * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + float2(uv0.x, uv2.y) * param.invShadowMapSize, param.shadowPos.z), param.comparisonValue); - shadowResult += weights1.x * weights2.y * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + float2(uv1.x, uv2.y) * param.invShadowMapSize, param.shadowPos.z), param.comparisonValue); - shadowResult += weights2.x * weights2.y * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + float2(uv2.x, uv2.y) * param.invShadowMapSize, param.shadowPos.z), param.comparisonValue); + [unroll] + for(int i = 0 ; i < 9 ; ++i) + { + const float2 texCoordOffset = uvOffsets[i] * param.invShadowMapSize; + const float fragmentDistance = param.comparisonValue + ApplyReceiverPlaneDepthBias(param.receiverPlaneDepthBias, texCoordOffset); + + shadowResult += weights[i] * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + texCoordOffset, param.shadowPos.z), fragmentDistance); + } shadowResult /= 144.0; return shadowResult * shadowResult; @@ -123,28 +141,27 @@ float SampleShadowMapBicubic_16Tap(SampleShadowMapBicubicParameters param) float2 uv2 = -((7.0 * fractionalUV + 5.0) / weights2) + 1.0; float2 uv3 = -(fractionalUV / weights3) + 3.0; - // Accumulate the shadow results and return the resolve value. - float shadow; + const float2 uvOffsets[16] = {float2(uv0.x, uv0.y), float2(uv1.x, uv0.y), float2(uv2.x, uv0.y), float2(uv3.x, uv0.y), + float2(uv0.x, uv1.y), float2(uv1.x, uv1.y), float2(uv2.x, uv1.y), float2(uv3.x, uv1.y), + float2(uv0.x, uv2.y), float2(uv1.x, uv2.y), float2(uv2.x, uv2.y), float2(uv3.x, uv2.y), + float2(uv0.x, uv3.y), float2(uv1.x, uv3.y), float2(uv2.x, uv3.y), float2(uv3.x, uv3.y)}; - shadow = weights0.x * weights0.y * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + float2(uv0.x, uv0.y) * param.invShadowMapSize, param.shadowPos.z), param.comparisonValue); - shadow += weights1.x * weights0.y * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + float2(uv1.x, uv0.y) * param.invShadowMapSize, param.shadowPos.z), param.comparisonValue); - shadow += weights2.x * weights0.y * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + float2(uv2.x, uv0.y) * param.invShadowMapSize, param.shadowPos.z), param.comparisonValue); - shadow += weights3.x * weights0.y * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + float2(uv3.x, uv0.y) * param.invShadowMapSize, param.shadowPos.z), param.comparisonValue); + const float weights[16] = {weights0.x * weights0.y, weights1.x * weights0.y, weights2.x * weights0.y, weights3.x * weights0.y, + weights0.x * weights1.y, weights1.x * weights1.y, weights2.x * weights1.y, weights3.x * weights1.y, + weights0.x * weights2.y, weights1.x * weights2.y, weights2.x * weights2.y, weights3.x * weights2.y, + weights0.x * weights3.y, weights1.x * weights3.y, weights2.x * weights3.y, weights3.x * weights3.y}; - shadow += weights0.x * weights1.y * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + float2(uv0.x, uv1.y) * param.invShadowMapSize, param.shadowPos.z), param.comparisonValue); - shadow += weights1.x * weights1.y * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + float2(uv1.x, uv1.y) * param.invShadowMapSize, param.shadowPos.z), param.comparisonValue); - shadow += weights2.x * weights1.y * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + float2(uv2.x, uv1.y) * param.invShadowMapSize, param.shadowPos.z), param.comparisonValue); - shadow += weights3.x * weights1.y * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + float2(uv3.x, uv1.y) * param.invShadowMapSize, param.shadowPos.z), param.comparisonValue); + // Accumulate the shadow results and return the resolve value. + float shadow = 0; - shadow += weights0.x * weights2.y * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + float2(uv0.x, uv2.y) * param.invShadowMapSize, param.shadowPos.z), param.comparisonValue); - shadow += weights1.x * weights2.y * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + float2(uv1.x, uv2.y) * param.invShadowMapSize, param.shadowPos.z), param.comparisonValue); - shadow += weights2.x * weights2.y * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + float2(uv2.x, uv2.y) * param.invShadowMapSize, param.shadowPos.z), param.comparisonValue); - shadow += weights3.x * weights2.y * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + float2(uv3.x, uv2.y) * param.invShadowMapSize, param.shadowPos.z), param.comparisonValue); + [unroll] + for(int i = 0 ; i < 16 ; ++i) + { + const float2 texCoordOffset = uvOffsets[i] * param.invShadowMapSize; + const float fragmentDistance = param.comparisonValue + ApplyReceiverPlaneDepthBias(param.receiverPlaneDepthBias, texCoordOffset); - shadow += weights0.x * weights3.y * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + float2(uv0.x, uv3.y) * param.invShadowMapSize, param.shadowPos.z), param.comparisonValue); - shadow += weights1.x * weights3.y * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + float2(uv1.x, uv3.y) * param.invShadowMapSize, param.shadowPos.z), param.comparisonValue); - shadow += weights2.x * weights3.y * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + float2(uv2.x, uv3.y) * param.invShadowMapSize, param.shadowPos.z), param.comparisonValue); - shadow += weights3.x * weights3.y * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + float2(uv3.x, uv3.y) * param.invShadowMapSize, param.shadowPos.z), param.comparisonValue); + shadow += weights[i] * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + texCoordOffset, param.shadowPos.z), fragmentDistance); + } shadow /= 2704; return shadow * shadow; diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/DirectionalLightShadow.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/DirectionalLightShadow.azsli index 8b3eedf2aa..8df13bd19a 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/DirectionalLightShadow.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/DirectionalLightShadow.azsli @@ -14,6 +14,7 @@ #include "Shadow.azsli" #include "ShadowmapAtlasLib.azsli" #include "BicubicPcfFilters.azsli" +#include "ReceiverPlaneDepthBias.azsli" // Before including this azsli file, a PassSrg must be defined with the following members: // Texture2DArray m_directionalLightShadowmap; @@ -23,6 +24,7 @@ // This matchs ShadowFilterMethod in ShadowConstants.h enum class ShadowFilterMethod {None, Pcf, Esm, EsmPcf}; option ShadowFilterMethod o_directional_shadow_filtering_method = ShadowFilterMethod::None; +option bool o_directional_shadow_receiver_plane_bias_enable = true; // DirectionalLightShadow calculates lit ratio for a directional light. class DirectionalLightShadow @@ -107,6 +109,8 @@ class DirectionalLightShadow float m_slopeBias[ViewSrg::MaxCascadeCount]; float3 m_normalVector; DebugInfo m_debugInfo; + float3 m_shadowPosDX[ViewSrg::MaxCascadeCount]; + float3 m_shadowPosDY[ViewSrg::MaxCascadeCount]; }; // This outputs the coordinate in shadowmap Texture space of the given point. @@ -438,6 +442,7 @@ float DirectionalLightShadow::SamplePcfBicubic(float3 shadowCoord, uint indexOfC { const uint filteringSampleCount = ViewSrg::m_directionalLightShadows[m_lightIndex].m_filteringSampleCount; const uint size = ViewSrg::m_directionalLightShadows[m_lightIndex].m_shadowmapSize; + const uint cascadeCount = ViewSrg::m_directionalLightShadows[m_lightIndex].m_cascadeCount; Texture2DArray shadowmap = PassSrg::m_directionalLightShadowmap; @@ -448,7 +453,8 @@ float DirectionalLightShadow::SamplePcfBicubic(float3 shadowCoord, uint indexOfC param.invShadowMapSize = rcp(size); param.comparisonValue = shadowCoord.z; param.samplerState = SceneSrg::m_hwPcfSampler; - + param.receiverPlaneDepthBias = o_directional_shadow_receiver_plane_bias_enable ? ComputeReceiverPlaneDepthBias(m_shadowPosDX[indexOfCascade], m_shadowPosDY[indexOfCascade]) : 0; + if (filteringSampleCount <= 4) { return SampleShadowMapBicubic_4Tap(param); @@ -476,6 +482,16 @@ float DirectionalLightShadow::GetVisibility( shadow.m_debugInfo.m_cascadeIndex = 0; shadow.m_debugInfo.m_usePcfFallback = false; + if (o_directional_shadow_receiver_plane_bias_enable) + { + [unroll] + for(int i = 0 ; i < ViewSrg::MaxCascadeCount ; ++i) + { + shadow.m_shadowPosDX[i] = ddx_fine(shadowCoords[i]); + shadow.m_shadowPosDY[i] = ddy_fine(shadowCoords[i]); + } + } + // Calculate slope bias const float3 lightDirection = normalize(SceneSrg::m_directionalLights[lightIndex].m_direction); diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/ReceiverPlaneDepthBias.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/ReceiverPlaneDepthBias.azsli new file mode 100644 index 0000000000..6225bb3434 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/ReceiverPlaneDepthBias.azsli @@ -0,0 +1,38 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#pragma once + +// Use ddx/ddy to attempt to predict the slope of the receiver plane (the triangle we are shading) and adjust the pcf comparision depth accordingly +// See Section 20.5 Large Pcf Kernels in "Introduction to 3D Game Programming with DirectX 12" for a good explanation and diagrams of the problem +// Solution from: +// https://web.archive.org/web/20120220010450/http://developer.amd.com/media/gpu_assets/Isidoro-ShadowMapping.pdf +// Another implementation example: https://github.com/TheRealMJP/Shadows +float2 ComputeReceiverPlaneDepthBias(float3 projCoordsDDX, float3 projCoordsDDY) +{ + const float invDet = 1.0f / ((projCoordsDDX.x * projCoordsDDY.y) - (projCoordsDDX.y * projCoordsDDY.x)); + + float2 receiverPlaneDepthBias; + + receiverPlaneDepthBias.x = projCoordsDDY.y * projCoordsDDX.z - projCoordsDDX.y * projCoordsDDY.z; + receiverPlaneDepthBias.y = projCoordsDDX.x * projCoordsDDY.z - projCoordsDDY.x * projCoordsDDX.z; + receiverPlaneDepthBias *= invDet; + + return receiverPlaneDepthBias; +} + +// For each sample in the Pcf kernel, offset the z comparison depth value by the amount returned by this function. +// receiverPlaneDepthBias should be the input from ComputeReceiverPlaneDepthBias() +float ApplyReceiverPlaneDepthBias(const float2 receiverPlaneDepthBias, const float2 texCoordOffset) +{ + float fragmentDepthBias = dot(receiverPlaneDepthBias, texCoordOffset); + // Because ddx/ddy can only give us a very rough approximation of the underlying surface, we might introduce acne by biasing away from the camera. + // Clamping this will remove this effect + fragmentDepthBias = min(fragmentDepthBias, 0.0); + return fragmentDepthBias; +} \ No newline at end of file diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/DirectionalLightFeatureProcessorInterface.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/DirectionalLightFeatureProcessorInterface.h index 8dc8f1bade..3244c8249e 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/DirectionalLightFeatureProcessorInterface.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/DirectionalLightFeatureProcessorInterface.h @@ -168,6 +168,10 @@ namespace AZ //! Sets the shadowmap Pcf method. virtual void SetPcfMethod(LightHandle handle, PcfMethod method) = 0; + + //! Sets whether the directional shadowmap should use receiver plane bias. + //! This attempts to reduce shadow acne when using large pcf filters. + virtual void SetShadowReceiverPlaneBiasEnabled(LightHandle handle, bool enable) = 0; }; } // namespace Render } // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp index e0812f633a..44f95a8b85 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp @@ -202,6 +202,7 @@ namespace AZ { uint32_t shadowFilterMethod = m_shadowData.at(nullptr).GetData(m_shadowingLightHandle.GetIndex()).m_shadowFilterMethod; RPI::ShaderSystemInterface::Get()->SetGlobalShaderOption(m_directionalShadowFilteringMethodName, AZ::RPI::ShaderOptionValue{shadowFilterMethod}); + RPI::ShaderSystemInterface::Get()->SetGlobalShaderOption(m_directionalShadowReceiverPlaneBiasEnableName, AZ::RPI::ShaderOptionValue{ m_shadowProperties.GetData(m_shadowingLightHandle.GetIndex()).m_isReceiverPlaneBiasEnabled }); const uint32_t cascadeCount = m_shadowData.at(nullptr).GetData(m_shadowingLightHandle.GetIndex()).m_cascadeCount; ShadowProperty& property = m_shadowProperties.GetData(m_shadowingLightHandle.GetIndex()); @@ -616,6 +617,10 @@ namespace AZ m_shadowBufferNeedsUpdate = true; } + void DirectionalLightFeatureProcessor::SetShadowReceiverPlaneBiasEnabled(LightHandle handle, bool enable) + { + m_shadowProperties.GetData(handle.GetIndex()).m_isReceiverPlaneBiasEnabled = enable; + } void DirectionalLightFeatureProcessor::OnRenderPipelineAdded(RPI::RenderPipelinePtr pipeline) { diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.h index 4c486c4540..d57b3aaf2b 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.h @@ -177,6 +177,10 @@ namespace AZ // Shadow filter method of the light ShadowFilterMethod m_shadowFilterMethod = ShadowFilterMethod::None; + + // If true, this will reduce the shadow acne introduced by large pcf kernels by estimating the angle of the triangle being shaded + // with the ddx/ddy functions. + bool m_isReceiverPlaneBiasEnabled = true; }; static void Reflect(ReflectContext* context); @@ -218,6 +222,7 @@ namespace AZ void SetFilteringSampleCount(LightHandle handle, uint16_t count) override; void SetShadowBoundaryWidth(LightHandle handle, float boundaryWidth) override; void SetPcfMethod(LightHandle handle, PcfMethod method) override; + void SetShadowReceiverPlaneBiasEnabled(LightHandle handle, bool enable) override; const Data::Instance GetLightBuffer() const; uint32_t GetLightCount() const; @@ -371,6 +376,7 @@ namespace AZ Name m_lightTypeName = Name("directional"); Name m_directionalShadowFilteringMethodName = Name("o_directional_shadow_filtering_method"); + Name m_directionalShadowReceiverPlaneBiasEnableName = Name("o_directional_shadow_receiver_plane_bias_enable"); static constexpr const char* FeatureProcessorName = "DirectionalLightFeatureProcessor"; }; } // namespace Render diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/DirectionalLightBus.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/DirectionalLightBus.h index 086f68f80f..610578ee2d 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/DirectionalLightBus.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/DirectionalLightBus.h @@ -185,6 +185,14 @@ namespace AZ //! This sets the type of Pcf (percentage-closer filtering) to use. //! @param method The Pcf method to use. virtual void SetPcfMethod(PcfMethod method) = 0; + + //! Gets whether the directional shadowmap should use receiver plane bias. + //! This attempts to reduce shadow acne when using large pcf filters. + virtual bool GetShadowReceiverPlaneBiasEnabled() const = 0; + + //! Sets whether the directional shadowmap should use receiver plane bias. + //! @param enable flag specifying whether to enable the receiver plane bias feature + virtual void SetShadowReceiverPlaneBiasEnabled(bool enable) = 0; }; using DirectionalLightRequestBus = EBus; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/DirectionalLightComponentConfig.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/DirectionalLightComponentConfig.h index e7fe692213..e9e5778086 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/DirectionalLightComponentConfig.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/DirectionalLightComponentConfig.h @@ -115,6 +115,10 @@ namespace AZ PcfMethod m_pcfMethod = PcfMethod::Bicubic; + //! Whether not to enable the receiver plane bias. + //! This uses partial derivatives to reduce shadow acne when using large pcf kernels. + bool m_receiverPlaneBiasEnabled = true; + bool IsSplitManual() const; bool IsSplitAutomatic() const; bool IsCascadeCorrectionDisabled() const; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DirectionalLightComponentConfig.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DirectionalLightComponentConfig.cpp index 86fb97aeba..24ce566fb4 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DirectionalLightComponentConfig.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DirectionalLightComponentConfig.cpp @@ -21,7 +21,7 @@ namespace AZ if (auto* serializeContext = azrtti_cast(context)) { serializeContext->Class() - ->Version(7) + ->Version(8) ->Field("Color", &DirectionalLightComponentConfig::m_color) ->Field("IntensityMode", &DirectionalLightComponentConfig::m_intensityMode) ->Field("Intensity", &DirectionalLightComponentConfig::m_intensity) @@ -41,7 +41,7 @@ namespace AZ ->Field("PcfPredictionSampleCount", &DirectionalLightComponentConfig::m_predictionSampleCount) ->Field("PcfFilteringSampleCount", &DirectionalLightComponentConfig::m_filteringSampleCount) ->Field("Pcf Method", &DirectionalLightComponentConfig::m_pcfMethod) - ; + ->Field("ShadowReceiverPlaneBiasEnabled", &DirectionalLightComponentConfig::m_receiverPlaneBiasEnabled); } } diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DirectionalLightComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DirectionalLightComponentController.cpp index 642e50d104..6bf449803b 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DirectionalLightComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DirectionalLightComponentController.cpp @@ -88,6 +88,8 @@ namespace AZ ->Event("SetFilteringSampleCount", &DirectionalLightRequestBus::Events::SetFilteringSampleCount) ->Event("GetPcfMethod", &DirectionalLightRequestBus::Events::GetPcfMethod) ->Event("SetPcfMethod", &DirectionalLightRequestBus::Events::SetPcfMethod) + ->Event("GetShadowReceiverPlaneBiasEnabled", &DirectionalLightRequestBus::Events::GetShadowReceiverPlaneBiasEnabled) + ->Event("SetShadowReceiverPlaneBiasEnabled", &DirectionalLightRequestBus::Events::SetShadowReceiverPlaneBiasEnabled) ->VirtualProperty("Color", "GetColor", "SetColor") ->VirtualProperty("Intensity", "GetIntensity", "SetIntensity") ->VirtualProperty("AngularDiameter", "GetAngularDiameter", "SetAngularDiameter") @@ -104,7 +106,8 @@ namespace AZ ->VirtualProperty("SofteningBoundaryWidth", "GetSofteningBoundaryWidth", "SetSofteningBoundaryWidth") ->VirtualProperty("PredictionSampleCount", "GetPredictionSampleCount", "SetPredictionSampleCount") ->VirtualProperty("FilteringSampleCount", "GetFilteringSampleCount", "SetFilteringSampleCount") - ->VirtualProperty("PcfMethod", "GetPcfMethod", "SetPcfMethod"); + ->VirtualProperty("PcfMethod", "GetPcfMethod", "SetPcfMethod") + ->VirtualProperty("ShadowReceiverPlaneBiasEnabled", "GetShadowReceiverPlaneBiasEnabled", "SetShadowReceiverPlaneBiasEnabled"); ; } } @@ -539,6 +542,7 @@ namespace AZ SetPredictionSampleCount(m_configuration.m_predictionSampleCount); SetFilteringSampleCount(m_configuration.m_filteringSampleCount); SetPcfMethod(m_configuration.m_pcfMethod); + SetShadowReceiverPlaneBiasEnabled(m_configuration.m_receiverPlaneBiasEnabled); // [GFX TODO][ATOM-1726] share config for multiple light (e.g., light ID). // [GFX TODO][ATOM-2416] adapt to multiple viewports. @@ -637,6 +641,17 @@ namespace AZ m_configuration.m_pcfMethod = method; m_featureProcessor->SetPcfMethod(m_lightHandle, method); } - + + bool DirectionalLightComponentController::GetShadowReceiverPlaneBiasEnabled() const + { + return m_configuration.m_receiverPlaneBiasEnabled; + } + + void DirectionalLightComponentController::SetShadowReceiverPlaneBiasEnabled(bool enable) + { + m_configuration.m_receiverPlaneBiasEnabled = enable; + m_featureProcessor->SetShadowReceiverPlaneBiasEnabled(m_lightHandle, enable); + } + } // namespace Render } // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DirectionalLightComponentController.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DirectionalLightComponentController.h index 4684852ff1..6b788c241c 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DirectionalLightComponentController.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DirectionalLightComponentController.h @@ -84,6 +84,8 @@ namespace AZ void SetFilteringSampleCount(uint32_t count) override; PcfMethod GetPcfMethod() const override; void SetPcfMethod(PcfMethod method) override; + bool GetShadowReceiverPlaneBiasEnabled() const override; + void SetShadowReceiverPlaneBiasEnabled(bool enable) override; private: friend class EditorDirectionalLightComponent; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorDirectionalLightComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorDirectionalLightComponent.cpp index 9f0e06f203..18d9ad70e0 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorDirectionalLightComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorDirectionalLightComponent.cpp @@ -164,9 +164,13 @@ namespace AZ ->EnumAttribute(PcfMethod::Bicubic, "Bicubic") ->EnumAttribute(PcfMethod::BoundarySearch, "Boundary search") ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) - ->Attribute(Edit::Attributes::ReadOnly, &DirectionalLightComponentConfig::IsShadowPcfDisabled); - ; - + ->Attribute(Edit::Attributes::ReadOnly, &DirectionalLightComponentConfig::IsShadowPcfDisabled) + ->DataElement( + Edit::UIHandlers::CheckBox, &DirectionalLightComponentConfig::m_receiverPlaneBiasEnabled, + "Shadow Receiver Plane Bias Enable", + "This reduces shadow acne when using large pcf kernels.") + ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) + ->Attribute(Edit::Attributes::ReadOnly, &DirectionalLightComponentConfig::IsShadowPcfDisabled); } } From ce962415d226e026d651c9af3fc6ff9af672a138 Mon Sep 17 00:00:00 2001 From: evanchia Date: Mon, 30 Aug 2021 14:20:51 -0700 Subject: [PATCH 789/803] Moving fixed smoke test from sandbox to smoke suite Signed-off-by: evanchia --- .../Gem/PythonTests/smoke/CMakeLists.txt | 12 ------------ .../smoke/test_RemoteConsole_CPULoadLevel_Works.py | 2 +- 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/AutomatedTesting/Gem/PythonTests/smoke/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/smoke/CMakeLists.txt index 5374b0d318..3fc4f3db0e 100644 --- a/AutomatedTesting/Gem/PythonTests/smoke/CMakeLists.txt +++ b/AutomatedTesting/Gem/PythonTests/smoke/CMakeLists.txt @@ -73,17 +73,5 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) AutomatedTesting.GameLauncher AutomatedTesting.Assets ) - ly_add_pytest( - NAME AutomatedTesting::LoadLevelCPU - TEST_SUITE sandbox - PATH ${CMAKE_CURRENT_LIST_DIR}/test_RemoteConsole_CPULoadLevel_Works.py - TIMEOUT 100 - RUNTIME_DEPENDENCIES - AZ::AssetProcessor - AZ::PythonBindingsExample - Legacy::Editor - AutomatedTesting.GameLauncher - AutomatedTesting.Assets - ) endif() diff --git a/AutomatedTesting/Gem/PythonTests/smoke/test_RemoteConsole_CPULoadLevel_Works.py b/AutomatedTesting/Gem/PythonTests/smoke/test_RemoteConsole_CPULoadLevel_Works.py index 701dcfab10..6522514f2f 100644 --- a/AutomatedTesting/Gem/PythonTests/smoke/test_RemoteConsole_CPULoadLevel_Works.py +++ b/AutomatedTesting/Gem/PythonTests/smoke/test_RemoteConsole_CPULoadLevel_Works.py @@ -24,7 +24,7 @@ from ly_remote_console.remote_console_commands import ( @pytest.mark.parametrize("launcher_platform", ["windows"]) @pytest.mark.parametrize("project", ["AutomatedTesting"]) @pytest.mark.parametrize("level", ["Simple"]) -@pytest.mark.SUITE_sandbox +@pytest.mark.SUITE_smoke class TestRemoteConsoleLoadLevelWorks(object): @pytest.fixture def remote_console_instance(self, request): From cdcdcb0777f3836615f36b7719fdb5433b6d558f Mon Sep 17 00:00:00 2001 From: AMZN-nggieber <52797929+AMZN-nggieber@users.noreply.github.com> Date: Mon, 30 Aug 2021 14:22:17 -0700 Subject: [PATCH 790/803] Remove Tab Overlay on Project Manager Startup + More Fixes (#3666) * Refocuses from tab to button on projects screen fist time it is opened Signed-off-by: nggieber * Adds border highlighting to big buttons when they are focused Signed-off-by: nggieber * Fixes issues where project buttons aren't found or deleted on projects screen Signed-off-by: nggieber * Adds tooltip to project name showing project path Signed-off-by: nggieber --- .../Resources/ProjectManager.qss | 13 ++++++--- .../Source/ProjectButtonWidget.cpp | 1 + .../ProjectManager/Source/ProjectsScreen.cpp | 27 +++++++++++++------ .../Tools/ProjectManager/Source/ScreensCtrl.h | 2 +- 4 files changed, 31 insertions(+), 12 deletions(-) diff --git a/Code/Tools/ProjectManager/Resources/ProjectManager.qss b/Code/Tools/ProjectManager/Resources/ProjectManager.qss index 1bd261da00..a45a79dcfc 100644 --- a/Code/Tools/ProjectManager/Resources/ProjectManager.qss +++ b/Code/Tools/ProjectManager/Resources/ProjectManager.qss @@ -213,6 +213,10 @@ QTabBar::tab:focus { stop: 0 #555555, stop: 1.0 #777777); } +#horizontalSeparatingLine { + color: #666666; +} + /************** Project Settings **************/ #projectSettings { margin-top:42px; @@ -293,8 +297,6 @@ QTabBar::tab:focus { border:none; } - - #projectSettingsTab::tab-bar { left: 60px; } @@ -360,6 +362,10 @@ QTabBar::tab:focus { color: #1e70eb; } +#firstTimeContent > QPushButton:focus { + border: 1px solid #1e70eb; +} + #firstTimeContent > QPushButton:pressed { border: 1px solid #0e60eb; color: #0e60eb; @@ -400,7 +406,8 @@ QTabBar::tab:focus { } #projectButton > #labelButton:hover, -#projectButton > #labelButton:pressed { +#projectButton > #labelButton:pressed, +#projectButton > #labelButton:focus { border:1px solid #1e70eb; } diff --git a/Code/Tools/ProjectManager/Source/ProjectButtonWidget.cpp b/Code/Tools/ProjectManager/Source/ProjectButtonWidget.cpp index 5bae3b807a..0f51524341 100644 --- a/Code/Tools/ProjectManager/Source/ProjectButtonWidget.cpp +++ b/Code/Tools/ProjectManager/Source/ProjectButtonWidget.cpp @@ -192,6 +192,7 @@ namespace O3DE::ProjectManager projectFooter->setLayout(hLayout); { QLabel* projectNameLabel = new QLabel(m_projectInfo.GetProjectDisplayName(), this); + projectNameLabel->setToolTip(m_projectInfo.m_path); hLayout->addWidget(projectNameLabel); QMenu* menu = new QMenu(this); diff --git a/Code/Tools/ProjectManager/Source/ProjectsScreen.cpp b/Code/Tools/ProjectManager/Source/ProjectsScreen.cpp index aa231afef2..81d4047db5 100644 --- a/Code/Tools/ProjectManager/Source/ProjectsScreen.cpp +++ b/Code/Tools/ProjectManager/Source/ProjectsScreen.cpp @@ -65,6 +65,16 @@ namespace O3DE::ProjectManager vLayout->addWidget(m_stack); connect(reinterpret_cast(parent), &ScreensCtrl::NotifyBuildProject, this, &ProjectsScreen::SuggestBuildProject); + + // Will focus whatever button it finds so the Project tab is not focused on start-up + QTimer::singleShot(0, this, [this] + { + QPushButton* foundButton = m_stack->currentWidget()->findChild(); + if (foundButton) + { + foundButton->setFocus(); + } + }); } ProjectsScreen::~ProjectsScreen() @@ -166,7 +176,7 @@ namespace O3DE::ProjectManager ProjectButton* ProjectsScreen::CreateProjectButton(const ProjectInfo& project) { ProjectButton* projectButton = new ProjectButton(project, this); - m_projectButtons.insert(project.m_path, projectButton); + m_projectButtons.insert(QDir::toNativeSeparators(project.m_path), projectButton); m_projectsFlowLayout->addWidget(projectButton); connect(projectButton, &ProjectButton::OpenProject, this, &ProjectsScreen::HandleOpenProject); @@ -193,7 +203,7 @@ namespace O3DE::ProjectManager QSet keepProject; for (const ProjectInfo& project : projectsVector) { - keepProject.insert(project.m_path); + keepProject.insert(QDir::toNativeSeparators(project.m_path)); } // Clear flow and delete buttons for removed projects @@ -204,6 +214,7 @@ namespace O3DE::ProjectManager if (!keepProject.contains(projectButtonsIter.key())) { + projectButtonsIter.value()->deleteLater(); projectButtonsIter = m_projectButtons.erase(projectButtonsIter); } else @@ -215,7 +226,7 @@ namespace O3DE::ProjectManager QString buildProjectPath = ""; if (m_currentBuilder) { - buildProjectPath = m_currentBuilder->GetProjectInfo().m_path; + buildProjectPath = QDir::toNativeSeparators(m_currentBuilder->GetProjectInfo().m_path); } // Put currently building project in front, then queued projects, then sorts alphabetically @@ -249,13 +260,13 @@ namespace O3DE::ProjectManager // Add any missing project buttons and restore buttons to default state for (const ProjectInfo& project : projectsVector) { - if (!m_projectButtons.contains(project.m_path)) + if (!m_projectButtons.contains(QDir::toNativeSeparators(project.m_path))) { - m_projectButtons.insert(project.m_path, CreateProjectButton(project)); + m_projectButtons.insert(QDir::toNativeSeparators(project.m_path), CreateProjectButton(project)); } else { - auto projectButtonIter = m_projectButtons.find(project.m_path); + auto projectButtonIter = m_projectButtons.find(QDir::toNativeSeparators(project.m_path)); if (projectButtonIter != m_projectButtons.end()) { projectButtonIter.value()->RestoreDefaultState(); @@ -273,7 +284,7 @@ namespace O3DE::ProjectManager for (const ProjectInfo& project : m_buildQueue) { - auto projectIter = m_projectButtons.find(project.m_path); + auto projectIter = m_projectButtons.find(QDir::toNativeSeparators(project.m_path)); if (projectIter != m_projectButtons.end()) { projectIter.value()->SetProjectButtonAction( @@ -288,7 +299,7 @@ namespace O3DE::ProjectManager for (const ProjectInfo& project : m_requiresBuild) { - auto projectIter = m_projectButtons.find(project.m_path); + auto projectIter = m_projectButtons.find(QDir::toNativeSeparators(project.m_path)); if (projectIter != m_projectButtons.end()) { if (project.m_buildFailed) diff --git a/Code/Tools/ProjectManager/Source/ScreensCtrl.h b/Code/Tools/ProjectManager/Source/ScreensCtrl.h index f046adbe78..7132d64dd0 100644 --- a/Code/Tools/ProjectManager/Source/ScreensCtrl.h +++ b/Code/Tools/ProjectManager/Source/ScreensCtrl.h @@ -19,7 +19,7 @@ QT_FORWARD_DECLARE_CLASS(QTabWidget) namespace O3DE::ProjectManager { - class ScreenWidget; + QT_FORWARD_DECLARE_CLASS(ScreenWidget); class ScreensCtrl : public QWidget From a7309cf2eb5fd4c39731a32fae8b6b68dee99205 Mon Sep 17 00:00:00 2001 From: jiaweig <51759646+jiaweig-amzn@users.noreply.github.com> Date: Mon, 30 Aug 2021 14:57:46 -0700 Subject: [PATCH 791/803] ATOM-16346 Change Atom setreg path (#3690) * Changed path Amazon to O3DE. Fixed issues that setreg is not loaded in game launchers. Signed-off-by: jiaweig * Add brackets. Signed-off-by: jiaweig --- .../Application/GameApplication.cpp | 6 +++++ .../RHI.Reflect/PlatformLimitsDescriptor.h | 2 +- .../RHI.Reflect/PlatformLimitsDescriptor.cpp | 2 +- Gems/Atom/RHI/Code/Source/RHI/RHISystem.cpp | 2 +- .../DX12/PlatformLimitsDescriptor.h | 2 ++ .../RHI.Reflect/PlatformLimitsDescriptor.cpp | 23 +++++++++++++++++++ .../Registry/PhysicalDeviceDriverInfo.setreg | 2 +- .../Platform/Android/PlatformLimits.setreg | 2 +- .../Platform/Linux/PlatformLimits.setreg | 2 +- .../Platform/Mac/PlatformLimits.setreg | 2 +- .../Platform/Windows/PlatformLimits.setreg | 2 +- .../Platform/iOS/PlatformLimits.setreg | 2 +- 12 files changed, 40 insertions(+), 9 deletions(-) diff --git a/Code/Framework/AzGameFramework/AzGameFramework/Application/GameApplication.cpp b/Code/Framework/AzGameFramework/AzGameFramework/Application/GameApplication.cpp index b4d61d7ac1..c42720311c 100644 --- a/Code/Framework/AzGameFramework/AzGameFramework/Application/GameApplication.cpp +++ b/Code/Framework/AzGameFramework/AzGameFramework/Application/GameApplication.cpp @@ -55,6 +55,12 @@ namespace AzGameFramework AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_TargetBuildDependencyRegistry(registry, AZ_TRAIT_OS_PLATFORM_CODENAME, specializations, &scratchBuffer); +#if AZ_TRAIT_OS_IS_HOST_OS_PLATFORM && (defined (AZ_DEBUG_BUILD) || defined(AZ_PROFILE_BUILD)) + AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_EngineRegistry(registry, AZ_TRAIT_OS_PLATFORM_CODENAME, specializations, &scratchBuffer); + AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_GemRegistries(registry, AZ_TRAIT_OS_PLATFORM_CODENAME, specializations, &scratchBuffer); + AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_ProjectRegistry(registry, AZ_TRAIT_OS_PLATFORM_CODENAME, specializations, &scratchBuffer); +#endif + // Used the lowercase the platform name since the bootstrap.game...setreg is being loaded // from the asset cache root where all the files are in lowercased from regardless of the filesystem case-sensitivity static constexpr char filename[] = "bootstrap.game." AZ_BUILD_CONFIGURATION_TYPE "." AZ_TRAIT_OS_PLATFORM_CODENAME_LOWER ".setreg"; diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI.Reflect/PlatformLimitsDescriptor.h b/Gems/Atom/RHI/Code/Include/Atom/RHI.Reflect/PlatformLimitsDescriptor.h index 2d85420694..a239242b33 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI.Reflect/PlatformLimitsDescriptor.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI.Reflect/PlatformLimitsDescriptor.h @@ -68,7 +68,7 @@ namespace AZ HeapMemoryHintParameters m_usageHintParameters; HeapAllocationStrategy m_heapAllocationStrategy = HeapAllocationStrategy::MemoryHint; - void LoadPlatformLimitsDescriptor(const char* rhiName); + virtual void LoadPlatformLimitsDescriptor(const char* rhiName); }; class PlatformLimits final diff --git a/Gems/Atom/RHI/Code/Source/RHI.Reflect/PlatformLimitsDescriptor.cpp b/Gems/Atom/RHI/Code/Source/RHI.Reflect/PlatformLimitsDescriptor.cpp index 250f03716d..eaaefe6065 100644 --- a/Gems/Atom/RHI/Code/Source/RHI.Reflect/PlatformLimitsDescriptor.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI.Reflect/PlatformLimitsDescriptor.cpp @@ -77,7 +77,7 @@ namespace AZ void PlatformLimitsDescriptor::LoadPlatformLimitsDescriptor(const char* rhiName) { auto settingsRegistry = AZ::SettingsRegistry::Get(); - AZStd::string platformLimitsRegPath = AZStd::string::format("/Amazon/Atom/RHI/PlatformLimits/%s", rhiName); + AZStd::string platformLimitsRegPath = AZStd::string::format("/O3DE/Atom/RHI/PlatformLimits/%s", rhiName); if (!(settingsRegistry && settingsRegistry->GetObject(this, azrtti_typeid(this), platformLimitsRegPath.c_str()))) { diff --git a/Gems/Atom/RHI/Code/Source/RHI/RHISystem.cpp b/Gems/Atom/RHI/Code/Source/RHI/RHISystem.cpp index b03cb34140..a381209d2b 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/RHISystem.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/RHISystem.cpp @@ -147,7 +147,7 @@ namespace AZ // Some GPU drivers have known issues and it is recommended to update or use other versions. auto settingsRegistry = AZ::SettingsRegistry::Get(); PhysicalDeviceDriverValidator physicalDriverValidator; - if (!(settingsRegistry && settingsRegistry->GetObject(physicalDriverValidator, "/Amazon/Atom/RHI/PhysicalDeviceDriverInfo"))) + if (!(settingsRegistry && settingsRegistry->GetObject(physicalDriverValidator, "/O3DE/Atom/RHI/PhysicalDeviceDriverInfo"))) { AZ_Printf("RHISystem", "Failed to get settings registry for GPU driver Info."); } diff --git a/Gems/Atom/RHI/DX12/Code/Include/Atom/RHI.Reflect/DX12/PlatformLimitsDescriptor.h b/Gems/Atom/RHI/DX12/Code/Include/Atom/RHI.Reflect/DX12/PlatformLimitsDescriptor.h index cbf1fd11f6..1f22599b38 100644 --- a/Gems/Atom/RHI/DX12/Code/Include/Atom/RHI.Reflect/DX12/PlatformLimitsDescriptor.h +++ b/Gems/Atom/RHI/DX12/Code/Include/Atom/RHI.Reflect/DX12/PlatformLimitsDescriptor.h @@ -65,6 +65,8 @@ namespace AZ AZStd::unordered_map> m_descriptorHeapLimits; FrameGraphExecuterData m_frameGraphExecuterData; + + void LoadPlatformLimitsDescriptor(const char* rhiName) override; }; } } diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI.Reflect/PlatformLimitsDescriptor.cpp b/Gems/Atom/RHI/DX12/Code/Source/RHI.Reflect/PlatformLimitsDescriptor.cpp index 980264aa9b..77b41d6ffc 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI.Reflect/PlatformLimitsDescriptor.cpp +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI.Reflect/PlatformLimitsDescriptor.cpp @@ -7,6 +7,7 @@ */ #include #include +#include namespace AZ { @@ -39,5 +40,27 @@ namespace AZ ; } } + + void PlatformLimitsDescriptor::LoadPlatformLimitsDescriptor(const char* rhiName) + { + auto settingsRegistry = AZ::SettingsRegistry::Get(); + AZStd::string platformLimitsRegPath = AZStd::string::format("/O3DE/Atom/RHI/PlatformLimits/%s", rhiName); + if (!(settingsRegistry && settingsRegistry->GetObject(this, azrtti_typeid(this), platformLimitsRegPath.c_str()))) + { + AZ_Warning( + "Device", false, "Platform limits for %s %s is not loaded correctly. Will use default values.", + AZ_TRAIT_OS_PLATFORM_NAME, rhiName); + + // Map default value must be initialized after attempting to serialize (and result in failure). + // Otherwise, serialization won't overwrite the default values. + m_descriptorHeapLimits = AZStd::unordered_map>({ + { AZStd::string("DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV"), { 1000000, 1000000 } }, + { AZStd::string("DESCRIPTOR_HEAP_TYPE_SAMPLER"), { 2048, 2048 } }, + { AZStd::string("DESCRIPTOR_HEAP_TYPE_RTV"), { 2048, 0 } }, + { AZStd::string("DESCRIPTOR_HEAP_TYPE_DSV"), { 2048, 0 } } + }); + } + + } } } diff --git a/Gems/Atom/RHI/Registry/PhysicalDeviceDriverInfo.setreg b/Gems/Atom/RHI/Registry/PhysicalDeviceDriverInfo.setreg index 823b9e5fcd..ecb2a0fb54 100644 --- a/Gems/Atom/RHI/Registry/PhysicalDeviceDriverInfo.setreg +++ b/Gems/Atom/RHI/Registry/PhysicalDeviceDriverInfo.setreg @@ -8,7 +8,7 @@ // { - "Amazon": + "O3DE": { "Atom": { diff --git a/Gems/Atom/RHI/Registry/Platform/Android/PlatformLimits.setreg b/Gems/Atom/RHI/Registry/Platform/Android/PlatformLimits.setreg index 6ce3c88bbb..683098138f 100644 --- a/Gems/Atom/RHI/Registry/Platform/Android/PlatformLimits.setreg +++ b/Gems/Atom/RHI/Registry/Platform/Android/PlatformLimits.setreg @@ -8,7 +8,7 @@ // { - "Amazon": + "O3DE": { "Atom": { diff --git a/Gems/Atom/RHI/Registry/Platform/Linux/PlatformLimits.setreg b/Gems/Atom/RHI/Registry/Platform/Linux/PlatformLimits.setreg index 7c60aeb098..ce1e65fb40 100644 --- a/Gems/Atom/RHI/Registry/Platform/Linux/PlatformLimits.setreg +++ b/Gems/Atom/RHI/Registry/Platform/Linux/PlatformLimits.setreg @@ -8,7 +8,7 @@ // { - "Amazon": + "O3DE": { "Atom": { diff --git a/Gems/Atom/RHI/Registry/Platform/Mac/PlatformLimits.setreg b/Gems/Atom/RHI/Registry/Platform/Mac/PlatformLimits.setreg index 508287b762..b16e72b625 100644 --- a/Gems/Atom/RHI/Registry/Platform/Mac/PlatformLimits.setreg +++ b/Gems/Atom/RHI/Registry/Platform/Mac/PlatformLimits.setreg @@ -8,7 +8,7 @@ // { - "Amazon": + "O3DE": { "Atom": { diff --git a/Gems/Atom/RHI/Registry/Platform/Windows/PlatformLimits.setreg b/Gems/Atom/RHI/Registry/Platform/Windows/PlatformLimits.setreg index dd1273953b..240f8b041c 100644 --- a/Gems/Atom/RHI/Registry/Platform/Windows/PlatformLimits.setreg +++ b/Gems/Atom/RHI/Registry/Platform/Windows/PlatformLimits.setreg @@ -8,7 +8,7 @@ // { - "Amazon": + "O3DE": { "Atom": { diff --git a/Gems/Atom/RHI/Registry/Platform/iOS/PlatformLimits.setreg b/Gems/Atom/RHI/Registry/Platform/iOS/PlatformLimits.setreg index 508287b762..b16e72b625 100644 --- a/Gems/Atom/RHI/Registry/Platform/iOS/PlatformLimits.setreg +++ b/Gems/Atom/RHI/Registry/Platform/iOS/PlatformLimits.setreg @@ -8,7 +8,7 @@ // { - "Amazon": + "O3DE": { "Atom": { From e8fa1dca58dd0f238cf3178e0432850212e9b745 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Mon, 30 Aug 2021 15:21:13 -0700 Subject: [PATCH 792/803] Improves runtime dependencies input dependency (#3665) Changes how runtime dependencies are hooked as dependencies to create depenedencies to the inputs This makes it that if an input to the runtime dependencies changes, it gets re-copied (e.g. a 3rdParty changes or a file added through ly_add_target_files) Closes Issue #3391 Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../AzFramework/IO/LocalFileIO.cpp | 21 +++++----- .../Code/Tests/TestFramework/AWSCoreFixture.h | 1 + cmake/LYWrappers.cmake | 39 +++++++++++++++++-- cmake/LyAutoGen.cmake | 2 +- cmake/Platform/Common/Install_common.cmake | 3 +- .../Common/RuntimeDependencies_common.cmake | 20 +++++++--- .../runtime_dependencies_common.cmake.in | 2 + 7 files changed, 67 insertions(+), 21 deletions(-) diff --git a/Code/Framework/AzFramework/AzFramework/IO/LocalFileIO.cpp b/Code/Framework/AzFramework/AzFramework/IO/LocalFileIO.cpp index 076cce4965..aca7a41950 100644 --- a/Code/Framework/AzFramework/AzFramework/IO/LocalFileIO.cpp +++ b/Code/Framework/AzFramework/AzFramework/IO/LocalFileIO.cpp @@ -673,18 +673,17 @@ namespace AZ { AZ_Assert(path && path[0] != '%', "%% is deprecated, @ is the only valid alias token"); AZStd::string_view pathView(path); - AZStd::string_view aliasKey; - AZStd::string_view aliasValue; - for (const auto& alias : m_aliases) - { - AZStd::string_view key{ alias.first }; - if (AZ::StringFunc::StartsWith(pathView, key)) // we only support aliases at the front of the path + + const auto found = AZStd::find_if(m_aliases.begin(), m_aliases.end(), + [pathView](const auto& alias) { - aliasKey = key; - aliasValue = alias.second; - break; - } - } + return pathView.starts_with(alias.first); + }); + + using string_view_pair = AZStd::pair; + auto [aliasKey, aliasValue] = (found != m_aliases.end()) ? string_view_pair(*found) + : string_view_pair{}; + size_t requiredResolvedPathSize = pathView.size() - aliasKey.size() + aliasValue.size() + 1; AZ_Assert(path != resolvedPath && resolvedPathSize >= requiredResolvedPathSize, "Resolved path is incorrect"); // we assert above, but we also need to properly handle the case when the resolvedPath buffer size diff --git a/Gems/AWSCore/Code/Tests/TestFramework/AWSCoreFixture.h b/Gems/AWSCore/Code/Tests/TestFramework/AWSCoreFixture.h index 9d33d96215..a5c2bf6475 100644 --- a/Gems/AWSCore/Code/Tests/TestFramework/AWSCoreFixture.h +++ b/Gems/AWSCore/Code/Tests/TestFramework/AWSCoreFixture.h @@ -132,6 +132,7 @@ public: AZ::IO::FileIOBase::SetInstance(nullptr); delete m_localFileIO; + m_localFileIO = nullptr; if (m_otherFileIO) { diff --git a/cmake/LYWrappers.cmake b/cmake/LYWrappers.cmake index 1a8e805f91..3dfef0bbbf 100644 --- a/cmake/LYWrappers.cmake +++ b/cmake/LYWrappers.cmake @@ -29,6 +29,20 @@ define_property(TARGET PROPERTY GEM_MODULE ]] ) +define_property(TARGET PROPERTY RUNTIME_DEPENDENCIES_DEPENDS + BRIEF_DOCS "Defines the dependencies the runtime dependencies of a target has" + FULL_DOCS [[ + Property which is queried through generator expressions at the moment + the target is declared so a custom command that will do the copies can + be generated later. Custom commands need to be declared in the same folder + the target is declared, however, runtime dependencies need all targets + to be declared, so it is done towards the end of CMake parsing. When + runtime dependencies are processed, this target property is filled so the + right dependencies are set for the custom command. + This property contains all the files that are going to be copied to the output + when the target gets built. + ]] +) #! ly_add_target: adds a target and provides parameters for the common configurations. # @@ -310,16 +324,35 @@ function(ly_add_target) set_property(GLOBAL APPEND PROPERTY LY_ALL_TARGET_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}) endif() + # Custom commands need to be declared in the same folder as the target that they use. + # Not all the targets will require runtime dependencies, but we will generate at least an + # empty file for them. set(runtime_dependencies_list SHARED MODULE EXECUTABLE APPLICATION) if(NOT ly_add_target_IMPORTED AND linking_options IN_LIST runtime_dependencies_list) - add_custom_command(TARGET ${ly_add_target_NAME} POST_BUILD + # the stamp file will be the one that triggers the execution of the custom rule. At the end + # of running the copy of runtime dependencies, the stamp file is touched so the timestamp is updated. + # Adding a config as part of the name since the stamp file is added to the VS project. + # Note the STAMP_OUTPUT_FILE need to match with the one used in runtime dependencies (e.g. RuntimeDependencies_common.cmake) + set(STAMP_OUTPUT_FILE ${CMAKE_BINARY_DIR}/runtime_dependencies/$/${ly_add_target_NAME}_$.stamp) + add_custom_command( + OUTPUT ${STAMP_OUTPUT_FILE} + DEPENDS "$>" COMMAND ${CMAKE_COMMAND} -P ${CMAKE_BINARY_DIR}/runtime_dependencies/$/${ly_add_target_NAME}.cmake - DEPENDS ${CMAKE_BINARY_DIR}/runtime_dependencies/${ly_add_target_NAME}.cmake - MESSAGE "Copying runtime dependencies..." + COMMENT "Copying ${ly_add_target_NAME} runtime dependencies to output..." VERBATIM ) + # Unfortunately the VS generator cannot deal with generation expressions as part of the file name, wrapping the + # stamp file on each configuration so it gets properly excluded by the generator + unset(stamp_files_per_config) + foreach(conf IN LISTS CMAKE_CONFIGURATION_TYPES) + set(stamp_file_conf ${CMAKE_BINARY_DIR}/runtime_dependencies/${conf}/${ly_add_target_NAME}_${conf}.stamp) + set_source_files_properties(${stamp_file_conf} PROPERTIES GENERATED TRUE SKIP_AUTOGEN TRUE) + list(APPEND stamp_files_per_config $<$:${stamp_file_conf}>) + endforeach() + target_sources(${ly_add_target_NAME} PRIVATE ${stamp_files_per_config}) + endif() if(ly_add_target_AUTOGEN_RULES) diff --git a/cmake/LyAutoGen.cmake b/cmake/LyAutoGen.cmake index 4aec0f9726..2f5891d837 100644 --- a/cmake/LyAutoGen.cmake +++ b/cmake/LyAutoGen.cmake @@ -34,8 +34,8 @@ function(ly_add_autogen) add_custom_command( OUTPUT ${AUTOGEN_OUTPUTS} DEPENDS ${AZCG_DEPENDENCIES} - COMMAND ${CMAKE_COMMAND} -E echo "Running AutoGen for ${ly_add_autogen_NAME}" COMMAND ${LY_PYTHON_CMD} "${LY_ROOT_FOLDER}/cmake/AzAutoGen.py" "${CMAKE_BINARY_DIR}/Azcg/TemplateCache/" "${CMAKE_CURRENT_BINARY_DIR}/Azcg/Generated/" "${CMAKE_CURRENT_SOURCE_DIR}" "${AZCG_INPUTFILES}" "${ly_add_autogen_AUTOGEN_RULES}" + COMMENT "Running AutoGen for ${ly_add_autogen_NAME}" VERBATIM ) set_target_properties(${ly_add_autogen_NAME} PROPERTIES AUTOGEN_INPUT_FILES "${AZCG_INPUTFILES}") diff --git a/cmake/Platform/Common/Install_common.cmake b/cmake/Platform/Common/Install_common.cmake index bee2349e75..0bd598f70e 100644 --- a/cmake/Platform/Common/Install_common.cmake +++ b/cmake/Platform/Common/Install_common.cmake @@ -486,7 +486,8 @@ endfunction()" ly_get_runtime_dependencies(runtime_dependencies ${target}) foreach(runtime_dependency ${runtime_dependencies}) unset(runtime_command) - ly_get_runtime_dependency_command(runtime_command ${runtime_dependency}) + unset(runtime_depend) # unused, but required to be passed to ly_get_runtime_dependency_command + ly_get_runtime_dependency_command(runtime_command runtime_depend ${runtime_dependency}) string(CONFIGURE "${runtime_command}" runtime_command @ONLY) list(APPEND runtime_commands ${runtime_command}) endforeach() diff --git a/cmake/Platform/Common/RuntimeDependencies_common.cmake b/cmake/Platform/Common/RuntimeDependencies_common.cmake index a669602ff7..dbc8513c97 100644 --- a/cmake/Platform/Common/RuntimeDependencies_common.cmake +++ b/cmake/Platform/Common/RuntimeDependencies_common.cmake @@ -113,7 +113,7 @@ function(ly_get_runtime_dependencies ly_RUNTIME_DEPENDENCIES ly_TARGET) unset(target_locations) get_target_property(target_locations ${ly_TARGET} ${imported_property}) if(target_locations) - list(APPEND all_runtime_dependencies ${target_locations}) + list(APPEND all_runtime_dependencies "${target_locations}") else() # Check if the property exists for configurations unset(target_locations) @@ -156,7 +156,7 @@ function(ly_get_runtime_dependencies ly_RUNTIME_DEPENDENCIES ly_TARGET) endfunction() -function(ly_get_runtime_dependency_command ly_RUNTIME_COMMAND ly_TARGET) +function(ly_get_runtime_dependency_command ly_RUNTIME_COMMAND ly_RUNTIME_DEPEND ly_TARGET) # To optimize this, we are going to cache the commands for the targets we requested. A lot of targets end up being # dependencies of other targets. @@ -166,6 +166,8 @@ function(ly_get_runtime_dependency_command ly_RUNTIME_COMMAND ly_TARGET) # We already walked through this target get_property(cached_command GLOBAL PROPERTY LY_RUNTIME_DEPENDENCY_COMMAND_${ly_TARGET}) set(${ly_RUNTIME_COMMAND} ${cached_command} PARENT_SCOPE) + get_property(cached_depend GLOBAL PROPERTY LY_RUNTIME_DEPENDENCY_DEPEND_${ly_TARGET}) + set(${ly_RUNTIME_DEPEND} "${cached_depend}" PARENT_SCOPE) return() endif() @@ -223,6 +225,8 @@ function(ly_get_runtime_dependency_command ly_RUNTIME_COMMAND ly_TARGET) set_property(GLOBAL PROPERTY LY_RUNTIME_DEPENDENCY_COMMAND_${ly_TARGET} "${runtime_command}") set(${ly_RUNTIME_COMMAND} ${runtime_command} PARENT_SCOPE) + set_property(GLOBAL PROPERTY LY_RUNTIME_DEPENDENCY_DEPEND_${ly_TARGET} "${source_file}") + set(${ly_RUNTIME_DEPEND} "${source_file}" PARENT_SCOPE) endfunction() @@ -245,17 +249,20 @@ function(ly_delayed_generate_runtime_dependencies) unset(runtime_dependencies) unset(LY_COPY_COMMANDS) + unset(runtime_depends) ly_get_runtime_dependencies(runtime_dependencies ${target}) foreach(runtime_dependency ${runtime_dependencies}) unset(runtime_command) - ly_get_runtime_dependency_command(runtime_command ${runtime_dependency}) + unset(runtime_depend) + ly_get_runtime_dependency_command(runtime_command runtime_depend ${runtime_dependency}) string(APPEND LY_COPY_COMMANDS ${runtime_command}) + list(APPEND runtime_depends ${runtime_depend}) endforeach() - # Generate the output file + # Generate the output file, note the STAMP_OUTPUT_FILE need to match with the one defined in LYWrappers.cmake + set(STAMP_OUTPUT_FILE ${CMAKE_BINARY_DIR}/runtime_dependencies/$/${target}_$.stamp) set(target_file_dir "$") - set(target_file "$") ly_file_read(${LY_RUNTIME_DEPENDENCIES_TEMPLATE} template_file) string(CONFIGURE "${LY_COPY_COMMANDS}" LY_COPY_COMMANDS @ONLY) string(CONFIGURE "${template_file}" configured_template_file @ONLY) @@ -263,6 +270,9 @@ function(ly_delayed_generate_runtime_dependencies) OUTPUT ${CMAKE_BINARY_DIR}/runtime_dependencies/$/${target}.cmake CONTENT "${configured_template_file}" ) + + # set the property that is consumed from the custom command generated in LyWrappers.cmake + set_target_properties(${target} PROPERTIES RUNTIME_DEPENDENCIES_DEPENDS "${runtime_depends}") endforeach() diff --git a/cmake/Platform/Common/runtime_dependencies_common.cmake.in b/cmake/Platform/Common/runtime_dependencies_common.cmake.in index bb280f895b..6e41dbaad1 100644 --- a/cmake/Platform/Common/runtime_dependencies_common.cmake.in +++ b/cmake/Platform/Common/runtime_dependencies_common.cmake.in @@ -22,3 +22,5 @@ function(ly_copy source_file target_directory) endfunction() @LY_COPY_COMMANDS@ + +file(TOUCH @STAMP_OUTPUT_FILE@) From 0e3c4cfb3a49ff8a88083a68971b862754fc32f6 Mon Sep 17 00:00:00 2001 From: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> Date: Mon, 30 Aug 2021 17:49:19 -0500 Subject: [PATCH 793/803] Updated Terrain Gem Info (#3688) Improved description, removed unused icon, and added documentation link. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> --- Gems/Terrain/gem.json | 8 ++++---- Gems/Terrain/preview.png | 3 --- 2 files changed, 4 insertions(+), 7 deletions(-) delete mode 100644 Gems/Terrain/preview.png diff --git a/Gems/Terrain/gem.json b/Gems/Terrain/gem.json index ccf034d399..c01ea7e534 100644 --- a/Gems/Terrain/gem.json +++ b/Gems/Terrain/gem.json @@ -1,10 +1,10 @@ { "gem_name": "Terrain", - "display_name": "Terrain (WIP)", + "display_name": "Terrain", "license": "Apache-2.0 Or MIT", "origin": "Open 3D Engine - o3de.org", - "summary": "The Terrain Gem is a WIP (work-in-progress) Gem for providing terrain services including authoring workflows, rendering, and physics.", + "summary": "The Terrain Gem is an experimental terrain system. The terrain system maps height, color, and surface data to regions of the world, provides gradient-based and shape-based authoring tools and workflows, includes specialized rendering for efficient display, and integrates with physics for physical simulation.", "canonical_tags": [ "Gem" ], - "user_tags": [ "Environment", "Terrain" ], - "icon_path": "preview.png" + "user_tags": [ "Environment", "Tools", "Design", "Terrain" ], + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/terrain/" } diff --git a/Gems/Terrain/preview.png b/Gems/Terrain/preview.png deleted file mode 100644 index 2f1ed47754..0000000000 --- a/Gems/Terrain/preview.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6d6204c6730e5675791765ca194e9b1cbec282208e280507de830afc2805e5fa -size 41127 From 9752fb009af5008d65a11d39370219c46b768ea1 Mon Sep 17 00:00:00 2001 From: AMZN-AlexOteiza <82234181+AMZN-AlexOteiza@users.noreply.github.com> Date: Tue, 31 Aug 2021 09:25:03 +0100 Subject: [PATCH 794/803] Added pdbs for python windows in order to allow python/c++ debugging on VS (#3661) * Added pdbs for python windows in order to allow python/c++ debugging on VS Signed-off-by: Garcia Ruiz * Modified other places where rev1 was used Signed-off-by: Garcia Ruiz Co-authored-by: Garcia Ruiz --- Gems/AWSClientAuth/cdk/README.md | 2 +- .../DccScriptingInterface/Launchers/Windows/Env_PyCharm.bat | 2 +- .../DccScriptingInterface/Launchers/Windows/Env_Python.bat | 2 +- .../DccScriptingInterface/Launchers/Windows/Env_WingIDE.bat | 2 +- .../Launchers/Windows/Launch_MayaPy_PyCharmPro.bat | 2 +- .../DccScriptingInterface/Launchers/Windows/Launch_VScode.bat | 2 +- .../Launchers/Windows/Launch_WingIDE-7-1.bat | 2 +- .../Launchers/Windows/Launch_mayapy_WingIDE-7-1.bat | 2 +- .../Launchers/Windows/Setuo_copy_oiio.bat | 2 +- cmake/LYPython.cmake | 4 ++-- python/python.cmd | 2 +- python/python.sh | 2 +- 12 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Gems/AWSClientAuth/cdk/README.md b/Gems/AWSClientAuth/cdk/README.md index 3bc2b59fc1..d0cc966578 100644 --- a/Gems/AWSClientAuth/cdk/README.md +++ b/Gems/AWSClientAuth/cdk/README.md @@ -13,7 +13,7 @@ Run from cdk directory within gem. Optional set up python path to LY Python ``` -set PATH="..\..\..\python\runtime\python-3.7.10-rev1-windows\python\";%PATH% +set PATH="..\..\..\python\runtime\python-3.7.10-rev2-windows\python\";%PATH% ``` This project is set up like a standard Python project. Use python interpreter from Open3d to setup python dependencies diff --git a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/Launchers/Windows/Env_PyCharm.bat b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/Launchers/Windows/Env_PyCharm.bat index 296245d171..67f2c3d81e 100644 --- a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/Launchers/Windows/Env_PyCharm.bat +++ b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/Launchers/Windows/Env_PyCharm.bat @@ -34,7 +34,7 @@ CALL %~dp0\Env_Python.bat CALL %~dp0\Env_Qt.bat :: Wing and other IDEs probably prefer access directly to the python.exe -set DCCSI_PY_IDE = %DCCSI_PYTHON_INSTALL%\runtime\python-3.7.10-rev1-windows\python +set DCCSI_PY_IDE = %DCCSI_PYTHON_INSTALL%\runtime\python-3.7.10-rev2-windows\python echo DCCSI_PY_IDE = %DCCSI_PY_IDE% :: ide and debugger plug diff --git a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/Launchers/Windows/Env_Python.bat b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/Launchers/Windows/Env_Python.bat index 7492811a1d..196d7b09bb 100644 --- a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/Launchers/Windows/Env_Python.bat +++ b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/Launchers/Windows/Env_Python.bat @@ -67,7 +67,7 @@ echo DCCSI_PY_BASE = %DCCSI_PY_BASE% set DCCSI_PY_DEFAULT=%DCCSI_PY_BASE% :: Wing and other IDEs probably prefer access directly to the python.exe -set DCCSI_PY_IDE=%DCCSI_PYTHON_INSTALL%\runtime\python-3.7.10-rev1-windows\python +set DCCSI_PY_IDE=%DCCSI_PYTHON_INSTALL%\runtime\python-3.7.10-rev2-windows\python echo DCCSI_PY_IDE = %DCCSI_PY_IDE% set DCCSI_PY_IDE_PACKAGES=%DCCSI_PY_IDE%\Lib\site-packages diff --git a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/Launchers/Windows/Env_WingIDE.bat b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/Launchers/Windows/Env_WingIDE.bat index 2532acce1f..56209ca5aa 100644 --- a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/Launchers/Windows/Env_WingIDE.bat +++ b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/Launchers/Windows/Env_WingIDE.bat @@ -28,7 +28,7 @@ CALL %~dp0\Env_Python.bat CALL %~dp0\Env_Qt.bat :: Wing and other IDEs probably prefer access directly to the python.exe -set DCCSI_PY_IDE = %DCCSI_PYTHON_INSTALL%\runtime\python-3.7.10-rev1-windows\python +set DCCSI_PY_IDE = %DCCSI_PYTHON_INSTALL%\runtime\python-3.7.10-rev2-windows\python echo DCCSI_PY_IDE = %DCCSI_PY_IDE% :: ide and debugger plug diff --git a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/Launchers/Windows/Launch_MayaPy_PyCharmPro.bat b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/Launchers/Windows/Launch_MayaPy_PyCharmPro.bat index bbccbba304..d98b8d81e7 100644 --- a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/Launchers/Windows/Launch_MayaPy_PyCharmPro.bat +++ b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/Launchers/Windows/Launch_MayaPy_PyCharmPro.bat @@ -63,7 +63,7 @@ set DCCSI_PYTHON_INSTALL=%LY_DEV%\Python echo DCCSI_PYTHON_INSTALL = %DCCSI_PYTHON_INSTALL% :: Wing and other IDEs probably prefer access directly to the python.exe -set DCCSI_PY_IDE = %DCCSI_PYTHON_INSTALL%\runtime\python-3.7.10-rev1-windows\python +set DCCSI_PY_IDE = %DCCSI_PYTHON_INSTALL%\runtime\python-3.7.10-rev2-windows\python echo DCCSI_PY_IDE = %DCCSI_PY_IDE% :: ide and debugger plug diff --git a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/Launchers/Windows/Launch_VScode.bat b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/Launchers/Windows/Launch_VScode.bat index 46b32f4fb0..120584ed6a 100644 --- a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/Launchers/Windows/Launch_VScode.bat +++ b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/Launchers/Windows/Launch_VScode.bat @@ -68,7 +68,7 @@ set DCCSI_PYTHON_INSTALL=%LY_DEV%\Python echo DCCSI_PYTHON_INSTALL = %DCCSI_PYTHON_INSTALL% :: Wing and other IDEs probably prefer access directly to the python.exe -set DCCSI_PY_IDE = %DCCSI_PYTHON_INSTALL%\runtime\python-3.7.10-rev1-windows\python +set DCCSI_PY_IDE = %DCCSI_PYTHON_INSTALL%\runtime\python-3.7.10-rev2-windows\python echo DCCSI_PY_IDE = %DCCSI_PY_IDE% :: ide and debugger plug diff --git a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/Launchers/Windows/Launch_WingIDE-7-1.bat b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/Launchers/Windows/Launch_WingIDE-7-1.bat index aa3ca76a72..c933670bab 100644 --- a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/Launchers/Windows/Launch_WingIDE-7-1.bat +++ b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/Launchers/Windows/Launch_WingIDE-7-1.bat @@ -62,7 +62,7 @@ set DCCSI_PYTHON_INSTALL=%LY_DEV%\Python echo DCCSI_PYTHON_INSTALL = %DCCSI_PYTHON_INSTALL% :: Wing and other IDEs probably prefer access directly to the python.exe -set DCCSI_PY_IDE = %DCCSI_PYTHON_INSTALL%\runtime\python-3.7.10-rev1-windows\python +set DCCSI_PY_IDE = %DCCSI_PYTHON_INSTALL%\runtime\python-3.7.10-rev2-windows\python echo DCCSI_PY_IDE = %DCCSI_PY_IDE% :: ide and debugger plug diff --git a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/Launchers/Windows/Launch_mayapy_WingIDE-7-1.bat b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/Launchers/Windows/Launch_mayapy_WingIDE-7-1.bat index f223d68ebb..631250d06b 100644 --- a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/Launchers/Windows/Launch_mayapy_WingIDE-7-1.bat +++ b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/Launchers/Windows/Launch_mayapy_WingIDE-7-1.bat @@ -62,7 +62,7 @@ set DCCSI_PYTHON_INSTALL=%LY_DEV%\Python echo DCCSI_PYTHON_INSTALL = %DCCSI_PYTHON_INSTALL% :: Wing and other IDEs probably prefer access directly to the python.exe -set DCCSI_PY_IDE = %DCCSI_PYTHON_INSTALL%\runtime\python-3.7.10-rev1-windows\python +set DCCSI_PY_IDE = %DCCSI_PYTHON_INSTALL%\runtime\python-3.7.10-rev2-windows\python echo DCCSI_PY_IDE = %DCCSI_PY_IDE% :: ide and debugger plug diff --git a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/Launchers/Windows/Setuo_copy_oiio.bat b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/Launchers/Windows/Setuo_copy_oiio.bat index 1a43e624c9..590e634d54 100644 --- a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/Launchers/Windows/Setuo_copy_oiio.bat +++ b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/Launchers/Windows/Setuo_copy_oiio.bat @@ -18,7 +18,7 @@ set LY_DEV=..\..\..\..\..\.. :: shared location for default O3DE python location set DCCSI_PYTHON_INSTALL=%LY_DEV%\Python -set PY_SITE=%DCCSI_PYTHON_INSTALL%\runtime\python-3.7.10-rev1-windows\python\Lib\site-packages +set PY_SITE=%DCCSI_PYTHON_INSTALL%\runtime\python-3.7.10-rev2-windows\python\Lib\site-packages set PACKAGE_LOC=C:\Depot\3rdParty\packages\openimageio-2.1.16.0-rev1-windows\OpenImageIO\2.1.16.0\win_x64\bin diff --git a/cmake/LYPython.cmake b/cmake/LYPython.cmake index 21e220f1d8..eeb9f97a55 100644 --- a/cmake/LYPython.cmake +++ b/cmake/LYPython.cmake @@ -29,8 +29,8 @@ elseif (${CMAKE_HOST_SYSTEM_NAME} STREQUAL "Darwin" ) ly_set(LY_PYTHON_PACKAGE_HASH 3f65801894e4e44b5faa84dd85ef80ecd772dcf728cdd2d668a6e75978a32695) elseif (${CMAKE_HOST_SYSTEM_NAME} STREQUAL "Windows" ) ly_set(LY_PYTHON_VERSION 3.7.10) - ly_set(LY_PYTHON_PACKAGE_NAME python-3.7.10-rev1-windows) - ly_set(LY_PYTHON_PACKAGE_HASH 851383addea5c54b7c6398860d04606c1053f1157c2edd801ec3d47394f73136) + ly_set(LY_PYTHON_PACKAGE_NAME python-3.7.10-rev2-windows) + ly_set(LY_PYTHON_PACKAGE_HASH 06d97488a2dbabe832ecfa832a42d3e8a7163ba95e975f032727331b0f49d280) endif() # settings and globals diff --git a/python/python.cmd b/python/python.cmd index 04c55c50c7..70c79e6789 100644 --- a/python/python.cmd +++ b/python/python.cmd @@ -17,7 +17,7 @@ SETLOCAL SET CMD_DIR=%~dp0 SET CMD_DIR=%CMD_DIR:~0,-1% -SET PYTHONHOME=%CMD_DIR%\runtime\python-3.7.10-rev1-windows\python +SET PYTHONHOME=%CMD_DIR%\runtime\python-3.7.10-rev2-windows\python IF EXIST "%PYTHONHOME%" GOTO PYTHONHOME_EXISTS diff --git a/python/python.sh b/python/python.sh index 590845dbd5..642878485b 100755 --- a/python/python.sh +++ b/python/python.sh @@ -19,7 +19,7 @@ DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" if [[ "$OSTYPE" == *"darwin"* ]]; then PYTHON=$DIR/runtime/python-3.7.10-rev1-darwin/Python.framework/Versions/3.7/bin/python3 elif [[ "$OSTYPE" == "msys" ]]; then - PYTHON=$DIR/runtime/python-3.7.10-rev1-windows/python/python.exe + PYTHON=$DIR/runtime/python-3.7.10-rev2-windows/python/python.exe else PYTHON=$DIR/runtime/python-3.7.10-rev2-linux/python/bin/python fi From d784ff8c57cefff7efd2b6bda71a053b5efda867 Mon Sep 17 00:00:00 2001 From: AMZN-AlexOteiza <82234181+AMZN-AlexOteiza@users.noreply.github.com> Date: Tue, 31 Aug 2021 09:27:14 +0100 Subject: [PATCH 795/803] Added debugger attachment utilities to the engine, fixed crash when showing console variables, improvements to timeout handling and small cleanup (#3591) * Added debugger attachment utilities to the engine, fixed crash when showing console variables Signed-off-by: Garcia Ruiz * Removed unused variables Signed-off-by: Garcia Ruiz * Removed unneded check Signed-off-by: Garcia Ruiz * Small fix for crashes/timeouts Signed-off-by: Garcia Ruiz * Removed unused variable, fixed compile error Signed-off-by: Garcia Ruiz * Fix compile Signed-off-by: Garcia Ruiz * Addressed esteban comments * Addressed tom comments Co-authored-by: Garcia Ruiz --- Code/Editor/Controls/ConsoleSCB.cpp | 4 + Code/Editor/CryEdit.cpp | 19 ++- Code/Editor/CryEditPy.cpp | 13 ++ Code/Framework/AzCore/AzCore/Debug/Trace.cpp | 36 ++++++ Code/Framework/AzCore/AzCore/Debug/Trace.h | 2 + .../Common/Apple/AzCore/Debug/Trace_Apple.cpp | 7 + .../UnixLike/AzCore/Debug/Trace_UnixLike.cpp | 7 + .../WinAPI/AzCore/Debug/Trace_WinAPI.cpp | 39 ++++++ .../ly_test_tools/o3de/editor_test.py | 121 ++++++++++++------ 9 files changed, 210 insertions(+), 38 deletions(-) diff --git a/Code/Editor/Controls/ConsoleSCB.cpp b/Code/Editor/Controls/ConsoleSCB.cpp index aed148976f..6b12348880 100644 --- a/Code/Editor/Controls/ConsoleSCB.cpp +++ b/Code/Editor/Controls/ConsoleSCB.cpp @@ -573,6 +573,10 @@ static CVarBlock* VarBlockFromConsoleVars() IVariable* pVariable = nullptr; for (int i = 0; i < cmdCount; i++) { + if (!cmds[i].data()) + { + continue; + } ICVar* pCVar = console->GetCVar(cmds[i].data()); if (!pCVar) { diff --git a/Code/Editor/CryEdit.cpp b/Code/Editor/CryEdit.cpp index ca139cc506..fe7b0a06be 100644 --- a/Code/Editor/CryEdit.cpp +++ b/Code/Editor/CryEdit.cpp @@ -551,7 +551,9 @@ public: { "NSDocumentRevisionsDebugMode", nsDocumentRevisionsDebugMode}, { "skipWelcomeScreenDialog", m_bSkipWelcomeScreenDialog}, { "autotest_mode", m_bAutotestMode}, - { "regdumpall", dummy } + { "regdumpall", dummy }, + { "attach-debugger", dummy }, // Attaches a debugger for the current application + { "wait-for-debugger", dummy }, // Waits until a debugger is attached to the current application }; QString dummyString; @@ -2290,7 +2292,7 @@ int CCryEditApp::IdleProcessing(bool bBackgroundUpdate) int res = 0; if (bIsAppWindow || m_bForceProcessIdle || m_bKeepEditorActive // Automated tests must always keep the editor active, or they can get stuck - || m_bAutotestMode) + || m_bAutotestMode || m_bRunPythonTestScript) { res = 1; bActive = true; @@ -4011,6 +4013,19 @@ extern "C" int AZ_DLL_EXPORT CryEditMain(int argc, char* argv[]) { CryAllocatorsRAII cryAllocatorsRAII; + // Debugging utilities + for (int i = 1; i < argc; ++i) + { + if (azstricmp(argv[i], "--attach-debugger") == 0) + { + AZ::Debug::Trace::AttachDebugger(); + } + else if (azstricmp(argv[i], "--wait-for-debugger") == 0) + { + AZ::Debug::Trace::WaitForDebugger(); + } + } + // ensure the EditorEventsBus context gets created inside EditorLib [[maybe_unused]] const auto& editorEventsContext = AzToolsFramework::EditorEvents::Bus::GetOrCreateContext(); diff --git a/Code/Editor/CryEditPy.cpp b/Code/Editor/CryEditPy.cpp index 10fd56c134..7a407aac37 100644 --- a/Code/Editor/CryEditPy.cpp +++ b/Code/Editor/CryEditPy.cpp @@ -401,6 +401,16 @@ inline namespace Commands { return static_cast(GetIEditor()->GetEditorConfigPlatform()); } + + bool PyAttachDebugger() + { + return AZ::Debug::Trace::AttachDebugger(); + } + + bool PyWaitForDebugger(float timeoutSeconds = -1.f) + { + return AZ::Debug::Trace::WaitForDebugger(timeoutSeconds); + } } namespace AzToolsFramework @@ -448,6 +458,9 @@ namespace AzToolsFramework addLegacyGeneral(behaviorContext->Method("start_process_detached", PyStartProcessDetached, nullptr, "Launches a detached process with an optional space separated list of arguments.")); addLegacyGeneral(behaviorContext->Method("launch_lua_editor", PyLaunchLUAEditor, nullptr, "Launches the Lua editor, may receive a list of space separate file paths, or an empty string to only open the editor.")); + addLegacyGeneral(behaviorContext->Method("attach_debugger", PyAttachDebugger, nullptr, "Prompts for attaching the debugger")); + addLegacyGeneral(behaviorContext->Method("wait_for_debugger", PyWaitForDebugger, behaviorContext->MakeDefaultValues(-1.f), "Pauses this thread execution until the debugger has been attached")); + // this will put these methods into the 'azlmbr.legacy.checkout_dialog' module auto addCheckoutDialog = [](AZ::BehaviorContext::GlobalMethodBuilder methodBuilder) { diff --git a/Code/Framework/AzCore/AzCore/Debug/Trace.cpp b/Code/Framework/AzCore/AzCore/Debug/Trace.cpp index 74ecee40e5..26c702c13a 100644 --- a/Code/Framework/AzCore/AzCore/Debug/Trace.cpp +++ b/Code/Framework/AzCore/AzCore/Debug/Trace.cpp @@ -25,6 +25,7 @@ #include #include #include +#include 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,40 @@ 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(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(); +#endif + } + //========================================================================= // HandleExceptions // [8/3/2009] diff --git a/Code/Framework/AzCore/AzCore/Debug/Trace.h b/Code/Framework/AzCore/AzCore/Debug/Trace.h index bae074281c..b00a1cd921 100644 --- a/Code/Framework/AzCore/AzCore/Debug/Trace.h +++ b/Code/Framework/AzCore/AzCore/Debug/Trace.h @@ -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); diff --git a/Code/Framework/AzCore/Platform/Common/Apple/AzCore/Debug/Trace_Apple.cpp b/Code/Framework/AzCore/Platform/Common/Apple/AzCore/Debug/Trace_Apple.cpp index 4ae25bfaf9..f9d4806bcb 100644 --- a/Code/Framework/AzCore/Platform/Common/Apple/AzCore/Debug/Trace_Apple.cpp +++ b/Code/Framework/AzCore/Platform/Common/Apple/AzCore/Debug/Trace_Apple.cpp @@ -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) {} diff --git a/Code/Framework/AzCore/Platform/Common/UnixLike/AzCore/Debug/Trace_UnixLike.cpp b/Code/Framework/AzCore/Platform/Common/UnixLike/AzCore/Debug/Trace_UnixLike.cpp index 545a712df8..e9c0234ffa 100644 --- a/Code/Framework/AzCore/Platform/Common/UnixLike/AzCore/Debug/Trace_UnixLike.cpp +++ b/Code/Framework/AzCore/Platform/Common/UnixLike/AzCore/Debug/Trace_UnixLike.cpp @@ -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) {} diff --git a/Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/Debug/Trace_WinAPI.cpp b/Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/Debug/Trace_WinAPI.cpp index 02c1988215..28d3459ba3 100644 --- a/Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/Debug/Trace_WinAPI.cpp +++ b/Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/Debug/Trace_WinAPI.cpp @@ -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(); diff --git a/Tools/LyTestTools/ly_test_tools/o3de/editor_test.py b/Tools/LyTestTools/ly_test_tools/o3de/editor_test.py index 4e15f32b37..781977cf33 100644 --- a/Tools/LyTestTools/ly_test_tools/o3de/editor_test.py +++ b/Tools/LyTestTools/ly_test_tools/o3de/editor_test.py @@ -59,6 +59,11 @@ class EditorTestBase(ABC): timeout = 180 # Test file that this test will run test_module = None + # Attach debugger when running the test, useful for debugging crashes. This should never be True on production. + # It's also recommended to switch to EditorSingleTest for debugging in isolation + attach_debugger = False + # Wait until a debugger is attached at the startup of the test, this is another way of debugging. + wait_for_debugger = False # Test that will be run alone in one editor class EditorSingleTest(EditorTestBase): @@ -117,8 +122,9 @@ class Result: class Pass(Base): @classmethod - def create(cls, output : str, editor_log : str): + def create(cls, test_spec : EditorTestBase, output : str, editor_log : str): r = cls() + r.test_spec = test_spec r.output = output r.editor_log = editor_log return r @@ -135,8 +141,9 @@ class Result: class Fail(Base): @classmethod - def create(cls, output, editor_log : str): + def create(cls, test_spec : EditorTestBase, output, editor_log : str): r = cls() + r.test_spec = test_spec r.output = output r.editor_log = editor_log return r @@ -157,9 +164,10 @@ class Result: class Crash(Base): @classmethod - def create(cls, output : str, ret_code : int, stacktrace : str, editor_log : str): + def create(cls, test_spec : EditorTestBase, output : str, ret_code : int, stacktrace : str, editor_log : str): r = cls() r.output = output + r.test_spec = test_spec r.ret_code = ret_code r.stacktrace = stacktrace r.editor_log = editor_log @@ -187,9 +195,10 @@ class Result: class Timeout(Base): @classmethod - def create(cls, output : str, time_secs : float, editor_log : str): + def create(cls, test_spec : EditorTestBase, output : str, time_secs : float, editor_log : str): r = cls() r.output = output + r.test_spec = test_spec r.time_secs = time_secs r.editor_log = editor_log return r @@ -210,9 +219,10 @@ class Result: class Unknown(Base): @classmethod - def create(cls, output : str, extra_info : str, editor_log : str): + def create(cls, test_spec : EditorTestBase, output : str, extra_info : str, editor_log : str): r = cls() r.output = output + r.test_spec = test_spec r.editor_log = editor_log r.extra_info = extra_info return r @@ -255,7 +265,7 @@ class EditorTestSuite(): def editor_test_data(self, request): class TestData(): def __init__(self): - self.results = {} + self.results = {} # Dict of str(test_spec.__name__) -> Result self.asset_processor = None test_data = TestData() @@ -548,7 +558,7 @@ class EditorTestSuite(): for test_spec in test_spec_list: name = editor_utils.get_module_filename(test_spec.test_module) if name not in found_jsons.keys(): - results[test_spec.__name__] = Result.Unknown.create(output, "Couldn't find any test run information on stdout", editor_log_content) + results[test_spec.__name__] = Result.Unknown.create(test_spec, output, "Couldn't find any test run information on stdout", editor_log_content) else: result = None json_result = found_jsons[name] @@ -564,9 +574,9 @@ class EditorTestSuite(): log_start = end if json_result["success"]: - result = Result.Pass.create(json_output, cur_log) + result = Result.Pass.create(test_spec, json_output, cur_log) else: - result = Result.Fail.create(json_output, cur_log) + result = Result.Fail.create(test_spec, json_output, cur_log) results[test_spec.__name__] = result return results @@ -587,8 +597,13 @@ class EditorTestSuite(): test_spec : EditorTestBase, cmdline_args : List[str] = []): test_cmdline_args = self.global_extra_cmdline_args + cmdline_args - if test_spec.use_null_renderer or (test_spec.use_null_renderer is None and self.use_null_renderer): + test_spec_uses_null_renderer = getattr(test_spec, "use_null_renderer", None) + if test_spec_uses_null_renderer or (test_spec_uses_null_renderer is None and self.use_null_renderer): test_cmdline_args += ["-rhi=null"] + if test_spec.attach_debugger: + test_cmdline_args += ["--attach-debugger"] + if test_spec.wait_for_debugger: + test_cmdline_args += ["--wait-for-debugger"] # Cycle any old crash report in case it wasn't cycled properly editor_utils.cycle_crash_report(run_id, workspace) @@ -610,18 +625,18 @@ class EditorTestSuite(): editor_log_content = editor_utils.retrieve_editor_log_content(run_id, log_name, workspace) if return_code == 0: - test_result = Result.Pass.create(output, editor_log_content) + test_result = Result.Pass.create(test_spec, output, editor_log_content) else: has_crashed = return_code != EditorTestSuite._TEST_FAIL_RETCODE if has_crashed: - test_result = Result.Crash.create(output, return_code, editor_utils.retrieve_crash_output(run_id, workspace, self._TIMEOUT_CRASH_LOG), None) + test_result = Result.Crash.create(test_spec, output, return_code, editor_utils.retrieve_crash_output(run_id, workspace, self._TIMEOUT_CRASH_LOG), None) editor_utils.cycle_crash_report(run_id, workspace) else: - test_result = Result.Fail.create(output, editor_log_content) + test_result = Result.Fail.create(test_spec, output, editor_log_content) except WaitTimeoutError: editor.kill() editor_log_content = editor_utils.retrieve_editor_log_content(run_id, log_name, workspace) - test_result = Result.Timeout.create(output, test_spec.timeout, editor_log_content) + test_result = Result.Timeout.create(test_spec, output, test_spec.timeout, editor_log_content) editor_log_content = editor_utils.retrieve_editor_log_content(run_id, log_name, workspace) results = self._get_results_using_output([test_spec], output, editor_log_content) @@ -629,13 +644,17 @@ class EditorTestSuite(): return results # Starts an editor executable with a list of tests and returns a dict of the result of every test ran within that editor - # instance. In case of failure this function also parses the editor output to find out what specific tests that failed + # instance. In case of failure this function also parses the editor output to find out what specific tests failed def _exec_editor_multitest(self, request, workspace, editor, run_id : int, log_name : str, test_spec_list : List[EditorTestBase], cmdline_args=[]): test_cmdline_args = self.global_extra_cmdline_args + cmdline_args if self.use_null_renderer: test_cmdline_args += ["-rhi=null"] + if any([t.attach_debugger for t in test_spec_list]): + test_cmdline_args += ["--attach-debugger"] + if any([t.wait_for_debugger for t in test_spec_list]): + test_cmdline_args += ["--wait-for-debugger"] # Cycle any old crash report in case it wasn't cycled properly editor_utils.cycle_crash_report(run_id, workspace) @@ -661,35 +680,65 @@ class EditorTestSuite(): if return_code == 0: # No need to scrap the output, as all the tests have passed for test_spec in test_spec_list: - results[test_spec.__name__] = Result.Pass.create(output, editor_log_content) + results[test_spec.__name__] = Result.Pass.create(test_spec, output, editor_log_content) else: + # Scrap the output to attempt to find out which tests failed. + # This function should always populate the result list, if it didn't find it, it will have "Unknown" type of result results = self._get_results_using_output(test_spec_list, output, editor_log_content) + assert len(results) == len(test_spec_list), "bug in _get_results_using_output(), the number of results don't match the tests ran" + + # If the editor crashed, find out in which test it happened and update the results has_crashed = return_code != EditorTestSuite._TEST_FAIL_RETCODE if has_crashed: - crashed_test = None - for key, result in results.items(): + crashed_result = None + for test_spec_name, result in results.items(): if isinstance(result, Result.Unknown): - if not crashed_test: + if not crashed_result: + # The first test with "Unknown" result (no data in output) is likely the one that crashed crash_error = editor_utils.retrieve_crash_output(run_id, workspace, self._TIMEOUT_CRASH_LOG) editor_utils.cycle_crash_report(run_id, workspace) - results[key] = Result.Crash.create(output, return_code, crash_error, result.editor_log) - crashed_test = results[key] + results[test_spec_name] = Result.Crash.create(result.test_spec, output, return_code, crash_error, result.editor_log) + crashed_result = result else: - results[key] = Result.Unknown.create(output, f"This test has unknown result, test '{crashed_test.__name__}' crashed before this test could be executed", result.editor_log) + # If there are remaning "Unknown" results, these couldn't execute because of the crash, update with info about the offender + results[test_spec_name].extra_info = f"This test has unknown result, test '{crashed_result.test_spec.__name__}' crashed before this test could be executed" - except WaitTimeoutError: - results = self._get_results_using_output(test_spec_list, output, editor_log_content) - editor_log_content = editor_utils.retrieve_editor_log_content(run_id, log_name, workspace) + # if all the tests ran, the one that has caused the crash is the last test + if not crashed_result: + crash_error = editor_utils.retrieve_crash_output(run_id, workspace, self._TIMEOUT_CRASH_LOG) + editor_utils.cycle_crash_report(run_id, workspace) + results[test_spec_name] = Result.Crash.create(crashed_result.test_spec, output, return_code, crash_error, crashed_result.editor_log) + + + except WaitTimeoutError: editor.kill() - for key, result in results.items(): + + output = editor.get_output() + editor_log_content = editor_utils.retrieve_editor_log_content(run_id, log_name, workspace) + + # The editor timed out when running the tests, get the data from the output to find out which ones ran + results = self._get_results_using_output(test_spec_list, output, editor_log_content) + assert len(results) == len(test_spec_list), "bug in _get_results_using_output(), the number of results don't match the tests ran" + + # Similar logic here as crashes, the first test that has no result is the one that timed out + timed_out_result = None + for test_spec_name, result in results.items(): if isinstance(result, Result.Unknown): - results[key] = Result.Timeout.create(result.output, total_timeout, result.editor_log) - # FIX-ME + if not timed_out_result: + results[test_spec_name] = Result.Timeout.create(result.test_spec, result.output, self.timeout_editor_shared_test, result.editor_log) + timed_out_result = result + else: + # If there are remaning "Unknown" results, these couldn't execute because of the timeout, update with info about the offender + results[test_spec_name].extra_info = f"This test has unknown result, test '{timed_out_result.test_spec.__name__}' timed out before this test could be executed" + + # if all the tests ran, the one that has caused the timeout is the last test, as it didn't close the editor + if not timed_out_result: + results[test_spec_name] = Result.Timeout.create(timed_out_result.test_spec, results[test_spec_name].output, self.timeout_editor_shared_test, result.editor_log) return results - # Runs a single test with the given specs, used by the collector to register the test - def _run_single_test(self, request, workspace, editor, editor_test_data, test_spec : EditorTestBase): + # Runs a single test (one editor, one test) with the given specs + def _run_single_test(self, request, workspace, editor, editor_test_data, test_spec : EditorSingleTest): self._setup_editor_test(editor, workspace, editor_test_data) extra_cmdline_args = [] if hasattr(test_spec, "extra_cmdline_args"): @@ -700,8 +749,8 @@ class EditorTestSuite(): test_name, test_result = next(iter(results.items())) self._report_result(test_name, test_result) - # Runs a batch of tests in one single editor with the given spec list - def _run_batched_tests(self, request, workspace, editor, editor_test_data, test_spec_list : List[EditorTestBase], extra_cmdline_args=[]): + # Runs a batch of tests in one single editor with the given spec list (one editor, multiple tests) + def _run_batched_tests(self, request, workspace, editor, editor_test_data, test_spec_list : List[EditorSharedTest], extra_cmdline_args=[]): if not test_spec_list: return @@ -710,8 +759,8 @@ class EditorTestSuite(): assert results is not None editor_test_data.results.update(results) - # Runs multiple editors with one test on each editor - def _run_parallel_tests(self, request, workspace, editor, editor_test_data, test_spec_list : List[EditorTestBase], extra_cmdline_args=[]): + # Runs multiple editors with one test on each editor (multiple editor, one test each) + def _run_parallel_tests(self, request, workspace, editor, editor_test_data, test_spec_list : List[EditorSharedTest], extra_cmdline_args=[]): if not test_spec_list: return @@ -747,8 +796,8 @@ class EditorTestSuite(): for result in results_per_thread: editor_test_data.results.update(result) - # Runs multiple editors with a batch of tests for each editor - def _run_parallel_batched_tests(self, request, workspace, editor, editor_test_data, test_spec_list : List[EditorTestBase], extra_cmdline_args=[]): + # Runs multiple editors with a batch of tests for each editor (multiple editor, multiple tests each) + def _run_parallel_batched_tests(self, request, workspace, editor, editor_test_data, test_spec_list : List[EditorSharedTest], extra_cmdline_args=[]): if not test_spec_list: return From 77e630085b190ed1182f7b00c965a723a625ca71 Mon Sep 17 00:00:00 2001 From: AMZN-AlexOteiza <82234181+AMZN-AlexOteiza@users.noreply.github.com> Date: Tue, 31 Aug 2021 10:04:24 +0100 Subject: [PATCH 796/803] Overhaul physics test organization (#3684) * Moved files Signed-off-by: Garcia Ruiz * Fixes for moved files Signed-off-by: Garcia Ruiz * Removed tmp file Signed-off-by: Garcia Ruiz Co-authored-by: Garcia Ruiz --- .../editor_python_test_tools/asset_utils.py | 47 +++++ .../PythonTests/physics/ImportPathHelper.py | 11 -- .../physics/TestSuite_InDevelopment.py | 96 +++++----- .../Gem/PythonTests/physics/TestSuite_Main.py | 26 +-- .../physics/TestSuite_Main_Optimized.py | 177 +++++++++-------- .../PythonTests/physics/TestSuite_Periodic.py | 178 +++++++++--------- .../PythonTests/physics/TestSuite_Sandbox.py | 8 +- .../PythonTests/physics/TestSuite_Utils.py | 6 +- ...654881_CharacterController_SwitchLevels.py | 8 - ...00000_RigidBody_EnablingGravityWorksPoC.py | 8 - ...ablingGravityWorksUsingNotificationsPoC.py | 8 - .../C14861498_ConfirmError_NoPxMesh.py | 8 - .../C14861500_DefaultSetting_ColliderShape.py | 5 - ...01_PhysXCollider_RenderMeshAutoAssigned.py | 7 +- ...4861502_PhysXCollider_AssetAutoAssigned.py | 7 +- ...C14861504_RenderMeshAsset_WithNoPxAsset.py | 9 +- ...78018_ShapeColliderWithNoShapeComponent.py | 5 - .../C19578021_ShapeCollider_CanBeAdded.py | 5 - ...19723164_ShapeColliders_WontCrashEditor.py | 5 - ...rShapeCollider_CollidesWithPhysXTerrain.py | 5 - .../C3510644_Collider_CollisionGroups.py | 8 - ...695_PhysXCollider_AddMultipleSurfaceFbx.py | 7 +- .../C4976227_Collider_NewGroup.py | 8 - .../C4976236_AddPhysxColliderComponent.py | 7 +- ...on_SameCollisionlayerSameCollisiongroup.py | 8 - ...n_SameCollisionGroupDiffCollisionLayers.py | 8 - ...44_Collider_SameGroupSameLayerCollision.py | 8 - ...976245_PhysXCollider_CollisionLayerTest.py | 8 - ...982593_PhysXCollider_CollisionLayerTest.py | 8 - ...82595_Collider_TriggerDisablesCollision.py | 8 - .../C4982797_Collider_ColliderOffset.py | 5 - ...4982798_Collider_ColliderRotationOffset.py | 5 - ...982800_PhysXColliderShape_CanBeSelected.py | 5 - ...982801_PhysXColliderShape_CanBeSelected.py | 5 - ...982802_PhysXColliderShape_CanBeSelected.py | 5 - .../C4982803_Enable_PxMesh_Option.py | 7 +- ...eRegion_DirectionHasNoAffectOnMagnitude.py | 8 - ...580_ForceRegion_SplineModifiedTransform.py | 9 - ...12905527_ForceRegion_MagnitudeDeviation.py | 9 - ...5528_ForceRegion_WithNonTriggerCollider.py | 15 +- ...5879_ForceRegion_HighLinearDampingForce.py | 8 - ...932040_ForceRegion_CubeExertsWorldForce.py | 8 - ...orceRegion_LocalSpaceForceOnRigidBodies.py | 8 - ...C5932042_PhysXForceRegion_LinearDamping.py | 8 - ...043_ForceRegion_SimpleDragOnRigidBodies.py | 5 - ...32044_ForceRegion_PointForceOnRigidBody.py | 8 - .../C5932045_ForceRegion_Spline.py | 8 - ...9_RigidBody_ForceRegionSpherePointForce.py | 8 - ...760_PhysXForceRegion_PointForceExertion.py | 8 - ...1_ForceRegion_PhysAssetExertsPointForce.py | 9 - ...763_ForceRegion_ForceRegionImpulsesCube.py | 5 - ..._ForceRegion_ForceRegionImpulsesCapsule.py | 5 - .../C5959765_ForceRegion_AssetGetsImpulsed.py | 5 - .../C5959808_ForceRegion_PositionOffset.py | 8 - .../C5959809_ForceRegion_RotationalOffset.py | 8 - ...0_ForceRegion_ForceRegionCombinesForces.py | 8 - ...ceRegion_ExertsSeveralForcesOnRigidBody.py | 5 - ...5968760_ForceRegion_CheckNetForceChange.py | 8 - ...90546_ForceRegion_SliceFileInstantiates.py | 8 - ...547_ForceRegion_ParentChildForceRegions.py | 8 - ...550_ForceRegion_WorldSpaceForceNegative.py | 8 - ...551_ForceRegion_LocalSpaceForceNegative.py | 8 - ...90552_ForceRegion_LinearDampingNegative.py | 8 - ...orceRegion_SimpleDragForceOnRigidBodies.py | 8 - ...C6090554_ForceRegion_PointForceNegative.py | 8 - ...5_ForceRegion_SplineFollowOnRigidBodies.py | 8 - .../C6321601_Force_HighValuesDirectionAxes.py | 9 - .../C14976307_Gravity_SetGravityWorks.py | 8 - .../{ => general}/C15425929_Undo_Redo.py | 8 - .../C19536274_GetCollisionName_PrintsName.py | 7 +- ...19536277_GetCollisionName_PrintsNothing.py | 7 +- ...2500_EditorComponents_WorldBodyBusWorks.py | 8 - ..._Verify_Terrain_RigidBody_Collider_Mesh.py | 8 - ...6131473_StaticSlice_OnDynamicSliceSpawn.py | 8 - ...18243580_Joints_Fixed2BodiesConstrained.py | 8 - .../C18243581_Joints_FixedBreakable.py | 8 - ...8243582_Joints_FixedLeadFollowerCollide.py | 8 - ...18243583_Joints_Hinge2BodiesConstrained.py | 8 - ...43584_Joints_HingeSoftLimitsConstrained.py | 5 - ...8243585_Joints_HingeNoLimitsConstrained.py | 8 - ...8243586_Joints_HingeLeadFollowerCollide.py | 8 - .../C18243587_Joints_HingeBreakable.py | 8 - ...C18243588_Joints_Ball2BodiesConstrained.py | 8 - ...243589_Joints_BallSoftLimitsConstrained.py | 5 - ...18243590_Joints_BallNoLimitsConstrained.py | 8 - ...18243591_Joints_BallLeadFollowerCollide.py | 8 - .../C18243592_Joints_BallBreakable.py | 8 - ...C18243593_Joints_GlobalFrameConstrained.py | 8 - .../physics/{ => joints}/JointsHelper.py | 4 - .../{ => material}/AddModifyDelete_Utils.py | 0 ...DefaultLibraryUpdatedAcrossLevels_after.py | 8 - ...efaultLibraryUpdatedAcrossLevels_before.py | 8 - ...735_Materials_DefaultLibraryConsistency.py | 8 - ...Materials_DefaultMaterialLibraryChanges.py | 5 - ...096740_Material_LibraryUpdatedCorrectly.py | 7 +- ...21_Material_ComponentsInSyncWithLibrary.py | 8 - ...935_Material_LibraryUpdatedAcrossLevels.py | 9 - ...s_CharacterControllerMaterialAssignment.py | 8 - ...al_AddModifyDeleteOnCharacterController.py | 8 - ...977601_Material_FrictionCombinePriority.py | 9 - ...526_Material_RestitutionCombinePriority.py | 8 - ...044455_Material_libraryChangesInstantly.py | 8 - .../C4044456_Material_FrictionCombine.py | 8 - .../C4044457_Material_RestitutionCombine.py | 8 - .../C4044459_Material_DynamicFriction.py | 8 - .../C4044460_Material_StaticFriction.py | 8 - .../C4044461_Material_Restitution.py | 8 - ...044694_Material_EmptyLibraryUsesDefault.py | 8 - ...4697_Material_PerfaceMaterialValidation.py | 8 - ...8315_Material_AddModifyDeleteOnCollider.py | 8 - ...577_Materials_MaterialAssignedToTerrain.py | 8 - ...25579_Material_AddModifyDeleteOnTerrain.py | 8 - .../C4925580_Material_RagdollBonesMaterial.py | 8 - ..._Material_AddModifyDeleteOnRagdollBones.py | 8 - .../C5296614_PhysXMaterial_ColliderShape.py | 8 - .../{ => material}/Physmaterial_Editor.py | 0 .../C13895144_Ragdoll_ChangeLevel.py | 8 - .../C14654882_Ragdoll_ragdollAPTest.py | 8 - .../C17411467_AddPhysxRagdollComponent.py | 8 - .../C28978033_Ragdoll_WorldBodyBusTests.py | 8 - .../C13351703_COM_NotIncludeTriggerShapes.py | 8 - ...13352089_RigidBodies_MaxAngularVelocity.py | 5 - ...4976194_RigidBody_PhysXComponentIsValid.py | 5 - ...76195_RigidBodies_InitialLinearVelocity.py | 8 - ...6197_RigidBodies_InitialAngularVelocity.py | 5 - ...9_RigidBodies_LinearDampingObjectMotion.py | 8 - ..._RigidBody_AngularDampingObjectRotation.py | 5 - .../C4976201_RigidBody_MassIsAssigned.py | 8 - ...igidBody_StopsWhenBelowKineticThreshold.py | 8 - .../C4976204_Verify_Start_Asleep_Condition.py | 8 - ...976206_RigidBodies_GravityEnabledActive.py | 8 - ...6207_PhysXRigidBodies_KinematicBehavior.py | 8 - .../C4976209_RigidBody_ComputesCOM.py | 8 - .../C4976210_COM_ManualSetting.py | 5 - ...8_RigidBodies_InertiaObjectsNotComputed.py | 8 - ...5340400_RigidBody_ManualMomentOfInertia.py | 8 - .../C12712452_ScriptCanvas_CollisionEvents.py | 8 - ...712453_ScriptCanvas_MultipleRaycastNode.py | 8 - ...54_ScriptCanvas_OverlapNodeVerification.py | 8 - ...2455_ScriptCanvas_ShapeCastVerification.py | 8 - .../C14195074_ScriptCanvas_PostUpdateEvent.py | 8 - .../C14902097_ScriptCanvas_PreUpdateEvent.py | 5 - ...14902098_ScriptCanvas_PostPhysicsUpdate.py | 8 - ...criptCanvas_SetKinematicTargetTransform.py | 8 - .../C6224408_ScriptCanvas_EntitySpawn.py | 8 - .../C6274125_ScriptCanvas_TriggerEvents.py | 8 - ...8019_Terrain_TerrainTexturePainterWorks.py | 5 - .../C15308217_NoCrash_LevelSwitch.py | 8 - .../C3510642_Terrain_NotCollideWithTerrain.py | 8 - ...8_PhysXTerrain_CollidesWithPhysXTerrain.py | 8 - ...ysxterrain_AddPhysxterrainNoEditorCrash.py | 8 - ..._MultipleTerrains_CheckWarningInConsole.py | 9 - ...89528_Terrain_MultipleTerrainComponents.py | 8 - ...31_Warning_TerrainSliceTerrainComponent.py | 8 - ...032082_Terrain_MultipleResolutionsValid.py | 8 - .../physics/{ => utils}/FileManagement.py | 0 .../{ => utils}/UtilTest_Managed_Files.py | 5 - .../UtilTest_Physmaterial_Editor.py | 2 - .../UtilTest_PhysxConfig_Default.py | 0 .../UtilTest_PhysxConfig_Override.py | 0 .../UtilTest_Tracer_PicksErrorsAndWarnings.py | 5 - 161 files changed, 316 insertions(+), 1333 deletions(-) create mode 100644 AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/asset_utils.py delete mode 100755 AutomatedTesting/Gem/PythonTests/physics/ImportPathHelper.py rename AutomatedTesting/Gem/PythonTests/physics/{ => character_controller}/C14654881_CharacterController_SwitchLevels.py (96%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => collider}/C100000_RigidBody_EnablingGravityWorksPoC.py (96%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => collider}/C111111_RigidBody_EnablingGravityWorksUsingNotificationsPoC.py (96%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => collider}/C14861498_ConfirmError_NoPxMesh.py (95%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => collider}/C14861500_DefaultSetting_ColliderShape.py (95%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => collider}/C14861501_PhysXCollider_RenderMeshAutoAssigned.py (96%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => collider}/C14861502_PhysXCollider_AssetAutoAssigned.py (96%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => collider}/C14861504_RenderMeshAsset_WithNoPxAsset.py (95%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => collider}/C19578018_ShapeColliderWithNoShapeComponent.py (96%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => collider}/C19578021_ShapeCollider_CanBeAdded.py (96%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => collider}/C19723164_ShapeColliders_WontCrashEditor.py (96%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => collider}/C24308873_CylinderShapeCollider_CollidesWithPhysXTerrain.py (97%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => collider}/C3510644_Collider_CollisionGroups.py (99%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => collider}/C4044695_PhysXCollider_AddMultipleSurfaceFbx.py (97%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => collider}/C4976227_Collider_NewGroup.py (95%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => collider}/C4976236_AddPhysxColliderComponent.py (95%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => collider}/C4976242_Collision_SameCollisionlayerSameCollisiongroup.py (98%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => collider}/C4976243_Collision_SameCollisionGroupDiffCollisionLayers.py (97%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => collider}/C4976244_Collider_SameGroupSameLayerCollision.py (98%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => collider}/C4976245_PhysXCollider_CollisionLayerTest.py (98%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => collider}/C4982593_PhysXCollider_CollisionLayerTest.py (98%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => collider}/C4982595_Collider_TriggerDisablesCollision.py (99%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => collider}/C4982797_Collider_ColliderOffset.py (99%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => collider}/C4982798_Collider_ColliderRotationOffset.py (99%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => collider}/C4982800_PhysXColliderShape_CanBeSelected.py (96%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => collider}/C4982801_PhysXColliderShape_CanBeSelected.py (97%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => collider}/C4982802_PhysXColliderShape_CanBeSelected.py (97%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => collider}/C4982803_Enable_PxMesh_Option.py (97%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => force_region}/C12868578_ForceRegion_DirectionHasNoAffectOnMagnitude.py (99%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => force_region}/C12868580_ForceRegion_SplineModifiedTransform.py (98%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => force_region}/C12905527_ForceRegion_MagnitudeDeviation.py (97%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => force_region}/C12905528_ForceRegion_WithNonTriggerCollider.py (89%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => force_region}/C15845879_ForceRegion_HighLinearDampingForce.py (98%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => force_region}/C5932040_ForceRegion_CubeExertsWorldForce.py (98%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => force_region}/C5932041_PhysXForceRegion_LocalSpaceForceOnRigidBodies.py (98%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => force_region}/C5932042_PhysXForceRegion_LinearDamping.py (99%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => force_region}/C5932043_ForceRegion_SimpleDragOnRigidBodies.py (98%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => force_region}/C5932044_ForceRegion_PointForceOnRigidBody.py (98%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => force_region}/C5932045_ForceRegion_Spline.py (98%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => force_region}/C5959759_RigidBody_ForceRegionSpherePointForce.py (98%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => force_region}/C5959760_PhysXForceRegion_PointForceExertion.py (98%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => force_region}/C5959761_ForceRegion_PhysAssetExertsPointForce.py (97%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => force_region}/C5959763_ForceRegion_ForceRegionImpulsesCube.py (98%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => force_region}/C5959764_ForceRegion_ForceRegionImpulsesCapsule.py (98%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => force_region}/C5959765_ForceRegion_AssetGetsImpulsed.py (98%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => force_region}/C5959808_ForceRegion_PositionOffset.py (99%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => force_region}/C5959809_ForceRegion_RotationalOffset.py (99%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => force_region}/C5959810_ForceRegion_ForceRegionCombinesForces.py (98%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => force_region}/C5968759_ForceRegion_ExertsSeveralForcesOnRigidBody.py (98%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => force_region}/C5968760_ForceRegion_CheckNetForceChange.py (98%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => force_region}/C6090546_ForceRegion_SliceFileInstantiates.py (97%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => force_region}/C6090547_ForceRegion_ParentChildForceRegions.py (98%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => force_region}/C6090550_ForceRegion_WorldSpaceForceNegative.py (98%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => force_region}/C6090551_ForceRegion_LocalSpaceForceNegative.py (98%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => force_region}/C6090552_ForceRegion_LinearDampingNegative.py (98%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => force_region}/C6090553_ForceRegion_SimpleDragForceOnRigidBodies.py (98%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => force_region}/C6090554_ForceRegion_PointForceNegative.py (98%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => force_region}/C6090555_ForceRegion_SplineFollowOnRigidBodies.py (98%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => force_region}/C6321601_Force_HighValuesDirectionAxes.py (98%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => general}/C14976307_Gravity_SetGravityWorks.py (97%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => general}/C15425929_Undo_Redo.py (96%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => general}/C19536274_GetCollisionName_PrintsName.py (93%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => general}/C19536277_GetCollisionName_PrintsNothing.py (93%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => general}/C29032500_EditorComponents_WorldBodyBusWorks.py (98%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => general}/C5689529_Verify_Terrain_RigidBody_Collider_Mesh.py (97%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => general}/C6131473_StaticSlice_OnDynamicSliceSpawn.py (96%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => joints}/C18243580_Joints_Fixed2BodiesConstrained.py (96%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => joints}/C18243581_Joints_FixedBreakable.py (96%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => joints}/C18243582_Joints_FixedLeadFollowerCollide.py (96%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => joints}/C18243583_Joints_Hinge2BodiesConstrained.py (97%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => joints}/C18243584_Joints_HingeSoftLimitsConstrained.py (98%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => joints}/C18243585_Joints_HingeNoLimitsConstrained.py (97%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => joints}/C18243586_Joints_HingeLeadFollowerCollide.py (96%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => joints}/C18243587_Joints_HingeBreakable.py (97%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => joints}/C18243588_Joints_Ball2BodiesConstrained.py (97%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => joints}/C18243589_Joints_BallSoftLimitsConstrained.py (97%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => joints}/C18243590_Joints_BallNoLimitsConstrained.py (97%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => joints}/C18243591_Joints_BallLeadFollowerCollide.py (96%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => joints}/C18243592_Joints_BallBreakable.py (97%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => joints}/C18243593_Joints_GlobalFrameConstrained.py (97%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => joints}/JointsHelper.py (97%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => material}/AddModifyDelete_Utils.py (100%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => material}/C15096732_Material_DefaultLibraryUpdatedAcrossLevels_after.py (99%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => material}/C15096732_Material_DefaultLibraryUpdatedAcrossLevels_before.py (98%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => material}/C15096735_Materials_DefaultLibraryConsistency.py (99%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => material}/C15096737_Materials_DefaultMaterialLibraryChanges.py (99%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => material}/C15096740_Material_LibraryUpdatedCorrectly.py (96%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => material}/C15308221_Material_ComponentsInSyncWithLibrary.py (99%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => material}/C15425935_Material_LibraryUpdatedAcrossLevels.py (99%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => material}/C15556261_PhysXMaterials_CharacterControllerMaterialAssignment.py (98%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => material}/C15563573_Material_AddModifyDeleteOnCharacterController.py (98%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => material}/C18977601_Material_FrictionCombinePriority.py (99%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => material}/C18981526_Material_RestitutionCombinePriority.py (99%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => material}/C4044455_Material_libraryChangesInstantly.py (99%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => material}/C4044456_Material_FrictionCombine.py (98%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => material}/C4044457_Material_RestitutionCombine.py (98%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => material}/C4044459_Material_DynamicFriction.py (98%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => material}/C4044460_Material_StaticFriction.py (98%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => material}/C4044461_Material_Restitution.py (98%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => material}/C4044694_Material_EmptyLibraryUsesDefault.py (98%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => material}/C4044697_Material_PerfaceMaterialValidation.py (99%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => material}/C4888315_Material_AddModifyDeleteOnCollider.py (98%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => material}/C4925577_Materials_MaterialAssignedToTerrain.py (99%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => material}/C4925579_Material_AddModifyDeleteOnTerrain.py (98%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => material}/C4925580_Material_RagdollBonesMaterial.py (98%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => material}/C4925582_Material_AddModifyDeleteOnRagdollBones.py (98%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => material}/C5296614_PhysXMaterial_ColliderShape.py (98%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => material}/Physmaterial_Editor.py (100%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => ragdoll}/C13895144_Ragdoll_ChangeLevel.py (96%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => ragdoll}/C14654882_Ragdoll_ragdollAPTest.py (97%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => ragdoll}/C17411467_AddPhysxRagdollComponent.py (96%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => ragdoll}/C28978033_Ragdoll_WorldBodyBusTests.py (97%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => rigid_body}/C13351703_COM_NotIncludeTriggerShapes.py (96%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => rigid_body}/C13352089_RigidBodies_MaxAngularVelocity.py (99%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => rigid_body}/C4976194_RigidBody_PhysXComponentIsValid.py (97%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => rigid_body}/C4976195_RigidBodies_InitialLinearVelocity.py (97%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => rigid_body}/C4976197_RigidBodies_InitialAngularVelocity.py (98%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => rigid_body}/C4976199_RigidBodies_LinearDampingObjectMotion.py (98%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => rigid_body}/C4976200_RigidBody_AngularDampingObjectRotation.py (99%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => rigid_body}/C4976201_RigidBody_MassIsAssigned.py (99%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => rigid_body}/C4976202_RigidBody_StopsWhenBelowKineticThreshold.py (99%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => rigid_body}/C4976204_Verify_Start_Asleep_Condition.py (97%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => rigid_body}/C4976206_RigidBodies_GravityEnabledActive.py (97%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => rigid_body}/C4976207_PhysXRigidBodies_KinematicBehavior.py (97%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => rigid_body}/C4976209_RigidBody_ComputesCOM.py (98%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => rigid_body}/C4976210_COM_ManualSetting.py (99%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => rigid_body}/C4976218_RigidBodies_InertiaObjectsNotComputed.py (98%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => rigid_body}/C5340400_RigidBody_ManualMomentOfInertia.py (98%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => script_canvas}/C12712452_ScriptCanvas_CollisionEvents.py (98%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => script_canvas}/C12712453_ScriptCanvas_MultipleRaycastNode.py (98%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => script_canvas}/C12712454_ScriptCanvas_OverlapNodeVerification.py (99%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => script_canvas}/C12712455_ScriptCanvas_ShapeCastVerification.py (98%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => script_canvas}/C14195074_ScriptCanvas_PostUpdateEvent.py (98%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => script_canvas}/C14902097_ScriptCanvas_PreUpdateEvent.py (98%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => script_canvas}/C14902098_ScriptCanvas_PostPhysicsUpdate.py (97%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => script_canvas}/C14976308_ScriptCanvas_SetKinematicTargetTransform.py (99%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => script_canvas}/C6224408_ScriptCanvas_EntitySpawn.py (97%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => script_canvas}/C6274125_ScriptCanvas_TriggerEvents.py (97%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => terrain}/C13508019_Terrain_TerrainTexturePainterWorks.py (98%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => terrain}/C15308217_NoCrash_LevelSwitch.py (96%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => terrain}/C3510642_Terrain_NotCollideWithTerrain.py (98%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => terrain}/C5689518_PhysXTerrain_CollidesWithPhysXTerrain.py (97%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => terrain}/C5689522_Physxterrain_AddPhysxterrainNoEditorCrash.py (96%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => terrain}/C5689524_MultipleTerrains_CheckWarningInConsole.py (96%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => terrain}/C5689528_Terrain_MultipleTerrainComponents.py (96%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => terrain}/C5689531_Warning_TerrainSliceTerrainComponent.py (97%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => terrain}/C6032082_Terrain_MultipleResolutionsValid.py (98%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => utils}/FileManagement.py (100%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => utils}/UtilTest_Managed_Files.py (89%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => utils}/UtilTest_Physmaterial_Editor.py (99%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => utils}/UtilTest_PhysxConfig_Default.py (100%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => utils}/UtilTest_PhysxConfig_Override.py (100%) mode change 100755 => 100644 rename AutomatedTesting/Gem/PythonTests/physics/{ => utils}/UtilTest_Tracer_PicksErrorsAndWarnings.py (97%) mode change 100755 => 100644 diff --git a/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/asset_utils.py b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/asset_utils.py new file mode 100644 index 0000000000..ece7670a9e --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/asset_utils.py @@ -0,0 +1,47 @@ +""" +Copyright (c) Contributors to the Open 3D Engine Project. +For complete copyright and license terms please see the LICENSE at the root of this distribution. + +SPDX-License-Identifier: Apache-2.0 OR MIT +""" + +# Built-in Imports +from __future__ import annotations + +# Open 3D Engine Imports +import azlmbr.bus as bus +import azlmbr.asset as azasset +import azlmbr.math as math + + +class Asset: + """ + Used to find Asset Id by its path and path of asset by its Id + If a component has any asset property, then this class object can be called as: + asset_id = editor_python_test_tools.editor_entity_utils.EditorComponent.get_component_property_value() + asset = asset_utils.Asset(asset_id) + """ + def __init__(self, id: azasset.AssetId): + self.id: azasset.AssetId = id + + # Creation functions + @classmethod + def find_asset_by_path(cls, path: str, RegisterType: bool = False) -> Asset: + """ + :param path: Absolute file path of the asset + :param RegisterType: Whether to register the asset if it's not in the database, + default to false for the general case + :return: Asset object associated with file path + """ + asset_id = azasset.AssetCatalogRequestBus(bus.Broadcast, "GetAssetIdByPath", path, math.Uuid(), RegisterType) + assert asset_id.is_valid(), f"Couldn't find Asset with path: {path}" + asset = cls(asset_id) + return asset + + # Methods + def get_path(self) -> str: + """ + :return: Absolute file path of Asset + """ + assert self.id.is_valid(), "Invalid Asset Id" + return azasset.AssetCatalogRequestBus(bus.Broadcast, "GetAssetPathById", self.id) diff --git a/AutomatedTesting/Gem/PythonTests/physics/ImportPathHelper.py b/AutomatedTesting/Gem/PythonTests/physics/ImportPathHelper.py deleted file mode 100755 index 0e395664ad..0000000000 --- a/AutomatedTesting/Gem/PythonTests/physics/ImportPathHelper.py +++ /dev/null @@ -1,11 +0,0 @@ -""" -Copyright (c) Contributors to the Open 3D Engine Project. -For complete copyright and license terms please see the LICENSE at the root of this distribution. - -SPDX-License-Identifier: Apache-2.0 OR MIT -""" - -def init(): - import os - import sys - sys.path.append(os.path.dirname(os.path.abspath(__file__)) + '/../automatedtesting_shared') diff --git a/AutomatedTesting/Gem/PythonTests/physics/TestSuite_InDevelopment.py b/AutomatedTesting/Gem/PythonTests/physics/TestSuite_InDevelopment.py index 2c5cca4f24..dad37297cc 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/TestSuite_InDevelopment.py +++ b/AutomatedTesting/Gem/PythonTests/physics/TestSuite_InDevelopment.py @@ -13,25 +13,25 @@ import pytest import os import sys -from .FileManagement import FileManagement as fm +from .utils.FileManagement import FileManagement as fm sys.path.append(os.path.dirname(os.path.abspath(__file__)) + '/../automatedtesting_shared') -@pytest.mark.parametrize("spec", ["all"]) +from base import TestAutomationBase + @pytest.mark.parametrize("project", ["AutomatedTesting"]) -@pytest.mark.system class TestAutomation(TestAutomationBase): @fm.file_revert("ragdollbones.physmaterial", r"AutomatedTesting\Levels\Physics\C4925582_Material_AddModifyDeleteOnRagdollBones") def test_C4925582_Material_AddModifyDeleteOnRagdollBones(self, request, workspace, editor): - from . import C4925582_Material_AddModifyDeleteOnRagdollBones as test_module + from .material import C4925582_Material_AddModifyDeleteOnRagdollBones as test_module expected_lines = [] unexpected_lines = ["Assert"] self._run_test(request, workspace, editor, test_module, expected_lines, unexpected_lines) def test_C4925580_Material_RagdollBonesMaterial(self, request, workspace, editor): - from . import C4925580_Material_RagdollBonesMaterial as test_module + from .material import C4925580_Material_RagdollBonesMaterial as test_module expected_lines = [] unexpected_lines = ["Assert"] @@ -40,7 +40,7 @@ class TestAutomation(TestAutomationBase): @fm.file_revert("c15308221_material_componentsinsyncwithlibrary.physmaterial", r"AutomatedTesting\Levels\Physics\C15308221_Material_ComponentsInSyncWithLibrary") def test_C15308221_Material_ComponentsInSyncWithLibrary(self, request, workspace, editor): - from . import C15308221_Material_ComponentsInSyncWithLibrary as test_module + from .material import C15308221_Material_ComponentsInSyncWithLibrary as test_module expected_lines = [] unexpected_lines = ["Assert"] @@ -48,7 +48,7 @@ class TestAutomation(TestAutomationBase): # BUG: LY-107723") def test_C14976308_ScriptCanvas_SetKinematicTargetTransform(self, request, workspace, editor): - from . import C14976308_ScriptCanvas_SetKinematicTargetTransform as test_module + from .script_canvas import C14976308_ScriptCanvas_SetKinematicTargetTransform as test_module expected_lines = [] unexpected_lines = ["Assert"] @@ -58,7 +58,7 @@ class TestAutomation(TestAutomationBase): @fm.file_revert("c4925579_material_addmodifydeleteonterrain.physmaterial", r"AutomatedTesting\Levels\Physics\C4925579_Material_AddModifyDeleteOnTerrain") def test_C4925579_Material_AddModifyDeleteOnTerrain(self, request, workspace, editor): - from . import C4925579_Material_AddModifyDeleteOnTerrain as test_module + from .material import C4925579_Material_AddModifyDeleteOnTerrain as test_module expected_lines = [] unexpected_lines = ["Assert"] @@ -66,7 +66,7 @@ class TestAutomation(TestAutomationBase): # Failing, PhysXTerrain def test_C13508019_Terrain_TerrainTexturePainterWorks(self, request, workspace, editor): - from . import C13508019_Terrain_TerrainTexturePainterWorks as test_module + from .terrain import C13508019_Terrain_TerrainTexturePainterWorks as test_module expected_lines = [] unexpected_lines = ["Assert"] @@ -74,7 +74,7 @@ class TestAutomation(TestAutomationBase): # Failing, PhysXTerrain def test_C4925577_Materials_MaterialAssignedToTerrain(self, request, workspace, editor): - from . import C4925577_Materials_MaterialAssignedToTerrain as test_module + from .material import C4925577_Materials_MaterialAssignedToTerrain as test_module expected_lines = [] unexpected_lines = ["Assert"] @@ -82,7 +82,7 @@ class TestAutomation(TestAutomationBase): # Failing, PhysXTerrain def test_C15096735_Materials_DefaultLibraryConsistency(self, request, workspace, editor): - from . import C15096735_Materials_DefaultLibraryConsistency as test_module + from .material import C15096735_Materials_DefaultLibraryConsistency as test_module expected_lines = [] unexpected_lines = ["Assert"] @@ -92,13 +92,13 @@ class TestAutomation(TestAutomationBase): @fm.file_revert("all_ones_1.physmaterial", r"AutomatedTesting\Levels\Physics\C15096737_Materials_DefaultMaterialLibraryChanges") @fm.file_override("default.physxconfiguration", "C15096737_Materials_DefaultMaterialLibraryChanges.physxconfiguration", "AutomatedTesting") def test_C15096737_Materials_DefaultMaterialLibraryChanges(self, request, workspace, editor): - from . import C15096737_Materials_DefaultMaterialLibraryChanges as test_module + from .material import C15096737_Materials_DefaultMaterialLibraryChanges as test_module expected_lines = [] unexpected_lines = ["Assert"] self._run_test(request, workspace, editor, test_module, expected_lines, unexpected_lines) def test_C4976242_Collision_SameCollisionlayerSameCollisiongroup(self, request, workspace, editor): - from . import C4976242_Collision_SameCollisionlayerSameCollisiongroup as test_module + from .collider import C4976242_Collision_SameCollisionlayerSameCollisiongroup as test_module expected_lines = [] unexpected_lines = ["Assert"] @@ -109,7 +109,7 @@ class TestAutomation(TestAutomationBase): "Material_DefaultLibraryUpdatedAcrossLevels_before.physxconfiguration", "AutomatedTesting", search_subdirs=True) def test_levels_before(self, request, workspace, editor): - from . import C15096732_Material_DefaultLibraryUpdatedAcrossLevels_before as test_module_0 + from .material import C15096732_Material_DefaultLibraryUpdatedAcrossLevels_before as test_module_0 expected_lines = [] unexpected_lines = ["Assert"] self._run_test(request, workspace, editor, test_module_0, expected_lines, unexpected_lines) @@ -119,7 +119,7 @@ class TestAutomation(TestAutomationBase): "Material_DefaultLibraryUpdatedAcrossLevels_after.physxconfiguration", "AutomatedTesting", search_subdirs=True) def test_levels_after(self, request, workspace, editor): - from . import C15096732_Material_DefaultLibraryUpdatedAcrossLevels_after as test_module_1 + from .material import C15096732_Material_DefaultLibraryUpdatedAcrossLevels_after as test_module_1 expected_lines = [] unexpected_lines = ["Assert"] self._run_test(request, workspace, editor, test_module_1, expected_lines, unexpected_lines) @@ -128,7 +128,7 @@ class TestAutomation(TestAutomationBase): test_levels_after(self, request, workspace, editor) def test_C14654882_Ragdoll_ragdollAPTest(self, request, workspace, editor): - from . import C14654882_Ragdoll_ragdollAPTest as test_module + from .ragdoll import C14654882_Ragdoll_ragdollAPTest as test_module expected_lines = [] unexpected_lines = test_module.UnexpectedLines.lines @@ -136,14 +136,14 @@ class TestAutomation(TestAutomationBase): @fm.file_override("default.physxconfiguration", "C12712454_ScriptCanvas_OverlapNodeVerification.physxconfiguration") def test_C12712454_ScriptCanvas_OverlapNodeVerification(self, request, workspace, editor): - from . import C12712454_ScriptCanvas_OverlapNodeVerification as test_module + from .script_canvas import C12712454_ScriptCanvas_OverlapNodeVerification as test_module expected_lines = [] unexpected_lines = ["Assert"] self._run_test(request, workspace, editor, test_module, expected_lines, unexpected_lines) def test_C4044460_Material_StaticFriction(self, request, workspace, editor): - from . import C4044460_Material_StaticFriction as test_module + from .material import C4044460_Material_StaticFriction as test_module expected_lines = [] unexpected_lines = ["Assert"] @@ -154,7 +154,7 @@ class TestAutomation(TestAutomationBase): @fm.file_revert("c4888315_material_addmodifydeleteoncollider.physmaterial", r"AutomatedTesting\Levels\Physics\C4888315_Material_AddModifyDeleteOnCollider") def test_C4888315_Material_AddModifyDeleteOnCollider(self, request, workspace, editor): - from . import C4888315_Material_AddModifyDeleteOnCollider as test_module + from .material import C4888315_Material_AddModifyDeleteOnCollider as test_module expected_lines = [] unexpected_lines = ["Assert"] @@ -164,7 +164,7 @@ class TestAutomation(TestAutomationBase): @fm.file_revert("c15563573_material_addmodifydeleteoncharactercontroller.physmaterial", r"AutomatedTesting\Levels\Physics\C15563573_Material_AddModifyDeleteOnCharacterController") def test_C15563573_Material_AddModifyDeleteOnCharacterController(self, request, workspace, editor): - from . import C15563573_Material_AddModifyDeleteOnCharacterController as test_module + from .material import C15563573_Material_AddModifyDeleteOnCharacterController as test_module expected_lines = [] unexpected_lines = ["Assert"] @@ -173,7 +173,7 @@ class TestAutomation(TestAutomationBase): @fm.file_revert("c4888315_material_addmodifydeleteoncollider.physmaterial", r"AutomatedTesting\Levels\Physics\C4888315_Material_AddModifyDeleteOnCollider") def test_C4888315_Material_AddModifyDeleteOnCollider(self, request, workspace, editor): - from . import C4888315_Material_AddModifyDeleteOnCollider as test_module + from .material import C4888315_Material_AddModifyDeleteOnCollider as test_module expected_lines = [] unexpected_lines = ["Assert"] @@ -185,7 +185,7 @@ class TestAutomation(TestAutomationBase): @fm.file_revert("c15563573_material_addmodifydeleteoncharactercontroller.physmaterial", r"AutomatedTesting\Levels\Physics\C15563573_Material_AddModifyDeleteOnCharacterController") def test_C15563573_Material_AddModifyDeleteOnCharacterController(self, request, workspace, editor): - from . import C15563573_Material_AddModifyDeleteOnCharacterController as test_module + from .material import C15563573_Material_AddModifyDeleteOnCharacterController as test_module expected_lines = [] unexpected_lines = ["Assert"] @@ -194,7 +194,7 @@ class TestAutomation(TestAutomationBase): @fm.file_revert("c4044455_material_librarychangesinstantly.physmaterial", r"AutomatedTesting\Levels\Physics\C4044455_Material_LibraryChangesInstantly") def test_C4044455_Material_libraryChangesInstantly(self, request, workspace, editor): - from . import C4044455_Material_libraryChangesInstantly as test_module + from .material import C4044455_Material_libraryChangesInstantly as test_module expected_lines = [] unexpected_lines = ["Assert"] @@ -204,103 +204,103 @@ class TestAutomation(TestAutomationBase): @fm.file_revert("C15425935_Material_LibraryUpdatedAcrossLevels.physmaterial", r"AutomatedTesting\Levels\Physics\C15425935_Material_LibraryUpdatedAcrossLevels") def test_C15425935_Material_LibraryUpdatedAcrossLevels(self, request, workspace, editor): - from . import C15425935_Material_LibraryUpdatedAcrossLevels as test_module + from .material import C15425935_Material_LibraryUpdatedAcrossLevels as test_module expected_lines = [] unexpected_lines = ["Assert"] self._run_test(request, workspace, editor, test_module, expected_lines, unexpected_lines) def test_C4976199_RigidBodies_LinearDampingObjectMotion(self, request, workspace, editor): - from . import C4976199_RigidBodies_LinearDampingObjectMotion as test_module + from .rigid_body import C4976199_RigidBodies_LinearDampingObjectMotion as test_module expected_lines = [] unexpected_lines = ["Assert"] self._run_test(request, workspace, editor, test_module, expected_lines, unexpected_lines) def test_C5689518_PhysXTerrain_CollidesWithPhysXTerrain(self, request, workspace, editor): - from . import C5689518_PhysXTerrain_CollidesWithPhysXTerrain as test_module + from .terrain import C5689518_PhysXTerrain_CollidesWithPhysXTerrain as test_module expected_lines = [] unexpected_lines = ["Assert"] self._run_test(request, workspace, editor, test_module, expected_lines, unexpected_lines) def test_C24308873_CylinderShapeCollider_CollidesWithPhysXTerrain(self, request, workspace, editor): - from . import C24308873_CylinderShapeCollider_CollidesWithPhysXTerrain as test_module + from .collider import C24308873_CylinderShapeCollider_CollidesWithPhysXTerrain as test_module expected_lines = [] unexpected_lines = ["Assert"] self._run_test(request, workspace, editor, test_module, expected_lines, unexpected_lines) def test_C29032500_EditorComponents_WorldBodyBusWorks(self, request, workspace, editor): - from . import C29032500_EditorComponents_WorldBodyBusWorks as test_module + from .general import C29032500_EditorComponents_WorldBodyBusWorks as test_module expected_lines = [] unexpected_lines = ["Assert"] self._run_test(request, workspace, editor, test_module, expected_lines, unexpected_lines) def test_C14861498_ConfirmError_NoPxMesh(self, request, workspace, editor, launcher_platform): - from . import C14861498_ConfirmError_NoPxMesh as test_module + from .collider import C14861498_ConfirmError_NoPxMesh as test_module expected_lines = [] unexpected_lines = ["Assert"] self._run_test(request, workspace, editor, test_module, expected_lines, unexpected_lines) def test_C5959763_ForceRegion_ForceRegionImpulsesCube(self, request, workspace, editor, launcher_platform): - from . import C5959763_ForceRegion_ForceRegionImpulsesCube as test_module + from .force_region import C5959763_ForceRegion_ForceRegionImpulsesCube as test_module expected_lines = [] unexpected_lines = ["Assert"] self._run_test(request, workspace, editor, test_module, expected_lines, unexpected_lines) def test_C5689531_Warning_TerrainSliceTerrainComponent(self, request, workspace, editor, launcher_platform): - from . import C5689531_Warning_TerrainSliceTerrainComponent as test_module + from .terrain import C5689531_Warning_TerrainSliceTerrainComponent as test_module expected_lines = [] unexpected_lines = ["Assert"] self._run_test(request, workspace, editor, test_module, expected_lines, unexpected_lines) def test_C5689522_Physxterrain_AddPhysxterrainNoEditorCrash(self, request, workspace, editor, launcher_platform): - from . import C5689522_Physxterrain_AddPhysxterrainNoEditorCrash as test_module + from .terrain import C5689522_Physxterrain_AddPhysxterrainNoEditorCrash as test_module expected_lines = [] unexpected_lines = ["Assert"] self._run_test(request, workspace, editor, test_module, expected_lines, unexpected_lines) def test_C5689524_MultipleTerrains_CheckWarningInConsole(self, request, workspace, editor, launcher_platform): - from . import C5689524_MultipleTerrains_CheckWarningInConsole as test_module + from .terrain import C5689524_MultipleTerrains_CheckWarningInConsole as test_module expected_lines = [] unexpected_lines = ["Assert"] self._run_test(request, workspace, editor, test_module, expected_lines, unexpected_lines) def test_C5689528_Terrain_MultipleTerrainComponents(self, request, workspace, editor, launcher_platform): - from . import C5689528_Terrain_MultipleTerrainComponents as test_module + from .terrain import C5689528_Terrain_MultipleTerrainComponents as test_module expected_lines = [] unexpected_lines = ["Assert"] self._run_test(request, workspace, editor, test_module, expected_lines, unexpected_lines) def test_C5689528_Terrain_MultipleTerrainComponents(self, request, workspace, editor, launcher_platform): - from . import C5689528_Terrain_MultipleTerrainComponents as test_module + from .terrain import C5689528_Terrain_MultipleTerrainComponents as test_module expected_lines = [] unexpected_lines = ["Assert"] self._run_test(request, workspace, editor, test_module, expected_lines, unexpected_lines) def test_C6321601_Force_HighValuesDirectionAxes(self, request, workspace, editor, launcher_platform): - from . import C6321601_Force_HighValuesDirectionAxes as test_module + from .force_region import C6321601_Force_HighValuesDirectionAxes as test_module expected_lines = [] unexpected_lines = ["Assert"] self._run_test(request, workspace, editor, test_module, expected_lines, unexpected_lines) def test_C6032082_Terrain_MultipleResolutionsValid(self, request, workspace, editor, launcher_platform): - from . import C6032082_Terrain_MultipleResolutionsValid as test_module + from .terrain import C6032082_Terrain_MultipleResolutionsValid as test_module expected_lines = [] unexpected_lines = ["Assert"] self._run_test(request, workspace, editor, test_module, expected_lines, unexpected_lines) def test_C12905527_ForceRegion_MagnitudeDeviation(self, request, workspace, editor, launcher_platform): - from . import C12905527_ForceRegion_MagnitudeDeviation as test_module + from .force_region import C12905527_ForceRegion_MagnitudeDeviation as test_module expected_lines = [] unexpected_lines = ["Assert"] @@ -308,7 +308,7 @@ class TestAutomation(TestAutomationBase): # Removed from active suite to meet 60 minutes limit in AR job def test_C18243580_Joints_Fixed2BodiesConstrained(self, request, workspace, editor, launcher_platform): - from . import C18243580_Joints_Fixed2BodiesConstrained as test_module + from .joints import C18243580_Joints_Fixed2BodiesConstrained as test_module expected_lines = [] unexpected_lines = ["Assert"] @@ -316,7 +316,7 @@ class TestAutomation(TestAutomationBase): # Removed from active suite to meet 60 minutes limit in AR job def test_C18243583_Joints_Hinge2BodiesConstrained(self, request, workspace, editor, launcher_platform): - from . import C18243583_Joints_Hinge2BodiesConstrained as test_module + from .joints import C18243583_Joints_Hinge2BodiesConstrained as test_module expected_lines = [] unexpected_lines = ["Assert"] @@ -324,7 +324,7 @@ class TestAutomation(TestAutomationBase): # Removed from active suite to meet 60 minutes limit in AR job def test_C18243588_Joints_Ball2BodiesConstrained(self, request, workspace, editor, launcher_platform): - from . import C18243588_Joints_Ball2BodiesConstrained as test_module + from .joints import C18243588_Joints_Ball2BodiesConstrained as test_module expected_lines = [] unexpected_lines = ["Assert"] @@ -332,7 +332,7 @@ class TestAutomation(TestAutomationBase): # Removed from active suite to meet 60 minutes limit in AR job def test_C18243581_Joints_FixedBreakable(self, request, workspace, editor, launcher_platform): - from . import C18243581_Joints_FixedBreakable as test_module + from .joints import C18243581_Joints_FixedBreakable as test_module expected_lines = [] unexpected_lines = ["Assert"] @@ -340,7 +340,7 @@ class TestAutomation(TestAutomationBase): # Removed from active suite to meet 60 minutes limit in AR job def test_C18243587_Joints_HingeBreakable(self, request, workspace, editor, launcher_platform): - from . import C18243587_Joints_HingeBreakable as test_module + from .joints import C18243587_Joints_HingeBreakable as test_module expected_lines = [] unexpected_lines = ["Assert"] @@ -348,7 +348,7 @@ class TestAutomation(TestAutomationBase): # Removed from active suite to meet 60 minutes limit in AR job def test_C18243592_Joints_BallBreakable(self, request, workspace, editor, launcher_platform): - from . import C18243592_Joints_BallBreakable as test_module + from .joints import C18243592_Joints_BallBreakable as test_module expected_lines = [] unexpected_lines = ["Assert"] @@ -356,7 +356,7 @@ class TestAutomation(TestAutomationBase): # Removed from active suite to meet 60 minutes limit in AR job def test_C18243585_Joints_HingeNoLimitsConstrained(self, request, workspace, editor, launcher_platform): - from . import C18243585_Joints_HingeNoLimitsConstrained as test_module + from .joints import C18243585_Joints_HingeNoLimitsConstrained as test_module expected_lines = [] unexpected_lines = ["Assert"] @@ -364,7 +364,7 @@ class TestAutomation(TestAutomationBase): # Removed from active suite to meet 60 minutes limit in AR job def test_C18243590_Joints_BallNoLimitsConstrained(self, request, workspace, editor, launcher_platform): - from . import C18243590_Joints_BallNoLimitsConstrained as test_module + from .joints import C18243590_Joints_BallNoLimitsConstrained as test_module expected_lines = [] unexpected_lines = ["Assert"] @@ -372,7 +372,7 @@ class TestAutomation(TestAutomationBase): # Removed from active suite to meet 60 minutes limit in AR job def test_C18243582_Joints_FixedLeadFollowerCollide(self, request, workspace, editor, launcher_platform): - from . import C18243582_Joints_FixedLeadFollowerCollide as test_module + from .joints import C18243582_Joints_FixedLeadFollowerCollide as test_module expected_lines = [] unexpected_lines = ["Assert"] @@ -380,7 +380,7 @@ class TestAutomation(TestAutomationBase): # Removed from active suite to meet 60 minutes limit in AR job def test_C18243593_Joints_GlobalFrameConstrained(self, request, workspace, editor, launcher_platform): - from . import C18243593_Joints_GlobalFrameConstrained as test_module + from .joints import C18243593_Joints_GlobalFrameConstrained as test_module expected_lines = [] unexpected_lines = ["Assert"] diff --git a/AutomatedTesting/Gem/PythonTests/physics/TestSuite_Main.py b/AutomatedTesting/Gem/PythonTests/physics/TestSuite_Main.py index bda4dae82b..de4828e36a 100644 --- a/AutomatedTesting/Gem/PythonTests/physics/TestSuite_Main.py +++ b/AutomatedTesting/Gem/PythonTests/physics/TestSuite_Main.py @@ -12,7 +12,7 @@ import pytest import os import sys -from .FileManagement import FileManagement as fm +from .utils.FileManagement import FileManagement as fm from ly_test_tools import LAUNCHERS sys.path.append(os.path.dirname(os.path.abspath(__file__)) + '/../automatedtesting_shared') @@ -29,58 +29,58 @@ revert_physics_config = fm.file_revert_list(['physxdebugconfiguration.setreg', ' class TestAutomation(TestAutomationBase): def test_C111111_RigidBody_EnablingGravityWorksUsingNotificationsPoC(self, request, workspace, editor, launcher_platform): - from . import C111111_RigidBody_EnablingGravityWorksUsingNotificationsPoC as test_module + from .collider import C111111_RigidBody_EnablingGravityWorksUsingNotificationsPoC as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C5932041_PhysXForceRegion_LocalSpaceForceOnRigidBodies(self, request, workspace, editor, launcher_platform): - from . import C5932041_PhysXForceRegion_LocalSpaceForceOnRigidBodies as test_module + from .force_region import C5932041_PhysXForceRegion_LocalSpaceForceOnRigidBodies as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config @fm.file_override('physxsystemconfiguration.setreg','C4044459_Material_DynamicFriction.setreg_override', 'AutomatedTesting/Registry') def test_C4044459_Material_DynamicFriction(self, request, workspace, editor, launcher_platform): - from . import C4044459_Material_DynamicFriction as test_module + from .material import C4044459_Material_DynamicFriction as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C4976243_Collision_SameCollisionGroupDiffCollisionLayers(self, request, workspace, editor, launcher_platform): - from . import C4976243_Collision_SameCollisionGroupDiffCollisionLayers as test_module + from .collider import C4976243_Collision_SameCollisionGroupDiffCollisionLayers as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C14654881_CharacterController_SwitchLevels(self, request, workspace, editor, launcher_platform): - from . import C14654881_CharacterController_SwitchLevels as test_module + from .character_controller import C14654881_CharacterController_SwitchLevels as test_module self._run_test(request, workspace, editor, test_module) def test_C17411467_AddPhysxRagdollComponent(self, request, workspace, editor, launcher_platform): - from . import C17411467_AddPhysxRagdollComponent as test_module + from .ragdoll import C17411467_AddPhysxRagdollComponent as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C12712453_ScriptCanvas_MultipleRaycastNode(self, request, workspace, editor, launcher_platform): - from . import C12712453_ScriptCanvas_MultipleRaycastNode as test_module + from .script_canvas import C12712453_ScriptCanvas_MultipleRaycastNode as test_module # Fixme: unexpected_lines = ["Assert"] + test_module.Lines.unexpected self._run_test(request, workspace, editor, test_module) @revert_physics_config @fm.file_override('physxsystemconfiguration.setreg','C4982593_PhysXCollider_CollisionLayer.setreg_override', 'AutomatedTesting/Registry') def test_C4982593_PhysXCollider_CollisionLayerTest(self, request, workspace, editor, launcher_platform): - from . import C4982593_PhysXCollider_CollisionLayerTest as test_module + from .collider import C4982593_PhysXCollider_CollisionLayerTest as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C18243586_Joints_HingeLeadFollowerCollide(self, request, workspace, editor, launcher_platform): - from . import C18243586_Joints_HingeLeadFollowerCollide as test_module + from .joints import C18243586_Joints_HingeLeadFollowerCollide as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C4982803_Enable_PxMesh_Option(self, request, workspace, editor, launcher_platform): - from . import C4982803_Enable_PxMesh_Option as test_module + from .collider import C4982803_Enable_PxMesh_Option as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C24308873_CylinderShapeCollider_CollidesWithPhysXTerrain(self, request, workspace, editor, launcher_platform): - from . import C24308873_CylinderShapeCollider_CollidesWithPhysXTerrain as test_module - self._run_test(request, workspace, editor, test_module) \ No newline at end of file + from .collider import C24308873_CylinderShapeCollider_CollidesWithPhysXTerrain as test_module + self._run_test(request, workspace, editor, test_module) diff --git a/AutomatedTesting/Gem/PythonTests/physics/TestSuite_Main_Optimized.py b/AutomatedTesting/Gem/PythonTests/physics/TestSuite_Main_Optimized.py index 75e226fba1..ce68bb10b5 100644 --- a/AutomatedTesting/Gem/PythonTests/physics/TestSuite_Main_Optimized.py +++ b/AutomatedTesting/Gem/PythonTests/physics/TestSuite_Main_Optimized.py @@ -12,7 +12,7 @@ import inspect from ly_test_tools import LAUNCHERS from ly_test_tools.o3de.editor_test import EditorSingleTest, EditorSharedTest, EditorParallelTest, EditorTestSuite -from .FileManagement import FileManagement as fm +from .utils.FileManagement import FileManagement as fm # Custom test spec, it provides functionality to override files class EditorSingleTest_WithFileOverrides(EditorSingleTest): @@ -54,7 +54,6 @@ class EditorSingleTest_WithFileOverrides(EditorSingleTest): fm._restore_file(f, file_list[f]) -@pytest.mark.xfail(reason="Optimized tests are experimental, we will enable xfail and monitor them temporarly.") @pytest.mark.SUITE_main @pytest.mark.parametrize("launcher_platform", ['windows_editor']) @pytest.mark.parametrize("project", ["AutomatedTesting"]) @@ -67,14 +66,14 @@ class TestAutomation(EditorTestSuite): ######################################### # Non-atomic tests: These need to be run in a single editor because they have custom setup and teardown class C4044459_Material_DynamicFriction(EditorSingleTest_WithFileOverrides): - from . import C4044459_Material_DynamicFriction as test_module + from .material import C4044459_Material_DynamicFriction as test_module files_to_override = [ ('physxsystemconfiguration.setreg', 'C4044459_Material_DynamicFriction.setreg_override') ] base_dir = "AutomatedTesting/Registry" class C4982593_PhysXCollider_CollisionLayerTest(EditorSingleTest_WithFileOverrides): - from . import C4982593_PhysXCollider_CollisionLayerTest as test_module + from .collider import C4982593_PhysXCollider_CollisionLayerTest as test_module files_to_override = [ ('physxsystemconfiguration.setreg', 'C4982593_PhysXCollider_CollisionLayer.setreg_override') ] @@ -82,268 +81,268 @@ class TestAutomation(EditorTestSuite): ######################################### class C111111_RigidBody_EnablingGravityWorksUsingNotificationsPoC(EditorSharedTest): - from . import C111111_RigidBody_EnablingGravityWorksUsingNotificationsPoC as test_module + from .collider import C111111_RigidBody_EnablingGravityWorksUsingNotificationsPoC as test_module class C5932041_PhysXForceRegion_LocalSpaceForceOnRigidBodies(EditorSharedTest): - from . import C5932041_PhysXForceRegion_LocalSpaceForceOnRigidBodies as test_module + from .force_region import C5932041_PhysXForceRegion_LocalSpaceForceOnRigidBodies as test_module class C15425929_Undo_Redo(EditorSharedTest): - from . import C15425929_Undo_Redo as test_module + from .general import C15425929_Undo_Redo as test_module class C4976243_Collision_SameCollisionGroupDiffCollisionLayers(EditorSharedTest): - from . import C4976243_Collision_SameCollisionGroupDiffCollisionLayers as test_module + from .collider import C4976243_Collision_SameCollisionGroupDiffCollisionLayers as test_module class C14654881_CharacterController_SwitchLevels(EditorSharedTest): - from . import C14654881_CharacterController_SwitchLevels as test_module + from .character_controller import C14654881_CharacterController_SwitchLevels as test_module class C17411467_AddPhysxRagdollComponent(EditorSharedTest): - from . import C17411467_AddPhysxRagdollComponent as test_module + from .ragdoll import C17411467_AddPhysxRagdollComponent as test_module class C12712453_ScriptCanvas_MultipleRaycastNode(EditorSharedTest): - from . import C12712453_ScriptCanvas_MultipleRaycastNode as test_module + from .script_canvas import C12712453_ScriptCanvas_MultipleRaycastNode as test_module class C18243586_Joints_HingeLeadFollowerCollide(EditorSharedTest): - from . import C18243586_Joints_HingeLeadFollowerCollide as test_module + from .joints import C18243586_Joints_HingeLeadFollowerCollide as test_module class C4982803_Enable_PxMesh_Option(EditorSharedTest): - from . import C4982803_Enable_PxMesh_Option as test_module + from .collider import C4982803_Enable_PxMesh_Option as test_module class C24308873_CylinderShapeCollider_CollidesWithPhysXTerrain(EditorSharedTest): - from . import C24308873_CylinderShapeCollider_CollidesWithPhysXTerrain as test_module + from .collider import C24308873_CylinderShapeCollider_CollidesWithPhysXTerrain as test_module class C3510642_Terrain_NotCollideWithTerrain(EditorSharedTest): - from . import C3510642_Terrain_NotCollideWithTerrain as test_module + from .terrain import C3510642_Terrain_NotCollideWithTerrain as test_module class C4976195_RigidBodies_InitialLinearVelocity(EditorSharedTest): - from . import C4976195_RigidBodies_InitialLinearVelocity as test_module + from .rigid_body import C4976195_RigidBodies_InitialLinearVelocity as test_module class C4976206_RigidBodies_GravityEnabledActive(EditorSharedTest): - from . import C4976206_RigidBodies_GravityEnabledActive as test_module + from .rigid_body import C4976206_RigidBodies_GravityEnabledActive as test_module class C4976207_PhysXRigidBodies_KinematicBehavior(EditorSharedTest): - from . import C4976207_PhysXRigidBodies_KinematicBehavior as test_module + from .rigid_body import C4976207_PhysXRigidBodies_KinematicBehavior as test_module class C5932042_PhysXForceRegion_LinearDamping(EditorSharedTest): - from . import C5932042_PhysXForceRegion_LinearDamping as test_module + from .force_region import C5932042_PhysXForceRegion_LinearDamping as test_module class C5932043_ForceRegion_SimpleDragOnRigidBodies(EditorSharedTest): - from . import C5932043_ForceRegion_SimpleDragOnRigidBodies as test_module + from .force_region import C5932043_ForceRegion_SimpleDragOnRigidBodies as test_module class C5959760_PhysXForceRegion_PointForceExertion(EditorSharedTest): - from . import C5959760_PhysXForceRegion_PointForceExertion as test_module + from .force_region import C5959760_PhysXForceRegion_PointForceExertion as test_module class C5959764_ForceRegion_ForceRegionImpulsesCapsule(EditorSharedTest): - from . import C5959764_ForceRegion_ForceRegionImpulsesCapsule as test_module + from .force_region import C5959764_ForceRegion_ForceRegionImpulsesCapsule as test_module class C5340400_RigidBody_ManualMomentOfInertia(EditorSharedTest): - from . import C5340400_RigidBody_ManualMomentOfInertia as test_module + from .rigid_body import C5340400_RigidBody_ManualMomentOfInertia as test_module class C4976210_COM_ManualSetting(EditorSharedTest): - from . import C4976210_COM_ManualSetting as test_module + from .rigid_body import C4976210_COM_ManualSetting as test_module class C4976194_RigidBody_PhysXComponentIsValid(EditorSharedTest): - from . import C4976194_RigidBody_PhysXComponentIsValid as test_module + from .rigid_body import C4976194_RigidBody_PhysXComponentIsValid as test_module class C5932045_ForceRegion_Spline(EditorSharedTest): - from . import C5932045_ForceRegion_Spline as test_module + from .force_region import C5932045_ForceRegion_Spline as test_module class C4982797_Collider_ColliderOffset(EditorSharedTest): - from . import C4982797_Collider_ColliderOffset as test_module + from .collider import C4982797_Collider_ColliderOffset as test_module class C4976200_RigidBody_AngularDampingObjectRotation(EditorSharedTest): - from . import C4976200_RigidBody_AngularDampingObjectRotation as test_module + from .rigid_body import C4976200_RigidBody_AngularDampingObjectRotation as test_module class C5689529_Verify_Terrain_RigidBody_Collider_Mesh(EditorSharedTest): - from . import C5689529_Verify_Terrain_RigidBody_Collider_Mesh as test_module + from .general import C5689529_Verify_Terrain_RigidBody_Collider_Mesh as test_module class C5959810_ForceRegion_ForceRegionCombinesForces(EditorSharedTest): - from . import C5959810_ForceRegion_ForceRegionCombinesForces as test_module + from .force_region import C5959810_ForceRegion_ForceRegionCombinesForces as test_module class C5959765_ForceRegion_AssetGetsImpulsed(EditorSharedTest): - from . import C5959765_ForceRegion_AssetGetsImpulsed as test_module + from .force_region import C5959765_ForceRegion_AssetGetsImpulsed as test_module class C6274125_ScriptCanvas_TriggerEvents(EditorSharedTest): - from . import C6274125_ScriptCanvas_TriggerEvents as test_module + from .script_canvas import C6274125_ScriptCanvas_TriggerEvents as test_module # needs to be updated to log for unexpected lines # expected_lines = test_module.LogLines.expected_lines class C6090554_ForceRegion_PointForceNegative(EditorSharedTest): - from . import C6090554_ForceRegion_PointForceNegative as test_module + from .force_region import C6090554_ForceRegion_PointForceNegative as test_module class C6090550_ForceRegion_WorldSpaceForceNegative(EditorSharedTest): - from . import C6090550_ForceRegion_WorldSpaceForceNegative as test_module + from .force_region import C6090550_ForceRegion_WorldSpaceForceNegative as test_module class C6090552_ForceRegion_LinearDampingNegative(EditorSharedTest): - from . import C6090552_ForceRegion_LinearDampingNegative as test_module + from .force_region import C6090552_ForceRegion_LinearDampingNegative as test_module class C5968760_ForceRegion_CheckNetForceChange(EditorSharedTest): - from . import C5968760_ForceRegion_CheckNetForceChange as test_module + from .force_region import C5968760_ForceRegion_CheckNetForceChange as test_module class C12712452_ScriptCanvas_CollisionEvents(EditorSharedTest): - from . import C12712452_ScriptCanvas_CollisionEvents as test_module + from .script_canvas import C12712452_ScriptCanvas_CollisionEvents as test_module class C12868578_ForceRegion_DirectionHasNoAffectOnMagnitude(EditorSharedTest): - from . import C12868578_ForceRegion_DirectionHasNoAffectOnMagnitude as test_module + from .force_region import C12868578_ForceRegion_DirectionHasNoAffectOnMagnitude as test_module class C4976204_Verify_Start_Asleep_Condition(EditorSharedTest): - from . import C4976204_Verify_Start_Asleep_Condition as test_module + from .rigid_body import C4976204_Verify_Start_Asleep_Condition as test_module class C6090546_ForceRegion_SliceFileInstantiates(EditorSharedTest): - from . import C6090546_ForceRegion_SliceFileInstantiates as test_module + from .force_region import C6090546_ForceRegion_SliceFileInstantiates as test_module class C6090551_ForceRegion_LocalSpaceForceNegative(EditorSharedTest): - from . import C6090551_ForceRegion_LocalSpaceForceNegative as test_module + from .force_region import C6090551_ForceRegion_LocalSpaceForceNegative as test_module class C6090553_ForceRegion_SimpleDragForceOnRigidBodies(EditorSharedTest): - from . import C6090553_ForceRegion_SimpleDragForceOnRigidBodies as test_module + from .force_region import C6090553_ForceRegion_SimpleDragForceOnRigidBodies as test_module class C4976209_RigidBody_ComputesCOM(EditorSharedTest): - from . import C4976209_RigidBody_ComputesCOM as test_module + from .rigid_body import C4976209_RigidBody_ComputesCOM as test_module class C4976201_RigidBody_MassIsAssigned(EditorSharedTest): - from . import C4976201_RigidBody_MassIsAssigned as test_module + from .rigid_body import C4976201_RigidBody_MassIsAssigned as test_module class C12868580_ForceRegion_SplineModifiedTransform(EditorSharedTest): - from . import C12868580_ForceRegion_SplineModifiedTransform as test_module + from .force_region import C12868580_ForceRegion_SplineModifiedTransform as test_module class C12712455_ScriptCanvas_ShapeCastVerification(EditorSharedTest): - from . import C12712455_ScriptCanvas_ShapeCastVerification as test_module + from .script_canvas import C12712455_ScriptCanvas_ShapeCastVerification as test_module class C4976197_RigidBodies_InitialAngularVelocity(EditorSharedTest): - from . import C4976197_RigidBodies_InitialAngularVelocity as test_module + from .rigid_body import C4976197_RigidBodies_InitialAngularVelocity as test_module class C6090555_ForceRegion_SplineFollowOnRigidBodies(EditorSharedTest): - from . import C6090555_ForceRegion_SplineFollowOnRigidBodies as test_module + from .force_region import C6090555_ForceRegion_SplineFollowOnRigidBodies as test_module class C6131473_StaticSlice_OnDynamicSliceSpawn(EditorSharedTest): - from . import C6131473_StaticSlice_OnDynamicSliceSpawn as test_module + from .general import C6131473_StaticSlice_OnDynamicSliceSpawn as test_module class C5959808_ForceRegion_PositionOffset(EditorSharedTest): - from . import C5959808_ForceRegion_PositionOffset as test_module + from .force_region import C5959808_ForceRegion_PositionOffset as test_module @pytest.mark.xfail(reason="Something with the CryRenderer disabling is causing this test to fail now.") class C13895144_Ragdoll_ChangeLevel(EditorSharedTest): - from . import C13895144_Ragdoll_ChangeLevel as test_module + from .ragdoll import C13895144_Ragdoll_ChangeLevel as test_module class C5968759_ForceRegion_ExertsSeveralForcesOnRigidBody(EditorSharedTest): - from . import C5968759_ForceRegion_ExertsSeveralForcesOnRigidBody as test_module + from .force_region import C5968759_ForceRegion_ExertsSeveralForcesOnRigidBody as test_module @pytest.mark.xfail(reason="This test will sometimes fail as the ball will continue to roll before the timeout is reached.") class C4976202_RigidBody_StopsWhenBelowKineticThreshold(EditorSharedTest): - from . import C4976202_RigidBody_StopsWhenBelowKineticThreshold as test_module + from .rigid_body import C4976202_RigidBody_StopsWhenBelowKineticThreshold as test_module class C13351703_COM_NotIncludeTriggerShapes(EditorSharedTest): - from . import C13351703_COM_NotIncludeTriggerShapes as test_module + from .rigid_body import C13351703_COM_NotIncludeTriggerShapes as test_module class C5296614_PhysXMaterial_ColliderShape(EditorSharedTest): - from . import C5296614_PhysXMaterial_ColliderShape as test_module + from .material import C5296614_PhysXMaterial_ColliderShape as test_module class C4982595_Collider_TriggerDisablesCollision(EditorSharedTest): - from . import C4982595_Collider_TriggerDisablesCollision as test_module + from .collider import C4982595_Collider_TriggerDisablesCollision as test_module class C14976307_Gravity_SetGravityWorks(EditorSharedTest): - from . import C14976307_Gravity_SetGravityWorks as test_module + from .general import C14976307_Gravity_SetGravityWorks as test_module class C4044694_Material_EmptyLibraryUsesDefault(EditorSharedTest): - from . import C4044694_Material_EmptyLibraryUsesDefault as test_module + from .material import C4044694_Material_EmptyLibraryUsesDefault as test_module class C15845879_ForceRegion_HighLinearDampingForce(EditorSharedTest): - from . import C15845879_ForceRegion_HighLinearDampingForce as test_module + from .force_region import C15845879_ForceRegion_HighLinearDampingForce as test_module class C4976218_RigidBodies_InertiaObjectsNotComputed(EditorSharedTest): - from . import C4976218_RigidBodies_InertiaObjectsNotComputed as test_module + from .rigid_body import C4976218_RigidBodies_InertiaObjectsNotComputed as test_module class C14902098_ScriptCanvas_PostPhysicsUpdate(EditorSharedTest): - from . import C14902098_ScriptCanvas_PostPhysicsUpdate as test_module + from .script_canvas import C14902098_ScriptCanvas_PostPhysicsUpdate as test_module # Note: Test needs to be updated to log for unexpected lines # unexpected_lines = ["Assert"] + test_module.Lines.unexpected class C5959761_ForceRegion_PhysAssetExertsPointForce(EditorSharedTest): - from . import C5959761_ForceRegion_PhysAssetExertsPointForce as test_module + from .force_region import C5959761_ForceRegion_PhysAssetExertsPointForce as test_module # Marking the Test as expected to fail using the xfail decorator due to sporadic failure on Automated Review: SPEC-3146 # The test still runs, but a failure of the test doesn't result in the test run failing @pytest.mark.xfail(reason="Test Sporadically fails with message [ NOT FOUND ] Success: Bar1 : Expected angular velocity") class C13352089_RigidBodies_MaxAngularVelocity(EditorSharedTest): - from . import C13352089_RigidBodies_MaxAngularVelocity as test_module + from .rigid_body import C13352089_RigidBodies_MaxAngularVelocity as test_module class C18243584_Joints_HingeSoftLimitsConstrained(EditorSharedTest): - from . import C18243584_Joints_HingeSoftLimitsConstrained as test_module + from .joints import C18243584_Joints_HingeSoftLimitsConstrained as test_module class C18243589_Joints_BallSoftLimitsConstrained(EditorSharedTest): - from . import C18243589_Joints_BallSoftLimitsConstrained as test_module + from .joints import C18243589_Joints_BallSoftLimitsConstrained as test_module class C18243591_Joints_BallLeadFollowerCollide(EditorSharedTest): - from . import C18243591_Joints_BallLeadFollowerCollide as test_module + from .joints import C18243591_Joints_BallLeadFollowerCollide as test_module class C19578018_ShapeColliderWithNoShapeComponent(EditorSharedTest): - from . import C19578018_ShapeColliderWithNoShapeComponent as test_module + from .collider import C19578018_ShapeColliderWithNoShapeComponent as test_module class C14861500_DefaultSetting_ColliderShape(EditorSharedTest): - from . import C14861500_DefaultSetting_ColliderShape as test_module + from .collider import C14861500_DefaultSetting_ColliderShape as test_module class C19723164_ShapeCollider_WontCrashEditor(EditorSharedTest): - from . import C19723164_ShapeColliders_WontCrashEditor as test_module + from .collider import C19723164_ShapeColliders_WontCrashEditor as test_module class C4982800_PhysXColliderShape_CanBeSelected(EditorSharedTest): - from . import C4982800_PhysXColliderShape_CanBeSelected as test_module + from .collider import C4982800_PhysXColliderShape_CanBeSelected as test_module class C4982801_PhysXColliderShape_CanBeSelected(EditorSharedTest): - from . import C4982801_PhysXColliderShape_CanBeSelected as test_module + from .collider import C4982801_PhysXColliderShape_CanBeSelected as test_module class C4982802_PhysXColliderShape_CanBeSelected(EditorSharedTest): - from . import C4982802_PhysXColliderShape_CanBeSelected as test_module + from .collider import C4982802_PhysXColliderShape_CanBeSelected as test_module class C12905528_ForceRegion_WithNonTriggerCollider(EditorSharedTest): - from . import C12905528_ForceRegion_WithNonTriggerCollider as test_module + from .force_region import C12905528_ForceRegion_WithNonTriggerCollider as test_module # Fixme: expected_lines = ["[Warning] (PhysX Force Region) - Please ensure collider component marked as trigger exists in entity"] class C5932040_ForceRegion_CubeExertsWorldForce(EditorSharedTest): - from . import C5932040_ForceRegion_CubeExertsWorldForce as test_module + from .force_region import C5932040_ForceRegion_CubeExertsWorldForce as test_module class C5932044_ForceRegion_PointForceOnRigidBody(EditorSharedTest): - from . import C5932044_ForceRegion_PointForceOnRigidBody as test_module + from .force_region import C5932044_ForceRegion_PointForceOnRigidBody as test_module class C5959759_RigidBody_ForceRegionSpherePointForce(EditorSharedTest): - from . import C5959759_RigidBody_ForceRegionSpherePointForce as test_module + from .force_region import C5959759_RigidBody_ForceRegionSpherePointForce as test_module class C5959809_ForceRegion_RotationalOffset(EditorSharedTest): - from . import C5959809_ForceRegion_RotationalOffset as test_module + from .force_region import C5959809_ForceRegion_RotationalOffset as test_module class C15096740_Material_LibraryUpdatedCorrectly(EditorSharedTest): - from . import C15096740_Material_LibraryUpdatedCorrectly as test_module + from .material import C15096740_Material_LibraryUpdatedCorrectly as test_module class C4976236_AddPhysxColliderComponent(EditorSharedTest): - from . import C4976236_AddPhysxColliderComponent as test_module + from .collider import C4976236_AddPhysxColliderComponent as test_module @pytest.mark.xfail(reason="This will fail due to this issue ATOM-15487.") class C14861502_PhysXCollider_AssetAutoAssigned(EditorSharedTest): - from . import C14861502_PhysXCollider_AssetAutoAssigned as test_module + from .collider import C14861502_PhysXCollider_AssetAutoAssigned as test_module class C14861501_PhysXCollider_RenderMeshAutoAssigned(EditorSharedTest): - from . import C14861501_PhysXCollider_RenderMeshAutoAssigned as test_module + from .collider import C14861501_PhysXCollider_RenderMeshAutoAssigned as test_module class C4044695_PhysXCollider_AddMultipleSurfaceFbx(EditorSharedTest): - from . import C4044695_PhysXCollider_AddMultipleSurfaceFbx as test_module + from .collider import C4044695_PhysXCollider_AddMultipleSurfaceFbx as test_module class C14861504_RenderMeshAsset_WithNoPxAsset(EditorSharedTest): - from . import C14861504_RenderMeshAsset_WithNoPxAsset as test_module + from .collider import C14861504_RenderMeshAsset_WithNoPxAsset as test_module class C100000_RigidBody_EnablingGravityWorksPoC(EditorSharedTest): - from . import C100000_RigidBody_EnablingGravityWorksPoC as test_module + from .collider import C100000_RigidBody_EnablingGravityWorksPoC as test_module class C4982798_Collider_ColliderRotationOffset(EditorSharedTest): - from . import C4982798_Collider_ColliderRotationOffset as test_module + from .collider import C4982798_Collider_ColliderRotationOffset as test_module class C15308217_NoCrash_LevelSwitch(EditorSharedTest): - from . import C15308217_NoCrash_LevelSwitch as test_module + from .terrain import C15308217_NoCrash_LevelSwitch as test_module class C6090547_ForceRegion_ParentChildForceRegions(EditorSharedTest): - from . import C6090547_ForceRegion_ParentChildForceRegions as test_module + from .force_region import C6090547_ForceRegion_ParentChildForceRegions as test_module class C19578021_ShapeCollider_CanBeAdded(EditorSharedTest): - from . import C19578021_ShapeCollider_CanBeAdded as test_module + from .collider import C19578021_ShapeCollider_CanBeAdded as test_module class C15425929_Undo_Redo(EditorSharedTest): - from . import C15425929_Undo_Redo as test_module + from .general import C15425929_Undo_Redo as test_module diff --git a/AutomatedTesting/Gem/PythonTests/physics/TestSuite_Periodic.py b/AutomatedTesting/Gem/PythonTests/physics/TestSuite_Periodic.py index 3d86db1014..fca7e0e3af 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/TestSuite_Periodic.py +++ b/AutomatedTesting/Gem/PythonTests/physics/TestSuite_Periodic.py @@ -12,7 +12,7 @@ import pytest import os import sys -from .FileManagement import FileManagement as fm +from .utils.FileManagement import FileManagement as fm from ly_test_tools import LAUNCHERS sys.path.append(os.path.dirname(os.path.abspath(__file__)) + '/../automatedtesting_shared') @@ -30,219 +30,219 @@ class TestAutomation(TestAutomationBase): @revert_physics_config def test_C3510642_Terrain_NotCollideWithTerrain(self, request, workspace, editor, launcher_platform): - from . import C3510642_Terrain_NotCollideWithTerrain as test_module + from .terrain import C3510642_Terrain_NotCollideWithTerrain as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C4976195_RigidBodies_InitialLinearVelocity(self, request, workspace, editor, launcher_platform): - from . import C4976195_RigidBodies_InitialLinearVelocity as test_module + from .rigid_body import C4976195_RigidBodies_InitialLinearVelocity as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C4976206_RigidBodies_GravityEnabledActive(self, request, workspace, editor, launcher_platform): - from . import C4976206_RigidBodies_GravityEnabledActive as test_module + from .rigid_body import C4976206_RigidBodies_GravityEnabledActive as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C4976207_PhysXRigidBodies_KinematicBehavior(self, request, workspace, editor, launcher_platform): - from . import C4976207_PhysXRigidBodies_KinematicBehavior as test_module + from .rigid_body import C4976207_PhysXRigidBodies_KinematicBehavior as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C5932042_PhysXForceRegion_LinearDamping(self, request, workspace, editor, launcher_platform): - from . import C5932042_PhysXForceRegion_LinearDamping as test_module + from .force_region import C5932042_PhysXForceRegion_LinearDamping as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C5932043_ForceRegion_SimpleDragOnRigidBodies(self, request, workspace, editor, launcher_platform): - from . import C5932043_ForceRegion_SimpleDragOnRigidBodies as test_module + from .force_region import C5932043_ForceRegion_SimpleDragOnRigidBodies as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C5959760_PhysXForceRegion_PointForceExertion(self, request, workspace, editor, launcher_platform): - from . import C5959760_PhysXForceRegion_PointForceExertion as test_module + from .force_region import C5959760_PhysXForceRegion_PointForceExertion as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C5959764_ForceRegion_ForceRegionImpulsesCapsule(self, request, workspace, editor, launcher_platform): - from . import C5959764_ForceRegion_ForceRegionImpulsesCapsule as test_module + from .force_region import C5959764_ForceRegion_ForceRegionImpulsesCapsule as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C5340400_RigidBody_ManualMomentOfInertia(self, request, workspace, editor, launcher_platform): - from . import C5340400_RigidBody_ManualMomentOfInertia as test_module + from .rigid_body import C5340400_RigidBody_ManualMomentOfInertia as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C4976210_COM_ManualSetting(self, request, workspace, editor, launcher_platform): - from . import C4976210_COM_ManualSetting as test_module + from .rigid_body import C4976210_COM_ManualSetting as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C4976194_RigidBody_PhysXComponentIsValid(self, request, workspace, editor, launcher_platform): - from . import C4976194_RigidBody_PhysXComponentIsValid as test_module + from .rigid_body import C4976194_RigidBody_PhysXComponentIsValid as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C5932045_ForceRegion_Spline(self, request, workspace, editor, launcher_platform): - from . import C5932045_ForceRegion_Spline as test_module + from .force_region import C5932045_ForceRegion_Spline as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config @fm.file_override('physxsystemconfiguration.setreg','C4044457_Material_RestitutionCombine.setreg_override', 'AutomatedTesting/Registry') def test_C4044457_Material_RestitutionCombine(self, request, workspace, editor, launcher_platform): - from . import C4044457_Material_RestitutionCombine as test_module + from .material import C4044457_Material_RestitutionCombine as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config @fm.file_override('physxsystemconfiguration.setreg','C4044456_Material_FrictionCombine.setreg_override', 'AutomatedTesting/Registry') def test_C4044456_Material_FrictionCombine(self, request, workspace, editor, launcher_platform): - from . import C4044456_Material_FrictionCombine as test_module + from .material import C4044456_Material_FrictionCombine as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C4982797_Collider_ColliderOffset(self, request, workspace, editor, launcher_platform): - from . import C4982797_Collider_ColliderOffset as test_module + from .collider import C4982797_Collider_ColliderOffset as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C4976200_RigidBody_AngularDampingObjectRotation(self, request, workspace, editor, launcher_platform): - from . import C4976200_RigidBody_AngularDampingObjectRotation as test_module + from .rigid_body import C4976200_RigidBody_AngularDampingObjectRotation as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C5689529_Verify_Terrain_RigidBody_Collider_Mesh(self, request, workspace, editor, launcher_platform): - from . import C5689529_Verify_Terrain_RigidBody_Collider_Mesh as test_module + from .general import C5689529_Verify_Terrain_RigidBody_Collider_Mesh as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C5959810_ForceRegion_ForceRegionCombinesForces(self, request, workspace, editor, launcher_platform): - from . import C5959810_ForceRegion_ForceRegionCombinesForces as test_module + from .force_region import C5959810_ForceRegion_ForceRegionCombinesForces as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C5959765_ForceRegion_AssetGetsImpulsed(self, request, workspace, editor, launcher_platform): - from . import C5959765_ForceRegion_AssetGetsImpulsed as test_module + from .force_region import C5959765_ForceRegion_AssetGetsImpulsed as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C6274125_ScriptCanvas_TriggerEvents(self, request, workspace, editor, launcher_platform): - from . import C6274125_ScriptCanvas_TriggerEvents as test_module + from .script_canvas import C6274125_ScriptCanvas_TriggerEvents as test_module # FIXME: expected_lines = test_module.LogLines.expected_lines self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C6090554_ForceRegion_PointForceNegative(self, request, workspace, editor, launcher_platform): - from . import C6090554_ForceRegion_PointForceNegative as test_module + from .force_region import C6090554_ForceRegion_PointForceNegative as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C6090550_ForceRegion_WorldSpaceForceNegative(self, request, workspace, editor, launcher_platform): - from . import C6090550_ForceRegion_WorldSpaceForceNegative as test_module + from .force_region import C6090550_ForceRegion_WorldSpaceForceNegative as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C6090552_ForceRegion_LinearDampingNegative(self, request, workspace, editor, launcher_platform): - from . import C6090552_ForceRegion_LinearDampingNegative as test_module + from .force_region import C6090552_ForceRegion_LinearDampingNegative as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C5968760_ForceRegion_CheckNetForceChange(self, request, workspace, editor, launcher_platform): - from . import C5968760_ForceRegion_CheckNetForceChange as test_module + from .force_region import C5968760_ForceRegion_CheckNetForceChange as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C12712452_ScriptCanvas_CollisionEvents(self, request, workspace, editor, launcher_platform): - from . import C12712452_ScriptCanvas_CollisionEvents as test_module + from .script_canvas import C12712452_ScriptCanvas_CollisionEvents as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C12868578_ForceRegion_DirectionHasNoAffectOnMagnitude(self, request, workspace, editor, launcher_platform): - from . import C12868578_ForceRegion_DirectionHasNoAffectOnMagnitude as test_module + from .force_region import C12868578_ForceRegion_DirectionHasNoAffectOnMagnitude as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C4976204_Verify_Start_Asleep_Condition(self, request, workspace, editor, launcher_platform): - from . import C4976204_Verify_Start_Asleep_Condition as test_module + from .rigid_body import C4976204_Verify_Start_Asleep_Condition as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C6090546_ForceRegion_SliceFileInstantiates(self, request, workspace, editor, launcher_platform): - from . import C6090546_ForceRegion_SliceFileInstantiates as test_module + from .force_region import C6090546_ForceRegion_SliceFileInstantiates as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C6090551_ForceRegion_LocalSpaceForceNegative(self, request, workspace, editor, launcher_platform): - from . import C6090551_ForceRegion_LocalSpaceForceNegative as test_module + from .force_region import C6090551_ForceRegion_LocalSpaceForceNegative as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C6090553_ForceRegion_SimpleDragForceOnRigidBodies(self, request, workspace, editor, launcher_platform): - from . import C6090553_ForceRegion_SimpleDragForceOnRigidBodies as test_module + from .force_region import C6090553_ForceRegion_SimpleDragForceOnRigidBodies as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C4976209_RigidBody_ComputesCOM(self, request, workspace, editor, launcher_platform): - from . import C4976209_RigidBody_ComputesCOM as test_module + from .rigid_body import C4976209_RigidBody_ComputesCOM as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C4976201_RigidBody_MassIsAssigned(self, request, workspace, editor, launcher_platform): - from . import C4976201_RigidBody_MassIsAssigned as test_module + from .rigid_body import C4976201_RigidBody_MassIsAssigned as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config @fm.file_override('physxsystemconfiguration.setreg','C18981526_Material_RestitutionCombinePriority.setreg_override', 'AutomatedTesting/Registry') def test_C18981526_Material_RestitutionCombinePriority(self, request, workspace, editor, launcher_platform): - from . import C18981526_Material_RestitutionCombinePriority as test_module + from .material import C18981526_Material_RestitutionCombinePriority as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C12868580_ForceRegion_SplineModifiedTransform(self, request, workspace, editor, launcher_platform): - from . import C12868580_ForceRegion_SplineModifiedTransform as test_module + from .force_region import C12868580_ForceRegion_SplineModifiedTransform as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C12712455_ScriptCanvas_ShapeCastVerification(self, request, workspace, editor, launcher_platform): - from . import C12712455_ScriptCanvas_ShapeCastVerification as test_module + from .script_canvas import C12712455_ScriptCanvas_ShapeCastVerification as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C4976197_RigidBodies_InitialAngularVelocity(self, request, workspace, editor, launcher_platform): - from . import C4976197_RigidBodies_InitialAngularVelocity as test_module + from .rigid_body import C4976197_RigidBodies_InitialAngularVelocity as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C6090555_ForceRegion_SplineFollowOnRigidBodies(self, request, workspace, editor, launcher_platform): - from . import C6090555_ForceRegion_SplineFollowOnRigidBodies as test_module + from .force_region import C6090555_ForceRegion_SplineFollowOnRigidBodies as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C6131473_StaticSlice_OnDynamicSliceSpawn(self, request, workspace, editor, launcher_platform): - from . import C6131473_StaticSlice_OnDynamicSliceSpawn as test_module + from .general import C6131473_StaticSlice_OnDynamicSliceSpawn as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C5959808_ForceRegion_PositionOffset(self, request, workspace, editor, launcher_platform): - from . import C5959808_ForceRegion_PositionOffset as test_module + from .force_region import C5959808_ForceRegion_PositionOffset as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config @fm.file_override('physxsystemconfiguration.setreg','C18977601_Material_FrictionCombinePriority.setreg_override', 'AutomatedTesting/Registry') def test_C18977601_Material_FrictionCombinePriority(self, request, workspace, editor, launcher_platform): - from . import C18977601_Material_FrictionCombinePriority as test_module + from .material import C18977601_Material_FrictionCombinePriority as test_module self._run_test(request, workspace, editor, test_module) @pytest.mark.xfail( reason="Something with the CryRenderer disabling is causing this test to fail now.") @revert_physics_config def test_C13895144_Ragdoll_ChangeLevel(self, request, workspace, editor, launcher_platform): - from . import C13895144_Ragdoll_ChangeLevel as test_module + from .ragdoll import C13895144_Ragdoll_ChangeLevel as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C5968759_ForceRegion_ExertsSeveralForcesOnRigidBody(self, request, workspace, editor, launcher_platform): - from . import C5968759_ForceRegion_ExertsSeveralForcesOnRigidBody as test_module + from .force_region import C5968759_ForceRegion_ExertsSeveralForcesOnRigidBody as test_module self._run_test(request, workspace, editor, test_module) # Marking the test as an expected failure due to sporadic failure on Automated Review: LYN-2580 @@ -252,96 +252,96 @@ class TestAutomation(TestAutomationBase): @revert_physics_config @fm.file_override('physxsystemconfiguration.setreg','C4044697_Material_PerfaceMaterialValidation.setreg_override', 'AutomatedTesting/Registry') def test_C4044697_Material_PerfaceMaterialValidation(self, request, workspace, editor, launcher_platform): - from . import C4044697_Material_PerfaceMaterialValidation as test_module + from .material import C4044697_Material_PerfaceMaterialValidation as test_module self._run_test(request, workspace, editor, test_module) @pytest.mark.xfail( reason="This test will sometimes fail as the ball will continue to roll before the timeout is reached.") @revert_physics_config def test_C4976202_RigidBody_StopsWhenBelowKineticThreshold(self, request, workspace, editor, launcher_platform): - from . import C4976202_RigidBody_StopsWhenBelowKineticThreshold as test_module + from .rigid_body import C4976202_RigidBody_StopsWhenBelowKineticThreshold as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C13351703_COM_NotIncludeTriggerShapes(self, request, workspace, editor, launcher_platform): - from . import C13351703_COM_NotIncludeTriggerShapes as test_module + from .rigid_body import C13351703_COM_NotIncludeTriggerShapes as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C5296614_PhysXMaterial_ColliderShape(self, request, workspace, editor, launcher_platform): - from . import C5296614_PhysXMaterial_ColliderShape as test_module + from .material import C5296614_PhysXMaterial_ColliderShape as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C4982595_Collider_TriggerDisablesCollision(self, request, workspace, editor, launcher_platform): - from . import C4982595_Collider_TriggerDisablesCollision as test_module + from .collider import C4982595_Collider_TriggerDisablesCollision as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C14976307_Gravity_SetGravityWorks(self, request, workspace, editor, launcher_platform): - from . import C14976307_Gravity_SetGravityWorks as test_module + from .general import C14976307_Gravity_SetGravityWorks as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config @fm.file_override('physxsystemconfiguration.setreg','C15556261_PhysXMaterials_CharacterControllerMaterialAssignment.setreg_override', 'AutomatedTesting/Registry') def test_C15556261_PhysXMaterials_CharacterControllerMaterialAssignment(self, request, workspace, editor, launcher_platform): - from . import C15556261_PhysXMaterials_CharacterControllerMaterialAssignment as test_module + from .material import C15556261_PhysXMaterials_CharacterControllerMaterialAssignment as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C4044694_Material_EmptyLibraryUsesDefault(self, request, workspace, editor, launcher_platform): - from . import C4044694_Material_EmptyLibraryUsesDefault as test_module + from .material import C4044694_Material_EmptyLibraryUsesDefault as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C15845879_ForceRegion_HighLinearDampingForce(self, request, workspace, editor, launcher_platform): - from . import C15845879_ForceRegion_HighLinearDampingForce as test_module + from .force_region import C15845879_ForceRegion_HighLinearDampingForce as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C4976218_RigidBodies_InertiaObjectsNotComputed(self, request, workspace, editor, launcher_platform): - from . import C4976218_RigidBodies_InertiaObjectsNotComputed as test_module + from .rigid_body import C4976218_RigidBodies_InertiaObjectsNotComputed as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C14902098_ScriptCanvas_PostPhysicsUpdate(self, request, workspace, editor, launcher_platform): - from . import C14902098_ScriptCanvas_PostPhysicsUpdate as test_module + from .script_canvas import C14902098_ScriptCanvas_PostPhysicsUpdate as test_module # Fixme: unexpected_lines = ["Assert"] + test_module.Lines.unexpected self._run_test(request, workspace, editor, test_module) @revert_physics_config @fm.file_override('physxsystemconfiguration.setreg','C4976245_PhysXCollider_CollisionLayerTest.setreg_override', 'AutomatedTesting/Registry') def test_C4976245_PhysXCollider_CollisionLayerTest(self, request, workspace, editor, launcher_platform): - from . import C4976245_PhysXCollider_CollisionLayerTest as test_module + from .collider import C4976245_PhysXCollider_CollisionLayerTest as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config @fm.file_override('physxsystemconfiguration.setreg','C4976244_Collider_SameGroupSameLayerCollision.setreg_override', 'AutomatedTesting/Registry') def test_C4976244_Collider_SameGroupSameLayerCollision(self, request, workspace, editor, launcher_platform): - from . import C4976244_Collider_SameGroupSameLayerCollision as test_module + from .collider import C4976244_Collider_SameGroupSameLayerCollision as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config @fm.file_override('physxdefaultsceneconfiguration.setreg','C14195074_ScriptCanvas_PostUpdateEvent.setreg_override', 'AutomatedTesting/Registry') def test_C14195074_ScriptCanvas_PostUpdateEvent(self, request, workspace, editor, launcher_platform): - from . import C14195074_ScriptCanvas_PostUpdateEvent as test_module + from .script_canvas import C14195074_ScriptCanvas_PostUpdateEvent as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config @fm.file_override('physxsystemconfiguration.setreg','C4044461_Material_Restitution.setreg_override', 'AutomatedTesting/Registry') def test_C4044461_Material_Restitution(self, request, workspace, editor, launcher_platform): - from . import C4044461_Material_Restitution as test_module + from .material import C4044461_Material_Restitution as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config @fm.file_override('physxdefaultsceneconfiguration.setreg','C14902097_ScriptCanvas_PreUpdateEvent.setreg_override', 'AutomatedTesting/Registry') def test_C14902097_ScriptCanvas_PreUpdateEvent(self, request, workspace, editor, launcher_platform): - from . import C14902097_ScriptCanvas_PreUpdateEvent as test_module + from .script_canvas import C14902097_ScriptCanvas_PreUpdateEvent as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C5959761_ForceRegion_PhysAssetExertsPointForce(self, request, workspace, editor, launcher_platform): - from . import C5959761_ForceRegion_PhysAssetExertsPointForce as test_module + from .force_region import C5959761_ForceRegion_PhysAssetExertsPointForce as test_module self._run_test(request, workspace, editor, test_module) # Marking the Test as expected to fail using the xfail decorator due to sporadic failure on Automated Review: SPEC-3146 @@ -349,138 +349,138 @@ class TestAutomation(TestAutomationBase): @pytest.mark.xfail(reason="Test Sporadically fails with message [ NOT FOUND ] Success: Bar1 : Expected angular velocity") @revert_physics_config def test_C13352089_RigidBodies_MaxAngularVelocity(self, request, workspace, editor, launcher_platform): - from . import C13352089_RigidBodies_MaxAngularVelocity as test_module + from .rigid_body import C13352089_RigidBodies_MaxAngularVelocity as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C18243584_Joints_HingeSoftLimitsConstrained(self, request, workspace, editor, launcher_platform): - from . import C18243584_Joints_HingeSoftLimitsConstrained as test_module + from .joints import C18243584_Joints_HingeSoftLimitsConstrained as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C18243589_Joints_BallSoftLimitsConstrained(self, request, workspace, editor, launcher_platform): - from . import C18243589_Joints_BallSoftLimitsConstrained as test_module + from .joints import C18243589_Joints_BallSoftLimitsConstrained as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C18243591_Joints_BallLeadFollowerCollide(self, request, workspace, editor, launcher_platform): - from . import C18243591_Joints_BallLeadFollowerCollide as test_module + from .joints import C18243591_Joints_BallLeadFollowerCollide as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config @fm.file_override('physxsystemconfiguration.setreg','C4976227_Collider_NewGroup.setreg_override', 'AutomatedTesting/Registry') def test_C4976227_Collider_NewGroup(self, request, workspace, editor, launcher_platform): - from . import C4976227_Collider_NewGroup as test_module + from .collider import C4976227_Collider_NewGroup as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C19578018_ShapeColliderWithNoShapeComponent(self, request, workspace, editor, launcher_platform): - from . import C19578018_ShapeColliderWithNoShapeComponent as test_module + from .collider import C19578018_ShapeColliderWithNoShapeComponent as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C14861500_DefaultSetting_ColliderShape(self, request, workspace, editor, launcher_platform): - from . import C14861500_DefaultSetting_ColliderShape as test_module + from .collider import C14861500_DefaultSetting_ColliderShape as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C19723164_ShapeCollider_WontCrashEditor(self, request, workspace, editor, launcher_platform): - from . import C19723164_ShapeColliders_WontCrashEditor as test_module + from .collider import C19723164_ShapeColliders_WontCrashEditor as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C4982800_PhysXColliderShape_CanBeSelected(self, request, workspace, editor, launcher_platform): - from . import C4982800_PhysXColliderShape_CanBeSelected as test_module + from .collider import C4982800_PhysXColliderShape_CanBeSelected as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C4982801_PhysXColliderShape_CanBeSelected(self, request, workspace, editor, launcher_platform): - from . import C4982801_PhysXColliderShape_CanBeSelected as test_module + from .collider import C4982801_PhysXColliderShape_CanBeSelected as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C4982802_PhysXColliderShape_CanBeSelected(self, request, workspace, editor, launcher_platform): - from . import C4982802_PhysXColliderShape_CanBeSelected as test_module + from .collider import C4982802_PhysXColliderShape_CanBeSelected as test_module self._run_test(request, workspace, editor, test_module) def test_C12905528_ForceRegion_WithNonTriggerCollider(self, request, workspace, editor, launcher_platform): - from . import C12905528_ForceRegion_WithNonTriggerCollider as test_module + from .force_region import C12905528_ForceRegion_WithNonTriggerCollider as test_module # Fixme: expected_lines = ["[Warning] (PhysX Force Region) - Please ensure collider component marked as trigger exists in entity"] self._run_test(request, workspace, editor, test_module) def test_C5932040_ForceRegion_CubeExertsWorldForce(self, request, workspace, editor, launcher_platform): - from . import C5932040_ForceRegion_CubeExertsWorldForce as test_module + from .force_region import C5932040_ForceRegion_CubeExertsWorldForce as test_module self._run_test(request, workspace, editor, test_module) def test_C5932044_ForceRegion_PointForceOnRigidBody(self, request, workspace, editor, launcher_platform): - from . import C5932044_ForceRegion_PointForceOnRigidBody as test_module + from .force_region import C5932044_ForceRegion_PointForceOnRigidBody as test_module self._run_test(request, workspace, editor, test_module) def test_C5959759_RigidBody_ForceRegionSpherePointForce(self, request, workspace, editor, launcher_platform): - from . import C5959759_RigidBody_ForceRegionSpherePointForce as test_module + from .force_region import C5959759_RigidBody_ForceRegionSpherePointForce as test_module self._run_test(request, workspace, editor, test_module) def test_C5959809_ForceRegion_RotationalOffset(self, request, workspace, editor, launcher_platform): - from . import C5959809_ForceRegion_RotationalOffset as test_module + from .force_region import C5959809_ForceRegion_RotationalOffset as test_module self._run_test(request, workspace, editor, test_module) def test_C15096740_Material_LibraryUpdatedCorrectly(self, request, workspace, editor, launcher_platform): - from . import C15096740_Material_LibraryUpdatedCorrectly as test_module + from .material import C15096740_Material_LibraryUpdatedCorrectly as test_module self._run_test(request, workspace, editor, test_module) def test_C4976236_AddPhysxColliderComponent(self, request, workspace, editor, launcher_platform): - from . import C4976236_AddPhysxColliderComponent as test_module + from .collider import C4976236_AddPhysxColliderComponent as test_module self._run_test(request, workspace, editor, test_module) @pytest.mark.xfail( reason="This will fail due to this issue ATOM-15487.") def test_C14861502_PhysXCollider_AssetAutoAssigned(self, request, workspace, editor, launcher_platform): - from . import C14861502_PhysXCollider_AssetAutoAssigned as test_module + from .collider import C14861502_PhysXCollider_AssetAutoAssigned as test_module self._run_test(request, workspace, editor, test_module) def test_C14861501_PhysXCollider_RenderMeshAutoAssigned(self, request, workspace, editor, launcher_platform): - from . import C14861501_PhysXCollider_RenderMeshAutoAssigned as test_module + from .collider import C14861501_PhysXCollider_RenderMeshAutoAssigned as test_module self._run_test(request, workspace, editor, test_module) def test_C4044695_PhysXCollider_AddMultipleSurfaceFbx(self, request, workspace, editor, launcher_platform): - from . import C4044695_PhysXCollider_AddMultipleSurfaceFbx as test_module + from .collider import C4044695_PhysXCollider_AddMultipleSurfaceFbx as test_module self._run_test(request, workspace, editor, test_module) def test_C14861504_RenderMeshAsset_WithNoPxAsset(self, request, workspace, editor, launcher_platform): - from . import C14861504_RenderMeshAsset_WithNoPxAsset as test_module + from .collider import C14861504_RenderMeshAsset_WithNoPxAsset as test_module self._run_test(request, workspace, editor, test_module) def test_C100000_RigidBody_EnablingGravityWorksPoC(self, request, workspace, editor, launcher_platform): - from . import C100000_RigidBody_EnablingGravityWorksPoC as test_module + from .collider import C100000_RigidBody_EnablingGravityWorksPoC as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config @fm.file_override('physxsystemconfiguration.setreg','C3510644_Collider_CollisionGroups.setreg_override', 'AutomatedTesting/Registry') def test_C3510644_Collider_CollisionGroups(self, request, workspace, editor, launcher_platform): - from . import C3510644_Collider_CollisionGroups as test_module + from .collider import C3510644_Collider_CollisionGroups as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C4982798_Collider_ColliderRotationOffset(self, request, workspace, editor, launcher_platform): - from . import C4982798_Collider_ColliderRotationOffset as test_module + from .collider import C4982798_Collider_ColliderRotationOffset as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C15308217_NoCrash_LevelSwitch(self, request, workspace, editor, launcher_platform): - from . import C15308217_NoCrash_LevelSwitch as test_module + from .terrain import C15308217_NoCrash_LevelSwitch as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C6090547_ForceRegion_ParentChildForceRegions(self, request, workspace, editor, launcher_platform): - from . import C6090547_ForceRegion_ParentChildForceRegions as test_module + from .force_region import C6090547_ForceRegion_ParentChildForceRegions as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C19578021_ShapeCollider_CanBeAdded(self, request, workspace, editor, launcher_platform): - from . import C19578021_ShapeCollider_CanBeAdded as test_module + from .collider import C19578021_ShapeCollider_CanBeAdded as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config def test_C15425929_Undo_Redo(self, request, workspace, editor, launcher_platform): - from . import C15425929_Undo_Redo as test_module + from .general import C15425929_Undo_Redo as test_module self._run_test(request, workspace, editor, test_module) diff --git a/AutomatedTesting/Gem/PythonTests/physics/TestSuite_Sandbox.py b/AutomatedTesting/Gem/PythonTests/physics/TestSuite_Sandbox.py index 255016ddd6..0346df2ebd 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/TestSuite_Sandbox.py +++ b/AutomatedTesting/Gem/PythonTests/physics/TestSuite_Sandbox.py @@ -12,7 +12,7 @@ import pytest import os import sys -from .FileManagement import FileManagement as fm +from .utils.FileManagement import FileManagement as fm from ly_test_tools import LAUNCHERS sys.path.append(os.path.dirname(os.path.abspath(__file__)) + '/../automatedtesting_shared') @@ -30,13 +30,13 @@ class TestAutomation(TestAutomationBase): ## Seems to be flaky, need to investigate def test_C19536274_GetCollisionName_PrintsName(self, request, workspace, editor, launcher_platform): - from . import C19536274_GetCollisionName_PrintsName as test_module + from .general import C19536274_GetCollisionName_PrintsName as test_module # Fixme: expected_lines=["Layer Name: Right"] self._run_test(request, workspace, editor, test_module) ## Seems to be flaky, need to investigate def test_C19536277_GetCollisionName_PrintsNothing(self, request, workspace, editor, launcher_platform): - from . import C19536277_GetCollisionName_PrintsNothing as test_module + from .general import C19536277_GetCollisionName_PrintsNothing as test_module # All groups present in the PhysX Collider that could show up in test # Fixme: collision_groups = ["All", "None", "All_NoTouchBend", "All_3", "None_1", "All_NoTouchBend_1", "All_2", "None_1_1", "All_NoTouchBend_1_1", "All_1", "None_1_1_1", "All_NoTouchBend_1_1_1", "All_4", "None_1_1_1_1", "All_NoTouchBend_1_1_1_1", "GroupLeft", "GroupRight"] # Fixme: for group in collision_groups: @@ -49,5 +49,5 @@ class TestAutomation(TestAutomationBase): reason="Editor crashes and errors about files accessed by multiple processes appear in the log.") @revert_physics_config def test_C15425929_Undo_Redo(self, request, workspace, editor, launcher_platform): - from . import C15425929_Undo_Redo as test_module + from .general import C15425929_Undo_Redo as test_module self._run_test(request, workspace, editor, test_module) diff --git a/AutomatedTesting/Gem/PythonTests/physics/TestSuite_Utils.py b/AutomatedTesting/Gem/PythonTests/physics/TestSuite_Utils.py index 9f4edba18b..a3fd5c741f 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/TestSuite_Utils.py +++ b/AutomatedTesting/Gem/PythonTests/physics/TestSuite_Utils.py @@ -29,14 +29,14 @@ class TestUtils(TestAutomationBase): :param request: Built in pytest object, and is needed to call the pytest "addfinalizer" teardown command. :editor: Fixture containing editor details """ - from . import UtilTest_Physmaterial_Editor as physmaterial_editor_test_module + from .utils import UtilTest_Physmaterial_Editor as physmaterial_editor_test_module expected_lines = [] unexpected_lines = ["Assert"] self._run_test(request, workspace, editor, physmaterial_editor_test_module, expected_lines, unexpected_lines) def test_UtilTest_Tracer_PicksErrorsAndWarnings(self, request, workspace, editor): - from . import UtilTest_Tracer_PicksErrorsAndWarnings as testcase_module + from .utils import UtilTest_Tracer_PicksErrorsAndWarnings as testcase_module self._run_test(request, workspace, editor, testcase_module, [], []) def test_FileManagement_FindingFiles(self, workspace): @@ -262,7 +262,7 @@ class TestUtils(TestAutomationBase): ) @fm.file_override("default.physxconfiguration", "UtilTest_PhysxConfig_Override.physxconfiguration") def test_UtilTest_Managed_Files(self, request, workspace, editor): - from . import UtilTest_Managed_Files as test_module + from .utils import UtilTest_Managed_Files as test_module expected_lines = [] unexpected_lines = ["Assert"] diff --git a/AutomatedTesting/Gem/PythonTests/physics/C14654881_CharacterController_SwitchLevels.py b/AutomatedTesting/Gem/PythonTests/physics/character_controller/C14654881_CharacterController_SwitchLevels.py old mode 100755 new mode 100644 similarity index 96% rename from AutomatedTesting/Gem/PythonTests/physics/C14654881_CharacterController_SwitchLevels.py rename to AutomatedTesting/Gem/PythonTests/physics/character_controller/C14654881_CharacterController_SwitchLevels.py index 975c5ee787..3976bcf25c --- a/AutomatedTesting/Gem/PythonTests/physics/C14654881_CharacterController_SwitchLevels.py +++ b/AutomatedTesting/Gem/PythonTests/physics/character_controller/C14654881_CharacterController_SwitchLevels.py @@ -53,11 +53,6 @@ def C14654881_CharacterController_SwitchLevels(): import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general @@ -93,8 +88,5 @@ def C14654881_CharacterController_SwitchLevels(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C14654881_CharacterController_SwitchLevels) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C100000_RigidBody_EnablingGravityWorksPoC.py b/AutomatedTesting/Gem/PythonTests/physics/collider/C100000_RigidBody_EnablingGravityWorksPoC.py old mode 100755 new mode 100644 similarity index 96% rename from AutomatedTesting/Gem/PythonTests/physics/C100000_RigidBody_EnablingGravityWorksPoC.py rename to AutomatedTesting/Gem/PythonTests/physics/collider/C100000_RigidBody_EnablingGravityWorksPoC.py index 58d92fd313..f3d3e02d8e --- a/AutomatedTesting/Gem/PythonTests/physics/C100000_RigidBody_EnablingGravityWorksPoC.py +++ b/AutomatedTesting/Gem/PythonTests/physics/collider/C100000_RigidBody_EnablingGravityWorksPoC.py @@ -25,11 +25,6 @@ class Tests(): def C100000_RigidBody_EnablingGravityWorksPoC(): import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -77,8 +72,5 @@ def C100000_RigidBody_EnablingGravityWorksPoC(): helper.exit_game_mode(Tests.exit_game_mode) if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C100000_RigidBody_EnablingGravityWorksPoC) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C111111_RigidBody_EnablingGravityWorksUsingNotificationsPoC.py b/AutomatedTesting/Gem/PythonTests/physics/collider/C111111_RigidBody_EnablingGravityWorksUsingNotificationsPoC.py old mode 100755 new mode 100644 similarity index 96% rename from AutomatedTesting/Gem/PythonTests/physics/C111111_RigidBody_EnablingGravityWorksUsingNotificationsPoC.py rename to AutomatedTesting/Gem/PythonTests/physics/collider/C111111_RigidBody_EnablingGravityWorksUsingNotificationsPoC.py index 77e8c73604..997ea8a5a6 --- a/AutomatedTesting/Gem/PythonTests/physics/C111111_RigidBody_EnablingGravityWorksUsingNotificationsPoC.py +++ b/AutomatedTesting/Gem/PythonTests/physics/collider/C111111_RigidBody_EnablingGravityWorksUsingNotificationsPoC.py @@ -24,11 +24,6 @@ def C111111_RigidBody_EnablingGravityWorksUsingNotificationsPoC(): # Setup path import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -84,8 +79,5 @@ def C111111_RigidBody_EnablingGravityWorksUsingNotificationsPoC(): helper.exit_game_mode(Tests.exit_game_mode) if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C111111_RigidBody_EnablingGravityWorksUsingNotificationsPoC) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C14861498_ConfirmError_NoPxMesh.py b/AutomatedTesting/Gem/PythonTests/physics/collider/C14861498_ConfirmError_NoPxMesh.py old mode 100755 new mode 100644 similarity index 95% rename from AutomatedTesting/Gem/PythonTests/physics/C14861498_ConfirmError_NoPxMesh.py rename to AutomatedTesting/Gem/PythonTests/physics/collider/C14861498_ConfirmError_NoPxMesh.py index 622f2aac35..731f114b8c --- a/AutomatedTesting/Gem/PythonTests/physics/C14861498_ConfirmError_NoPxMesh.py +++ b/AutomatedTesting/Gem/PythonTests/physics/collider/C14861498_ConfirmError_NoPxMesh.py @@ -48,11 +48,6 @@ def C14861498_ConfirmError_NoPxMesh(): """ import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper from editor_python_test_tools.utils import Tracer @@ -85,8 +80,5 @@ def C14861498_ConfirmError_NoPxMesh(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C14861498_ConfirmError_NoPxMesh) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C14861500_DefaultSetting_ColliderShape.py b/AutomatedTesting/Gem/PythonTests/physics/collider/C14861500_DefaultSetting_ColliderShape.py old mode 100755 new mode 100644 similarity index 95% rename from AutomatedTesting/Gem/PythonTests/physics/C14861500_DefaultSetting_ColliderShape.py rename to AutomatedTesting/Gem/PythonTests/physics/collider/C14861500_DefaultSetting_ColliderShape.py index 0827ee540a..aed856f530 --- a/AutomatedTesting/Gem/PythonTests/physics/C14861500_DefaultSetting_ColliderShape.py +++ b/AutomatedTesting/Gem/PythonTests/physics/collider/C14861500_DefaultSetting_ColliderShape.py @@ -40,9 +40,7 @@ def C14861500_DefaultSetting_ColliderShape(): :return: None """ # Helper Files - import ImportPathHelper as imports - imports.init() from editor_python_test_tools.editor_entity_utils import EditorEntity as Entity from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -70,8 +68,5 @@ def C14861500_DefaultSetting_ColliderShape(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C14861500_DefaultSetting_ColliderShape) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C14861501_PhysXCollider_RenderMeshAutoAssigned.py b/AutomatedTesting/Gem/PythonTests/physics/collider/C14861501_PhysXCollider_RenderMeshAutoAssigned.py old mode 100755 new mode 100644 similarity index 96% rename from AutomatedTesting/Gem/PythonTests/physics/C14861501_PhysXCollider_RenderMeshAutoAssigned.py rename to AutomatedTesting/Gem/PythonTests/physics/collider/C14861501_PhysXCollider_RenderMeshAutoAssigned.py index 1a4fe471a4..73c94a2dfb --- a/AutomatedTesting/Gem/PythonTests/physics/C14861501_PhysXCollider_RenderMeshAutoAssigned.py +++ b/AutomatedTesting/Gem/PythonTests/physics/collider/C14861501_PhysXCollider_RenderMeshAutoAssigned.py @@ -48,13 +48,11 @@ def C14861501_PhysXCollider_RenderMeshAutoAssigned(): import os # Helper Files - import ImportPathHelper as imports - imports.init() from editor_python_test_tools.editor_entity_utils import EditorEntity as Entity from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper - from asset_utils import Asset + from editor_python_test_tools.asset_utils import Asset # Asset paths STATIC_MESH = os.path.join("assets", "c14861501_physxcollider_rendermeshautoassigned", "spherebot", "r0-b_body.azmodel") @@ -91,8 +89,5 @@ def C14861501_PhysXCollider_RenderMeshAutoAssigned(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C14861501_PhysXCollider_RenderMeshAutoAssigned) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C14861502_PhysXCollider_AssetAutoAssigned.py b/AutomatedTesting/Gem/PythonTests/physics/collider/C14861502_PhysXCollider_AssetAutoAssigned.py old mode 100755 new mode 100644 similarity index 96% rename from AutomatedTesting/Gem/PythonTests/physics/C14861502_PhysXCollider_AssetAutoAssigned.py rename to AutomatedTesting/Gem/PythonTests/physics/collider/C14861502_PhysXCollider_AssetAutoAssigned.py index 490708007e..b8c0e4a529 --- a/AutomatedTesting/Gem/PythonTests/physics/C14861502_PhysXCollider_AssetAutoAssigned.py +++ b/AutomatedTesting/Gem/PythonTests/physics/collider/C14861502_PhysXCollider_AssetAutoAssigned.py @@ -47,13 +47,11 @@ def C14861502_PhysXCollider_AssetAutoAssigned(): import os # Helper Files - import ImportPathHelper as imports - imports.init() from editor_python_test_tools.editor_entity_utils import EditorEntity as Entity from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper - from asset_utils import Asset + from editor_python_test_tools.asset_utils import Asset # Open 3D Engine Imports import azlmbr.legacy.general as general @@ -93,8 +91,5 @@ def C14861502_PhysXCollider_AssetAutoAssigned(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C14861502_PhysXCollider_AssetAutoAssigned) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C14861504_RenderMeshAsset_WithNoPxAsset.py b/AutomatedTesting/Gem/PythonTests/physics/collider/C14861504_RenderMeshAsset_WithNoPxAsset.py old mode 100755 new mode 100644 similarity index 95% rename from AutomatedTesting/Gem/PythonTests/physics/C14861504_RenderMeshAsset_WithNoPxAsset.py rename to AutomatedTesting/Gem/PythonTests/physics/collider/C14861504_RenderMeshAsset_WithNoPxAsset.py index 589245e884..1a63f478fd --- a/AutomatedTesting/Gem/PythonTests/physics/C14861504_RenderMeshAsset_WithNoPxAsset.py +++ b/AutomatedTesting/Gem/PythonTests/physics/collider/C14861504_RenderMeshAsset_WithNoPxAsset.py @@ -22,7 +22,7 @@ class Tests(): # fmt: on -def run(): +def C14861504_RenderMeshAsset_WithNoPxAsset(): """ Summary: Create entity with Mesh component and assign a render mesh that has no physics asset to the Mesh component. @@ -52,14 +52,12 @@ def run(): import os # Helper Files - import ImportPathHelper as imports - imports.init() from editor_python_test_tools.editor_entity_utils import EditorEntity as Entity from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper from editor_python_test_tools.utils import Tracer - from asset_utils import Asset + from editor_python_test_tools.asset_utils import Asset # Open 3D Engine Imports import azlmbr.asset as azasset @@ -102,4 +100,5 @@ def run(): if __name__ == "__main__": - run() + from editor_python_test_tools.utils import Report + Report.start_test(C14861504_RenderMeshAsset_WithNoPxAsset) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C19578018_ShapeColliderWithNoShapeComponent.py b/AutomatedTesting/Gem/PythonTests/physics/collider/C19578018_ShapeColliderWithNoShapeComponent.py old mode 100755 new mode 100644 similarity index 96% rename from AutomatedTesting/Gem/PythonTests/physics/C19578018_ShapeColliderWithNoShapeComponent.py rename to AutomatedTesting/Gem/PythonTests/physics/collider/C19578018_ShapeColliderWithNoShapeComponent.py index 478910e56c..3da42eb40f --- a/AutomatedTesting/Gem/PythonTests/physics/C19578018_ShapeColliderWithNoShapeComponent.py +++ b/AutomatedTesting/Gem/PythonTests/physics/collider/C19578018_ShapeColliderWithNoShapeComponent.py @@ -47,9 +47,7 @@ def C19578018_ShapeColliderWithNoShapeComponent(): """ # Built-in Imports - import ImportPathHelper as imports - imports.init() # Helper Imports from editor_python_test_tools.utils import Report @@ -92,8 +90,5 @@ def C19578018_ShapeColliderWithNoShapeComponent(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C19578018_ShapeColliderWithNoShapeComponent) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C19578021_ShapeCollider_CanBeAdded.py b/AutomatedTesting/Gem/PythonTests/physics/collider/C19578021_ShapeCollider_CanBeAdded.py old mode 100755 new mode 100644 similarity index 96% rename from AutomatedTesting/Gem/PythonTests/physics/C19578021_ShapeCollider_CanBeAdded.py rename to AutomatedTesting/Gem/PythonTests/physics/collider/C19578021_ShapeCollider_CanBeAdded.py index cf5aac6e98..0ec9908f2d --- a/AutomatedTesting/Gem/PythonTests/physics/C19578021_ShapeCollider_CanBeAdded.py +++ b/AutomatedTesting/Gem/PythonTests/physics/collider/C19578021_ShapeCollider_CanBeAdded.py @@ -44,9 +44,7 @@ def C19578021_ShapeCollider_CanBeAdded(): :return: None """ # Helper Files - import ImportPathHelper as imports - imports.init() from editor_python_test_tools.editor_entity_utils import EditorEntity as Entity from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -90,8 +88,5 @@ def C19578021_ShapeCollider_CanBeAdded(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C19578021_ShapeCollider_CanBeAdded) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C19723164_ShapeColliders_WontCrashEditor.py b/AutomatedTesting/Gem/PythonTests/physics/collider/C19723164_ShapeColliders_WontCrashEditor.py old mode 100755 new mode 100644 similarity index 96% rename from AutomatedTesting/Gem/PythonTests/physics/C19723164_ShapeColliders_WontCrashEditor.py rename to AutomatedTesting/Gem/PythonTests/physics/collider/C19723164_ShapeColliders_WontCrashEditor.py index f6f21a5322..7d277a734d --- a/AutomatedTesting/Gem/PythonTests/physics/C19723164_ShapeColliders_WontCrashEditor.py +++ b/AutomatedTesting/Gem/PythonTests/physics/collider/C19723164_ShapeColliders_WontCrashEditor.py @@ -40,9 +40,7 @@ def C19723164_ShapeColliders_WontCrashEditor(): :return: None """ # Helper Files - import ImportPathHelper as imports - imports.init() from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper from editor_python_test_tools.editor_entity_utils import EditorEntity as Entity @@ -96,8 +94,5 @@ def C19723164_ShapeColliders_WontCrashEditor(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C19723164_ShapeColliders_WontCrashEditor) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C24308873_CylinderShapeCollider_CollidesWithPhysXTerrain.py b/AutomatedTesting/Gem/PythonTests/physics/collider/C24308873_CylinderShapeCollider_CollidesWithPhysXTerrain.py old mode 100755 new mode 100644 similarity index 97% rename from AutomatedTesting/Gem/PythonTests/physics/C24308873_CylinderShapeCollider_CollidesWithPhysXTerrain.py rename to AutomatedTesting/Gem/PythonTests/physics/collider/C24308873_CylinderShapeCollider_CollidesWithPhysXTerrain.py index 9258cf8547..9094ba68c6 --- a/AutomatedTesting/Gem/PythonTests/physics/C24308873_CylinderShapeCollider_CollidesWithPhysXTerrain.py +++ b/AutomatedTesting/Gem/PythonTests/physics/collider/C24308873_CylinderShapeCollider_CollidesWithPhysXTerrain.py @@ -51,9 +51,7 @@ def C24308873_CylinderShapeCollider_CollidesWithPhysXTerrain(): import os import sys - import ImportPathHelper as imports - imports.init() from editor_python_test_tools.editor_entity_utils import EditorEntity import azlmbr.legacy.general as general import azlmbr.bus @@ -134,8 +132,5 @@ def C24308873_CylinderShapeCollider_CollidesWithPhysXTerrain(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C24308873_CylinderShapeCollider_CollidesWithPhysXTerrain) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C3510644_Collider_CollisionGroups.py b/AutomatedTesting/Gem/PythonTests/physics/collider/C3510644_Collider_CollisionGroups.py old mode 100755 new mode 100644 similarity index 99% rename from AutomatedTesting/Gem/PythonTests/physics/C3510644_Collider_CollisionGroups.py rename to AutomatedTesting/Gem/PythonTests/physics/collider/C3510644_Collider_CollisionGroups.py index e41aecf4fe..28638cc2a6 --- a/AutomatedTesting/Gem/PythonTests/physics/C3510644_Collider_CollisionGroups.py +++ b/AutomatedTesting/Gem/PythonTests/physics/collider/C3510644_Collider_CollisionGroups.py @@ -90,11 +90,6 @@ def C3510644_Collider_CollisionGroups(): import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -362,8 +357,5 @@ def C3510644_Collider_CollisionGroups(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C3510644_Collider_CollisionGroups) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4044695_PhysXCollider_AddMultipleSurfaceFbx.py b/AutomatedTesting/Gem/PythonTests/physics/collider/C4044695_PhysXCollider_AddMultipleSurfaceFbx.py old mode 100755 new mode 100644 similarity index 97% rename from AutomatedTesting/Gem/PythonTests/physics/C4044695_PhysXCollider_AddMultipleSurfaceFbx.py rename to AutomatedTesting/Gem/PythonTests/physics/collider/C4044695_PhysXCollider_AddMultipleSurfaceFbx.py index 538f28ff36..cfe6f3962c --- a/AutomatedTesting/Gem/PythonTests/physics/C4044695_PhysXCollider_AddMultipleSurfaceFbx.py +++ b/AutomatedTesting/Gem/PythonTests/physics/collider/C4044695_PhysXCollider_AddMultipleSurfaceFbx.py @@ -48,13 +48,11 @@ def C4044695_PhysXCollider_AddMultipleSurfaceFbx(): import os # Helper Files - import ImportPathHelper as imports - imports.init() from editor_python_test_tools.editor_entity_utils import EditorEntity as Entity from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper - from asset_utils import Asset + from editor_python_test_tools.asset_utils import Asset # Constants PHYSICS_ASSET_INDEX = 7 # Hardcoded enum index value for Shape property @@ -107,8 +105,5 @@ def C4044695_PhysXCollider_AddMultipleSurfaceFbx(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C4044695_PhysXCollider_AddMultipleSurfaceFbx) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4976227_Collider_NewGroup.py b/AutomatedTesting/Gem/PythonTests/physics/collider/C4976227_Collider_NewGroup.py old mode 100755 new mode 100644 similarity index 95% rename from AutomatedTesting/Gem/PythonTests/physics/C4976227_Collider_NewGroup.py rename to AutomatedTesting/Gem/PythonTests/physics/collider/C4976227_Collider_NewGroup.py index e123067f54..e9704d6be5 --- a/AutomatedTesting/Gem/PythonTests/physics/C4976227_Collider_NewGroup.py +++ b/AutomatedTesting/Gem/PythonTests/physics/collider/C4976227_Collider_NewGroup.py @@ -51,11 +51,6 @@ def C4976227_Collider_NewGroup(): import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -84,8 +79,5 @@ def C4976227_Collider_NewGroup(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C4976227_Collider_NewGroup) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4976236_AddPhysxColliderComponent.py b/AutomatedTesting/Gem/PythonTests/physics/collider/C4976236_AddPhysxColliderComponent.py old mode 100755 new mode 100644 similarity index 95% rename from AutomatedTesting/Gem/PythonTests/physics/C4976236_AddPhysxColliderComponent.py rename to AutomatedTesting/Gem/PythonTests/physics/collider/C4976236_AddPhysxColliderComponent.py index d4b7d85169..e4341bb148 --- a/AutomatedTesting/Gem/PythonTests/physics/C4976236_AddPhysxColliderComponent.py +++ b/AutomatedTesting/Gem/PythonTests/physics/collider/C4976236_AddPhysxColliderComponent.py @@ -42,14 +42,12 @@ def C4976236_AddPhysxColliderComponent(): """ # Helper file Imports - import ImportPathHelper as imports - imports.init() from editor_python_test_tools.editor_entity_utils import EditorEntity from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper from editor_python_test_tools.utils import Tracer - from asset_utils import Asset + from editor_python_test_tools.asset_utils import Asset helper.init_idle() # 1) Load the level @@ -84,8 +82,5 @@ def C4976236_AddPhysxColliderComponent(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C4976236_AddPhysxColliderComponent) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4976242_Collision_SameCollisionlayerSameCollisiongroup.py b/AutomatedTesting/Gem/PythonTests/physics/collider/C4976242_Collision_SameCollisionlayerSameCollisiongroup.py old mode 100755 new mode 100644 similarity index 98% rename from AutomatedTesting/Gem/PythonTests/physics/C4976242_Collision_SameCollisionlayerSameCollisiongroup.py rename to AutomatedTesting/Gem/PythonTests/physics/collider/C4976242_Collision_SameCollisionlayerSameCollisiongroup.py index 86dd81a6de..86ef5b6ed4 --- a/AutomatedTesting/Gem/PythonTests/physics/C4976242_Collision_SameCollisionlayerSameCollisiongroup.py +++ b/AutomatedTesting/Gem/PythonTests/physics/collider/C4976242_Collision_SameCollisionlayerSameCollisiongroup.py @@ -62,11 +62,6 @@ def C4976242_Collision_SameCollisionlayerSameCollisiongroup(): import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -188,8 +183,5 @@ def C4976242_Collision_SameCollisionlayerSameCollisiongroup(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C4976242_Collision_SameCollisionlayerSameCollisiongroup) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4976243_Collision_SameCollisionGroupDiffCollisionLayers.py b/AutomatedTesting/Gem/PythonTests/physics/collider/C4976243_Collision_SameCollisionGroupDiffCollisionLayers.py old mode 100755 new mode 100644 similarity index 97% rename from AutomatedTesting/Gem/PythonTests/physics/C4976243_Collision_SameCollisionGroupDiffCollisionLayers.py rename to AutomatedTesting/Gem/PythonTests/physics/collider/C4976243_Collision_SameCollisionGroupDiffCollisionLayers.py index f1a646e964..893d0d06f6 --- a/AutomatedTesting/Gem/PythonTests/physics/C4976243_Collision_SameCollisionGroupDiffCollisionLayers.py +++ b/AutomatedTesting/Gem/PythonTests/physics/collider/C4976243_Collision_SameCollisionGroupDiffCollisionLayers.py @@ -66,11 +66,6 @@ def C4976243_Collision_SameCollisionGroupDiffCollisionLayers(): import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -127,8 +122,5 @@ def C4976243_Collision_SameCollisionGroupDiffCollisionLayers(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C4976243_Collision_SameCollisionGroupDiffCollisionLayers) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4976244_Collider_SameGroupSameLayerCollision.py b/AutomatedTesting/Gem/PythonTests/physics/collider/C4976244_Collider_SameGroupSameLayerCollision.py old mode 100755 new mode 100644 similarity index 98% rename from AutomatedTesting/Gem/PythonTests/physics/C4976244_Collider_SameGroupSameLayerCollision.py rename to AutomatedTesting/Gem/PythonTests/physics/collider/C4976244_Collider_SameGroupSameLayerCollision.py index 1d1f0aba35..44ea29de76 --- a/AutomatedTesting/Gem/PythonTests/physics/C4976244_Collider_SameGroupSameLayerCollision.py +++ b/AutomatedTesting/Gem/PythonTests/physics/collider/C4976244_Collider_SameGroupSameLayerCollision.py @@ -62,11 +62,6 @@ def C4976244_Collider_SameGroupSameLayerCollision(): import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -185,8 +180,5 @@ def C4976244_Collider_SameGroupSameLayerCollision(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C4976244_Collider_SameGroupSameLayerCollision) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4976245_PhysXCollider_CollisionLayerTest.py b/AutomatedTesting/Gem/PythonTests/physics/collider/C4976245_PhysXCollider_CollisionLayerTest.py old mode 100755 new mode 100644 similarity index 98% rename from AutomatedTesting/Gem/PythonTests/physics/C4976245_PhysXCollider_CollisionLayerTest.py rename to AutomatedTesting/Gem/PythonTests/physics/collider/C4976245_PhysXCollider_CollisionLayerTest.py index 9d2c6f5fb4..a7c9152744 --- a/AutomatedTesting/Gem/PythonTests/physics/C4976245_PhysXCollider_CollisionLayerTest.py +++ b/AutomatedTesting/Gem/PythonTests/physics/collider/C4976245_PhysXCollider_CollisionLayerTest.py @@ -67,11 +67,6 @@ def C4976245_PhysXCollider_CollisionLayerTest(): import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general @@ -223,8 +218,5 @@ def C4976245_PhysXCollider_CollisionLayerTest(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C4976245_PhysXCollider_CollisionLayerTest) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4982593_PhysXCollider_CollisionLayerTest.py b/AutomatedTesting/Gem/PythonTests/physics/collider/C4982593_PhysXCollider_CollisionLayerTest.py old mode 100755 new mode 100644 similarity index 98% rename from AutomatedTesting/Gem/PythonTests/physics/C4982593_PhysXCollider_CollisionLayerTest.py rename to AutomatedTesting/Gem/PythonTests/physics/collider/C4982593_PhysXCollider_CollisionLayerTest.py index 500515f707..3fdb9d3403 --- a/AutomatedTesting/Gem/PythonTests/physics/C4982593_PhysXCollider_CollisionLayerTest.py +++ b/AutomatedTesting/Gem/PythonTests/physics/collider/C4982593_PhysXCollider_CollisionLayerTest.py @@ -67,11 +67,6 @@ def C4982593_PhysXCollider_CollisionLayerTest(): import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general @@ -231,8 +226,5 @@ def C4982593_PhysXCollider_CollisionLayerTest(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C4982593_PhysXCollider_CollisionLayerTest) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4982595_Collider_TriggerDisablesCollision.py b/AutomatedTesting/Gem/PythonTests/physics/collider/C4982595_Collider_TriggerDisablesCollision.py old mode 100755 new mode 100644 similarity index 99% rename from AutomatedTesting/Gem/PythonTests/physics/C4982595_Collider_TriggerDisablesCollision.py rename to AutomatedTesting/Gem/PythonTests/physics/collider/C4982595_Collider_TriggerDisablesCollision.py index 23e43cd741..d3b0faa6d4 --- a/AutomatedTesting/Gem/PythonTests/physics/C4982595_Collider_TriggerDisablesCollision.py +++ b/AutomatedTesting/Gem/PythonTests/physics/collider/C4982595_Collider_TriggerDisablesCollision.py @@ -75,11 +75,6 @@ def C4982595_Collider_TriggerDisablesCollision(): # Setup path import os import sys - - import ImportPathHelper as imports - - imports.init() - import azlmbr.legacy.general as general import azlmbr.bus import azlmbr.components @@ -234,8 +229,5 @@ def C4982595_Collider_TriggerDisablesCollision(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C4982595_Collider_TriggerDisablesCollision) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4982797_Collider_ColliderOffset.py b/AutomatedTesting/Gem/PythonTests/physics/collider/C4982797_Collider_ColliderOffset.py old mode 100755 new mode 100644 similarity index 99% rename from AutomatedTesting/Gem/PythonTests/physics/C4982797_Collider_ColliderOffset.py rename to AutomatedTesting/Gem/PythonTests/physics/collider/C4982797_Collider_ColliderOffset.py index 9ede25e5a0..d4d8ab15fd --- a/AutomatedTesting/Gem/PythonTests/physics/C4982797_Collider_ColliderOffset.py +++ b/AutomatedTesting/Gem/PythonTests/physics/collider/C4982797_Collider_ColliderOffset.py @@ -87,9 +87,7 @@ def C4982797_Collider_ColliderOffset(): import sys # Internal editor imports - import ImportPathHelper as imports - imports.init() from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -332,8 +330,5 @@ def C4982797_Collider_ColliderOffset(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C4982797_Collider_ColliderOffset) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4982798_Collider_ColliderRotationOffset.py b/AutomatedTesting/Gem/PythonTests/physics/collider/C4982798_Collider_ColliderRotationOffset.py old mode 100755 new mode 100644 similarity index 99% rename from AutomatedTesting/Gem/PythonTests/physics/C4982798_Collider_ColliderRotationOffset.py rename to AutomatedTesting/Gem/PythonTests/physics/collider/C4982798_Collider_ColliderRotationOffset.py index c0bc208d48..8368b9a66f --- a/AutomatedTesting/Gem/PythonTests/physics/C4982798_Collider_ColliderRotationOffset.py +++ b/AutomatedTesting/Gem/PythonTests/physics/collider/C4982798_Collider_ColliderRotationOffset.py @@ -86,9 +86,7 @@ def C4982798_Collider_ColliderRotationOffset(): :return: None """ - import ImportPathHelper as imports - imports.init() # Internal editor imports @@ -300,8 +298,5 @@ def C4982798_Collider_ColliderRotationOffset(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C4982798_Collider_ColliderRotationOffset) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4982800_PhysXColliderShape_CanBeSelected.py b/AutomatedTesting/Gem/PythonTests/physics/collider/C4982800_PhysXColliderShape_CanBeSelected.py old mode 100755 new mode 100644 similarity index 96% rename from AutomatedTesting/Gem/PythonTests/physics/C4982800_PhysXColliderShape_CanBeSelected.py rename to AutomatedTesting/Gem/PythonTests/physics/collider/C4982800_PhysXColliderShape_CanBeSelected.py index abfa6c44a1..0f1b9c6070 --- a/AutomatedTesting/Gem/PythonTests/physics/C4982800_PhysXColliderShape_CanBeSelected.py +++ b/AutomatedTesting/Gem/PythonTests/physics/collider/C4982800_PhysXColliderShape_CanBeSelected.py @@ -43,9 +43,7 @@ def C4982800_PhysXColliderShape_CanBeSelected(): :return: None """ # Helper Files - import ImportPathHelper as imports - imports.init() from editor_python_test_tools.editor_entity_utils import EditorEntity as Entity from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -91,8 +89,5 @@ def C4982800_PhysXColliderShape_CanBeSelected(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C4982800_PhysXColliderShape_CanBeSelected) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4982801_PhysXColliderShape_CanBeSelected.py b/AutomatedTesting/Gem/PythonTests/physics/collider/C4982801_PhysXColliderShape_CanBeSelected.py old mode 100755 new mode 100644 similarity index 97% rename from AutomatedTesting/Gem/PythonTests/physics/C4982801_PhysXColliderShape_CanBeSelected.py rename to AutomatedTesting/Gem/PythonTests/physics/collider/C4982801_PhysXColliderShape_CanBeSelected.py index 0d5aa39941..33b7dc0b48 --- a/AutomatedTesting/Gem/PythonTests/physics/C4982801_PhysXColliderShape_CanBeSelected.py +++ b/AutomatedTesting/Gem/PythonTests/physics/collider/C4982801_PhysXColliderShape_CanBeSelected.py @@ -43,9 +43,7 @@ def C4982801_PhysXColliderShape_CanBeSelected(): :return: None """ # Helper Files - import ImportPathHelper as imports - imports.init() from editor_python_test_tools.editor_entity_utils import EditorEntity as Entity from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -103,8 +101,5 @@ def C4982801_PhysXColliderShape_CanBeSelected(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C4982801_PhysXColliderShape_CanBeSelected) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4982802_PhysXColliderShape_CanBeSelected.py b/AutomatedTesting/Gem/PythonTests/physics/collider/C4982802_PhysXColliderShape_CanBeSelected.py old mode 100755 new mode 100644 similarity index 97% rename from AutomatedTesting/Gem/PythonTests/physics/C4982802_PhysXColliderShape_CanBeSelected.py rename to AutomatedTesting/Gem/PythonTests/physics/collider/C4982802_PhysXColliderShape_CanBeSelected.py index 7eec3b070a..4881c5b9a0 --- a/AutomatedTesting/Gem/PythonTests/physics/C4982802_PhysXColliderShape_CanBeSelected.py +++ b/AutomatedTesting/Gem/PythonTests/physics/collider/C4982802_PhysXColliderShape_CanBeSelected.py @@ -43,9 +43,7 @@ def C4982802_PhysXColliderShape_CanBeSelected(): :return: None """ # Helper Files - import ImportPathHelper as imports - imports.init() from editor_python_test_tools.editor_entity_utils import EditorEntity as Entity from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -103,8 +101,5 @@ def C4982802_PhysXColliderShape_CanBeSelected(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C4982802_PhysXColliderShape_CanBeSelected) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4982803_Enable_PxMesh_Option.py b/AutomatedTesting/Gem/PythonTests/physics/collider/C4982803_Enable_PxMesh_Option.py old mode 100755 new mode 100644 similarity index 97% rename from AutomatedTesting/Gem/PythonTests/physics/C4982803_Enable_PxMesh_Option.py rename to AutomatedTesting/Gem/PythonTests/physics/collider/C4982803_Enable_PxMesh_Option.py index 340b9c7785..7497ae8253 --- a/AutomatedTesting/Gem/PythonTests/physics/C4982803_Enable_PxMesh_Option.py +++ b/AutomatedTesting/Gem/PythonTests/physics/collider/C4982803_Enable_PxMesh_Option.py @@ -57,13 +57,11 @@ def C4982803_Enable_PxMesh_Option(): import os # Helper Files - import ImportPathHelper as imports - imports.init() from editor_python_test_tools.editor_entity_utils import EditorEntity from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper - from asset_utils import Asset + from editor_python_test_tools.asset_utils import Asset import azlmbr.math as math # Open 3D Engine Imports @@ -141,8 +139,5 @@ def C4982803_Enable_PxMesh_Option(): helper.exit_game_mode(Tests.exit_game_mode) if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C4982803_Enable_PxMesh_Option) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C12868578_ForceRegion_DirectionHasNoAffectOnMagnitude.py b/AutomatedTesting/Gem/PythonTests/physics/force_region/C12868578_ForceRegion_DirectionHasNoAffectOnMagnitude.py old mode 100755 new mode 100644 similarity index 99% rename from AutomatedTesting/Gem/PythonTests/physics/C12868578_ForceRegion_DirectionHasNoAffectOnMagnitude.py rename to AutomatedTesting/Gem/PythonTests/physics/force_region/C12868578_ForceRegion_DirectionHasNoAffectOnMagnitude.py index aae57cffc8..11488b14c2 --- a/AutomatedTesting/Gem/PythonTests/physics/C12868578_ForceRegion_DirectionHasNoAffectOnMagnitude.py +++ b/AutomatedTesting/Gem/PythonTests/physics/force_region/C12868578_ForceRegion_DirectionHasNoAffectOnMagnitude.py @@ -86,11 +86,6 @@ def C12868578_ForceRegion_DirectionHasNoAffectOnMagnitude(): """ import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -283,8 +278,5 @@ def C12868578_ForceRegion_DirectionHasNoAffectOnMagnitude(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C12868578_ForceRegion_DirectionHasNoAffectOnMagnitude) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C12868580_ForceRegion_SplineModifiedTransform.py b/AutomatedTesting/Gem/PythonTests/physics/force_region/C12868580_ForceRegion_SplineModifiedTransform.py old mode 100755 new mode 100644 similarity index 98% rename from AutomatedTesting/Gem/PythonTests/physics/C12868580_ForceRegion_SplineModifiedTransform.py rename to AutomatedTesting/Gem/PythonTests/physics/force_region/C12868580_ForceRegion_SplineModifiedTransform.py index f21dde6ae0..4e052a1b00 --- a/AutomatedTesting/Gem/PythonTests/physics/C12868580_ForceRegion_SplineModifiedTransform.py +++ b/AutomatedTesting/Gem/PythonTests/physics/force_region/C12868580_ForceRegion_SplineModifiedTransform.py @@ -73,12 +73,6 @@ def C12868580_ForceRegion_SplineModifiedTransform(): """ import os import sys - - import ImportPathHelper as imports - - imports.init() - - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -168,8 +162,5 @@ def C12868580_ForceRegion_SplineModifiedTransform(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C12868580_ForceRegion_SplineModifiedTransform) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C12905527_ForceRegion_MagnitudeDeviation.py b/AutomatedTesting/Gem/PythonTests/physics/force_region/C12905527_ForceRegion_MagnitudeDeviation.py old mode 100755 new mode 100644 similarity index 97% rename from AutomatedTesting/Gem/PythonTests/physics/C12905527_ForceRegion_MagnitudeDeviation.py rename to AutomatedTesting/Gem/PythonTests/physics/force_region/C12905527_ForceRegion_MagnitudeDeviation.py index 6df2d545da..c9d411b873 --- a/AutomatedTesting/Gem/PythonTests/physics/C12905527_ForceRegion_MagnitudeDeviation.py +++ b/AutomatedTesting/Gem/PythonTests/physics/force_region/C12905527_ForceRegion_MagnitudeDeviation.py @@ -54,12 +54,6 @@ def C12905527_ForceRegion_MagnitudeDeviation(): """ import os import sys - - import ImportPathHelper as imports - - imports.init() - - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -144,8 +138,5 @@ def C12905527_ForceRegion_MagnitudeDeviation(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C12905527_ForceRegion_MagnitudeDeviation) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C12905528_ForceRegion_WithNonTriggerCollider.py b/AutomatedTesting/Gem/PythonTests/physics/force_region/C12905528_ForceRegion_WithNonTriggerCollider.py old mode 100755 new mode 100644 similarity index 89% rename from AutomatedTesting/Gem/PythonTests/physics/C12905528_ForceRegion_WithNonTriggerCollider.py rename to AutomatedTesting/Gem/PythonTests/physics/force_region/C12905528_ForceRegion_WithNonTriggerCollider.py index ca5a29e182..93453b29c0 --- a/AutomatedTesting/Gem/PythonTests/physics/C12905528_ForceRegion_WithNonTriggerCollider.py +++ b/AutomatedTesting/Gem/PythonTests/physics/force_region/C12905528_ForceRegion_WithNonTriggerCollider.py @@ -19,7 +19,7 @@ class Tests(): # fmt: on -def run(): +def C12905528_ForceRegion_WithNonTriggerCollider(): """ Summary: Create entity with PhysX Force Region component. Check that user is warned if new PhysX Collider component is @@ -43,13 +43,10 @@ def run(): :return: None """ - # Helper file Imports - import ImportPathHelper as imports - + import azlmbr.legacy.general as general from editor_python_test_tools.editor_entity_utils import EditorEntity from editor_python_test_tools.utils import Report - imports.init() from editor_python_test_tools.utils import TestHelper as helper from editor_python_test_tools.utils import Tracer @@ -66,11 +63,14 @@ def run(): Report.result(Tests.add_physx_force_region, test_entity.has_component("PhysX Force Region")) # 4) Start the Tracer to catch any errors and warnings + Report.info("Starting warning monitoring") with Tracer() as section_tracer: # 5) Add the PhysX Collider component test_entity.add_component("PhysX Collider") Report.result(Tests.add_physx_collider, test_entity.has_component("PhysX Collider")) - + general.idle_wait_frames(1) + Report.info("Ending warning monitoring") + # ) Verify there is warning in the logs success_condition = section_tracer.has_warnings # Checking if warning exist and the exact warning is caught in the expected lines in Test file @@ -78,4 +78,5 @@ def run(): if __name__ == "__main__": - run() + from editor_python_test_tools.utils import Report + Report.start_test(C12905528_ForceRegion_WithNonTriggerCollider) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C15845879_ForceRegion_HighLinearDampingForce.py b/AutomatedTesting/Gem/PythonTests/physics/force_region/C15845879_ForceRegion_HighLinearDampingForce.py old mode 100755 new mode 100644 similarity index 98% rename from AutomatedTesting/Gem/PythonTests/physics/C15845879_ForceRegion_HighLinearDampingForce.py rename to AutomatedTesting/Gem/PythonTests/physics/force_region/C15845879_ForceRegion_HighLinearDampingForce.py index 1021186a9b..d4807476c2 --- a/AutomatedTesting/Gem/PythonTests/physics/C15845879_ForceRegion_HighLinearDampingForce.py +++ b/AutomatedTesting/Gem/PythonTests/physics/force_region/C15845879_ForceRegion_HighLinearDampingForce.py @@ -56,11 +56,6 @@ def C15845879_ForceRegion_HighLinearDampingForce(): """ import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -169,8 +164,5 @@ def C15845879_ForceRegion_HighLinearDampingForce(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C15845879_ForceRegion_HighLinearDampingForce) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5932040_ForceRegion_CubeExertsWorldForce.py b/AutomatedTesting/Gem/PythonTests/physics/force_region/C5932040_ForceRegion_CubeExertsWorldForce.py old mode 100755 new mode 100644 similarity index 98% rename from AutomatedTesting/Gem/PythonTests/physics/C5932040_ForceRegion_CubeExertsWorldForce.py rename to AutomatedTesting/Gem/PythonTests/physics/force_region/C5932040_ForceRegion_CubeExertsWorldForce.py index db3d4708ce..969a203502 --- a/AutomatedTesting/Gem/PythonTests/physics/C5932040_ForceRegion_CubeExertsWorldForce.py +++ b/AutomatedTesting/Gem/PythonTests/physics/force_region/C5932040_ForceRegion_CubeExertsWorldForce.py @@ -65,11 +65,6 @@ def C5932040_ForceRegion_CubeExertsWorldForce(): import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -183,8 +178,5 @@ def C5932040_ForceRegion_CubeExertsWorldForce(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C5932040_ForceRegion_CubeExertsWorldForce) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5932041_PhysXForceRegion_LocalSpaceForceOnRigidBodies.py b/AutomatedTesting/Gem/PythonTests/physics/force_region/C5932041_PhysXForceRegion_LocalSpaceForceOnRigidBodies.py old mode 100755 new mode 100644 similarity index 98% rename from AutomatedTesting/Gem/PythonTests/physics/C5932041_PhysXForceRegion_LocalSpaceForceOnRigidBodies.py rename to AutomatedTesting/Gem/PythonTests/physics/force_region/C5932041_PhysXForceRegion_LocalSpaceForceOnRigidBodies.py index 09965214b2..15c77ba17e --- a/AutomatedTesting/Gem/PythonTests/physics/C5932041_PhysXForceRegion_LocalSpaceForceOnRigidBodies.py +++ b/AutomatedTesting/Gem/PythonTests/physics/force_region/C5932041_PhysXForceRegion_LocalSpaceForceOnRigidBodies.py @@ -65,11 +65,6 @@ def C5932041_PhysXForceRegion_LocalSpaceForceOnRigidBodies(): """ import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -161,8 +156,5 @@ def C5932041_PhysXForceRegion_LocalSpaceForceOnRigidBodies(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C5932041_PhysXForceRegion_LocalSpaceForceOnRigidBodies) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5932042_PhysXForceRegion_LinearDamping.py b/AutomatedTesting/Gem/PythonTests/physics/force_region/C5932042_PhysXForceRegion_LinearDamping.py old mode 100755 new mode 100644 similarity index 99% rename from AutomatedTesting/Gem/PythonTests/physics/C5932042_PhysXForceRegion_LinearDamping.py rename to AutomatedTesting/Gem/PythonTests/physics/force_region/C5932042_PhysXForceRegion_LinearDamping.py index c05e71573f..5112729cc2 --- a/AutomatedTesting/Gem/PythonTests/physics/C5932042_PhysXForceRegion_LinearDamping.py +++ b/AutomatedTesting/Gem/PythonTests/physics/force_region/C5932042_PhysXForceRegion_LinearDamping.py @@ -71,11 +71,6 @@ def C5932042_PhysXForceRegion_LinearDamping(): import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -269,8 +264,5 @@ def C5932042_PhysXForceRegion_LinearDamping(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C5932042_PhysXForceRegion_LinearDamping) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5932043_ForceRegion_SimpleDragOnRigidBodies.py b/AutomatedTesting/Gem/PythonTests/physics/force_region/C5932043_ForceRegion_SimpleDragOnRigidBodies.py old mode 100755 new mode 100644 similarity index 98% rename from AutomatedTesting/Gem/PythonTests/physics/C5932043_ForceRegion_SimpleDragOnRigidBodies.py rename to AutomatedTesting/Gem/PythonTests/physics/force_region/C5932043_ForceRegion_SimpleDragOnRigidBodies.py index d88232ff78..cd81315e73 --- a/AutomatedTesting/Gem/PythonTests/physics/C5932043_ForceRegion_SimpleDragOnRigidBodies.py +++ b/AutomatedTesting/Gem/PythonTests/physics/force_region/C5932043_ForceRegion_SimpleDragOnRigidBodies.py @@ -42,9 +42,7 @@ def C5932043_ForceRegion_SimpleDragOnRigidBodies(): # Setup path import os, sys - import ImportPathHelper as imports - imports.init() from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -139,8 +137,5 @@ def C5932043_ForceRegion_SimpleDragOnRigidBodies(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C5932043_ForceRegion_SimpleDragOnRigidBodies) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5932044_ForceRegion_PointForceOnRigidBody.py b/AutomatedTesting/Gem/PythonTests/physics/force_region/C5932044_ForceRegion_PointForceOnRigidBody.py old mode 100755 new mode 100644 similarity index 98% rename from AutomatedTesting/Gem/PythonTests/physics/C5932044_ForceRegion_PointForceOnRigidBody.py rename to AutomatedTesting/Gem/PythonTests/physics/force_region/C5932044_ForceRegion_PointForceOnRigidBody.py index 58eec3a9be..23760909db --- a/AutomatedTesting/Gem/PythonTests/physics/C5932044_ForceRegion_PointForceOnRigidBody.py +++ b/AutomatedTesting/Gem/PythonTests/physics/force_region/C5932044_ForceRegion_PointForceOnRigidBody.py @@ -65,11 +65,6 @@ def C5932044_ForceRegion_PointForceOnRigidBody(): import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -189,8 +184,5 @@ def C5932044_ForceRegion_PointForceOnRigidBody(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C5932044_ForceRegion_PointForceOnRigidBody) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5932045_ForceRegion_Spline.py b/AutomatedTesting/Gem/PythonTests/physics/force_region/C5932045_ForceRegion_Spline.py old mode 100755 new mode 100644 similarity index 98% rename from AutomatedTesting/Gem/PythonTests/physics/C5932045_ForceRegion_Spline.py rename to AutomatedTesting/Gem/PythonTests/physics/force_region/C5932045_ForceRegion_Spline.py index ea9ca060c0..e74f5cc6e0 --- a/AutomatedTesting/Gem/PythonTests/physics/C5932045_ForceRegion_Spline.py +++ b/AutomatedTesting/Gem/PythonTests/physics/force_region/C5932045_ForceRegion_Spline.py @@ -70,11 +70,6 @@ def C5932045_ForceRegion_Spline(): """ import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -162,8 +157,5 @@ def C5932045_ForceRegion_Spline(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C5932045_ForceRegion_Spline) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5959759_RigidBody_ForceRegionSpherePointForce.py b/AutomatedTesting/Gem/PythonTests/physics/force_region/C5959759_RigidBody_ForceRegionSpherePointForce.py old mode 100755 new mode 100644 similarity index 98% rename from AutomatedTesting/Gem/PythonTests/physics/C5959759_RigidBody_ForceRegionSpherePointForce.py rename to AutomatedTesting/Gem/PythonTests/physics/force_region/C5959759_RigidBody_ForceRegionSpherePointForce.py index 3bfad9d770..99baeb1fff --- a/AutomatedTesting/Gem/PythonTests/physics/C5959759_RigidBody_ForceRegionSpherePointForce.py +++ b/AutomatedTesting/Gem/PythonTests/physics/force_region/C5959759_RigidBody_ForceRegionSpherePointForce.py @@ -38,11 +38,6 @@ def C5959759_RigidBody_ForceRegionSpherePointForce(): """ import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -150,8 +145,5 @@ def C5959759_RigidBody_ForceRegionSpherePointForce(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C5959759_RigidBody_ForceRegionSpherePointForce) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5959760_PhysXForceRegion_PointForceExertion.py b/AutomatedTesting/Gem/PythonTests/physics/force_region/C5959760_PhysXForceRegion_PointForceExertion.py old mode 100755 new mode 100644 similarity index 98% rename from AutomatedTesting/Gem/PythonTests/physics/C5959760_PhysXForceRegion_PointForceExertion.py rename to AutomatedTesting/Gem/PythonTests/physics/force_region/C5959760_PhysXForceRegion_PointForceExertion.py index 85d15aec33..6648b41d31 --- a/AutomatedTesting/Gem/PythonTests/physics/C5959760_PhysXForceRegion_PointForceExertion.py +++ b/AutomatedTesting/Gem/PythonTests/physics/force_region/C5959760_PhysXForceRegion_PointForceExertion.py @@ -63,11 +63,6 @@ def C5959760_PhysXForceRegion_PointForceExertion(): """ import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -223,8 +218,5 @@ def C5959760_PhysXForceRegion_PointForceExertion(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C5959760_PhysXForceRegion_PointForceExertion) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5959761_ForceRegion_PhysAssetExertsPointForce.py b/AutomatedTesting/Gem/PythonTests/physics/force_region/C5959761_ForceRegion_PhysAssetExertsPointForce.py old mode 100755 new mode 100644 similarity index 97% rename from AutomatedTesting/Gem/PythonTests/physics/C5959761_ForceRegion_PhysAssetExertsPointForce.py rename to AutomatedTesting/Gem/PythonTests/physics/force_region/C5959761_ForceRegion_PhysAssetExertsPointForce.py index 1e58a8d975..c77fc39a77 --- a/AutomatedTesting/Gem/PythonTests/physics/C5959761_ForceRegion_PhysAssetExertsPointForce.py +++ b/AutomatedTesting/Gem/PythonTests/physics/force_region/C5959761_ForceRegion_PhysAssetExertsPointForce.py @@ -61,12 +61,6 @@ def C5959761_ForceRegion_PhysAssetExertsPointForce(): import os import sys - - import ImportPathHelper as imports - - imports.init() - - import azlmbr import azlmbr.legacy.general as general import azlmbr.bus as bus @@ -140,8 +134,5 @@ def C5959761_ForceRegion_PhysAssetExertsPointForce(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C5959761_ForceRegion_PhysAssetExertsPointForce) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5959763_ForceRegion_ForceRegionImpulsesCube.py b/AutomatedTesting/Gem/PythonTests/physics/force_region/C5959763_ForceRegion_ForceRegionImpulsesCube.py old mode 100755 new mode 100644 similarity index 98% rename from AutomatedTesting/Gem/PythonTests/physics/C5959763_ForceRegion_ForceRegionImpulsesCube.py rename to AutomatedTesting/Gem/PythonTests/physics/force_region/C5959763_ForceRegion_ForceRegionImpulsesCube.py index 6123381588..8bea169a82 --- a/AutomatedTesting/Gem/PythonTests/physics/C5959763_ForceRegion_ForceRegionImpulsesCube.py +++ b/AutomatedTesting/Gem/PythonTests/physics/force_region/C5959763_ForceRegion_ForceRegionImpulsesCube.py @@ -42,9 +42,7 @@ def C5959763_ForceRegion_ForceRegionImpulsesCube(): # Setup path import os, sys - import ImportPathHelper as imports - imports.init() from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -165,8 +163,5 @@ def C5959763_ForceRegion_ForceRegionImpulsesCube(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C5959763_ForceRegion_ForceRegionImpulsesCube) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5959764_ForceRegion_ForceRegionImpulsesCapsule.py b/AutomatedTesting/Gem/PythonTests/physics/force_region/C5959764_ForceRegion_ForceRegionImpulsesCapsule.py old mode 100755 new mode 100644 similarity index 98% rename from AutomatedTesting/Gem/PythonTests/physics/C5959764_ForceRegion_ForceRegionImpulsesCapsule.py rename to AutomatedTesting/Gem/PythonTests/physics/force_region/C5959764_ForceRegion_ForceRegionImpulsesCapsule.py index 9e4ef9379a..4ce345a5eb --- a/AutomatedTesting/Gem/PythonTests/physics/C5959764_ForceRegion_ForceRegionImpulsesCapsule.py +++ b/AutomatedTesting/Gem/PythonTests/physics/force_region/C5959764_ForceRegion_ForceRegionImpulsesCapsule.py @@ -42,9 +42,7 @@ def C5959764_ForceRegion_ForceRegionImpulsesCapsule(): # Setup path import os, sys - import ImportPathHelper as imports - imports.init() from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -167,8 +165,5 @@ def C5959764_ForceRegion_ForceRegionImpulsesCapsule(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C5959764_ForceRegion_ForceRegionImpulsesCapsule) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5959765_ForceRegion_AssetGetsImpulsed.py b/AutomatedTesting/Gem/PythonTests/physics/force_region/C5959765_ForceRegion_AssetGetsImpulsed.py old mode 100755 new mode 100644 similarity index 98% rename from AutomatedTesting/Gem/PythonTests/physics/C5959765_ForceRegion_AssetGetsImpulsed.py rename to AutomatedTesting/Gem/PythonTests/physics/force_region/C5959765_ForceRegion_AssetGetsImpulsed.py index 3a28208805..36ecddb3ca --- a/AutomatedTesting/Gem/PythonTests/physics/C5959765_ForceRegion_AssetGetsImpulsed.py +++ b/AutomatedTesting/Gem/PythonTests/physics/force_region/C5959765_ForceRegion_AssetGetsImpulsed.py @@ -45,9 +45,7 @@ def C5959765_ForceRegion_AssetGetsImpulsed(): # Setup path import os, sys - import ImportPathHelper as imports - imports.init() from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -169,8 +167,5 @@ def C5959765_ForceRegion_AssetGetsImpulsed(): helper.exit_game_mode(Tests.exit_game_mode) if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C5959765_ForceRegion_AssetGetsImpulsed) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5959808_ForceRegion_PositionOffset.py b/AutomatedTesting/Gem/PythonTests/physics/force_region/C5959808_ForceRegion_PositionOffset.py old mode 100755 new mode 100644 similarity index 99% rename from AutomatedTesting/Gem/PythonTests/physics/C5959808_ForceRegion_PositionOffset.py rename to AutomatedTesting/Gem/PythonTests/physics/force_region/C5959808_ForceRegion_PositionOffset.py index 4b70fcc734..480869457c --- a/AutomatedTesting/Gem/PythonTests/physics/C5959808_ForceRegion_PositionOffset.py +++ b/AutomatedTesting/Gem/PythonTests/physics/force_region/C5959808_ForceRegion_PositionOffset.py @@ -124,11 +124,6 @@ def C5959808_ForceRegion_PositionOffset(): import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -405,8 +400,5 @@ def C5959808_ForceRegion_PositionOffset(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C5959808_ForceRegion_PositionOffset) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5959809_ForceRegion_RotationalOffset.py b/AutomatedTesting/Gem/PythonTests/physics/force_region/C5959809_ForceRegion_RotationalOffset.py old mode 100755 new mode 100644 similarity index 99% rename from AutomatedTesting/Gem/PythonTests/physics/C5959809_ForceRegion_RotationalOffset.py rename to AutomatedTesting/Gem/PythonTests/physics/force_region/C5959809_ForceRegion_RotationalOffset.py index ccf05cfe5d..d26aebab8d --- a/AutomatedTesting/Gem/PythonTests/physics/C5959809_ForceRegion_RotationalOffset.py +++ b/AutomatedTesting/Gem/PythonTests/physics/force_region/C5959809_ForceRegion_RotationalOffset.py @@ -125,11 +125,6 @@ def C5959809_ForceRegion_RotationalOffset(): import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -405,8 +400,5 @@ def C5959809_ForceRegion_RotationalOffset(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C5959809_ForceRegion_RotationalOffset) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5959810_ForceRegion_ForceRegionCombinesForces.py b/AutomatedTesting/Gem/PythonTests/physics/force_region/C5959810_ForceRegion_ForceRegionCombinesForces.py old mode 100755 new mode 100644 similarity index 98% rename from AutomatedTesting/Gem/PythonTests/physics/C5959810_ForceRegion_ForceRegionCombinesForces.py rename to AutomatedTesting/Gem/PythonTests/physics/force_region/C5959810_ForceRegion_ForceRegionCombinesForces.py index 330a2662ab..b7660926d5 --- a/AutomatedTesting/Gem/PythonTests/physics/C5959810_ForceRegion_ForceRegionCombinesForces.py +++ b/AutomatedTesting/Gem/PythonTests/physics/force_region/C5959810_ForceRegion_ForceRegionCombinesForces.py @@ -65,11 +65,6 @@ def C5959810_ForceRegion_ForceRegionCombinesForces(): import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -234,8 +229,5 @@ def C5959810_ForceRegion_ForceRegionCombinesForces(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C5959810_ForceRegion_ForceRegionCombinesForces) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5968759_ForceRegion_ExertsSeveralForcesOnRigidBody.py b/AutomatedTesting/Gem/PythonTests/physics/force_region/C5968759_ForceRegion_ExertsSeveralForcesOnRigidBody.py old mode 100755 new mode 100644 similarity index 98% rename from AutomatedTesting/Gem/PythonTests/physics/C5968759_ForceRegion_ExertsSeveralForcesOnRigidBody.py rename to AutomatedTesting/Gem/PythonTests/physics/force_region/C5968759_ForceRegion_ExertsSeveralForcesOnRigidBody.py index 068238e64d..b1f8d27900 --- a/AutomatedTesting/Gem/PythonTests/physics/C5968759_ForceRegion_ExertsSeveralForcesOnRigidBody.py +++ b/AutomatedTesting/Gem/PythonTests/physics/force_region/C5968759_ForceRegion_ExertsSeveralForcesOnRigidBody.py @@ -55,9 +55,7 @@ def C5968759_ForceRegion_ExertsSeveralForcesOnRigidBody(): Second force region: Name = "Force Region Simple Drag" Applies a drag force on both spheres Setup path """ - import ImportPathHelper as imports - imports.init() import azlmbr.legacy.general as general @@ -175,8 +173,5 @@ def C5968759_ForceRegion_ExertsSeveralForcesOnRigidBody(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C5968759_ForceRegion_ExertsSeveralForcesOnRigidBody) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5968760_ForceRegion_CheckNetForceChange.py b/AutomatedTesting/Gem/PythonTests/physics/force_region/C5968760_ForceRegion_CheckNetForceChange.py old mode 100755 new mode 100644 similarity index 98% rename from AutomatedTesting/Gem/PythonTests/physics/C5968760_ForceRegion_CheckNetForceChange.py rename to AutomatedTesting/Gem/PythonTests/physics/force_region/C5968760_ForceRegion_CheckNetForceChange.py index 41d5b93eb7..d64a0564f4 --- a/AutomatedTesting/Gem/PythonTests/physics/C5968760_ForceRegion_CheckNetForceChange.py +++ b/AutomatedTesting/Gem/PythonTests/physics/force_region/C5968760_ForceRegion_CheckNetForceChange.py @@ -61,11 +61,6 @@ def C5968760_ForceRegion_CheckNetForceChange(): import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -163,8 +158,5 @@ def C5968760_ForceRegion_CheckNetForceChange(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C5968760_ForceRegion_CheckNetForceChange) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C6090546_ForceRegion_SliceFileInstantiates.py b/AutomatedTesting/Gem/PythonTests/physics/force_region/C6090546_ForceRegion_SliceFileInstantiates.py old mode 100755 new mode 100644 similarity index 97% rename from AutomatedTesting/Gem/PythonTests/physics/C6090546_ForceRegion_SliceFileInstantiates.py rename to AutomatedTesting/Gem/PythonTests/physics/force_region/C6090546_ForceRegion_SliceFileInstantiates.py index f1c13291e3..0c360edee5 --- a/AutomatedTesting/Gem/PythonTests/physics/C6090546_ForceRegion_SliceFileInstantiates.py +++ b/AutomatedTesting/Gem/PythonTests/physics/force_region/C6090546_ForceRegion_SliceFileInstantiates.py @@ -63,11 +63,6 @@ def C6090546_ForceRegion_SliceFileInstantiates(): import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -138,8 +133,5 @@ def C6090546_ForceRegion_SliceFileInstantiates(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C6090546_ForceRegion_SliceFileInstantiates) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C6090547_ForceRegion_ParentChildForceRegions.py b/AutomatedTesting/Gem/PythonTests/physics/force_region/C6090547_ForceRegion_ParentChildForceRegions.py old mode 100755 new mode 100644 similarity index 98% rename from AutomatedTesting/Gem/PythonTests/physics/C6090547_ForceRegion_ParentChildForceRegions.py rename to AutomatedTesting/Gem/PythonTests/physics/force_region/C6090547_ForceRegion_ParentChildForceRegions.py index 2091a1a1f4..f466680e0c --- a/AutomatedTesting/Gem/PythonTests/physics/C6090547_ForceRegion_ParentChildForceRegions.py +++ b/AutomatedTesting/Gem/PythonTests/physics/force_region/C6090547_ForceRegion_ParentChildForceRegions.py @@ -72,11 +72,6 @@ def C6090547_ForceRegion_ParentChildForceRegions(): import os import sys - - import ImportPathHelper as imports - - imports.init() - import azlmbr.legacy.general as general import azlmbr.bus import azlmbr.math as lymath @@ -199,8 +194,5 @@ def C6090547_ForceRegion_ParentChildForceRegions(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C6090547_ForceRegion_ParentChildForceRegions) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C6090550_ForceRegion_WorldSpaceForceNegative.py b/AutomatedTesting/Gem/PythonTests/physics/force_region/C6090550_ForceRegion_WorldSpaceForceNegative.py old mode 100755 new mode 100644 similarity index 98% rename from AutomatedTesting/Gem/PythonTests/physics/C6090550_ForceRegion_WorldSpaceForceNegative.py rename to AutomatedTesting/Gem/PythonTests/physics/force_region/C6090550_ForceRegion_WorldSpaceForceNegative.py index 7b0586586b..7d6a8966b2 --- a/AutomatedTesting/Gem/PythonTests/physics/C6090550_ForceRegion_WorldSpaceForceNegative.py +++ b/AutomatedTesting/Gem/PythonTests/physics/force_region/C6090550_ForceRegion_WorldSpaceForceNegative.py @@ -69,11 +69,6 @@ def C6090550_ForceRegion_WorldSpaceForceNegative(): """ import os import sys - - import ImportPathHelper as imports - - imports.init() - import azlmbr.legacy.general as general import azlmbr.bus @@ -243,8 +238,5 @@ def C6090550_ForceRegion_WorldSpaceForceNegative(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C6090550_ForceRegion_WorldSpaceForceNegative) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C6090551_ForceRegion_LocalSpaceForceNegative.py b/AutomatedTesting/Gem/PythonTests/physics/force_region/C6090551_ForceRegion_LocalSpaceForceNegative.py old mode 100755 new mode 100644 similarity index 98% rename from AutomatedTesting/Gem/PythonTests/physics/C6090551_ForceRegion_LocalSpaceForceNegative.py rename to AutomatedTesting/Gem/PythonTests/physics/force_region/C6090551_ForceRegion_LocalSpaceForceNegative.py index 6025777d86..48d08666fd --- a/AutomatedTesting/Gem/PythonTests/physics/C6090551_ForceRegion_LocalSpaceForceNegative.py +++ b/AutomatedTesting/Gem/PythonTests/physics/force_region/C6090551_ForceRegion_LocalSpaceForceNegative.py @@ -69,11 +69,6 @@ def C6090551_ForceRegion_LocalSpaceForceNegative(): """ import os import sys - - import ImportPathHelper as imports - - imports.init() - import azlmbr.legacy.general as general import azlmbr.bus @@ -243,8 +238,5 @@ def C6090551_ForceRegion_LocalSpaceForceNegative(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C6090551_ForceRegion_LocalSpaceForceNegative) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C6090552_ForceRegion_LinearDampingNegative.py b/AutomatedTesting/Gem/PythonTests/physics/force_region/C6090552_ForceRegion_LinearDampingNegative.py old mode 100755 new mode 100644 similarity index 98% rename from AutomatedTesting/Gem/PythonTests/physics/C6090552_ForceRegion_LinearDampingNegative.py rename to AutomatedTesting/Gem/PythonTests/physics/force_region/C6090552_ForceRegion_LinearDampingNegative.py index 07f399a41a..100a07d346 --- a/AutomatedTesting/Gem/PythonTests/physics/C6090552_ForceRegion_LinearDampingNegative.py +++ b/AutomatedTesting/Gem/PythonTests/physics/force_region/C6090552_ForceRegion_LinearDampingNegative.py @@ -68,11 +68,6 @@ def C6090552_ForceRegion_LinearDampingNegative(): """ import os import sys - - import ImportPathHelper as imports - - imports.init() - import azlmbr.legacy.general as general import azlmbr.bus @@ -242,8 +237,5 @@ def C6090552_ForceRegion_LinearDampingNegative(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C6090552_ForceRegion_LinearDampingNegative) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C6090553_ForceRegion_SimpleDragForceOnRigidBodies.py b/AutomatedTesting/Gem/PythonTests/physics/force_region/C6090553_ForceRegion_SimpleDragForceOnRigidBodies.py old mode 100755 new mode 100644 similarity index 98% rename from AutomatedTesting/Gem/PythonTests/physics/C6090553_ForceRegion_SimpleDragForceOnRigidBodies.py rename to AutomatedTesting/Gem/PythonTests/physics/force_region/C6090553_ForceRegion_SimpleDragForceOnRigidBodies.py index 57f6d13d8e..7b5904a3d7 --- a/AutomatedTesting/Gem/PythonTests/physics/C6090553_ForceRegion_SimpleDragForceOnRigidBodies.py +++ b/AutomatedTesting/Gem/PythonTests/physics/force_region/C6090553_ForceRegion_SimpleDragForceOnRigidBodies.py @@ -63,11 +63,6 @@ def C6090553_ForceRegion_SimpleDragForceOnRigidBodies(): import os import sys - - import ImportPathHelper as imports - - imports.init() - import azlmbr.legacy.general as general import azlmbr.bus @@ -174,8 +169,5 @@ def C6090553_ForceRegion_SimpleDragForceOnRigidBodies(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C6090553_ForceRegion_SimpleDragForceOnRigidBodies) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C6090554_ForceRegion_PointForceNegative.py b/AutomatedTesting/Gem/PythonTests/physics/force_region/C6090554_ForceRegion_PointForceNegative.py old mode 100755 new mode 100644 similarity index 98% rename from AutomatedTesting/Gem/PythonTests/physics/C6090554_ForceRegion_PointForceNegative.py rename to AutomatedTesting/Gem/PythonTests/physics/force_region/C6090554_ForceRegion_PointForceNegative.py index fd3846a801..0b6b9a8b58 --- a/AutomatedTesting/Gem/PythonTests/physics/C6090554_ForceRegion_PointForceNegative.py +++ b/AutomatedTesting/Gem/PythonTests/physics/force_region/C6090554_ForceRegion_PointForceNegative.py @@ -69,11 +69,6 @@ def C6090554_ForceRegion_PointForceNegative(): """ import os import sys - - import ImportPathHelper as imports - - imports.init() - import azlmbr.legacy.general as general import azlmbr.bus @@ -243,8 +238,5 @@ def C6090554_ForceRegion_PointForceNegative(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C6090554_ForceRegion_PointForceNegative) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C6090555_ForceRegion_SplineFollowOnRigidBodies.py b/AutomatedTesting/Gem/PythonTests/physics/force_region/C6090555_ForceRegion_SplineFollowOnRigidBodies.py old mode 100755 new mode 100644 similarity index 98% rename from AutomatedTesting/Gem/PythonTests/physics/C6090555_ForceRegion_SplineFollowOnRigidBodies.py rename to AutomatedTesting/Gem/PythonTests/physics/force_region/C6090555_ForceRegion_SplineFollowOnRigidBodies.py index 800e9245dc..7a642c6c59 --- a/AutomatedTesting/Gem/PythonTests/physics/C6090555_ForceRegion_SplineFollowOnRigidBodies.py +++ b/AutomatedTesting/Gem/PythonTests/physics/force_region/C6090555_ForceRegion_SplineFollowOnRigidBodies.py @@ -65,11 +65,6 @@ def C6090555_ForceRegion_SplineFollowOnRigidBodies(): """ import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -176,8 +171,5 @@ def C6090555_ForceRegion_SplineFollowOnRigidBodies(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C6090555_ForceRegion_SplineFollowOnRigidBodies) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C6321601_Force_HighValuesDirectionAxes.py b/AutomatedTesting/Gem/PythonTests/physics/force_region/C6321601_Force_HighValuesDirectionAxes.py old mode 100755 new mode 100644 similarity index 98% rename from AutomatedTesting/Gem/PythonTests/physics/C6321601_Force_HighValuesDirectionAxes.py rename to AutomatedTesting/Gem/PythonTests/physics/force_region/C6321601_Force_HighValuesDirectionAxes.py index 6c94e7aea9..47cc085479 --- a/AutomatedTesting/Gem/PythonTests/physics/C6321601_Force_HighValuesDirectionAxes.py +++ b/AutomatedTesting/Gem/PythonTests/physics/force_region/C6321601_Force_HighValuesDirectionAxes.py @@ -90,11 +90,6 @@ def C6321601_Force_HighValuesDirectionAxes(): import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper from editor_python_test_tools.utils import Tracer @@ -246,10 +241,6 @@ def C6321601_Force_HighValuesDirectionAxes(): Report.result(Tests.error_not_found, not has_physx_error()) - if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C6321601_Force_HighValuesDirectionAxes) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C14976307_Gravity_SetGravityWorks.py b/AutomatedTesting/Gem/PythonTests/physics/general/C14976307_Gravity_SetGravityWorks.py old mode 100755 new mode 100644 similarity index 97% rename from AutomatedTesting/Gem/PythonTests/physics/C14976307_Gravity_SetGravityWorks.py rename to AutomatedTesting/Gem/PythonTests/physics/general/C14976307_Gravity_SetGravityWorks.py index 1b50863ccd..335ef75649 --- a/AutomatedTesting/Gem/PythonTests/physics/C14976307_Gravity_SetGravityWorks.py +++ b/AutomatedTesting/Gem/PythonTests/physics/general/C14976307_Gravity_SetGravityWorks.py @@ -60,11 +60,6 @@ def C14976307_Gravity_SetGravityWorks(): import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -122,8 +117,5 @@ def C14976307_Gravity_SetGravityWorks(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C14976307_Gravity_SetGravityWorks) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C15425929_Undo_Redo.py b/AutomatedTesting/Gem/PythonTests/physics/general/C15425929_Undo_Redo.py old mode 100755 new mode 100644 similarity index 96% rename from AutomatedTesting/Gem/PythonTests/physics/C15425929_Undo_Redo.py rename to AutomatedTesting/Gem/PythonTests/physics/general/C15425929_Undo_Redo.py index 9595030b4b..f74c1d10cb --- a/AutomatedTesting/Gem/PythonTests/physics/C15425929_Undo_Redo.py +++ b/AutomatedTesting/Gem/PythonTests/physics/general/C15425929_Undo_Redo.py @@ -44,11 +44,6 @@ def C15425929_Undo_Redo(): """ import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper from editor_python_test_tools.utils import Tracer @@ -91,8 +86,5 @@ def C15425929_Undo_Redo(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C15425929_Undo_Redo) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C19536274_GetCollisionName_PrintsName.py b/AutomatedTesting/Gem/PythonTests/physics/general/C19536274_GetCollisionName_PrintsName.py old mode 100755 new mode 100644 similarity index 93% rename from AutomatedTesting/Gem/PythonTests/physics/C19536274_GetCollisionName_PrintsName.py rename to AutomatedTesting/Gem/PythonTests/physics/general/C19536274_GetCollisionName_PrintsName.py index 4c035eea96..abf2045ed4 --- a/AutomatedTesting/Gem/PythonTests/physics/C19536274_GetCollisionName_PrintsName.py +++ b/AutomatedTesting/Gem/PythonTests/physics/general/C19536274_GetCollisionName_PrintsName.py @@ -17,7 +17,7 @@ class Tests(): # fmt: on -def run(): +def C19536274_GetCollisionName_PrintsName(): """ Summary: Loads a level that contains an entity with script canvas and PhysX Collider components @@ -43,9 +43,7 @@ def run(): :return: None """ # Helper Files - import ImportPathHelper as imports - imports.init() from editor_python_test_tools.utils import Report from editor_python_test_tools.editor_entity_utils import EditorEntity as Entity from editor_python_test_tools.utils import TestHelper as helper @@ -66,4 +64,5 @@ def run(): if __name__ == "__main__": - run() + from editor_python_test_tools.utils import Report + Report.start_test(C19536274_GetCollisionName_PrintsName) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C19536277_GetCollisionName_PrintsNothing.py b/AutomatedTesting/Gem/PythonTests/physics/general/C19536277_GetCollisionName_PrintsNothing.py old mode 100755 new mode 100644 similarity index 93% rename from AutomatedTesting/Gem/PythonTests/physics/C19536277_GetCollisionName_PrintsNothing.py rename to AutomatedTesting/Gem/PythonTests/physics/general/C19536277_GetCollisionName_PrintsNothing.py index 1bf5248a1f..a0d242542f --- a/AutomatedTesting/Gem/PythonTests/physics/C19536277_GetCollisionName_PrintsNothing.py +++ b/AutomatedTesting/Gem/PythonTests/physics/general/C19536277_GetCollisionName_PrintsNothing.py @@ -17,7 +17,7 @@ class Tests(): # fmt: on -def run(): +def C19536277_GetCollisionName_PrintsNothing(): """ Summary: Loads a level that contains an entity with script canvas and PhysX Collider components @@ -43,9 +43,7 @@ def run(): :return: None """ # Helper Files - import ImportPathHelper as imports - imports.init() from editor_python_test_tools.utils import Report from editor_python_test_tools.editor_entity_utils import EditorEntity as Entity from editor_python_test_tools.utils import TestHelper as helper @@ -66,4 +64,5 @@ def run(): if __name__ == "__main__": - run() + from editor_python_test_tools.utils import Report + Report.start_test(C19536277_GetCollisionName_PrintsNothing) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C29032500_EditorComponents_WorldBodyBusWorks.py b/AutomatedTesting/Gem/PythonTests/physics/general/C29032500_EditorComponents_WorldBodyBusWorks.py old mode 100755 new mode 100644 similarity index 98% rename from AutomatedTesting/Gem/PythonTests/physics/C29032500_EditorComponents_WorldBodyBusWorks.py rename to AutomatedTesting/Gem/PythonTests/physics/general/C29032500_EditorComponents_WorldBodyBusWorks.py index a022cc7011..0f7f91dafb --- a/AutomatedTesting/Gem/PythonTests/physics/C29032500_EditorComponents_WorldBodyBusWorks.py +++ b/AutomatedTesting/Gem/PythonTests/physics/general/C29032500_EditorComponents_WorldBodyBusWorks.py @@ -82,11 +82,6 @@ def C29032500_EditorComponents_WorldBodyBusWorks(): """ import os import sys - - import ImportPathHelper as imports - - imports.init() - import azlmbr.legacy.general as general import azlmbr.bus import math @@ -154,8 +149,5 @@ def C29032500_EditorComponents_WorldBodyBusWorks(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C29032500_EditorComponents_WorldBodyBusWorks) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5689529_Verify_Terrain_RigidBody_Collider_Mesh.py b/AutomatedTesting/Gem/PythonTests/physics/general/C5689529_Verify_Terrain_RigidBody_Collider_Mesh.py old mode 100755 new mode 100644 similarity index 97% rename from AutomatedTesting/Gem/PythonTests/physics/C5689529_Verify_Terrain_RigidBody_Collider_Mesh.py rename to AutomatedTesting/Gem/PythonTests/physics/general/C5689529_Verify_Terrain_RigidBody_Collider_Mesh.py index 1436a98536..f011e65972 --- a/AutomatedTesting/Gem/PythonTests/physics/C5689529_Verify_Terrain_RigidBody_Collider_Mesh.py +++ b/AutomatedTesting/Gem/PythonTests/physics/general/C5689529_Verify_Terrain_RigidBody_Collider_Mesh.py @@ -58,11 +58,6 @@ def C5689529_Verify_Terrain_RigidBody_Collider_Mesh(): import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -106,8 +101,5 @@ def C5689529_Verify_Terrain_RigidBody_Collider_Mesh(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C5689529_Verify_Terrain_RigidBody_Collider_Mesh) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C6131473_StaticSlice_OnDynamicSliceSpawn.py b/AutomatedTesting/Gem/PythonTests/physics/general/C6131473_StaticSlice_OnDynamicSliceSpawn.py old mode 100755 new mode 100644 similarity index 96% rename from AutomatedTesting/Gem/PythonTests/physics/C6131473_StaticSlice_OnDynamicSliceSpawn.py rename to AutomatedTesting/Gem/PythonTests/physics/general/C6131473_StaticSlice_OnDynamicSliceSpawn.py index 16fff25a25..e28893dee3 --- a/AutomatedTesting/Gem/PythonTests/physics/C6131473_StaticSlice_OnDynamicSliceSpawn.py +++ b/AutomatedTesting/Gem/PythonTests/physics/general/C6131473_StaticSlice_OnDynamicSliceSpawn.py @@ -58,11 +58,6 @@ def C6131473_StaticSlice_OnDynamicSliceSpawn(): import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -103,8 +98,5 @@ def C6131473_StaticSlice_OnDynamicSliceSpawn(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C6131473_StaticSlice_OnDynamicSliceSpawn) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C18243580_Joints_Fixed2BodiesConstrained.py b/AutomatedTesting/Gem/PythonTests/physics/joints/C18243580_Joints_Fixed2BodiesConstrained.py old mode 100755 new mode 100644 similarity index 96% rename from AutomatedTesting/Gem/PythonTests/physics/C18243580_Joints_Fixed2BodiesConstrained.py rename to AutomatedTesting/Gem/PythonTests/physics/joints/C18243580_Joints_Fixed2BodiesConstrained.py index 24adc2ff71..ceabb91a28 --- a/AutomatedTesting/Gem/PythonTests/physics/C18243580_Joints_Fixed2BodiesConstrained.py +++ b/AutomatedTesting/Gem/PythonTests/physics/joints/C18243580_Joints_Fixed2BodiesConstrained.py @@ -49,11 +49,6 @@ def C18243580_Joints_Fixed2BodiesConstrained(): """ import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -99,8 +94,5 @@ def C18243580_Joints_Fixed2BodiesConstrained(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C18243580_Joints_Fixed2BodiesConstrained) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C18243581_Joints_FixedBreakable.py b/AutomatedTesting/Gem/PythonTests/physics/joints/C18243581_Joints_FixedBreakable.py old mode 100755 new mode 100644 similarity index 96% rename from AutomatedTesting/Gem/PythonTests/physics/C18243581_Joints_FixedBreakable.py rename to AutomatedTesting/Gem/PythonTests/physics/joints/C18243581_Joints_FixedBreakable.py index fb3da2c4e5..716df85c67 --- a/AutomatedTesting/Gem/PythonTests/physics/C18243581_Joints_FixedBreakable.py +++ b/AutomatedTesting/Gem/PythonTests/physics/joints/C18243581_Joints_FixedBreakable.py @@ -48,11 +48,6 @@ def C18243581_Joints_FixedBreakable(): """ import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -98,8 +93,5 @@ def C18243581_Joints_FixedBreakable(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C18243581_Joints_FixedBreakable) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C18243582_Joints_FixedLeadFollowerCollide.py b/AutomatedTesting/Gem/PythonTests/physics/joints/C18243582_Joints_FixedLeadFollowerCollide.py old mode 100755 new mode 100644 similarity index 96% rename from AutomatedTesting/Gem/PythonTests/physics/C18243582_Joints_FixedLeadFollowerCollide.py rename to AutomatedTesting/Gem/PythonTests/physics/joints/C18243582_Joints_FixedLeadFollowerCollide.py index 0c7a1d7007..0f130a300b --- a/AutomatedTesting/Gem/PythonTests/physics/C18243582_Joints_FixedLeadFollowerCollide.py +++ b/AutomatedTesting/Gem/PythonTests/physics/joints/C18243582_Joints_FixedLeadFollowerCollide.py @@ -50,11 +50,6 @@ def C18243582_Joints_FixedLeadFollowerCollide(): """ import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -93,8 +88,5 @@ def C18243582_Joints_FixedLeadFollowerCollide(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C18243582_Joints_FixedLeadFollowerCollide) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C18243583_Joints_Hinge2BodiesConstrained.py b/AutomatedTesting/Gem/PythonTests/physics/joints/C18243583_Joints_Hinge2BodiesConstrained.py old mode 100755 new mode 100644 similarity index 97% rename from AutomatedTesting/Gem/PythonTests/physics/C18243583_Joints_Hinge2BodiesConstrained.py rename to AutomatedTesting/Gem/PythonTests/physics/joints/C18243583_Joints_Hinge2BodiesConstrained.py index e91a4a495e..e9b11bc198 --- a/AutomatedTesting/Gem/PythonTests/physics/C18243583_Joints_Hinge2BodiesConstrained.py +++ b/AutomatedTesting/Gem/PythonTests/physics/joints/C18243583_Joints_Hinge2BodiesConstrained.py @@ -52,11 +52,6 @@ def C18243583_Joints_Hinge2BodiesConstrained(): """ import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -116,8 +111,5 @@ def C18243583_Joints_Hinge2BodiesConstrained(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C18243583_Joints_Hinge2BodiesConstrained) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C18243584_Joints_HingeSoftLimitsConstrained.py b/AutomatedTesting/Gem/PythonTests/physics/joints/C18243584_Joints_HingeSoftLimitsConstrained.py old mode 100755 new mode 100644 similarity index 98% rename from AutomatedTesting/Gem/PythonTests/physics/C18243584_Joints_HingeSoftLimitsConstrained.py rename to AutomatedTesting/Gem/PythonTests/physics/joints/C18243584_Joints_HingeSoftLimitsConstrained.py index d4bf9308d2..e100b61494 --- a/AutomatedTesting/Gem/PythonTests/physics/C18243584_Joints_HingeSoftLimitsConstrained.py +++ b/AutomatedTesting/Gem/PythonTests/physics/joints/C18243584_Joints_HingeSoftLimitsConstrained.py @@ -54,9 +54,7 @@ def C18243584_Joints_HingeSoftLimitsConstrained(): import sys import math - import ImportPathHelper as imports - imports.init() from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -142,8 +140,5 @@ def C18243584_Joints_HingeSoftLimitsConstrained(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C18243584_Joints_HingeSoftLimitsConstrained) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C18243585_Joints_HingeNoLimitsConstrained.py b/AutomatedTesting/Gem/PythonTests/physics/joints/C18243585_Joints_HingeNoLimitsConstrained.py old mode 100755 new mode 100644 similarity index 97% rename from AutomatedTesting/Gem/PythonTests/physics/C18243585_Joints_HingeNoLimitsConstrained.py rename to AutomatedTesting/Gem/PythonTests/physics/joints/C18243585_Joints_HingeNoLimitsConstrained.py index 3a734e1ef0..90ac80b1fa --- a/AutomatedTesting/Gem/PythonTests/physics/C18243585_Joints_HingeNoLimitsConstrained.py +++ b/AutomatedTesting/Gem/PythonTests/physics/joints/C18243585_Joints_HingeNoLimitsConstrained.py @@ -52,11 +52,6 @@ def C18243585_Joints_HingeNoLimitsConstrained(): """ import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -112,8 +107,5 @@ def C18243585_Joints_HingeNoLimitsConstrained(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C18243585_Joints_HingeNoLimitsConstrained) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C18243586_Joints_HingeLeadFollowerCollide.py b/AutomatedTesting/Gem/PythonTests/physics/joints/C18243586_Joints_HingeLeadFollowerCollide.py old mode 100755 new mode 100644 similarity index 96% rename from AutomatedTesting/Gem/PythonTests/physics/C18243586_Joints_HingeLeadFollowerCollide.py rename to AutomatedTesting/Gem/PythonTests/physics/joints/C18243586_Joints_HingeLeadFollowerCollide.py index f22b1b0c9c..2b5b95939f --- a/AutomatedTesting/Gem/PythonTests/physics/C18243586_Joints_HingeLeadFollowerCollide.py +++ b/AutomatedTesting/Gem/PythonTests/physics/joints/C18243586_Joints_HingeLeadFollowerCollide.py @@ -49,11 +49,6 @@ def C18243586_Joints_HingeLeadFollowerCollide(): """ import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -92,8 +87,5 @@ def C18243586_Joints_HingeLeadFollowerCollide(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C18243586_Joints_HingeLeadFollowerCollide) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C18243587_Joints_HingeBreakable.py b/AutomatedTesting/Gem/PythonTests/physics/joints/C18243587_Joints_HingeBreakable.py old mode 100755 new mode 100644 similarity index 97% rename from AutomatedTesting/Gem/PythonTests/physics/C18243587_Joints_HingeBreakable.py rename to AutomatedTesting/Gem/PythonTests/physics/joints/C18243587_Joints_HingeBreakable.py index c11851bde4..b1ea7e123a --- a/AutomatedTesting/Gem/PythonTests/physics/C18243587_Joints_HingeBreakable.py +++ b/AutomatedTesting/Gem/PythonTests/physics/joints/C18243587_Joints_HingeBreakable.py @@ -50,11 +50,6 @@ def C18243587_Joints_HingeBreakable(): """ import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -110,8 +105,5 @@ def C18243587_Joints_HingeBreakable(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C18243587_Joints_HingeBreakable) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C18243588_Joints_Ball2BodiesConstrained.py b/AutomatedTesting/Gem/PythonTests/physics/joints/C18243588_Joints_Ball2BodiesConstrained.py old mode 100755 new mode 100644 similarity index 97% rename from AutomatedTesting/Gem/PythonTests/physics/C18243588_Joints_Ball2BodiesConstrained.py rename to AutomatedTesting/Gem/PythonTests/physics/joints/C18243588_Joints_Ball2BodiesConstrained.py index 107140d7d0..fd8556660a --- a/AutomatedTesting/Gem/PythonTests/physics/C18243588_Joints_Ball2BodiesConstrained.py +++ b/AutomatedTesting/Gem/PythonTests/physics/joints/C18243588_Joints_Ball2BodiesConstrained.py @@ -51,11 +51,6 @@ def C18243588_Joints_Ball2BodiesConstrained(): """ import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -114,8 +109,5 @@ def C18243588_Joints_Ball2BodiesConstrained(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C18243588_Joints_Ball2BodiesConstrained) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C18243589_Joints_BallSoftLimitsConstrained.py b/AutomatedTesting/Gem/PythonTests/physics/joints/C18243589_Joints_BallSoftLimitsConstrained.py old mode 100755 new mode 100644 similarity index 97% rename from AutomatedTesting/Gem/PythonTests/physics/C18243589_Joints_BallSoftLimitsConstrained.py rename to AutomatedTesting/Gem/PythonTests/physics/joints/C18243589_Joints_BallSoftLimitsConstrained.py index 2c6f1f34b0..30747bc2eb --- a/AutomatedTesting/Gem/PythonTests/physics/C18243589_Joints_BallSoftLimitsConstrained.py +++ b/AutomatedTesting/Gem/PythonTests/physics/joints/C18243589_Joints_BallSoftLimitsConstrained.py @@ -55,9 +55,7 @@ def C18243589_Joints_BallSoftLimitsConstrained(): import sys import math - import ImportPathHelper as imports - imports.init() from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -135,8 +133,5 @@ def C18243589_Joints_BallSoftLimitsConstrained(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C18243589_Joints_BallSoftLimitsConstrained) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C18243590_Joints_BallNoLimitsConstrained.py b/AutomatedTesting/Gem/PythonTests/physics/joints/C18243590_Joints_BallNoLimitsConstrained.py old mode 100755 new mode 100644 similarity index 97% rename from AutomatedTesting/Gem/PythonTests/physics/C18243590_Joints_BallNoLimitsConstrained.py rename to AutomatedTesting/Gem/PythonTests/physics/joints/C18243590_Joints_BallNoLimitsConstrained.py index b5de805d16..990f4f826b --- a/AutomatedTesting/Gem/PythonTests/physics/C18243590_Joints_BallNoLimitsConstrained.py +++ b/AutomatedTesting/Gem/PythonTests/physics/joints/C18243590_Joints_BallNoLimitsConstrained.py @@ -54,11 +54,6 @@ def C18243590_Joints_BallNoLimitsConstrained(): """ import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -113,8 +108,5 @@ def C18243590_Joints_BallNoLimitsConstrained(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C18243590_Joints_BallNoLimitsConstrained) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C18243591_Joints_BallLeadFollowerCollide.py b/AutomatedTesting/Gem/PythonTests/physics/joints/C18243591_Joints_BallLeadFollowerCollide.py old mode 100755 new mode 100644 similarity index 96% rename from AutomatedTesting/Gem/PythonTests/physics/C18243591_Joints_BallLeadFollowerCollide.py rename to AutomatedTesting/Gem/PythonTests/physics/joints/C18243591_Joints_BallLeadFollowerCollide.py index 2e73232bd9..47422d1508 --- a/AutomatedTesting/Gem/PythonTests/physics/C18243591_Joints_BallLeadFollowerCollide.py +++ b/AutomatedTesting/Gem/PythonTests/physics/joints/C18243591_Joints_BallLeadFollowerCollide.py @@ -49,11 +49,6 @@ def C18243591_Joints_BallLeadFollowerCollide(): """ import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -92,8 +87,5 @@ def C18243591_Joints_BallLeadFollowerCollide(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C18243591_Joints_BallLeadFollowerCollide) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C18243592_Joints_BallBreakable.py b/AutomatedTesting/Gem/PythonTests/physics/joints/C18243592_Joints_BallBreakable.py old mode 100755 new mode 100644 similarity index 97% rename from AutomatedTesting/Gem/PythonTests/physics/C18243592_Joints_BallBreakable.py rename to AutomatedTesting/Gem/PythonTests/physics/joints/C18243592_Joints_BallBreakable.py index 6539b1b413..6182c312dc --- a/AutomatedTesting/Gem/PythonTests/physics/C18243592_Joints_BallBreakable.py +++ b/AutomatedTesting/Gem/PythonTests/physics/joints/C18243592_Joints_BallBreakable.py @@ -49,11 +49,6 @@ def C18243592_Joints_BallBreakable(): """ import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -108,8 +103,5 @@ def C18243592_Joints_BallBreakable(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C18243592_Joints_BallBreakable) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C18243593_Joints_GlobalFrameConstrained.py b/AutomatedTesting/Gem/PythonTests/physics/joints/C18243593_Joints_GlobalFrameConstrained.py old mode 100755 new mode 100644 similarity index 97% rename from AutomatedTesting/Gem/PythonTests/physics/C18243593_Joints_GlobalFrameConstrained.py rename to AutomatedTesting/Gem/PythonTests/physics/joints/C18243593_Joints_GlobalFrameConstrained.py index 63708d7571..bd527f10f8 --- a/AutomatedTesting/Gem/PythonTests/physics/C18243593_Joints_GlobalFrameConstrained.py +++ b/AutomatedTesting/Gem/PythonTests/physics/joints/C18243593_Joints_GlobalFrameConstrained.py @@ -53,11 +53,6 @@ def C18243593_Joints_GlobalFrameConstrained(): """ import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -121,8 +116,5 @@ def C18243593_Joints_GlobalFrameConstrained(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C18243593_Joints_GlobalFrameConstrained) diff --git a/AutomatedTesting/Gem/PythonTests/physics/JointsHelper.py b/AutomatedTesting/Gem/PythonTests/physics/joints/JointsHelper.py old mode 100755 new mode 100644 similarity index 97% rename from AutomatedTesting/Gem/PythonTests/physics/JointsHelper.py rename to AutomatedTesting/Gem/PythonTests/physics/joints/JointsHelper.py index 12c05c3ced..6226f42534 --- a/AutomatedTesting/Gem/PythonTests/physics/JointsHelper.py +++ b/AutomatedTesting/Gem/PythonTests/physics/joints/JointsHelper.py @@ -5,10 +5,6 @@ For complete copyright and license terms please see the LICENSE at the root of t SPDX-License-Identifier: Apache-2.0 OR MIT """ -import ImportPathHelper as imports - -imports.init() - from editor_python_test_tools.utils import Report import azlmbr.legacy.general as general import azlmbr.bus diff --git a/AutomatedTesting/Gem/PythonTests/physics/AddModifyDelete_Utils.py b/AutomatedTesting/Gem/PythonTests/physics/material/AddModifyDelete_Utils.py old mode 100755 new mode 100644 similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/AddModifyDelete_Utils.py rename to AutomatedTesting/Gem/PythonTests/physics/material/AddModifyDelete_Utils.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/C15096732_Material_DefaultLibraryUpdatedAcrossLevels_after.py b/AutomatedTesting/Gem/PythonTests/physics/material/C15096732_Material_DefaultLibraryUpdatedAcrossLevels_after.py old mode 100755 new mode 100644 similarity index 99% rename from AutomatedTesting/Gem/PythonTests/physics/C15096732_Material_DefaultLibraryUpdatedAcrossLevels_after.py rename to AutomatedTesting/Gem/PythonTests/physics/material/C15096732_Material_DefaultLibraryUpdatedAcrossLevels_after.py index 96e05b88fb..de1945bc8d --- a/AutomatedTesting/Gem/PythonTests/physics/C15096732_Material_DefaultLibraryUpdatedAcrossLevels_after.py +++ b/AutomatedTesting/Gem/PythonTests/physics/material/C15096732_Material_DefaultLibraryUpdatedAcrossLevels_after.py @@ -99,11 +99,6 @@ def C15096732_Material_DefaultLibraryUpdatedAcrossLevels_after(): """ import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -285,8 +280,5 @@ def C15096732_Material_DefaultLibraryUpdatedAcrossLevels_after(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C15096732_Material_DefaultLibraryUpdatedAcrossLevels_after) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C15096732_Material_DefaultLibraryUpdatedAcrossLevels_before.py b/AutomatedTesting/Gem/PythonTests/physics/material/C15096732_Material_DefaultLibraryUpdatedAcrossLevels_before.py old mode 100755 new mode 100644 similarity index 98% rename from AutomatedTesting/Gem/PythonTests/physics/C15096732_Material_DefaultLibraryUpdatedAcrossLevels_before.py rename to AutomatedTesting/Gem/PythonTests/physics/material/C15096732_Material_DefaultLibraryUpdatedAcrossLevels_before.py index 95e3acefd7..46262f3f77 --- a/AutomatedTesting/Gem/PythonTests/physics/C15096732_Material_DefaultLibraryUpdatedAcrossLevels_before.py +++ b/AutomatedTesting/Gem/PythonTests/physics/material/C15096732_Material_DefaultLibraryUpdatedAcrossLevels_before.py @@ -92,11 +92,6 @@ def C15096732_Material_DefaultLibraryUpdatedAcrossLevels_before(): """ import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -237,8 +232,5 @@ def C15096732_Material_DefaultLibraryUpdatedAcrossLevels_before(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C15096732_Material_DefaultLibraryUpdatedAcrossLevels_before) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C15096735_Materials_DefaultLibraryConsistency.py b/AutomatedTesting/Gem/PythonTests/physics/material/C15096735_Materials_DefaultLibraryConsistency.py old mode 100755 new mode 100644 similarity index 99% rename from AutomatedTesting/Gem/PythonTests/physics/C15096735_Materials_DefaultLibraryConsistency.py rename to AutomatedTesting/Gem/PythonTests/physics/material/C15096735_Materials_DefaultLibraryConsistency.py index 18ffe68415..75c9849756 --- a/AutomatedTesting/Gem/PythonTests/physics/C15096735_Materials_DefaultLibraryConsistency.py +++ b/AutomatedTesting/Gem/PythonTests/physics/material/C15096735_Materials_DefaultLibraryConsistency.py @@ -140,11 +140,6 @@ def C15096735_Materials_DefaultLibraryConsistency(): """ import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -417,8 +412,5 @@ def C15096735_Materials_DefaultLibraryConsistency(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C15096735_Materials_DefaultLibraryConsistency) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C15096737_Materials_DefaultMaterialLibraryChanges.py b/AutomatedTesting/Gem/PythonTests/physics/material/C15096737_Materials_DefaultMaterialLibraryChanges.py old mode 100755 new mode 100644 similarity index 99% rename from AutomatedTesting/Gem/PythonTests/physics/C15096737_Materials_DefaultMaterialLibraryChanges.py rename to AutomatedTesting/Gem/PythonTests/physics/material/C15096737_Materials_DefaultMaterialLibraryChanges.py index 4dae4c536c..a4c65fc24c --- a/AutomatedTesting/Gem/PythonTests/physics/C15096737_Materials_DefaultMaterialLibraryChanges.py +++ b/AutomatedTesting/Gem/PythonTests/physics/material/C15096737_Materials_DefaultMaterialLibraryChanges.py @@ -107,9 +107,7 @@ def C15096737_Materials_DefaultMaterialLibraryChanges(): import os import sys - import ImportPathHelper as imports - imports.init() from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -293,8 +291,5 @@ def C15096737_Materials_DefaultMaterialLibraryChanges(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C15096737_Materials_DefaultMaterialLibraryChanges) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C15096740_Material_LibraryUpdatedCorrectly.py b/AutomatedTesting/Gem/PythonTests/physics/material/C15096740_Material_LibraryUpdatedCorrectly.py old mode 100755 new mode 100644 similarity index 96% rename from AutomatedTesting/Gem/PythonTests/physics/C15096740_Material_LibraryUpdatedCorrectly.py rename to AutomatedTesting/Gem/PythonTests/physics/material/C15096740_Material_LibraryUpdatedCorrectly.py index 341597e36a..88c51bae8a --- a/AutomatedTesting/Gem/PythonTests/physics/C15096740_Material_LibraryUpdatedCorrectly.py +++ b/AutomatedTesting/Gem/PythonTests/physics/material/C15096740_Material_LibraryUpdatedCorrectly.py @@ -49,15 +49,13 @@ def C15096740_Material_LibraryUpdatedCorrectly(): # Built-in Imports import os - import ImportPathHelper as imports - imports.init() # Helper file Imports from editor_python_test_tools.editor_entity_utils import EditorEntity from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper - from asset_utils import Asset + from editor_python_test_tools.asset_utils import Asset # Open 3D Engine Imports import azlmbr.asset as azasset @@ -101,8 +99,5 @@ def C15096740_Material_LibraryUpdatedCorrectly(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C15096740_Material_LibraryUpdatedCorrectly) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C15308221_Material_ComponentsInSyncWithLibrary.py b/AutomatedTesting/Gem/PythonTests/physics/material/C15308221_Material_ComponentsInSyncWithLibrary.py old mode 100755 new mode 100644 similarity index 99% rename from AutomatedTesting/Gem/PythonTests/physics/C15308221_Material_ComponentsInSyncWithLibrary.py rename to AutomatedTesting/Gem/PythonTests/physics/material/C15308221_Material_ComponentsInSyncWithLibrary.py index 349e824a49..b29709e95b --- a/AutomatedTesting/Gem/PythonTests/physics/C15308221_Material_ComponentsInSyncWithLibrary.py +++ b/AutomatedTesting/Gem/PythonTests/physics/material/C15308221_Material_ComponentsInSyncWithLibrary.py @@ -105,11 +105,6 @@ def C15308221_Material_ComponentsInSyncWithLibrary(): """ import os import sys - - import ImportPathHelper as imports - - imports.init() - import azlmbr.legacy.general as general import azlmbr.bus as bus import azlmbr.components @@ -244,8 +239,5 @@ def C15308221_Material_ComponentsInSyncWithLibrary(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C15308221_Material_ComponentsInSyncWithLibrary) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C15425935_Material_LibraryUpdatedAcrossLevels.py b/AutomatedTesting/Gem/PythonTests/physics/material/C15425935_Material_LibraryUpdatedAcrossLevels.py old mode 100755 new mode 100644 similarity index 99% rename from AutomatedTesting/Gem/PythonTests/physics/C15425935_Material_LibraryUpdatedAcrossLevels.py rename to AutomatedTesting/Gem/PythonTests/physics/material/C15425935_Material_LibraryUpdatedAcrossLevels.py index 283b8e3d55..91452a1173 --- a/AutomatedTesting/Gem/PythonTests/physics/C15425935_Material_LibraryUpdatedAcrossLevels.py +++ b/AutomatedTesting/Gem/PythonTests/physics/material/C15425935_Material_LibraryUpdatedAcrossLevels.py @@ -112,12 +112,6 @@ def C15425935_Material_LibraryUpdatedAcrossLevels(): """ import os import sys - - import ImportPathHelper as imports - - imports.init() - - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -307,8 +301,5 @@ def C15425935_Material_LibraryUpdatedAcrossLevels(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C15425935_Material_LibraryUpdatedAcrossLevels) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C15556261_PhysXMaterials_CharacterControllerMaterialAssignment.py b/AutomatedTesting/Gem/PythonTests/physics/material/C15556261_PhysXMaterials_CharacterControllerMaterialAssignment.py old mode 100755 new mode 100644 similarity index 98% rename from AutomatedTesting/Gem/PythonTests/physics/C15556261_PhysXMaterials_CharacterControllerMaterialAssignment.py rename to AutomatedTesting/Gem/PythonTests/physics/material/C15556261_PhysXMaterials_CharacterControllerMaterialAssignment.py index 88abe8dcd1..4d806cda11 --- a/AutomatedTesting/Gem/PythonTests/physics/C15556261_PhysXMaterials_CharacterControllerMaterialAssignment.py +++ b/AutomatedTesting/Gem/PythonTests/physics/material/C15556261_PhysXMaterials_CharacterControllerMaterialAssignment.py @@ -79,11 +79,6 @@ def C15556261_PhysXMaterials_CharacterControllerMaterialAssignment(): import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general @@ -202,8 +197,5 @@ def C15556261_PhysXMaterials_CharacterControllerMaterialAssignment(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C15556261_PhysXMaterials_CharacterControllerMaterialAssignment) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C15563573_Material_AddModifyDeleteOnCharacterController.py b/AutomatedTesting/Gem/PythonTests/physics/material/C15563573_Material_AddModifyDeleteOnCharacterController.py old mode 100755 new mode 100644 similarity index 98% rename from AutomatedTesting/Gem/PythonTests/physics/C15563573_Material_AddModifyDeleteOnCharacterController.py rename to AutomatedTesting/Gem/PythonTests/physics/material/C15563573_Material_AddModifyDeleteOnCharacterController.py index ca00b30479..cf38ddc11c --- a/AutomatedTesting/Gem/PythonTests/physics/C15563573_Material_AddModifyDeleteOnCharacterController.py +++ b/AutomatedTesting/Gem/PythonTests/physics/material/C15563573_Material_AddModifyDeleteOnCharacterController.py @@ -107,11 +107,6 @@ def C15563573_Material_AddModifyDeleteOnCharacterController(): """ import os import sys - - import ImportPathHelper as imports - - imports.init() - import azlmbr.legacy.general as general import azlmbr.math as lymath @@ -197,8 +192,5 @@ def C15563573_Material_AddModifyDeleteOnCharacterController(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C15563573_Material_AddModifyDeleteOnCharacterController) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C18977601_Material_FrictionCombinePriority.py b/AutomatedTesting/Gem/PythonTests/physics/material/C18977601_Material_FrictionCombinePriority.py old mode 100755 new mode 100644 similarity index 99% rename from AutomatedTesting/Gem/PythonTests/physics/C18977601_Material_FrictionCombinePriority.py rename to AutomatedTesting/Gem/PythonTests/physics/material/C18977601_Material_FrictionCombinePriority.py index 14103ad223..4cef743854 --- a/AutomatedTesting/Gem/PythonTests/physics/C18977601_Material_FrictionCombinePriority.py +++ b/AutomatedTesting/Gem/PythonTests/physics/material/C18977601_Material_FrictionCombinePriority.py @@ -126,12 +126,6 @@ def C18977601_Material_FrictionCombinePriority(): """ import os import sys - - import ImportPathHelper as imports - - imports.init() - - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -357,8 +351,5 @@ def C18977601_Material_FrictionCombinePriority(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C18977601_Material_FrictionCombinePriority) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C18981526_Material_RestitutionCombinePriority.py b/AutomatedTesting/Gem/PythonTests/physics/material/C18981526_Material_RestitutionCombinePriority.py old mode 100755 new mode 100644 similarity index 99% rename from AutomatedTesting/Gem/PythonTests/physics/C18981526_Material_RestitutionCombinePriority.py rename to AutomatedTesting/Gem/PythonTests/physics/material/C18981526_Material_RestitutionCombinePriority.py index 696eb1115a..9663453df2 --- a/AutomatedTesting/Gem/PythonTests/physics/C18981526_Material_RestitutionCombinePriority.py +++ b/AutomatedTesting/Gem/PythonTests/physics/material/C18981526_Material_RestitutionCombinePriority.py @@ -126,11 +126,6 @@ def C18981526_Material_RestitutionCombinePriority(): """ import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -417,8 +412,5 @@ def C18981526_Material_RestitutionCombinePriority(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C18981526_Material_RestitutionCombinePriority) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4044455_Material_libraryChangesInstantly.py b/AutomatedTesting/Gem/PythonTests/physics/material/C4044455_Material_libraryChangesInstantly.py old mode 100755 new mode 100644 similarity index 99% rename from AutomatedTesting/Gem/PythonTests/physics/C4044455_Material_libraryChangesInstantly.py rename to AutomatedTesting/Gem/PythonTests/physics/material/C4044455_Material_libraryChangesInstantly.py index 8a84f5302f..8eb2e7e9a4 --- a/AutomatedTesting/Gem/PythonTests/physics/C4044455_Material_libraryChangesInstantly.py +++ b/AutomatedTesting/Gem/PythonTests/physics/material/C4044455_Material_libraryChangesInstantly.py @@ -173,11 +173,6 @@ def C4044455_Material_libraryChangesInstantly(): import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -478,8 +473,5 @@ def C4044455_Material_libraryChangesInstantly(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C4044455_Material_libraryChangesInstantly) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4044456_Material_FrictionCombine.py b/AutomatedTesting/Gem/PythonTests/physics/material/C4044456_Material_FrictionCombine.py old mode 100755 new mode 100644 similarity index 98% rename from AutomatedTesting/Gem/PythonTests/physics/C4044456_Material_FrictionCombine.py rename to AutomatedTesting/Gem/PythonTests/physics/material/C4044456_Material_FrictionCombine.py index 3048224d79..8c3b389264 --- a/AutomatedTesting/Gem/PythonTests/physics/C4044456_Material_FrictionCombine.py +++ b/AutomatedTesting/Gem/PythonTests/physics/material/C4044456_Material_FrictionCombine.py @@ -91,11 +91,6 @@ def C4044456_Material_FrictionCombine(): """ import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -213,8 +208,5 @@ def C4044456_Material_FrictionCombine(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C4044456_Material_FrictionCombine) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4044457_Material_RestitutionCombine.py b/AutomatedTesting/Gem/PythonTests/physics/material/C4044457_Material_RestitutionCombine.py old mode 100755 new mode 100644 similarity index 98% rename from AutomatedTesting/Gem/PythonTests/physics/C4044457_Material_RestitutionCombine.py rename to AutomatedTesting/Gem/PythonTests/physics/material/C4044457_Material_RestitutionCombine.py index 2ba038c928..a20c7e49f7 --- a/AutomatedTesting/Gem/PythonTests/physics/C4044457_Material_RestitutionCombine.py +++ b/AutomatedTesting/Gem/PythonTests/physics/material/C4044457_Material_RestitutionCombine.py @@ -96,11 +96,6 @@ def C4044457_Material_RestitutionCombine(): """ import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -245,8 +240,5 @@ def C4044457_Material_RestitutionCombine(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C4044457_Material_RestitutionCombine) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4044459_Material_DynamicFriction.py b/AutomatedTesting/Gem/PythonTests/physics/material/C4044459_Material_DynamicFriction.py old mode 100755 new mode 100644 similarity index 98% rename from AutomatedTesting/Gem/PythonTests/physics/C4044459_Material_DynamicFriction.py rename to AutomatedTesting/Gem/PythonTests/physics/material/C4044459_Material_DynamicFriction.py index 096a1bc742..cdf2816f17 --- a/AutomatedTesting/Gem/PythonTests/physics/C4044459_Material_DynamicFriction.py +++ b/AutomatedTesting/Gem/PythonTests/physics/material/C4044459_Material_DynamicFriction.py @@ -82,11 +82,6 @@ def C4044459_Material_DynamicFriction(): """ import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -191,8 +186,5 @@ def C4044459_Material_DynamicFriction(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C4044459_Material_DynamicFriction) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4044460_Material_StaticFriction.py b/AutomatedTesting/Gem/PythonTests/physics/material/C4044460_Material_StaticFriction.py old mode 100755 new mode 100644 similarity index 98% rename from AutomatedTesting/Gem/PythonTests/physics/C4044460_Material_StaticFriction.py rename to AutomatedTesting/Gem/PythonTests/physics/material/C4044460_Material_StaticFriction.py index 9730b28e73..5558f01222 --- a/AutomatedTesting/Gem/PythonTests/physics/C4044460_Material_StaticFriction.py +++ b/AutomatedTesting/Gem/PythonTests/physics/material/C4044460_Material_StaticFriction.py @@ -80,11 +80,6 @@ def C4044460_Material_StaticFriction(): """ import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -188,8 +183,5 @@ def C4044460_Material_StaticFriction(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C4044460_Material_StaticFriction) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4044461_Material_Restitution.py b/AutomatedTesting/Gem/PythonTests/physics/material/C4044461_Material_Restitution.py old mode 100755 new mode 100644 similarity index 98% rename from AutomatedTesting/Gem/PythonTests/physics/C4044461_Material_Restitution.py rename to AutomatedTesting/Gem/PythonTests/physics/material/C4044461_Material_Restitution.py index 9cb54331cb..b077af1593 --- a/AutomatedTesting/Gem/PythonTests/physics/C4044461_Material_Restitution.py +++ b/AutomatedTesting/Gem/PythonTests/physics/material/C4044461_Material_Restitution.py @@ -87,11 +87,6 @@ def C4044461_Material_Restitution(): """ import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -230,8 +225,5 @@ def C4044461_Material_Restitution(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C4044461_Material_Restitution) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4044694_Material_EmptyLibraryUsesDefault.py b/AutomatedTesting/Gem/PythonTests/physics/material/C4044694_Material_EmptyLibraryUsesDefault.py old mode 100755 new mode 100644 similarity index 98% rename from AutomatedTesting/Gem/PythonTests/physics/C4044694_Material_EmptyLibraryUsesDefault.py rename to AutomatedTesting/Gem/PythonTests/physics/material/C4044694_Material_EmptyLibraryUsesDefault.py index 4cf092d3bf..8cba90cba8 --- a/AutomatedTesting/Gem/PythonTests/physics/C4044694_Material_EmptyLibraryUsesDefault.py +++ b/AutomatedTesting/Gem/PythonTests/physics/material/C4044694_Material_EmptyLibraryUsesDefault.py @@ -66,11 +66,6 @@ def C4044694_Material_EmptyLibraryUsesDefault(): """ import os import sys - - import ImportPathHelper as imports - - imports.init() - import azlmbr.legacy.general as general import azlmbr.bus as bus import azlmbr.components @@ -189,8 +184,5 @@ def C4044694_Material_EmptyLibraryUsesDefault(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C4044694_Material_EmptyLibraryUsesDefault) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4044697_Material_PerfaceMaterialValidation.py b/AutomatedTesting/Gem/PythonTests/physics/material/C4044697_Material_PerfaceMaterialValidation.py old mode 100755 new mode 100644 similarity index 99% rename from AutomatedTesting/Gem/PythonTests/physics/C4044697_Material_PerfaceMaterialValidation.py rename to AutomatedTesting/Gem/PythonTests/physics/material/C4044697_Material_PerfaceMaterialValidation.py index e365a799aa..9ee8d404d7 --- a/AutomatedTesting/Gem/PythonTests/physics/C4044697_Material_PerfaceMaterialValidation.py +++ b/AutomatedTesting/Gem/PythonTests/physics/material/C4044697_Material_PerfaceMaterialValidation.py @@ -107,11 +107,6 @@ def C4044697_Material_PerfaceMaterialValidation(): """ import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -302,8 +297,5 @@ def C4044697_Material_PerfaceMaterialValidation(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C4044697_Material_PerfaceMaterialValidation) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4888315_Material_AddModifyDeleteOnCollider.py b/AutomatedTesting/Gem/PythonTests/physics/material/C4888315_Material_AddModifyDeleteOnCollider.py old mode 100755 new mode 100644 similarity index 98% rename from AutomatedTesting/Gem/PythonTests/physics/C4888315_Material_AddModifyDeleteOnCollider.py rename to AutomatedTesting/Gem/PythonTests/physics/material/C4888315_Material_AddModifyDeleteOnCollider.py index d66cf17b5f..61c378d287 --- a/AutomatedTesting/Gem/PythonTests/physics/C4888315_Material_AddModifyDeleteOnCollider.py +++ b/AutomatedTesting/Gem/PythonTests/physics/material/C4888315_Material_AddModifyDeleteOnCollider.py @@ -90,11 +90,6 @@ def C4888315_Material_AddModifyDeleteOnCollider(): """ import os import sys - - import ImportPathHelper as imports - - imports.init() - import azlmbr.legacy.general as general import azlmbr.math as lymath @@ -176,8 +171,5 @@ def C4888315_Material_AddModifyDeleteOnCollider(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C4888315_Material_AddModifyDeleteOnCollider) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4925577_Materials_MaterialAssignedToTerrain.py b/AutomatedTesting/Gem/PythonTests/physics/material/C4925577_Materials_MaterialAssignedToTerrain.py old mode 100755 new mode 100644 similarity index 99% rename from AutomatedTesting/Gem/PythonTests/physics/C4925577_Materials_MaterialAssignedToTerrain.py rename to AutomatedTesting/Gem/PythonTests/physics/material/C4925577_Materials_MaterialAssignedToTerrain.py index feafce07d5..219e12fdb2 --- a/AutomatedTesting/Gem/PythonTests/physics/C4925577_Materials_MaterialAssignedToTerrain.py +++ b/AutomatedTesting/Gem/PythonTests/physics/material/C4925577_Materials_MaterialAssignedToTerrain.py @@ -76,11 +76,6 @@ def C4925577_Materials_MaterialAssignedToTerrain(): """ import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -305,8 +300,5 @@ def C4925577_Materials_MaterialAssignedToTerrain(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C4925577_Materials_MaterialAssignedToTerrain) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4925579_Material_AddModifyDeleteOnTerrain.py b/AutomatedTesting/Gem/PythonTests/physics/material/C4925579_Material_AddModifyDeleteOnTerrain.py old mode 100755 new mode 100644 similarity index 98% rename from AutomatedTesting/Gem/PythonTests/physics/C4925579_Material_AddModifyDeleteOnTerrain.py rename to AutomatedTesting/Gem/PythonTests/physics/material/C4925579_Material_AddModifyDeleteOnTerrain.py index db2093047e..8b3d72a932 --- a/AutomatedTesting/Gem/PythonTests/physics/C4925579_Material_AddModifyDeleteOnTerrain.py +++ b/AutomatedTesting/Gem/PythonTests/physics/material/C4925579_Material_AddModifyDeleteOnTerrain.py @@ -91,11 +91,6 @@ def C4925579_Material_AddModifyDeleteOnTerrain(): """ import os import sys - - import ImportPathHelper as imports - - imports.init() - import azlmbr.legacy.general as general import azlmbr.math as lymath @@ -176,8 +171,5 @@ def C4925579_Material_AddModifyDeleteOnTerrain(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C4925579_Material_AddModifyDeleteOnTerrain) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4925580_Material_RagdollBonesMaterial.py b/AutomatedTesting/Gem/PythonTests/physics/material/C4925580_Material_RagdollBonesMaterial.py old mode 100755 new mode 100644 similarity index 98% rename from AutomatedTesting/Gem/PythonTests/physics/C4925580_Material_RagdollBonesMaterial.py rename to AutomatedTesting/Gem/PythonTests/physics/material/C4925580_Material_RagdollBonesMaterial.py index 203db0bd39..96316b1cdf --- a/AutomatedTesting/Gem/PythonTests/physics/C4925580_Material_RagdollBonesMaterial.py +++ b/AutomatedTesting/Gem/PythonTests/physics/material/C4925580_Material_RagdollBonesMaterial.py @@ -66,11 +66,6 @@ def C4925580_Material_RagdollBonesMaterial(): # Setup path import os import sys - - import ImportPathHelper as imports - - imports.init() - import azlmbr.legacy.general as general import azlmbr.bus import azlmbr.components @@ -194,8 +189,5 @@ def C4925580_Material_RagdollBonesMaterial(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C4925580_Material_RagdollBonesMaterial) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4925582_Material_AddModifyDeleteOnRagdollBones.py b/AutomatedTesting/Gem/PythonTests/physics/material/C4925582_Material_AddModifyDeleteOnRagdollBones.py old mode 100755 new mode 100644 similarity index 98% rename from AutomatedTesting/Gem/PythonTests/physics/C4925582_Material_AddModifyDeleteOnRagdollBones.py rename to AutomatedTesting/Gem/PythonTests/physics/material/C4925582_Material_AddModifyDeleteOnRagdollBones.py index acdfb98411..0abfae08f9 --- a/AutomatedTesting/Gem/PythonTests/physics/C4925582_Material_AddModifyDeleteOnRagdollBones.py +++ b/AutomatedTesting/Gem/PythonTests/physics/material/C4925582_Material_AddModifyDeleteOnRagdollBones.py @@ -92,11 +92,6 @@ def C4925582_Material_AddModifyDeleteOnRagdollBones(): """ import os import sys - - import ImportPathHelper as imports - - imports.init() - import azlmbr.legacy.general as general import azlmbr.bus as bus import azlmbr.components @@ -212,8 +207,5 @@ def C4925582_Material_AddModifyDeleteOnRagdollBones(): Report.info("Modified max bouce: " + str(modified_ragdoll.bounces[0])) if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C4925582_Material_AddModifyDeleteOnRagdollBones) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5296614_PhysXMaterial_ColliderShape.py b/AutomatedTesting/Gem/PythonTests/physics/material/C5296614_PhysXMaterial_ColliderShape.py old mode 100755 new mode 100644 similarity index 98% rename from AutomatedTesting/Gem/PythonTests/physics/C5296614_PhysXMaterial_ColliderShape.py rename to AutomatedTesting/Gem/PythonTests/physics/material/C5296614_PhysXMaterial_ColliderShape.py index 82275d1b0d..de7ed4db9b --- a/AutomatedTesting/Gem/PythonTests/physics/C5296614_PhysXMaterial_ColliderShape.py +++ b/AutomatedTesting/Gem/PythonTests/physics/material/C5296614_PhysXMaterial_ColliderShape.py @@ -60,11 +60,6 @@ def C5296614_PhysXMaterial_ColliderShape(): import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general @@ -152,8 +147,5 @@ def C5296614_PhysXMaterial_ColliderShape(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C5296614_PhysXMaterial_ColliderShape) diff --git a/AutomatedTesting/Gem/PythonTests/physics/Physmaterial_Editor.py b/AutomatedTesting/Gem/PythonTests/physics/material/Physmaterial_Editor.py old mode 100755 new mode 100644 similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/Physmaterial_Editor.py rename to AutomatedTesting/Gem/PythonTests/physics/material/Physmaterial_Editor.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/C13895144_Ragdoll_ChangeLevel.py b/AutomatedTesting/Gem/PythonTests/physics/ragdoll/C13895144_Ragdoll_ChangeLevel.py old mode 100755 new mode 100644 similarity index 96% rename from AutomatedTesting/Gem/PythonTests/physics/C13895144_Ragdoll_ChangeLevel.py rename to AutomatedTesting/Gem/PythonTests/physics/ragdoll/C13895144_Ragdoll_ChangeLevel.py index 28baa2bcf3..c7ff00a7e3 --- a/AutomatedTesting/Gem/PythonTests/physics/C13895144_Ragdoll_ChangeLevel.py +++ b/AutomatedTesting/Gem/PythonTests/physics/ragdoll/C13895144_Ragdoll_ChangeLevel.py @@ -58,11 +58,6 @@ def C13895144_Ragdoll_ChangeLevel(): """ import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -104,8 +99,5 @@ def C13895144_Ragdoll_ChangeLevel(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C13895144_Ragdoll_ChangeLevel) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C14654882_Ragdoll_ragdollAPTest.py b/AutomatedTesting/Gem/PythonTests/physics/ragdoll/C14654882_Ragdoll_ragdollAPTest.py old mode 100755 new mode 100644 similarity index 97% rename from AutomatedTesting/Gem/PythonTests/physics/C14654882_Ragdoll_ragdollAPTest.py rename to AutomatedTesting/Gem/PythonTests/physics/ragdoll/C14654882_Ragdoll_ragdollAPTest.py index 024126ef55..56784b0c72 --- a/AutomatedTesting/Gem/PythonTests/physics/C14654882_Ragdoll_ragdollAPTest.py +++ b/AutomatedTesting/Gem/PythonTests/physics/ragdoll/C14654882_Ragdoll_ragdollAPTest.py @@ -69,11 +69,6 @@ def C14654882_Ragdoll_ragdollAPTest(): """ import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -129,8 +124,5 @@ def C14654882_Ragdoll_ragdollAPTest(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C14654882_Ragdoll_ragdollAPTest) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C17411467_AddPhysxRagdollComponent.py b/AutomatedTesting/Gem/PythonTests/physics/ragdoll/C17411467_AddPhysxRagdollComponent.py old mode 100755 new mode 100644 similarity index 96% rename from AutomatedTesting/Gem/PythonTests/physics/C17411467_AddPhysxRagdollComponent.py rename to AutomatedTesting/Gem/PythonTests/physics/ragdoll/C17411467_AddPhysxRagdollComponent.py index ea58f84dad..9c02239d73 --- a/AutomatedTesting/Gem/PythonTests/physics/C17411467_AddPhysxRagdollComponent.py +++ b/AutomatedTesting/Gem/PythonTests/physics/ragdoll/C17411467_AddPhysxRagdollComponent.py @@ -9,7 +9,6 @@ Test Case Title : Check that Physx Ragdoll component can be added without errors """ - # fmt: off class Tests(): create_test_entity = ("Entity created successfully", "Failed to create Entity") @@ -45,10 +44,6 @@ def C17411467_AddPhysxRagdollComponent(): :return: None """ - # Helper file Imports - import ImportPathHelper as imports - - imports.init() from editor_python_test_tools.utils import Report from editor_python_test_tools.editor_entity_utils import EditorEntity from editor_python_test_tools.utils import TestHelper as helper @@ -93,8 +88,5 @@ def C17411467_AddPhysxRagdollComponent(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C17411467_AddPhysxRagdollComponent) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C28978033_Ragdoll_WorldBodyBusTests.py b/AutomatedTesting/Gem/PythonTests/physics/ragdoll/C28978033_Ragdoll_WorldBodyBusTests.py old mode 100755 new mode 100644 similarity index 97% rename from AutomatedTesting/Gem/PythonTests/physics/C28978033_Ragdoll_WorldBodyBusTests.py rename to AutomatedTesting/Gem/PythonTests/physics/ragdoll/C28978033_Ragdoll_WorldBodyBusTests.py index b22bcf5a36..d917449daf --- a/AutomatedTesting/Gem/PythonTests/physics/C28978033_Ragdoll_WorldBodyBusTests.py +++ b/AutomatedTesting/Gem/PythonTests/physics/ragdoll/C28978033_Ragdoll_WorldBodyBusTests.py @@ -45,11 +45,6 @@ def C28978033_Ragdoll_WorldBodyBusTests(): """ import os import sys - - import ImportPathHelper as imports - - imports.init() - import azlmbr.legacy.general as general import azlmbr.bus from editor_python_test_tools.utils import Report @@ -116,8 +111,5 @@ def C28978033_Ragdoll_WorldBodyBusTests(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C28978033_Ragdoll_WorldBodyBusTests) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C13351703_COM_NotIncludeTriggerShapes.py b/AutomatedTesting/Gem/PythonTests/physics/rigid_body/C13351703_COM_NotIncludeTriggerShapes.py old mode 100755 new mode 100644 similarity index 96% rename from AutomatedTesting/Gem/PythonTests/physics/C13351703_COM_NotIncludeTriggerShapes.py rename to AutomatedTesting/Gem/PythonTests/physics/rigid_body/C13351703_COM_NotIncludeTriggerShapes.py index a9e7727890..56f44503ae --- a/AutomatedTesting/Gem/PythonTests/physics/C13351703_COM_NotIncludeTriggerShapes.py +++ b/AutomatedTesting/Gem/PythonTests/physics/rigid_body/C13351703_COM_NotIncludeTriggerShapes.py @@ -55,11 +55,6 @@ def C13351703_COM_NotIncludeTriggerShapes(): import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -93,8 +88,5 @@ def C13351703_COM_NotIncludeTriggerShapes(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C13351703_COM_NotIncludeTriggerShapes) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C13352089_RigidBodies_MaxAngularVelocity.py b/AutomatedTesting/Gem/PythonTests/physics/rigid_body/C13352089_RigidBodies_MaxAngularVelocity.py old mode 100755 new mode 100644 similarity index 99% rename from AutomatedTesting/Gem/PythonTests/physics/C13352089_RigidBodies_MaxAngularVelocity.py rename to AutomatedTesting/Gem/PythonTests/physics/rigid_body/C13352089_RigidBodies_MaxAngularVelocity.py index 2342545a87..41635ecc47 --- a/AutomatedTesting/Gem/PythonTests/physics/C13352089_RigidBodies_MaxAngularVelocity.py +++ b/AutomatedTesting/Gem/PythonTests/physics/rigid_body/C13352089_RigidBodies_MaxAngularVelocity.py @@ -123,9 +123,7 @@ def C13352089_RigidBodies_MaxAngularVelocity(): import math import time - import ImportPathHelper as imports - imports.init() from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -281,8 +279,5 @@ def C13352089_RigidBodies_MaxAngularVelocity(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C13352089_RigidBodies_MaxAngularVelocity) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4976194_RigidBody_PhysXComponentIsValid.py b/AutomatedTesting/Gem/PythonTests/physics/rigid_body/C4976194_RigidBody_PhysXComponentIsValid.py old mode 100755 new mode 100644 similarity index 97% rename from AutomatedTesting/Gem/PythonTests/physics/C4976194_RigidBody_PhysXComponentIsValid.py rename to AutomatedTesting/Gem/PythonTests/physics/rigid_body/C4976194_RigidBody_PhysXComponentIsValid.py index 79c3e06814..b0b69d6d91 --- a/AutomatedTesting/Gem/PythonTests/physics/C4976194_RigidBody_PhysXComponentIsValid.py +++ b/AutomatedTesting/Gem/PythonTests/physics/rigid_body/C4976194_RigidBody_PhysXComponentIsValid.py @@ -54,9 +54,7 @@ def C4976194_RigidBody_PhysXComponentIsValid(): import os, sys - import ImportPathHelper as imports - imports.init() from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -110,8 +108,5 @@ def C4976194_RigidBody_PhysXComponentIsValid(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C4976194_RigidBody_PhysXComponentIsValid) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4976195_RigidBodies_InitialLinearVelocity.py b/AutomatedTesting/Gem/PythonTests/physics/rigid_body/C4976195_RigidBodies_InitialLinearVelocity.py old mode 100755 new mode 100644 similarity index 97% rename from AutomatedTesting/Gem/PythonTests/physics/C4976195_RigidBodies_InitialLinearVelocity.py rename to AutomatedTesting/Gem/PythonTests/physics/rigid_body/C4976195_RigidBodies_InitialLinearVelocity.py index 6bddae76f4..f13a7232fa --- a/AutomatedTesting/Gem/PythonTests/physics/C4976195_RigidBodies_InitialLinearVelocity.py +++ b/AutomatedTesting/Gem/PythonTests/physics/rigid_body/C4976195_RigidBodies_InitialLinearVelocity.py @@ -58,11 +58,6 @@ def C4976195_RigidBodies_InitialLinearVelocity(): import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -132,8 +127,5 @@ def C4976195_RigidBodies_InitialLinearVelocity(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C4976195_RigidBodies_InitialLinearVelocity) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4976197_RigidBodies_InitialAngularVelocity.py b/AutomatedTesting/Gem/PythonTests/physics/rigid_body/C4976197_RigidBodies_InitialAngularVelocity.py old mode 100755 new mode 100644 similarity index 98% rename from AutomatedTesting/Gem/PythonTests/physics/C4976197_RigidBodies_InitialAngularVelocity.py rename to AutomatedTesting/Gem/PythonTests/physics/rigid_body/C4976197_RigidBodies_InitialAngularVelocity.py index 73c1e88f79..7f400051ec --- a/AutomatedTesting/Gem/PythonTests/physics/C4976197_RigidBodies_InitialAngularVelocity.py +++ b/AutomatedTesting/Gem/PythonTests/physics/rigid_body/C4976197_RigidBodies_InitialAngularVelocity.py @@ -72,9 +72,7 @@ def C4976197_RigidBodies_InitialAngularVelocity(): import sys import math - import ImportPathHelper as imports - imports.init() from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -177,8 +175,5 @@ def C4976197_RigidBodies_InitialAngularVelocity(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C4976197_RigidBodies_InitialAngularVelocity) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4976199_RigidBodies_LinearDampingObjectMotion.py b/AutomatedTesting/Gem/PythonTests/physics/rigid_body/C4976199_RigidBodies_LinearDampingObjectMotion.py old mode 100755 new mode 100644 similarity index 98% rename from AutomatedTesting/Gem/PythonTests/physics/C4976199_RigidBodies_LinearDampingObjectMotion.py rename to AutomatedTesting/Gem/PythonTests/physics/rigid_body/C4976199_RigidBodies_LinearDampingObjectMotion.py index 08b212d1e7..502478f13c --- a/AutomatedTesting/Gem/PythonTests/physics/C4976199_RigidBodies_LinearDampingObjectMotion.py +++ b/AutomatedTesting/Gem/PythonTests/physics/rigid_body/C4976199_RigidBodies_LinearDampingObjectMotion.py @@ -56,11 +56,6 @@ def C4976199_RigidBodies_LinearDampingObjectMotion(): # Setup path import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -270,8 +265,5 @@ def C4976199_RigidBodies_LinearDampingObjectMotion(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C4976199_RigidBodies_LinearDampingObjectMotion) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4976200_RigidBody_AngularDampingObjectRotation.py b/AutomatedTesting/Gem/PythonTests/physics/rigid_body/C4976200_RigidBody_AngularDampingObjectRotation.py old mode 100755 new mode 100644 similarity index 99% rename from AutomatedTesting/Gem/PythonTests/physics/C4976200_RigidBody_AngularDampingObjectRotation.py rename to AutomatedTesting/Gem/PythonTests/physics/rigid_body/C4976200_RigidBody_AngularDampingObjectRotation.py index b889276554..77dfe4c483 --- a/AutomatedTesting/Gem/PythonTests/physics/C4976200_RigidBody_AngularDampingObjectRotation.py +++ b/AutomatedTesting/Gem/PythonTests/physics/rigid_body/C4976200_RigidBody_AngularDampingObjectRotation.py @@ -61,9 +61,7 @@ def C4976200_RigidBody_AngularDampingObjectRotation(): import sys import math - import ImportPathHelper as imports - imports.init() from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -285,8 +283,5 @@ def C4976200_RigidBody_AngularDampingObjectRotation(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C4976200_RigidBody_AngularDampingObjectRotation) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4976201_RigidBody_MassIsAssigned.py b/AutomatedTesting/Gem/PythonTests/physics/rigid_body/C4976201_RigidBody_MassIsAssigned.py old mode 100755 new mode 100644 similarity index 99% rename from AutomatedTesting/Gem/PythonTests/physics/C4976201_RigidBody_MassIsAssigned.py rename to AutomatedTesting/Gem/PythonTests/physics/rigid_body/C4976201_RigidBody_MassIsAssigned.py index 17fd0827c1..54f589da1e --- a/AutomatedTesting/Gem/PythonTests/physics/C4976201_RigidBody_MassIsAssigned.py +++ b/AutomatedTesting/Gem/PythonTests/physics/rigid_body/C4976201_RigidBody_MassIsAssigned.py @@ -101,11 +101,6 @@ def C4976201_RigidBody_MassIsAssigned(): import os import sys - - import ImportPathHelper as imports - - imports.init() - import azlmbr.legacy.general as general import azlmbr.bus import azlmbr @@ -373,8 +368,5 @@ def C4976201_RigidBody_MassIsAssigned(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C4976201_RigidBody_MassIsAssigned) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4976202_RigidBody_StopsWhenBelowKineticThreshold.py b/AutomatedTesting/Gem/PythonTests/physics/rigid_body/C4976202_RigidBody_StopsWhenBelowKineticThreshold.py old mode 100755 new mode 100644 similarity index 99% rename from AutomatedTesting/Gem/PythonTests/physics/C4976202_RigidBody_StopsWhenBelowKineticThreshold.py rename to AutomatedTesting/Gem/PythonTests/physics/rigid_body/C4976202_RigidBody_StopsWhenBelowKineticThreshold.py index 53415bf43a..655c33304d --- a/AutomatedTesting/Gem/PythonTests/physics/C4976202_RigidBody_StopsWhenBelowKineticThreshold.py +++ b/AutomatedTesting/Gem/PythonTests/physics/rigid_body/C4976202_RigidBody_StopsWhenBelowKineticThreshold.py @@ -124,11 +124,6 @@ def C4976202_RigidBody_StopsWhenBelowKineticThreshold(): import os import sys - - import ImportPathHelper as imports - - imports.init() - import azlmbr.legacy.general as general import azlmbr.bus @@ -326,8 +321,5 @@ def C4976202_RigidBody_StopsWhenBelowKineticThreshold(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C4976202_RigidBody_StopsWhenBelowKineticThreshold) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4976204_Verify_Start_Asleep_Condition.py b/AutomatedTesting/Gem/PythonTests/physics/rigid_body/C4976204_Verify_Start_Asleep_Condition.py old mode 100755 new mode 100644 similarity index 97% rename from AutomatedTesting/Gem/PythonTests/physics/C4976204_Verify_Start_Asleep_Condition.py rename to AutomatedTesting/Gem/PythonTests/physics/rigid_body/C4976204_Verify_Start_Asleep_Condition.py index 6c21912d11..ff3111aa55 --- a/AutomatedTesting/Gem/PythonTests/physics/C4976204_Verify_Start_Asleep_Condition.py +++ b/AutomatedTesting/Gem/PythonTests/physics/rigid_body/C4976204_Verify_Start_Asleep_Condition.py @@ -62,11 +62,6 @@ def C4976204_Verify_Start_Asleep_Condition(): import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -112,8 +107,5 @@ def C4976204_Verify_Start_Asleep_Condition(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C4976204_Verify_Start_Asleep_Condition) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4976206_RigidBodies_GravityEnabledActive.py b/AutomatedTesting/Gem/PythonTests/physics/rigid_body/C4976206_RigidBodies_GravityEnabledActive.py old mode 100755 new mode 100644 similarity index 97% rename from AutomatedTesting/Gem/PythonTests/physics/C4976206_RigidBodies_GravityEnabledActive.py rename to AutomatedTesting/Gem/PythonTests/physics/rigid_body/C4976206_RigidBodies_GravityEnabledActive.py index 96c62f26ea..e6b50eb2bf --- a/AutomatedTesting/Gem/PythonTests/physics/C4976206_RigidBodies_GravityEnabledActive.py +++ b/AutomatedTesting/Gem/PythonTests/physics/rigid_body/C4976206_RigidBodies_GravityEnabledActive.py @@ -64,11 +64,6 @@ def C4976206_RigidBodies_GravityEnabledActive(): import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -145,8 +140,5 @@ def C4976206_RigidBodies_GravityEnabledActive(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C4976206_RigidBodies_GravityEnabledActive) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4976207_PhysXRigidBodies_KinematicBehavior.py b/AutomatedTesting/Gem/PythonTests/physics/rigid_body/C4976207_PhysXRigidBodies_KinematicBehavior.py old mode 100755 new mode 100644 similarity index 97% rename from AutomatedTesting/Gem/PythonTests/physics/C4976207_PhysXRigidBodies_KinematicBehavior.py rename to AutomatedTesting/Gem/PythonTests/physics/rigid_body/C4976207_PhysXRigidBodies_KinematicBehavior.py index 81bed2bbde..65814bd438 --- a/AutomatedTesting/Gem/PythonTests/physics/C4976207_PhysXRigidBodies_KinematicBehavior.py +++ b/AutomatedTesting/Gem/PythonTests/physics/rigid_body/C4976207_PhysXRigidBodies_KinematicBehavior.py @@ -59,11 +59,6 @@ def C4976207_PhysXRigidBodies_KinematicBehavior(): # Setup path import os import sys - import ImportPathHelper as imports - - imports.init() - - import azlmbr.legacy.general as general import azlmbr.bus from editor_python_test_tools.utils import Report @@ -132,8 +127,5 @@ def C4976207_PhysXRigidBodies_KinematicBehavior(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C4976207_PhysXRigidBodies_KinematicBehavior) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4976209_RigidBody_ComputesCOM.py b/AutomatedTesting/Gem/PythonTests/physics/rigid_body/C4976209_RigidBody_ComputesCOM.py old mode 100755 new mode 100644 similarity index 98% rename from AutomatedTesting/Gem/PythonTests/physics/C4976209_RigidBody_ComputesCOM.py rename to AutomatedTesting/Gem/PythonTests/physics/rigid_body/C4976209_RigidBody_ComputesCOM.py index f3f57b2b65..27d4ea1356 --- a/AutomatedTesting/Gem/PythonTests/physics/C4976209_RigidBody_ComputesCOM.py +++ b/AutomatedTesting/Gem/PythonTests/physics/rigid_body/C4976209_RigidBody_ComputesCOM.py @@ -86,11 +86,6 @@ def C4976209_RigidBody_ComputesCOM(): # Setup path import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -173,8 +168,5 @@ def C4976209_RigidBody_ComputesCOM(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C4976209_RigidBody_ComputesCOM) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4976210_COM_ManualSetting.py b/AutomatedTesting/Gem/PythonTests/physics/rigid_body/C4976210_COM_ManualSetting.py old mode 100755 new mode 100644 similarity index 99% rename from AutomatedTesting/Gem/PythonTests/physics/C4976210_COM_ManualSetting.py rename to AutomatedTesting/Gem/PythonTests/physics/rigid_body/C4976210_COM_ManualSetting.py index 9373f20850..cbbefb5a0e --- a/AutomatedTesting/Gem/PythonTests/physics/C4976210_COM_ManualSetting.py +++ b/AutomatedTesting/Gem/PythonTests/physics/rigid_body/C4976210_COM_ManualSetting.py @@ -69,9 +69,7 @@ def C4976210_COM_ManualSetting(): """ # internal editor imports - import ImportPathHelper as imports - imports.init() from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -298,8 +296,5 @@ def C4976210_COM_ManualSetting(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C4976210_COM_ManualSetting) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4976218_RigidBodies_InertiaObjectsNotComputed.py b/AutomatedTesting/Gem/PythonTests/physics/rigid_body/C4976218_RigidBodies_InertiaObjectsNotComputed.py old mode 100755 new mode 100644 similarity index 98% rename from AutomatedTesting/Gem/PythonTests/physics/C4976218_RigidBodies_InertiaObjectsNotComputed.py rename to AutomatedTesting/Gem/PythonTests/physics/rigid_body/C4976218_RigidBodies_InertiaObjectsNotComputed.py index ef19a00042..eb87fd0c68 --- a/AutomatedTesting/Gem/PythonTests/physics/C4976218_RigidBodies_InertiaObjectsNotComputed.py +++ b/AutomatedTesting/Gem/PythonTests/physics/rigid_body/C4976218_RigidBodies_InertiaObjectsNotComputed.py @@ -39,11 +39,6 @@ def C4976218_RigidBodies_InertiaObjectsNotComputed(): # Setup path import os import sys - - import ImportPathHelper as imports - - imports.init() - import azlmbr.legacy.general as general import azlmbr.bus as bus import azlmbr.components @@ -161,8 +156,5 @@ def C4976218_RigidBodies_InertiaObjectsNotComputed(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C4976218_RigidBodies_InertiaObjectsNotComputed) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5340400_RigidBody_ManualMomentOfInertia.py b/AutomatedTesting/Gem/PythonTests/physics/rigid_body/C5340400_RigidBody_ManualMomentOfInertia.py old mode 100755 new mode 100644 similarity index 98% rename from AutomatedTesting/Gem/PythonTests/physics/C5340400_RigidBody_ManualMomentOfInertia.py rename to AutomatedTesting/Gem/PythonTests/physics/rigid_body/C5340400_RigidBody_ManualMomentOfInertia.py index 7daf9d3dc8..92d3945391 --- a/AutomatedTesting/Gem/PythonTests/physics/C5340400_RigidBody_ManualMomentOfInertia.py +++ b/AutomatedTesting/Gem/PythonTests/physics/rigid_body/C5340400_RigidBody_ManualMomentOfInertia.py @@ -67,11 +67,6 @@ def C5340400_RigidBody_ManualMomentOfInertia(): # Setup path import os import sys - - import ImportPathHelper as imports - - imports.init() - import azlmbr.legacy.general as general import azlmbr.bus from editor_python_test_tools.utils import Report @@ -160,8 +155,5 @@ def C5340400_RigidBody_ManualMomentOfInertia(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C5340400_RigidBody_ManualMomentOfInertia) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C12712452_ScriptCanvas_CollisionEvents.py b/AutomatedTesting/Gem/PythonTests/physics/script_canvas/C12712452_ScriptCanvas_CollisionEvents.py old mode 100755 new mode 100644 similarity index 98% rename from AutomatedTesting/Gem/PythonTests/physics/C12712452_ScriptCanvas_CollisionEvents.py rename to AutomatedTesting/Gem/PythonTests/physics/script_canvas/C12712452_ScriptCanvas_CollisionEvents.py index 3d3011ef26..6806d5acc8 --- a/AutomatedTesting/Gem/PythonTests/physics/C12712452_ScriptCanvas_CollisionEvents.py +++ b/AutomatedTesting/Gem/PythonTests/physics/script_canvas/C12712452_ScriptCanvas_CollisionEvents.py @@ -67,11 +67,6 @@ def C12712452_ScriptCanvas_CollisionEvents(): # Setup path import os import sys - - import ImportPathHelper as imports - - imports.init() - import azlmbr.legacy.general as general import azlmbr.bus import azlmbr.components @@ -201,8 +196,5 @@ def C12712452_ScriptCanvas_CollisionEvents(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C12712452_ScriptCanvas_CollisionEvents) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C12712453_ScriptCanvas_MultipleRaycastNode.py b/AutomatedTesting/Gem/PythonTests/physics/script_canvas/C12712453_ScriptCanvas_MultipleRaycastNode.py old mode 100755 new mode 100644 similarity index 98% rename from AutomatedTesting/Gem/PythonTests/physics/C12712453_ScriptCanvas_MultipleRaycastNode.py rename to AutomatedTesting/Gem/PythonTests/physics/script_canvas/C12712453_ScriptCanvas_MultipleRaycastNode.py index 2e4c0a3fe2..edbbde4c94 --- a/AutomatedTesting/Gem/PythonTests/physics/C12712453_ScriptCanvas_MultipleRaycastNode.py +++ b/AutomatedTesting/Gem/PythonTests/physics/script_canvas/C12712453_ScriptCanvas_MultipleRaycastNode.py @@ -75,11 +75,6 @@ def C12712453_ScriptCanvas_MultipleRaycastNode(): import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -199,8 +194,5 @@ def C12712453_ScriptCanvas_MultipleRaycastNode(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C12712453_ScriptCanvas_MultipleRaycastNode) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C12712454_ScriptCanvas_OverlapNodeVerification.py b/AutomatedTesting/Gem/PythonTests/physics/script_canvas/C12712454_ScriptCanvas_OverlapNodeVerification.py old mode 100755 new mode 100644 similarity index 99% rename from AutomatedTesting/Gem/PythonTests/physics/C12712454_ScriptCanvas_OverlapNodeVerification.py rename to AutomatedTesting/Gem/PythonTests/physics/script_canvas/C12712454_ScriptCanvas_OverlapNodeVerification.py index f741f0d019..5829e5850c --- a/AutomatedTesting/Gem/PythonTests/physics/C12712454_ScriptCanvas_OverlapNodeVerification.py +++ b/AutomatedTesting/Gem/PythonTests/physics/script_canvas/C12712454_ScriptCanvas_OverlapNodeVerification.py @@ -97,11 +97,6 @@ def C12712454_ScriptCanvas_OverlapNodeVerification(): """ import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -320,8 +315,5 @@ def C12712454_ScriptCanvas_OverlapNodeVerification(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C12712454_ScriptCanvas_OverlapNodeVerification) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C12712455_ScriptCanvas_ShapeCastVerification.py b/AutomatedTesting/Gem/PythonTests/physics/script_canvas/C12712455_ScriptCanvas_ShapeCastVerification.py old mode 100755 new mode 100644 similarity index 98% rename from AutomatedTesting/Gem/PythonTests/physics/C12712455_ScriptCanvas_ShapeCastVerification.py rename to AutomatedTesting/Gem/PythonTests/physics/script_canvas/C12712455_ScriptCanvas_ShapeCastVerification.py index 581c6033e9..8ce59d2b29 --- a/AutomatedTesting/Gem/PythonTests/physics/C12712455_ScriptCanvas_ShapeCastVerification.py +++ b/AutomatedTesting/Gem/PythonTests/physics/script_canvas/C12712455_ScriptCanvas_ShapeCastVerification.py @@ -67,11 +67,6 @@ def C12712455_ScriptCanvas_ShapeCastVerification(): """ import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -137,8 +132,5 @@ def C12712455_ScriptCanvas_ShapeCastVerification(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C12712455_ScriptCanvas_ShapeCastVerification) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C14195074_ScriptCanvas_PostUpdateEvent.py b/AutomatedTesting/Gem/PythonTests/physics/script_canvas/C14195074_ScriptCanvas_PostUpdateEvent.py old mode 100755 new mode 100644 similarity index 98% rename from AutomatedTesting/Gem/PythonTests/physics/C14195074_ScriptCanvas_PostUpdateEvent.py rename to AutomatedTesting/Gem/PythonTests/physics/script_canvas/C14195074_ScriptCanvas_PostUpdateEvent.py index 08adccfc60..2c833ba5f3 --- a/AutomatedTesting/Gem/PythonTests/physics/C14195074_ScriptCanvas_PostUpdateEvent.py +++ b/AutomatedTesting/Gem/PythonTests/physics/script_canvas/C14195074_ScriptCanvas_PostUpdateEvent.py @@ -61,11 +61,6 @@ def C14195074_ScriptCanvas_PostUpdateEvent(): """ import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -182,8 +177,5 @@ def C14195074_ScriptCanvas_PostUpdateEvent(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C14195074_ScriptCanvas_PostUpdateEvent) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C14902097_ScriptCanvas_PreUpdateEvent.py b/AutomatedTesting/Gem/PythonTests/physics/script_canvas/C14902097_ScriptCanvas_PreUpdateEvent.py old mode 100755 new mode 100644 similarity index 98% rename from AutomatedTesting/Gem/PythonTests/physics/C14902097_ScriptCanvas_PreUpdateEvent.py rename to AutomatedTesting/Gem/PythonTests/physics/script_canvas/C14902097_ScriptCanvas_PreUpdateEvent.py index 2a2ce3aaf6..4d48ce34a6 --- a/AutomatedTesting/Gem/PythonTests/physics/C14902097_ScriptCanvas_PreUpdateEvent.py +++ b/AutomatedTesting/Gem/PythonTests/physics/script_canvas/C14902097_ScriptCanvas_PreUpdateEvent.py @@ -64,9 +64,7 @@ def C14902097_ScriptCanvas_PreUpdateEvent(): import os import sys - import ImportPathHelper as imports - imports.init() from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -189,8 +187,5 @@ def C14902097_ScriptCanvas_PreUpdateEvent(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C14902097_ScriptCanvas_PreUpdateEvent) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C14902098_ScriptCanvas_PostPhysicsUpdate.py b/AutomatedTesting/Gem/PythonTests/physics/script_canvas/C14902098_ScriptCanvas_PostPhysicsUpdate.py old mode 100755 new mode 100644 similarity index 97% rename from AutomatedTesting/Gem/PythonTests/physics/C14902098_ScriptCanvas_PostPhysicsUpdate.py rename to AutomatedTesting/Gem/PythonTests/physics/script_canvas/C14902098_ScriptCanvas_PostPhysicsUpdate.py index b977b9ae10..5cb0b1431e --- a/AutomatedTesting/Gem/PythonTests/physics/C14902098_ScriptCanvas_PostPhysicsUpdate.py +++ b/AutomatedTesting/Gem/PythonTests/physics/script_canvas/C14902098_ScriptCanvas_PostPhysicsUpdate.py @@ -75,11 +75,6 @@ def C14902098_ScriptCanvas_PostPhysicsUpdate(): import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -110,8 +105,5 @@ def C14902098_ScriptCanvas_PostPhysicsUpdate(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C14902098_ScriptCanvas_PostPhysicsUpdate) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C14976308_ScriptCanvas_SetKinematicTargetTransform.py b/AutomatedTesting/Gem/PythonTests/physics/script_canvas/C14976308_ScriptCanvas_SetKinematicTargetTransform.py old mode 100755 new mode 100644 similarity index 99% rename from AutomatedTesting/Gem/PythonTests/physics/C14976308_ScriptCanvas_SetKinematicTargetTransform.py rename to AutomatedTesting/Gem/PythonTests/physics/script_canvas/C14976308_ScriptCanvas_SetKinematicTargetTransform.py index 2827ba5f16..9e8331f369 --- a/AutomatedTesting/Gem/PythonTests/physics/C14976308_ScriptCanvas_SetKinematicTargetTransform.py +++ b/AutomatedTesting/Gem/PythonTests/physics/script_canvas/C14976308_ScriptCanvas_SetKinematicTargetTransform.py @@ -91,11 +91,6 @@ def C14976308_ScriptCanvas_SetKinematicTargetTransform(): # Setup path import os import sys - - import ImportPathHelper as imports - - imports.init() - import azlmbr.legacy.general as general import azlmbr.bus import azlmbr.components @@ -220,8 +215,5 @@ def C14976308_ScriptCanvas_SetKinematicTargetTransform(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C14976308_ScriptCanvas_SetKinematicTargetTransform) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C6224408_ScriptCanvas_EntitySpawn.py b/AutomatedTesting/Gem/PythonTests/physics/script_canvas/C6224408_ScriptCanvas_EntitySpawn.py old mode 100755 new mode 100644 similarity index 97% rename from AutomatedTesting/Gem/PythonTests/physics/C6224408_ScriptCanvas_EntitySpawn.py rename to AutomatedTesting/Gem/PythonTests/physics/script_canvas/C6224408_ScriptCanvas_EntitySpawn.py index c458073799..12e4a25b4d --- a/AutomatedTesting/Gem/PythonTests/physics/C6224408_ScriptCanvas_EntitySpawn.py +++ b/AutomatedTesting/Gem/PythonTests/physics/script_canvas/C6224408_ScriptCanvas_EntitySpawn.py @@ -60,11 +60,6 @@ def C6224408_ScriptCanvas_EntitySpawn(): """ import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -144,8 +139,5 @@ def C6224408_ScriptCanvas_EntitySpawn(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C6224408_ScriptCanvas_EntitySpawn) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C6274125_ScriptCanvas_TriggerEvents.py b/AutomatedTesting/Gem/PythonTests/physics/script_canvas/C6274125_ScriptCanvas_TriggerEvents.py old mode 100755 new mode 100644 similarity index 97% rename from AutomatedTesting/Gem/PythonTests/physics/C6274125_ScriptCanvas_TriggerEvents.py rename to AutomatedTesting/Gem/PythonTests/physics/script_canvas/C6274125_ScriptCanvas_TriggerEvents.py index 0e7ca0c8d3..5fc4261607 --- a/AutomatedTesting/Gem/PythonTests/physics/C6274125_ScriptCanvas_TriggerEvents.py +++ b/AutomatedTesting/Gem/PythonTests/physics/script_canvas/C6274125_ScriptCanvas_TriggerEvents.py @@ -66,11 +66,6 @@ def C6274125_ScriptCanvas_TriggerEvents(): import os import sys - - import ImportPathHelper as imports - - imports.init() - import azlmbr.legacy.general as general import azlmbr.bus @@ -128,8 +123,5 @@ def C6274125_ScriptCanvas_TriggerEvents(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C6274125_ScriptCanvas_TriggerEvents) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C13508019_Terrain_TerrainTexturePainterWorks.py b/AutomatedTesting/Gem/PythonTests/physics/terrain/C13508019_Terrain_TerrainTexturePainterWorks.py old mode 100755 new mode 100644 similarity index 98% rename from AutomatedTesting/Gem/PythonTests/physics/C13508019_Terrain_TerrainTexturePainterWorks.py rename to AutomatedTesting/Gem/PythonTests/physics/terrain/C13508019_Terrain_TerrainTexturePainterWorks.py index 87534ffd58..9822b933d1 --- a/AutomatedTesting/Gem/PythonTests/physics/C13508019_Terrain_TerrainTexturePainterWorks.py +++ b/AutomatedTesting/Gem/PythonTests/physics/terrain/C13508019_Terrain_TerrainTexturePainterWorks.py @@ -40,9 +40,7 @@ def C13508019_Terrain_TerrainTexturePainterWorks(): # Setup path import os, sys - import ImportPathHelper as imports - imports.init() from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -137,8 +135,5 @@ def C13508019_Terrain_TerrainTexturePainterWorks(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C13508019_Terrain_TerrainTexturePainterWorks) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C15308217_NoCrash_LevelSwitch.py b/AutomatedTesting/Gem/PythonTests/physics/terrain/C15308217_NoCrash_LevelSwitch.py old mode 100755 new mode 100644 similarity index 96% rename from AutomatedTesting/Gem/PythonTests/physics/C15308217_NoCrash_LevelSwitch.py rename to AutomatedTesting/Gem/PythonTests/physics/terrain/C15308217_NoCrash_LevelSwitch.py index 0fc5c65db3..f3641b12bc --- a/AutomatedTesting/Gem/PythonTests/physics/C15308217_NoCrash_LevelSwitch.py +++ b/AutomatedTesting/Gem/PythonTests/physics/terrain/C15308217_NoCrash_LevelSwitch.py @@ -62,11 +62,6 @@ def C15308217_NoCrash_LevelSwitch(): import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -106,8 +101,5 @@ def C15308217_NoCrash_LevelSwitch(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C15308217_NoCrash_LevelSwitch) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C3510642_Terrain_NotCollideWithTerrain.py b/AutomatedTesting/Gem/PythonTests/physics/terrain/C3510642_Terrain_NotCollideWithTerrain.py old mode 100755 new mode 100644 similarity index 98% rename from AutomatedTesting/Gem/PythonTests/physics/C3510642_Terrain_NotCollideWithTerrain.py rename to AutomatedTesting/Gem/PythonTests/physics/terrain/C3510642_Terrain_NotCollideWithTerrain.py index c3e1ac018c..09522da31a --- a/AutomatedTesting/Gem/PythonTests/physics/C3510642_Terrain_NotCollideWithTerrain.py +++ b/AutomatedTesting/Gem/PythonTests/physics/terrain/C3510642_Terrain_NotCollideWithTerrain.py @@ -65,11 +65,6 @@ def C3510642_Terrain_NotCollideWithTerrain(): import os import sys - - import ImportPathHelper as imports - - imports.init() - import azlmbr.legacy.general as general import azlmbr.bus @@ -168,8 +163,5 @@ def C3510642_Terrain_NotCollideWithTerrain(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C3510642_Terrain_NotCollideWithTerrain) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5689518_PhysXTerrain_CollidesWithPhysXTerrain.py b/AutomatedTesting/Gem/PythonTests/physics/terrain/C5689518_PhysXTerrain_CollidesWithPhysXTerrain.py old mode 100755 new mode 100644 similarity index 97% rename from AutomatedTesting/Gem/PythonTests/physics/C5689518_PhysXTerrain_CollidesWithPhysXTerrain.py rename to AutomatedTesting/Gem/PythonTests/physics/terrain/C5689518_PhysXTerrain_CollidesWithPhysXTerrain.py index b586c0b096..a10cc72ed2 --- a/AutomatedTesting/Gem/PythonTests/physics/C5689518_PhysXTerrain_CollidesWithPhysXTerrain.py +++ b/AutomatedTesting/Gem/PythonTests/physics/terrain/C5689518_PhysXTerrain_CollidesWithPhysXTerrain.py @@ -47,11 +47,6 @@ def C5689518_PhysXTerrain_CollidesWithPhysXTerrain(): """ import os import sys - - import ImportPathHelper as imports - - imports.init() - import azlmbr.legacy.general as general import azlmbr.bus from editor_python_test_tools.utils import Report @@ -113,8 +108,5 @@ def C5689518_PhysXTerrain_CollidesWithPhysXTerrain(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C5689518_PhysXTerrain_CollidesWithPhysXTerrain) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5689522_Physxterrain_AddPhysxterrainNoEditorCrash.py b/AutomatedTesting/Gem/PythonTests/physics/terrain/C5689522_Physxterrain_AddPhysxterrainNoEditorCrash.py old mode 100755 new mode 100644 similarity index 96% rename from AutomatedTesting/Gem/PythonTests/physics/C5689522_Physxterrain_AddPhysxterrainNoEditorCrash.py rename to AutomatedTesting/Gem/PythonTests/physics/terrain/C5689522_Physxterrain_AddPhysxterrainNoEditorCrash.py index 0c1d0d4d1c..8e42f9f77c --- a/AutomatedTesting/Gem/PythonTests/physics/C5689522_Physxterrain_AddPhysxterrainNoEditorCrash.py +++ b/AutomatedTesting/Gem/PythonTests/physics/terrain/C5689522_Physxterrain_AddPhysxterrainNoEditorCrash.py @@ -58,11 +58,6 @@ def C5689522_Physxterrain_AddPhysxterrainNoEditorCrash(): import os import sys - - import ImportPathHelper as imports - - imports.init() - import azlmbr.legacy.general as general from editor_python_test_tools.utils import Report @@ -105,8 +100,5 @@ def C5689522_Physxterrain_AddPhysxterrainNoEditorCrash(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C5689522_Physxterrain_AddPhysxterrainNoEditorCrash) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5689524_MultipleTerrains_CheckWarningInConsole.py b/AutomatedTesting/Gem/PythonTests/physics/terrain/C5689524_MultipleTerrains_CheckWarningInConsole.py old mode 100755 new mode 100644 similarity index 96% rename from AutomatedTesting/Gem/PythonTests/physics/C5689524_MultipleTerrains_CheckWarningInConsole.py rename to AutomatedTesting/Gem/PythonTests/physics/terrain/C5689524_MultipleTerrains_CheckWarningInConsole.py index 04912dd401..ba74716544 --- a/AutomatedTesting/Gem/PythonTests/physics/C5689524_MultipleTerrains_CheckWarningInConsole.py +++ b/AutomatedTesting/Gem/PythonTests/physics/terrain/C5689524_MultipleTerrains_CheckWarningInConsole.py @@ -60,12 +60,6 @@ def C5689524_MultipleTerrains_CheckWarningInConsole(): import os import sys - - import ImportPathHelper as imports - - imports.init() - - import azlmbr.legacy.general as general from editor_python_test_tools.utils import Report @@ -107,8 +101,5 @@ def C5689524_MultipleTerrains_CheckWarningInConsole(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C5689524_MultipleTerrains_CheckWarningInConsole) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5689528_Terrain_MultipleTerrainComponents.py b/AutomatedTesting/Gem/PythonTests/physics/terrain/C5689528_Terrain_MultipleTerrainComponents.py old mode 100755 new mode 100644 similarity index 96% rename from AutomatedTesting/Gem/PythonTests/physics/C5689528_Terrain_MultipleTerrainComponents.py rename to AutomatedTesting/Gem/PythonTests/physics/terrain/C5689528_Terrain_MultipleTerrainComponents.py index a5a8d65788..fb1fd01724 --- a/AutomatedTesting/Gem/PythonTests/physics/C5689528_Terrain_MultipleTerrainComponents.py +++ b/AutomatedTesting/Gem/PythonTests/physics/terrain/C5689528_Terrain_MultipleTerrainComponents.py @@ -60,11 +60,6 @@ def C5689528_Terrain_MultipleTerrainComponents(): import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper from editor_python_test_tools.utils import Tracer @@ -103,8 +98,5 @@ def C5689528_Terrain_MultipleTerrainComponents(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C5689528_Terrain_MultipleTerrainComponents) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5689531_Warning_TerrainSliceTerrainComponent.py b/AutomatedTesting/Gem/PythonTests/physics/terrain/C5689531_Warning_TerrainSliceTerrainComponent.py old mode 100755 new mode 100644 similarity index 97% rename from AutomatedTesting/Gem/PythonTests/physics/C5689531_Warning_TerrainSliceTerrainComponent.py rename to AutomatedTesting/Gem/PythonTests/physics/terrain/C5689531_Warning_TerrainSliceTerrainComponent.py index 2eaa55eacf..68ddaba5ed --- a/AutomatedTesting/Gem/PythonTests/physics/C5689531_Warning_TerrainSliceTerrainComponent.py +++ b/AutomatedTesting/Gem/PythonTests/physics/terrain/C5689531_Warning_TerrainSliceTerrainComponent.py @@ -65,11 +65,6 @@ def C5689531_Warning_TerrainSliceTerrainComponent(): import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper from editor_python_test_tools.utils import Tracer @@ -115,8 +110,5 @@ def C5689531_Warning_TerrainSliceTerrainComponent(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C5689531_Warning_TerrainSliceTerrainComponent) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C6032082_Terrain_MultipleResolutionsValid.py b/AutomatedTesting/Gem/PythonTests/physics/terrain/C6032082_Terrain_MultipleResolutionsValid.py old mode 100755 new mode 100644 similarity index 98% rename from AutomatedTesting/Gem/PythonTests/physics/C6032082_Terrain_MultipleResolutionsValid.py rename to AutomatedTesting/Gem/PythonTests/physics/terrain/C6032082_Terrain_MultipleResolutionsValid.py index 6bb44323a2..66615e1937 --- a/AutomatedTesting/Gem/PythonTests/physics/C6032082_Terrain_MultipleResolutionsValid.py +++ b/AutomatedTesting/Gem/PythonTests/physics/terrain/C6032082_Terrain_MultipleResolutionsValid.py @@ -80,11 +80,6 @@ def C6032082_Terrain_MultipleResolutionsValid(): import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper @@ -209,8 +204,5 @@ def C6032082_Terrain_MultipleResolutionsValid(): if __name__ == "__main__": - import ImportPathHelper as imports - imports.init() - from editor_python_test_tools.utils import Report Report.start_test(C6032082_Terrain_MultipleResolutionsValid) diff --git a/AutomatedTesting/Gem/PythonTests/physics/FileManagement.py b/AutomatedTesting/Gem/PythonTests/physics/utils/FileManagement.py old mode 100755 new mode 100644 similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/FileManagement.py rename to AutomatedTesting/Gem/PythonTests/physics/utils/FileManagement.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/UtilTest_Managed_Files.py b/AutomatedTesting/Gem/PythonTests/physics/utils/UtilTest_Managed_Files.py old mode 100755 new mode 100644 similarity index 89% rename from AutomatedTesting/Gem/PythonTests/physics/UtilTest_Managed_Files.py rename to AutomatedTesting/Gem/PythonTests/physics/utils/UtilTest_Managed_Files.py index 2e6e854c7d..49747da443 --- a/AutomatedTesting/Gem/PythonTests/physics/UtilTest_Managed_Files.py +++ b/AutomatedTesting/Gem/PythonTests/physics/utils/UtilTest_Managed_Files.py @@ -13,11 +13,6 @@ class Tests: def run(): import os import sys - - import ImportPathHelper as imports - - imports.init() - from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper diff --git a/AutomatedTesting/Gem/PythonTests/physics/UtilTest_Physmaterial_Editor.py b/AutomatedTesting/Gem/PythonTests/physics/utils/UtilTest_Physmaterial_Editor.py old mode 100755 new mode 100644 similarity index 99% rename from AutomatedTesting/Gem/PythonTests/physics/UtilTest_Physmaterial_Editor.py rename to AutomatedTesting/Gem/PythonTests/physics/utils/UtilTest_Physmaterial_Editor.py index ec870d12c4..27d670d1e8 --- a/AutomatedTesting/Gem/PythonTests/physics/UtilTest_Physmaterial_Editor.py +++ b/AutomatedTesting/Gem/PythonTests/physics/utils/UtilTest_Physmaterial_Editor.py @@ -50,9 +50,7 @@ def run(): """ import os import sys - import ImportPathHelper as imports - imports.init() from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper diff --git a/AutomatedTesting/Gem/PythonTests/physics/UtilTest_PhysxConfig_Default.py b/AutomatedTesting/Gem/PythonTests/physics/utils/UtilTest_PhysxConfig_Default.py old mode 100755 new mode 100644 similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/UtilTest_PhysxConfig_Default.py rename to AutomatedTesting/Gem/PythonTests/physics/utils/UtilTest_PhysxConfig_Default.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/UtilTest_PhysxConfig_Override.py b/AutomatedTesting/Gem/PythonTests/physics/utils/UtilTest_PhysxConfig_Override.py old mode 100755 new mode 100644 similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/UtilTest_PhysxConfig_Override.py rename to AutomatedTesting/Gem/PythonTests/physics/utils/UtilTest_PhysxConfig_Override.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/UtilTest_Tracer_PicksErrorsAndWarnings.py b/AutomatedTesting/Gem/PythonTests/physics/utils/UtilTest_Tracer_PicksErrorsAndWarnings.py old mode 100755 new mode 100644 similarity index 97% rename from AutomatedTesting/Gem/PythonTests/physics/UtilTest_Tracer_PicksErrorsAndWarnings.py rename to AutomatedTesting/Gem/PythonTests/physics/utils/UtilTest_Tracer_PicksErrorsAndWarnings.py index 92405498d2..136bcfc03d --- a/AutomatedTesting/Gem/PythonTests/physics/UtilTest_Tracer_PicksErrorsAndWarnings.py +++ b/AutomatedTesting/Gem/PythonTests/physics/utils/UtilTest_Tracer_PicksErrorsAndWarnings.py @@ -30,11 +30,6 @@ def run(): import os import sys - - import ImportPathHelper as imports - - imports.init() - import azlmbr.legacy.general as general from editor_python_test_tools.utils import Report From 79c98fe6a34bb2427430f048f0019d1f14450feb Mon Sep 17 00:00:00 2001 From: AMZN-Igarri <82394219+AMZN-Igarri@users.noreply.github.com> Date: Tue, 31 Aug 2021 14:29:17 +0200 Subject: [PATCH 797/803] [Fix] Editor Crash in Debug Mode (#3647) * Fixed Crash AssetBrowserTableView Signed-off-by: igarri * Fixed comments Signed-off-by: igarri * fixed lamda capture Signed-off-by: igarri * Capturing object in lambda Signed-off-by: igarri --- .../AssetBrowser/AssetBrowserTableModel.cpp | 78 ++++++++++++------- .../AssetBrowser/AssetBrowserTableModel.h | 10 ++- 2 files changed, 58 insertions(+), 30 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp index efa47e600d..d0999c5c56 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp @@ -25,19 +25,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()) + 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 +77,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 +92,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( @@ -103,13 +133,11 @@ 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) + 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 +171,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); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h index d80e2bd093..04559fbfbc 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h @@ -30,12 +30,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 +44,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 m_filterModel; QMap m_indexMap; + QMap m_rowMap; }; } // namespace AssetBrowser } // namespace AzToolsFramework From fe6238bbb80babc3dbd827b55407d1e64c421175 Mon Sep 17 00:00:00 2001 From: moraaar Date: Tue, 31 Aug 2021 14:55:58 +0100 Subject: [PATCH 798/803] Update Blast gem to use newer version of Blast 3p package, which fixes Blast gem on monolithic builds. (#3754) Signed-off-by: moraaar --- Gems/Blast/Code/Platform/Windows/PAL_windows.cmake | 2 ++ cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Gems/Blast/Code/Platform/Windows/PAL_windows.cmake b/Gems/Blast/Code/Platform/Windows/PAL_windows.cmake index bf05e5c7eb..cab1497a7c 100644 --- a/Gems/Blast/Code/Platform/Windows/PAL_windows.cmake +++ b/Gems/Blast/Code/Platform/Windows/PAL_windows.cmake @@ -7,3 +7,5 @@ # set(PAL_TRAIT_BLAST_SUPPORTED TRUE) + +ly_associate_package(PACKAGE_NAME Blast-v1.1.7_rc2-9-geb169fe-rev2-windows TARGETS Blast PACKAGE_HASH ac3ab4c778194f9e8413b95b87116032a336f58d55f489e941c8932609f892ff) \ No newline at end of file diff --git a/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake b/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake index 2655b7247f..10b56f90d9 100644 --- a/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake +++ b/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake @@ -27,7 +27,6 @@ ly_associate_package(PACKAGE_NAME PVRTexTool-4.24.0-rev4-multiplatform # platform-specific: ly_associate_package(PACKAGE_NAME AWSGameLiftServerSDK-3.4.1-rev1-windows TARGETS AWSGameLiftServerSDK PACKAGE_HASH a0586b006e4def65cc25f388de17dc475e417dc1e6f9d96749777c88aa8271b0) -ly_associate_package(PACKAGE_NAME Blast-v1.1.7_rc2-9-geb169fe-rev1-windows TARGETS Blast PACKAGE_HASH 216df71f4ffaf4a6ea3f2e77e5f27d68f2325e717fbd1626b00c785b82cd1b67) ly_associate_package(PACKAGE_NAME DirectXShaderCompilerDxc-1.6.2104-o3de-rev3-windows TARGETS DirectXShaderCompilerDxc PACKAGE_HASH 803e10b94006b834cbbdd30f562a8ddf04174c2cb6956c8399ec164ef8418d1f) ly_associate_package(PACKAGE_NAME SPIRVCross-2021.04.29-rev1-windows TARGETS SPIRVCross PACKAGE_HASH 7d601ea9d625b1d509d38bd132a1f433d7e895b16adab76bac6103567a7a6817) ly_associate_package(PACKAGE_NAME freetype-2.10.4.14-windows TARGETS freetype PACKAGE_HASH 88dedc86ccb8c92f14c2c033e51ee7d828fa08eafd6475c6aa963938a99f4bf3) From fe2bf07c55b5f1af182016e990fc7205add03d7a Mon Sep 17 00:00:00 2001 From: moraaar Date: Tue, 31 Aug 2021 14:56:37 +0100 Subject: [PATCH 799/803] Fixed blast asset reflection, which was generating a wrong Id for the Asset class type due to 'const' (#3756) Signed-off-by: moraaar --- Gems/Blast/Code/Source/Components/BlastFamilyComponent.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/Blast/Code/Source/Components/BlastFamilyComponent.h b/Gems/Blast/Code/Source/Components/BlastFamilyComponent.h index c27a738b05..99957d0fce 100644 --- a/Gems/Blast/Code/Source/Components/BlastFamilyComponent.h +++ b/Gems/Blast/Code/Source/Components/BlastFamilyComponent.h @@ -107,7 +107,7 @@ namespace Blast BlastMeshData* m_meshDataComponent = nullptr; // Configurations - const AZ::Data::Asset m_blastAsset; + AZ::Data::Asset m_blastAsset; const BlastMaterialId m_materialId{}; Physics::MaterialId m_physicsMaterialId; const BlastActorConfiguration m_actorConfiguration{}; From 0d728a76778cb0ca88caa5c07f17162fac668b2a Mon Sep 17 00:00:00 2001 From: sharmajs-amzn <82233357+sharmajs-amzn@users.noreply.github.com> Date: Tue, 31 Aug 2021 07:22:09 -0700 Subject: [PATCH 800/803] Added new index on SourceDependency Table (#3648) Signed-off-by: sharmajs-amzn <82233357+sharmajs-amzn@users.noreply.github.com> --- .../AssetDatabase/AssetDatabaseConnection.h | 1 + .../native/AssetDatabase/AssetDatabase.cpp | 23 +++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetDatabase/AssetDatabaseConnection.h b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetDatabase/AssetDatabaseConnection.h index a59dbfbda4..d9c83107e3 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetDatabase/AssetDatabaseConnection.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetDatabase/AssetDatabaseConnection.h @@ -65,6 +65,7 @@ namespace AzToolsFramework AddedScanTimeSecondsSinceEpochField = 29, ChangedSortFunctionFromQSortToStdStableSort = 30, RemoveOutputPrefixFromScanFolders, + AddedSourceIndexForSourceDependencyTable, //Add all new versions before this DatabaseVersionCount, LatestVersion = DatabaseVersionCount - 1 diff --git a/Code/Tools/AssetProcessor/native/AssetDatabase/AssetDatabase.cpp b/Code/Tools/AssetProcessor/native/AssetDatabase/AssetDatabase.cpp index 4d2053c6d1..9be991eb0b 100644 --- a/Code/Tools/AssetProcessor/native/AssetDatabase/AssetDatabase.cpp +++ b/Code/Tools/AssetProcessor/native/AssetDatabase/AssetDatabase.cpp @@ -758,6 +758,14 @@ namespace AssetProcessor "FileID = :fileid;"; static const auto s_DeleteFileQuery = MakeSqlQuery(DELETE_FILE, DELETE_FILE_STATEMENT, LOG_NAME, SqlParam(":fileid")); + + static const char* CREATEINDEX_SOURCEDEPENDENCY_SOURCE = "AssetProcesser::CreateIndexSourceSourceDependency"; + static const char* CREATEINDEX_SOURCEDEPENDENCY_SOURCE_STATEMENT = + "CREATE INDEX IF NOT EXISTS Source_SourceDependency ON SourceDependency (Source);"; + + static const char* DROPINDEX_BUILDERGUID_SOURCE_SOURCEDEPENDENCY = "AssetProcesser::DropIndexBuilderGuid_Source_SourceDependency"; + static const char* DROPINDEX_BUILDERGUID_SOURCE_SOURCEDEPENDENCY_STATEMENT = + "DROP INDEX IF EXISTS BuilderGuid_Source_SourceDependency;"; } AssetDatabaseConnection::AssetDatabaseConnection() @@ -1033,6 +1041,15 @@ namespace AssetProcessor // sqlite doesn't not support altering a table to remove a column // This is fine as the extra OutputPrefix column will not be queried + if (foundVersion == AssetDatabase::DatabaseVersion::RemoveOutputPrefixFromScanFolders) + { + if (m_databaseConnection->ExecuteOneOffStatement(DROPINDEX_BUILDERGUID_SOURCE_SOURCEDEPENDENCY) && m_databaseConnection->ExecuteOneOffStatement(CREATEINDEX_SOURCEDEPENDENCY_SOURCE)) + { + foundVersion = AssetDatabase::DatabaseVersion::AddedSourceIndexForSourceDependencyTable; + AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Upgraded Asset Database to version %i (AddedSourceIndexForSourceDependencyTable)\n", foundVersion) + } + } + if (foundVersion == CurrentDatabaseVersion()) { dropAllTables = false; @@ -1306,6 +1323,12 @@ namespace AssetProcessor m_databaseConnection->AddStatement(CREATEINDEX_SCANFOLDERS_FILES, CREATEINDEX_SCANFOLDERS_FILES_STATEMENT); m_createStatements.push_back(CREATEINDEX_SCANFOLDERS_FILES); + m_databaseConnection->AddStatement(CREATEINDEX_SOURCEDEPENDENCY_SOURCE, CREATEINDEX_SOURCEDEPENDENCY_SOURCE_STATEMENT); + m_createStatements.push_back(CREATEINDEX_SOURCEDEPENDENCY_SOURCE); + + m_databaseConnection->AddStatement(DROPINDEX_BUILDERGUID_SOURCE_SOURCEDEPENDENCY, DROPINDEX_BUILDERGUID_SOURCE_SOURCEDEPENDENCY_STATEMENT); + m_createStatements.push_back(DROPINDEX_BUILDERGUID_SOURCE_SOURCEDEPENDENCY); + m_databaseConnection->AddStatement(DELETE_AUTO_SUCCEED_JOBS, DELETE_AUTO_SUCCEED_JOBS_STATEMENT); } From 6e3b03dfaa89bab530013c7599d504f1145d7e21 Mon Sep 17 00:00:00 2001 From: Mike Chang <62353586+amzn-changml@users.noreply.github.com> Date: Tue, 31 Aug 2021 09:47:57 -0700 Subject: [PATCH 801/803] Install and configure Ubuntu nodes with Nvidia drivers and NiceDCV (#3728) These scripts will configure build and test Ubuntu 18/20 nodes with: Nvidia gaming drivers for GPU instances (g4dn) lightdm for Ubuntu 18 and gdm3 for Ubuntu 20 (wayland is disabled here, but should have xcb capabilities) NiceDCV for remote console access Note: Does not include user setup and firewall configurations Signed-off-by: Mike Chang --- .../Platform/Linux/install-ubuntu-gpu.sh | 94 +++++++++++++++++++ .../Platform/Linux/install-ubuntu-nicedcv.sh | 78 +++++++++++++++ 2 files changed, 172 insertions(+) create mode 100755 scripts/build/build_node/Platform/Linux/install-ubuntu-gpu.sh create mode 100755 scripts/build/build_node/Platform/Linux/install-ubuntu-nicedcv.sh diff --git a/scripts/build/build_node/Platform/Linux/install-ubuntu-gpu.sh b/scripts/build/build_node/Platform/Linux/install-ubuntu-gpu.sh new file mode 100755 index 0000000000..033d32369c --- /dev/null +++ b/scripts/build/build_node/Platform/Linux/install-ubuntu-gpu.sh @@ -0,0 +1,94 @@ +#!/bin/bash + +# Copyright (c) Contributors to the Open 3D Engine Project. +# For complete copyright and license terms please see the LICENSE at the root of this distribution. +# +# SPDX-License-Identifier: Apache-2.0 OR MIT +# + +# This script must be run as root +if [[ $EUID -ne 0 ]] +then + echo "This script must be run as root (sudo)" + exit 1 +fi + +# Install latest updates to AWS drivers and GCC (to build display driver) +# +echo Updating OS and tools +apt-get update -y +apt-get upgrade -y linux-aws +apt-get install -y gcc make linux-headers-$(uname -r) + +# Install Desktop environment with tools. Nice is only compatible with Gnome +# +echo Installing desktop environment and tools +apt-get install ubuntu-desktop mesa-utils vulkan-tools awscli unzip -y + +# Setup X desktop manager (Wayland needs to be turned off for GDM3) +# +if [ "`cat /etc/issue | grep 18.04`" != "" ] ; then + apt-get install lightdm -y +else + apt-get install gdm3 -y + sed -i 's/#WaylandEnable=false/WaylandEnable=false/g' /etc/gdm3/custom.conf + systemctl restart gdm3 +fi + +# Set desktop environment to start by default +# +systemctl get-default +systemctl set-default graphical.target +systemctl isolate graphical.target + +# Prepare for the nVidia driver by disabling nouveau +# +cat << EOF | sudo tee --append /etc/modprobe.d/blacklist.conf +blacklist vga16fb +blacklist nouveau +blacklist rivafb +blacklist nvidiafb +blacklist rivatv +EOF + +# Blocking nouveau from activating during grub startup +# +echo 'GRUB_CMDLINE_LINUX="rdblacklist=nouveau"' >> /etc/default/grub +update-grub + +# Copy drivers to local, then install +# +aws s3 cp --recursive s3://nvidia-gaming/linux/latest/ /tmp +cd /tmp +unzip NVIDIA-Linux-x86_64* \ +&& rm NVIDIA-Linux-x86_64* \ +&& chmod +x Linux/NVIDIA-Linux-x86_64*.run \ +&& Linux/NVIDIA-Linux-x86_64*.run --accept-license \ + --no-questions \ + --no-backup \ + --ui=none \ + --install-libglvnd \ +&& nvidia-xconfig --preserve-busid --enable-all-gpus \ +&& rm -rf /tmp/Linux + +# Download and configure licenses (needed for VMs and multiuser) +# +cat << EOF | sudo tee -a /etc/nvidia/gridd.conf +vGamingMarketplace=2 +EOF +curl -o /etc/nvidia/GridSwCert.txt "https://nvidia-gaming.s3.amazonaws.com/GridSwCert-Archive/GridSwCertLinux_2021_10_2.cert" + +# Optimize settings if headless +# +if [ ! $DISPLAY ] ; then + echo Headless instance found. Disabling HardDPMS + if [ ! $(grep '"HardDPMS" "false"' /etc/X11/xorg.conf) ]; then + sed -i '/BusID */ a\ + Option "HardDPMS" "false"' /etc/X11/xorg.conf + fi +fi + +echo Install complete! +read -t 10 -p "Rebooting in 10 seconds. Press enter to reboot this instance now or CTRL+c to cancel" +reboot now + diff --git a/scripts/build/build_node/Platform/Linux/install-ubuntu-nicedcv.sh b/scripts/build/build_node/Platform/Linux/install-ubuntu-nicedcv.sh new file mode 100755 index 0000000000..d566c94c21 --- /dev/null +++ b/scripts/build/build_node/Platform/Linux/install-ubuntu-nicedcv.sh @@ -0,0 +1,78 @@ +#!/bin/bash + +# Copyright (c) Contributors to the Open 3D Engine Project. +# For complete copyright and license terms please see the LICENSE at the root of this distribution. +# +# SPDX-License-Identifier: Apache-2.0 OR MIT +# + +# This script must be run as root +if [[ $EUID -ne 0 ]] +then + echo "This script must be run as root (sudo)" + exit 1 +fi + +# Download Nice DCV +# +echo Downloading Nice-DCV +mkdir /tmp/nice-dcv +cd /tmp/nice-dcv +curl -sSL https://d1uj6qtbmh3dt5.cloudfront.net/NICE-GPG-KEY | gpg --import - + +if [ "`cat /etc/issue | grep 18.04`" != "" ] ; then + dcv_server=`curl --silent --output - https://download.nice-dcv.com/ | \ +grep href | egrep "$dcv_version" | egrep "ubuntu1804" | grep Server | \ +sed -e 's/.*http/http/' -e 's/tgz.*/tgz/' | head -1` +else + dcv_server=`curl --silent --output - https://download.nice-dcv.com/ | \ +grep href | egrep "$dcv_version" | egrep "ubuntu2004" | grep Server | \ +sed -e 's/.*http/http/' -e 's/tgz.*/tgz/' | head -1` +fi + +# Install Nice DCV +# +echo Installing DCV from $dcv_server +wget $dcv_server \ +&& tar zxvf nice-dcv-*ubun*.tgz +cd nice-dcv-*64 +apt install -y ./nice-*amd64.ubuntu*.deb \ +&& usermod -aG video dcv \ +&& rm -rf /tmp/nice-dcv + +# Setup multiuser environment for DCV +# +systemctl isolate multi-user.target +sleep 1 +dcvgladmin enable +systemctl isolate graphical.target + +# Check if DCV localuser for X has been setup correctly +# +if [ $(DISPLAY=:0 XAUTHORITY=$(ps aux | grep "X.*\-auth" | grep -v grep | sed -n 's/.*-auth \([^ ]\+\).*/\1/p') xhost | grep "SI:localuser:dcv$") ]; then + echo DCV localuser validated +else + echo [ERROR] DCV localuser not found. Output should be: SI:localuser:dcv. Exiting with 1 + exit 1 +fi + +# Configure DCV for auto start sessions and performance +# +sed -i "s/#create-session = true/create-session = true/g" /etc/dcv/dcv.conf +sed -i "s/#owner=\"session-owner\"/owner=\"$LOGNAME\"/g" /etc/dcv/dcv.conf +sed -i "s/#target-fps=30/target-fps=0/g" /etc/dcv/dcv.conf + +# Enable and start the DCV server +# +systemctl enable dcvserver +systemctl start dcvserver + +# Output the DCV installation diagnostics +# +dcvgldiag + +# Start a DCV session to login +# +IP_ADDR=$(curl http://checkip.amazonaws.com) +echo Starting DCV desktop session for $LOGNAME. Session can be accessed at https://$IP_ADDR:8443 +dcv create-session --type=console --owner $LOGNAME desktop From dd3bdcd3f4088afdaec060678c1f8258735945ee Mon Sep 17 00:00:00 2001 From: Nicholas Van Sickle Date: Tue, 31 Aug 2021 11:08:11 -0700 Subject: [PATCH 802/803] Fix some Qt warnings (#3731) -Fix a missing QPainter::restore call -Remove 0px font sizes from our qss, which was just getting ignored by Qt and triggering a warning Signed-off-by: nvsickle --- .../ComponentEntityEditorPlugin/UI/Outliner/EntityOutliner.qss | 2 -- Code/Editor/Style/NewEditorStylesheet.qss | 1 - .../AzToolsFramework/UI/Outliner/EntityOutliner.qss | 2 -- .../AzToolsFramework/UI/Prefab/LevelRootUiHandler.cpp | 1 + 4 files changed, 1 insertion(+), 5 deletions(-) diff --git a/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/EntityOutliner.qss b/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/EntityOutliner.qss index 1b6f04d06d..de35f91678 100644 --- a/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/EntityOutliner.qss +++ b/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/EntityOutliner.qss @@ -48,7 +48,6 @@ OutlinerCheckBox spacing: 0px; padding: 0px; line-height: 0px; - font-size: 0px; margin: 0px; background-color: none; max-height: 20px; @@ -66,7 +65,6 @@ OutlinerCheckBox::indicator spacing: 0px; padding: 0px; line-height: 0px; - font-size: 0px; margin: 0; } diff --git a/Code/Editor/Style/NewEditorStylesheet.qss b/Code/Editor/Style/NewEditorStylesheet.qss index d92ec33357..1de8634b4c 100644 --- a/Code/Editor/Style/NewEditorStylesheet.qss +++ b/Code/Editor/Style/NewEditorStylesheet.qss @@ -2505,7 +2505,6 @@ OutlinerCheckBox spacing: 0px; padding: 0px; line-height: 0px; - font-size: 0px; margin: 2px 2px 0 2px; background-color: none; max-height: 20px; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutliner.qss b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutliner.qss index 8e569eb134..15ff8b1b67 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutliner.qss +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutliner.qss @@ -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; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/LevelRootUiHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/LevelRootUiHandler.cpp index 708a6d9b13..73a28a3edc 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/LevelRootUiHandler.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/LevelRootUiHandler.cpp @@ -99,5 +99,6 @@ namespace AzToolsFramework // Draw border at the bottom painter->drawLine(rect.bottomLeft(), rect.bottomRight()); + painter->restore(); } } From 9fc824d98bf9105d15213f5736050462c0f843ab Mon Sep 17 00:00:00 2001 From: Junbo Liang <68558268+junbo75@users.noreply.github.com> Date: Tue, 31 Aug 2021 11:15:04 -0700 Subject: [PATCH 803/803] Create config files automatically and UX style updates (#3514) --- Code/Editor/MainWindow.qrc | 2 + Code/Editor/res/error_report_helper.svg | 14 + Code/Editor/res/o3de_application_reverse.svg | 9 + .../AWSResourceMappingConstants.h | 2 +- .../AWSResourceMappingManagerTest.cpp | 22 + .../controller/view_edit_controller.py | 37 +- .../manager/view_manager.py | 2 +- .../model/error_messages.py | 8 +- .../model/notification_label_text.py | 11 +- .../model/view_size_constants.py | 11 +- .../style/base_style_sheet.qss | 56 +- .../style/editormainwindow_resources.py | 54803 ++++++++-------- .../unit/controller/test_error_controller.py | 29 + .../controller/test_view_edit_controller.py | 43 +- .../tests/unit/utils/test_json_utils.py | 28 +- .../ResourceMappingTool/utils/json_utils.py | 36 +- .../view/common_view_components.py | 52 +- .../ResourceMappingTool/view/error_page.py | 29 +- .../view/view_edit_page.py | 63 +- .../Config/default_aws_resource_mappings.json | 6 + .../Registry/awscoreconfiguration.setreg | 10 + Templates/DefaultProject/template.json | 12 + 22 files changed, 27846 insertions(+), 27439 deletions(-) create mode 100644 Code/Editor/res/error_report_helper.svg create mode 100644 Code/Editor/res/o3de_application_reverse.svg create mode 100644 Gems/AWSCore/Code/Tools/ResourceMappingTool/tests/unit/controller/test_error_controller.py create mode 100644 Templates/DefaultProject/Template/Config/default_aws_resource_mappings.json create mode 100644 Templates/DefaultProject/Template/Registry/awscoreconfiguration.setreg diff --git a/Code/Editor/MainWindow.qrc b/Code/Editor/MainWindow.qrc index fd207ebe13..4506a4a2a8 100644 --- a/Code/Editor/MainWindow.qrc +++ b/Code/Editor/MainWindow.qrc @@ -76,6 +76,7 @@ res/o3de_editor.ico + res/o3de_application_reverse.svg res/Eye.svg @@ -152,6 +153,7 @@ res/error_report_error.svg res/error_report_warning.svg res/error_report_comment.svg + res/error_report_helper.svg particles_tree_00.png particles_tree_01.png particles_tree_02.png diff --git a/Code/Editor/res/error_report_helper.svg b/Code/Editor/res/error_report_helper.svg new file mode 100644 index 0000000000..d61970d163 --- /dev/null +++ b/Code/Editor/res/error_report_helper.svg @@ -0,0 +1,14 @@ + + + Icons / Notification / Helpers + + + + + + + + + + + \ No newline at end of file diff --git a/Code/Editor/res/o3de_application_reverse.svg b/Code/Editor/res/o3de_application_reverse.svg new file mode 100644 index 0000000000..841affe8ba --- /dev/null +++ b/Code/Editor/res/o3de_application_reverse.svg @@ -0,0 +1,9 @@ + + + o3de icon + + + + + + \ No newline at end of file diff --git a/Gems/AWSCore/Code/Include/Private/ResourceMapping/AWSResourceMappingConstants.h b/Gems/AWSCore/Code/Include/Private/ResourceMapping/AWSResourceMappingConstants.h index ee052617e3..97eb5b6492 100644 --- a/Gems/AWSCore/Code/Include/Private/ResourceMapping/AWSResourceMappingConstants.h +++ b/Gems/AWSCore/Code/Include/Private/ResourceMapping/AWSResourceMappingConstants.h @@ -68,7 +68,7 @@ namespace AWSCore }, "AccountIdString": { "type": "string", - "pattern": "^[0-9]{12}$" + "pattern": "^[0-9]{12}$|EMPTY" }, "NonEmptyString": { "type": "string", diff --git a/Gems/AWSCore/Code/Tests/ResourceMapping/AWSResourceMappingManagerTest.cpp b/Gems/AWSCore/Code/Tests/ResourceMapping/AWSResourceMappingManagerTest.cpp index 91d85c2f99..d438a99f83 100644 --- a/Gems/AWSCore/Code/Tests/ResourceMapping/AWSResourceMappingManagerTest.cpp +++ b/Gems/AWSCore/Code/Tests/ResourceMapping/AWSResourceMappingManagerTest.cpp @@ -66,6 +66,13 @@ R"({ "Region": "123", "Version": "123" })"; +static constexpr const char TEST_TEMPLATE_RESOURCE_MAPPING_CONFIG_FILE[] = + R"({ + "AWSResourceMappings": {}, + "AccountId": "EMPTY", + "Region": "us-west-2", + "Version": "1.0.0" +})"; class AWSResourceMappingManagerTest : public AWSCoreFixture @@ -190,6 +197,21 @@ TEST_F(AWSResourceMappingManagerTest, ActivateManager_ParseValidConfigFile_Confi EXPECT_TRUE(m_resourceMappingManager->GetStatus() == AWSResourceMappingManager::Status::Ready); } +TEST_F(AWSResourceMappingManagerTest, ActivateManager_ParseTemplateConfigFile_ConfigDataIsNotEmpty) +{ + CreateTestConfigFile(TEST_TEMPLATE_RESOURCE_MAPPING_CONFIG_FILE); + m_resourceMappingManager->ActivateManager(); + + AZStd::string actualAccountId; + AZStd::string actualRegion; + AWSResourceMappingRequestBus::BroadcastResult(actualAccountId, &AWSResourceMappingRequests::GetDefaultAccountId); + AWSResourceMappingRequestBus::BroadcastResult(actualRegion, &AWSResourceMappingRequests::GetDefaultRegion); + EXPECT_EQ(m_reloadConfigurationCounter, 0); + EXPECT_FALSE(actualAccountId.empty()); + EXPECT_FALSE(actualRegion.empty()); + EXPECT_TRUE(m_resourceMappingManager->GetStatus() == AWSResourceMappingManager::Status::Ready); +} + TEST_F(AWSResourceMappingManagerTest, ActivateManager_ParseValidConfigFile_ConfigDataIsNotEmptyWithMultithreadCalls) { CreateTestConfigFile(TEST_VALID_RESOURCE_MAPPING_CONFIG_FILE); diff --git a/Gems/AWSCore/Code/Tools/ResourceMappingTool/controller/view_edit_controller.py b/Gems/AWSCore/Code/Tools/ResourceMappingTool/controller/view_edit_controller.py index 54d0a29fea..bdfe7fa11e 100755 --- a/Gems/AWSCore/Code/Tools/ResourceMappingTool/controller/view_edit_controller.py +++ b/Gems/AWSCore/Code/Tools/ResourceMappingTool/controller/view_edit_controller.py @@ -68,12 +68,17 @@ class ViewEditController(QObject): # convert model resources into json dict json_dict: Dict[str, any] = \ json_utils.convert_resources_to_json_dict(self._proxy_model.get_resources(), self._config_file_json_source) + + configuration: Configuration = self._configuration_manager.configuration + if json_dict.get(json_utils.RESOURCE_MAPPING_ACCOUNTID_JSON_KEY_NAME) == \ + json_utils.RESOURCE_MAPPING_ACCOUNTID_TEMPLATE_VALUE: + json_dict[json_utils.RESOURCE_MAPPING_ACCOUNTID_JSON_KEY_NAME] = configuration.account_id + if json_dict == self._config_file_json_source: # skip because no difference found against existing json file return True # try to write in memory json content into json file - configuration: Configuration = self._configuration_manager.configuration try: config_file_full_path: str = file_utils.join_path(configuration.config_directory, config_file_name) json_utils.write_into_json_file(config_file_full_path, json_dict) @@ -103,31 +108,6 @@ class ViewEditController(QObject): for resource in resources: self._proxy_model.load_resource(resource) - def _create_new_config_file(self) -> None: - configuration: Configuration = self._configuration_manager.configuration - self._set_default_region(configuration) - - try: - new_config_file_path: str = file_utils.join_path( - configuration.config_directory, constants.RESOURCE_MAPPING_DEFAULT_CONFIG_FILE_NAME) - json_utils.create_empty_resource_mapping_file( - new_config_file_path, configuration.account_id, configuration.region) - except IOError as e: - logger.exception(e) - self.set_notification_frame_text_sender.emit(str(e)) - return - - self._rescan_config_directory() - - def _set_default_region(self, configuration: Configuration): - default_region = configuration.region - if not default_region or default_region == 'aws-global': - self.set_notification_frame_text_sender.emit( - notification_label_text.VIEW_EDIT_PAGE_CREATE_NEW_CONFIG_FILE_NO_DEFAULT_REGION_MESSAGE) - logger.warning(notification_label_text.VIEW_EDIT_PAGE_CREATE_NEW_CONFIG_FILE_NO_DEFAULT_REGION_MESSAGE) - - configuration.region = constants.RESOURCE_MAPPING_DEFAULT_CONFIG_FILE_REGION - def _delete_table_row(self) -> None: indices: List[QModelIndex] = self._table_view.selectedIndexes() self._proxy_model.remove_resources(indices) @@ -246,14 +226,13 @@ class ViewEditController(QObject): self._view_edit_page.save_changes_button.clicked.connect(self._save_changes) self._view_edit_page.search_filter_input.returnPressed.connect(self._filter_based_on_search_text) self._view_edit_page.cancel_button.clicked.connect(self._cancel) - self._view_edit_page.create_new_button.clicked.connect(self._create_new_config_file) self._view_edit_page.rescan_button.clicked.connect(self._rescan_config_directory) def _setup_page_start_state(self) -> None: configuration: Configuration = self._configuration_manager.configuration self._view_edit_page.set_current_main_view_index(ViewEditPageConstants.NOTIFICATION_PAGE_INDEX) - self._view_edit_page.set_config_files(configuration.config_files) self._view_edit_page.set_config_location(configuration.config_directory) + self._view_edit_page.set_config_files(configuration.config_files) def _switch_to_import_resources_page(self) -> None: if self._view_edit_page.import_resources_combobox.currentIndex() == -1: @@ -297,5 +276,5 @@ class ViewEditController(QObject): def setup(self) -> None: """Setting view edit page starting state and bind interactions with its corresponding behavior""" - self._setup_page_start_state() self._setup_page_interactions_behavior() + self._setup_page_start_state() diff --git a/Gems/AWSCore/Code/Tools/ResourceMappingTool/manager/view_manager.py b/Gems/AWSCore/Code/Tools/ResourceMappingTool/manager/view_manager.py index e6ca6a1480..f6d51155ad 100755 --- a/Gems/AWSCore/Code/Tools/ResourceMappingTool/manager/view_manager.py +++ b/Gems/AWSCore/Code/Tools/ResourceMappingTool/manager/view_manager.py @@ -44,7 +44,7 @@ class ViewManager(object): def __init__(self) -> None: if ViewManager.__instance is None: self._main_window: QMainWindow = QMainWindow() - self._main_window.setWindowIcon(QIcon(":/Application/res/o3de_editor.ico")) + self._main_window.setWindowIcon(QIcon(":/Application/o3de_application_reverse.svg")) self._main_window.setWindowTitle("Resource Mapping") self._main_window.setGeometry(0, 0, view_size_constants.TOOL_APPLICATION_MAIN_WINDOW_WIDTH, diff --git a/Gems/AWSCore/Code/Tools/ResourceMappingTool/model/error_messages.py b/Gems/AWSCore/Code/Tools/ResourceMappingTool/model/error_messages.py index 93d1ee1754..4316c145ba 100755 --- a/Gems/AWSCore/Code/Tools/ResourceMappingTool/model/error_messages.py +++ b/Gems/AWSCore/Code/Tools/ResourceMappingTool/model/error_messages.py @@ -5,11 +5,11 @@ For complete copyright and license terms please see the LICENSE at the root of t SPDX-License-Identifier: Apache-2.0 OR MIT """ +ERROR_PAGE_TOOL_SETUP_ERROR_TITLE: str = "AWS credentials are missing or invalid" + ERROR_PAGE_TOOL_SETUP_ERROR_MESSAGE: str = \ - "AWS credentials are missing or invalid. See " \ - ""\ - "documentation for details." \ - "
Check log file under Gems/AWSCore/Code/Tool/ResourceMappingTool for further information." + "Use our "\ + "documentation to setup your AWS credentials. " VIEW_EDIT_PAGE_SAVING_FAILED_WITH_INVALID_ROW_ERROR_MESSAGE: str = \ "Row {} have errors. Please correct errors or delete the row to proceed." diff --git a/Gems/AWSCore/Code/Tools/ResourceMappingTool/model/notification_label_text.py b/Gems/AWSCore/Code/Tools/ResourceMappingTool/model/notification_label_text.py index ecd6d8282c..80ea934209 100755 --- a/Gems/AWSCore/Code/Tools/ResourceMappingTool/model/notification_label_text.py +++ b/Gems/AWSCore/Code/Tools/ResourceMappingTool/model/notification_label_text.py @@ -13,6 +13,7 @@ ERROR_PAGE_OK_TEXT: str = "OK" VIEW_EDIT_PAGE_CONFIG_FILE_TEXT: str = "Config File" VIEW_EDIT_PAGE_CONFIG_LOCATION_TEXT: str = "Config Location:" +VIEW_EDIT_PAGE_INVALID_CONFIG_LOCATION_TEXT: str = "Invalid Location" VIEW_EDIT_PAGE_ADD_ROW_TEXT: str = "Add Row" VIEW_EDIT_PAGE_DELETE_ROW_TEXT: str = "Delete Row" VIEW_EDIT_PAGE_SAVE_CHANGES_TEXT: str = "Save Changes" @@ -23,17 +24,11 @@ VIEW_EDIT_PAGE_RESCAN_TEXT: str = "Rescan" VIEW_EDIT_PAGE_CONFIG_FILES_PLACEHOLDER_TEXT: str = "Found {} config files" VIEW_EDIT_PAGE_SEARCH_PLACEHOLDER_TEXT: str = "Search by Key Name, Type, Name/ID, Account ID or Region" VIEW_EDIT_PAGE_IMPORT_RESOURCES_PLACEHOLDER_TEXT: str = "Import Additional Resources" -VIEW_EDIT_PAGE_CREATE_NEW_CONFIG_FILE_NO_DEFAULT_REGION_MESSAGE: str = \ - f"Resource mapping file {constants.RESOURCE_MAPPING_DEFAULT_CONFIG_FILE_NAME} is created"\ - f" with {constants.RESOURCE_MAPPING_DEFAULT_CONFIG_FILE_REGION} as the default region. "\ - f"See "\ - f"documentation "\ - f"for configuring the AWS credentials and default region." VIEW_EDIT_PAGE_SELECT_CONFIG_FILE_MESSAGE: str = "Please select the Config file you would like to view and modify..." +VIEW_EDIT_PAGE_NO_CONFIG_FILE_FOUND_TITLE: str = "Unable to locate a resource mapping config file" VIEW_EDIT_PAGE_NO_CONFIG_FILE_FOUND_MESSAGE: str = \ - "

Unable to locate a resource mapping config file.

"\ - "

We can either make this file for you or you can rescan your directory.

" + "

Please select your project's config file directory using the browse tool in the upper right.

" VIEW_EDIT_PAGE_SAVING_SUCCEED_MESSAGE: str = "Config file {} is saved successfully." IMPORT_RESOURCES_PAGE_BACK_TEXT: str = "Back" diff --git a/Gems/AWSCore/Code/Tools/ResourceMappingTool/model/view_size_constants.py b/Gems/AWSCore/Code/Tools/ResourceMappingTool/model/view_size_constants.py index 2ce4279502..85b636bfbf 100755 --- a/Gems/AWSCore/Code/Tools/ResourceMappingTool/model/view_size_constants.py +++ b/Gems/AWSCore/Code/Tools/ResourceMappingTool/model/view_size_constants.py @@ -14,13 +14,14 @@ MAIN_PAGE_LAYOUT_MARGIN_TOPBOTTOM: int = 15 INTERACTION_COMPONENT_HEIGHT: int = 25 """error page related constants""" -ERROR_PAGE_LAYOUT_MARGIN_LEFTRIGHT: int = 10 -ERROR_PAGE_LAYOUT_MARGIN_TOPBOTTOM: int = 10 +ERROR_PAGE_LAYOUT_MARGIN_LEFTRIGHT: int = 25 +ERROR_PAGE_LAYOUT_MARGIN_TOPBOTTOM: int = 20 +ERROR_PAGE_LAYOUT_SPACING: int = 15 -ERROR_PAGE_MAIN_WINDOW_WIDTH: int = 600 -ERROR_PAGE_MAIN_WINDOW_HEIGHT: int = 145 +ERROR_PAGE_MAIN_WINDOW_WIDTH: int = 100 +ERROR_PAGE_MAIN_WINDOW_HEIGHT: int = 75 -ERROR_PAGE_NOTIFICATION_AREA_HEIGHT: int = 100 +ERROR_PAGE_NOTIFICATION_AREA_HEIGHT: int = 30 ERROR_PAGE_FOOTER_AREA_HEIGHT: int = 45 OK_BUTTON_WIDTH: int = 90 diff --git a/Gems/AWSCore/Code/Tools/ResourceMappingTool/style/base_style_sheet.qss b/Gems/AWSCore/Code/Tools/ResourceMappingTool/style/base_style_sheet.qss index d8f61713a7..51791dc519 100644 --- a/Gems/AWSCore/Code/Tools/ResourceMappingTool/style/base_style_sheet.qss +++ b/Gems/AWSCore/Code/Tools/ResourceMappingTool/style/base_style_sheet.qss @@ -35,6 +35,17 @@ QComboBox line-height: 16px; } +[HighlightField=true] +{ + border:3px solid #E57829; +} + +[HighlightText=true] +{ + font-weight: bold; + color: #E57829; +} + QToolTip { color: black; @@ -356,7 +367,7 @@ QScrollBar::handle:hover } /* NotificationFrame */ -QFrame#NotificationFrame +NotificationFrame { background-color: transparent; border: 1px solid #E57829; @@ -365,17 +376,38 @@ QFrame#NotificationFrame padding: 4px; } -QFrame#ErrorPage +NotificationFrame QLabel#NotificationIcon { - background-color: #2d2d2d; - border: 1px solid #4A90E2; - border-radius: 2px; - margin: 0px; - padding: 15px; -} - -QFrame#ErrorPage QLabel#NotificationIcon -{ - padding-left: 15px; + padding-left: 0px; padding-right: 15px; } + +NotificationFrame QLabel#NotificationTitle +{ + font-size: 15px; + font-weight: bold; +} + +NotificationFrame#ErrorPage +{ + background-color: transparent; + border: none; +} + +NotificationFrame#ErrorPage QLabel#NotificationIcon +{ + qproperty-alignment: "AlignTop"; +} + +NotificationFrame#ErrorPage QLabel#NotificationTitle +{ + padding-top: 0px; + text-align: top; +} + +NotificationFrame#ErrorPage QLabel#NotificationContent +{ + padding-top: 0px; + text-align: top; + qproperty-wordWrap: false; +} diff --git a/Gems/AWSCore/Code/Tools/ResourceMappingTool/style/editormainwindow_resources.py b/Gems/AWSCore/Code/Tools/ResourceMappingTool/style/editormainwindow_resources.py index 64ad2212ea..36303e40cd 100644 --- a/Gems/AWSCore/Code/Tools/ResourceMappingTool/style/editormainwindow_resources.py +++ b/Gems/AWSCore/Code/Tools/ResourceMappingTool/style/editormainwindow_resources.py @@ -1,27257 +1,27546 @@ -""" -Copyright (c) Contributors to the Open 3D Engine Project. -For complete copyright and license terms please see the LICENSE at the root of this distribution. - -SPDX-License-Identifier: Apache-2.0 OR MIT -""" - -from PySide2 import QtCore - -qt_resource_data = b"\ -\x00\x00\x01\x84\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\ -\x00\x00\x01KIDATx\xdac`\x18\x05\xa3`\ -\x14\x0c&\x10\x91\x90\xe3\x18\x99\x98{\x08\x88\xf7\x810\ -\x90\xbf\x1f\xca\xd6\xa6\x8b\x03\x80\x165\x01-\xfd\x0f\xc3\ -@>\x8c\x1dK\xaf\x10h\x00Y\x0a\xc3@\xfe_(\ -{5\x10\x9b\x01\xf9V@\x1a\x8e\x89\xe4[\x03\xb1>\ -\xa5\x0e\x80\x87\x06\x05|\xf5\x81v\x80\x1e1i\xa0\x01\ -\x1a\xe7\x7f\xa1\x96\xff\x83\xf2o\x00\xf1\x19 \xff\x0c\x88\ -\x86a\x12\xf8\x97\x81X\x85\x9c\x10\x00\xd1\x13\xe8\x99\x0d\ -\xd1\x1d\xf0\x05Hs\x00\xb1\x1b\x10_\x07\xf2o\x02\xe9\ -\x1b0\x0c\x0a\x192\xf8\xb7\x80\xf80\x10\xb3\x12\xe3\x80\ -\x1ah\xd4<\xa4B\x1a@\xe6\xcf%\x94\x06@q\xff\ -\x1d\xea\xa8tX\xba\x80\xa6\x89\xbfhi\x84T>\xc8\ -,)b\xa2\xa0\x0c\xea\xa8gxr\x05\xa9|\xdc\xbe\ -Gs\xc0+ f\x06\xf23)\xb4\x10\x1b_\x94\x18\ -\x07\xe4A\xf9\xaf\xa9\xec\x80i\x84\xca\x81F\xa0\xa2W\ -@\xcc\x04\xc4i0C(\x8c\xf3\xbf\xd04\xf5\x03\xc8\ -\x97!\x94\x0d\xdb\x81\x8ar\xa0\x8ey\x8a%\x15S\x12\ -\x02\xd3\x88)\x07R\xa0\x96gQ1\xceA\xec_@\ -,A\x8c\x03\x98\x81\x0a9\xa1\x89\x90\x9a\xf9~\x1a)\ -\xa5\xa1\x0a\x10o\x07\xe2\xcd@\x8d\x9b\x81\xf4&\x18&\ -\x93\xbf\x14\x88yF\x9b{\xa3`\x14\x0cZ\x00\x00\xef\ -\xad\x00\xe1,\x84\xf5\xf4\x00\x00\x00\x00IEND\xae\ -B`\x82\ -\x00\x00\x02h\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\ -\x00\x00\x02/IDATx\xda\xed\x96\xcb+\xc4Q\ -\x14\xc7\xe7\xe11\xcd\x90\xc9L\x1a\x22e\xe4\x91YL\ -\x13\x8a\xa2lllX\xa1\x94WQ\xc6\xb3\xd8x\xd4\ -\x10\x0bE\x8d\x14\xfe\x03\x0b\x89\xb2\x96\xc4\xc2B\xf2(\ -\x22\x0by,lH\x16\x1e5\x8d\xef\xad\xab\x8e\x99{\ -~\xbfYZ\xfcn};\xbf\xee\xe7\x9e\xf3;\xfd\xee\ -\xb9\xe7wM\xa6\xff0Z;\x07J\xa0\xf5\x96\x8e\xfe\ -a\x8d5\xed\xe0\x1b\xb0\x95\x0c\xb7\x83\x87aW\xc4\xb3\ -j\x0dx\x00l\x13\xea\x8au>\x82\xa2X\x10\x85\xf5\ -+\x82g\x13~\xcf$0.\xb9P\x88I\xe0Jr\ -!/u\xde!/(P\x04\xcf\x80\x22\x92\x9f0\x09\ -t\x93\x04\x82L\x02\x07\x92G \x0f\x056\xa8\x07\x93\ -\x15\xdc\x16\x80\x8bm\x0a\xc2:5\xb6\xa9\x09\xbcY\x83\ -\xa7\x83\x8b\x18>\x931\x8c\xa1(\x90L\x14\x87Uk\ -\x0d\xb8[\x87\xdb\x11'M\xe7=.\xc8\x1c;9)\ -\x8f\xe1\x13\xacC\xe1d\x85\xce\xe51[e\x02W\x83\ -G\xe41\xaba\x12\x5c\x94\xfc\x02\xb2Q\xe7k\xd2\x07\ -j\x15\xc1\xbd\x84\xbf0\x09\xcc\x93>\x10Vp3\xf8\ -\x03iDe43\xd1f_1y\xc8m\x03\xe6\xb7\ -\xc0\xdf`\xc7\x18^\x0c~'^\x02\x952I\x0e\x81\ -\xbdC\xdb\x90%\x16Z\xf4\xeaD\xafF\x12\xac5\xab\ -q\xe2\x8c\xa1*\x8c\x5ch\x19E\xd6\xa6\xb1\xa6\x01\x5c\ -\x5c6\xb8\x0aO\x02\x17\xfdd\x1aJf\x8aX\x1c\xe7\ -5\xa81\xd6y\x9f\x9cs\x9f\x22x\x16\xe1\xb7L\x02\ -#\xa4\x0fL0\x09\x9c\x91>\x90O\xc1\xee\xaf3l\ -\x91\xc2\xd1E\xf8%\x13|\xf07Ih\x94I\xf2X\ -r\xa1\xbc?\xff\x01\xd1\x8e1Y\xaf\xb1\x05U\xe0!\ -\xd8\x1c\x8d>\xd1\xcb\xdd\x86$\xf7\x80\xcfp\xad\xda\x18\ -F/p\xc6\xfd\xa1\xe2\x8b(3\x81\x0b\x89C\xef\xe2\ -\xa3\x9a\xec\x83>\x10\xe0\x146\x85q\x14G\xf5\x0bv\ -\x96\xe1~\xf0gq_\x80\x02L\x82S`\x22\xc6\xde\ -\x9ff\x05pC\xcey\x9d\xc2\xb1\x90\xf0W&\xf8\x02\ -\xe9\x03K\x0an\x01\x7f$}\xa0\x8cf\x1f\x84>e\ -\xa7J\xd5\xf9\x02s\x09|\x81r&I\xd1\xaa\xbf\xe3\ -\xbe\x00\xb9\x94\xea\xd5\x80\xde\xa5\xd4\x91@\x0d\xb8\xffU\ -\xf1\xff\x00\xf0W\x81\xb2\xb1-\xb20\x00\x00\x00\x00I\ -END\xaeB`\x82\ -\x00\x00\xa1\xcb\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x80\x00\x00\x00\x80\x08\x06\x00\x00\x00\xc3>a\xcb\ -\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\ -\x04gAMA\x00\x00\xb1\x8f\x0b\xfca\x05\x00\x00\x00\ -\x09pHYs\x00\x00\x0b\x22\x00\x00\x0b\x22\x01\x09\xe1\ -O\xa2\x00\x00\xa1`IDATx^]\xfdg{\ -cI\xb2\xa5\x89\xf2\x0fMF\x04\xb5\x04@\x90\x00\x08\ -j\xad\xb5\xd6Zk\x15\xd4:\x14\x19Z\xeb\x88\x8c\x94\ -\x91:\xab\xb2\xeaTU\xd7Q=\xdd}\xfav\xf7\xcc\ -<\xf7\xfe\x13\xbb\xef\xf2MFe\xcf\x07{\x00\x92 \ -\xf6\xden\xcb\xcc\x96\xb9\x9b\x9b\xc7\x84\xc7\x1f[\x04\xc9\ -Ar'\x9eZ\xf1\xec+\xabX\xfe`5\xeb\xdfX\ -\xc3\xd6\xf7\xd6\xb4\xf3\xa35\xec|o5\x1b_Y\xc5\ -\xea;+Y|n\x05\xb3\x0f-:qf\xe1\xa1c\ -\xcb\xea\xdd\xb2@\xfb\x92\xa57MYZ\xfd\x88\xa5\xd6\ -\x0dyR?li\x0dc\x96\xd68\x8eLx\xaf\xfc\ -\x9cZ7b)\xb5\xc3\x96\x5c3dI\xd5\xc3\xc8\xa8\ -%\xd5LXr\xdd\x8c\xa54,Xj\xd3\x8a\xa5\xb7\ -\xae\x9b\xafs\xdb\x02\xbd\x07\x16\x1c\xe0\x1a\x83\xd7,{\ -Hr\x82\x1c\xf2\xbb=\xcb\xec\xdf\xb6\xcc\xbe\x0dd\x1d\ -Y\xb3\xcc\xde\x15\xcb\xec^\xb2\xcc\xae\x05\xf3\xb7\xcdX\ -F\xd3\xa8\xa5\xd6\xf6ZRE\xab\xc5\x17\xd7ZlA\ -\xa5]\xce\xaf\xb0K\x055v\xa5\xb8\xd5\x12\xaa\x87,\ -\xade\xd1\xb2\x07\x0e\xadp\xe6\xa1U\xae\xbc\xb3\xba\xcd\ -o\xac~\xeb;\xabZ\xfb\xc2\x0a\xe7\x9e3.w,\ -\x93k\xfb\xfa\x0e\xcc\xd7\xb3o\xfen^\xbb\x90\xce]\ -^w-\xd8\x7f\xc8\xb8\xdd\xb4\xc2\xf9\xfbV\xb6\xfa\xcc\ -*\xd6_Y\xf9\xfaK+\xe5}\xf1\xf2c+Z~\ -\x80\xdc\xb3\xfc\xc5\xdb\x96;\x7fj\xd1\xb93\xe4\x8e\xe5\ --<\xb0\xd2\xf5\x17V\xbb\xf3\xceZ\x0e\xbe\xb0\xee\xe3\ -\xaf\xad\xff\xda\xb76p\xed\xa3\x0d\xde\xf8\xd1F\xef\xfc\ -\xc9&\x1e\xff\xb3M\xbd\xf8\xaf6\xf7\xfa\xffc\xf3\xaf\ -\xff\x87-\xbc\xf9\x1f\xb6\xf2\xf6\x7f\xd9*\xb2\xfc\xfa\x7f\ -\xda\xc2\x8b\xffn\x93\x8f\xfe\xdd\xfaO\xffj]\xd7\xfe\ -h\xedG\xbf:\xe9:\xf9\xa3\xf5\xdd\xfc\x8b\x0d\xdf\xfe\ -\xbb\x8d\xdf\xffw\x9b~\xfc_m\xe6\xc9\x7f\xd8\xe4\xc3\ -\xffb\xa3w\xff\xcdzo\xfc\xcd\x9a\xf7\xff`5\x9b\ -\xdfs\xcf_[Ld\xec\xaeE\xc6\xeeYt\xfc\xbe\ -\xe5M>\xb2\xe2\xb9\x17\x0c\xc6{\xab\xbd\xfa\xb552\ -\x18\xcd\xbb?X\xf3\xcewV\xbf\xf9\x95U\xaf\xbd\xb3\ -\xf2\xa5\x17V2\xf7\xc8\x0a&y\xa8\x91k\x16\xe9\xdf\ -\xb5\xec\xee5\x0b\xb6\xcf[\xa0e\xca\xfc\xcd\xe3\xe6k\ -\x92L\x98\xafy\xd22.\x84\x9f\xd3\x01Az=\xa0\ -\xa8\x93r\xc6\x00\x82\x14?e\xc9\xf5s\x96\xd2\xb8h\ -\xa9\xcd\xab\x96\xd6v\xd52:\xb6\x18l\x94\xdcwd\ -A\xa7\xfc\xeb\x96=\x8c\x00\x80\xacA~7\xb0\xcf\xdf\ -\x04\x90\x0d\xf3\xf7\xac\xf1\xd9\x15d\xc9\xfc\x9d(\xbfc\ -\xce|\xadS\x5c\x0b0\xd6\xf6YRe\xbb%\x944\ -Z\x5cQ\xad])D\x8a\x1a-\xb6\xb4\xd3\x12kF\ -\x1d\x00\x82\xbd{\x967~f\xa5sO\xadr\xe9\x8d\ -U\xf1\xec\xe5\x0b\xaf\xacp\x1a\x90\x8f\x9d9\xe0I\xd1\ -\x99\xbd\xe7\xd2sd\x81\xee}\x0b\x00\x88`\xff\x91\x85\ -G\xaf[\xde\xd4\x19\x80\xb9o\xc5\x0b\x8c\xdf\x22\x8a_\ -xh\x85\x0b\xf7\x91\xbbV\xb8x\xd7\xf2\xe6Q\xfc\xec\ --\xcb\x99\xb9e\x91\xe9S\xcb\x99\xbem\x05\x80\xa6\x14\ -\x90T\xaf=\xb3\xc6\x8d\x17\xd6\xba\xf5\xca\xdav\xdeX\ -\xc7\xfe\x07\xeb\xb9\xfe\xd1\x06n\xffj\xc3\x0f\xfebc\ -\x8f\xfe\xeed\xea\xc9?\xdb\xc2\xf3\x7f\xb5\x85g\xffb\ -s\x8f\xff\x93M?\xf8'\x1b\xbc\xf5\xb3\xb5\xee\x7fe\ -\x8d\xdb\x1f\x90/\xd0\xd5\xd7\xd6~\xf8\xbd\xf5\xdc\xf8\xd5\ -\x06\xce\xfe\xc9F\xee\xfd'\x1b\x7f\xf8o\x00\xe5?\xdb\ -\xf8\x83\x7f\xb3\xa1;\x7f\xb7\xee\xeb\x7f\xb6\xa6\xbd\x1f\xac\ -\xea\xea\x97\x5c\xff\x1d\x00\x18\xbd\x09\x8aO\xb1\xfe;V\ -0\x0d2\x17\x9ec\x01\xb2\x86/\xadi\xfb[k\xd9\ -\xfd\x0e\xf9\x160|iu\xeb\xef\x18\xa0\x17V6\xff\ -\xc8\x8a\xa6n[\xfe\xd8u\xcb\x1d:\xb0\x9c\xbeM\x0b\ -w\xafZ6\x0a\xc8F\x01Y\xed\xb3\x16l\x9b\xb5L\ -$\xd0:k\xfe\x96i\x80\x018\xf0\x12\x12_\xe3\x94\ -e4\xce\xa0\xa4yKk\x92\xe2W,\x0d\xabOo\ -\xdf\xb4\x8c\xce\x1d\xf3i\x805\xd8\xfd'\x0e\x00Y\x00\ - \x0bEd\x0d\xea\xe7c\x00p\xc0\xdfv\xf9\x0c@\ -\xe9\xb9\x8a\xf2W\xb1\xca%\xf3u,\x98O\xd6\xdf\x8c\ -\xc7i\x18\xb6\x94\x1a\x01\xa0\xc3\x12\xcaZ,\xbe\xb4\xd9\ -\xe2Jx-\xeb\xb4\x84\xaa\x01@7\x89\xa7Y\xb6`\ -\xcf\x8eE\x86\xafY>\xcf_4\xfd\xc8Jf\x9eX\ -\xd1\xe4\x03\xcbC\xf9\xfa\xbdW>\x7f\xd7\xaa\x16\xefY\xcd\xca\ -C\xab_\x7f\x8a\xc1\xbd\xb6\xb6\xc3\x0f\xd6\x81W\xe8\xbe\ -\xf1\xbd\x93\xbe\x9b\xdf\xdb\xe8\xd9\x8f6r\xfa\x1d^\xe2\ -k\xeb;\xfe`\xad\xdb/\xadj\xf9\xa1U,=@\ -/\x8f1\xda\x97\xd6\xb4\xfb\xde\xda\x8e\xbe\xb1\xae\xeb?\ -X\xef)@\xb8\xfd\x9b\x0d\xdc\xf9\xb3\xf5\x9d\xfe\x91\xdf\ -\xfd\x8c\xc7\xf9\x887\x7foe\xcb/\xf0\x5c\x8f-&\ -:\x0e\x82'o\xa2\xfc\xdbX\xff}+_~\x8a\xfb\ -\x7f\x8d\xc5\xbf\xf7P\xb5\xf3\xa55\xf3\xda\xc8?\xd5\xf1\ -\xfb\xea\x95\xe7V\x01\xd2Kf\xeeX\xe1\xc4M\xcb\x1f\ -9\xb6\xbc\xc1=\x8b\x0elY\xb4\xef*`X\xb3H\ -\xef*\x80X\x01\x10K\x96\x85R\x82ms\x16\x04\x08\ -\x9e\xcc\xf33\x96\xd7\xb6j\x99\xed(\x0fk\xf7u\xa0\ -\xf4\xae=\x14\x7f\x80B\xb1\xb0>\x06\xb9\x1f\xcb\x1b\x90\ -\xd2\xaf;\x10\x04\x9d\xf2/\xe4\x08\xd7\x8c\x12\x08\x05\x01\ -<\x81\xbfg\x83\xff\x07\x04\xed\x8b\x96\xd1\x0a\xb0\xf06\ -\x0aA\xc9\xb5\xfd\x96T\xd5\x0d\x08\xba\x10^\xab\xfa\xf1\ -:#\x80\x03\x00\xb6.\xe21\xd6Q\xe8\x0e\xa1\x0cW\ ->\x02\x98GO-o\xf4\xccr\x87Q\x10\xd7\x09\xf7\ -\x1fXv\xdf\xaee\xf5\xe0\xeee\xf1(>\xc8\xbdI\ -\xe4\x9d2\x09\x0d\x99x\x90L\xbeC\x12\xec\xc5\x1b\xe2\ -\x9dB\xc3\x87x\xd5#\xcb\x99<\xb1\xdc\x99\xeb\x16E\ -\x22\xd37,\xb12\xc0V\xbd\ -\x06\x88\xb6_X\xe3\xde[k9\xfc\xdcZ\x8f\xbe@\ -\xd0\xe1\xfe\xe7\xd6\xb0\xfd\xd6\xaa\x09=eK\x8f\xf0X\ -w-\x1f\xf0\xc5\xe4q\xd1\xfc\x99\x9bV\x04ZKp\ -Y\xe5 \xaaz\xed\x89\xd5\xae?C\xe1\xcf\x91\x97V\ -\xb7\xfa\xd2jAL\xf5\xd23\xab\x5cxles\x0f\ -\xacdZ\x00\xb8e\x05\xa3\xdc\xc4\xc8\xa1\xe5\x0fs#\ -\xc3\xbb\x967\xbc\x83W\xd8\xb2\x9c\xfe\x0d\x0b\xf7\xaeY\ -\xa8k\x19\xaf\x80g D\x84x\x0dw\xaeX\xa4{\ -\x03\x90\xec\x12>\x0e-\xa4\x18?p\x822O,\x80\ -\xf8Q|\x00q\x00\x90\x07\xe8g\xc0q\xb5\x99\xb2>\ -^\xb3\x1c'@\xc4?\x18\xbcL\x06<\xd0\xbb\x0d\x00\ -\xd6-\x03`\xa5\xb7\xccX*\xa1&E\x00\xa8\x1b\x04\ -\x04\x03\x96\xc2kj=._\xde\xa7m\xc1\x02\x9d\x84\ -\xac\xdeM\x94\xb5k\xa1\xa1}\x0b\x0f\x1f G(\xe4\ -\xc4B\x5c/\x9bke\xf7\xee[6\x8a\xcfF\xb1\xd9\ -(9\xc4\xefB\xdc_h\x10%\x02J\xdds\x10\x00\ -\x04\xba\x01o\x07a\x0b@K\x1c\xa8\xf0\x88!\xc6!\ -2q`Q\x14\xe3\x000u\xc3B\xe37\x9c'\x13\ -x\x5c\x18\xc1\xdbevm\x01\xae-\xae\xb9ea\x8c\ -(\x87\xb1\xcb\x1d\xde\x02\x14\xdb(v\xd7\x0a&\xf6\x90\ -}+\x9e>D\xe1'V1{he\xd3\xbbV<\ -\xb1i\xd1!\xf1\x1e\x7f\xe4\x00!\x9e\x8e\xec\xf2\x00;\x963@X\ -\xe8]w\x9e \xdc\xc5\xcd!9\xbc\xcf\xed\xbdj\xb9\ -\xb8\xef\x5c\x94\x97\x8b5Dq\x87\xe1\xb1\x9b\x96\x85\x0b\ -\xcd\xc4\x0a\x03X\xbb\x1f\xc5\xfb5HX\x9cbm\x00\ ->\x10\xe8\xd9s\x03\xee\xb9\x5c\x06\x94\xff\xd1\xff\x85\x00\ -`pP\x9ec\xcb2\xda\x09%-s\x00`\x12B\ -\x09\xc7\x80\x94\xa64\xc07D@\x09C\x19x\x88@\ -\xf7:\x83\xb5\x85\xe2\xf7,2\x8a\x95\x8e\x1fC\xf6\xf8\ -\xceQ\x11L)U\xca\xe1z\x90P\x7f\xc7&\xaf\x9b\ -\x16D\xc9\x02E\x88P\x14\x199\xe5\xfa\xa7\x8e\x97\xe8\ -~\xfc]\x9b\x96\xde\xb6L\x18\x9b\xb7\x94\xe6YB\xd9\ -\x19\xf7\xd1M\xc6h\x9b\xe7\xdb\ -a\x8cw!\xed{\x84\xa8}\xe4\xc0r'\x8f,:\ -y\x8c\x9cXL\xc1\x0cDe\xd6\x93\x22\x85\x81\xa9[\ -V\x02ZK&\xafY1R4y\x1d\x81\xe9\xe2\xee\ -\x0b\xe4\xf2Aq\x9eb?\x03\x16E\xf19\x83\xfb\x16\ -\x19\xdc\xe5\x15\xc4\x0fn#B2\x16@8\xc8\xeeY\ -\xb5\x10J\x8f 9\xbc\xcf\x05\x10\xf9\x03 \x1b\x8b\xcb\ -\xe7\xff\xf3\xf8\xbe\x5c\xae\x17\x01\x84\xa1\x09\x06\x94\xdf\x05\ -\xb0\xec\x00V\x1e`\xc0\xfdX\xa1\xc8\xa0\xbfk\x07\x81\ -\xf5c\x91\x22\x81\x22^\x11\xbcO\x0e\xe4+\x02\x10\xb3\ -\x01\x81<\x81\xbf\x1be8\x10\xcc\xa3\x10\xb2\x8a\xa6i\ -^\x91\x16\x14\xd36\x8f\xa5.;\x00\x04\xfb\xb9\xbf!\ -\x5c\xff(\xd6?\x8er\xc6\xb1\xf81<\x8d\xae\xad\xeb\ -b\x9d.,\xc1I\x1c\x08\xb8v\x90{\x91\xe2B\xc3\ -x\x80\xa1\x1b\x84\xa7#>\xb7\xcd\xf5V\xb9\xc6\x9c%\ -\x13V\x92\x1a&-\xb9i\xd2R[QL\x07\xdc\xa7\ -{\x01O\xb6\x0a@7p\xfbx\x9ba\x80\x06\x00\xc2\ -|G\x18/\x12\x22\x94\xb8\xf0\xd2\xb5A&\xb5l~\ -B\xa4\xafe\xc2e0\xe9MCp$\xa4i\xd8\xd2\ -\x9bG\x10~\xd7\x0c\x81n!\x93j\x01\xd4N\xf43\ -\xc4\xba\x15\x92\x0d\xf1\xcdh\x9b\xe6\xbeg\xe0Cs\x5c\ -{\x1e\xa3\xc0\xdb\xe1\x192\x07\x00\xe3\xe0\xba\x85F\xb6\ -\x00\xc5>`8f\xdc\xd1#\x844\xa6d\xe99\xee\ -\x82\xb4E\xc4N`\x90\x92\xb1\x8c\x5c,$g\x00\xa5\ -\x22a$$w\x89\x84%X\xb0'\xfc\x9e\x18\x1c\x92\ -E\xe1\xf6\xb2Qz\x16J\xce\x82\x99\x07Qz\x10\xab\ -\xcf&\x04\xc8\x0b8\x00\xf0\xf7<\xbe+\x0f\xb7\x9b;\ -\xc25\x88{\xd1\x09b-7\x94=\x86\x8b\x1f\xc1\xda\ -\xf9[\x00\x92\x17 \xfe\x06 _\x01\xdc\xaf\xdc\xac\x06\ -\xdb\x01\x00R&\xab\x8f@\xa6\xc4\xa6s \x5ca\xee\ -9\x8b\xc1\x0dpO>\xc2Kz\x87\xb2\x09\xac\xb2u\ -\xc9IZ\x9b'\x19\x00\xc0\xd7\xb5\x827A)\xfd\xdc\ -\xa7S\x0c\xeewd\x87Wb\xbcx\x85\xc2\x8d<\x0f\ -|$\x00/\xc9D\x82\xe7\xde\xc7\x0b?\xe2&\xf2N\ -\x5c\x0b\xcbM\x83K\xa44\xcd8\x00$\x03\x80\x14R\ -\xdeT8H\x1aDT\x8a\xf1\xb5\xcf\x00\xdeE\xee\x1d\ -\x83\xe8\xc7\xeb\x10\x02r\xe0\x18\xd1\x91[\xb8p\x80 \ -\x22\xd9\xb3i\x99\x1d\x90X\xb2\xa8t\xc8k*\xdc%\ -\xa5\xa6\xc7\x92\xab\xbbH\x97\xbb\x09c\xbc\xaf\xebC\xfa\ -!\xaf\x10\xd8\x06\xc9 \xd7\xe2\xb3\x8d\x0amx8]\ -\x13\xf0\xe9\xbai\x80(\x8dk\xa7\xb5O[z'@\ -\xe8\xc5\xb3\x0c\xe0\x8dF\xe1j\x18t\xfe\xccm+\x9a\ -\x7fH\xc6\xf2\xd4b*\xaf~n\xe5\xabo\x88\xff\xcf\ - \x82\xf7\xb1\xec\x1b(\x1dW\x0b\xc3\x0ev\xc95\xad\ -\xe3^H\xb5\x10\xc5\xceL\x5cU\x90\xd7\xac.\x09\x83\ -\xe8\x04\x85#\x99\x1a\x5c\xdcX@.\x90x\x1fh\xc7\ -\x9dA\x04\x9d\x17\xe8Y\xb7\x1c\xe2n\x94\xfc=\x0a\x88\ -\x22\x10\xb80 \x0b\x112\xb2P@p\x18\x05\x0f\x91\ -\xda\xe1I\x02\x90\xcaL<\x8b\xac:\xb3_ \xd8\x05\ -\x00\x02\x011S\x8c\x9c\xf0\x91=v\x0d\xaf\xc1\x00N\ -*\xb6B\x16\x01\x94\xf3\x02\xf0\x81\x0cy\x82N\x01\xe1\ -*\x16\xba\xce@\xac\x01\x00<\x03 H\x87'dp\ -_J\x19\x03\xa4\x8e\x01\xcd\x1fh\x1e\x01\x00\x07\x01P\ -\x96\x14\x22\x1e\x00\x07\x099\xc1\xeae\xf9(_\xe1G\ - \xd0=\xf8\xbb\x15r\xf8^R\xc9\xd4&\xd2X@\ - I\xd5|\x88\x14\xa1\xb0\x83b\x94\x02\xfb\xb0\xec\x00\ -\xdcG|\x22\xc2wDG\xb0\xbe\xd1[\x18\x01c\x0d\ -\xe8\xb2\x19\x97L\xc6\xcd\x87\xe7HG\xa1\x9aGI\x11\ -w\xa9A\xe1\xff/IrBv\x03H\xc4q\xc4u\ -R\x95Z7\xa0tB\x9f\xe6\x5c\x04\xc0T\xae\x9b\x06\ -!\xf6\xc2\x11\xe0#\xc2\ -\x00\xd6\xef\xc3\x12\x15\x16\x02()\xa0\xf9\x00\x88[\x90\ -0\x14$\x15\xd5\xe7\xfd|\xb7O\x84\x10o\x91\xc1\xfd\ -g\x10_3p\xe1\xe9m\xb2T\x00\xd0\xbc\x88\xcc\xe1\ -J\x19\x18\xc8\xa2\x14\xe3\xee\xb5\x83g\x121D\xa9\xd9\ -(7\x8c\x92#\x837 dX\xaa2\x02\x5c\xb6,\ -W$Qia\xa6\x00I\xec\xcf\xc0\xfd+\x95\x14\x08\ -\xd2\x9a\x17x%\xad\x15\x0f\x10\x08\xce'\xbf\xd2\x01\x83\ -\xafu\xce\x19N\x08\x8f\x19\xc5S\xe5\xc1w\xf2\xe0>\ -\xb9\x84\xd2\x1c\xee?\x84Qduc`\x18\x8dOJ\ -#e\xd6\xff\xa5\xa3P\x89\xfb\xae\xfaq\x801\x0a(\ -.&\xd1\x06\x01\xc2\x10\xdeA\x80\xe1\xef\x0d\x80\xa7i\ -\x96\xffE\xe0A\x19\x0ay\x18_\x00\xce\x95%oN\ -\x88-\x9c\xbf\x87\xb1C\xee\xb7\xde\x93\x0e~c\x9d\xc7\ -?ZL7\xf9b\xe3\xee\x97V\xbe\xf2\x12rp\x8f\ -\xd8\x08\x19S\xec\x85\xfc\x88\xd5\xa6\xc9\x85\xb6\xf0p\x90\ -\x9ct\xbe\xd8\x87\xf8y\xd0@+\xf1M\x22@\x00\x8c\ -\x00\xaf~~\xfe\xbd\xe8\xf7Y\xb8\xe3\x10n9\xdc\x03\ -?`\xe0\xc2H\x88\xf7A,4\xc0\xdf|\x9aE\x04\ -(\xe9\xdcp:\x8a\xc8\xc0\x8b\xf8\xb9i\x7f?\xe4\x08\ -O!\x00\xf8\x09\x07Np\xc3nVN\x82g\xf0c\ -\xb1~\x06\xd5\xafT\x10\x8f\xe5\xc3\xf2}R\x0c\xca\xd7\ -L\xa2f\xeb\xfc\x12\xcd-h\x8e\xa1m\x8d\xc1\x01\xcc\ -(,\x83g\xca\xe09|\xbc\xf7\x03\xf0L<]\x16\ -\xf7\x15\xe6{s\xb0\xd2\x1c\xb9j\xdc\xbdK\x07q\xf9\ -!\xae\x9f\xa5\x94O\x9e\xa8c\xc3}W\xba@\xc5\xf7\ -\xa5;Y!\x0e\xaf\xa0@\x0cE)\xa6\x9e\x9fW\x19\ -@\xb6\xb2\x1e\xdc\x7f\xee\xc8\x89\xe5+s\x9a\xba\xed\xd2\ -\xee|\xc2X.\x9e,B\xf8\x09\xf1\xbcAB\xa7<\ -\xa8\x9fp\xe0g\x5c\x9f\x89\xc7\x08:\x81x\ -t\x10&\x88\x93\xd9XV\xa8G\x96\x8f\xdbWJ\xc5\ -\xfb,\x00\x16\xe03RF\x1a\xc8Mm\xf4\x08[Z\ -\x1b\xe8\xd5\xa4\x0e\x83\xe1\xc3-K\xc9R\xb6\x0f\x05\xf8\ -\xb0|)?\x83\xef\xc8\xe0;2\xf8\xdet\x067\x83\ -P\x95\x81\x05+\xf6\xa7\xe3\x96\xd3\xdb5\x9b\x08(\x14\ -\xc3{4y\x83\xa7\xd0+\x1e$SdR\xd7&<\ -\x04\xf8\x5c&\xaf\x02c\x16^#\xa4\x18MF\x91C\ -\x88\xc9\x19\x22\x97'\x14\x86\x19\x8bl\xdd/\xd7\xf2\xfe\ -o\x03\x85\x5cE\x94v*\xfd\xe3\xbd#\x8bb\xf3\xfa\ -\xcc\x16!\x11OBV\x12\xc2#E\xf0bQ2\xa5\ -|M\x19\xa3\xf4\xa2\xd9{d[\xf7\x1c\xe9\xce\x87\x84\ -\xe5b\x999\xa4\xd1a\x88\xb4R\xc1`\xcf\x06\xf7,\ -\xc1C*\x0c+<\xa0L?^V\x80M\x85k\xa4\ -\xa0\xf4d\x94\xafi\xf4\xe4\x1aV.\ -k/D\xf1E\xf3\x0f\xdc$L\xf9\xf2#8\xd7}\ -\x97z\xe7C\xca\x22dE\xd9x2\xa5\xa7N\xe9<\ -o\x10\xd0k\xc63\x0b\x91N\x02x7\x97\xe6\x8ao\ -\xd4\x93m\xd4\x8c\x9d\xaf\xa3\x90\xee\xd6)L\xa0\x17\x9e\ -\xdf\x8f\xd1\xb9y\x05\x9e@\x00\x10@\x95e\x9c[\ -\xbb\x03\x80\xb2\x1d\x94\x0fA\x94\x08\x0c\x01\xcds\xa0\x17\ -\x19\xa4K9k\xc7\xddz\x86$\xa9\x8eq\x83\x03\xe8\ -o\x19\xa4\x93\x01t\x98\x05h\xc2\x84\x9c\xa8\xb2:X\ -\x7f\xc1\x9c@p\xd7\x8a\x97\xeeA\x00\x1f\x01\x82g\xd6\ -\xb6\xff\xcab\x0a\xa7oXt\x5c\xd3\x92\x9al\xc1\xda\ -x\xe8\x0c\x91>,S\x00\x90\xd2=!\x0e5+\xbe\ -\xad2\x10\x905,!\x93\xc1\xc8B\xe9!\x5ck\x18\ -\xeb\xce\xc1E\xe7\x10/\xf5z\xa1h)\xffB\x22<\ -\x98\x16\x8fr\xe4\x9ex\xe0l\x91@\xd8\xb1b\xa6\x08\ -Lj\xa3\xc8\x93\x08\x10y\xb4\xf8\x0610\x00\x00\xe4\ -\x0e3!wN\x18\x08Y\x83r~\x111'\x00\xc2\ -\x0f\x10}\xf2(\x88\xf8K&\x96\xa9\x19\xbb\x9c1\x1e\ -|\xf6\xb1[\xc4\xaaXye\x15\xab\x92\xd7(\xe0\x15\ -\x16\xf9\xc2\x8a\xe6\x9eY\xe1\xccc\x0c\xe0\x1e\x83u\x8b\ -AS\x06\xb0\x8b\xdb\xe5;]\x88\x02P\xcd\x00\xacE\ -\xe3\x22\xe3\xc0\xf2\xf1,R~\xd6 \x19\xc8\xf0)\xd7\ -\xb8\x8d\xe2\xef\xa2x\xb9uM\xb1\x22(>\x8f\xb8\xeb\ -\x04\x05\xe490\xdc\xc1\xd3b\x89N\xf9w\x00%\xe0\ -\x1c\x87_\x0c\xe8\xd9D\x88%\x1b.vg\xcb\x0b\x01\ -FI\x96V?\x19\x03)7\x95qJ\xaa\x9f\xb0D\ -\xc8_\x02\x5c \x01R\xa8\xf7JA\xf57e9~\ -B\xa2@\x14R(\x83hF\xf1\x02\xd1)\x84\xeb)\ -\x13\xc8\xe3\xb5p\xf6\xa6\x95\xcc\x9fZ\x8c\xdc\x8d\x06V\ -3i>\xc5}\xacR\x1e@\x0f/\xf4\xfb!6\x9e\ -\xe8\xe7s\xc5kb\x04+P\xb6\x10\x92\x95\xe1JE\ -\x98\xa2\xc3\x5cL2\x04\x8b>\x8f\x9f\x9e\x17\x80\x5c!\ -\x11\xae\x93\x03a\xcb\xe1\x01#\x90\x9e\x90\x18*n>\ -\x93\xf8\xe6Sz\xe6H\x19\xfc\xc2e\x10\xe4\xce\xca0\ -\x94f\xa2\xec,\xee/\x8b\xff\xd7\xf2sP\xaf\xdcw\ -\x16\xdf\xffI\x00\x98\x16v4\x1f\x9fE\x98\xc9\xe6~\ -\x22\x9a\xd7\x9f\xbc\xcf\x83>u$\xb7b\xed\xb5K\x7f\ -\xaa\xd6\xdf\xc2\x86\xdfZ\xd9\xca\x1b\xdc\xe2+\x97\x02\x17\ -\xce\xe2\x11&Q\xe6\xa8\x8ca\xdf}\x7fPs\x0f<\ -k\xa0\x13W\xdf\x85K\x86Gd\x91\x16z\x16\xcfg\ -\xc7Q.\xdf_\x80G)\x9c}\xe4\xbe\xa3\x00W/\ -eG\x89\xef\x11R\xd4\xc8\x04\x16>\xa6\x99FM`\ -\x1d\xe1uN\xf0>\xd7y=&\xe5\x16\xdf\xd0=\x03\ -\xdan<*\xbcGK\xdcY\x9a{!~\xe7\x11B\ -\xc4\x1d\xf24c\x8a'\x08IGx8\xf1\xb1d\x98\ -\xbf\x07\x82aK\xa8\x1d\xb1D\xb2\x84dx\x94f\x22\ -}\xf0\x00y\x0c\x01G\xcb\xe7!@\x1d\x22M\xce\x86\ -kd\x911\x051v-\xa9\x07\x09s1\x9a`\x91\ -\xc8\xb5z\x0cZ\x0b+\xc4=,@3TY\xfcN\ -\xf1:\x9b\xcf\xc8\xda\xb3dY\x9a\x16u\xb1\x93\xf8\xa5\ -T\x09\xf7\xa7\x85\x14OH\x9b\x86\xbc\x85\x94\x90\xe6\xd1\ -Q^\x88\xef\x09\xf3}.\x15\x84\xd8i\xe1\xc8M\x15\ -\xf3\xb0\xd9\x9a8\x12\x08\xf0\x04\x9a\x0d\x0b82\xe9\x89\ -G$5\xcf \x22\xc9}\xf0P\xfa\xce\x90<\x08\xe1\ -*\x0ca\xd3B\x8e\x13\x0d\x10\xa2\x1a\x85\x08\xf9\xb5\x96\ -r\x9dr\xb4\xc2\xb7\x00\x00\x96\x9f\x03\x02\xbc\xc0\xeaK\ -@\xf0\x1a\x00\xe0\x05\xf0\x08\xa5\xfc\xbeh\xfe\x11\x96\x8b\ -\xd2\xc65KG\x08\xe0\xbb\xb3\xf1`\xd9\xe7s\x02\xa1\ -\x01\x14>t\x06\xa0n\xf3\x19B\x06\xdf\x9bGH)\ -\x9c{\x845?\xc5\xb3<\xb7\xca\x15\x85\xd2\xc7.\xb6\ -\xe7\xcd\x9cZXs\x13\xc4\xf6\xe0\xa0\xe6.\xf0Z\x80\ -=\xd0\xb3\xee&\xcc\x22<\x7f\x98t\xd7{~1\x7f\ -<+\xa2e\xedL\xe5\xec\x9aY%~\x17A\xdeJ\ -\xf1&ex\x95\x92\x09\xc2\x85V'\x01\xa4O\xd9\x07\ -\xa19\x19\xf6\x9f\x88\xfbO$3Hl\x98\xb0d\xcd\ -|\x0a\x00\x18\xb0\x00\x90\x89\x17\xd0\xd2\xb9\xc2I\xa6x\ -\x04?\x07\x18?\x17N\xd1\xa9$&@\x8c\xd6<\xbb\ -\x1f\xcb\xb9\x10}0\x0bt\x88\x08i\xc2&\x8aE\xe4\ -2\xb8Q\xdc{\x14\x92\xa3\x19,O\xe9\x0c2V\x90\ -O,- \x85\xd4\x92j\xee(\xb1\x14\x00\x84\xb0J\ -)-\x0b4f#!,9\x8c\xcb\xcf\xe1\xc1s\x07\ -\xb7-wh\x9b\xef\xc2\x1b0\x18\x9e7\xe0\xb3\xb0\xdd\ -,\xa5c(=H|\xd7\x8a\xa1^\xf5\xb3H\xa5x\ -\x83f 5\xfd\xac\xfc9G,\x17\x89\xf0\xde\x13~\ -\x1e\xc1\x13\x11\xcf\xf3\xb8\x97\xfc)\x01\x80\x98\x8f\xa2J\ -\x16P\xce\x22\xb1w\x09Y~j\xc5\x8bOP\xfcc\ -\xac\x16\x85\x11\xb3\xa3.\x1d\x03DR>\x03\xa6\x95\xba\ -\xf0\xf9\xdc\x7ft\x0cw>\xf1\x00\x90\xc0\x1df\x1e\xb9\ -\x82\x98\xc2\xb9\x87V\xc6w\xd4\xc2\xaa[\xb6_#\xaf\ -\xacq\xe3\xa9U\xa9\x00dJ\xcb\xd7\x1aS\x19\x94\xb2\ -\x12\xc2\x08i\xa1K\xa3Q\x90\xe6J.\xc4M\x98u\ -\xe0\xf1:I\xa9{V\xf0<\x02\xc0\x0e$\xf2\xc4J\ -\x08\x1d\xe5\x10\xc7J\x00Z\xa1\x05\xb8I@\xaa\xb9\x88\ -ntD\x18N\x87\xf3\xb85\x08\x91hxT*\x1e\ -T\xd7\x12\x99\x8c`\xe9\xca>\xa2\xf0\x80\xc80\xe1\x0a\ -@\x8bC]L\xa8\x05\xf4\x1dH\x8c\x98\xabf\xb7T\ -y\x93\x89\x82\xb5\xcc\xaaU\xb6\x08.#*\x97\x85\x14\ -\xe0\xc2\x0a\xb5d\xc9\x97\x15\xe0\x8e\x0a\xc7\xb5^@^\ -\xc9\xe0\x951\xb8\xaa\x0f(e@\x0a\x88\x81Q<\x80\ -\x18\xb5f\xbdD\xf2\xbc\x89\x22ra,<\x8c\x8b\x13\ -\x00\xf2p{Z8\xca\x1f\xddw\x927B\xaa\xe4\xa6\ -\x9e\xc5\x0d\x142\xf08\xf2>\x22\x98\xf2\x00\xb0\xf0\x10\ -`\xd2\xdf\xa4|M#\xe7\x89\xe1\x8e!\xdc\x97\xd2(\ -1i'zh\xc7\xc0\x05\x02B\xc0\x04\xf1yR\xa1\ -\x00\xef\x84D\xf5:\xe5\xbd\x8a \xe5\xa0xY}H\ -\xee\x12pi\xba\xd6-\xd3*\x94\xe1E\x14\xdb\xf3\xa7\ -p\xed(\xbe\xd0)^\x96\x0f\xa1\xd3\xd2\xf9\xe2Ck\ -\xdaxf]{\xaf\xac{\xef\xa5\xb5m=\xb1\xba\x95\ -;V0\xa1\xd5K\xcdF*;\xd1<\x8a\xea\x1e\x94\ -F\xc3q p\xeeU5\x11Xl\xb0}\x8eg]\ -\xe0\xf9\x96\xe0Hk\x18\x1c^\x01\x83\x10\x18\x8b\x09#\ -\xe5\x90\xc7J-\xc6!Z\x85\xcd\x1f'\xf4\xc8\x13\xe0\ -a\x15\xf2\x02\x8c\x93\xe3m\x22\xee\xce\xf5\xe3i\x87\xf7\ -\xad\x90\xf4\xb2\x08b_D\xec\xd7\x1a\x8e<\xa3\x96\xaf\ -U\xd7\xe02\x16\xe7\xd9N,&\x17\x0b\x8e\x8e\x8b\x05\ -\xe3\xe2\xb0\x1c\xad\xb0ET\xdc\xa0\x14\x86/)\xc0\x95\ -\x15j\xad\x9a\xc1\x16\x08\x0aa\xca%\x90\xa5JHN\ -\x0d\x03P\x8b\xdb\xabY~b\x15\xaa\x82\x99\xe2{\x18\ -8\xb9O\xcd\xaaerc\x9a\x0c\xcal\xd7\x84\xc8\x12\ -\xc8]\xe5!\xaf:\xcb\xcf\x13\x00\xc6\x0e\xf8\xfeC^\ -\x11\xe2a.\x0a\x94\xb7\x11I\x8c`\xed\x0a\x1d\xd9\x9a\ -G\x90(\x8c\x88C`\xa1\xb9\x9aM\xe3>\xf2P\xde\ -\x05\x00\xc2C\x90&b\x9b\xf2i\xa5q\xb2\x00\x97\xd2\ -i\xda\x18P\xbb*\x22\xb9A\xd2-\x89J\xcaD\xb6\ -\xa4(\x0d\x9a\x98\xb3\x08\xa6\xf8\x84\xb7\xe2\x088\xc6\xf1\ -\x0c\x0e@x6\xc0\x9dG\x98\xc8\x83\xddk\x11%_\ -\x8bf\xb3\xa7(\xfc\x9e\xb5o>B\x1eZ\xcb:c\ -\xb2\xc0\xb8\x8d*m\xc3B\x9d\xf2\xc9\xa4\x1c\xc1\xc5=\ -\x93\xbe\xa5\xfdN\xd2\x01A\x16\x00\x08a\xfda\x01\xa0\ -\x97\xf1\xe9\x07\xf4x\x0e\x01R\x0bo\xaa\xbb(#{\ -\xa8 },c\xbc\x0b\x09\x09yd\x1a\xf2t\x0a{\ -Y\x8c\x95RG\xf7\x0cH\x10\x8e\x95\x8b\xd1\x16O\xdf\ -\xc2@o#0\x7f\xee[\x9eY\xa48{P\xe1\x0c\ -/=r\xc6w\xdc\xb6\x98\xe2\xf9g\xa0\xf9\x89#1\ -\xf9Z\x0b\xe0A\x9d\xc5(\x9d\x11\x08\x88\x8b\xf9(\xbf\ -@\x1e\x00\x17+)f\xe0+g\xcex\xd8{V\xbb\ -\xf4\x00 <\xb0r\x15\x18hiW\xf3\xe5\xa4|A\ -,6S\x88T\x5c\x07\x00\x99\x1d\x80@\xb5\x01=\xab\ -\xb8\xf1\x0d,^ \xd8\xe5\xbb\xf7\xf10\x87N\xf2G\ -\xb5\xac|hy\xc4\xf6(\xca\xca\xc1\x8b\x84\x01\x92\xac\ -_\xf3\x09aBS\x0e\xee\xd9\x03\xc0\x89\x93(\xde@\ -\x96\x1f\xd2D\x0a\x96\x93%\x12E\xa8\xf1D\xef5\xe5\ -\xec)\xd9O\x88\xc9\xe8\x22m\xec\xc4%\x03\xc8t\xee\ -+\x0d7\xac\x05\x1d\xa5\x92Z\xdc\xd14\xafV\x1c\xb5\ -l\x1b\x1a\x85\xe5;\x81\x1b \x11\x18uD\xa1\x82\xeb\ -\xcaC\xe6\x8d\x1dY\xc5\xecukX\xbae\x8d\xcb7\ -\xad~Q\xe3rh\xb9C\xcaL4/\xb1\xe0V\x0a\ -E\xda4\x81#\x00x\x82\x07p\xb3w3\x00`\xd1\ -\xc2\xe7\x0bf\x11 \xc9\xc7{\xe52\xce9\x18\ -\x80\xc0\x1dR\xba(\x10\x88\xb4\xa2\xfcl\x80S\x80\xe1\ -\x96\x93eT\xa2\x97*\xc2^\x05\xa1\xae\x80p\x18\x19\ -\xbd\x83\xdc\x05\xd8\xe8y\xf2!\xfa~l1e\x8b\xcf\ -A\x16\x04f\xe9\x19\xaf\xc4I\xad\x12\xc1de\xcd\x02\ -\x80bH\x94\x0bE\xa5\x14Y\x1fR\x88{*\x87\xc9\ -Vc\x015\x0bw\xac\x1a)S\x09\x94\x06\x08Tf\ -\x8b\x95\xe3\x9e4\xf8YZ~e\xd03yH\x89V\ -\x09E|<\x10\x10\x0a\x00@\x11.\xb3x\x92\x98\xa7\ -%hX\xb3\xbcM\x81f\xcf\xb0\xe0\x5c\xacY\xd7u\ -\xd7\xe6\x1er\x01\xa0\xabA@\x14\x0arP~\x18\xcb\ -\x97\xf2\xc5\xa63\xf9~\x91\xaa\x80\xe6\xf7Q\xb2[g\ -g@\x03\x9aM\xe35\x83\x90\xa4T\xc9\xd5\x0d(n\ -6\xcd\x91?\x93\x81(\xcf\xef\x12q\xd2b\x13 \xe6\ -\xb9%\x99<{&\xd7U\xcdA\x90{q\xec\x19\x0f\ -\xa2\x9c]YL\xfe\xe0\xa6\x95\x8en[\xf9\xd8\xb6\x95\ -\x8emZ\xe1\x90\xc2\x15it+\xdf\xaf\xc5!Y>\ -9z\x0a\x0a\x97\xe2\xf5\xdeM\xaa\x9dO\xa8es\x7f\ -\xdeB\x19\x9e\x91\xf0\x18\xc1#iZZ\xeb0\x01\xa5\ -s\xf2J(X\x99\x89\xe39\x0e\xf0\xc8'\xf2\x0b\xf8\ -\x19\x1b\x85.)_\x9f)\xc4\xf5W`\x9c\xd5x\x8d\ -\x1a\xf8N\xd5\xd2S\xbc\xd5#G\x8as5\xff1\x85\ -\xf2I}\x0bg\x9f\x08\x00OP\xfe\x13\xc8\x8b\x08\x0c\ -\xae\xdc\xc5\x1a\xf2T\x01\x00\xf4\xe70\x18\x1e\xa3\xf7\xe6\ -\xf0e\x91Q\x90VD\xdc.#\x95)\x9f\xbaf\xe5\ -\xd3\xd7Q\x1c\xf1\x98\x8bk.=\x84\xa5\xaa\x94*\x1b\ -T\xba\xd94\xac1\x88\xfb\xff\x04\x82.@ >@\ -&P\x08\x00\xca\xa6N\x08)7\xacj\xee\x96U\xcd\ -\xde\xe2\xe7\x1bVL\xe8q@\x10\x07A\x0a\xb1\xb6\xa2\ -\xf1\xe3OR\xc0\xcfQb\x9d\x9bBu\xca\x87ek\ -\x1d\x01\xc5k\x81\xc7-\xf2\xa0h\xb7\x82\xc9 \xaa\xf4\ -\xcb\xa5v\x9al\x01\x0c\x0e\x18.\xdde\xa05i\xd4\ -\xad\xd4\xef\xc8-\xf7f\x11c\x83R>\x03\xad\xa5i\ -?\x80\xf6\xf3<~\xc7\xa0a\xcf(\xc6\x07\x90\xfc\x9a\ -\xeb\xe7:!H\x9cD\xf5\x90*\x7f\xf35K\xf1S\ -\x96\xa2i[Y>JOE\xe9\xa9\x9aQm\x12\x1f\ -\x80\x10jB\x8dLGs!\x9a\x13\xc9\x19\x80\x14\x0f\ -\x89\xe0\xe2\x81t\x8f\x5cC\x00\xd0\xab\xcb\xc8dL\x1a\ -K\xc6\xfeB\xb2?\x09\xe3\x0c(\xc5a\xc2\x84\xbe<\ -\xbc\x94b\x7f\xc9\xec\x1d\xc7!*0j\xf1\x87\xe2\x99\ -{V$\x91\x81;\xb9O\x08 F\x94\xe2\xbe+H\ -_*\x17!6\xf3\xf7H=nc\x95\xb7\x18`/\ -\x9dSi\x94\xe6\xb75\xeb\x17\x14#gPs\xb8\xf1\ -<\x10\x9b?\xb8Ez\xa22\xb0\x1d\xe2\x97j\x03\xfe\ -w\xc9\x06\xd1\xaa\x11\x90efv\xc9\x22=\xe6\x1b\xec\ -\x5ct1\xafhd\xc7*\xa7\x8e\xacf\xf6\x9a\xd5\xcd\ -\xdf\xc0\xab\x5cw\xc0*\x84\x13\xe4\x0f\x13\x07\x87w\xf1\ -\x06{\x00\xe2\x00`\x1cy2y\x08\x08\xf6\xb8&\xe1\ -\x01N\xa1\xfa\x03-E;\xe5\xb7{\xcaw\xa5_(\ -X\xae4\x0b\xab\x0e)\xae\xf3<.S\x00\xa89\x0c\ -\x94\xe6\xfb\x95\xb2j\xd5/\x87\x98\x18\x1d\xbb\x83{\xbc\ -M\x0a\xa7\x22\x93\xeb\x16\xe4\xf3\x81\x81C\x94\xaf\x15I\ -\x84\xd0\xe6RfB\x85&\xcb4\xff\x9e\xaeU\xb8\x06\ -b\xfa\xb9\xa4jF\x137\xef\xc9\xb9\xf2\xa5x\xd26\ -7\xb1\x06s\xcf \x97w\xe5c\xe2HR.\x8a\xcd\ -V\xcd\x858\x8c\x96\xc85\x0d\xcd\xd8\xb9\xf0\xa5\xbf\xe3\ -\x11\xe4\x15\x5cH\xd5\xff\x08|\xe7\xe2y8\x9e_\x9e\ -\xb6W\x04r\xdb\x85Dq\xa3\xfc\x09\x0c\x09\xbeR\x06\ -\x17(W\xb5\xd7\xec\x19\x9c\xe2\x94\xf4\xf2\x96\xe5O\xaa\ -\x88\xf5\x86\xc5\xe4\x8b\xe8\xe1\xceKfn\xa2x\x88\x03\ -\xaf\xaa\x08\x12\xf1\x8b2HZ\xd0P:'\xc5k\xde\ -_\x8b?\x01\x88\x8d\x8a;\xb3\x18\xecl\x06]u\x7f\ -!,<\xa4<\x17`(\xa5\x0b\xf1P*\x14\xb9\x00\ -\x80\xf3\x00\xce5k\x92g\x8e\xef\x82\xfc\x00\x88\xc2\xc1\ -\xab\xb8\xcf\x1d\xab\x9a\xdc\xb7\xea\xa9\x03\xab\x98\xd8\xb3\xa2\ -\xe1-\xcb\xed\xc7-\xc2\x8as\xfa\xd7\xc8\x1a6\xe0\x1d\ -\xb8\xd9\xa9=\xab\x98\xde\xe3u\xd7J\xc6\xf9\xcc `\ -\xecUX\x81h\x9e\xd7 \xf8\xb5\xd6\xaf\xd54\x06&\ -\x13o\xa5\x8a^Y\xb5H]\x14\xc5j\xb2Gq\xb4\ -P\x0b$\x9a#\x9fy\x80\x90\x12\xce>\xb3b\xcd\x0a\ -\xce>\x86\xe4\xdd'K\x80\xd0\x92I\x84\xc8jB\xe2\ -\x03C0o\xf1\x1b\xbeO\xdf\xebf\x09\xa5P7M\ -.\xb7~\xe1\xe2/\xc4\xb3z\xa7x\x80\xa2\x99UM\ -\xe2\xb8\x096)R\x96-\x05\xa3\xe8 \xca\xcfR\x18\ -\x13\x91\x05\x00\x9a\x07p\xeb\x02x\xaaLy)\xc0\xa6\ -5\x13w=\xe7A\xe4I\xf8nD\xd3\xe8.\xbdT\ -Z\x09\xef\xd0\x8a\xa2V\x16#x\x93\xe8\x88H\xf6\xb1\ -\x95\xe2\xa1+\xf0\xb0\xe52\xae\x19\xbc5^[3\x90\ -\xca\xf2b\x22Xn\x8e\x8a9q\xc5\x85\x13X\x16\xf1\ -\xb8\x08\x0b\x14)SUPXV\xcc\x8d\x04eM\xb0\ -\xda\x80f\xea\x9a\xbd2\xef@\xf3\xa4e\xb6L\xe1\xf6\ -fI\xd7\x16\xf0\x0c\xaa\x00Z\xe5\xf3\x02\x02y;\xca\ -\xbf\xa8\x16\x0a\x09\x9d\xddZ\x1d\xd4J\xa1\x5c'\xa9\x0f\ -\x9f/\x80\xf5\x96\xa1\xf0\x0a\xe2h%J.\x1b\xde\xb0\ -\xfc>\xe2b7\xe4\xa8\x1bv\xdc\xb3Hl\x5c\xc1S\ -\x00\x94I>7\xb5\xe5^K\xc6\xae\xc2G\xb4\xd4:\ -\x8f\x85\xcc\x03\x809\x0f\x5c\xca\xab5\xa9\xa4\x01&l\ -\xb9B\xd2\xa1\x1b\x907\x88-\xa9k\x81X1n\xb1\ -d\x11\xb7Hl,_~i\x15+\xef\x90\xf7ns\ -H\xf9\xd2+x\x10\xa4xF\xeb#\xca\x904\x01\x04\ -\xb9\x85uk\xa2IdK\xdf-\xf7\xad\x18\x9e\xeeV\ -I=\x00\xfcC\xbc8\x9f\x0e\xbf\xf0a,n\xb9\x99\ -\xf1\xd3\xac\xa6j d\xa9Y2\x0c\xdc~\x96S>\ -\x0aGa\x9a;\xd0\xfb \x0a\xd4\x8a\xa0@\xac\x19\xd2\ -\xf4s\x22\xa9p\x92\x5c\xaf\xbd\x14\xe3\xc8\x98\x93\x94\xfa\ -1\x806\x0e\x18 \x95*<\x01\xfcA\xc69\x1b2\ -\xac\x22S\xd5g\x16\xe1=K\xa7\x0e\x9d\x94\xe0=\x0b\ -\xc75\x8f\xa2*\xafm\x8b\x09\xc2\xca\xe5B\xe5JU\ -\xcf\xa78\xa4\x14-\x97\xf8\xaa\xca\x9d\xdf\x03@)\x9d\ -_h#\x7f\xf55N c\xc88`\x98\xc43L\ -;\xab\x0e\x8a\xed\xa3\x00\x91?y\x82\xb0\x5c\x92\x9bP\ -\x22D\xf0]\x02F6\xee,\x9b\xef\x8b0 \x05<\ -l)\x00\xac\x18\xdd\xb5\xca\xd1\x1d\x00\xb0i\x05}+\ -\x96#\xe5w\xc9K\xccA\x92\x16\x085\xcbV<\xba\ -\x86\xe2\x91\xd1U\x88\xe82\x1e\x02\x0f\xd45\xcb\xf5f\ -\x19`\x00\x80G\xf2\x0aR\x96\x08\x05\xb24\xa5F\x9a\ -\x0d;B\x81\xd7\x01\x806p\xdcE\xf9\x0f\xacl\xe5\ -\xb1U\xae\xbf\xb0\xea\x0d\xed\x81\xf8\x02\xf9\xca\xea7\xbe\ -\xb4\xda5\xc0\x001.Q\xce\xaf\x8c\x08/\x10q\xca\ -W\xfeL\xfa(\xe5\x93\xd9h\xdaZK\xe3N\xf9.\ -\xbf\xbf\x08\x03S\x80b\x9a\x1c_S\xda\x0b\xa4\xc0\xe2\ -<\xde\x18g\xf7\xf1\xdcx\xb6\xec\x01\xd2Z\xf2\xfd,\ -8P\x10\xc9$\x94\x06\x00D\x00\xa5y\xfb\x1c\xb4\x9a\ -\xa90\xa1:\x8cYK\xe1\xfb\x93\xeb\xc7\xdd\xd4o\xa2\ -\xa6~\xab\x07\x91\x01KD\x92j\x06-\xa5n\x84{\ -\x98\xe0\x9e\xce\x01\x80'\x16\x00B\x22\x95\xe84\x8f0\ -[0F(e|\xf3y\x1f\xe5w\x9a\x81\xcd\xc4+\ -\xc7x\xb1\x12\xa5\x11\xa3\xc3\x179:\xcaW\xa5\xaf\xdb\ -\xf4!R'\x02\xe5\xd2:\x08\x93sG\xb84-\xd8\ -\xe8\xa2\xa0/\xa3q\x12\xe2\x83W\xd0\x1c\xbe*\x85p\ -q\xaasS\xcd\xa0\x9b\xb8\xe1\xbb\x1cs\x87Q\xe7\x12\ -S\xa3\x90\xaa\x1c\x14\x93\x8b\x85\x16B\xb2J`\xb6e\ -\x90\xba\xf21\x90\xcaM\x16\xe2\xdasU\x05\x8bug\ -w\xce8\x09w\xcf\xc1\x94\xe7\xf9\xdf\x05\xcbE\xf4>\ -\xa4\xaaY,_\x1e (\xcb\x97\xfbg\xd0\xddB\x96\ -\x8b\xb5+\x96\x01\xc9\xf3w\xc9\xd5\x02f\xae\x13U\xc8\ -S,\x5c\x82\x1c\xad=\xb5\x9a\x8d\xd7V\xbf\xf5\xb95\ -l}a\x8d\x9b\x1f\xacn\xed\x8dU.\xc0\x9a\xa7\xef\ -\x91N\x89\x07\x1d\xbb\xa9g\xa5\x94\xae\x80E3z\xca\ -\xebQt*\xd6\x98\x825\xaaH#\x15\x05\xa9,+\ -\x03e\xf9P\x9a\xd62\x82\xb8d\xcd}d\xc3u\xb2\ -\x01uv\xff2\x8c~\x09\x01\x14x\xb5 \x9e.\xc0\ -\xdf\xb4\x0e\xa0B\x18\xa5\xa6i\x0d\x0f\x81\xe4\x15\x11\x0ar\x07\x95\x13\ -k\x105\x98\x80\x0b\xd1k\xa0\x1dO\xd3>\xc5=\xf3\ -\xbec\x06\xd1\xfd{ V\xf5L\x06\x0f\xa5\xb2/\xad\ -\x8cI\x5c\x09\x18\xca\xf03\xc0A\xb9E\x88e.\xcf\ -\xa7\xda\xf82@P\xb5\xfa\xd4\xed\xa8\xa9\xbb\xfa\x0a\xe5\ -\xe3\x114]\xccXs\x02\x11\ -\x94\xab\xc9\x197g\xaf\xf9zrhW\x17@\xa6 \ -\x90\xa8\xd2U\xa5T\xaa\xa7\xcbG\xc1ES\xf7\x5c\x1e\ -Z6G\xca9\xff\x94\xb4\x04\xd1^<\xa4z\xe1\x99\ -\xd5,=?\xcfWq\xcd\xa4\x82\x85\x10\xc2(\xf9\xb4\ -\xea\xe1\xfd\xed\x22:\xb8V\x15:\xe2qT\xe3\xafJ\ -\xd8\x14m\xfel\xc6\xeaTIK\xecK\x03\xc8\xca\xed\ -U\x0a\x9eD\x5cL\xa8\x1bf \x87p\x9d\xc3\x00a\ -\x0cw\x0ap \x8b!\x5co\x14\x90\x17LA|a\ -\xc6\xe5d>\x95\x5cW\x93&\xe5\xe2\x07\x137\x9d\xf7\ -\x0bCb\xb5\x1a\xa9ei\xa5t\x8a\xbbRzb\xf5\ -\x08\x83\x8fEV\xfeCT\x98\x91R\x87\xf5\x036U\ -D\x85\x18\xec\x08\xde/B\x8c\x95W\xcdRyv'\ -\xe0h\x1b\xc63\x0d\x00\xca\x01\xee\x1d\xd0\xf0\x0c\xc9<\ -K\x12\xa14\xb1~\xd4Sz\xcd\x90\xc5U\x0dX,\ -J\x8fE\xe9W\xca{\xecJY\xb7\xc5:\x01\x00\xe5\ -\xb2|mv\x19u\xe9f6\xc0V\xf5\xb6\xdb]\xe4\ -vx\x9d\x91\xe7\x9f\x02\xf2\x9b\x84.M\xf3k)y\ -\x8b\x90\xa2\x0a&-k\xab~\x91\xb1\xd2\xc2\x11\x9e;\ -F\xec9\x0c\x11+P>>w\x13e\xdc\xb5\x86\xb5\ -G\xd6\xba\xf1\xd4:6\x9f[\xfb\xc6sk\xbd\xfa\xcc\ -\x1aV\x89\x99\x90\xa7b\xb1h\x01A\xf3\xe50bW\ -\xf0!\xe9\xe5\xbd\xea\x00T\x11\xe3V\x08!]\xa3\x9a\ -\x17\xe7\x7ff\x1e[\xd9\xc2s\x06\xfa\x95U\xad\xbc\xb6\ -\xea\xd5\xd7V\xc3k\x0d\xaf\xb5\xb8\xdc\xba\xabo\xacv\ -\x9d\xbf\xad>\xb1\xd2\x05\xd5\xcaifO\xeb\xfa\xaa\xef\ -W\xb95\x83\x7f\xb1\xea\xc5\x83'\x12\xf3\x12\xa5\xe0\xfa\ -\x11g1Z\x05K\xc6:\x93\x88\xbdZ\x16\x8d'.\ -\xc6Uuc9\xda\x07\xd8\x85\xc5\xf6\xf2\xc0\xc3\xcec\ -d\xe3vs4\x039y\x02\xfb'\xeb\x01\x04\x92\x12\ -\xd2\xa5\x22\xbc^\x9e&W\xa4|\x14\xa9\x02K\xb9\xf9\ -$\x17{\xa5|\x09\xf7P\xcd\xef\x9c\xe0\xa2k\x95\xee\ -\x09\xa4\xcaB\x94\x95\x90\xcb\xe315\x81\xa6I\xaa\x10\ -^G\x045\xa3e\x84\xb0\xd1k\xc95\x9d\xfc\xbf6\ -\xa7v\xe3\xd6q\xe5N\xfa\x9c\xc4U\xc9\xbdK\xfa-\ -\xb6\x1c\x00H\xca$x\x81\xf2\x01,\x7f\x10\xe5\x8f\xa0\ -|\xc2\x0c\x8aT\xb5\x92\xf6fH\xf1.\xa3\x99#l\ -\x01b\xadu\xe4\xe0\x054y\xa4\x14\xd3\x15\xf7\x92\x81\ -x\x05>\xe2-\xe2,\x18\x12\xa1#F7\x98\x87E\ -\x94\xe2\x12kV\x1fZ\xf3\xd6s\xeb>xkc7\ -\xbe\xb0\xf9;\xdf\xda\xe2\xddom\xf6\xeck\x1b9y\ -o\xad\x00BS\xbe\x8a\x8d\xb9\x90\xaa(9tt\x80\ -\x87\x1d\xe0u\x90\x9f\xb1\xf8\x5c\xa7\xf8\xbbd\x15\x0f\xc8\ -C\x1f\x93s>\xb5\xd2\xf9\x97V\xb9\xfc\xc6\xaa\xd7\xdf\ -Y\xcd\xd5wV\xbb\xf1\x16\xb7\xfb\x86\xf7\x80\x00\xa9\xc6\ -\x05W\xad?\xb3\xf2\x15\xad\xdc\x9d\xc2\xbc\x0f\x88\x91\xeb\ -\x96\x8ekK\x22\xd6&\xd4N\xa0\xd4\x09^'\xb1\xec\ -I\x94?n\x09(Z\x92\xc8\xdf\x93\xc8\xb3\x93H\xb7\ -\x12a\xde\x09Xb\x1c\xae3\xb6\x12\x8b)\xef`\xd0\ -:\x18\xb4n\x06m\x80A\x98\xf0\xbc\xc0\xd0\xa6\xbbF\ ->\xe9P\x01)o\xc1\x946\xbc@\x125\xcb\xa6x\ -\x0f9\x15\x97\x10\xc1\xd3\xba\xbbW}#\x12&\x85\xe3\ -\xaa\xeb\xe7a\xe4*\x07W\x15\x92\xea\x10E\xdc\xe0I\ -\x18@xD\xeb(\x8c\x81\x16m\x00\x81*\x81\x15\x9e\ -\xd2\xb1ro\xb3j\x97%Ttr_]\x08 \x95\ -K\xaf\xecq1=\x1e\xe5\xc7c\xdd\xf1UC\x08\xde\ -\x00e'T\xe1\xcd\x00[b\x8d\xbc\x90\xd6\x144k\ -\xa9l\x02\x0f\xc3\xf8\xe7\xe3\x9d\xdd\xe2\xd4\xfc\x03Wy\ -\xa4\xfa\xbf\xc8\x98\xf6\x1e\xee\xb9I/\xcd\x13\xa8\xeaJ\ -\xd9\x88\x0f\xcbW\x88\x92\xe7\xf0\xb5@\xe4\x91\x98\x5c\xcd\ -\xac\xcd\x9e\x92\x06=\x84\x0c\xbd\xb4\xd6\x83\xf76x\xf3\ -k[z\xfc\x93\x1d\xbe\xfd\x93]{\xff';x\xf5\ -\x07[\xbe\xff\xd1z\xf7_\xe3\xbe\xb9\xc8\x98,\x1c\x91\ -\xc2\x87\x15\x1an\xe3A\xee\x92F\xde\xc7}\x8b=?\ -E\xf1/q\xb1op\xb1\xef\xdd~\xfbZ1l\x88\ -V\xed\xd6{\xab\xd9|mUW\x9f[\x05\xf1\xb7\x5c\ -\xe5Q\xb8\xe0\xe2E\x95N\x9d\x91\x7f\x93o\x93\x85\x88\ -\x11gp\xf3\xa9 7\xb9y\x19R\xb4\xf2;Y\xe4\ -w\xf3\x96DN\x9c\xd4\x04H\xf8\xd9\x09?'\x82\xf0\ -\x04<\x85\xe2g\x02\x16\x95\xc8\xc0&U\xf7C\xd4\x88\ -\x97\xcaVD\x18\xf1\x02\xa1\xa1-\x94\xb5\x87\x9b\xd4\x0a\ -\xa2\xa6W\xbd\xa5`\x15\x9eh\x11K\x03&k\xd1\x9a\ -{\x12\x16\x97T\xa7\xd02\x87\xcb\xd6\x12\xec\x1a\xbcb\ -\x93\xf8\xad\x125\xdd+\xe9\xe1 \xf7\xad\xa5\xf0\x09Y\ -\xa0\x96\x98\xef\xb9ei-\xd8h\x7f\x85\x06?M\xe9\ -\x1b\xcaM\xa8\xe8\xff$\xf1z\xad\x84\xd1W\xc9\xba\x87\ -\xbc\x10s\x0e\xb6\xc4:\x11A-\xf7jQI\xcb\xca\ -\xaaz\xde5\xed-\xd4\x0e\xa5\xa8\x96\xbcU\x84\xa2z\ -\x86\xb9\x07\x16\x9d\xbama,_\xd3\xd5\x9a\xfa\xf6\xb2\ -\x15Ur\xcd\xbb\xeb\xfb\x91\x00\x5c\xe6b]F\xc4?\ -&\x1f7X\xa28\xb8\xfe\xd4\xeav\xb4\xa3\xf4\x0b\x1b\ -8\xfdh+\xcf\xffh\xd7\xbf\xfa\xbb\x9d}\xf3\xcfv\ -\xfd\xc3_m\xe3\xc9\xcf6pD\xae\xbc\xf0\xc0\xb4\x9f\ ->\x8a\xd2\xf3\xc6\xb4A\x94\x9cz\x1a\x17?\xfb\xcc\xca\ -\xe6_\xe0\xea_\xa2\xf4\xb7\xb8\xf3/\xadq\xeb\xa3\xb5\ -\xed\xffh\x1dG?Y\xc7\xf1\x0f\xd6r\xf05\x00\x00\ -\x14\xb0o\xb1\xf0B\x5c\xaf\xae\xafmJ\xd1\x89k \ -\xf7\x18\xe5\x1fX&1\xcd+\xf5f\x80U\xab\xd0\xa3\ -\xbd\x7fG\xa4tG\x0c\xf8!\x8cy\xcf\xd2:\xb6-\ -\xb5}\xc3R\xb0\x86\x148Hr\xeb*\x02Xp\x8d\ -\x02B\xb2\xcb\x9b5\x19\xe3\xe5\xe5J\xd9D\xe4\xb4\x83\ -\xd8\xafy\x02\xd22\xf5\x17P\x9f\x01\x15]\xba\x1a<\ -2\x1e\xada\xa8\x08T\x936\x9a\xb2MQ\xe1E\xc3\ -\x1c\x1eF`[\xb2\x14\x14\x91\xda\xae\xba\xc4=\xee\xed\ -\x00\xe5k\xad@\x1bSnY\x08\x82\x1bA\xf9\xd1\xe9\ -\x87\x96+\x99\xbc\x07!\xc3\x13\xa8@\x86\x10\x99\xa5\x82\ -Rm\x85\x97R\xa5\xdcZ\xac\xba\x86\x10\x82w\x93$\ -\xab_\x02\x22\xc0%\xd6\xcf\x12\xd6\xb8>\x1e&M%\ -\xed*o\xd7~B\xbc\xad\xae\x15\x1e\xbfc9\xba\xd6\ -\xccC\xe4\x81E&\xef\x00\xc0\x1b\xfc\x9d\xb1\x82\x9f]\ -\xd4uj\xf2\xc8\xc7\xf7\xf8y\x0d06JK\x95\xa2\ -\xbb4Q\xf3\x00\x05\xf3*\x14|\x88R\x9eY5\xca\ -i\xd8\xfb\xdczn|\xb4\x85\xa7\xbf\xd9\xd1W\xffb\ -7\xbf\xfd7;\xf9\xe2\x9fm\xfd\xd9\x1fm\xe0\xe4+\ -\xe2\xf8S\xcb\xd3\x83\xa1\xf8\xfc\xa9GV<\xfb\xc4)\ -\xbdr\xe9\xb5U\xae\x90B\xad\xa0\xfc\xb5\x0f\xd6\xb2\xf7\ -\x9d\x0d\xde\xfa\xa3M?\xf8\xab\xcd>\xfa\x9bM=\xf8\ -\x93\xf5\xdd\xfc\x88\x97y\xe5\xea\xe2\xb4)5\x07W\xa5\ -\xd2\xa7l\xd2M\x95*]\x886{\xb8-\xd4\x9a\x85\ -\x1b\xd3\xd4\xec=,\xeb\xa1E\xc6\x1fYh\xf4\x01\x7f\ -\xbb\xcb\xa0\xdf\x02$'\x96\xd1\xb3oi]\x80\xa1\x03\ -0\x90\xf2\xa5\xe2\x8e\xd3T\xba\xad\x12n\x95\xaeu)\ -\x85\xf5D\x9b<55\xec\xe6\xf2\xc9VTN\xae\xbd\ -\x04\xday\x14\xec\xe7\xda\x02\x01\x04W\x9f\xf1\xa9\xe0\x94\ -TR\xde\xc6y\x19\x94\x9f\xd4\xb2b\xc9mW\xb9\xd6\ -\xb6\xa5w\xed\x03\x80C\xf3\xf7\x03LxO&\x16\x19\ -$\xbb\xc9\xd6T2^ Gc\x84\x17\xc8W:\xa9\ -Wy\x06\xc2\xa3v\x1be\xaa\xcbH\x1b\xdf\xd1r\x15\ -`\x12B\x1a\x89\xcf\x0dX9\xc0H\x05l\xc9\x02\x9d\ -S\xfe\x8a\x03y\xba\xf65\x08l\xfd\xc7\x969\x04\xd8\ -\xb4\xb4\x0b\x00B\x5c#\xbe\ -G%}\xae\x88W\x15^J\x89\x19\xe7\x08\xc41\xa6\ -@\xe5\xc90\xe0b\xad7\xe3\x92+\xaf\xbe\xb0\xa6\xfd\ -\xf76t\xfb;[z\xf1'\xbb\xfa\xf6\xaf\xb6\xf6\xea\ -\x9fl\xe6\xc1/\xd6u\x0c\x00V^@4p9\xb3\ -\x8f\xad\x106\xaf\x961\xe5\xcb\xaf\xac\x12B\xa7r+\ -I\xf5\xfa[\xac\xfe#\xff\xf3'\xdbx\xfd\xcf\xb6\xf5\ -\xe6\x9fm\xed\xc5\x9fm\xf4\xec\x1b\xb7\xd7=\x9ft\xcf\ -\xd5\xdeA\xb8T}sQ\x01\x9b\x0dk\xd5\x0e\xda\x88\ -\xd6\xbb\x19\xb8<\xcd\xc8\xa9xs\xf9\x9d\x95\xac|\xb0\ -\xe2\xe5/\xf8\xf9\xbd\xe5\xcd\xbe\x06\xfd\xcf\xb0\xb8\xfb\x0c\ -\xfc-\xf310\xe9x\x0a\x01!\x0d\x85\xab\x9d\x8bW\ -\xb4\xa9%S\xae\xc5g\xa2\xaa\xe1\x93\xe5\xc8U\xf7\xe1\ -e\xb0t\x95D\x09\x00\xf24\xaa\x15pB\xca$\x0b\ -\xca\x808i7Q\x0a\x83\x98\xec\x04\xe5\xb7\xae\x01\xb2\ -MKE!\xe9j\x17\x03\x00|\xdaL*\x10`\x99\ -\x99\xda1Lh\x94\x82\xb4\x9e\x90\x8bK.$.\xab\ -\x12\xa9\x8cL\xa7t\xe1\x85\x15\xc2\x89r\x00q\xf6\xc0\ -\x19q\xfc:`\xc0\x83tr?\xed\xbb\xa4\xb9\x00\x97\ -k\xa4\xa3\xacT\x89v4u\x02\x94\xee}\x80~\x01\ -6\x81@\xd7\xb9\xc5un;\x09\x02\xac\xc0\xd0\x0dw\ -/\x19\xdd\x02\x80X?\xdf%n\x02\x80\x02*\x91g\ -\x5c\xb4/Ben\xe1\xe1k\xa6\xd66Q\xf8CL\ ->\xcc>\x9f\x9bT\xc5\xaa\xa4@3ex\x84\xba\xed\ -\x97\xd6q\xed\x83\xf5\x9e~k}\x84\x84\xee\xeb\xdfX\ -\xd3\xde\x07\xd7\x07\xa7xY=p\x9e\xa3\x14\xdc\xbd\x94\ -N\xfe\x5c\xb1*\x12\xc7\x83\xaa\xf6\x1c \xb5\x01\xa2\xe9\ -{?\xd8:\xa1\xe4\xea\xf3?\xd8\xd2\xa3\xefl\xe0\x18\ -\xa0,\x9e\x12o\xb5|\x89U*?\xd5\xdc\x82\x16\x9c\ -\xb0\xa2\x10\xc4R\x03\x17A\xf9\xb9(\xbf\x88L\xa1l\ -\xf3K\xab\xda\xf9\xcej\xf7\x7fB~\xb6\xea\x9d\x1f\xad\ -l\xe3#\x7f\xfb\x02\x80\xbc\xc6\x02\x1ey\x030p\xcd\ -|\xb8HI\xa0\x1f7\x89\xe2C\xfc>\x07\xef\x91\x07\ -/Qm\xa0\xaa\x7f\x0b\xb4$\x8a\xa5\xaa~_\xeda\ -\x9c\xbb\x94\x90\xba\xb9\xf2s\xbd\xc73dh\xc1\x87\xd4\ -\xd6\xdb[\xe8y\x95t\x066\x1d/\x92\x0e\xc0|\xbd\ -\x84#Dn\xd9/\x10\x10\x0ad\xa1\xb2\xc2L2\xa4\ -,-\xd9\xe2\xe1\x04v\xcd\x9e\xc4\x89\ -,_\xca\x17\xf0\x18h\x1f.8\x83g\xf2i\xfa\x1c\ -\x8e\x11!\xe5,\x22\xc3\xaa#\x9dn?\xfc\x0a.\xf4\ -\x9d\xb5\x1d\xaa\xf9\xd6\xb7VM\xa8,\x9b\x7f\x05\x7fz\ -ne\xf0\xa8\xd2\xf1\xbbV\x84\x82\xf2\xb9/eV\xda\ -\x98\x9a\xd5\x07\xa9C2\x7f\xdf\x9a\x86\xebi?\x82@\ -\x90\x09\xd03y\x95\x07\xf2\x9aY\x09\xd4\xaa\xf7\x83\x08\ -\xba\xf2uO\xf1Ay\x0dH{\xf6\x18a\x08\xf2\x18\ -\x11I\x9d\x06\x00\xa1\x11\x5c\x22\xaeX\xabR\x81\x8by\ -h\x08\x92\x0f\x92\x10\x18\x86\x1cM\x9cX\x04\xa2\x96\x07\ -W(\x80,\x16-#\x22pK\xc46\xe5\xec\xb3d\ -\x02\x93\x00fTK\x99\xaabY\xc7\xba6\xadd\xea\ -\xc0\x9aWnY\xcf\xd6]\xeb\xdd\xbcm\x1dk7\xac\ -zz\xcf\xad\xf0\xb9\x05\x0e\x11\x14M+\x13k\xb5\xba\ -\xe6v\xe5j\xdf<1?2\x05\xb1\x81[\xe4/\xa2\ -4\xc2I\xe5\xce\x17Vw\xfc\xd1\x9an\xfch\xcd7\ -~\xb6\x86\x93\x9f\x00\xc1\xf7V\xbe\xf1\x0d\xf7\xf3\x01\xaf\ -\xf5\x1aK{\x0e/y\x049\x85\x18\x8d\xc0\x19F\xee\ -\x12\xe3\xee\x01\xee\x87\x96\x07\x00\x0a\xe1)%\xa4\xa2\xa5\ -H1\xdf\x9b\x0fyR\x93\x09\xb9\xfd\x0c\x14\x9d\x069\ -Lm#\xcdj\x9d\xc6\xf5k\x7f\xff<\x1cb\xc5-\ -\xca\xb8Z\x02\x11D\x94\x1f\xc4\x05\x07QPP1_\ -B\xfa+\xeb\xd2\x0e!Y\x5c\x86\xbc\x856\xa8\xc0\xb8\ -57\xaf\x86\x0fy#\xdb\xd6\xb4v\xcf\x86\xae\x7f\xb0\ -\x89\xdb\xdf\xdb\xe4\xdd_l\xe4\xf4gk\xdf\xfb\xda\xcd\ -\x89h\xed\xa1B\x93d(\xa5\x14\xeb,&\x84\xe4\xe3\ -\xe2s\x86\x14\xb2T\xca\xa5M;\xd7\xb9\x07\xae\xad\x8c\ -\xc3\x09\x80@\x02x!\x81\xcf/\xaf$\xf7\xcf=\xb8\ -\xfd\x90\x0e\x00Z\xc6\xf6\x88\xa3\xc2F\xa6\xc2\x06\x06\x16\ -\x9a\xbcka\xae%\x12\x19\xe3j\xe54Y\x00\xfa\xb5\ -\x1b'\x95\xdc0\xa5\x19ie0:\x97,];v\ -\x07\x19\x80\xd1\x03\x90s\x8crN\xf8G\x18\xfb\xe41\ -\xeeZJ\x13\x81\xd2\xd2\xa6V\xe0\xc4\xb0\x17x\xe8%\ -\x0b\xa3\xe8\xc2\xe1-+\x1d\xdbA\xb6@\xf6\x86E\xfb\ -\xb1z\xe5\xc4\xca\xb1[\x17\x11m\x0c]\xe6\x7f\xb0\x16\ -\xc8\x97:r\x85A\xa8c\xb7\xa03W\x0b2\x8bO\ -\xac\x04\xafS\xb9\xfd\xc6j\x0f>\xe0\x09\xbe\xb6\x06\xf8\ -E\xdd\xc1\xf7V\xb3\xf3\x83Um~OJ\xf9\x11\xe2\ -\x09?Y\xc6\xc5.\xa0\xe4\xd9\x97V\x04G\xc8\x9f\x84\ -\xb0\x92\x92\x16\xcc\xbe@\xe9*\x03\x7f\x0b\xcf\x11\x9fx\ -E\xea\xf4\x18\xaeq\x8b\xc1\xd9\xc5\xb5+\xd6\x93\xf3k\ -V\xee|\xdf}z\xcb\x04\xf1s\x0e\x0f\xa5\x85\x1c\xd5\ -\x14\x10\xaa\xe0*\x1e\x00P\x86b\xbd\x06\xd4\x81@^\ -@\xec\x1b\x97\x0d\xf9J%\x0bq\xb5\x00\xa4\xa3\x19\x8d\ -\xe3\x16\xe9Z\xb0\x86\xf9c\x1b9|j\xd3\xa7\xefm\ -\xee\xee76y\xfb[\xeb\xd8\x03\xdc\xcbxXrx\ -\x95\x7f\x97\xc0}\x8aa\xf2\x85x\xc2\x06C\xa2\xcd\x15a^s&\x89\x8b\xb3\xb7\ -\xc9T\x1eX\x05|\xa4\x9eT\xb5\xed\xe4{\xeb\xbc\xf9\ -\xab\xf5\x9c\x92^\x22\xbd\xbc\x1f:\xfd\xc5\xc6o\xffj\ -\xa3\xbc\x8e\xde\xfa\xc5\xa6\xef\xfcf\xe3g\xa4\xaf\xd7\x7f\ -F~\xb2\x9ek\xda\x0a\xff\x05<\x86\x10\xa0\xcd\xb0|\ -\xb7\xbf\x7f\x13\x00h\xbf\xdd\x88%VkF\xae\xcd\x12\ -*[-\x09 \x08\x04\xea8\xe6*\x8c\xc8\xab\x95>\ -jS\x85\xfa\x15\xb8\x12z\x14\xef\x94\x8fb\x02\xdc\xbb\ -\xebe@\xb8\x10o\xf0\xb9\xa9\xe4yR\xbb)\x0b4\ -MZq\xff\xb25\xcf\xeeZ\xe7\xca\x91\xf5\x5c\xbda\ -]WO\xadzNet\xbbn\xb5N\xcb\xe6\xd9\x84\ -\x1b\xcdB\x06\x01Q\xa6\x96\xb2!r\xda\xb3!\xee\xe1\ -\xb6\xc7\xf3\xfd>@\x98\x01\x18\xdd\xe6X\xa5\xbd-j\ -QC\xca\xda\x8c\xf2[\x18\xd3V\x94\xdf\xa6P\x84\xd2\ -\x01\x80\x9b/\xc1;\xa4\xc2KR\xf9\xbf4B}\x06\ -\xd7\xf2i\xaeep\x17\x00\x10\xe7\xd4E\x22\x9dAH\ -S\x87\xad&\xdc\x7f\xe34\xaep\xda\x12\x9d\xcc8I\ -\x16\xa2\xf5@\x9a!k!^:\xc5\x03\x02D\xe9\x92\ -\xbaeh\x7f\x9e\x1a\x1e\xb9:6-\x1d\xab\xf2\xc5\x11\ -=\x5c<\x03\xa78\xea\xedC\x00}\x221\x9aD\x11\ -C\xc5E\x05A\xbd\x98\xb3z\xf5\x84\xc6!\xa4\xe2\x1e\ -\x13\xa4+\x93Z\xc7\xc7J\xe6\xeeX)\xd9I\x8d\xc8\ -\xd4\xf1\x176r\xf7'\x9b~\xf2'\x9b\x7f\xfeO6\ -\xf7\x04E\xdf\xfd\x1e\xe5\x7fkSw\xbe\xb5\xf1\xd3\xaf\ -m\x82\xece\xe9\xe1\xcf6\x7f\xef'\x1b\xbd\xf9\xd1F\ -n~k\x83\xd7\xbf\xb6\xc6m\x88\xe0\xf2\x03x\x01\x84\ -hD\x939\x022\xc0\xaf\xd3L\x5c\x97\xc5\x97\xb78\ -I\xacl\xb7d\x00\x91\xa2\xae\xa7n\xc3\xaa\xf6\xdd\x01\ -d=\x93f\x0b\xe1\x0e^\xbb:)\x9fl@\x1e\x00\ -\x0b\x0bh\xf1E\xd3\xbf\xbdd\x14\x10\xc9\x8c\xd6y\xf3\ -3\xae\xd1\xaey+\x1d\x5c\xb1\x8a\x91\x15\xbc\xc1\x9a\x95\ -\x8d\xaa\x10\x94\xef#\xd4\xaaa\x85V\x1a]\xc1G\x9d\ -\x96\x805\x0b\xa8\x95A-\x0b3\xce\x18T*\xe3\x9a\ -J\x86\x92\x0a\xb8R\x19\xd3T\xa5\xa9\x00 \x9dT1\ -]\x16\xdf\xa6\xf0#\xc5\x13\xd2\x9c\xa0|B\x81&\xad\ -4G\x92\xc6\xff\xa7AL\xd3{%\x18}\x1fY\x0e\ -\x12\xe3\xebY\x858\xe0\x86\x89\xdb>\xe2\xb3\xeb\xb5\xc7\ -\x83\xca\xc2SPr\xf2\xf9DHr\xa3\xa6$\xb58\ -\xa3\xc6\x8eR\xfe\xcay\xae\xea\xddH\x86,\x1b\x94i\ -\xe3\xa6\x8a\x18/\xc4U\xb5\x92\xee\xa9\x9a&\x82{\xd7\ -\x0eZ\xd5\xdbGx\xd5\xbc\xf9\xa7\xee\x9f\xaa\xba\x1d\x82\ -h\xa1\x94,\x08eh\x0cR9\xb6\xcf\xe7\x0eH\x97\ -\x8eL\xbbm\xd4\xe2\xac\xee\xea#\x1b\xb8\xf1\xc1V\x9e\ -\xffjG_\xfd\xddn|\xfcW;\xfa\xe2/\xb6\xf2\ -\xe4[\x9b\xb9\xf3\xd6\xc6o<\xb7\xc1\xc3\xc76L\xbc\ -\x9d=}g\xd37\xdf\xda\xd0\xe1K\x1b:zi}\ -\x07x\x8f5\x98\xf6\xec\x09\xdf\xa9\xf4\x93\xf0\xd5>\x0d\ -\xe8\xd5h\xa1\x0f\x00tZB\x05\x1e\xa0\xbc\x95\xd7v\ -@\xa0p\xa0\xde<\x02\xc18\x166\x03\xc8\x09i=\ -\xeb\xfc/\x80\xd6b\x0b\xcf\xa5\xb4\xcf/\x0f\xc0\xcf^\ -{\x1b\x00\x80g\x11\x99\xd6zF:\x9cJ]S\x03\ -\x84\x14\x7f\xd3\xa8\xf9\x1bG\xcc\xa7N\xa6|o\x92\x9b\ -\x02\x1e\xc4\xeb\x0cZ|\xc5\x80\xc5],\x02\x95k\x19\ -x\xc8\x12j\xf0\xc8\xf5\x18\xa2\xa6\xbd1\xb6$\x8cM\ -\xb3\x9e\x9a\x01M#\xc7\xcf\x10\x07\xe8\xda\x87\xc8z\x92\ -\xde\xa9Y\xd2\x1d\xf4\xb2\xe9\xe6,RP\xbe\x00\x93\xa6\ -0\xdf\xbdJ\x0a\x0b\xd7\x03\xf4\x92\x0c\xde\xc7\xb8V\xab\ -\x17B8P\x91\xa2\x10\xae\xc5\x0d}\xb9\xa6!SZ\ -\xd7\xdd\x1c|j\xb3\x17\xb7\xd3P~\x1a7!\xc5{\ -92\xa8r\x00P\xca\xc4\xff\x7fR>.\x0d\x8e\xa1\ -\x9c_\xe5\xcbZ\x9e\xd4nU\x89\xdb\x8a\x8d\xc5\xab\x16\ -N\x9b4\xfc\xa0\xd1\x07q\xf4C\x14%\x81\x81U\x06\ -w\x1d\x80h\x0d\x7f\x8b\xb4m\xcf\x8ag\x8e\xaca\xfd\ -\xb6M\x9e\xbd\xb5\xa3\xcf\x7f\xb5g\x7f\xf87{\xfb\x97\ -\xff\xd3\x1e\xff\xf4\x17\xdb}\xfe\x85\xcd\xdd|h\x03;\ -\xd7\xac}e\xcf:V\x0elx\xe7\xa6\x0dn\xdf\xb4\ -\xce\xd5\x13\xeb\x5c\xe3\xf7H\xe5\xcc\x8e\xe5\x0d\xafBR\ -\xc5K\xa6\xb0<-\x19\xf7\xa1h\xad\xb1w!\x1d(\ -\xa3\x03\xe5w\xba\x9f\x93\xf0\x02j8\x99R7L\x5c\ -\x1f\xc7bg\xf0n\x8b<\x1b\xbc\xa0\x0f\xb0+{\x92\ -\xdb\xefE\x11\xb2z\x9e\xc3\xafLG\x03\x0c\xf9Ko\ -S5\xb0\xa6x\x15b\x06\x00V/\x00\xebF\xba<\ -)\xeb\xb6\xc42~\x87\xc4KJ{,N\xe2\x96~\ -\xfb\x09I\x1e\x08\x12\xea\x00A#\x86\x88\x0e\x92[\xd6\ -\xd0\x09\xe3\x8eu+\xc6gh\xa2\x08\xb2\xa7I\xa0t\ -\xb8T:Y\x95\xf3\x14\xe8 \x0d\x02\x9b\xaeu\x15g\ -\xf1\x00\xbe\x17\xaf\xa4{S\xe9:\x82\x07\xe0\x86\xc9W\ -\x03}rk\xb0}\xdcX61M\xb3hJ\x1f\xfc\ -\xa4\x19n\xee]\x17s\xeeFn\xc7\x13\x17\x83\x1c\x08\ -@\x17.\xc9\xa7\x18)\xf7\xffI\xf9W\x11^\x19(\ -\xcd;\x87\x86v]AF\x88\xb8\x97\xad]\xb1\x03\xba\ -.\x83\xd5\x0d1\xec\x9c\xc3M\xcd\x22\xb8\xc3\xae\x19n\ -n\x96kC\xc0PTv\xff\x12\x8cx\xd5\x0a\xc77\ -\xac~\xf9\xd0\xa6n>\xb6\x9b\x9f\x7f\xb4\xf7\x7f\xfa\x9b\ -}\xfb\xb7\x7f\xb6\xd7?\xfdj\x07O^\xd8\xc4\xde\x89\ -\xb5\xcc.[\xf9\xe0\xa4\x95\x0dLZ\xfd\xf8\xbc\xd5\x8d\ -\xcd[\xc5\xd0\xb4U\x0c\xcf\xe2~\xe7,\xafw\xc2\xb2\ -\xda\x87-\xd0:\x08C\xef\xb3\x94\xdan\x94\x8f\xe2\x89\ -\xf9\xff\x9b\x08\x0c\xbc&U\xf3\xf7\xea^\x148`\xa9\ -\xf0\x04\xb7\xa0\xe4\xb2\x03<\x01\x16\x15P\xda\xac\xcd&\ -p\x1c\x91I5\xb7Hk\xc3\xab\xb4N`4c\x84\ -S\xbcK=\x96^\xa3E\x1f8\x06J\x8f/\xebD\ -\xd1\x1dN\x12\xd5\xb7\xb8\x14 \xf1%\x9e\xc4\x95v\ -\x9f\x83\xa0\x0f\xaf\xa0E-\x15\x88(,/\xf2\x9d\xea\ -\x89\x80.p\xf3\xbeN\xf5s \xec\x90\xef\xfbd\xb0\ -x\xdft\x8c8\x95\xac&\x19o\x9e\x02P\xd3Pr\ -:J\xf7\x8c\x0b\x03G<\x80\xf2;\x95\x84\xa5\xa30\ -\xcd\x82\xa9\xe5\xaa6>\x84 a\x11\xcd\xc6iN{\ -\xf46i\x1e\xa9R\xff5<\x04\x17Q\x9e\xdb)\x86\ -\xb9\xc1\x0d\x00\x86s\xe5K4u\xfaI\xf9R\xba\x13\ -M\x86\x88A#\xbcfq\xe1 n7\xd8G~M\ -\xfcS/\xbb\x8cN\xf2\xee\xb6q\x1el\x98P3h\ -I\x8d\x03p\x8e~\xf7\x9a\xc2\xcfi-C\xc4Q\xad\ -\xe5\x8fZ\xb8g\xc2\xca\xc6\x97lp\xe7\xc4\xf6\x9e\xbc\ -\xb4g\x1f\x7f\xb0\xf7?\xffj\x8f\xbf\xfc\xda6\xce\xee\ -Y\xf7\xd2\xba\x15v\x0dY\xa0\xb6\xcd2\xaa\x9a,P\ -\xd3l~\xc4W\xddd>\xbd\xafk\xb5\x8c\x9a\x16K\ -\xadF\xaaZ-\x19\xc2\x97\x88\xcbO\xc4\xdd;\xabw\ -\x1e\x00\x8bD\xe9\x89Ux\x04\xac_\xcaO\xaa&\x0c\ -\xd4\xaa\xdb\xe8\x08\xa4P^`\x0a\x82;C\xb8$\xd7\ -oS!\x8a\xac\x5c\x04\x9a4\x92\xcf%\x126\x12\xf8\ -\x0e\xd5\x22$\xc8\x93\xa8_1\xd7\x88/kC\xe9\xad\ -(\x19\x9eQ\xdc\xec^\x13J\x087%\xfc\xbe\xb8\xdd\ -\xe2\x90\xd8\xe2\x0e\x8b-\xe9\xb4X\x81\x80P\xa0e\xe1\ -\xc4\x1a\xbe[\xeb\x04\xeaQ\x80{\x0ft\x8b;\xc1\xa3\ -\xfa$\x10Q\xcdDb\xf5\xda\xf5\x94J\xb6\x95\xdc6\ -e\x89-c\x84\x8cQB\x05\xfc\x05\xa3\xca\xe8&\x0b\ -\xeb\x85\x98\x93\xd6\xfb\xc5\x01\x00\xae&\xbfbD0\xd2\ -5\xe3\x85\xdbWK\x12\x15O\xe6\x90#F'\xef\xf3\ -\x0aS\x1e\xbb\x039\xf3@\xa0\x99.\xbf\x9bi\xf2\xa6\ -\x1a\xddvr\xdc\xbfS>$\xc3+u\xf6f\xc0\x9c\ -\xf2Q|&\x08\xd4\xfc\x80\x96a}XxF\xc74\ -\xc0\xe1\xa6\xda\xb0\x8e\x16\x94.\x85\xd7\xe3\xfajA\x7f\ -u\x87\xc5U1\x10U\x0c\x88\xd88\xaf\x92\xc4\xeav\ -,\xa8\xc3\xd2\xea\xbb,\xd29l\x8d3\xab6up\ -\xd3\xf6\x1f\xbe\xb0\x9b/\xde\xda\xfe\x83\xa76\xb9sl\ -\xf5c3\x96\xdd\xd0a\xc9\xa55\x96PX\x89TX\ -BQ\x85%\x16WZbI\x95%\x95T[Ri\ --\x16W\x8f4\xe2v\x9b\x11\x14P.\x00\xa0,)\ -\xbf\xaa\x97\xeb\x89\x0f\xf4\xf3\xca\xbd\xd5H\xa1X\xb0Z\ -\xdc\xd7\x8d\x90\xdf_\x08\x83\x8b\xe8w\xea\xd6\x95X}\ -a\xe1<\x03J\x8e+iB\x99\x0d(\xb5\xde\x93\xa2\ -Z\x8b-\xfc\xbd\xd4\xf1\xbb\x06@\xd0\xe4\x01\x02\x10\xc4\ -\x95\xf0\xec%\x00\x00o\x10K8\x88\x85\x13\xc4\xab\x00\ -\xa5N\xbb\x7f!\xda0z\x11\xe70\xfa\xd0V\xf5\x1c\ -$b}?9v\ -\xcf\x88E[{p\xf7M\x96\x5c&%\xcb\xea+\xb0\ -xI%V\x8f\xf5\xe3\x15\x12KQ>\xd6\x1f_\x8a\ -\xf2\x1d\xb8\x00\x9d,\x16\x00\xc4\xf1\xbd\xf1\x0e\x00\x03X\ -\xbb,\x9bA\xc2\xed&7\x92\x05A\xbe\x12Uqt\ -^r\xa6\x92\xb4\x04<\x83\x0aNd\xf5\x22u\xbf\x07\ -\xc0\x95b\x0f\x00\x97\x0b\xaa\xecr^9R\x8a\xe2\x8b\ -\x9d\x5c\x91\xf0sl~\x19\x00\xa8\xc4;\xd4\xf2?\x8d\ -\x0e\xe4q\xfc\x7f,\x1c!\xb6\x12\xf2'\xf05`\xf9\ -\x90m\x91;\x15\x9c\x84\xd1Kt\x1a\xe5\xcf=r\x92\ -;\x03\x00 \xd4\xda\xe5\x9c\x81\xebOi\x1cu\xe3\x19\ -[\xd1lWx\xd6+x=I,^/\xae\x82g\ -\x16\xc1%\xa4%\xd4\x00\x12\x95\xcd\x01\xe2\x98\xd8rb\ -]\x8d\x0a'U\xa5JzC>\x1b\x1eU\xaav\xd7\ -\xa2\x84\x00\xb7\x99p\xf2\x11i\xd8\x13+\x98~\xea$\ -\x7fJ\xa7\x8b\ - (\x00\x04\x85x\x81b@PnW\x8a\xf0\x14\x84\ -\x89+\x80\xf2\x0a\xdf\x15+`\x01\xb4\x94\xd6\x05G\xec\ -4\x03\x18\x998\xb3\xe8\x0c\xfa\x98G\x1fH\xee\xac\x0a\ -BH\xa3!\xd5\x01\xd29\xb5\x86M\xaeW\xd6\xd0\x86\ -\xc2\x1b\xf8\xbej\xbbL\x08\xbc\x5c\x00\x00y\xd55b\ -\xb9F,\xdeF\xcf\x1d\xab\xe7\xe6~cbE@\x18\ -\x5cU\xbdj\x0aS)\x8d\xb6FG\xc6@\x9b\xbah\ -M=\xb4\x02m\x9d\x9aWO\xe1W\xc8k+\xd6\x89\ -\x1a\xb3\xcf\x1c8\xd4A#t\xbe\xc6\xeez\xf4ha\ -\xa7[\x8a\xd6\x19\x02\xc7\xae\xfc\xbb|\xf2\xaeU\x81\xd6\ -\xca\x99\xdbV:qby\x83x\x1aBCF\x8b\xa6\ -\x9e\xe5f\xe5n\x89\xa3\xff\x9b\xc8\x0d+\xb6\xca\xd5\xe2\ --\xb0\x8a\x84\x0a@\x82\x8bt\x0c\x9a\x81\x8e\xc7\xd5\xc6\ -\x13O\xe3p\xb3\xb1XZ\x5cA\x19q\xb5\x9c\xbfa\ -\xf5R|e\x1dd\xaf\x1e\xd2Wo)\xd5\x80\x04b\ -\x98XI8q\xa1\xa6\xcd.3\x10\x97$\xb8\xdf\xcf\ -\x90\xcbR$\xd6\xa1vu*\xa7rM\xa9\x00\xb0\xda\ -\xd3\xa5\x91V%\xb5.\xe2\x05T\xa38\x82\xd7\xd2`\ -\xff\x8e\xd5\x0b\x00r\xe1|OlI\xb3]\xc6\xb5_\ -f\xd0/\xa1\x00\x07\x80\xdcB@\x90\x87\xe4\x02\x82(\ -\xde\x80\xd7\xbc|\xbb\x9c\x8fg\x90\xa2t\xa2\x09\xca\x11\ -\x00\xe2\xc4=\x00Z\xaa\xa6\xd6\x95F+}V\xa3\xa7\ -i<\xb3j\xfeP|h\xfc\x10`\x90\xae\xf7h\xce\ -F\xc6$#\xc2\x03a\x0cWJt2\x0a\xd6\x8f\x87\ -\xb9\x5c \x10\x10\x86\x0a\x01\x99;1\x05\xa0)D!\ -\x97\x8b\x9a\x00@\xb1\xe2\xa0R!\xf2\x5c\x15\x0d\x12\xcb\ -\xb5\xe0\xa0\xa5Ym\x94\xcc#\xde\x14\xcc=\xb6\xe2\xc5\ -\xe7V\xba\xa2\x05\x15\x00\xb0\x04\x00\xe6_\x10\x8b\x1e\xe1\ --\xce\x08\x07\xd7a\xa3\x87X\xfd\x9ee#\x11\xde\xe7\ -\xf1\xbb\x12\xf8C\xf5\xec\x13k]{m}\xbb\x9f\xdb\ -\xe0\xfe{\xeb\xdd~n-\xeac?\xbek!\x11\x92\ -&n\xde\x91)\x89\xb7\xdd\xc9\x131j\x84\xfbr@\ -\xa8\x04\x04b\xc5b\xc7\x90\xa5\xd8\x22\x90\x5c\x00\xa2\xf3\ -x\xb0\x5c\x01\xa0\x02\x00T\xe1R\x89\xabeX{e\ -\x03Jo\xb2\x94\x9aFK\xadmB\x9a-Y\xf1\x10\ -\x8f!\xbe\x11\x8b\xd5_Fi\x97\xce\xe53\xbd\xa2\xcc\ -81\xfe\x86Q\x88\xea\x1c\x83\x8f\xb7\xea\xdf\x22\x85\xda\ -v\xf9tr\xfb\x0a^@\xc5\xa7\xe7^\x00\x0e\x10\x8f\ -\xa7\x8a/\xfb\x07\x08\x14Vbq\xe7Wp\xebR\xea\ -%\x94\xe0\xbc\x00\xae\xff\x12\x1e\xc0\x03A\xd4\x13@p\ -\x09O\xe0\xfe^P\x03h\x00\x00\xdf\xa5\xb2\xf0\xc4z\ -\x11e\x98\xbb&\x9d\xb4\xc1cT\x9eY\xdd[4o\ -\x02\xf1&uN\x85\xed'\x13\xd7\x13\xe0E\xf1z\xae\ -\xf2\x06\xc0Ws\xae|\x89\x94.\xd1\xef\xea\x183)\ -\x1f\xef\xe08\x8a'1n\x22\xa2B\x8d\x88\xd5u\x1a\ -\x96\xc8C\x0a\xf9\xd9\x83*h\xb8\xe1\xaaF\xf2\xb5\x95\ -X\xe7\xe1,=\xb3\x22\xa4p\xe1\x19\xbf{\xc2\xdf\x1e\ -pS\xe2\x04j\x0c\x01w\x18<\xb1\x5c8D\x11D\ -\xa5\x1c\x82R;\xff\xd4Z\xd6\xde\xda\xf0\xe1G[\xba\ -\xfb\xabm>\xf9\xcd\xd6\x1f\xfc`3\xd7\xdfX\xc7\xea\ --+\x1a\x22\x05\xc5\x0bh\x7f\x9b\xd6 R\xe4\xf6\xb4\ -\xdb\xc6\xc9\xf9\xfe7\xac\xcd\xb1l\xcd\x96\xc9\x03\x08\x00\ -J\x97\x0a\x01@\xbe\x00\x00\xa3F\xe2\x0a\xea<\x8f\x80\ -\x15%h*\xb7\xaa\x85\xffk\xe1\xff\x9b-\xa5\x0e\xa9\ -\xe7}\x1d\x19E\x0d\x8c\x1f\xbe\x11G\x18\xb9\x82\xfb\xbe\ -LH\xb9Lh\xb9\xa4Wm\xbc\xc0\xfd&\xd5+\xfd\ -$\xdd\xeb\xc2 4i\x02\x10\xd2PDJ\xa7j\x0f\ -U\xa4:\x0f\xa9\x22\xd5\x02\xa0\x09\xdc\x97<\xa8\xf3L\ -\x02@)V\x08\xb9t\xae\x16\xb2y\xc5\x9dU\x04\x17\ -\x90+\xce\x87\x0b\xe4\x15a\xfd\x00!\x17 \xe4\xe6;\ -`|\x06x?\x03\xcc\x97\x8aZ\xed2\xcf'\xf6\x9f\ -\xc0w\xa7@\xd6\x14\xdb\x03\xdc\x83\x0aY3yU\xa9\ -|:d:\x19\xa6\x9fX\xcbu\xaby\x16b~l\ -\x99\x94\xcfX(\x9cp=\x11Le\x1a\xb1(<\x96\ -\x90$n\x22\xef\xe4\xdd\x9f\x84{%\xe3\x88I\x22\xcf\ -T\xd7ImgV\x17J\xf5\xa2S'\x0d5A\xc8\ -V\xf3\x85\xb1\x13\xdc\xcf\x0d\x08\xc7-\xcb\x9b\xc5#\x10\ -{rU{>\x0dA\x9c\x84\x14j\xf9\x16\x85\xe7\x8d\ -y\xbb\x7f\xca\xa6\xb1\xfa\xf9\x87\xd6\xb0\xfc\xdc\x9a\xd7P\ -\xf4\xd6\x07\x9b\xb8\xf9\xa3m?\xff\x8b\xdd\xf8\xfc\xefv\ -\xf2\xf6\xcf\xb6\xf9\xf0\x1b\x1b\xde}`\x15c\xdb\xee\xa0\ -)\xedm\x93\xa2SP\xb8\x07\x82\x7f\x88@\x90\x04Q\ -U\xc5l\x82\xd2\xa22,\x8e\x1b\x8fc\xb0\xe2\x00A\ -\x1c(\x8e\xc7\x95%`=\x09\x0c|\x02\x16\xe8\xa6s\ -+[\xcfA\xe0)?\xb5\xb1\xdd\xd2\x1a\xbbyOn\ -\xef\x06\xae\xef|\xf3\x85^\xfb=\xe1\xbd\xb6])\x87\ -O\xe2s)-\xe4\xfe\xed\xe3n\x82*\x15\x12+\x00\ -\xa4\x90\xf6\xa6\xb4\x03\x04M\xcb\x8a\x18\xd6Nb}\xc3\ -X_/\xd6\xaf\xfc]\x83\xab\x81\xd6\x80\x0b\x04M\xc4\ -c\x85\x03H!\xd6x\x09w\xec\xf1\x82R\x84W\xc2\ -\xd7g\x80\xf7\xb3B\x94_\xdcM\x18\xd0\x9e\x80!\xc2\ -\x0b)\xb2\xc6D'\xaf\xa9\xeb8\x80\xcc\xd0\xb9\x01d\ -P\xa9dOIdN\x09\xca\x9c\x5c\xc6D\xca\x09\xd8\ -b\xc9pb\x8b\xa4\xf8\x1a\xc6Ei&\xe4R\x1e^\ -!S\xb3\x8e\xf2V<\xa3\x17N5+9`1)\ -0\xcd\xd4\xc6y\xdc\xbf\xb6Uii\xd6\xab\x84QK\ -\x15mZ\x0c\x0e\x10\xd3\x87\xf0\x08#\xb8\xecQ\x01\x82\ -Td\x1ck\x9f\xb8I\xa6 \xb2\xa8](\xda\x83~\ -\xd7\xea\x96\x1fY\xd3\xda3k\xdf|e\x9d\xdb\xef\xac\ -m\xf3\x9d\xb5\x22C\xd7\xbe\xb1\xd5G\xbf\xd8\xe1\x9b?\ -\xdb\xc1\xab_m\xe3\xe1W6\xbc'\x00l\xb9\x1d\xc6\ -)Xx2qO]\xb0u\xa6\xcf?\x80 O\xa0\ -\x85\x9a\x09\x14\x09\x10\xaa\x00\x82f\xc6\xdc\x94)\xae\xd2\ -\xe5\xcdp\x18$\x01R\xa3,\xc1\x09\xac^S\xbaI\ -\xc4\xc4\xe4Z)\xbe\x93\x01\xecE\x06\x18\xccA\xbc\x0d\ -\xbc\xa2\x16\xcb\x85_\xc4\x13^\x12H\xf9$\xaa\xc9\xd7\ -\xf6+\x97\x8a\xc2\x9ac\x95F\x91B%4\x0dYR\ -\xdb\xac%u\xaeZ2ioJ\xd76`\xd8\xb2\xe4\ -\xb6uR\xa9E\xacu\x12\xe0\x0c\xa1\x08\xfe\xd7\x85\x01\ -\xee\x8b\x10\x13/!\xabQ\xa6\xa1\x90s\x05p^\x01\ -\x18\x97\x1dI\x14(p\xc3\xc5\x0a\x17\x9d\xfcM\x9b?\ -\xe0\x16\x15\xe3\xe7\x82w!\x15T\xe8K\x82\x1c'C\ -zS\xaa\xda\xe15\xad\x90Y\x00\x8f\xc5\xc7\x97\xa1\xe0\ -2Y?\x02\xd8\x048\xcd?\xb8I&\x1d\x8d\x87\xa1\ -$pO*?\xffG\xc99\x9c\xcb\x95\x9dk\xbf\xc3\ -\xa4\xc5\xe8\x8c>\xd7\xf0\xb8C\xdb\x91\xc9\xe9\x95\xd7\x93\ -\xcai]@\xd5AN\xb4N\xa0\xdd\xa4}\x9b\xc4\xa3\ -\x1d\xf8\xc1!\xa9\xe2uB\x00\x96\xaf\xc2\xc7\x99\xbb\xae\ -QT+\x8a\xef\xd8~k\xdd{\x9f;i\xdexm\ -\xb5+\xcf\xacc\xe7\xb5M\xde\xfc\xc2\xd6\x1e~D\xbe\ -\xb6\x85\xb37\xaeJ\xa8l\x84\xeb\x80\xee\x14\x08U\x12\ -\x84*\x09\x8bt@8\x07\x81\x9a-\xb8\xce\x1aHJ\ -\xfd4\xe0 \xe6q\xf3\xf2Z\x0e\xc1\xb8nG\xc2P\ -zBE\x977PX\xb66`\xe8\xcc\xc0\xd4\xfa^\ -Kk\xe8%\xcc\xf4\x9b\xbfu\xc8|\xad:yc\x04\ -\xc0kzV\x16\x06\xbfP\x88Q\xf3e\xf1\x0d\x00!\ -V\xef\x91\xb8\x1a\xbbT\x02\x93&\xae^\x91\x9b%\xc5\ -J &'unXJ\xcf\xae\xa5@\x0cS!\xbb\ -)\xedW!\x86\x0b\x16\xc7}\xc52\xd0.\x8d\xe3~\ -\xe2\x091n6\x91\x0c\xc7\x11Zq\x06\xf8\x8c\x00\x17\ -\xa7\xb0\x81b\xe3+\x95J\x0a|J-g\xf0:\x84\ -\x96z\xd2\xce\xbay~7\x8d\xa5\x8e\xf1\x8c<'\xbc\ -@\xde-\x11v\x9f\x88\x9bO\xe0\xbe\xe2\xc5uJ\xb0\ -r)\x1dB+\x90\xb9\xcd&.%U\xb6\xd4\x8b!\ -\xc0%\x04\x22\x19N5\x06t^r\x9eT\xaf\xfd\x06\ -s\x90\xddE\x8b\xc9h\xdf\xf0\xd2\x1dP\xad\x22\x83\x80\ -\x13\x01A\x877\xae!\xaa\x8f\xf3j\xe4\xb4\xd9\xc05\ -\x22\x22\xad\xd3\xd6\xa3<-\xd3b\xf9e\x8b\x8f\xac\x11\ -\xe5w\x1d|\xb0\x9e\xc3/\x9dt\xee\xbd\xb7\xda\xd5g\ -\xaeKU\xd5\xc2]k]\x7f`}{Ol`\xff\ -\xb1\xf5l\xdf\xb5\x86\x85#\xcb\xef\xc7\xe30\xb0\xc9(\ -\xdf\xb3^\x06\xcdm\xe4\xd0aO\x9aiS\xa3\x05<\ -\x94+\x97>\x97zrc\xe5\xe8n\x83\xa6\x08\x22\x0f\ -\x89\xd25\xd7\xee\x1d\x0e5d\xe9\x0dC\x96A\x8c\xcc\ -\xc0]f`\xf1\xbe\x96!\x000j\xfe6\xed\xa2\x1d\ -\x83x\x0a\x5c\xe7 P\xf8\x81p\xba0$E\x89\xd9\ -c\xa5r\xa7b\xf1\x97\x19\xe4\xcb\x15XiM\xaf]\ -i\x1c\xb782\x81\x04\xd2\xe5$\xc6(\xa5\x8b\xf4\x10\ -@h\x95.\x81A\x8d\xc7\xc2D\xe0\x94!hJX\ -\xe7\x15\xb9\xc3#Zf\x11M\xe5\xaai\xd4<\x03\xcf\ -38Pk\x09x\xce\xad\xae\xa6\x91fju/M\ -k\xf7\xadW!w\xcb\x80b\x16\xe5\x01<\x94\xa9\xd0\ -\x96\x08\xb1L\x90\xe2I\xf1$q%\x9a\xd3\xd0\xf2\xb5\ -\x94\xcf}kb\xca\xad,\xe2\xd5\x90\xc4J\x14/\xe1\ -;\x1c\x00jd\xf5\xbf\x03\x00\xde+\xe6\xe2\xa0FW\ -K\x06\xb2\xd5\x06EG\xa0y \xd0\xe2\x8e\xa6y\x09\ -\x09n\x96O\xa5Q\xde\xd2\xae\x00\x90?}\xea:c\ -V\xae>\xb5\xd6\xbdw\xd6w\xedk\xe4\x1b\xeb>\xfa\ -\xd2\xdav\xdeZ\xe5\xe2C\xb8\xc1\x0d\xcb\xc3c\x14\x8d\ -\x1dZ\xd9\x94\xe4\xc0J&v-\x7f\x08v\xdb\xc1\xc0\ -\xd4\xa1\x04\xe5\xdf\xb8NM\xf6(\xdf\x17\xe1\x93\xcb\xd7\ -d\x8c\xea\xe4\xb5\x1d*\xadq\x09\xc5-c\xc1H\x93\ -v\xed\xe8\xf7x\x85\x06\x85\x8aQ>\xa7\xc1\x1eC\xe1\ -(\xb9y\xcc\xfc(\xda\x93Q\x0b\xb4\x8e}\x12\x0f\x00\ -\xfa\xbc\xa6s\xe1?\x88^S\x00\x8eV\xfd\xb4\x16\xa0\ -\xe5\xe0\x0b\x02wY@(m\xb4K\x15\xedv\x09\x90\ -]\x86\xac\xc6B\x96\xe3\x95\x12\xb6i\x9f\x00a\x01\x00\ -\xb8\x89\x22\x00+\xf6\xaem\xddZ\x1f\xf0\xb5\xc3\xe21\ -\x1e\xd7\xe8\x01cr\x87o\xa8Z\xa8\x19 \xf0y\xd7\ -=\xa4e\xd1\x85]\xad\xc0\xaa\x06\xaa\x9c\xd2\xd6mw|\x1dc\xaa2\ -\xb5\xec\xb1\x9b\xa6\xcac\xedo\xd0\xb17\xa9\xad\xf2\x1c\ -p\xa5F\x8c\xa5^\xde\x050h\xf9\x1a\xaf\x94\xc8\xf8\ -%\xd5b\xedx0\xafm\xec$\x0a\xf6$\xa9\x86\xd7\ -\xaa\x09\x84\xdf\x0b\x00n\x9f\xa1@\xa0-\xe8\x02\xeb\x8c\ -\xc5\x08\xbd)\xa08\x95\x0b\xa5\x13\xff}(Zk\xdb\ -:\x8bO\x00p=l\x9cxu\xfcjC\xaen\x19\ -\xaeO\xde\xe4u\xd7\xf2\x5c\xed\xe6\xab\xd7\x1f[\x8dZ\ -\xa5\xae\xa9\xa1!i\xe3\xf4M\xac\x1f\xae\x00\x89\xd4\x16\ -f\x1d-\xab\x93D\xb5\x9c\xea\xce\xf5\xc3b\xd5\xdc \ -Q\x1b\x22\x15\xb7\x94F\xc9\xd5\x11\x17\x93\xb8Im\x9b\ -J\xa9\xd76f,_\xab`(\xdd\xf5\xe8\xef\x06\xa0\ -*\x88\x94\xb7\x12hU~u\x1e\xaa\xfc\x00\xcc-<\ -ui;\xb6Z\xc6\xa8\xaf\x80\xf6\xec\xa3x\xc2\x81\x18\ -\xb4\xc2C\x1a\x03\x99F\xe8I\xd5\x86M\x85 \x07\x00\ -@W\xa7\xc9\x141e\x119M\xe9\x9e\xb3w\xe43\ -\x09@\xb8\x04\x104\x81\x14+\xd0*\xfc(Um\x84\ -\xa7\xa0L\xb5\xaf\x17\x7frar@-Xd0\x90\ -h\x80\xa0\xbaBw\xe8\x83\x03\xacd\x01#\xe0^\x01\ -\x85\xba\x82\xa9\xd1\xa5\xebA8\xa1z\xc8S\x0b\x8e\x02\ -\x02Rj\xef\xa4\x14<\xb4+\xdcY\xe0\x1axE2\ -\x02o\x99Y\x9eK\xa1R\xe3\xc9xi;\x1c^E\ -\xee=Y[\xcb\xc4+d\xed\x02\x02J\x17\xd7H\xc0\ -\xb0\xb4\xd9V\x9bl\x13\xe0U1\x09\xa06\x91\x9bO\ -\x22\x03p+\x83\xb8{\xd7\xa3\x9fx\xef2\x01!\xf8\ -w\xa2\x22\x08\xf5\xb0\x09\xa9\xeb\x84Z\xbdN\x9dX\xf1\ -\xfcM\x94N\x0a\xb8t\xe6\xde\xebw*\x13\x8fh\x03\ -f\x9fz\x05/\xba>B\x81\x96i\x94\xc0\xcd\x12s\ -]~\xff\x89\xcc\x117\xc5\xeeI}\xe4\xa2d\xf9)\ -\x8a\xf7\xb8}\xb7\xfbV;f\xa4\xfc\x9e\x03\xae\x7f\xc4\ -\xf5\x8f\x11^\xfb\x0e\xb8'B\x97\xc2\x95H+^\xc6\ -\xef*\x9b\xb4\x07p\x06\x0b\x9bp\xee>\x0d\xa5\xab\xbe\ -/\xadA \xd0\x92.a@\xa7k\x09\x8c\x90PM\ -\xfcx|\x80{\x80@\xc6kk9._\xcc\xfa2\ -J\xbf\x5c\xa8\x09\x9djR\xb5*\x84TN\xa0\x00\x08\ -n\xf71\x16\x98\x8c'H\x93\xd5\xab\xec\xcdU>\xe9\ -\xf9O\xcc5\xb1\x1cR\xc7/\xc6\xad[u\x92\x9e\xb7\ -R\x09\x98'\xf2Z\x8b\x84V\xc6H\xbd\x04\xd4\xf1\x14\ -\x10h\x8f_p\xe4:\x008q\xe5f\xae\xd2\x88\xbf\ -\x07\xfa\xd0M\xf7\x12!\x9b\xefP\xf9:\xf7\x9f\xae\xb9\ -\x02\xbe\xcb\xb5\xd7\x07P:\xb2\xc6kq\xcf\xd8\xe9X\ -^\x08\xaa\xc6\xd2\xedo\xc4\xe2U]$\xc5\xab\xd63\ -\xa1\x01\x00$\xa1t\x89f\xb9R@c*\xa22i\ -oc\x84\x88\xdf\xb9\x80\xc0\x0b\xc9\xec\x05\xb5\xfd\xebn\ -\x1f@tL{\xed\x0f\x08\x07\x90\xba\xe9CRB\xed\ -\xb8\x95\x05\x5c\xb5\x90v\xe1\xf6,\xe3\x01\x16\x88\xf7s\ -x\x00\xe2b\x13\x83Ej\x97\x8a\x8bJ\xd6\x1e\xfbJ\ -\xdc\x93D\xae\xaa\x06\xb4j\xe9S\x07I7\xad\xa0|\ -\x15\x9el\x9a\xce\x13\xd6Y~\x17\x9b\x1c\x5c/?\xc9\ -\x80\x80p\xe8V1\xe5\xb1\x04ZGX;\x18\xe86\ -\x0d4\x83\x84\x82\xc5\x0f\xe4\xf2\xc5\x11\xd2[t\xc6\xde\ -\xb4\x0b\x19\xe9\x88\x0e\x94\xd4!\x15\xc9\xe4\xdb\x17\x8b<\ -n\xaf>\xae^\x0a\xd6\xf4\xac@\xe0\x00P\xa0\x09\x9b\ -r@@.\xaf\x09\x1e\xbc\x84>\xab\xb3\x02\xb5\x93Y\ -1\xdc\xb5\xd9U%3\x19R\xae\xd2\xe5\xe1=\x00\xa0\ -\x95R\x15\xcdr=\x14\xa6\xeakw\xba\x98\x14\xa7\x16\ -=\x8co\x16F\xe5\xba\x84\xa9\xa9\x03\x00r-\xea\x08\ -\xb5\xae\xd8\x14\x8f\x1b\x18\xc4\xe3\x91\x96\x07\xc8\xc6\xd4\xed\ -D-\xf1\xd4\x11\xcd\xed\xf4\xe5\x99ur\x9bz9\xb9\ -\x1e\xcb:/\x01b\x1f\xd0nb\x15\xde\x22:\x9b9\ -U[\xdb\xb4\xddMee\x84\x22IL:n=\x8d\ -\xc1K\xc3\xda\xd3\x88Si\xb8\xd3t\xb9\xaa\x0e\xcd\x09\ -\x9c\xd7\x09v\xe0\xae\xdcz>(\xeb\x9a\x83,\xe2\xce\ -{\x97P\xc0\x8a\x85\x86\xd7-\xa2S*G\xb1\xf6a\ -b\xfd\xe0:\x96\xb9\xc2C\x81\xec\xaeyn\x0c\xe1\x7f\ -\xdd\xc1\xd2\xf2\x04\xbaa\xcd\xb3C\xa0\xb4S6\xe3|\ -cdj\xfd\x12H\xc5\x0b5\x01\xc2\x16\xeeCU/\ -\x1d*@Q\x97k\x06\xa1\xef\xc4\xd5$\x04\x07\xaeC\ -\x94T*}\x0e\x02m\xf1R\x99\xf6\x80\x8aKw\xf9\ -\xac\x16p\x08\x19\x8a\xb50o\x0d\xb2:h9kA\ -\xd9\x19\xe2\x1fz\x1e\x95\xbac}:\xac\xca;d\x92\ -\xcc\xa2\x11W\x89;M\x00\x08^\x93\x09\xad\xc9\x03\x02\ -\xf2\xec\xcb0\xeeK0\xef\xcf\x8a*\x91*B\x01\x00\ -\x10\x09S\xb9\x18|FUUR\x9evZ\xe9\xc0\x08\ -\xd7\xa9c\xe2\xba\xe5\x8c\xa0T5\x83\xd2\x22X\xe7\xc5\ -\x98\xea\x15\xa0*,\x88\x1f\xa0\x03\xd7\x81\x14e\xebH\ -\xdcO\x95\xc6\xe7\x00p\x9dJ\xf5w\x85b\xc2\x85k\ -\x83+\xaf\xd1\x83\x11\xe2\x91\xa3\x84\x9a\x5c\xc0\x93?L\ -X\x068\xb9\x8cI\x0e^2\xd4{\xc4g\x19\x17\x9d\ -\xc9\xac\xcd\xac\xdaf\xe6\xb6\x9a\xa9\xb2\x18\x81\xf3\xc5\xa8\ -\x98Q\xe5\xc6:}\xcb\xd7K\xac\x01Ejq\xee\xd5\ -\xfak\x80\xd4cGk\xf9S\xbc\xe2R\xdb\x89\xa9\x9d\ -\x93X\x1bD\xabw\x0e\x0b\x5cD\x09 \x10\x09\x92\xd6\ -\xb9J\x1f\x94\xee\x83\xe1\xeb$o\xf5\xf6\xc9\xd4i\xe2\ -\x02\xc0y#*\xb54Q\xeb\xd7\x1c\x5cx\x84\x1b\x0c\ -u\xf1\x80(:\xd0\xb9\xc7\xff\xeeq\x0f\xda\xe2\xa4}\ -~\xc7\xc4?\x9d%\x8c\xd2\x07\xb41B\xa2\xf7\x02\x02\ -\x22\x00\x0cy\xc7\xb1\xba#Y5p\x03\xda%#\xe0\ -lp\xbf\xf2\x22\xaa`&c\xc0\xf5\xea\xf4P\xef\x18\ -\x1a\xf1\x05\x06\x9fP\xe7\xea\x17\x90\x8b\xa5\xeb\x00^O\ -V\xa9V3\xda\x1b!\x17\xafn#\xb1\x95m\xa4\x83\ -\x00\xa1\xa2\xd1.W6\xdb\x95*ro\x1d\xe6H\x98\ -\xc9\x90\x05Cv\xa3S\xa7\x96?w\xdf\x0a\xe7\xd5Q\ -\xfc\x1e\x1eQ=\x97oXt\xf4\xd8\xc5xo?$\ -a\xe2\x9cS\xe9\x9cB\x15\xc3\xaa;\xbbS<\xca\x93\ -\xa8S\xa9vG\x07\xd5\xe6]\x95\xd2\xfc]\xa9\xb7\x0e\ -\xb5R\xbb|\xb5\x9f\xd1\x18\xaa\x8d\x9f\xba\xa8\x16\x8d_\ -\xb7\x12<\x8ez\x1b\x95N\xdf\xe3\xfd]+\x1c\xbb\x0d\ -\x18N\xf9\xdc\x0d<1c\xd3\xab\xede*\xeaQ\x99\ -\x9f\x8e\xe6el\x09\xa31*kV\xea\xe1\xaarU\ -\xd2\xcc\x8d\xb9\xa3c\xe4\x09\xda\x15\x83\xc9\xc3\x9b&\x18\ -\x10\xdch\x13\xb1\xb4\x99<\xbbu\x98\x81$\xaf\xee\x9a\ -\xe0\xb3\xd3<\x0cV>\x00\x10\x06\x96x\xaf\x86H\x9e\ -\xf5\xfbQ\xbc\x18\xff\x85\xf2\xd5\x09;\x97\x98\xa8\xf6\xf3\ -E\xe37I\x0dO\xadp\x14\x8b\x19a\xa0\x86\xb5\x15\ -\x8a\x9b\xd5\xee\x15D\xdb\xad\xb5\xe350\xa8\xbdo\xc8\ -\xc0M\x06\x0c\x00\xe0\x05\xdcY=\x88;\xbd\x03\x10\x84\ -!L9\x13g\x10\xa8\xdb\xe6\xba|\xf2\xbf:lZ\ -s\x1b^\xd9\x9a\x0aXI\xc1D\x16\xa5p\x80\xae\xfe\ -\xbb\xea\xb5\xab\x86Jj\xb1\xa2\xee\x99\xae\x83\xa6\xf6\x22\ -\x0c\x12R\x00\x87\xfa\xefk\xe1'\x1e\xb2\x1aG\x86\x10\ -[\xd3mWj\x01\x83\xea\x18\xe0\x13I\xe2\x18\xb8v\ -\x1d\x0a\xa1\x89\xb1<,\xbfp\xfe\x91\x15-<6\x1d\ -B\xe1N\x10\xd1\x112\x93\xb7\x09\x07\xb7\x00\x82<\x02\ -\xd6\x89r%j?\x17Q\x13j5\xd9\xd69\xc8\x88\ -2\x00q\x80lm\xd9\xd3\x1e\x09\x09@Pc\xe8\x08\ -zR\x8f\xa6<~\xa7\x8d$\xc5R\xfa\xccm+\x03\ -l:W@M\xa1+\xe6\x9fX\xf9\xecc+\x99z\ -\x08\x08\xee\x02\x823@\xc0w3vY\xbd\x8c\xab\x04\ -@\x04$\x8ce\x8cw\x22\xb7\x10v\xe8P\xa6\x83\xa3\ -Ta\xf2\xe9\x94*\x88\x8a\xe6\xa3\xbd\x93\xb8\xb5l\xdc\ -\xc3\xcf\xbd\xfc\xbe\x1f\x0b\x1b\xc2\xd2\xc7`\xe5\xd3\xb8\xb9\ -\x05\x08\xcf2\xb2j9\xea\xf0\xd5\xbf\x86\xfbQ\xbf@\ -\xaf/\xf0?\x9aC\x1fZ\xd1\xa4\xd7\xc2\xb4\x04\xc4\xaa\ -\x1d[\xf1\x14\x037\xa5\x03\x1en;+\x0aO\xdd\xb2\ -l\x1e.\x8bA\xcb\x1c9\xc5\x1d\xf2\xcaCd\xe2\x09\ -2\x15\x0apm\x17'ui)Z\xd3\xd1yj\xec\ -\xc8\xa0\xe71\x08\xb93\x0f]\xf1\x84\xbc\xc5\xc5\x86M\ -\x9f\xb6\x83\xf3\x5c\xae\xec\x8d\xc1\x97B\x8af\xefZ\x85\ -\xda\xddk\xb3\xc9\xe6\x0b\xe4\xb9U\xaf>\xb2b\xd2W\ -u\x0cQ\x86\x91\xd2\x02I&\xafO\x80G\xc4\x93-\ -\xc4\xc3%\x12E\x1c\x95\xc6*\xad\xed\xdfF\x89\xc7\xa6\ -C'\x0aP\xb8N\x11)\x9c{\xcc{dF\x1d\xd8\ -\x1f\xf2\x5c\xaa\xa9\xb8OHP\xab\xf7\xdb\x96\x0fX/\ -\xc4;\xd3@\xbb\x98yn\xed\x88\x02\xcc\xd9*\x97\x07\ -\x00\xda\xb7\xa9\x06\x95\xaa\xa0vg \xc0/\x0a&\xd4\ -\xea\x15K\x9f{`\xe5\x8b\x8f\xadR\xa7\x80.\xbf@\ -^Z\xc5\xd2K+_xae\xb3O\x19S\xeec\ -\xec\x1e\x06w\x8a\xe1\xe1!\xb1\xfa`7a\xa5\x1bn\ -\x81\xf8{T\xe7\x09\x004\x90\x22RZ\xfdS~\x1f\ -\xc2\x15\x09\x0c\xea\xb2\xa9-[\x9a\xc1R\x93\xc2$\xe5\ -\xeb\xaef\xae\x83\x5c\xb9\x9d\xf4\xa2\x03 t; \xf8\ -\xf1\x06\xa1\xbe\x19\x14\xbf\x84%\xafa\xd1\x9b o\x8b\ -\x14\x90\xf4\x06r\xa3nY9XU.,W\x16\xa6\ -\x83\x0c\x8ag\x00\x00\xe8U?\xfcb\x1d\xab\xa6n\xe3\ -3X\xc9\xcc\x0d\x0bOs\xc3:u\x03\xf7\xa9\xbdl\ -\xda\x0b\x1f\x1c\xc2\x03h\x7f\x9c<\x80\x00\xa0\x8c\x00\xe5\ -f\xb92\xa9\x9b\x96;\x8b\xcbe@\x0a\x96\x9eY\xc1\ -\xe23\xd79C\xcd%\xb4\x87/\x88K\xd5.\x1e\xb9\ -V\xb5\x7f-\xd0a\x17\x0b\x0fI]\x9fY\xc3\xcek\ -k>xk\xadGo\xad\xed\xf0\x8d5\xed\xbc\xb0\xaa\ -\x15\x14\x897P\xba\x9bNV\xa4\ -m\xce\x08a\x19\xae%\xaa\xe2O\xbfv\xbb\x8a=.\ -\x02\x00\xe5\x90J\xd54\xd7\xdc\x86\xb4\xb8\x19\xa9DU\ -\xd6\xd6v\x92\x86\xf4C\xf6&@\xda\x02\x8a_\x07y\ -;V8~\xe0f\x00\xdd!\xd1\xb8\xac\x5cP\xac\xa3\ -R\xddAH\x13:\x89\x5c\xfb\xe1\xce\xf7\xc4\x8d\xab'\ -\xfe1\xec\xf9\xc8r&\x0f-DV\x91\xcdk\xd68\ -n\x9e\xbfg9\xb7\x88G\xd0\x86L\xed\x93\xd3\x8e\x22\ -Gn4kIlU\xc5\x0c^#w\x1e\x0b[\xc4\ -\xe2\x16\x1fY.\xb18\x82\xeb\x0dc1!\x06P\xaf\ -Q,G'~\x94-\xe9\x00\xc5gV\xbf\xf3\xd2\x9a\ -\x0e^Y\xf3\xe1\x0bk9xf\xad\xfbO\xadq\xfb\ -\xa1U\xad\xdeu\xcd\xaa\xc2X\xb6\xe6ER\xb5\xe1S\ -\x9ba\xce\xa7lu4\xad\xb8F\x18\xe5\xe8\x940\x1d\ -GS\xbe\xf4\x1cy\xe9\x9a@\xe8$\xb2\x02\x94^0\ -\xf3\x1c\xe5\xbf\x04\x1c:\x9bY\x0az\xcb\xdf_[\xc9\ -\xfcs\x00\x80\x85\x12\xab\xf3\x08\x83\xaa\xebsG\xd7\xab\ -\xb7\x80\x13\x85d\xb5\xcb\xd1\xf68\x8cB\xde\x11\xefR\ -\x04\xc0t\xc6\x91\x0e\xbf\xaa\xdax\xe7\xce\xfe\xad\xba\xaa\ -C?\xdf[\xf1\xc2\x1b\xae\xf7\x02O\xf3\x94q\xe6\xf9\ -\x87\xefat<\x03\x00 \xce\x03\x94l\ -\xe2\xa4\xe2\xa3\xeeS\xe9\xa0#\x8bn\x03\xa4\xaab \ -T\x9aq\xd4v2\xbcK\xee\xac\xca\xa7p\xab\xa4c\ -9j\x99\x86\xa7\xc9\x9d#\xcc\x00\x8e\xb2\xd5'N\xf9\ -\x9a\xb4\xaa\xddzl\xb5\x9b\xf7\xb0\xa4\x9bX\xfd\xb1U\ -.\x1d\x10C\xb5\x01\x05F=\xb9\x8f1\xa8/\x8fJ\ -\xe0\xe1\x10-\x9a\x90R*\x07\x9bW\xd5\x93R>\x9e\ -A\x8d\xa7u\x12h\xe9\x82w\x80\x94\xe7\x01\x1e\xe3\xcd\ -$z\xff\x82\xdf\xbd\xb6\xd2\xa5\xb7\x00\x0f\x00,\x0a\x10\ -x\x86\xc9{\xae\xd1\x96\x0e\xa5V1M@E\xb6\xee\ -\x15\xe6\xaf}\x87\xd2\x09\xc0\xd0\xa4P\xe4\xbc\x99C\x01\ -\xf1\xbd\x18\xa0\x95\xb9\x13\xd0\xdeX\x85N>[z\x83\ -W\xd1\xd6\xf8\xc7\x84\xb6\xfbx\xad;\x90MB(\xb1\ ->K\xe5\xe3\x9d<\x83\xf6sh\x17\x97\xdbQ\x04\x98\ -I\x11\xd3\xbat\x00\xe7\x01\x00\xe0B\xae\xef\x8c.\x86\ -\x1b\x0a\x83H\x81@\xbc@\xb5\xe6\xda\xc5\x9b\xdc0\xed\ -\xe6\x98]\x0b3W\x9fwQ\x97\xd7m\xe9\x90\xa3@\ -\xd3\xb0\x85;\xa7\x01\xc0\xb2\x15\xa1\xb8\xb2\xe9k\x0c\xe4\ -\x1db\x94\xac\xed\x89\x95-?u'V\x97\xea\xe0\x02\ -\x91#,Q\x1eA-\xd4t\xea\xb8;\x1f\xd7\xa5g\ -d\x0e\xca \xcek\xd8u\xe4yP=\x0a`\xbaY\ -c\x0c\xc8(\xf7\x0a!\xd2\xe1\xd1\xda\xf6\xac\xc9!\xb7\ -5J\x0bX\xfa.u\xdav+\x95\x90,\xa5`p\ -\x8d(\xae2\x0c\x85R5\xa1\xd0\xb9Cj\x1b\ -\x97\x87\xcbw\xad\xe3\xe0Z\xae=\x8dKU\xb5\xd3G\ -\x82\x95\xe2\xcd\x94\xa3\x0b\x04\x1e\x000Du\xf4\xc0[\ -\xe4@&s\x09\x1b*\x07\xd7!\x97y\xaa\x10V%\ -\x962\x22\xf5\x01\xd0V1\xcd\xa1\xb89\x95yK\xad\ -\x83\xabhR\xadn\x06\x99&\x8c\xc3a4M, \ -\xb4j\xe5\x11\x92\x0f\x08b\x5c'\x09\x11A\xf2\xea\x10\ -d\xcbm\xda\x14\x13%\xae\x8a\x08j\xe3\x87z\xf5i\ -+\xb8k\xe6\xd0A\xbe\xdf\xb9\xe2\xce\x08\x08\x93\x02E\ -\xba\x16\x9d\x84\x11\x9d|\x15\xee[\xc7\xb5o\xc3\xb2\x19\ -d\xc8\x5c\xc1j>Hlje\xa3%\x95TY|A\xa9\xc5\ -\xe7\x17[B\x01R\x5cn\x89e\xd5\x96\xc8\xdf\x12\xab\ -[-Q\xdd=I\x01\x93j\xb5OP\x99\x10\xa2\xf7\ -\xbc\xa64\xa8\xc8d\x84\xfb?\xdf2\xa6\xc5.\xadI\ -tk\xc6\x14\x0f\x86g\xd2Q.ZA\x0dq\x7fj\ -4\xa1\xd2y-d)\xbcj\xc3\xad\xb7\x90\xc4\x18k\ -\xcb\x9dVf\x05\x02\xc2\x81\x1aQ\xa8\xa5K\x04\x008\ -\xe5\xe3\x01r\x05\x22\xf4\xa3\x83\x8f\xa2\x0b\x067-\ -_\xfdwQ|\x18ku\xcd\x91y\xaf\xa9\xe0\xf0\xf0\ -&\x80\xda\xc6\x02\xf8\xec\xcc\x11D\xe8&\xd6\x7f\x9b\x94\ -\xe5\x1e\xf1\x96\xb89{\x8a%\x92\xe3\xe2Ju\xbe\xbe\ -\xeb\xcb\x8b\x87\xd1Z\xbf@\x90\x5c\xafU;\xcd?\x8c\ -a\x89X_\xdb\x14\xe4e\xc1\xedr\xf5i/\xe3\xa0\ -v\x13\xc3\x96I\x91\xdc\xe1N\xb8\xd5\x90\xd8\xbe\xa6\x87\ -\xdd\x926\xf7\xcdgu \xa3\xdfmPQ\x0b\xf7q\ -\xcb\x90\xd2\xaa\xda-Y;\x84\x0a\xab,!\xbf\xdc\xe2\ -sK-.Z\x8c\x14Z\x5c.\x92Wdq\x05%\ -\x16W\x5c\x01\xe7Q\xa1i\xbd%\x947\x10\xfe\x1a\xbd\ -W~\x8e\xd7\x1e\x832\xfd\xdc\x02X:\xe0C\xbdn\ -\xc7\xaf\xb74-O\xe1M\xf5\xfa\xdaum\xad\x05\xac\ -\x98\x16\x82\xdc\x01\xd0\x8d*\x00\xd1\xd4\xf7$\xafX\xa8\ -\x96\xbdQL\x1a\x8a\xd1\xbeKu\xfa\x129\xd7\xbc\x88\ -vj\xe9@/w\xa8\x17\xfcI\xe72)t\xaac\ -{J\xed\x90%\xb9\x92y-\xa6IT$\xd3\xebB\ -u|\xa5*\x97\x09\xdb*\xa7\x03\x10\xdae\xa4\xc5 \ -\xaf\x09\xa5\x1a_\xceXLB\xc5\xb0[7N\xe5\x17\ ->\xd0\xa4\xae\x96!\x14\xad\x16\xe9\x9ayr\x07@!\ -\xda\xdd\xab\x83\x08\x0b\xc6\xbc\x83\x9dJ'O\xact\x02\ -W?\xbeg\x85XWTs\xff\xe4\xfdA7\xd0\xe7\ -3\x81\x9d3\xc4\xb7\x19B\xc9,\x80X\x02\xb9W\x89\ -Y\xbb\xa4~'V\x86g(\x83i\x17\xb9UC\xb2\ -\x0fMBqm-\x93\xaa\x10\xc4k\xcc\xac\x92p-\ -\x0fk\xbd\xbb\x97\x9b\x1e\x00\xbd\xdck\xdb,\xaer\x85\ -\xd0\xb0\x09)\xc4\xdd\xaa\xe5\x9c\x96R\xc92\x94;\x8b\ -\xbf\x04\x14[Ic\xbdC\xa5q\x89\x0cV\xaaV\xce\ -\xb4\xd1\x93L&\xa9X\xca\xaf\xb1$IA\x8d%\xe6\ -W\x03\x84J\x80Pf\xb19Ev%\xa7\xd0\xae\x00\ -\x86+\xb9\xbc\xcf+\xb1X{\x98\xd16\x8a\x82\xa7\ -\xf1 \xcb\x90\xaem\xc8\x17\x00\x02\x00e\x0b\xa4Q\xa4\ -o:\xc2E\x93\x1d\x02\x9b_[\xce\xe5\x165Pd\ -\x1f\x89B3)\xa86bh>B\xed\x5c\xd4\xcc)\ -\x83A\xd0n\xd7 \x9e(8\x827\x80Sh>=\ -\x80'Sv\xa0r\xb74H\x90\x0aJRA{*\ -\x03\x9e\xc2\xa0$\x97\x01\x80\x92FK.i\xb0\x94\xd2\ -&\xa4\x05i\x06\x14XsA\xad\xc5\xe7U\xe2\x05P\ -4^!\x16\xafp%\x0a\x08\x04\x86h\xc1'\x89u\ -\xaf\x85\xee\xef\xb1\xb9\xe5x\x8cZK(l\xc1\xab\xf4\ -\xe0]\x08\x09\x18\x94\xbf\x11\x0e\xc3sd4\xe2\xb5\xea\ -\x15\x93\xb1tU\xe5hM^\x16\xe9J\xc3\xb4\x0dL\ -[\xc1\xcf\x97\xc4U\xc3W\xa6\x9e\xc2C\xeeh95\ -\xad\x8e`\x88\x1a\xff\x0a\xc6\xa9z\xe9\xaeU\xcci\x16\ -\x900;L(\xeb\xd6fU\xc6\xb7E}\x8d\xf0\x96\ -\xcd\x00\x88\xb1O\x82K\xa9c\xba\xf6\x18\xa8\xf8\xf5\x0a\ -\xdf\x7f\xa9\xb4\xd3.\x93\xc5].iCZ\xed\x0a\x02\ -\x00T\xb9\xea\xed\x91SM]:V\xa2\x93?t~\ -]\x1e\xa9\x95:h\x97J\xe9\xb3w\xacR\x87K\xe9\ -\x00\xa2\x19\x08\xde\xd45w\x14\x89\x94\x9f\xab=\xfc}\ -\x9a\xf5\xf3\x8a=\xdc\x9a\x7f\x83J\xadT\xac\xd0\x8b\xd2\ -\xbcx\x99\x0e\x18\x02\xedS\xee\xb3\xf9c{\x84\x80\x9b\ -\x84\x83\x07V\xbd\xf6\x14rH\x96@\x9e+\x82\xa3\xb3\ -\xfeu0\xb5\x80\x90\xa1\xa6\x14\xae\xc7\xae\xca\xb5T\xb1\ -\xd3\xef\x81@\xe1AS\xb1\xf24*\x97\xee\xc7\xdd\x13\ -\xf3\xfd\xc4~\xd7-K+\x88\xdaI\xdbA\xcc%\xef\ -\xcd\x04\x0c\x01\xbe+\x83\xefJ\xab\x06\xecd0i\xd5\ -d15\xdcWM\x1f\xef\xb9G5\x96\xd6F\xcd\xa2\ -\x06Wf\x1e\x87W\x88\x05\x0c\xb1\x02C\x14/\x80g\ -\x88uJ\xf7\x00\x10\x0b0\xe2\xf8}\x5cn\x05\xde\xa3\ -\xce\x92\x8a\xda-\xad\x82g\x84|e\xb7@\x0c!Z\ -\xd90\xee\xcc\x16\xc2\x1b \xf8\xdf\x01\xa0\xfa\xc0\x81s\ -+\xedv\x15\xc5\xaa\xdeM(iw\xc5\x9c\x89\x00!\ -\xa5z\xc8|\x8d\xd3\x10\xd55\xbc\xec\x915\x10:\xbb\ -w\x9eX\xcf\xeeC\xeb\xdc>\xb3\xe6u\xa5\xdb\xea\x18\ -\xbeLX\x80\x97\x0dh\xe7\xb5j\x12\x08#dV\xc9\ -\xcdZ\xfe\x1d\x03\x04C\xe7 \xe8B:\xcc\xdb\x19\xd4\ -\xea\xd2\xf9\x18\xb7\xf9\x92|>^\xdb\xa4\x19\x10\x15K\ -\x04\x19\xd4\x1c\xe2\xba\x8eg\xd3IS\x95\xa4PU0\ -\xfaJ\xac\xb5\x1c\xab\xd5!D:[ \x0fr%\xcb\ -\x0f\xf7.[V\x17\x04\x88L\xc0\xafE#\xe2\x9f\x03\ -@\xadJ\xbb@\xb3\xb6Y\x03\x82\x94\xba>R\x93Q\ -\xd39?y#[^{\xfa\xf5'\xd6\xb0\xf3\xc6\x1a\ -w?X\xdd\xd6\xe7\x10\xc5\xb7p\x85\xe7\xb8\xba\x07\xb0\ -j\x80\xa0\xe2\x0f\x91#\xb9PGt\x86\x01\xc2 !\ -\xc1+\xb4LV}\x01\xb16\xad\x03\x97H\x5c\xd4!\ -\xd8j\x8f\x96\x05;\x0e\x0f\xdc\xc4Jn\x03\xd2;V\ -0|\xcb\xf2\x06\x8f,\xa7\x17\xa5t\x12\xea \x97A\ -\xee5\x13\xf2\xa6\x8c&C\xc5\x15\xd5\x84\x1b)B;\ -u\x8b\x18\x97\xc2&\x80\x00\x18\xf2\xb5\xf7\x007\x9fW\ -\x81\x94#\x00\x02\xf7\xaf\xd78~\x8e\x07(\x89|6\ -\x05\xeb\xf7\xd5L:\xe5G\xbb\xf7-\x8f{\x88\xf6\x1e\ -Y\x88T5\xa0\xba\x86\x06u\x0f\x13+?\xaft\x86\ -\xf0z\x1bM\x07x&B\x1c\x9e \x09KM*\xeb\ -r\xaf)\x80=\xbd~\x1c\xf0.\xc0\xb3v\xdc\x86\x9a\ -\xe1\x83\xe76v\xf2\xdcF\xaf=\xb1\xbe\x83{V\xb7\ -\xa2\xb5\x8c=\xb2\x02B\xf4\xd8!\x19\x06\xe4PF\x00\ -g\x13qW\xf6\xa6\x8d\xad:\x87\xc0\xab\x19$\x9c\x02\ -~\x85\x0b5\xc1\x88QW,m\xceL\xac\xed\x86\x88\ -\xf4\xe3\xaa\xc7,\x9b\xfcWn\xbaD\xf9\xfc\xc2m\xab\ -\x82\xb0U.\xea\x0c\xbaS\x5c\xb7N\x12\xd5qk\xf0\ -\x04\xed\xf7W\xf5M;\xfcA\xe4\xaaY5\xec\xaa\xb4\ -Q\x95\x0d,T\xf5~\xb5<\x9c\x06V\x16\x867\xc8\ -\xc0\x0bduN\x03\x80\xabV\xbep\xc3\x1a\xb6\x9eZ\ -\xdb\xd1\x07\xeb\xbc\xfe\xd1:\xae\xfd`-G\xdf\x03\x88\ -o\xacj\xeds\xd7f\xbe`\x82J\xd6\xb0\x88\x87\xd9\xb5\ -\xda\xb5\xdb\xd6\xb2\xff\xc2\xba\xae\x7f\xb0\xbe\xb3\x8f\xd6\x0f\ -\x08\xfa\xef\xfc\xc1\xfan\xfff=\xb7~\xb3\xae\x93?\ -Z\xfb\xfeO\xd6\xbc\xf1\xad\xd5-\xbf\xb7\xca\xd9\x17\x90\ -\xcf\xc7\x84\xa7\x07V4\x86\xf0Z2\xf1\xc8\x01\xa4b\ -^\xd6\xfe\xb9\xd5\x01\x9a\xc6\x9d\xef\xacy\xffGk=\ -\xfc\x09\xf9\xc1\x9a\xf6\x00\xc0\xc6[w\x08s\xa1\xe6\x1f\ -H=\xb3T>&\xbe\x22O\x85B\xbd\x9d3(\xdf\ -\xf1\x0c\xd5\xdb\xc1\x17\xc8\x1etB\x98J\xadt\xd6\x8e\ -6\x8d*\xadS1\xaa\x8f1\xc8P\xaa\xa7\xcf\x10\xab\ -\xfdp\x8c`\xeb*\x00%+B\xe1\xda\x1f\x99\xeb\x1a\ ->\xde \x8b\x22\xa7w\xfd\x15\x8e\xed\xa2\xd9\xa3\xa6\x94\ -?e*X\xaa\xcb\x14T.\xcew\xb9\xfd\xfb\x18W\ -\xb2t\x03\xe1\xd5\x81\x9b\x85p\xad\xda\xa9\x03\xabW\xaf\ -\xa4\xd9\x13\xab\xc5C\x17\xaa\xe1v7Y\x01\x86\xa0z\ -\x0au!Ok^\xe7;VP8\xd6\xaf\xcc\x03/\ -)q\xe1\xe7\x5cRI=\x95\xa1\xc4\xa4\xaa\x22F-\ -\xe2:\x17]\xd7\xa8\x001=kx\xcb\xc2\xa3\xbb\x16\ -\x81\xe1\xabS\x97v\x05\x05\x07A.nH\x07/\xa7\ -\x92\xdb\xba#Z@S\x22\xb1\xcc\xabF%>\xcb\xcd\ -\x90\xc7'\xe2\xd6<\xe1\xbd\x03\x81j\xfd4\xa8\xbd\xa0\ -\xbb\x97A\x1f\xe4\xa6\xf1\x02#+\x10\xc1\x03,\xf5\x0c\ -+}l\xedGo\xac\xfb\xc6\x97\xd6{\xeb;\xeb?\ -\xfb\xd9\x06\xce\xfeh\xfd\xa7\xbfY\xdf\x8d?Z\xf7\xf1\ -/\xd6\xb1\xf7\x835c\xd1\x0dWQ\xa6\x9a?\x22\x8d\ -W\xbf\xb2\xf6\x9do\xad\xfb\xe0{\xeb=\x06<|\xb6\ -\xff\xd6\x9f\xac\xeb\xe6o\xd6q\xfdWk;A\xf9\xfb\ -j\x12\xf9\xc6*Vt\x82\xc9\xa9\xe9\xa8\xfa`\xd72\ -!\x0b\xf0_X\xbeS\xbe\xe2#\xf7\x09hS\x9a\x08\ -\x0b\xad\xa4b<\xafkx\xa1B\x0e\xa5\xc5*\xcc \ -\xdb\x08A\x90\xb3U\xef7\xa8\xe2\x8e\xf3\xbe\x08Xv\ -\xb0\x93\xd4\x14\x00\x84\xe0!\x11\x94\x9d3\x08\xd8T\x98\ -1z\xc7r\x08K\x91\xb1;\x16\xc6+\xa8\x8eA \ -Pk\xf7tM\xcfb\xa9\xea\xc4\xe6\xa4\x19\x01tI\ -\x00,\x19IQA\x0e\xa9of\xe7\xbcE\xdc\xe4\xdb\ -\xb2\x855\x19\xd7\xb9j\x01\x00\x97\x8e\xb2\xd3\x90\xd4\x06\ -\x94^\xb7\x88\xc1\xcd\x91\xefk\xfa~\xd2\xcb\xfb\xc5\x9d\ -\x5c\xea\xa9\x13O\x14:\xbd\x99A\x81-&\xa5m\x89\ -\x0bx\xedB\x5c-`\xf7\x1aV\xae\xa5N\xed\x02\xe2\ -\xe1\x10m\x11\xd3yv\x17\xe7\xe1k\x8d<\xd9\xcd`\ -q\x83nzQ\x02\xc1Qy\xb4\xfeF\x8cs\xafz\ -\x10\x80\xa2R+o\x070\xee\xb3\x0e\x06\xde\xd8\x8fE\ -\x0d\x935La\x1d\xcbX\xe46\xe9\xe0\x09@\xb8\x03\ -\x10\xe0\x04\x87o\xad\xfb\xdaW\xd6w\xeb{\x1b8\x05\ -\x08\xa7\xbf\xa2\xd4_\xad\xe7\xfa/x\x84\x9f\xad\x030\ -\xb4\x0b\x10'x\x8a\x9b\x7f\xb2\xa9\xfb\x7f\xb3\x85'\xff\ -l\x8b\xcf\xfe\xd5\x16\x9f\xff\x9bM?\xfd;\xe1\xe47\ -k\xbd\xf6\x9d\xd5\xef\xe15 \x9aE\xf3g\x96\x0bw\ -\xc9&\xbb\xd1Ii\x8a\xad\xae\x22Y\xbbq%\x9a<\ -\x11\xb1\xe4\xf7\xda\x94\xa9\xbe\x89j\x9f\xa7\x1a\xbc \xde\ -Bg\x1ahuPk\x0c\xd1\xa9\x9bn\x8d!\xaa\xb6\ -\xf7S\xeao\x8cu\xab\xa2\xc7\xb9\xf9}g\x8dY\xbc\ -\x86 \x81r\xcb:\x926wR\xd3\xb8O\xdc\x8e\xea\ -\xc8\xf8]>\x7f\x1d\xb2\xba\x8b']uqZ3t\ -*\xd3v\xfb\x0b\xb4\xf9T\x00he\xfcZ\xb1`\xb5\ -\xb1\xc5S\x09\x94\xee\xe0,\x8c\xccY0\xd6\x9dJz\ -\x99R\xc7\xe7Pz2\xdc(I\x8a\xaf\x82\xf4\x91\x8a\ -\xbacgH'\xf5\x9a\xa0\x0d&\xae*X\x15\xc1\x18\ -'\xd7\xd2Q;\xaeGPJ\x9b\x0a\x05\xbd\xe9^)\ -Xu\xed\xae\xb8R\xacZ3N(^u\x82^w\ -\xd0\x7f\x88\x88W\x1a\x0f\xe0\x1aE\xa9v\xa0\x83\xfc\xfd\ -BT\x89\xa3\xbf\xe9\xb3\x8e\xf0\x88\xacM\xe0\x9a\xb45\ -\x8b\x1c\xb7i\x10\xf79B\x9a6I\xca\x07\xb2\xe1\x1d\ -\xf9\x13\xa4\x86:?x\xed\x1e1\xfb\x99\xb5\x1d\xbc\xb1\ -\xce\xe3\x0f\xd6}\xf2\x15\x80\xf8\xda:\xaf}c\xed\xd7\ ->Z\xfb\x8d\x1f\xad\xe3\xd6/\xd6M\x98\x18~\xf0W\ -[|\xf5\xaf\xb6\xfe\xee?\xdb\xda\xdb\x7f\xb7\xe5\xd7\xff\ -bSO\xfel\x1d7\xbe\xb5\x9a\x9dWVJ\xea\x94\ -\x07w\xc9\x06\xd0\xfe\x0eU\xc82\x08Xy\x1c9q\ -,\xe9\x96\xfa\xf1hBD{\x03\xe5\xbdR\xb4\x8b\x07\ -\x17\xaf2/uP\xd3\xd15\x1e\x00\xf0\x86\x22\x8f\x93\ -\x84\xc4\x19\xb2\x0b\xb2\xa1\x5c\x1dqCZ\x1c\x99\xba\x0d\ -\x08\xce\xe0N\xb7\xc8>\xae[\xb0\x070\xf4\x1c\xb9x\ -,B\xaac\xdb\xd5\xb5m2^\xe9g\x17c\xdd\x03\ -\xdc{\x00@\x17\xe3\x8fB\x9bb\x83v\x8d|\x02\x00\ -\x17S\xbe\xaa\x1e\xb9\xaa\x0f\xcc`0\xd4G\xc8u\x02\ -\xedSQ\xc4\x0enOK\xaf\xca\x10\xd4N]\xc0\xc0\ -+h\xb5K\xcaw^\x83\xc1\x13\xdb\x96\xf2\xbb\x17x\ -\xd5\xba\xff4\xa9\x0d\xa9\xa3\xbaV5\xc0\x0b\xeaQ\x84\ -\x8a,\x95B*%#3\xd1*\xa0\x8aJ3;f\ -\x89\xa9\xb0k\xfe7S\xc5\xa6\xfd\xa4n\xc3X\xe3\xf8\ -\xb6\x85\xa7\xf7\xac`\xf1\xd0\xaa\xd6\xafY\xdd\xe6u\xab\ -Y?\x86\xe5\xef[\xc1\xb4\xb6\xb5\xcb\x9a\xb1\x8c&\xa5\ -\xa2\xc4\xf6j\xe2=\xd6\xefu\xe1\x82\xf0a\xf9\xca\x8b\ -\x05rw@\x04\x0aw\xc0\x05\xe0\xda\x8e\xe5\x8aI\x09\ -\x8d\xb2Pg\x08\x840-\xee\xb8Jg\x81\x14@\x07\ -\xe1\x07\xd9:\x17\x99\xdc[\x07P\x14\x12\xdfK\x94\xa5\ -\xa8\x00D\x95?\x0b:\x1f\xe9\x85\x15\xce=s\x05\x22\ -\x02IX-\xe6U\xf0\x01\x00\xdc\xa9 (\xdc)\x05\ -\xde\xa0n\x9f*\xd4Hi\xdf@'KX?\x06\x89\ -\xeb\x96E\x0b\x00J\xdb\xdc\xa1\x8f.\x04\x13\xb6\xe55\ -\x94\xde\xc9C\xe0\xee\x93D`\x11\xb5\xd4Q\xdf'\x1d\ -w'\xb2\x97\xaa\xddUR\xbe\xeb1\xa8]U\x07x\ -l\xd5J\xee[\x8c\xeb\x80\x85\xeb\xf7\x94\xafmCr\ -7r\x19X\x06\xee\xc6-\xa2\xc8B $j)\xef\ -C\x99Z\xea\x0cB\x14\xb3q\x89\xe1!-\xb3\xc2z\ -y\xd56(u\x08\xd5\xf1\xe8\xae[6\xdeCLZ\ -e\xe5\xea\xc9\xab\x1e\x81\xb2~\x9d\xdf\x97\x06\x17\xd0Y\ -~\xaeEku\x17\x0f\xaa\x06M\xb0\xf0Zn^=\ -t\x9dh\xb2BG\xa4\xea\xd8\xb7\x01\xdc\x9dz\xf9\x03\ -\x12\xbcEr\x1b\xf7\xd6\xc9\xf7\xf5N[\xe6\xc0\x0c^\ -\x88\x10\xd2?\xc5\x83\xa9t\x9d\xfb\xc7\xb3$\xaa\x13\x99\ -k\xda\xc8\xf7j\xd7\xef'\xa6\xaf)j\xad2\xea\xbe\ -T\xc6\xae\x9dP\xdc\xb7\xac\x1f\xc5\x8b\x95{\x87>\xa8\ -N\x81\x01\xe7s\xe9J\xf5 \x87\xfefR2\xb5\x8b\ -%{\xd2\xb2x6\x80\xd7A\x91\xf9\xe3\xb7\xcd; \ -\xf3\xa5\x95/\xbf\xb5\xf2\x95wV\xb6\xf2\x16\x0e\xf2\xda\ -\x8a\x00A\xc1\x9c\x08\xe0}\xf8\x802\x80\x13\xc0s\xc0\ -8j^@\xa2\x94\xd0\xab\xdd\xd7^\x08\xb5\x81Mj\ -\x5c\xf4t\x22\x97\x8e25Q$\xf2\x97\x06/\x10\xf7\ -J\x15y\xe4\x1e]6\x86\xbe\xdc\x16t\x94\xef:\x97\ -\xf1|\xee\xffd\xc8\x18\xb6\xdc\xbeZ\x00\xf8;\xb6I\ -\x155=\xae\x1215\x98\xde\xb0\x18\xa5\x09Z&\xd4\ -\xd6\xe6x\x5c\x88\xa6\x0c5\xc5\xaaT\xc8\xc5\x1c5+\ -r\x1b+\x18\x04\x18\xa9\x5c\xb4v\xb9\x04q\x85\xda\x1d\ -\xa4I!m|\x10\xc9\xca\xd6\xb61\x11'H\xa3\xda\ -\xc4kyW[\x97t\xf8B\x9av\xe5J\x9aG\xdd\ -t\xb3\x94\x9a\xa4\xd5+\xd5\x18~\x9a\x8e\xee\xc02\xbb\ -\x11Y(\xaf\xea\xdf\xc7\xdf]3\xc72\xbd\x22\xe7\xfb\ -\xe0\xdd\xc9\xa0j1W\xc7w\xd4w\x02bO\x12\xd4\ -\xd0AM'\xf9\x9b>\x13\xcf5\xbc\xef\x04`\x88V\ -\x175g\xe1:\x81\xe9\x189\xac_\x80\xfd\x04Z,\ -^g\xf4\xa7\xe36\xd3\xc9\x93\xd3\xf1\x84\xe9\xa4\xb4\xda\ -\xd1\xe4\x94\x0f#\xcf\x84(\xea\xf8{\x9d\x0f\xac\xd3\xd5\ -sGN\xacH\x85\xa6*\xcb^yi\x95:\x80z\ -\xfd\x9d\x13\x95n\x95\xae\xc8\x13\xe0\x05\xa6\x1f\xc0\x13N\ -\xdd\x92\xb5\xdb\xd6&\x00\xb85\x0b<\x806\xc2\xb4\x12\ -\x06\x9aW\xf1\x84R>\xee_\x06y\x0e\x00q\x00\xdd\ -\xb3\xbc\x91k\xd3\x0f!O\xe15\x99\x9f\x93\xc8\x0c4\ -\xe9\x96HJ\x9b\xe0\x84\xf7\x18\xb0\xba\xbd\xab\xd6@\x8d\ -\xbd\xb5\xe4\x9f\xd1J\x18\xd7>K\x1dx\xd9@\xf8 \ -\x83\x88\x89\xab\x80\x11K\xb4*\x05\x82\xb4@\xa1\xedQ\ -\x1e\x08.\x88\x87@ \xf4\xc9z\xa7\x19\xa8Yn\x5c\ -\xb1z\x09\xd6\xbb\x86\xe5\x0b\x04[\x16\xea\xc7\x0b\xa8\xe6\ -^!\x02\xf7\xefN\xf2f\xd0\xd4^US\xc4\xb2z\ -7[\xa85\x02\x94\xac\xae\x1eq%\xcd\x16[\xdc\x08\ -1k\x22.\xab\xdd\x09\xe4\xacL[\xb2\xb4CW\xfb\ -\xf4\x1b\xbd\x8e\x9aH\x82V\xeb\xf8\xbc\xa6e\xe3\xf4w\ -\x00\xa1\xedY\x97\xb5s\xa7\xbc\xc9\xc9\x95r\xbeO]\ -\xc0\xb4\xc1\xb3R\x80R\xb3\x06\xafa\x83\x00\x90\xa4Y\ -\ -\xb9\x7f\xbeX\xb5{:\xf3G\xe7\xd4k\xb7\xabw\xfa\ -$i\xd1\xb0\xb7]\xdc\x89\xab\xf4\xdd\x01\x04\x1b\x0c\x12\ -\x5cA\x9fo\x9b\x03\x08\x0c`# \xd02.\x00H\ -V\xd3\x22Y2\x00P\xef\xdc+\x05\xea\xa6U\x07\x10\ -\xb4\x1b\xb7\xfe\x5c\xf9\xb5\xe7\x00\xb8P\xbe\x07\x80+\x80\ -\xe32\x00\xb8T\xdc\x8a\xd2\xdb\xce\xa5\xf5\xd3\x1aw\xac\ -z\xf5\xaa\x0d\xec'9\xef!\x04\xe84\x8f\x7f\xd1~\ -FG\xc3\xa6K\x18\xcct\x065\x1d\xc5g\x90+g\ -\x10\x163PH\xba\x04\x10\xb8\xbf\xf1\x99\x0c,Mg\ -\xee\xeb8y\xed\xf9\xcfF\x99\xda\x09\x1c\x1d\xbfa:\ -\xad\xdbm\x03\xd3!\x17d\x06\xd1\x09\xc9\x91;\xeb \ -G\xbd\x95D\x92\xe1H\xfa?\x85\x1b\xed]\x14\xc7\x10\ -\x89S+Z\x85_\xb5\x8e\x91b$\xcaP.\x00\xa0\ -\xc6\x0f\x0a\x03^\x9bZ\xbc\x81\x13\xbc\xb3\x08\xbb\xe6\x03\ -x\x06\x85\x02\xcd\x1e&\xab\x8c_\x93u\x22\xb0J3\ -?q\x05\xfe\xce3+\xe5M\xd0\xca\xa0\xf6>2\x16\ -1\xf1M \x0f\xcb\x8c\xaf\x1f&\xee\xfc.\xf6\xa3|\ -m\x0b\x13\xf1s\x9d\xc3 <\xae\xe9A7)\x906\ -B\xf20a2\x80\x9cQ=$\x83\xc0\x83G\x95\x12\ -\xb9\x87\xc5\x1b\xf4\xc3\x09\xc4\x92U&\xa6\xddA\x9dX\ -\x8d\xbc\x86\x80 O\x00\xd8\x92d\x99\xb8~\x0f\x04u\ -\xe7\x00\xf0\xe4\x12\xca\xbe\x8c\xd2/\xe7\xab\xe7\xae\xac^\ -\x9f!T\xe0\x1d.\x94\xffYI\xbb}V\xaa>\x7f\ -\x9d\xae\xe7\x9f:_\xc6^t\xe9\x02\x14\xde\x0a\xde\xb9\ -\xf0\xb3W\xad\xa3>DjFE\x18`\xe0\x9d\xa0\xe8\ -4\xd8\xb6\x13\x5c\xaf\x13\xde\xa7\xe2&S\x01C*\x03\ -\x9dJH\x10`Dl\xb5mNg-eiZ\x18\ -\x00\xb8\xdd;\xc3\x9a\xf5;\xc4\xc2\xb5X\x06)\xd6\xe4\ -\x91z#\xa8.QS\xc5\x9aO\xd0\xc4\x1a\x99\x94\xc6\ -Ss,\x8a\xe7\xca\xb6t\x91\x14P\xd5O^\xda\xa4\ -\xc1\x04\xf4\xbc&Wz\x92REv\x02\x00RP~\ -\x0a\x03,Qc*\x15r\xa8TMi\xb1fF\xd5\ -\xb4!K\x0a\x1f\xf5\xb6o\x85\xb5\xb1\xa6o\x1f\xc0\xef\ -`$(\x9c\x8cB%n:B\xc7\x1d\xdf\x8eBd\ -\xf5N\x5cvD\x86\xe1@ \xc5\xe8Tt\x8c\x10\xe3\ -\x8b\x93`\xe9\xf1b\xf6\x80\xd3\xb5tq\xa9 @\xf8\ -\xa4|\xadJ\x02\x00\xdd\x97&\x81\x00\x808D\x8a\x8a\ -N\x00\x81\x97\xbaJ\x88\xf9\x9aY\x04\xb8:e=\xb1\ -^M!&P>\xafx\xf6\x04\xf8YL\x22\x16\xae\ -9g\x89;\x18\x8a\x9bR\x1f\x1b1b\xb9*-r\ -H\xf1nkr?\xb1]\xee]\x9d+\xc9\xfde\xed\ -\xd1\xf1C\xa7x\x1d\xc7\x1e\x1e\xe5oC\x9b|F[\ -\xc4E\x0eQ\xf8\xe0U\xcb'M,\xe4oE#\xbc\ -\x0eoZ~\xff\x8aE\xbaf-K={\xea\xff\x01\ -\x02\xf1\x01)\xfd3b\xfeg\xe7\x00\xb8\x5c\x80\xe5K\ -\xf9X\xb1\xd7\xe0P-\xd5\xa4\xf4.\x94\xdf\x83\xf4\xda\ -%\xd5\xbb92\xab\xd8I*\xa4\x936\xca\x08m\xfc\ -\xdd\xe5\xfdj.\xa9\x89\x1f\x95[\xa9\x0b\x89\xa6~\xf9\ -\x9c\xbah]\x9c\xe2\x9d\xc8\xff\xa8\x05]R\x85\x06\x19\ -\x17\xcb\xa0{5z\xe7B\xecu$Li\xad\xa6\x89\ -\xb1n\xb7\x19EE\xa9\xc3\xc8\xc01\x1e\xef\x00\xe5\xc3\ -\xec;\xb6\xe0H\xe4\xf7\xa4Z\xee\x087\xf7\xba\xe1D\ -\xe7*\xb9\xc3\xb34\xa7\x02Q\x96\x91\xc9\xd8\xd4\xb0\xdb\ -\xedADI\xf1R\x94\xe2\xb5\xc2\x03\xfc\xc0u\xf6r\ -`\xe0\x9ep\xff\xc9\x10\xf4d\xcd^\xf2;\x15\x97\xb8\ -\x0ej\x02\x81\xd6\x06H\xe9U\x83\xa8\xdfy'\x9f\xab\ -\xef\x82\xdc\xbe\xc2\xc79\xa8\xf8\xfeD\xae\x97\x00\xf8b\ -R\x94N\xb8x\xa1\x19/M\xf5\xe2\xa6:u\xd0\x13\ -\xae^q\x0e\xe5\x8b\xdd\xab#\xc8\xc5\x89\x1f\x91\x91=\ -\x8b\x8e\x1dX\x1e\xca\xcfG\xf9y\x13\x00at\x97\xbf\ -\x83|\x95$\xf5\x00\x9enx\x02\xee_^@\x07'\ -\x16\x8d\xefY\xe9\xc4\xbek\x10\xa53\x04s\xfb\x97,\ -\xd49c\x01\xd2\xc2Truu\x09\x8b\x13\xa9\xc3\xda\ -/\xa9k&\x22\xe5_QGP\xe7\xc2\xd5C\x08\x92\ -\xaa\x82F\x14v\x05\xe5]\xc6b/c\xc1W\xb0\xd8\ -8\xd7\xff\x86\x87u\x82\x9b\x13\xcbE\x89\xde\xa2\x88\x1a\ -/j&P+\x7f\x84:\xf7\x9e\xf8\x8a\x88l\x094\ -\xf1\x02\x8dZ\xb2\xa9S\x09 P\xa3F\xb7\x98\x82\xeb\ -U\xd7N\xa5Ub\xda:\x90!\xbd\x97g\x1c\x14\x00\ -\xb4R\xeaUQ\x87\x01@X{\xf2\xfb\x04\x84#\x04\ -P\xf4\xdd\xe0w\xa7\xde\xb4\xf0\xe0)!\xe2\x16\xef\xaf\ -a\x18\x87\x84Q\xaf\xc3\xba\x1ap\xc9\xe0\xd4=L\x8b\ -3\xee\xf8{\xbdb\xb9Z\x14rk\x03\xfcN^\x22\ -I\xf7\x80\xfbV\x88Vog)W\xe0p\xab{Z\ -\x0f\xa8U\x95\xb0\xb7&\xe0X\xbe\xd2z\xc7+Tz\ -\xa6\xb5\x01=\x0f\xbf\xe7\xef^\x97\x10\x01@\xeeB\x84\ -D\xcaG\xe9\xda>\xadrj5!\xc8F\xd4\xe0I\ -;{\xc3\xb8\xf1\xb0&~\x90\x88\xce\xf0\x19\xd9\xb1<\ -u\x07A\xf2\xb0\xee\xa8&\x83\xf8\x8c\x0eTRg\x11\ -\xd7V\x8e\x98'\xa2\x98;\xec\xed\x15,\x99:B\x0e\ -\xadhB{\xdb\xd7I\xa3\x16\x5c\x09\x99N\xe2\xd0$\ -\x86,\xf6JI\x97])\xd6\x5c=RDL/\x16\ -0\xe4\xd6{\x9c\x82\xdcC\x80\xe48\x1e\x22\x0e\xeb\x88\ -#\x97\x8d\xaf\x9f\xe7\x814\xa1\xb5\xf8;Y` \xf9\ -\xbd\xe6\xd3yPgI\xce\x9aD\xbap\x7f\xb8t\x0d\ -F\x1c\x00\x89\x05\x10q(]\xe2V\xcf\xf43\xa0Q\ --]\x1c\x96\x13\xcf`ky;\x19\x22\x9c\x06\x01\xce\ -\xe0\x99\x02Z\x0a\x86\xffD \x80Q\xedNV_\xe5\ -q\xed\xf5\xd3\xa6\x8d\x07\x18\x86\x96\x9e\x9f[\xc9\xec\x1b\ -+\x9b\x7fg\xe5\x0bo\xadl\xe15\xe9\xa2\xa6\x88\xef\ -Y\xee\xd8-\xc6\xf1\x84\x90\xaa\x89 -\x09{L\xdd\ -\xad\x0a^\x00\x00\x8f,q\xcc^i\x1daZi\x9e\ -\xab \x92\xf25m\x8f\xd2=\xe5{\xab\x81z\x9f\xa4\ -T\xb2j\x1c\xa5C,\xdd\xb3\x09\x04\xe7\x00\xc0P\xe2\ -\xf5\xec\x8cA<\xff\x1b\xe3\x8e\x82\xc3\x0d\xb9\xa5`\x94\ -\xa7]8Y(22\xb8iQ$\xd7\x89\xe2\xf8\x06\ -\xf1\x5c1\xfd\xaas\xeb\xb9r\xe5#[\xc8\xb6\xb3\xf0\ -\x5c\x00\xa0]\xc0jx\xa4\xb0\xa1\x87rm\xe5\xf0 \ -\x11\x88Q\xde\xe8\xa1\x15\xc0\x88\x0b\xe51\x00MD\xfb\ -\x00\xd5L\x02b\x98\xaa\xbcU\xae\x09\x85\xe8\x06]\x83\ -Du\xca,\x1f\x81\xb8q\xd3\x92\x0a\xdec\xd9j\xa8\ -\x98\x88b\x13\x9b\x97\xce\x17NV\x19$O\x92Z\xd6\ -\xf9\xf9*\xb2aIm\x88\xa6T\x11\x1d\xf9\x9e\xcc\xef\ -5\xc3\x96\xc2g\x92\x9b\xf8l\xe3\x12\xa0\xd0\xfa\xc7,\ -\x03\xa14\x0c\x8b\xd0\xc0\x9d\xaf\xa1{ \x1b\xb5X\x94\ -\x1f'\xf2\x84B\x925C\xa8\x850m3\x1fF\xf9\ -0\xff\xfc\x99{V2\xff\xc4\xca\x17\xc9\xf9\x97\xdfX\ -\xe5\xca;\xd3\xf1\xf9\xb5\x1b_[\xc3\xf6\xf7\xd6\xbc\xfb\ -\xb3\xb5\xec\xfdb-\xbc6\xf2s\xed\xd5\xaf\xacrU\ -{\x04\x9f\x93\x1e>p\xdb\xd4\xc5\x1f2\xbb\xb6\xe0\x06\ -xb\xe5\xea<\x9f\xeb<&\xe5\xb7\xf1\x9e1Jn\ -;_\x16\xc6\x0biB\xc8\xb9~\xac_n_\x93:\ -i\xea\xaer.)\xf5\xaa\x09\x98=\x7f\x1em\xec\x95\ -7\xd0l\xa1\xc2\x08\x1e\x12\xe5{\x02\x00\xd2\x1d\xd9\x83\ -\xe9\xc3\xd2}\xbd\xcb\x969\xb0\x86\x8b\xd7\xf6.\xdc6\ -\x96Z\xac\xd7Q,\x1e\xa5\x87\xfbp\xe9\xbd\xc4\xef\xbe\ -\x15\x00\xb1fy(1\x0f H\xa2\x10\xbf\x08\x8c7\ -\x1b\x00x$\x88\x94\xa7[\x80 l\x0c\x1cX\x8ev\ -\x09+c\x807D\xf0\x08Y}\xea\xc6\xa19j\x11\ -\x17\x11\x18\x89&+\x18\xe4\xa65O\x1aW-\xad\x1e\ -\x16[G\x1aS\x8f4.3\x08kN\xa1Z4Q\ -\xbb\xd6\x0bI&\xee\xa6t\xee {\x96\xda\xb5oi\ -\xddG\x96\xd6s\xfcI\xd2\xf99\xbd\xeb\x10\xa0\x1f\xe0\ -\xed\xf8\x8c\xce\xd4k\xd39\x00\x1b\x1e0TE\x030\ -t\x0fI\x0ch\x22\x03\x1b\x8f\xc7\x88\x97\x07\xd1D\x0d\ -1=]S\xb6jJ1r\xcbr&\xeeX\xc1\xec\ -C+[zaU\xeb\xef\xacn\xebKk\xdc\xfd\xd6\ -Z\x0e\x7f\xb0\xee\xeb\xbf\xda\xd0\xed\x7f\xb2\xb1\xfb\x7f\xb7\ -\xa9\x87\xff\x86\xfc\xbb\x8d\xdc\xfd\x17\xeb\xbb\xf57\xeb8\ -\xf9\xa3\xb5\x1c\xfch\xf5;\xdf\xb8\xad\xddej\xbe\xad\ -\xbe\xcb#\xd7\xf1\xba\xbb\x8e#\x880:n\xc0\xd8H\ -\xf9)\xed\xc4\xf4V\xa4E\xf3\xfa3.\x1bI\xd3L\ -%c\xe6\xc3\x10\xfc\xad\x8c%<\xc3\x9b\xe2\xdd\x01H\ -\x9bn\xfc\xf4,\xee\xd0\x0b\x9eC\xab\x81nE\xd0\x89\ -W\x15\xa4mc1iX_\x9a\x9a)\xb5M38\ -\xb3\xa47j\xf4\xb0\x82\xcb\xde ^o\x13\xb7\xb7\xad\ -x\x0c\x00@\xecB=K\xae\xe1S\xa8\x9b\xcf`\xbd\ -\xd1\x01\x800\xb8\x86\xac[\x0e\x9eA\xed_\xdc\xe9\x97\ -d\x0cY=R\xfe\x9e\x8bw\xe1AR$\xeduW\ -\xca\xa4\xfd\x80\x10\xc9\x00\xdeF\x0bEnZ\xd3mS\ -\xd2\xea!\xee\xb0\xe7\x08ph\xe3\xa4:Z =\xd7\ -\x01\xca1!E\xfb\xd9\x0f\x9c\x12\xd2\xba\xd5\xa6u\xd7\ -\xbd\xa6u\xeb\xe7}~F\xb1\xdd(\xba\xf7\x1a.\xfa\ -\xa6\xf9\x07\xce,s\xe8\xaee\x0e\xdf\xe3\x15\x19\xbc\xeb\ -~\xe7\xeb\xbf\x89\x05_G\xae\xc1\xe4\xbd\xf63\xea\x98\ -\xe1\xda\xa7\x00\x12_\xc7>\x83\x0f8\xf0\x22)\x02\x9a\ -S\xfc\x9e\xfbl\xf6\xd0mr|\x9d\x9f\xf0\xd4\x8a\x17\ -\x9e[\xc5\xca+\xab\xd9xg\x0d;_\xa0\xd4o\xac\ -\xfd\xe4{\x1b8\xfb\x83\xcd>\xf9\x9bm\xbe\xff?\xed\ -\xe0\xeb\xffa\xc7\x1f\xff\x1f^\xff\x1f[{\xf7?m\ -\xea\xe9\x7f\xb3\xa1{\xffj\xbdg\x00\xe1\xc6o\xd6t\ -\xf8\xbd\xd5l~ne\xcb\xcfM\xcd1\x9c'pe\ -b\x22\x87b\xf3(\xae\x05KGt\xa6\xb3\xeb*\x06\ -I\x0f\x02\x90l2\x8b0\x86\x16\xc5\x1b\xe5\xf2\x7f\xd1\ -!\xd5D\xaa\xf4\x8c1\xeb;a\xcc~_\x17\xb8t\ -n`\xca\x16P<\x04S\xe2J\xc2RT\x0e\xed\x8a\ -\x0f\x87\xb9\xc8\x08\x17\x9f\x80\xf4\xcdY\xc1\xc8*\x8a\xdf\ -p\xca/\x1c\xd9\xb4\x1cu\xfc\xc0Kdv\xcc\xb9\xb2\ -\xf1\xac\xce9\xcb\x06\x08\x02E\x08\xcf\x11\xc2;dk\ -[\x18\x8a\x15w\xc8\xee\x917\x808\x92\x1a\x85\x05\x82\ -\x01\xd2$\ -\x22\xad|Bz\xf9\x84\xf8\xfa\x98l\xe3\x01)\x17\xca\ -\x84H\xf9PXz\xdf\xa1\xa5\xf5\xa2\xf8\x9e=\x14\xce\ -\x83\xaa\xb8\xa2\x1f\x05\x0e\xde\xb2\xac\xe1;\x16\x1a{`\ -\xe1\x89'\x963\xf9\x1cy\x81\xab~\xce\xef\x9eX\xd6\ -\xc8\x03\xc0p\x87\xf8-p\xa8y\xc4]~\x7f\xdf\x22\ -c\x0f\xb9\xc6C\xc0y\x8f\xdc\xfe\xcc\xd4>\xc5\xdf\xcb\ -w\xc2\xea%\xb2z\x1dI\xaf\x13\xc9uRJ\xe1\xf4\ -c\xcf\xedc\xbd\xd5k/\xacn\xe35\xee\xfd\xad\xb5\ -\xec\x7fn\xfd7?\xda\xf2\xf3?\xd9\xb5o\xfe\xb3\xdd\ -\xfb\xe5\x7f\xda\xa3\xdf\xfe\x7fv\xe7\x97\xff\xaf\xed~\xf5\ -\xbfl\xf6\xe5\x7f\xb5\x91G\xfff\xfdx\x86\xae\xdb\x7f\ -\xb1\xd6\xeb\xbfX\xdd\xeeWV\xbe\xfa\x92Pr\x97\xf4\ -Y\x00P\xb6\x80g\xd4^I\xc5\xfb\x06H\xb2\x0aC\ -q\xfd>\xb8@\x10p\x14\x10R\xab&\xaf[\xed\xec\ -M\xab_<\xb3\xfaem\x16\xb9m\x05\xae3\x99\xb8\ -\x05 \xe8\xd7\xeenU\x1c\xe9\xccGyOo\xceA\ -\xbd\x1eD \xd5\x85]\xfb/c\xbcs\xf14E\xda\ -\xcd/\xbd\xcd\x1b\xd9]S\x967\xb8\x04[_\xc7\xfd\ -oZ\x01\xec>\x82r\x03\xed\x0b\xa6\xa3N} \xd3\ -\xdf\x0a\x83\xd7\x9a\x80\x96Fubx\xd7\xa2i[\x98\ -j\xed\xb4\xd9SS\xc1\xd9 4D^\x1c\xc6\x13\x84\ -\x05\x04\xe5\xc9\xbc\xcf\xe2w\x0a\x0f\xfe.\xc4mNU\ -C\x04\x94?\xae-\xd0\xb8D\x9dJ\xb2\xfc\x1e\xf9\x9c\ -\xf7\x9f[\xde\xdc[\xcb\x99za\xd9X\x9f\x94\x97\xce\ -\xc3\xa5\xe2.S\xb1\x964\xbeG;\x85\xb5\x9f>{\ -D\xdb\xb2\x89\xabSO\x19\xd0W\x96\x0f\x01\xcb\x9fy\ -c\xd1\xa9W\x00\xe2\x99e\x8f=\xb2\xe0\xe8}\xe4.\ -\xdf\xa5\x06\x12j'\x83\xf5\xcd\xea\xb3/\xf9\xbfgX\ -\xf8#R\xbb\xbb\x00\x0e0aQjH\x91\xcdkh\ -\xf8&\x008%\xfb\x81\xec\xe1\xfe\xd5\xd2F\xf3\xffe\ -\x0b\xf7\xbc\xcd-\xab\x0f\xadv\xfd\x91u\x1e\xbc\xb2\xb9\ -\xfb\xdf\xd8\xe1\xfb?\xd9\xe9\xc7\x7f\xb1{?\xfd7\xbb\ -\xfd\xe3\x7f\xb7\xdd/\xff\x8b\xcd\xbe\xf8W\x1b{\xfcw\ -\x1bz\xf87\x00\xf0'k\xbe\xfe\x93\xd5\xee}ie\ -k\xdc\xc3\xccmWk\x18\xe8\xc63j\x8e\x00\xcf\xac\ -\xfe\xc5\xaaYL\xab\x1buk\x11\x99\xad\x8b\x16\xc1\xbb\ -V\xa0\xfc\x8e\xf5\x07\xd6\xbd\xf5\xd0zv\x1eZ\xf7\xee\ -CkX\xbd\x0d\xe9\xbc\x06@\xd5R\x06\xc0\xaa\xbf\x03\ -^X\xfd\x91\xdcz\x01)\xa1\xb2\x19\xafHD\xa5\xfa\ -\xfd\xe8\xbc\xcfb\xb4\x1a\xe7\x8eM+\xef0\xf5\xecM\ -\xab\x1b\xb4`\xeb\xa4Eq\xf1\x05\xc4\xfd\x02b{\x1e\ -9oX\x04\x91\xb8\xe4\xe6\xcd\x9b\xd4\xf1s\x06 \x00\ -\x06\x15Nj\xaa\x17\xb2r!\x81vZyEb4e\xaaY3\xf5\xdf\xf7\ -\xf6\x07\x8eZ\x00\xc5\x86\xb1\xe2(\xa4.wp\x97\xf8\ -N\x8e\xaf\xc9 \x15\x83\xb4\xaf\x00\x84e'R\xb2$\ -\xa05u5y\x80\xb4\xf8\xb4\xc2F\x9c\xf2\x93^f\ -\x92\xda\x04A\xa0\xe2U\x08\xf6\x1cBY!\xc0\x10\xc2\ -u\xabN^9\xb1*du<]t\xea\xb1\xe5\xa3\ -\x8c\xe2\xd5w\x0c\xcaWV\xb3\xff\x9d\xd5\x1f\xff\x8c\xfc\ -j5\x07?\x03\x88\xef\x00\xc1\x07\xcb\xc1Cd\xa1h\ -?nY\x0d\x0eTD\xa1FP\xb2T\x1db%\x17\ -\xed\xf5\xe6y\xeeZ\xb4\x14L?\xb3<\x94\xaa\xb2\xac\ -\xf0\xe8\x1d\xbc\xc4\xa9\x93\xd0\xe8\x99+\xe3\xca\x9b\xd2\xe7\ -\xb96\xd7\xcfS\xd9\xd6\xd8]\x94\x8d\x1b\x1d\xe2\xfb\xe0\ -.9\x83\x87\x08$V2\x84\x0c\x8b\xd0\x1e\x02\x06~\ -\xcfk\x0eV\x9b3\xb4O\x06\xb4\x03\x09\xde\xb4B\xb2\ -\xa1\xfa\xd9#\xeb]\xbfe#\xbb\xf7l\xea\xf8\xa9\xcd\ -\x9f\xbe\xb5\xa9\xd3\xcf\xdd\x99\xc7=7\xbe\xb4\xce\x1b_\ -Y\xdd\xde;\x80\xfe\xcc\x0a\xf0 \x11,:\xc88{\ -\x0aSY\x9e7g\x7fQ\x09\xa4\x92\xf3,\x5c\x7f\x8e\ -\xf6\x08\x8e\x01\xb2\xa5\xfb(\xfe\x09 \xb8kmk\xc7\ -\xd6\xb4\xb4c\xa5c\xf2\xbe:\xebh\x12\x12I|o\ -\xc1\xddkvWS\xbex\x91X\xd2\xec+(\xff\xb2\ -\xa6\xcdK\xdb\x916\xa4\xd5b\xdcVb7\x0b\xa6\x8b\ -\x8d\xc3,\xb5\xda\xa5m\xde\xdb\x10\x0b\xf5\xf7\xc1\xad\x90\ -\xaf\xe6\xf0>\xacF\xd1}Z\xe8!\xbe+\xc6#\x22\ -|\xdaQ\xac\x93\xc2u\x5c\xbc\xda\x95f\x00\x00\x1fi\ -\x8c\xbfy\x110\x01\x12\xd2\x9b`\x1b\x1c\xa2}\x1d\xee\ -\x00B\x01\x81<\x80\xce\xc7W\x85\x8c\x00\x903\xa5\xbe\ ->x\x80\xe5\xd7V\xb6\xf1\xc1\xaa\xf7\xbe\xb1\x86\x93\x1f\ -\xac\xf1\xba@\xf03?\x7fo\xa5\xa4P\xf9\x0bo\x88\ -\xebOP \xf1zH\xe5U\xb8h\x80\x14Baa\ -b_\x0e\xdf\x17E\xb9\x12)2\xcc\xef\xdd\x89\xe5\x00\ -N\xdb\xdf\x83d%j\xce\x90\xa5p\xe4\x08\xea\x89S\ -v\x0e.^$J\xc7\xde8\xce\xd2\xb7G\xd8#|\ -\xe1F\xc3<\xa3\x96~\x95\xe1h^?[\x13cX\ -bXmb\xfa\x0f\xf0j<\x0b\xe1,\x0b>\x13j\ -_\xb3|\xdcx\x19VXIz\x5c;y`m\xcb\ -7\xadu\xed\x8e5\xae\xdf\xb3\x86\x8d\x87p\x06\x1d\xbf\ -\x03\xd7\x99VS\x8ec\x94\x0f\xc9\xe4\xfb\xd5\xd7\xd0M\ -\xdf*^\x9f3wu\x15\xd7\xb6r\xf1\xa9(\xba(\ -\x9c\xd3\xfeC\xb7C\x18\xb9\xa2\xb9\x16'\xdd\x16\ -\x8b\xc4x\x95\xa5b\x87\xc4\x9d\xe6U\xd2\x10\xcd\xf9\x13\ -\xafq{\xb9c\xa7\xae\x9dI\xde\xf8\xa9s}9Z\ -\xf0\x18\xe4ox\x04\xad\xf8\xa9\xc5K\xb6\xa6\x88\x19 \ -\xcd\x1c\xba\xe9M\x1e\xc2\x87\xe5\xfb`\xf6~r\xf4L\ -HH\xb0\xc3k_\x9aE\xba\xa6\x13\xc54_\xaec\ -\xe6B\x1al\x07\x80;X\x81\x5c2\x96\xb8\xf8\xc2J\ -\xd6\xdfZ\xe5\xee\x17(\xfe#\x00\xf8\xd1\x1a\xaf\xfdd\ -u\xa4W\x95\xdb\x1f\xadd\xf5K+\x5cx\x87\xbb~\ -\x89\xc5B\x14\xc7\x94B\x9dy\x8a\xee\x97\xa2Q2\x1e\ -&S\xfc\x82\xeb\xfa\x00\x9e\xb7\x1d\x0bbE\xc6!\xd1\ -|\xbc\xee\xd3\x8f\xb2\xbc\xe3\xee\x95\xba\xa2\xc0s\xc9\x86\ -[8o\xc5\xefC\xdcw\xf6\xb9d\xf1{\xcd\xe0e\ -\x13_\xdd*\xe0\xd8M\xcbgl\x0a\xc6\xce \xcd7\ -\x09\x95x\x0cy7=\xaf@\x8f\x01dq\xad\x02<\ -C\xe9\xd8\xbe\x95M\x1d[\xf9\xec\x0d\xb7'Rk(\ -Yx\x0e\xb5\xb6\xf1\x03,\xd5#\xaa\x0c\xed\xf7g3\ -\xebg\x1f\xd7\xcd\x04\xb0*\x22\x89\x8e\x9fY\xfe\xe4\x1d\ -\xc2\x8e\x1aB\x12~F\xf7\x08\xd5\x10\xf0\xf6)\xf3\xab\ -\xd95!\x5c\x07g\x5clp\x89G\xf1\x09*}?\ -_]\xd4\x8c\xa8&\xbe\xe2\xabF\xdd$X|\xf58\ -i 9dz\xfb\x06\xeeG\x95\xbd\x07\x16\xc4\xb5\x86\ -\xd4\xb4Q\xb3Z\xd3\xeao\x83\x90\xa7\xe6\x81<\xb5\x88\ -\x8f\x0c\x03\x00M\x0bk\xb5K\x0b\x22\xbd\x9a\xf0\xb9\xf0\ -\x00\x02\x80D\xef\x19Xr\xf3\xac\xae]\x14\x8e\xb2q\ -\xd3!Y\x8a,\xaf\x8fl@Y\x01 \xd3I\x98\x11\ -\x1d'\x0f\xb1\xcaQ\xf7\x8b\x99\xfb\xb8\xc5GV\xa2\xa2\ -\x0a\x98u\xed\xc1\x97V\x7f\xf4-\xf1\xf2{\xab\xdd\xfd\ -\xc1\xaa\xb7~\xb0\xaa\xab\xdfY\xd5\xda7V\xb5\x02W\ -\xc0#\x94(\x96\x03\xa2( \xd05\x82(O\x1bJ\ -}*\x84\xc4\x82TC\xef\x8e\x9e\x11\x03Vl\xe5\xd5\ -m\x8f\x82\x15\xa7\xab\x00D\xde\x0a\x90\x04\xb8\x7f\x85\xb9\ -,@!\x85\x87\x00\xac6vfK\xbaP<\xcau\ -^\x83\xfb\x8e\xc2\xb6\xf3\xa6t\x14\xfd\x03+\x9d{\x84\ -R\x91\x99\x07V\xacf\x0ej\xea\xa0\xb0\x841\x05Z\ -\xe1A\xe4\xf69x\xcd(\x9eC!5\x8a\xe2u\xfc\ -\xbc\xca\xd0\xd4\xbcR\x85\xa7Z\xbau\xc5\xa1j\xdd\xe2\ -j\x04w\xd1\x87\x00BZ\xcc\xf7\xa9uO\xf4\xd3\x89\ -\xa1\xea\x12\xa2if\x9e\x15^\xe0\x87\xe4i\xc9:\x19\ -\xe5&Vj\xba[\xa2\x121-x\x0d\xbb\x95C\xd7\ -oA\x93m\x9a&\xc6\xbbx\x15\xe0\x0b\x16\x93\xc1\x85\ -|*\x14\x84\x90\xb9\x1e\xbc(?4\xa6C\x09E\xca\ -\xb0\xc89d\xf6!\x17Vy\xb3\xdc\xacn^^\x02\ ->\xa0\xee\x1b\x9dX\x92\x8a*qS>\x1eB\x13\x19\ -\x99\xce\xd2\x15\xe7\x09\x1b\x903\xb9\xd6\x1c\xb9gD\x84\ -*\x0c\x9a=\x11\x07\xe0A\x5cw2\x91A\x84\xf7\xaa\ -\xb2\xd5\xe1T\xc5\xcb\x8f\xacb\xe3\xa5\xd5\xec~\xb0\xfa\ -\xfd\x8f\xd6p\xf0\x935\x1e\xfcjM\x07\x7f\xb0\xe6\xfd\ -_\xacy\x17\xef\x00Y\xac]\x837\xcc\x93\x9bc\x1d\ -\xea\x95\x1b\xc1}\x87 \x9fA\x94\xea\x17aE\xe1\xa9\ -\xc4T\xad\xa2\xb9\x83\x15T3\xc7{W\x17H\xbc\xcd\ -`\x00\x03\x84/\x852\x85\xb5\x10\xb9\xb52\x96\x08\xf7\ -\x1f\xd1\xe6\x0e\xed4&\xb7\x0e\xcb8D6\xa5`\xac\ -_\xcd!\x0b\xb9\xcf\xd2\x85\x07\xae\xe1d\xd5\xca\x132\ -\x02\xd2\xc3y\x5c\xbc\xa6{\x19\xcb\xec\xdec\xc6\x83\xf1\ -=\xaf\xc3S\xbb6\xe7\x99\x5c\x0a\x8c\xcb\xe7\x1e]\xc1\ -\x86f\x01\x05\x00\x8cF\xfd|\x95~\xfaU<\xaa\xbe\ -\x81\x18\x89k\x14\x05\x00\xa2\x02\x80\x80\xa0\xfe\x82xh\ -\xe5\xffa\x0c*\xc8\xff\xa9\xdcK\x07k\xa8G\x90&\ -yRk\x09!\xb5d\x13Hr\x1d\x06\x80\xb7O\xaa\ -\x9f5\xd5\x81z\xc7\xd0\xaf\xea\xf8\xf8C\xf3\xf3\xa0j\ -\x17\x17DQ\xd9\xa3\x10$\xac\xc9\x03\xc0\x13R0\x04\ -\x00\xe4\xaa\x9cI\xad\xcc5\x89\xa3\xd50m\xc7\x86\xf0\ -\xb9\xeeYn\x05Qnu\xcd)_\xf1=\xc2@\xe5\ -\xe2\xde\xf3\xf9\xae\xfc\xc9{^c#\x90\xab\xa6\x88j\ -\x94\xa4\xd2(\x1dT\x1d\xd6r\xaa\x13\x06\x17Q\xbbt\ -\xcd\xaf\xe7N\x9d\xc2\xce\xef\xbb\x06S\xd5[o\x01\xc0\ -\xd7\xd6D\x18h9\xfe\xc5\xda\xae\xfd\xc1\xdaO~\xb1\ -\xf6\xa3\x1f\xadu\xff\x1bk\xdc|o5+\xcf\xac|\ -\x0e\x8b\x04\xa4y\x90\xb5(\xa1)BX\x0aAP\x83\ -d*\x01W\x9a\x86\xe5\xbbM\xab\x12\xf2`\x94\xaf\xc9\ -\x15q\x17-|\xa9\x0f\xaf\xb8\x8ebm..=\x17\ -\xb2(\x89\xc25\xd4s/\xa2T\x15#\x11o\x08\x13\ -\x0eU\xe1\xa3\xa5\xf0\xa2\xf9[V\xb1z\xdfj6\x9e\ -X\xfd\xf6K\xab\xe3~\xab\xd7\xc9f\xdc6\xf7G\x80\ -\x1e\xf2\xd9\xa7.^\x8c\xb3\xfa!\xbb\x1a@\x00\xc0\x98\ -\xb9\xf2n\x09\x5c\xe9\x1f=\x824\xf1t\xe0\xda\xc5\xa9\ -e|\xa6v\xfcb(\xd9j0%O\x80\xf2\xd5\x9f\ -\xb0\x10oY\x04 \x0a\x09\x9f\xb9\x10`\xb5\x83\xcd\xec\ -:\xc4\x10w\xe0a\x80\xac\x89\xf0\xd7\xb8\x82\x97#\xf4\ -\xa1t\xb7\xff\xb0\x19\x80\x9c\x83-\x15o\x13\xe3\x07\xa1\ -\x01\x10\xae\x06\x85\xbf\xef\x16\xa6\xc6D\xd1iX1!\ - \x8a\xabS?[m\x8f\x0a\xf4\x90^\xc0\xf8\xbd\x1e\ -\xc2\x9a\x9aT\xcd\xf9\x02qU\xde@\xb3\x80\x22G\xc4\ -+)\x1f\x96]\xc8\x0d\x16\xcd>\x22%{\xec\xda\xa8\ -\x16p\xd3r\x9d\xea~)@\x85G\x09\x05\xa3\x84\x87\ -QB\x0b\xccZ-\xde\xa2\x137`\xef:{@]\ -\xc6\x1e[5^\xa0~\xf7=\xd6\xff\x855\x1f~m\ --G_[3\xef\x9bv\xdfY\xc3\xd6K<\x00\xd6\ -\x07\xa9*\x9b%\x1d\x9b<\xb6\x02\xbe+oh\xc7r\ -\xf1TQ\xd2\xa1\x88Z\xd5j+\xf8\xf9I\xe6:\x8b\ -/\xbd]\xa2z\x87\x157\xf9\x92\x8d\xf2#R>\xc0\ -\xcc\xbdX\xdcQ\x96\x00A\xcd\xd5\xe4\xd4\x08F\x01\x10\ -\xb4\x0bY\x00wK\xe4|\xb7\xba\xa3G'w!u\ -\xd7\xadr\xe3\x1e\xec\xfe\x855\x1e~\x0e`\xbft\x8d\ -\x1cK\x97IE\xd5\xc0Q\x13ZC\xa4\x97\x03\xe7^\ -A-lTz\xee\xaau\xe6=q\x0bsZ\x95\xbd\ -\xeaJ\xd4\xb5\xc7\xc2\x8f7\x0b\xe0\xea\xd51\x5c\x8d\xa3\ -U\x7f\xa0\xc3\xba\x0aT\x83\xb8\x84\xb7YQ\x152a\ -p\xde\xe3D\xe1\xa1{\xdc\xd7-\x80\xc05:\x0e \ -\xf4\xf0!\xb5\x8dk\x13\x1f\x02`\x18\xa9\xe3\x1ax\xa1\ -4\x80\x18\xa3\xce\xdc\xea\xc5\xaf\xa6\x0ajJ\xa4n\x95\ -j\xb6\xac\xadN\x8a\xcb\x12u\xab\xcc\x06\xf1\x99X\x95\ -V\xf9>mi\x96(\xfe\x80d\x95SkbG\xe5\ -\xce\xae\x7f/\x00\xc8\xe5\x7f\x0b\xa6\xef\xe3&q\x89\xf3\ -\x8f\xadx\x01\x99\x7f\xc8\xcf\x0c\xec\xa4\xb6L\x1d\x02\xaa\ -\x1dR8\xed\xba\xb9\x0a)\x22\xee\x8e\x90N\x01\x88\xbc\ -\x89\x13\xc0s\x93\x07;3\xf5\xf5\xab\xbe\xfa\xd8j6\ -\xd5\xdc\xf1)\x16\xf6\xc4j\xd6\xef\xe3r\xf9\xdb\xe2u\ -\xe2\xef\xb1\x95L\x1f\xa0|\xb5RQ3jdt\xd7\ -\xf2G\xbcfV\xf9\xc3;\xae\x99\x85\xd6+\xc2\x5c+\ -\xab_\x0d\xa3\xe1-X\xbd\x0a]\xdc9H\x03\x80O\ -\xd9\xce(\x04M\xaeUm\xd8\xf0^\xb9\x84\xc3\xe8\xa8\ -Z\xb2\xe1\x01\xc88\xc4e\x82\x90C1sm\x8f\xf7\ -w\x91\x9f\x0f\xadX\xde\xcc\xae\x95\xae\xdc\xb0\xea\x9d\xc7\ -\xd6x\xf4\xce\x9a\x8e\xbe\xb2\x06\xbcV\xed\xf6Wx\x83\ -/Q\xd2;+\x99{\x89\xc5\x12R\xe5a\xb1j\x11\ -JM\xfbj\xeb\x5c2\xa9\x9e*v\xdc\x16\xeeFm\ -\xfeP\xfd\xbf\xc0\xcau\xba \xab\xdc\xab:\x8e\x85\xe4\ -\xdd\xc6\xafaH\xb7\x01\xc0c<\xcf+\xab$\x04\x96\ -\x09h\xb3\xaf\xf8\x9b\x07\x82P\x1f\x9e\xbc\x87\xd0\xda}\ -\x02\x7f\x01\xb0\xf0\x8a\x00\xbcLaZ\xba\xca\xd0\x0c,\ -\xde&&\xb5\x05\x14\x8a\x08\xb6ijV\xb5\xf1|P\ -\x08\x17\xa3\xd6\xec\x1a\xa2\x03\xa5]/~\xe2\xaak \ -\x0dR]\xcd<\xaf\xaa\xa1\xd7\x97\xa9\xab\x95f\xf5\xb4\ -ARiYD\x00`\x10\x05\x80b,\xbf\x14\xe5\x97\ -.A\xee\xd4\x1eN\xfb\xea&D\x02a\xb8}\xc4\xe9\ -\x9ey\xf3!\xfe\xdeE\x00H\x0a:\xb4\xc1\xa0o\xe3\ -AP\xe8\x14\x8a%\xaf.\x9dG\xc9\xf3G\x0c\x22?\ -3\xd8\x85\x13\x1b\x967\xba\x82R\xd5\xe4q\x9etl\ -\x8eM\xb0u*T\ -\xads/\x90\xc9\xb1#+\x9a9\xb32\x08s\xc5\xd2\ -\x0b+[|\xc58\xbdp\xcb\xd0\xd1\xe1{x*\xc2\ -E/\xe9q7\xf7\xdc\xb9cA\xb8G@\x04]\x99\ -\x10^'M!\xa7y\x854\xb0^\x85\x89\xdaf\xa4\ -\xc5\x07m\x1fRQ\x08\x08\x87\xf5\xea|\x1e\xb7y\x81\ -\x87\x96\xf2\x1dq\x91\x8b:\x97\x7f(\x9e\xcf\x00\x1am\ -x\x14p4\x80\xf2\x00J!\x8bp\xf9%\x0bZ5\ -\x83-\xabJv\xfe\x14>\x009\x1c\x96\xf5\xcds\xad\ -I\xd8/\x0f\x8a\xa4wL\xf0]\xda#8\xcfC.\ -\xe1rQ\xf0\xf0\x0a\x0a]\xe6u\x09E\xcc\xa3\x04\x06\ -\xbc{\x02\xf76\x02s\x1f \xce\xf5\x11\xe7\xd4y\xc4\ -;\x1f0\xd0>\xc2\xdf\xa7\xb0\xd6E\xcb\xd3Z\x06\x9e\ -\xa1l\xde\xdbgX\xb1$\xc2\x86W\x9a\x91\x85\xe3\xca\ -\x07\xbd\xa6\xd8^\xd3\x06\x89\x9e\x93\xe7\xd6^{\xbcb\ -\xa6\x04\xcf\x18D\x14\xda4\x85\x9d\x85k\xf6\x8e\xc3_\ -\xc2\xcd\xce\xf1\xf7Y\x9ew\x09\x00\x008\x00Z\xbe~\ -\xc7jv\x9e[\xdd>\xbc\xe5\xe0s\xb2\x97\x0fV\xbb\ -\xf7\xde\xaa\xb4=}\xfd9!\x01\x0f8\xa7\x19K\x19\ -\x17\xf1\x9e\xefImV\xe5\xce\x08\xe4\xd4\xebQ\xa0\x96\ -o\x92$\xde'\x93\xc7\xa7\xd6\x0c\xc2\xf2\x87]Q\xad\ -\x8ak\x83x\x1e5\xb7\x88\x02\xa0|xS\x91:\x88\ -\xc3\x0b\x94\x09\xe5\xcaS\x11\xa6Bx\xf6,\x9e'\x88\ -a\x070RM\xcc\xb9\xb2\xf7\xa69/3Bt\x22\ -Y\x8c+(lPQ!\xbf\xe0\x03\xaa\x1fO\xd3\x9e\ -s\xe5\xa0\x8e\xb1\x92\xca\x10\xdb\x03\xae\x94\x89\xdf!\xf2\ -\x14\x19\x9a\x82\xd5\xf2\xa568\xa0t\x1d\xe5\xa2\xe9X\ -\x1d\xe0\x10\x86G(gU_`\xf5\xd1-Y\x90\x00\ -\x86\xb9\x1b\xc4\x7f-\x07\xaf3\xa8s\xe4\xe7\xda\xec\xd0\ -\xcf\xc3w\x83\xfe.\x88Y\x0f\xee\xaf\x0f\xef\x82b[\ -\x87@\xec\x88Sh\xa0\x8d\x87o\x1d\x84\xad\xf7[Z\ -\x83z\x0duZ\xb2:\x96W\xb5Z\xa2\x9aV#I\ -\x95-\x96R\xd3\xce\xdf\x01\x02\xff\x17\xec\x99\xe1:\xab\ -\x90\xb0\x1d\xee\xe1\x18\x00B\xd4\x96\xe1\x09\x80\xb0H\xc7\ -\xdf\xc2A\x94[\x0b\xe0\xeeH\x15\x18tj\xf3\x85\xe8\ -\xac\x80\xab\x8c\x83J\xb77\xf9>\xb9|o\x1cT\xe7\ -\x97\xa5R\xf8\xdeU\xbc\x0698 \xcd\x19\xbbJ\x96\ -\x84WZ8\xb1\xd2\xd5;V\xb1\xf9\xc4*\xb6^X\ -\x05\x84\xb0|\xeb\xb9\x95m<%\xad}HVs\x0f\ -\x90\x90\xcbO\xebtvyY\xf1)\x18\xbb\xac\x9f\xec\ -D\x15O\xae\x96Q5\x8c\xc5:\xf9\xb3\xcd\x92J;\ -\x5c\x05uje\x8f\xa9\xb9Uz\x1d\xe3\xd0\xc0\x984\ -Ox@\xe8Z\xb1\x08\xa9x\x0e\xe19G\x13W\xdd\ -\x90pt\xa4\x0c(\x80>\xfd\x84\x93\x0c\xa5\xbb\xa4\xbd\ -idCi\xa4\x8b*p\xf5\xfa\x14MY\x8c\x8a\x11\ -\xd5IJ\x1d=\xdc6\xe4\xa6iWb\xec\xd5\x06\xc2\ -\xec?M\x96(\xdf\x07\x10X\x80\x8fTI\xadY\xb5\ -\x08\xa3<\xd5\xb5\x9b\x95\xe0\xfa\xb5\xef=B\x1c\x15\xdb\ -wm\xd4g\xd5J\x1dF?s\x0d\x8f\x00At\xca\ -'5\x93\xf2\xeb\xd5;H=\xeeZMG\xbaK\xf4\ ->\xa1\xaa\x8d\x1c\x96\x87\x97\x92\xcf%\xb1\x0a\xa9l\xc3\ -B\xf8{y\x0b\x83\xd5d\xf1\xa5\x8d\x16_\xd2\xe0$\ -\x91\x9f\x93\xf9L:\xdf\x19h\x1b'V/\xc2\x8c\xb7\ -\xdc\xa6R\xb5\xba)\xc1\xf3\x94\xcc{\x80,\x98Q6\ -\xa2~\xbd\x10[\xc0\x1b\xe8\xdc\xc5-n\x00\xbe5\x8c\ -a\x85X\xacs\x81\xb5cZu\xfb\x22j\x1e\x10d\ -\x0cZ\xaeU\xd1\x8b\xaa\x9f4\xef\x1e\xd1J\xe98\xfc\ -bj\x8f\x8c\x09\x02\xba\xc4\xb3\xaeB~\xd7\x1eX\xc1\ -\xda}\xcb_\x06l\x0b\xb7,:\x07y\x9bQ7t\ -\x91\xddm\xc2\x86\x88\x1e^\xb7U\xc5\x9a#\xa6vq\ -WT\xefX\xdcnW\x0a[\xbcR8$\xbe\xa8\xc5\ -\x12\x00D\x22@H*\x03\xf8\x15^\x8f\xe6Tu[\ -\xa9\xed'\xc5\x1dB\xc9c\x16 \xc3\x094M:\xf1\ -7jC\xcb\xb8[DJQ\xfd\xa0\xf6a \xae\xef\ -\xa2\x0b1^\x95\xb1\x9aG\xc6\xa8s\x94\x8eEI\xa8\ -\x1d\xb4\x04\x95\x86\xabq\x82Z\xb6\x02\x04U\xc0\xea|\ -\x9b\xcc\xf3R\xf0\xa0\xca\x9b\xfbq\x95}\x00@\x84P\ -=\xfd\x1c\x08p\xa5\x00A\x04R\x05\x92\xea\xa1/\x92\ -\xa7\x9e\xfbE3zU;\xf8=\xcf\xf2q\xef\x19(\ -H-V\xd5~5\xa1R\x1b7\xb4\x89\xe3w\xe2j\ -\xf9\xd5\x91\x5c\x070#:\xf9\xda\x89\x8aC\x9b\x90\x06\ -\x8b+\xaaGj-\xae\x10\xe15Q=\xff\x00\x80\xbf\ -q\xc8B\x9ds\x96;\xb8I\xfc?\x81 \x9eY\xf9\ -\xe2]\xe4\xbe\xcb\xd7\xd5\xd7\xbfp\x16\xc5\x90\x89hU\ -/J\xda\x1b\xd614\xc4J_\xdb.\xdeg\x8bp\ -x\x15R\xa6\xca!y\x82M\xc2\x9d6r\x88\xf9\xc3\ -\x11x\xc6\xc8\x90\xea\x1bD\x1a\x05\xe8m\x9ey\x0bv\ -\xbema\x94\x9b3K\x16\xb3p\xc3r\x90\xc8<\x06\ -1E\x18\x81\x8f\xf8\x87\xc8\x92\x08k\xbe>\x9e\xbf\x9b\ -\xcc\xa9C%fcn\xcc\xe3\xb0\xecX\x5c\xbe;C\ -X\x00\xd0)\xe2(^@\x88E\xe2\x0a\x19\x13^\x05\ -\x06w.p\x89\xc0\xdf\x04\xe8\x9b\x01D\x1b\xde\xa1\xc3\ -\xd2\xaa\xba\x10y\x89^KE\xd4\xf1,I\xfb<\xdc\ -^\xc1^\x070'\x15\x12t\x8e\xc4\xf1>F\x9b\x09\ -]\x17/\xd0\xa4N\x9c\x89 *\xd1\xed\xd2\xc5]h\ -\x07P'\xc4\xcc\x9d\x12\x86\xdb\x1bX\xc7\xda\x89)\xb8\ -.\xd7\xb3\x97T\xc8k\xd2\xbcK\xfc\x17\xa9\x22\x03\x18\ -:t{\x05r\xc7\x8f\x19\xe0#H\xc9>\x84\x85\xc1\ -\x19T\x87m\x1e\xbe\x1d\xf7\xd34lI\x5cO]-\ -\x13\xb4e\xab\x02/\xa0\xf3v\xcf\xc5\x9d z.\xee\ -\xe4kU\x03\x970\x08\xeaiX\xd4\xc8\xa0\xd4Yl\ -A\x0dRmW\x0a\xd4\xa5\xb3\x0awYg\xa9U\x1d\ -\x96\xd9\xa5T}\x10\xc3\xc1\ -[x\x0d\xf8\x03\x1e.gD\xab\x84\xaaoPg2\ -\xed\x13P\xe7\xd2U\x0b\x0c3>\xda\x96>\xca\xf8@\ -F\xd3\xfb\x16,\xa5\x0b\x86\x0f\xe8\x93ZG,\xa9\x99\ -go\xc2\x12\x09}\xf1\xb5\xbd\x16\xc7\x18\xc4a\xd5n\ -;\x5c\x09\xcaw\xd2\x06\x10$\xaa\x89$$\xa86\xb2\ -\xa8\x0d\x01\x14<\xff\x15\xc0\x7f\xa5\xb8\x8e\xf1\xa8\xf7\xbc\ -\x1f`H\xc2P\x92\xca\xf0\x9a\xe5xL\xb7\x0b\xaa\x07\ -\xe5kM\x80q\xbe\x98\xfc\x92\xa8\x18\xd6UCK\xfa\ --\xc6\xf5\xa7\xe3&\xd4\xc6\xcd\x9dD) \xd4\x0f\xe2\ -\x0aGp\x7f\xe3(l\x1ab4G\x1a\x02\x0b\xedU\ -\x1bw\xc8D\xcf\x92\xeb'\x94\x0e\x19r\x0d\x14H\xa5\ -\xdcA\x93\xa4S^\xd9\xb8\xd2\x15/\xe5\x0a1(j\ -;\x17\xe8\xd4\xa6\x0a\xe2P\xb3&`\x04\x00\xb9#\xae\ -\xa5\x9bts\xd6\xbf\x13\x1dq\xae]\xbc\xda\xc6\xed\xca\ -\xba\x19\x00\xed\x09\xc0\xfac\x0b\xeb=\xe5\xe7W\xd9\x95\ -\xbc\x0a\xa4\x9c\xf7\xe5\x00\xa0\xc6\xd2\xe1\x00\xd9m\x13V\ -\xc0u\xcbI!k\xc8:\xea\xd6\x9e[-\xe4\xabZ\ -\x1d\xcbI\x9bJ\x01@1,\x5c\x9dIu\xf2\xa9\xe6\ -\x1b\x0a\xd4\xe6\x1d\xce\xa2^>\xca\xd3\xb3\xfan\x00z\ -\xbc\x82\xaa\x92\x06\xcfH\x81\xd5\xd7\x87\x94Xs\x01\x00\ -@\x8bG!\xb2\x06\xad\x0dhu\xd4\xf58\x86\xc8\xa5\ -\xb4LXJ\x1b\xaf\x1d\xa4r\xb2p\x94\x9e\x88\xc2\xe3\ -\xeb\xb1\xf0\xda\x1e\x8b\xad\xe9\xc2\xdaQ(!-\x8ep\ -\xa6S\xcau\xa2xl\xa9\x94\xad\xe3\xe3\xbd\x9dM\x92\ -\xcb\x02B\xa9\xceg\x00$\xa5}\xbc\xaa`V\xbd\x0d\ -\xf47m\x81\x03\x08\x88N\x0bw\x07K\xab\xd1'\x06\ -#\xe2\xa8-\xe2\xaet\xfc|\xb2\xcbkE\xa7\x02R\ -@\xa8=\x06U\x84\x80s \xc4\xa8\xf7\xbf6M\xba\ -\xe6\x81\x17[\xb4\xd5\xd0I[\xb3\xf1\x06\xa9M#\xc4\ -\xc7Q\xdc\xf6\x18\xe4O\x9d9!\x14(3\xbd\x93\xfc\ -_\x8d\xa5.N\xe0\x22LHt\xea\x96\xd2\x15\xb5c\ -\xf1\xb7\xcd\xc2\xd4\xb5\xab\x96\x98\xd44\x06\xfb\x1c5w\ -b\xa7<\x0c\xae/Y[\xc0\xb5\x07Q\xcd\x0c\xb4+\ -Y\xe2b\x94\xe6\xb1\x85P\xdc\x15 p\x00`p\xdc\ -\xce\xa0\x025m\xac\xb6\xd8\xdcJ\x8b\x8d\xa2\xfc\xdc2\ -\x8b\x03\x00I%\xb5\xe6\xab\xed\xb4(\xd6V6\xb6g\ -u\xb8\xfc\xe6\xab\xaf\xadu\xfb\x0b'M\x9b\xef\xadv\ -\xed\xb5\xe9\x8c\x1d\x81\xa0\x88<\xba\x80\x10\xe5dJ\x8b\ -^ZA\x94ruT\xccM'\xe1\x11-\x19k\xea\ -\xf5\x09$\x0f\xd1\x8a\xe5\xf8]\x97\x16fA\x1e\xfd\xb0\ -k\xb5sMR\xf95\xc0\xf5\xf6V\x22\x0am\xb5\x12\ -\xbc\x18\xa0\x8c\x85\xa0^\xa9\xd0\xc6\xd5\x06\xbb\x5cV\xef\ -\xe4J)\xafX\xef\x15\x81\xbaX\x96\x8d\xe0\xe1\xae\x10\ -\xea.c\xcdZ\xb2\xbdR\xa6\x15\xbc\x01\xaf\xaa\x97W\ -\xb7\x9a\x87\xb7P\xb7\xcf+Xz\x1c\x96\xee6\xbcJ\ -\xe1\x8c\x9d:\x84\x88\xdc\xb9\x13\xd7!\x80iJ\xf9\x5c\ -}\xa1j\x0c\xe0\x1bM\xda/\x00\xf9\xd3\xfe\x82*\xc6\ -\xb9R}\x02\x89\x0bj\x11\x9b\xe4\xbc\x00\x1e@5\xfa\ -\xe7\xa2\x8a\x91d\x00\xa1\x06\x8f)\xda\xc0\xd10\xe8\x00\ -q\xd1\xcd#\xbd\x1d2\x87\xa2}j\x00!\xe9\x00\x10\ -\xe4\xab*\x16I\x87P\xa6\x83\xc0t\xd2\x9b\x0c\x09D\ -'\xa3\x01 \xa9\xbc\x09Ik\x10:E\x04G]\xbe\ -+q\x1d-.r\xe1\x0b\x008f\xcc \x16\xe1\xfe\ -\xb5K(\x0f\xeb\xcf\xad\xb28\x00\xe0$\xaf\xd2\xe2\x09\ -\x05\xc9e\x8d\x16h\xe8\xb3<\xbcT\xd5\xf4\xb1\xb5\x5c\ -}f\xdd\x07_Y\xff\xb5\x9fl\xe0\xc6/\xd6\x7f\xfd\ -'\xeb:\xfc\xceZw\xbe\xc0+\xbc\xb2rMH\xc9\ -\xf2U\xd9\xab\xb5\x07\xc4\xcd\xad\xbb\xa5d\x08\xe2\xa8W\ -\xfe\x95\xaf\x0a\xa5\xf9\xd7V\xbc\xf8\xc6\x8a\x17^Af\ -\x9fZ.\x9fQM\x83\x96\xbbS Rj,\xe9\xdc\ -\xb3\x00\xeav:\xc3Q\xca$\xb8\xe9\xb2\x1a\x94]\x85\ -\xb2+\xedRq\x85'E\x95\xc4\xf8j\x040\xe3\xd2\ -\xb5\x1fB\xa2c\xebuZ\xa9\xb7\xe3\x19\x00`\xcd*\ -\xe2p\xe5\xe9H,\xe9`,\xc6)\x89\x97\x07\x15\xc9\ -\x83\xe1\xabg\x80*\x8a\xd5\x03\xc0G\xb6\xa2\xce\xef.\ -=\xd7\x8a\xa8\x13\x11X\xad\x8a\x02\x08M\xdei1\x8c\ -\xb1VG\x91\x98\x14\xbeT\x1d)u\xfc\xfa\x85\xb83\ -\xef\xcf\xdd\xb3v\xd4&\xba\xb3\xf0\x11\xd7\xf2\x15\xb4\x91\ -\x93\xea\xfc_50T'\x0f\x9f:j!R\xbej\ -\xd9\xd4L!]\x8b,u\xe3\xe6\xab\x1bs\xe2\x87\x95\ -\xfa\xb5\xcbV\x0c\x15I'\xeb\x10\x08R\xe5\xa6\xceE\ -uj\x0e\x08nO\x9c6n\xf0\xa0\xe7\xa9\x91\x068\ -V\xbb\x84\xf2\x19\xd4\xbcZ\x8b\xcf\xab\xb3x\xde\xc7\x17\ -\xeaL\xfdF\xe2\x7f\xbb\x05[\x86-\x7fp\xc5j\x16\ -nZ\xc7\xeek\x14\xff\xbd\x8d\xde\xf9\x93M\xde\xff\x0b\ -\xf2O6v\xfb7\x1b\xbc\xfe3\x7f\xfb\xda\xeaV^\ -[\xa9V:\xc7\xceP\xa8\x94O\xe6\xa2\xe5or\xe9\ -\x82I\xd5\xfd=\x810\xbe\xb4\xd2\xa5\xf7V\xbe\xfa\x95\ -\x95\xaf!+\x9f[\xf1\xfc\x0b\xcb\x1b\xbb\x0d\x00v\xcd\ -G\xea\x9c\xaceV\xc5\xe7|\xac\x99\xfb\xba\x22\x80\xe6\ -\xe3\xa1\xc4M\x0a+\x01E\xb9]*(\xb5\xcf\x0aJ\ -\xec\xff\xc8/\xb6\xcf\xf2Kx_\xc6\xef\x00\x81B\x19\ -\xf7\xef\xb6\xbd\xb9\xddO\x00\xe0|w\xf3\x15m\x93\xc7\ -8\xa5\xf8x\x94\xa5\xbd\x09\xf1\x8ca\x1cc\x96\xc0\xf8\ -%5O[\xaa\xb6\xb4\x93\x96\xaa\xdd\x5c\x96Rp\xbc\ -\x96j\x17\xb3\xdc\x11{\xea\x18Jz\xde\xab\xad\xe8{\ -xf\xa5\xb2\xab\xaeXG\xfaIS\xdf\x07\xc6<\xc6\ -\x1d\x09'+\xc4%\xbb\xd6\xae\x88\xb6\x86\xab\xe3D\x12\ -\xe8s\x1cAa\x02Q\xd7n5l\xd6\xe6\xcaT\x14\ -\x95&\x104k\xcb\xb8\xb6Z\xc3l% L;n\ -3\x1a\xa6\xcd\x87{\xf4#\x01\x09H\xf5K\x88G>\ -\xcdnq\xf14\xae\xab\xefQgL\xed\xd8ueP\ -\x02\x01\x0f\xecR\x15\xc5)\x15\xach\xbf\x1f\xec\xf8S\ -\xff^$\xbe\x88\xd8\xc7\x80%\x12\x13\x93\xcb\xdb,\x0d\ -\xb7\x1bl\x1d\xb3\xbc\xa15\xab^\xbci\x9d\xfbol\ -\xe8\xf4G\x9bz\xf8\x17\x9b\x7f\xaa\x16r\xffl\xf3\x8f\ -\xff\x93M\xdd\xfb\x8b\x0d]\xff\xd5\xda\xb7\xbf\xb1\x1aY\ -\xf5\xc4#\xcb\x1b\xc1\xe2q\xfd*\x0a\x91\x07P\x9fb\ -\x9d\xc3S\xba\xf8\xce*\xd6\xbf\xb1\xaa\xad\xef\xadz\xfb\ -{\xab\xda\xfc\x06\x10\xbc\xb5B\xb5zQ\x06\x84\xe5\xa5\ -\x08\x00\x10\xb6\xd8|brn\x1d\x82\xc5\xe7b\xddx\ -\xa7\xcb\xf0\x93Kye\xf6Y\x1e\xca\xcf+F\xf4\x0a\ -\x18\x08Y\x97\x00\xc8\xe5\x02\xc8,^\xc3c\xf7\xda\xcc\ -\xaa\x0d\xac\x10b\xad\xe9\xe3\xd6]U\x10c\xa6\x1dC\ -I\xda4\xc2\xf5\xd4>.\xa5U\xedo\x08\xbb\xf0.\ -\x9d2\x1a\x06\xb4Q\xf5!\x9ay\xce\xeb3R\xcd\xc7\ -\x16\x19\xbbOv\x02\x7fqU\xc2\x00A \xe8\xd4v\ -\xb5U<\x01 \xc0K\xeb\x94\x96\x18\x1dh\xa0\xe3S\ -\xd3Z=\x05j\x81\xc7k'J*\xe8\xbaN\x11\x9f\ -a\x91\x02\xc3\xc5\x86JmLt\x00\xc0\x8au\x18t\ -:\xb9\xa7+-\x97\xebo&,`\x19\xb2\x0eu\xe7\ -\xcel\xbc\x10~\xe6A\xfc\xc4'\x1fq(]\xff\x0f\ -QQ\x8bV\xe5\xaa\x0e\x04\x00@\xd7U\x9f}\xed{\ -s\x84E[\xb9\xcaa\xb2e\x10B\xb7\xe9\x13 \xb8\ -\xadbJ\x15\xc9\x8f\x89\x85\xc9\x95\x9d|W\x8f\x05Z\ -\xd5\x81t\xd9\xaa\x16\xae[\xcf\xd1\x1b\x9b\xba\xff\xb3-\ -\xbf\xfcO\xb6\xf9\xee\xdfl\x0bY{\xf5/\xb6\xf0\xc4\ -\x03\xc1\xe0\xf5?Z\xfb\xce\xf7V\xb7\xfc\xc1\xcag^\ -X\xd1\xc4C,\x1b\xb7\x8f\xe4M>\xb4\x82\xd9\x17V\ -\xb2\xf4\xb9\x95_\xfdhU\xdb?Z\xf5.\xb2\xf3\xd1\ -*7>w\xd3\xday\xea\x0d\xd8\xb5\x0e\xd0\x89\xa9J\ -\xab\xc4\xd8\x0b\xb0^\x01!\x8f\xf8\x8e\x87\xd2\xb6\xf6\xcb\ -(Z\xcavR(\xe1wE\x00E\x8d/\xd4\x99\x9c\ -X\x9fX\xa6\xe6\xd0=\xa4\xb1\xfd\x96\xceX\xc8K\xfa\ -[\xe7,\xb3c\xd5\xed\xb1P\x15\x93\x8aB$\x01\x85\ -\x1eD\xb3\xae*V\x8dL\xdc\xb3\xfc\xb9\xe7V\xac\xb5\ -\x86\xb5/\xadd\xf5\x0b+Zz\xc7\xef^\x98\xaa\xab\ -\xd5\xa2.\xa4\xa6\xdb\x9a\xacS}\x81&\xf0:5\xdb\ -\xab)\xfc%\x8bq\xdd/5\x1f\xde\xef\x1dk\xaa\xc9\ -\x1eW\x97\x8e\xabH\xc5\x92\xbdmH\xda\x90\x88\x97\x10\ -\xc9@1\xeaJ\xe5\x1a\x16a\xc9N\xb4\x95\x5cn\x1f\ -\xe5\xeb\xbc^\x95\x85\xf9\x897\x01$\xb3\x05i\xf6$\ -\xd0\x041T\x01\x86\x00@\xacW\x9f\x80\x14\xc0\xe5\xfa\ -\xef\xd6\x9cw\xc1\xc2[\x88\xc4x\x1b\x17`\xd3\xb5\x0c\ -\xb0\x03\xc2\x10\x96\xc1@\xab\x97\xaf\xd2\xc3r\x08\x90\xd2\ -\x1dBS2\xe45\xb5\xae\x17\xee1d\xd9=sV\ -1{h\x03\xc7/m\xf9\xe9\xcf\xb6\xf3\xfeov\xfc\ -\xf5\xbf\xd8\xe1\x97\x7f\xb7\xf5W\xffds\x8f\x7f\x03\x18\ -\x7f\xb2\xd1\xdb\x7f\x86\x1f\xfcf\x1d{?[\xe3U\xbc\ -\xc1\xf2{+\x9b\xf7\xe6\xd3\x8bt\xf6\xde\xe2{+]\ -\xf9\xda\xca\xae~o\xe5\x9b?X\xd9\xe6\xb7\xbc\xff`\ -%+/\xadp\xee>dP\x99\x80V\xd9\x96\x1c\x11\ -L\x86Y'\xc0\xd6\xe3\x8aa\xeeE\xb0\xf5\x22b\xb8\ -B\x83\xbc\x03\x96-\xa6\xaf\x8e&jX\xf1\x0f\xf2\xd6\ -\xe7\x9e_\x86\x90\x81\xe7\x0b0\x86\xd9(%\xa7g\xc3\ -\xf2\x06\x0f\xac\x88\xb0\xa4C5K\xa6\x1fX\xf1\xf4#\ -+\x82\x84\xea\x90\xa8\xbc\xf1\xfbp\x16\x9dJ\xaa\xc3\xa3\ -^[\xd9\xea\x07\xab\xe4\xfe\xaa\xf0R\x95\xdb\xdfY\xd9\ -\xc6\xd7V\xb4\xf2\xfe\x13\x08\x94\xc1d\x13\x1eT\xec\x93\ -\xd9{@\xc6\x06\x90H\xdf\xd5\xe9-FK\x8b\x92\x5c\ -\xbdB\x88t\x14Z\x16)\x8e\x90\xa2\xf9~\xafF\xcd\ -[\xf9K\xc3\xa2\xd3\x9b\xd4C\xe7\xbc\x8f\x8e\xdc=\x1e\ -\xc3\xc5|Y\xbe\x0aBu\xaaV\x87\xb2\x00\xf2b\x80\ -\x94\xc9wh.Z\xb5\x81\x22M>\xbeK\xd5+\xa9\ -R8^%\xd9\x91P\xb8\x07a\xc5\x01Lupn\ -\x87\xeb<\xa2-O\xbc\x0a\x0c\x80\xce\xb1W\x97!\x88\ -\xa3\x88\xa8B^k\x19\xc4\xba>>\xd3\xc7\xfd\x0dr\ -\xcdI+\x1e\xdf\xb0\x9e\xbd\xfb\xb6\xf0\xe0\x83m\xbc\xfc\ -\xde\xf6\xde\xfdd[\xaf\x7f\xb0\xb9\x07_\xd9\xf0\xe9\x17\ -\x84\x86\x8f6t\xf6\x8b\x0d\xdc\xfa\xcdz\x00A\xfb\xc1\ -/\xd6\xc4\xc0\xd5`A\xe5\x00\xa1\x84\xb8_\xb2\xf2\x85\ -\x95\xae\x7fk\xa5\x1b\xdfY\xc9\xc6\xb7V\xb4\xf6\xc1\x0a\ -\x96_X\xee\x9c\x8a8U\xc4\xa2\x85\xa3],t\xc3\ -2\xdb\xd7\xf0x\xb0\xecZ\xf2\xfd\xea\x09\x94\xab\xedm\ -J\xb7\xc4gd8\xda\xc8y!c\xa6^\xca:\x80\ -J\x9e\xd3\xa7\x9eCx\xe0l\xc6L\x8aW\xef\xdf\xb2\ -\xc9S\xab\xc6\xcb\xd4\xaf\xbd!{\xf9\xc2\x9a\xb7\xbe\xb6\ -\xa6-\xd5=|c\xf5\xeb_Y\x0d\x0a\xafZA\xb0\ -\xf6\xaa\xf5\xaf\xadz\xf3\xa3\xd5\xec\xfc\xe0\xbcT\x15\xaf\ -\xe5[\x1f\xadd\xfdK+\x5c|ky\x00:g\xe2\ -\xb1\xa9\x862\x9bP\x97\xad\x22\x95\xe1\x1b\x08\x1el\xe4\ -\xba\xc5\xe8(2\x15|\xe4\xcf=\xb2\xfcY\xefT*\ -\xd5\xbe\xab\xc6N\x85\x94Z\xb7\x16\x18$\xaa\xb3\xcbt\ -\x8b%0L\xadY+\x07V\x9e\ -B'\x89\xe7\xe9g\x17W\xdb\ -\xa7\xb9\xcb]\xc8DP\x04* 0\x85\x1c\x05E\xa0\ -\xc4\x04\xde\x03!\x00\xe7%8\x9fB\xaa~\xccn\x05\ -h\xc2x\xdaF\x04\xd49$7\xd1\xdf\x06\xf6\x9d\x12\ -h\xf2\xec\xbe \xe5e\x08\xe0}\x04\xfd\x1d\xb2\x03|\ -\x00q'\x04\xd2\x80\xc6\x0e\xc6\xa4[\x8c\xa9r\xbff\ -\xd1\xb7\x01\xbcr?\xa1\xbe\xcc\x1a\xcb\xe4\x9c\x8c\x00\x9a\ -y9\xa0o\xa1?\x06\x197\x87\x1d\xe8\xea\xce!\x1b\ -n\x12\xed7\x12<\x8b!\xf4\x880\xcb\x04\xf4c\xc8\ -$\x10\x12\xde+<\x9e\x9c+^$$\x91\x18\x02G\ -\xacg\x81\x1e;\xd0C<\x02j\xd0\xc3\x90\xab\xc03\ -\x11\xf1\xb2*\x22\x1c\x91\x9a>;&\xf0m\xd2\x89X\ -\x14X\xf3\xa3\xee\xb3\xecdB\x8e\xd9\xb9\xd1\xd6\xc9@\ ->\xfa\xb5\xf3\xf5\x84\x90\xcf\x8a\xc0\x84\xdb\x87\x8e\x0f\x16\ -\xde\xdbiw3\x00\xbd\x0aI\xd9\xbe3\xc3\xe1,\xfd\ -\x8e\xa3\x96G\xbb,\xd8#y\x03d\xcc\x04\xf6LI\ -5\x15\xf4\x18\xcd\xc8!\x81&\x13x\xb2\xb0G\xa8\x98\ -\xd7\x97J\xea\x93v5\xda\xdbu\xf0f\x14\x07\x92\xfc\ -\xb1y\xcd\xadt\xa3\xf6\xa1\xb7\xd0\x1e\x08\xf6HR9\ -\x17\x9d.Q\x88JMX\xe3E\x11\xc8\xf9\x91\x84\xf7\ -6\x92\x90d\xdf\x972\x84\xd10\xd7\xf9\x22\x02'^\ -\xd7?\xed\xed\x0f\xbc\xcbE!\xdb\xbc\xce\x86SF_\ -w\x8ev\x01Hy\xe1\x9cN\xb5.\xcf\xf0\x0d\xfa:\ -G\x83\xaa\xe2\x16:\x1d\xdb\x0d\xe0\x5c\x0f;d\x81\xc7\ -k\xf3\xee\x13\xb6\xb6_\x18x\x11B\xac\xd8\xfc.\xa5\ -\x1f`t\x8aZ\x1d\xe5v\x8c\xd0M\xa6#$\x9db\ -1&\xcfu\xde\xb2q\x9f\x90\x9d\x86\xbe\xbd\xe8<\xc7\ -\xfb2\xf7\x0f\xe6\x1c\xe5c!G\x1c\xdd\x88\x0e\xe8\x1a\ -\x85\x8f\xea.\xef\x842G\xf0z\x99e\x88\xdb\xbc\x96\ -\xabn\xecx\xf1_\xa0JA\x0d\x0a\x0d\x0a Icons / Noti\ -fication / Error\ - - black\ -\x0d\x0a \x0d\x0a \x0d\x0a \x0d\x0a \ - \x0d\x0a \ - \x0d\x0a\x0d\ -\x0a\ -\x00\x00\x01u\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\ -\x00\x00\x01\xd0\xa2K@\xfc\x1f\ -\x84\x81\xfc\xff06\x10\xbf\x02\xf2\xe7\x00i9Z\xf8\ -\xd8\x02\x88\x9f\xa3Y\x08r\xc0_4>\x8c\xddHM\ -_G\x00\xf1?\xa8\xe1 \xfa/\x0c\xe3\xe0\x83\xd5\x02\ -\xf1\x1a \x9f\x91R\xcbA>\xff\x87\xc7\xc7\x84\xf83\ -(u\xc03\x12-\xc4\x16%n\xe4\xc6{>\x11q\ -N\x8c\x03\xae\x93\xeb\xfb\x8b0C\x09\xc49!>\xc8\ -\x0c}r\xf29H\xe3?\x0aC\x00\xc6\xaf!\xd5\x01\ -\x0e\x14Z\x88\xce_C\xaa\x03B\xa8\xec\x80\x03\xa4\xc6\ -\xbf\x0f\x09\xf9\x9e\x984\xb0\x95\xd4\x10P\xa7r\x08L\ -\x22\xd5\x01l\xd0\xb2\xfd?\x95\x1c\x10@N90\x9b\ -\x0a\x0e\x00\xe5\xa2\x9f@\xccDN9 \x0d3\x84\x82\ -4\x00\xd2\xdfBIQ\x5cOa\x08\xdc\x01\xd2\xcc\x94\ -V\xc5k\xc8t\xc0\x1b _\x99\x1am\x01F \x9e\ -\x81\xa5\x01\x82+\xceAl\x90\xcf\x95\xa9\xdd\x1ar\x07\ -\x1az\x13\x9a\xaf\xe1\x8eA\xe3\xff\x04\xc59\x10\xb3\xd0\ -\xb2=\xa8\x0f\xc4\xb5@\xbc\x16h\xd1! \xbd\x1d\x88\ -\xa7\x00q \x90\xcf\xcc0\x0aF\xc1( \x11\x00\x00\ -\x90\xbf\xd0E\xdf\x04S\xa8\x00\x00\x00\x00IEND\ -\xaeB`\x82\ -\x00\x00\x02\xaa\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\ -\x00\x00\x02qIDATx\xda\xedWMHTQ\ -\x14\xd6q,\x0c\x1db\xd0d\xa86\x814!\x11A\ -\x90\x92H\x14\xc4@\xaef\x11\xb5\x10l'\xe4l\xc4\ -\x85\xcb\x1aA\x88@\xc2E0\xad\x1c1h!\xd3\xa6\ -\x7f\x9a\x84\x90hg$$\xb6\xa84]\x88\x039\x8b\ -\x18)g\xf2;\xf0=8\x5c\xdfLo\x86\xb9\xd2b\ -\x1e||s\xcf\xb9\xef\xdes\xbew\xce}o\xea\xea\ -jW\xed*\xe3\xba>0\x14\xbbq3\xf6\x07w\ -\xe9q\x8d\x8fN\x00\x15+\x80\x88E\xbe\x0f\xe0\x97\xe0\ -\xa8\x11\x80\x1f\xf6\xcfF\x9f;\x9c\x01\xb7x\xad\x01\xd8\ -\xafJ{\x82g\xc0>\xbd\xc9)#\xab\x84\x11D\x08\ -\xf8i\xcc\xd9\x06\xcex\xad\x01U?\x82M\xa0IG\ -\x16fF\x1b|\xdb\xc9\xa4Qc\x81n\xd8w\xd4I\ -\x17\xf5\xda\x05\xac\x15\xb9oM6\xe7>M\xfa\xe60\ -#{\x0c\xf4\x02\x05\x8e{\x8cM\xae\xd1>\xec\x92\xa1\ -S\x039\xad\x00~\x1f\x06\xb6\xe8\x93\xb5\xbf\x01\x1b\xc5\ -\x14Hq<\xa0\x14\x09\x19\x1b\x9d.QK\x17E)\ -c\xfe\x0b*s\x8f\xe3\x1f\xa5\x14H)\xdb]\xda\xa4\ -\x00\x0fU\xd8A\x0f\xb8\xc6;\x8e}\x12\xc0?\x15P\ -\xf6I\xda\xbfK\xa1\x96\xd1UG0\xff53\x9f\x07\ -\xfbio\xf0\xac\x80\xf2\xddR5\x91\x04\xce;\xad\xa7\ -\xe6\xc8\xc2\xb2\xe9%9%\xd5\xf7\xc1}\xa0\xde\x98\xe7\ -]\x01\xe5\xef\x90\xd7\xadz\xcfK\xab}\x05/\x81\x97\ -\xc1\xeb\xf2\x1aV\xfeW\xe0\xb3.\xeb\x94\xaf\x80\x91\xe9\ -1`\x10\x90#y\x1e\xf8\x04,\x00r4'\xe4[\ -\x10h/q\xbf\xd4\xc0\xaa\x9b\x02'\x9d\xc8-\x7fU\ -\x1f\xe49\xb1G\x01\xe9\xe1\x1d\xf6\xf0\x09Ko\xd2\x03\ -\xc0C*\xbd\xe06a\x92\xcf\xf0\x17x\x0e\x9c\x06\xa7\ -\xab\xc4o\xc1\x19U#}\xc5\xa2\x1c\x01\x16Y\xa9\xab\ -U\xc6\x0a\xf0\x1e\x88xyV\x8d\x98\xd8Xe\xf6\xff\ -\x97\x7f\xf7v\x01&\xc7\xb3\xa0\x90\xee\xe83\x00\x00\x00\ -\x00IEND\xaeB`\x82\ -\x00\x00\x02\xae\ -<\ -?xml version=\x221.\ -0\x22 encoding=\x22UTF\ --8\x22?>\x0d\x0a\x0d\x0a Icons / Noti\ -fication / Warni\ -ng\x0d\x0a \ -\x0d\x0a \ -\x0d\x0a <\ -polygon id=\x22Tria\ -ngle\x22 points=\x2212\ - 2 22 22 2 22\x22><\ -/polygon>\x0d\x0a \ - \x0d\x0a <\ -/g>\x0d\x0a\x0d\x0a\ -\x00\x00\x06\x8c\ -<\ -?xml version=\x221.\ -0\x22 encoding=\x22UTF\ --8\x22?>\x0d\x0a\x0d\x0a Icons / Icon\ - Grid\x0d\x0a \ - \x0d\x0a \ - \x0d\x0a \ - \x0d\x0a \x0d\x0a \ - \ -\x0d\x0a \x0d\x0a \ - <\ -use xlink:href=\x22\ -#path-1\x22>\x0d\ -\x0a \x0d\x0a \ - \x0d\x0a \ - \x0d\x0a \x0d\x0a\x0d\x0a\ -\x00\x00\x01\x12\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\ -\x00\x00\x00\xd9IDATx\xdac`\x18\x05\xa3`\ -\x14\x8c\x82\xa1\x06\x22\x13s\xd9\x818\x15\x887G$\ -\xe4\x5c\x00\xd2\x87\x80\xb8\x1b\x88Uhn9\xd0BG\ -\xa0Eo\x80\xf8?\x08\x03\xf9\xffal(\xbf\x87\x96\ ->w\xc2b\xe1_4>\x88^F\x0b\x9f\xb3\x03\xf1\ -k\x98\xa50\x0c\xe4\xff\xc3\xc2\x07\xa9\x09\xa2\xb6\xefS\ -q\xf8\x18\x17\xff4\xb5\x1d\xb0\x91D\x07\x800\x0f5\ -\x1dp\x9e\x0c\x07(R3\x0d\x1c\x84&\xb0\x7fD\xa4\ -\x81\xbf\xd0t N\xcd\x10\xe8\x221\x04^\x011#\ -5\x1d\xa0\x04\xb5\xe0\x1f\x91\x0e\xe8\xa0E9\xd0Cd\ -9\xf0\x0c\x889hU\x18-\x83\xc6/,4\x90\xe3\ -\x1cl9\x90V\xa1u]\x10\x04\xca\xe7hE1(\ -\xce;\x81|\x0e\x06z\x01P>\x07Z\xa8\x08\xa4\xc5\ -\xa9\x9a\xe0F\xc1(\x18\x05\xa3\x80\xde\x00\x00*\x106\ -\x97\x13c\xdc\xaf\x00\x00\x00\x00IEND\xaeB`\ -\x82\ -\x00\x00\x01\xf5\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\ -\x00\x00\x01\xbcIDATx\xdac`\x18\x05\xa3\x80\ -D\x10\x91\x90#\x06\xc4\xd7\x80\xf8jdb\xeeU\x10\ -\x0d\xc47\x81\xb8\x84.\x0e\x00Z\xaa\x02\xc4\xffA\x18\ -h\xe9\x7f\x18\x1b\x88\x17\xd1\xcb\x01\xcaH\x0e\xf8\x8b\xe4\ -\x80\x05#\xc3\x01@KU@A\x0f\xb5\xfc\x1f\x88\x86\ -\xf2\x17\x8c\x98(P\xc4\xe1\x80\xf9\xb4\xb4T\x0e\x88u\ -\x81\x16j\x01\xe9(\x1c\x0e\xd8\x0b\xe4k\x00i\x1d(\ -f\xa1V\x9c3\x02\xf1mX\x96\x83\xc5?Z\x1a\xf8\ -\x8b&\x0f\xc2\xce\xd4\x0c\x01\x17\xa8\xe1\xff\x90|\x8c\x1e\ -\x02\xc8\xf2\x1bi\x11\x0d\xe9h\x05\x0f6\x07\x80\xe8\xab\ -\xe4Z\xc0NDtL'\xe0\x80W@Z\x92\x80=\ -L\xd8\x0cV\x06\xe27@\xc9\x07@\xba\x06\x14\xefx\ -\x1c\xb1\x17K9\x00\xa2\xff\x00\xf9\x16\xf8\xea\x10\xa0\xfc\ -J \xfd\x1c\x88\xeb\xd1]\xa5\x87V\xb6o\xc7\xe3\x03\ -\x1e \xbe\x8f%\x04\xa2\xf0\xe8\x11\x02\xe2gH\xe6\xcf\ -CW\xa0\x8b\xc5\xc0\xe9x\x0c\x94\x05\xe2\x1fH\x06\xb6\ -\x11\x08\xf6#h\xe6\xcf%\xc6\x01 ~\x00\x1eC\x9d\ -\xa1q\xbe\x94\x80\xe5yX\xd2\xcc\x5c\xf4\xf8\xd1\x85\xfa\ -\x069_\x83\xb2\xd47 \xadFA\xce1FJ#\ -\xb04\x03r\x08\xd1!\x00\xa2_\x03\xb1\x12\x99\x96\x7f\ -\xc0\x91k\x88v\x00\x8c\xff\x05\x88#\x88\xb4\x98\x0b\x88\ -\xab\x81\xf8/\x9er\x83d\x07\xc0\xf8\x17\x81t\x19\x10\ -\x9b\x03\xb1(\x90\xcf\x0b\xa2\xa1\xb9(\x06T%\x03\xe9\ -7x\xf4\x93\x94\x06\xfebI\x13\xc8e\xfd\x7f<|\ -l\xfa\xc9J\x03\xb4\xe2c8@\x9b\xce\x0e\x98\x8e\xad\ -t{KDeC-~\x18\xb6\xb2:\x84\x848\xa6\ -\x84\xbf\x1e_m\xa7\x04TT\x07\xc4\x13\x81x\x02\x90\ -?\x01D\xc30\x85\xfc. \xdfo\xb4k\x87\x0e\x00\ -\x0bqL\xd4T\x13W`\x00\x00\x00\x00IEND\ -\xaeB`\x82\ -\x00\x00\x00\xd5\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xffa\ -\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\ -\x04gAMA\x00\x00\xb1\x8f\x0b\xfca\x05\x00\x00\x00\ -\x09pHYs\x00\x00\x0e\xc3\x00\x00\x0e\xc3\x01\xc7o\ -\xa8d\x00\x00\x00jIDAT8Oc\xfc\xff\xff\ -?\x03%\x80\x09Jc\x80\xc522\xffA\x18\xca\xc5\ -\x09\xb0\x1a@\x8cF\x18\x00{\x01\x9f\x86\xd8'O\x18\ -\xa1L\xac\x00\xa7\x17`\x80\x90k\xc0\x06\x10\xb2\x05\x9f\ -!\x04]\x00\x03 C\xb0\x19D0\x0c`\x00\x97+\ -\x09\xba\x00\xa4\x11\x9f\x17Q\x0c \xa4\x18\x1b\xc0\x99\x12\ -a\xde\x22d \xed\x922\xb1`\xc8\x1b\xc0\xc0\x00\x00\ -\x1d[2\xc1\xc0t\xc2\x0d\x00\x00\x00\x00IEND\ -\xaeB`\x82\ -\x00\x00\x00\xeb\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\ -\x00\x00\x00\xb2IDATx\xdac`\x18\x05\xa3`\ -\x14\x8c\x82Q0\x14Adb\xae:\x10O\x8eH\xc8\ -\xd9\x0f\xa4\xd7\x00q8\xdd,\x07Z\x1a\x0f\xc4\x7f\x81\ -\xf8?\xd0\xe2\xff \x1a\x8a\xb7\x00\xf9\xcc\xb4\xb6\x1c\xe4\ -\xf3\xbf \x8b\xa1\x96\xc3\xd9P~\x1b\xad\x1d0\x19\xcd\ -Bt\x07\xbc\x05\xd2l\xb4t\xc0~\x02\x0e\xf8\x0d\xa4\ -\x15i\x99\xf8VA\xe3\xfb/\xd4\xf2\x7f06\x10\xff\ -\x03\xf2\xbf\x02i\x11Z\x86@\x18\x81\x108H\x8f,\ -\xb8\x19\xc9\xc2\x7fH\x0e\x00\xf9^\x95\x1e\x0e`\x06\xe2\ -6 ~\x0b\xb4\xf0\x0f\xc8b >\x04\xc4\xaat-\ -\x8c\x80\x96\xb3\x81\x12\x1c\x90\x16\x1d-\x9aG\xc1(\x18\ -\x05\xa3`H\x03\x00\xac\xe7\x98*\x92\x10\x95\xa4\x00\x00\ -\x00\x00IEND\xaeB`\x82\ -\x00\x00\x03\x0b\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\ -\x00\x00\x02\xd2IDATx\xda\xed\x97MH\x94Q\ -\x18\x85\xd5i\x0a-\x17\xba0\xcc1!\x88\xc2(\x0b\ -\x92\x5cLFn*\x88Z\x05J(\xd3&*4B\ -\xfbq\xd5\xa2\xc2 \xa4\xb2_Z\xb4\x88\x8aP\x82)\ -\x22\xab\x85\x14Q\x8b\x16\x81\xf4\xb7h!\x16\x95\x05-\ -\x8a\x8a\xd2t\xea\x1c8\x1f\xbc\xdc\xee7)\xe9H\xe0\ -\xc0\xe1r\xee\xf3\xcd\xbd\xef\xf7\xce\xfdy'+k\xea\ -\x83O\xdd\x96\xa6\x1d\xd0\xc1\x10\xb6\x11\xba\x09\x1d\x0e\xe1\ -\xab\xa0\x1b\xd0\xb1\xdaDc\xae\x87/\x86\x92\xd09\xf0\ -\xc2\xb0\x00NC\xbf\xf0@\x9b\xed\x87\xaff\x7f \xf8\ -\xf3\x0e_\x84\xfe\x94\xe1\xb7\x1c>\x1b\xfd?\x0c\x7f\xe2\ -\x0d\x00\xa0\x03\xe2C?\xed[\xc0?b\xbf\x94\xd2 \ -s\x0dOzx\xa5\xe1\x1d\x86\x07A\xac\xf7e\xa0Z\ -\x90\x0f\xd5\xaa\xaf0\xf8\x12t\xd9\xf0f\xf1\x5c\xf8\xef\ -\xe2]\xd0\x90x\xbbx\x04\xfe\xb5x\x0f4 \xde\xe9\ -\x0b`:\xf4N\x0f\x5cT\xdff\x13\x00S\xfdL\xbe\ -G\xbc\xc6\xf0\x95\xd0]\xf9\x97\xe2\xe5\x86\xd7A\x17\xe4\ -?\x86\xad\x83.=\xd0'\x7fI\xfe\x8d\xfcQ\xf9\xcf\ -P\x0etD\x9eY\x88@\xbb\xcd\x84\xb3\xa0\x9d\xc6\xe7\ -C\x9b\x8c/\xf7\xad\x83D\x90fh!\xf4J\xbeS\ -|\xad\xe1\xcb\xb9\xa0\xe4\x1f\x88/3|\x03tG\xbe\ -O\xbc\x18~D\xbc\xd5\x97\x81\x22\x13a\xb7\xf9\xcd\xeb\ -\xc5\xa3\xf0#\x1e\xbeO<\x1b\xfe\xbd\xf8}\xe8\x9b\xf8\ -I\xf3\x92\xbd\xe2\x8f\xc3v\xc3Cg\xdbq\x0b\xe5\x1b\ -\x9et8\x03*3\xfc\x84\xc3\xd9V\x1a\xbe\xc7\xf0\x12\ -_\x00+\x9c\x01\xf6:|\x01\xfa\x07\x0d?\xee\xd9\xf7\ -\x9f\x0c\xbf\xea\xf0(\xfa?\x88\xc7\xc2\xb2\x10\x87\xcep\ -M\x84\xf0\xa5\xd0)h;\xd3\xee\xe1\xf3\x98\x09\xa8\x85\ -\xbb\xcb\xc3K!\x9e\x9a\x05\xff\xfd\xfd\x11,Z\xae\x93\ -\xc8d\x04P\xaaE\xc8\x00\xf22\x1e\x00&\x8fa\xe2\ -a\xee\x14\xdf-\x98\x89\x0c\xc40\xf1\xb020)\x01\ -\x14+\x00\x1e\xc5\xd1L\xa5\xbd\x0c\x93q\xfbm\x85Z\ -\xb5\x06\x86\xa0&\xf6\xc1oC[0\x91o]\xe5\xdc\ -\xef)\xd6\x01\xc6\x0frmLt\xea\x1b\x9c\xa3\xd8\x9e\ -\x9c\xf1L\xfd\xfe\x87<\x01$2\xbd\x08\xaf\x99\xdb\xb3\ -}<\x16X\xceX\x9f\xc7\xc4/\xd0v\xff\xf3\x5c\x18\ -\xe8\xac\xb9>\xbfB\xcfY\xbb\xc17\xa2]\x92f\xa0\ -\xec4\x19\xca\x03\xafA{\x00\xba\x0d\xf5k\xdb\x06Y\ -\x8b\x87\x05\xe0\xde\xe7\xd4\x80J6\x06\xc4A\xe7Cs\ -T\xe5P%\xac\xffY\x09\xa1\xdd\x0f\xdd\x83\xbe\xa4\x19\ -\xef\x8f\x00\xaa\xa0]\xbc\xffY\xfbA\xd7\xa1\xb7\x7f\x19\ -`\xb4\x9e\xe5\xfaS\xd5\x98mh[tn\x14\x8df\ -\xa1\xf1-\x1b\xa0+P\xbf\xa9\xf9l\x9d\xefz\x9e\x0b\ -\xbd,V\xe0\xd7\xa0\x9d1\x9e'\xe1L\x0cZ\x01\xad\ -\xe3\xff\x07\xf8z\xd6\x8c\xacx\xa1\xd5,F\xd0N\x9b\ -\xfa\xb3;\x96\xcfo\xe5\xb5\xdc\x8eP\x05\x84\xb2\x00\x00\ -\x00\x00IEND\xaeB`\x82\ -\x00\x00\x00\xe0\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xffa\ -\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\ -\x04gAMA\x00\x00\xb1\x8f\x0b\xfca\x05\x00\x00\x00\ -\x09pHYs\x00\x00\x0e\xc3\x00\x00\x0e\xc3\x01\xc7o\ -\xa8d\x00\x00\x00uIDAT8O\xd5R\xed\x0e\ -\x80 \x08\xd4\xd6{\x83ON\x9d\x03\xe7,\xd0\xd5\xfa\ -\xd1m|(p\x0a\x9aE$\xbd\xc1\xa6\xf6\x82R\x8a\ -@t\xe9\xe2\x96\x00\x85D\x94u\x19b\x87\x1aOZ\ --\xae\xc0\x0c\x98\xf94R\xfdQ\xa2\x18\xa49OI\ -\xdc!\xf6@K\xeeP\xc12;=\x8aWe\x09c\ -rTh\xd2Z\xb0\xa7\xb3\xeb\xea\xf6\x14\xeeO4\x92\ -\xd9\x93~\xf7\x95W\xf1{\x82\x94\x0e\xd4\x89\xe2k\x0c\ -\xdb\xee*\x00\x00\x00\x00IEND\xaeB`\x82\ -\x00\x00\x00\xa6\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\ -\x00\x00\x00mIDATx\xdac`\x18\x05\xa3`\ -\x14\x8c\x82Q0\x0a\x86*\x88L\xcc\xad\x89H\xc89\ -\x07\xa4\xd7\x00\xb1\x14\xbd-\xaf\x05\xe2\xff@\x07\xfc\x07\ -\xd1@\xfc\x98\xde\x0e8\x03u\xc0_\xa8\x03@X\x85\ -n\x0e\x00Z\xbc\x1a\xea\xfb\x7f@\x1a\x84A\x8e\xe1\xa2\ -g\x08H\x82\x82\x1d)\x0aR\x07$!\x02\x1d\xa0\x02\ -\xb4\x9ck4K\x8e\x82Q0\x0aF\xc1(\x18\xd2\x00\ -\x00e^3\xba\x9ez\xe49\x00\x00\x00\x00IEN\ -D\xaeB`\x82\ -\x00\x00\x00\xef\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\ -\x00\x00\x00\xb6IDATx\xdac`\x18\x05H \ -21\x97\x11\x88C\x81\xb8\x18\x88\x0b\xa9\x88\x8b\xa0\xd8\ -\x05\x9f\xe5\xdc@|\x19\x88\xff\xd3\x18o\xc0\xe5\x80i\ -d\x18\xf6\x1b)\xe4\xf0a\x16 \xf6\x01\xe27P}\ -)\xd8\x1cp\x85\x0c\x07\xfc!1\x8aM\xa1\xfaVb\ -\x93\xbcFk\x07@\xed\xf9\x00\xc4\x9b\x06\xd2\x01\xcf\x06\ -\xda\x01\xcfG\x1d0\xea\x80Q\x07\x8c:`\xd4\x01\xa3\ -\x0e\x18u\xc0\xa8\x03\x06\xad\x03\xae\xd3\xa1Q\xca\x8e\xb3\ -i\x0e\x14\xdcK\x07\x07\xac\x83\xea\xeb\xc6&iEf\ -Gc\x11\x10/#\x80W\x01\xf1{\xa8\xfa\xaf@,\ -\x8e\xcb\x85\xd6@|\x08\x88\xef\x92\x80\x1f\x10\x89\xef\x01\ -\xf1\x16 V\x1c\xed\x04#\x03\x00u\xbb\x07\x04\xef\x85\ -8\x87\x00\x00\x00\x00IEND\xaeB`\x82\ -\x00\x00\x00\xfe\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xffa\ -\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\ -\x04gAMA\x00\x00\xb1\x8f\x0b\xfca\x05\x00\x00\x00\ -\x09pHYs\x00\x00\x0e\xc3\x00\x00\x0e\xc3\x01\xc7o\ -\xa8d\x00\x00\x00\x93IDAT8O\xa5\x93[\x12\ -\xc0\x10\x0cE\xb1\x0d\xb6fs\xb55]G;!\x94\ -4\x8f\x0fg\xa6\xa3&rs\xe3\xe1\xaf\x18\x1fw@\ -\xc8w\xf5\xf8\xbf\x91k\xf5\xf0\xe1T$\x94\x98~\x0e\ -\xb4D*\xdcZ\xd0\x12J\xfa\x0a\x80[Z0\xe0(\ -\xb2\x8asn\x9b\xc0Z\x85Csh:\x18\xd0\xde\x07\ -\xe6\x1e\x0c$\x97\xa6\x03H\xd4Z\xdc\x04\xac\xc5\x1c\xe2\ -M\x1cmi\x82p\xacS\x80;\xe3\x15)\xdeZ\xe0\ -\x82tc!\x0e\xebp:\xe9\xf7@\xa9\xbc\xc2\xad;\ -\x7f\x8d8\xaap\xd6;\xce\xbd\xfa\x8fW\xbc\x9c\xc2\xae\ -\xed\x00\x00\x00\x00IEND\xaeB`\x82\ -\x00\x00\x00\x8b\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\ -\x00\x00\x00RIDATx\xdac`\x18\x05\xa3`\ -\x14\x8c\x82Q0\x0aF\x01\x99 21\xd77\x22!\ -\xe7.\x90\x9e7P\x0e\xb8\x0bt\xc0\x7f \x0d\xc2\xa6\ -tw\x00\xd0\xf29 \xcb\x81\xf4+ \x16\x1c\x90P\ -\x00Zl\x0at\x84\xe0h\x82\x1c\x05\xa3`\x14\x8c\x82\ -Q0\x0a(\x01\x00\x9bf\x16\x9e7\xad\x98\xae\x00\x00\ -\x00\x00IEND\xaeB`\x82\ -\x00\x00\x02\x02\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\ -\x00\x00\x01\xc9IDATx\xda\xedW\xbbJ\x03A\ -\x14MLc)XJTD\x91\xd8\xf9\x016V\x82\ -A4I\x13AH\xc4\x80\x8d\x96\x96NZ\xbf\xc4\xca\ -GH\x14T,\xf4\x17\xfc\x89<\xf0E\xea\xac\x9e\x0b\ -we\x18fwgv\xb2\x09B\x16\x0e7\xb3\x99\xdd\ -{\xee\x9c3\x8fM\xa5&\x97\xe3\xb5_=M\x8f+\ -\xf1N\xb9z\xd2F\xec\x03g#M\x8e\xc4\x05\xe0G\ -\x81\x18U\xe5%\xc0\x03(\xe9\x80\xa2\x8f\xc4I \xc1\ -\xae\x92P%@Q$Uy\x81\x13\x84\x11\xf0\xf8w\ -}\xd8\x95\x17Yg\x8f\x92J\xd0\xb5\xbd\xa1z\x02\xd5\ -\x14C4\x8fj\x0bg\xb7[&\xd4y\xa2\x1e\xb7\xf2\ -=\x03\xcd\x07\x86\x9e\x10\xb6\x95\x97\x14=eDy\xc0\ -\xcd\x13\xe4vIsb\xff\x02l\x02e\xb4?\x1cG\ -DDU\xbe\xae<\xd0dR\xb3\xc0\x14\xdaY\xc4\xae\ -\xa3'*a\x04\x84\xf4\xc0\x1d'\xaf\x01\xf4\xa2\x0e\xfe\ -\x9fG$\xb4\x1d\x084\xc3\x08\xe4Y\xaf\x16\xb7\x0f\xa5\ -\xf9O\xb1\x0b,\x02s\xc0{\x0cOP\xff\xf3(\x0f\ -T8\x1ehf\x01\xc5\x1e\x8fB\x96HX\x8e@\xcb\ -\xd4\x88G\xca4R_\xf8M$h$|9\x0c\x08\ -\x5c\x99&\xaf\x19\xbe\xb0Gr .\xf8\xc6\x0c\xe9\x7f\ -mtp\x91\xf6y\xcf@S\xeaG\xc6\x9c\x016\x02\ -\xf6\x0a\xbawo\xb3\x00]\xc6p\xf5\x160\x1d Y\ -\xc3v\x05\x5c\xc1\x83_\x16\x04\x1eX\xb6\xe3\xd8\x9ak\ -<\xb0\x06|\x1a\x10x\xe6\xfey\xcdn\xd9p\xdd\x05\ -s@?`\x9e\xd3\xbdW\xee\xb7-\xad\xf7\xf6\x9aG\ -\x8c\xc4\x12\x91\xd0h\xfe$\x9d\x8a\xd5u\xe2f\xd8'\ -\xa1\x9c/\x07'xD\xcc\x00\xcb\x12\xa1?\xcd\xd1N\ -'q\x16$O\xbcq\x82\x8ct\xffB\x22p;\x96\ -\x8f\x13\xda\x1d\x81\xd5\xc9\xf7\xe1\xbf\xbe~\x01}\x06\x5c\ -\x02\xc1U\xc6\xe7\x00\x00\x00\x00IEND\xaeB`\ -\x82\ -\x00\x00\x00\xd0\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xffa\ -\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\ -\x04gAMA\x00\x00\xb1\x8f\x0b\xfca\x05\x00\x00\x00\ -\x09pHYs\x00\x00\x0e\xc3\x00\x00\x0e\xc3\x01\xc7o\ -\xa8d\x00\x00\x00eIDAT8O\xd5\x91Q\x0e\ -\xc0 \x08Cq\xd9\xbd\x99'g\xe9\x06\x06q&\xea\ -\xcf\xb6\xf7SBLmC\x12\x11\x029\xe7{\xe8\xc0\ -\xcc\x09o\xa0\xba\xba\xd8T\x87\x89\x1fM\x1b\x00o2\ -UA\xc7\x8aa\x83\x88\x19.U\xf0\xec\xaa\x85^T\ -#&}\xbfBc\x00gs\xe7\xa3\xd6'~p\x05\ -$\xf3\xbb\xef]\xa1$X\x83\xe8\x04\x88\xd4H\x07\xd8\ -\xd9\x12\x13\x00\x00\x00\x00IEND\xaeB`\x82\ -\x00\x00\x01/\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xffa\ -\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\ -\x04gAMA\x00\x00\xb1\x8f\x0b\xfca\x05\x00\x00\x00\ -\x09pHYs\x00\x00\x0e\xc3\x00\x00\x0e\xc3\x01\xc7o\ -\xa8d\x00\x00\x00\xc4IDAT8O\xa5\x92\xd1\x0d\ -\xc3 \x0cD\x01E\xcd\x10\xcd\x0e\xedB\x99.\x0b\xa5\ -;\xa4CD\x8d\x94\xf6\x5c\x83\x8ck\xc3G\x9fD\x04\ -\x0e\x1cg\x9b\xf8Z/g\xf8\x834\xdc\xf7\xc8\xf3\x8a\ -\xe1\xb6G\x0c^\xba\xa4c\x1d\x7f\x1c@t\x99&\xd3\ -\x99\x16N\xf8\xe4`\x1e\xcb\xd59\xfc\x11>\x1e\xe3\x89\ -\xc1\xa1@5\xa0C\xce\x8d\xf3s\x8b\x96\xcb\x0c9\x80\ -\xe2\xbcmf\xbep\xe3\xd5\x09\x90@\x0f\x12\xe1\xf48\ -T\xe8\xa7\xc0\xced\xde\x92\xca\x016\xcbT0\xd7E\ -\xd3\x14\x01\xb9\x19\x85\xe3p\x17\xf7%\xe6|[\xb7\xa3\ -\xb8\xc5\x81\xae\xb4\xb6nu\x02\xed%\x01z \xaa\xd7\ -\xba\xe2\xf8o\x89\x90@\xeb\xa1H\xac}U\x17$\xad\ -\xdc%\xae\x80\xc4\xb2\xfe%\x847o\x1ay\x8cB\x12\ -\xd5\x15\x00\x00\x00\x00IEND\xaeB`\x82\ -\x00\x00\x01\xe6\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\ -\x00\x00\x01\xadIDATx\xda\xedW\xcdJ\xc3@\ -\x10\xeeK\x88 ^D\x11\x11\xd1\xda\x1f\x22^l\xd2\ -J\x9e\xa1\xde\x0az\xb3\x82\x17\x05\x1f@(\xf8\xb0\x05\ -\x1blS\xd38\x1f\xec\xc2\x12v6\xbb\x9b\x04`\xb8]\x8e\xe6\xb0\xd8\xa2\x0cO\xb8\xcf\x02\x12\ -\xde\x97\xf4\xab\xc9y\xcaq;\xc8\x0a\x8c\xc9\xd4\x04\x1c\ -9\xb1u\xe0\xd4\xc0\xfd\xa1E\xcdp\xb3\xe3\xc6%\xff\ -\xcfJNe\xce#\xdb\x01&\xe6\xbf\xaa\xbf\xf0\xa9\x83\ -'\x91\xd3\xad\xeb<'\xf9+DB\xe8/\xaat\xc2\ -\x19]p\xe0\xc9\x1f\xf8eu\xd1\xfe\xb7h\xd7\xbf_\ -\x7f\xb3\xb1^\xeamg8\x00\x00\x00\x00\x00IEN\ -D\xaeB`\x82\ -\x00\x00\x00\xd0\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xffa\ -\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\ -\x04gAMA\x00\x00\xb1\x8f\x0b\xfca\x05\x00\x00\x00\ -\x09pHYs\x00\x00\x0e\xc3\x00\x00\x0e\xc3\x01\xc7o\ -\xa8d\x00\x00\x00eIDAT8O\xd5\x91Q\x0e\ -\xc0 \x08Cq\xd9\xbd\x99'g\xe9\x06\x06q&\xea\ -\xcf\xb6\xf7SBLmC\x12\x11\x029\xe7{\xe8\xc0\ -\xcc\x09o\xa0\xba\xba\xd8T\x87\x89\x1fM\x1b\x00o2\ -UA\xc7\x8aa\x83\x88\x19.U\xf0\xec\xaa\x85^T\ -#&}\xbfBc\x00gs\xe7\xa3\xd6'~p\x05\ -$\xf3\xbb\xef]\xa1$X\x83\xe8\x04\x88\xd4H\x07\xd8\ -\xd9\x12\x13\x00\x00\x00\x00IEND\xaeB`\x82\ -\x00\x00\x01\x05\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xffa\ -\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\ -\x04gAMA\x00\x00\xb1\x8f\x0b\xfca\x05\x00\x00\x00\ -\x09pHYs\x00\x00\x0e\xc3\x00\x00\x0e\xc3\x01\xc7o\ -\xa8d\x00\x00\x00\x9aIDAT8O\xa5Sm\x0a\ -\x80 \x0c\x9d\x12\x05]\xa6\xdf\x9d\xa6\xb3u\x9a\xfe\xd6\ -e\x82(\xb0&j*\xfb\x08z0\xd6\xb4\xbd\xf7&\ -j\x9cs\xf0\x07\xf6\xda:\x92a\x99z\x87\x11J\x16\ -\xb6\x19\x0e\x13\xbe\x13\xa4F\x14\xccE\xfd\x08R\xc38\ -\xefI\x00\x1bkA\x1b2\x8b\x9c\x9cr\xeb\x09r\x15\ -\x0a\x92C\xd5A\x04\x92PD\xea\x19Dp.U\x07\ -\xd8(\x8dX\x10h?S`ob\x1cK\x22\xf4\xf7\ -\x01\x090\xce\xb5}\xd2[\xd7\xc1\xed\xb3\x9b_\xd7\x8a\ -\x22\x0f\xcdQ\x8c\xff\xaf1d\x11\xdc\x8b\x05\x00\xb8\x01\ -\xef\x94\xd6@\xd4\x8c1\xa7\x00\x00\x00\x00IEND\ -\xaeB`\x82\ -\x00\x00\x01\x88\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\ -\x00\x00\x01OIDATx\xdac`\x18\x05t\x00\ -\xd1I\xb9<\x03iy\x03\x10\x7f\x04b\xc9\x81\xb0<\ -\x0c\x88\xffC\xf1m f\xa7\xa7\xe5\xe6@\xfc\x17\xc9\ -\x01 \xbc\x9b^\x96K\x03\xf1k4\xcba\xb8\x9f\xd6\ -\x963\x02\xf1\x1d\x1c\x96\xc3p<\xad\x1d\xe1\x01\xc4\xbe\ -@\xec\x0e\xc4\xb7\xa0\x966\x01\xb1\x17\x10\xfb\x03\xb1\x12\ -=\xd3\xc2\x09\xa8\x03<\x07*\x1b\x9e\x84:\xc0\x87X\ -\x0d\xea@\xcc\x0f\xc5\x1aP>>,\x0f\xc4,@,\ -F\xb1\x03\x80\x8av@\x15\x17B\xf1\x7f\x22\xf0U \ -V\x80\xb2\xb7\x90\xed\x00\xa0\x02\x0e \xfe\x0aU\x9c\x0b\ -\xc5\xc48\xe0\x1c4\x14`|\xb5\x81v\x80\xfa\xa8\x03\ -\xd0\xcc=\x0b\x15\xf7\x1d(\x07\x14\x03\xf1Jtq\xba\ -9\x80\x94\x02c\xd09\xa0\x80H\x07\x5c\xa6\x85\x03\xf2\ -\x80X\x18\x88\x83\x818\x10\x0f\x0e\x82\xd6\xfb\x92\xd4v\ -\xc0cP\xe3\x01\x88w\x11\x89OQ\xdb\x01\xc4\xe0\xdf\ -@\xfc\x0b\x88\xff\xa0\x89S\xc5\x01_\x09\xb5d\xa1\xd1\ -S\x01\xc4\x86Hu\x08\xd5\x1c\xf0\x05\x88E\x08\xa8?\ -\x04U\xdbF+\x07\x08\x10P\xbf\x1e\xaa\x0e\x14\x0a\xdb\ -\xa9\xed\x00P\xfc\xd6\x03q\x11\x01\x5c\x0c\xcd\xb2wp\ -\xd5\x86\xa4:\xa2\x05\xea\xabo\xd0\x04\xf6\x9b\x00\x86\xa9\ -\xf9\x0eu\xfcvj4\xa1\xd8\xa1\xa1A2\x1e\xed\x84\ -\x92\x03\x00\xf9}\xdcv\x87\xa5\xe0^\xe3\x07\xa0\xd1\xc6\x9f\xc8\x81\xcf\xc5T\ -\x81;\xb0\xdb^0\x12\x9ac\x5c\x0f%\xa0N\xf1\x07\ -\x9a\xf3\xaa\xbd`\x18\xbf\xca\xb8\x06\x1a\x0c>+n\x93\ -\x03o\x8a;\xa1\xa1\x7f;\x80?\xe4@\xb7c\xb0\xdc\ -\xc6\xae\x07\xcf6\x1e\x07^\x02;PL\xa7\x16\xc3\x96\ -\xd8\x87\xcc\x04\xdfd\x9c\x04/\x83\xfa\x8asq\xcdg\ -\x14\xc5)`\xce\xe7\xe0\x0fW\xd8\xd85t\xc2\x98!\ -\x9d\xcf\x87X\xce\xe7\xc2^nNN\x05O3\x1e\x0b\ -\xbe\xd9\xd6DB\x5c\x10;\xf0\xac\x85\xfc\x12h\x96q\ -\xad\x1c<#~[s^\x123\xccC\xa0[-\x05\ -\x8b\xa0A\xe0\xd3\xe2\xbdr\xe05\xf1o\xd0\xc5\xee\xc0\ -A{a\x09Tg\xbc\x81\xf94\xee\xd0\x9c\xc3\xf6\xc2\ -\x22\xa8\xc9x%4\xc6\xf8\xb0\x1c\xf8\xd2\x16\xe1X_\ -\x03\xdcR/b\xb0A\xdc\x07\xda\x04\xde\x0e\x9b\xa7\xb1\ -%\xe0\x97aS\xe2\x09\x5c\xbc\xb0\xf5\xe2~\xe0-\xb0\ -\xdbx-'\x97\xe3\x9as&\x8a+q\xbd\x07\xaa\xf9\ -\xa7Z\x90\x888\x0b7\xf6\xf61pn\xc4\x89\x88{\ -b^v\xf4\x9c~\xff\xc5a\xb0I!\xee\xe0\x82\x81\ -J\xa1?\x15\xc2i\xd1\xbe\xdf$^-\xfeZk\xa4\ -\x1a\xdc\xa9\xf0\xa6\xe8\x08\xf8S\xf1:9\xb8>\xd4\x05\ -(\xc7\x1d\xf8\xc2r\x5c\x0d5\x1a?\x05\x0d7>\xa9\ -9G-\xc7\xe5\xd0\xc3\xc6\x5c7E\xc6\xed\x8a\xe87\ -\xb6\x06\x92\x1e:\x96\xd9S\x18\xdc\x0f\x9b\x09]\x0a\xf1\ -\xcb\xbe\x87-\xd5=\xcf\x83\x7f\x86\xbdG\xbc\x14\xfc\x13\ -,\x0bR\x0f\xd5\x09:\xf5-T\xc81\xed\x94_B\ -\xce\xc1w\x89_\xe0{2\xba\xcd\x0f\x9e]\x0b}\x05\ -\xafv\x88Y\xfb\xdb\xc0\x1f\xb2\x00il\x03\xf8\x08\xf7\ -\xbbU\xbd4\xec\xd3\xe2a\xe0\xfd\xb0\xef1e\x8aR\ -\x0b\xa3\xc2\xba\x22\x9e-n\x89\x1d\xf8\xccr\x5c\xc9\x83\ -\xc5x\xa3\x8aS\xe0\x13\x9a\x93\xb6\x1cs\xd1\xae2^\ -\xc7\x0aiLG\x99\xda\xa3\xb6\x06\x0a}\x0d<\xa1\x9b\ -\x99\x9f\x81\xd0\xd5a2\xec<(K;\x84\xdc\xaa9\ -[\xc5'\xa0\xfe\xd0\x8c\xe0$4Su\xe1\x07\xf16\ -9\xbdK\xdc\x01\x0d\x88\xa3P\x1c\x0e\x1a\xf1\x08\xf0\x18\ -c\x1eXe\xd1\xbe/\x09\xfd\x82\xf82\xaf\xf3r\xa2\ -\xb0\xdc)\x8f\ -\xc3\xce\x15\xf7\x047\xaa\x17\xe8%\x07nT\x0aG\x8b\ -\x0b\xc47\xc4\x0e\xb4Y\x8e\xd9\x5c,6^\x05]d\ -\x9c\xd6\x9c\x03\x96c\x9ezu\xc6\x0d\xd0(\xe3\x83r\ -\xe0#[\x03\xa3<\x94\xaf[\xcey\xec.4nV\ -\x8e\x03\x87\x83\xe5-\xcb9_v\xa7\xf1\xdd\xd0p\xe3\ -w\xe5\xf4\xfbbj\x84G\x80_\xd8\xc0\xf3\xdc\xc6\x16\ -\xe8\xa1=\xc4U\xe0\xfb\xb9\xdd\xc2VU\xc8'\xd9\x87\ -\xb0\x07\x5cj|\x15\xb8\x99\xf7\x8a\x87\x88Sq\x0a\x98\ -\xf3I\xb8a\xa4\x8d\x95\x80\xab\x8c\x07\xab\xe1\xc8\xb1\xc3\ -j2\xb7\xa8\xbd\x90'd\x85\xf1P\xf0\x14\xae\x0fq\ -6\xae\xa7\x9e\xd7\x8e\xe9aaK\x9dU\x11\xba\xcer\ -\xce\xe6\x82\x13O\x8a_\xd1\x9c\x9d\xe2_\xd9|\xb0\xd8\ -X\xce\xd99q;\xff(n\xb5r~\xee<\x81\xf2\ -|\x0d\x1c\xb2\x1cO\x84V\x18\xb7\xf0K\x8c\x8fkN\ -\xdar\x5c\xaa\x1d\x13x-4\xde8\xad\xb3\xa1\xdd\xd6\ -\xc0x\x8f@\x15[-\xf6\xf5\xa17\xa0\xd7\xe0\xbdl\ -\xb74\xc65r\x00v\xba8\x05f;\xbfF<\x80\ -\x87\x0c\xec\x1e\xae)9\xf9 w\x0b4Yc\xdfy\ -\x8e\xb2Y\xb4\x1c\xa7\xb4\xf7\x03o\xe6\xee0>\xa59\ -\xc7,\xc7\x15\xd0\x1a\xe3G\xa0\xa4q\xbb\xa2\xf3\x9d\xad\ -\x81\xa4G\x80\xfb\xfd4\x06?\xa6gQ\x04RQ\x04\ -V\xffK\x04\x8a-\x02\x15Q\x04\x1a\xe5t\x93x_\ -\x9c*>0\xcf\xbb\x14\x9e\x01\xa1\xbb\xb5H\xe5G<\ -(\x14*\xfb\xc7#a\x9c\x19\x8a\x90=7?\xa3;\ -\xfd\xfe\x02\x18\xfc\x86\x85\xa5`T\xfb\x00\x00\x00\x00I\ -END\xaeB`\x82\ -\x00\x00\x00\xfc\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xffa\ -\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\ -\x04gAMA\x00\x00\xb1\x8f\x0b\xfca\x05\x00\x00\x00\ -\x09pHYs\x00\x00\x0e\xc3\x00\x00\x0e\xc3\x01\xc7o\ -\xa8d\x00\x00\x00\x91IDAT8O\xa5S\x81\x0d\ -\x80 \x0c\x03b\xf4\x1c\xff\xffB\xcf1\x9a\xa0%T\ -q\xbaa\xa4I\x1dts\x14P\x1fct-\x08\xdb\ -<\xbcv\x80\xae\xe5n\x80\x03\xc9u\xea\x8fp\xc5\x92\ -\xd0J=mA\xae\xd4\x8d\x8bG\x84\xce1 \xe7\x09\ -\xec\xca\x8e\x92V\x0e<\x07\x7f\x9b\x84l\xc4\x04l\xab\ -\x87\x8a.\xb5\xd5\xad|z\xb0@\x16[/\x92\xe7\x16\ -x\xc2\xb4\x9b\xe5*\xd4/\x91M\x1e\xd7V \xd5\xd0\ -J\xcd\xae\x96W\x93_\xb5\xdb\xa4d\xcd\x11\xd9\xfe7\ -\xe6hB\xbf\x15\xe7v\xf1\xcd\xb3\xd1w\xeb$X\x00\ -\x00\x00\x00IEND\xaeB`\x82\ -\x00\x00\x02\x14\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\ -\x00\x00\x01\xdbIDATx\xda\xed\x97\xbfKBQ\ -\x14\xc7E\xa1!\x10,tk\x08\xda\x02\x1bj\x8eR\ -hj\xd1!\xe8\xd7\x90\x8deCS\xd1\xd2\xd8\xd2\x16\ -iC\xb4e\xf8'\xb4i:YTCC\x8bA\x16\ -M\x85IF\x93\xda\xf7\xbc\x8er\xb9\xdcgO\xbb*\ -\xc1{\xf0\xe1\xf0\xe5\x1d\xef\xfdz\xcey\xf7\xa9\xc3a\ -_\x1d\xbe\x96V7\x92\xe0\x0e\x0cu}\xf3\xc5\x955\ -\x176~\x0650\xd6}\x03\x91\xa8\x0b&\x0a\xa0\x06\ -\xfc\xbd\xaa@\x81+`\x1b\xf0\xdb3\xd0\xabs\xe0\x91\ -\x0d\x8cZq\xbc\x8f\xc4\x0b\xe0\x01G\xd0i\xc4T\x1d\ -\xe8\x94\xa43\x88\x9b`\x02\x9c@\x0f#\xd2\xb7^\x06\ -\x0b\xd0\x14_\xd9\xc0\x16\xf4<\xdf\x1bQm>\x83\x9e\ -\xd5\xb8_>p%\xe8\x1f\xd4\x9a\x8c\x06YS\xbf=\ -\xa0,\xdc\xaf\x82\x8a\xf4\xf9YU\xa9Bt\x93\xddz\ -AN\xd0\x06\xb4\x90\xa4)\xc6@\x80\xf5;b?\x18\ -\x07\xb4qU\x91\xbfk\xd6+\x1d\x06\x8a\x88n^o\ -N\xf1\xf9D\xb3a\xd1j\x80\xdb\xba#\xe4g\xa1\x9d\ -\xcd\x060$\xf4\xc8\x0br\xac+\x0d\x22\xd1\xaa\xa4\xe9\ -~\x0c\x04\xb8\xc7ED\xb7\xb4\xee)x\x02\x03\xbf=\ -.\xda+\xc0\xeb:\xe9\xa9\xb2\xf2\xbcv\xc4@+\x07\ -\x86l\xe0Ra@5\xd5q-\x06\xa4\x19\x18\x04\xe7\ -\xd0\x1f\x88\xa5\x06\x91hI\xd2\x9f\x88{`\xdal\x06\ -\xda\xad\xc0\x14\xa0\xc3\xc8\xcb\xd500\xd1>\xb0\xae\xbb\ -\x05b\x89[\xd1\xda\x0c\xbc\x80\x03\xe88\xf7\xd8@\xd0\ -1I\x97u\xcf@\xdaB\xfe-\xf2\xef\x11'A^\ -\xf7\x0cd,\xe4\xd7[\x10\x06y\x1d-\x08\x0b\x06\xd2\ -\x16\xf2\x0f\x91\x7fL\xefy\xf0 \xbc\x8c\xda6\x10\x14\ -\x0c|\x81\x1b*3b\x03I\xd3A\x95C\xbc\xa67\ -\x1f\x1bxC\xec\xfb\xcbo\xb8m,r\xc6$\xa1\x93\ -F\xacc\xae)?\x01\x1d\xb0\xff\x0b\xfe\xbb\xeb\x1b\xc9\ -\xfb\xd7\x13\xad&L\xa9\x00\x00\x00\x00IEND\xae\ -B`\x82\ -\x00\x00\x00\xd0\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xffa\ -\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\ -\x04gAMA\x00\x00\xb1\x8f\x0b\xfca\x05\x00\x00\x00\ -\x09pHYs\x00\x00\x0e\xc3\x00\x00\x0e\xc3\x01\xc7o\ -\xa8d\x00\x00\x00eIDAT8O\xdd\x93\xd1\x0a\ -\x800\x08E]?.~\xb9atc\xc55\xad\x97\ -\xa0\xf32\x86\xf3p\x057\xdc]\x18f\xc6\x0b;\xaa\ -:\xe2<\x04s\x03\x8aA&\xc2\x9be\xbb]\x88&\ -4\xce2\x06\x15\x80\x8e\xe4V\x10d#\x80RP\xf1\ -Z\x80d\xdf%\x00\x7f\x12T\x1b\x97qJ\x10\x92\xa7\ -\x22:BG\x84z\xfa\x9d{\x88\xac\x1d\xf5-\x8f\xc3\ -r\xe1\x95\x00\x00\x00\x00IEND\xaeB`\x82\ -\x00\x00\x04M\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\ -\x00\x00\x04\x14IDATx\xda\xcdW}L\xceQ\ -\x14~U$\x94\xbc\xd2\x87,\x9f\xf3\xe6\xcd|d-\ -LS\x93lY6\x9f+[MM\x85B\xc3l6\ -b\xfc!B\xd6\x1f\xac\x86\x0cM\x96\xcfe\xb3\xd9d\ -\xf3\xfdG#\xf9\x1c\xcd\xb0\xcc\x98\xaf\xc9V!y\xce\ -\x9c\xcb\xd3\xf5\xf2\xf7\xdb\xf6\xec\xbe\xe7\xf9\x9ds~\xe7\ -w\xefs\xef=9\x1c\xde\xf0\x97\x91\xbd2\x1a8\x9e\ -\xbe\xa4\xb0\x88\xb8`\xd8\x071\x96\x00=\x85\x83\xed\x87\ -\xdf\xdb\x81*\xc0I\xbe\x85@\x0d\x9e\xbb\x89\x9b\x0b\xfb\ -$\xc6\x14\xc3\xc1\x8e\x85}\x0a\xc8\xb1\x0b\xb8\x05t\xc1\ -\xa1\x0b\xe3\x04\xe5\xf6\xa9-\xc8\xd3\x049j\x0b*\xd4\ -o\x9c\xe1\xf0\xfc\x8er}\x80o\x1a\xdfI\x05<\xa2\ -\xf8\x91\x5c@\x1d\x150B\xb9b*`\x9e&\x98C\ -\x09\xb6\xa9\xdf0*\xe0\x82r>\xc0'\x8d\x7fC\x05\ -\x5cU\xdfN \xdcA\x0fz\x03y \xe3\xac\x99\xc9\ -\x02\x9f\xca\x1c\xecY@\x96\xc5\xc5\x02\xcb\xe0\x1f@\xdc\ -P\xd8\x05\x18#(_ l\xe1\xc6:\xbc\xea\x0f\x95\ -\x0d\x14q\xa1\xb24\xe2z\xc0\xde\x841\xdf\xf2]\x0a\ -\x08\xefK\xdcl\x8d\x0f!Nfe\x17F7\xcdJ\ -\x04\xecR`\x86]\xc0\x15\xd2\x80[\xb92\xd2@\xa6\ -&\xc8 \x0d\x94\xd3\x0e2\x1a\xb8\xa9\x5c/\xa0]\xe3\ -\xdb\xa8\x80\xbb\x14\x1f\xc5kXo^f\xb6\x12\xc6R\ -S\x14\x90\xa9\x893\xd4\x16\x94\xa9_\xb4\xe1\xf0\xfc\x9a\ -r\xfe\xc0\x17\x8do\xa5\x0f\xbdM\xf1Q<\x0325\ -;@.$N\x92l\xd6=\xde\x83\xf8\x02`\x0b\x0b\ -Nv\x09\xb0\x13\xfe\x83\x89\x9b\x02{\x0f\xc6\xf1\x960\ -\x85K\xf5:\x11\xf6\x05\xb2Qa\x9c\xb5\xbd\xd2\xf9$\ -S\xdf\x99@\xba\xc5\xc9\x09\x97\x03\xff~\xc4\x0d\xd7\xad\ -\x1dI\xf9\xfa\xc3\xce\x05b\x1c\xd6\x8bN\x93\x06\x86*\ -\xb7\x814\x90f\xd4NkX\xac~Q\xa4\x81:\xe5\ -|\x81\xb7\x1a\xdfBE\xd5\xabo\x1b\x10\xc6_\xd0@\ -\xbb`\x92r\x15\xb4\x0b\x96k\xe2\x5cR\xf1!\xf5\x1b\ -O\xbb\xa0\x89\x8e\xe2\x1f&\x9e>\xf4\x09\xc5\x8f\xb2/\ -\xa3Z8\xac#.\x08\xf6\x11\x8c\xbb\x01?\xf3e\x22\ -6\xe0\xa8\x5cV\xe4[\x04\x9c\xc4\xf31\xc4\xcd\x87}\ -\xce\xba\x8c&\xc0\x16.\xd7\xbbD\x88\xca\xe4\xd4\x9b.\ -\xdb\xd1\x12W\x1f\xd8\xc9|b\x9a\ -\x07\x95\xba\x86\xdf1\x86*\x97O\x1aH\xd4\xa4\xd3h\ -\x0d\x0b\xd5o\x10\xf0U\xe3\xab(g\xb3\xc67QQ\ -g4\xf6#0\x80\x0b\xb8G\x22\x9c\xac\xdca*`\ -\xb5&(\xa0\x02\xaa\xd5/\x8eD\xf8\xd8\xe8\x87\xf2\xb1\ -\x08\x9fQ\xbc\x8b\x0bH\x00\x1a\xe1\xb0\x9f8\xd9^\xd7\ -1\x9e\x95\x844\xad\xd2\xd1\xdc\x90}N\xbe\xe5\xc0]\ -Y\x06\x16&\xec\x07ryQ\x01ri\xdd\x97\x8b\xcb\ -\xe1u\x7f\xd2\x09\xa1\xc2\x00K\x5c\x91rU[~N\ -`\x88\xc5\xf5\xee\xd6b\xfd\xb9\xce]\x1e\xde\xe32\xdb\ -\x9a\xc9\x12]\xb3wf\x7fc\x5c\xa0k\xd8\x0eL\xd4\ -\x82\xe4\xd0i\xd35\x5cL\xeb\xfdZ\xe3K\xb9\xcf\xd4\ -\xf8K\xf4A\x15\x1a\xfbT\x0e+.\xe0!\x89&A\ -\xb9c$\xc2\xb5\x9a`\x15\x89\xa8F\xfd\xa6\x92\x08\x9b\ -MGm\x8bPg\xe4\x05\xc5\xbby\xaa\x17\x01\xefA\ -^\x943A9\xe9v_I\xa7\x0b\x84k\x92P\xfc\ -\x96;]x3+\xb2\xb7\xcf\x03\x1f\xa4_\xa0\x9c{\ -a\x7f\xc6\xb8\x95\xbb)\xd8\xc2UK\x9c\xd7\x890\xd8\ -\xaeJ\xaeWiL,?\x7f\xe9n-\xce\x87\xef\x06\ -\x8awzx\x8f\xd3\xd3\xcbW\x88\xb8\x10\xd0(\xfd\x9c\ -r\x892]\x18[\xcc\xcd\x05{8~\xbf\x04Z\xe5\ -\x98\xa5\x82\x1a\xb4\x07\x5cM9O\xc0\x96\x13\xb2\x92\x0a\ -\x92f\xb6\x03\xb8l\xfe\xdb\xfa}MR?\x90\xa4\x5c\ -\x0d\xf5\x03\xeb5\xe9\x1a\xea\x07j\xcd\xf1L\xfd\xc0s\ -\xf3\xe5\x94\xaf\xcbhE>\x86\xe2c\x1cV\x9f\xd7\xae\ -]\xab?\xcd@\xeb\x7ff \x85\xce\x00\x99\x81\x0e\xd9\ -%\x94\xb3Vg\xe0\x00}\xe8F\xbd7\xba\xcf\x80Y\ -\x1b\x0f\x1a\x08\xfa\x87\x06\x82\xecC\xc7\xd3\xda\xfeu\xeb\ -\xfd\xf2\x0d\xf1*\xf1\xff\x04\x8f\x07^\xb5\xbe\xa8\x80\xde\ -\x00\x00\x00\x00IEND\xaeB`\x82\ -\x00\x00\x00\xd0\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xffa\ -\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\ -\x04gAMA\x00\x00\xb1\x8f\x0b\xfca\x05\x00\x00\x00\ -\x09pHYs\x00\x00\x0e\xc3\x00\x00\x0e\xc3\x01\xc7o\ -\xa8d\x00\x00\x00eIDAT8O\xdd\x93\xd1\x0a\ -\x800\x08E]?.~\xb9atc\xc55\xad\x97\ -\xa0\xf32\x86\xf3p\x057\xdc]\x18f\xc6\x0b;\xaa\ -:\xe2<\x04s\x03\x8aA&\xc2\x9be\xbb]\x88&\ -4\xce2\x06\x15\x80\x8e\xe4V\x10d#\x80RP\xf1\ -Z\x80d\xdf%\x00\x7f\x12T\x1b\x97qJ\x10\x92\xa7\ -\x22:BG\x84z\xfa\x9d{\x88\xac\x1d\xf5-\x8f\xc3\ -r\xe1\x95\x00\x00\x00\x00IEND\xaeB`\x82\ -\x00\x00C\x13\ -\x00\ -\x01\x9f\xd1x\x9c\xed\x1d\x09\x5c\x8c\xdb\xf7\x9bR!\xd4\ -\xc3#)e\x8dl\xf9{\xc8Z\xf6}_\x1f\x22<\ -\xbb\x92\x84,\xd5\x90%d\x97\x9d,E$B\xa4\x92\ -\x22\x22k\x12\xd9[H4\xed{\xd3\xcc|\xff{\xee\ -\xf7MM\xd3LM3\x93&\xba\xbf\xdfy\xbdI\xf3\ -}\xf7\xdes\xee\xd9\xef9\x04\xc1 T\x09\x18\x0cB\ -\x9f\x98\xa7M\x10\x0b\xd0\xff3\x99\xd4\xe7\xb65\x19D\ -\x18\xfa\x9d\xa9)\xfdy\x00A\xa4\xb7`\x10FF\xd4\ -g\x8f\xd6\x04\xd1d>\xfa?}\xfa\xb3&A\xdc\xdb\ -\xc1 45\xa9\xcf\x8bj\x10\xc4\xe2\xe3\x0cb\xfb\xb8\ -1C\xeb\xd6\xd6\xae\x8d\x1e]w\xf8\xb0A\x13\xe0_\ -\x01j\xc2\xabgZ{\xa0wj\x1b\x0e\x1f\xd4\x7f\x92\ -\xed\x87\xe4\xcf\xa3\x975\x88\xfa\xa2\x9a\xf6\xa8\xd5\x18+\ -\xa2\xc1\x86\xe8e\xdeM\xe3w\x5c>1\xe4\xb9\xd9?\ -\xb5/\xd5\xb09p\xd0\xccP\xe5\xcc\xe5'\xdb\xa6]\ -\xf3h9\xcd\xac\xd6\xf8I?\xaf\x98\xaeh|\xd9P\ -\xc9\xac\xf9 \xb7\x05C\x0f\x8c\xaeU\xbf\xc5\x88\xc6\xcf\ -'\xef\x98\xda\xff\xf9\xf1\xd0eg{t\xeb\xb4\xeb\x80\ -\xf1\xf6\xe8\x87\xcf\xb4\xe6-{\xa4\xd75\xd3\xa4k&\ -\xa7\xbb\xe9\xf4\xb4\xf4w\x09G3\xbb%\xe4Y\xfb\xe9\ -8=>~\x8c\x11\x9c\x909\xfcp\xc8\x94\x93\xd7n\ -\xae&\xec\x08\xe7\xd9\x8c\x98\x06\xdc\x97\xdf\xec\xdb\x11\xe4\ -\x1b\x87\xa0\xd3\xe4\xda9\xad\xbf\xec\xdb\xdf\xe9\xc8I\xf4\ -\xf7\x1b\xfcf\xbex\xc3\x08o2\x83\xe58%\xcc\xe4\ -\x95C\xb2r\xfb^.\x8765\xaa\xa9\x1e\xae4\x17\ -\xfd\xdd5}\xb3\xb6\x9e\xb7\xffG\xf4\x9a\xb7\xd4\x8c\xd8\ -\xca8\xa1j\xa5z9)\xf2HC\xe6\x05b\x01c\ -\x94\xd7\x83\xde\x87\xdc\xd5\xffk\x14U\x83i\x7f\x98\xac\ -=\xfda\xea\xfeN\x1a~\x1f\xfe\xc7lG\x98\x18\x07\ -\xae\x8a\xf9A\x84\xa7f5>=\x99\xd3\xe9g\xc6^\ -\x83\x8e\xcay\x8c`e\x83[ut\x9a\x10hns\ -\x88\xd9\x03\x97~ip1\xae\x1d3uJ\x9c\xee\xc4\ -\x08\x95\x8b\x87\xe6)\x99\xea\xdd\x0c\x22\xbc\xe2\xd6\x0c?\ -\xbc\xcdc\xd3|\x22\xba\xff\xd2\xbf\xdd\xdc\xd4'n\xcf\ -`\x9c\x9e\xca\xd1\xf2\xd9\x11\xdd\xc9\xac\xd9Ym\xb7\xd3\ -*\xfdg\xbe\xd1\x1f\xd7\x0b&\x16\xcd\xfc\xdb\xf5Dg\ -\x15\xaf\xa5i\xbbl\xfa\xefh\xd7\x84X\xa7\xe7\xa0\xb3\ -,\xf1@@\x07e\xad\x89\x8b\x9dM/\x12\xe1C\xb3\ -S\x1d\x1d\xd7\x7f\xb3\x1c\xcb\x989i\xce[\xfd\xc3O\ -c\x996\xcd\x99\x1bV\x92k\xbc3\x0e\x14\x9cd\xa4\ -\x05\xf0N66\xf8\xa0\x14\xde8\xed\xd3\xa3\x80\xec\xbc\ -A\xb3\xae\x13^\xdd\xbc\xf5\xd3\xe3\xcevd\xbex7\ -\xbdN\xf0K\xf3x\x83\xd4D\xe5\xb4\x1b\xb3\x1a\x0fz\ -\xf7E)\xfcBN\xca\xc0\x19\xb7F\x0e:\xd6n\x91\ -\xd7\xc6\x83f\x9d\x17\xadW7]\x9eA\xd6\x99b\x7f\ -vnH\xf8te\xbb\xd5w=,\x18\xa7\xc7\xa6^\ -\x0b\x1b;i\x96\x9e\x8f\xa6\xd6-\x96\x8aE-\xf4\xb0\ -\x0f*\x84\xc9\xa6\x9d\xeb\x9cr^\xd7\x8b\x19\x1a\xf8b\ -\xda\x8b\x0c\xe2\x87\xb3\xd7\xe7mo\x13\x0c\xce&~\x8e\ -b\xedv\xefP\x97\xe0\xd6\x9d\xe9\xcd\x1e\xad\xe9\x17\xa9\ -\xe290\xf8:\x81^\xfe\xbf-\xee\xcd\xcd\x87\x13\xde\ -\x19\x0d\x8e>\xb9\xaei\xd4\x97\x98\x96\xbf\xbd\xc3\x9c\xe1\ -5\x8fh\x13\x979\x83\x0e\xfd\xafo\x8dQ\xea\x84\xdd\ -\x87\xb8M\xcf\x1bo~\xbc\xb4\xd3\x91\x9e\x83\x17=\x99\ -`n\x17{\x7f\xcf\xf5\xa8-\x8f'\xde]f\xb3\x9c\ -11G\xb9\xed\xb4/\x1f;\xd9\x0dv\xea\xd3J%\ -&s\xc8\xa9V\xcb\x8c\x89,\xb5\xf5\xf6*kR\x9b\ -\xef\xf7&:\xd6\x98\x90\xcd\x99\xdf\xb5\x99\xaa\xbf\xc6\x14\ -\xfb\x16\xed\xec\x16Y\xb9X|f\x9c6\x09\xe9\xd3\xc1\ -N\xc5\xa9\x8f\xe5\xed}\xdc\x1a\x89\x89J\xde\xd1c\xdd\ -\x0e6L\xd4\xd2X\xe4\xa6n\xa5\x87^\x7fi\xd1\xd0\ -\x93f\x1b\x8f)\x9bF?\xf3\x1e\xcb\xd6m\xf0j=\ -;\xf1\xfd\x22\x9f\xf3\x9d\x98wW\xe5\xa6F\xa4\x1et\ -z\xc2^xs\xc6\xee\xa8\xd7*1+\xb9\x83\x96x\ -^\xdc=E\x97`/\x09\xea\x1a\x91\xba\xdb\xc9\xb0\xd7\ -\xc4\xa7\x87\xe6\xde\xf4!B\xdd\xa3\x9b\xfc5\xd9=\xd1\ -\x7f\xfad\xe2\x87\xa3\xbaYD\xea\x0e\xa7K\x11\x93\x93\ -\x991w\x1d\x99l\xeb\xe8\xe8{\x8bMZ\x18\x0c\xef\ -\xdfTs\x94K\x81\xde%\xdd\x1a\xce\x1b]\x5c\x1f/\ -\xfep\xe6\xcd\xe7\x1d\x86\xb7\x08\xdb\x5c\x03k\x9f\x86\x86\ ->J\x97\x163f\x12\xedM\xf6M\xbc9\xcfu\xf4\ -\xbac\xb9\xf9jw\x0fu\xb0k\x15\xb9y%\xd7k\ -\x15\xc95y\x9bk\xd43\xa8]~#'7\xbb\xba\ -\xfa\xb3RL\x0e\xd5%\xec>\x9e\xe9\x14\xb6\x7f\xe8\x00\ -5\xcd\xa6K<\x0bR_v\x9c\xdf\x84\xf8\xb6\xca\x0c\ -\xd1\xa9z\xfb\xf4\xddj\xee\xbcy\xee\x9d\x82\xa7F\xb4\ -6h1\xf1\xa0\xd7\xd3\xd6\xca\xa6\xb33\x1d\x86\xf8G\ -\x0e\xfaoG\xd7u'y\xa6~\x8d\x82U~\xd6o\ -\xb0\xefb\xa7\x83\xec9~\x84y\xa6\xebc\xb3\x11o\ -\x7fj(\x99F'_\x18\xe9\xef3\xe8\xbfK\x9d\x02\ --\x83.LRg\xaeqh\xb1\x86}\xda\xf2\xf01\ -U\x9dC\x9dZ\x87\xed\xd8z\xfc\xaf:y\x9a\xb5\xba\ -\xc5\x9e\x0b\x0fX?(\xebvN\xe6\x84\xfaa\xban\ -=V\xe6\x9b\x04\x8dJ\xd1?\x196g\x95\x9d\x86'\ -+ b\xf9\xf6\x7fB\x88\xd0\xda\x0ei\xb3\x88\x1f-\ -\xb7\x98E\xb8\xb7Z_\xc7\xa6\xe0\xaf\xba=\xbe\x9e\x9b\ -\xa7\xa6Y\xb7GB{\xfb@rJ\xeb!\x9a\xcf\x02\ -\x9f\xc4\xed\xc9\xee\xdbj\x7f\xefa\xad\xd6\xb8u\xde\x18\ -e\xb3*\xf4\xad\x7f\xed5u\x0c-\x19uF\x1e\xde\ -{\xf9\xafZ\xdd\xe6\x9c\xfe\xb8\xe7\x80\x01\xc7i\xebq\ -\xcd\xba\xa9\xbe5#\x93\xa2L\x98\xc3~\x04\xab\xf5\xef\ -\xe2{\xf0\xe1'\xcf\x0e\xb3\xda\xac1\xf2=8\xb8\xd7\ -\x01\xcf\xcc\xbf=F\x84\xb4\x9d\xd6d\x1a\xa7\xa3qG\ -\xb3^\xff\x8b2_\xaenYOoH\xab\xff\xd8\xc3\ -\xd3\xcek\xfd\xc8\x09j\x5c{\xe5\xc8\x7fG\x91\xb7v\ -\xf9\xb9w\x98Q\xf3\xad\xf1\xae\xda\x0c\xab!\xfe6\xb3\ -\xfe\xfb'h\xfd\xee\xa5k\xbe\xdb\xb4\xd9\xd6\xbe\xc1\xe2\ -\x89\xbc\xe4SV7\xae\xbb\x04\x1d\xbco:\xcd,:\ -\xe4Y\x5c\xa3f\xe4\xf5\x87FF/\x8f\xde7\xf9\xa6\ -l\xea\xdab\xd1\xe1N'?\x0e\x1e0\x1aM*\xbc\ -\x81ehp-\x870\xfb\x1e\xc7\xef\x1d\x1b\xf6\x83\xe8\ -t\xb2^L\xc4O\x02mL\x1f\xde|\xf5\x03\x99\xc7\ -\xef\xf4\xdb\xb58\xd5\xd9+\xbb\xc96\xa7\x86\xb7\x08\xb6\ -\xdb\xc8\xef\xdd\xef15^Yu\x1d\xb3\xba\xe0\xaf\xbe\ -W>\xc7{\xfa5m\xda2M\xa7\xaf\x83\x81\xb6e\ -\xe8s\xab\xaeh\xca\xf7\xbfq\xe0\x95\xdb\xfd\xdc/\xdb\ -\x5c;qI\xe3\xc3\xbd\xb3\xa9*\xc1\x06\x11\xee\xd6\xbd\ -\xe6M\x0aL\xb0]\x19\xa2l\xf1\xcaH\xf9\xf4\x89}\ -\xbc)\xceY\xbes-\xdb\x1d_\xfe\xf7\xb8\xd1\x19\xab\ -\xcc~6\x0aNd7\x8b{\xdd\x94\xa2\x9e\x0e\xedg\ -\xac\x08\xb2\x0bZ\xec=={\xf3\xf1.7n[\xfc\ -\x9b\xff9X\xab\xb3V\xd3%!yY\xaa\x8e\xa7\xd7\ -\xd9\x85.o\xa8\xc14s&'9\x10G\xdcoG\ -[\xae\x9e\xdfy~\xcc\xe6\xec\xab\xb1\x8d\xf6\x853>\ -5\xe9\xfbL\xdfc\x96k\xfa\xf1\x05\xfaA\xb9\xb3\x03\ -l.N\x1a\xf7i\xb9\xde\x8f\x9c\xa8@\xe3\xf3\x7f\xad\ -\xde\xec\xfcQ\xab\xbfU\xca\xeb)\xcec\x97[9\x9f\ -\xbe\xb3:\xf0\xc5\x05\xe7F\xa6\xae6\xdb\xdd\x1a\xe6|\ -T\xf3\xe7\x8e\x18}tp\xc8\xf3\x13\xbcK!\xa6\xbe\ -z{\xfc\xf7\xcc\xb5\xb6W\xff\xfa\xba\xa9\xce\xc8v^\ -\x1a\xc1\x13[\x12\x1f\xdcG\xb6\x8cuxD\x0e\xf5\xaf\ -\xf9w\x17B\xbbkD\xf4\x8e{_\x1a\xa1\xa7\x99\xcf\ -\xed\xde\xd2L\xe7\x8d\x8fr\xea)\xd5\xa4\x03\x9dvm\ -\x9e\xac\xaeV\xeby\xf8\xca;\xc3\xfdk\xeen\x5c'\ -\xcfje\x9ef3\xb3\xbeK\x0a2\x16>\xccf\xdc\ -A+\xea\xbc\x5c\xbe\ -\xd9jaV\xcd!l\x8d\x16\xf5\xaf\x9f\xef\x9c\xb4Y\ -\xc3\xd5\x8bXZC\xb9_\x1f\xffu\x91\x99fJ3\ -\xee\x9aeg\xcdoyF9\xbf\xb5+\xb3\xbb\xf9\xd4\ -w\xf3\x8d<\xb7\xec\x1d\x96\xd2\xd6,l\xddn\xcf\x19\ -\xdd{\xdcF\x13\xeb\xfb\xe8\xf8\x8a\xa5\x89^\x06\x015\ -\x0e9\x04\xb48\xd3f\xe2\xf7\xb7\xedU\xee?\x8b\x9b\ -\xf2YoV\x0b?O\x1b\xc2J?|]K\xae\x17\ -\x22L+^J\xd3\x97[\x98\xf1f\x84\xe7\xdd\xe0!\ -\xfa\x08\x95\xce\x0fI\x8e\xf2\xd8+\xbeQ\xddN\xe7f\ -\xdc\xfc\xd0\x95\x810\xbc\xcf\xc5iV\x03t0\xc3\xb2\ -\xe7\x8d\x88\xaes\xd9|-1\xe95\xd9\xc3\xf1\xda\xbe\ -!^\xc6\xf5L\xb7\x0e\xfb\xc1Lx\xab>\xad\x19\xb1\ -z\xcc\x8d7\x13\x8fN\x9e\xadN\x10\x06\xef\xebz\xef\ -\xeab\xfc\xc3E\xd3\xfb\x1fB\xfb\xfd\xfc[Sv\xf5\ -\xe9\xe5\xb9\xae\xbd\xfe\x93\x8d\xa63\xd6\xb6\xab\x81\x84B\ -o5\xefYw.\x05\xd5\xf7\xfcR;\xed~\xe3\xf1\ -\xddf\xd5b\x8cT\x0e\xbe\xc23\x09\x7fg\xc6\x89_\ -z\xd3\xb5\xd1\xeb[\x91\xdfW2Vg\x0e\xa8y\xfb\ -\xac\xca\xde\x17\xdf\xb4\xfdwz~Q\x22|:\xde\x7f\ -lo\xa9\xc1x\xaa\x14\xfc\x82\xe7p\xce.o\xb3\xbd\ -\xb3\xcb\x93u3\xd9*6J-k|2\xd6]\xfa\ -/a\xecN.\x1f\x17\xf8wp\xc7\xfb\xff\xf9u\xab\ -\xd1!\xc0\x0b\xfd\xc2\x95\xec1k\xbe\xcb\xacU\x17\x06\ -4\xf0\x990ud\xfc\xd2\x85\x87\x16\xddn\xb2f\xc8\ -\x9e#\xab\x17\xed\xac\xdd\xa1`JO\xf4%\xdb\x8b\xb6\ -\xea\xc1\xef<\xc3\x13\x0f=\xb9\xb4\xc2*\x81u\x92S\ -+\xe8f\x8d\xcb\xe3\xc7|\xfd/\xd6z\x9b\xab\xf1\x1b\ -\xc4/B\xef.\x9a8\xf7\xc6\xf4\xae\xd3\xea\x13\xab-\ -\xdd\x16\xbf\xd5\xb1oq1g\x14a\xfe\xbc\xd1\x9c\xd0\ -\xae\x7f\xbf\x0e\xb28jm\x9c\x10\x10lK\xae\xecR\ -\xcf@\x97}{\xf0\xb2s\x93o<\xd8\xfa!mn\ -;O\x0e{\xdf\x12\xf8\xde\x95\x99]\xcf\x91\x1a\x8bf\ -\xec\xbdz%\xb5\xdd\xcdv\x8b\xae\x9d\xfa:\xfa\xc8?\ -\xf1\x81\x1f\x1c\xbe\x7fIdwj\x93\xb0&s\xc6j\ -\x8d\x9c[\xe6?\xe6Y\xbc\xecg\xb0\xf5^\xee\xe1M\ -\xc6\xeb{\xc7\xe7\xd5\x1d\xea\xb5\x98a|\x99\x5c\x8e\xb8\ -\xa1f-\xbf5\xdb\xf4]vG\x1e\xfb\xf7S\xe8\xb3\ -\xb8\xee\x9b&\xf6\xab\x93s+.\xe3\xa2\xe3\x08\xe7\x95\ -\x93\xdak\xa5\xc5\xbe\xf81\xe7DP\xc1\x10\xff\xb6u\ -\xaf]V7W\xbb\xc1&U\xdf\xf8\xd6\xf4L\xf0\xe7\ -\x9dq\xbd\x92ek?2,`r\xaf\x03!\xdf8\ -m\xda$\xf4\xe8\x12\x9e\xfc(~\x22\xc3\xdd\xc4q\x80\ -\xf2g\xfbG{\xd4\x8e|\xf9rs\xe5?\xef\x92z\ -\xbfWWIq.\xb8\x98\xcd\x1e\xf3b\xf9\x5c\x8e\xc1\ -\xc2\xa4]&\x88\xb1\xbal\xff\xa7_A\xce\xd8\xd6\xd3\ -\xdb\xbdq\xaa{\xb3\xe7\xa5\xf8\x09\xcf\xb2\x08\xef\x1b\xa4\ -\x09\xf7\xb8\xdf\xc2\x84\x8bw\x1b\x11\xe3\xe6\xf5\x0a_\x82\ -\xb8\xbd\xb1Cn\xdd\x17\xd1v_\x9d^~C3\xfa\ -\xd9\x22\xf29\xa7\x11s`\x01\xc9\xcc7\xab\xdd\xdev\ -\xf1No\xc4k_|\x19\x13\xfb62z\xc4\xd5H\ -\xe7\xad\xc7\xbb\xe4\x0c>n\xd3%q\xee\x12\x02\x11\xff\ -G\x7f\xc2\x93\xb5\xfe\xd0?K'\xbb\xd6\xcb\x8a\xeb\xca\ -hp\xa3\xc9\x89\xc0\x93\x13\xfcgX\xfd\x9c\x14\xbcO\ -c\xd9\xd1/J\xb7s\xd2:\xb6I\xf0\xed`\xb2\xea\ -\xd1\xa5\xce\x8e\x8936\xfb-\x1e?\xba\xa3\xb3e\xff\ -\x96\x8f\x1e\xce\x083\xde\xf8x\xf1(\x8b\xb1\x8dv\xff\ -Pz\xdb\x89g\xb4\x94\x17t$\xd1\x8c0Ug\xb8\ -\xa4n\x9d\xa2M.V~\xbd\xf3\xe3\x88+O\xf5\x92\ -,V|\xeaY\xef\xd0\x95u\xaf\x1a9,\x8b{2\ -H;\x90\xe4\x05mp\xb0\x5c\xb0\x22 \xb6\xdf\xc9\xc9\ -\x8d\xdf\xd7\xd2;\x15\xe5[sd\xab5i\xef}Y\ -#\xb6f\x9f|\xd52b\xb0\xc7v\xaf\x96#\xb6\x7f\ -\xabW?\xec$g\xb8\xd7+\xef\xd5\xadr\xc3\x1a\xf0\ -\x8e}\xb7\xf7J$\x9b~?\x14io\xd4\xd6v\x9c\ -Wo\xd7\xcdHrd\xae\x89\x8ey\xf1\xe3/\xf7\xb7\ -u\x17\x05L\xd6{\xe6\xbbi\xb2A/\xb7\x99:5\ -\xd1~\x9fH\xca\x99\x17\xb39h\xae\x8a\x0f\xbb\xd3I\ -t\xa4\x1b\x10[4\x12\xee\x84\xbf\x1c7i\xed\xa0O\ -c~\x8e\xaa7\xb5M\x04\xbb\xd6\x04\xaf\x88\x87aM\ -\x9b.\x99GD\xce\xbb\xf2\x83\xb1\xd3z\xa3\xf9d2\ -Z\xff\xe6\xe0#]\xea\xf6\xcc5\xdcy8L\xb7\xd5\ -\xfe\x80\xdd\xd3\x82[&\x7f\x08\x09\x22L\x8fjZM\ -h\x8f\x94\xc6\xb6S\xb4j\x866\xfc\x1a\xd6\xe0\xad\xc6\ -\xf5wo|\xff\x193\xd8>\x7f]\x8fh\xed\xb3l\ -\x8fFJc\x16\xab\xb4\xd5%\xb6D\x1c\x9d\xc9c\xd4\ -\xf7l\xf2|Y\xd7\xa1G\x1b\xb0u\xb9\xf1K\xbd\xce\ -\xf6\x9e\xe3\xfdj\xf1\xa4\xda\x8c\x0b>J:\x0d\x88\xd5\ -K\xff\xd3arW\xf7\xf4=\xff\xa5\x85\xb6\xe5\x84\xb9\ -a>\x0d\xa632\xa6\x0e\x1f\xff\xc6\xf2\xafP\xfb\x80\ -\xe9\xce\xef7&\xf4\x18\x10\xc7\xaa\xd1\xe2\x8c\xf2\x93\xab\ -\xea\xe6\xc4\xc1\xf1\x96;\x8dr>\xbeY\xb89\xf8\x00\ -+9b\xf0=D`\xaa\xcc\x06\xad\xf7\x07$\xf9\xf6\ -\x9e\xd6\xc2\xcfq\xc6D\x87\x9d\x9d_\xea&Y\xf4o\ -\x15\xe9\xb6\xccs/c\x5c(\xa2\x7fD\x0c\xc3\x1b;\ -j\x1bu9\x1e\xd6y\xe0a\x9b+A\x93\xdf\x8f\x1e\ -\x18\xf9\x99\xd8\xf3\xb8FT\xb3\xbb\x7f\xeb1u\xf3\xb3\ -Ng\xcdo\xbb\x93az\xe5\x96\xff\xdd\x9d+b\x0d\ -j\xee\xbag\x8a\x04\xc4\xe3\xec6\x0b\xba\xc6}\xed\x91\ -\xd0\xd0B\xc5\x88x\xdc\xc0m\x06\xc3\xb0\xaf\xf7$'\ -\x86\xe9)\xa4\x02<\xfc\xc69\xf4\x8e\xd5\xd4\xa0\xcd\xc5\ -\xad\xe8\x17\xcd?\xd76\xce\xbd\xc8\xa9\x1f?\xb7\x0e\x91\ -Q\xc7\xc2Q\xdbo\x0as\x87\xf2F\xf4\xa1a\xd8\x14\ -\xe6\x8aE\x97Fh\x11\xdf\xda!\xfa=\xdbU\xe9\xd2\ -M\xa5\xc8\xa6.\x9ai?\x12\xc7\xef\x8b\xea\xb6\xda\xa7\ -\xf9\xfa\xcf\xeb\x0f\xfd\xe5\xe9d06\xcfe\xdd\x80\xf0\ -L\x86y\xd2\xc8\xb6\xfd\xaf\x9b$\xce\x0f=\xefS\x7f\ -\xac\xfa\xa5\xd5W\x1c\x13\x02\x88\xfd\x13\xbb\xe6\x9e\x9a\xef\ -\x16}w\xe1\xf0\xcf[&\xf7\x8e\xba\x97\xc9\x08_9\ -\xb3\xcd\xbe]\xa3\x07\x0e\x0b\xfd:\xfb\xdb\xf4\xd9\x86^\ -ji\x1b\x88avZ]w.\xe3\x8d\x1c\xd1jM\ -\x07\x93\xc0K:./V\xc1o\xb3I\xaf/\xef\x8f\ -\xe4\x18tk\xaa\xd9\xf3\xfc\x0bc\xe6\x05eS\xeb1\ -ow?\x1f}\xf1\xfa\xcf\xe8\xff\xa6\xcf\xd9\xb7\xb7\xd7\ -\x9b1'\xf7\xd7\xdc\xcb\xd6ws\x1d\xd5rWd\xc2\ -\xe9\x88\xe9\xc4X5\xe6$\xd2a\xf7s\x87\xd6n]\ -{^[AL^\xa0\xd4G\x97\x18\xba\xa5\xdf\xe6\xc3\ -:\xdc\xa9['\xb57u9\x8a\xfe\xc84\xeb\xf6\xb3\ -m{\x87]\xf2\xeb\xef\xd6\xd8\x8b\xf73\xf9\xe5\xfd\xd7\ -\x0c\xfd7u&\xae\xda6\xad\xf3\xba\xe6\x91J\xe3\xe6\ -\x1b\xeee\x98w\xadG\x5c\x1a\xbc.d\xdc\xe2S\xf5\ -\x88\xc9\xec9\xad\x1e\xb1<\xbb\xf4\xd5%\xea\x1b+\x9b\ -\x12FV\x9b\xcc\x88\x16\xadm\xfdf\x84\x12\xfa\x19F\ -\xaa\xcc\xe7_l7\x84o\x8f\xbcOx\x1f\x8dR;\ -9\xacc\x1d\xa2\x85\xc6<\xe2\xdd(\x97n1\x83\x08\ -\xe5\xe0\xd5}g\xae7\xad=\x87\xd0\x5c\xab\xa5\xcc\xec\ -3\xf6fH\xaf\xa4\x07\xe8OG|\xec\xbfo\xc8\xdc\ -yZ\x17\xedj\xeeX\xdb\x8bh\xd5\xac\xc6\xf8\xc5\xbd\ -\xdb\xd6\xdf\xd0b\xd2\xbeG{\xfbr-\x0e\x1e9\x90\ -k\xbdr\xe2\xe0Y\x0e\xfa\xcf\xd0\x147v$n\x0e\ -S\xc9\xd0KRz|`\xba\xcb\x85\x88\xf3{g\xe5\ -\xee\x1b\xa7\xefy\xbd\x9d\xf3\x05e\xfd\xc0v7:E\ -\xb3\x9e\x8fq\x19\xd6\xf7\x90\xe7\x93!\xad\xd0\xb4/>\ -\xef\xb9~sN\x0b7\x8d\xe17C'\xadm\xf3\x00\ -=\xc3\xe5~\x92\x92G\xffK\xad\xcf?i\xa8\x1f\x93\ -Nh\xf6\xd66\xb4a\xde`\xd4\xde[{\xeed6\ -\xc9|\xa4L\xec\x1d\xf9\x15\xe9\x19?}S\xd6\x0e\xd4\ -{\xbaA\xd5\xd0B=!\x9f\xd8\x9b\xb8\xf3\xe4\xa4\xff\ -\xc6\x1a_\xad\xad\xbaanGb\xf2y\x82\xa1J\xd4\ -\xbf:_\xc9\xdc\xdbw\xcb\x1eUu\xed$\x8b\xbf\xd7\ -[LVE\xbff\xbe\xbb\xa7\xc9L:\x1c\xceza\ -g\xb82\xf9\xf5Q\x1de\xd3\xd6\xfb\xf5B\xe3'\xaa\ -\xb9G\xdf5@\x8a\xe1)W^W\xdb~D\xab\x06\ -=\xb5-\xbf\x9f\xd5g\xec\xbf\xe7\x19A\xe8\x07\x13\x84\ -~@g\x0e:&?}S\xdb!-\xb0%\xd7\x9a\ -\xa1\xff>\xbe\xc3\x16\x06\x11\xb3\xc5\xdcpO\x96\xaf\xf5\ -h\xe6.\xd5\xf53\x1e\xaa\xce~}\xf4\x84\xf5\xb6\xbd\ -\xc8\xea\x7f\xd6\xc1r\xe7]\xde\xbbq\xc7\xb3Z\xa7\xd5\ -\x09[\xea5=^M\x8bX\xbb\xbfy\xf0\x14f_\ -\xa4M\xec\xe8\xb7\xbb/\xf7x\xd2\xae\xf3\x0dU\x99c\ -\xd8!s\xda\x07O\xbf\xc7\x1c\xcb\xd1~\xd9\xc1r\xf8\ -\xec\xad\x1aF\x84M\x84\xde\x8ba\x0e\xed\x17\xd6\xe8`\ -\x93oc\x9a\x95br\xe3\xb6\xd7\xb3\x96\xc1[\xb4\x08\ -\x7f\x9b6\x06\xfd\x1a!]jo\xd6|+\xf7a\x1e\ -\xb5\xba\xc4\x06\x04\xd9\xa8\xdf\xd0Q5e\xfc\xd4X\x8c\ -\x14\xef\x91\x17zv\x5ct\xab\xf7\xb9m\xee;\xf5\xbf\ -\xdc\xef\xb0\x8d1\xcet\x8b\xc6\xe2e\x1e\xbb\x947\xb5\ -\xf1\xb7\xe9\xa5\x7f\x97\xdct\xe9\xb9\x03\x93\x91v\x0a1\ -\xc0\xb0\xb5\xef5k\xaan\x18\xf1\xe9\xda'\xfd\xfaK\ -\xea\xeb\xe5)3\x1f\x05-\x1b\xd1\xf8L\x07U\xd3\xbf\ -\xfe\xeewy\xa3\xa5I\xe8\xdd\xbdd\x5c\xaf\xcf\xb9\x87\ -w;\x99\xac\xf0\xf3\xbfk\xd0\xef\xd6\xa4Z\xca\xa7\x1f\ -\x7f\x9a0e\xbbZ\xf7\xb9\x03-\xe2FO5\x08\xe8\ -\xban\xd0\xf6\x7f]\x86\xabX\xb6u1\x22F\xdc\xce\ -\x1d\xb5K#\xb9`d\xff\xd6w\x1f\x8c\xe9\x1a\xe1\xa0\ -\xd9\x92\xbb\xa4\xcf\x12\xbb\xe5HC\xdc\xbcC\x8bh=\ -\xea\xc5r\xc3.\x8b\xe69\xab\x0d\xeb1\xef\xe4\x7f\xde\ -\xbe\x83\x8fv9\x18\x96\xdf\xb1\xf5\xdd\xa1\xe8\xdbO\x8e\ -\xd8\x9e\x1fb=4\xe4\xb9\xadMv\xdb\x81\xa7k#\ -\xbd;\xc5\xb9\xd9\xbeNC\xbe\xe4em\xb5\xf9+\xe7\ -!\xd1\xf6\xeb\x97eC\x8ef-\xa8\x994\xf6\xe6\xd2\ -\x7fz\x06\xb9G\xa6\x04\xc5\xa3/\x0e[h\xfd\xc4G\ -\x89\xc8\xbe\x1bc8>\xfd\x83ql\x0a\xdaJ\xc3\x09\ -\x17\xff&<\xf2\x07\x1f>\x1f\xd7m\xc5\x93\xcfz\xe6\ -\xc4\xa4\x83/\xbe\x1d\x1ci\xfdU\xfd\xe5{\x86\x85\x0f\ -\x19\x96\xbd\xda\xdd\xd0$\xe6D\x80I0\xf1.\xea\xc1\ -\xb2!\x17\xcf\x9d`\xaei\x1e\x13\xbfJi\xdel\x9f\ -v]?\xccn\xdb/0\xf6\x08\xfc\xb3\xc7\x13\xaf\x8b\ -\xbe\x11\x83\xf3L\x8dbB\xcey\x0e\xed\xeb;7\xdc\ -6:bl\xae\xcb~\xf4D\xd7\xdc\xce\xa1\x84\x07R\ -\xecn\xed\xff\xd8\x93\xf1a\xc7\xbd\xa1S\xf7\xac\x8bc\ -\x9cE[x*\xbaf\xbb\x8f\x19~\xdd\xb2}'\xcc\ -\x1b\xf2\x06\xcd\xe0\xe7\x87\x10\xdf'\xf6\xb7\x91\x98\xe9\xe3\ -\xf7%\xe5\xc3\xd0\xed\x8e\x0c=dCL\xb0\xf4\xbe\x1a\ -\xfeiB\xa3\x03\x99K.\xeb{\xa9(\x9f\x1e\x81\x98\ -\xdd\x88\xd1\xea\x8d\xda_ne\xb9\xa4\xaes\x96\xde\x83\ -\xcc\xa6\xcd\xe3C\x92?\x0c\xcc\xf6\xdf\x8e\x1e\x14i\xce\ -\xb9P\xb7u\xb3\x86\x97\x06-m\xa3\x17rr|\xbe\ -A\xac\xb6\x9d\xde\x9e+\xcdV=\x98\xb0\xe8B]\xce\ -\xdfs\x89\xc8\xc7\xed\x86\x9b %\x1d\xc9\x01\xad\x82\xb3\ -\xa3\xf3kOz\xec\x917\xe6h<\xd2W\x8cx\x07\ -V\x9e\xe7\xee\xe8B,98,%\x06\x09\xfb\x88\x87\ -\x1e#\x8cb\x06.\xf3\xa8\xbb\x93\xccWC\x9b>\xde\ -\x7f)\xd2\x9f\xe3\xaa*\xf7\xcb\xfa\xe1\xd0\xc3\xfar-\xa4T\x0f\ -\x1a0z\xf7\xb2\xb7\xa9\x8f~\xe4\x8e\x5c\xe3\xfa\xec>\ -\xb1(\x1c)acN\xa5\xb5\xbf\xa1\xe2r\xd4\xd9\xb4\ -\xad\x0e\xcb\xa9\xee\xf0\xc3#\xde\xbal\xf7\xf9Z\xc0\xdd\ -\xf2\xa9\xf1+\xa5+}9#\xdf\xbb\xdf\xff\xef\xd4R\ -\x8dh\xff\x94\x95\x0b\x88#\xdf\x9e\x0c\x9a\x9e?x\xc0\ -\xa4 D\xa8\xedUagG\xcd\xadS\xfb\x7f5>\ --\xb4\xb6\x7f\xfaj\xa7\x9d\xe1\x1c\xe2\xc8c\x0b\xe5A\ -n\x93yK5N\x06\xbe\xbbP_\x95\x196%j\ -\xcd\x0a\xa4\xf7oe\xaa\xdf\x0e\xccP\xaeC\x8cDS\ -\xae\xc3\xd8\x969 ^\x0d\xd91#\xfc\xf5-\x0f \ -\xec$%7|TC\xe7qK\x17\x13\x95;\xeaL\ -r\xc4\xe1\xd0]\xce)\xc4\xc0\xe0\x9e}&\xe43\x02\ -_\xdcP7\xef2ou\xb0E\xe6#K\x9b\xe4\xd8\ -\x19W'\xf1\xfa\xb4$\x1a\xb9\xa9\xc7-\x18R\x13\x1d\ -\xb6\xe1\x8d\xb7\x8c\x08_\xb0<\xe2\xca\x89\x84\xab\xe6\x8c\ -\x18-\xa6\x17\x9a\xfc\xd3.Mw\xd8>D\xa6'R\ -\x05\x1d\x8f>\xb4\xf8y\xf6]G\x15o\x15\xf3\x80\xb0\ -\xfc\xd1H\xa1\x8b\xab\xb3Q\x09\x99M+rr\x5cg\ -\xe9\x9e\xfb\x97 fw:\xec\xf82a\xe0\xc2e\xc9\ -c\x89\xe4\x08\xf7\x8c\x1d\xe6\xc1\xdbR;\xab\xe8\xde\xbc\ -\xe8t\xfc\xc1\x85\x1e3\x03\xfc\xaf\xd6\xbe\xe8b\xfb\xe8\ -\xda\xccN\xb9_\xf4c6\xd9\x5c\xbc\xf3@\xab\xb1\xd5\ -\x93\x9c\xb9\x96\xd7\xfc\xefn\xbb\xe1;q\xd6\x15\x8ei\ -\x7f\xb3\x85D\xcd\xe3G\x9e[\x052G\xfb,M~\ -\xdf\xc6\xe1\x8c\xca\xd7\x1e[\x18\xc17\x89\x01\xce\x83\x07\ -\xaeP\xd35\xfc\xd9*\xd4\xd4\xb5\xc1\xd8\x94k\xc3\xee\ -^\xb9\xa1rzo\xbakw\xa4\xe09X?gn\ -GV\xb2\xf1\xfa\xe3Q>\x8f7\xa5\x1f\xe7\xe8\xeb\x13\ -\xf5j\x18\x22\xf6\xa1\xd2c\x9bF\x80\xf5\x8c\x8e\xbd\x9f\ -u\x9c\xbf\x02-\x7fj\xf2\x97y\xfb#G\xdc\xf9\xaa\ -E4\xd4PR\x0a\x9e\xf83b\xdf\x82\x05+\x9a\xba\ -\xda\x05\xecF6\xf4q\xafnGf<\x89\xe3|\xee\ -\x01\x8ap{\x87\xc5c\xd5\xc9q:\xc4\x8d\x08\xf7s\ -\xb9\x8b?+\xa9\xde\xb3\x9f\x12\x95k\x85\x9e\xd3)\xe0\ -K\xf4\xfaUwn\xab\x87\xab\xc4\xac\xf9Y\x7f\xc2b\ -\xc4\xff\x0f\x8fU\x03=\xf7\xef\x8fK\x8f7\xdf\xf7\xe9\ -^\xe0\xc2\xe3\xb3f\x84~tr\xb8\xf2\xa0\xf7!\x86\ -\x97z\xda,\x820E[\xb4\x860\x8bpw\xcb\xd8\ -\xc4\xd0C\xa2\xa1K\xf7\xc8\xef\xef\xbblB{\xfci\ -\xfd\xa1\xd8\xcfw\xbb?m\x9f\xbe\xdbA\xdb\xe1q\xbc\ -uk_\x15W%\xcd\x03\x9d\xda\xb9\x1c~\xf1\xcd\xa8\ -\xe7\xd5\xcf\xd9>\x13W\xd7\xf3\xb7\x9e\x911\x17)\xd9\ -G\xfe\xfdt\x1f\xbd!):j\xe1\xa5<5\xf7\xe9\ -\x84\x1da\xef\xd2\xa9\xdd\x9b6Zis\xdc\xc8\xd3_\ -\xf7|2<\xf4\xe2[V\xcbg\xb7\xee\xe4\x05\xef~\ -\xcf\xbbY?u\x9a\x11o\xdcuu\xc2\xbbi\x8c\xcd\ -\xbeq\x0d\xd0\xcbu\xd60/\x9e\xf1\x8ex\xd9q~\ -\xcf\xbc\xc5\xbbs\x8f\x91\xa6\xf9\x9d\x08\x82C\xc4\x9c\xb7\ -\xd9~\xb1\x1fb0G\x8e4\xf5\x9d\xfd\xbe\x8b#\xb2\x01\xbe\xcf\ -\x9a\x9f>\xb7\xddS\xfb\xc0n\xf6m\xb3C\xac;2\ -;Yu\x0fvq6\xfdQ\xab\x07\xd2\x8dW[]\ -\xf8\xdc\xb56\x9a\xe5\x07\x86\xdb\xd55\xd3b\x93\x0f\xe8\ -q{\x1cLV\xc2\xeb_H,t\x1b9\xfa\xad\xba\ -\xea\x86\xfc\x90\xfe{T785\x8b\x1ap/om\ -_\xe7\x11\x81\x88\x16\xde\x98\xacI\x8f0^t\xd0\xc5\ -\xec\xfekD1\x09\x0fM.G\xaa\x10>mB\x9a\ -\xfc\xdc\x7f \xdby\x87\xdf\xec\xf8\xcb\x0dk^~7\ -\xa2\xe0\xca'\x87\xb6\x1f\x95\x08c\xada\xdf\x94\xf4\xea\ -\xf0\x9a\x8c\xe8\xab>.\xa9\xb7\xe6\xbe\x03\x93/\x87\x14\ -\xa8\x04+[\x85\x8ckqaD\x7f\xcf\x90\xf9\x93\xeb\ -0]l\x87\xd6^\xa6\xa2\xd9\xf3\xcd\x9au\xba\x9d<\ -\x8f\x0d\x8f5~W[\xdf\xfaXC\x1f\xff\x19\xaf\xee\ -2\x82\xa7\x10\xfbZ&\xaf\xcfU\xcb9\xaa\xd2\xf6A\ -\x13F\x8bGm{g\xcc\xf68\xf6/s\xc0<\xec\ -\x0c\x9c\xb0\xca\xcc\xcb_\x85\xb0Z\xa5\xbfO\xf9\xe0\xcc\ -\xec\xa9#\xbc:\x12\xc4\xed\xb6\xdc\x14'\x8f\xb3\xc7\x12\ -\x17\x8df\x9c6\x19e5\x92\xad[\x7f\xfcp\xdf\x1d\ -zy\xef\xc7\x8e6#\xe08L%\xec\x22R\x0f9\ -e4\x9a\x12\xa7K^\x8a\xef\x1c\xf9Z\xc5hf\x8d\ -(U\xcd\x8b-\xb6\xf4\x0aHX\xa5\xc2\xbc\xeb\xa5\x19\ -\xa04h\xc9\xed\xc9\xb7\xdfL\xed\x98\x98\xa8\xa4\xd5k\ -\xdeR\x13%\xadC\xf6\xb9\x83\x9auGH\xcb\xbb~\ -*\xe8\xdd\xb0\xc6\xc1V\x7f\xf5\x99\xb8w\xd8\x13%\xed\ -\x13G\x97\xb6%\xb2\xdc\xb7\xeah\xe8_\x9f];\xf8\ -\xe1\x92C\x05S\x22\xd2\xea\xed[\x17\xed\xc8RvJ\ -Zu\xed\x8b\xbdC\xf3\x89\xb7\x9c\xcc\xb6\xaf\x19\xb5\xb1\ -\xb9\xe9\x7f\x87w\xae;\xb9\xf4\xc8\xe2\xf5\x83\xae>\xe8\ -\xdd\xcc\xdc\xf5\xb9\x9a\x93\xc7\x1c\x8d,\xff\x05\xb5'\xf6\ -\xd8>{\xfb\x9a\x995\x062\x1f\x1bjd\xf5Z\xa0\ -\xfdz\xecv\xf3\x9a\x9a\xff\xde\xcfz\xa21M\x93 \ -\xd0\xef\xff;4\xc9>\xf8,Ah)\x0djs\xed\ -r\x86r#U\x22XS\x7f\xc9^w\x17=oc\ -\x82\xb9\xa1\xa6\xd5\x8e\xbd\x1e\xdd\x1b{]\xe10\xeb2\ -\x88o\x17j\x06\xd5\x98Z\xa7~\xb2\x81J\xcc\xc8\xae\ -\x17\xd8\x86\xd7\x92//\xb2\x8b\xbd\x9f\x10sCyP\ -|\x07\x22\xef\xd3\xe5\xc1\xfd\xdexg{\xdb\xda\xfd\x8c\ -K \x96\xadw\x1cT\xaf\x8b\x8aWF\xe7w\xf9g\ -\xeb\xf6\xad\xf7\xc9\x09{\xbcG\x13\xc9\xb7\x82\x8c\xf7\xf5\ -\x9a\x10~*a\xcfG\xee}\xbf\x99c\x10Q\x9e\xee\ -z\xeb\xadZL\xbf\xdb\x81Zk_+\x8dZ\xe7q\ -\xa1Y\x1c\xc3\xfc\x87\xb3\x97\x9d\xb2W7\xd3o\x7f\xfb\ -\xa2\xfd\x8d\x1e\xd6\xc8\xf4(A\x80\xdf\xbc\xb1\xcf\xdb\xe0\ -&?\xafk\xfe\xfb\xa3\x9dO\x00\xef\xbaM\xff\x83\xb5\ -\x01\x1d\x16Z\xc1\xc6\xb6u\x9a\xf8=\xfd\x1f\xb3K\xef\ -\xa1y\xb9\xe7\xfe#\xb4\xb2,\xefE\xc5\xe87\xef9\ -\xa3\xf6\x87\xfe'\xa3\x875v;\x12\xc1 \x08\x1c\xc3\ -\xe8bT\xf3\xf1\xda\x09\xe1c\xde\xec\xee\xe1oqx\ -\xf2A\x0d\xc2\xb1Y\x8d\xc6\xa7U\xfa\x1f\xb6Y\xebd\ -8m\xeb\x94t=\x8f\xe9\xe9uw\xd7b\x0e`k\ -\xa1\xa7\x987\xbf\x18\xdf\xce\xe7<\xef\xa0M\xffK\xf1\ -\x8f\x09\xa3\x1f7T\x1b\x13\x1bTn\xd5\x1e\x16\xfa?\ -\xa6\xde\xe9\xcf\xc9\x87\xdd\xd5'\xb6\x1f\xaaf\xda\xdc\xae\ -\xff\xab\xa9\xe1\xf5\xda\xfd\xa4\xc2\x16>\xf3\x03L\x86u\ -\x8c\xe9\xb2s\xa9\xd2\xe9\xbd_\xfe\xa7\xa5j\xa5=\xbd\ -\xc7\x193\xffQ\xdf\x16\xb5[\xf4\xbc\xe0\xdfE\x17\xd2\ -:\x8cl\xfc\xb8\xc3\x95:\xcc\xb9\xebX\xa75\x82\x0d\ -\xd8W\xed\xcc\xdb\x8e[\xdcn\xd1\xd3\x95\x8d\x09N\xe3\ -\x0f\xdb\x03\xd4#\xb6\x5c\xdfa\xa0t\xba\xa1\xdd\x943\ -\x1a\xd35\xb3~\x9a\xf0j\xd4Q\xbd:\xac\xbfg\x0c\ -s\xca\xfb\x89\xe1\x86\xebG\xf8\x9b\xaf~\xa2F\xfc\xb5\ -\xf65\xa9\xdc\xc0\xa2\x87\x91\x96\xb6\xdfr\x08[\x0d\x1f\ -\x08\x1c\x11\ -\xe8\x15\xd5\xf2\xbe\ -\xeaA:\x8d\xbbr\xdb\x05\x02\xf8\x07\xbb\xa2Z\xcf\xaf\ -\xba\x10K\xe3Pb\xfc\x0b\xe0^\x8fUm\xdf\xff\x0e\ -\x10\xc2\x12\xf0\x11I\x88{\xf0+\xeeV\x80\xb9W\x83\ -|`7K\xc0W,\x01\xfe\xc1\xb7\x5c\xed\xd3\xfd}\ - \x85\xc6\xa9X\xfc\x0b\xe0\x1ebK~\x0a0\xe7j\ -\x90/\xf8\xb1\x04\xe2\x86\xa5\xe0\x1f\xe2\x8b\xd5\xb6\xde\xef\ -\x07\xf94nK\xe0_\x00\xf7\x90_\x10\xaa\x00s\xad\ -\x86\x8a\x81P\x96@\x0e\x89\x08\xfc\xcfb\xfdI\xb9\x1b\ -\xcbu\x11\xe8\x90,\xcb\xa64h\x93,\x0bm\xea\xff\ -\xad\xf5\x114'Y+\xf4\x05~O\xff\x9b\xa5\x0e\xf5\ -=\xf8~e\xaf\xa1|\x00\xb85\x13\x83\x7f\xc81\xbb\ -\xa5\x00s\xfc\x05\xf8Fx\x5c\xa1G&\xad\xed@&\ -o\xecI\xa6\xed\x9fHf\x9cYJf^\xb6#\xb3\ -o\xed\x22\xb3\xfd\x0f\x90\xb9\x0f\xce\x91\xb9\xa1\xee\xe8\xe7\ -Y2\xdbo\x1f\xfa\xbd3\x99yi\x1d\x99\xe1\xba\x88\ -L\xdd3\x86Lfv'\x93l\xdbS\xcf\x85\xe7\xc1\ -s\xad\xaa\x04=\xf8\xd0\xb8\x16>\xfb\x90g\xf8\x1b\xe6\ -\xeb\xe9\xd2\xe7U\x17\xe3+u\xe702\xf3\xe2\x1a2\ -\xe7\xbe+\xc9\xfe\x18JrS\xbe\x91\xbc\x9c4\x92\xc7\ -\xce#I\x1e\x8f,up\xb9\xe8\xefrI^v*\ -\xc9I\x8a!\xd9\xefC\xc8\x9c\xa0cd\xc69K2\ -e\xdb\x002i\xb5\x01\xcd\x17\x14\x9a\x16\x92i\x5c\x0b\ -\xe7\xf28*\xc0\xdc\xe4\x07p\xd6\x11\xafNZ\xd5\x86\ -L\xdd=\x86\xcc\xbe\xb9\x13\xe3\x8b\x9b\xc1Bx\xe4\x94\ -\x8e\xe7r\x0e^A>\xc9M\xfdN\xe6G\xdc&\xb3\ -\xbc\xec\xc9\x14\xa7Ad\xd2\xca\x96\x94\xacPL\x19\xe1\ -(\x84{\xb0\x0b\x1e*\xc0\xbc\xe4\x83wt\xfe\x92\xed\ -\xfe\x87\xce\xa5\x05\x99\xff\xea\x16\xc9\xcdL\x92+\xbeK\ -\x1d\x88G\x00O\xc9{r\x99L?f\x8ee\x0c\x9f\ -\xffT\xfa\xde\x14\xc1CV\xf1\x1cR\xb8o\x90\xa4\x00\ -\xf3\x92\x03\xde\xbb\x229\xbd\x96,\x88~\x86\xcee\xde\ -\xaf\xc3\xbb\x88\xc1\xcb\xcb$\xd9\xef\xee\x91\x19g-(\ -]\x01\xf8\x81b\xc8\x85$\x1a\xe7|\xfc\xc3\x9d\x93\xaa\ -{7\x03\x9d\xaf\xa45m\xd1>/#\xd9_\x9e\x91\ -$\x87]\xa9x\x17\x1e\xc3m9\xf6\xb3\xfc\x8e\x83\xf3\xfd\x1d\xf6C\ -\xffB\x1a\xc8c\x15\xd5\xdd`W>\x8eK\x07\xc0=\ -/+\xb9\xb2\xd1T\xa1\xe3\x17\xd3\x00\x9bUT\x8bD\ -q\xf1\x8f\xe4=\xf0\xfc\xdf\xf5\xdc\x0b\x8f\x82\xf8(2\ -u\xd7\xa8_A\x03\x8a\x8f\x7f\xb4\x07\xa0\xeb\xfdJy\ -\x0f\xf6\x04//\x8b\xe4e\xa7\x90\xdc\xac\x14\x1c\xeb\xe1\ -\xe5e\xffR\x9f\x12\xfbs\x18\x99\xb2\xb9_E\xd3\x80\ -b\xe3\x9f\xb6\xf1*T\xcf\xe7\xf1Hnf2\xf6\x19\ -\xe6>\xba@f\xdd\xd8\x86cy\xe0\xb7O\xdd3\x16\ -\x9f\xc3\xd4}\xe31\xff\xc9<\xbf\x92\xcc\xbe\xb9\x83\xcc\ -{z\x19\xd9\xefo\x10]\xa4U\xdc\xbc\xd0\xc8{q\ -\x9dLZ\xd7\xa9\x22\xe3\x06\x8a\x8b\x7f\x88\xd5\xaei\x87\ -\xed\xfb\x8a\x18\xbc\x9ct2?*\x98\xcc\xf2v\xc4\xbe\ -C\xbc\xcf\xd6-\x04\xf2;\x04r<,u\x8arC\ -\xe0\xe7\xca\x968\xb6\x04r\x1ar\x02\x80>y\xf9\xd9\ -\xf2\x9f$\x97Cf\xfb\xee\xa6rP*\xc6O\xa8\xb8\ -\xf8G\x00~=y\xfbv \x0e\x98\xfb\xd8\x83Ls\ -\xf9\x97L\xb25,\xc2o\xb9\xce\x98nal\x19~\ -&\xaf\xefL\xa6\x9fZ\x80\xfd\xfb 7\xe49xH\ -\xfe\x00\xef\xa9 9\xa0\x98\xf8G\xf8\x00\xbe\xcbI\x8e\ -\x93\xdf>\xb2\xf3\xc8\xfc\xf0\x9bd\xda\x81)\xe8\xfc\xb6\ -\x90o\x5c\x9e\x9fg\x80\xf8U\xfa\xc9\xffpN\x89<\ -\xf3\x0b\x0ab_\x92\xc9L\xe3\x8a\xa0\x01\xc5\xc3?\x9f\ -\xef?\xbf&\xb7\xfd\x03\xdd\x11\xf2\xb6\xe0\xb9\x15\x1a\x7f\ -\xa5\xe9 y\xc3\xff\x90\x1e\xe1D\xe5\x99\xc8e\xf0\xc8\ -\x9c\x80\x83\xb4\x1c\xf8\xcd\xf1\x8f\xce~\xc6\x99er\x8a\ -\xe3\xf1H\xf6\xbb\xfbX\xbeS\xb9\x01\xbf(\xd6\x06\xe7\ -t\x85\x1e\x99~\xc4\x8c,\xf8\x1a!\x87u v\x92\ -\xfe\x13\xd9A\xe3\xe5\xed#V,\xfc\x83,Ez\x15\ -\xd8>2\x0f\x1e\x97\xccE\xbac2\xb3\x07}\xe6+\ -\x87\x96S\xb7\x0f\x22\xf3\xdf\x06\xc9\xbe\x1e4\xf2\x9e]\ -!\x93V\xb5&\xe5\xc8\xbf\x14\x0c\xff:8o\x87\xe4\ -\x14\xc8\x8e\xfb\xb0KdR\xe5\xc5\xd5\x04h\xa0)\x99\ -\xb2\xb1'\xd6\x0de\x1d`o\xa6\x1d\xfaW\x9e\xf4\xac\ -8\xf8\xc7z\xb4\x11\x95\xbb#\xdb.\xe1s\xaf\x10\xb8\ -\x17\xa0k\xec\xc7x\x1f\x223\x0d\xe4=\xbbJ&\xd9\ -\xc8\x8d\x07(\x0e\xfe\x11MC\xfe=\xe4V\xcb2@\ -\xdec\x9e\xaf(\xb8\x17\xa0\x81\xd4\x1dCIN|\x94\ -L\xeb\xe3f%\x93\xa9{\xc7\xc9\x8b\x07(\x08\xfe\x91\ -\xce\xbf\xca\x00\xdbg\xb2\x0c\xd0\xf3\xb1\xaeWY\xf2^\ -\x02\x1aH?1\x0f\xdb\xf4\xb2\x8c\x9c\xc0\xc3X\xbf\xfc\ -m\xf0\x0fg\xc3y\x84L\xf6\x12\xd8\xf7`\xe3)X\ -\x8eu\x09:\x07\x1f#\xe4\xfc\x80\x9c\x92v@\x8c0\ -\xd9\xa1\xbb\xfeA\xef?\xbfR\xea\xd8:\xe4\ -\xd0\xa6\x1f\x9eYu\xce\xbe\x00\xdd\x83\xbe\x22m\x9c\x00\ -\xe2\x97i\x07\xa7\xca\xba\xee\xca\xc7\xbf\x95\x1e\x99\x13|\ -B\xaa=\x80\x0165\xbeW\xa5\xe8r_\x04\xfe\xc1\ -'\xc0\xf9\xf1I\xca\x95\xf3\xc8\xac\xab\x1b\xab6\xfe\xe9\ -\xfb\xd8`\xb3K\xb7\x05h\x0f\xaemV<[_R\ -\xb0\xd6\xc7\xb5\x05\xa4\x1d\xb9\x8f\xce\xcb\xaa\x03T2\xfe\ -up\x0d\x05\xb8G/\x15\xfa\x91\x1d\x9d\xb6gl\xd5\ -\xe3\xfd|(\xf4yIwG\x15\xe2\xcc\xf8n\xb1\xf4\ -\xbc\xafr\xf1\x0f\xf1\x91=cp~\x9d4\xa3 \xf6\ -\x15}w\xa6\x8a\xf1~>\x80\x0c\xd8jJr\xd3~\ -H\xb5~NR\xac\xac~\x80J\xc6\x7fSd\xc7.\ -\x90:\xd6\x0b\xb9a\xf8\xfe\x5cU\xd1\xfbK\xe0_\x17\ -\x9f_\xf6\xc7GR\xad\x1f\xf2\x16Sw\x0e\xaf\xc2\xf8\ -\xd7&3/\xae\x95Z\x07\x86\x5c\xcc*\xcb\xfb\xf9\xb0\ -\xb2\x05\x99\xfb\xf8\xa2T\xeb\xe7\xe5f\xcaj\xfbT.\ -\xfe-\xb41\x0e\xa5\x1a\xc8^\x84|\x5c\x9c\x93Y\xd9\ -8\x94\x05\x10\xee\xb2\xfd\xf7K\x87\x7fv.u\x87\xb8\ -*\xe3\xff\xf6\x1e\xe9\xd6\x9e\x9f\x8ds\xed\xaa\xfc\xf9G\ -\xf4\x0by\xaeR\xc5\x03\x10\xdf\xcc\xbch+\xcb\x19\xa8\ -\xba\xf8\xcf\xcd\x90w.D\xa5\xe1\x1fp(\x95\x0c\xc4\ -\xf8_\xfbg\xe2\x1f\xd9~`;T\xc2\x9d\xe9\x0a\xc0\ -\xbf\x94:\xd0\x9f\x8c\xff\xbcL\xaa\x96\xce\x9f~\xfe/\ -\xfd\xa1\xf8G6\xa3\x9cb\xa0\x95\x0bh\x0fp\xec[\ -\x9a\xc1- 3=VWi\xfcg]\xdf*\xe5\xda\ -e\xd6}\x14\x03\x90\xed\x0e\xf9<\xd2\x0c\xea\x0c,\xa8\ -\xba\xfa?\xf0\xbe\x0b\xab\xa4\xce\xf7\x85\x1a\xbdU\xd6\xf7\ -\x8fA\x17\xe7r\xe6=\xf7\x96\x0e\xff\x10\x03t\x99V\ -\x85\xf1\xdf\x14\xdf\xb3\x95\xf6\xce\x1c\xd4{\xabRq\x7f\ -a\xa0\xef\x0e\x16\xc4\xbd\x92j\xfd\x90/\x97\xe24\xb0\ -\xea\xfa\xff\xe8\x9cX\xf0cJ38?>\x90\xc9\xf6\ -\xdd\xaa\xb4\xff\x1f\xfc\xb7\xd2\xd6\xa6\xe5\xfc\xf8\x88k\x9d\ -V\xd9\xf8\x0f\xd0\xbf}W\x8cGi\x06\xf0\x8d\xb4#\ -U0\xf7\x83\x0fh\xdeR\xeb\xfeh\xc0\xbd\x22|\xa7\ -\xb1\xaa\xe2\x1f\xe4\xdfj\x032?\xc2O\xaa\xf5\xc3\xc8\ -\x09p\xa9|\x8f+5\xfes\xee\x80\xde#\ -3\xed+ \xfe\xab\xe8\x99\x96\x14 \xe7\xcdy8\xc9\ -aI\x97\xf3\x08\x03\xe7}\x1c1\xfb=\xee\xff\x08A\ -\xd2\xea\xb6\x94M\x83\xf7J[\xa06\xd3o@\x13r\ -\xaam#'\xde\xafx\xf8\xb7nN\xd5S\x8b\xbaG\ -\xe6\xdc=\x8a\xefHA\x0d>\xf0q`?\x1f\xbfO\ -\xdf\xf2\xaaK\x13YW\x99\xb2\xd54\x83\x9c\xf7\xeb[\ -\xe5\xc5#+\x06\xff\xfc\x1e{\xe5\xd1M\xf9w\x01\x04\ -s!9l\x1c\xe7\x87\xfb\xae\xe0\xeb\x85Zx\x90\xef\ -\x04\xf7\xc5\x92\x90\xee\xcf\xe2\xf7\xd7*F\x13\x95\x8fc\ -\xd1\xeb\xd3\xa1j\xd8\xcaX\x13\x8a\x9b\x1c\x87\xfb\xcc\xc9\ -)\xee!\x1f\xfc\x0b\xf6TD\x9f!\xa7\x15d\x1c\xf4\ -\xd9\x93\xf8\x9e:\xd8\xc3[L\xca\xac\xf1\x0b\xb9\xf2\xdc\ -\x8cD\xb2 \xe6\x05\xce\xff\x85\xfb\x1f\x10C\x80\xef&\ -\xadmO\xf7\xea\xe4\xd3\x84\x82\xd0\x03\xd4\xb0\xdd?\x09\ -\xfbke\x1d\xd0kP\x8e\xf6\xaet\xf8\x17\xec\x99\x8a\ -e\x9a!\xa2\xc9\x81\xb8njN\xd0Q\xaa\xa7bV\ -2\x99\x1f~\x0b\xcbs\x89\xf0 C,\x08\xbe\x03t\ -\x03\xef\x85\xde:\x99\x977\x90i.S\xc9d\xfb\x7f\ -\xe4U'Av\xdc#\x1e&\xeb\x80\x9er\x10/\x91\ -c\xceS\xf9\xf0O\xf3Y\xd0a\xe0\xbcA\x1fT\xa8\ -K\x07\xfd\xcd\xb8\xe9?J\xc85\xcc\xab\x1c{K\xc6\ -\xab\xd0\xb3\xe1,\xcbe \xbb\x0ah\x22\xf7\x89'\xd5\ -\x8f\xb32\xf4\x04\x9a\xe6\xa1\xde\x07\xe7\xe7g\xb9,+\ -\xe7\xee\x11y\xfb\xba$\xc4?\xe5\xa7\x87\xf3\x09\xf9:\ -\xf9o\xee\xa2\xf3\x16_\xe6\xfdu\x9c\xa3\x0b\xb5K\xcb\ -\xb4St\xb1,\x97w\xad\xdf\x9c{\xa7*\xe7\xfcC\ -/:[C2\xcb{\x93\xdcj@r\x12>P=\ -b\xe4\x9b\xef \x19\xfe\xe98\x1d\xf8\xdb\xcb;p\xfd\ -\xe2\xb2\xe6\x0c2\x04\xe2\xe0H\xa6\xcbm\x94\xea\x1f\xaf\ -\xa8\xfa\x9f\xd4:\xa1\x96\x0d\xd8x\xf2\xaa]\x0c\xcf\xc9\ -\xf4\xdcP\x11\xfa\x8c\xe4\xe7_\xcaX\x15\xf0\x8a2c\ -\x94\xfc\x1a\x10H\xaf\x93\xd7\xc0\xb91H\xee\x96\xe0=\ -\xd0\xf3\x9b\x9f3\x22\x97\xfe{\xba\x85\xf2\x18\xees\x03\ -\xbd\xcb\xb3n1\x0c\xe8\x0f%\xe3=O\x19\xf1\xdfL\ -j\xf9\x0cr\xa2\xa8\xd7\xa1\xf8g\x83]'\xed=X\ -Q\x03\xe7F\x80\xfeWl\xcf(9\x96\xed\xbb\x0b\xdb\ -\xd0)\xdb\xfac\xba.\x9fO\x81_\xfb\x9b\xd2\x7f\xe1\ -y\xa9\xce#q\x7fxN\xc2{\x99j\x18\x89\x5c\x07\ -\xaeiVa\xbd@\xca\x85\x7f\xa87\x01\xe7\xaa<\x03\ -\xdfQBzb\xa9:\x00Z\x1b\x9c\x1by\x0e|f\ -\x84u?~\xad\xa17\x81\xf8o\xb8\xc9_1O\x83\ -\x1c\x0c\xb0U!\x06\x09\xb1H\xfc\x1d\x0bm\xda\xffH\ -\x83\x05m\xdb\xa2gB\xdd\x15\xe8'\x0e}\xbe\xe1=\ -\xb2\xd4\xae)m\x80\x0e\x9by\xdeZ\x0e\ -;\x90\xcc]\x87i#\xd3s=\xf6K\xe6\xdc;\x89\ -{\x89s\xbeGQ5\xfcd\x88\xdf\x949\xd0\x9c\xa0\ -N\x1c\x0b\xf8\x93\x22\xe0\x9f\xaf\xa3\x87]*\xf7R\xd8\ -Q\xc1\xe2u\x00\x9a\xae\xe4a\x1f\xf3\x07\xe8K\xd0\xf7\ -\xbd\x04\xcf\x11\x87\x7fq\x83\xcb\xa5r\xb3*\x12\xcfb\ -F\xde3o\xda\xc7\xaf@\xfd\x7f@\x07@<\xaf\xbc\ -2\xaeT\x1d\x00\xd7\x80\x18+sM\xccb\xefCg\ -\x19t\xf0\x12\xef+/\xfe+i@\xadh\xa8\x11\xa8\ -p\xfd\xbf@\x07\xd87\xa1\xdc}\x8f(\x1d`\xb1h\ -\x1d\x00\xc9V\x88\xf3\xc8\xb3\xb7\x16\xe4\x92%o\xe8\x22\ -9\xffW\xa0\x01\xb8\x87z\xe1\x0a\xd9\xff\x0fx5\xda\ -Wiz\x1a`\xdf\x95\x98gJ{\xffE\xdc\x00\x9d\ -.I\x94\xdcTp\xfc\xffb\xdc\x97\x1f\xff\x00\xd6\xcd\ -\xc9\xdcP\xb7\xb2\x17\x83\xe4&\xf4\xea\x84:\xa7\xb9\x0f\ -\xceQ\xf9\x0a\xd6B\xbeK:\x1e\xce\xd7\xc7\xe55\xb2\ -o\xee\x14\xcdk\x14\x15\xffh\xaf\xf2\x9ezUF\xdd\ -\xf2\xf2\xe3\x1f\xe7\xac\x8b\xb8\xaf\x8ct\x02\x90\xe1\x18\xdf\ -\x88>\xe0o ?\x11\xd7g\x02\xbc\x8b\x8aY@\x1e\ -\x9cC7\x92\x93\xf8En[\x09w\xe22N\x89\xb9\ -\x13\xa7\x80\xf8\x87\x5c\x9el\xbf\xfd\xb8\x1eh%\xdce\ -\xe3\xe3_\xf2\xfe\xcf\xa0\xaf!\xbc\x82_\x1b|\x01\x90\ -\xc3\x086\x01\xe8\x85i{\xc7\xd1\xf8n.YL^\ -J\x9fBi\x03lq\xb1\xf1q\x05\xc3?\xd0}\x86\ -\x9b\x15\x95\xc7P9\xb1j~\xff\xe7r\xf4\x7f\xa7x\ -v\xc6\xd9e\xb8\xff!\xaeA[\x98\x87Q\xce\x1c\x0c\ -\xa8}\xe2e'\xd7=e\x7fyJ\x9f%\xd1\xb6\xa6\ -\x22\xe0\x1f\xfc\x9cy\xe17i\x1b\xa5R\xf3\x98\xf8\xfd\ -\xdfM\x10\xb0$\xff\x9e\xaeP\x8e\x85\xf0\xfcK\xcb\xd5\ -\x16\xf4\xc7\xe9\xe08=\xc8>\x90\x1b\x98\xa7\xc8\xe8\x03\ -\x86\xfb \xb8\x8f\xa7\xa8y+\x00\xfe\xc1w\x04>\xa5\ -\xc2\xde\x93\x95\x83w>\xb0h\xdc\xb7D\x10-\x97g\ -\xae\xd0\xc7>R\xf0\xb3\xe2\x5cNA\x80\xdfa\xff\xaa\ -@Lv9\xe5W\x82\xbb\x1c\x10\x03\x82z\x98\xe0K\ -\x07?\x1c\xc4\xb8\xf7 \x0a\xd2\x0eL\xa2{6T\ -\xfa\x1e\xfc\xa9\x90G\xe3\xb8\xf0\xec\x0b\xe1\xbf1\x82P\ -\xe9\x9f\xaf+$C\x85Aa\xed\xa1?\x05Bi\x1c\ -\x17\xc3\xbf\x10\x0d,@\x90\xaf\x00s\xad\x06\xf9B>\ -\x8d\xdb\x12\xb8\x17\xc2?\xd8\x05~\x0a0\xdfj\x90/\ -\xf8\xb1\x04l>QC\x80\x06\x86#HQ\x809W\ -\x83| \x85\xc6\xa9X\xdc\x0b\xe1\x1f\xfc\xc2\xbb\x15`\ -\xde\xd5 \x1f\xd8\xcd*\xf2\xf5\x8b\xc5\xbf\x10\x0d\xe8!\ -\x08Q\x80\xb9W\x83l\x10B\xe3\xb2L\xdc\x8b\xa0\x81\ -\x81\x08\xbe)\xc0\x1a\xaaA:\x88E0\xa0<\xb8\x17\ -\xc2?\x83E\xe9\x8c\xe9\x0a\xb0\x96j(\x1f\x00\xce\xe6\ -\xd38,\x17\xfe\x85h@\x15\x81\x03\xab\xda&\xacJ\ -\x90O\xe3LU\x1a\xdc\x8b\xa0\x81:\x08vT\xd3@\ -\x95\x80|\x1aWud\xc1}5\x0dTI\x90+\xee\ -\xc5\xd0\x80\x03\xabZ\x1fPDH\xa7q#W\xdc\x8b\ -\xa0\x01\x90)\xa0W\xc4*\xc0\x9a\xab\x81\x82X\x1a'\ -2\xc9\xfbr\xd0\x00\xe8\x94`WT\xfb\x07*\x1fB\ -h\x5cH\xa5\xe7\xcb@\x03|\x1f\x11\xf8\x96\xaa}\xc5\ -\xbf\x1eR\xe8\xbd\xd7\x13\xc4\xc9\xaf\x18B4\x00~E\ -\xf0-C|\xa1Z7\xacx\xc8\xa7\xf7z8K\xc0\ -\xa7\xfb\xabp_\x0a\x1d@l\x09|E\x10c\x962\ -\x87\xa4\x1aJ\x81\x13\xd5\xa3zT\x8f\ -\xeaQ=D\x0ef\xf1\x8fe\xf2\xd3\xe0\xe2\x9fK\xf0\ -\xe7\x98\xe2\x9f\xd5\x84?\x0b\xcb\x83\xb2\xe4\x87\xb0\xbc\x11\ -\x96G\xc2\xf2\xaa\x84<+6A\xe5\x92\xf2PX^\ -\x0a\xcbSay+,\x8fK\xc8kay^\x5c\xde\ -\xb7E?L\x09j\xdf\x19\x84>\xf5{\xf4\x8b\x96\x9d\ -(\x90t\x88\xd0[\xfeB\xd0\x17\xc1r\x04G\x11\xdc\ -D\x10TIp\x93\x9e\xc3rzN\x7f\xc9K\xc7\x12\ -z\x0e\xf8\xe0\x0d\x11\xaccQ~y\xb0\xdd9\xac\xca\ -\xb7)\xf9\xc0\xa1\xe7\x14B\xcf\xd1\x90%\x107(\xef\ ->\x08\xad]\x1f\x81\x13\x828\x05X\xa7\xa4\x10G\xcf\ -Y\xbf\xbc{ \xf0\xf7J\x08& x\xa5\x00\xeb\x91\ -\x16^\xd1kP\x92d\x0f\x04\xd6^\x13\x81-\x824\ -\x05X\x83\xac\x90F\xaf\xa5fi{ \xb4\xf6-,\ -E\xe8\x9d)?`\xd3k\x12\xb9\x07\xac\xe24o\xfb\ -\x9b\xad]p\x0flY\x22\xce\x82\xc0\xfa\xe1\xac\xfc\x0e\ -4/\x0e\xd2\xe85\x16\xae\x9fU\x9c\xcfWe^'\ -)\xbcb\x09\xc9\x05\x16%+\x9d*\x7fn\xbf\xec\xfe\ -\xbc\x13\xab\xb8~\x00\xfa\xc2/\x94\xef\xbaE\xb58\xa0\ -\xee\x06\xd4\xd2Z\xd9\x92\xaa1\x08}\x9c\xa0\xd6,\xfc\ -]\xc5\xf5\xfc\x8c\xa3\xd7\xcc_\xff\xfa_\xb2n\xbav\ -\x14\xf4\xd6\x84\x9a\x0a\x19\xee\xd6dN\xe0!\x5c\xdb<\ -?*\x88d\x7fzL\xb2\xdf?\xc0\xfdgr\x1f\x9c\ -\xc5u\x0f\xd3\x0eM\xc7\xf5\x94q\xcf;\x5c\x0bIn\ -{\xb1\x8eU\xa4\xcfWl\xbe\x0f\xae\x97\xa5\x87k\xf8\ -f\xdd\xd8\x86\xd7I\xf5Z)\xbb\xe7\x04\xd4\x97\x80\xbe\ -O\xb9\x0f\xddp\x0d\x02\xa8\xf5&\xa7}\x08a\x15\xd9\ -2\x15\x14\xcf\xd4\xa5\xeb'\x9a\xe2Z\x87\xd03C\x96\ -\x01\xf56\xf2\xdf\x06\xe1\x9aET}a\x99\xee\xdd'\ -\xb3\x8a\xec8\xf9\xdb2\xb8\xdec\x1b\x5coI\x9e\xb5\ -\xc0\xf1>\xe4e\xe3\x9a\xb0P\xb3I\x86\xda\x03\x1cV\ -\x91\x0d+\xdf\xb5\xa39A\x9d\xcb\xdcG\xe7\xe5\xda\x03\ -Cx@\xbd2\x5c\x1bSz\xfe\xc8\xb7\xdf\xe5\x8aw\ -\xa8\x87\x0a\xfc\xecW\x0c\xa8\xef\x96q\xd6B\xda\xf9\xf2\ -}\x17r[{\xf2\xa6^\xb8N\xe4\xaf\x1c\xd0\x97\x19\ -j\x9bIA\x07Ar[?\xd4\xe1\x5c\xdb\x11\xf7\x87\ -\x96xp\x0aHNR,\xc9~w\x9f\xcc}|\x91\ -\xcc\x09>\x81\xe5\x1e\xd4\xe0+\xf8\x16I\xd5\x84\x95t\ -\x0f\xd2~\x90i.\xff\x96\x97\x1f\xc8o\xfdH\x87\xc9\ -\xf6\xdf\x8ff\x22\x81L\xcb\xcd\xc4\xb5\xc2q\xdf{D\ -/T\xefJ\xbd\x22\xfc!\xfd\x07\xeaiA_\x1e\xa8\ -/\x0c\xfd\x02%\x19\x05q\x11\xf8y\xe5\x90\x0b\xf2Y\ -?\xd4\xfc?4C\xa2\x1eB\xec\xcfad\xfa\xd1Y\ -t\x8fF\xedR\xeb\xba\xf2u?\xa8?\x0c\xb4\xc1\xcb\ -\xcb,\xf3\xf9\xb9\x0f\xce\x88\xaf\x15^\x11\xeb\x07\xba\xb7\ -m\x8f\xf8\xdd\xbd\xd2'\xc6\xe5\x90\xb9\xa1\xeeT\xff\xca\ -\xf2\xea/\xb0G\xd6\xfa\xb8>\x7fY:\x04\x9c\x19\xd0\ -\x19%\xac\x9b)\xfb\xfa\xa1\xcf\xe7\x99\xa5\xa5\xcb9\x1e\ -\x17\xf7m\xa6\xfa\xc6K+\xaf)]*\xfd\xc8,\x5c\ -\x1b\xb8\xb4\x01\xfc\x03j\xc2J\xb0\xc72\xae_\x17\xeb\ -8e\xf5\xba\xc9{\xe9C\xd7\x11\x95C\x9d$\xf4\x8c\ -\x0c\xb7\xe5X\x17\x14\xbb\xdd9\x19\xa2\xfb\xe4\xca{\xfd\ -\xe8\xf9\xd03\x13\xd7\xdd\x1538I1d\x8a\xd3 \ -\x89\xeb\xb8JD\x07\xe8|C\xff\xa1\xd2\x06\xeeMU\ -\xb6<\x94y\xfdY\xd7\xb7\x95:\x8fl\x9f\xed\xf2\xaf\ -\x17\x8cd\x5c\xca\xb6\x81\xb8&\x9f\xb8\x015\x19\xa9^\ -\x83\xa5\xee\x81l\xebG6\x08\xf4\xb7\x12\x8f\xfbXJ\ -G\xaf\xa0z\xc9\xb9\xf7O\x8b}7\xf0A\xa83_\ -\x06\xddI\xbf~\xdc?\xfd\x1fl\x9b\x8a\x1b\xd0C\x07\ -\xfb6*`\xed\xb0.\xb0\x87\xc1>\x16\xbd\x01<2\ -\xf3\xbc\x8d\x98^\xe9rX?\x9c\xfd\x1dC\xb1\xee)\ -nd^\xb2-\xeb\xfd\xd2\x03\xe8\xda\xcc\x1e\xa5\xda\x96\ -\xa0\x8f\x95\xa1\x0f\xca\xb4~\xa8\x09.n\xff\xa1\xb64\ -\xfc\xbb\xfc\xf8\x9e0P\xb2\xa74[\x03\xf7M\x11\xec\ -\xcb!\xd7\xf5kc=\x0etx\x91\xeb\xcfJ!S\ -\x9d\x87W\xe0\xfa\x9ba=\x19\xf4hq#\xef\xc5\xf5\ -\xb2\xce_\x85\xad\x9f\x9b\x99\x8c\xce\xc7\x90\x8a\xad\x8d\x88\ -t\xc2\xbc\x17\xe2{,C\xbf\x95B_jE\xac\xff\ -\xf0L\x5c'_$\xfe\xa1o\xc7\xde\xf1\x15\x8b\x7f\x90\ -?o\xee\x8a_\xffS/\xcaoZ!\xeboJ\xf5\ -\xb8\xcd\x11c\xa3\x22}\x1f\xec\xbb\x8a\xe3\x7f\xba\xd8F\ -\x04;Y\xdc\xc8\x09:^q\xf2\x1f\xfc<\x9bz\x97\ -j\x8fH\xa8\x83I\x07\xb0\xff\xce#K\xd5=\xb3\xae\ -0+N\xfe[Q}G\xf2\x9e_\xc32\x08\xf4\x80\ -b\x80~\x07\xf4\x87m\x9e\x8a\x88\xeb\x80\xee\xe9\xed(\ -v\xed\xd0\xeb\x00\xf7\xe7\xac\xb0\xf5S\x00>\x9fd\xfb\ -\xae\xb8\xdfw\x09\x80~\xbd\xc2\xfdA\xe5D\xfb\xa0\xdb\ -\x16D?\x13\xbb~\xd0=\x93\xcb\xf6\x85\xc8\xbc\xfeB\ -?\x85E\x13\x04\xda\xc5\xfb\x06T\x18\xed\xeb\xe0\x1e\x06\ -\xa5\xf5:\xc1\xb2\xafl?\x88\xe4\xeb\x17\xd7\x0b\x01\xf8\ -\xc0\xd6\xfe\xd8\x07\x0b1-\x0a\xe7\xcd\x8b\xc7\xf7\xe4\xb9\ -\x0fp\xee\xb7\x0fA\xe7+Z\xec\xdaa_\xa0\x7f\x87\ -L\xf6\xefr\x81\x9a\xc7\xd0\xcbl\xa31\xd5\x83P\xf8\ -,\xc39\xbc\x016 \x0f\xf3\xa2\x82\xf8\xb7\xd8\xde\xcf\ -\xbe\xe5L\xa6\x9f\xfc\x0f\xdbi\xb8o\xcc\x0a=\xd9\xf7\ -\x01\xbd\x0bb\x81\xf9Q\xc1\xe2\xd7N\x92\xb8\x973\xee\ -\xe1(\xad\xfd\x8b\xe8\x06\xde\x03\xfa+\xac\x0d\xe2\x91`\ -\xc7C?\xd0\x12{\x8a\xf4+\xe8\x0d&\xfa\x10\xb2q\ -\x0f\x9d\x82\x98\x97d.\xb2\x85Rw\x8d\x94\xde\x16D\ -\xef\x05yS\x9a\xbd\x89\x07\x8fKf]\xb6\x93T\xef\ -*\xbe\xfe\xe5T\xads\xe8A\xc5\xf9\xf9\x19\xd7\xbb/\ -~\xa6\x84\xf4)>\x1f\xfa\xfa\xba\xf49a\x9a\xe4 \ -}qv\xd1\xfeI\x14\xd7\xa6i\x10\xf1P\x88\xf3\x14\ -\xc4\xbc(\xf35\x10[\x95\xac\x17\x97(\xfc\xeb\xe2\x18\ -<\xf4\xdf\x12\x89\xce\x9f\x9f\xa8X4\xff\xd9\xd07\x16\ -l\xc0\xcc\xa4\xb2\x97\x9f\xfa\x9d\xea\x93gI\xf5\x81K\ -;0\x19=\xab;\x89\xed\x93\x12\xfd8\xb4\xa9\xbfC\ -sI\xdb7\x1e\xc7~%\xf1-\xc3\xf9\x93@\xe6\x95\ -N\xff\x88>\xb3\xfd\x0f\x88~~\xbe\x90M\x07}\xee\ -O/.\xd97Y\xc4\xc0=\x12\xd6\xb4\xa3\xe2\xa2X\ -v=\xa7\xe2\xda\xa1\xe7\xc9L\xcf\xf5d\xfa1s\xbc\ -'\xe0\xbb\x05^\x0a=\xa7\xa0\xf7\x94$\xeb\xa66\x98\ -C\xf9\x9aJ\xd7w\xcb^?\xf8\x15\x8e\xcfE\xc8\x16\ -\xad\xd7g]\xdfZ\xb4~\xd8+4OI\x06\xf8\xeb\ -\x8a\xceL\xc7\x92\xfd\xe6\x11\xaf\xa0\xfaI\xe4\x89\xec\x03\ -X\xfa\xe0\xe1\xe7S\xfe\xe5r\xf1X\x91\xf8\x87~s\ -\xdc\x94\xaf\x22\xdfD\xf1\x80\x16\xd4\xd9\x04\xfb\x03\xf1F\ -IF\xa6\xe7\xba\xc23\x8f\xf1\x1f\x17Q\xf6\x97$Z\ -:\x0f\xd3Pao\xb2\xf2\xf1U\x91\xfc\x1fb3\x90\ -g\x80\x07\xf4AK\xfe\x8a}\xdc\xd9\xb7\xf7`\x1a\xc5\ -:\x1d\xf8_\x90\x8e\x07\xfd<\xcb\x9cb^6\xf5=\ -9\xaf\x1f|/9\x81\x87e\xf1\xad\xc3\xdaK\xc6\xbf\ -\xd1\x1c3\xce-\xc7\xb178\x0b)\x8e\xbd\xe9x\x15\ -_\xa7\xd1\xa5}\xdf\xa3%\xeas\xcda\xc5\x90\xc9L\ -\xe3B]H\x1e\xeb\x87\x98`\xe6\xf9\x95\xb2\xf6\x99\xe6\ -\xe7\xcf\x8b\xf87=\x81~Zz\x98\xbe`\xde\x18`\ -\xbf\xd1\xdf\x80\xae\x07}\xb4\xa8\x9e\x8d\x8f\xd0\x99\x89\x17\ -\xe9\x0f\x83\xd8\x18\x15\xe3l&\xf3\xfa\x81\xc7C\x1c-\ -\xc5i \x8ds\x99t*\xfe\xdd\x01\xf1\xf9/\xb4\x9d\ -\x9b\xff\xee\x1e\x96\xf3\x05_#\xb1\xcf\x89\xeaw\xa4S\ -\xc8\x0b\x81\xf7\x00\xdf\x009\x9duu\x13\x99\x17\xe6\x89\ -\xf5\x1e\xf0\x8f\xe6\xdcq)\xc2\x11\x7f\xfd\xa5\xd8\xed%\ -\x06\xe2\xed`\xcf@l\x1cb\xc2\x98\xff\xc8\xeeS\xe7\ -\xe7\xbf\x94\x9e\xff\x04\xeb\xdf6\xa0\x98\x8c\xe7$~\xc6\ -g\xbfd\xbfW\xc1>\x8e\x14\xcd@\xec\x87\xa2\xfd\xa2\ -\xbf\x85\xb3\x94\x89t\xb4b=\xfa\xd09\xc2\xfc?7\ -\x13\xef\x19\xce\x0b@2\x13\xd6\x0c\xba<\xee\x01Z\x98\ -\x03'\xd3\xba\xf9\xc0\xcf\x7f*=\xff\x8d\xbf\xfe\x0cV\ -\xd1\xfaA\x0f*\xb1~Q\xdf\xd5\x15\xdf/\x12~\x07\ -v\x05\xf4\xa8\xdbj\x8ay\x09\xf0\xc8\xd4\xbd\xe3\xb1N\ -\x05{\x86\xf5\x05\xf8[\xbeM)\x9fu\xf3\x81\x9f\xff\ -Vz\xfe#\xce_3\xc1k\xc68\xca\xcd\xc0zh\ -\xf2\x06\x89\xec\x8b\xb2Ad\x8f6\x1dy\x9c\xed\xb2`\ -=K\xc2\xfcW\xe0]\x80\x93\xd4]\xa30\xe0x\xe6\ -J\x89s\x0c\x14\x11\x84\xf3_\xcb\xce\x7f\xb6\x14\xc0\x91\ -\xe2\xf6?\x95\x14\x84\xf3\x9f\xff\xd8\xfc\xf7?\xfd\xfeC\ -\xf5\xfd\x97\xea\xfbO\xd5\xf7\xdf\xc4\xde\x05\xfb\xa3\xee?\ -\x8a\xd8\x83?\xee\xfe\xab\x98=\xf8\xa3\xee?\x97\xb2\x0f\ -\xbf\xdd\xfdw\xba\xcc\x00I\xd7?\xe0\xd7\xd9\xe1\xd7\xd3\ -\xe1\xd7\xd1\xe1\xd7\xcb\xe1\xd7\xc5\xe1\xd7k\xa8\xae{S\ -\xc9\x83I\xfd(\xc4G0\xf5\x93_\x1f\x83_\x07\x83\ -_\xff\x82_\xe7\xc2\x84\x8fw\xa8\x13a\x84\xc0\x9c\x10\ -\xa8\x13\xd1\xaa\xec:\x11\x22\xce\x85\x06\x82A\x086!\ -\xb8\x8e\xe0\x19\x82\x08\x16\xc5\x83\xe5\x09\x11\xf4\xb3\xaf\xd3\ -\xef\x1aD\xbf[b\xba\x171os\x04\x81\x08R\x7f\ -\x01\xaf\x12\x86T\xfa\xdd\xe6\xc2\xeb\x90`\xee=\x10\xf8\ -\x22(\xa8\x84y\x0bC\x01=\x97\x1e\xe2\xd6 4\xf7\ -\xc9\x08b\x14`\xde\xc2\x10C\xcf\xad\xd8\x1aD\xcc\x9d\ -\xa5\x00s\x15\x07,\xe15\xb0\x8a\xd3\x8c\x22\xee\xbb(\ -<\x14\xa3%\x16u>|\x15`n\x92\x82/\xab\xf8\ -\x99\x863.\xdf\xb3Z\xccw\xa6#\xe4O\xd3&%\ -\x8b3\x8b\x85\x02z\xce\xfc\xbd\x0f\x94\xcf\xbc\xe9\xb8\xf6\ -\x0a}\x9cW\x011\xdb\xac+\x0ed\xce\x9dC\xd8\xdf\ -\x9bs\xff\x14\x99\xed\xbb\x1b\xdf\x8f\x06\x7f[a|G\ -:\xbfS \xabH6\xc9\xce\xdf\xd1\xbc!\xef\x16\xe6\ -\x9c\x1bv\x11\xc7vx\x05yb\x82\x15<\x92\x97\x93\ -F\xb2\xbf<%\xb3|\x9c\xb0\x1fU\x8a\xbc\xa0TV\ -\x91\x5c\x95m\xcf\xd1{S\xf7\x8c\xc1\xf1\x8b\xd2\xee\x8f\ -\x88\x1b\xe0\x93\x87|\x10|\xaf\xa0|y\xad|\x9d@\ -J\x1a\xa7b\xad\x10'\x87{~\xb2\x0d\x1e\xce\x9f\x01\ -\x7fn9\xe8\x89\xaf\xcfH5w\xf0\x1fC.\xbaX\ -:\x91b@\xdc5m\xffDI\xd7\xc0\xd7\xc5\xca?\ -\x7f\xeb\xe68\x97\xa9\xb4\x5c3\xbc\xab\xec\x5c\x9c\xe3\xc1\ -\xcf}\xc4\xf7\x02\xca\x88\xe3\xc3\xdf\xe2\x9c\xa0\xb2i\x89\ -\xafG\x96s\xefu\xf0\xbdX\x88?\x8b\x9f\xc3'\x1c\ -\xe7\x85\xbc\x0b\xb8\xab\x02yS\x90\xe3\x02\xb9\xdbp\xcf\ -\x0a\x9f\x95R\xee\xa1\xb2?=\xa2cA\xa5\xae\xe1U\ -\xb9\xe7O\xe7!\x88\x8b\xaf\xc3\x9ar\x82\x8e\x15\xdd\xf7\ -,\x96w(\xc0\xff\xd1\xb9I?2\x13\xf1\xa0'b\ -\xd7\x00\xeb/\xe3\x9e@\xf9\xe7\x8f\x00\xf8\xb9\xc8\xb9g\ -\xa7\x91\x99\x1e\xab\x0b\xf3\x08\xca|\x16\xce{\xeb\x8ep\ -\xe1#\xf2y\x90c\x06\xb9\x87\xa5\xc4\x06\xcb7\x7f\xfa\ -\x0e;'9\xae\xe4\xdc\x0b\xf2\xa9<8\xfc\xb7\xe5\xe0\ -\xe3\xb0\x06\xfb\x7fH\xf6\x87\x07\xa2q\x10|B~\xfb\ -\x8f\xde\x95yi\x9d\xc8\xf7@^(\x8e\xc5K\xa3\x13\ -\xc0\x9d\x97}\x13D\xe6{Q\xb9a\xdd\xc5\xe1\xb3|\ -\xf3\xb7n!\xf2^\x07\xc4\x1f\x0b\xf3H\xca;w>\ -\xac\xd0\xc3:F\x89\x81\xf0\x0a\xb9\x1eb\x9e-\xf9\xfc\ -!/\x1f\xf1\x10\xce\x8f\x92\xe7\x16\xee\xb9\x83\xee S\ -\x5c\x13\xdf\xb5\x9e^\x227\x11\x06\xe8L2\xcf\x1fr\ -\xfa\xb6\x0f\x11y\xaf+\xdbo\xbf\xec\xf1w|o\xae\ -\x1b\xce\xaf,A\x9bO/\x8b\xcb_+\xc7\xfc)\x1a\ -\x15\xa5\xdfd^(\xf3>\x9c\x04@\xe7H\x22\xbe/\ -< G\x0a\xe7\xe3\xc8:\xff\xfd\x93\xf0\xfd\xb1\xe2\xc4\ -\xcf\xa5j<\xc8\xe1>\x09\xce\xef\x12q_\x9d\xfd\xee\ -\x1e\x95\xe7$\xe3\xfc!\x87\x81\x97\x97Ur\xff/\xad\ -\x95\xcf\xfe\xafi\x87u\xea\x12\xfb\x1f\x19 \xfb\xfe\x8b\ -\xc8w\xe1\x8f\x9c{'e\xcfy\xc0\xf9D\xbdpN\ -\x9d\xf0\xa0\xee\xeb\x89\xfc^\xb9\xf8\x0f\xe4W\xe6G\xde\ -\xc1\xb6\x09\xbe\x9b\x02\x80\xfe\x1f\xf2\xb4\x81ve\xe3?\ -\xdad\xfa\xa9\x85\x22\xef\xfbg]\xdb\x22;\xff\x01\x80\ -\xdc\xa1\xf5\x9d\xa9;$p\xb7\x04\xc9M\x0c\x90s\x22\ -\xd3}\x12]L\xdf\x90\x9f/\xf8\x1e\xce\x19\x17:c\xf9\xaf\ -\xfdp\xce\x1b\xf0\xe5\xack\x9b\xb1\x1e\x09:2\xce\xb3\ --_\x9e1}_x\x98H\xb9\x08#\xfb\xe6\x8e\xd2\ -t\xc1b\xf3\x07\x19\x0awKA\x87\x843S\x10\x1f\ -\x85u\xe1bg\x0c\xe9o\xdc\xb4\x84\xe28F\xf6\x17\ -\xd8(\xec\xcfO0\x0d\x17\xe1\xa2\x14|\xd0~\x07\xb8\ -\xeb\x07w\xeaE\x0d\x90e8?M\x92\xf9\xc3>\xec\ -\x1c^\xe2\xee~A\xec+:\x87W\x97\xbe\xdb=\xab\ -T{\x11\xdf\xed\xb6\xd0\xc6x\xc2:\x85\xa0\xbfG \ -O\x15\xceM\xd6\xd5\x8d\xe2k\x05p9d\xe6\xe5\x0d\ -\x92\xdb/X\xbf)\x99\xf7\x0by\x99p\x1f\x8f\xff~\ -\xe0\x05\xe2\x06\xe8q\x90\xef\x96\xb8L\x0b\xd9XVX\ -nfyo\xc2k\x06\xff\x04\xc8o\xb8;\x095\xd3\ -\x00\xb7\xa5\xd9\x91\x14O+3\xef\xbb8\xfd\x8b\xb9\xb3\ -\x02\xb5\xca\xf0\xbe\xc1\xbf?\xbd\x22\xf6\x9d\x9c\x84\xf7\xd4\ -\xfd\x1at\x9e!\x8f\xb1p]H\x87\x84\xfcE|>\ -%\xb9\x13\xf0>\xa4(/\xb8\xf4\xf3\xc3\x8f{\x14\x9e\ -%\xb0A\x0a\xdf\x8b\xecS\xc8\xa3\xc4\xfa\x0d\xdc/X\ -\xdbQ,\xad\xc2\x80\x9cu\x9c\xbf\x86\xd6\x0a\xb8\x97f\ -\xe4\xbf\xbd[\x16\xcd\x0b\x02?fC\xcf_\x07\xf3\x82\ -\xdcG\x1eh\x1d\x0e\xf8lQw\xab\x9a\xe19\xe1\xda\ -\x16\xe9?\xc5\xbe;\xdboo!\x8d\x97w\xfe\xa0\x97\ -@-\x1a\xea~\x94\xc4\xfe\x1f~\xbc\xa9\xe8w\xc0\xff\ -VPwW\xc0\xee\x815\xa4\xee\x1d\x87\xcf\x1b\xf8+\ -3\x5c\x17\x93\xd9\xc8\xae\xc69\xae\x90;)\xe0C\x00\ -\x1e\xce\xbf\xf3\x92\xe9eW\xcal\x05\xe6\xcd\xce\xc3\xf4\ -\x82m\x94\x95\xe5\xce\xff\xe5\xc7\xcaD\xf27\xb8\xc3\x01\ -\xf2\x0f\xe8\x16\xdf\x99\xb5\xd0.\xba\xbb\x079\xaahM\ -\xb0\xb6\xcc\x0b\xab\xf0\x9a\x0a\xf1\x0e\xf2\xe8\xf4b|\x07\ -\x18\xe7}\x0b\x9eSn\x01>\xe7@\x97\xc0\xa3\xa1f\ -a\x92\xad\xa1\xb4\xf6\x03?\xceW\xd2\x7f\x8b\xe6\x01\xbc\ -\x9f?\xc0?YB\xc7,\xbc\xcbW\xb2\xde\x14\xe8\x03\ -8o\xfb\xe0T\x5c_\x09x\x00\x9c#\xb8\xbb\x07\xbe\ -g|\x9f\x91\x9fw,\x9d\xee\xc7\xf7\xdf\x8a\xf6\x9f\xa3\ -\xf9\x00\x0f)\x88\x0dG\xf0\x12\xdf;(\xf7\x1e\x15\xf3\ -\xf7\x0b\x82\x5cj\xa7\xf2\xfd\xe7b\xe3\x17Pk\x09p\ -\x8bA\xb4\xfdPY \x18\xbf(=~T\x91\xf7u\ -\xa5\x07\xe1\xf8\x11?~W\x15zt\x8b\x8a\xdfU\xd9\ -\xf8iU\x8f_\xff\x0e\xf9\x03\xbfC\xfeFU\xcd\x9f\ -\xc1yD\x1a\x04\x11\x03?\xd5\x08\x22\x18~*\xd3\xf9\ -G\xd5Y`2\x0f&\xfc\x87Q\xb4\xaf1\xf0S\xad\ -h\xdf!OK\x9f\xa0z\xfa\x14\xe6ii\x8a\xce\xd3\ -\x12\xc2e\x0d\x16\x95\x1b\xb8\x07\xc1c\x16\xc5\x1f\xbeJ\ -\x091\xf43\xf6\xd0\xcf\xac!L3B\xefn\x8e\xe0\ -\x10\x82\xc4\x0a8w\x89\xf4\xb3\x9b\x8b8K\x00\xffC\ -\x10V\x01\xef\x15\x860\xfa]\xc2\xeb\xfe\x15\xef\x16\x9c\ -\x03\x7f\x1fj\xd0\xfbR\xceg\xe8\x8a\xd6!%\xb73\ -\x0e\xb1\x8ahMr|\xd3\xbayaM|d\x1b\x81\ -\x9f\x18|;\xe9\xc7\xe6P9\x13\xe0\xd3-\xbbfj\ -\x22\xab\x88\xce%{7\xc4\xe4\xd6\x1b\xe1\xbc\x02\x5c\x93\ -\x1ej\x09\x09\xda\xedP\xbf\x22-\x01\xc7\xa2\xc0\xee\xc2\ -\xbam\xe9\xfb\xc1?c\x12\xac[\x07\xfb9\xe0\xbd\x12\ -\xd5\xc1G\xf6\x19\xd8\xcbP\xf3\xae\x949\xf0\xcfw\x99\ -\xefN?6\xbb\x14\x9f\x10W\xec\x9c\xa0\xde\x5c)v\ -?\x9f\xb7\x94\xb2\xe7:\x18\xcf\x90K\x22\xbc>\xf0)\ -\x80\x9f\x11h\x00\xd7@\xf0\xdfO\xf91\x84\xfc?P\ -\x03\x04|\x1c\x22\xf4\xf5\xaf\xa5\xbf_\x17\xfb\x8a\xc0\xaf\ -)8\xc0\x7f\x07\xef\xa4\xfch\xc5\xed'\xb0\xff\xc07\ -Y\xbc\xce\x17\x8f\xcc\xba\xbe\xa5\xfc\xef\x07\xbf\xde\x89y\ -\xc5\xfcz\xb0\x0f\xa9\xb8N\x9a\xb6h\xfa\xa6\xf7\x19h\ -T\xf0n5\xcc9ycOa<\x94\xfe~\xf0k\ -\x85y\x0a\xe0\x99C\xc7d\xca\xb07\xe9\xfc\x1b\xa8g\ -U\xb4\x05<\xea\xfey\xf1\xef\x8a\x7f?\xf8\x0d\xd1^\ -\x82?\x80?\x0a\xbeGIZ\xa7\x86\x8a\x8b\xb9\xfc[\ -\xcc\xf7-\x22^\x22\xfe\xfdP3\xd5i`\xb1\xb8N\ -\xde\x93\xcbd\x19y\x0f\xc5\xe7\x0f~\xcf\x9f\x9f\x04\xce\ -\xc2\x03:\x9e+\xc9\xfb\x9bb\xba\x17\xac\x17\x00\xfeM\ -\xc9\xf9\xab.\xb6\xaf\xe1Ny\xe1\xfe\xc5\xbc\xc0|S\ -\x80nJ\x7f\xff\xf6!\xc5\xea\xa5\xe5>\xf6\x90\xf0\xdd\ -\xf4\xfa\x11\xaf\x14\xc4\x1f\xc4@\x85\xe2I\xa5\xe3\x1f\xed\ -\x1f\xf0\x0f\xa0y\xc8\xad\xc0\xb9\x08\x92\xc6\xa3p\xbd\xbd\ -1\xc5\xf6/\xef\xd9\x15\xe18\x84\x88\xf7\x0b\xd8\xf5\xe8\ -o\x81\x06!\xbf\x07\xe7\xf9@\xcc\x03\x7f_2\xbb_\ -\xd0\xcf\x04CD=\xa4\xa2\xf7\xf3{\xbd ~S\x18\ -[\xa1c\xeb\xe0\x7f\x84\xfc\x0c\x88\xf3\xe2{\xde6\xad\ -K\xc5;U\x93eN1\xdc\x81\x5c\x02?\xa9\xc8\xf3\ -\x0fy~;\x86\xe2\xde2 _\xf2^\x5c\xa3\xe8\xd4\ -B\x9b\xaa\x1b\xc6?\xc2\xe8,A\x1c2\xeb\x86\x13Y\ -8g\xe1\x18\x02:\xf7\xe0\x8b\x17\x96\x15\x98vK\xc6\ -\x80\xa8\xf7C]\x1c\xc4\xbf\x0b\xe7\x9a\xfe\x83\x92\xe3\xe8\ -\x99\xa2r/ 7\x12\xe2\x18\x10\xa7\x009\x0b\xf1\x11\ -\xf0\xbd\xc13\xa0\x86\xa5p\xfe\x16\xf8\xcaD\xf0>\x81\ -\xf5\xf3\xcf:\x95\xc3\x00\xfc\x16\xea\xeb\x80\xfc\xc6\xf2V\ -`\x80\xcf\x1e\xeaxB\x0c\x0c\xd7\x92E<\x11\xf2\x93\ -\xb0\xbfVD\xdc\x01\xf2\xc5\xc0\x17*&g\x8d\xd6\x91\ -\xa9\xda\x80\xb9\xf7]1\xae3\x5c\x17b\xff6\xe4\xba\ -B\x1cVp\x80\x9f\x1bbU\xc9\x1b\x8c\x8a\xf1\x16Q\ -\x03\xea2\xc1\xbe\x94\xc23\xf8\xfa9\xf5\xd9\xba\x05\xf6\ -E\x83\xdf\x16x5\xd0>\xaeOq}+>;\xd0\ -?\x04\xe2\xc4\x98F\x817\x8b\x88\xcd\x81\xdf\x19jU\ -\x80\x5c\x869\x96\x91\xab\xc7\xb7\x0d\x8ax.Z\x1b\xd4\ -\x82\x85\xb8\x1b\xce\x0f\x82\x18(\x9d\xfb\x0by\xa4\xb8\x9e\ -\x14\xf0`\xc8SC4\x9e\xed\xbb\x0b\xe7\xffB\xedJ\ -\x1cs<<\x93\xf2\xc1JVG\x8eo\x97$\x16\xf1\ -\xac\xce\xb8n\x0d\xc8p*\x8fX\xe0\x19\xc2>?\xc1\ -\xfb\xed\x82y\xd5\x92\xf9\x05\xf9\xfagI\xfd[\xfa\xdc\ -\xe5\xf2\x00_\xff\xe6\xdb\x1fO*\xf8}\x82 h\x7f\ -(\x82\xfdUi\xf6ge\xdb\xdf\xccJ\xf4\xc6\xc0\xbb\ -\xc1O\xa1IP\xbe\x8aB?E\x8d\x92~\x0az\xce\ -\x0d\x100\x11\xbcG\x90\x8e C\x0c\xa4\xd3\x7f\xc3\xa4\ -\xbf\xc3\xff\xee9\x04\xdc\x12\xb8\x11\x7fv\xb9\xf4w\xf8\ -\xef\xe5\x96\xf8\x1e\xe4C >\x0du\xe7 \xa6\x07\xf9\ -'B|\x82+0\xe7b\xdf\x858\x19\xd4\xbc\x05\xdd\ -\x06\xc7\x82\xe9\xdeeX\xbe\xad-\xc6{\xf8\xeb-\xe4\ -C\xa0\x8f\xf0\xfbH\x80L\x86\x5c\xd7\xfc\x08\xbf\xc2\xba\ -3\xa0\xeb\x0a\xd4\x92\xe5\xefU\xe1\xf7!\xf7\x0f\x06<\ -\x03\xea\xc9\xe0\xba\xd7\xd6\xcd\xb1\xbc\x80\xb8\x92\x90\xbe\x9e\ -Q\xf8\xfd\xc2zDo\xb0n\x8c\xf3\xe2-\x04\xe2g\ -\x88_S\xb9\x08\xf9T~\x1b\x15\xdf\x11\xf8>U\x1f\ -\x06x<\xe4d\x95\xc8o\xc49\x08]q\xfdH\x88\ -\x9b'Q9*E\xdf\x07\x1b\x0b\xed7\xd4\xc3\xc3}\ -;\x84\xeb\xe5\xf2\xeb\xb1!\x1d\x02rQh\x1eN}\ -\x1fz\x06B\xdcxe\x0b\xec+H?\xb5\x80\xea\xaf\ -\x22X\xbb\x13\xfd?U\x9f\x93\xc4u\x04i}\x1f\x7f\ -\x1f\xf0\x022\x15\xea{\x81M\x08\xf8\x02\x9d\x18\xea\x99\ -\xa6\xee\x1c\x86\xf5\xf5\xec\xdb{q\xcc\x98\x9b\x9e\x88\xf5\ -OZ\xfee\xa0\x9f\xe9`\x93\xc1\x9cqn\x08]\x03\ -\x12\xf2xA\xbe\xc2w\xf89p \xfb\xa0G\x8a\x00\ -\xbdP\xf4\x8c\xf0\x93q\xde\x1a\xe7\x99C>\x04\xe8f\ -\xd0O\x03\xe4 \xc4z\xa1\x87\x16\xc4[\xa9\xbb\x0a\xc5\ -\xe8\x98:\x0b\xcbu\xb9)\xdb\x07Sz\xa0`\xcc\x16\ -\xeau\x01\x9e\xf8=\xe2\x8a\xcb\x1e>\xfdR\xe7g\xb9\ -\x0e\xb7\x1c\xb2I\xf0\xfc\xc8t~e\x1d\xff\x07\x9d\xab\ -\xf3\x85\ -\x00\x00_\x84\ -I\ -I*\x00\x08\x00\x00\x00\x17\x00\xfe\x00\x04\x00\x01\x00\x00\ -\x00\x00\x00\x00\x00\x00\x01\x03\x00\x01\x00\x00\x00`\x00\x00\ -\x00\x01\x01\x03\x00\x01\x00\x00\x00`\x00\x00\x00\x02\x01\x03\ -\x00\x04\x00\x00\x00\x22\x01\x00\x00\x03\x01\x03\x00\x01\x00\x00\ -\x00\x05\x00\x00\x00\x06\x01\x03\x00\x01\x00\x00\x00\x02\x00\x00\ -\x00\x11\x01\x04\x00\x01\x00\x00\x00@T\x00\x00\x12\x01\x03\ -\x00\x01\x00\x00\x00\x01\x00\x00\x00\x15\x01\x03\x00\x01\x00\x00\ -\x00\x04\x00\x00\x00\x16\x01\x03\x00\x01\x00\x00\x00`\x00\x00\ -\x00\x17\x01\x04\x00\x01\x00\x00\x00\x17\x0b\x00\x00\x1a\x01\x05\ -\x00\x01\x00\x00\x00*\x01\x00\x00\x1b\x01\x05\x00\x01\x00\x00\ -\x002\x01\x00\x00\x1c\x01\x03\x00\x01\x00\x00\x00\x01\x00\x00\ -\x00(\x01\x03\x00\x01\x00\x00\x00\x02\x00\x00\x001\x01\x02\ -\x00$\x00\x00\x00:\x01\x00\x002\x01\x02\x00\x14\x00\x00\ -\x00^\x01\x00\x00=\x01\x03\x00\x01\x00\x00\x00\x02\x00\x00\ -\x00R\x01\x03\x00\x01\x00\x00\x00\x01\x00\x00\x00\xbc\x02\x01\ -\x00\xfa8\x00\x00r\x01\x00\x00I\x86\x01\x00\x8c\x0d\x00\ -\x00l:\x00\x00i\x87\x04\x00\x01\x00\x00\x00X_\x00\ -\x00s\x87\x07\x00H\x0c\x00\x00\xf8G\x00\x00\x00\x00\x00\ -\x00\x08\x00\x08\x00\x08\x00\x08\x00\x00\xf9\x15\x00\x10'\x00\ -\x00\x00\xf9\x15\x00\x10'\x00\x00Adobe P\ -hotoshop CC 2015\ -.5 (Windows)\x00201\ -7:03:08 11:38:26\ -\x00\x0a\x0a \x0a \ -\x0a pain\ -t.net 4.0.9\x0a \ - 2017-03-0\ -7T11:32:29-08:00\ -\x0a 2017-\ -03-08T11:38:26-0\ -8:00\x0a <\ -xmp:MetadataDate\ ->2017-03-08T11:3\ -8:26-08:00\x0a \ - image/tiff\x0a \ - 3\x0a \ - sR\ -GB IEC61966-2.1<\ -/photoshop:ICCPr\ -ofile>\x0a \ -\x0a \ - \x0a \ - adobe\ -:docid:photoshop\ -:94a27cdb-0433-1\ -1e7-b02d-9f84d9f\ -5a326\x0a \ - \x0a <\ -/photoshop:Docum\ -entAncestors>\x0a \ - xmp.iid\ -:d3f831c7-1693-8\ -248-a9a0-2c4f91d\ -81b49\x0a \ - adobe:docid:\ -photoshop:c7bad1\ -dd-0436-11e7-b02\ -d-9f84d9f5a326\x0a xmp.did:a36\ -4ea4e-2280-ea40-\ -ae73-10beb7a78ae\ -8\x0a \ - \x0a \ - \x0a \ - \x0a \ - <\ -stEvt:action>cre\ -ated\x0a \ - xmp.iid:\ -a364ea4e-2280-ea\ -40-ae73-10beb7a7\ -8ae8\x0a \ - 2017-03-07\ -T11:32:29-08:00<\ -/stEvt:when>\x0a \ - <\ -stEvt:softwareAg\ -ent>Adobe Photos\ -hop CC 2015.5 (W\ -indows)\x0a \ - \x0a \ - \x0a \ - saved\x0a \ - <\ -stEvt:instanceID\ ->xmp.iid:d3f831c\ -7-1693-8248-a9a0\ --2c4f91d81b49\ -\x0a \ - 2\ -017-03-08T11:38:\ -26-08:00\x0a \ - Ado\ -be Photoshop CC \ -2015.5 (Windows)\ -\x0a \ - /\x0a \ - \x0a <\ -/rdf:Seq>\x0a \ - \x0a \x0a \ -\x0a\x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ -\x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a\ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ -\x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a\ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ -\x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a\ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ -\x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a\ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ -\x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a\ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ -\x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a\ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ -\x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a\ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ -\x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \x0a8BIM\x04\ -%\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x008BIM\x04:\x00\x00\x00\ -\x00\x00\xe5\x00\x00\x00\x10\x00\x00\x00\x01\x00\x00\x00\x00\x00\ -\x0bprintOutput\x00\x00\x00\x05\ -\x00\x00\x00\x00PstSbool\x01\x00\x00\x00\ -\x00Inteenum\x00\x00\x00\x00Int\ -e\x00\x00\x00\x00Clrm\x00\x00\x00\x0fpri\ -ntSixteenBitbool\ -\x00\x00\x00\x00\x0bprinterName\ -TEXT\x00\x00\x00\x01\x00\x00\x00\x00\x00\x0fpr\ -intProofSetupObj\ -c\x00\x00\x00\x0c\x00P\x00r\x00o\x00o\x00f\x00\ - \x00S\x00e\x00t\x00u\x00p\x00\x00\x00\x00\x00\ -\x0aproofSetup\x00\x00\x00\x01\x00\ -\x00\x00\x00Bltnenum\x00\x00\x00\x0cb\ -uiltinProof\x00\x00\x00\x09p\ -roofCMYK\x008BIM\x04;\x00\ -\x00\x00\x00\x02-\x00\x00\x00\x10\x00\x00\x00\x01\x00\x00\x00\ -\x00\x00\x12printOutputOp\ -tions\x00\x00\x00\x17\x00\x00\x00\x00Cpt\ -nbool\x00\x00\x00\x00\x00Clbrbo\ -ol\x00\x00\x00\x00\x00RgsMbool\x00\ -\x00\x00\x00\x00CrnCbool\x00\x00\x00\x00\ -\x00CntCbool\x00\x00\x00\x00\x00Lb\ -lsbool\x00\x00\x00\x00\x00Ngtvb\ -ool\x00\x00\x00\x00\x00EmlDbool\ -\x00\x00\x00\x00\x00Intrbool\x00\x00\x00\ -\x00\x00BckgObjc\x00\x00\x00\x01\x00\x00\ -\x00\x00\x00\x00RGBC\x00\x00\x00\x03\x00\x00\x00\x00\ -Rd doub@o\xe0\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00Grn doub@o\xe0\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00Bl doub\ -@o\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00BrdT\ -UntF#Rlt\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00Bld UntF#Rlt\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00Rslt\ -UntF#Pxl@b\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x0avectorDatabo\ -ol\x01\x00\x00\x00\x00PgPsenum\x00\ -\x00\x00\x00PgPs\x00\x00\x00\x00PgPC\x00\ -\x00\x00\x00LeftUntF#Rlt\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00Top U\ -ntF#Rlt\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00Scl UntF#Prc@\ -Y\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10cropW\ -henPrintingbool\x00\ -\x00\x00\x00\x0ecropRectBott\ -omlong\x00\x00\x00\x00\x00\x00\x00\x0ccr\ -opRectLeftlong\x00\x00\ -\x00\x00\x00\x00\x00\x0dcropRectRi\ -ghtlong\x00\x00\x00\x00\x00\x00\x00\x0bc\ -ropRectToplong\x00\x00\ -\x00\x00\x008BIM\x03\xed\x00\x00\x00\x00\x00\x10\x00\ -\x90\x00\x00\x00\x01\x00\x01\x00\x90\x00\x00\x00\x01\x00\x018\ -BIM\x04&\x00\x00\x00\x00\x00\x0e\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00?\x80\x00\x008BIM\x03\xee\x00\ -\x00\x00\x00\x00\x0d\x0cTransparen\ -cy\x008BIM\x04\x15\x00\x00\x00\x00\x00\x1e\x00\ -\x00\x00\x0d\x00T\x00r\x00a\x00n\x00s\x00p\x00\ -a\x00r\x00e\x00n\x00c\x00y\x00\x008BI\ -M\x045\x00\x00\x00\x00\x00\x11\x00\x00\x00\x01\x00\x00\xff\ -\xff\x00\x00\x00\x00\x00\x00\x00d\x01\x008BIM\x04\ -\x1d\x00\x00\x00\x00\x00\x04\x00\x00\x00\x008BIM\x04\ -\x0d\x00\x00\x00\x00\x00\x04\x00\x00\x00\x1e8BIM\x04\ -\x19\x00\x00\x00\x00\x00\x04\x00\x00\x00\x1e8BIM\x03\ -\xf3\x00\x00\x00\x00\x00\x09\x00\x00\x00\x00\x00\x00\x00\x00\x01\ -\x008BIM'\x10\x00\x00\x00\x00\x00\x0a\x00\x01\x00\ -\x00\x00\x00\x00\x00\x00\x018BIM\x03\xf5\x00\x00\x00\ -\x00\x00H\x00/ff\x00\x01\x00lff\x00\x06\x00\ -\x00\x00\x00\x00\x01\x00/ff\x00\x01\x00\xa1\x99\x9a\x00\ -\x06\x00\x00\x00\x00\x00\x01\x002\x00\x00\x00\x01\x00Z\x00\ -\x00\x00\x06\x00\x00\x00\x00\x00\x01\x005\x00\x00\x00\x01\x00\ --\x00\x00\x00\x06\x00\x00\x00\x00\x00\x018BIM\x03\ -\xf8\x00\x00\x00\x00\x00p\x00\x00\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x03\ -\xe8\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x03\xe8\x00\x00\x00\ -\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\x03\xe8\x00\x00\x00\x00\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\x03\xe8\x00\x008BIM\x04\x00\x00\x00\x00\ -\x00\x00\x02\x00\x008BIM\x04\x02\x00\x00\x00\x00\x00\ -\x02\x00\x008BIM\x040\x00\x00\x00\x00\x00\x01\x01\ -\x008BIM\x04-\x00\x00\x00\x00\x00\x06\x00\x01\x00\ -\x00\x00\x0a8BIM\x04\x08\x00\x00\x00\x00\x00\x10\x00\ -\x00\x00\x01\x00\x00\x02@\x00\x00\x02@\x00\x00\x00\x008\ -BIM\x04\x1e\x00\x00\x00\x00\x00\x04\x00\x00\x00\x008\ -BIM\x04\x1a\x00\x00\x00\x00\x035\x00\x00\x00\x06\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00`\x00\x00\x00`\x00\ -\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00`\x00\x00\x00`\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\ -\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00null\x00\x00\ -\x00\x02\x00\x00\x00\x06boundsObjc\ -\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00Rct1\x00\x00\ -\x00\x04\x00\x00\x00\x00Top long\x00\x00\ -\x00\x00\x00\x00\x00\x00Leftlong\x00\x00\ -\x00\x00\x00\x00\x00\x00Btomlong\x00\x00\ -\x00`\x00\x00\x00\x00Rghtlong\x00\x00\ -\x00`\x00\x00\x00\x06slicesVlLs\ -\x00\x00\x00\x01Objc\x00\x00\x00\x01\x00\x00\x00\x00\ -\x00\x05slice\x00\x00\x00\x12\x00\x00\x00\x07s\ -liceIDlong\x00\x00\x00\x00\x00\x00\ -\x00\x07groupIDlong\x00\x00\x00\ -\x00\x00\x00\x00\x06originenum\x00\ -\x00\x00\x0cESliceOrigin\x00\ -\x00\x00\x0dautoGenerated\ -\x00\x00\x00\x00Typeenum\x00\x00\x00\x0a\ -ESliceType\x00\x00\x00\x00Im\ -g \x00\x00\x00\x06boundsObjc\ -\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00Rct1\x00\x00\ -\x00\x04\x00\x00\x00\x00Top long\x00\x00\ -\x00\x00\x00\x00\x00\x00Leftlong\x00\x00\ -\x00\x00\x00\x00\x00\x00Btomlong\x00\x00\ -\x00`\x00\x00\x00\x00Rghtlong\x00\x00\ -\x00`\x00\x00\x00\x03urlTEXT\x00\x00\x00\ -\x01\x00\x00\x00\x00\x00\x00nullTEXT\x00\ -\x00\x00\x01\x00\x00\x00\x00\x00\x00MsgeTEX\ -T\x00\x00\x00\x01\x00\x00\x00\x00\x00\x06altTa\ -gTEXT\x00\x00\x00\x01\x00\x00\x00\x00\x00\x0ec\ -ellTextIsHTMLboo\ -l\x01\x00\x00\x00\x08cellTextTE\ -XT\x00\x00\x00\x01\x00\x00\x00\x00\x00\x09horz\ -Alignenum\x00\x00\x00\x0fESl\ -iceHorzAlign\x00\x00\x00\x07\ -default\x00\x00\x00\x09vertA\ -lignenum\x00\x00\x00\x0fESli\ -ceVertAlign\x00\x00\x00\x07d\ -efault\x00\x00\x00\x0bbgColo\ -rTypeenum\x00\x00\x00\x11ESl\ -iceBGColorType\x00\x00\ -\x00\x00None\x00\x00\x00\x09topOut\ -setlong\x00\x00\x00\x00\x00\x00\x00\x0al\ -eftOutsetlong\x00\x00\x00\ -\x00\x00\x00\x00\x0cbottomOutse\ -tlong\x00\x00\x00\x00\x00\x00\x00\x0brig\ -htOutsetlong\x00\x00\x00\x00\ -\x008BIM\x04(\x00\x00\x00\x00\x00\x0c\x00\x00\x00\ -\x02?\xf0\x00\x00\x00\x00\x00\x008BIM\x04\x14\x00\ -\x00\x00\x00\x00\x04\x00\x00\x00\x0d8BIM\x04\x0c\x00\ -\x00\x00\x00\x043\x00\x00\x00\x01\x00\x00\x000\x00\x00\x00\ -0\x00\x00\x00\x90\x00\x00\x1b\x00\x00\x00\x04\x17\x00\x18\x00\ -\x01\xff\xd8\xff\xed\x00\x0cAdobe_CM\x00\ -\x01\xff\xee\x00\x0eAdobe\x00d\x80\x00\x00\x00\ -\x01\xff\xdb\x00\x84\x00\x0c\x08\x08\x08\x09\x08\x0c\x09\x09\x0c\ -\x11\x0b\x0a\x0b\x11\x15\x0f\x0c\x0c\x0f\x15\x18\x13\x13\x15\x13\ -\x13\x18\x11\x0c\x0c\x0c\x0c\x0c\x0c\x11\x0c\x0c\x0c\x0c\x0c\x0c\ -\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\ -\x0c\x0c\x0c\x0c\x0c\x0c\x01\x0d\x0b\x0b\x0d\x0e\x0d\x10\x0e\x0e\ -\x10\x14\x0e\x0e\x0e\x14\x14\x0e\x0e\x0e\x0e\x14\x11\x0c\x0c\x0c\ -\x0c\x0c\x11\x11\x0c\x0c\x0c\x0c\x0c\x0c\x11\x0c\x0c\x0c\x0c\x0c\ -\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\ -\x0c\x0c\x0c\x0c\x0c\x0c\x0c\xff\xc0\x00\x11\x08\x000\x000\ -\x03\x01\x22\x00\x02\x11\x01\x03\x11\x01\xff\xdd\x00\x04\x00\x03\ -\xff\xc4\x01?\x00\x00\x01\x05\x01\x01\x01\x01\x01\x01\x00\x00\ -\x00\x00\x00\x00\x00\x03\x00\x01\x02\x04\x05\x06\x07\x08\x09\x0a\ -\x0b\x01\x00\x01\x05\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\ -\x00\x00\x01\x00\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x10\x00\ -\x01\x04\x01\x03\x02\x04\x02\x05\x07\x06\x08\x05\x03\x0c3\x01\ -\x00\x02\x11\x03\x04!\x121\x05AQa\x13\x22q\x81\ -2\x06\x14\x91\xa1\xb1B#$\x15R\xc1b34r\ -\x82\xd1C\x07%\x92S\xf0\xe1\xf1cs5\x16\xa2\xb2\ -\x83&D\x93TdE\xc2\xa3t6\x17\xd2U\xe2e\ -\xf2\xb3\x84\xc3\xd3u\xe3\xf3F'\x94\xa4\x85\xb4\x95\xc4\ -\xd4\xe4\xf4\xa5\xb5\xc5\xd5\xe5\xf5Vfv\x86\x96\xa6\xb6\ -\xc6\xd6\xe6\xf67GWgw\x87\x97\xa7\xb7\xc7\xd7\xe7\ -\xf7\x11\x00\x02\x02\x01\x02\x04\x04\x03\x04\x05\x06\x07\x07\x06\ -\x055\x01\x00\x02\x11\x03!1\x12\x04AQaq\x22\ -\x13\x052\x81\x91\x14\xa1\xb1B#\xc1R\xd1\xf03$\ -b\xe1r\x82\x92CS\x15cs4\xf1%\x06\x16\xa2\ -\xb2\x83\x07&5\xc2\xd2D\x93T\xa3\x17dEU6\ -te\xe2\xf2\xb3\x84\xc3\xd3u\xe3\xf3F\x94\xa4\x85\xb4\ -\x95\xc4\xd4\xe4\xf4\xa5\xb5\xc5\xd5\xe5\xf5Vfv\x86\x96\ -\xa6\xb6\xc6\xd6\xe6\xf6'7GWgw\x87\x97\xa7\xb7\ -\xc7\xff\xda\x00\x0c\x03\x01\x00\x02\x11\x03\x11\x00?\x00\xf5\ -T\x92@\xce\xbe\xdcl+\xef\xa6\xa7d[S\x1c\xea\ -\xe9f\xae{\x80\xf6\xb0\x7fY\xc9)\x8e_Q\xe9\xf8\ -Q\xf6\xcc\x9a\xb1\xf7}\x1fU\xedd\xff\x00Wy\xf7\ -\x22\xd1\x91\x8f\x93X\xb7\x1e\xd6]S\xb8}n\x0ei\ -\xfe\xd3%\xab\x98\xe8?Uq\xf31\x7fju\xfa\x9d\ -\x95\xd4\xb3\x7fI`\xbbp\xd8\xd3\xfc\xdd~\x94\xb7g\ -\xb3\xf3\x1d\xfc\xc7\xf3?\xe0\xd0rzs~\xab\xf5\xcc\ -\x0c\xae\x98\xe73\x03\xa9\x5c\xdc\x5c\xacB\xe2[\xb9\xda\ -Wcw\xeew\xb7\xe9\xfe\xfd\x7f\xcd\xff\x005v\xc4\ -\x94\xf6)$\x92J\x7f\xff\xd0\xf5U\x9b\xd6\xfa\xf6\x17\ -E\xaa\xb7\xe4\x8b,}\xee-\xaa\x9a\x9b\xb9\xee#W\ -}\x22\xc6\xedo\xf5\x96\x92\xe5\xfe\xbd\xfe\x87\x1f\xa6\xf5\ -\x01\xa3\xb0\xf3kt\xf84\xcb\x9d\xff\x00\x9e\x98\x92\x94\ ->\xb7\xf5[\xc4\xe1t\x0c\xab\x01\xfa.\xb6k\x1f\xf9\ -\xed\xcd\xff\x00\xa6\xb3\xba\x9d\x1f\x5cz\x8d\xf4u,\x9c\ -*q\x9b\xd3w_UN\xb09\xbb\x84Y\xea=\x8c\ -s\x9fe\x8d\xf4\xfd\x9f\xcd\xad\xff\x00\xad\xcf\xeau\xf4\ -Km\xe9\xaf5\xbe\xb2\x1f{\xd8@x\xa5\xb2\xeb\x9d\ -S\x8f\xd1s\x7f\xcf\xf4\xfdOO\xf4\x89\xfe\xaa]\x99\ -\x97\xf5~\x8bs\xec\x17\xbe\xdd\xfb^L\xb8\xd7\xb9\xcd\ -\xaf\xd5#\xfc&\xcf\xa7\xff\x00\x82~\x91%6>\xaf\ -\xf5Gun\x8f\x8d\x9fcZ\xcb.i\xf5\x1a\xd9\xda\ -\x1c\xd7:\xb7\xed\xdd\xee\xda\xed\x9b\x96\x8a\xe6?\xc5\xf9\ -,\xe9\x19\x18\x8e>\xecL\xabj\x8f\x01\xedw\xfdV\ -\xf5\xd3\xa4\xa7\xff\xd1\xf5U\x87\xf5\xd3\x0d\xf9\x7fV\xf2\ -\xd9[\x0d\x9606\xc65\xa2O\xb1\xcds\xf6\xb4\x7f\ -\xc1\xef[\x89$\xa7\x92\xa3\xeb\xadY8\x8c\xa2\x9e\x97\ -\x97\xd4\x1ek\x0c\xb86\xb0kq\xdb\xb6\xc1\xfe\x13u\ -n\xfeS\x13\xe3u_\xad\x1e\x8b1\xfa_\xd5\xe6a\ -\xe3\xd66\xd6\xcbl\x0ckG\x95_\xab\xae\xb1$\x94\ -\xe0}U\xe9\x1dK\x01\xd9\xf9]G\xd3\xae\xec\xfb\xbd\ -oB\xa2KX}\xc5\xee\xdc\x7f}\xcf\xfa\x1e\xff\x00\ -\xf8\xc5\xbe\x92I)\xff\xd9\x008BIM\x04!\x00\ -\x00\x00\x00\x00a\x00\x00\x00\x01\x01\x00\x00\x00\x0f\x00A\ -\x00d\x00o\x00b\x00e\x00 \x00P\x00h\x00o\ -\x00t\x00o\x00s\x00h\x00o\x00p\x00\x00\x00\x19\ -\x00A\x00d\x00o\x00b\x00e\x00 \x00P\x00h\ -\x00o\x00t\x00o\x00s\x00h\x00o\x00p\x00 \ -\x00C\x00C\x00 \x002\x000\x001\x005\x00.\ -\x005\x00\x00\x00\x01\x00\x00\x00\x0cHLino\x02\ -\x10\x00\x00mntrRGB XYZ \x07\ -\xce\x00\x02\x00\x09\x00\x06\x001\x00\x00acspM\ -SFT\x00\x00\x00\x00IEC sRGB\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf6\xd6\x00\ -\x01\x00\x00\x00\x00\xd3-HP \x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11cprt\x00\ -\x00\x01P\x00\x00\x003desc\x00\x00\x01\x84\x00\ -\x00\x00lwtpt\x00\x00\x01\xf0\x00\x00\x00\x14b\ -kpt\x00\x00\x02\x04\x00\x00\x00\x14rXYZ\x00\ -\x00\x02\x18\x00\x00\x00\x14gXYZ\x00\x00\x02,\x00\ -\x00\x00\x14bXYZ\x00\x00\x02@\x00\x00\x00\x14d\ -mnd\x00\x00\x02T\x00\x00\x00pdmdd\x00\ -\x00\x02\xc4\x00\x00\x00\x88vued\x00\x00\x03L\x00\ -\x00\x00\x86view\x00\x00\x03\xd4\x00\x00\x00$l\ -umi\x00\x00\x03\xf8\x00\x00\x00\x14meas\x00\ -\x00\x04\x0c\x00\x00\x00$tech\x00\x00\x040\x00\ -\x00\x00\x0crTRC\x00\x00\x04<\x00\x00\x08\x0cg\ -TRC\x00\x00\x04<\x00\x00\x08\x0cbTRC\x00\ -\x00\x04<\x00\x00\x08\x0ctext\x00\x00\x00\x00C\ -opyright (c) 199\ -8 Hewlett-Packar\ -d Company\x00\x00desc\x00\ -\x00\x00\x00\x00\x00\x00\x12sRGB IEC6\ -1966-2.1\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x12sRGB IEC6196\ -6-2.1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00XYZ \x00\x00\x00\x00\x00\ -\x00\xf3Q\x00\x01\x00\x00\x00\x01\x16\xccXYZ \x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00X\ -YZ \x00\x00\x00\x00\x00\x00o\xa2\x00\x008\xf5\x00\ -\x00\x03\x90XYZ \x00\x00\x00\x00\x00\x00b\x99\x00\ -\x00\xb7\x85\x00\x00\x18\xdaXYZ \x00\x00\x00\x00\x00\ -\x00$\xa0\x00\x00\x0f\x84\x00\x00\xb6\xcfdesc\x00\ -\x00\x00\x00\x00\x00\x00\x16IEC http:\ -//www.iec.ch\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x16IEC http\ -://www.iec.ch\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00desc\x00\ -\x00\x00\x00\x00\x00\x00.IEC 61966\ --2.1 Default RGB\ - colour space - \ -sRGB\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00.\ -IEC 61966-2.1 De\ -fault RGB colour\ - space - sRGB\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00desc\x00\x00\x00\x00\x00\x00\x00,R\ -eference Viewing\ - Condition in IE\ -C61966-2.1\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00,Reference \ -Viewing Conditio\ -n in IEC61966-2.\ -1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00view\x00\ -\x00\x00\x00\x00\x13\xa4\xfe\x00\x14_.\x00\x10\xcf\x14\x00\ -\x03\xed\xcc\x00\x04\x13\x0b\x00\x03\x5c\x9e\x00\x00\x00\x01X\ -YZ \x00\x00\x00\x00\x00L\x09V\x00P\x00\x00\x00\ -W\x1f\xe7meas\x00\x00\x00\x00\x00\x00\x00\x01\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x02\x8f\x00\x00\x00\x02sig \x00\x00\x00\x00C\ -RT curv\x00\x00\x00\x00\x00\x00\x04\x00\x00\ -\x00\x00\x05\x00\x0a\x00\x0f\x00\x14\x00\x19\x00\x1e\x00#\x00\ -(\x00-\x002\x007\x00;\x00@\x00E\x00J\x00\ -O\x00T\x00Y\x00^\x00c\x00h\x00m\x00r\x00\ -w\x00|\x00\x81\x00\x86\x00\x8b\x00\x90\x00\x95\x00\x9a\x00\ -\x9f\x00\xa4\x00\xa9\x00\xae\x00\xb2\x00\xb7\x00\xbc\x00\xc1\x00\ -\xc6\x00\xcb\x00\xd0\x00\xd5\x00\xdb\x00\xe0\x00\xe5\x00\xeb\x00\ -\xf0\x00\xf6\x00\xfb\x01\x01\x01\x07\x01\x0d\x01\x13\x01\x19\x01\ -\x1f\x01%\x01+\x012\x018\x01>\x01E\x01L\x01\ -R\x01Y\x01`\x01g\x01n\x01u\x01|\x01\x83\x01\ -\x8b\x01\x92\x01\x9a\x01\xa1\x01\xa9\x01\xb1\x01\xb9\x01\xc1\x01\ -\xc9\x01\xd1\x01\xd9\x01\xe1\x01\xe9\x01\xf2\x01\xfa\x02\x03\x02\ -\x0c\x02\x14\x02\x1d\x02&\x02/\x028\x02A\x02K\x02\ -T\x02]\x02g\x02q\x02z\x02\x84\x02\x8e\x02\x98\x02\ -\xa2\x02\xac\x02\xb6\x02\xc1\x02\xcb\x02\xd5\x02\xe0\x02\xeb\x02\ -\xf5\x03\x00\x03\x0b\x03\x16\x03!\x03-\x038\x03C\x03\ -O\x03Z\x03f\x03r\x03~\x03\x8a\x03\x96\x03\xa2\x03\ -\xae\x03\xba\x03\xc7\x03\xd3\x03\xe0\x03\xec\x03\xf9\x04\x06\x04\ -\x13\x04 \x04-\x04;\x04H\x04U\x04c\x04q\x04\ -~\x04\x8c\x04\x9a\x04\xa8\x04\xb6\x04\xc4\x04\xd3\x04\xe1\x04\ -\xf0\x04\xfe\x05\x0d\x05\x1c\x05+\x05:\x05I\x05X\x05\ -g\x05w\x05\x86\x05\x96\x05\xa6\x05\xb5\x05\xc5\x05\xd5\x05\ -\xe5\x05\xf6\x06\x06\x06\x16\x06'\x067\x06H\x06Y\x06\ -j\x06{\x06\x8c\x06\x9d\x06\xaf\x06\xc0\x06\xd1\x06\xe3\x06\ -\xf5\x07\x07\x07\x19\x07+\x07=\x07O\x07a\x07t\x07\ -\x86\x07\x99\x07\xac\x07\xbf\x07\xd2\x07\xe5\x07\xf8\x08\x0b\x08\ -\x1f\x082\x08F\x08Z\x08n\x08\x82\x08\x96\x08\xaa\x08\ -\xbe\x08\xd2\x08\xe7\x08\xfb\x09\x10\x09%\x09:\x09O\x09\ -d\x09y\x09\x8f\x09\xa4\x09\xba\x09\xcf\x09\xe5\x09\xfb\x0a\ -\x11\x0a'\x0a=\x0aT\x0aj\x0a\x81\x0a\x98\x0a\xae\x0a\ -\xc5\x0a\xdc\x0a\xf3\x0b\x0b\x0b\x22\x0b9\x0bQ\x0bi\x0b\ -\x80\x0b\x98\x0b\xb0\x0b\xc8\x0b\xe1\x0b\xf9\x0c\x12\x0c*\x0c\ -C\x0c\x5c\x0cu\x0c\x8e\x0c\xa7\x0c\xc0\x0c\xd9\x0c\xf3\x0d\ -\x0d\x0d&\x0d@\x0dZ\x0dt\x0d\x8e\x0d\xa9\x0d\xc3\x0d\ -\xde\x0d\xf8\x0e\x13\x0e.\x0eI\x0ed\x0e\x7f\x0e\x9b\x0e\ -\xb6\x0e\xd2\x0e\xee\x0f\x09\x0f%\x0fA\x0f^\x0fz\x0f\ -\x96\x0f\xb3\x0f\xcf\x0f\xec\x10\x09\x10&\x10C\x10a\x10\ -~\x10\x9b\x10\xb9\x10\xd7\x10\xf5\x11\x13\x111\x11O\x11\ -m\x11\x8c\x11\xaa\x11\xc9\x11\xe8\x12\x07\x12&\x12E\x12\ -d\x12\x84\x12\xa3\x12\xc3\x12\xe3\x13\x03\x13#\x13C\x13\ -c\x13\x83\x13\xa4\x13\xc5\x13\xe5\x14\x06\x14'\x14I\x14\ -j\x14\x8b\x14\xad\x14\xce\x14\xf0\x15\x12\x154\x15V\x15\ -x\x15\x9b\x15\xbd\x15\xe0\x16\x03\x16&\x16I\x16l\x16\ -\x8f\x16\xb2\x16\xd6\x16\xfa\x17\x1d\x17A\x17e\x17\x89\x17\ -\xae\x17\xd2\x17\xf7\x18\x1b\x18@\x18e\x18\x8a\x18\xaf\x18\ -\xd5\x18\xfa\x19 \x19E\x19k\x19\x91\x19\xb7\x19\xdd\x1a\ -\x04\x1a*\x1aQ\x1aw\x1a\x9e\x1a\xc5\x1a\xec\x1b\x14\x1b\ -;\x1bc\x1b\x8a\x1b\xb2\x1b\xda\x1c\x02\x1c*\x1cR\x1c\ -{\x1c\xa3\x1c\xcc\x1c\xf5\x1d\x1e\x1dG\x1dp\x1d\x99\x1d\ -\xc3\x1d\xec\x1e\x16\x1e@\x1ej\x1e\x94\x1e\xbe\x1e\xe9\x1f\ -\x13\x1f>\x1fi\x1f\x94\x1f\xbf\x1f\xea \x15 A \ -l \x98 \xc4 \xf0!\x1c!H!u!\xa1!\ -\xce!\xfb\x22'\x22U\x22\x82\x22\xaf\x22\xdd#\x0a#\ -8#f#\x94#\xc2#\xf0$\x1f$M$|$\ -\xab$\xda%\x09%8%h%\x97%\xc7%\xf7&\ -'&W&\x87&\xb7&\xe8'\x18'I'z'\ -\xab'\xdc(\x0d(?(q(\xa2(\xd4)\x06)\ -8)k)\x9d)\xd0*\x02*5*h*\x9b*\ -\xcf+\x02+6+i+\x9d+\xd1,\x05,9,\ -n,\xa2,\xd7-\x0c-A-v-\xab-\xe1.\ -\x16.L.\x82.\xb7.\xee/$/Z/\x91/\ -\xc7/\xfe050l0\xa40\xdb1\x121J1\ -\x821\xba1\xf22*2c2\x9b2\xd43\x0d3\ -F3\x7f3\xb83\xf14+4e4\x9e4\xd85\ -\x135M5\x875\xc25\xfd676r6\xae6\ -\xe97$7`7\x9c7\xd78\x148P8\x8c8\ -\xc89\x059B9\x7f9\xbc9\xf9:6:t:\ -\xb2:\xef;-;k;\xaa;\xe8<' >`>\ -\xa0>\xe0?!?a?\xa2?\xe2@#@d@\ -\xa6@\xe7A)AjA\xacA\xeeB0BrB\ -\xb5B\xf7C:C}C\xc0D\x03DGD\x8aD\ -\xceE\x12EUE\x9aE\xdeF\x22FgF\xabF\ -\xf0G5G{G\xc0H\x05HKH\x91H\xd7I\ -\x1dIcI\xa9I\xf0J7J}J\xc4K\x0cK\ -SK\x9aK\xe2L*LrL\xbaM\x02MJM\ -\x93M\xdcN%NnN\xb7O\x00OIO\x93O\ -\xddP'PqP\xbbQ\x06QPQ\x9bQ\xe6R\ -1R|R\xc7S\x13S_S\xaaS\xf6TBT\ -\x8fT\xdbU(UuU\xc2V\x0fV\x5cV\xa9V\ -\xf7WDW\x92W\xe0X/X}X\xcbY\x1aY\ -iY\xb8Z\x07ZVZ\xa6Z\xf5[E[\x95[\ -\xe5\x5c5\x5c\x86\x5c\xd6]']x]\xc9^\x1a^\ -l^\xbd_\x0f_a_\xb3`\x05`W`\xaa`\ -\xfcaOa\xa2a\xf5bIb\x9cb\xf0cCc\ -\x97c\xebd@d\x94d\xe9e=e\x92e\xe7f\ -=f\x92f\xe8g=g\x93g\xe9h?h\x96h\ -\xeciCi\x9ai\xf1jHj\x9fj\xf7kOk\ -\xa7k\xfflWl\xafm\x08m`m\xb9n\x12n\ -kn\xc4o\x1eoxo\xd1p+p\x86p\xe0q\ -:q\x95q\xf0rKr\xa6s\x01s]s\xb8t\ -\x14tpt\xccu(u\x85u\xe1v>v\x9bv\ -\xf8wVw\xb3x\x11xnx\xccy*y\x89y\ -\xe7zFz\xa5{\x04{c{\xc2|!|\x81|\ -\xe1}A}\xa1~\x01~b~\xc2\x7f#\x7f\x84\x7f\ -\xe5\x80G\x80\xa8\x81\x0a\x81k\x81\xcd\x820\x82\x92\x82\ -\xf4\x83W\x83\xba\x84\x1d\x84\x80\x84\xe3\x85G\x85\xab\x86\ -\x0e\x86r\x86\xd7\x87;\x87\x9f\x88\x04\x88i\x88\xce\x89\ -3\x89\x99\x89\xfe\x8ad\x8a\xca\x8b0\x8b\x96\x8b\xfc\x8c\ -c\x8c\xca\x8d1\x8d\x98\x8d\xff\x8ef\x8e\xce\x8f6\x8f\ -\x9e\x90\x06\x90n\x90\xd6\x91?\x91\xa8\x92\x11\x92z\x92\ -\xe3\x93M\x93\xb6\x94 \x94\x8a\x94\xf4\x95_\x95\xc9\x96\ -4\x96\x9f\x97\x0a\x97u\x97\xe0\x98L\x98\xb8\x99$\x99\ -\x90\x99\xfc\x9ah\x9a\xd5\x9bB\x9b\xaf\x9c\x1c\x9c\x89\x9c\ -\xf7\x9dd\x9d\xd2\x9e@\x9e\xae\x9f\x1d\x9f\x8b\x9f\xfa\xa0\ -i\xa0\xd8\xa1G\xa1\xb6\xa2&\xa2\x96\xa3\x06\xa3v\xa3\ -\xe6\xa4V\xa4\xc7\xa58\xa5\xa9\xa6\x1a\xa6\x8b\xa6\xfd\xa7\ -n\xa7\xe0\xa8R\xa8\xc4\xa97\xa9\xa9\xaa\x1c\xaa\x8f\xab\ -\x02\xabu\xab\xe9\xac\x5c\xac\xd0\xadD\xad\xb8\xae-\xae\ -\xa1\xaf\x16\xaf\x8b\xb0\x00\xb0u\xb0\xea\xb1`\xb1\xd6\xb2\ -K\xb2\xc2\xb38\xb3\xae\xb4%\xb4\x9c\xb5\x13\xb5\x8a\xb6\ -\x01\xb6y\xb6\xf0\xb7h\xb7\xe0\xb8Y\xb8\xd1\xb9J\xb9\ -\xc2\xba;\xba\xb5\xbb.\xbb\xa7\xbc!\xbc\x9b\xbd\x15\xbd\ -\x8f\xbe\x0a\xbe\x84\xbe\xff\xbfz\xbf\xf5\xc0p\xc0\xec\xc1\ -g\xc1\xe3\xc2_\xc2\xdb\xc3X\xc3\xd4\xc4Q\xc4\xce\xc5\ -K\xc5\xc8\xc6F\xc6\xc3\xc7A\xc7\xbf\xc8=\xc8\xbc\xc9\ -:\xc9\xb9\xca8\xca\xb7\xcb6\xcb\xb6\xcc5\xcc\xb5\xcd\ -5\xcd\xb5\xce6\xce\xb6\xcf7\xcf\xb8\xd09\xd0\xba\xd1\ -<\xd1\xbe\xd2?\xd2\xc1\xd3D\xd3\xc6\xd4I\xd4\xcb\xd5\ -N\xd5\xd1\xd6U\xd6\xd8\xd7\x5c\xd7\xe0\xd8d\xd8\xe8\xd9\ -l\xd9\xf1\xdav\xda\xfb\xdb\x80\xdc\x05\xdc\x8a\xdd\x10\xdd\ -\x96\xde\x1c\xde\xa2\xdf)\xdf\xaf\xe06\xe0\xbd\xe1D\xe1\ -\xcc\xe2S\xe2\xdb\xe3c\xe3\xeb\xe4s\xe4\xfc\xe5\x84\xe6\ -\x0d\xe6\x96\xe7\x1f\xe7\xa9\xe82\xe8\xbc\xe9F\xe9\xd0\xea\ -[\xea\xe5\xebp\xeb\xfb\xec\x86\xed\x11\xed\x9c\xee(\xee\ -\xb4\xef@\xef\xcc\xf0X\xf0\xe5\xf1r\xf1\xff\xf2\x8c\xf3\ -\x19\xf3\xa7\xf44\xf4\xc2\xf5P\xf5\xde\xf6m\xf6\xfb\xf7\ -\x8a\xf8\x19\xf8\xa8\xf98\xf9\xc7\xfaW\xfa\xe7\xfbw\xfc\ -\x07\xfc\x98\xfd)\xfd\xba\xfeK\xfe\xdc\xffm\xff\xff\x80\ -\x00 P8$\x16\x0d\x07\x84BaP\xb8d6\x1d\ -\x0f\x88DbQ8\xa4V-\x17\x8cFcQ\xb8\xe4\ -v=\x1f\x90HdR9$\x96M'\x94JeR\ -\xb9d\xb6]/\x98LfS9\xa4\xd6m7\x9cN\ -gS\xb9\xe4\xf6}?\xa0PhT:%\x16\x8dG\ -\xa4RiT\xbae6\x9dO\xa8TjU:\xa5V\ -\xadW\xacVkU\xba\xe5v\xbd_\xb0XlV;\ -%\x96\x10\x01\x07ZDA\x1b`\xac\x1bo\x0f\x81\xae\ -A\x10\x0d\xd4\x02\xf9\xbc<\x1eW\xb6\xe3\xc6\xfc\xda\xbf\ -<[vl&\x166\x0a\xc4\x06\x84x\xb2\xb6,F\ -Y\xb6\x04E@\x5c\xa02(\xfc\xcc=\xdd\x99\xb6c\ -\x83<\xb2n\xe8U\x0f]#\x93\x0d\xa7\xc3\x04\xf5C\ -\x01n\xb4\xde\x1e\xd8\x12\xc1\x1b0\xac\xb1\xf1\xb7v7\ -\xf7J\xe6\xce\xf5:\xea\xe02\xb5\x1c:\xc8\xbf\x8cu\ -\x19\xf2O\xe0N`.x\xfd\xe8>\x18\xbd3cc\ -\xac\x9d\xe2vi ~\xe0K\x923?\x8b\x10*b\x1eA\x04\xa8U\x05\x8dH\ -\xc1\xdd\x07\x9aN\x01\xd4e\x9c\xf0\xa9\x82\xd2\x1e\xa7)\ -\xfd\x0d\x9f,\xa0\x0a\xb7\xad\xe1\x105\x11\x88\x00\x94L\ -\x16\x02\x11HP\x81\x80(\xc1\xad\x17\x93\x064d6\ -\xc3g\xf1\xf9\x03G\x09(]\x1d\x8eA\xc4|F\xa2\ -\x90\x91\x94fH\x83\xe1\xcb#\x97\xb0\x11\xff\x02\x22\xe0\ -\x14\x9c\x02\x832\x88|\x18\xca\x83\xe4F\x0d\x08\x08\xc1\ -\xa1-\x90\xe6T\xbc=G3\x0a;\x13\x02Ah\xa1\ -3\x99\x0e`\x08\x05\x22\x06\xdc\xdcR\x18s\x88\xcc\xcc\ -\x1f\x87\xbaP\xbb\x00MhZ8\x86\xf3\xe9\x12\xbb\x00\ -h\x82\xf0|\x9d\xe5U\x0c\x14=\x87\xb9\xd51Q\x88\ -\xa8\x93G\x96\xc0\xed$$\xa2\x0d\x09\xbaT\x97\xf4\xc8\ -\xbd\x1a\x9fI\xa07O\x88b\x0dDR1\x00P0\ -\x88\x1bUIB`U\x83\x05\x1bW\xa1\xa0]d\x0d\ -\x8a\xf5\xa9\xb359\xc8\x5c0r\x15\xb5\xe8`\xdb\x9f\ -\x07jx\x0b\xd8\x81\xd0\x9bc\x98\x12p\x04\x02\xa1\x94\ -\xe1Wg\x85\x8c\x0b\x07XZ\x88 ik\x90A\x95\ -\xb4>\xa2\x13\x89\x864\x1a\xf7\x092\xa2\x077)\x1f\ -=\x0e\x08\x84\xb6h\x11\x12\xf1\x94<\xda\xb5\x83\xb8\x03\ -\x82U\xa8\xael6`Cj\x85\xd1'QQ\x7f\x84\ -\x87\xde\x04y\xa8\x80\x1e\x0c\x04\x0axI\xa1\x14\x82\x01\ -:\x18y\xe2\x07\x05\x9eU\x85s\xa1\xedx\xcc/\x10\ -X7\x07X\xe9\x22\x887F\xf9\x5c]\xe4\x82\x9a\x99\ -\x8d\x0d\xf8\xe8tH!\x92Q\xfcWf\x01\x99\xdb\x99\ -\x9a\x18\xc3\xe0\xf9\x01\xe2\xb6tkT\xa0\xd2\x1e\x7f\x96\ -Z\x08zth\x86*\x98\x04\xe9\x00\xbet+\x1a\xf7\ -\x98\x22\x86\x17\x9a\x88\xaaoj\x85fl\xf7\xe1\x81D\ -\xce(\x18\xef\x90 \x86h\x87A\x86Y\xec\x82\x06\x5c\ -\xa8\x0a;I\x96\x0a\xed\x81\xa2\x18an\x03#\xcc\xec\ -j\xef\x80\x03Y\x01`\xd6\xd8\x0a\x86\xb7D\xa2\x0c\x87\ -\xe8#\xfe[\x89G\x1f\x0c[\xaa\x827\x14X\x04\x1c\ -h\x9e\x86FF0\xdcjr\x84\x9e\xebx\xd3\xe0\xd8\ -\x87\xcc\x88\x86o<@:\x07\xe9\xf2\xaaQ\xe2M#\ -I\xf2\x11\x97'\xca\xf2\xfdj\xb35\x018H\xa6h\ -\x81\xfd\xa8J\x86\x18=\xc8\xc6\xde\x9b$\xf7]\xdf\xaa\ -\xaf\xc0,\x1ckf4X\x86\x17^H\xa4\xcf\x1c\x05\ -\x7f\x81\xe7\xaa!\xf7\xa4M\x85\x1e\xa8\xc9\x96\xc0G\xe9\ -_\xed\x86\xcc\xd9\xd8gz\x1f\x0a\x92\xc8\x85B\x97\xcc\ -g`\xc0\x18\x0e\x86\x1d\xffi\xad^\x95\xa1\x8d9\xf1\ -~\x8a-\xca\x1c\x91\xd3\xd0\xe2\x88s\xc6i\x02\xffD\ -\x03\xf5\x80E\x05\xf4\x80v\x966\x11\x00 !\x83\xda\ -\x06\x0ef`+\x81\xa4\x0c\x1e\xc3\x9e\x01\xc1Rz\x95\ -\xc2\x10L\x83B\xf1\xe3\x90\xb1\xf5\x07\xc7\x84!\x1e\x03\ -e<\x0fHL8\xc7\x0c)\x16*\xa4m\x0a(-\ -\x0b\xc8\xaa\x1e\x01\x8d \x04\x81d@\x08KH\x0e\x04\ -\x802\x1e\x01\xd8h\x06\x1b\xf8>v\xa0=\xdb\x923\ -\xf89\x05\xd3\x91\x0d\xf0\x88lC\x07\x5c\x87\x80kx\ -\x03p&!\x82f\x18\x0ab\x18$\x87 \x8e\x1a\x01\ -epO\x10x\xee\x1aB\xc22\x03\x96-\x13\x8a\xe2\ -x\x86L\xe1\xbcC\xe6\x90\x05\xa2\xec?\x87\x800\x0e\ -\xb0\xc0O\x1bU(\x19\x80\xa5a\xe4\x8b\xa7\x96g\x9e\ -th(\xcb(\x02\xb7\xb0i\x0eA!\x91\x05q\xda\ -\x1c\x82%\xe6\x04\x95\xc3NQ\x90\xb0P*\xc1\x80\x18\ -d\x11>k\xc0\xaeN\x06\xb0E'\xc2\xa9\xaa\x02`\ -\xbd\x1c#Q\xf6\xc5\x96\x00\xeci\xd2<\x86!Q\xce\ -0\x9b \xb3p2d\x9cH\x80\x8f-\xc5\x84\x8a,\ -\x08\xd4~,\x01\xd5\x09\x87\xa0\xe2\x89\x90\x88\xc0\x17\xe1\ -\xb2\x86\x074\x1f\x1fC\xc6e\x0e\xf5\x06<\x10@<\ -\x12\xa0\x9ej\x06\x22\x190\x07\x18\xac\x9b@\xb6e\x0f\ -\x19hL$ N\x9cC\x0d\xe1\x03r\x98\xe8G\xc2\ -\x89\x1dl@y\x8d\xe3\x027!\x10\xd6\x89\x93\xb0p\ -\xcc\x01\xc4\xc0\x87\xdb\x04#i\xf4\x1b\x88\xa3\x8c\x0b\xc3\ -\xa9\x0ct#\xe6m\x0a\xc0\x5c`F\xd4\xdf%\xe0\x9a\ -\x86\x06\x00\x81C\xc4\xf90e\xca\x0cv\xcd\x8a\x10\xb4\ -\xa0\x90\xe8Pc\xb9`N\xb6\x22\xa2GL\xf8\x1e\x84\ -\xd2N\x02\xb0\xd6\x0e\xe9@\x94\x22\x02\xe2\x96\x04\xb1\xc5\ -K\xc5\xb5\x0a%\xce(#\x0a\xf7\x1a\x08\x02\x81\x18\x97\ -\x94vv\x0e\x02\xf6<\x86\xeb\xed\x1d\xe3QiS\xf1\ -\xbb=\x94\x18\xef*\x8ep%\xd4\xd1vD\x06=Q\ -\x0e#N\xaa2\xcadK\x168M\x181\x04\x86Q\ -\xd1\xa5W\xc4ta\x1aS\xd1]\xcd\xd3\x87\x16\xc2\xad\ -i\x1a\xb1\xec\x85\xa2\xf1\xac&\x06%q\x0d5\x5c\x96\ -P\xf0\x80(h`&\x0b\xd0.\x06\x8aZ\xfc\x07\x92\ -P\xfdQ\x8f\xa4\x044\xb1\xaf\x02H`\xe6\xb1B\xfc\ -ZX\xd0\x85]\x09X0\xb2A\xe4\x1bYQ\x0c\xf6\ -\x07\xf8\xfd~\x00\xca\xb1-J\xb20\x1b\xfc\xb3!T\ -\xfcoPP[\x19\xec\x81%\x03\xf6\xac&\xcbp\x8e\ -,\x88\x83Q\x17\x8dM\xaa\x93KBc\x82\xb47\x95\ --\x84b&\xe1\xb6)S\xa0\xf5%\x93DK \xb0\ -U\x5c\xc8\x5c\xe8\xa0\xa0\xbe\x84Z\x92J\x99\x01s\xb2\ -\x19\xe9\xe0\x86.\xe0\xf0\xba\xc4I,\xb0\x8f\xdcG\x82\ -\x9b\xbc\x19\xae\xa1\x0b\x1d7\x8cc)\x91~\x17\xaa1\ -(G`\xb9\x1e\xa3\xf2 -o\x80DH\xe3\x94^\ -\xdc\xe2H\xd7\x97\xb0\xd8\x86\x80\x5c\x86[\xe1Gy\xab\ -\xd9*\x004\xd0WSzrE\xe7\xb4}\x0a\x0fx\ -g\x92E$\x07BC\xa5q\x04>\xb8\x8c@\xd5[\ -\x84\xbd\xf6$\xed\xa4(\xb6\xb6\xdaC\x10\x90\xc8\x8c\x82\ -\xc0\x1c\x92\x8bCg\xc9\x03\x86\x1cb\xe1\xc1\xa9BG\ -\x1d\x82\xa61\x1ar\x10\x86.\xb5\xda\x97\x97\x86\x1a$\ -\xa1\x0f\x1e\x0as\x1c\x16\x08b\xbbP\xc2\xa8\x15O\x89\ -\xf4H\xab\xb0\xa0\xaf!|\x90A!\xce\xbf\xc5@%\ -\xb8$\x82\x19@x\xa4C\x1d\xe0\x9ew#\x041\xe3\ -\xa2J\xb6\x81\x90|Z\xe0\xd0A\x90\xc6-\x90\xc1T\ -\xc0\x1c$\x93\x0ea\xe0*\xdb\x88\xfc\xe8b`\xae\xd2\ -\x12I\xc4\x13\x86\x18\x18\xcf@\xf0\x86R\xf1\xc4-)\ -`\xb8\x09\xb9x\x92\x18\xe0\xaf\x8f\x02\x18\xa8\xb3\x16i\ -^\xd9\xc4 I,\xfd\xa1$\x14\x8b9\xcfbI\x92\ -rY\x0c\x1dzlf=\xb1^\x0d\x88\x18\xff\xd0\x84\ -~Q\x03\x07\xcc\x14\x86m\xe1!V4Z\x04+\x14\ -9\x85\xf9$\xcckem\x92\x0a\x8d\x90\xc1L\xa6$\ -\x97\xac:#\xe0p\x22\xc8e b`\xb2T\xea2\ -<\xbe@\xa2\xf6\x1bRH\x85\xc9`\xbf\x0b!q#\ -\x91\x0d,j\xac\xa0\x0cG\x1c\xa0\xd4\x12.Et\x92\ -{V\x07\xc2u\xae\x16+5\x0d\x8f\xc8\x1f\xa3\x87p\ -\xd3\xd8\xc4u@\x1cH#\x82\xc4\ -i\xcd\x07\x02(\x8a\xef\x08Y@\x08!\x83\xd2\x19`\ -\xf6\x19\xf0\xc4\xb2\xe2nP\x0b\xf6\xfbH\xb6\x91H\xb6\ -k(\xf2\x8a\x07`&\x0e\xc8\x11\x8e\xc2\x19\x0a\x03\x0b\ -\x02&g\x05\xec\x1b+\xf6\xf5g*r#\xc8#e\ -\x00M@\x15\x08\xe8\xe6\x03\xe8\xaa\x8a\xa7\xc8\x81/\xb4\ -k\xc2\x90\x99A\xe0\xb3i\xd8\x1b\xf0\xec\x22\xc0\x02x\ -\xa7\x84?B\x16\xf4a\xb8\x14\xcf@\x17\xc0\xb6 \x8b\ -\xf6\x8f0\x9cEH\xb2D\x00E\x0aF\x9ck\xc8d\ -+\x8a@\x171\x5c\x0a\x0cC\x12b4\x08Qh\x14\ -\xa0I\x16\xe0\xb4\x9a\xe8L\x1c.\xde\x18\xe8\xab\x10\xa6\ -\x9c\xd5C\x88\x99A\xe4\x95\xc1\x80H\x81\x98\x0f\xe6f\ -\x1d\xa6k\x16B8\xb2@`\x0f\x0e8\x10\xe9J\xdc\ -\xa9|\x9e\xc9\x88\xa7\xe1\xb6X\x01\xda\xa3\xa9R\xa8\xc9\ -\xb1\x19\xc2H\xebn\xba\x9cN\xbe+i\xd1\x1b\xe2\xf6\ -\x9d\xc2\xfc\x1bi\x86\x84!\xac\x9e\x89\xec\xc8\xd1\xc4'\ -\xe7`\xb5\xc1ds\x82v\x1f\xe9R\x9b\x040\x1c\xaa\ -(\x9dQ\xfe0!\xb2\x9d\xeaA\x1e\x91\xea+0\xa4\ -\xae\xc1D\xa6\xe7\x1e#jv7\x11\x22\x9d\x81\xbc\x8c\ -!\xaa\x9ef \x1b\xec\xd4\xa92\x12Z\xa4\xf0\xeam\ -\xbe\x09\xa9\x1e\x97\x91\x1c\xa2\xe2\xfc\x1b\x8a\x85\x1e& \ -\x1b\xd1\xfe\xf2\xf2;%\xf2a&2e&ri&\ -\xb2m&\xf2q'2u'ry'\xb2}'\xf2\ -\x81(2\x85(r\x89(\xb2\x8d(\xf2\x91)2\x95\ -)r\x98(\x22\x02\x00\x03\x00\x01\xa0\x03\x00\x01\x00\x00\ -\x00\x01\x00\x00\x00\x02\xa0\x04\x00\x01\x00\x00\x00`\x00\x00\ -\x00\x03\xa0\x04\x00\x01\x00\x00\x00`\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\ -\x00\x00\x02\x9e\ -<\ -?xml version=\x221.\ -0\x22 encoding=\x22UTF\ --8\x22?>\x0d\x0a\x0d\x0a \x0d\x0a \ - Artboard\ -\x0d\x0a Created with\ - Sketch.\x0d\ -\x0a \x0d\x0a \ - \x0d\x0a \ - \x0d\x0a \ - \x0d\x0a <\ -/g>\x0d\x0a\x0d\x0a\ -\x00\x00\x02\xa4\ -<\ -?xml version=\x221.\ -0\x22 encoding=\x22UTF\ --8\x22?>\x0d\x0a\x0d\x0a \x0d\x0a \ - Icons / \ -System / Carat /\ - White / Default\ -\x0d\x0a Created with\ - Sketch.\x0d\ -\x0a \x0d\x0a <\ -polygon id=\x22Tria\ -ngle\x22 fill=\x22#FFF\ -FFF\x22 transform=\x22\ -translate(8.0000\ -00, 8.000000) sc\ -ale(1, -1) trans\ -late(-8.000000, \ --8.000000) \x22 poi\ -nts=\x228 6 12 10 4\ - 10\x22>\x0d\ -\x0a \x0d\x0a\x0d\x0a\ -\x00\x00\x05!\ -<\ -?xml version=\x221.\ -0\x22 encoding=\x22UTF\ --8\x22?>\x0d\x0a\x0d\x0a \x0d\x0a \ - icon / o\ -utliner / slice \ -/ standard copy \ -2\x0d\x0a <\ -desc>Created wit\ -h Sketch.\ -\x0d\x0a \x0d\x0a \x0d\x0a \ - \x0d\x0a \ - \x0d\ -\x0a \x0d\x0a\ - \x0d\x0a \ - \x0d\x0a\x0d\x0a\ -\ -\x00\x00\x035\ -<\ -?xml version=\x221.\ -0\x22 encoding=\x22UTF\ --8\x22?>\x0d\x0a\x0d\x0a \x0d\x0a \ - icon / o\ -utliner / layer \ -/ default\x0d\x0a Cre\ -ated with Sketch\ -.\x0d\x0a \x0d\x0a \ - \x0d\x0a \ - \x0d\x0a \ - \ -\x0d\x0a \ - \x0d\x0a \ -\x0d\x0a \x0d\x0a\x0d\x0a\ -\x00\x00\x04\xa0\ -<\ -?xml version=\x221.\ -0\x22 encoding=\x22UTF\ --8\x22?>\x0d\x0a\x0d\x0a \x0d\x0a \ - icon / o\ -utliner / entity\ - / Not active - \ -Default\x0d\ -\x0a Creat\ -ed with Sketch.<\ -/desc>\x0d\x0a \x0d\x0a <\ -g id=\x22icon-/-out\ -liner-/-entity-/\ --Not-active---De\ -fault\x22 stroke=\x22n\ -one\x22 stroke-widt\ -h=\x221\x22 fill=\x22none\ -\x22 fill-rule=\x22eve\ -nodd\x22>\x0d\x0a \ -\x0d\x0a \ - \x0d\x0a\x0d\x0a\ -\x00\x00\x09\x94\ -<\ -?xml version=\x221.\ -0\x22 encoding=\x22UTF\ --8\x22?>\x0d\x0a\x0d\x0a \x0d\x0a \ - Artboard\ -\x0d\x0a Created with\ - Sketch.\x0d\ -\x0a \x0d\x0a <\ -g id=\x22Sky-Icon-/\ --System-/-View\x22 \ -transform=\x22trans\ -late(-1.000000, \ --1.000000)\x22>\x0d\x0a \ - \x0d\x0a \ - \x0d\ -\x0a \x0d\x0a <\ -path d=\x22M7.06342\ -091,12.9074237 L\ -7.88176629,12.08\ -90784 C8.2054235\ -6,12.1935613 8.5\ -5066739,12.25000\ -46 8.90909425,12\ -.2500046 C10.754\ -2281,12.2500046 \ -12.2500046,10.75\ -42281 12.2500046\ -,8.90909425 C12.\ -2500046,8.550667\ -39 12.1935613,8.\ -20542356 12.0890\ -784,7.88176629 L\ -13.4371592,6.533\ -68547 C14.319022\ -1,7.17645386 15.\ -2844155,7.968256\ -79 16.3333395,8.\ -90909425 C13.022\ -4727,11.8787923 \ -10.5438307,13.36\ -36414 8.89741345\ -,13.3636414 C8.3\ -7051833,13.36364\ -14 7.75918749,13\ -.2115688 7.06342\ -091,12.9074237 Z\ - M5.69216773,12.\ -1787833 C4.48306\ -461,11.4370945 3\ -.08062505,10.347\ -1982 1.48484904,\ -8.90909425 C4.78\ -014139,5.9393961\ -7 7.25099619,4.4\ -5454713 8.897413\ -45,4.45454713 C9\ -.76312087,4.4545\ -4713 10.8589211,\ -4.865077 12.1848\ -142,5.68613676 L\ -11.2977095,6.573\ -24152 C10.691167\ -6,5.95308542 9.8\ -450802,5.5681839\ -1 8.90909425,5.5\ -6818391 C7.06396\ -042,5.56818391 5\ -.56818391,7.0639\ -6042 5.56818391,\ -8.90909425 C5.56\ -818391,9.8450802\ - 5.95308542,10.6\ -911676 6.5732415\ -2,11.2977095 L5.\ -69216773,12.1787\ -833 Z M8.8358430\ -8,11.1350016 L11\ -.1461965,8.82464\ -811 C11.1472437,\ -8.85266758 11.14\ -77719,8.88081938\ - 11.1477719,8.90\ -909425 C11.14777\ -19,10.1391835 10\ -.1480347,11.1363\ -678 8.91479629,1\ -1.1363678 C8.888\ -36881,11.1363678\ - 8.86204856,11.1\ -359099 8.8358430\ -8,11.1350016 Z M\ -7.3616286,10.509\ -3224 C6.94241377\ -,10.1044297 6.68\ -182069,9.5371166\ -3 6.68182069,8.9\ -0909425 C6.68182\ -069,7.67900503 7\ -.68155792,6.6818\ -2069 8.91479629,\ -6.68182069 C9.54\ -237304,6.6818206\ -9 10.1094814,6.9\ -4005568 10.51514\ -44,7.35580661 L7\ -.3616286,10.5093\ -224 Z\x22 id=\x22Combi\ -ned-Shape\x22 fill=\ -\x22#E9E9E9\x22>\x0d\x0a <\ -polygon id=\x22Rect\ -angle-25\x22 fill=\x22\ -#E9E9E9\x22 transfo\ -rm=\x22translate(8.\ -582044, 8.280986\ -) rotate(45.0000\ -00) translate(-8\ -.582044, -8.2809\ -86) \x22 points=\x227.\ -7813425 0.916636\ -365 9.38274632 0\ -.913653421 9.358\ -23763 15.6483178\ - 7.7813425 15.61\ -58919\x22>\x0d\x0a \x0d\ -\x0a \x0d\x0a\x0d\x0a\ -\x00\x00\x05\x1f\ -<\ -?xml version=\x221.\ -0\x22 encoding=\x22UTF\ --8\x22?>\x0d\x0a\x0d\x0a \x0d\x0a \ - icon / o\ -utliner / slice \ -/ Editor only -\ - Saved\x0d\x0a\ - Create\ -d with Sketch.\x0d\x0a \x0d\x0a \x0d\x0a \x0d\x0a \ -\x0d\x0a\x0d\x0a\ -\x00\x00\x02\x9e\ -<\ -?xml version=\x221.\ -0\x22 encoding=\x22UTF\ --8\x22?>\x0d\x0a\x0d\x0a \x0d\x0a \ - Artboard\ -\x0d\x0a Created with\ - Sketch.\x0d\ -\x0a \x0d\x0a \ - \x0d\x0a \ - \x0d\x0a \ - \x0d\x0a <\ -/g>\x0d\x0a\x0d\x0a\ -\x00\x00\x05#\ -<\ -?xml version=\x221.\ -0\x22 encoding=\x22UTF\ --8\x22?>\x0d\x0a\x0d\x0a \x0d\x0a \ - icon / o\ -utliner / slice \ -/ Editor only -\ - Updated\ -\x0d\x0a Crea\ -ted with Sketch.\ -\x0d\x0a \x0d\x0a \ -\x0d\x0a \ - \x0d\x0a\ - \x0d\x0a\ -\x0d\x0a\ -\x00\x00\x06\x09\ -<\ -?xml version=\x221.\ -0\x22 encoding=\x22UTF\ --8\x22?>\x0d\x0a\x0d\x0a \x0d\x0a \ - icon / o\ -utliner / lock /\ - on\x0d\x0a \ - Created w\ -ith Sketch.\x0d\x0a \x0d\x0a \ - \x0d\x0a\ - \x0d\x0a \ - \x0d\x0a \ - \x0d\x0a\ - \ -\x0d\x0a \ - \x0d\x0a \ -\x0d\x0a \x0d\x0a\ -\x0d\x0a\ -\x00\x00\x15\xa4\ -I\ -I*\x00B\x08\x00\x00\x80?\xe0@\x08$\x16\x0d\x07\ -\x84BaP\xb8d6\x1d\x0f\x88DbQ8\xa4V\ --\x17\x8cFcQ\xb8\xe4v\x0b\x02\x7f\xc7\xa4R9\ -$\x96M'\x94JeR\xb8\xa4\x82Y/\x98Lf\ -S9\xa4\xd6a.\x9bNgS\xb9\xe4\xf6}#\x9c\ -O\xe8T:%\x16\x8d/\xa0\xd1\xe9T\xbae6\x9d\ -\x1f\x81\xd3\xeaU:\xa5V\x91Q\xabVkU\xba\xe4\ -B\x93]\xb0XlU*\xfd\x8e\xcdg\xb4N\xec\xb6\ -\x9be\xb6\xdd&\xb5\xdb\xeeW;\xa4J\xe3u\xbc^\ -o7{\xd5\xf6\xfdi\xbe_\xf0X:\xde\x07\x09\x87\ -\xc4Sp\xd8\x9cf6\x7f\x8b\xc7drS<\x86O\ --\x97\x93\xe5s\x19\xbc\xe4k5\x9d\xd0hk\xd5\x8d\ -\x16\x97M-\xd2Q\x00:\xbb\xf1\xaf\x5c\x1a}\xecG\ -pQ\x94\x14c\x05\x0e\xc1B;\xa8K\xbe\x0a\xf0\x82\ -\xb8\xf5`\x16|\x15\x9c\x04\xe41\x12\xbc\xb75\xf7?\ -\x94\xd4\xd0\xf8v\xc3?T7 .AJ\x10Q\xbc\ -\x14\x036\x90\xc1\x19pUx\x0f\xcc\xa5K\xfa\x5cx\ -\x0e\x8d\x0b\x9f2\xe9\xd7M\x1f1\xc4\x80\xe1 )\xc1\ -@\x95g\xe7\x93\xcc\x01\x92\x0fI.c+\xafzc\ -\x03&\x0f\x8a\xa44\xc1\x80\xe9\xfb\x07\x91\xa8(\xaa\xbd\ -\x15\xa8(\xe4MC\x07\x12\xa7\x04*\xef\x0a\x8d\x05(\ -\xa3\xfcD\x03\x1d\x11(\xe6\x90\x0fh(\x16\xc4\x1e\xc8\ -)\x0a\x03\xc6\x04i'\x19\x9f*<8\x96F\xe9\x5c\ -@\x9f\x0c\xd1\xe8\x8c\x82\x92h(L\xd1\x1bh(\xdd\ -\x0c\x13E\xc2\x87\x1c\xa5RbS\x1d\xa6q\x10\xfe\x01\ -D\xa7A\x06\x90\x0fM:\x1eD\x032\xe8\xf6@\xcc\ -\x07\xf2s'%\x13\x22O(%\x83|\xd4\x08\x1e\xf3\ -iL\x82\x892\xd2&\xe1\x97\x00D\xec,\x923\xcb\ -\x80\x99L\xcb\x83\xda\x9f\xcd\x09;\xaa3\x85I\x01`\ -\x82\x84\xb3\x92:n9\x00 \xa0KR\x06\xac:\xa5\ -O\xa9-\x02\x91G\xa30\x86\xf2 \xa0m\x14\x93\x9e\ -\x8f\xf8\xa3\x01\x17\x89M*\x92T\xe9\x1d.\x8dPb\ -*@X\xa0\xa0M>\x98\x1f\x0e\x18\x9cL\xd7\x05\xda\ -KT\xa4U\xe2=U\xa2\xb4\xcc~\x82V\x08 \x10\ -\xa99\xa8!X\x82\x96\xef\xf9\xc2\x06Z\x07!\xebi\ -\x9f\xee\x1b`\xd8\x97\xa8(8\xae\x1f\x08(\x9f$\x17\ -H\xf5|\x8e\xdch\xe5\x80\x88>c@\x8e\x7f]\x94\ -=\x8c\xa6\x1c\x00\x15\xe4:\x02\xf7\xa9_0\x103\x15\ -\x83\x1e\x9b\x88(F\xb1\x1f\x17\x90\x04(\x13\x18)r\ -\xcfO\xe9\xf5\xca\x8d\xdc\xe8\x5c\x184\x86\xb0y\xfa`\ -\xd6*a\x18\x05\xe3\x03\xf1\x1f\x8d\x9e\xe8\xf53~\xa0\ -\x97\xfa\xcf\x16\xa0\x81\xfc\x90f\x22\xd8^\x11\x0f(\xb8\ -j\x0dL\x83\xc8)\x92\x82\x83\x0a5\xf4\x00\x0d\x92A\ -.\x94\xe3\xf7\xf2\xdcs\xbf\xe1\xbc\x04\xf5\xa29R3\ -\xa3#\x18h\xdb\xa5\x81\xc7\xce\x9cb\xa0\xa1b\x8e\xe1\ -\x8c\x95\xc12N\xa5\xf9\xeeB\xba\x1a@~\xbc\x1e\x11\ -{\x09\xe6\x87i\x08\xbe\xca\x8bR\xe9\x00\x03A\x96h\ -(\x96\xa6\x14\x12@\xc2\x99\xeb@\x06D\xbc\x16Z\xb0\ -\xa0\xe1\xe5\x886\xce\x8a\xef\xe8\xa5/L\x8f\x88)\x07\ -xc\x00XU\x8d\x91\xf8\xeae\xba\xee\xeb\xc3\x86;\ -\xea\xc4R\x15\xc0\xa2|\xc2%\x1d\xdd!\xed\xd8\x7f\x17\ -\xe8(\x06\xa6\x0c\xb2A8\x9c\xf2\x0c\x13\xfa\x82\x07\x92\ -Ff\xa8o\xb2^\x12\x9e\xbazX\xdb\xa6\xe9\xc6\x92\ -\x0a\x0f\xa9\x87\x0d\x11$\x1f}E\xf9\x9f0\xf2*\x08\ -\x18I\x07\xb75\xa2\xf6i\xe3\xa7A\x91\xa9\x00\xe4\xa6\ -\xb8dN\xac<'\xbdK\x10\xe1\x90:\xb1\x01\xe5\xb4\ -}\x8a\x848|\x93d\xdb\xa2\x00\x00b\x9a\xff\x88\x10\ -\x16(\x9e{La\xdfF\x83\xceY*zF\xdej\ -wt\x8e\xc9\x01\x12T\x9cp\x00\x01\xef\x01\xec\xbc6\ -\xb6c\x8e\x18r`\xa2`G\xbf\x97\xc4O\xd4\x18\xb5\ - \xa1(\xa9\x0d\xd4\x90\x09\x0a\x1b\x0f\x04D\x80\x02\x92\ -\x97>\xdbH\x22\x89)\x87\x0cY\xc0\xb0\x9d\x03\x8aR\ -\x83\x1b)\x08\xa9\x0cT\x90\x0f\x0c\x1a\x99t$\x10 \ -\x15!\xb0\xd5\x81L((\xea\x0d\x92\x00\x05dS\xc5\ -\xa2H\x09\xb0\xc5\x1e\x8a\xf3\xb4T\x87\xb3VEe\x19\ -\xf0\x10\xf5\x067\xc8( *C\x19$\x1b3\x04\xa6\ -F\x11\x05\x07\xa5Ho5g\x22\xec\xa0y>Pj\ -\xe8\x82\x04H\xb8\x92\x22\xf9zS#iD\x15!r\ -\xd5\x82D:(\xcb\xa4D\x12\x00\xeeT\x87\xc2]\x03\ - =|\x0f\xa2\xea\xa6`\xe9\x04O`\x00\x05=C\ -V! X}\x8eE\x14\xd7\x06\xb0>?$\x80\xdd\ -tE5\x81\x048\x16/\x8b\xaa\x83\x08\x04\x82\x19\x94\ -\xe1\xf4\x01e\x00!\x12\x92\x8dd\x94X\x9aC\x8e\x9a\ -\x99\x15$\x14+\x15\x22\x00\x8cM@\xce\xa0\x084\x1e\ -\x11\x09\x85B\xe1\x90\xd8t>!\x11\x00\x19\xa2\x88\x98\ -9\xda%\x19\x8dF\xe1)\xe8\x1ah\xc6\xff\x91G$\ -\x92XD\x89\xff&\x95G\x002\xd0\x01\xa6`\x22~\ -\xcc\xda\x10pl\xaeq\x1aq\x86g\x82D\x0c\xfd\xf5\ -9\xa1P\xe1G\xfa0\x19\xcfInA\xc3\xb4Jt\ -)\xdf-\x00\x8bS5W,\xa2\x9fY\xacVi\xd5\ -(I\x9e\xc0^\x94(k\x96X1\xa6>\x98\xb3Z\ -\xe31C1\xa2\x0e\x97\xb6Q*Ez\xaaeU'\ -\x91\xdc\xe5u\xbb\xe4\x9a\xbd\x0c\xb7'\xe0\xe6\x0b\xfc\xe1\ -\xc4\x0d\xc5\x0a\x91\xb8\xd7\xae\x1e\xd8j\xc9\x03\x1f\x99V\ -\xb53!$\xa9&\xae\xe6xe\xfb3\x1a\xd0hb\ -X\x18]\x18\xfe\x08\xa4\xb9\xd8\xd0q\x8e\x92H\xa5\x8f\ -\x976\x15\x9br\x9a\x0eY\xda\xe9e\xac\xc06\xfcx\ -\x93\xe1>s\xf7\xbd\xdcCG\xc7\x86i\xa1\xc6\xdep\ -q\xf3\xd1d\xc1\xc3\x5c\xa8}H\xd7wKu\xa3\x96\ -\xe3l\x1d%\xdc\x889*C\x8b\xbb\x97\x91\xc6\xf1B\ -\xb9>\xb872#\x925\x0c2\xaf\xc6\x1c\x1c\x19\xee\ -\x84\xca`\xc7H\xf9\x1c\xfd!+r\x0a\x83\x22\xcf|\ -\x02\x83\x9e`\x1c\x16\x1e\x12\xf0q\xa4\xd1=PC\xda\ -\xf7>\x08\xd0\xd1\x0c\x09'\xf46Y \xe0$\x10\x85\ -\x12\xe0|F;\x91q1\xe6\xd29\xc3h\x1c}E\ -\xa4ZP3D\x08I\xf8\x01F\xa2a1\x1c\x17)\ -,(\xf5\xc7\x8f\x14,\x92-\xcd\xa2\x0cP \xe0\x1c\ -d\x84\x1d\x088\xf0\x83\x94\xc8\xf9\xf6\xa25\x0aB\x92\ --\xa0\xe4:\x0e\x0b\xc9\x089\xfa\xc2\xa3\xe5\x22q\x1f\ -;\x93\x0b\xad %P\xc0\xd0,Cg\xf1G\x0fK\ -HQ\xe0\x83\x96\x089q\x1a\x80G\x08\x0b<\x1c\x88\ -A\xf7>\x03\x93P>\x83\x89\x088\xa0\x83\x82\x13r\ -\x12~\xce\xa2\xe4pL\x15\x0a$\xc6\xe5R\x0e<\xca\ -\x9c\xac\x038\xa8\x947\x080\x0bC\xd3\xac9\xf8\xa9\ -\x0b+\xb9X\xaeRM\xddL\xda\xd2\x8a\x22\xddB \ -\xc5:\x0e\x04S\xd5\x92\x88|7(\xfc\xe4\xb5\xd5\x0d\ -\x85t\xd2UJ\xca`4\x86i\x99\xfaW \xe0\xf5\ -gd#G\x12\x0e)\xa3\xe6c\x0f^46\x8b3\ -_,\xcbp(\xa9\x15\x09@\x87d\xdb\xa8A~\x03\ -\xdc\x22\xbb\x84I\x9dm%\xa6\xc8]\x0c=\xaa\xb9\x95\ -Wp\x06^^$B\x0e:[\xd2\xd2\xa4G\x08w\ -\xd0\xec+_\xb2\xe5O\x09@7R\xffv4\x93<\ -5\x0d\x92(8K{7f\xe2\xa47\xae\xe5\xb6\x05\ -\x80\xbfX\x1a\xf9\x82\xb7r\x93V9 \xe3\xdb\xf1\x86\ -\xa9\xecz\x0cC\x5c 9\x1br8\x91\x96.\xb9\xe5\ -\x8bf2\xf7R\xc0\xdaPE \xe2\xd6B\x93\x15\x19\ -0\xebrOU\x9e]\x5c\xe2\xb0\xaa]\x9c\x22h\xa0\ -d\x83\x8d\xc88\xb0\x83\x80\xf6\xf6T\x00\x15PX\x06\ -H\xc1\xc4\xb9\x9b\xa2\xe8\x0b6\xb4\xb2\xe6\x16LT\x0a\ -\xc5\xa7\xd0\xafA\xa5\x01\xfc\xda\xda\x9f\x889\x858\xce\ -\xa5M\x18uh\xae+\xf9\x95\xe8O^\xbd\xb9 \xe3\ -~\xf6\x08\x1e\xfb\xf0p\xa9\x06)C^\x83)\xa85\ -\x0c\x83\x02(\x5c\xe0\x83\x1d\xe89\xc6\x83\x9a\x13\xa9\x9e\ -\xa9\x19\x1a\xb7\x1d\xbc\xa3z\xe5K\xbbs<\xf7?\xd0\ -:\xdc\xdfC\xd2t\xbd2#\xd1\xf4\xfdWW\xd3u\ -=g_\xd8k<\xefc\xdav\xbd_]\xdbw=\ -\xd4'\xd9\xf7}\xf7\x7fn\xf7\x1e\x07\x87\xe2/\x9e\x17\ -\x8b\xe4y4\x7f{\xe5y\xbes3\xe3\xf9\xfe\x97\xa6\ -\x86\xfa>\xa7\xaf\xeb\xfa\xde\xc7\xb7\xe7{^\xe7\xbf\xe2\ -\xfb\xdf\x07\xc7\xdf|_'\xcf\xda\xfc\xdfG\xd7\xd6}\ -_g\xdf\xd2\xfd\xdf\x87\xe7\xcf~_\xa7\xef\x9c~\xdf\ -\xc7\xf7\xe0\xf9\x9f\xe3\xffwo\xea\x00@4\xb4@@\ -\x00\x13\x00\xfe\x00\x04\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\ -\x01\x04\x00\x01\x00\x00\x00`\x00\x00\x00\x01\x01\x04\x00\x01\ -\x00\x00\x00`\x00\x00\x00\x02\x01\x03\x00\x04\x00\x00\x00,\ -\x09\x00\x00\x03\x01\x03\x00\x01\x00\x00\x00\x05\x00\x00\x00\x06\ -\x01\x03\x00\x01\x00\x00\x00\x02\x00\x00\x00\x11\x01\x04\x00\x01\ -\x00\x00\x00\x08\x00\x00\x00\x15\x01\x03\x00\x01\x00\x00\x00\x04\ -\x00\x00\x00\x16\x01\x04\x00\x01\x00\x00\x00`\x00\x00\x00\x17\ -\x01\x04\x00\x01\x00\x00\x009\x08\x00\x00\x1a\x01\x05\x00\x01\ -\x00\x00\x004\x09\x00\x00\x1b\x01\x05\x00\x01\x00\x00\x00<\ -\x09\x00\x00\x1c\x01\x03\x00\x01\x00\x00\x00\x01\x00\x00\x00(\ -\x01\x03\x00\x01\x00\x00\x00\x02\x00\x00\x001\x01\x02\x00\x10\ -\x00\x00\x00D\x09\x00\x00=\x01\x03\x00\x01\x00\x00\x00\x02\ -\x00\x00\x00R\x01\x03\x00\x01\x00\x00\x00\x02\x00\x00\x00S\ -\x01\x03\x00\x04\x00\x00\x00T\x09\x00\x00s\x87\x07\x00H\ -\x0c\x00\x00\x5c\x09\x00\x00\x00\x00\x00\x00\x08\x00\x08\x00\x08\ -\x00\x08\x00\x802\x02\x00\xe8\x03\x00\x00\x802\x02\x00\xe8\ -\x03\x00\x00paint.net 4.0\ -.9\x00\x01\x00\x01\x00\x01\x00\x01\x00\x00\x00\x0cHL\ -ino\x02\x10\x00\x00mntrRGB X\ -YZ \x07\xce\x00\x02\x00\x09\x00\x06\x001\x00\x00a\ -cspMSFT\x00\x00\x00\x00IEC s\ -RGB\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\xf6\xd6\x00\x01\x00\x00\x00\x00\xd3-HP \x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11c\ -prt\x00\x00\x01P\x00\x00\x003desc\x00\ -\x00\x01\x84\x00\x00\x00lwtpt\x00\x00\x01\xf0\x00\ -\x00\x00\x14bkpt\x00\x00\x02\x04\x00\x00\x00\x14r\ -XYZ\x00\x00\x02\x18\x00\x00\x00\x14gXYZ\x00\ -\x00\x02,\x00\x00\x00\x14bXYZ\x00\x00\x02@\x00\ -\x00\x00\x14dmnd\x00\x00\x02T\x00\x00\x00pd\ -mdd\x00\x00\x02\xc4\x00\x00\x00\x88vued\x00\ -\x00\x03L\x00\x00\x00\x86view\x00\x00\x03\xd4\x00\ -\x00\x00$lumi\x00\x00\x03\xf8\x00\x00\x00\x14m\ -eas\x00\x00\x04\x0c\x00\x00\x00$tech\x00\ -\x00\x040\x00\x00\x00\x0crTRC\x00\x00\x04<\x00\ -\x00\x08\x0cgTRC\x00\x00\x04<\x00\x00\x08\x0cb\ -TRC\x00\x00\x04<\x00\x00\x08\x0ctext\x00\ -\x00\x00\x00Copyright (c)\ - 1998 Hewlett-Pa\ -ckard Company\x00\x00d\ -esc\x00\x00\x00\x00\x00\x00\x00\x12sRGB \ -IEC61966-2.1\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x12sRGB IEC\ -61966-2.1\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00XYZ \x00\ -\x00\x00\x00\x00\x00\xf3Q\x00\x01\x00\x00\x00\x01\x16\xccX\ -YZ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00XYZ \x00\x00\x00\x00\x00\x00o\xa2\x00\ -\x008\xf5\x00\x00\x03\x90XYZ \x00\x00\x00\x00\x00\ -\x00b\x99\x00\x00\xb7\x85\x00\x00\x18\xdaXYZ \x00\ -\x00\x00\x00\x00\x00$\xa0\x00\x00\x0f\x84\x00\x00\xb6\xcfd\ -esc\x00\x00\x00\x00\x00\x00\x00\x16IEC h\ -ttp://www.iec.ch\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x16IEC \ -http://www.iec.c\ -h\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\ -esc\x00\x00\x00\x00\x00\x00\x00.IEC 6\ -1966-2.1 Default\ - RGB colour spac\ -e - sRGB\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00.IEC 61966-2.\ -1 Default RGB co\ -lour space - sRG\ -B\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00desc\x00\x00\x00\x00\x00\ -\x00\x00,Reference Vie\ -wing Condition i\ -n IEC61966-2.1\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00,Refere\ -nce Viewing Cond\ -ition in IEC6196\ -6-2.1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00v\ -iew\x00\x00\x00\x00\x00\x13\xa4\xfe\x00\x14_.\x00\ -\x10\xcf\x14\x00\x03\xed\xcc\x00\x04\x13\x0b\x00\x03\x5c\x9e\x00\ -\x00\x00\x01XYZ \x00\x00\x00\x00\x00L\x09V\x00\ -P\x00\x00\x00W\x1f\xe7meas\x00\x00\x00\x00\x00\ -\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x02\x8f\x00\x00\x00\x02sig \x00\ -\x00\x00\x00CRT curv\x00\x00\x00\x00\x00\ -\x00\x04\x00\x00\x00\x00\x05\x00\x0a\x00\x0f\x00\x14\x00\x19\x00\ -\x1e\x00#\x00(\x00-\x002\x007\x00;\x00@\x00\ -E\x00J\x00O\x00T\x00Y\x00^\x00c\x00h\x00\ -m\x00r\x00w\x00|\x00\x81\x00\x86\x00\x8b\x00\x90\x00\ -\x95\x00\x9a\x00\x9f\x00\xa4\x00\xa9\x00\xae\x00\xb2\x00\xb7\x00\ -\xbc\x00\xc1\x00\xc6\x00\xcb\x00\xd0\x00\xd5\x00\xdb\x00\xe0\x00\ -\xe5\x00\xeb\x00\xf0\x00\xf6\x00\xfb\x01\x01\x01\x07\x01\x0d\x01\ -\x13\x01\x19\x01\x1f\x01%\x01+\x012\x018\x01>\x01\ -E\x01L\x01R\x01Y\x01`\x01g\x01n\x01u\x01\ -|\x01\x83\x01\x8b\x01\x92\x01\x9a\x01\xa1\x01\xa9\x01\xb1\x01\ -\xb9\x01\xc1\x01\xc9\x01\xd1\x01\xd9\x01\xe1\x01\xe9\x01\xf2\x01\ -\xfa\x02\x03\x02\x0c\x02\x14\x02\x1d\x02&\x02/\x028\x02\ -A\x02K\x02T\x02]\x02g\x02q\x02z\x02\x84\x02\ -\x8e\x02\x98\x02\xa2\x02\xac\x02\xb6\x02\xc1\x02\xcb\x02\xd5\x02\ -\xe0\x02\xeb\x02\xf5\x03\x00\x03\x0b\x03\x16\x03!\x03-\x03\ -8\x03C\x03O\x03Z\x03f\x03r\x03~\x03\x8a\x03\ -\x96\x03\xa2\x03\xae\x03\xba\x03\xc7\x03\xd3\x03\xe0\x03\xec\x03\ -\xf9\x04\x06\x04\x13\x04 \x04-\x04;\x04H\x04U\x04\ -c\x04q\x04~\x04\x8c\x04\x9a\x04\xa8\x04\xb6\x04\xc4\x04\ -\xd3\x04\xe1\x04\xf0\x04\xfe\x05\x0d\x05\x1c\x05+\x05:\x05\ -I\x05X\x05g\x05w\x05\x86\x05\x96\x05\xa6\x05\xb5\x05\ -\xc5\x05\xd5\x05\xe5\x05\xf6\x06\x06\x06\x16\x06'\x067\x06\ -H\x06Y\x06j\x06{\x06\x8c\x06\x9d\x06\xaf\x06\xc0\x06\ -\xd1\x06\xe3\x06\xf5\x07\x07\x07\x19\x07+\x07=\x07O\x07\ -a\x07t\x07\x86\x07\x99\x07\xac\x07\xbf\x07\xd2\x07\xe5\x07\ -\xf8\x08\x0b\x08\x1f\x082\x08F\x08Z\x08n\x08\x82\x08\ -\x96\x08\xaa\x08\xbe\x08\xd2\x08\xe7\x08\xfb\x09\x10\x09%\x09\ -:\x09O\x09d\x09y\x09\x8f\x09\xa4\x09\xba\x09\xcf\x09\ -\xe5\x09\xfb\x0a\x11\x0a'\x0a=\x0aT\x0aj\x0a\x81\x0a\ -\x98\x0a\xae\x0a\xc5\x0a\xdc\x0a\xf3\x0b\x0b\x0b\x22\x0b9\x0b\ -Q\x0bi\x0b\x80\x0b\x98\x0b\xb0\x0b\xc8\x0b\xe1\x0b\xf9\x0c\ -\x12\x0c*\x0cC\x0c\x5c\x0cu\x0c\x8e\x0c\xa7\x0c\xc0\x0c\ -\xd9\x0c\xf3\x0d\x0d\x0d&\x0d@\x0dZ\x0dt\x0d\x8e\x0d\ -\xa9\x0d\xc3\x0d\xde\x0d\xf8\x0e\x13\x0e.\x0eI\x0ed\x0e\ -\x7f\x0e\x9b\x0e\xb6\x0e\xd2\x0e\xee\x0f\x09\x0f%\x0fA\x0f\ -^\x0fz\x0f\x96\x0f\xb3\x0f\xcf\x0f\xec\x10\x09\x10&\x10\ -C\x10a\x10~\x10\x9b\x10\xb9\x10\xd7\x10\xf5\x11\x13\x11\ -1\x11O\x11m\x11\x8c\x11\xaa\x11\xc9\x11\xe8\x12\x07\x12\ -&\x12E\x12d\x12\x84\x12\xa3\x12\xc3\x12\xe3\x13\x03\x13\ -#\x13C\x13c\x13\x83\x13\xa4\x13\xc5\x13\xe5\x14\x06\x14\ -'\x14I\x14j\x14\x8b\x14\xad\x14\xce\x14\xf0\x15\x12\x15\ -4\x15V\x15x\x15\x9b\x15\xbd\x15\xe0\x16\x03\x16&\x16\ -I\x16l\x16\x8f\x16\xb2\x16\xd6\x16\xfa\x17\x1d\x17A\x17\ -e\x17\x89\x17\xae\x17\xd2\x17\xf7\x18\x1b\x18@\x18e\x18\ -\x8a\x18\xaf\x18\xd5\x18\xfa\x19 \x19E\x19k\x19\x91\x19\ -\xb7\x19\xdd\x1a\x04\x1a*\x1aQ\x1aw\x1a\x9e\x1a\xc5\x1a\ -\xec\x1b\x14\x1b;\x1bc\x1b\x8a\x1b\xb2\x1b\xda\x1c\x02\x1c\ -*\x1cR\x1c{\x1c\xa3\x1c\xcc\x1c\xf5\x1d\x1e\x1dG\x1d\ -p\x1d\x99\x1d\xc3\x1d\xec\x1e\x16\x1e@\x1ej\x1e\x94\x1e\ -\xbe\x1e\xe9\x1f\x13\x1f>\x1fi\x1f\x94\x1f\xbf\x1f\xea \ -\x15 A l \x98 \xc4 \xf0!\x1c!H!\ -u!\xa1!\xce!\xfb\x22'\x22U\x22\x82\x22\xaf\x22\ -\xdd#\x0a#8#f#\x94#\xc2#\xf0$\x1f$\ -M$|$\xab$\xda%\x09%8%h%\x97%\ -\xc7%\xf7&'&W&\x87&\xb7&\xe8'\x18'\ -I'z'\xab'\xdc(\x0d(?(q(\xa2(\ -\xd4)\x06)8)k)\x9d)\xd0*\x02*5*\ -h*\x9b*\xcf+\x02+6+i+\x9d+\xd1,\ -\x05,9,n,\xa2,\xd7-\x0c-A-v-\ -\xab-\xe1.\x16.L.\x82.\xb7.\xee/$/\ -Z/\x91/\xc7/\xfe050l0\xa40\xdb1\ -\x121J1\x821\xba1\xf22*2c2\x9b2\ -\xd43\x0d3F3\x7f3\xb83\xf14+4e4\ -\x9e4\xd85\x135M5\x875\xc25\xfd676\ -r6\xae6\xe97$7`7\x9c7\xd78\x148\ -P8\x8c8\xc89\x059B9\x7f9\xbc9\xf9:\ -6:t:\xb2:\xef;-;k;\xaa;\xe8<\ -'\ - >`>\xa0>\xe0?!?a?\xa2?\xe2@\ -#@d@\xa6@\xe7A)AjA\xacA\xeeB\ -0BrB\xb5B\xf7C:C}C\xc0D\x03D\ -GD\x8aD\xceE\x12EUE\x9aE\xdeF\x22F\ -gF\xabF\xf0G5G{G\xc0H\x05HKH\ -\x91H\xd7I\x1dIcI\xa9I\xf0J7J}J\ -\xc4K\x0cKSK\x9aK\xe2L*LrL\xbaM\ -\x02MJM\x93M\xdcN%NnN\xb7O\x00O\ -IO\x93O\xddP'PqP\xbbQ\x06QPQ\ -\x9bQ\xe6R1R|R\xc7S\x13S_S\xaaS\ -\xf6TBT\x8fT\xdbU(UuU\xc2V\x0fV\ -\x5cV\xa9V\xf7WDW\x92W\xe0X/X}X\ -\xcbY\x1aYiY\xb8Z\x07ZVZ\xa6Z\xf5[\ -E[\x95[\xe5\x5c5\x5c\x86\x5c\xd6]']x]\ -\xc9^\x1a^l^\xbd_\x0f_a_\xb3`\x05`\ -W`\xaa`\xfcaOa\xa2a\xf5bIb\x9cb\ -\xf0cCc\x97c\xebd@d\x94d\xe9e=e\ -\x92e\xe7f=f\x92f\xe8g=g\x93g\xe9h\ -?h\x96h\xeciCi\x9ai\xf1jHj\x9fj\ -\xf7kOk\xa7k\xfflWl\xafm\x08m`m\ -\xb9n\x12nkn\xc4o\x1eoxo\xd1p+p\ -\x86p\xe0q:q\x95q\xf0rKr\xa6s\x01s\ -]s\xb8t\x14tpt\xccu(u\x85u\xe1v\ ->v\x9bv\xf8wVw\xb3x\x11xnx\xccy\ -*y\x89y\xe7zFz\xa5{\x04{c{\xc2|\ -!|\x81|\xe1}A}\xa1~\x01~b~\xc2\x7f\ -#\x7f\x84\x7f\xe5\x80G\x80\xa8\x81\x0a\x81k\x81\xcd\x82\ -0\x82\x92\x82\xf4\x83W\x83\xba\x84\x1d\x84\x80\x84\xe3\x85\ -G\x85\xab\x86\x0e\x86r\x86\xd7\x87;\x87\x9f\x88\x04\x88\ -i\x88\xce\x893\x89\x99\x89\xfe\x8ad\x8a\xca\x8b0\x8b\ -\x96\x8b\xfc\x8cc\x8c\xca\x8d1\x8d\x98\x8d\xff\x8ef\x8e\ -\xce\x8f6\x8f\x9e\x90\x06\x90n\x90\xd6\x91?\x91\xa8\x92\ -\x11\x92z\x92\xe3\x93M\x93\xb6\x94 \x94\x8a\x94\xf4\x95\ -_\x95\xc9\x964\x96\x9f\x97\x0a\x97u\x97\xe0\x98L\x98\ -\xb8\x99$\x99\x90\x99\xfc\x9ah\x9a\xd5\x9bB\x9b\xaf\x9c\ -\x1c\x9c\x89\x9c\xf7\x9dd\x9d\xd2\x9e@\x9e\xae\x9f\x1d\x9f\ -\x8b\x9f\xfa\xa0i\xa0\xd8\xa1G\xa1\xb6\xa2&\xa2\x96\xa3\ -\x06\xa3v\xa3\xe6\xa4V\xa4\xc7\xa58\xa5\xa9\xa6\x1a\xa6\ -\x8b\xa6\xfd\xa7n\xa7\xe0\xa8R\xa8\xc4\xa97\xa9\xa9\xaa\ -\x1c\xaa\x8f\xab\x02\xabu\xab\xe9\xac\x5c\xac\xd0\xadD\xad\ -\xb8\xae-\xae\xa1\xaf\x16\xaf\x8b\xb0\x00\xb0u\xb0\xea\xb1\ -`\xb1\xd6\xb2K\xb2\xc2\xb38\xb3\xae\xb4%\xb4\x9c\xb5\ -\x13\xb5\x8a\xb6\x01\xb6y\xb6\xf0\xb7h\xb7\xe0\xb8Y\xb8\ -\xd1\xb9J\xb9\xc2\xba;\xba\xb5\xbb.\xbb\xa7\xbc!\xbc\ -\x9b\xbd\x15\xbd\x8f\xbe\x0a\xbe\x84\xbe\xff\xbfz\xbf\xf5\xc0\ -p\xc0\xec\xc1g\xc1\xe3\xc2_\xc2\xdb\xc3X\xc3\xd4\xc4\ -Q\xc4\xce\xc5K\xc5\xc8\xc6F\xc6\xc3\xc7A\xc7\xbf\xc8\ -=\xc8\xbc\xc9:\xc9\xb9\xca8\xca\xb7\xcb6\xcb\xb6\xcc\ -5\xcc\xb5\xcd5\xcd\xb5\xce6\xce\xb6\xcf7\xcf\xb8\xd0\ -9\xd0\xba\xd1<\xd1\xbe\xd2?\xd2\xc1\xd3D\xd3\xc6\xd4\ -I\xd4\xcb\xd5N\xd5\xd1\xd6U\xd6\xd8\xd7\x5c\xd7\xe0\xd8\ -d\xd8\xe8\xd9l\xd9\xf1\xdav\xda\xfb\xdb\x80\xdc\x05\xdc\ -\x8a\xdd\x10\xdd\x96\xde\x1c\xde\xa2\xdf)\xdf\xaf\xe06\xe0\ -\xbd\xe1D\xe1\xcc\xe2S\xe2\xdb\xe3c\xe3\xeb\xe4s\xe4\ -\xfc\xe5\x84\xe6\x0d\xe6\x96\xe7\x1f\xe7\xa9\xe82\xe8\xbc\xe9\ -F\xe9\xd0\xea[\xea\xe5\xebp\xeb\xfb\xec\x86\xed\x11\xed\ -\x9c\xee(\xee\xb4\xef@\xef\xcc\xf0X\xf0\xe5\xf1r\xf1\ -\xff\xf2\x8c\xf3\x19\xf3\xa7\xf44\xf4\xc2\xf5P\xf5\xde\xf6\ -m\xf6\xfb\xf7\x8a\xf8\x19\xf8\xa8\xf98\xf9\xc7\xfaW\xfa\ -\xe7\xfbw\xfc\x07\xfc\x98\xfd)\xfd\xba\xfeK\xfe\xdc\xff\ -m\xff\xff\ -\x00\x00\x89\xf8\ -I\ -I*\x00\x08\x00\x00\x00\x18\x00\xfe\x00\x04\x00\x01\x00\x00\ -\x00\x00\x00\x00\x00\x00\x01\x03\x00\x01\x00\x00\x00`\x00\x00\ -\x00\x01\x01\x03\x00\x01\x00\x00\x00`\x00\x00\x00\x02\x01\x03\ -\x00\x04\x00\x00\x00.\x01\x00\x00\x03\x01\x03\x00\x01\x00\x00\ -\x00\x05\x00\x00\x00\x06\x01\x03\x00\x01\x00\x00\x00\x02\x00\x00\ -\x00\x11\x01\x04\x00\x01\x00\x00\x00\xfcS\x00\x00\x12\x01\x03\ -\x00\x01\x00\x00\x00\x01\x00\x00\x00\x15\x01\x03\x00\x01\x00\x00\ -\x00\x04\x00\x00\x00\x16\x01\x03\x00\x01\x00\x00\x00`\x00\x00\ -\x00\x17\x01\x04\x00\x01\x00\x00\x00\xf9\x12\x00\x00\x1a\x01\x05\ -\x00\x01\x00\x00\x006\x01\x00\x00\x1b\x01\x05\x00\x01\x00\x00\ -\x00>\x01\x00\x00\x1c\x01\x03\x00\x01\x00\x00\x00\x01\x00\x00\ -\x00(\x01\x03\x00\x01\x00\x00\x00\x02\x00\x00\x001\x01\x02\ -\x00\x22\x00\x00\x00F\x01\x00\x002\x01\x02\x00\x14\x00\x00\ -\x00h\x01\x00\x00=\x01\x03\x00\x01\x00\x00\x00\x02\x00\x00\ -\x00R\x01\x03\x00\x01\x00\x00\x00\x01\x00\x00\x00\xbc\x02\x01\ -\x00\xf68\x00\x00|\x01\x00\x00I\x86\x01\x00B\x0d\x00\ -\x00r:\x00\x00i\x87\x04\x00\x01\x00\x00\x00\xf8f\x00\ -\x00s\x87\x07\x00H\x0c\x00\x00\xb4G\x00\x00\x5c\x93\x07\ -\x00\xd0\x22\x00\x00$g\x00\x00\x00\x00\x00\x00\x08\x00\x08\ -\x00\x08\x00\x08\x00\x00\xf9\x15\x00\x10'\x00\x00\x00\xf9\x15\ -\x00\x10'\x00\x00Adobe Photo\ -shop CC 2017 (Wi\ -ndows)\x002017:04:0\ -4 11:01:55\x00\ -\x0a\x0a \ - \x0a \x0a \ - paint.net \ -4.0.9\x0a \ - 2017-03-01T11:2\ -0:20-08:00\x0a \ - 2017-04-04T\ -11:01:55-07:00\x0a\ - 2017-\ -04-04T11:01:55-0\ -7:00\x0a \ - imag\ -e/tiff\x0a 3\x0a \ - sRGB IEC\ -61966-2.1\ -\x0a \x0a \ - \x0a \ - adobe:docid\ -:photoshop:6e5b1\ -c59-1960-11e7-ba\ -e7-e6e7a5cd2814<\ -/rdf:li>\x0a \ - \x0a\ - \x0a \ - xmp.iid:db7b2\ -8e8-30e9-e04f-9f\ -78-916e5c5110e6<\ -/xmpMM:InstanceI\ -D>\x0a ad\ -obe:docid:photos\ -hop:bf3203a1-196\ -0-11e7-bae7-e6e7\ -a5cd2814\x0a \ - x\ -mp.did:8f625742-\ -0048-e64f-ab3c-d\ -4b1a5a27a24\x0a \ -\x0a\ - \x0a \ - \x0a \ - created\x0a \ - \ -xmp.iid:8f6257\ -42-0048-e64f-ab3\ -c-d4b1a5a27a24\x0a \ - \ -2017-03-01T11:20\ -:20-08:00\x0a \ - Ad\ -obe Photoshop CC\ - 2017 (Windows)<\ -/stEvt:softwareA\ -gent>\x0a \ - \x0a \ - \x0a\ - \ - \ -saved\x0a \ - xmp.iid\ -:db7b28e8-30e9-e\ -04f-9f78-916e5c5\ -110e6\x0a \ - 2017-04-0\ -4T11:01:55-07:00\ -\x0a \ - \ -Adobe Photo\ -shop CC 2017 (Wi\ -ndows)\x0a \ - <\ -stEvt:changed>/<\ -/stEvt:changed>\x0a\ - <\ -/rdf:li>\x0a \ - \x0a\ - \x0a \ -\x0a \ -\x0a\x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ -\x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a\ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ -\x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a\ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ -\x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a\ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ -\x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a\ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ -\x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a\ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ -\x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a\ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ -\x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a\ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ -\x0a \ - \x0a8BIM\x04%\x00\x00\x00\x00\x00\x10\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x008BI\ -M\x04:\x00\x00\x00\x00\x00\xe5\x00\x00\x00\x10\x00\x00\x00\ -\x01\x00\x00\x00\x00\x00\x0bprintOutp\ -ut\x00\x00\x00\x05\x00\x00\x00\x00PstSbo\ -ol\x01\x00\x00\x00\x00Inteenum\x00\ -\x00\x00\x00Inte\x00\x00\x00\x00Clrm\x00\ -\x00\x00\x0fprintSixteenB\ -itbool\x00\x00\x00\x00\x0bprint\ -erNameTEXT\x00\x00\x00\x01\x00\x00\ -\x00\x00\x00\x0fprintProofSe\ -tupObjc\x00\x00\x00\x0c\x00P\x00r\x00\ -o\x00o\x00f\x00 \x00S\x00e\x00t\x00u\x00\ -p\x00\x00\x00\x00\x00\x0aproofSetu\ -p\x00\x00\x00\x01\x00\x00\x00\x00Bltnenu\ -m\x00\x00\x00\x0cbuiltinProo\ -f\x00\x00\x00\x09proofCMYK\x008\ -BIM\x04;\x00\x00\x00\x00\x02-\x00\x00\x00\x10\x00\ -\x00\x00\x01\x00\x00\x00\x00\x00\x12printOu\ -tputOptions\x00\x00\x00\x17\x00\ -\x00\x00\x00Cptnbool\x00\x00\x00\x00\x00\ -Clbrbool\x00\x00\x00\x00\x00Rgs\ -Mbool\x00\x00\x00\x00\x00CrnCbo\ -ol\x00\x00\x00\x00\x00CntCbool\x00\ -\x00\x00\x00\x00Lblsbool\x00\x00\x00\x00\ -\x00Ngtvbool\x00\x00\x00\x00\x00Em\ -lDbool\x00\x00\x00\x00\x00Intrb\ -ool\x00\x00\x00\x00\x00BckgObjc\ -\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00RGBC\x00\x00\ -\x00\x03\x00\x00\x00\x00Rd doub@o\ -\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00Grn do\ -ub@o\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00Bl\ - doub@o\xe0\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00BrdTUntF#Rlt\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00Bld Un\ -tF#Rlt\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00RsltUntF#Pxl@b\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0avector\ -Databool\x01\x00\x00\x00\x00PgP\ -senum\x00\x00\x00\x00PgPs\x00\x00\x00\ -\x00PgPC\x00\x00\x00\x00LeftUnt\ -F#Rlt\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00Top UntF#Rlt\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00Scl Unt\ -F#Prc@Y\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x10cropWhenPrintin\ -gbool\x00\x00\x00\x00\x0ecropRe\ -ctBottomlong\x00\x00\x00\x00\ -\x00\x00\x00\x0ccropRectLeft\ -long\x00\x00\x00\x00\x00\x00\x00\x0dcrop\ -RectRightlong\x00\x00\x00\ -\x00\x00\x00\x00\x0bcropRectTop\ -long\x00\x00\x00\x00\x008BIM\x03\xed\x00\ -\x00\x00\x00\x00\x10\x00\x90\x00\x00\x00\x01\x00\x01\x00\x90\x00\ -\x00\x00\x01\x00\x018BIM\x04&\x00\x00\x00\x00\x00\ -\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00?\x80\x00\x008\ -BIM\x03\xee\x00\x00\x00\x00\x00\x0d\x0cTran\ -sparency\x008BIM\x04\x15\x00\ -\x00\x00\x00\x00\x1e\x00\x00\x00\x0d\x00T\x00r\x00a\x00\ -n\x00s\x00p\x00a\x00r\x00e\x00n\x00c\x00\ -y\x00\x008BIM\x045\x00\x00\x00\x00\x00\x11\x00\ -\x00\x00\x01\x00\x00\xff\xff\x00\x00\x00\x00\x00\x00\x00d\x01\ -\x008BIM\x04\x1d\x00\x00\x00\x00\x00\x04\x00\x00\x00\ -\x008BIM\x04\x0d\x00\x00\x00\x00\x00\x04\x00\x00\x00\ -\x1e8BIM\x04\x19\x00\x00\x00\x00\x00\x04\x00\x00\x00\ -\x1e8BIM\x03\xf3\x00\x00\x00\x00\x00\x09\x00\x00\x00\ -\x00\x00\x00\x00\x00\x01\x008BIM'\x10\x00\x00\x00\ -\x00\x00\x0a\x00\x01\x00\x00\x00\x00\x00\x00\x00\x018BI\ -M\x03\xf5\x00\x00\x00\x00\x00H\x00/ff\x00\x01\x00\ -lff\x00\x06\x00\x00\x00\x00\x00\x01\x00/ff\x00\ -\x01\x00\xa1\x99\x9a\x00\x06\x00\x00\x00\x00\x00\x01\x002\x00\ -\x00\x00\x01\x00Z\x00\x00\x00\x06\x00\x00\x00\x00\x00\x01\x00\ -5\x00\x00\x00\x01\x00-\x00\x00\x00\x06\x00\x00\x00\x00\x00\ -\x018BIM\x03\xf8\x00\x00\x00\x00\x00p\x00\x00\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\x03\xe8\x00\x00\x00\x00\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\x03\xe8\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x03\xe8\x00\ -\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\x03\xe8\x00\x008BI\ -M\x04\x00\x00\x00\x00\x00\x00\x02\x00\x018BIM\x04\ -\x02\x00\x00\x00\x00\x00\x04\x00\x00\x00\x008BIM\x04\ -0\x00\x00\x00\x00\x00\x02\x01\x018BIM\x04-\x00\ -\x00\x00\x00\x00\x06\x00\x01\x00\x00\x00\x048BIM\x04\ -\x08\x00\x00\x00\x00\x00\x10\x00\x00\x00\x01\x00\x00\x02@\x00\ -\x00\x02@\x00\x00\x00\x008BIM\x04\x1e\x00\x00\x00\ -\x00\x00\x04\x00\x00\x00\x008BIM\x04\x1a\x00\x00\x00\ -\x00\x035\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00`\x00\x00\x00`\x00\x00\x00\x00\x00\x00\x00\x01\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00`\x00\ -\x00\x00`\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x01\x00\x00\x00\x00\ -\x00\x00null\x00\x00\x00\x02\x00\x00\x00\x06bo\ -undsObjc\x00\x00\x00\x01\x00\x00\x00\x00\ -\x00\x00Rct1\x00\x00\x00\x04\x00\x00\x00\x00To\ -p long\x00\x00\x00\x00\x00\x00\x00\x00Le\ -ftlong\x00\x00\x00\x00\x00\x00\x00\x00Bt\ -omlong\x00\x00\x00`\x00\x00\x00\x00Rg\ -htlong\x00\x00\x00`\x00\x00\x00\x06sl\ -icesVlLs\x00\x00\x00\x01Objc\ -\x00\x00\x00\x01\x00\x00\x00\x00\x00\x05slice\x00\ -\x00\x00\x12\x00\x00\x00\x07sliceIDlo\ -ng\x00\x00\x00\x00\x00\x00\x00\x07groupI\ -Dlong\x00\x00\x00\x00\x00\x00\x00\x06ori\ -ginenum\x00\x00\x00\x0cESlic\ -eOrigin\x00\x00\x00\x0dautoG\ -enerated\x00\x00\x00\x00Type\ -enum\x00\x00\x00\x0aESliceTy\ -pe\x00\x00\x00\x00Img \x00\x00\x00\x06bo\ -undsObjc\x00\x00\x00\x01\x00\x00\x00\x00\ -\x00\x00Rct1\x00\x00\x00\x04\x00\x00\x00\x00To\ -p long\x00\x00\x00\x00\x00\x00\x00\x00Le\ -ftlong\x00\x00\x00\x00\x00\x00\x00\x00Bt\ -omlong\x00\x00\x00`\x00\x00\x00\x00Rg\ -htlong\x00\x00\x00`\x00\x00\x00\x03ur\ -lTEXT\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00n\ -ullTEXT\x00\x00\x00\x01\x00\x00\x00\x00\x00\ -\x00MsgeTEXT\x00\x00\x00\x01\x00\x00\x00\ -\x00\x00\x06altTagTEXT\x00\x00\x00\ -\x01\x00\x00\x00\x00\x00\x0ecellTextI\ -sHTMLbool\x01\x00\x00\x00\x08ce\ -llTextTEXT\x00\x00\x00\x01\x00\x00\ -\x00\x00\x00\x09horzAlignenu\ -m\x00\x00\x00\x0fESliceHorzA\ -lign\x00\x00\x00\x07default\x00\ -\x00\x00\x09vertAlignenum\ -\x00\x00\x00\x0fESliceVertAl\ -ign\x00\x00\x00\x07default\x00\x00\ -\x00\x0bbgColorTypeenu\ -m\x00\x00\x00\x11ESliceBGCol\ -orType\x00\x00\x00\x00None\x00\x00\ -\x00\x09topOutsetlong\x00\ -\x00\x00\x00\x00\x00\x00\x0aleftOutse\ -tlong\x00\x00\x00\x00\x00\x00\x00\x0cbot\ -tomOutsetlong\x00\x00\x00\ -\x00\x00\x00\x00\x0brightOutset\ -long\x00\x00\x00\x00\x008BIM\x04(\x00\ -\x00\x00\x00\x00\x0c\x00\x00\x00\x02?\xf0\x00\x00\x00\x00\x00\ -\x008BIM\x04\x14\x00\x00\x00\x00\x00\x04\x00\x00\x00\ -\x048BIM\x04\x0c\x00\x00\x00\x00\x03\xeb\x00\x00\x00\ -\x01\x00\x00\x000\x00\x00\x000\x00\x00\x00\x90\x00\x00\x1b\ -\x00\x00\x00\x03\xcf\x00\x18\x00\x01\xff\xd8\xff\xed\x00\x0cA\ -dobe_CM\x00\x01\xff\xee\x00\x0eAdo\ -be\x00d\x80\x00\x00\x00\x01\xff\xdb\x00\x84\x00\x0c\x08\ -\x08\x08\x09\x08\x0c\x09\x09\x0c\x11\x0b\x0a\x0b\x11\x15\x0f\x0c\ -\x0c\x0f\x15\x18\x13\x13\x15\x13\x13\x18\x11\x0c\x0c\x0c\x0c\x0c\ -\x0c\x11\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\ -\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x01\x0d\ -\x0b\x0b\x0d\x0e\x0d\x10\x0e\x0e\x10\x14\x0e\x0e\x0e\x14\x14\x0e\ -\x0e\x0e\x0e\x14\x11\x0c\x0c\x0c\x0c\x0c\x11\x11\x0c\x0c\x0c\x0c\ -\x0c\x0c\x11\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\ -\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\xff\ -\xc0\x00\x11\x08\x000\x000\x03\x01\x22\x00\x02\x11\x01\x03\ -\x11\x01\xff\xdd\x00\x04\x00\x03\xff\xc4\x01?\x00\x00\x01\x05\ -\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x03\x00\x01\ -\x02\x04\x05\x06\x07\x08\x09\x0a\x0b\x01\x00\x01\x05\x01\x01\x01\ -\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x02\x03\x04\x05\ -\x06\x07\x08\x09\x0a\x0b\x10\x00\x01\x04\x01\x03\x02\x04\x02\x05\ -\x07\x06\x08\x05\x03\x0c3\x01\x00\x02\x11\x03\x04!\x121\ -\x05AQa\x13\x22q\x812\x06\x14\x91\xa1\xb1B#\ -$\x15R\xc1b34r\x82\xd1C\x07%\x92S\xf0\ -\xe1\xf1cs5\x16\xa2\xb2\x83&D\x93TdE\xc2\ -\xa3t6\x17\xd2U\xe2e\xf2\xb3\x84\xc3\xd3u\xe3\xf3\ -F'\x94\xa4\x85\xb4\x95\xc4\xd4\xe4\xf4\xa5\xb5\xc5\xd5\xe5\ -\xf5Vfv\x86\x96\xa6\xb6\xc6\xd6\xe6\xf67GWg\ -w\x87\x97\xa7\xb7\xc7\xd7\xe7\xf7\x11\x00\x02\x02\x01\x02\x04\ -\x04\x03\x04\x05\x06\x07\x07\x06\x055\x01\x00\x02\x11\x03!\ -1\x12\x04AQaq\x22\x13\x052\x81\x91\x14\xa1\xb1\ -B#\xc1R\xd1\xf03$b\xe1r\x82\x92CS\x15\ -cs4\xf1%\x06\x16\xa2\xb2\x83\x07&5\xc2\xd2D\ -\x93T\xa3\x17dEU6te\xe2\xf2\xb3\x84\xc3\xd3\ -u\xe3\xf3F\x94\xa4\x85\xb4\x95\xc4\xd4\xe4\xf4\xa5\xb5\xc5\ -\xd5\xe5\xf5Vfv\x86\x96\xa6\xb6\xc6\xd6\xe6\xf6'7\ -GWgw\x87\x97\xa7\xb7\xc7\xff\xda\x00\x0c\x03\x01\x00\ -\x02\x11\x03\x11\x00?\x00\xf4<\xdc\xcc\x96d\x9a\xa9;\ -@\x80\x00\x00\x92O\xc6P\xfd~\xab\xe0\xff\x00\xfbl\ -\x7f\xe4R\xc9\xff\x00\x95\x1b\xfdz\xff\x00\xef\xabU\xce\ -\x0dis\xb4\x00I>A%9^\xbfU\xf0\x7f\xfd\ -\xb6?\xf2)z\xfdW\xc1\xff\x00\xf6\xd8\xff\x00\xc8\xa2\ -UU\xf9\xe0\xdde\x8e\xaa\x92}\x95\xb7\xc0x\xa7{\ -o\xe9\xeem\x82\xc3n9 =\xae\xd4\x89\xee\x12R\ -/_\xaa\xf8?\xfc\xc1\xff\x00\x91D\xc0\xcc\xc8\xb3#\ -\xd2\xb4\xee\x04\x1e@\x04\x11\xfdU\xa4\xb20\x7f\xe5\x03\ -\xff\x00\x5c\xfc\xa9)\xff\xd0\xef\xf2\x7f\xe5F\xff\x00^\ -\xbf\xfb\xea\xb9\x9f\x7f\xa7W\xa6\x1a\x5c\xfb\x81c@\xf3\ -\x11\xfcU<\x9f\xf9Q\xbf\xd7\xaf\xfe\xfa\xacu\x0f\xe9\ -\x18\x9f\xf1\x9f\xc5\x89)\x1e>NU\x14\xb6\xaf\xb2\xbd\ -\xdbg\xdd\xa8\xe4\xcf\xee\xa8\xe5]\x95\x93I\xa8\xe2\xbd\ -\x92A\x9dO\x1f\xd9\x0a\xdfP\xb6\xea\xb1\xf7\xd3\xa1\x90\ -\x1c\xee`x\xa9aYu\x98\xed}\xdfH\xcc\x1e$\ -~k\x92R\xd8y\x02\xfa\xa7ik\x98v\xb8\x1f\x10\ -\xa8`\xff\x00\xca\x07\xfe\xb9\xf9U\x9e\x97\xf4.\xff\x00\ -\x8d*\xb6\x0f\xfc\xa0\x7f\xeb\x9f\x95%?\xff\xd1\xef\xf2\ -\x7f\xe5F\xff\x00^\xbf\xfb\xea?R;,\xc6\xb4\x83\ -\xb1\x8f\x97\x11\xf1i\xff\x00\xbe\xa8f\xe1d\xbf$\xdb\ -P\x90b\x0c\xc1\x04!\xfd\x9b\xaa~\xf3\xff\x00\xed\xcf\ -\xfc\xc9%'\xb7\xa8\xe1[[\xabxyk\x84\x1d\x08\ -N\xce\xa7\x86\xc65\x8d\x0f\x0dh\x00\x0d\xa7\x80\xab\xfd\ -\x9b\xaa~\xf3\xff\x00\xed\xcf\xf6\xa5\xf6n\xa9\xfb\xcf\xff\ -\x00\xb7?\xda\x92\x9b\x1d(\x1fJ\xd7A\x0du\x84\xb4\ -\x9e\xe1V\xc1\xff\x00\x94\x0f\xc6\xcf\xca\x9f\xec\xddS\xf7\ -\x9f\xff\x00n\x7f\xe6H\xb88Y\x15\xdf\xea\xda\x03@\ -\x04s$\x92\x92\x9f\xff\xd9\x008BIM\x04!\x00\ -\x00\x00\x00\x00]\x00\x00\x00\x01\x01\x00\x00\x00\x0f\x00A\ -\x00d\x00o\x00b\x00e\x00 \x00P\x00h\x00o\ -\x00t\x00o\x00s\x00h\x00o\x00p\x00\x00\x00\x17\ -\x00A\x00d\x00o\x00b\x00e\x00 \x00P\x00h\ -\x00o\x00t\x00o\x00s\x00h\x00o\x00p\x00 \ -\x00C\x00C\x00 \x002\x000\x001\x007\x00\x00\ -\x00\x01\x00\x00\x00\x0cHLino\x02\x10\x00\x00m\ -ntrRGB XYZ \x07\xce\x00\x02\x00\ -\x09\x00\x06\x001\x00\x00acspMSFT\x00\ -\x00\x00\x00IEC sRGB\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf6\xd6\x00\x01\x00\x00\x00\ -\x00\xd3-HP \x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x11cprt\x00\x00\x01P\x00\ -\x00\x003desc\x00\x00\x01\x84\x00\x00\x00lw\ -tpt\x00\x00\x01\xf0\x00\x00\x00\x14bkpt\x00\ -\x00\x02\x04\x00\x00\x00\x14rXYZ\x00\x00\x02\x18\x00\ -\x00\x00\x14gXYZ\x00\x00\x02,\x00\x00\x00\x14b\ -XYZ\x00\x00\x02@\x00\x00\x00\x14dmnd\x00\ -\x00\x02T\x00\x00\x00pdmdd\x00\x00\x02\xc4\x00\ -\x00\x00\x88vued\x00\x00\x03L\x00\x00\x00\x86v\ -iew\x00\x00\x03\xd4\x00\x00\x00$lumi\x00\ -\x00\x03\xf8\x00\x00\x00\x14meas\x00\x00\x04\x0c\x00\ -\x00\x00$tech\x00\x00\x040\x00\x00\x00\x0cr\ -TRC\x00\x00\x04<\x00\x00\x08\x0cgTRC\x00\ -\x00\x04<\x00\x00\x08\x0cbTRC\x00\x00\x04<\x00\ -\x00\x08\x0ctext\x00\x00\x00\x00Copyr\ -ight (c) 1998 He\ -wlett-Packard Co\ -mpany\x00\x00desc\x00\x00\x00\x00\x00\ -\x00\x00\x12sRGB IEC61966\ --2.1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x12\ -sRGB IEC61966-2.\ -1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00XYZ \x00\x00\x00\x00\x00\x00\xf3Q\x00\ -\x01\x00\x00\x00\x01\x16\xccXYZ \x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00XYZ \x00\ -\x00\x00\x00\x00\x00o\xa2\x00\x008\xf5\x00\x00\x03\x90X\ -YZ \x00\x00\x00\x00\x00\x00b\x99\x00\x00\xb7\x85\x00\ -\x00\x18\xdaXYZ \x00\x00\x00\x00\x00\x00$\xa0\x00\ -\x00\x0f\x84\x00\x00\xb6\xcfdesc\x00\x00\x00\x00\x00\ -\x00\x00\x16IEC http://ww\ -w.iec.ch\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x16IEC http://w\ -ww.iec.ch\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00desc\x00\x00\x00\x00\x00\ -\x00\x00.IEC 61966-2.1\ - Default RGB col\ -our space - sRGB\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00.IEC \ -61966-2.1 Defaul\ -t RGB colour spa\ -ce - sRGB\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\ -esc\x00\x00\x00\x00\x00\x00\x00,Refer\ -ence Viewing Con\ -dition in IEC619\ -66-2.1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00,Reference View\ -ing Condition in\ - IEC61966-2.1\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00view\x00\x00\x00\x00\x00\ -\x13\xa4\xfe\x00\x14_.\x00\x10\xcf\x14\x00\x03\xed\xcc\x00\ -\x04\x13\x0b\x00\x03\x5c\x9e\x00\x00\x00\x01XYZ \x00\ -\x00\x00\x00\x00L\x09V\x00P\x00\x00\x00W\x1f\xe7m\ -eas\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x8f\x00\ -\x00\x00\x02sig \x00\x00\x00\x00CRT c\ -urv\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x05\x00\ -\x0a\x00\x0f\x00\x14\x00\x19\x00\x1e\x00#\x00(\x00-\x00\ -2\x007\x00;\x00@\x00E\x00J\x00O\x00T\x00\ -Y\x00^\x00c\x00h\x00m\x00r\x00w\x00|\x00\ -\x81\x00\x86\x00\x8b\x00\x90\x00\x95\x00\x9a\x00\x9f\x00\xa4\x00\ -\xa9\x00\xae\x00\xb2\x00\xb7\x00\xbc\x00\xc1\x00\xc6\x00\xcb\x00\ -\xd0\x00\xd5\x00\xdb\x00\xe0\x00\xe5\x00\xeb\x00\xf0\x00\xf6\x00\ -\xfb\x01\x01\x01\x07\x01\x0d\x01\x13\x01\x19\x01\x1f\x01%\x01\ -+\x012\x018\x01>\x01E\x01L\x01R\x01Y\x01\ -`\x01g\x01n\x01u\x01|\x01\x83\x01\x8b\x01\x92\x01\ -\x9a\x01\xa1\x01\xa9\x01\xb1\x01\xb9\x01\xc1\x01\xc9\x01\xd1\x01\ -\xd9\x01\xe1\x01\xe9\x01\xf2\x01\xfa\x02\x03\x02\x0c\x02\x14\x02\ -\x1d\x02&\x02/\x028\x02A\x02K\x02T\x02]\x02\ -g\x02q\x02z\x02\x84\x02\x8e\x02\x98\x02\xa2\x02\xac\x02\ -\xb6\x02\xc1\x02\xcb\x02\xd5\x02\xe0\x02\xeb\x02\xf5\x03\x00\x03\ -\x0b\x03\x16\x03!\x03-\x038\x03C\x03O\x03Z\x03\ -f\x03r\x03~\x03\x8a\x03\x96\x03\xa2\x03\xae\x03\xba\x03\ -\xc7\x03\xd3\x03\xe0\x03\xec\x03\xf9\x04\x06\x04\x13\x04 \x04\ --\x04;\x04H\x04U\x04c\x04q\x04~\x04\x8c\x04\ -\x9a\x04\xa8\x04\xb6\x04\xc4\x04\xd3\x04\xe1\x04\xf0\x04\xfe\x05\ -\x0d\x05\x1c\x05+\x05:\x05I\x05X\x05g\x05w\x05\ -\x86\x05\x96\x05\xa6\x05\xb5\x05\xc5\x05\xd5\x05\xe5\x05\xf6\x06\ -\x06\x06\x16\x06'\x067\x06H\x06Y\x06j\x06{\x06\ -\x8c\x06\x9d\x06\xaf\x06\xc0\x06\xd1\x06\xe3\x06\xf5\x07\x07\x07\ -\x19\x07+\x07=\x07O\x07a\x07t\x07\x86\x07\x99\x07\ -\xac\x07\xbf\x07\xd2\x07\xe5\x07\xf8\x08\x0b\x08\x1f\x082\x08\ -F\x08Z\x08n\x08\x82\x08\x96\x08\xaa\x08\xbe\x08\xd2\x08\ -\xe7\x08\xfb\x09\x10\x09%\x09:\x09O\x09d\x09y\x09\ -\x8f\x09\xa4\x09\xba\x09\xcf\x09\xe5\x09\xfb\x0a\x11\x0a'\x0a\ -=\x0aT\x0aj\x0a\x81\x0a\x98\x0a\xae\x0a\xc5\x0a\xdc\x0a\ -\xf3\x0b\x0b\x0b\x22\x0b9\x0bQ\x0bi\x0b\x80\x0b\x98\x0b\ -\xb0\x0b\xc8\x0b\xe1\x0b\xf9\x0c\x12\x0c*\x0cC\x0c\x5c\x0c\ -u\x0c\x8e\x0c\xa7\x0c\xc0\x0c\xd9\x0c\xf3\x0d\x0d\x0d&\x0d\ -@\x0dZ\x0dt\x0d\x8e\x0d\xa9\x0d\xc3\x0d\xde\x0d\xf8\x0e\ -\x13\x0e.\x0eI\x0ed\x0e\x7f\x0e\x9b\x0e\xb6\x0e\xd2\x0e\ -\xee\x0f\x09\x0f%\x0fA\x0f^\x0fz\x0f\x96\x0f\xb3\x0f\ -\xcf\x0f\xec\x10\x09\x10&\x10C\x10a\x10~\x10\x9b\x10\ -\xb9\x10\xd7\x10\xf5\x11\x13\x111\x11O\x11m\x11\x8c\x11\ -\xaa\x11\xc9\x11\xe8\x12\x07\x12&\x12E\x12d\x12\x84\x12\ -\xa3\x12\xc3\x12\xe3\x13\x03\x13#\x13C\x13c\x13\x83\x13\ -\xa4\x13\xc5\x13\xe5\x14\x06\x14'\x14I\x14j\x14\x8b\x14\ -\xad\x14\xce\x14\xf0\x15\x12\x154\x15V\x15x\x15\x9b\x15\ -\xbd\x15\xe0\x16\x03\x16&\x16I\x16l\x16\x8f\x16\xb2\x16\ -\xd6\x16\xfa\x17\x1d\x17A\x17e\x17\x89\x17\xae\x17\xd2\x17\ -\xf7\x18\x1b\x18@\x18e\x18\x8a\x18\xaf\x18\xd5\x18\xfa\x19\ - \x19E\x19k\x19\x91\x19\xb7\x19\xdd\x1a\x04\x1a*\x1a\ -Q\x1aw\x1a\x9e\x1a\xc5\x1a\xec\x1b\x14\x1b;\x1bc\x1b\ -\x8a\x1b\xb2\x1b\xda\x1c\x02\x1c*\x1cR\x1c{\x1c\xa3\x1c\ -\xcc\x1c\xf5\x1d\x1e\x1dG\x1dp\x1d\x99\x1d\xc3\x1d\xec\x1e\ -\x16\x1e@\x1ej\x1e\x94\x1e\xbe\x1e\xe9\x1f\x13\x1f>\x1f\ -i\x1f\x94\x1f\xbf\x1f\xea \x15 A l \x98 \ -\xc4 \xf0!\x1c!H!u!\xa1!\xce!\xfb\x22\ -'\x22U\x22\x82\x22\xaf\x22\xdd#\x0a#8#f#\ -\x94#\xc2#\xf0$\x1f$M$|$\xab$\xda%\ -\x09%8%h%\x97%\xc7%\xf7&'&W&\ -\x87&\xb7&\xe8'\x18'I'z'\xab'\xdc(\ -\x0d(?(q(\xa2(\xd4)\x06)8)k)\ -\x9d)\xd0*\x02*5*h*\x9b*\xcf+\x02+\ -6+i+\x9d+\xd1,\x05,9,n,\xa2,\ -\xd7-\x0c-A-v-\xab-\xe1.\x16.L.\ -\x82.\xb7.\xee/$/Z/\x91/\xc7/\xfe0\ -50l0\xa40\xdb1\x121J1\x821\xba1\ -\xf22*2c2\x9b2\xd43\x0d3F3\x7f3\ -\xb83\xf14+4e4\x9e4\xd85\x135M5\ -\x875\xc25\xfd676r6\xae6\xe97$7\ -`7\x9c7\xd78\x148P8\x8c8\xc89\x059\ -B9\x7f9\xbc9\xf9:6:t:\xb2:\xef;\ --;k;\xaa;\xe8<' >`>\xa0>\xe0?\ -!?a?\xa2?\xe2@#@d@\xa6@\xe7A\ -)AjA\xacA\xeeB0BrB\xb5B\xf7C\ -:C}C\xc0D\x03DGD\x8aD\xceE\x12E\ -UE\x9aE\xdeF\x22FgF\xabF\xf0G5G\ -{G\xc0H\x05HKH\x91H\xd7I\x1dIcI\ -\xa9I\xf0J7J}J\xc4K\x0cKSK\x9aK\ -\xe2L*LrL\xbaM\x02MJM\x93M\xdcN\ -%NnN\xb7O\x00OIO\x93O\xddP'P\ -qP\xbbQ\x06QPQ\x9bQ\xe6R1R|R\ -\xc7S\x13S_S\xaaS\xf6TBT\x8fT\xdbU\ -(UuU\xc2V\x0fV\x5cV\xa9V\xf7WDW\ -\x92W\xe0X/X}X\xcbY\x1aYiY\xb8Z\ -\x07ZVZ\xa6Z\xf5[E[\x95[\xe5\x5c5\x5c\ -\x86\x5c\xd6]']x]\xc9^\x1a^l^\xbd_\ -\x0f_a_\xb3`\x05`W`\xaa`\xfcaOa\ -\xa2a\xf5bIb\x9cb\xf0cCc\x97c\xebd\ -@d\x94d\xe9e=e\x92e\xe7f=f\x92f\ -\xe8g=g\x93g\xe9h?h\x96h\xeciCi\ -\x9ai\xf1jHj\x9fj\xf7kOk\xa7k\xffl\ -Wl\xafm\x08m`m\xb9n\x12nkn\xc4o\ -\x1eoxo\xd1p+p\x86p\xe0q:q\x95q\ -\xf0rKr\xa6s\x01s]s\xb8t\x14tpt\ -\xccu(u\x85u\xe1v>v\x9bv\xf8wVw\ -\xb3x\x11xnx\xccy*y\x89y\xe7zFz\ -\xa5{\x04{c{\xc2|!|\x81|\xe1}A}\ -\xa1~\x01~b~\xc2\x7f#\x7f\x84\x7f\xe5\x80G\x80\ -\xa8\x81\x0a\x81k\x81\xcd\x820\x82\x92\x82\xf4\x83W\x83\ -\xba\x84\x1d\x84\x80\x84\xe3\x85G\x85\xab\x86\x0e\x86r\x86\ -\xd7\x87;\x87\x9f\x88\x04\x88i\x88\xce\x893\x89\x99\x89\ -\xfe\x8ad\x8a\xca\x8b0\x8b\x96\x8b\xfc\x8cc\x8c\xca\x8d\ -1\x8d\x98\x8d\xff\x8ef\x8e\xce\x8f6\x8f\x9e\x90\x06\x90\ -n\x90\xd6\x91?\x91\xa8\x92\x11\x92z\x92\xe3\x93M\x93\ -\xb6\x94 \x94\x8a\x94\xf4\x95_\x95\xc9\x964\x96\x9f\x97\ -\x0a\x97u\x97\xe0\x98L\x98\xb8\x99$\x99\x90\x99\xfc\x9a\ -h\x9a\xd5\x9bB\x9b\xaf\x9c\x1c\x9c\x89\x9c\xf7\x9dd\x9d\ -\xd2\x9e@\x9e\xae\x9f\x1d\x9f\x8b\x9f\xfa\xa0i\xa0\xd8\xa1\ -G\xa1\xb6\xa2&\xa2\x96\xa3\x06\xa3v\xa3\xe6\xa4V\xa4\ -\xc7\xa58\xa5\xa9\xa6\x1a\xa6\x8b\xa6\xfd\xa7n\xa7\xe0\xa8\ -R\xa8\xc4\xa97\xa9\xa9\xaa\x1c\xaa\x8f\xab\x02\xabu\xab\ -\xe9\xac\x5c\xac\xd0\xadD\xad\xb8\xae-\xae\xa1\xaf\x16\xaf\ -\x8b\xb0\x00\xb0u\xb0\xea\xb1`\xb1\xd6\xb2K\xb2\xc2\xb3\ -8\xb3\xae\xb4%\xb4\x9c\xb5\x13\xb5\x8a\xb6\x01\xb6y\xb6\ -\xf0\xb7h\xb7\xe0\xb8Y\xb8\xd1\xb9J\xb9\xc2\xba;\xba\ -\xb5\xbb.\xbb\xa7\xbc!\xbc\x9b\xbd\x15\xbd\x8f\xbe\x0a\xbe\ -\x84\xbe\xff\xbfz\xbf\xf5\xc0p\xc0\xec\xc1g\xc1\xe3\xc2\ -_\xc2\xdb\xc3X\xc3\xd4\xc4Q\xc4\xce\xc5K\xc5\xc8\xc6\ -F\xc6\xc3\xc7A\xc7\xbf\xc8=\xc8\xbc\xc9:\xc9\xb9\xca\ -8\xca\xb7\xcb6\xcb\xb6\xcc5\xcc\xb5\xcd5\xcd\xb5\xce\ -6\xce\xb6\xcf7\xcf\xb8\xd09\xd0\xba\xd1<\xd1\xbe\xd2\ -?\xd2\xc1\xd3D\xd3\xc6\xd4I\xd4\xcb\xd5N\xd5\xd1\xd6\ -U\xd6\xd8\xd7\x5c\xd7\xe0\xd8d\xd8\xe8\xd9l\xd9\xf1\xda\ -v\xda\xfb\xdb\x80\xdc\x05\xdc\x8a\xdd\x10\xdd\x96\xde\x1c\xde\ -\xa2\xdf)\xdf\xaf\xe06\xe0\xbd\xe1D\xe1\xcc\xe2S\xe2\ -\xdb\xe3c\xe3\xeb\xe4s\xe4\xfc\xe5\x84\xe6\x0d\xe6\x96\xe7\ -\x1f\xe7\xa9\xe82\xe8\xbc\xe9F\xe9\xd0\xea[\xea\xe5\xeb\ -p\xeb\xfb\xec\x86\xed\x11\xed\x9c\xee(\xee\xb4\xef@\xef\ -\xcc\xf0X\xf0\xe5\xf1r\xf1\xff\xf2\x8c\xf3\x19\xf3\xa7\xf4\ -4\xf4\xc2\xf5P\xf5\xde\xf6m\xf6\xfb\xf7\x8a\xf8\x19\xf8\ -\xa8\xf98\xf9\xc7\xfaW\xfa\xe7\xfbw\xfc\x07\xfc\x98\xfd\ -)\xfd\xba\xfeK\xfe\xdc\xffm\xff\xff\x80\x00 P8\ -$\x16\x0d\x07\x84BaP\xb8d6\x1d\x0f\x88Db\ -Q8\xa4V-\x17\x8cFcQ\xb8\xe4v=\x1f\x90\ -HdR9$\x96M'\x94JeR\xb9d\xb6]\ -/\x98A\x00\x930(*l\x0c\x9c\x03\x02\x13`P\ -0\x07?\x02?\xe8O\xe8X\x06 \x01\xa4\x00hO\ -\xfa$\x1a\x93H\x82R\xdf\xf0J}J\x06\xff\xa4\x80\ -\xa9t\xd0\x05\x1a\x07U\xa5\xd5\xeb\xf4\xfa\x8d\x86\x05S\ -\x81S\xe9VhK\xfc\x05o\x01\xd5\xaa\xf6\xca\x8d~\ -\x0fh\xb4\xd2\x00P\x8a\x95\x92\xefK\xb0P\xacW\x9a\ -M\xca\x9dI\xbe]05\xca\xf0\x02\x98\xfe\xc8>\xf2\ -O\xa7\xa6U\xe2\xf3\xcc<2O\xb7\xce\x1aSO\x07\ -\xe8Bcm!\x10\x87\xa7)\x89\xb5C\x00v\xb4#\ -?\x01\x81*\x98\x88]\xf7i\x87\xa4g\xb18+\x1e\ -\xe7\x01\xb7\x8e\xed\xaa\x17:\x15\xfa\x0d\xba\xde\xda\xf7\x98\ -Ln;\x7f\xbe\xe2\xf0!\x99\xec\x0d\xe2\xbbj\xe8T\ -\xab\x18^\x7f6\x9f\x90\xc8uz\xbb>\xcf\x81\xfc\xf8\ -\xf4=\x9c\xbe\xb6\xf3#\xdc\xbaa|VN\x0f\xa3c\ -6\xfa\x94\x04\xbfAb\xcf\xf4\xe0)\xc0\x03:r\x08\ --\xebzc\x03\xc1\x10L\x15\x05>\xe6\x94\x1cc\x13\ -p\x89\x04h\xc2\x86+\xee\x90\x00\xd0\xc8\x10(C\x83\ - \xdb\x0f\x91\x00LD\x05\xc1q,M\x13\xc5\x09B\ -\xa4fE\x85\xf9\x17\x17\x8d\xa6\xfcdk\xb9\x08\xb0;\ -\x1b\x84\x84LtV5A0_\x14\xc8\x12\x0c\x85!\ -\xa2\xe7\xd4\x8c|\x93RI\x00SI\x84|\x8c}\x1f\ -(\xc4\x0a\x01\x07\xb2\xa8\x9aCK\x058\x0f-\x812\ -$\xbd/\xcc\x13\x0a\x04gL\x86\x08\xed3\x8a\x87\x84\ -\xd4v#\x09\x98\x08\x02\x8a\xf3\x88\xda7\xce\x84\x5c\xa7\ -1O\x13\xcc\xf5\x03\x9d\x13\xe9\xc44P\x02\x11\xc9A\ -\x9b\xa8\xc42\x03\x01\x03-\x14?\x0c\x14h\xf0\xe3O\ -t\x8d%I\xa3\xe7\x95,w\x0c\x94\xc8|oS\x86\ -\xad\x0d\x0d\x0d\x95\x09\x0e\xfe\x8b#}!JU\x15M\ -T\x873\x07\x99\xe1E\x0c\xa1\xf1\xb9Y\x9ah\xc4\xb6\ -\x03\x810\xf8\xdaDN\x22\xb8\xdbS\xc4\xae\x13\x9bU\ -\xc8q\xab\xae\xe1\xa1V\x15UV\x9e\x14\xc8\xc8\x1e\x9b\ -\xb6\x89\xa9O\xd1\x03u\xacD\xd7\xb5\xfb\xa4\x89\xaaF\ -\xdd\xbch\x9e\xb7\x09\xe6\xea\xcav\x13\xa8\xe0\x1f\xb7I\ -\xfb;\xb8\x8e\xdb\xb2\xf29Wr\xd4\x82<\xc8E\x80\ -\xe3\xbb\xab+\xa3d9\xd7\xdd\xe3}-\xd0-\xec\xe0\ -X\xc8\xa3\xc6\xe4\xbc\xce\xc5\xde\xbf\xb9`\x04\xdc\x02\x84\ -X\x88T\x05\xe2\x80r8\xca\x9e\x87\x8d\x9c\x1e\xd6f\ -\xe5j\x8b\xd6\xe0MB6\x10\xe2\xc6L7^\xe8\x89\ -\xf9\x95\x9fc\xa6\x5c(\x9a\xf9\x89\x9be!\xf72\x87\ -\x02\x80xN\x15\x80:\xb6\x15 \xed.\x92\x9d\xea\x81\ -\xe8O\x06R\xe9\xad\x97r\xb5\x9b\xae\x17\xa6\x8c\xe0`\ -\xeec\xcdr\xbb\xb9\xa5\x93|\xdd\xb4\x83\xcc\x08\xeb\x80\ -\xa8\xf9\xaf\x93an\xc4\x1cb\xec\xb0\xc7\xb3\x87\x96\x89\ -\xbbi\xe4\x12\xe6GQ\xbf\xa3z8\xfb\x8c\xdb\xa8~\ -i\xef\x06E\x89\xbd\xef\x88>\xb8\x08\x82\xb1\xd1\x12U\ -\x86\x5c(~\x8eY\x9b\xa8\xcc\x1f\xdb\xc6\xd9\xa5[K\ -\x95\xd5y9h\xe8{\xefX\x07\xc6\xa74d\xef\xa8\ -\xbcD\x04\x81a\x0fD\x14\x82\x9d(2\x0a\xf5\x00\xd3\ -Z\x07\x02G\x7f\x5cu\x9d\x9d\x89\xccu\xf6\x8758\ -o\x1a\xd0\xbf:\x8a\x82\x1d\xe8)\x17\x91epa\xe1\ -\x87\x9c\xaa\x1d\x8ccT\xce9Zr\x15\xc6\xdf\x93\x0b\ -\x19E\xb6\x89I\xe7\xc8\xcf\xeb\x88\x1b\xc1\xa7\xbdwh\ -Gz\x08\x02\x82\x07\xc4(|B\x00\x9e\xd2\x06\xc2%\ -\x0e\x04#\x07\xb7\xdcy\x98\xdf\x89n`~\x85\x8b\xe2\ -a\x16_q\xecz{\xbe\xf7|\xf0\x1e\x13\xc4x\xc4\ -5f=p\xce\x10\x06\xd4\x09\x1a+P\x049%H\ -\xdc\x88\xd9\xf7\x80\xc1\x01\x07\x0d!\x8e\xf7I\xe0\x0c\x0b\ -\x90l9\xc1\xb0\xb8\x1d \xc90MC\xc0v\x09\xc8\ -L \xc5l)\x13\x0e\xe9\xce\xbd\xf0(\x22\xa1\x80\xad\ -p\xa0\xc8\x1f6V2\xe2\x81\xfc\x09\x1bP-\xb6\xbc\ -\xe5D\xf4\x1e\x92\xfc\x22\x8e]E9\x976\xdf\x02<\ -I\x0b\x01\xce&\x09\x03\xf4\x04\x80\xbaD=c\x94o\ -\x08X\xac\x19\x86TY\x17\xad\xf1\xd5\x81!\x19\x17\xc5\ -t3p\xe4mf9\x86:\xc7\xc8\xb3!rKf\ -\x01\x90\xc6\xe8\xdd\x9e\xd3\xdcR)L5GQ\x0a\xa3\ -C\x00xRk\xa8~\x08\xe8\xfc\x1cEL\x81\x12\x8a\ -\xaa\x17@\x00c!\xc1\xe9\x1c\x5c#\xd4y6p\xc6\ -\x0f#;\xcddP\xfd\x93\xc6\xd2\x16\xca\xc7\xe0\xfbs\ -\x11\xc5=\x00Y<\x01\x9c\x10\xab\x07\xd2\x8c'=\xd1\ -Y)\xc4\xb0\x88\x95A\xadI\xb7\xf7\x02\x8e\xe1\x9c5\ -\x8c\x86f3<\xc8z\x02V\xb0n[\x09\xc9\xb9\x99\ -70\xe6\x86\xa3\x9cO!\xf6b\x09\xc0\x9f1\xc3\x19\ - \x1dS,r\x8d\x89\x9c3\x9dp\xef\x1dO \xd0\ -\x80\xf8\x9f\x14\x01T\xd9\x06\xb0\xb8\x90\x09y\xbc\x1f\x04\ -\xec\xe1\x10\xa9\xeaWC\x01\x14+d81\x912\xcd\ -W1\xb6\xd4\xdb#K\x91D\x11\xb1\xe9\x91\x18\xde\xe2\ -\xe4\xe2`\x81\xf109\x89\x020\xa5\x87\x90\xee\x15T\ -\x0cJ\x8b\x8a\x0c)\x8f\xa0\xe0\x1b\x0c\x18\xa4\x82z\x1c\ -\x0c\x02e\x11\x0c\x13\x1c'\x867>\x89\x16\xe1K\x0e\ -\xb4l)?A\x80,\x13\x0c\x85E\xe2\xbat\xce\xb2\ -4\xf2!\xc4:\x87\x93\xc6\x1f2H\x1eG$\xc0\xfb\ -cs\x02a$ IM\xc1jL\x14\xc3=\x9c\x11\ -\x02\xa4)j\x00\x8e\x135\x0c?\x8fz\x8c=IC\ -\xdf\x02a\xca\xa6\x09\x00\x95S\xc2\xe1\x14\x7fC\xcd\x0e\ -\x05\x00H;\xaa\xc0\xeaH\x93\x96\x18\xd2W\x11-\x22\ -,\x91\x96\xeeJ \x11\xc7\xab\x0e)\xa2D\x125\xac\ -Z\x83\xba\xdc\x12\x88\x85F\x1e\xe3\xd6\x8d\x87P\xa2{\ -\x86@\xbbD\xd4D&\x05\xe0\xfd_\xc4\xf5=!\xe2\ -\xae\xc2\x09W\x04\x1b\x12$.\x9c\xd3\xa2DIb\x15\ -\x01^\xc5*\x81\x95\x92J\xcfR!=\xdb\xbbyH\ -\x00\xd2\xce\x04\x011g\xc5\xf9\x10I\xe3\xe2\x5c\x84\xa4\ -X3-\x0aC\x096\xac-\x88\x1b\x5c(\x97a\x0a\ -\xa6!V\xda\x02\xa1\xc7m\xc6\xe2@\xab\x93\x9e\xaf\x11\ -\xb7\x90\xc6\xeb\x15,W3\xcd\xcaYg-/\xa2-\ -iE\x22B\xe6\x0b@ys\xc2Y\x10\xb9\x82@:\ -\x0aK\xac#S\xd0w\xbbBR\xda\x05YXC\xe8\ -\x18\xaa\x12\x93\x986\xa4\x08]\x17\xc4`\xafx`\xc0\ -\x1eCa\xe3J`T\x92\x8dw\x16!\x11:cL\ -\xe2:%\x83\x22\xf2\xfe\x0e\xc5\x0e\x01\xc8dg\x0bx\ -\x0c\x18\xae\xa1\xfa\x9e\x98\xa0\x0b\x01\xa2\xbf\x06\x0d\xc8\x9e\ -\x05\x88`\xe9\xc2C\x8c%\xe1P=n\x9a\xeb\x82\x15\ -\x92\xc6E.\x19\x1a\xda.\x09\x15d2\xe4D\x85l\ -L\x1b,q\x09z\xb0N|\xa0\xb3N\x10\xc2\x9e\x1a\ -\x22\x17\xa07\x0a\x8cl$\xd5UL\x0eB8-c\ -\xd0\xe2D \xf03\x99\xc3`g\x22kwc'U\ -\xees\x0e5\xc7\xcbv\xdfK\xe0\x89\x93\x87\x18\xb5\x05\ -\x07\xbc\xac&B\x8eY\x0c\xc4@$e\xd04\xecG\ -`\xe7U@\xbf2\x03\xa9\xc2'F)\x10\x12\x99\xac\ -<\x0a\x0c\xdc\x22r3]\xb1v\xf6\x93\x99l\x96\xb7\ -\xb2m\xc2y\xf6V\xfa\x91($\xf6 \xac\x17D\xa2\ -KB\x0b`u\xa1\xc2I\x0c\xaeC\xd5*\x83\xd0\x18\ -\xdf%p\xbb\xd2Uh\x87\xcaqY*e^qp\ -\x10\x032\x02\xf0w\x8aHDe\xac2\xd8\x8b>\xbc\ -IYr\x88\xfb\x1fR\xfe\xfc\xa0\xbat4\x11\xea?\ -!c\x8bZ\x0d\xb0\xa5\xad\xc13\xdd\x19:\xec}\x9b\ -\x03dB\xe8\xf0\xb0e\xc1\xd0(\xa2jD\xf0o[\ -\xc5\xb8\xcf\x1c\xcb_\x08w|\xae\x22\xbe\xd4\x04\x1e\xcc\ -eD\x13\xa4\x85\xd8\xea\x95\xc42\x84\x8d\x80\xa9\xb7\xc1\ -K\xdd~#\x18|_\xf2\x19M#\xc3dD\xb6*\ -\x18\xe1\xcb}\x9d\xa2.L\xda\x0a\xeezg\xd9\xed\x94\ -\xa3\x85\x9aD\xa3\x0f~\x0fJ/\xb7\x0f\xae\xdf\x0a\x9b\ -\x85\xdd\xee=\xca\x86p\x01\x0b\x9d\xea\xf4\x16\xecg}\ -b\xf7vuc9\xdd\xc7o7'\xb4\xb6Y\x0d\xcf\ -\xf0\x1f@\xa2m\xf80\xf7\xf2#\xe0\x14+\x81pG\ -;\xc1\xb77\x0aZ\x5c3\x87>\x09\x0d\x220\xec\x8c\ -c{\xca[\xe2LL\x15\xb1G\x19\x8d\xc6N\x09\xf1\ -\xdd\xf7\xbfw\xf9\x0b\xdb\xbc\x97q?\x1e\x0e\x01\xb8I\ -\x0a\xe1i\xc7\x86\xa2Y]\x86\xb8\x89\x19\xa5\x0d\xda\xc9\ -\x11w\xd6\x1c:\xc0\x8b\xbb\xa1\xafi\x90m\xab\xbe\x90\ -_\x1f\xe4.\x83\x91\xed\xed\xc1\xd1w')\xe9\x5c\xaf\ -\xa6i\xa9^\x22Ee%\xeb\xa4\x15\xc4\xb7nip\ -\xaf\x9f\x18\xde\xd6_|O\x8e\xc0\x82\xbb\x17A!]\ -\x0f\xb3\xf0^\x8d\xda\x88OK\x0a\xfd5\x05\xee\xc9\xcf\ -\xd4H\xc6\xa2V8\x84\x8a>\xb6\xdf\x8fB\xd0p\x97\ -\xba\xab\x9e\xa0\xed\x04\x81\xef\xf8\xbe\xf4C\xb8\x04zP\ -\x14C5\xa0\xe2\x1br8\x1d\xbd\xd1m\xeb\xc7$\x9e\ -\x00\xa0\x18\x86#!\xbe5\xd5 /\xa6(&WJ\ -\xa1\x10*\xa3\x17s \x94\x00w\xc1>\xef\x88\x92\xe7\ -6\xc4\xff\x08\x81\xbdU\x00\x1a\x02\x0f>$\xc5?\x9b\ -\x86\xben\x1b\x00\xff\xd9\x04\xef\xf5\x04-\xd5\xbe(\x7f\ -\x00\x89\x17?\x8cT\x12\xcd\x8fI9\x84\xec\x1e\x10\xe3\ -\xe3\x91H\xd4\x885A\x1a\xeb\xefl\x92MP%\x00\ -#\x17\xdcO\x1e\x88_\x0a\xdc\xac\x0f`\xb4\x85\x82B\ -\xf1\xc8dp\xa9d\xe2G\x92Y\xef(\x22fB\xcf\ -g\xa2\xf9\x82\x04\xfeh\xe4$(\xac\x10\xa1L\x89 \ -\x8e\x0b/\xf4R\x8c\xdc\x14\x01\x0e\xcda(\x0fBI\ -\x00\x8f \x22\xe5\x98\x9d\xc5\xa4\x92P\x1c\x88%\x86\x22\ -h\x88V+\x94#\xc0q\x06`\x8b\x04\x01u\x03e\ -T<\x01\xfa\xe1\x8fl\x1a\xe2@\xc8\xec\xe8#)\x16\ -\x1eNf\xcf\x0e,\xfe\x223\x02B@\x0fP\x98\x13\ -\x0dn\x0a@\xcf\x07\x06\xf6\x12\xb0\xa8\x0fA?\x0a\xe1\ -\x0e$\x0b\xce\x8b\xeb\xd4x\x8ec\x08\x87\x94\xfd\xb0\x18\ -\xf9%\xae\xfa\xf0 \x00\x0e6\x82\x8f<$\x10@\x17\ -0f\x07\x00\x8c\x22\x08\xb2\x19Ay\x07P\xa4$G\ ->\x01\x8d:\xf5\xa2\x1e\x16\x10\xfc\x13a\x09\x10,\xb6\ -#\xe9\xaa\x02k\xd0\x15\xf0\x82#\x07\x90\xe2\x8c\xf2\xf9\ -\x05p\xef%\xb4\xefk\x8e\xd5MX\x98\x22@I!\ -4\x18\x0f\xf2!\xed\x1a\x01\x8d\x17\x0e\xe2B\xa6\xe0H\ -\x05\x8cl\x15\x08\xd0!\xa1k\x15!D\x0f\xf1X\x0b\ -\xf0~\xceHb\xd90\xcf\x11m\xe3\x08\xca\xc6\xda1\ -#\x05\xac\xfc\xef\xab2\xfe\x82?\x13\x114p\xc2!\ -\x13\xb1?\x14\x02?\x14QH\xc6\xd1N!\x91R\x16\ -\xb1W\x15\xb0\xb4\xe1\xed\xdb\x00\xca\xbeU\xcf\xd9\x16\xce\ -\xf1\x17\x10\xce\xc5g\xb0\xda\xc27\x18\x116!\xd1\x88\ -\xa8\xf1\x8d\x18\xeao\x191L\x22\x11\x9b\x19\xe0\xff\x15\ -\xc2>\xe9\xe9a\x1a\x8f\xd4\x96\xa6<\xe2\xcd\xeb\x17M\ -\xef\x12\x8b\x92\xd5\xa2;\x1c\x11\x85\x13\x84\xab\x13\xd1\xc9\ -\x1c\xa2;\x19\x11K\x19b\x17\x1dqY\x1d\xb1\xa2\xe5\ -\xcaG\x16Nt!p\x87\x08\xae+\x16\xed\xe8\xbe\x91\ -\xf0\xef\x8dT\xcan\xfe#\x91\xfc\x06H\xc7\x1cR\x03\ -\x18\xb2\x08#r\x0d\x19Q\xd5\x15R\x17\x1d\xc2<\xc8\ -\xf2!\x12EX31\xaf\x22\xac\xf4\x92\x90\x1f\x22\x22\ -\x15\x09Q~I1\x83$\x11\x87$r\x06@\xe07\ -(`B\x06r\x8c\x08\x08\x5c\xcc\x01\xcf\x0eax\xcc\ -\x01\xd0A2O\x1d\x22\x1f!Q\xa0#\xf0I\x1eB\ -4\xee\xa7\x17\x0cB$\xc4p\xca\xf9rp!0^\ -\x88\xd1-'q3\x1c\x22\x1b\x1cj\xe6%\x8fJ\x01\ -\x00\x14rP\xcc\x9e\xaab\x84\xc18\x10P:\x11\x09\ -0\x1f\x82Y*2\x10!R\xa9!\x91\xdf\x16\x0bx\ -\xfd0\x11\x11\x90\x8ed\xef6\x1fR9\x17\xc2=#\ -\xf2C-2\x81-bN\xbf\xf0:\x19\x04z\x06\x02\ -0\x18\xb34\x16\xc4\xe8\x0d\xeb\xa2%r\xf9%1\x9d\ -%q^p\x0e\xa1+\x023+G\x19\x1b\x11\x1c\xb8\ -ew\x09\x021,pc\x1f\xb2y-\x02\x19-J\ -\x90$\xe6\xde\x8f\x08\xf4#\xe1\x0f7\xe0\xd0\x85!Z\ -\x13\x22Q42\xa7%R\xaa#\xcf\x1c\xc3q\xff+\ -*\xc0\xf2mI5\xb1!\x0c\xf2u1\xb3k9\xb3\ - \xd1\xd2H$\x22r\x01\xeb\xf8\x17\x81\xd6a\xe2@\ -\xab\x01\xdc\x1d,\xba\x09\x004hbE8\xc2\x1d/\ -\xf2X#\xb1\x0ax\x10\x0b'\xcd\xde\xe2qk&\x93\ -\xa5\x1bR\xc2!\x13e\x1f\x92=:\xf3\xe9$S\xb5\ -(\x22C\x0d\xf0j\xcdpn$\xe4\x00\x0a`N\x1c\ -4\x1c\x1bBI=\x91Q9\x13\x019Q\xa4\xf1\xf3\ -P#\x12'\x0c3X\xfd\xc9\xe55\xf3\x10#jb\ -\x93r;\x1b\xf4\x011\xf3o23r$@\x83E\ -\xa0\xa2\x80\x02P\xc8,\x86\xc8\xa2GBQ\x99B\x93\ -\xde#\x91\xe0\xee\x10J\x22\xcf$VS\xa3C\xd1\x1f\ -?R`\xe3K\x91\x06\x13\xfdD\xd2\xcf;\x14S@\ -s$$J\x1c\x04\xe0`\xa8\x01J\x19\xe2P\xc5\xe0\ -&\x1e4\xb4\x1d\xd4#\x1c\xf2\x0f4Q\xd9G\x227\ -\x10\xb1\x0f\x11\x22.\xb7\xe7\x95\x01r\xbbC\xee/\x17\ -3b\xe7\x8d\x01\x0dr\xcd'\xb4P!sp$\x84\ -\xa6\x15\xd4\xf4\x1b@9O\xa0F$\x0bN\x17\xef\x9e\ -\x08S\x8bK\xd2Q8\xf3G9\x22;%\xc8\x05?\ -b\x0fCe\x9f+\x82#+\xc9t[3\x131p\ -'?\xf4\x97@3\xb3 T\x9e$\xa0\x8bT \xad\ -7\xe1\x0e\x15\x228\x8f\x88&\x1a\x15T\xcd\x22OF\ -\xd2\x13G\x13J\x02\xac\xe70\x8e\xa42\xcb\x81H0\ -\xc7Hr.\xefR2!\xe7\xaas\x01\xabX!\x95\ -\x12\xf4O'\xf4\x9dEbR\x0cU\x94\x0f@\xd3Y\ -\xa1\x08\xc5#\xef\x02\xa0\xcc\x16\x95\xa8\x142\xf7P\xd2\ -\xa5=\xb5a*\xd4.\xc9\x00{\x16umM5q\ -MuuM\xb3\xa9\x17\x91\xbc#S\x1dX\xd5=Y\ -\x02Xda\x0c\x8f\x00\xf2\x22\x11\x02\x10\x80\xcb\x0f\xc1\ -`\x13\x82aU\xd2\xfd[t-!\xc7\x83L\xc2-\ -\x16\x85cRB!R\x8cK,\x14\x8a!\x95~\x88\ -\xb5\x82\x1a\xb5\x87NsmN\xd4T&\x00\xbfb\xe0\ -\xecWL\xe0!\xe0\xf1c\xa0\xad;\xe1W_u\xb1\ -/\xa2\x13=\xd2\x1a\x85\xf1\xa6\x86\x8b\xdc\xd9\xcaW?\ -4@z5.\xdf3\x196\x957N\xa2\x15N\xe2\ -_b\xe0\xbfc$?cb\x1dc\xa0\xf1c\xeb\xf9\ -d\x22__\x96K_\xd5\x16\xc3$v\xeeU\x1c \ -\xd6\x08\x07\xd6\x0c!\xef\xdfWt\xdcH\xa4\x8e\xc5\x94\ -K]U\x8b \x15\x8fb\xd61cB!h\x16\x84\ -\x17\x96\x88%\xd6\x8c!\x16M0'\x01Vl\x92#\ -p\x86\x91\xc9!\x5cu'M\x93`\x22\xf4F\x88\xb5\ -\xd2#5\xd7k\x95\xda&\x0a\x9e\x09@\xb8\x10W\x04\ -\x14b Y\xc0yUA\xa1U\x96\xcddt\xc14\ -\x91\x084T\xcbV\x91\x14\xde\x16\x0bC\xa2&}h\ -\x1cn6b\xef\xd6gST\xe9]\x93\xb6%\x8f\xec\ -\xb0\x81V\x1a\xc8\x9e\x8a\x22\x0ev\xe1\xaa\xc0`\xb6\x06\ -P\x05Z\xf1GK\xf5\x11L6N\x80\x12_W\xad\ -\x99>\xd7+?\x14\x855\xc1\x11n\xa2-:\xb6i\ -s\xf6\xf9t\x22^\x04\x17\x90\x05\x07$t@B\x05\ -!\xady\xe1\x96\xd0\x81$\x0e\xe9\x96\x1dA\xcb*\x17\ -\x19vw\x1c#\xd4\xc9\x0b\x96\x04\x22\xb6\x9fj\x22\x1c\ -\xd4\xc5\xaf\x1e\xf4\xdf\x1fT\x91,\xb3\xadf\xb7A@\ -\x92J#\x16\xce \xf6\xd3%\xb6\x94pi\xd2\x07\xd0\ -\xcfG\xf4\xd5nu\xcb|\xd6\xacJ\x0f\x9e\xfa4\xe5\ -}w\x89@V\xfb}\xe25~\x22\x0d~b:\xfc\ -\xf7\xbe\x22\x97\xf5nV\x0em\xc5D\xca\x0f\xe42f\ -7a\xf6#\x80\x96'f\xf6+\x81\x023\x81B\x0b\ -\x81\x8299x:\x22\xb0\x87Y@\xc4\x07i\xdf\x05\ -X+sMR\xd5q\xf7}W\x87\x84\xe2\x11g\x18\ -@\x22\xf8D \x98H#r\xafeO\xd4\x82n\xab\ -&\xa6H\x88\x15\xcf#veS4\x95\x80\xb5;x\ -\xd8r\x22Xv xz#Tw9\x98\x81\x01\x15\ -o\x1e\xb2-\x5c\xd6\x9a \xb7\x84#\x8b>\x13\x01|\ -\xb3\x80h\x08\x22 \xbb@\xee\x0a\x81\xf3\x8da\xf1\x89\ -\xe2.\x03X\xe0\x04\x04\xce\x0e\xc9\x06!\xf5\xa8\x16\x81\ -@\x10\x18\xf4\x0c7j\xa4x\x1e\x22sU|B\x1b\ -jx\xb9ab\x17\x8b\xe26\x94,^\x0a\x98\xdcO\ -\x0b\xac\x14\x81\x1a\xba`\xe9d\xee!C4\xcf\x5c0\ -\x15\x82V\xa5n\x94C\x82\xf7\xd1,\x8aj#\xa9\xf6\ -\x89\xb9\x1aLM\x86\x0a-\x83\x92\x96S\x00\xf3S&\ -N\xedr\xd5\xc8\x92x\x8a\xcf\x97qH\xcf9N(\ -,$\x0c\x12\x01\xb2\x0e\x039|\x03\xf9JH\x17\x9e\ -\x1a\xc1\x97\x85@u/5b\xc3V\x99\x90\xc2\x15M\ -\x193\x8bMJCMO\x93\xa23n\xe5co\x22\ -8\x06\xb9\xb4\x08A'\x9b\xa1qC\x88)\xc2\x0aS\x82\x81\ -*\xcf\xcf\x18\x0b\xfcH\x06P\x09\x8c\xae\xbd\xc9\xbb\x9e\ -\xa1>\x0a\x91\xa3\x05\x83\x87\xdc\x1cG \xa2\xaa\xf4V\ -\xa0\xa3\x90i\x0b\x9cJ\x9c\x0a\xab\xbc\x0a4\x12\xa2\x9a\ -\x91\x08\x0c|D\x83\x92\x0a> \xa0[\x10{ \xa4\ -(\x1d\x17\x91\xa14d|\xa8\xf0\xdaY\x1b%p\xfa\ -|\xf9\x19\x822\x0aI\xa0\xa13Dn6\xa3k\x92\ -\x19\x97\x0a\x1cp\x95IiLt\xe7\x1f\xe0\x11\x9d)\ -\x90i\x00\xf4\xd3\xa1\xe4L\x8e=6\xa7\xf2s&\xa5\ -\x13\x02O'\xa5\x8e\x99\x9e\x08\x1f\xb3IJ\x82\x89R\ -\xc2,\x5c\x00s\x88\xb2\x18\xce\x8e\x03\xdb\x03\xb1\xf3\xc2\ -}2$\xf2\x99\x9c\x15:\xc7\xf1`\x82\x84\xb3r:\ -nN \x18\xa1:\x06&\xac8\xa5LI4\xf8\x91\ -5\xc6h\x86\x90\x15\xe8(\x1bC$\xe7\xa3\xfc\x01\x0a\ -P\x08d]\xa54\x8aKS$\x94\x9a5?\x08\x94\ -\x09d\x82\x814\xe2`|S\xe2uER$\x95B\ -\x81='\xb5R+\x1eG\xc8!b\x82\x81\x0a\x93\x96\ -\x82\x15\x8d\xa9n\xda\x9c@M\x9cq\xcd'\xe9\xfe~\ -Z\x80\xd5\xa8~\x17\xa8(8\xae\x1f\x08(\x9f\x0b\x86\ -\x85\xd2=]$W\x22=_\x22\x11\xe0\x8e\x82\xd0h\ -%\x8a\xa5\x9c-\xa8\xe7Q\x15\xf2\xea-\x1e\x1bh(\ -H\xb1[\xa8 \xa1p\x17,\xf5x\x9e\x5c\xc8\xed\xd0\ -\x85\xcf\xc1\xad\x02` \xa0R\x98F\x82\xd8\x88\xfa\x0f\ -b\x87\xba=|_KA\xec\xda\x87\xf29\x98\x8b`\ -\xa8\xe6B\x8d\xe0\xe84x\x0f \xa6J\x0a\x0c(\xd2\ -\xf2\x086\xdc\x04\xb2S\x8c \x97\xda\xdat<\xa08\ -l\xf4\x05\xafSG\x0e\xa8\xb9\x1a5\x83\x9bZ(\x1c\ -yi\x06*\x0a\x16)\x83-\xc0N%\xf9\xa0\x01\x9b\ -.F\x90\x17\xab\x87\x81N\xb4y\xa1\xda\x123\xaf#\ -\x14\x9a@\x00\xd2\xa5\x9a\x0a%\xa8\xed\xa9A#\x8c)\ -\x9e\xa5\xaa.\xa5\x94\x8e(6\xba\x02\x0d\xb0\x22\xfb\xc2\ --I\xd2\xa3\xe2@A\xa9\x87\x02\x0a\x15\xdc\x11be\ -\xb7\xaf\xad\xa8\xf1#\x91(V\xf4\x8a\xf1\xe8\xa4u\x1e\ -\x07\x88.\x18\x82\x00zn\x9e\x9c\xf1\x0b\xfb\xf8\x82\x07\ -\x97\x06T\xa8n\xd2V\x06\x9d\xba:)\xb5\xa3\xe9\x06\ -\x92\x0a\x0f\xa9\x87\x0d\x09p\x1f|\xe3\xe5|\xe6\xacG\ -p\x00\x06\x1c/\x22\x89\xf7\xe8\x93\xa3\x1e\x11\xb0\xaa\xa4\ -E\x5c\x03\xba{\xce\xb0\xed\xa9\x05#\x8f\xfe\x0a#\xe9\ -\x22\x06\x87\xad4M9\xf0\x18\xa6\xd1\x22\x0d\x19\xcb\xa7\ -~c\x12w\x81\x1f(<\x15\xfd\x07\xa4k\xd3\xa7S\ -\xf0\xec\x90q\xaa~,\x82\x01\xfd\xa7\x97\xdb\xe3,s\ -j9TD\x7f\xd6\xe9J\x12\x95\x16\xa9\xb0\xa9\x0d\xd5\ -\xc0\xdc\x09\xe8\xd2\x81@\x88\x90\x00RR\x83\x87\xda\xaf\ - \x89\x08\xa7\x8b4\x8e\x13\x9f\xf9JR\xa3e \x95\ -!\x8a\xb8\x1c\xa9\x82G\x82\xf8\x82\x84\x12\xa46\x128\ -)\x83%\x1dJ\xb8`\x00\xacJa\xb5\x16\x89\x1c&\ -\x984x\xa6W\xf1R\x1e\xe9\x1d\x87\x14g\xa8C\xd4\ -\xa8\xdf \xa0\x80\xa9\x0cu\xc0\x0e\x8c\x1a\x95\x18D\x80\ -\x1e\x95!\xbe\x91\xc1\x14+(\xcaU\x5c\x00\x00\x88T\ -\x86\xf2\xe0\x04p\xd8\xf9A\xc8&T\x85\xd2G]p\ -\xf9\xf6\x13\x95*\x22\x08+\xca)\xe3\xe1\xf2\x80\x80\x1e\ -\x0b#\x80\xfa.\xa8\xf2\x07\x10D\xec\x00!\xe9N\x10\ -\xa9\x1d\x14FH\x00O\xd3\xf0\x1f$\x03t\x82\xb9\x92\ -\x9e\x10\xd7\x04$.\x89\xf8\x1f\xb0\xb2\xa4>\x8d\xa8!\ -TK\x1d\xa0\xc6RltT\xa8\xa9$\x01X\xa6\x90\ -\x00\x0c\x09\x183\x82\x9d@\x10\x88L*\x17\x0c\x86\xc3\ -\xa1\xf1\x08\x8cJ&\x00fE\x910\x93\xb4R7\x1c\ -\x8e\xc2\xd3\xe3I\x09\x89\xff$\x8fI\xa4\xf0\xa9#\xfe\ -Q,\x8f@\x80 \x06\x94\xc8D\xfa\x9a\xb4! \xd9\ -l\xea8\xe3\x04O\x84\x82\xca\x0b\xeawD\xa2\xc3\x1a\ -\x94\x803\xe2\x96\xdb\x84\x87\xa8\xd5\x08c\xc0\x07T\x16\ -\x0cj\xeeYUF\xb7Z\xad\xd4%\xf0\xb6u\x88\xbc\ -\xfe\xb2\xa8k\xd5\xe9y\xa6\x0a3LZ-\xf1\xd6m\ -\xc8\xcf*\xb7\x5c(\xd2\xf2\xc5\xb1S)\x92\xdd\xe7U\ -\xdb\xfc\xb2\xc1\x0e\xb93S\xf2\xa3\x06\x0av\xe2\x02c\ -\x85C\x0c\x8b\xd7\x17\x7fhe\x81o\xcc\xcb^\x12\x1d\ -\xcaI\xe5\xe9\xbba\x9a\x1d\x81\xcfGt\xbah\xde\x12\ -\x1a\xe2\xd6\x82][\x06,$c\xa9\x8e\xcb\xd4\xb6\xc2\ -\xe6\xd6\xbd\x16f)a%\xad\xde\xaa\x04\xcd\x06\xf1\x87\ -bnK\xe7I~\xe1D\xf5\x1c\xe8~\xae \xd3\xea\ -\x87_=\x86D$5\xd1\x8d\x9a\xe4#D\xb7vM\ -\x866J\x92~8\x9b\x96\xa8\x03\x1b\xd5\xc6.X\x97\ -C\xd3}\x95\xfd!\xdd8\x9b?\xf60~\xff\x8c4\ -$\x0c}\xd0\xc3\xfd/\x1d\x16\xc2:\x03C\x1b\xd4\x1d\ -\x08F\x10\x84\xc2\x0aBO0\x0a\x15\x0fC(`\xd1\ -G\x1f8\x0e\x1c}\xdf\x94qb3\x84\x95\x94\xfe,\ -\xd0\x90\x0e\x12B\x92\xf2X\x0a\x8b\x87\x80\xa61<\xdb\ -Sj5\x03\x8f(\xe0\x8aBFx\xa9\x0c?R\xf1\ -1l.\x12xy\xf4\x91^\x98\x81\xe4\x5c\x85\xc4\xa8\ -\xa0\x8a#\xd4,\xe7BG\x94$\xa6x\x0f\xb5\x19H\ -5\x14\xa5-\xc1B\x08\x84$\x17\x94\x10\xa8\xfd\x02\x18\ -\x16\xc2\x91\x80sc\xd9\x1d\xe3\x92R\xc8\x88Y\x89J\ -9>cC\x0e\xf4$\xb0Bd4 \xe2\x01g\xf3\ -\x91\x0a>\xe80qNK\xc4\x94\xa8PBA\x09\xda\ ->\x85@!v\x18\x0c\x8au\x1amwigFo\ -N\xe2!R%\xa5\x10\x80\x12\x8d\xa8\x9ac\xf1\xc0x\ -\x0a\xb5z\x98s\xaa\xa7\x0a\x9aQ\x9b\xda)\x08\xa7\xc0\ -\x00\x22\xa3\xad\x95\x17-\x08\x16^\x02\xbdw\xab\x1b\xba\ -\xfd\xb5\xab\x95\xb6\x183J\x8a\xe5:\xb7\xb2\x91\xe3\x8d\ -/\x14\x96\xc31\x94\xb0Z\x9bM\xa6\xb0\xd6\xf6\xf4\x14\ -K\xca\x94\xa8B\xb2\xed\xf40\xc0\xa3\xc5jH\xebm\ -mVz\xe8e-u\xfd*\x00\xe2\x22!*\x1d.\ -\x0a\xd8\x8f[\x07d\xbe\xa5\xaa\xe6\xb8\xaa\xeab\xee\xc6\ -\xd6\x22\x89\x16RI\x09\x09/GD\xddBF\xf7\x80\ -\xb5\x84\xaf\xe6\x0b\x10_\xf0\x07:Z\x97\x0f\x81\xc9\x09\ -\x1f\x10\x90/\x08V\xd94 \x86\x03\xb225\xc9\x09\ -\xab\x99\xb2\xfc\xc3\xf2\xa8+\x14\x80\xdf\xb3<\x1b\x7f\x8f\ -\xd2-\x09\x16q\xe4\xb0\xa9\x9f\xc0Q\xd0/\xcf\xa8\x1b\ -+\x12\xaf\xb2\xc8\x0f.\x9d\xacT\xa8nBEt$\ -\x07\xbd\x144 \xa9K\xc9+C8B4%\xc3X\ -[\xf4k.\x22\x05R\xa1a\x09\x14\x12\xa0\xf9\x09\xa8\ -\x5c+\xe8\x00\x80\x10\x82\xc1\x8e\x01\x0a\x86D0:\xb5\ -d?ZZ7e\xa5\x02\xdd\x12\x84\xc8\xd2\x04Y\x93\ -\xf08\x89[D 0K\xc1\xd4\xa8\x11\xa2\xd0\x98D\ -\x00\x9e\x10\x83\xc1\x098\xd0\x93>\x8f46\xe3\x1c.\ -\xe6\xb8\xfd\xed\xa7\xd1\x1f}\xe3\x9d\xe8\xba>\x93w\xe7\ -\xfa^\xa3\xa9\xea\xb1\x1e\x9f\xab\xeb\xba\xfe\xc1(\xe8{\ -\x1e\xd3\xb5\xde\xfb>\xdb\xb9\xee\xb4\x1e\xb7\xbb\xef\xbb\xfe\ -\x8b\xb8\xf0\x01E\x01L\x01R\x01Y\x01`\x01g\x01n\x01\ -u\x01|\x01\x83\x01\x8b\x01\x92\x01\x9a\x01\xa1\x01\xa9\x01\ -\xb1\x01\xb9\x01\xc1\x01\xc9\x01\xd1\x01\xd9\x01\xe1\x01\xe9\x01\ -\xf2\x01\xfa\x02\x03\x02\x0c\x02\x14\x02\x1d\x02&\x02/\x02\ -8\x02A\x02K\x02T\x02]\x02g\x02q\x02z\x02\ -\x84\x02\x8e\x02\x98\x02\xa2\x02\xac\x02\xb6\x02\xc1\x02\xcb\x02\ -\xd5\x02\xe0\x02\xeb\x02\xf5\x03\x00\x03\x0b\x03\x16\x03!\x03\ --\x038\x03C\x03O\x03Z\x03f\x03r\x03~\x03\ -\x8a\x03\x96\x03\xa2\x03\xae\x03\xba\x03\xc7\x03\xd3\x03\xe0\x03\ -\xec\x03\xf9\x04\x06\x04\x13\x04 \x04-\x04;\x04H\x04\ -U\x04c\x04q\x04~\x04\x8c\x04\x9a\x04\xa8\x04\xb6\x04\ -\xc4\x04\xd3\x04\xe1\x04\xf0\x04\xfe\x05\x0d\x05\x1c\x05+\x05\ -:\x05I\x05X\x05g\x05w\x05\x86\x05\x96\x05\xa6\x05\ -\xb5\x05\xc5\x05\xd5\x05\xe5\x05\xf6\x06\x06\x06\x16\x06'\x06\ -7\x06H\x06Y\x06j\x06{\x06\x8c\x06\x9d\x06\xaf\x06\ -\xc0\x06\xd1\x06\xe3\x06\xf5\x07\x07\x07\x19\x07+\x07=\x07\ -O\x07a\x07t\x07\x86\x07\x99\x07\xac\x07\xbf\x07\xd2\x07\ -\xe5\x07\xf8\x08\x0b\x08\x1f\x082\x08F\x08Z\x08n\x08\ -\x82\x08\x96\x08\xaa\x08\xbe\x08\xd2\x08\xe7\x08\xfb\x09\x10\x09\ -%\x09:\x09O\x09d\x09y\x09\x8f\x09\xa4\x09\xba\x09\ -\xcf\x09\xe5\x09\xfb\x0a\x11\x0a'\x0a=\x0aT\x0aj\x0a\ -\x81\x0a\x98\x0a\xae\x0a\xc5\x0a\xdc\x0a\xf3\x0b\x0b\x0b\x22\x0b\ -9\x0bQ\x0bi\x0b\x80\x0b\x98\x0b\xb0\x0b\xc8\x0b\xe1\x0b\ -\xf9\x0c\x12\x0c*\x0cC\x0c\x5c\x0cu\x0c\x8e\x0c\xa7\x0c\ -\xc0\x0c\xd9\x0c\xf3\x0d\x0d\x0d&\x0d@\x0dZ\x0dt\x0d\ -\x8e\x0d\xa9\x0d\xc3\x0d\xde\x0d\xf8\x0e\x13\x0e.\x0eI\x0e\ -d\x0e\x7f\x0e\x9b\x0e\xb6\x0e\xd2\x0e\xee\x0f\x09\x0f%\x0f\ -A\x0f^\x0fz\x0f\x96\x0f\xb3\x0f\xcf\x0f\xec\x10\x09\x10\ -&\x10C\x10a\x10~\x10\x9b\x10\xb9\x10\xd7\x10\xf5\x11\ -\x13\x111\x11O\x11m\x11\x8c\x11\xaa\x11\xc9\x11\xe8\x12\ -\x07\x12&\x12E\x12d\x12\x84\x12\xa3\x12\xc3\x12\xe3\x13\ -\x03\x13#\x13C\x13c\x13\x83\x13\xa4\x13\xc5\x13\xe5\x14\ -\x06\x14'\x14I\x14j\x14\x8b\x14\xad\x14\xce\x14\xf0\x15\ -\x12\x154\x15V\x15x\x15\x9b\x15\xbd\x15\xe0\x16\x03\x16\ -&\x16I\x16l\x16\x8f\x16\xb2\x16\xd6\x16\xfa\x17\x1d\x17\ -A\x17e\x17\x89\x17\xae\x17\xd2\x17\xf7\x18\x1b\x18@\x18\ -e\x18\x8a\x18\xaf\x18\xd5\x18\xfa\x19 \x19E\x19k\x19\ -\x91\x19\xb7\x19\xdd\x1a\x04\x1a*\x1aQ\x1aw\x1a\x9e\x1a\ -\xc5\x1a\xec\x1b\x14\x1b;\x1bc\x1b\x8a\x1b\xb2\x1b\xda\x1c\ -\x02\x1c*\x1cR\x1c{\x1c\xa3\x1c\xcc\x1c\xf5\x1d\x1e\x1d\ -G\x1dp\x1d\x99\x1d\xc3\x1d\xec\x1e\x16\x1e@\x1ej\x1e\ -\x94\x1e\xbe\x1e\xe9\x1f\x13\x1f>\x1fi\x1f\x94\x1f\xbf\x1f\ -\xea \x15 A l \x98 \xc4 \xf0!\x1c!\ -H!u!\xa1!\xce!\xfb\x22'\x22U\x22\x82\x22\ -\xaf\x22\xdd#\x0a#8#f#\x94#\xc2#\xf0$\ -\x1f$M$|$\xab$\xda%\x09%8%h%\ -\x97%\xc7%\xf7&'&W&\x87&\xb7&\xe8'\ -\x18'I'z'\xab'\xdc(\x0d(?(q(\ -\xa2(\xd4)\x06)8)k)\x9d)\xd0*\x02*\ -5*h*\x9b*\xcf+\x02+6+i+\x9d+\ -\xd1,\x05,9,n,\xa2,\xd7-\x0c-A-\ -v-\xab-\xe1.\x16.L.\x82.\xb7.\xee/\ -$/Z/\x91/\xc7/\xfe050l0\xa40\ -\xdb1\x121J1\x821\xba1\xf22*2c2\ -\x9b2\xd43\x0d3F3\x7f3\xb83\xf14+4\ -e4\x9e4\xd85\x135M5\x875\xc25\xfd6\ -76r6\xae6\xe97$7`7\x9c7\xd78\ -\x148P8\x8c8\xc89\x059B9\x7f9\xbc9\ -\xf9:6:t:\xb2:\xef;-;k;\xaa;\ -\xe8<' >`>\xa0>\xe0?!?a?\xa2?\ -\xe2@#@d@\xa6@\xe7A)AjA\xacA\ -\xeeB0BrB\xb5B\xf7C:C}C\xc0D\ -\x03DGD\x8aD\xceE\x12EUE\x9aE\xdeF\ -\x22FgF\xabF\xf0G5G{G\xc0H\x05H\ -KH\x91H\xd7I\x1dIcI\xa9I\xf0J7J\ -}J\xc4K\x0cKSK\x9aK\xe2L*LrL\ -\xbaM\x02MJM\x93M\xdcN%NnN\xb7O\ -\x00OIO\x93O\xddP'PqP\xbbQ\x06Q\ -PQ\x9bQ\xe6R1R|R\xc7S\x13S_S\ -\xaaS\xf6TBT\x8fT\xdbU(UuU\xc2V\ -\x0fV\x5cV\xa9V\xf7WDW\x92W\xe0X/X\ -}X\xcbY\x1aYiY\xb8Z\x07ZVZ\xa6Z\ -\xf5[E[\x95[\xe5\x5c5\x5c\x86\x5c\xd6]']\ -x]\xc9^\x1a^l^\xbd_\x0f_a_\xb3`\ -\x05`W`\xaa`\xfcaOa\xa2a\xf5bIb\ -\x9cb\xf0cCc\x97c\xebd@d\x94d\xe9e\ -=e\x92e\xe7f=f\x92f\xe8g=g\x93g\ -\xe9h?h\x96h\xeciCi\x9ai\xf1jHj\ -\x9fj\xf7kOk\xa7k\xfflWl\xafm\x08m\ -`m\xb9n\x12nkn\xc4o\x1eoxo\xd1p\ -+p\x86p\xe0q:q\x95q\xf0rKr\xa6s\ -\x01s]s\xb8t\x14tpt\xccu(u\x85u\ -\xe1v>v\x9bv\xf8wVw\xb3x\x11xnx\ -\xccy*y\x89y\xe7zFz\xa5{\x04{c{\ -\xc2|!|\x81|\xe1}A}\xa1~\x01~b~\ -\xc2\x7f#\x7f\x84\x7f\xe5\x80G\x80\xa8\x81\x0a\x81k\x81\ -\xcd\x820\x82\x92\x82\xf4\x83W\x83\xba\x84\x1d\x84\x80\x84\ -\xe3\x85G\x85\xab\x86\x0e\x86r\x86\xd7\x87;\x87\x9f\x88\ -\x04\x88i\x88\xce\x893\x89\x99\x89\xfe\x8ad\x8a\xca\x8b\ -0\x8b\x96\x8b\xfc\x8cc\x8c\xca\x8d1\x8d\x98\x8d\xff\x8e\ -f\x8e\xce\x8f6\x8f\x9e\x90\x06\x90n\x90\xd6\x91?\x91\ -\xa8\x92\x11\x92z\x92\xe3\x93M\x93\xb6\x94 \x94\x8a\x94\ -\xf4\x95_\x95\xc9\x964\x96\x9f\x97\x0a\x97u\x97\xe0\x98\ -L\x98\xb8\x99$\x99\x90\x99\xfc\x9ah\x9a\xd5\x9bB\x9b\ -\xaf\x9c\x1c\x9c\x89\x9c\xf7\x9dd\x9d\xd2\x9e@\x9e\xae\x9f\ -\x1d\x9f\x8b\x9f\xfa\xa0i\xa0\xd8\xa1G\xa1\xb6\xa2&\xa2\ -\x96\xa3\x06\xa3v\xa3\xe6\xa4V\xa4\xc7\xa58\xa5\xa9\xa6\ -\x1a\xa6\x8b\xa6\xfd\xa7n\xa7\xe0\xa8R\xa8\xc4\xa97\xa9\ -\xa9\xaa\x1c\xaa\x8f\xab\x02\xabu\xab\xe9\xac\x5c\xac\xd0\xad\ -D\xad\xb8\xae-\xae\xa1\xaf\x16\xaf\x8b\xb0\x00\xb0u\xb0\ -\xea\xb1`\xb1\xd6\xb2K\xb2\xc2\xb38\xb3\xae\xb4%\xb4\ -\x9c\xb5\x13\xb5\x8a\xb6\x01\xb6y\xb6\xf0\xb7h\xb7\xe0\xb8\ -Y\xb8\xd1\xb9J\xb9\xc2\xba;\xba\xb5\xbb.\xbb\xa7\xbc\ -!\xbc\x9b\xbd\x15\xbd\x8f\xbe\x0a\xbe\x84\xbe\xff\xbfz\xbf\ -\xf5\xc0p\xc0\xec\xc1g\xc1\xe3\xc2_\xc2\xdb\xc3X\xc3\ -\xd4\xc4Q\xc4\xce\xc5K\xc5\xc8\xc6F\xc6\xc3\xc7A\xc7\ -\xbf\xc8=\xc8\xbc\xc9:\xc9\xb9\xca8\xca\xb7\xcb6\xcb\ -\xb6\xcc5\xcc\xb5\xcd5\xcd\xb5\xce6\xce\xb6\xcf7\xcf\ -\xb8\xd09\xd0\xba\xd1<\xd1\xbe\xd2?\xd2\xc1\xd3D\xd3\ -\xc6\xd4I\xd4\xcb\xd5N\xd5\xd1\xd6U\xd6\xd8\xd7\x5c\xd7\ -\xe0\xd8d\xd8\xe8\xd9l\xd9\xf1\xdav\xda\xfb\xdb\x80\xdc\ -\x05\xdc\x8a\xdd\x10\xdd\x96\xde\x1c\xde\xa2\xdf)\xdf\xaf\xe0\ -6\xe0\xbd\xe1D\xe1\xcc\xe2S\xe2\xdb\xe3c\xe3\xeb\xe4\ -s\xe4\xfc\xe5\x84\xe6\x0d\xe6\x96\xe7\x1f\xe7\xa9\xe82\xe8\ -\xbc\xe9F\xe9\xd0\xea[\xea\xe5\xebp\xeb\xfb\xec\x86\xed\ -\x11\xed\x9c\xee(\xee\xb4\xef@\xef\xcc\xf0X\xf0\xe5\xf1\ -r\xf1\xff\xf2\x8c\xf3\x19\xf3\xa7\xf44\xf4\xc2\xf5P\xf5\ -\xde\xf6m\xf6\xfb\xf7\x8a\xf8\x19\xf8\xa8\xf98\xf9\xc7\xfa\ -W\xfa\xe7\xfbw\xfc\x07\xfc\x98\xfd)\xfd\xba\xfeK\xfe\ -\xdc\xffm\xff\xff\ -\x00\x00\x03\xaa\ -<\ -?xml version=\x221.\ -0\x22 encoding=\x22UTF\ --8\x22?>\x0d\x0a\x0d\x0a \x0d\x0a \ - icon / o\ -utliner / entity\ - / Default - Sav\ -ed\x0d\x0a \ -Created wi\ -th Sketch.\x0d\x0a \x0d\x0a \x0d\x0a \ - \x0d\x0a \x0d\ -\x0a\x0d\x0a\ -\x00\x00\x04q\ -<\ -?xml version=\x221.\ -0\x22 encoding=\x22UTF\ --8\x22?>\x0d\x0a\x0d\x0a \x0d\x0a \ - icon / o\ -utliner / entity\ - / Editor only -\ - Default\ -\x0d\x0a Crea\ -ted with Sketch.\ -\x0d\x0a \x0d\x0a \ -\x0d\x0a \ - \x0d\x0a \ - \x0d\x0a\x0d\x0a\ -\ -\x00\x00\x02\x9b\ -<\ -?xml version=\x221.\ -0\x22 encoding=\x22UTF\ --8\x22?>\x0d\x0a\x0d\x0a \x0d\x0a \ - Artboard\ -\x0d\x0a Created with\ - Sketch.\x0d\ -\x0a \x0d\x0a \ - \x0d\x0a \ - <\ -/circle>\x0d\x0a \ - \x0d\x0a \ -\x0d\x0a\x0d\x0a\ -\x00\x00#k\ -\x00\ -\x00\xf0\x80x\x9c\xed\x5c\x07\x5c\x93\xc7\xdf\xbf'\x09\x09\ -[\xb62\xc4\x88\x03\x17#\xcc\x10\x01\xd9CE\x11\x10\ -\xd4\xbaB\xf2\x00\x91,\x930\xc4=\xaaV\xad\x03\xad\ -\x0b\xb7\xd6=\xea^\xad\xd6\x89V\xabu\xb7\xd5\xb6\x8e\ -?\xae*\xe2`\xa3y\xef\x9e$\x10\x14\x15$\x8a\xf6\ -}\xbe\xf9\xdc\x93\xbb\xdf\xdd\xfd\xd6\xddsw\xcf\xb8'\ -&\x06t\x02\x00\xe8\x83\x16\xe0\x15\xa0\xc1\x18\x06T\x07\ -*\xf17\x14\x1e0\xad8\x85\x88\xc3r\x98+FU\ -\xd3aa\x8c\xae\x8eS\xe0\xc1\x5c\xc3'q!f\xa1\ -U\xc6Z\x1dG\xb5m\xb4x6\xd7\x94\x9f\x0d0;\ -\xa0\xa7\x8ac>\x98}u<\x10s\xd0\xe2\xd3AK\ -\x16\x0b\x1d\x81\x13\x8cE`\x1eD\xdc\x0a\xc6\xd3\xb0\xb8\ -\x9a\xf2\x94\x1f\xd1\x91\xb3\x16&GM<\x08\x18\x90\xde\ -\x0c\x00\x7f\xa7\xc9\xd1\x88n\xea\x08\xe3\x1eS\x04\x1a\x1d\ -\xee.\x9c\x22Ge\x8c\xa3\x00\xe8\x1e;w \x8a\x1b\ -\xec\x83\xf4\xe3\xc8/\xd0O\xaa\x9fa\xd58\x00\x9c\xcd\ -4\xff\xc1|I2\xce\x8cM\x93($\xf24\x89\x94\ -\x19\x1a\xca\xf4pg\xf92;$\x09\xc4|I\x96\xbc\ -#@I\x8e\xbb\x07\xc7\xdd\x93\xc9\xf2\xe1x\xf8p\xbc\ -X\xc0\xbf[\xb6\x94\xcbK\xc7\x15\xccda\xb8\x9c'\x13H\x15\x02\x89\x98\x89\ -\xd2\xdcdI\x86\x22\xc0\xc9\xc9\x90\xa9\x05\xb5]\x22i\ -\xb5 \xb1\xdc\x95\xb0\xd1\x95'\x11\xb9es\xa5n,\ -Ww\xb7\xba*\xf1y\xd5u\xa4\x192!\xa1\x1a\x9f\ -\xe7\x86\x0bq\x11.V\xc8a=V\x9d\xf5\xa4\x9a\xb6\ -\xab[du\xf6[\x05Cmcb\xde\xad\xafHT\ -gM\xb9\x22\x9f\xef\xc3\xe6\xe1P\x0b\x1cOv\ -\xf1\xf3\xf3rwa\xb3y\x9e.\xbe\xc9\x1e\xde\xc9\xc9\ -\x1e8\xd7\xdd\xc3\x8bh\xcb\xda\xd5\xdf`\xad\x91\xaef\ -M\x98\xca\xf3\xf4\xc0}\xfd\xd8.)\xfc\x14\x96\x8b\xb7\ -\x9f\x17\xdf\xc5\xcf;\xc5\xcf\x85\xeb\xe5\xc3\xf2e\xf9&\ -\xfbp\xb9\xbe\x1a\xd6Z\xd5\xdf`\xdd[&\x80\xa31\ -W\xd8H\x11u\xb0yCT\x94\x00ynD\x1dm\ -\x1b\x8f\x0f\x7f[\xdb\x12\xe3\xa6\x94+\x93\xe3hT\x08\ -p\xd2\x0c\x0bNoT@u\x88\xd1\x85\xc3\xe5\xa1\x11\ -7\x90G\x9c\xf8\xb0\xc1kQ\xdf^M\xf0f\x03\xd6\ -\xcf\x05oT\x7f\xbb\x8c\xac4\x5c\xfc\xae\x01K\xab\xd4\ -\xdb\x99\xc8%)\x8a,\xae\x0c\x0fN\x85\x9e\xae\xcfh\ -QW\xb57\xfc]\xe7y\xa1\x93\x86\x90s3\x1b\xd7\ -\x0c\x9e)\xbe>\xc98\xcb\xc7\x85\xcd\xe7y\xb8p\xd9\ -^\xb0\x05\x90\x0f}\xbdY\x9e\x9e\xbe\x1e\x5c/\x16\x8b\ -\xdf\xb8f\x80m\xc0\xd2\x1a\xad\x9b\xae\x19j\xd8\xf3\xd2\ -\xb8\xe2T\x9c\x1f\xe8\xa6\xa9\xa8!|I-W\xbf\x11\ -\xb0\x91-\xe7\xf3\xdfj9\x15\xb5\xf6\x98\xa8\x19g_\ -\x1bCUE\xb5\x96\x99\xaa5\xac\x9bz\x11\x0b\xd7\xcf\ -n\xd5\x0b\xe8\xba\x14\xd6=H!\xa4\x10R\x08)\x84\ -\x14B\x0a!\x85\x90BH!\xa4\x10R\x08)\x84\x14\ -B\x0a!\x85\x90BH!\xa4\x10R\x08)\x84\x14B\ -\x0a!\x85\x90BH!\xa4\x10R\x08)\x84\x14B\x0a\ -!\x85\x90BH!\xa4\x10R\x08)\x84\x14B\x0a!\ -\x85\x90BH!\xa4\x10R\x08)\x84\x14B\x0a\xd1\xb1\ -\x10\xc3\x9a-\xa9\xb8\x98\x1f\xe0\x94\xe5\xd4-\xd0\x01\x1b\ -\x00\xa8\xf6\xed\x22\x1d(\x80\xd8`\xcb\x0e\x89\x8e\xa1\xb5\ -#v\xc3\x9a\xfdz\xbeb\xf4\xfa\xfcC\x06z\xd2\xcc\ -\xad\xdb\xf4\x8e\xf5\x22\xf28D^\x01\xca\xd7\xec'\x06\ -FR\x99@\xac\xe8\x9d\xa1\x90f(`\x12m\xec\x05\ -\xb1rE|\xb2D\x22$JD\x8b\x158.\xce\x10\ -i\xe2\xe8?T(C\xe9fD\xddxA6*\x11\ -\x22P\xa0:5\x8f\xf0\x85\ -\xca6\x8a:E\xa9\x95rW\xe9\xa8\xf6\xb5\x0b\x91\xa2\ -\x13\xfe\xb0%(\xfa\xea^A\xb4\x0d%H\x15\xd4u\ -\x1dk\xb7\x0c\xcd\x0e\xc5\xa8\xde\xd5\x96\xab0T\x1dT\ -\xdey\x13\xda4\xed\xb2u\x16\xd0\xa0fp\x03\xe2\x0c\ -\xa1Pe\x10\xa0'K2\xc4|\xf9kc\x0bO\xc1\ -\xd2\xa8\x89NH\xad\x93\x01\xbcv\xd6\x80\x90\x9a\xb3\x8b\ -P#\xae\xe6\xe4Ai\xba\x5c(\xe0\xe1\xf2DaO\ -t\xfac\xb5\xe4\xe8\x11y0b\x01\x03\x83HD\x87\ -i\xf1f\xa4\xca$\x19\xd2Z$\xba\x84\xd8\x97\xab\x19\ -\xd9\xc3\xe3Q%\xd5^]\x986\xe1f($\x91\xb8\ -\x18\x97\xa1}\xb2\x84\xf6#\xa4\x9a\x89\xc9PU\x18Q\ -PN\xb4(\x95\xf9\x09\xec\xa7f\xc8\x84\xb5\xa67\xc2\ -\xf9\xb5)1\xf2\xd4\xdaS \x9d+T$pSk\ -\xd1Ly8\xac\x87g+\xa2\xe5Q\x091=5\x83\ -\xac\xbe\x86\x5c\xab\xb0A\x9aD\x96\x13,\x14\xa4j<\ -\xd5Le|\x94\x86\x8c\xbc\xcb\xc7S\xb8\x19\xc4(k\ -\x90\x89\xcb\x14u\x14O\xd4\x90k\x177JN%\xf6\ -\xd1k9\xd7\x5cU!$\xb2:\x03\xa9\xd1K\x22F\ -\xff\x06\x0a\x89\x14N\xa5r\x5c\xdbq\x86B\xe8\xc87\ -\xa8\xc6\xc9\xc4p\xfd\x06\xddH\x86\x06\xe5\xd7\xc8\xc4\x19\ -\xd4AU\x0f\x06J\xb7\x22PC\xb7\x22\xa2\xa8\x09U\ -g\xa51\x91\xdc\xa9v\xd1PU\xc0`\x17@g\x02\ -m\x01h\x010\xe5\xef\xca\xc7\xc0\x98\xd8=9$4\ -\x06\xa6\x0b\x81)\x91\x02\xfcq\xa8\x9e\xf2:\x98\x04\x8c\ -\xf5\xf5\xf5\x0d\xf4\x8d\x0d\x0c\x8c\xcd\x8d\x0c\x8d\xcc\xad\x9b\ -\x19\x1b7\xb3naiimi\xd9\xc2\xdc\x98\x80\xfa\ -\xafn`&FF&\xa6&f\xa6\xa6fV\xa6\xa6\ -\xa6V\xe8`j\xa5\xaab^\x1f\x06\xca\x9f\x81\xb9>\ -T~(\x15s\x02\x14s\x8cj\x8e)\xff\x82\x86\xd2\ -\x95\xc7\xb1nPK=\x8c\x80\xdaqT\x80Qhz\ -t\x86\xbe\x81\xa1\x11\xf6z&\x06(TM\xa6\x19\xc0\ -h\x18\x95B\xa3\xe81\xe8\xfazTcO\x98iN\ -\xa5\xb5\xb6`\xe9\x05\xf7\xe1Z:\x0d\x1f\xefA\xb7\x9a\ -\xb3r{H\x9b\xb6\xd6qG\x92=\xbdd\x13.\x84\ -2\xda\xe5\xc6\x17\xddz\xca\x93{\xdb\xac\xda1\xb1}\ -\xd8\xdc\x04~\xf8\xd1\xd5\x0a\x9f\xe6\x17\xfb\xde\xc6\x9f\xed\ -\x9ct\xecR\xc6\x9d\xe7\x11\xce\xf3\xd6|\xbd\xeb\xbb\xe3\ -\x97\xff\xf7\xe2\xfb\xdd'\xae\x14\x14'\xa6dN\x9e\xbf\ -v\xcf\xc9\xabwK|#\x93R\xb3\xa6,X\xb77\ -\xff\xda\xbdRs@\xa1@mi\x84N\x0c\xba\x9e7\ -\xa1Bk\x96\x05\x0dj0\xdc\xc9R\xcfc\xfc\x1c+\ -\xa4\xc1\x91\xb8\x0bE\x9em\x93o\xc9&\xe4\x86\xc6[\ -\xf3\xe4^O\xdb\xd1\x91\x02\x8c\xf6\xdeG/B%V\ -7\xe7\x87\xf7\xf5Q\xe0\xb7\xabUx\xbb\x06\xce5*\ -(\xff\x04\xc6TB\xa69\xe8\x06\x8a\x13r\xa3\xdbu\ -l\x9b\x1b\xdd=\xbamn\x5cnt\xdbyk\xd4\x84\ -\xde\xca\xdf\x8a\xfb\x1a\x89\xf0\xbey\x8e\x0a\xc3a6\x89\ -g\xfa\xf5{\xba\x7f\xdd\x8e\xeei\x17\xae\xb4?\xeaj\ -vq\xf4\x9a\xcc\xb2- \xd8\xc2x\xe2\x91~\xe5\xd9\ -n+\x0a%\x07\x0e;\xde\xa98\xbd}\xa7(\xbf\xe4\ -\xa5\xcf\x98\x07\x8f\x8b\xa2{\x9df\x1aph\xcdSn\ -\xffp\xe4\x87Q\xbb\x95`C\x7f\xdf\x82A#\x16\x1c\ -\xec\xf5\xabC\xeb\xb6\xebD\xfb\xf7ms\xef\xd2*\xa0\ -\xdb\xc39\xe3iQ\x97]G\xd8\xcc\xd8\xb4\xde#_\ -\xf0\xd7\xbaI\xf3\x0a\xd7l\xba}7i\xb6W\xc9\x8f\ -\xb2\x7f\x0a\x13-\x08\xcd\x94@y\x81\xd0\xd7\xfb\xb9G\ -^\xf8\xf0\xd5\xcb\x1e\xdb]\xaaJ\xecx\xc5\xd2\xe9\xde\ - \xf9\xb2\x91K\xfd\xa7\xf0\xbd\xe6}\xbfn\xe2`\xeb\ -\x19\x17V^m\xb6\xa6\xd5\x86\xbeO\x8bF\x8f\x92\xf3\ -z\xfa\xb3\xc75\xa3\x85l\xb3\xb9\x90\x9a\x19\xb0\xa1\xa3\ -\xebH\xbb\xb3\xebv\x8f\xf3^\xe5egJ\xd9\xfa\xed\ -\x933\x07z,\xbe\xb6\x0f\xdb:\xee\xe7\xaf;\x17\x89\ -W\xe6\xfd= \xec\xe4\x94\x97\xdft\xa4:\xdee\xfb\ -\xadu`wNm\xd6q\xbf\xf5\xbf\xdf\x7f[\x11Z\ -\xb69\xa1\xe7\xc8\xa51\xbff?\xcax\xde\xf2b\xfc\ -\x8fP\xadu\xca\x8b\x84R\xec\x11\x0a\xce\xf4%\x97^\ -\xf4\xda\x12\x18\xd5Y\xeel\xbb\xc8\xfaq\xe6\xccV\xe1\ -\x7f\xeb%_\x8f\x7f8\x82w\xdc,w\xa9\xe9\xdc\xa1\ -]F\x0f:r#\x90\x11\x9e\xeel\xf3\xe3\xe4c\xbb\ -\xa4\x15\xae\x0e_O\xef;k\xc3\xadG\xee7w=\ -|8o\xdf\x98\xd96]\x0fKs\x97\xfc\xfb\xf4q\ -\xfe\x98k\xdfveK\x13\x96/\x10\xcd3\x1cR8\ -\xb1\xf5_/\x1em\xfd_\xb1q\xd2\xd5~\xf6\x0f\xcf\ -\xcf\x9c\xa8\x04mwZ\xc4\xcd\xd9\xde\xc1\xf7\xc6\xd5Y\ -\xab\xbc\x87?\x0b\xfe\x8a\xed}\xf1\x17l}\xe1\xf25\ -\x85\xcfr\xf3`+v\x1f\xab\xbc\xa4jb\xc3\xaa\x9c\ -')\xd7fM\x9c\xd2\xda\xba\xed\xbc;C\xc6\x8f\x8e\ -\x18\x10\x10\x91\xbd\xb7lw\xe2 \x8b\xe9\x9b\xb6(A\ -\xf4\xb7Y\xc7)\xb9\xcbF\xf7_M\xa9\xec\xb9/G\ -\xf84\xabh\xd85Q\xc6\xce\xfb\xdb\xb7\x94\x01\xab\xdc\ -\xf8Es/\x19\xd9\x1f\x980\x88z\xe3\xd2\xf9\x13\x1b\ -\xbfo~=\xb4\xd4=\x7fzo\xc6\xed\xbd\xdf\xf5\xdc\ -L\x1f\x9c\xb5\xf3\xf7W\xf7\xb6GG\x0f\xdf\xd1\x7f\xf6\ -\xaf\xbf\x9aE\xccdl\x8f\x88]\xbb6\xbe\xdf\x96\x89\ -\xc1e\xe5\x1b\xd6\xacS^~W_\xfbC5\x9e\xb5\ -&\xce\xd8A\x80Xy\xa0\x8f \x05\x03>\xbc\x18J\ -\x86\x0bC&\xbc4J\x83q\x05\x0cr\x22\x86.\x83\ -\x9a\xbf\xa7\x04\x13\x84\xc2\x1f\x13.\xc7\xdc\x01\x0b\xf8\xaa\ -\x07F\xe3\xa8\x9e\x02\xb1\x84\x02\x17\x0b\x22x\xfd\x81\xbe\ -\x81\xd2\xaf\xff\x00&\xe3\x1c\x5c,\x18\xc05\x0a\x9c\x16\ -\xb9<\xb94&>\x22\x81\x98D\xc3C\x99\xe8C)\ -\xa0\x16J\xae\xaa\xa6\xa1K.Q\xb1L&h\x18\xcc\ -yR\x19\x9cd\xb0X\x18\xf7\xe4\xe3r8-c\x93\ -`\x5c\x98\xa5\x90\x22:\x1a\xe3\xad\x92\xd3Q\x9c\x82F\ -w+\x19T\x10\xc6[\xa0x\xaa*\xde\x85(\xa3\x8a\ -\x07\xa18_$\x86\xcb\x01\x0a\xd2Y\xca\x17\xf1Q\x1c\ -}\x11jjf\x06Z&P{\xc2\xf8\xe4L\x01\x9e\ -\x05\xe3\x97a\xbc\xad0C$\x80q\xb4\x02\xb5\x12\xe1\ -\x5c\xb8t!\xe6\x8f\xb6\x0a\x9c\x97\x06\xe3h\x05h,\ -K\x88\x83W24\x7f8\x07\x1b\xa7j\xc5\x93\xb5\xe2\ -\x0a81#\xa3B%\xd2\x11\xc4\x0c\xc6\xec\xc0\xeb\xc8\ -d\xf9\xf9\xb1\x99Qx\x96\x10W(\x5cb\xe1\x05;\ -W\xc6g\x86JDR\xae\x18\xae\xefU6\x13\xb0x\ -\xe3#4Z\x8ezgf=\x81\xdaV\x15{\xde\x87\ -h3\xcc\xe6l\x0d\xad\xaer\x92Up~\x85\xab}\ -\xea\xec\x1aZ\xf2\x22\x00\xf6~\x0d@\x8b?khm\ -W\xc0>\x0a\xdbm\xcfy-{lP\x7f\xd1\xfa\xf8\ -\x94\x00\xe7\xb9\x22\x87V\xe3\xbd\x05\xea\x01-y\xae\x88\ -]\xb5{\x98a\xaa\x15\x0c\x13\xf9\x8d\x07\xd7)\x192\ -&\xbc\xfe\xe2\xe1L\x97\xd7;\xf1\x07W\xac[\x8f.\ -qx\x0a\x8e\xae\xf3pf\x22\xece\xf02\x156\xb7\ -\x98/ \xbe\xa3%\x10\xbf\xad\x11?\xb0\xdakP\xf5\ -k\x08\xcb5\xaf\x80\xd5\x10W`v\xde\x0aP\x1f\x9f\ -\x054K#@\x1d\xb8\x0c\xe6`\xd5\xed\xd6\xd3 \x11\ -\xa03/\xa9\xd5=U\xbf'P\xc7\xe5\x04e\x16:\ -\xc8\x05\xc4\x22\x1a\x84\xc6%0y\x19\xb2LU\x1e\xb1\ -n\xd6\x83\xd7\x88\xcd\x80\x15\xb0\x85\xd7\xb3m@\x07x\ -u\xe7\x01\x07\x99\xae \x08\x84\x83\xee\xa07\xbc\xbe\xed\ -\x0f\x06\xc3+\xda4 \x82W\xb7Y`\x14\x18\x0f&\ -\x83\xe9`6\xf8\x0e,\x06\xcb\xc1\x1a\xb0\x01l\x05;\ -\xc0^\xf0#8\x02N\x823\xe07p\x05\x5c\x077\ -A\x01\xf8\x17\x14\x81\x12P\x09\x172\x0c\xcc\x04\xb3\xc4\ -l\xb1VX;\xac3\xe6\x81\xb1\xb1@,\x1c\xeb\x89\ -\xc5a\xfd\xb1\xa1X*&\xc62\xb0Q\xd8Dl:\ -\x96\x8b-\xc6Vb\x1b\xb0\xed\xd8~\xec\x08v\x1a\xbb\ -\x80\xfd\x81\xdd\xc2\x1e`\xcf\xb0\x0a\x0a\x95bL\xb1\xa2\ -\xb4\xa4\xb4\xa7\xb8Q\xd8\x94`J\x0fJ\x02e\x10%\ -\x952\x9c\x92C\x99D\x99IYHYE\xd9L\xd9\ -C9B9C\xb9B\xb9I\xf9\x97RL\x05T#\ -\xaa\x0d\xb55\xd5\x85\xca\xa6\x86R{S\x07PS\xa8\ -2\xea\x18\xea4\xea|\xea*\xeaV\xea\x01j>\xf5\ -\x12\xf5&\xf5\x11\xb5\x9cF\xa7Y\xd2\x984\x17ZW\ -Z\x14\xad/\x8dG\x1bN\x1bC\x9bA[L[O\ -\xdbC;N\xbbD\xbbE+\xa2\xbd\xd23\xd1s\xd0\ -\xeb\xac\xc7\xd1\x8b\xd6\xeb\xa7\x97\xaa\x97\xa57Yo\xbe\ -\xdeZ\xbd\xddz'\xf4\xae\xe8\x15\xe8\x95\xd0\xe9t\x1b\ -\xba3\xdd\x97\x1eE\xefO\x1fF\x1fI\x9fA_J\ -\xdfF\xff\x99~\x81~\x87^\xcc`0l\x19\x9d\x19\ -\x01\x8c\xde\x0c.C\xc1\x98\xccX\xc4\xd8\xcc8\xcc\xb8\ -\xc8(`\x94\xe9\x1b\xe9\xb7\xd2\xf7\xd0\x8f\xd0\x1f\xa0/\ -\xd6\x9f\xa0?_\x7f\xa3\xfe!\xfd\x8b\xfa\xf7\xf4+\x0d\ -\xcc\x0c\xda\x19p\x0cz\x1b\xf0\x0dF\x18\xcc2Xc\ -p\xc0\xe0\xbcA\x81A\xa5\xa1\xb9\xa1\xb3a\x80a\x82\ -\xe10\xc3\xf1\x86\x0b\x0d\xb7\x1a\x9e0\xbca\xf8\xdc\xc8\ -\xc8\xc8\xc9\xc8\xcf\xa8\x8f\x91\xc0h\x9c\xd1B\xa3\x1f\x8c\ -N\x19\xdd2*7\xb60\xeed\x1cj<\xd08\xc3\ -x\xa6\xf1:\xe3\x9f\x8d\xff0~nbb\xd2\xde$\ -\xc8d\x80\x89\xc2d\xa6\xc9\x06\x93c&\x7f\x9b\x94\x99\ -Z\x9a\xba\x9aF\x9b\xf2M\xc7\x9a\xe6\x99\xee1\xbdh\ -Z\xd8\xcc\xa0Y\xbbf\xc1\xcd\x067\xcbi6\xbf\xd9\ -\xcef\xe7\x9b=230ko\x16j\xc65\x1bc\ -\x96g\xb6\xdf\xec\x9aY\xb1\xb9\xa59\xcb\xbc\xb7\xb9\xc8\ -|\x86\xf9F\xf3\xd3\xe6\xf7-\x18\x16\xed-\xc2-\xf8\ -\x16\x93,V[\x1c\xb3\xb8cI\xb5lc\x19j\xc9\ -\xb3\x9ch\xb9\xc6\xf2\x84e\x81\x15\xdd\xca\xd9*\xdaj\ -\x98\xd5t\xab-V\xe7\xac\x8a\xac-\xac\xbd\xac\x13\xad\ -\xb3\xad\xf3\xac\x7f\xb2\xbeiC\xb5io\x13m#\xb4\ -\x99e\xb3\xc3\xe6\xaaME\xf3\x96\xcd\x83\x9b\xe3\xcd\xbf\ -i\xbe\xb5\xf9\xc5\xe6\xa5-\xec[\x04\xb5\xc0[Lk\ -\xb1\xad\xc5\x95\x16\x15\xb6L\xdbp\xdbt\xdb9\xb6{\ -m\xff\xb2\xa3\xd9u\xb2\xebc\x97e\xb7\xcc\xee\x84\xdd\ -#{+\xfb\xae\xf6<\xfbi\xf6;\xec\xfft\xa08\ -tr\x88s\x18\xe9\xb0\xda\xe1\xacCqK\xc7\x96\x91\ --\xa5-\x17\xb5<\xd6\xf2\x91\xa3\x8dc\x90\xe30\xc7\ -y\x8e\x87\x1c\x1f\xb4\xb2l\x15\xd8J\xd0j^\xab\xc3\ -\xad\x1e2\xad\x99\xc1L!s!\xf38\xb3\xa8\xb5C\ -\xeb\xa8\xd6\x19\xadW\xb6>\xd7\xba\xd2\xc9\xd9\xa9\xaf\xd3\ -\x04\xa7mN\x7f\xb51l\xc3n\x93\xd2f^\x9b\xa3\ -m\x8a\xda\xb6j\x1b\xd3vT\xdbMm\xfflg\xd0\ -\x8e\xdd.\xad\xdd\x82v\xf9\xedJ\xdb;\xb7Oj?\ -\xa5\xfd\xde\xf6\xf7\x9d[8G;\xe78or\xbe\xd1\ -\xc1\xa4C\xb7\x0e\xc3;\xac\xeap\xb9#\xbd#\xbbc\ -z\xc7\xa5\x1d\x7f\xebD\xe9\xe4\xdd)\xadS^\xa7\xf3\ -\x9d)\x9d}:\x0b:/\xed|\xa1\x8b^\x17\xbf.\ -\xe2.\xab\xba\x5cs1v\x09v\xc9t\xd9\xe4r\xcb\ -\xd5\xc6\xb5\xa7\xeb\x04\xd7\xbd\xae\x85nm\xdd\x06\xb8\xcd\ -q\xcbw{\xe5\xee\xed.t_\xe3~\x9de\xc1\xea\ -\xce\x9a\xc0:\xc0z\xe6\xd1\xc9\x83\xe7\x91\xe7q\xd9\xd3\ -\xc43\xc2s\xac\xe7>\xcf\xa7^\x9d\xbdp\xafe^\ -\xbf{[z\xc7xO\xf1>\xea\xfd\xd2\xc7\xd7G\xe6\ -\xb3\xd5\xe7\x81o[\xdf\xa1\xbeK|\xaf\xb1\xad\xd8\xb1\ -\xec\x19\xecS~z~!~c\xfd~\xf4+\xe7\xf8\ -p\x14\x9c\x1d\x9c']]\xba\xa6w\xdd\xd8\xf5\xbe\xbf\ -\xb3?\xee\xbf\xc6\xffN\x80S\x007`e\xc0\xcd@\ -f\xe0\xd0\xc0\x15\x817\xbb\xb5\xee\xc6\xed\xb6\xaa\xdb\xed\ -\xa06A\xfc\xa0\xb5A\xf7\x82;\x06\x0f\x0b\xde\x1c\x5c\ -\x18\xe2\x1e\x22\x0b\xd9\x1dR\x1a\xca\x09\x1d\x1d\xfas\x18\ -5,2lZ\xd8\xb9p\x8b\xf0\xbe\xe1\x8b\xc3\xff\x8e\ -p\x8aH\x8d\xd8\x14Q\x14\xe9\x1d92\xf2\xe7(\xbd\ -\xa8\x1eQs\xa2\xaeE\xb7\x8c\xe6Eo\x88.\xea\xee\ -\xdb}t\xf7\xe3=\x8c{\xc4\xf7X\xdc\xe3v\xcfN\ -=e=\x0f\xc4Pb\xba\xc7\xcc\x8d\xb9\xd1\xab]/\ -q\xaf\xbd\xbdA\xef\xe8\xdes{\xff\x15\xeb\x1c;<\ -\xf6`\x1fz\x9f\xd8>y}\xee\xc6\xb1\xe2F\xc5\xe5\ -\xc7[\xc6\x0f\x89\xdf\x18_\x92\x10\x920+\xe1z\xdf\ -\x0e}3\xfa\x1eMl\x9680qCbiRX\ -Rn\xd2\xcd~n\xfdF\xf7;\xd3\xdf\xae\xbf\xa0\xff\ -\xbe\x01\x8c\x01\x89\x03\xd6\x0e(\xfe*\xfc\xab\xef\xbe*\ -\x18\xe8=p\xf2\xc0\xab\x83\x9c\x07e\x0f:=\xd8n\ -\xb0p\xf0OC\x9a\x0d\xe1\x0e\xd99Toh\xd2\xd0\ -\x8dC\xab\xb8\xbd\xb9\xab\xb8\xc5\xc9\xd1\xc9K\x92\x8bx\ -\xa1\xbc\x05\xbc\x7f\xf9A\xfcy\xfc\x07x\x00\x9e\x8b\xdf\ -K\x09H\xc9M\xb9\x9f\x1a\x90:7\xf5AZ\xb7\xb4\ -\xf9i\x8f\x04\xa1\x82\xc5\x82\xa7\xc3\xa2\x86-\x1fV\x9a\ -\xde;}]\xbaR\x98$\xdc&\xd2\x17\x0d\x15\xed\x17\ -[\x88\xd3\xc5\xc7%\x8e\x92l\xc9\x05ig\xe9d\xe9\ -\xcd\xe1\x9c\xe1\xdf\x0d/\x92\xf5\x90\xad\x95c\xf2A\xf2\ -}\x0a+\xb8\x98:\x9b\xd1!\xe3\xeb\x8c[\x99\x81\x99\ -y\x99eY\x89Y;\xb3\xcd\xb3\xc5\xd9gGt\x1a\ -\xf1\xcd\x88{9\x119\xdf\x8f\xa4\x8d\xe4\x8d<:\xaa\ -\xf5\xa8\xf1\xa3n\x8d\x0e\x1e\xbdr\x0c6&y\xcc\xd1\ -\xb1m\xc6N\x1a[0.r\xdc\xfa\xf1\x86\xe3\xd3\xc7\ -\xff:\xc1}B\xee\x84\x17\x13\x93&\x1e\x98\xd4r\xd2\ -\xb8Iw\xbe\x8e\xfcz\xd3d\xd3\xc9\xb2\xc9\xd7\xa6t\ -\x9d\xb2|*m\xaa`\xea\xb9o<\xbfY\xf4\xcd\xab\ -i\xfci\xbfLw\x9f>\x7fz\xd5\x0c\xde\x8c_\xbe\ -e}\xbb\xf0[\xe5\xcc\x94\x99\xe7f\xf9\xccZ6\x9b\ ->[<\xfb\xea\x9cns\xd6\xe7\x9a\xe7\xe6\xe4\xde\x99\ -\x1b3w\xcf<\xe6\xbci\xf3^|7\xe4\xbb\xd3\xf3\ -\xbd\xe6/_`\xb8 c\xc1\xcd\x85=\x17\xee[\xd4\ -v\xd1\xecEU\x8b\xd3\x16_\xc9\x0b\xc9\xdb\xb6\xc4a\ -\xc97KJ\x97\xf2\x97^\x5c\x16\xb4l\xeb\xf2\x96\xcb\ -\xa7/\xafX!X\xf1\xfb\xca\xc8\x95{V\xb5_5\ -\x7f5}u\xe6\xea\xbbk\x12\xd7\xe4\x7f\xcf\xfe~\xc3\ -Z\xbb\xb5\xd3\xd7\xbe\x5c'^ws}\xdc\xfa\xe3\x1b\ -|7l\xd8\xe8\xb0q\xd6&\xca\xa6\x8cM\x0f6\x0f\ -\xdc\xfc\xdb\x96\xb0-\xfb\xb6\xbal]\xb9\xcdf\xdb\xf4\ -\x1f\xc0\x0f\x19?<\xdc>t\xfb\xd5\x1d=v\x1c\xdd\ -\xc9\xde\xb9uW\xbb]Kv[\xee\x9e\xb6\x07\xdb3\ -bO\xd1\xde\xb4\xbd7\xf7\xf5\xdfwa\x7f\xf7\xfdG\ -\x0ft=\xb0\xfb\xa0\xeb\xc1u?\xb6\xfe1\xef'\xeb\ -\x9ff\x1d2<4\xe9\x90\xf2p\xce\xe1\xe2\x9f\xa5?\ -?:\x92z\xe4\xce\xd1!G\xaf\x1f\xebw\xec\xf2\xf1\ ->\xc7\xcf\x9d\xe8q\xe2\xd4\xc9\x88\x93\xc7\xf2\x83\xf3\x0f\ -\x9f\x0a8\xf5\xe3i\xce\xe9\xfd\xbf\xb0\x7f\xd9{\xc6\xe7\ -\xcc\x9e\xb3\xdegw\xff\xea\xfd\xeb\xees>\xe7\xf6\x9c\ -\xf7=\xbf\xef7\xbf\xdf\x0e\x5c\xf0\xbfp\xe8b\xb7\x8b\ -G.\x85]:y9\xfa\xf2\x99+\xbd\xae\x5c\xb8\xda\ -\xf7\xea\xef\xd7\x06^\xbb\xf9;\xff\xf7\xfb\x7f\x08\xffx\ -\xfag\xe6\x9f\x95\xd7\xc7\xdd\xd0\xbb1\xed/\xb3\xbf\xe6\ -\xff\xed\xf0\xf7\xaa\x7f:\xfe\xb3\xed\xa6\xcf\xcd\x9fn\x85\ -\xdd:{;\xfe\xf6\xf5;\xbc;\xff\xfeO\xfe\xbf\xaa\ -\x82IwM\xee\xce\xbf\xd7\xea\xde\x86\xfb\x1e\xf7\x7f|\ -\x10\xf1\xe0\xb7\x87_=,\xf8W\xfao\xe5\xa3\xc9\x8f\ -\xcd\x1f/)\xecP\xb8\xebI\xd0\x93\xb3E\xfd\x8a\x0a\ -\x9e\xca\x9e*\x9f\xcdxn\xfb|\xdd\x0b\xaf\x17G\x8b\ -c\x8b\xff.\x11\x95T\x96N+\xb3-[_\xce.\ -\xcf\xafH\xaa\xb8W\x99U\xc5\xa8Z\xf8\xb2\xe3\xcb\x03\ -\xafz\xbc\xba\xa1\x14U\xdf\x8f&A\x82\x04\x09\x12$\ -H\x90 A\x82\x04\x09\x12$H\x90 A\x82\x04\x09\ -\x12$H\x90 A\x82\x84\x1a\xb1\xb1\xb1\xfc\x9c\x9c\x9c\ -\x85zzz\xf4\xf7\x97&\xa1K\xb8\xba\xba\xfa\xe5\xe7\ -\xe7\x97\x9f={V\xb9l\xd9\xb2\x13VVV\xb6M\ -\xad\xd3\xff\x17\xd8\xdb\xdb;\x1d>|\xf8\x09\xf2\xbd&\ -\xec\xdd\xbb\xb7\x00\xb5IS\xeb\xf6_\x07\x1ak\x0e\x1e\ -<\xf8P\xdb\xf7\x9ap\xf2\xe4\xc9\xb2\xb8\xb8\xb8\x94\xa6\ -\xd6\xf1\xbf\x8cE\x8b\x16\x1d\xae\xcb\xf7\xda\x01\xce\x09\x8b\ -\xe8t:\xa3\xb1\xb2\xac\xad\xad\xed\xc2\xc2\xc2\xfa\x0a\x85\ -\xc2)s\xe7\xce\xdd\xb7q\xe3\xc6+\xfb\xf6\xed\xbb\x0b\ -\xdb\xb9\x14\x05\x14\xdf\xb4i\xd3\xd5y\xf3\xe6\xed\x17\x89\ -DS\xc3\xc3\xc3\x13Q\x1d]\xd8\xf99\x22))I\ -\xf4>\xdfk\x02\x9a\x13>\xc4\x17666\xf6C\x86\ -\x0c\xc9Z\xbe|y\xfe\x993g^\xd5W\x9e&\xa0\ -:+W\xae<=t\xe8\xd0\xec\xe6\xcd\x9b\xb7\xfc\x18\ -~h*\x8c\x1c9rqC|\xa1\x9e\x138\xf5\xe1\ -\xed\xe2\xe2\xc2\x9e\x16X,V\xc0\x81\x03\x07\xee7\xc4\xfe\xd7\xe7\ -\x044\x8f\xa31\xe2\xd8\xb1c/>\xb6\xef5\xe1\xf8\ -\xf1\xe3\xc5\xc9\xc9\xc99\xba\x98\x9b\x9a\x1a\xa8\xdf\xa2q\ -\xb6!\xf6k\xe6\x046\x9b\x1d\xb1u\xeb\xd6?>\x95\ -\xdf_\x0f\xdb\xb6m\xbb\xce\xe1p\xa2\x9a\xda\x87\x8d\x05\ -\xecG\xfac\xc6\x8cY\xd6\x10\xdb\x8f\x1e=\xfa\xbc\xa9\ -\xfc\xfez@k&\x0aDS\xfb\xb1\xb1h\xe8\x9c\xf0\ -9\x85\xdc\xdc\xdc\xbd&&&fM\xed\xc3\xc6\xe2C\ -\xe6\x84\xcf%\xa0\xf1\xc8\xc9\xc9\xa9sS\xfb\xb0\xb1\xf8\ -\x909\xe1s\x09h\x5c\xf4\xf5\xf5\x0doj\x1f6\x16\ -\xea9aiS\xfb\xf3C\x02\xba\xa6\xfe/\xb4\x01B\ -ff\xe6\x5c]\xf9\x05]\xc7)\x14\x8a9h\xcd\x02\ -\xc7\x89N\x86\x86\x86&0\x18;::\xb6\xdf\xb3g\ -\xcf\x1d]\xb7\x01Z\x9f5\xb5\xff\x1a\x03??\xbfH\ -dGc}\xb1s\xe7\xce\x9b!!!\xf1\xefZ\xa3\ -\xa0\xb1\xfbc\x9c\x07\xc8\x86O\xe93]\xa1S\xa7N\ -\xde\xe8:\xa7\xb1>@\xcfu\x18\x0c\x86\xc1\xfb\xe4}\ -\x0c\xff\xa3\x80l\x80\xb6x}\x0a\x9f\xe9\x0a\xe8\xfa~\ -\xff\xfe\xfd\xf7ta?\xba\xb7Y\x9f\xfb6\x1f\xcb\xff\ -( [\xbe\x94{xFFF\xa6\x1b6l\xb8\xa4\ -K\xfb\xd1\xf3\xb5\xb8\xb8\xb8\xd4w\xc9\xfd\x98\xfeGa\ -\xdd\xbau\x17\xd0|\xf3\xa9\xfc\xf8!@\xdfk\x9a=\ -{\xf6\xae\x8f\xe5\x03t\xdf\xf5m\xf7l>\xb6\xffQ\ -\x989s\xe6v\xadoR}v\xe0\xf1x\xa3>\xb6\ -\x0f\x96-[v\x12=\x1bx]\xf6\xa7\xf0?\x0a\xe8\ -\x99DS\xf8\xf6}pww\xf7\xff\xe5\x97_\xaa>\ -\x85\x0f\xd0\x9c\xe0\xe6\xe6\xd6U[\xfe\xa7\xf2?z\x96\ -\xd0\xa5K\x17\xdf\xa6\xf2s]@c>Z#6\xd6\ -\xb6\x86<\xe7BsB|||\xf5\x17\x7f>\x95\xff\ -Q\xd8\xbau\xeb\x9f\xfa\xfa\xfa\x86M\xe9sm\x0c\x1f\ ->\xfc[]\xd85q\xe2\xc45\x0d]7\x8d\x1a5\ -*\x0f\xcd\x09\x9f\xd2\xff(\xa4\xa6\xa6\x8eoj\xbf#\ -\xa0{\x86\xba\xba\x97\xec\xe9\xe9\x19\x84\xc6\xf6\x15+V\ -\x9cjH=\xf4\x8cx\xc7\x8e\x1d\xff|J\xff\x1f:\ -t\xa8\x10]{7\xb5\xff\x07\x0f\x1e\x9c\xa9\x0b{N\ -\x9c8QB\xa3\xd1\x88\x0f\x96\xa3\xfe\xd7\x86\xaelY\ -\xbat\xe9\xf1\xba\xf8\xa3u\xce\x87\xce\x09o\xd3y\xe1\ -\xc2\x85\x87t\xa1\xf3\xe6\xcd\x9b\xaf}<\xcf\xd6\x0fh\ -\xdc\xd0\x85-\xb3f\xcd\xda\xf96\x19\x1f:'\xd4u\ -\x9d\x800c\xc6\x8cm\xba\xd0\x19\xd9\xfe\xf1<[?\ -\xe8j\xdeC\xd7U\xef\x92\x83\xfa3\xea\xd7\x0d\xe1Y\ -\xd7u\x02B^^\xdeQ]\xe8\x0cm\xff\xfb\xe3y\ -\xb6~\x98?\x7f\xfeA]\xd8\xb2}\xfb\xf6\xbf\xea#\ -\x0f\xad\xf95\xef[\xd7'\xa09\x01\xcd#\xda\x058\x1cN\xb4.\xae\x0b\xb2\xb2\xb2\xbe\xfb\x90\xf7\ -\x0e\xd039\xf4\xeePc\xe5#\x1b\xbe\xd4=\x02\xdd\ -\xbbw\x1f\xa8\x8b6@\xeb\x9a\x9e={\x0e\xd1<\x1f\ -x\x17\xd0\xfa5&&f\xa8.\xde\xc1\x86\xba\xbfD\ -6|\x0a_},DFF\xf6\xd7\xd5\xf51z\xe6\ -\x84\xae{\xd0\xfeR\xb4O\x0f\xbdg\x8d\x02\x8a#\x1a\ -Z\x7f\xbd\xbe\x1f\xbc\xb1}\xbf\xb1\xf3\xd0\xe7\x80\xd0\xd0\ -\xd0\x84\xa6x>\xa5\xab\x80\xde\xe3\xfe\xdc\xd7=\xefC\ -PPP\xac.\xde\xc5m\xaa\x80\xf63|)\xeb\x9f\ -\xb7\xa1c\xc7\x8e\x9e\xe8\xfa\xaa\xa9}\xf9\xa1\x01\xcd)\ -\xe8=\xa7\xa6\xf6cc`fff\xb5`\xc1\x82\x9f\ -\x9a\xda\x97\x1f\x1a\xd0\xf3\x84/}N\xa0P(Tt\ -\xaf\xb3\xa9}\xa9\x09h\xbf}C\xaf\x19\xff\x0bs\x02\ -\xbaF\xf8\xd4\xefMi\x07\xf4\xce\x85\xbf\xbf\x7f\x0f\xa4\ -\x0b\xba\x97\x8f\xf6%7\xa4\xbezNphj?6\ -\x06M\xb1\xff\x1d\xc9\xaak\xff;J\xa3\xfd\xf9\x0d\xe1\ -\x85\xe6\x04\xb4\xe7\xb3\xa9\xfc\xa7+\xa0\xb5\xc5\xd7_\x7f\ -\xbd\xf6S\x8c5\xef\xeb\xb3\xe8;\x15\xe8{\x15\xf5\xe5\ -\x89\xe6\x04\xb4\xf7\xf9S\xf9\xeac\x02\xad\x91\xc6\x8f\x1f\ -\xbf\xb2!\xf6\xbf/\xa0\xfbp\x13&LX\xd5\x90}\ -D\xe8\xdeQC\xe7\x84\xcf\xf9\xdetCannn\ -\x8d\xbe3\x84\xd6J\x1fr\xed\x86\xea\xa0\xf7\xac\xfa\xf5\ -\xeb'\xb6\xb0\xb0\xb0\xf9\x10\x1d\x1a:' Y\xba\xf6\ -\xc3\xe7\x00SSSs4W\xa31\x1b}\xa3\x06=\ -w\xdf\xb2e\xcb\xefh\xec\x85\xe1\x01\x8a\xa3g\xeb\xdf\ -|\xf3\xcd&T\xa6k\xd7\xae\xddQ\x1d]\xc8F\xf3\ -S}\xee\xe3}N\xcf\x83\xff\x8b\xe8\xd3\xa7\x0f\xfe\xb6\ -1\x11\xb5\xfd\x97\xbe\x16\xfd\x12\x80\xbe\xeb\xf8\xfa\x9c\x80\ -\xdeM\xfd\xd2\xd7\xa0_\x12\xd0\xf7M5s\x02\x9a\xd7\ -\xffK\xdf4\xfbR\xa0\x99\x13\xd0w\x7f\x9bZ\x17\x12\ -$H\x90 A\x82\x04\x09\x12$H\x90 A\x82\x04\ -\x09\x12$H\x90 A\x82\x04\x09\x12$H\x90\xa8\x06\ -u\x05\x06\xa8\xf0\x1f\x83?\xb0\x82\x02hD\x1c\x80\xa1\ -+\xa85qU\xd1`\xbe$\x19g\xc6\xa6I\x14\x12\ -y\x9aD\xca\x0c\x93\xf02D\xb8X\xc1\x0c\xe3*\xb8\ -\xcc\x10\xa1\x84\x97\x0e\xd8!\xd111\x092\xe2=$\ -\x14\xef\xc9\x1d!\x03\xc0\xc0\x8f\xe0c\x01\x03\xdaI\x17\ -\x03C\x02\xa0)\x95\x00\xd0J\x09\xd6\x85D~!@\ -\xdf7/D\xf5\xc4\x12\x99H\x09\xf4\x91\x02\x9a\xf7\xed\ -;\x00\x80j\xbc?0\xe2\xd3\xb8R\x9c\xc9B|\x84\ -\x19b\xf4\xed\x19+\x18\x18 \x1e\xa4\x01.\x90\x02\x1c\ -0\x01K\xa5\x9fP,G{,irX\x85H\x8f\ -\x10\xa0g\xba\xc8r[\x94\xe6\x09\x93\x85(\x8d\xa9\xed\ -\x11\x88S\xb2\xd5\xf9D:]\x9c.\xd1N\x0b\xe5\xd2\ -\x94Zi\x9e\x10\xf1\xd7\xd7\xb8\x1b\xd1\xe4i\x22$\x03\ -\xed\xe9\xc3\x08\x19\x19r\x85:\x1b\xbd\x9fg\xa6\xf6:\ -\xac%\xc2\x15\x5c>t\xae\x9ab \xe4\x8e\xc0e\x09\ -\x02\x11\xce\x97d$\x07_m\x17Y\x94\xc4\xdaK\xf0\ -L\xc9\x96I\xd5uk\x03\x83\xb2\x0d\x8110\x02\xf6\ -\xa09\xb0\x86\xbf\xe6\xc0\x12\x963V\xffl\xe0\xcfZ\ -\xfd\xb3\x84\xa1\x05Q\xc2\x068T\xff\xec\x81\x1dA\xb1\ -\x84^D\xa5P\x8d\x16\xc0\xb6\x9a\x839\xa4\xb7Ps\ -\xb6\x87r\x8c\xa1<\xfd\x97\x80\xc2_H?\x02^\x01\ -\x9a_\xb9\xf2\x84\xedQ\xa0\x04\x98\xd3\x93WJ\xac\xc0\ -\xef\x18lf\xfa\xc3*%V\x96r\x1c\xeaw\xb8\x5c\ -\x89-b<\x05&v}\xa7\xec\xbbr\xb7\xb4\xf4\xee\ -\xd5\xfdS\x13\xed\xfe\x07\x80\xa8T\x89\x9d\xb0+\x06T\ -\xfb\xac\xfcW\xc5J\xea\xab\xd3\xd9-\xef\x01\xb0\xb8\x04\ -r\xe1\x94\x01\x0a{}\xe5\x13%\xa5r#\xe7\x01\xe4\ -\x98^Q\x8a8V\x02\xcca\xe3\x03%\xb6\xd9\xf1_\ -$2\xe0~\x89\x92\xbe\x88\x01\x00=\xfb\xc5=%\xa5\ -8\x87\xf1\x18\xea\x849\x9c.QRO\xd8E\xfcq\ -G\x89]\x8f*\x04/\x01\xa6\xbf\xacD\x09\x9e\xff\xa3\ -\xc4\xa6R\x8a\x00\xe4\x92^qY\x89\xed5{\x0a*\ -\x10\x17\x18\xbf\xde\xf9\x19(GUa\xfcy\xf8sP\ -\x06\xeb,\x85\xf1\xd2\xf0\x17\xa0\x04\x80\xb9O\x94\x8c\x82\ -9Q\x9dL\x8c\xdb\xdf)\x84\xd4\x88bP\x0a\xb0\xc8\ -\xd2\xa7J\xca\xcdxJ%\x00\xd7\x1fCjd\x09\xaa\ -\xe7]\xfcT\x89-4(\x87\xc4GJ\xac\xd8\xab\x14\ -1v\xbcW\xa4\xc4\xeer\x10\xf1_%v\xafe\x19\ -\x92lz\x09\xf2*O\xad\x80\xc4\x87J\xec\x82I9\ -R\x0d\xdb\x05\x0b,fTA\x22\xb4t;V\x01\x89\ -`\x14\x8c\x9e\xb4\x7f\x09i\xf7\x95 \xab\x02T\xc13\ -\xa7\xea>\xe4\xd8\xf5\x15A\xc3*}+\x91\x9d\xa67\ -\x9f*\xc1\xabR%\xad<\x0d\xd2\xef)\xb1?\x0d\xab\ - \x1d|\x0b\xa5\xaf\xb9W\xa2\xa4\xe41\xae\xdfU\x82\ -\xf1U\xc8Of\xcf\x8b\x94\x94 \xfbS\xd0\xe3\xf9\xff\ -\xdcUb\x85\xc6/!\x19d\x16)i%z\x80\xb1\ -\x04\xba\xac\xb2@\x09\x86\x13\xd4\xddEJp\x03J\x10\ -\xa0\x96\xa8\x18[\xee\x0c\xfe\x80\x94\x1dD\x1e\x8a\x1d\x87\ -*u\x85\x12\xb0<\x06\xd4\xf7\x10\xa4\x5c#\xf2J`\ -l'4K%\xc6\x1e\x9a\xb5\x0dRJ\x88\xbc\x7f`\ -\xec$\xf4\x03#\xaf\x04\x99\x02\xf5<\x0a)\x7f\x13y\ -\x07a\xec/\xe8\xcd\xb4r$O\xa0\x96\xb2\x9f\xc8\x9b\ -\x0a\xad)\xa5\xc3\xcc\xaewaK/a\xe8\x15\xc3\xac\ -I(\x0bkU\x05\xa3!\xb0m\xec\xf3!\xcfS\xf1\ -\xb0d\xb9\xddK\xe4\x82\x0d0cz\x89J\x18x\x01\ -\x13\xcb\x90g0\xa7g\xb0\xb5n\xd3\x8b\x91$\xe8\xaf\ -'PC\xa8\xe3`\x98\x9f\xf6\x02\x09\x80\xfeN\xaaD\ -M\xb0\x1c\x96\xbbe\x04i\xf6'\x1f*\xc1b\xd4,\ -\x98\xc19\xe8\xee5\xcf!\xd3\xc5\xb0\xa9\xcf2*P\ -\xab\xb6,\x80\xc4a\xcf\x00\x96Z\xfeD\x89\xfd\xcf\xbe\ -\x1c\xb5\xbf\xfb\xf3gJ\xec\x95\x0cR9O!\xa3g\ -ne\xa8\xabDW\xc1\xf8w&P\xb8\xe9B\x18\xab\ -\x8a*E\xddj \xa4R\xee\x0e\xd1+\x07\x14\xfa\xd0\ -\xfb\x90\xfer`\x09\xec\x84X\x7fh\x9bA\xe1\xb2D\ -\xb6\x83\x03;q\xf9\x13\xc8\xbcjX\x09\x80\x95\x13*\ -/)\xb1\xa5\x8c2\x00\xb5\x8b-\x85\xf1\xd3P(\xd4\ -\xca\xf3\x16\x8c\xdf\xf7\xaf\x00P\xac\xd5O0^1\xac\ -\x12<\x05\x18u:<\x13\xd6\x17\x94\xa0J/\xc1\x13\ -\xa8\xc7\xf5;J\xda\x8d\x1e\xc0\xee\x04\xa4\x9dvx\x85\ -\x06k\xd59\xf5\x22\x87\x01\xbd\xcaX\x04\xfd|?\x00\ -\x80G\xd0\xfc\xb5\xb0/\xaew\x80\x86\xa6\x94\x95*)\ -\x15\xe9\xe0!\xa0x\xae,\x83'k\xf9*\xd8\xd91\ -\x0ed\x0c\x16\xdf\x07Tk\xd1O\x95\xf0\xc4\xae<$\ -\xb6\x81\x8a\xd9\x9d(U\x02q\x0101\x8f\xce\xd9\x98\ -\xff\xfb\xfd\x07\xbf\x9f\xda\x94\xd3\xdd\xbc\x08`\xf4\x85p\ -\x90X\x06\xe0p\x81\x97U))\xa7\x18\xe0\x18\xc0\xfc\ -\x0a^)\xa9\xf7\x1c`\x97\x004\xdb\x13\xcar\xce+\ -p\x04*\xb5\x90\xff\x12\x0d{\x94\xa6\xf8\x1d8\xdb\x14\ -?\xd2\xda\xff\xb0\xb5\xeauT\x8c\x1c\xedo0U\xad\ -q\x08x\x8cS\xe7\xc5r\x15\x0a\xcd\xda\x22BU\xce\ -X\xbb\x1c:\xfc\x1f\x02\xea)+\ -\x00\x00\x80\x08\ -I\ -I*\x00\x08\x00\x00\x00\x18\x00\xfe\x00\x04\x00\x01\x00\x00\ -\x00\x00\x00\x00\x00\x00\x01\x03\x00\x01\x00\x00\x00`\x00\x00\ -\x00\x01\x01\x03\x00\x01\x00\x00\x00`\x00\x00\x00\x02\x01\x03\ -\x00\x04\x00\x00\x00.\x01\x00\x00\x03\x01\x03\x00\x01\x00\x00\ -\x00\x05\x00\x00\x00\x06\x01\x03\x00\x01\x00\x00\x00\x02\x00\x00\ -\x00\x11\x01\x04\x00\x01\x00\x00\x00NS\x00\x00\x12\x01\x03\ -\x00\x01\x00\x00\x00\x01\x00\x00\x00\x15\x01\x03\x00\x01\x00\x00\ -\x00\x04\x00\x00\x00\x16\x01\x03\x00\x01\x00\x00\x00`\x00\x00\ -\x00\x17\x01\x04\x00\x01\x00\x00\x000\x12\x00\x00\x1a\x01\x05\ -\x00\x01\x00\x00\x006\x01\x00\x00\x1b\x01\x05\x00\x01\x00\x00\ -\x00>\x01\x00\x00\x1c\x01\x03\x00\x01\x00\x00\x00\x01\x00\x00\ -\x00(\x01\x03\x00\x01\x00\x00\x00\x02\x00\x00\x001\x01\x02\ -\x00\x22\x00\x00\x00F\x01\x00\x002\x01\x02\x00\x14\x00\x00\ -\x00h\x01\x00\x00=\x01\x03\x00\x01\x00\x00\x00\x02\x00\x00\ -\x00R\x01\x03\x00\x01\x00\x00\x00\x01\x00\x00\x00\xbc\x02\x01\ -\x00\x1f8\x00\x00|\x01\x00\x00I\x86\x01\x00j\x0d\x00\ -\x00\x9c9\x00\x00i\x87\x04\x00\x01\x00\x00\x00\x80e\x00\ -\x00s\x87\x07\x00H\x0c\x00\x00\x06G\x00\x00\x5c\x93\x07\ -\x00X\x1a\x00\x00\xace\x00\x00\x00\x00\x00\x00\x08\x00\x08\ -\x00\x08\x00\x08\x00\x00\xf9\x15\x00\x10'\x00\x00\x00\xf9\x15\ -\x00\x10'\x00\x00Adobe Photo\ -shop CC 2017 (Wi\ -ndows)\x002017:04:0\ -4 11:01:25\x00\ -\x0a\x0a \ - \x0a \x0a \ - paint.net \ -4.0.9\x0a \ - 2017-03-01T11:2\ -0:20-08:00\x0a \ - 2017-04-04T\ -11:01:25-07:00\x0a\ - 2017-\ -04-04T11:01:25-0\ -7:00\x0a \ - imag\ -e/tiff\x0a 3\x0a \ - sRGB IEC\ -61966-2.1\ -\x0a xmp.\ -iid:7284f562-66e\ -c-6d4b-bfaf-a292\ -c87d086e\x0a \ - adobe:doc\ -id:photoshop:aca\ -ee4ff-1960-11e7-\ -bae7-e6e7a5cd281\ -4\x0a xmp.did:\ -15df0628-f397-b6\ -41-8e6b-37248a21\ -c43f\x0a\ - \x0a \ - \x0a \ - \x0a\ - \ - \ -created\x0a \ - xmp.i\ -id:15df0628-f397\ --b641-8e6b-37248\ -a21c43f\x0a \ - 2017-03\ --01T11:20:20-08:\ -00\x0a\ - \ - Adobe Pho\ -toshop CC 2017 (\ -Windows)\x0a \ - \x0a \ - \x0a \ - saved\x0a \ - \ -xmp.iid:7284f5\ -62-66ec-6d4b-bfa\ -f-a292c87d086e\x0a \ - \ -2017-04-04T11:01\ -:25-07:00\x0a \ - Ad\ -obe Photoshop CC\ - 2017 (Windows)<\ -/stEvt:softwareA\ -gent>\x0a \ - /\x0a \ - \x0a \x0a \ - \x0a \x0a <\ -/rdf:RDF>\x0a\x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ -\x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a\ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ -\x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a\ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ -\x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a\ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ -\x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a\ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ -\x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a\ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ -\x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a\ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ -\x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a\ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ -\x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a\ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \x0a\x008BIM\x04\ -%\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x008BIM\x04:\x00\x00\x00\ -\x00\x00\xe5\x00\x00\x00\x10\x00\x00\x00\x01\x00\x00\x00\x00\x00\ -\x0bprintOutput\x00\x00\x00\x05\ -\x00\x00\x00\x00PstSbool\x01\x00\x00\x00\ -\x00Inteenum\x00\x00\x00\x00Int\ -e\x00\x00\x00\x00Clrm\x00\x00\x00\x0fpri\ -ntSixteenBitbool\ -\x00\x00\x00\x00\x0bprinterName\ -TEXT\x00\x00\x00\x01\x00\x00\x00\x00\x00\x0fpr\ -intProofSetupObj\ -c\x00\x00\x00\x0c\x00P\x00r\x00o\x00o\x00f\x00\ - \x00S\x00e\x00t\x00u\x00p\x00\x00\x00\x00\x00\ -\x0aproofSetup\x00\x00\x00\x01\x00\ -\x00\x00\x00Bltnenum\x00\x00\x00\x0cb\ -uiltinProof\x00\x00\x00\x09p\ -roofCMYK\x008BIM\x04;\x00\ -\x00\x00\x00\x02-\x00\x00\x00\x10\x00\x00\x00\x01\x00\x00\x00\ -\x00\x00\x12printOutputOp\ -tions\x00\x00\x00\x17\x00\x00\x00\x00Cpt\ -nbool\x00\x00\x00\x00\x00Clbrbo\ -ol\x00\x00\x00\x00\x00RgsMbool\x00\ -\x00\x00\x00\x00CrnCbool\x00\x00\x00\x00\ -\x00CntCbool\x00\x00\x00\x00\x00Lb\ -lsbool\x00\x00\x00\x00\x00Ngtvb\ -ool\x00\x00\x00\x00\x00EmlDbool\ -\x00\x00\x00\x00\x00Intrbool\x00\x00\x00\ -\x00\x00BckgObjc\x00\x00\x00\x01\x00\x00\ -\x00\x00\x00\x00RGBC\x00\x00\x00\x03\x00\x00\x00\x00\ -Rd doub@o\xe0\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00Grn doub@o\xe0\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00Bl doub\ -@o\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00BrdT\ -UntF#Rlt\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00Bld UntF#Rlt\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00Rslt\ -UntF#Pxl@b\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x0avectorDatabo\ -ol\x01\x00\x00\x00\x00PgPsenum\x00\ -\x00\x00\x00PgPs\x00\x00\x00\x00PgPC\x00\ -\x00\x00\x00LeftUntF#Rlt\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00Top U\ -ntF#Rlt\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00Scl UntF#Prc@\ -Y\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10cropW\ -henPrintingbool\x00\ -\x00\x00\x00\x0ecropRectBott\ -omlong\x00\x00\x00\x00\x00\x00\x00\x0ccr\ -opRectLeftlong\x00\x00\ -\x00\x00\x00\x00\x00\x0dcropRectRi\ -ghtlong\x00\x00\x00\x00\x00\x00\x00\x0bc\ -ropRectToplong\x00\x00\ -\x00\x00\x008BIM\x03\xed\x00\x00\x00\x00\x00\x10\x00\ -\x90\x00\x00\x00\x01\x00\x01\x00\x90\x00\x00\x00\x01\x00\x018\ -BIM\x04&\x00\x00\x00\x00\x00\x0e\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00?\x80\x00\x008BIM\x03\xee\x00\ -\x00\x00\x00\x00\x0d\x0cTransparen\ -cy\x008BIM\x04\x15\x00\x00\x00\x00\x00\x1e\x00\ -\x00\x00\x0d\x00T\x00r\x00a\x00n\x00s\x00p\x00\ -a\x00r\x00e\x00n\x00c\x00y\x00\x008BI\ -M\x045\x00\x00\x00\x00\x00\x11\x00\x00\x00\x01\x00\x00\xff\ -\xff\x00\x00\x00\x00\x00\x00\x00d\x01\x008BIM\x04\ -\x1d\x00\x00\x00\x00\x00\x04\x00\x00\x00\x008BIM\x04\ -\x0d\x00\x00\x00\x00\x00\x04\x00\x00\x00\x1e8BIM\x04\ -\x19\x00\x00\x00\x00\x00\x04\x00\x00\x00\x1e8BIM\x03\ -\xf3\x00\x00\x00\x00\x00\x09\x00\x00\x00\x00\x00\x00\x00\x00\x01\ -\x008BIM'\x10\x00\x00\x00\x00\x00\x0a\x00\x01\x00\ -\x00\x00\x00\x00\x00\x00\x018BIM\x03\xf5\x00\x00\x00\ -\x00\x00H\x00/ff\x00\x01\x00lff\x00\x06\x00\ -\x00\x00\x00\x00\x01\x00/ff\x00\x01\x00\xa1\x99\x9a\x00\ -\x06\x00\x00\x00\x00\x00\x01\x002\x00\x00\x00\x01\x00Z\x00\ -\x00\x00\x06\x00\x00\x00\x00\x00\x01\x005\x00\x00\x00\x01\x00\ --\x00\x00\x00\x06\x00\x00\x00\x00\x00\x018BIM\x03\ -\xf8\x00\x00\x00\x00\x00p\x00\x00\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x03\ -\xe8\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x03\xe8\x00\x00\x00\ -\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\x03\xe8\x00\x00\x00\x00\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\x03\xe8\x00\x008BIM\x04\x00\x00\x00\x00\ -\x00\x00\x02\x00\x008BIM\x04\x02\x00\x00\x00\x00\x00\ -\x02\x00\x008BIM\x040\x00\x00\x00\x00\x00\x01\x01\ -\x008BIM\x04-\x00\x00\x00\x00\x00\x06\x00\x01\x00\ -\x00\x00\x038BIM\x04\x08\x00\x00\x00\x00\x00$\x00\ -\x00\x00\x01\x00\x00\x02@\x00\x00\x02@\x00\x00\x00\x04\x00\ -\x00\x01+\x00\x00\x00\x0a\xc5\x00\x00\x00\x01\x1b\x01\x00\x00\ -\x0a\xd5\x018BIM\x04\x1e\x00\x00\x00\x00\x00\x04\x00\ -\x00\x00\x008BIM\x04\x1a\x00\x00\x00\x00\x035\x00\ -\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00`\x00\ -\x00\x00`\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00`\x00\x00\x00`\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x10\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00nu\ -ll\x00\x00\x00\x02\x00\x00\x00\x06bounds\ -Objc\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00Rc\ -t1\x00\x00\x00\x04\x00\x00\x00\x00Top lo\ -ng\x00\x00\x00\x00\x00\x00\x00\x00Leftlo\ -ng\x00\x00\x00\x00\x00\x00\x00\x00Btomlo\ -ng\x00\x00\x00`\x00\x00\x00\x00Rghtlo\ -ng\x00\x00\x00`\x00\x00\x00\x06slices\ -VlLs\x00\x00\x00\x01Objc\x00\x00\x00\x01\ -\x00\x00\x00\x00\x00\x05slice\x00\x00\x00\x12\x00\ -\x00\x00\x07sliceIDlong\x00\x00\ -\x00\x00\x00\x00\x00\x07groupIDlon\ -g\x00\x00\x00\x00\x00\x00\x00\x06origine\ -num\x00\x00\x00\x0cESliceOri\ -gin\x00\x00\x00\x0dautoGener\ -ated\x00\x00\x00\x00Typeenum\ -\x00\x00\x00\x0aESliceType\x00\x00\ -\x00\x00Img \x00\x00\x00\x06bounds\ -Objc\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00Rc\ -t1\x00\x00\x00\x04\x00\x00\x00\x00Top lo\ -ng\x00\x00\x00\x00\x00\x00\x00\x00Leftlo\ -ng\x00\x00\x00\x00\x00\x00\x00\x00Btomlo\ -ng\x00\x00\x00`\x00\x00\x00\x00Rghtlo\ -ng\x00\x00\x00`\x00\x00\x00\x03urlTEX\ -T\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00nullT\ -EXT\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00Msg\ -eTEXT\x00\x00\x00\x01\x00\x00\x00\x00\x00\x06a\ -ltTagTEXT\x00\x00\x00\x01\x00\x00\x00\ -\x00\x00\x0ecellTextIsHTM\ -Lbool\x01\x00\x00\x00\x08cellTe\ -xtTEXT\x00\x00\x00\x01\x00\x00\x00\x00\x00\x09\ -horzAlignenum\x00\x00\x00\ -\x0fESliceHorzAlign\ -\x00\x00\x00\x07default\x00\x00\x00\x09v\ -ertAlignenum\x00\x00\x00\x0f\ -ESliceVertAlign\x00\ -\x00\x00\x07default\x00\x00\x00\x0bbg\ -ColorTypeenum\x00\x00\x00\ -\x11ESliceBGColorTy\ -pe\x00\x00\x00\x00None\x00\x00\x00\x09to\ -pOutsetlong\x00\x00\x00\x00\x00\ -\x00\x00\x0aleftOutsetlon\ -g\x00\x00\x00\x00\x00\x00\x00\x0cbottomO\ -utsetlong\x00\x00\x00\x00\x00\x00\x00\ -\x0brightOutsetlong\ -\x00\x00\x00\x00\x008BIM\x04(\x00\x00\x00\x00\x00\ -\x0c\x00\x00\x00\x02?\xf0\x00\x00\x00\x00\x00\x008BI\ -M\x04\x14\x00\x00\x00\x00\x00\x04\x00\x00\x00\x048BI\ -M\x04\x0c\x00\x00\x00\x00\x04\x02\x00\x00\x00\x01\x00\x00\x00\ -0\x00\x00\x000\x00\x00\x00\x90\x00\x00\x1b\x00\x00\x00\x03\ -\xe6\x00\x18\x00\x01\xff\xd8\xff\xed\x00\x0cAdobe\ -_CM\x00\x01\xff\xee\x00\x0eAdobe\x00d\ -\x80\x00\x00\x00\x01\xff\xdb\x00\x84\x00\x0c\x08\x08\x08\x09\x08\ -\x0c\x09\x09\x0c\x11\x0b\x0a\x0b\x11\x15\x0f\x0c\x0c\x0f\x15\x18\ -\x13\x13\x15\x13\x13\x18\x11\x0c\x0c\x0c\x0c\x0c\x0c\x11\x0c\x0c\ -\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\ -\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x01\x0d\x0b\x0b\x0d\x0e\ -\x0d\x10\x0e\x0e\x10\x14\x0e\x0e\x0e\x14\x14\x0e\x0e\x0e\x0e\x14\ -\x11\x0c\x0c\x0c\x0c\x0c\x11\x11\x0c\x0c\x0c\x0c\x0c\x0c\x11\x0c\ -\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\ -\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\xff\xc0\x00\x11\x08\ -\x000\x000\x03\x01\x22\x00\x02\x11\x01\x03\x11\x01\xff\xdd\ -\x00\x04\x00\x03\xff\xc4\x01?\x00\x00\x01\x05\x01\x01\x01\x01\ -\x01\x01\x00\x00\x00\x00\x00\x00\x00\x03\x00\x01\x02\x04\x05\x06\ -\x07\x08\x09\x0a\x0b\x01\x00\x01\x05\x01\x01\x01\x01\x01\x01\x00\ -\x00\x00\x00\x00\x00\x00\x01\x00\x02\x03\x04\x05\x06\x07\x08\x09\ -\x0a\x0b\x10\x00\x01\x04\x01\x03\x02\x04\x02\x05\x07\x06\x08\x05\ -\x03\x0c3\x01\x00\x02\x11\x03\x04!\x121\x05AQa\ -\x13\x22q\x812\x06\x14\x91\xa1\xb1B#$\x15R\xc1\ -b34r\x82\xd1C\x07%\x92S\xf0\xe1\xf1cs\ -5\x16\xa2\xb2\x83&D\x93TdE\xc2\xa3t6\x17\ -\xd2U\xe2e\xf2\xb3\x84\xc3\xd3u\xe3\xf3F'\x94\xa4\ -\x85\xb4\x95\xc4\xd4\xe4\xf4\xa5\xb5\xc5\xd5\xe5\xf5Vfv\ -\x86\x96\xa6\xb6\xc6\xd6\xe6\xf67GWgw\x87\x97\xa7\ -\xb7\xc7\xd7\xe7\xf7\x11\x00\x02\x02\x01\x02\x04\x04\x03\x04\x05\ -\x06\x07\x07\x06\x055\x01\x00\x02\x11\x03!1\x12\x04A\ -Qaq\x22\x13\x052\x81\x91\x14\xa1\xb1B#\xc1R\ -\xd1\xf03$b\xe1r\x82\x92CS\x15cs4\xf1\ -%\x06\x16\xa2\xb2\x83\x07&5\xc2\xd2D\x93T\xa3\x17\ -dEU6te\xe2\xf2\xb3\x84\xc3\xd3u\xe3\xf3F\ -\x94\xa4\x85\xb4\x95\xc4\xd4\xe4\xf4\xa5\xb5\xc5\xd5\xe5\xf5V\ -fv\x86\x96\xa6\xb6\xc6\xd6\xe6\xf6'7GWgw\ -\x87\x97\xa7\xb7\xc7\xff\xda\x00\x0c\x03\x01\x00\x02\x11\x03\x11\ -\x00?\x00\xf4<\xdc\xcc\x96d\x9a\xa9;@\x80\x00\x00\ -\x92O\xc6P\xfd~\xab\xe0\xff\x00\xfbl\x7f\xe4R\xc9\ -\xff\x00\x95\x1b\xfdz\xff\x00\xef\xabR\xcb\x19[\x0b\xec\ -!\xad\x1c\x92\x92\x9c\xbf_\xaa\xf8?\xfe\xdb\x1f\xf9\x14\ -\xbd~\xab\xe0\xff\x00\xfbl\x7f\xe4T\xed\xea\xee\x9f\xd0\ -\xb0\x06\xfe\xf3\xff\x00\xf2#\xff\x00$\x95]]\xd3\xfa\ -f\x02\xd3\xf9\xcc\xff\x00\xc8\x9f\xfc\x92Ja\xeb\xf5_\ -\x07\xff\x00\x98?\xf2(\x98\x19\x99\x16dzV\x9d\xc0\ -\x83\xc8\x00\x82?\xaa\xb4+\xb1\x960>\xb2\x1c\xd3\xc1\ -\x0b+\x07\xfeP?\xf5\xcf\xca\x92\x9f\xff\xd0\xef\xf2\x7f\ -\xe5F\xff\x00^\xbf\xfb\xea\x16fS\xb2-\xff\x00\x83\ -i\x867\xfe\xff\x00\xfd\xa4\x5c\x9f\xf9Q\xbf\xd7\xaf\xfe\ -\xfa\x87\x9b\x8a\xec{\x09\x03\xf4O>\xc3\xe0O\xe6\x1f\ -\xfb\xeaJnt\xecJ\x85-\xb9\xed\x0e{\xf5\x13\xac\ -\x0e\xd0\xa9dc\xde-\xb5\xfe\x9b\x85a\xce;\xbbD\ -\xf2\xad\xe0f\xd4\xda\x856\xb81\xcc\xd1\xa4\xe8\x08\xf8\ -\xa5\x9f\x9bS\xaa4\xd4\xe0\xf7?G\x11\xa8\x03\xe2\x92\ -\x9a\x98y.\xc7\xb4\x7f\xa3y\x01\xe3\xfe\xff\x00\xfd\x94\ -L\x1d:\x8b\x87\x9d\x9f\x95C\x0b\x15\xd9\x16\x87\x11\xfa\ -&\x19q\xf1#\xf3\x07\xfd\xf9O\x07^\xa2\xe3\xe7g\ -\xe5IO\xff\xd1\xef\xf2\x7f\xe5F\xff\x00^\xbf\xfb\xea\ -\xd4{\x1a\xf6\x96<\x074\xe8A\xe1g\xe6\xe1d\xbf\ -$\xdbP\x90b\x0c\xc1\x04!\xfd\x9b\xaa~\xf3\xff\x00\ -\xed\xcf\xfc\xc9%&\xb7\xa4\xb4\x99\xa6\xc2\xd1\xfb\xae\x1b\ -\x87\xdf\xf4\x92\xab\xa4\xb4\x19\xba\xc2\xe1\xfb\xad\x1bG\xdf\ -\xf4\x90~\xcd\xd5?y\xff\x00\xf6\xe7\xfed\x97\xd9\xba\ -\xa7\xef?\xfe\xdc\xff\x00\xcc\x92S\xa8\xc65\x8d\x0c`\ -\x0dh\xd0\x01\xc2\xca\xc1\xff\x00\x94\x0f\xc6\xcf\xca\x9f\xec\ -\xddS\xf7\x9f\xff\x00n\x7f\xe6H\xb88Y\x15\xdf\xea\ -\xda\x03@\x04s$\x92\x92\x9f\xff\xd98BIM\x04\ -!\x00\x00\x00\x00\x00]\x00\x00\x00\x01\x01\x00\x00\x00\x0f\ -\x00A\x00d\x00o\x00b\x00e\x00 \x00P\x00h\ -\x00o\x00t\x00o\x00s\x00h\x00o\x00p\x00\x00\ -\x00\x17\x00A\x00d\x00o\x00b\x00e\x00 \x00P\ -\x00h\x00o\x00t\x00o\x00s\x00h\x00o\x00p\ -\x00 \x00C\x00C\x00 \x002\x000\x001\x007\ -\x00\x00\x00\x01\x00\x00\x00\x0cHLino\x02\x10\x00\ -\x00mntrRGB XYZ \x07\xce\x00\ -\x02\x00\x09\x00\x06\x001\x00\x00acspMSF\ -T\x00\x00\x00\x00IEC sRGB\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf6\xd6\x00\x01\x00\ -\x00\x00\x00\xd3-HP \x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x11cprt\x00\x00\x01\ -P\x00\x00\x003desc\x00\x00\x01\x84\x00\x00\x00\ -lwtpt\x00\x00\x01\xf0\x00\x00\x00\x14bkp\ -t\x00\x00\x02\x04\x00\x00\x00\x14rXYZ\x00\x00\x02\ -\x18\x00\x00\x00\x14gXYZ\x00\x00\x02,\x00\x00\x00\ -\x14bXYZ\x00\x00\x02@\x00\x00\x00\x14dmn\ -d\x00\x00\x02T\x00\x00\x00pdmdd\x00\x00\x02\ -\xc4\x00\x00\x00\x88vued\x00\x00\x03L\x00\x00\x00\ -\x86view\x00\x00\x03\xd4\x00\x00\x00$lum\ -i\x00\x00\x03\xf8\x00\x00\x00\x14meas\x00\x00\x04\ -\x0c\x00\x00\x00$tech\x00\x00\x040\x00\x00\x00\ -\x0crTRC\x00\x00\x04<\x00\x00\x08\x0cgTR\ -C\x00\x00\x04<\x00\x00\x08\x0cbTRC\x00\x00\x04\ -<\x00\x00\x08\x0ctext\x00\x00\x00\x00Cop\ -yright (c) 1998 \ -Hewlett-Packard \ -Company\x00\x00desc\x00\x00\x00\ -\x00\x00\x00\x00\x12sRGB IEC619\ -66-2.1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x12sRGB IEC61966-\ -2.1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00XYZ \x00\x00\x00\x00\x00\x00\xf3\ -Q\x00\x01\x00\x00\x00\x01\x16\xccXYZ \x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00XYZ\ - \x00\x00\x00\x00\x00\x00o\xa2\x00\x008\xf5\x00\x00\x03\ -\x90XYZ \x00\x00\x00\x00\x00\x00b\x99\x00\x00\xb7\ -\x85\x00\x00\x18\xdaXYZ \x00\x00\x00\x00\x00\x00$\ -\xa0\x00\x00\x0f\x84\x00\x00\xb6\xcfdesc\x00\x00\x00\ -\x00\x00\x00\x00\x16IEC http://\ -www.iec.ch\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x16IEC http:/\ -/www.iec.ch\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00desc\x00\x00\x00\ -\x00\x00\x00\x00.IEC 61966-2\ -.1 Default RGB c\ -olour space - sR\ -GB\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00.IE\ -C 61966-2.1 Defa\ -ult RGB colour s\ -pace - sRGB\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00desc\x00\x00\x00\x00\x00\x00\x00,Ref\ -erence Viewing C\ -ondition in IEC6\ -1966-2.1\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00,Reference Vi\ -ewing Condition \ -in IEC61966-2.1\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00view\x00\x00\x00\ -\x00\x00\x13\xa4\xfe\x00\x14_.\x00\x10\xcf\x14\x00\x03\xed\ -\xcc\x00\x04\x13\x0b\x00\x03\x5c\x9e\x00\x00\x00\x01XYZ\ - \x00\x00\x00\x00\x00L\x09V\x00P\x00\x00\x00W\x1f\ -\xe7meas\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\ -\x8f\x00\x00\x00\x02sig \x00\x00\x00\x00CRT\ - curv\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\ -\x05\x00\x0a\x00\x0f\x00\x14\x00\x19\x00\x1e\x00#\x00(\x00\ --\x002\x007\x00;\x00@\x00E\x00J\x00O\x00\ -T\x00Y\x00^\x00c\x00h\x00m\x00r\x00w\x00\ -|\x00\x81\x00\x86\x00\x8b\x00\x90\x00\x95\x00\x9a\x00\x9f\x00\ -\xa4\x00\xa9\x00\xae\x00\xb2\x00\xb7\x00\xbc\x00\xc1\x00\xc6\x00\ -\xcb\x00\xd0\x00\xd5\x00\xdb\x00\xe0\x00\xe5\x00\xeb\x00\xf0\x00\ -\xf6\x00\xfb\x01\x01\x01\x07\x01\x0d\x01\x13\x01\x19\x01\x1f\x01\ -%\x01+\x012\x018\x01>\x01E\x01L\x01R\x01\ -Y\x01`\x01g\x01n\x01u\x01|\x01\x83\x01\x8b\x01\ -\x92\x01\x9a\x01\xa1\x01\xa9\x01\xb1\x01\xb9\x01\xc1\x01\xc9\x01\ -\xd1\x01\xd9\x01\xe1\x01\xe9\x01\xf2\x01\xfa\x02\x03\x02\x0c\x02\ -\x14\x02\x1d\x02&\x02/\x028\x02A\x02K\x02T\x02\ -]\x02g\x02q\x02z\x02\x84\x02\x8e\x02\x98\x02\xa2\x02\ -\xac\x02\xb6\x02\xc1\x02\xcb\x02\xd5\x02\xe0\x02\xeb\x02\xf5\x03\ -\x00\x03\x0b\x03\x16\x03!\x03-\x038\x03C\x03O\x03\ -Z\x03f\x03r\x03~\x03\x8a\x03\x96\x03\xa2\x03\xae\x03\ -\xba\x03\xc7\x03\xd3\x03\xe0\x03\xec\x03\xf9\x04\x06\x04\x13\x04\ - \x04-\x04;\x04H\x04U\x04c\x04q\x04~\x04\ -\x8c\x04\x9a\x04\xa8\x04\xb6\x04\xc4\x04\xd3\x04\xe1\x04\xf0\x04\ -\xfe\x05\x0d\x05\x1c\x05+\x05:\x05I\x05X\x05g\x05\ -w\x05\x86\x05\x96\x05\xa6\x05\xb5\x05\xc5\x05\xd5\x05\xe5\x05\ -\xf6\x06\x06\x06\x16\x06'\x067\x06H\x06Y\x06j\x06\ -{\x06\x8c\x06\x9d\x06\xaf\x06\xc0\x06\xd1\x06\xe3\x06\xf5\x07\ -\x07\x07\x19\x07+\x07=\x07O\x07a\x07t\x07\x86\x07\ -\x99\x07\xac\x07\xbf\x07\xd2\x07\xe5\x07\xf8\x08\x0b\x08\x1f\x08\ -2\x08F\x08Z\x08n\x08\x82\x08\x96\x08\xaa\x08\xbe\x08\ -\xd2\x08\xe7\x08\xfb\x09\x10\x09%\x09:\x09O\x09d\x09\ -y\x09\x8f\x09\xa4\x09\xba\x09\xcf\x09\xe5\x09\xfb\x0a\x11\x0a\ -'\x0a=\x0aT\x0aj\x0a\x81\x0a\x98\x0a\xae\x0a\xc5\x0a\ -\xdc\x0a\xf3\x0b\x0b\x0b\x22\x0b9\x0bQ\x0bi\x0b\x80\x0b\ -\x98\x0b\xb0\x0b\xc8\x0b\xe1\x0b\xf9\x0c\x12\x0c*\x0cC\x0c\ -\x5c\x0cu\x0c\x8e\x0c\xa7\x0c\xc0\x0c\xd9\x0c\xf3\x0d\x0d\x0d\ -&\x0d@\x0dZ\x0dt\x0d\x8e\x0d\xa9\x0d\xc3\x0d\xde\x0d\ -\xf8\x0e\x13\x0e.\x0eI\x0ed\x0e\x7f\x0e\x9b\x0e\xb6\x0e\ -\xd2\x0e\xee\x0f\x09\x0f%\x0fA\x0f^\x0fz\x0f\x96\x0f\ -\xb3\x0f\xcf\x0f\xec\x10\x09\x10&\x10C\x10a\x10~\x10\ -\x9b\x10\xb9\x10\xd7\x10\xf5\x11\x13\x111\x11O\x11m\x11\ -\x8c\x11\xaa\x11\xc9\x11\xe8\x12\x07\x12&\x12E\x12d\x12\ -\x84\x12\xa3\x12\xc3\x12\xe3\x13\x03\x13#\x13C\x13c\x13\ -\x83\x13\xa4\x13\xc5\x13\xe5\x14\x06\x14'\x14I\x14j\x14\ -\x8b\x14\xad\x14\xce\x14\xf0\x15\x12\x154\x15V\x15x\x15\ -\x9b\x15\xbd\x15\xe0\x16\x03\x16&\x16I\x16l\x16\x8f\x16\ -\xb2\x16\xd6\x16\xfa\x17\x1d\x17A\x17e\x17\x89\x17\xae\x17\ -\xd2\x17\xf7\x18\x1b\x18@\x18e\x18\x8a\x18\xaf\x18\xd5\x18\ -\xfa\x19 \x19E\x19k\x19\x91\x19\xb7\x19\xdd\x1a\x04\x1a\ -*\x1aQ\x1aw\x1a\x9e\x1a\xc5\x1a\xec\x1b\x14\x1b;\x1b\ -c\x1b\x8a\x1b\xb2\x1b\xda\x1c\x02\x1c*\x1cR\x1c{\x1c\ -\xa3\x1c\xcc\x1c\xf5\x1d\x1e\x1dG\x1dp\x1d\x99\x1d\xc3\x1d\ -\xec\x1e\x16\x1e@\x1ej\x1e\x94\x1e\xbe\x1e\xe9\x1f\x13\x1f\ ->\x1fi\x1f\x94\x1f\xbf\x1f\xea \x15 A l \ -\x98 \xc4 \xf0!\x1c!H!u!\xa1!\xce!\ -\xfb\x22'\x22U\x22\x82\x22\xaf\x22\xdd#\x0a#8#\ -f#\x94#\xc2#\xf0$\x1f$M$|$\xab$\ -\xda%\x09%8%h%\x97%\xc7%\xf7&'&\ -W&\x87&\xb7&\xe8'\x18'I'z'\xab'\ -\xdc(\x0d(?(q(\xa2(\xd4)\x06)8)\ -k)\x9d)\xd0*\x02*5*h*\x9b*\xcf+\ -\x02+6+i+\x9d+\xd1,\x05,9,n,\ -\xa2,\xd7-\x0c-A-v-\xab-\xe1.\x16.\ -L.\x82.\xb7.\xee/$/Z/\x91/\xc7/\ -\xfe050l0\xa40\xdb1\x121J1\x821\ -\xba1\xf22*2c2\x9b2\xd43\x0d3F3\ -\x7f3\xb83\xf14+4e4\x9e4\xd85\x135\ -M5\x875\xc25\xfd676r6\xae6\xe97\ -$7`7\x9c7\xd78\x148P8\x8c8\xc89\ -\x059B9\x7f9\xbc9\xf9:6:t:\xb2:\ -\xef;-;k;\xaa;\xe8<' >`>\xa0>\ -\xe0?!?a?\xa2?\xe2@#@d@\xa6@\ -\xe7A)AjA\xacA\xeeB0BrB\xb5B\ -\xf7C:C}C\xc0D\x03DGD\x8aD\xceE\ -\x12EUE\x9aE\xdeF\x22FgF\xabF\xf0G\ -5G{G\xc0H\x05HKH\x91H\xd7I\x1dI\ -cI\xa9I\xf0J7J}J\xc4K\x0cKSK\ -\x9aK\xe2L*LrL\xbaM\x02MJM\x93M\ -\xdcN%NnN\xb7O\x00OIO\x93O\xddP\ -'PqP\xbbQ\x06QPQ\x9bQ\xe6R1R\ -|R\xc7S\x13S_S\xaaS\xf6TBT\x8fT\ -\xdbU(UuU\xc2V\x0fV\x5cV\xa9V\xf7W\ -DW\x92W\xe0X/X}X\xcbY\x1aYiY\ -\xb8Z\x07ZVZ\xa6Z\xf5[E[\x95[\xe5\x5c\ -5\x5c\x86\x5c\xd6]']x]\xc9^\x1a^l^\ -\xbd_\x0f_a_\xb3`\x05`W`\xaa`\xfca\ -Oa\xa2a\xf5bIb\x9cb\xf0cCc\x97c\ -\xebd@d\x94d\xe9e=e\x92e\xe7f=f\ -\x92f\xe8g=g\x93g\xe9h?h\x96h\xeci\ -Ci\x9ai\xf1jHj\x9fj\xf7kOk\xa7k\ -\xfflWl\xafm\x08m`m\xb9n\x12nkn\ -\xc4o\x1eoxo\xd1p+p\x86p\xe0q:q\ -\x95q\xf0rKr\xa6s\x01s]s\xb8t\x14t\ -pt\xccu(u\x85u\xe1v>v\x9bv\xf8w\ -Vw\xb3x\x11xnx\xccy*y\x89y\xe7z\ -Fz\xa5{\x04{c{\xc2|!|\x81|\xe1}\ -A}\xa1~\x01~b~\xc2\x7f#\x7f\x84\x7f\xe5\x80\ -G\x80\xa8\x81\x0a\x81k\x81\xcd\x820\x82\x92\x82\xf4\x83\ -W\x83\xba\x84\x1d\x84\x80\x84\xe3\x85G\x85\xab\x86\x0e\x86\ -r\x86\xd7\x87;\x87\x9f\x88\x04\x88i\x88\xce\x893\x89\ -\x99\x89\xfe\x8ad\x8a\xca\x8b0\x8b\x96\x8b\xfc\x8cc\x8c\ -\xca\x8d1\x8d\x98\x8d\xff\x8ef\x8e\xce\x8f6\x8f\x9e\x90\ -\x06\x90n\x90\xd6\x91?\x91\xa8\x92\x11\x92z\x92\xe3\x93\ -M\x93\xb6\x94 \x94\x8a\x94\xf4\x95_\x95\xc9\x964\x96\ -\x9f\x97\x0a\x97u\x97\xe0\x98L\x98\xb8\x99$\x99\x90\x99\ -\xfc\x9ah\x9a\xd5\x9bB\x9b\xaf\x9c\x1c\x9c\x89\x9c\xf7\x9d\ -d\x9d\xd2\x9e@\x9e\xae\x9f\x1d\x9f\x8b\x9f\xfa\xa0i\xa0\ -\xd8\xa1G\xa1\xb6\xa2&\xa2\x96\xa3\x06\xa3v\xa3\xe6\xa4\ -V\xa4\xc7\xa58\xa5\xa9\xa6\x1a\xa6\x8b\xa6\xfd\xa7n\xa7\ -\xe0\xa8R\xa8\xc4\xa97\xa9\xa9\xaa\x1c\xaa\x8f\xab\x02\xab\ -u\xab\xe9\xac\x5c\xac\xd0\xadD\xad\xb8\xae-\xae\xa1\xaf\ -\x16\xaf\x8b\xb0\x00\xb0u\xb0\xea\xb1`\xb1\xd6\xb2K\xb2\ -\xc2\xb38\xb3\xae\xb4%\xb4\x9c\xb5\x13\xb5\x8a\xb6\x01\xb6\ -y\xb6\xf0\xb7h\xb7\xe0\xb8Y\xb8\xd1\xb9J\xb9\xc2\xba\ -;\xba\xb5\xbb.\xbb\xa7\xbc!\xbc\x9b\xbd\x15\xbd\x8f\xbe\ -\x0a\xbe\x84\xbe\xff\xbfz\xbf\xf5\xc0p\xc0\xec\xc1g\xc1\ -\xe3\xc2_\xc2\xdb\xc3X\xc3\xd4\xc4Q\xc4\xce\xc5K\xc5\ -\xc8\xc6F\xc6\xc3\xc7A\xc7\xbf\xc8=\xc8\xbc\xc9:\xc9\ -\xb9\xca8\xca\xb7\xcb6\xcb\xb6\xcc5\xcc\xb5\xcd5\xcd\ -\xb5\xce6\xce\xb6\xcf7\xcf\xb8\xd09\xd0\xba\xd1<\xd1\ -\xbe\xd2?\xd2\xc1\xd3D\xd3\xc6\xd4I\xd4\xcb\xd5N\xd5\ -\xd1\xd6U\xd6\xd8\xd7\x5c\xd7\xe0\xd8d\xd8\xe8\xd9l\xd9\ -\xf1\xdav\xda\xfb\xdb\x80\xdc\x05\xdc\x8a\xdd\x10\xdd\x96\xde\ -\x1c\xde\xa2\xdf)\xdf\xaf\xe06\xe0\xbd\xe1D\xe1\xcc\xe2\ -S\xe2\xdb\xe3c\xe3\xeb\xe4s\xe4\xfc\xe5\x84\xe6\x0d\xe6\ -\x96\xe7\x1f\xe7\xa9\xe82\xe8\xbc\xe9F\xe9\xd0\xea[\xea\ -\xe5\xebp\xeb\xfb\xec\x86\xed\x11\xed\x9c\xee(\xee\xb4\xef\ -@\xef\xcc\xf0X\xf0\xe5\xf1r\xf1\xff\xf2\x8c\xf3\x19\xf3\ -\xa7\xf44\xf4\xc2\xf5P\xf5\xde\xf6m\xf6\xfb\xf7\x8a\xf8\ -\x19\xf8\xa8\xf98\xf9\xc7\xfaW\xfa\xe7\xfbw\xfc\x07\xfc\ -\x98\xfd)\xfd\xba\xfeK\xfe\xdc\xffm\xff\xff\x80\x00 \ -P8$\x16\x0d\x07\x84BaP\xb8d6\x1d\x0f\x88\ -DbQ8\xa4V-\x17\x8cFcQ\xb8\xe4v=\ -\x1f\x90HdR9$\x96M'\x94JeR\xb9d\ -\xb6]/\x98A\x00\x930(*l\x0c\x9c\x03\x02\x13\ -`P0\x07?\x02?\xe8O\xe8X\x06 \x01\xa4\x00\ -hO\xfa$\x1a\x93H\x82R\xdf\xf0J}J\x06\xff\ -\xa4\x80\xa9t\xd0\x05\x1a\x07U\xa5\xd5\xeb\xf4\xfa\x8d\x86\ -\x05S\x81S\xe9VhK\xfc\x05o\x01\xd5\xaa\xf6\xca\ -\x8d~\x0fh\xb4\xd2\x00P\x8a\x95\x92\xefK\xb0P\xac\ -W\x9aM\xca\x9dI\xbe]05\xca\xf0\x02\x98\xfe\xc8\ ->\xf2O\xa7\xa6U\xe2\xf3\xcc<2O\xb7\xce\x1aS\ -O\x07\xe8Bcm!\x10\x87\xa7)\x89\xb5C\x00v\ -\xb4#?\x01\x81*\x98\x88]\xf7i\x87\xa4g\xb18\ -+\x1e\xe7\x01\xb7\x8e\xed\xaa\x17:\x15\xfa\x0d\xba\xde\xda\ -\xf7\x98Ln;\x7f\xbe\xe2\xf0!\x99\xec\x0d\xe2\xbbj\ -\xe8T\xab\x18^\x7f6\x9f\x90\xc8uz\xbb>\xcf\x81\ -\xfc\xf8\xf4=\x9c\xbe\xb6\xf3#\xdc\xbaa|VN\x0f\ -\xa3c6\xfa\x94\x04\xbfAb\xcf\xf4\xe0)\xc0\x03:\ -r\x08-\xebzc\x03\xc1\x10L\x15\x05>\xe6\x94\x1c\ -c\x13p\x89\x04h\xc2\x86+\xee\x90\x00\xd0\xc8\x10(\ -C\x83 \xdb\x0f\x91\x00LD\x05\xc1q,M\x13\xc5\ -\x09B\xa4fE\x85\xf9\x17\x17\x8d\xa6\xfcdk\xb9\x08\ -\xb0;\x1b\x84\x84LtV5A0_\x14\xc8\x12\x0c\ -\x85!\xa2\xe7\xd4\x8c|\x93RI\x00SI\x84|\x8c\ -}\x1f(\xc4\x0a\x01\x07\xb2\xa8\x9aCK\x058\x0f-\ -\x812$\xbd/\xcc\x13\x0a\x04gL\x86\x08\xed3\x8a\ -\x87\x84\xd4v#\x09\x98\x08\x02\x8a\xf3\x88\xda7\xce\x84\ -\x5c\xa71O\x13\xcc\xf5\x03\x9d\x13\xe9\xc44P\x02\x11\ -\xc9A\x9b\xa8\xc42\x03\x01\x03-\x14?\x0c\x14h\xf0\ -\xe3Ot\x8d%I\xa3\xe7\x95,w\x0c\x94\xc8|o\ -S\x86\xad\x0d\x0d\x0d\x95\x09\x0e\xfe\x8b#}!JU\ -\x15MT\x873\x07\x99\xe1E\x0c\xa1\xf1\xb9Y\x9ah\ -\xc4\xb6\x03\x810\xf8\xdaDN\x22\xb8\xdbS\xc4\xae\x13\ -\x9bU\xc8q\xab\xae\xe1\xa1V\x15UV\x9e\x14\xc8\xc8\ -\x1e\x9b\xb6\x89\xa9O\xd1\x03u\xacD\xd7\xb5\xfb\xa4\x89\ -\xaaF\xdd\xbch\x9e\xb7\x09\xe6\xea\xcav\x13\xa8\xe0\x1f\ -\xb7I\xfb;\xb8\x8e\xdb\xb2\xf29Wr\xd4\x82<\xc8\ -E\x80\xe3\xbb\xab+\xa3d9\xd7\xdd\xe3}-\xd0-\ -\xec\xe0X\xc8\xa3\xc6\xe4\xbc\xce\xc5\xde\xbf\xb9`\x04\xdc\ -\x02\x84X\x88T\x05\xe2\x80r8\xca\x9e\x87\x8d\x9c\x1e\ -\xd6f\xe5j\x8b\xd6\xe0MB6\x10\xe2\xc6L7^\ -\xe8\x89\xf9\x95\x9fc\xa6\x5c(\x9a\xf9\x89\x9be!\xf7\ -2\x87\x02\x80xN\x15\x80:\xb6\x15 \xed.\x92\x9d\ -\xea\x81\xe8O\x06R\xe9\xad\x97r\xb5\x9b\xae\x17\xa6\x8c\ -\xe0`\xeec\xcdr\xbb\xb9\xa5\x93|\xdd\xb4\x83\xcc\x08\ -\xeb\x80\xa8\xf9\xaf\x93an\xc4\x1cb\xec\xb0\xc7\xb3\x87\ -\x96\x89\xbbi\xe4\x12\xe6GQ\xbf\xa3z8\xfb\x8c\xdb\ -\xa8~i\xef\x06E\x89\xbd\xef\x88>\xb8\x08\x82\xb1\xd1\ -\x12U\x86\x5c(~\x8eY\x9b\xa8\xcc\x1f\xdb\xc6\xd9\xa5\ -[K\x95\xd5y9h\xe8{\xefX\x07\xc6\xa74d\ -\xef\xbc\xee\xfa\x08t\x00\xa4^E\x95\xc1\x87L\x1er\ -\xa8v1\x8dS8\xe5i\xc8W\x1b~L,e\x16\ -\xda%'\x9f#?t o\x06\x9e\xf5\xcfx\x15W\ -@\x08tQ\x7fK\xd3\xf5(m\x99\xdd\x0c\xe2\x01\xb5\ -\xe7\x9a6\xa0\x11\xc9T\x9b\x926\xfb\xf9\x82\x04\x1ci\ -\x18\xfe\x0f\xbdJx`\xa1\x15\xf1\x95\xbc(d\x1fl\ -\xb8\xcf\x14\x1f\xf9\xe6\xd7\xa3\xb6\xf65\x17g\xda\xdf\x88\ -\xa7/Es<\xdf\xbf\xfd\xcfmh\x1c\x04\x84d\x01\ -\x15\xcf\x99\xc3\x91\xb5\x98\xe6\x18\xeb\x1f\x22\xcc\x85\xc9-\ -\x97\x92C\x1b\xa3vw\xae\xfd\xfeAT\xc0\xf8]\x18\ -\xae\x060l\x1e\x91\xc5\xc2=G\x93g\x0c`\xf2\x04\ -\xbb\x06D\xfc\x99<\x0f!l\xac~\x0f\xb71\x04\xe0\ -\xb41K\xcd\xfd\xc0\xa3\xb7\xcc\xfa 1\x99\x81\x0e\xbd\ -\xf8\x00\x95\xac\x1b\x96\xc2rnfM\xcc9\xa1\xa8\xe7\ -!\x91\x02\x02\xb1,\x0d\x02\xf8\x9c\x0e\xc1DQ\x06Q\ -D\x14\x03\x10-\x15\xc0\xeb\xfe\x021h\x82)a\xe4\ -;\xd6`\xe9\x8cC\x8cl\xc6Q\x9e6#@\xce\x1a\ -\x11\xacb\x0e\xb8\xdc9\xa1\x8c4|b(V\xc1\xb0\ -c\x07a\xca\xaecm\xa9\xb6@\xb7\x22\x88 s\xb6\ -\x220E\xc5\xc3\x07=\x15\xc0\xb0\x1b\x09R,.\x04\ -\x09\x1c\x14\x01\x5c\x91\x06\xf0\xa8\x8f\x15!\xad%\xc6X\ -\xbf\x93B\xbc\x5cI\xd1J\x9fG@\xe3o\x90a\xe3\ -Gh\xf0F\x9d[\xeb}\xaf\xbe??\x16H\xf5H\ -\xe4,\x1fln#D\x85P\xd8\x81h8T\x81\xc0\ -\xd3\x840\xa6l\x0d\x92`]C\xf2M\x0b\xf1^)\ -\xe6@\x90B\x83Dc)8\xe4\xf9%3\x88\x87O\ -\xe2\x12\xc3\xd7$\xfc\xc8\xe3\xb8}r\xd5=\x01y\xbc\ -\x07\x03\x8c\xe1\x11\xc1\x12r\x05W\xf6/\xa7@\xad\x11\ -\xd3\xac9J\x01\xc4\x98_\x0cs\x8e\xb0rJ\x10\x97\ -\x96\xee\xe5[\xd2\x9a\xf0\xa6A\x11\x09\x08\xdd\xdb\xcaD\ -\x00\xb4\x0c\x03\x05\xba\x0c\x1c\xa1\x10|D@%\x12D\ -\x90\x00z\x07\xc0\xf6\x13\xd4LB\x8aJ,#]\xc2\ -@\x99\xf1\xd2h\x91\xb7V\xc6\xe6\xac\xadW2\x01\xca\ -O\xd7-\x11\x1f\xc4\xdcE \xe2\x96\x04d\xce\x1d\x84\ -\x98\x1e\xa6@\x9a\x87\x11\x11\xc7M\xc6\xe3\xa3\x0d\xa3\x1a\ -\x9e\x0b\x84L\xf8`\x08\x8c\x15\xee\x98\x18\x03\xc7\xd2<\ -eS\xd0\x84\xd06\x92\xbfR',\xa5\xa3\xfaA\x09\ -L4\xd5Q\x06\x18j\xc0z\xa6\xa4\x80P\xd5\xd1\x12\ -%k\x00zhd\xba\x1a8!Y\x0d\xe0\xf2\xe1\x84\ --\xa2\x90\x91VC\x0f\xc4HV\xaeA\xb2z\x90\x87\ -p\xf6d1.\x01\xb5\xec\x08\x08J\xfc)A\xdd\x81\ -\x09Ul\x93\xd3\xc1\x8c.\x03\xdd\x89\x0b+0\x96Q\ -\xb9\xe7\x1d\xea;\x98q\xae>\x1e\xb6\xf9`\xf5\xcc\x9b\ -\xeb\xaf$\xa5\x88\x82 UPE\x852\x03\xc0\x96\xc2\ -\x12\xean8\xc6\xe3.\x0e\x81A\xb5)\xe2Oc\xa8\ -\xec\xa82\xd6IoYJD\xec\xa7\xe5N\x22Oa\ -\xdd\xbd\xb7\xbaI\xcd 6\x08u\x04W\x93\xc0\x1bi\ -PP\xf6\xb9C\xd2\x97\x85#\xdc2\x05\xd9$\x86\x90\ -f'\x02\xf0w]H<\x07\x9a\x90\xf0\x8b(p\x11\ -\x5c&\xc5\x98\x1fc\xea\x22\xd5\x22D\x0d\xef@D\x9d\ -b8Y2\x1b\x90\x90\x12x\xf8\x0eW\xcc'\x5c\xfb\ -\xa2G\xe5#\xa4\xa8\x8e\xa2\x93:\xa3-R_uK\ -\xa4\x8a\xfa\xec\x10i\xfff\xc8\xe5,\x07\x01\x1a\xf5\x8b\ -\x1b\xbc\x91#p\xeb\x1c\xc2\xf7\x0a\x0a\xcb\x0c-\xe7t\ -b\x1d#\x8c\xa9D\xb0*\x06\x84\xbe!\x17\xb2 \x0e\ -'\xab\xe3|\xc3\x90O\xb9\xe2\xe8\x8eO\x17\xc9Z(\ -\xf5\xb3\x7f\x16O\x01+\xb9\x03n\xa4\x1d\x99\x82T\x04\ -\x8d\x83\x9c|\x11\xc4nA\x16\x18=\x14\x8e|\x8c8\ -D\x86I\x0es\x14W\xd62\x22+\xf2\x80\xdbF\xe0\ -t\x12);\xe2\x1c\xf2\xc0P\x18\xf9l\x5c\x91\x8c]\ -\x1d1\x85\xb2c6\xd1\xc7cW'\x81/\xe9\x0d\xb7\ -\x8f6\xdf\x11\x89\x22\x0a\xc1\xa8\x99\xceC\x00\x04gP\ -\x14\x90(\xb0\xa4\x11\xa2c>\x07\xda =\xc8\xe6P\ -\x15\xf9I\x1c*\xaa =\x9f\x5c\x97\x1a\xc30\x8a_\ -\x985\x07+L cx\xd2\x1e\xd7\x0a\xe4\x15\xab\xa6\ -i\x82\x06M\xec\xe6\xd2&\x065\x00\x1e\xab\xa2\x84d\ -\x81=L\x06\x111\xe6\xa7B\xafV\x09bI\xa0\xb4\ -&To\x83\xb7Z\x0e\x80\xbf\xad\xc1\xb4\xa0\x94D>\ -\xb2\xc3g\x0b\x0e3\x15Hn\xd3\xe4\x8b\xdd\xe0\xe1\xb1\ -\xc4XU\xd9A\xaf\x02\x90\x5c\x0f\x8f\x08q9\x01\xc2\ -wj\x0cPG\xb5\xc1b@\xaf\xc2\x102\x8b\x0d\xbc\ -'\x09F\xb0\xcayU\xcfY5\x9c\x0f \xf8\xf3!\ -\x9a\xf4D\x8a\xc9M\xb3H#\x89n\xdaR\x91T\xcc\ -\xd1\x8e'\xf6:\x90\xbb@\x84\x94\xf1\x1f\xbf\xc5\x98<\ -\xe0A- \x0bN\x0c(\x04\x07\x09\x0c$\xb3qh\ -W\xbe|F\x10\xb2\xcb\x01\xcc(,l\xbe\xf9u\xfc\ -\xd2U\xd0\xed\x8f=&\xde\x16\xb9\x00p\x88w\x8fN\ -\xa0\xeb~B\x96p|P\x01\xa0A\xa4\x01\xcd\xcb\xc7\ -\x06\x97\x05z\x1f\x86e\x1d\xc7\x0cD\xa79\x0f\x02\x83\ -\x9e\x08\x92\x11\x0d\x04GA\x15P\x13x\x108\xbc;\ -\xde\xce\xf4\xad\xc9sKW>\x8a@\x9d\xc7+\x08:\ -x\x83_\xb4\x92&\x86\x038\xdbU\xfbn\xed\xf2a\ -\xc3u\x94\x16\x98p\x88\x1eR\xa2\x05\xa3\xad\x89\x19\xde\ -N/\xa5\x11H\x18\x88/\x09\x1a\xd9\xee\xf8\x82m)\ -\x90)\xc6\x90\x19\xef@} da\xce8B\x8f\x81\ -\x04\xb2\xcb\xaf\xf3n\x1d\x12G\x17\x89\x1b|\x80-\x03\ -\x0d\x0f\xc5\xf3\x09\x19\xa3\xee\xb6\xb6\xf6\xe6\xdd\x0a\x1d\xa7\ -O\x00\x1d\xce\x0a\x00\x09\xc2\x1cDm\x06\x0ba\xc9\x22\ -\x0a/L\x22\x84\x97\xa9\x0e\xe8'\xb0nK\x08'=\ -\x80\x82\xcf\x82`?\xf9\x0e3\x1eVk\xad\x8f\x90\x9a\ -\xdcy\x9d4B\xdf\xba\xb1\x96\xb5\xec\x06\x81\x01k\xf1\ -\xc7\x19<\x01\x89\x13\xa9\x22\xc1\x980=g\x86\xec6\ -\x13\xa3\x84\xcf\xac\x07\x99\x0c\xf2\xed$b\x0f\x8f-'\ -ms7q#>s[\x85\xf0\xec\xae\xb9\xf2C\x1f\ -?\xac{\x83\xff\xdc\x03\xfc\x22\x08\xf5\xb7\xbc\x81\xef\xf1\ -\x1e\x1c\xbe8\xb5\x14w\x12\xfd\xe9\x1f\xbcu\xae\xda\x22\ -j\xdeZ\xed.\xd3-\xf0\xa4\xeeH\xb7\xaeL\x120\ -\x18\x16\xab\x02\x07k\x06He\x06\x1c\x81\xbaC\x80\xa0\ -\xf5\xc4\x14\x03\x904\x04F\x1e$\x8b\xd6\x16KD\xa6\ -\x84\x86\xe2\x01f\x100L\x0c+\x88\xfbb.ul\ -\xc8\xb6\xce\x96W\x0d\xec[P\x0e!\xcf\x82\x7f(\x8e\ -\x15\xd0p\x1b0BH\x89\x96\x18\xae\xc8\xa6\xaff\x17\ -\xc0i\x08`\x82H\x83\xe8\x1c\x01\xb0s\x09\xe4\xbfo\ -5\x05\x8cf\xfc\x09\xac\xc0pdXb&\xf3\x81\x8b\ -\x0a\xe1\xec\xbd\xc4\x86\x18\x90\xb8\x16\x8d\x8e\x0e\x00\x9a\xa6\ -\xab\x88\x91\xc0\x80\x0a\x04\x88\xfda\xf2\x1e\xe0\x97\x0d`\ -<\x9eO\x22#\x0e\xd6q\x90\xa0\xde\xb0\xa4\xf3J\xee\ -wh&\x16P\xf4\x1b\xe05\x0f\xa0@H\x8b|\x0c\ -Q\x04\x07Jj\xf6\x018\x18J\x88\x94\xe4\x82\xe5\xe1\ -\xcc\x1b\xef\xca\x06\xea\xcd\x0d\xe2.\xbbEb\xf2\xb0\x04\ -\x8f\xecl\xa9\xb0\xa8\xb7jP\xf8G6\x12\xd1@\x17\ -k\x82\x08\x84\x88=a\xca\x1b\xc0\x9f\x15 F\xa6\xb0\ -p\x15\xd0t\xa6d\x88\xc5f\xbe\x0f\x80\xb6\x830\x98\ -\xf7\xe2\x14\xfb\xaf\xbe\xcc\xb0\xa3\x13-\xef\x13lr\xbc\ -k4o'$\xfc\xafVHk\xe2\xfd\xc0~\x01\xe4\ -.{\xe6\x1e\x18\x11\xa0\x1e\x0c\xea\x01\x0c\xeeHj&\ -\x13\xc1\x0a\xee\xe1#\x09g\x91\x17\x09\xec3'\xd7\x00\ -\x22$d/z~\x91\x80\xdf1\x84\xc7g|\xef@\ -2\x03\xe1c\x1d\xe1\xba\xebD\x86\xaa\xa0\xd2\x08a\x97\ -\x1e\xe1|\x7f`g\x1f`~\xceA2\xfa\x04\x86>\ -\xe0\x9d `B>\xf0\xdc\xf6\xe25\x0e1\xc4\x220\ -\x06\x88\x10\x0a\xf3Pj\xec\xc0\x00\xe8!\x10\x15)\xc8\ -\x08\x80\xacH\x8c\xf2\x11\x8c\x92\x12\x00\xea\x7fj\xe0\x0b\ -\xd2D\x0e\xc4\x89\x0fAd\x13\xe1\x05% \xc4\xb6\x0d\ - \xc6,\xc7\x09\xf1y\x0e\x85v\xfcB0\xf3\x82\x09\ -\x03@8\x04D\x98\x14\xc1\xa0\xb8\xc4\x80\xc3A\xc7\x02\ -\xc0I\x19\xa5\x88\xa0`\x0a\x00\xcd`\xd4\x000\x03\xc4\ -\x80Y\x85z\x05\x81\xd5*!\xca\xdd\x8a\xcf!\x0e\xd5\ -\x1c\x0d\xe7\x0ep^\xa4rfd\xeeF\xbc\x8aR\xbc\ -\xc2\x0a\xfa\xc0\x98\x0b\xce\x12\x10\x01BH\x92(\x0d!\ -Y-\xa10o\x84\x00\x0a`\xce\x0f2\xe9-\xe4\x86\ -\x0fR\xf0\x0b\x01u/aR \x8c\xbf*\xa0d\x80\ -\xb2\x12\x9aq*\xbb\x92\xb7\x062 \xdfJ\x00\xee\x82\ -\x17,\xe1?,\x80\xc0H\x09\xdc\xd9@\xaa\x05A\xef\ -2\xe1\xeaRj\x16\x01r\xda\x15\x81\xae\x9b\xc0.\x03\ -\xa4\x80\xdb\xc1`\x13m\xb6\x0c\xc2\x104 \x1e\x02g\ -F\xe3\x13\x02\xb22a\x05\xcf-\x06\x10\xeb\x1b\xc2\x11\ -\x222\xc4!\x11\xa6\x01-\xa8\x13\xa1\x8a\x04\xf3\x80\x06\ -$\x80\x93\xa1p\x14\xb1f\x0b\x85&\xdbaJ\x09\x13\ -\x98\x0bD\x80\x8d\x01\xb0\x19\xb1\x04\x0c@v\xa3\x22\x0e\ -\xf6\xc7\xce\xff\xd1w6Q/6\x92\xbav\x89be\ -\x88^\xdf\x82\x19)@:\x13\xf3\xd0\x19\x0c<\x03D\ -\x80p@\xd6\xd5\x81V\xd5\xc4\xc0W\xa0\xd8\x0e\xb3\xec\ -\x12d\x81*!\xd4\x1c\xa5\x1a\x0c\x00o?A\xca\xdd\ -f\xbb\x122\xad\x0e\x13\x08VS\x0d6r\xb8\xcc\xf0\ -\xa7&\xb1;\x06\xc9l\x223\x80\x04\xe0`B!6\ -\x18o\x94D\xc2\xa5\x01\x81\x22\x0e\x8c\xf2\x11\xc4\x81$\ -@\xbc\x0e\xaf\xd0\xf3B@\xb9A\xec\x1ef6\xd8\x82\ -\x1d5@'\x052Z\xd8*AA3\xbbAlo\ -\x1c\xf0\x10\x1fNJ{\x821\x01\xe0\x92\xfe\xc1g\x1e\ -DQ3\xa1,\x12t\x8c\x0f\x0d\xd2%\x8d\xa4\x87\xe1\ -\x14\x0aT\x9c\x0c\xe4\x80<\x01\xfb\x0b\xe0\x98\xb0\xca|\ -\x22k\x1d\x16\xf0f!\xb1u\x00\x12\xb5AJ\xe0[\ -2\xbf\x18s\x18#I\x16\x09@\xb9,\xe1AHD\ -N\x1d\x94\xdc\x1c\xeer\x12\x80\xf38\x81L\xfe\x225\ -(\xc0\x0d9\x80\x90\x0bG$?@$\x02\xf4\xa22\ -\x01\xfb,\xe0\xc0\x16\xd5\x0c\x14\x821%\x8b!%\xc7\ -XY\xf1-\x1cq1A\x90\xecH\xe70\x1a\xb5,\ -\x19BAO@\xb3%!\x04\x14t\xd8H\x0e\x8f\x1a\ -\x01\x80\x16\x0c\xb6\x18\xe1p\x9d\xd3\xf4\x1c\x82\x08\xc4\x92\ -\x94\x03\xd4}\x19@\xa0\xf8\x80 H\x94\xa4\x0f\xd5l\ -\x0b\xb3\x88\x14\xecZt/\xb4\x9e\x93l \xef'Q\ -\xd4iR\x13\xbdRU~\xc0\xd3\x14\xc1\x02?\x22\xe0\ -\xa8\x10\xb5\x9c\x14\xe9\x80\xfe\x84P\x98k\x12\x0f`\xb4\ -\x17\x95\xb0\x15b@\xed\x14b\xf2LdV2\x16\x22\ -\x12\x1a\xae.\x9dX\xe2\x0aw\x15+R\xe2Q\x0c\x80\ -\xa0K\x01\x0c\x14\xec\x89ZB^w\x15\xaa\x0b,\x98\ -$\x93\xb0\xd8\x15\xbc}M\x86\xa9Qz\x11\x12h\x22\ -\xf2l%`S`\xa0f\x835[^BQ(\x13\ -\xec\x0e\xa0\xa4\xd1M\x18\xb5\xf4\x06Gm\xdf\x5c\xc2\x09\ -\x09\xd5\xc1K\xf4k1\x16, p\xeey\xb5\x94%\ -G\xc3\x22\x81S\x08`h\x08V\x14#\xe1\x9bea\ -\x80\x0f\x16\x5c\x0a\xc1\xdff!\xd6\xb1\xa6\xbbW\xb5\x16\ -#O\xba\xec\x95\x1f!\x95#`\x22,\x96S\xc7L\ -\xa2b6\x00\x06r@\xb9h\xe0\xe9e\x22-'a\ -\x1e\xf5!$\x0e\xc8X\x1f\x82aE\xd4af\xf5\xf6\ -\x1e0Z\x9fD@\xb2\xee\xe5Y3\xc8D\xb4|\xb5\ -A$\xe6\xf6\x94 \x90&\x1b\xaa\x82\x0d\xf0\xb8\x18\x81\ -j\xa7\xe7C\x16\xd1\xbbKb\x19c\x00}\x5c\x22\x1e\ -\xed\xf3\xbe\x0d\xd4\xc7\x1dO:H\x14\xf0\xf4J\x10l\ -\xea\x14Djk2\xe1\xee\x1e\xb3\xd0\x13\xe1\x0c\xcf*\ -0H\xe4\x81j\x88\x02\x15\xf0T\x22\xd6\xe9n\xc2\x1c\ -\xbb\xd4\xc3\x13T\x1c\xbck\xca\x88\xe4\xf4\x91\x006N\ -\x80\xde\x11`\x8ft\xa0\xb2\x7fr\xf6\x17ASC\x80\ -\xe8\xc3UTL\x0d\xd8\x15h\xec\x07\xcf5\x12\x94\x10\ -\xe3\xb5\xffF\xe20\xea%\x00\xeanLUV\x0a\x05\ - f~`\x8bx\xa0\xaeP\xe0\x0eL#\xee\x17w\ -\x98\x15!Qy\xe1%b\x05'[\x96\xad@\xce6\ -\xbbwp\xb6\xe5Ek\x8f\xc62f7R\xc1\xabS\ -\x07<\x86\x97J\x08\xe0\xb1]\x97gZ\x22V\x98a\ -\x9f}\xa1\x87TAau!P\x1d\xd7\xe8\x1dIG\ -W\x87\xc70\x13\x04#/\xbb:`v\xf7k+{\ -f\xe3+\xf7;B(b\x8bIp\x07\x14&\x06$\ -z\x06\x13\xcc\xf8\x80#VB\xbeU\xa8\xc032\x80\ -\x8c\xa1\xb2\x19\xe7\xda\x1a\x0b|\xe8\xe8c_.4\x1e\ -\x07\xb3E\x92\xb7\x1c\xb3\x13\x1d-\xf7hV\xcb\x85b\ -7*\x91%r\x83-Fw\xb30\xf3knO\x81\ -k\xd8U\x85\x98t\x22\xd7\xa9\x11W\xac\x1e\x11\xc3c\ -U\x89F\xd75`Xqo\xb8w\x89\x22%\x84\x15\ -\x19\x86H\x15\x86\x96\xf3\x80\x92\xc3s\xd8\x95\x8a\xb8\x97\ -\x7f\x0c\xc1@\xb1'+\x0e\xd9\x88Vx\x95\xc6J\xb7\ -4q\x06\x8d9\x01Ty\x8a\xd8\xd0!\xd2\xa9b\xb8\ -l!U\x82u\xd8f\x22\x970Z\xf6|\x22\xb6\x80\ -\x7f\x16C\x8d8\xf4 \x98]\x8bXa%\xf63&\ -2\xb6\xe9\xad1\x84\xf2\xc1\x13\xd8\xa9\x8fy\x14 \xb8\ -\x99FO)Xx\xbe\x84\xe6H~y\x0d\x80\xb9\x17\ -\x92\xe2\x06\xa8\x17\x22\xff\xa27g*\xd9\x92\x15\xc5R\ -7t\x22\xe9e\x22\x80\xd4FA\xbeF\x82\xe8.\xe3\ -v^B\xb2_C\x19\x96\x06p+b\xbfJT\x84\ -/\x02\xd5\x96\x83zic\x96;Y^6\xa2\x86`\ -\x09\x81\x97B\x1c+#\x0ciF\x9c\x1f\xc1\xfb\x97\xe3\ -\x1cjf\x04-#j \xe3\x94\x1f\xc3\x8c9\xa2\xb7\ -\x96b\x87\x82\x00\xd7\x9ba\x0b\x81\xaa\x8f\x89\xcf\xc3+\ -\xc2>\x96F\x0ak&\x08j\xa3\x14;\x85\xfc!\x86\ -\xa2_\xa5\xe4\x5c\xecpj\xc2\x0b\x9eFl_\xd9\xe0\ -^&\x7f\x9d4\xb7\x9eFy\x9c\xe2\x84]\x82\xcf\x95\ -e\xda^\x06\x1fD\xc2\x07r\xb8\xbd\x945\x8b\x94y\ -1\xa1\xa4\xf7\xa1\x19\x05\x8eD5s1\x7f\xa1\xda,\ -O.\x8e}vw\xa1@\x12\x0dZ<\x10\x97\x01\xa2\ -\xfaDO7\xe8\x1d\xc1\xd4\xe5`\x84S\x81\xbc\xb5\xcb\ -\xbaC \x0fh\xe0\xb8\x0e\x91\xe8\x10z\x0d\xa4zl\ -$\xbaT\x1a\xd7D\x09N\xfc\x1c\x220\x98\x00\x83\xa8\ - \xa3\x04\xc1\x02\x140\xb5\xa6\xfa\x90AC\xcdN\x88\ -\xe6\x0d\x87V#\x02\x9f\x0458\x14L\xde\x06\xda\x93\ -\xaa\xe4\x10\xd6\x81\xda\x1d\x19L\x18:\xbc\x16T\xa4#\ -\x86B\x97\xa0\xa9\x0b\xe1\x19O\xc0-\xab\x1a\xd4$\xe7\ -W'a \x15:\xe0\x12a\xe3\xaea\xda$\x87\xfc\ -\x02Q\x94\x09\xd0\x0a\xda\xe0F\x05r\x8dy\x22'\x9d\ -\xb9\xd9\x9dC\xac^\x19\xeb\xb0\xa3\x93\x9e\xfb\x0f\xb0c\ -\xb3\x9d\xa3\xc5\x9f\xc3\xac\x9e\xb9\xef\x95\xbb\x1e_\x99\xca\ -!Y\xf2a\xbb*_\xe6j)k\xe2\x1c;@\x1b\ -1\xde\x16!=[\x01x\x15zJ\x1d\x22P)\xe6\ -B\xdch\xa8\x06PCVB\x9fN\xd9\xdc`e\xf9\ -\x9d\xb9\xe4gC\xb0h\x05\xfd\x9d\xa6\x8a2\x02\x08g\ -\x14\xa5\xb2Y\xd0a\xa2\xa4j\x86\x1a`\x1a\x00X\xe0\ -\x02<\xdb\x8f\x99\xe2\x05\x99\xc2\xdf\xb7\x99\x5c8\x1bu\ -\x8c`\x01\xb7\xe1\xfd\xb2b\x0eJe\xd4\x1f\xbb\x82@\ -\xb0\xd0\x1f\x18(\xb4\xe1\xb9\xa7)@\x1c7\x0c\x1e\xbb\ -.$\xa2\x9e\x98\x06\x1f\xb9\x03\xb4\x22\x99\xf8A\x1b\xb8\ -H[\xea$[\xf2K\xc3\xcc\x98t\xa5\xbd\xba\xd7\xc0\ -<\x05\xc0|\x09\xc0\xbc\x0d\xc0\xe2\x08 \x00\x00\x03\ -\x00\x01\xa0\x03\x00\x01\x00\x00\x00\x01\x00\x00\x00\x02\xa0\x04\ -\x00\x01\x00\x00\x00`\x00\x00\x00\x03\xa0\x04\x00\x01\x00\x00\ -\x00`\x00\x00\x00\x00\x00\x00\x00\x00\x00Adobe\ - Photoshop Docum\ -ent Data Block\x00M\ -IB8nrTM\x00\x00\x00\x00MIB8r\ -yaL\xdc\x19\x00\x00\x01\x00\x03\x00\x00\x00\x03\x00\x00\ -\x00]\x00\x00\x00\x5c\x00\x00\x00\x04\x00\xff\xff\x9b\x0b\x00\ -\x00\x00\x00C\x04\x00\x00\x01\x00C\x04\x00\x00\x02\x00C\ -\x04\x00\x00MIB8mron\xff\x00\x08\x00<\ -\x01\x00\x00\x00\x00\x00\x00(\x00\x00\x00\x00\x00\xff\xff\x00\ -\x00\xff\xff\x00\x00\xff\xff\x00\x00\xff\xff\x00\x00\xff\xff\x00\ -\x00\xff\xff\x00\x00\xff\xff\x00\x00\xff\xff\x00\x00\xff\xff\x00\ -\x00\xff\xff\x07Layer 0MIB8i\ -nul\x14\x00\x00\x00\x07\x00\x00\x00L\x00a\x00y\ -\x00e\x00r\x00 \x000\x00\x00\x00MIB8r\ -snl\x04\x00\x00\x00ryalMIB8d\ -iyl\x04\x00\x00\x00\x03\x00\x00\x00MIB8l\ -blc\x04\x00\x00\x00\x01\x00\x00\x00MIB8x\ -fni\x04\x00\x00\x00\x00\x00\x00\x00MIB8o\ -knk\x04\x00\x00\x00\x00\x00\x00\x00MIB8f\ -psl\x04\x00\x00\x00\x00\x00\x00\x00MIB8r\ -lcl\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00M\ -IB8dmhsH\x00\x00\x00\x01\x00\x00\x00M\ -IB8tsuc\x00\x00\x00\x004\x00\x00\x00\x10\ -\x00\x00\x00\x01\x00\x00\x00\x00\x00\x08\x00\x00\x00met\ -adata\x01\x00\x00\x00\x09\x00\x00\x00lay\ -erTimebuod\xc2\x93A\xe0\xf78\ -\xd6A\x00MIB8prxf\x10\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\ -\x00S\x00O\x00\x0f\x00\x0c\x00\x0a\x00\x09\x00\x09\x00\x09\ -\x00\x09\x00\x15\x00I\x00K\x00\x12\x00\x14\x00\x14\x00\x12\ -\x00\x13\x00\x13\x00\x13\x00#\x00!\x00\x1e\x00\x1d\x00\x1f\ -\x00\x1d\x00\x1d\x00\x1d\x00\x1c\x00\x1e\x00\x1d\x00(\x00'\ -\x00&\x00&\x00&\x00%\x00$\x00$\x00\x22\x00 \ -\x00 \x00\x1e\x00\x22\x00\x1f\x00\x1e\x00\x1e\x00\x1f\x00!\ -\x00 \x00 \x00#\x00!\x00%\x00%\x00$\x00'\ -\x00(\x00(\x00+\x00\x1d\x00\x1d\x00\x1d\x00\x1d\x00\x1c\ -\x00\x1d\x00\x1e\x00\x1e\x00\x1f\x00 \x00#\x00\x13\x00\x13\ -\x00\x13\x00\x12\x00\x14\x00\x12\x00\x13\x00\x13\x00M\x00L\ -\x00\x09\x00\x09\x00\x08\x00\x09\x00\x0a\x00\x0a\x00\x0c\x00L\ -\x00W\x00 \x00\xfd\x00\x04\x05\x11!-1\xfe/\xfc\ -0\x181//0110010/1/0\ -010/0110/01\xfe0\x0a/2\ -1100/00//\xfe1\x000\xfe1\x05\ -010/01\xfe0\xfe1\xff0\x081/0\ -/-'\x18\x08\x01\xfe\x00\xff\x00\x07\x01\x14X\xab\xdb\ -\xec\xf0\xf0\xfd\xf1\x00\xf0\xfe\xf1\x00\xf2\xfd\xf1\xff\xf0\x01\ -\xf1\xf0\xf8\xf1\x03\xf0\xf1\xf1\xf0\xfe\xf1\xfe\xf0\x07\xf1\xf0\ -\xf0\xf1\xf1\xf0\xf1\xf0\xfc\xf1\xff\xf0\x1b\xf1\xf0\xf0\xf1\xf2\ -\xf1\xf0\xf1\xf0\xf1\xf1\xf2\xf0\xf1\xf0\xf1\xf0\xf0\xf1\xf0\xee\ -\xe4\xc2|.\x06\x00\x00\xff\x00\x03\x16\x86\xed\xfd\xb3\xff\ -\x04\xf9\xbfA\x06\x00\x03\x00\x08l\xf4\xb0\xff\x03\xfe\xbd\ -*\x01\x02\x00$\xd0\xae\xff\x02\xf8x\x07\x02\x02O\xf6\ -\xad\xff\x01\xc0\x14\x02\x05r\xfd\xad\xff\x01\xe1#\x02\x08\ -\x86\xfe\xad\xff\x01\xed+\x02\x08\x8f\xfe\xad\xff\x01\xef-\ -\x02\x09\x91\xfe\xf1\xff\x00\xfe\xdb\xff\xfe\xfe\xfd\xff\x00\xfe\ -\xec\xff\x01\xef,\x02\x08\x91\xfe\xfa\xff\x17\xfe\xcf\xc2\xc3\ -\xc2\xc4\xc3\xc4\xc3\xc3\xc4\xc4\xc1\xc3\xc3\xc2\xc3\xc2\xc2\xc3\ -\xc2\xc3\xc4\xc4\xfe\xc2\xfd\xc3\x0a\xc2\xc3\xc3\xc2\xc3\xc3\xc2\ -\xc3\xc2\xc2\xc1\xfe\xc3\xff\xc4\xf9\xc3\x06\xc4\xc3\xc3\xc4\xc2\ -\xc3\xc4\xfe\xc3\xff\xc2\x01\xc7\xf1\xf9\xff\x01\xf0-\x02\x09\ -\x90\xfe\xfa\xff\x03\xfaK\x18\x17\xfc\x18\x16\x17\x18\x16\x19\ -\x17\x18\x19\x19\x18\x19\x18\x17\x18\x19\x19\x18\x17\x17\x19\x17\ -\x17\x19\x17\xfb\x18\x11\x17\x16\x18\x16\x19\x19\x17\x18\x18\x19\ -\x18\x18\x19\x17\x19\x18\x19\x18\xfd\x19\x08\x18\x19\x19\x18\x19\ -\x19\x17,\xc7\xf9\xff\x01\xf0,\x01\x09\x90\xf9\xff\x01\xf9\ -8\xc0\x00\x01\x15\xc0\xf9\xff\x01\xef.\x02\x09\x91\xfe\xfa\ -\xff\x01\xf97\xc0\x00\x02\x14\xc2\xfe\xfa\xff\x01\xf0-\x02\ -\x09\x90\xfe\xfa\xff\x01\xf88\xc0\x00\x02\x14\xc2\xfe\xfa\xff\ -\x01\xef/\x01\x08\x90\xf9\xff\x01\xf99\xc0\x00\x01\x14\xc1\ -\xf9\xff\x01\xf0/\x02\x09\x90\xfe\xfa\xff\x01\xf97\xc0\x00\ -\x01\x12\xc0\xf9\xff\x01\xef-\x02\x09\x91\xfe\xfa\xff\x01\xf9\ -8\xc0\x00\x01\x14\xc2\xf9\xff\x01\xf1-\x02\x09\x90\xfe\xfa\ -\xff\x01\xfa8\xc0\x00\x01\x15\xc1\xf9\xff\x01\xef-\x01\x09\ -\x92\xf9\xff\x01\xf97\xe7\x00\x0d\x1aU\x87\xb8\xd5\xe6\xf7\ -\xf7\xe6\xd6\xb9\x88V\x1a\xe8\x00\x01\x15\xc2\xf9\xff\x01\xef\ -,\x02\x09\x91\xfe\xfa\xff\x01\xf98\xea\x00\x03\x1bw\xc7\ -\xfe\xf5\xff\x03\xfe\xc9x\x1d\xeb\x00\x01\x14\xc2\xf9\xff\x01\ -\xf0/\x01\x09\x90\xf9\xff\x01\xfa7\xec\x00\x028\xa8\xfb\ -\xef\xff\x02\xfb\xaa:\xed\x00\x01\x15\xc2\xf9\xff\x01\xef-\ -\x01\x09\x91\xf9\xff\x01\xf87\xee\x00\x01\x1c\xaa\xe9\xff\x01\ -\xac\x1e\xef\x00\x02\x14\xc1\xfe\xfa\xff\x01\xef/\x02\x08\x90\ -\xfe\xfa\xff\x01\xf98\xf0\x00\x02\x06x\xf4\xe7\xff\x02\xf5\ -z\x07\xf1\x00\x01\x15\xc2\xf9\xff\x01\xf0-\x02\x09\x91\xfe\ -\xfa\xff\x01\xf97\xf1\x00\x01F\xd9\xe3\xff\x01\xdbH\xf2\ -\x00\x01\x14\xc3\xf9\xff\x01\xf0/\x02\x09\x91\xfe\xfa\xff\x01\ -\xfa7\xf3\x00\x01\x02\x85\xdf\xff\x01\x88\x02\xf4\x00\x01\x15\ -\xc1\xf9\xff\x01\xf1-\x02\x09\x92\xfe\xfa\xff\x01\xf88\xf4\ -\x00\x01\x10\xb5\xdd\xff\x01\xb7\x10\xf5\x00\x01\x15\xc2\xf9\xff\ -\x01\xf0.\x01\x09\x90\xf9\xff\x01\xf98\xf5\x00\x01*\xda\ -\xdb\xff\x01\xdb+\xf6\x00\x01\x15\xc2\xf9\xff\x01\xf0.\x02\ -\x09\x90\xfe\xfa\xff\x01\xf99\xf6\x00\x01C\xf2\xd9\xff\x01\ -\xf3E\xf7\x00\x02\x15\xc3\xfe\xfa\xff\x01\xef-\x01\x08\x91\ -\xf9\xff\x01\xf97\xf7\x00\x01D\xf6\xd7\xff\x01\xf7E\xf8\ -\x00\x02\x14\xc2\xfe\xfa\xff\x01\xf0/\x02\x09\x91\xfe\xfa\xff\ -\x01\xf98\xf8\x00\x01F\xf7\xf0\xff\x07\xe5\x91H*\x0d\ -\x0c&\xe3\xee\xff\x01\xf7F\xf9\x00\x01\x14\xc1\xf9\xff\x01\ -\xf0.\x02\x09\x91\xfe\xfa\xff\x01\xf98\xf9\x00\x01G\xf7\ -\xf1\xff\x02\xe0S\x02\xfb\x00\x00\xdb\xed\xff\x01\xf7G\xfa\ -\x00\x01\x14\xc1\xf9\xff\x01\xf0.\x02\x09\x91\xfe\xfa\xff\x01\ -\xf99\xfa\x00\x015\xf5\xf1\xff\x01\x8c\x09\xf9\x00\x00\xdb\ -\xec\xff\x01\xf54\xfb\x00\x01\x14\xc2\xf9\xff\x01\xf1.\x02\ -\x09\x92\xfe\xfa\xff\x01\xf99\xfb\x00\x01\x1e\xe7\xf2\xff\x01\ -\xfdj\xf7\x00\x00\xdb\xeb\xff\x01\xe7\x1d\xfc\x00\x01\x15\xc1\ -\xf9\xff\x01\xf0/\x02\x08\x93\xfe\xfa\xff\x01\xf98\xfc\x00\ -\x01\x0e\xd3\xf1\xff\x00d\xf6\x00\x00\xdb\xea\xff\x01\xd1\x0d\ -\xfd\x00\x02\x15\xc1\xfe\xfa\xff\x01\xef.\x02\x09\x91\xfe\xfa\ -\xff\x01\xf98\xfd\x00\x01\x01\xb4\xf1\xff\x00\x9f\xf5\x00\x00\ -\xdb\xe9\xff\x01\xb1\x01\xfe\x00\x01\x14\xc1\xf9\xff\x01\xef-\ -\x01\x08\x8f\xf9\xff\x01\xf99\xfd\x00\x00|\xf1\xff\x01\xdf\ -\x0a\xf5\x00\x00\xdb\xe8\xff\x00w\xfe\x00\x02\x15\xbf\xfe\xfa\ -\xff\x01\xee.\x02\x09\x92\xfe\xfa\xff\x01\xf89\xfe\x00\x01\ -<\xfc\xf1\xff\x00d\xf4\x00\x00\xdb\xe8\xff\x05\xfb7\x00\ -\x00\x14\xc2\xf9\xff\x01\xef.\x01\x09\x91\xf9\xff\x05\xf98\ -\x00\x00\x0e\xe0\xf1\xff\x01\xe0\x05\xf4\x00\x00\xdb\xe7\xff\x04\ -\xda\x0a\x00\x14\xc1\xf9\xff\x01\xf0-\x02\x09\x90\xfe\xfa\xff\ -\x04\xf98\x00\x00\x8d\xf0\xff\x00\x89\xf3\x00\x00\xdb\xe6\xff\ -\x03\x81\x00\x14\xc1\xf9\xff\x01\xef,\x02\x09\x90\xfe\xfa\xff\ -\x04\xf97\x00\x10\xf3\xf0\xff\x00@\xf3\x00\x00\xdb\xe6\xff\ -\x03\xee\x0c\x15\xc2\xf9\xff\x01\xf1.\x01\x09\x91\xf9\xff\x03\ -\xf98\x00v\xf0\xff\x01\xf6\x05\xf3\x00\x00\xdb\xe5\xff\x02\ -q\x14\xc3\xf9\xff\x01\xf1.\x02\x09\x92\xfe\xfa\xff\x03\xf9\ -9\x00\xb5\xf0\xff\x00\xdc\xf2\x00\x00\x22\xf7'\x00\xd9\xf0\ -\xff\x02\xb2\x13\xc2\xf9\xff\x01\xf0.\x02\x09\x91\xfe\xfa\xff\ -\x03\xf97\x00\xd9\xf0\xff\x00\xc4\xe7\x00\x00\xbe\xf0\xff\x03\ -\xd7\x15\xc2\xfe\xfa\xff\x01\xf0.\x02\x09\x91\xfe\xfa\xff\x03\ -\xf98\x00\xf6\xf0\xff\x00\xb3\xe7\x00\x00\xaf\xf0\xff\x02\xf6\ -\x14\xc1\xf9\xff\x01\xef.\x02\x09\x91\xfe\xfa\xff\x03\xf88\ -\x00\xdf\xf0\xff\x00\xc6\xe7\x00\x00\xc2\xf0\xff\x02\xde\x15\xc1\ -\xf9\xff\x01\xef-\x02\x09\x91\xfe\xfa\xff\x03\xf97\x00\xbb\ -\xf0\xff\x00\xdd\xe7\x00\x00\xd9\xf0\xff\x03\xb9\x14\xc2\xfe\xfa\ -\xff\x01\xf1.\x02\x09\x91\xfe\xfa\xff\x03\xf98\x00\x88\xf0\ -\xff\x01\xf7\x06\xe9\x00\x01\x05\xf5\xf0\xff\x03\x84\x15\xc2\xfe\ -\xfa\xff\x01\xef.\x02\x09\x90\xfe\xfa\xff\x04\xf98\x00\x1f\ -\xfc\xf0\xff\x00B\xe9\x00\x00?\xf0\xff\x03\xf9\x1a\x14\xc1\ -\xf9\xff\x01\xef.\x02\x09\x92\xfe\xfa\xff\x04\xf97\x00\x00\ -\xa9\xf0\xff\x00\x8b\xe9\x00\x00\x89\xf0\xff\x03\x9e\x00\x15\xc2\ -\xf9\xff\x01\xf0.\x01\x09\x91\xf9\xff\x05\xf98\x00\x00\x22\ -\xf2\xf1\xff\x01\xe2\x06\xeb\x00\x01\x06\xe1\xf1\xff\x04\xef\x1b\ -\x00\x15\xc1\xf9\xff\x01\xef.\x01\x09\x91\xf9\xff\x01\xf97\ -\xfe\x00\x00^\xf0\xff\x00h\xeb\x00\x00g\xf0\xff\x04W\ -\x00\x00\x14\xc0\xf9\xff\x01\xef-\x02\x09\x91\xfe\xfa\xff\x01\ -\xf98\xfd\x00\x00\x9f\xf1\xff\x01\xe1\x0b\xed\x00\x01\x0b\xe2\ -\xf1\xff\x00\x9a\xfe\x00\x01\x13\xc0\xf9\xff\x01\xf0.\x02\x09\ -\x91\xfe\xfa\xff\x01\xf97\xfd\x00\x01\x09\xce\xf1\xff\x00\xa4\ -\xed\x00\x00\xa5\xf1\xff\x01\xcc\x07\xfe\x00\x01\x14\xc1\xf9\xff\ -\x01\xf1.\x01\x09\x91\xf9\xff\x01\xfa8\xfc\x00\x01\x1d\xe5\ -\xf1\xff\x00j\xef\x00\x00l\xf1\xff\x01\xe4\x1b\xfd\x00\x01\ -\x15\xc1\xf9\xff\x01\xef-\x02\x09\x91\xfe\xfa\xff\x01\xf97\ -\xfb\x00\x010\xf3\xf2\xff\x01\xfer\xf1\x00\x01u\xfe\xf2\ -\xff\x01\xf2/\xfc\x00\x01\x13\xc2\xf9\xff\x01\xf0-\x02\x09\ -\x91\xfe\xfa\xff\x01\xf99\xfa\x00\x01I\xfc\xf1\xff\x01\x95\ -\x0d\xf5\x00\x01\x0e\x98\xf1\xff\x01\xfcH\xfb\x00\x02\x15\xc2\ -\xfe\xfa\xff\x01\xf1.\x01\x09\x92\xf9\xff\x01\xf98\xf9\x00\ -\x01\x5c\xfc\xf1\xff\x02\xe6_\x05\xf9\x00\x02\x06`\xe8\xf1\ -\xff\x01\xfc\x5c\xfa\x00\x01\x15\xc2\xf9\xff\x01\xf0-\x02\x09\ -\x91\xfe\xfa\xff\x01\xf86\xf8\x00\x01Y\xfc\xf0\xff\x09\xee\ -\x9eV8\x1c\x1c8V\x9f\xef\xf0\xff\x01\xfcY\xf9\x00\ -\x02\x14\xc1\xfe\xfa\xff\x01\xf0-\x02\x09\x91\xfe\xfa\xff\x01\ -\xf98\xf7\x00\x01T\xfb\xd7\xff\x01\xfbU\xf8\x00\x01\x14\ -\xc2\xf9\xff\x01\xf0.\x02\x09\x92\xfe\xfa\xff\x01\xf86\xf6\ -\x00\x01P\xf7\xd9\xff\x01\xf8Q\xf7\x00\x01\x14\xc1\xf9\xff\ -\x01\xf0/\x01\x09\x91\xf9\xff\x01\xf98\xf5\x00\x013\xe1\ -\xdb\xff\x01\xe24\xf6\x00\x02\x15\xc1\xfe\xfa\xff\x01\xf0.\ -\x02\x09\x91\xfe\xfa\xff\x01\xf88\xf4\x00\x01\x14\xbd\xdd\xff\ -\x01\xbf\x15\xf5\x00\x01\x15\xc2\xf9\xff\x01\xf1-\x01\x09\x91\ -\xf9\xff\x01\xfa8\xf3\x00\x01\x03\x8b\xdf\xff\x01\x8e\x04\xf4\ -\x00\x01\x13\xc2\xf9\xff\x01\xf0.\x01\x08\x90\xf9\xff\x01\xf9\ -8\xf1\x00\x01I\xdb\xe3\xff\x01\xdcK\xf2\x00\x02\x14\xc2\ -\xfe\xfa\xff\x01\xf0.\x01\x09\x91\xf9\xff\x01\xf98\xf0\x00\ -\x02\x06x\xf4\xe7\xff\x02\xf4z\x07\xf1\x00\x01\x13\xc2\xf9\ -\xff\x01\xf0.\x02\x08\x91\xfe\xfa\xff\x01\xf97\xee\x00\x01\ -\x1b\xa6\xe9\xff\x01\xa8\x1c\xef\x00\x02\x15\xc0\xfe\xfa\xff\x01\ -\xef-\x02\x09\x91\xfe\xfa\xff\x01\xf89\xec\x00\x023\xa1\ -\xf8\xef\xff\x02\xf9\xa24\xed\x00\x01\x14\xc2\xf9\xff\x01\xef\ --\x01\x09\x90\xf9\xff\x01\xf96\xea\x00\x03\x15m\xbd\xfb\ -\xf5\xff\x03\xfb\xben\x16\xeb\x00\x01\x14\xc0\xf9\xff\x01\xf1\ -,\x01\x09\x90\xf9\xff\x01\xf97\xe7\x00\x0d\x11Iz\xaa\ -\xc7\xd8\xe8\xe9\xd8\xc8\xabzJ\x11\xe8\x00\x01\x14\xc1\xf9\ -\xff\x01\xef/\x02\x09\x90\xfe\xfa\xff\x01\xf98\xc0\x00\x01\ -\x15\xc1\xf9\xff\x01\xf0-\x02\x09\x91\xfe\xfa\xff\x01\xf98\ -\xc0\x00\x01\x14\xc2\xf9\xff\x01\xef.\x02\x09\x91\xfe\xfa\xff\ -\x01\xf98\xc0\x00\x01\x14\xc1\xf9\xff\x01\xf0-\x01\x09\x91\ -\xf9\xff\x01\xf97\xc0\x00\x01\x14\xc1\xf9\xff\x01\xef.\x02\ -\x09\x90\xfe\xfa\xff\x01\xf99\xc0\x00\x02\x15\xc1\xfe\xfa\xff\ -\x01\xf0-\x01\x08\x91\xf9\xff\x01\xfa8\xc0\x00\x01\x15\xc1\ -\xf9\xff\x01\xf0.\x02\x09\x92\xfe\xfa\xff\x01\xf97\xc0\x00\ -\x01\x14\xc1\xf9\xff\x01\xf0-\x02\x09\x90\xfe\xfa\xff\x01\xf9\ -7\xc0\x00\x01\x14\xc3\xf9\xff\x01\xf1-\x02\x09\x91\xfe\xfa\ -\xff\x02\xfad;\xfe:\xfe9\x1589;;9:\ -:8;9:7:9:;99;:98\ -\xfd:\xff8\x017;\xfc9\x09;:9;;8\ -:979\xfe:\xff9\x09:89::8;\ -9J\xcf\xf9\xff\x01\xf0-\x01\x09\x91\xf8\xff\x00\xfa\xfd\ -\xf9\x08\xf8\xf9\xf9\xf8\xf9\xf8\xf8\xf9\xf8\xfd\xf9\x06\xfa\xf9\ -\xf9\xf8\xf9\xf8\xf8\xfe\xf9\x00\xf8\xfe\xf9\x0e\xf8\xf9\xf9\xf8\ -\xf9\xf8\xf9\xf8\xf8\xf9\xf8\xf9\xf9\xf8\xf8\xfd\xf9\x00\xf8\xfe\ -\xf9\x05\xf8\xf9\xf9\xf8\xfa\xfa\xfe\xf9\xff\xf8\x01\xf9\xfe\xf9\ -\xff\x01\xf0.\x02\x09\x91\xfe\xad\xff\x01\xf0.\x02\x08\x91\ -\xfe\xad\xff\x01\xee-\x01\x09\x8d\xac\xff\x01\xe9+\x02\x07\ -{\xfe\xad\xff\x01\xd5\x1f\x02\x04U\xf6\xae\xff\x02\xfd\xa3\ -\x0f\x02\x01'\xc9\xae\xff\x02\xe7Q\x03\x03\x00\x09]\xe9\ -\xb0\xff\x03\xf0\x80\x13\x00\xff\x00\x03\x12`\xcc\xf7\xfb\xfe\ -\x00\xff\xfc\xfe\x00\xff\xfe\xfe\x02\xff\xfe\xff\xfe\xfe\x05\xff\ -\xfe\xfe\xff\xfe\xff\xfd\xfe\x0a\xff\xfe\xff\xfe\xfe\xff\xfe\xff\ -\xff\xfe\xfe\xfc\xff\xff\xfe\xfe\xff\x04\xfe\xff\xfe\xff\xff\xfb\ -\xfe\xff\xff\xff\xfe\x02\xff\xfe\xff\xfc\xfe\x06\xfd\xf5\xcel\ -\x17\x00\x00\xff\x00\x08\x01\x0a.`\x86\x96\x97\x92\x92\xfe\ -\x91\xff\x92\x13\x93\x92\x92\x91\x92\x92\x90\x91\x92\x91\x90\x91\ -\x92\x91\x91\x93\x91\x91\x94\x91\xfc\x92\x05\x91\x92\x91\x91\x90\ -\x92\xfe\x91\x0f\x90\x92\x92\x93\x91\x90\x92\x92\x90\x92\x91\x90\ -\x91\x92\x92\x90\xfd\x91\x03\x93\x91\x90\x90\xfe\x91\x0b\x93\x90\ -\x90\x92\x8ayU+\x0c\x01\x00\x00\xfd\x00\x04\x01\x05\x0a\ -\x0c\x0b\xfb\x0a\x00\x09\xf2\x0a\xff\x09\xf0\x0a\x00\x09\xf6\x0a\ -\x00\x09\xee\x0a\x02\x08\x04\x01\xfd\x00\x01\x00\x02\x00\x02\x00\ -\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\ -\x02\x00\x02\x00\x02\x00\x02\x00\x06\x00\x06\x00\x06\x00\x06\x00\ -\x06\x00\x11\x00\x10\x00\x0c\x00\x0c\x00\x0e\x00\x0c\x00\x0f\x00\ -\x0e\x00\x0e\x00\x0e\x00\x0e\x00\x12\x00\x11\x00\x14\x00\x10\x00\ -\x12\x00\x14\x00\x12\x00\x0e\x00\x0f\x00\x0f\x00\x10\x00\x0e\x00\ -\x0a\x00\x06\x00\x08\x00\x08\x00\x06\x00\x08\x00\x10\x00\x11\x00\ -\x14\x00\x16\x00\x16\x00\x15\x00\x14\x00\x14\x00\x17\x00\x14\x00\ -\x16\x00\x0c\x00\x0a\x00\x0e\x00\x0f\x00\x0f\x00\x0c\x00\x0e\x00\ -\x0e\x00\x0e\x00\x10\x00\x13\x00\x06\x00\x06\x00\x06\x00\x06\x00\ -\x06\x00\x06\x00\x06\x00\x06\x00\x02\x00\x02\x00\x02\x00\x02\x00\ -\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\ -\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\ -\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xf4\xcc\xc1\xff\ -\xf5\xcc\xf4\xcc\xc1\xff\xf5\xcc\xf4\xcc\xc1\xff\xf5\xcc\xf4\xcc\ -\xc1\xff\xf5\xcc\xf4\xcc\xc1\xff\xf5\xcc\xf4\xcc\xe8\x00\x03\xcd\ -\xcc\xcc\xcd\xf8\xcc\x00\xcd\xe8\x00\xf5\xcc\xf4\xcc\xeb\x00\x02\ -\xcf\xcd\xcd\xf1\xcc\x00\xd3\xeb\x00\xf5\xcc\xf4\xcc\xed\x00\xea\ -\xcc\x00\xce\xed\x00\xf5\xcc\xf4\xcc\xef\x00\x00\xd1\xe6\xcc\xef\ -\x00\xf5\xcc\xf4\xcc\xf1\x00\x00\xd4\xe3\xcc\x00\xda\xf1\x00\xf5\ -\xcc\xf4\xcc\xf2\x00\xe0\xcc\x00\xcd\xf2\x00\xf5\xcc\xf4\xcc\xf4\ -\x00\x01\xff\xcd\xde\xcc\x00\xff\xf4\x00\xf5\xcc\xf4\xcc\xf5\x00\ -\x00\xcf\xdb\xcc\x00\xcf\xf5\x00\xf5\xcc\xf4\xcc\xf6\x00\x00\xce\ -\xd9\xcc\x00\xcf\xf6\x00\xf5\xcc\xf4\xcc\xf7\x00\x00\xcd\xd7\xcc\ -\x00\xce\xf7\x00\xf5\xcc\xf4\xcc\xf8\x00\x00\xce\xd5\xcc\x00\xce\ -\xf8\x00\xf5\xcc\xf4\xcc\xf9\x00\xec\xcc\x04\xcd\xce\xd7\xd4\xd0\ -\xeb\xcc\xf9\x00\xf5\xcc\xf4\xcc\xfa\x00\xee\xcc\x01\xcd\xff\xfb\ -\x00\xea\xcc\xfa\x00\xf5\xcc\xf4\xcc\xfb\x00\x00\xce\xef\xcc\x00\ -\xe2\xf9\x00\xea\xcc\x00\xcd\xfb\x00\xf5\xcc\xf4\xcc\xfc\x00\xee\ -\xcc\xf7\x00\xe9\xcc\x00\xd3\xfc\x00\xf5\xcc\xf4\xcc\xfd\x00\x00\ -\xda\xef\xcc\xf6\x00\xe8\xcc\x00\xd7\xfd\x00\xf5\xcc\xf4\xcc\xfe\ -\x00\x00\xff\xf0\xcc\x00\xcd\xf5\x00\xe7\xcc\x00\xff\xfe\x00\xf5\ -\xcc\xf4\xcc\xfe\x00\x00\xcd\xef\xcc\xf5\x00\xe7\xcc\x00\xcd\xfe\ -\x00\xf5\xcc\xf4\xcc\xff\x00\xee\xcc\xf4\x00\xe5\xcc\xff\x00\xf5\ -\xcc\xf4\xcc\x01\x00\xda\xee\xcc\xf4\x00\xe4\xcc\x00\x00\xf5\xcc\ -\xf4\xcc\x00\x00\xee\xcc\xf3\x00\xe5\xcc\x01\xcd\x00\xf5\xcc\xf4\ -\xcc\x00\xcf\xef\xcc\x00\xcf\xf3\x00\xe4\xcc\x00\xd4\xf5\xcc\xf4\ -\xcc\x00\xcd\xee\xcc\xf3\x00\xe4\xcc\x00\xcd\xf5\xcc\xe1\xcc\xf2\ -\x00\x00\xd2\xf7\xd1\xe2\xcc\xe1\xcc\xe7\x00\xe2\xcc\xe2\xcc\x00\ -\xcd\xe7\x00\xe2\xcc\xe1\xcc\xe7\x00\x00\xcd\xe3\xcc\xe1\xcc\xe7\ -\x00\xe2\xcc\xe1\xcc\x00\xd4\xe9\x00\xe1\xcc\xf4\xcc\x00\xcd\xee\ -\xcc\xe9\x00\x00\xce\xef\xcc\x00\xcd\xf5\xcc\xf4\xcc\x01\x00\xcd\ -\xf0\xcc\x00\xcd\xe9\x00\xee\xcc\x00\x00\xf5\xcc\xf4\xcc\x01\x00\ -\xd2\xef\xcc\x00\xd4\xeb\x00\x00\xd4\xef\xcc\x01\xcf\x00\xf5\xcc\ -\xf4\xcc\xff\x00\x00\xce\xf0\xcc\x00\xcd\xeb\x00\x00\xcd\xf0\xcc\ -\x02\xcd\x00\x00\xf5\xcc\xf4\xcc\xfe\x00\x00\xcd\xf0\xcc\x00\xd0\ -\xed\x00\x00\xd0\xf0\xcc\x00\xcd\xfe\x00\xf5\xcc\xf4\xcc\xfe\x00\ -\x00\xe2\xf0\xcc\x00\xcd\xed\x00\xf0\xcc\x01\xcd\xda\xfe\x00\xf5\ -\xcc\xf4\xcc\xfd\x00\x00\xd3\xef\xcc\xef\x00\x00\xcd\xf0\xcc\x00\ -\xcf\xfd\x00\xf5\xcc\xf4\xcc\xfc\x00\x00\xcf\xf0\xcc\x00\xcd\xf1\ -\x00\xef\xcc\x00\xce\xfc\x00\xf5\xcc\xf4\xcc\xfb\x00\x00\xce\xf0\ -\xcc\x01\xcd\xd7\xf5\x00\x00\xda\xef\xcc\x00\xcd\xfb\x00\xf5\xcc\ -\xf4\xcc\xfa\x00\x00\xcd\xed\xcc\xf9\x00\x00\xd4\xee\xcc\x00\xcd\ -\xfa\x00\xf5\xcc\xf4\xcc\xf9\x00\x00\xce\xeb\xcc\xff\xd1\xff\xcc\ -\x00\xcd\xee\xcc\x00\xce\xf9\x00\xf5\xcc\xf4\xcc\xf8\x00\x00\xce\ -\xd4\xcc\xf8\x00\xf5\xcc\xf4\xcc\xf7\x00\xd5\xcc\xf7\x00\xf5\xcc\ -\xf4\xcc\xf6\x00\x00\xcd\xd9\xcc\x00\xcd\xf6\x00\xf5\xcc\xf4\xcc\ -\xf5\x00\x01\xcc\xcd\xdc\xcc\x00\xce\xf5\x00\xf5\xcc\xf4\xcc\xf4\ -\x00\x01\xff\xcd\xde\xcc\x00\xff\xf4\x00\xf5\xcc\xf4\xcc\xf2\x00\ -\x00\xce\xe0\xcc\xf2\x00\xf5\xcc\xf4\xcc\xf1\x00\x00\xd4\xe3\xcc\ -\x00\xda\xf1\x00\xf5\xcc\xf4\xcc\xef\x00\x00\xcf\xe7\xcc\x00\xd1\ -\xef\x00\xf5\xcc\xf4\xcc\xed\x00\x00\xcd\xeb\xcc\x00\xcd\xed\x00\ -\xf5\xcc\xf4\xcc\xeb\x00\x02\xce\xcd\xcd\xf1\xcc\x00\xd0\xeb\x00\ -\xf5\xcc\xf4\xcc\xe8\x00\x04\xd2\xce\xcc\xcc\xcd\xfa\xcc\x01\xce\ -\xd2\xe8\x00\xf5\xcc\xf4\xcc\xc1\xff\xf5\xcc\xf4\xcc\xc1\xff\xf5\ -\xcc\xf4\xcc\xc1\xff\xf5\xcc\xf4\xcc\xc1\xff\xf5\xcc\xf4\xcc\xc1\ -\xff\xf5\xcc\xf4\xcc\xc1\xff\xf5\xcc\xf4\xcc\xc1\xff\xf5\xcc\xf4\ -\xcc\xc1\xff\xf5\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\ -\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\x01\x00\x02\ -\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\ -\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x06\x00\x06\x00\x06\ -\x00\x06\x00\x06\x00\x11\x00\x10\x00\x0c\x00\x0c\x00\x0e\x00\x0c\ -\x00\x0f\x00\x0e\x00\x0e\x00\x0e\x00\x0e\x00\x12\x00\x11\x00\x14\ -\x00\x10\x00\x12\x00\x14\x00\x12\x00\x0e\x00\x0f\x00\x0f\x00\x10\ -\x00\x0e\x00\x0a\x00\x06\x00\x08\x00\x08\x00\x06\x00\x08\x00\x10\ -\x00\x11\x00\x14\x00\x16\x00\x16\x00\x15\x00\x14\x00\x14\x00\x17\ -\x00\x14\x00\x16\x00\x0c\x00\x0a\x00\x0e\x00\x0f\x00\x0f\x00\x0c\ -\x00\x0e\x00\x0e\x00\x0e\x00\x10\x00\x13\x00\x06\x00\x06\x00\x06\ -\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x02\x00\x02\x00\x02\ -\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\ -\x00\x02\x00\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\ -\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xf4\ -\xcc\xc1\xff\xf5\xcc\xf4\xcc\xc1\xff\xf5\xcc\xf4\xcc\xc1\xff\xf5\ -\xcc\xf4\xcc\xc1\xff\xf5\xcc\xf4\xcc\xc1\xff\xf5\xcc\xf4\xcc\xe8\ -\x00\x03\xcd\xcc\xcc\xcd\xf8\xcc\x00\xcd\xe8\x00\xf5\xcc\xf4\xcc\ -\xeb\x00\x02\xcf\xcd\xcd\xf1\xcc\x00\xd3\xeb\x00\xf5\xcc\xf4\xcc\ -\xed\x00\xea\xcc\x00\xce\xed\x00\xf5\xcc\xf4\xcc\xef\x00\x00\xd1\ -\xe6\xcc\xef\x00\xf5\xcc\xf4\xcc\xf1\x00\x00\xd4\xe3\xcc\x00\xda\ -\xf1\x00\xf5\xcc\xf4\xcc\xf2\x00\xe0\xcc\x00\xcd\xf2\x00\xf5\xcc\ -\xf4\xcc\xf4\x00\x01\xff\xcd\xde\xcc\x00\xff\xf4\x00\xf5\xcc\xf4\ -\xcc\xf5\x00\x00\xcf\xdb\xcc\x00\xcf\xf5\x00\xf5\xcc\xf4\xcc\xf6\ -\x00\x00\xce\xd9\xcc\x00\xcf\xf6\x00\xf5\xcc\xf4\xcc\xf7\x00\x00\ -\xcd\xd7\xcc\x00\xce\xf7\x00\xf5\xcc\xf4\xcc\xf8\x00\x00\xce\xd5\ -\xcc\x00\xce\xf8\x00\xf5\xcc\xf4\xcc\xf9\x00\xec\xcc\x04\xcd\xce\ -\xd7\xd4\xd0\xeb\xcc\xf9\x00\xf5\xcc\xf4\xcc\xfa\x00\xee\xcc\x01\ -\xcd\xff\xfb\x00\xea\xcc\xfa\x00\xf5\xcc\xf4\xcc\xfb\x00\x00\xce\ -\xef\xcc\x00\xe2\xf9\x00\xea\xcc\x00\xcd\xfb\x00\xf5\xcc\xf4\xcc\ -\xfc\x00\xee\xcc\xf7\x00\xe9\xcc\x00\xd3\xfc\x00\xf5\xcc\xf4\xcc\ -\xfd\x00\x00\xda\xef\xcc\xf6\x00\xe8\xcc\x00\xd7\xfd\x00\xf5\xcc\ -\xf4\xcc\xfe\x00\x00\xff\xf0\xcc\x00\xcd\xf5\x00\xe7\xcc\x00\xff\ -\xfe\x00\xf5\xcc\xf4\xcc\xfe\x00\x00\xcd\xef\xcc\xf5\x00\xe7\xcc\ -\x00\xcd\xfe\x00\xf5\xcc\xf4\xcc\xff\x00\xee\xcc\xf4\x00\xe5\xcc\ -\xff\x00\xf5\xcc\xf4\xcc\x01\x00\xda\xee\xcc\xf4\x00\xe4\xcc\x00\ -\x00\xf5\xcc\xf4\xcc\x00\x00\xee\xcc\xf3\x00\xe5\xcc\x01\xcd\x00\ -\xf5\xcc\xf4\xcc\x00\xcf\xef\xcc\x00\xcf\xf3\x00\xe4\xcc\x00\xd4\ -\xf5\xcc\xf4\xcc\x00\xcd\xee\xcc\xf3\x00\xe4\xcc\x00\xcd\xf5\xcc\ -\xe1\xcc\xf2\x00\x00\xd2\xf7\xd1\xe2\xcc\xe1\xcc\xe7\x00\xe2\xcc\ -\xe2\xcc\x00\xcd\xe7\x00\xe2\xcc\xe1\xcc\xe7\x00\x00\xcd\xe3\xcc\ -\xe1\xcc\xe7\x00\xe2\xcc\xe1\xcc\x00\xd4\xe9\x00\xe1\xcc\xf4\xcc\ -\x00\xcd\xee\xcc\xe9\x00\x00\xce\xef\xcc\x00\xcd\xf5\xcc\xf4\xcc\ -\x01\x00\xcd\xf0\xcc\x00\xcd\xe9\x00\xee\xcc\x00\x00\xf5\xcc\xf4\ -\xcc\x01\x00\xd2\xef\xcc\x00\xd4\xeb\x00\x00\xd4\xef\xcc\x01\xcf\ -\x00\xf5\xcc\xf4\xcc\xff\x00\x00\xce\xf0\xcc\x00\xcd\xeb\x00\x00\ -\xcd\xf0\xcc\x02\xcd\x00\x00\xf5\xcc\xf4\xcc\xfe\x00\x00\xcd\xf0\ -\xcc\x00\xd0\xed\x00\x00\xd0\xf0\xcc\x00\xcd\xfe\x00\xf5\xcc\xf4\ -\xcc\xfe\x00\x00\xe2\xf0\xcc\x00\xcd\xed\x00\xf0\xcc\x01\xcd\xda\ -\xfe\x00\xf5\xcc\xf4\xcc\xfd\x00\x00\xd3\xef\xcc\xef\x00\x00\xcd\ -\xf0\xcc\x00\xcf\xfd\x00\xf5\xcc\xf4\xcc\xfc\x00\x00\xcf\xf0\xcc\ -\x00\xcd\xf1\x00\xef\xcc\x00\xce\xfc\x00\xf5\xcc\xf4\xcc\xfb\x00\ -\x00\xce\xf0\xcc\x01\xcd\xd7\xf5\x00\x00\xda\xef\xcc\x00\xcd\xfb\ -\x00\xf5\xcc\xf4\xcc\xfa\x00\x00\xcd\xed\xcc\xf9\x00\x00\xd4\xee\ -\xcc\x00\xcd\xfa\x00\xf5\xcc\xf4\xcc\xf9\x00\x00\xce\xeb\xcc\xff\ -\xd1\xff\xcc\x00\xcd\xee\xcc\x00\xce\xf9\x00\xf5\xcc\xf4\xcc\xf8\ -\x00\x00\xce\xd4\xcc\xf8\x00\xf5\xcc\xf4\xcc\xf7\x00\xd5\xcc\xf7\ -\x00\xf5\xcc\xf4\xcc\xf6\x00\x00\xcd\xd9\xcc\x00\xcd\xf6\x00\xf5\ -\xcc\xf4\xcc\xf5\x00\x01\xcc\xcd\xdc\xcc\x00\xce\xf5\x00\xf5\xcc\ -\xf4\xcc\xf4\x00\x01\xff\xcd\xde\xcc\x00\xff\xf4\x00\xf5\xcc\xf4\ -\xcc\xf2\x00\x00\xce\xe0\xcc\xf2\x00\xf5\xcc\xf4\xcc\xf1\x00\x00\ -\xd4\xe3\xcc\x00\xda\xf1\x00\xf5\xcc\xf4\xcc\xef\x00\x00\xcf\xe7\ -\xcc\x00\xd1\xef\x00\xf5\xcc\xf4\xcc\xed\x00\x00\xcd\xeb\xcc\x00\ -\xcd\xed\x00\xf5\xcc\xf4\xcc\xeb\x00\x02\xce\xcd\xcd\xf1\xcc\x00\ -\xd0\xeb\x00\xf5\xcc\xf4\xcc\xe8\x00\x04\xd2\xce\xcc\xcc\xcd\xfa\ -\xcc\x01\xce\xd2\xe8\x00\xf5\xcc\xf4\xcc\xc1\xff\xf5\xcc\xf4\xcc\ -\xc1\xff\xf5\xcc\xf4\xcc\xc1\xff\xf5\xcc\xf4\xcc\xc1\xff\xf5\xcc\ -\xf4\xcc\xc1\xff\xf5\xcc\xf4\xcc\xc1\xff\xf5\xcc\xf4\xcc\xc1\xff\ -\xf5\xcc\xf4\xcc\xc1\xff\xf5\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\ -\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\ -\x01\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\ -\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x06\x00\ -\x06\x00\x06\x00\x06\x00\x06\x00\x11\x00\x10\x00\x0c\x00\x0c\x00\ -\x0e\x00\x0c\x00\x0f\x00\x0e\x00\x0e\x00\x0e\x00\x0e\x00\x12\x00\ -\x11\x00\x14\x00\x10\x00\x12\x00\x14\x00\x12\x00\x0e\x00\x0f\x00\ -\x0f\x00\x10\x00\x0e\x00\x0a\x00\x06\x00\x08\x00\x08\x00\x06\x00\ -\x08\x00\x10\x00\x11\x00\x14\x00\x16\x00\x16\x00\x15\x00\x14\x00\ -\x14\x00\x17\x00\x14\x00\x16\x00\x0c\x00\x0a\x00\x0e\x00\x0f\x00\ -\x0f\x00\x0c\x00\x0e\x00\x0e\x00\x0e\x00\x10\x00\x13\x00\x06\x00\ -\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x02\x00\ -\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\ -\x02\x00\x02\x00\x02\x00\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\ -\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\ -\xa8\xcc\xf4\xcc\xc1\xff\xf5\xcc\xf4\xcc\xc1\xff\xf5\xcc\xf4\xcc\ -\xc1\xff\xf5\xcc\xf4\xcc\xc1\xff\xf5\xcc\xf4\xcc\xc1\xff\xf5\xcc\ -\xf4\xcc\xe8\x00\x03\xcd\xcc\xcc\xcd\xf8\xcc\x00\xcd\xe8\x00\xf5\ -\xcc\xf4\xcc\xeb\x00\x02\xcf\xcd\xcd\xf1\xcc\x00\xd3\xeb\x00\xf5\ -\xcc\xf4\xcc\xed\x00\xea\xcc\x00\xce\xed\x00\xf5\xcc\xf4\xcc\xef\ -\x00\x00\xd1\xe6\xcc\xef\x00\xf5\xcc\xf4\xcc\xf1\x00\x00\xd4\xe3\ -\xcc\x00\xda\xf1\x00\xf5\xcc\xf4\xcc\xf2\x00\xe0\xcc\x00\xcd\xf2\ -\x00\xf5\xcc\xf4\xcc\xf4\x00\x01\xff\xcd\xde\xcc\x00\xff\xf4\x00\ -\xf5\xcc\xf4\xcc\xf5\x00\x00\xcf\xdb\xcc\x00\xcf\xf5\x00\xf5\xcc\ -\xf4\xcc\xf6\x00\x00\xce\xd9\xcc\x00\xcf\xf6\x00\xf5\xcc\xf4\xcc\ -\xf7\x00\x00\xcd\xd7\xcc\x00\xce\xf7\x00\xf5\xcc\xf4\xcc\xf8\x00\ -\x00\xce\xd5\xcc\x00\xce\xf8\x00\xf5\xcc\xf4\xcc\xf9\x00\xec\xcc\ -\x04\xcd\xce\xd7\xd4\xd0\xeb\xcc\xf9\x00\xf5\xcc\xf4\xcc\xfa\x00\ -\xee\xcc\x01\xcd\xff\xfb\x00\xea\xcc\xfa\x00\xf5\xcc\xf4\xcc\xfb\ -\x00\x00\xce\xef\xcc\x00\xe2\xf9\x00\xea\xcc\x00\xcd\xfb\x00\xf5\ -\xcc\xf4\xcc\xfc\x00\xee\xcc\xf7\x00\xe9\xcc\x00\xd3\xfc\x00\xf5\ -\xcc\xf4\xcc\xfd\x00\x00\xda\xef\xcc\xf6\x00\xe8\xcc\x00\xd7\xfd\ -\x00\xf5\xcc\xf4\xcc\xfe\x00\x00\xff\xf0\xcc\x00\xcd\xf5\x00\xe7\ -\xcc\x00\xff\xfe\x00\xf5\xcc\xf4\xcc\xfe\x00\x00\xcd\xef\xcc\xf5\ -\x00\xe7\xcc\x00\xcd\xfe\x00\xf5\xcc\xf4\xcc\xff\x00\xee\xcc\xf4\ -\x00\xe5\xcc\xff\x00\xf5\xcc\xf4\xcc\x01\x00\xda\xee\xcc\xf4\x00\ -\xe4\xcc\x00\x00\xf5\xcc\xf4\xcc\x00\x00\xee\xcc\xf3\x00\xe5\xcc\ -\x01\xcd\x00\xf5\xcc\xf4\xcc\x00\xcf\xef\xcc\x00\xcf\xf3\x00\xe4\ -\xcc\x00\xd4\xf5\xcc\xf4\xcc\x00\xcd\xee\xcc\xf3\x00\xe4\xcc\x00\ -\xcd\xf5\xcc\xe1\xcc\xf2\x00\x00\xd2\xf7\xd1\xe2\xcc\xe1\xcc\xe7\ -\x00\xe2\xcc\xe2\xcc\x00\xcd\xe7\x00\xe2\xcc\xe1\xcc\xe7\x00\x00\ -\xcd\xe3\xcc\xe1\xcc\xe7\x00\xe2\xcc\xe1\xcc\x00\xd4\xe9\x00\xe1\ -\xcc\xf4\xcc\x00\xcd\xee\xcc\xe9\x00\x00\xce\xef\xcc\x00\xcd\xf5\ -\xcc\xf4\xcc\x01\x00\xcd\xf0\xcc\x00\xcd\xe9\x00\xee\xcc\x00\x00\ -\xf5\xcc\xf4\xcc\x01\x00\xd2\xef\xcc\x00\xd4\xeb\x00\x00\xd4\xef\ -\xcc\x01\xcf\x00\xf5\xcc\xf4\xcc\xff\x00\x00\xce\xf0\xcc\x00\xcd\ -\xeb\x00\x00\xcd\xf0\xcc\x02\xcd\x00\x00\xf5\xcc\xf4\xcc\xfe\x00\ -\x00\xcd\xf0\xcc\x00\xd0\xed\x00\x00\xd0\xf0\xcc\x00\xcd\xfe\x00\ -\xf5\xcc\xf4\xcc\xfe\x00\x00\xe2\xf0\xcc\x00\xcd\xed\x00\xf0\xcc\ -\x01\xcd\xda\xfe\x00\xf5\xcc\xf4\xcc\xfd\x00\x00\xd3\xef\xcc\xef\ -\x00\x00\xcd\xf0\xcc\x00\xcf\xfd\x00\xf5\xcc\xf4\xcc\xfc\x00\x00\ -\xcf\xf0\xcc\x00\xcd\xf1\x00\xef\xcc\x00\xce\xfc\x00\xf5\xcc\xf4\ -\xcc\xfb\x00\x00\xce\xf0\xcc\x01\xcd\xd7\xf5\x00\x00\xda\xef\xcc\ -\x00\xcd\xfb\x00\xf5\xcc\xf4\xcc\xfa\x00\x00\xcd\xed\xcc\xf9\x00\ -\x00\xd4\xee\xcc\x00\xcd\xfa\x00\xf5\xcc\xf4\xcc\xf9\x00\x00\xce\ -\xeb\xcc\xff\xd1\xff\xcc\x00\xcd\xee\xcc\x00\xce\xf9\x00\xf5\xcc\ -\xf4\xcc\xf8\x00\x00\xce\xd4\xcc\xf8\x00\xf5\xcc\xf4\xcc\xf7\x00\ -\xd5\xcc\xf7\x00\xf5\xcc\xf4\xcc\xf6\x00\x00\xcd\xd9\xcc\x00\xcd\ -\xf6\x00\xf5\xcc\xf4\xcc\xf5\x00\x01\xcc\xcd\xdc\xcc\x00\xce\xf5\ -\x00\xf5\xcc\xf4\xcc\xf4\x00\x01\xff\xcd\xde\xcc\x00\xff\xf4\x00\ -\xf5\xcc\xf4\xcc\xf2\x00\x00\xce\xe0\xcc\xf2\x00\xf5\xcc\xf4\xcc\ -\xf1\x00\x00\xd4\xe3\xcc\x00\xda\xf1\x00\xf5\xcc\xf4\xcc\xef\x00\ -\x00\xcf\xe7\xcc\x00\xd1\xef\x00\xf5\xcc\xf4\xcc\xed\x00\x00\xcd\ -\xeb\xcc\x00\xcd\xed\x00\xf5\xcc\xf4\xcc\xeb\x00\x02\xce\xcd\xcd\ -\xf1\xcc\x00\xd0\xeb\x00\xf5\xcc\xf4\xcc\xe8\x00\x04\xd2\xce\xcc\ -\xcc\xcd\xfa\xcc\x01\xce\xd2\xe8\x00\xf5\xcc\xf4\xcc\xc1\xff\xf5\ -\xcc\xf4\xcc\xc1\xff\xf5\xcc\xf4\xcc\xc1\xff\xf5\xcc\xf4\xcc\xc1\ -\xff\xf5\xcc\xf4\xcc\xc1\xff\xf5\xcc\xf4\xcc\xc1\xff\xf5\xcc\xf4\ -\xcc\xc1\xff\xf5\xcc\xf4\xcc\xc1\xff\xf5\xcc\xa8\xcc\xa8\xcc\xa8\ -\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\ -\xcc\xa8\xccMIB8ksML\x0e\x00\x00\x00\x00\ -\x00\xff\xff\x00\x00\x00\x00\x00\x002\x00\x80\x00\x00\x00M\ -IB8ttaP\x00\x00\x00\x00MIB8k\ -sMF\x0c\x00\x00\x00\x00\x00\xff\xff\x00\x00\x00\x00\x00\ -\x002\x00\x00\x00\x00\x00\ -\x00\x00\x05}\ -<\ -?xml version=\x221.\ -0\x22 encoding=\x22UTF\ --8\x22 standalone=\x22\ -no\x22?>\x0d\x0a\x0d\x0a \x0d\x0a \ - eye on<\ -/title>\x0d\x0a Created with \ -Sketch.\x0d\x0a\ - \x0d\x0a \x0d\x0a <\ -path d=\x22M62.3998\ -86,20.262032 C61\ -.0656979,18.1619\ -773 49.0033003,3\ -.55271368e-15 32\ -.0083577,3.55271\ -368e-15 C15.0134\ -15,3.55271368e-1\ -5 2.9510174,18.1\ -619773 1.5499679\ -5,20.262032 C-0.\ -516655982,23.447\ -0641 -0.51665598\ -2,27.7140347 1.5\ -4996795,30.97200\ -66 C2.9510174,32\ -.9991215 15.0134\ -15,50.9422798 32\ -.0083577,50.9422\ -798 C49.0033003,\ -50.9422798 61.06\ -56979,32.9991215\ - 62.399886,30.97\ -20066 C64.533371\ -3,27.7140347 64.\ -5333713,23.44706\ -41 62.399886,20.\ -262032 L62.39988\ -6,20.262032 Z M3\ -2.0083577,39.943\ -5857 C24.6110597\ -,39.9435857 18.6\ -786333,33.503620\ -9 18.6786333,25.\ -4711399 C18.6786\ -333,17.5115986 2\ -4.6110597,10.998\ -6941 32.0083577,\ -10.9986941 C32.7\ -407935,10.998694\ -1 33.4732293,11.\ -0716338 34.14184\ -3,11.2175131 L34\ -.141843,23.15530\ -55 L45.1405371,2\ -3.1553055 C45.27\ -12206,23.8786238\ - 45.338082,24.67\ -48819 45.338082,\ -25.4711399 C45.3\ -38082,33.5036209\ - 39.3387943,39.9\ -435857 32.008357\ -7,39.9435857 L32\ -.0083577,39.9435\ -857 Z\x22 id=\x22Shape\ -\x22 fill=\x22#CCCCCC\x22\ ->\x0d\x0a \x0d\x0a\x0d\x0a\ -\x00\x00\x1f\xef\ -\x00\ -\x00\xe4\x14x\x9c\xed\x5c\x07\x5cS\xc7\x1f\xbf\x0c\x12\xf6\ -^2c\x98*\x10\xc2&\xc8\xde\x0a\x82l\x14\x85\x90\ -\x04\x88\x84$f\x80\xab\xe2\xaa\xd6U\x95\xba\xb5uo\ -\xc5\xd6]\xad\xdb\xd6Z\xf7\xb6u\xfc\xb1\xd6\xbaW\x15\ -\xb5\xa8\xf0\xbf{!\x10\x10-J\x00\xfb\xff\xbfo>\ -\xf7r\xef\xd6o\xdc\xbd\xbb\xdf\xdd\xbb{\x89\x89\xa0;\ -\x00@\x13\x98\x83Z@\x86>\x02P\x5cH\xd8_\x1e\ -\xbc\x10T\xfcD\xcc\x0f\xd3\x11\xcc\x09\xa4\xfap\x98\x98\ -@\xa9\xf7\x13\xe1\xc5HYN\xeam\x82\xb1J\x1a\xb3\ -z?\x96[\xa5L\x0be\xfa\xe9\x80`\x054\x14~\ -\x82\x1d\xc1\xba\xc1\xefL\xb0Q)\xc7U\x85\x16\x13]\ -\x01\x1d\xfa<\x08^\x98\xdf\x14\xfa\x93\x09)\x8d\xe9\x89\ -?\xa0\xab\x9f5\xbc\xe5\x8e\x8fG~C\x1a\x00\xfe\xa3\ -&\xf0\x95to\xdc\x9e \x05T\x00t\xe3\x00\x88]\ -\x8c\xe4\x87\xfaP\xfc\xb4_\x8f\x02\xc0\xc5P\xf9\x1f\xce\ -\x15\xe5\xf3h\xc9E\x22\x99HZ$\x12\xd3\x22#i\ -^\x9eL\x7f\x9ak&_\xc8\x15\x95I\xbb\x01t\xcb\ -\xf2\xf4byz\xd3\x98\xbe,/o\x96\xa7\x0f\xe8\x19\ -:D\xcc\xe6\x14\xf3d\xb4|^!_\x18L\x7f\xb4\ -k/\x9d\xc6\xe7\x06\xd33}\x13=\x13\xc5\x91\xbc\x22\ -~\xdc0\x09/uX\x9f4\xce\xb0bN \x97\x1e\ -\x1a\xa2\xdds\x08kH\x89\xb8\x84'c\xd3\x86\x94\x08\ -\x84R\xd6\x90`:\x1b\xd1gA?\x0af\xd0iX\ -\x12Yq0]\xc1XVb2-R$\xe1\xd1|\ -=\xfc\xdc9L\xef\x00\x9a\x7f\xa0\x07\xd370\xc0\xcb\ -\xc7\x0d1\xea\xc7\xf0\x0cd0}\xdc=\x99,\xcf@\ -\x96'\x93V\x0fz\x886\xbc\xf6\x94p\x0bX)Q\ -1\xf5\xe4\xe0]0\xbdH&\x13\xb3\x18\x8c\xb2\xb22\ -\x8f2o\x0f\x91\xa4\x90\xc1\x0c\x0c\x0cdxz1\xbc\ -\xbc\xdca\x0aw\xe9P\xa1\x8c=\xc4](uP\x14\ -\xa2,'\x8a'\xe5H\xf8b\x19_$\xa4\xa1{v\ -\xbeH.\x0b\xa6\xd3\xb5i*\xa8\x97\xabD\xdc@H\ -(\xf5\xc0d\xf4\xe0\x88J\x18C\xd8b\x06\xd3\xc3\x93\ -\xd1R&.\xa7!\x8fX.\x11`\xacq9\x0c\x9e\ -\x80W\xc2\x13\xca\xa40\x1f\xb3\xc5|be\xdd\xb5L\ -\xb2!\xfa\x9d\x84!\xb7\x89\x89\xef\xe7\xb7\xa4\xa4\xc5\x9c\ -RYt\xa9\xec\xfd9\xa5iC\xc5\x05\xee\x01\xcc|&|\xc6|}\xb9<\x0e\ -\xd3\xcb\x97\xeb\x8b\xe9\xa0i\xf6\xb7\x8a\x8e\x12q\xe4\xa8\ -\xe9\xd6\x17\xcd\xfd\xc0\xa2U\xb2\xbfUt\x92\x84\x0f\xbb\ -\x1d\xb6\xa0\x8d$Z(\xe6-Rq|\xa9L$\x19\ -\x1a\xd2\xa4\xf9c\x1dB*op\xd3Pe\x84\x80\x8f\ -u\x10b\xb6D\xcaC\xcd?\x98\xael\xff\xf4\xb72\ -\xa0<\xd8c\xc4bsP\xd7\x12\xc2\xc1Z8\xb7'\ -\xa3I\xe8\xbb\xb3\xf1?\xb6\x02\xdf\xca\xfen\x1aeE\ -<\xe1\xfb\x9eL\x95T\xef.D**\x90\x95\xb1%\ -\xbc\xf0B\xa8\xe9\x90\x7f\x1cw\x94\xa56\xcd\xf6\x96\xbe\ -\x19\x0a\x857\xab\x1e\xc6\xdb\xf5\xa3\xac\xf3f\xf5\xa9H\ -\xaa\xd2\xb7+\x06\x0eF\xfd\xc8\x01\x07-F\xc3\xa8\xd5\ -\x92p\xea\x07N\x04'\x82\x13\xc1\x89\xe0Dp\x228\ -\x11\x9c\x08N\x04'\x82\x13\xc1\x89\xe0Dp\x228\x11\ -\x9c\x08N\x04'\x82\x13\xc1\x89\xe0Dp\x228\x11\x9c\ -\x08N\x04'\x82\x13\xc1\x89\xe0Dp\x228\x11\x9c\x08\ -N\x04'\x82\x13\xc1\x89\xe0Dp\x228\x11\x9c\x08N\ -\x04'\x82\x13\xc1\x89\xe0Dp\x22j&\xa2\xddx\x0e\ -\x8c'\xe4\x06\xd3\xcb\xe8\xa1! \x22>\x91\xec\x84\ -\x9d93\x04\xcd\x80\xc5\xb10\xef\xcd\xfax\xect\x1e\ -\xd0\x11K\xf8BY\x92\x5c&\x96\xcb\xe0-:&\x07\ -\x92\xa5\xb2\xd4|\x91H\x80\xa5\x88\x17\xcax<\xa1\xbc\ -D\xe9G\xff\x91\x02\x09\xba7\xc0\xf2\xa6\xf2\x87\xa0\x14\ -\x11|\x19\xca\xd3X&O\xd2\x87]\xc2K\x8b\xceJ\ -k \xa6\xc8\x90,\x11\x89\x0aRy2\xb98)\x7f\ -\x10\x07\x06\xeb\x82d \x01\x22\xf8+\x004\x90\x0ax\ -@\x06\xe4@\x8ce\xd1\x167\xa4V\x16\x13!\x90\x09\ -\xeb9\xd2\xcd\x97\xf3\x052\xbe\x10+\x12\xdeka\xa9\ -#\x13\xb3{+$\x0eB\xe9\x89\xeeM$6V\x91\ -8\x09;y \x85\xa1\x16\x98\x5cb\x99P)\x04\x14\ -2_\xd2p\x93R(Ml\x8c\x91\x08#\x1bo\x84\ -\xb2\xc6\x9b\x84|\x81\xb4\xe1\xa6O\xa1\xac\xb4\xe1&\xba\ -D\x10\xd5p\x03\xf5\xd8Xt\x04\xa7\xb8\xb0^\x11\x0a\ -\x06AJlD$P\x1c\x9b\x04)\x5c\x1a\x8d+\x92\ -\xe7\x87\x89\xaa\x1a*3V\x22|+,B\xf0v\xba\ -\x08\x097-](\x8bqH\x11\xc8T\x1bC\x84\x80\ -Kk)\ -\x8b\xae2\x06\xb1\xa0\x12\xae\xa7\x0cO\xe1\x17\x16\xa9F\ -\xe8(# o\x0d\xc1\xa8\xe5\x90\x1e(x\x00q@\ -q\xf6\xb3\xfe\x1fkU\xceX\x9c~\xa3\x04\xa1\xa3\xea\ -s=T\x90\xd3M\x93\xb0\x85R1[\xc2\x13r\x86\ -*Z\xa2\x19\x16c\x87bA\x1al\xedl \x04R\ -\xd8\xc6\xd9\xd0\xcf\x83~\x0e\x18Z\xff\x94\xfab)\x8d\ -0z\xa0\xae\xae\x9e\x04\x97\xa0\x88\xb5\xc5\xee\xc8J>\ -\xc9z\x0d\xf7v\xd8}\x97\xa6\xf7\xa4\xa7\xd8\xbd\x96\x92\ -SE).\x8a\xfeA[\xd9\xe0\x14r\x91\xaa1\x7f\ -\x1c`\x14\x14\xc0\x18\x01\xbcR\xea3)B\x96\xcc\x9b\ -\xdf\x10\xe2\x85]\xfb\xc1\xab2\xc4\x17\xbb\xba7\x86`\ -e\xbe\xc4\xfcb$IK \xddF\xd1\xea\x8f\xc3t\ -\xa1\x90\x8dX\x7fGlr\xe7\xa9\xe0\xb1^\xab\xee\xd8\ -\x1d\x05\xd3\x07\x09\x0b\xd1\xac\xaf\x7f\xac\x16\x88a\x0aW\ -\x9f\xd7\xaeY\x1dX!\x1f\xc9\xb7Ar\x05\xf2\xea\x9d\ -B;oC5L5m\x8b\x09\x94h\xec\xc6\x80P\ -.\x10(\x04\x02\x94|\x91\x5c\xc8\x956\xebE82\ -\xa6\x92M\xf4\xe8\xa94{\xd0\xec\xf9\x00\x11\x8d\xcf\x11\ -\xc6FJ\xe3c\x82\xee)R\x01\x9f\xc3\x93f\x08\x12\ -\xd0\x83NhBG\x03\x8b\x83\x1ec\xe8\xa8\xd8M|\ -\x94J\xd9\xd4B\x89H.n\x12D\x11a\xc7\xff\x94\ -}xt*\xca\xa48\x12\x08\xef\xf5\xd8r\x99(\x96\ -'\xe4I\xd0q<\x8c\xfb\xa1b\xe5\x10\xa4\xadH\x8c\ -BPL|I!\xad\x03\xe4'\xc9%\x82&\x03\x19\ -\xa6\xfc\xa6!\x89\xd2\xc2\xa6\x83\x1d\x85-\x90\xa5\xb1\x0b\ -\x9b\x84\xe9sx0\x1fo\x88,^\x1a\x97\x96\x98\xa0\ -\xecN5\x95\xc1M\x12k\x15\x89$\xc3\xc2\x05\xfcB\ -\xa5\xa6\x0c\x14\xc2\xc7)\x83\x91v\xb9\xbc\x02\xb6\x1c\xeb\ -O\xb5Jy\x12Y\x0b\xc93\x94\xc1M\x93\xeb\xe4\x17\ -b\xa7\x5cU\x94k\xa4\xc8\x10\x11\xdb\x10\x81\xd8\xe8#\ -\x12\xa2\x7f-\x99H\x0c\x07M)OUq\xda\x02\xa8\ -\xc8\xb7Bu\xf3\xb1\x8e\xf9\xadp\x1d\x09\xea~\x9b\x05\ -cO\x90\xab\x22\x1ft\xc4\xd0\xc7\xa01\xdc\x14\xf3\xa2\ -*T<\x95\xba\x98b\x8f\xd6\xab(O\xe1\x08\xb0\x09\ -\xa0'\x81\xb2\x11X\x02B\xdd\xa5\xba\x07@\x17;\xe5\ -\x98\x1b\x99\x08\xef\x1f\x02}\xec\x0epG\xa1|u\x97\ -\xc18\xa0\xab\xa9\xa9\xa9\xa5\xa9\xab\xa5\xa5k\xa4\xa3\xad\ -cdf\xa0\xabk`fibbfbbi\xa4\ -\x8b\xa1\xfe\xafe\x10\xf4tt\xf4\xf4\xf5\x0c\xf5\xf5\x0d\ -M\xf5\xf5\xf5M\xd1E\xdfT\x91\xc5\xa85\x05\xd4\xed\ -\x03F\x9a\x90\xf9<\x12\x81\x0e\x88F\x04\x92\x11\xa1\xee\ -*\x14\x94Rw\x88\x10\x0a\xb9\xd4 `\xa8W\x1c\x09\ -\x10\x88d\x0d\x0aUSK[\x87\xd0<\x92\x00\x88$\ -e\xa4! \x90\x09$\x22\x99\xa8A\xa5hj\x90t\ -\xbda\xa4\x11\x89\xdc\xd5\x98\xa9\x11\xde\x97mB\x1f<\ -\xda\x8bb:c\xc9w\x11\x0e\x8ef)\xfb\xf3\xbd}\ -$cNGR\x9d*R\x1f_\x7f\xc2\x91\xfa\x9a/\ -\xdd4\xd69\xea\xab4n\xf4\x81e2?\x8b3\xe9\ -\xbf\xf3\xfe\xda<\xee\xe0Y\xf9\x8d\xa71.3\x97\x7f\ -\xbee\xd6\xa1s\x7f<[\xb1\xf5\xc7\xf37\xab3\x0a\ -J\xc7\xcf^\xb9\xed\xa7\x0b\x7f>\xf7\x8f\xcd,,\x9b\ -0g\xd5\xf6\xc3\x17o\xbd0\x02D\x22\xe4\x96\x8c\xf1\ -D\xa5h\xf8b,te\x1a\x93!\x07\x83\xe9&\x1a\ -^\xa3g\x98\x22\x0e\xf6\xa7\x9c~\xec\xed\x98\x7f]2\ -\xa6\x222\xd5\x8c#\xf5y\xe2DA\x0cP\x9d}\x0f\ -\x9c\x81L,\xb3\xe0F\xa7\xfb\xc9x\xbf7\xb0\xf0n\ -\x0e\x5c\x1aY\xa8\xfb\x0d\xe8\x920\x9aF \x14T\xa7\ -U\xc4;us\xac\x88\xef\x15\xefX\x91R\x11\xef8\ -sy}@R\xdd\xa9\xea4\xb7\x05\xbfN\x9dV\x10\ -\xb9\xdfm\xcd\x8a\x87z\xd6S\x08!\x17\xc6\xa5U\xa4\ -F.\xaf^h\xb7!v\xdd\xa4G\xe2Z\xc9\xaa\xa2\ -\xe7\xf67\xfdk_o\xac\x94\xae{\xd3o\xeb\xf7\xf6\ -[Y\xd6\xb5G\x17^\x1d\x90uz\xf6\x90:\xe0T\ -Y\xf6f{>\xa8y\x9a\x1e \x12\x16\x04\xdd\xbb\x9b\ -n\xfb\xe5\xe11V\x03^\xbd\xfa\xfa\xf5\xe5\xf2\x8a\x8a\ -oV\x9c(\xee\x97\xf3\xbb\xd5\xe95.a\xe6\xbc:\ -\x90\xbdS?h\xb2\xe0\xf8\xfa\x19'\x8el\xae\x03\xc1\ -\xd4\x8d\xc1ww\x97\xad\x91\xf7\xd7\xfaeKM\xf9\x82\ -\xde>y\xb5\x87o\x95g\xdf\x0bv\x0aY\x11{A\ -8vz\xd5oO\x8b\xc9O\xf6\x14\xd7\x81\x93K&\ -'V\x16\xcf\xb79csv\xb5Cr\xe6Tw\xfd\ -Y\x17\x87\xcd\xe9\xf5m\x90\xf9\xd9;\xb5r\xc6\xf9\x09\ -\xaf\xec\x17\xbc)p\x5cu\xbe\x22;X\xe7\x9e\x9d}\ -\xd6\xda.5n+'n\x1a#\xaf\xddZ\xf8\xf4\xd2\ -V\x85\xf8u\xa0\xee4\xa6\x94@\xfb\xac\x9a7\x03\xec\ -\x8d\xfb\x1b\x1c\xdd\x16m\xb6\xe8\xf5\xcb:\xf0\x07s\xe8\ -\xca\x98\xe8_\xfdC^]\x13l;\xc8\x18\xfe\xbd\x13\ -d$\xe6\xda\x8as\xc2_\xbe\xfdY\xfa\xc5\xfa\x91\xf7\ -\x08o\xacc\x9f\xa7;\xce\x9cc>;\xf7\xab\x01\x8c\ -\xad[\xfc\x0eS\x16\xe4>\xebgp+pXh\x9f\ -\x9aU\xa7\x9et\x17\x9c\xba\xb2j\x86\xf3\xe5\xddO\x1f\ -\x17>-\xc9\xda\x9bZ\xe3\xac_\x1es\xa4t\x00\xbb\ -v\xeb.\xd2\xde\xc0%S\xad\x07\xf4\xdf\xeb{y\xfd\ -0o\x8f\xbb{\xd3\x1e\x98q\x85\xc7o\x9f\xf0;lV`\x82\xa7U\xd5e\xea#\xcf:\x10p\ -\xa6bQ6l:\xa9ug0\xad\x85\xa4W\x8f]\ -q\xf9L\xcd\xd7[\x02\xec\xe3\x0f\xed\x99P\xea\xe6r\ -\xb9VtJrb\xe0\xba\x8b,\x8f\xd0\xac\x83>\xfd\ -\x1fl\xddyVT\xba\xab\x0e\xd0\x1e\x9d\x1c\xc8[4\ -z\xd6\xd9\xbfr'\xcf<>\xdb\xfb\xa1\xc3\xe6K\xe5\ -\x81_\xc6'\xb1k\x19\x9b\xb3\xee\xe7L!\x96\xc7\x1d\ -\xae9n\xe7..\xb6\xad\xe5\xcc\xab\x03\x89\xf2\xd9\x99\ -\x03\xd6\xcbK}\x82\xa7\x19\xfe\xb9#\x8e\xf6\x9c\xb6\x91\ -\xbe\xff\xf8\x91}\xbf\x14dxo\xeb\x9f=}\xb8\xd1\ -\xd5J\xfb\x9d7\xaf\xe4}6\xe2\xce\x9c\x0cJq\xee\ -\xd4\xa2\x9ad\x9dK\xe5k\xb3\x1f\xd5\x81\xc5\x153n\ ->\x1b\xb9\xec\x14\xa3,\xf9v\xaa\xb0\xdbE\x07\xf2\x91\ -\xb3\x7f\xdb\xef\xae\x03\x8b`\xdb\x19\x97\xfd\x9f~#7\ -\xb1\xab\x07\xce\x9a\x9a\xe1\xb3\xedp\xf6\x9e\xbbW\x8f\xfa\ -\xe9\xed*\x9f\xb5\xeb\xdc\xf3\x0d9u`\xe3\xd7^\xf3\ -\x7f>P\xfcWIhL8\x87Z=\xf9M\x1dx\ -f\xa15kFAF\xf4<\xf3\xc3k\x8a'\x7f\xbd\ -\x8521DoP\xaf\x98-{6>[\xc7Z\x95\ -\xbav\xfc\xd8;\x9e\x13\xae=\xdc?\xea\xd5\xde\x935\ -zi\x8f\x9fx\x1c\xffe\xa3\xf9\x17~W\x1el\xb8\ -\x92\x974\xaf\xc7\xd9\x1a\xfb\xe8\xc3\xb7_\xe6O\xda}\ -aW\xff\x0d\x0fo\x95\xffa\xfd\xf7\xc4n\xa71]\ -\x9eU<\x96}\xef^\xb5\xa6\xae\xe3\xd4\x04&\x9c+\ -\xf7/\x96\x0d7\xf8k@\x1d\xf8,\x13>\x9b\xf3\xab\ -Ekm3W\xed\xd8\xb3\xd2\xe6\x87\x91\x17\xd2\x1cG\ -\xd7\x01\xad\x8c\xcaA\x07ic\xc9\xe16\x9f\xdf\xff\xd9\ -\x82\xcd\xe6v\xd9k\xb7.i\xf2\xa5\x8b\xe5\xe7\xc93\ -\xff\x06\xe4\xb9\xc4\xf8*\xf7\x13_U\xc7\xae\xad\xa6R\ -/\x1d\x9c8\xed\xda\xd1(\xe3\xd0\xaa\xbb\xa7O\x0c\x9c\ -\xd0\xc7\xdc

\xf3\xee\xea\x97\xdfM\x15\xbd\x89\x8b\ -\x8dO\x0a\x15\x9d\xdbS\xf1\xf0\x9b+\xfdFW>\x1f\ -\xbe`\xd6\xd1\x17\xe5\x8c\x17\xf3^\x7f\xde\x9fZyK\ -6b\xfc\xb3\x93\xebi\x0fX}\x17\xfa\x16Ox\xed\ -\xb07\xa8\xa6\x0e$\xbd\xe9~7}\xc4}\xdd>K\ -\xbe\xbc/\xd8\xf9\xe3\xac]\xdf\xfda\x7f\x8d\xb3\xd7\xf7\ -H\xb7\xa0\x9c\x8b[\x02\x97\x07V\x1a_\xd4\x0b\xa7\xee\ -\xe8\xb3$\xd1\xb7o\xefn+\x96\xcc\xca e\x9d\xde\ -GHt\x0a\xad;\xf7\xbe>\xe8W\xc58\xd7\x15\xeb\ -\xc9\x07\x00\xcc\x22\x85#7\x08\x07\x5c8\x1d\xce\x87S\ -\x03\x1a\x9c\x1c\x17A\xbf\x0c:)\xe6C\x13a\x8b\x7f\ -HA\x03\x91\xf0G\x83f\xba'`\x02\xff\xfa\x01S\ -7.\x81/\x14\x11\xa1\x11Y\x02g\xa0\xe8\xcb\x15Y\ -\xd9\xfdh\xd4\x13\xd0\x88\xd4\x82\xb6+4\x97\xd8\x1c\xa9\ -815&\x0d3\xae\xa2#i\xe8\xf3\x16\xa0\x09\x9e\ -_P\x98'g\xdd\xe3\x92i4\xf0a0\xe2\x88%\ -2\xf4U\x1d\xe8\xf7\xe6\xf2\xa4\xd0\x5c#\x8c\x83~A\ -\x99L\x8c\xc2\xd1\xd8o\x9a_\x8c\xfcD4\xea\x9bJ\ - \x83\xd0o\x89\xfc\x85\x0a\xbf\x1b\x96F\xe1\x0fC~\ -n\x89\x10\x9a\x89D\xc4\xb3\x98[\xc2E\xfeC\xd0\xff\ -E\xa9\x1c\x99\x8f\xa4\x04\xe8\x1f_\xca\xe7\x95A\xff9\ -\xe8w\x14\xc8K\xf8\xd0\x8ff&\xa6%<64i\ -1\xbb\xc2Q\xc6\xe3\x14A?\x9a\x19\xe8J\xd2R\xe0\ -\x5c\x96\xdc\x13\xdaf\xba\x85*\xfe|\x15\xbf\x0c\x1al\ -H\xa8H\x91x(f\xd9\xd0\x5c9\xddh\xcc\xc0\xc0\ -\x00Z\x1c\xafL\xc0\x93\xc9\xdc\x93\xd9\x9cb\xb6\x84K\ -\x8b\x14\x95\x88\xd9B8\xc3S\xc8\x8c\xc1\xf8\xadO\x87\ -\xa8(\xea\xbd\x91\xad\x04\xaa[\x85\xefi_\xac\xce\x08\ -\xe6\xc7\x1a\xc3ZJ'Z\x0a\xed.8\x0b$Mo\ -\x0c\xcb\x9f\x07\xc0\xf6\xcf\x01\xb0\xfc\xad1\xccq1l\ -\xa3\xb0\xde\xb6\x9dT\x91\xc7\x1c\xb5\x17\x95\x8f\xfc\xf0y\ -\x1c\x0f\xa4\xd0\x06\xfcc\x82V@\x85\x9e\x07*\xaeA\ -=\xb4(\x85eKCz\xe3@\xfbU.\xa1\xc1\x19\ -8\x87Gso\xde\x88?:c\xcb|\xb8\xa5\xf0\x0a\ -xh\xa6\xcf\xa3e\xc0V\xc6\x17\x16\xc2\xea\x16r\xf9\ -\xd8\xf7\x8a\xf8\xc2wU\xe2Gfk\x06E\xbb\x860\ -Y^\x0bLs=\x80\xe1IS@zp\x0c\x90M\ -t\x00)\xe7\x1b\x18Ch\xa8\xb7\x04\xad\x0c\x80\x9e\xbc\ -L\xfb[\x8av\x8f\xa1\x85i&q\x1a\xbaH\xf9\xd8\ -\xe4\x0aD\xa6\xa4\xd18rI\xa9\x22\x0e\x9bOi\x00\ -m\xd8I\x99\x82.\xc0\x0e8\x00W8\xeb\xf7\x82\x9d\ -L\x10\x08\x03\xd1\xa0\x17H\x02i \x1b\x0c\x04\x1c\xd8\ -\x19\x95\x00\x09(\x03#\xc0h0\x1eL\x06\xd3\xc1,\ -0\x1f,\x02\xcb\xc1\x1aP\x096\x81\xed\xe0\x07\xb0\x1f\ -\xfc\x04\x8e\x82S\xe0<\xb8\x0c\xaa\xc0Mp\x0f<\x06\ -\xcf\xc1+h\xe0R\x09z\x04\x13B\x17\x82=\xc1\x89\ -\xd0\x83\xe0E\x08 \x84\x10\xa2\x09\x09\x84\x14B6!\ -\x8fPH\x10\x12\xe4\x84\x11\x84\xb1\x84\xc9\x84\x0a\xc2|\ -\xc2\x12\xc2\x1a\xc2w\x84\xef\x09\xfb\x09G\x08\xa7\x09\xbf\ -\x12\xae\x13\xee\x10\xfe\x22\xd4\x10ID]\xa2)\xd1\x96\ -\xe8Ld\x10\x03\x88\xe1\xc4\xde\xc44\xe2\x00b!q\ -0q\x18q\x1c\xf1K\xe2\x5c\xe2R\xe2z\xe26\xe2\ -~\xe2Q\xe2yb\x15\xf1\x1e\xb1\x9a\x04H:$s\ -RW\x92;)\x80\x14IJ\x22\xf5#\x15\x90$\xa4\ -\x91\xa4I\xa4\xd9\xa4\xa5\xa4J\xd2N\xd2a\xd2YR\ -\x15\xe9>\xe9o2\x85lB\xa6\x91\xdd\xc9A\xe48\ -r:\x99C\x1eL\x1eI\x9eB\x9eO^M\xdeF\ ->D>K\xbeN~L\xae\xd5\xd0\xd3\xb0\xd1\xe8\xa1\ -\xc1\xd2\x88\xd7\xc8\xd2(\xd4(\xd3\x18\xaf1[c\xa5\ -\xc6V\x8d\x1f5\xcek\xdc\xd4xN\xa1P\xcc).\ -\x14\x7fJ\x1c%\x9b2\x882\x9c2\x85\xf25e#\ -e\x1f\xe54\xe5\x06\x05\x0eh\xd4.\xd4\x1e\xd4`j\ -\x12\x95M\x95Q\xc7S\xe7Q\xd7S\xf7R\xcfPo\ -R_j\xeah\xdakzi\xc6h\xf6\xd3\x14j\x8e\ -\xd1\x9c\xad\xb9Vs\x8f\xe6\x19\xcd[\x9a\xaf\xb4\x0c\xb5\ -\x9c\xb4XZIZ\x5c\xad\xa1Z\xd3\xb4\x96k\xed\xd4\ -:\xa9uS\xeb\x95\xb6\x91\xb6\x8bv\xb0v\x9a\xf6 \ -\xed\xd1\xdas\xb5+\xb5\x7f\xd4\xbe\xa2\xfdTGG\x87\ -\xae\x13\xa8\xd3W\x87\xaf3Jg\xae\xce\xb7:?\xeb\ -\x5c\xd7\xf9[\xd7X\xb7\xbbn\xa4n\x8e\xae\x5c\xf7K\ -\xddU\xba\xfbt\x7f\xd5}\xaa\xa7\xa7\xe7\xac\x17\xa6\xd7\ -OO\xa6\xf7\xa5\xde\x1a\xbd\x83z\xd7\xf4^\xea\x9b\xe8\ -{\xe8\xc7\xebs\xf5\xcb\xf5\x17\xe8o\xd3?\xa3\xff\xd0\ -@\xcb\xc0\xc9 \xdc`\xa0\xc10\x83\xd9\x06\x9b\x0dN\ -\x1a\xdc7\xd42t6\x8c4d\x1b\x8e4\x5c`\xf8\ -\xbd\xe1E\xc3j#\x13#\xa6Q\x92Q\x89\xd1\x14\xa3\ -\xb5FG\x8cn\x1bS\x8d\x9d\x8d\xa3\x8d\xb9\xc6\xe3\x8c\ -\x97\x19\x1f4\xbeaB2q0\x894\xe1\x98\x8c5\ -Yn\xf2\xa3\xc9MS\x8a\xa9\x8bi\xbc\xe9 \xd3\xc9\ -\xa6\x1bLO\x98>636\xf31\xcb0\x1bb\xb6\ -\xc0l\xb7Y\x959\xc9\xdc\xd9<\xde\x5c`>\xcd|\ -\x93\xf9\x05\xf3\x1a\x0b[\x8bp\x0b\x9e\xc5D\x8bJ\x8b\ -3\x16/,\xad-\xc3,y\x96\x93,7Z\x9e\xb7\ -\xac\xe9B\xeb\x12\xdd\xa5\xb8\xcb\x8c.\xdb\xbb\x5c\xb5\x22\ -[u\xb7\xeakUf\xf5\x8d\xd5\x8fV\xf7\xadM\xad\ -\x83\xac9\xd6\x93\xac7Y\xfffC\xb4\xe9n\x93b\ -3\xdcf\x99\xcd1\x9bj[;\xdbX[\xb1\xed<\ -\xdb\x83\xb6\xf7\xed\xcc\xed\xc2\xec\x06\xd9\xcd\xb4\xdbcw\ -\xc7\xde\xc4>\xc4\x9eo?\xd3~\xaf\xfd]\x9a\x19-\ -\x9c&\xa0\xcd\xa5\x1d\xa2=\xeej\xd35\xae\xab\xbc\xeb\ -\x92\xae'\xba\xbe\xa2\xbb\xd0\xd3\xe9c\xe8\x1b\xe9W\x1d\ -\xb4\x1d\x02\x1c\x0a\x1cf:\x1cpx\xech\xef\x98\xe8\ -8\xc2q\x9d\xe3oNZN\x01NENs\x9c\x0e\ -;\xbdpvq\xcet\x9e\xe0\xbc\xdd\xf9\xb6\x8b\xa5K\ -\xbc\xcb0\x97u.W\x5c\xf5\x5cC]\x07\xbb.u\ -=\xd7\x8d\xd2-\xa0[q\xb7\xaf\xbb\x9d\xeaN\xec\xee\ -\xdb\xbd\xa8\xfb\x82\xee'{\x10{\xf8\xf5\xe0\xf7\xf8\xba\ -\xc7i7\x0d\xb7@7\xa1\xdbR\xb7\x8b\xee\xba\xee\xe1\ -\xee\xa5\xee\xeb\xdc\xaf{\x98{$x\x8c\xf1\xd8\xee\xf1\ -\x90\xe1\xc8\xe8\xc7\x98\xc18\xcc\xa8\xf5\xf4\xf5\x14x.\ -\xf7\xbc\xcc4f\xf6b\x8ea\xeed\xfe\xe5\xd5\xdd\x8b\ -\xe3\xb5\xc0\xeb\x9c\xb7\x9ew\x8cw\xb9\xf7\x0e\xef'>\ -=|x>\xdf\xf8\x5c\xf25\xf1M\xf4\x9d\xe0{\xc0\ -\xf7\x8d\x9f\xbf\x9f\xc4\xaf\xd2\xef\x8e\xbf\xa3\x7f\x9e\xffB\ -\xff\x8b\x01\xa6\x01\xc9\x01S\x02~\x0e\xd4\x08\x8c\x08,\ -\x0f\xfc!\xf0o\x96\x1fK\xc6\xda\xc4z\x14\xe4\x1eT\ -\x1c\xb46\xe8vO\x97\x9e\xbc\x9e\xcb{\xde\x08\xa6\x07\ -\xb3\x83\x97\x04W\x85\xd0B\xf2B\x16\x87T\x85v\x0d\ -e\x87.\x0d\xfd=\xcc!\x8c\x1b\xb62\xecVx\xb7\ -\xf0A\xe1\xeb\xc3\x1fFxFH\x22\xb6F\xbc\x88d\ -E~\x16\xb9/\x8a\x14\x15\x1b5)\xeaD\xb4qt\ -z\xf4\xfc\xe8k1\xf4\x98\xc2\x98u1\x8fc}c\ -\x87\xc7\xee\x8b\xd3\x88\xeb\x1d7#\xeeb\xbcm<'\ -~M\xfc\xe3^\xfe\xbd>\xebu\xa8\xb7n\xef\xd4\xde\ -\xf3{\xff\x9e\xd0=A\x92\xb03\x91\x98\xd8+\xf1\xab\ -\xc4+}\x9c\xfa\x08\xfblO\x02I\xf1I_%]\ -MvI\x1e\x9c\xbc\xab/\xa5or\xdf\x05}\xffL\ -a\xa6\x8cH9\x9cj\x92\x9a\x9b\xba6\xf5yZD\ -\xda\xb4\xb4\xcb\xe9\xae\xe9\xf2\xf4\x03\x19\x06\x199\x19k\ -2^dFeVdVe1\xb2>\xcb:\x9am\ -\x95\xcd\xcf\xde\xd1\x8f\xda/\xa3\xdf\xca~\xd5\xfd\xa3\xfb\ -\xcf\xea\x7f3\xc77g|\xce\x85\x01.\x03\x86\x0c8\ -2\xd0j\xa0`\xe0\xee\x5c\x83\x5cv\xee\xe6<\x8d\xbc\ -\xcc\xbc\xb5y\xaf\xd9I\xec\xa5\xec\xea\xfc\xf8\xfc\x85\xf9\ -\x8f9\x91\x9c9\x9c{\xdc0\xeeL\xee\x1d^0\xaf\ -\x82w\xab \xb8\xa0\xa2\xe0vap\xe1W\x85w\x8a\ -B\x8bf\x17\xdd\xe7G\xf2\xe7\xf3\x9f\x0c\x8a\x1b\xb4h\ -\xd0\x8b\xe2\xa4\xe2U\xc5u\x82L\xc1\xc6\x12\xcd\x92\xbc\ -\x92\xef\x85\xc6\xc2b\xe1!\x91\x9dh\x88\xe8\xb4\xb8\x87\ -x\xbc\xb8j0k\xf0\xac\xc1\x8f%\xbd%+\xa5\x04\ -\xe9\x00\xe9\x0e\x99)4\xa6\x8e\xc9]\xe5\x9f\xcb\xaf\x97\ -\x86\x94.(}Y\x96Q\xb6y\x88\xd1\x10\xe1\x90c\ -C\xbb\x0f\x9d8\xf4\xd6\xb0\x98a+\x86\x93\x87s\x86\ -\x1f\x18\xd1u\xc4\xe8\x11\xd7?\x0b\xffl\xc9H\xc2\xc8\ -\xfc\x91\x07\xca\x1d\xca\xc7\x95\xdf\x1c\x15;j\xf5h\xed\ -\xd1\xc5\xa3\x8f\x8f\xf1\x1cS1\xe6\xd9\xd8\xcc\xb1;\xc7\ -\xd9\x8e\x1b5\xee\xc6\xe7\xb1\x9f\xaf\x1b\xaf?^2\xfe\ -\xe2\x84\xa0\x09\x8b\xbe \x7f\xc1\xff\xe2\xc4D\xef\x89\xf3\ -&\xd6N\xe2N\xfae\xb2\xe7\xe4\xd9\x93_O\xe1L\ -\xf9e*s\xea\xdc\xa9u_\x16|yb\x9a\xdf\xb4\ -o\xa6S\xa6\x0b\xa7_\x98\x11:cu\x85Q\xc5\xb0\ -\x8a\x1b_%~\xb5m&m\xe6\xa4\x99\xcff\xe5\xce\ -:2\xdbg\xf6\xa29\xdas\xe4s\xaa\xe6&\xcc\xdd\ -1\xcfq\xde\xf4y\xaf\xe7\x17\xcd?\xbf b\xc1\xc6\ -\x856\x0b'.|\xf15\xf7\xeb3\xdf\x84}S\xb9\ -\xc8v\xd1\xe4E5\x8b\xf9\x8b/-\x89]\xb2m\xa9\ -\xf3\xd2\xd9\xcb(\xcbJ\x97\xfd\xb9\ -\xf1\xbe\xfb\xfb\x0b\xf7\xdf8\x90{\xe0\xf2\xc1\xac\x83\xe7\ -\x0e\xf5=t\xe2\xc7\xde?\xfe\xfcS\xccO\x07\x0f\x87\ -\x1f\xde\xfbs\xf0\xcf?\x1ca\x1d\xf9\xfe\x97\x80_\xb6\ -\x1f\xf5;\xba\xed\x98\xef\xb1\xad\xc7}\x8fo=\xe1w\ -b\xdbI\xff\x93;N\x05\x9e\xday\xba\xe7\xe9=g\ -B\xcf\xec?\x1bu\xf6\xa7s\xf1\xe7\x8e\x9e\xefs\xfe\ -\xf4\x85\xf4\x0b\x97.\xe6\x5c\xac\xba\xc4\xbdt\xfbW\xc1\ -\xafO~+\xfd\xed\xd5\xe5QW4\xaeL\xbajx\ -u\xf65\x9bkK\xff\xd3\xed?\x1b\xab\xfc\xaav_\ -\x8f\xba~\xec\xf7\xd4\xdf/\xdf\xe0\xdc\xb8\xf7\x87\xf4\x8f\ -\xd77\xc7\xfd\xa9\xf7\xe7\xec[\xf6\xb7\xd6\xdc\xf6\xba\xfd\ -\xc3\x9d\x98;\xa7\xee\xf6\xbf{\xf3\x9e\xf8\xde\xab\xfb\xe3\ -\x1f\x18=X\xf8\xd0\xf5\xe1\x96Ga\x8f\x8e=\xcez\ -|\xf3\x89\xe4I\xdd_S\x9evy\xba\xea\x99\xcf\xb3\ -\x03\xd5\xc9\xd5\xd7\x9e\x97<\x7f\xf5b\xd2\xcb./W\ -\xff\x1d\xf0\xf7\xe1\x9a\xcc\x9a[\xaf\xca^S_\xcf}\ -\xd3\xed\xcd\xce\xda\xde\xb5W\xeaJ\x1a\xdeH\xe0\xc0\x81\ -\x03\x07\x0e\x1c8p\xe0\xc0\x81\x03\x07\x0e\x1c8p\xe0\ -\xc0\x81\x03\x07\x0e\x1c8p\xe0\xc0\x81\x03\x07\x8e\xffc\ -\x90\xc9dMGG\xc7\xac\xce\xe6\xe3\xff\x15aaa\ -\x8b\x0a\x0a\x0a\xea\xe0\xff7\xa8.:\x9b\x9f\xff'\xa0\ -v\x8ft\xaft)))Guuu\xed\xda\x83\x96\ -\x8e\x8e\x8e\x15\x9dNO\xf7\xf3\xf3\x9b\xd0\xabW\xaf\x1d\ -\x19\x19\x19\xe7srr\xfe\xe4p8/\x90C~\x18\ -v\x01\xc6}\xef\xef\xef\xff\x85\x83\x83C\x06\xca\xd3\x1e\ -\xbc|*@\xed\x1d\xb5{\xd5:\x188p\xe0]k\ -k\xebw\xec\xf2\xfd0@\xfdY{zz\x96%'\ -'\x1f\x86e\xd7\xaa\xd2i\xa5\xab\xed\xdb\xb7\xef\x11X\ -\xc6\x10\xd8.l\xd5\xc1\xd3\xa7\x0877\xb7\x12.\x97\ -[\xa3\x94\x9b\xc7\xe3\xbdvww\x17}ly\x16\x16\ -\x16\x01QQQ\xaba9\xaf>B\xe7-:T\x16\ -,s\xad\xa5\xa5%K\x9d\xb2\x7f*\x80r\x05\x0d\x18\ -0\xe0\x96\xaa\xcc\x91\x91\x91+\xe13\xa2\xdd\xda2`\ -\x1b\xb5A:R\x97\xce\xdf\xe5\xa2\xa3\xa3\xd7\xb7W?\ -\xd9\x99\xd0\xd6\xd6\xee\x02\xfb\x8a\x9fTeMKK;\ -\xad\xaf\xafO\x7f_>\x12\x89DA}D~~\xfe\ -\xb3\xf6\xd6\xbd\xd2AZ\xd5L&s\x18\xa4M\xed(\ -\xfdt\x04\x90.CBB\xe6\xa9\xca\x9a\x97\x97\xf7\xd0\ -\xd6\xd66\xb6\xa5\xf46661\x99\x99\x99\xbfv\x94\ -\xde\x9b\xbb\xac\xac\xac\xcb\x90\xb7\xb8\x8e\xd6S{\xc3\xd5\ -\xd55\x1f\x8e\x09/Ud}\x83\xc6R\xe59g\xf8\ -G\x84\xb6\xcc\xe7\x9d\xa5\xf7\xe6\x0e\xd9L\x88\xa7\xce\xd6\ -\x9b:ann\xee\xdb\xbf\x7f\xff\xdfU\xe5\x8c\x89\x89\ -\xd9\x80\xfa\xf9\xf8\xf8\xf8\xad\x9d\xad\xf3\xe6\x0e\xda\xae\xdb\ -\xa9T\xea[\xdf:\xfa7CKK\xcb,11q\ -\xaf\xaa\x9c\xf0\xb9\xf8\xbb\xb3u\xfd\xbe\xfe\xc8\xd8\xd8\xb8\ -Gg\xebM\x9d \x12\x89d\x16\x8b5\xa3\xb3u\xdb\ -Z\x07\xc7\xe6\xa7p\x5c\x8a\xeel\xbd\xa9\x13P\x9e\xa8\ -O\xb9\xdd7whN\xfd\xbfR\x07\xc8\xc6A\xf2\xa8\ -C/9997\xd1\xb3\x84l\x16##\xa3\xee\x14\ -\x0aEOCCC\xd7\xd0\xd0\xd0\x19\x8e57\xda\xa1\ -\x0eb:[\x7fm\x01\xb2;\xd5\xa1\xfb~\xfd\xfaU\ -\xd1\xe9\xf4\xd4\xf7\xd9(\xa8\xefn\x8f\xe7\xe0]\xb6\xf3\ -\xa7\x0ed\xff\xa0yN[u\x10\x10\x100\x05\xce\xa3\ -\xb5\xfe\x89^{\xe8\x1f9$\x83\x99\x99\x99OG\xe8\ -L]@\xf3\xfb\xe6\xeb\x11\x1f\xe1\xde\xf4\xe8\xd1cP\ -ki\xb6\x97\xfe\x91C\xb2\xfc[\xd6\xf0`\x9f\xac\x9f\ -\x9e\x9e~\xb6\xad2\x7f\xe8\x1a^{\xea\x1f9\xb4\x96\ -\x82\xc6\x9b\xf6\xd2\x9b:\x80\xe6\xb7qqq[\xd4!\ -/\xea\xf3MMM[\xfd\xa5\x90\xf6\xd6?r\xb1\xb1\ -\xb1\xdf\xa9|\xab\xec\x93\x83\x97\x97\xd7\x085\xc8\xd9\xb0\ -\xd6\x0f\xc7\xbf\xe7\xce\xce\xce\x03ZC\xbb#\xf4\x8f\x1c\ -ZGio=~\x0c,--{\xa2\xb5\xff\xb6\xca\ -\x87\xec\xcb\xbc\xbc\xbc\xc7\xcd\xc2\xa6\xa3y\xdc\xfb\xe8w\ -\x94\xfe\xd1\xbb\x04h[\xf8w\x94^[\x03\xd4\xe7\xa3\ -\xfeB\x1d}\x0e\xd4\xb3\x86\x81\x81\x81\x13\x1cC\xce\xa9\ -\xc6\xf5\xe9\xd3\xe7\x80\xb6\xb6\xb6\xc5\xbbx\xe8(\xfd#\ -\x07i\xfd\xf6!\xef6\xda\x1b\x81\x81\x81S\xd5!\x97\ -\xbf\xbf\xffDe\x99h^\xd5\xfc}\x0c\x9c\x7f\xfd\xf1\ -\xae\xb6\xd7\x91\xfaG\xce\xc7\xc7gt\xc7i\xf8\xdd@\ -k\x86h\xcdD\x1d2YYY\x855/\x1f\xbd\x9b\ -Q\xed\xd7\xd0:\x86\xab\xab+\xb7y\xba\x8e\xd6?z\ -\xaf\x81\xdaH\x87(\xf9=\x80\xfa)U\x87H\x15h\x8d\xa8\xf9\xf8\ -\x8a\xd6\x92\x0c\x0c\x0c\x1cQ\xd9\xd0^\xb8\xdeV>\xe1\ -\xdc\xf7\x91r\xde\xf1\xa9\xc0\xd9\xd9y\xa0:\xdaU\xf7\ -\xee\xdd?\xf0+\xdao\x03\xf5\xf1={\xf6\x9c\xd9\x5c\ -gAAA_\xa9\x83G\x07\x07\x87Lu\xe8L\xdd\ -P\x9e\x87i\x8bC\xedS\xb5\xbfh\x0bP\x9bh\xf6\ -\xfe\xffc\xce\x114qh\xddC\x1d\xbc\xb5\x07\x90\xed\ -\xdd|\x8d\xe0c\x1c\x9c\xe3.W\x17O\xa6\xa6\xa6^\ -\xeaX\x1bG.%%\xe5\xd8\xa7\xbeg\x1a\xbd\xa7F\ -\xfbt\xda*\xeb\x87\xbc{\xff'\xa8c\x8d\x10\x8d\xeb\ -\x9fZ\x9f\xff.\xc06\xe7\xa9\x865\xe9Z\x0f\x0f\x0f\ -I[yA6h[\xfb\x1dd[\x98\x98\x980\xd4\ -\xa1\x9b\x8e\x82\x9d\x9d]\xbc:\xe6\x05p\x1c\x9d\xf51\ -\xfb\x0e\xd0;\xb9\xe0\xe0\xe0\xb9m\xa5\x8fd\xf8\xb7\x9e\ -\x11prr\xcaQG\x1d\xa0\xf3\x8dp,\xcd}\xd7\ -\xfb\x01U \x1b\xd3\xc5\xc5%\xaf\xf9\xda\xd0\xc7\xea\x1e\ -\xc9\xd0\x11\xbaj/8::f\xabk~\x8c\xde9\ -\xa1y\x0f:_\x8a\xe6Z\xe8,\x01r\xc8\x8f\xc2\x90\ -\xfd\x85\xecLu\xd0B<#\xde;[\x7f\xea\x00\x9d\ -NOS\xe7y\xc6\xf6vH\xf7\xe8\xbcqg\xebM\ -\x9d\xa0\xd1h\xc9\xea\xda\x07\xdd\x11.00\xf0\xcb\x7f\ -\xda\xf3\xf2o\x83\x99\x99\x99\xb7:\xe6\xff\xed\xe5T\xcf\ -1#\x87\xce\xee\xa03<\x9d\xad7uBSS\xd3\ -4!!awg\xeb\xba\xb9C\xba\xd6\xd7\xd7\xa7\xc5\ -\xc4\xc4T\xaa\x86\xa35)\xb4\x97\xbb\xb3\xf5\xa6N\xc0\ -\xe7\x9a\x84\xd6:;[\xe7-\xf55h\x7f\xa7\x97\x97\ -\xd7p\x18\xfeF\xe5\xb9x\x89\xcetv\xb6\xde\xd4\x0d\ -4G\xe8\x8c}#J\x87\xf6\x5c@\x1ez\xb7\xc4\x1b\ -\xb2\xf9\x91\xbd\xa5\x9a\x1e\xceEf\xb7\xc6\x06\xfe7\xa1\ -\x93\xce\xbf?k\xcd\xf9w\xb4\xae\x8e\xf6\x9d\xab\xe6M\ -JJ\xfa\x11\x9d\xf5\xef(\xfdt\x14\xd0\xda\x0a\xfaf\ -D{\xeb\x1e}\xdb\x03\xcd\x19Z\xcb\x17\xda\xe7\xd9\x9c\ -/4\x1fD\xdf\xbchO}t\x16\x90\x8d\x14\x1e\x1e\ -\xbe\xa4\xd9\xf9\xf969\xf4\xae\x10\xed\x8dh\xcb9\x22\ -\xb4\x16\xd5l\x1fd\x8d:\xd7\x08?5 \xbb\x0f}\ -\xdb\x06\xd9J\x1f3wCy\xd0>+X\x86\x10\x96\ -e\xae\x0e\x9e\xac\xac\xac\xc2\xd17\x8eT\xe9\xa09\xf7\ -\xff\xfa\xb7\xbf\xa8T\xaa\x11\x1a\xabQ\x9f\x8d\xde\xe7\xa2\ -o2eff^Bk\x0d\x0a\x0d\x0a \x0d\x0a \ - Artboard\ -\x0d\x0a Created with\ - Sketch.\x0d\ -\x0a \x0d\x0a \ - \x0d\x0a \ - <\ -/circle>\x0d\x0a \ - \x0d\x0a \ -\x0d\x0a\x0d\x0a\ -\x00\x00\x04\x5c\ -<\ -?xml version=\x221.\ -0\x22 encoding=\x22UTF\ --8\x22?>\x0d\x0a\x0d\x0a \x0d\x0a \ - icon / o\ -utliner / entity\ - / error / Edit\ -or only\x0d\ -\x0a Creat\ -ed with Sketch.<\ -/desc>\x0d\x0a \x0d\x0a \ -\x0d\x0a \x0d\x0a\x0d\x0a\ -\x00\x00\x15\xcc\ -I\ -I*\x00j\x08\x00\x00\x80?\xe0@\x08$\x16\x0d\x07\ -\x84BaP\xb8d6\x1d\x0f\x88DbQ8\xa4V\ --\x17\x8cFcQ\xb8\xe4v\x0b\x02\x7f\xc7\xa4R9\ -$\x96M'\x94JeR\xb8\xa4\x82Y/\x98Lf\ -S9\xa4\xd6a.\x9bNgS\xb9\xe4\xf6}#\x9c\ -O\xe8T:%\x16\x8d/\xa0\xd1\xe9T\xbae6\x9d\ -\x1f\x81\xd3\xeaU:\xa5V\x91Q\xabVkU\xba\xe4\ -B\x93]\xb0XlU*\xfd\x8e\xcdg\xb4N\xec\xb6\ -\x9be\xb6\xdd&\xb5\xdb\xeeW;\xa4J\xe3u\xbc^\ -o7{\xd5\xf6\xfdi\xbe_\xf0X:\xde\x07\x09\x87\ -\xc4Sp\xd6`\x0e6\xb4\xd0\xc8\x02\xdf\xb91L\x14\ -3\x05\x0dH\x02PWX\x0b<\xe6\xc6\x80\x5c\xc0]\ -#XY\xa7}Vqx\x0a\xc5\xcfCJflB\ -\x90R\x86\x84\x9f \x22AA\x11\xd7\x9e\x85o X\ -\x828K-8\xb1\xe9G\xd5\xda96\x1d|\xf5\xa9\ -\xcf\x06>:G8)\xd2\x0a\x0c\x9e; \xa8>\x10\ -!1\xc5\xd4\xcf9vo\x1dw\x9b6f\xfaK\x12\ -\x04\x84\x14/RohL\xc3?\xa2\xf6s\xe5\xb1~\ -+~y\x5c\x80\x04\xf4\x99\xa4*\x0a<,G\xe3B\ -8\xbe\x81\x99(\x99\xbfK\x04\x1a\xac\xbf\x893\x9ej\ -\x00\xce\x91\xf0U\xa0\xa2r\xde\xd0\x92\xd0H\xd6\xab\xa4\ -+\xec\x1e\xabB)+bf\x13\x88(\xc6\x94\x1c\xa8\ -)\x9c\x82\x9dH)\xe2\xd0\x82I\x03\xde\x82\x06\xa8+\ -f\x924#\xe4\x13\x01%\x11\x1b\x0a\xd6\xaeQ*;\ -\x13\x8d\xe8+\xda\x8e\x1d\xc8)*\x82\x94\xc1\xa4\xa4l\ -\x22\xc9\x00\x02h\xcb\x01\x81\xf9-\x8c\x11R\x0a\x05\xa3\ -1\x08\x00)JA\xa1`\x92\xc8J\xd4\xd2\xa9\xc8\xc8\ -\xc4N\x16\xa0\xa6z\x0a\x01\xa2\xb3\x11\x1c\x02O\x03\xf8\ -a=\x9e\xa9y\xad?\x82g\xb5\x05%\x80\x02\xe22\ -y\xcf\x00 I=\x86\x11\x8a;5\xaa\xd4\x82\x9f6\ -\xa2\xf19j\x82\x89H\xa9\xea\xcf\x00B\x88eO\x97\ -j\x19\x9dQ\x8b\xc7\xf5LONh\x93BJ\xc1#\ -b=I*\x95\x82\x9bJ\x22F}l 2g\xe9\ -~\x8a\x9f\x14\xc4\xcb]\xa9\x918\xb6\x82\x94H(\x04\ -\x88\x9fm\x08U\x04\x9b\x88\xd5d\xb2H\x90\xdb\x1c\x8d\ -D\xe5\xa2\x0a%\xa2\xa3\xa4\xcaF\xab0\x01(\x90C\ -\xe8\xa1)2\x8d\xb6u\xa2\xbaY\xea]h\x86\xc2n\ -\x8b\xa4\xed \x80:\x22i\xc1!\x8bB~\xab&\xbd\ -\xf4\x06\x9e\xb7\xed\x9a\x82\x02\xc8\x89\xc72\x83\xd74\xc4\ -\xbd\xdc\xebm\xd6\x86@\x02\x9a@VULh\xdd\x04\ -\x92k\x1cNG \xa3\x8a*\x19\xcc\xb1|\xeb\x84\xae\ -WJ\x95\x85\xa1p\x012\x90\x0c\xc8\xa852\x9c\xeb\ -\x1dFg\x07U1\xfcb\xe2 \x08\xf1\x04\x912\xae\ -@\xb7\xe4J>H\x85D\xe5\xb2\x0a$\xa2'\xac\xca\ -\xec-\x19x+\x99Q\xc8\x849\x0fgX:\xf1\x9e\ -\xa8\xd9\xfa\x13\x13\x9a\x08(^\x88\x9bs(L\xb7\xc4\ -\xe7\xda\x0a\x02\x22%\x84\xca(\xea+\xf6\xa8\xa2\xea\xc8\ -DO\xa6\x82\xa8\x89\xb12\xb2\xabtO^\xde(\x89\ -\x932\x87\x1bLE\x9d\xad\x1bj\x0f\x13\xb8\xe8$\xc0\ -\x88nr\x96\xea\xb6\xee\xe8-\xe4\x88\x1a\x93,\xe1\x8f\ -\xeaK\xae\xd6\xa2pH7\x09/\xee[\xa6\xc0\xd8\xef\ -\x00\x07\x1e\x87\xf22\x97&\x96\xf0\x0bo.\xa1\xf3(\ -/7\xc3s\xbcW>ft=\x1a\x1d\xd2\x86\x9d:\ -'\xd5\xa8\xdd\xe2\x7f\xd6\xa0\x9dx\x01\xc3\xa1\xfcHi\ -\xc5\xad\x9cn\xf3\xc8r[\xf2\xf5\xdf'\xde\x00\x01\xe1\ -x\x88w\x8d\xe4->WD\x88\xf7\x1d\xd2\xed\xd4\xad\ -\x9e\x82{\xc1\x1b_(\x0ey}\x12j\x08\x05k\x94\ -\xe0v\xb7\xe6G\x22\x0a\x03\x22&\xbe\xb52\xecH\x8f\ -\xc4\xa1\x7fi\xdc\x22\x95\x99xk$\x0a\xb8\x82\x02s\ -\x12K\x13\x10\xd14\x22%\x04\x8a\x82\x14\xffI\xf4\x10\ -'&\xbd\x09\x81$,+\x88(?\x80\xe5\x14V\x9d\ -\xd0\xb4x \x91\xe2|\x05\x8c\xd7\xa2qLAB\xcc\ -\x1b]F4C\xa0\x90\xf5\x08KT#,J\xd8g\ -\x84Vd.\xa1QS\x1f\xa6\x84\x16\xa9\xf0d\xfd\x9e\ -|2,(\x00L\x10P\xcf\x0eJ\xb0zA\x22\x1d\ -\xbf\xb9R\xdc\x80\x05\xc9\x05\x08\xc4T^/x\x90\xe5\ -\x1a@\x00}\xe4D\xd0\x89\xb8|\xcab\x0cN-\xa8\ -\x00`A\x92$\xa2@b\x8cO\xb1\x5c\x89\x99\x01\xa0\ -\x0b\x12\xd8\xfc\x1adTQ \x90\xbf\x13K\xc4d\x8c\ -\xc4F4F\xa8\xd9\x1bL\x84pKq\xcc\x8aGS\ -\xe9\x1d\xe3\x0cy=1\x94\x82A\xa8\xf8\x9e#J|\ -\x8f\xe4J7H(\xe5\x1d#\xb4x.\xb1\xeaF\xc6\ -y!\x1f\xa4\x99\x10\x92\xb1\xc6B\x119\x0c\x0c\xe4C\ -\x08\x8cE\xb2N\x00\x09\x1cD#\xec\x92\x94$>Q\ -\xc891!\xe4\xd1t\x95\xb2\xbc\x87\xcb\x10a\x1a\xc9\ -\xdcn\x04*\xe4 \x12\x00(hG8\x07\x99B\xf0\ -\xe2\x8e\x82{-d\xbc\x85\x932&M\x90\x06k5\ -\x80\x00\x82\x8f\xe0\xb0\x88L*\x0a\x04\x86\x83\x06\x11\x07\ -\xac.'\x14\x8a\xc5\xa1,\xc8\xc8*\x10\x88\x84\x1b!\ -\x00\x18\xbb\xec\x03$A\x0c\xa4\xe8\x89 \x05\xf9\x17\x96\ -\xcb\xa2\x8d\x09\x88\xb1\xf94i\xcb\xe1J!\x9c\xe8\xbf\ -7\x9e\xcf\xa7\xf4\x08\xbb\xfe\x87A\xa2\xd1\xa8\xf18\x14\ -\x0e\x11\x07\x9b\xc3@\x90\xf8\x8d\x22z\xda\xaa\x81\xdeU\ -\x86D aS\x82\xad\x86\x96\x02]v\x7f1hL\ -\xe6\xb4\x09\xcc\xee\xc7l\xb6\xcbho\xfbu\xca\xe7J\ -\x82A\xa7\xb4\xfa\x88\xc2%s\x89\xc6Y\x88xA\xe2\ -\xe7*4N\x86i\x9b\xecN\xcbg~M\xa7\xf6\xa1\ -\x9c\xf3\x15\x94\xae\xdc2\xb9\x8a\x0d\xd6\x99x\x87D/\ -y[\xf8>\x10\xeb\x84\x01r\x8e\x9c8jT\xfe\xca\ -\xe3&\x98\xebN\x1f'\x99\xda\xcf\xb2\xfbm\xcc_7\ -w\xa7g\xaaYFw\x08\x8a\xfe\xe2\xae\xb6\xd4\xf1>\ -}\xb5\xae\x99l1\xf3\xec\x8e\xd3u\xd4\x8an:\xbd\ -\x88.\xf0\x01M\x97\xdes\xf7\xccU\xfc\xa3\x08Wu\ -\x06v\x01\xa3;\x9bf\xe7\xec\xad}\x9f\x8c\x17\xaf\xf2\ -\xddv\xfb\xb2\xee\xff\x03\x14\xcf\xfe\x8c\x0f\xd8\x00\xcfm\ -\x80\x88\x10\x13\x0b s\xb9\xecc]\x04\xf5\xd2}_\ -\x17\xd2\x0fm_vuPx\x19U\xc0\x02R\x9c\xc4\ -\x14#e\x0b\xf7\xa4Bm\x9a\xf5\xa1\x90l\xe1'b\ -\x11\x8a\x19XQ\xbe\x85\x9f\xb6a\x7f\x15\x90\x82\xa5r\ -?\x008\xe0@\x0cc\xb3\x16#s\xa2WF'\x8a\ -\xdb\xa8\xaaC_b\xd7y\xbfh\x1dE\xfczB\x08\ -D\x81@>\x90\x81\x99\xe9(]X\x91\xb1\x89\x9f\x09\ -\x19\xb5\x91e\xd5\xbaH~d\xa7\x85\xd8R\x88e\xc0\ -yP\x06W\xa4\x9c|\xa5\x9817\x83\xa6\x06f_\ -\x9d\x169\x89-~\xa4\xb7eJ\x1d\x97\x02%@\x15\ -\x9e\x92\xaeo\x8f\xe5\xa9\x06\x5c\x9d\xd8\xa9\xda\x8bR'\ -\x94^{\x99]Y\xfa\x80\xa0\xa8J\x19\xed\x90 \xd9\ -\x0a\x8e_h\xdayE\xa4\x11jI\xf2\xa5T:\x05\ -?\xa0\xd6\x0a\x15\xf1\x9c\x1e\xf6J\xa1\xa7\xd4J\xc9l\ -\xa8\xd1Z\x95\xf1R\x85\xc5\xc0\xa3Oc\x80\x0c<\x8e\ -\xc3\x18\xf6\xae\xa1\xe7\x14\xbes\xadV\xda\x82\xcbOk\ -tR\xb9vMKP\x12>-sY\x08\x05\xd1s\ -V\x04\x02\x03(\x1c,\x94\xecjj\x88\xa7(\xab9\ -S\xb3n\x94\xba\xd0D\xed'\xd5\x7f\x0a\x11\xc4 )\ -J\x8c\xb0\x0a\xf9\x1d\xec3\x96(\xab\xe5\xba\xc6\xece\ -\xabL\x0a\xa2@\x97gr\x15^\xa9<\x16\xfe\xb1\xeb\ -\x07O\x0dPn\xbcII\xc1\xd9\xc8\xbb\x0b\xc5d;\ -\xfe\x89\xc0q\xb5\x03\x14\xc8\x10\x8b\xb9\x0b\xbc2;\x92\ -\x0b\xc42\x84\xff\x22\xca2T+'\xcb%\x8c?\x00\ -\xc4s5\x0b\x04\xce\x11\x5c\xc1\x09\xcc\xb3\xb8\xfa\xe5\xb2\ -\x12\xeb+@E\xb2\xec\x8dJ/\x90\x81\x05=J\x85\ -E\xc0\xf8\xd1\x9f\x10\x81\x08%4\xe4\x90\xa0I\xc3!\ -\x87S\xceW\x1dy\x0bR\xaa\xd0\x00T\xd8vt$\ -\x8da\xc7M\xa1\x13\xd22\x05(oB\x09\x0d\xb7h\ -\x14Xr\xc3uB\xb6\xfcl\xd8\xdf\x80\xd3\xd7\x81t\ -\x01\xfd\xeb,2\xd8p\xe9\x08K8W\xcf:\xda\x12\ -\xa0\x01\x7f\x88\x90R\xe1\xa6\xe3.\xc3\xd1*\x0d\x98s\ -_|\xca9\xecK\x90BVP\xc5\xb0\x95\xd0P\xb7\ -\x97\xa2\xcc \x1b\xad\x18B\xee\xc0\xdeBz\x0c\x83\xb4\ -\xea\xbb~\xe2\xe9\xed\xbb\x9e\xf3\xbd\x9d;\xbe\xfb\xc1\xf0\ -\x9f/\x03\xc3\xf1\xbcy\xd7\x8e\xf2<\xbf1\xf5\xf1|\ -\xdfC\xd1\xc8|\xafK\xd5\xf5\x96\xef?\xd7\xf6\xbd\xbf\ -g\xdb\xf7\xbd/w\xdf\xf8\xbc\xbf\x87\xe3\xf9\xbc/\x97\ -\xe7\xfa\xbb\x9f\xa7\xeb\xfb\xb8\xcf\xb7\xef\xfc\xb6\x8f\xc7\xf3\ -\xfd\xb4o\xd7\xf7\xfe\xb2\xc4\x04\x13\x00\xfe\x00\x04\x00\x01\ -\x00\x00\x00\x00\x00\x00\x00\x00\x01\x04\x00\x01\x00\x00\x00`\ -\x00\x00\x00\x01\x01\x04\x00\x01\x00\x00\x00`\x00\x00\x00\x02\ -\x01\x03\x00\x04\x00\x00\x00T\x09\x00\x00\x03\x01\x03\x00\x01\ -\x00\x00\x00\x05\x00\x00\x00\x06\x01\x03\x00\x01\x00\x00\x00\x02\ -\x00\x00\x00\x11\x01\x04\x00\x01\x00\x00\x00\x08\x00\x00\x00\x15\ -\x01\x03\x00\x01\x00\x00\x00\x04\x00\x00\x00\x16\x01\x04\x00\x01\ -\x00\x00\x00`\x00\x00\x00\x17\x01\x04\x00\x01\x00\x00\x00b\ -\x08\x00\x00\x1a\x01\x05\x00\x01\x00\x00\x00\x5c\x09\x00\x00\x1b\ -\x01\x05\x00\x01\x00\x00\x00d\x09\x00\x00\x1c\x01\x03\x00\x01\ -\x00\x00\x00\x01\x00\x00\x00(\x01\x03\x00\x01\x00\x00\x00\x02\ -\x00\x00\x001\x01\x02\x00\x10\x00\x00\x00l\x09\x00\x00=\ -\x01\x03\x00\x01\x00\x00\x00\x02\x00\x00\x00R\x01\x03\x00\x01\ -\x00\x00\x00\x02\x00\x00\x00S\x01\x03\x00\x04\x00\x00\x00|\ -\x09\x00\x00s\x87\x07\x00H\x0c\x00\x00\x84\x09\x00\x00\x00\ -\x00\x00\x00\x08\x00\x08\x00\x08\x00\x08\x00\x802\x02\x00\xe8\ -\x03\x00\x00\x802\x02\x00\xe8\x03\x00\x00paint\ -.net 4.0.9\x00\x01\x00\x01\x00\x01\ -\x00\x01\x00\x00\x00\x0cHLino\x02\x10\x00\x00m\ -ntrRGB XYZ \x07\xce\x00\x02\x00\ -\x09\x00\x06\x001\x00\x00acspMSFT\x00\ -\x00\x00\x00IEC sRGB\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf6\xd6\x00\x01\x00\x00\x00\ -\x00\xd3-HP \x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x11cprt\x00\x00\x01P\x00\ -\x00\x003desc\x00\x00\x01\x84\x00\x00\x00lw\ -tpt\x00\x00\x01\xf0\x00\x00\x00\x14bkpt\x00\ -\x00\x02\x04\x00\x00\x00\x14rXYZ\x00\x00\x02\x18\x00\ -\x00\x00\x14gXYZ\x00\x00\x02,\x00\x00\x00\x14b\ -XYZ\x00\x00\x02@\x00\x00\x00\x14dmnd\x00\ -\x00\x02T\x00\x00\x00pdmdd\x00\x00\x02\xc4\x00\ -\x00\x00\x88vued\x00\x00\x03L\x00\x00\x00\x86v\ -iew\x00\x00\x03\xd4\x00\x00\x00$lumi\x00\ -\x00\x03\xf8\x00\x00\x00\x14meas\x00\x00\x04\x0c\x00\ -\x00\x00$tech\x00\x00\x040\x00\x00\x00\x0cr\ -TRC\x00\x00\x04<\x00\x00\x08\x0cgTRC\x00\ -\x00\x04<\x00\x00\x08\x0cbTRC\x00\x00\x04<\x00\ -\x00\x08\x0ctext\x00\x00\x00\x00Copyr\ -ight (c) 1998 He\ -wlett-Packard Co\ -mpany\x00\x00desc\x00\x00\x00\x00\x00\ -\x00\x00\x12sRGB IEC61966\ --2.1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x12\ -sRGB IEC61966-2.\ -1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00XYZ \x00\x00\x00\x00\x00\x00\xf3Q\x00\ -\x01\x00\x00\x00\x01\x16\xccXYZ \x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00XYZ \x00\ -\x00\x00\x00\x00\x00o\xa2\x00\x008\xf5\x00\x00\x03\x90X\ -YZ \x00\x00\x00\x00\x00\x00b\x99\x00\x00\xb7\x85\x00\ -\x00\x18\xdaXYZ \x00\x00\x00\x00\x00\x00$\xa0\x00\ -\x00\x0f\x84\x00\x00\xb6\xcfdesc\x00\x00\x00\x00\x00\ -\x00\x00\x16IEC http://ww\ -w.iec.ch\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x16IEC http://w\ -ww.iec.ch\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00desc\x00\x00\x00\x00\x00\ -\x00\x00.IEC 61966-2.1\ - Default RGB col\ -our space - sRGB\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00.IEC \ -61966-2.1 Defaul\ -t RGB colour spa\ -ce - sRGB\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\ -esc\x00\x00\x00\x00\x00\x00\x00,Refer\ -ence Viewing Con\ -dition in IEC619\ -66-2.1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00,Reference View\ -ing Condition in\ - IEC61966-2.1\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00view\x00\x00\x00\x00\x00\ -\x13\xa4\xfe\x00\x14_.\x00\x10\xcf\x14\x00\x03\xed\xcc\x00\ -\x04\x13\x0b\x00\x03\x5c\x9e\x00\x00\x00\x01XYZ \x00\ -\x00\x00\x00\x00L\x09V\x00P\x00\x00\x00W\x1f\xe7m\ -eas\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x8f\x00\ -\x00\x00\x02sig \x00\x00\x00\x00CRT c\ -urv\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x05\x00\ -\x0a\x00\x0f\x00\x14\x00\x19\x00\x1e\x00#\x00(\x00-\x00\ -2\x007\x00;\x00@\x00E\x00J\x00O\x00T\x00\ -Y\x00^\x00c\x00h\x00m\x00r\x00w\x00|\x00\ -\x81\x00\x86\x00\x8b\x00\x90\x00\x95\x00\x9a\x00\x9f\x00\xa4\x00\ -\xa9\x00\xae\x00\xb2\x00\xb7\x00\xbc\x00\xc1\x00\xc6\x00\xcb\x00\ -\xd0\x00\xd5\x00\xdb\x00\xe0\x00\xe5\x00\xeb\x00\xf0\x00\xf6\x00\ -\xfb\x01\x01\x01\x07\x01\x0d\x01\x13\x01\x19\x01\x1f\x01%\x01\ -+\x012\x018\x01>\x01E\x01L\x01R\x01Y\x01\ -`\x01g\x01n\x01u\x01|\x01\x83\x01\x8b\x01\x92\x01\ -\x9a\x01\xa1\x01\xa9\x01\xb1\x01\xb9\x01\xc1\x01\xc9\x01\xd1\x01\ -\xd9\x01\xe1\x01\xe9\x01\xf2\x01\xfa\x02\x03\x02\x0c\x02\x14\x02\ -\x1d\x02&\x02/\x028\x02A\x02K\x02T\x02]\x02\ -g\x02q\x02z\x02\x84\x02\x8e\x02\x98\x02\xa2\x02\xac\x02\ -\xb6\x02\xc1\x02\xcb\x02\xd5\x02\xe0\x02\xeb\x02\xf5\x03\x00\x03\ -\x0b\x03\x16\x03!\x03-\x038\x03C\x03O\x03Z\x03\ -f\x03r\x03~\x03\x8a\x03\x96\x03\xa2\x03\xae\x03\xba\x03\ -\xc7\x03\xd3\x03\xe0\x03\xec\x03\xf9\x04\x06\x04\x13\x04 \x04\ --\x04;\x04H\x04U\x04c\x04q\x04~\x04\x8c\x04\ -\x9a\x04\xa8\x04\xb6\x04\xc4\x04\xd3\x04\xe1\x04\xf0\x04\xfe\x05\ -\x0d\x05\x1c\x05+\x05:\x05I\x05X\x05g\x05w\x05\ -\x86\x05\x96\x05\xa6\x05\xb5\x05\xc5\x05\xd5\x05\xe5\x05\xf6\x06\ -\x06\x06\x16\x06'\x067\x06H\x06Y\x06j\x06{\x06\ -\x8c\x06\x9d\x06\xaf\x06\xc0\x06\xd1\x06\xe3\x06\xf5\x07\x07\x07\ -\x19\x07+\x07=\x07O\x07a\x07t\x07\x86\x07\x99\x07\ -\xac\x07\xbf\x07\xd2\x07\xe5\x07\xf8\x08\x0b\x08\x1f\x082\x08\ -F\x08Z\x08n\x08\x82\x08\x96\x08\xaa\x08\xbe\x08\xd2\x08\ -\xe7\x08\xfb\x09\x10\x09%\x09:\x09O\x09d\x09y\x09\ -\x8f\x09\xa4\x09\xba\x09\xcf\x09\xe5\x09\xfb\x0a\x11\x0a'\x0a\ -=\x0aT\x0aj\x0a\x81\x0a\x98\x0a\xae\x0a\xc5\x0a\xdc\x0a\ -\xf3\x0b\x0b\x0b\x22\x0b9\x0bQ\x0bi\x0b\x80\x0b\x98\x0b\ -\xb0\x0b\xc8\x0b\xe1\x0b\xf9\x0c\x12\x0c*\x0cC\x0c\x5c\x0c\ -u\x0c\x8e\x0c\xa7\x0c\xc0\x0c\xd9\x0c\xf3\x0d\x0d\x0d&\x0d\ -@\x0dZ\x0dt\x0d\x8e\x0d\xa9\x0d\xc3\x0d\xde\x0d\xf8\x0e\ -\x13\x0e.\x0eI\x0ed\x0e\x7f\x0e\x9b\x0e\xb6\x0e\xd2\x0e\ -\xee\x0f\x09\x0f%\x0fA\x0f^\x0fz\x0f\x96\x0f\xb3\x0f\ -\xcf\x0f\xec\x10\x09\x10&\x10C\x10a\x10~\x10\x9b\x10\ -\xb9\x10\xd7\x10\xf5\x11\x13\x111\x11O\x11m\x11\x8c\x11\ -\xaa\x11\xc9\x11\xe8\x12\x07\x12&\x12E\x12d\x12\x84\x12\ -\xa3\x12\xc3\x12\xe3\x13\x03\x13#\x13C\x13c\x13\x83\x13\ -\xa4\x13\xc5\x13\xe5\x14\x06\x14'\x14I\x14j\x14\x8b\x14\ -\xad\x14\xce\x14\xf0\x15\x12\x154\x15V\x15x\x15\x9b\x15\ -\xbd\x15\xe0\x16\x03\x16&\x16I\x16l\x16\x8f\x16\xb2\x16\ -\xd6\x16\xfa\x17\x1d\x17A\x17e\x17\x89\x17\xae\x17\xd2\x17\ -\xf7\x18\x1b\x18@\x18e\x18\x8a\x18\xaf\x18\xd5\x18\xfa\x19\ - \x19E\x19k\x19\x91\x19\xb7\x19\xdd\x1a\x04\x1a*\x1a\ -Q\x1aw\x1a\x9e\x1a\xc5\x1a\xec\x1b\x14\x1b;\x1bc\x1b\ -\x8a\x1b\xb2\x1b\xda\x1c\x02\x1c*\x1cR\x1c{\x1c\xa3\x1c\ -\xcc\x1c\xf5\x1d\x1e\x1dG\x1dp\x1d\x99\x1d\xc3\x1d\xec\x1e\ -\x16\x1e@\x1ej\x1e\x94\x1e\xbe\x1e\xe9\x1f\x13\x1f>\x1f\ -i\x1f\x94\x1f\xbf\x1f\xea \x15 A l \x98 \ -\xc4 \xf0!\x1c!H!u!\xa1!\xce!\xfb\x22\ -'\x22U\x22\x82\x22\xaf\x22\xdd#\x0a#8#f#\ -\x94#\xc2#\xf0$\x1f$M$|$\xab$\xda%\ -\x09%8%h%\x97%\xc7%\xf7&'&W&\ -\x87&\xb7&\xe8'\x18'I'z'\xab'\xdc(\ -\x0d(?(q(\xa2(\xd4)\x06)8)k)\ -\x9d)\xd0*\x02*5*h*\x9b*\xcf+\x02+\ -6+i+\x9d+\xd1,\x05,9,n,\xa2,\ -\xd7-\x0c-A-v-\xab-\xe1.\x16.L.\ -\x82.\xb7.\xee/$/Z/\x91/\xc7/\xfe0\ -50l0\xa40\xdb1\x121J1\x821\xba1\ -\xf22*2c2\x9b2\xd43\x0d3F3\x7f3\ -\xb83\xf14+4e4\x9e4\xd85\x135M5\ -\x875\xc25\xfd676r6\xae6\xe97$7\ -`7\x9c7\xd78\x148P8\x8c8\xc89\x059\ -B9\x7f9\xbc9\xf9:6:t:\xb2:\xef;\ --;k;\xaa;\xe8<' >`>\xa0>\xe0?\ -!?a?\xa2?\xe2@#@d@\xa6@\xe7A\ -)AjA\xacA\xeeB0BrB\xb5B\xf7C\ -:C}C\xc0D\x03DGD\x8aD\xceE\x12E\ -UE\x9aE\xdeF\x22FgF\xabF\xf0G5G\ -{G\xc0H\x05HKH\x91H\xd7I\x1dIcI\ -\xa9I\xf0J7J}J\xc4K\x0cKSK\x9aK\ -\xe2L*LrL\xbaM\x02MJM\x93M\xdcN\ -%NnN\xb7O\x00OIO\x93O\xddP'P\ -qP\xbbQ\x06QPQ\x9bQ\xe6R1R|R\ -\xc7S\x13S_S\xaaS\xf6TBT\x8fT\xdbU\ -(UuU\xc2V\x0fV\x5cV\xa9V\xf7WDW\ -\x92W\xe0X/X}X\xcbY\x1aYiY\xb8Z\ -\x07ZVZ\xa6Z\xf5[E[\x95[\xe5\x5c5\x5c\ -\x86\x5c\xd6]']x]\xc9^\x1a^l^\xbd_\ -\x0f_a_\xb3`\x05`W`\xaa`\xfcaOa\ -\xa2a\xf5bIb\x9cb\xf0cCc\x97c\xebd\ -@d\x94d\xe9e=e\x92e\xe7f=f\x92f\ -\xe8g=g\x93g\xe9h?h\x96h\xeciCi\ -\x9ai\xf1jHj\x9fj\xf7kOk\xa7k\xffl\ -Wl\xafm\x08m`m\xb9n\x12nkn\xc4o\ -\x1eoxo\xd1p+p\x86p\xe0q:q\x95q\ -\xf0rKr\xa6s\x01s]s\xb8t\x14tpt\ -\xccu(u\x85u\xe1v>v\x9bv\xf8wVw\ -\xb3x\x11xnx\xccy*y\x89y\xe7zFz\ -\xa5{\x04{c{\xc2|!|\x81|\xe1}A}\ -\xa1~\x01~b~\xc2\x7f#\x7f\x84\x7f\xe5\x80G\x80\ -\xa8\x81\x0a\x81k\x81\xcd\x820\x82\x92\x82\xf4\x83W\x83\ -\xba\x84\x1d\x84\x80\x84\xe3\x85G\x85\xab\x86\x0e\x86r\x86\ -\xd7\x87;\x87\x9f\x88\x04\x88i\x88\xce\x893\x89\x99\x89\ -\xfe\x8ad\x8a\xca\x8b0\x8b\x96\x8b\xfc\x8cc\x8c\xca\x8d\ -1\x8d\x98\x8d\xff\x8ef\x8e\xce\x8f6\x8f\x9e\x90\x06\x90\ -n\x90\xd6\x91?\x91\xa8\x92\x11\x92z\x92\xe3\x93M\x93\ -\xb6\x94 \x94\x8a\x94\xf4\x95_\x95\xc9\x964\x96\x9f\x97\ -\x0a\x97u\x97\xe0\x98L\x98\xb8\x99$\x99\x90\x99\xfc\x9a\ -h\x9a\xd5\x9bB\x9b\xaf\x9c\x1c\x9c\x89\x9c\xf7\x9dd\x9d\ -\xd2\x9e@\x9e\xae\x9f\x1d\x9f\x8b\x9f\xfa\xa0i\xa0\xd8\xa1\ -G\xa1\xb6\xa2&\xa2\x96\xa3\x06\xa3v\xa3\xe6\xa4V\xa4\ -\xc7\xa58\xa5\xa9\xa6\x1a\xa6\x8b\xa6\xfd\xa7n\xa7\xe0\xa8\ -R\xa8\xc4\xa97\xa9\xa9\xaa\x1c\xaa\x8f\xab\x02\xabu\xab\ -\xe9\xac\x5c\xac\xd0\xadD\xad\xb8\xae-\xae\xa1\xaf\x16\xaf\ -\x8b\xb0\x00\xb0u\xb0\xea\xb1`\xb1\xd6\xb2K\xb2\xc2\xb3\ -8\xb3\xae\xb4%\xb4\x9c\xb5\x13\xb5\x8a\xb6\x01\xb6y\xb6\ -\xf0\xb7h\xb7\xe0\xb8Y\xb8\xd1\xb9J\xb9\xc2\xba;\xba\ -\xb5\xbb.\xbb\xa7\xbc!\xbc\x9b\xbd\x15\xbd\x8f\xbe\x0a\xbe\ -\x84\xbe\xff\xbfz\xbf\xf5\xc0p\xc0\xec\xc1g\xc1\xe3\xc2\ -_\xc2\xdb\xc3X\xc3\xd4\xc4Q\xc4\xce\xc5K\xc5\xc8\xc6\ -F\xc6\xc3\xc7A\xc7\xbf\xc8=\xc8\xbc\xc9:\xc9\xb9\xca\ -8\xca\xb7\xcb6\xcb\xb6\xcc5\xcc\xb5\xcd5\xcd\xb5\xce\ -6\xce\xb6\xcf7\xcf\xb8\xd09\xd0\xba\xd1<\xd1\xbe\xd2\ -?\xd2\xc1\xd3D\xd3\xc6\xd4I\xd4\xcb\xd5N\xd5\xd1\xd6\ -U\xd6\xd8\xd7\x5c\xd7\xe0\xd8d\xd8\xe8\xd9l\xd9\xf1\xda\ -v\xda\xfb\xdb\x80\xdc\x05\xdc\x8a\xdd\x10\xdd\x96\xde\x1c\xde\ -\xa2\xdf)\xdf\xaf\xe06\xe0\xbd\xe1D\xe1\xcc\xe2S\xe2\ -\xdb\xe3c\xe3\xeb\xe4s\xe4\xfc\xe5\x84\xe6\x0d\xe6\x96\xe7\ -\x1f\xe7\xa9\xe82\xe8\xbc\xe9F\xe9\xd0\xea[\xea\xe5\xeb\ -p\xeb\xfb\xec\x86\xed\x11\xed\x9c\xee(\xee\xb4\xef@\xef\ -\xcc\xf0X\xf0\xe5\xf1r\xf1\xff\xf2\x8c\xf3\x19\xf3\xa7\xf4\ -4\xf4\xc2\xf5P\xf5\xde\xf6m\xf6\xfb\xf7\x8a\xf8\x19\xf8\ -\xa8\xf98\xf9\xc7\xfaW\xfa\xe7\xfbw\xfc\x07\xfc\x98\xfd\ -)\xfd\xba\xfeK\xfe\xdc\xffm\xff\xff\ -\x00\x00\x03\xae\ -<\ -?xml version=\x221.\ -0\x22 encoding=\x22UTF\ --8\x22?>\x0d\x0a\x0d\x0a \x0d\x0a \ - icon / o\ -utliner / entity\ - / Default - Upd\ -ated\x0d\x0a \ - Created \ -with Sketch.\x0d\x0a <\ -/defs>\x0d\x0a \ -\x0d\x0a \x0d\x0a <\ -/g>\x0d\x0a\x0d\x0a\ -\x00\x00\x04\x8d\ -<\ -?xml version=\x221.\ -0\x22 encoding=\x22UTF\ --8\x22?>\x0d\x0a\x0d\x0a \x0d\x0a \ - icon / o\ -utliner / entity\ - / error / Not \ -active \x0d\ -\x0a Creat\ -ed with Sketch.<\ -/desc>\x0d\x0a \x0d\x0a \x0d\x0a \x0d\x0a\x0d\x0a\ -\x00\x00\x04s\ -<\ -?xml version=\x221.\ -0\x22 encoding=\x22UTF\ --8\x22?>\x0d\x0a\x0d\x0a \x0d\x0a \ - icon / o\ -utliner / entity\ - / Editor only \ -- Updated\x0d\x0a Cre\ -ated with Sketch\ -.\x0d\x0a \x0d\x0a \ - \x0d\x0a \ - \x0d\x0a\ - \x0d\x0a\ -\x0d\x0a\ -\x00\x00\x15\x0a\ -I\ -I*\x00\xa8\x07\x00\x00\x80?\xe0@\x08$\x16\x0d\x07\ -\x84BaP\xb8d6\x1d\x0f\x88DbQ8\xa4V\ --\x17\x8cFcQ\xb8\xe4v\x0b\x02\x7f\xc7\xa4R9\ -$\x96M'\x94JeR\xb8\xa4\x82Y/\x98Lf\ -S9\xa4\xd6a.\x9bNgS\xb9\xe4\xf6}#\x9c\ -O\xe8T:%\x16\x8d/\xa0\xd1\xe9T\xbae6\x9d\ -\x1f\x81\xd3\xeaU:\xa5V\x91Q\xabVkU\xba\xe4\ -B\x93]\xb0XlU*\xfd\x8e\xcdg\xb4N\xec\xb6\ -\x9be\xb6\xdd&\xb5\xdb\xeeW;\xa4J\xe3u\xbc^\ -o7{\xd5\xf6\xfdi\xbe_\xf0X:\xde\x07\x09\x87\ -\xc4Sp\xd6`\x0e6\xb5 \x05\xc1E0P\xcc\x14\ -5\x05\x09A]pW6r\x0a\xd6\xc6\x80_U\x9c\ -^\x02\xb1s\xd0\xd2\xa4\x01H)B\x0aO\x82\x91 \ -\xa0\x88\xeb\xce\x0a\xb7\x82\xac`\xab-\x0b\xd2\x8f\xa5\xb4\ -p,:\x99\xec\x80\x19\x059\xc1N\x90^<\xed\xd9\ -\x05A\xc1S\x1a\x1d\x1c\xf3\x85f\xeb\xd7x\x93i\x01\ -b\x0a\x90\x82\x85\xeaM\xe8)\x9bB\xbd\x9c\xf6l^\ -\xaa\xdfnW \x01AP\xb0S\xc5\x89\xf9\x058\xe8\ -R\x93?e\x83\xfa\xac\xbd\xcb\x82\x04\x03 \xa5Z\x0a\ -'.\x84\xb3B5\xaa\xe9\x0a\xfa\xff\xaa\xd0\x0aJ\x90\ -\x13\x88(\xc6\x94\x1c\xa8)\x9c\x82\x9dH)\xe2\xcc<\ -((j\x82\xb5\x898\xf8\xd0\xbeiD \xc2\xb4\xeb\ -\x94$\x8e\xa4\x03{\xbe\x8e\x9d\xc8)*\x82\x94\xcd\x09\ -\xb0\x8b$\x00\x0a\x0a\x18 \xa3\x04,\x82\xb2(\xc4\x1c\ -\x00\x0aM\x09a\x09\xc5\xab\xacV\xaaE\xf22\x04\x16\ -\xa0\xa6z\x0a\x01\xa2\xb29\x1c\x82\x8f\xed\x09\xeb\x06\x82\ -q\x9a\x08.#-\xb2\x08\x1240\xeca&\xae\x92\ -z\xa7(\xa2\xe9\x01j\x82\x89H\xac\xbe\x82\x0a-\x09\ -v\xa1\xa4\x02\xf2\x0aOJ\xe8\xa9*\xd0\x8d\x88\xf4\xdc\ -\xabP\xea|\xe0\xbb B\x02\x0a_\xa2\xa7\xc4\xe8\xd0\ -\xd2\x0ab@-\xa0\xa5\x12\x0a\xf8\xa2\x07\xda\x0a\x154\ -&\xe25D\xaa\x95\x22\x9bE\xa2)\x01h\x82\x89h\ -\xa8\xe8\xd0\x91\xad\x22\x04\xfd\xa0\x90b(J4#m\ -G6.u2\x99T!\x8e2\x0a\xe7\xa0\x80:\x22\ -i\xa0\xa1\x8bB~\xd6G\xf8\x1a\x82\xd4H ,\x88\ -\x9cm\x08=]\xc8\xeb\xddx\xb6X\x08Z@)\xa0\ -\xa5b*74$\x9a\xc6\x90Kh \xe2\x8a\x86m\ -\x0c7,\xdbk}|\xa5\xdb\xa8R@L\xbc\xa8\xa8\ -4\xd0\x9c\xf7:\x04\x1d \xa6**<4$Ly\ -x\xad\xd7\x9a\x95z\xa1)\x01l\x82\x89(\x89\xea\xd0\ -\xb9\xab:@\x0a\xc3\x88\xac\x14\xc6\xd6\xc9n\x10\xb6\xe1\ -J>\x18\x84$\x06\x82\x0a\x17\xa2&\xdbB\x13^H\ -\x15<\x82\x00\x88\x89`\xd0\x8a8=\xb2\xbcd*6\ -F\x83\xa4\x13P\x01\x8c\x22\x06\xc3B\xc9\xe1(\x15%\ -b\xa2&KB\x1cf\xcb\xf6r\xa2\xe7h2@\xdf\ - \x92*\x1f\xa11\xba&A\xa3 \xb62 j4\ -2\xa5\xe1\x9b\xc9\xd8\xfb\x18\xc7f\xda\xa0\x01\xab!\xda\ -\xc0\x03\xad-\x89\x06\x8e\x00k\xc8~\xc0\xc6\xecX\xf6\ -\xc96\xec\xcb\x1e\xa2\xa8\x1f\xfbV\xd8\x86\xed\xdb\x83L\ -\x7f\xee{\xaa\x1d\xbb\x80;\xca'\xa7\xb5[\xea\xc5\xbf\ -\xa0\x9a\x9c\x88\x88\xf0\xb9o\x11\xae\xa2\x9aJ\x80\xf0fD\x18aE\ -\x81\xad\xa4d\xbal\xdaU,\x81\xcb\xa6\xd3\x18\x1c\xce\ -\xa5\x5c\xae\xceb\xb5\xeb\x0d\x8a\x0d@\x00Af\xd40\ -\x0c:\xc7\x09\x95!\xe0\xc7\x8b`\x00\xd1#L\xdc\xa1\ -\x15Il\xde\xb2\x00\xad\xdd\xef\xf3\xb9\xd6\x03\x076\xb2\ -\xd9\xe6\xb6\x9b]\xb2T\x0f\x83:\xe0\xc0[\x93\xa6\x0c\ -\x1a\x91\xbf\xae\xf7\x9a\xb5\xeee\x84\xce\xcb\xf0Y\xed\x0c\ -G\x0dB\x91\xe2\xacr\xa2,\x19u\xa1\x13\xc8\xdbY\ -\x88\xadT\x01W\x9a\xdf/\xda-\xccR\xc1\xba\xde\xc0\ -\xf4\x96\x8d6\xc5\xfeQ\x83+\xb4#9\x1b;\x87\xb3\ -\xda\xcd6\xfb\xed\xf6\x83\xa3\xa2\xe0b8W)U2\ -\x06\xcf\xd0\x84\xe4n\xeee\xea\xb1\x9c\xeanz~l\ -\xefZi\x89\xe1\x80\xa0\xdb\x08\x18\x8e\xe4\xbf\x91\x90\xb0\ -\x99\x9d\xa6n\xb5\xe9\xd1z\x1f\xd6\x01\xebK\xde\xd6\x0d\ -*\x15\x90b\xa5aIP1\x01#1_\x86\xc9\xe3\ -m\x9eX\x02\x10?\xe1W\xa9\x06a\xde\xc7a\x9eJ\ -\x87\xa4\x18\x84G\x13s\xe9\x06\x19\x922\x85\xfe\x84Y\ -\xa7\x91\xfc\x86 V\xf2/_\xe0$\xa2\x04n\x92\xa2\ -\x19\x06\x1eSq\x95#'\x1d(\xad\xfa\x8bW\xd8\xc9\ -\x80\x7f\xe4U\x864I\xe3g\x9d\x15\x1d\x90b%7\ -\x15\x922\xae@J\xe1'>\x14\x92\x1a\x88\xc6[X\ -\xa4\xa4\x9aL\x8a\x8f\xf9=\x03\x94SiM\x0c\x95[\ -\xd7\xe5\xceK\xdd\x09z\x5c\x85\xe7\x19~\x1aiTI\ -\xb2N\x94%)RVs_\xb9\x12tXdz\x09\ ->\x98\x119\x89\xa1J\x85\xc4\x18\xa3M\xc3\xc8:~\ -\x96&\xf9j\x85ShJY;\xa1\xd1*&\x1eE\ -A$\x18\xd6A\x81tL\xd5A\x83$\x8e%\x9ee\ -x\xb2\x13\x8b\xa9\x9a^]\xac\x13\xdam\x11\xa7d\xd3\ -\xfc(F\x10`\xa5\x062\xd0a\xdd#9^\x99\xb6\ -\x80n+4\xf2\x98\xb2\x13J\xd5\x10\xad\xec\xbaJ\xad\ -\x96j\xfbA8\xb2\xadT\x9a\xcdC\xec\xfbbc\x9f\ -\xe4;\x1e\xddg\xeb+\x89(\xb6\x90\x9br\xe5\x85\xad\ -\xfa\xba\x81\xba\xae9\xce\xef\xb9\xa7g\x06x\xbc\xab\x8b\ -\xb2\xd3\xbb\xafu~\xf1\xbf\x13\xfb\xd1\xd7\xbd\xaf\xf6v\ -\xc5\xb80K\xf7\x08D\x8b\xe4\x18AM\xc5D\x18\xf8\ -\xc2\x9a \x81\x06%\x13r\x81\x06\x18q4\xa6\xe4\xc7\ -\x00\x09\xac\x00\xc41\xfcL\x8dA\x87L\x91x\xc7\xb1\ -\xc1\xbd\x06$2\x9c)\xc5@\xcb\x0c\xc1\x06\xb5\xf0@\ -6\x12\x07\xf3[\x8a\xbf@\xc3\xa4\x1a\x0b\xcds{\xc9\ -#\x00\x12\xa7\xdd\x03.\x19\x0c\xf2\x99=\x10`\xd9#\ -5\xf4K\xffT\xba\xb4f\xec\xff\x0cPh\xa5\x03\x0b\ -t\xd9\x14\xc2\xc6\x923{Y\xd85m\x83i\xda\xac\ -\xbd\xa3k\xdb\xb6\xf9{m\xdc7=\xd2\xc4\xca\xf7]\ -\xe3y\xdd\xaf\xed\xeb}\xdf\xaa\xbd\xff\x81\xe0\xa9\xed\xf3\ -\x83\xe1\xb8usr\xe28\xbe1m\xdd\xf8\xdeC\x91\ -\xe3\xb8^K\x95\xe5\xb8\xae[\x99\xde\xb9\x8ek\x9d\xdc\ -\xf9\xce{\xa1\xda\xba\x0e\x8b\xa5\xd0\xf8\xfe\x9b\xa9\xdb\xfa\ -N\xab\xad\xc1\x10\x10\x00\x13\x00\xfe\x00\x04\x00\x01\x00\x00\ -\x00\x00\x00\x00\x00\x00\x01\x04\x00\x01\x00\x00\x00`\x00\x00\ -\x00\x01\x01\x04\x00\x01\x00\x00\x00`\x00\x00\x00\x02\x01\x03\ -\x00\x04\x00\x00\x00\x92\x08\x00\x00\x03\x01\x03\x00\x01\x00\x00\ -\x00\x05\x00\x00\x00\x06\x01\x03\x00\x01\x00\x00\x00\x02\x00\x00\ -\x00\x11\x01\x04\x00\x01\x00\x00\x00\x08\x00\x00\x00\x15\x01\x03\ -\x00\x01\x00\x00\x00\x04\x00\x00\x00\x16\x01\x04\x00\x01\x00\x00\ -\x00`\x00\x00\x00\x17\x01\x04\x00\x01\x00\x00\x00\x9f\x07\x00\ -\x00\x1a\x01\x05\x00\x01\x00\x00\x00\x9a\x08\x00\x00\x1b\x01\x05\ -\x00\x01\x00\x00\x00\xa2\x08\x00\x00\x1c\x01\x03\x00\x01\x00\x00\ -\x00\x01\x00\x00\x00(\x01\x03\x00\x01\x00\x00\x00\x02\x00\x00\ -\x001\x01\x02\x00\x10\x00\x00\x00\xaa\x08\x00\x00=\x01\x03\ -\x00\x01\x00\x00\x00\x02\x00\x00\x00R\x01\x03\x00\x01\x00\x00\ -\x00\x02\x00\x00\x00S\x01\x03\x00\x04\x00\x00\x00\xba\x08\x00\ -\x00s\x87\x07\x00H\x0c\x00\x00\xc2\x08\x00\x00\x00\x00\x00\ -\x00\x08\x00\x08\x00\x08\x00\x08\x00\x802\x02\x00\xe8\x03\x00\ -\x00\x802\x02\x00\xe8\x03\x00\x00paint.n\ -et 4.0.9\x00\x01\x00\x01\x00\x01\x00\x01\ -\x00\x00\x00\x0cHLino\x02\x10\x00\x00mnt\ -rRGB XYZ \x07\xce\x00\x02\x00\x09\x00\ -\x06\x001\x00\x00acspMSFT\x00\x00\x00\ -\x00IEC sRGB\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\xf6\xd6\x00\x01\x00\x00\x00\x00\xd3\ --HP \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x11cprt\x00\x00\x01P\x00\x00\x00\ -3desc\x00\x00\x01\x84\x00\x00\x00lwtp\ -t\x00\x00\x01\xf0\x00\x00\x00\x14bkpt\x00\x00\x02\ -\x04\x00\x00\x00\x14rXYZ\x00\x00\x02\x18\x00\x00\x00\ -\x14gXYZ\x00\x00\x02,\x00\x00\x00\x14bXY\ -Z\x00\x00\x02@\x00\x00\x00\x14dmnd\x00\x00\x02\ -T\x00\x00\x00pdmdd\x00\x00\x02\xc4\x00\x00\x00\ -\x88vued\x00\x00\x03L\x00\x00\x00\x86vie\ -w\x00\x00\x03\xd4\x00\x00\x00$lumi\x00\x00\x03\ -\xf8\x00\x00\x00\x14meas\x00\x00\x04\x0c\x00\x00\x00\ -$tech\x00\x00\x040\x00\x00\x00\x0crTR\ -C\x00\x00\x04<\x00\x00\x08\x0cgTRC\x00\x00\x04\ -<\x00\x00\x08\x0cbTRC\x00\x00\x04<\x00\x00\x08\ -\x0ctext\x00\x00\x00\x00Copyrig\ -ht (c) 1998 Hewl\ -ett-Packard Comp\ -any\x00\x00desc\x00\x00\x00\x00\x00\x00\x00\ -\x12sRGB IEC61966-2\ -.1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x12sR\ -GB IEC61966-2.1\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00XYZ \x00\x00\x00\x00\x00\x00\xf3Q\x00\x01\x00\ -\x00\x00\x01\x16\xccXYZ \x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00XYZ \x00\x00\x00\ -\x00\x00\x00o\xa2\x00\x008\xf5\x00\x00\x03\x90XYZ\ - \x00\x00\x00\x00\x00\x00b\x99\x00\x00\xb7\x85\x00\x00\x18\ -\xdaXYZ \x00\x00\x00\x00\x00\x00$\xa0\x00\x00\x0f\ -\x84\x00\x00\xb6\xcfdesc\x00\x00\x00\x00\x00\x00\x00\ -\x16IEC http://www.\ -iec.ch\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x16IEC http://www\ -.iec.ch\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00desc\x00\x00\x00\x00\x00\x00\x00\ -.IEC 61966-2.1 D\ -efault RGB colou\ -r space - sRGB\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00.IEC 61\ -966-2.1 Default \ -RGB colour space\ - - sRGB\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00des\ -c\x00\x00\x00\x00\x00\x00\x00,Referen\ -ce Viewing Condi\ -tion in IEC61966\ --2.1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00,\ -Reference Viewin\ -g Condition in I\ -EC61966-2.1\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00view\x00\x00\x00\x00\x00\x13\xa4\ -\xfe\x00\x14_.\x00\x10\xcf\x14\x00\x03\xed\xcc\x00\x04\x13\ -\x0b\x00\x03\x5c\x9e\x00\x00\x00\x01XYZ \x00\x00\x00\ -\x00\x00L\x09V\x00P\x00\x00\x00W\x1f\xe7mea\ -s\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x8f\x00\x00\x00\ -\x02sig \x00\x00\x00\x00CRT cur\ -v\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x05\x00\x0a\x00\ -\x0f\x00\x14\x00\x19\x00\x1e\x00#\x00(\x00-\x002\x00\ -7\x00;\x00@\x00E\x00J\x00O\x00T\x00Y\x00\ -^\x00c\x00h\x00m\x00r\x00w\x00|\x00\x81\x00\ -\x86\x00\x8b\x00\x90\x00\x95\x00\x9a\x00\x9f\x00\xa4\x00\xa9\x00\ -\xae\x00\xb2\x00\xb7\x00\xbc\x00\xc1\x00\xc6\x00\xcb\x00\xd0\x00\ -\xd5\x00\xdb\x00\xe0\x00\xe5\x00\xeb\x00\xf0\x00\xf6\x00\xfb\x01\ -\x01\x01\x07\x01\x0d\x01\x13\x01\x19\x01\x1f\x01%\x01+\x01\ -2\x018\x01>\x01E\x01L\x01R\x01Y\x01`\x01\ -g\x01n\x01u\x01|\x01\x83\x01\x8b\x01\x92\x01\x9a\x01\ -\xa1\x01\xa9\x01\xb1\x01\xb9\x01\xc1\x01\xc9\x01\xd1\x01\xd9\x01\ -\xe1\x01\xe9\x01\xf2\x01\xfa\x02\x03\x02\x0c\x02\x14\x02\x1d\x02\ -&\x02/\x028\x02A\x02K\x02T\x02]\x02g\x02\ -q\x02z\x02\x84\x02\x8e\x02\x98\x02\xa2\x02\xac\x02\xb6\x02\ -\xc1\x02\xcb\x02\xd5\x02\xe0\x02\xeb\x02\xf5\x03\x00\x03\x0b\x03\ -\x16\x03!\x03-\x038\x03C\x03O\x03Z\x03f\x03\ -r\x03~\x03\x8a\x03\x96\x03\xa2\x03\xae\x03\xba\x03\xc7\x03\ -\xd3\x03\xe0\x03\xec\x03\xf9\x04\x06\x04\x13\x04 \x04-\x04\ -;\x04H\x04U\x04c\x04q\x04~\x04\x8c\x04\x9a\x04\ -\xa8\x04\xb6\x04\xc4\x04\xd3\x04\xe1\x04\xf0\x04\xfe\x05\x0d\x05\ -\x1c\x05+\x05:\x05I\x05X\x05g\x05w\x05\x86\x05\ -\x96\x05\xa6\x05\xb5\x05\xc5\x05\xd5\x05\xe5\x05\xf6\x06\x06\x06\ -\x16\x06'\x067\x06H\x06Y\x06j\x06{\x06\x8c\x06\ -\x9d\x06\xaf\x06\xc0\x06\xd1\x06\xe3\x06\xf5\x07\x07\x07\x19\x07\ -+\x07=\x07O\x07a\x07t\x07\x86\x07\x99\x07\xac\x07\ -\xbf\x07\xd2\x07\xe5\x07\xf8\x08\x0b\x08\x1f\x082\x08F\x08\ -Z\x08n\x08\x82\x08\x96\x08\xaa\x08\xbe\x08\xd2\x08\xe7\x08\ -\xfb\x09\x10\x09%\x09:\x09O\x09d\x09y\x09\x8f\x09\ -\xa4\x09\xba\x09\xcf\x09\xe5\x09\xfb\x0a\x11\x0a'\x0a=\x0a\ -T\x0aj\x0a\x81\x0a\x98\x0a\xae\x0a\xc5\x0a\xdc\x0a\xf3\x0b\ -\x0b\x0b\x22\x0b9\x0bQ\x0bi\x0b\x80\x0b\x98\x0b\xb0\x0b\ -\xc8\x0b\xe1\x0b\xf9\x0c\x12\x0c*\x0cC\x0c\x5c\x0cu\x0c\ -\x8e\x0c\xa7\x0c\xc0\x0c\xd9\x0c\xf3\x0d\x0d\x0d&\x0d@\x0d\ -Z\x0dt\x0d\x8e\x0d\xa9\x0d\xc3\x0d\xde\x0d\xf8\x0e\x13\x0e\ -.\x0eI\x0ed\x0e\x7f\x0e\x9b\x0e\xb6\x0e\xd2\x0e\xee\x0f\ -\x09\x0f%\x0fA\x0f^\x0fz\x0f\x96\x0f\xb3\x0f\xcf\x0f\ -\xec\x10\x09\x10&\x10C\x10a\x10~\x10\x9b\x10\xb9\x10\ -\xd7\x10\xf5\x11\x13\x111\x11O\x11m\x11\x8c\x11\xaa\x11\ -\xc9\x11\xe8\x12\x07\x12&\x12E\x12d\x12\x84\x12\xa3\x12\ -\xc3\x12\xe3\x13\x03\x13#\x13C\x13c\x13\x83\x13\xa4\x13\ -\xc5\x13\xe5\x14\x06\x14'\x14I\x14j\x14\x8b\x14\xad\x14\ -\xce\x14\xf0\x15\x12\x154\x15V\x15x\x15\x9b\x15\xbd\x15\ -\xe0\x16\x03\x16&\x16I\x16l\x16\x8f\x16\xb2\x16\xd6\x16\ -\xfa\x17\x1d\x17A\x17e\x17\x89\x17\xae\x17\xd2\x17\xf7\x18\ -\x1b\x18@\x18e\x18\x8a\x18\xaf\x18\xd5\x18\xfa\x19 \x19\ -E\x19k\x19\x91\x19\xb7\x19\xdd\x1a\x04\x1a*\x1aQ\x1a\ -w\x1a\x9e\x1a\xc5\x1a\xec\x1b\x14\x1b;\x1bc\x1b\x8a\x1b\ -\xb2\x1b\xda\x1c\x02\x1c*\x1cR\x1c{\x1c\xa3\x1c\xcc\x1c\ -\xf5\x1d\x1e\x1dG\x1dp\x1d\x99\x1d\xc3\x1d\xec\x1e\x16\x1e\ -@\x1ej\x1e\x94\x1e\xbe\x1e\xe9\x1f\x13\x1f>\x1fi\x1f\ -\x94\x1f\xbf\x1f\xea \x15 A l \x98 \xc4 \ -\xf0!\x1c!H!u!\xa1!\xce!\xfb\x22'\x22\ -U\x22\x82\x22\xaf\x22\xdd#\x0a#8#f#\x94#\ -\xc2#\xf0$\x1f$M$|$\xab$\xda%\x09%\ -8%h%\x97%\xc7%\xf7&'&W&\x87&\ -\xb7&\xe8'\x18'I'z'\xab'\xdc(\x0d(\ -?(q(\xa2(\xd4)\x06)8)k)\x9d)\ -\xd0*\x02*5*h*\x9b*\xcf+\x02+6+\ -i+\x9d+\xd1,\x05,9,n,\xa2,\xd7-\ -\x0c-A-v-\xab-\xe1.\x16.L.\x82.\ -\xb7.\xee/$/Z/\x91/\xc7/\xfe050\ -l0\xa40\xdb1\x121J1\x821\xba1\xf22\ -*2c2\x9b2\xd43\x0d3F3\x7f3\xb83\ -\xf14+4e4\x9e4\xd85\x135M5\x875\ -\xc25\xfd676r6\xae6\xe97$7`7\ -\x9c7\xd78\x148P8\x8c8\xc89\x059B9\ -\x7f9\xbc9\xf9:6:t:\xb2:\xef;-;\ -k;\xaa;\xe8<' >`>\xa0>\xe0?!?\ -a?\xa2?\xe2@#@d@\xa6@\xe7A)A\ -jA\xacA\xeeB0BrB\xb5B\xf7C:C\ -}C\xc0D\x03DGD\x8aD\xceE\x12EUE\ -\x9aE\xdeF\x22FgF\xabF\xf0G5G{G\ -\xc0H\x05HKH\x91H\xd7I\x1dIcI\xa9I\ -\xf0J7J}J\xc4K\x0cKSK\x9aK\xe2L\ -*LrL\xbaM\x02MJM\x93M\xdcN%N\ -nN\xb7O\x00OIO\x93O\xddP'PqP\ -\xbbQ\x06QPQ\x9bQ\xe6R1R|R\xc7S\ -\x13S_S\xaaS\xf6TBT\x8fT\xdbU(U\ -uU\xc2V\x0fV\x5cV\xa9V\xf7WDW\x92W\ -\xe0X/X}X\xcbY\x1aYiY\xb8Z\x07Z\ -VZ\xa6Z\xf5[E[\x95[\xe5\x5c5\x5c\x86\x5c\ -\xd6]']x]\xc9^\x1a^l^\xbd_\x0f_\ -a_\xb3`\x05`W`\xaa`\xfcaOa\xa2a\ -\xf5bIb\x9cb\xf0cCc\x97c\xebd@d\ -\x94d\xe9e=e\x92e\xe7f=f\x92f\xe8g\ -=g\x93g\xe9h?h\x96h\xeciCi\x9ai\ -\xf1jHj\x9fj\xf7kOk\xa7k\xfflWl\ -\xafm\x08m`m\xb9n\x12nkn\xc4o\x1eo\ -xo\xd1p+p\x86p\xe0q:q\x95q\xf0r\ -Kr\xa6s\x01s]s\xb8t\x14tpt\xccu\ -(u\x85u\xe1v>v\x9bv\xf8wVw\xb3x\ -\x11xnx\xccy*y\x89y\xe7zFz\xa5{\ -\x04{c{\xc2|!|\x81|\xe1}A}\xa1~\ -\x01~b~\xc2\x7f#\x7f\x84\x7f\xe5\x80G\x80\xa8\x81\ -\x0a\x81k\x81\xcd\x820\x82\x92\x82\xf4\x83W\x83\xba\x84\ -\x1d\x84\x80\x84\xe3\x85G\x85\xab\x86\x0e\x86r\x86\xd7\x87\ -;\x87\x9f\x88\x04\x88i\x88\xce\x893\x89\x99\x89\xfe\x8a\ -d\x8a\xca\x8b0\x8b\x96\x8b\xfc\x8cc\x8c\xca\x8d1\x8d\ -\x98\x8d\xff\x8ef\x8e\xce\x8f6\x8f\x9e\x90\x06\x90n\x90\ -\xd6\x91?\x91\xa8\x92\x11\x92z\x92\xe3\x93M\x93\xb6\x94\ - \x94\x8a\x94\xf4\x95_\x95\xc9\x964\x96\x9f\x97\x0a\x97\ -u\x97\xe0\x98L\x98\xb8\x99$\x99\x90\x99\xfc\x9ah\x9a\ -\xd5\x9bB\x9b\xaf\x9c\x1c\x9c\x89\x9c\xf7\x9dd\x9d\xd2\x9e\ -@\x9e\xae\x9f\x1d\x9f\x8b\x9f\xfa\xa0i\xa0\xd8\xa1G\xa1\ -\xb6\xa2&\xa2\x96\xa3\x06\xa3v\xa3\xe6\xa4V\xa4\xc7\xa5\ -8\xa5\xa9\xa6\x1a\xa6\x8b\xa6\xfd\xa7n\xa7\xe0\xa8R\xa8\ -\xc4\xa97\xa9\xa9\xaa\x1c\xaa\x8f\xab\x02\xabu\xab\xe9\xac\ -\x5c\xac\xd0\xadD\xad\xb8\xae-\xae\xa1\xaf\x16\xaf\x8b\xb0\ -\x00\xb0u\xb0\xea\xb1`\xb1\xd6\xb2K\xb2\xc2\xb38\xb3\ -\xae\xb4%\xb4\x9c\xb5\x13\xb5\x8a\xb6\x01\xb6y\xb6\xf0\xb7\ -h\xb7\xe0\xb8Y\xb8\xd1\xb9J\xb9\xc2\xba;\xba\xb5\xbb\ -.\xbb\xa7\xbc!\xbc\x9b\xbd\x15\xbd\x8f\xbe\x0a\xbe\x84\xbe\ -\xff\xbfz\xbf\xf5\xc0p\xc0\xec\xc1g\xc1\xe3\xc2_\xc2\ -\xdb\xc3X\xc3\xd4\xc4Q\xc4\xce\xc5K\xc5\xc8\xc6F\xc6\ -\xc3\xc7A\xc7\xbf\xc8=\xc8\xbc\xc9:\xc9\xb9\xca8\xca\ -\xb7\xcb6\xcb\xb6\xcc5\xcc\xb5\xcd5\xcd\xb5\xce6\xce\ -\xb6\xcf7\xcf\xb8\xd09\xd0\xba\xd1<\xd1\xbe\xd2?\xd2\ -\xc1\xd3D\xd3\xc6\xd4I\xd4\xcb\xd5N\xd5\xd1\xd6U\xd6\ -\xd8\xd7\x5c\xd7\xe0\xd8d\xd8\xe8\xd9l\xd9\xf1\xdav\xda\ -\xfb\xdb\x80\xdc\x05\xdc\x8a\xdd\x10\xdd\x96\xde\x1c\xde\xa2\xdf\ -)\xdf\xaf\xe06\xe0\xbd\xe1D\xe1\xcc\xe2S\xe2\xdb\xe3\ -c\xe3\xeb\xe4s\xe4\xfc\xe5\x84\xe6\x0d\xe6\x96\xe7\x1f\xe7\ -\xa9\xe82\xe8\xbc\xe9F\xe9\xd0\xea[\xea\xe5\xebp\xeb\ -\xfb\xec\x86\xed\x11\xed\x9c\xee(\xee\xb4\xef@\xef\xcc\xf0\ -X\xf0\xe5\xf1r\xf1\xff\xf2\x8c\xf3\x19\xf3\xa7\xf44\xf4\ -\xc2\xf5P\xf5\xde\xf6m\xf6\xfb\xf7\x8a\xf8\x19\xf8\xa8\xf9\ -8\xf9\xc7\xfaW\xfa\xe7\xfbw\xfc\x07\xfc\x98\xfd)\xfd\ -\xba\xfeK\xfe\xdc\xffm\xff\xff\ -\x00\x00\x04o\ -<\ -?xml version=\x221.\ -0\x22 encoding=\x22UTF\ --8\x22?>\x0d\x0a\x0d\x0a \x0d\x0a \ - icon / o\ -utliner / entity\ - / Editor only \ -- Saved\x0d\ -\x0a Creat\ -ed with Sketch.<\ -/desc>\x0d\x0a \x0d\x0a <\ -g id=\x22icon-/-out\ -liner-/-entity-/\ ---Editor-only---\ -Saved\x22 stroke=\x22n\ -one\x22 stroke-widt\ -h=\x221\x22 fill=\x22none\ -\x22 fill-rule=\x22eve\ -nodd\x22>\x0d\x0a \ -\x0d\x0a \ -\x0d\x0a\x0d\x0a\ -\x00\x00\x07\x1d\ -<\ -?xml version=\x221.\ -0\x22 encoding=\x22UTF\ --8\x22 standalone=\x22\ -no\x22?>\x0d\x0a\x0d\x0a \x0d\x0a \ - lock on\ -\x0d\x0a Created with\ - Sketch.\x0d\ -\x0a \x0d\x0a \x0d\x0a \ -\x0d\x0a \x0d\x0a\x0d\x0a\ -\x00\x00\x05\x1d\ -<\ -?xml version=\x221.\ -0\x22 encoding=\x22UTF\ --8\x22?>\x0d\x0a\x0d\x0a \x0d\x0a \ - icon / o\ -utliner / slice \ -/ standard copy<\ -/title>\x0d\x0a Created with \ -Sketch.\x0d\x0a\ - \x0d\x0a \x0d\x0a \ -\x0d\x0a \ - \x0d\x0a \ - \x0d\x0a \ - \x0d\x0a \x0d\x0a\x0d\x0a\ -\x00\x00\x04\xa0\ -<\ -?xml version=\x221.\ -0\x22 encoding=\x22UTF\ --8\x22?>\x0d\x0a\x0d\x0a \x0d\x0a \ - icon / o\ -utliner / entity\ - / Not active - \ -Updated\x0d\ -\x0a Creat\ -ed with Sketch.<\ -/desc>\x0d\x0a \x0d\x0a <\ -g id=\x22icon-/-out\ -liner-/-entity-/\ --Not-active---Up\ -dated\x22 stroke=\x22n\ -one\x22 stroke-widt\ -h=\x221\x22 fill=\x22none\ -\x22 fill-rule=\x22eve\ -nodd\x22>\x0d\x0a \ -\x0d\x0a \ - \x0d\x0a\x0d\x0a\ -\x00\x00\x04\x9c\ -<\ -?xml version=\x221.\ -0\x22 encoding=\x22UTF\ --8\x22?>\x0d\x0a\x0d\x0a \x0d\x0a \ - icon / o\ -utliner / entity\ - / Not active - \ -Saved\x0d\x0a \ - Created\ - with Sketch.\x0d\x0a \ -\x0d\x0a \x0d\x0a \ -\x0d\x0a \x0d\x0a\x0d\x0a\ -\x00\x00\x06\xdc\ -<\ -?xml version=\x221.\ -0\x22 encoding=\x22UTF\ --8\x22?>\x0d\x0a\x0d\x0a \x0d\x0a \ - Group 13\ -\x0d\x0a Created with\ - Sketch.\x0d\ -\x0a \x0d\x0a \ - \x0d\x0a \ - \x0d\x0a\ - \ -\x0d\x0a \ - \ - \x0d\x0a \ - \x0d\x0a \ - \x0d\x0a \ - \x0d\x0a \x0d\x0a\x0d\x0a\ -\x00\x00\x03\x87\ -<\ -?xml version=\x221.\ -0\x22 encoding=\x22UTF\ --8\x22?>\x0d\x0a\x0d\x0a \x0d\x0a \ - icon / o\ -utliner / entity\ - / Loop v2\x0d\x0a Cr\ -eated with Sketc\ -h.\x0d\x0a <\ -g id=\x22icon-/-out\ -liner-/-entity-/\ --Loop-v2\x22 stroke\ -=\x22none\x22 stroke-w\ -idth=\x221\x22 fill=\x22n\ -one\x22 fill-rule=\x22\ -evenodd\x22>\x0d\x0a \ - \x0d\x0a \x0d\x0a\x0d\x0a\ -\x00\x00_l\ -I\ -I*\x00\x08\x00\x00\x00\x17\x00\xfe\x00\x04\x00\x01\x00\x00\ -\x00\x00\x00\x00\x00\x00\x01\x03\x00\x01\x00\x00\x00`\x00\x00\ -\x00\x01\x01\x03\x00\x01\x00\x00\x00`\x00\x00\x00\x02\x01\x03\ -\x00\x04\x00\x00\x00\x22\x01\x00\x00\x03\x01\x03\x00\x01\x00\x00\ -\x00\x05\x00\x00\x00\x06\x01\x03\x00\x01\x00\x00\x00\x02\x00\x00\ -\x00\x11\x01\x04\x00\x01\x00\x00\x00DS\x00\x00\x12\x01\x03\ -\x00\x01\x00\x00\x00\x01\x00\x00\x00\x15\x01\x03\x00\x01\x00\x00\ -\x00\x04\x00\x00\x00\x16\x01\x03\x00\x01\x00\x00\x00`\x00\x00\ -\x00\x17\x01\x04\x00\x01\x00\x00\x00\xfa\x0b\x00\x00\x1a\x01\x05\ -\x00\x01\x00\x00\x00*\x01\x00\x00\x1b\x01\x05\x00\x01\x00\x00\ -\x002\x01\x00\x00\x1c\x01\x03\x00\x01\x00\x00\x00\x01\x00\x00\ -\x00(\x01\x03\x00\x01\x00\x00\x00\x02\x00\x00\x001\x01\x02\ -\x00$\x00\x00\x00:\x01\x00\x002\x01\x02\x00\x14\x00\x00\ -\x00^\x01\x00\x00=\x01\x03\x00\x01\x00\x00\x00\x02\x00\x00\ -\x00R\x01\x03\x00\x01\x00\x00\x00\x01\x00\x00\x00\xbc\x02\x01\ -\x00\xfa8\x00\x00r\x01\x00\x00I\x86\x01\x00\x90\x0c\x00\ -\x00l:\x00\x00i\x87\x04\x00\x01\x00\x00\x00@_\x00\ -\x00s\x87\x07\x00H\x0c\x00\x00\xfcF\x00\x00\x00\x00\x00\ -\x00\x08\x00\x08\x00\x08\x00\x08\x00\x00\xf9\x15\x00\x10'\x00\ -\x00\x00\xf9\x15\x00\x10'\x00\x00Adobe P\ -hotoshop CC 2015\ -.5 (Windows)\x00201\ -7:03:08 11:37:45\ -\x00\x0a\x0a \x0a \ -\x0a pain\ -t.net 4.0.9\x0a \ - 2017-03-0\ -7T11:32:29-08:00\ -\x0a 2017-\ -03-08T11:37:45-0\ -8:00\x0a <\ -xmp:MetadataDate\ ->2017-03-08T11:3\ -7:45-08:00\x0a \ - image/tiff\x0a \ - 3\x0a \ - sR\ -GB IEC61966-2.1<\ -/photoshop:ICCPr\ -ofile>\x0a \ -\x0a \ - \x0a \ - adobe\ -:docid:photoshop\ -:94a27cdb-0433-1\ -1e7-b02d-9f84d9f\ -5a326\x0a \ - \x0a <\ -/photoshop:Docum\ -entAncestors>\x0a \ - xmp.iid\ -:16fdf09c-857d-9\ -44e-9783-e127cb1\ -b9cf4\x0a \ - adobe:docid:\ -photoshop:9f9351\ -ac-0436-11e7-b02\ -d-9f84d9f5a326\x0a xmp.did:ca7\ -71a70-f965-e14f-\ -9103-360465543db\ -f\x0a \ - \x0a \ - \x0a \ - \x0a \ - <\ -stEvt:action>cre\ -ated\x0a \ - xmp.iid:\ -ca771a70-f965-e1\ -4f-9103-36046554\ -3dbf\x0a \ - 2017-03-07\ -T11:32:29-08:00<\ -/stEvt:when>\x0a \ - <\ -stEvt:softwareAg\ -ent>Adobe Photos\ -hop CC 2015.5 (W\ -indows)\x0a \ - \x0a \ - \x0a \ - saved\x0a \ - <\ -stEvt:instanceID\ ->xmp.iid:16fdf09\ -c-857d-944e-9783\ --e127cb1b9cf4\ -\x0a \ - 2\ -017-03-08T11:37:\ -45-08:00\x0a \ - Ado\ -be Photoshop CC \ -2015.5 (Windows)\ -\x0a \ - /\x0a \ - \x0a <\ -/rdf:Seq>\x0a \ - \x0a \x0a \ -\x0a\x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ -\x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a\ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ -\x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a\ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ -\x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a\ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ -\x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a\ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ -\x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a\ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ -\x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a\ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ -\x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a\ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ -\x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \x0a8BIM\x04\ -%\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x008BIM\x04:\x00\x00\x00\ -\x00\x00\xe5\x00\x00\x00\x10\x00\x00\x00\x01\x00\x00\x00\x00\x00\ -\x0bprintOutput\x00\x00\x00\x05\ -\x00\x00\x00\x00PstSbool\x01\x00\x00\x00\ -\x00Inteenum\x00\x00\x00\x00Int\ -e\x00\x00\x00\x00Clrm\x00\x00\x00\x0fpri\ -ntSixteenBitbool\ -\x00\x00\x00\x00\x0bprinterName\ -TEXT\x00\x00\x00\x01\x00\x00\x00\x00\x00\x0fpr\ -intProofSetupObj\ -c\x00\x00\x00\x0c\x00P\x00r\x00o\x00o\x00f\x00\ - \x00S\x00e\x00t\x00u\x00p\x00\x00\x00\x00\x00\ -\x0aproofSetup\x00\x00\x00\x01\x00\ -\x00\x00\x00Bltnenum\x00\x00\x00\x0cb\ -uiltinProof\x00\x00\x00\x09p\ -roofCMYK\x008BIM\x04;\x00\ -\x00\x00\x00\x02-\x00\x00\x00\x10\x00\x00\x00\x01\x00\x00\x00\ -\x00\x00\x12printOutputOp\ -tions\x00\x00\x00\x17\x00\x00\x00\x00Cpt\ -nbool\x00\x00\x00\x00\x00Clbrbo\ -ol\x00\x00\x00\x00\x00RgsMbool\x00\ -\x00\x00\x00\x00CrnCbool\x00\x00\x00\x00\ -\x00CntCbool\x00\x00\x00\x00\x00Lb\ -lsbool\x00\x00\x00\x00\x00Ngtvb\ -ool\x00\x00\x00\x00\x00EmlDbool\ -\x00\x00\x00\x00\x00Intrbool\x00\x00\x00\ -\x00\x00BckgObjc\x00\x00\x00\x01\x00\x00\ -\x00\x00\x00\x00RGBC\x00\x00\x00\x03\x00\x00\x00\x00\ -Rd doub@o\xe0\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00Grn doub@o\xe0\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00Bl doub\ -@o\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00BrdT\ -UntF#Rlt\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00Bld UntF#Rlt\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00Rslt\ -UntF#Pxl@b\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x0avectorDatabo\ -ol\x01\x00\x00\x00\x00PgPsenum\x00\ -\x00\x00\x00PgPs\x00\x00\x00\x00PgPC\x00\ -\x00\x00\x00LeftUntF#Rlt\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00Top U\ -ntF#Rlt\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00Scl UntF#Prc@\ -Y\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10cropW\ -henPrintingbool\x00\ -\x00\x00\x00\x0ecropRectBott\ -omlong\x00\x00\x00\x00\x00\x00\x00\x0ccr\ -opRectLeftlong\x00\x00\ -\x00\x00\x00\x00\x00\x0dcropRectRi\ -ghtlong\x00\x00\x00\x00\x00\x00\x00\x0bc\ -ropRectToplong\x00\x00\ -\x00\x00\x008BIM\x03\xed\x00\x00\x00\x00\x00\x10\x00\ -\x90\x00\x00\x00\x01\x00\x01\x00\x90\x00\x00\x00\x01\x00\x018\ -BIM\x04&\x00\x00\x00\x00\x00\x0e\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00?\x80\x00\x008BIM\x03\xee\x00\ -\x00\x00\x00\x00\x0d\x0cTransparen\ -cy\x008BIM\x04\x15\x00\x00\x00\x00\x00\x1e\x00\ -\x00\x00\x0d\x00T\x00r\x00a\x00n\x00s\x00p\x00\ -a\x00r\x00e\x00n\x00c\x00y\x00\x008BI\ -M\x045\x00\x00\x00\x00\x00\x11\x00\x00\x00\x01\x00\x00\xff\ -\xff\x00\x00\x00\x00\x00\x00\x00d\x01\x008BIM\x04\ -\x1d\x00\x00\x00\x00\x00\x04\x00\x00\x00\x008BIM\x04\ -\x0d\x00\x00\x00\x00\x00\x04\x00\x00\x00\x1e8BIM\x04\ -\x19\x00\x00\x00\x00\x00\x04\x00\x00\x00\x1e8BIM\x03\ -\xf3\x00\x00\x00\x00\x00\x09\x00\x00\x00\x00\x00\x00\x00\x00\x01\ -\x008BIM'\x10\x00\x00\x00\x00\x00\x0a\x00\x01\x00\ -\x00\x00\x00\x00\x00\x00\x018BIM\x03\xf5\x00\x00\x00\ -\x00\x00H\x00/ff\x00\x01\x00lff\x00\x06\x00\ -\x00\x00\x00\x00\x01\x00/ff\x00\x01\x00\xa1\x99\x9a\x00\ -\x06\x00\x00\x00\x00\x00\x01\x002\x00\x00\x00\x01\x00Z\x00\ -\x00\x00\x06\x00\x00\x00\x00\x00\x01\x005\x00\x00\x00\x01\x00\ --\x00\x00\x00\x06\x00\x00\x00\x00\x00\x018BIM\x03\ -\xf8\x00\x00\x00\x00\x00p\x00\x00\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x03\ -\xe8\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x03\xe8\x00\x00\x00\ -\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\x03\xe8\x00\x00\x00\x00\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\x03\xe8\x00\x008BIM\x04\x00\x00\x00\x00\ -\x00\x00\x02\x00\x008BIM\x04\x02\x00\x00\x00\x00\x00\ -\x02\x00\x008BIM\x040\x00\x00\x00\x00\x00\x01\x01\ -\x008BIM\x04-\x00\x00\x00\x00\x00\x06\x00\x01\x00\ -\x00\x00\x0a8BIM\x04\x08\x00\x00\x00\x00\x00\x10\x00\ -\x00\x00\x01\x00\x00\x02@\x00\x00\x02@\x00\x00\x00\x008\ -BIM\x04\x1e\x00\x00\x00\x00\x00\x04\x00\x00\x00\x008\ -BIM\x04\x1a\x00\x00\x00\x00\x035\x00\x00\x00\x06\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00`\x00\x00\x00`\x00\ -\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00`\x00\x00\x00`\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\ -\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00null\x00\x00\ -\x00\x02\x00\x00\x00\x06boundsObjc\ -\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00Rct1\x00\x00\ -\x00\x04\x00\x00\x00\x00Top long\x00\x00\ -\x00\x00\x00\x00\x00\x00Leftlong\x00\x00\ -\x00\x00\x00\x00\x00\x00Btomlong\x00\x00\ -\x00`\x00\x00\x00\x00Rghtlong\x00\x00\ -\x00`\x00\x00\x00\x06slicesVlLs\ -\x00\x00\x00\x01Objc\x00\x00\x00\x01\x00\x00\x00\x00\ -\x00\x05slice\x00\x00\x00\x12\x00\x00\x00\x07s\ -liceIDlong\x00\x00\x00\x00\x00\x00\ -\x00\x07groupIDlong\x00\x00\x00\ -\x00\x00\x00\x00\x06originenum\x00\ -\x00\x00\x0cESliceOrigin\x00\ -\x00\x00\x0dautoGenerated\ -\x00\x00\x00\x00Typeenum\x00\x00\x00\x0a\ -ESliceType\x00\x00\x00\x00Im\ -g \x00\x00\x00\x06boundsObjc\ -\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00Rct1\x00\x00\ -\x00\x04\x00\x00\x00\x00Top long\x00\x00\ -\x00\x00\x00\x00\x00\x00Leftlong\x00\x00\ -\x00\x00\x00\x00\x00\x00Btomlong\x00\x00\ -\x00`\x00\x00\x00\x00Rghtlong\x00\x00\ -\x00`\x00\x00\x00\x03urlTEXT\x00\x00\x00\ -\x01\x00\x00\x00\x00\x00\x00nullTEXT\x00\ -\x00\x00\x01\x00\x00\x00\x00\x00\x00MsgeTEX\ -T\x00\x00\x00\x01\x00\x00\x00\x00\x00\x06altTa\ -gTEXT\x00\x00\x00\x01\x00\x00\x00\x00\x00\x0ec\ -ellTextIsHTMLboo\ -l\x01\x00\x00\x00\x08cellTextTE\ -XT\x00\x00\x00\x01\x00\x00\x00\x00\x00\x09horz\ -Alignenum\x00\x00\x00\x0fESl\ -iceHorzAlign\x00\x00\x00\x07\ -default\x00\x00\x00\x09vertA\ -lignenum\x00\x00\x00\x0fESli\ -ceVertAlign\x00\x00\x00\x07d\ -efault\x00\x00\x00\x0bbgColo\ -rTypeenum\x00\x00\x00\x11ESl\ -iceBGColorType\x00\x00\ -\x00\x00None\x00\x00\x00\x09topOut\ -setlong\x00\x00\x00\x00\x00\x00\x00\x0al\ -eftOutsetlong\x00\x00\x00\ -\x00\x00\x00\x00\x0cbottomOutse\ -tlong\x00\x00\x00\x00\x00\x00\x00\x0brig\ -htOutsetlong\x00\x00\x00\x00\ -\x008BIM\x04(\x00\x00\x00\x00\x00\x0c\x00\x00\x00\ -\x02?\xf0\x00\x00\x00\x00\x00\x008BIM\x04\x14\x00\ -\x00\x00\x00\x00\x04\x00\x00\x00\x0c8BIM\x04\x0c\x00\ -\x00\x00\x00\x038\x00\x00\x00\x01\x00\x00\x000\x00\x00\x00\ -0\x00\x00\x00\x90\x00\x00\x1b\x00\x00\x00\x03\x1c\x00\x18\x00\ -\x01\xff\xd8\xff\xed\x00\x0cAdobe_CM\x00\ -\x01\xff\xee\x00\x0eAdobe\x00d\x80\x00\x00\x00\ -\x01\xff\xdb\x00\x84\x00\x0c\x08\x08\x08\x09\x08\x0c\x09\x09\x0c\ -\x11\x0b\x0a\x0b\x11\x15\x0f\x0c\x0c\x0f\x15\x18\x13\x13\x15\x13\ -\x13\x18\x11\x0c\x0c\x0c\x0c\x0c\x0c\x11\x0c\x0c\x0c\x0c\x0c\x0c\ -\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\ -\x0c\x0c\x0c\x0c\x0c\x0c\x01\x0d\x0b\x0b\x0d\x0e\x0d\x10\x0e\x0e\ -\x10\x14\x0e\x0e\x0e\x14\x14\x0e\x0e\x0e\x0e\x14\x11\x0c\x0c\x0c\ -\x0c\x0c\x11\x11\x0c\x0c\x0c\x0c\x0c\x0c\x11\x0c\x0c\x0c\x0c\x0c\ -\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\ -\x0c\x0c\x0c\x0c\x0c\x0c\x0c\xff\xc0\x00\x11\x08\x000\x000\ -\x03\x01\x22\x00\x02\x11\x01\x03\x11\x01\xff\xdd\x00\x04\x00\x03\ -\xff\xc4\x01?\x00\x00\x01\x05\x01\x01\x01\x01\x01\x01\x00\x00\ -\x00\x00\x00\x00\x00\x03\x00\x01\x02\x04\x05\x06\x07\x08\x09\x0a\ -\x0b\x01\x00\x01\x05\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\ -\x00\x00\x01\x00\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x10\x00\ -\x01\x04\x01\x03\x02\x04\x02\x05\x07\x06\x08\x05\x03\x0c3\x01\ -\x00\x02\x11\x03\x04!\x121\x05AQa\x13\x22q\x81\ -2\x06\x14\x91\xa1\xb1B#$\x15R\xc1b34r\ -\x82\xd1C\x07%\x92S\xf0\xe1\xf1cs5\x16\xa2\xb2\ -\x83&D\x93TdE\xc2\xa3t6\x17\xd2U\xe2e\ -\xf2\xb3\x84\xc3\xd3u\xe3\xf3F'\x94\xa4\x85\xb4\x95\xc4\ -\xd4\xe4\xf4\xa5\xb5\xc5\xd5\xe5\xf5Vfv\x86\x96\xa6\xb6\ -\xc6\xd6\xe6\xf67GWgw\x87\x97\xa7\xb7\xc7\xd7\xe7\ -\xf7\x11\x00\x02\x02\x01\x02\x04\x04\x03\x04\x05\x06\x07\x07\x06\ -\x055\x01\x00\x02\x11\x03!1\x12\x04AQaq\x22\ -\x13\x052\x81\x91\x14\xa1\xb1B#\xc1R\xd1\xf03$\ -b\xe1r\x82\x92CS\x15cs4\xf1%\x06\x16\xa2\ -\xb2\x83\x07&5\xc2\xd2D\x93T\xa3\x17dEU6\ -te\xe2\xf2\xb3\x84\xc3\xd3u\xe3\xf3F\x94\xa4\x85\xb4\ -\x95\xc4\xd4\xe4\xf4\xa5\xb5\xc5\xd5\xe5\xf5Vfv\x86\x96\ -\xa6\xb6\xc6\xd6\xe6\xf6'7GWgw\x87\x97\xa7\xb7\ -\xc7\xff\xda\x00\x0c\x03\x01\x00\x02\x11\x03\x11\x00?\x00\xf5\ -T\x92P\xb5\xceensZ^\xe6\x82CG$\xa4\ -\xa5YuU\xff\x008\xf6\xb2x\xdc@N\xd7\xb1\xe3\ -s\x1c\x1c\xdf\x10d*X\xb8,\xb1\x9e\xbe[K\xee\ -\xb3S\xbb\xb0\xec6\xa6}#\x07&\xa7\xd2H\xaa\xe7\ -\x06=\x93\x22O\x05%:\x09$\x92J\x7f\xff\xd0\xf5\ -T\x1c\x9c\xaa\xf1\x9a\x0b\xe4\x97\x18kZ$\x94eK\ -\xaa{YM\xbd\xeb\xb0\x1f\x97\xfa\x84\x94\xb7\xdb\xefw\ -\xf3x\xaf>\x05\xda\x7f\x04+\x9b\xd4.s.}m\ -`\xa6\x5c\xd6\x93:\xf3:|\x15\xac\xf3x\xc6s\xa9\ -0F\xae#\x9d\xa3\xe9mK\x05\xd6Y\x88\xd7Zw\ -\x17L\x1e\xf1:nIL\xf1/7\xe3\xb2\xd2\x00.\ -\xe4\x0e$\x1d\xa8\xca\x97J\xd3\x1d\xf5\x9ekyj\xba\ -\x92\x9f\xff\xd1\xf5UW\xa8\xd6l\xc3\xb0\x01$A\x00\ -y\x1f\xfc\x8a\xb4\x92Jh7\xa95\xf5\x86\xb6\x8b-\ -1\x0e\x86\xe8t\xd7\xc5&_\x9b\xb42\x8cA[\x06\ -\x808\xc0\x1f/b\xbe\x92Jj`\xe3\xddQ\xb5\xf7\ -@u\xae\xdd\xb5\xbc\x05m$\x92S\xff\xd98BI\ -M\x04!\x00\x00\x00\x00\x00a\x00\x00\x00\x01\x01\x00\x00\ -\x00\x0f\x00A\x00d\x00o\x00b\x00e\x00 \x00P\ -\x00h\x00o\x00t\x00o\x00s\x00h\x00o\x00p\ -\x00\x00\x00\x19\x00A\x00d\x00o\x00b\x00e\x00 \ -\x00P\x00h\x00o\x00t\x00o\x00s\x00h\x00o\ -\x00p\x00 \x00C\x00C\x00 \x002\x000\x001\ -\x005\x00.\x005\x00\x00\x00\x01\x00\x00\x00\x0cHL\ -ino\x02\x10\x00\x00mntrRGB X\ -YZ \x07\xce\x00\x02\x00\x09\x00\x06\x001\x00\x00a\ -cspMSFT\x00\x00\x00\x00IEC s\ -RGB\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\xf6\xd6\x00\x01\x00\x00\x00\x00\xd3-HP \x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11c\ -prt\x00\x00\x01P\x00\x00\x003desc\x00\ -\x00\x01\x84\x00\x00\x00lwtpt\x00\x00\x01\xf0\x00\ -\x00\x00\x14bkpt\x00\x00\x02\x04\x00\x00\x00\x14r\ -XYZ\x00\x00\x02\x18\x00\x00\x00\x14gXYZ\x00\ -\x00\x02,\x00\x00\x00\x14bXYZ\x00\x00\x02@\x00\ -\x00\x00\x14dmnd\x00\x00\x02T\x00\x00\x00pd\ -mdd\x00\x00\x02\xc4\x00\x00\x00\x88vued\x00\ -\x00\x03L\x00\x00\x00\x86view\x00\x00\x03\xd4\x00\ -\x00\x00$lumi\x00\x00\x03\xf8\x00\x00\x00\x14m\ -eas\x00\x00\x04\x0c\x00\x00\x00$tech\x00\ -\x00\x040\x00\x00\x00\x0crTRC\x00\x00\x04<\x00\ -\x00\x08\x0cgTRC\x00\x00\x04<\x00\x00\x08\x0cb\ -TRC\x00\x00\x04<\x00\x00\x08\x0ctext\x00\ -\x00\x00\x00Copyright (c)\ - 1998 Hewlett-Pa\ -ckard Company\x00\x00d\ -esc\x00\x00\x00\x00\x00\x00\x00\x12sRGB \ -IEC61966-2.1\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x12sRGB IEC\ -61966-2.1\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00XYZ \x00\ -\x00\x00\x00\x00\x00\xf3Q\x00\x01\x00\x00\x00\x01\x16\xccX\ -YZ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00XYZ \x00\x00\x00\x00\x00\x00o\xa2\x00\ -\x008\xf5\x00\x00\x03\x90XYZ \x00\x00\x00\x00\x00\ -\x00b\x99\x00\x00\xb7\x85\x00\x00\x18\xdaXYZ \x00\ -\x00\x00\x00\x00\x00$\xa0\x00\x00\x0f\x84\x00\x00\xb6\xcfd\ -esc\x00\x00\x00\x00\x00\x00\x00\x16IEC h\ -ttp://www.iec.ch\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x16IEC \ -http://www.iec.c\ -h\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\ -esc\x00\x00\x00\x00\x00\x00\x00.IEC 6\ -1966-2.1 Default\ - RGB colour spac\ -e - sRGB\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00.IEC 61966-2.\ -1 Default RGB co\ -lour space - sRG\ -B\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00desc\x00\x00\x00\x00\x00\ -\x00\x00,Reference Vie\ -wing Condition i\ -n IEC61966-2.1\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00,Refere\ -nce Viewing Cond\ -ition in IEC6196\ -6-2.1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00v\ -iew\x00\x00\x00\x00\x00\x13\xa4\xfe\x00\x14_.\x00\ -\x10\xcf\x14\x00\x03\xed\xcc\x00\x04\x13\x0b\x00\x03\x5c\x9e\x00\ -\x00\x00\x01XYZ \x00\x00\x00\x00\x00L\x09V\x00\ -P\x00\x00\x00W\x1f\xe7meas\x00\x00\x00\x00\x00\ -\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x02\x8f\x00\x00\x00\x02sig \x00\ -\x00\x00\x00CRT curv\x00\x00\x00\x00\x00\ -\x00\x04\x00\x00\x00\x00\x05\x00\x0a\x00\x0f\x00\x14\x00\x19\x00\ -\x1e\x00#\x00(\x00-\x002\x007\x00;\x00@\x00\ -E\x00J\x00O\x00T\x00Y\x00^\x00c\x00h\x00\ -m\x00r\x00w\x00|\x00\x81\x00\x86\x00\x8b\x00\x90\x00\ -\x95\x00\x9a\x00\x9f\x00\xa4\x00\xa9\x00\xae\x00\xb2\x00\xb7\x00\ -\xbc\x00\xc1\x00\xc6\x00\xcb\x00\xd0\x00\xd5\x00\xdb\x00\xe0\x00\ -\xe5\x00\xeb\x00\xf0\x00\xf6\x00\xfb\x01\x01\x01\x07\x01\x0d\x01\ -\x13\x01\x19\x01\x1f\x01%\x01+\x012\x018\x01>\x01\ -E\x01L\x01R\x01Y\x01`\x01g\x01n\x01u\x01\ -|\x01\x83\x01\x8b\x01\x92\x01\x9a\x01\xa1\x01\xa9\x01\xb1\x01\ -\xb9\x01\xc1\x01\xc9\x01\xd1\x01\xd9\x01\xe1\x01\xe9\x01\xf2\x01\ -\xfa\x02\x03\x02\x0c\x02\x14\x02\x1d\x02&\x02/\x028\x02\ -A\x02K\x02T\x02]\x02g\x02q\x02z\x02\x84\x02\ -\x8e\x02\x98\x02\xa2\x02\xac\x02\xb6\x02\xc1\x02\xcb\x02\xd5\x02\ -\xe0\x02\xeb\x02\xf5\x03\x00\x03\x0b\x03\x16\x03!\x03-\x03\ -8\x03C\x03O\x03Z\x03f\x03r\x03~\x03\x8a\x03\ -\x96\x03\xa2\x03\xae\x03\xba\x03\xc7\x03\xd3\x03\xe0\x03\xec\x03\ -\xf9\x04\x06\x04\x13\x04 \x04-\x04;\x04H\x04U\x04\ -c\x04q\x04~\x04\x8c\x04\x9a\x04\xa8\x04\xb6\x04\xc4\x04\ -\xd3\x04\xe1\x04\xf0\x04\xfe\x05\x0d\x05\x1c\x05+\x05:\x05\ -I\x05X\x05g\x05w\x05\x86\x05\x96\x05\xa6\x05\xb5\x05\ -\xc5\x05\xd5\x05\xe5\x05\xf6\x06\x06\x06\x16\x06'\x067\x06\ -H\x06Y\x06j\x06{\x06\x8c\x06\x9d\x06\xaf\x06\xc0\x06\ -\xd1\x06\xe3\x06\xf5\x07\x07\x07\x19\x07+\x07=\x07O\x07\ -a\x07t\x07\x86\x07\x99\x07\xac\x07\xbf\x07\xd2\x07\xe5\x07\ -\xf8\x08\x0b\x08\x1f\x082\x08F\x08Z\x08n\x08\x82\x08\ -\x96\x08\xaa\x08\xbe\x08\xd2\x08\xe7\x08\xfb\x09\x10\x09%\x09\ -:\x09O\x09d\x09y\x09\x8f\x09\xa4\x09\xba\x09\xcf\x09\ -\xe5\x09\xfb\x0a\x11\x0a'\x0a=\x0aT\x0aj\x0a\x81\x0a\ -\x98\x0a\xae\x0a\xc5\x0a\xdc\x0a\xf3\x0b\x0b\x0b\x22\x0b9\x0b\ -Q\x0bi\x0b\x80\x0b\x98\x0b\xb0\x0b\xc8\x0b\xe1\x0b\xf9\x0c\ -\x12\x0c*\x0cC\x0c\x5c\x0cu\x0c\x8e\x0c\xa7\x0c\xc0\x0c\ -\xd9\x0c\xf3\x0d\x0d\x0d&\x0d@\x0dZ\x0dt\x0d\x8e\x0d\ -\xa9\x0d\xc3\x0d\xde\x0d\xf8\x0e\x13\x0e.\x0eI\x0ed\x0e\ -\x7f\x0e\x9b\x0e\xb6\x0e\xd2\x0e\xee\x0f\x09\x0f%\x0fA\x0f\ -^\x0fz\x0f\x96\x0f\xb3\x0f\xcf\x0f\xec\x10\x09\x10&\x10\ -C\x10a\x10~\x10\x9b\x10\xb9\x10\xd7\x10\xf5\x11\x13\x11\ -1\x11O\x11m\x11\x8c\x11\xaa\x11\xc9\x11\xe8\x12\x07\x12\ -&\x12E\x12d\x12\x84\x12\xa3\x12\xc3\x12\xe3\x13\x03\x13\ -#\x13C\x13c\x13\x83\x13\xa4\x13\xc5\x13\xe5\x14\x06\x14\ -'\x14I\x14j\x14\x8b\x14\xad\x14\xce\x14\xf0\x15\x12\x15\ -4\x15V\x15x\x15\x9b\x15\xbd\x15\xe0\x16\x03\x16&\x16\ -I\x16l\x16\x8f\x16\xb2\x16\xd6\x16\xfa\x17\x1d\x17A\x17\ -e\x17\x89\x17\xae\x17\xd2\x17\xf7\x18\x1b\x18@\x18e\x18\ -\x8a\x18\xaf\x18\xd5\x18\xfa\x19 \x19E\x19k\x19\x91\x19\ -\xb7\x19\xdd\x1a\x04\x1a*\x1aQ\x1aw\x1a\x9e\x1a\xc5\x1a\ -\xec\x1b\x14\x1b;\x1bc\x1b\x8a\x1b\xb2\x1b\xda\x1c\x02\x1c\ -*\x1cR\x1c{\x1c\xa3\x1c\xcc\x1c\xf5\x1d\x1e\x1dG\x1d\ -p\x1d\x99\x1d\xc3\x1d\xec\x1e\x16\x1e@\x1ej\x1e\x94\x1e\ -\xbe\x1e\xe9\x1f\x13\x1f>\x1fi\x1f\x94\x1f\xbf\x1f\xea \ -\x15 A l \x98 \xc4 \xf0!\x1c!H!\ -u!\xa1!\xce!\xfb\x22'\x22U\x22\x82\x22\xaf\x22\ -\xdd#\x0a#8#f#\x94#\xc2#\xf0$\x1f$\ -M$|$\xab$\xda%\x09%8%h%\x97%\ -\xc7%\xf7&'&W&\x87&\xb7&\xe8'\x18'\ -I'z'\xab'\xdc(\x0d(?(q(\xa2(\ -\xd4)\x06)8)k)\x9d)\xd0*\x02*5*\ -h*\x9b*\xcf+\x02+6+i+\x9d+\xd1,\ -\x05,9,n,\xa2,\xd7-\x0c-A-v-\ -\xab-\xe1.\x16.L.\x82.\xb7.\xee/$/\ -Z/\x91/\xc7/\xfe050l0\xa40\xdb1\ -\x121J1\x821\xba1\xf22*2c2\x9b2\ -\xd43\x0d3F3\x7f3\xb83\xf14+4e4\ -\x9e4\xd85\x135M5\x875\xc25\xfd676\ -r6\xae6\xe97$7`7\x9c7\xd78\x148\ -P8\x8c8\xc89\x059B9\x7f9\xbc9\xf9:\ -6:t:\xb2:\xef;-;k;\xaa;\xe8<\ -'\ - >`>\xa0>\xe0?!?a?\xa2?\xe2@\ -#@d@\xa6@\xe7A)AjA\xacA\xeeB\ -0BrB\xb5B\xf7C:C}C\xc0D\x03D\ -GD\x8aD\xceE\x12EUE\x9aE\xdeF\x22F\ -gF\xabF\xf0G5G{G\xc0H\x05HKH\ -\x91H\xd7I\x1dIcI\xa9I\xf0J7J}J\ -\xc4K\x0cKSK\x9aK\xe2L*LrL\xbaM\ -\x02MJM\x93M\xdcN%NnN\xb7O\x00O\ -IO\x93O\xddP'PqP\xbbQ\x06QPQ\ -\x9bQ\xe6R1R|R\xc7S\x13S_S\xaaS\ -\xf6TBT\x8fT\xdbU(UuU\xc2V\x0fV\ -\x5cV\xa9V\xf7WDW\x92W\xe0X/X}X\ -\xcbY\x1aYiY\xb8Z\x07ZVZ\xa6Z\xf5[\ -E[\x95[\xe5\x5c5\x5c\x86\x5c\xd6]']x]\ -\xc9^\x1a^l^\xbd_\x0f_a_\xb3`\x05`\ -W`\xaa`\xfcaOa\xa2a\xf5bIb\x9cb\ -\xf0cCc\x97c\xebd@d\x94d\xe9e=e\ -\x92e\xe7f=f\x92f\xe8g=g\x93g\xe9h\ -?h\x96h\xeciCi\x9ai\xf1jHj\x9fj\ -\xf7kOk\xa7k\xfflWl\xafm\x08m`m\ -\xb9n\x12nkn\xc4o\x1eoxo\xd1p+p\ -\x86p\xe0q:q\x95q\xf0rKr\xa6s\x01s\ -]s\xb8t\x14tpt\xccu(u\x85u\xe1v\ ->v\x9bv\xf8wVw\xb3x\x11xnx\xccy\ -*y\x89y\xe7zFz\xa5{\x04{c{\xc2|\ -!|\x81|\xe1}A}\xa1~\x01~b~\xc2\x7f\ -#\x7f\x84\x7f\xe5\x80G\x80\xa8\x81\x0a\x81k\x81\xcd\x82\ -0\x82\x92\x82\xf4\x83W\x83\xba\x84\x1d\x84\x80\x84\xe3\x85\ -G\x85\xab\x86\x0e\x86r\x86\xd7\x87;\x87\x9f\x88\x04\x88\ -i\x88\xce\x893\x89\x99\x89\xfe\x8ad\x8a\xca\x8b0\x8b\ -\x96\x8b\xfc\x8cc\x8c\xca\x8d1\x8d\x98\x8d\xff\x8ef\x8e\ -\xce\x8f6\x8f\x9e\x90\x06\x90n\x90\xd6\x91?\x91\xa8\x92\ -\x11\x92z\x92\xe3\x93M\x93\xb6\x94 \x94\x8a\x94\xf4\x95\ -_\x95\xc9\x964\x96\x9f\x97\x0a\x97u\x97\xe0\x98L\x98\ -\xb8\x99$\x99\x90\x99\xfc\x9ah\x9a\xd5\x9bB\x9b\xaf\x9c\ -\x1c\x9c\x89\x9c\xf7\x9dd\x9d\xd2\x9e@\x9e\xae\x9f\x1d\x9f\ -\x8b\x9f\xfa\xa0i\xa0\xd8\xa1G\xa1\xb6\xa2&\xa2\x96\xa3\ -\x06\xa3v\xa3\xe6\xa4V\xa4\xc7\xa58\xa5\xa9\xa6\x1a\xa6\ -\x8b\xa6\xfd\xa7n\xa7\xe0\xa8R\xa8\xc4\xa97\xa9\xa9\xaa\ -\x1c\xaa\x8f\xab\x02\xabu\xab\xe9\xac\x5c\xac\xd0\xadD\xad\ -\xb8\xae-\xae\xa1\xaf\x16\xaf\x8b\xb0\x00\xb0u\xb0\xea\xb1\ -`\xb1\xd6\xb2K\xb2\xc2\xb38\xb3\xae\xb4%\xb4\x9c\xb5\ -\x13\xb5\x8a\xb6\x01\xb6y\xb6\xf0\xb7h\xb7\xe0\xb8Y\xb8\ -\xd1\xb9J\xb9\xc2\xba;\xba\xb5\xbb.\xbb\xa7\xbc!\xbc\ -\x9b\xbd\x15\xbd\x8f\xbe\x0a\xbe\x84\xbe\xff\xbfz\xbf\xf5\xc0\ -p\xc0\xec\xc1g\xc1\xe3\xc2_\xc2\xdb\xc3X\xc3\xd4\xc4\ -Q\xc4\xce\xc5K\xc5\xc8\xc6F\xc6\xc3\xc7A\xc7\xbf\xc8\ -=\xc8\xbc\xc9:\xc9\xb9\xca8\xca\xb7\xcb6\xcb\xb6\xcc\ -5\xcc\xb5\xcd5\xcd\xb5\xce6\xce\xb6\xcf7\xcf\xb8\xd0\ -9\xd0\xba\xd1<\xd1\xbe\xd2?\xd2\xc1\xd3D\xd3\xc6\xd4\ -I\xd4\xcb\xd5N\xd5\xd1\xd6U\xd6\xd8\xd7\x5c\xd7\xe0\xd8\ -d\xd8\xe8\xd9l\xd9\xf1\xdav\xda\xfb\xdb\x80\xdc\x05\xdc\ -\x8a\xdd\x10\xdd\x96\xde\x1c\xde\xa2\xdf)\xdf\xaf\xe06\xe0\ -\xbd\xe1D\xe1\xcc\xe2S\xe2\xdb\xe3c\xe3\xeb\xe4s\xe4\ -\xfc\xe5\x84\xe6\x0d\xe6\x96\xe7\x1f\xe7\xa9\xe82\xe8\xbc\xe9\ -F\xe9\xd0\xea[\xea\xe5\xebp\xeb\xfb\xec\x86\xed\x11\xed\ -\x9c\xee(\xee\xb4\xef@\xef\xcc\xf0X\xf0\xe5\xf1r\xf1\ -\xff\xf2\x8c\xf3\x19\xf3\xa7\xf44\xf4\xc2\xf5P\xf5\xde\xf6\ -m\xf6\xfb\xf7\x8a\xf8\x19\xf8\xa8\xf98\xf9\xc7\xfaW\xfa\ -\xe7\xfbw\xfc\x07\xfc\x98\xfd)\xfd\xba\xfeK\xfe\xdc\xff\ -m\xff\xff\x80\x00 P8$\x16\x0d\x07\x84BaP\ -\xb8d6\x1d\x0f\x88DbQ8\xa4V-\x17\x8cF\ -cQ\xb8\xe4v=\x1f\x90HdR9$\x96M'\ -\x94JeR\xb9d\xb6]/\x98LfS9\xa4\xd6\ -m7\x9cNgS\xb9\xe4\xf6}?\xa0PhT:\ -%\x16\x8dG\xa4RiT\xbae6\x9dO\xa8Tj\ -U:\xa5V\xadW\xacVkU\xba\xe5v\xbd_\xb0\ -XlV;%\x96\x0a\x01\xb4\x00Cv\xb1\x15\xb4D\ -+\x0c\xdcC\xe0\xeb\xa0F\xd2\x01y\xde^\x0e;\xe3\ -q\xc5\x7fm_\xdcM\xbb6\x17\x0d\x1b\x0a\xe2CD\ -\x5caX\x8f\x8f,\x88rB\xa0VT\x19\x14|\xe6\ -^\xedl\xe31\x85\x9fY.tJ\x87V\x95\xc9\x87\ -\xd4a\xc4\xda\xb1\x81g\x5co\x1elIa\x1d\xa0V\ -X\xf0\xdc;\x17\xdb\xb5r\xc7|\x9dj\xf0YZ\x9e\ -%d\xbd\xc7:\x99yG\xf0O4\x17<}t_\ -\x08\x9e\xa1\xb3|\xb1N\xf1{T\x9b\xa08$f\xf0\ -\x1f\xcb\x1e3u1_\xe7M\xa5\xfdG\xd7w\xb5\xd3\ -\xdb\xf8NA\x7f0rS\xec\xb9\x16\xfeG\x15FO\ -\xf5v6\xc0\x02A\xfd\x01\x9f\xcf\x8c\x0c\x98\x8e\xf0I\ -**\xc1\x83R0m\xc2\x06\x938k\x19fl,\ -`\x9dp\xc9\xca\xe8\x9fG\xcb\xe6\x05\x81\xabX6\x11\ -\x06q(\x80\x11\xc5\x01`A\x15\x85\x0b\xba0V\xc6\ -\x04\xc1\x15\x19\x8d\xa7\xecl~@\xf1\xcaJ-\xc7\x83\ -\x90\xe3\x1f\x91\xa8\xa3\x82j\x99D\xb4\x8c>\x19rI\ -{\x02@\xa8\xb8\x09'\x80\xa1\x94\xa4\x1f\x0cr\xa8\xf9\ -\x12\x86b\x020O\xcb\x849+/\x8fQ\xd4\xc4\x8e\ -\x84\x93(ZPM\x06@\x115\x81H\x81m7\x94\ -\x84,\xe433'\xc9\xee\x94\x00S\xc8\x04-O\x83\ -\x88\xdd?\x913\xd0\x06\x88\x1eT)\xde*Q\x01C\ -\xdaw\x1dS\x1d\x1c\x8a\x92T\x89l\x1dR\x82J \ -]S\x05H\xffM\x8b\xc7\xdd<}&\x81\xb5D!\ -\x90u)H\x09\xd5\x00\xc2 ZU\x85\x09\x01W\x8c\ -\x14}d\x86\x82\xd5\xa87\x18\x15\xa6\xcb\x9a\x04\xb9\xe8\ -[Ju\x1c\x8dp\xb2\x18\x1e6)\xda\x9e\x05\xd6H\ -tMY\x86\x04\x9e\x02\x00\xa8e<}\x9fB\xbd\xac\ -\x160L%gm\xa0\x83E\xbcA\x0c\x97\x08\xfa\x88\ -\x10\xd7(\xd0W]\x04\xca\x889]\x84|\xf8-\x0e\ -\x08\x84\xd0P\x11\x0f\xb1(<\xdb\x95\x9b\xba\x09W\x06\ -\xc3h\x08\xb6\xc8]\x16u\x0a\x18(H{a\x07\x9a\ -\x88\x03a\x80AO\x87\x9a\x00\xfe$\x13\xa1\x876,\ -p\x0a\xd8\xc8V|c\x87\xb5\xf31c\x81\xbbH \x86\x19\xfbi\x863\xee\ -\x02\x04\x98\xa8\x14[\xa9\x96\x15o\x01\xa2\x19R\x90c\ -#\xae\xec\xec.\xd2\xef\xa2\x03[\xc0T\x1a\xdd\xe3\x84\ -\xa4\x19\x07\xe8$\xfe7\x09F7$[\xaa\x84o,\ -X\x07\xfc\xc8\x9e\x86\x11|\xe8\xdcT\xf4\x04\x9f\x03|\ -\xd4A\xb0\x87\xd2\x88\x96a4@C\x87\xca\xa9H\x92\ -T\x9d+\xces\xdd\x01S\xd1t}\xca\xb0\x03\xf7\x80\ -N\x1eS\x9a \xf7\x84\x12\xa1\x84\x17\x8c1\x96^I\ -=\xddy\x8a\xab\xf2\x16\x87\x04\xf7\xa4cE\xc8X\xeb\ -\xeb\x8aE\xff\xb4W\xf9\xbe\xea\xa2>|\x04\xde\x0a(\ -\x0c\x99\xa4\x06~\xb8\xe2\xf0ll}\x86w\xbd\xf7\xa9\ -+pTR~\x86v\x18\x03\x00\xe8a\xbd\xfd\x9a\xd1\ -\xe0\xb6\x0cV\x9a\xa0~\x10\x0du\xae\xc1\x1c\xbb\xc3\x89\ -\x10uB\x05\xd5\x08\x08\x09\x03\xca\x0b\xf7\x00\xedTV\ -\x0d\x805\x05\xc1\x01\x0cC#\xacs\x05\xd8<\x0d\x07\ -d!\x1c\xf0B\x12\x13\xd0k\x09\xc2\x12F\x12\xc2\xf1\ -\xea\x90\xa2\xf2<\xc7\x80\xe1\x86Ce=\x00!\xd1\x0d\ -\xc7\x18\xc1\x87B\xc4Z\xc3\xd1E\x09b\x01\x152\xa0\ -(\x06/\xf0,\x88\x81\x08\x1c\x89@\x90\x0cD\xd0:\ -\xaa\x00\x98\x18\x061L\x1f< <\xf1\x09\x18\xc8\x8b\ -B\xe8FE\xd0\xde8#\x00\xd8\x88.\xea!\x80\xd5\ -k\x11\xe0\xb8\x1a\x04\x11X\x13\x19 B\x0a@\xecq\ -\x04\x91(\x0e\x028\x8c\xae\xd5\xe9:B\x03li\x06\ -\x18\xfc\x0eX\xe0\xf8c\xd1\x8c\xad\xc3Uv\xcf\x99\xf8\ -\x17\x91@u\xa9\x01 -#@\xb4P\x03\x12(\x0b\ -\x81\xd6$\x07\xc1<\x94\x03\xa0RN\x01\x98$V\x1e\ -\xb8u{/nB\x14u\x9e\x01\x5c04\x8e\x80\x91\ -\x14\x020W%\xc1:\x22\x04@>Z\x01$\xd6\x02\ -\x00[XQ\xc2\xce^\x0a\x01\x03/\xc3\x0c\xa5'\xcd\ -\xa4\x06\x81\x04\x18\x15CXD\x99AT\xd5\x82`^\ -\x8eG\xe4\xd1\x1fr\x04{\x1b\x81\xe0;\x1a\xc2\xfb!\ -\x83:n\x0c#\xc0\x19\x9cl\xc2'\x11\xc4\x0e\x82G\ -,#E\x81n\x05e\x81\x1b\x0f\xd1\xf8\xc0\xe1\xb8\xe8\ -\x1cQ\x80p\x0d\x83\x046\xa1\x90\xe1\x1b0ls\x0f\ -I\xfc\x1b\xf0\xb8\x1a\ -\xe2hK\x00\x80\x130\xc4\xe2\x02\x1e\xebn\xb3\x09\x02\ -2\x13\xb0\xd4\x18\x80_\x0d\xa0v!\x87\xd8\x1b\x01\x9c\ -\xe3\xa0h\xe0%\x1c\xb9\xcb\x98\xfe\x82\x16<\xe1^\x13\ -d\xe4\x10\xa0\xcd\x0d\x021\x01\xa0\xfa\x13\x80\x9f\x10\xed\ -v!l\x06\xd8\xcb<[e\xfa\x96\x02\x18\xc8\x81\x94\ -\x17\x8c\x82\x0dP\x01\x10B-\x06.A\x06\x8f\xd2i\ -/D\x06l\xc2\x1b,\xc6;h$\xe5@ \x02\xa8\ -\x90\x0f1T\x12\xe9\xd4!\x91B\x19\xeb\xc5\x13\x02,\ -\xe8\xce\x90\xb2.\x94!\xea\xc8\x0a\x86P\x15\xa2\xa0\x86\ -\xa9\x10\x02\x0c\x92\x9b\x22\xe8\x02Np\x8d\x8f\x10\xb9\xc7\ -\x08C\xe0\x1cHC\x84\xfdj=\x16B(\x8d\xc0R\ -\xfe!\xa4\x00q\xac\x00\x82\x18\x85@\xf6zA<\xbb\ -\xc2nPH\xa0\x92\x89*\xb5\xa9\xd4\xb5\xaf\x10\x93\x80\ -(\x03$>\x01\xa7x\x00\xe0\x12&\x01G\x1e!\x18\ -\x121\xe8\xa7\x91\xa0\x22oh\xe5\xa1\xb2\xc9\x82\x18v\ -\xc1&\xca\xe3\xca#e\x04\x96\xe0\x14\xc9\x22\xe2\x03 \ ->\x8d\x89.\x8d\xa3&\xb9\xc94\xc9\x22\x90\xa0\x8b\xc4\ -b\xc1\xcc\x1b\xf1\xee\x22b\xef\x1b\x81\x8cy\xe3\xf6!\ -aq#\xe1L|\x00\xf8\x0bb\x08\xc9\x91\xd1!\x06\ -$\x04\xcf\x10\xe7\x09e\x19F\xb1\x17\xed^+\x8a\xb8\ -\xcb\xec\xee\x1aa\x91\x22\xe24\x10\x92t\x14\xa0\x91'\ -\xa0\xb4!\x8d\x91&\xa1\x8e\x8d\x92\x0e\x03\xe9\x88\x02.\ -\x148\xb0\xae\x1e\xa1\xe4B\xc1\x9a\x18\x011* \xfe\ -g!\xb4grp#\x80\xc1+ \xf0\xf0\xa0\xd8\x10\ -\xe4r\xae\xe9\xe0\x86\xe3\x04\x1cC\x02/\xe1\xb6\xa9\x81\ -\xda\xb3\xcc\x06\xc7J\x9e\x1cr\xae$\x8f\x92\xf9o\x9a\ -+\x8aA-j\xfc\xa4\xe2\xf8\x1bj\x5c\xa5a\xac\xd9\ -\x0af\xd3r\xde'\xf1\xda\x01!\x1f0\xa1du\x02\ -p\xe0,\x07-\xa5~\x1c\xb2\xd0\xb3\xc86\x1c\xa9\xf2\ -\x1b*P\x1b\x8f\x8a\xab\xa6\x130\x22\xb5\x19Mr\x14\ -G2\x07\xe76#j\xee\xc0k\xd6\x1b\xed\xa6\xa5a\ -\xaa\xa5\xd3J\x9e!\xc2\xb1S4[\x88j\xf8\x00{\ -6`\x9a\x96\x80\x1e\x02N2\x1f\x8a&\x86(d\x1b\ -S+\x0b\x81\xbe\x1a\xcd\xa71\xb0\x095\xf3\x8d8\xf3\ -\x9193\x959s\x999\xb3\x9d9\xf3\xa1:3\xa5\ -:s\xa9:\xb3\xad:\xf3\xb1;3\xb5;s\xb9;\ -\xb3\xbd;\xf3\xc1<3\xc5\x0d\x0a\x0d\x0a \x0d\x0a \ - icon / o\ -utliner / entity\ - / Default\x0d\x0a Cr\ -eated with Sketc\ -h.\x0d\x0a <\ -defs>\x0d\x0a \ - \x0d\x0a \ - \x0d\x0a \x0d\ -\x0a\x0d\x0a\ -\x00\x00\x03\x87\ -<\ -?xml version=\x221.\ -0\x22 encoding=\x22UTF\ --8\x22?>\x0d\x0a\x0d\x0a \x0d\x0a \ - icon / o\ -utliner / entity\ - / Loop v2\x0d\x0a Cr\ -eated with Sketc\ -h.\x0d\x0a <\ -g id=\x22icon-/-out\ -liner-/-entity-/\ --Loop-v2\x22 stroke\ -=\x22none\x22 stroke-w\ -idth=\x221\x22 fill=\x22n\ -one\x22 fill-rule=\x22\ -evenodd\x22>\x0d\x0a \ - \x0d\x0a \x0d\x0a\x0d\x0a\ -\x00\x00\x19\xf8\ -\x00\ -\x00\xe0\x1cx\x9c\xed\x9c\x09\x5c\x14\xd5\x1f\xc0\xdf\xec\xc5\ -\xb5\xdc\x87\x17\xea\x8a\x1c^\xdc7\xca\xb9\xa0\xa0\x22\x08\ -xf\xc9\xb2;\xc0\xea\xb2\xbb\xee\x01hVj\xa6\xa5\ -\x96Gf^e\x1e\x99GiY\x1e\x99\x1d\x9af\x87\ -\x7f\xcb\xdb\xb2\x03\xf3oj\x99Q\xa6V\x9a\xfc\x7f\xbf\ -Y\x16\x06\x04E\x19\xc0\xfe\xcd\x97\x0f\xb3o\xde\xf5\xfb\ -\xbd\xdf\xbcy\xd7\xcc\x9b\xccL\xd2\x8b\x10bK\xbc\xc8\ -M\x22\x02\x17E,\x07!\xf3\x93\x0f\x07\x8a\xe5\x160\ -n\x88GyQ\xc2j\x7f\x88LI\xaa\xdd\x028\xb8\ -Z\xf3\xc9\xaa\xa4\xdcXq<\xab\xddLjV\x9e\xed\ -\xac\xf1\xe7\x11\xaa#\x11[\xdcT\x17\xaaS\x8d\xdb\x9f\ -\xf2f\xe5\xd3\x83%+\x14\x8f\xc4\x07\x5cAT\x18\xe3\ -\xf6\x00w6\x95S\x1b_\xb0\x0b\x8fQ\x9d\xe0T5\ -#\x03\xdd\xd2\x1e\x84DO\x99\xa9\xb6\xca\xfd\xaer\xa6\ -\x91\xd8\x80\x7f:!\xf2uX~\xb0\x87\xe5\xcf\xfe\xc6\ -\x14B\x02\x5c\xac\xbf\xc9*]\x01-\xcb.\xd6\x99t\ -\xc6b\x9d^&\x97\xcb\xc2BB\xa3e=F\xa8\xb5\ -*]\x99\xb1'\xc1\xd3\xb8\x90\xb0\xb8\x90pYhd\ -\x5cX88H\xbf\xc4r\xbdB9\x9e6\xc9\x0a\xe8\ -\x22\xb56\xde\xe7\x97w\xde\xf7\x91\xa9U\xf1>#\x22\ -3C2\xf5r\xbaX\x9d>\xc9@\xe7N\x1a\x92\xa7\ -\x9c4^\x19\xab\xf2IL\xb0\xefW\x1eW^\xa2/\ -\xa1M\x0aYy\x89Fk\x8c+\x8f\xf7Q\xa0\xfc8\ -p\xa3w\xb0\x8f\x8c\x89b\x1a\x1f\xefcQldf\ -\xb6L\xae3\xd0\xb2\xc8\xa0\xa8@ehx\x8c,:\ -6(426&,\xa2\x0f*\x1a\x15\x1c\x12\x1b\x1c\ -\x1a\x11\x18\x12\x1a\x17\x12\x1b\x17\x12*\xab\xc6'\xc1\x1e\ -\x8e\xfd\x0c\xaa\xc2\xb8\x9c\xd4\xfe\xd5\xe2\xe0,\xde\xa7\xd8\ -d\xd2\xc7\x05\x07\x97\x95\x95\x05\x95\x85\x07\xe9\x0cE\xc1\ -\xa1\xb1\xb1\xb1\xc1!a\xc1aa\x81\x10#\xd08Q\ -kR\x94\x07j\x8d\xdd-\x99X\xf3I\xa5\x8dJ\x83\ -ZoR\xeb\xb4284($\xb8\xa1D*eM\x1a\ -\xbd\xd9\xa0aTS)\x83i\x0d]BkMFH\ -\x17\xda`:\xbd\xf5\xda5,\xb2&\xb8Q\xc1\xa0m\ -f\xe6\xed\xf5-)i0\xa5\xd1\x94Vj\xba}J\ -c\xdeD=\x1d\x9cC\x1buf\x83\x92N+\x85\xa2\ -\xd4\xda\x15M\x0b\xd2\xe3\xe4\x06Za\xa2S\xe1?\x01\ -k[`HX`Hx\x1e\xd4\xb6\x90\xa8\xb8\xb0\xc8\ -\xc0\x90\x98\xb8\x90\x90~\xc1\xf5b\xd6\xcb#S\xa7R\ -\x17Nl \x0f\xa6\xc6\xb2\xf3`\xc5\xac\x9f\x07\xd4A\ -\x95\xc2\xa4hR.\xec\xb8\xac|T\xca\xb8B\x9d\xa1\ -DaJP\x97(\x8a\xe8`\x93\xba\xb0\xb0_p\xad\ -/+j\xcd\xa5\x89\x93\xeb4:\x03\xe8E'\x84\xf7\ -\x0bn\xc8\xbb\xc1T\x19ry\xb6AW\xa8\xd6\xd0\x09\ -\xc6\x9c\x01)\xb2\x8c4yThlTT`XP\ -(;\x1bV\xbc\xba\x05\xce\xcc\x8c\xcb\xd0\x1aM\x0a\xad\ -\x92\xceHM\x00\x8f \xb5Z\x15WX\x18AG\x85\ -\xc7D\x05\xd2\x85\xe1t`(\x1dA\x07\x16D+c\ -\x02\xa3\x14\x11\x91ttxAX\xb4R\xc5\xd8\xa0n\ -\xf2[\xb2N\xd5)\xcdXu\xab\xb3V\xdde\xd6\xac\ -\xe4\xb7d\x9dePC\xb3\xa3\xd04SD\x03\xd9\xdc\ -\x22*]m4\xe9\x0c\x13\x13\xeaT\x7f\xa6A\xc8\xa5\ -'\xd4\xf5\xb5\x06h\xd4L\x03\xa1W\x18\x8c4V\xff\ -x\x1fk\xfd\xf7\xb9%\x01\xa6an\xa38\x85\x12\x9b\ -\x96\x04%S\xc3A\xc5:\xbe\x8d'S\xdf\xeb\x05\xbc\ -%y\xe32\xca\x8ai\xed\xed\xeeLV\xac\xc631\ -\xea\x0aMe\x0a\x03\x9d\x5c\x04\x96N\xb8c\xbfc\xcd\ -\xb5n\xb2[\xec\x1dl1x\xbd\xcb\x13|\xeb\xf5\xb1\ -^\xf3z\xd7\xd3\x12\x95\xd5\xb6[:\x8e\xe0\xea\x9e\x03\ -:\xad\xe0\x9a^\xab\xa1\xc2q\x0f/\x84\x17\xc2\x0b\xe1\ -\x85\xf0Bx!\xbc\x10^\x08/\x84\x17\xc2\x0b\xe1\x85\ -\xf0Bx!\xbc\x10^\x08/\x84\x17\xc2\x0b\xe1\x85\xf0\ -Bx!\xbc\x10^\x08/\x84\x17\xc2\x0b\xe1\x85\xf0B\ -x!\xbc\x10^\x08/\x84\x17\xc2\x0b\xe1\x85\xf0Bx\ -!\xbc\x10^\x08/\x84\x17\xc2\x0b\xe1\x85\xf0Bx!\ -\x1c\x0b\xb1\xaf\xdd\x07FkU\xf1>e>\x89\x09$\ -&%#S\xe4\xc7\xec9s!\xf5`\xc2\xe2\x18\xe7\ -\xd9\xeapfw\x1eq\xd0\x1b\xd4ZS\x96\xd9\xa47\ -\x9b\xe0\x14\xb7\xc9\x91l\xa3)\xb7@\xa7\xd3012\ -\xb4&\x9a\xd6\x9aK\xacn\xfc\x95k\x0cx\xee\xcc\xa4\ -\xcdU\x97c\x8c\x14\xb5\x09\xd3\xd4\xe6I\x1b\x86(J\ -\xe8\xbc\xb4\x91y5\xc2,\x09\xb2\x0d:]a.m\ -2\xeb\xb3\x0a\xc6)\xc1[J\xb2\x89\x81\xe8\xe0\xaf\x90\ -\xc8H.\xa1\x89\x89\x98\x89\x9eIb\xaf\xaf\x89m\xcd\ -&Ec\xd2Vk$-0\xab5&\xb5\x96\xc9\x12\ -\xce\xed\x98\xd8\xf2\xccQ\x83,%\xee\x8b\xf1\x05\x81u\ -J\xec\xc6*q\x16\xb3\xf3\xc0\x08\xbe\xed\x98r\xe9M\ -Zk!\xa0\x90\x05\x86\x9a\x93\x9c\x22cfm\x88A\ -+\xaf=\xd1\x9ajO\x06\x17h\x8c5'C\x8aL\ -\xa55'i%\x9a\xd4\x9a\x13\xb0cm\xd6)\xca\xf1\ -E\xd5\x86\xb0(Hr\x06\xa4\xc8\x89e\xdb$\xc9Q\ -\xc9d*\x9d\xb9 IWQs1\x07\x18\xb4\xb7\xf8\ -\xa5hn\x8d\x97bP\xe5\x0d\xd3\x9a\xfaw\xcf\xd1\x98\ -\xd8\x95!E\xa3\x925\xe4\x9fc\xd4\x98\x18\xff\xecr\ -MRN\x8d\xb7})\xad4\xe9\x0c\xa9\x0a\x93\xa2\xa6\ -Vd\x17e\x1b\xad\xb5\x02\xdd\xd5\xbfr\xc6\x08t\xa1\ -\xa9\xa1\xec\xf3t\xfa\x06\xc5\xe6*5\x16\xffl\x832\ -iT\x8d\xb7\x8b\xd2\xa0\xd3\x8f(\xa6\xe1\xe2\xc2\xf5R\ -k\x8b\xac\x16s\xc2\x80\x1c\xd0)Eg2\xe9J4\ -:mQu\x12\xa95\x04U`\xf9;Z\xfds\xd4\ -E\xc5\xec\x00\x07k\x00\xe8V\xe3\x8d5G\xf8\xb3E\ -\x07\x92N,{?\xab\x7f\x99Z\xe5\xcf\x849\xd5\x96\ - qJu\xaaK\x16q\xd2<\x83Bk\xd4+\x0c\ -\xb4V9\xd1R\x13=\x99\x90.\x18J\xf2\xa0\xb6+\ -\x88\x96\x18\xa1\x8e+\xc0M\x83[I&V\xdf\xa5\x91\ -LLWF\x1e\xa9\xaa\xaa\x16\xa1\xa2,\xa1\x9d\x993\ -\x91UO\x91c\xcdy\x17\xe6\xbcC\xdds\xe1e\xe6\ -\xdc\xce\xaa\xa9%\x97\x00K\xfb`o\xadp\x96r\x09\ -\xaf0\xeet\x12\x5cX\x08!\x1a8J\xaa\x13Y|\ -V.YZ\xe3\x13\xc6\x1cG\xc3\xd1\xea\x13\xc9\x1c\x03\ -k}\x98<\xff`\xdcz,IC\x08\xcfc0\xf7\ -a\x8c-,e\x13T\x9f\x09\xea\x9c\x85Xt\xac\xb6\ -j`\x9d0\xdb\xeak\xcf\x5c\x01A\x92\xe5\xbf:\xac\ -K=\xfbwD\x970\xb2\xa6\xd4\x16\xf2\xab\xff-\x96\ -\xb9\x15\xb6\x1f;n\x83\x11\xac\xd46aDk\xd6h\ -,\x0a\x13I\x81\xce\xacU\x19\xeb\xb5 JS\xa8U\ -M\xbc\xedXU\x9e\xd4\xbb7HJ\xed=\xc4\xa8\x91\ -S{\x8b\xe0\xb9\xc4\xa8Q+i\xe3p\xcd`\xbc\xc9\ -\xa9:r\xc4L\x188\xdc\xe0\xdf\x869\xc9He\xe5\ -mSd\xd0\x99\xf5u\xbc$:f\xeb\x9f\xb5\xfdN\ -\xcb\xc5D\x96\xed\x80p\xee\xa80\x9bt\x03h-m\ -\xc0\xadx\x8c\xf6\x13\xf5\xd6\xee\xc7\xde\x12\x19}0$\ -\xa3\xa4H\xd6\x0a\xe5\x17\x9a\x0d\x9a:\x9d\x18c\xfc\xba\ ->\x99\xc6\xa2\xba\x1d\x9dD\xa11\xe5)\x8a\xea\xf89\ -)iHG\x97\x9b2\x8c\xe9y\x99\x83\xadM\xa9\xad\ -\xd5\xbbNd\xbbb\x9daR\xb2F]d\xb5\x94\xb3\ -\xa5\xf0\xe9Vo\xb4\xae\x8a.T\x98\x99\xb6\xd4\xae\x94\ -6\x98\x1a\x88>\xdc\xea]7\xbaCA\x11\xb3\xc3\x95\ -e\x5cWK\x82\x94\x015\x01\xa8\xc6\x10\x9d\x16\x7f\xed\ -L:=t\x98F\x9am8{\x0d\x18\xf2\x16_i\ -\x01\xd3(\xdf\xe2\xef`\xc0\xa6\xb7\x9e7s\x07\xf5\xb0\ -\xa4\x83\x7fAb%\xa9\xf5\xf7`\x9cx\x09\x85\xcc9\ -\xc6 \x82\x93\xd5&\xca\xb7\xfcSP\x05\x98;a\x17\ -iO\xa8\xaa\x93U?\x13)\xb3\xc3q\xac<\x13\xce\ -/\x11'\xe6\x8c\xa8\xa6`\xba\xaaSd:\x91\xda\xda\ -\xda\xda\xd9J\xed\xec\xa4\xae\x0e\xf6\x0e\xae\x9e\xceR\xa9\ -\xb3g{wwOw\xf7\xf6\xaeR\x86\xea\x9f\x86\xa1\ -\x1c\x1d\x1c\x1c\x9d\x1c]\x9c\x9c\x5c<\x9c\x9c\x9c<\xf0\ -\xe0\xe4aI\xe2\xda\x94\x0c\xaa> \xae\xb6\xa0|\xbe\ -\x90\xf2!\x02WJ\xe8JU}\x03\x05\x95T\xed\xa5\ -\x12AK1\xc5Pm8!\xa1\x04\x22\xb1\xc4\xc6\xd6\ -\xce\xde\x81\xaa\x1fH\x11\x81\xd0\x1a\xe8B(\x11%\x14\ -\x88\x04b\x1b\x89\xadX(\x0d\x87@W\xa1\xa8\x9b[\ -\xa88y\xa8\xc2\xddg\xc2\xd40\x89\xc7\xfc\x95o\xa4\ -t\xf7\xf5\xcc\xd9]\x10\x1ea\x98vHn\xe3\xb7 \ -\xb7\xf2\xf4\xafJc\xa4\xd7\xaa-\x8f\xfb\xa7>\x9b\xa7\ -J\xdb\xb3\xda\x14\xd5\xee\xf0\xb0\xef\xe9\xdf\xde\x9c\xfe\xe1\ -\x11\xf3\x99\xcb\xfd\x03\x16\xaey\xe2\xad\xe7\xf6\x1e\xfd\xef\ -\xef/o\xddw\xec\xec\x95\xe1\x85\xa53\x16\xad\xdd\xf6\ -\xd1\xf1\x1f\xaeF\x0f\x18QT6\xf3\xf9W\xb6\xef?\ -q\xee\x9a+\x11\x08@[\x11\xa3\x93\x8dD\x1c\xc9\xa8\ -\xd0-\xd4M\x04\x1aL\xf0q\x17\x87M\x9d\xef\x81\x1a\ -\xec\xce9T\x19\xee[p\xda0m\x81<\xd7Si\ -\x8c\xf8\xd5O\x82\x0a\xd8\xf8G\xee9\x0cJ\xacn\xa7\ -J\x1b\x16e\xa2\xbf\xafQ\xa1q\x0d\x02jU\xa8\xfa\ -\x8aH\x85\x8cLW\x92H\xae\xe4-\xc8\xf0\xeb\xe9\xbb\ - c`\x86\xef\x82\x9c\x05\x19\xbe\x0b\xd7T{dU\ -}q\xbb\xc0C\xb7\x0b<|\xbb\xc0#\xb7\x0b\ -!\xc02\xd4m\x03\x9b\x08^[\x8b\xeb\xf2P\xe6\x9a\ -Q^\x07j\xfd\x1a\x8a\xa7[\x05m0\x8c\x06\x85\xf3\ -j\xfd\x0a\x96\x10\xb2\xfd\x09B\xda\x7fU\xeb\xe7\xfb\x12\ -\xd4Q\xb8n\xdb>g\x95\xc7\x0b\xeb\x0b\xebc\x1fj\ -Z\x19\x84\x06\xad\xe1\x8e\x11\x9a\x00K^\x10fWc\ -\x1eY\xaa\xa5\x97\x93\xa1\xdd\x94\xd0\x97\x99\x0d2\x18\x89\ -+iY`\xfdJ|\xcf\x09\x1b\xd6\xa3O\x0e]H\ -\xe3\x88\x9f\x96\x0d\x87Z\x06\x13\x16\xb8\xdcZ\x95\x9a\xf9\ -n\x89Z\xdb\xd8E\xbc\xc7d\xf5\xb0\xd4k\xc0}\xcd\ -M\xe216\x88\xb8|\xeeA\x84?\x1f \x22w\x07\ -\x22\x1c\xf3\x22\x84P5\xd7m\xb0\xddp\x82w\xde\x88\ -\xae\xe7,\xf5\x9e\xa1\x81!\xa7`.\x1e\x8cjf\xa0\ -E\xe49y2\xa5\xd9Pj\x09c\xc6Vb\x98C\ -8\x13\x0f\xd2\x01f6\xddI\x0f\x18\xfd\x87A#\xd3\ -\x97$\x9142\x90d\xc1Lg\x14y\x08\xe66\xc5\ -\xa4\x04\xe69ed2\x99Jf\x90\xd9d\x1ey\x8e\ -,%+\xc8\x1a\xb2\x9el\x22[\xc8v\xb2\x8b\xec&\ -\x1f\x91\xcf\xc8\x17\xe4\x189E*\xc8Y\xf2\x13\xa9$\ -W\xc9u\xe8\xecl(G\xca\x9d\xea@u\xa5\xfc\xa8\ -\xdeT\x18\x15C%Pi\xd4`*\x87\x1aE\xe5S\ -E\x94\x962S\x93\xa9\xc7\xa9\xd9\xd4\x02j)\xb5\x92\ -ZO\xbdA\xbdM\xed\xa6>\xa1\x0eQ_R\xa7\xa9\ -\x0b\xd4o\xd4_\x02\xa1@*\xf0\x10t\x16\xf8\x0b\x82\ -\x051\x82d\xc1 A\x9e\xe0AA\x91`\x82`\x92\ -`\xba\xe0\x19\xc1b\xc1*\xc1\xab\x82m\x82\xdd\x82\xcf\ -\x04\xc7\x04\x15\x82\x9f\x04W\x84D\xe8 \xf4\x12v\x13\ -\x06\x0ac\x84ra\x96p\xb4\xb0Ph\x10>*\x9c\ -%\x5c$\x5c%\xdc$\xdc)\xdc/<\x22\xac\x10^\ -\x14\xfe)\x92\x88\xdcE2Q\xa0\xa8\xaf(]4L\ -\xa4\x14M\x10=*\x9a#Z*Z'\xda&\xda+\ -:\x22:-\xaa\x14\xdd\x14;\x8a\xbd\xc5\xbd\xc5q\xe2\ -\x0c\xf1Hq\x91\xb8L\xb7;kw\xdd\xde\xd5>\xc0>\xde>\xcf~\x9c\ -\xfdT\xfb\xc5\xf6\x9b\xec\xf7\xd9\x7fm\x7f\xd9\xc1\xc1\xc1\ -\xc7!\xd6a\xa8\x83\xdaa\x8a\xc3b\x87\xd7\x1d>v\ -8\xed\xf0\xa7\xd4M\xdaK*\x97\x8e\x91\x9a\xa5\xcfH\ -_\x91~ \xfdRz\xd9\xd1\xd1\xd1\xdf1\xc9q\xb4\ -\xa3\xc9\xf1\x19\xc7\xf5\x8e\x1f:~\xeb\xf8\x87\x93\xbbS\ -\x90S\x86\x93\xca\xe91\xa7eN\xdb\x9c\x0e;]r\ -\xb6s\xf6sNv~\xc8y\x92\xf3\x22\xe77\x9d?\ -w\xbe\xe8b\xe7\xe2\xef\x22wQ\xb8<\xea\xb2\xcc\xe5\ -m\x97\x13.W\x5c\xdd]C]\xb3\x5cK\x5c\xe7\xb8\ -np\xfd\xc4\xf5\xbc\x9b\x8d\x9b\xbf[\x9a\x9b\xcam\xba\ -\xdbj\xb7\x0f\xdd\xce\xb8\x0b\xdd\xbb\xbb\xcb\xdd\x95\xee\x8f\ -\xbb\xafq\xdf\xe7~\xd6C\xe2\x11\xe0\x91\xe11\xcec\ -\xb6\xc7k\x1e\x07=*=\xdd<#<\x87{\x96{\ -.\xf3|\xd7\xb3\xc2K\xe8\xe5\xef\x95\xe1\xa5\xf1\x9a\xeb\ -\xb5\xc5\xeb\xb8\xd7_\xed:\xb7KnG\xb7{\xaa\xdd\ -\xa6v\x87\xdb]k\xdf\xa9}R{\xba\xfd\xac\xf6\x9b\ -\xdb\x1fk\xffW\x07Y\x87\xb4\x0e\xe3;\xcc\xef\xb0\xbd\ -\xc37\x1dE\x1d{u\x1c\xda\xb1\xac\xe3\x8b\x1d\xf7u\ -\xbc\xd8\xc9\xa3S\xdfN\xcaN\xb3:m\xe9\xf4\x95\xb7\ -\xc0\xbb\x97w\x8e\xf7\xc3\xde\xab\xbd\x0fx_\xe9\xdc\xa5\ -\xf3\x80\xce\xfa\xceK:\x7f\xd8\xf9b\x17\xaf.I]\ -\xc6uY\xd8\xe5\xbd.\x17\xba\xbawM\xe8\xaa\xee\xba\ -\xb0\xeb\xfb]\x7f\x94y\xca\x92e\x1a\xd9b\xd9^Y\ -e7\xefn\xe9\xdd\xcc\xddVv;\xd8\xed\xbaO\x80\ -\xcf0\x9fi>\x9b}\xbe\xe9n\xdf=\xa6{a\xf7\ -\x85\xdd\xf7t\xaf\xf4\xed\xea\x9b\xe9;\xd9w\xa3\xefW\ -~v~1~\xc5~\xcf\xfb\xed\xf7\xbb\xe6\x1f\xe0?\ -\xc2\x7f\xa6\xffv\xff\xf3\x01\xed\x032\x02&\x05l\x0c\ -\xf8\xba\x87c\x8f\xc4\x1e\x13z\xac\xeaq\xb4\xa7\xa4g\ -L\xcf\xf1=_\xe8\xf9E/A\xaf\xc8^\xc5\xbd\x96\ -\xf5\xfa\xbc\xb7\xa0wTou\xef\x17z\x1f\xea#\xee\ -\x13\xdbG\xdbgU\x9f\x13\x81\xd2\xc0\xe4\xc0\xd2\xc0\x8d\ -\x81\xa7\x83\xbc\x82\x06\x07M\x0b\xda\x1et)\xd87x\ -t\xf0\xfc\xe0\xfd\xc17C\x22C4!kBN\x85\ -\xba\x85\x0e\x0c\x9d\x16\xba3\xf4\xb7\xb0^a\xca\xb0e\ -aG\xc3\x1d\xc3\xfb\x87?\x16\xbe#\xfc\xd7\x88\xde\x11\ -t\xc4\x8b\x11'#\xdd#3#gF\xee\x89\xfc;\ -*:\xca\x10\xb5)\xeaB\xb4ot~\xf4\xf2\xe8\x13\ -1\x1e1\xd91sb>\x8e\x15\xc7\xa6\xc4>\x16\xbb\ -+\xf6\xcf\xb8\xa88S\xdc\x96\xb8_\xfa\x06\xf6\x1d\xdf\ -wC\xdf\xf3\xfd\x02\xfa\xd1\xfd\xd6\xf4;\x13\xef\x13\xaf\ -\x88_\x19_\x91 K\xc8Ox)\xa1\x22\xb1[\xa2\ -\x22qU\xe2\xf7I\xdd\x93TIk\x93\xce%\xf7L\ -\x1e\x97\xfcj\xf2\xa5\x94\x90\x14C\xca\xd6\x94k\xf28\ -\xf9#\xf2\x0fR\x85\xa9\x03Rg\xa5\x1eLsK\x1b\ -\x96\xb64\xed\xdb\xfe>\xfd\x8b\xfao\xec_9 r\ -\xc0\xc3\x03>H\x17\xa7\x0fJ\x9f\x9f~\x22\xa3s\x86\ -2c}F\xe5\xc0\xe8\x81\x8f\x0c\xdc;H:(w\ -\xd0\xd2A\xdf\x0f\xee5\xd80xg\xa6 s`\xe6\ -\xb3\x99_\x0f\xf1\x1b\xa2\x1d\xb2=\x8bded=\x9b\ -\xf5Mv@\xf6\x84\xecw\x86J\x86f\x0f]6\xf4\ -\x87\x9c\xd0\x9c\xc99\xfbs\xdds\xc7\xe6n\xc8\xbd\x9a\ -\x97\x9277\xef\xd4\xb0\x1e\xc3\xcc\xc3\xf6\x0cw\x1e>\ -f\xf8\xfa\xe1\xd7F\xa4\x8eX0\xa2bd\xf0\xc8G\ -F~6\xaa\xe3(\xf5\xa8\x1d\xa3mF\x0f\x1f\xbdv\ -\xf4\x95\x07\xd2\x1ex\xee\x81\xb3c\x22\xc7\xcc\x18s\xfc\ -\xc1\x80\x07\xcb\x1f\xfc\xe4\xa1\x8e\x0fi\x1ezw\xac\xf3\ -X\xc5\xd87\xf3\xc5\xf9#\xf27\xe4\xdfPd)V\ -)\xae\x14d\x14,/\xa8T\xca\x95\xcf+\x7fR%\ -\xa9\x16\xaa.\xd0\xf1\xf4\x02\xfa\x5ca|\xe1\x82\xc2\xf3\ -E\xf1E\xcf\x16](N,^T|Q-W/\ -U\xff:.}\xdc\x8aq\xd7\xc6g\x8d\x7fe|\x95\ -f\x84fs\x89mI~\xc9\xdbZ7\xedx\xed^\ -]\x17]\xb9\xee\x90\xbe\xb7~\x86\xbebB\xdc\x84\xe7\ -&T\x1a\x06\x19\xd6\x1a)\xe3\x83\xc6\x1d&\x0f\x18L\ -\x1d0\xf70?a>]\x9aP\xba\xac\xf4\x8f\xb2\xe1\ -eo\x96\xbb\x96k\xcb\x0fL\xec5\xf1\xa9\x89\xe7&\ -\xf5\x9f\xf4\xf2\xc3\xa2\x87\x95\x0f\xef\x99\xdcm\xf2\xd4\xc9\ -\xa7\x1fI~d\xe5\xa3\xd4\xa3\x05\x8f\xeey\xac\xfbc\ -\xd3\x1f;;e\xc0\x94uS\xed\xa7\x8e\x9f\xfa\x9fi\ -!\xd3\x16L\xfb\xfd\xf1\x11\x8f\xef\x9c\xdey\xfa\x94\xe9\ -g\x9e\x18\xf0\xc4\xc6\x19N3\x0c3N\xcc\xec;s\ -\xc5\x93\xa2'\xd5O\x1e|*\xfc\xa9%O\xdd\x9c\xa5\ -\x9a\xf5\xe9\xec\x90\xd9\x8bf\xdf\x98\xa3\x9c\xf3\xe9\xd3\xa1\ -O/~\xba\xea\x99\xc2g\x0e\xce\x8d\x9a\xfb\xe2<\xc9\ -<\xed\xbc\xe3\xf3\x13\xe7\xaf[\xe0\xba`\xd2\x823\xcf\ -f>\xbbm\xa1l\xe1\xac\x85\xbf?7\xf6\xb9O\x16\ -E,Z\xf1\xbc\xfd\xf3\xe6\xe7+\x16\x0f^\xbcc\x89\ -\xef\x92yKn,-^zlY\xca\xb2\xcd\xcb\xbd\ -\x97?\xb5\xfc\xda\x0b\xaa\x17\x0e\xbf\x98\xf4\xe2\xa6\x15\x9d\ -W\xcc^\xf1\xd7K\xea\x97N\xae\x1c\xb0r\xdb*\xff\ -U\x8bVKV\x97\xae\xfea\xcd\xf05\xfb_\x8ey\ -y\xfd\xda\x8ekg\xaf\xfd\xfb\x15\xed+\x15\xebr\xd6\ -\xed]\x1f\xbd~\xfd\x06\xef\x0ds7\x0a6\x9a7^\ -xu\xcc\xab_\xbc\x96\xfa\xda\x8eM\x81\x9bVn\xf6\ -\xda<\xfbu\xf2\xba\xf9\xf5\x1f\xdf\xc8\x7f\xe3\xf8\x96A\ -[\xf6\xbc\x19\xf3\xe6\xa6\xb7\xfc\xdeZ\xbe\xd5}\xeb\xac\ -m\xd4\xb6\x89\xdb*\xb7\x17o\xaf\xd81j\xc7\xa1\xb7\ -\x07\xbe\xbdgg\xdf\x9d[\xdf\x09z\xe7\x95]\xddv\ --{\xd7\xf3\xdd\xb9\xef\xd9\xbf7\xfd\xbd\xaa\xf7'\xbd\ -\x7f\xe5\x03\xfd\x07\x17w\x17\xed>\xb3g\xec\x9eS\x1f\ -\x8e\xfc\xf0\xe8\xde\xa1{\x0f\xee\x1b\xb4\xef\xe3\x8f\xfa\x7f\ -\xf4\xe1\xfe\xe4\xfd\xef\x7f\x1c\xff\xf1\xaeO\xe2>y\xfb\ -\xd3\x98O\xb7\x7f\x16\xf5\xd9\xb6\x03\x91\x07\xb6\xfe'\xf2\ -?[\x0fF\x1d\xdc\xf6y\xf4\xe7;\xbe\x88\xfdb\xe7\ -\xa1~\x87\xde;\x9cxx\xf7\x91\xd4#\x1f\x1d\xcd8\ -\xfa\xd9\xb1!\xc7\x0e\x1d\x1fv\xfc\xe4\x891'*N\ -\xaaN\x9e\xffR\xf3\xe5\xaf_\x95~u\xfd\xd4\x94\xaf\ -\xc5_\xcf\xfa\xc6\xe5\x9bE\xdfz\x7f\xbb\xea\xbb\x9e\xdf\ -m\xae\x88\xaax\xf7t\xea\xe9\x03\xdf\xe7~\x7f\xea\x8c\ -\xf2\xccO\xff5\xfe\xf7\xc6\xd9\xe9?8\xfe\xb0\xe8\x5c\ -\xd7s\xeb\xcf\x87\x9d\xdfu\xa1\xff\x85/~|\xe0\xc7\ -\xb3?\xe9\x7f\xba~q\xc6\xcf\xae?/\xbf\xd4\xe3\xd2\ -[\xbf$\xfdr\xa0rd\xe5\xd9_\x0d\xbfV\xfd6\ -\xe7r\x87\xcb\xaf\xfc\x1e\xf1\xfb\x9e+\xd9W\xbe\xbdZ\ -r\xf5\xfa\xb5Y\x7ft\xf8c\xdd\x9f1\x7f\xee\xffk\ -\xc4_\xe7\xae\x97\xdd\xb0\xb9\xb1\xf8\xef\x9e\x7f\xef\xbc9\ -\xe8\xe6\xd7U%5+\x93<<<<<<<<\ -<<<<<<<<<<<<<<<<\ -<<<<<\xffbl\x81\x91@[\xeb\xf1oe\ -\x05\x80{e^\x04\xf0Z\xb4\xb5>\xff&\xb0\xde\xb3\ -\xf7+}\x06t\x01ZBVG`\x180\x13\xd8\x01\ -\x1c\x03~\x00\xaeU\x83\xee\xe3\xc0\xdb\xc0\x93\xc0p\x00\ -\xd3\xb4\x84.\xf7\x0bX\xdf\xb1\xde\xb3\xaf\xc1\x8f@\x0a\ -\xc0E\xfe\x9d\x802`?p\x13hx\x97Z\xe3`\ -\x9aO\x80r\xa03\xc0\x85N\xf7#%\xc0_\x80\xb5\ -\xdc7\x00\x1dp\xaf\xf9\xc5\x00\xeb\x80\xeb\xc0\xdd\xda\xbc\ -10\xaf\x0d@\x1c\xc0e\xd9\xef\x17\xfa\x02\xe7\x00v\ -\x99\xd7\x02\xf6@S\xf3\xf0\x06\xd0F\x5c\xd9\xbc1^\ -\x05Z\xaa\x9dlK:\x00\x1f\x01\xec\xb2\x1e\x02|\x80\ -\xdb\xa5\x93\x00\xd8F\xfc\x0e\xb4\xb4\xed\xad\x5c\x01&\x01\ -6@k\xd9\xa75@[.\x01\xd8e\xbd\x04\x0c\x00\ -\x1a\x8a\xdf\x1f\xf8\x12h-\xbb\xd7\xe7\x14\x90\x0e\xb4\xb6\ -\x9dZ\x9a\x02\xe0\x0f\xc0Z\xce\xbf\x01\xecK\xad{\x1e\ -\x05\xc0\x13@[\xd9\xbd>8fB\x9d\xda\xdan\x5c\ -\x12\x09|\x0f\xb0\xcb\xf9\x1a\x80\xed\xfcV\xa0\xadl\xdd\ -\x18\xdb\x01\x17\xa0\xad\xed\xc6%\x9e\xc0\xfb\x00\xbb\x9c\x7f\ -\x02md\xe2;\x82\xedQo\xa0\xad\xed\xc6%\x22`\ ->\xd0\xd6\xb6m*\x97\x814\xa0\xad\xed\xc6%\xa9\xc0\ -\xfd\x5c\xef\xeb\x83s\xea\xff\x97k\x80c\x1c,\x0f\x17\ -v9\x0b\xe0\xbd\x84c\x96^\x80#\x80\xdfB\xf0\x07\ -\xce\x00\x5c\xc8\xb0\x82:\xa3\xeemm\xbf\xe6\x80\xe3N\ -.l_\x01\xe4\x02\xb7\x1b\xa3`\xdb\xcd\x85\xdd\xd9\xa0\ -\xee\x8d\x8d\x9d\xefwp\xfc\x83\xf3\x9c\xe6\xda`\x0e`\ -\x07\xdcI^K\xd8\x1f\xc12D\x00\xada3\xae\xc0\ -\xf9}\xfd\xf5\x88\xbb\x05\xe7\x0c\xe3\x80\xa6\xcal)\xfb\ -#X\x96\x7f\xca\x1a\x1e~\xc7\xe6\x08\xd0\xdc2\xdf\xed\ -\x1a^K\xda\x1f\xc1\xb5\x14\xecoZ\xcan\x5c\x80\xf3\ -\xdb\xb7\x00.\xca\x8bm~(\xd0T\xd9-m\x7f\xe4\ -\x0d\x80\xf5\xdd\xa2\xfb\x8e\xc9@s\xcb\xc8^\xeb\xbf\x0a\ -<\x084Evk\xd8\x1f\xc1u\x94\x96\xb6\xe3\xbd\xd0\ -\x0f\xc0\xb5\xff\xe6\x96\x0f\xc7\x97\x95\x00\xdbo\x1e\x80\xf3\ -\xb8\xdb\xc9o-\xfb\xe3\xb3\x84h\xa0\xb5\xec\xda\x14\xb0\ -\xcd\xc7\xf6\xa2\xb9e\xc3<\xc4\x80\x1fp\x14`\x87\xed\ -\x01\xda\x01\x8d\xe9\xd0Z\xf6G\xbe\x02\xee\xe6\xd9FK\ -\xf34\xc0E\xb9\x9e\x02\xacy\xe2\xbc\xaa\xfe\xf3\x98\xff\ -\x02\x8d\xd5\xbd\xd6\xb4?2\x15h=\x0b7\x0e\xae\x19\ -\xe2\x9a\x09\x17eJ\x02\xea\xe7\x8f\xcff\xd8\xed\x1a\xae\ -c\xa8T*U\xfdx\xadm\x7f|\xae\x81u\xa4U\ -\x8c|\x1bJ\x01.\xca\x83}-\xb6=\x0d\xc9\xc0\xf5\ -\xa3\x8b\x00;\xfeR\x00\x9f\xf7X\xe3\xb4\xb6\xfd\x91\x09\ -@\xebY\xbaa\xb8Z\xcb\xff\x1a\xb8\x9d\x1c\xfc`\xf9\ -A\x80\x9d\xe6c\x00\xdf\x93\xc0p|\xce\x19\xd0D\xb8\ -z\xe6\xb6\x05h\x1d+7\x0eWe\xd9\x0b\xdcI\x16\ -\xaeC\xac\x06\xd8\xe9\xce\x03\x09\xc0\xdd\xe8\xfc\x1e\xc0\x85\ -\xce'\x80{\xb7\x1c7`\xbb\xc1EY\xde\x04\x9a*\ -S\x0f\xb0\xdfOA\xb7F\xa3\xd145\xfdf\x80\x0b\ -\x9d\xb1\xec\xf7f5\xee\xf8\x0e\xe0\xa2,\xf8\xee\xc4\xdd\ -\xc8\xc5:\x8fu\x9f\x9d\xc7*\xa0)ku8\x96\xe5\ -B\xe7o\x81{\xb7\x1c7\xbc\x03pQ\x96o\x80\xbb\ -\x95\x8dm?\xf6\x01\xec|\xb0\x8f\xc0\xbe\xe2v\xe9\xb8\ -j3\xf1}\xc7{6\x1cG\xe0\xbb\x03\x5c\x94\x05\xd7\ -\xda\xd9\xe3\x99\xa6\x82\xef\xf0,\x07\xd8y\xe1X\x09\xc7\ -L\x0d\xc5\xc71\x16\x17\xeb\xe2\xc8t\xa0\xf9\x16l\x1e\ -]\x01.\xd6\x1d\x90\xe6\xbc;Z\x08\xb0\x9fq\xa2N\ -f\xa0~\xbcD\x80\x0b]Q\xd6\xfd\xf2\x8e\xefz\x80\ -\x8b2\xcd\x06\x9a\xa3\x07\xbe;\x8asdv\x9e8\x87\ -v\x00\xacqp\x8e\xcd\x85\xae\xf8\xeeq\xf3-\xc7\x0d\ -8\xf6\xfe\x0dhn\x99\xf0}\xa1{i\x83\xd8\xe0\x1a\ -Q\xfd\xfe\x15\xd7\x92|\x01\xcc\xfb4\xd0\x5c=\x7f\x01\ -\xac\xf3\x8e\xfb\x85\x87\x80\xe6\x96\x0b)\x06\x9a\xab\x0b\xb6\ -\xf1\x0b\x81\xfa6{\x16\xe0B\xc7\x11\x00\x176\xe3\x1a\ -\xeb~\x98\xe6\x80\xf5\x93\xdd^4\x07\xac\x13\xec\xe7\xff\ -\xf7\xb2\x8f\xa0>\xb8\xee\xc1\x85n-\x01\x8e\xbd\xeb\xaf\ -\x11\xdc\x0bk\x00\xaet\x0a\x03\xb8X\x1bG\x0e\x00\xf7\ -\xfb;\xd3\xf8\x9c\x1a\xdf\xd3inY\xef\xe6\xd9\xfb\x9d\ -\xe0b\x8d\x10\xfb\xf5\xfb\xad\xcdo\x8c\x10\xa0\xb9k\xd2\ -\xd8V\x18\x80\xe6\xea\x82c\xd0\xe6\xb6;8\xb6\x08\x06\ -\xb8\xb0Mk\x91\x01p1/x\x0e\xb8\x97\xf7\x0e\xf0\ -\x99\xdcb\xa0\xb9\xf2\xb1\x0c\xff\xd4=\x02c\x00.\xae\ -\x01\xeeo\x1c\x0b4\xf6|\x80\x0d\x8e1\xf3\x81\xfak\ -C\xf7j{,Ck\xd8\xaa\xa5\x18\x05p5?\xc6\ -gN8\xef\xc1\xfd\xa58\xd7\xf2\xae\x06\xdd\xe8\x87\xe3\ -/\x1cgr!\x0buF\xdd\xdb\xda~\x5c\x90\x07p\ -\xb9\x9f\xb1\xa5A\xdb\xe3~\xe3\xb6\xb6\x1b\x97d\x03\x5c\ -\xbd\x07\xdd\x1a<\x03\xdc\xe9\x9d\x97\x7f\x1a\xe1\x00\x17\xf3\ -\xff\x96\x82\xbd\x8f\x19\xc1\xbd;\xb8\x87\xa7\xad\xed\xc6%\ -\x1e\xc0\xbb@[\xd9\xb81\xd0\xd6\xf8\xdc`\x13\xc0\xf6\ -\xc75)|\x97\xbb\xad\xed\xc6%B\x00\xd7:\xdb\xca\ -\xd6\xf5a\xb75\xf8~\xe7\xc3\x00\xbe\x7fm\x0d\xc7\xbd\ -\x9c\xb8\xa7\xb3\xad\xed\xc658Gh\x8b\xf7F\xac\xe0\ -;\x17\x83\x80\x86t\xc31?\x8e\xb7\xd8\xf1\x17\x01M\ -\x19\x03\xff\x93h\x8b\xfd\xef(\xab)\xfb\xdfq]\x1d\ -\xdf;g\xa7\xdd\x07\xe0^\xff\xd6\xb2Ok\x81k+\ -\xf8\xcd\x88\x96\xb6=~\xdb\x03\xe7\x0cM\xd5\x0b\xdf\xf3\ -\xac\xaf\x17\xce\x07\xf1\x9b\x17-i\x8f\xb6\x02\xc7H+\ -\x01\xf6\xfe\xf9\xe6\x82\xcf\x0a\xf1\xdd\x88\xe6\xec#\xc2\xb5\ -(\xf6<\x12\xc7J\x5c\xae\x11\xdeo\xe0\xb8\x0f\xbfm\ -\x83c\xa5{\x99\xbba\x1a|\xcfJ\x0bx\x01\x5c\xe8\ -\x94\x0c\xe07\x8e\xd8rp\xce\xfd\xff\xfe\xed/W\x00\ -\xfbjl\xb3\xf1y.~\x93\xe9$\x80k<\x17\x00\ -t\xe3{(\x1b\x01\x8c3\x10\xc04-\xa1\x0b\xae\xaf\ -\xe3\xb7\xbe\xd8\xd7\x80\xff\x06^\xeb\x82\xf5\x9d\xfd\xed\xbb\ -\xb6\xd6\xe7\xdf\x0a\xd6\xfb\xff\xf7\xb6\x87\x87\x87\x87\x87\x87\ -\x87\x87\x87\x87\x87\x87\x87\x87\x87\x87\x87\x87\x87\x87\x87\x87\ -\x87\x87\x87\x87\x87\x87\x87\x87\xe7\x1f\x81\xf0%\x8a\x08\xe1\ -\x97\x82?\xf2\x92\x80\x88\x187!\xf9/\x09k\xdd\x96\ -\xa8\xff\x03;\xbc\xca\x99\ -\x00\x00\x087\ -<\ -?xml version=\x221.\ -0\x22 encoding=\x22UTF\ --8\x22?>\x0d\x0a\x0d\x0a \x0d\x0a \ - icon / o\ -utliner / slice \ -/ not active - s\ -aved\x0d\x0a \ - Created \ -with Sketch.\x0d\x0a <\ -/defs>\x0d\x0a \ -\x0d\x0a \x0d\x0a <\ -path d=\x22M3.11645\ -814,1.98491547 C\ -1.81085731,3.256\ -48192 1,5.033548\ -03 1,7 C1,10.691\ -145 3.85693233,1\ -3.7150177 7.4801\ -6927,13.9809903 \ -C7.55923919,13.9\ -867947 7.5433296\ -9,11.4601372 7.4\ -3244079,6.401017\ -95 C4.76920501,3\ -.70741298 3.3305\ -4412,2.23537882 \ -3.11645814,1.984\ -91547 Z\x22 id=\x22Com\ -bined-Shape\x22>\x0d\x0a \ - \x0d\x0a <\ -path d=\x22M14.9826\ -165,6.50282053 C\ -14.7276121,2.868\ -84654 11.6988335\ -,0 8,0 C6.821531\ -33,0 5.71107957,\ -0.29121506 4.736\ -68211,0.80560781\ - C5.52211072,1.5\ -7704166 8.929157\ -37,4.97484587 10\ -.4514738,6.50452\ -22 C10.82345,6.5\ -0282053 14.72604\ -01,6.5045222 14.\ -9826165,6.502820\ -53 Z\x22 id=\x22Combin\ -ed-Shape\x22>\x0d\x0a <\ -path d=\x22M12.3449\ -55,7.6097276 C12\ -.344955,7.609727\ -6 13.3370708,7.7\ -3374209 14.60803\ -62,8.42756253 C1\ -4.2393452,8.7623\ -7994 12.344955,1\ -0.6534218 12.344\ -955,10.6534218 L\ -12.344955,7.6097\ -276 Z\x22 id=\x22Trian\ -gle-2\x22 transform\ -=\x22translate(13.4\ -76496, 9.131575)\ - rotate(90.00000\ -0) translate(-13\ -.476496, -9.1315\ -75) \x22>\x0d\x0a \ - \x0d\x0a \x0d\x0a \x0d\x0a\x0d\x0a\ -\x00\x00\x05(\ -<\ -?xml version=\x221.\ -0\x22 encoding=\x22UTF\ --8\x22?>\x0d\x0a\x0d\x0a \x0d\x0a \ - Artboard\ -\x0d\x0a Created with\ - Sketch.\x0d\ -\x0a \x0d\x0a \x0d\ -\x0a \x0d\x0a <\ -/g>\x0d\x0a \x0d\x0a<\ -/svg>\x0d\x0a\ -\x00\x00\x05\x14\ -<\ -?xml version=\x221.\ -0\x22 encoding=\x22UTF\ --8\x22?>\x0d\x0a\x0d\x0a \x0d\x0a \ - Artboard\ -\x0d\x0a Created with\ - Sketch.\x0d\ -\x0a \x0d\x0a <\ -g id=\x22lock_on_No\ -tTransparent\x22 tr\ -ansform=\x22transla\ -te(3.000000, 1.0\ -00000)\x22 fill=\x22#E\ -9E9E9\x22 fill-rule\ -=\x22nonzero\x22>\x0d\x0a \ - \x0d\x0a \x0d\ -\x0a \x0d\x0a\x0d\x0a\ -\x00\x00\x07o\ -<\ -?xml version=\x221.\ -0\x22 encoding=\x22UTF\ --8\x22?>\x0d\x0a\x0d\x0a \x0d\x0a <\ -title>icon / out\ -liner / visible \ -/ mixed state - \ -hover\x0d\x0a \ - Created\ - with Sketch.\x0d\x0a \x0d\x0a\ - \ -\x0d\x0a \x0d\x0a \ - \x0d\x0a \ - \x0d\x0a \ - \ - \x0d\x0a \ - \ -\x0d\x0a \ - \x0d\x0a \ - \x0d\x0a \ - \x0d\x0a \ -\x0d\x0a\x0d\x0a\ -\x00\x001/\ -\x00\ -\x01\x04 x\x9c\xed=\x07@SW\xd7\xf7%\xec\xa5\ -lpF\x147#\xcc$\xa8\x88\xb8P\xa9\x0a\x8a\xa3\ -\xfaIH\xc2\xd0\x90`\x12\xdc\xab\xcb~\xd5\xd6\x81\xd6\ -]m\xd5\xda\xaa\xd5\xd6Zg\x9d\xe0.8\xab\xb6\xda\ -\xe1\xde\x0a8\x90\x99\xfc\xe7\xbc\xe4a\x8c\x8c\xa0Q\xfb\ -\xf7\xcb\x0d\xe7\xbd;\xce=\xe7\xdcs\xef;\xf7\xdc\xfb\ -\x06\xb1\xb1\xa4-!\xc4\x86x\x115\xb1\x80\x18E\xb4\ -\x076}J\x84\x03\xa5\x17g\xd1q\xc0\xa3\xfc)\xb6\ -.\x1f\x90)+]\x9c\x05\x07g\x86\xce\x90\x06\x94\x8b\ -\x1e\x8e\xbb.\x8e\xb5=\xf4hz2\xf8s\x08\xd5\x80\ -Xj\xe3T\x18\xd5\xb02\xde\x89j\xa4G\xa7\xb5\x1e\ -/.\x1e\x89\x0f\xc4\xbaSAt\xdc\x0d\xe2\xa9T\xdc\ -3|\xd6.\xa7\xe7\x0d\xc3x\ -\x83_!\xbf'\xea\x05\xf4\xa4\xfd\xd9\x95O#\xa4U\ -}\xe6\x1c%\x96'I8\xfdR\xe5*\xb92U\x9e\ -\xc1\x89\x8e\xe6\x04\x05r\xc39\xad\x07\xa5\xc9\xc4\xf2\xb1\ -\xca6\x04\x93\x82\xc0\x10\xf8\xe3p\xb9\x82 \x9e\x80\x1b\ -F:D\x8e\xcb\x10\x8aFIT\x9c$IJ\x9a\xac\ -\xa3O\xfe\xcf{}8i\xe2\x8e>\x83Bc\x03c\ -3\xa2%\xa9i='($\xf1\x13\xde\x19 \x9a0\ -J\xc4\x17\xfbDv\xb2\xeb0N0.=#]\xa2\ -\x12r\xc6\xa5KeJ\xc1\xb8\x8e>B\xe4/\x808\ -f\x07\xf8ph\x14\xd5\xa8\x8e>Z\xc1\x06\xc7\xf6\xe3\ -D\xcb\x15\x12N\xa8\x7f\x98\x9f\x88\x1b\xcc\xe3\x84\xf3\xfd\ -\xb9\xa1|^PH{\x144, \x90\x1f\xc0\x0d\xf1\ -\x0b\xe4\x0a\x02\xf9\x82@.G\x17|:\xd9\xc1\xb1\x83\ -B\x9c,\x88\xeb\xda]\xc7\x0eR\x1d}RU\xaa\x0c\ -A@\xc0\xd8\xb1c\xfd\xc7\x06\xfb\xcb\x15)\x01\x5c>\ -\x9f\x1f\x10\x18\x14\x10\x14\xe4\x07\x18~\xca\xf12\x95p\ -\x9c\x9fL\xd9\x5cK\x84\xa1\xd3U\xa2\x14)\xd22T\ -ir\x19\x07\xd3\xc2$y\xa6\xaa\xa3\x8f\x8f\x1dG/\ -\xe8\xda\x95\x9eQ\xc9H\xa6\xf4\xa7\xdb\xe8/\x92\xa7\x07\ -\x8c\x13f\x04p\xfd\x03\x03\xaa\xaa$\x16U\xd6\xc9\xc8\ -THi\xd1\xc4\xa2\x00\x89T\x92.\x91\xa9\x94P\x8f\ -[e\xbd\x0c\xa6\xef\xaafYY\x5c-c\x9066\ -\xb6fy\xd3\xd3\xab\xac\xa9Tu\x1b\xa3\xaa\xb9\xa6r\ -\xc0\xf8\x0cI@\x9cD)\xcfT\x88$\xdd\xc6@S\ -\x9e\xe9\x15U\x0b\xdc\x05\xd1\x0a\x89P%\xe9\x0a\xd0\x09\ -G\x9b_`\x90_`\xf0\x00n\xa8 0L\x10\x14\ -\xea\x17\xc8\x13\x04\x06v\x080\xc04\xa0\x11+\x17\xa7\ -%\x8f\xd7\xa3\x01\x83\x22d\x003b\xfd\x02\xc3+i\ -\xe8a\x1a\xd2\x801(\x16\xaa\x84FQ\xd1\xc7\xad\xaa\ -=r\xc5\x00\xb9\x5c\xda\xa9\xd6\x0bL\xafa\xba*z\ -\xd4\xc4\x22A\xb2\x5c\x91.TuJK\x17\xa6H\x02\ -Ti\xc9\xc9\x1d\x02\x9e\xe5\xea\xa1Vv\xb4 Z.\ -\x95+\xa0\x95\x92N\xc1\x1d\x02\xaa\xca\xae\xb2VLt\ -t?\x85<9M*\xe9\xa4\x8c\xeb\xd1\x85\x13\xd3-\ -:\x8c\xcb\x0f\x0b\xf3\x0b\xf2\xe7\xea\x93\xd1\xc3\xab\x92N\ -W\xb9(\x13Gl\x94L$QB\x93\x94\x9d\x9e\x1b\ -9\xf4\xb5\xd4E\x98\xf2|.S M\xeb\xa4\xb5\x08\ -b\xb9(M\xfcll\x0b\x84\x22\xa1D\x12\x92\x9c\xec\ -\x07\x22\x05\xfaq\xb9\x92p\xbf$!\x1c$a\x92p\ -a\xa8H\x1c\xc4\xe3\x86t\x08\xd0\x91\xa8\x8e4(\xda\ -_\x0cd\x93\x93C$a\xc1\xbc0?Ir\xb0\xc4\ -\x8f+\x09\x91\xf8%\x85\x8bx~a\xc2\x90PIx\ -pRP\xb8H\x5c51m\xee\xf3\xe2\xeb+\xa7\xa6\ -\xc6w\xa0/4A\x8cL\xa9\x12BqLWZ\x9e\ -4\x90\x87\x1f\x1a,\x11\xf3\xf9\xc9~ S\xb2_R\ -(\xc8#\x0c\x0a\x0c\xf3\x13\x06\x07\x07qy\x81a\x10\ -\x0f\xa1\x87\xc9\xf3\xd5_ \xcdp\x87\xb2\xaa\xb5\x18\x1e\ -\x12\x1c\xce\x0b\xe2\x89Q\x8b!Z-\xf2D!I~\ -\xe2\xb0d\x89(\x5c\x98\xc4\x0b\x16\x051\x8c\xf4\x88\xbd\ -\xc0\xa8\xaf\x22\x0d\xcc\xbeP\xaa\x87S\xa9[Qp\x90\ -$\x9c\xcf\xf3K\x16's\xfdB\xf9!b?~h\ -2\xdfO\x18\x12\xc6\x0d\xe7\x86'\x85\x09\x85\xe1\x0c\x8b\ -*\xc8\xbc\xc0\xaag\x1a\xeaq|\x15\x83(^2\xba\ -\xba\x9e\xa6\x0dt\x86P\xa1\x94\xa0\xf9\xe9\xe8\xc3\xd8\x1f\ -\x9f\x17*`\x1d\xda\x8c\xc1\x08C\xd3\xdeID[\x18\ -\xe8\xfe\xe7r\xab\xaf\x96\xf6bw\x1a\xa7\x82\x17\xaaW\ -\xcfcl\xaaDV\x93e\xd4\xc3\xaa\x9e\x88R\x9e\xac\ -\x1a+TH\xa2R@\xd3\xc6\x98\xa5\xaa\xaa\xbd\xa0\xef\ -Z.\xb9W\xe8\x08\xa5p\xcc\xabuCprxX\ -\x92\x04\xac6O,\x0a\xf2\x13\xf2B\xa0\x07P\x87\xe1\ -\xa1\xdc\xe0\xe0\xf0 a\x08\x97+~\xb5n\x80>\xe0\ -\x0aB\xb8o\xbf\x1b\x9e\x91\x17\xa5\x0ae)\x12q\xa7\ -\x00\xa6\x22\x93\xf1\xff\xa9\xe7\x8c\xb3\x87/\xd7sUN\ -\xe8\xff\x82\x9e\xd3\xe6>o\x13\x19;k`C\xb5\xa8\ -z\xfe\xac\xd6Y\x0e\xd0y\xcb\xe0\xa8\x07Tz\xeaU\ -\x09l\xfa`fbfbfbfbfbfb\ -fbfbfbfbfbfbfbfb\ -fbfbfbfbfbfbfbfb\ -fbfbfbfbfbfbfbfb\ -fbfbfbfbfbfbfbfb\ -fbfbfbfbfbfbfbfb\ -b&v\xcf\xde}\x95\xc8\xc4\x1d}\xc6\xfaDv\x22\ -\x8d\xa8\xa1\x84\xdd\xd0\xb7G\xe5\x99E\xe8Wzy]\ -bb-|\xe9\xf7o\xeb\x1f\x1e\xeey]\xb5E\xf6\ -\xe4\xe2\x1e\xfe\xfc}\xb7\xc7\x0f\xa3\xcb\x04t\xd9u,\ -g\xde`&\xf6\x19\x8a4\x99\xaao\xa6*#S\x05\ -I|\x95\x98\xf4S\xaa\xe2\x93\xe4r)\x8d\x11#S\ -I$\xb2\xcct&\x8e\xe7h\xa9\x02\xd3\xf5\xe8\xba\xf1\ -i\xe3\x10\xa3K\x9a\x0a\xeb<\xa3)Q\xbc#L\x97\ -\x0c\xe86x@%3m\x85~\x0a\xb9<9^\xa2\ -\xca\xcc\xe8\x9b4R\x04\xd9\x0e\xa4\x1fQ\x109\xfc\x92\ -\x09\x87\xc4\x13\x09Q\x91L\x92AW\xb1\xcb\xa8\xc4f\ -\xc8t\x91\xaad:\x89\x1c\x922\xd3\xa4\xaa4\x19M\ -\x12\xd2\xb64vt\xec\x90\xdeZmD >\xcb\xef\ -\xb9\x16\xbb\xe8\xb5\xb8/\xfdF\x82R\xfb\xae3\xb4+\ -C%c\x1a\x01\x8dLRT&\xe2R\x94\xb1\xcfJ\ -\x14\xb2\xe8g\x09\x99\xeaY\xa2O\x92TY\x99x'\ -E5\xa62\xd1-]\xda\xb52\x01z|F\xba\x8b\ -hT\x8aN\x11Z\x01I\x5c\x8f.\xd1D\xfbj9\ -\x89\x13s8byfRg\xf9%\xc2\x84\x1e\x0a\xd9\ -\x0by]\xa4/\xe2uQ\x88\x07\x0c\x94\xa9\xba7\x8f\ -\x93\xaa\x88^\xe8\x22\x15s\xaa\xca\x8fSJUt~\ -\xbfq\xd2\xceq\x95\xd9vc$\x22\x95\x5c\xd1U\xa8\ -\x12V\x8e\x8a~)\xfd\x94\xcc\xa8\xc0\xb8\xee\x1cM+\ -A\x92\xac\xaa\x8a\xfc\x00yF\x95l\xe3ERm~\ -?\x85\xa8\xf3\x90\xca\xec\xfa\x22\x85?\xf0\xeb\xb5\xc7_o\ -9x\xf6\xfa\x93\x84\xe41\xd3\x17\xac\xd9z\xe8\xdc\x8d\ -\xa2\xf0\x1e\x83R\xc6~\xbc\xf0\x9bm\x87\xcf\xdf|\xea\ -LX,\x90\xd6\x82\x96\xc9\xda\xca2\x94\x16\xa1\x19\xd7\ -\xc5\x02$\x18\xed\xe3j\x19\xf4\xde\x5c7\x94`\x7f\xdc\ -\xa9\x82\xe0\x16I\x97\x15\xefgE\xc7\xbb\x8b\x94!\x85\ -\xbeV(\x80u\xcb\xd0\xec\xd3 \xc4*Oq\xb7\x81\ -a*\xc9\x95J\x11\xaa\x97\xa0\xd53\x114\x17\x88\x03\ -\x9b\xe6\xe9L\x22\xc9\x93\x86\xf9\x12\xf7\x85{g\xe5\x1c\ -X\xd7j}\xf1\xc0b\x0d\xd9\xd4w}\xd3S\xe7:\ -\x9c\xb86\xe4\xec\xb9\xbbM\xbc\xf6\xfbw\xb0\x98\xffW\ -\xc5\xc6\xa9\xa7\xa6D\xde\xeb]\xb4CC\xba!\x12\xbb\ -h\xcc\x88\x07S\x9a\x05\xfc\xfe\xfb\xd4\x1d\xc5\x1f\xce_\ -QY\x10p\xe1f\x85\xe7U\xf5\x81z\xda\x92\xbd)\ -\x12\xf5\xcd+.qSu\xd9{G\xadx\ -\x9a\xea\xb2.qj\xef\xef\xafLm\x16\xf3\xce\x02Y\ -|\xea\xc6\x90\x80\xa9\xa7\xd2\xca7\x0e>6\xf6\xc2\xdd\ -\x0d\x99\xb3\x1e\xa8\x9a\xb0\x7f\xe8\x17\xd3k\xe8\xe0P\xe1\ -\xe0\xfd\x8e\x7f&\x96F]P7\xed1\xf2\xfb\xcf>\ -*\xfatl\xc75M\x1a\x93&\x0e\x166[gF\ -l\xba\x1f\x13\x13\xbc\xe8\x9c\xa4\xe3w\xd4\x06g2z\ -_\xe7\xeeO\xaf\xff\x11\xe37\xea\xcfF\xb7\x1c\x1c\xd7\ -\xe6g\xef\x9cn\xbd\x87\xb3\xe8\xe4\xea\xd5~\xcaE\x97\ -n,\xca\xf8\xb5\xfe\xd6\xc0\x87\x87\xa2CO\x1f\xaah\ -\xa6!S\xec\xbd\xdf\x99\xf9E\xec\x86\x1f\xc6\x08f;\ -\xff\xd1bM\xad\x8d9]sc\xfa(R3=\xf9\ -\x1f\xcf\x1a:\xa9\x8b\xcb\x1f\xc7\x0e\xc9\xbaM|gV\ -\x83-\x7fY&\xfd\xfe\xee\x9d\xf1\xa2\x03\xbc\x16\xdfD\ -\xaf\xbe\x10\xb6g\xe3\xa5\x07M\xe7\xac\x1f\xc2\xdbr-\ -\xac\xf1\xaa\x8fOe\x5ck?\xf4\xdedy=\xe1\xc7\ -Nv\xa7\xd7\xaf\x8b\xbb\xd4\xb1\xdf\xe0\x07\xd7F\xba\xc4\ -\xaf\x98\xd2q{\xfe\x85\xc2oR\x9c\xec>_\x9c\xf0\ -{\xe7\xaf\xd5\x97\xce4\xfb\xb3\xf8#e\xaboE\x9d\ -~\xdc\x97#.\xbe\xd5)r\xd7\xe6\xb8\xb8\xb9\xa3\xbf\ -\xcd|\x1a\xfa\xc1\xaca\x93X.\xbf\xef\xdb\xb8\xa0\x9f\ -cW\xde\xcf\xb7#N\xec\xf7\xe5\x8f\x1fqZZc\ -\x93\xce\xd4\xd2?\x17<\xba\x87\x0eq\xbcP\xf8\xed\xe5\ -\x9c93\xb2z\x8d\x96\xef\xdb3\x8f\xbb{\xc5\xae\xbf\ -\xaf\xb8g\x9ej-X\xb2\x5cro\xd4\xecO\xc8\xea\ -o\xa8\xc1\xab\xac\xca\xfe\xcb\xdd\xb4bW\xfe%\x8f\x9f\ -\xd3\xd6N\x1f|\xe8\xa7\xe2i\xac%\xbd\x14\x0f'\x08\ -E\xe1q\xbd/M\x5c2\xbex\xcb\xc0\x95e\xa9S\ -nx\x15\xa6]*Ox\xb8\xf6\xf3i\xbf\x1c/\x9a\ -\xd8\xf4\x8f\xa26m\x8emQ\x7f=kR\xf7\xab\x81\ -?\xed\xd4\x0ak/\xb8a5\xb4\xc8\xa9A\xe2\xa4\x05\ -\xb3{\xa9\x85\x7f\x9fSS\xbe\x91\x9a_\x1f\xcb6\x94\ -\xff9\xd5e\xf3\xe0\xa7\x09\x97\x8a\xbc2.m\xb8\xb8\ -V\x92\xdb~\xaa\xdd\x8a{K4\xe4t\xd3\x1d\xbe\xa1\ -\x9d\xfe^\xa8\x9eS\x91S\x96U6eDi\xf4\xd3\ -z\x0f\x124D\xbc\xb9\xa2YYVE\xd6\x89\xc7\x1f\ -?\x88\x89\xed\xbb\xed\xba\x86\xac\x8e\xccP_\xdb\xa3\xc3\ -\xfd|\xef\xef\xed5\xa4\xe7\x94k{\xb5\x98\xf1\xf1\xf7\ -K\xa6\xde\xae\xf7G\xe4\x8e\x00\x06\xf7\xba\xbc\xa8w$\ -0\x08\xd0a\xce\xff\x95\xa1\xdf\x9b\xc1}W\xcb\xa0\xb7\ -\x16\xd1\x97\x7f\x5c\xb9\xfc\xcaM\xefVq\x09\xdf\xf4j\ -\xfa\xe5\xd8\xa5{\xa7\xf5o\xdcr\xc7\xd9k\x1f)v\ -\xfe\x1e\xcf\xf6j\xf6\x15\xb4\xe7w\xed\xac\xd7\x8c\xb6\xeb\ -\xc3\x09\xed\x9f\xc2\ -i29\x0b\x5c\xcatX\x8f\xe2Wx\x06\x0f\x19\xca\ -\xb1>\x0e.\xa5-x\xb2\xe0<\x09E\xca\x8c\xd8\xf8\ -\xee\x03hW\xab[4\x07?\xd5C\x9e\x0bE\xe7\xb4\ -\xce\xca\x19\xbf\x9e\xfd8\x1cR\xb7\xe0,\xcaP\x80+\ -B\xf5\x83x\xb0X\xa2\x04\xe7\x8d\xfa\x10\xe2\xd2\xb1\xaa\ -\x0c\xccGO\xc0-i\x14\xc6Y\xe8\x03\xb8)@@\ -\x88{a\x83\xa4\xa7\ -\xa8\x1a\x0b\x8d\x0c\xd8\xb7\xda\xd8\xa3\xfet\x9fQ\x1e\xb9\ -\xcf\xf2\xaa\xc2\x93\xaf\x04/\x0c\xd6\x84\xec9\xcf\xf2\x92\ -\x16\x13\xb2\xed#B\xbc.<\xcbk\xf1%\x8cQ\xe8\ -\xb7\xad'\xf4\xda\xe3\x81\xe3E\xef\xf3gi\x12\x91?\ -*\xb42\xd4\x8a`D\xd0\xe3\xe7\x8f\xe4*\xd5\xc3\xe9\ -\xaa\xf5s9\xa87\x11x\xb3\x99\x0a\x0e\xac\xc7E\x12\ -\x8e\x9f\xe1 ~\xe9\x8aU\xcb\xd1>N\x92,\xc1u\ -\xbf\x84\x93\x00\xa3,M\x96\x02\xdd-\x13\xa7\xd1_r\ -K\x93U\xd7\x89/Y\xcd h\xc75\x04\xd7\xd5j\ -\xe26\xc2\x9f\xd4?\xe1F\xd8\xf7s\x89\x85\xab=a\ -\x0f[\x0e%Te\xbf\xf5\xb1M x\xe5\x0djz\ -S;\xee\xe9P\xc5\xa2\x935\x1b\x0f\xca4z\xa9E\ -\xa2\xe3\x06pD\x99\x8a1\xda2zueI\xec\xc0\ -H\xb9\x11o\xd2\x844'\xad\x89\x1f\x18\x9ap\x12A\ -:\x93n\xa4\x17\xe9K\x06\x90!\xe4?D\x04\xc6(\ -\x9d(\xc8X2\x89\xbcG\xa6\x93\x99d\x0e\xf9\x9c,\ -!+\xc8j\xb2\x96l$?\x92md\x17\xd9O\x0e\ -\x91_\xc8Ir\x96\x5c$\x97\xc8ur\x97\x14\x90\x22\ -R\x06\xee\xae5\xe5H\xb9R\xdeTS\xca\x97jG\ -\x05Q<\xaa\x13\xd5\x8d\xeaC\xc5QC\xa8D*\x85\ -\x92Q\x99\xd4$\xea\x03j&\x95E-\xa1\xbe\xa2\xd6\ -R\x9b\xa8\x1d\xd4~\xea(u\x8a\xfa\x9d\xbaL\xdd\xa6\ -\x1eR\xa5,6\xcb\x81\xe5\xc6j\xccj\xc9\x0a`\xf1\ -XQ\xac\xde\xac\x01\xac\xe1\xac\x14\xd6h\xd6\x04\xd6\x87\ -\xacY\xacE\xac\x95\xac\xefX[Y\xfbY\xbf\xb0\xce\ -\xb2.\xb1\xee\xb2\x9e\xb0\x09\xdb\x9e\xed\xc1n\xc6\xf6c\ -\xf3\xd8\xd1\xec\xbe\xec\xa1\xecd\xb6\x82=\x85=\x83\xbd\ -\x80\xbd\x92\xbd\x91\xbd\x93}\x98}\x86}\x89}\x8f]\ -bae\xe1j\xc1\xb1\xf0\xb3\x88\xb0\xe8i1\xd0B\ -d1\xdab\x8a\xc5\xa7\x16K,\xbe\xb5\xd8jq\xc0\ -\xe2\x8c\xc5e\x8b\x02\x0b\xb5\xa5\xa3e#\xcbv\x96\x02\ -\xcb\x18\xcb\xc1\x96)\x96c-\xa7[.\xb0\x5cc\xb9\ -\xc5\xf2\xa0\xe5Y\xcb\xeb\x96EVVV\x1eV\xad\xac\ -\xc2\xadzZ\x0d\xb1\x1ai5\xd1\xeaS\xab/\xac\xbe\ -\xb7\xdagu\xca\xea\xaa\xd5\x13kkko\xebv\xd6\ -\x1d\xad\xfbZ\x0b\xadU\xd6\xd3\xad\x17[\x7fg\xbd\xd7\ -\xfa\xb4\xf5u\xebb\x1b{\x9b\xa66A6\xddm\x86\ -\xda\xc8l\xde\xb7Y`\xb3\xcef\x8f\xcdi\x9b\x9b6\ -e\xb6\xf5m}m\x05\xb6}m\xc5\xb6\xe3mg\xdb\ -\xae\xb6\xddi{\xc2\xf6\xbam\x99\x9d\xb3]+\xbb\x8e\ -v\x03\xecF\xda\xbdg\xb7\xc8n\xa3\xddA\xbb?\xec\ -\x1e\xd9\xdb\xdb\xfb\xd8\xf3\xed\xfb\xdb\xa7\xd9O\xb3_d\ -\xff\x83\xfd\x11\xfb\xcb\xf6%\x0e.\x0em\x1d\xa2\x1d\x86\ -9d:\xccr\xf8\xc6a\x9f\xc3\xef\x0e\x8f\x1c\x1d\x1d\ -[:vv\x1c\xea\xa8r\x9c\xe5\xb8\xd61\xc7\xf1/\ -\xc7b'W'\x7f\xa7\x18'\xb1\xd3T\xa7\xa5N[\ -\x9dN;=\xa8g[\xcf\xb7^T\xbd\xff\xd4\x9bP\ -oA\xbd\xcd\xf5N\xd4\xbbW\xdf\xb6~\xcb\xfa\xd1\xf5\ -\x85\xf5\xa7\xd4_Z\x7fG\xfd\xf3\xf5\x9f8\xbb:s\ -\x9d\xfb:\xa7;\x7f\xea\xbc\xce\xf9\xa8\xf3-\x17k\x97\ -\x96.\xdd\x5c\xc4.\x1f\xba\xacr\xc9q\xb9\xea\xcav\ -m\xee\x1a\xed*r\xfd\xc0u\xb5\xebA\xd7\xebnV\ -n\xad\xdcb\xdcF\xba\xcdt\xdb\xe0v\xdc\xad\xc0\xdd\ -\xc5=\xc4=\xc1}\x9c\xfbR\xf7\xdd\xee\x97<\xd8\x1e\ --=b<\xa4\x1e\xb3=~\xf48\xe7Q\xea\xd9\xd8\ -3\xcaS\xe2\xf9\x89\xe7F\xcf\xd3\x9eO\xbd\x1azu\ -\xf6\x92x\xcd\xf0\xfa\xde\xeb\xacW\xa97\xc7\xbb\x9b\xf7\ -(\xef\xb9\xde\xdb\xbc\xffl`\xd1\xa0m\x83\xfe\x0d\xc6\ -6X\xde\xe0`\x83{\x0d\xdd\x1aF4\x145\x9c\xd1\ -\xf0\xc7\x86\x17\x1a\xb1\x1a\xb5m\x14\xd7hb\xa3U\x8d\ -r\x1b=i\xdc\xa4q\x8f\xc6\x19\x8d\x177\xcei|\ -\xaf\x89G\x93\xceMF6\x99\xdfdO\x93\xdbM]\ -\x9bvj\x9a\xd6t~\xd3\xbdM\xefp\xdc9Q\x1c\ -)g\x11\xe7\x00\xa7\xa0Y\xa3f=\x9be6\xfb\xaa\ -\xd9\xf1fe>\xad|\x06\xfa\xbc\xef\xf3\xbd\xcf\x9f\xcd\ -\xed\x9a\xf3\x9a'7\x9f\xdf<\xbbyA\x8b\xa6-b\ -[Lj\xb1\xbe\xc5\x05_[_\x9eo\xaa\xefB\xdf\ -\xc3\xbeO[\xb6j9\xa8\xe5\xc7-\xb7\xb5\xbc\xd5\xca\ -\xabUL\xab\x09\xad\xd6\xb7\xfa\xa3\xb5c\xeb\xc8\xd6\xa3\ -[\xafl\xfdk\x1b\xab6\xbc6\xa3\xda|\xd1\xe6d\ -[V\xdb\xd0\xb6\xa9m\x97\xb6=\xd1\x8e\xd5.\xac]\ -Z\xbb/\xda\x9djo\xd9\x9e\xdf^\xd6~e\xfb\xf3\ -~\x0e~Q~c\xfc\xd6\xfb]\xf6\xf7\xf0\xef\xe3\xff\ -\xbe\xff6\xff\x07\x01-\x02\x86\x06\xcc\x0d8\x1c\xa0\x0e\ -\x0c\x0d\x94\x06\xae\x0e\xbc\xc8u\xe1\xf6\xe2\xbe\xcf\xdd\xc9\ -}\x18\xd46H\x14\xb44\xe8\xd7`\xc7\xe0\xee\xc1S\ -\x83\xb7\x07\x17\x86\xb4\x0b\x91\x84,\x0f\xf9-\xd454\ -6\xf4\xe3\xd0\xec\xd0\x8a\xb0\xf00E\xd8\xc6\xb0\xdb\xe1\ --\xc2\x13\xc3\x97\x85\x9f\xe7\xb9\xf1\xfa\xf1>\xe5\x1d\xe1\ -[\xf2\xbb\xf0\xa7\xf2w\xf1K\x04a\x02\x95\xe0GA\ -~\x84_\xc4\xa8\x88u\x11\xb7:\xb4\xea \xe9\xb0\xba\ -\xc3\xd5\x8e>\x1d\x85\x1d\xbf\xeax\xa9\x13\xa7Sb\xa7\ -/;]\x8al\x16)\x8c\x5c\x19y\xa5s\xf3\xce\xe2\ -\xcek:\xdf\x8cj\x1352\xea\xbb\xa8\x07]\x02\xbb\ -(\xbal\xe9\xf24Z\x10=9z_Wv\xd7\x1e\ -]gt=\xde\xcd\xa5\xdb\xc0nK\xba\xfd\xd5\xdd\xa7\ -{J\xf7\xf5\xdd\x0bz\x84\xf6\x98\xd8c_O\xcb\x9e\ -\xbd{\xce\xedy>\xa6q\x8c(fmLA\xaf\xf0\ -^\x93{\x1d\xe8\xed\xd0;\xbe\xf7\x92\xdeW\xfa\xb4\xed\ -\xa3\xe8\xb33\x96\x15\xdb+v^\xec\x1f\xef\xf8\xbe#\ -{g[_\xd27\xa6\xef\xbc\xbe\x7f\xf6k\xd5ot\ -\xbf\x9f\xfb[\xf5\xef\xd7\x7fi\xff\x1bq\xdc\xb8Iq\ -\x87\xe3]\xe3G\xc4\xaf\x8b/\x1a\xd0e\xc0\xec\x01\x17\ -\x07\xb6\x1e\x9890;\xa1^\xc2\xb0\x84\xb5\x09O\x07\ -u\x1d\x945\xe8\xd2\xe0\x80\xc1\x93\x07\xff2\xa4\xc1\x90\ -\xb4!\xdb\x87Z\x0fM\x18\xbaf\xe8\x93w\xbb\xbd\xfb\ -\xf9\xbb\xd7\x87\x85\x0e\x9b>\xec\xdc\xf0V\xc3\xc7\x0d?\ -\xfa\x9f\x06\xff\x91\xfeg\xf7\x88z#\x84#6'Z\ -&\x0eJ\x5c\x97X.\xec+\x5c)|\x92\x14\x93\xb4\ -,\xa9@\x14-Z(\xba+\xee,\x9e/\xbe-\xe9\ -(\xc9\x92\xdcL\xee\x98\x9c\x95|+\xa5c\xca\xbc\x94\ -\xdb\xa9\x91\xa9\x0bR\xef\xa5E\xa7-I+\x1c\xd9s\ -\xe4\x8a\x91OG\xf5\x1d\xf5\xcd(\x8dt\x90\xf4\xfbt\ -\x9b\xf4\xc4\xf4\x1d2\x17\xd9(\xd9\x01y\x13\xf98\xf9\ -\xa9\x8cv\x19\xd33.\x8d\x16\x8c\xfe|t\x81\xa2\xb7\ -b\x8d\x92R\x0eWnW\xb9\x813\x95\x9b\xd9:\xf3\ -\xa3\xcc\xcbc:\x8dY:\xa6xl\xc2\xd8\xcd\xe3\x9c\ -\xc7\xc9\xc6\xe5\x8eo;\xfe\x93\xf17't\x9f\xf0\xf5\ -D\x8b\x89\xa2\x89\xd9\x93\x9aMzo\xd2\xe5\xc9Q\x93\ -\xbf\x9aBMI\x9a\x92=\xb5\xf9\xd4\x0f\xa7^\x9f\xd6\ -c\xda\xb7\xef\xd9\xbd7\xea\xbd\xbc\xf7\x03\xdf\xcfz\xff\ -\xf1\x07\x83>\xd8\xf9a\xe3\x0f\xa7}x\xf5\xa3\x1e\x1f\ -\xad\x9f\xee4]1\xfd\xfc\xc7\x11\x1f\xaf\xf8\xaf\xc5\x7f\ -\xd3\xfe{\xfc\x93\xe0O\x16\x7f\xa2\x9e!\x9eqlf\ -\xe0\xcc\x053\xcb?\x15}z\xec3\xeeg\x8b>\xd3\ -\xccJ\x9eu|v\xd8\xec\xe5s\xac\xe6\xc8\xe6\x9c\x9b\ -\x1b9\xf7\xdb,\xe7\xac\x09YW\xe7\xc5\xce\xdb:\x9f\ -3\x7f\xc6\xfc\xc7\x9f\x8f\xf8\xfc\xe8\x82\x90\x05+\x16\xda\ --\xcc\x5cxiQ\x9fE\xdb\x17\xb7XY\xf6\xf4\ -\x0b\xf1\x17\xa7\x97w^\xbeqE\xe3\x153W\x94~\ -\x99\xf6\xe5o_\xf5\xf8j\xeb\xca\x96+\x17\xac\xb2Z\ -5f\xd5\x8d\xd5\x09\xab\x0f\x7f\xcd\xfbz\xed\x9a\x06k\ -f\xae\xa9\xf8F\xf6\xcd\xa5o\xe3\xbe=\xb06|\xed\ -\xdau\x8d\xd6\xcd^\xcfZ\x9f\xb9\xfe\xf6w\xc3\xbe;\ -\xb9\xa1\xeb\x86\xed\x1b\xfd6~\xf5\xbd\xc7\xf73\x7f \ -?d\xfepgS\xe2\xa6s?\xf6\xfe1{3o\ -\xf3\xc6\x9f|\x7fZ\xb6\xc5u\xcb\x8c\xad\xd4\xd6\xf1[\ -\x0b\xb6\xa5n\xbb\xb4}\xc8\xf6S;z\xed\xc8\xde\x19\ -\xb1s\xcb\xcf\xfe?\x7f\xb3\xab\xd9\xae\xa5\xbb\xddw\xcf\ -\xdec\xb7\xe7\xc3=\x9a\xbd\x13\xf6>\xd9\x97\xb1\xef\xde\ -\xfe\x94\xfdW\xb3Gd_\xcc\x19\x9c\xf3\xeb\x81\xfe\x07\ -\x8e\x1f\xec}\xf0\xc8\xa1\xee\x87r\x0eG\x1d\xde{\xa4\ -\xe3\x91]G\x05Gw\x1c\xe3\x1d\xdb\xf6K\xd8/[\ -sCs\xb7\xe4\x85\xe6m9\x1ev|\xeb\x89\xf0\x13\ -\xdbO\xf2O\xee<\xd5\xe1\xd4\x9e\xd3\x91\xa7\xf7\x9f\xe9\ -z\xe6\xd0\xaf1\xbf\xfer\xf6\x9d\xb3\xa7\xce\x0d<\xf7\ -\xdb\xf9a\xe7/\xfd&\xfe\xed\xd6\xef\xd2\xdf\x0b/\x8c\ -\xb9Pvq\xda\x1f\x96\x7f\xcc\xf8\xb3\xfe\x9f\x0b\xfej\ -\xf4\xd7\xca\xbf\xdb\xfc\xfd\xfd\xa5\xb0K\xbb/w\xbd\x9c\ -{%\xfe\xca\xc5\xab\xa2\xabw\xaf)\xaf\x95_\xff\xf0\ -\x86\xe3\x8d\x057\x9b\xde\x5c{+\xe8\xd6\xae\xdb\xddo\ -\x9f\xbc\xf3\xee\x9d\xebw3\xee\x96\xdd\x9b~\xdf\xf9\xfe\ -\xb2\x07\xad\x1f\xfc\x94\xdf9?\xb7`p\xc1\xf5BE\ -\xa1\xe6\xe1\xa7\x8f\xbc\x1f}\xf38\xe4q\xf6\x93~O\ -\xfe*J/*{:\xa3\xd8\xbb\xf8\xdb\x12^\xc9\xe1\ -\xd2A\xa57\xcb\xc6\x96[\x97/\xaahS\xb1S\xdd\ -[\xfd\x87&\xbd\xf2\xfe\x849\x98\x839\x98\xc3?*\ -XXXX:9997h\xd0\xa0Y\x8b\x16-\ -\xfcZ\xb5j\xc5m\xd9\xb2e\x80\x1e\x04\x1a\x82\x01\x0e\ -\x9d\xd6\xe5\xe9\x97c<@\x0f\xf7\x85\xb2*\xea\x06\x18\ -\xe00\x10\xd0\xbau\xeb C>\x06\xf2\x050\xfc\xf4\ -\xf1\xaaJ\xd7\xc4\xcb\x10\xdf\xa0\xbdt=\xd4S\xd3\xa6\ -M[\xb9\xba\xbaz\xc1:\xc4F\xefN\x83\xd1\x01\xeb\ -\xd4\xaf_\xdf\xad{\xf7\xee\x83?\xf9\xe4\x93\xf5\xdf\x7f\ -\xff\xfd\xc5\xdd\xbbw\xdf\xdb\xb7o_\x01\xc2\xfe\xfd\xfb\ -\x0b\xf5\xc10/;;\xfbaU8\x0c^U4\xaa\ -\x02}<\xc3:\x0c=}\x9aU\xe1W\xc7\xab\xba\xba\ -\x8c\xecU\xd5\xc72\xc3|C:{\xf6\xecy\xb0u\ -\xeb\xd6kK\x97.\xcd\x16\x89D\x93|}}\xfd-\ ---\xadj\xd7\xfa\xb3\xe0\xe2\xe2\xe21j\xd4\xa8\xe9\ -@\xeb\xfe\xb1c\xc7*rss5f\xa8;\x1c>\ -|\xb8d\xf1\xe2\xc5{CBB\xa2\x8c\xed\x03\xbcf\ -\x12\x12\x12\xa4999\x8f\xdf\xb6\xfc\xff\x06\xf8\xe5\x97\ -_\xd4\x0b\x17.\xdc\xed\xe3\xe3\xd3\xd6\x18[\xd4\xb8q\ -\xe3\x16k\xd6\xac9\xf9\xb6\xe5\xfe7\xc1\xa1C\x87\x8a\ -\x13\x13\x13\xc7\xc1\xd8\xb6\xaeI\xf7,\x08\x91\x91\x91}\ -\x0f\x1e\xae\x0dj\xd2\xbf\xb5\xb5\ -\xb5\xadJ\xa5\x9ak\x0a\xfd\xff\x93\xfb\x10ec\xe0M\ -\xc9\x8d\xfao\xde\xbcy\xfb\xda\xc6\xbf1\xfa\xc7r\xf0\ -\x91N\xe0\x1ac\xd9\xb2e9x\xfe\xe2\x8b/\x0e`\ -\x9c93q\x04\x98{\xf63y\xfau\xf4\xe3\xfa\xf8\ -L\x19\x93\xaf\x0f\xfayU\xc5\x99z\xfa<\xf5i\x1b\ -\xd23\x04C\xf9\xf5e3\x94\x03a\xc5\x8a\x15\x87q\ -\xedU\x9b\xfeqmf\xcc\xf8W*\x95sj\xd3\xff\ -\x91#GJ;t\xe8\xd0\x1b\xd7\xd8\xb0V\xf3\xc4\xb3\ -!0\xf9\xb8\x96sss\xf3f\xd2\x18G`\xe2\xfa\ -\xb8\xfae\x98\x87\xc0\xd4\xd5\x8fW\xc5O\xaf\x8e\x87>\ -_\xc3:\x0c}&\xce\xd0\xd5/c\xea\x19\xcaj\x18\ -\xc7\xba8\xa6\xb1\x0f\x8c\xd1\x7fm\xe3\x9f\xd1\x7fm\xb4\ -p]\xe7\xe7\xe7\xc7\xab\x89\xd6\xffJpvvvG\ -\xdf\xd2\x18\xfb\x83{\x115\xd12\xd6\xfe\xa3\xfe\xdb\xb7\ -o\x1f\xfe\xa6\xda\xf8O\x0e\xe8\xd3\xa3\x1d\xaaMg\xa6\ -\xb4?\xb8\x9e3\x8f\x7fm0V\xff8\xfeq\x7f\xb4\ -&Z8\xff\x1ak\x7f\xfc\xfd\xfd\xf9L\xbd~\xfd\xfa\ -\x89'L\x98\xb0\xa8\xae\xfb|\xff\x86\x80\xfa\xc7\xb9\xde\ -\x18\xfb_\x9b\xfe\x8d\x1d\xff\xfa\xf6\x07\xfb\x01\xd3\x98\xbf\ -|\xf9\xf2\x838/\xbd\x99\x96\xff3\x82\x93\x93\x93\x8b\ -\xb1\xf6\xdfT\xfe?3\xff6l\xd8\xd0\x07\xe9\xea\x97\ -m\xdb\xb6\xed\xba\xfe\xb5\xf1o\x0f\x8c\xfd\xa9M\xff\xe8\ -\xa3\x9a\xd2\xff\xe4r\xb9\x1d\x7f\xfe\xf9\xe7;\xd5\xcd\x0f\ -qqq\xc9oJ\x07o3\xe8\xfc\x9fZ\xed\x8f\xb1\ -\xe3?333\xcb\x18\xfb\xbfz\xf5\xea\xbc\xda\xf0`\ -NX\x5c\xdb\x9e\xab1\x01\xef\xf1)\x14\x8aY\xe8g\ -\xef\xde\xbd\xfb.\xf6\xaf\xfe\x1e!\xc61\x0f\xef\xd1!\ -\x0e\xee\xa1`\x9dW\xe5kL@\xfd\x1b3\xfe\x8dY\ -\xff\x1ak\x7f\xa0\xbd\xe5\xb5\xf1c\x00\xe7\x04ww\xf7\ -\x06umW\x9b6m\x82\xb3\xb2\xb2\xb6\xe6\xe4\xe4<\ -2\x96\x97!\xe0=\xa4y\xf3\xe6m\x07[\xf9\xda|\ -ec\xedO]\xe6\xdf\xdah\xd5u\x7fZ7'\x08\ -\x8ci\x0f\xfaR\xb8W\xfb\xb2:\xaf\x0e\xb6n\xddz\ -5>>>\xa5v\x09\xea\x16\xea2\xfe\x8d\x9d\x7fk\ -\xa3\x85\xd7\xba\x5c.\x9f\x89\xf3\x80\xb1\xed\xafmNh\ -\xd7\xae](\xea\xc8\xd4z\xaf\xa2\x1f\xae\x99r\xed\xc2\ -\xf8\x9f\xa6\xf4\xff\x8d\xf5\x7fp\x0e\xde\xb9s\xe7\xad\xba\ -\xb4\xdfpN\xb0\xb3\xb3s@\x1b\xf1\xba\xf5n\x08\x9f\ -\x7f\xfe\xf9N\x07\x07\x07\xa7\x9a\xf4aL0v\xfc\x1b\ -\xbb\xfe\xad\xeb\xfe\x83\x87\x87G\xa3\xaf\xbe\xfa\xeah]\ -\xda\xce\xcc\x09B\xa1p<\xb3vx\x1b\x80\xd7\xafX\ -,\x9e\xf4*\xfa\xc7\xf1\x8f\xfb\xa1\xc6\xe8\xdf\x18\xfbo\ -\x8c\xfeQn\xfd\xfd\x1f\xbcn\xa6L\x99\xb2\xbc\x8em\ -\x7fkz7\x04\xf4\x99, \xbc\x8c\xfe\x8d\xf5?\x8d\ -\xf5\xff\xd1\xff|\xd9\xfd\x9f\x84\x84\x84Qu\x99\x13\xfe\ -I\xb0k\xd7\xae\xbb\xde\xde\xdeM_F\xff\xc6\xda\x1f\ -c\xf6?_u\xff\xf9e\xe6\x84\x7f\x0a\xe0\xd8\xe9\xdc\ -\xb9s\xdf\xb7\xad\x7fc\xec\x7fM{\x0c/3'\xfc\ -S\x00\xdb\x9e\x98\x988\xb6.\xfaG\xfbo\x8c\xffS\ -\x9b\xfda\xee?\x1a3\xfek\xdb\xff\xd7\xcd\x09_ \ -~^^\xde[\xd7k]\xc1\xd8>\xa8\xcb\xfe\xbf\xa9\ -\xe6\xdf\xba\xdc\xff\x9a5k\xd6&S\xe9\x04\xd7\xdd\xf8\ -l\x1e\xfa,\x9d:u\x8a\x05\x1f\x0a\xef\x07z\xf2\xf9\ -\xfc\xeeuY\x93\x1b\x0b\xe8\x9f\x19\xa3\x7fc\xf7\x9fM\ -y\xff\xcb\x18\xfd'%%M0\x85\x1e\x8e\x1e=Z\ -\x96\x91\x911\xb3&\x1f\xe5u\xcd\xfb\xd8\x86\x7f\xa2\xfe\ -k\xdbc\xee\xd3\xa7\xcf\x08S\xb4\xff\x9bo\xbe9U\ -\xaf^=\x97\x9a{\xfa\xf5\xe9\x1f\xa1w\xef\xde\xc3k\ -\xd2\xbf\xb1\xfb\xcf\xc6\xe8\xdf\x18\xff\xb36\xfd\xe3\xb5a\ -\xaag\x18\xb7o\xdf~\xc3\x98\xbd\xa3\xd7\xa9\x7flK\ -u{x\xc6\xfa\xff\xc6\xd8\x7f\x9c3\xc7\x8c\x193\xef\ -U\xec\x0f\xf8>\x0da}\xf0\xd4\x94\xedG~qq\ -q5\xee\x9d\xbd\xeeu\x07\xb6\x09\xe7\x9b\xea\xf4o\x8c\ -\xff\xf3\xba\xed?>?\x0d\xbe\xff\xedWmku\xfe\ -\xd2\xc4\x89\x13\x97Tw?\xe1M\xac\xfbv\xec\xd8q\ -\x13\xdb\xa8\xcf\xd7X\xfbo\xac\xff\x89\xf7.\x8c\x19\x8f\ -U\xd9\x9f\x85\x0b\x17\xeez\xdd:X\xbe|\xf9!\xbc\ -\xc6\xde\x86\xfe\x11\xf0\x9e\x84>_\x1c\xff\xf8\x8eKm\ -c\x16\xdfK2\x95\xfd\xc7\xfd\x07C\xfd\x0f\x1c8p\ -\xe4\x9bh?\x02\xce\x09\x01\x01\x01\x11oC\xff\x08\xef\ -\xbc\xf3N\x92\xfe\xf87v\xff\xdfX\xfbS\x1b-C\ -\xfb\x83\xe3\x11}\xc47\xd5~F\x86\xf8\xf8\xf8\xca/\ -\xfe\xbcI\xfd#/\xe6]\x8a\xba\xf8\x9f\xa6\xba\xffn\ -\xa8\xffU\xabV\xe5\x9a\xa2]\xeb\xd6\xad;\x8b6\xb6\ -.u&M\x9a\xb4\x14\xe7\x847\xbd\xef\x07c~\x7f\ -]\xf4o\xec\xfd\xdf\xba>\xff\x83{\x86\xa6zf{\ -\xe8\xd0\xa1\x19x-}\xf9\xe5\x97G\xeaR\x0f\xf7\x8f\ -\xdf\xb4\xfe\xb1\xcd\xb8\xf66v\xff\xcdX\xff\xbf\xae\xf6\ -\x07\xe6\xa3-\xa6j\x93\x8d\x8d\x8d\x1d\xd2\xc4\xf1ZSW\xfdcx\x999\xe1\ -e\x01t4\x87\xe1\xab\xb3?o\xe5\xfd#\xc3\xfa?\ -\xfc\xf0\xc3\xc5Wm\x1b\xfat\xf8\xee\xf4\xcb\xf4\x01\xce\ -\x09x\x7f\xe0u\xea~\xc3\x86\x0d\xe7\xf5y\xe2\xfa\xd7\ -\x18\xfd\xbf\xae\xf5\xaf\x81,.\xa6\xf8v\xd0\xe6\xcd\x9b\ -\xff~\x19\xfdc\xc09\x01\xef\x93\xbd\x0e\xddC\xdb\x9e\ -\x18>3m\xec\xfck\xca\xfd7\x9c\xc3\xaa\xbb\xff\x8b\ -\xf7\xa9M\xf1,\xce\xf4\xe9\xd3\xbf}\xd9>\xc0\x80\xf7\ -\x8bM9'`\x9b\x18\x9b\xaf\x1f\xde\xf6\xfa\xab\xaa\xd0\ -\xbd{\xf7A\xa6\x98\x8f\xf1\xd9\xadW\xe9\x03|n\xc2\ -\x14\xcf\x02`[\xbav\xed:\xb0*\x1eu\xd9\x7f3\ -\xa5\xfek{\xfe\xc7T~\xf6\xbau\xeb\xceT\xf5\xdc\ -Am\x01\xe7\x02\xbc\x9fc\x0a\x19jzG\xc0\xd8\xf5\ -W]\xf6\x9fk\x93\xc7\xd8\xe7\xdf\xc6\x8f\x1f\xbf\xd0D\ -\xd7~\x05\xfa\xf9\xcc\xfd\x81\x9a\x02\xfa\xaf\xb8\xd65\xd5\ -\xf3G\xd8\x86\x9a\xf8\xbd\x8d\xf7_p\xff\xad]\xbbv\ -a\xb5\xe9\x02\x03\xee\xc7\x9bB\x0f\x08(\x17\xae{\xf0\ -\x19\x0d|O\x0f\xdf\x19C\xc08\xe6\xa1\xffe\xca\xfb\ -0@\xab\x02\x9f+\xa8\xa9}\xc6\xbe\xffej\xfbS\ -\x97w\xd8F\x8f\x1e\xfd\xa9\xa9t\xf26\x00\x9f\xe3\xae\ -\xee~B]\xde?5\xe5\xf3'\xc6\x8e\x7f&H\xa5\ -\xd2\x8f\xdf\xb6\x1e_\x05\xf0}\x86\xaa\xee'\x98\xfa\xfb\ -\x1b/\xb3\xff`l\xe8\xd5\xab\xd7\xb07\xfd\x9c\x8a)\ -\x01\xef7\x06\x06\x06v\xd0o\x93\xb1\xcf\x1f\x9ar\xfd\ -\xf5*\xdf\xffi\xd2\xa4IK\xf0\x85Mr\xff\xefm\ -\x00\xae}\xf4\xe7\x84\xba<\xff`\xaa\xf7\xafkZ\x7f\ -\x19\x13\xf0;A\xb8\xd7\xf9\xb6u\xc9\xc0\x86\x0d\x1b~\ -\xdb\xbe}\xfb\xf5\xba\xd4a\xe6\x04S\xde\x7f\xaf\xcb\xf7\ -\x97L\xf1\x0e9\xae\x11\xde\xe6\xfb\x92\xc8;99y\ -\x1a\xca\x82\xef#\xe3{\xc9u\xa9\x8fs\x02\xea\xd4\xd4\ -\xf7\xdf\xdf\x94\xfe1\xfc\x93\xde\x7f\xc7\xf1\x8c\xef\xe7\xd7\ -\x85\x0e>\x7f\x83\xef\x88\x98j\xfc\xbf\xad\xef\xef\xe1\xde\ -\xca\xe6\xcd\x9b/\xbdn\xbd\xe3\xb7=p\xcdP\x93,\ -\xf8\x9d\x0a\x9c\xe3\x8c\xa5Y\xdd\xb7\x5c\xf5\xc1\x94\xfb?\ -U=\xffl\xaa\x80>\x12\xac\xa3\xfe0\xb5\xde7m\ -\xda\xf4gM\xef\x11\x19\x06\xdc;\xc2\xef\xb6\x98\x8a\xbf\ -\xb1\xfa7\xd6\xfe\xd7\xd5\xff\xafk\xe0p8\xad\xf1\x7f\ -\x9f\xbc\x8a\xaf\x84\xcfY\xcd\x981c\x03\xfe\xef\x83\x97\ -\x91\xe1e\xe6\x84\xea\x00\xfd\x1fS~\x7f\xf5M~\xff\ -\xb3a\xc3\x86\xcdp\xaeF\x9b\x8d\xdf\xa8\xc1o2\xa1\ -\x0c\xb8\xc7\x83\x80\xf1\xec\xec\xecGX\x8680\xa7N\ -\xc5:\xa6\xe0\x8d\xbe\x1a~\xdb\xd1\x14\xe3\xdf\x94\xdf?\ -\xfc_\xfb\xfeg\xff\xfe\xfd%\xd5\xcd\x09\xf8\xecXm\ -\xfa\x7f\x9b\xfb?\xff\x96\x80s\x9e\xe1\x9c\x80\xef\xbb\x19\ -\xf3\xad\x857\xf1\xfe\xdd\xffB\xc0\xef\x9b2s\x02\xea\ -A \x10\xc4\x98\xf2\xfd\x17S}\xff\xe1\xdf\x1c\x989\ -\x01\xf7\xbdM\xfd\xfc\x95)\xbe\x7f\xf2\xbf\x14\xea\xb2\xff\ -f\xaa\xef\x9f\xbc\xea\xfe\xcf\xbf)\xd4\xe5\xfd\xf7\xd7\xf5\ -\xfc\xe1\xffrx[\xef?\x9a\xf5\xaf\x0duy\xff\xcb\ -T\xfe'\xda\x1f\x9c{\xf0\x99?\x5c\xa7\xeb\x01\x9f\x01\ -\xb4OxF\x1c\x1d\x1e\x9f\xc1\xc32\xfd<\xecK\xbd\ -\xfa\x02\xbd2\xbe\x1e\x0f\x86\xa6>?\x9a\x16\x02\xd2\xd0\ -\xaf\xa7\x0f\xfa4\x18y\xf4h\xf1u\xfc\xf9\xfeU\xb7\ -E\xc0\xb4\xa5*\xf9#\x22\x22z\xe1\xff\xc2y\x93\xfe\ -\x0f\xd3\x07x\x1d\xe8\x03\xaeO\x0c\xe3x\xd6\x8f\x1b\xd6\ -\xd1\xa7SU\x9d\xaah\xd7\xc4\xab&\x9eU\xd15\x86\ -6\xcah\xd8^}Z\xc6\xdc\xf37\xe5\xfd/3\xd4\ -\x1dL\xb9\xffl\x86\xba\x03\xee\x05\x1ac\x7fF\x8f\x1e\ -\xfd\xd9\xdb\x96\xf5\xdf\x08\xb8Oa\xc4\xff\x1f\xb4NJ\ -J\x9ah\x1e\xff\xa6\x07|\x16\xb2\xb6\xef\xbb\xb2\xd9l\ -\x0b|\xce\xd4\xfc\xffgM\x0b\xb8G\xfe\xfe\xfb\xef\xaf\ -rpp\xa8W\x93\xfe\xf1\xff3\xe3\xff\x8e\xff\xff\xfa\ -\xed\xd4\x7f*\xe0\xfb\xfbQQQ\xfdY,\x16\xbb&\ -\xfd3s@\xaf^\xbd\x86\x9b\xe2;bf\xd0\xfa=\ -\xf8\x8c\x05>\xa7R\x9b\xee\x99\x80\xffS)666\ -\x11\xbf\xeb\x83\xcf\xcf\xeb\xff\xbfP\xc3\xff\x1djL>\ -\x93\xae.\xbf&\x9c\xea\xca\xf4\xf3\x0c\xf3\x0d\xa1\xaa\xb2\ -\x9ahT\xc5\xdfXY\x11\xd0\xde\x1c8p\xe0\xc9\xd7\ -_\x7f}\xeb\xac_\xce\xc4\ -qO\x83I\xe3\xd90\x8d\x80u\xf5\xe2\xf3\xf5\xeb\xeb\ -\x83a=\xa4e(\x0f\x93\xc7\xc8d\x98\xa7_G_\ -\x16}Y\xf5A\x9f\x86a9\x961\xf9X_&\x93\ -\xcd\xc0\xef\xe6\xe2<\x8a\xfe\x0e>_\x83\xfa\xac\x8b\xfe\ -\xf5\xfb\x01\xff'9\xf6\x05\xd2\xb1\xb5\xb5\xb5\xc7xU\ -\x80v\xab\xba2c\x00\xeb\xbf*\x8d\x97\x95\xc5T|\ -\x19\xc0u\x14\xfa2/\xabws0\x07s0\x877\ -\x14\xd8_R\x04\xfdR\x0a~\xe4K\x16\xb1\xa0\xe3\x84\ -$~\xc9~\x16\xd7\xa2F\x89\xe5I\x12N\xbfT\xb9\ -J\xaeL\x95gp\xba\xcaE\x99\xe9\x12\x99\x8a\xd3U\ -\xa8\x12r\xbaH\xe5\xa2Q\x84\xd7%&6v\x80B\ -\x86\xf8\x18\xef#\x1c\xaf \xa4A\x02M\x87\xad\x03|\ -\x0em\x18\xb1\xd0h\x08q\xa0\xdfi\xb0\x88\xc2r8\ -\xb2\xf0\x88\xf5drE\xba\x86\xd8\xa0\x00\xcc\x13\xf7\xad\ -\x09\xc1\x1a\xb5\x83u|\xaa0C\xc2\xe1\x22\x1di\xa6\ -\x0c\xbf>\x83_\x8b\xb4&\xf1$\x95\x08I\x06\x91\x10\ -\x0e\xe1j\xe5\x93\xca\x94\x0a\x14@\x09U\xe8\xf4\xf84\ -1\xa6\x01\xbc1-\x92&I1M\xe9\xda\x93&K\ -\x1e\xa7+\xa7\xd3\xa3d\xa3\xe4\xfai\xa92#\xf9\xb9\ -\xb4H\x8a\xf4m\x18uc\x9e25\x1dy\xf4\xc4\xc6\ -\xd1<2\x95*]q\x08@}\x9d\xd6\xa1V\xbaD\ -%\x14\x83ru9\xb6R\xe1x\x89b@Z\xbaD\ -,\xcfL\x8a:\xc7+\xc9\x90\xf4\xb8B\xd3L\x1e\xa7\ -\xc8\xd0\xd5}>P\xd0\xea\xbe\xa4\x1eq v\xc4V\ -\xf7s'1\xa47q\x01\xad\xb8\x11O\xe2M\x1a\x00\ -\xb4&\xcdA+\xcd\xe1\xe7\x03\xe7\xc6\xa4\x11i\x02\xd0\ -\x92\xf8\x92\x16pl\x05\xd0\x02\xca\x9a\xd1\x18\x1c\xc0n\ -\x039\xdac\x0b\xc0\xc1Z\xbe4vK\xfa\xd7\x16\xea\ -6\xd2QiF\xff\x1aC\xac9p\xf3\x02p\x07\xbe\ -.\xc4\x15~\xb1\xa4\x0f-\x91\x0d\x80\x1d\xfc\x1c =\ -\x88p*\x88\x85\xa5s3?\xae:\xa0<\xd0\x8b\x1b\ -\x10\x10\xc8\xe5\x06\x06r\x03\x03\xb8\x01\xf4\x09\x93pP\ -\x07\xda\x05\x04a\x09\xe4\x06\x04\xa8\xb9$P\xcd\xb5\x0c\ -\xd4\x15\xa9\xb9\x9a@\x1b\xc0\x0f\xf0k\xe5eC\xa9\x89\ -\x86XSn\x83\xd7_\xbcWPPQH\x0a\xd4\x85\ -\xe4aE\xa1\xa6\x80*,(.d\x17\x14\x16B\x8e\ -\xba\xc0\xba\xb0\x00\xa3\x85\x05\xe5P\xd4\x10\x13\x0f1U\ -X\xf8\x10\x8f\x90,xp-{\x92\xbf\x15\x8c2\xc2\ -\xf6\x98~\xbfb\xb3\xc6\xa2do\x94\x15\x8cj\x1b\xe9\ -\xe3\x1f4l\xf5\xee\xb6\x14\x8b\xb48\xb9Q\xc3*\x1e\ -g\xcdb\xf5-\xda\xa0\xa1\xf6\xb9\xb1,\x15\x15\x10\xb9\ -\xdc\x9ce3]\x0d\x91\xfb\xedX6\xb31\x92\xef\xc7\ -\xb2\x9d\xab.\xd4\x10\xf5E\x8dZ]\x01\xe7{\x90\xd9\ -\x9ee3W]\xaa\xf1T\x9f\xc8\xce\xc9>\x90s \ -'\xe7\xc0\x81\xfd99\x90\x80?\x88\xab\xb3+r\xec\ -\xb21\x83\xce\xdb\xaf\xce\xd1\x1c(\xc9\xb1B<(\x86\ -T6u\xb8\xb0DC\x15\x00\xf59@\x88]\xda\xdb\ -\xcb\xb3\xdc\xcb\xc3\xd3\xcb\xc3\xdb\xd3\xcb\xdb\xdb\xcb\xdb\x8b\ ->yzz\xe3_\x99\x97\xb3\xa7\x07\x14A\x19\x94x\ -y{\x22B\x85\xb7\x0d\x8d\xe9\xed\xd9\xfe0\x92jO\ -\xd9\xce\x81s\x09o\x1f\xa1\xdc\xf7A,\xdf\x1fE/\ -\x85\xac\xf0}\x84\xe5\x96\x8dQ\x86!U\xcc\xab\xcc\xcb\ -\x0f\xa0l\xa0\xa6U\x09\x9f\x10\xf1\x22\xab\x83\x84r\xdb\ -\x8f\x04\x03\xb4\xa8\xd6%\xe1\x84_\xa29\xe8}\x88P\ -.4]?-]v\x09\xcf'_\xad\xa1\xae\xf3\x0f\ -C\x95l()\xd4Qg\x95v\xbcS\x0e<\x92\x8f\ -\x80(\xfb\xe9*\x94m\x16\x0a\x97\x07\x87\xc5\xd6\x85\xc4\ -\x91;\xeb\xf0\xdd\xe2\x0a\x8d\xa6\xa2\xf8\xde\xe1\xd9\xdc[\ -\x80\x87\x04@\xb14iR\xfeTC\x1dl\xf0\x84\xb0\ -\x82\xb7>z\xa4a=\xde\x1e~W\xc7\xa3 \x80n\ -'\xa9(\x02\xce\x82bB\x89/\xdf\xd7PWS\xee\ -3$\x80\xd5\xdc\x12\xe8\xdd\x99\xa5OQ\x842B\x85\ -^\xbd\xad\xa1\xae\xf1\xf2\xa1\xc1\xfb\xb5\x0df\xd9\xcc\xd1\ -6\xa0\xe3\xad\x22\x8d\xe5bk0s\xdb\xafk\xa8\x9d\ -N\x85:*\x05\xba6Z@\xe3\x1b\x1d-\xd2\xb0\x0f\ -6\x18_rUC\x95Nz\x08r\xe4\xe8\xd4\x83\x18\ -\x96\xa5\xe1`\x07\x96\x17iH\xc9\xdf\x1a\xea\xb0\xc5c\ -]\x93Q\x17YZMW\x10jT\xe9\xaf\x1a\xean\ -\xd3'\x0cy\x7f\xa6\xb3\xca\x09\xd5\xf1\x16\x94\x95\xf6-\ -\xaa,\xd3uQ\x09\x1fdot\x14\x0a\xd5c\x9f\x12\ -\x96{\x0e-\xbb\x1fe3\x17k\x86\x97\x12\xca\xe6\x8b\ -3\x1a2\xb6\xb8\xb2s\x03\x98\x0e\xe7\x15\x13\xb2)_\ -c]~rR\xac\xb7g\xf7\xf2\xfb\x1a2\xbe\x84\xe9\ -\xd7\xcaa\xc1+!dB\x81\x86U6\xd3\xa2\x8c\x90\ -\xd2{\x1a2\xa1\xf4\x05$~)!#\x0a4\xd4)\ -\x17\xc0.\xbd\xab!\xc3\xcb\x98\xde\xf6\xd7\xb5\x90\x16\x94\ -W\x01H7\x04Z$\xaa\x22\xbc\x5c\xa7\x07\x10\xcaf\ -\x9e\x96\x1dd5|\xfa\x00b)@\xb3\xf4\x8e\x86z\ -\xea]\x01\xed\xd2\xf6\xc93\xa9@]\xac\xdb@c\x89\ -u9\xa0A\xd7\xddd\xa9uba\xebgc\xeb\xf9\ -\x15\x84\xec\x82\xa2C\x0d!RzKC\xb6\xaa\x81\xd2\ -^$\xf0\x80\x11\xab\x98\xaf&d\xe4M\x90*\x02\x22\ -\xa575\x16I0\xcf\xd0c\xc4\x9f\x1e#\x96%<\ -B\x1a\x96\xdd\x80^N\xd5\x22\x94\x82\xc1\xdd\xafw]\ -Z F.4\xec\xec\xcd\x22\x0dk\xa9u\xe9\x0d\x0d\ -{\xbf\x16\x05\x87\xea\x1c\xdd\x08i\xaa\x06-f4<\ -\x02C\xf20\xa2\xa8=\xdd\xb5\x0a\xa2\xd9\xc00#[\ -\xf25l;b\xbd\x0c\x86\x89\xfa\xba\x86\xf5\x03=\x84\ -\x18\x05\xb2\xe1\xca\xbbS\xa0!\xa5\xd0\xf24\x1c\xb5e\ -\xf3Jz\x92\x12\xa0y\xcb5[\xaf3\xd8\xc0\x0ar\ -I!(2\x02\x04\xa2\x96ZC\xbf=(\x80\x02w\ -\xed\x00\xd0!\xb2\x80c\xbe\x86\xdc\x82n\xd1\x0a\xd5\x10\ -4y#_\xa3S\x22C\xae\x98G\xca\x80\xdcC\xe8\ -t\xeb\xa5E\xa8'Pf\x01\x0e\x08\xddE\xfb\x8c\xed\ -}\x14\x0f.\xb6\xd4\x12\x10\xaf4\x0d\xf4\x09\x82\xb0\xef\ -i\xc7]a\xa5|\x05\xe9\x0e\x03\xdb#\x93\xf35,n\xa5hY\ -:\xa5\x92+\xc0\xf3X\x91V6R\x0a\xec.\x90\xca\ -\x8b\x87\xe9\xbdH0\xcdT\xb9\xc3\x13\x94\x0c\xfaO\x1d\ -L\xb4\xa2kQ\xe0*\x01I\x17\x03\x9d5\x8fQ\xa4\ -[\x1a\x8b90\x04\xf4\x8d\x18=\xde\xc8E\xa0R\xe6\ -\x018\x0d\x0f\xdd\xd1\x90\xf30\xdc\x5c\xf7=w\x15\x84\ -C\xd7\xb8\x14\xc14\xf0\xf7#\x10h\x09\xcc\x01O\x9c\ -\x98A\xa9\xebf\xaa\x14\x07x8LL\xe4[0\x12\ -)%\xa0\xef\xf2\xe0\x8aJ\x0bXI\x0aze\x10\xce\ -(\x9b\x00K\xf0\x148\xab\x07BEW}\xb3\xa3\xbd\ -\xec&\xc3\xc0;\xe3\x0dmkx\x16\x9a0\xa9\x0cF\ -\xb8N\xdf:k\x8a\x17\xf0B\xe8\xaf\x8a\xa5v%\x84\ -\xe5\xb0\x0c.A\xb2\xb0\xd4\xc0\x84Q\xc5a`\x0d\xe6\ -\xe5kl\xd5\x17f\x8bCC\xc5\xb3/\xaaA\xb4\x8a\ -\x91\xa5\x8c=|\xc6\x95\xf7\x94\x90OOk\xa8/\xe0\ -\xd2\xd3\x99\xdb\xca\xab)\xac\x88\x90\x8f\xa1\xec(\x5cr\ -\xcc\x0c\xa1\xd32\x0fd\x1cVvFC\xdd\xea\xa0f\ -.\xe8J\xdd\x15\xf3@\xaf-\x1f\x9c\x01K9\x92h\ -{\xb0\xd0\x8f\xd1\x18h\xd3\xea\x18\xd8\xcd\xdf\xae\x83\x8d\ -\xfd\xc2Z7\xdc\xe9\xf9\x08\xc8\x825\x9e\x5cz\x15.\ -\xcbi\xa4\xc1A@8\xea\xaf\x1b\xe6\x0c\xdf\x02B\xe9\ -\x0c7t\x86\xf5b\x18LwNi\x85\xb6\xd1)\xfb\ -\x01\xa1\x82/\x81\xa1\xb8\x1c\x0azI.~\xaa\xd1h\ -\xad(#\x1c\xff\x1e\x88\xfe\x07\xcc \x7f\x0e\x87\xf1(\ -\xb8\x9e\xaf\x9dAh\xfeaw\x08\xab\xf5\xfa\x070\xff\ -<\xd8\xd0\x16\x1a\xd1\xe0 tH!3\xcf\x86\xdf$\ -\x8e\xcd&\xef\xbc\xfa\xa8\xa4\xa2\xa2\xe4\xd1\xd5\x9dS\x9b\ -\x814V\x8b\x0a\xe9\xf9Eg\xc1y0gJ\x8a\xcb\ -\xe1\x1a{\xaesy0\xc7\xf2\xaf\xc3\xd4y\xfb\xe8s\ -\xf34\xef\x00\xb1\xf4>\xa8)\x89\xd1\xda f\x0c\xe7\ -\x10\x0b\xabE\xe2\xca\x0bD79\xec\xab\xd4\xb4nJ\ -(\xa5g\xfe\xfd\xfa\x9d\x863?\xf5\x9cE\xd3e\xe5\ -\xe8f(\xdaZ\x94\x8a#\xd4\x025\xdf\x9d\xc7\x8f\x88\ -\xe0\x0b\x04<8\x84\x0b\xf8\x82\x08>?B\xc0\xe7U\ -\x084<*<\xa2\x9co\x0b\xa9\x88\x08\x9e\x80\x1f\xce\ -W\x0b4|[\x01O\x8b\xdc\xeb\x04#m1\xda\xb0\ -\x12\x9b\xe2\x92\x92\xe2\x92b\xf8\xab(\xb1*\xd5\xc6\xd5\ -%\x04\xc0I[B\x97A\x0c\xca1\xd7\x12\xe3\xa5\xa5\ -\xea\x12M1U\xa2\xae\xbc\xec60\xfd\x08\x91\x07@\ -\xfd\xb3\xef@_\xedX\xd6\x131\xe3lS\x96\xc5\xc0\ -\x22p\xe2*V\xd5cQ\xad\x8eB\xecf\x7f6\x9b\ -\xd8\x0e\xbf\x0dN^\xc14W\xf4\xff\x5c\x12s\x9f\x96\ -\x81cY\x0e\xa0V\xb34j8Z\x02@\xa4Bm\ -G'\xe1\x00\xc7r<\x80\xf5\xc0T\x19\x80\x86F.\ -W[U<9.\xf5D_\xd2\x86\xb2\xf3O\x9c\xbe\ -`aV\x96z\xae&\xcbu^V\xd6\xdc\xac\xac9\ -s\xb3\xe6\x22\xcc\x9d7w\xee\xfc\xb9\xe5Y\x96\x18\x9f\ -\x03\x18\xf5\xe6de\xcd\x83X\xd6\x1c\x1a!kN\xc5\ -\x5c6\xa4\xe7\xa8\xe7\xda\xcf\x9b3'k\xc6\xf8\x81\xed\ -\x1c`\xb9\x00N4ei\xe7`_\x06\x8e\xffC;\ -\x8dm\x01\x9c\x8b\x00\x1e\xd8\xb1l,\xa8\x0a\x5c\x1a\xb0\ -j\xf8Y\x81;nE\xff\x9caY\xe1\x00?'p\ -\xd3\xb51\x078\xbb@\xbe\x1b}\xf6\x00p\x82%\x86\ -=\x1c\x9d\xe8\x85\x86\x03}\xb4\xa1q\xb4\xcb\x0cw\xfa\ -\xecI\x83\x16\xc3\x11~\x0et\x0d\xfc\xb9\xeax=\xfb\ -U#\xd7\xb7\xb9\xd5\xff\x1e\xe7\xee\xd7<\x81#\xf4G\ -\xeeA\x88\xe5\xe7\x1e\x82\xe3\x83\xdc\xc3p\xbc\x9f{\x04\ -\x8ews\x0b\x09;/77\xaf8\x97\xe4\xdd\x22O\ -r\xef\xe4\x82\x17x\x04-\x92\xe3\x15:\x8d\x92\xe3\ -\x05t\xd7B\xcb\xf2\xca+5_\x00\x95N?\x01\xf5\ -\xe6W*\x1f\xe6\xcf\xbc\xfb\xa0~r\x12QKu\xfd\ -H\xf2\xee\xe6jNh\xe8\xc6Py\xba\xbe\x83\xe91\ -\xefd\xae\x96\xdaSr\x22W\xcb\xab\x88\xce\xd5J\x02\ -\xf3[n\xde)\x9d\xfaa&\xb8\x81\x03*\xef\x16$\ -\x1e\x02\xd6%h\xfeM\x88\x17\xea\x06\xa0\x9a`I>\ -\xc8\x0a=x\xa2\x14\x9a\xf48\xf7>\xcd\x1a\x07\xd8]\ -H\xdd%j\x1c\xd0\xa0\x82{\x90\xbaE,N\xe0\x90\ -/\x05\x91N\x14\x90\xfb\x90uX\x93\x0f\xc7C\x9a\x02\ -8\x1e\xd4\x14\xc2\xf1\x80\xe6a\xe5\xe5cx\xac\xeer\ -3\x1b\x10\xb3\x011\x1b\x10\xb3\x011\x1b\x10\xb3\x011\ -\x1b\x10\xb3\x01y\x0b\x06D{\x8f)V9\x8a\x10\xb8\ -\x84\xe9\xfb?t\x08\x9a\xa6\xbb\xd7\xd2O\xa8R1\xf7\ -]\xbak\xf1\x1c\xf4\xf1\xf0\xf0\x7f\xa8-\xb6Q\ -\x00\x00\x09t\ -<\ -?xml version=\x221.\ -0\x22 encoding=\x22UTF\ --8\x22?>\x0d\x0a\x0d\x0a \x0d\x0a \ - Sky Icon\ - / System / View\ -\x0d\x0a Created with\ - Sketch.\x0d\ -\x0a \x0d\x0a \ - \x0d\x0a \ - \x0d\ -\x0a \ - \x0d\x0a\ - \ - \x0d\x0a \ - \x0d\x0a \ - \x0d\x0a \ - \ - \x0d\x0a \ - <\ -/polygon>\x0d\x0a \ - \x0d\ -\x0a \x0d\x0a \x0d\ -\x0a \x0d\x0a\x0d\x0a\ -\x00\x00\x14\xc4\ -I\ -I*\x00b\x07\x00\x00\x80?\xe0@\x08$\x16\x0d\x07\ -\x84BaP\xb8d6\x1d\x0f\x88DbQ8\xa4V\ --\x17\x8cFcQ\xb8\xe4v\x0b\x02\x7f\xc7\xa4R9\ -$\x96M'\x94JeR\xb8\xa4\x82Y/\x98Lf\ -S9\xa4\xd6a.\x9bNgS\xb9\xe4\xf6}#\x9c\ -O\xe8T:%\x16\x8d/\xa0\xd1\xe9T\xbae6\x9d\ -\x1f\x81\xd3\xeaU:\xa5V\x91Q\xabVkU\xba\xe4\ -B\x93]\xb0XlU*\xfd\x8e\xcdg\xb4N\xec\xb6\ -\x9be\xb6\xdd&\xb5\xdb\xeeW;\xa4J\xe3u\xbc^\ -o7{\xd5\xf6\xfdi\xbe_\xf0X:\xde\x07\x09\x87\ -\xc4Sp\xd8\x9cf6\x7f\x8b\xc7drS<\x86O\ --\x97\x93\xe5s\x19\xbc\xe4k5\x9d\xd0hk\xd5\x8d\ -\x16\x97M-\xd2Q\x00:\xbb\xf4\x805\x05\x1d\xc1F\ -PQ\x8c\x14;\x05\x08\xee!.\xf8+\xc2\x0a\xe3\x82\ -\xb3\xe0\xac\xe8+\x13V\x01s_s\xf9MM\x0f\x8f\ -l\x90\x06\xe0\xa5\xc8)B\x0a7\x82\x80f\xd2\x18#\ -.\x0a\xaf\x82\xa9x\xfc\x0bG.e\xe6\x98\xf3\xeb\xb2\ -\x01\xc4\x14\xe1\x05)\xc1@\x95g\xe7~\x0a\x90\xe3\xb1\ -\xbd|\xda\x17\xa2`\xf5,\x88\x13n\x82\x11\xa8(\xaa\ -\xbd\x15\xa8(\xe4\xe3\x9cJ\x9b\xfc\xab\xbb\x8a4\x00\xa2\ -\xa4\x002\x0a9\xa0\xa3\xda\x0a\x05\xb1\x07\xb2\x0aB\xa0\ -\xa4k\x8e|\xa8\xf0zY\x13%p\x9a|\x90\x08\xc8\ -)&\x82\x84\xcd\x11\xb6\x82\x8d\xce9p\xa1\xc5\x09T\ -r\x94\xc5Na\xfe\x01 \xa4\x1a\x0a=4\xe8y\x11\ -\x0c\xb8\xe7\xf2s\x1d\xa5\x12bO\x1e\xc4\xe8\x10 \x82\ -\x94\xc8(\x93\x22\xa2\xd1\xba\x08,\xb8\xed\xf3\xce\xfe1\ -\xf3\x02}(3(\x10T\x82\x96\x08(K,#\xa6\ -\xe3\xaa\xe3\x9a\xb0\x82\x95'$\xd3\x22D\x90\x08o\xb2\ -\x08\x06\xcd\x899\xe8\x82\x8a.9x\x94\xce\x89-\x0a\ -\x92N\xcc\xf2\x04\x22\xa0\xa5\x8a\x0a\x04\xcf\xa9\x81\xf0\x82\ -\x89\xce9wCLI\xed\x0e\x91\xd1(\xacYF\xa0\ -\xa0B\xa4\xe4\xa0\x85b\x0a[\xa0\xa7\x0a\x0ar#\xe8\ -+^\x82\x17\xa8(8\xaeRh \x9e\xe3\x97H\xf5\ -7;\xd3)\xe5:\xd1\x9f\xe2<\xd1P\xa9\x87\x02\x0a\ -:;\xf2J,\x90M\xc8 F\xb1V\xa0\x00\xa0\xe3\ -\x974T#\x0aW\xa9\xdd~\x85\xa4\x01\xaa\x0a`\xd1\ -\xeaa\x18\x82\x8f\xce9\xef] Vh\x01g\xac\xf0\ -\xf2\x08\x1f\xb8\xe6e\x97l\xa7U\xda=m\xa0\xc9\x00\ -<\x82\x99((0\xa3IH \xd8\xe3\x92\xf4%\xd2\ -\x82\xdd\x8ba\xce\xeb\xbck\xb5\xe9%\xe1\xe9\xb5\xb6\x90\ -\x01\xc8)\x8a\x82\x85\x8a`\xc8\xe3\x93\xb0\x85\xd5\x84\xad\ -\xe6\x92\x0a\x1e8\xe7\x9a\x1d{#\xb9B9;$\x0e\ -\xd2\x08Y\xa0\xa2Z\x98P8\xe3\x0c}\x8f\xafE\x94\ -\xde\xd5\xda\xf7\xce\x22\x9a\xe5H\xdeX\x81\x0f\x92\x0d\x8a\ -\x82\x85W6o\x840C\xbb\x8eE!Z\x0d\xac\xa5\ -EI\x00z\x82\x97\xe8(\x06\xa6\x0c\xae99\x88\x1f\ -\xf9\xc2\xfe\xfa\xa0\x99#W~\xaa\x19\xecq\x9f\xa6\x8e\ -~(\x82\xe4H >\xa6UH J\xe3\x9f{\x06\ -\xc4\xc2Fh `\xe3\x9e\xda\x923\xc1#\x1br\x05\ -\x02\xa0\x83\x92\xa4D\xb8\xe3\xc55\x83\xd9\xccq\x02\xe3\ -\x90\x1c\x22/\xcb#2\x9a\x08\xf2\x00\x00b\xa4 8\ -\xf7\x02yfi\x8ckx\x82_h$\xfe\xa3s\x08\ -\xc0\xec\x82\x91*\x95\xce\x82\x01\xfb\xc7\x1f\xb0\xf4\xac\x97\ -\x14\x82\x11\xf1.\xd8\x9b\x16\xa8(\x94\xa9\x1b\xae8I\ -\xb5\x9f\xe1\x12\x0a\x02\xa5\x99\x86\xec\xa9y\xc0\x00\x9d\xdf\ -mJ)\xb3\x18*F+\x8e\x1e0i\x06\xb2\x82\x08\ -\x0a\x91\xb0\x82\x85>\xa2\x9bw\x00\x14\x82\x9eZ8\xe2\ -o\xba\x81<\x08#\xac\xa7\xfd\x10\xe7Y\xdf\xa6\xa6\xfa\ -\x0a\x10*F3\x8elL\x11 \x18D\x15\xab\x94\xf1\ -\xbc\xeeJ#\xad\x22\xea\x5c\x82\x04B\xa47\x8e; \ -9D\x08m&\xa2\xa4\xb5H H|\xc51#\x90\ -@\xeeT\x96\x8b\xb55c\xe8\xba\x92\x07\x98A\x12\xf0\ -\x00\x01EHB\x10P\xfb\x06\xca[s \x83u\xad\ -\x15 \x86q\xc5\xf4% O\x84\x82=\xf2\x9d\x09\x08\ - ! \xaa\x91l=R~\xe1\x87\xf8\xa9 \xa1X\ -\xa9\x10\x04`\x06\x06u\x00A\xa0\xf0\x88L*\x17\x0c\ -\x86\xc3\xa1\xf1\x08\x88\x01\xff\x14D\xc1\xce\xd1(\xccj\ -7\x09O@\xc0&8\xa3\xfe9$\x92\xc2$Ri\ -Lr?\x13\x8a\x08\xa0\xed\x0886U4\x8d8\xe0\ -\xe2H\xfb\xeak<\x9e\xc2\xa4@h;r\x0e\x1d\x9f\ -Q\xa1N\xf88\xb6>\xe5\x94Q\xe8\xf4\xea|\xfaY\ -'\x8a\x17\xa0\xea\x1a\x95j\x0ci\x8f\xa6+v\x08\xcc\ -\x88\xd1\x07K\xd8i\xe5x\xfa\xaa\xab#\xb3\xca\xaa6\ -\xe9-R\x17\x22O\xc1\xcc\x17\x19\xa3\x8a\x0e*\x8f\xbd\ -o6\x19\x102\x0e\xd6\xa2`%)\xa8\xf9\x9e\x19p\ -\xc3\xd8\xa2\x98\xe9\x5c\x0e\x1b\x22\x04A\xd8\xd0q\x8eF\ -H\xa5\x8f\x973t\xf9\x12\x9a\x0eY\xd0F\xd9\x90q\ -\xe4}\xf3\x8c\xc8i\xa28\xdd|2\xe7\x0e\x91\x07 \ -\xec\x988ke\x125\xc7\xd2\xdb\xc8\xe4\x88\xdb\x07I\ -pb\x0eH8\xe2\x99\x10\xd8\xf1\xe0\xfc\xeex\x03i\ -\xb0\x8a\x0c \xec8>\x0f\xa5'\x83\x9d#\xe8\xee\xe4\ -&E\x05\x83E\xa0\xc0\x1f\x14\x1d\xe7\xa9\x8f\xb4\xa3]\ -\x1e\x7f\xc7\x8f\xd4\xf8E\x090u\x94\x1c\x09\xea\x85Y\ -\x90a\xdd\x1f{\x18\xe4\x88\x0eA\xc8\xb4\x1cf\x7fP\ -\x93\xf1\x07\x13\x11\xf2\xe5%|\xdc\x18M\xbc}RD\ -\x89\x9fA\x8a\x04\x1c\x03\x82\xd0\x83\xa1\x07\x1e\x10r\x99\ -\x1f>\xd3\xe5\x01\x07\x16\xd0r\x1d\x07\x05\xe1\xf4\x1c\xfd\ -]\xd1\xf2\x914\x85[(\xdd\xaf\x85\xd2\x94\x88XA\ -\xca7\xee0B\x8f\x04\x1c\xb0A\xcb\x84\x1c\xe1A\xdc\ -\x94)\xb7A\x81\xf4\x1cHA\xc5\x04\x1c\x10\x90\x90\x98\ -\xc9\x06\x17\x11\xf2\xa2(k\xa0\xb8\xe5\xa6\x8e\xd3T\x88\ -T\x89\x10p\x16W\x9a\x97\x985\x06\x16Q\xf2\xb1R\ -\x98Z\x09\xcd\x9b\x98\xe5\xe3\xfeTA\x8at\x1d\x96\x9a\ -\xe7\xf4\xf4\xf8i\x11\xf9\x19`\x9dY\x1a\x1d\x8e\x9d\xda\ -\x14P3A\xca\xe4\x1c\x1e\xa0)4i{A\x854\ -}\xa8\x5ch\x96\x1e\x9c`(\xb5m\x22\x05\x10yu\ -\x06\x10\xe9J\xa1\x08/\xd0u\xa5\x03:\xe8\x89}\xfd\ -\xa7\x97\x9a\x81gH\xa1\xe4\x18\x88w\xaa\x99\xa9\xe1A\ -\x87d~Y\x9d+\x17\xaa\xb3\x5ckZ\xc0\xff~\x10\ -bE\x07\x09k\xc6\x99CA\x86\xf4|\xb6x\xace\ -\xba\xd8Y\xec\x86\x9a)A\x87$\x1c{v\xad\x05\x1d\ -\x7fA\x88d\x1c\x8dj\xe1\xfbi\x81\xb1\x1e+q\xd2\ -H\x81\xb4\x1c\x8aA\xc5\xab\x91&\xa9@\x01\xd5\x1f\x93\ -'\xfb\xb6\x86\xbb\xdd\xcb\xc60H\x83$\x1cnA\xe3\ -\xe4\x18\x07\xaaZ\xc4\x19k\xb3\x11\xf36\xf9KV\xd9\ -\x83\x03t\xb0ZM\x22\x05j\xc9M\x07\x0f\xe4\x16\x82\ -m\x00\x0c)\x15\x07*Q\xf3\xab\x16kq\x8a\xcb\x1a\ -s\xf1\xcc\xb9\x06H\xa5d\x188fs\xb4\x19EA\ -\xb3\x80\x00\x11B\xe4D\x19IA\x93t\x191A\x8c\ -\xf4\x1c\xc8G\xf4l\xd5\xf6\xcc,\x5c\xcbQ\xd5\xb5}\ -a\xbc\xc0u\x9ds]\xd7\xb5-\x7fa\xd8\xb64\xf7\ -[\xd96}\xa3.\xd9\xb6\x9d\xb3m\xa06\xbd\xbbq\ -\xdc\xb5MOs\xdd\xb7{Cp\xde7\xbd\xf2\xd9\xd5\ -w\xde\x03\x81\xd6\xb7\xfe\x0b\x85\xe1\x97\x9d\xeb\x87\xe2\xb8\ -\xb6\xd7\x84\xe38\xfeA&\xe2y\x1eS\x86\xe4\xf9^\ -c}\xe5\xf9\x9esv\xe6\xf9\xde\x83m\xe7\xfa\x1e\x93\ -d\xe8\xfa^\xa3^\xe9\xfa\x9e\xb3W\xea\xfa\xde\xc3\x16\ -\xeb\xfb\x1e\xd2\xa9\xec\xfb^\xe3\x00\xe3\xbb\x9e\xf3d@\ -@\x13\x00\xfe\x00\x04\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\ -\x01\x04\x00\x01\x00\x00\x00`\x00\x00\x00\x01\x01\x04\x00\x01\ -\x00\x00\x00`\x00\x00\x00\x02\x01\x03\x00\x04\x00\x00\x00L\ -\x08\x00\x00\x03\x01\x03\x00\x01\x00\x00\x00\x05\x00\x00\x00\x06\ -\x01\x03\x00\x01\x00\x00\x00\x02\x00\x00\x00\x11\x01\x04\x00\x01\ -\x00\x00\x00\x08\x00\x00\x00\x15\x01\x03\x00\x01\x00\x00\x00\x04\ -\x00\x00\x00\x16\x01\x04\x00\x01\x00\x00\x00`\x00\x00\x00\x17\ -\x01\x04\x00\x01\x00\x00\x00Z\x07\x00\x00\x1a\x01\x05\x00\x01\ -\x00\x00\x00T\x08\x00\x00\x1b\x01\x05\x00\x01\x00\x00\x00\x5c\ -\x08\x00\x00\x1c\x01\x03\x00\x01\x00\x00\x00\x01\x00\x00\x00(\ -\x01\x03\x00\x01\x00\x00\x00\x02\x00\x00\x001\x01\x02\x00\x10\ -\x00\x00\x00d\x08\x00\x00=\x01\x03\x00\x01\x00\x00\x00\x02\ -\x00\x00\x00R\x01\x03\x00\x01\x00\x00\x00\x02\x00\x00\x00S\ -\x01\x03\x00\x04\x00\x00\x00t\x08\x00\x00s\x87\x07\x00H\ -\x0c\x00\x00|\x08\x00\x00\x00\x00\x00\x00\x08\x00\x08\x00\x08\ -\x00\x08\x00\x802\x02\x00\xe8\x03\x00\x00\x802\x02\x00\xe8\ -\x03\x00\x00paint.net 4.0\ -.9\x00\x01\x00\x01\x00\x01\x00\x01\x00\x00\x00\x0cHL\ -ino\x02\x10\x00\x00mntrRGB X\ -YZ \x07\xce\x00\x02\x00\x09\x00\x06\x001\x00\x00a\ -cspMSFT\x00\x00\x00\x00IEC s\ -RGB\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\xf6\xd6\x00\x01\x00\x00\x00\x00\xd3-HP \x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11c\ -prt\x00\x00\x01P\x00\x00\x003desc\x00\ -\x00\x01\x84\x00\x00\x00lwtpt\x00\x00\x01\xf0\x00\ -\x00\x00\x14bkpt\x00\x00\x02\x04\x00\x00\x00\x14r\ -XYZ\x00\x00\x02\x18\x00\x00\x00\x14gXYZ\x00\ -\x00\x02,\x00\x00\x00\x14bXYZ\x00\x00\x02@\x00\ -\x00\x00\x14dmnd\x00\x00\x02T\x00\x00\x00pd\ -mdd\x00\x00\x02\xc4\x00\x00\x00\x88vued\x00\ -\x00\x03L\x00\x00\x00\x86view\x00\x00\x03\xd4\x00\ -\x00\x00$lumi\x00\x00\x03\xf8\x00\x00\x00\x14m\ -eas\x00\x00\x04\x0c\x00\x00\x00$tech\x00\ -\x00\x040\x00\x00\x00\x0crTRC\x00\x00\x04<\x00\ -\x00\x08\x0cgTRC\x00\x00\x04<\x00\x00\x08\x0cb\ -TRC\x00\x00\x04<\x00\x00\x08\x0ctext\x00\ -\x00\x00\x00Copyright (c)\ - 1998 Hewlett-Pa\ -ckard Company\x00\x00d\ -esc\x00\x00\x00\x00\x00\x00\x00\x12sRGB \ -IEC61966-2.1\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x12sRGB IEC\ -61966-2.1\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00XYZ \x00\ -\x00\x00\x00\x00\x00\xf3Q\x00\x01\x00\x00\x00\x01\x16\xccX\ -YZ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00XYZ \x00\x00\x00\x00\x00\x00o\xa2\x00\ -\x008\xf5\x00\x00\x03\x90XYZ \x00\x00\x00\x00\x00\ -\x00b\x99\x00\x00\xb7\x85\x00\x00\x18\xdaXYZ \x00\ -\x00\x00\x00\x00\x00$\xa0\x00\x00\x0f\x84\x00\x00\xb6\xcfd\ -esc\x00\x00\x00\x00\x00\x00\x00\x16IEC h\ -ttp://www.iec.ch\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x16IEC \ -http://www.iec.c\ -h\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\ -esc\x00\x00\x00\x00\x00\x00\x00.IEC 6\ -1966-2.1 Default\ - RGB colour spac\ -e - sRGB\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00.IEC 61966-2.\ -1 Default RGB co\ -lour space - sRG\ -B\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00desc\x00\x00\x00\x00\x00\ -\x00\x00,Reference Vie\ -wing Condition i\ -n IEC61966-2.1\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00,Refere\ -nce Viewing Cond\ -ition in IEC6196\ -6-2.1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00v\ -iew\x00\x00\x00\x00\x00\x13\xa4\xfe\x00\x14_.\x00\ -\x10\xcf\x14\x00\x03\xed\xcc\x00\x04\x13\x0b\x00\x03\x5c\x9e\x00\ -\x00\x00\x01XYZ \x00\x00\x00\x00\x00L\x09V\x00\ -P\x00\x00\x00W\x1f\xe7meas\x00\x00\x00\x00\x00\ -\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x02\x8f\x00\x00\x00\x02sig \x00\ -\x00\x00\x00CRT curv\x00\x00\x00\x00\x00\ -\x00\x04\x00\x00\x00\x00\x05\x00\x0a\x00\x0f\x00\x14\x00\x19\x00\ -\x1e\x00#\x00(\x00-\x002\x007\x00;\x00@\x00\ -E\x00J\x00O\x00T\x00Y\x00^\x00c\x00h\x00\ -m\x00r\x00w\x00|\x00\x81\x00\x86\x00\x8b\x00\x90\x00\ -\x95\x00\x9a\x00\x9f\x00\xa4\x00\xa9\x00\xae\x00\xb2\x00\xb7\x00\ -\xbc\x00\xc1\x00\xc6\x00\xcb\x00\xd0\x00\xd5\x00\xdb\x00\xe0\x00\ -\xe5\x00\xeb\x00\xf0\x00\xf6\x00\xfb\x01\x01\x01\x07\x01\x0d\x01\ -\x13\x01\x19\x01\x1f\x01%\x01+\x012\x018\x01>\x01\ -E\x01L\x01R\x01Y\x01`\x01g\x01n\x01u\x01\ -|\x01\x83\x01\x8b\x01\x92\x01\x9a\x01\xa1\x01\xa9\x01\xb1\x01\ -\xb9\x01\xc1\x01\xc9\x01\xd1\x01\xd9\x01\xe1\x01\xe9\x01\xf2\x01\ -\xfa\x02\x03\x02\x0c\x02\x14\x02\x1d\x02&\x02/\x028\x02\ -A\x02K\x02T\x02]\x02g\x02q\x02z\x02\x84\x02\ -\x8e\x02\x98\x02\xa2\x02\xac\x02\xb6\x02\xc1\x02\xcb\x02\xd5\x02\ -\xe0\x02\xeb\x02\xf5\x03\x00\x03\x0b\x03\x16\x03!\x03-\x03\ -8\x03C\x03O\x03Z\x03f\x03r\x03~\x03\x8a\x03\ -\x96\x03\xa2\x03\xae\x03\xba\x03\xc7\x03\xd3\x03\xe0\x03\xec\x03\ -\xf9\x04\x06\x04\x13\x04 \x04-\x04;\x04H\x04U\x04\ -c\x04q\x04~\x04\x8c\x04\x9a\x04\xa8\x04\xb6\x04\xc4\x04\ -\xd3\x04\xe1\x04\xf0\x04\xfe\x05\x0d\x05\x1c\x05+\x05:\x05\ -I\x05X\x05g\x05w\x05\x86\x05\x96\x05\xa6\x05\xb5\x05\ -\xc5\x05\xd5\x05\xe5\x05\xf6\x06\x06\x06\x16\x06'\x067\x06\ -H\x06Y\x06j\x06{\x06\x8c\x06\x9d\x06\xaf\x06\xc0\x06\ -\xd1\x06\xe3\x06\xf5\x07\x07\x07\x19\x07+\x07=\x07O\x07\ -a\x07t\x07\x86\x07\x99\x07\xac\x07\xbf\x07\xd2\x07\xe5\x07\ -\xf8\x08\x0b\x08\x1f\x082\x08F\x08Z\x08n\x08\x82\x08\ -\x96\x08\xaa\x08\xbe\x08\xd2\x08\xe7\x08\xfb\x09\x10\x09%\x09\ -:\x09O\x09d\x09y\x09\x8f\x09\xa4\x09\xba\x09\xcf\x09\ -\xe5\x09\xfb\x0a\x11\x0a'\x0a=\x0aT\x0aj\x0a\x81\x0a\ -\x98\x0a\xae\x0a\xc5\x0a\xdc\x0a\xf3\x0b\x0b\x0b\x22\x0b9\x0b\ -Q\x0bi\x0b\x80\x0b\x98\x0b\xb0\x0b\xc8\x0b\xe1\x0b\xf9\x0c\ -\x12\x0c*\x0cC\x0c\x5c\x0cu\x0c\x8e\x0c\xa7\x0c\xc0\x0c\ -\xd9\x0c\xf3\x0d\x0d\x0d&\x0d@\x0dZ\x0dt\x0d\x8e\x0d\ -\xa9\x0d\xc3\x0d\xde\x0d\xf8\x0e\x13\x0e.\x0eI\x0ed\x0e\ -\x7f\x0e\x9b\x0e\xb6\x0e\xd2\x0e\xee\x0f\x09\x0f%\x0fA\x0f\ -^\x0fz\x0f\x96\x0f\xb3\x0f\xcf\x0f\xec\x10\x09\x10&\x10\ -C\x10a\x10~\x10\x9b\x10\xb9\x10\xd7\x10\xf5\x11\x13\x11\ -1\x11O\x11m\x11\x8c\x11\xaa\x11\xc9\x11\xe8\x12\x07\x12\ -&\x12E\x12d\x12\x84\x12\xa3\x12\xc3\x12\xe3\x13\x03\x13\ -#\x13C\x13c\x13\x83\x13\xa4\x13\xc5\x13\xe5\x14\x06\x14\ -'\x14I\x14j\x14\x8b\x14\xad\x14\xce\x14\xf0\x15\x12\x15\ -4\x15V\x15x\x15\x9b\x15\xbd\x15\xe0\x16\x03\x16&\x16\ -I\x16l\x16\x8f\x16\xb2\x16\xd6\x16\xfa\x17\x1d\x17A\x17\ -e\x17\x89\x17\xae\x17\xd2\x17\xf7\x18\x1b\x18@\x18e\x18\ -\x8a\x18\xaf\x18\xd5\x18\xfa\x19 \x19E\x19k\x19\x91\x19\ -\xb7\x19\xdd\x1a\x04\x1a*\x1aQ\x1aw\x1a\x9e\x1a\xc5\x1a\ -\xec\x1b\x14\x1b;\x1bc\x1b\x8a\x1b\xb2\x1b\xda\x1c\x02\x1c\ -*\x1cR\x1c{\x1c\xa3\x1c\xcc\x1c\xf5\x1d\x1e\x1dG\x1d\ -p\x1d\x99\x1d\xc3\x1d\xec\x1e\x16\x1e@\x1ej\x1e\x94\x1e\ -\xbe\x1e\xe9\x1f\x13\x1f>\x1fi\x1f\x94\x1f\xbf\x1f\xea \ -\x15 A l \x98 \xc4 \xf0!\x1c!H!\ -u!\xa1!\xce!\xfb\x22'\x22U\x22\x82\x22\xaf\x22\ -\xdd#\x0a#8#f#\x94#\xc2#\xf0$\x1f$\ -M$|$\xab$\xda%\x09%8%h%\x97%\ -\xc7%\xf7&'&W&\x87&\xb7&\xe8'\x18'\ -I'z'\xab'\xdc(\x0d(?(q(\xa2(\ -\xd4)\x06)8)k)\x9d)\xd0*\x02*5*\ -h*\x9b*\xcf+\x02+6+i+\x9d+\xd1,\ -\x05,9,n,\xa2,\xd7-\x0c-A-v-\ -\xab-\xe1.\x16.L.\x82.\xb7.\xee/$/\ -Z/\x91/\xc7/\xfe050l0\xa40\xdb1\ -\x121J1\x821\xba1\xf22*2c2\x9b2\ -\xd43\x0d3F3\x7f3\xb83\xf14+4e4\ -\x9e4\xd85\x135M5\x875\xc25\xfd676\ -r6\xae6\xe97$7`7\x9c7\xd78\x148\ -P8\x8c8\xc89\x059B9\x7f9\xbc9\xf9:\ -6:t:\xb2:\xef;-;k;\xaa;\xe8<\ -'\ - >`>\xa0>\xe0?!?a?\xa2?\xe2@\ -#@d@\xa6@\xe7A)AjA\xacA\xeeB\ -0BrB\xb5B\xf7C:C}C\xc0D\x03D\ -GD\x8aD\xceE\x12EUE\x9aE\xdeF\x22F\ -gF\xabF\xf0G5G{G\xc0H\x05HKH\ -\x91H\xd7I\x1dIcI\xa9I\xf0J7J}J\ -\xc4K\x0cKSK\x9aK\xe2L*LrL\xbaM\ -\x02MJM\x93M\xdcN%NnN\xb7O\x00O\ -IO\x93O\xddP'PqP\xbbQ\x06QPQ\ -\x9bQ\xe6R1R|R\xc7S\x13S_S\xaaS\ -\xf6TBT\x8fT\xdbU(UuU\xc2V\x0fV\ -\x5cV\xa9V\xf7WDW\x92W\xe0X/X}X\ -\xcbY\x1aYiY\xb8Z\x07ZVZ\xa6Z\xf5[\ -E[\x95[\xe5\x5c5\x5c\x86\x5c\xd6]']x]\ -\xc9^\x1a^l^\xbd_\x0f_a_\xb3`\x05`\ -W`\xaa`\xfcaOa\xa2a\xf5bIb\x9cb\ -\xf0cCc\x97c\xebd@d\x94d\xe9e=e\ -\x92e\xe7f=f\x92f\xe8g=g\x93g\xe9h\ -?h\x96h\xeciCi\x9ai\xf1jHj\x9fj\ -\xf7kOk\xa7k\xfflWl\xafm\x08m`m\ -\xb9n\x12nkn\xc4o\x1eoxo\xd1p+p\ -\x86p\xe0q:q\x95q\xf0rKr\xa6s\x01s\ -]s\xb8t\x14tpt\xccu(u\x85u\xe1v\ ->v\x9bv\xf8wVw\xb3x\x11xnx\xccy\ -*y\x89y\xe7zFz\xa5{\x04{c{\xc2|\ -!|\x81|\xe1}A}\xa1~\x01~b~\xc2\x7f\ -#\x7f\x84\x7f\xe5\x80G\x80\xa8\x81\x0a\x81k\x81\xcd\x82\ -0\x82\x92\x82\xf4\x83W\x83\xba\x84\x1d\x84\x80\x84\xe3\x85\ -G\x85\xab\x86\x0e\x86r\x86\xd7\x87;\x87\x9f\x88\x04\x88\ -i\x88\xce\x893\x89\x99\x89\xfe\x8ad\x8a\xca\x8b0\x8b\ -\x96\x8b\xfc\x8cc\x8c\xca\x8d1\x8d\x98\x8d\xff\x8ef\x8e\ -\xce\x8f6\x8f\x9e\x90\x06\x90n\x90\xd6\x91?\x91\xa8\x92\ -\x11\x92z\x92\xe3\x93M\x93\xb6\x94 \x94\x8a\x94\xf4\x95\ -_\x95\xc9\x964\x96\x9f\x97\x0a\x97u\x97\xe0\x98L\x98\ -\xb8\x99$\x99\x90\x99\xfc\x9ah\x9a\xd5\x9bB\x9b\xaf\x9c\ -\x1c\x9c\x89\x9c\xf7\x9dd\x9d\xd2\x9e@\x9e\xae\x9f\x1d\x9f\ -\x8b\x9f\xfa\xa0i\xa0\xd8\xa1G\xa1\xb6\xa2&\xa2\x96\xa3\ -\x06\xa3v\xa3\xe6\xa4V\xa4\xc7\xa58\xa5\xa9\xa6\x1a\xa6\ -\x8b\xa6\xfd\xa7n\xa7\xe0\xa8R\xa8\xc4\xa97\xa9\xa9\xaa\ -\x1c\xaa\x8f\xab\x02\xabu\xab\xe9\xac\x5c\xac\xd0\xadD\xad\ -\xb8\xae-\xae\xa1\xaf\x16\xaf\x8b\xb0\x00\xb0u\xb0\xea\xb1\ -`\xb1\xd6\xb2K\xb2\xc2\xb38\xb3\xae\xb4%\xb4\x9c\xb5\ -\x13\xb5\x8a\xb6\x01\xb6y\xb6\xf0\xb7h\xb7\xe0\xb8Y\xb8\ -\xd1\xb9J\xb9\xc2\xba;\xba\xb5\xbb.\xbb\xa7\xbc!\xbc\ -\x9b\xbd\x15\xbd\x8f\xbe\x0a\xbe\x84\xbe\xff\xbfz\xbf\xf5\xc0\ -p\xc0\xec\xc1g\xc1\xe3\xc2_\xc2\xdb\xc3X\xc3\xd4\xc4\ -Q\xc4\xce\xc5K\xc5\xc8\xc6F\xc6\xc3\xc7A\xc7\xbf\xc8\ -=\xc8\xbc\xc9:\xc9\xb9\xca8\xca\xb7\xcb6\xcb\xb6\xcc\ -5\xcc\xb5\xcd5\xcd\xb5\xce6\xce\xb6\xcf7\xcf\xb8\xd0\ -9\xd0\xba\xd1<\xd1\xbe\xd2?\xd2\xc1\xd3D\xd3\xc6\xd4\ -I\xd4\xcb\xd5N\xd5\xd1\xd6U\xd6\xd8\xd7\x5c\xd7\xe0\xd8\ -d\xd8\xe8\xd9l\xd9\xf1\xdav\xda\xfb\xdb\x80\xdc\x05\xdc\ -\x8a\xdd\x10\xdd\x96\xde\x1c\xde\xa2\xdf)\xdf\xaf\xe06\xe0\ -\xbd\xe1D\xe1\xcc\xe2S\xe2\xdb\xe3c\xe3\xeb\xe4s\xe4\ -\xfc\xe5\x84\xe6\x0d\xe6\x96\xe7\x1f\xe7\xa9\xe82\xe8\xbc\xe9\ -F\xe9\xd0\xea[\xea\xe5\xebp\xeb\xfb\xec\x86\xed\x11\xed\ -\x9c\xee(\xee\xb4\xef@\xef\xcc\xf0X\xf0\xe5\xf1r\xf1\ -\xff\xf2\x8c\xf3\x19\xf3\xa7\xf44\xf4\xc2\xf5P\xf5\xde\xf6\ -m\xf6\xfb\xf7\x8a\xf8\x19\xf8\xa8\xf98\xf9\xc7\xfaW\xfa\ -\xe7\xfbw\xfc\x07\xfc\x98\xfd)\xfd\xba\xfeK\xfe\xdc\xff\ -m\xff\xff\ -\x00\x00\x08A\ -<\ -?xml version=\x221.\ -0\x22 encoding=\x22UTF\ --8\x22?>\x0d\x0a\x0d\x0a \x0d\x0a \ - icon / o\ -utliner / slice \ -/ not active - s\ -aved copy\x0d\x0a Cre\ -ated with Sketch\ -.\x0d\x0a \x0d\x0a \ - \x0d\x0a \ - \x0d\x0a \ - \x0d\x0a\ - \x0d\x0a \ - \x0d\x0a \ - \ -\x0d\x0a \ - \x0d\x0a\ - \x0d\x0a \ - \x0d\x0a\x0d\x0a\ -\ -\x00\x00\x09\xa3\ -<\ -?xml version=\x221.\ -0\x22 encoding=\x22UTF\ --8\x22?>\x0d\x0a\x0d\x0a \x0d\x0a \ - Artboard\ -\x0d\x0a Created with\ - Sketch.\x0d\ -\x0a \x0d\x0a \x0d\x0a \ - \x0d\x0a \ - \x0d\x0a\ - \ -\x0d\x0a \ -\x0d\x0a \ -\x0d\x0a \x0d\x0a\ - \x0d\x0a\ -\x0d\x0a\ -\x00\x00\x02\xb6\ -<\ -?xml version=\x221.\ -0\x22 encoding=\x22UTF\ --8\x22?>\x0d\x0a\x0d\x0a \x0d\x0a \ - Icons / \ -System / Carat /\ - White / Default\ -\x0d\x0a Created with\ - Sketch.\x0d\ -\x0a \x0d\x0a <\ -polygon id=\x22Tria\ -ngle\x22 fill=\x22#FFF\ -FFF\x22 transform=\x22\ -translate(8.0000\ -00, 8.000000) sc\ -ale(1, -1) rotat\ -e(90.000000) tra\ -nslate(-8.000000\ -, -8.000000) \x22 p\ -oints=\x228 6 12 10\ - 4 10\x22>\x0d\x0a \x0d\x0a\x0d\x0a\ -\x00\x00\x8e\x0c\ -I\ -I*\x00\x08\x00\x00\x00\x19\x00\xfe\x00\x04\x00\x01\x00\x00\ -\x00\x00\x00\x00\x00\x00\x01\x03\x00\x01\x00\x00\x00`\x00\x00\ -\x00\x01\x01\x03\x00\x01\x00\x00\x00`\x00\x00\x00\x02\x01\x03\ -\x00\x04\x00\x00\x00:\x01\x00\x00\x03\x01\x03\x00\x01\x00\x00\ -\x00\x05\x00\x00\x00\x06\x01\x03\x00\x01\x00\x00\x00\x02\x00\x00\ -\x00\x11\x01\x04\x00\x01\x00\x00\x00`V\x00\x00\x12\x01\x03\ -\x00\x01\x00\x00\x00\x01\x00\x00\x00\x15\x01\x03\x00\x01\x00\x00\ -\x00\x04\x00\x00\x00\x16\x01\x03\x00\x01\x00\x00\x00`\x00\x00\ -\x00\x17\x01\x04\x00\x01\x00\x00\x00\xd9\x15\x00\x00\x1a\x01\x05\ -\x00\x01\x00\x00\x00B\x01\x00\x00\x1b\x01\x05\x00\x01\x00\x00\ -\x00J\x01\x00\x00\x1c\x01\x03\x00\x01\x00\x00\x00\x01\x00\x00\ -\x00(\x01\x03\x00\x01\x00\x00\x00\x02\x00\x00\x001\x01\x02\ -\x00\x22\x00\x00\x00R\x01\x00\x002\x01\x02\x00\x14\x00\x00\ -\x00t\x01\x00\x00=\x01\x03\x00\x01\x00\x00\x00\x02\x00\x00\ -\x00R\x01\x03\x00\x01\x00\x00\x00\x01\x00\x00\x00\xbc\x02\x01\ -\x00\x1a;\x00\x00\x88\x01\x00\x00\xbb\x83\x07\x00\x0f\x00\x00\ -\x00\xa2<\x00\x00I\x86\x01\x00f\x0d\x00\x00\xb2<\x00\ -\x00i\x87\x04\x00\x01\x00\x00\x00\x0a\x0a \x0a\ - \x0a \ - Adobe Photosho\ -p CC 2015.5 (Win\ -dows)\x0a \ - 2017-03-07T11:3\ -2:29-08:00\x0a \ - 2017-04-04T\ -11:28-07:00\x0a \ - 2017-04-\ -04T11:28-07:00\x0a image/tiff\ -\x0a \ - 3\x0a sRGB IEC61966-\ -2.1\x0a \ - \x0a \x0a \ - a\ -dobe:docid:photo\ -shop:94a27cdb-04\ -33-11e7-b02d-9f8\ -4d9f5a326\x0a \ - adobe:\ -docid:photoshop:\ -acaee4ff-1960-11\ -e7-bae7-e6e7a5cd\ -2814\x0a \ - \x0a \x0a \ - xmp.iid:\ -fa5f33a4-5729-d3\ -41-9ab8-5edce3a2\ -68a4\x0a \ - adobe:docid:p\ -hotoshop:696e80e\ -4-1964-11e7-8c4b\ --d6fec7ab83c2\ -\x0a xmp.did:ca77\ -1a70-f965-e14f-9\ -103-360465543dbf\ -\x0a \ - \x0a \ - \x0a \ - \x0a \ - crea\ -ted\x0a \ - xmp.iid:c\ -a771a70-f965-e14\ -f-9103-360465543\ -dbf\x0a \ - 2017-03-07T\ -11:32:29-08:00\x0a \ - Adobe Photosh\ -op CC 2015.5 (Wi\ -ndows)\x0a \ - \x0a \ - \x0a \ - saved\x0a \ - \ -xmp.iid:16fdf09c\ --857d-944e-9783-\ -e127cb1b9cf4\x0a\ - \ - 20\ -17-03-08T11:37:4\ -5-08:00\x0a \ - Adob\ -e Photoshop CC 2\ -015.5 (Windows)<\ -/stEvt:softwareA\ -gent>\x0a \ - /\x0a \ - \x0a \ - \x0a \ - saved\x0a \ - xmp.\ -iid:fa5f33a4-572\ -9-d341-9ab8-5edc\ -e3a268a4\x0a \ - 2017-0\ -4-04T11:28-07:00\ -\x0a \ - \ -Adobe Photo\ -shop CC 2017 (Wi\ -ndows)\x0a \ - <\ -stEvt:changed>/<\ -/stEvt:changed>\x0a\ - <\ -/rdf:li>\x0a \ - \x0a\ - \x0a \ -\x0a \ -\x0a\x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ -\x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a\ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ -\x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a\ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ -\x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a\ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ -\x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a\ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ -\x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a\ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ -\x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a\ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ -\x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a\ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \x0a \ - \ - \ - \ - \ - \ - \ -\x0a \ - \x0a\x1c\x01Z\x00\x03\x1b%G\x1c\x02\x00\x00\x02\x00\x00\ -\x008BIM\x04%\x00\x00\x00\x00\x00\x10\xcd\xcf\xfa\ -}\xa8\xc7\xbe\x09\x05pv\xae\xaf\x05\xc3N8BI\ -M\x04:\x00\x00\x00\x00\x00\xe5\x00\x00\x00\x10\x00\x00\x00\ -\x01\x00\x00\x00\x00\x00\x0bprintOutp\ -ut\x00\x00\x00\x05\x00\x00\x00\x00PstSbo\ -ol\x01\x00\x00\x00\x00Inteenum\x00\ -\x00\x00\x00Inte\x00\x00\x00\x00Clrm\x00\ -\x00\x00\x0fprintSixteenB\ -itbool\x00\x00\x00\x00\x0bprint\ -erNameTEXT\x00\x00\x00\x01\x00\x00\ -\x00\x00\x00\x0fprintProofSe\ -tupObjc\x00\x00\x00\x0c\x00P\x00r\x00\ -o\x00o\x00f\x00 \x00S\x00e\x00t\x00u\x00\ -p\x00\x00\x00\x00\x00\x0aproofSetu\ -p\x00\x00\x00\x01\x00\x00\x00\x00Bltnenu\ -m\x00\x00\x00\x0cbuiltinProo\ -f\x00\x00\x00\x09proofCMYK\x008\ -BIM\x04;\x00\x00\x00\x00\x02-\x00\x00\x00\x10\x00\ -\x00\x00\x01\x00\x00\x00\x00\x00\x12printOu\ -tputOptions\x00\x00\x00\x17\x00\ -\x00\x00\x00Cptnbool\x00\x00\x00\x00\x00\ -Clbrbool\x00\x00\x00\x00\x00Rgs\ -Mbool\x00\x00\x00\x00\x00CrnCbo\ -ol\x00\x00\x00\x00\x00CntCbool\x00\ -\x00\x00\x00\x00Lblsbool\x00\x00\x00\x00\ -\x00Ngtvbool\x00\x00\x00\x00\x00Em\ -lDbool\x00\x00\x00\x00\x00Intrb\ -ool\x00\x00\x00\x00\x00BckgObjc\ -\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00RGBC\x00\x00\ -\x00\x03\x00\x00\x00\x00Rd doub@o\ -\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00Grn do\ -ub@o\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00Bl\ - doub@o\xe0\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00BrdTUntF#Rlt\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00Bld Un\ -tF#Rlt\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00RsltUntF#Pxl@b\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0avector\ -Databool\x01\x00\x00\x00\x00PgP\ -senum\x00\x00\x00\x00PgPs\x00\x00\x00\ -\x00PgPC\x00\x00\x00\x00LeftUnt\ -F#Rlt\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00Top UntF#Rlt\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00Scl Unt\ -F#Prc@Y\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x10cropWhenPrintin\ -gbool\x00\x00\x00\x00\x0ecropRe\ -ctBottomlong\x00\x00\x00\x00\ -\x00\x00\x00\x0ccropRectLeft\ -long\x00\x00\x00\x00\x00\x00\x00\x0dcrop\ -RectRightlong\x00\x00\x00\ -\x00\x00\x00\x00\x0bcropRectTop\ -long\x00\x00\x00\x00\x008BIM\x03\xed\x00\ -\x00\x00\x00\x00\x10\x00\x90\x00\x00\x00\x01\x00\x01\x00\x90\x00\ -\x00\x00\x01\x00\x018BIM\x04&\x00\x00\x00\x00\x00\ -\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00?\x80\x00\x008\ -BIM\x03\xee\x00\x00\x00\x00\x00\x0d\x0cTran\ -sparency\x008BIM\x04\x15\x00\ -\x00\x00\x00\x00\x1e\x00\x00\x00\x0d\x00T\x00r\x00a\x00\ -n\x00s\x00p\x00a\x00r\x00e\x00n\x00c\x00\ -y\x00\x008BIM\x045\x00\x00\x00\x00\x00\x11\x00\ -\x00\x00\x01\x00\x00\xff\xff\x00\x00\x00\x00\x00\x00\x00d\x01\ -\x008BIM\x04\x1d\x00\x00\x00\x00\x00\x04\x00\x00\x00\ -\x008BIM\x03\xf2\x00\x00\x00\x00\x00\x0a\x00\x00\xff\ -\xff\xff\xff\xff\xff\x00\x008BIM\x04\x0d\x00\x00\x00\ -\x00\x00\x04\x00\x00\x00\x1e8BIM\x04\x19\x00\x00\x00\ -\x00\x00\x04\x00\x00\x00\x1e8BIM\x03\xf3\x00\x00\x00\ -\x00\x00\x09\x00\x00\x00\x00\x00\x00\x00\x00\x01\x008BI\ -M'\x10\x00\x00\x00\x00\x00\x0a\x00\x01\x00\x00\x00\x00\x00\ -\x00\x00\x018BIM\x03\xf5\x00\x00\x00\x00\x00H\x00\ -/ff\x00\x01\x00lff\x00\x06\x00\x00\x00\x00\x00\ -\x01\x00/ff\x00\x01\x00\xa1\x99\x9a\x00\x06\x00\x00\x00\ -\x00\x00\x01\x002\x00\x00\x00\x01\x00Z\x00\x00\x00\x06\x00\ -\x00\x00\x00\x00\x01\x005\x00\x00\x00\x01\x00-\x00\x00\x00\ -\x06\x00\x00\x00\x00\x00\x018BIM\x03\xf8\x00\x00\x00\ -\x00\x00p\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x03\xe8\x00\x00\x00\ -\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\x03\xe8\x00\x00\x00\x00\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\x03\xe8\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x03\ -\xe8\x00\x008BIM\x04\x00\x00\x00\x00\x00\x00\x02\x00\ -\x008BIM\x04\x02\x00\x00\x00\x00\x00\x02\x00\x008\ -BIM\x040\x00\x00\x00\x00\x00\x01\x01\x008BI\ -M\x04-\x00\x00\x00\x00\x00\x06\x00\x01\x00\x00\x00\x038\ -BIM\x04\x08\x00\x00\x00\x00\x00\x10\x00\x00\x00\x01\x00\ -\x00\x02@\x00\x00\x02@\x00\x00\x00\x008BIM\x04\ -\x1e\x00\x00\x00\x00\x00\x04\x00\x00\x00\x008BIM\x04\ -\x1a\x00\x00\x00\x00\x035\x00\x00\x00\x06\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00`\x00\x00\x00`\x00\x00\x00\x00\x00\ -\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00`\x00\x00\x00`\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x01\ -\x00\x00\x00\x00\x00\x00null\x00\x00\x00\x02\x00\x00\ -\x00\x06boundsObjc\x00\x00\x00\x01\ -\x00\x00\x00\x00\x00\x00Rct1\x00\x00\x00\x04\x00\x00\ -\x00\x00Top long\x00\x00\x00\x00\x00\x00\ -\x00\x00Leftlong\x00\x00\x00\x00\x00\x00\ -\x00\x00Btomlong\x00\x00\x00`\x00\x00\ -\x00\x00Rghtlong\x00\x00\x00`\x00\x00\ -\x00\x06slicesVlLs\x00\x00\x00\x01\ -Objc\x00\x00\x00\x01\x00\x00\x00\x00\x00\x05sl\ -ice\x00\x00\x00\x12\x00\x00\x00\x07slice\ -IDlong\x00\x00\x00\x00\x00\x00\x00\x07gr\ -oupIDlong\x00\x00\x00\x00\x00\x00\x00\ -\x06originenum\x00\x00\x00\x0cE\ -SliceOrigin\x00\x00\x00\x0da\ -utoGenerated\x00\x00\x00\x00\ -Typeenum\x00\x00\x00\x0aESli\ -ceType\x00\x00\x00\x00Img \x00\x00\ -\x00\x06boundsObjc\x00\x00\x00\x01\ -\x00\x00\x00\x00\x00\x00Rct1\x00\x00\x00\x04\x00\x00\ -\x00\x00Top long\x00\x00\x00\x00\x00\x00\ -\x00\x00Leftlong\x00\x00\x00\x00\x00\x00\ -\x00\x00Btomlong\x00\x00\x00`\x00\x00\ -\x00\x00Rghtlong\x00\x00\x00`\x00\x00\ -\x00\x03urlTEXT\x00\x00\x00\x01\x00\x00\x00\ -\x00\x00\x00nullTEXT\x00\x00\x00\x01\x00\ -\x00\x00\x00\x00\x00MsgeTEXT\x00\x00\x00\ -\x01\x00\x00\x00\x00\x00\x06altTagTEX\ -T\x00\x00\x00\x01\x00\x00\x00\x00\x00\x0ecellT\ -extIsHTMLbool\x01\x00\x00\ -\x00\x08cellTextTEXT\x00\x00\ -\x00\x01\x00\x00\x00\x00\x00\x09horzAlig\ -nenum\x00\x00\x00\x0fESliceH\ -orzAlign\x00\x00\x00\x07defa\ -ult\x00\x00\x00\x09vertAlign\ -enum\x00\x00\x00\x0fESliceVe\ -rtAlign\x00\x00\x00\x07defau\ -lt\x00\x00\x00\x0bbgColorTyp\ -eenum\x00\x00\x00\x11ESliceB\ -GColorType\x00\x00\x00\x00No\ -ne\x00\x00\x00\x09topOutsetl\ -ong\x00\x00\x00\x00\x00\x00\x00\x0aleftO\ -utsetlong\x00\x00\x00\x00\x00\x00\x00\ -\x0cbottomOutsetlon\ -g\x00\x00\x00\x00\x00\x00\x00\x0brightOu\ -tsetlong\x00\x00\x00\x00\x008BI\ -M\x04(\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x02?\xf0\x00\ -\x00\x00\x00\x00\x008BIM\x04\x14\x00\x00\x00\x00\x00\ -\x04\x00\x00\x00\x0d8BIM\x04\x0c\x00\x00\x00\x00\x03\ -\xfb\x00\x00\x00\x01\x00\x00\x000\x00\x00\x000\x00\x00\x00\ -\x90\x00\x00\x1b\x00\x00\x00\x03\xdf\x00\x18\x00\x01\xff\xd8\xff\ -\xed\x00\x0cAdobe_CM\x00\x01\xff\xee\x00\ -\x0eAdobe\x00d\x80\x00\x00\x00\x01\xff\xdb\x00\ -\x84\x00\x0c\x08\x08\x08\x09\x08\x0c\x09\x09\x0c\x11\x0b\x0a\x0b\ -\x11\x15\x0f\x0c\x0c\x0f\x15\x18\x13\x13\x15\x13\x13\x18\x11\x0c\ -\x0c\x0c\x0c\x0c\x0c\x11\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\ -\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\ -\x0c\x0c\x01\x0d\x0b\x0b\x0d\x0e\x0d\x10\x0e\x0e\x10\x14\x0e\x0e\ -\x0e\x14\x14\x0e\x0e\x0e\x0e\x14\x11\x0c\x0c\x0c\x0c\x0c\x11\x11\ -\x0c\x0c\x0c\x0c\x0c\x0c\x11\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\ -\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\ -\x0c\x0c\x0c\xff\xc0\x00\x11\x08\x000\x000\x03\x01\x22\x00\ -\x02\x11\x01\x03\x11\x01\xff\xdd\x00\x04\x00\x03\xff\xc4\x01?\ -\x00\x00\x01\x05\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\ -\x00\x03\x00\x01\x02\x04\x05\x06\x07\x08\x09\x0a\x0b\x01\x00\x01\ -\x05\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\ -\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x10\x00\x01\x04\x01\x03\ -\x02\x04\x02\x05\x07\x06\x08\x05\x03\x0c3\x01\x00\x02\x11\x03\ -\x04!\x121\x05AQa\x13\x22q\x812\x06\x14\x91\ -\xa1\xb1B#$\x15R\xc1b34r\x82\xd1C\x07\ -%\x92S\xf0\xe1\xf1cs5\x16\xa2\xb2\x83&D\x93\ -TdE\xc2\xa3t6\x17\xd2U\xe2e\xf2\xb3\x84\xc3\ -\xd3u\xe3\xf3F'\x94\xa4\x85\xb4\x95\xc4\xd4\xe4\xf4\xa5\ -\xb5\xc5\xd5\xe5\xf5Vfv\x86\x96\xa6\xb6\xc6\xd6\xe6\xf6\ -7GWgw\x87\x97\xa7\xb7\xc7\xd7\xe7\xf7\x11\x00\x02\ -\x02\x01\x02\x04\x04\x03\x04\x05\x06\x07\x07\x06\x055\x01\x00\ -\x02\x11\x03!1\x12\x04AQaq\x22\x13\x052\x81\ -\x91\x14\xa1\xb1B#\xc1R\xd1\xf03$b\xe1r\x82\ -\x92CS\x15cs4\xf1%\x06\x16\xa2\xb2\x83\x07&\ -5\xc2\xd2D\x93T\xa3\x17dEU6te\xe2\xf2\ -\xb3\x84\xc3\xd3u\xe3\xf3F\x94\xa4\x85\xb4\x95\xc4\xd4\xe4\ -\xf4\xa5\xb5\xc5\xd5\xe5\xf5Vfv\x86\x96\xa6\xb6\xc6\xd6\ -\xe6\xf6'7GWgw\x87\x97\xa7\xb7\xc7\xff\xda\x00\ -\x0c\x03\x01\x00\x02\x11\x03\x11\x00?\x00\xf4<\xdc\xcc\x96\ -d\x9a\xa9;@\x80\x00\x00\x92O\xc6P\xfd~\xab\xe0\ -\xff\x00\xfbl\x7f\xe4R\xc9\xff\x00\x95\x1b\xfdz\xff\x00\ -\xef\xabN\xd79\x95\xb9\xcdi{\x9a\x09\x0d\x1c\x92\x92\ -\x9c\xa7e\xf5\x16}79\xb3\xc6\xe6\xb4~V\xa7n\ -OSp\x96\x978\x1e\xe1\x80\x8f\xc1\xaa\xc6.\x0bl\ -g\xaf\x96\xd2\xfb\xac\xd4\xee\x9d\x07a\xb53\xea\x18Y\ -5>\x92EW81\xec\x99\x12x))\x0f\xaf\xd5\ -|\x1f\xfe`\xff\x00\xc8\xa2`fdY\x91\xe9Zw\ -\x02\x0f \x02\x08\xfe\xaa\xd2Y\x18?\xf2\x81\xff\x00\xae\ -~T\x94\xff\x00\xff\xd0\xef\xf2\x7f\xe5F\xff\x00^\xbf\ -\xfb\xea\xd0\xc9\xca\xaf\x19\xa0\xbeIq\x86\xb5\xa2IY\ -\xf9?\xf2\xa3\x7f\xaf_\xfd\xf5Y\xea\x9e\xd6Soz\ -\xec\x07\xe5\xfe\xa1%-\xf6\xfb\xdd\xfc\xde+\xcf\x81v\ -\x9f\xc1\x0a\xe6\xf5\x0b\x9c\xcb\x9f[X)\x975\xa4\xce\ -\xbc\xce\x9f\x05k<\xde1\x9c\xeaL\x11\xab\x88\xe7h\ -\xfa[R\xc1u\x96b5\xd6\x9d\xc5\xd3\x07\xbcN\x9b\ -\x92S\x01E\x01L\x01\ -R\x01Y\x01`\x01g\x01n\x01u\x01|\x01\x83\x01\ -\x8b\x01\x92\x01\x9a\x01\xa1\x01\xa9\x01\xb1\x01\xb9\x01\xc1\x01\ -\xc9\x01\xd1\x01\xd9\x01\xe1\x01\xe9\x01\xf2\x01\xfa\x02\x03\x02\ -\x0c\x02\x14\x02\x1d\x02&\x02/\x028\x02A\x02K\x02\ -T\x02]\x02g\x02q\x02z\x02\x84\x02\x8e\x02\x98\x02\ -\xa2\x02\xac\x02\xb6\x02\xc1\x02\xcb\x02\xd5\x02\xe0\x02\xeb\x02\ -\xf5\x03\x00\x03\x0b\x03\x16\x03!\x03-\x038\x03C\x03\ -O\x03Z\x03f\x03r\x03~\x03\x8a\x03\x96\x03\xa2\x03\ -\xae\x03\xba\x03\xc7\x03\xd3\x03\xe0\x03\xec\x03\xf9\x04\x06\x04\ -\x13\x04 \x04-\x04;\x04H\x04U\x04c\x04q\x04\ -~\x04\x8c\x04\x9a\x04\xa8\x04\xb6\x04\xc4\x04\xd3\x04\xe1\x04\ -\xf0\x04\xfe\x05\x0d\x05\x1c\x05+\x05:\x05I\x05X\x05\ -g\x05w\x05\x86\x05\x96\x05\xa6\x05\xb5\x05\xc5\x05\xd5\x05\ -\xe5\x05\xf6\x06\x06\x06\x16\x06'\x067\x06H\x06Y\x06\ -j\x06{\x06\x8c\x06\x9d\x06\xaf\x06\xc0\x06\xd1\x06\xe3\x06\ -\xf5\x07\x07\x07\x19\x07+\x07=\x07O\x07a\x07t\x07\ -\x86\x07\x99\x07\xac\x07\xbf\x07\xd2\x07\xe5\x07\xf8\x08\x0b\x08\ -\x1f\x082\x08F\x08Z\x08n\x08\x82\x08\x96\x08\xaa\x08\ -\xbe\x08\xd2\x08\xe7\x08\xfb\x09\x10\x09%\x09:\x09O\x09\ -d\x09y\x09\x8f\x09\xa4\x09\xba\x09\xcf\x09\xe5\x09\xfb\x0a\ -\x11\x0a'\x0a=\x0aT\x0aj\x0a\x81\x0a\x98\x0a\xae\x0a\ -\xc5\x0a\xdc\x0a\xf3\x0b\x0b\x0b\x22\x0b9\x0bQ\x0bi\x0b\ -\x80\x0b\x98\x0b\xb0\x0b\xc8\x0b\xe1\x0b\xf9\x0c\x12\x0c*\x0c\ -C\x0c\x5c\x0cu\x0c\x8e\x0c\xa7\x0c\xc0\x0c\xd9\x0c\xf3\x0d\ -\x0d\x0d&\x0d@\x0dZ\x0dt\x0d\x8e\x0d\xa9\x0d\xc3\x0d\ -\xde\x0d\xf8\x0e\x13\x0e.\x0eI\x0ed\x0e\x7f\x0e\x9b\x0e\ -\xb6\x0e\xd2\x0e\xee\x0f\x09\x0f%\x0fA\x0f^\x0fz\x0f\ -\x96\x0f\xb3\x0f\xcf\x0f\xec\x10\x09\x10&\x10C\x10a\x10\ -~\x10\x9b\x10\xb9\x10\xd7\x10\xf5\x11\x13\x111\x11O\x11\ -m\x11\x8c\x11\xaa\x11\xc9\x11\xe8\x12\x07\x12&\x12E\x12\ -d\x12\x84\x12\xa3\x12\xc3\x12\xe3\x13\x03\x13#\x13C\x13\ -c\x13\x83\x13\xa4\x13\xc5\x13\xe5\x14\x06\x14'\x14I\x14\ -j\x14\x8b\x14\xad\x14\xce\x14\xf0\x15\x12\x154\x15V\x15\ -x\x15\x9b\x15\xbd\x15\xe0\x16\x03\x16&\x16I\x16l\x16\ -\x8f\x16\xb2\x16\xd6\x16\xfa\x17\x1d\x17A\x17e\x17\x89\x17\ -\xae\x17\xd2\x17\xf7\x18\x1b\x18@\x18e\x18\x8a\x18\xaf\x18\ -\xd5\x18\xfa\x19 \x19E\x19k\x19\x91\x19\xb7\x19\xdd\x1a\ -\x04\x1a*\x1aQ\x1aw\x1a\x9e\x1a\xc5\x1a\xec\x1b\x14\x1b\ -;\x1bc\x1b\x8a\x1b\xb2\x1b\xda\x1c\x02\x1c*\x1cR\x1c\ -{\x1c\xa3\x1c\xcc\x1c\xf5\x1d\x1e\x1dG\x1dp\x1d\x99\x1d\ -\xc3\x1d\xec\x1e\x16\x1e@\x1ej\x1e\x94\x1e\xbe\x1e\xe9\x1f\ -\x13\x1f>\x1fi\x1f\x94\x1f\xbf\x1f\xea \x15 A \ -l \x98 \xc4 \xf0!\x1c!H!u!\xa1!\ -\xce!\xfb\x22'\x22U\x22\x82\x22\xaf\x22\xdd#\x0a#\ -8#f#\x94#\xc2#\xf0$\x1f$M$|$\ -\xab$\xda%\x09%8%h%\x97%\xc7%\xf7&\ -'&W&\x87&\xb7&\xe8'\x18'I'z'\ -\xab'\xdc(\x0d(?(q(\xa2(\xd4)\x06)\ -8)k)\x9d)\xd0*\x02*5*h*\x9b*\ -\xcf+\x02+6+i+\x9d+\xd1,\x05,9,\ -n,\xa2,\xd7-\x0c-A-v-\xab-\xe1.\ -\x16.L.\x82.\xb7.\xee/$/Z/\x91/\ -\xc7/\xfe050l0\xa40\xdb1\x121J1\ -\x821\xba1\xf22*2c2\x9b2\xd43\x0d3\ -F3\x7f3\xb83\xf14+4e4\x9e4\xd85\ -\x135M5\x875\xc25\xfd676r6\xae6\ -\xe97$7`7\x9c7\xd78\x148P8\x8c8\ -\xc89\x059B9\x7f9\xbc9\xf9:6:t:\ -\xb2:\xef;-;k;\xaa;\xe8<' >`>\ -\xa0>\xe0?!?a?\xa2?\xe2@#@d@\ -\xa6@\xe7A)AjA\xacA\xeeB0BrB\ -\xb5B\xf7C:C}C\xc0D\x03DGD\x8aD\ -\xceE\x12EUE\x9aE\xdeF\x22FgF\xabF\ -\xf0G5G{G\xc0H\x05HKH\x91H\xd7I\ -\x1dIcI\xa9I\xf0J7J}J\xc4K\x0cK\ -SK\x9aK\xe2L*LrL\xbaM\x02MJM\ -\x93M\xdcN%NnN\xb7O\x00OIO\x93O\ -\xddP'PqP\xbbQ\x06QPQ\x9bQ\xe6R\ -1R|R\xc7S\x13S_S\xaaS\xf6TBT\ -\x8fT\xdbU(UuU\xc2V\x0fV\x5cV\xa9V\ -\xf7WDW\x92W\xe0X/X}X\xcbY\x1aY\ -iY\xb8Z\x07ZVZ\xa6Z\xf5[E[\x95[\ -\xe5\x5c5\x5c\x86\x5c\xd6]']x]\xc9^\x1a^\ -l^\xbd_\x0f_a_\xb3`\x05`W`\xaa`\ -\xfcaOa\xa2a\xf5bIb\x9cb\xf0cCc\ -\x97c\xebd@d\x94d\xe9e=e\x92e\xe7f\ -=f\x92f\xe8g=g\x93g\xe9h?h\x96h\ -\xeciCi\x9ai\xf1jHj\x9fj\xf7kOk\ -\xa7k\xfflWl\xafm\x08m`m\xb9n\x12n\ -kn\xc4o\x1eoxo\xd1p+p\x86p\xe0q\ -:q\x95q\xf0rKr\xa6s\x01s]s\xb8t\ -\x14tpt\xccu(u\x85u\xe1v>v\x9bv\ -\xf8wVw\xb3x\x11xnx\xccy*y\x89y\ -\xe7zFz\xa5{\x04{c{\xc2|!|\x81|\ -\xe1}A}\xa1~\x01~b~\xc2\x7f#\x7f\x84\x7f\ -\xe5\x80G\x80\xa8\x81\x0a\x81k\x81\xcd\x820\x82\x92\x82\ -\xf4\x83W\x83\xba\x84\x1d\x84\x80\x84\xe3\x85G\x85\xab\x86\ -\x0e\x86r\x86\xd7\x87;\x87\x9f\x88\x04\x88i\x88\xce\x89\ -3\x89\x99\x89\xfe\x8ad\x8a\xca\x8b0\x8b\x96\x8b\xfc\x8c\ -c\x8c\xca\x8d1\x8d\x98\x8d\xff\x8ef\x8e\xce\x8f6\x8f\ -\x9e\x90\x06\x90n\x90\xd6\x91?\x91\xa8\x92\x11\x92z\x92\ -\xe3\x93M\x93\xb6\x94 \x94\x8a\x94\xf4\x95_\x95\xc9\x96\ -4\x96\x9f\x97\x0a\x97u\x97\xe0\x98L\x98\xb8\x99$\x99\ -\x90\x99\xfc\x9ah\x9a\xd5\x9bB\x9b\xaf\x9c\x1c\x9c\x89\x9c\ -\xf7\x9dd\x9d\xd2\x9e@\x9e\xae\x9f\x1d\x9f\x8b\x9f\xfa\xa0\ -i\xa0\xd8\xa1G\xa1\xb6\xa2&\xa2\x96\xa3\x06\xa3v\xa3\ -\xe6\xa4V\xa4\xc7\xa58\xa5\xa9\xa6\x1a\xa6\x8b\xa6\xfd\xa7\ -n\xa7\xe0\xa8R\xa8\xc4\xa97\xa9\xa9\xaa\x1c\xaa\x8f\xab\ -\x02\xabu\xab\xe9\xac\x5c\xac\xd0\xadD\xad\xb8\xae-\xae\ -\xa1\xaf\x16\xaf\x8b\xb0\x00\xb0u\xb0\xea\xb1`\xb1\xd6\xb2\ -K\xb2\xc2\xb38\xb3\xae\xb4%\xb4\x9c\xb5\x13\xb5\x8a\xb6\ -\x01\xb6y\xb6\xf0\xb7h\xb7\xe0\xb8Y\xb8\xd1\xb9J\xb9\ -\xc2\xba;\xba\xb5\xbb.\xbb\xa7\xbc!\xbc\x9b\xbd\x15\xbd\ -\x8f\xbe\x0a\xbe\x84\xbe\xff\xbfz\xbf\xf5\xc0p\xc0\xec\xc1\ -g\xc1\xe3\xc2_\xc2\xdb\xc3X\xc3\xd4\xc4Q\xc4\xce\xc5\ -K\xc5\xc8\xc6F\xc6\xc3\xc7A\xc7\xbf\xc8=\xc8\xbc\xc9\ -:\xc9\xb9\xca8\xca\xb7\xcb6\xcb\xb6\xcc5\xcc\xb5\xcd\ -5\xcd\xb5\xce6\xce\xb6\xcf7\xcf\xb8\xd09\xd0\xba\xd1\ -<\xd1\xbe\xd2?\xd2\xc1\xd3D\xd3\xc6\xd4I\xd4\xcb\xd5\ -N\xd5\xd1\xd6U\xd6\xd8\xd7\x5c\xd7\xe0\xd8d\xd8\xe8\xd9\ -l\xd9\xf1\xdav\xda\xfb\xdb\x80\xdc\x05\xdc\x8a\xdd\x10\xdd\ -\x96\xde\x1c\xde\xa2\xdf)\xdf\xaf\xe06\xe0\xbd\xe1D\xe1\ -\xcc\xe2S\xe2\xdb\xe3c\xe3\xeb\xe4s\xe4\xfc\xe5\x84\xe6\ -\x0d\xe6\x96\xe7\x1f\xe7\xa9\xe82\xe8\xbc\xe9F\xe9\xd0\xea\ -[\xea\xe5\xebp\xeb\xfb\xec\x86\xed\x11\xed\x9c\xee(\xee\ -\xb4\xef@\xef\xcc\xf0X\xf0\xe5\xf1r\xf1\xff\xf2\x8c\xf3\ -\x19\xf3\xa7\xf44\xf4\xc2\xf5P\xf5\xde\xf6m\xf6\xfb\xf7\ -\x8a\xf8\x19\xf8\xa8\xf98\xf9\xc7\xfaW\xfa\xe7\xfbw\xfc\ -\x07\xfc\x98\xfd)\xfd\xba\xfeK\xfe\xdc\xffm\xff\xff\x80\ -\x00 P8$\x16\x0d\x07\x84BaP\xb8d6\x1d\ -\x0f\x88DbQ8\xa4V-\x17\x8cFcQ\xb8\xe4\ -v=\x1f\x90HdR9$\x96M'\x94JeR\ -\xb9d\xb6]/\x98A\x00\x930(*l\x0c\x9c\x03\ -\x02\x13`P0\x07?\x02?\xe8O\xe8X\x06 \x01\ -\xa4\x00hO\xfa$\x1a\x93H\x82R\xdf\xf0J}J\ -\x06\xff\xa4\x80\xa9t\xd0\x05\x1a\x07U\xa5\xd5\xeb\xf4\xfa\ -\x8d\x86\x05S\x81S\xe9VhK\xfc\x05o\x01\xd5\xaa\ -\xf6\xca\x8d~\x0fh\xb4\xd2\x00P\x8a\x95\x92\xefK\xb0\ -P\xacW\x9aM\xca\x9dI\xbe]05\xca\xf0\x02\x98\ -\xfe\xc8>\xf2O\xa7\xa6U\xe2\xf3\xcc<2O\xb7\xce\ -\x1aSO\x07\xe8Bcm!\x10\x87\xa7)\x89\xb5C\ -\x00v\xb4#?\x01\x81*\x98\x88]\xf7i\x87\xa4g\ -\xb18+\x1e\xe7\x01\xb7\x8e\xed\xaa\x17:\x15\xfa\x0d\xba\ -\xde\xda\xf7\x98Ln;\x7f\xbe\xe2\xf0!\x99\xec\x0d\xe2\ -\xbbj\xe8T\xab\x18^\x7f6\x9f\x90\xc8uz\xbb>\ -\xcf\x81\xfc\xf8\xf4=\x9c\xbe\xb6\xf3#\xdc\xbaa|V\ -N\x0f\xa3c6\xfa\x94\x04\xbfAb\xcf\xf4\xe0)\xc0\ -\x03:r\x08-\xebzc\x03\xc1\x10L\x15\x05>\xe6\ -\x94\x1cc\x13p\x89\x04h\xc2\x86+\xee\x90\x00\xd0\xc8\ -\x10(C\x83 \xdb\x0f\x91\x00LD\x05\xc1q,M\ -\x13\xc5\x09B\xa4fE\x85\xf9\x17\x17\x8d\xa6\xfcdk\ -\xb9\x08\xb0;\x1b\x84\x84LtV5A0_\x14\xc8\ -\x12\x0c\x85!\xa2\xe7\xd4\x8c|\x93RI\x00SI\x84\ -|\x8c}\x1f(\xc4\x0a\x01\x07\xb2\xa8\x9aCK\x058\ -\x0f-\x812$\xbd/\xcc\x13\x0a\x04gL\x86\x08\xed\ -3\x8a\x87\x84\xd4v#\x09\x98\x08\x02\x8a\xf3\x88\xda7\ -\xce\x84\x5c\xa71O\x13\xcc\xf5\x03\x9d\x13\xe9\xc44P\ -\x02\x11\xc9A\x9b\xa8\xc42\x03\x01\x03-\x14?\x0c\x14\ -h\xf0\xe3Ot\x8d%I\xa3\xe7\x95,w\x0c\x94\xc8\ -|oS\x86\xad\x0d\x0d\x0d\x95\x09\x0e\xfe\x8b#}!\ -JU\x15MT\x873\x07\x99\xe1E\x0c\xa1\xf1\xb9Y\ -\x9ah\xc4\xb6\x03\x810\xf8\xdaDN\x22\xb8\xdbS\xc4\ -\xae\x13\x9bU\xc8q\xab\xae\xe1\xa1V\x15UV\x9e\x14\ -\xc8\xc8\x1e\x9b\xb6\x89\xa9O\xd1\x03u\xacD\xd7\xb5\xfb\ -\xa4\x89\xaaF\xdd\xbch\x9e\xb7\x09\xe6\xea\xcav\x13\xa8\ -\xe0\x1f\xb7I\xfb;\xb8\x8e\xdb\xb2\xf29Wr\xd4\x82\ -<\xc8E!C\x81\x17\xc8\x10\x05P\xe0<\xdc\x02\xa0\ -\x97Q\xf8|\xe0\x87\xc6\x08|\x9e\xefA\xf0{C\ -<\x01\x08\x0eli\xb9\xd4\xf2k@p\x12xa\xfd\ -\xfd\x06\xe5&+\xe0\x80\x9b\x12\xf0L>\x8e\xe8,:\ -]\xbb\xe7\x02\x0f\xa5\x17\xbe\xc7\xdc\xfc\x08z\xcc\x80!\ -\x9c 6\x11\xb44V\xa0\x08yn\x89\xcb\x198F\ -\x10\x10p\xd2\x18\xe9\x85\x90\x00\xb0\x1c%!\xc0\xb9p\ -\xa0\xb5\xc3\xb9\xe1\x93\x0f\xc5\xda\xba\x09\x0b\xd5T\xc1\xa0\ -(\x22\xa2@\xadw\xc0\xc8\x1f8\x86J\xf0\xc1\xfc&\ -\x85\x0eA\xfc*(\x1b\x08\x08s\xd0QOI\xea&\ -\x10\xef\x17\xc4\xa8U\x8cA\xa8\x8c\x0c\xb9\x5c\ -/b!\x16_\xf1,\x1f8\xa0\xc6\x1f#\xb83\x08\ -\x04`O\xcb\xd1\x0e%f\x00zRq\x19\xf5\x0a\xe0\ -c1\xc1\xe9\x1c\x5c#\xd4yK`y%\x1f\xbb.\ -\x8a\xcc\xceM\x10\xb6n?\x07\xdb\xd1\x93\xc9\x00\x12M\ -\xd0Z('\x00\xc8_@(\x88\x0bi\xcc)\x04,\ -\xe9\x0c\xcc\x1c{\x92\x84\xa6\x16\xa7\x80qZ\xc1\xb8D\ -\xb6\xe2\x1e\xa5\x87\x90\xef\x0a\x93\xec\x14Aa\xdc:\x93\ -\xd3\xb9wb\xb2Z<\x133$\xdf\xb4T\x013\xcd\ -l'(Z>\xc7\xd3\xd1zcQ\xea\xa2\x91%E\ -\xc5\xb0:\xa3A$\x88\x0b\xaa<*C\xfd!\x0b\xc8\ -]\x04\x1a@l\x10\xc4\x1d)\x14\x80N\x96\x01\x82 \ --)\x80\xa1\x10\x14\xcc0P\x17\x01!El\xc7\x06\ -3&H\x99\x96N\xe3\x5c|\x96yH\x82L\xbf\xd7\ -\x9ed\xe2\x84\xdbD\xa0Z\xa6\x01\xb9\x04+F\xcb\xdc\ -!\x83\xaa\xaa\x0eEH\x0c\x07\x8dY\x1d\xa9\x00\x17U\ -\xd0t\x92D\xd0\xc0_\xf2l\xc9\xab\xd0X8\xab@\ -\xdbL3\x12\x0e\xd3\xaaxF\x9f\x94P\x8aSE\xc9\ -B\xc275\xc7\xdb'\xa2tU\x05\xa8\x00\xd0 \x96\ -p}\x22\x09`C\x06\x81]a\xc4\xcaa\x0eV,\ -G\xcf\x00\xb4\x1c\x08\x84\xe0\x14\x02\x22\x1c\x09@\xf2\x98\ -]\xcd8\xad\xd4\x19WP\x86U4^\x5c\x0d#\x8f\ -\xfe(W\xb4\x13\x22\xaax\xd8w$2\x7f\x0e\xa48\ -\x14\x01 \xf6\xb6C\xcd0\xaf\x81Om\xc6\x80\x1f\xb7\ -@\x9c\x86\x0ek|8\x02\xb5\xc1\x05l({$H\ -\x8df\xa6D\xd5!P\x8a\x01W2.\xbe-\x0c\xd4\ -\xa8\xc4BN-+\x1bLK\xc9\ -\xc8\x0f\x15x\x0ck\x01\x5c\x0c\x06\x8e\x99Kd\xe8P\ -h\x8cU&~\x80\x90\x17\x15\x98Lk\xc0\x80\x22C\ -\x22\xf8w\x0a\xa2\xf7\x0e\x0a\xcb\x8c\xfa$`\x8c\x15\xef\ -\xb4\x18\x03\xc8\x9c'\xc8\x90\xe8\x12;\ -\xa0\xa4ne\xcc\xd7\x17}\xea\x12\xb8\xa1\x97\x04+\x06\ -\xcb\x94B_\xfc/\xba\xe4\xb4\xa7\xe0`*\x06\xb28\ -*\x06\xb688H\xf2\x09<\xc2P\xc6\xceB\xdd\xdb\ -\x88\xdc\xec,\x1a\x90?\x09\xe41\xf5\x06\xe1S\x9f\xc4\ -\x9d\xf0\xa6\xf7\xcadbw\xa3\x19\xab\xa2\xa2\xae\xc4j\ -\xea\xb9\xa78\x91)0C\xa4\xc1\x12\xb0\x08\x07\xfe\xed\ -\xe8\xb8\x92\xa34o>\x22\xfc\xfd\xa04\x13\xa8\xb9\x14\ -\xefCE\xbd\x11B\x9f\xcd\xd2\xc5\xc4P\xfb\xc2\xf8c\ -\x0c\xdf*\x91e\xb6\xdcS\x8d\x16\xb0\x07\x81)\x0c\x10\ -Z\xec1\x8b-|'\xb5\x08\x15\x98\xa0\xbfb\x03\xbc\ -\xbeB$\x94[\xcb\x04U|P\xcbDF\xef\xec\x5c\ -\xa2\x9a\xc5H\xc3\xb0p'\xb6\xc0\xc6\x90\x01\xd7n\x05\ -&\xce/\xc5~\x1f\x83s\x17\x12>\xfb\xf6C\xab\x8b\ -\x99\xb9\xd9e\x5c\xe2\xc5}\xb1\xc8>\x8d\xcc{Q1\ -8 \xf8&\xedxd\xbd&@~\xbdp\xbc\x0d\x86\ -\xc7\x01\x19\xdb\x8a#\xc4\x9c\xa7\x5c\x0c\xb6\x87[\xcf\x22\ -\xfcn\xe5\xb5\xaa\xc8\x9e\xf2\xd1\xfb\xd101\xd0D\x0a\ -\x85'\x19\x19\xcb\xf4\x86)\xc1\xbc5\xa5\x08[\x064\ -\x91!\x5c~\x0c\xef\xa2m\xf4\xe1:\x9b\x85\xe2\xb5w\ -Qx\x81\x12\xd5\xb0\x0bW\xf1D\xc1b\xc3\x90\x8e\xb1\ -\xc1\xc4\x88V\x01\x03\xa5k[\xe8\x98\xb7\xcc\x8deV\ -O\xa9\xf7f[\xb89{s\x90\xdeg\x099\xaf6\ -H+\xf7\x09\x8a\xc1\xb0\x06\xba\xc0 !\x91\xb8u\x8e\ -`\xbb\xd7\xc1\xa0\xec\xecC\x9e\xcc8\x0a\x07\xc1\xc8\xce\ -\xe9x\x9b\xaff!\xa0\xe1\xdb\xc4\x5cb\x0a\xa1\xafx\ -\x10n%\x01z\x92A\x06\xbd\xec!J\xb1,/$\ -\x02\xcc\x1c>\x0cl\xa54\xfa:\x07\x18\xc1\xf1B\xc4\ -Z\xf8\xd1D\x89\xb2\x88\x89\x15\x95\xbb\xba\x90W\x84\xe6\ -zA\x15\x92\xfc;\xca\x90N\xef'\xfb\xc9!'\x80\ -1\xd3\x81h\xe8\x06\xc1\x08\x1c\xf5@\x90\x0cz\xd0;\ -K\x00\x98\x18\xa7@\xfb[\xeb\x92F{\x86@\xba\xc4\ -!\xbc\xfa\x0e\x01\xb0L90\x8a\x89\x5c\xa2\xce*\xfd\ -\x95BH\xb2\xf8rY\xb2\x87\x8f\xad\x5c\x83\xb5\x87\xa1\ -!$\xf0\x06\xd4\xcfM\xd6\x00\xd0 \xd6\xe0\x98\x10\xfd\ -\xd0R\x8d\xc0\xe8$\xf5@p\x11\xfaZ\xa4\x8ac0\ -a\xfd@\xe6\xe2\x12\xc7r\x22?\x80\xaa\x91\xfet\x81\ -\xcf\x81\xdf\x0b\xfc\xc9\x14e\xbd+.\xffB\x04\x7f\xea\ -\xfc\x08.\xa2K\xe4\xa6kbr\x01\x80\x1e\x02\xf0\x14\ -\x03\xac \x02\xd0\x1a\xf6\x001\x01@.\x03\xabt\x03\ -\xe0O\x02@:i\xe0(\x03.8\xda\x8d\xb8\x0e\xad\ -\xbcm\x02X\xad\x87\xd6\xe8\x822\xf2\xe7\x88\xff\x22&\ -\xf3ev\xd9\xed\x18\xa9\x09:\xe2b\x5c_\xec\xd2\x06\ -\x8f\xc6\x04\x88\xf4\x04`W\x02\xa0N\xf4\xe0D4 \ -\x1e\x02E\xf4\x86\xc3\x5c\xfaB4\x16p\x90\x14\x01\x03\ -\x09`\xc3\x04g\xd0\xa7\x0e\xd0#\x0b\xea~\x8d\x96\xff\ -G\x22\x9ag\xf6\xff\xc0\x00\xf3\xe2P\xc7@\x1a\x02\x0e\ -\xe4\x0d`\x89\x0c`\xaaG\xa4\x7f\x08\xc2(\xaf\x0b\x88\ -ua\xd8\xc2\xc9\x14!\x84\xc8\x19\xc1\x84\x8a\x10\x9c\x83\ -p\xa0\xf8\x8azU\xca~ZM\x12f\x08\xae\xe9\xaa\ -\xc8\xa2\x0a$\xc6BD\xfc\x00H\xce\xc1\x1a\x16\x0e,\ -\x05p\xd0`KZ\xf0\xe1\xc4\xf7\xa1\xb0\xad\x01\xc4\x1b\ -O\x06\x1c!\xb2\xeb\x81\xcc~O\xecY\x80\xf1\x13\xe1\ -*\x09\xd1D\x0cB\x18\x1d1L\x1cez\x05\xa7\xe4\ -%\x0b\xe2\xf8PL#\x0e\x8c~\x90T\x22PX\x11\ -\x10\x5c#0\xb8#\xe5\xfe\x13\x91x\x18`Y\x17\xe0\ -nRf\xbe\x1d\xf1\x88\x1dc\xd6\x1c\xa1\xbc\x1cq\x94\ -\x1b\x8e<\x1a\xd1$\x1c\xf1\xa0\x1c1 \xb6A\xec\xb6\ -\x826\x9ea\x14\xdf\xc0\xea!\x87\xfe\x7f@]\x12\x81\ -\xb4%\x08\x8c\xc4,F}\xc9\x94\x5c!\xe4\xe8\xeeZ\ -\xa1O\xf8\xe9\x8eb\xa8\xea \xf9\xe8d$\x00\x9b\x1e\ -\xa0\xc0\xa4 \xfe\x13\xe2`<\xca\xb2\x1e!\xdb\x14\xc1\ -\xd2\x1cq\xc1\x12\x81\xb6mA\xda\x1d\x11\xfa\x1d\xc7V\ -\xeb\xab~\x9f\xc1\xd3\x1a\x81\xe8A,\xb8\x0dk\xc2\x12\ -\x82 N\x80\xde\x09a\x8b#al%\x10\x80\x02q\ -\xc9\x15\xe2.~N\x14x\xee\x5cy\x8d\xdf\x10\x02\x16\ -\xda+\xfe#\xd1\xc8j\xa0\x80\x0a\x020`Q\x88\x1d\ -\xf2\x18\x1c\xc1\xc0Pa\xc8q\xa7\x1d\x19A\xc6\x1br\ -t\x1b\xb1 \xfe\xc7n\xd2n\xfc\x17b \x11\xd2\x94\ -\x0e$\x98\x14\xcb\xd0$\xf1Z\x15\xad\xcb\x0bRH\xe5\ -\x92L\xe1\xae^\xc5\xa5\x86\xe20`\xba\xd0d#\xaa\ -\xc0\x180\xa2 \xf2j\x1daK,\xe1\x1c\x8c\xd1\xa0\ -\x1c\xe1\xc2\xaa\x81\xd4\x1c\x91W\x0d\x02\x16\xfc`F\x15\ -R\xec\x1a\xb0:!J\x9e\x13\x01\x0f/\xa0\xd3\x1cP\ -\x9e\xe4\xe8\x98\xf8\xa8\xa1\x16b#\x16\xaea+g\xfc\ -H\xec\xc5+\xe29\x09a\x02\x14 \x972`\xbc\xeb\ -h\xdc\x1c\xd3&\x09`<<\x01\xfb.K\x9eCN\ -\xaa\x1a\xef\xb0\xebB\x16E\x81\x98\x17\xea\xfc\x08QX\ -\xec\xcc\xa5\x0f\x024\xd9%c\x0a\xb0V\xa8r\xb3%\ -1\xde\xba\x83'\x10m\xa6#\xef\xd4\x0c \xf2\x0ds\ -\x80\x10\xcd\xf6\x1f\xc1\xfa\xe4 e0\xd3<\x22J\xc0\ -\x18\x0c\xdc!q\x8e\x1b\xd1R\xfd\xa2G\x04\x88<\xc4\ -\xb0\xb5\x16%\x9f9\x02\x1f1\x12\xb4#\x11r#\xc0\ -}< \x9b)A\x1c\x16B \xc3,6\xc3\xa4\x12\ -\x91\xe0\x8b=\xa0\xac\xf4\xe0C\x0d\x81\xa1>a\x88\x16\ -\xf3\xec\x14\xa1\xef?!\xea%\x91>\x0f\x01,\x9f`\ -\xa9/\xe2\x16k\xe7\xf4\x05\xf1\xc0$\x92\xa3*rT\ -\xb9c30\xb1\xd6\xdd\x8dS\x0b4\x16!3\xbe#\ -\xa0KB\xe0],\xe1J\x19\xe6\x1e!!'C\xe0\ -\xf0\x144D\x11\x22X_\x0b\xcc\x0ea\x1e\x0a4T\ -\x0c\xd4:!\x08b\x18\xc0\xfdF \xbd(\x22P\xe4\ -)F\x94\xa2 \x0dTt\x08\x81\x95G\xa1z$\x8f\ -\x82\xf8s\x07\x0f!\xe1A\xd2\xae\xe9%\xae\xcb\x91\xdd\ -1Q\xe0\xa2(\xb7%\xa2;\x0b\xc0 \xb5, \x02\ -\xe2\x18\x9c\xc1l\x14tb\x0f\xd3*$\xe2\x9e\x98\xb2\ -a&B/\x12\x14N\x0a\x01\xb3L\xe1\x9e$\x8a4\ -\x07@\x90\xd3,\xe8!\xef\xe0\x11\x00\xd4\xea\xa1/A\ -\x0d\x07\x15\xcd\x0a\xe5FK$\xae\x18\xdd\x8b\xa2\x7fo\ -\x9a\xa93\x1c#\xec\x88\x14L\x8c\xc9\x02\x18\x93\xd3z\ -\x07\x22P\x91\xf3\x96$\x0c\xe4\x18\xc1p\x9ej8$\ -px\xcf\xe1R\x1aj\xc6!k$\xb2\x88p\xb2\xe2\ -F\xf2*\x095\xd0OA\xaf1A\xef56\x91l\ -fo\x9b7J\xf8$+\x08\x14\xe0\x8dV`\xb0\xaa\ -j\xab@\x00U\x1a\x91\xac$Jf\x10\x01@\x09\x95\ -\x80\x0b\xe2@\xecA\xd8\x1c\xf4T\x0a K?!\xef\ -?b>\xf4n\xaa\x1b\x0f\xac\x03b\x18\xd7\xc1d\x13\ -\xcdv\x10@\xc7H\x13\x02\x11UF\x06I!5\xea\ -\x0e\xf8\xeb?+\x12P\xe1\xf4\x997\x0a!PN\xf0\ -$il\x0f\x80\xd3]\xe1\x06!\x8b\x88\xee@U-\ -a\xc2$\x95\x0bP\xe0T\xc9\x22>k\xee\xe4\x05s\ -\x9e$\x91x\x13\x81\x86\xdc\xa2\x18\x18v\x10\x16\x89H\ -\x0e \x9a$\x92>}T\x85[\xee\xd2\xe5ec;\ -B\x1d;\x93m\x5c\xeb\xf974\x9f\x10\x82CV`\ -\x8c\x0a\xeb\x08\x15\x13\x878\xa9C8\xf5P$\x13\x97\ -9\xa2=\x22\x0c\xb8\x05q $\x95{W\xf5\x82!\ -\x88\xd0\x1a\xc1\x98\x0b\xf6t\x06\xc6$\x22\xf4\x83,b\ --;\x00{b\xc2\x1b\x16\xb1n#\x0a\xf0\x9bU\x06\ -#\xc7@\xe3!H\x19\xb4Z \xf3S4\xc1~$\ -\x8a\xfc\xb0\x052\xb0B?(4\x00\x05*\xf0$\x8e\ -\xbe\x0b\xa0\xe9#\x01\x16\xb5\x88.\xcb\x80Y\x0d\x82A\ -TV\x80\x22\xb3`VO\x91U%p\xbf63;\ -\xd68\xbf\xd6<$\x08\x8c\xb0\xe1\x5c\x1bL,!\x91\ -\xf0\x0b\xef\x1a\x16\xaf\x1e$q\x0d.\xc1T\x1a\xa0\x0b\ -q`\x0c#\x8dh\x121\x10\xb2\x02O< |\x09\ -\xd3\xc8\x16\x22\x18`S\x8d6B5#\xf2CO.\ -\x10d\xab\xedn0\xadno9Bb\x10\xe9\xe8`\ -\xfa\x02HJu\xf2\x05\x17`\x06B\x19P\xa1\x16\xd3\ - \xec%\x12'\x22\xa2(*T\xb0\x14r\xfa\x10\xe0\ -\xd3:BL\xcd kP\xa7l!\xf3\xd0\xc3\x81z\ -\xc3\xc2?A(?u\x02\x0fhV\x88!\x8f\xf6Z\ -\xe5\xb3P0c]bL\x12\x17\xb8\x16\x87H\x07\x80\ -\x96!\x8d\xbe\x15\xf0>\x0aBYL'$\xc6\x80P\ -!\x8a\xf0@\x00\xa6\x05\x16\x02%w\xd4\x15\x17\xe8\x1a\ -U6!K*\x0f5;mt\xee\xa77Abw\ -E\x0a\x97I6wM6\xb5\xcc#\x07\xfez)Q\ -x\xe2M2\x13%2\x82\x18\x8c\xcb\xd6\x0b\x80f\x91\ -\x02V4\xe0\x86\x0a\x87v\x15b!R\x95\x22\x17\x02\ -Y\x02\x0bR\xc0\x22\x19\x09\x01g\x09P\x99oU\xb7\ -\x7f\xcaw*\x83-tu\xc7O\xd7O6\xf67]\ -7\xb2\xf4\x02H\xed\xe0\xe0\x11\x98&\x0eb\x18\xfe\xd5\ -\xe9 \xc1\xd0%\x8a\xdcB!6\x18B!{\x81 \ -\x0e\x96\x9c\x94\xc2Wq`\x0a\x00\xd50\x1a\x8fj!\ -\x8d^\x0cX\xb0\x07XT\xdcj\xdb\x7f\xf0\xa5b\x80\ -}zb\x17z\xa9\xe9IP\xb5\x81(\xb7\x81tj\ -\x94V\x17\x89\xc6\xf2(Vt\x0b\xe0mf\xe1\x98%\ -\x8fk~\x81P\x1aE\xf0!\x96\xf8\x13+\x08\x0d\x02\ -`\x98\x01*\x17@o\x90\xa0\x8bV\xd2\xdfm\x12\xe2\ -#V\x7fT\x98\xbe\x89\xed\xd4\xc5U\xc9h\xe2/B\ -\xa2H\x07\x190\x08\xcb*\x17\x22 \x0f\xb9<\x0b\x93\ -\xec\x16\xe1KD\xa45q\x01\xa9.\x82\x19q\xf7\x22\ -&\x0ep\xb1\xa9\xe1rB\x14`K\x1c\x06*\x80#\ -\x95D\xf2\x97\xa0 \xd2\xabb\xb6S\x80\x8d\xdb\x80\xd8\ -\xcf1\x88\x04\xdeu,\xb7u1SBh!\x8e|\ -\xe8\x02_l6\xc6N\xa2\x10\xfe\xc8\xa1s\x82R\xee\ -@\xd4\xc3!*\x22\x18t\x09\x81\x89\x9b\xa1k\x96\xd7\ -\xfb$V\x83\x1d\x09\x9d\x9a\x82!h\xd5X\xae\xe6q\ -iW\xb4$\xa7\xb9400!\x97\x94\x15\x93\xd0A\ --'\x83\x00\xa6\x99a\xe7\x84\xc1>FA\xbe\x1a\xe4\ -\x12\x97 \x80\x13:\x09j\xa2\x1fv\xd7h#\x97<\ -\x91\x81_\x9cB+\x97x\xc3\x97\xa2$\xba\x04@\xd1\ -qq+\xad\x1d\x9d\xa2P\x13\xba8\x18\x8d\x88\x05\xe0\ -v!\x8e\x02\x1b\x01\x9dl ig\xb3\x92!sG\ -48\xf6!h \x15\xe16\x9d!\x0a\x0c\xc29:\ -\x94\x15\x86\x8d\xd1\x8c\x18\xc4!Y\xd1P\x0d\xa1\xa3\x19\ -\x88$\xd9<\x0f\xa18\x09\xfa\x8d[\x22\x17\x0d\x95\xe9\ -,\xbaR#\x0bS\x07\x82\x19G\xa1\x94\x17\x94t\x0d\ -Y\x0e#z\x16\xc4Z\x1c\x22\x9a!\xa7b\x12\xd9\xb7\ -\xad;\xb9+n\xed\xa5U\xe2Q\x99\xd6\xc8\xc1\x22\x85\ -\x82`gL\xe1\xb3M:\x9a!E\xfa\x83@+>\ -\x00\xf3\xae\xe1/\x11b\x19\xad\xc1\x9f8\xd9\xc0u\x18\ -6\xf6p\xb5m\xf9\xcd;uU18\x10H\xf0\x03\ -\x00bSr\x97-)W0!\xeb\xc2\x0a\x8b\xbc\x15\ -\xa5TJd\x07JP\xdc5\xa0%\x10\xcf\xb7}S\ -F\xcc\xc04\x86\xa6D\x22x\x17\x8e1\x82#s\xa9\ -\xabb'\xb0\x98\x07\x16\x90\xaef\x1a-n\xca d\ -\xf8\xd4%o\xba\x04 S\x8f\x01\xa46\x03d!n\ -\xfc\x0fm\xb0\x13\xd3\x84D\xa6\x88\xf6\x10%\x02r\xe9\ -\x11r\xe9}P4\x03(\xe4e\xa2`\x14{\xa8\x11\ -\x81#\xba\xf1\xb7\xb5U\xb7[\xb6%\x16\x11\xd1\x8b\x00\ -\xc4\x07yj\xd5\x0d\x14r\x95[c\xb3v%L\x03\ -o\x81\xb3J\xa2\x19S\x01&\xcf\xa28h\x89\xc7J\ -@3\xbe\xe0>\xfbp*\xfb\x8f\xba\x05SG\x03\x14\ -\xa4OE\x998\xcb|\x1c\xc1\xbf\xa6\xb8Wm\xa2(\ -\xb9\x88H\xed\x97J\x9aP\xfc\xd5V4\x8b:\x81i\ -bJ)\xfb\x86\x18\xcd\xac!\x81q\xc3\xa1L\xde\xc0\ -\xb6 \x94\xab\xb9\xfb\xf7}Q\x0d\x07\xdbH\xc2\xc4\x06\ -\xf4n\xf3!\xd4\xcb\xa8\x223m\x99\x1d$x_\x80\ -XcnY\x7f\x5c\xb0\xb5\x92\xc2V\x10\x9c|\x14\xa0\ -\x91\xc8 \xb4!\x95\xec\x80\x81\x8e\xfb{\xee\x03 ?\ -\x0b\xc0#j:\xe2 \x8c\xaa\x8da\x9a\x18\x011\xca\ -\xa0\xfe\xbd\xd5\xb5\x8b\x90K\x8b\xc2/\x05\x07\x8b\xa2S\ -\x0f\xb0\xfa\xc4\x22\xdcx%E\x1a\x0c\x00\xf0r\x5c\x9e\ -!\xb1\x1c\x82\xc1\xd5\x12\x12\x06\xad1\xfa\x1d\xb2\xcb\x0d\ -\x92\x83 \x01\xc7\x0e\xae\x0a\xf8\x5c\x14\x22p\xa6Y\xfb\ -\x0bb\xf5U\x92\x9c\xc9\xac\x94\xa1\x88\x89\x91\x88\xd8\x90\ -\xeaF\xbf\xce\xc5\x07\x191\x94\x1bq%\x19\xb5\xed\x1a\ -kfOY\x1bHu\xc0U\xd4\x8dO\xbcqB'\ -\xf9\xa7\x0e\x9c\x85\xceiu\x82^e\xa1\x1f\xd5!d\ -\xd2dL*P\xd9\xcf\x12\xdc\x1c\xbc\xe7,\xae\xb8\x1c\ -\xb1.\x1b2|\x1b\x92\x0d!\xfd/\x08\xd9n\xb99\ -r \xbc\xfe~\xbcn\x22\x9a\xc0\x9e\x9d\x08\xc5\xf9\xd6\ -\x8b|`%\x9bIZ\xe1D\xcf,\xf6#f\x05\x0d\ -\x91\x8e\x1b\xf3\x9e\xe3\xc1\xab\x12]\xae\xf0\xe1\xc3(\x9c\ -\xd6\x22\xfce\xd3X\x00\x1e4\xf8\x9a1\xdb\xc7}\x0d\ -o$\x10JxzJ\xa0z\x09\xb0\x80\x02I\xae\x1f\ -\x86H\x1e\x11.\x1b]s\x9f\xc1\xad9\xfdc\x91}\ -\xc3\xcfP\xef\xdc\x99\x1e~}\x01\xb5\xfc\xc2\x8a\xbc#\ -B]E\x104\x9do\x1b\xd3\xe0>%0\x087\x1c\ -\x96\x0c\xca\x99\xc8\xca\xfe\x11\x9c\xfc\xc5n\xa2.\xaf\x14\ -\xe2\x0dY\xfc\x1a\xec\x18\xc1\xde'\xe4\xe2D\x07~T\ -\x09S\x80\x0da\x0at\x0cO\x86\x09+\xc7\x14\xfe\x81\ -\xc2>\xaf\x1aP9\xc6\x92b&\xee1C\xb9\xe7b\ -\x18nF\x84cG\x9co\x02\x0b\xe8\xde\x86^E\xce\ -;&\x99\xe7\xddE\xe8\xc6\xf7\xe9\xa2\x85C\xa5\x8d\xe9\ -`\x02_\xf0\xb4 \x9a\xbb\xcc\x1e9\x80\xbcu\xd8>\ -Q\xec.\xa5\xebt\x8e\xed\xa5\xab\xac>=\xec^\xd5\ -\xdc9\xa4s=\x03h\xa4\xb9\xaa\xa1\x09F\xde\xd7\xee\ -\xbe$\xb5\xb3S\xdbE\xa8\x00\xf8&\x0e\x95\xde\x0d!\ -\x07\xeb>\xed\xf0e#\x19\xb20\x09U\xec#\x1b|\ -\x08?\x18\x0a8\x1d\xba_\x09\xf2.l<\xdc:\x17\ -\x01L\x90\xa0\xd9\xe0\x06&)/\xb7\xda\x00W\xf3\xe0\ -m\xf2_D\xda\x98\x85\xe4/\x14\x18!e3\x828\ -e\xb80\x0a\x98t\x11\x90\x1b\xf4\x7fdRG\xe5)\ -\xa1!\xbe\x1c\xe6$\x89\x14\xcf \x9dIPr\x05x\ -\xa0\x00\xff6c\x02\x1cnE\xe1\xe9%\xed\xe7\xe3\xac\ -<_\x95\xe8?\x94n_\x98\xc5\xde\xac\x22\x1f\xa6c\ ->\x94oE\xdb\xf8~y\xe8\x9f\x9f\xf9\xa6\x82)f\ -\xbf\xd6\xe7\xc4\x13\xc1y\xfc\xa1W!\xc2P)\xe6[\ -\x10\xd7`\x05\x00d\xfbt\xa4)\xf6\xbf\xfb\x22\x0en\ -?\xbc,\xff\xb0 F\x8c;\x06\x9a \x0f\xf7\xf8\x06\ -\x09\x05\x82@\xa0@\x08P\x00\x05\x0d\x01?\xa2\x0f\xe8\ -\x5c2\x1a\x03\x88\xbf`\xd18\xd4l\x01\x08\x81\xc1c\ -\xd18\xf48\x05!\x8eH\xe1\xd184E\xfd(\x86\ -\xc4\xe5\x92H\xf4z\x0d\x19\x85\xcb&\xd1\xc8\x5c\x92Y\ -&\x85NcRG\xed\x0d\xfb\x13\x92>i\x0f\x87\x9d\ --\xde\xe3\xa77\x1b\xd5\x16\xb3\xa2\xa8\xe1{\xd5\xde\xb3\ -\xe9\xd5n\xb9]\x8eA\x80v\x10%\x8c\x08\x05\x99L\ -\xe15\xe9<\x22\x81j\xb7[\xeb\x95\xabm\xc2\xe9u\ -\x9dM \xb7k\xd4v\xd9y\xbd\xdf\xf0\x11\xa9e\x11\ -\xf9\x17\xad`q\x18\x9cV/\x19\x8d\xc7c\xf2\x19\x1c\ -\x96O)\x95\xcbe\xf3\x19\x9c\xd6o9\x9d\xcfg\xf4\ -\x1a\x1d\x16\x8fI{\x80\x80\x00\x00\x00\x03\x00\x01\xa0\x03\ -\x00\x01\x00\x00\x00\x01\x00\x00\x00\x02\xa0\x04\x00\x01\x00\x00\ -\x00`\x00\x00\x00\x03\xa0\x04\x00\x01\x00\x00\x00`\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00Adobe Pho\ -toshop Document \ -Data Block\x00MIB8n\ -rTM\x00\x00\x00\x00MIB8ryaL$\ -!\x00\x00\x01\x00\x03\x00\x00\x00\x03\x00\x00\x00]\x00\x00\ -\x00\x5c\x00\x00\x00\x04\x00\xff\xff\x88\x0d\x00\x00\x00\x00\x0c\ -\x06\x00\x00\x01\x00\x0c\x06\x00\x00\x02\x00\x0c\x06\x00\x00M\ -IB8mron\xff\x00\x08\x00<\x01\x00\x00\x00\ -\x00\x00\x00(\x00\x00\x00\x00\x00\xff\xff\x00\x00\xff\xff\x00\ -\x00\xff\xff\x00\x00\xff\xff\x00\x00\xff\xff\x00\x00\xff\xff\x00\ -\x00\xff\xff\x00\x00\xff\xff\x00\x00\xff\xff\x00\x00\xff\xff\x07\ -Layer 0MIB8inul\x14\ -\x00\x00\x00\x07\x00\x00\x00L\x00a\x00y\x00e\x00r\ -\x00 \x000\x00\x00\x00MIB8rsnl\x04\ -\x00\x00\x00ryalMIB8diyl\x04\ -\x00\x00\x00\x03\x00\x00\x00MIB8lblc\x04\ -\x00\x00\x00\x01\x00\x00\x00MIB8xfni\x04\ -\x00\x00\x00\x00\x00\x00\x00MIB8oknk\x04\ -\x00\x00\x00\x00\x00\x00\x00MIB8fpsl\x04\ -\x00\x00\x00\x04\x00\x00\x00MIB8rlcl\x08\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00MIB8d\ -mhsH\x00\x00\x00\x01\x00\x00\x00MIB8t\ -suc\x00\x00\x00\x004\x00\x00\x00\x10\x00\x00\x00\x01\ -\x00\x00\x00\x00\x00\x08\x00\x00\x00metadat\ -a\x01\x00\x00\x00\x09\x00\x00\x00layerTi\ -mebuod\xc5\xa4\xf3l\xf98\xd6A\x00M\ -IB8prxf\x10\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00S\x00O\ -\x00\x0f\x00\x0c\x00\x0a\x00\x09\x00\x09\x00\x09\x00\x09\x00\x15\ -\x00K\x00K\x00\x1e\x00\x1e\x00\x1e\x00\x1c\x00)\x00'\ -\x00(\x00$\x00'\x00\x22\x00'\x00$\x00&\x00%\ -\x00%\x00 \x00\x1d\x00\x1c\x00\x1c\x00\x1d\x00\x1b\x00\x1d\ -\x00!\x00\x22\x00#\x00%\x00!\x00$\x00+\x00+\ -\x00,\x00+\x00(\x00%\x00&\x00.\x00/\x00.\ -\x00+\x00-\x00-\x00.\x00-\x00.\x00/\x00-\ -\x00.\x00-\x00.\x00-\x00-\x00*\x00%\x00#\ -\x00(\x00,\x00+\x00,\x00,\x00%\x00#\x00!\ -\x00&\x00\x22\x00!\x00\x13\x00\x14\x00L\x00\x09\x00\x09\ -\x00\x08\x00\x09\x00\x0a\x00\x0a\x00\x0c\x00L\x00W\x00 \ -\x00\xfd\x00\x04\x05\x11!-1\xfe/\xfc0\x181/\ -/0110010/1/0010/\ -0110/01\xfe0\x0a/21100\ -/00//\xfe1\x000\xfe1\x05010/\ -01\xfe0\xfe1\xff0\x081/0/-'\x18\ -\x08\x01\xfe\x00\xff\x00\x07\x01\x14X\xab\xdb\xec\xf0\xf0\xfd\ -\xf1\x00\xf0\xfe\xf1\x00\xf2\xfd\xf1\xff\xf0\x01\xf1\xf0\xf8\xf1\ -\x03\xf0\xf1\xf1\xf0\xfe\xf1\xfe\xf0\x07\xf1\xf0\xf0\xf1\xf1\xf0\ -\xf1\xf0\xfc\xf1\xff\xf0\x1b\xf1\xf0\xf0\xf1\xf2\xf1\xf0\xf1\xf0\ -\xf1\xf1\xf2\xf0\xf1\xf0\xf1\xf0\xf0\xf1\xf0\xee\xe4\xc2|.\ -\x06\x00\x00\xff\x00\x03\x16\x86\xed\xfd\xb3\xff\x04\xf9\xbfA\ -\x06\x00\x03\x00\x08l\xf4\xb0\xff\x03\xfe\xbd*\x01\x02\x00\ -$\xd0\xae\xff\x02\xf8x\x07\x02\x02O\xf6\xad\xff\x01\xc0\ -\x14\x02\x05r\xfd\xad\xff\x01\xe1#\x02\x08\x86\xfe\xad\xff\ -\x01\xed+\x02\x08\x8f\xfe\xad\xff\x01\xef-\x02\x09\x91\xfe\ -\xf1\xff\x00\xfe\xdb\xff\xfe\xfe\xfd\xff\x00\xfe\xec\xff\x01\xef\ -,\x02\x08\x91\xfe\xfa\xff\x17\xfe\xcf\xc2\xc3\xc2\xc4\xc3\xc4\ -\xc3\xc3\xc4\xc4\xc1\xc3\xc3\xc2\xc3\xc2\xc2\xc3\xc2\xc3\xc4\xc4\ -\xfe\xc2\xff\xc3\x0c\xcb\xd5\xdc\xe1\xe1\xdd\xd5\xcc\xc2\xc3\xc2\ -\xc2\xc1\xfe\xc3\xff\xc4\xf9\xc3\x06\xc4\xc3\xc3\xc4\xc2\xc3\xc4\ -\xfe\xc3\xff\xc2\x01\xc7\xf1\xf9\xff\x01\xf0-\x02\x09\x90\xfe\ -\xfa\xff\x03\xfaK\x18\x17\xfc\x18\x14\x17\x18\x16\x19\x17\x18\ -\x19\x19\x18\x19\x18\x17\x18\x19\x19\x18\x17/~\xce\xf4\xfb\ -\xff\x13\xf7\xc8\x810\x18\x16\x19\x19\x17\x18\x18\x19\x18\x18\ -\x19\x17\x19\x18\x19\x18\xfd\x19\x08\x18\x19\x19\x18\x19\x19\x17\ -,\xc7\xf9\xff\x01\xf0,\x01\x09\x90\xf9\xff\x01\xf98\xeb\ -\x00\x020\x9f\xea\xf5\xff\x02\xeb\x996\xe8\x00\x01\x15\xc0\ -\xf9\xff\x01\xef.\x02\x09\x91\xfe\xfa\xff\x01\xf97\xec\x00\ -\x01u\xf4\xf1\xff\x01\xf7c\xe9\x00\x02\x14\xc2\xfe\xfa\xff\ -\x01\xf0-\x02\x09\x90\xfe\xfa\xff\x01\xf88\xee\x00\x01\x12\ -\x91\xed\xff\x01\x9a\x17\xeb\x00\x02\x14\xc2\xfe\xfa\xff\x01\xef\ -/\x01\x08\x90\xf9\xff\x01\xf99\xef\x00\x01\x0e\xc7\xeb\xff\ -\x01\xba\x02\xec\x00\x01\x14\xc1\xf9\xff\x01\xf0/\x02\x09\x90\ -\xfe\xfa\xff\x01\xf97\xef\x00\x00\x95\xfa\xff\x09\xd1\x9c]\ -B;Hj\xaa\xd6\xfe\xfa\xff\x01\x97\x04\xed\x00\x01\x12\ -\xc0\xf9\xff\x01\xef-\x02\x09\x91\xfe\xfa\xff\x01\xf98\xf0\ -\x00\x00r\xfb\xff\x02\xc9E\x02\xfa\x00\x02\x05C\xbf\xfa\ -\xff\x00\x86\xed\x00\x01\x14\xc2\xf9\xff\x01\xf1-\x02\x09\x90\ -\xfe\xfa\xff\x01\xfa8\xf1\x00\x01-\xf5\xfc\xff\x01\xa3\x09\ -\xf6\x00\x02\x02s\xfc\xfc\xff\x01\xee\x16\xee\x00\x01\x15\xc1\ -\xf9\xff\x01\xef-\x01\x09\x92\xf9\xff\x01\xf97\xf1\x00\x00\ -\xb6\xfc\xff\x01\xa8\x06\xf3\x00\x01C\xe7\xfc\xff\x00\xa0\xee\ -\x00\x01\x15\xc2\xf9\xff\x01\xef,\x02\x09\x91\xfe\xfa\xff\x01\ -\xf98\xf2\x00\x01\x1b\xf4\xfd\xff\x01\xe3\x13\xf1\x00\x01:\ -\xfa\xfd\xff\x01\xf9%\xef\x00\x01\x14\xc2\xf9\xff\x01\xf0/\ -\x01\x09\x90\xf9\xff\x01\xfa7\xf2\x00\x00\x82\xfc\xff\x00g\ -\xef\x00\x00\x8f\xfc\xff\x00\x87\xef\x00\x01\x15\xc2\xf9\xff\x01\ -\xef-\x01\x09\x91\xf9\xff\x01\xf87\xf3\x00\x01\x12\xea\xfd\ -\xff\x01\xe9\x0d\xef\x00\x01\x08\xd8\xfd\xff\x01\xdf\x0a\xf0\x00\ -\x02\x14\xc1\xfe\xfa\xff\x01\xef/\x02\x08\x90\xfe\xfa\xff\x01\ -\xf98\xf3\x00\x00n\xfc\xff\x00\xad\xed\x00\x00o\xfd\xff\ -\x01\xfd0\xf0\x00\x01\x15\xc2\xf9\xff\x01\xf0-\x02\x09\x91\ -\xfe\xfa\xff\x01\xf97\xf4\x00\x01\x0f\xe5\xfd\xff\x01\xfe;\ -\xed\x00\x01\x17\xee\xfd\xff\x00T\xf0\x00\x01\x14\xc3\xf9\xff\ -\x01\xf0/\x02\x09\x91\xfe\xfa\xff\x01\xfa7\xf4\x00\x01(\ -\xef\xfd\xff\x01\xc2\x02\xec\x00\x00\xcb\xfd\xff\x00c\xf0\x00\ -\x01\x15\xc1\xf9\xff\x01\xf1-\x02\x09\x92\xfe\xfa\xff\x01\xf8\ -8\xf4\x00\x06\x01\x1bP\xc0\xff\xffI\xeb\x00\x00\xb0\xfd\ -\xff\x00m\xf0\x00\x01\x15\xc2\xf9\xff\x01\xf0.\x01\x09\x90\ -\xf9\xff\x01\xf98\xf0\x00\x02C\x87\x07\xeb\x00\x00\xb6\xfd\ -\xff\x00m\xf0\x00\x01\x15\xc2\xf9\xff\x01\xf0.\x02\x09\x90\ -\xfe\xfa\xff\x01\xf99\xd8\x00\x01\x09\xda\xfd\xff\x00b\xf0\ -\x00\x02\x15\xc3\xfe\xfa\xff\x01\xef-\x01\x08\x91\xf9\xff\x01\ -\xf97\xd8\x00\x018\xfe\xfd\xff\x00Q\xf0\x00\x02\x14\xc2\ -\xfe\xfa\xff\x01\xf0/\x02\x09\x91\xfe\xfa\xff\x01\xf98\xd8\ -\x00\x00\x9b\xfd\xff\x01\xfc2\xf0\x00\x01\x14\xc1\xf9\xff\x01\ -\xf0.\x02\x09\x91\xfe\xfa\xff\x01\xf98\xd9\x00\x01*\xf8\ -\xfd\xff\x01\xd5\x06\xf0\x00\x01\x14\xc1\xf9\xff\x01\xf0.\x02\ -\x09\x91\xfe\xfa\xff\x01\xf99\xd9\x00\x00\x8e\xfc\xff\x00\x80\ -\xef\x00\x01\x14\xc2\xf9\xff\x01\xf1.\x02\x09\x92\xfe\xfa\xff\ -\x01\xf99\xda\x00\x01\x07\xdf\xfd\xff\x01\xe5\x19\xef\x00\x01\ -\x15\xc1\xf9\xff\x01\xf0/\x02\x08\x93\xfe\xfa\xff\x01\xf98\ -\xda\x00\x01B\xfe\xfd\xff\x04\xef\xc8\xca\xad^\xf2\x00\x02\ -\x15\xc1\xfe\xfa\xff\x01\xef.\x02\x09\x91\xfe\xfa\xff\x01\xf9\ -8\xe0\x00\x06\x0c\x22Cg\x84\x9c\xda\xf7\xff\x01\xb9(\ -\xf4\x00\x01\x14\xc1\xf9\xff\x01\xef-\x01\x08\x8f\xf9\xff\x01\ -\xf99\xe6\x00\x07\x0d(Hn\x97\xbb\xde\xf4\xf1\xff\x01\ -\xd1\x0a\xf5\x00\x02\x15\xbf\xfe\xfa\xff\x01\xee.\x02\x09\x92\ -\xfe\xfa\xff\x01\xf89\xef\x00\x0a\x02\x0e\x1d:Pf~\ -\x9b\xc2\xdf\xf8\xea\xff\x00Q\xf5\x00\x01\x14\xc2\xf9\xff\x01\ -\xef.\x01\x09\x91\xf9\xff\x01\xf98\xf4\x00\x07\x059]\ -\x88\xaf\xd1\xe3\xee\xe2\xff\x00\x9f\xf5\x00\x01\x14\xc1\xf9\xff\ -\x01\xf0-\x02\x09\x90\xfe\xfa\xff\x01\xf98\xf6\x00\x02\x10\ -{\xd0\xe3\xff\x03\xfa\xf0\xdc\xed\xfd\xff\x00\xc1\xf5\x00\x01\ -\x14\xc1\xf9\xff\x01\xef,\x02\x09\x90\xfe\xfa\xff\x01\xf97\ -\xf7\x00\x01$\xd4\xe8\xff\x0a\xfb\xe5\xc7\x9fyR8)\ -\x18\x08\x9d\xfd\xff\x01\xe2\x0f\xf6\x00\x01\x15\xc2\xf9\xff\x01\ -\xf1.\x01\x09\x91\xf9\xff\x01\xf98\xf8\x00\x01\x05\xc8\xed\ -\xff\x07\xf7\xe2\xc0\x9crJ+\x0d\xf9\x00\x00\x8a\xfd\xff\ -\x01\xf8&\xf6\x00\x01\x14\xc3\xf9\xff\x01\xf1.\x02\x09\x92\ -\xfe\xfa\xff\x01\xf99\xf8\x00\x00`\xf4\xff\x09\xfd\xea\xcd\ -\xa7\x82jXC#\x0c\xf3\x00\x00k\xfc\xff\x00J\xf6\ -\x00\x01\x13\xc2\xf9\xff\x01\xf0.\x02\x09\x91\xfe\xfa\xff\x01\ -\xf97\xf8\x00\x00\xaf\xfa\xff\x07\xfb\xe6\xc6\xa3wR/\ -\x11\xeb\x00\x00D\xfc\xff\x00p\xf6\x00\x02\x15\xc2\xfe\xfa\ -\xff\x01\xf0.\x02\x09\x91\xfe\xfa\xff\x01\xf98\xf8\x00\x00\ -\xc1\xfd\xff\x04\xeaxJ+\x0f\xe5\x00\x01#\xf8\xfd\xff\ -\x00\x97\xf6\x00\x01\x14\xc1\xf9\xff\x01\xef.\x02\x09\x91\xfe\ -\xfa\xff\x01\xf88\xf8\x00\x00\xa1\xfd\xff\x01\xe5\x03\xe2\x00\ -\x01\x08\xdf\xfd\xff\x00\xbe\xf6\x00\x01\x15\xc1\xf9\xff\x01\xef\ --\x02\x09\x91\xfe\xfa\xff\x01\xf97\xf8\x00\x00y\xfd\xff\ -\x01\xfc.\xe1\x00\x00\xc0\xfd\xff\x01\xdd\x0a\xf7\x00\x02\x14\ -\xc2\xfe\xfa\xff\x01\xf1.\x02\x09\x91\xfe\xfa\xff\x01\xf98\ -\xf8\x00\x00M\xfc\xff\x00T\xf3\x00\x05?\x95\xb6\xa2f\ -\x0b\xf5\x00\x00\x96\xfd\xff\x01\xf7&\xf7\x00\x02\x15\xc2\xfe\ -\xfa\xff\x01\xef.\x02\x09\x90\xfe\xfa\xff\x01\xf98\xf8\x00\ -\x01.\xfd\xfd\xff\x00w\xf5\x00\x02\x08\x97\xfd\xfd\xff\x01\ -\xc5#\xf6\x00\x00r\xfc\xff\x00C\xf7\x00\x01\x14\xc1\xf9\ -\xff\x01\xef.\x02\x09\x92\xfe\xfa\xff\x01\xf97\xf8\x00\x01\ -\x10\xe8\xfd\xff\x00\xa2\xf6\x00\x01\x01\xaf\xfa\xff\x01\xe11\ -\xf7\x00\x00H\xfc\xff\x00i\xf7\x00\x01\x15\xc2\xf9\xff\x01\ -\xf0.\x01\x09\x91\xf9\xff\x01\xf98\xf7\x00\x00\xcb\xfd\xff\ -\x00\xc7\xf6\x00\x00?\xf8\xff\x00\xb7\xf7\x00\x01'\xfa\xfd\ -\xff\x00\x87\xf7\x00\x01\x15\xc1\xf9\xff\x01\xef.\x01\x09\x91\ -\xf9\xff\x01\xf97\xf7\x00\x00\xa7\xfd\xff\x01\xe3\x0d\xf7\x00\ -\x00\xa0\xf8\xff\x01\xe6\x0b\xf8\x00\x01\x0c\xe4\xfd\xff\x00\x9d\ -\xf7\x00\x01\x14\xc0\xf9\xff\x01\xef-\x02\x09\x91\xfe\xfa\xff\ -\x01\xf98\xf7\x00\x00|\xfd\xff\x01\xf5\x1f\xf7\x00\x00\xcb\ -\xf8\xff\x01\xf7\x22\xf7\x00\x00\xc3\xfd\xff\x00\xb3\xf7\x00\x01\ -\x13\xc0\xf9\xff\x01\xf0.\x02\x09\x91\xfe\xfa\xff\x01\xf97\ -\xf7\x00\x00W\xfd\xff\x01\xfc.\xf7\x00\x00\xc0\xf8\xff\x01\ -\xf3\x1e\xf7\x00\x00\xa0\xfd\xff\x01\xcb\x01\xf8\x00\x01\x14\xc1\ -\xf9\xff\x01\xf1.\x01\x09\x91\xf9\xff\x01\xfa8\xf7\x00\x01\ -0\xfd\xfd\xff\x00A\xf7\x00\x00\x82\xf8\xff\x01\xdc\x05\xf7\ -\x00\x00t\xfd\xff\x01\xe8\x14\xf8\x00\x01\x15\xc1\xf9\xff\x01\ -\xef-\x02\x09\x91\xfe\xfa\xff\x01\xf97\xf7\x00\x01\x14\xee\ -\xfd\xff\x00^\xf7\x00\x01$\xf9\xf9\xff\x00\x90\xf6\x00\x00\ -N\xfd\xff\x01\xfb-\xf8\x00\x01\x13\xc2\xf9\xff\x01\xf0-\ -\x02\x09\x91\xfe\xfa\xff\x01\xf99\xf7\x00\x01\x02\xcd\xfd\xff\ -\x00\x8a\xf6\x00\x00k\xfb\xff\x02\xfe\xa1\x0a\xf6\x00\x005\ -\xfc\xff\x00T\xf8\x00\x02\x15\xc2\xfe\xfa\xff\x01\xf1.\x01\ -\x09\x92\xf9\xff\x01\xf98\xf6\x00\x00\xb4\xfd\xff\x00\xae\xf5\ -\x00\x01P\xd7\xfd\xff\x01\xfa\x22\xf5\x00\x01(\xfa\xfd\xff\ -\x00x\xf8\x00\x01\x15\xc2\xf9\xff\x01\xf0-\x02\x09\x91\xfe\ -\xfa\xff\x01\xf86\xf6\x00\x00\xa1\xfd\xff\x01\xd1\x04\xf5\x00\ -\x00T\xfc\xff\x00H\xf5\x00\x01\x18\xf0\xfd\xff\x00\x9f\xf8\ -\x00\x02\x14\xc1\xfe\xfa\xff\x01\xf0-\x02\x09\x91\xfe\xfa\xff\ -\x01\xf98\xf6\x00\x00\x8c\xfd\xff\x01\xee\x18\xf5\x00\x00=\ -\xfc\xff\x00s\xf5\x00\x01\x06\xda\xfd\xff\x00\xc6\xf8\x00\x01\ -\x14\xc2\xf9\xff\x01\xf0.\x02\x09\x92\xfe\xfa\xff\x01\xf86\ -\xf6\x00\x00r\xfd\xff\x01\xfe4\xf5\x00\x01%\xf7\xfd\xff\ -\x00\x98\xf4\x00\x00\xba\xfd\xff\x01\xe3\x0f\xf9\x00\x01\x14\xc1\ -\xf9\xff\x01\xf0/\x01\x09\x91\xf9\xff\x01\xf98\xf6\x00\x00\ -F\xfc\xff\x00[\xf5\x00\x01\x08\xdc\xfd\xff\x00\x90\xf4\x00\ -\x00\x8f\xfd\xff\x01\xfb,\xf9\x00\x02\x15\xc1\xfe\xfa\xff\x01\ -\xf0.\x02\x09\x91\xfe\xfa\xff\x01\xf88\xf6\x00\x01'\xfa\ -\xfd\xff\x00\x80\xf4\x00\x00t\xfe\xff\x01\xee-\xf4\x00\x00\ -j\xfc\xff\x00K\xf9\x00\x01\x15\xc2\xf9\xff\x01\xf1-\x01\ -\x09\x91\xf9\xff\x01\xfa8\xf6\x00\x01\x0b\xe2\xfd\xff\x00\xab\ -\xf3\x00\x03D\x97\x8a)\xf3\x00\x00@\xfc\xff\x00u\xf9\ -\x00\x01\x13\xc2\xf9\xff\x01\xf0.\x01\x08\x90\xf9\xff\x01\xf9\ -8\xf5\x00\x00\xc4\xfd\xff\x01\xcd\x01\xe2\x00\x01 \xf7\xfd\ -\xff\x00\x9a\xf9\x00\x02\x14\xc2\xfe\xfa\xff\x01\xf0.\x01\x09\ -\x91\xf9\xff\x01\xf98\xf5\x00\x00\x9c\xfd\xff\x01\xeb\x15\xe1\ -\x00\x00\xd8\xfd\xff\x00\xbb\xf9\x00\x01\x13\xc2\xf9\xff\x01\xf0\ -.\x02\x08\x91\xfe\xfa\xff\x01\xf97\xf5\x00\x00t\xfd\xff\ -\x01\xfe1\xe4\x00\x03\x07\x1c=\xd4\xfd\xff\x00\xce\xf9\x00\ -\x02\x15\xc0\xfe\xfa\xff\x01\xef-\x02\x09\x91\xfe\xfa\xff\x01\ -\xf89\xf5\x00\x00N\xfc\xff\x00S\xec\x00\x09\x02\x12\x22\ -3Ei\x8f\xb7\xd7\xf1\xfb\xff\x00\xc9\xf9\x00\x01\x14\xc2\ -\xf9\xff\x01\xef-\x01\x09\x90\xf9\xff\x01\xf96\xf5\x00\x01\ -)\xfb\xfd\xff\x00z\xf2\x00\x08\x03\x1a7Z\x85\xa8\xd0\ -\xe9\xf6\xf4\xff\x00\x8b\xf9\x00\x01\x14\xc0\xf9\xff\x01\xf1,\ -\x01\x09\x90\xf9\xff\x01\xf97\xf5\x00\x01\x0f\xe8\xfd\xff\x00\ -\x92\xf9\x00\x08\x03\x0d\x1d\x0d\x0a\x0d\x0a \x0d\x0a <\ -title>icon / Pre\ -ferences / Globa\ -l\x0d\x0a <\ -desc>Created wit\ -h Sketch.\ -\x0d\x0a \x0d\x0a \ - \x0d\x0a \x0d\x0a\x0d\x0a\ -\x00\x00\x09\xba\ -<\ -?xml version=\x221.\ -0\x22 encoding=\x22UTF\ --8\x22?>\x0d\x0a\x0d\x0a \x0d\x0a <\ -title>icon / Pre\ -ferences / Camer\ -a\x0d\x0a <\ -desc>Created wit\ -h Sketch.\ -\x0d\x0a \x0d\x0a \ - \x0d\x0a \ - \ -\x0d\x0a \ - \x0d\x0a \x0d\ -\x0a\x0d\x0a\ -\x00\x00\x00\xab\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x10\x00\x00\x00\x0d\x08\x06\x00\x00\x00\xa0\xbb\xee$\ -\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\ -\x04gAMA\x00\x00\xb1\x8f\x0b\xfca\x05\x00\x00\x00\ -UIDAT8Oc\xfc\xff\xff?\x03%\x80\x09\ -J\x93\x0d\xf0\x1a\xd0\xd8\xd8H\xd0y\x04]@\xc8\x10\ -\x940\xc0\xa7\xb8\xbe\xbe\x9e\x11\xcaD\x01D\x87\x01.\ -\xc3I\x0aDl\x86\x90d\x006o\x10m\x00\xae0\ -\xc0\x9b\x90`N\xc6\xa5\x19\x04\x08\xba\x00\x9ff\x10\x18\ -\xe8\xa4\xcc\xc0\x00\x00\x9d\xda\x22\x8d\x12\xa2\xae,\x00\x00\ -\x00\x00IEND\xaeB`\x82\ -\x00\x00\x05{\ -<\ -?xml version=\x221.\ -0\x22 encoding=\x22UTF\ --8\x22?>\x0d\x0a\x0d\x0a \x0d\x0a <\ -title>icon / Pre\ -ferences / viewp\ -ort\x0d\x0a \ - Created w\ -ith Sketch.\x0d\x0a \x0d\x0a \ - \x0d\x0a \ - \x0d\x0a \ - \x0d\x0a \ -\x0d\x0a\x0d\x0a\ -\x00\x00\x00\xca\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x10\x00\x00\x00\x0d\x08\x06\x00\x00\x00\xa0\xbb\xee$\ -\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\ -\x04gAMA\x00\x00\xb1\x8f\x0b\xfca\x05\x00\x00\x00\ -\x09pHYs\x00\x00\x0e\xc3\x00\x00\x0e\xc3\x01\xc7o\ -\xa8d\x00\x00\x00_IDAT8O\xc5\x91\xc1\x0e\ -\xc0 \x08C\xc1\x1f\x07\xbe\x9c\x05'\x86\xc4\xb9\x89\x1e\ -\xf6.r\xa1\xd2\x16U\x15\x0c\x11\xb9\x87\x07\x88\x08\xdb\ -8\x80\xcc<]\x5c\xa1\xb4w\x9b\xff\x05z\x88\x19b\ -\xe0\xe9\x10\xbd\x11\x17I[\xf0E\x17*o\x1d\xcf\x88\ -\x16\x8eB\xb4\xcf\xab\xc0\xc9\x15\xfd\x82\x1d\x11c\xa81\ -\xfa\xfb\x06\xe0\x02\xfbk*\x0b\x22\xb70[\x00\x00\x00\ -\x00IEND\xaeB`\x82\ -\x00\x00\x06\x06\ -<\ -?xml version=\x221.\ -0\x22 encoding=\x22UTF\ --8\x22?>\x0d\x0a\x0d\x0a Icons / Edit\ -or / EMFX / Moti\ -on\x0d\x0a \ -\x0d\x0a \ -\x0d\x0a \x0d\x0a \x0d\x0a\x0d\x0a\ -\x00\x00\x00\xa0\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x10\x00\x00\x00\x0d\x08\x06\x00\x00\x00\xa0\xbb\xee$\ -\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\ -\x04gAMA\x00\x00\xb1\x8f\x0b\xfca\x05\x00\x00\x00\ -\x09pHYs\x00\x00\x0e\xc3\x00\x00\x0e\xc3\x01\xc7o\ -\xa8d\x00\x00\x005IDAT8Oclhh\ -\xf8\xcf\x80\x06\xea\xeb\xeb\x19\xa1L\x82\x80\x09J\x93\x0d\ -\xb0\xba\x80\x18\x00s%\xd9.hll\x04[L\xb1\ -\x17F\x0d\x185\x80\x81\x81\x81\x01\x00\xc0\x1c\x0a\x95\xd5\ -0\x97g\x00\x00\x00\x00IEND\xaeB`\x82\ -\x00\x00\x11\xc7\ -<\ -?xml version=\x221.\ -0\x22 encoding=\x22UTF\ --8\x22?>\x0d\x0a\x0d\x0a \x0d\x0a <\ -title>icon / Pre\ -ferences / Debug\ -\x0d\x0a Created with\ - Sketch.\x0d\ -\x0a \x0d\x0a \ - \x0d\x0a \ - \x0d\x0a \x0d\x0a \x0d\x0a\x0d\x0a\ -\x00\x00\x12>\ -<\ -?xml version=\x221.\ -0\x22 encoding=\x22UTF\ --8\x22?>\x0d\x0a\x0d\x0a \x0d\x0a <\ -title>icon / Pre\ -ferences / Exper\ -imental\x0d\ -\x0a Creat\ -ed with Sketch.<\ -/desc>\x0d\x0a \x0d\x0a <\ -path d=\x22M15.1323\ -36,4.99076918 C1\ -5.5178274,4.9907\ -6918 15.8485779,\ -5.34903984 16.04\ -13236,5.67028261\ - C16.2340693,5.9\ -9152539 16.20194\ -5,6.90832486 16.\ -0413236,7.261691\ -92 C15.7410536,7\ -.67565898 15.559\ -016,8.029019 15.\ -4952109,8.321771\ -96 C15.4376576,8\ -.58583981 15.459\ -0738,9.15831061 \ -15.5594594,10.03\ -91844 C17.808158\ -9,11.0992855 19.\ -0519645,13.44435\ -78 18.9234674,15\ -.9500515 C18.797\ -9586,19.0877716 \ -16.2512974,21.89\ -56839 13.1394393\ -,22.1143917 L12.\ -9162275,22.12557\ -98 L12.1999856,2\ -2.1255798 C8.794\ -81215,22.1255798\ - 6,19.0982307 6,\ -15.660933 C6,13.\ -3376593 7.088222\ -19,11.2234803 9.\ -09581042,10.1537\ -076 L9.3226506,1\ -0.0391844 L9.162\ -02921,8.06479886\ - L8.71228932,7.2\ -6169192 C8.55166\ -793,6.90832486 8\ -.64804077,5.9915\ -2539 8.84078643,\ -5.67028261 C9.04\ -316938,5.3811641\ -2 9.51285982,5.0\ -6205304 9.885797\ -26,5.00112201 L1\ -0.0060269,4.9907\ -6918 L15.132336,\ -4.99076918 Z M14\ -.5477747,9.22030\ -884 L10.3382049,\ -9.22030884 L10.3\ -087674,10.505628\ -3 C10.3087674,10\ -.5645034 10.2793\ -298,10.6233785 1\ -0.2204547,10.652\ -8161 C8.30701393\ -,11.5065051 7.07\ -063679,13.419945\ -9 7.07063679,15.\ -5394495 C7.07063\ -679,18.5420797 9\ -.54339107,20.985\ -3965 12.5754588,\ -20.8970838 C15.3\ -720262,20.838208\ -7 17.6681551,18.\ -5715173 17.78590\ -53,15.8043875 C1\ -7.9036555,13.626\ -0087 16.6378408,\ -11.5359426 14.63\ -60874,10.6528161\ - C14.5919311,10.\ -6307379 14.56433\ -34,10.5921011 14\ -.5532943,10.5493\ -247 L14.5477747,\ -10.5056283 L14.5\ -477747,9.2203088\ -4 Z M16.248292,1\ -5.5813393 C16.43\ -33656,15.5813393\ - 16.5920002,15.6\ -606566 16.697756\ -5,15.792852 C16.\ -8035128,15.92504\ -74 16.856391,16.\ -1101211 16.82995\ -19,16.2951947 C1\ -6.6977565,17.009\ -05 16.4069265,18\ -.0137353 15.6930\ -712,18.806908 C1\ -4.4693191,20.158\ -1342 12.6801281,\ -20.2309765 12.48\ -27708,20.2344561\ - L12.4146244,20.\ -2346187 C12.0973\ -553,20.2346187 1\ -0.4581319,20.155\ -3014 9.29481208,\ -18.806908 C8.501\ -63946,17.8815399\ - 8.2108095,16.92\ -97328 8.10505315\ -,16.2951947 C8.0\ -7861407,16.11012\ -11 8.10505315,15\ -.9250474 8.23724\ -859,15.792852 C8\ -.32185367,15.687\ -0957 8.44030078,\ -15.6321024 8.579\ -05311,15.6007985\ - L8.68671307,15.\ -5813393 L16.2482\ -92,15.5813393 Z \ -M13.525066,16.42\ -73901 C12.996284\ -3,16.4273901 12.\ -5468198,16.87685\ -46 12.5468198,17\ -.4056363 C12.520\ -3807,17.9344181 \ -12.9698452,18.38\ -38826 13.525066,\ -18.3838826 C14.0\ -538478,18.383882\ -6 14.5033123,17.\ -9344181 14.50331\ -23,17.4056363 C1\ -4.5033123,16.876\ -8546 14.0538478,\ -16.4273901 13.52\ -5066,16.4273901 \ -Z M10.5110101,16\ -.5331465 C10.114\ -4238,16.5331465 \ -9.79715474,16.82\ -39764 9.82359382\ -,17.2205627 C9.8\ -2359382,17.59070\ -99 10.1408629,17\ -.907979 10.51101\ -01,17.907979 C10\ -.8811573,17.9079\ -79 11.1984264,17\ -.5907099 11.1984\ -264,17.2205627 C\ -11.1984264,16.85\ -04155 10.8811573\ -,16.5331465 10.5\ -110101,16.533146\ -5 Z M11.0960618,\ -12.7156002 C11.6\ -351612,12.715600\ -2 12.0891397,13.\ -1695787 12.08913\ -97,13.7086781 C1\ -2.0891397,14.247\ -7775 11.6351612,\ -14.701756 11.096\ -0618,14.701756 C\ -10.5569624,14.70\ -1756 10.1029839,\ -14.2477775 10.10\ -29839,13.7086781\ - C10.1029839,13.\ -1695787 10.55696\ -24,12.7156002 11\ -.0960618,12.7156\ -002 Z M12.429623\ -6,10.4173342 C12\ -.8268547,10.4173\ -342 13.1389649,1\ -0.7294444 13.138\ -9649,11.1266755 \ -C13.1389649,11.5\ -239067 12.826854\ -7,11.8360169 12.\ -4296236,11.83601\ -69 C12.0323924,1\ -1.8360169 11.720\ -2822,11.5239067 \ -11.7202822,11.12\ -66755 C11.720282\ -2,10.7294444 12.\ -0323924,10.41733\ -42 12.4296236,10\ -.4173342 Z M14.4\ -300245,6.2371834\ -4 L10.39708,6.23\ -718344 C10.16157\ -96,6.23718344 9.\ -95551678,6.35493\ -364 9.83776658,6\ -.5609965 C9.7396\ -4141,6.73271554 \ -9.72328721,6.924\ -87734 9.77166837\ -,7.10341063 L9.8\ -0832903,7.208622\ -62 L10.39708,8.0\ -9174915 L10.3970\ -8,8.60845497 L14\ -.5919794,8.60845\ -497 L14.5919794,\ -8.09174915 L15.0\ -187755,7.2086226\ -2 C15.1365257,7.\ -00255976 15.1070\ -882,6.76705935 1\ -4.989338,6.56099\ -65 C14.8715878,6\ -.35493364 14.665\ -5249,6.23718344 \ -14.4300245,6.237\ -18344 Z M12.3728\ -762,6.5763594 C1\ -2.7984811,6.5763\ -594 13.1389649,6\ -.91684325 13.138\ -9649,7.34244807 \ -C13.1389649,7.76\ -805289 12.798481\ -1,8.10853674 12.\ -3728762,8.108536\ -74 C11.9472714,8\ -.10853674 11.606\ -7876,7.76805289 \ -11.6067876,7.342\ -44807 C11.606787\ -6,6.91684325 11.\ -9472714,6.576359\ -4 12.3728762,6.5\ -763594 Z M14.933\ -6824,2 C15.64302\ -38,2 16.2388706,\ -2.53909944 16.23\ -88706,3.27681446\ - C16.2388706,4.0\ -1452947 15.64302\ -38,4.58200257 14\ -.9336824,4.58200\ -257 C14.2243411,\ -4.58200257 13.62\ -84943,4.04290313\ - 13.6284943,3.30\ -518811 C13.62849\ -43,2.56747309 14\ -.2243411,2 14.93\ -36824,2 Z\x22 id=\x22C\ -ombined-Shape\x22 f\ -ill=\x22#FFFFFF\x22 fi\ -ll-rule=\x22nonzero\ -\x22>\x0d\x0a <\ -/g>\x0d\x0a\x0d\x0a\ -\x00\x00\x04\x17\ -<\ -?xml version=\x221.\ -0\x22 encoding=\x22UTF\ --8\x22?>\x0d\x0a\x0d\x0a \x0d\x0a <\ -title>icon / Pre\ -ferences / Files\ -\x0d\x0a Created with\ - Sketch.\x0d\ -\x0a \x0d\x0a \ - \x0d\x0a \x0d\x0a\x0d\x0a\ -\x00\x00\x03i\ -<\ -?xml version=\x221.\ -0\x22 encoding=\x22UTF\ --8\x22?>\x0d\x0a\x0d\x0a \x0d\x0a <\ -title>icon / Pre\ -ferences / Gizmo\ -s\x0d\x0a <\ -desc>Created wit\ -h Sketch.\ -\x0d\x0a \x0d\x0a \ - \x0d\x0a \x0d\x0a\ -\x0d\x0a\ -\x00\x00\x00[\ -\x00\ -\x00\x01Fx\x9c\x8d\x8c1\x0a\x800\x10\x04\xe7\xacD\ -P;\xeb\x94\x96>\xc1\xa7\xf9d\xad\x05\xcf\x8d\x88B\ -\xc0\x98Y\x86\x83cY\xa80B\x80V\x99\x0c\x06`\ -\x94z1KS\x22\x0b/\xd5m\xc4\xdd)\xa2\x93\xcd\ -\xb7\xfd~Pk5\xde\x5c\xef\xdaI\xf0\x12\xb6\xbc+\ -\xf6\xf8\xd7M9\x01\x0cb\x81\xee\ -\x00\x00\x00[\ -\x00\ -\x00\x01Fx\x9c\xc5\xc81\x0e@@\x18D\xe1\xf9W\ -!**\xad-\x95n\xc0\xcd\xec\xd1\x1c\xc5\x11\x94\x0a\ -\xf1\xec\xc6\x8a\x0bH|\x93\xd7\x8c\xe4d\xf2^jT\ -i0\xa9\x95\xd4\xc7\xe2\xa5)fqI\xd0\xcb\xe5\x12\ -@\x7f\xe3q\xcep\x8c\xb0w\xb0\xd5\xb0\x96\xb0\x14\x10\ -\xec\xfe\xbe.\xbb\x00\x9d\x16jC\ -\x00\x00\x01F\ -\x00\ -\x00\x02\x00\x01\x00 \x00\x00\x0c\x00\x04\x000\x01\x00\ -\x00\x16\x00\x00\x00(\x00\x00\x00 \x00\x00\x00@\x00\x00\ -\x00\x01\x00\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x07\xf8\x00\x00\x07\xf8\x00\x00\x0f\xfc\x00\x00\x0f\xfc\ -\x00\x00\x1f\xfc\x00\x00\x1f\xfe\x00\x00?\xfe\x00\x00/\xfe\ -\x00\x00o\xfe\x00\x00\xef\xfe\x00\x00\xcf\xf6\x00\x00\x0d\xb6\ -\x00\x00\x0d\xb4\x00\x00\x0d\xb0\x00\x00\x0d\x80\x00\x00\x0c\x00\ -\x00\x00\x0c\x00\x00\x00\x0c\x00\x00\x00\x0c\x00\x00\x00\x0c\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf0\x03\ -\xff\xff\xf0\x03\xff\xff\xf0\x03\xff\xff\xe0\x01\xff\xff\xe0\x01\ -\xff\xff\xc0\x01\xff\xff\xc0\x00\xff\xff\x80\x00\xff\xff\x80\x00\ -\xff\xff\x00\x00\xff\xfe\x00\x00\xff\xfe\x00\x00\xff\xfe \x00\ -\xff\xff\xe0\x01\xff\xff\xe0\x03\xff\xff\xe0\x0f\xff\xff\xe0\x7f\ -\xff\xff\xe1\xff\xff\xff\xe1\xff\xff\xff\xe1\xff\xff\xff\xe1\xff\ -\xff\xff\xf3\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\ -\x00\x00\x00\xa7\ -\x00\ -\x00\x0c\xbex\x9c\xed\x921\x0a\xc20\x18\x85_t\xe8\ -Rp\x13\xc7\x8e=\x867\xf0J\x1e\xc1cx\x0c\xc1\ -\x8btsut(<_\x8bC1\x12K\x93\xdfA\ -\xfe\x0f\x1e\x09\x09\xf9^\x02\x01V\x08h\x1a\x8c\xe3\xb9\ -\x06\xb6\x00ZEK\xd8+\x01;\x8c\xd4p\x1c\xc7q\ -\x9c?\x85\x11\xa6\xf2\x82\xfe\x8f\xf2R\x15\x09\xf9\x0f\xfc\ -\x99\x15_\xe59\xfe\xa9\xc1\xce?\xe7!\x8b+\xe2\xb7\ -\xbci\x8b\xf8c\xdbt\x92}\xf7\x94\xbf\xa0\xdc\x08k\ -\xbf\x11\xe9\x0f9\x8f~C>*\xf2\xaetk\xf22\ -$\x90G\x05C\xd4rR\xba\xf0\xda?\x90W\x9d\xbb\ -)O\x85i\xaa%\ -\x00\x00\x01F\ -\x00\ -\x00\x02\x00\x01\x00 \x00\x00\x06\x00\x06\x000\x01\x00\ -\x00\x16\x00\x00\x00(\x00\x00\x00 \x00\x00\x00@\x00\x00\ -\x00\x01\x00\x01\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\ -\x00\xff\xff\xff\x00\x000\x00\x00\x000\x00\x00\x000\x00\ -\x00\x01\xfe\x00\x00\x01\xfe\x00\x00\x000\x00\x00\x000\x00\ -\x00\x001\x80\x00\x00\x01\x80\x00\x00\x03\x00\x00\x00\x03\x00\ -\x00\x00\x06\x00\x00\x00F\x00\x00\x00l\x00\x00\x00|\x00\ -\x00\x00\x7f\x80\x00\x00\x7f\x00\x00\x00~\x00\x00\x00|\x00\ -\x00\x00x\x00\x00\x00p\x00\x00?\xe0\x00\x00 \x00\ -\x00 \x00\x00 \x00\x00 \x00\x00 \x00\ -\x00 \x00\x00 \x00\x00?\xe0\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\xff\xcf\xff\xff\xff\xcf\xff\xff\xff\xcf\xff\ -\xff\xfe\x01\xff\xff\xfe\x01\xff\xff\xff\xcf\xff\xff\xff\xce\x7f\ -\xff\xff\xcc?\xff\xff\xfc?\xff\xff\xf8\x7f\xff\xffx\x7f\ -\xff\xff0\xff\xff\xff\x10\xff\xff\xff\x01\xff\xff\xff\x00\x1f\ -\xff\xff\x00?\xff\xff\x00\x7f\xff\xff\x00\xff\xff\xff\x01\xff\ -\xff\xff\x03\xff\xff\x80\x07\xff\xff\x80\x0f\xff\xff\x9f\xcf\xff\ -\xff\x9f\xcf\xff\xff\x9f\xcf\xff\xff\x9f\xcf\xff\xff\x9f\xcf\xff\ -\xff\x9f\xcf\xff\xff\x9f\xcf\xff\xff\x80\x0f\xff\xff\x80\x0f\xff\ -\xff\xff\xff\xff\xff\ -\x00\x00\x00`\ -\x00\ -\x00\x01Fx\x9cc``b`dPP``\xe0\ -f\xe0e0`d`\x10c``\xd0\x00b\xa0\x10\ -\x83\x03\x103\x02!\x0840 \x00\x13\x14\x83\xc0\xff\ -\xff\xff\x19H\x025@\x1c\x82\x03\x0b\xe0\x91\xab\xc1m\ -\xe4\x7fR@3&\xfe\xdd\xbc\xff\xff\xe7\xe6\xf9\xff\x1f\ -0\xf0\x83i\x10\x1f\x9b:\x5c\x00\x00\x81\xb3~\xf0\ -\x00\x00\x01F\ -\x00\ -\x00\x02\x00\x01\x00 \x00\x00\x0f\x00\x0f\x000\x01\x00\ -\x00\x16\x00\x00\x00(\x00\x00\x00 \x00\x00\x00@\x00\x00\ -\x00\x01\x00\x01\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\ -\x00\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x03\x80\x00\x00\x02\x80\x00\x00\x02\x80\ -\x00\x00\x02\x80\x00\x00\x02\x80\x00\x00\x04@\x00\x00\x0c`\ -\x00\x03\xf0\x1f\x80\x02\x01\x00\x80\x03\xf0\x1f\x80\x00\x0c`\ -\x00\x00\x04@\x00\x00\x02\x80\x00\x00\x02\x80\x00\x00\x02\x80\ -\x00\x00\x02\x80\x00\x00\x03\x80\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\ -\xff\xff\xfe\xff\xff\xff\xfc\x7f\xff\xff\xfc\x7f\xff\xff\xfc\x7f\ -\xff\xff\xfc\x7f\xff\xff\xfc\x7f\xff\xff\xf9?\xff\xff\xf1\x1f\ -\xff\xfc\x03\x80\x7f\xf0\x1e\xf0\x1f\xfc\x03\x80\x7f\xff\xf1\x1f\ -\xff\xff\xf9?\xff\xff\xfc\x7f\xff\xff\xfc\x7f\xff\xff\xfc\x7f\ -\xff\xff\xfc\x7f\xff\xff\xfc\x7f\xff\xff\xfe\xff\xff\xff\xfe\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\ -\x00\x00\x01F\ -\x00\ -\x00\x02\x00\x01\x00 \x00\x00\x10\x00\x0d\x000\x01\x00\ -\x00\x16\x00\x00\x00(\x00\x00\x00 \x00\x00\x00@\x00\x00\ -\x00\x01\x00\x01\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\ -\x00\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\ - \x01\x00\x00@\x00\xc0\x01\x80\x008\x0e\x00\x00\x07\xf0\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf9\xff\xff\xcf\xf8\xff\xff\ -\x8f\xfc?\xfe\x1f\xfe\x07\xe0?\xff\x00\x00\x7f\xff\xc0\x01\ -\xff\xff\xf8\x0f\xff\xff\xff\xff\xff\xff\xff\x7f\xff\xff\xfe?\ -\xff\xff\xff\x7f\xff\xff\xff\x7f\xff\xff\xff\x7f\xff\xff\xfe?\ -\xff\xff\xff\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\ -\x00\x00\x00X\ -\x00\ -\x00\x01Fx\x9c\xc5\xcd1\x0a\x800\x0cF\xe1\x97.\ -\xe2\xa4\x93k;:z\x83z\xb3\xf6\xc8\xbdA\xfc\x0b\ -\x05A\x9c\x5c|\xe1#\x90\xa1\x85\x80\x91\x12\xac\xcc\x1c\ -\x06\x1b\xb0\x8bN\x9cb\x9a^\xe5.\x0c=w\xe7\xef\ -\xfc\xa5V>+\x92\x1bDYd\x1a;\xea\xd9,\xe5\ -\xf9\xd7\x05'\x93i\xe6\ -\x00\x00\x01F\ -\x00\ -\x00\x02\x00\x01\x00 \x00\x00\x03\x00\x03\x000\x01\x00\ -\x00\x16\x00\x00\x00(\x00\x00\x00 \x00\x00\x00@\x00\x00\ -\x00\x01\x00\x01\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\ -\x00\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x1e\x00\x00\x00\x1e\x00\ -\x00\x00\x1e\x00\x00\x00\x1e\x00\x00\x18\x1e\x00\x00\x14\x0c\x00\ -\x00\x12\x00\x00\x00\x11\xe0\x00\x00\x10\x10\x00\x00\x10 \x00\ -\x00\x10@\x00\x00\x10\x80\x00\x00\x11\x00\x00\x00\x12\x00\x00\ -\x00\x14\x00\x00\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xf3\xff\xff\xff\xe1\xff\xff\xff\xc0\xff\xff\xff\xc0\xff\ -\xff\xff\xc0\xff\xff\xff\xc0\xff\xff\xe7\xc0\xff\xff\xe3\xe1\xbf\ -\xff\xe1\xf3\xbf\xff\xe0\x1e\x0f\xff\xe0\x0f\xbf\xff\xe0\x1f\xbf\ -\xff\xe0?\xff\xff\xe0\x7f\xff\xff\xe0\xff\xff\xff\xe1\xff\xff\ -\xff\xe3\xff\xff\xff\xe7\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\ -\x00\x00\x01F\ -\x00\ -\x00\x02\x00\x01\x00 \x00\x00\x00\x00\x18\x000\x01\x00\ -\x00\x16\x00\x00\x00(\x00\x00\x00 \x00\x00\x00@\x00\x00\ -\x00\x01\x00\x01\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\ -\x00\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\xf0\x00\x00\x00\x88\x00\x00\x00\x84\x00\x00\x00\x82\x00\x00\ -\x00A\x00\x00\x00 \x80\x00\x00\x10@\x00\x00\x0b\xa0\x00\ -\x00\x05\xd6\x00\x00\x02\xe9\x00\x00\x01a\x00\x00\x00\x81\x00\ -\x00\x00@\x80\x00\x00\x80@\x00\x00\x80 \x00\x00p \ -\x00\x00\x08 \x00\x00\x04@\x00\x00\x03\x80\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\x0f\xff\xff\xff\x07\xff\xff\xff\x03\xff\xff\xff\x01\xff\xff\ -\xff\x80\xfc\xff\x0f\xc0~|c\xe0?1\xf9\xf0\x1f\x87\ -\xff\xf8\x09\xfd\xff\xfc\x00\xf8\xff\xfe\x00\xf0\x7f\xff\x00\xfd\ -\xdb\xff\x80}\xdb\xff\x00=\xdb\xff\x00\x1d\xc3\xff\x80\x1d\ -\xdb\xff\xf0\x1d\xdb\xff\xf8=\xdb\xff\xfcp\x7f\xff\xff\xf8\ -\xff\xff\xff\xfd\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\ -\x00\x00\x01F\ -\x00\ -\x00\x02\x00\x01\x00 \x00\x00\x01\x00\x01\x000\x01\x00\ -\x00\x16\x00\x00\x00(\x00\x00\x00 \x00\x00\x00@\x00\x00\ -\x00\x01\x00\x01\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\ -\x00\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x18\x00\x00\x00\x18\x00\x00\x00\x18\x00\x00\x00\xff\x00\x00\ -\x00\xff\x00\x00\x00\x18\x00\x00\x00\x18\x00\x00\x00\x18\xc0\x00\ -\x00\x00\xc0\x00\x00\x01\x80\x00\x00\x01\x80\x00\x00\x03\x00\x00\ -\x00#\x00\x00\x006\x00\x00\x00>\x00\x00\x00?\xc0\x00\ -\x00?\x80\x00\x00?\x00\x00\x00>\x00\x00\x00<\x00\x00\ -\x008\x00\x00\x000\x00\x00\x00 \x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xe7\xff\xff\xff\xe7\xff\xff\xff\xe7\xff\xff\xff\x00\xff\xff\ -\xff\x00\xff\xff\xff\xe7\xff\xff\xff\xe7?\xff\xff\xe6\x1f\xff\ -\xff\xfe\x1f\xff\xff\xfc?\xff\xff\xbc?\xff\xff\x98\x7f\xff\ -\xff\x88\x7f\xff\xff\x80\xff\xff\xff\x80\x0f\xff\xff\x80\x1f\xff\ -\xff\x80?\xff\xff\x80\x7f\xff\xff\x80\xff\xff\xff\x81\xff\xff\ -\xff\x83\xff\xff\xff\x87\xff\xff\xff\x8f\xff\xff\xff\x9f\xff\xff\ -\xff\xff\xff\xff\xff\ -\x00\x00\x01F\ -\x00\ -\x00\x02\x00\x01\x00 \x00\x00\x0f\x00\x0f\x000\x01\x00\ -\x00\x16\x00\x00\x00(\x00\x00\x00 \x00\x00\x00@\x00\x00\ -\x00\x01\x00\x01\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\ -\x00\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x07\xe0\ -\x00\x00\x18\x18\x00\x00 \x04\x00\x00@\x02\x00\x00\x80\x01\ -\x00\x01\x00\x00\x80\x01\x00\x00\x80\x02\x00\x00@\x02\x00\x00\ -@\x02\x02\x00@\x02\x02\x00\x00\x02\x03\x00\x00\x02\x00\x00\ -\x00\x01\x00\x7f\x80\x01\x00 \x80\x00\x80\x10\x80\x00@\x08\ -\x80\x00 \x04\x80\x00\x18\x1a\x80\x00\x07\xe1\x80\x00\x00\x00\ -\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf8\x1f\ -\xff\xff\xe0\x07\xff\xff\xc7\xe3\xff\xff\x9f\xf9\xff\xff?\xfc\ -\xff\xfe\x7f\xfe\x7f\xfe\x7f\xfe\x7f\xfc\xff\xff?\xfc\xff\xff\ -?\xfc\xfc\x7f?\xfc\xfc\x7f\xff\xfc\xfc\x7f\xff\xfc\xff\xff\ -\xff\xfe\x7f\x80\x7f\xfe\x7f\xc0\x7f\xff?\xe0\x7f\xff\x9f\xf0\ -\x7f\xff\xc7\xe0\x7f\xff\xe0\x04\x7f\xff\xf8\x1e\x7f\xff\xff\xff\ -\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\ -\x00\x00\x01F\ -\x00\ -\x00\x02\x00\x01\x00 \x00\x00\x0f\x00\x0f\x000\x01\x00\ -\x00\x16\x00\x00\x00(\x00\x00\x00 \x00\x00\x00@\x00\x00\ -\x00\x01\x00\x01\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\ -\x00\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x80\x00\x00\x04@\ -\x00\x00\x08 \x00\x00\x02\x80\x00\x00\x22\x88\x00\x00B\x84\ -\x00\x00\x9e\xf2\x00\x01\x00\x01\x00\x00\x9e\xf2\x00\x00B\x84\ -\x00\x00\x22\x88\x00\x00\x02\x80\x00\x00\x08 \x00\x00\x04@\ -\x00\x00\x02\x80\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff\xfc\x7f\xff\xff\xf8?\ -\xff\xff\xf0\x1f\xff\xff\xfc\x7f\xff\xff\xdcw\xff\xff\x9cs\ -\xff\xff\x00\x01\xff\xfe\x00\x00\xff\xff\x00\x01\xff\xff\x9cs\ -\xff\xff\xdcw\xff\xff\xfc\x7f\xff\xff\xf0\x1f\xff\xff\xf8?\ -\xff\xff\xfc\x7f\xff\xff\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\ -\x00\x00\x01F\ -\x00\ -\x00\x02\x00\x01\x00 \x00\x00\x04\x00\x06\x000\x01\x00\ -\x00\x16\x00\x00\x00(\x00\x00\x00 \x00\x00\x00@\x00\x00\ -\x00\x01\x00\x01\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\ -\x00\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x03\xe0\x00\x00\x03\xe8\x00\x00\x03\xe0\x00\x00\x03\xe8\ -\x00\x00\x00\x08\x00\x00\x01\xf0\x00\x00\x0c\x00\x00\x00\x0c\x00\ -\x00\x00\x00\x00\x00\x00`\x00\x00\x00`\x00\x00\x00\x00\x00\ -\x00\x1f\x00\x00\x00\x13@\x00\x00\x13@\x00\x00\x1f@\x00\ -\x00\x00@\x00\x00\x0f\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf8\x0f\ -\xff\xff\xf8\x07\xff\xff\xf8\x03\xff\xff\xf8\x03\xff\xff\xf8\x03\ -\xff\xff\xf8\x03\xff\xff\xf0\x03\xff\xff\xe0\x03\xff\xff\xe1\xff\ -\xff\xff\x93\xff\xff\xff\x0f\xff\xff\xff\x0f\xff\xff\xc0\x1f\xff\ -\xff\xc0?\xff\xff\xc0\x1f\xff\xff\xc0\x1f\xff\xff\xc0\x1f\xff\ -\xff\xc0\x1f\xff\xff\xe0\x1f\xff\xff\xf0\x1f\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\ -\x00\x00\x01F\ -\x00\ -\x00\x02\x00\x01\x00 \x00\x00\x01\x00\x01\x000\x01\x00\ -\x00\x16\x00\x00\x00(\x00\x00\x00 \x00\x00\x00@\x00\x00\ -\x00\x01\x00\x01\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\ -\x00\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x00\x00\ -\x00\x0e\x00\x00\x00\x0e\x00\x00\x00\x00\x80\x00\x00\x01@\x00\ -\x00\x00\xa0\x00\x00\x00P\x00\x00\x00(\x00\x00\x00\x14\x00\ -\x00\x00\x0a\x00\x00\x00\x05\x00\x00\x00\x02\x80\x00\x00\xc1\x00\ -\x00\x00\xc0\xe0\x00\x01\x80\xe0\x00\x01\x80\xe0\x00\x03\x00\x00\ -\x00#\x00\x00\x006\x00\x00\x00>\x00\x00\x00?\xc0\x00\ -\x00?\x80\x00\x00?\x00\x00\x00>\x00\x00\x00<\x00\x00\ -\x008\x00\x00\x000\x00\x00\x00 \x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\xff\xff\xff\xff\xf1\xff\xff\xff\xe0\xff\xff\ -\xff\xe0\xff\xff\xff\xe0\xff\xff\xff\xf0\x7f\xff\xff\xfe?\xff\ -\xff\xff\x1f\xff\xff\xff\x8f\xff\xff\xff\xc7\xff\xff\xff\xe3\xff\ -\xff\xff\xf1\xff\xff\xff\xf8\xff\xff\xff<\x7f\xff\xfe\x1e\x1f\ -\xff\xfe\x1e\x0f\xff\xfc>\x0f\xff\xbc>\x0f\xff\x98\x7f\x1f\ -\xff\x88\x7f\xff\xff\x80\xff\xff\xff\x80\x0f\xff\xff\x80\x1f\xff\ -\xff\x80?\xff\xff\x80\x7f\xff\xff\x80\xff\xff\xff\x81\xff\xff\ -\xff\x83\xff\xff\xff\x87\xff\xff\xff\x8f\xff\xff\xff\x9f\xff\xff\ -\xff\xff\xff\xff\xff\ -\x00\x00\x01F\ -\x00\ -\x00\x02\x00\x01\x00 \x00\x00\x01\x00\x01\x000\x01\x00\ -\x00\x16\x00\x00\x00(\x00\x00\x00 \x00\x00\x00@\x00\x00\ -\x00\x01\x00\x01\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\ -\x00\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\x00\x00\ -\x00\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc0\x00\ -\x00\x00\xc0\x00\x00\x01\x80\x00\x00\x01\x80\x00\x00\x03\x00\x00\ -\x00#\x00\x00\x006\x00\x00\x00>\x00\x00\x00?\xc0\x00\ -\x00?\x80\x00\x00?\x00\x00\x00>\x00\x00\x00<\x00\x00\ -\x008\x00\x00\x000\x00\x00\x00 \x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\ -\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff?\xff\xff\xfe\x1f\xff\ -\xff\xfe\x1f\xff\xff\xfc?\xff\xff\xbc?\xff\xff\x98\x7f\xff\ -\xff\x88\x7f\xff\xff\x80\xff\xff\xff\x80\x0f\xff\xff\x80\x1f\xff\ -\xff\x80?\xff\xff\x80\x7f\xff\xff\x80\xff\xff\xff\x81\xff\xff\ -\xff\x83\xff\xff\xff\x87\xff\xff\xff\x8f\xff\xff\xff\x9f\xff\xff\ -\xff\xff\xff\xff\xff\ -\x00\x00\x00\xc9\ -\x00\ -\x00\x0c\xbex\x9cc``b`dPP`\x00\x83\ -\x15<\x0c\x0cb@Z\x03\x88AB\x0e@\xcc\xc8 \ -\x01\x91\xe4a\x18@`<\x93\x04D\xba\xe13\xff\xff\ -g\x98I4\x22\xd5\x0a\x88\xf9g\x88C\xa3\xe6\x8f\x9a\ -?\x10\xe6\x13\x8f\xc8\xcbb4\xcc\xbf\xc3\x0e\xfc\x07\x83\ -!j\xfe\xa8\xe31\xcd\xa4\xb5\xf9\x103i\x142\xff\ -Q\x01\xad\xcd\xa7\xbaE45\x1c\xab\xf9T4\x1c\xd3\ -|\xea\x1a\x8ef>\xd5\x0dG6\x9f\x16\x863\xd0\xa5\ -\xc0\xa1\x9d\xe1C\x1a\x80\xc2\xfd\x01\x83\xfd\xff\x03\x0c\xf2\ -\x041H\x1d\x18\x00\xa9\x7f\xf2\x10\xfc\x07\xc8\xde\x03\xc4\ -3\xea\xff\xff\xef\x00\xe2\x06\xa0t\x03?\x10\x03\xe5\x1a\ -\x80\xe2\x0dP\xb1F n\x06\xe2v \xee\x07\xe2\xf9\ -\xd0\x04\x05\x00\x85\x1b/\xe1\ -\x00\x00\x00\x5c\ -\x00\ -\x00\x01Fx\x9cc``b`dPP``\x10\ -`\xe0d0`d`\x10c``\xd0\x00b\xa0\x10\ -\x83\x03\x103\x02!\x0840 \x00\x13\x14\x83\xc0\xff\ -\xff\xff\x19\x06\x1a\xfc\x87\x81\x1f\xf2\xd4\xc7\x0d\x8c\xff\xff\ -\x1f`\xfe\xff\xff\x01\xfb\xff\xff\x1f\xf8!b\x7f\xec\xff\ -\xff\xffW\x0f\xb7\x16\x00\xb3\x96jC\ -\x00\x00\x01F\ -\x00\ -\x00\x02\x00\x01\x00 \x00\x00\x07\x00\x18\x000\x01\x00\ -\x00\x16\x00\x00\x00(\x00\x00\x00 \x00\x00\x00@\x00\x00\ -\x00\x01\x00\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x01\xe0\x00\x00\x01\x10\x00\x00\x01\x08\x00\x00\x01\x04\x00\ -\x00\x00\x82\x00\x00\x00A\x00\x00\x00 \x80\x00\x00\x17@\ -\x00\x00\x0b\xac\x00\x00\x05\xd2\x00\x00\x02\xc2\x00\x00\x01\x02\ -\x00\x00\x00\x81\x00\x00\x01\x00\x80\x00\x01\x00@\x00\x00\xe0\ -@\x00\x00\x10@\x00\x00\x08\x80\x00\x00\x07\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xfe\x1f\xff\xff\xfe\x0f\xff\xff\xfe\x07\xff\xff\xfe\x03\xff\ -\xff\xff\x01\xff\xff\xff\x80\xff\xff\xff\xc0\x7f\xff\xff\xe0?\ -\xff\xff\xf0\x13\xff\xff\xf8\x01\xff\xff\xfc\x01\xff\xff\xfe\x01\ -\xff\xff\xff\x00\xff\xff\xfe\x00\x7f\xff\xfe\x00?\xff\xff\x00\ -?\xff\xff\xe0?\xff\xff\xf0\x7f\xff\xff\xf8\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\ -\x00\x00\x01F\ -\x00\ -\x00\x02\x00\x01\x00 \x00\x00\x11\x00\x0d\x000\x01\x00\ -\x00\x16\x00\x00\x00(\x00\x00\x00 \x00\x00\x00@\x00\x00\ -\x00\x01\x00\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff?\xff\xff\xff\x1f\xff\ -\xff\xff\x8f\xff\xff\xff\xc4\x0f\xff\xff\xe1\xe7\xff\xff\xf3\xf3\ -\xff\xff\xe3\xf9\xff\xff\xef\xfd\xff\xff\xef\xfd\xff\xff\xef\xfd\ -\xff\xff\xef\xfd\xff\xff\xe7\xf9\xff\xff\xf3\xf3\xff\xff\xf9\xe7\ -\xff\xff\xfc\x0f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\ -\x00\x00\x01F\ -\x00\ -\x00\x02\x00\x01\x00 \x00\x00\x07\x00\x0e\x000\x01\x00\ -\x00\x16\x00\x00\x00(\x00\x00\x00 \x00\x00\x00@\x00\x00\ -\x00\x01\x00\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x07\xf8\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xf7\xff\xff\xff\xe7\xff\xff\xff\xe7\ -\xff\xff\xff\x0f\xff\xff\xfe\x7f\xff\xff\xfe\x7f\xff\xfe\xfe\xff\ -\xff\xff~\xff\xff\xfe \x01\xff\xff\x00\x01\xff\xfe0\x03\ -\xff\xff~\xff\xff\xfe\xfc\x7f\xff\xff\xfc\x7f\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\ -\x00\x00\x01F\ -\x00\ -\x00\x02\x00\x01\x00 \x00\x00\x03\x00\x03\x000\x01\x00\ -\x00\x16\x00\x00\x00(\x00\x00\x00 \x00\x00\x00@\x00\x00\ -\x00\x01\x00\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x18\x00\x00\x00\x14\x00\x00\x00\x12\x00\x00\ -\x00\x11\xf8\x00\x00\x10\x08\x00\x00\x10\x10\x00\x00\x10 \x00\ -\x00\x10@\x00\x00\x10\x80\x00\x00\x11\x00\x00\x00\x12\x00\x00\ -\x00\x14\x00\x00\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xe7\xff\xff\xff\xe3\xff\xff\xff\xe1\xff\xff\ -\xff\xe0\x07\xff\xff\xe0\x07\xff\xff\xe0\x0f\xff\xff\xe0\x1f\xff\ -\xff\xe0?\xff\xff\xe0\x7f\xff\xff\xe0\xff\xff\xff\xe1\xff\xff\ -\xff\xe3\xff\xff\xff\xe7\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\ -\x00\x00\x01F\ -\x00\ -\x00\x02\x00\x01\x00 \x00\x00\x10\x00\x08\x000\x01\x00\ -\x00\x16\x00\x00\x00(\x00\x00\x00 \x00\x00\x00@\x00\x00\ -\x00\x01\x00\x01\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\ -\x00\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\xf0\x00\x00\x07\xf0\ -\x00\x00\x0f\xf8\x00\x00\x1f\xf8\x00\x00\x1f\xfc\x00\x00?\xfc\ -\x00\x00w\xfc\x00\x00g\xfe\x00\x00\x07\xf6\x00\x00\x0d\xb6\ -\x00\x00\x0d\xb2\x00\x00\x19\xb0\x00\x00\x19\xb0\x00\x00\x01\x80\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xfc\x0f\xff\xff\xf8\x07\xff\xff\xf0\x07\ -\xff\xff\xe0\x03\xff\xff\xc0\x03\xff\xff\xc0\x01\xff\xff\x80\x01\ -\xff\xff\x00\x01\xff\xff\x00\x00\xff\xff\x90\x00\xff\xff\xe0\x00\ -\xff\xff\xe0\x00\xff\xff\xc0\x05\xff\xff\xc0\x07\xff\xff\xe4\x0f\ -\xff\xff\xfe\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\ -\x00\x00\x01F\ -\x00\ -\x00\x02\x00\x01\x00 \x00\x00\x03\x00\x03\x000\x01\x00\ -\x00\x16\x00\x00\x00(\x00\x00\x00 \x00\x00\x00@\x00\x00\ -\x00\x01\x00\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x0a\x00\ -\x00\x00\x11\x00\x00\x00*\x80\x00\x18[@\x00\x14\x80 \ -\x00\x12[@\x00\x11\xea\x80\x00\x10\x11\x00\x00\x10*\x00\ -\x00\x10D\x00\x00\x10\x80\x00\x00\x11\x00\x00\x00\x12\x00\x00\ -\x00\x14\x00\x00\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfb\xff\xff\xff\xf1\xff\ -\xff\xff\xe0\xff\xff\xff\xd1\x7f\xff\xe7\x80?\xff\xe3\x00\x1f\ -\xff\xe1\x80?\xff\xe0\x11\x7f\xff\xe0\x00\xff\xff\xe0\x11\xff\ -\xff\xe0;\xff\xff\xe0\x7f\xff\xff\xe0\xff\xff\xff\xe1\xff\xff\ -\xff\xe3\xff\xff\xff\xe7\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\ -\x00\x00\x01F\ -\x00\ -\x00\x02\x00\x01\x00 \x00\x00\x0f\x00\x0f\x000\x01\x00\ -\x00\x16\x00\x00\x00(\x00\x00\x00 \x00\x00\x00@\x00\x00\ -\x00\x01\x00\x01\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\ -\x00\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00?\xff\x80\x00!\x00\x80\x00!*\x80\x00!T\ -\x80\x00!*\x80\x00!T\x80\x00!*\x80\x00!T\ -\x80\x00!\x00\x80\x00!\xfe\x80\x00 \x00\x80\x00 \x00\ -\x80\x00 \x00\x80\x00 \x00\x80\x00?\xff\x80\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xc0\x00\x7f\xff\xc0\x00\x7f\xff\xce\x00\x7f\xff\xce\x00\ -\x7f\xff\xce\x00\x7f\xff\xce\x00\x7f\xff\xce\x00\x7f\xff\xce\x00\ -\x7f\xff\xce\x00\x7f\xff\xce\x00\x7f\xff\xcf\xfe\x7f\xff\xcf\xfe\ -\x7f\xff\xcf\xfe\x7f\xff\xc0\x00\x7f\xff\xc0\x00\x7f\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\ -\x00\x00\x01F\ -\x00\ -\x00\x02\x00\x01\x00 \x00\x00\x03\x00\x03\x000\x01\x00\ -\x00\x16\x00\x00\x00(\x00\x00\x00 \x00\x00\x00@\x00\x00\ -\x00\x01\x00\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18\x00\x00\x00\x14\x00\x00\ -\x00\x12\x00\x00\x00\x15\xf0\x00\x00\x16\x10\x00\x00\x17\xa0\x00\ -\x00\x17@\x00\x00\x16\x80\x00\x00\x15\x00\x00\x00\x12\x00\x00\ -\x00\x14\x00\x00\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe7\xff\xff\xff\xe3\xff\xff\ -\xff\xe1\xff\xff\xff\xe0\x0f\xff\xff\xe0\x0f\xff\xff\xe0\x1f\xff\ -\xff\xe0?\xff\xff\xe0\x7f\xff\xff\xe0\xff\xff\xff\xe1\xff\xff\ -\xff\xe3\xff\xff\xff\xe7\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\ -\x00\x00\x01F\ -\x00\ -\x00\x02\x00\x01\x00 \x00\x00\x06\x00\x06\x000\x01\x00\ -\x00\x16\x00\x00\x00(\x00\x00\x00 \x00\x00\x00@\x00\x00\ -\x00\x01\x00\x01\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\ -\x00\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x01\xfe\x00\x00\x01\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x01\x80\x00\x00\x01\x80\x00\x00\x03\x00\x00\x00\x03\x00\ -\x00\x00\x06\x00\x00\x00F\x00\x00\x00l\x00\x00\x00|\x00\ -\x00\x00\x7f\x80\x00\x00\x7f\x00\x00\x00~\x00\x00\x00|\x00\ -\x00\x00x\x00\x00\x00p\x00\x00?\xe0\x00\x00 \x00\ -\x00 \x00\x00 \x00\x00 \x00\x00 \x00\ -\x00 \x00\x00 \x00\x00?\xe0\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xfe\x01\xff\xff\xfe\x01\xff\xff\xff\xff\xff\xff\xff\xfe\x7f\ -\xff\xff\xfc?\xff\xff\xfc?\xff\xff\xf8\x7f\xff\xffx\x7f\ -\xff\xff0\xff\xff\xff\x10\xff\xff\xff\x01\xff\xff\xff\x00\x1f\ -\xff\xff\x00?\xff\xff\x00\x7f\xff\xff\x00\xff\xff\xff\x01\xff\ -\xff\xff\x03\xff\xff\x80\x07\xff\xff\x80\x0f\xff\xff\x9f\xcf\xff\ -\xff\x9f\xcf\xff\xff\x9f\xcf\xff\xff\x9f\xcf\xff\xff\x9f\xcf\xff\ -\xff\x9f\xcf\xff\xff\x9f\xcf\xff\xff\x80\x0f\xff\xff\x80\x0f\xff\ -\xff\xff\xff\xff\xff\ -\x00\x00\x01F\ -\x00\ -\x00\x02\x00\x01\x00 \x00\x00\x0b\x00\x09\x000\x01\x00\ -\x00\x16\x00\x00\x00(\x00\x00\x00 \x00\x00\x00@\x00\x00\ -\x00\x01\x00\x01\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\ -\x00\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18\x00\x00\x00\x18\ -\x00\x00\x000\x00\x00\x000\x00\x00\x00`\x00\x00\x04`\ -\x00\x00\x06\xc0\x00\x00\x07\xc0\x00\x00\x07\xf8\x00\x00\x07\xf0\ -\x00\x00\x07\xe0\x00\x00\x07\xc0\x00\x00\x07\x80\x00\x01\xff\x00\ -\x00\x01\x01\x00\x00\x01\x01\x00\x00\x01\x01\x00\x00\x01\x01\x00\ -\x00\x01\x01\x00\x00\x01\x01\x00\x00\x01\x01\x00\x00\x01\xff\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xe7\xff\xff\xff\xc3\xff\xff\xff\xc3\ -\xff\xff\xff\x87\xff\xff\xf7\x87\xff\xff\xf3\x0f\xff\xff\xf1\x0f\ -\xff\xff\xf0\x1f\xff\xff\xf0\x01\xff\xff\xf0\x03\xff\xff\xf0\x07\ -\xff\xff\xf0\x0f\xff\xff\xf0\x1f\xff\xfc\x00?\xff\xfc\x00\x7f\ -\xff\xfc\xfe\x7f\xff\xfc\xfe\x7f\xff\xfc\xfe\x7f\xff\xfc\xfe\x7f\ -\xff\xfc\xfe\x7f\xff\xfc\xfe\x7f\xff\xfc\xfe\x7f\xff\xfc\x00\x7f\ -\xff\xfc\x00\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\ -\x00\x00\x00V\ -\x00\ -\x00\x01Fx\x9c\xc5\xc8\xb1\x0d\x800\x0cD\xd1\xef4\ -\x88\x0a*\xda\xa4\xa4d\x03\xd8\xcc\x8c\x9c\x0d\xccE\x8a\ -D\x01\x15\x0d\xdfz\xb2t\x900J\x81\x99\x91\xcd`\ -\x01V\xd1\xc4!\xa6k\x9d\xdc\xa5\xae\x15\x11\xfc]<\ -s\xd9+d\x99d\xe8?W\xd7\xee\xe1\x12_\xbcu\ -\x01\xec\xfbi\xe6\ -\x00\x00\x01F\ -\x00\ -\x00\x02\x00\x01\x00 \x00\x00\x10\x00\x11\x000\x01\x00\ -\x00\x16\x00\x00\x00(\x00\x00\x00 \x00\x00\x00@\x00\x00\ -\x00\x01\x00\x01\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\ -\x00\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xfc\x1f\xc0\x00\x04\x10\ -\x00\x00\x04\x10\x00\x00\x04\x10\x00\x00\x04\x10\x00\x00\x04\x10\ -\x00\x00\x07\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\xfc\x01\xc0\x1f\xfc\x01\xc0\x1f\xfc\x01\xc0\ -\x1f\xff\xf1\xc7\xff\xff\xf1\xc7\xff\xff\xf1\xc7\xff\xff\xf0\x07\ -\xff\xff\xf0\x07\xff\xff\xf0\x07\xff\xff\xff\x7f\xff\xff\xfe?\ -\xff\xff\xff\x7f\xff\xff\xff\x7f\xff\xff\xff\x7f\xff\xff\xfe?\ -\xff\xff\xff\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ -\xff\xff\xff\xff\xff\ -\x00\x00\x00\xef\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xffa\ -\x00\x00\x00\x04gAMA\x00\x00\xb1\x8f\x0b\xfca\x05\ -\x00\x00\x00\x09pHYs\x00\x00\x0e\xc3\x00\x00\x0e\xc3\ -\x01\xc7o\xa8d\x00\x00\x00\x18tEXtSof\ -tware\x00paint.net \ -4.0.6\xfc\x8cc\xdf\x00\x00\x00mIDA\ -T8O\xb5\x8c\xd1\x0a\xc0 \x0c\x03\xfdt\xff\xbc\xb3\ -\x83d]\xa8\xd82\xf6p\xa2\xc7\x99af\x9fHe\ -\x87\xe7\xb2\xae\x15\xd0\xf3\xdf}Htb\xce\xb9\xbe\xc9\ -\x80\xcb\x0a\xdb\x01\x88\x13\xff\x0d\xec@\x08\xdc\xa5\x03.\ -\x15\x8dc\xcb7$DD\xe3\xccQBD4\xce\x1c\ -%DD\xe3\xccQBD4\xce\x1ce\x07|\xe6\x80\ -\xe3\xab\x15\xd0\x83\xd7\xa3\x8f\x8d\x0b\xd1.k\xedV\x14\ -\x8b0\x00\x00\x00\x00IEND\xaeB`\x82\ -\x00\x00\x00\xd0\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xffa\ -\x00\x00\x00\x04gAMA\x00\x00\xb1\x8f\x0b\xfca\x05\ -\x00\x00\x00\x09pHYs\x00\x00\x0e\xc2\x00\x00\x0e\xc2\ -\x01\x15(J\x80\x00\x00\x00\x18tEXtSof\ -tware\x00paint.net \ -4.0.6\xfc\x8cc\xdf\x00\x00\x00NIDA\ -T8O\xdd\x8c\xc1\x09\x00 \x0c\x03\xbb\xffT\xdd\xac\ -\x1a\xb0\x82\xb6*U\x10\xf4q\x8f\x5cBHD\x8ep\ -e\x04+\xb2\x02+\xa7XQ\xc6\xcc\x9c\xe3\xd8\xd5\xce\ -\x88\x7f\x0e<\xee\x1e`\xacl\x1f\xcc\x5c\xed\x8cx\xff\ -\x00`\xd8\x8f=\x07\x9a\x10G(\x01oN\x98?\xf6\ -\xff\xda\xc5\x00\x00\x00\x00IEND\xaeB`\x82\ -\x00\x00\x00\xd4\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xffa\ -\x00\x00\x00\x04gAMA\x00\x00\xb1\x8f\x0b\xfca\x05\ -\x00\x00\x00\x09pHYs\x00\x00\x0e\xc2\x00\x00\x0e\xc2\ -\x01\x15(J\x80\x00\x00\x00\x18tEXtSof\ -tware\x00paint.net \ -4.0.6\xfc\x8cc\xdf\x00\x00\x00RIDA\ -T8O\xed\x8fA\x0a\xc00\x08\x04}\xba?\xb7\xce\ -a/a\xa1m\xbc\xe4\x90\xc0\x043\xd1\x05\xa3\xaaF\ -X\xf9\x07+\xa1\x0fW\x97\xfe_X\x09\x0a\xc8\xcc~\ -\xfa\x1e\xb0R0<\x0a\xf8\x82\x95\xa0\x15V\xbfb%\ -(`{\x85\x1bpB\x000<\x0ax\xa7\xe2\x01V\ -T\xcf_\x16\xfbf\x81\x00\x00\x00\x00IEND\xae\ -B`\x82\ -\x00\x00\x03\xea\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x93\x00\x00\x00\x15\x08\x06\x00\x00\x00B\x0c\xdc\xd0\ -\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\ -\x04gAMA\x00\x00\xb1\x8f\x0b\xfca\x05\x00\x00\x00\ -\x09pHYs\x00\x00\x0b\x11\x00\x00\x0b\x11\x01\x7fd\ -_\x91\x00\x00\x03\x7fIDAThC\xed\x9a\xbbN\ -*Q\x14\x86\x07Cb,\xec}#\x1e\x81\xc6\xca\xbb\ -!\xbe\x81\x8d\x8d\x8d%\x0d=Zig\xb4\xd0\xc4H\ -c(H,\x88\x85Zx\x04\x04\x01\xaf\xf1\x0e\xe2\x92\ -o\x9d\xb3\xf7\x19\x07\xf4\xe4h5\xb0\xff\xe4\x97q\xad\ -=4|\xf9\xf7\x9a\x0d^,\x16\x93n\x9e\x9e\x9e\x96\ -\xa9\xa9)\x99\x9c\x9ctvV\xc3\x03\x5ct\xe3\x05w\ -\xc0\xb4\xbe\xbe.\xa7\xa7\xbf\xda>\x95\xf3\xf3s\xb9\xb8\ -\xb8\x90\xeb\xebk\xb9\xb9\xb9q\xeeS\xf3\xf9\xc3\x01<\ -\xc0\x05|\x04\xb9\xc1\x16& :;;\x93B\xa1 \ -\xb5ZMnoo\xe5\xe1\xe1A\x9e\x9f\x9f\xa5\xd1h\ -8\xf7\xb9\xe1\x00\x1e\xe0\x02>\xe0\x04f:`\xa2X\ -n\x83T*\x95\x94\xc2\xc7\xc7G}\x83V\xab%o\ -ooj\xa7\xfe\x95a\x00\x1e\xe0\x02>\xe0\x04^\x08\ - \x0b\x13 U\xabU-\x12i\x10\xf8\xfa\xfa\xea\x00\ -\xeaS\xb1\x9d\xe5\xf3y\xc9d2\xb2\xb9\xb9\xa9\xde\xdd\ -\xdd\xd5\x1a=\xbf\xe0\x05nLB)L\x14 \x0d\x90\ -\xa0\x0f\x98\x9a\xcd\xa6\xec\xec\xec\xc8\xd2\xd2\x92\x0e^\x98\ -kj\xf4\x9czO\xc7\xc7\xc7\xb2\xbd\xbd\xadpt3\ -=\xd6\x98\xa0\x81\x17\xb81@y\xa4\x12{ \xd1e\ -\x12\x09XVVV$\x1e\x8fw5=\xd6\xb8\xf4\xea\ -\x1d\x01\xc9\xc6\xc6F\x07@A\xb3\x86\xb5\xb0\x82\xe1\x06\ -~\xe8y\x95JE\x87*\xf6B\xe0\xc0\x10\x0843\ -33\xb2\xba\xba*\xc5bQ\xcd55z\xac\xe1\xcd\ -\x9c\xc2/\xb6/\x7f\x22\xed\xed\xed\xd9\xebn5\xd6r\ -\x0f\xac\xc0\x0d\xfcP\xd7dbJg{C,X\x5c\ -\x5cT`\x80'(j\xf4XC\xcc\xb9t\x0a\xbf\x98\ -\x87\xfc\xd0\xa0\xc3\xc3C[\xe3\x1a\xf9\x81\xe2\x1e\x047\ -\xf0C\xcd\x830?\x144'&&\x14\x18\xd2((\ -j\xf4Xs\x7f\x7f\xef`\xea\x011`\x1bH\xb0\x81\ -\x87W\xff\xb5\x7f\x0d\xf7 >\x7f\xf8\xa1\xe6]^^\ -\xca\xcb\xcb\xcb\x07\x98\xc6\xc7\xc7\xff\x09\x13k\x887\xa7\ -\xf0\x8b'6?(\xd8@\x84\x82 a\xeeAp\x03\ -?\xd4<\xa6q3/!`ZXXP`\xbe\xda\ -\xe6X\x03Lf{t\x0a\xaf~\x0a\x13\xfcP\xf3\xae\ -\xae\xae:\x92\xc9\x00\xf3\xd5\x00\x9eN\xa7\xe5\xee\xee\xce\ -\xde\xe7\x14^}g\x9b\xe3\x1c\x0a}H&\xb69\xff\ -\xcc\xc4+\xe7\x06\xc9dR\xa1\xf9\xcc\x89DBO@\ -]2\x85_?\x19\xc0\xe1\xc5\xceL\x0c\xe0L\xe3\x9e\ -\xe7\xd9&\x89srr\x22\xcb\xcb\xcb2??/c\ -ccj\xaeS\xa9\x94M\xa7\xb9\xb99==7 \ -:\x85S\xdf=\x1a@\x84\x89}\x9ac\x9b\xe3X\x1c\ -\x98\x0cP\x9c\x1f\x01T\xb9\x5c\xd6\x03\xaa\x83\x83\x03\xf5\ -\xd1\xd1\x91\xfe\x9f\xcdfevv\xd6\x02\xc5\xa1\x95S\ -\xb8\xf5\xdf\x87\x96\xad\xdfg\x92\xccK\xf0CO\xe9!\ -\xa6\x86\x86\x86d``@\xd6\xd6\xd6\xf4\xcd\x01\x8a:\ -\x8f\xff\x0c\xda\x18\xc00i\x94\xcb\xe5\x14\xa8\xd1\xd1Q\ -\x85\xcb)\xfc\x02\x12\x7fB\x05M\xcf\x80\x84`\xc4\xa4\ -\x92\xfd\xd5\x00\xc0\x0c\x0e\x0e\xdat\x1a\x19\x19\xd1\xc5\x9f\ -\x09\x22\xeb\xf5\xba\xec\xef\xef\xcb\xd6\xd6\x96\x90nN\xbd\ -!\xb6/\xe6!\x86r\x9e\xd8\xb0\xf9\xa2\xb7\xde\xee5\ -\x9a\x7fgd3+\xd9_\x0d\xf0\x07\x0d\x0f\x0fK$\ -\x12\x91h4\xaa\xaff\xcb\xfbLL\xf0\xc4\x1b =\ -==\xfd\xa9:\xf5\xba\x08\x12\x12\x89\xcf\xdc\x0f\x92\x85\ -\x09\xd3\xe0\xcc\xa9V\xab* \xec\x85\x0cW\xdc\xec\x06\ -\xec\xfe\x96a\x00\x1e\xe0\x82Q'\x08\x12\xb609;\ -\xff\xcc1y\x07P\x7f\x17\xd6Q\x02K\x02\x00\x00\x00\ -\x00IEND\xaeB`\x82\ -\x00\x00\x01\xbb\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x0f\x00\x00\x00\x10\x08\x06\x00\x00\x00\xc9V%\x04\ -\x00\x00\x01\x82IDAT(\x91\x8d\xd2O\x88\x8eQ\ -\x14\x06\xf0\xdf7\xf3\xa6Qc#\xb1\x9b\xbe\xc6\xd0,\ -,&\x1dM\x8aI\xa9Ql\xecg\xa1H2J\xb3\ -\xb2\xb4\xc5\xdeJ\x91\xb5\xa6\xc8\xbf\xa5P\x16rD\xb1\ -\xa0\x11\x92\x92\x05if\xc1\xa4)\x8b\xf7}\xa7\xfb}\ ->\xe5Y\x9d{\xcf}\xce9\xf7yN\xc7\x7f 3\ -Gq\x0a\xdb#b\xbe\xbd\xaf\x9a\xe4\x16\x8c\x16\xefW\ -\x22\xe2[fV8\x8e1\x5c\xc1\x91\xa2\xe0H\xa7\x09\ -\xf6a\x02\xd3x\x8aw\x98\xc5\x14~c\xa5(<\x8c\ -M\xd8\xda)*m\xc0\x09\x1c\xc5$\xae\xe3E\xdf\x0f\ -f\xf0\x18\x9b\xf1\xbd\xca\xcc\xcb\xf8\x899\xbc\xc7%\xdc\ -\xc78\xe6\xf1*\x22\xae5\x0d\xba\x11q+3\xbb\x98\ -\x1a\xc2g,#\xb0\x18\x11w\x22b\x0d\x8bX\xc0\xd5\ -\xcc<4H\xc8*\x22.\x16\xa3\x97\xb9\xc9\x22\xde\x9f\ -\x99\x0f0\x91\x99\xc3\xed\xe5\xd0\xa0\x8a\x0d\xde\x16\xf1K\ -\xdcS\x0b\xfa\x05\xc7z\xc8\x99\xb9\x13\x072s.3\ -\xf7\xe2\x1c\x96p\x13\x9fp7\x22\xf6\xe0\xb4\xda\xb2\x91\ -\xaa\xa8\xbe\x80\x8f8\x8b\xdd\xf8\x85\x0b\xb8\x81\xd5\xa6\xc1\ -\x13\xb5\xa5\xb7\xf1\xbc\x1c\xfb\x07\xb6E\xc446\xe2\x0d\ -\x0e\xab}\xff\x80nC\x9a\x8d\x88\x93\x11\xb1T\xfa\xbc\ -\xabI\xee\x88\x88\xb5\xcc\x9c\xc1\xa36\xdd\x8c\xdc\x83\xf5\ -\xce\x11\xf1\x1a\xcb\x8dM\x1aqZ\x8c\xf7\x13\xfb\x05\x1b\ -S/I\x8b\xce?\xe2\xbf\xc9\xf8\x8a3\xc5\xf9Y\x11\ -\xf7,@\x8bu\xb5#bU\xeda\x8b\x87\xea-;\ -\x88\xf3\x83\xc8\x7f\x00k\xb9|\xe7dF#\x7f\x00\x00\ -\x00\x00IEND\xaeB`\x82\ -\x00\x00\x01\x01\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x0f\x00\x00\x00\x12\x08\x06\x00\x00\x00\x84\x9e\x84\x0f\ -\x00\x00\x00\xc8IDAT8\x8d\xa5\xd3=N\x031\ -\x10\x86\xe1gQ\x02]\xe8R\xf3\x97\x0e\xaa\xbd\x12E\ -.\x10J\x84\xc4=\xd2%\x12\x15\x11\xe7\xd8\x8d\x10\xa2\ -\xe5 H\x88M\x11G\xdaX\xded1_7\xdf\xe8\ -\x9d\xf1\x8c\xed\xa2i\x1am\xd5u-\xd2\x19\xbec\xb3\ -,K'\xb1\x99\xd0\x03\xceS\x89>\xf0\x04W\xb9\xf0\ -\xf5\x7f\xe0\x9b\x5cx\x841.s\xe0]\xc7,x\x12\ -\x15\xd9\xd3\xa0\x03\xba\xc3\x10\xb7!\xbe@i;\xffJ\ -\xb8\xf7.x\x88\x0aE\x88OC\xfc\x8a\x97c\xc7^\ -\xe3-\xf2~\xf1\xd86\x0e\xcd\xfc\x84\xf6\xdb]\xe2\xb3\ -/\xfcn;\x1f\xfc\x84b{:\xb6\xed]\xf79\xbe\ -\xfe\x0a\x7f`\x81\xe7T\xb2k\xdbm\xddK|I(\ -\xaa\xaa\xea\xc1\xa75\xc0\x14\xb3\x1cx\x03\xb2\x99!K\ -\xef\xfb\x80\xb9\x00\x00\x00\x00IEND\xaeB`\x82\ -\ -\x00\x00\x02\x1e\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x18\x00\x00\x00\x11\x08\x06\x00\x00\x00\xc7xl0\ -\x00\x00\x01\xe5IDAT8\x8d\x95\xd4]h\x8ea\ -\x18\x07\xf0\xdflIQC\xf2q\x22\x8a\x92\xe2\xd8G\ -!\x0e\x97\x16j\x07D\x88\x94R\xcb\xe7\xa2\x9c\x8d\x92\ -\x906\x16K\xf9\x96!\xc7\xac\xa4\x90\x83\xb7)\x07r\ -\x22\x12\xcd\xc1\x88%\x8b\xf9:\xb8\xafw\xef\xd3\xb3g\ -\xeb\xdd\xbf\x9e\xee\xfb\xbe\xee\xeb\xb9\xfe\xd7\xe7]S*\ -\x95\xea\xf1\xd5pl\xc2\x0d\x5c\xc7\xc6\xdc\xddy\xec.\ -\xf8g\x18\xc6\xe1\x07\x9a\xb0\x03\xbf\xf0\x1d\x9b\xf1$t\ -\xce\xe2p\xec\xbbC\xb7\xb3\x1a\xe3P\x87At\xc5y\ -:\x8ea1\xae\x85\xac\x84\xd3\xf8\x8c-\xe8\xad\xd6x\ -9\x82,N\xe0\x19\xf6bY\xc8Z\xb0\x14\xbb\xc6j\ -\xbc\x88\xe0Ox9\x80\xcbX\x81\xa3\xb8\x82\xbb\x19\xbd\ -\x16\xfc\xcb}\x0dq\xf72+\xcf\x13\xc0\x1b\xec\xc3<\ -<\x0c\xaf\xf7\xe4t\xeeK\xb5x\x1f\xe7\xfd\xe8\xc9\xec\ -\xbbc\xdf^D\x00\x17\xc3\x93\xf1hC\x7f\xee\xfe\xb5\ -T\xb7\x8e8ORI\xdf\x03\xcc\xc0_\xb4\x8eD\xb0\ -\x06\x8bB\xe9\x10f\x8e\xe2\xc8\x00\xb6\xaa\xa4{v\xfc\ -\xfb\x14\xbdE\x04\xf5\xb8\x84W\xd2,L\x93\xda\xb2\xa6\ -@\xb7\x0f71\x07\xabC\xb66\xd6;\x0c/2\x9c\ -\xc1\xac\xf0\xea\x96T\xe0\x06\xec\x1c!\x8a\xb6X\xb7\xc5\ -\xbaN\x8a\xbc\xab\x88\xa01\x0c\x1f\x97\xfa\x1f\x9a\xf1\x01\ -\xa7\xa4\xc2\xe7\xf1\x02\x8f\xb1\x1e\xf3\xb1J\xa4\xa7LP\ -\x8b)\x11f\x87T\xc0\xf6\x90\xc3O\x1c\xc4D\x5c\xc5\ -TL\xce\x91\x9c\xc3\x04)-\xb5\xb1*\x13,\xc4\x17\ -\xbc\x95\x8a\xb9\x00\x9fB\x0e'\xa57\x09\x96H\x13\xfd\ -.Gp\x0f\xad\x98+\xa5ghf\xea\xa4^n*\ -\x08\xbd\xdc\xe3\x9dx\x94\xbb\x1b\xcc\x9d\x7f\xe36\x8eH\ -3\xf01K\xf0M\xe5-*B\x8f\xca\x10\xe5\xb1]\ -\xea\xb6\xe78\x10\xb2\x0bY\x85\xbaQ\x0cW\x83f)\ -\xbd}\xd8 \xbd\xc0\xd9'\xa5\xb0M\xc7\x82~\xac\xc4\ -r)\x95\x8dR\x0d\x86\xf0\x1f\x84\xf8v\x1d=\x86M\ -P\x00\x00\x00\x00IEND\xaeB`\x82\ -\x00\x00\x01p\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x12\x00\x00\x00\x12\x08\x06\x00\x00\x00V\xce\x8eW\ -\x00\x00\x017IDAT8\x8d\x9d\x93\xc1J\xc3@\ -\x14EO\xa2\xa0\xa0\xa2\x05\x11\xba\xf3#\xde\xd2\x8d\xf4\ -\x1b\xc4\x1fp'\x88\xa0\x82Pp\xa3\xa2;\xc5\x95\xee\ -\x14\x7f\xe7\x82\x1f\xe1\xc6\x8d\xa4P\xb5\x9a\xb4\xd5E_\ -a\x88IF\xbc0d\xde\xcd\xc9\x9d7a\x06\x22\x92\ -\xb4#i/\xc6\xcd\xc6\x00\xe0\x02\x98\x01n\x9a\xa04\ -\xd6\x0d\xb0\x0a\xb4|\xfe\xbf \xef\xa6j\xfe\xf7 I\ -\x9d\xa0\xfc\x06\x0aI\x9b\x91\x85\xeb%i \xe9#\xc6\ -\xfd\xeaH\xd2v\xc9\xfa\xf4\x112\x07\x92\xe6+\x83$\ -\xedK\xca\x80\xdbR\xd0\x08(J\xde!\xd0\x93t)\ -)\x05H$\xed\x02g\xc0J\x00\x0e\x81\xdcC\x16\x99\ -\xfc\xa3w&\xc7`\xce\x9fS\xbd\x01\xdd\x14x\x02^\ -K+\x0e\x80\x9e\x8f\xb1\x07\xf5\xdd\xcf\xbd\x9e\xea\x0b\xc8\ -\x92`k\x1d\xe0\x0eh\x9b\xd9B\xe0g@afk\ -\x81\xf7\x0c,\x03'fvM\x95$m\x94\xea\xbe\x87\ -\x85\xdeV\xe5\xc7M\x92\x94K\x1a\xc4\xb8\xa4\xee\x85_\ -\x89.\xb0\xee\xd6\x0bplf\x0fU|\xd3\x15\xb9\x07\ -\xdaA\xbd\x04<\xd6\xc1\xb5Af6\x04\xae\x02\xeb\xd4\ -\xcc\xc6u|\xed\xd6\x00\xfc\xb0\xf5\x81\xdc\xccZMl\ -\xe3\xed\xf7\x0e\xce\x81\xa3&\x0e\xe0\x07\x81\x1e\x7f\x14\x8c\ -;\xe7\x95\x00\x00\x00\x00IEND\xaeB`\x82\ -\x00\x00\x01{\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x12\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1b\x06/\x5c\ -\x00\x00\x01BIDAT8\x8d\x95\xd3?K\xdbQ\ -\x14\xc6\xf1OB\xaa\x9bb\xfd\xb3IQ\xc8(\x08\x97\ -:\x1b\xa8\x9d\x5c\xb5\xd0\xcdEqt\x93\x80\xef\xa0o\ -\xa0N.\x0e\xba\xd61\x10p\x90\x0a\xbf\x0cm\x17\xb3\ -\xb8\xb8H\x15u\x8a\xa0`\x1c\xe2\ -\x06\x15\x9c`$\xa5t\x05\xc5\x1c\x90\x11\xccD^\xc6\ -%\xfe\xbf\x1e\x96r\x80\x86P\xc5'\x1c\xe3\x0b4\x1a\ -\x8d:\x96\xf3\x80\xae\x03\x92\xd0\x88\x05\x8b8(\x0c\xd8\ -\xa3\x02\xbec\x12-L\x04T\x00k\xfd*\xaa\xa0\x1e\ -y\x1b\xfb]\xe0RJmz7{\x12\x9b\x91\x0f\xf5\ -\xf0\xb4c\xe9\x07\x1aG\x0d\x19\xf6\xfa\xc0\xde\xa2\xdb\xd5\ -fq\x869/\x8d-\xe1a\x10\xd02\x8eB\x7f\xc0\ -\x1a\xa6p\x8b\x0d\x0c\xe3g\x9c\xef\xe8\x98\x9d\xce(\xe2\ -\x17\x96B?\x06d=*\xdb\xc5\xbf\xd0\xeb\x98\xeeU\ -Q!\xcb\xb2\xc3\xc8\x7fx\x9f\x93Y\x5c\xe07F\xf1\ -5<\xb5\xa8\xf4/\x9a\xb17\x81\xfb\x12Vc#\x0b\ -\xc8\x06\xb6\xb1\x82C\xfc\xc1|\x17O\x13\x0b8E9\ -\xcf_\xeb\x16\xafC\xa9\xe8}\x1e\xb60\x86\xcf\xa1\xbf\ -\x85\xae\x0e\xe09\xef|\xfe\x16\xee\xf0\x14\xfa)t\xab\ -\x9f'\xa5t\x07\xcf)mR\xad\xb7y\x8e\x81\x00\x00\ -\x00\x00IEND\xaeB`\x82\ -\x00\x00\x02,\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x11\x00\x00\x00\x10\x08\x06\x00\x00\x00\xf01\x94_\ -\x00\x00\x01\xf3IDAT8\x8de\xd3K\x88\x8fa\ -\x14\x06\xf0\xdf\x7f\xfc\x95\xb0@\x22\x9a\x92{\xe4\x9aS\ -\x9a\x85\xb2\x125R\xee\xa5L)\x16\xa6\x90\x8d\xb2D\ -\x12Rl$\xc9(I.Qr\xbf\xaf\xa4\x8e\x14\xd1\ -\xe4R\xc8\x06\xc9%\xb7$,\xbeW}\x8dSo_\ -o\xe7;\xcf\xfb<\xe79\xa7\xa1Gd\xe6h\xac\xc1\ -\x1c\x8c\xc1\x1f\xf4\xc2C\x9c\xc6\xc1\x88\xf8X\xafi\xa9\ -\x15\xf7\xce\xcc\x9d\xb8\x83N\xbc\xc5R\xdcB_\x1c\xc5\ -(<\xcd\xcc5u\x90F\x01\xe8\x8bs\xf8\x8c\x09\x18\ -_\xf2kq\x11\x0b1\xb5\xb0\x9a\x82\xa18\x1b\x11\x9d\ -u&\xc70\x02W\xf1\x18\xaf\xb0>\x22\xf6G\xc4\x0b\ -\xfc\xc4Jt`:V\xa0-3;\xa1\x91\x99m\xb8\ -\x81O\x18\x19\x11\xdf3s\x11N\xe15\x9e\xe1:\x96\ -a\x12\xeeEDd\xe6\xf4\x22\xbd\xb5\x05\xdb\xd1\x07;\ -\x22\xe2{a\xb6\xa4|[1\x1bG#br\x91z\ -937`0\xbebs#3_c\x0b\xc6\xe1\x01\ -\xba\x0b\xb3~\x05\xa8;\x22&\xd4\x0c8\x8b\x05\xe5z\ -\x18\x93\x9a\x18\x80\x13\xf8P\x12\xcf0\x11\xf3\xcay\x92\ -\x99\xcd\x88\xf8\xe5\xff8\x8e\xad\xcdri\xd6\x12\x8f\x22\ -\xe2\x15\x0e\xe0@fvcca\xfc\x02\x17\xf0\xa3<\ -\xf4\x05?Z\xf0\x06]\xd8\x8d\x9b\xb8_\xa3>Ye\ -w/\x95{\xad\xd8\x13\x11\xcb\xb1\x17\x97\xf0\xb1Y\xa4\ -tFD{)\xec\xca\xcc{8\x89\x81=\xe8o\xab\ -\xc9Z\xa22\xe4H#3\x87\xe0)fFDwf\ -v\xa9\xe6\x01\x16\xe16\xc6b\xbe\xaa\xd9\x0f\xf0\x5c5\ -\x9c\xdf0\xbc%\x22\xdeb\x03\xceg\xe6*\xf4\xae\xbd\ -\x9c\x11\xf1^5|\xab\xb1\x1e\x87\xd0^\xfa\xd2\x1e\x11\ -\xbf\x1b5\xfd\xeb\xb0\x09g\xb0\x0b\x8b1\xab\xa4\xaf\x14\ -\x80q\xb8[\xfa\xd3\x11\x11W\xa8-`D\xec+\xf4\ -g\xa8\xf6%0\x0c\xfd\x8b\x0b\xd7\xf0\xae\xb0j\xfb\x07\ -@Y\xc0\x9e\x91\x99\xd30W\xb5\xb5\x83J\xf1C\x9c\ -\x8f\x88\x97=\xff\xff\x0b\x84C\xb2\xa8\xaa\xc4\xf2\x0e\x00\ -\x00\x00\x00IEND\xaeB`\x82\ -\x00\x00\x00\xee\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x0a\x00\x00\x00\x0d\x08\x06\x00\x00\x00\x907\xff\x05\ -\x00\x00\x00\xb5IDAT(\x91}\xd0\xa1\x8aBQ\ -\x14\x85\xe1O\xb9\xcdd\x9b\xeek\x08\xbe\xc7X\x0c:\ -\x08\xfa V\x1f@\xb1h1\xcc4\xc1l\xbc0\xc1\ -7\x10\x83ED\xc3\x14\x83\x96s`s\xb9\xcc\x82\x13\ -\xf6f\xb1\xfe\xb5O\xa3,\xcbO\xac\xfd\xafY\x11\x86\ -\x01\xfe\xc2\xdc\xc0\x1c\x1f8F\xe3\x0f\xeea\x9e&\xd3\ -\x0e\x9b&N\xd8\xe2\x19L\x1d\xccp\xc3\x17\x148\xa4\ -\x17\x91\x0b\xb4R\xea\x19\x9a5\xc5'\xe8%\xe4*/\ -\xab\xc6\x8c\xbcgdV<&\x22\x87\x19Y\x97\x98\x91\ -{,\xab}rbF>0\xc2+x\xc6\xb8\x145\ -\xc8S%\xac/}\xf88!\x0f\xf8F\xbb\x8eZ\xa0\ -\x9b\x16]\x5c\xab\xdd\x92~\xdf\xc4\xcd&:\xc3\xef\xf7\ -E\x00\x00\x00\x00IEND\xaeB`\x82\ -\x00\x00\x015\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x0f\x00\x00\x00\x0f\x08\x06\x00\x00\x00;\xd6\x95J\ -\x00\x00\x00\xfcIDAT(\x91\x95\xd0\xcf*D\x01\ -\x14\xc7\xf1\xcf\xcc\xcaB<\x06YX\x9d\xe6\x09\x94\x12\ -SJ\x9a\x97\xb0'\x8bY\xc8+XY\x121\xfe\x16\ -\x1b;ew\x1e@\xd9YX\xb0A\xd9\x10c\xe1\xca\ -\xedv\xa7\xc6os:\xe7\xf4\xfd\xfdN\xa7\x91\x99\xab\ -\xf8\xc0aD\xdc\xfb\x87\x1a\x99\xd9\xc1\x1e\xfa\xb8\xc1\x01\ -\x8e\x22\xe2a\x18x\x14O\x18)\xcd\xfb\xb8\xc6>\x8e\ -#\xe2\xb1\x16\x86\xcc\x06Z\xa5\xb1W#\xc4HW\x92\xccZ\xcf5\x97\ -i|8\xb0\x14h\x0e\xcc\x06^\x06\xb6\x03#\xf0~\ -\xfdU\xf5@aq\xa2\x8d\xf7\xfe\x00p\x13\xf0\xb8\xb3\ -\xe6\x9bx(\x80M\xc0 `\x82\xb3f\xd1U\xf1\x80\ -\xf7\xfe-\xa0-0/e\x1c\xc0Y\x03\x88\x22\xe0_\ -`Faq\x22+}M:@\xfc\xca\xf1\xc0?\xc0\ -{\x99\xeb\xce&\x0f\x03K\x80N\xde\xfb\xe7\xb3\xd1\xd9\ -`\x08\xa4\xd2\x03\x08q\xed\x07\xb4\x8f\x06\x0f\x03'\x80\ -\xe1\xc02g\xcd\xd8K\xec\xed\x05T\x02\xbb\x81\xbd@\ -\x0f\xa0\x03p\x168\x00\xac\x13B\xcc+\x8b\x89*\x00\ -\x0a\x8b'u\xf6\xbe\xee\x1d\xe0]g\xcda\xa9t\x0d\ -!\xc1\xceE\xa37\x12J-E\xe7\x81\xcd\xc0\xa7 \ -\x968\x9bD*\xdd\x1f(\x06F\xc6C\xa7>\xae6\ -\xeah\x09\xb4\x89\xbc\xfd\xc0@g\xcd\xef1\x04~p\ -\xfc\xe2\x1f\xa5\xd2}\x9d5-\x80\x02\xef}\x0bg\xcd\ -\xad\xce\x9a\x9b\xbd\xf7\xad\x81\x83@\x0d\xb0\x03x\x04X\ -\x0c\xbeZ*\xbd\x03\xd8\x0a\xbc\x12\xc3\xba?\x1a\x1a\xeb\ -\xaci\xee\xac\xe9\xec\xaci\x8b\x10]\x81R\xe0.`\ -Qz\x0e\x5c\x1b\xc7N\xc0\xf7R\xe9!\xce\x9a/W\ -\x94.\xb8\x18+!N\x01]\x81]\xce\x9a<`*\ -\xe0\x09\xd5\x90\x1b\xc5*\x81{\x81\xe9q\xde\xa5^\x8e\ -\x94$\x8f8k\x14\xf0\x0bP \x95n0\x09o\x00\ -\xd6I\xa5'\xd4K\x16!\xee\x8f\x07>-\x95\xdeD\ -\xa8\x7f\x80\x95\xc0\x9b\xc01\xa07\xb0\x0f\x18\x10\xd7z\ -]\x22\xf7\x0e\x03\xcd\x80\x8e\x97\xaa\x82k\x80\x85R\xe9\ -\x0fR\x0c\xef\xfd\x9d\xf1\xef@B\xad\x7f\x0d\xf4u\xd6\ -\x8cv\xd6\xcc\x11B\xdc\x02L\x8b\x8au\x94\xed\x9e\xa9\ -8\x96g?\xa0\xcaYs\xbc\xb12|C*\xbd\x22\ -\x96_N\xe4\xfd\x09\x14:k\x06;k*S\x82e\ -%I\x9c5\xb3@\xf4\x04R\xdd\xb0\x8fT\xba^\xb5\ -x\xef_\x8fa[\x09\x17\xaa \xf1\x82\xf7\xfe\x93\xff\ -9\xc8fg\xcd\x00\xa9\xf4d`\xb7\xb3\xe6B\xbb-\ -,Nt\x00r\xcaJ\x92\xbb\xd37H\xa5\xf7\x00w\ -\xc7\xe9\x82\xe8\x95n\xc0\xcf\xd1K=\x9c5\x87\xb2m\ -D\x0fK\xa5\xf79k\xe6\x0a!\xd6\xa7\x19\x19\xe3\xbd\ -?\xea\xbd\xdf%\x95\xde\x94\xd1\xfd\xaa\xe2\xf8\x1b0\x11\ -\xf8\x22\xfeZ\x01S\x9c5\x87R\xb1\xce\x96\xbaK\xa5\ -\x97\x96\xd5G\xba\xf7\xe3\xd7\x00\x0c\xf2\x9eQikg\ -S|\xe0;`\x18\xa1Z\xca\x9c5\x1f\xa6\x84\x9a\x8a\ -\x05\xe73\xe6u\x8d\xcc!4\xb4\x96\x97\x92i\xca\x01\ -v9k\xc6e\xf0^\x03\xce\xc4\xff\x1b\x84`u\xda\ -Z\xca\xe8\xb7\xc0\x83\xc0\x1a\x02d\x17I\xa5_m\xea\ -\x016:kr\xa5\xd2oK\xa5\x87\xa5\x98\xce\x9a5\ -@\x8e\x10\xe26g\xcd\x90\x8c\xf0\xb4\x8fcW`\xbe\ -\xb3f\x04\xf0,P\x0d\xcc\x91Jw\x86\xd8\x01{\xe5\ -\xe5\xf7!\x80LCT\x0a\x8c\xcc\xcd\xcb\xd7\x84\x98\x0f\ -\xcd\xcd\xcb?\xb1\xb3\xa2|;\xc0\xce\x8a\xf2\x9a\x9d?\ -m=\x99\x12\x96Jw\xcb\xcd\xcb\xff\x8cP\xebg\x80\ -\x22g\xcd\xbc([\x9d\x9b\x97\x7f\x1ax\x06h\xb6\xb3\ -\xa2|Cc\x1e\x98\xe9\xacQ\x01\xeb9\x1ay\xad\x81\ -\xc5R\xe9-R\xe9\x87.\x1aN \x95\x9eE@\xc1\ -\xc7\x22\xbb\xc2Y\xb32]\xa1\x10b\x01p\x12\x18\x0d\ -\x1738\x93j\x81\xf1\xce\x9a\xd2\xb4\x8d\xfb\xbd\xf7\x00\ -\x1b\x09\x19^\x00l\x91J\xaf\x03~\x00?\x09hG\ -hT\x06\x98L\xe8\xf9\xf5\xa8\xac$\x89Tz\x1b0\ -X*\xdd\xa6!\x0fT\x03O\xa6\x1b\x07\xf0\xdeW\x10\ -2\xb8\xa3\xb3f(0\x85\x00FO\x033\xa2\xf1J\ -\xe0>B\xb2A@\xcd\x86\xe8v\x02\xaa\xfe\x9d\xf2@\ -m\x1c\x8f\x00O8kvK\xa5G\x01\xab\xa2\xfb!\ - \xe5!\xe0\x1e\xa9\xf4^\xa0g\xe4W\x11\xe0\xb7?\ -\x01\x8c~%\xe0?@\x95T\x9a\x94\x0e\xa9tw`\ -&\xa1#\xaer\xd6\xc4V\xfc\xe2\xa4\x1c_W7\x15\ -\x98\xed\xac9&\x95>\x97\x16\x9ej\xe0zB=\xa7\ -\xa8\x06\xf8\x0aX*\x84X^V\x92D\x16'r\xf1\ -\xbe\x18\x18E\xc8\xfc\xf4\xdb\xd6\xe9\xb8\xff\xba8\xdf\x85\ -\x10\x8f\xba\x92\xe4\x89\x86\xafd\xc5\x89\x07\xf0\xfe%B\ -&\xb7#\x5c4\x0f\x02\x7f\x01c\x80\xe5\xce\x9a\xa2\x06\ -\xf7*\xdd\x9b\xd0\xef+\xe3\xd83\xea\xa8\x8d\xdeY+\ -\x84XT\xefJ\x96-\x8d\x1e7\x11!\xc4\x1f\x044\ -\xeb\xe2\xac\xa9\xca\x94\x91J/\x04&\x10\x10\xd35\xa6\ -\xb3I\xad8\xde\x90\x16\x12\xba\xdc\xf4\xccu\xa9\xf4\x1d\ -\x80\x02\x8e\x08!\x1a5\xde\xe4\x03\x00\x08!\xe6\x02\xc7\ -\x81\x84T\xfa\xa94\xe3\x00\xcb\x09q\x9eV\x96\xe5\xf3\ -\xec\xb2\xde\x86R\xe9\x02`-\xa1,?\x22@\xeex\ -\xc2}\xf0sg\xcd\xf0lu]\xd6\xdb0^H\x9e\ -\x03N\x01\x09`~4\xbeL\x08\x91\xb5\xf1\xcb\xf6@\ -\x9a' `H\xeay\xbe\xa7\xa9:\xfe\x03\x5c\xaa\xea\ -&\xfd\x17M\xd2\x00\x00\x00%tEXtdat\ -e:create\x002016-01\ --08T15:18:18+00:\ -00\x01E\x99\xf0\x00\x00\x00%tEXtda\ -te:modify\x002016-0\ -1-08T15:18:18+00\ -:00p\x18!L\x00\x00\x00\x00IEND\xae\ -B`\x82\ -\x00\x00\x00\xce\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x0c\x00\x00\x00\x0c\x08\x06\x00\x00\x00Vu\x5c\xe7\ -\x00\x00\x00\x95IDAT(\x91\x9d\xd0\xb1\x09\x02Q\ -\x10E\xd1\xb3\x22\x08\xb6a,\x98\xd9\x80\x81\xa0e\x88\ -\x91%\x18Z\x82\x89b\x19\x0a\x826 \xfc`\xc1\xd8\ -\xd0\x16\x04#\x0d\xfe.\xac\xe8\xdf\x05_x\x87\xcb\xcc\ -\x9b,\x84\xf0\xc2\x01S1{L$\xd2\xc6\x19y\x85\ -\xe5\xe8\xa4\x84,\x84\x90\x9a%7lp\xc5\xba`\x0b\ -\xf4\xeb\x84\xb9\xd8\xa1\x14\xc6\x1a:\xf4\xf0\xa8\xb0\x19\xba\ -)\xa1\xd5|\xf5\xf7\x86\x9b\xcf\xb7\xee\x9aN\xda\x8a\xa5\ -\xcb\x1cqO\x09\x7f\xbd\xf5\x84\x0b\x96\x05[aX'\ -\x8c\xf0\xac\xb0A\xc1~\xe6\x0d\xc9\xd6\x1dQ\xcd\xba\xaa\ -\xa1\x00\x00\x00\x00IEND\xaeB`\x82\ -\x00\x00\x01}\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xffa\ -\x00\x00\x01DIDAT8\x8d\x95\xd2\xb1KVQ\ -\x14\x00\xf0\xdf\xf7Qa\xe2\x12N\x91\x93\x85MN\x9d\ -\xa1E\x10\x84\x86j\xd4M\x87\x96\xc0\xdd]\xb7hh\ -\x8d \xa1!A\x1cZ\x85\xa6j*\xf2P\xe0\x90\xe2\ -\x1f\x10\x88A\x86aa|\xe2\xf0\xae\xa1\xaf\x0b\xe6\x99\ -\xde;\xf7\x9c\xdf=\x5cNG\x89\xcc\xbc\x829Lb\ -\x18\x7f\x90X\xc4RD\x1c\xaaD\xa74\x8f\xe25\xae\ -\x96\xfc/\xf40P\xfeW1\x15\x11\xfbm\xa0[n\ -^=\xd1\x0c\x971\x8bql\xe2.\x9e\xd5&\xe8\x96\ -\xb1\x87*g\xdf#\xe2\x1d\xc6\xf0\x153\x99y\xab\x06\ -L\xd5d\xecBD|\xc3\xa3\x92\xfb\xa7\xf6\x82\xe6\xc1\ -~\xa3\xaf\x0dd\xe6\x00\x06\xb1Qr\xd7k@\x0f{\ -xP\x90\x9f\xd8\xc6+\xdcl\xd5\xf7j\xc0:\x02[\ -\x11\xf1\xe9\xf8 3\xdb\x13\xc1\xe7v\xa2\x8b\x17\xe5\xfb\ -if\xf6W\x9ahv\xe2\x00/k\x13,b\x06\xb7\ -\xb1\x96\x99\xf3x\x8f\x8b\xa5\xe6\x00\x97\xf0\x04;m\xe0\ -x\x91\x06\xb1\x82\x89\xca\xed=,c\x1a\x1fq'\x22\ -~\x9c\x02\x0a\xd2\xc1=\xcd*\x8fh\xb61\xf1\x5c\xf3\ -\xa8_4\xfbr\x0a\xf9\x0b\x9c\x15\x99y\x03oq\x0d\ -\x1f0\x11\x11\xfb\xff\x0dT\x907\xb8\x7f.\xa0\x82<\ ->7p\x02Y\xc0\xc3#S\xefd\xae\x0f\x1eB$\ -\x00\x00\x00\x00IEND\xaeB`\x82\ -\x00\x00\x01x\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x10\x00\x00\x00\x12\x08\x06\x00\x00\x00R;^j\ -\x00\x00\x01?IDAT8\x8d\x9d\xd3=K\x5cA\ -\x14\xc6\xf1\xdf\xae\x06\x04\x8bt\xdb\xa8\x88q#\xa2\xd8\ -X\xa4\xb2\x15\x041\xd8\x05\xa2\x95\xe5\xd6!\xd8,n\ -!~\x06+IJ\xf3\x09\x94\x10P\x904n\x11H\ -0$\xf8\x02.\x0b\x0a\x16Vb\xe1\x8a\x8538\x19\ -]\xc2\xfa\xc0\xe5\x9e\xf3\x1c\xce\x7f\xce\x9d\x99[\xa8\xd7\ -\xeb\x12\xad\xa1\x8a\x96\x7fu\x89\x97\x99w\x8a\xc1bf\ -\x8e\xa3O\x07\xca\x01\xaf\xc2\xf3,@\x01\xe5N\x01\xdd\ -I\xdc\x8f\x9e6\x80\x1d\xf4\x86E&\xf0\x13\xe7\xf9\x04\ -\xb1q\xe8\x09\xc0<\xa6\xf1\x19%|\xc2B\x0ex\x9d\ -\x81r\xbd\xc0J\x88\xabq\xfa\x22\xc6BS\x0a\x18\xc5\ -\x1c\xba\x12\xc0\x12\x86C<\x82\xf7\x110\x80#|\x0c\ -\xc5\x12~\xe3\x9d\x87\xfb\xd0\x13VMUEw\x11\xdb\ -\xf8\x9e\x15oPK\xf2\x8a\xc7\xf7\xa3\x8c\xc5\xb8\x07\xb5\ -\xac\xb8\x81\xc3$ob\x06?B\xbe\x857hD\xc0\ -W\xec\x85\xf8\x1a\xab\x19p3Lz\x10\xf2_\xd8\xc7\ -\xb7\xf4\x14\xe2\x0e\xaf\xa3\xe1i\x1d\x87\xf7Q4\xe2E\ -Z\xc6$\xce\xdc\x9f\xc2\x97\xe0Wp\x91\x00N\xda\x01\ -\xa60\x1b\xe2\xb7I\xc3\x876\x13\xfc\x8dF\xfe3\xfd\ -O\xc7\xb8\x92|b\xa7\x80&\xfe\xe0\xf6\xb9\x80\x16v\ -S\xe3\x0e3\xc49\xa5\x12)N:\x00\x00\x00\x00I\ -END\xaeB`\x82\ -\x00\x00\x01\x1b\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x0e\x00\x00\x00\x0d\x08\x06\x00\x00\x00\x99\xdc_\x7f\ -\x00\x00\x00\xe2IDAT(\x91\x9d\xd1/K\x83Q\ -\x14\x06\xf0\xdf\xe6\x8aE\x98_`&\x83U\x10\xbf\x82\ -\x98\x9d0\x16\x945\xbb \xd6\x05\xcd.\x88}j\xb1\ -\x0cV4\x1b_\x164\xac\xb8b\x96\x81\xc5 2\x16\ -v\x06\x97\xd7wC|\xe0p\xcfs\xce\xf3\xdcs\xff\ -\x94\xb2,\xbb\xc0\x99\xdf8\xc1u\xe4}\xec\xa7\xcd2\ -\xeePG7j\xc3\xe0O\x89\xee\x12\xc7\xf8\xc2\x18\xcd\ -\x0a^#z\xd8\xc4\x0e\xaa\x18%\xc6g\x1ca\x15\x0d\ -\xf4\xcaI\xf3\x1b\x07\xf8\xc0\x15\xb6\x93^\x1d-tb\ -\x80\xd4\x08\xefh\xa2\x82\x07\xacc\x037\x18\xe04\xbd\ -c\x1e\x8fh\x87\xa1\x8b\xdb\xd0\x1d\xc6\xa9\x88\x9d\x8b\xd0\ -\xc6.\xf6\x827\xf0\x96\x0a\x8a&\xc2\x04\xe7\x91\x0fq\ -\x9f\x17,2\xc2On\xfd\xb3q)\xfem,z\x9c\ -\x15\xacE\xccy\xd5\xec\xde\x9f\xcb\x8c[x\xc9\xf1\xb1\ -\xd9\x1f\xd7\xe6\xc5)P\xcb+^\xfd\x05+R\x00\x00\ -\x00\x00IEND\xaeB`\x82\ -\x00\x00\x01\xcf\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xffa\ -\x00\x00\x01\x96IDAT8\x8dm\xd3M\x88\x8eQ\ -\x14\x07\xf0\xdf\xf3\xf4R\x83\x8d\x05\xc5\xbc\x14)\xcd\x8a\ -\x95(R\x13\xa5\xac\xcc\xc6GMJY\x8cX(K\ -\x99\x8c\x05\x9a\xb1b\xc3b\xc6\x82R2\xd9\xc8(_\ -eA\x16b\xa1\xde\x84\x89Y\xccBB\xa4\x19\x1f\xc3\ -\xe2\x9e\x9b\xdb\x93S\xb7\xdb9\xf7\x9c\x7f\xff\xf3?\xe7\ -V\x9dN\xc7\x7fl\x1b\xfa\xb1\x05m\xfc\xc6\x1bL`\ -\x0c/sb\xd5\x00X\x82\xab\xd8^\xc4>\xa3\x85E\ -\xe1\xcf\xe1\x22\x8eb\xb6.\x12\xdbxZ\x14\x7f\xc3q\ -,\xc7\x0a\x9c\xc3\x0f\xd4\x18\xc0=,\xc8\x0cj<\xc6\ -\x06\xcc\xe0\x12\xce`\xba\xd1\xda\x1a\x0ca\x0f*\x8ce\ -\x80\xfd\xb8\x8c)\xf4\xe2uQ\xd4\x1d\xa0\x1f\x8b\xd8F\ -\x5c\xc1\xea\xdc\xc2\xc1\xb8\x87\x1b\xc5\x83x\x8bI\x9c\xc4\ -\xc2\x88?\xc1mT5\xba\xb0)\x1e\xde5(\x0fc\ -/n\xe20\x9ec}\xa1\x91VP\xccLv\xe2\x96\ -46\xf8\x8e\xf18-i\xac\xfb\xd0\x87u\x19\xa0\x9c\ -\xc44\x0ea-\x1e\xe2\x0e\xbe\xc6\xdb/<\x88C\xd2\ -L\x8d\xf7\x98\x8d\xe0+\x9c\xc7(\xce\xe2\x83\xb4<\x03\ -X\xdah\xefE\x06\x98\xc1\xfd\x08\xce\x8b\xfb\x19zp\ -,\xee\xc1L\xb9\xb0\x1e\xfem\xe2\x0eI\xd5I\x1c\x08\ -\xfa\xa5U\xf8S\xf8}\xb8\x86\xb9\xdc\xff\x84$\xd4\xaa\ -\xe8q\x5cZ\x9al\xb9xs\x80\xdf\x08\xb6\xa7K\x01\ -\xfb\xa5m\x84]\xd2\x87\x19\xc1b\xac\x8c\xa2G\xd8\x1a\ -9\xa3\x18j~\xa6.\x9c\xc2\x11\xcc\x8f\xd8\xcfh\xa1\ -\x15\xfe'\x9c\xc0\x85R\x83\xa6\xb5\xb1[\x9a\xfb2i\ -\x84S\xb8\x8b\xeb\xf8\x92\x13\xff\x02w\x5ckPMg\ -\xdc\xa5\x00\x00\x00\x00IEND\xaeB`\x82\ -\x00\x00\x01\x86\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x0f\x00\x00\x00\x0e\x08\x06\x00\x00\x00\xf0\x8aF\xef\ -\x00\x00\x01MIDAT(\x91\x85\xd21K\xd6Q\ -\x14\x06\xf0\x9fW\x0a)jhh\xc8h\x91\x1c5\xe9\ -PRIC\x82\x0e\xd9 !\x82\xd1j\x1f \xa8o\ -\xd0\x16\xb4\xb4\xd4\xe6`\xb4DB\xadA\xe0\x10\x1dT\ -hlh\x11A\x8c\x8ah\x10\xa9lx\xef?^\xfe\ -\xf0\xf2\x9e\xe9\x9e\xe79\xcf}\xce9\x9c\x01\xad\xc8\xcc\ -\x9bX\xc6\x15\x9c\xc2O|\xc4s\xbc\x8c\x88\xbfM\xed\ -@\x97\xe8\x18V0\x8f/X\xc3W\x9c\xc6\x0cF\xf1\ -\x1e\xb7#b\xaf-^\xc3\x1c\x1e\xe0qD\xfc\xee\xe2\ -\x0a\xee\xe2)>a*\x22\x0e\x1ar!3\x0f3\xf3\ -~{\x8c\xd6H\xb3\xb5\xee\xe1\x7f\xe7\xcc\x5c\xc7qL\ -D\xc4a\x9f\x0f^\xe0\x1a\xce\x95\xcc<\x89I\xac\xf6\ -\x13\xd6X\xc50F\x0b.\xa3`;3\x8f\xf4q=\ -\x8a]\xfc\xc1\xa5\x82G\x95\x1b\xc7\xab>\xaeou\x96\ -:\x88{\x05\x17*1\x86\xc1\xcc\x1c\xe9\xe1:\x82)\ -|\xab\xd0\xc5\x82\x1f5\xb9\x8e7X\xea\xe1z\x07\xef\ -p\xb5\x01\x0a>\xd7\xf7\x10~a\xb1\x87xI\xe7p\ -\xa6k\xbeY\xf0\xba\xab\xe0\x06\xf62s\xac\xd5\xf2$\ -\xcec\x1f'*\xbcR\xf0\x04\x9b\x15\x98\xc7\x87\xae\xb9\ -\x9a\xd8\xc7\x16n\xd5|\x03\xcf\x9a#9\xab\xb3\xe93\ -X\x88\x88\xf5v\xcf\x999\xa1\xb3\xed\xef\x98\x8e\x88\x9d\ -\x7fI\x1dq\x82#,l\xf1\x00\x00\x00\x00IEN\ -D\xaeB`\x82\ -\x00\x00\x01\xc6\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x11\x00\x00\x00\x10\x08\x06\x00\x00\x00\xf01\x94_\ -\x00\x00\x01\x8dIDAT8\x8d\x9d\xd3M\x88\xcda\ -\x14\x06\xf0\xdf\x9d\x99\xcd\xd8h\xc6,$ERS\xcc\ -4\xa5\x135\xd9\xcclg(\x12\x1b\x0b)\x16>v\ -\x16\xa2,(\xcdF\xcab\xa6\x1b[\x85\x22+K\xf9\ -X\xb9\x0ee!#D\x16\xa8!\x09\xc9\xc2\xc7\xe2\xff\ -\xcet\xfb\xd7\xcc\x8dS\xef\xe6=\xe7<\xcfs\xbe\x1a\ -\xfe\xd32\xb3\x89\xfd8\xde\xe8\x108\x82\xb5X\x85\xd5\ -\xe8F\x17\xd6c\x1bz\xd0\xea\xe9@x\x06O1\x83\ -\xe5\xd8\x83e\xb8\x82\xbeBp\xa2{\x09\x15\x1bp\x16\ -\xc3\xe8G/\x9ax\x84\x83\xd8\x87\x81\x88hv-\x02\ -\xb0\x157\xf0\x10o\xd1\x8a\x88i\x0c\xe04\x0eG\xc4\ -\x17\xfcVj\x9aO\x5c\x89\xbdE\xe2\x1b\xac@\x94w\ -)3[8R\x00~df?>B#3\x03\xc7\ -\xd0\xc0\xbb\xc26\x8a\x8b\x111U\x08\xee\xa8\x9ay\x0b\ -\xcf\xf1\x12?\xf1=\x22\xee\xf7\x14\xc6\xed\xc51\x8b\xc7\ -\xb8\x80'm\x15\xee\xc4H\x01\x1a\xc4I|\xc2\x98\xc2\ -.3\xc7q\x0d\xbb#\xe2\xf6b\xcd.\xb1S\x98\xc0\ -xD\xccQ\xcd\x5cI\xdc\x81\xcb\x999\xf9/\x00\x0b\ -J\xda\x82\xb6\xe0\xaejt\xdfj\xbeI\x9c\xc7h;\ -\xc0\x82\x926{\x8d\xafu\x80b\xef\x8bo\xae\xee\xa8\ -o\xec\x90jCef/\x8e\xe2\x05n\xe2\x19\x063\ -\xb3;\x22~-\xa5d\x08\xb3\x99y\x08\xaf\xb0\x19\xa7\ -\xf0@5\xf6\x0fXWWR\x07\x19\xc6\x01\xd5qM\ -D\xc4.l\xc29Lc\x0d6v*\xe73\xc6\x22\ -\xe2\xde\xfcGD\xfc\xc1\xd5\xcc\xbc\xae\xba\x97\xbe:\xc8\ -_\xc6l\x83y\x0c\xda\xbaW\x00\x00\x00\x00IEN\ -D\xaeB`\x82\ -\x00\x00\x01\x89\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x15\x00\x00\x00\x14\x08\x06\x00\x00\x00bKv3\ -\x00\x00\x01PIDAT8\x8d\xad\xd4\xb1K[Q\ -\x14\xc7\xf1O$\xb4\xee\x12j\xabq\xaaYJ\x05\xc9\ -_P\x07\x17\x07\x17\xc1BE:T\x90\xae\x9d\x0a\xed\ -\xa0t\x13\x97v\xc8\xd8\xc5\xc1E7\xdduN\x16\xa5\ -\x94\xd6M#m\x05'\x95XQ\xe2\x90\x9b\x12\x02\xef\ -\xbd\x9b\x92\x1f\x5c.<\xce\xf9\xf2;\xf7\xc7y\xb9f\ -\xb3)I\xb5Z\x0d\x9e\xe3\x00oQ)\x97\xcb\x89\xf5\ -m\x0ddV\xfc\x87b\xa1?P\x8d\x85\xe6\x92\xc6\x0f\ -\xa3\xc3C\xdc\xe16\x16\x1a\xe3\xf4o\x00\xe6\xf1\x1a\xab\ -\xfd\x80\xe6\xb1\x88\xef\xf8\x8a\xc7\x18\xc7`RC\xd6\xf8\ -S\xa8\xa0\x94\xd0\x7f\x86S\xd4q\x1c\xee\xbd|\x86\xcb\ -}\xac\xe1#\xc6\xc2\xb7?\xf8\xd6\x01\xfb\x85\x93p\xd7\ -\xf1;W\xadF\x85\xfa\x00\xcbx\x8f\x1d\xbcI+\x8e\ -y\xd3\x12n\xf0\x19O\xb1\x9d\xd5\x10\x03\xdd\xc2\x86V\ -8W\xd8\xcdj\xe8|\xd3A\x8c\xe0\x09F;\xee!\ -\xbc\xc2\xbcV\xfa\x9f\xb4B\x91\xb4\xb2y\xbc\xc44&\ -\x03\xb4\x90b`\x093x\x81\x9fiN7\xc3\xe9t\ -\x5c\x0c.\x8bx\x87\x09\x9cc\x1d_p\x99\x04lC\ -\xbbu\x8d\xa3p`\x01\x1f\xb4\x82\xbaH\x83\xa5A\xbb\ -5\x8bF\x0c\xac\xad\x98\xf4\x1bx\x86\xb9Xh\xe2\x9a\ -\xf2oU\x0b8\xc4\x8a>\xfe\xa4\x87\xf1(\xcab\x0f\ -\xd0\x9eu\x0f\xb5UQ\xc4\x18\x14\xeam\x00\x00\x00\x00\ -IEND\xaeB`\x82\ -\x00\x00\x01J\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x0d\x00\x00\x00\x0d\x08\x06\x00\x00\x00r\xeb\xe4|\ -\x00\x00\x01\x11IDAT(\x91\x85\xd2\xbf+\xc4q\ -\x1c\xc7\xf1\xc7\x9d\x93\xe4\xa2\xcb \x8b\xb2(\x7f\x00\x03\ -e2\xa0\x94\xd1 \xeab\xb1 \x0b2#\x93,\x16\ -\x89\x0c&E\xba\xc2\xa0\x84\x81\xbe\xc9$\xeb1\xa9\xeb\ -&\x8b\x1f\xc9p\x9f\xab\xef\xe9\xe2=\xbe?\xaf\xe7\xe7\ -\xf5\xfa|z%\xa2(\xca\xa3M\xe5\xaca\x11\x0bX\ -\xfduv\x9d\xc24\xd2\xd8@\x0b\xe6p\x11\x04Gx\ -\xc5\x16^\xb0\x84B\x0a\xb9 x\xc3\x09\x06\xb0\x19v\ -O\x98G\x0ac\xb8\x85d\xcc6\x87\xed\x00M\x85\xdd\ -0&\xb1R\x06 \x11EQ\xcc\xe2\x1c\xcb\xe8\xc0z\x5c\x14\xff\ -\xbdN\xdc\xe3,\xc4\x83\x1a\x5c\xa2\x07C8-;e\ -\xd0\x8c=\xbc+\xd5\xa7.@)\xa5\x86|`G\xa9\ -n\x99$\x8a(\xa0\x0bMxD6@Y\xdc\x85K\ -Z\x91G\xf1\x07i\x04=o\x03\x18\x5c\xb7\x00\x00\x00\ -\x00IEND\xaeB`\x82\ -\x00\x00\x02\x15\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x13\x00\x00\x00\x14\x08\x06\x00\x00\x00oU\x06t\ -\x00\x00\x01\xdcIDAT8\x8d\x9d\xd4]h\xcfQ\ -\x1c\xc7\xf1\xd7\x7ff)\xe5\xa15\xca\x05\x174\xb5\xd4\ -\x94\x8b\xb1%\xb1\xac<\xa4(S\xd4.\xdcz\xb8q\ -\xe7F\x89\xc2\x8dZ+)\x96I\xc9\xe4!\x91\x9a\x84\ -\x95q\xf1\xbf\xf0\xfc\x90;#\xa1\x11.H\xcd\x5c|\ -\xcf?\xbf\xfe\xfe\xff\xfd\xd6N\x9d\xce\xefw\x1e\xde\xe7\ -\x9c\xcf\xf7\xf3=\x85b\xb1h\x02\xa5\x06\xbbS]\x88\ -W8\x8a\xb3\xd9I\xb5\x13\x00MA/\xba\xd2\xff\x07\ -4\xa1\x0f\xd3q\x22\xbbc\x1e\xe8L\x02\xbdG+\xe6\ -a#\xc6p \xcb\xc8\x83m\xc5z\xbcD\x1b\x1e\xa4\ -\xfe\x1b\xf8\x84\xb9\x98Q\x9a<\xde5g\xe2\xb9\xd0\xe8\ -\x07F3c+1\x07\x1f\xf1}\xbc\x93M\xc3)\x8c\ -\xe0Ij{Q\x97\xc6\x97\xe2\x0a\x0a8\x84?\xd5N\ -6\x0bW\xb1\x0a_q_\xe8\xd4\x85~!\xfe\x00\xea\ -q\x1c=\xd9\xc5YX\x03n\xa1\x19/\xb0\x0d\xef\xd2\ -\xce\xab\xf1\x13w\x84F=\xd8W~\xa5\x12lv\xda\ -\xb1\x19\x0f\xb1\x01\x97\xb1\x1c\x17D\xe4v\xa4\xf9G\xb0\ -?\xf5\xfd\x07\xab\xc3\xcd\xa4\xc5\x10\xd6\x09Q\xcfc\x85\ -\x7f\xfe\xfa\x85\xbd2\xbe\xaa\x04\xdb\x8e\x16<\x126(\ -E\xe7\xa4\xd0\xaf\x15SqOD\xafj\xa9\xc1\xb2\xf4\ -\xdd\x8do\x99\xb1\xcd\xb8\x8bMx\x9c\x07*\xc1\x86\xd3\ -w{\xa6\x7f\x0f.b\xb10\xec\xeb\xfd7\x08\xdf\xb5\xd4\xa6\xe3w\x88\x1c\x5c\x92&\ -<\xc3.\x0cV8@\xbf\xc8\xcfF!\xc55\xe1\x82\ -\xa6B\xd9\x134?\xb5\xc3*\x84>\x95v\x5c\x12\xe9\ -\xf6[\xb8a\x04[\xca\xd3\xe9m\xaa\xd5@p[\x04\ -e,\x81F\xb1\x16\x83y\xafF\xa5\xd2\x88\xd3\x227\ -\x89g\xea\x1c\x16L\x06v\x1d\x8b\xc4\xd5:\xf1Y<\ -\x96\x03\x93\x81\x1d\xc6\x1b\xac\x11\xf6\xe9\x10\xd69\xf8\x17\ --\x83l\x7f\xf5\xb9\xae\x1b\x00\x00\x00\x00IEND\ -\xaeB`\x82\ -\x00\x00\x02\xff\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\ -\x00\x00\x00\x04gAMA\x00\x00\xb1\x8f\x0b\xfca\x05\ -\x00\x00\x00 cHRM\x00\x00z&\x00\x00\x80\x84\ -\x00\x00\xfa\x00\x00\x00\x80\xe8\x00\x00u0\x00\x00\xea`\ -\x00\x00:\x98\x00\x00\x17p\x9c\xbaQ<\x00\x00\x00\x06\ -bKGD\x00\xff\x00\xff\x00\xff\xa0\xbd\xa7\x93\x00\x00\ -\x00\x09pHYs\x00\x00\x0b\x12\x00\x00\x0b\x12\x01\xd2\ -\xdd~\xfc\x00\x00\x00\x07tIME\x07\xe0\x01\x08\x0f\ -\x12,c4\xebp\x00\x00\x01\xeeIDATX\xc3\ -\xed\x95\xbdk\x14A\x18\xc6\x7fo\x12D\x09\x09\x82 \ -h#H\x02\x16I\x99\xbf }\xdap\xdb\xc8\x92\xca\ -\xe2\x16\xff\x00\xc12U\x88\xec\x15!\xd5\x14\xe2\x1e)\ -\x02Q\xc4t6\x92\xc2\x90\xc6B,\xceBN\x11<\ -\x0c\xf9 \x09\x5c>nR\xdc\x9c\xbeYw7\x93\x8f\ -\xce}\x96\x81w\xe6}v\xe6\xd9g\xde\x99\x85\x12%\ -J\xfc\xef\x90\xbcD%\xac\xde\x03\x06]\xd7*\xfeA\ -\xdd\xd4~\xa6\xb8\x0f\x81\xfb\xc0\x100\x00\x1c\x01m`\ -\x17\xd8\xac\x9b\xda\xb7\xbcu\xfa\xf2\x95\xc9\xa2 \x0d\xa0\ -!\xc8W\xd7\x1a@3\x08\xa3\xf5 \x8c\x1e)\xeec\ -A>\x08\xf2\x0ex#\xc8\xaa \xef\x05\xd9\x00\xee\x04\ -a\xc4\x85\x05\x00\x87\xea\xeb;\xca\x85~`\x02\xf8\xa8\ -&>*\x98g\xb7h\x0b\x06\xce\xdd\xa4\xae\xedS\x89\ -\x89\xdf\x06at\x17X\x03F\x80a\xe0)\xf0\x22\xc5\ -\x9f\x06\xda\x89\x89_{\xcc\x9d\xef\x80uO/\x06H\ -L\xdc\x02\x9e\xdb?Y;\xa9\xb9\x8a\xe7\xb5x\xa1\x03\ -\xe2\xea\xd3b\x11D\x17\xeb'\xf9[\xbb\x0f4W\x8b\ -\xbd\xb2\x80\x02\xec\x03\xc7\xee\xdd\xe1,B\x10FO\x80\ -&\xb0e\xb1;\x82|NL|m\x02\x8e\x81\x13\xf7\ -\xee\xcd\x8c\xfcR\xaa?v)\x07\xb4\x95)[\xc5b\ -{\x9e\xf7g\xe4\xcf\xed{\x09H\xd5\x80N\xdd\x12\xe4\ -\x86\x8b\xdb\x9a\xeb\xf8\xd3\x82\x9c$&^\xf6\xb1\xb3\xcf\ -\x87\x94\xc2m\x15og\x11|\x17\xbf\x88\x80\x8e\x8a'\ -U\xfc\xe5\x12\x1fp\x06\xbe50^\x09\xab[\xc0(\ -\xf0\xccb-\xdd\x0b\xeaU\x9a\x0bP\x09\xabU\xa0\x05\ -\x1c\xb8\xb6\x0d\xfc\xaa\x9b\xda\x0fo\x01\xbd\xb3\xefj`\ -V\x0bs{\xbe\x9a\x98xEs]~)}/\xb8\ -\xfe\x18\xe0/\xc0\xa9n\xd1=r\x1a-\xe0eb\xe2\ -95\xb6\x07\xfc\xe6\xdf\x7fB\x07\xf8\x0e,\x90\xf3\xbf\ -(\x120\x935X7\xb5\xac\xe1y\xd7\xb2\x9c\x04 \ -\xef\x22*Q\xa2D\x89S\xad\x83\xa9\xe2\x81\x96I:\ -\x00\x00\x00%tEXtdate:cre\ -ate\x002016-01-08T1\ -5:18:44+00:00\x8e\x05\xfd\ -\xe0\x00\x00\x00%tEXtdate:mo\ -dify\x002016-01-08T\ -15:18:44+00:00\xffX\ -E\x5c\x00\x00\x00\x00IEND\xaeB`\x82\ -\x00\x00\x01\xeb\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x11\x00\x00\x00\x10\x08\x06\x00\x00\x00\xf01\x94_\ -\x00\x00\x01\xb2IDAT8\x8d\x95\xd3Oh\xcfq\ -\x18\x07\xf0\xd7\xf7\xb7%s\x908(.\x8aYM\x19\ -y\x14\x8a\x1c89\xb98\x92\x9b\x96\x7f3\xb2&\x9b\ -?5\x89\xb3\xc2\x8a\x5c8)M\x9a\x03Jqz\x0e\ -\x86\x83\x03\x07\xb2\xd5\xe4_\x88R3\x87\xdfw\xf5m\ -~#O}\xeaS\xef\xe7\xfd\xee\xfd|\x9e\xcf\xbb0\ -Cef+\xce\xa1\x1d\x0f\xd1\x13\x11\xef\x1b\xf5\x16\x0d\ -\xc8\x813X\x8d\x05\x15h\x14\x8fq$\x22^7\x14\ -\xc9\xcc-\xe8\xc7J\xcc\x9d\xc9!\xde!q4\x22\x9e\ -C\x91\x99;p\x18+0\xe7/\xe4\xe9\xf5\x09#\xe8\ -\xada\x02\xcd\xe5\xf9\xdf\x9a\xc0\xaf\x022\xb3\xc0nt\ -\xa3\x0dM\xffp\xf0\x04]\x111\x02\xb5\x12X\x8e]\ -X\x88>\xbc\xc0\xe44\xf2\x07\xdc\xc1N\xacCWf\ -\xce\x83Zf>\xc2S\xbcA[D\x0c\xa0\x03\xa7\xf0\ -\x0a\xe3\x18\xc2\x86\x88\xd8\x16\x11\xb7\xd57\xb7\x0c\xe3\x99\ -y\xbdY}m\xab\xb0V}3\x0f\x22\xe2'Nd\ -\xe6Y\xcc\x8f\x88\xd1);\x99Y\xc3&\xb4\xe23\xee\ -O\xbd\xc9,\x9c\xc4\x01\xbc\xc5\xfe\x88\x18\xae\xceR\x92\ -;\xcb\xbeB}\xa3W\x22b\xb2\xc8\xcc\x96\xd2zg\ -i\x7f\x08{\xf1\x11\xfb0\x8cC\xe8\xc1w\x9c/\xef\ -\x05\x8ec\xb0\xc8\xcc\xaf\x98\x8d\xed\xe5\xbc2\xb3\xb9$\ -\xf6\xa2\x05c\xe8\x8e\x88\x9b%^\xe04\x8e\xe1e\x91\ -\x99m\xb8\x88\xf5\xb8\x85\xce\xa9\x8cdf\x13\xda#\xe2\ -Ye\xac\x0e\x5c.\xdf\xef\x06\x0eV\xbf\xfd\x12\x0cb\ -#\xeebOD\x8cU\xf05\xb8\xa4\x1e\xc8k\xea\x19\ -\xfaB\xe3\x00..\x9dm\xc5=\x5c\xc0\x00\x96\xe2\xaa\ -zf\xbeU9\x7f\x88T\xc4\x16\x95\x02\x9bK\xfb}\ -\x11\xf1\xa3Q\xefos\xf3\x98\x0b\x981\xe3\xce\x00\x00\ -\x00\x00IEND\xaeB`\x82\ -\x00\x00\x02\x91\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x14\x00\x00\x00\x11\x08\x06\x00\x00\x00\xddD\x8c\xbe\ -\x00\x00\x02XIDAT8\x8d}\x93QhVe\ -\x18\xc7\x7f\xcf\xc7>(u\xcb\xae\xc4\xd01\x91\x85|\ -Q\x9a\x9eH\xac\xad\x18\x12\x14\xee\xb2\xb0\xebH(\x1a\ -\x0c\x04a\xdd\x85\x17\x0e\x12/\x82\x04\xe92\xbf`\x22\ -\x08\x0e\xbb\x182%\xb5\xa0\xde\xb352\xa9\x1b\xa9\x8b\ -\xe9\x96\xae\xf8J\xc4\xc2\xfau\xd1\xfb\xe9\xd9\xe7\xf2\xb9\ -9\xe79\xe7\xf9\xff\xfe\xff\x07\xde\x17:J]\xa3\x8e\ -\xa8g\xd5y\xf5\xb6\xba\xa4\xce\xa9\x1f\xa9;;5Y\ -\x87\xfa\xc0\xc7\xb7\xd4\x9b\xea\xd5\x0c|^\xedS\x9fR\ -\x87\xd5O\xd4[\xea\xa4\xfa\xc4C\x81\xd9\xfd\x8e\xfa\xae\ -\xfa\xb1\xba\xf1\x7f\x92lR\xcf\xa9\xd7\xd4-+\x02\xd5\ -\xd1\xbc\xda.\xb5\xa6\x9eZ\x09V\x11\xd7\xd5\x93y\x93\ -\xb5\xcb\x80joN6\xa6nW_S\x0f?\x0c\x98\ -\x01\xab\xd4\x9f\xd5\x0f\xab\xc0.\xe0m\xe0Z\x9e\xdb\x09\ -\xec\x02\xba\xd5O\x81_\x81q\xe0zD,\x03F\xc4\ -mu\x0a\x18P\x1f\x01\xee\x00\x84:\x0bLD\xc4x\ -vz\x07\xb8\x1c\x11\x17\xd4\xae\x99\x99\x99iu.\x22\ -N\xf7\xf4\xf4|\xd1\xdf\xdf\xffg\x9e[\x0d<\x0b<\ -\x07\x5c\x8c\x88o\x00j\xc0\x93\xc0\xb7\x15\xf3.\xe0\xaf\ -\x9c\xe2\xaez\x1exO\x9dj\xb5Z\x8beYN\xa4\ -\x94^_XXx\x1c\xf8\x0ah\x02\x7f\xb4\xc55\xe0\ -Q\xa0U\x01.\x01\xab*}\xb3\xf2\xfe\x98\xfa\x06p\ -b~~\xbeY\x96\xe5\x9a\x88\xf8\x05X\xac\x02\x17\x81\ -\xde\x8a\xe8\x07\xe0\x99vS\x14\xc5\x8f@by}\x07\ -\x0c\x15E\xd1\x0e\xf2{\x15\xf8%\xf0Jex\x0ex\ -\xa9\x03\xd0\xec\xe8\x9f\x06\x0e\xb6\x9b\x88\xf8\xbb\x0a\xfc\x0c\ -xS\xddP\xf9\xf9\x93\xda\x00Pw4\x1a\x8du\x80\ -\xc0\x11\xe0b\xd6\x8e\xa5\x94\xf6u\x18\x11j\x0d\xf8\x1e\ -\xa8\x03G\xf3\xb3\x17\xd8\x03\x5c\x00\xae\x00\xcd\xb2,_\ -\x05\x8e\xe5\x10\x1f\x00\xefg\x93\xe1\xa2(>\xbf\x07\xcc\ -)\x1aY\x5c\x02\x07\xf8\xef\x5c\x0e\x02/\x03#\x11\xd1\ -q\xeb!\xa5\xb4\x1b8\x0et\x03\x83EQ\x94\xed\x95\ -\x89\x88+\xc0\x00\xb0\x19\x98\x00\x86\x80I`\x1a8\xa1\ -n\xcd\xc6\xf56\xb0(\x8a\xb3\xc06\xe0\x12p&\xa5\ -\xd4w/a\xbb\xf2a\xdd\x0f\x8c\xe6\xd5\xbf\x06~\x03\ -\xb6\x00S\xc0\xa1\x88\xb8\xd1\x91\xb4\x96\xd7\xdf\x0b\x0c.\ -\xbfO\xf7\xc1u\xe0\x05`+\xb0\x1e\xb8\x09\x9c\x03f\ -#\xe2\x9f\x954)\xa5\x17\x81}\xff\x02\xe28ya\ -\x96\xfd\xc4\x97\x00\x00\x00\x00IEND\xaeB`\x82\ -\ -\x00\x00\x04x\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\ -\x00\x00\x00\x04gAMA\x00\x00\xb1\x8f\x0b\xfca\x05\ -\x00\x00\x00 cHRM\x00\x00z&\x00\x00\x80\x84\ -\x00\x00\xfa\x00\x00\x00\x80\xe8\x00\x00u0\x00\x00\xea`\ -\x00\x00:\x98\x00\x00\x17p\x9c\xbaQ<\x00\x00\x00\x06\ -bKGD\x00\xff\x00\xff\x00\xff\xa0\xbd\xa7\x93\x00\x00\ -\x00\x09oFFs\x00\x00\x01@\x00\x00\x00\x00\x00s\ -\x05\xb7\x16\x00\x00\x00\x09pHYs\x00\x00\x0b\x13\x00\ -\x00\x0b\x13\x01\x00\x9a\x9c\x18\x00\x00\x00\x07tIME\ -\x07\xdf\x0c\x12\x0e\x1b\x0b$&IW\x00\x00\x00\x09v\ -pAg\x00\x00\x03@\x00\x00\x00 \x00\xbe\xe6\x89Z\ -\x00\x00\x03=IDATX\xc3\xe5\x97MhUG\ -\x14\xc7\x7f'\xba\xf3\xa3`\xa3Q\xb1\xa9-(*\xb5\ -(6\x96 \xadP\xdc\xc4\x16\x04\xad\xe0}\xbb\xa1\xb8\ -\xb0p\x1fZ\xa8\x8b\x82\xe8\xa6\x14\xba\x11\xee\x05\x15\x17\ -N\xa1p/h\xa4.\x0b\x8d\xa4\xa4i\xd4E\x055\ -~ H\xd1*\xa95DP*\x88\xf6\x9d.\xdey\ -\x8f\xf1a\xde\xbb\xe6C\x17\x9e\xcd\x999\x1f\x9c\xff\x9c\ -\xff\xdc\x99\xb9\xf0\x8aE\x8a\x04\x95\x5c\x19`\x8f\xa2?\ -\xe4>\xbd\xff*\x00\xfc\x02lR\xf4\x0fA>\xc8|\ -\x12\xfa\xf6\x03\xf3\x81S\x99O\xfa\xcc\xd6\x03lVT\ -\x049\x92\xf9d\x18 r\xf1^A:\x81\x93\x99O\ -\xfa\x01f\x16(~\x14\xd8d\xd3u\xc0I`[\x10\ -\xf21\xf0\x090\x0f\xe83\xdb\x97\xc0g6\x1e\x05\x86\ -K\xae\x8c\xa2_\x03\xed\xc0O\xb5\xe4\xb6f\xc5#\x17\ -\xefUt\xa7\xa2\xaah\x05PE\xb7F.\xfe\xbe\x16\ -\xa3\xe8iEQ\xf4\xbd\xc0\xd6\xadh}l\xfam\xa0\ -\xddbO\xb7\x04`\xbc\x7f+\xc8cA\x9e\x0a\xd2\x06\ -\xfcg\xf3\xafJ\xae\xdc^\xe5P\x06\x05A\x90w\x22\ -\x17Sr\xe5E\x82\xbc)\xc8C\xe0\xb1 \xdd\x16\xb7\ -\xca\xf4\x95\xdc\xa7\xb4\x04`\xb2\ -y/0\x02\xcc1\xb0k\xcc~.\xac\xd3\x94\x82\xdc\ -\xa7c\x99O\xfe\x01\xc6\xcc\xf4 \xf3\xc9hP\xbc\x06\ -\xf4b\xb0G6\xda\xf8\x14p\xd9\xc6\x1b\x80\xb5\x0d\x80\ -[\x03\x088\x95\x1a\xa7\xe3\xf8\xcf\x99\xbfK\xd1.\xe3\ -y\x10\x18\xb2q\xb7\xa2\xab-\xf6\xec\x0b\x030\x8e\x9b\ -\xf9\x07\xcd\xdf#\xc8rAn\xe5>\x1d\x03\x86,w\ -\x8b \x8b\x80G\xb9O\xaf\x85\xb9-?\xc3\x82\xf2\xbb\ -\xe9\x95\xa6\x7f6}\xde\xf4\x0a\xd3\xfd\x8d\x89\x85:\xd0\ -J2\x9f\xdc\x00\x1eA\x9d\xa7~\x80\xdc\xa7\x0f\x80+\ -A\xe8\xaf\x13\x02`<\xb6\x8a9\x03\x88\xc5\x0e\x04\xf6\ -\x0bA\xfePc^!\x0aj\xfc7\x03!\xc8nE\ -\x97\x0b\xa2\x99O\xae\x06\xf6\x03T?\xc9\x8a\xa2}\x8d\ -yS\xb5\x07\xb0\xf3~\xf89\xf6\xeb\xc0\xf5\xf1\xf2\xa6\ -d\x0fLF\x0au\xa0\x15\xff\xd3\x0e\xa0\xc8\x1eh&\ -v=\xc7\x8an\x0e\xef\x01xy\x14,\x03z\x80[\ -%W^\xfa\xc2\x1d\x00*\xa6\xe7\x96\x5c\xb9\xa3\x96\xa7\ -\xe83'\xe48\xf3\xa7\xc0\x1bfz\x0b\xb8Tr\xe5\ -O3\x9f\x0cT\xbb[@\x22\x17\x1f\x07\xb6O\xb2\x0b\ -\x15\xab'\xc0\x13`q\xee\xd3\xd1\x22/\xa2\x13\xc0\xe7\ -\xc0\xdf\xf6$\xab\xd3V\xb0\x03\x15\xe0]`\xa5\xa2j\ -\xfe\xdf\xa8\xbe\x94\x9aS\x10\xb9\xb8\x97\xea\xf3\xeb&\xd0\ -\x95\xfb\xf4\xdeD\x96^r\xe5]\xc0![\xfd\xb1\xcc\ -'_\xd4|mA\xd0\xda\x86\xa4<(\xde\x9d\xf9d\ -B\xc5Mf\x98\xfe&,^\x07\x10\xb9x\x81\xa2\xe7\ -#\x17\x1f\xb6y\xa6\xe8\x0e\xe0\x8e\xa2\x1ff>\x19\x99\ -Dq\x14\xedUtc\xee\xd3\xef\x1a}b\xab]\x0a\ -\xfci\x9c\xfdEu\xb7\xdeV\xf4\xfd\xa9\xfe\x0fh\x94\ -\x1a\x05\xed\xa6+V\xfc_`\xfdt\x17\x0f\x01t4\ -\xd8g\x01\xfb\xa6\xbbx\x1d\x80\xa2\xf3\xec\x98m\xd3\xfa\ -\xed\xaf\xbb\x22\x17G\xd3\x0d`&\x80 ?\x02\x9d\x8a\ ->\x11d\x04\xb8\x0b\xdcU\xf4\xc2\xcb\xe8\xc2\xeb-\xff\ -\x03Q\x9bYF6Y\xf5\xec\x00\x00\x00%tEX\ -tdate:create\x00201\ -5-12-18T14:27:11\ -+00:00YM\xe3\xc6\x00\x00\x00%tE\ -Xtdate:modify\x0020\ -15-12-18T14:27:1\ -1+00:00(\x10[z\x00\x00\x00\x00I\ -END\xaeB`\x82\ -\x00\x00\x01U\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xffa\ -\x00\x00\x01\x1cIDAT8\x8d\xa5\x92?K\xc3P\ -\x14\xc5\x7f\xa9\x11%\x8b\x1d\x5c\x5c\x05\x05'\xa1\xdcM\ -\xfc\x02*n\xd9\x5c]\xc5/P\x1c;\xf9=\x1cU\ -\xea\x87\x10\x0eq\x12\xc4\xa5\x11\x8b\xe0\xa6(4R\x9a\ -8\xe4EB\xdaj\x82\x07\x1e\x8f\xfb\xe7\x9c\xfb\xce\xe3\ -z\x922 c6\x92J\xbc\x08\xf8\xc0\x17\xb0\x04\x8c\ -}G\xf6f\x90\x07f\xb6^NH:\x05B3\xdb\ -\x91t\x09\x1cx\xee\x05\xef\x15r\xcbM\xb8\x02\xd2R\ -~\x1b\xd8\x04\xae\x81=`\xc1\x07\x86\xc0\xee\x1c\x0b\xbf\ -\xe1\x0c\xe8\xfb\xc0\xc4\xcc\xe2\xa6lIm \xf5\x8bD\ -\x14E!\xb0_\x93\xff\x9c\xa6\xe99\xe4?Z\xe0(\ -\x08\x82\xc3:\xec$I\x1e\x0a\x81V\xcd\x89s\xf1o\ -\x81\xb2\x85\xa7\xd1ht\x0b,\x03\x9f\x95\xda\x9a;\x8f\ -\xc0[\x96e\xe3)\x81N\xa7s2o\x8a\xa4\x10\xb8\ -\x00\xb6\x80.\xd0\x03V\x9aX\x18\xba\xde\x04\xd8 _\ -\x22\x9a\x08\x0c\x80;\xe0\x1ex1\xb3\x9b)\x0b\x7f\xe0\ -\x158&_\xef\xbe\xa4\xdeOER\x5cS\xa4\xe8_\ -uw[R\xecI\xfa\x00&MD\x1c< \xfe\x06\ -\x8cB^q\x9bC\x89i\x00\x00\x00\x00IEND\ -\xaeB`\x82\ -\x00\x00\x01\xf9\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x13\x00\x00\x00\x13\x08\x06\x00\x00\x00rP6\xcc\ -\x00\x00\x01\xc0IDAT8\x8d\x9d\xd4M\x88\x8eQ\ -\x14\x07\xf0\xdf\xc3\xe4c\xf0\x8e\xa4\xa4X!a3\xf9\ -*55)!\x0b\x1f\xb1bMYH\x0a)+\x91\ -\x22\x89a%I\x16^5Y\xf8JV>J\x91G\ -Y(\xb11,$\xe3{2\xc64bq\xcfSO\ -\x0f\xaf\xf7\xcd\xa9[\xb7s\xcf\xfd\x9f\xff\xf9\x9fso\ -\x96\xe7\xb9\x16\xac\x1b\x07\xb0\x10\xef\xd0\x83S\xf8U\x0e\ -jk\x01h#.E\xec\x10f\xe1$j8T\x0e\ -\x1c\xd5\x04h-.\x22\xc3\x0eL\xc4\xb2\x00\xdd\x8b\xb1\ -\xad\x82M\x93J\xc9\xb0\x05\xa7\xf1\x13\x0fbM\xc2\x8c\ -\xf2\x85fe\xce\xc58|\xae$\xe9\xc40\xde6c\ -\xb6\x14O#p\x00\xe70=\xce:p\x0d\x93q\x16\ -\xdf\xfe\x05\xb6\x1a\xb7\xb1\x00/\xf1\x15\x1b$}j\xb8\ -\x89%\xb8\x87=U\x16e\xb05\xb8\x82v\x1c\xc4l\ -I\x93\xed\xb8\x80\x1b\x92\xf8O\xa4\xc6\x0c6\x02\xebB\ -/\xc6`\x1f\x1e\x06\xab\x13\x18\xc1\xf9\x88y\x8c\x15\xf8\ -R\x05\x225`\x1e\xae\x07\xa3\xfd8\x82\xc5\xd2@n\ -\x8b\x05w\xb0\xbe\x11P\x01v\x5c\x12\xf6(\x0e\x87?\ -\xc7|l\xc2L<\x0a\xe6#q^\xc3\x1c\xbcF\x7f\ -\xb9\xcc\xe5\xf8\x18\xac\x0a\x1b\x8d]\x18\x8f\xab\xa8\x97\x80\ -`w$\xe1\ -M\xd9\xf9\x1b\x87\xd0i\x8b\x22\xfc\x9f\xfe\x00\x00\x00\x00\ -IEND\xaeB`\x82\ -\x00\x00\x02\xbf\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x16\x00\x00\x00\x13\x08\x06\x00\x00\x00\x94y\xfd\x88\ -\x00\x00\x02\x86IDAT8\x8d\x8d\xd4]\x88\x97U\ -\x10\x06\xf0\xdf\x7fQ\xd0B\xdb2)\x08D]\xc9B\ -\xec\xa6!\x03\xa3\xb2 \xd1J(\x0d#\x13\x14\x0b\x8b\ -\xc0\x82\xad\x9b0\x0a\xa4@\x906BJ\x141\xb0 \ -$\xfb\xf0\x22r\xefV\xcc\x14fS\xe8\x036HJ\ -J\x0d!\xdd\xf2\x03#\xda.\xceYx\xf7M\xc9\x81\ -\xc3\xcb{f\xe693\xcf|t\xb4$3\xc7\xe1s\ -\x04\x0e\xe3B=k#\xe2\xf7js5^\xc63\xf8\ -\x0bK#\xe2@\x13\xa7\xab\x0d\x8c\xf9\x98\x80)8\x8e\ -\x07\xb1\x0c\xab*\xe8t|\x85n\xf4\xe0\x05\xack\x83\ -\x5c\x0a\xf8Z\x1c\x8d\x88\x11|\x8a\x91z\x7fCfN\ -\xc3\x00\xfa\x22\xe2\xb9\x888\x83\x1f0\xf5J\x80\x7f\xc5\ -4\x88\x88\xdd\x98\x8e\xdb\xf0\x08\x0e\xe1\xd5\x88\xd8\xd1\xb0\ -\x9f\x81_\xae\x04\xf8{\xcc\xcd\xcc\xf1\x15\xfc\x18\xbe\xc5\ -QL\xc2`\xcb\xfeN\x1c\xf9_\xe0\x888W\x9d\xef\ -o\x5c\xf7*\x94<\x81\x0fk\xf1Fe)\xf6\xb4q\ -:\xcd\x9f\xcc\x9c\x80\xdb\xf1\x12f)\xb4\xdc\x84[p\ -\xb1\x9en\x9c\xc0\xcf8\x85\x05X\x83\xfd\x11qb\x0c\ -pf\xce\xc3\x8b\xd5h\x10\x07\xf1<\x1e\xc5f\xbc\x16\ -\x11\xbb\xaa\xedU\xf8\x0e\xaf`%~\xabXw\xe1\x1c\ -\xb6bk'3{\xf1,6`wD\x9c\xad\x00\x9b\ -p7\xceD\xc4\x03\xad\xcc\x96\xe0\x0d\xa5\x83f7|\ -\xee\xa8\x01\xcd\x91\x99g3\xb3\xbb\xcdQf\xf6d\xe6\ -Hf\xceo\xeb\xaa\xfe\xeb\xcc|\xeb2\xba\xf7\xc6\xd5\ -\xb47d\xe6\xfa\x88\x18n\xe8\x17\xd4\xd4\x1e\xc2\x97-\ -\xc7\x99J\x1bv5\xee\x16b\x0b~\xc4\xad\x9d\xcc\x9c\ -Tix\x12\xfd\xf5\x1c\xc4'\x95\xa2\x0fp_D\x0c\ -5@\xf6`/\x1eG\x1f\xfe\xac\xdf9\xd5\xe4\xe9N\ -\xc3\xf8\x1a,Rx]X#\x1a\xc2u\x18V\xc6\x98\ -\xc2\xeb\x12\xa5\xc8=\x98\x88/p\x12O\xe1\x18\xe6\x8d\ -i\xb7\xc6#\xdbq\x00\x9f\xe1Fl\xc2\xdf\x15`#\ -\x1eS\x86\xe64~\xc2\x8c\x88\xf8\xa3\xf6\xf7\x85\x88\xf8\ -\xe7?\xc0\x99\xb9\x02\xef\xe0\xe1\x88\xd8W\xef\xaeG\xd6\ -\x94\xdf\x8e\x88m\x0d\xfb]\xf8h\xb4\x1dGe\xcc\xe4\ -e\xe6l\xbc\x8f\xc9x\xb3\xa1:]#\xbc\x19\xfbZ\ -\xb1\x0c\xe0\x9ev\x80\xed\x91\x1eVv/\x85+\x99\xd9\ -\xa5\x0c\xc9De\xff\xf6g\xe6\xac\x86\xcf\x90\xc2\xf5\xe5\ -\x81#\xe2$V+\x85Z\x91\x99\x93\x95\xd59S\xa1\ -f\x07\xd6c 3\xefm\xb8\x8eh\xc9\xa5\xb6[\xbf\ -\xb26\xfb\xf0M=\x8b#\xe2|}|'\x96\xe3\xdd\ -\xcc\xfc\x18\xaf+E\x1d#\xff\x02\xad\xb1\xf2$\x9a\xc7\ -|\xa6\x00\x00\x00\x00IEND\xaeB`\x82\ -\x00\x00\x02=\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x13\x00\x00\x00\x12\x08\x06\x00\x00\x00\xb9\x0c\xe5i\ -\x00\x00\x02\x04IDAT8\x8d\xad\xd4\xcfKTa\ -\x14\xc6\xf1\xaf6\x5cc&\x09\x84\x89\x91\x81\x82D.\ -.t\xa3\xa9\xa0\xb6\x17\x83\xcc\x7f\xa0\xeex\xab\x8d\x08\ -\xd5JJC\x0b\xda\x14ZV\x1b\xdf\xdew\xfa!\xb4\ -S\xaaM\xe0\xca\x19#52\xf1N\xbd\x17\xa1\xc8\x8d\ -\xad\xd2`\xae\xc9\x85\x99\xdb\xa2\x94\x8c\x08g\xecY\x9d\ -\xc5\xe1\xc3\xe1p8%Z\xeb\x1bV\xc2\xee\xa3\xc8\xbc\ -\x9aIm\xd7%Z\xeb\x00\xb8\x0b\xf4Z\x09;\xd8\x0b\ -V\x0a\xb0\xbc\xbc\xdc\x03H%\xc5\xbeb'\xdc\xc6n\ -\xde\x1a\xe6\x83\xd6g\x80Y%\x85\xb1'\xcc\xf7}\xd6\ -\xd6\xd6p2\x99z`RI\x11.\x1a\x03\x10B2\ -<|\x9b\x85\x85\x85v\xe0\x8d\x92\xa2\xbch,\x08~\ -\xee\xfe\xfb\xe6&\xa9t\xba\x06\x98RRT\x14\x85E\ -\xa3QB\xa1\x10cc\x0fP\xea!ss\xf3\x8d\xc0\ -[%E\xac`\xac\xaa\xea(\x03\xfd\x97\xa9\xac\x8ca\ -\x18\x06\xd9l\x96\x89\x89\xc9#\xc0\xb4\x92\xe2pA\x18\ -@<\x1e\xffxu\xa0\x7f\xa3\xa1\xbe\x9e\xc7O\xc6y\ -\xf6\xfc\x05s\xf3\xf3\xd5A\x10\xcc*)\xaa\x0b\xc2\x80\ -\xd7eeeM\xb6\x9d\xd0\xdd\xdd\x16\x87\xa2QV>\ -\xaf\x90L>\x8a\xe5\xf3\xf9i%Em!\x18V\xc2\ -v\x80\x86\xd6\x96\x96doo\x0f\xef\x16\x17I\xa5\xd3\ -8\x99L,\x97\xcb\xa5\x94\x14\x8d\xbb\xc6~\x81\x9e\x95\ -\xb0\xadxm\x9a\xe6\ -\xd3\xad\xa6\xd0V\xb1\xb4\xe408t\xad\x02\xf8\xe7\xa1\ -\x1e\x88Dp2\xefY_\xfff\x9c\xea<9\xee\xba\ -\xee~\xd34\x93;0\xcf\xf3\xf0<\xef_\xce\x8ed\ -\xb3Y\x06\x87\xae\x97^\xbaxA\xba\xae\x1b6M\xf3\ -\xfe\xd6?\xfb\x1f\xe9\xfb\x01\xfd\x9c\xd6\xcao\xa8\xd4\xb1\ -\x00\x00\x00\x00IEND\xaeB`\x82\ -\x00\x00\x01\x5c\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x0c\x00\x00\x00\x0c\x08\x06\x00\x00\x00Vu\x5c\xe7\ -\x00\x00\x01#IDAT(\x91m\x90?(\x84\x01\ -\x18\xc6\x7f\xef\xe7\x9b.\x03\xc9\xec\x06\x8aA\xc8`P\ -$\xebe0\xd8t\x03\x83\xc5`30;\x93U\xf9\ -su\x06\x8b\xc5\x22euJ1*\x97l\xca \x94\ -\xae\xfcI\xfd,\xdf\xe9K\x9e\xf1\xe9\xfd=\xcf\xd3\x0b\ -\x99\xd4.\xb5\xa2\xde\xa97\xea\xadZW\xcbjB^\ -\xea\x88\xdaP\xb7\xd5\xc9\x9c_T\xab\xea\x89Z\xc8'\ -7\xd4!u\x8d\x7f\xa4\xae\xaa5\x80P7\x80\x01\xe0\ -\x1c\x98\x02\x8e\x80\xb3\x88x\xf8\x03\xdd\x03s)0\x03\ -\x8cEDS\x058\x05Jj\x118\x88\x88[\xb5\x1b\ -\xa8\x03\xb3)@D4[I\x11\xf1\x08\xec\xa8)\xb0\ -\xac\xf6\x03\x83@\x15XJ\x80\xb6\x5cs\x9a\x03\xbf#\ -b\x0b(\x01_\xc0\x07\xf0\x91\x00\xcfY=@\xaaF\ -\xb6\xb9S]\x07\x8e\x81v`\x02\xb8\x0e\xb5\x0c\xcc\x02\ -+\x999\x0c\xbc\x00\xef\xc0nD\xbcf\xe0<0\x8e\ -\x9a\xa8\x97jM\x9dV7\xd5\xbe\xdcw:\xd4\x0bu\ -\x11\xa0U_\x00\xb6\x81\x1e`\x0f\x18\x02\xde\xb2\xdd\x0b\ -@%\x22\xf6\x7f\x81\x5c\xdah6\xaf\x17\xf8\x04\xae\x80\ -\xc3\x88xj\xdd\xfc\x00\xa7\xf6\xbd\x96\x10\xb6\xbf\xd9\x00\ -\x00\x00\x00IEND\xaeB`\x82\ -\x00\x00\x01\xd0\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x14\x00\x00\x00\x10\x08\x06\x00\x00\x00\x16\x18_\x1b\ -\x00\x00\x01\x97IDAT8\x8d\xad\xd4\xcf\x8bOQ\ -\x18\xc7\xf1\xd7w\x9aIJ\x8a\xac\xfc\xc8ld$\x0b\ -\xd33ca!ij\xa2\x99\xd9XY\xda\xd9Q\x9a\ -\x85\xc2\x1f )Jb\xa9l\xa7(EJ\x84,\x1e\ -\xc2\x86\x155\x89\x05\x9b\xafh\xfcfq\xcf\x9d\xb9\xa6\ -kL\x8dO\xdd\xee\xe9~\xde\xcf\xe7\xdc{\xcfsN\ -GQf\xae\xc55L\xe39n\xe0nD\xfc\xd2P\ -fn\xc38\x02\x1bq'\x22\x8e\xd4~O\x81\x86q\ -\x00\x83\x05\x1a\xc4\x15\xbc\xc8\xcc\xbd\x85\xd9\x93\x99\x0f\xf0\ -\x0c\x93X\x81\x01\xec\xca\xcc-\x7f\x04\x96\xb0\xa3e|\ -6\x22F#b\x1d\x0e\xe2tf>\xc4-|\xc1>\ -\xac\x89\x88\x11\xbc\xc4v\x9c\x9c\x0d\xcc\xcc{\x18\xc6X\ -y\xf6\xa96#\xe2>Na\x07ND\xc4\xee\x88\xb8\ -\x1e\x11\xdf\x0a\xf2\x1dO1\x9a\x99\x1b\xea7\xdc\x89\x9b\ -xW\xa0\x1a\xae\xf5\xa3\xdc/k\xd7\x13\x5c\xc2tf\ -\x1e\xee\xf9\x0b\xd4Tw\x11\xccq\xcc\xa0\x7f1\x81\xff\ -TD|\xc6W\xe6\x16\xe5\xbf\xa9-pI\x93\xb4\x15\ -\xaf\x5cJ}o\x0b\xb4?3\xfb0\x15\x11\xef\xd1i\ -\x9a\x99\xb9\x1a#\xd8\x8a~<^(\xb0\x8b!U\xf3\ -\x9e\xc9\xccc\xf8P\xbcU\x999\xa9j\xf6e\xf8\xa8\ -Z\xd9\x99f@'3\x7f\xe2*\xa6\xcc\xb5H\x9fj\ -\x07\x8c\x95\xe2Mx\x8d\xb7\xb8\xad\xea\xbd:hya\ -\xce\xe3b/.\xe0\x10&Z>\xbf\xa9\xf5\xe5\x1aZ\ -\x80y\xd3\x81\xcc\xdc\x5cfjj@\xb5;\xe6\xff\x96\ -\x09\xd5\x894_\xdd\x88x\xd5i1f\x95\x99\xe3\xaa\ -\xa3\xaa\x0e}\x14\x11\xe7\x16\xaa\xf9\x0d\xa0\xcdx<3\ -\xa5\x8a\xf0\x00\x00\x00\x00IEND\xaeB`\x82\ -\x00\x00\x01X\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x0f\x00\x00\x00\x10\x08\x06\x00\x00\x00\xc9V%\x04\ -\x00\x00\x01\x1fIDAT(\x91\x95\xd0\xbf\xab\xcfQ\ -\x1c\xc7\xf1\xc7\xe7v\xb8r\x19X\x94\x1feq\x07\x85\ -\xd4{`0\xf9\x03\x84R\x18\xac\x06\x832Q\xca\xbf\ -`Q\x06\xfe\x03\x0c\xba\x7f\xc3]^\x0b\x912(%\ -E\x08I_\xe12\xdcs\xeb\x9b\xe9x\xd6\xbbsz\ -\x9d\xf7\xb3\xf7\xe9=%\xd9\x84\x078l\x8c\xaf\xb8W\ -U\xb7\xa7$\x87\xf0tP\x9cg\xd7\x02\xde\xe3\xe7\x7f\ -\x8a\xcf\xf1i\x82$\xcb88(~\xc1jU\xcdZ\ -\x0f\x1a>\x0f\xcak\xd8\x86\xd9\x94\xe4\x12n\xe0\xc5\xa0\ -<\xe1(\xce5\x9c\xc0\xf5\xaaz8(Kr\x19\xa7\ -\x1b^\xe2T\x92\xb5Aw\x09WpkJ\xb2\xb5\x7f\ -{\xef\xa0\xfc\x1d+U\xb5\xd2\xf0\xabO\xff0(\xff\ -\xb1\xbeq\x0b\xb8\x8a\x0b\xd6\x171\xc2\x22\xee$9\xd3\ -\xb0\x8c\xbbU\xf5hP\x96\xe4\x1b\x8e5\xac\xe2Z\x92\ -#\x83\xeev\x9c\xc7\xd9\x86\xfb\xf8\x88\xfd\xff4\xed\xc0\ -\x01<\xc1\x8f\xb9\xfc\x0d\x8eW\xd5\xeb)\xc9nl\xee\ -\x0f\xfbp\xb3\xdf\xb7`'\xde\xe17\x1e\xf7\xda`\xd6\ -p\x11{z\xb0\x88\xb7s\x0d\xaf\xfa\xb9\x84\x93\xbd6\ -x\xf6\x17\xf1zO\xd5\x8bA\xa4\xa9\x00\x00\x00\x00I\ -END\xaeB`\x82\ -\x00\x00\x01\x0a\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x08\x00\x00\x00\x0d\x08\x06\x00\x00\x00\x94\xc2/8\ -\x00\x00\x00\xd1IDAT\x18\x95]\xd1\xbf/\xc3a\ -\x10\xc7\xf1\x97'\xd5\xc9h\x11F\x83\xe8\x82\xa4\xb1\x96\ -\x8d\x8dAl\x9a\x0e\xfe\x83\xae\x1d\x18\xc4`\xa71\x1b\ -\x0c\x12\x8b\xc9`\xd3\xe1;t3h\x18-\x12\x93(\ -\xea\xc7\xe0\x9e4\xf5I\x9e\xdc=w\xef{\xee\xc9\xdd\ -XQ\x14B\xab8B\x05\x1d\xec\xe01Er\x06\x97\ -X\xc01^q\x81R)\x80\x06&\xd0\xc7\x1efq\ -\x8b\xad\x0c\xac\x87=\xc7s\x9c;l&T\xb1\x14@\ -\x17\xe5\xf0oPM\xd8\xc5x\x04\x9b\x86\xeaa*\xa1\ -\x15\xbd\xa1\x8d\x8f\xf0\xdf\xf0\x95\xf0\x84\x83H\x9c\x18\xd5\ -K\xfe\xe4!~\x02\xce\x9aF/\xcf\xe1\x1d\xfb\xff\xaa\ -\x17\xd1\xcd\xc0<\xceP\x8f\xfb$Vp\x9d[\xdcc\ -\x19\xdb\xf8F\x0d\x0f\xb8\xca/|b\xcd\xdf\x0eN1\ -\x87\x0d\x0c~\x01]'-R\x7f\xd2\xe3\xe9\x00\x00\x00\ -\x00IEND\xaeB`\x82\ -\x00\x00\x01~\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x0f\x00\x00\x00\x10\x08\x06\x00\x00\x00\xc9V%\x04\ -\x00\x00\x01EIDAT(\x91\x85\xd2\xbbjVQ\ -\x14\x04\xe0/\x1a\xa3h\xe5\x05A\xd0\x17\x10\x04\x85\x05\ -\xa6P\x10D\xb0\xb5\xb0\xb2Jc\xa1\x9d\x85\x8d\x01\xb1\ -\x15\x1b\x0b\x11\x0b\xf1\x15\x22v\xa9,l\x84)R\x05\ -\x84\x08\x0a\x81\x88\x22\xa8` x\x89\xc5\xd9\x07~\x0f\ -\xffe`\xc3\xda\xb3Xkf\x0f[\x92\x0fIN\x1b\ -A\x92\x85$\x17\xcd\xc0\x5c\x92]\x5c\xc5\xbb\xc6\xed\xc3\ -S\x5c\xc6\xc3V\x8f\xc3v?\xbc\x85\x13\xb3\x94\x06x\ -\xb9\xa7\x15\xd7q\xb8\x9d#x\x81\xbf\xb89\xc2\x0f\xcf\ -\x0dIv\x93\x9c\x1d]\x99d.\xc9\xc9Y\xd2\xbd\xed\ -Gx\x82E|\xc27\x5c\xc2\xca\x14\xee\xf5X\xe5!\ -\x92\x1cL\xf2|\xe8\xa6W\xbe\xa5\x0bm\x1c\x16\xb0\x8c\ -3\xcd\xc12\xbeb\xab\x1f^k!L\xc21\x1c\xc2\ -\x0e>\xeb\xc2\x5c\x9do\xcd\xa5\xaaZ\x9bb{/\xee\ -\xe1qU}\x1f\xda\xbe\x80\xb7\xd8\x8f?m\xf3\x01l\ -O\xe2\xaa\xeag\xaf|\x05\x1fq\x0e_\xf0C\x97\xe8\ -\xea\x14\xeeU?\xbcRU\x9bIvp\x17\xf7\xabj\ -\xbd\xf56G^\xf0\x1f\xd7\xdb~\x80_\xb8\xad\xfb\xa6\ -\x1bx\x86\xdf\x93r\xc0\xfb^y\x11Gq\xbc\xddO\ -\xe1Z[8\x09o\xe6\xdb[\xefT\xd5z\x92\xf3\xba\ -\xdf\xb6TU\x1bS\x06\xc1?\xb7?\x88\x1a\xfe<\x0d\ -\xb2\x00\x00\x00\x00IEND\xaeB`\x82\ -\x00\x00\x02\xce\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x17\x00\x00\x00\x13\x08\x06\x00\x00\x00{\xbb\x96\xb6\ -\x00\x00\x02\x95IDAT8\x8du\xd5]\x88\x96U\ -\x10\x07\xf0\xdf\xbe\xec\xa6\xb5R\x86\x19\x15Kx\x11F\ -B\x118\xb1\x98e\x94PT\x0a\xf6\xa9\x90\x10^I\ -Y$\xacE7\x19!D]\xa4E\x1f.\xa1\x88\x22\ -\xde\x88X\x04]\xecEEA\x9f'D\x12\x17\xb2\x94\ -\xa4\x15\xc2\xb0\xb7R\xa3\x0f\xb2\x8b3k\x8f\xcf\xbe\x0e\ -\x1c\x9e\xe7\x9c\x99\xf9\xcf\xccyf\xfeO\x9f\x96\x94R\ -\xfa\xf1>\x02\xfb\xf0G\xae\xd58\x91f}8\x93\xcf\ -\x95X\x86\x19\xf8\x02\x9b\xf0\x0bt\xda\xe0X\x88\xe9\x98\ -\x85c\xb8\x17\x0f\xe2\xd1\xd4Ok\xd8n\xc5\x0e\xdc\x8f\ -\x1b\xf0\x0c>\xc7\xec\xf3\x81_\x8a\xc3\x11q\x06\xefd\ -\x860\x13\x17\xe3\x82<{\x00\xabR\xf7\x0fn\xc6s\ -\x98\x8b7\xce\x07>\x81\xab!\x22\xf6`Nf5\x8c\ -\x058\x95vO4|\xf6\xe2\x086\xa3\x8b\x870\xb7\ -\x17\xf8A\x5c_J\x19\xc8\x00Gq\x00_\xe3'\xfc\ -\x9b\xd5-j\xf8\xbc\x95\xcf\x93\xd8\xae~\x8b\x15S\xc0\ -#\xe2T\x02-n\x1c\xaf\xc1\x8f\xf86\xf7\x8b\x1aU\ -\xef\xc3G\xad*\xe0\xb6\xbe&p)e:\xe6\xe3i\ -\x5c\x93\x80Wa\x00\xa3\xd8\x95\xc0kqK\xba\x8d\xab\ -w<\x99\xfdL\xb5[\x8eu\x12t\xb8\x94\xb2;\xc1\ -\xd6c?\x86\xf02\xfe\xc6\xe3\x11\xf1\x1a\x8e'\xd8p\ -#\xa7\xebpQc\xdf\xc5o\xb8\xac\xbf\x942\x82\xc7\ -\xb0\x01\xab\x22\xe2d\x06\x1c\xc4\x8b\xf8!\x22>l8\ -\x1f\xc4\x96\xf4\xa1\xde\xf3\x16\xe7J\x17C\xfdx\x01C\ -\x11\xd1m\x19l\xc6\x93\xb8\xd5Ty\x1e\x0f\xab\xb3\xb0\ --\xc1\xdar\xa2\xa36\xfd\x86R\xca%-\xe5\xedj\ -\xdb\xdd\xd9\xc3\xf18F\xd4\xfe~\xb5\x87~\x16&\xfa\ -q\x9fz%\xdf\x97R\xc60\x96\x01GR7ZJ\ -\xd9\x16\x11\x13-\x80\x1d\xea@\x1dn\x9d_\x8eA\x8c\ -\x9f\xed\x96\xcc\xfcn\xb5\x1b\xeeR\x87g\x5c\xe5\x8c/\ -\xf1\xba\xda\xa2\xa7{d\xda\x94%x\x0f#}\xbd\xb4\ -\xa5\x94\xad\xf8\x14\xef\xe2\x0a<\x8bO\xd4\x1e\xee\xe2/\ -\xdc\x84\x1b\xf1\x9d\xda\xe7\x9341\xaa\x92\xdc\xbc)C\ -TJyD%\xaaC\x11\xf1sD\x1c\xc0SX\x9a\ -k0M/\xc4\xdb\xf8\x00\x1b\xf3lHe\xc9\xcf0\ -\xdei\x01_\x8b\x9d*Aml\xa8\xba\xf8\x1dwd\ -\xd6\xf01v\xe7\xfbZ\xbc\xa4\x12\xdd@&3\x85\xb8\ -~U\xb9\x1b\x8ef\xc0\x8e:\x81\x83x\x13W6\xec\ -W\xe2\x95\x0c\xbeN\xe5\x94%\xf8Jn\xda\xd7\xb2<\ -#/\xce,v\xaa\x1c\xbe,\x03O\xc3\x9fm?\xff\ -\xff@\xceJ/V\x1cS)w\x13\xbe\xc9uOD\ -LV\xd4\x0bX\x1b\x18\xfe\x03:\x81\xbf\x95\xfd\x1fR\ -q\x00\x00\x00\x00IEND\xaeB`\x82\ -\x00\x00\x01]\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x0e\x00\x00\x00\x0e\x08\x06\x00\x00\x00\x1fH-\xd1\ -\x00\x00\x01$IDAT(\x91\x9d\xd2!K\xa4a\ -\x14\xc5\xf1\xdf\xbcc\x90\xc5\xb5\xd8\xd7\xb22i\xda\xfd\ -\x00b\xd02A6\xca&\xd3\xb2U\x90A\xfc\x00&\ -\x8b\xb8[D\x10\xd4\x22\x82\xc5f\xb5\xb8\xb7\x88\x96\x0d\ -\xe6M\xc2*\x83\x82\x08\x1a\xe6\x1dy}w4\xeci\ -\x0f\xf7\xfc9\xf7\x1e\x1e\x99\xf9\xcd\x7f\xa8\x91\x99W8\ -\x88\x88\xee{\xc6\xcc\x1c\xc5\x0c:X.pQ\x0e\xd6\ -\xde\x00\xda\x99y\x84k\x1cc*\x22z\x05\x94i\x8f\ -o\xc0\x97\xf8\x88\x0f\xe5{\x17\x8a\xc14\x22V\xf1w\ -\x08\xdc\xc14np\x8f\xc3W`\x09\xafU\xe1\xccl\ -c\x1f\xa7\xf8\x8c\xa5\x88\xe8\xd1/\xe7(\x22\xe6kw\ -u\xd1*\x93~\xe1kDC\xc7x\x17\xfa*\x00\xe6\ -KG\x079=z\xde\xaek\xf8{\x85\x5c\xa3S\x0b\ -(C\x22!\x1c\xc1ry\x9e\x91\x17_~.\xb0\x89\ -\xf5\x8b+#\xe7.\x94\xcd\xa69c\x9d\x1d@()\ -\x9b\x14vJ\xc0\xd9{\x06\xbf\xaf\x80m\xd3\xbe\xdab\ -\xad\x07\xa8z\xbd~ \x02\xcd\xf2\xbb\xa1f\x89}\x89\ -\x8e\x14\x19\x22\x96\x04\xfe\xa8\x94\xe7\x97\xb76\x1f\x1e\x88\ -@\xdc(\xd6\xcaw=\xdd6N\x00\xc3@\x09\x9d\x1b\ -\x14\xfajV\x80Z.\xbf\xf7\x15\xef\x94\x80\x0d\xb50\ -,\x81\xd7\x0c\x81[\xe8\xec\xe9\x00\x09\xe0%`(\x99\ -J\x93/\x14Y_\xf3:&`7\xednC\xc0\xc2\ -VAo>\xda\xdeZ\x07H\xa6\xd2\xa03h\x1e\xa2\ -?\xc7aX\xb9DD\xf9\xf8\xaf?]\xe7\xfa\xd7\x9f\ -\xdb\xbe\xf4\xad\x14\xf19~\xac\x94\xa2\xaf\xdfF\x98_\ -\x1f\xc6\xcc)k(e\x9dp!\xa0\xcb\x1e\xaf\x8a\x10\ -d\x0b\xbdv\xbd\xf2\xe7\x22\xe6\x81#\xb9B/\xe3\x13\ -\x93\xb6?\x1aPT\x03\xd2\xb1C\xf1\xe2\xf8\xc4\xa4\x07\ -\x9cg\xb7p\xb5[\x8c\x8dOL\xce\x1aR\x05\xb4\xf3\ -6@W\xc8\xfb\x11\xb0O\xed{\xe6\x0b#mH\x8c\ -\x00\x0fBs\xb1\xc0\xf9n\xb6\xbb\x9bp\xc9\xee\x13\xf0\ -\xeeWh4\xea\x1b\xae\x1b\xfb\x18\x1dN%\xb3a\xc2\ -\x9c\xee\x11\xf0-0\x80~v\x934\x97\xec\xdf\x1bU\ -5\xb4\xb3\xda\xfaP\xa2\xdf\x8c\xdb^u\x99`E\xbc\ -\xe7F\xce\x8c\x8eqj\xf8,\xdd\xdd)\x84\xb3\x9b\xba\ -\xa5R(\xd9\xe0\xde\xec\x0c\x99l\x9e\x9eb\x1f\x8e\xe3\ -\xea\xa7O)\xa4\x94T\xca\xf7\x00\xe8\x1f\x18\xc2q\x1c\ -\x84\x10\xbe\xd7I)Y\xf5\xaa\xccLO\xb10w\x97\ -g\xf8_\xe1\x1f\x16\x8f\x0dW\xeaa@l\x00\x00\x00\ -%tEXtdate:create\ -\x002015-12-18T14:2\ -7:00+00:003\x90\xe8\xec\x00\x00\ -\x00%tEXtdate:modif\ -y\x002015-12-18T14:\ -27:00+00:00B\xcdPP\x00\ -\x00\x00\x00IEND\xaeB`\x82\ -\x00\x00\x01\xa9\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x0f\x00\x00\x00\x0e\x08\x06\x00\x00\x00\xf0\x8aF\xef\ -\x00\x00\x01pIDAT(\x91}\xd2\xbbk\x94Q\ -\x14\x04\xf0\xdf.A\x22\xd8\x88O\xb0\xf0Q\xf9\x8a\xa8\ -\x1c\x9bhaa\x1b%\x01\x11\x8b\xfc\x01\x06A1+\ -\x096Z\x88HH\x0am\x04\x03*ha\xe3\xa3\xb3\ -\x08\x98*\x12\xe5@\x1a1\x08V\x0a\x8a\x06\x82b*\ -\x1bS\xec\xfd`\xf7#\xe4\xb4wf\xce\xcc\x9c\xdb\xb0\ -\xc6d\xe6~\xdc\xc1!\xbc\xc3XD\xfc\xaa\xe3\x1a5\ -R?n\xe2\x046w<\xfd\xc4\x5c\x11\xf9\xd2E\xce\ -\xcc\xb3h\xe1\x186\xad\xe5\xa6\xcc2>\xe0VD\xbc\ -od\xe63\x0ca\xe3:\xa4\xfa\xfc\xc5\xedj\xf30\ -\xae\xe10z\xd6!\xfd\xc1|\xd9<_\x01\xdf\xe2\x22\ -\xbea7\xfat\xf7\xb1\xac]\xdc\x06|\xc5Ghf\ -\xe6,\x16\xf1\x19\x17\xb4s\xdf\xc0',\xe15NF\ -\xc4\x00\x86\xb1\x05?2\xf3IO\xb1q\x14\xc7\xb1'\ -\x22\x16q73\xa7\xb0-\x22\xbew88\x82\x83X\ -\xc1\x5c\x95\xb9\x17\xafp\xaaX\x1a\x89\x88\x85\x8a\x91\x99\ -\xe70\x89\xed\x98\x8e\x88\x1642s\x1c\xa3%\xcb%\ -\x9c\xc6\xf5\x92\xff)\xae\xe0\xbf\xf6)\x9b\x98(\x9ac\ -M\x0c\xa2\x17/\xb1\x10\x11\x13\xd8\x81\xc7\xa5\xc4\x91\x88\ -\xd8\x1b\x11/0S\xca\xdd\x89\xf3\x95\xed\x03x\xa8}\ -\xaa\x07\xe5\x14\xff:lo\xc5=\x0c\xe0\x0d.G\xc4\ -R\xfd{\xee\xc34\x02\x8fp\x1fS8S\x9c]\x8d\ -\x88\xdf\x15\xbe\x8b\xdc!\xb2\xab\x88\xf4\xe39Z\x11\xb1\ -R\xc7\xad\x02\xcc\x87tf \xe3\x97\xea\x00\x00\x00\x00\ -IEND\xaeB`\x82\ -\x00\x00\x01\x04\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x08\x00\x00\x00\x0d\x08\x06\x00\x00\x00\x94\xc2/8\ -\x00\x00\x00\xcbIDAT\x18\x95]\xd0!K\x83a\ -\x14\xc5\xf1\xdf\x1e\xa7\xc5j\x19[\xb1\xc9\x92\x22\xab\x82\ -\xc1\xb0\xa8\xc1l\xda\x17\x10\xeb`\x03\x0d~\x82\x81\xb2\ -:0\x18\xd6V\xdc\xa2\xe1\x05WDP\xd1\xb8\xe2\x07\ -\x105\x18\xde\xfb\xe0\xf0\x94{9\xfc9\x97{*E\ -Q\xc0&\xae\xb0\x87G\x9c\xe2\x0e\x12\xaa\xb8\xc57\x06\ -\xd8\xc6\x18\x8d\x0c\x1c\x87\xd9C\x1f\x9fXG'\x03G\ -x\xc2=>p\xa3\xd4A\x06Z\x98\x86\xb9\x86y\xec\ -\xbbh%\xd4\xf0\xeaOg1W\xd1IX\x89\xbb\xf0\ -\x15\xdf\x08\xaf\x9b\xe2\xee\xb2\x06\x01^`\x91\xf0\x8c\xfa\ -\x12\xb0\xc09.E\x07\x0f\xd8\xf9\x97\xd2\xcfK\xc2\x04\ -\xfb\xd8\x08\xef\x04#4s\xc2\x04o\x119\xc3\x10\xef\ -x\xc9\x09?8\xc4\x16\xae\x95\x85\xb5\x95\xd5\xfb\x05\x08\ -|+}\x8e\x949\xf5\x00\x00\x00\x00IEND\xae\ -B`\x82\ -\x00\x00\x06\x1d\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\ -\x00\x00\x00\x04gAMA\x00\x00\xb1\x8f\x0b\xfca\x05\ -\x00\x00\x00 cHRM\x00\x00z&\x00\x00\x80\x84\ -\x00\x00\xfa\x00\x00\x00\x80\xe8\x00\x00u0\x00\x00\xea`\ -\x00\x00:\x98\x00\x00\x17p\x9c\xbaQ<\x00\x00\x00\x06\ -bKGD\x00\xff\x00\xff\x00\xff\xa0\xbd\xa7\x93\x00\x00\ -\x00\x09oFFs\x00\x00\x01\x00\x00\x00\x00\x00\x00|\ -]\xbdz\x00\x00\x00\x09pHYs\x00\x00\x0b\x12\x00\ -\x00\x0b\x12\x01\xd2\xdd~\xfc\x00\x00\x00\x07tIME\ -\x07\xdf\x0c\x12\x0e\x1b\x00\xb3\xf4\x90\xdf\x00\x00\x00\x09v\ -pAg\x00\x00\x02`\x00\x00\x00 \x00\x1f=\x87\xd8\ -\x00\x00\x04\xe2IDATX\xc3\xed\x97YlTU\ -\x18\x80\xbf\xdb\xb9C;3]fa\xe8\x02\xb4@\x99\ -.\xd0R*\xb4\x104b\xc2\xea\x86\x18\x97 \xea\x83\ -F4\xfaf4F_\x5c\xde$\xf2\xa0\x0f&FE\ -\xe2\x83\x01#\xa6\x88@@)E\x81\xcaRZ\xbaP\ -\xbaP\xa4\xdbl\x1d\x0b\x85v\x98i;\xbd>\xdcs\ -\x87)\x9d\xa5`|\xd2?\xb99\xe7\xfc\xe7\xfc\xe7\xff\ -\xce\xb9\xff\xf9\xcf\xbd\xf0_\x17\xe9^\x0d\x93S\x0cX\ -\xac3\x99\x91\x9c\x82N\x96\x19\x1f\x1b%\x18\x08\xf0\xd7\ -\x80\x9bP(\xf4\xef\x00\xd8\xecY\xcc\xce\x9d\x8f}V\ -6\xf6\xac\xd91\xc7\x0dx\x9c\xf8\xbc.\xdc\xfd\xbdx\ -\x5c\xbd\xff\x1c \xddleaa\x09\x05\x8b\xca4\xd5\ -\xeb\xc0\x9b\x80#\xca\xf03\xc0\x0f\xc0\x1e\xa0\xbf\xf7j\ -\x17\xed\x17\xeb\xf1y\xdd\xf7\x06`\xb6\xd8\xd8\xb0i\x0b\ -RR\x12\xc0W\xc0f \x1d\x98\x00\xde\x07N\x01)\ -b\xae\x5c\xe0\x9b\x08\xf3s\xc0c\x80\xf7\xf7_\x7f\xc6\ -\xd9w\xf5\xee\x00\xcc\x16\x1b\x1b7o\x05\xb0\x00>\xe0\ -i\xa0J\xeb\xbf\xe5\x1f\xc1`4\x85\xc7\x8f\x8f\x8f!\ -\xcbz\xadY\x00\xb4\x8b\xfas\xc0\x9e\xdf~\xd9\x8f\xab\ -\xbf{\x92\x8f\xa4x\x00y\x0b\x0a\xb5j\x0fP\x01T\ -\xdd\xb8>\xa8\xe9\xca\x0dF\xd3v\xe08\xd0\x08\x9c\x96\ -e\xfd\x0e`\x0e@(\x14\xea\x10\x0b<\x09\xec\x06^\ -Z\xbd~\x136{\xd6\xf4v\xc0:3\x93\xf5\x8f?\ -\x0b\xf02\xf09`\x08\x06\x03$'\xa7d\x02M\xc0\ -\xac8\xec\xe7\x81\xe5\x11\xed\xb3b\x019\xed\x17/\xb8\ -\x1a\xce\x9eH\xbc\x03s\xf3\xf2\xb5\xea\x87@\x99p\x0e\ -\xe0N\xe0\x1c`\x19\xa0\x88\xd7\x00P)\xcao\x1dE\ -\xa5\x98\xd2\xd2\x13\x03dXl\x88\x09\xe6\x02\x1dMu\ -\xb5Z\xd7\xa7L_\x0e\x00f\xcd9\xb0.I\xa7\xc3\ ->+'1@\xce\xdcy\x00\xcf\x00-\xa0\x9emW\ -_7\xa8\xc7\xef\xebi\x028\x80\x8fD\xfd\x0bM\x99\ -\x9a\x9e\x11\x1f\xc0f\xcf\xd4\xaa\xaf\x01}\x8a\xa2pc\ -\xe8\x1a\xe7jk\xb89t\x0d`\x1b\xb0e\x9a\x10/\ -\x88r4\xacQ\x94D;\x10\x8e\xcdl\xa0\x5c\x92$\ -\xd22,\xf8GnRsd\x1fW:[\x01\xbe\x17\ -\x03\xb7'\x00\xb0\x8a2\x9c:\x83\xc1@|\x00\xb1\xfd\ -\x002\xf0\xaa\xd7\xdd\xaf\xad\x1c\xff\xc80gOVS\ -sd\x1f\x97\xdbZ\x00\xde\x05\xd6\xc4\x01xO\x94o\ -\x01]\xa0\xbe\xce\x98\x00\x16\x9b\x9d\xc5e\x15\xa0\x1e=\ -\x80\xfd\x91\x06\x9ax\x9c\xbd\xd4\xfdQC\xed\xf1\xc3\x00\ -\xc7\x80w\xa28\xf7\x00\x1f\xa3&\xb2\xd5\xc0\x06\x9f\xd7\ -\xc5\xf5A_l\x809\xb9\xe1\xe3\xf7\x06\xf0\x0a\x80\xbb\ -\xbf'\xe6\xf2z\xfe\xec\xe4Rs=\xc0'\xc0:\xc0\ -\x1f\xd1]!\xcaZ\xd4\x14\xdd\xd5T\x7fz\x92\xbd|\ -\xe7\x84\xb2^\x1f\xd9\xdc\xa9(\x0a\xa3\xa3A\xe2Ic\ -\xdd)<\xce\x1e*\x1fX{\xd4hJ5E\x19R\ -\x04\x14{\x5c}x]}\x93:\xa6\xec\xc0\xc4\xe4\xbb\ -\xfc\xb2$I\xdc\xff\xd0F\x8c\xa6\xb4\xb8\x10ng/\ -\x87\x7f\xda\xcd\x89\xea\x03(\xb7\xa3\xfcm \x84\x88\xea\ -\x96\x863S\xec\xa6\x00\xb8o\xdf\xdf\x0f\x02\xf9\x80\x92\ -n\xb6\xe2(.%\x91\x8c\x06\x03\xd8\xecYH\x92d\ -A\xcd\x84\x1f\x00:\x80\xeaC?\x12-\x96\xa6\x00x\ -\x9c\xbd4\xab\xa4'\x22\xf5#\xc37\x13\x02\x00\xcc_\ -X\x0c\xf0\x99h\xa6\xf9G\x869zpoT\xe7\x10\ -%\x06\x00|\x93\x07\x8f\x03\xa4\x18\x8c\x94\x96\xaf\x00\xa0\ -\xb3\xad\x99\xc0-\xff\x14\xbb\x0c\x8bM\xbb\x9e\x9f\xd7\xec\ -N\x1e;\xc8\xa0\xcf\x1b\x138*\xc0\x80\xd7\xa5UO\ -\x03+\x01J\x96V\x86\xfb\x0d\xc6TZ.\x9c\xc1?\ -2|\xdb\xb9\xd9J\xee\xbc\x85\x8c\x8f\x8d!\xeb\xf5\xdf\ -\x09\x08R\xd3\xccq\x01\xa2&\xa2\x89P\x88+\x1d\xad\ -\x00O\x09\x95\x22\x9e\x10\xf0\xf0\x82\x82E8\x8a\x96\x00\ -`\xb1\xdaYr\xdfJ6n\xde\xca\xe2\xa5\x95\xc8z\ -\xfd*\xa0\x5c\xcc]\x90=;7\xee+\x8by\x19\xb5\ -_l@Q\x14'j\x04k\xcf#\xc0!`g^\ -~!\xa5\xe5+\xd8\xf0\xc4\x16\x16\x95UX$I\xda\ -. O\x01%b\x9a]\xf3\x1d\xc5\xe8d9&@\ -\xdcO\xb2\x0c\xb3\x15{f\x0e\x06\xa3\x89\xa4$\x1d\xc5\ -K\x96i\xbbQ\xad(\xcaZI\x92@M\xb1;\x80\ -\x00\xf0\x22\xb0W\x98\x97\x00\xcd\x80Ts\xb8\x0a\xcf\x1d\ -\xe7?n\x0ch2t}\x90!\xf1\x09\x96\xb7\xa0 \ -\xb2k\x8d$I_\xa2\xde\x8a\x00\xfb\x80'\x01.5\ -\x9d'\x10\xf0\x93_X\xd2\x92\x9ea\x91n\x0c]c\ -\xc0\xe3\x8a\xe9#.@\xa4\x0cx\x5c\x8c\x8f\x8d\x22\xeb\ -g\xecB\x8d\x8dm\xa8A\xfa(0\xd8\xd1\xda\xc8\xd5\ -\xae\xb6p\xc0u_\xe9\xc0QTJg[3\x13\x13\ -\xb1\x7fT\xee\xea\xc7\xa4l\xf9*\x1cE\xa5\xc8\xfa\x19\ -a]wW;]\x9d\xadSR\xect\xe5\xae\x7f\xcd\ -dY\x8f=3\x1b\x9dNf\xc0\xeb\x22\x18\xb8uO\ -\x8e\xff\x17M\xfe\x06<\xc9\x9b\xa3b\xcb\x06=\x00\x00\ -\x00%tEXtdate:creat\ -e\x002015-12-18T14:\ -27:00+00:003\x90\xe8\xec\x00\ -\x00\x00%tEXtdate:modi\ -fy\x002015-12-18T14\ -:27:00+00:00B\xcdPP\ -\x00\x00\x00\x00IEND\xaeB`\x82\ -\x00\x00\x01Z\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x0e\x00\x00\x00\x11\x08\x06\x00\x00\x00\xed\xc8\x9d\x9f\ -\x00\x00\x01!IDAT(\x91\xc5\xd3\xbf+\xc5Q\ -\x18\xc7\xf1\xd7\xe5\x86\xe4\x12\x8b\xd1j5\xca\x8f.!\ -\xe4\x0fP\xc4\xceD\x06e\x91\x12\x7f\x81\xcd \x19d\ -\xb0\xc8d\x91\xc1f\xfe\xda\xc8b\x10I\xa9\x9b\x9f\xc3\ -9\xd7\x8f\xd3\xa5L>u\x86\xf3<\xe7\xfd\x9c\xf3\x9c\ ->O.\xcb\xb2\x02\x96\xd1\xe0S\x8d\xa8\xf6]\xb5\xa8\ -/o\xf2x\xc0\x0e\x0ep\x85M\xdc\xe35\x01\x1fQ\ -\xc2\x14\x86\xf21x\x86N\x1c\xa2\x1d\x0b\x15@\x98A\ -\x11\xc5\xaa/\xc1Kt\xa3\x03\xbb\xa8K\xa0E\xcc\xa3\ -\x17YU\x92\xbc\xc30\x9ep\x84\x96\x18_\xc5$z\ -pQ\xee1U\x09\x13X\xc3)N\xe2+\x8a\xb8)\ -\x1f\xaa\x04\xc2[|\xda\x05\xc6\xd1/|\xd8\x87rY\ -\x96\xfd\xc0\xfe\xae\xb4\xc7\xff\x07g1\xf8Wp\x09s\ -\xd8\xc6t\x9a\xac\xf4\xab9\xaccD0D\x93\xe0\xa8\ -6\xac\xfctc\x0e\x1b\xa2\xadp\x8dstaL\xf0\ -q>\x05\xab\xb1%xu\x00\xb7_r\xd7\xe8C\xab\ -0\x0c\x852X\x83=\xc1b\xa3\xb1`s\xb2\x0a\xb1\ -\xe7\x17\x1c\xe7\x85\x19\xdb\xc7P,\xf2(\x8c\xdas\xd2\ -F)\xe6\xc0;/f:\x9b\xed\xa3J\x96\x00\x00\x00\ -\x00IEND\xaeB`\x82\ -\x00\x00\x02\x0c\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x0e\x00\x00\x00\x0f\x08\x06\x00\x00\x00\xd4\x14\xfet\ -\x00\x00\x01\xd3IDAT(\x91\x8d\x90\xbfk\x13a\ -\x18\xc7?wy#I\x04\xc1HMq(m\x22\xa5\ -\x15/\x15DA\xed\xdda\x8d.\x82q\xabm\x97\x03\ -AJ]\x5cJ\x97\xc6?\xc2\x1f\xc5\xd1\xc9\xae\xea\x5c\ -\xa5w7\xd4\xa1\x08=\x0bbQ\xc8-\xd23%C\ -\x04\xf1\x02i\x1c\xbc\xf7\xed\x05\x1c|\xb6\xef\xe7\x9e\xe7\ -\x9e\xf7\xf9hc\xe5\xca7\x8ej\xd6\xb6\xccm\xd7\xf3\ -\x17\x81\xe5\x84m\xdb\x969\xebz\xfe4\xe0\xcbF\xf1\ -\xec\xe9\x93\xb2\x0c\xcf\xd7\xd6\x86\x01n\xd6j\xe3\xf5\xfa\ -\x9d2\xc0\x97\xbd\xbd_\xc1\xce\x0e\x86a\x14\x1f7V\ -\xd5\x06Q*\x95\x8e\x82\xc8\xea\x00\xb9|>#y\x14\ -E:\xff(\xd1\xe9t>\xcb\xa0\xebz\x07\xa0\x7fx\ -\xf8]\xf28\x8e\xbf\x02d2\x99V\x14E\xea\xa9\x9a\ -\xe38\xb7S?\xda\x02\xda@\x05\x98HX;\xe1'\ -\x80)\xb5\xd1\xf5\xfcG\xa9\xc1\xd0\xb6\xcc\xb6\xeb\xf9\x97\ -\x80\xfb\x09\xdb\xb5-s\xcb\xf5\xfcq\xe0\xa5\x1al4\ -Vk2\xac\xbfZ\x1f\x01v\xa7\xaf]\xbdx}f\ -\xa6\x06\x106\xc3\xa10l2991\xfcpiI\ -\x89\x14U\xc3P\xeb^\x17\xde\x08\x80\x93\xc5S\xc7\x14\ -\xef\xf7\xb3a\xd8D\x88\xac> \xb2\xdb\xed\x1e\xa8\x83\ -5-\xfe\xdb\xdb\xff)y\xaf\xd7kKqi\x91\x9a\ -\xe38\xf7R7\xbe\x03Z\xc09\xa0\x9a\xb0\x03`\x03\ -(\x02W\xd2r.\xa4\x06?\xd8\x96\xd9r=\xff4\ - y\xd3\xb6\xcc\x0d\xd7\xf3\xcf\x00J\xa4XX\x98_\ -\x91as\xd3}\x0f4\x0d\xe3\xfc\xadj\xb5\xba\x02\xd0\ -\xfa\xd1\xfa\x18\xc7\xbf_\x9c\xadTF\xe6\xe6\xe7\x94H\ -q\xb7^W\xeb\x82\xe0S\x0e`tt\xec\xb8\xe4A\ -\x10\xe4<\xcf#_(\x0c\x88\x14\xfcgi\x9a\x16\x0f\ -\x88t\x1c\xe7A\xea\xfb[`?\xb9\xefr\xc2\xf6\x13\ ->\x04\xdc\x90\x8d\x7f\x00\xbf\x16\xa5`bD\x0f\x81\x00\ -\x00\x00\x00IEND\xaeB`\x82\ -\x00\x00\x01}\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x14\x00\x00\x00\x10\x08\x06\x00\x00\x00\x16\x18_\x1b\ -\x00\x00\x01DIDAT8\x8d\xad\x93A+DQ\ -\x18\x86\x1f#\x8d\xc8l\x94\x14QC\x16\xa2,N\x83\ -\x8d\x8dbJI\x8d,X($\x14\x0b!)%;\ -eq\xcb\xf0c\xf8\x09\xde\x95\xad\x85\xb2\xb1\xb1`c\ -cc\xe1\xbb:\x9d\xb9\xf72x7_\xefw\xcf\xf7\ -\x9c\xf7\x9e\xd3\x81\x14I:\x95\x94K\xfb\x9e\xa6\xc4\x01\ -I\x1d\xc0!0\xf7/@`\x15h\x02v\xeb\x056\ -\x84\x0d\xfb\xcd\x07\xa0\xc7Z%\xe7\xdc\xed_\x12\xcex\ -0\x80\xbdz\x12&\x017\x03_\x91\xd4\xfb+\xa0\xa4\ -\x22P6\xfbl\xb5\x11\xd8\x0e\xd6\x95$u\xfd$\xe1\ -\x06\x9f\xe7\xfa\x0eL\x02\xaf\xd6_\x97T0\xd8(p\ -\x03D\x99@Iy`\xc5\xec\x95s\xee\xce\x1bj\x03\ -\xd6\x0cv\x0d\x14\x80yI\xd3Y\x09\x17\x80v\xe0\x0d\ -8\xb3^\xe4\xa5\xdc\xf7`\xb1\xaa\x92\x9a\xd3\x80\xf1e\ -\x5c8\xe7\x9e\x00\x9cs/^\xca\xce\x00\x06\xd0\x0f\x1c\ -\xd4\x00%\x8d\x00\xe3\x96\xe6<\x18\xf2S&\xe9HR\ -_\x98p\xcb\xea=p,i\xca6\x9a\x05.\x81\xc7\ -\x0c`\x1e\xa8~\x01\xed\xf6\x96\xcc;`\x07\x980?\ -\x06,\x02\xc3\x19@\x80\xb2\xa4J\x9cp\x19h\x09\x16\ -\x14\xad\x0e|\x03\xf2\x15Ij\xcdQ\xfb2\x00\x06\xad\ -\x0e\xd5\x01\xec\x06N>\x00o\x01\x5c\xe2;\xefo\xbb\ -\x00\x00\x00\x00IEND\xaeB`\x82\ -\x00\x00\x01u\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x0b\x00\x00\x00\x10\x08\x06\x00\x00\x00\xc0\xbd\x85~\ -\x00\x00\x01\xcfy\xce=g\xa2!\xc9n\x5c\xc3!\xfc\ -\xc2F\xfc\xc0\xcd\xaaz\xaf\x13\x1eO\xf22\xc9i\x1d\ -\x92\xcc%YJr\x0e&I\xb6c\x11g\xaaj\xc5\ -\x14\x92l\xc6s\x5c\x18p\x19\xb7\xd6\x13BU\xfd\xc6\ -%\xdc\x18p\x0cO\xd6\x13v\x05\xaf\xb1m\x06?\xab\ -j\xb5\xb5\xdc\x87\xa3X\xc6a\xec\xac\xaag\xad\xe6\xdb\ -\x80\x17IN\xb5\x87\x19\xdci\xe7>\xb64\x93\x03X\ -\x19\xf0\x10\x0bIf\xab\xea\x03\x96\xb0\x80/U\xf58\ -\xc9&\xdc\xc5\xed\xa1\xaa\xfe\xe2js\xd3\xfe\x7f\x11\xef\ -Z~\x1d\x0f\xaa\xea\xfb\xd0\x06x\x85!\xc9\x0e|\xc5\ -,\xc6\xed\x9c\xc0S\x18\xba\xa1\x971\xdfo!\xc9A\ -\xbc\xa9\xaa\xb5q\xa0\x11\x8fp\x0f[\xb1\x17Gp\x12\ -WF\xc1d\xcai\xb1\x85k\xed\xdeSUs#\xdf\ -;\xc3.\xec\xef\xf2?=9-\xfe\x88U\xfck]\ -7\xf4\xe40%>\x8f\xb7\xf8\x8cO8\xdb\x93\xff\x01\ -?\x07g7v\xdb#C\x00\x00\x00\x00IEND\ -\xaeB`\x82\ -\x00\x00\x01\x03\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x13\x00\x00\x00\x11\x08\x06\x00\x00\x00?\x98\x97\xc7\ -\x00\x00\x00\xcaIDAT8\x8d\xed\xd2=J\x03Q\ -\x14@\xe1od2\xa6\x11W\x90F\xec\xd2Y\x84\x08\ -.!\xe0\x02DHe\xe1n\xa6\xb2Nm'$\xa5\ -\x16YA\xba\xb1\xb0\xb1\xc8\x16\x04GL\x8a\x99\xe0\xf8\ -\x08f^\xb4\xf4\xc0\xe5\x15\x17\xce\xbb\x7fIQ\x14\x0f\ -\xb8\xd0\x9e\x15\xae1\x0b\x13)Fx\xc6\x02\x07;D\ -=\x0cq\xba-\x99\x22\xc1\x13n[Tu\x82\x17\x5c\ -\xa1\xdfp\x1ca\x99\xb6\x104\xf9\xa8\xdfA\x1d\xdf\xd8\ -\xd5V\xc8\xab\xaa\x930\xee\xf0\x16+\xfb\x89\xf7\xb0\xcd\ -.&\xf5o1\x9cQ\x0d\xaf\xc9\xa1j\xbb\xe3H\xd9\ -\x14\xf9\xb6\x05\x94\xb8\x8f\x94\x1d#\xff\xcb\x99Eo\xf3\ -_\xf6%\xfb\xfc\xa5\xa7D\xb69\x8dKt\x90\xed)\ -K6\xb29\xceq\xd3H\xae\xf6\xa8\xecq\x0d\xfe\xb1\ -\x1c=z\xc7\xebp\x00\x00\x00\x00IEND\xaeB\ -`\x82\ -\x00\x00\x01)\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x12\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1b\x06/\x5c\ -\x00\x00\x00\xf0IDAT8\x8d\xd5\xd2/K\x83Q\ -\x18\x05\xf0\xdf\xe6\x9a`0h1\xbb&\x13\xee'\x10\ -\xf4KX\xd4l\x10\xecV\x99E\xa3q3\x1b\xd4b\ -5\x18\x9f0\x0d6\x83`S\x04\xa3 \xce\xe0\x8b\xbc\ -\x5c\xdc\xdd\x16=\xed\xdc?\xe7\x1c\xce\xf34\x22bh\ -4\xeeRJ\x9d\xc2\xfd/\x9a\x93<\xfa\x9fB-l\ -\xd7\xf8:^0\xa8\xf8\xdb\xa4B\x8d:\x89\x88\x1e\x06\ -)\xa5\x93\xec|\x07\x07\x05\x9d\xe7V\xc9%\x22\xf6\xd1\ -\xc7\x1c\xeeG\x88\xb5\xd1\xcd\x13]c\x15\xef\x18b\x09\ -\x9f\xb8\xc40\xa5\xb4\xf5\x87Y\x07\x17y\xa2W\x9c\xe3\ -\x0a\x0b\xd8\xc5)\xe6\xb1RJ_\xec(\x22\x9a)\xa5\ -\xaf\x88\xd8\xc3qA\xe7)\x8f\xd9\xab>M\x8db\xd9\ -5\x83\xb1\x89\xc6M\xed\x01\x87\x15\xedOS\xf626\ -#\xe2\xc8\xcf\xd6\xcf\xe0\x0c\xb7x,\x99\xe6B\x1b\x98\ -\xc5G\xc5o\xd0\xc5\x22\xd6*\xf7\x1cm\xb2\xa9\x8d\xc2\ -$\x9b\xfd\x0d1\x8aV\x95q\x1f\x8eP\x00\x00\x00\x00\ -IEND\xaeB`\x82\ -\x00\x00\x02\x01\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x11\x00\x00\x00\x14\x08\x06\x00\x00\x00k\xa0\xd6I\ -\x00\x00\x01\xc8IDAT8\x8d}\xd3\xcf\x8b\xcdQ\ -\x18\xc7\xf1\xd7\xdc\xaeD\xc9(4\xca\x1d\x1b\x16\xc4\xea\ -\xa2\x98\x85\xc5\x10eAhJj\x84\xf8\x0b\xb0\xc4\xca\ -\x86\xa4&c\xd6\xb2\xa04%\xc9\x8f\xe4\xc7$\xc4\xbd\ -+3S\x16\x16D\x94_%\xc5\x8c\xb8\x16\xe7\xf96\ -\xdf\xf9\xba\xdf9\x9b\xcfs\xcey\xce\xfb<\xcfy\x9e\ -\xd3\xd1j\xb5\xb4\x1b\xcdf\x13\x06q\x1c?by\x1f\ -&p-\xef\xdb\xd1h4\xdaBb\xf4c>\x06b\ -~\x13\xfb\xf19\xefT)9\xbc+\xf4\x0a6\x87=\ -\x0b\xbf\x8a\x802\xc8\x06\x5c\xc5JLb\x07:\xb1\x08\ -\xbbs~\x8bq\x06\xab\xdbAN\xa2\x8a\x13\xb9\xb5\x87\ -x\x1f\xba0\xa2\xbb\x8e\xa7\x18+B6bk\xd8}\ -\x11\x0d\x5c\x08\xdd\x84\xb3x\x80\x1e\x0c\xa3U\x84d\xb7\ -\x7f\x88T\xb3\xf9eSo\xb1\x0d\x7f\xf07;\x94\x87\ -\xac\x8b(\xbec\x8b\xf4\x1e}X\x8e\x9f\x18\x0a\xbf/\ -\x91Rov>\x0f9\x1a:\x841\x5c\x8a\xfdc\xb1\ ->\x18\xe0\xf31\xdf\x89&\xb6g}\xd2\x8d\xd7\xb1\xd9\ -\x1d\xe9\xac\xc2\xa8T\xd6\xa5\xf8\x8a\xf5x\x9e\xbbx6\ -\xe6f\x91\x1c\x92*2\x1c\x00\x18\xc7]\xcc\x91\x9a\x0e\ -\xe6\xe1H\x0e2\x81o\x95\x08\xf9@.\xe4\xfc\xb8\x18\ -z0\xf4I\xf8N+HEj\xae\x1a\xde`\xa4\x00\ -\xb9\x15i\xac\xc1\x0a\xe9\x81\xefDZ\xd3 \xbda\xdf\ -@\xf17N\xc6!R\xc5\xe0\x14\x9e\xe5\x9d\xaa\xe8\x0a\ -\xfb\x95\xf6c<\xb4\x06\xf5z\xfd?\x87\x8a\xa9&\xaa\ -\x95@\x96\x85~,\xd9W\xc1\xbd\xb0\xfb\xb1\xa0\xb0\xbf\ -\x04{\xc2\xbe?\x13d\x04\x8f\xa5\xb4nc\xad\xf4\xed\ -{\xa4\x12wJ\x9f\xede\x19\xa4\x1a\xba\x17\x8f\xa4W\ -\x7fQ\xf0\x19\xc5\xe12@\x16\x09\xbc\x8b\x08\xce\xe1-\ -~K\x1d|Zj\x81O3A\xfe\x015\x8de<\ -wk\x85?\x00\x00\x00\x00IEND\xaeB`\x82\ -\ -\x00\x00\x01\xba\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x15\x00\x00\x00\x10\x08\x06\x00\x00\x00\xf9\xda4%\ -\x00\x00\x01\x81IDAT8\x8d\xa5\xd1M\x88\x8ea\ -\x14\xc6\xf1\xdf\xfb6>\x92\x92|Dij4\xa1\xec\ -8\x1b+5\xb1\x18f\xa1f\xc5J1\xc3DVR\ -H!+;\x14\xc9J\xd2lf\xe3\xabdg)\x97\ -\x94\xb2\xb1 e\xc9\xdeJ\x16\x9eW\x8f\xe9\x19\x93q\ -V\xe7>\xd7\xb9\xfe\xf7\xb9\xef\xd3\xb3\x84H\xd2\xc3.\ -L\xe0 f\xaa\xea\xcd@\xef/`\xda\x94d\xef_\ -\xb8}\x5c\xc0e\xacn\x03ah\x01\xd3q\xec\xc1\xcb\ -\x05\xf4Q\x8c\xe1\x1df\xbbn\x9c?e\x1fS\x18O\ -\xb2\xbdC_\x87\xc7\xb8\x86\xdd\xb87\xbf\xa7k\xd2q\ -\x0c7\xf9\x19\x9cj\x01\x97\xe3\x01\xceV\xd5\x93\xa6\xfc\ -m\xd1Iq\xb2\x95\x1fM\xb2\xb6\x01\xf6p\x15\x17\x07\ -\xc0$\x9b;\xfc\x7fB\x93\x0c\xe3@\xab\xb4\x0a\xd3M\ -^\xb8SUo[\xfaX\x92\x1d\x8bM:\xd5Q;\ -\x9dd\xa8\xaa^W\xd5\xe7$\xd3IF\x1am\x16\x97\ -\x92l\xe8\x84&\x19\xc2\xb1\x8e\xd7l\xc1d\xd33\x83\ -\xbb\xb8\x01U\xf5\x03\xd71\x97d\xe5\xc0\xd0kA'\ -1\xd7\x01\x85W\xb8\x8f\xdb\xad\xdaDU=k\xbc7\ -\xb1\x11\x87\xd1kC_`\xff\x02\xd0\xae\xf8\x88\x9dU\ -\xf5=\xc9\x1a|@\xf0\xb4\xdf\x00G\xb1\xef\x1f\x80\xb0\ -\x15\xe7\x9a|\x19>\xf9\xb5\xe4m\x83?\x9d\xd6\xfa\x8a\ -\x7f\x88\xf3IF\xaa\xea+\xae\xe0=FzIV\xe0\ -\x0b\xd6/\x01\x0a\x8f\xaa\xea\x10\xbf\x97=\xd6Kr\x04\ -\x0f\x97\x08\x1c\xc4xU=\x1f\x1c\xfa8\xf1\x9f@\xb8\ -\xd5\xbc\x18\xfc\x049\xa0\x7f\x85\xe9\xdfLL\x00\x00\x00\ -\x00IEND\xaeB`\x82\ -\x00\x00\x01\xb8\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x11\x00\x00\x00\x12\x08\x06\x00\x00\x00\xbd\xf95T\ -\x00\x00\x01\x7fIDAT8\x8d\x95\xd3;hTQ\ -\x10\xc6\xf1\xdf\xbd((jv;\x05+\xc1\xad\x04!\ -0\x8d\x8d\x16\x82\x88H*A\xd2\xd9\xf8\xa8\x04\x1b5\ -\x82\x9d\x06;\xed\xc4B\x10\x0b\xedl$\xb0`e\x93\ -\x22\x0e\xda\x1bS\x89/\x10\x82\x16\xc1g\xb4\xc8\x89\x5c\ -\xd7\xbb\xbbf\xe0p\x98\xef|\xe7\xcf\xcc\x1cN\x95\x99\ -\xbd\x88X\xb4\xc1\xc8\xccI\x5cA\xa7\xca\xcc{\x98\xc6\ -\x02nF\xc4\xa31\x97\x8f\xe1\x01:E\xba[ef\ -\x0f/\x1b\xbek\x11qu\x0ch\x19\xdd\x92\xee\xadK\ -+\xcbE\xf8\x85'c\x00w\x0a\xe03>F\xc4R\ -]\xce\xfa\x98\xc3\x0f\xf43\xb3;\x04p\x02\xa7\xf18\ -\x22:8\x05\xeb\x903\x11q\x1c\xfb\xf0\xd5\xda|\x06\ -\x01{p\x1f\xd7#b\x0a\x22b\x0e\xaa\x16\xf3v<\ -\xc3+\xac\xcf\xa6\xc6C\xcc\xb4\x0d\xfe\x1fH\x03\xf6\x0d\ -\x9b\x1b\xd2\xdb\x88\xd8\xdd\xe6\xad\xdb\xc4\x12+\x03\xf9\xf7\ -a\xc6Q\x90\xff\x8eQ\x90\xc1\xb3m\x1b\x82d\xe6I\ -\xac\xe2ic\xc9\xcc\x1bm\xfe\xb6\xd7\x99\xc5y\xf4\x22\ -\xe2]C\xdf\x82\xf7\xd6\x9e\xffhD\xac\xfeUIf\ -\x1e){\x1f\x971\xdd\x04@D|\xc1A\x1c\xc6R\ -f\xee\xcc\xcc\x99?\x95d\xe6\xa7R~\x17\xb7\x22\xe2\ -\xc2\xb0\xfe3\xf3\x1cn\x17\xffJD\xec\xa8\xca\x97~\ -^<\x1f\x22b\xd70@\x81L\xe05&\x8at\xa0\ -\xc6\xc5\x86gkf\x1e\x1a\x05\xc1$\x16\xf1\xb3\xe4\x97\ -\xaa\xcc\x9c\xc7\x1b\xccF\xc4\x8b1\x80fE\x9bp\x16\ -\xfb\x7f\x03$D\x8d]u\xca0\xbc\x00\x00\x00\x00I\ -END\xaeB`\x82\ -\x00\x00\x04\xe6\ -<\ -?xml version=\x221.\ -0\x22 encoding=\x22UTF\ --8\x22?>\x0d\x0a\x0d\x0a Set object h\ -eight 1\x0d\ -\x0a \ -\x0d\x0a \x0d\x0a \x0d\x0a \ - \x0d\ -\x0a \x0d\x0a \x0d\x0a\x0d\x0a\ -\x00\x00\x01h\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x0c\x00\x00\x00\x10\x08\x06\x00\x00\x00\x22a\x9e\x07\ -\x00\x00\x01/IDAT(\x91m\xd2!H\x9dQ\ -\x14\x07\xf0\xdf\xf7=\xf0\xa5!\x82\x93\x85\x85\x81E\x96\ -\x0c\x074mma\xb0\xf0\x94\x19\xb5Y\xc4<\x1cC\ -\x04\xe3\xb3\x8a\x0b\xa6\x85\x85\x19\x1e\x0c\x8b\xc50\xb4\xdd\ -&cF\x8b\x08o,\x092\xa6\x8c\x85w\x95\x8f\xbb\ -\xef\xa4{\xcf\xff\x9c\xff\xff\xfc\xcf\xbd\x95\x96H)=\ -\xc5\x17\xbc\x89\x88_M\xacn)\xee`\x0f\x17\xd8(\ -\xf1\xaaQ8\x89>z\xe8\xe0;\xa6\xf1\x0d[\x11q\ -\xf6\xa0\x90R\x9a\xc1\x0f,c\x1cG\x111\x8f)\xec\ -\xe3 \xa5\xb4\x04UJ\xa9\x9b\xe5\x9f4\x94\xb7#b\ -\xb3\xa1>\x85\x13\xf4j\xac`\xa2\x18\xf5\xb2y\x89\x88\ -!\xde\xe1C\x8d\xb7\xe8\x16\x0d\xbfK\xb38\xc4\x5c\xdd\ -\xc2\xde\x1a\x11q{o\xfa\xbc\x05\xaf\xcaD\xf6qS\ -\x1b\xed\xfc\xba\xc0\x1f\xb7\x90\xac\xe1\xa0\x8e\x88S\x1c\xe3\ -O\x03|V\xb0/b\x01;UN\x8c\xe13^\xe1\ -\x11\xce\xf2\xf99V3\xc1bD\x5cV\x05\xd3\x1c\xd6\ -\xf1\x1a?q\x87M\x0c\x22\xe2o\xab\xb9\xdc\xd8\xc7\x0b\ -|\x8a\x88\xdd&\xf6\xdf\xe7\xcb\xf1\x1e_\xf1\xb1\x04\xee\ -=\xcc\xe2\xa5\xd1\x9bt\x8d\xfeP'/b\x98G\xbb\ -\xc2\xe0\x1f\x06\xdbU3\x9dA\x19\x09\x00\x00\x00\x00I\ -END\xaeB`\x82\ -\x00\x00\x01O\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x13\x00\x00\x00\x12\x08\x06\x00\x00\x00\xb9\x0c\xe5i\ -\x00\x00\x01\x16IDAT8\x8d\xe5\xd4=/DA\ -\x14\xc6\xf1\xdf\xae\xcd\x8d\xd7H\xd8\x88\xc6&tJ\x89\ -B\x22\xdb)t(\x84\x8f\xe0\xa5\xf09T:\x85\x1a\ -A\xa3Pjt\xbe\x00\xb2\x05\xd1\xa0\x14B\x16\xbb\x89\ -(\xee\xacl.\xb9w\xb3JOu\xe6\xccs\xfe9\ -3g2\xb9J\xa5r\x8e)\xed\xe9\x18\xcb\xa8A\x01\ -\xe3a\xe3\x05\xcf(\xe2!\x050\x84W\xf4a\x01\x07\ -\x0d`!\x18\xea(a\x04\xdb(\xa7\xc0\xf6\xb0\x8f+\ -\x9c\x06\xe0!\x96\xf2\xc1P\xc5S\xabg\x0b\xba\xc5l\ -\xa8\x9b\xc7Q>\xdd\x9f\xa9kl\x84x\xae\xf0\x8b\xa1\ -\x88\xc5\x14@)\xb1\xde\xc5\x16\x06\x92\xb0{\x9ca\x06\ -\x11z\x9a\xf6\xde\xf0\x8eK\xf1}5\xf4)\x1e\xc8\x0f\ -\xd8#VS\xbaJU\x12\xd6\x8b\x15td\xd4U\xb1\ -\x83\x8f\xe6dr\x00\xa3Xo\xa1\x895Lfu\x06\ -w\xd8\xcc\x80\x95\x91K&\xff\xfa4\xfe3\xac\x0b\x83\ -m2\x22\xf1\x0f\xf2=\xcdH\xfc\xedT\xd1\x89\x9b\x0c\ -\xc00&\xc4\xef\xb1?\xd4\xd4\x0a\xb8\xc0t\x00F\xc1\ -<\xd6BG\xddMq\x1d'_\xecY0\xc6f\xd8\ -\x84\x84\x00\x00\x00\x00IEND\xaeB`\x82\ -\x00\x00\x01/\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x08\x00\x00\x00\x10\x08\x06\x00\x00\x00+\x8a>}\ -\x00\x00\x00\xf6IDAT(\x91m\xd0=+\x86\x01\ -\x18\xc5\xf1\xdf\xf3\x84\xb2\xb0\x89\xf4$\xe4\xa5\x8c\xae\x12\ -\x8b\x922\xd9\x18\x14\xa3\x85\xd5\x8a\xcf`\x90\xcd\xcb&\ -e\x91\xcc>\xc0UH^V\x93A\x8aE\x8a\xb0\xdc\ -wn\xe5l\xd7\xe9\x7f\xaeN\xa7\xa6Pf\x0e\xe1\x1c\ -w\x98\x8e\x88/\xa8\xfb\xd5\x22v\xd0\x8e\xd1\xd2\xac\x02\ -\x9fh\xa0\x05\x1f\xa5\xd9T\x01\x0ep\x8dK\x5c\xfd\xf7\ -\xe1\x15\x0f\xb8\x8d\x88\xef\xff\x80u\x0cb&3;\xff\ -\x00\x99\xb9\x899\x1c\xe1\x19W\x999\x09\xb5\x02\xb8,\ -\xfa\xacb\x1e\xb3h\xc5[Sfv\xa1\x1f\x138\xc4\ -MD\xf4\x14\xc1\xaezQn\x19Cx/v\x00\x11\ -\xf1X+\x8f\xcc\x5c\xc2\x02\xc60\x1c\x11O\xd5\x92\x0d\ -\xac\xe1\x0c7\xb8\xc8\xcc6\xa8gf3\xb6\xd1\x8bc\ -\xec\xa3\x03\x93\xe5\x92\x1b\xf8\xc2xD\x85\x9fX\x87\xdbU\x95uc\x11\x97\xca~\x0f\ -L\xe2\x03:\xaa\xc8&p\x00\x9f\xb1'~o\xc5\xd1\ - \xf8\x1e\x1d\xec\xca\x93\xd5\xd1\x17\xfey\xf4\x87?\x8d\ -\xe7-\x84u\xdc\xc0\xee\xc8\xe9\xc7\xeb\x88\x1dA_\x0d\ -\xab\xf1\x02\x9bsU\x5c\xc1}\xcc\xa0\x177q(\xda\ -k\xc5(\xae\xe3G\x863\xd8\x88\xf7\xf8\xaa\x1dk\xd1\ -\x89_xT\x10\xef\xc5\x02F2I\xa7\x078\x8b\xb7\ -\xb9\xc4\x83\xb8\x16\xf6\x02\x8e\xe3[.\xe72\xb6b2\ -\x93\xf6iTZ\xceV\xec\x97\xa6\xda\x90\xb4|\x22\xad\ -\xc2>i\x00+8-i9\x90I\xda\xac\xa0\x81\xc1\ -hk\x18\x87\xb1\x1c\xb1\xf1x\x9f\xf5g\xff\xaeb\x1e\ -\xe7h_\x8d\xa6\xa4\xcdX\xb4\x9e?\x9f\x8b\xd1\xd2\x89\ - \xf9K\xe3<\xd9;\xec\x95v\xa8\xec\xd4j\xd2d\ -{\xf2dE\xe7\xb4\x05C\xd2\x94\x8ap\x17\x17\x8a\x02\ -Ed$]f\xc3\xde\x86\x0d\xd2\xad~\x91$(-\ -\xb9\x0a\xc3\xb8\x855x\xa9\xfd\xbc\xfe\x8bl\x08\xa7\xa2\ -\xca)l\xafJ\xfe\x0dZUP\xe3\xae\x0f\xedJ\x00\ -\x00\x00\x00IEND\xaeB`\x82\ -\x00\x00\x01\xfc\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x17\x00\x00\x00\x12\x08\x06\x00\x00\x00\xb0\xe7E\x13\ -\x00\x00\x01\xc3IDAT8\x8d\xad\xd4\xcd\x8bNa\ -\x1c\xc6\xf1\xcf\x19/y\x9d\x85\x97\x14)\xa4\xcc\xc8\x82\ -\xe6\x96\x14EY(Rd\xa3\x89$\x8d\x05\xe5e\x1a\ -ec\x83\xb2\xb2\x90\x8d\x8d\x05v\x96vVVV\xd7\ -)\x7f\x02\xf2\x0f\xc8[\x8a\x1e\x8b\xe7\x9czL\xe7\x99\ -\x19q\xd5\xa9\xfb\xba\xbb\x7f\xdf\xdf\xd5\xef>\xe7T\xbd\ -^\xcfBT\xd7u\x85\xb3\x18\xc7G|\xc6\xb3\x89\x89\ -\x89\xa1\x80\xc5\x0b\x22\xf7u\x1d\xebJ)\xb7 \xc9X\ -\xb3\xf7`X\xc1HUU\xba\x9e\xba\xaeo\xd7u\xbd\ -\xac\xf5\xf8\x81WIv'9\x84\xefX?\xac\xbe\xaa\ -*#]\x1d\x93\x8cb\xa6\x19\xc3\x1f*\xa5\xbc\xc5[\ -\x9c\xd4\x1f\xcfPu\xc2q\x0e\xab0\x9d\xa4=\xf3\x0b\ -cI.b\x0b\xde\xe9\xcf}\xe1\xf0$\x15.7v\ -\x07\x8e5\xeb\xc7\xf8\x86\x8d8\x82Q<\x9b\x0b\xdeu\ -\xa1\x8716\xe0o\xe2e)\xa5\x87\xa7\x1daV\x96\ -R\xbe.(9\xae\xcc\xf2\x07\x92\xec\x9d#\xe0\xda$\ -\x17\xe6\x85'\xd9\x8c\x13\x1d\xe7ff\x9d\xdb\xde6,\ -\xa5|\xc0\xd2$\xa7\xe7K~\x09\x8b:\xe0\xa7\x92l\ -m\xc1x\x8d'I\xda\xb1>\xc6T\x92\x83\x9d\xf0$\ -K1\xd5\x01\xd64\xbc\x91dg\x03\xde\x84]\xb8\xd1\ -\xa4\xef\xe1\x1a^$\x19o\x8b\xaa\x01\xf8$\x9e\x0f\x81\ -\xc3W\xfd\x0fg\xdd\xc0\xde7\xec,\xa5\xbco\x18\xf7\ -0\x893\xf898\x96\xcb\xe6\xd6\xcaY`X\x81G\ -\x03\xfe.\x96\xe0\x0d\x0e\x8e4\x1d\xf7`\xff<\xf0a\ -:\x9e\xe4d\xb3\xde\xd7\xc0a[\x9b|\xf6\xeb\xf7\xb7\ -z\x98du)\xe55\xb6\xe1\x0e6TI\xd6\xe8\xff\ -#\x96\xffc\x83\x07\xa5\x94\xe9\xd6$Y5\x82\xf3\xff\ -\x01\x0cW\x93\xecnM)\xe5\xcbb\xfd\xdb\xfd\xf4\x1f\ -\xe0p\x1fG[\xf3\x1b\xdb,\x90K\x95\x7f\xdek\x00\ -\x00\x00\x00IEND\xaeB`\x82\ -\x00\x00\x01\xb8\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x15\x00\x00\x00\x0e\x08\x06\x00\x00\x00\xc0\x06W\xce\ -\x00\x00\x01\x7fIDAT8\x8d\x8d\xd3\xbdk\x15Q\ -\x10\xc6\xe1g\xaf\x17EQ\xd1\x18E\x04\xb1\xd2F\xcb\ -\x01k\x0b\xed\x82\xa4NH\xa1EH\xa7]\x08\xa2H\ -\x04M\xa5\x85 \x8a \xe2_ X(\x08\x8aU\xc0\ -)\xc5\xc2&\x85\xe2g\xe7G\x22\x92\x0f\x8b\xdd\xab\xeb\ -\x82\xbbw\xba3\xf3\xce\xef\xcc9\xe7=\x85Fd\xe6\ -fLa\x0cG\xb1\x17[\xd1\xaf$k\xf8\x81\x0fx\ -\x81k\x11\xb1Tg\x145\xd8q\xdc\xc11\xf4\x9a\x9b\ -u\xc4\x1bLF\xc4\xcb?\xd0\xcc\xbc\x8b\xb3\x0d\xe1\x0a\ ->\xe3#~V\xb9-\xd5\xe4\xfb\xb0\xa3\xa1\xdf\xc0\xa5\ -\x88\x98/2\xf3\x02\xe6k\xa0\x07\xb8\x12\x11o\xdbF\ -\xcb\xcc]\x98\xab\x86\x19\xa9\x95\xc6\x8b\xcc\xfc\x86\xedx\ -\x84\xd3\x11\xb1>\xd4\x81\xff\xdd`\x12\xd71\x8awE\ -fn`-\x22\xfa\xed\xad\x9d\xe0Sx\x82\xf5\xc1\x83\ -l\xca\xcc\xd7\x999\xd2\xd27h\x9e\xce\xccC\xb5\xf5\ -\x91\xcc|\x8e\xc7U\xaa(2sYi\x19\xf8\x8a=\ -\x11\xb1\xda\x00\xf5q\x15\xd3\xca\x07\x9a\xc5+,(m\ -W\x8f\xef}\xdc\xc6\xb9*\xb1\x13\x13\xb8_\xc1F\x95\ -6\x1b\xf3\xd7\xa7p\x11\xdb\xfes\x98\x87\xbd\x888\x8f\ -\xa7\xb5\xe4\xfe\x0a8\xa3\xb4\xd4x\x03\xa8\x05\xf8\x1eg\ -z\x10\x11'1\x83/\xaa\xab\x88\x88[\xb8\xa7\xf4_\ -W\xac\xe2\x19\x0eG\xc4\xaf\xa2K\x9d\x99\x07\xb1\x88\x03\ -\x8d\xd22\x96\x94_\xf5rD|\x1a\x14:\xa15\xf8\ -\x14n`7f#ba\xd8\xdea\xe073\xf3D\ -\x9b\xe67\xefB~?\xd8\xe7\x90V\x00\x00\x00\x00I\ -END\xaeB`\x82\ -\x00\x00\x02\x0e\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00\x12\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1b\x06/\x5c\ -\x00\x00\x01\xd5IDAT8\x8dm\xd3M\x88\xceQ\ -\x14\x06\xf0\xdf;\xc6\x82)\xb10jl|5\x92\x8f\ -1u\x94\x90\x95\x95\x9a\x94\x12j2\x09[\x1a6,\ -H6\xa3|\x84\xcd\xa4h\xb2\xd1\x88\x99\x85\xaf\x86\xa4\ -\x88l\x8ef\x8a\x15K\xb3@hR\x94\x91X\xbc\xd7\ -\xf4\xce\xbf9u\xeb\x9e\xf3\x9c\x9es\xces\xef\xa9e\ -\xe6\x1cl\xc3hD\x8c\x9b\xc12\xb3\x0fK\xd0\x1d\x11\ -\x7ff\xca\xa9e\xe6\x03\xcc\xc5j\xb4G\xc4Df\x1e\ -\xc2A\xec\x88\x88\x8f\x999\x86\xa5h-g/\x1eF\ -\xc4\xdb\xffDMh\xc7\x1d\xfc\xc5\xfc\x12_\x8cuh\ -)\xfe0\xceD\xc4/\xdc,\xd8\x93\xc6\x8e\x9a\xb0\x1f\ -[\xf1\x1c\x9b!\x22N\xe3\x18\x96\x97\xbce\xf8Z\xee\ -\xdf\xb0\x16\x9f\xa7\x11E\xc4\x8b\x88\xd8\x8d\xe38\x95\x99\ -\x07\x0a6\x80\xdd\xe5\xde\x82\xef\x99\xb9\x08kp\xf6\x7f\ -\xd1)\x8d\x1a\x9d\xcc\x5c\x88\x07\x18\x88\x88\xfe\xcc<\x82\ -\x11\x5cB?\x8e\xe2bD\xdc\xcd\xcc\x1az\x8b\xb6\xe7\ -\xa6\x11\x15\xb2\x16\xdc\xc6c\x5c+z\xacG'\x86\x22\ -b\xa4\xe4m\xc1u\x0caC\xad\x04[\xd1\x19\x11\x8f\ -\x8a?\x1b]\x111\xdcP`\x05\xc6\x11\xd8\xa4\xfee\ -6b\x14\xef\x9bK\xde\x05tg\xe63L\x94Xo\ -\xa5\xd9\x85\xb8\x887x\x8dA\xcc\xc3J\xdco$\x1a\ -\xc3\x95\x88\xf8\xdd\xd0EG\xe9b\x01\xda\xcah7*\ -\x05\xdeR\x11\xbb\xa2\xd5N\xec\xc2>u\x91g\xe1G\ -\x19\xe9\x9e\xfa\x83L\x15m\x9a\x81\xa0\x96\x99'\xd1\x83\ -\x9e\x92<\x88=\x11q\x19?q\xb5\xe83e\xd5\xe7\ -\xefB\x1f>\xa8\xaf\xc7d\x03\xf6\xb2h\xf4N\xfdC\ -\xdej\xdc\xbbf\xd3m;V\xa9/\xe7d\x05\x9b\xc0\ -y\xf5\xbd\xec\xa8.ou\xb4\xc3h\x8b\x88\xb1\xea\xc8\ -\xea{\xd8\x87/XQ\x05\xa7uT\xf4\xf84\x03\x09\ -\x9c\xc0\x19<\xc5\xab*\xf8\x0f\xdd\xdb\x9d,w\xcc\x1f\ -\xb4\x00\x00\x00\x00IEND\xaeB`\x82\ -\x00\x00\x04\xe9\ -\x89\ -PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ -\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\ -\x00\x00\x00\x04gAMA\x00\x00\xb1\x8f\x0b\xfca\x05\ -\x00\x00\x00 cHRM\x00\x00z&\x00\x00\x80\x84\ -\x00\x00\xfa\x00\x00\x00\x80\xe8\x00\x00u0\x00\x00\xea`\ -\x00\x00:\x98\x00\x00\x17p\x9c\xbaQ<\x00\x00\x00\x06\ -bKGD\x00\xff\x00\xff\x00\xff\xa0\xbd\xa7\x93\x00\x00\ -\x00\x09oFFs\x00\x00\x02\xc0\x00\x00\x00\x00\x00\x5c\ -]\xb9S\x00\x00\x00\x09pHYs\x00\x00\x0b\x13\x00\ -\x00\x0b\x13\x01\x00\x9a\x9c\x18\x00\x00\x00\x07tIME\ -\x07\xdf\x0c\x12\x0e\x1b\x0b$&IW\x00\x00\x00\x09v\ -pAg\x00\x00\x03@\x00\x00\x00 \x00\xbe\xe6\x89Z\ -\x00\x00\x03\xaeIDATX\xc3\xed\xd6]\x88UU\ -\x14\x07\xf0\xdf\x98\x8e\x96\xa8QIjA\x1f\x04BD\ -\xd0KQ\xf8\x12\x91\x11=\x04\xf5b'\x85\x8e\x88\x8d\ -i\xa7\x14\x02\xc3\xc2\xbe\xa0\xcc,8f\x1aa\xa7/\ -N\x11J\x05RP\xe1C\x1f\x86\x0f\xbe\x98(\x94\x1a\ -F\x94\x85Y\x98\xcd\x80:\xde\x1e\xf6\xbe\xce\x9e\xdb\xbd\ -3:MO\xb5\xe0p\xf7\xddg\x9d\xb5\xfe{}\xfc\ -\xf7\xe2\xbf.]\xcdE\x96\x17Oa\xc5(\xdb\x9f]\ -W\xe5'C)\x8cM\xd6+p\x02\x07p\xec\x1f:\ -\x9e\x82\x19\xb8\x1a\xa7\x0d\x00\x0e\xd4Uy\xc5h\x1c=\ -\xcb\x8b\x06N\x0e\xa7\xd7\x0a\xe0X\x07cS\xb0\x11\x1b\ -\xeb\xaa\xfch\x04``a\x8c\xcc\xea\xba*;\x02h\ -~\xb0\x16S\xf1\x07&`\x12n\xc7\xac,/\xde\xc5\ -\xf7Q\xb5\x0b\xefa:\xaeCo]\x95/%\xa6\x9a\ -5\xb6\x04k\x84\x14\x8f\xc9\xf2bU\x13D[\x00\x98\ -\x17\xd1\xf6cL\xb2\x7f!\xee\x8b\xc0\xc6\xe3\xec\x08\xe6\ -Z,C\x1fR\x00?dy\xb1\x00O\xa3;>\xcb\ -\xb0j\xc8\x08\xe0!\xcc\xc48\xfc\x88\x8bp\x17.\xc0\ -Y\xf1\x99\x8f\x8b\xb1\x07G\xe2i\x8f&6\x1e\x8b\xfa\ -\xeb\x92\xbdo1o\xd8\x14\xd4U\xf9J\x9b\xb4lC\ -\x95\xa4d\x0dz\xea\xaa\xdc\x89\x9dh\xad\x8d?\xf1L\ -\xf2\xffg\xcc\xaf\xabr{\xaa\xd4\xa9\x06\xee\xc0e\x06\ -\xaa\xb8\x0b\xbf\xe1~\xac\xc6\xb9B\x9b\xbd\x9d\xe5\xc5-\ -uU~\x99\xe5\xc5R\xf4\xd5U\xb9!\xcb\x8b\x1e<\ -\x19\xc16\x9d\xcf\xa9\xab\xf2\x8bV_\x9dR\xb0\x14\xb3\ -\xda\xec7\xe2\xd3\x1f\xd30\x11\x1fdy\xb1\x0c+\x85\ -\x22\xdb\x80\xf5-a\x9f\xdf\xce\xf9P\x006\xe2\xb3\xe8\ -,\x95cx\x1d7\x09\xc56\x1e\xe7\xc7P/\xc0\x8c\ -,/~O\xf4\x8f\x0a9\xdf\xde\xc1O\xc7\x1ax\xcd\ -\xd0\xf2j\x96\x17\xbdX+\x14\xdat\xbc)tLw\ -\xd4\xd9\x8f|(\xe7\x1d\x01dyq'.\xd5\x99\xc9\ -\xba\xf0\x0b\x1eF)\xb4\xe3\x84\xe4\xfd^<\x81\xc3\xc3\ -\x1c\xa4c\x0a\x1e\xd4\xbe\x06Ri\x08\xfd\xbcI\xe0\x8d\ -T\xd6\xc7\xc8\xcc\xc6\xae\x91\x00x\x03\xdb\x87\x89\xc0.\ -\xa1\x1d\x97\xb7y\xbfR`\xbfm#\x8a@;\x1eh\ -\x95,/\x16\x09\x0c\xd7\x94\xc3\x02qM\xc2d\xa10\ -\x17c\xdf\x19\x03\xc8\xf2b\xb9p\x95\xa6\x11\xe8\xc2q\ -!\xbf\x87\xf0\x82\xd0\x05\xf0\x13\xee\xc1%x\xd6\x00O\ -\xbc\x95\xe5\xc5\xaduU~~\xa6)\xb8M\xfb\x1a8\ -.\xe4\xbe;\xd9\xfbF\xa0\xdd\x0f\xe3\xbbE\x06\xc8j\ -\x22\xde\xcf\xf2ba]\x95\x9b\xcf\x04\xc0\xa3\xf1\x04M\ -\x1eh\xa0W`\xc7\xc7\x13\x00G1\x17\x07\xe3o\x1f\ -\xb6\xc6\xc8\xad\x13:\xe3<\xbc\x98\xe5Eo\xbb\xab<\ -\x1d\xc9\x1a\xd8SW\xe5\x95\x1d\xd2r\xaf\xc0rM\xd9\ -\x8f\xb9uU~\xd5F\x17z\x84V\x9c\x1a\xb7\x8f\x08\ -t<\x08D[\x00\x09\x0f4\x84Ke\x1c\x9e3\x90\ -\xf3}x$\x86\xf9S\xc9< \xcc\x077\xe0F\xec\ -\x10Z\xb2\xf9\xddA,I\xd31\x1c\x0f\xf4\x0b\xfc\xde\ -\x9d\x80=\x89\xcbQ\xc7\xbd9\x06\xe6\x81\x13\xd8\x1d\xed\ -.\xc6\xddx@ \xabnL\xc3\xcbY^l\x1en\ - i\xf2@\xbfPd\xd7\x08\x83\xc8^a.\x98\x8e\ -\x9b\xe3\xfb\xdd\x06\xcf\x03\xdf\x09\x83\x0bL\xab\xab\xf2\xf9\ -,/~\x8d\xe9\xeb\x12\xae\xf0S\x8eN\x8b\x07\xb2\xbc\ -\x98\x1c\xc3\xbb\xa5\xae\xca\x1dq{K\xa2\xf2\xb5d\x1e\ -\xc8\xf2\xe2\xfa\xb8lD{\x9b\xb2\xbc\x18\x8b\xee\xba*\ -7\xa5\xb6[\x01\x8cI\x8ahr\xb2\xdf\x10\xfa\xfbP\ -\x043\x94\x1c\xc19q}\xaa\xc6\xea\xaa|'\xda\x1d\ -$\xad\x00f\xc6b\x1c-\x19D\xe5i\xe8\xdb\x01\xc8\ -p\x95\xbf\xcf\x00#\x95\x06>\x1e\xc5\xc3\xfc/\xff\x8e\ -\xfc\x05\x99&,\xa0:Dw\xab\x00\x00\x00%tE\ -Xtdate:create\x0020\ -15-12-18T14:27:1\ -1+00:00YM\xe3\xc6\x00\x00\x00%t\ -EXtdate:modify\x002\ -015-12-18T14:27:\ -11+00:00(\x10[z\x00\x00\x00\x00\ -IEND\xaeB`\x82\ -\x00\x00\x04~\ -\x00\ -\x00\x01\x00\x01\x00\x10\x10\x00\x00\x00\x00 \x00h\x04\x00\ -\x00\x16\x00\x00\x00(\x00\x00\x00\x10\x00\x00\x00 \x00\x00\ -\x00\x01\x00 \x00\x00\x00\x00\x00@\x04\x00\x00\x13\x0b\x00\ -\x00\x13\x0b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ ->\x00\x00\x00\xa1\x00\x00\x00\xd6\x00\x00\x00\xeb\x00\x00\x00\ -\xec\x00\x00\x00\xd8\x00\x00\x00\xa7\x00\x00\x00G\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x9e\x02\x022\ -\xff\x04\x10\x81\xff\x03#\xaa\xff\x02,\xbb\xff\x02-\xbc\ -\xff\x03$\xac\xff\x03\x12\x85\xff\x02\x028\xff\x00\x00\x00\ -\xac\x00\x00\x00\x12\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x0c\x00\x00\x00\xbb\x03\x08\x5c\xff\x02/\xcb\ -\xff\x00;\xca\xff\x00:\xca\xff\x009\xca\xff\x009\xca\ -\xff\x00:\xca\xff\x00;\xca\xff\x022\xcb\xff\x03\x09b\ -\xff\x00\x00\x00\xc9\x00\x00\x00\x13\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x98\x04\x08^\xff\x015\xca\xff\x00:\xca\ -\xff\x008\xca\xff\x008\xca\xff\x008\xca\xff\x008\xca\ -\xff\x008\xca\xff\x008\xca\xff\x00:\xca\xff\x018\xca\ -\xff\x03\x09c\xff\x00\x00\x00\xaf\x00\x00\x00\x00\x00\x00\x00\ -0\x00\x00\x00\xfd\x02.\xc8\xff\x00:\xca\xff\x008\xca\ -\xff\x008\xca\xff\x008\xca\xff\x008\xca\xff\x008\xca\ -\xff\x008\xca\xff\x008\xca\xff\x008\xca\xff\x00:\xca\ -\xff\x022\xcb\xff\x02\x027\xff\x00\x00\x00E\x00\x00\x00\ -\x92\x04\x0eu\xff\x00:\xca\xff\x008\xca\xff\x008\xca\ -\xff\x008\xca\xff\x008\xca\xff\x008\xca\xff\x008\xca\ -\xff\x008\xca\xff\x008\xca\xff\x008\xca\xff\x008\xca\ -\xff\x00;\xca\xff\x03\x13\x87\xff\x00\x00\x00\xaa\x00\x00\x00\ -\xce\x02\x1f\xa4\xff\x00:\xc9\xff\x008\xc9\xff\x008\xca\ -\xff\x008\xca\xff\x008\xca\xff\x008\xca\xff\x008\xca\ -\xff\x008\xca\xff\x008\xca\xff\x008\xca\xff\x008\xca\ -\xff\x00:\xca\xff\x03%\xaf\xff\x00\x00\x00\xdc\x00\x00\x00\ -\xea\x02)\xb9\xff\x01:\xca\xff\x088\xd1\xff\x098\xd1\ -\xff\x078\xd0\xff\x058\xce\xff\x038\xcd\xff\x028\xcc\ -\xff\x018\xca\xff\x008\xca\xff\x008\xca\xff\x008\xca\ -\xff\x009\xca\xff\x02-\xbd\xff\x00\x00\x00\xed\x00\x00\x00\ -\xe8\x02)\xb8\xff\x0d:\xd6\xff\x139\xdb\xff\x118\xd9\ -\xff\x0f8\xd7\xff\x0d8\xd6\xff\x0b8\xd4\xff\x0a8\xd3\ -\xff\x088\xd1\xff\x068\xcf\xff\x048\xce\xff\x028\xcb\ -\xff\x009\xc9\xff\x02-\xbd\xff\x00\x00\x00\xed\x00\x00\x00\ -\xcb\x06\x1d\xa5\xff\x1b;\xe2\xff\x1a9\xe2\xff\x189\xe0\ -\xff\x179\xde\xff\x159\xdd\xff\x139\xdb\xff\x129\xda\ -\xff\x108\xd8\xff\x0e8\xd7\xff\x0c8\xd5\xff\x0a8\xd3\ -\xff\x01:\xcb\xff\x03$\xad\xff\x00\x00\x00\xd9\x00\x00\x00\ -\x8b\x07\x0dr\xff\x22;\xe8\xff\x22:\xe9\xff 9\xe7\ -\xff\x1e9\xe5\xff\x1c9\xe3\xff\x1b9\xe2\xff\x199\xe0\ -\xff\x179\xdf\xff\x169\xdd\xff\x149\xdc\xff\x139\xdb\ -\xff\x07;\xd0\xff\x03\x11\x82\xff\x00\x00\x00\xa3\x00\x00\x00\ -(\x00\x00\x00\xfa\x1c+\xd7\xff,;\xf2\xff(:\xee\ -\xff&:\xec\xff$:\xeb\xff#:\xe9\xff!:\xe7\ -\xff\x1f9\xe6\xff\x1d9\xe4\xff\x1c9\xe3\xff\x1b;\xe2\ -\xff\x090\xd1\xff\x02\x02/\xff\x00\x00\x00;\x00\x00\x00\ -\x00\x00\x00\x00\x88\x07\x08[\xff,5\xf1\xff3;\xf8\ -\xff.;\xf3\xff,:\xf1\xff*:\xf0\xff(:\xee\ -\xff':\xed\xff%:\xeb\xff&;\xec\xff\x1c6\xe3\ -\xff\x04\x08]\xff\x00\x00\x00\x9f\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x05\x00\x00\x00\xaa\x08\x08[\xff)+\xe2\ -\xff8;\xfc\xff7;\xfc\xff4;\xf9\xff2;\xf8\ -\xff1;\xf6\xff/;\xf5\xff#/\xe5\xff\x06\x08`\ -\xff\x00\x00\x00\xbb\x00\x00\x00\x0b\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x88\x00\x00\x00\ -\xf6\x0e\x0ex\xff\x1e\x1f\xb8\xff)+\xda\xff)+\xdb\ -\xff\x1d!\xba\xff\x0e\x0f~\xff\x00\x00\x00\xfb\x00\x00\x00\ -\x96\x00\x00\x00\x0b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -+\x00\x00\x00\x8a\x00\x00\x00\xc8\x00\x00\x00\xe7\x00\x00\x00\ -\xe8\x00\x00\x00\xcb\x00\x00\x00\x91\x00\x00\x003\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0\x0f\x00\ -\x00\xc0\x03\x00\x00\x80\x01\x00\x00\x80\x01\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x01\x00\ -\x00\x80\x01\x00\x00\xc0\x03\x00\x00\xf0\x0f\x00\x00\ -\x00\x00\x03F\ -<\ -?xml version=\x221.\ -0\x22 encoding=\x22UTF\ --8\x22?>\x0d\x0a\x0d\x0a source contr\ -ol connected\x0d\x0a \x0d\x0a \ - \x0d\x0a \x0d\x0a\x0d\x0a\ -\x00\x00\x03J\ -<\ -?xml version=\x221.\ -0\x22 encoding=\x22UTF\ --8\x22?>\x0d\x0a\x0d\x0a source contr\ -ol - not setup\x0d\x0a \x0d\x0a\ - \x0d\x0a \x0d\ -\x0a\x0d\x0a\ -\x00\x00\x04~\ -\x00\ -\x00\x01\x00\x01\x00\x10\x10\x00\x00\x00\x00 \x00h\x04\x00\ -\x00\x16\x00\x00\x00(\x00\x00\x00\x10\x00\x00\x00 \x00\x00\ -\x00\x01\x00 \x00\x00\x00\x00\x00@\x04\x00\x00\x13\x0b\x00\ -\x00\x13\x0b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1c\x1a\x1c\ ->\x1c\x0f\x1b\xa1\x1c\x13\x1b\xd6\x1b\x1e\x1b\xeb\x19\x1d\x1a\ -\xec\x17\x0f\x17\xd8\x13\x05\x11\xa7\x0d\x09\x0cG\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00###\x0a#\x19\x22\x9e!$\x22\ -\xff\x18q!\xff\x0d\xb6\x1e\xff\x09\xd0\x1d\xff\x09\xd2\x1d\ -\xff\x0d\xba\x1f\xff\x16x \xff\x18!\x19\xff\x10\x05\x0f\ -\xac\x0f\x0f\x0f\x12\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00%&%\x0c'\x1b&\xbb\x1fK$\xff\x09\xcd\x1d\ -\xff\x00\xfd\x19\xff\x00\xfb\x18\xff\x00\xf7\x18\xff\x00\xf6\x18\ -\xff\x00\xfa\x18\xff\x00\xff\x19\xff\x0a\xd7\x1f\xff\x18P\x1e\ -\xff\x12\x06\x11\xc9\x04\x05\x05\x13\x00\x00\x00\x00\x00\x00\x00\ -\x00-#,\x98\x22I&\xff\x03\xe6\x1a\xff\x00\xfb\x18\ -\xff\x00\xf0\x19\xff\x00\xf0\x19\xff\x00\xf0\x19\xff\x00\xf0\x19\ -\xff\x00\xf0\x19\xff\x00\xf0\x19\xff\x00\xf9\x18\xff\x05\xf1\x1c\ -\xff\x18P\x1e\xff\x11\x06\x11\xaf\x00\x00\x00\x00.,.\ -0+.+\xfd\x08\xc8\x1c\xff\x00\xfb\x18\xff\x00\xf0\x19\ -\xff\x00\xf0\x19\xff\x00\xf0\x19\xff\x00\xf0\x19\xff\x00\xf0\x19\ -\xff\x00\xf0\x19\xff\x00\xf0\x19\xff\x00\xf0\x19\xff\x00\xfa\x18\ -\xff\x09\xd7\x1e\xff\x19\x22\x1a\xff\x0c\x09\x0cE3&1\ -\x92\x1dk%\xff\x00\xfb\x18\xff\x00\xf0\x19\xff\x00\xf0\x18\ -\xff\x00\xf0\x18\xff\x00\xf0\x19\xff\x00\xf0\x19\xff\x00\xf0\x19\ -\xff\x00\xf0\x19\xff\x00\xf0\x19\xff\x00\xf0\x19\xff\x00\xf0\x19\ -\xff\x00\xff\x19\xff\x16x \xff\x14\x07\x13\xaa3'2\ -\xce\x0f\xa5\x1f\xff\x00\xfc\x17\xff\x00\xf0\x17\xff\x01\xf0\x1a\ -\xff\x02\xf0\x1b\xff\x00\xf0\x19\xff\x00\xf0\x18\xff\x00\xf0\x18\ -\xff\x00\xf0\x18\xff\x00\xf0\x19\xff\x00\xf0\x19\xff\x00\xf0\x19\ -\xff\x00\xfa\x18\xff\x0c\xba\x1f\xff\x1a\x12\x19\xdc5/4\ -\xea\x07\xc2\x1a\xff\x03\xf9\x1b\xff!\xf27\xff%\xf2:\ -\xff\x1e\xf24\xff\x16\xf1-\xff\x0f\xf1&\xff\x08\xf0!\ -\xff\x04\xf0\x1c\xff\x01\xf0\x1a\xff\x00\xf0\x18\xff\x00\xf0\x18\ -\xff\x00\xf7\x18\xff\x08\xd1\x1d\xff\x1b\x1f\x1c\xed616\ -\xe8\x07\xc1\x1b\xff:\xfcO\xffT\xf5e\xffH\xf4Z\ -\xffA\xf4S\xff9\xf4M\xff1\xf3F\xff*\xf2?\ -\xff\x22\xf27\xff\x1a\xf10\xff\x12\xf1*\xff\x08\xf0 \ -\xff\x00\xf7\x17\xff\x08\xd0\x1d\xff\x1d \x1d\xed8.7\ -\xcb \xa1.\xffs\xff\x82\xffr\xf6\x80\xffi\xf6x\ -\xffb\xf6q\xffZ\xf6k\xffS\xf5d\xffL\xf5]\ -\xffD\xf4W\xff=\xf4P\xff6\xf3I\xff-\xf2A\ -\xff\x06\xfb\x1f\xff\x0b\xb5\x1d\xff \x17\x1f\xd9;2:\ -\x8b3i9\xff\x91\xff\x9d\xff\x95\xfa\x9f\xff\x8b\xf8\x96\ -\xff\x83\xf8\x8f\xff{\xf7\x88\xfft\xf7\x82\xffm\xf7{\ -\xffe\xf6t\xff^\xf6n\xffV\xf5g\xffS\xf5d\ -\xff\x1d\xfe5\xff\x13q\x1d\xff\x1f\x12\x1e\xa3><=\ -(262\xfa\x83\xc4\x8a\xff\xbf\xff\xc7\xff\xac\xfa\xb4\ -\xff\xa5\xfa\xae\xff\x9d\xf9\xa7\xff\x96\xf9\xa0\xff\x8e\xf9\x99\ -\xff\x87\xf8\x92\xff\x7f\xf7\x8c\xffx\xf7\x85\xfft\xff\x83\ -\xff(\xce9\xff\x1f' \xff!\x1e!;\x00\x00\x00\ -\x00>;>\x88DME\xff\xbd\xe3\xc2\xff\xdb\xff\xdf\ -\xff\xc7\xfd\xcc\xff\xbe\xfb\xc4\xff\xb6\xfb\xbe\xff\xaf\xfa\xb7\ -\xff\xa8\xfa\xb0\xff\xa1\xfa\xaa\xff\xa3\xff\xad\xffx\xeb\x84\ -\xff$M(\xff'\x1f&\x9f\x00\x00\x00\x00\x00\x00\x00\ -\x00<=<\x05979\xaaLPL\xff\xba\xc7\xbb\ -\xff\xf1\xff\xf4\xff\xee\xff\xf0\xff\xe2\xff\xe6\xff\xda\xff\xdf\ -\xff\xd5\xff\xda\xff\xcd\xff\xd3\xff\x9b\xd0\xa0\xff9M;\ -\xff#\x1d#\xbb\x0d\x0e\x0d\x0b\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00CCC\x04<;<\x889:9\ -\xf6lnl\xff\xa4\xa8\xa4\xff\xc3\xcb\xc4\xff\xc1\xcd\xc2\ -\xff\xa2\xb0\xa3\xffitj\xff333\xfb,'+\ -\x96$$$\x0b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00BBB\ -+555\x8a111\xc8444\xe7333\ -\xe8-+-\xcb,*,\x911113\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0\x0f\x00\ -\x00\xc0\x03\x00\x00\x80\x01\x00\x00\x80\x01\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x01\x00\ -\x00\x80\x01\x00\x00\xc0\x03\x00\x00\xf0\x0f\x00\x00\ -\x00\x00\x03L\ -<\ -?xml version=\x221.\ -0\x22 encoding=\x22UTF\ --8\x22?>\x0d\x0a\x0d\x0a source contr\ -ol - warning v2<\ -/title>\x0d\x0a \ -\x0d\x0a \ -\x0d\x0a \x0d\x0a\x0d\x0a\ -\x00\x00\x04~\ -\x00\ -\x00\x01\x00\x01\x00\x10\x10\x00\x00\x00\x00 \x00h\x04\x00\ -\x00\x16\x00\x00\x00(\x00\x00\x00\x10\x00\x00\x00 \x00\x00\ -\x00\x01\x00 \x00\x00\x00\x00\x00@\x04\x00\x00\x13\x0b\x00\ -\x00\x13\x0b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ ->\x00\x00\x00\xa1\x00\x00\x00\xd6\x00\x00\x00\xeb\x00\x00\x00\ -\xec\x00\x00\x00\xd8\x00\x00\x00\xa7\x00\x00\x00G\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x9e\x0148\ -\xff\x02\x8c\x92\xff\x01\xbf\xc1\xff\x01\xd5\xd4\xff\x01\xd6\xd5\ -\xff\x01\xc2\xc3\xff\x01\x91\x97\xff\x01;@\xff\x00\x00\x00\ -\xac\x00\x00\x00\x12\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x0c\x00\x00\x00\xbb\x01bh\xff\x01\xe7\xe6\ -\xff\x00\xec\xe6\xff\x00\xec\xe6\xff\x00\xeb\xe6\xff\x00\xeb\xe6\ -\xff\x00\xec\xe6\xff\x00\xec\xe6\xff\x01\xe8\xe6\xff\x01io\ -\xff\x00\x00\x00\xc9\x00\x00\x00\x13\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x98\x02cj\xff\x00\xea\xe6\xff\x00\xec\xe6\ -\xff\x00\xeb\xe6\xff\x00\xeb\xe6\xff\x00\xeb\xe6\xff\x00\xeb\xe6\ -\xff\x00\xeb\xe6\xff\x00\xeb\xe6\xff\x00\xec\xe6\xff\x01\xeb\xe6\ -\xff\x01jp\xff\x00\x00\x00\xaf\x00\x00\x00\x00\x00\x00\x00\ -0\x00\x00\x00\xfd\x01\xe4\xe4\xff\x00\xec\xe6\xff\x00\xeb\xe6\ -\xff\x00\xeb\xe6\xff\x00\xeb\xe6\xff\x00\xeb\xe6\xff\x00\xeb\xe6\ -\xff\x00\xeb\xe6\xff\x00\xeb\xe6\xff\x00\xeb\xe6\xff\x00\xec\xe6\ -\xff\x01\xe8\xe6\xff\x019>\xff\x00\x00\x00E\x00\x00\x00\ -\x92\x02~\x84\xff\x00\xec\xe6\xff\x00\xeb\xe6\xff\x00\xeb\xe6\ -\xff\x00\xeb\xe6\xff\x00\xeb\xe6\xff\x00\xeb\xe6\xff\x00\xeb\xe6\ -\xff\x00\xeb\xe6\xff\x00\xeb\xe6\xff\x00\xeb\xe6\xff\x00\xeb\xe6\ -\xff\x00\xec\xe6\xff\x01\x93\x9a\xff\x00\x00\x00\xaa\x00\x00\x00\ -\xce\x02\xb7\xba\xff\x00\xec\xe6\xff\x00\xeb\xe6\xff\x00\xeb\xe6\ -\xff\x00\xeb\xe6\xff\x00\xeb\xe6\xff\x00\xeb\xe6\xff\x00\xeb\xe6\ -\xff\x00\xeb\xe6\xff\x00\xeb\xe6\xff\x00\xeb\xe6\xff\x00\xeb\xe6\ -\xff\x00\xec\xe6\xff\x01\xc6\xc6\xff\x00\x00\x00\xdc\x00\x00\x00\ -\xea\x01\xd3\xd3\xff\x00\xec\xe6\xff\x04\xeb\xe9\xff\x04\xeb\xe9\ -\xff\x03\xeb\xe9\xff\x02\xeb\xe8\xff\x02\xeb\xe7\xff\x01\xeb\xe7\ -\xff\x00\xeb\xe6\xff\x00\xeb\xe6\xff\x00\xeb\xe6\xff\x00\xeb\xe6\ -\xff\x00\xeb\xe6\xff\x01\xd7\xd6\xff\x00\x00\x00\xed\x00\x00\x00\ -\xe8\x01\xd0\xd1\xff\x06\xec\xec\xff\x09\xeb\xee\xff\x08\xeb\xed\ -\xff\x07\xeb\xec\xff\x06\xeb\xeb\xff\x05\xeb\xeb\xff\x05\xeb\xea\ -\xff\x04\xeb\xe9\xff\x03\xeb\xe8\xff\x02\xeb\xe8\xff\x01\xeb\xe7\ -\xff\x00\xeb\xe6\xff\x01\xd7\xd6\xff\x00\x00\x00\xed\x00\x00\x00\ -\xcb\x03\xb4\xb9\xff\x0d\xec\xf1\xff\x0d\xeb\xf1\xff\x0c\xeb\xf0\ -\xff\x0b\xeb\xef\xff\x0a\xeb\xef\xff\x09\xeb\xee\xff\x08\xeb\xed\ -\xff\x07\xeb\xed\xff\x07\xeb\xec\xff\x06\xeb\xeb\xff\x05\xeb\xea\ -\xff\x01\xec\xe6\xff\x01\xc2\xc4\xff\x00\x00\x00\xd9\x00\x00\x00\ -\x8b\x03x\x7f\xff\x10\xec\xf4\xff\x10\xec\xf4\xff\x0f\xec\xf3\ -\xff\x0e\xec\xf3\xff\x0e\xeb\xf2\xff\x0d\xeb\xf1\xff\x0c\xeb\xf1\ -\xff\x0b\xeb\xf0\xff\x0a\xeb\xef\xff\x09\xeb\xee\xff\x09\xeb\xee\ -\xff\x03\xec\xe9\xff\x01\x8d\x93\xff\x00\x00\x00\xa3\x00\x00\x00\ -(\x00\x00\x00\xfa\x0d\xd9\xe5\xff\x15\xec\xf9\xff\x13\xec\xf7\ -\xff\x12\xec\xf6\xff\x11\xec\xf5\xff\x10\xec\xf5\xff\x10\xec\xf4\ -\xff\x0f\xec\xf3\xff\x0e\xeb\xf2\xff\x0d\xeb\xf2\xff\x0d\xec\xf1\ -\xff\x04\xe7\xe9\xff\x0115\xff\x00\x00\x00;\x00\x00\x00\ -\x00\x00\x00\x00\x88\x03^e\xff\x15\xe9\xf8\xff\x18\xec\xfb\ -\xff\x16\xec\xf9\xff\x15\xec\xf9\xff\x14\xec\xf8\xff\x13\xec\xf7\ -\xff\x12\xec\xf6\xff\x12\xec\xf6\xff\x12\xec\xf6\xff\x0d\xea\xf1\ -\xff\x02ci\xff\x00\x00\x00\x9f\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x05\x00\x00\x00\xaa\x03]d\xff\x13\xd9\xea\ -\xff\x1a\xec\xfe\xff\x1a\xec\xfd\xff\x19\xec\xfc\xff\x18\xec\xfb\ -\xff\x17\xec\xfb\xff\x17\xec\xfa\xff\x11\xe3\xf1\xff\x03cj\ -\xff\x00\x00\x00\xbb\x00\x00\x00\x0b\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x88\x00\x00\x00\ -\xf6\x06w\x81\xff\x0e\xb2\xc0\xff\x13\xd1\xe2\xff\x13\xd2\xe2\ -\xff\x0e\xb6\xc3\xff\x07~\x88\xff\x00\x00\x00\xfb\x00\x00\x00\ -\x96\x00\x00\x00\x0b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -+\x00\x00\x00\x8a\x00\x00\x00\xc8\x00\x00\x00\xe7\x00\x00\x00\ -\xe8\x00\x00\x00\xcb\x00\x00\x00\x91\x00\x00\x003\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0\x0f\x00\ -\x00\xc0\x03\x00\x00\x80\x01\x00\x00\x80\x01\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x01\x00\ -\x00\x80\x01\x00\x00\xc0\x03\x00\x00\xf0\x0f\x00\x00\ -\x00\x00\x04~\ -\x00\ -\x00\x01\x00\x01\x00\x10\x10\x00\x00\x01\x00 \x00h\x04\x00\ -\x00\x16\x00\x00\x00(\x00\x00\x00\x10\x00\x00\x00 \x00\x00\ -\x00\x01\x00 \x00\x00\x00\x00\x00@\x04\x00\x00\x13\x0b\x00\ -\x00\x13\x0b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00|||\ ->|||\xa1|||\xd6|||\xeb|||\ -\xec|||\xd8|||\xa7|||G\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00|||\x0a|||\x9e\x89\x89\x89\ -\xff\x9e\x9e\x9e\xff\xa8\xa8\xa8\xff\xac\xac\xac\xff\xad\xad\xad\ -\xff\xa9\xa9\xa9\xff\x9f\x9f\x9f\xff\x8b\x8b\x8b\xff|||\ -\xac|||\x12\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00|||\x0c|||\xbb\x94\x94\x94\xff\xb0\xb0\xb0\ -\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\ -\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\xff\x96\x96\x96\ -\xff|||\xc9|||\x13\x00\x00\x00\x00\x00\x00\x00\ -\x00|||\x98\x95\x95\x95\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\ -\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\ -\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\ -\xff\x96\x96\x96\xff|||\xaf\x00\x00\x00\x00|||\ -0|||\xfd\xb0\xb0\xb0\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\ -\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\ -\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\ -\xff\xb0\xb0\xb0\xff\x8a\x8a\x8a\xff|||E|||\ -\x92\x9b\x9b\x9b\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\ -\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\ -\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\ -\xff\xb0\xb0\xb0\xff\x9f\x9f\x9f\xff|||\xaa|||\ -\xce\xa6\xa6\xa6\xff\xaf\xaf\xaf\xff\xaf\xaf\xaf\xff\xb0\xb0\xb0\ -\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\ -\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\ -\xff\xb0\xb0\xb0\xff\xaa\xaa\xaa\xff|||\xdc|||\ -\xea\xac\xac\xac\xff\xb0\xb0\xb0\xff\xb3\xb3\xb3\xff\xb4\xb4\xb4\ -\xff\xb3\xb3\xb3\xff\xb2\xb2\xb2\xff\xb1\xb1\xb1\xff\xb1\xb1\xb1\ -\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\ -\xff\xb0\xb0\xb0\xff\xad\xad\xad\xff|||\xed|||\ -\xe8\xac\xac\xac\xff\xb6\xb6\xb6\xff\xb9\xb9\xb9\xff\xb8\xb8\xb8\ -\xff\xb7\xb7\xb7\xff\xb6\xb6\xb6\xff\xb5\xb5\xb5\xff\xb4\xb4\xb4\ -\xff\xb3\xb3\xb3\xff\xb2\xb2\xb2\xff\xb2\xb2\xb2\xff\xb0\xb0\xb0\ -\xff\xaf\xaf\xaf\xff\xad\xad\xad\xff|||\xed|||\ -\xcb\xa8\xa8\xa8\xff\xbd\xbd\xbd\xff\xbc\xbc\xbc\xff\xbb\xbb\xbb\ -\xff\xbb\xbb\xbb\xff\xba\xba\xba\xff\xb9\xb9\xb9\xff\xb8\xb8\xb8\ -\xff\xb7\xb7\xb7\xff\xb6\xb6\xb6\xff\xb5\xb5\xb5\xff\xb4\xb4\xb4\ -\xff\xb0\xb0\xb0\xff\xa9\xa9\xa9\xff|||\xd9|||\ -\x8b\x9b\x9b\x9b\xff\xc0\xc0\xc0\xff\xc0\xc0\xc0\xff\xbf\xbf\xbf\ -\xff\xbe\xbe\xbe\xff\xbd\xbd\xbd\xff\xbd\xbd\xbd\xff\xbc\xbc\xbc\ -\xff\xbb\xbb\xbb\xff\xba\xba\xba\xff\xb9\xb9\xb9\xff\xb9\xb9\xb9\ -\xff\xb3\xb3\xb3\xff\x9e\x9e\x9e\xff|||\xa3|||\ -(|||\xfa\xba\xba\xba\xff\xc5\xc5\xc5\xff\xc3\xc3\xc3\ -\xff\xc2\xc2\xc2\xff\xc1\xc1\xc1\xff\xc1\xc1\xc1\xff\xc0\xc0\xc0\ -\xff\xbf\xbf\xbf\xff\xbe\xbe\xbe\xff\xbd\xbd\xbd\xff\xbd\xbd\xbd\ -\xff\xb4\xb4\xb4\xff\x88\x88\x88\xff|||;\x00\x00\x00\ -\x00|||\x88\x95\x95\x95\xff\xc5\xc5\xc5\xff\xc8\xc8\xc8\ -\xff\xc6\xc6\xc6\xff\xc5\xc5\xc5\xff\xc4\xc4\xc4\xff\xc3\xc3\xc3\ -\xff\xc3\xc3\xc3\xff\xc2\xc2\xc2\xff\xc2\xc2\xc2\xff\xbd\xbd\xbd\ -\xff\x95\x95\x95\xff|||\x9f\x00\x00\x00\x00\x00\x00\x00\ -\x00|||\x05|||\xaa\x95\x95\x95\xff\xc0\xc0\xc0\ -\xff\xcb\xcb\xcb\xff\xca\xca\xca\xff\xc9\xc9\xc9\xff\xc8\xc8\xc8\ -\xff\xc7\xc7\xc7\xff\xc7\xc7\xc7\xff\xc0\xc0\xc0\xff\x96\x96\x96\ -\xff|||\xbb|||\x0b\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00|||\x04|||\x88|||\ -\xf6\x9e\x9e\x9e\xff\xb3\xb3\xb3\xff\xbe\xbe\xbe\xff\xbf\xbf\xbf\ -\xff\xb3\xb3\xb3\xff\xa0\xa0\xa0\xff|||\xfb|||\ -\x96|||\x0b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00|||\ -+|||\x8a|||\xc8|||\xe7|||\ -\xe8|||\xcb|||\x91|||3\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0\x0f\x00\ -\x00\xc0\x03\x00\x00\x80\x01\x00\x00\x80\x01\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x01\x00\ -\x00\x80\x01\x00\x00\xc0\x03\x00\x00\xf0\x0f\x00\x00\ -\x00\x00\x03D\ -<\ -?xml version=\x221.\ -0\x22 encoding=\x22UTF\ --8\x22?>\x0d\x0a\x0d\x0a source contr\ -ol error v2\x0d\x0a \x0d\x0a \ - \x0d\ -\x0a \x0d\x0a\x0d\x0a\ -" - -qt_resource_name = b"\ -\x00\x0f\ -\x04T\x95'\ -\x00b\ -\x00m\x00p\x000\x000\x000\x000\x005\x00_\x000\x000\x00.\x00p\x00n\x00g\ -\x00\x0f\ -\x04S\x95\xc7\ -\x00b\ -\x00m\x00p\x000\x000\x000\x000\x006\x00_\x000\x005\x00.\x00p\x00n\x00g\ -\x00\x09\ -\x0a\xc5\xacG\ -\x00w\ -\x00a\x00t\x00e\x00r\x00.\x00p\x00n\x00g\ -\x00\x15\ -\x06Z\x7fG\ -\x00p\ -\x00a\x00r\x00t\x00i\x00c\x00l\x00e\x00s\x00_\x00t\x00r\x00e\x00e\x00_\x000\x000\ -\x00.\x00p\x00n\x00g\ -\x00\x0f\ -\x04_\x95'\ -\x00b\ -\x00m\x00p\x000\x000\x000\x000\x005\x00_\x000\x009\x00.\x00p\x00n\x00g\ -\x00\x16\ -\x0eE\x9e\x87\ -\x00e\ -\x00r\x00r\x00o\x00r\x00_\x00r\x00e\x00p\x00o\x00r\x00t\x00_\x00e\x00r\x00r\x00o\ -\x00r\x00.\x00s\x00v\x00g\ -\x00\x09\ -\x08\xbcm\xc2\ -\x00s\ -\x00t\x00a\x00t\x00u\x00s\x00b\x00a\x00r\ -\x00\x0f\ -\x04P\x95\xc7\ -\x00b\ -\x00m\x00p\x000\x000\x000\x000\x006\x00_\x000\x004\x00.\x00p\x00n\x00g\ -\x00\x0f\ -\x04\x5c\x95'\ -\x00b\ -\x00m\x00p\x000\x000\x000\x000\x005\x00_\x000\x008\x00.\x00p\x00n\x00g\ -\x00\x18\ -\x00\xf0&'\ -\x00e\ -\x00r\x00r\x00o\x00r\x00_\x00r\x00e\x00p\x00o\x00r\x00t\x00_\x00w\x00a\x00r\x00n\ -\x00i\x00n\x00g\x00.\x00s\x00v\x00g\ -\x00\x18\ -\x0c\x85t\xe7\ -\x00e\ -\x00r\x00r\x00o\x00r\x00_\x00r\x00e\x00p\x00o\x00r\x00t\x00_\x00c\x00o\x00m\x00m\ -\x00e\x00n\x00t\x00.\x00s\x00v\x00g\ -\x00\x0a\ -\x03\xd6;g\ -\x00M\ -\x00a\x00i\x00n\x00W\x00i\x00n\x00d\x00o\x00w\ -\x00\x0f\ -\x04U\x95\xc7\ -\x00b\ -\x00m\x00p\x000\x000\x000\x000\x006\x00_\x000\x003\x00.\x00p\x00n\x00g\ -\x00\x09\ -\x0c\xe6\xbd#\ -\x00v\ -\x00i\x00e\x00w\x00p\x00a\x00n\x00e\x00s\ -\x00\x0f\ -\x04a\x95'\ -\x00b\ -\x00m\x00p\x000\x000\x000\x000\x005\x00_\x000\x007\x00.\x00p\x00n\x00g\ -\x00\x07\ -\x0a\xc9\xa6S\ -\x00c\ -\x00u\x00r\x00s\x00o\x00r\x00s\ -\x00\x15\ -\x06S\x7fG\ -\x00p\ -\x00a\x00r\x00t\x00i\x00c\x00l\x00e\x00s\x00_\x00t\x00r\x00e\x00e\x00_\x000\x007\ -\x00.\x00p\x00n\x00g\ -\x00\x0f\ -\x04R\x95\xc7\ -\x00b\ -\x00m\x00p\x000\x000\x000\x000\x006\x00_\x000\x002\x00.\x00p\x00n\x00g\ -\x00\x0f\ -\x04^\x95'\ -\x00b\ -\x00m\x00p\x000\x000\x000\x000\x005\x00_\x000\x006\x00.\x00p\x00n\x00g\ -\x00\x15\ -\x06P\x7fG\ -\x00p\ -\x00a\x00r\x00t\x00i\x00c\x00l\x00e\x00s\x00_\x00t\x00r\x00e\x00e\x00_\x000\x006\ -\x00.\x00p\x00n\x00g\ -\x00\x0f\ -\x04W\x95\xc7\ -\x00b\ -\x00m\x00p\x000\x000\x000\x000\x006\x00_\x000\x001\x00.\x00p\x00n\x00g\ -\x00\x0f\ -\x04S\x95'\ -\x00b\ -\x00m\x00p\x000\x000\x000\x000\x005\x00_\x000\x005\x00.\x00p\x00n\x00g\ -\x00\x15\ -\x06a\x7fG\ -\x00p\ -\x00a\x00r\x00t\x00i\x00c\x00l\x00e\x00s\x00_\x00t\x00r\x00e\x00e\x00_\x000\x005\ -\x00.\x00p\x00n\x00g\ -\x00\x0f\ -\x04T\x95\xc7\ -\x00b\ -\x00m\x00p\x000\x000\x000\x000\x006\x00_\x000\x000\x00.\x00p\x00n\x00g\ -\x00\x0f\ -\x04P\x95'\ -\x00b\ -\x00m\x00p\x000\x000\x000\x000\x005\x00_\x000\x004\x00.\x00p\x00n\x00g\ -\x00\x03\ -\x00\x00x\xc3\ -\x00r\ -\x00e\x00s\ -\x00\x14\ -\x07\x22u\xc7\ -\x00a\ -\x00r\x00h\x00i\x00t\x00y\x00p\x00e\x00_\x00t\x00r\x00e\x00e\x00_\x000\x003\x00.\ -\x00p\x00n\x00g\ -\x00\x05\ -\x00O\xa6S\ -\x00I\ -\x00c\x00o\x00n\x00s\ -\x00\x15\ -\x06^\x7fG\ -\x00p\ -\x00a\x00r\x00t\x00i\x00c\x00l\x00e\x00s\x00_\x00t\x00r\x00e\x00e\x00_\x000\x004\ -\x00.\x00p\x00n\x00g\ -\x00\x0f\ -\x04U\x95'\ -\x00b\ -\x00m\x00p\x000\x000\x000\x000\x005\x00_\x000\x003\x00.\x00p\x00n\x00g\ -\x00\x14\ -\x07!u\xc7\ -\x00a\ -\x00r\x00h\x00i\x00t\x00y\x00p\x00e\x00_\x00t\x00r\x00e\x00e\x00_\x000\x002\x00.\ -\x00p\x00n\x00g\ -\x00\x15\ -\x06_\x7fG\ -\x00p\ -\x00a\x00r\x00t\x00i\x00c\x00l\x00e\x00s\x00_\x00t\x00r\x00e\x00e\x00_\x000\x003\ -\x00.\x00p\x00n\x00g\ -\x00\x0b\ -\x0f\x08B\x1e\ -\x00A\ -\x00p\x00p\x00l\x00i\x00c\x00a\x00t\x00i\x00o\x00n\ -\x00\x0f\ -\x04R\x95'\ -\x00b\ -\x00m\x00p\x000\x000\x000\x000\x005\x00_\x000\x002\x00.\x00p\x00n\x00g\ -\x00\x14\ -\x07(u\xc7\ -\x00a\ -\x00r\x00h\x00i\x00t\x00y\x00p\x00e\x00_\x00t\x00r\x00e\x00e\x00_\x000\x001\x00.\ -\x00p\x00n\x00g\ -\x00\x0f\ -\x04a\x95\xc7\ -\x00b\ -\x00m\x00p\x000\x000\x000\x000\x006\x00_\x000\x007\x00.\x00p\x00n\x00g\ -\x00\x15\ -\x06\x5c\x7fG\ -\x00p\ -\x00a\x00r\x00t\x00i\x00c\x00l\x00e\x00s\x00_\x00t\x00r\x00e\x00e\x00_\x000\x002\ -\x00.\x00p\x00n\x00g\ -\x00\x0f\ -\x04W\x95'\ -\x00b\ -\x00m\x00p\x000\x000\x000\x000\x005\x00_\x000\x001\x00.\x00p\x00n\x00g\ -\x00\x14\ -\x07'u\xc7\ -\x00a\ -\x00r\x00h\x00i\x00t\x00y\x00p\x00e\x00_\x00t\x00r\x00e\x00e\x00_\x000\x000\x00.\ -\x00p\x00n\x00g\ -\x00\x0f\ -\x04^\x95\xc7\ -\x00b\ -\x00m\x00p\x000\x000\x000\x000\x006\x00_\x000\x006\x00.\x00p\x00n\x00g\ -\x00\x15\ -\x06]\x7fG\ -\x00p\ -\x00a\x00r\x00t\x00i\x00c\x00l\x00e\x00s\x00_\x00t\x00r\x00e\x00e\x00_\x000\x001\ -\x00.\x00p\x00n\x00g\ -\x00\x0f\ -\x0e\x0f\xf3\xff\ -\x00o\ -\x003\x00d\x00e\x00_\x00e\x00d\x00i\x00t\x00o\x00r\x00.\x00i\x00c\x00o\ -\x00\x14\ -\x0b\x1b&\xb6\ -\x00P\ -\x00a\x00d\x00l\x00o\x00c\x00k\x00_\x00D\x00i\x00s\x00a\x00b\x00l\x00e\x00d\x00.\ -\x00t\x00i\x00f\ -\x00\x17\ -\x0c\x9a\xdb\xc7\ -\x00l\ -\x00o\x00c\x00k\x00_\x00c\x00i\x00r\x00c\x00l\x00e\x00_\x00d\x00e\x00f\x00a\x00u\ -\x00l\x00t\x00.\x00s\x00v\x00g\ -\x00\x10\ -\x07T\xb1'\ -\x00D\ -\x00e\x00f\x00a\x00u\x00l\x00t\x00_\x00o\x00p\x00e\x00n\x00.\x00s\x00v\x00g\ -\x00\x19\ -\x0e\xd2\x13\xe7\ -\x00S\ -\x00l\x00i\x00c\x00e\x00_\x00H\x00a\x00n\x00d\x00l\x00e\x00_\x00M\x00o\x00d\x00i\ -\x00f\x00i\x00e\x00d\x00.\x00s\x00v\x00g\ -\x00\x0e\ -\x0b\xd8M\x87\ -\x00l\ -\x00a\x00y\x00e\x00r\x00_\x00i\x00c\x00o\x00n\x00.\x00s\x00v\x00g\ -\x00\x15\ -\x01\xaf\x1c'\ -\x00E\ -\x00n\x00t\x00i\x00t\x00y\x00_\x00N\x00o\x00t\x00_\x00A\x00c\x00t\x00i\x00v\x00e\ -\x00.\x00s\x00v\x00g\ -\x00\x19\ -\x05\xf2\xd2\x07\ -\x00v\ -\x00i\x00s\x00_\x00o\x00n\x00_\x00N\x00o\x00t\x00T\x00r\x00a\x00n\x00s\x00p\x00a\ -\x00r\x00e\x00n\x00t\x00.\x00s\x00v\x00g\ -\x00\x1c\ -\x05A\x11\x07\ -\x00S\ -\x00l\x00i\x00c\x00e\x00_\x00H\x00a\x00n\x00d\x00l\x00e\x00_\x00E\x00d\x00i\x00t\ -\x00o\x00r\x00_\x00O\x00n\x00l\x00y\x00.\x00s\x00v\x00g\ -\x00\x16\ -\x0c>\x8f\xc7\ -\x00v\ -\x00i\x00s\x00_\x00c\x00i\x00r\x00c\x00l\x00e\x00_\x00d\x00e\x00f\x00a\x00u\x00l\ -\x00t\x00.\x00s\x00v\x00g\ -\x00%\ -\x0f-\x08'\ -\x00S\ -\x00l\x00i\x00c\x00e\x00_\x00H\x00a\x00n\x00d\x00l\x00e\x00_\x00M\x00o\x00d\x00i\ -\x00f\x00i\x00e\x00d\x00_\x00E\x00d\x00i\x00t\x00o\x00r\x00_\x00O\x00n\x00l\x00y\ -\x00.\x00s\x00v\x00g\ -\x00\x0a\ -\x01\xb91\x87\ -\x00l\ -\x00o\x00c\x00k\x00e\x00d\x00.\x00s\x00v\x00g\ -\x00\x0f\ -\x05bA^\ -\x00E\ -\x00y\x00e\x00_\x00O\x00p\x00e\x00n\x00_\x00H\x00i\x00d\x00d\x00e\x00n\ -\x00\x1b\ -\x05K\x05V\ -\x00P\ -\x00a\x00d\x00l\x00o\x00c\x00k\x00_\x00P\x00a\x00r\x00t\x00i\x00a\x00l\x00_\x00E\ -\x00n\x00a\x00b\x00l\x00e\x00d\x00.\x00t\x00i\x00f\ -\x00\x0c\ -\x0f^26\ -\x00E\ -\x00y\x00e\x00_\x00O\x00p\x00e\x00n\x00.\x00t\x00i\x00f\ -\x00\x10\ -\x03\xcaZG\ -\x00S\ -\x00l\x00i\x00c\x00e\x00_\x00E\x00n\x00t\x00i\x00t\x00y\x00.\x00s\x00v\x00g\ -\x00\x16\ -\x06\x8e\x16\xc7\ -\x00E\ -\x00n\x00t\x00i\x00t\x00y\x00_\x00E\x00d\x00i\x00t\x00o\x00r\x00_\x00O\x00n\x00l\ -\x00y\x00.\x00s\x00v\x00g\ -\x00\x1b\ -\x04\xe2\x14'\ -\x00l\ -\x00o\x00c\x00k\x00_\x00c\x00i\x00r\x00c\x00l\x00e\x00_\x00t\x00r\x00a\x00n\x00s\ -\x00p\x00a\x00r\x00e\x00n\x00t\x00.\x00s\x00v\x00g\ -\x00\x0d\ -\x01m\xcf\x96\ -\x00E\ -\x00y\x00e\x00_\x00S\x00l\x00a\x00s\x00h\x00.\x00t\x00i\x00f\ -\x00\x14\ -\x0e\x00\x9e6\ -\x00E\ -\x00y\x00e\x00_\x00P\x00a\x00r\x00t\x00i\x00a\x00l\x00_\x00O\x00p\x00e\x00n\x00.\ -\x00t\x00i\x00f\ -\x00\x07\ -\x0c\xf8ZG\ -\x00E\ -\x00y\x00e\x00.\x00s\x00v\x00g\ -\x00\x14\ -\x07T)\xf6\ -\x00E\ -\x00y\x00e\x00_\x00S\x00l\x00a\x00s\x00h\x00_\x00H\x00i\x00d\x00d\x00e\x00n\x00.\ -\x00t\x00i\x00f\ -\x00\x1a\ -\x00\xe3\x5c\xa7\ -\x00v\ -\x00i\x00s\x00_\x00c\x00i\x00r\x00c\x00l\x00e\x00_\x00t\x00r\x00a\x00n\x00s\x00p\ -\x00a\x00r\x00e\x00n\x00t\x00.\x00s\x00v\x00g\ -\x00/\ -\x0a\xf8TG\ -\x00S\ -\x00l\x00i\x00c\x00e\x00_\x00E\x00n\x00t\x00i\x00t\x00y\x00_\x00M\x00o\x00d\x00i\ -\x00f\x00i\x00e\x00d\x00_\x00E\x00d\x00i\x00t\x00o\x00r\x00_\x00O\x00n\x00l\x00y\ -\x00_\x00U\x00n\x00s\x00a\x00v\x00a\x00b\x00l\x00e\x00.\x00s\x00v\x00g\ -\x00\x13\ -\x09+\x00\xf6\ -\x00P\ -\x00a\x00d\x00l\x00o\x00c\x00k\x00_\x00E\x00n\x00a\x00b\x00l\x00e\x00d\x00.\x00t\ -\x00i\x00f\ -\x00\x19\ -\x07,\xf6\x07\ -\x00S\ -\x00l\x00i\x00c\x00e\x00_\x00E\x00n\x00t\x00i\x00t\x00y\x00_\x00M\x00o\x00d\x00i\ -\x00f\x00i\x00e\x00d\x00.\x00s\x00v\x00g\ -\x00.\ -\x07\x84Qg\ -\x00S\ -\x00l\x00i\x00c\x00e\x00_\x00E\x00n\x00t\x00i\x00t\x00y\x00_\x00M\x00o\x00d\x00i\ -\x00f\x00i\x00e\x00d\x00_\x00N\x00o\x00t\x00_\x00A\x00c\x00t\x00i\x00v\x00e\x00_\ -\x00U\x00n\x00s\x00a\x00v\x00a\x00b\x00l\x00e\x00.\x00s\x00v\x00g\ -\x00%\ -\x08\xc2\x87g\ -\x00S\ -\x00l\x00i\x00c\x00e\x00_\x00E\x00n\x00t\x00i\x00t\x00y\x00_\x00M\x00o\x00d\x00i\ -\x00f\x00i\x00e\x00d\x00_\x00E\x00d\x00i\x00t\x00o\x00r\x00_\x00O\x00n\x00l\x00y\ -\x00.\x00s\x00v\x00g\ -\x00\x19\ -\x0e\x89\x90\x16\ -\x00P\ -\x00a\x00d\x00l\x00o\x00c\x00k\x00_\x00E\x00n\x00a\x00b\x00l\x00e\x00d\x00_\x00H\ -\x00o\x00v\x00e\x00r\x00.\x00t\x00i\x00f\ -\x00\x1c\ -\x0bd6G\ -\x00S\ -\x00l\x00i\x00c\x00e\x00_\x00E\x00n\x00t\x00i\x00t\x00y\x00_\x00E\x00d\x00i\x00t\ -\x00o\x00r\x00_\x00O\x00n\x00l\x00y\x00.\x00s\x00v\x00g\ -\x00\x0b\ -\x052\xac\xa7\ -\x00P\ -\x00a\x00d\x00l\x00o\x00c\x00k\x00.\x00s\x00v\x00g\ -\x00\x10\ -\x08Y\x11\xa7\ -\x00S\ -\x00l\x00i\x00c\x00e\x00_\x00H\x00a\x00n\x00d\x00l\x00e\x00.\x00s\x00v\x00g\ -\x00$\ -\x05\xcb\xc5\xc7\ -\x00S\ -\x00l\x00i\x00c\x00e\x00_\x00E\x00n\x00t\x00i\x00t\x00y\x00_\x00M\x00o\x00d\x00i\ -\x00f\x00i\x00e\x00d\x00_\x00N\x00o\x00t\x00_\x00A\x00c\x00t\x00i\x00v\x00e\x00.\ -\x00s\x00v\x00g\ -\x00\x1b\ -\x0e\xf5\xfe\xc7\ -\x00S\ -\x00l\x00i\x00c\x00e\x00_\x00E\x00n\x00t\x00i\x00t\x00y\x00_\x00N\x00o\x00t\x00_\ -\x00A\x00c\x00t\x00i\x00v\x00e\x00.\x00s\x00v\x00g\ -\x00\x0c\ -\x0e=1\x87\ -\x00u\ -\x00n\x00l\x00o\x00c\x00k\x00e\x00d\x00.\x00s\x00v\x00g\ -\x00\x1a\ -\x00\x9cw\x07\ -\x00S\ -\x00l\x00i\x00c\x00e\x00_\x00E\x00n\x00t\x00i\x00t\x00y\x00_\x00U\x00n\x00s\x00a\ -\x00v\x00a\x00b\x00l\x00e\x00.\x00s\x00v\x00g\ -\x00\x1a\ -\x0a\xe9\xdc\x96\ -\x00P\ -\x00a\x00d\x00l\x00o\x00c\x00k\x00_\x00D\x00i\x00s\x00a\x00b\x00l\x00e\x00d\x00_\ -\x00H\x00o\x00v\x00e\x00r\x00.\x00t\x00i\x00f\ -\x00\x0a\ -\x00\xb5\xd1\xa7\ -\x00E\ -\x00n\x00t\x00i\x00t\x00y\x00.\x00s\x00v\x00g\ -\x00#\ -\x08\x0b\xd5\x87\ -\x00S\ -\x00l\x00i\x00c\x00e\x00_\x00E\x00n\x00t\x00i\x00t\x00y\x00_\x00M\x00o\x00d\x00i\ -\x00f\x00i\x00e\x00d\x00_\x00U\x00n\x00s\x00a\x00v\x00a\x00b\x00l\x00e\x00.\x00s\ -\x00v\x00g\ -\x00\x13\ -\x0e\x1c\x0e\xf6\ -\x00E\ -\x00y\x00e\x00_\x00S\x00l\x00a\x00s\x00h\x00_\x00H\x00o\x00v\x00e\x00r\x00.\x00t\ -\x00i\x00f\ -\x00\x1b\ -\x03\x98\x0c'\ -\x00S\ -\x00l\x00i\x00c\x00e\x00_\x00H\x00a\x00n\x00d\x00l\x00e\x00_\x00N\x00o\x00t\x00_\ -\x00A\x00c\x00t\x00i\x00v\x00e\x00.\x00s\x00v\x00g\ -\x00\x17\ -\x03\xf8\xf5g\ -\x00l\ -\x00o\x00c\x00k\x00_\x00o\x00n\x00_\x00t\x00r\x00a\x00n\x00s\x00p\x00a\x00r\x00e\ -\x00n\x00t\x00.\x00s\x00v\x00g\ -\x00\x1a\ -\x00\xb2\x86\xa7\ -\x00l\ -\x00o\x00c\x00k\x00_\x00o\x00n\x00_\x00N\x00o\x00t\x00T\x00r\x00a\x00n\x00s\x00p\ -\x00a\x00r\x00e\x00n\x00t\x00.\x00s\x00v\x00g\ -\x00\x08\ -\x00\x95Ug\ -\x00v\ -\x00i\x00s\x00b\x00.\x00s\x00v\x00g\ -\x00\x15\ -\x0c\x87\x8f\xd6\ -\x00E\ -\x00y\x00e\x00_\x00P\x00a\x00r\x00t\x00i\x00a\x00l\x00_\x00S\x00l\x00a\x00s\x00h\ -\x00.\x00t\x00i\x00f\ -\x00\x0f\ -\x09\xcbq\xa7\ -\x00v\ -\x00i\x00s\x00b\x00_\x00h\x00i\x00d\x00d\x00e\x00n\x00.\x00s\x00v\x00g\ -\x00\x12\ -\x02{\xf5\x96\ -\x00E\ -\x00y\x00e\x00_\x00O\x00p\x00e\x00n\x00_\x00H\x00o\x00v\x00e\x00r\x00.\x00t\x00i\ -\x00f\ -\x00$\ -\x0a9L\xa7\ -\x00S\ -\x00l\x00i\x00c\x00e\x00_\x00H\x00a\x00n\x00d\x00l\x00e\x00_\x00M\x00o\x00d\x00i\ -\x00f\x00i\x00e\x00d\x00_\x00N\x00o\x00t\x00_\x00A\x00c\x00t\x00i\x00v\x00e\x00.\ -\x00s\x00v\x00g\ -\x00\x16\ -\x05\x5c\xa1g\ -\x00v\ -\x00i\x00s\x00_\x00o\x00n\x00_\x00t\x00r\x00a\x00n\x00s\x00p\x00a\x00r\x00e\x00n\ -\x00t\x00.\x00s\x00v\x00g\ -\x00\x12\ -\x0cS?'\ -\x00D\ -\x00e\x00f\x00a\x00u\x00l\x00t\x00_\x00c\x00l\x00o\x00s\x00e\x00d\x00.\x00s\x00v\ -\x00g\ -\x00\x1c\ -\x0d\x1b}6\ -\x00P\ -\x00a\x00d\x00l\x00o\x00c\x00k\x00_\x00P\x00a\x00r\x00t\x00i\x00a\x00l\x00_\x00D\ -\x00i\x00s\x00a\x00b\x00l\x00e\x00d\x00.\x00t\x00i\x00f\ -\x00\x12\ -\x06\xdb\x9dg\ -\x00P\ -\x00r\x00e\x00f\x00e\x00r\x00e\x00n\x00c\x00e\x00s\x00_\x000\x001\x00.\x00p\x00n\ -\x00g\ -\x00\x0a\ -\x08v\x9cg\ -\x00G\ -\x00l\x00o\x00b\x00a\x00l\x00.\x00s\x00v\x00g\ -\x00\x0a\ -\x0c\x8dj\xa7\ -\x00C\ -\x00a\x00m\x00e\x00r\x00a\x00.\x00s\x00v\x00g\ -\x00\x12\ -\x06\xd8\x9dg\ -\x00P\ -\x00r\x00e\x00f\x00e\x00r\x00e\x00n\x00c\x00e\x00s\x00_\x000\x000\x00.\x00p\x00n\ -\x00g\ -\x00\x0c\ -\x0d\x08\xc6'\ -\x00V\ -\x00i\x00e\x00w\x00p\x00o\x00r\x00t\x00.\x00s\x00v\x00g\ -\x00\x12\ -\x06\xe1\x9dg\ -\x00P\ -\x00r\x00e\x00f\x00e\x00r\x00e\x00n\x00c\x00e\x00s\x00_\x000\x003\x00.\x00p\x00n\ -\x00g\ -\x00\x0a\ -\x00k\xd7\xa7\ -\x00M\ -\x00o\x00t\x00i\x00o\x00n\x00.\x00s\x00v\x00g\ -\x00\x12\ -\x06\xde\x9dg\ -\x00P\ -\x00r\x00e\x00f\x00e\x00r\x00e\x00n\x00c\x00e\x00s\x00_\x000\x002\x00.\x00p\x00n\ -\x00g\ -\x00\x09\ -\x09\xba\xcf\xa7\ -\x00D\ -\x00e\x00b\x00u\x00g\x00.\x00s\x00v\x00g\ -\x00\x10\ -\x03l\x17\xc7\ -\x00E\ -\x00x\x00p\x00e\x00r\x00i\x00m\x00e\x00n\x00t\x00a\x00l\x00.\x00s\x00v\x00g\ -\x00\x09\ -\x02\xc6\xc0\xc7\ -\x00F\ -\x00i\x00l\x00e\x00s\x00.\x00s\x00v\x00g\ -\x00\x0a\ -\x04o\x98\xe7\ -\x00G\ -\x00i\x00z\x00m\x00o\x00s\x00.\x00s\x00v\x00g\ -\x00\x07\ -\x0f\x07J\x02\ -\x00h\ -\x00i\x00t\x00.\x00c\x00u\x00r\ -\x00\x0e\ -\x06\x0c\xfb\x82\ -\x00a\ -\x00r\x00r\x00o\x00w\x00_\x00d\x00o\x00w\x00n\x00.\x00c\x00u\x00r\ -\x00\x0b\ -\x06\x89\xd9\x82\ -\x00c\ -\x00u\x00r\x00s\x00o\x00r\x001\x00.\x00c\x00u\x00r\ -\x00\x0b\ -\x06\x80\xd9\x82\ -\x00c\ -\x00u\x00r\x00s\x00o\x00r\x002\x00.\x00c\x00u\x00r\ -\x00\x17\ -\x06h\xad\xa2\ -\x00p\ -\x00o\x00i\x00n\x00t\x00e\x00r\x00_\x00s\x00o\x00_\x00s\x00e\x00l\x00_\x00p\x00l\ -\x00u\x00s\x00.\x00c\x00u\x00r\ -\x00\x0d\ -\x08\x8c:\xe2\ -\x00l\ -\x00e\x00f\x00t\x00r\x00i\x00g\x00h\x00t\x00.\x00c\x00u\x00r\ -\x00\x0e\ -\x03\x0c\x0f\xc2\ -\x00p\ -\x00o\x00i\x00n\x00t\x00e\x00r\x00H\x00i\x00t\x00.\x00c\x00u\x00r\ -\x00\x12\ -\x03\xfe\x1c\x82\ -\x00p\ -\x00o\x00i\x00n\x00t\x00e\x00r\x00_\x00s\x00m\x00o\x00o\x00t\x00h\x00.\x00c\x00u\ -\x00r\ -\x00\x11\ -\x06\x8d\xde\x82\ -\x00a\ -\x00r\x00r\x00o\x00w\x00_\x00u\x00p\x00r\x00i\x00g\x00h\x00t\x00.\x00c\x00u\x00r\ -\ -\x00\x0e\ -\x02\xc2\xa5\x82\ -\x00a\ -\x00r\x00r\x00_\x00a\x00d\x00d\x00k\x00e\x00y\x00.\x00c\x00u\x00r\ -\x00\x15\ -\x07\x0a7B\ -\x00p\ -\x00o\x00i\x00n\x00t\x00e\x00r\x00_\x00g\x00e\x00t\x00h\x00e\x00i\x00g\x00h\x00t\ -\x00.\x00c\x00u\x00r\ -\x00\x10\ -\x08\x83\x1e\x22\ -\x00p\ -\x00o\x00i\x00n\x00t\x00e\x00r\x00_\x00p\x00l\x00u\x00s\x00.\x00c\x00u\x00r\ -\x00\x11\ -\x0d\xbf%b\ -\x00o\ -\x00b\x00j\x00e\x00c\x00t\x00_\x00r\x00o\x00t\x00a\x00t\x00e\x00.\x00c\x00u\x00r\ -\ -\x00\x0f\ -\x07\xb5h\x82\ -\x00o\ -\x00b\x00j\x00e\x00c\x00t\x00_\x00m\x00o\x00v\x00e\x00.\x00c\x00u\x00r\ -\x00\x13\ -\x00.\xa8\x22\ -\x00p\ -\x00o\x00i\x00n\x00t\x00e\x00r\x00_\x00l\x00i\x00n\x00k\x00n\x00o\x00w\x00.\x00c\ -\x00u\x00r\ -\x00\x10\ -\x07\x0b\x1e\x82\ -\x00p\ -\x00o\x00i\x00n\x00t\x00e\x00r\x00_\x00l\x00i\x00n\x00k\x00.\x00c\x00u\x00r\ -\x00\x11\ -\x01\x93\x0c\x22\ -\x00p\ -\x00o\x00i\x00n\x00t\x00e\x00r\x00_\x00m\x00i\x00n\x00u\x00s\x00.\x00c\x00u\x00r\ -\ -\x00\x13\ -\x0aQ\xeab\ -\x00p\ -\x00o\x00i\x00n\x00t\x00e\x00r\x00D\x00r\x00a\x00g\x00I\x00t\x00e\x00m\x00.\x00c\ -\x00u\x00r\ -\x00\x0c\ -\x0b\xd0gb\ -\x00a\ -\x00r\x00r\x00o\x00w\x00_\x00u\x00p\x00.\x00c\x00u\x00r\ -\x00\x0f\ -\x0eO\xc8\x02\ -\x00p\ -\x00i\x00c\x00k\x00_\x00c\x00u\x00r\x00s\x00o\x00r\x00.\x00c\x00u\x00r\ -\x00\x0c\ -\x0el\xec\xa2\ -\x00c\ -\x00u\x00r\x000\x000\x000\x000\x001\x00.\x00c\x00u\x00r\ -\x00\x0c\ -\x0em\xec\xa2\ -\x00c\ -\x00u\x00r\x000\x000\x000\x000\x002\x00.\x00c\x00u\x00r\ -\x00\x0c\ -\x0en\xec\xa2\ -\x00c\ -\x00u\x00r\x000\x000\x000\x000\x003\x00.\x00c\x00u\x00r\ -\x00\x0c\ -\x05\xaa\xdb\xa2\ -\x00h\ -\x00a\x00n\x00d\x00D\x00r\x00a\x00g\x00.\x00c\x00u\x00r\ -\x00\x0c\ -\x0eo\xec\xa2\ -\x00c\ -\x00u\x00r\x000\x000\x000\x000\x004\x00.\x00c\x00u\x00r\ -\x00\x10\ -\x03y\xfd\xc2\ -\x00o\ -\x00b\x00j\x00e\x00c\x00t\x00_\x00s\x00c\x00a\x00l\x00e\x00.\x00c\x00u\x00r\ -\x00\x0c\ -\x0ep\xec\xa2\ -\x00c\ -\x00u\x00r\x000\x000\x000\x000\x005\x00.\x00c\x00u\x00r\ -\x00\x0c\ -\x02\xaeA\x82\ -\x00p\ -\x00o\x00i\x00n\x00t\x00e\x00r\x00_\x00.\x00c\x00u\x00r\ -\x00\x15\ -\x0eb\xe8\x22\ -\x00p\ -\x00o\x00i\x00n\x00t\x00e\x00r\x00_\x00s\x00o\x00_\x00s\x00e\x00l\x00e\x00c\x00t\ -\x00.\x00c\x00u\x00r\ -\x00\x13\ -\x096M\x02\ -\x00a\ -\x00r\x00r\x00o\x00w\x00_\x00d\x00o\x00w\x00n\x00r\x00i\x00g\x00h\x00t\x00.\x00c\ -\x00u\x00r\ -\x00\x13\ -\x0f\xbas\x02\ -\x00p\ -\x00o\x00i\x00n\x00t\x00e\x00r\x00_\x00f\x00l\x00a\x00t\x00t\x00e\x00n\x00.\x00c\ -\x00u\x00r\ -\x00\x0c\ -\x0fy\xb7\xc7\ -\x00m\ -\x00a\x00x\x00i\x00m\x00i\x00z\x00e\x00.\x00p\x00n\x00g\ -\x00\x10\ -\x0a5o'\ -\x00h\ -\x00i\x00d\x00e\x00_\x00h\x00e\x00l\x00p\x00e\x00r\x00s\x00.\x00p\x00n\x00g\ -\x00\x10\ -\x0a\x9d~\xc7\ -\x00d\ -\x00i\x00s\x00p\x00l\x00a\x00y\x00_\x00i\x00n\x00f\x00o\x00.\x00p\x00n\x00g\ -\x00\x17\ -\x04\xb0\xfe\xc7\ -\x00e\ -\x00d\x00i\x00t\x00w\x00i\x00t\x00h\x00b\x00u\x00t\x00t\x00o\x00n\x00_\x00d\x00a\ -\x00r\x00k\x00.\x00p\x00n\x00g\ -\x00\x08\ -\x06b\x87\xf3\ -\x00t\ -\x00o\x00o\x00l\x00b\x00a\x00r\x00s\ -\x00\x1d\ -\x08\xa8\xaf\xe7\ -\x00s\ -\x00t\x00a\x00n\x00d\x00a\x00r\x00d\x00_\x00v\x00i\x00e\x00w\x00s\x00_\x00t\x00o\ -\x00o\x00l\x00b\x00a\x00r\x00-\x000\x005\x00.\x00p\x00n\x00g\ -\x00\x15\ -\x0e\x98q\xa7\ -\x00o\ -\x00b\x00j\x00e\x00c\x00t\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\x00-\x000\x004\ -\x00.\x00p\x00n\x00g\ -\x00\x18\ -\x000\xce\x87\ -\x00e\ -\x00d\x00i\x00t\x00_\x00m\x00o\x00d\x00e\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\ -\x00-\x001\x004\x00.\x00p\x00n\x00g\ -\x00\x18\ -\x00N\xce\x87\ -\x00e\ -\x00d\x00i\x00t\x00_\x00m\x00o\x00d\x00e\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\ -\x00-\x000\x006\x00.\x00p\x00n\x00g\ -\x00\x1d\ -\x08\xd5\xaf\xe7\ -\x00s\ -\x00t\x00a\x00n\x00d\x00a\x00r\x00d\x00_\x00v\x00i\x00e\x00w\x00s\x00_\x00t\x00o\ -\x00o\x00l\x00b\x00a\x00r\x00-\x001\x002\x00.\x00p\x00n\x00g\ -\x00\x1d\ -\x08\xa7\xaf\xe7\ -\x00s\ -\x00t\x00a\x00n\x00d\x00a\x00r\x00d\x00_\x00v\x00i\x00e\x00w\x00s\x00_\x00t\x00o\ -\x00o\x00l\x00b\x00a\x00r\x00-\x000\x004\x00.\x00p\x00n\x00g\ -\x00\x18\ -\x005\xce\x87\ -\x00e\ -\x00d\x00i\x00t\x00_\x00m\x00o\x00d\x00e\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\ -\x00-\x001\x003\x00.\x00p\x00n\x00g\ -\x00\x18\ -\x00C\xce\x87\ -\x00e\ -\x00d\x00i\x00t\x00_\x00m\x00o\x00d\x00e\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\ -\x00-\x000\x005\x00.\x00p\x00n\x00g\ -\x00\x1d\ -\x08\xd4\xaf\xe7\ -\x00s\ -\x00t\x00a\x00n\x00d\x00a\x00r\x00d\x00_\x00v\x00i\x00e\x00w\x00s\x00_\x00t\x00o\ -\x00o\x00l\x00b\x00a\x00r\x00-\x001\x001\x00.\x00p\x00n\x00g\ -\x00\x15\ -\x0e\xecq\xa7\ -\x00o\ -\x00b\x00j\x00e\x00c\x00t\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\x00-\x001\x000\ -\x00.\x00p\x00n\x00g\ -\x00\x18\ -\x00$\xce\x87\ -\x00e\ -\x00d\x00i\x00t\x00_\x00m\x00o\x00d\x00e\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\ -\x00-\x002\x000\x00.\x00p\x00n\x00g\ -\x00\x1d\ -\x08\xa6\xaf\xe7\ -\x00s\ -\x00t\x00a\x00n\x00d\x00a\x00r\x00d\x00_\x00v\x00i\x00e\x00w\x00s\x00_\x00t\x00o\ -\x00o\x00l\x00b\x00a\x00r\x00-\x000\x003\x00.\x00p\x00n\x00g\ -\x00\x15\ -\x0e\x9aq\xa7\ -\x00o\ -\x00b\x00j\x00e\x00c\x00t\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\x00-\x000\x002\ -\x00.\x00p\x00n\x00g\ -\x00\x18\ -\x002\xce\x87\ -\x00e\ -\x00d\x00i\x00t\x00_\x00m\x00o\x00d\x00e\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\ -\x00-\x001\x002\x00.\x00p\x00n\x00g\ -\x00\x1e\ -\x076,\x87\ -\x00p\ -\x00r\x00o\x00c\x00e\x00d\x00u\x00r\x00a\x00l\x00m\x00a\x00t\x00e\x00r\x00i\x00a\ -\x00l\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\x00.\x00p\x00n\x00g\ -\x00\x1d\ -\x08\xd3\xaf\xe7\ -\x00s\ -\x00t\x00a\x00n\x00d\x00a\x00r\x00d\x00_\x00v\x00i\x00e\x00w\x00s\x00_\x00t\x00o\ -\x00o\x00l\x00b\x00a\x00r\x00-\x001\x000\x00.\x00p\x00n\x00g\ -\x00\x1d\ -\x08\xa5\xaf\xe7\ -\x00s\ -\x00t\x00a\x00n\x00d\x00a\x00r\x00d\x00_\x00v\x00i\x00e\x00w\x00s\x00_\x00t\x00o\ -\x00o\x00l\x00b\x00a\x00r\x00-\x000\x002\x00.\x00p\x00n\x00g\ -\x00\x15\ -\x0e\x9fq\xa7\ -\x00o\ -\x00b\x00j\x00e\x00c\x00t\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\x00-\x000\x001\ -\x00.\x00p\x00n\x00g\ -\x00\x18\ -\x007\xce\x87\ -\x00e\ -\x00d\x00i\x00t\x00_\x00m\x00o\x00d\x00e\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\ -\x00-\x001\x001\x00.\x00p\x00n\x00g\ -\x00\x18\ -\x00E\xce\x87\ -\x00e\ -\x00d\x00i\x00t\x00_\x00m\x00o\x00d\x00e\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\ -\x00-\x000\x003\x00.\x00p\x00n\x00g\ -\x00\x13\ -\x0c\xd0\x1e\x87\ -\x00m\ -\x00i\x00s\x00c\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\x00-\x000\x000\x00.\x00p\ -\x00n\x00g\ -\x00\x1d\ -\x08\xa4\xaf\xe7\ -\x00s\ -\x00t\x00a\x00n\x00d\x00a\x00r\x00d\x00_\x00v\x00i\x00e\x00w\x00s\x00_\x00t\x00o\ -\x00o\x00l\x00b\x00a\x00r\x00-\x000\x001\x00.\x00p\x00n\x00g\ -\x00\x15\ -\x0e\x9cq\xa7\ -\x00o\ -\x00b\x00j\x00e\x00c\x00t\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\x00-\x000\x000\ -\x00.\x00p\x00n\x00g\ -\x00\x18\ -\x004\xce\x87\ -\x00e\ -\x00d\x00i\x00t\x00_\x00m\x00o\x00d\x00e\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\ -\x00-\x001\x000\x00.\x00p\x00n\x00g\ -\x00\x1d\ -\x08\xdb\xaf\xe7\ -\x00s\ -\x00t\x00a\x00n\x00d\x00a\x00r\x00d\x00_\x00v\x00i\x00e\x00w\x00s\x00_\x00t\x00o\ -\x00o\x00l\x00b\x00a\x00r\x00-\x001\x008\x00.\x00p\x00n\x00g\ -\x00\x18\ -\x00B\xce\x87\ -\x00e\ -\x00d\x00i\x00t\x00_\x00m\x00o\x00d\x00e\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\ -\x00-\x000\x002\x00.\x00p\x00n\x00g\ -\x00\x15\ -\x0e\x97q\xa7\ -\x00o\ -\x00b\x00j\x00e\x00c\x00t\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\x00-\x000\x009\ -\x00.\x00p\x00n\x00g\ -\x00\x18\ -\x00?\xce\x87\ -\x00e\ -\x00d\x00i\x00t\x00_\x00m\x00o\x00d\x00e\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\ -\x00-\x001\x009\x00.\x00p\x00n\x00g\ -\x00\x10\ -\x0f\xf1A\xe7\ -\x00O\ -\x00b\x00j\x00S\x00e\x00l\x00e\x00c\x00t\x00i\x00o\x00n\x00.\x00p\x00n\x00g\ -\x00\x1d\ -\x08\xa3\xaf\xe7\ -\x00s\ -\x00t\x00a\x00n\x00d\x00a\x00r\x00d\x00_\x00v\x00i\x00e\x00w\x00s\x00_\x00t\x00o\ -\x00o\x00l\x00b\x00a\x00r\x00-\x000\x000\x00.\x00p\x00n\x00g\ -\x00\x1d\ -\x08\xda\xaf\xe7\ -\x00s\ -\x00t\x00a\x00n\x00d\x00a\x00r\x00d\x00_\x00v\x00i\x00e\x00w\x00s\x00_\x00t\x00o\ -\x00o\x00l\x00b\x00a\x00r\x00-\x001\x007\x00.\x00p\x00n\x00g\ -\x00\x18\ -\x00G\xce\x87\ -\x00e\ -\x00d\x00i\x00t\x00_\x00m\x00o\x00d\x00e\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\ -\x00-\x000\x001\x00.\x00p\x00n\x00g\ -\x00\x1d\ -\x08\xac\xaf\xe7\ -\x00s\ -\x00t\x00a\x00n\x00d\x00a\x00r\x00d\x00_\x00v\x00i\x00e\x00w\x00s\x00_\x00t\x00o\ -\x00o\x00l\x00b\x00a\x00r\x00-\x000\x009\x00.\x00p\x00n\x00g\ -\x00\x15\ -\x0e\x94q\xa7\ -\x00o\ -\x00b\x00j\x00e\x00c\x00t\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\x00-\x000\x008\ -\x00.\x00p\x00n\x00g\ -\x00\x18\ -\x00<\xce\x87\ -\x00e\ -\x00d\x00i\x00t\x00_\x00m\x00o\x00d\x00e\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\ -\x00-\x001\x008\x00.\x00p\x00n\x00g\ -\x00\x1d\ -\x08\xd9\xaf\xe7\ -\x00s\ -\x00t\x00a\x00n\x00d\x00a\x00r\x00d\x00_\x00v\x00i\x00e\x00w\x00s\x00_\x00t\x00o\ -\x00o\x00l\x00b\x00a\x00r\x00-\x001\x006\x00.\x00p\x00n\x00g\ -\x00\x18\ -\x00#\xce\x87\ -\x00e\ -\x00d\x00i\x00t\x00_\x00m\x00o\x00d\x00e\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\ -\x00-\x002\x005\x00.\x00p\x00n\x00g\ -\x00\x18\ -\x00D\xce\x87\ -\x00e\ -\x00d\x00i\x00t\x00_\x00m\x00o\x00d\x00e\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\ -\x00-\x000\x000\x00.\x00p\x00n\x00g\ -\x00\x1d\ -\x08\xab\xaf\xe7\ -\x00s\ -\x00t\x00a\x00n\x00d\x00a\x00r\x00d\x00_\x00v\x00i\x00e\x00w\x00s\x00_\x00t\x00o\ -\x00o\x00l\x00b\x00a\x00r\x00-\x000\x008\x00.\x00p\x00n\x00g\ -\x00\x15\ -\x0e\x99q\xa7\ -\x00o\ -\x00b\x00j\x00e\x00c\x00t\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\x00-\x000\x007\ -\x00.\x00p\x00n\x00g\ -\x00\x18\ -\x00A\xce\x87\ -\x00e\ -\x00d\x00i\x00t\x00_\x00m\x00o\x00d\x00e\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\ -\x00-\x001\x007\x00.\x00p\x00n\x00g\ -\x00\x18\ -\x00O\xce\x87\ -\x00e\ -\x00d\x00i\x00t\x00_\x00m\x00o\x00d\x00e\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\ -\x00-\x000\x009\x00.\x00p\x00n\x00g\ -\x00\x1d\ -\x08\xd8\xaf\xe7\ -\x00s\ -\x00t\x00a\x00n\x00d\x00a\x00r\x00d\x00_\x00v\x00i\x00e\x00w\x00s\x00_\x00t\x00o\ -\x00o\x00l\x00b\x00a\x00r\x00-\x001\x005\x00.\x00p\x00n\x00g\ -\x00\x18\ -\x00 \xce\x87\ -\x00e\ -\x00d\x00i\x00t\x00_\x00m\x00o\x00d\x00e\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\ -\x00-\x002\x004\x00.\x00p\x00n\x00g\ -\x00\x1d\ -\x08\xaa\xaf\xe7\ -\x00s\ -\x00t\x00a\x00n\x00d\x00a\x00r\x00d\x00_\x00v\x00i\x00e\x00w\x00s\x00_\x00t\x00o\ -\x00o\x00l\x00b\x00a\x00r\x00-\x000\x007\x00.\x00p\x00n\x00g\ -\x00\x15\ -\x0e\x96q\xa7\ -\x00o\ -\x00b\x00j\x00e\x00c\x00t\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\x00-\x000\x006\ -\x00.\x00p\x00n\x00g\ -\x00\x18\ -\x00>\xce\x87\ -\x00e\ -\x00d\x00i\x00t\x00_\x00m\x00o\x00d\x00e\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\ -\x00-\x001\x006\x00.\x00p\x00n\x00g\ -\x00\x18\ -\x00L\xce\x87\ -\x00e\ -\x00d\x00i\x00t\x00_\x00m\x00o\x00d\x00e\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\ -\x00-\x000\x008\x00.\x00p\x00n\x00g\ -\x00\x15\ -\x0e\x9d|'\ -\x00o\ -\x00b\x00j\x00e\x00c\x00t\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\x00-\x000\x003\ -\x00.\x00s\x00v\x00g\ -\x00\x1d\ -\x08\xd7\xaf\xe7\ -\x00s\ -\x00t\x00a\x00n\x00d\x00a\x00r\x00d\x00_\x00v\x00i\x00e\x00w\x00s\x00_\x00t\x00o\ -\x00o\x00l\x00b\x00a\x00r\x00-\x001\x004\x00.\x00p\x00n\x00g\ -\x00\x18\ -\x00%\xce\x87\ -\x00e\ -\x00d\x00i\x00t\x00_\x00m\x00o\x00d\x00e\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\ -\x00-\x002\x003\x00.\x00p\x00n\x00g\ -\x00\x1d\ -\x08\xa9\xaf\xe7\ -\x00s\ -\x00t\x00a\x00n\x00d\x00a\x00r\x00d\x00_\x00v\x00i\x00e\x00w\x00s\x00_\x00t\x00o\ -\x00o\x00l\x00b\x00a\x00r\x00-\x000\x006\x00.\x00p\x00n\x00g\ -\x00\x15\ -\x0e\x9bq\xa7\ -\x00o\ -\x00b\x00j\x00e\x00c\x00t\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\x00-\x000\x005\ -\x00.\x00p\x00n\x00g\ -\x00\x18\ -\x003\xce\x87\ -\x00e\ -\x00d\x00i\x00t\x00_\x00m\x00o\x00d\x00e\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\ -\x00-\x001\x005\x00.\x00p\x00n\x00g\ -\x00\x18\ -\x00Q\xce\x87\ -\x00e\ -\x00d\x00i\x00t\x00_\x00m\x00o\x00d\x00e\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\ -\x00-\x000\x007\x00.\x00p\x00n\x00g\ -\x00\x1d\ -\x08\xd6\xaf\xe7\ -\x00s\ -\x00t\x00a\x00n\x00d\x00a\x00r\x00d\x00_\x00v\x00i\x00e\x00w\x00s\x00_\x00t\x00o\ -\x00o\x00l\x00b\x00a\x00r\x00-\x001\x003\x00.\x00p\x00n\x00g\ -\x00\x18\ -\x00\x22\xce\x87\ -\x00e\ -\x00d\x00i\x00t\x00_\x00m\x00o\x00d\x00e\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\ -\x00-\x002\x002\x00.\x00p\x00n\x00g\ -\x00\x10\ -\x0c\x99\xf5\x1f\ -\x00b\ -\x00a\x00l\x00l\x00_\x00o\x00f\x00f\x00l\x00i\x00n\x00e\x00.\x00i\x00c\x00o\ -\x00\x1c\ -\x0d\xbb\x8bG\ -\x00s\ -\x00o\x00u\x00r\x00c\x00e\x00_\x00c\x00o\x00n\x00t\x00r\x00o\x00l\x00_\x00c\x00o\ -\x00n\x00n\x00e\x00c\x00t\x00e\x00d\x00.\x00s\x00v\x00g\ -\x00\x1c\ -\x03ZJ\xe7\ -\x00s\ -\x00o\x00u\x00r\x00c\x00e\x00_\x00c\x00o\x00n\x00t\x00r\x00o\x00l\x00-\x00n\x00o\ -\x00t\x00_\x00s\x00e\x00t\x00u\x00p\x00.\x00s\x00v\x00g\ -\x00\x0f\ -\x0a\x0d'\xdf\ -\x00b\ -\x00a\x00l\x00l\x00_\x00o\x00n\x00l\x00i\x00n\x00e\x00.\x00i\x00c\x00o\ -\x00\x1d\ -\x03\xe3zG\ -\x00s\ -\x00o\x00u\x00r\x00c\x00e\x00_\x00c\x00o\x00n\x00t\x00r\x00o\x00l\x00-\x00w\x00a\ -\x00r\x00n\x00i\x00n\x00g\x00_\x00v\x002\x00.\x00s\x00v\x00g\ -\x00\x10\ -\x0c\xa1\xe6\x1f\ -\x00b\ -\x00a\x00l\x00l\x00_\x00p\x00e\x00n\x00d\x00i\x00n\x00g\x00.\x00i\x00c\x00o\ -\x00\x11\ -\x08tl?\ -\x00b\ -\x00a\x00l\x00l\x00_\x00d\x00i\x00s\x00a\x00b\x00l\x00e\x00d\x00.\x00i\x00c\x00o\ -\ -\x00\x1b\ -\x00\x22\x12'\ -\x00s\ -\x00o\x00u\x00r\x00c\x00e\x00_\x00c\x00o\x00n\x00t\x00r\x00o\x00l\x00_\x00e\x00r\ -\x00r\x00o\x00r\x00_\x00v\x002\x00.\x00s\x00v\x00g\ -" - -qt_resource_struct = b"\ -\x00\x00\x00\x00\x00\x02\x00\x00\x00)\x00\x00\x00\x01\ -\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x03\xa8\x00\x02\x00\x00\x00\x0c\x00\x00\x00\xc5\ -\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x03\xe2\x00\x02\x00\x00\x002\x00\x00\x00\x93\ -\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x01F\x00\x00\x00\x00\x00\x01\x00\x00\xb19\ -\x00\x00\x01y+\x8f\x93\xf2\ -\x00\x00\x01\xb2\x00\x02\x00\x00\x00\x01\x00\x00\x00Y\ -\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x03\x84\x00\x00\x00\x00\x00\x01\x00\x00\xc6s\ -\x00\x00\x01x\xc7F\xf7\x89\ -\x00\x00\x00\xfe\x00\x00\x00\x00\x00\x01\x00\x00\xad\x12\ -\x00\x00\x01x\xc7F\xf7\xee\ -\x00\x00\x04\xc0\x00\x00\x00\x00\x00\x01\x00\x00\xceG\ -\x00\x00\x01x\xc7F\xf7\xd7\ -\x00\x00\x02p\x00\x00\x00\x00\x00\x01\x00\x00\xbec\ -\x00\x00\x01x\xc7F\xf8\x08\ -\x00\x00\x03\x0c\x00\x00\x00\x00\x00\x01\x00\x00\xc3\xef\ -\x00\x00\x01x\xc7F\xf8\x04\ -\x00\x00\x00$\x00\x00\x00\x00\x00\x01\x00\x00\x01\x88\ -\x00\x00\x01x\xc7F\xf7\x88\ -\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ -\x00\x00\x01x\xc7F\xf7\xd9\ -\x00\x00\x03`\x00\x00\x00\x00\x00\x01\x00\x00\xc5\xe4\ -\x00\x00\x01x\xc7F\xf85\ -\x00\x00\x04\x22\x00\x00\x00\x00\x00\x01\x00\x00\xca\x80\ -\x00\x00\x01x\xc7F\xf7\xa9\ -\x00\x00\x01\xcc\x00\x00\x00\x00\x00\x01\x00\x00\xba{\ -\x00\x00\x01x\xc7F\xf7\xed\ -\x00\x00\x05f\x00\x00\x00\x00\x00\x01\x00\x00\xd6\xb3\ -\x00\x00\x01x\xc7F\xf7\x85\ -\x00\x00\x02\xe8\x00\x00\x00\x00\x00\x01\x00\x00\xc3E\ -\x00\x00\x01x\xc7F\xf88\ -\x00\x00\x01\x22\x00\x00\x00\x00\x00\x01\x00\x00\xae\x8b\ -\x00\x00\x01x\xc7F\xf7\x81\ -\x00\x00\x02\x94\x00\x00\x00\x00\x00\x01\x00\x00\xbfR\ -\x00\x00\x01x\xc7F\xf7|\ -\x00\x00\x05\xb8\x00\x00\x00\x00\x00\x01\x00\x00\xd9\x9f\ -\x00\x00\x01x\xc7F\xf6\xe8\ -\x00\x00\x00\x90\x00\x00\x00\x00\x00\x01\x00\x00\xa6\x97\ -\x00\x00\x01x\xc7F\xf7}\ -\x00\x00\x02\x08\x00\x00\x00\x00\x00\x01\x00\x00\xbb\x91\ -\x00\x00\x01x\xc7F\xf7\x82\ -\x00\x00\x05\x12\x00\x00\x00\x00\x00\x01\x00\x00\xd0\xa7\ -\x00\x00\x01x\xc7F\xf6\xeb\ -\x00\x00\x02\xb8\x00\x00\x00\x00\x00\x01\x00\x00\xc2a\ -\x00\x00\x01x\xc7F\xf8\x07\ -\x00\x00\x02@\x00\x00\x00\x00\x00\x01\x00\x00\xbd\x8a\ -\x00\x00\x01x\xc7F\xf8\x13\ -\x00\x00\x00`\x00\x00\x00\x00\x00\x01\x00\x00\xa5\xc3\ -\x00\x00\x01x\xc7F\xf8\x17\ -\x00\x00\x056\x00\x00\x00\x00\x00\x01\x00\x00\xd5\xb3\ -\x00\x00\x01x\xc7F\xf7\xf5\ -\x00\x00\x05\xdc\x00\x00\x00\x00\x00\x01\x00\x00\xdd\xf0\ -\x00\x00\x01x\xc7F\xf8&\ -\x00\x00\x03\xf2\x00\x00\x00\x00\x00\x01\x00\x00\xc9M\ -\x00\x00\x01x\xc7F\xf7\xf1\ -\x00\x00\x04t\x00\x00\x00\x00\x00\x01\x00\x00\xcd>\ -\x00\x00\x01x\xc7F\xf7\xf2\ -\x00\x00\x030\x00\x00\x00\x00\x00\x01\x00\x00\xc4\xe2\ -\x00\x00\x01x\xc7F\xf7\xf3\ -\x00\x00\x04F\x00\x00\x00\x00\x00\x01\x00\x00\xccj\ -\x00\x00\x01x\xc7F\xf8\x11\ -\x00\x00\x03\xb4\x00\x00\x00\x00\x00\x01\x00\x00\xc8y\ -\x00\x00\x01x\xc7F\xf8\x12\ -\x00\x00\x05\x8a\x00\x00\x00\x00\x00\x01\x00\x00\xd8\xcb\ -\x00\x00\x01x\xc7F\xf8\x15\ -\x00\x00\x04\xe4\x00\x00\x00\x00\x00\x01\x00\x00\xcf\xd3\ -\x00\x00\x01x\xc7F\xf8\x16\ -\x00\x00\x00\xe6\x00\x02\x00\x00\x00\x01\x00\x00\x00P\ -\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00H\x00\x00\x00\x00\x00\x01\x00\x00\x03\xf4\ -\x00\x00\x01x\xc7G\x01\xc4\ -\x00\x00\x02,\x00\x02\x00\x00\x00\x01\x00\x00\x000\ -\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x01|\x00\x00\x00\x00\x00\x01\x00\x00\xb3\xeb\ -\x00\x00\x01y+\x8f\x93\xef\ -\x00\x00\x01\xf0\x00\x02\x00\x00\x00\x04\x00\x00\x00,\ -\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\xb4\x00\x00\x00\x00\x00\x01\x00\x00\xa9\x0c\ -\x00\x00\x01y+\x8f\x93\xf0\ -\x00\x00\x04\xa4\x00\x02\x00\x00\x00\x01\x00\x00\x00*\ -\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x03\xa8\x00\x02\x00\x00\x00\x01\x00\x00\x00+\ -\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x06\x0c\x00\x01\x00\x00\x00\x01\x00\x00\xde\xc4\ -\x00\x00\x01y\xd2\xb2\xf5B\ -\x00\x00\x16\x86\x00\x00\x00\x00\x00\x01\x00\x05\x9eC\ -\x00\x00\x01x\xc7F\xed\xa9\ -\x00\x00\x16:\x00\x00\x00\x00\x00\x01\x00\x05\x9c\x97\ -\x00\x00\x01x\xc7F\xf0\x97\ -\x00\x00\x16`\x00\x00\x00\x00\x00\x01\x00\x05\x9dk\ -\x00\x00\x01x\xc7F\xeb4\ -\x00\x00\x16\x1c\x00\x00\x00\x00\x00\x01\x00\x05\x9b\xa4\ -\x00\x00\x01x\xc7F\xf0\x87\ -\x00\x00\x03\xa8\x00\x02\x00\x00\x00\x1f\x00\x00\x001\ -\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x13\xb4\x00\x00\x00\x00\x00\x01\x00\x05\x88\x11\ -\x00\x00\x01x\xc7D\x85\xca\ -\x00\x00\x14\x06\x00\x00\x00\x00\x00\x01\x00\x05\x8a\xa5\ -\x00\x00\x01x\xc7D\x85\xcc\ -\x00\x00\x15v\x00\x00\x00\x00\x00\x01\x00\x05\x97l\ -\x00\x00\x01x\xc7D\x85\xc3\ -\x00\x00\x12\xf0\x00\x00\x00\x00\x00\x01\x00\x05\x81\x9f\ -\x00\x00\x01x\xc7D\x83\xc5\ -\x00\x00\x12|\x00\x00\x00\x00\x00\x01\x00\x05~\xaf\ -\x00\x00\x01x\xc7D\x85\xbb\ -\x00\x00\x152\x00\x00\x00\x00\x00\x01\x00\x05\x94\xd8\ -\x00\x00\x01x\xc7D\x85e\ -\x00\x00\x12\x9e\x00\x00\x00\x00\x00\x01\x00\x05\x7f\xf9\ -\x00\x00\x01x\xc7D\x85\xd0\ -\x00\x00\x14\xf6\x00\x00\x00\x00\x00\x01\x00\x05\x92D\ -\x00\x00\x01x\xc7D\x84\xb4\ -\x00\x00\x11\xce\x00\x01\x00\x00\x00\x01\x00\x05z\xad\ -\x00\x00\x01x\xc7D\x83\xca\ -\x00\x00\x12(\x00\x00\x00\x00\x00\x01\x00\x05}\x01\ -\x00\x00\x01x\xc7D\x85\xd2\ -\x00\x00\x12\x0c\x00\x01\x00\x00\x00\x01\x00\x05|V\ -\x00\x00\x01x\xc7D\x84\x12\ -\x00\x00\x11\xf0\x00\x00\x00\x00\x00\x01\x00\x05{\x0c\ -\x00\x00\x01x\xc7D\x84\x12\ -\x00\x00\x12\xc8\x00\x01\x00\x00\x00\x01\x00\x05\x81C\ -\x00\x00\x01x\xc7D\x83\xcf\ -\x00\x00\x13\x12\x00\x00\x00\x00\x00\x01\x00\x05\x82\xe9\ -\x00\x00\x01x\xc7D\x85\xc7\ -\x00\x00\x13\xe0\x00\x00\x00\x00\x00\x01\x00\x05\x89[\ -\x00\x00\x01x\xc7D\x85\xc8\ -\x00\x00\x13\x90\x00\x00\x00\x00\x00\x01\x00\x05\x86\xc7\ -\x00\x00\x01x\xc7D\x85d\ -\x00\x00\x13B\x00\x00\x00\x00\x00\x01\x00\x05\x843\ -\x00\x00\x01x\xc7D\x85\xce\ -\x00\x00\x12\x5c\x00\x01\x00\x00\x00\x01\x00\x05~K\ -\x00\x00\x01x\xc7D\x85-\ -\x00\x00\x15\xc4\x00\x01\x00\x00\x00\x01\x00\x05\x9a\x00\ -\x00\x00\x01x\xc7D\x83\xcb\ -\x00\x00\x14.\x00\x01\x00\x00\x00\x01\x00\x05\x8b\xef\ -\x00\x00\x01x\xc7D\x85\xb9\ -\x00\x00\x14Z\x00\x01\x00\x00\x00\x01\x00\x05\x8c\xbc\ -\x00\x00\x01x\xc7D\x83\xcc\ -\x00\x00\x13h\x00\x00\x00\x00\x00\x01\x00\x05\x85}\ -\x00\x00\x01x\xc7D\x85d\ -\x00\x00\x14x\x00\x00\x00\x00\x00\x01\x00\x05\x8d\x1c\ -\x00\x00\x01x\xc7D\x85\xb6\ -\x00\x00\x15\x94\x00\x00\x00\x00\x00\x01\x00\x05\x98\xb6\ -\x00\x00\x01x\xc7D\x85\xd4\ -\x00\x00\x14\x9c\x00\x00\x00\x00\x00\x01\x00\x05\x8ef\ -\x00\x00\x01x\xc7D\x84\x0b\ -\x00\x00\x14\xba\x00\x00\x00\x00\x00\x01\x00\x05\x8f\xb0\ -\x00\x00\x01x\xc7D\x84\x0d\ -\x00\x00\x14\xd8\x00\x00\x00\x00\x00\x01\x00\x05\x90\xfa\ -\x00\x00\x01x\xc7D\x84\x0e\ -\x00\x00\x15\x14\x00\x00\x00\x00\x00\x01\x00\x05\x93\x8e\ -\x00\x00\x01x\xc7D\x84\x0e\ -\x00\x00\x15X\x00\x00\x00\x00\x00\x01\x00\x05\x96\x22\ -\x00\x00\x01x\xc7D\x84\x0f\ -\x00\x00\x11\xba\x00\x01\x00\x00\x00\x01\x00\x05zN\ -\x00\x00\x01x\xc7D\x84\xb5\ -\x00\x00\x15\xf0\x00\x00\x00\x00\x00\x01\x00\x05\x9aZ\ -\x00\x00\x01x\xc7D\x85\xc5\ -\x00\x00\x03\xa8\x00\x02\x00\x00\x00\x08\x00\x00\x00Q\ -\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00$\x98\x00\x00\x00\x00\x00\x01\x00\x062&\ -\x00\x00\x01y+\x8f\x94\x0d\ -\x00\x00#\xa8\x00\x00\x00\x00\x00\x01\x00\x06\x1e\x02\ -\x00\x00\x01y+\x8f\x94\x0b\ -\x00\x00$\x0a\x00\x00\x00\x00\x00\x01\x00\x06%\xd2\ -\x00\x00\x01y+\x8f\x94\x0b\ -\x00\x00$p\x00\x00\x00\x00\x00\x01\x00\x06-\xa4\ -\x00\x00\x01x\xc7F\xf7d\ -\x00\x00#\xe6\x00\x00\x00\x00\x00\x01\x00\x06!P\ -\x00\x00\x01x\xc7F\xf6\xff\ -\x00\x00#D\x00\x00\x00\x00\x00\x01\x00\x06\x166\ -\x00\x00\x01x\xc7F\xf6\xed\ -\x00\x00$J\x00\x00\x00\x00\x00\x01\x00\x06)\x22\ -\x00\x00\x01x\xc7F\xf6\xf0\ -\x00\x00#j\x00\x00\x00\x00\x00\x01\x00\x06\x1a\xb8\ -\x00\x00\x01y+\x8f\x94\x0c\ -\x00\x00\x16\xba\x00\x02\x00\x00\x009\x00\x00\x00Z\ -\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00 :\x00\x00\x00\x00\x00\x01\x00\x05\xf9\x0c\ -\x00\x00\x01x\xc7F\xf0|\ -\x00\x00#\x0e\x00\x00\x00\x00\x00\x01\x00\x06\x11I\ -\x00\x00\x01x\xc7F\xed\xa1\ -\x00\x00\x1e\xb2\x00\x00\x00\x00\x00\x01\x00\x05\xe9\xce\ -\x00\x00\x01x\xc7F\xef\xf0\ -\x00\x00\x19\x08\x00\x00\x00\x00\x00\x01\x00\x05\xb65\ -\x00\x00\x01x\xc7F\xf0\xa1\ -\x00\x00!\xbc\x00\x00\x00\x00\x00\x01\x00\x06\x07\x15\ -\x00\x00\x01x\xc7F\xf0W\ -\x00\x00\x17@\x00\x00\x00\x00\x00\x01\x00\x05\xa4\xf5\ -\x00\x00\x01x\xc7F\xed\xd6\ -\x00\x00\x19\xae\x00\x00\x00\x00\x00\x01\x00\x05\xba\x04\ -\x00\x00\x01x\xc7F\xe9{\ -\x00\x00\x22b\x00\x00\x00\x00\x00\x01\x00\x06\x0b{\ -\x00\x00\x01x\xc7F\xef\xab\ -\x00\x00\x1b\xde\x00\x00\x00\x00\x00\x01\x00\x05\xcc\xc5\ -\x00\x00\x01x\xc7F\xcb~\ -\x00\x00\x18,\x00\x00\x00\x00\x00\x01\x00\x05\xac:\ -\x00\x00\x01x\xc7F\xf0\x90\ -\x00\x00\x1a\xd6\x00\x00\x00\x00\x00\x01\x00\x05\xc1\xd7\ -\x00\x00\x01x\xc7F\xe9@\ -\x00\x00\x1e<\x00\x00\x00\x00\x00\x01\x00\x05\xe3\x8d\ -\x00\x00\x01x\xc7F\xf0=\ -\x00\x00 \xe0\x00\x00\x00\x00\x00\x01\x00\x05\xfdE\ -\x00\x00\x01x\xc7F\xf0\x03\ -\x00\x00\x1c\xba\x00\x00\x00\x00\x00\x01\x00\x05\xd7Z\ -\x00\x00\x01x\xc7F\xed\xd8\ -\x00\x00\x1f\x8e\x00\x00\x00\x00\x00\x01\x00\x05\xf4\x02\ -\x00\x00\x01x\xc7F\xed\xda\ -\x00\x00\x1cT\x00\x00\x00\x00\x00\x01\x00\x05\xd2\x9a\ -\x00\x00\x01x\xc7F\xcc\x09\ -\x00\x00\x18b\x00\x00\x00\x00\x00\x01\x00\x05\xad,\ -\x00\x00\x01x\xc7F\xe9f\ -\x00\x00\x1e\xe8\x00\x00\x00\x00\x00\x01\x00\x05\xeb{\ -\x00\x00\x01x\xc7F\xe9\x86\ -\x00\x00\x1b\x0c\x00\x00\x00\x00\x00\x01\x00\x05\xc3%\ -\x00\x00\x01x\xc7F\xcb\xfe\ -\x00\x00\x1d\x96\x00\x00\x00\x00\x00\x01\x00\x05\xde+\ -\x00\x00\x01x\xc7F\xe9\x82\ -\x00\x00!\x16\x00\x00\x00\x00\x00\x01\x00\x05\xff\x03\ -\x00\x00\x01x\xc7F\xe7N\ -\x00\x00\x17v\x00\x00\x00\x00\x00\x01\x00\x05\xa7\x17\ -\x00\x00\x01x\xc7F\xe97\ -\x00\x00\x1f\xc4\x00\x00\x00\x00\x00\x01\x00\x05\xf6\x12\ -\x00\x00\x01x\xc7F\xe7\xa5\ -\x00\x00\x22\x98\x00\x00\x00\x00\x00\x01\x00\x06\x0d{\ -\x00\x00\x01x\xc7F\xe6\xb8\ -\x00\x00\x19\xe4\x00\x00\x00\x00\x00\x01\x00\x05\xbb#\ -\x00\x00\x01x\xc7F\xef\xeb\ -\x00\x00\x1d\x16\x00\x00\x00\x00\x00\x01\x00\x05\xda\xfb\ -\x00\x00\x01x\xc7F\xef\xe2\ -\x00\x00\x1bn\x00\x00\x00\x00\x00\x01\x00\x05\xc8A\ -\x00\x00\x01x\xc7F\xef\x93\ -\x00\x00\x1af\x00\x00\x00\x00\x00\x01\x00\x05\xbe\x80\ -\x00\x00\x01x\xc7F\xef\xee\ -\x00\x00\x19>\x00\x00\x00\x00\x00\x01\x00\x05\xb7\x07\ -\x00\x00\x01x\xc7F\xf00\ -\x00\x00\x17\xec\x00\x00\x00\x00\x00\x01\x00\x05\xaa\x0a\ -\x00\x00\x01x\xc7F\xed\xd3\ -\x00\x00\x16\xd0\x00\x00\x00\x00\x00\x01\x00\x05\xa21\ -\x00\x00\x01x\xc7F\xef\xe6\ -\x00\x00!\xf2\x00\x00\x00\x00\x00\x01\x00\x06\x08h\ -\x00\x00\x01x\xc7F\xf0f\ -\x00\x00 p\x00\x00\x00\x00\x00\x01\x00\x05\xfa\x13\ -\x00\x00\x01x\xc7F\xf0k\ -\x00\x00\x1f\x1e\x00\x00\x00\x00\x00\x01\x00\x05\xec\x83\ -\x00\x00\x01x\xc7F\xed\xc2\ -\x00\x00\x1d\xcc\x00\x00\x00\x00\x00\x01\x00\x05\xdf9\ -\x00\x00\x01x\xc7F\xf0\x0e\ -\x00\x00\x1a&\x00\x00\x00\x00\x00\x01\x00\x05\xbc\xf6\ -\x00\x00\x01x\xc7F\xf0%\ -\x00\x00\x18\x98\x00\x00\x00\x00\x00\x01\x00\x05\xaee\ -\x00\x00\x01x\xc7F\xf0I\ -\x00\x00\x17\xac\x00\x00\x00\x00\x00\x01\x00\x05\xa8\x8b\ -\x00\x00\x01x\xc7F\xf0,\ -\x00\x00\x22\xce\x00\x00\x00\x00\x00\x01\x00\x06\x0f7\ -\x00\x00\x01x\xc7F\xed\xdd\ -\x00\x00!|\x00\x00\x00\x00\x00\x01\x00\x06\x05\xa9\ -\x00\x00\x01x\xc7F\xf04\ -\x00\x00\x1f\xfa\x00\x00\x00\x00\x00\x01\x00\x05\xf7\x93\ -\x00\x00\x01x\xc7F\xf0*\ -\x00\x00\x1er\x00\x00\x00\x00\x00\x01\x00\x05\xe4\xee\ -\x00\x00\x01x\xc7F\xed\xc6\ -\x00\x00\x1dV\x00\x00\x00\x00\x00\x01\x00\x05\xdc\xcf\ -\x00\x00\x01x\xc7F\xf0@\ -\x00\x00\x1c\x14\x00\x00\x00\x00\x00\x01\x00\x05\xd1A\ -\x00\x00\x01x\xc7F\xf0K\ -\x00\x00\x1bB\x00\x00\x00\x00\x00\x01\x00\x05\xc5>\ -\x00\x00\x01x\xc7F\xed\xcb\ -\x00\x00\x1e\x0c\x00\x00\x00\x00\x00\x01\x00\x05\xe0\xbb\ -\x00\x00\x01x\xc7F\xed\xc8\ -\x00\x00 \xb0\x00\x00\x00\x00\x00\x01\x00\x05\xfb@\ -\x00\x00\x01x\xc7F\xef\xa6\ -\x00\x00\x1c\x8a\x00\x00\x00\x00\x00\x01\x00\x05\xd4\x97\ -\x00\x00\x01x\xc7F\xed\xce\ -\x00\x00\x17\x10\x00\x00\x00\x00\x00\x01\x00\x05\xa3\xf0\ -\x00\x00\x01x\xc7F\xf0\x80\ -\x00\x00\x1f^\x00\x00\x00\x00\x00\x01\x00\x05\xf2\xa4\ -\x00\x00\x01x\xc7F\xf0:\ -\x00\x00\x19~\x00\x00\x00\x00\x00\x01\x00\x05\xb8\x88\ -\x00\x00\x01x\xc7F\xf0(\ -\x00\x00\x222\x00\x00\x00\x00\x00\x01\x00\x06\x09\x9b\ -\x00\x00\x01x\xc7F\xef\xdd\ -\x00\x00\x1b\xae\x00\x00\x00\x00\x00\x01\x00\x05\xca0\ -\x00\x00\x01x\xc7F\xed\xd1\ -\x00\x00!L\x00\x00\x00\x00\x00\x01\x00\x06\x00\xbf\ -\x00\x00\x01y+\x8f\x93{\ -\x00\x00\x1a\xa6\x00\x00\x00\x00\x00\x01\x00\x05\xc0J\ -\x00\x00\x01x\xc7F\xf0\x0c\ -\x00\x00\x18\xd8\x00\x00\x00\x00\x00\x01\x00\x05\xaf\xbd\ -\x00\x00\x01x\xc7F\xed\xa4\ -\x00\x00\x1c\xf0\x00\x00\x00\x00\x00\x01\x00\x05\xd9\x9b\ -\x00\x00\x01x\xc7F\xe9<\ -\x00\x00\x0e\xba\x00\x00\x00\x00\x00\x01\x00\x04/>\ -\x00\x00\x01y+\x8f\x94\x12\ -\x00\x00\x0d\x0a\x00\x00\x00\x00\x00\x01\x00\x03\x98\x9f\ -\x00\x00\x01y+\x8f\x93\xdc\ -\x00\x00\x0e\x80\x00\x00\x00\x00\x00\x01\x00\x04*&\ -\x00\x00\x01y+\x8f\x94\x08\ -\x00\x00\x0d~\x00\x00\x00\x00\x00\x01\x00\x03\xfb\x9a\ -\x00\x00\x01y+\x8f\x93\xcd\ -\x00\x00\x09\xf6\x00\x00\x00\x00\x00\x01\x00\x039/\ -\x00\x00\x01y+\x8f\x94\x10\ -\x00\x00\x09f\x00\x01\x00\x00\x00\x01\x00\x02p@\ -\x00\x00\x01x\xc7F\xf5\xfe\ -\x00\x00\x07\x12\x00\x00\x00\x00\x00\x01\x00\x01\x8f\x0b\ -\x00\x00\x01y+\x8f\x93\xce\ -\x00\x00\x08:\x00\x00\x00\x00\x00\x01\x00\x01\xaa3\ -\x00\x00\x01y+\x8f\x94\x0a\ -\x00\x00\x0f$\x00\x00\x00\x00\x00\x01\x00\x04q\x5c\ -\x00\x00\x01x\xc7F\xf6G\ -\x00\x00\x0e\x10\x00\x00\x00\x00\x00\x01\x00\x04\x1c\xbf\ -\x00\x00\x01y+\x8f\x93\xe3\ -\x00\x00\x08\xd2\x00\x00\x00\x00\x00\x01\x00\x02e~\ -\x00\x00\x01y+\x8f\x93\xd6\ -\x00\x00\x0eL\x00\x00\x00\x00\x00\x01\x00\x04$\xfa\ -\x00\x00\x01y+\x8f\x94\x09\ -\x00\x00\x09*\x00\x00\x00\x00\x00\x01\x00\x02m\xa1\ -\x00\x00\x01y+\x8f\x94\x07\ -\x00\x00\x0c \x00\x00\x00\x00\x00\x01\x00\x03|9\ -\x00\x00\x01y+\x8f\x93\xd5\ -\x00\x00\x07z\x00\x00\x00\x00\x00\x01\x00\x01\x9dG\ -\x00\x00\x01y+\x8f\x93\xdf\ -\x00\x00\x08x\x00\x00\x00\x00\x00\x01\x00\x01\xc5\xe8\ -\x00\x00\x01x\xc7F\xf6*\ -\x00\x00\x0f\x9c\x00\x00\x00\x00\x00\x01\x00\x04\x8ei\ -\x00\x00\x01y+\x8f\x94\x12\ -\x00\x00\x08T\x00\x00\x00\x00\x00\x01\x00\x01\xb0@\ -\x00\x00\x01x\xc7F\xf61\ -\x00\x00\x0cb\x00\x00\x00\x00\x00\x01\x00\x03\x88{\ -\x00\x00\x01y+\x8f\x93\xda\ -\x00\x00\x07B\x00\x00\x00\x00\x00\x01\x00\x01\x93\xaf\ -\x00\x00\x01y+\x8f\x94\x11\ -\x00\x00\x08\xf8\x00\x00\x00\x00\x00\x01\x00\x02i,\ -\x00\x00\x01y+\x8f\x93\xce\ -\x00\x00\x0a\xc0\x00\x00\x00\x00\x00\x01\x00\x03U\xfe\ -\x00\x00\x01y+\x8f\x93\xd8\ -\x00\x00\x09\xc8\x00\x01\x00\x00\x00\x01\x00\x03\x19<\ -\x00\x00\x01x\xc7F\xf5\xf8\ -\x00\x00\x06\x92\x00\x00\x00\x00\x00\x01\x00\x01\x84\x05\ -\x00\x00\x01y+\x8f\x93\xcc\ -\x00\x00\x0a\xf8\x00\x00\x00\x00\x00\x01\x00\x03Y\xb0\ -\x00\x00\x01y+\x8f\x93\xdb\ -\x00\x00\x0d\x98\x00\x00\x00\x00\x00\x01\x00\x03\xff8\ -\x00\x00\x01y+\x8f\x93\xdc\ -\x00\x00\x0c<\x00\x00\x00\x00\x00\x01\x00\x03\x83Z\ -\x00\x00\x01y+\x8f\x93\xde\ -\x00\x00\x0bZ\x00\x00\x00\x00\x00\x01\x00\x03^A\ -\x00\x00\x01y+\x8f\x93\xd8\ -\x00\x00\x0a\x94\x00\x00\x00\x00\x00\x01\x00\x03@.\ -\x00\x00\x01x\xc7F\xf60\ -\x00\x00\x0f\x00\x00\x00\x00\x00\x00\x01\x00\x04g\xe4\ -\x00\x00\x01y+\x8f\x94\x13\ -\x00\x00\x0fN\x00\x00\x00\x00\x00\x01\x00\x04\x86$\ -\x00\x00\x01y+\x8f\x93\xe2\ -\x00\x00\x0dD\x00\x00\x00\x00\x00\x01\x00\x03\x9c*\ -\x00\x00\x01x\xc7F\xf6\x18\ -\x00\x00\x0a0\x00\x00\x00\x00\x00\x01\x00\x03;\xce\ -\x00\x00\x01y+\x8f\x93\xd9\ -\x00\x00\x060\x00\x00\x00\x00\x00\x01\x00\x01!\xdb\ -\x00\x00\x01x\xc7F\xf6\x1b\ -\x00\x00\x0b\xe2\x00\x00\x00\x00\x00\x01\x00\x03w\xc6\ -\x00\x00\x01y+\x8f\x93\xd7\ -\x00\x00\x06\xf0\x00\x00\x00\x00\x00\x01\x00\x01\x8b\xd2\ -\x00\x00\x01y+\x8f\x93\xfd\ -\x00\x00\x07\xb8\x00\x00\x00\x00\x00\x01\x00\x01\xa2j\ -\x00\x00\x01y+\x8f\x94\x0f\ -\x00\x00\x0f\xce\x00\x00\x00\x00\x00\x01\x00\x04\x98\x10\ -\x00\x00\x01y+\x8f\x93\xcb\ -\x00\x00\x0e\xd0\x00\x01\x00\x00\x00\x01\x00\x046\xb1\ -\x00\x00\x01x\xc7F\xf5\xf3\ -\x00\x00\x06^\x00\x00\x00\x00\x00\x01\x00\x01\x81c\ -\x00\x00\x01y+\x8f\x94\x06\ -\x00\x00\x09\xb4\x00\x00\x00\x00\x00\x01\x00\x03\x13\xbb\ -\x00\x00\x01y+\x8f\x93\xd0\ -\x00\x00\x0f\xf8\x00\x00\x00\x00\x00\x01\x00\x04\x9a\xca\ -\x00\x00\x01x\xc7F\xf5\xf0\ -\x00\x00\x09\x86\x00\x00\x00\x00\x00\x01\x00\x02\x93\xaf\ -\x00\x00\x01x\xc7F\xf6$\ -\x00\x00\x0d\xe4\x00\x01\x00\x00\x00\x01\x00\x04\x02\xc3\ -\x00\x00\x01x\xc7F\xf6\x04\ -\x00\x00\x0c\xec\x00\x00\x00\x00\x00\x01\x00\x03\x91\xbf\ -\x00\x00\x01y+\x8f\x94\x0e\ -\x00\x00\x0b\xaa\x00\x00\x00\x00\x00\x01\x00\x03b\xb8\ -\x00\x00\x01x\xc7F\xf6L\ -\x00\x00\x06\xb8\x00\x00\x00\x00\x00\x01\x00\x01\x86\xad\ -\x00\x00\x01y+\x8f\x93\xe0\ -\x00\x00\x0c\xb0\x00\x00\x00\x00\x00\x01\x00\x03\x8d\x1f\ -\x00\x00\x01y+\x8f\x93\xdd\ -\x00\x00\x07\xea\x00\x00\x00\x00\x00\x01\x00\x01\xa5\x0c\ -\x00\x00\x01y+\x8f\x93\xe1\ -\x00\x00\x08\xb4\x00\x00\x00\x00\x00\x01\x00\x02O\xe4\ -\x00\x00\x01x\xc7F\xf6D\ -\x00\x00\x11\x06\x00\x00\x00\x00\x00\x01\x00\x05H\x0b\ -\x00\x00\x01y+\x8f\x93\xd4\ -\x00\x00\x11\x88\x00\x00\x00\x00\x00\x01\x00\x05r\xc6\ -\x00\x00\x01y+\x8f\x93\xd1\ -\x00\x00\x11b\x00\x00\x00\x00\x00\x01\x00\x05`\x84\ -\x00\x00\x01y+\x8f\x93\xcf\ -\x00\x00\x11\xa0\x00\x00\x00\x00\x00\x01\x00\x05v\xe1\ -\x00\x00\x01y+\x8f\x93\xd2\ -\x00\x00\x10\x94\x00\x00\x00\x00\x00\x01\x00\x05A\x0f\ -\x00\x00\x01x\xc7F\xf8/\ -\x00\x00\x106\x00\x00\x00\x00\x00\x01\x00\x05(\xda\ -\x00\x00\x01x\xc7F\xf8,\ -\x00\x00\x11 \x00\x00\x00\x00\x00\x01\x00\x05N\x15\ -\x00\x00\x01x\xc7F\xf83\ -\x00\x00\x10\xdc\x00\x00\x00\x00\x00\x01\x00\x05G=\ -\x00\x00\x01x\xc7F\xf8(\ -\x00\x00\x10`\x00\x00\x00\x00\x00\x01\x00\x05)g\ -\x00\x00\x01y+\x8f\x93\xd3\ -\x00\x00\x11J\x00\x00\x00\x00\x00\x01\x00\x05N\xb9\ -\x00\x00\x01y+\x8f\x93\xca\ -\x00\x00\x10z\x00\x00\x00\x00\x00\x01\x00\x057Q\ -\x00\x00\x01y+\x8f\x93\xc9\ -\x00\x00\x10\xbe\x00\x00\x00\x00\x00\x01\x00\x05A\xbe\ -\x00\x00\x01y+\x8f\x93\xe3\ -" - -def qInitResources(): - QtCore.qRegisterResourceData(0x03, qt_resource_struct, qt_resource_name, qt_resource_data) - -def qCleanupResources(): - QtCore.qUnregisterResourceData(0x03, qt_resource_struct, qt_resource_name, qt_resource_data) - -qInitResources() +""" +Copyright (c) Contributors to the Open 3D Engine Project. +For complete copyright and license terms please see the LICENSE at the root of this distribution. +SPDX-License-Identifier: Apache-2.0 OR MIT +""" + +from PySide2 import QtCore + +qt_resource_data = b"\ +\x00\x00\x01\x84\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\ +\x00\x00\x01KIDATx\xdac`\x18\x05\xa3`\ +\x14\x0c&\x10\x91\x90\xe3\x18\x99\x98{\x08\x88\xf7\x810\ +\x90\xbf\x1f\xca\xd6\xa6\x8b\x03\x80\x165\x01-\xfd\x0f\xc3\ +@>\x8c\x1dK\xaf\x10h\x00Y\x0a\xc3@\xfe_(\ +{5\x10\x9b\x01\xf9V@\x1a\x8e\x89\xe4[\x03\xb1>\ +\xa5\x0e\x80\x87\x06\x05|\xf5\x81v\x80\x1e1i\xa0\x01\ +\x1a\xe7\x7f\xa1\x96\xff\x83\xf2o\x00\xf1\x19 \xff\x0c\x88\ +\x86a\x12\xf8\x97\x81X\x85\x9c\x10\x00\xd1\x13\xe8\x99\x0d\ +\xd1\x1d\xf0\x05Hs\x00\xb1\x1b\x10_\x07\xf2o\x02\xe9\ +\x1b0\x0c\x0a\x192\xf8\xb7\x80\xf80\x10\xb3\x12\xe3\x80\ +\x1ah\xd4<\xa4B\x1a@\xe6\xcf%\x94\x06@q\xff\ +\x1d\xea\xa8tX\xba\x80\xa6\x89\xbfhi\x84T>\xc8\ +,)b\xa2\xa0\x0c\xea\xa8gxr\x05\xa9|\xdc\xbe\ +Gs\xc0+ f\x06\xf23)\xb4\x10\x1b_\x94\x18\ +\x07\xe4A\xf9\xaf\xa9\xec\x80i\x84\xca\x81F\xa0\xa2W\ +@\xcc\x04\xc4i0C(\x8c\xf3\xbf\xd04\xf5\x03\xc8\ +\x97!\x94\x0d\xdb\x81\x8ar\xa0\x8ey\x8a%\x15S\x12\ +\x02\xd3\x88)\x07R\xa0\x96gQ1\xceA\xec_@\ +,A\x8c\x03\x98\x81\x0a9\xa1\x89\x90\x9a\xf9~\x1a)\ +\xa5\xa1\x0a\x10o\x07\xe2\xcd@\x8d\x9b\x81\xf4&\x18&\ +\x93\xbf\x14\x88yF\x9b{\xa3`\x14\x0cZ\x00\x00\xef\ +\xad\x00\xe1,\x84\xf5\xf4\x00\x00\x00\x00IEND\xae\ +B`\x82\ +\x00\x00\x02h\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\ +\x00\x00\x02/IDATx\xda\xed\x96\xcb+\xc4Q\ +\x14\xc7\xe7\xe11\xcd\x90\xc9L\x1a\x22e\xe4\x91YL\ +\x13\x8a\xa2lllX\xa1\x94WQ\xc6\xb3\xd8x\xd4\ +\x10\x0bE\x8d\x14\xfe\x03\x0b\x89\xb2\x96\xc4\xc2B\xf2(\ +\x22\x0by,lH\x16\x1e5\x8d\xef\xad\xab\x8e\x99{\ +~\xbfYZ\xfcn};\xbf\xee\xe7\x9e\xf3;\xfd\xee\ +\xb9\xe7wM\xa6\xff0Z;\x07J\xa0\xf5\x96\x8e\xfe\ +a\x8d5\xed\xe0\x1b\xb0\x95\x0c\xb7\x83\x87aW\xc4\xb3\ +j\x0dx\x00l\x13\xea\x8au>\x82\xa2X\x10\x85\xf5\ ++\x82g\x13~\xcf$0.\xb9P\x88I\xe0Jr\ +!/u\xde!/(P\x04\xcf\x80\x22\x92\x9f0\x09\ +t\x93\x04\x82L\x02\x07\x92G \x0f\x056\xa8\x07\x93\ +\x15\xdc\x16\x80\x8bm\x0a\xc2:5\xb6\xa9\x09\xbcY\x83\ +\xa7\x83\x8b\x18>\x931\x8c\xa1(\x90L\x14\x87Uk\ +\x0d\xb8[\x87\xdb\x11'M\xe7=.\xc8\x1c;9)\ +\x8f\xe1\x13\xacC\xe1d\x85\xce\xe51[e\x02W\x83\ +G\xe41\xaba\x12\x5c\x94\xfc\x02\xb2Q\xe7k\xd2\x07\ +j\x15\xc1\xbd\x84\xbf0\x09\xcc\x93>\x10Vp3\xf8\ +\x03iDe43\xd1f_1y\xc8m\x03\xe6\xb7\ +\xc0\xdf`\xc7\x18^\x0c~'^\x02\x952I\x0e\x81\ +\xbdC\xdb\x90%\x16Z\xf4\xeaD\xafF\x12\xac5\xab\ +q\xe2\x8c\xa1*\x8c\x5ch\x19E\xd6\xa6\xb1\xa6\x01\x5c\ +\x5c6\xb8\x0aO\x02\x17\xfdd\x1aJf\x8aX\x1c\xe7\ +5\xa81\xd6y\x9f\x9cs\x9f\x22x\x16\xe1\xb7L\x02\ +#\xa4\x0fL0\x09\x9c\x91>\x90O\xc1\xee\xaf3l\ +\x91\xc2\xd1E\xf8%\x13|\xf07Ih\x94I\xf2X\ +r\xa1\xbc?\xff\x01\xd1\x8e1Y\xaf\xb1\x05U\xe0!\ +\xd8\x1c\x8d>\xd1\xcb\xdd\x86$\xf7\x80\xcfp\xad\xda\x18\ +F/p\xc6\xfd\xa1\xe2\x8b(3\x81\x0b\x89C\xef\xe2\ +\xa3\x9a\xec\x83>\x10\xe0\x146\x85q\x14G\xf5\x0bv\ +\x96\xe1~\xf0gq_\x80\x02L\x82S`\x22\xc6\xde\ +\x9ff\x05pC\xcey\x9d\xc2\xb1\x90\xf0W&\xf8\x02\ +\xe9\x03K\x0an\x01\x7f$}\xa0\x8cf\x1f\x84>e\ +\xa7J\xd5\xf9\x02s\x09|\x81r&I\xd1\xaa\xbf\xe3\ +\xbe\x00\xb9\x94\xea\xd5\x80\xde\xa5\xd4\x91@\x0d\xb8\xffU\ +\xf1\xff\x00\xf0W\x81\xb2\xb1-\xb20\x00\x00\x00\x00I\ +END\xaeB`\x82\ +\x00\x00\xa1\xcb\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x80\x00\x00\x00\x80\x08\x06\x00\x00\x00\xc3>a\xcb\ +\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\ +\x04gAMA\x00\x00\xb1\x8f\x0b\xfca\x05\x00\x00\x00\ +\x09pHYs\x00\x00\x0b\x22\x00\x00\x0b\x22\x01\x09\xe1\ +O\xa2\x00\x00\xa1`IDATx^]\xfdg{\ +cI\xb2\xa5\x89\xf2\x0fMF\x04\xb5\x04@\x90\x00\x08\ +j\xad\xb5\xd6Zk\x15\xd4:\x14\x19Z\xeb\x88\x8c\x94\ +\x91:\xab\xb2\xeaTU\xd7Q=\xdd}\xfav\xf7\xcc\ +<\xf7\xfe\x13\xbb\xef\xf2MFe\xcf\x07{\x00\x92 \ +\xf6\xden\xcb\xcc\x96\xb9\x9b\x9b\xc7\x84\xc7\x1f[\x04\xc9\ +Ar'\x9eZ\xf1\xec+\xabX\xfe`5\xeb\xdfX\ +\xc3\xd6\xf7\xd6\xb4\xf3\xa35\xec|o5\x1b_Y\xc5\ +\xea;+Y|n\x05\xb3\x0f-:qf\xe1\xa1c\ +\xcb\xea\xdd\xb2@\xfb\x92\xa57MYZ\xfd\x88\xa5\xd6\ +\x0dyR?li\x0dc\x96\xd68\x8eLx\xaf\xfc\ +\x9cZ7b)\xb5\xc3\x96\x5c3dI\xd5\xc3\xc8\xa8\ +%\xd5LXr\xdd\x8c\xa54,Xj\xd3\x8a\xa5\xb7\ +\xae\x9b\xafs\xdb\x02\xbd\x07\x16\x1c\xe0\x1a\x83\xd7,{\ +Hr\x82\x1c\xf2\xbb=\xcb\xec\xdf\xb6\xcc\xbe\x0dd\x1d\ +Y\xb3\xcc\xde\x15\xcb\xec^\xb2\xcc\xae\x05\xf3\xb7\xcdX\ +F\xd3\xa8\xa5\xd6\xf6ZRE\xab\xc5\x17\xd7ZlA\ +\xa5]\xce\xaf\xb0K\x055v\xa5\xb8\xd5\x12\xaa\x87,\ +\xade\xd1\xb2\x07\x0e\xadp\xe6\xa1U\xae\xbc\xb3\xba\xcd\ +o\xac~\xeb;\xabZ\xfb\xc2\x0a\xe7\x9e3.w,\ +\x93k\xfb\xfa\x0e\xcc\xd7\xb3o\xfen^\xbb\x90\xce]\ +^w-\xd8\x7f\xc8\xb8\xdd\xb4\xc2\xf9\xfbV\xb6\xfa\xcc\ +*\xd6_Y\xf9\xfaK+\xe5}\xf1\xf2c+Z~\ +\x80\xdc\xb3\xfc\xc5\xdb\x96;\x7fj\xd1\xb93\xe4\x8e\xe5\ +-<\xb0\xd2\xf5\x17V\xbb\xf3\xceZ\x0e\xbe\xb0\xee\xe3\ +\xaf\xad\xff\xda\xb76p\xed\xa3\x0d\xde\xf8\xd1F\xef\xfc\ +\xc9&\x1e\xff\xb3M\xbd\xf8\xaf6\xf7\xfa\xffc\xf3\xaf\ +\xff\x87-\xbc\xf9\x1f\xb6\xf2\xf6\x7f\xd9*\xb2\xfc\xfa\x7f\ +\xda\xc2\x8b\xffn\x93\x8f\xfe\xdd\xfaO\xffj]\xd7\xfe\ +h\xedG\xbf:\xe9:\xf9\xa3\xf5\xdd\xfc\x8b\x0d\xdf\xfe\ +\xbb\x8d\xdf\xffw\x9b~\xfc_m\xe6\xc9\x7f\xd8\xe4\xc3\ +\xffb\xa3w\xff\xcdzo\xfc\xcd\x9a\xf7\xff`5\x9b\ +\xdfs\xcf_[Ld\xec\xaeE\xc6\xeeYt\xfc\xbe\ +\xe5M>\xb2\xe2\xb9\x17\x0c\xc6{\xab\xbd\xfa\xb552\ +\x18\xcd\xbb?X\xf3\xcewV\xbf\xf9\x95U\xaf\xbd\xb3\ +\xf2\xa5\x17V2\xf7\xc8\x0a&y\xa8\x91k\x16\xe9\xdf\ +\xb5\xec\xee5\x0b\xb6\xcf[\xa0e\xca\xfc\xcd\xe3\xe6k\ +\x92L\x98\xafy\xd22.\x84\x9f\xd3\x01Az=\xa0\ +\xa8\x93r\xc6\x00\x82\x14?e\xc9\xf5s\x96\xd2\xb8h\ +\xa9\xcd\xab\x96\xd6v\xd52:\xb6\x18l\x94\xdcwd\ +A\xa7\xfc\xeb\x96=\x8c\x00\x80\xacA~7\xb0\xcf\xdf\ +\x04\x90\x0d\xf3\xf7\xac\xf1\xd9\x15d\xc9\xfc\x9d(\xbfc\ +\xce|\xadS\x5c\x0b0\xd6\xf6YRe\xbb%\x944\ +Z\x5cQ\xad])D\x8a\x1a-\xb6\xb4\xd3\x12kF\ +\x1d\x00\x82\xbd{\x967~f\xa5sO\xadr\xe9\x8d\ +U\xf1\xec\xe5\x0b\xaf\xacp\x1a\x90\x8f\x9d9\xe0I\xd1\ +\x99\xbd\xe7\xd2sd\x81\xee}\x0b\x00\x88`\xff\x91\x85\ +G\xaf[\xde\xd4\x19\x80\xb9o\xc5\x0b\x8c\xdf\x22\x8a_\ +xh\x85\x0b\xf7\x91\xbbV\xb8x\xd7\xf2\xe6Q\xfc\xec\ +-\xcb\x99\xb9e\x91\xe9S\xcb\x99\xbem\x05\x80\xa6\x14\ +\x90T\xaf=\xb3\xc6\x8d\x17\xd6\xba\xf5\xca\xdav\xdeX\ +\xc7\xfe\x07\xeb\xb9\xfe\xd1\x06n\xffj\xc3\x0f\xfebc\ +\x8f\xfe\xeed\xea\xc9?\xdb\xc2\xf3\x7f\xb5\x85g\xffb\ +s\x8f\xff\x93M?\xf8'\x1b\xbc\xf5\xb3\xb5\xee\x7fe\ +\x8d\xdb\x1f\x90/\xd0\xd5\xd7\xd6~\xf8\xbd\xf5\xdc\xf8\xd5\ +\x06\xce\xfe\xc9F\xee\xfd'\x1b\x7f\xf8o\x00\xe5?\xdb\ +\xf8\x83\x7f\xb3\xa1;\x7f\xb7\xee\xeb\x7f\xb6\xa6\xbd\x1f\xac\ +\xea\xea\x97\x5c\xff\x1d\x00\x18\xbd\x09\x8aO\xb1\xfe;V\ +0\x0d2\x17\x9ec\x01\xb2\x86/\xadi\xfb[k\xd9\ +\xfd\x0e\xf9\x160|iu\xeb\xef\x18\xa0\x17V6\xff\ +\xc8\x8a\xa6n[\xfe\xd8u\xcb\x1d:\xb0\x9c\xbeM\x0b\ +w\xafZ6\x0a\xc8F\x01Y\xed\xb3\x16l\x9b\xb5L\ +$\xd0:k\xfe\x96i\x80\x018\xf0\x12\x12_\xe3\x94\ +e4\xce\xa0\xa4yKk\x92\xe2W,\x0d\xabOo\ +\xdf\xb4\x8c\xce\x1d\xf3i\x805\xd8\xfd'\x0e\x00Y\x00\ + \x0bEd\x0d\xea\xe7c\x00p\xc0\xdfv\xf9\x0c@\ +\xe9\xb9\x8a\xf2W\xb1\xca%\xf3u,\x98O\xd6\xdf\x8c\ +\xc7i\x18\xb6\x94\x1a\x01\xa0\xc3\x12\xcaZ,\xbe\xb4\xd9\ +\xe2Jx-\xeb\xb4\x84\xaa\x01@7\x89\xa7Y\xb6`\ +\xcf\x8eE\x86\xafY>\xcf_4\xfd\xc8Jf\x9eX\ +\xd1\xe4\x03\xcbC\xf9\xfa\xbdW>\x7f\xd7\xaa\x16\xefY\xcd\xca\ +C\xab_\x7f\x8a\xc1\xbd\xb6\xb6\xc3\x0f\xd6\x81W\xe8\xbe\ +\xf1\xbd\x93\xbe\x9b\xdf\xdb\xe8\xd9\x8f6r\xfa\x1d^\xe2\ +k\xeb;\xfe`\xad\xdb/\xadj\xf9\xa1U,=@\ +/\x8f1\xda\x97\xd6\xb4\xfb\xde\xda\x8e\xbe\xb1\xae\xeb?\ +X\xef)@\xb8\xfd\x9b\x0d\xdc\xf9\xb3\xf5\x9d\xfe\x91\xdf\ +\xfd\x8c\xc7\xf9\x887\x7foe\xcb/\xf0\x5c\x8f-&\ +:\x0e\x82'o\xa2\xfc\xdbX\xff}+_~\x8a\xfb\ +\x7f\x8d\xc5\xbf\xf7P\xb5\xf3\xa55\xf3\xda\xc8?\xd5\xf1\ +\xfb\xea\x95\xe7V\x01\xd2Kf\xeeX\xe1\xc4M\xcb\x1f\ +9\xb6\xbc\xc1=\x8b\x0elY\xb4\xef*`X\xb3H\ +\xef*\x80X\x01\x10K\x96\x85R\x82ms\x16\x04\x08\ +\x9e\xcc\xf33\x96\xd7\xb6j\x99\xed(\x0fk\xf7u\xa0\ +\xf4\xae=\x14\x7f\x80B\xb1\xb0>\x06\xb9\x1f\xcb\x1b\x90\ +\xd2\xaf;\x10\x04\x9d\xf2/\xe4\x08\xd7\x8c\x12\x08\x05\x01\ +<\x81\xbfg\x83\xff\x07\x04\xed\x8b\x96\xd1\x0a\xb0\xf06\ +\x0aA\xc9\xb5\xfd\x96T\xd5\x0d\x08\xba\x10^\xab\xfa\xf1\ +:#\x80\x03\x00\xb6.\xe21\xd6Q\xe8\x0e\xa1\x0cW\ +>\x02\x98GO-o\xf4\xccr\x87Q\x10\xd7\x09\xf7\ +\x1fXv\xdf\xaee\xf5\xe0\xeee\xf1(>\xc8\xbdI\ +\xe4\x9d2\x09\x0d\x99x\x90L\xbeC\x12\xec\xc5\x1b\xe2\ +\x9dB\xc3\x87x\xd5#\xcb\x99<\xb1\xdc\x99\xeb\x16E\ +\x22\xd37,\xb12\xc0V\xbd\ +\x06\x88\xb6_X\xe3\xde[k9\xfc\xdcZ\x8f\xbe@\ +\xd0\xe1\xfe\xe7\xd6\xb0\xfd\xd6\xaa\x09=eK\x8f\xf0X\ +w-\x1f\xf0\xc5\xe4q\xd1\xfc\x99\x9bV\x04ZKp\ +Y\xe5 \xaaz\xed\x89\xd5\xae?C\xe1\xcf\x91\x97V\ +\xb7\xfa\xd2jAL\xf5\xd23\xab\x5cxles\x0f\ +\xacdZ\x00\xb8e\x05\xa3\xdc\xc4\xc8\xa1\xe5\x0fs#\ +\xc3\xbb\x967\xbc\x83W\xd8\xb2\x9c\xfe\x0d\x0b\xf7\xaeY\ +\xa8k\x19\xaf\x80g D\x84x\x0dw\xaeX\xa4{\ +\x03\x90\xec\x12>\x0e-\xa4\x18?p\x822O,\x80\ +\xf8Q|\x00q\x00\x90\x07\xe8g\xc0q\xb5\x99\xb2>\ +^\xb3\x1c'@\xc4?\x18\xbcL\x06<\xd0\xbb\x0d\x00\ +\xd6-\x03`\xa5\xb7\xccX*\xa1&E\x00\xa8\x1b\x04\ +\x04\x03\x96\xc2kj=._\xde\xa7m\xc1\x02\x9d\x84\ +\xac\xdeM\x94\xb5k\xa1\xa1}\x0b\x0f\x1f G(\xe4\ +\xc4B\x5c/\x9bke\xf7\xee[6\x8a\xcfF\xb1\xd9\ +(9\xc4\xefB\xdc_h\x10%\x02J\xdds\x10\x00\ +\x04\xba\x01o\x07a\x0b@K\x1c\xa8\xf0\x88!\xc6!\ +2q`Q\x14\xe3\x000u\xc3B\xe37\x9c'\x13\ +x\x5c\x18\xc1\xdbevm\x01\xae-\xae\xb9ea\x8c\ +(\x87\xb1\xcb\x1d\xde\x02\x14\xdb(v\xd7\x0a&\xf6\x90\ +}+\x9e>D\xe1'V1{he\xd3\xbbV<\ +\xb1i\xd1!\xf1\x1e\x7f\xe4\x00!\x9e\x8e\xec\xf2\x00;\x963@X\ +\xe8]w\x9e \xdc\xc5\xcd!9\xbc\xcf\xed\xbdj\xb9\ +\xb8\xef\x5c\x94\x97\x8b5Dq\x87\xe1\xb1\x9b\x96\x85\x0b\ +\xcd\xc4\x0a\x03X\xbb\x1f\xc5\xfb5HX\x9cbm\x00\ +>\x10\xe8\xd9s\x03\xee\xb9\x5c\x06\x94\xff\xd1\xff\x85\x00\ +`pP\x9ec\xcb2\xda\x09%-s\x00`\x12B\ +\x09\xc7\x80\x94\xa64\xc07D@\x09C\x19x\x88@\ +\xf7:\x83\xb5\x85\xe2\xf7,2\x8a\x95\x8e\x1fC\xf6\xf8\ +\xceQ\x11L)U\xca\xe1z\x90P\x7f\xc7&\xaf\x9b\ +\x16D\xc9\x02E\x88P\x14\x199\xe5\xfa\xa7\x8e\x97\xe8\ +~\xfc]\x9b\x96\xde\xb6L\x18\x9b\xb7\x94\xe6YB\xd9\ +\x19\xf7\xd1M\xc6h\x9b\xe7\xdb\ +a\x8cw!\xed{\x84\xa8}\xe4\xc0r'\x8f,:\ +y\x8c\x9cXL\xc1\x0cDe\xd6\x93\x22\x85\x81\xa9[\ +V\x02ZK&\xafY1R4y\x1d\x81\xe9\xe2\xee\ +\x0b\xe4\xf2Aq\x9eb?\x03\x16E\xf19\x83\xfb\x16\ +\x19\xdc\xe5\x15\xc4\x0fn#B2\x16@8\xc8\xeeY\ +\xb5\x10J\x8f 9\xbc\xcf\x05\x10\xf9\x03 \x1b\x8b\xcb\ +\xe7\xff\xf3\xf8\xbe\x5c\xae\x17\x01\x84\xa1\x09\x06\x94\xdf\x05\ +\xb0\xec\x00V\x1e`\xc0\xfdX\xa1\xc8\xa0\xbfk\x07\x81\ +\xf5c\x91\x22\x81\x22^\x11\xbcO\x0e\xe4+\x02\x10\xb3\ +\x01\x81<\x81\xbf\x1be8\x10\xcc\xa3\x10\xb2\x8a\xa6i\ +^\x91\x16\x14\xd36\x8f\xa5.;\x00\x04\xfb\xb9\xbf!\ +\x5c\xff(\xd6?\x8er\xc6\xb1\xf81<\x8d\xae\xad\xeb\ +b\x9d.,\xc1I\x1c\x08\xb8v\x90{\x91\xe2B\xc3\ +x\x80\xa1\x1b\x84\xa7#>\xb7\xcd\xf5V\xb9\xc6\x9c%\ +\x13V\x92\x1a&-\xb9i\xd2R[QL\x07\xdc\xa7\ +{\x01O\xb6\x0a@7p\xfbx\x9ba\x80\x06\x00\xc2\ +|G\x18/\x12\x22\x94\xb8\xf0\xd2\xb5A&\xb5l~\ +B\xa4\xafe\xc2e0\xe9MCp$\xa4i\xd8\xd2\ +\x9bG\x10~\xd7\x0c\x81n!\x93j\x01\xd4N\xf43\ +\xc4\xba\x15\x92\x0d\xf1\xcdh\x9b\xe6\xbeg\xe0Cs\x5c\ +{\x1e\xa3\xc0\xdb\xe1\x192\x07\x00\xe3\xe0\xba\x85F\xb6\ +\x00\xc5>`8f\xdc\xd1#\x844\xa6d\xe99\xee\ +\x82\xb4E\xc4N`\x90\x92\xb1\x8c\x5c,$g\x00\xa5\ +\x22a$$w\x89\x84%X\xb0'\xfc\x9e\x18\x1c\x92\ +E\xe1\xf6\xb2Qz\x16J\xce\x82\x99\x07Qz\x10\xab\ +\xcf&\x04\xc8\x0b8\x00\xf0\xf7<\xbe+\x0f\xb7\x9b;\ +\xc25\x88{\xd1\x09b-7\x94=\x86\x8b\x1f\xc1\xda\ +\xf9[\x00\x92\x17 \xfe\x06 _\x01\xdc\xaf\xdc\xac\x06\ +\xdb\x01\x00R&\xab\x8f@\xa6\xc4\xa6s \x5ca\xee\ +9\x8b\xc1\x0dpO>\xc2Kz\x87\xb2\x09\xac\xb2u\ +\xc9IZ\x9b'\x19\x00\xc0\xd7\xb5\x827A)\xfd\xdc\ +\xa7S\x0c\xeewd\x87Wb\xbcx\x85\xc2\x8d<\x0f\ +|$\x00/\xc9D\x82\xe7\xde\xc7\x0b?\xe2&\xf2N\ +\x5c\x0b\xcbM\x83K\xa44\xcd8\x00$\x03\x80\x14R\ +\xdeT8H\x1aDT\x8a\xf1\xb5\xcf\x00\xdeE\xee\x1d\ +\x83\xe8\xc7\xeb\x10\x02r\xe0\x18\xd1\x91[\xb8p\x80 \ +\x22\xd9\xb3i\x99\x1d\x90X\xb2\xa8t\xc8k*\xdc%\ +\xa5\xa6\xc7\x92\xab\xbbH\x97\xbb\x09c\xbc\xaf\xebC\xfa\ +!\xaf\x10\xd8\x06\xc9 \xd7\xe2\xb3\x8d\x0amx8]\ +\x13\xf0\xe9\xbai\x80(\x8dk\xa7\xb5O[z'@\ +\xe8\xc5\xb3\x0c\xe0\x8dF\xe1j\x18t\xfe\xccm+\x9a\ +\x7fH\xc6\xf2\xd4b*\xaf~n\xe5\xabo\x88\xff\xcf\ + \x82\xf7\xb1\xec\x1b(\x1dW\x0b\xc3\x0ev\xc95\xad\ +\xe3^H\xb5\x10\xc5\xceL\x5cU\x90\xd7\xac.\x09\x83\ +\xe8\x04\x85#\x99\x1a\x5c\xdcX@.\x90x\x1fh\xc7\ +\x9dA\x04\x9d\x17\xe8Y\xb7\x1c\xe2n\x94\xfc=\x0a\x88\ +\x22\x10\xb80 \x0b\x112\xb2P@p\x18\x05\x0f\x91\ +\xda\xe1I\x02\x90\xcaL<\x8b\xac:\xb3_ \xd8\x05\ +\x00\x02\x011S\x8c\x9c\xf0\x91=v\x0d\xaf\xc1\x00N\ +*\xb6B\x16\x01\x94\xf3\x02\xf0\x81\x0cy\x82N\x01\xe1\ +*\x16\xba\xce@\xac\x01\x00<\x03 H\x87'dp\ +_J\x19\x03\xa4\x8e\x01\xcd\x1fh\x1e\x01\x00\x07\x01P\ +\x96\x14\x22\x1e\x00\x07\x099\xc1\xeae\xf9(_\xe1G\ + \xd0=\xf8\xbb\x15r\xf8^R\xc9\xd4&\xd2X@\ + I\xd5|\x88\x14\xa1\xb0\x83b\x94\x02\xfb\xb0\xec\x00\ +\xdcG|\x22\xc2wDG\xb0\xbe\xd1[\x18\x01c\x0d\ +\xe8\xb2\x19\x97L\xc6\xcd\x87\xe7HG\xa1\x9aGI\x11\ +w\xa9A\xe1\xff/IrBv\x03H\xc4q\xc4u\ +R\x95Z7\xa0tB\x9f\xe6\x5c\x04\xc0T\xae\x9b\x06\ +!\xf6\xc2\x11\xe0#\xc2\ +\x00\xd6\xef\xc3\x12\x15\x16\x02()\xa0\xf9\x00\x88[\x90\ +0\x14$\x15\xd5\xe7\xfd|\xb7O\x84\x10o\x91\xc1\xfd\ +g\x10_3p\xe1\xe9m\xb2T\x00\xd0\xbc\x88\xcc\xe1\ +J\x19\x18\xc8\xa2\x14\xe3\xee\xb5\x83g\x121D\xa9\xd9\ +(7\x8c\x92#\x837 dX\xaa2\x02\x5c\xb6,\ +W$Qia\xa6\x00I\xec\xcf\xc0\xfd+\x95\x14\x08\ +\xd2\x9a\x17x%\xad\x15\x0f\x10\x08\xce'\xbf\xd2\x01\x83\ +\xafu\xce\x19N\x08\x8f\x19\xc5S\xe5\xc1w\xf2\xe0>\ +\xb9\x84\xd2\x1c\xee?\x84Qduc`\x18\x8dOJ\ +#e\xd6\xff\xa5\xa3P\x89\xfb\xae\xfaq\x801\x0a(\ +.&\xd1\x06\x01\xc2\x10\xdeA\x80\xe1\xef\x0d\x80\xa7i\ +\x96\xffE\xe0A\x19\x0ay\x18_\x00\xce\x95%oN\ +\x88-\x9c\xbf\x87\xb1C\xee\xb7\xde\x93\x0e~c\x9d\xc7\ +?ZL7\xf9b\xe3\xee\x97V\xbe\xf2\x12rp\x8f\ +\xd8\x08\x19S\xec\x85\xfc\x88\xd5\xa6\xc9\x85\xb6\xf0p\x90\ +\x9ct\xbe\xd8\x87\xf8y\xd0@+\xf1M\x22@\x00\x8c\ +\x00\xaf~~\xfe\xbd\xe8\xf7Y\xb8\xe3\x10n9\xdc\x03\ +?`\xe0\xc2H\x88\xf7A,4\xc0\xdf|\x9aE\x04\ +(\xe9\xdcp:\x8a\xc8\xc0\x8b\xf8\xb9i\x7f?\xe4\x08\ +O!\x00\xf8\x09\x07Np\xc3nVN\x82g\xf0c\ +\xb1~\x06\xd5\xafT\x10\x8f\xe5\xc3\xf2}R\x0c\xca\xd7\ +L\xa2f\xeb\xfc\x12\xcd-h\x8e\xa1m\x8d\xc1\x01\xcc\ +(,\x83g\xca\xe09|\xbc\xf7\x03\xf0L<]\x16\ +\xf7\x15\xe6{s\xb0\xd2\x1c\xb9j\xdc\xbdK\x07q\xf9\ +!\xae\x9f\xa5\x94O\x9e\xa8c\xc3}W\xba@\xc5\xf7\ +\xa5;Y!\x0e\xaf\xa0@\x0cE)\xa6\x9e\x9fW\x19\ +@\xb6\xb2\x1e\xdc\x7f\xee\xc8\x89\xe5+s\x9a\xba\xed\xd2\ +\xee|\xc2X.\x9e,B\xf8\x09\xf1\xbcAB\xa7<\ +\xa8\x9fp\xe0g\x5c\x9f\x89\xc7\x08:\x81x\ +t\x10&\x88\x93\xd9XV\xa8G\x96\x8f\xdbWJ\xc5\ +\xfb,\x00\x16\xe03RF\x1a\xc8Mm\xf4\x08[Z\ +\x1b\xe8\xd5\xa4\x0e\x83\xe1\xc3-K\xc9R\xb6\x0f\x05\xf8\ +\xb0|)?\x83\xef\xc8\xe0;2\xf8\xdet\x067\x83\ +P\x95\x81\x05+\xf6\xa7\xe3\x96\xd3\xdb5\x9b\x08(\x14\ +\xc3{4y\x83\xa7\xd0+\x1e$SdR\xd7&<\ +\x04\xf8\x5c&\xaf\x02c\x16^#\xa4\x18MF\x91C\ +\x88\xc9\x19\x22\x97'\x14\x86\x19\x8bl\xdd/\xd7\xf2\xfe\ +o\x03\x85\x5cE\x94v*\xfd\xe3\xbd#\x8bb\xf3\xfa\ +\xcc\x16!\x11OBV\x12\xc2#E\xf0bQ2\xa5\ +|M\x19\xa3\xf4\xa2\xd9{d[\xf7\x1c\xe9\xce\x87\x84\ +\xe5b\x999\xa4\xd1a\x88\xb4R\xc1`\xcf\x06\xf7,\ +\xc1C*\x0c+<\xa0L?^V\x80M\x85k\xa4\ +\xa0\xf4d\x94\xafi\xf4\xe4\x1aV.\ +k/D\xf1E\xf3\x0f\xdc$L\xf9\xf2#8\xd7}\ +\x97z\xe7C\xca\x22dE\xd9x2\xa5\xa7N\xe9<\ +o\x10\xd0k\xc63\x0b\x91N\x02x7\x97\xe6\x8ao\ +\xd4\x93m\xd4\x8c\x9d\xaf\xa3\x90\xee\xd6)L\xa0\x17\x9e\ +\xdf\x8f\xd1\xb9y\x05\x9e@\x00\x10@\x95e\x9c[\ +\xbb\x03\x80\xb2\x1d\x94\x0fA\x94\x08\x0c\x01\xcds\xa0\x17\ +\x19\xa4K9k\xc7\xddz\x86$\xa9\x8eq\x83\x03\xe8\ +o\x19\xa4\x93\x01t\x98\x05h\xc2\x84\x9c\xa8\xb2:X\ +\x7f\xc1\x9c@p\xd7\x8a\x97\xeeA\x00\x1f\x01\x82g\xd6\ +\xb6\xff\xcab\x0a\xa7oXt\x5c\xd3\x92\x9al\xc1\xda\ +x\xe8\x0c\x91>,S\x00\x90\xd2=!\x0e5+\xbe\ +\xad2\x10\x905,!\x93\xc1\xc8B\xe9!\x5ck\x18\ +\xeb\xce\xc1E\xe7\x10/\xf5z\xa1h)\xffB\x22<\ +\x98\x16\x8fr\xe4\x9ex\xe0l\x91@\xd8\xb1b\xa6\x08\ +Lj\xa3\xc8\x93\x08\x10y\xb4\xf8\x0610\x00\x00\xe4\ +\x0e3!wN\x18\x08Y\x83r~\x111'\x00\xc2\ +\x0f\x10}\xf2(\x88\xf8K&\x96\xa9\x19\xbb\x9c1\x1e\ +|\xf6\xb1[\xc4\xaaXye\x15\xab\x92\xd7(\xe0\x15\ +\x16\xf9\xc2\x8a\xe6\x9eY\xe1\xccc\x0c\xe0\x1e\x83u\x8b\ +AS\x06\xb0\x8b\xdb\xe5;]\x88\x02P\xcd\x00\xacE\ +\xe3\x22\xe3\xc0\xf2\xf1,R~\xd6 \x19\xc8\xf0)\xd7\ +\xb8\x8d\xe2\xef\xa2x\xb9uM\xb1\x22(>\x8f\xb8\xeb\ +\x04\x05\xe490\xdc\xc1\xd3b\x89N\xf9w\x00%\xe0\ +\x1c\x87_\x0c\xe8\xd9D\x88%\x1b.vg\xcb\x0b\x01\ +FI\x96V?\x19\x03)7\x95qJ\xaa\x9f\xb0D\ +\xc8_\x02\x5c \x01R\xa8\xf7JA\xf57e9~\ +B\xa2@\x14R(\x83hF\xf1\x02\xd1)\x84\xeb)\ +\x13\xc8\xe3\xb5p\xf6\xa6\x95\xcc\x9fZ\x8c\xdc\x8d\x06V\ +3i>\xc5}\xacR\x1e@\x0f/\xf4\xfb!6\x9e\ +\xe8\xe7s\xc5kb\x04+P\xb6\x10\x92\x95\xe1JE\ +\x98\xa2\xc3\x5cL2\x04\x8b>\x8f\x9f\x9e\x17\x80\x5c!\ +\x11\xae\x93\x03a\xcb\xe1\x01#\x90\x9e\x90\x18*n>\ +\x93\xf8\xe6Sz\xe6H\x19\xfc\xc2e\x10\xe4\xce\xca0\ +\x94f\xa2\xec,\xee/\x8b\xff\xd7\xf2sP\xaf\xdcw\ +\x16\xdf\xffI\x00\x98\x16v4\x1f\x9fE\x98\xc9\xe6~\ +\x22\x9a\xd7\x9f\xbc\xcf\x83>u$\xb7b\xed\xb5K\x7f\ +\xaa\xd6\xdf\xc2\x86\xdfZ\xd9\xca\x1b\xdc\xe2+\x97\x02\x17\ +\xce\xe2\x11&Q\xe6\xa8\x8ca\xdf}\x7fPs\x0f<\ +k\xa0\x13W\xdf\x85K\x86Gd\x91\x16z\x16\xcfg\ +\xc7Q.\xdf_\x80G)\x9c}\xe4\xbe\xa3\x00W/\ +eG\x89\xef\x11R\xd4\xc8\x04\x16>\xa6\x99FM`\ +\x1d\xe1uN\xf0>\xd7y=&\xe5\x16\xdf\xd0=\x03\ +\xdan<*\xbcGK\xdcY\x9a{!~\xe7\x11B\ +\xc4\x1d\xf24c\x8a'\x08IGx8\xf1\xb1d\x98\ +\xbf\x07\x82aK\xa8\x1d\xb1D\xb2\x84dx\x94f\x22\ +}\xf0\x00y\x0c\x01G\xcb\xe7!@\x1d\x22M\xce\x86\ +kd\x911\x051v-\xa9\x07\x09s1\x9a`\x91\ +\xc8\xb5z\x0cZ\x0b+\xc4=,@3TY\xfcN\ +\xf1:\x9b\xcf\xc8\xda\xb3dY\x9a\x16u\xb1\x93\xf8\xa5\ +T\x09\xf7\xa7\x85\x14OH\x9b\x86\xbc\x85\x94\x90\xe6\xd1\ +Q^\x88\xef\x09\xf3}.\x15\x84\xd8i\xe1\xc8M\x15\ +\xf3\xb0\xd9\x9a8\x12\x08\xf0\x04\x9a\x0d\x0b82\xe9\x89\ +G$5\xcf \x22\xc9}\xf0P\xfa\xce\x90<\x08\xe1\ +*\x0ca\xd3B\x8e\x13\x0d\x10\xa2\x1a\x85\x08\xf9\xb5\x96\ +r\x9dr\xb4\xc2\xb7\x00\x00\x96\x9f\x03\x02\xbc\xc0\xeaK\ +@\xf0\x1a\x00\xe0\x05\xf0\x08\xa5\xfc\xbeh\xfe\x11\x96\x8b\ +\xd2\xc65KG\x08\xe0\xbb\xb3\xf1`\xd9\xe7s\x02\xa1\ +\x01\x14>t\x06\xa0n\xf3\x19B\x06\xdf\x9bGH)\ +\x9c{\x845?\xc5\xb3<\xb7\xca\x15\x85\xd2\xc7.\xb6\ +\xe7\xcd\x9cZXs\x13\xc4\xf6\xe0\xa0\xe6.\xf0Z\x80\ +=\xd0\xb3\xee&\xcc\x22<\x7f\x98t\xd7{~1\x7f\ +<+\xa2e\xedL\xe5\xec\x9aY%~\x17A\xdeJ\ +\xf1&ex\x95\x92\x09\xc2\x85V'\x01\xa4O\xd9\x07\ +\xa19\x19\xf6\x9f\x88\xfbO$3Hl\x98\xb0d\xcd\ +|\x0a\x00\x18\xb0\x00\x90\x89\x17\xd0\xd2\xb9\xc2I\xa6x\ +\x04?\x07\x18?\x17N\xd1\xa9$&@\x8c\xd6<\xbb\ +\x1f\xcb\xb9\x10}0\x0bt\x88\x08i\xc2&\x8aE\xe4\ +2\xb8Q\xdc{\x14\x92\xa3\x19,O\xe9\x0c2V\x90\ +O,- \x85\xd4\x92j\xee(\xb1\x14\x00\x84\xb0J\ +)-\x0b4f#!,9\x8c\xcb\xcf\xe1\xc1s\x07\ +\xb7-wh\x9b\xef\xc2\x1b0\x18\x9e7\xe0\xb3\xb0\xdd\ +,\xa5c(=H|\xd7\x8a\xa1^\xf5\xb3H\xa5x\ +\x83f 5\xfd\xac\xfc9G,\x17\x89\xf0\xde\x13~\ +\x1e\xc1\x13\x11\xcf\xf3\xb8\x97\xfc)\x01\x80\x98\x8f\xa2J\ +\x16P\xce\x22\xb1w\x09Y~j\xc5\x8bOP\xfcc\ +\xac\x16\x85\x11\xb3\xa3.\x1d\x03DR>\x03\xa6\x95\xba\ +\xf0\xf9\xdc\x7ft\x0cw>\xf1\x00\x90\xc0\x1df\x1e\xb9\ +\x82\x98\xc2\xb9\x87V\xc6w\xd4\xc2\xaa[\xb6_#\xaf\ +\xacq\xe3\xa9U\xa9\x00dJ\xcb\xd7\x1aS\x19\x94\xb2\ +\x12\xc2\x08i\xa1K\xa3Q\x90\xe6J.\xc4M\x98u\ +\xe0\xf1:I\xa9{V\xf0<\x02\xc0\x0e$\xf2\xc4J\ +\x08\x1d\xe5\x10\xc7J\x00Z\xa1\x05\xb8I@\xaa\xb9\x88\ +ntD\x18N\x87\xf3\xb85\x08\x91hxT*\x1e\ +T\xd7\x12\x99\x8c`\xe9\xca>\xa2\xf0\x80\xc80\xe1\x0a\ +@\x8bC]L\xa8\x05\xf4\x1dH\x8c\x98\xabf\xb7T\ +y\x93\x89\x82\xb5\xcc\xaaU\xb6\x08.#*\x97\x85\x14\ +\xe0\xc2\x0a\xb5d\xc9\x97\x15\xe0\x8e\x0a\xc7\xb5^@^\ +\xc9\xe0\x951\xb8\xaa\x0f(e@\x0a\x88\x81Q<\x80\ +\x18\xb5f\xbdD\xf2\xbc\x89\x22ra,<\x8c\x8b\x13\ +\x00\xf2p{Z8\xca\x1f\xddw\x927B\xaa\xe4\xa6\ +\x9e\xc5\x0d\x142\xf08\xf2>\x22\x98\xf2\x00\xb0\xf0\x10\ +`\xd2\xdf\xa4|M#\xe7\x89\xe1\x8e!\xdc\x97\xd2(\ +1i'zh\xc7\xc0\x05\x02B\xc0\x04\xf1yR\xa1\ +\x00\xef\x84D\xf5:\xe5\xbd\x8a \xe5\xa0xY}H\ +\xee\x12pi\xba\xd6-\xd3*\x94\xe1E\x14\xdb\xf3\xa7\ +p\xed(\xbe\xd0)^\x96\x0f\xa1\xd3\xd2\xf9\xe2Ck\ +\xdaxf]{\xaf\xac{\xef\xa5\xb5m=\xb1\xba\x95\ +;V0\xa1\xd5K\xcdF*;\xd1<\x8a\xea\x1e\x94\ +F\xc3q p\xeeU5\x11Xl\xb0}\x8eg]\ +\xe0\xf9\x96\xe0Hk\x18\x1c^\x01\x83\x10\x18\x8b\x09#\ +\xe5\x90\xc7J-\xc6!Z\x85\xcd\x1f'\xf4\xc8\x13\xe0\ +a\x15\xf2\x02\x8c\x93\xe3m\x22\xee\xce\xf5\xe3i\x87\xf7\ +\xad\x90\xf4\xb2\x08b_D\xec\xd7\x1a\x8e<\xa3\x96\xaf\ +U\xd7\xe02\x16\xe7\xd9N,&\x17\x0b\x8e\x8e\x8b\x05\ +\xe3\xe2\xb0\x1c\xad\xb0ET\xdc\xa0\x14\x86/)\xc0\x95\ +\x15j\xad\x9a\xc1\x16\x08\x0aa\xca%\x90\xa5JHN\ +\x0d\x03P\x8b\xdb\xabY~b\x15\xaa\x82\x99\xe2{\x18\ +8\xb9O\xcd\xaaerc\x9a\x0c\xcal\xd7\x84\xc8\x12\ +\xc8]\xe5!\xaf:\xcb\xcf\x13\x00\xc6\x0e\xf8\xfeC^\ +\x11\xe2a.\x0a\x94\xb7\x11I\x8c`\xed\x0a\x1d\xd9\x9a\ +G\x90(\x8c\x88C`\xa1\xb9\x9aM\xe3>\xf2P\xde\ +\x05\x00\xc2C\x90&b\x9b\xf2i\xa5q\xb2\x00\x97\xd2\ +i\xda\x18P\xbb*\x22\xb9A\xd2-\x89J\xcaD\xb6\ +\xa4(\x0d\x9a\x98\xb3\x08\xa6\xf8\x84\xb7\xe2\x088\xc6\xf1\ +\x0c\x0e@x6\xc0\x9dG\x98\xc8\x83\xddk\x11%_\ +\x8bf\xb3\xa7(\xfc\x9e\xb5o>B\x1eZ\xcb:c\ +\xb2\xc0\xb8\x8d*m\xc3B\x9d\xf2\xc9\xa4\x1c\xc1\xc5=\ +\x93\xbe\xa5\xfdN\xd2\x01A\x16\x00\x08a\xfda\x01\xa0\ +\x97\xf1\xe9\x07\xf4x\x0e\x01R\x0bo\xaa\xbb(#{\ +\xa8 },c\xbc\x0b\x09\x09yd\x1a\xf2t\x0a{\ +Y\x8c\x95RG\xf7\x0cH\x10\x8e\x95\x8b\xd1\x16O\xdf\ +\xc2@o#0\x7f\xee[\x9eY\xa48{P\xe1\x0c\ +/=r\xc6w\xdc\xb6\x98\xe2\xf9g\xa0\xf9\x89#1\ +\xf9Z\x0b\xe0A\x9d\xc5(\x9d\x11\x08\x88\x8b\xf9(\xbf\ +@\x1e\x00\x17+)f\xe0+g\xcex\xd8{V\xbb\ +\xf4\x00 <\xb0r\x15\x18hiW\xf3\xe5\xa4|A\ +,6S\x88T\x5c\x07\x00\x99\x1d\x80@\xb5\x01=\xab\ +\xb8\xf1\x0d,^ \xd8\xe5\xbb\xf7\xf10\x87N\xf2G\ +\xb5\xac|hy\xc4\xf6(\xca\xca\xc1\x8b\x84\x01\x92\xac\ +_\xf3\x09aBS\x0e\xee\xd9\x03\xc0\x89\x93(\xde@\ +\x96\x1f\xd2D\x0a\x96\x93%\x12E\xa8\xf1D\xef5\xe5\ +\xec)\xd9O\x88\xc9\xe8\x22m\xec\xc4%\x03\xc8t\xee\ ++\x0d7\xac\x05\x1d\xa5\x92Z\xdc\xd14\xafV\x1c\xb5\ +l\x1b\x1a\x85\xe5;\x81\x1b \x11\x18uD\xa1\x82\xeb\ +\xcaC\xe6\x8d\x1dY\xc5\xecukX\xbae\x8d\xcb7\ +\xad~Q\xe3rh\xb9C\xcaL4/\xb1\xe0V\x0a\ +E\xda4\x81#\x00x\x82\x07p\xb3w3\x00`\xd1\ +\xc2\xe7\x0bf\x11 \xc9\xc7{\xe52\xce9\x18\ +\x80\xc0\x1dR\xba(\x10\x88\xb4\xa2\xfcl\x80S\x80\xe1\ +\x96\x93eT\xa2\x97*\xc2^\x05\xa1\xae\x80p\x18\x19\ +\xbd\x83\xdc\x05\xd8\xe8y\xf2!\xfa~l1e\x8b\xcf\ +A\x16\x04f\xe9\x19\xaf\xc4I\xad\x12\xc1de\xcd\x02\ +\x80bH\x94\x0bE\xa5\x14Y\x1fR\x88{*\x87\xc9\ +Vc\x015\x0bw\xac\x1a)S\x09\x94\x06\x08Tf\ +\x8b\x95\xe3\x9e4\xf8YZ~e\xd03yH\x89V\ +\x09E|<\x10\x10\x0a\x00@\x11.\xb3x\x92\x98\xa7\ +%hX\xb3\xbcM\x81f\xcf\xb0\xe0\x5c\xacY\xd7u\ +\xd7\xe6\x1er\x01\xa0\xabA@\x14\x0arP~\x18\xcb\ +\x97\xf2\xc5\xa63\xf9~\x91\xaa\x80\xe6\xf7Q\xb2[g\ +g@\x03\x9aM\xe35\x83\x90\xa4T\xc9\xd5\x0d(n\ +6\xcd\x91?\x93\x81(\xcf\xef\x12q\xd2b\x13 \xe6\ +\xb9%\x99<{&\xd7U\xcdA\x90{q\xec\x19\x0f\ +\xa2\x9c]YL\xfe\xe0\xa6\x95\x8en[\xf9\xd8\xb6\x95\ +\x8emZ\xe1\x90\xc2\x15it+\xdf\xaf\xc5!Y>\ +9z\x0a\x0a\x97\xe2\xf5\xdeM\xaa\x9dO\xa8es\x7f\ +\xdeB\x19\x9e\x91\xf0\x18\xc1#iZZ\xeb0\x01\xa5\ +s\xf2J(X\x99\x89\xe39\x0e\xf0\xc8'\xf2\x0b\xf8\ +\x19\x1b\x85.)_\x9f)\xc4\xf5W`\x9c\xd5x\x8d\ +\x1a\xf8N\xd5\xd2S\xbc\xd5#G\x8as5\xff1\x85\ +\xf2I}\x0bg\x9f\x08\x00OP\xfe\x13\xc8\x8b\x08\x0c\ +\xae\xdc\xc5\x1a\xf2T\x01\x00\xf4\xe70\x18\x1e\xa3\xf7\xe6\ +\xf0e\x91Q\x90VD\xdc.#\x95)\x9f\xbaf\xe5\ +\xd3\xd7Q\x1c\xf1\x98\x8bk.=\x84\xa5\xaa\x94*\x1b\ +T\xba\xd94\xac1\x88\xfb\xff\x04\x82.@ >@\ +&P\x08\x00\xca\xa6N\x08)7\xacj\xee\x96U\xcd\ +\xde\xe2\xe7\x1bVL\xe8q@\x10\x07A\x0a\xb1\xb6\xa2\ +\xf1\xe3OR\xc0\xcfQb\x9d\x9bBu\xca\x87ek\ +\x1d\x01\xc5k\x81\xc7-\xf2\xa0h\xb7\x82\xc9 \xaa\xf4\ +\xcb\xa5v\x9al\x01\x0c\x0e\x18.\xdde\xa05i\xd4\ +\xad\xd4\xef\xc8-\xf7f\x11c\x83R>\x03\xad\xa5i\ +?\x80\xf6\xf3<~\xc7\xa0a\xcf(\xc6\x07\x90\xfc\x9a\ +\xeb\xe7:!H\x9cD\xf5\x90*\x7f\xf35K\xf1S\ +\x96\xa2i[Y>JOE\xe9\xa9\x9aQm\x12\x1f\ +\x80\x10jB\x8dLGs!\x9a\x13\xc9\x19\x80\x14\x0f\ +\x89\xe0\xe2\x81t\x8f\x5cC\x00\xd0\xab\xcb\xc8dL\x1a\ +K\xc6\xfeB\xb2?\x09\xe3\x0c(\xc5a\xc2\x84\xbe<\ +\xbc\x94b\x7f\xc9\xec\x1d\xc7!*0j\xf1\x87\xe2\x99\ +{V$\x91\x81;\xb9O\x08 F\x94\xe2\xbe+H\ +_*\x17!6\xf3\xf7H=nc\x95\xb7\x18`/\ +\x9dSi\x94\xe6\xb75\xeb\x17\x14#gPs\xb8\xf1\ +<\x10\x9b?\xb8Ez\xa22\xb0\x1d\xe2\x97j\x03\xfe\ +w\xc9\x06\xd1\xaa\x11\x90efv\xc9\x22=\xe6\x1b\xec\ +\x5ct1\xafhd\xc7*\xa7\x8e\xacf\xf6\x9a\xd5\xcd\ +\xdf\xc0\xab\x5cw\xc0*\x84\x13\xe4\x0f\x13\x07\x87w\xf1\ +\x06{\x00\xe2\x00`\x1cy2y\x08\x08\xf6\xb8&\xe1\ +\x01N\xa1\xfa\x03-E;\xe5\xb7{\xcaw\xa5_(\ +X\xae4\x0b\xab\x0e)\xae\xf3<.S\x00\xa89\x0c\ +\x94\xe6\xfb\x95\xb2j\xd5/\x87\x98\x18\x1d\xbb\x83{\xbc\ +M\x0a\xa7\x22\x93\xeb\x16\xe4\xf3\x81\x81C\x94\xaf\x15I\ +\x84\xd0\xe6RfB\x85&\xcb4\xff\x9e\xaeU\xb8\x06\ +b\xfa\xb9\xa4jF\x137\xef\xc9\xb9\xf2\xa5x\xd26\ +7\xb1\x06s\xcf \x97w\xe5c\xe2HR.\x8a\xcd\ +V\xcd\x858\x8c\x96\xc85\x0d\xcd\xd8\xb9\xf0\xa5\xbf\xe3\ +\x11\xe4\x15\x5cH\xd5\xff\x08|\xe7\xe2y8\x9e_\x9e\ +\xb6W\x04r\xdb\x85Dq\xa3\xfc\x09\x0c\x09\xbeR\x06\ +\x17(W\xb5\xd7\xec\x19\x9c\xe2\x94\xf4\xf2\x96\xe5O\xaa\ +\x88\xf5\x86\xc5\xe4\x8b\xe8\xe1\xceKfn\xa2x\x88\x03\ +\xaf\xaa\x08\x12\xf1\x8b2HZ\xd0P:'\xc5k\xde\ +_\x8b?\x01\x88\x8d\x8a;\xb3\x18\xecl\x06]u\x7f\ +!,<\xa4<\x17`(\xa5\x0b\xf1P*\x14\xb9\x00\ +\x80\xf3\x00\xce5k\x92g\x8e\xef\x82\xfc\x00\x88\xc2\xc1\ +\xab\xb8\xcf\x1d\xab\x9a\xdc\xb7\xea\xa9\x03\xab\x98\xd8\xb3\xa2\ +\xe1-\xcb\xed\xc7-\xc2\x8as\xfa\xd7\xc8\x1a6\xe0\x1d\ +\xb8\xd9\xa9=\xab\x98\xde\xe3u\xd7J\xc6\xf9\xcc `\ +\xecUX\x81h\x9e\xd7 \xf8\xb5\xd6\xaf\xd54\x06&\ +\x13o\xa5\x8a^Y\xb5H]\x14\xc5j\xb2Gq\xb4\ +P\x0b$\x9a#\x9fy\x80\x90\x12\xce>\xb3b\xcd\x0a\ +\xce>\x86\xe4\xdd'K\x80\xd0\x92I\x84\xc8jB\xe2\ +\x03C0o\xf1\x1b\xbeO\xdf\xebf\x09\xa5P7M\ +.\xb7~\xe1\xe2/\xc4\xb3z\xa7x\x80\xa2\x99UM\ +\xe2\xb8\x096)R\x96-\x05\xa3\xe8 \xca\xcfR\x18\ +\x13\x91\x05\x00\x9a\x07p\xeb\x02x\xaaLy)\xc0\xa6\ +5\x13w=\xe7A\xe4I\xf8nD\xd3\xe8.\xbdT\ +Z\x09\xef\xd0\x8a\xa2V\x16#x\x93\xe8\x88H\xf6\xb1\ +\x95\xe2\xa1+\xf0\xb0\xe52\xae\x19\xbc5^[3\x90\ +\xca\xf2b\x22Xn\x8e\x8a9q\xc5\x85\x13X\x16\xf1\ +\xb8\x08\x0b\x14)SUPXV\xcc\x8d\x04eM\xb0\ +\xda\x80f\xea\x9a\xbd2\xef@\xf3\xa4e\xb6L\xe1\xf6\ +fI\xd7\x16\xf0\x0c\xaa\x00Z\xe5\xf3\x02\x02y;\xca\ +\xbf\xa8\x16\x0a\x09\x9d\xddZ\x1d\xd4J\xa1\x5c'\xa9\x0f\ +\x9f/\x80\xf5\x96\xa1\xf0\x0a\xe2h%J.\x1b\xde\xb0\ +\xfc>\xe2b7\xe4\xa8\x1bv\xdc\xb3Hl\x5c\xc1S\ +\x00\x94I>7\xb5\xe5^K\xc6\xae\xc2G\xb4\xd4:\ +\x8f\x85\xcc\x03\x809\x0f\x5c\xca\xab5\xa9\xa4\x01&l\ +\xb9B\xd2\xa1\x1b\x907\x88-\xa9k\x81X1n\xb1\ +d\x11\xb7Hl,_~i\x15+\xef\x90\xf7ns\ +H\xf9\xd2+x\x10\xa4xF\xeb#\xca\x904\x01\x04\ +\xb9\x85uk\xa2IdK\xdf-\xf7\xad\x18\x9e\xeeV\ +I=\x00\xfcC\xbc8\x9f\x0e\xbf\xf0a,n\xb9\x99\ +\xf1\xd3\xac\xa6j d\xa9Y2\x0c\xdc~\x96S>\ +\x0aGa\x9a;\xd0\xfb \x0a\xd4\x8a\xa0@\xac\x19\xd2\ +\xf4s\x22\xa9p\x92\x5c\xaf\xbd\x14\xe3\xc8\x98\x93\x94\xfa\ +1\x806\x0e\x18 \x95*<\x01\xfcA\xc69\x1b2\ +\xac\x22S\xd5g\x16\xe1=K\xa7\x0e\x9d\x94\xe0=\x0b\ +\xc75\x8f\xa2*\xafm\x8b\x09\xc2\xca\xe5B\xe5JU\ +\xcf\xa78\xa4\x14-\x97\xf8\xaa\xca\x9d\xdf\x03@)\x9d\ +_h#\x7f\xf55N c\xc88`\x98\xc43L\ +;\xab\x0e\x8a\xed\xa3\x00\x91?y\x82\xb0\x5c\x92\x9bP\ +\x22D\xf0]\x02F6\xee,\x9b\xef\x8b0 \x05<\ +l)\x00\xac\x18\xdd\xb5\xca\xd1\x1d\x00\xb0i\x05}+\ +\x96#\xe5w\xc9K\xccA\x92\x16\x085\xcbV<\xba\ +\x86\xe2\x91\xd1U\x88\xe82\x1e\x02\x0f\xd45\xcb\xf5f\ +\x19`\x00\x80G\xf2\x0aR\x96\x08\x05\xb24\xa5F\x9a\ +\x0d;B\x81\xd7\x01\x806p\xdcE\xf9\x0f\xacl\xe5\ +\xb1U\xae\xbf\xb0\xea\x0d\xed\x81\xf8\x02\xf9\xca\xea7\xbe\ +\xb4\xda5\xc0\x001.Q\xce\xaf\x8c\x08/\x10q\xca\ +W\xfeL\xfa(\xe5\x93\xd9h\xdaZK\xe3N\xf9.\ +\xbf\xbf\x08\x03S\x80b\x9a\x1c_S\xda\x0b\xa4\xc0\xe2\ +<\xde\x18g\xf7\xf1\xdcx\xb6\xec\x01\xd2Z\xf2\xfd,\ +8P\x10\xc9$\x94\x06\x00D\x00\xa5y\xfb\x1c\xb4\x9a\ +\xa90\xa1:\x8cYK\xe1\xfb\x93\xeb\xc7\xdd\xd4o\xa2\ +\xa6~\xab\x07\x91\x01KD\x92j\x06-\xa5n\x84{\ +\x98\xe0\x9e\xce\x01\x80'\x16\x00B\x22\x95\xe84\x8f0\ +[0F(e|\xf3y\x1f\xe5w\x9a\x81\xcd\xc4+\ +\xc7x\xb1\x12\xa5\x11\xa3\xc3\x179:\xcaW\xa5\xaf\xdb\ +\xf4!R'\x02\xe5\xd2:\x08\x93sG\xb84-\xd8\ +\xe8\xa2\xa0/\xa3q\x12\xe2\x83W\xd0\x1c\xbe*\x85p\ +q\xaasS\xcd\xa0\x9b\xb8\xe1\xbb\x1cs\x87Q\xe7\x12\ +S\xa3\x90\xaa\x1c\x14\x93\x8b\x85\x16B\xb2J`\xb6e\ +\x90\xba\xf21\x90\xcaM\x16\xe2\xdasU\x05\x8bug\ +w\xce8\x09w\xcf\xc1\x94\xe7\xf9\xdf\x05\xcbE\xf4>\ +\xa4\xaaY,_\x1e (\xcb\x97\xfbg\xd0\xddB\x96\ +\x8b\xb5+\x96\x01\xc9\xf3w\xc9\xd5\x02f\xae\x13U\xc8\ +S,\x5c\x82\x1c\xad=\xb5\x9a\x8d\xd7V\xbf\xf5\xb95\ +l}a\x8d\x9b\x1f\xacn\xed\x8dU.\xc0\x9a\xa7\xef\ +\x91N\x89\x07\x1d\xbb\xa9g\xa5\x94\xae\x80E3z\xca\ +\xebQt*\xd6\x98\x825\xaaH#\x15\x05\xa9,+\ +\x03e\xf9P\x9a\xd62\x82\xb8d\xcd}d\xc3u\xb2\ +\x01uv\xff2\x8c~\x09\x01\x14x\xb5 \x9e.\xc0\ +\xdf\xb4\x0e\xa0B\x18\xa5\xa6i\x0d\x0f\x81\xe4\x15\x11\x0ar\x07\x95\x13\ +k\x105\x98\x80\x0b\xd1k\xa0\x1dO\xd3>\xc5=\xf3\ +\xbec\x06\xd1\xfd{ V\xf5L\x06\x0f\xa5\xb2/\xad\ +\x8cI\x5c\x09\x18\xca\xf03\xc0A\xb9E\x88e.\xcf\ +\xa7\xda\xf82@P\xb5\xfa\xd4\xed\xa8\xa9\xbb\xfa\x0a\xe5\ +\xe3\x114]\xccXs\x02\x11\ +\x94\xab\xc9\x197g\xaf\xf9zrhW\x17@\xa6 \ +\x90\xa8\xd2U\xa5T\xaa\xa7\xcbG\xc1ES\xf7\x5c\x1e\ +Z6G\xca9\xff\x94\xb4\x04\xd1^<\xa4z\xe1\x99\ +\xd5,=?\xcfWq\xcd\xa4\x82\x85\x10\xc2(\xf9\xb4\ +\xea\xe1\xfd\xed\x22:\xb8V\x15:\xe2qT\xe3\xafJ\ +\xd8\x14m\xfel\xc6\xeaTIK\xecK\x03\xc8\xca\xed\ +U\x0a\x9eD\x5cL\xa8\x1bf \x87p\x9d\xc3\x00a\ +\x0cw\x0ap \x8b!\x5co\x14\x90\x17LA|a\ +\xc6\xe5d>\x95\x5cW\x93&\xe5\xe2\x07\x137\x9d\xf7\ +\x0bCb\xb5\x1a\xa9ei\xa5t\x8a\xbbRzb\xf5\ +\x08\x83\x8fEV\xfeCT\x98\x91R\x87\xf5\x036U\ +D\x85\x18\xec\x08\xde/B\x8c\x95W\xcdRyv'\ +\xe0h\x1b\xc63\x0d\x00\xca\x01\xee\x1d\xd0\xf0\x0c\xc9<\ +K\x12\xa14\xb1~\xd4Sz\xcd\x90\xc5U\x0dX,\ +J\x8fE\xe9W\xca{\xecJY\xb7\xc5:\x01\x00\xe5\ +\xb2|mv\x19u\xe9f6\xc0V\xf5\xb6\xdb]\xe4\ +vx\x9d\x91\xe7\x9f\x02\xf2\x9b\x84.M\xf3k)y\ +\x8b\x90\xa2\x0a&-k\xab~\x91\xb1\xd2\xc2\x11\x9e;\ +F\xec9\x0c\x11+P>>w\x13e\xdc\xb5\x86\xb5\ +G\xd6\xba\xf1\xd4:6\x9f[\xfb\xc6sk\xbd\xfa\xcc\ +\x1aV\x89\x99\x90\xa7b\xb1h\x01A\xf3\xe50bW\ +\xf0!\xe9\xe5\xbd\xea\x00T\x11\xe3V\x08!]\xa3\x9a\ +\x17\xe7\x7ff\x1e[\xd9\xc2s\x06\xfa\x95U\xad\xbc\xb6\ +\xea\xd5\xd7V\xc3k\x0d\xaf\xb5\xb8\xdc\xba\xabo\xacv\ +\x9d\xbf\xad>\xb1\xd2\x05\xd5\xcaifO\xeb\xfa\xaa\xef\ +W\xb95\x83\x7f\xb1\xea\xc5\x83'\x12\xf3\x12\xa5\xe0\xfa\ +\x11g1Z\x05K\xc6:\x93\x88\xbdZ\x16\x8d'.\ +\xc6Uuc9\xda\x07\xd8\x85\xc5\xf6\xf2\xc0\xc3\xcec\ +d\xe3vs4\x039y\x02\xfb'\xeb\x01\x04\x92\x12\ +\xd2\xa5\x22\xbc^\x9e&W\xa4|\x14\xa9\x02K\xb9\xf9\ +$\x17{\xa5|\x09\xf7P\xcd\xef\x9c\xe0\xa2k\x95\xee\ +\x09\xa4\xcaB\x94\x95\x90\xcb\xe315\x81\xa6I\xaa\x10\ +^G\x045\xa3e\x84\xb0\xd1k\xc95\x9d\xfc\xbf6\ +\xa7v\xe3\xd6q\xe5N\xfa\x9c\xc4U\xc9\xbdK\xfa-\ +\xb6\x1c\x00H\xca$x\x81\xf2\x01,\x7f\x10\xe5\x8f\xa0\ +|\xc2\x0c\x8aT\xb5\x92\xf6fH\xf1.\xa3\x99#l\ +\x01b\xadu\xe4\xe0\x054y\xa4\x14\xd3\x15\xf7\x92\x81\ +x\x05>\xe2-\xe2,\x18\x12\xa1#F7\x98\x87E\ +\x94\xe2\x12kV\x1fZ\xf3\xd6s\xeb>xkc7\ +\xbe\xb0\xf9;\xdf\xda\xe2\xddom\xf6\xeck\x1b9y\ +o\xad\x00BS\xbe\x8a\x8d\xb9\x90\xaa(9tt\x80\ +\x87\x1d\xe0u\x90\x9f\xb1\xf8\x5c\xa7\xf8\xbbd\x15\x0f\xc8\ +C\x1f\x93s>\xb5\xd2\xf9\x97V\xb9\xfc\xc6\xaa\xd7\xdf\ +Y\xcd\xd5wV\xbb\xf1\x16\xb7\xfb\x86\xf7\x80\x00\xa9\xc6\ +\x05W\xad?\xb3\xf2\x15\xad\xdc\x9d\xc2\xbc\x0f\x88\x91\xeb\ +\x96\x8ekK\x22\xd6&\xd4N\xa0\xd4\x09^'\xb1\xec\ +I\x94?n\x09(Z\x92\xc8\xdf\x93\xc8\xb3\x93H\xb7\ +\x12a\xde\x09Xb\x1c\xae3\xb6\x12\x8b)\xef`\xd0\ +:\x18\xb4n\x06m\x80A\x98\xf0\xbc\xc0\xd0\xa6\xbbF\ +>\xe9P\x01)o\xc1\x946\xbc@\x125\xcb\xa6x\ +\x0f9\x15\x97\x10\xc1\xd3\xba\xbbW}#\x12&\x85\xe3\ +\xaa\xeb\xe7a\xe4*\x07W\x15\x92\xea\x10E\xdc\xe0I\ +\x18@xD\xeb(\x8c\x81\x16m\x00\x81*\x81\x15\x9e\ +\xd2\xb1ro\xb3j\x97%Ttr_]\x08 \x95\ +K\xaf\xecq1=\x1e\xe5\xc7c\xdd\xf1UC\x08\xde\ +\x00e'T\xe1\xcd\x00[b\x8d\xbc\x90\xd6\x144k\ +\xa9l\x02\x0f\xc3\xf8\xe7\xe3\x9d\xdd\xe2\xd4\xfc\x03Wy\ +\xa4\xfa\xbf\xc8\x98\xf6\x1e\xee\xb9I/\xcd\x13\xa8\xeaJ\ +\xd9\x88\x0f\xcbW\x88\x92\xe7\xf0\xb5@\xe4\x91\x98\x5c\xcd\ +\xac\xcd\x9e\x92\x06=\x84\x0c\xbd\xb4\xd6\x83\xf76x\xf3\ +k[z\xfc\x93\x1d\xbe\xfd\x93]{\xff';x\xf5\ +\x07[\xbe\xff\xd1z\xf7_\xe3\xbe\xb9\xc8\x98,\x1c\x91\ +\xc2\x87\x15\x1an\xe3A\xee\x92F\xde\xc7}\x8b=?\ +E\xf1/q\xb1op\xb1\xef\xdd~\xfbZ1l\x88\ +V\xed\xd6{\xab\xd9|mUW\x9f[\x05\xf1\xb7\x5c\ +\xe5Q\xb8\xe0\xe2E\x95N\x9d\x91\x7f\x93o\x93\x85\x88\ +\x11gp\xf3\xa9 7\xb9y\x19R\xb4\xf2;Y\xe4\ +w\xf3\x96DN\x9c\xd4\x04H\xf8\xd9\x09?'\x82\xf0\ +\x04<\x85\xe2g\x02\x16\x95\xc8\xc0&U\xf7C\xd4\x88\ +\x97\xcaVD\x18\xf1\x02\xa1\xa1-\x94\xb5\x87\x9b\xd4\x0a\ +\xa2\xa6W\xbd\xa5`\x15\x9eh\x11K\x03&k\xd1\x9a\ +{\x12\x16\x97T\xa7\xd02\x87\xcb\xd6\x12\xec\x1a\xbcb\ +\x93\xf8\xad\x125\xdd+\xe9\xe1 \xf7\xad\xa5\xf0\x09Y\ +\xa0\x96\x98\xef\xb9ei-\xd8h\x7f\x85\x06?M\xe9\ +\x1b\xcaM\xa8\xe8\xff$\xf1z\xad\x84\xd1W\xc9\xba\x87\ +\xbc\x10s\x0e\xb6\xc4:\x11A-\xf7jQI\xcb\xca\ +\xaaz\xde5\xed-\xd4\x0e\xa5\xa8\x96\xbcU\x84\xa2z\ +\x86\xb9\x07\x16\x9d\xbama,_\xd3\xd5\x9a\xfa\xf6\xb2\ +\x15Ur\xcd\xbb\xeb\xfb\x91\x00\x5c\xe6b]F\xc4?\ +&\x1f7X\xa28\xb8\xfe\xd4\xeav\xb4\xa3\xf4\x0b\x1b\ +8\xfdh+\xcf\xffh\xd7\xbf\xfa\xbb\x9d}\xf3\xcfv\ +\xfd\xc3_m\xe3\xc9\xcf6pD\xae\xbc\xf0\xc0\xb4\x9f\ +>\x8a\xd2\xf3\xc6\xb4A\x94\x9cz\x1a\x17?\xfb\xcc\xca\ +\xe6_\xe0\xea_\xa2\xf4\xb7\xb8\xf3/\xadq\xeb\xa3\xb5\ +\xed\xffh\x1dG?Y\xc7\xf1\x0f\xd6r\xf05\x00\x00\ +\x14\xb0o\xb1\xf0B\x5c\xaf\xae\xafmJ\xd1\x89k \ +\xf7\x18\xe5\x1fX&1\xcd+\xf5f\x80U\xab\xd0\xa3\ +\xbd\x7fG\xa4tG\x0c\xf8!\x8cy\xcf\xd2:\xb6-\ +\xb5}\xc3R\xb0\x86\x148Hr\xeb*\x02Xp\x8d\ +\x02B\xb2\xcb\x9b5\x19\xe3\xe5\xe5J\xd9D\xe4\xb4\x83\ +\xd8\xafy\x02\xd22\xf5\x17P\x9f\x01\x15]\xba\x1a<\ +2\x1e\xada\xa8\x08T\x936\x9a\xb2MQ\xe1E\xc3\ +\x1c\x1eF`[\xb2\x14\x14\x91\xda\xae\xba\xc4=\xee\xed\ +\x00\xe5k\xad@\x1bSnY\x08\x82\x1bA\xf9\xd1\xe9\ +\x87\x96+\x99\xbc\x07!\xc3\x13\xa8@\x86\x10\x99\xa5\x82\ +Rm\x85\x97R\xa5\xdcZ\xac\xba\x86\x10\x82w\x93$\ +\xab_\x02\x22\xc0%\xd6\xcf\x12\xd6\xb8>\x1e&M%\ +\xed*o\xd7~B\xbc\xad\xae\x15\x1e\xbfc9\xba\xd6\ +\xccC\xe4\x81E&\xef\x00\xc0\x1b\xfc\x9d\xb1\x82\x9f]\ +\xd4uj\xf2\xc8\xc7\xf7\xf8y\x0d06JK\x95\xa2\ +\xbb4Q\xf3\x00\x05\xf3*\x14|\x88R\x9eY5\xca\ +i\xd8\xfb\xdczn|\xb4\x85\xa7\xbf\xd9\xd1W\xffb\ +7\xbf\xfd7;\xf9\xe2\x9fm\xfd\xd9\x1fm\xe0\xe4+\ +\xe2\xf8S\xcb\xd3\x83\xa1\xf8\xfc\xa9GV<\xfb\xc4)\ +\xbdr\xe9\xb5U\xae\x90B\xad\xa0\xfc\xb5\x0f\xd6\xb2\xf7\ +\x9d\x0d\xde\xfa\xa3M?\xf8\xab\xcd>\xfa\x9bM=\xf8\ +\x93\xf5\xdd\xfc\x88\x97y\xe5\xea\xe2\xb4)5\x07W\xa5\ +\xd2\xa7l\xd2M\x95*]\x886{\xb8-\xd4\x9a\x85\ +\x1b\xd3\xd4\xec=,\xeb\xa1E\xc6\x1fYh\xf4\x01\x7f\ +\xbb\xcb\xa0\xdf\x02$'\x96\xd1\xb3oi]\x80\xa1\x03\ +0\x90\xf2\xa5\xe2\x8e\xd3T\xba\xad\x12n\x95\xaeu)\ +\x85\xf5D\x9b<55\xec\xe6\xf2\xc9VTN\xae\xbd\ +\x04\xday\x14\xec\xe7\xda\x02\x01\x04W\x9f\xf1\xa9\xe0\x94\ +TR\xde\xc6y\x19\x94\x9f\xd4\xb2b\xc9mW\xb9\xd6\ +\xb6\xa5w\xed\x03\x80C\xf3\xf7\x03LxO&\x16\x19\ +$\xbb\xc9\xd6T2^ Gc\x84\x17\xc8W:\xa9\ +Wy\x06\xc2\xa3v\x1be\xaa\xcbH\x1b\xdf\xd1r\x15\ +`\x12B\x1a\x89\xcf\x0dX9\xc0H\x05l\xc9\x02\x9d\ +S\xfe\x8a\x03y\xba\xf65\x08l\xfd\xc7\x969\x04\xd8\ +\xb4\xb4\x0b\x00B\x5c#\xbe\ +G%}\xae\x88W\x15^J\x89\x19\xe7\x08\xc41\xa6\ +@\xe5\xc90\xe0b\xad7\xe3\x92+\xaf\xbe\xb0\xa6\xfd\ +\xf76t\xfb;[z\xf1'\xbb\xfa\xf6\xaf\xb6\xf6\xea\ +\x9fl\xe6\xc1/\xd6u\x0c\x00V^@4p9\xb3\ +\x8f\xad\x106\xaf\x961\xe5\xcb\xaf\xac\x12B\xa7r+\ +I\xf5\xfa[\xac\xfe#\xff\xf3'\xdbx\xfd\xcf\xb6\xf5\ +\xe6\x9fm\xed\xc5\x9fm\xf4\xec\x1b\xb7\xd7=\x9ft\xcf\ +\xd5\xdeA\xb8T}sQ\x01\x9b\x0dk\xd5\x0e\xda\x88\ +\xd6\xbb\x19\xb8<\xcd\xc8\xa9xs\xf9\x9d\x95\xac|\xb0\ +\xe2\xe5/\xf8\xf9\xbd\xe5\xcd\xbe\x06\xfd\xcf\xb0\xb8\xfb\x0c\ +\xfc-\xf310\xe9x\x0a\x01!\x0d\x85\xab\x9d\x8bW\ +\xb4\xa9%S\xae\xc5g\xa2\xaa\xe1\x93\xe5\xc8U\xf7\xe1\ +e\xb0t\x95D\x09\x00\xf24\xaa\x15pB\xca$\x0b\ +\xca\x808i7Q\x0a\x83\x98\xec\x04\xe5\xb7\xae\x01\xb2\ +MKE!\xe9j\x17\x03\x00|\xdaL*\x10`\x99\ +\x99\xda1Lh\x94\x82\xb4\x9e\x90\x8bK.$.\xab\ +\x12\xa9\x8cL\xa7t\xe1\x85\x15\xc2\x89r\x00q\xf6\xc0\ +\x19q\xfc:`\xc0\x83tr?\xed\xbb\xa4\xb9\x00\x97\ +k\xa4\xa3\xacT\x89v4u\x02\x94\xee}\x80~\x01\ +6\x81@\xd7\xb9\xc5un;\x09\x02\xac\xc0\xd0\x0dw\ +/\x19\xdd\x02\x80X?\xdf%n\x02\x80\x02*\x91g\ +\x5c\xb4/Ben\xe1\xe1k\xa6\xd66Q\xf8CL\ +>\xcc>\x9f\x9bT\xc5\xaa\xa4@3ex\x84\xba\xed\ +\x97\xd6q\xed\x83\xf5\x9e~k}\x84\x84\xee\xeb\xdfX\ +\xd3\xde\x07\xd7\x07\xa7xY=p\x9e\xa3\x14\xdc\xbd\x94\ +N\xfe\x5c\xb1*\x12\xc7\x83\xaa\xf6\x1c \xb5\x01\xa2\xe9\ +{?\xd8:\xa1\xe4\xea\xf3?\xd8\xd2\xa3\xefl\xe0\x18\ +\xa0,\x9e\x12o\xb5|\x89U*?\xd5\xdc\x82\x16\x9c\ +\xb0\xa2\x10\xc4R\x03\x17A\xf9\xb9(\xbf\x88L\xa1l\ +\xf3K\xab\xda\xf9\xcej\xf7\x7fB~\xb6\xea\x9d\x1f\xad\ +l\xe3#\x7f\xfb\x02\x80\xbc\xc6\x02\x1ey\x030p\xcd\ +|\xb8HI\xa0\x1f7\x89\xe2C\xfc>\x07\xef\x91\x07\ +/Qm\xa0\xaa\x7f\x0b\xb4$\x8a\xa5\xaa~_\xeda\ +\x9c\xbb\x94\x90\xba\xb9\xf2s\xbd\xc73dh\xc1\x87\xd4\ +\xd6\xdb[\xe8y\x95t\x066\x1d/\x92\x0e\xc0|\xbd\ +\x84#Dn\xd9/\x10\x10\x0ad\xa1\xb2\xc2L2\xa4\ +,-\xd9\xe2\xe1\x04v\xcd\x9e\xc4\x89\ +,_\xca\x17\xf0\x18h\x1f.8\x83g\xf2i\xfa\x1c\ +\x8e\x11!\xe5,\x22\xc3\xaa#\x9dn?\xfc\x0a.\xf4\ +\x9d\xb5\x1d\xaa\xf9\xd6\xb7VM\xa8,\x9b\x7f\x05\x7fz\ +ne\xf0\xa8\xd2\xf1\xbbV\x84\x82\xf2\xb9/eV\xda\ +\x98\x9a\xd5\x07\xa9C2\x7f\xdf\x9a\x86\xebi?\x82@\ +\x90\x09\xd03y\x95\x07\xf2\x9aY\x09\xd4\xaa\xf7\x83\x08\ +\xba\xf2uO\xf1Ay\x0dH{\xf6\x18a\x08\xf2\x18\ +\x11I\x9d\x06\x00\xa1\x11\x5c\x22\xaeX\xabR\x81\x8by\ +h\x08\x92\x0f\x92\x10\x18\x86\x1cM\x9cX\x04\xa2\x96\x07\ +W(\x80,\x16-#\x22pK\xc46\xe5\xec\xb3d\ +\x02\x93\x00fTK\x99\xaabY\xc7\xba6\xadd\xea\ +\xc0\x9aWnY\xcf\xd6]\xeb\xdd\xbcm\x1dk7\xac\ +zz\xcf\xad\xf0\xb9\x05\x0e\x11\x14M+\x13k\xb5\xba\ +\xe6v\xe5j\xdf<1?2\x05\xb1\x81[\xe4/\xa2\ +4\xc2I\xe5\xce\x17Vw\xfc\xd1\x9an\xfch\xcd7\ +~\xb6\x86\x93\x9f\x00\xc1\xf7V\xbe\xf1\x0d\xf7\xf3\x01\xaf\ +\xf5\x1aK{\x0e/y\x049\x85\x18\x8d\xc0\x19F\xee\ +\x12\xe3\xee\x01\xee\x87\x96\x07\x00\x0a\xe1)%\xa4\xa2\xa5\ +H1\xdf\x9b\x0fyR\x93\x09\xb9\xfd\x0c\x14\x9d\x069\ +Lm#\xcdj\x9d\xc6\xf5k\x7f\xff<\x1cb\xc5-\ +\xca\xb8Z\x02\x11D\x94\x1f\xc4\x05\x07QPP1_\ +B\xfa+\xeb\xd2\x0e!Y\x5c\x86\xbc\x856\xa8\xc0\xb8\ +57\xaf\x86\x0fy#\xdb\xd6\xb4v\xcf\x86\xae\x7f\xb0\ +\x89\xdb\xdf\xdb\xe4\xdd_l\xe4\xf4gk\xdf\xfb\xda\xcd\ +\x89h\xed\xa1B\x93d(\xa5\x14\xeb,&\x84\xe4\xe3\ +\xe2s\x86\x14\xb2T\xca\xa5M;\xd7\xb9\x07\xae\xad\x8c\ +\xc3\x09\x80@\x02x!\x81\xcf/\xaf$\xf7\xcf=\xb8\ +\xfd\x90\x0e\x00Z\xc6\xf6\x88\xa3\xc2F\xa6\xc2\x06\x06\x16\ +\x9a\xbcka\xae%\x12\x19\xe3j\xe54Y\x00\xfa\xb5\ +\x1b'\x95\xdc0\xa5\x19ie0:\x97,];v\ +\x07\x19\x80\xd1\x03\x90s\x8crN\xf8G\x18\xfb\xe41\ +\xeeZJ\x13\x81\xd2\xd2\xa6V\xe0\xc4\xb0\x17x\xe8%\ +\x0b\xa3\xe8\xc2\xe1-+\x1d\xdbA\xb6@\xf6\x86E\xfb\ +\xb1z\xe5\xc4\xca\xb1[\x17\x11m\x0c]\xe6\x7f\xb0\x16\ +\xc8\x97:r\x85A\xa8c\xb7\xa03W\x0b2\x8bO\ +\xac\x04\xafS\xb9\xfd\xc6j\x0f>\xe0\x09\xbe\xb6\x06\xf8\ +E\xdd\xc1\xf7V\xb3\xf3\x83Um~OJ\xf9\x11\xe2\ +\x09?Y\xc6\xc5.\xa0\xe4\xd9\x97V\x04G\xc8\x9f\x84\ +\xb0\x92\x92\x16\xcc\xbe@\xe9*\x03\x7f\x0b\xcf\x11\x9fx\ +E\xea\xf4\x18\xaeq\x8b\xc1\xd9\xc5\xb5+\xd6\x93\xf3k\ +V\xee|\xdf}z\xcb\x04\xf1s\x0e\x0f\xa5\x85\x1c\xd5\ +\x14\x10\xaa\xe0*\x1e\x00P\x86b\xbd\x06\xd4\x81@^\ +@\xec\x1b\x97\x0d\xf9J%\x0bq\xb5\x00\xa4\xa3\x19\x8d\ +\xe3\x16\xe9Z\xb0\x86\xf9c\x1b9|j\xd3\xa7\xefm\ +\xee\xee76y\xfb[\xeb\xd8\x03\xdc\xcbxXrx\ +\x95\x7f\x97\xc0}\x8aa\xf2\x85x\xc2\x06C\xa2\xcd\x15a^s&\x89\x8b\xb3\xb7\ +\xc9T\x1eX\x05|\xa4\x9eT\xb5\xed\xe4{\xeb\xbc\xf9\ +\xab\xf5\x9c\x92^\x22\xbd\xbc\x1f:\xfd\xc5\xc6o\xffj\ +\xa3\xbc\x8e\xde\xfa\xc5\xa6\xef\xfcf\xe3g\xa4\xaf\xd7\x7f\ +F~\xb2\x9ek\xda\x0a\xff\x05<\x86\x10\xa0\xcd\xb0|\ +\xb7\xbf\x7f\x13\x00h\xbf\xdd\x88%VkF\xae\xcd\x12\ +*[-\x09 \x08\x04\xea8\xe6*\x8c\xc8\xab\x95>\ +jS\x85\xfa\x15\xb8\x12z\x14\xef\x94\x8fb\x02\xdc\xbb\ +\xebe@\xb8\x10o\xf0\xb9\xa9\xe4yR\xbb)\x0b4\ +MZq\xff\xb25\xcf\xeeZ\xe7\xca\x91\xf5\x5c\xbda\ +]WO\xadzNet\xbbn\xb5N\xcb\xe6\xd9\x84\ +\x1b\xcdB\x06\x01Q\xa6\x96\xb2!r\xda\xb3!\xee\xe1\ +\xb6\xc7\xf3\xfd>@\x98\x01\x18\xdd\xe6X\xa5\xbd-j\ +QC\xca\xda\x8c\xf2[\x18\xd3V\x94\xdf\xa6P\x84\xd2\ +\x01\x80\x9b/\xc1;\xa4\xc2KR\xf9\xbf4B}\x06\ +\xd7\xf2i\xaeep\x17\x00\x10\xe7\xd4E\x22\x9dAH\ +S\x87\xad&\xdc\x7f\xe34\xaep\xda\x12\x9d\xcc8I\ +\x16\xa2\xf5@\x9a!k!^:\xc5\x03\x02D\xe9\x92\ +\xbaeh\x7f\x9e\x1a\x1e\xb9:6-\x1d\xab\xf2\xc5\x11\ +=\x5c<\x03\xa78\xea\xedC\x00}\x221\x9aD\x11\ +C\xc5E\x05A\xbd\x98\xb3z\xf5\x84\xc6!\xa4\xe2\x1e\ +\x13\xa4+\x93Z\xc7\xc7J\xe6\xeeX)\xd9I\x8d\xc8\ +\xd4\xf1\x176r\xf7'\x9b~\xf2'\x9b\x7f\xfeO6\ +\xf7\x04E\xdf\xfd\x1e\xe5\x7fkSw\xbe\xb5\xf1\xd3\xaf\ +m\x82\xece\xe9\xe1\xcf6\x7f\xef'\x1b\xbd\xf9\xd1F\ +n~k\x83\xd7\xbf\xb6\xc6m\x88\xe0\xf2\x03x\x01\x84\ +hD\x939\x022\xc0\xaf\xd3L\x5c\x97\xc5\x97\xb78\ +I\xacl\xb7d\x00\x91\xa2\xae\xa7n\xc3\xaa\xf6\xdd\x01\ +d=\x93f\x0b\xe1\x0e^\xbb:)\x9fl@\x1e\x00\ +\x0b\x0bh\xf1E\xd3\xbf\xbdd\x14\x10\xc9\x8c\xd6y\xf3\ +3\xae\xd1\xaey+\x1d\x5c\xb1\x8a\x91\x15\xbc\xc1\x9a\x95\ +\x8d\xaa\x10\x94\xef#\xd4\xaaa\x85V\x1a]\xc1G\x9d\ +\x96\x805\x0b\xa8\x95A-\x0b3\xce\x18T*\xe3\x9a\ +J\x86\x92\x0a\xb8R\x19\xd3T\xa5\xa9\x00 \x9dT1\ +]\x16\xdf\xa6\xf0#\xc5\x13\xd2\x9c\xa0|B\x81&\xad\ +4G\x92\xc6\xff\xa7AL\xd3{%\x18}\x1fY\x0e\ +\x12\xe3\xebY\x858\xe0\x86\x89\xdb>\xe2\xb3\xeb\xb5\xc7\ +\x83\xca\xc2SPr\xf2\xf9DHr\xa3\xa6$\xb58\ +\xa3\xc6\x8eR\xfe\xcay\xae\xea\xddH\x86,\x1b\x94i\ +\xe3\xa6\x8a\x18/\xc4U\xb5\x92\xee\xa9\x9a&\x82{\xd7\ +\x0eZ\xd5\xdbGx\xd5\xbc\xf9\xa7\xee\x9f\xaa\xba\x1d\x82\ +h\xa1\x94,\x08eh\x0cR9\xb6\xcf\xe7\x0eH\x97\ +\x8eL\xbbm\xd4\xe2\xac\xee\xea#\x1b\xb8\xf1\xc1V\x9e\ +\xffjG_\xfd\xddn|\xfcW;\xfa\xe2/\xb6\xf2\ +\xe4[\x9b\xb9\xf3\xd6\xc6o<\xb7\xc1\xc3\xc76L\xbc\ +\x9d=}g\xd37\xdf\xda\xd0\xe1K\x1b:zi}\ +\x07x\x8f5\x98\xf6\xec\x09\xdf\xa9\xf4\x93\xf0\xd5>\x0d\ +\xe8\xd5h\xa1\x0f\x00tZB\x05\x1e\xa0\xbc\x95\xd7v\ +@\xa0p\xa0\xde<\x02\xc18\x166\x03\xc8\x09i=\ +\xeb\xfc/\x80\xd6b\x0b\xcf\xa5\xb4\xcf/\x0f\xc0\xcf^\ +{\x1b\x00\x80g\x11\x99\xd6zF:\x9cJ]S\x03\ +\x84\x14\x7f\xd3\xa8\xf9\x1bG\xcc\xa7N\xa6|o\x92\x9b\ +\x02\x1e\xc4\xeb\x0cZ|\xc5\x80\xc5],\x02\x95k\x19\ +x\xc8\x12j\xf0\xc8\xf5\x18\xa2\xa6\xbd1\xb6$\x8cM\ +\xb3\x9e\x9a\x01M#\xc7\xcf\x10\x07\xe8\xda\x87\xc8z\x92\ +\xde\xa9Y\xd2\x1d\xf4\xb2\xe9\xe6,RP\xbe\x00\x93\xa6\ +0\xdf\xbdJ\x0a\x0b\xd7\x03\xf4\x92\x0c\xde\xc7\xb8V\xab\ +\x17B8P\x91\xa2\x10\xae\xc5\x0d}\xb9\xa6!SZ\ +\xd7\xdd\x1c|j\xb3\x17\xb7\xd3P~\x1a7!\xc5{\ +92\xa8r\x00P\xca\xc4\xff\x7fR>.\x0d\x8e\xa1\ +\x9c_\xe5\xcbZ\x9e\xd4nU\x89\xdb\x8a\x8d\xc5\xab\x16\ +N\x9b4\xfc\xa0\xd1\x07q\xf4C\x14%\x81\x81U\x06\ +w\x1d\x80h\x0d\x7f\x8b\xb4m\xcf\x8ag\x8e\xaca\xfd\ +\xb6M\x9e\xbd\xb5\xa3\xcf\x7f\xb5g\x7f\xf87{\xfb\x97\ +\xff\xd3\x1e\xff\xf4\x17\xdb}\xfe\x85\xcd\xdd|h\x03;\ +\xd7\xac}e\xcf:V\x0elx\xe7\xa6\x0dn\xdf\xb4\ +\xce\xd5\x13\xeb\x5c\xe3\xf7H\xe5\xcc\x8e\xe5\x0d\xafBR\ +\xc5K\xa6\xb0<-\x19\xf7\xa1h\xad\xb1w!\x1d(\ +\xa3\x03\xe5w\xba\x9f\x93\xf0\x02j8\x99R7L\x5c\ +\x1f\xc7bg\xf0n\x8b<\x1b\xbc\xa0\x0f\xb0+{\x92\ +\xdb\xefE\x11\xb2z\x9e\xc3\xafLG\x03\x0c\xf9Ko\ +S5\xb0\xa6x\x15b\x06\x00V/\x00\xebF\xba<\ +)\xeb\xb6\xc42~\x87\xc4KJ{,N\xe2\x96~\ +\xfb\x09I\x1e\x08\x12\xea\x00A#\x86\x88\x0e\x92[\xd6\ +\xd0\x09\xe3\x8eu+\xc6gh\xa2\x08\xb2\xa7I\xa0t\ +\xb8T:Y\x95\xf3\x14\xe8 \x0d\x02\x9b\xaeu\x15g\ +\xf1\x00\xbe\x17\xaf\xa4{S\xe9:\x82\x07\xe0\x86\xc9W\ +\x03}rk\xb0}\xdcX61M\xb3hJ\x1f\xfc\ +\xa4\x19n\xee]\x17s\xeeFn\xc7\x13\x17\x83\x1c\x08\ +@\x17.\xc9\xa7\x18)\xf7\xffI\xf9W\x11^\x19(\ +\xcd;\x87\x86v]AF\x88\xb8\x97\xad]\xb1\x03\xba\ +.\x83\xd5\x0d1\xec\x9c\xc3M\xcd\x22\xb8\xc3\xae\x19n\ +n\x96kC\xc0PTv\xff\x12\x8cx\xd5\x0a\xc77\ +\xac~\xf9\xd0\xa6n>\xb6\x9b\x9f\x7f\xb4\xf7\x7f\xfa\x9b\ +}\xfb\xb7\x7f\xb6\xd7?\xfdj\x07O^\xd8\xc4\xde\x89\ +\xb5\xcc.[\xf9\xe0\xa4\x95\x0dLZ\xfd\xf8\xbc\xd5\x8d\ +\xcd[\xc5\xd0\xb4U\x0c\xcf\xe2~\xe7,\xafw\xc2\xb2\ +\xda\x87-\xd0:\x08C\xef\xb3\x94\xdan\x94\x8f\xe2\x89\ +\xf9\xff\x9b\x08\x0c\xbc&U\xf3\xf7\xea^\x148`\xa9\ +\xf0\x04\xb7\xa0\xe4\xb2\x03<\x01\x16\x15P\xda\xac\xcd&\ +p\x1c\x91I5\xb7Hk\xc3\xab\xb4N`4c\x84\ +S\xbcK=\x96^\xa3E\x1f8\x06J\x8f/\xebD\ +\xd1\x1dN\x12\xd5\xb7\xb8\x14 \xf1%\x9e\xc4\x95v\ +\x9f\x83\xa0\x0f\xaf\xa0E-\x15\x88(,/\xf2\x9d\xea\ +\x89\x80.p\xf3\xbeN\xf5s \xec\x90\xef\xfbd\xb0\ +x\xdft\x8c8\x95\xac&\x19o\x9e\x02P\xd3Pr\ +:J\xf7\x8c\x0b\x03G<\x80\xf2;\x95\x84\xa5\xa30\ +\xcd\x82\xa9\xe5\xaa6>\x84 a\x11\xcd\xc6iN{\ +\xf46i\x1e\xa9R\xff5<\x04\x17Q\x9e\xdb)\x86\ +\xb9\xc1\x0d\x00\x86s\xe5K4u\xfaI\xf9R\xba\x13\ +M\x86\x88A#\xbcfq\xe1 n7\xd8G~M\ +\xfcS/\xbb\x8cN\xf2\xee\xb6q\x1el\x98P3h\ +I\x8d\x03p\x8e~\xf7\x9a\xc2\xcfi-C\xc4Q\xad\ +\xe5\x8fZ\xb8g\xc2\xca\xc6\x97lp\xe7\xc4\xf6\x9e\xbc\ +\xb4g\x1f\x7f\xb0\xf7?\xffj\x8f\xbf\xfc\xda6\xce\xee\ +Y\xf7\xd2\xba\x15v\x0dY\xa0\xb6\xcd2\xaa\x9a,P\ +\xd3l~\xc4W\xddd>\xbd\xafk\xb5\x8c\x9a\x16K\ +\xadF\xaaZ-\x19\xc2\x97\x88\xcbO\xc4\xdd;\xabw\ +\x1e\x00\x8bD\xe9\x89Ux\x04\xac_\xcaO\xaa&\x0c\ +\xd4\xaa\xdb\xe8\x08\xa4P^`\x0a\x82;C\xb8$\xd7\ +oS!\x8a\xac\x5c\x04\x9a4\x92\xcf%\x126\x12\xf8\ +\x0e\xd5\x22$\xc8\x93\xa8_1\xd7\x88/kC\xe9\xad\ +(\x19\x9eQ\xdc\xec^\x13J\x087%\xfc\xbe\xb8\xdd\ +\xe2\x90\xd8\xe2\x0e\x8b-\xe9\xb4X\x81\x80P\xa0e\xe1\ +\xc4\x1a\xbe[\xeb\x04\xeaQ\x80{\x0ft\x8b;\xc1\xa3\ +\xfa$\x10Q\xcdDb\xf5\xda\xf5\x94J\xb6\x95\xdc6\ +e\x89-c\x84\x8cQB\x05\xfc\x05\xa3\xca\xe8&\x0b\ +\xeb\x85\x98\x93\xd6\xfb\xc5\x01\x00\xae&\xbfbD0\xd2\ +5\xe3\x85\xdbWK\x12\x15O\xe6\x90#F'\xef\xf3\ +\x0aS\x1e\xbb\x039\xf3@\xa0\x99.\xbf\x9bi\xf2\xa6\ +\x1a\xddvr\xdc\xbfS>$\xc3+u\xf6f\xc0\x9c\ +\xf2Q|&\x08\xd4\xfc\x80\x96a}XxF\xc74\ +\xc0\xe1\xa6\xda\xb0\x8e\x16\x94.\x85\xd7\xe3\xfajA\x7f\ +u\x87\xc5U1\x10U\x0c\x88\xd88\xaf\x92\xc4\xeav\ +,\xa8\xc3\xd2\xea\xbb,\xd29l\x8d3\xab6up\ +\xd3\xf6\x1f\xbe\xb0\x9b/\xde\xda\xfe\x83\xa76\xb9sl\ +\xf5c3\x96\xdd\xd0a\xc9\xa55\x96PX\x89TX\ +BQ\x85%\x16WZbI\x95%\x95T[Ri\ +-\x16W\x8f4\xe2v\x9b\x11\x14P.\x00\xa0,)\ +\xbf\xaa\x97\xeb\x89\x0f\xf4\xf3\xca\xbd\xd5H\xa1X\xb0Z\ +\xdc\xd7\x8d\x90\xdf_\x08\x83\x8b\xe8w\xea\xd6\x95X}\ +a\xe1<\x03J\x8e+iB\x99\x0d(\xb5\xde\x93\xa2\ +Z\x8b-\xfc\xbd\xd4\xf1\xbb\x06@\xd0\xe4\x01\x02\x10\xc4\ +\x95\xf0\xec%\x00\x00o\x10K8\x88\x85\x13\xc4\xab\x00\ +\xa5N\xbb\x7f!\xda0z\x11\xe70\xfa\xd0V\xf5\x1c\ +$b}?9v\ +\xcf\x88E[{p\xf7M\x96\x5c&%\xcb\xea+\xb0\ +xI%V\x8f\xf5\xe3\x15\x12KQ>\xd6\x1f_\x8a\ +\xf2\x1d\xb8\x00\x9d,\x16\x00\xc4\xf1\xbd\xf1\x0e\x00\x03X\ +\xbb,\x9bA\xc2\xed&7\x92\x05A\xbe\x12Uqt\ +^r\xa6\x92\xb4\x04<\x83\x0aNd\xf5\x22u\xbf\x07\ +\xc0\x95b\x0f\x00\x97\x0b\xaa\xecr^9R\x8a\xe2\x8b\ +\x9d\x5c\x91\xf0sl~\x19\x00\xa8\xc4;\xd4\xf2?\x8d\ +\x0e\xe4q\xfc\x7f,\x1c!\xb6\x12\xf2'\xf05`\xf9\ +\x90m\x91;\x15\x9c\x84\xd1Kt\x1a\xe5\xcf=r\x92\ +;\x03\x00 \xd4\xda\xe5\x9c\x81\xebOi\x1cu\xe3\x19\ +[\xd1lWx\xd6+x=I,^/\xae\x82g\ +\x16\xc1%\xa4%\xd4\x00\x12\x95\xcd\x01\xe2\x98\xd8rb\ +]\x8d\x0a'U\xa5JzC>\x1b\x1eU\xaav\xd7\ +\xa2\x84\x00\xb7\x99p\xf2\x11i\xd8\x13+\x98~\xea$\ +\x7fJ\xa7\x8b\ + (\x00\x04\x85x\x81b@PnW\x8a\xf0\x14\x84\ +\x89+\x80\xf2\x0a\xdf\x15+`\x01\xb4\x94\xd6\x05G\xec\ +4\x03\x18\x998\xb3\xe8\x0c\xfa\x98G\x1fH\xee\xac\x0a\ +BH\xa3!\xd5\x01\xd29\xb5\x86M\xaeW\xd6\xd0\x86\ +\xc2\x1b\xf8\xbej\xbbL\x08\xbc\x5c\x00\x00y\xd55b\ +\xb9F,\xdeF\xcf\x1d\xab\xe7\xe6~cbE@\x18\ +\x5cU\xbdj\x0aS)\x8d\xb6FG\xc6@\x9b\xbah\ +M=\xb4\x02m\x9d\x9aWO\xe1W\xc8k+\xd6\x89\ +\x1a\xb3\xcf\x1c8\xd4A#t\xbe\xc6\xeez\xf4ha\ +\xa7[\x8a\xd6\x19\x02\xc7\xae\xfc\xbb|\xf2\xaeU\x81\xd6\ +\xca\x99\xdbV:qby\x83x\x1aBCF\x8b\xa6\ +\x9e\xe5f\xe5n\x89\xa3\xff\x9b\xc8\x0d+\xb6\xca\xd5\xe2\ +-\xb0\x8a\x84\x0a@\x82\x8bt\x0c\x9a\x81\x8e\xc7\xd5\xc6\ +\x13O\xe3p\xb3\xb1XZ\x5cA\x19q\xb5\x9c\xbfa\ +\xf5R|e\x1dd\xaf\x1e\xd2Wo)\xd5\x80\x04b\ +\x98XI8q\xa1\xa6\xcd.3\x10\x97$\xb8\xdf\xcf\ +\x90\xcbR$\xd6\xa1vu*\xa7rM\xa9\x00\xb0\xda\ +\xd3\xa5\x91V%\xb5.\xe2\x05T\xa38\x82\xd7\xd2`\ +\xff\x8e\xd5\x0b\x00r\xe1|OlI\xb3]\xc6\xb5_\ +f\xd0/\xa1\x00\x07\x80\xdcB@\x90\x87\xe4\x02\x82(\ +\xde\x80\xd7\xbc|\xbb\x9c\x8fg\x90\xa2t\xa2\x09\xca\x11\ +\x00\xe2\xc4=\x00Z\xaa\xa6\xd6\x95F+}V\xa3\xa7\ +i<\xb3j\xfeP|h\xfc\x10`\x90\xae\xf7h\xce\ +F\xc6$#\xc2\x03a\x0cWJt2\x0a\xd6\x8f\x87\ +\xb9\x5c \x10\x10\x86\x0a\x01\x99;1\x05\xa0)D!\ +\x97\x8b\x9a\x00@\xb1\xe2\xa0R!\xf2\x5c\x15\x0d\x12\xcb\ +\xb5\xe0\xa0\xa5Ym\x94\xcc#\xde\x14\xcc=\xb6\xe2\xc5\ +\xe7V\xba\xa2\x05\x15\x00\xb0\x04\x00\xe6_\x10\x8b\x1e\xe1\ +-\xce\x08\x07\xd7a\xa3\x87X\xfd\x9ee#\x11\xde\xe7\ +\xf1\xbb\x12\xf8C\xf5\xec\x13k]{m}\xbb\x9f\xdb\ +\xe0\xfe{\xeb\xdd~n-\xeac?\xbek!\x11\x92\ +&n\xde\x91)\x89\xb7\xdd\xc9\x131j\x84\xfbr@\ +\xa8\x04\x04b\xc5b\xc7\x90\xa5\xd8\x22\x90\x5c\x00\xa2\xf3\ +x\xb0\x5c\x01\xa0\x02\x00T\xe1R\x89\xabeX{e\ +\x03Jo\xb2\x94\x9aFK\xadmB\x9a-Y\xf1\x10\ +\x8f!\xbe\x11\x8b\xd5_Fi\x97\xce\xe53\xbd\xa2\xcc\ +81\xfe\x86Q\x88\xea\x1c\x83\x8f\xb7\xea\xdf\x22\x85\xda\ +v\xf9tr\xfb\x0a^@\xc5\xa7\xe7^\x00\x0e\x10\x8f\ +\xa7\x8a/\xfb\x07\x08\x14Vbq\xe7Wp\xebR\xea\ +%\x94\xe0\xbc\x00\xae\xff\x12\x1e\xc0\x03A\xd4\x13@p\ +\x09O\xe0\xfe^P\x03h\x00\x00\xdf\xa5\xb2\xf0\xc4z\ +\x11e\x98\xbb&\x9d\xb4\xc1cT\x9eY\xdd[4o\ +\x02\xf1&uN\x85\xed'\x13\xd7\x13\xe0E\xf1z\xae\ +\xf2\x06\xc0Ws\xae|\x89\x94.\xd1\xef\xea\x183)\ +\x1f\xef\xe08\x8a'1n\x22\xa2B\x8d\x88\xd5u\x1a\ +\x96\xc8C\x0a\xf9\xd9\x83*h\xb8\xe1\xaaF\xf2\xb5\x95\ +X\xe7\xe1,=\xb3\x22\xa4p\xe1\x19\xbf{\xc2\xdf\x1e\ +pS\xe2\x04j\x0c\x01w\x18<\xb1\x5c8D\x11D\ +\xa5\x1c\x82R;\xff\xd4Z\xd6\xde\xda\xf0\xe1G[\xba\ +\xfb\xabm>\xf9\xcd\xd6\x1f\xfc`3\xd7\xdfX\xc7\xea\ +-+\x1a\x22\x05\xc5\x0bh\x7f\x9b\xd6 R\xe4\xf6\xb4\ +\xdb\xc6\xc9\xf9\xfe7\xac\xcd\xb1l\xcd\x96\xc9\x03\x08\x00\ +J\x97\x0a\x01@\xbe\x00\x00\xa3F\xe2\x0a\xea<\x8f\x80\ +\x15%h*\xb7\xaa\x85\xffk\xe1\xff\x9b-\xa5\x0e\xa9\ +\xe7}\x1d\x19E\x0d\x8c\x1f\xbe\x11G\x18\xb9\x82\xfb\xbe\ +LH\xb9Lh\xb9\xa4Wm\xbc\xc0\xfd&\xd5+\xfd\ +$\xdd\xeb\xc2 4i\x02\x10\xd2PDJ\xa7j\x0f\ +U\xa4:\x0f\xa9\x22\xd5\x02\xa0\x09\xdc\x97<\xa8\xf3L\ +\x02@)V\x08\xb9t\xae\x16\xb2y\xc5\x9dU\x04\x17\ +\x90+\xce\x87\x0b\xe4\x15a\xfd\x00!\x17 \xe4\xe6;\ +`|\x06x?\x03\xcc\x97\x8aZ\xed2\xcf'\xf6\x9f\ +\xc0w\xa7@\xd6\x14\xdb\x03\xdc\x83\x0aY3yU\xa9\ +|:d:\x19\xa6\x9fX\xcbu\xaby\x16b~l\ +\x99\x94\xcfX(\x9cp=\x11Le\x1a\xb1(<\x96\ +\x90$n\x22\xef\xe4\xdd\x9f\x84{%\xe3\x88I\x22\xcf\ +T\xd7ImgV\x17J\xf5\xa2S'\x0d5A\xc8\ +V\xf3\x85\xb1\x13\xdc\xcf\x0d\x08\xc7-\xcb\x9b\xc5#\x10\ +{rU{>\x0dA\x9c\x84\x14j\xf9\x16\x85\xe7\x8d\ +y\xbb\x7f\xca\xa6\xb1\xfa\xf9\x87\xd6\xb0\xfc\xdc\x9a\xd7P\ +\xf4\xd6\x07\x9b\xb8\xf9\xa3m?\xff\x8b\xdd\xf8\xfc\xefv\ +\xf2\xf6\xcf\xb6\xf9\xf0\x1b\x1b\xde}`\x15c\xdb\xee\xa0\ +)\xedm\x93\xa2SP\xb8\x07\x82\x7f\x88@\x90\x04Q\ +U\xc5l\x82\xd2\xa22,\x8e\x1b\x8fc\xb0\xe2\x00A\ +\x1c(\x8e\xc7\x95%`=\x09\x0c|\x02\x16\xe8\xa6s\ ++[\xcfA\xe0)?\xb5\xb1\xdd\xd2\x1a\xbbyOn\ +\xef\x06\xae\xef|\xf3\x85^\xfb=\xe1\xbd\xb6])\x87\ +O\xe2s)-\xe4\xfe\xed\xe3n\x82*\x15\x12+\x00\ +\xa4\x90\xf6\xa6\xb4\x03\x04M\xcb\x8a\x18\xd6Nb}\xc3\ +X_/\xd6\xaf\xfc]\x83\xab\x81\xd6\x80\x0b\x04M\xc4\ +c\x85\x03H!\xd6x\x09w\xec\xf1\x82R\x84W\xc2\ +\xd7g\x80\xf7\xb3B\x94_\xdcM\x18\xd0\x9e\x80!\xc2\ +\x0b)\xb2\xc6D'\xaf\xa9\xeb8\x80\xcc\xd0\xb9\x01d\ +P\xa9dOIdN\x09\xca\x9c\x5c\xc6D\xca\x09\xd8\ +b\xc9pb\x8b\xa4\xf8\x1a\xc6Ei&\xe4R\x1e^\ +!S\xb3\x8e\xf2V<\xa3\x17N5+9`1)\ +0\xcd\xd4\xc6y\xdc\xbf\xb6Uii\xd6\xab\x84QK\ +\x15mZ\x0c\x0e\x10\xd3\x87\xf0\x08#\xb8\xecQ\x01\x82\ +Td\x1ck\x9f\xb8I\xa6 \xb2\xa8](\xda\x83~\ +\xd7\xea\x96\x1fY\xd3\xda3k\xdf|e\x9d\xdb\xef\xac\ +m\xf3\x9d\xb5\x22C\xd7\xbe\xb1\xd5G\xbf\xd8\xe1\x9b?\ +\xdb\xc1\xab_m\xe3\xe1W6\xbc'\x00l\xb9\x1d\xc6\ +)Xx2qO]\xb0u\xa6\xcf?\x80 O\xa0\ +\x85\x9a\x09\x14\x09\x10\xaa\x00\x82f\xc6\xdc\x94)\xae\xd2\ +\xe5\xcdp\x18$\x01R\xa3,\xc1\x09\xac^S\xbaI\ +\xc4\xc4\xe4Z)\xbe\x93\x01\xecE\x06\x18\xccA\xbc\x0d\ +\xbc\xa2\x16\xcb\x85_\xc4\x13^\x12H\xf9$\xaa\xc9\xd7\ +\xf6+\x97\x8a\xc2\x9ac\x95F\x91B%4\x0dYR\ +\xdb\xac%u\xaeZ2ioJ\xd76`\xd8\xb2\xe4\ +\xb6uR\xa9E\xacu\x12\xe0\x0c\xa1\x08\xfe\xd7\x85\x01\ +\xee\x8b\x10\x13/!\xabQ\xa6\xa1\x90s\x05p^\x01\ +\x18\x97\x1dI\x14(p\xc3\xc5\x0a\x17\x9d\xfcM\x9b?\ +\xe0\x16\x15\xe3\xe7\x82w!\x15T\xe8K\x82\x1c'C\ +zS\xaa\xda\xe15\xad\x90Y\x00\x8f\xc5\xc7\x97\xa1\xe0\ +2Y?\x02\xd8\x048\xcd?\xb8I&\x1d\x8d\x87\xa1\ +$pO*?\xffG\xc99\x9c\xcb\x95\x9dk\xbf\xc3\ +\xa4\xc5\xe8\x8c>\xd7\xf0\xb8C\xdb\x91\xc9\xe9\x95\xd7\x93\ +\xcai]@\xd5AN\xb4N\xa0\xdd\xa4}\x9b\xc4\xa3\ +\x1d\xf8\xc1!\xa9\xe2uB\x00\x96\xaf\xc2\xc7\x99\xbb\xae\ +QT+\x8a\xef\xd8~k\xdd{\x9f;i\xdexm\ +\xb5+\xcf\xacc\xe7\xb5M\xde\xfc\xc2\xd6\x1e~D\xbe\ +\xb6\x85\xb37\xaeJ\xa8l\x84\xeb\x80\xee\x14\x08U\x12\ +\x84*\x09\x8bt@8\x07\x81\x9a-\xb8\xce\x1aHJ\ +\xfd4\xe0 \xe6q\xf3\xf2Z\x0e\xc1\xb8nG\xc2P\ +zBE\x977PX\xb66`\xe8\xcc\xc0\xd4\xfa^\ +Kk\xe8%\xcc\xf4\x9b\xbfu\xc8|\xad:yc\x04\ +\xc0kzV\x16\x06\xbfP\x88Q\xf3e\xf1\x0d\x00!\ +V\xef\x91\xb8\x1a\xbbT\x02\x93&\xae^\x91\x9b%\xc5\ +J &'unXJ\xcf\xae\xa5@\x0cS!\xbb\ +)\xedW!\x86\x0b\x16\xc7}\xc52\xd0.\x8d\xe3~\ +\xe2\x091n6\x91\x0c\xc7\x11Zq\x06\xf8\x8c\x00\x17\ +\xa7\xb0\x81b\xe3+\x95J\x0a|J-g\xf0:\x84\ +\x96z\xd2\xce\xbay~7\x8d\xa5\x8e\xf1\x8c<'\xbc\ +@\xde-\x11v\x9f\x88\x9bO\xe0\xbe\xe2\xc5uJ\xb0\ +r)\x1dB+\x90\xb9\xcd&.%U\xb6\xd4\x8b!\ +\xc0%\x04\x22\x19N5\x06t^r\x9eT\xaf\xfd\x06\ +s\x90\xddE\x8b\xc9h\xdf\xf0\xd2\x1dP\xad\x22\x83\x80\ +\x13\x01A\x877\xae!\xaa\x8f\xf3j\xe4\xb4\xd9\xc05\ +\x22\x22\xad\xd3\xd6\xa3<-\xd3b\xf9e\x8b\x8f\xac\x11\ +\xe5w\x1d|\xb0\x9e\xc3/\x9dt\xee\xbd\xb7\xda\xd5g\ +\xaeKU\xd5\xc2]k]\x7f`}{Ol`\xff\ +\xb1\xf5l\xdf\xb5\x86\x85#\xcb\xef\xc7\xe30\xb0\xc9(\ +\xdf\xb3^\x06\xcdm\xe4\xd0aO\x9aiS\xa3\x05<\ +\x94+\x97>\x97zrc\xe5\xe8n\x83\xa6\x08\x22\x0f\ +\x89\xd25\xd7\xee\x1d\x0e5d\xe9\x0dC\x96A\x8c\xcc\ +\xc0]f`\xf1\xbe\x96!\x000j\xfe6\xed\xa2\x1d\ +\x83x\x0a\x5c\xe7 P\xf8\x81p\xba0$E\x89\xd9\ +c\xa5r\xa7b\xf1\x97\x19\xe4\xcb\x15XiM\xaf]\ +i\x1c\xb782\x81\x04\xd2\xe5$\xc6(\xa5\x8b\xf4\x10\ +@h\x95.\x81A\x8d\xc7\xc2D\xe0\x94!hJX\ +\xe7\x15\xb9\xc3#Zf\x11M\xe5\xaai\xd4<\x03\xcf\ +38Pk\x09x\xce\xad\xae\xa6\x91fju/M\ +k\xf7\xadW!w\xcb\x80b\x16\xe5\x01<\x94\xa9\xd0\ +\x96\x08\xb1L\x90\xe2I\xf1$q%\x9a\xd3\xd0\xf2\xb5\ +\x94\xcf}kb\xca\xad,\xe2\xd5\x90\xc4J\x14/\xe1\ +;\x1c\x00jd\xf5\xbf\x03\x00\xde+\xe6\xe2\xa0FW\ +K\x06\xb2\xd5\x06EG\xa0y \xd0\xe2\x8e\xa6y\x09\ +\x09n\x96O\xa5Q\xde\xd2\xae\x00\x90?}\xea:c\ +V\xae>\xb5\xd6\xbdw\xd6w\xedk\xe4\x1b\xeb>\xfa\ +\xd2\xdav\xdeZ\xe5\xe2C\xb8\xc1\x0d\xcb\xc3c\x14\x8d\ +\x1dZ\xd9\x94\xe4\xc0J&v-\x7f\x08v\xdb\xc1\xc0\ +\xd4\xa1\x04\xe5\xdf\xb8NM\xf6(\xdf\x17\xe1\x93\xcb\xd7\ +d\x8c\xea\xe4\xb5\x1d*\xadq\x09\xc5-c\xc1H\x93\ +v\xed\xe8\xf7x\x85\x06\x85\x8aQ>\xa7\xc1\x1eC\xe1\ +(\xb9y\xcc\xfc(\xda\x93Q\x0b\xb4\x8e}\x12\x0f\x00\ +\xfa\xbc\xa6s\xe1?\x88^S\x00\x8eV\xfd\xb4\x16\xa0\ +\xe5\xe0\x0b\x02wY@(m\xb4K\x15\xedv\x09\x90\ +]\x86\xac\xc6B\x96\xe3\x95\x12\xb6i\x9f\x00a\x01\x00\ +\xb8\x89\x22\x00+\xf6\xaem\xddZ\x1f\xf0\xb5\xc3\xe21\ +\x1e\xd7\xe8\x01cr\x87o\xa8Z\xa8\x19 \xf0y\xd7\ +=\xa4e\xd1\x85]\xad\xc0\xaa\x06\xaa\x9c\xd2\xd6mw|\x1dc\xaa2\ +\xb5\xec\xb1\x9b\xa6\xcac\xedo\xd0\xb17\xa9\xad\xf2\x1c\ +p\xa5F\x8c\xa5^\xde\x050h\xf9\x1a\xaf\x94\xc8\xf8\ +%\xd5b\xedx0\xafm\xec$\x0a\xf6$\xa9\x86\xd7\ +\xaa\x09\x84\xdf\x0b\x00n\x9f\xa1@\xa0-\xe8\x02\xeb\x8c\ +\xc5\x08\xbd)\xa08\x95\x0b\xa5\x13\xff}(Zk\xdb\ +:\x8bO\x00p=l\x9cxu\xfcjC\xaen\x19\ +\xaeO\xde\xe4u\xd7\xf2\x5c\xed\xe6\xab\xd7\x1f[\x8dZ\ +\xa5\xae\xa9\xa1!i\xe3\xf4M\xac\x1f\xae\x00\x89\xd4\x16\ +f\x1d-\xab\x93D\xb5\x9c\xea\xce\xf5\xc3b\xd5\xdc \ +Q\x1b\x22\x15\xb7\x94F\xc9\xd5\x11\x17\x93\xb8Im\x9b\ +J\xa9\xd76f,_\xab`(\xdd\xf5\xe8\xef\x06\xa0\ +*\x88\x94\xb7\x12hU~u\x1e\xaa\xfc\x00\xcc-<\ +ui;\xb6Z\xc6\xa8\xaf\x80\xf6\xec\xa3x\xc2\x81\x18\ +\xb4\xc2C\x1a\x03\x99F\xe8I\xd5\x86M\x85 \x07\x00\ +@W\xa7\xc9\x141e\x119M\xe9\x9e\xb3w\xe43\ +\x09@\xb8\x04\x104\x81\x14+\xd0*\xfc(Um\x84\ +\xa7\xa0L\xb5\xaf\x17\x7frar@-Xd0\x90\ +h\x80\xa0\xbaBw\xe8\x83\x03\xacd\x01#\xe0^\x01\ +\x85\xba\x82\xa9\xd1\xa5\xebA8\xa1z\xc8S\x0b\x8e\x02\ +\x02Rj\xef\xa4\x14<\xb4+\xdcY\xe0\x1axE2\ +\x02o\x99Y\x9eK\xa1R\xe3\xc9xi;\x1c^E\ +\xee=Y[\xcb\xc4+d\xed\x02\x02J\x17\xd7H\xc0\ +\xb0\xb4\xd9V\x9bl\x13\xe0U1\x09\xa06\x91\x9bO\ +\x22\x03p+\x83\xb8{\xd7\xa3\x9fx\xef2\x01!\xf8\ +w\xa2\x22\x08\xf5\xb0\x09\xa9\xeb\x84Z\xbdN\x9dX\xf1\ +\xfcM\x94N\x0a\xb8t\xe6\xde\xebw*\x13\x8fh\x03\ +f\x9fz\x05/\xba>B\x81\x96i\x94\xc0\xcd\x12s\ +]~\xff\x89\xcc\x117\xc5\xeeI}\xe4\xa2d\xf9)\ +\x8a\xf7\xb8}\xb7\xfbV;f\xa4\xfc\x9e\x03\xae\x7f\xc4\ +\xf5\x8f\x11^\xfb\x0e\xb8'B\x97\xc2\x95H+^\xc6\ +\xef*\x9b\xb4\x07p\x06\x0b\x9bp\xee>\x0d\xa5\xab\xbe\ +/\xadA \xd0\x92.a@\xa7k\x09\x8c\x90PM\ +\xfcx|\x80{\x80@\xc6kk9._\xcc\xfa2\ +J\xbf\x5c\xa8\x09\x9djR\xb5*\x84TN\xa0\x00\x08\ +n\xf71\x16\x98\x8c'H\x93\xd5\xab\xec\xcdU>\xe9\ +\xf9O\xcc5\xb1\x1cR\xc7/\xc6\xad[u\x92\x9e\xb7\ +R\x09\x98'\xf2Z\x8b\x84V\xc6H\xbd\x04\xd4\xf1\x14\ +\x10h\x8f_p\xe4:\x008q\xe5f\xae\xd2\x88\xbf\ +\x07\xfa\xd0M\xf7\x12!\x9b\xefP\xf9:\xf7\x9f\xae\xb9\ +\x02\xbe\xcb\xb5\xd7\x07P:\xb2\xc6kq\xcf\xd8\xe9X\ +^\x08\xaa\xc6\xd2\xedo\xc4\xe2U]$\xc5\xab\xd63\ +\xa1\x01\x00$\xa1t\x89f\xb9R@c*\xa22i\ +oc\x84\x88\xdf\xb9\x80\xc0\x0b\xc9\xec\x05\xb5\xfd\xebn\ +\x1f@tL{\xed\x0f\x08\x07\x90\xba\xe9CRB\xed\ +\xb8\x95\x05\x5c\xb5\x90v\xe1\xf6,\xe3\x01\x16\x88\xf7s\ +x\x00\xe2b\x13\x83Ej\x97\x8a\x8bJ\xd6\x1e\xfbJ\ +\xdc\x93D\xae\xaa\x06\xb4j\xe9S\x07I7\xad\xa0|\ +\x15\x9el\x9a\xce\x13\xd6Y~\x17\x9b\x1c\x5c/?\xc9\ +\x80\x80p\xe8V1\xe5\xb1\x04ZGX;\x18\xe86\ +\x0d4\x83\x84\x82\xc5\x0f\xe4\xf2\xc5\x11\xd2[t\xc6\xde\ +\xb4\x0b\x19\xe9\x88\x0e\x94\xd4!\x15\xc9\xe4\xdb\x17\x8b<\ +n\xaf>\xae^\x0a\xd6\xf4\xac@\xe0\x00P\xa0\x09\x9b\ +r@@.\xaf\x09\x1e\xbc\x84>\xab\xb3\x02\xb5\x93Y\ +1\xdc\xb5\xd9U%3\x19R\xae\xd2\xe5\xe1=\x00\xa0\ +\x95R\x15\xcdr=\x14\xa6\xeakw\xba\x98\x14\xa7\x16\ +=\x8co\x16F\xe5\xba\x84\xa9\xa9\x03\x00r-\xea\x08\ +\xb5\xae\xd8\x14\x8f\x1b\x18\xc4\xe3\x91\x96\x07\xc8\xc6\xd4\xed\ +D-\xf1\xd4\x11\xcd\xed\xf4\xe5\x99ur\x9bz9\xb9\ +\x1e\xcb:/\x01b\x1f\xd0nb\x15\xde\x22:\x9b9\ +U[\xdb\xb4\xddMee\x84\x22IL:n=\x8d\ +\xc1K\xc3\xda\xd3\x88Si\xb8\xd3t\xb9\xaa\x0e\xcd\x09\ +\x9c\xd7\x09v\xe0\xae\xdcz>(\xeb\x9a\x83,\xe2\xce\ +{\x97P\xc0\x8a\x85\x86\xd7-\xa2S*G\xb1\xf6a\ +b\xfd\xe0:\x96\xb9\xc2C\x81\xec\xaeyn\x0c\xe1\x7f\ +\xdd\xc1\xd2\xf2\x04\xbaa\xcd\xb3C\xa0\xb4S6\xe3|\ +cdj\xfd\x12H\xc5\x0b5\x01\xc2\x16\xeeCU/\ +\x1d*@Q\x97k\x06\xa1\xef\xc4\xd5$\x04\x07\xaeC\ +\x94T*}\x0e\x02m\xf1R\x99\xf6\x80\x8aKw\xf9\ +\xac\x16p\x08\x19\x8a\xb50o\x0d\xb2:h9kA\ +\xd9\x19\xe2\x1fz\x1e\x95\xbac}:\xac\xca;d\x92\ +\xcc\xa2\x11W\x89;M\x00\x08^\x93\x09\xad\xc9\x03\x02\ +\xf2\xec\xcb0\xeeK0\xef\xcf\x8a*\x91*B\x01\x00\ +\x10\x09S\xb9\x18|FUUR\x9evZ\xe9\xc0\x08\ +\xd7\xa9c\xe2\xba\xe5\x8c\xa0T5\x83\xd2\x22X\xe7\xc5\ +\x98\xea\x15\xa0*,\x88\x1f\xa0\x03\xd7\x81\x14e\xebH\ +\xdcO\x95\xc6\xe7\x00p\x9dJ\xf5w\x85b\xc2\x85k\ +\x83+\xaf\xd1\x83\x11\xe2\x91\xa3\x84\x9a\x5c\xc0\x93?L\ +X\x068\xb9\x8cI\x0e^2\xd4{\xc4g\x19\x17\x9d\ +\xc9\xac\xcd\xac\xdaf\xe6\xb6\x9a\xa9\xb2\x18\x81\xf3\xc5\xa8\ +\x98Q\xe5\xc6:}\xcb\xd7K\xac\x01Ejq\xee\xd5\ +\xfak\x80\xd4cGk\xf9S\xbc\xe2R\xdb\x89\xa9\x9d\ +\x93X\x1bD\xabw\x0e\x0b\x5cD\x09 \x10\x09\x92\xd6\ +\xb9J\x1f\x94\xee\x83\xe1\xeb$o\xf5\xf6\xc9\xd4i\xe2\ +\x02\xc0y#*\xb54Q\xeb\xd7\x1c\x5cx\x84\x1b\x0c\ +u\xf1\x80(:\xd0\xb9\xc7\xff\xeeq\x0f\xda\xe2\xa4}\ +~\xc7\xc4?\x9d%\x8c\xd2\x07\xb41B\xa2\xf7\x02\x02\ +\x22\x00\x0cy\xc7\xb1\xba#Y5p\x03\xda%#\xe0\ +lp\xbf\xf2\x22\xaa`&c\xc0\xf5\xea\xf4P\xef\x18\ +\x1a\xf1\x05\x06\x9fP\xe7\xea\x17\x90\x8b\xa5\xeb\x00^O\ +V\xa9V3\xda\x1b!\x17\xafn#\xb1\x95m\xa4\x83\ +\x00\xa1\xa2\xd1.W6\xdb\x95*ro\x1d\xe6H\x98\ +\xc9\x90\x05Cv\xa3S\xa7\x96?w\xdf\x0a\xe7\xd5Q\ +\xfc\x1e\x1eQ=\x97oXt\xf4\xd8\xc5xo?$\ +a\xe2\x9cS\xe9\x9cB\x15\xc3\xaa;\xbbS<\xca\x93\ +\xa8S\xa9vG\x07\xd5\xe6]\x95\xd2\xfc]\xa9\xb7\x0e\ +\xb5R\xbb|\xb5\x9f\xd1\x18\xaa\x8d\x9f\xba\xa8\x16\x8d_\ +\xb7\x12<\x8ez\x1b\x95N\xdf\xe3\xfd]+\x1c\xbb\x0d\ +\x18N\xf9\xdc\x0d<1c\xd3\xab\xede*\xeaQ\x99\ +\x9f\x8e\xe6el\x09\xa31*kV\xea\xe1\xaarU\ +\xd2\xcc\x8d\xb9\xa3c\xe4\x09\xda\x15\x83\xc9\xc3\x9b&\x18\ +\x10\xdch\x13\xb1\xb4\x99<\xbbu\x98\x81$\xaf\xee\x9a\ +\xe0\xb3\xd3<\x0cV>\x00\x10\x06\x96x\xaf\x86H\x9e\ +\xf5\xfbQ\xbc\x18\xff\x85\xf2\xd5\x09;\x97\x98\xa8\xf6\xf3\ +E\xe37I\x0dO\xadp\x14\x8b\x19a\xa0\x86\xb5\x15\ +\x8a\x9b\xd5\xee\x15D\xdb\xad\xb5\xe350\xa8\xbdo\xc8\ +\xc0M\x06\x0c\x00\xe0\x05\xdcY=\x88;\xbd\x03\x10\x84\ +!L9\x13g\x10\xa8\xdb\xe6\xba|\xf2\xbf:lZ\ +s\x1b^\xd9\x9a\x0aXI\xc1D\x16\xa5p\x80\xae\xfe\ +\xbb\xea\xb5\xab\x86Jj\xb1\xa2\xee\x99\xae\x83\xa6\xf6\x22\ +\x0c\x12R\x00\x87\xfa\xefk\xe1'\x1e\xb2\x1aG\x86\x10\ +[\xd3mWj\x01\x83\xea\x18\xe0\x13I\xe2\x18\xb8v\ +\x1d\x0a\xa1\x89\xb1<,\xbfp\xfe\x91\x15-<6\x1d\ +B\xe1N\x10\xd1\x112\x93\xb7\x09\x07\xb7\x00\x82<\x02\ +\xd6\x89r%j?\x17Q\x13j5\xd9\xd69\xc8\x88\ +2\x00q\x80lm\xd9\xd3\x1e\x09\x09@Pc\xe8\x08\ +zR\x8f\xa6<~\xa7\x8d$\xc5R\xfa\xccm+\x03\ +l:W@M\xa1+\xe6\x9fX\xf9\xecc+\x99z\ +\x08\x08\xee\x02\x823@\xc0w3vY\xbd\x8c\xab\x04\ +@\x04$\x8ce\x8cw\x22\xb7\x10v\xe8P\xa6\x83\xa3\ +Ta\xf2\xe9\x94*\x88\x8a\xe6\xa3\xbd\x93\xb8\xb5l\xdc\ +\xc3\xcf\xbd\xfc\xbe\x1f\x0b\x1b\xc2\xd2\xc7`\xe5\xd3\xb8\xb9\ +\x05\x08\xcf2\xb2j9\xea\xf0\xd5\xbf\x86\xfbQ\xbf@\ +\xaf/\xf0?\x9aC\x1fZ\xd1\xa4\xd7\xc2\xb4\x04\xc4\xaa\ +\x1d[\xf1\x14\x037\xa5\x03\x1en;+\x0aO\xdd\xb2\ +l\x1e.\x8bA\xcb\x1c9\xc5\x1d\xf2\xcaCd\xe2\x09\ +2\x15\x0apm\x17'ui)Z\xd3\xd1yj\xec\ +\xc8\xa0\xe71\x08\xb93\x0f]\xf1\x84\xbc\xc5\xc5\x86M\ +\x9f\xb6\x83\xf3\x5c\xae\xec\x8d\xc1\x97B\x8af\xefZ\x85\ +\xda\xddk\xb3\xc9\xe6\x0b\xe4\xb9U\xaf>\xb2b\xd2W\ +u\x0cQ\x86\x91\xd2\x02I&\xafO\x80G\xc4\x93-\ +\xc4\xc3%\x12E\x1c\x95\xc6*\xad\xed\xdfF\x89\xc7\xa6\ +C'\x0aP\xb8N\x11)\x9c{\xcc{dF\x1d\xd8\ +\x1f\xf2\x5c\xaa\xa9\xb8OHP\xab\xf7\xdb\x96\x0fX/\ +\xc4;\xd3@\xbb\x98yn\xed\x88\x02\xcc\xd9*\x97\x07\ +\x00\xda\xb7\xa9\x06\x95\xaa\xa0vg \xc0/\x0a&\xd4\ +\xea\x15K\x9f{`\xe5\x8b\x8f\xadR\xa7\x80.\xbf@\ +^Z\xc5\xd2K+_xae\xb3O\x19S\xeec\ +\xec\x1e\x06w\x8a\xe1\xe1!\xb1\xfa`7a\xa5\x1bn\ +\x81\xf8{T\xe7\x09\x004\x90\x22RZ\xfdS~\x1f\ +\xc2\x15\x09\x0c\xea\xb2\xa9-[\x9a\xc1R\x93\xc2$\xe5\ +\xeb\xaef\xae\x83\x5c\xb9\x9d\xf4\xa2\x03 t; \xf8\ +\xf1\x06\xa1\xbe\x19\x14\xbf\x84%\xafa\xd1\x9b o\x8b\ +\x14\x90\xf4\x06r\xa3nY9XU.,W\x16\xa6\ +\x83\x0c\x8ag\x00\x00\xe8U?\xfcb\x1d\xab\xa6n\xe3\ +3X\xc9\xcc\x0d\x0bOs\xc3:u\x03\xf7\xa9\xbdl\ +\xda\x0b\x1f\x1c\xc2\x03h\x7f\x9c<\x80\x00\xa0\x8c\x00\xe5\ +f\xb92\xa9\x9b\x96;\x8b\xcbe@\x0a\x96\x9eY\xc1\ +\xe23\xd79C\xcd%\xb4\x87/\x88K\xd5.\x1e\xb9\ +V\xb5\x7f-\xd0a\x17\x0b\x0fI]\x9fY\xc3\xcek\ +k>xk\xadGo\xad\xed\xf0\x8d5\xed\xbc\xb0\xaa\ +\x15\x14\x897P\xba\x9bNV\xa4\ +m\xce\x08a\x19\xae%\xaa\xe2O\xbfv\xbb\x8a=.\ +\x02\x00\xe5\x90J\xd54\xd7\xdc\x86\xb4\xb8\x19\xa9DU\ +\xd6\xd6v\x92\x86\xf4C\xf6&@\xda\x02\x8a_\x07y\ +;V8~\xe0f\x00\xdd!\xd1\xb8\xac\x5cP\xac\xa3\ +R\xddAH\x13:\x89\x5c\xfb\xe1\xce\xf7\xc4\x8d\xab'\ +\xfe1\xec\xf9\xc8r&\x0f-DV\x91\xcdk\xd68\ +n\x9e\xbfg9\xb7\x88G\xd0\x86L\xed\x93\xd3\x8e\x22\ +Gn4kIlU\xc5\x0c^#w\x1e\x0b[\xc4\ +\xe2\x16\x1fY.\xb18\x82\xeb\x0dc1!\x06P\xaf\ +Q,G'~\x94-\xe9\x00\xc5gV\xbf\xf3\xd2\x9a\ +\x0e^Y\xf3\xe1\x0bk9xf\xad\xfbO\xadq\xfb\ +\xa1U\xad\xdeu\xcd\xaa\xc2X\xb6\xe6ER\xb5\xe1S\ +\x9ba\xce\xa7lu4\xad\xb8F\x18\xe5\xe8\x940\x1d\ +GS\xbe\xf4\x1cy\xe9\x9a@\xe8$\xb2\x02\x94^0\ +\xf3\x1c\xe5\xbf\x04\x1c:\x9bY\x0az\xcb\xdf_[\xc9\ +\xfcs\x00\x80\x85\x12\xab\xf3\x08\x83\xaa\xebsG\xd7\xab\ +\xb7\x80\x13\x85d\xb5\xcb\xd1\xf68\x8cB\xde\x11\xefR\ +\x04\xc0t\xc6\x91\x0e\xbf\xaa\xdax\xe7\xce\xfe\xad\xba\xaa\ +C?\xdf[\xf1\xc2\x1b\xae\xf7\x02O\xf3\x94q\xe6\xf9\ +\x87\xefat<\x03\x00 \xce\x03\x94l\ +\xe2\xa4\xe2\xa3\xeeS\xe9\xa0#\x8bn\x03\xa4\xaab \ +T\x9aq\xd4v2\xbcK\xee\xac\xca\xa7p\xab\xa4c\ +9j\x99\x86\xa7\xc9\x9d#\xcc\x00\x8e\xb2\xd5'N\xf9\ +\x9a\xb4\xaa\xddzl\xb5\x9b\xf7\xb0\xa4\x9bX\xfd\xb1U\ +.\x1d\x10C\xb5\x01\x05F=\xb9\x8f1\xa8/\x8fJ\ +\xe0\xe1\x10-\x9a\x90R*\x07\x9bW\xd5\x93R>\x9e\ +A\x8d\xa7u\x12h\xe9\x82w\x80\x94\xe7\x01\x1e\xe3\xcd\ +$z\xff\x82\xdf\xbd\xb6\xd2\xa5\xb7\x00\x0f\x00,\x0a\x10\ +x\x86\xc9{\xae\xd1\x96\x0e\xa5V1M@E\xb6\xee\ +\x15\xe6\xaf}\x87\xd2\x09\xc0\xd0\xa4P\xe4\xbc\x99C\x01\ +\xf1\xbd\x18\xa0\x95\xb9\x13\xd0\xdeX\x85N>[z\x83\ +W\xd1\xd6\xf8\xc7\x84\xb6\xfbx\xad;\x90MB(\xb1\ +>K\xe5\xe3\x9d<\x83\xf6sh\x17\x97\xdbQ\x04\x98\ +I\x11\xd3\xbat\x00\xe7\x01\x00\xe0B\xae\xef\x8c.\x86\ +\x1b\x0a\x83H\x81@\xbc@\xb5\xe6\xda\xc5\x9b\xdc0\xed\ +\xe6\x98]\x0b3W\x9fwQ\x97\xd7m\xe9\x90\xa3@\ +\xd3\xb0\x85;\xa7\x01\xc0\xb2\x15\xa1\xb8\xb2\xe9k\x0c\xe4\ +\x1db\x94\xac\xed\x89\x95-?u'V\x97\xea\xe0\x02\ +\x91#,Q\x1eA-\xd4t\xea\xb8;\x1f\xd7\xa5g\ +d\x0e\xca \xcek\xd8u\xe4yP=\x0a`\xbaY\ +c\x0c\xc8(\xf7\x0a!\xd2\xe1\xd1\xda\xf6\xac\xc9!\xb7\ +5J\x0bX\xfa.u\xdav+\x95\x90,\xa5`p\ +\x8d(\xae2\x0c\x85R5\xa1\xd0\xb9Cj\x1b\ +\x97\x87\xcbw\xad\xe3\xe0Z\xae=\x8dKU\xb5\xd3G\ +\x82\x95\xe2\xcd\x94\xa3\x0b\x04\x1e\x000Du\xf4\xc0[\ +\xe4@&s\x09\x1b*\x07\xd7!\x97y\xaa\x10V%\ +\x962\x22\xf5\x01\xd0V1\xcd\xa1\xb89\x95yK\xad\ +\x83\xabhR\xadn\x06\x99&\x8c\xc3a4M, \ +\xb4j\xe5\x11\x92\x0f\x08b\x5c'\x09\x11A\xf2\xea\x10\ +d\xcbm\xda\x14\x13%\xae\x8a\x08j\xe3\x87z\xf5i\ ++\xb8k\xe6\xd0A\xbe\xdf\xb9\xe2\xce\x08\x08\x93\x02E\ +\xba\x16\x9d\x84\x11\x9d|\x15\xee[\xc7\xb5o\xc3\xb2\x19\ +d\xc8\x5c\xc1j>Hlje\xa3%\x95TY|A\xa9\xc5\ +\xe7\x17[B\x01R\x5cn\x89e\xd5\x96\xc8\xdf\x12\xab\ +[-Q\xdd=I\x01\x93j\xb5OP\x99\x10\xa2\xf7\ +\xbc\xa64\xa8\xc8d\x84\xfb?\xdf2\xa6\xc5.\xadI\ +tk\xc6\x14\x0f\x86g\xd2Q.ZA\x0dq\x7fj\ +4\xa1\xd2y-d)\xbcj\xc3\xad\xb7\x90\xc4\x18k\ +\xcb\x9dVf\x05\x02\xc2\x81\x1aQ\xa8\xa5K\x04\x008\ +\xe5\xe3\x01r\x05\x22\xf4\xa3\x83\x8f\xa2\x0b\x067-\ +_\xfdwQ|\x18ku\xcd\x91y\xaf\xa9\xe0\xf0\xf0\ +&\x80\xda\xc6\x02\xf8\xec\xcc\x11D\xe8&\xd6\x7f\x9b\x94\ +\xe5\x1e\xf1\x96\xb89{\x8a%\x92\xe3\xe2Ju\xbe\xbe\ +\xeb\xcb\x8b\x87\xd1Z\xbf@\x90\x5c\xafU;\xcd?\x8c\ +a\x89X_\xdb\x14\xe4e\xc1\xedr\xf5i/\xe3\xa0\ +v\x13\xc3\x96I\x91\xdc\xe1N\xb8\xd5\x90\xd8\xbe\xa6\x87\ +\xdd\x926\xf7\xcdgu \xa3\xdfmPQ\x0b\xf7q\ +\xcb\x90\xd2\xaa\xda-Y;\x84\x0a\xab,!\xbf\xdc\xe2\ +sK-.Z\x8c\x14Z\x5c.\x92Wdq\x05%\ +\x16W\x5c\x01\xe7Q\xa1i\xbd%\x947\x10\xfe\x1a\xbd\ +W~\x8e\xd7\x1e\x832\xfd\xdc\x02X:\xe0C\xbdn\ +\xc7\xaf\xb74-O\xe1M\xf5\xfa\xdaum\xad\x05\xac\ +\x98\x16\x82\xdc\x01\xd0\x8d*\x00\xd1\xd4\xf7$\xafX\xa8\ +\x96\xbdQL\x1a\x8a\xd1\xbeKu\xfa\x129\xd7\xbc\x88\ +vj\xe9@/w\xa8\x17\xfcI\xe72)t\xaac\ +{J\xed\x90%\xb9\x92y-\xa6IT$\xd3\xebB\ +u|\xa5*\x97\x09\xdb*\xa7\x03\x10\xdae\xa4\xc5 \ +\xaf\x09\xa5\x1a_\xceXLB\xc5\xb0[7N\xe5\x17\ +>\xd0\xa4\xae\x96!\x14\xad\x16\xe9\x9ayr\x07@!\ +\xda\xdd\xab\x83\x08\x0b\xc6\xbc\x83\x9dJ'O\xact\x02\ +W?\xbeg\x85XWTs\xff\xe4\xfdA7\xd0\xe7\ +3\x81\x9d3\xc4\xb7\x19B\xc9,\x80X\x02\xb9W\x89\ +Y\xbb\xa4~'V\x86g(\x83i\x17\xb9UC\xb2\ +\x0fMBqm-\x93\xaa\x10\xc4k\xcc\xac\x92p-\ +\x0fk\xbd\xbb\x97\x9b\x1e\x00\xbd\xdck\xdb,\xaer\x85\ +\xd0\xb0\x09)\xc4\xdd\xaa\xe5\x9c\x96R\xc92\x94;\x8b\ +\xbf\x04\x14[Ic\xbdC\xa5q\x89\x0cV\xaaV\xce\ +\xb4\xd1\x93L&\xa9X\xca\xaf\xb1$IA\x8d%\xe6\ +W\x03\x84J\x80Pf\xb19Ev%\xa7\xd0\xae\x00\ +\x86+\xb9\xbc\xcf+\xb1X{\x98\xd16\x8a\x82\xa7\ +\xf1 \xcb\x90\xaem\xc8\x17\x00\x02\x00e\x0b\xa4Q\xa4\ +o:\xc2E\x93\x1d\x02\x9b_[\xce\xe5\x165Pd\ +\x1f\x89B3)\xa86bh>B\xed\x5c\xd4\xcc)\ +\x83A\xd0n\xd7 \x9e(8\x827\x80Sh>=\ +\x80'Sv\xa0r\xb74H\x90\x0aJRA{*\ +\x03\x9e\xc2\xa0$\x97\x01\x80\x92FK.i\xb0\x94\xd2\ +&\xa4\x05i\x06\x14XsA\xad\xc5\xe7U\xe2\x05P\ +4^!\x16\xafp%\x0a\x08\x04\x86h\xc1'\x89u\ +\xaf\x85\xee\xef\xb1\xb9\xe5x\x8cZK(l\xc1\xab\xf4\ +\xe0]\x08\x09\x18\x94\xbf\x11\x0e\xc3sd4\xe2\xb5\xea\ +\x15\x93\xb1tU\xe5hM^\x16\xe9J\xc3\xb4\x0dL\ +[\xc1\xcf\x97\xc4U\xc3W\xa6\x9e\xc2C\xeeh95\ +\xad\x8e`\x88\x1a\xff\x0a\xc6\xa9z\xe9\xaeU\xcci\x16\ +\x900;L(\xeb\xd6fU\xc6\xb7E}\x8d\xf0\x96\ +\xcd\x00\x88\xb1O\x82K\xa9c\xba\xf6\x18\xa8\xf8\xf5\x0a\ +\xdf\x7f\xa9\xb4\xd3.\x93\xc5].iCZ\xed\x0a\x02\ +\x00T\xb9\xea\xed\x91SM]:V\xa2\x93?t~\ +]\x1e\xa9\x95:h\x97J\xe9\xb3w\xacR\x87K\xe9\ +\x00\xa2\x19\x08\xde\xd45w\x14\x89\x94\x9f\xab=\xfc}\ +\x9a\xf5\xf3\x8a=\xdc\x9a\x7f\x83J\xadT\xac\xd0\x8b\xd2\ +\xbcx\x99\x0e\x18\x02\xedS\xee\xb3\xf9c{\x84\x80\x9b\ +\x84\x83\x07V\xbd\xf6\x14rH\x96@\x9e+\x82\xa3\xb3\ +\xfeu0\xb5\x80\x90\xa1\xa6\x14\xae\xc7\xae\xca\xb5T\xb1\ +\xd3\xef\x81@\xe1AS\xb1\xf24*\x97\xee\xc7\xdd\x13\ +\xf3\xfd\xc4~\xd7-K+\x88\xdaI\xdbA\xcc%\xef\ +\xcd\x04\x0c\x01\xbe+\x83\xefJ\xab\x06\xecd0i\xd5\ +d15\xdcWM\x1f\xef\xb9G5\x96\xd6F\xcd\xa2\ +\x06Wf\x1e\x87W\x88\x05\x0c\xb1\x02C\x14/\x80g\ +\x88uJ\xf7\x00\x10\x0b0\xe2\xf8}\x5cn\x05\xde\xa3\ +\xce\x92\x8a\xda-\xad\x82g\x84|e\xb7@\x0c!Z\ +\xd90\xee\xcc\x16\xc2\x1b \xf8\xdf\x01\xa0\xfa\xc0\x81s\ ++\xedv\x15\xc5\xaa\xdeM(iw\xc5\x9c\x89\x00!\ +\xa5z\xc8|\x8d\xd3\x10\xd55\xbc\xec\x915\x10:\xbb\ +w\x9eX\xcf\xeeC\xeb\xdc>\xb3\xe6u\xa5\xdb\xea\x18\ +\xbeLX\x80\x97\x0dh\xe7\xb5j\x12\x08#dV\xc9\ +\xcdZ\xfe\x1d\x03\x04C\xe7 \xe8B:\xcc\xdb\x19\xd4\ +\xea\xd2\xf9\x18\xb7\xf9\x92|>^\xdb\xa4\x19\x10\x15K\ +\x04\x19\xd4\x1c\xe2\xba\x8eg\xd3IS\x95\xa4PU0\ +\xfaJ\xac\xb5\x1c\xab\xd5!D:[ \x0fr%\xcb\ +\x0f\xf7.[V\x17\x04\x88L\xc0\xafE#\xe2\x9f\x03\ +@\xadJ\xbb@\xb3\xb6Y\x03\x82\x94\xba>R\x93Q\ +\xd39?y#[^{\xfa\xf5'\xd6\xb0\xf3\xc6\x1a\ +w?X\xdd\xd6\xe7\x10\xc5\xb7p\x85\xe7\xb8\xba\x07\xb0\ +j\x80\xa0\xe2\x0f\x91#\xb9PGt\x86\x01\xc2 !\ +\xc1+\xb4LV}\x01\xb16\xad\x03\x97H\x5c\xd4!\ +\xd8j\x8f\x96\x05;\x0e\x0f\xdc\xc4Jn\x03\xd2;V\ +0|\xcb\xf2\x06\x8f,\xa7\x17\xa5t\x12\xea \x97A\ +\xee5\x13\xf2\xa6\x8c&C\xc5\x15\xd5\x84\x1b)B;\ +u\x8b\x18\x97\xc2&\x80\x00\x18\xf2\xb5\xf7\x007\x9fW\ +\x81\x94#\x00\x02\xf7\xaf\xd78~\x8e\x07(\x89|6\ +\x05\xeb\xf7\xd5L:\xe5G\xbb\xf7-\x8f{\x88\xf6\x1e\ +Y\x88T5\xa0\xba\x86\x06u\x0f\x13+?\xaft\x86\ +\xf0z\x1bM\x07x&B\x1c\x9e \x09KM*\xeb\ +r\xaf)\x80=\xbd~\x1c\xf0.\xc0\xb3v\xdc\x86\x9a\ +\xe1\x83\xe76v\xf2\xdcF\xaf=\xb1\xbe\x83{V\xb7\ +\xa2\xb5\x8c=\xb2\x02B\xf4\xd8!\x19\x06\xe4PF\x00\ +g\x13qW\xf6\xa6\x8d\xad:\x87\xc0\xab\x19$\x9c\x02\ +~\x85\x0b5\xc1\x88QW,m\xceL\xac\xed\x86\x88\ +\xf4\xe3\xaa\xc7,\x9b\xfcWn\xbaD\xf9\xfc\xc2m\xab\ +\x82\xb0U.\xea\x0c\xbaS\x5c\xb7N\x12\xd5qk\xf0\ +\x04\xed\xf7W\xf5M;\xfcA\xe4\xaaY5\xec\xaa\xb4\ +Q\x95\x0d,T\xf5~\xb5<\x9c\x06V\x16\x867\xc8\ +\xc0\x0bduN\x03\x80\xabV\xbep\xc3\x1a\xb6\x9eZ\ +\xdb\xd1\x07\xeb\xbc\xfe\xd1:\xae\xfd`-G\xdf\x03\x88\ +o\xacj\xeds\xd7f\xbe`\x82J\xd6\xb0\x88\x87\xd9\xb5\ +\xda\xb5\xdb\xd6\xb2\xff\xc2\xba\xae\x7f\xb0\xbe\xb3\x8f\xd6\x0f\ +\x08\xfa\xef\xfc\xc1\xfan\xfff=\xb7~\xb3\xae\x93?\ +Z\xfb\xfeO\xd6\xbc\xf1\xad\xd5-\xbf\xb7\xca\xd9\x17\x90\ +\xcf\xc7\x84\xa7\x07V4\x86\xf0Z2\xf1\xc8\x01\xa4b\ +^\xd6\xfe\xb9\xd5\x01\x9a\xc6\x9d\xef\xacy\xffGk=\ +\xfc\x09\xf9\xc1\x9a\xf6\x00\xc0\xc6[w\x08s\xa1\xe6\x1f\ +H=\xb3T>&\xbe\x22O\x85B\xbd\x9d3(\xdf\ +\xf1\x0c\xd5\xdb\xc1\x17\xc8\x1etB\x98J\xadt\xd6\x8e\ +6\x8d*\xadS1\xaa\x8f1\xc8P\xaa\xa7\xcf\x10\xab\ +\xfdp\x8c`\xeb*\x00%+B\xe1\xda\x1f\x99\xeb\x1a\ +>\xde \x8b\x22\xa7w\xfd\x15\x8e\xed\xa2\xd9\xa3\xa6\x94\ +?e*X\xaa\xcb\x14T.\xcew\xb9\xfd\xfb\x18W\ +\xb2t\x03\xe1\xd5\x81\x9b\x85p\xad\xda\xa9\x03\xabW\xaf\ +\xa4\xd9\x13\xab\xc5C\x17\xaa\xe1v7Y\x01\x86\xa0z\ +\x0au!Ok^\xe7;VP8\xd6\xaf\xcc\x03/\ +)q\xe1\xe7\x5cRI=\x95\xa1\xc4\xa4\xaa\x22F-\ +\xe2:\x17]\xd7\xa8\x001=kx\xcb\xc2\xa3\xbb\x16\ +\x81\xe1\xabS\x97v\x05\x05\x07A.nH\x07/\xa7\ +\x92\xdb\xba#Z@S\x22\xb1\xcc\xabF%>\xcb\xcd\ +\x90\xc7'\xe2\xd6<\xe1\xbd\x03\x81j\xfd4\xa8\xbd\xa0\ +\xbb\x97A\x1f\xe4\xa6\xf1\x02#+\x10\xc1\x03,\xf5\x0c\ ++}l\xedGo\xac\xfb\xc6\x97\xd6{\xeb;\xeb?\ +\xfb\xd9\x06\xce\xfeh\xfd\xa7\xbfY\xdf\x8d?Z\xf7\xf1\ +/\xd6\xb1\xf7\x835c\xd1\x0dWQ\xa6\x9a?\x22\x8d\ +W\xbf\xb2\xf6\x9do\xad\xfb\xe0{\xeb=\x06<|\xb6\ +\xff\xd6\x9f\xac\xeb\xe6o\xd6q\xfdWk;A\xf9\xfb\ +j\x12\xf9\xc6*Vt\x82\xc9\xa9\xe9\xa8\xfa`\xd72\ +!\x0b\xf0_X\xbeS\xbe\xe2#\xf7\x09hS\x9a\x08\ +\x0b\xad\xa4b<\xafkx\xa1B\x0e\xa5\xc5*\xcc \ +\xdb\x08A\x90\xb3U\xef7\xa8\xe2\x8e\xf3\xbe\x08Xv\ +\xb0\x93\xd4\x14\x00\x84\xe0!\x11\x94\x9d3\x08\xd8T\x98\ +1z\xc7r\x08K\x91\xb1;\x16\xc6+\xa8\x8eA \ +Pk\xf7tM\xcfb\xa9\xea\xc4\xe6\xa4\x19\x01tI\ +\x00,\x19IQA\x0e\xa9of\xe7\xbcE\xdc\xe4\xdb\ +\xb2\x855\x19\xd7\xb9j\x01\x00\x97\x8e\xb2\xd3\x90\xd4\x06\ +\x94^\xb7\x88\xc1\xcd\x91\xefk\xfa~\xd2\xcb\xfb\xc5\x9d\ +\x5c\xea\xa9\x13O\x14:\xbd\x99A\x81-&\xa5m\x89\ +\x0bx\xedB\x5c-`\xf7\x1aV\xae\xa5N\xed\x02\xe2\ +\xe1\x10m\x11\xd3yv\x17\xe7\xe1k\x8d<\xd9\xcd`\ +q\x83nzQ\x02\xc1Qy\xb4\xfeF\x8cs\xafz\ +\x10\x80\xa2R+o\x070\xee\xb3\x0e\x06\xde\xd8\x8fE\ +\x0d\x935La\x1d\xcbX\xe46\xe9\xe0\x09@\xb8\x03\ +\x10\xe0\x04\x87o\xad\xfb\xdaW\xd6w\xeb{\x1b8\x05\ +\x08\xa7\xbf\xa2\xd4_\xad\xe7\xfa/x\x84\x9f\xad\x030\ +\xb4\x0b\x10'x\x8a\x9b\x7f\xb2\xa9\xfb\x7f\xb3\x85'\xff\ +l\x8b\xcf\xfe\xd5\x16\x9f\xff\x9bM?\xfd;\xe1\xe47\ +k\xbd\xf6\x9d\xd5\xef\xe15 \x9aE\xf3g\x96\x0bw\ +\xc9&\xbb\xd1Ii\x8a\xad\xae\x22Y\xbbq%\x9a<\ +\x11\xb1\xe4\xf7\xda\x94\xa9\xbe\x89j\x9f\xa7\x1a\xbc \xde\ +Bg\x1ahuPk\x0c\xd1\xa9\x9bn\x8d!\xaa\xb6\ +\xf7S\xeao\x8cu\xab\xa2\xc7\xb9\xf9}g\x8dY\xbc\ +\x86 \x81r\xcb:\x926wR\xd3\xb8O\xdc\x8e\xea\ +\xc8\xf8]>\x7f\x1d\xb2\xba\x8b']uqZ3t\ +*\xd3v\xfb\x0b\xb4\xf9T\x00he\xfcZ\xb1`\xb5\ +\xb1\xc5S\x09\x94\xee\xe0,\x8c\xccY0\xd6\x9dJz\ +\x99R\xc7\xe7Pz2\xdc(I\x8a\xaf\x82\xf4\x91\x8a\ +\xbacgH'\xf5\x9a\xa0\x0d&\xae*X\x15\xc1\x18\ +'\xd7\xd2Q;\xaeGPJ\x9b\x0a\x05\xbd\xe9^)\ +Xu\xed\xae\xb8R\xacZ3N(^u\x82^w\ +\xd0\x7f\x88\x88W\x1a\x0f\xe0\x1aE\xa9v\xa0\x83\xfc\xfd\ +BT\x89\xa3\xbf\xe9\xb3\x8e\xf0\x88\xacM\xe0\x9a\xb45\ +\x8b\x1c\xb7i\x10\xf79B\x9a6I\xca\x07\xb2\xe1\x1d\ +\xf9\x13\xa4\x86:?x\xed\x1e1\xfb\x99\xb5\x1d\xbc\xb1\ +\xce\xe3\x0f\xd6}\xf2\x15\x80\xf8\xda:\xaf}c\xed\xd7\ +>Z\xfb\x8d\x1f\xad\xe3\xd6/\xd6M\x98\x18~\xf0W\ +[|\xf5\xaf\xb6\xfe\xee?\xdb\xda\xdb\x7f\xb7\xe5\xd7\xff\ +bSO\xfel\x1d7\xbe\xb5\x9a\x9dWVJ\xea\x94\ +\x07w\xc9\x06\xd0\xfe\x0eU\xc82\x08Xy\x1c9q\ +,\xe9\x96\xfa\xf1hBD{\x03\xe5\xbdR\xb4\x8b\x07\ +\x17\xaf2/uP\xd3\xd15\x1e\x00\xf0\x86\x22\x8f\x93\ +\x84\xc4\x19\xb2\x0b\xb2\xa1\x5c\x1dqCZ\x1c\x99\xba\x0d\ +\x08\xce\xe0N\xb7\xc8>\xae[\xb0\x070\xf4\x1c\xb9x\ +,B\xaac\xdb\xd5\xb5m2^\xe9g\x17c\xdd\x03\ +\xdc{\x00@\x17\xe3\x8fB\x9bb\x83v\x8d|\x02\x00\ +\x17S\xbe\xaa\x1e\xb9\xaa\x0f\xcc`0\xd4G\xc8u\x02\ +\xedSQ\xc4\x0enOK\xaf\xca\x10\xd4N]\xc0\xc0\ ++h\xb5K\xcaw^\x83\xc1\x13\xdb\x96\xf2\xbb\x17x\ +\xd5\xba\xff4\xa9\x0d\xa9\xa3\xbaV5\xc0\x0b\xeaQ\x84\ +\x8a,\x95B*%#3\xd1*\xa0\x8aJ3;f\ +\x89\xa9\xb0k\xfe7S\xc5\xa6\xfd\xa4n\xc3X\xe3\xf8\ +\xb6\x85\xa7\xf7\xac`\xf1\xd0\xaa\xd6\xafY\xdd\xe6u\xab\ +Y?\x86\xe5\xef[\xc1\xb4\xb6\xb5\xcb\x9a\xb1\x8c&\xa5\ +\xa2\xc4\xf6j\xe2=\xd6\xefu\xe1\x82\xf0a\xf9\xca\x8b\ +\x05rw@\x04\x0aw\xc0\x05\xe0\xda\x8e\xe5\x8aI\x09\ +\x8d\xb2Pg\x08\x840-\xee\xb8Jg\x81\x14@\x07\ +\xe1\x07\xd9:\x17\x99\xdc[\x07P\x14\x12\xdfK\x94\xa5\ +\xa8\x00D\x95?\x0b:\x1f\xe9\x85\x15\xce=s\x05\x22\ +\x02IX-\xe6U\xf0\x01\x00\xdc\xa9 (\xdc)\x05\ +\xde\xa0n\x9f*\xd4Hi\xdf@'KX?\x06\x89\ +\xeb\x96E\x0b\x00J\xdb\xdc\xa1\x8f.\x04\x13\xb6\xe55\ +\x94\xde\xc9C\xe0\xee\x93D`\x11\xb5\xd4Q\xdf'\x1d\ +w'\xb2\x97\xaa\xddUR\xbe\xeb1\xa8]U\x07x\ +l\xd5J\xee[\x8c\xeb\x80\x85\xeb\xf7\x94\xafmCr\ +7r\x19X\x06\xee\xc6-\xa2\xc8B $j)\xef\ +C\x99Z\xea\x0cB\x14\xb3q\x89\xe1!-\xb3\xc2z\ +y\xd56(u\x08\xd5\xf1\xe8\xae[6\xdeCLZ\ +e\xe5\xea\xc9\xab\x1e\x81\xb2~\x9d\xdf\x97\x06\x17\xd0Y\ +~\xaeEku\x17\x0f\xaa\x06M\xb0\xf0Zn^=\ +t\x9dh\xb2BG\xa4\xea\xd8\xb7\x01\xdc\x9dz\xf9\x03\ +\x12\xbcEr\x1b\xf7\xd6\xc9\xf7\xf5N[\xe6\xc0\x0c^\ +\x88\x10\xd2?\xc5\x83\xa9t\x9d\xfb\xc7\xb3$\xaa\x13\x99\ +k\xda\xc8\xf7j\xd7\xef'\xa6\xaf)j\xad2\xea\xbe\ +T\xc6\xae\x9dP\xdc\xb7\xac\x1f\xc5\x8b\x95{\x87>\xa8\ +N\x81\x01\xe7s\xe9J\xf5 \x87\xfefR2\xb5\x8b\ +%{\xd2\xb2x6\x80\xd7A\x91\xf9\xe3\xb7\xcd; \ +\xf3\xa5\x95/\xbf\xb5\xf2\x95wV\xb6\xf2\x16\x0e\xf2\xda\ +\x8a\x00A\xc1\x9c\x08\xe0}\xf8\x802\x80\x13\xc0s\xc0\ +8j^@\xa2\x94\xd0\xab\xdd\xd7^\x08\xb5\x81Mj\ +\x5c\xf4t\x22\x97\x8e25Q$\xf2\x97\x06/\x10\xf7\ +J\x15y\xe4\x1e]6\x86\xbe\xdc\x16t\x94\xef:\x97\ +\xf1|\xee\xffd\xc8\x18\xb6\xdc\xbeZ\x00\xf8;\xb6I\ +\x155=\xae\x1215\x98\xde\xb0\x18\xa5\x09Z&\xd4\ +\xd6\xe6x\x5c\x88\xa6\x0c5\xc5\xaaT\xc8\xc5\x1c5+\ +r\x1b+\x18\x04\x18\xa9\x5c\xb4v\xb9\x04q\x85\xda\x1d\ +\xa4I!m|\x10\xc9\xca\xd6\xb61\x11'H\xa3\xda\ +\xc4kyW[\x97t\xf8B\x9av\xe5J\x9aG\xdd\ +t\xb3\x94\x9a\xa4\xd5+\xd5\x18~\x9a\x8e\xee\xc02\xbb\ +\x11Y(\xaf\xea\xdf\xc7\xdf]3\xc72\xbd\x22\xe7\xfb\ +\xe0\xdd\xc9\xa0j1W\xc7w\xd4w\x02bO\x12\xd4\ +\xd0AM'\xf9\x9b>\x13\xcf5\xbc\xef\x04`\x88V\ +\x175g\xe1:\x81\xe9\x189\xac_\x80\xfd\x04Z,\ +^g\xf4\xa7\xe36\xd3\xc9\x93\xd3\xf1\x84\xe9\xa4\xb4\xda\ +\xd1\xe4\x94\x0f#\xcf\x84(\xea\xf8{\x9d\x0f\xac\xd3\xd5\ +sGN\xacH\x85\xa6*\xcb^yi\x95:\x80z\ +\xfd\x9d\x13\x95n\x95\xae\xc8\x13\xe0\x05\xa6\x1f\xc0\x13N\ +\xdd\x92\xb5\xdb\xd6&\x00\xb85\x0b<\x806\xc2\xb4\x12\ +\x06\x9aW\xf1\x84R>\xee_\x06y\x0e\x00q\x00\xdd\ +\xb3\xbc\x91k\xd3\x0f!O\xe15\x99\x9f\x93\xc8\x0c4\ +\xe9\x96HJ\x9b\xe0\x84\xf7\x18\xb0\xba\xbd\xab\xd6@\x8d\ +\xbd\xb5\xe4\x9f\xd1J\x18\xd7>K\x1dx\xd9@\xf8 \ +\x83\x88\x89\xab\x80\x11K\xb4*\x05\x82\xb4@\xa1\xedQ\ +\x1e\x08.\x88\x87@ \xf4\xc9z\xa7\x19\xa8Yn\x5c\ +\xb1z\x09\xd6\xbb\x86\xe5\x0b\x04[\x16\xea\xc7\x0b\xa8\xe6\ +^!\x02\xf7\xefN\xf2f\xd0\xd4^US\xc4\xb2z\ +7[\xa85\x02\x94\xac\xae\x1eq%\xcd\x16[\xdc\x08\ +1k\x22.\xab\xdd\x09\xe4\xacL[\xb2\xb4CW\xfb\ +\xf4\x1b\xbd\x8e\x9aH\x82V\xeb\xf8\xbc\xa6e\xe3\xf4w\ +\x00\xa1\xedY\x97\xb5s\xa7\xbc\xc9\xc9\x95r\xbeO]\ +\xc0\xb4\xc1\xb3R\x80R\xb3\x06\xafa\x83\x00\x90\xa4Y\ +\ +\xb9\x7f\xbeX\xb5{:\xf3G\xe7\xd4k\xb7\xabw\xfa\ +$i\xd1\xb0\xb7]\xdc\x89\xab\xf4\xdd\x01\x04\x1b\x0c\x12\ +\x5cA\x9fo\x9b\x03\x08\x0c`# \xd02.\x00H\ +V\xd3\x22Y2\x00P\xef\xdc+\x05\xea\xa6U\x07\x10\ +\xb4\x1b\xb7\xfe\x5c\xf9\xb5\xe7\x00\xb8P\xbe\x07\x80+\x80\ +\xe32\x00\xb8T\xdc\x8a\xd2\xdb\xce\xa5\xf5\xd3\x1aw\xac\ +z\xf5\xaa\x0d\xec'9\xef!\x04\xe84\x8f\x7f\xd1~\ +FG\xc3\xa6K\x18\xcct\x065\x1d\xc5g\x90+g\ +\x10\x163PH\xba\x04\x10\xb8\xbf\xf1\x99\x0c,Mg\ +\xee\xeb8y\xed\xf9\xcfF\x99\xda\x09\x1c\x1d\xbfa:\ +\xad\xdbm\x03\xd3!\x17d\x06\xd1\x09\xc9\x91;\xeb \ +G\xbd\x95D\x92\xe1H\xfa?\x85\x1b\xed]\x14\xc7\x10\ +\x89S+Z\x85_\xb5\x8e\x91b$\xcaP.\x00\xa0\ +\xc6\x0f\x0a\x03^\x9bZ\xbc\x81\x13\xbc\xb3\x08\xbb\xe6\x03\ +x\x06\x85\x02\xcd\x1e&\xab\x8c_\x93u\x22\xb0J3\ +?q\x05\xfe\xce3+\xe5M\xd0\xca\xa0\xf6>2\x16\ +1\xf1M \x0f\xcb\x8c\xaf\x1f&\xee\xfc.\xf6\xa3|\ +m\x0b\x13\xf1s\x9d\xc3 <\xae\xe9A7)\x906\ +B\xf20a2\x80\x9cQ=$\x83\xc0\x83G\x95\x12\ +\xb9\x87\xc5\x1b\xf4\xc3\x09\xc4\x92U&\xa6\xddA\x9dX\ +\x8d\xbc\x86\x80 O\x00\xd8\x92d\x99\xb8~\x0f\x04u\ +\xe7\x00\xf0\xe4\x12\xca\xbe\x8c\xd2/\xe7\xab\xe7\xae\xac^\ +\x9f!T\xe0\x1d.\x94\xffYI\xbb}V\xaa>\x7f\ +\x9d\xae\xe7\x9f:_\xc6^t\xe9\x02\x14\xde\x0a\xde\xb9\ +\xf0\xb3W\xad\xa3>DjFE\x18`\xe0\x9d\xa0\xe8\ +4\xd8\xb6\x13\x5c\xaf\x13\xde\xa7\xe2&S\x01C*\x03\ +\x9dJH\x10`Dl\xb5mNg-eiZ\x18\ +\x00\xb8\xdd;\xc3\x9a\xf5;\xc4\xc2\xb5X\x06)\xd6\xe4\ +\x91z#\xa8.QS\xc5\x9aO\xd0\xc4\x1a\x99\x94\xc6\ +Ss,\x8a\xe7\xca\xb6t\x91\x14P\xd5O^\xda\xa4\ +\xc1\x04\xf4\xbc&Wz\x92REv\x02\x00RP~\ +\x0a\x03,Qc*\x15r\xa8TMi\xb1fF\xd5\ +\xb4!K\x0a\x1f\xf5\xb6o\x85\xb5\xb1\xa6o\x1f\xc0\xef\ +`$(\x9c\x8cB%n:B\xc7\x1d\xdf\x8eBd\ +\xf5N\x5cvD\x86\xe1@ \xc5\xe8Tt\x8c\x10\xe3\ +\x8b\x93`\xe9\xf1b\xf6\x80\xd3\xb5tq\xa9 @\xf8\ +\xa4|\xadJ\x02\x00\xdd\x97&\x81\x00\x808D\x8a\x8a\ +N\x00\x81\x97\xbaJ\x88\xf9\x9aY\x04\xb8:e=\xb1\ +^M!&P>\xafx\xf6\x04\xf8YL\x22\x16\xae\ +9g\x89;\x18\x8a\x9bR\x1f\x1b1b\xb9*-r\ +H\xf1nkr?\xb1]\xee]\x9d+\xc9\xfde\xed\ +\xd1\xf1C\xa7x\x1d\xc7\x1e\x1e\xe5oC\x9b|F[\ +\xc4E\x0eQ\xf8\xe0U\xcb'M,\xe4oE#\xbc\ +\x0eoZ~\xff\x8aE\xbaf-K={\xea\xff\x01\ +\x02\xf1\x01)\xfd3b\xfeg\xe7\x00\xb8\x5c\x80\xe5K\ +\xf9X\xb1\xd7\xe0P-\xd5\xa4\xf4.\x94\xdf\x83\xf4\xda\ +%\xd5\xbb92\xab\xd8I*\xa4\x936\xca\x08m\xfc\ +\xdd\xe5\xfdj.\xa9\x89\x1f\x95[\xa9\x0b\x89\xa6~\xf9\ +\x9c\xbah]\x9c\xe2\x9d\xc8\xff\xa8\x05]R\x85\x06\x19\ +\x17\xcb\xa0{5z\xe7B\xecu$Li\xad\xa6\x89\ +\xb1n\xb7\x19EE\xa9\xc3\xc8\xc01\x1e\xef\x00\xe5\xc3\ +\xec;\xb6\xe0H\xe4\xf7\xa4Z\xee\x087\xf7\xba\xe1D\ +\xe7*\xb9\xc3\xb34\xa7\x02Q\x96\x91\xc9\xd8\xd4\xb0\xdb\ +\xedADI\xf1R\x94\xe2\xb5\xc2\x03\xfc\xc0u\xf6r\ +`\xe0\x9ep\xff\xc9\x10\xf4d\xcd^\xf2;\x15\x97\xb8\ +\x0ej\x02\x81\xd6\x06H\xe9U\x83\xa8\xdfy'\x9f\xab\ +\xef\x82\xdc\xbe\xc2\xc79\xa8\xf8\xfeD\xae\x97\x00\xf8b\ +R\x94N\xb8x\xa1\x19/M\xf5\xe2\xa6:u\xd0\x13\ +\xae^q\x0e\xe5\x8b\xdd\xab#\xc8\xc5\x89\x1f\x91\x91=\ +\x8b\x8e\x1dX\x1e\xca\xcfG\xf9y\x13\x00at\x97\xbf\ +\x83|\x95$\xf5\x00\x9enx\x02\xee_^@\x07'\ +\x16\x8d\xefY\xe9\xc4\xbek\x10\xa53\x04s\xfb\x97,\ +\xd49c\x01\xd2\xc2Truu\x09\x8b\x13\xa9\xc3\xda\ +/\xa9k&\x22\xe5_QGP\xe7\xc2\xd5C\x08\x92\ +\xaa\x82F\x14v\x05\xe5]\xc6b/c\xc1W\xb0\xd8\ +8\xd7\xff\x86\x87u\x82\x9b\x13\xcbE\x89\xde\xa2\x88\x1a\ +/j&P+\x7f\x84:\xf7\x9e\xf8\x8a\x88l\x094\ +\xf1\x02\x8dZ\xb2\xa9S\x09 P\xa3F\xb7\x98\x82\xeb\ +U\xd7N\xa5Ub\xda:\x90!\xbd\x97g\x1c\x14\x00\ +\xb4R\xeaUQ\x87\x01@X{\xf2\xfb\x04\x84#\x04\ +P\xf4\xdd\xe0w\xa7\xde\xb4\xf0\xe0)!\xe2\x16\xef\xaf\ +a\x18\x87\x84Q\xaf\xc3\xba\x1ap\xc9\xe0\xd4=L\x8b\ +3\xee\xf8{\xbdb\xb9Z\x14rk\x03\xfcN^\x22\ +I\xf7\x80\xfbV\x88Vog)W\xe0p\xab{Z\ +\x0f\xa8U\x95\xb0\xb7&\xe0X\xbe\xd2z\xc7+Tz\ +\xa6\xb5\x01=\x0f\xbf\xe7\xef^\x97\x10\x01@\xeeB\x84\ +D\xcaG\xe9\xda>\xadrj5!\xc8F\xd4\xe0I\ +;{\xc3\xb8\xf1\xb0&~\x90\x88\xce\xf0\x19\xd9\xb1<\ +u\x07A\xf2\xb0\xee\xa8&\x83\xf8\x8c\x0eTRg\x11\ +\xd7V\x8e\x98'\xa2\x98;\xec\xed\x15,\x99:B\x0e\ +\xadhB{\xdb\xd7I\xa3\x16\x5c\x09\x99N\xe2\xd0$\ +\x86,\xf6JI\x97])\xd6\x5c=RDL/\x16\ +0\xe4\xd6{\x9c\x82\xdcC\x80\xe48\x1e\x22\x0e\xeb\x88\ +#\x97\x8d\xaf\x9f\xe7\x814\xa1\xb5\xf8;Y` \xf9\ +\xbd\xe6\xd3yPgI\xce\x9aD\xbap\x7f\xb8t\x0d\ +F\x1c\x00\x89\x05\x10q(]\xe2V\xcf\xf43\xa0Q\ +-]\x1c\x96\x13\xcf`ky;\x19\x22\x9c\x06\x01\xce\ +\xe0\x99\x02Z\x0a\x86\xffD \x80Q\xedNV_\xe5\ +q\xed\xf5\xd3\xa6\x8d\x07\x18\x86\x96\x9e\x9f[\xc9\xec\x1b\ ++\x9b\x7fg\xe5\x0bo\xadl\xe15\xe9\xa2\xa6\x88\xef\ +Y\xee\xd8-\xc6\xf1\x84\x90\xaa\x89 -\x09{L\xdd\ +\xad\x0a^\x00\x00\x8f,q\xcc^i\x1daZi\x9e\ +\xab \x92\xf25m\x8f\xd2=\xe5{\xab\x81z\x9f\xa4\ +T\xb2j\x1c\xa5C,\xdd\xb3\x09\x04\xe7\x00\xc0P\xe2\ +\xf5\xec\x8cA<\xff\x1b\xe3\x8e\x82\xc3\x0d\xb9\xa5`\x94\ +\xa7]8Y(22\xb8iQ$\xd7\x89\xe2\xf8\x06\ +\xf1\x5c1\xfd\xaas\xeb\xb9r\xe5#[\xc8\xb6\xb3\xf0\ +\x5c\x00\xa0]\xc0jx\xa4\xb0\xa1\x87rm\xe5\xf0 \ +\x11\x88Q\xde\xe8\xa1\x15\xc0\x88\x0b\xe51\x00MD\xfb\ +\x00\xd5L\x02b\x98\xaa\xbcU\xae\x09\x85\xe8\x06]\x83\ +Du\xca,\x1f\x81\xb8q\xd3\x92\x0a\xdec\xd9j\xa8\ +\x98\x88b\x13\x9b\x97\xce\x17NV\x19$O\x92Z\xd6\ +\xf9\xf9*\xb2aIm\x88\xa6T\x11\x1d\xf9\x9e\xcc\xef\ +5\xc3\x96\xc2g\x92\x9b\xf8l\xe3\x12\xa0\xd0\xfa\xc7,\ +\x03\xa14\x0c\x8b\xd0\xc0\x9d\xaf\xa1{ \x1b\xb5X\x94\ +\x1f'\xf2\x84B\x925C\xa8\x850m3\x1fF\xf9\ +0\xff\xfc\x99{V2\xff\xc4\xca\x17\xc9\xf9\x97\xdfX\ +\xe5\xca;\xd3\xf1\xf9\xb5\x1b_[\xc3\xf6\xf7\xd6\xbc\xfb\ +\xb3\xb5\xec\xfdb-\xbc6\xf2s\xed\xd5\xaf\xacrU\ +{\x04\x9f\x93\x1e>p\xdb\xd4\xc5\x1f2\xbb\xb6\xe0\x06\ +xb\xe5\xea<\x9f\xeb<&\xe5\xb7\xf1\x9e1Jn\ +;_\x16\xc6\x0biB\xc8\xb9~\xac_n_\x93:\ +i\xea\xaer.)\xf5\xaa\x09\x98=\x7f\x1em\xec\x95\ +7\xd0l\xa1\xc2\x08\x1e\x12\xe5{\x02\x00\xd2\x1d\xd9\x83\ +\xe9\xc3\xd2}\xbd\xcb\x969\xb0\x86\x8b\xd7\xf6.\xdc6\ +\x96Z\xac\xd7Q,\x1e\xa5\x87\xfbp\xe9\xbd\xc4\xef\xbe\ +\x15\x00\xb1fy(1\x0f H\xa2\x10\xbf\x08\x8c7\ +\x1b\x00x$\x88\x94\xa7[\x80 l\x0c\x1cX\x8ev\ +\x09+c\x807D\xf0\x08Y}\xea\xc6\xa19j\x11\ +\x17\x11\x18\x89&+\x18\xe4\xa65O\x1aW-\xad\x1e\ +\x16[G\x1aS\x8f4.3\x08kN\xa1Z4Q\ +\xbb\xd6\x0bI&\xee\xa6t\xee {\x96\xda\xb5oi\ +\xddG\x96\xd6s\xfcI\xd2\xf99\xbd\xeb\x10\xa0\x1f\xe0\ +\xed\xf8\x8c\xce\xd4k\xd39\x00\x1b\x1e0TE\x030\ +t\x0fI\x0ch\x22\x03\x1b\x8f\xc7\x88\x97\x07\xd1D\x0d\ +1=]S\xb6jJ1r\xcbr&\xeeX\xc1\xec\ +C+[zaU\xeb\xef\xacn\xebKk\xdc\xfd\xd6\ +Z\x0e\x7f\xb0\xee\xeb\xbf\xda\xd0\xed\x7f\xb2\xb1\xfb\x7f\xb7\ +\xa9\x87\xff\x86\xfc\xbb\x8d\xdc\xfd\x17\xeb\xbb\xf57\xeb8\ +\xf9\xa3\xb5\x1c\xfch\xf5;\xdf\xb8\xad\xddej\xbe\xad\ +\xbe\xcb#\xd7\xf1\xba\xbb\x8e#\x880:n\xc0\xd8H\ +\xf9)\xed\xc4\xf4V\xa4E\xf3\xfa3.\x1bI\xd3L\ +%c\xe6\xc3\x10\xfc\xad\x8c%<\xc3\x9b\xe2\xdd\x01H\ +\x9bn\xfc\xf4,\xee\xd0\x0b\x9eC\xab\x81nE\xd0\x89\ +W\x15\xa4mc1iX_\x9a\x9a)\xb5M38\ +\xb3\xa47j\xf4\xb0\x82\xcb\xde ^o\x13\xb7\xb7\xad\ +x\x0c\x00@\xecB=K\xae\xe1S\xa8\x9b\xcf`\xbd\ +\xd1\x01\x800\xb8\x86\xac[\x0e\x9eA\xed_\xdc\xe9\x97\ +d\x0cY=R\xfe\x9e\x8bw\xe1AR$\xeduW\ +\xca\xa4\xfd\x80\x10\xc9\x00\xdeF\x0bEnZ\xd3mS\ +\xd2\xea!\xee\xb0\xe7\x08ph\xe3\xa4:Z =\xd7\ +\x01\xca1!E\xfb\xd9\x0f\x9c\x12\xd2\xba\xd5\xa6u\xd7\ +\xbd\xa6u\xeb\xe7}~F\xb1\xdd(\xba\xf7\x1a.\xfa\ +\xa6\xf9\x07\xce,s\xe8\xaee\x0e\xdf\xe3\x15\x19\xbc\xeb\ +~\xe7\xeb\xbf\x89\x05_G\xae\xc1\xe4\xbd\xf63\xea\x98\ +\xe1\xda\xa7\x00\x12_\xc7>\x83\x0f8\xf0\x22)\x02\x9a\ +S\xfc\x9e\xfbl\xf6\xd0mr|\x9d\x9f\xf0\xd4\x8a\x17\ +\x9e[\xc5\xca+\xab\xd9xg\x0d;_\xa0\xd4o\xac\ +\xfd\xe4{\x1b8\xfb\x83\xcd>\xf9\x9bm\xbe\xff?\xed\ +\xe0\xeb\xffa\xc7\x1f\xff\x1f^\xff\x1f[{\xf7?m\ +\xea\xe9\x7f\xb3\xa1{\xffj\xbdg\x00\xe1\xc6o\xd6t\ +\xf8\xbd\xd5l~ne\xcb\xcfM\xcd1\x9c'pe\ +b\x22\x87b\xf3(\xae\x05KGt\xa6\xb3\xeb*\x06\ +I\x0f\x02\x90l2\x8b0\x86\x16\xc5\x1b\xe5\xf2\x7f\xd1\ +!\xd5D\xaa\xf4\x8c1\xeb;a\xcc~_\x17\xb8t\ +n`\xca\x16P<\x04S\xe2J\xc2RT\x0e\xed\x8a\ +\x0f\x87\xb9\xc8\x08\x17\x9f\x80\xf4\xcdY\xc1\xc8*\x8a\xdf\ +p\xca/\x1c\xd9\xb4\x1cu\xfc\xc0Kdv\xcc\xb9\xb2\ +\xf1\xac\xce9\xcb\x06\x08\x02E\x08\xcf\x11\xc2;dk\ +[\x18\x8a\x15w\xc8\xee\x917\x808\x92\x1a\x85\x05\x82\ +\x01\xd2$\ +\x22\xad|Bz\xf9\x84\xf8\xfa\x98l\xe3\x01)\x17\xca\ +\x84H\xf9PXz\xdf\xa1\xa5\xf5\xa2\xf8\x9e=\x14\xce\ +\x83\xaa\xb8\xa2\x1f\x05\x0e\xde\xb2\xac\xe1;\x16\x1a{`\ +\xe1\x89'\x963\xf9\x1cy\x81\xab~\xce\xef\x9eX\xd6\ +\xc8\x03\xc0p\x87\xf8-p\xa8y\xc4]~\x7f\xdf\x22\ +c\x0f\xb9\xc6C\xc0y\x8f\xdc\xfe\xcc\xd4>\xc5\xdf\xcb\ +w\xc2\xea%\xb2z\x1dI\xaf\x13\xc9uRJ\xe1\xf4\ +c\xcf\xedc\xbd\xd5k/\xacn\xe35\xee\xfd\xad\xb5\ +\xec\x7fn\xfd7?\xda\xf2\xf3?\xd9\xb5o\xfe\xb3\xdd\ +\xfb\xe5\x7f\xda\xa3\xdf\xfe\x7fv\xe7\x97\xff\xaf\xed~\xf5\ +\xbfl\xf6\xe5\x7f\xb5\x91G\xfff\xfdx\x86\xae\xdb\x7f\ +\xb1\xd6\xeb\xbfX\xdd\xeeWV\xbe\xfa\x92Pr\x97\xf4\ +Y\x00P\xb6\x80g\xd4^I\xc5\xfb\x06H\xb2\x0aC\ +q\xfd>\xb8@\x10p\x14\x10R\xab&\xaf[\xed\xec\ +M\xab_<\xb3\xfaem\x16\xb9m\x05\xae3\x99\xb8\ +\x05 \xe8\xd7\xeenU\x1c\xe9\xccGyOo\xceA\ +\xbd\x1eD \xd5\x85]\xfb/c\xbcs\xf14E\xda\ +\xcd/\xbd\xcd\x1b\xd9]S\x967\xb8\x04[_\xc7\xfd\ +oZ\x01\xec>\x82r\x03\xed\x0b\xa6\xa3N} \xd3\ +\xdf\x0a\x83\xd7\x9a\x80\x96Fubx\xd7\xa2i[\x98\ +j\xed\xb4\xd9SS\xc1\xd9 4D^\x1c\xc6\x13\x84\ +\x05\x04\xe5\xc9\xbc\xcf\xe2w\x0a\x0f\xfe.\xc4mNU\ +C\x04\x94?\xae-\xd0\xb8D\x9dJ\xb2\xfc\x1e\xf9\x9c\ +\xf7\x9f[\xde\xdc[\xcb\x99za\xd9X\x9f\x94\x97\xce\ +\xc3\xa5\xe2.S\xb1\x964\xbeG;\x85\xb5\x9f>{\ +D\xdb\xb2\x89\xabSO\x19\xd0W\x96\x0f\x01\xcb\x9fy\ +c\xd1\xa9W\x00\xe2\x99e\x8f=\xb2\xe0\xe8}\xe4.\ +\xdf\xa5\x06\x12j'\x83\xf5\xcd\xea\xb3/\xf9\xbfgX\ +\xf8#R\xbb\xbb\x00\x0e0aQjH\x91\xcdkh\ +\xf8&\x008%\xfb\x81\xec\xe1\xfe\xd5\xd2F\xf3\xffe\ +\x0b\xf7\xbc\xcd-\xab\x0f\xadv\xfd\x91u\x1e\xbc\xb2\xb9\ +\xfb\xdf\xd8\xe1\xfb?\xd9\xe9\xc7\x7f\xb1{?\xfd7\xbb\ +\xfd\xe3\x7f\xb7\xdd/\xff\x8b\xcd\xbe\xf8W\x1b{\xfcw\ +\x1bz\xf87\x00\xf0'k\xbe\xfe\x93\xd5\xee}ie\ +k\xdc\xc3\xccmWk\x18\xe8\xc63j\x8e\x00\xcf\xac\ +\xfe\xc5\xaaYL\xab\x1buk\x11\x99\xad\x8b\x16\xc1\xbb\ +V\xa0\xfc\x8e\xf5\x07\xd6\xbd\xf5\xd0zv\x1eZ\xf7\xee\ +CkX\xbd\x0d\xe9\xbc\x06@\xd5R\x06\xc0\xaa\xbf\x03\ +^X\xfd\x91\xdcz\x01)\xa1\xb2\x19\xafHD\xa5\xfa\ +\xfd\xe8\xbc\xcfb\xb4\x1a\xe7\x8eM+\xef0\xf5\xecM\ +\xab\x1b\xb4`\xeb\xa4Eq\xf1\x05\xc4\xfd\x02b{\x1e\ +9oX\x04\x91\xb8\xe4\xe6\xcd\x9b\xd4\xf1s\x06 \x00\ +\x06\x15Nj\xaa\x17\xb2r!\x81vZyEb4e\xaaY3\xf5\xdf\xf7\ +\xf6\x07\x8eZ\x00\xc5\x86\xb1\xe2(\xa4.wp\x97\xf8\ +N\x8e\xaf\xc9 \x15\x83\xb4\xaf\x00\x84e'R\xb2$\ +\xa05u5y\x80\xb4\xf8\xb4\xc2F\x9c\xf2\x93^f\ +\x92\xda\x04A\xa0\xe2U\x08\xf6\x1cBY!\xc0\x10\xc2\ +u\xabN^9\xb1*du<]t\xea\xb1\xe5\xa3\ +\x8c\xe2\xd5w\x0c\xcaWV\xb3\xff\x9d\xd5\x1f\xff\x8c\xfc\ +j5\x07?\x03\x88\xef\x00\xc1\x07\xcb\xc1Cd\xa1h\ +?nY\x0d\x0eTD\xa1FP\xb2T\x1db%\x17\ +\xed\xf5\xe6y\xeeZ\xb4\x14L?\xb3<\x94\xaa\xb2\xac\ +\xf0\xe8\x1d\xbc\xc4\xa9\x93\xd0\xe8\x99+\xe3\xca\x9b\xd2\xe7\ +\xb96\xd7\xcfS\xd9\xd6\xd8]\x94\x8d\x1b\x1d\xe2\xfb\xe0\ +.9\x83\x87\x08$V2\x84\x0c\x8b\xd0\x1e\x02\x06~\ +\xcfk\x0eV\x9b3\xb4O\x06\xb4\x03\x09\xde\xb4B\xb2\ +\xa1\xfa\xd9#\xeb]\xbfe#\xbb\xf7l\xea\xf8\xa9\xcd\ +\x9f\xbe\xb5\xa9\xd3\xcf\xdd\x99\xc7=7\xbe\xb4\xce\x1b_\ +Y\xdd\xde;\x80\xfe\xcc\x0a\xf0 \x11,:\xc88{\ +\x0aSY\x9e7g\x7fQ\x09\xa4\x92\xf3,\x5c\x7f\x8e\ +\xf6\x08\x8e\x01\xb2\xa5\xfb(\xfe\x09 \xb8kmk\xc7\ +\xd6\xb4\xb4c\xa5c\xf2\xbe:\xebh\x12\x12I|o\ +\xc1\xddkvWS\xbex\x91X\xd2\xec+(\xff\xb2\ +\xa6\xcdK\xdb\x916\xa4\xd5b\xdcVb7\x0b\xa6\x8b\ +\x8d\xc3,\xb5\xda\xa5m\xde\xdb\x10\x0b\xf5\xf7\xc1\xad\x90\ +\xaf\xe6\xf0>\xacF\xd1}Z\xe8!\xbe+\xc6#\x22\ +|\xdaQ\xac\x93\xc2u\x5c\xbc\xda\x95f\x00\x00\x1fi\ +\x8c\xbfy\x110\x01\x12\xd2\x9b`\x1b\x1c\xa2}\x1d\xee\ +\x00B\x01\x81<\x80\xce\xc7W\x85\x8c\x00\x903\xa5\xbe\ +>x\x80\xe5\xd7V\xb6\xf1\xc1\xaa\xf7\xbe\xb1\x86\x93\x1f\ +\xac\xf1\xba@\xf03?\x7fo\xa5\xa4P\xf9\x0bo\x88\ +\xebOP \xf1zH\xe5U\xb8h\x80\x14Baa\ +b_\x0e\xdf\x17E\xb9\x12)2\xcc\xef\xdd\x89\xe5\x00\ +N\xdb\xdf\x83d%j\xce\x90\xa5p\xe4\x08\xea\x89S\ +v\x0e.^$J\xc7\xde8\xce\xd2\xb7G\xd8#|\ +\xe1F\xc3<\xa3\x96~\x95\xe1h^?[\x13cX\ +bXmb\xfa\x0f\xf0j<\x0b\xe1,\x0b>\x13j\ +_\xb3|\xdcx\x19VXIz\x5c;y`m\xcb\ +7\xadu\xed\x8e5\xae\xdf\xb3\x86\x8d\x87p\x06\x1d\xbf\ +\x03\xd7\x99VS\x8ec\x94\x0f\xc9\xe4\xfb\xd5\xd7\xd0M\ +\xdf*^\x9f3wu\x15\xd7\xb6r\xf1\xa9(\xba(\ +\x9c\xd3\xfeC\xb7C\x18\xb9\xa2\xb9\x16'\xdd\x16\ +\x8b\xc4x\x95\xa5b\x87\xc4\x9d\xe6U\xd2\x10\xcd\xf9\x13\ +\xafq{\xb9c\xa7\xae\x9dI\xde\xf8\xa9s}9Z\ +\xf0\x18\xe4ox\x04\xad\xf8\xa9\xc5K\xb6\xa6\x88\x19 \ +\xcd\x1c\xba\xe9M\x1e\xc2\x87\xe5\xfb`\xf6~r\xf4L\ +HH\xb0\xc3k_\x9aE\xba\xa6\x13\xc54_\xaec\ +\xe6B\x1al\x07\x80;X\x81\x5c2\x96\xb8\xf8\xc2J\ +\xd6\xdfZ\xe5\xee\x17(\xfe#\x00\xf8\xd1\x1a\xaf\xfdd\ +u\xa4W\x95\xdb\x1f\xadd\xf5K+\x5cx\x87\xbb~\ +\x89\xc5B\x14\xc7\x94B\x9dy\x8a\xee\x97\xa2Q2\x1e\ +&S\xfc\x82\xeb\xfa\x00\x9e\xb7\x1d\x0bbE\xc6!\xd1\ +|\xbc\xee\xd3\x8f\xb2\xbc\xe3\xee\x95\xba\xa2\xc0s\xc9\x86\ +[8o\xc5\xefC\xdcw\xf6\xb9d\xf1{\xcd\xe0e\ +\x13_\xdd*\xe0\xd8M\xcbgl\x0a\xc6\xce \xcd7\ +\x09\x95x\x0cy7=\xaf@\x8f\x01dq\xad\x02<\ +C\xe9\xd8\xbe\x95M\x1d[\xf9\xec\x0d\xb7'Rk(\ +Yx\x0e\xb5\xb6\xf1\x03,\xd5#\xaa\x0c\xed\xf7g3\ +\xebg\x1f\xd7\xcd\x04\xb0*\x22\x89\x8e\x9fY\xfe\xe4\x1d\ +\xc2\x8e\x1aB\x12~F\xf7\x08\xd5\x10\xf0\xf6)\xf3\xab\ +\xd95!\x5c\x07g\x5clp\x89G\xf1\x09*}?\ +_]\xd4\x8c\xa8&\xbe\xe2\xabF\xdd$X|\xf58\ +i 9dz\xfb\x06\xeeG\x95\xbd\x07\x16\xc4\xb5\x86\ +\xd4\xb4Q\xb3Z\xd3\xeao\x83\x90\xa7\xe6\x81<\xb5\x88\ +\x8f\x0c\x03\x00M\x0bk\xb5K\x0b\x22\xbd\x9a\xf0\xb9\xf0\ +\x00\x02\x80D\xef\x19Xr\xf3\xac\xae]\x14\x8e\xb2q\ +\xd3!Y\x8a,\xaf\x8fl@Y\x01 \xd3I\x98\x11\ +\x1d'\x0f\xb1\xcaQ\xf7\x8b\x99\xfb\xb8\xc5GV\xa2\xa2\ +\x0a\x98u\xed\xc1\x97V\x7f\xf4-\xf1\xf2{\xab\xdd\xfd\ +\xc1\xaa\xb7~\xb0\xaa\xab\xdfY\xd5\xda7V\xb5\x02W\ +\xc0#\x94(\x96\x03\xa2( \xd05\x82(O\x1bJ\ +}*\x84\xc4\x82TC\xef\x8e\x9e\x11\x03Vl\xe5\xd5\ +m\x8f\x82\x15\xa7\xab\x00D\xde\x0a\x90\x04\xb8\x7f\x85\xb9\ +,@!\x85\x87\x00\xac6vfK\xbaP<\xcau\ +^\x83\xfb\x8e\xc2\xb6\xf3\xa6t\x14\xfd\x03+\x9d{\x84\ +R\x91\x99\x07V\xacf\x0ej\xea\xa0\xb0\x841\x05Z\ +\xe1A\xe4\xf69x\xcd(\x9eC!5\x8a\xe2u\xfc\ +\xbc\xca\xd0\xd4\xbcR\x85\xa7Z\xbau\xc5\xa1j\xdd\xe2\ +j\x04w\xd1\x87\x00BZ\xcc\xf7\xa9uO\xf4\xd3\x89\ +\xa1\xea\x12\xa2if\x9e\x15^\xe0\x87\xe4i\xc9:\x19\ +\xe5&Vj\xba[\xa2\x121-x\x0d\xbb\x95C\xd7\ +oA\x93m\x9a&\xc6\xbbx\x15\xe0\x0b\x16\x93\xc1\x85\ +|*\x14\x84\x90\xb9\x1e\xbc(?4\xa6C\x09E\xca\ +\xb0\xc89d\xf6!\x17Vy\xb3\xdc\xacn^^\x02\ +>\xa0\xee\x1b\x9dX\x92\x8a*qS>\x1eB\x13\x19\ +\x99\xce\xd2\x15\xe7\x09\x1b\x903\xb9\xd6\x1c\xb9gD\x84\ +*\x0c\x9a=\x11\x07\xe0A\x5cw2\x91A\x84\xf7\xaa\ +\xb2\xd5\xe1T\xc5\xcb\x8f\xacb\xe3\xa5\xd5\xec~\xb0\xfa\ +\xfd\x8f\xd6p\xf0\x935\x1e\xfcjM\x07\x7f\xb0\xe6\xfd\ +_\xacy\x17\xef\x00Y\xac]\x837\xcc\x93\x9bc\x1d\ +\xea\x95\x1b\xc1}\x87 \x9fA\x94\xea\x17aE\xe1\xa9\ +\xc4T\xad\xa2\xb9\x83\x15T3\xc7{W\x17H\xbc\xcd\ +`\x00\x03\x84/\x852\x85\xb5\x10\xb9\xb52\x96\x08\xf7\ +\x1f\xd1\xe6\x0e\xed4&\xb7\x0e\xcb8D6\xa5`\xac\ +_\xcd!\x0b\xb9\xcf\xd2\x85\x07\xae\xe1d\xd5\xca\x132\ +\x02\xd2\xc3y\x5c\xbc\xa6{\x19\xcb\xec\xdec\xc6\x83\xf1\ +=\xaf\xc3S\xbb6\xe7\x99\x5c\x0a\x8c\xcb\xe7\x1e]\xc1\ +\x86f\x01\x05\x00\x8cF\xfd|\x95~\xfaU<\xaa\xbe\ +\x81\x18\x89k\x14\x05\x00\xa2\x02\x80\x80\xa0\xfe\x82xh\ +\xe5\xffa\x0c*\xc8\xff\xa9\xdcK\x07k\xa8G\x90&\ +yRk\x09!\xb5d\x13Hr\x1d\x06\x80\xb7O\xaa\ +\x9f5\xd5\x81z\xc7\xd0\xaf\xea\xf8\xf8C\xf3\xf3\xa0j\ +\x17\x17DQ\xd9\xa3\x10$\xac\xc9\x03\xc0\x13R0\x04\ +\x00\xe4\xaa\x9cI\xad\xcc5\x89\xa3\xd50m\xc7\x86\xf0\ +\xb9\xeeYn\x05Qnu\xcd)_\xf1=\xc2@\xe5\ +\xe2\xde\xf3\xf9\xae\xfc\xc9{^c#\x90\xab\xa6\x88j\ +\x94\xa4\xd2(\x1dT\x1d\xd6r\xaa\x13\x06\x17Q\xbbt\ +\xcd\xaf\xe7N\x9d\xc2\xce\xef\xbb\x06S\xd5[o\x01\xc0\ +\xd7\xd6D\x18h9\xfe\xc5\xda\xae\xfd\xc1\xdaO~\xb1\ +\xf6\xa3\x1f\xadu\xff\x1bk\xdc|o5+\xcf\xac|\ +\x0e\x8b\x04\xa4y\x90\xb5(\xa1)BX\x0aAP\x83\ +d*\x01W\x9a\x86\xe5\xbbM\xab\x12\xf2`\x94\xaf\xc9\ +\x15q\x17-|\xa9\x0f\xaf\xb8\x8ebm..=\x17\ +\xb2(\x89\xc25\xd4s/\xa2T\x15#\x11o\x08\x13\ +\x0eU\xe1\xa3\xa5\xf0\xa2\xf9[V\xb1z\xdfj6\x9e\ +X\xfd\xf6K\xab\xe3~\xab\xd7\xc9f\xdc6\xf7G\x80\ +\x1e\xf2\xd9\xa7.^\x8c\xb3\xfa!\xbb\x1a@\x00\xc0\x98\ +\xb9\xf2n\x09\x5c\xe9\x1f=\x824\xf1t\xe0\xda\xc5\xa9\ +e|\xa6v\xfcb(\xd9j0%O\x80\xf2\xd5\x9f\ +\xb0\x10oY\x04 \x0a\x09\x9f\xb9\x10`\xb5\x83\xcd\xec\ +:\xc4\x10w\xe0a\x80\xac\x89\xf0\xd7\xb8\x82\x97#\xf4\ +\xa1t\xb7\xff\xb0\x19\x80\x9c\x83-\x15o\x13\xe3\x07\xa1\ +\x01\x10\xae\x06\x85\xbf\xef\x16\xa6\xc6D\xd1iX1!\ + \x8a\xabS?[m\x8f\x0a\xf4\x90^\xc0\xf8\xbd\x1e\ +\xc2\x9a\x9aT\xcd\xf9\x02qU\xde@\xb3\x80\x22G\xc4\ ++)\x1f\x96]\xc8\x0d\x16\xcd>\x22%{\xec\xda\xa8\ +\x16p\xd3r\x9d\xea~)@\x85G\x09\x05\xa3\x84\x87\ +QB\x0b\xccZ-\xde\xa2\x137`\xef:{@]\ +\xc6\x1e[5^\xa0~\xf7=\xd6\xff\x855\x1f~m\ +-G_[3\xef\x9bv\xdfY\xc3\xd6K<\x00\xd6\ +\x07\xa9*\x9b%\x1d\x9b<\xb6\x02\xbe+oh\xc7r\ +\xf1TQ\xd2\xa1\x88Z\xd5j+\xf8\xf9I\xe6:\x8b\ +/\xbd]\xa2z\x87\x157\xf9\x92\x8d\xf2#R>\xc0\ +\xcc\xbdX\xdcQ\x96\x00A\xcd\xd5\xe4\xd4\x08F\x01\x10\ +\xb4\x0bY\x00wK\xe4|\xb7\xba\xa3G'w!u\ +\xd7\xadr\xe3\x1e\xec\xfe\x855\x1e~\x0e`\xbft\x8d\ +\x1cK\x97IE\xd5\xc0Q\x13ZC\xa4\x97\x03\xe7^\ +A-lTz\xee\xaau\xe6=q\x0bsZ\x95\xbd\ +\xeaJ\xd4\xb5\xc7\xc2\x8f7\x0b\xe0\xea\xd51\x5c\x8d\xa3\ +U\x7f\xa0\xc3\xba\x0aT\x83\xb8\x84\xb7YQ\x152a\ +p\xde\xe3D\xe1\xa1{\xdc\xd7-\x80\xc05:\x0e \ +\xf4\xf0!\xb5\x8dk\x13\x1f\x02`\x18\xa9\xe3\x1ax\xa1\ +4\x80\x18\xa3\xce\xdc\xea\xc5\xaf\xa6\x0ajJ\xa4n\x95\ +j\xb6\xac\xadN\x8a\xcb\x12u\xab\xcc\x06\xf1\x99X\x95\ +V\xf9>mi\x96(\xfe\x80d\x95SkbG\xe5\ +\xce\xae\x7f/\x00\xc8\xe5\x7f\x0b\xa6\xef\xe3&q\x89\xf3\ +\x8f\xadx\x01\x99\x7f\xc8\xcf\x0c\xec\xa4\xb6L\x1d\x02\xaa\ +\x1dR8\xed\xba\xb9\x0a)\x22\xee\x8e\x90N\x01\x88\xbc\ +\x89\x13\xc0s\x93\x07;3\xf5\xf5\xab\xbe\xfa\xd8j6\ +\xd5\xdc\xf1)\x16\xf6\xc4j\xd6\xef\xe3r\xf9\xdb\xe2u\ +\xe2\xef\xb1\x95L\x1f\xa0|\xb5RQ3jdt\xd7\ +\xf2G\xbcfV\xf9\xc3;\xae\x99\x85\xd6+\xc2\x5c+\ +\xab_\x0d\xa3\xe1-X\xbd\x0a]\xdc9H\x03\x80O\ +\xd9\xce(\x04M\xaeUm\xd8\xf0^\xb9\x84\xc3\xe8\xa8\ +Z\xb2\xe1\x01\xc88\xc4e\x82\x90C1sm\x8f\xf7\ +w\x91\x9f\x0f\xadX\xde\xcc\xae\x95\xae\xdc\xb0\xea\x9d\xc7\ +\xd6x\xf4\xce\x9a\x8e\xbe\xb2\x06\xbcV\xed\xf6Wx\x83\ +/Q\xd2;+\x99{\x89\xc5\x12R\xe5a\xb1j\x11\ +JM\xfbj\xeb\x5c2\xa9\x9e*v\xdc\x16\xeeFm\ +\xfeP\xfd\xbf\xc0\xcau\xba \xab\xdc\xab:\x8e\x85\xe4\ +\xdd\xc6\xafaH\xb7\x01\xc0c<\xcf+\xab$\x04\x96\ +\x09h\xb3\xaf\xf8\x9b\x07\x82P\x1f\x9e\xbc\x87\xd0\xda}\ +\x02\x7f\x01\xb0\xf0\x8a\x00\xbcLaZ\xba\xca\xd0\x0c,\ +\xde&&\xb5\x05\x14\x8a\x08\xb6ijV\xb5\xf1|P\ +\x08\x17\xa3\xd6\xec\x1a\xa2\x03\xa5]/~\xe2\xaak \ +\x0dR]\xcd<\xaf\xaa\xa1\xd7\x97\xa9\xab\x95f\xf5\xb4\ +ARiYD\x00`\x10\x05\x80b,\xbf\x14\xe5\x97\ +.A\xee\xd4\x1eN\xfb\xea&D\x02a\xb8}\xc4\xe9\ +\x9ey\xf3!\xfe\xdeE\x00H\x0a:\xb4\xc1\xa0o\xe3\ +AP\xe8\x14\x8a%\xaf.\x9dG\xc9\xf3G\x0c\x22?\ +3\xd8\x85\x13\x1b\x967\xba\x82R\xd5\xe4q\x9etl\ +\x8eM\xb0u*T\ +\xads/\x90\xc9\xb1#+\x9a9\xb32\x08s\xc5\xd2\ +\x0b+[|\xc58\xbdp\xcb\xd0\xd1\xe1{x*\xc2\ +E/\xe9q7\xf7\xdc\xb9cA\xb8G@\x04]\x99\ +\x10^'M!\xa7y\x854\xb0^\x85\x89\xdaf\xa4\ +\xc5\x07m\x1fRQ\x08\x08\x87\xf5\xea|\x1e\xb7y\x81\ +\x87\x96\xf2\x1dq\x91\x8b:\x97\x7f(\x9e\xcf\x00\x1am\ +x\x14p4\x80\xf2\x00J!\x8bp\xf9%\x0bZ5\ +\x83-\xabJv\xfe\x14>\x009\x1c\x96\xf5\xcds\xad\ +I\xd8/\x0f\x8a\xa4wL\xf0]\xda#8\xcfC.\ +\xe1rQ\xf0\xf0\x0a\x0a]\xe6u\x09E\xcc\xa3\x04\x06\ +\xbc{\x02\xf76\x02s\x1f \xce\xf5\x11\xe7\xd4y\xc4\ +;\x1f0\xd0>\xc2\xdf\xa7\xb0\xd6E\xcb\xd3Z\x06\x9e\ +\xa1l\xde\xdbgX\xb1$\xc2\x86W\x9a\x91\x85\xe3\xca\ +\x07\xbd\xa6\xd8^\xd3\x06\x89\x9e\x93\xe7\xd6^{\xbcb\ +\xa6\x04\xcf\x18D\x14\xda4\x85\x9d\x85k\xf6\x8e\xc3_\ +\xc2\xcd\xce\xf1\xf7Y\x9ew\x09\x00\x008\x00Z\xbe~\ +\xc7jv\x9e[\xdd>\xbc\xe5\xe0s\xb2\x97\x0fV\xbb\ +\xf7\xde\xaa\xb4=}\xfd9!\x01\x0f8\xa7\x19K\x19\ +\x17\xf1\x9e\xefImV\xe5\xce\x08\xe4\xd4\xebQ\xa0\x96\ +o\x92$\xde'\x93\xc7\xa7\xd6\x0c\xc2\xf2\x87]Q\xad\ +\x8ak\x83x\x1e5\xb7\x88\x02\xa0|xS\x91:\x88\ +\xc3\x0b\x94\x09\xe5\xcaS\x11\xa6Bx\xf6,\x9e'\x88\ +a\x070RM\xcc\xb9\xb2\xf7\xa69/3Bt\x22\ +Y\x8c+(lPQ!\xbf\xe0\x03\xaa\x1fO\xd3\x9e\ +s\xe5\xa0\x8e\xb1\x92\xca\x10\xdb\x03\xae\x94\x89\xdf!\xf2\ +\x14\x19\x9a\x82\xd5\xf2\xa568\xa0t\x1d\xe5\xa2\xe9X\ +\x1d\xe0\x10\x86G(gU_`\xf5\xd1-Y\x90\x00\ +\x86\xb9\x1b\xc4\x7f-\x07\xaf3\xa8s\xe4\xe7\xda\xec\xd0\ +\xcf\xc3w\x83\xfe.\x88Y\x0f\xee\xaf\x0f\xef\x82b[\ +\x87@\xec\x88Sh\xa0\x8d\x87o\x1d\x84\xad\xf7[Z\ +\x83z\x0duZ\xb2:\x96W\xb5Z\xa2\x9aV#I\ +\x95-\x96R\xd3\xce\xdf\x01\x02\xff\x17\xec\x99\xe1:\xab\ +\x90\xb0\x1d\xee\xe1\x18\x00B\xd4\x96\xe1\x09\x80\xb0H\xc7\ +\xdf\xc2A\x94[\x0b\xe0\xeeH\x15\x18tj\xf3\x85\xe8\ +\xac\x80\xab\x8c\x83J\xb77\xf9>\xb9|o\x1cT\xe7\ +\x97\xa5R\xf8\xdeU\xbc\x0698 \xcd\x19\xbbJ\x96\ +\x84WZ8\xb1\xd2\xd5;V\xb1\xf9\xc4*\xb6^X\ +\x05\x84\xb0|\xeb\xb9\x95m<%\xad}HVs\x0f\ +\x90\x90\xcbO\xebtvyY\xf1)\x18\xbb\xac\x9f\xec\ +D\x15O\xae\x96Q5\x8c\xc5:\xf9\xb3\xcd\x92J;\ +\x5c\x05uje\x8f\xa9\xb9Uz\x1d\xe3\xd0\xc0\x984\ +Ox@\xe8Z\xb1\x08\xa9x\x0e\xe19G\x13W\xdd\ +\x90pt\xa4\x0c(\x80>\xfd\x84\x93\x0c\xa5\xbb\xa4\xbd\ +idCi\xa4\x8b*p\xf5\xfa\x14MY\x8c\x8a\x11\ +\xd5IJ\x1d=\xdc6\xe4\xa6iWb\xec\xd5\x06\xc2\ +\xec?M\x96(\xdf\x07\x10X\x80\x8fTI\xadY\xb5\ +\x08\xa3<\xd5\xb5\x9b\x95\xe0\xfa\xb5\xef=B\x1c\x15\xdb\ +wm\xd4g\xd5J\x1dF?s\x0d\x8f\x00At\xca\ +'5\x93\xf2\xeb\xd5;H=\xeeZMG\xbaK\xf4\ +>\xa1\xaa\x8d\x1c\x96\x87\x97\x92\xcf%\xb1\x0a\xa9l\xc3\ +B\xf8{y\x0b\x83\xd5d\xf1\xa5\x8d\x16_\xd2\xe0$\ +\x91\x9f\x93\xf9L:\xdf\x19h\x1b'V/\xc2\x8c\xb7\ +\xdc\xa6R\xb5\xba)\xc1\xf3\x94\xcc{\x80,\x98Q6\ +\xa2~\xbd\x10[\xc0\x1b\xe8\xdc\xc5-n\x00\xbe5\x8c\ +a\x85X\xacs\x81\xb5cZu\xfb\x22j\x1e\x10d\ +\x0cZ\xaeU\xd1\x8b\xaa\x9f4\xef\x1e\xd1J\xe98\xfc\ +bj\x8f\x8c\x09\x02\xba\xc4\xb3\xaeB~\xd7\x1eX\xc1\ +\xda}\xcb_\x06l\x0b\xb7,:\x07y\x9bQ7t\ +\x91\xddm\xc2\x86\x88\x1e^\xb7U\xc5\x9a#\xa6vq\ +WT\xefX\xdcnW\x0a[\xbcR8$\xbe\xa8\xc5\ +\x12\x00D\x22@H*\x03\xf8\x15^\x8f\xe6Tu[\ +\xa9\xed'\xc5\x1dB\xc9c\x16 \xc3\x094M:\xf1\ +7jC\xcb\xb8[DJQ\xfd\xa0\xf6a \xae\xef\ +\xa2\x0b1^\x95\xb1\x9aG\xc6\xa8s\x94\x8eEI\xa8\ +\x1d\xb4\x04\x95\x86\xabq\x82Z\xb6\x02\x04U\xc0\xea|\ +\x9b\xcc\xf3R\xf0\xa0\xca\x9b\xfbq\x95}\x00@\x84P\ +=\xfd\x1c\x08p\xa5\x00A\x04R\x05\x92\xea\xa1/\x92\ +\xa7\x9e\xfbE3zU;\xf8=\xcf\xf2q\xef\x19(\ +H-V\xd5~5\xa1R\x1b7\xb4\x89\xe3w\xe2j\ +\xf9\xd5\x91\x5c\x070#:\xf9\xda\x89\x8aC\x9b\x90\x06\ +\x8b+\xaaGj-\xae\x10\xe15Q=\xff\x00\x80\xbf\ +q\xc8B\x9ds\x96;\xb8I\xfc?\x81 \x9eY\xf9\ +\xe2]\xe4\xbe\xcb\xd7\xd5\xd7\xbfp\x16\xc5\x90\x89hU\ +/J\xda\x1b\xd614\xc4J_\xdb.\xdeg\x8bp\ +x\x15R\xa6\xca!y\x82M\xc2\x9d6r\x88\xf9\xc3\ +\x11x\xc6\xc8\x90\xea\x1bD\x1a\x05\xe8m\x9ey\x0bv\ +\xbema\x94\x9b3K\x16\xb3p\xc3r\x90\xc8<\x06\ +1E\x18\x81\x8f\xf8\x87\xc8\x92\x08k\xbe>\x9e\xbf\x9b\ +\xcc\xa9C%fcn\xcc\xe3\xb0\xecX\x5c\xbe;C\ +X\x00\xd0)\xe2(^@\x88E\xe2\x0a\x19\x13^\x05\ +\x06w.p\x89\xc0\xdf\x04\xe8\x9b\x01D\x1b\xde\xa1\xc3\ +\xd2\xaa\xba\x10y\x89^KE\xd4\xf1,I\xfb<\xdc\ +^\xc1^\x070'\x15\x12t\x8e\xc4\xf1>F\x9b\x09\ +]\x17/\xd0\xa4N\x9c\x89 *\xd1\xed\xd2\xc5]h\ +\x07P'\xc4\xcc\x9d\x12\x86\xdb\x1bX\xc7\xda\x89)\xb8\ +.\xd7\xb3\x97T\xc8k\xd2\xbcK\xfc\x17\xa9\x22\x03\x18\ +:t{\x05r\xc7\x8f\x19\xe0#H\xc9>\x84\x85\xc1\ +\x19T\x87m\x1e\xbe\x1d\xf7\xd34lI\x5cO]-\ +\x13\xb4e\xab\x02/\xa0\xf3v\xcf\xc5\x9d z.\xee\ +\xe4kU\x03\x970\x08\xeaiX\xd4\xc8\xa0\xd4Yl\ +A\x0dRmW\x0a\xd4\xa5\xb3\x0awYg\xa9U\x1d\ +\x96\xd9\xa5T}\x10\xc3\xc1\ +[x\x0d\xf8\x03\x1e.gD\xab\x84\xaaoPg2\ +\xed\x13P\xe7\xd2U\x0b\x0c3>\xda\x96>\xca\xf8@\ +F\xd3\xfb\x16,\xa5\x0b\x86\x0f\xe8\x93ZG,\xa9\x99\ +go\xc2\x12\x09}\xf1\xb5\xbd\x16\xc7\x18\xc4a\xd5n\ +;\x5c\x09\xcaw\xd2\x06\x10$\xaa\x89$$\xa86\xb2\ +\xa8\x0d\x01\x14<\xff\x15\xc0\x7f\xa5\xb8\x8e\xf1\xa8\xf7\xbc\ +\x1f`H\xc2P\x92\xca\xf0\x9a\xe5xL\xb7\x0b\xaa\x07\ +\xe5kM\x80q\xbe\x98\xfc\x92\xa8\x18\xd6UCK\xfa\ +-\xc6\xf5\xa7\xe3&\xd4\xc6\xcd\x9dD) \xd4\x0f\xe2\ +\x0aGp\x7f\xe3(l\x1ab4G\x1a\x02\x0b\xedU\ +\x1bw\xc8D\xcf\x92\xeb'\x94\x0e\x19r\x0d\x14H\xa5\ +\xdcA\x93\xa4S^\xd9\xb8\xd2\x15/\xe5\x0a1(j\ +;\x17\xe8\xd4\xa6\x0a\xe2P\xb3&`\x04\x00\xb9#\xae\ +\xa5\x9bts\xd6\xbf\x13\x1dq\xae]\xbc\xda\xc6\xed\xca\ +\xba\x19\x00\xed\x09\xc0\xfac\x0b\xeb=\xe5\xe7W\xd9\x95\ +\xbc\x0a\xa4\x9c\xf7\xe5\x00\xa0\xc6\xd2\xe1\x00\xd9m\x13V\ +\xc0u\xcbI!k\xc8:\xea\xd6\x9e[-\xe4\xabZ\ +\x1d\xcbI\x9bJ\x01@1,\x5c\x9dIu\xf2\xa9\xe6\ +\x1b\x0a\xd4\xe6\x1d\xce\xa2^>\xca\xd3\xb3\xfan\x00z\ +\xbc\x82\xaa\x92\x06\xcfH\x81\xd5\xd7\x87\x94Xs\x01\x00\ +@\x8bG!\xb2\x06\xad\x0dhu\xd4\xf58\x86\xc8\xa5\ +\xb4LXJ\x1b\xaf\x1d\xa4r\xb2p\x94\x9e\x88\xc2\xe3\ +\xeb\xb1\xf0\xda\x1e\x8b\xad\xe9\xc2\xdaQ(!-\x8ep\ +\xa6S\xcau\xa2xl\xa9\x94\xad\xe3\xe3\xbd\x9dM\x92\ +\xcb\x02B\xa9\xceg\x00$\xa5}\xbc\xaa`V\xbd\x0d\ +\xf47m\x81\x03\x08\x88N\x0bw\x07K\xab\xd1'\x06\ +#\xe2\xa8-\xe2\xaet\xfc|\xb2\xcbkE\xa7\x02R\ +@\xa8=\x06U\x84\x80s \xc4\xa8\xf7\xbf6M\xba\ +\xe6\x81\x17[\xb4\xd5\xd0I[\xb3\xf1\x06\xa9M#\xc4\ +\xc7Q\xdc\xf6\x18\xe4O\x9d9!\x14(3\xbd\x93\xfc\ +_\x8d\xa5.N\xe0\x22LHt\xea\x96\xd2\x15\xb5c\ +\xf1\xb7\xcd\xc2\xd4\xb5\xab\x96\x98\xd44\x06\xfb\x1c5w\ +b\xa7<\x0c\xae/Y[\xc0\xb5\x07Q\xcd\x0c\xb4+\ +Y\xe2b\x94\xe6\xb1\x85P\xdc\x15 p\x00`p\xdc\ +\xce\xa0\x025m\xac\xb6\xd8\xdcJ\x8b\x8d\xa2\xfc\xdc2\ +\x8b\x03\x00I%\xb5\xe6\xab\xed\xb4(\xd6V6\xb6g\ +u\xb8\xfc\xe6\xab\xaf\xadu\xfb\x0b'M\x9b\xef\xadv\ +\xed\xb5\xe9\x8c\x1d\x81\xa0\x88<\xba\x80\x10\xe5dJ\x8b\ +^ZA\x94ruT\xccM'\xe1\x11-\x19k\xea\ +\xf5\x09$\x0f\xd1\x8a\xe5\xf8]\x97\x16fA\x1e\xfd\xb0\ +k\xb5sMR\xf95\xc0\xf5\xf6V\x22\x0am\xb5\x12\ +\xbc\x18\xa0\x8c\x85\xa0^\xa9\xd0\xc6\xd5\x06\xbb\x5cV\xef\ +\xe4J)\xafX\xef\x15\x81\xbaX\x96\x8d\xe0\xe1\xae\x10\ +\xea.c\xcdZ\xb2\xbdR\xa6\x15\xbc\x01\xaf\xaa\x97W\ +\xb7\x9a\x87\xb7P\xb7\xcf+Xz\x1c\x96\xee6\xbcJ\ +\xe1\x8c\x9d:\x84\x88\xdc\xb9\x13\xd7!\x80iJ\xf9\x5c\ +}\xa1j\x0c\xe0\x1bM\xda/\x00\xf9\xd3\xfe\x82*\xc6\ +\xb9R}\x02\x89\x0bj\x11\x9b\xe4\xbc\x00\x1e@5\xfa\ +\xe7\xa2\x8a\x91d\x00\xa1\x06\x8f)\xda\xc0\xd10\xe8\x00\ +q\xd1\xcd#\xbd\x1d2\x87\xa2}j\x00!\xe9\x00\x10\ +\xe4\xab*\x16I\x87P\xa6\x83\xc0t\xd2\x9b\x0c\x09D\ +'\xa3\x01 \xa9\xbc\x09Ik\x10:E\x04G]\xbe\ ++q\x1d-.r\xe1\x0b\x008f\xcc \x16\xe1\xfe\ +\xb5K(\x0f\xeb\xcf\xad\xb28\x00\xe0$\xaf\xd2\xe2\x09\ +\x05\xc9e\x8d\x16h\xe8\xb3<\xbcT\xd5\xf4\xb1\xb5\x5c\ +}f\xdd\x07_Y\xff\xb5\x9fl\xe0\xc6/\xd6\x7f\xfd\ +'\xeb:\xfc\xceZw\xbe\xc0+\xbc\xb2rMH\xc9\ +\xf2U\xd9\xab\xb5\x07\xc4\xcd\xad\xbb\xa5d\x08\xe2\xa8W\ +\xfe\x95\xaf\x0a\xa5\xf9\xd7V\xbc\xf8\xc6\x8a\x17^Af\ +\x9fZ.\x9fQM\x83\x96\xbbS Rj,\xe9\xdc\ +\xb3\x00\xeav:\xc3Q\xca$\xb8\xe9\xb2\x1a\x94]\x85\ +\xb2+\xedRq\x85'E\x95\xc4\xf8j\x040\xe3\xd2\ +\xb5\x1fB\xa2c\xebuZ\xa9\xb7\xe3\x19\x00`\xcd*\ +\xe2p\xe5\xe9H,\xe9`,\xc6)\x89\x97\x07\x15\xc9\ +\x83\xe1\xabg\x80*\x8a\xd5\x03\xc0G\xb6\xa2\xce\xef.\ +=\xd7\x8a\xa8\x13\x11X\xad\x8a\x02\x08M\xdei1\x8c\ +\xb1VG\x91\x98\x14\xbeT\x1d)u\xfc\xfa\x85\xb83\ +\xef\xcf\xdd\xb3v\xd4&\xba\xb3\xf0\x11\xd7\xf2\x15\xb4\x91\ +\x93\xea\xfc_50T'\x0f\x9f:j!R\xbej\ +\xd9\xd4L!]\x8b,u\xe3\xe6\xab\x1bs\xe2\x87\x95\ +\xfa\xb5\xcbV\x0c\x15I'\xeb\x10\x08R\xe5\xa6\xceE\ +uj\x0e\x08nO\x9c6n\xf0\xa0\xe7\xa9\x91\x068\ +V\xbb\x84\xf2\x19\xd4\xbcZ\x8b\xcf\xab\xb3x\xde\xc7\x17\ +\xeaL\xfdF\xe2\x7f\xbb\x05[\x86-\x7fp\xc5j\x16\ +nZ\xc7\xeek\x14\xff\xbd\x8d\xde\xf9\x93M\xde\xff\x0b\ +\xf2O6v\xfb7\x1b\xbc\xfe3\x7f\xfb\xda\xeaV^\ +[\xa9V:\xc7\xceP\xa8\x94O\xe6\xa2\xe5or\xe9\ +\x82I\xd5\xfd=\x810\xbe\xb4\xd2\xa5\xf7V\xbe\xfa\x95\ +\x95\xaf!+\x9f[\xf1\xfc\x0b\xcb\x1b\xbb\x0d\x00v\xcd\ +G\xea\x9c\xaceV\xc5\xe7|\xac\x99\xfb\xba\x22\x80\xe6\ +\xe3\xa1\xc4M\x0a+\x01E\xb9]*(\xb5\xcf\x0aJ\ +\xec\xff\xc8/\xb6\xcf\xf2Kx_\xc6\xef\x00\x81B\x19\ +\xf7\xef\xb6\xbd\xb9\xddO\x00\xe0|w\xf3\x15m\x93\xc7\ +8\xa5\xf8x\x94\xa5\xbd\x09\xf1\x8ca\x1cc\x96\xc0\xf8\ +%5O[\xaa\xb6\xb4\x93\x96\xaa\xdd\x5c\x96Rp\xbc\ +\x96j\x17\xb3\xdc\x11{\xea\x18Jz\xde\xab\xad\xe8{\ +xf\xa5\xb2\xab\xaeXG\xfaIS\xdf\x07\xc6<\xc6\ +\x1d\x09'+\xc4%\xbb\xd6\xae\x88\xb6\x86\xab\xe3D\x12\ +\xe8s\x1cAa\x02Q\xd7n5l\xd6\xe6\xcaT\x14\ +\x95&\x104k\xcb\xb8\xb6Z\xc3l% L;n\ +3\x1a\xa6\xcd\x87{\xf4#\x01\x09H\xf5K\x88G>\ +\xcdnq\xf14\xae\xab\xefQgL\xed\xd8ueP\ +\x02\x01\x0f\xecR\x15\xc5)\x15\xach\xbf\x1f\xec\xf8S\ +\xff^$\xbe\x88\xd8\xc7\x80%\x12\x13\x93\xcb\xdb,\x0d\ +\xb7\x1bl\x1d\xb3\xbc\xa15\xab^\xbci\x9d\xfbol\ +\xe8\xf4G\x9bz\xf8\x17\x9b\x7f\xaa\x16r\xffl\xf3\x8f\ +\xff\x93M\xdd\xfb\x8b\x0d]\xff\xd5\xda\xb7\xbf\xb1\x1aY\ +\xf5\xc4#\xcb\x1b\xc1\xe2q\xfd*\x0a\x91\x07P\x9fb\ +\x9d\xc3S\xba\xf8\xce*\xd6\xbf\xb1\xaa\xad\xef\xadz\xfb\ +{\xab\xda\xfc\x06\x10\xbc\xb5B\xb5zQ\x06\x84\xe5\xa5\ +\x08\x00\x10\xb6\xd8|brn\x1d\x82\xc5\xe7b\xddx\ +\xa7\xcb\xf0\x93Kye\xf6Y\x1e\xca\xcf+F\xf4\x0a\ +\x18\x08Y\x97\x00\xc8\xe5\x02\xc8,^\xc3c\xf7\xda\xcc\ +\xaa\x0d\xac\x10b\xad\xe9\xe3\xd6]U\x10c\xa6\x1dC\ +I\xda4\xc2\xf5\xd4>.\xa5U\xedo\x08\xbb\xf0.\ +\x9d2\x1a\x06\xb4Q\xf5!\x9ay\xce\xeb3R\xcd\xc7\ +\x16\x19\xbbOv\x02\x7fqU\xc2\x00A \xe8\xd4v\ +\xb5U<\x01 \xc0K\xeb\x94\x96\x18\x1dh\xa0\xe3S\ +\xd3Z=\x05j\x81\xc7k'J*\xe8\xbaN\x11\x9f\ +a\x91\x02\xc3\xc5\x86JmLt\x00\xc0\x8au\x18t\ +:\xb9\xa7+-\x97\xebo&,`\x19\xb2\x0eu\xe7\ +\xcel\xbc\x10~\xe6A\xfc\xc4'\x1fq(]\xff\x0f\ +QQ\x8bV\xe5\xaa\x0e\x04\x00@\xd7U\x9f}\xed{\ +s\x84E[\xb9\xcaa\xb2e\x10B\xb7\xe9\x13 \xb8\ +\xadbJ\x15\xc9\x8f\x89\x85\xc9\x95\x9d|W\x8f\x05Z\ +\xd5\x81t\xd9\xaa\x16\xae[\xcf\xd1\x1b\x9b\xba\xff\xb3-\ +\xbf\xfcO\xb6\xf9\xee\xdfl\x0bY{\xf5/\xb6\xf0\xc4\ +\x03\xc1\xe0\xf5?Z\xfb\xce\xf7V\xb7\xfc\xc1\xcag^\ +X\xd1\xc4C,\x1b\xb7\x8f\xe4M>\xb4\x82\xd9\x17V\ +\xb2\xf4\xb9\x95_\xfdhU\xdb?Z\xf5.\xb2\xf3\xd1\ +*7>w\xd3\xday\xea\x0d\xd8\xb5\x0e\xd0\x89\xa9J\ +\xab\xc4\xd8\x0b\xb0^\x01!\x8f\xf8\x8e\x87\xd2\xb6\xf6\xcb\ +(Z\xcavR(\xe1wE\x00E\x8d/\xd4\x99\x9c\ +X\x9fX\xa6\xe6\xd0=\xa4\xb1\xfd\x96\xceX\xc8K\xfa\ +[\xe7,\xb3c\xd5\xed\xb1P\x15\x93\x8aB$\x01\x85\ +\x1eD\xb3\xae*V\x8dL\xdc\xb3\xfc\xb9\xe7V\xac\xb5\ +\x86\xb5/\xadd\xf5\x0b+Zz\xc7\xef^\x98\xaa\xab\ +\xd5\xa2.\xa4\xa6\xdb\x9a\xacS}\x81&\xf0:5\xdb\ +\xab)\xfc%\x8bq\xdd/5\x1f\xde\xef\x1dk\xaa\xc9\ +\x1eW\x97\x8e\xabH\xc5\x92\xbdmH\xda\x90\x88\x97\x10\ +\xc9@1\xeaJ\xe5\x1a\x16a\xc9N\xb4\x95\x5cn\x1f\ +\xe5\xeb\xbc^\x95\x85\xf9\x897\x01$\xb3\x05i\xf6$\ +\xd0\x041T\x01\x86\x00@\xacW\x9f\x80\x14\xc0\xe5\xfa\ +\xef\xd6\x9cw\xc1\xc2[\x88\xc4x\x1b\x17`\xd3\xb5\x0c\ +\xb0\x03\xc2\x10\x96\xc1@\xab\x97\xaf\xd2\xc3r\x08\x90\xd2\ +\x1dBS2\xe45\xb5\xae\x17\xee1d\xd9=sV\ +1{h\x03\xc7/m\xf9\xe9\xcf\xb6\xf3\xfeov\xfc\ +\xf5\xbf\xd8\xe1\x97\x7f\xb7\xf5W\xffds\x8f\x7f\x03\x18\ +\x7f\xb2\xd1\xdb\x7f\x86\x1f\xfcf\x1d{?[\xe3U\xbc\ +\xc1\xf2{+\x9b\xf7\xe6\xd3\x8bt\xf6\xde\xe2{+]\ +\xf9\xda\xca\xae~o\xe5\x9b?X\xd9\xe6\xb7\xbc\xff`\ +%+/\xadp\xee>dP\x99\x80V\xd9\x96\x1c\x11\ +L\x86Y'\xc0\xd6\xe3\x8aa\xeeE\xb0\xf5\x22b\xb8\ +B\x83\xbc\x03\x96-\xa6\xaf\x8e&jX\xf1\x0f\xf2\xd6\ +\xe7\x9e_\x86\x90\x81\xe7\x0b0\x86\xd9(%\xa7g\xc3\ +\xf2\x06\x0f\xac\x88\xb0\xa4C5K\xa6\x1fX\xf1\xf4#\ ++\x82\x84\xea\x90\xa8\xbc\xf1\xfbp\x16\x9dJ\xaa\xc3\xa3\ +^[\xd9\xea\x07\xab\xe4\xfe\xaa\xf0R\x95\xdb\xdfY\xd9\ +\xc6\xd7V\xb4\xf2\xfe\x13\x08\x94\xc1d\x13\x1eT\xec\x93\ +\xd9{@\xc6\x06\x90H\xdf\xd5\xe9-FK\x8b\x92\x5c\ +\xbdB\x88t\x14Z\x16)\x8e\x90\xa2\xf9~\xafF\xcd\ +[\xf9K\xc3\xa2\xd3\x9b\xd4C\xe7\xbc\x8f\x8e\xdc=\x1e\ +\xc3\xc5|Y\xbe\x0aBu\xaaV\x87\xb2\x00\xf2b\x80\ +\x94\xc9wh.Z\xb5\x81\x22M>\xbeK\xd5+\xa9\ +R8^%\xd9\x91P\xb8\x07a\xc5\x01Lupn\ +\x87\xeb<\xa2-O\xbc\x0a\x0c\x80\xce\xb1W\x97!\x88\ +\xa3\x88\xa8B^k\x19\xc4\xba>>\xd3\xc7\xfd\x0dr\ +\xcdI+\x1e\xdf\xb0\x9e\xbd\xfb\xb6\xf0\xe0\x83m\xbc\xfc\ +\xde\xf6\xde\xfdd[\xaf\x7f\xb0\xb9\x07_\xd9\xf0\xe9\x17\ +\x84\x86\x8f6t\xf6\x8b\x0d\xdc\xfa\xcdz\x00A\xfb\xc1\ +/\xd6\xc4\xc0\xd5`A\xe5\x00\xa1\x84\xb8_\xb2\xf2\x85\ +\x95\xae\x7fk\xa5\x1b\xdfY\xc9\xc6\xb7V\xb4\xf6\xc1\x0a\ +\x96_X\xee\x9c\x8a8U\xc4\xa2\x85\xa3],t\xc3\ +2\xdb\xd7\xf0x\xb0\xecZ\xf2\xfd\xea\x09\x94\xab\xedm\ +J\xb7\xc4gd8\xda\xc8y!c\xa6^\xca:\x80\ +J\x9e\xd3\xa7\x9eCx\xe0l\xc6L\x8aW\xef\xdf\xb2\ +\xc9S\xab\xc6\xcb\xd4\xaf\xbd!{\xf9\xc2\x9a\xb7\xbe\xb6\ +\xa6-\xd5=|c\xf5\xeb_Y\x0d\x0a\xafZA\xb0\ +\xf6\xaa\xf5\xaf\xadz\xf3\xa3\xd5\xec\xfc\xe0\xbcT\x15\xaf\ +\xe5[\x1f\xadd\xfdK+\x5c|ky\x00:g\xe2\ +\xb1\xa9\x862\x9bP\x97\xad\x22\x95\xe1\x1b\x08\x1el\xe4\ +\xba\xc5\xe8(2\x15|\xe4\xcf=\xb2\xfcY\xefT*\ +\xd5\xbe\xab\xc6N\x85\x94Z\xb7\x16\x18$\xaa\xb3\xcbt\ +\x8b%0L\xadY+\x07V\x9e\ +B'\x89\xe7\xe9g\x17W\xdb\ +\xa7\xb9\xcb]\xc8DP\x04* 0\x85\x1c\x05E\xa0\ +\xc4\x04\xde\x03!\x00\xe7%8\x9fB\xaa~\xccn\x05\ +h\xc2x\xdaF\x04\xd49$7\xd1\xdf\x06\xf6\x9d\x12\ +h\xf2\xec\xbe \xe5e\x08\xe0}\x04\xfd\x1d\xb2\x03|\ +\x00q'\x04\xd2\x80\xc6\x0e\xc6\xa4[\x8c\xa9r\xbff\ +\xd1\xb7\x01\xbcr?\xa1\xbe\xcc\x1a\xcb\xe4\x9c\x8c\x00\x9a\ +y9\xa0o\xa1?\x06\x197\x87\x1d\xe8\xea\xce!\x1b\ +n\x12\xed7\x12<\x8b!\xf4\x880\xcb\x04\xf4c\xc8\ +$\x10\x12\xde+<\x9e\x9c+^$$\x91\x18\x02G\ +\xacg\x81\x1e;\xd0C<\x02j\xd0\xc3\x90\xab\xc03\ +\x11\xf1\xb2*\x22\x1c\x91\x9a>;&\xf0m\xd2\x89X\ +\x14X\xf3\xa3\xee\xb3\xecdB\x8e\xd9\xb9\xd1\xd6\xc9@\ +>\xfa\xb5\xf3\xf5\x84\x90\xcf\x8a\xc0\x84\xdb\x87\x8e\x0f\x16\ +\xde\xdbiw3\x00\xbd\x0aI\xd9\xbe3\xc3\xe1,\xfd\ +\x8e\xa3\x96G\xbb,\xd8#y\x03d\xcc\x04\xf6LI\ +5\x15\xf4\x18\xcd\xc8!\x81&\x13x\xb2\xb0G\xa8\x98\ +\xd7\x97J\xea\x93v5\xda\xdbu\xf0f\x14\x07\x92\xfc\ +\xb1y\xcd\xadt\xa3\xf6\xa1\xb7\xd0\x1e\x08\xf6HR9\ +\x17\x9d.Q\x88JMX\xe3E\x11\xc8\xf9\x91\x84\xf7\ +6\x92\x90d\xdf\x972\x84\xd10\xd7\xf9\x22\x02'^\ +\xd7?\xed\xed\x0f\xbc\xcbE!\xdb\xbc\xce\x86SF_\ +w\x8ev\x01Hy\xe1\x9cN\xb5.\xcf\xf0\x0d\xfa:\ +G\x83\xaa\xe2\x16:\x1d\xdb\x0d\xe0\x5c\x0f;d\x81\xc7\ +k\xf3\xee\x13\xb6\xb6_\x18x\x11B\xac\xd8\xfc.\xa5\ +\x1f`t\x8aZ\x1d\xe5v\x8c\xd0M\xa6#$\x9db\ +1&\xcfu\xde\xb2q\x9f\x90\x9d\x86\xbe\xbd\xe8<\xc7\ +\xfb2\xf7\x0f\xe6\x1c\xe5c!G\x1c\xdd\x88\x0e\xe8\x1a\ +\x85\x8f\xea.\xef\x842G\xf0z\x99e\x88\xdb\xbc\x96\ +\xabn\xecx\xf1_\xa0JA\x0a\x0a Icons / Notifi\ +cation / Error -\ + black\x0a \ + \x0a\ + \x0a \ + \x0a \ +\ +\x0a \ +\x0a\x0a\ +\x00\x00\x01u\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\ +\x00\x00\x01\xd0\xa2K@\xfc\x1f\ +\x84\x81\xfc\xff06\x10\xbf\x02\xf2\xe7\x00i9Z\xf8\ +\xd8\x02\x88\x9f\xa3Y\x08r\xc0_4>\x8c\xddHM\ +_G\x00\xf1?\xa8\xe1 \xfa/\x0c\xe3\xe0\x83\xd5\x02\ +\xf1\x1a \x9f\x91R\xcbA>\xff\x87\xc7\xc7\x84\xf83\ +(u\xc03\x12-\xc4\x16%n\xe4\xc6{>\x11q\ +N\x8c\x03\xae\x93\xeb\xfb\x8b0C\x09\xc49!>\xc8\ +\x0c}r\xf29H\xe3?\x0aC\x00\xc6\xaf!\xd5\x01\ +\x0e\x14Z\x88\xce_C\xaa\x03B\xa8\xec\x80\x03\xa4\xc6\ +\xbf\x0f\x09\xf9\x9e\x984\xb0\x95\xd4\x10P\xa7r\x08L\ +\x22\xd5\x01l\xd0\xb2\xfd?\x95\x1c\x10@N90\x9b\ +\x0a\x0e\x00\xe5\xa2\x9f@\xccDN9 \x0d3\x84\x82\ +4\x00\xd2\xdfBIQ\x5cOa\x08\xdc\x01\xd2\xcc\x94\ +V\xc5k\xc8t\xc0\x1b _\x99\x1am\x01F \x9e\ +\x81\xa5\x01\x82+\xceAl\x90\xcf\x95\xa9\xdd\x1ar\x07\ +\x1az\x13\x9a\xaf\xe1\x8eA\xe3\xff\x04\xc59\x10\xb3\xd0\ +\xb2=\xa8\x0f\xc4\xb5@\xbc\x16h\xd1! \xbd\x1d\x88\ +\xa7\x00q \x90\xcf\xcc0\x0aF\xc1( \x11\x00\x00\ +\x90\xbf\xd0E\xdf\x04S\xa8\x00\x00\x00\x00IEND\ +\xaeB`\x82\ +\x00\x00\x02\xaa\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\ +\x00\x00\x02qIDATx\xda\xedWMHTQ\ +\x14\xd6q,\x0c\x1db\xd0d\xa86\x814!\x11A\ +\x90\x92H\x14\xc4@\xaef\x11\xb5\x10l'\xe4l\xc4\ +\x85\xcb\x1aA\x88@\xc2E0\xad\x1c1h!\xd3\xa6\ +\x7f\x9a\x84\x90hg$$\xb6\xa84]\x88\x039\x8b\ +\x18)g\xf2;\xf0=8\x5c\xdfLo\x86\xb9\xd2b\ +\x1e||s\xcf\xb9\xef\xdes\xbew\xce}o\xea\xea\ +jW\xed*\xe3\xba>0\x14\xbbq3\xf6\x07w\ +\xe9q\x8d\x8fN\x00\x15+\x80\x88E\xbe\x0f\xe0\x97\xe0\ +\xa8\x11\x80\x1f\xf6\xcfF\x9f;\x9c\x01\xb7x\xad\x01\xd8\ +\xafJ{\x82g\xc0>\xbd\xc9)#\xab\x84\x11D\x08\ +\xf8i\xcc\xd9\x06\xcex\xad\x01U?\x82M\xa0IG\ +\x16fF\x1b|\xdb\xc9\xa4Qc\x81n\xd8w\xd4I\ +\x17\xf5\xda\x05\xac\x15\xb9oM6\xe7>M\xfa\xe60\ +#{\x0c\xf4\x02\x05\x8e{\x8cM\xae\xd1>\xec\x92\xa1\ +S\x039\xad\x00~\x1f\x06\xb6\xe8\x93\xb5\xbf\x01\x1b\xc5\ +\x14Hq<\xa0\x14\x09\x19\x1b\x9d.QK\x17E)\ +c\xfe\x0b*s\x8f\xe3\x1f\xa5\x14H)\xdb]\xda\xa4\ +\x00\x0fU\xd8A\x0f\xb8\xc6;\x8e}\x12\xc0?\x15P\ +\xf6I\xda\xbfK\xa1\x96\xd1UG0\xff53\x9f\x07\ +\xfbio\xf0\xac\x80\xf2\xddR5\x91\x04\xce;\xad\xa7\ +\xe6\xc8\xc2\xb2\xe9%9%\xd5\xf7\xc1}\xa0\xde\x98\xe7\ +]\x01\xe5\xef\x90\xd7\xadz\xcfK\xab}\x05/\x81\x97\ +\xc1\xeb\xf2\x1aV\xfeW\xe0\xb3.\xeb\x94\xaf\x80\x91\xe9\ +1`\x10\x90#y\x1e\xf8\x04,\x00r4'\xe4[\ +\x10h/q\xbf\xd4\xc0\xaa\x9b\x02'\x9d\xc8-\x7fU\ +\x1f\xe49\xb1G\x01\xe9\xe1\x1d\xf6\xf0\x09Ko\xd2\x03\ +\xc0C*\xbd\xe06a\x92\xcf\xf0\x17x\x0e\x9c\x06\xa7\ +\xab\xc4o\xc1\x19U#}\xc5\xa2\x1c\x01\x16Y\xa9\xab\ +U\xc6\x0a\xf0\x1e\x88xyV\x8d\x98\xd8Xe\xf6\xff\ +\x97\x7f\xf7v\x01&\xc7\xb3\xa0\x90\xee\xe83\x00\x00\x00\ +\x00IEND\xaeB`\x82\ +\x00\x00\x02\xa5\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22?>\x0a\x0a Icons / Notifi\ +cation / Warning\ +\x0a \x0a \x0a \x0a \x0a \x0a\x0a\ +\x00\x00\x06}\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22?>\x0a\x0a Icons / Icon G\ +rid\x0a \ +\x0a <\ +path d=\x22M7.02749\ +543,18.2117232 C\ +7.8834099,18.038\ +7856 8.54248262,\ +17.8471758 8.883\ +41584,17.6633902\ + L9.13660094,17.\ +5269066 L9.41318\ +015,17.6058648 C\ +10.2365316,17.84\ +09162 11.1075671\ +,17.9625414 12,1\ +7.9625414 C16.32\ +37915,17.9625414\ + 19.7799758,15.1\ +162719 19.779975\ +8,11.6803149 C19\ +.7799758,8.24435\ +789 16.3237915,5\ +.39808842 12,5.3\ +9808842 C7.67620\ +852,5.39808842 4\ +.22002417,8.2443\ +5789 4.22002417,\ +11.6803149 C4.22\ +002417,13.43386 \ +5.11977547,15.08\ +21543 6.6930318,\ +16.269688 L7.214\ +92385,16.6636253\ + L6.12154393,18.\ +3763334 C6.43148\ +919,18.3255971 6\ +.73578148,18.270\ +664 7.02749543,1\ +8.2117232 Z M3.9\ +4487569,20.05404\ +83 L5.67352379,1\ +7.3462342 C3.805\ +49981,15.9362024\ + 2.63427705,13.9\ +10191 2.63427705\ +,11.6589 C2.6342\ +7705,7.3991563 6\ +.82745404,3.9459\ +5171 12,3.945951\ +71 C17.172546,3.\ +94595171 21.3657\ +229,7.3991563 21\ +.3657229,11.6589\ + C21.3657229,15.\ +9186438 17.17254\ +6,19.3718483 12,\ +19.3718483 C10.9\ +251584,19.371848\ +3 9.89260571,19.\ +2227398 8.931178\ +29,18.9482703 C7\ +.61917454,19.655\ +5273 3.94487569,\ +20.0540483 3.944\ +87569,20.0540483\ + Z\x22 id=\x22path-1\x22>\ +\x0a \x0a \x0a <\ +g id=\x22Group\x22 tra\ +nsform=\x22translat\ +e(-2.000000, -3.\ +000000)\x22>\x0a \ + \x0a \ + \ +\x0a \ + \x0a \ + \x0a \ + \x0a \ +\x0a\x0a\ +\x00\x00\x01\x12\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\ +\x00\x00\x00\xd9IDATx\xdac`\x18\x05\xa3`\ +\x14\x8c\x82\xa1\x06\x22\x13s\xd9\x818\x15\x887G$\ +\xe4\x5c\x00\xd2\x87\x80\xb8\x1b\x88Uhn9\xd0BG\ +\xa0Eo\x80\xf8?\x08\x03\xf9\xffal(\xbf\x87\x96\ +>w\xc2b\xe1_4>\x88^F\x0b\x9f\xb3\x03\xf1\ +k\x98\xa50\x0c\xe4\xff\xc3\xc2\x07\xa9\x09\xa2\xb6\xefS\ +q\xf8\x18\x17\xff4\xb5\x1d\xb0\x91D\x07\x800\x0f5\ +\x1dp\x9e\x0c\x07(R3\x0d\x1c\x84&\xb0\x7fD\xa4\ +\x81\xbf\xd0t N\xcd\x10\xe8\x221\x04^\x011#\ +5\x1d\xa0\x04\xb5\xe0\x1f\x91\x0e\xe8\xa0E9\xd0Cd\ +9\xf0\x0c\x889hU\x18-\x83\xc6/,4\x90\xe3\ +\x1cl9\x90V\xa1u]\x10\x04\xca\xe7hE1(\ +\xce;\x81|\x0e\x06z\x01P>\x07Z\xa8\x08\xa4\xc5\ +\xa9\x9a\xe0F\xc1(\x18\x05\xa3\x80\xde\x00\x00*\x106\ +\x97\x13c\xdc\xaf\x00\x00\x00\x00IEND\xaeB`\ +\x82\ +\x00\x00\x01\xf5\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\ +\x00\x00\x01\xbcIDATx\xdac`\x18\x05\xa3\x80\ +D\x10\x91\x90#\x06\xc4\xd7\x80\xf8jdb\xeeU\x10\ +\x0d\xc47\x81\xb8\x84.\x0e\x00Z\xaa\x02\xc4\xffA\x18\ +h\xe9\x7f\x18\x1b\x88\x17\xd1\xcb\x01\xcaH\x0e\xf8\x8b\xe4\ +\x80\x05#\xc3\x01@KU@A\x0f\xb5\xfc\x1f\x88\x86\ +\xf2\x17\x8c\x98(P\xc4\xe1\x80\xf9\xb4\xb4T\x0e\x88u\ +\x81\x16j\x01\xe9(\x1c\x0e\xd8\x0b\xe4k\x00i\x1d(\ +f\xa1V\x9c3\x02\xf1mX\x96\x83\xc5?Z\x1a\xf8\ +\x8b&\x0f\xc2\xce\xd4\x0c\x01\x17\xa8\xe1\xff\x90|\x8c\x1e\ +\x02\xc8\xf2\x1bi\x11\x0d\xe9h\x05\x0f6\x07\x80\xe8\xab\ +\xe4Z\xc0NDtL'\xe0\x80W@Z\x92\x80=\ +L\xd8\x0cV\x06\xe27@\xc9\x07@\xba\x06\x14\xefx\ +\x1c\xb1\x17K9\x00\xa2\xff\x00\xf9\x16\xf8\xea\x10\xa0\xfc\ +J \xfd\x1c\x88\xeb\xd1]\xa5\x87V\xb6o\xc7\xe3\x03\ +\x1e \xbe\x8f%\x04\xa2\xf0\xe8\x11\x02\xe2gH\xe6\xcf\ +CW\xa0\x8b\xc5\xc0\xe9x\x0c\x94\x05\xe2\x1fH\x06\xb6\ +\x11\x08\xf6#h\xe6\xcf%\xc6\x01 ~\x00\x1eC\x9d\ +\xa1q\xbe\x94\x80\xe5yX\xd2\xcc\x5c\xf4\xf8\xd1\x85\xfa\ +\x069_\x83\xb2\xd47 \xadFA\xce1FJ#\ +\xb04\x03r\x08\xd1!\x00\xa2_\x03\xb1\x12\x99\x96\x7f\ +\xc0\x91k\x88v\x00\x8c\xff\x05\x88#\x88\xb4\x98\x0b\x88\ +\xab\x81\xf8/\x9er\x83d\x07\xc0\xf8\x17\x81t\x19\x10\ +\x9b\x03\xb1(\x90\xcf\x0b\xa2\xa1\xb9(\x06T%\x03\xe9\ +7x\xf4\x93\x94\x06\xfebI\x13\xc8e\xfd\x7f<|\ +l\xfa\xc9J\x03\xb4\xe2c8@\x9b\xce\x0e\x98\x8e\xad\ +t{KDeC-~\x18\xb6\xb2:\x84\x848\xa6\ +\x84\xbf\x1e_m\xa7\x04TT\x07\xc4\x13\x81x\x02\x90\ +?\x01D\xc30\x85\xfc. \xdfo\xb4k\x87\x0e\x00\ +\x0bqL\xd4T\x13W`\x00\x00\x00\x00IEND\ +\xaeB`\x82\ +\x00\x00\x00\xd5\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xffa\ +\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\ +\x04gAMA\x00\x00\xb1\x8f\x0b\xfca\x05\x00\x00\x00\ +\x09pHYs\x00\x00\x0e\xc3\x00\x00\x0e\xc3\x01\xc7o\ +\xa8d\x00\x00\x00jIDAT8Oc\xfc\xff\xff\ +?\x03%\x80\x09Jc\x80\xc522\xffA\x18\xca\xc5\ +\x09\xb0\x1a@\x8cF\x18\x00{\x01\x9f\x86\xd8'O\x18\ +\xa1L\xac\x00\xa7\x17`\x80\x90k\xc0\x06\x10\xb2\x05\x9f\ +!\x04]\x00\x03 C\xb0\x19D0\x0c`\x00\x97+\ +\x09\xba\x00\xa4\x11\x9f\x17Q\x0c \xa4\x18\x1b\xc0\x99\x12\ +a\xde\x22d \xed\x922\xb1`\xc8\x1b\xc0\xc0\x00\x00\ +\x1d[2\xc1\xc0t\xc2\x0d\x00\x00\x00\x00IEND\ +\xaeB`\x82\ +\x00\x00\x00\xeb\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\ +\x00\x00\x00\xb2IDATx\xdac`\x18\x05\xa3`\ +\x14\x8c\x82Q0\x14Adb\xae:\x10O\x8eH\xc8\ +\xd9\x0f\xa4\xd7\x00q8\xdd,\x07Z\x1a\x0f\xc4\x7f\x81\ +\xf8?\xd0\xe2\xff \x1a\x8a\xb7\x00\xf9\xcc\xb4\xb6\x1c\xe4\ +\xf3\xbf \x8b\xa1\x96\xc3\xd9P~\x1b\xad\x1d0\x19\xcd\ +Bt\x07\xbc\x05\xd2l\xb4t\xc0~\x02\x0e\xf8\x0d\xa4\ +\x15i\x99\xf8VA\xe3\xfb/\xd4\xf2\x7f06\x10\xff\ +\x03\xf2\xbf\x02i\x11Z\x86@\x18\x81\x108H\x8f,\ +\xb8\x19\xc9\xc2\x7fH\x0e\x00\xf9^\x95\x1e\x0e`\x06\xe2\ +6 ~\x0b\xb4\xf0\x0f\xc8b >\x04\xc4\xaat-\ +\x8c\x80\x96\xb3\x81\x12\x1c\x90\x16\x1d-\x9aG\xc1(\x18\ +\x05\xa3`H\x03\x00\xac\xe7\x98*\x92\x10\x95\xa4\x00\x00\ +\x00\x00IEND\xaeB`\x82\ +\x00\x00\x03\x0b\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\ +\x00\x00\x02\xd2IDATx\xda\xed\x97MH\x94Q\ +\x18\x85\xd5i\x0a-\x17\xba0\xcc1!\x88\xc2(\x0b\ +\x92\x5cLFn*\x88Z\x05J(\xd3&*4B\ +\xfbq\xd5\xa2\xc2 \xa4\xb2_Z\xb4\x88\x8aP\x82)\ +\x22\xab\x85\x14Q\x8b\x16\x81\xf4\xb7h!\x16\x95\x05-\ +\x8a\x8a\xd2t\xea\x1c8\x1f\xbc\xdc\xee7)\xe9H\xe0\ +\xc0\xe1r\xee\xf3\xcd\xbd\xef\xf7\xce\xfdy'+k\xea\ +\x83O\xdd\x96\xa6\x1d\xd0\xc1\x10\xb6\x11\xba\x09\x1d\x0e\xe1\ +\xab\xa0\x1b\xd0\xb1\xdaDc\xae\x87/\x86\x92\xd09\xf0\ +\xc2\xb0\x00NC\xbf\xf0@\x9b\xed\x87\xaff\x7f \xf8\ +\xf3\x0e_\x84\xfe\x94\xe1\xb7\x1c>\x1b\xfd?\x0c\x7f\xe2\ +\x0d\x00\xa0\x03\xe2C?\xed[\xc0?b\xbf\x94\xd2 \ +s\x0dOzx\xa5\xe1\x1d\x86\x07A\xac\xf7e\xa0Z\ +\x90\x0f\xd5\xaa\xaf0\xf8\x12t\xd9\xf0f\xf1\x5c\xf8\xef\ +\xe2]\xd0\x90x\xbbx\x04\xfe\xb5x\x0f4 \xde\xe9\ +\x0b`:\xf4N\x0f\x5cT\xdff\x13\x00S\xfdL\xbe\ +G\xbc\xc6\xf0\x95\xd0]\xf9\x97\xe2\xe5\x86\xd7A\x17\xe4\ +?\x86\xad\x83.=\xd0'\x7fI\xfe\x8d\xfcQ\xf9\xcf\ +P\x0etD\x9eY\x88@\xbb\xcd\x84\xb3\xa0\x9d\xc6\xe7\ +C\x9b\x8c/\xf7\xad\x83D\x90fh!\xf4J\xbeS\ +|\xad\xe1\xcb\xb9\xa0\xe4\x1f\x88/3|\x03tG\xbe\ +O\xbc\x18~D\xbc\xd5\x97\x81\x22\x13a\xb7\xf9\xcd\xeb\ +\xc5\xa3\xf0#\x1e\xbeO<\x1b\xfe\xbd\xf8}\xe8\x9b\xf8\ +I\xf3\x92\xbd\xe2\x8f\xc3v\xc3Cg\xdbq\x0b\xe5\x1b\ +\x9et8\x03*3\xfc\x84\xc3\xd9V\x1a\xbe\xc7\xf0\x12\ +_\x00+\x9c\x01\xf6:|\x01\xfa\x07\x0d?\xee\xd9\xf7\ +\x9f\x0c\xbf\xea\xf0(\xfa?\x88\xc7\xc2\xb2\x10\x87\xcep\ +M\x84\xf0\xa5\xd0)h;\xd3\xee\xe1\xf3\x98\x09\xa8\x85\ +\xbb\xcb\xc3K!\x9e\x9a\x05\xff\xfd\xfd\x11,Z\xae\x93\ +\xc8d\x04P\xaaE\xc8\x00\xf22\x1e\x00&\x8fa\xe2\ +a\xee\x14\xdf-\x98\x89\x0c\xc40\xf1\xb020)\x01\ +\x14+\x00\x1e\xc5\xd1L\xa5\xbd\x0c\x93q\xfbm\x85Z\ +\xb5\x06\x86\xa0&\xf6\xc1oC[0\x91o]\xe5\xdc\ +\xef)\xd6\x01\xc6\x0frmLt\xea\x1b\x9c\xa3\xd8\x9e\ +\x9c\xf1L\xfd\xfe\x87<\x01$2\xbd\x08\xaf\x99\xdb\xb3\ +}<\x16X\xceX\x9f\xc7\xc4/\xd0v\xff\xf3\x5c\x18\ +\xe8\xac\xb9>\xbfB\xcfY\xbb\xc17\xa2]\x92f\xa0\ +\xec4\x19\xca\x03\xafA{\x00\xba\x0d\xf5k\xdb\x06Y\ +\x8b\x87\x05\xe0\xde\xe7\xd4\x80J6\x06\xc4A\xe7Cs\ +T\xe5P%\xac\xffY\x09\xa1\xdd\x0f\xdd\x83\xbe\xa4\x19\ +\xef\x8f\x00\xaa\xa0]\xbc\xffY\xfbA\xd7\xa1\xb7\x7f\x19\ +`\xb4\x9e\xe5\xfaS\xd5\x98mh[tn\x14\x8df\ +\xa1\xf1-\x1b\xa0+P\xbf\xa9\xf9l\x9d\xefz\x9e\x0b\ +\xbd,V\xe0\xd7\xa0\x9d1\x9e'\xe1L\x0cZ\x01\xad\ +\xe3\xff\x07\xf8z\xd6\x8c\xacx\xa1\xd5,F\xd0N\x9b\ +\xfa\xb3;\x96\xcfo\xe5\xb5\xdc\x8eP\x05\x84\xb2\x00\x00\ +\x00\x00IEND\xaeB`\x82\ +\x00\x00\x00\xe0\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xffa\ +\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\ +\x04gAMA\x00\x00\xb1\x8f\x0b\xfca\x05\x00\x00\x00\ +\x09pHYs\x00\x00\x0e\xc3\x00\x00\x0e\xc3\x01\xc7o\ +\xa8d\x00\x00\x00uIDAT8O\xd5R\xed\x0e\ +\x80 \x08\xd4\xd6{\x83ON\x9d\x03\xe7,\xd0\xd5\xfa\ +\xd1m|(p\x0a\x9aE$\xbd\xc1\xa6\xf6\x82R\x8a\ +@t\xe9\xe2\x96\x00\x85D\x94u\x19b\x87\x1aOZ\ +-\xae\xc0\x0c\x98\xf94R\xfdQ\xa2\x18\xa49OI\ +\xdc!\xf6@K\xeeP\xc12;=\x8aWe\x09c\ +rTh\xd2Z\xb0\xa7\xb3\xeb\xea\xf6\x14\xeeO4\x92\ +\xd9\x93~\xf7\x95W\xf1{\x82\x94\x0e\xd4\x89\xe2k\x0c\ +\xdb\xee*\x00\x00\x00\x00IEND\xaeB`\x82\ +\x00\x00\x00\xa6\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\ +\x00\x00\x00mIDATx\xdac`\x18\x05\xa3`\ +\x14\x8c\x82Q0\x0a\x86*\x88L\xcc\xad\x89H\xc89\ +\x07\xa4\xd7\x00\xb1\x14\xbd-\xaf\x05\xe2\xff@\x07\xfc\x07\ +\xd1@\xfc\x98\xde\x0e8\x03u\xc0_\xa8\x03@X\x85\ +n\x0e\x00Z\xbc\x1a\xea\xfb\x7f@\x1a\x84A\x8e\xe1\xa2\ +g\x08H\x82\x82\x1d)\x0aR\x07$!\x02\x1d\xa0\x02\ +\xb4\x9ck4K\x8e\x82Q0\x0aF\xc1(\x18\xd2\x00\ +\x00e^3\xba\x9ez\xe49\x00\x00\x00\x00IEN\ +D\xaeB`\x82\ +\x00\x00\x00\xef\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\ +\x00\x00\x00\xb6IDATx\xdac`\x18\x05H \ +21\x97\x11\x88C\x81\xb8\x18\x88\x0b\xa9\x88\x8b\xa0\xd8\ +\x05\x9f\xe5\xdc@|\x19\x88\xff\xd3\x18o\xc0\xe5\x80i\ +d\x18\xf6\x1b)\xe4\xf0a\x16 \xf6\x01\xe27P}\ +)\xd8\x1cp\x85\x0c\x07\xfc!1\x8aM\xa1\xfaVb\ +\x93\xbcFk\x07@\xed\xf9\x00\xc4\x9b\x06\xd2\x01\xcf\x06\ +\xda\x01\xcfG\x1d0\xea\x80Q\x07\x8c:`\xd4\x01\xa3\ +\x0e\x18u\xc0\xa8\x03\x06\xad\x03\xae\xd3\xa1Q\xca\x8e\xb3\ +i\x0e\x14\xdcK\x07\x07\xac\x83\xea\xeb\xc6&iEf\ +Gc\x11\x10/#\x80W\x01\xf1{\xa8\xfa\xaf@,\ +\x8e\xcb\x85\xd6@|\x08\x88\xef\x92\x80\x1f\x10\x89\xef\x01\ +\xf1\x16 V\x1c\xed\x04#\x03\x00u\xbb\x07\x04\xef\x85\ +8\x87\x00\x00\x00\x00IEND\xaeB`\x82\ +\x00\x00\x00\xfe\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xffa\ +\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\ +\x04gAMA\x00\x00\xb1\x8f\x0b\xfca\x05\x00\x00\x00\ +\x09pHYs\x00\x00\x0e\xc3\x00\x00\x0e\xc3\x01\xc7o\ +\xa8d\x00\x00\x00\x93IDAT8O\xa5\x93[\x12\ +\xc0\x10\x0cE\xb1\x0d\xb6fs\xb55]G;!\x94\ +4\x8f\x0fg\xa6\xa3&rs\xe3\xe1\xaf\x18\x1fw@\ +\xc8w\xf5\xf8\xbf\x91k\xf5\xf0\xe1T$\x94\x98~\x0e\ +\xb4D*\xdcZ\xd0\x12J\xfa\x0a\x80[Z0\xe0(\ +\xb2\x8asn\x9b\xc0Z\x85Csh:\x18\xd0\xde\x07\ +\xe6\x1e\x0c$\x97\xa6\x03H\xd4Z\xdc\x04\xac\xc5\x1c\xe2\ +M\x1cmi\x82p\xacS\x80;\xe3\x15)\xdeZ\xe0\ +\x82tc!\x0e\xebp:\xe9\xf7@\xa9\xbc\xc2\xad;\ +\x7f\x8d8\xaap\xd6;\xce\xbd\xfa\x8fW\xbc\x9c\xc2\xae\ +\xed\x00\x00\x00\x00IEND\xaeB`\x82\ +\x00\x00\x00\x8b\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\ +\x00\x00\x00RIDATx\xdac`\x18\x05\xa3`\ +\x14\x8c\x82Q0\x0aF\x01\x99 21\xd77\x22!\ +\xe7.\x90\x9e7P\x0e\xb8\x0bt\xc0\x7f \x0d\xc2\xa6\ +tw\x00\xd0\xf29 \xcb\x81\xf4+ \x16\x1c\x90P\ +\x00Zl\x0at\x84\xe0h\x82\x1c\x05\xa3`\x14\x8c\x82\ +Q0\x0a(\x01\x00\x9bf\x16\x9e7\xad\x98\xae\x00\x00\ +\x00\x00IEND\xaeB`\x82\ +\x00\x00\x02\x02\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\ +\x00\x00\x01\xc9IDATx\xda\xedW\xbbJ\x03A\ +\x14MLc)XJTD\x91\xd8\xf9\x016V\x82\ +A4I\x13AH\xc4\x80\x8d\x96\x96NZ\xbf\xc4\xca\ +GH\x14T,\xf4\x17\xfc\x89<\xf0E\xea\xac\x9e\x0b\ +we\x18fwgv\xb2\x09B\x16\x0e7\xb3\x99\xdd\ +{\xee\x9c3\x8fM\xa5&\x97\xe3\xb5_=M\x8f+\ +\xf1N\xb9z\xd2F\xec\x03g#M\x8e\xc4\x05\xe0G\ +\x81\x18U\xe5%\xc0\x03(\xe9\x80\xa2\x8f\xc4I \xc1\ +\xae\x92P%@Q$Uy\x81\x13\x84\x11\xf0\xf8w\ +}\xd8\x95\x17Yg\x8f\x92J\xd0\xb5\xbd\xa1z\x02\xd5\ +\x14C4\x8fj\x0bg\xb7[&\xd4y\xa2\x1e\xb7\xf2\ +=\x03\xcd\x07\x86\x9e\x10\xb6\x95\x97\x14=eDy\xc0\ +\xcd\x13\xe4vIsb\xff\x02l\x02e\xb4?\x1cG\ +DDU\xbe\xae<\xd0dR\xb3\xc0\x14\xdaY\xc4\xae\ +\xa3'*a\x04\x84\xf4\xc0\x1d'\xaf\x01\xf4\xa2\x0e\xfe\ +\x9fG$\xb4\x1d\x084\xc3\x08\xe4Y\xaf\x16\xb7\x0f\xa5\ +\xf9O\xb1\x0b,\x02s\xc0{\x0cOP\xff\xf3(\x0f\ +T8\x1ehf\x01\xc5\x1e\x8fB\x96HX\x8e@\xcb\ +\xd4\x88G\xca4R_\xf8M$h$|9\x0c\x08\ +\x5c\x99&\xaf\x19\xbe\xb0Gr .\xf8\xc6\x0c\xe9\x7f\ +mtp\x91\xf6y\xcf@S\xeaG\xc6\x9c\x016\x02\ +\xf6\x0a\xbawo\xb3\x00]\xc6p\xf5\x160\x1d Y\ +\xc3v\x05\x5c\xc1\x83_\x16\x04\x1eX\xb6\xe3\xd8\x9ak\ +<\xb0\x06|\x1a\x10x\xe6\xfey\xcdn\xd9p\xdd\x05\ +s@?`\x9e\xd3\xbdW\xee\xb7-\xad\xf7\xf6\x9aG\ +\x8c\xc4\x12\x91\xd0h\xfe$\x9d\x8a\xd5u\xe2f\xd8'\ +\xa1\x9c/\x07'xD\xcc\x00\xcb\x12\xa1?\xcd\xd1N\ +'q\x16$O\xbcq\x82\x8ct\xffB\x22p;\x96\ +\x8f\x13\xda\x1d\x81\xd5\xc9\xf7\xe1\xbf\xbe~\x01}\x06\x5c\ +\x02\xc1U\xc6\xe7\x00\x00\x00\x00IEND\xaeB`\ +\x82\ +\x00\x00\x00\xd0\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xffa\ +\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\ +\x04gAMA\x00\x00\xb1\x8f\x0b\xfca\x05\x00\x00\x00\ +\x09pHYs\x00\x00\x0e\xc3\x00\x00\x0e\xc3\x01\xc7o\ +\xa8d\x00\x00\x00eIDAT8O\xd5\x91Q\x0e\ +\xc0 \x08Cq\xd9\xbd\x99'g\xe9\x06\x06q&\xea\ +\xcf\xb6\xf7SBLmC\x12\x11\x029\xe7{\xe8\xc0\ +\xcc\x09o\xa0\xba\xba\xd8T\x87\x89\x1fM\x1b\x00o2\ +UA\xc7\x8aa\x83\x88\x19.U\xf0\xec\xaa\x85^T\ +#&}\xbfBc\x00gs\xe7\xa3\xd6'~p\x05\ +$\xf3\xbb\xef]\xa1$X\x83\xe8\x04\x88\xd4H\x07\xd8\ +\xd9\x12\x13\x00\x00\x00\x00IEND\xaeB`\x82\ +\x00\x00\x01/\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xffa\ +\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\ +\x04gAMA\x00\x00\xb1\x8f\x0b\xfca\x05\x00\x00\x00\ +\x09pHYs\x00\x00\x0e\xc3\x00\x00\x0e\xc3\x01\xc7o\ +\xa8d\x00\x00\x00\xc4IDAT8O\xa5\x92\xd1\x0d\ +\xc3 \x0cD\x01E\xcd\x10\xcd\x0e\xedB\x99.\x0b\xa5\ +;\xa4CD\x8d\x94\xf6\x5c\x83\x8ck\xc3G\x9fD\x04\ +\x0e\x1cg\x9b\xf8Z/g\xf8\x834\xdc\xf7\xc8\xf3\x8a\ +\xe1\xb6G\x0c^\xba\xa4c\x1d\x7f\x1c@t\x99&\xd3\ +\x99\x16N\xf8\xe4`\x1e\xcb\xd59\xfc\x11>\x1e\xe3\x89\ +\xc1\xa1@5\xa0C\xce\x8d\xf3s\x8b\x96\xcb\x0c9\x80\ +\xe2\xbcmf\xbep\xe3\xd5\x09\x90@\x0f\x12\xe1\xf48\ +T\xe8\xa7\xc0\xced\xde\x92\xca\x016\xcbT0\xd7E\ +\xd3\x14\x01\xb9\x19\x85\xe3p\x17\xf7%\xe6|[\xb7\xa3\ +\xb8\xc5\x81\xae\xb4\xb6nu\x02\xed%\x01z \xaa\xd7\ +\xba\xe2\xf8o\x89\x90@\xeb\xa1H\xac}U\x17$\xad\ +\xdc%\xae\x80\xc4\xb2\xfe%\x847o\x1ay\x8cB\x12\ +\xd5\x15\x00\x00\x00\x00IEND\xaeB`\x82\ +\x00\x00\x01\xe6\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\ +\x00\x00\x01\xadIDATx\xda\xedW\xcdJ\xc3@\ +\x10\xeeK\x88 ^D\x11\x11\xd1\xda\x1f\x22^l\xd2\ +J\x9e\xa1\xde\x0az\xb3\x82\x17\x05\x1f@(\xf8\xb0\x05\ +\x1blS\xd38\x1f\xec\xc2\x12v6\xbb\x9b\x04`\xb8]\x8e\xe6\xb0\xd8\xa2\x0cO\xb8\xcf\x02\x12\ +\xde\x97\xf4\xab\xc9y\xcaq;\xc8\x0a\x8c\xc9\xd4\x04\x1c\ +9\xb1u\xe0\xd4\xc0\xfd\xa1E\xcdp\xb3\xe3\xc6%\xff\ +\xcfJNe\xce#\xdb\x01&\xe6\xbf\xaa\xbf\xf0\xa9\x83\ +'\x91\xd3\xad\xeb<'\xf9+DB\xe8/\xaat\xc2\ +\x19]p\xe0\xc9\x1f\xf8eu\xd1\xfe\xb7h\xd7\xbf_\ +\x7f\xb3\xb1^\xeamg8\x00\x00\x00\x00\x00IEN\ +D\xaeB`\x82\ +\x00\x00\x00\xd0\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xffa\ +\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\ +\x04gAMA\x00\x00\xb1\x8f\x0b\xfca\x05\x00\x00\x00\ +\x09pHYs\x00\x00\x0e\xc3\x00\x00\x0e\xc3\x01\xc7o\ +\xa8d\x00\x00\x00eIDAT8O\xd5\x91Q\x0e\ +\xc0 \x08Cq\xd9\xbd\x99'g\xe9\x06\x06q&\xea\ +\xcf\xb6\xf7SBLmC\x12\x11\x029\xe7{\xe8\xc0\ +\xcc\x09o\xa0\xba\xba\xd8T\x87\x89\x1fM\x1b\x00o2\ +UA\xc7\x8aa\x83\x88\x19.U\xf0\xec\xaa\x85^T\ +#&}\xbfBc\x00gs\xe7\xa3\xd6'~p\x05\ +$\xf3\xbb\xef]\xa1$X\x83\xe8\x04\x88\xd4H\x07\xd8\ +\xd9\x12\x13\x00\x00\x00\x00IEND\xaeB`\x82\ +\x00\x00\x01\x05\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xffa\ +\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\ +\x04gAMA\x00\x00\xb1\x8f\x0b\xfca\x05\x00\x00\x00\ +\x09pHYs\x00\x00\x0e\xc3\x00\x00\x0e\xc3\x01\xc7o\ +\xa8d\x00\x00\x00\x9aIDAT8O\xa5Sm\x0a\ +\x80 \x0c\x9d\x12\x05]\xa6\xdf\x9d\xa6\xb3u\x9a\xfe\xd6\ +e\x82(\xb0&j*\xfb\x08z0\xd6\xb4\xbd\xf7&\ +j\x9cs\xf0\x07\xf6\xda:\x92a\x99z\x87\x11J\x16\ +\xb6\x19\x0e\x13\xbe\x13\xa4F\x14\xccE\xfd\x08R\xc38\ +\xefI\x00\x1bkA\x1b2\x8b\x9c\x9cr\xeb\x09r\x15\ +\x0a\x92C\xd5A\x04\x92PD\xea\x19Dp.U\x07\ +\xd8(\x8dX\x10h?S`ob\x1cK\x22\xf4\xf7\ +\x01\x090\xce\xb5}\xd2[\xd7\xc1\xed\xb3\x9b_\xd7\x8a\ +\x22\x0f\xcdQ\x8c\xff\xaf1d\x11\xdc\x8b\x05\x00\xb8\x01\ +\xef\x94\xd6@\xd4\x8c1\xa7\x00\x00\x00\x00IEND\ +\xaeB`\x82\ +\x00\x00\x01\x88\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\ +\x00\x00\x01OIDATx\xdac`\x18\x05t\x00\ +\xd1I\xb9<\x03iy\x03\x10\x7f\x04b\xc9\x81\xb0<\ +\x0c\x88\xffC\xf1m f\xa7\xa7\xe5\xe6@\xfc\x17\xc9\ +\x01 \xbc\x9b^\x96K\x03\xf1k4\xcba\xb8\x9f\xd6\ +\x963\x02\xf1\x1d\x1c\x96\xc3p<\xad\x1d\xe1\x01\xc4\xbe\ +@\xec\x0e\xc4\xb7\xa0\x966\x01\xb1\x17\x10\xfb\x03\xb1\x12\ +=\xd3\xc2\x09\xa8\x03<\x07*\x1b\x9e\x84:\xc0\x87X\ +\x0d\xea@\xcc\x0f\xc5\x1aP>>,\x0f\xc4,@,\ +F\xb1\x03\x80\x8av@\x15\x17B\xf1\x7f\x22\xf0U \ +V\x80\xb2\xb7\x90\xed\x00\xa0\x02\x0e \xfe\x0aU\x9c\x0b\ +\xc5\xc48\xe0\x1c4\x14`|\xb5\x81v\x80\xfa\xa8\x03\ +\xd0\xcc=\x0b\x15\xf7\x1d(\x07\x14\x03\xf1Jtq\xba\ +9\x80\x94\x02c\xd09\xa0\x80H\x07\x5c\xa6\x85\x03\xf2\ +\x80X\x18\x88\x83\x818\x10\x0f\x0e\x82\xd6\xfb\x92\xd4v\ +\xc0cP\xe3\x01\x88w\x11\x89OQ\xdb\x01\xc4\xe0\xdf\ +@\xfc\x0b\x88\xff\xa0\x89S\xc5\x01_\x09\xb5d\xa1\xd1\ +S\x01\xc4\x86Hu\x08\xd5\x1c\xf0\x05\x88E\x08\xa8?\ +\x04U\xdbF+\x07\x08\x10P\xbf\x1e\xaa\x0e\x14\x0a\xdb\ +\xa9\xed\x00P\xfc\xd6\x03q\x11\x01\x5c\x0c\xcd\xb2wp\ +\xd5\x86\xa4:\xa2\x05\xea\xabo\xd0\x04\xf6\x9b\x00\x86\xa9\ +\xf9\x0eu\xfcvj4\xa1\xd8\xa1\xa1A2\x1e\xed\x84\ +\x92\x03\x00\xf9}\xdcv\x87\xa5\x0a\x0a Icons / Notifi\ +cation / Helpers\ +\x0a \x0a <\ +g id=\x22Screen-1-C\ +opy-61\x22 transfor\ +m=\x22translate(-62\ +0.000000, -295.0\ +00000)\x22>\x0a \ + \x0a \ + \ +\x0a \ + \x0a \ + <\ +path d=\x22M12,2 C1\ +7.5228475,2 22,6\ +.4771525 22,12 C\ +22,17.5228475 17\ +.5228475,22 12,2\ +2 C6.4771525,22 \ +2,17.5228475 2,1\ +2 C2,6.4771525 6\ +.4771525,2 12,2 \ +Z M12.4748737,17\ + L10.4748737,17 \ +L10.4748737,20 L\ +12.4748737,20 L1\ +2.4748737,17 Z M\ +8.47487373,5 L5.\ +5,8.06066017 L6.\ +91421356,9.47487\ +373 L9.324,7 L14\ +.9,7 L16,7.888 L\ +16,11.306 L15.50\ +1,12 L10.4748737\ +,12 L10.4748737,\ +15 L12.4748737,1\ +5 L12.474,14 L16\ +.4748737,14 L17.\ +998,12 L18,12 L1\ +8,7 L15.4748737,\ +5 L8.47487373,5 \ +Z\x22 id=\x22Combined-\ +Shape\x22 fill=\x22#FF\ +FFFF\x22>\x0a \ + \x0a <\ +/g>\x0a \ +\x0a \x0a\ +\ +\x00\x00\x05\x08\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\ +\x00\x00\x04\xcfIDATx\xda\xcd\x97{h\x96e\ +\x18\xc6\xe7\xa6s\xfa9\xb5\xb9<\x90\x87r\x1e\xd6\xbe\ +\xda\xe667\x06\x1fQ\x9e*\x05\x0b\xc9S\x05\xa9%\ +\xea\x9a4bakk\x91&\xa9\xa0\x9df&\x82!\ +\xa2R1*,\xc1\x0e\xd8\xc8\xa2,;X\x19\xd5\x97\ +\xd3j\x85BZ\x14\xa5\xe5X\xd7%\xd7\x13\x97\x0f\x15\ +\xd2_\xfb\xe0\xe2~\x7f\xcf\xde\xe7}\xef\xf7\xbe\x9f\xe7\ +~\xeeedt\x87\xdf\xfc\x85\xcb\x0b\xa1]\xf3\x16\xd4\ +\xd6\x89{C\xeb\xc1\x9ba\xfbk\xec6\xf0s\xb0\x95\ +\xe2+\xc1\xcf\xc0\xd6\x88\xfb\x82\x1f\x85}\x12\xea\xc31\ +\xf0\x1d\xb8\xe6\x9cbq\x19\xae[\xa1E\xb1\x03\xef@\ +]\xb8\xa1\x0b6\x09\xd5\x1a\xaf\x85\xf2\x8d\x8fi\xce!\ +q\x97>\xe0^\xe3\x07\xa0\xd1\xc6\x9f\xc8\x81\xcf\xc5T\ +\x81;\xb0\xdb^0\x12\x9ac\x5c\x0f%\xa0N\xf1\x07\ +\x9a\xf3\xaa\xbd`\x18\xbf\xca\xb8\x06\x1a\x0c>+n\x93\ +\x03o\x8a;\xa1\xa1\x7f;\x80?\xe4@\xb7c\xb0\xdc\ +\xc6\xae\x07\xcf6\x1e\x07^\x02;PL\xa7\x16\xc3\x96\ +\xd8\x87\xcc\x04\xdfd\x9c\x04/\x83\xfa\x8asq\xcdg\ +\x14\xc5)`\xce\xe7\xe0\x0fW\xd8\xd85t\xc2\x98!\ +\x9d\xcf\x87X\xce\xe7\xc2^nNN\x05O3\x1e\x0b\ +\xbe\xd9\xd6DB\x5c\x10;\xf0\xac\x85\xfc\x12h\x96q\ +\xad\x1c<#~[s^\x123\xccC\xa0[-\x05\ +\x8b\xa0A\xe0\xd3\xe2\xbdr\xe05\xf1o\xd0\xc5\xee\xc0\ +A{a\x09Tg\xbc\x81\xf94\xee\xd0\x9c\xc3\xf6\xc2\ +\x22\xa8\xc9x%4\xc6\xf8\xb0\x1c\xf8\xd2\x16\xe1X_\ +\x03\xdcR/b\xb0A\xdc\x07\xda\x04\xde\x0e\x9b\xa7\xb1\ +%\xe0\x97aS\xe2\x09\x5c\xbc\xb0\xf5\xe2~\xe0-\xb0\ +\xdbx-'\x97\xe3\x9as&\x8a+q\xbd\x07\xaa\xf9\ +\xa7Z\x90\x888\x0b7\xf6\xf61pn\xc4\x89\x88{\ +b^v\xf4\x9c~\xff\xc5a\xb0I!\xee\xe0\x82\x81\ +J\xa1?\x15\xc2i\xd1\xbe\xdf$^-\xfeZk\xa4\ +\x1a\xdc\xa9\xf0\xa6\xe8\x08\xf8S\xf1:9\xb8>\xd4\x05\ +(\xc7\x1d\xf8\xc2r\x5c\x0d5\x1a?\x05\x0d7>\xa9\ +9G-\xc7\xe5\xd0\xc3\xc6\x5c7E\xc6\xed\x8a\xe87\ +\xb6\x06\x92\x1e:\x96\xd9S\x18\xdc\x0f\x9b\x09]\x0a\xf1\ +\xcb\xbe\x87-\xd5=\xcf\x83\x7f\x86\xbdG\xbc\x14\xfc\x13\ +,\x0bR\x0f\xd5\x09:\xf5-T\xc81\xed\x94_B\ +\xce\xc1w\x89_\xe0{2\xba\xcd\x0f\x9e]\x0b}\x05\ +\xafv\x88Y\xfb\xdb\xc0\x1f\xb2\x00il\x03\xf8\x08\xf7\ +\xbbU\xbd4\xec\xd3\xe2a\xe0\xfd\xb0\xef1e\x8aR\ +\x0b\xa3\xc2\xba\x22\x9e-n\x89\x1d\xf8\xccr\x5c\xc9\x83\ +\xc5x\xa3\x8aS\xe0\x13\x9a\x93\xb6\x1cs\xd1\xae2^\ +\xc7\x0aiLG\x99\xda\xa3\xb6\x06\x0a}\x0d<\xa1\x9b\ +\x99\x9f\x81\xd0\xd5a2\xec<(K;\x84\xdc\xaa9\ +[\xc5'\xa0\xfe\xd0\x8c\xe0$4Su\xe1\x07\xf16\ +9\xbdK\xdc\x01\x0d\x88\xa3P\x1c\x0e\x1a\xf1\x08\xf0\x18\ +c\x1eXe\xd1\xbe/\x09\xfd\x82\xf82\xaf\xf3r\xa2\ +\xb0\xdc)\x8f\ +\xc3\xce\x15\xf7\x047\xaa\x17\xe8%\x07nT\x0aG\x8b\ +\x0b\xc47\xc4\x0e\xb4Y\x8e\xd9\x5c,6^\x05]d\ +\x9c\xd6\x9c\x03\x96c\x9ezu\xc6\x0d\xd0(\xe3\x83r\ +\xe0#[\x03\xa3<\x94\xaf[\xcey\xec.4nV\ +\x8e\x03\x87\x83\xe5-\xcb9_v\xa7\xf1\xdd\xd0p\xe3\ +w\xe5\xf4\xfbbj\x84G\x80_\xd8\xc0\xf3\xdc\xc6\x16\ +\xe8\xa1=\xc4U\xe0\xfb\xb9\xdd\xc2VU\xc8'\xd9\x87\ +\xb0\x07\x5cj|\x15\xb8\x99\xf7\x8a\x87\x88Sq\x0a\x98\ +\xf3I\xb8a\xa4\x8d\x95\x80\xab\x8c\x07\xab\xe1\xc8\xb1\xc3\ +j2\xb7\xa8\xbd\x90'd\x85\xf1P\xf0\x14\xae\x0fq\ +6\xae\xa7\x9e\xd7\x8e\xe9aaK\x9dU\x11\xba\xcer\ +\xce\xe6\x82\x13O\x8a_\xd1\x9c\x9d\xe2_\xd9|\xb0\xd8\ +X\xce\xd99q;\xff(n\xb5r~\xee<\x81\xf2\ +|\x0d\x1c\xb2\x1cO\x84V\x18\xb7\xf0K\x8c\x8fkN\ +\xdar\x5c\xaa\x1d\x13x-4\xde8\xad\xb3\xa1\xdd\xd6\ +\xc0x\x8f@\x15[-\xf6\xf5\xa17\xa0\xd7\xe0\xbdl\ +\xb74\xc65r\x00v\xba8\x05f;\xbfF<\x80\ +\x87\x0c\xec\x1e\xae)9\xf9 w\x0b4Yc\xdfy\ +\x8e\xb2Y\xb4\x1c\xa7\xb4\xf7\x03o\xe6\xee0>\xa59\ +\xc7,\xc7\x15\xd0\x1a\xe3G\xa0\xa4q\xbb\xa2\xf3\x9d\xad\ +\x81\xa4G\x80\xfb\xfd4\x06?\xa6gQ\x04RQ\x04\ +V\xffK\x04\x8a-\x02\x15Q\x04\x1a\xe5t\x93x_\ +\x9c*>0\xcf\xbb\x14\x9e\x01\xa1\xbb\xb5H\xe5G<\ +(\x14*\xfb\xc7#a\x9c\x19\x8a\x90=7?\xa3;\ +\xfd\xfe\x02\x18\xfc\x86\x85\xa5`T\xfb\x00\x00\x00\x00I\ +END\xaeB`\x82\ +\x00\x00\x00\xfc\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xffa\ +\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\ +\x04gAMA\x00\x00\xb1\x8f\x0b\xfca\x05\x00\x00\x00\ +\x09pHYs\x00\x00\x0e\xc3\x00\x00\x0e\xc3\x01\xc7o\ +\xa8d\x00\x00\x00\x91IDAT8O\xa5S\x81\x0d\ +\x80 \x0c\x03b\xf4\x1c\xff\xffB\xcf1\x9a\xa0%T\ +q\xbaa\xa4I\x1dts\x14P\x1fct-\x08\xdb\ +<\xbcv\x80\xae\xe5n\x80\x03\xc9u\xea\x8fp\xc5\x92\ +\xd0J=mA\xae\xd4\x8d\x8bG\x84\xce1 \xe7\x09\ +\xec\xca\x8e\x92V\x0e<\x07\x7f\x9b\x84l\xc4\x04l\xab\ +\x87\x8a.\xb5\xd5\xad|z\xb0@\x16[/\x92\xe7\x16\ +x\xc2\xb4\x9b\xe5*\xd4/\x91M\x1e\xd7V \xd5\xd0\ +J\xcd\xae\x96W\x93_\xb5\xdb\xa4d\xcd\x11\xd9\xfe7\ +\xe6hB\xbf\x15\xe7v\xf1\xcd\xb3\xd1w\xeb$X\x00\ +\x00\x00\x00IEND\xaeB`\x82\ +\x00\x00\x02\x14\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\ +\x00\x00\x01\xdbIDATx\xda\xed\x97\xbfKBQ\ +\x14\xc7E\xa1!\x10,tk\x08\xda\x02\x1bj\x8eR\ +hj\xd1!\xe8\xd7\x90\x8deCS\xd1\xd2\xd8\xd2\x16\ +iC\xb4e\xf8'\xb4i:YTCC\x8bA\x16\ +M\x85IF\x93\xda\xf7\xbc\x8er\xb9\xdcgO\xbb*\ +\xc1{\xf0\xe1\xf0\xe5\x1d\xef\xfdz\xcey\xf7\xa9\xc3a\ +_\x1d\xbe\x96V7\x92\xe0\x0e\x0cu}\xf3\xc5\x955\ +\x176~\x0650\xd6}\x03\x91\xa8\x0b&\x0a\xa0\x06\ +\xfc\xbd\xaa@\x81+`\x1b\xf0\xdb3\xd0\xabs\xe0\x91\ +\x0d\x8cZq\xbc\x8f\xc4\x0b\xe0\x01G\xd0i\xc4T\x1d\ +\xe8\x94\xa43\x88\x9b`\x02\x9c@\x0f#\xd2\xb7^\x06\ +\x0b\xd0\x14_\xd9\xc0\x16\xf4<\xdf\x1bQm>\x83\x9e\ +\xd5\xb8_>p%\xe8\x1f\xd4\x9a\x8c\x06YS\xbf=\ +\xa0,\xdc\xaf\x82\x8a\xf4\xf9YU\xa9Bt\x93\xddz\ +AN\xd0\x06\xb4\x90\xa4)\xc6@\x80\xf5;b?\x18\ +\x07\xb4qU\x91\xbfk\xd6+\x1d\x06\x8a\x88n^o\ +N\xf1\xf9D\xb3a\xd1j\x80\xdb\xba#\xe4g\xa1\x9d\ +\xcd\x060$\xf4\xc8\x0br\xac+\x0d\x22\xd1\xaa\xa4\xe9\ +~\x0c\x04\xb8\xc7ED\xb7\xb4\xee)x\x02\x03\xbf=\ +.\xda+\xc0\xeb:\xe9\xa9\xb2\xf2\xbcv\xc4@+\x07\ +\x86l\xe0Ra@5\xd5q-\x06\xa4\x19\x18\x04\xe7\ +\xd0\x1f\x88\xa5\x06\x91hI\xd2\x9f\x88{`\xdal\x06\ +\xda\xad\xc0\x14\xa0\xc3\xc8\xcb\xd500\xd1>\xb0\xae\xbb\ +\x05b\x89[\xd1\xda\x0c\xbc\x80\x03\xe88\xf7\xd8@\xd0\ +1I\x97u\xcf@\xdaB\xfe-\xf2\xef\x11'A^\ +\xf7\x0cd,\xe4\xd7[\x10\x06y\x1d-\x08\x0b\x06\xd2\ +\x16\xf2\x0f\x91\x7fL\xefy\xf0 \xbc\x8c\xda6\x10\x14\ +\x0c|\x81\x1b*3b\x03I\xd3A\x95C\xbc\xa67\ +\x1f\x1bxC\xec\xfb\xcbo\xb8m,r\xc6$\xa1\x93\ +F\xacc\xae)?\x01\x1d\xb0\xff\x0b\xfe\xbb\xeb\x1b\xc9\ +\xfb\xd7\x13\xad&L\xa9\x00\x00\x00\x00IEND\xae\ +B`\x82\ +\x00\x00\x00\xd0\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xffa\ +\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\ +\x04gAMA\x00\x00\xb1\x8f\x0b\xfca\x05\x00\x00\x00\ +\x09pHYs\x00\x00\x0e\xc3\x00\x00\x0e\xc3\x01\xc7o\ +\xa8d\x00\x00\x00eIDAT8O\xdd\x93\xd1\x0a\ +\x800\x08E]?.~\xb9atc\xc55\xad\x97\ +\xa0\xf32\x86\xf3p\x057\xdc]\x18f\xc6\x0b;\xaa\ +:\xe2<\x04s\x03\x8aA&\xc2\x9be\xbb]\x88&\ +4\xce2\x06\x15\x80\x8e\xe4V\x10d#\x80RP\xf1\ +Z\x80d\xdf%\x00\x7f\x12T\x1b\x97qJ\x10\x92\xa7\ +\x22:BG\x84z\xfa\x9d{\x88\xac\x1d\xf5-\x8f\xc3\ +r\xe1\x95\x00\x00\x00\x00IEND\xaeB`\x82\ +\x00\x00\x04M\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\ +\x00\x00\x04\x14IDATx\xda\xcdW}L\xceQ\ +\x14~U$\x94\xbc\xd2\x87,\x9f\xf3\xe6\xcd|d-\ +LS\x93lY6\x9f+[MM\x85B\xc3l6\ +b\xfc!B\xd6\x1f\xac\x86\x0cM\x96\xcfe\xb3\xd9d\ +\xf3\xfdG#\xf9\x1c\xcd\xb0\xcc\x98\xaf\xc9V!y\xce\ +\x9c\xcb\xd3\xf5\xf2\xf7\xdb\xf6\xec\xbe\xe7\xf9\x9ds~\xe7\ +w\xefs\xef=9\x1c\xde\xf0\x97\x91\xbd2\x1a8\x9e\ +\xbe\xa4\xb0\x88\xb8`\xd8\x071\x96\x00=\x85\x83\xed\x87\ +\xdf\xdb\x81*\xc0I\xbe\x85@\x0d\x9e\xbb\x89\x9b\x0b\xfb\ +$\xc6\x14\xc3\xc1\x8e\x85}\x0a\xc8\xb1\x0b\xb8\x05t\xc1\ +\xa1\x0b\xe3\x04\xe5\xf6\xa9-\xc8\xd3\x049j\x0b*\xd4\ +o\x9c\xe1\xf0\xfc\x8er}\x80o\x1a\xdfI\x05<\xa2\ +\xf8\x91\x5c@\x1d\x150B\xb9b*`\x9e&\x98C\ +\x09\xb6\xa9\xdf0*\xe0\x82r>\xc0'\x8d\x7fC\x05\ +\x5cU\xdfN \xdcA\x0fz\x03y \xe3\xac\x99\xc9\ +\x02\x9f\xca\x1c\xecY@\x96\xc5\xc5\x02\xcb\xe0\x1f@\xdc\ +P\xd8\x05\x18#(_ l\xe1\xc6:\xbc\xea\x0f\x95\ +\x0d\x14q\xa1\xb24\xe2z\xc0\xde\x841\xdf\xf2]\x0a\ +\x08\xefK\xdcl\x8d\x0f!Nfe\x17F7\xcdJ\ +\x04\xecR`\x86]\xc0\x15\xd2\x80[\xb92\xd2@\xa6\ +&\xc8 \x0d\x94\xd3\x0e2\x1a\xb8\xa9\x5c/\xa0]\xe3\ +\xdb\xa8\x80\xbb\x14\x1f\xc5kXo^f\xb6\x12\xc6R\ +S\x14\x90\xa9\x893\xd4\x16\x94\xa9_\xb4\xe1\xf0\xfc\x9a\ +r\xfe\xc0\x17\x8do\xa5\x0f\xbdM\xf1Q<\x0325\ +;@.$N\x92l\xd6=\xde\x83\xf8\x02`\x0b\x0b\ +Nv\x09\xb0\x13\xfe\x83\x89\x9b\x02{\x0f\xc6\xf1\x960\ +\x85K\xf5:\x11\xf6\x05\xb2Qa\x9c\xb5\xbd\xd2\xf9$\ +S\xdf\x99@\xba\xc5\xc9\x09\x97\x03\xff~\xc4\x0d\xd7\xad\ +\x1dI\xf9\xfa\xc3\xce\x05b\x1c\xd6\x8bN\x93\x06\x86*\ +\xb7\x814\x90f\xd4NkX\xac~Q\xa4\x81:\xe5\ +|\x81\xb7\x1a\xdfBE\xd5\xabo\x1b\x10\xc6_\xd0@\ +\xbb`\x92r\x15\xb4\x0b\x96k\xe2\x5cR\xf1!\xf5\x1b\ +O\xbb\xa0\x89\x8e\xe2\x1f&\x9e>\xf4\x09\xc5\x8f\xb2/\ +\xa3Z8\xac#.\x08\xf6\x11\x8c\xbb\x01?\xf3e\x22\ +6\xe0\xa8\x5cV\xe4[\x04\x9c\xc4\xf31\xc4\xcd\x87}\ +\xce\xba\x8c&\xc0\x16.\xd7\xbbD\x88\xca\xe4\xd4\x9b.\ +\xdb\xd1\x12W\x1f\xd8\xc9|b\x9a\ +\x07\x95\xba\x86\xdf1\x86*\x97O\x1aH\xd4\xa4\xd3h\ +\x0d\x0b\xd5o\x10\xf0U\xe3\xab(g\xb3\xc67QQ\ +g4\xf6#0\x80\x0b\xb8G\x22\x9c\xac\xdca*`\ +\xb5&(\xa0\x02\xaa\xd5/\x8eD\xf8\xd8\xe8\x87\xf2\xb1\ +\x08\x9fQ\xbc\x8b\x0bH\x00\x1a\xe1\xb0\x9f8\xd9^\xd7\ +1\x9e\x95\x844\xad\xd2\xd1\xdc\x90}N\xbe\xe5\xc0]\ +Y\x06\x16&\xec\x07ryQ\x01ri\xdd\x97\x8b\xcb\ +\xe1u\x7f\xd2\x09\xa1\xc2\x00K\x5c\x91rU[~N\ +`\x88\xc5\xf5\xee\xd6b\xfd\xb9\xce]\x1e\xde\xe32\xdb\ +\x9a\xc9\x12]\xb3wf\x7fc\x5c\xa0k\xd8\x0eL\xd4\ +\x82\xe4\xd0i\xd35\x5cL\xeb\xfdZ\xe3K\xb9\xcf\xd4\ +\xf8K\xf4A\x15\x1a\xfbT\x0e+.\xe0!\x89&A\ +\xb9c$\xc2\xb5\x9a`\x15\x89\xa8F\xfd\xa6\x92\x08\x9b\ +MGm\x8bPg\xe4\x05\xc5\xbby\xaa\x17\x01\xefA\ +^\x943A9\xe9v_I\xa7\x0b\x84k\x92P\xfc\ +\x96;]x3+\xb2\xb7\xcf\x03\x1f\xa4_\xa0\x9c{\ +a\x7f\xc6\xb8\x95\xbb)\xd8\xc2UK\x9c\xd7\x890\xd8\ +\xaeJ\xaeWiL,?\x7f\xe9n-\xce\x87\xef\x06\ +\x8awzx\x8f\xd3\xd3\xcbW\x88\xb8\x10\xd0(\xfd\x9c\ +r\x892]\x18[\xcc\xcd\x05{8~\xbf\x04Z\xe5\ +\x98\xa5\x82\x1a\xb4\x07\x5cM9O\xc0\x96\x13\xb2\x92\x0a\ +\x92f\xb6\x03\xb8l\xfe\xdb\xfa}MR?\x90\xa4\x5c\ +\x0d\xf5\x03\xeb5\xe9\x1a\xea\x07j\xcd\xf1L\xfd\xc0s\ +\xf3\xe5\x94\xaf\xcbhE>\x86\xe2c\x1cV\x9f\xd7\xae\ +]\xab?\xcd@\xeb\x7ff \x85\xce\x00\x99\x81\x0e\xd9\ +%\x94\xb3Vg\xe0\x00}\xe8F\xbd7\xba\xcf\x80Y\ +\x1b\x0f\x1a\x08\xfa\x87\x06\x82\xecC\xc7\xd3\xda\xfeu\xeb\ +\xfd\xf2\x0d\xf1*\xf1\xff\x04\x8f\x07^\xb5\xbe\xa8\x80\xde\ +\x00\x00\x00\x00IEND\xaeB`\x82\ +\x00\x00\x00\xd0\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xffa\ +\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\ +\x04gAMA\x00\x00\xb1\x8f\x0b\xfca\x05\x00\x00\x00\ +\x09pHYs\x00\x00\x0e\xc3\x00\x00\x0e\xc3\x01\xc7o\ +\xa8d\x00\x00\x00eIDAT8O\xdd\x93\xd1\x0a\ +\x800\x08E]?.~\xb9atc\xc55\xad\x97\ +\xa0\xf32\x86\xf3p\x057\xdc]\x18f\xc6\x0b;\xaa\ +:\xe2<\x04s\x03\x8aA&\xc2\x9be\xbb]\x88&\ +4\xce2\x06\x15\x80\x8e\xe4V\x10d#\x80RP\xf1\ +Z\x80d\xdf%\x00\x7f\x12T\x1b\x97qJ\x10\x92\xa7\ +\x22:BG\x84z\xfa\x9d{\x88\xac\x1d\xf5-\x8f\xc3\ +r\xe1\x95\x00\x00\x00\x00IEND\xaeB`\x82\ +\x00\x00\x07\xe6\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22?>\x0a\x0a o3de icon\x0a \x0a \ + \x0a \ + \x0a \ + \x0a \x0a<\ +/svg>\ +\x00\x00C\x13\ +\x00\ +\x01\x9f\xd1x\x9c\xed\x1d\x09\x5c\x8c\xdb\xf7\x9bR!\xd4\ +\xc3#)e\x8dl\xf9{\xc8Z\xf6}_\x1f\x22<\ +\xbb\x92\x84,\xd5\x90%d\x97\x9d,E$B\xa4\x92\ +\x22\x22k\x12\xd9[H4\xed{\xd3\xcc|\xff{\xee\ +\xf7MM\xd3LM3\x93&\xba\xbf\xdfy\xbdI\xf3\ +}\xf7\xdes\xee\xd9\xef9\x04\xc1 T\x09\x18\x0cB\ +\x9f\x98\xa7M\x10\x0b\xd0\xff3\x99\xd4\xe7\xb65\x19D\ +\x18\xfa\x9d\xa9)\xfdy\x00A\xa4\xb7`\x10FF\xd4\ +g\x8f\xd6\x04\xd1d>\xfa?}\xfa\xb3&A\xdc\xdb\ +\xc1 45\xa9\xcf\x8bj\x10\xc4\xe2\xe3\x0cb\xfb\xb8\ +1C\xeb\xd6\xd6\xae\x8d\x1e]w\xf8\xb0A\x13\xe0_\ +\x01j\xc2\xabgZ{\xa0wj\x1b\x0e\x1f\xd4\x7f\x92\ +\xed\x87\xe4\xcf\xa3\x975\x88\xfa\xa2\x9a\xf6\xa8\xd5\x18+\ +\xa2\xc1\x86\xe8e\xdeM\xe3w\x5c>1\xe4\xb9\xd9?\ +\xb5/\xd5\xb09p\xd0\xccP\xe5\xcc\xe5'\xdb\xa6]\ +\xf3h9\xcd\xac\xd6\xf8I?\xaf\x98\xaeh|\xd9P\ +\xc9\xac\xf9 \xb7\x05C\x0f\x8c\xaeU\xbf\xc5\x88\xc6\xcf\ +'\xef\x98\xda\xff\xf9\xf1\xd0eg{t\xeb\xb4\xeb\x80\ +\xf1\xf6\xe8\x87\xcf\xb4\xe6-{\xa4\xd75\xd3\xa4k&\ +\xa7\xbb\xe9\xf4\xb4\xf4w\x09G3\xbb%\xe4Y\xfb\xe9\ +8=>~\x8c\x11\x9c\x909\xfcp\xc8\x94\x93\xd7n\ +\xae&\xec\x08\xe7\xd9\x8c\x98\x06\xdc\x97\xdf\xec\xdb\x11\xe4\ +\x1b\x87\xa0\xd3\xe4\xda9\xad\xbf\xec\xdb\xdf\xe9\xc8I\xf4\ +\xf7\x1b\xfcf\xbex\xc3\x08o2\x83\xe58%\xcc\xe4\ +\x95C\xb2r\xfb^.\x8765\xaa\xa9\x1e\xae4\x17\ +\xfd\xdd5}\xb3\xb6\x9e\xb7\xffG\xf4\x9a\xb7\xd4\x8c\xd8\ +\xca8\xa1j\xa5z9)\xf2HC\xe6\x05b\x01c\ +\x94\xd7\x83\xde\x87\xdc\xd5\xffk\x14U\x83i\x7f\x98\xac\ +=\xfda\xea\xfeN\x1a~\x1f\xfe\xc7lG\x98\x18\x07\ +\xae\x8a\xf9A\x84\xa7f5>=\x99\xd3\xe9g\xc6^\ +\x83\x8e\xcay\x8c`e\x83[ut\x9a\x10hns\ +\x88\xd9\x03\x97~ip1\xae\x1d3uJ\x9c\xee\xc4\ +\x08\x95\x8b\x87\xe6)\x99\xea\xdd\x0c\x22\xbc\xe2\xd6\x0c?\ +\xbc\xcdc\xd3|\x22\xba\xff\xd2\xbf\xdd\xdc\xd4'n\xcf\ +`\x9c\x9e\xca\xd1\xf2\xd9\x11\xdd\xc9\xac\xd9Ym\xb7\xd3\ +*\xfdg\xbe\xd1\x1f\xd7\x0b&\x16\xcd\xfc\xdb\xf5Dg\ +\x15\xaf\xa5i\xbbl\xfa\xefh\xd7\x84X\xa7\xe7\xa0\xb3\ +,\xf1@@\x07e\xad\x89\x8b\x9dM/\x12\xe1C\xb3\ +S\x1d\x1d\xd7\x7f\xb3\x1c\xcb\x989i\xce[\xfd\xc3O\ +c\x996\xcd\x99\x1bV\x92k\xbc3\x0e\x14\x9cd\xa4\ +\x05\xf0N66\xf8\xa0\x14\xde8\xed\xd3\xa3\x80\xec\xbc\ +A\xb3\xae\x13^\xdd\xbc\xf5\xd3\xe3\xcevd\xbex7\ +\xbdN\xf0K\xf3x\x83\xd4D\xe5\xb4\x1b\xb3\x1a\x0fz\ +\xf7E)\xfcBN\xca\xc0\x19\xb7F\x0e:\xd6n\x91\ +\xd7\xc6\x83f\x9d\x17\xadW7]\x9eA\xd6\x99b\x7f\ +vnH\xf8te\xbb\xd5w=,\x18\xa7\xc7\xa6^\ +\x0b\x1b;i\x96\x9e\x8f\xa6\xd6-\x96\x8aE-\xf4\xb0\ +\x0f*\x84\xc9\xa6\x9d\xeb\x9cr^\xd7\x8b\x19\x1a\xf8b\ +\xda\x8b\x0c\xe2\x87\xb3\xd7\xe7mo\x13\x0c\xce&~\x8e\ +b\xedv\xefP\x97\xe0\xd6\x9d\xe9\xcd\x1e\xad\xe9\x17\xa9\ +\xe290\xf8:\x81^\xfe\xbf-\xee\xcd\xcd\x87\x13\xde\ +\x19\x0d\x8e>\xb9\xaei\xd4\x97\x98\x96\xbf\xbd\xc3\x9c\xe1\ +5\x8fh\x13\x979\x83\x0e\xfd\xafo\x8dQ\xea\x84\xdd\ +\x87\xb8M\xcf\x1bo~\xbc\xb4\xd3\x91\x9e\x83\x17=\x99\ +`n\x17{\x7f\xcf\xf5\xa8-\x8f'\xde]f\xb3\x9c\ +11G\xb9\xed\xb4/\x1f;\xd9\x0dv\xea\xd3J%\ +&s\xc8\xa9V\xcb\x8c\x89,\xb5\xf5\xf6*kR\x9b\ +\xef\xf7&:\xd6\x98\x90\xcd\x99\xdf\xb5\x99\xaa\xbf\xc6\x14\ +\xfb\x16\xed\xec\x16Y\xb9X|f\x9c6\x09\xe9\xd3\xc1\ +N\xc5\xa9\x8f\xe5\xed}\xdc\x1a\x89\x89J\xde\xd1c\xdd\ +\x0e6L\xd4\xd2X\xe4\xa6n\xa5\x87^\x7fi\xd1\xd0\ +\x93f\x1b\x8f)\x9bF?\xf3\x1e\xcb\xd6m\xf0j=\ +;\xf1\xfd\x22\x9f\xf3\x9d\x98wW\xe5\xa6F\xa4\x1et\ +z\xc2^xs\xc6\xee\xa8\xd7*1+\xb9\x83\x96x\ +^\xdc=E\x97`/\x09\xea\x1a\x91\xba\xdb\xc9\xb0\xd7\ +\xc4\xa7\x87\xe6\xde\xf4!B\xdd\xa3\x9b\xfc5\xd9=\xd1\ +\x7f\xfad\xe2\x87\xa3\xbaYD\xea\x0e\xa7K\x11\x93\x93\ +\x991w\x1d\x99l\xeb\xe8\xe8{\x8bMZ\x18\x0c\xef\ +\xdfTs\x94K\x81\xde%\xdd\x1a\xce\x1b]\x5c\x1f/\ +\xfep\xe6\xcd\xe7\x1d\x86\xb7\x08\xdb\x5c\x03k\x9f\x86\x86\ +>J\x97\x163f\x12\xedM\xf6M\xbc9\xcfu\xf4\ +\xbac\xb9\xf9jw\x0fu\xb0k\x15\xb9y%\xd7k\ +\x15\xc95y\x9bk\xd43\xa8]~#'7\xbb\xba\ +\xfa\xb3RL\x0e\xd5%\xec>\x9e\xe9\x14\xb6\x7f\xe8\x00\ +5\xcd\xa6K<\x0bR_v\x9c\xdf\x84\xf8\xb6\xca\x0c\ +\xd1\xa9z\xfb\xf4\xddj\xee\xbcy\xee\x9d\x82\xa7F\xb4\ +6h1\xf1\xa0\xd7\xd3\xd6\xca\xa6\xb33\x1d\x86\xf8G\ +\x0e\xfaoG\xd7u'y\xa6~\x8d\x82U~\xd6o\ +\xb0\xefb\xa7\x83\xec9~\x84y\xa6\xebc\xb3\x11o\ +\x7fj(\x99F'_\x18\xe9\xef3\xe8\xbfK\x9d\x02\ +-\x83.LRg\xaeqh\xb1\x86}\xda\xf2\xf01\ +U\x9dC\x9dZ\x87\xed\xd8z\xfc\xaf:y\x9a\xb5\xba\ +\xc5\x9e\x0b\x0fX?(\xebvN\xe6\x84\xfaa\xban\ +=V\xe6\x9b\x04\x8dJ\xd1?\x196g\x95\x9d\x86'\ ++ b\xf9\xf6\x7fB\x88\xd0\xda\x0ei\xb3\x88\x1f-\ +\xb7\x98E\xb8\xb7Z_\xc7\xa6\xe0\xaf\xba=\xbe\x9e\x9b\ +\xa7\xa6Y\xb7GB{\xfb@rJ\xeb!\x9a\xcf\x02\ +\x9f\xc4\xed\xc9\xee\xdbj\x7f\xefa\xad\xd6\xb8u\xde\x18\ +e\xb3*\xf4\xad\x7f\xed5u\x0c-\x19uF\x1e\xde\ +{\xf9\xafZ\xdd\xe6\x9c\xfe\xb8\xe7\x80\x01\xc7i\xebq\ +\xcd\xba\xa9\xbe5#\x93\xa2L\x98\xc3~\x04\xab\xf5\xef\ +\xe2{\xf0\xe1'\xcf\x0e\xb3\xda\xac1\xf2=8\xb8\xd7\ +\x01\xcf\xcc\xbf=F\x84\xb4\x9d\xd6d\x1a\xa7\xa3qG\ +\xb3^\xff\x8b2_\xaenYOoH\xab\xff\xd8\xc3\ +\xd3\xcek\xfd\xc8\x09j\x5c{\xe5\xc8\x7fG\x91\xb7v\ +\xf9\xb9w\x98Q\xf3\xad\xf1\xae\xda\x0c\xab!\xfe6\xb3\ +\xfe\xfb'h\xfd\xee\xa5k\xbe\xdb\xb4\xd9\xd6\xbe\xc1\xe2\ +\x89\xbc\xe4SV7\xae\xbb\x04\x1d\xbco:\xcd,:\ +\xe4Y\x5c\xa3f\xe4\xf5\x87FF/\x8f\xde7\xf9\xa6\ +l\xea\xdab\xd1\xe1N'?\x0e\x1e0\x1aM*\xbc\ +\x81ehp-\x870\xfb\x1e\xc7\xef\x1d\x1b\xf6\x83\xe8\ +t\xb2^L\xc4O\x02mL\x1f\xde|\xf5\x03\x99\xc7\ +\xef\xf4\xdb\xb58\xd5\xd9+\xbb\xc96\xa7\x86\xb7\x08\xb6\ +\xdb\xc8\xef\xdd\xef15^Yu\x1d\xb3\xba\xe0\xaf\xbe\ +W>\xc7{\xfa5m\xda2M\xa7\xaf\x83\x81\xb6e\ +\xe8s\xab\xaeh\xca\xf7\xbfq\xe0\x95\xdb\xfd\xdc/\xdb\ +\x5c;qI\xe3\xc3\xbd\xb3\xa9*\xc1\x06\x11\xee\xd6\xbd\ +\xe6M\x0aL\xb0]\x19\xa2l\xf1\xcaH\xf9\xf4\x89}\ +\xbc)\xceY\xbes-\xdb\x1d_\xfe\xf7\xb8\xd1\x19\xab\ +\xcc~6\x0aNd7\x8b{\xdd\x94\xa2\x9e\x0e\xedg\ +\xac\x08\xb2\x0bZ\xec=={\xf3\xf1.7n[\xfc\ +\x9b\xff9X\xab\xb3V\xd3%!yY\xaa\x8e\xa7\xd7\ +\xd9\x85.o\xa8\xc14s&'9\x10G\xdcoG\ +[\xae\x9e\xdfy~\xcc\xe6\xec\xab\xb1\x8d\xf6\x853>\ +5\xe9\xfbL\xdfc\x96k\xfa\xf1\x05\xfaA\xb9\xb3\x03\ +l.N\x1a\xf7i\xb9\xde\x8f\x9c\xa8@\xe3\xf3\x7f\xad\ +\xde\xec\xfcQ\xab\xbfU\xca\xeb)\xcec\x97[9\x9f\ +\xbe\xb3:\xf0\xc5\x05\xe7F\xa6\xae6\xdb\xdd\x1a\xe6|\ +T\xf3\xe7\x8e\x18}tp\xc8\xf3\x13\xbcK!\xa6\xbe\ +z{\xfc\xf7\xcc\xb5\xb6W\xff\xfa\xba\xa9\xce\xc8v^\ +\x1a\xc1\x13[\x12\x1f\xdcG\xb6\x8cuxD\x0e\xf5\xaf\ +\xf9w\x17B\xbbkD\xf4\x8e{_\x1a\xa1\xa7\x99\xcf\ +\xed\xde\xd2L\xe7\x8d\x8fr\xea)\xd5\xa4\x03\x9dvm\ +\x9e\xac\xaeV\xeby\xf8\xca;\xc3\xfdk\xeen\x5c'\ +\xcfje\x9ef3\xb3\xbeK\x0a2\x16>\xccf\xdc\ +A+\xea\xbc\x5c\xbe\ +\xd9jaV\xcd!l\x8d\x16\xf5\xaf\x9f\xef\x9c\xb4Y\ +\xc3\xd5\x8bXZC\xb9_\x1f\xffu\x91\x99fJ3\ +\xee\x9aeg\xcdoyF9\xbf\xb5+\xb3\xbb\xf9\xd4\ +w\xf3\x8d<\xb7\xec\x1d\x96\xd2\xd6,l\xddn\xcf\x19\ +\xdd{\xdcF\x13\xeb\xfb\xe8\xf8\x8a\xa5\x89^\x06\x015\ +\x0e9\x04\xb48\xd3f\xe2\xf7\xb7\xedU\xee?\x8b\x9b\ +\xf2YoV\x0b?O\x1b\xc2J?|]K\xae\x17\ +\x22L+^J\xd3\x97[\x98\xf1f\x84\xe7\xdd\xe0!\ +\xfa\x08\x95\xce\x0fI\x8e\xf2\xd8+\xbeQ\xddN\xe7f\ +\xdc\xfc\xd0\x95\x810\xbc\xcf\xc5iV\x03t0\xc3\xb2\ +\xe7\x8d\x88\xaes\xd9|-1\xe95\xd9\xc3\xf1\xda\xbe\ +!^\xc6\xf5L\xb7\x0e\xfb\xc1Lx\xab>\xad\x19\xb1\ +z\xcc\x8d7\x13\x8fN\x9e\xadN\x10\x06\xef\xebz\xef\ +\xeab\xfc\xc3E\xd3\xfb\x1fB\xfb\xfd\xfc[Sv\xf5\ +\xe9\xe5\xb9\xae\xbd\xfe\x93\x8d\xa63\xd6\xb6\xab\x81\x84B\ +o5\xefYw.\x05\xd5\xf7\xfcR;\xed~\xe3\xf1\ +\xddf\xd5b\x8cT\x0e\xbe\xc23\x09\x7fg\xc6\x89_\ +z\xd3\xb5\xd1\xeb[\x91\xdfW2Vg\x0e\xa8y\xfb\ +\xac\xca\xde\x17\xdf\xb4\xfdwz~Q\x22|:\xde\x7f\ +lo\xa9\xc1x\xaa\x14\xfc\x82\xe7p\xce.o\xb3\xbd\ +\xb3\xcb\x93u3\xd9*6J-k|2\xd6]\xfa\ +/a\xecN.\x1f\x17\xf8wp\xc7\xfb\xff\xf9u\xab\ +\xd1!\xc0\x0b\xfd\xc2\x95\xec1k\xbe\xcb\xacU\x17\x06\ +4\xf0\x990ud\xfc\xd2\x85\x87\x16\xddn\xb2f\xc8\ +\x9e#\xab\x17\xed\xac\xdd\xa1`JO\xf4%\xdb\x8b\xb6\ +\xea\xc1\xef<\xc3\x13\x0f=\xb9\xb4\xc2*\x81u\x92S\ ++\xe8f\x8d\xcb\xe3\xc7|\xfd/\xd6z\x9b\xab\xf1\x1b\ +\xc4/B\xef.\x9a8\xf7\xc6\xf4\xae\xd3\xea\x13\xab-\ +\xdd\x16\xbf\xd5\xb1oq1g\x14a\xfe\xbc\xd1\x9c\xd0\ +\xae\x7f\xbf\x0e\xb28jm\x9c\x10\x10lK\xae\xecR\ +\xcf@\x97}{\xf0\xb2s\x93o<\xd8\xfa!mn\ +;O\x0e{\xdf\x12\xf8\xde\x95\x99]\xcf\x91\x1a\x8bf\ +\xec\xbdz%\xb5\xdd\xcdv\x8b\xae\x9d\xfa:\xfa\xc8?\ +\xf1\x81\x1f\x1c\xbe\x7fIdwj\x93\xb0&s\xc6j\ +\x8d\x9c[\xe6?\xe6Y\xbc\xecg\xb0\xf5^\xee\xe1M\ +\xc6\xeb{\xc7\xe7\xd5\x1d\xea\xb5\x98a|\x99\x5c\x8e\xb8\ +\xa1f-\xbf5\xdb\xf4]vG\x1e\xfb\xf7S\xe8\xb3\ +\xb8\xee\x9b&\xf6\xab\x93s+.\xe3\xa2\xe3\x08\xe7\x95\ +\x93\xdak\xa5\xc5\xbe\xf81\xe7DP\xc1\x10\xff\xb6u\ +\xaf]V7W\xbb\xc1&U\xdf\xf8\xd6\xf4L\xf0\xe7\ +\x9dq\xbd\x92ek?2,`r\xaf\x03!\xdf8\ +m\xda$\xf4\xe8\x12\x9e\xfc(~\x22\xc3\xdd\xc4q\x80\ +\xf2g\xfbG{\xd4\x8e|\xf9rs\xe5?\xef\x92z\ +\xbfWWIq.\xb8\x98\xcd\x1e\xf3b\xf9\x5c\x8e\xc1\ +\xc2\xa4]&\x88\xb1\xbal\xff\xa7_A\xce\xd8\xd6\xd3\ +\xdb\xbdq\xaa{\xb3\xe7\xa5\xf8\x09\xcf\xb2\x08\xef\x1b\xa4\ +\x09\xf7\xb8\xdf\xc2\x84\x8bw\x1b\x11\xe3\xe6\xf5\x0a_\x82\ +\xb8\xbd\xb1Cn\xdd\x17\xd1v_\x9d^~C3\xfa\ +\xd9\x22\xf29\xa7\x11s`\x01\xc9\xcc7\xab\xdd\xdev\ +\xf1No\xc4k_|\x19\x13\xfb62z\xc4\xd5H\ +\xe7\xad\xc7\xbb\xe4\x0c>n\xd3%q\xee\x12\x02\x11\xff\ +G\x7f\xc2\x93\xb5\xfe\xd0?K'\xbb\xd6\xcb\x8a\xeb\xca\ +hp\xa3\xc9\x89\xc0\x93\x13\xfcgX\xfd\x9c\x14\xbcO\ +c\xd9\xd1/J\xb7s\xd2:\xb6I\xf0\xed`\xb2\xea\ +\xd1\xa5\xce\x8e\x8936\xfb-\x1e?\xba\xa3\xb3e\xff\ +\x96\x8f\x1e\xce\x083\xde\xf8x\xf1(\x8b\xb1\x8dv\xff\ +Pz\xdb\x89g\xb4\x94\x17t$\xd1\x8c0Ug\xb8\ +\xa4n\x9d\xa2M.V~\xbd\xf3\xe3\x88+O\xf5\x92\ +,V|\xeaY\xef\xd0\x95u\xaf\x1a9,\x8b{2\ +H;\x90\xe4\x05mp\xb0\x5c\xb0\x22 \xb6\xdf\xc9\xc9\ +\x8d\xdf\xd7\xd2;\x15\xe5[sd\xab5i\xef}Y\ +#\xb6f\x9f|\xd52b\xb0\xc7v\xaf\x96#\xb6\x7f\ +\xabW?\xec$g\xb8\xd7+\xef\xd5\xadr\xc3\x1a\xf0\ +\x8e}\xb7\xf7J$\x9b~?\x14io\xd4\xd6v\x9c\ +Wo\xd7\xcdHrd\xae\x89\x8ey\xf1\xe3/\xf7\xb7\ +u\x17\x05L\xd6{\xe6\xbbi\xb2A/\xb7\x99:5\ +\xd1~\x9fH\xca\x99\x17\xb39h\xae\x8a\x0f\xbb\xd3I\ +t\xa4\x1b\x10[4\x12\xee\x84\xbf\x1c7i\xed\xa0O\ +c~\x8e\xaa7\xb5M\x04\xbb\xd6\x04\xaf\x88\x87aM\ +\x9b.\x99GD\xce\xbb\xf2\x83\xb1\xd3z\xa3\xf9d2\ +Z\xff\xe6\xe0#]\xea\xf6\xcc5\xdcy8L\xb7\xd5\ +\xfe\x80\xdd\xd3\x82[&\x7f\x08\x09\x22L\x8fjZM\ +h\x8f\x94\xc6\xb6S\xb4j\x866\xfc\x1a\xd6\xe0\xad\xc6\ +\xf5wo|\xff\x193\xd8>\x7f]\x8fh\xed\xb3l\ +\x8fFJc\x16\xab\xb4\xd5%\xb6D\x1c\x9d\xc9c\xd4\ +\xf7l\xf2|Y\xd7\xa1G\x1b\xb0u\xb9\xf1K\xbd\xce\ +\xf6\x9e\xe3\xfdj\xf1\xa4\xda\x8c\x0b>J:\x0d\x88\xd5\ +K\xff\xd3arW\xf7\xf4=\xff\xa5\x85\xb6\xe5\x84\xb9\ +a>\x0d\xa632\xa6\x0e\x1f\xff\xc6\xf2\xafP\xfb\x80\ +\xe9\xce\xef7&\xf4\x18\x10\xc7\xaa\xd1\xe2\x8c\xf2\x93\xab\ +\xea\xe6\xc4\xc1\xf1\x96;\x8dr>\xbeY\xb89\xf8\x00\ ++9b\xf0=D`\xaa\xcc\x06\xad\xf7\x07$\xf9\xf6\ +\x9e\xd6\xc2\xcfq\xc6D\x87\x9d\x9d_\xea&Y\xf4o\ +\x15\xe9\xb6\xccs/c\x5c(\xa2\x7fD\x0c\xc3\x1b;\ +j\x1bu9\x1e\xd6y\xe0a\x9b+A\x93\xdf\x8f\x1e\ +\x18\xf9\x99\xd8\xf3\xb8FT\xb3\xbb\x7f\xeb1u\xf3\xb3\ +Ng\xcdo\xbb\x93az\xe5\x96\xff\xdd\x9d+b\x0d\ +j\xee\xbag\x8a\x04\xc4\xe3\xec6\x0b\xba\xc6}\xed\x91\ +\xd0\xd0B\xc5\x88x\xdc\xc0m\x06\xc3\xb0\xaf\xf7$'\ +\x86\xe9)\xa4\x02<\xfc\xc69\xf4\x8e\xd5\xd4\xa0\xcd\xc5\ +\xad\xe8\x17\xcd?\xd76\xce\xbd\xc8\xa9\x1f?\xb7\x0e\x91\ +Q\xc7\xc2Q\xdbo\x0as\x87\xf2F\xf4\xa1a\xd8\x14\ +\xe6\x8aE\x97Fh\x11\xdf\xda!\xfa=\xdbU\xe9\xd2\ +M\xa5\xc8\xa6.\x9ai?\x12\xc7\xef\x8b\xea\xb6\xda\xa7\ +\xf9\xfa\xcf\xeb\x0f\xfd\xe5\xe9d06\xcfe\xdd\x80\xf0\ +L\x86y\xd2\xc8\xb6\xfd\xaf\x9b$\xce\x0f=\xefS\x7f\ +\xac\xfa\xa5\xd5W\x1c\x13\x02\x88\xfd\x13\xbb\xe6\x9e\x9a\xef\ +\x16}w\xe1\xf0\xcf[&\xf7\x8e\xba\x97\xc9\x08_9\ +\xb3\xcd\xbe]\xa3\x07\x0e\x0b\xfd:\xfb\xdb\xf4\xd9\x86^\ +ji\x1b\x88avZ]w.\xe3\x8d\x1c\xd1jM\ +\x07\x93\xc0K:./V\xc1o\xb3I\xaf/\xef\x8f\ +\xe4\x18tk\xaa\xd9\xf3\xfc\x0bc\xe6\x05eS\xeb1\ +ow?\x1f}\xf1\xfa\xcf\xe8\xff\xa6\xcf\xd9\xb7\xb7\xd7\ +\x9b1'\xf7\xd7\xdc\xcb\xd6ws\x1d\xd5rWd\xc2\ +\xe9\x88\xe9\xc4X5\xe6$\xd2a\xf7s\x87\xd6n]\ +{^[AL^\xa0\xd4G\x97\x18\xba\xa5\xdf\xe6\xc3\ +:\xdc\xa9['\xb57u9\x8a\xfe\xc84\xeb\xf6\xb3\ +m{\x87]\xf2\xeb\xef\xd6\xd8\x8b\xf73\xf9\xe5\xfd\xd7\ +\x0c\xfd7u&\xae\xda6\xad\xf3\xba\xe6\x91J\xe3\xe6\ +\x1b\xeee\x98w\xadG\x5c\x1a\xbc.d\xdc\xe2S\xf5\ +\x88\xc9\xec9\xad\x1e\xb1<\xbb\xf4\xd5%\xea\x1b+\x9b\ +\x12FV\x9b\xcc\x88\x16\xadm\xfdf\x84\x12\xfa\x19F\ +\xaa\xcc\xe7_l7\x84o\x8f\xbcOx\x1f\x8dR;\ +9\xacc\x1d\xa2\x85\xc6<\xe2\xdd(\x97n1\x83\x08\ +\xe5\xe0\xd5}g\xae7\xad=\x87\xd0\x5c\xab\xa5\xcc\xec\ +3\xf6fH\xaf\xa4\x07\xe8OG|\xec\xbfo\xc8\xdc\ +yZ\x17\xedj\xeeX\xdb\x8bh\xd5\xac\xc6\xf8\xc5\xbd\ +\xdb\xd6\xdf\xd0b\xd2\xbeG{\xfbr-\x0e\x1e9\x90\ +k\xbdr\xe2\xe0Y\x0e\xfa\xcf\xd0\x147v$n\x0e\ +S\xc9\xd0KRz|`\xba\xcb\x85\x88\xf3{g\xe5\ +\xee\x1b\xa7\xefy\xbd\x9d\xf3\x05e\xfd\xc0v7:E\ +\xb3\x9e\x8fq\x19\xd6\xf7\x90\xe7\x93!\xad\xd0\xb4/>\ +\xef\xb9~sN\x0b7\x8d\xe17C'\xadm\xf3\x00\ +=\xc3\xe5~\x92\x92G\xffK\xad\xcf?i\xa8\x1f\x93\ +Nh\xf6\xd66\xb4a\xde`\xd4\xde[{\xeed6\ +\xc9|\xa4L\xec\x1d\xf9\x15\xe9\x19?}S\xd6\x0e\xd4\ +{\xbaA\xd5\xd0B=!\x9f\xd8\x9b\xb8\xf3\xe4\xa4\xff\ +\xc6\x1a_\xad\xad\xbaanGb\xf2y\x82\xa1J\xd4\ +\xbf:_\xc9\xdc\xdbw\xcb\x1eUu\xed$\x8b\xbf\xd7\ +[LVE\xbff\xbe\xbb\xa7\xc9L:\x1c\xceza\ +g\xb82\xf9\xf5Q\x1de\xd3\xd6\xfb\xf5B\xe3'\xaa\ +\xb9G\xdf5@\x8a\xe1)W^W\xdb~D\xab\x06\ +=\xb5-\xbf\x9f\xd5g\xec\xbf\xe7\x19A\xe8\x07\x13\x84\ +~@g\x0e:&?}S\xdb!-\xb0%\xd7\x9a\ +\xa1\xff>\xbe\xc3\x16\x06\x11\xb3\xc5\xdcpO\x96\xaf\xf5\ +h\xe6.\xd5\xf53\x1e\xaa\xce~}\xf4\x84\xf5\xb6\xbd\ +\xc8\xea\x7f\xd6\xc1r\xe7]\xde\xbbq\xc7\xb3Z\xa7\xd5\ +\x09[\xea5=^M\x8bX\xbb\xbfy\xf0\x14f_\ +\xa4M\xec\xe8\xb7\xbb/\xf7x\xd2\xae\xf3\x0dU\x99c\ +\xd8!s\xda\x07O\xbf\xc7\x1c\xcb\xd1~\xd9\xc1r\xf8\ +\xec\xad\x1aF\x84M\x84\xde\x8ba\x0e\xed\x17\xd6\xe8`\ +\x93oc\x9a\x95br\xe3\xb6\xd7\xb3\x96\xc1[\xb4\x08\ +\x7f\x9b6\x06\xfd\x1a!]jo\xd6|+\xf7a\x1e\ +\xb5\xba\xc4\x06\x04\xd9\xa8\xdf\xd0Q5e\xfc\xd4X\x8c\ +\x14\xef\x91\x17zv\x5ct\xab\xf7\xb9m\xee;\xf5\xbf\ +\xdc\xef\xb0\x8d1\xcet\x8b\xc6\xe2e\x1e\xbb\x947\xb5\ +\xf1\xb7\xe9\xa5\x7f\x97\xdct\xe9\xb9\x03\x93\x91v\x0a1\ +\xc0\xb0\xb5\xef5k\xaan\x18\xf1\xe9\xda'\xfd\xfaK\ +\xea\xeb\xe5)3\x1f\x05-\x1b\xd1\xf8L\x07U\xd3\xbf\ +\xfe\xeewy\xa3\xa5I\xe8\xdd\xbdd\x5c\xaf\xcf\xb9\x87\ +w;\x99\xac\xf0\xf3\xbfk\xd0\xef\xd6\xa4Z\xca\xa7\x1f\ +\x7f\x9a0e\xbbZ\xf7\xb9\x03-\xe2FO5\x08\xe8\ +\xban\xd0\xf6\x7f]\x86\xabX\xb6u1\x22F\xdc\xce\ +\x1d\xb5K#\xb9`d\xff\xd6w\x1f\x8c\xe9\x1a\xe1\xa0\ +\xd9\x92\xbb\xa4\xcf\x12\xbb\xe5HC\xdc\xbcC\x8bh=\ +\xea\xc5r\xc3.\x8b\xe69\xab\x0d\xeb1\xef\xe4\x7f\xde\ +\xbe\x83\x8fv9\x18\x96\xdf\xb1\xf5\xdd\xa1\xe8\xdbO\x8e\ +\xd8\x9e\x1fb=4\xe4\xb9\xadMv\xdb\x81\xa7k#\ +\xbd;\xc5\xb9\xd9\xbeNC\xbe\xe4em\xb5\xf9+\xe7\ +!\xd1\xf6\xeb\x97eC\x8ef-\xa8\x994\xf6\xe6\xd2\ +\x7fz\x06\xb9G\xa6\x04\xc5\xa3/\x0e[h\xfd\xc4G\ +\x89\xc8\xbe\x1bc8>\xfd\x83ql\x0a\xdaJ\xc3\x09\ +\x17\xff&<\xf2\x07\x1f>\x1f\xd7m\xc5\x93\xcfz\xe6\ +\xc4\xa4\x83/\xbe\x1d\x1ci\xfdU\xfd\xe5{\x86\x85\x0f\ +\x19\x96\xbd\xda\xdd\xd0$\xe6D\x80I0\xf1.\xea\xc1\ +\xb2!\x17\xcf\x9d`\xaei\x1e\x13\xbfJi\xdel\x9f\ +v]?\xccn\xdb/0\xf6\x08\xfc\xb3\xc7\x13\xaf\x8b\ +\xbe\x11\x83\xf3L\x8dbB\xcey\x0e\xed\xeb;7\xdc\ +6:bl\xae\xcb~\xf4D\xd7\xdc\xce\xa1\x84\x07R\ +\xecn\xed\xff\xd8\x93\xf1a\xc7\xbd\xa1S\xf7\xac\x8bc\ +\x9cE[x*\xbaf\xbb\x8f\x19~\xdd\xb2}'\xcc\ +\x1b\xf2\x06\xcd\xe0\xe7\x87\x10\xdf'\xf6\xb7\x91\x98\xe9\xe3\ +\xf7%\xe5\xc3\xd0\xed\x8e\x0c=dCL\xb0\xf4\xbe\x1a\ +\xfeiB\xa3\x03\x99K.\xeb{\xa9(\x9f\x1e\x81\x98\ +\xdd\x88\xd1\xea\x8d\xda_ne\xb9\xa4\xaes\x96\xde\x83\ +\xcc\xa6\xcd\xe3C\x92?\x0c\xcc\xf6\xdf\x8e\x1e\x14i\xce\ +\xb9P\xb7u\xb3\x86\x97\x06-m\xa3\x17rr|\xbe\ +A\xac\xb6\x9d\xde\x9e+\xcdV=\x98\xb0\xe8B]\xce\ +\xdfs\x89\xc8\xc7\xed\x86\x9b %\x1d\xc9\x01\xad\x82\xb3\ +\xa3\xf3kOz\xec\x917\xe6h<\xd2W\x8cx\x07\ +V\x9e\xe7\xee\xe8B,98,%\x06\x09\xfb\x88\x87\ +\x1e#\x8cb\x06.\xf3\xa8\xbb\x93\xccWC\x9b>\xde\ +\x7f)\xd2\x9f\xe3\xaa*\xf7\xcb\xfa\xe1\xd0\xc3\xfar-\xa4T\x0f\ +\x1a0z\xf7\xb2\xb7\xa9\x8f~\xe4\x8e\x5c\xe3\xfa\xec>\ +\xb1(\x1c)acN\xa5\xb5\xbf\xa1\xe2r\xd4\xd9\xb4\ +\xad\x0e\xcb\xa9\xee\xf0\xc3#\xde\xbal\xf7\xf9Z\xc0\xdd\ +\xf2\xa9\xf1+\xa5+}9#\xdf\xbb\xdf\xff\xef\xd4R\ +\x8dh\xff\x94\x95\x0b\x88#\xdf\x9e\x0c\x9a\x9e?x\xc0\ +\xa4 D\xa8\xedUagG\xcd\xadS\xfb\x7f5>\ +-\xb4\xb6\x7f\xfaj\xa7\x9d\xe1\x1c\xe2\xc8c\x0b\xe5A\ +n\x93yK5N\x06\xbe\xbbP_\x95\x196%j\ +\xcd\x0a\xa4\xf7oe\xaa\xdf\x0e\xccP\xaeC\x8cDS\ +\xae\xc3\xd8\x969 ^\x0d\xd91#\xfc\xf5-\x0f \ +\xec$%7|TC\xe7qK\x17\x13\x95;\xeaL\ +r\xc4\xe1\xd0]\xce)\xc4\xc0\xe0\x9e}&\xe43\x02\ +_\xdcP7\xef2ou\xb0E\xe6#K\x9b\xe4\xd8\ +\x19W'\xf1\xfa\xb4$\x1a\xb9\xa9\xc7-\x18R\x13\x1d\ +\xb6\xe1\x8d\xb7\x8c\x08_\xb0<\xe2\xca\x89\x84\xab\xe6\x8c\ +\x18-\xa6\x17\x9a\xfc\xd3.Mw\xd8>D\xa6'R\ +\x05\x1d\x8f>\xb4\xf8y\xf6]G\x15o\x15\xf3\x80\xb0\ +\xfc\xd1H\xa1\x8b\xab\xb3Q\x09\x99M+rr\x5cg\ +\xe9\x9e\xfb\x97 fw:\xec\xf82a\xe0\xc2e\xc9\ +c\x89\xe4\x08\xf7\x8c\x1d\xe6\xc1\xdbR;\xab\xe8\xde\xbc\ +\xe8t\xfc\xc1\x85\x1e3\x03\xfc\xaf\xd6\xbe\xe8b\xfb\xe8\ +\xda\xccN\xb9_\xf4c6\xd9\x5c\xbc\xf3@\xab\xb1\xd5\ +\x93\x9c\xb9\x96\xd7\xfc\xefn\xbb\xe1;q\xd6\x15\x8ei\ +\x7f\xb3\x85D\xcd\xe3G\x9e[\x052G\xfb,M~\ +\xdf\xc6\xe1\x8c\xca\xd7\x1e[\x18\xc17\x89\x01\xce\x83\x07\ +\xaeP\xd35\xfc\xd9*\xd4\xd4\xb5\xc1\xd8\x94k\xc3\xee\ +^\xb9\xa1rzo\xbakw\xa4\xe09X?gn\ +GV\xb2\xf1\xfa\xe3Q>\x8f7\xa5\x1f\xe7\xe8\xeb\x13\ +\xf5j\x18\x22\xf6\xa1\xd2c\x9bF\x80\xf5\x8c\x8e\xbd\x9f\ +u\x9c\xbf\x02-\x7fj\xf2\x97y\xfb#G\xdc\xf9\xaa\ +E4\xd4PR\x0a\x9e\xf83b\xdf\x82\x05+\x9a\xba\ +\xda\x05\xecF6\xf4q\xafnGf<\x89\xe3|\xee\ +\x01\x8ap{\x87\xc5c\xd5\xc9q:\xc4\x8d\x08\xf7s\ +\xb9\x8b?+\xa9\xde\xb3\x9f\x12\x95k\x85\x9e\xd3)\xe0\ +K\xf4\xfaUwn\xab\x87\xab\xc4\xac\xf9Y\x7f\xc2b\ +\xc4\xff\x0f\x8fU\x03=\xf7\xef\x8fK\x8f7\xdf\xf7\xe9\ +^\xe0\xc2\xe3\xb3f\x84~tr\xb8\xf2\xa0\xf7!\x86\ +\x97z\xda,\x820E[\xb4\x860\x8bpw\xcb\xd8\ +\xc4\xd0C\xa2\xa1K\xf7\xc8\xef\xef\xbblB{\xfci\ +\xfd\xa1\xd8\xcfw\xbb?m\x9f\xbe\xdbA\xdb\xe1q\xbc\ +uk_\x15W%\xcd\x03\x9d\xda\xb9\x1c~\xf1\xcd\xa8\ +\xe7\xd5\xcf\xd9>\x13W\xd7\xf3\xb7\x9e\x911\x17)\xd9\ +G\xfe\xfdt\x1f\xbd!):j\xe1\xa5<5\xf7\xe9\ +\x84\x1da\xef\xd2\xa9\xdd\x9b6Zis\xdc\xc8\xd3_\ +\xf7|2<\xf4\xe2[V\xcbg\xb7\xee\xe4\x05\xef~\ +\xcf\xbbY?u\x9a\x11o\xdcuu\xc2\xbbi\x8c\xcd\ +\xbeq\x0d\xd0\xcbu\xd60/\x9e\xf1\x8ex\xd9q~\ +\xcf\xbc\xc5\xbbs\x8f\x91\xa6\xf9\x9d\x08\x82C\xc4\x9c\xb7\ +\xd9~\xb1\x1fb0G\x8e4\xf5\x9d\xfd\xbe\x8b#\xb2\x01\xbe\xcf\ +\x9a\x9f>\xb7\xddS\xfb\xc0n\xf6m\xb3C\xac;2\ +;Yu\x0fvq6\xfdQ\xab\x07\xd2\x8dW[]\ +\xf8\xdc\xb56\x9a\xe5\x07\x86\xdb\xd55\xd3b\x93\x0f\xe8\ +q{\x1cLV\xc2\xeb_H,t\x1b9\xfa\xad\xba\ +\xea\x86\xfc\x90\xfe{T785\x8b\x1ap/om\ +_\xe7\x11\x81\x88\x16\xde\x98\xacI\x8f0^t\xd0\xc5\ +\xec\xfekD1\x09\x0fM.G\xaa\x10>mB\x9a\ +\xfc\xdc\x7f \xdby\x87\xdf\xec\xf8\xcb\x0dk^~7\ +\xa2\xe0\xca'\x87\xb6\x1f\x95\x08c\xada\xdf\x94\xf4\xea\ +\xf0\x9a\x8c\xe8\xab>.\xa9\xb7\xe6\xbe\x03\x93/\x87\x14\ +\xa8\x04+[\x85\x8ckqaD\x7f\xcf\x90\xf9\x93\xeb\ +0]l\x87\xd6^\xa6\xa2\xd9\xf3\xcd\x9au\xba\x9d<\ +\x8f\x0d\x8f5~W[\xdf\xfaXC\x1f\xff\x19\xaf\xee\ +2\x82\xa7\x10\xfbZ&\xaf\xcfU\xcb9\xaa\xd2\xf6A\ +\x13F\x8bGm{g\xcc\xf68\xf6/s\xc0<\xec\ +\x0c\x9c\xb0\xca\xcc\xcb_\x85\xb0Z\xa5\xbfO\xf9\xe0\xcc\ +\xec\xa9#\xbc:\x12\xc4\xed\xb6\xdc\x14'\x8f\xb3\xc7\x12\ +\x17\x8df\x9c6\x19e5\x92\xad[\x7f\xfcp\xdf\x1d\ +zy\xef\xc7\x8e6#\xe08L%\xec\x22R\x0f9\ +e4\x9a\x12\xa7K^\x8a\xef\x1c\xf9Z\xc5hf\x8d\ +(U\xcd\x8b-\xb6\xf4\x0aHX\xa5\xc2\xbc\xeb\xa5\x19\ +\xa04h\xc9\xed\xc9\xb7\xdfL\xed\x98\x98\xa8\xa4\xd5k\ +\xdeR\x13%\xadC\xf6\xb9\x83\x9auGH\xcb\xbb~\ +*\xe8\xdd\xb0\xc6\xc1V\x7f\xf5\x99\xb8w\xd8\x13%\xed\ +\x13G\x97\xb6%\xb2\xdc\xb7\xeah\xe8_\x9f];\xf8\ +\xe1\x92C\x05S\x22\xd2\xea\xed[\x17\xed\xc8RvJ\ +Zu\xed\x8b\xbdC\xf3\x89\xb7\x9c\xcc\xb6\xaf\x19\xb5\xb1\ +\xb9\xe9\x7f\x87w\xae;\xb9\xf4\xc8\xe2\xf5\x83\xae>\xe8\ +\xdd\xcc\xdc\xf5\xb9\x9a\x93\xc7\x1c\x8d,\xff\x05\xb5'\xf6\ +\xd8>{\xfb\x9a\x995\x062\x1f\x1bjd\xf5Z\xa0\ +\xfdz\xecv\xf3\x9a\x9a\xff\xde\xcfz\xa21M\x93 \ +\xd0\xef\xff;4\xc9>\xf8,Ah)\x0djs\xed\ +r\x86r#U\x22XS\x7f\xc9^w\x17=oc\ +\x82\xb9\xa1\xa6\xd5\x8e\xbd\x1e\xdd\x1b{]\xe10\xeb2\ +\x88o\x17j\x06\xd5\x98Z\xa7~\xb2\x81J\xcc\xc8\xae\ +\x17\xd8\x86\xd7\x92//\xb2\x8b\xbd\x9f\x10sCyP\ +|\x07\x22\xef\xd3\xe5\xc1\xfd\xdexg{\xdb\xda\xfd\x8c\ +K \x96\xadw\x1cT\xaf\x8b\x8aWF\xe7w\xf9g\ +\xeb\xf6\xad\xf7\xc9\x09{\xbcG\x13\xc9\xb7\x82\x8c\xf7\xf5\ +\x9a\x10~*a\xcfG\xee}\xbf\x99c\x10Q\x9e\xee\ +z\xeb\xadZL\xbf\xdb\x81Zk_+\x8dZ\xe7q\ +\xa1Y\x1c\xc3\xfc\x87\xb3\x97\x9d\xb2W7\xd3o\x7f\xfb\ +\xa2\xfd\x8d\x1e\xd6\xc8\xf4(A\x80\xdf\xbc\xb1\xcf\xdb\xe0\ +&?\xafk\xfe\xfb\xa3\x9dO\x00\xef\xbaM\xff\x83\xb5\ +\x01\x1d\x16Z\xc1\xc6\xb6u\x9a\xf8=\xfd\x1f\xb3K\xef\ +\xa1y\xb9\xe7\xfe#\xb4\xb2,\xefE\xc5\xe87\xef9\ +\xa3\xf6\x87\xfe'\xa3\x875v;\x12\xc1 \x08\x1c\xc3\ +\xe8bT\xf3\xf1\xda\x09\xe1c\xde\xec\xee\xe1oqx\ +\xf2A\x0d\xc2\xb1Y\x8d\xc6\xa7U\xfa\x1f\xb6Y\xebd\ +8m\xeb\x94t=\x8f\xe9\xe9uw\xd7b\x0e`k\ +\xa1\xa7\x987\xbf\x18\xdf\xce\xe7<\xef\xa0M\xffK\xf1\ +\x8f\x09\xa3\x1f7T\x1b\x13\x1bTn\xd5\x1e\x16\xfa?\ +\xa6\xde\xe9\xcf\xc9\x87\xdd\xd5'\xb6\x1f\xaaf\xda\xdc\xae\ +\xff\xab\xa9\xe1\xf5\xda\xfd\xa4\xc2\x16>\xf3\x03L\x86u\ +\x8c\xe9\xb2s\xa9\xd2\xe9\xbd_\xfe\xa7\xa5j\xa5=\xbd\ +\xc7\x193\xffQ\xdf\x16\xb5[\xf4\xbc\xe0\xdfE\x17\xd2\ +:\x8cl\xfc\xb8\xc3\x95:\xcc\xb9\xebX\xa75\x82\x0d\ +\xd8W\xed\xcc\xdb\x8e[\xdcn\xd1\xd3\x95\x8d\x09N\xe3\ +\x0f\xdb\x03\xd4#\xb6\x5c\xdfa\xa0t\xba\xa1\xdd\x943\ +\x1a\xd35\xb3~\x9a\xf0j\xd4Q\xbd:\xac\xbfg\x0c\ +s\xca\xfb\x89\xe1\x86\xebG\xf8\x9b\xaf~\xa2F\xfc\xb5\ +\xf65\xa9\xdc\xc0\xa2\x87\x91\x96\xb6\xdfr\x08[\x0d\x1f\ +\x08\x1c\x11\ +\xe8\x15\xd5\xf2\xbe\ +\xeaA:\x8d\xbbr\xdb\x05\x02\xf8\x07\xbb\xa2Z\xcf\xaf\ +\xba\x10K\xe3Pb\xfc\x0b\xe0^\x8fUm\xdf\xff\x0e\ +\x10\xc2\x12\xf0\x11I\x88{\xf0+\xeeV\x80\xb9W\x83\ +|`7K\xc0W,\x01\xfe\xc1\xb7\x5c\xed\xd3\xfd}\ + \x85\xc6\xa9X\xfc\x0b\xe0\x1ebK~\x0a0\xe7j\ +\x90/\xf8\xb1\x04\xe2\x86\xa5\xe0\x1f\xe2\x8b\xd5\xb6\xde\xef\ +\x07\xf94nK\xe0_\x00\xf7\x90_\x10\xaa\x00s\xad\ +\x86\x8a\x81P\x96@\x0e\x89\x08\xfc\xcfb\xfdI\xb9\x1b\ +\xcbu\x11\xe8\x90,\xcb\xa64h\x93,\x0bm\xea\xff\ +\xad\xf5\x114'Y+\xf4\x05~O\xff\x9b\xa5\x0e\xf5\ +=\xf8~e\xaf\xa1|\x00\xb85\x13\x83\x7f\xc81\xbb\ +\xa5\x00s\xfc\x05\xf8Fx\x5c\xa1G&\xad\xed@&\ +o\xecI\xa6\xed\x9fHf\x9cYJf^\xb6#\xb3\ +o\xed\x22\xb3\xfd\x0f\x90\xb9\x0f\xce\x91\xb9\xa1\xee\xe8\xe7\ +Y2\xdbo\x1f\xfa\xbd3\x99yi\x1d\x99\xe1\xba\x88\ +L\xdd3\x86Lfv'\x93l\xdbS\xcf\x85\xe7\xc1\ +s\xad\xaa\x04=\xf8\xd0\xb8\x16>\xfb\x90g\xf8\x1b\xe6\ +\xeb\xe9\xd2\xe7U\x17\xe3+u\xe702\xf3\xe2\x1a2\ +\xe7\xbe+\xc9\xfe\x18JrS\xbe\x91\xbc\x9c4\x92\xc7\ +\xce#I\x1e\x8f,up\xb9\xe8\xefrI^v*\ +\xc9I\x8a!\xd9\xefC\xc8\x9c\xa0cd\xc69K2\ +e\xdb\x002i\xb5\x01\xcd\x17\x14\x9a\x16\x92i\x5c\x0b\ +\xe7\xf28*\xc0\xdc\xe4\x07p\xd6\x11\xafNZ\xd5\x86\ +L\xdd=\x86\xcc\xbe\xb9\x13\xe3\x8b\x9b\xc1Bx\xe4\x94\ +\x8e\xe7r\x0e^A>\xc9M\xfdN\xe6G\xdc&\xb3\ +\xbc\xec\xc9\x14\xa7Ad\xd2\xca\x96\x94\xacPL\x19\xe1\ +(\x84{\xb0\x0b\x1e*\xc0\xbc\xe4\x83wt\xfe\x92\xed\ +\xfe\x87\xce\xa5\x05\x99\xff\xea\x16\xc9\xcdL\x92+\xbeK\ +\x1d\x88G\x00O\xc9{r\x99L?f\x8ee\x0c\x9f\ +\xffT\xfa\xde\x14\xc1CV\xf1\x1cR\xb8o\x90\xa4\x00\ +\xf3\x92\x03\xde\xbb\x229\xbd\x96,\x88~\x86\xcee\xde\ +\xaf\xc3\xbb\x88\xc1\xcb\xcb$\xd9\xef\xee\x91\x19g-(\ +]\x01\xf8\x81b\xc8\x85$\x1a\xe7|\xfc\xc3\x9d\x93\xaa\ +{7\x03\x9d\xaf\xa45m\xd1>/#\xd9_\x9e\x91\ +$\x87]\xa9x\x17\x1e\xc3m9\xf6\xb3\xfc\x8e\x83\xf3\xfd\x1d\xf6C\ +\xffB\x1a\xc8c\x15\xd5\xdd`W>\x8eK\x07\xc0=\ +/+\xb9\xb2\xd1T\xa1\xe3\x17\xd3\x00\x9bUT\x8bD\ +q\xf1\x8f\xe4=\xf0\xfc\xdf\xf5\xdc\x0b\x8f\x82\xf8(2\ +u\xd7\xa8_A\x03\x8a\x8f\x7f\xb4\x07\xa0\xeb\xfdJy\ +\x0f\xf6\x04//\x8b\xe4e\xa7\x90\xdc\xac\x14\x1c\xeb\xe1\ +\xe5e\xffR\x9f\x12\xfbs\x18\x99\xb2\xb9_E\xd3\x80\ +b\xe3\x9f\xb6\xf1*T\xcf\xe7\xf1Hnf2\xf6\x19\ +\xe6>\xba@f\xdd\xd8\x86cy\xe0\xb7O\xdd3\x16\ +\x9f\xc3\xd4}\xe31\xff\xc9<\xbf\x92\xcc\xbe\xb9\x83\xcc\ +{z\x19\xd9\xefo\x10]\xa4U\xdc\xbc\xd0\xc8{q\ +\x9dLZ\xd7\xa9\x22\xe3\x06\x8a\x8b\x7f\x88\xd5\xaei\x87\ +\xed\xfb\x8a\x18\xbc\x9ct2?*\x98\xcc\xf2v\xc4\xbe\ +C\xbc\xcf\xd6-\x04\xf2;\x04r<,u\x8arC\ +\xe0\xe7\xca\x968\xb6\x04r\x1ar\x02\x80>y\xf9\xd9\ +\xf2\x9f$\x97Cf\xfb\xee\xa6rP*\xc6O\xa8\xb8\ +\xf8G\x00~=y\xfbv \x0e\x98\xfb\xd8\x83Ls\ +\xf9\x97L\xb25,\xc2o\xb9\xce\x98nal\x19~\ +&\xaf\xefL\xa6\x9fZ\x80\xfd\xfb 7\xe49xH\ +\xfe\x00\xef\xa9 9\xa0\x98\xf8G\xf8\x00\xbe\xcbI\x8e\ +\x93\xdf>\xb2\xf3\xc8\xfc\xf0\x9bd\xda\x81)\xe8\xfc\xb6\ +\x90o\x5c\x9e\x9fg\x80\xf8U\xfa\xc9\xffpN\x89<\ +\xf3\x0b\x0ab_\x92\xc9L\xe3\x8a\xa0\x01\xc5\xc3?\x9f\ +\xef?\xbf&\xb7\xfd\x03\xdd\x11\xf2\xb6\xe0\xb9\x15\x1a\x7f\ +\xa5\xe9 y\xc3\xff\x90\x1e\xe1D\xe5\x99\xc8e\xf0\xc8\ +\x9c\x80\x83\xb4\x1c\xf8\xcd\xf1\x8f\xce~\xc6\x99er\x8a\ +\xe3\xf1H\xf6\xbb\xfbX\xbeS\xb9\x01\xbf(\xd6\x06\xe7\ +t\x85\x1e\x99~\xc4\x8c,\xf8\x1a!\x87u v\x92\ +\xfe\x13\xd9A\xe3\xe5\xed#V,\xfc\x83,Ez\x15\ +\xd8>2\x0f\x1e\x97\xccE\xbac2\xb3\x07}\xe6+\ +\x87\x96S\xb7\x0f\x22\xf3\xdf\x06\xc9\xbe\x1e4\xf2\x9e]\ +!\x93V\xb5&\xe5\xc8\xbf\x14\x0c\xff:8o\x87\xe4\ +\x14\xc8\x8e\xfb\xb0KdR\xe5\xc5\xd5\x04h\xa0)\x99\ +\xb2\xb1'\xd6\x0de\x1d`o\xa6\x1d\xfaW\x9e\xf4\xac\ +8\xf8\xc7z\xb4\x11\x95\xbb#\xdb.\xe1s\xaf\x10\xb8\ +\x17\xa0k\xec\xc7x\x1f\x223\x0d\xe4=\xbbJ&\xd9\ +\xc8\x8d\x07(\x0e\xfe\x11MC\xfe=\xe4V\xcb2@\ +\xdec\x9e\xaf(\xb8\x17\xa0\x81\xd4\x1dCIN|\x94\ +L\xeb\xe3f%\x93\xa9{\xc7\xc9\x8b\x07(\x08\xfe\x91\ +\xce\xbf\xca\x00\xdbg\xb2\x0c\xd0\xf3\xb1\xaeWY\xf2^\ +\x02\x1aH?1\x0f\xdb\xf4\xb2\x8c\x9c\xc0\xc3X\xbf\xfc\ +m\xf0\x0fg\xc3y\x84L\xf6\x12\xd8\xf7`\xe3)X\ +\x8eu\x09:\x07\x1f#\xe4\xfc\x80\x9c\x92v@\x8c0\ +\xd9\xa1\xbb\xfeA\xef?\xbfR\xea\xd8:\xe4\ +\xd0\xa6\x1f\x9eYu\xce\xbe\x00\xdd\x83\xbe\x22m\x9c\x00\ +\xe2\x97i\x07\xa7\xca\xba\xee\xca\xc7\xbf\x95\x1e\x99\x13|\ +B\xaa=\x80\x0165\xbeW\xa5\xe8r_\x04\xfe\xc1\ +'\xc0\xf9\xf1I\xca\x95\xf3\xc8\xac\xab\x1b\xab6\xfe\xe9\ +\xfb\xd8`\xb3K\xb7\x05h\x0f\xaemV<[_R\ +\xb0\xd6\xc7\xb5\x05\xa4\x1d\xb9\x8f\xce\xcb\xaa\x03T2\xfe\ +up\x0d\x05\xb8G/\x15\xfa\x91\x1d\x9d\xb6gl\xd5\ +\xe3\xfd|(\xf4yIwG\x15\xe2\xcc\xf8n\xb1\xf4\ +\xbc\xafr\xf1\x0f\xf1\x91=cp~\x9d4\xa3 \xf6\ +\x15}w\xa6\x8a\xf1~>\x80\x0c\xd8jJr\xd3~\ +H\xb5~NR\xac\xac~\x80J\xc6\x7fSd\xc7.\ +\x90:\xd6\x0b\xb9a\xf8\xfe\x5cU\xd1\xfbK\xe0_\x17\ +\x9f_\xf6\xc7GR\xad\x1f\xf2\x16Sw\x0e\xaf\xc2\xf8\ +\xd7&3/\xae\x95Z\x07\x86\x5c\xcc*\xcb\xfb\xf9\xb0\ +\xb2\x05\x99\xfb\xf8\xa2T\xeb\xe7\xe5f\xcaj\xfbT.\ +\xfe-\xb41\x0e\xa5\x1a\xc8^\x84|\x5c\x9c\x93Y\xd9\ +8\x94\x05\x10\xee\xb2\xfd\xf7K\x87\x7fv.u\x87\xb8\ +*\xe3\xff\xf6\x1e\xe9\xd6\x9e\x9f\x8ds\xed\xaa\xfc\xf9G\ +\xf4\x0by\xaeR\xc5\x03\x10\xdf\xcc\xbch+\xcb\x19\xa8\ +\xba\xf8\xcf\xcd\x90w.D\xa5\xe1\x1fp(\x95\x0c\xc4\ +\xf8_\xfbg\xe2\x1f\xd9~`;T\xc2\x9d\xe9\x0a\xc0\ +\xbf\x94:\xd0\x9f\x8c\xff\xbcL\xaa\x96\xce\x9f~\xfe/\ +\xfd\xa1\xf8G6\xa3\x9cb\xa0\x95\x0bh\x0fp\xec[\ +\x9a\xc1- 3=VWi\xfcg]\xdf*\xe5\xda\ +e\xd6}\x14\x03\x90\xed\x0e\xf9<\xd2\x0c\xea\x0c,\xa8\ +\xba\xfa?\xf0\xbe\x0b\xab\xa4\xce\xf7\x85\x1a\xbdU\xd6\xf7\ +\x8fA\x17\xe7r\xe6=\xf7\x96\x0e\xff\x10\x03t\x99V\ +\x85\xf1\xdf\x14\xdf\xb3\x95\xf6\xce\x1c\xd4{\xabRq\x7f\ +a\xa0\xef\x0e\x16\xc4\xbd\x92j\xfd\x90/\x97\xe24\xb0\ +\xea\xfa\xff\xe8\x9cX\xf0cJ38?>\x90\xc9\xf6\ +\xdd\xaa\xb4\xff\x1f\xfc\xb7\xd2\xd6\xa6\xe5\xfc\xf8\x88k\x9d\ +V\xd9\xf8\x0f\xd0\xbf}W\x8cGi\x06\xf0\x8d\xb4#\ +U0\xf7\x83\x0fh\xdeR\xeb\xfeh\xc0\xbd\x22|\xa7\ +\xb1\xaa\xe2\x1f\xe4\xdfj\x032?\xc2O\xaa\xf5\xc3\xc8\ +\x09p\xa9|\x8f+5\xfes\xee\x80\xde#\ +3\xed+ \xfe\xab\xe8\x99\x96\x14 \xe7\xcdy8\xc9\ +aI\x97\xf3\x08\x03\xe7}\x1c1\xfb=\xee\xff\x08A\ +\xd2\xea\xb6\x94M\x83\xf7J[\xa06\xd3o@\x13r\ +\xaam#'\xde\xafx\xf8\xb7nN\xd5S\x8b\xbaG\ +\xe6\xdc=\x8a\xefHA\x0d>\xf0q`?\x1f\xbfO\ +\xdf\xf2\xaaK\x13YW\x99\xb2\xd54\x83\x9c\xf7\xeb[\ +\xe5\xc5#+\x06\xff\xfc\x1e{\xe5\xd1M\xf9w\x01\x04\ +s!9l\x1c\xe7\x87\xfb\xae\xe0\xeb\x85Zx\x90\xef\ +\x04\xf7\xc5\x92\x90\xee\xcf\xe2\xf7\xd7*F\x13\x95\x8fc\ +\xd1\xeb\xd3\xa1j\xd8\xcaX\x13\x8a\x9b\x1c\x87\xfb\xcc\xc9\ +)\xee!\x1f\xfc\x0b\xf6TD\x9f!\xa7\x15d\x1c\xf4\ +\xd9\x93\xf8\x9e:\xd8\xc3[L\xca\xac\xf1\x0b\xb9\xf2\xdc\ +\x8cD\xb2 \xe6\x05\xce\xff\x85\xfb\x1f\x10C\x80\xef&\ +\xadmO\xf7\xea\xe4\xd3\x84\x82\xd0\x03\xd4\xb0\xdd?\x09\ +\xfbke\x1d\xd0kP\x8e\xf6\xaet\xf8\x17\xec\x99\x8a\ +e\x9a!\xa2\xc9\x81\xb8njN\xd0Q\xaa\xa7bV\ +2\x99\x1f~\x0b\xcbs\x89\xf0 C,\x08\xbe\x03t\ +\x03\xef\x85\xde:\x99\x977\x90i.S\xc9d\xfb\x7f\ +\xe4U'Av\xdc#\x1e&\xeb\x80\x9er\x10/\x91\ +c\xceS\xf9\xf0O\xf3Y\xd0a\xe0\xbcA\x1fT\xa8\ +K\x07\xfd\xcd\xb8\xe9?J\xc85\xcc\xab\x1c{K\xc6\ +\xab\xd0\xb3\xe1,\xcbe \xbb\x0ah\x22\xf7\x89'\xd5\ +\x8f\xb32\xf4\x04\x9a\xe6\xa1\xde\x07\xe7\xe7g\xb9,+\ +\xe7\xee\x11y\xfb\xba$\xc4?\xe5\xa7\x87\xf3\x09\xf9:\ +\xf9o\xee\xa2\xf3\x16_\xe6\xfdu\x9c\xa3\x0b\xb5K\xcb\ +\xb4St\xb1,\x97w\xad\xdf\x9c{\xa7*\xe7\xfcC\ +/:[C2\xcb{\x93\xdcj@r\x12>P=\ +b\xe4\x9b\xef \x19\xfe\xe98\x1d\xf8\xdb\xcb;p\xfd\ +\xe2\xb2\xe6\x0c2\x04\xe2\xe0H\xa6\xcbm\x94\xea\x1f\xaf\ +\xa8\xfa\x9f\xd4:\xa1\x96\x0d\xd8x\xf2\xaa]\x0c\xcf\xc9\ +\xf4\xdcP\x11\xfa\x8c\xe4\xe7_\xcaX\x15\xf0\x8a2c\ +\x94\xfc\x1a\x10H\xaf\x93\xd7\xc0\xb91H\xee\x96\xe0=\ +\xd0\xf3\x9b\x9f3\x22\x97\xfe{\xba\x85\xf2\x18\xees\x03\ +\xbd\xcb\xb3n1\x0c\xe8\x0f%\xe3=O\x19\xf1\xdfL\ +j\xf9\x0cr\xa2\xa8\xd7\xa1\xf8g\x83]'\xed=X\ +Q\x03\xe7F\x80\xfeWl\xcf(9\x96\xed\xbb\x0b\xdb\ +\xd0)\xdb\xfac\xba.\x9fO\x81_\xfb\x9b\xd2\x7f\xe1\ +y\xa9\xce#q\x7fxN\xc2{\x99j\x18\x89\x5c\x07\ +\xaeiVa\xbd@\xca\x85\x7f\xa87\x01\xe7\xaa<\x03\ +\xdfQBzb\xa9:\x00Z\x1b\x9c\x1by\x0e|f\ +\x84u?~\xad\xa17\x81\xf8o\xb8\xc9_1O\x83\ +\x1c\x0c\xb0U!\x06\x09\xb1H\xfc\x1d\x0bm\xda\xffH\ +\x83\x05m\xdb\xa2gB\xdd\x15\xe8'\x0e}\xbe\xe1=\ +\xb2\xd4\xae)m\x80\x0e\x9by\xdeZ\x0e\ +;\x90\xcc]\x87i#\xd3s=\xf6K\xe6\xdc;\x89\ +{\x89s\xbeGQ5\xfcd\x88\xdf\x949\xd0\x9c\xa0\ +N\x1c\x0b\xf8\x93\x22\xe0\x9f\xaf\xa3\x87]*\xf7R\xd8\ +Q\xc1\xe2u\x00\x9a\xae\xe4a\x1f\xf3\x07\xe8K\xd0\xf7\ +\xbd\x04\xcf\x11\x87\x7fq\x83\xcb\xa5r\xb3*\x12\xcfb\ +F\xde3o\xda\xc7\xaf@\xfd\x7f@\x07@<\xaf\xbc\ +2\xaeT\x1d\x00\xd7\x80\x18+sM\xccb\xefCg\ +\x19t\xf0\x12\xef+/\xfe+i@\xadh\xa8\x11\xa8\ +p\xfd\xbf@\x07\xd87\xa1\xdc}\x8f(\x1d`\xb1h\ +\x1d\x00\xc9V\x88\xf3\xc8\xb3\xb7\x16\xe4\x92%o\xe8\x22\ +9\xffW\xa0\x01\xb8\x87z\xe1\x0a\xd9\xff\x0fx5\xda\ +Wiz\x1a`\xdf\x95\x98gJ{\xffE\xdc\x00\x9d\ +.I\x94\xdcTp\xfc\xffb\xdc\x97\x1f\xff\x00\xd6\xcd\ +\xc9\xdcP\xb7\xb2\x17\x83\xe4&\xf4\xea\x84:\xa7\xb9\x0f\ +\xceQ\xf9\x0a\xd6B\xbeK:\x1e\xce\xd7\xc7\xe55\xb2\ +o\xee\x14\xcdk\x14\x15\xffh\xaf\xf2\x9ezUF\xdd\ +\xf2\xf2\xe3\x1f\xe7\xac\x8b\xb8\xaf\x8ct\x02\x90\xe1\x18\xdf\ +\x88>\xe0o ?\x11\xd7g\x02\xbc\x8b\x8aY@\x1e\ +\x9cC7\x92\x93\xf8En[\x09w\xe22N\x89\xb9\ +\x13\xa7\x80\xf8\x87\x5c\x9el\xbf\xfd\xb8\x1eh%\xdce\ +\xe3\xe3_\xf2\xfe\xcf\xa0\xaf!\xbc\x82_\x1b|\x01\x90\ +\xc3\x086\x01\xe8\x85i{\xc7\xd1\xf8n.YL^\ +J\x9fBi\x03lq\xb1\xf1q\x05\xc3?\xd0}\x86\ +\x9b\x15\x95\xc7P9\xb1j~\xff\xe7r\xf4\x7f\xa7x\ +v\xc6\xd9e\xb8\xff!\xaeA[\x98\x87Q\xce\x1c\x0c\ +\xa8}\xe2e'\xd7=e\x7fyJ\x9f%\xd1\xb6\xa6\ +\x22\xe0\x1f\xfc\x9cy\xe17i\x1b\xa5R\xf3\x98\xf8\xfd\ +\xdfM\x10\xb0$\xff\x9e\xaeP\x8e\x85\xf0\xfcK\xcb\xd5\ +\x16\xf4\xc7\xe9\xe08=\xc8>\x90\x1b\x98\xa7\xc8\xe8\x03\ +\x86\xfb \xb8\x8f\xa7\xa8y+\x00\xfe\xc1w\x04>\xa5\ +\xc2\xde\x93\x95\x83w>\xb0h\xdc\xb7D\x10-\x97g\ +\xae\xd0\xc7>R\xf0\xb3\xe2\x5cNA\x80\xdfa\xff\xaa\ +@Lv9\xe5W\x82\xbb\x1c\x10\x03\x82z\x98\xe0K\ +\x07?\x1c\xc4\xb8\xf7 \x0a\xd2\x0eL\xa2{6T\ +\xfa\x1e\xfc\xa9\x90G\xe3\xb8\xf0\xec\x0b\xe1\xbf1\x82P\ +\xe9\x9f\xaf+$C\x85Aa\xed\xa1?\x05Bi\x1c\ +\x17\xc3\xbf\x10\x0d,@\x90\xaf\x00s\xad\x06\xf9B>\ +\x8d\xdb\x12\xb8\x17\xc2?\xd8\x05~\x0a0\xdfj\x90/\ +\xf8\xb1\x04l>QC\x80\x06\x86#HQ\x809W\ +\x83| \x85\xc6\xa9X\xdc\x0b\xe1\x1f\xfc\xc2\xbb\x15`\ +\xde\xd5 \x1f\xd8\xcd*\xf2\xf5\x8b\xc5\xbf\x10\x0d\xe8!\ +\x08Q\x80\xb9W\x83l\x10B\xe3\xb2L\xdc\x8b\xa0\x81\ +\x81\x08\xbe)\xc0\x1a\xaaA:\x88E0\xa0<\xb8\x17\ +\xc2?\x83E\xe9\x8c\xe9\x0a\xb0\x96j(\x1f\x00\xce\xe6\ +\xd38,\x17\xfe\x85h@\x15\x81\x03\xab\xda&\xacJ\ +\x90O\xe3LU\x1a\xdc\x8b\xa0\x81:\x08vT\xd3@\ +\x95\x80|\x1aWud\xc1}5\x0dTI\x90+\xee\ +\xc5\xd0\x80\x03\xabZ\x1fPDH\xa7q#W\xdc\x8b\ +\xa0\x01\x90)\xa0W\xc4*\xc0\x9a\xab\x81\x82X\x1a'\ +2\xc9\xfbr\xd0\x00\xe8\x94`WT\xfb\x07*\x1fB\ +h\x5cH\xa5\xe7\xcb@\x03|\x1f\x11\xf8\x96\xaa}\xc5\ +\xbf\x1eR\xe8\xbd\xd7\x13\xc4\xc9\xaf\x18B4\x00~E\ +\xf0-C|\xa1Z7\xacx\xc8\xa7\xf7z8K\xc0\ +\xa7\xfb\xabp_\x0a\x1d@l\x09|E\x10c\x962\ +\x87\xa4\x1aJ\x81\x13\xd5\xa3zT\x8f\ +\xeaQ=D\x0ef\xf1\x8fe\xf2\xd3\xe0\xe2\x9fK\xf0\ +\xe7\x98\xe2\x9f\xd5\x84?\x0b\xcb\x83\xb2\xe4\x87\xb0\xbc\x11\ +\x96G\xc2\xf2\xaa\x84<+6A\xe5\x92\xf2PX^\ +\x0a\xcbSay+,\x8fK\xc8kay^\x5c\xde\ +\xb7E?L\x09j\xdf\x19\x84>\xf5{\xf4\x8b\x96\x9d\ +(\x90t\x88\xd0[\xfeB\xd0\x17\xc1r\x04G\x11\xdc\ +D\x10TIp\x93\x9e\xc3rzN\x7f\xc9K\xc7\x12\ +z\x0e\xf8\xe0\x0d\x11\xaccQ~y\xb0\xdd9\xac\xca\ +\xb7)\xf9\xc0\xa1\xe7\x14B\xcf\xd1\x90%\x107(\xef\ +>\x08\xad]\x1f\x81\x13\x828\x05X\xa7\xa4\x10G\xcf\ +Y\xbf\xbc{ \xf0\xf7J\x08& x\xa5\x00\xeb\x91\ +\x16^\xd1kP\x92d\x0f\x04\xd6^\x13\x81-\x824\ +\x05X\x83\xac\x90F\xaf\xa5fi{ \xb4\xf6-,\ +E\xe8\x9d)?`\xd3k\x12\xb9\x07\xac\xe24o\xfb\ +\x9b\xad]p\x0flY\x22\xce\x82\xc0\xfa\xe1\xac\xfc\x0e\ +4/\x0e\xd2\xe85\x16\xae\x9fU\x9c\xcfWe^'\ +)\xbcb\x09\xc9\x05\x16%+\x9d*\x7fn\xbf\xec\xfe\ +\xbc\x13\xab\xb8~\x00\xfa\xc2/\x94\xef\xbaE\xb58\xa0\ +\xee\x06\xd4\xd2Z\xd9\x92\xaa1\x08}\x9c\xa0\xd6,\xfc\ +]\xc5\xf5\xfc\x8c\xa3\xd7\xcc_\xff\xfa_\xb2n\xbav\ +\x14\xf4\xd6\x84\x9a\x0a\x19\xee\xd6dN\xe0!\x5c\xdb<\ +?*\x88d\x7fzL\xb2\xdf?\xc0\xfdgr\x1f\x9c\ +\xc5u\x0f\xd3\x0eM\xc7\xf5\x94q\xcf;\x5c\x0bIn\ +{\xb1\x8eU\xa4\xcfWl\xbe\x0f\xae\x97\xa5\x87k\xf8\ +f\xdd\xd8\x86\xd7I\xf5Z)\xbb\xe7\x04\xd4\x97\x80\xbe\ +O\xb9\x0f\xddp\x0d\x02\xa8\xf5&\xa7}\x08a\x15\xd9\ +2\x15\x14\xcf\xd4\xa5\xeb'\x9a\xe2Z\x87\xd03C\x96\ +\x01\xf56\xf2\xdf\x06\xe1\x9aET}a\x99\xee\xdd'\ +\xb3\x8a\xec8\xf9\xdb2\xb8\xdec\x1b\x5coI\x9e\xb5\ +\xc0\xf1>\xe4e\xe3\x9a\xb0P\xb3I\x86\xda\x03\x1cV\ +\x91\x0d+\xdf\xb5\xa39A\x9d\xcb\xdcG\xe7\xe5\xda\x03\ +Cx@\xbd2\x5c\x1bSz\xfe\xc8\xb7\xdf\xe5\x8aw\ +\xa8\x87\x0a\xfc\xecW\x0c\xa8\xef\x96q\xd6B\xda\xf9\xf2\ +}\x17r[{\xf2\xa6^\xb8N\xe4\xaf\x1c\xd0\x97\x19\ +j\x9bIA\x07Ar[?\xd4\xe1\x5c\xdb\x11\xf7\x87\ +\x96xp\x0aHNR,\xc9~w\x9f\xcc}|\x91\ +\xcc\x09>\x81\xe5\x1e\xd4\xe0+\xf8\x16I\xd5\x84\x95t\ +\x0f\xd2~\x90i.\xff\x96\x97\x1f\xc8o\xfdH\x87\xc9\ +\xf6\xdf\x8ff\x22\x81L\xcb\xcd\xc4\xb5\xc2q\xdf{D\ +/T\xefJ\xbd\x22\xfc!\xfd\x07\xeaiA_\x1e\xa8\ +/\x0c\xfd\x02%\x19\x05q\x11\xf8y\xe5\x90\x0b\xf2Y\ +?\xd4\xfc?4C\xa2\x1eB\xec\xcfad\xfa\xd1Y\ +t\x8fF\xedR\xeb\xba\xf2u?\xa8?\x0c\xb4\xc1\xcb\ +\xcb,\xf3\xf9\xb9\x0f\xce\x88\xaf\x15^\x11\xeb\x07\xba\xb7\ +m\x8f\xf8\xdd\xbd\xd2'\xc6\xe5\x90\xb9\xa1\xeeT\xff\xca\ +\xf2\xea/\xb0G\xd6\xfa\xb8>\x7fY:\x04\x9c\x19\xd0\ +\x19%\xac\x9b)\xfb\xfa\xa1\xcf\xe7\x99\xa5\xa5\xcb9\x1e\ +\x17\xf7m\xa6\xfa\xc6K+\xaf)]*\xfd\xc8,\x5c\ +\x1b\xb8\xb4\x01\xfc\x03j\xc2J\xb0\xc72\xae_\x17\xeb\ +8e\xf5\xba\xc9{\xe9C\xd7\x11\x95C\x9d$\xf4\x8c\ +\x0c\xb7\xe5X\x17\x14\xbb\xdd9\x19\xa2\xfb\xe4\xca{\xfd\ +\xe8\xf9\xd03\x13\xd7\xdd\x1538I1d\x8a\xd3 \ +\x89\xeb\xb8JD\x07\xe8|C\xff\xa1\xd2\x06\xeeMU\ +\xb6<\x94y\xfdY\xd7\xb7\x95:\x8fl\x9f\xed\xf2\xaf\ +\x17\x8cd\x5c\xca\xb6\x81\xb8&\x9f\xb8\x015\x19\xa9^\ +\x83\xa5\xee\x81l\xebG6\x08\xf4\xb7\x12\x8f\xfbXJ\ +G\xaf\xa0z\xc9\xb9\xf7O\x8b}7\xf0A\xa83_\ +\x06\xddI\xbf~\xdc?\xfd\x1fl\x9b\x8a\x1b\xd0C\x07\ +\xfb6*`\xed\xb0.\xb0\x87\xc1>\x16\xbd\x01<2\ +\xf3\xbc\x8d\x98^\xe9rX?\x9c\xfd\x1dC\xb1\xee)\ +nd^\xb2-\xeb\xfd\xd2\x03\xe8\xda\xcc\x1e\xa5\xda\x96\ +\xa0\x8f\x95\xa1\x0f\xca\xb4~\xa8\x09.n\xff\xa1\xb64\ +\xfc\xbb\xfc\xf8\x9e0P\xb2\xa74[\x03\xf7M\x11\xec\ +\xcb!\xd7\xf5kc=\x0etx\x91\xeb\xcfJ!S\ +\x9d\x87W\xe0\xfa\x9ba=\x19\xf4hq#\xef\xc5\xf5\ +\xb2\xce_\x85\xad\x9f\x9b\x99\x8c\xce\xc7\x90\x8a\xad\x8d\x88\ +t\xc2\xbc\x17\xe2{,C\xbf\x95B_jE\xac\xff\ +\xf0L\x5c'_$\xfe\xa1o\xc7\xde\xf1\x15\x8b\x7f\x90\ +?o\xee\x8a_\xffS/\xcaoZ!\xeboJ\xf5\ +\xb8\xcd\x11c\xa3\x22}\x1f\xec\xbb\x8a\xe3\x7f\xba\xd8F\ +\x04;Y\xdc\xc8\x09:^q\xf2\x1f\xfc<\x9bz\x97\ +j\x8fH\xa8\x83I\x07\xb0\xff\xce#K\xd5=\xb3\xae\ +0+N\xfe[Q}G\xf2\x9e_\xc32\x08\xf4\x80\ +b\x80~\x07\xf4\x87m\x9e\x8a\x88\xeb\x80\xee\xe9\xed(\ +v\xed\xd0\xeb\x00\xf7\xe7\xac\xb0\xf5S\x00>\x9fd\xfb\ +\xae\xb8\xdfw\x09\x80~\xbd\xc2\xfdA\xe5D\xfb\xa0\xdb\ +\x16D?\x13\xbb~\xd0=\x93\xcb\xf6\x85\xc8\xbc\xfeB\ +?\x85E\x13\x04\xda\xc5\xfb\x06T\x18\xed\xeb\xe0\x1e\x06\ +\xa5\xf5:\xc1\xb2\xafl?\x88\xe4\xeb\x17\xd7\x0b\x01\xf8\ +\xc0\xd6\xfe\xd8\x07\x0b1-\x0a\xe7\xcd\x8b\xc7\xf7\xe4\xb9\ +\x0fp\xee\xb7\x0fA\xe7+Z\xec\xdaa_\xa0\x7f\x87\ +L\xf6\xefr\x81\x9a\xc7\xd0\xcbl\xa31\xd5\x83P\xf8\ +,\xc39\xbc\x016 \x0f\xf3\xa2\x82\xf8\xb7\xd8\xde\xcf\ +\xbe\xe5L\xa6\x9f\xfc\x0f\xdbi\xb8o\xcc\x0a=\xd9\xf7\ +\x01\xbd\x0bb\x81\xf9Q\xc1\xe2\xd7N\x92\xb8\x973\xee\ +\xe1(\xad\xfd\x8b\xe8\x06\xde\x03\xfa+\xac\x0d\xe2\x91`\ +\xc7C?\xd0\x12{\x8a\xf4+\xe8\x0d&\xfa\x10\xb2q\ +\x0f\x9d\x82\x98\x97d.\xb2\x85Rw\x8d\x94\xde\x16D\ +\xef\x05yS\x9a\xbd\x89\x07\x8fKf]\xb6\x93T\xef\ +*\xbe\xfe\xe5T\xads\xe8A\xc5\xf9\xf9\x19\xd7\xbb/\ +~\xa6\x84\xf4)>\x1f\xfa\xfa\xba\xf49a\x9a\xe4 \ +}qv\xd1\xfeI\x14\xd7\xa6i\x10\xf1P\x88\xf3\x14\ +\xc4\xbc(\xf35\x10[\x95\xac\x17\x97(\xfc\xeb\xe2\x18\ +<\xf4\xdf\x12\x89\xce\x9f\x9f\xa8X4\xff\xd9\xd07\x16\ +l\xc0\xcc\xa4\xb2\x97\x9f\xfa\x9d\xea\x93gI\xf5\x81K\ +;0\x19=\xab;\x89\xed\x93\x12\xfd8\xb4\xa9\xbfC\ +sI\xdb7\x1e\xc7~%\xf1-\xc3\xf9\x93@\xe6\x95\ +N\xff\x88>\xb3\xfd\x0f\x88~~\xbe\x90M\x07}\xee\ +O/.\xd97Y\xc4\xc0=\x12\xd6\xb4\xa3\xe2\xa2X\ +v=\xa7\xe2\xda\xa1\xe7\xc9L\xcf\xf5d\xfa1s\xbc\ +'\xe0\xbb\x05^\x0a=\xa7\xa0\xf7\x94$\xeb\xa66\x98\ +C\xf9\x9aJ\xd7w\xcb^?\xf8\x15\x8e\xcfE\xc8\x16\ +\xad\xd7g]\xdfZ\xb4~\xd8+4OI\x06\xf8\xeb\ +\x8a\xceL\xc7\x92\xfd\xe6\x11\xaf\xa0\xfaI\xe4\x89\xec\x03\ +X\xfa\xe0\xe1\xe7S\xfe\xe5r\xf1X\x91\xf8\x87~s\ +\xdc\x94\xaf\x22\xdfD\xf1\x80\x16\xd4\xd9\x04\xfb\x03\xf1F\ +IF\xa6\xe7\xba\xc23\x8f\xf1\x1f\x17Q\xf6\x97$Z\ +:\x0f\xd3Pao\xb2\xf2\xf1U\x91\xfc\x1fb3\x90\ +g\x80\x07\xf4AK\xfe\x8a}\xdc\xd9\xb7\xf7`\x1a\xc5\ +:\x1d\xf8_\x90\x8e\x07\xfd<\xcb\x9cb^6\xf5=\ +9\xaf\x1f|/9\x81\x87e\xf1\xad\xc3\xdaK\xc6\xbf\ +\xd1\x1c3\xce-\xc7\xb178\x0b)\x8e\xbd\xe9x\x15\ +_\xa7\xd1\xa5}\xdf\xa3%\xeas\xcda\xc5\x90\xc9L\ +\xe3B]H\x1e\xeb\x87\x98`\xe6\xf9\x95\xb2\xf6\x99\xe6\ +\xe7\xcf\x8b\xf87=\x81~Zz\x98\xbe`\xde\x18`\ +\xbf\xd1\xdf\x80\xae\x07}\xb4\xa8\x9e\x8d\x8f\xd0\x99\x89\x17\ +\xe9\x0f\x83\xd8\x18\x15\xe3l&\xf3\xfa\x81\xc7C\x1c-\ +\xc5i \x8ds\x99t*\xfe\xdd\x01\xf1\xf9/\xb4\x9d\ +\x9b\xff\xee\x1e\x96\xf3\x05_#\xb1\xcf\x89\xeaw\xa4S\ +\xc8\x0b\x81\xf7\x00\xdf\x009\x9duu\x13\x99\x17\xe6\x89\ +\xf5\x1e\xf0\x8f\xe6\xdcq)\xc2\x11\x7f\xfd\xa5\xd8\xed%\ +\x06\xe2\xed`\xcf@l\x1cb\xc2\x98\xff\xc8\xeeS\xe7\ +\xe7\xbf\x94\x9e\xff\x04\xeb\xdf6\xa0\x98\x8c\xe7$~\xc6\ +g\xbfd\xbfW\xc1>\x8e\x14\xcd@\xec\x87\xa2\xfd\xa2\ +\xbf\x85\xb3\x94\x89t\xb4b=\xfa\xd09\xc2\xfc?7\ +\x13\xef\x19\xce\x0b@2\x13\xd6\x0c\xba<\xee\x01Z\x98\ +\x03'\xd3\xba\xf9\xc0\xcf\x7f*=\xff\x8d\xbf\xfe\x0cV\ +\xd1\xfaA\x0f*\xb1~Q\xdf\xd5\x15\xdf/\x12~\x07\ +v\x05\xf4\xa8\xdbj\x8ay\x09\xf0\xc8\xd4\xbd\xe3\xb1N\ +\x05{\x86\xf5\x05\xf8[\xbeM)\x9fu\xf3\x81\x9f\xff\ +Vz\xfe#\xce_3\xc1k\xc68\xca\xcd\xc0zh\ +\xf2\x06\x89\xec\x8b\xb2Ad\x8f6\x1dy\x9c\xed\xb2`\ +=K\xc2\xfcW\xe0]\x80\x93\xd4]\xa30\xe0x\xe6\ +J\x89s\x0c\x14\x11\x84\xf3_\xcb\xce\x7f\xb6\x14\xc0\x91\ +\xe2\xf6?\x95\x14\x84\xf3\x9f\xff\xd8\xfc\xf7?\xfd\xfeC\ +\xf5\xfd\x97\xea\xfbO\xd5\xf7\xdf\xc4\xde\x05\xfb\xa3\xee?\ +\x8a\xd8\x83?\xee\xfe\xab\x98=\xf8\xa3\xee?\x97\xb2\x0f\ +\xbf\xdd\xfdw\xba\xcc\x00I\xd7?\xe0\xd7\xd9\xe1\xd7\xd3\ +\xe1\xd7\xd1\xe1\xd7\xcb\xe1\xd7\xc5\xe1\xd7k\xa8\xae{S\ +\xc9\x83I\xfd(\xc4G0\xf5\x93_\x1f\x83_\x07\x83\ +_\xff\x82_\xe7\xc2\x84\x8fw\xa8\x13a\x84\xc0\x9c\x10\ +\xa8\x13\xd1\xaa\xec:\x11\x22\xce\x85\x06\x82A\x086!\ +\xb8\x8e\xe0\x19\x82\x08\x16\xc5\x83\xe5\x09\x11\xf4\xb3\xaf\xd3\ +\xef\x1aD\xbf[b\xba\x171os\x04\x81\x08R\x7f\ +\x01\xaf\x12\x86T\xfa\xdd\xe6\xc2\xeb\x90`\xee=\x10\xf8\ +\x22(\xa8\x84y\x0bC\x01=\x97\x1e\xe2\xd6 4\xf7\ +\xc9\x08b\x14`\xde\xc2\x10C\xcf\xad\xd8\x1aD\xcc\x9d\ +\xa5\x00s\x15\x07,\xe15\xb0\x8a\xd3\x8c\x22\xee\xbb(\ +<\x14\xa3%\x16u>|\x15`n\x92\x82/\xab\xf8\ +\x99\x863.\xdf\xb3Z\xccw\xa6#\xe4O\xd3&%\ +\x8b3\x8b\x85\x02z\xce\xfc\xbd\x0f\x94\xcf\xbc\xe9\xb8\xf6\ +\x0a}\x9cW\x011\xdb\xac+\x0ed\xce\x9dC\xd8\xdf\ +\x9bs\xff\x14\x99\xed\xbb\x1b\xdf\x8f\x06\x7f[a|G\ +:\xbfS \xabH6\xc9\xce\xdf\xd1\xbc!\xef\x16\xe6\ +\x9c\x1bv\x11\xc7vx\x05yb\x82\x15<\x92\x97\x93\ +F\xb2\xbf<%\xb3|\x9c\xb0\x1fU\x8a\xbc\xa0TV\ +\x91\x5c\x95m\xcf\xd1{S\xf7\x8c\xc1\xf1\x8b\xd2\xee\x8f\ +\x88\x1b\xe0\x93\x87|\x10|\xaf\xa0|y\xad|\x9d@\ +J\x1a\xa7b\xad\x10'\x87{~\xb2\x0d\x1e\xce\x9f\x01\ +\x7fn9\xe8\x89\xaf\xcfH5w\xf0\x1fC.\xbaX\ +:\x91b@\xdc5m\xffDI\xd7\xc0\xd7\xc5\xca?\ +\x7f\xeb\xe68\x97\xa9\xb4\x5c3\xbc\xab\xec\x5c\x9c\xe3\xc1\ +\xcf}\xc4\xf7\x02\xca\x88\xe3\xc3\xdf\xe2\x9c\xa0\xb2i\x89\ +\xafG\x96s\xefu\xf0\xbdX\x88?\x8b\x9f\xc3'\x1c\ +\xe7\x85\xbc\x0b\xb8\xab\x02yS\x90\xe3\x02\xb9\xdbp\xcf\ +\x0a\x9f\x95R\xee\xa1\xb2?=\xa2cA\xa5\xae\xe1U\ +\xb9\xe7O\xe7!\x88\x8b\xaf\xc3\x9ar\x82\x8e\x15\xdd\xf7\ +,\x96w(\xc0\xff\xd1\xb9I?2\x13\xf1\xa0'b\ +\xd7\x00\xeb/\xe3\x9e@\xf9\xe7\x8f\x00\xf8\xb9\xc8\xb9g\ +\xa7\x91\x99\x1e\xab\x0b\xf3\x08\xca|\x16\xce{\xeb\x8ep\ +\xe1#\xf2y\x90c\x06\xb9\x87\xa5\xc4\x06\xcb7\x7f\xfa\ +\x0e;'9\xae\xe4\xdc\x0b\xf2\xa9<8\xfc\xb7\xe5\xe0\ +\xe3\xb0\x06\xfb\x7fH\xf6\x87\x07\xa2q\x10|B~\xfb\ +\x8f\xde\x95yi\x9d\xc8\xf7@^(\x8e\xc5K\xa3\x13\ +\xc0\x9d\x97}\x13D\xe6{Q\xb9a\xdd\xc5\xe1\xb3|\ +\xf3\xb7n!\xf2^\x07\xc4\x1f\x0b\xf3H\xca;w>\ +\xac\xd0\xc3:F\x89\x81\xf0\x0a\xb9\x1eb\x9e-\xf9\xfc\ +!/\x1f\xf1\x10\xce\x8f\x92\xe7\x16\xee\xb9\x83\xee S\ +\x5c\x13\xdf\xb5\x9e^\x227\x11\x06\xe8L2\xcf\x1fr\ +\xfa\xb6\x0f\x11y\xaf+\xdbo\xbf\xec\xf1w|o\xae\ +\x1b\xce\xaf,A\x9bO/\x8b\xcb_+\xc7\xfc)\x1a\ +\x15\xa5\xdfd^(\xf3>\x9c\x04@\xe7H\x22\xbe/\ +< G\x0a\xe7\xe3\xc8:\xff\xfd\x93\xf0\xfd\xb1\xe2\xc4\ +\xcf\xa5j<\xc8\xe1>\x09\xce\xef\x12q_\x9d\xfd\xee\ +\x1e\x95\xe7$\xe3\xfc!\x87\x81\x97\x97Ur\xff/\xad\ +\x95\xcf\xfe\xafi\x87u\xea\x12\xfb\x1f\x19 \xfb\xfe\x8b\ +\xc8w\xe1\x8f\x9c{'e\xcfy\xc0\xf9D\xbdpN\ +\x9d\xf0\xa0\xee\xeb\x89\xfc^\xb9\xf8\x0f\xe4W\xe6G\xde\ +\xc1\xb6\x09\xbe\x9b\x02\x80\xfe\x1f\xf2\xb4\x81ve\xe3?\ +\xdad\xfa\xa9\x85\x22\xef\xfbg]\xdb\x22;\xff\x01\x80\ +\xdc\xa1\xf5\x9d\xa9;$p\xb7\x04\xc9M\x0c\x90s\x22\ +\xd3}\x12]L\xdf\x90\x9f/\xf8\x1e\xce\x19\x17:c\xf9\xaf\ +\xfdp\xce\x1b\xf0\xe5\xack\x9b\xb1\x1e\x09:2\xce\xb3\ +-_\x9e1}_x\x98H\xb9\x08#\xfb\xe6\x8e\xd2\ +t\xc1b\xf3\x07\x19\x0awKA\x87\x843S\x10\x1f\ +\x85u\xe1bg\x0c\xe9o\xdc\xb4\x84\xe28F\xf6\x17\ +\xd8(\xec\xcfO0\x0d\x17\xe1\xa2\x14|\xd0~\x07\xb8\ +\xeb\x07w\xeaE\x0d\x90e8?M\x92\xf9\xc3>\xec\ +\x1c^\xe2\xee~A\xec+:\x87W\x97\xbe\xdb=\xab\ +T{\x11\xdf\xed\xb6\xd0\xc6x\xc2:\x85\xa0\xbfG \ +O\x15\xceM\xd6\xd5\x8d\xe2k\x05p9d\xe6\xe5\x0d\ +\x92\xdb/X\xbf)\x99\xf7\x0by\x99p\x1f\x8f\xff~\ +\xe0\x05\xe2\x06\xe8q\x90\xef\x96\xb8L\x0b\xd9XVX\ +nfyo\xc2k\x06\xff\x04\xc8o\xb8;\x095\xd3\ +\x00\xb7\xa5\xd9\x91\x14O+3\xef\xbb8\xfd\x8b\xb9\xb3\ +\x02\xb5\xca\xf0\xbe\xc1\xbf?\xbd\x22\xf6\x9d\x9c\x84\xf7\xd4\ +\xfd\x1at\x9e!\x8f\xb1p]H\x87\x84\xfcE|>\ +%\xb9\x13\xf0>\xa4(/\xb8\xf4\xf3\xc3\x8f{\x14\x9e\ +%\xb0A\x0a\xdf\x8b\xecS\xc8\xa3\xc4\xfa\x0d\xdc/X\ +\xdbQ,\xad\xc2\x80\x9cu\x9c\xbf\x86\xd6\x0a\xb8\x97f\ +\xe4\xbf\xbd[\x16\xcd\x0b\x02?fC\xcf_\x07\xf3\x82\ +\xdcG\x1eh\x1d\x0e\xf8lQw\xab\x9a\xe19\xe1\xda\ +\x16\xe9?\xc5\xbe;\xdboo!\x8d\x97w\xfe\xa0\x97\ +@-\x1a\xea~\x94\xc4\xfe\x1f~\xbc\xa9\xe8w\xc0\xff\ +VPwW\xc0\xee\x815\xa4\xee\x1d\x87\xcf\x1b\xf8+\ +3\x5c\x17\x93\xd9\xc8\xae\xc69\xae\x90;)\xe0C\x00\ +\x1e\xce\xbf\xf3\x92\xe9eW\xcal\x05\xe6\xcd\xce\xc3\xf4\ +\x82m\x94\x95\xe5\xce\xff\xe5\xc7\xcaD\xf27\xb8\xc3\x01\ +\xf2\x0f\xe8\x16\xdf\x99\xb5\xd0.\xba\xbb\x079\xaahM\ +\xb0\xb6\xcc\x0b\xab\xf0\x9a\x0a\xf1\x0e\xf2\xe8\xf4b|\x07\ +\x18\xe7}\x0b\x9eSn\x01>\xe7@\x97\xc0\xa3\xa1f\ +a\x92\xad\xa1\xb4\xf6\x03?\xceW\xd2\x7f\x8b\xe6\x01\xbc\ +\x9f?\xc0?YB\xc7,\xbc\xcbW\xb2\xde\x14\xe8\x03\ +8o\xfb\xe0T\x5c_\x09x\x00\x9c#\xb8\xbb\x07\xbe\ +g|\x9f\x91\x9fw,\x9d\xee\xc7\xf7\xdf\x8a\xf6\x9f\xa3\ +\xf9\x00\x0f)\x88\x0dG\xf0\x12\xdf;(\xf7\x1e\x15\xf3\ +\xf7\x0b\x82\x5cj\xa7\xf2\xfd\xe7b\xe3\x17Pk\x09p\ +\x8bA\xb4\xfdPY \x18\xbf(=~T\x91\xf7u\ +\xa5\x07\xe1\xf8\x11?~W\x15zt\x8b\x8a\xdfU\xd9\ +\xf8iU\x8f_\xff\x0e\xf9\x03\xbfC\xfeFU\xcd\x9f\ +\xc1yD\x1a\x04\x11\x03?\xd5\x08\x22\x18~*\xd3\xf9\ +G\xd5Y`2\x0f&\xfc\x87Q\xb4\xaf1\xf0S\xad\ +h\xdf!OK\x9f\xa0z\xfa\x14\xe6ii\x8a\xce\xd3\ +\x12\xc2e\x0d\x16\x95\x1b\xb8\x07\xc1c\x16\xc5\x1f\xbeJ\ +\x091\xf43\xf6\xd0\xcf\xac!L3B\xefn\x8e\xe0\ +\x10\x82\xc4\x0a8w\x89\xf4\xb3\x9b\x8b8K\x00\xffC\ +\x10V\x01\xef\x15\x860\xfa]\xc2\xeb\xfe\x15\xef\x16\x9c\ +\x03\x7f\x1fj\xd0\xfbR\xceg\xe8\x8a\xd6!%\xb73\ +\x0e\xb1\x8ahMr|\xd3\xbayaM|d\x1b\x81\ +\x9f\x18|;\xe9\xc7\xe6P9\x13\xe0\xd3-\xbbfj\ +\x22\xab\x88\xce%{7\xc4\xe4\xd6\x1b\xe1\xbc\x02\x5c\x93\ +\x1ej\x09\x09\xda\xedP\xbf\x22-\x01\xc7\xa2\xc0\xee\xc2\ +\xbam\xe9\xfb\xc1?c\x12\xac[\x07\xfb9\xe0\xbd\x12\ +\xd5\xc1G\xf6\x19\xd8\xcbP\xf3\xae\x949\xf0\xcfw\x99\ +\xefN?6\xbb\x14\x9f\x10W\xec\x9c\xa0\xde\x5c)v\ +?\x9f\xb7\x94\xb2\xe7:\x18\xcf\x90K\x22\xbc>\xf0)\ +\x80\x9f\x11h\x00\xd7@\xf0\xdfO\xf91\x84\xfc?P\ +\x03\x04|\x1c\x22\xf4\xf5\xaf\xa5\xbf_\x17\xfb\x8a\xc0\xaf\ +)8\xc0\x7f\x07\xef\xa4\xfch\xc5\xed'\xb0\xff\xc07\ +Y\xbc\xce\x17\x8f\xcc\xba\xbe\xa5\xfc\xef\x07\xbf\xde\x89y\ +\xc5\xfcz\xb0\x0f\xa9\xb8N\x9a\xb6h\xfa\xa6\xf7\x19h\ +T\xf0n5\xcc9ycOa<\x94\xfe~\xf0k\ +\x85y\x0a\xe0\x99C\xc7d\xca\xb07\xe9\xfc\x1b\xa8g\ +U\xb4\x05<\xea\xfey\xf1\xef\x8a\x7f?\xf8\x0d\xd1^\ +\x82?\x80?\x0a\xbeGIZ\xa7\x86\x8a\x8b\xb9\xfc[\ +\xcc\xf7-\x22^\x22\xfe\xfdP3\xd5i`\xb1\xb8N\ +\xde\x93\xcbd\x19y\x0f\xc5\xe7\x0f~\xcf\x9f\x9f\x04\xce\ +\xc2\x03:\x9e+\xc9\xfb\x9bb\xba\x17\xac\x17\x00\xfeM\ +\xc9\xf9\xab.\xb6\xaf\xe1Ny\xe1\xfe\xc5\xbc\xc0|S\ +\x80nJ\x7f\xff\xf6!\xc5\xea\xa5\xe5>\xf6\x90\xf0\xdd\ +\xf4\xfa\x11\xaf\x14\xc4\x1f\xc4@\x85\xe2I\xa5\xe3\x1f\xed\ +\x1f\xf0\x0f\xa0y\xc8\xad\xc0\xb9\x08\x92\xc6\xa3p\xbd\xbd\ +1\xc5\xf6/\xef\xd9\x15\xe18\x84\x88\xf7\x0b\xd8\xf5\xe8\ +o\x81\x06!\xbf\x07\xe7\xf9@\xcc\x03\x7f_2\xbb_\ +\xd0\xcf\x04CD=\xa4\xa2\xf7\xf3{\xbd ~S\x18\ +[\xa1c\xeb\xe0\x7f\x84\xfc\x0c\x88\xf3\xe2{\xde6\xad\ +K\xc5;U\x93eN1\xdc\x81\x5c\x02?\xa9\xc8\xf3\ +\x0fy~;\x86\xe2\xde2 _\xf2^\x5c\xa3\xe8\xd4\ +B\x9b\xaa\x1b\xc6?\xc2\xe8,A\x1c2\xeb\x86\x13Y\ +8g\xe1\x18\x02:\xf7\xe0\x8b\x17\x96\x15\x98vK\xc6\ +\x80\xa8\xf7C]\x1c\xc4\xbf\x0b\xe7\x9a\xfe\x83\x92\xe3\xe8\ +\x99\xa2r/ 7\x12\xe2\x18\x10\xa7\x009\x0b\xf1\x11\ +\xf0\xbd\xc13\xa0\x86\xa5p\xfe\x16\xf8\xcaD\xf0>\x81\ +\xf5\xf3\xcf:\x95\xc3\x00\xfc\x16\xea\xeb\x80\xfc\xc6\xf2V\ +`\x80\xcf\x1e\xeaxB\x0c\x0c\xd7\x92E<\x11\xf2\x93\ +\xb0\xbfVD\xdc\x01\xf2\xc5\xc0\x17*&g\x8d\xd6\x91\ +\xa9\xda\x80\xb9\xf7]1\xae3\x5c\x17b\xff6\xe4\xba\ +B\x1cVp\x80\x9f\x1bbU\xc9\x1b\x8c\x8a\xf1\x16Q\ +\x03\xea2\xc1\xbe\x94\xc23\xf8\xfa9\xf5\xd9\xba\x05\xf6\ +E\x83\xdf\x16x5\xd0>\xaeOq}+>;\xd0\ +?\x04\xe2\xc4\x98F\x817\x8b\x88\xcd\x81\xdf\x19jU\ +\x80\x5c\x869\x96\x91\xab\xc7\xb7\x0d\x8ax.Z\x1b\xd4\ +\x82\x85\xb8\x1b\xce\x0f\x82\x18(\x9d\xfb\x0by\xa4\xb8\x9e\ +\x14\xf0`\xc8SC4\x9e\xed\xbb\x0b\xe7\xffB\xedJ\ +\x1cs<<\x93\xf2\xc1JVG\x8eo\x97$\x16\xf1\ +\xac\xce\xb8n\x0d\xc8p*\x8fX\xe0\x19\xc2>?\xc1\ +\xfb\xed\x82y\xd5\x92\xf9\x05\xf9\xfagI\xfd[\xfa\xdc\ +\xe5\xf2\x00_\xff\xe6\xdb\x1fO*\xf8}\x82 h\x7f\ +(\x82\xfdUi\xf6ge\xdb\xdf\xccJ\xf4\xc6\xc0\xbb\ +\xc1O\xa1IP\xbe\x8aB?E\x8d\x92~\x0az\xce\ +\x0d\x100\x11\xbcG\x90\x8e C\x0c\xa4\xd3\x7f\xc3\xa4\ +\xbf\xc3\xff\xee9\x04\xdc\x12\xb8\x11\x7fv\xb9\xf4w\xf8\ +\xef\xe5\x96\xf8\x1e\xe4C >\x0du\xe7 \xa6\x07\xf9\ +'B|\x82+0\xe7b\xdf\x858\x19\xd4\xbc\x05\xdd\ +\x06\xc7\x82\xe9\xdeeX\xbe\xad-\xc6{\xf8\xeb-\xe4\ +C\xa0\x8f\xf0\xfbH\x80L\x86\x5c\xd7\xfc\x08\xbf\xc2\xba\ +3\xa0\xeb\x0a\xd4\x92\xe5\xefU\xe1\xf7!\xf7\x0f\x06<\ +\x03\xea\xc9\xe0\xba\xd7\xd6\xcd\xb1\xbc\x80\xb8\x92\x90\xbe\x9e\ +Q\xf8\xfd\xc2zDo\xb0n\x8c\xf3\xe2-\x04\xe2g\ +\x88_S\xb9\x08\xf9T~\x1b\x15\xdf\x11\xf8>U\x1f\ +\x06x<\xe4d\x95\xc8o\xc49\x08]q\xfdH\x88\ +\x9b'Q9*E\xdf\x07\x1b\x0b\xed7\xd4\xc3\xc3}\ +;\x84\xeb\xe5\xf2\xeb\xb1!\x1d\x02rQh\x1eN}\ +\x1fz\x06B\xdcxe\x0b\xec+H?\xb5\x80\xea\xaf\ +\x22X\xbb\x13\xfd?U\x9f\x93\xc4u\x04i}\x1f\x7f\ +\x1f\xf0\x022\x15\xea{\x81M\x08\xf8\x02\x9d\x18\xea\x99\ +\xa6\xee\x1c\x86\xf5\xf5\xec\xdb{q\xcc\x98\x9b\x9e\x88\xf5\ +OZ\xfee\xa0\x9f\xe9`\x93\xc1\x9cqn\x08]\x03\ +\x12\xf2xA\xbe\xc2w\xf89p \xfb\xa0G\x8a\x00\ +\xbdP\xf4\x8c\xf0\x93q\xde\x1a\xe7\x99C>\x04\xe8f\ +\xd0O\x03\xe4 \xc4z\xa1\x87\x16\xc4[\xa9\xbb\x0a\xc5\ +\xe8\x98:\x0b\xcbu\xb9)\xdb\x07Sz\xa0`\xcc\x16\ +\xeau\x01\x9e\xf8=\xe2\x8a\xcb\x1e>\xfdR\xe7g\xb9\ +\x0e\xb7\x1c\xb2I\xf0\xfc\xc8t~e\x1d\xff\x07\x9d\xab\ +\xf3\x85\ +\x00\x00_\x84\ +I\ +I*\x00\x08\x00\x00\x00\x17\x00\xfe\x00\x04\x00\x01\x00\x00\ +\x00\x00\x00\x00\x00\x00\x01\x03\x00\x01\x00\x00\x00`\x00\x00\ +\x00\x01\x01\x03\x00\x01\x00\x00\x00`\x00\x00\x00\x02\x01\x03\ +\x00\x04\x00\x00\x00\x22\x01\x00\x00\x03\x01\x03\x00\x01\x00\x00\ +\x00\x05\x00\x00\x00\x06\x01\x03\x00\x01\x00\x00\x00\x02\x00\x00\ +\x00\x11\x01\x04\x00\x01\x00\x00\x00@T\x00\x00\x12\x01\x03\ +\x00\x01\x00\x00\x00\x01\x00\x00\x00\x15\x01\x03\x00\x01\x00\x00\ +\x00\x04\x00\x00\x00\x16\x01\x03\x00\x01\x00\x00\x00`\x00\x00\ +\x00\x17\x01\x04\x00\x01\x00\x00\x00\x17\x0b\x00\x00\x1a\x01\x05\ +\x00\x01\x00\x00\x00*\x01\x00\x00\x1b\x01\x05\x00\x01\x00\x00\ +\x002\x01\x00\x00\x1c\x01\x03\x00\x01\x00\x00\x00\x01\x00\x00\ +\x00(\x01\x03\x00\x01\x00\x00\x00\x02\x00\x00\x001\x01\x02\ +\x00$\x00\x00\x00:\x01\x00\x002\x01\x02\x00\x14\x00\x00\ +\x00^\x01\x00\x00=\x01\x03\x00\x01\x00\x00\x00\x02\x00\x00\ +\x00R\x01\x03\x00\x01\x00\x00\x00\x01\x00\x00\x00\xbc\x02\x01\ +\x00\xfa8\x00\x00r\x01\x00\x00I\x86\x01\x00\x8c\x0d\x00\ +\x00l:\x00\x00i\x87\x04\x00\x01\x00\x00\x00X_\x00\ +\x00s\x87\x07\x00H\x0c\x00\x00\xf8G\x00\x00\x00\x00\x00\ +\x00\x08\x00\x08\x00\x08\x00\x08\x00\x00\xf9\x15\x00\x10'\x00\ +\x00\x00\xf9\x15\x00\x10'\x00\x00Adobe P\ +hotoshop CC 2015\ +.5 (Windows)\x00201\ +7:03:08 11:38:26\ +\x00\x0a\x0a \x0a \ +\x0a pain\ +t.net 4.0.9\x0a \ + 2017-03-0\ +7T11:32:29-08:00\ +\x0a 2017-\ +03-08T11:38:26-0\ +8:00\x0a <\ +xmp:MetadataDate\ +>2017-03-08T11:3\ +8:26-08:00\x0a \ + image/tiff\x0a \ + 3\x0a \ + sR\ +GB IEC61966-2.1<\ +/photoshop:ICCPr\ +ofile>\x0a \ +\x0a \ + \x0a \ + adobe\ +:docid:photoshop\ +:94a27cdb-0433-1\ +1e7-b02d-9f84d9f\ +5a326\x0a \ + \x0a <\ +/photoshop:Docum\ +entAncestors>\x0a \ + xmp.iid\ +:d3f831c7-1693-8\ +248-a9a0-2c4f91d\ +81b49\x0a \ + adobe:docid:\ +photoshop:c7bad1\ +dd-0436-11e7-b02\ +d-9f84d9f5a326\x0a xmp.did:a36\ +4ea4e-2280-ea40-\ +ae73-10beb7a78ae\ +8\x0a \ + \x0a \ + \x0a \ + \x0a \ + <\ +stEvt:action>cre\ +ated\x0a \ + xmp.iid:\ +a364ea4e-2280-ea\ +40-ae73-10beb7a7\ +8ae8\x0a \ + 2017-03-07\ +T11:32:29-08:00<\ +/stEvt:when>\x0a \ + <\ +stEvt:softwareAg\ +ent>Adobe Photos\ +hop CC 2015.5 (W\ +indows)\x0a \ + \x0a \ + \x0a \ + saved\x0a \ + <\ +stEvt:instanceID\ +>xmp.iid:d3f831c\ +7-1693-8248-a9a0\ +-2c4f91d81b49\ +\x0a \ + 2\ +017-03-08T11:38:\ +26-08:00\x0a \ + Ado\ +be Photoshop CC \ +2015.5 (Windows)\ +\x0a \ + /\x0a \ + \x0a <\ +/rdf:Seq>\x0a \ + \x0a \x0a \ +\x0a\x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ +\x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a\ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ +\x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a\ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ +\x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a\ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ +\x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a\ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ +\x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a\ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ +\x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a\ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ +\x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a\ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ +\x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \x0a8BIM\x04\ +%\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x008BIM\x04:\x00\x00\x00\ +\x00\x00\xe5\x00\x00\x00\x10\x00\x00\x00\x01\x00\x00\x00\x00\x00\ +\x0bprintOutput\x00\x00\x00\x05\ +\x00\x00\x00\x00PstSbool\x01\x00\x00\x00\ +\x00Inteenum\x00\x00\x00\x00Int\ +e\x00\x00\x00\x00Clrm\x00\x00\x00\x0fpri\ +ntSixteenBitbool\ +\x00\x00\x00\x00\x0bprinterName\ +TEXT\x00\x00\x00\x01\x00\x00\x00\x00\x00\x0fpr\ +intProofSetupObj\ +c\x00\x00\x00\x0c\x00P\x00r\x00o\x00o\x00f\x00\ + \x00S\x00e\x00t\x00u\x00p\x00\x00\x00\x00\x00\ +\x0aproofSetup\x00\x00\x00\x01\x00\ +\x00\x00\x00Bltnenum\x00\x00\x00\x0cb\ +uiltinProof\x00\x00\x00\x09p\ +roofCMYK\x008BIM\x04;\x00\ +\x00\x00\x00\x02-\x00\x00\x00\x10\x00\x00\x00\x01\x00\x00\x00\ +\x00\x00\x12printOutputOp\ +tions\x00\x00\x00\x17\x00\x00\x00\x00Cpt\ +nbool\x00\x00\x00\x00\x00Clbrbo\ +ol\x00\x00\x00\x00\x00RgsMbool\x00\ +\x00\x00\x00\x00CrnCbool\x00\x00\x00\x00\ +\x00CntCbool\x00\x00\x00\x00\x00Lb\ +lsbool\x00\x00\x00\x00\x00Ngtvb\ +ool\x00\x00\x00\x00\x00EmlDbool\ +\x00\x00\x00\x00\x00Intrbool\x00\x00\x00\ +\x00\x00BckgObjc\x00\x00\x00\x01\x00\x00\ +\x00\x00\x00\x00RGBC\x00\x00\x00\x03\x00\x00\x00\x00\ +Rd doub@o\xe0\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00Grn doub@o\xe0\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00Bl doub\ +@o\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00BrdT\ +UntF#Rlt\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00Bld UntF#Rlt\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00Rslt\ +UntF#Pxl@b\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x0avectorDatabo\ +ol\x01\x00\x00\x00\x00PgPsenum\x00\ +\x00\x00\x00PgPs\x00\x00\x00\x00PgPC\x00\ +\x00\x00\x00LeftUntF#Rlt\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00Top U\ +ntF#Rlt\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00Scl UntF#Prc@\ +Y\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10cropW\ +henPrintingbool\x00\ +\x00\x00\x00\x0ecropRectBott\ +omlong\x00\x00\x00\x00\x00\x00\x00\x0ccr\ +opRectLeftlong\x00\x00\ +\x00\x00\x00\x00\x00\x0dcropRectRi\ +ghtlong\x00\x00\x00\x00\x00\x00\x00\x0bc\ +ropRectToplong\x00\x00\ +\x00\x00\x008BIM\x03\xed\x00\x00\x00\x00\x00\x10\x00\ +\x90\x00\x00\x00\x01\x00\x01\x00\x90\x00\x00\x00\x01\x00\x018\ +BIM\x04&\x00\x00\x00\x00\x00\x0e\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00?\x80\x00\x008BIM\x03\xee\x00\ +\x00\x00\x00\x00\x0d\x0cTransparen\ +cy\x008BIM\x04\x15\x00\x00\x00\x00\x00\x1e\x00\ +\x00\x00\x0d\x00T\x00r\x00a\x00n\x00s\x00p\x00\ +a\x00r\x00e\x00n\x00c\x00y\x00\x008BI\ +M\x045\x00\x00\x00\x00\x00\x11\x00\x00\x00\x01\x00\x00\xff\ +\xff\x00\x00\x00\x00\x00\x00\x00d\x01\x008BIM\x04\ +\x1d\x00\x00\x00\x00\x00\x04\x00\x00\x00\x008BIM\x04\ +\x0d\x00\x00\x00\x00\x00\x04\x00\x00\x00\x1e8BIM\x04\ +\x19\x00\x00\x00\x00\x00\x04\x00\x00\x00\x1e8BIM\x03\ +\xf3\x00\x00\x00\x00\x00\x09\x00\x00\x00\x00\x00\x00\x00\x00\x01\ +\x008BIM'\x10\x00\x00\x00\x00\x00\x0a\x00\x01\x00\ +\x00\x00\x00\x00\x00\x00\x018BIM\x03\xf5\x00\x00\x00\ +\x00\x00H\x00/ff\x00\x01\x00lff\x00\x06\x00\ +\x00\x00\x00\x00\x01\x00/ff\x00\x01\x00\xa1\x99\x9a\x00\ +\x06\x00\x00\x00\x00\x00\x01\x002\x00\x00\x00\x01\x00Z\x00\ +\x00\x00\x06\x00\x00\x00\x00\x00\x01\x005\x00\x00\x00\x01\x00\ +-\x00\x00\x00\x06\x00\x00\x00\x00\x00\x018BIM\x03\ +\xf8\x00\x00\x00\x00\x00p\x00\x00\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x03\ +\xe8\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x03\xe8\x00\x00\x00\ +\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\x03\xe8\x00\x00\x00\x00\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\x03\xe8\x00\x008BIM\x04\x00\x00\x00\x00\ +\x00\x00\x02\x00\x008BIM\x04\x02\x00\x00\x00\x00\x00\ +\x02\x00\x008BIM\x040\x00\x00\x00\x00\x00\x01\x01\ +\x008BIM\x04-\x00\x00\x00\x00\x00\x06\x00\x01\x00\ +\x00\x00\x0a8BIM\x04\x08\x00\x00\x00\x00\x00\x10\x00\ +\x00\x00\x01\x00\x00\x02@\x00\x00\x02@\x00\x00\x00\x008\ +BIM\x04\x1e\x00\x00\x00\x00\x00\x04\x00\x00\x00\x008\ +BIM\x04\x1a\x00\x00\x00\x00\x035\x00\x00\x00\x06\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00`\x00\x00\x00`\x00\ +\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00`\x00\x00\x00`\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\ +\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00null\x00\x00\ +\x00\x02\x00\x00\x00\x06boundsObjc\ +\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00Rct1\x00\x00\ +\x00\x04\x00\x00\x00\x00Top long\x00\x00\ +\x00\x00\x00\x00\x00\x00Leftlong\x00\x00\ +\x00\x00\x00\x00\x00\x00Btomlong\x00\x00\ +\x00`\x00\x00\x00\x00Rghtlong\x00\x00\ +\x00`\x00\x00\x00\x06slicesVlLs\ +\x00\x00\x00\x01Objc\x00\x00\x00\x01\x00\x00\x00\x00\ +\x00\x05slice\x00\x00\x00\x12\x00\x00\x00\x07s\ +liceIDlong\x00\x00\x00\x00\x00\x00\ +\x00\x07groupIDlong\x00\x00\x00\ +\x00\x00\x00\x00\x06originenum\x00\ +\x00\x00\x0cESliceOrigin\x00\ +\x00\x00\x0dautoGenerated\ +\x00\x00\x00\x00Typeenum\x00\x00\x00\x0a\ +ESliceType\x00\x00\x00\x00Im\ +g \x00\x00\x00\x06boundsObjc\ +\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00Rct1\x00\x00\ +\x00\x04\x00\x00\x00\x00Top long\x00\x00\ +\x00\x00\x00\x00\x00\x00Leftlong\x00\x00\ +\x00\x00\x00\x00\x00\x00Btomlong\x00\x00\ +\x00`\x00\x00\x00\x00Rghtlong\x00\x00\ +\x00`\x00\x00\x00\x03urlTEXT\x00\x00\x00\ +\x01\x00\x00\x00\x00\x00\x00nullTEXT\x00\ +\x00\x00\x01\x00\x00\x00\x00\x00\x00MsgeTEX\ +T\x00\x00\x00\x01\x00\x00\x00\x00\x00\x06altTa\ +gTEXT\x00\x00\x00\x01\x00\x00\x00\x00\x00\x0ec\ +ellTextIsHTMLboo\ +l\x01\x00\x00\x00\x08cellTextTE\ +XT\x00\x00\x00\x01\x00\x00\x00\x00\x00\x09horz\ +Alignenum\x00\x00\x00\x0fESl\ +iceHorzAlign\x00\x00\x00\x07\ +default\x00\x00\x00\x09vertA\ +lignenum\x00\x00\x00\x0fESli\ +ceVertAlign\x00\x00\x00\x07d\ +efault\x00\x00\x00\x0bbgColo\ +rTypeenum\x00\x00\x00\x11ESl\ +iceBGColorType\x00\x00\ +\x00\x00None\x00\x00\x00\x09topOut\ +setlong\x00\x00\x00\x00\x00\x00\x00\x0al\ +eftOutsetlong\x00\x00\x00\ +\x00\x00\x00\x00\x0cbottomOutse\ +tlong\x00\x00\x00\x00\x00\x00\x00\x0brig\ +htOutsetlong\x00\x00\x00\x00\ +\x008BIM\x04(\x00\x00\x00\x00\x00\x0c\x00\x00\x00\ +\x02?\xf0\x00\x00\x00\x00\x00\x008BIM\x04\x14\x00\ +\x00\x00\x00\x00\x04\x00\x00\x00\x0d8BIM\x04\x0c\x00\ +\x00\x00\x00\x043\x00\x00\x00\x01\x00\x00\x000\x00\x00\x00\ +0\x00\x00\x00\x90\x00\x00\x1b\x00\x00\x00\x04\x17\x00\x18\x00\ +\x01\xff\xd8\xff\xed\x00\x0cAdobe_CM\x00\ +\x01\xff\xee\x00\x0eAdobe\x00d\x80\x00\x00\x00\ +\x01\xff\xdb\x00\x84\x00\x0c\x08\x08\x08\x09\x08\x0c\x09\x09\x0c\ +\x11\x0b\x0a\x0b\x11\x15\x0f\x0c\x0c\x0f\x15\x18\x13\x13\x15\x13\ +\x13\x18\x11\x0c\x0c\x0c\x0c\x0c\x0c\x11\x0c\x0c\x0c\x0c\x0c\x0c\ +\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\ +\x0c\x0c\x0c\x0c\x0c\x0c\x01\x0d\x0b\x0b\x0d\x0e\x0d\x10\x0e\x0e\ +\x10\x14\x0e\x0e\x0e\x14\x14\x0e\x0e\x0e\x0e\x14\x11\x0c\x0c\x0c\ +\x0c\x0c\x11\x11\x0c\x0c\x0c\x0c\x0c\x0c\x11\x0c\x0c\x0c\x0c\x0c\ +\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\ +\x0c\x0c\x0c\x0c\x0c\x0c\x0c\xff\xc0\x00\x11\x08\x000\x000\ +\x03\x01\x22\x00\x02\x11\x01\x03\x11\x01\xff\xdd\x00\x04\x00\x03\ +\xff\xc4\x01?\x00\x00\x01\x05\x01\x01\x01\x01\x01\x01\x00\x00\ +\x00\x00\x00\x00\x00\x03\x00\x01\x02\x04\x05\x06\x07\x08\x09\x0a\ +\x0b\x01\x00\x01\x05\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\ +\x00\x00\x01\x00\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x10\x00\ +\x01\x04\x01\x03\x02\x04\x02\x05\x07\x06\x08\x05\x03\x0c3\x01\ +\x00\x02\x11\x03\x04!\x121\x05AQa\x13\x22q\x81\ +2\x06\x14\x91\xa1\xb1B#$\x15R\xc1b34r\ +\x82\xd1C\x07%\x92S\xf0\xe1\xf1cs5\x16\xa2\xb2\ +\x83&D\x93TdE\xc2\xa3t6\x17\xd2U\xe2e\ +\xf2\xb3\x84\xc3\xd3u\xe3\xf3F'\x94\xa4\x85\xb4\x95\xc4\ +\xd4\xe4\xf4\xa5\xb5\xc5\xd5\xe5\xf5Vfv\x86\x96\xa6\xb6\ +\xc6\xd6\xe6\xf67GWgw\x87\x97\xa7\xb7\xc7\xd7\xe7\ +\xf7\x11\x00\x02\x02\x01\x02\x04\x04\x03\x04\x05\x06\x07\x07\x06\ +\x055\x01\x00\x02\x11\x03!1\x12\x04AQaq\x22\ +\x13\x052\x81\x91\x14\xa1\xb1B#\xc1R\xd1\xf03$\ +b\xe1r\x82\x92CS\x15cs4\xf1%\x06\x16\xa2\ +\xb2\x83\x07&5\xc2\xd2D\x93T\xa3\x17dEU6\ +te\xe2\xf2\xb3\x84\xc3\xd3u\xe3\xf3F\x94\xa4\x85\xb4\ +\x95\xc4\xd4\xe4\xf4\xa5\xb5\xc5\xd5\xe5\xf5Vfv\x86\x96\ +\xa6\xb6\xc6\xd6\xe6\xf6'7GWgw\x87\x97\xa7\xb7\ +\xc7\xff\xda\x00\x0c\x03\x01\x00\x02\x11\x03\x11\x00?\x00\xf5\ +T\x92@\xce\xbe\xdcl+\xef\xa6\xa7d[S\x1c\xea\ +\xe9f\xae{\x80\xf6\xb0\x7fY\xc9)\x8e_Q\xe9\xf8\ +Q\xf6\xcc\x9a\xb1\xf7}\x1fU\xedd\xff\x00Wy\xf7\ +\x22\xd1\x91\x8f\x93X\xb7\x1e\xd6]S\xb8}n\x0ei\ +\xfe\xd3%\xab\x98\xe8?Uq\xf31\x7fju\xfa\x9d\ +\x95\xd4\xb3\x7fI`\xbbp\xd8\xd3\xfc\xdd~\x94\xb7g\ +\xb3\xf3\x1d\xfc\xc7\xf3?\xe0\xd0rzs~\xab\xf5\xcc\ +\x0c\xae\x98\xe73\x03\xa9\x5c\xdc\x5c\xacB\xe2[\xb9\xda\ +Wcw\xeew\xb7\xe9\xfe\xfd\x7f\xcd\xff\x005v\xc4\ +\x94\xf6)$\x92J\x7f\xff\xd0\xf5U\x9b\xd6\xfa\xf6\x17\ +E\xaa\xb7\xe4\x8b,}\xee-\xaa\x9a\x9b\xb9\xee#W\ +}\x22\xc6\xedo\xf5\x96\x92\xe5\xfe\xbd\xfe\x87\x1f\xa6\xf5\ +\x01\xa3\xb0\xf3kt\xf84\xcb\x9d\xff\x00\x9e\x98\x92\x94\ +>\xb7\xf5[\xc4\xe1t\x0c\xab\x01\xfa.\xb6k\x1f\xf9\ +\xed\xcd\xff\x00\xa6\xb3\xba\x9d\x1f\x5cz\x8d\xf4u,\x9c\ +*q\x9b\xd3w_UN\xb09\xbb\x84Y\xea=\x8c\ +s\x9fe\x8d\xf4\xfd\x9f\xcd\xad\xff\x00\xad\xcf\xeau\xf4\ +Km\xe9\xaf5\xbe\xb2\x1f{\xd8@x\xa5\xb2\xeb\x9d\ +S\x8f\xd1s\x7f\xcf\xf4\xfdOO\xf4\x89\xfe\xaa]\x99\ +\x97\xf5~\x8bs\xec\x17\xbe\xdd\xfb^L\xb8\xd7\xb9\xcd\ +\xaf\xd5#\xfc&\xcf\xa7\xff\x00\x82~\x91%6>\xaf\ +\xf5Gun\x8f\x8d\x9fcZ\xcb.i\xf5\x1a\xd9\xda\ +\x1c\xd7:\xb7\xed\xdd\xee\xda\xed\x9b\x96\x8a\xe6?\xc5\xf9\ +,\xe9\x19\x18\x8e>\xecL\xabj\x8f\x01\xedw\xfdV\ +\xf5\xd3\xa4\xa7\xff\xd1\xf5U\x87\xf5\xd3\x0d\xf9\x7fV\xf2\ +\xd9[\x0d\x9606\xc65\xa2O\xb1\xcds\xf6\xb4\x7f\ +\xc1\xef[\x89$\xa7\x92\xa3\xeb\xadY8\x8c\xa2\x9e\x97\ +\x97\xd4\x1ek\x0c\xb86\xb0kq\xdb\xb6\xc1\xfe\x13u\ +n\xfeS\x13\xe3u_\xad\x1e\x8b1\xfa_\xd5\xe6a\ +\xe3\xd66\xd6\xcbl\x0ckG\x95_\xab\xae\xb1$\x94\ +\xe0}U\xe9\x1dK\x01\xd9\xf9]G\xd3\xae\xec\xfb\xbd\ +oB\xa2KX}\xc5\xee\xdc\x7f}\xcf\xfa\x1e\xff\x00\ +\xf8\xc5\xbe\x92I)\xff\xd9\x008BIM\x04!\x00\ +\x00\x00\x00\x00a\x00\x00\x00\x01\x01\x00\x00\x00\x0f\x00A\ +\x00d\x00o\x00b\x00e\x00 \x00P\x00h\x00o\ +\x00t\x00o\x00s\x00h\x00o\x00p\x00\x00\x00\x19\ +\x00A\x00d\x00o\x00b\x00e\x00 \x00P\x00h\ +\x00o\x00t\x00o\x00s\x00h\x00o\x00p\x00 \ +\x00C\x00C\x00 \x002\x000\x001\x005\x00.\ +\x005\x00\x00\x00\x01\x00\x00\x00\x0cHLino\x02\ +\x10\x00\x00mntrRGB XYZ \x07\ +\xce\x00\x02\x00\x09\x00\x06\x001\x00\x00acspM\ +SFT\x00\x00\x00\x00IEC sRGB\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf6\xd6\x00\ +\x01\x00\x00\x00\x00\xd3-HP \x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11cprt\x00\ +\x00\x01P\x00\x00\x003desc\x00\x00\x01\x84\x00\ +\x00\x00lwtpt\x00\x00\x01\xf0\x00\x00\x00\x14b\ +kpt\x00\x00\x02\x04\x00\x00\x00\x14rXYZ\x00\ +\x00\x02\x18\x00\x00\x00\x14gXYZ\x00\x00\x02,\x00\ +\x00\x00\x14bXYZ\x00\x00\x02@\x00\x00\x00\x14d\ +mnd\x00\x00\x02T\x00\x00\x00pdmdd\x00\ +\x00\x02\xc4\x00\x00\x00\x88vued\x00\x00\x03L\x00\ +\x00\x00\x86view\x00\x00\x03\xd4\x00\x00\x00$l\ +umi\x00\x00\x03\xf8\x00\x00\x00\x14meas\x00\ +\x00\x04\x0c\x00\x00\x00$tech\x00\x00\x040\x00\ +\x00\x00\x0crTRC\x00\x00\x04<\x00\x00\x08\x0cg\ +TRC\x00\x00\x04<\x00\x00\x08\x0cbTRC\x00\ +\x00\x04<\x00\x00\x08\x0ctext\x00\x00\x00\x00C\ +opyright (c) 199\ +8 Hewlett-Packar\ +d Company\x00\x00desc\x00\ +\x00\x00\x00\x00\x00\x00\x12sRGB IEC6\ +1966-2.1\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x12sRGB IEC6196\ +6-2.1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00XYZ \x00\x00\x00\x00\x00\ +\x00\xf3Q\x00\x01\x00\x00\x00\x01\x16\xccXYZ \x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00X\ +YZ \x00\x00\x00\x00\x00\x00o\xa2\x00\x008\xf5\x00\ +\x00\x03\x90XYZ \x00\x00\x00\x00\x00\x00b\x99\x00\ +\x00\xb7\x85\x00\x00\x18\xdaXYZ \x00\x00\x00\x00\x00\ +\x00$\xa0\x00\x00\x0f\x84\x00\x00\xb6\xcfdesc\x00\ +\x00\x00\x00\x00\x00\x00\x16IEC http:\ +//www.iec.ch\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x16IEC http\ +://www.iec.ch\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00desc\x00\ +\x00\x00\x00\x00\x00\x00.IEC 61966\ +-2.1 Default RGB\ + colour space - \ +sRGB\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00.\ +IEC 61966-2.1 De\ +fault RGB colour\ + space - sRGB\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00desc\x00\x00\x00\x00\x00\x00\x00,R\ +eference Viewing\ + Condition in IE\ +C61966-2.1\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00,Reference \ +Viewing Conditio\ +n in IEC61966-2.\ +1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00view\x00\ +\x00\x00\x00\x00\x13\xa4\xfe\x00\x14_.\x00\x10\xcf\x14\x00\ +\x03\xed\xcc\x00\x04\x13\x0b\x00\x03\x5c\x9e\x00\x00\x00\x01X\ +YZ \x00\x00\x00\x00\x00L\x09V\x00P\x00\x00\x00\ +W\x1f\xe7meas\x00\x00\x00\x00\x00\x00\x00\x01\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x02\x8f\x00\x00\x00\x02sig \x00\x00\x00\x00C\ +RT curv\x00\x00\x00\x00\x00\x00\x04\x00\x00\ +\x00\x00\x05\x00\x0a\x00\x0f\x00\x14\x00\x19\x00\x1e\x00#\x00\ +(\x00-\x002\x007\x00;\x00@\x00E\x00J\x00\ +O\x00T\x00Y\x00^\x00c\x00h\x00m\x00r\x00\ +w\x00|\x00\x81\x00\x86\x00\x8b\x00\x90\x00\x95\x00\x9a\x00\ +\x9f\x00\xa4\x00\xa9\x00\xae\x00\xb2\x00\xb7\x00\xbc\x00\xc1\x00\ +\xc6\x00\xcb\x00\xd0\x00\xd5\x00\xdb\x00\xe0\x00\xe5\x00\xeb\x00\ +\xf0\x00\xf6\x00\xfb\x01\x01\x01\x07\x01\x0d\x01\x13\x01\x19\x01\ +\x1f\x01%\x01+\x012\x018\x01>\x01E\x01L\x01\ +R\x01Y\x01`\x01g\x01n\x01u\x01|\x01\x83\x01\ +\x8b\x01\x92\x01\x9a\x01\xa1\x01\xa9\x01\xb1\x01\xb9\x01\xc1\x01\ +\xc9\x01\xd1\x01\xd9\x01\xe1\x01\xe9\x01\xf2\x01\xfa\x02\x03\x02\ +\x0c\x02\x14\x02\x1d\x02&\x02/\x028\x02A\x02K\x02\ +T\x02]\x02g\x02q\x02z\x02\x84\x02\x8e\x02\x98\x02\ +\xa2\x02\xac\x02\xb6\x02\xc1\x02\xcb\x02\xd5\x02\xe0\x02\xeb\x02\ +\xf5\x03\x00\x03\x0b\x03\x16\x03!\x03-\x038\x03C\x03\ +O\x03Z\x03f\x03r\x03~\x03\x8a\x03\x96\x03\xa2\x03\ +\xae\x03\xba\x03\xc7\x03\xd3\x03\xe0\x03\xec\x03\xf9\x04\x06\x04\ +\x13\x04 \x04-\x04;\x04H\x04U\x04c\x04q\x04\ +~\x04\x8c\x04\x9a\x04\xa8\x04\xb6\x04\xc4\x04\xd3\x04\xe1\x04\ +\xf0\x04\xfe\x05\x0d\x05\x1c\x05+\x05:\x05I\x05X\x05\ +g\x05w\x05\x86\x05\x96\x05\xa6\x05\xb5\x05\xc5\x05\xd5\x05\ +\xe5\x05\xf6\x06\x06\x06\x16\x06'\x067\x06H\x06Y\x06\ +j\x06{\x06\x8c\x06\x9d\x06\xaf\x06\xc0\x06\xd1\x06\xe3\x06\ +\xf5\x07\x07\x07\x19\x07+\x07=\x07O\x07a\x07t\x07\ +\x86\x07\x99\x07\xac\x07\xbf\x07\xd2\x07\xe5\x07\xf8\x08\x0b\x08\ +\x1f\x082\x08F\x08Z\x08n\x08\x82\x08\x96\x08\xaa\x08\ +\xbe\x08\xd2\x08\xe7\x08\xfb\x09\x10\x09%\x09:\x09O\x09\ +d\x09y\x09\x8f\x09\xa4\x09\xba\x09\xcf\x09\xe5\x09\xfb\x0a\ +\x11\x0a'\x0a=\x0aT\x0aj\x0a\x81\x0a\x98\x0a\xae\x0a\ +\xc5\x0a\xdc\x0a\xf3\x0b\x0b\x0b\x22\x0b9\x0bQ\x0bi\x0b\ +\x80\x0b\x98\x0b\xb0\x0b\xc8\x0b\xe1\x0b\xf9\x0c\x12\x0c*\x0c\ +C\x0c\x5c\x0cu\x0c\x8e\x0c\xa7\x0c\xc0\x0c\xd9\x0c\xf3\x0d\ +\x0d\x0d&\x0d@\x0dZ\x0dt\x0d\x8e\x0d\xa9\x0d\xc3\x0d\ +\xde\x0d\xf8\x0e\x13\x0e.\x0eI\x0ed\x0e\x7f\x0e\x9b\x0e\ +\xb6\x0e\xd2\x0e\xee\x0f\x09\x0f%\x0fA\x0f^\x0fz\x0f\ +\x96\x0f\xb3\x0f\xcf\x0f\xec\x10\x09\x10&\x10C\x10a\x10\ +~\x10\x9b\x10\xb9\x10\xd7\x10\xf5\x11\x13\x111\x11O\x11\ +m\x11\x8c\x11\xaa\x11\xc9\x11\xe8\x12\x07\x12&\x12E\x12\ +d\x12\x84\x12\xa3\x12\xc3\x12\xe3\x13\x03\x13#\x13C\x13\ +c\x13\x83\x13\xa4\x13\xc5\x13\xe5\x14\x06\x14'\x14I\x14\ +j\x14\x8b\x14\xad\x14\xce\x14\xf0\x15\x12\x154\x15V\x15\ +x\x15\x9b\x15\xbd\x15\xe0\x16\x03\x16&\x16I\x16l\x16\ +\x8f\x16\xb2\x16\xd6\x16\xfa\x17\x1d\x17A\x17e\x17\x89\x17\ +\xae\x17\xd2\x17\xf7\x18\x1b\x18@\x18e\x18\x8a\x18\xaf\x18\ +\xd5\x18\xfa\x19 \x19E\x19k\x19\x91\x19\xb7\x19\xdd\x1a\ +\x04\x1a*\x1aQ\x1aw\x1a\x9e\x1a\xc5\x1a\xec\x1b\x14\x1b\ +;\x1bc\x1b\x8a\x1b\xb2\x1b\xda\x1c\x02\x1c*\x1cR\x1c\ +{\x1c\xa3\x1c\xcc\x1c\xf5\x1d\x1e\x1dG\x1dp\x1d\x99\x1d\ +\xc3\x1d\xec\x1e\x16\x1e@\x1ej\x1e\x94\x1e\xbe\x1e\xe9\x1f\ +\x13\x1f>\x1fi\x1f\x94\x1f\xbf\x1f\xea \x15 A \ +l \x98 \xc4 \xf0!\x1c!H!u!\xa1!\ +\xce!\xfb\x22'\x22U\x22\x82\x22\xaf\x22\xdd#\x0a#\ +8#f#\x94#\xc2#\xf0$\x1f$M$|$\ +\xab$\xda%\x09%8%h%\x97%\xc7%\xf7&\ +'&W&\x87&\xb7&\xe8'\x18'I'z'\ +\xab'\xdc(\x0d(?(q(\xa2(\xd4)\x06)\ +8)k)\x9d)\xd0*\x02*5*h*\x9b*\ +\xcf+\x02+6+i+\x9d+\xd1,\x05,9,\ +n,\xa2,\xd7-\x0c-A-v-\xab-\xe1.\ +\x16.L.\x82.\xb7.\xee/$/Z/\x91/\ +\xc7/\xfe050l0\xa40\xdb1\x121J1\ +\x821\xba1\xf22*2c2\x9b2\xd43\x0d3\ +F3\x7f3\xb83\xf14+4e4\x9e4\xd85\ +\x135M5\x875\xc25\xfd676r6\xae6\ +\xe97$7`7\x9c7\xd78\x148P8\x8c8\ +\xc89\x059B9\x7f9\xbc9\xf9:6:t:\ +\xb2:\xef;-;k;\xaa;\xe8<' >`>\ +\xa0>\xe0?!?a?\xa2?\xe2@#@d@\ +\xa6@\xe7A)AjA\xacA\xeeB0BrB\ +\xb5B\xf7C:C}C\xc0D\x03DGD\x8aD\ +\xceE\x12EUE\x9aE\xdeF\x22FgF\xabF\ +\xf0G5G{G\xc0H\x05HKH\x91H\xd7I\ +\x1dIcI\xa9I\xf0J7J}J\xc4K\x0cK\ +SK\x9aK\xe2L*LrL\xbaM\x02MJM\ +\x93M\xdcN%NnN\xb7O\x00OIO\x93O\ +\xddP'PqP\xbbQ\x06QPQ\x9bQ\xe6R\ +1R|R\xc7S\x13S_S\xaaS\xf6TBT\ +\x8fT\xdbU(UuU\xc2V\x0fV\x5cV\xa9V\ +\xf7WDW\x92W\xe0X/X}X\xcbY\x1aY\ +iY\xb8Z\x07ZVZ\xa6Z\xf5[E[\x95[\ +\xe5\x5c5\x5c\x86\x5c\xd6]']x]\xc9^\x1a^\ +l^\xbd_\x0f_a_\xb3`\x05`W`\xaa`\ +\xfcaOa\xa2a\xf5bIb\x9cb\xf0cCc\ +\x97c\xebd@d\x94d\xe9e=e\x92e\xe7f\ +=f\x92f\xe8g=g\x93g\xe9h?h\x96h\ +\xeciCi\x9ai\xf1jHj\x9fj\xf7kOk\ +\xa7k\xfflWl\xafm\x08m`m\xb9n\x12n\ +kn\xc4o\x1eoxo\xd1p+p\x86p\xe0q\ +:q\x95q\xf0rKr\xa6s\x01s]s\xb8t\ +\x14tpt\xccu(u\x85u\xe1v>v\x9bv\ +\xf8wVw\xb3x\x11xnx\xccy*y\x89y\ +\xe7zFz\xa5{\x04{c{\xc2|!|\x81|\ +\xe1}A}\xa1~\x01~b~\xc2\x7f#\x7f\x84\x7f\ +\xe5\x80G\x80\xa8\x81\x0a\x81k\x81\xcd\x820\x82\x92\x82\ +\xf4\x83W\x83\xba\x84\x1d\x84\x80\x84\xe3\x85G\x85\xab\x86\ +\x0e\x86r\x86\xd7\x87;\x87\x9f\x88\x04\x88i\x88\xce\x89\ +3\x89\x99\x89\xfe\x8ad\x8a\xca\x8b0\x8b\x96\x8b\xfc\x8c\ +c\x8c\xca\x8d1\x8d\x98\x8d\xff\x8ef\x8e\xce\x8f6\x8f\ +\x9e\x90\x06\x90n\x90\xd6\x91?\x91\xa8\x92\x11\x92z\x92\ +\xe3\x93M\x93\xb6\x94 \x94\x8a\x94\xf4\x95_\x95\xc9\x96\ +4\x96\x9f\x97\x0a\x97u\x97\xe0\x98L\x98\xb8\x99$\x99\ +\x90\x99\xfc\x9ah\x9a\xd5\x9bB\x9b\xaf\x9c\x1c\x9c\x89\x9c\ +\xf7\x9dd\x9d\xd2\x9e@\x9e\xae\x9f\x1d\x9f\x8b\x9f\xfa\xa0\ +i\xa0\xd8\xa1G\xa1\xb6\xa2&\xa2\x96\xa3\x06\xa3v\xa3\ +\xe6\xa4V\xa4\xc7\xa58\xa5\xa9\xa6\x1a\xa6\x8b\xa6\xfd\xa7\ +n\xa7\xe0\xa8R\xa8\xc4\xa97\xa9\xa9\xaa\x1c\xaa\x8f\xab\ +\x02\xabu\xab\xe9\xac\x5c\xac\xd0\xadD\xad\xb8\xae-\xae\ +\xa1\xaf\x16\xaf\x8b\xb0\x00\xb0u\xb0\xea\xb1`\xb1\xd6\xb2\ +K\xb2\xc2\xb38\xb3\xae\xb4%\xb4\x9c\xb5\x13\xb5\x8a\xb6\ +\x01\xb6y\xb6\xf0\xb7h\xb7\xe0\xb8Y\xb8\xd1\xb9J\xb9\ +\xc2\xba;\xba\xb5\xbb.\xbb\xa7\xbc!\xbc\x9b\xbd\x15\xbd\ +\x8f\xbe\x0a\xbe\x84\xbe\xff\xbfz\xbf\xf5\xc0p\xc0\xec\xc1\ +g\xc1\xe3\xc2_\xc2\xdb\xc3X\xc3\xd4\xc4Q\xc4\xce\xc5\ +K\xc5\xc8\xc6F\xc6\xc3\xc7A\xc7\xbf\xc8=\xc8\xbc\xc9\ +:\xc9\xb9\xca8\xca\xb7\xcb6\xcb\xb6\xcc5\xcc\xb5\xcd\ +5\xcd\xb5\xce6\xce\xb6\xcf7\xcf\xb8\xd09\xd0\xba\xd1\ +<\xd1\xbe\xd2?\xd2\xc1\xd3D\xd3\xc6\xd4I\xd4\xcb\xd5\ +N\xd5\xd1\xd6U\xd6\xd8\xd7\x5c\xd7\xe0\xd8d\xd8\xe8\xd9\ +l\xd9\xf1\xdav\xda\xfb\xdb\x80\xdc\x05\xdc\x8a\xdd\x10\xdd\ +\x96\xde\x1c\xde\xa2\xdf)\xdf\xaf\xe06\xe0\xbd\xe1D\xe1\ +\xcc\xe2S\xe2\xdb\xe3c\xe3\xeb\xe4s\xe4\xfc\xe5\x84\xe6\ +\x0d\xe6\x96\xe7\x1f\xe7\xa9\xe82\xe8\xbc\xe9F\xe9\xd0\xea\ +[\xea\xe5\xebp\xeb\xfb\xec\x86\xed\x11\xed\x9c\xee(\xee\ +\xb4\xef@\xef\xcc\xf0X\xf0\xe5\xf1r\xf1\xff\xf2\x8c\xf3\ +\x19\xf3\xa7\xf44\xf4\xc2\xf5P\xf5\xde\xf6m\xf6\xfb\xf7\ +\x8a\xf8\x19\xf8\xa8\xf98\xf9\xc7\xfaW\xfa\xe7\xfbw\xfc\ +\x07\xfc\x98\xfd)\xfd\xba\xfeK\xfe\xdc\xffm\xff\xff\x80\ +\x00 P8$\x16\x0d\x07\x84BaP\xb8d6\x1d\ +\x0f\x88DbQ8\xa4V-\x17\x8cFcQ\xb8\xe4\ +v=\x1f\x90HdR9$\x96M'\x94JeR\ +\xb9d\xb6]/\x98LfS9\xa4\xd6m7\x9cN\ +gS\xb9\xe4\xf6}?\xa0PhT:%\x16\x8dG\ +\xa4RiT\xbae6\x9dO\xa8TjU:\xa5V\ +\xadW\xacVkU\xba\xe5v\xbd_\xb0XlV;\ +%\x96\x10\x01\x07ZDA\x1b`\xac\x1bo\x0f\x81\xae\ +A\x10\x0d\xd4\x02\xf9\xbc<\x1eW\xb6\xe3\xc6\xfc\xda\xbf\ +<[vl&\x166\x0a\xc4\x06\x84x\xb2\xb6,F\ +Y\xb6\x04E@\x5c\xa02(\xfc\xcc=\xdd\x99\xb6c\ +\x83<\xb2n\xe8U\x0f]#\x93\x0d\xa7\xc3\x04\xf5C\ +\x01n\xb4\xde\x1e\xd8\x12\xc1\x1b0\xac\xb1\xf1\xb7v7\ +\xf7J\xe6\xce\xf5:\xea\xe02\xb5\x1c:\xc8\xbf\x8cu\ +\x19\xf2O\xe0N`.x\xfd\xe8>\x18\xbd3cc\ +\xac\x9d\xe2vi ~\xe0K\x923?\x8b\x10*b\x1eA\x04\xa8U\x05\x8dH\ +\xc1\xdd\x07\x9aN\x01\xd4e\x9c\xf0\xa9\x82\xd2\x1e\xa7)\ +\xfd\x0d\x9f,\xa0\x0a\xb7\xad\xe1\x105\x11\x88\x00\x94L\ +\x16\x02\x11HP\x81\x80(\xc1\xad\x17\x93\x064d6\ +\xc3g\xf1\xf9\x03G\x09(]\x1d\x8eA\xc4|F\xa2\ +\x90\x91\x94fH\x83\xe1\xcb#\x97\xb0\x11\xff\x02\x22\xe0\ +\x14\x9c\x02\x832\x88|\x18\xca\x83\xe4F\x0d\x08\x08\xc1\ +\xa1-\x90\xe6T\xbc=G3\x0a;\x13\x02Ah\xa1\ +3\x99\x0e`\x08\x05\x22\x06\xdc\xdcR\x18s\x88\xcc\xcc\ +\x1f\x87\xbaP\xbb\x00MhZ8\x86\xf3\xe9\x12\xbb\x00\ +h\x82\xf0|\x9d\xe5U\x0c\x14=\x87\xb9\xd51Q\x88\ +\xa8\x93G\x96\xc0\xed$$\xa2\x0d\x09\xbaT\x97\xf4\xc8\ +\xbd\x1a\x9fI\xa07O\x88b\x0dDR1\x00P0\ +\x88\x1bUIB`U\x83\x05\x1bW\xa1\xa0]d\x0d\ +\x8a\xf5\xa9\xb359\xc8\x5c0r\x15\xb5\xe8`\xdb\x9f\ +\x07jx\x0b\xd8\x81\xd0\x9bc\x98\x12p\x04\x02\xa1\x94\ +\xe1Wg\x85\x8c\x0b\x07XZ\x88 ik\x90A\x95\ +\xb4>\xa2\x13\x89\x864\x1a\xf7\x092\xa2\x077)\x1f\ +=\x0e\x08\x84\xb6h\x11\x12\xf1\x94<\xda\xb5\x83\xb8\x03\ +\x82U\xa8\xael6`Cj\x85\xd1'QQ\x7f\x84\ +\x87\xde\x04y\xa8\x80\x1e\x0c\x04\x0axI\xa1\x14\x82\x01\ +:\x18y\xe2\x07\x05\x9eU\x85s\xa1\xedx\xcc/\x10\ +X7\x07X\xe9\x22\x887F\xf9\x5c]\xe4\x82\x9a\x99\ +\x8d\x0d\xf8\xe8tH!\x92Q\xfcWf\x01\x99\xdb\x99\ +\x9a\x18\xc3\xe0\xf9\x01\xe2\xb6tkT\xa0\xd2\x1e\x7f\x96\ +Z\x08zth\x86*\x98\x04\xe9\x00\xbet+\x1a\xf7\ +\x98\x22\x86\x17\x9a\x88\xaaoj\x85fl\xf7\xe1\x81D\ +\xce(\x18\xef\x90 \x86h\x87A\x86Y\xec\x82\x06\x5c\ +\xa8\x0a;I\x96\x0a\xed\x81\xa2\x18an\x03#\xcc\xec\ +j\xef\x80\x03Y\x01`\xd6\xd8\x0a\x86\xb7D\xa2\x0c\x87\ +\xe8#\xfe[\x89G\x1f\x0c[\xaa\x827\x14X\x04\x1c\ +h\x9e\x86FF0\xdcjr\x84\x9e\xebx\xd3\xe0\xd8\ +\x87\xcc\x88\x86o<@:\x07\xe9\xf2\xaaQ\xe2M#\ +I\xf2\x11\x97'\xca\xf2\xfdj\xb35\x018H\xa6h\ +\x81\xfd\xa8J\x86\x18=\xc8\xc6\xde\x9b$\xf7]\xdf\xaa\ +\xaf\xc0,\x1ckf4X\x86\x17^H\xa4\xcf\x1c\x05\ +\x7f\x81\xe7\xaa!\xf7\xa4M\x85\x1e\xa8\xc9\x96\xc0G\xe9\ +_\xed\x86\xcc\xd9\xd8gz\x1f\x0a\x92\xc8\x85B\x97\xcc\ +g`\xc0\x18\x0e\x86\x1d\xffi\xad^\x95\xa1\x8d9\xf1\ +~\x8a-\xca\x1c\x91\xd3\xd0\xe2\x88s\xc6i\x02\xffD\ +\x03\xf5\x80E\x05\xf4\x80v\x966\x11\x00 !\x83\xda\ +\x06\x0ef`+\x81\xa4\x0c\x1e\xc3\x9e\x01\xc1Rz\x95\ +\xc2\x10L\x83B\xf1\xe3\x90\xb1\xf5\x07\xc7\x84!\x1e\x03\ +e<\x0fHL8\xc7\x0c)\x16*\xa4m\x0a(-\ +\x0b\xc8\xaa\x1e\x01\x8d \x04\x81d@\x08KH\x0e\x04\ +\x802\x1e\x01\xd8h\x06\x1b\xf8>v\xa0=\xdb\x923\ +\xf89\x05\xd3\x91\x0d\xf0\x88lC\x07\x5c\x87\x80kx\ +\x03p&!\x82f\x18\x0ab\x18$\x87 \x8e\x1a\x01\ +epO\x10x\xee\x1aB\xc22\x03\x96-\x13\x8a\xe2\ +x\x86L\xe1\xbcC\xe6\x90\x05\xa2\xec?\x87\x800\x0e\ +\xb0\xc0O\x1bU(\x19\x80\xa5a\xe4\x8b\xa7\x96g\x9e\ +th(\xcb(\x02\xb7\xb0i\x0eA!\x91\x05q\xda\ +\x1c\x82%\xe6\x04\x95\xc3NQ\x90\xb0P*\xc1\x80\x18\ +d\x11>k\xc0\xaeN\x06\xb0E'\xc2\xa9\xaa\x02`\ +\xbd\x1c#Q\xf6\xc5\x96\x00\xeci\xd2<\x86!Q\xce\ +0\x9b \xb3p2d\x9cH\x80\x8f-\xc5\x84\x8a,\ +\x08\xd4~,\x01\xd5\x09\x87\xa0\xe2\x89\x90\x88\xc0\x17\xe1\ +\xb2\x86\x074\x1f\x1fC\xc6e\x0e\xf5\x06<\x10@<\ +\x12\xa0\x9ej\x06\x22\x190\x07\x18\xac\x9b@\xb6e\x0f\ +\x19hL$ N\x9cC\x0d\xe1\x03r\x98\xe8G\xc2\ +\x89\x1dl@y\x8d\xe3\x027!\x10\xd6\x89\x93\xb0p\ +\xcc\x01\xc4\xc0\x87\xdb\x04#i\xf4\x1b\x88\xa3\x8c\x0b\xc3\ +\xa9\x0ct#\xe6m\x0a\xc0\x5c`F\xd4\xdf%\xe0\x9a\ +\x86\x06\x00\x81C\xc4\xf90e\xca\x0cv\xcd\x8a\x10\xb4\ +\xa0\x90\xe8Pc\xb9`N\xb6\x22\xa2GL\xf8\x1e\x84\ +\xd2N\x02\xb0\xd6\x0e\xe9@\x94\x22\x02\xe2\x96\x04\xb1\xc5\ +K\xc5\xb5\x0a%\xce(#\x0a\xf7\x1a\x08\x02\x81\x18\x97\ +\x94vv\x0e\x02\xf6<\x86\xeb\xed\x1d\xe3QiS\xf1\ +\xbb=\x94\x18\xef*\x8ep%\xd4\xd1vD\x06=Q\ +\x0e#N\xaa2\xcadK\x168M\x181\x04\x86Q\ +\xd1\xa5W\xc4ta\x1aS\xd1]\xcd\xd3\x87\x16\xc2\xad\ +i\x1a\xb1\xec\x85\xa2\xf1\xac&\x06%q\x0d5\x5c\x96\ +P\xf0\x80(h`&\x0b\xd0.\x06\x8aZ\xfc\x07\x92\ +P\xfdQ\x8f\xa4\x044\xb1\xaf\x02H`\xe6\xb1B\xfc\ +ZX\xd0\x85]\x09X0\xb2A\xe4\x1bYQ\x0c\xf6\ +\x07\xf8\xfd~\x00\xca\xb1-J\xb20\x1b\xfc\xb3!T\ +\xfcoPP[\x19\xec\x81%\x03\xf6\xac&\xcbp\x8e\ +,\x88\x83Q\x17\x8dM\xaa\x93KBc\x82\xb47\x95\ +-\x84b&\xe1\xb6)S\xa0\xf5%\x93DK \xb0\ +U\x5c\xc8\x5c\xe8\xa0\xa0\xbe\x84Z\x92J\x99\x01s\xb2\ +\x19\xe9\xe0\x86.\xe0\xf0\xba\xc4I,\xb0\x8f\xdcG\x82\ +\x9b\xbc\x19\xae\xa1\x0b\x1d7\x8cc)\x91~\x17\xaa1\ +(G`\xb9\x1e\xa3\xf2 -o\x80DH\xe3\x94^\ +\xdc\xe2H\xd7\x97\xb0\xd8\x86\x80\x5c\x86[\xe1Gy\xab\ +\xd9*\x004\xd0WSzrE\xe7\xb4}\x0a\x0fx\ +g\x92E$\x07BC\xa5q\x04>\xb8\x8c@\xd5[\ +\x84\xbd\xf6$\xed\xa4(\xb6\xb6\xdaC\x10\x90\xc8\x8c\x82\ +\xc0\x1c\x92\x8bCg\xc9\x03\x86\x1cb\xe1\xc1\xa9BG\ +\x1d\x82\xa61\x1ar\x10\x86.\xb5\xda\x97\x97\x86\x1a$\ +\xa1\x0f\x1e\x0as\x1c\x16\x08b\xbbP\xc2\xa8\x15O\x89\ +\xf4H\xab\xb0\xa0\xaf!|\x90A!\xce\xbf\xc5@%\ +\xb8$\x82\x19@x\xa4C\x1d\xe0\x9ew#\x041\xe3\ +\xa2J\xb6\x81\x90|Z\xe0\xd0A\x90\xc6-\x90\xc1T\ +\xc0\x1c$\x93\x0ea\xe0*\xdb\x88\xfc\xe8b`\xae\xd2\ +\x12I\xc4\x13\x86\x18\x18\xcf@\xf0\x86R\xf1\xc4-)\ +`\xb8\x09\xb9x\x92\x18\xe0\xaf\x8f\x02\x18\xa8\xb3\x16i\ +^\xd9\xc4 I,\xfd\xa1$\x14\x8b9\xcfbI\x92\ +rY\x0c\x1dzlf=\xb1^\x0d\x88\x18\xff\xd0\x84\ +~Q\x03\x07\xcc\x14\x86m\xe1!V4Z\x04+\x14\ +9\x85\xf9$\xcckem\x92\x0a\x8d\x90\xc1L\xa6$\ +\x97\xac:#\xe0p\x22\xc8e b`\xb2T\xea2\ +<\xbe@\xa2\xf6\x1bRH\x85\xc9`\xbf\x0b!q#\ +\x91\x0d,j\xac\xa0\x0cG\x1c\xa0\xd4\x12.Et\x92\ +{V\x07\xc2u\xae\x16+5\x0d\x8f\xc8\x1f\xa3\x87p\ +\xd3\xd8\xc4u@\x1cH#\x82\xc4\ +i\xcd\x07\x02(\x8a\xef\x08Y@\x08!\x83\xd2\x19`\ +\xf6\x19\xf0\xc4\xb2\xe2nP\x0b\xf6\xfbH\xb6\x91H\xb6\ +k(\xf2\x8a\x07`&\x0e\xc8\x11\x8e\xc2\x19\x0a\x03\x0b\ +\x02&g\x05\xec\x1b+\xf6\xf5g*r#\xc8#e\ +\x00M@\x15\x08\xe8\xe6\x03\xe8\xaa\x8a\xa7\xc8\x81/\xb4\ +k\xc2\x90\x99A\xe0\xb3i\xd8\x1b\xf0\xec\x22\xc0\x02x\ +\xa7\x84?B\x16\xf4a\xb8\x14\xcf@\x17\xc0\xb6 \x8b\ +\xf6\x8f0\x9cEH\xb2D\x00E\x0aF\x9ck\xc8d\ ++\x8a@\x171\x5c\x0a\x0cC\x12b4\x08Qh\x14\ +\xa0I\x16\xe0\xb4\x9a\xe8L\x1c.\xde\x18\xe8\xab\x10\xa6\ +\x9c\xd5C\x88\x99A\xe4\x95\xc1\x80H\x81\x98\x0f\xe6f\ +\x1d\xa6k\x16B8\xb2@`\x0f\x0e8\x10\xe9J\xdc\ +\xa9|\x9e\xc9\x88\xa7\xe1\xb6X\x01\xda\xa3\xa9R\xa8\xc9\ +\xb1\x19\xc2H\xebn\xba\x9cN\xbe+i\xd1\x1b\xe2\xf6\ +\x9d\xc2\xfc\x1bi\x86\x84!\xac\x9e\x89\xec\xc8\xd1\xc4'\ +\xe7`\xb5\xc1ds\x82v\x1f\xe9R\x9b\x040\x1c\xaa\ +(\x9dQ\xfe0!\xb2\x9d\xeaA\x1e\x91\xea+0\xa4\ +\xae\xc1D\xa6\xe7\x1e#jv7\x11\x22\x9d\x81\xbc\x8c\ +!\xaa\x9ef \x1b\xec\xd4\xa92\x12Z\xa4\xf0\xeam\ +\xbe\x09\xa9\x1e\x97\x91\x1c\xa2\xe2\xfc\x1b\x8a\x85\x1e& \ +\x1b\xd1\xfe\xf2\xf2;%\xf2a&2e&ri&\ +\xb2m&\xf2q'2u'ry'\xb2}'\xf2\ +\x81(2\x85(r\x89(\xb2\x8d(\xf2\x91)2\x95\ +)r\x98(\x22\x02\x00\x03\x00\x01\xa0\x03\x00\x01\x00\x00\ +\x00\x01\x00\x00\x00\x02\xa0\x04\x00\x01\x00\x00\x00`\x00\x00\ +\x00\x03\xa0\x04\x00\x01\x00\x00\x00`\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\ +\x00\x00\x02\x93\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22?>\x0a\x0a \x0a Artboard\x0a \ +Created with Ske\ +tch.\x0a \ +\x0a \x0a <\ +circle id=\x22Oval-\ +3\x22 cx=\x223.0315222\ +4\x22 cy=\x222.9313699\ +9\x22 r=\x222.5\x22>\x0a \x0a \x0a\x0a\ +\x00\x00\x02\x9b\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22?>\x0a\x0a \x0a Icons / Sys\ +tem / Carat / Wh\ +ite / Default\x0a \ +Created with Ske\ +tch.\x0a \ +\ +\x0a <\ +/polygon>\x0a \x0a\x0a\ +\x00\x00\x05\x14\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22?>\x0a\x0a \x0a icon / outl\ +iner / slice / s\ +tandard copy 2\x0a Created with Sk\ +etch.\x0a \ + \x0a \ + \x0a \x0a \ + \ +\x0a \ + \x0a \x0a \x0a\x0a\ +\x00\x00\x03(\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22?>\x0a\x0a \x0a icon / outl\ +iner / layer / d\ +efault\x0a \ + Created\ + with Sketch.\x0a \x0a \x0a <\ +rect id=\x22Rectang\ +le\x22 x=\x220\x22 y=\x226\x22 \ +width=\x2212\x22 heigh\ +t=\x228\x22 rx=\x221\x22>\x0a \ + \x0a\ + \x0a \ + \x0a \x0a\ +\x0a\ +\x00\x00\x04\x96\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22?>\x0a\x0a \x0a icon / outl\ +iner / entity / \ +Not active - Def\ +ault\x0a \ + Created w\ +ith Sketch.\x0a \x0a \ +\x0a \x0a \x0a\x0a\ +\x00\x00\x09\x85\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22?>\x0a\x0a \x0a Artboard\x0a \ +Created with Ske\ +tch.\x0a \ +\ +\x0a \x0a \ + \x0a \ + \ +\x0a \ + \x0a \ + \ +\x0a \ + \x0a <\ +/g>\x0a \x0a\x0a\ +\x00\x00\x05\x15\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22?>\x0a\x0a \x0a icon / outl\ +iner / slice / \ +Editor only - Sa\ +ved\x0a \ +Created wi\ +th Sketch.\x0a \x0a \x0a \ + \x0a \x0a\x0a\ +\x00\x00\x02\x93\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22?>\x0a\x0a \x0a Artboard\x0a \ +Created with Ske\ +tch.\x0a \ +\x0a \x0a <\ +circle id=\x22Oval-\ +3\x22 cx=\x223.0315222\ +4\x22 cy=\x222.9313699\ +9\x22 r=\x222.5\x22>\x0a \x0a \x0a\x0a\ +\x00\x00\x05\x19\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22?>\x0a\x0a \x0a icon / outl\ +iner / slice / \ +Editor only - Up\ +dated\x0a \ + Created \ +with Sketch.\x0a \x0a \x0a \ +\x0a \ +\x0a\x0a\ +\x00\x00\x05\xfa\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22?>\x0a\x0a \x0a icon / outl\ +iner / lock / on\ +\x0a Created with \ +Sketch.\x0a \ + \x0a \ +\x0a \ + \x0a \ + \x0a \ + \ +\x0a \ + \x0a \ + \x0a \ + \x0a \x0a\x0a\ +\x00\x00\x15\xa4\ +I\ +I*\x00B\x08\x00\x00\x80?\xe0@\x08$\x16\x0d\x07\ +\x84BaP\xb8d6\x1d\x0f\x88DbQ8\xa4V\ +-\x17\x8cFcQ\xb8\xe4v\x0b\x02\x7f\xc7\xa4R9\ +$\x96M'\x94JeR\xb8\xa4\x82Y/\x98Lf\ +S9\xa4\xd6a.\x9bNgS\xb9\xe4\xf6}#\x9c\ +O\xe8T:%\x16\x8d/\xa0\xd1\xe9T\xbae6\x9d\ +\x1f\x81\xd3\xeaU:\xa5V\x91Q\xabVkU\xba\xe4\ +B\x93]\xb0XlU*\xfd\x8e\xcdg\xb4N\xec\xb6\ +\x9be\xb6\xdd&\xb5\xdb\xeeW;\xa4J\xe3u\xbc^\ +o7{\xd5\xf6\xfdi\xbe_\xf0X:\xde\x07\x09\x87\ +\xc4Sp\xd8\x9cf6\x7f\x8b\xc7drS<\x86O\ +-\x97\x93\xe5s\x19\xbc\xe4k5\x9d\xd0hk\xd5\x8d\ +\x16\x97M-\xd2Q\x00:\xbb\xf1\xaf\x5c\x1a}\xecG\ +pQ\x94\x14c\x05\x0e\xc1B;\xa8K\xbe\x0a\xf0\x82\ +\xb8\xf5`\x16|\x15\x9c\x04\xe41\x12\xbc\xb75\xf7?\ +\x94\xd4\xd0\xf8v\xc3?T7 .AJ\x10Q\xbc\ +\x14\x036\x90\xc1\x19pUx\x0f\xcc\xa5K\xfa\x5cx\ +\x0e\x8d\x0b\x9f2\xe9\xd7M\x1f1\xc4\x80\xe1 )\xc1\ +@\x95g\xe7\x93\xcc\x01\x92\x0fI.c+\xafzc\ +\x03&\x0f\x8a\xa44\xc1\x80\xe9\xfb\x07\x91\xa8(\xaa\xbd\ +\x15\xa8(\xe4MC\x07\x12\xa7\x04*\xef\x0a\x8d\x05(\ +\xa3\xfcD\x03\x1d\x11(\xe6\x90\x0fh(\x16\xc4\x1e\xc8\ +)\x0a\x03\xc6\x04i'\x19\x9f*<8\x96F\xe9\x5c\ +@\x9f\x0c\xd1\xe8\x8c\x82\x92h(L\xd1\x1bh(\xdd\ +\x0c\x13E\xc2\x87\x1c\xa5RbS\x1d\xa6q\x10\xfe\x01\ +D\xa7A\x06\x90\x0fM:\x1eD\x032\xe8\xf6@\xcc\ +\x07\xf2s'%\x13\x22O(%\x83|\xd4\x08\x1e\xf3\ +iL\x82\x892\xd2&\xe1\x97\x00D\xec,\x923\xcb\ +\x80\x99L\xcb\x83\xda\x9f\xcd\x09;\xaa3\x85I\x01`\ +\x82\x84\xb3\x92:n9\x00 \xa0KR\x06\xac:\xa5\ +O\xa9-\x02\x91G\xa30\x86\xf2 \xa0m\x14\x93\x9e\ +\x8f\xf8\xa3\x01\x17\x89M*\x92T\xe9\x1d.\x8dPb\ +*@X\xa0\xa0M>\x98\x1f\x0e\x18\x9cL\xd7\x05\xda\ +KT\xa4U\xe2=U\xa2\xb4\xcc~\x82V\x08 \x10\ +\xa99\xa8!X\x82\x96\xef\xf9\xc2\x06Z\x07!\xebi\ +\x9f\xee\x1b`\xd8\x97\xa8(8\xae\x1f\x08(\x9f$\x17\ +H\xf5|\x8e\xdch\xe5\x80\x88>c@\x8e\x7f]\x94\ +=\x8c\xa6\x1c\x00\x15\xe4:\x02\xf7\xa9_0\x103\x15\ +\x83\x1e\x9b\x88(F\xb1\x1f\x17\x90\x04(\x13\x18)r\ +\xcfO\xe9\xf5\xca\x8d\xdc\xe8\x5c\x184\x86\xb0y\xfa`\ +\xd6*a\x18\x05\xe3\x03\xf1\x1f\x8d\x9e\xe8\xf53~\xa0\ +\x97\xfa\xcf\x16\xa0\x81\xfc\x90f\x22\xd8^\x11\x0f(\xb8\ +j\x0dL\x83\xc8)\x92\x82\x83\x0a5\xf4\x00\x0d\x92A\ +.\x94\xe3\xf7\xf2\xdcs\xbf\xe1\xbc\x04\xf5\xa29R3\ +\xa3#\x18h\xdb\xa5\x81\xc7\xce\x9cb\xa0\xa1b\x8e\xe1\ +\x8c\x95\xc12N\xa5\xf9\xeeB\xba\x1a@~\xbc\x1e\x11\ +{\x09\xe6\x87i\x08\xbe\xca\x8bR\xe9\x00\x03A\x96h\ +(\x96\xa6\x14\x12@\xc2\x99\xeb@\x06D\xbc\x16Z\xb0\ +\xa0\xe1\xe5\x886\xce\x8a\xef\xe8\xa5/L\x8f\x88)\x07\ +xc\x00XU\x8d\x91\xf8\xeae\xba\xee\xeb\xc3\x86;\ +\xea\xc4R\x15\xc0\xa2|\xc2%\x1d\xdd!\xed\xd8\x7f\x17\ +\xe8(\x06\xa6\x0c\xb2A8\x9c\xf2\x0c\x13\xfa\x82\x07\x92\ +Ff\xa8o\xb2^\x12\x9e\xbazX\xdb\xa6\xe9\xc6\x92\ +\x0a\x0f\xa9\x87\x0d\x11$\x1f}E\xf9\x9f0\xf2*\x08\ +\x18I\x07\xb75\xa2\xf6i\xe3\xa7A\x91\xa9\x00\xe4\xa6\ +\xb8dN\xac<'\xbdK\x10\xe1\x90:\xb1\x01\xe5\xb4\ +}\x8a\x848|\x93d\xdb\xa2\x00\x00b\x9a\xff\x88\x10\ +\x16(\x9e{La\xdfF\x83\xceY*zF\xdej\ +wt\x8e\xc9\x01\x12T\x9cp\x00\x01\xef\x01\xec\xbc6\ +\xb6c\x8e\x18r`\xa2`G\xbf\x97\xc4O\xd4\x18\xb5\ + \xa1(\xa9\x0d\xd4\x90\x09\x0a\x1b\x0f\x04D\x80\x02\x92\ +\x97>\xdbH\x22\x89)\x87\x0cY\xc0\xb0\x9d\x03\x8aR\ +\x83\x1b)\x08\xa9\x0cT\x90\x0f\x0c\x1a\x99t$\x10 \ +\x15!\xb0\xd5\x81L((\xea\x0d\x92\x00\x05dS\xc5\ +\xa2H\x09\xb0\xc5\x1e\x8a\xf3\xb4T\x87\xb3VEe\x19\ +\xf0\x10\xf5\x067\xc8( *C\x19$\x1b3\x04\xa6\ +F\x11\x05\x07\xa5Ho5g\x22\xec\xa0y>Pj\ +\xe8\x82\x04H\xb8\x92\x22\xf9zS#iD\x15!r\ +\xd5\x82D:(\xcb\xa4D\x12\x00\xeeT\x87\xc2]\x03\ + =|\x0f\xa2\xea\xa6`\xe9\x04O`\x00\x05=C\ +V! X}\x8eE\x14\xd7\x06\xb0>?$\x80\xdd\ +tE5\x81\x048\x16/\x8b\xaa\x83\x08\x04\x82\x19\x94\ +\xe1\xf4\x01e\x00!\x12\x92\x8dd\x94X\x9aC\x8e\x9a\ +\x99\x15$\x14+\x15\x22\x00\x8cM@\xce\xa0\x084\x1e\ +\x11\x09\x85B\xe1\x90\xd8t>!\x11\x00\x19\xa2\x88\x98\ +9\xda%\x19\x8dF\xe1)\xe8\x1ah\xc6\xff\x91G$\ +\x92XD\x89\xff&\x95G\x002\xd0\x01\xa6`\x22~\ +\xcc\xda\x10pl\xaeq\x1aq\x86g\x82D\x0c\xfd\xf5\ +9\xa1P\xe1G\xfa0\x19\xcfInA\xc3\xb4Jt\ +)\xdf-\x00\x8bS5W,\xa2\x9fY\xacVi\xd5\ +(I\x9e\xc0^\x94(k\x96X1\xa6>\x98\xb3Z\ +\xe31C1\xa2\x0e\x97\xb6Q*Ez\xaaeU'\ +\x91\xdc\xe5u\xbb\xe4\x9a\xbd\x0c\xb7'\xe0\xe6\x0b\xfc\xe1\ +\xc4\x0d\xc5\x0a\x91\xb8\xd7\xae\x1e\xd8j\xc9\x03\x1f\x99V\ +\xb53!$\xa9&\xae\xe6xe\xfb3\x1a\xd0hb\ +X\x18]\x18\xfe\x08\xa4\xb9\xd8\xd0q\x8e\x92H\xa5\x8f\ +\x976\x15\x9br\x9a\x0eY\xda\xe9e\xac\xc06\xfcx\ +\x93\xe1>s\xf7\xbd\xdcCG\xc7\x86i\xa1\xc6\xdep\ +q\xf3\xd1d\xc1\xc3\x5c\xa8}H\xd7wKu\xa3\x96\ +\xe3l\x1d%\xdc\x889*C\x8b\xbb\x97\x91\xc6\xf1B\ +\xb9>\xb872#\x925\x0c2\xaf\xc6\x1c\x1c\x19\xee\ +\x84\xca`\xc7H\xf9\x1c\xfd!+r\x0a\x83\x22\xcf|\ +\x02\x83\x9e`\x1c\x16\x1e\x12\xf0q\xa4\xd1=PC\xda\ +\xf7>\x08\xd0\xd1\x0c\x09'\xf46Y \xe0$\x10\x85\ +\x12\xe0|F;\x91q1\xe6\xd29\xc3h\x1c}E\ +\xa4ZP3D\x08I\xf8\x01F\xa2a1\x1c\x17)\ +,(\xf5\xc7\x8f\x14,\x92-\xcd\xa2\x0cP \xe0\x1c\ +d\x84\x1d\x088\xf0\x83\x94\xc8\xf9\xf6\xa25\x0aB\x92\ +-\xa0\xe4:\x0e\x0b\xc9\x089\xfa\xc2\xa3\xe5\x22q\x1f\ +;\x93\x0b\xad %P\xc0\xd0,Cg\xf1G\x0fK\ +HQ\xe0\x83\x96\x089q\x1a\x80G\x08\x0b<\x1c\x88\ +A\xf7>\x03\x93P>\x83\x89\x088\xa0\x83\x82\x13r\ +\x12~\xce\xa2\xe4pL\x15\x0a$\xc6\xe5R\x0e<\xca\ +\x9c\xac\x038\xa8\x947\x080\x0bC\xd3\xac9\xf8\xa9\ +\x0b+\xb9X\xaeRM\xddL\xda\xd2\x8a\x22\xddB \ +\xc5:\x0e\x04S\xd5\x92\x88|7(\xfc\xe4\xb5\xd5\x0d\ +\x85t\xd2UJ\xca`4\x86i\x99\xfaW \xe0\xf5\ +gd#G\x12\x0e)\xa3\xe6c\x0f^46\x8b3\ +_,\xcbp(\xa9\x15\x09@\x87d\xdb\xa8A~\x03\ +\xdc\x22\xbb\x84I\x9dm%\xa6\xc8]\x0c=\xaa\xb9\x95\ +Wp\x06^^$B\x0e:[\xd2\xd2\xa4G\x08w\ +\xd0\xec+_\xb2\xe5O\x09@7R\xffv4\x93<\ +5\x0d\x92(8K{7f\xe2\xa47\xae\xe5\xb6\x05\ +\x80\xbfX\x1a\xf9\x82\xb7r\x93V9 \xe3\xdb\xf1\x86\ +\xa9\xecz\x0cC\x5c 9\x1br8\x91\x96.\xb9\xe5\ +\x8bf2\xf7R\xc0\xdaPE \xe2\xd6B\x93\x15\x19\ +0\xebrOU\x9e]\x5c\xe2\xb0\xaa]\x9c\x22h\xa0\ +d\x83\x8d\xc88\xb0\x83\x80\xf6\xf6T\x00\x15PX\x06\ +H\xc1\xc4\xb9\x9b\xa2\xe8\x0b6\xb4\xb2\xe6\x16LT\x0a\ +\xc5\xa7\xd0\xafA\xa5\x01\xfc\xda\xda\x9f\x889\x858\xce\ +\xa5M\x18uh\xae+\xf9\x95\xe8O^\xbd\xb9 \xe3\ +~\xf6\x08\x1e\xfb\xf0p\xa9\x06)C^\x83)\xa85\ +\x0c\x83\x02(\x5c\xe0\x83\x1d\xe89\xc6\x83\x9a\x13\xa9\x9e\ +\xa9\x19\x1a\xb7\x1d\xbc\xa3z\xe5K\xbbs<\xf7?\xd0\ +:\xdc\xdfC\xd2t\xbd2#\xd1\xf4\xfdWW\xd3u\ +=g_\xd8k<\xefc\xdav\xbd_]\xdbw=\ +\xd4'\xd9\xf7}\xf7\x7fn\xf7\x1e\x07\x87\xe2/\x9e\x17\ +\x8b\xe4y4\x7f{\xe5y\xbes3\xe3\xf9\xfe\x97\xa6\ +\x86\xfa>\xa7\xaf\xeb\xfa\xde\xc7\xb7\xe7{^\xe7\xbf\xe2\ +\xfb\xdf\x07\xc7\xdf|_'\xcf\xda\xfc\xdfG\xd7\xd6}\ +_g\xdf\xd2\xfd\xdf\x87\xe7\xcf~_\xa7\xef\x9c~\xdf\ +\xc7\xf7\xe0\xf9\x9f\xe3\xffwo\xea\x00@4\xb4@@\ +\x00\x13\x00\xfe\x00\x04\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\ +\x01\x04\x00\x01\x00\x00\x00`\x00\x00\x00\x01\x01\x04\x00\x01\ +\x00\x00\x00`\x00\x00\x00\x02\x01\x03\x00\x04\x00\x00\x00,\ +\x09\x00\x00\x03\x01\x03\x00\x01\x00\x00\x00\x05\x00\x00\x00\x06\ +\x01\x03\x00\x01\x00\x00\x00\x02\x00\x00\x00\x11\x01\x04\x00\x01\ +\x00\x00\x00\x08\x00\x00\x00\x15\x01\x03\x00\x01\x00\x00\x00\x04\ +\x00\x00\x00\x16\x01\x04\x00\x01\x00\x00\x00`\x00\x00\x00\x17\ +\x01\x04\x00\x01\x00\x00\x009\x08\x00\x00\x1a\x01\x05\x00\x01\ +\x00\x00\x004\x09\x00\x00\x1b\x01\x05\x00\x01\x00\x00\x00<\ +\x09\x00\x00\x1c\x01\x03\x00\x01\x00\x00\x00\x01\x00\x00\x00(\ +\x01\x03\x00\x01\x00\x00\x00\x02\x00\x00\x001\x01\x02\x00\x10\ +\x00\x00\x00D\x09\x00\x00=\x01\x03\x00\x01\x00\x00\x00\x02\ +\x00\x00\x00R\x01\x03\x00\x01\x00\x00\x00\x02\x00\x00\x00S\ +\x01\x03\x00\x04\x00\x00\x00T\x09\x00\x00s\x87\x07\x00H\ +\x0c\x00\x00\x5c\x09\x00\x00\x00\x00\x00\x00\x08\x00\x08\x00\x08\ +\x00\x08\x00\x802\x02\x00\xe8\x03\x00\x00\x802\x02\x00\xe8\ +\x03\x00\x00paint.net 4.0\ +.9\x00\x01\x00\x01\x00\x01\x00\x01\x00\x00\x00\x0cHL\ +ino\x02\x10\x00\x00mntrRGB X\ +YZ \x07\xce\x00\x02\x00\x09\x00\x06\x001\x00\x00a\ +cspMSFT\x00\x00\x00\x00IEC s\ +RGB\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\xf6\xd6\x00\x01\x00\x00\x00\x00\xd3-HP \x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11c\ +prt\x00\x00\x01P\x00\x00\x003desc\x00\ +\x00\x01\x84\x00\x00\x00lwtpt\x00\x00\x01\xf0\x00\ +\x00\x00\x14bkpt\x00\x00\x02\x04\x00\x00\x00\x14r\ +XYZ\x00\x00\x02\x18\x00\x00\x00\x14gXYZ\x00\ +\x00\x02,\x00\x00\x00\x14bXYZ\x00\x00\x02@\x00\ +\x00\x00\x14dmnd\x00\x00\x02T\x00\x00\x00pd\ +mdd\x00\x00\x02\xc4\x00\x00\x00\x88vued\x00\ +\x00\x03L\x00\x00\x00\x86view\x00\x00\x03\xd4\x00\ +\x00\x00$lumi\x00\x00\x03\xf8\x00\x00\x00\x14m\ +eas\x00\x00\x04\x0c\x00\x00\x00$tech\x00\ +\x00\x040\x00\x00\x00\x0crTRC\x00\x00\x04<\x00\ +\x00\x08\x0cgTRC\x00\x00\x04<\x00\x00\x08\x0cb\ +TRC\x00\x00\x04<\x00\x00\x08\x0ctext\x00\ +\x00\x00\x00Copyright (c)\ + 1998 Hewlett-Pa\ +ckard Company\x00\x00d\ +esc\x00\x00\x00\x00\x00\x00\x00\x12sRGB \ +IEC61966-2.1\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x12sRGB IEC\ +61966-2.1\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00XYZ \x00\ +\x00\x00\x00\x00\x00\xf3Q\x00\x01\x00\x00\x00\x01\x16\xccX\ +YZ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00XYZ \x00\x00\x00\x00\x00\x00o\xa2\x00\ +\x008\xf5\x00\x00\x03\x90XYZ \x00\x00\x00\x00\x00\ +\x00b\x99\x00\x00\xb7\x85\x00\x00\x18\xdaXYZ \x00\ +\x00\x00\x00\x00\x00$\xa0\x00\x00\x0f\x84\x00\x00\xb6\xcfd\ +esc\x00\x00\x00\x00\x00\x00\x00\x16IEC h\ +ttp://www.iec.ch\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x16IEC \ +http://www.iec.c\ +h\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\ +esc\x00\x00\x00\x00\x00\x00\x00.IEC 6\ +1966-2.1 Default\ + RGB colour spac\ +e - sRGB\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00.IEC 61966-2.\ +1 Default RGB co\ +lour space - sRG\ +B\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00desc\x00\x00\x00\x00\x00\ +\x00\x00,Reference Vie\ +wing Condition i\ +n IEC61966-2.1\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00,Refere\ +nce Viewing Cond\ +ition in IEC6196\ +6-2.1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00v\ +iew\x00\x00\x00\x00\x00\x13\xa4\xfe\x00\x14_.\x00\ +\x10\xcf\x14\x00\x03\xed\xcc\x00\x04\x13\x0b\x00\x03\x5c\x9e\x00\ +\x00\x00\x01XYZ \x00\x00\x00\x00\x00L\x09V\x00\ +P\x00\x00\x00W\x1f\xe7meas\x00\x00\x00\x00\x00\ +\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x02\x8f\x00\x00\x00\x02sig \x00\ +\x00\x00\x00CRT curv\x00\x00\x00\x00\x00\ +\x00\x04\x00\x00\x00\x00\x05\x00\x0a\x00\x0f\x00\x14\x00\x19\x00\ +\x1e\x00#\x00(\x00-\x002\x007\x00;\x00@\x00\ +E\x00J\x00O\x00T\x00Y\x00^\x00c\x00h\x00\ +m\x00r\x00w\x00|\x00\x81\x00\x86\x00\x8b\x00\x90\x00\ +\x95\x00\x9a\x00\x9f\x00\xa4\x00\xa9\x00\xae\x00\xb2\x00\xb7\x00\ +\xbc\x00\xc1\x00\xc6\x00\xcb\x00\xd0\x00\xd5\x00\xdb\x00\xe0\x00\ +\xe5\x00\xeb\x00\xf0\x00\xf6\x00\xfb\x01\x01\x01\x07\x01\x0d\x01\ +\x13\x01\x19\x01\x1f\x01%\x01+\x012\x018\x01>\x01\ +E\x01L\x01R\x01Y\x01`\x01g\x01n\x01u\x01\ +|\x01\x83\x01\x8b\x01\x92\x01\x9a\x01\xa1\x01\xa9\x01\xb1\x01\ +\xb9\x01\xc1\x01\xc9\x01\xd1\x01\xd9\x01\xe1\x01\xe9\x01\xf2\x01\ +\xfa\x02\x03\x02\x0c\x02\x14\x02\x1d\x02&\x02/\x028\x02\ +A\x02K\x02T\x02]\x02g\x02q\x02z\x02\x84\x02\ +\x8e\x02\x98\x02\xa2\x02\xac\x02\xb6\x02\xc1\x02\xcb\x02\xd5\x02\ +\xe0\x02\xeb\x02\xf5\x03\x00\x03\x0b\x03\x16\x03!\x03-\x03\ +8\x03C\x03O\x03Z\x03f\x03r\x03~\x03\x8a\x03\ +\x96\x03\xa2\x03\xae\x03\xba\x03\xc7\x03\xd3\x03\xe0\x03\xec\x03\ +\xf9\x04\x06\x04\x13\x04 \x04-\x04;\x04H\x04U\x04\ +c\x04q\x04~\x04\x8c\x04\x9a\x04\xa8\x04\xb6\x04\xc4\x04\ +\xd3\x04\xe1\x04\xf0\x04\xfe\x05\x0d\x05\x1c\x05+\x05:\x05\ +I\x05X\x05g\x05w\x05\x86\x05\x96\x05\xa6\x05\xb5\x05\ +\xc5\x05\xd5\x05\xe5\x05\xf6\x06\x06\x06\x16\x06'\x067\x06\ +H\x06Y\x06j\x06{\x06\x8c\x06\x9d\x06\xaf\x06\xc0\x06\ +\xd1\x06\xe3\x06\xf5\x07\x07\x07\x19\x07+\x07=\x07O\x07\ +a\x07t\x07\x86\x07\x99\x07\xac\x07\xbf\x07\xd2\x07\xe5\x07\ +\xf8\x08\x0b\x08\x1f\x082\x08F\x08Z\x08n\x08\x82\x08\ +\x96\x08\xaa\x08\xbe\x08\xd2\x08\xe7\x08\xfb\x09\x10\x09%\x09\ +:\x09O\x09d\x09y\x09\x8f\x09\xa4\x09\xba\x09\xcf\x09\ +\xe5\x09\xfb\x0a\x11\x0a'\x0a=\x0aT\x0aj\x0a\x81\x0a\ +\x98\x0a\xae\x0a\xc5\x0a\xdc\x0a\xf3\x0b\x0b\x0b\x22\x0b9\x0b\ +Q\x0bi\x0b\x80\x0b\x98\x0b\xb0\x0b\xc8\x0b\xe1\x0b\xf9\x0c\ +\x12\x0c*\x0cC\x0c\x5c\x0cu\x0c\x8e\x0c\xa7\x0c\xc0\x0c\ +\xd9\x0c\xf3\x0d\x0d\x0d&\x0d@\x0dZ\x0dt\x0d\x8e\x0d\ +\xa9\x0d\xc3\x0d\xde\x0d\xf8\x0e\x13\x0e.\x0eI\x0ed\x0e\ +\x7f\x0e\x9b\x0e\xb6\x0e\xd2\x0e\xee\x0f\x09\x0f%\x0fA\x0f\ +^\x0fz\x0f\x96\x0f\xb3\x0f\xcf\x0f\xec\x10\x09\x10&\x10\ +C\x10a\x10~\x10\x9b\x10\xb9\x10\xd7\x10\xf5\x11\x13\x11\ +1\x11O\x11m\x11\x8c\x11\xaa\x11\xc9\x11\xe8\x12\x07\x12\ +&\x12E\x12d\x12\x84\x12\xa3\x12\xc3\x12\xe3\x13\x03\x13\ +#\x13C\x13c\x13\x83\x13\xa4\x13\xc5\x13\xe5\x14\x06\x14\ +'\x14I\x14j\x14\x8b\x14\xad\x14\xce\x14\xf0\x15\x12\x15\ +4\x15V\x15x\x15\x9b\x15\xbd\x15\xe0\x16\x03\x16&\x16\ +I\x16l\x16\x8f\x16\xb2\x16\xd6\x16\xfa\x17\x1d\x17A\x17\ +e\x17\x89\x17\xae\x17\xd2\x17\xf7\x18\x1b\x18@\x18e\x18\ +\x8a\x18\xaf\x18\xd5\x18\xfa\x19 \x19E\x19k\x19\x91\x19\ +\xb7\x19\xdd\x1a\x04\x1a*\x1aQ\x1aw\x1a\x9e\x1a\xc5\x1a\ +\xec\x1b\x14\x1b;\x1bc\x1b\x8a\x1b\xb2\x1b\xda\x1c\x02\x1c\ +*\x1cR\x1c{\x1c\xa3\x1c\xcc\x1c\xf5\x1d\x1e\x1dG\x1d\ +p\x1d\x99\x1d\xc3\x1d\xec\x1e\x16\x1e@\x1ej\x1e\x94\x1e\ +\xbe\x1e\xe9\x1f\x13\x1f>\x1fi\x1f\x94\x1f\xbf\x1f\xea \ +\x15 A l \x98 \xc4 \xf0!\x1c!H!\ +u!\xa1!\xce!\xfb\x22'\x22U\x22\x82\x22\xaf\x22\ +\xdd#\x0a#8#f#\x94#\xc2#\xf0$\x1f$\ +M$|$\xab$\xda%\x09%8%h%\x97%\ +\xc7%\xf7&'&W&\x87&\xb7&\xe8'\x18'\ +I'z'\xab'\xdc(\x0d(?(q(\xa2(\ +\xd4)\x06)8)k)\x9d)\xd0*\x02*5*\ +h*\x9b*\xcf+\x02+6+i+\x9d+\xd1,\ +\x05,9,n,\xa2,\xd7-\x0c-A-v-\ +\xab-\xe1.\x16.L.\x82.\xb7.\xee/$/\ +Z/\x91/\xc7/\xfe050l0\xa40\xdb1\ +\x121J1\x821\xba1\xf22*2c2\x9b2\ +\xd43\x0d3F3\x7f3\xb83\xf14+4e4\ +\x9e4\xd85\x135M5\x875\xc25\xfd676\ +r6\xae6\xe97$7`7\x9c7\xd78\x148\ +P8\x8c8\xc89\x059B9\x7f9\xbc9\xf9:\ +6:t:\xb2:\xef;-;k;\xaa;\xe8<\ +'\ + >`>\xa0>\xe0?!?a?\xa2?\xe2@\ +#@d@\xa6@\xe7A)AjA\xacA\xeeB\ +0BrB\xb5B\xf7C:C}C\xc0D\x03D\ +GD\x8aD\xceE\x12EUE\x9aE\xdeF\x22F\ +gF\xabF\xf0G5G{G\xc0H\x05HKH\ +\x91H\xd7I\x1dIcI\xa9I\xf0J7J}J\ +\xc4K\x0cKSK\x9aK\xe2L*LrL\xbaM\ +\x02MJM\x93M\xdcN%NnN\xb7O\x00O\ +IO\x93O\xddP'PqP\xbbQ\x06QPQ\ +\x9bQ\xe6R1R|R\xc7S\x13S_S\xaaS\ +\xf6TBT\x8fT\xdbU(UuU\xc2V\x0fV\ +\x5cV\xa9V\xf7WDW\x92W\xe0X/X}X\ +\xcbY\x1aYiY\xb8Z\x07ZVZ\xa6Z\xf5[\ +E[\x95[\xe5\x5c5\x5c\x86\x5c\xd6]']x]\ +\xc9^\x1a^l^\xbd_\x0f_a_\xb3`\x05`\ +W`\xaa`\xfcaOa\xa2a\xf5bIb\x9cb\ +\xf0cCc\x97c\xebd@d\x94d\xe9e=e\ +\x92e\xe7f=f\x92f\xe8g=g\x93g\xe9h\ +?h\x96h\xeciCi\x9ai\xf1jHj\x9fj\ +\xf7kOk\xa7k\xfflWl\xafm\x08m`m\ +\xb9n\x12nkn\xc4o\x1eoxo\xd1p+p\ +\x86p\xe0q:q\x95q\xf0rKr\xa6s\x01s\ +]s\xb8t\x14tpt\xccu(u\x85u\xe1v\ +>v\x9bv\xf8wVw\xb3x\x11xnx\xccy\ +*y\x89y\xe7zFz\xa5{\x04{c{\xc2|\ +!|\x81|\xe1}A}\xa1~\x01~b~\xc2\x7f\ +#\x7f\x84\x7f\xe5\x80G\x80\xa8\x81\x0a\x81k\x81\xcd\x82\ +0\x82\x92\x82\xf4\x83W\x83\xba\x84\x1d\x84\x80\x84\xe3\x85\ +G\x85\xab\x86\x0e\x86r\x86\xd7\x87;\x87\x9f\x88\x04\x88\ +i\x88\xce\x893\x89\x99\x89\xfe\x8ad\x8a\xca\x8b0\x8b\ +\x96\x8b\xfc\x8cc\x8c\xca\x8d1\x8d\x98\x8d\xff\x8ef\x8e\ +\xce\x8f6\x8f\x9e\x90\x06\x90n\x90\xd6\x91?\x91\xa8\x92\ +\x11\x92z\x92\xe3\x93M\x93\xb6\x94 \x94\x8a\x94\xf4\x95\ +_\x95\xc9\x964\x96\x9f\x97\x0a\x97u\x97\xe0\x98L\x98\ +\xb8\x99$\x99\x90\x99\xfc\x9ah\x9a\xd5\x9bB\x9b\xaf\x9c\ +\x1c\x9c\x89\x9c\xf7\x9dd\x9d\xd2\x9e@\x9e\xae\x9f\x1d\x9f\ +\x8b\x9f\xfa\xa0i\xa0\xd8\xa1G\xa1\xb6\xa2&\xa2\x96\xa3\ +\x06\xa3v\xa3\xe6\xa4V\xa4\xc7\xa58\xa5\xa9\xa6\x1a\xa6\ +\x8b\xa6\xfd\xa7n\xa7\xe0\xa8R\xa8\xc4\xa97\xa9\xa9\xaa\ +\x1c\xaa\x8f\xab\x02\xabu\xab\xe9\xac\x5c\xac\xd0\xadD\xad\ +\xb8\xae-\xae\xa1\xaf\x16\xaf\x8b\xb0\x00\xb0u\xb0\xea\xb1\ +`\xb1\xd6\xb2K\xb2\xc2\xb38\xb3\xae\xb4%\xb4\x9c\xb5\ +\x13\xb5\x8a\xb6\x01\xb6y\xb6\xf0\xb7h\xb7\xe0\xb8Y\xb8\ +\xd1\xb9J\xb9\xc2\xba;\xba\xb5\xbb.\xbb\xa7\xbc!\xbc\ +\x9b\xbd\x15\xbd\x8f\xbe\x0a\xbe\x84\xbe\xff\xbfz\xbf\xf5\xc0\ +p\xc0\xec\xc1g\xc1\xe3\xc2_\xc2\xdb\xc3X\xc3\xd4\xc4\ +Q\xc4\xce\xc5K\xc5\xc8\xc6F\xc6\xc3\xc7A\xc7\xbf\xc8\ +=\xc8\xbc\xc9:\xc9\xb9\xca8\xca\xb7\xcb6\xcb\xb6\xcc\ +5\xcc\xb5\xcd5\xcd\xb5\xce6\xce\xb6\xcf7\xcf\xb8\xd0\ +9\xd0\xba\xd1<\xd1\xbe\xd2?\xd2\xc1\xd3D\xd3\xc6\xd4\ +I\xd4\xcb\xd5N\xd5\xd1\xd6U\xd6\xd8\xd7\x5c\xd7\xe0\xd8\ +d\xd8\xe8\xd9l\xd9\xf1\xdav\xda\xfb\xdb\x80\xdc\x05\xdc\ +\x8a\xdd\x10\xdd\x96\xde\x1c\xde\xa2\xdf)\xdf\xaf\xe06\xe0\ +\xbd\xe1D\xe1\xcc\xe2S\xe2\xdb\xe3c\xe3\xeb\xe4s\xe4\ +\xfc\xe5\x84\xe6\x0d\xe6\x96\xe7\x1f\xe7\xa9\xe82\xe8\xbc\xe9\ +F\xe9\xd0\xea[\xea\xe5\xebp\xeb\xfb\xec\x86\xed\x11\xed\ +\x9c\xee(\xee\xb4\xef@\xef\xcc\xf0X\xf0\xe5\xf1r\xf1\ +\xff\xf2\x8c\xf3\x19\xf3\xa7\xf44\xf4\xc2\xf5P\xf5\xde\xf6\ +m\xf6\xfb\xf7\x8a\xf8\x19\xf8\xa8\xf98\xf9\xc7\xfaW\xfa\ +\xe7\xfbw\xfc\x07\xfc\x98\xfd)\xfd\xba\xfeK\xfe\xdc\xff\ +m\xff\xff\ +\x00\x00\x89\xf8\ +I\ +I*\x00\x08\x00\x00\x00\x18\x00\xfe\x00\x04\x00\x01\x00\x00\ +\x00\x00\x00\x00\x00\x00\x01\x03\x00\x01\x00\x00\x00`\x00\x00\ +\x00\x01\x01\x03\x00\x01\x00\x00\x00`\x00\x00\x00\x02\x01\x03\ +\x00\x04\x00\x00\x00.\x01\x00\x00\x03\x01\x03\x00\x01\x00\x00\ +\x00\x05\x00\x00\x00\x06\x01\x03\x00\x01\x00\x00\x00\x02\x00\x00\ +\x00\x11\x01\x04\x00\x01\x00\x00\x00\xfcS\x00\x00\x12\x01\x03\ +\x00\x01\x00\x00\x00\x01\x00\x00\x00\x15\x01\x03\x00\x01\x00\x00\ +\x00\x04\x00\x00\x00\x16\x01\x03\x00\x01\x00\x00\x00`\x00\x00\ +\x00\x17\x01\x04\x00\x01\x00\x00\x00\xf9\x12\x00\x00\x1a\x01\x05\ +\x00\x01\x00\x00\x006\x01\x00\x00\x1b\x01\x05\x00\x01\x00\x00\ +\x00>\x01\x00\x00\x1c\x01\x03\x00\x01\x00\x00\x00\x01\x00\x00\ +\x00(\x01\x03\x00\x01\x00\x00\x00\x02\x00\x00\x001\x01\x02\ +\x00\x22\x00\x00\x00F\x01\x00\x002\x01\x02\x00\x14\x00\x00\ +\x00h\x01\x00\x00=\x01\x03\x00\x01\x00\x00\x00\x02\x00\x00\ +\x00R\x01\x03\x00\x01\x00\x00\x00\x01\x00\x00\x00\xbc\x02\x01\ +\x00\xf68\x00\x00|\x01\x00\x00I\x86\x01\x00B\x0d\x00\ +\x00r:\x00\x00i\x87\x04\x00\x01\x00\x00\x00\xf8f\x00\ +\x00s\x87\x07\x00H\x0c\x00\x00\xb4G\x00\x00\x5c\x93\x07\ +\x00\xd0\x22\x00\x00$g\x00\x00\x00\x00\x00\x00\x08\x00\x08\ +\x00\x08\x00\x08\x00\x00\xf9\x15\x00\x10'\x00\x00\x00\xf9\x15\ +\x00\x10'\x00\x00Adobe Photo\ +shop CC 2017 (Wi\ +ndows)\x002017:04:0\ +4 11:01:55\x00\ +\x0a\x0a \ + \x0a \x0a \ + paint.net \ +4.0.9\x0a \ + 2017-03-01T11:2\ +0:20-08:00\x0a \ + 2017-04-04T\ +11:01:55-07:00\x0a\ + 2017-\ +04-04T11:01:55-0\ +7:00\x0a \ + imag\ +e/tiff\x0a 3\x0a \ + sRGB IEC\ +61966-2.1\ +\x0a \x0a \ + \x0a \ + adobe:docid\ +:photoshop:6e5b1\ +c59-1960-11e7-ba\ +e7-e6e7a5cd2814<\ +/rdf:li>\x0a \ + \x0a\ + \x0a \ + xmp.iid:db7b2\ +8e8-30e9-e04f-9f\ +78-916e5c5110e6<\ +/xmpMM:InstanceI\ +D>\x0a ad\ +obe:docid:photos\ +hop:bf3203a1-196\ +0-11e7-bae7-e6e7\ +a5cd2814\x0a \ + x\ +mp.did:8f625742-\ +0048-e64f-ab3c-d\ +4b1a5a27a24\x0a \ +\x0a\ + \x0a \ + \x0a \ + created\x0a \ + \ +xmp.iid:8f6257\ +42-0048-e64f-ab3\ +c-d4b1a5a27a24\x0a \ + \ +2017-03-01T11:20\ +:20-08:00\x0a \ + Ad\ +obe Photoshop CC\ + 2017 (Windows)<\ +/stEvt:softwareA\ +gent>\x0a \ + \x0a \ + \x0a\ + \ + \ +saved\x0a \ + xmp.iid\ +:db7b28e8-30e9-e\ +04f-9f78-916e5c5\ +110e6\x0a \ + 2017-04-0\ +4T11:01:55-07:00\ +\x0a \ + \ +Adobe Photo\ +shop CC 2017 (Wi\ +ndows)\x0a \ + <\ +stEvt:changed>/<\ +/stEvt:changed>\x0a\ + <\ +/rdf:li>\x0a \ + \x0a\ + \x0a \ +\x0a \ +\x0a\x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ +\x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a\ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ +\x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a\ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ +\x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a\ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ +\x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a\ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ +\x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a\ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ +\x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a\ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ +\x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a\ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ +\x0a \ + \x0a8BIM\x04%\x00\x00\x00\x00\x00\x10\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x008BI\ +M\x04:\x00\x00\x00\x00\x00\xe5\x00\x00\x00\x10\x00\x00\x00\ +\x01\x00\x00\x00\x00\x00\x0bprintOutp\ +ut\x00\x00\x00\x05\x00\x00\x00\x00PstSbo\ +ol\x01\x00\x00\x00\x00Inteenum\x00\ +\x00\x00\x00Inte\x00\x00\x00\x00Clrm\x00\ +\x00\x00\x0fprintSixteenB\ +itbool\x00\x00\x00\x00\x0bprint\ +erNameTEXT\x00\x00\x00\x01\x00\x00\ +\x00\x00\x00\x0fprintProofSe\ +tupObjc\x00\x00\x00\x0c\x00P\x00r\x00\ +o\x00o\x00f\x00 \x00S\x00e\x00t\x00u\x00\ +p\x00\x00\x00\x00\x00\x0aproofSetu\ +p\x00\x00\x00\x01\x00\x00\x00\x00Bltnenu\ +m\x00\x00\x00\x0cbuiltinProo\ +f\x00\x00\x00\x09proofCMYK\x008\ +BIM\x04;\x00\x00\x00\x00\x02-\x00\x00\x00\x10\x00\ +\x00\x00\x01\x00\x00\x00\x00\x00\x12printOu\ +tputOptions\x00\x00\x00\x17\x00\ +\x00\x00\x00Cptnbool\x00\x00\x00\x00\x00\ +Clbrbool\x00\x00\x00\x00\x00Rgs\ +Mbool\x00\x00\x00\x00\x00CrnCbo\ +ol\x00\x00\x00\x00\x00CntCbool\x00\ +\x00\x00\x00\x00Lblsbool\x00\x00\x00\x00\ +\x00Ngtvbool\x00\x00\x00\x00\x00Em\ +lDbool\x00\x00\x00\x00\x00Intrb\ +ool\x00\x00\x00\x00\x00BckgObjc\ +\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00RGBC\x00\x00\ +\x00\x03\x00\x00\x00\x00Rd doub@o\ +\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00Grn do\ +ub@o\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00Bl\ + doub@o\xe0\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00BrdTUntF#Rlt\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00Bld Un\ +tF#Rlt\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00RsltUntF#Pxl@b\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0avector\ +Databool\x01\x00\x00\x00\x00PgP\ +senum\x00\x00\x00\x00PgPs\x00\x00\x00\ +\x00PgPC\x00\x00\x00\x00LeftUnt\ +F#Rlt\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00Top UntF#Rlt\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00Scl Unt\ +F#Prc@Y\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x10cropWhenPrintin\ +gbool\x00\x00\x00\x00\x0ecropRe\ +ctBottomlong\x00\x00\x00\x00\ +\x00\x00\x00\x0ccropRectLeft\ +long\x00\x00\x00\x00\x00\x00\x00\x0dcrop\ +RectRightlong\x00\x00\x00\ +\x00\x00\x00\x00\x0bcropRectTop\ +long\x00\x00\x00\x00\x008BIM\x03\xed\x00\ +\x00\x00\x00\x00\x10\x00\x90\x00\x00\x00\x01\x00\x01\x00\x90\x00\ +\x00\x00\x01\x00\x018BIM\x04&\x00\x00\x00\x00\x00\ +\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00?\x80\x00\x008\ +BIM\x03\xee\x00\x00\x00\x00\x00\x0d\x0cTran\ +sparency\x008BIM\x04\x15\x00\ +\x00\x00\x00\x00\x1e\x00\x00\x00\x0d\x00T\x00r\x00a\x00\ +n\x00s\x00p\x00a\x00r\x00e\x00n\x00c\x00\ +y\x00\x008BIM\x045\x00\x00\x00\x00\x00\x11\x00\ +\x00\x00\x01\x00\x00\xff\xff\x00\x00\x00\x00\x00\x00\x00d\x01\ +\x008BIM\x04\x1d\x00\x00\x00\x00\x00\x04\x00\x00\x00\ +\x008BIM\x04\x0d\x00\x00\x00\x00\x00\x04\x00\x00\x00\ +\x1e8BIM\x04\x19\x00\x00\x00\x00\x00\x04\x00\x00\x00\ +\x1e8BIM\x03\xf3\x00\x00\x00\x00\x00\x09\x00\x00\x00\ +\x00\x00\x00\x00\x00\x01\x008BIM'\x10\x00\x00\x00\ +\x00\x00\x0a\x00\x01\x00\x00\x00\x00\x00\x00\x00\x018BI\ +M\x03\xf5\x00\x00\x00\x00\x00H\x00/ff\x00\x01\x00\ +lff\x00\x06\x00\x00\x00\x00\x00\x01\x00/ff\x00\ +\x01\x00\xa1\x99\x9a\x00\x06\x00\x00\x00\x00\x00\x01\x002\x00\ +\x00\x00\x01\x00Z\x00\x00\x00\x06\x00\x00\x00\x00\x00\x01\x00\ +5\x00\x00\x00\x01\x00-\x00\x00\x00\x06\x00\x00\x00\x00\x00\ +\x018BIM\x03\xf8\x00\x00\x00\x00\x00p\x00\x00\xff\ +\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\x03\xe8\x00\x00\x00\x00\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\x03\xe8\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x03\xe8\x00\ +\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\xff\xff\x03\xe8\x00\x008BI\ +M\x04\x00\x00\x00\x00\x00\x00\x02\x00\x018BIM\x04\ +\x02\x00\x00\x00\x00\x00\x04\x00\x00\x00\x008BIM\x04\ +0\x00\x00\x00\x00\x00\x02\x01\x018BIM\x04-\x00\ +\x00\x00\x00\x00\x06\x00\x01\x00\x00\x00\x048BIM\x04\ +\x08\x00\x00\x00\x00\x00\x10\x00\x00\x00\x01\x00\x00\x02@\x00\ +\x00\x02@\x00\x00\x00\x008BIM\x04\x1e\x00\x00\x00\ +\x00\x00\x04\x00\x00\x00\x008BIM\x04\x1a\x00\x00\x00\ +\x00\x035\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00`\x00\x00\x00`\x00\x00\x00\x00\x00\x00\x00\x01\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00`\x00\ +\x00\x00`\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x01\x00\x00\x00\x00\ +\x00\x00null\x00\x00\x00\x02\x00\x00\x00\x06bo\ +undsObjc\x00\x00\x00\x01\x00\x00\x00\x00\ +\x00\x00Rct1\x00\x00\x00\x04\x00\x00\x00\x00To\ +p long\x00\x00\x00\x00\x00\x00\x00\x00Le\ +ftlong\x00\x00\x00\x00\x00\x00\x00\x00Bt\ +omlong\x00\x00\x00`\x00\x00\x00\x00Rg\ +htlong\x00\x00\x00`\x00\x00\x00\x06sl\ +icesVlLs\x00\x00\x00\x01Objc\ +\x00\x00\x00\x01\x00\x00\x00\x00\x00\x05slice\x00\ +\x00\x00\x12\x00\x00\x00\x07sliceIDlo\ +ng\x00\x00\x00\x00\x00\x00\x00\x07groupI\ +Dlong\x00\x00\x00\x00\x00\x00\x00\x06ori\ +ginenum\x00\x00\x00\x0cESlic\ +eOrigin\x00\x00\x00\x0dautoG\ +enerated\x00\x00\x00\x00Type\ +enum\x00\x00\x00\x0aESliceTy\ +pe\x00\x00\x00\x00Img \x00\x00\x00\x06bo\ +undsObjc\x00\x00\x00\x01\x00\x00\x00\x00\ +\x00\x00Rct1\x00\x00\x00\x04\x00\x00\x00\x00To\ +p long\x00\x00\x00\x00\x00\x00\x00\x00Le\ +ftlong\x00\x00\x00\x00\x00\x00\x00\x00Bt\ +omlong\x00\x00\x00`\x00\x00\x00\x00Rg\ +htlong\x00\x00\x00`\x00\x00\x00\x03ur\ +lTEXT\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00n\ +ullTEXT\x00\x00\x00\x01\x00\x00\x00\x00\x00\ +\x00MsgeTEXT\x00\x00\x00\x01\x00\x00\x00\ +\x00\x00\x06altTagTEXT\x00\x00\x00\ +\x01\x00\x00\x00\x00\x00\x0ecellTextI\ +sHTMLbool\x01\x00\x00\x00\x08ce\ +llTextTEXT\x00\x00\x00\x01\x00\x00\ +\x00\x00\x00\x09horzAlignenu\ +m\x00\x00\x00\x0fESliceHorzA\ +lign\x00\x00\x00\x07default\x00\ +\x00\x00\x09vertAlignenum\ +\x00\x00\x00\x0fESliceVertAl\ +ign\x00\x00\x00\x07default\x00\x00\ +\x00\x0bbgColorTypeenu\ +m\x00\x00\x00\x11ESliceBGCol\ +orType\x00\x00\x00\x00None\x00\x00\ +\x00\x09topOutsetlong\x00\ +\x00\x00\x00\x00\x00\x00\x0aleftOutse\ +tlong\x00\x00\x00\x00\x00\x00\x00\x0cbot\ +tomOutsetlong\x00\x00\x00\ +\x00\x00\x00\x00\x0brightOutset\ +long\x00\x00\x00\x00\x008BIM\x04(\x00\ +\x00\x00\x00\x00\x0c\x00\x00\x00\x02?\xf0\x00\x00\x00\x00\x00\ +\x008BIM\x04\x14\x00\x00\x00\x00\x00\x04\x00\x00\x00\ +\x048BIM\x04\x0c\x00\x00\x00\x00\x03\xeb\x00\x00\x00\ +\x01\x00\x00\x000\x00\x00\x000\x00\x00\x00\x90\x00\x00\x1b\ +\x00\x00\x00\x03\xcf\x00\x18\x00\x01\xff\xd8\xff\xed\x00\x0cA\ +dobe_CM\x00\x01\xff\xee\x00\x0eAdo\ +be\x00d\x80\x00\x00\x00\x01\xff\xdb\x00\x84\x00\x0c\x08\ +\x08\x08\x09\x08\x0c\x09\x09\x0c\x11\x0b\x0a\x0b\x11\x15\x0f\x0c\ +\x0c\x0f\x15\x18\x13\x13\x15\x13\x13\x18\x11\x0c\x0c\x0c\x0c\x0c\ +\x0c\x11\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\ +\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x01\x0d\ +\x0b\x0b\x0d\x0e\x0d\x10\x0e\x0e\x10\x14\x0e\x0e\x0e\x14\x14\x0e\ +\x0e\x0e\x0e\x14\x11\x0c\x0c\x0c\x0c\x0c\x11\x11\x0c\x0c\x0c\x0c\ +\x0c\x0c\x11\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\ +\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\xff\ +\xc0\x00\x11\x08\x000\x000\x03\x01\x22\x00\x02\x11\x01\x03\ +\x11\x01\xff\xdd\x00\x04\x00\x03\xff\xc4\x01?\x00\x00\x01\x05\ +\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x03\x00\x01\ +\x02\x04\x05\x06\x07\x08\x09\x0a\x0b\x01\x00\x01\x05\x01\x01\x01\ +\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x02\x03\x04\x05\ +\x06\x07\x08\x09\x0a\x0b\x10\x00\x01\x04\x01\x03\x02\x04\x02\x05\ +\x07\x06\x08\x05\x03\x0c3\x01\x00\x02\x11\x03\x04!\x121\ +\x05AQa\x13\x22q\x812\x06\x14\x91\xa1\xb1B#\ +$\x15R\xc1b34r\x82\xd1C\x07%\x92S\xf0\ +\xe1\xf1cs5\x16\xa2\xb2\x83&D\x93TdE\xc2\ +\xa3t6\x17\xd2U\xe2e\xf2\xb3\x84\xc3\xd3u\xe3\xf3\ +F'\x94\xa4\x85\xb4\x95\xc4\xd4\xe4\xf4\xa5\xb5\xc5\xd5\xe5\ +\xf5Vfv\x86\x96\xa6\xb6\xc6\xd6\xe6\xf67GWg\ +w\x87\x97\xa7\xb7\xc7\xd7\xe7\xf7\x11\x00\x02\x02\x01\x02\x04\ +\x04\x03\x04\x05\x06\x07\x07\x06\x055\x01\x00\x02\x11\x03!\ +1\x12\x04AQaq\x22\x13\x052\x81\x91\x14\xa1\xb1\ +B#\xc1R\xd1\xf03$b\xe1r\x82\x92CS\x15\ +cs4\xf1%\x06\x16\xa2\xb2\x83\x07&5\xc2\xd2D\ +\x93T\xa3\x17dEU6te\xe2\xf2\xb3\x84\xc3\xd3\ +u\xe3\xf3F\x94\xa4\x85\xb4\x95\xc4\xd4\xe4\xf4\xa5\xb5\xc5\ +\xd5\xe5\xf5Vfv\x86\x96\xa6\xb6\xc6\xd6\xe6\xf6'7\ +GWgw\x87\x97\xa7\xb7\xc7\xff\xda\x00\x0c\x03\x01\x00\ +\x02\x11\x03\x11\x00?\x00\xf4<\xdc\xcc\x96d\x9a\xa9;\ +@\x80\x00\x00\x92O\xc6P\xfd~\xab\xe0\xff\x00\xfbl\ +\x7f\xe4R\xc9\xff\x00\x95\x1b\xfdz\xff\x00\xef\xabU\xce\ +\x0dis\xb4\x00I>A%9^\xbfU\xf0\x7f\xfd\ +\xb6?\xf2)z\xfdW\xc1\xff\x00\xf6\xd8\xff\x00\xc8\xa2\ +UU\xf9\xe0\xdde\x8e\xaa\x92}\x95\xb7\xc0x\xa7{\ +o\xe9\xeem\x82\xc3n9 =\xae\xd4\x89\xee\x12R\ +/_\xaa\xf8?\xfc\xc1\xff\x00\x91D\xc0\xcc\xc8\xb3#\ +\xd2\xb4\xee\x04\x1e@\x04\x11\xfdU\xa4\xb20\x7f\xe5\x03\ +\xff\x00\x5c\xfc\xa9)\xff\xd0\xef\xf2\x7f\xe5F\xff\x00^\ +\xbf\xfb\xea\xb9\x9f\x7f\xa7W\xa6\x1a\x5c\xfb\x81c@\xf3\ +\x11\xfcU<\x9f\xf9Q\xbf\xd7\xaf\xfe\xfa\xacu\x0f\xe9\ +\x18\x9f\xf1\x9f\xc5\x89)\x1e>NU\x14\xb6\xaf\xb2\xbd\ +\xdbg\xdd\xa8\xe4\xcf\xee\xa8\xe5]\x95\x93I\xa8\xe2\xbd\ +\x92A\x9dO\x1f\xd9\x0a\xdfP\xb6\xea\xb1\xf7\xd3\xa1\x90\ +\x1c\xee`x\xa9aYu\x98\xed}\xdfH\xcc\x1e$\ +~k\x92R\xd8y\x02\xfa\xa7ik\x98v\xb8\x1f\x10\ +\xa8`\xff\x00\xca\x07\xfe\xb9\xf9U\x9e\x97\xf4.\xff\x00\ +\x8d*\xb6\x0f\xfc\xa0\x7f\xeb\x9f\x95%?\xff\xd1\xef\xf2\ +\x7f\xe5F\xff\x00^\xbf\xfb\xea?R;,\xc6\xb4\x83\ +\xb1\x8f\x97\x11\xf1i\xff\x00\xbe\xa8f\xe1d\xbf$\xdb\ +P\x90b\x0c\xc1\x04!\xfd\x9b\xaa~\xf3\xff\x00\xed\xcf\ +\xfc\xc9%'\xb7\xa8\xe1[[\xabxyk\x84\x1d\x08\ +N\xce\xa7\x86\xc65\x8d\x0f\x0dh\x00\x0d\xa7\x80\xab\xfd\ +\x9b\xaa~\xf3\xff\x00\xed\xcf\xf6\xa5\xf6n\xa9\xfb\xcf\xff\ +\x00\xb7?\xda\x92\x9b\x1d(\x1fJ\xd7A\x0du\x84\xb4\ +\x9e\xe1V\xc1\xff\x00\x94\x0f\xc6\xcf\xca\x9f\xec\xddS\xf7\ +\x9f\xff\x00n\x7f\xe6H\xb88Y\x15\xdf\xea\xda\x03@\ +\x04s$\x92\x92\x9f\xff\xd9\x008BIM\x04!\x00\ +\x00\x00\x00\x00]\x00\x00\x00\x01\x01\x00\x00\x00\x0f\x00A\ +\x00d\x00o\x00b\x00e\x00 \x00P\x00h\x00o\ +\x00t\x00o\x00s\x00h\x00o\x00p\x00\x00\x00\x17\ +\x00A\x00d\x00o\x00b\x00e\x00 \x00P\x00h\ +\x00o\x00t\x00o\x00s\x00h\x00o\x00p\x00 \ +\x00C\x00C\x00 \x002\x000\x001\x007\x00\x00\ +\x00\x01\x00\x00\x00\x0cHLino\x02\x10\x00\x00m\ +ntrRGB XYZ \x07\xce\x00\x02\x00\ +\x09\x00\x06\x001\x00\x00acspMSFT\x00\ +\x00\x00\x00IEC sRGB\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf6\xd6\x00\x01\x00\x00\x00\ +\x00\xd3-HP \x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x11cprt\x00\x00\x01P\x00\ +\x00\x003desc\x00\x00\x01\x84\x00\x00\x00lw\ +tpt\x00\x00\x01\xf0\x00\x00\x00\x14bkpt\x00\ +\x00\x02\x04\x00\x00\x00\x14rXYZ\x00\x00\x02\x18\x00\ +\x00\x00\x14gXYZ\x00\x00\x02,\x00\x00\x00\x14b\ +XYZ\x00\x00\x02@\x00\x00\x00\x14dmnd\x00\ +\x00\x02T\x00\x00\x00pdmdd\x00\x00\x02\xc4\x00\ +\x00\x00\x88vued\x00\x00\x03L\x00\x00\x00\x86v\ +iew\x00\x00\x03\xd4\x00\x00\x00$lumi\x00\ +\x00\x03\xf8\x00\x00\x00\x14meas\x00\x00\x04\x0c\x00\ +\x00\x00$tech\x00\x00\x040\x00\x00\x00\x0cr\ +TRC\x00\x00\x04<\x00\x00\x08\x0cgTRC\x00\ +\x00\x04<\x00\x00\x08\x0cbTRC\x00\x00\x04<\x00\ +\x00\x08\x0ctext\x00\x00\x00\x00Copyr\ +ight (c) 1998 He\ +wlett-Packard Co\ +mpany\x00\x00desc\x00\x00\x00\x00\x00\ +\x00\x00\x12sRGB IEC61966\ +-2.1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x12\ +sRGB IEC61966-2.\ +1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00XYZ \x00\x00\x00\x00\x00\x00\xf3Q\x00\ +\x01\x00\x00\x00\x01\x16\xccXYZ \x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00XYZ \x00\ +\x00\x00\x00\x00\x00o\xa2\x00\x008\xf5\x00\x00\x03\x90X\ +YZ \x00\x00\x00\x00\x00\x00b\x99\x00\x00\xb7\x85\x00\ +\x00\x18\xdaXYZ \x00\x00\x00\x00\x00\x00$\xa0\x00\ +\x00\x0f\x84\x00\x00\xb6\xcfdesc\x00\x00\x00\x00\x00\ +\x00\x00\x16IEC http://ww\ +w.iec.ch\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x16IEC http://w\ +ww.iec.ch\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00desc\x00\x00\x00\x00\x00\ +\x00\x00.IEC 61966-2.1\ + Default RGB col\ +our space - sRGB\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00.IEC \ +61966-2.1 Defaul\ +t RGB colour spa\ +ce - sRGB\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\ +esc\x00\x00\x00\x00\x00\x00\x00,Refer\ +ence Viewing Con\ +dition in IEC619\ +66-2.1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00,Reference View\ +ing Condition in\ + IEC61966-2.1\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00view\x00\x00\x00\x00\x00\ +\x13\xa4\xfe\x00\x14_.\x00\x10\xcf\x14\x00\x03\xed\xcc\x00\ +\x04\x13\x0b\x00\x03\x5c\x9e\x00\x00\x00\x01XYZ \x00\ +\x00\x00\x00\x00L\x09V\x00P\x00\x00\x00W\x1f\xe7m\ +eas\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x8f\x00\ +\x00\x00\x02sig \x00\x00\x00\x00CRT c\ +urv\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x05\x00\ +\x0a\x00\x0f\x00\x14\x00\x19\x00\x1e\x00#\x00(\x00-\x00\ +2\x007\x00;\x00@\x00E\x00J\x00O\x00T\x00\ +Y\x00^\x00c\x00h\x00m\x00r\x00w\x00|\x00\ +\x81\x00\x86\x00\x8b\x00\x90\x00\x95\x00\x9a\x00\x9f\x00\xa4\x00\ +\xa9\x00\xae\x00\xb2\x00\xb7\x00\xbc\x00\xc1\x00\xc6\x00\xcb\x00\ +\xd0\x00\xd5\x00\xdb\x00\xe0\x00\xe5\x00\xeb\x00\xf0\x00\xf6\x00\ +\xfb\x01\x01\x01\x07\x01\x0d\x01\x13\x01\x19\x01\x1f\x01%\x01\ ++\x012\x018\x01>\x01E\x01L\x01R\x01Y\x01\ +`\x01g\x01n\x01u\x01|\x01\x83\x01\x8b\x01\x92\x01\ +\x9a\x01\xa1\x01\xa9\x01\xb1\x01\xb9\x01\xc1\x01\xc9\x01\xd1\x01\ +\xd9\x01\xe1\x01\xe9\x01\xf2\x01\xfa\x02\x03\x02\x0c\x02\x14\x02\ +\x1d\x02&\x02/\x028\x02A\x02K\x02T\x02]\x02\ +g\x02q\x02z\x02\x84\x02\x8e\x02\x98\x02\xa2\x02\xac\x02\ +\xb6\x02\xc1\x02\xcb\x02\xd5\x02\xe0\x02\xeb\x02\xf5\x03\x00\x03\ +\x0b\x03\x16\x03!\x03-\x038\x03C\x03O\x03Z\x03\ +f\x03r\x03~\x03\x8a\x03\x96\x03\xa2\x03\xae\x03\xba\x03\ +\xc7\x03\xd3\x03\xe0\x03\xec\x03\xf9\x04\x06\x04\x13\x04 \x04\ +-\x04;\x04H\x04U\x04c\x04q\x04~\x04\x8c\x04\ +\x9a\x04\xa8\x04\xb6\x04\xc4\x04\xd3\x04\xe1\x04\xf0\x04\xfe\x05\ +\x0d\x05\x1c\x05+\x05:\x05I\x05X\x05g\x05w\x05\ +\x86\x05\x96\x05\xa6\x05\xb5\x05\xc5\x05\xd5\x05\xe5\x05\xf6\x06\ +\x06\x06\x16\x06'\x067\x06H\x06Y\x06j\x06{\x06\ +\x8c\x06\x9d\x06\xaf\x06\xc0\x06\xd1\x06\xe3\x06\xf5\x07\x07\x07\ +\x19\x07+\x07=\x07O\x07a\x07t\x07\x86\x07\x99\x07\ +\xac\x07\xbf\x07\xd2\x07\xe5\x07\xf8\x08\x0b\x08\x1f\x082\x08\ +F\x08Z\x08n\x08\x82\x08\x96\x08\xaa\x08\xbe\x08\xd2\x08\ +\xe7\x08\xfb\x09\x10\x09%\x09:\x09O\x09d\x09y\x09\ +\x8f\x09\xa4\x09\xba\x09\xcf\x09\xe5\x09\xfb\x0a\x11\x0a'\x0a\ +=\x0aT\x0aj\x0a\x81\x0a\x98\x0a\xae\x0a\xc5\x0a\xdc\x0a\ +\xf3\x0b\x0b\x0b\x22\x0b9\x0bQ\x0bi\x0b\x80\x0b\x98\x0b\ +\xb0\x0b\xc8\x0b\xe1\x0b\xf9\x0c\x12\x0c*\x0cC\x0c\x5c\x0c\ +u\x0c\x8e\x0c\xa7\x0c\xc0\x0c\xd9\x0c\xf3\x0d\x0d\x0d&\x0d\ +@\x0dZ\x0dt\x0d\x8e\x0d\xa9\x0d\xc3\x0d\xde\x0d\xf8\x0e\ +\x13\x0e.\x0eI\x0ed\x0e\x7f\x0e\x9b\x0e\xb6\x0e\xd2\x0e\ +\xee\x0f\x09\x0f%\x0fA\x0f^\x0fz\x0f\x96\x0f\xb3\x0f\ +\xcf\x0f\xec\x10\x09\x10&\x10C\x10a\x10~\x10\x9b\x10\ +\xb9\x10\xd7\x10\xf5\x11\x13\x111\x11O\x11m\x11\x8c\x11\ +\xaa\x11\xc9\x11\xe8\x12\x07\x12&\x12E\x12d\x12\x84\x12\ +\xa3\x12\xc3\x12\xe3\x13\x03\x13#\x13C\x13c\x13\x83\x13\ +\xa4\x13\xc5\x13\xe5\x14\x06\x14'\x14I\x14j\x14\x8b\x14\ +\xad\x14\xce\x14\xf0\x15\x12\x154\x15V\x15x\x15\x9b\x15\ +\xbd\x15\xe0\x16\x03\x16&\x16I\x16l\x16\x8f\x16\xb2\x16\ +\xd6\x16\xfa\x17\x1d\x17A\x17e\x17\x89\x17\xae\x17\xd2\x17\ +\xf7\x18\x1b\x18@\x18e\x18\x8a\x18\xaf\x18\xd5\x18\xfa\x19\ + \x19E\x19k\x19\x91\x19\xb7\x19\xdd\x1a\x04\x1a*\x1a\ +Q\x1aw\x1a\x9e\x1a\xc5\x1a\xec\x1b\x14\x1b;\x1bc\x1b\ +\x8a\x1b\xb2\x1b\xda\x1c\x02\x1c*\x1cR\x1c{\x1c\xa3\x1c\ +\xcc\x1c\xf5\x1d\x1e\x1dG\x1dp\x1d\x99\x1d\xc3\x1d\xec\x1e\ +\x16\x1e@\x1ej\x1e\x94\x1e\xbe\x1e\xe9\x1f\x13\x1f>\x1f\ +i\x1f\x94\x1f\xbf\x1f\xea \x15 A l \x98 \ +\xc4 \xf0!\x1c!H!u!\xa1!\xce!\xfb\x22\ +'\x22U\x22\x82\x22\xaf\x22\xdd#\x0a#8#f#\ +\x94#\xc2#\xf0$\x1f$M$|$\xab$\xda%\ +\x09%8%h%\x97%\xc7%\xf7&'&W&\ +\x87&\xb7&\xe8'\x18'I'z'\xab'\xdc(\ +\x0d(?(q(\xa2(\xd4)\x06)8)k)\ +\x9d)\xd0*\x02*5*h*\x9b*\xcf+\x02+\ +6+i+\x9d+\xd1,\x05,9,n,\xa2,\ +\xd7-\x0c-A-v-\xab-\xe1.\x16.L.\ +\x82.\xb7.\xee/$/Z/\x91/\xc7/\xfe0\ +50l0\xa40\xdb1\x121J1\x821\xba1\ +\xf22*2c2\x9b2\xd43\x0d3F3\x7f3\ +\xb83\xf14+4e4\x9e4\xd85\x135M5\ +\x875\xc25\xfd676r6\xae6\xe97$7\ +`7\x9c7\xd78\x148P8\x8c8\xc89\x059\ +B9\x7f9\xbc9\xf9:6:t:\xb2:\xef;\ +-;k;\xaa;\xe8<' >`>\xa0>\xe0?\ +!?a?\xa2?\xe2@#@d@\xa6@\xe7A\ +)AjA\xacA\xeeB0BrB\xb5B\xf7C\ +:C}C\xc0D\x03DGD\x8aD\xceE\x12E\ +UE\x9aE\xdeF\x22FgF\xabF\xf0G5G\ +{G\xc0H\x05HKH\x91H\xd7I\x1dIcI\ +\xa9I\xf0J7J}J\xc4K\x0cKSK\x9aK\ +\xe2L*LrL\xbaM\x02MJM\x93M\xdcN\ +%NnN\xb7O\x00OIO\x93O\xddP'P\ +qP\xbbQ\x06QPQ\x9bQ\xe6R1R|R\ +\xc7S\x13S_S\xaaS\xf6TBT\x8fT\xdbU\ +(UuU\xc2V\x0fV\x5cV\xa9V\xf7WDW\ +\x92W\xe0X/X}X\xcbY\x1aYiY\xb8Z\ +\x07ZVZ\xa6Z\xf5[E[\x95[\xe5\x5c5\x5c\ +\x86\x5c\xd6]']x]\xc9^\x1a^l^\xbd_\ +\x0f_a_\xb3`\x05`W`\xaa`\xfcaOa\ +\xa2a\xf5bIb\x9cb\xf0cCc\x97c\xebd\ +@d\x94d\xe9e=e\x92e\xe7f=f\x92f\ +\xe8g=g\x93g\xe9h?h\x96h\xeciCi\ +\x9ai\xf1jHj\x9fj\xf7kOk\xa7k\xffl\ +Wl\xafm\x08m`m\xb9n\x12nkn\xc4o\ +\x1eoxo\xd1p+p\x86p\xe0q:q\x95q\ +\xf0rKr\xa6s\x01s]s\xb8t\x14tpt\ +\xccu(u\x85u\xe1v>v\x9bv\xf8wVw\ +\xb3x\x11xnx\xccy*y\x89y\xe7zFz\ +\xa5{\x04{c{\xc2|!|\x81|\xe1}A}\ +\xa1~\x01~b~\xc2\x7f#\x7f\x84\x7f\xe5\x80G\x80\ +\xa8\x81\x0a\x81k\x81\xcd\x820\x82\x92\x82\xf4\x83W\x83\ +\xba\x84\x1d\x84\x80\x84\xe3\x85G\x85\xab\x86\x0e\x86r\x86\ +\xd7\x87;\x87\x9f\x88\x04\x88i\x88\xce\x893\x89\x99\x89\ +\xfe\x8ad\x8a\xca\x8b0\x8b\x96\x8b\xfc\x8cc\x8c\xca\x8d\ +1\x8d\x98\x8d\xff\x8ef\x8e\xce\x8f6\x8f\x9e\x90\x06\x90\ +n\x90\xd6\x91?\x91\xa8\x92\x11\x92z\x92\xe3\x93M\x93\ +\xb6\x94 \x94\x8a\x94\xf4\x95_\x95\xc9\x964\x96\x9f\x97\ +\x0a\x97u\x97\xe0\x98L\x98\xb8\x99$\x99\x90\x99\xfc\x9a\ +h\x9a\xd5\x9bB\x9b\xaf\x9c\x1c\x9c\x89\x9c\xf7\x9dd\x9d\ +\xd2\x9e@\x9e\xae\x9f\x1d\x9f\x8b\x9f\xfa\xa0i\xa0\xd8\xa1\ +G\xa1\xb6\xa2&\xa2\x96\xa3\x06\xa3v\xa3\xe6\xa4V\xa4\ +\xc7\xa58\xa5\xa9\xa6\x1a\xa6\x8b\xa6\xfd\xa7n\xa7\xe0\xa8\ +R\xa8\xc4\xa97\xa9\xa9\xaa\x1c\xaa\x8f\xab\x02\xabu\xab\ +\xe9\xac\x5c\xac\xd0\xadD\xad\xb8\xae-\xae\xa1\xaf\x16\xaf\ +\x8b\xb0\x00\xb0u\xb0\xea\xb1`\xb1\xd6\xb2K\xb2\xc2\xb3\ +8\xb3\xae\xb4%\xb4\x9c\xb5\x13\xb5\x8a\xb6\x01\xb6y\xb6\ +\xf0\xb7h\xb7\xe0\xb8Y\xb8\xd1\xb9J\xb9\xc2\xba;\xba\ +\xb5\xbb.\xbb\xa7\xbc!\xbc\x9b\xbd\x15\xbd\x8f\xbe\x0a\xbe\ +\x84\xbe\xff\xbfz\xbf\xf5\xc0p\xc0\xec\xc1g\xc1\xe3\xc2\ +_\xc2\xdb\xc3X\xc3\xd4\xc4Q\xc4\xce\xc5K\xc5\xc8\xc6\ +F\xc6\xc3\xc7A\xc7\xbf\xc8=\xc8\xbc\xc9:\xc9\xb9\xca\ +8\xca\xb7\xcb6\xcb\xb6\xcc5\xcc\xb5\xcd5\xcd\xb5\xce\ +6\xce\xb6\xcf7\xcf\xb8\xd09\xd0\xba\xd1<\xd1\xbe\xd2\ +?\xd2\xc1\xd3D\xd3\xc6\xd4I\xd4\xcb\xd5N\xd5\xd1\xd6\ +U\xd6\xd8\xd7\x5c\xd7\xe0\xd8d\xd8\xe8\xd9l\xd9\xf1\xda\ +v\xda\xfb\xdb\x80\xdc\x05\xdc\x8a\xdd\x10\xdd\x96\xde\x1c\xde\ +\xa2\xdf)\xdf\xaf\xe06\xe0\xbd\xe1D\xe1\xcc\xe2S\xe2\ +\xdb\xe3c\xe3\xeb\xe4s\xe4\xfc\xe5\x84\xe6\x0d\xe6\x96\xe7\ +\x1f\xe7\xa9\xe82\xe8\xbc\xe9F\xe9\xd0\xea[\xea\xe5\xeb\ +p\xeb\xfb\xec\x86\xed\x11\xed\x9c\xee(\xee\xb4\xef@\xef\ +\xcc\xf0X\xf0\xe5\xf1r\xf1\xff\xf2\x8c\xf3\x19\xf3\xa7\xf4\ +4\xf4\xc2\xf5P\xf5\xde\xf6m\xf6\xfb\xf7\x8a\xf8\x19\xf8\ +\xa8\xf98\xf9\xc7\xfaW\xfa\xe7\xfbw\xfc\x07\xfc\x98\xfd\ +)\xfd\xba\xfeK\xfe\xdc\xffm\xff\xff\x80\x00 P8\ +$\x16\x0d\x07\x84BaP\xb8d6\x1d\x0f\x88Db\ +Q8\xa4V-\x17\x8cFcQ\xb8\xe4v=\x1f\x90\ +HdR9$\x96M'\x94JeR\xb9d\xb6]\ +/\x98A\x00\x930(*l\x0c\x9c\x03\x02\x13`P\ +0\x07?\x02?\xe8O\xe8X\x06 \x01\xa4\x00hO\ +\xfa$\x1a\x93H\x82R\xdf\xf0J}J\x06\xff\xa4\x80\ +\xa9t\xd0\x05\x1a\x07U\xa5\xd5\xeb\xf4\xfa\x8d\x86\x05S\ +\x81S\xe9VhK\xfc\x05o\x01\xd5\xaa\xf6\xca\x8d~\ +\x0fh\xb4\xd2\x00P\x8a\x95\x92\xefK\xb0P\xacW\x9a\ +M\xca\x9dI\xbe]05\xca\xf0\x02\x98\xfe\xc8>\xf2\ +O\xa7\xa6U\xe2\xf3\xcc<2O\xb7\xce\x1aSO\x07\ +\xe8Bcm!\x10\x87\xa7)\x89\xb5C\x00v\xb4#\ +?\x01\x81*\x98\x88]\xf7i\x87\xa4g\xb18+\x1e\ +\xe7\x01\xb7\x8e\xed\xaa\x17:\x15\xfa\x0d\xba\xde\xda\xf7\x98\ +Ln;\x7f\xbe\xe2\xf0!\x99\xec\x0d\xe2\xbbj\xe8T\ +\xab\x18^\x7f6\x9f\x90\xc8uz\xbb>\xcf\x81\xfc\xf8\ +\xf4=\x9c\xbe\xb6\xf3#\xdc\xbaa|VN\x0f\xa3c\ +6\xfa\x94\x04\xbfAb\xcf\xf4\xe0)\xc0\x03:r\x08\ +-\xebzc\x03\xc1\x10L\x15\x05>\xe6\x94\x1cc\x13\ +p\x89\x04h\xc2\x86+\xee\x90\x00\xd0\xc8\x10(C\x83\ + \xdb\x0f\x91\x00LD\x05\xc1q,M\x13\xc5\x09B\ +\xa4fE\x85\xf9\x17\x17\x8d\xa6\xfcdk\xb9\x08\xb0;\ +\x1b\x84\x84LtV5A0_\x14\xc8\x12\x0c\x85!\ +\xa2\xe7\xd4\x8c|\x93RI\x00SI\x84|\x8c}\x1f\ +(\xc4\x0a\x01\x07\xb2\xa8\x9aCK\x058\x0f-\x812\ +$\xbd/\xcc\x13\x0a\x04gL\x86\x08\xed3\x8a\x87\x84\ +\xd4v#\x09\x98\x08\x02\x8a\xf3\x88\xda7\xce\x84\x5c\xa7\ +1O\x13\xcc\xf5\x03\x9d\x13\xe9\xc44P\x02\x11\xc9A\ +\x9b\xa8\xc42\x03\x01\x03-\x14?\x0c\x14h\xf0\xe3O\ +t\x8d%I\xa3\xe7\x95,w\x0c\x94\xc8|oS\x86\ +\xad\x0d\x0d\x0d\x95\x09\x0e\xfe\x8b#}!JU\x15M\ +T\x873\x07\x99\xe1E\x0c\xa1\xf1\xb9Y\x9ah\xc4\xb6\ +\x03\x810\xf8\xdaDN\x22\xb8\xdbS\xc4\xae\x13\x9bU\ +\xc8q\xab\xae\xe1\xa1V\x15UV\x9e\x14\xc8\xc8\x1e\x9b\ +\xb6\x89\xa9O\xd1\x03u\xacD\xd7\xb5\xfb\xa4\x89\xaaF\ +\xdd\xbch\x9e\xb7\x09\xe6\xea\xcav\x13\xa8\xe0\x1f\xb7I\ +\xfb;\xb8\x8e\xdb\xb2\xf29Wr\xd4\x82<\xc8E\x80\ +\xe3\xbb\xab+\xa3d9\xd7\xdd\xe3}-\xd0-\xec\xe0\ +X\xc8\xa3\xc6\xe4\xbc\xce\xc5\xde\xbf\xb9`\x04\xdc\x02\x84\ +X\x88T\x05\xe2\x80r8\xca\x9e\x87\x8d\x9c\x1e\xd6f\ +\xe5j\x8b\xd6\xe0MB6\x10\xe2\xc6L7^\xe8\x89\ +\xf9\x95\x9fc\xa6\x5c(\x9a\xf9\x89\x9be!\xf72\x87\ +\x02\x80xN\x15\x80:\xb6\x15 \xed.\x92\x9d\xea\x81\ +\xe8O\x06R\xe9\xad\x97r\xb5\x9b\xae\x17\xa6\x8c\xe0`\ +\xeec\xcdr\xbb\xb9\xa5\x93|\xdd\xb4\x83\xcc\x08\xeb\x80\ +\xa8\xf9\xaf\x93an\xc4\x1cb\xec\xb0\xc7\xb3\x87\x96\x89\ +\xbbi\xe4\x12\xe6GQ\xbf\xa3z8\xfb\x8c\xdb\xa8~\ +i\xef\x06E\x89\xbd\xef\x88>\xb8\x08\x82\xb1\xd1\x12U\ +\x86\x5c(~\x8eY\x9b\xa8\xcc\x1f\xdb\xc6\xd9\xa5[K\ +\x95\xd5y9h\xe8{\xefX\x07\xc6\xa74d\xef\xa8\ +\xbcD\x04\x81a\x0fD\x14\x82\x9d(2\x0a\xf5\x00\xd3\ +Z\x07\x02G\x7f\x5cu\x9d\x9d\x89\xccu\xf6\x8758\ +o\x1a\xd0\xbf:\x8a\x82\x1d\xe8)\x17\x91epa\xe1\ +\x87\x9c\xaa\x1d\x8ccT\xce9Zr\x15\xc6\xdf\x93\x0b\ +\x19E\xb6\x89I\xe7\xc8\xcf\xeb\x88\x1b\xc1\xa7\xbdwh\ +Gz\x08\x02\x82\x07\xc4(|B\x00\x9e\xd2\x06\xc2%\ +\x0e\x04#\x07\xb7\xdcy\x98\xdf\x89n`~\x85\x8b\xe2\ +a\x16_q\xecz{\xbe\xf7|\xf0\x1e\x13\xc4x\xc4\ +5f=p\xce\x10\x06\xd4\x09\x1a+P\x049%H\ +\xdc\x88\xd9\xf7\x80\xc1\x01\x07\x0d!\x8e\xf7I\xe0\x0c\x0b\ +\x90l9\xc1\xb0\xb8\x1d \xc90MC\xc0v\x09\xc8\ +L \xc5l)\x13\x0e\xe9\xce\xbd\xf0(\x22\xa1\x80\xad\ +p\xa0\xc8\x1f6V2\xe2\x81\xfc\x09\x1bP-\xb6\xbc\ +\xe5D\xf4\x1e\x92\xfc\x22\x8e]E9\x976\xdf\x02<\ +I\x0b\x01\xce&\x09\x03\xf4\x04\x80\xbaD=c\x94o\ +\x08X\xac\x19\x86TY\x17\xad\xf1\xd5\x81!\x19\x17\xc5\ +t3p\xe4mf9\x86:\xc7\xc8\xb3!rKf\ +\x01\x90\xc6\xe8\xdd\x9e\xd3\xdcR)L5GQ\x0a\xa3\ +C\x00xRk\xa8~\x08\xe8\xfc\x1cEL\x81\x12\x8a\ +\xaa\x17@\x00c!\xc1\xe9\x1c\x5c#\xd4y6p\xc6\ +\x0f#;\xcddP\xfd\x93\xc6\xd2\x16\xca\xc7\xe0\xfbs\ +\x11\xc5=\x00Y<\x01\x9c\x10\xab\x07\xd2\x8c'=\xd1\ +Y)\xc4\xb0\x88\x95A\xadI\xb7\xf7\x02\x8e\xe1\x9c5\ +\x8c\x86f3<\xc8z\x02V\xb0n[\x09\xc9\xb9\x99\ +70\xe6\x86\xa3\x9cO!\xf6b\x09\xc0\x9f1\xc3\x19\ + \x1dS,r\x8d\x89\x9c3\x9dp\xef\x1dO \xd0\ +\x80\xf8\x9f\x14\x01T\xd9\x06\xb0\xb8\x90\x09y\xbc\x1f\x04\ +\xec\xe1\x10\xa9\xeaWC\x01\x14+d81\x912\xcd\ +W1\xb6\xd4\xdb#K\x91D\x11\xb1\xe9\x91\x18\xde\xe2\ +\xe4\xe2`\x81\xf109\x89\x020\xa5\x87\x90\xee\x15T\ +\x0cJ\x8b\x8a\x0c)\x8f\xa0\xe0\x1b\x0c\x18\xa4\x82z\x1c\ +\x0c\x02e\x11\x0c\x13\x1c'\x867>\x89\x16\xe1K\x0e\ +\xb4l)?A\x80,\x13\x0c\x85E\xe2\xbat\xce\xb2\ +4\xf2!\xc4:\x87\x93\xc6\x1f2H\x1eG$\xc0\xfb\ +cs\x02a$ IM\xc1jL\x14\xc3=\x9c\x11\ +\x02\xa4)j\x00\x8e\x135\x0c?\x8fz\x8c=IC\ +\xdf\x02a\xca\xa6\x09\x00\x95S\xc2\xe1\x14\x7fC\xcd\x0e\ +\x05\x00H;\xaa\xc0\xeaH\x93\x96\x18\xd2W\x11-\x22\ +,\x91\x96\xeeJ \x11\xc7\xab\x0e)\xa2D\x125\xac\ +Z\x83\xba\xdc\x12\x88\x85F\x1e\xe3\xd6\x8d\x87P\xa2{\ +\x86@\xbbD\xd4D&\x05\xe0\xfd_\xc4\xf5=!\xe2\ +\xae\xc2\x09W\x04\x1b\x12$.\x9c\xd3\xa2DIb\x15\ +\x01^\xc5*\x81\x95\x92J\xcfR!=\xdb\xbbyH\ +\x00\xd2\xce\x04\x011g\xc5\xf9\x10I\xe3\xe2\x5c\x84\xa4\ +X3-\x0aC\x096\xac-\x88\x1b\x5c(\x97a\x0a\ +\xa6!V\xda\x02\xa1\xc7m\xc6\xe2@\xab\x93\x9e\xaf\x11\ +\xb7\x90\xc6\xeb\x15,W3\xcd\xcaYg-/\xa2-\ +iE\x22B\xe6\x0b@ys\xc2Y\x10\xb9\x82@:\ +\x0aK\xac#S\xd0w\xbbBR\xda\x05YXC\xe8\ +\x18\xaa\x12\x93\x986\xa4\x08]\x17\xc4`\xafx`\xc0\ +\x1eCa\xe3J`T\x92\x8dw\x16!\x11:cL\ +\xe2:%\x83\x22\xf2\xfe\x0e\xc5\x0e\x01\xc8dg\x0bx\ +\x0c\x18\xae\xa1\xfa\x9e\x98\xa0\x0b\x01\xa2\xbf\x06\x0d\xc8\x9e\ +\x05\x88`\xe9\xc2C\x8c%\xe1P=n\x9a\xeb\x82\x15\ +\x92\xc6E.\x19\x1a\xda.\x09\x15d2\xe4D\x85l\ +L\x1b,q\x09z\xb0N|\xa0\xb3N\x10\xc2\x9e\x1a\ +\x22\x17\xa07\x0a\x8cl$\xd5UL\x0eB8-c\ +\xd0\xe2D \xf03\x99\xc3`g\x22kwc'U\ +\xees\x0e5\xc7\xcbv\xdfK\xe0\x89\x93\x87\x18\xb5\x05\ +\x07\xbc\xac&B\x8eY\x0c\xc4@$e\xd04\xecG\ +`\xe7U@\xbf2\x03\xa9\xc2'F)\x10\x12\x99\xac\ +<\x0a\x0c\xdc\x22r3]\xb1v\xf6\x93\x99l\x96\xb7\ +\xb2m\xc2y\xf6V\xfa\x91($\xf6 \xac\x17D\xa2\ +KB\x0b`u\xa1\xc2I\x0c\xaeC\xd5*\x83\xd0\x18\ +\xdf%p\xbb\xd2Uh\x87\xcaqY*e^qp\ +\x10\x032\x02\xf0w\x8aHDe\xac2\xd8\x8b>\xbc\ +IYr\x88\xfb\x1fR\xfe\xfc\xa0\xbat4\x11\xea?\ +!c\x8bZ\x0d\xb0\xa5\xad\xc13\xdd\x19:\xec}\x9b\ +\x03dB\xe8\xf0\xb0e\xc1\xd0(\xa2jD\xf0o[\ +\xc5\xb8\xcf\x1c\xcb_\x08w|\xae\x22\xbe\xd4\x04\x1e\xcc\ +eD\x13\xa4\x85\xd8\xea\x95\xc42\x84\x8d\x80\xa9\xb7\xc1\ +K\xdd~#\x18|_\xf2\x19M#\xc3dD\xb6*\ +\x18\xe1\xcb}\x9d\xa2.L\xda\x0a\xeezg\xd9\xed\x94\ +\xa3\x85\x9aD\xa3\x0f~\x0fJ/\xb7\x0f\xae\xdf\x0a\x9b\ +\x85\xdd\xee=\xca\x86p\x01\x0b\x9d\xea\xf4\x16\xecg}\ +b\xf7vuc9\xdd\xc7o7'\xb4\xb6Y\x0d\xcf\ +\xf0\x1f@\xa2m\xf80\xf7\xf2#\xe0\x14+\x81pG\ +;\xc1\xb77\x0aZ\x5c3\x87>\x09\x0d\x220\xec\x8c\ +c{\xca[\xe2LL\x15\xb1G\x19\x8d\xc6N\x09\xf1\ +\xdd\xf7\xbfw\xf9\x0b\xdb\xbc\x97q?\x1e\x0e\x01\xb8I\ +\x0a\xe1i\xc7\x86\xa2Y]\x86\xb8\x89\x19\xa5\x0d\xda\xc9\ +\x11w\xd6\x1c:\xc0\x8b\xbb\xa1\xafi\x90m\xab\xbe\x90\ +_\x1f\xe4.\x83\x91\xed\xed\xc1\xd1w')\xe9\x5c\xaf\ +\xa6i\xa9^\x22Ee%\xeb\xa4\x15\xc4\xb7nip\ +\xaf\x9f\x18\xde\xd6_|O\x8e\xc0\x82\xbb\x17A!]\ +\x0f\xb3\xf0^\x8d\xda\x88OK\x0a\xfd5\x05\xee\xc9\xcf\ +\xd4H\xc6\xa2V8\x84\x8a>\xb6\xdf\x8fB\xd0p\x97\ +\xba\xab\x9e\xa0\xed\x04\x81\xef\xf8\xbe\xf4C\xb8\x04zP\ +\x14C5\xa0\xe2\x1br8\x1d\xbd\xd1m\xeb\xc7$\x9e\ +\x00\xa0\x18\x86#!\xbe5\xd5 /\xa6(&WJ\ +\xa1\x10*\xa3\x17s \x94\x00w\xc1>\xef\x88\x92\xe7\ +6\xc4\xff\x08\x81\xbdU\x00\x1a\x02\x0f>$\xc5?\x9b\ +\x86\xben\x1b\x00\xff\xd9\x04\xef\xf5\x04-\xd5\xbe(\x7f\ +\x00\x89\x17?\x8cT\x12\xcd\x8fI9\x84\xec\x1e\x10\xe3\ +\xe3\x91H\xd4\x885A\x1a\xeb\xefl\x92MP%\x00\ +#\x17\xdcO\x1e\x88_\x0a\xdc\xac\x0f`\xb4\x85\x82B\ +\xf1\xc8dp\xa9d\xe2G\x92Y\xef(\x22fB\xcf\ +g\xa2\xf9\x82\x04\xfeh\xe4$(\xac\x10\xa1L\x89 \ +\x8e\x0b/\xf4R\x8c\xdc\x14\x01\x0e\xcda(\x0fBI\ +\x00\x8f \x22\xe5\x98\x9d\xc5\xa4\x92P\x1c\x88%\x86\x22\ +h\x88V+\x94#\xc0q\x06`\x8b\x04\x01u\x03e\ +T<\x01\xfa\xe1\x8fl\x1a\xe2@\xc8\xec\xe8#)\x16\ +\x1eNf\xcf\x0e,\xfe\x223\x02B@\x0fP\x98\x13\ +\x0dn\x0a@\xcf\x07\x06\xf6\x12\xb0\xa8\x0fA?\x0a\xe1\ +\x0e$\x0b\xce\x8b\xeb\xd4x\x8ec\x08\x87\x94\xfd\xb0\x18\ +\xf9%\xae\xfa\xf0 \x00\x0e6\x82\x8f<$\x10@\x17\ +0f\x07\x00\x8c\x22\x08\xb2\x19Ay\x07P\xa4$G\ +>\x01\x8d:\xf5\xa2\x1e\x16\x10\xfc\x13a\x09\x10,\xb6\ +#\xe9\xaa\x02k\xd0\x15\xf0\x82#\x07\x90\xe2\x8c\xf2\xf9\ +\x05p\xef%\xb4\xefk\x8e\xd5MX\x98\x22@I!\ +4\x18\x0f\xf2!\xed\x1a\x01\x8d\x17\x0e\xe2B\xa6\xe0H\ +\x05\x8cl\x15\x08\xd0!\xa1k\x15!D\x0f\xf1X\x0b\ +\xf0~\xceHb\xd90\xcf\x11m\xe3\x08\xca\xc6\xda1\ +#\x05\xac\xfc\xef\xab2\xfe\x82?\x13\x114p\xc2!\ +\x13\xb1?\x14\x02?\x14QH\xc6\xd1N!\x91R\x16\ +\xb1W\x15\xb0\xb4\xe1\xed\xdb\x00\xca\xbeU\xcf\xd9\x16\xce\ +\xf1\x17\x10\xce\xc5g\xb0\xda\xc27\x18\x116!\xd1\x88\ +\xa8\xf1\x8d\x18\xeao\x191L\x22\x11\x9b\x19\xe0\xff\x15\ +\xc2>\xe9\xe9a\x1a\x8f\xd4\x96\xa6<\xe2\xcd\xeb\x17M\ +\xef\x12\x8b\x92\xd5\xa2;\x1c\x11\x85\x13\x84\xab\x13\xd1\xc9\ +\x1c\xa2;\x19\x11K\x19b\x17\x1dqY\x1d\xb1\xa2\xe5\ +\xcaG\x16Nt!p\x87\x08\xae+\x16\xed\xe8\xbe\x91\ +\xf0\xef\x8dT\xcan\xfe#\x91\xfc\x06H\xc7\x1cR\x03\ +\x18\xb2\x08#r\x0d\x19Q\xd5\x15R\x17\x1d\xc2<\xc8\ +\xf2!\x12EX31\xaf\x22\xac\xf4\x92\x90\x1f\x22\x22\ +\x15\x09Q~I1\x83$\x11\x87$r\x06@\xe07\ +(`B\x06r\x8c\x08\x08\x5c\xcc\x01\xcf\x0eax\xcc\ +\x01\xd0A2O\x1d\x22\x1f!Q\xa0#\xf0I\x1eB\ +4\xee\xa7\x17\x0cB$\xc4p\xca\xf9rp!0^\ +\x88\xd1-'q3\x1c\x22\x1b\x1cj\xe6%\x8fJ\x01\ +\x00\x14rP\xcc\x9e\xaab\x84\xc18\x10P:\x11\x09\ +0\x1f\x82Y*2\x10!R\xa9!\x91\xdf\x16\x0bx\ +\xfd0\x11\x11\x90\x8ed\xef6\x1fR9\x17\xc2=#\ +\xf2C-2\x81-bN\xbf\xf0:\x19\x04z\x06\x02\ +0\x18\xb34\x16\xc4\xe8\x0d\xeb\xa2%r\xf9%1\x9d\ +%q^p\x0e\xa1+\x023+G\x19\x1b\x11\x1c\xb8\ +ew\x09\x021,pc\x1f\xb2y-\x02\x19-J\ +\x90$\xe6\xde\x8f\x08\xf4#\xe1\x0f7\xe0\xd0\x85!Z\ +\x13\x22Q42\xa7%R\xaa#\xcf\x1c\xc3q\xff+\ +*\xc0\xf2mI5\xb1!\x0c\xf2u1\xb3k9\xb3\ + \xd1\xd2H$\x22r\x01\xeb\xf8\x17\x81\xd6a\xe2@\ +\xab\x01\xdc\x1d,\xba\x09\x004hbE8\xc2\x1d/\ +\xf2X#\xb1\x0ax\x10\x0b'\xcd\xde\xe2qk&\x93\ +\xa5\x1bR\xc2!\x13e\x1f\x92=:\xf3\xe9$S\xb5\ +(\x22C\x0d\xf0j\xcdpn$\xe4\x00\x0a`N\x1c\ +4\x1c\x1bBI=\x91Q9\x13\x019Q\xa4\xf1\xf3\ +P#\x12'\x0c3X\xfd\xc9\xe55\xf3\x10#jb\ +\x93r;\x1b\xf4\x011\xf3o23r$@\x83E\ +\xa0\xa2\x80\x02P\xc8,\x86\xc8\xa2GBQ\x99B\x93\ +\xde#\x91\xe0\xee\x10J\x22\xcf$VS\xa3C\xd1\x1f\ +?R`\xe3K\x91\x06\x13\xfdD\xd2\xcf;\x14S@\ +s$$J\x1c\x04\xe0`\xa8\x01J\x19\xe2P\xc5\xe0\ +&\x1e4\xb4\x1d\xd4#\x1c\xf2\x0f4Q\xd9G\x227\ +\x10\xb1\x0f\x11\x22.\xb7\xe7\x95\x01r\xbbC\xee/\x17\ +3b\xe7\x8d\x01\x0dr\xcd'\xb4P!sp$\x84\ +\xa6\x15\xd4\xf4\x1b@9O\xa0F$\x0bN\x17\xef\x9e\ +\x08S\x8bK\xd2Q8\xf3G9\x22;%\xc8\x05?\ +b\x0fCe\x9f+\x82#+\xc9t[3\x131p\ +'?\xf4\x97@3\xb3 T\x9e$\xa0\x8bT \xad\ +7\xe1\x0e\x15\x228\x8f\x88&\x1a\x15T\xcd\x22OF\ +\xd2\x13G\x13J\x02\xac\xe70\x8e\xa42\xcb\x81H0\ +\xc7Hr.\xefR2!\xe7\xaas\x01\xabX!\x95\ +\x12\xf4O'\xf4\x9dEbR\x0cU\x94\x0f@\xd3Y\ +\xa1\x08\xc5#\xef\x02\xa0\xcc\x16\x95\xa8\x142\xf7P\xd2\ +\xa5=\xb5a*\xd4.\xc9\x00{\x16umM5q\ +MuuM\xb3\xa9\x17\x91\xbc#S\x1dX\xd5=Y\ +\x02Xda\x0c\x8f\x00\xf2\x22\x11\x02\x10\x80\xcb\x0f\xc1\ +`\x13\x82aU\xd2\xfd[t-!\xc7\x83L\xc2-\ +\x16\x85cRB!R\x8cK,\x14\x8a!\x95~\x88\ +\xb5\x82\x1a\xb5\x87NsmN\xd4T&\x00\xbfb\xe0\ +\xecWL\xe0!\xe0\xf1c\xa0\xad;\xe1W_u\xb1\ +/\xa2\x13=\xd2\x1a\x85\xf1\xa6\x86\x8b\xdc\xd9\xcaW?\ +4@z5.\xdf3\x196\x957N\xa2\x15N\xe2\ +_b\xe0\xbfc$?cb\x1dc\xa0\xf1c\xeb\xf9\ +d\x22__\x96K_\xd5\x16\xc3$v\xeeU\x1c \ +\xd6\x08\x07\xd6\x0c!\xef\xdfWt\xdcH\xa4\x8e\xc5\x94\ +K]U\x8b \x15\x8fb\xd61cB!h\x16\x84\ +\x17\x96\x88%\xd6\x8c!\x16M0'\x01Vl\x92#\ +p\x86\x91\xc9!\x5cu'M\x93`\x22\xf4F\x88\xb5\ +\xd2#5\xd7k\x95\xda&\x0a\x9e\x09@\xb8\x10W\x04\ +\x14b Y\xc0yUA\xa1U\x96\xcddt\xc14\ +\x91\x084T\xcbV\x91\x14\xde\x16\x0bC\xa2&}h\ +\x1cn6b\xef\xd6gST\xe9]\x93\xb6%\x8f\xec\ +\xb0\x81V\x1a\xc8\x9e\x8a\x22\x0ev\xe1\xaa\xc0`\xb6\x06\ +P\x05Z\xf1GK\xf5\x11L6N\x80\x12_W\xad\ +\x99>\xd7+?\x14\x855\xc1\x11n\xa2-:\xb6i\ +s\xf6\xf9t\x22^\x04\x17\x90\x05\x07$t@B\x05\ +!\xady\xe1\x96\xd0\x81$\x0e\xe9\x96\x1dA\xcb*\x17\ +\x19vw\x1c#\xd4\xc9\x0b\x96\x04\x22\xb6\x9fj\x22\x1c\ +\xd4\xc5\xaf\x1e\xf4\xdf\x1fT\x91,\xb3\xadf\xb7A@\ +\x92J#\x16\xce \xf6\xd3%\xb6\x94pi\xd2\x07\xd0\ +\xcfG\xf4\xd5nu\xcb|\xd6\xacJ\x0f\x9e\xfa4\xe5\ +}w\x89@V\xfb}\xe25~\x22\x0d~b:\xfc\ +\xf7\xbe\x22\x97\xf5nV\x0em\xc5D\xca\x0f\xe42f\ +7a\xf6#\x80\x96'f\xf6+\x81\x023\x81B\x0b\ +\x81\x8299x:\x22\xb0\x87Y@\xc4\x07i\xdf\x05\ +X+sMR\xd5q\xf7}W\x87\x84\xe2\x11g\x18\ +@\x22\xf8D \x98H#r\xafeO\xd4\x82n\xab\ +&\xa6H\x88\x15\xcf#veS4\x95\x80\xb5;x\ +\xd8r\x22Xv xz#Tw9\x98\x81\x01\x15\ +o\x1e\xb2-\x5c\xd6\x9a \xb7\x84#\x8b>\x13\x01|\ +\xb3\x80h\x08\x22 \xbb@\xee\x0a\x81\xf3\x8da\xf1\x89\ +\xe2.\x03X\xe0\x04\x04\xce\x0e\xc9\x06!\xf5\xa8\x16\x81\ +@\x10\x18\xf4\x0c7j\xa4x\x1e\x22sU|B\x1b\ +jx\xb9ab\x17\x8b\xe26\x94,^\x0a\x98\xdcO\ +\x0b\xac\x14\x81\x1a\xba`\xe9d\xee!C4\xcf\x5c0\ +\x15\x82V\xa5n\x94C\x82\xf7\xd1,\x8aj#\xa9\xf6\ +\x89\xb9\x1aLM\x86\x0a-\x83\x92\x96S\x00\xf3S&\ +N\xedr\xd5\xc8\x92x\x8a\xcf\x97qH\xcf9N(\ +,$\x0c\x12\x01\xb2\x0e\x039|\x03\xf9JH\x17\x9e\ +\x1a\xc1\x97\x85@u/5b\xc3V\x99\x90\xc2\x15M\ +\x193\x8bMJCMO\x93\xa23n\xe5co\x22\ +8\x06\xb9\xb4\x08A'\x9b\xa1qC\x88)\xc2\x0aS\x82\x81\ +*\xcf\xcf\x18\x0b\xfcH\x06P\x09\x8c\xae\xbd\xc9\xbb\x9e\ +\xa1>\x0a\x91\xa3\x05\x83\x87\xdc\x1cG \xa2\xaa\xf4V\ +\xa0\xa3\x90i\x0b\x9cJ\x9c\x0a\xab\xbc\x0a4\x12\xa2\x9a\ +\x91\x08\x0c|D\x83\x92\x0a> \xa0[\x10{ \xa4\ +(\x1d\x17\x91\xa14d|\xa8\xf0\xdaY\x1b%p\xfa\ +|\xf9\x19\x822\x0aI\xa0\xa13Dn6\xa3k\x92\ +\x19\x97\x0a\x1cp\x95IiLt\xe7\x1f\xe0\x11\x9d)\ +\x90i\x00\xf4\xd3\xa1\xe4L\x8e=6\xa7\xf2s&\xa5\ +\x13\x02O'\xa5\x8e\x99\x9e\x08\x1f\xb3IJ\x82\x89R\ +\xc2,\x5c\x00s\x88\xb2\x18\xce\x8e\x03\xdb\x03\xb1\xf3\xc2\ +}2$\xf2\x99\x9c\x15:\xc7\xf1`\x82\x84\xb3r:\ +nN \x18\xa1:\x06&\xac8\xa5LI4\xf8\x91\ +5\xc6h\x86\x90\x15\xe8(\x1bC$\xe7\xa3\xfc\x01\x0a\ +P\x08d]\xa54\x8aKS$\x94\x9a5?\x08\x94\ +\x09d\x82\x814\xe2`|S\xe2uER$\x95B\ +\x81='\xb5R+\x1eG\xc8!b\x82\x81\x0a\x93\x96\ +\x82\x15\x8d\xa9n\xda\x9c@M\x9cq\xcd'\xe9\xfe~\ +Z\x80\xd5\xa8~\x17\xa8(8\xae\x1f\x08(\x9f\x0b\x86\ +\x85\xd2=]$W\x22=_\x22\x11\xe0\x8e\x82\xd0h\ +%\x8a\xa5\x9c-\xa8\xe7Q\x15\xf2\xea-\x1e\x1bh(\ +H\xb1[\xa8 \xa1p\x17,\xf5x\x9e\x5c\xc8\xed\xd0\ +\x85\xcf\xc1\xad\x02` \xa0R\x98F\x82\xd8\x88\xfa\x0f\ +b\x87\xba=|_KA\xec\xda\x87\xf29\x98\x8b`\ +\xa8\xe6B\x8d\xe0\xe84x\x0f \xa6J\x0a\x0c(\xd2\ +\xf2\x086\xdc\x04\xb2S\x8c \x97\xda\xdat<\xa08\ +l\xf4\x05\xafSG\x0e\xa8\xb9\x1a5\x83\x9bZ(\x1c\ +yi\x06*\x0a\x16)\x83-\xc0N%\xf9\xa0\x01\x9b\ +.F\x90\x17\xab\x87\x81N\xb4y\xa1\xda\x123\xaf#\ +\x14\x9a@\x00\xd2\xa5\x9a\x0a%\xa8\xed\xa9A#\x8c)\ +\x9e\xa5\xaa.\xa5\x94\x8e(6\xba\x02\x0d\xb0\x22\xfb\xc2\ +-I\xd2\xa3\xe2@A\xa9\x87\x02\x0a\x15\xdc\x11be\ +\xb7\xaf\xad\xa8\xf1#\x91(V\xf4\x8a\xf1\xe8\xa4u\x1e\ +\x07\x88.\x18\x82\x00zn\x9e\x9c\xf1\x0b\xfb\xf8\x82\x07\ +\x97\x06T\xa8n\xd2V\x06\x9d\xba:)\xb5\xa3\xe9\x06\ +\x92\x0a\x0f\xa9\x87\x0d\x09p\x1f|\xe3\xe5|\xe6\xacG\ +p\x00\x06\x1c/\x22\x89\xf7\xe8\x93\xa3\x1e\x11\xb0\xaa\xa4\ +E\x5c\x03\xba{\xce\xb0\xed\xa9\x05#\x8f\xfe\x0a#\xe9\ +\x22\x06\x87\xad4M9\xf0\x18\xa6\xd1\x22\x0d\x19\xcb\xa7\ +~c\x12w\x81\x1f(<\x15\xfd\x07\xa4k\xd3\xa7S\ +\xf0\xec\x90q\xaa~,\x82\x01\xfd\xa7\x97\xdb\xe3,s\ +j9TD\x7f\xd6\xe9J\x12\x95\x16\xa9\xb0\xa9\x0d\xd5\ +\xc0\xdc\x09\xe8\xd2\x81@\x88\x90\x00RR\x83\x87\xda\xaf\ + \x89\x08\xa7\x8b4\x8e\x13\x9f\xf9JR\xa3e \x95\ +!\x8a\xb8\x1c\xa9\x82G\x82\xf8\x82\x84\x12\xa46\x128\ +)\x83%\x1dJ\xb8`\x00\xacJa\xb5\x16\x89\x1c&\ +\x984x\xa6W\xf1R\x1e\xe9\x1d\x87\x14g\xa8C\xd4\ +\xa8\xdf \xa0\x80\xa9\x0cu\xc0\x0e\x8c\x1a\x95\x18D\x80\ +\x1e\x95!\xbe\x91\xc1\x14+(\xcaU\x5c\x00\x00\x88T\ +\x86\xf2\xe0\x04p\xd8\xf9A\xc8&T\x85\xd2G]p\ +\xf9\xf6\x13\x95*\x22\x08+\xca)\xe3\xe1\xf2\x80\x80\x1e\ +\x0b#\x80\xfa.\xa8\xf2\x07\x10D\xec\x00!\xe9N\x10\ +\xa9\x1d\x14FH\x00O\xd3\xf0\x1f$\x03t\x82\xb9\x92\ +\x9e\x10\xd7\x04$.\x89\xf8\x1f\xb0\xb2\xa4>\x8d\xa8!\ +TK\x1d\xa0\xc6RltT\xa8\xa9$\x01X\xa6\x90\ +\x00\x0c\x09\x183\x82\x9d@\x10\x88L*\x17\x0c\x86\xc3\ +\xa1\xf1\x08\x8cJ&\x00fE\x910\x93\xb4R7\x1c\ +\x8e\xc2\xd3\xe3I\x09\x89\xff$\x8fI\xa4\xf0\xa9#\xfe\ +Q,\x8f@\x80 \x06\x94\xc8D\xfa\x9a\xb4! \xd9\ +l\xea8\xe3\x04O\x84\x82\xca\x0b\xeawD\xa2\xc3\x1a\ +\x94\x803\xe2\x96\xdb\x84\x87\xa8\xd5\x08c\xc0\x07T\x16\ +\x0cj\xeeYUF\xb7Z\xad\xd4%\xf0\xb6u\x88\xbc\ +\xfe\xb2\xa8k\xd5\xe9y\xa6\x0a3LZ-\xf1\xd6m\ +\xc8\xcf*\xb7\x5c(\xd2\xf2\xc5\xb1S)\x92\xdd\xe7U\ +\xdb\xfc\xb2\xc1\x0e\xb93S\xf2\xa3\x06\x0av\xe2\x02c\ +\x85C\x0c\x8b\xd7\x17\x7fhe\x81o\xcc\xcb^\x12\x1d\ +\xcaI\xe5\xe9\xbba\x9a\x1d\x81\xcfGt\xbah\xde\x12\ +\x1a\xe2\xd6\x82][\x06,$c\xa9\x8e\xcb\xd4\xb6\xc2\ +\xe6\xd6\xbd\x16f)a%\xad\xde\xaa\x04\xcd\x06\xf1\x87\ +bnK\xe7I~\xe1D\xf5\x1c\xe8~\xae \xd3\xea\ +\x87_=\x86D$5\xd1\x8d\x9a\xe4#D\xb7vM\ +\x866J\x92~8\x9b\x96\xa8\x03\x1b\xd5\xc6.X\x97\ +C\xd3}\x95\xfd!\xdd8\x9b?\xf60~\xff\x8c4\ +$\x0c}\xd0\xc3\xfd/\x1d\x16\xc2:\x03C\x1b\xd4\x1d\ +\x08F\x10\x84\xc2\x0aBO0\x0a\x15\x0fC(`\xd1\ +G\x1f8\x0e\x1c}\xdf\x94qb3\x84\x95\x94\xfe,\ +\xd0\x90\x0e\x12B\x92\xf2X\x0a\x8b\x87\x80\xa61<\xdb\ +Sj5\x03\x8f(\xe0\x8aBFx\xa9\x0c?R\xf1\ +1l.\x12xy\xf4\x91^\x98\x81\xe4\x5c\x85\xc4\xa8\ +\xa0\x8a#\xd4,\xe7BG\x94$\xa6x\x0f\xb5\x19H\ +5\x14\xa5-\xc1B\x08\x84$\x17\x94\x10\xa8\xfd\x02\x18\ +\x16\xc2\x91\x80sc\xd9\x1d\xe3\x92R\xc8\x88Y\x89J\ +9>cC\x0e\xf4$\xb0Bd4 \xe2\x01g\xf3\ +\x91\x0a>\xe80qNK\xc4\x94\xa8PBA\x09\xda\ +>\x85@!v\x18\x0c\x8au\x1amwigFo\ +N\xe2!R%\xa5\x10\x80\x12\x8d\xa8\x9ac\xf1\xc0x\ +\x0a\xb5z\x98s\xaa\xa7\x0a\x9aQ\x9b\xda)\x08\xa7\xc0\ +\x00\x22\xa3\xad\x95\x17-\x08\x16^\x02\xbdw\xab\x1b\xba\ +\xfd\xb5\xab\x95\xb6\x183J\x8a\xe5:\xb7\xb2\x91\xe3\x8d\ +/\x14\x96\xc31\x94\xb0Z\x9bM\xa6\xb0\xd6\xf6\xf4\x14\ +K\xca\x94\xa8B\xb2\xed\xf40\xc0\xa3\xc5jH\xebm\ +mVz\xe8e-u\xfd*\x00\xe2\x22!*\x1d.\ +\x0a\xd8\x8f[\x07d\xbe\xa5\xaa\xe6\xb8\xaa\xeab\xee\xc6\ +\xd6\x22\x89\x16RI\x09\x09/GD\xddBF\xf7\x80\ +\xb5\x84\xaf\xe6\x0b\x10_\xf0\x07:Z\x97\x0f\x81\xc9\x09\ +\x1f\x10\x90/\x08V\xd94 \x86\x03\xb225\xc9\x09\ +\xab\x99\xb2\xfc\xc3\xf2\xa8+\x14\x80\xdf\xb3<\x1b\x7f\x8f\ +\xd2-\x09\x16q\xe4\xb0\xa9\x9f\xc0Q\xd0/\xcf\xa8\x1b\ ++\x12\xaf\xb2\xc8\x0f.\x9d\xacT\xa8nBEt$\ +\x07\xbd\x144 \xa9K\xc9+C8B4%\xc3X\ +[\xf4k.\x22\x05R\xa1a\x09\x14\x12\xa0\xf9\x09\xa8\ +\x5c+\xe8\x00\x80\x10\x82\xc1\x8e\x01\x0a\x86D0:\xb5\ +d?ZZ7e\xa5\x02\xdd\x12\x84\xc8\xd2\x04Y\x93\ +\xf08\x89[D 0K\xc1\xd4\xa8\x11\xa2\xd0\x98D\ +\x00\x9e\x10\x83\xc1\x098\xd0\x93>\x8f46\xe3\x1c.\ +\xe6\xb8\xfd\xed\xa7\xd1\x1f}\xe3\x9d\xe8\xba>\x93w\xe7\ +\xfa^\xa3\xa9\xea\xb1\x1e\x9f\xab\xeb\xba\xfe\xc1(\xe8{\ +\x1e\xd3\xb5\xde\xfb>\xdb\xb9\xee\xb4\x1e\xb7\xbb\xef\xbb\xfe\ +\x8b\xb8\xf0\x01E\x01L\x01R\x01Y\x01`\x01g\x01n\x01\ +u\x01|\x01\x83\x01\x8b\x01\x92\x01\x9a\x01\xa1\x01\xa9\x01\ +\xb1\x01\xb9\x01\xc1\x01\xc9\x01\xd1\x01\xd9\x01\xe1\x01\xe9\x01\ +\xf2\x01\xfa\x02\x03\x02\x0c\x02\x14\x02\x1d\x02&\x02/\x02\ +8\x02A\x02K\x02T\x02]\x02g\x02q\x02z\x02\ +\x84\x02\x8e\x02\x98\x02\xa2\x02\xac\x02\xb6\x02\xc1\x02\xcb\x02\ +\xd5\x02\xe0\x02\xeb\x02\xf5\x03\x00\x03\x0b\x03\x16\x03!\x03\ +-\x038\x03C\x03O\x03Z\x03f\x03r\x03~\x03\ +\x8a\x03\x96\x03\xa2\x03\xae\x03\xba\x03\xc7\x03\xd3\x03\xe0\x03\ +\xec\x03\xf9\x04\x06\x04\x13\x04 \x04-\x04;\x04H\x04\ +U\x04c\x04q\x04~\x04\x8c\x04\x9a\x04\xa8\x04\xb6\x04\ +\xc4\x04\xd3\x04\xe1\x04\xf0\x04\xfe\x05\x0d\x05\x1c\x05+\x05\ +:\x05I\x05X\x05g\x05w\x05\x86\x05\x96\x05\xa6\x05\ +\xb5\x05\xc5\x05\xd5\x05\xe5\x05\xf6\x06\x06\x06\x16\x06'\x06\ +7\x06H\x06Y\x06j\x06{\x06\x8c\x06\x9d\x06\xaf\x06\ +\xc0\x06\xd1\x06\xe3\x06\xf5\x07\x07\x07\x19\x07+\x07=\x07\ +O\x07a\x07t\x07\x86\x07\x99\x07\xac\x07\xbf\x07\xd2\x07\ +\xe5\x07\xf8\x08\x0b\x08\x1f\x082\x08F\x08Z\x08n\x08\ +\x82\x08\x96\x08\xaa\x08\xbe\x08\xd2\x08\xe7\x08\xfb\x09\x10\x09\ +%\x09:\x09O\x09d\x09y\x09\x8f\x09\xa4\x09\xba\x09\ +\xcf\x09\xe5\x09\xfb\x0a\x11\x0a'\x0a=\x0aT\x0aj\x0a\ +\x81\x0a\x98\x0a\xae\x0a\xc5\x0a\xdc\x0a\xf3\x0b\x0b\x0b\x22\x0b\ +9\x0bQ\x0bi\x0b\x80\x0b\x98\x0b\xb0\x0b\xc8\x0b\xe1\x0b\ +\xf9\x0c\x12\x0c*\x0cC\x0c\x5c\x0cu\x0c\x8e\x0c\xa7\x0c\ +\xc0\x0c\xd9\x0c\xf3\x0d\x0d\x0d&\x0d@\x0dZ\x0dt\x0d\ +\x8e\x0d\xa9\x0d\xc3\x0d\xde\x0d\xf8\x0e\x13\x0e.\x0eI\x0e\ +d\x0e\x7f\x0e\x9b\x0e\xb6\x0e\xd2\x0e\xee\x0f\x09\x0f%\x0f\ +A\x0f^\x0fz\x0f\x96\x0f\xb3\x0f\xcf\x0f\xec\x10\x09\x10\ +&\x10C\x10a\x10~\x10\x9b\x10\xb9\x10\xd7\x10\xf5\x11\ +\x13\x111\x11O\x11m\x11\x8c\x11\xaa\x11\xc9\x11\xe8\x12\ +\x07\x12&\x12E\x12d\x12\x84\x12\xa3\x12\xc3\x12\xe3\x13\ +\x03\x13#\x13C\x13c\x13\x83\x13\xa4\x13\xc5\x13\xe5\x14\ +\x06\x14'\x14I\x14j\x14\x8b\x14\xad\x14\xce\x14\xf0\x15\ +\x12\x154\x15V\x15x\x15\x9b\x15\xbd\x15\xe0\x16\x03\x16\ +&\x16I\x16l\x16\x8f\x16\xb2\x16\xd6\x16\xfa\x17\x1d\x17\ +A\x17e\x17\x89\x17\xae\x17\xd2\x17\xf7\x18\x1b\x18@\x18\ +e\x18\x8a\x18\xaf\x18\xd5\x18\xfa\x19 \x19E\x19k\x19\ +\x91\x19\xb7\x19\xdd\x1a\x04\x1a*\x1aQ\x1aw\x1a\x9e\x1a\ +\xc5\x1a\xec\x1b\x14\x1b;\x1bc\x1b\x8a\x1b\xb2\x1b\xda\x1c\ +\x02\x1c*\x1cR\x1c{\x1c\xa3\x1c\xcc\x1c\xf5\x1d\x1e\x1d\ +G\x1dp\x1d\x99\x1d\xc3\x1d\xec\x1e\x16\x1e@\x1ej\x1e\ +\x94\x1e\xbe\x1e\xe9\x1f\x13\x1f>\x1fi\x1f\x94\x1f\xbf\x1f\ +\xea \x15 A l \x98 \xc4 \xf0!\x1c!\ +H!u!\xa1!\xce!\xfb\x22'\x22U\x22\x82\x22\ +\xaf\x22\xdd#\x0a#8#f#\x94#\xc2#\xf0$\ +\x1f$M$|$\xab$\xda%\x09%8%h%\ +\x97%\xc7%\xf7&'&W&\x87&\xb7&\xe8'\ +\x18'I'z'\xab'\xdc(\x0d(?(q(\ +\xa2(\xd4)\x06)8)k)\x9d)\xd0*\x02*\ +5*h*\x9b*\xcf+\x02+6+i+\x9d+\ +\xd1,\x05,9,n,\xa2,\xd7-\x0c-A-\ +v-\xab-\xe1.\x16.L.\x82.\xb7.\xee/\ +$/Z/\x91/\xc7/\xfe050l0\xa40\ +\xdb1\x121J1\x821\xba1\xf22*2c2\ +\x9b2\xd43\x0d3F3\x7f3\xb83\xf14+4\ +e4\x9e4\xd85\x135M5\x875\xc25\xfd6\ +76r6\xae6\xe97$7`7\x9c7\xd78\ +\x148P8\x8c8\xc89\x059B9\x7f9\xbc9\ +\xf9:6:t:\xb2:\xef;-;k;\xaa;\ +\xe8<' >`>\xa0>\xe0?!?a?\xa2?\ +\xe2@#@d@\xa6@\xe7A)AjA\xacA\ +\xeeB0BrB\xb5B\xf7C:C}C\xc0D\ +\x03DGD\x8aD\xceE\x12EUE\x9aE\xdeF\ +\x22FgF\xabF\xf0G5G{G\xc0H\x05H\ +KH\x91H\xd7I\x1dIcI\xa9I\xf0J7J\ +}J\xc4K\x0cKSK\x9aK\xe2L*LrL\ +\xbaM\x02MJM\x93M\xdcN%NnN\xb7O\ +\x00OIO\x93O\xddP'PqP\xbbQ\x06Q\ +PQ\x9bQ\xe6R1R|R\xc7S\x13S_S\ +\xaaS\xf6TBT\x8fT\xdbU(UuU\xc2V\ +\x0fV\x5cV\xa9V\xf7WDW\x92W\xe0X/X\ +}X\xcbY\x1aYiY\xb8Z\x07ZVZ\xa6Z\ +\xf5[E[\x95[\xe5\x5c5\x5c\x86\x5c\xd6]']\ +x]\xc9^\x1a^l^\xbd_\x0f_a_\xb3`\ +\x05`W`\xaa`\xfcaOa\xa2a\xf5bIb\ +\x9cb\xf0cCc\x97c\xebd@d\x94d\xe9e\ +=e\x92e\xe7f=f\x92f\xe8g=g\x93g\ +\xe9h?h\x96h\xeciCi\x9ai\xf1jHj\ +\x9fj\xf7kOk\xa7k\xfflWl\xafm\x08m\ +`m\xb9n\x12nkn\xc4o\x1eoxo\xd1p\ ++p\x86p\xe0q:q\x95q\xf0rKr\xa6s\ +\x01s]s\xb8t\x14tpt\xccu(u\x85u\ +\xe1v>v\x9bv\xf8wVw\xb3x\x11xnx\ +\xccy*y\x89y\xe7zFz\xa5{\x04{c{\ +\xc2|!|\x81|\xe1}A}\xa1~\x01~b~\ +\xc2\x7f#\x7f\x84\x7f\xe5\x80G\x80\xa8\x81\x0a\x81k\x81\ +\xcd\x820\x82\x92\x82\xf4\x83W\x83\xba\x84\x1d\x84\x80\x84\ +\xe3\x85G\x85\xab\x86\x0e\x86r\x86\xd7\x87;\x87\x9f\x88\ +\x04\x88i\x88\xce\x893\x89\x99\x89\xfe\x8ad\x8a\xca\x8b\ +0\x8b\x96\x8b\xfc\x8cc\x8c\xca\x8d1\x8d\x98\x8d\xff\x8e\ +f\x8e\xce\x8f6\x8f\x9e\x90\x06\x90n\x90\xd6\x91?\x91\ +\xa8\x92\x11\x92z\x92\xe3\x93M\x93\xb6\x94 \x94\x8a\x94\ +\xf4\x95_\x95\xc9\x964\x96\x9f\x97\x0a\x97u\x97\xe0\x98\ +L\x98\xb8\x99$\x99\x90\x99\xfc\x9ah\x9a\xd5\x9bB\x9b\ +\xaf\x9c\x1c\x9c\x89\x9c\xf7\x9dd\x9d\xd2\x9e@\x9e\xae\x9f\ +\x1d\x9f\x8b\x9f\xfa\xa0i\xa0\xd8\xa1G\xa1\xb6\xa2&\xa2\ +\x96\xa3\x06\xa3v\xa3\xe6\xa4V\xa4\xc7\xa58\xa5\xa9\xa6\ +\x1a\xa6\x8b\xa6\xfd\xa7n\xa7\xe0\xa8R\xa8\xc4\xa97\xa9\ +\xa9\xaa\x1c\xaa\x8f\xab\x02\xabu\xab\xe9\xac\x5c\xac\xd0\xad\ +D\xad\xb8\xae-\xae\xa1\xaf\x16\xaf\x8b\xb0\x00\xb0u\xb0\ +\xea\xb1`\xb1\xd6\xb2K\xb2\xc2\xb38\xb3\xae\xb4%\xb4\ +\x9c\xb5\x13\xb5\x8a\xb6\x01\xb6y\xb6\xf0\xb7h\xb7\xe0\xb8\ +Y\xb8\xd1\xb9J\xb9\xc2\xba;\xba\xb5\xbb.\xbb\xa7\xbc\ +!\xbc\x9b\xbd\x15\xbd\x8f\xbe\x0a\xbe\x84\xbe\xff\xbfz\xbf\ +\xf5\xc0p\xc0\xec\xc1g\xc1\xe3\xc2_\xc2\xdb\xc3X\xc3\ +\xd4\xc4Q\xc4\xce\xc5K\xc5\xc8\xc6F\xc6\xc3\xc7A\xc7\ +\xbf\xc8=\xc8\xbc\xc9:\xc9\xb9\xca8\xca\xb7\xcb6\xcb\ +\xb6\xcc5\xcc\xb5\xcd5\xcd\xb5\xce6\xce\xb6\xcf7\xcf\ +\xb8\xd09\xd0\xba\xd1<\xd1\xbe\xd2?\xd2\xc1\xd3D\xd3\ +\xc6\xd4I\xd4\xcb\xd5N\xd5\xd1\xd6U\xd6\xd8\xd7\x5c\xd7\ +\xe0\xd8d\xd8\xe8\xd9l\xd9\xf1\xdav\xda\xfb\xdb\x80\xdc\ +\x05\xdc\x8a\xdd\x10\xdd\x96\xde\x1c\xde\xa2\xdf)\xdf\xaf\xe0\ +6\xe0\xbd\xe1D\xe1\xcc\xe2S\xe2\xdb\xe3c\xe3\xeb\xe4\ +s\xe4\xfc\xe5\x84\xe6\x0d\xe6\x96\xe7\x1f\xe7\xa9\xe82\xe8\ +\xbc\xe9F\xe9\xd0\xea[\xea\xe5\xebp\xeb\xfb\xec\x86\xed\ +\x11\xed\x9c\xee(\xee\xb4\xef@\xef\xcc\xf0X\xf0\xe5\xf1\ +r\xf1\xff\xf2\x8c\xf3\x19\xf3\xa7\xf44\xf4\xc2\xf5P\xf5\ +\xde\xf6m\xf6\xfb\xf7\x8a\xf8\x19\xf8\xa8\xf98\xf9\xc7\xfa\ +W\xfa\xe7\xfbw\xfc\x07\xfc\x98\xfd)\xfd\xba\xfeK\xfe\ +\xdc\xffm\xff\xff\ +\x00\x00\x03\xa0\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22?>\x0a\x0a \x0a icon / outl\ +iner / entity / \ +Default - Saved<\ +/title>\x0a Created with S\ +ketch.\x0a \ + \x0a\ + \x0a <\ +path d=\x22M13.6916\ +3,3.24686842 L8.\ +01783965,6.52512\ +131 L2.34404932,\ +3.24686842 L8,0.\ +481790242 L13.69\ +163,3.24686842 Z\ + M7.25035308,7.8\ +2264135 L7.25035\ +308,14.7689324 L\ +1.9912897,11.723\ +6967 L1.9912897,\ +4.79310939 L7.25\ +035308,7.8226413\ +5 Z M14.0326515,\ +11.6884321 L8.74\ +360561,14.776916\ +3 L8.74360561,7.\ +8257203 L14.0024\ +918,4.79949203 L\ +14.0326515,11.68\ +84321 Z\x22 id=\x22Sha\ +pe\x22 fill=\x22#4285F\ +4\x22 fill-rule=\x22no\ +nzero\x22>\x0a \ + \x0a\x0a\ +\x00\x00\x04g\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22?>\x0a\x0a \x0a icon / outl\ +iner / entity / \ +Editor only - De\ +fault\x0a \ + Created \ +with Sketch.\x0a \x0a \x0a \x0a \x0a<\ +/svg>\x0a\ +\x00\x00\x02\x90\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22?>\x0a\x0a \x0a Artboard\x0a \ +Created with Ske\ +tch.\x0a \ +\x0a \x0a \x0a \x0a \ + \x0a\x0a\ +\x00\x00#k\ +\x00\ +\x00\xf0\x80x\x9c\xed\x5c\x07\x5c\x93\xc7\xdf\xbf'\x09\x09\ +[\xb62\xc4\x88\x03\x17#\xcc\x10\x01\xd9CE\x11\x10\ +\xd4\xbaB\xf2\x00\x91,\x930\xc4=\xaaV\xad\x03\xad\ +\x0b\xb7\xd6=\xea^\xad\xd6\x89V\xabu\xb7\xd5\xb6\x8e\ +?\xae*\xe2`\xa3y\xef\x9e$\x10\x14\x15$\x8a\xf6\ +}\xbe\xf9\xdc\x93\xbb\xdf\xdd\xfd\xd6\xddsw\xcf\xb8'\ +&\x06t\x02\x00\xe8\x83\x16\xe0\x15\xa0\xc1\x18\x06T\x07\ +*\xf17\x14\x1e0\xad8\x85\x88\xc3r\x98+FU\ +\xd3aa\x8c\xae\x8eS\xe0\xc1\x5c\xc3'q!f\xa1\ +U\xc6Z\x1dG\xb5m\xb4x6\xd7\x94\x9f\x0d0;\ +\xa0\xa7\x8ac>\x98}u<\x10s\xd0\xe2\xd3AK\ +\x16\x0b\x1d\x81\x13\x8cE`\x1eD\xdc\x0a\xc6\xd3\xb0\xb8\ +\x9a\xf2\x94\x1f\xd1\x91\xb3\x16&GM<\x08\x18\x90\xde\ +\x0c\x00\x7f\xa7\xc9\xd1\x88n\xea\x08\xe3\x1eS\x04\x1a\x1d\ +\xee.\x9c\x22Ge\x8c\xa3\x00\xe8\x1e;w \x8a\x1b\ +\xec\x83\xf4\xe3\xc8/\xd0O\xaa\x9fa\xd58\x00\x9c\xcd\ +4\xff\xc1|I2\xce\x8cM\x93($\xf24\x89\x94\ +\x19\x1a\xca\xf4pg\xf92;$\x09\xc4|I\x96\xbc\ +#@I\x8e\xbb\x07\xc7\xdd\x93\xc9\xf2\xe1x\xf8p\xbc\ +X\xc0\xbf[\xb6\x94\xcbK\xc7\x15\xccda\xb8\x9c'\x13H\x15\x02\x89\x98\x89\ +\xd2\xdcdI\x86\x22\xc0\xc9\xc9\x90\xa9\x05\xb5]\x22i\ +\xb5 \xb1\xdc\x95\xb0\xd1\x95'\x11\xb9es\xa5n,\ +Ww\xb7\xba*\xf1y\xd5u\xa4\x192!\xa1\x1a\x9f\ +\xe7\x86\x0bq\x11.V\xc8a=V\x9d\xf5\xa4\x9a\xb6\ +\xab[du\xf6[\x05Cmcb\xde\xad\xafHT\ +gM\xb9\x22\x9f\xef\xc3\xe6\xe1P\x0b\x1cOv\ +\xf1\xf3\xf3rwa\xb3y\x9e.\xbe\xc9\x1e\xde\xc9\xc9\ +\x1e8\xd7\xdd\xc3\x8bh\xcb\xda\xd5\xdf`\xad\x91\xaef\ +M\x98\xca\xf3\xf4\xc0}\xfd\xd8.)\xfc\x14\x96\x8b\xb7\ +\x9f\x17\xdf\xc5\xcf;\xc5\xcf\x85\xeb\xe5\xc3\xf2e\xf9&\ +\xfbp\xb9\xbe\x1a\xd6Z\xd5\xdf`\xdd[&\x80\xa31\ +W\xd8H\x11u\xb0yCT\x94\x00ynD\x1dm\ +\x1b\x8f\x0f\x7f[\xdb\x12\xe3\xa6\x94+\x93\xe3hT\x08\ +p\xd2\x0c\x0bNoT@u\x88\xd1\x85\xc3\xe5\xa1\x11\ +7\x90G\x9c\xf8\xb0\xc1kQ\xdf^M\xf0f\x03\xd6\ +\xcf\x05oT\x7f\xbb\x8c\xac4\x5c\xfc\xae\x01K\xab\xd4\ +\xdb\x99\xc8%)\x8a,\xae\x0c\x0fN\x85\x9e\xae\xcfh\ +QW\xb57\xfc]\xe7y\xa1\x93\x86\x90s3\x1b\xd7\ +\x0c\x9e)\xbe>\xc98\xcb\xc7\x85\xcd\xe7y\xb8p\xd9\ +^\xb0\x05\x90\x0f}\xbdY\x9e\x9e\xbe\x1e\x5c/\x16\x8b\ +\xdf\xb8f\x80m\xc0\xd2\x1a\xad\x9b\xae\x19j\xd8\xf3\xd2\ +\xb8\xe2T\x9c\x1f\xe8\xa6\xa9\xa8!|I-W\xbf\x11\ +\xb0\x91-\xe7\xf3\xdfj9\x15\xb5\xf6\x98\xa8\x19g_\ +\x1bCUE\xb5\x96\x99\xaa5\xac\x9bz\x11\x0b\xd7\xcf\ +n\xd5\x0b\xe8\xba\x14\xd6=H!\xa4\x10R\x08)\x84\ +\x14B\x0a!\x85\x90BH!\xa4\x10R\x08)\x84\x14\ +B\x0a!\x85\x90BH!\xa4\x10R\x08)\x84\x14B\ +\x0a!\x85\x90BH!\xa4\x10R\x08)\x84\x14B\x0a\ +!\x85\x90BH!\xa4\x10R\x08)\x84\x14B\x0a!\ +\x85\x90BH!\xa4\x10R\x08)\x84\x14B\x0a\xd1\xb1\ +\x10\xc3\x9a-\xa9\xb8\x98\x1f\xe0\x94\xe5\xd4-\xd0\x01\x1b\ +\x00\xa8\xf6\xed\x22\x1d(\x80\xd8`\xcb\x0e\x89\x8e\xa1\xb5\ +#v\xc3\x9a\xfdz\xbeb\xf4\xfa\xfcC\x06z\xd2\xcc\ +\xad\xdb\xf4\x8e\xf5\x22\xf28D^\x01\xca\xd7\xec'\x06\ +FR\x99@\xac\xe8\x9d\xa1\x90f(`\x12m\xec\x05\ +\xb1rE|\xb2D\x22$JD\x8b\x158.\xce\x10\ +i\xe2\xe8?T(C\xe9fD\xddxA6*\x11\ +\x22P\xa0:5\x8f\xf0\x85\ +\xca6\x8a:E\xa9\x95rW\xe9\xa8\xf6\xb5\x0b\x91\xa2\ +\x13\xfe\xb0%(\xfa\xea^A\xb4\x0d%H\x15\xd4u\ +\x1dk\xb7\x0c\xcd\x0e\xc5\xa8\xde\xd5\x96\xab0T\x1dT\ +\xdey\x13\xda4\xed\xb2u\x16\xd0\xa0fp\x03\xe2\x0c\ +\xa1Pe\x10\xa0'K2\xc4|\xf9kc\x0bO\xc1\ +\xd2\xa8\x89NH\xad\x93\x01\xbcv\xd6\x80\x90\x9a\xb3\x8b\ +P#\xae\xe6\xe4Ai\xba\x5c(\xe0\xe1\xf2DaO\ +t\xfac\xb5\xe4\xe8\x11y0b\x01\x03\x83HD\x87\ +i\xf1f\xa4\xca$\x19\xd2Z$\xba\x84\xd8\x97\xab\x19\ +\xd9\xc3\xe3Q%\xd5^]\x986\xe1f($\x91\xb8\ +\x18\x97\xa1}\xb2\x84\xf6#\xa4\x9a\x89\xc9PU\x18Q\ +PN\xb4(\x95\xf9\x09\xec\xa7f\xc8\x84\xb5\xa67\xc2\ +\xf9\xb5)1\xf2\xd4\xdaS \x9d+T$pSk\ +\xd1Ly8\xac\x87g+\xa2\xe5Q\x091=5\x83\ +\xac\xbe\x86\x5c\xab\xb0A\x9aD\x96\x13,\x14\xa4j<\ +\xd5Le|\x94\x86\x8c\xbc\xcb\xc7S\xb8\x19\xc4(k\ +\x90\x89\xcb\x14u\x14O\xd4\x90k\x177JN%\xf6\ +\xd1k9\xd7\x5cU!$\xb2:\x03\xa9\xd1K\x22F\ +\xff\x06\x0a\x89\x14N\xa5r\x5c\xdbq\x86B\xe8\xc87\ +\xa8\xc6\xc9\xc4p\xfd\x06\xddH\x86\x06\xe5\xd7\xc8\xc4\x19\ +\xd4AU\x0f\x06J\xb7\x22PC\xb7\x22\xa2\xa8\x09U\ +g\xa51\x91\xdc\xa9v\xd1PU\xc0`\x17@g\x02\ +m\x01h\x010\xe5\xef\xca\xc7\xc0\x98\xd8=9$4\ +\x06\xa6\x0b\x81)\x91\x02\xfcq\xa8\x9e\xf2:\x98\x04\x8c\ +\xf5\xf5\xf5\x0d\xf4\x8d\x0d\x0c\x8c\xcd\x8d\x0c\x8d\xcc\xad\x9b\ +\x19\x1b7\xb3naiimi\xd9\xc2\xdc\x98\x80\xfa\ +\xafn`&FF&\xa6&f\xa6\xa6fV\xa6\xa6\ +\xa6V\xe8`j\xa5\xaab^\x1f\x06\xca\x9f\x81\xb9>\ +T~(\x15s\x02\x14s\x8cj\x8e)\xff\x82\x86\xd2\ +\x95\xc7\xb1nPK=\x8c\x80\xdaqT\x80Qhz\ +t\x86\xbe\x81\xa1\x11\xf6z&\x06(TM\xa6\x19\xc0\ +h\x18\x95B\xa3\xe81\xe8\xfazTcO\x98iN\ +\xa5\xb5\xb6`\xe9\x05\xf7\xe1Z:\x0d\x1f\xefA\xb7\x9a\ +\xb3r{H\x9b\xb6\xd6qG\x92=\xbdd\x13.\x84\ +2\xda\xe5\xc6\x17\xddz\xca\x93{\xdb\xac\xda1\xb1}\ +\xd8\xdc\x04~\xf8\xd1\xd5\x0a\x9f\xe6\x17\xfb\xde\xc6\x9f\xed\ +\x9ct\xecR\xc6\x9d\xe7\x11\xce\xf3\xd6|\xbd\xeb\xbb\xe3\ +\x97\xff\xf7\xe2\xfb\xdd'\xae\x14\x14'\xa6dN\x9e\xbf\ +v\xcf\xc9\xabwK|#\x93R\xb3\xa6,X\xb77\ +\xff\xda\xbdRs@\xa1@mi\x84N\x0c\xba\x9e7\ +\xa1Bk\x96\x05\x0dj0\xdc\xc9R\xcfc\xfc\x1c+\ +\xa4\xc1\x91\xb8\x0bE\x9em\x93o\xc9&\xe4\x86\xc6[\ +\xf3\xe4^O\xdb\xd1\x91\x02\x8c\xf6\xdeG/B%V\ +7\xe7\x87\xf7\xf5Q\xe0\xb7\xabUx\xbb\x06\xce5*\ +(\xff\x04\xc6TB\xa69\xe8\x06\x8a\x13r\xa3\xdbu\ +l\x9b\x1b\xdd=\xbamn\x5cnt\xdbyk\xd4\x84\ +\xde\xca\xdf\x8a\xfb\x1a\x89\xf0\xbey\x8e\x0a\xc3a6\x89\ +g\xfa\xf5{\xba\x7f\xdd\x8e\xeei\x17\xae\xb4?\xeaj\ +vq\xf4\x9a\xcc\xb2- \xd8\xc2x\xe2\x91~\xe5\xd9\ +n+\x0a%\x07\x0e;\xde\xa98\xbd}\xa7(\xbf\xe4\ +\xa5\xcf\x98\x07\x8f\x8b\xa2{\x9df\x1aph\xcdSn\ +\xffp\xe4\x87Q\xbb\x95`C\x7f\xdf\x82A#\x16\x1c\ +\xec\xf5\xabC\xeb\xb6\xebD\xfb\xf7ms\xef\xd2*\xa0\ +\xdb\xc39\xe3iQ\x97]G\xd8\xcc\xd8\xb4\xde#_\ +\xf0\xd7\xbaI\xf3\x0a\xd7l\xba}7i\xb6W\xc9\x8f\ +\xb2\x7f\x0a\x13-\x08\xcd\x94@y\x81\xd0\xd7\xfb\xb9G\ +^\xf8\xf0\xd5\xcb\x1e\xdb]\xaaJ\xecx\xc5\xd2\xe9\xde\ + \xf9\xb2\x91K\xfd\xa7\xf0\xbd\xe6}\xbfn\xe2`\xeb\ +\x19\x17V^m\xb6\xa6\xd5\x86\xbeO\x8bF\x8f\x92\xf3\ +z\xfa\xb3\xc75\xa3\x85l\xb3\xb9\x90\x9a\x19\xb0\xa1\xa3\ +\xebH\xbb\xb3\xebv\x8f\xf3^\xe5egJ\xd9\xfa\xed\ +\x933\x07z,\xbe\xb6\x0f\xdb:\xee\xe7\xaf;\x17\x89\ +W\xe6\xfd= \xec\xe4\x94\x97\xdft\xa4:\xdee\xfb\ +\xadu`wNm\xd6q\xbf\xf5\xbf\xdf\x7f[\x11Z\ +\xb69\xa1\xe7\xc8\xa51\xbff?\xcax\xde\xf2b\xfc\ +\x8fP\xadu\xca\x8b\x84R\xec\x11\x0a\xce\xf4%\x97^\ +\xf4\xda\x12\x18\xd5Y\xeel\xbb\xc8\xfaq\xe6\xccV\xe1\ +\x7f\xeb%_\x8f\x7f8\x82w\xdc,w\xa9\xe9\xdc\xa1\ +]F\x0f:r#\x90\x11\x9e\xeel\xf3\xe3\xe4c\xbb\ +\xa4\x15\xae\x0e_O\xef;k\xc3\xadG\xee7w=\ +|8o\xdf\x98\xd96]\x0fKs\x97\xfc\xfb\xf4q\ +\xfe\x98k\xdfveK\x13\x96/\x10\xcd3\x1cR8\ +\xb1\xf5_/\x1em\xfd_\xb1q\xd2\xd5~\xf6\x0f\xcf\ +\xcf\x9c\xa8\x04mwZ\xc4\xcd\xd9\xde\xc1\xf7\xc6\xd5Y\ +\xab\xbc\x87?\x0b\xfe\x8a\xed}\xf1\x17l}\xe1\xf25\ +\x85\xcfr\xf3`+v\x1f\xab\xbc\xa4jb\xc3\xaa\x9c\ +')\xd7fM\x9c\xd2\xda\xba\xed\xbc;C\xc6\x8f\x8e\ +\x18\x10\x10\x91\xbd\xb7lw\xe2 \x8b\xe9\x9b\xb6(A\ +\xf4\xb7Y\xc7)\xb9\xcbF\xf7_M\xa9\xec\xb9/G\ +\xf84\xabh\xd85Q\xc6\xce\xfb\xdb\xb7\x94\x01\xab\xdc\ +\xf8Es/\x19\xd9\x1f\x980\x88z\xe3\xd2\xf9\x13\x1b\ +\xbfo~=\xb4\xd4=\x7fzo\xc6\xed\xbd\xdf\xf5\xdc\ +L\x1f\x9c\xb5\xf3\xf7W\xf7\xb6GG\x0f\xdf\xd1\x7f\xf6\ +\xaf\xbf\x9aE\xccdl\x8f\x88]\xbb6\xbe\xdf\x96\x89\ +\xc1e\xe5\x1b\xd6\xacS^~W_\xfbC5\x9e\xb5\ +&\xce\xd8A\x80Xy\xa0\x8f \x05\x03>\xbc\x18J\ +\x86\x0bC&\xbc4J\x83q\x05\x0cr\x22\x86.\x83\ +\x9a\xbf\xa7\x04\x13\x84\xc2\x1f\x13.\xc7\xdc\x01\x0b\xf8\xaa\ +\x07F\xe3\xa8\x9e\x02\xb1\x84\x02\x17\x0b\x22x\xfd\x81\xbe\ +\x81\xd2\xaf\xff\x00&\xe3\x1c\x5c,\x18\xc05\x0a\x9c\x16\ +\xb9<\xb94&>\x22\x81\x98D\xc3C\x99\xe8C)\ +\xa0\x16J\xae\xaa\xa6\xa1K.Q\xb1L&h\x18\xcc\ +yR\x19\x9cd\xb0X\x18\xf7\xe4\xe3r8-c\x93\ +`\x5c\x98\xa5\x90\x22:\x1a\xe3\xad\x92\xd3Q\x9c\x82F\ +w+\x19T\x10\xc6[\xa0x\xaa*\xde\x85(\xa3\x8a\ +\x07\xa18_$\x86\xcb\x01\x0a\xd2Y\xca\x17\xf1Q\x1c\ +}\x11jjf\x06Z&P{\xc2\xf8\xe4L\x01\x9e\ +\x05\xe3\x97a\xbc\xad0C$\x80q\xb4\x02\xb5\x12\xe1\ +\x5c\xb8t!\xe6\x8f\xb6\x0a\x9c\x97\x06\xe3h\x05h,\ +K\x88\x83W24\x7f8\x07\x1b\xa7j\xc5\x93\xb5\xe2\ +\x0a81#\xa3B%\xd2\x11\xc4\x0c\xc6\xec\xc0\xeb\xc8\ +d\xf9\xf9\xb1\x99Qx\x96\x10W(\x5cb\xe1\x05;\ +W\xc6g\x86JDR\xae\x18\xae\xefU6\x13\xb0x\ +\xe3#4Z\x8ezgf=\x81\xdaV\x15{\xde\x87\ +h3\xcc\xe6l\x0d\xad\xaer\x92Up~\x85\xab}\ +\xea\xec\x1aZ\xf2\x22\x00\xf6~\x0d@\x8b?khm\ +W\xc0>\x0a\xdbm\xcfy-{lP\x7f\xd1\xfa\xf8\ +\x94\x00\xe7\xb9\x22\x87V\xe3\xbd\x05\xea\x01-y\xae\x88\ +]\xb5{\x98a\xaa\x15\x0c\x13\xf9\x8d\x07\xd7)\x192\ +&\xbc\xfe\xe2\xe1L\x97\xd7;\xf1\x07W\xac[\x8f.\ +qx\x0a\x8e\xae\xf3pf\x22\xece\xf02\x156\xb7\ +\x98/ \xbe\xa3%\x10\xbf\xad\x11?\xb0\xdakP\xf5\ +k\x08\xcb5\xaf\x80\xd5\x10W`v\xde\x0aP\x1f\x9f\ +\x054K#@\x1d\xb8\x0c\xe6`\xd5\xed\xd6\xd3 \x11\ +\xa03/\xa9\xd5=U\xbf'P\xc7\xe5\x04e\x16:\ +\xc8\x05\xc4\x22\x1a\x84\xc6%0y\x19\xb2LU\x1e\xb1\ +n\xd6\x83\xd7\x88\xcd\x80\x15\xb0\x85\xd7\xb3m@\x07x\ +u\xe7\x01\x07\x99\xae \x08\x84\x83\xee\xa07\xbc\xbe\xed\ +\x0f\x06\xc3+\xda4 \x82W\xb7Y`\x14\x18\x0f&\ +\x83\xe9`6\xf8\x0e,\x06\xcb\xc1\x1a\xb0\x01l\x05;\ +\xc0^\xf0#8\x02N\x823\xe07p\x05\x5c\x077\ +A\x01\xf8\x17\x14\x81\x12P\x09\x172\x0c\xcc\x04\xb3\xc4\ +l\xb1VX;\xac3\xe6\x81\xb1\xb1@,\x1c\xeb\x89\ +\xc5a\xfd\xb1\xa1X*&\xc62\xb0Q\xd8Dl:\ +\x96\x8b-\xc6Vb\x1b\xb0\xed\xd8~\xec\x08v\x1a\xbb\ +\x80\xfd\x81\xdd\xc2\x1e`\xcf\xb0\x0a\x0a\x95bL\xb1\xa2\ +\xb4\xa4\xb4\xa7\xb8Q\xd8\x94`J\x0fJ\x02e\x10%\ +\x952\x9c\x92C\x99D\x99IYHYE\xd9L\xd9\ +C9B9C\xb9B\xb9I\xf9\x97RL\x05T#\ +\xaa\x0d\xb55\xd5\x85\xca\xa6\x86R{S\x07PS\xa8\ +2\xea\x18\xea4\xea|\xea*\xeaV\xea\x01j>\xf5\ +\x12\xf5&\xf5\x11\xb5\x9cF\xa7Y\xd2\x984\x17ZW\ +Z\x14\xad/\x8dG\x1bN\x1bC\x9bA[L[O\ +\xdbC;N\xbbD\xbbE+\xa2\xbd\xd23\xd1s\xd0\ +\xeb\xac\xc7\xd1\x8b\xd6\xeb\xa7\x97\xaa\x97\xa57Yo\xbe\ +\xdeZ\xbd\xddz'\xf4\xae\xe8\x15\xe8\x95\xd0\xe9t\x1b\ +\xba3\xdd\x97\x1eE\xefO\x1fF\x1fI\x9fA_J\ +\xdfF\xff\x99~\x81~\x87^\xcc`0l\x19\x9d\x19\ +\x01\x8c\xde\x0c.C\xc1\x98\xccX\xc4\xd8\xcc8\xcc\xb8\ +\xc8(`\x94\xe9\x1b\xe9\xb7\xd2\xf7\xd0\x8f\xd0\x1f\xa0/\ +\xd6\x9f\xa0?_\x7f\xa3\xfe!\xfd\x8b\xfa\xf7\xf4+\x0d\ +\xcc\x0c\xda\x19p\x0cz\x1b\xf0\x0dF\x18\xcc2Xc\ +p\xc0\xe0\xbcA\x81A\xa5\xa1\xb9\xa1\xb3a\x80a\x82\ +\xe10\xc3\xf1\x86\x0b\x0d\xb7\x1a\x9e0\xbca\xf8\xdc\xc8\ +\xc8\xc8\xc9\xc8\xcf\xa8\x8f\x91\xc0h\x9c\xd1B\xa3\x1f\x8c\ +N\x19\xdd2*7\xb60\xeed\x1cj<\xd08\xc3\ +x\xa6\xf1:\xe3\x9f\x8d\xff0~nbb\xd2\xde$\ +\xc8d\x80\x89\xc2d\xa6\xc9\x06\x93c&\x7f\x9b\x94\x99\ +Z\x9a\xba\x9aF\x9b\xf2M\xc7\x9a\xe6\x99\xee1\xbdh\ +Z\xd8\xcc\xa0Y\xbbf\xc1\xcd\x067\xcbi6\xbf\xd9\ +\xcef\xe7\x9b=230ko\x16j\xc65\x1bc\ +\x96g\xb6\xdf\xec\x9aY\xb1\xb9\xa59\xcb\xbc\xb7\xb9\xc8\ +|\x86\xf9F\xf3\xd3\xe6\xf7-\x18\x16\xed-\xc2-\xf8\ +\x16\x93,V[\x1c\xb3\xb8cI\xb5lc\x19j\xc9\ +\xb3\x9ch\xb9\xc6\xf2\x84e\x81\x15\xdd\xca\xd9*\xdaj\ +\x98\xd5t\xab-V\xe7\xac\x8a\xac-\xac\xbd\xac\x13\xad\ +\xb3\xad\xf3\xac\x7f\xb2\xbeiC\xb5io\x13m#\xb4\ +\x99e\xb3\xc3\xe6\xaaME\xf3\x96\xcd\x83\x9b\xe3\xcd\xbf\ +i\xbe\xb5\xf9\xc5\xe6\xa5-\xec[\x04\xb5\xc0[Lk\ +\xb1\xad\xc5\x95\x16\x15\xb6L\xdbp\xdbt\xdb9\xb6{\ +m\xff\xb2\xa3\xd9u\xb2\xebc\x97e\xb7\xcc\xee\x84\xdd\ +#{+\xfb\xae\xf6<\xfbi\xf6;\xec\xfft\xa08\ +tr\x88s\x18\xe9\xb0\xda\xe1\xacCqK\xc7\x96\x91\ +-\xa5-\x17\xb5<\xd6\xf2\x91\xa3\x8dc\x90\xe30\xc7\ +y\x8e\x87\x1c\x1f\xb4\xb2l\x15\xd8J\xd0j^\xab\xc3\ +\xad\x1e2\xad\x99\xc1L!s!\xf38\xb3\xa8\xb5C\ +\xeb\xa8\xd6\x19\xadW\xb6>\xd7\xba\xd2\xc9\xd9\xa9\xaf\xd3\ +\x04\xa7mN\x7f\xb51l\xc3n\x93\xd2f^\x9b\xa3\ +m\x8a\xda\xb6j\x1b\xd3vT\xdbMm\xfflg\xd0\ +\x8e\xdd.\xad\xdd\x82v\xf9\xedJ\xdb;\xb7Oj?\ +\xa5\xfd\xde\xf6\xf7\x9d[8G;\xe78or\xbe\xd1\ +\xc1\xa4C\xb7\x0e\xc3;\xac\xeap\xb9#\xbd#\xbbc\ +z\xc7\xa5\x1d\x7f\xebD\xe9\xe4\xdd)\xadS^\xa7\xf3\ +\x9d)\x9d}:\x0b:/\xed|\xa1\x8b^\x17\xbf.\ +\xe2.\xab\xba\x5cs1v\x09v\xc9t\xd9\xe4r\xcb\ +\xd5\xc6\xb5\xa7\xeb\x04\xd7\xbd\xae\x85nm\xdd\x06\xb8\xcd\ +q\xcbw{\xe5\xee\xed.t_\xe3~\x9de\xc1\xea\ +\xce\x9a\xc0:\xc0z\xe6\xd1\xc9\x83\xe7\x91\xe7q\xd9\xd3\ +\xc43\xc2s\xac\xe7>\xcf\xa7^\x9d\xbdp\xafe^\ +\xbf{[z\xc7xO\xf1>\xea\xfd\xd2\xc7\xd7G\xe6\ +\xb3\xd5\xe7\x81o[\xdf\xa1\xbeK|\xaf\xb1\xad\xd8\xb1\ +\xec\x19\xecS~z~!~c\xfd~\xf4+\xe7\xf8\ +p\x14\x9c\x1d\x9c']]\xba\xa6w\xdd\xd8\xf5\xbe\xbf\ +\xb3?\xee\xbf\xc6\xffN\x80S\x007`e\xc0\xcd@\ +f\xe0\xd0\xc0\x15\x817\xbb\xb5\xee\xc6\xed\xb6\xaa\xdb\xed\ +\xa06A\xfc\xa0\xb5A\xf7\x82;\x06\x0f\x0b\xde\x1c\x5c\ +\x18\xe2\x1e\x22\x0b\xd9\x1dR\x1a\xca\x09\x1d\x1d\xfas\x18\ +5,2lZ\xd8\xb9p\x8b\xf0\xbe\xe1\x8b\xc3\xff\x8e\ +p\x8aH\x8d\xd8\x14Q\x14\xe9\x1d92\xf2\xe7(\xbd\ +\xa8\x1eQs\xa2\xaeE\xb7\x8c\xe6Eo\x88.\xea\xee\ +\xdb}t\xf7\xe3=\x8c{\xc4\xf7X\xdc\xe3v\xcfN\ +=e=\x0f\xc4Pb\xba\xc7\xcc\x8d\xb9\xd1\xab]/\ +q\xaf\xbd\xbdA\xef\xe8\xdes{\xff\x15\xeb\x1c;<\ +\xf6`\x1fz\x9f\xd8>y}\xee\xc6\xb1\xe2F\xc5\xe5\ +\xc7[\xc6\x0f\x89\xdf\x18_\x92\x10\x920+\xe1z\xdf\ +\x0e}3\xfa\x1eMl\x9680qCbiRX\ +Rn\xd2\xcd~n\xfdF\xf7;\xd3\xdf\xae\xbf\xa0\xff\ +\xbe\x01\x8c\x01\x89\x03\xd6\x0e(\xfe*\xfc\xab\xef\xbe*\ +\x18\xe8=p\xf2\xc0\xab\x83\x9c\x07e\x0f:=\xd8n\ +\xb0p\xf0OC\x9a\x0d\xe1\x0e\xd99Toh\xd2\xd0\ +\x8dC\xab\xb8\xbd\xb9\xab\xb8\xc5\xc9\xd1\xc9K\x92\x8bx\ +\xa1\xbc\x05\xbc\x7f\xf9A\xfcy\xfc\x07x\x00\x9e\x8b\xdf\ +K\x09H\xc9M\xb9\x9f\x1a\x90:7\xf5AZ\xb7\xb4\ +\xf9i\x8f\x04\xa1\x82\xc5\x82\xa7\xc3\xa2\x86-\x1fV\x9a\ +\xde;}]\xbaR\x98$\xdc&\xd2\x17\x0d\x15\xed\x17\ +[\x88\xd3\xc5\xc7%\x8e\x92l\xc9\x05ig\xe9d\xe9\ +\xcd\xe1\x9c\xe1\xdf\x0d/\x92\xf5\x90\xad\x95c\xf2A\xf2\ +}\x0a+\xb8\x98:\x9b\xd1!\xe3\xeb\x8c[\x99\x81\x99\ +y\x99eY\x89Y;\xb3\xcd\xb3\xc5\xd9gGt\x1a\ +\xf1\xcd\x88{9\x119\xdf\x8f\xa4\x8d\xe4\x8d<:\xaa\ +\xf5\xa8\xf1\xa3n\x8d\x0e\x1e\xbdr\x0c6&y\xcc\xd1\ +\xb1m\xc6N\x1a[0.r\xdc\xfa\xf1\x86\xe3\xd3\xc7\ +\xff:\xc1}B\xee\x84\x17\x13\x93&\x1e\x98\xd4r\xd2\ +\xb8Iw\xbe\x8e\xfcz\xd3d\xd3\xc9\xb2\xc9\xd7\xa6t\ +\x9d\xb2|*m\xaa`\xea\xb9o<\xbfY\xf4\xcd\xab\ +i\xfci\xbfLw\x9f>\x7fz\xd5\x0c\xde\x8c_\xbe\ +e}\xbb\xf0[\xe5\xcc\x94\x99\xe7f\xf9\xccZ6\x9b\ +>[<\xfb\xea\x9cns\xd6\xe7\x9a\xe7\xe6\xe4\xde\x99\ +\x1b3w\xcf<\xe6\xbci\xf3^|7\xe4\xbb\xd3\xf3\ +\xbd\xe6/_`\xb8 c\xc1\xcd\x85=\x17\xee[\xd4\ +v\xd1\xecEU\x8b\xd3\x16_\xc9\x0b\xc9\xdb\xb6\xc4a\ +\xc97KJ\x97\xf2\x97^\x5c\x16\xb4l\xeb\xf2\x96\xcb\ +\xa7/\xafX!X\xf1\xfb\xca\xc8\x95{V\xb5_5\ +\x7f5}u\xe6\xea\xbbk\x12\xd7\xe4\x7f\xcf\xfe~\xc3\ +Z\xbb\xb5\xd3\xd7\xbe\x5c'^ws}\xdc\xfa\xe3\x1b\ +|7l\xd8\xe8\xb0q\xd6&\xca\xa6\x8cM\x0f6\x0f\ +\xdc\xfc\xdb\x96\xb0-\xfb\xb6\xbal]\xb9\xcdf\xdb\xf4\ +\x1f\xc0\x0f\x19?<\xdc>t\xfb\xd5\x1d=v\x1c\xdd\ +\xc9\xde\xb9uW\xbb]Kv[\xee\x9e\xb6\x07\xdb3\ +bO\xd1\xde\xb4\xbd7\xf7\xf5\xdfwa\x7f\xf7\xfdG\ +\x0ft=\xb0\xfb\xa0\xeb\xc1u?\xb6\xfe1\xef'\xeb\ +\x9ff\x1d2<4\xe9\x90\xf2p\xce\xe1\xe2\x9f\xa5?\ +?:\x92z\xe4\xce\xd1!G\xaf\x1f\xebw\xec\xf2\xf1\ +>\xc7\xcf\x9d\xe8q\xe2\xd4\xc9\x88\x93\xc7\xf2\x83\xf3\x0f\ +\x9f\x0a8\xf5\xe3i\xce\xe9\xfd\xbf\xb0\x7f\xd9{\xc6\xe7\ +\xcc\x9e\xb3\xdegw\xff\xea\xfd\xeb\xees>\xe7\xf6\x9c\ +\xf7=\xbf\xef7\xbf\xdf\x0e\x5c\xf0\xbfp\xe8b\xb7\x8b\ +G.\x85]:y9\xfa\xf2\x99+\xbd\xae\x5c\xb8\xda\ +\xf7\xea\xef\xd7\x06^\xbb\xf9;\xff\xf7\xfb\x7f\x08\xffx\ +\xfag\xe6\x9f\x95\xd7\xc7\xdd\xd0\xbb1\xed/\xb3\xbf\xe6\ +\xff\xed\xf0\xf7\xaa\x7f:\xfe\xb3\xed\xa6\xcf\xcd\x9fn\x85\ +\xdd:{;\xfe\xf6\xf5;\xbc;\xff\xfeO\xfe\xbf\xaa\ +\x82IwM\xee\xce\xbf\xd7\xea\xde\x86\xfb\x1e\xf7\x7f|\ +\x10\xf1\xe0\xb7\x87_=,\xf8W\xfao\xe5\xa3\xc9\x8f\ +\xcd\x1f/)\xecP\xb8\xebI\xd0\x93\xb3E\xfd\x8a\x0a\ +\x9e\xca\x9e*\x9f\xcdxn\xfb|\xdd\x0b\xaf\x17G\x8b\ +c\x8b\xff.\x11\x95T\x96N+\xb3-[_\xce.\ +\xcf\xafH\xaa\xb8W\x99U\xc5\xa8Z\xf8\xb2\xe3\xcb\x03\ +\xafz\xbc\xba\xa1\x14U\xdf\x8f&A\x82\x04\x09\x12$\ +H\x90 A\x82\x04\x09\x12$H\x90 A\x82\x04\x09\ +\x12$H\x90 A\x82\x84\x1a\xb1\xb1\xb1\xfc\x9c\x9c\x9c\ +\x85zzz\xf4\xf7\x97&\xa1K\xb8\xba\xba\xfa\xe5\xe7\ +\xe7\x97\x9f={V\xb9l\xd9\xb2\x13VVV\xb6M\ +\xad\xd3\xff\x17\xd8\xdb\xdb;\x1d>|\xf8\x09\xf2\xbd&\ +\xec\xdd\xbb\xb7\x00\xb5IS\xeb\xf6_\x07\x1ak\x0e\x1e\ +<\xf8P\xdb\xf7\x9ap\xf2\xe4\xc9\xb2\xb8\xb8\xb8\x94\xa6\ +\xd6\xf1\xbf\x8cE\x8b\x16\x1d\xae\xcb\xf7\xda\x01\xce\x09\x8b\ +\xe8t:\xa3\xb1\xb2\xac\xad\xad\xed\xc2\xc2\xc2\xfa\x0a\x85\ +\xc2)s\xe7\xce\xdd\xb7q\xe3\xc6+\xfb\xf6\xed\xbb\x0b\ +\xdb\xb9\x14\x05\x14\xdf\xb4i\xd3\xd5y\xf3\xe6\xed\x17\x89\ +DS\xc3\xc3\xc3\x13Q\x1d]\xd8\xf99\x22))I\ +\xf4>\xdfk\x02\x9a\x13>\xc4\x17666\xf6C\x86\ +\x0c\xc9Z\xbe|y\xfe\x993g^\xd5W\x9e&\xa0\ +:+W\xae<=t\xe8\xd0\xec\xe6\xcd\x9b\xb7\xfc\x18\ +~h*\x8c\x1c9rqC|\xa1\x9e\x138\xf5\xe1\ +\xed\xe2\xe2\xc2\x9e\x16X,V\xc0\x81\x03\x07\xee7\xc4\xfe\xd7\xe7\ +\x044\x8f\xa31\xe2\xd8\xb1c/>\xb6\xef5\xe1\xf8\ +\xf1\xe3\xc5\xc9\xc9\xc99\xba\x98\x9b\x9a\x1a\xa8\xdf\xa2q\ +\xb6!\xf6k\xe6\x046\x9b\x1d\xb1u\xeb\xd6?>\x95\ +\xdf_\x0f\xdb\xb6m\xbb\xce\xe1p\xa2\x9a\xda\x87\x8d\x05\ +\xecG\xfac\xc6\x8cY\xd6\x10\xdb\x8f\x1e=\xfa\xbc\xa9\ +\xfc\xfez@k&\x0aDS\xfb\xb1\xb1h\xe8\x9c\xf0\ +9\x85\xdc\xdc\xdc\xbd&&&fM\xed\xc3\xc6\xe2C\ +\xe6\x84\xcf%\xa0\xf1\xc8\xc9\xc9\xa9sS\xfb\xb0\xb1\xf8\ +\x909\xe1s\x09h\x5c\xf4\xf5\xf5\x0doj\x1f6\x16\ +\xea9aiS\xfb\xf3C\x02\xba\xa6\xfe/\xb4\x01B\ +ff\xe6\x5c]\xf9\x05]\xc7)\x14\x8a9h\xcd\x02\ +\xc7\x89N\x86\x86\x86&0\x18;::\xb6\xdf\xb3g\ +\xcf\x1d]\xb7\x01Z\x9f5\xb5\xff\x1a\x03??\xbfH\ +dGc}\xb1s\xe7\xce\x9b!!!\xf1\xefZ\xa3\ +\xa0\xb1\xfbc\x9c\x07\xc8\x86O\xe93]\xa1S\xa7N\ +\xde\xe8:\xa7\xb1>@\xcfu\x18\x0c\x86\xc1\xfb\xe4}\ +\x0c\xff\xa3\x80l\x80\xb6x}\x0a\x9f\xe9\x0a\xe8\xfa~\ +\xff\xfe\xfd\xf7ta?\xba\xb7Y\x9f\xfb6\x1f\xcb\xff\ +( [\xbe\x94{xFFF\xa6\x1b6l\xb8\xa4\ +K\xfb\xd1\xf3\xb5\xb8\xb8\xb8\xd4w\xc9\xfd\x98\xfeGa\ +\xdd\xbau\x17\xd0|\xf3\xa9\xfc\xf8!@\xdfk\x9a=\ +{\xf6\xae\x8f\xe5\x03t\xdf\xf5m\xf7l>\xb6\xffQ\ +\x989s\xe6v\xadoR}v\xe0\xf1x\xa3>\xb6\ +\x0f\x96-[v\x12=\x1bx]\xf6\xa7\xf0?\x0a\xe8\ +\x99DS\xf8\xf6}pww\xf7\xff\xe5\x97_\xaa>\ +\x85\x0f\xd0\x9c\xe0\xe6\xe6\xd6U[\xfe\xa7\xf2?z\x96\ +\xd0\xa5K\x17\xdf\xa6\xf2s]@c>Z#6\xd6\ +\xb6\x86<\xe7BsB|||\xf5\x17\x7f>\x95\xff\ +Q\xd8\xbau\xeb\x9f\xfa\xfa\xfa\x86M\xe9sm\x0c\x1f\ +>\xfc[]\xd85q\xe2\xc45\x0d]7\x8d\x1a5\ +*\x0f\xcd\x09\x9f\xd2\xff(\xa4\xa6\xa6\x8eoj\xbf#\ +\xa0{\x86\xba\xba\x97\xec\xe9\xe9\x19\x84\xc6\xf6\x15+V\ +\x9cjH=\xf4\x8cx\xc7\x8e\x1d\xff|J\xff\x1f:\ +t\xa8\x10]{7\xb5\xff\x07\x0f\x1e\x9c\xa9\x0b{N\ +\x9c8QB\xa3\xd1\x88\x0f\x96\xa3\xfe\xd7\x86\xaelY\ +\xbat\xe9\xf1\xba\xf8\xa3u\xce\x87\xce\x09o\xd3y\xe1\ +\xc2\x85\x87t\xa1\xf3\xe6\xcd\x9b\xaf}<\xcf\xd6\x0fh\ +\xdc\xd0\x85-\xb3f\xcd\xda\xf96\x19\x1f:'\xd4u\ +\x9d\x800c\xc6\x8cm\xba\xd0\x19\xd9\xfe\xf1<[?\ +\xe8j\xdeC\xd7U\xef\x92\x83\xfa3\xea\xd7\x0d\xe1Y\ +\xd7u\x02B^^\xdeQ]\xe8\x0cm\xff\xfb\xe3y\ +\xb6~\x98?\x7f\xfeA]\xd8\xb2}\xfb\xf6\xbf\xea#\ +\x0f\xad\xf95\xef[\xd7'\xa09\x01\xcd#\xda\x058\x1cN\xb4.\xae\x0b\xb2\xb2\xb2\xbe\xfb\x90\xf7\ +\x0e\xd039\xf4\xeePc\xe5#\x1b\xbe\xd4=\x02\xdd\ +\xbbw\x1f\xa8\x8b6@\xeb\x9a\x9e={\x0e\xd1<\x1f\ +x\x17\xd0\xfa5&&f\xa8.\xde\xc1\x86\xba\xbfD\ +6|\x0a_},DFF\xf6\xd7\xd5\xf51z\xe6\ +\x84\xae{\xd0\xfeR\xb4O\x0f\xbdg\x8d\x02\x8a#\x1a\ +Z\x7f\xbd\xbe\x1f\xbc\xb1}\xbf\xb1\xf3\xd0\xe7\x80\xd0\xd0\ +\xd0\x84\xa6x>\xa5\xab\x80\xde\xe3\xfe\xdc\xd7=\xefC\ +PPP\xac.\xde\xc5m\xaa\x80\xf63|)\xeb\x9f\ +\xb7\xa1c\xc7\x8e\x9e\xe8\xfa\xaa\xa9}\xf9\xa1\x01\xcd)\ +\xe8=\xa7\xa6\xf6cc`fff\xb5`\xc1\x82\x9f\ +\x9a\xda\x97\x1f\x1a\xd0\xf3\x84/}N\xa0P(Tt\ +\xaf\xb3\xa9}\xa9\x09h\xbf}C\xaf\x19\xff\x0bs\x02\ +\xbaF\xf8\xd4\xefMi\x07\xf4\xce\x85\xbf\xbf\x7f\x0f\xa4\ +\x0b\xba\x97\x8f\xf6%7\xa4\xbezNphj?6\ +\x06M\xb1\xff\x1d\xc9\xaak\xff;J\xa3\xfd\xf9\x0d\xe1\ +\x85\xe6\x04\xb4\xe7\xb3\xa9\xfc\xa7+\xa0\xb5\xc5\xd7_\x7f\ +\xbd\xf6S\x8c5\xef\xeb\xb3\xe8;\x15\xe8{\x15\xf5\xe5\ +\x89\xe6\x04\xb4\xf7\xf9S\xf9\xeac\x02\xad\x91\xc6\x8f\x1f\ +\xbf\xb2!\xf6\xbf/\xa0\xfbp\x13&LX\xd5\x90}\ +D\xe8\xdeQC\xe7\x84\xcf\xf9\xdetCannn\ +\x8d\xbe3\x84\xd6J\x1fr\xed\x86\xea\xa0\xf7\xac\xfa\xf5\ +\xeb'\xb6\xb0\xb0\xb0\xf9\x10\x1d\x1a:' Y\xba\xf6\ +\xc3\xe7\x00SSSs4W\xa31\x1b}\xa3\x06=\ +w\xdf\xb2e\xcb\xefh\xec\x85\xe1\x01\x8a\xa3g\xeb\xdf\ +|\xf3\xcd&T\xa6k\xd7\xae\xddQ\x1d]\xc8F\xf3\ +S}\xee\xe3}N\xcf\x83\xff\x8b\xe8\xd3\xa7\x0f\xfe\xb6\ +1\x11\xb5\xfd\x97\xbe\x16\xfd\x12\x80\xbe\xeb\xf8\xfa\x9c\x80\ +\xdeM\xfd\xd2\xd7\xa0_\x12\xd0\xf7M5s\x02\x9a\xd7\ +\xffK\xdf4\xfbR\xa0\x99\x13\xd0w\x7f\x9bZ\x17\x12\ +$H\x90 A\x82\x04\x09\x12$H\x90 A\x82\x04\ +\x09\x12$H\x90 A\x82\x04\x09\x12$H\x90\xa8\x06\ +u\x05\x06\xa8\xf0\x1f\x83?\xb0\x82\x02hD\x1c\x80\xa1\ ++\xa85qU\xd1`\xbe$\x19g\xc6\xa6I\x14\x12\ +y\x9aD\xca\x0c\x93\xf02D\xb8X\xc1\x0c\xe3*\xb8\ +\xcc\x10\xa1\x84\x97\x0e\xd8!\xd111\x092\xe2=$\ +\x14\xef\xc9\x1d!\x03\xc0\xc0\x8f\xe0c\x01\x03\xdaI\x17\ +\x03C\x02\xa0)\x95\x00\xd0J\x09\xd6\x85D~!@\ +\xdf7/D\xf5\xc4\x12\x99H\x09\xf4\x91\x02\x9a\xf7\xed\ +;\x00\x80j\xbc?0\xe2\xd3\xb8R\x9c\xc9B|\x84\ +\x19b\xf4\xed\x19+\x18\x18 \x1e\xa4\x01.\x90\x02\x1c\ +0\x01K\xa5\x9fP,G{,irX\x85H\x8f\ +\x10\xa0g\xba\xc8r[\x94\xe6\x09\x93\x85(\x8d\xa9\xed\ +\x11\x88S\xb2\xd5\xf9D:]\x9c.\xd1N\x0b\xe5\xd2\ +\x94Zi\x9e\x10\xf1\xd7\xd7\xb8\x1b\xd1\xe4i\x22$\x03\ +\xed\xe9\xc3\x08\x19\x19r\x85:\x1b\xbd\x9fg\xa6\xf6:\ +\xac%\xc2\x15\x5c>t\xae\x9ab \xe4\x8e\xc0e\x09\ +\x02\x11\xce\x97d$\x07_m\x17Y\x94\xc4\xdaK\xf0\ +L\xc9\x96I\xd5uk\x03\x83\xb2\x0d\x8110\x02\xf6\ +\xa09\xb0\x86\xbf\xe6\xc0\x12\x963V\xffl\xe0\xcfZ\ +\xfd\xb3\x84\xa1\x05Q\xc2\x068T\xff\xec\x81\x1dA\xb1\ +\x84^D\xa5P\x8d\x16\xc0\xb6\x9a\x839\xa4\xb7Ps\ +\xb6\x87r\x8c\xa1<\xfd\x97\x80\xc2_H?\x02^\x01\ +\x9a_\xb9\xf2\x84\xedQ\xa0\x04\x98\xd3\x93WJ\xac\xc0\ +\xef\x18lf\xfa\xc3*%V\x96r\x1c\xeaw\xb8\x5c\ +\x89-b<\x05&v}\xa7\xec\xbbr\xb7\xb4\xf4\xee\ +\xd5\xfdS\x13\xed\xfe\x07\x80\xa8T\x89\x9d\xb0+\x06T\ +\xfb\xac\xfcW\xc5J\xea\xab\xd3\xd9-\xef\x01\xb0\xb8\x04\ +r\xe1\x94\x01\x0a{}\xe5\x13%\xa5r#\xe7\x01\xe4\ +\x98^Q\x8a8V\x02\xcca\xe3\x03%\xb6\xd9\xf1_\ +$2\xe0~\x89\x92\xbe\x88\x01\x00=\xfb\xc5=%\xa5\ +8\x87\xf1\x18\xea\x849\x9c.QRO\xd8E\xfcq\ +G\x89]\x8f*\x04/\x01\xa6\xbf\xacD\x09\x9e\xff\xa3\ +\xc4\xa6R\x8a\x00\xe4\x92^qY\x89\xed5{\x0a*\ +\x10\x17\x18\xbf\xde\xf9\x19(GUa\xfcy\xf8sP\ +\x06\xeb,\x85\xf1\xd2\xf0\x17\xa0\x04\x80\xb9O\x94\x8c\x82\ +9Q\x9dL\x8c\xdb\xdf)\x84\xd4\x88bP\x0a\xb0\xc8\ +\xd2\xa7J\xca\xcdxJ%\x00\xd7\x1fCjd\x09\xaa\ +\xe7]\xfcT\x89-4(\x87\xc4GJ\xac\xd8\xab\x14\ +1v\xbcW\xa4\xc4\xeer\x10\xf1_%v\xafe\x19\ +\x92lz\x09\xf2*O\xad\x80\xc4\x87J\xec\x82I9\ +R\x0d\xdb\x05\x0b,fTA\x22\xb4t;V\x01\x89\ +`\x14\x8c\x9e\xb4\x7f\x09i\xf7\x95 \xab\x02T\xc13\ +\xa7\xea>\xe4\xd8\xf5\x15A\xc3*}+\x91\x9d\xa67\ +\x9f*\xc1\xabR%\xad<\x0d\xd2\xef)\xb1?\x0d\xab\ + \x1d|\x0b\xa5\xaf\xb9W\xa2\xa4\xe41\xae\xdfU\x82\ +\xf1U\xc8Of\xcf\x8b\x94\x94 \xfbS\xd0\xe3\xf9\xff\ +\xdcUb\x85\xc6/!\x19d\x16)i%z\x80\xb1\ +\x04\xba\xac\xb2@\x09\x86\x13\xd4\xddEJp\x03J\x10\ +\xa0\x96\xa8\x18[\xee\x0c\xfe\x80\x94\x1dD\x1e\x8a\x1d\x87\ +*u\x85\x12\xb0<\x06\xd4\xf7\x10\xa4\x5c#\xf2J`\ +l'4K%\xc6\x1e\x9a\xb5\x0dRJ\x88\xbc\x7f`\ +\xec$\xf4\x03#\xaf\x04\x99\x02\xf5<\x0a)\x7f\x13y\ +\x07a\xec/\xe8\xcd\xb4r$O\xa0\x96\xb2\x9f\xc8\x9b\ +\x0a\xad)\xa5\xc3\xcc\xaewaK/a\xe8\x15\xc3\xac\ +I(\x0bkU\x05\xa3!\xb0m\xec\xf3!\xcfS\xf1\ +\xb0d\xb9\xddK\xe4\x82\x0d0cz\x89J\x18x\x01\ +\x13\xcb\x90g0\xa7g\xb0\xb5n\xd3\x8b\x91$\xe8\xaf\ +'PC\xa8\xe3`\x98\x9f\xf6\x02\x09\x80\xfeN\xaaD\ +M\xb0\x1c\x96\xbbe\x04i\xf6'\x1f*\xc1b\xd4,\ +\x98\xc19\xe8\xee5\xcf!\xd3\xc5\xb0\xa9\xcf2*P\ +\xab\xb6,\x80\xc4a\xcf\x00\x96Z\xfeD\x89\xfd\xcf\xbe\ +\x1c\xb5\xbf\xfb\xf3gJ\xec\x95\x0cR9O!\xa3g\ +ne\xa8\xabDW\xc1\xf8w&P\xb8\xe9B\x18\xab\ +\x8a*E\xddj \xa4R\xee\x0e\xd1+\x07\x14\xfa\xd0\ +\xfb\x90\xfer`\x09\xec\x84X\x7fh\x9bA\xe1\xb2D\ +\xb6\x83\x03;q\xf9\x13\xc8\xbcjX\x09\x80\x95\x13*\ +/)\xb1\xa5\x8c2\x00\xb5\x8b-\x85\xf1\xd3P(\xd4\ +\xca\xf3\x16\x8c\xdf\xf7\xaf\x00P\xac\xd5O0^1\xac\ +\x12<\x05\x18u:<\x13\xd6\x17\x94\xa0J/\xc1\x13\ +\xa8\xc7\xf5;J\xda\x8d\x1e\xc0\xee\x04\xa4\x9dvx\x85\ +\x06k\xd59\xf5\x22\x87\x01\xbd\xcaX\x04\xfd|?\x00\ +\x80G\xd0\xfc\xb5\xb0/\xaew\x80\x86\xa6\x94\x95*)\ +\x15\xe9\xe0!\xa0x\xae,\x83'k\xf9*\xd8\xd91\ +\x0ed\x0c\x16\xdf\x07Tk\xd1O\x95\xf0\xc4\xae<$\ +\xb6\x81\x8a\xd9\x9d(U\x02q\x0101\x8f\xce\xd9\x98\ +\xff\xfb\xfd\x07\xbf\x9f\xda\x94\xd3\xdd\xbc\x08`\xf4\x85p\ +\x90X\x06\xe0p\x81\x97U))\xa7\x18\xe0\x18\xc0\xfc\ +\x0a^)\xa9\xf7\x1c`\x97\x004\xdb\x13\xcar\xce+\ +p\x04*\xb5\x90\xff\x12\x0d{\x94\xa6\xf8\x1d8\xdb\x14\ +?\xd2\xda\xff\xb0\xb5\xeauT\x8c\x1c\xedo0U\xad\ +q\x08x\x8cS\xe7\xc5r\x15\x0a\xcd\xda\x22BU\xce\ +X\xbb\x1c:\xfc\x1f\x02\xea)+\ +\x00\x00\x80\x08\ +I\ +I*\x00\x08\x00\x00\x00\x18\x00\xfe\x00\x04\x00\x01\x00\x00\ +\x00\x00\x00\x00\x00\x00\x01\x03\x00\x01\x00\x00\x00`\x00\x00\ +\x00\x01\x01\x03\x00\x01\x00\x00\x00`\x00\x00\x00\x02\x01\x03\ +\x00\x04\x00\x00\x00.\x01\x00\x00\x03\x01\x03\x00\x01\x00\x00\ +\x00\x05\x00\x00\x00\x06\x01\x03\x00\x01\x00\x00\x00\x02\x00\x00\ +\x00\x11\x01\x04\x00\x01\x00\x00\x00NS\x00\x00\x12\x01\x03\ +\x00\x01\x00\x00\x00\x01\x00\x00\x00\x15\x01\x03\x00\x01\x00\x00\ +\x00\x04\x00\x00\x00\x16\x01\x03\x00\x01\x00\x00\x00`\x00\x00\ +\x00\x17\x01\x04\x00\x01\x00\x00\x000\x12\x00\x00\x1a\x01\x05\ +\x00\x01\x00\x00\x006\x01\x00\x00\x1b\x01\x05\x00\x01\x00\x00\ +\x00>\x01\x00\x00\x1c\x01\x03\x00\x01\x00\x00\x00\x01\x00\x00\ +\x00(\x01\x03\x00\x01\x00\x00\x00\x02\x00\x00\x001\x01\x02\ +\x00\x22\x00\x00\x00F\x01\x00\x002\x01\x02\x00\x14\x00\x00\ +\x00h\x01\x00\x00=\x01\x03\x00\x01\x00\x00\x00\x02\x00\x00\ +\x00R\x01\x03\x00\x01\x00\x00\x00\x01\x00\x00\x00\xbc\x02\x01\ +\x00\x1f8\x00\x00|\x01\x00\x00I\x86\x01\x00j\x0d\x00\ +\x00\x9c9\x00\x00i\x87\x04\x00\x01\x00\x00\x00\x80e\x00\ +\x00s\x87\x07\x00H\x0c\x00\x00\x06G\x00\x00\x5c\x93\x07\ +\x00X\x1a\x00\x00\xace\x00\x00\x00\x00\x00\x00\x08\x00\x08\ +\x00\x08\x00\x08\x00\x00\xf9\x15\x00\x10'\x00\x00\x00\xf9\x15\ +\x00\x10'\x00\x00Adobe Photo\ +shop CC 2017 (Wi\ +ndows)\x002017:04:0\ +4 11:01:25\x00\ +\x0a\x0a \ + \x0a \x0a \ + paint.net \ +4.0.9\x0a \ + 2017-03-01T11:2\ +0:20-08:00\x0a \ + 2017-04-04T\ +11:01:25-07:00\x0a\ + 2017-\ +04-04T11:01:25-0\ +7:00\x0a \ + imag\ +e/tiff\x0a 3\x0a \ + sRGB IEC\ +61966-2.1\ +\x0a xmp.\ +iid:7284f562-66e\ +c-6d4b-bfaf-a292\ +c87d086e\x0a \ + adobe:doc\ +id:photoshop:aca\ +ee4ff-1960-11e7-\ +bae7-e6e7a5cd281\ +4\x0a xmp.did:\ +15df0628-f397-b6\ +41-8e6b-37248a21\ +c43f\x0a\ + \x0a \ + \x0a \ + \x0a\ + \ + \ +created\x0a \ + xmp.i\ +id:15df0628-f397\ +-b641-8e6b-37248\ +a21c43f\x0a \ + 2017-03\ +-01T11:20:20-08:\ +00\x0a\ + \ + Adobe Pho\ +toshop CC 2017 (\ +Windows)\x0a \ + \x0a \ + \x0a \ + saved\x0a \ + \ +xmp.iid:7284f5\ +62-66ec-6d4b-bfa\ +f-a292c87d086e\x0a \ + \ +2017-04-04T11:01\ +:25-07:00\x0a \ + Ad\ +obe Photoshop CC\ + 2017 (Windows)<\ +/stEvt:softwareA\ +gent>\x0a \ + /\x0a \ + \x0a \x0a \ + \x0a \x0a <\ +/rdf:RDF>\x0a\x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ +\x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a\ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ +\x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a\ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ +\x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a\ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ +\x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a\ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ +\x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a\ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ +\x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a\ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ +\x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a\ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ +\x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a\ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \x0a\x008BIM\x04\ +%\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x008BIM\x04:\x00\x00\x00\ +\x00\x00\xe5\x00\x00\x00\x10\x00\x00\x00\x01\x00\x00\x00\x00\x00\ +\x0bprintOutput\x00\x00\x00\x05\ +\x00\x00\x00\x00PstSbool\x01\x00\x00\x00\ +\x00Inteenum\x00\x00\x00\x00Int\ +e\x00\x00\x00\x00Clrm\x00\x00\x00\x0fpri\ +ntSixteenBitbool\ +\x00\x00\x00\x00\x0bprinterName\ +TEXT\x00\x00\x00\x01\x00\x00\x00\x00\x00\x0fpr\ +intProofSetupObj\ +c\x00\x00\x00\x0c\x00P\x00r\x00o\x00o\x00f\x00\ + \x00S\x00e\x00t\x00u\x00p\x00\x00\x00\x00\x00\ +\x0aproofSetup\x00\x00\x00\x01\x00\ +\x00\x00\x00Bltnenum\x00\x00\x00\x0cb\ +uiltinProof\x00\x00\x00\x09p\ +roofCMYK\x008BIM\x04;\x00\ +\x00\x00\x00\x02-\x00\x00\x00\x10\x00\x00\x00\x01\x00\x00\x00\ +\x00\x00\x12printOutputOp\ +tions\x00\x00\x00\x17\x00\x00\x00\x00Cpt\ +nbool\x00\x00\x00\x00\x00Clbrbo\ +ol\x00\x00\x00\x00\x00RgsMbool\x00\ +\x00\x00\x00\x00CrnCbool\x00\x00\x00\x00\ +\x00CntCbool\x00\x00\x00\x00\x00Lb\ +lsbool\x00\x00\x00\x00\x00Ngtvb\ +ool\x00\x00\x00\x00\x00EmlDbool\ +\x00\x00\x00\x00\x00Intrbool\x00\x00\x00\ +\x00\x00BckgObjc\x00\x00\x00\x01\x00\x00\ +\x00\x00\x00\x00RGBC\x00\x00\x00\x03\x00\x00\x00\x00\ +Rd doub@o\xe0\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00Grn doub@o\xe0\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00Bl doub\ +@o\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00BrdT\ +UntF#Rlt\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00Bld UntF#Rlt\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00Rslt\ +UntF#Pxl@b\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x0avectorDatabo\ +ol\x01\x00\x00\x00\x00PgPsenum\x00\ +\x00\x00\x00PgPs\x00\x00\x00\x00PgPC\x00\ +\x00\x00\x00LeftUntF#Rlt\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00Top U\ +ntF#Rlt\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00Scl UntF#Prc@\ +Y\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10cropW\ +henPrintingbool\x00\ +\x00\x00\x00\x0ecropRectBott\ +omlong\x00\x00\x00\x00\x00\x00\x00\x0ccr\ +opRectLeftlong\x00\x00\ +\x00\x00\x00\x00\x00\x0dcropRectRi\ +ghtlong\x00\x00\x00\x00\x00\x00\x00\x0bc\ +ropRectToplong\x00\x00\ +\x00\x00\x008BIM\x03\xed\x00\x00\x00\x00\x00\x10\x00\ +\x90\x00\x00\x00\x01\x00\x01\x00\x90\x00\x00\x00\x01\x00\x018\ +BIM\x04&\x00\x00\x00\x00\x00\x0e\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00?\x80\x00\x008BIM\x03\xee\x00\ +\x00\x00\x00\x00\x0d\x0cTransparen\ +cy\x008BIM\x04\x15\x00\x00\x00\x00\x00\x1e\x00\ +\x00\x00\x0d\x00T\x00r\x00a\x00n\x00s\x00p\x00\ +a\x00r\x00e\x00n\x00c\x00y\x00\x008BI\ +M\x045\x00\x00\x00\x00\x00\x11\x00\x00\x00\x01\x00\x00\xff\ +\xff\x00\x00\x00\x00\x00\x00\x00d\x01\x008BIM\x04\ +\x1d\x00\x00\x00\x00\x00\x04\x00\x00\x00\x008BIM\x04\ +\x0d\x00\x00\x00\x00\x00\x04\x00\x00\x00\x1e8BIM\x04\ +\x19\x00\x00\x00\x00\x00\x04\x00\x00\x00\x1e8BIM\x03\ +\xf3\x00\x00\x00\x00\x00\x09\x00\x00\x00\x00\x00\x00\x00\x00\x01\ +\x008BIM'\x10\x00\x00\x00\x00\x00\x0a\x00\x01\x00\ +\x00\x00\x00\x00\x00\x00\x018BIM\x03\xf5\x00\x00\x00\ +\x00\x00H\x00/ff\x00\x01\x00lff\x00\x06\x00\ +\x00\x00\x00\x00\x01\x00/ff\x00\x01\x00\xa1\x99\x9a\x00\ +\x06\x00\x00\x00\x00\x00\x01\x002\x00\x00\x00\x01\x00Z\x00\ +\x00\x00\x06\x00\x00\x00\x00\x00\x01\x005\x00\x00\x00\x01\x00\ +-\x00\x00\x00\x06\x00\x00\x00\x00\x00\x018BIM\x03\ +\xf8\x00\x00\x00\x00\x00p\x00\x00\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x03\ +\xe8\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x03\xe8\x00\x00\x00\ +\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\x03\xe8\x00\x00\x00\x00\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\x03\xe8\x00\x008BIM\x04\x00\x00\x00\x00\ +\x00\x00\x02\x00\x008BIM\x04\x02\x00\x00\x00\x00\x00\ +\x02\x00\x008BIM\x040\x00\x00\x00\x00\x00\x01\x01\ +\x008BIM\x04-\x00\x00\x00\x00\x00\x06\x00\x01\x00\ +\x00\x00\x038BIM\x04\x08\x00\x00\x00\x00\x00$\x00\ +\x00\x00\x01\x00\x00\x02@\x00\x00\x02@\x00\x00\x00\x04\x00\ +\x00\x01+\x00\x00\x00\x0a\xc5\x00\x00\x00\x01\x1b\x01\x00\x00\ +\x0a\xd5\x018BIM\x04\x1e\x00\x00\x00\x00\x00\x04\x00\ +\x00\x00\x008BIM\x04\x1a\x00\x00\x00\x00\x035\x00\ +\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00`\x00\ +\x00\x00`\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00`\x00\x00\x00`\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x10\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00nu\ +ll\x00\x00\x00\x02\x00\x00\x00\x06bounds\ +Objc\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00Rc\ +t1\x00\x00\x00\x04\x00\x00\x00\x00Top lo\ +ng\x00\x00\x00\x00\x00\x00\x00\x00Leftlo\ +ng\x00\x00\x00\x00\x00\x00\x00\x00Btomlo\ +ng\x00\x00\x00`\x00\x00\x00\x00Rghtlo\ +ng\x00\x00\x00`\x00\x00\x00\x06slices\ +VlLs\x00\x00\x00\x01Objc\x00\x00\x00\x01\ +\x00\x00\x00\x00\x00\x05slice\x00\x00\x00\x12\x00\ +\x00\x00\x07sliceIDlong\x00\x00\ +\x00\x00\x00\x00\x00\x07groupIDlon\ +g\x00\x00\x00\x00\x00\x00\x00\x06origine\ +num\x00\x00\x00\x0cESliceOri\ +gin\x00\x00\x00\x0dautoGener\ +ated\x00\x00\x00\x00Typeenum\ +\x00\x00\x00\x0aESliceType\x00\x00\ +\x00\x00Img \x00\x00\x00\x06bounds\ +Objc\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00Rc\ +t1\x00\x00\x00\x04\x00\x00\x00\x00Top lo\ +ng\x00\x00\x00\x00\x00\x00\x00\x00Leftlo\ +ng\x00\x00\x00\x00\x00\x00\x00\x00Btomlo\ +ng\x00\x00\x00`\x00\x00\x00\x00Rghtlo\ +ng\x00\x00\x00`\x00\x00\x00\x03urlTEX\ +T\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00nullT\ +EXT\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00Msg\ +eTEXT\x00\x00\x00\x01\x00\x00\x00\x00\x00\x06a\ +ltTagTEXT\x00\x00\x00\x01\x00\x00\x00\ +\x00\x00\x0ecellTextIsHTM\ +Lbool\x01\x00\x00\x00\x08cellTe\ +xtTEXT\x00\x00\x00\x01\x00\x00\x00\x00\x00\x09\ +horzAlignenum\x00\x00\x00\ +\x0fESliceHorzAlign\ +\x00\x00\x00\x07default\x00\x00\x00\x09v\ +ertAlignenum\x00\x00\x00\x0f\ +ESliceVertAlign\x00\ +\x00\x00\x07default\x00\x00\x00\x0bbg\ +ColorTypeenum\x00\x00\x00\ +\x11ESliceBGColorTy\ +pe\x00\x00\x00\x00None\x00\x00\x00\x09to\ +pOutsetlong\x00\x00\x00\x00\x00\ +\x00\x00\x0aleftOutsetlon\ +g\x00\x00\x00\x00\x00\x00\x00\x0cbottomO\ +utsetlong\x00\x00\x00\x00\x00\x00\x00\ +\x0brightOutsetlong\ +\x00\x00\x00\x00\x008BIM\x04(\x00\x00\x00\x00\x00\ +\x0c\x00\x00\x00\x02?\xf0\x00\x00\x00\x00\x00\x008BI\ +M\x04\x14\x00\x00\x00\x00\x00\x04\x00\x00\x00\x048BI\ +M\x04\x0c\x00\x00\x00\x00\x04\x02\x00\x00\x00\x01\x00\x00\x00\ +0\x00\x00\x000\x00\x00\x00\x90\x00\x00\x1b\x00\x00\x00\x03\ +\xe6\x00\x18\x00\x01\xff\xd8\xff\xed\x00\x0cAdobe\ +_CM\x00\x01\xff\xee\x00\x0eAdobe\x00d\ +\x80\x00\x00\x00\x01\xff\xdb\x00\x84\x00\x0c\x08\x08\x08\x09\x08\ +\x0c\x09\x09\x0c\x11\x0b\x0a\x0b\x11\x15\x0f\x0c\x0c\x0f\x15\x18\ +\x13\x13\x15\x13\x13\x18\x11\x0c\x0c\x0c\x0c\x0c\x0c\x11\x0c\x0c\ +\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\ +\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x01\x0d\x0b\x0b\x0d\x0e\ +\x0d\x10\x0e\x0e\x10\x14\x0e\x0e\x0e\x14\x14\x0e\x0e\x0e\x0e\x14\ +\x11\x0c\x0c\x0c\x0c\x0c\x11\x11\x0c\x0c\x0c\x0c\x0c\x0c\x11\x0c\ +\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\ +\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\xff\xc0\x00\x11\x08\ +\x000\x000\x03\x01\x22\x00\x02\x11\x01\x03\x11\x01\xff\xdd\ +\x00\x04\x00\x03\xff\xc4\x01?\x00\x00\x01\x05\x01\x01\x01\x01\ +\x01\x01\x00\x00\x00\x00\x00\x00\x00\x03\x00\x01\x02\x04\x05\x06\ +\x07\x08\x09\x0a\x0b\x01\x00\x01\x05\x01\x01\x01\x01\x01\x01\x00\ +\x00\x00\x00\x00\x00\x00\x01\x00\x02\x03\x04\x05\x06\x07\x08\x09\ +\x0a\x0b\x10\x00\x01\x04\x01\x03\x02\x04\x02\x05\x07\x06\x08\x05\ +\x03\x0c3\x01\x00\x02\x11\x03\x04!\x121\x05AQa\ +\x13\x22q\x812\x06\x14\x91\xa1\xb1B#$\x15R\xc1\ +b34r\x82\xd1C\x07%\x92S\xf0\xe1\xf1cs\ +5\x16\xa2\xb2\x83&D\x93TdE\xc2\xa3t6\x17\ +\xd2U\xe2e\xf2\xb3\x84\xc3\xd3u\xe3\xf3F'\x94\xa4\ +\x85\xb4\x95\xc4\xd4\xe4\xf4\xa5\xb5\xc5\xd5\xe5\xf5Vfv\ +\x86\x96\xa6\xb6\xc6\xd6\xe6\xf67GWgw\x87\x97\xa7\ +\xb7\xc7\xd7\xe7\xf7\x11\x00\x02\x02\x01\x02\x04\x04\x03\x04\x05\ +\x06\x07\x07\x06\x055\x01\x00\x02\x11\x03!1\x12\x04A\ +Qaq\x22\x13\x052\x81\x91\x14\xa1\xb1B#\xc1R\ +\xd1\xf03$b\xe1r\x82\x92CS\x15cs4\xf1\ +%\x06\x16\xa2\xb2\x83\x07&5\xc2\xd2D\x93T\xa3\x17\ +dEU6te\xe2\xf2\xb3\x84\xc3\xd3u\xe3\xf3F\ +\x94\xa4\x85\xb4\x95\xc4\xd4\xe4\xf4\xa5\xb5\xc5\xd5\xe5\xf5V\ +fv\x86\x96\xa6\xb6\xc6\xd6\xe6\xf6'7GWgw\ +\x87\x97\xa7\xb7\xc7\xff\xda\x00\x0c\x03\x01\x00\x02\x11\x03\x11\ +\x00?\x00\xf4<\xdc\xcc\x96d\x9a\xa9;@\x80\x00\x00\ +\x92O\xc6P\xfd~\xab\xe0\xff\x00\xfbl\x7f\xe4R\xc9\ +\xff\x00\x95\x1b\xfdz\xff\x00\xef\xabR\xcb\x19[\x0b\xec\ +!\xad\x1c\x92\x92\x9c\xbf_\xaa\xf8?\xfe\xdb\x1f\xf9\x14\ +\xbd~\xab\xe0\xff\x00\xfbl\x7f\xe4T\xed\xea\xee\x9f\xd0\ +\xb0\x06\xfe\xf3\xff\x00\xf2#\xff\x00$\x95]]\xd3\xfa\ +f\x02\xd3\xf9\xcc\xff\x00\xc8\x9f\xfc\x92Ja\xeb\xf5_\ +\x07\xff\x00\x98?\xf2(\x98\x19\x99\x16dzV\x9d\xc0\ +\x83\xc8\x00\x82?\xaa\xb4+\xb1\x960>\xb2\x1c\xd3\xc1\ +\x0b+\x07\xfeP?\xf5\xcf\xca\x92\x9f\xff\xd0\xef\xf2\x7f\ +\xe5F\xff\x00^\xbf\xfb\xea\x16fS\xb2-\xff\x00\x83\ +i\x867\xfe\xff\x00\xfd\xa4\x5c\x9f\xf9Q\xbf\xd7\xaf\xfe\ +\xfa\x87\x9b\x8a\xec{\x09\x03\xf4O>\xc3\xe0O\xe6\x1f\ +\xfb\xeaJnt\xecJ\x85-\xb9\xed\x0e{\xf5\x13\xac\ +\x0e\xd0\xa9dc\xde-\xb5\xfe\x9b\x85a\xce;\xbbD\ +\xf2\xad\xe0f\xd4\xda\x856\xb81\xcc\xd1\xa4\xe8\x08\xf8\ +\xa5\x9f\x9bS\xaa4\xd4\xe0\xf7?G\x11\xa8\x03\xe2\x92\ +\x9a\x98y.\xc7\xb4\x7f\xa3y\x01\xe3\xfe\xff\x00\xfd\x94\ +L\x1d:\x8b\x87\x9d\x9f\x95C\x0b\x15\xd9\x16\x87\x11\xfa\ +&\x19q\xf1#\xf3\x07\xfd\xf9O\x07^\xa2\xe3\xe7g\ +\xe5IO\xff\xd1\xef\xf2\x7f\xe5F\xff\x00^\xbf\xfb\xea\ +\xd4{\x1a\xf6\x96<\x074\xe8A\xe1g\xe6\xe1d\xbf\ +$\xdbP\x90b\x0c\xc1\x04!\xfd\x9b\xaa~\xf3\xff\x00\ +\xed\xcf\xfc\xc9%&\xb7\xa4\xb4\x99\xa6\xc2\xd1\xfb\xae\x1b\ +\x87\xdf\xf4\x92\xab\xa4\xb4\x19\xba\xc2\xe1\xfb\xad\x1bG\xdf\ +\xf4\x90~\xcd\xd5?y\xff\x00\xf6\xe7\xfed\x97\xd9\xba\ +\xa7\xef?\xfe\xdc\xff\x00\xcc\x92S\xa8\xc65\x8d\x0c`\ +\x0dh\xd0\x01\xc2\xca\xc1\xff\x00\x94\x0f\xc6\xcf\xca\x9f\xec\ +\xddS\xf7\x9f\xff\x00n\x7f\xe6H\xb88Y\x15\xdf\xea\ +\xda\x03@\x04s$\x92\x92\x9f\xff\xd98BIM\x04\ +!\x00\x00\x00\x00\x00]\x00\x00\x00\x01\x01\x00\x00\x00\x0f\ +\x00A\x00d\x00o\x00b\x00e\x00 \x00P\x00h\ +\x00o\x00t\x00o\x00s\x00h\x00o\x00p\x00\x00\ +\x00\x17\x00A\x00d\x00o\x00b\x00e\x00 \x00P\ +\x00h\x00o\x00t\x00o\x00s\x00h\x00o\x00p\ +\x00 \x00C\x00C\x00 \x002\x000\x001\x007\ +\x00\x00\x00\x01\x00\x00\x00\x0cHLino\x02\x10\x00\ +\x00mntrRGB XYZ \x07\xce\x00\ +\x02\x00\x09\x00\x06\x001\x00\x00acspMSF\ +T\x00\x00\x00\x00IEC sRGB\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf6\xd6\x00\x01\x00\ +\x00\x00\x00\xd3-HP \x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x11cprt\x00\x00\x01\ +P\x00\x00\x003desc\x00\x00\x01\x84\x00\x00\x00\ +lwtpt\x00\x00\x01\xf0\x00\x00\x00\x14bkp\ +t\x00\x00\x02\x04\x00\x00\x00\x14rXYZ\x00\x00\x02\ +\x18\x00\x00\x00\x14gXYZ\x00\x00\x02,\x00\x00\x00\ +\x14bXYZ\x00\x00\x02@\x00\x00\x00\x14dmn\ +d\x00\x00\x02T\x00\x00\x00pdmdd\x00\x00\x02\ +\xc4\x00\x00\x00\x88vued\x00\x00\x03L\x00\x00\x00\ +\x86view\x00\x00\x03\xd4\x00\x00\x00$lum\ +i\x00\x00\x03\xf8\x00\x00\x00\x14meas\x00\x00\x04\ +\x0c\x00\x00\x00$tech\x00\x00\x040\x00\x00\x00\ +\x0crTRC\x00\x00\x04<\x00\x00\x08\x0cgTR\ +C\x00\x00\x04<\x00\x00\x08\x0cbTRC\x00\x00\x04\ +<\x00\x00\x08\x0ctext\x00\x00\x00\x00Cop\ +yright (c) 1998 \ +Hewlett-Packard \ +Company\x00\x00desc\x00\x00\x00\ +\x00\x00\x00\x00\x12sRGB IEC619\ +66-2.1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x12sRGB IEC61966-\ +2.1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00XYZ \x00\x00\x00\x00\x00\x00\xf3\ +Q\x00\x01\x00\x00\x00\x01\x16\xccXYZ \x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00XYZ\ + \x00\x00\x00\x00\x00\x00o\xa2\x00\x008\xf5\x00\x00\x03\ +\x90XYZ \x00\x00\x00\x00\x00\x00b\x99\x00\x00\xb7\ +\x85\x00\x00\x18\xdaXYZ \x00\x00\x00\x00\x00\x00$\ +\xa0\x00\x00\x0f\x84\x00\x00\xb6\xcfdesc\x00\x00\x00\ +\x00\x00\x00\x00\x16IEC http://\ +www.iec.ch\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x16IEC http:/\ +/www.iec.ch\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00desc\x00\x00\x00\ +\x00\x00\x00\x00.IEC 61966-2\ +.1 Default RGB c\ +olour space - sR\ +GB\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00.IE\ +C 61966-2.1 Defa\ +ult RGB colour s\ +pace - sRGB\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00desc\x00\x00\x00\x00\x00\x00\x00,Ref\ +erence Viewing C\ +ondition in IEC6\ +1966-2.1\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00,Reference Vi\ +ewing Condition \ +in IEC61966-2.1\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00view\x00\x00\x00\ +\x00\x00\x13\xa4\xfe\x00\x14_.\x00\x10\xcf\x14\x00\x03\xed\ +\xcc\x00\x04\x13\x0b\x00\x03\x5c\x9e\x00\x00\x00\x01XYZ\ + \x00\x00\x00\x00\x00L\x09V\x00P\x00\x00\x00W\x1f\ +\xe7meas\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\ +\x8f\x00\x00\x00\x02sig \x00\x00\x00\x00CRT\ + curv\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\ +\x05\x00\x0a\x00\x0f\x00\x14\x00\x19\x00\x1e\x00#\x00(\x00\ +-\x002\x007\x00;\x00@\x00E\x00J\x00O\x00\ +T\x00Y\x00^\x00c\x00h\x00m\x00r\x00w\x00\ +|\x00\x81\x00\x86\x00\x8b\x00\x90\x00\x95\x00\x9a\x00\x9f\x00\ +\xa4\x00\xa9\x00\xae\x00\xb2\x00\xb7\x00\xbc\x00\xc1\x00\xc6\x00\ +\xcb\x00\xd0\x00\xd5\x00\xdb\x00\xe0\x00\xe5\x00\xeb\x00\xf0\x00\ +\xf6\x00\xfb\x01\x01\x01\x07\x01\x0d\x01\x13\x01\x19\x01\x1f\x01\ +%\x01+\x012\x018\x01>\x01E\x01L\x01R\x01\ +Y\x01`\x01g\x01n\x01u\x01|\x01\x83\x01\x8b\x01\ +\x92\x01\x9a\x01\xa1\x01\xa9\x01\xb1\x01\xb9\x01\xc1\x01\xc9\x01\ +\xd1\x01\xd9\x01\xe1\x01\xe9\x01\xf2\x01\xfa\x02\x03\x02\x0c\x02\ +\x14\x02\x1d\x02&\x02/\x028\x02A\x02K\x02T\x02\ +]\x02g\x02q\x02z\x02\x84\x02\x8e\x02\x98\x02\xa2\x02\ +\xac\x02\xb6\x02\xc1\x02\xcb\x02\xd5\x02\xe0\x02\xeb\x02\xf5\x03\ +\x00\x03\x0b\x03\x16\x03!\x03-\x038\x03C\x03O\x03\ +Z\x03f\x03r\x03~\x03\x8a\x03\x96\x03\xa2\x03\xae\x03\ +\xba\x03\xc7\x03\xd3\x03\xe0\x03\xec\x03\xf9\x04\x06\x04\x13\x04\ + \x04-\x04;\x04H\x04U\x04c\x04q\x04~\x04\ +\x8c\x04\x9a\x04\xa8\x04\xb6\x04\xc4\x04\xd3\x04\xe1\x04\xf0\x04\ +\xfe\x05\x0d\x05\x1c\x05+\x05:\x05I\x05X\x05g\x05\ +w\x05\x86\x05\x96\x05\xa6\x05\xb5\x05\xc5\x05\xd5\x05\xe5\x05\ +\xf6\x06\x06\x06\x16\x06'\x067\x06H\x06Y\x06j\x06\ +{\x06\x8c\x06\x9d\x06\xaf\x06\xc0\x06\xd1\x06\xe3\x06\xf5\x07\ +\x07\x07\x19\x07+\x07=\x07O\x07a\x07t\x07\x86\x07\ +\x99\x07\xac\x07\xbf\x07\xd2\x07\xe5\x07\xf8\x08\x0b\x08\x1f\x08\ +2\x08F\x08Z\x08n\x08\x82\x08\x96\x08\xaa\x08\xbe\x08\ +\xd2\x08\xe7\x08\xfb\x09\x10\x09%\x09:\x09O\x09d\x09\ +y\x09\x8f\x09\xa4\x09\xba\x09\xcf\x09\xe5\x09\xfb\x0a\x11\x0a\ +'\x0a=\x0aT\x0aj\x0a\x81\x0a\x98\x0a\xae\x0a\xc5\x0a\ +\xdc\x0a\xf3\x0b\x0b\x0b\x22\x0b9\x0bQ\x0bi\x0b\x80\x0b\ +\x98\x0b\xb0\x0b\xc8\x0b\xe1\x0b\xf9\x0c\x12\x0c*\x0cC\x0c\ +\x5c\x0cu\x0c\x8e\x0c\xa7\x0c\xc0\x0c\xd9\x0c\xf3\x0d\x0d\x0d\ +&\x0d@\x0dZ\x0dt\x0d\x8e\x0d\xa9\x0d\xc3\x0d\xde\x0d\ +\xf8\x0e\x13\x0e.\x0eI\x0ed\x0e\x7f\x0e\x9b\x0e\xb6\x0e\ +\xd2\x0e\xee\x0f\x09\x0f%\x0fA\x0f^\x0fz\x0f\x96\x0f\ +\xb3\x0f\xcf\x0f\xec\x10\x09\x10&\x10C\x10a\x10~\x10\ +\x9b\x10\xb9\x10\xd7\x10\xf5\x11\x13\x111\x11O\x11m\x11\ +\x8c\x11\xaa\x11\xc9\x11\xe8\x12\x07\x12&\x12E\x12d\x12\ +\x84\x12\xa3\x12\xc3\x12\xe3\x13\x03\x13#\x13C\x13c\x13\ +\x83\x13\xa4\x13\xc5\x13\xe5\x14\x06\x14'\x14I\x14j\x14\ +\x8b\x14\xad\x14\xce\x14\xf0\x15\x12\x154\x15V\x15x\x15\ +\x9b\x15\xbd\x15\xe0\x16\x03\x16&\x16I\x16l\x16\x8f\x16\ +\xb2\x16\xd6\x16\xfa\x17\x1d\x17A\x17e\x17\x89\x17\xae\x17\ +\xd2\x17\xf7\x18\x1b\x18@\x18e\x18\x8a\x18\xaf\x18\xd5\x18\ +\xfa\x19 \x19E\x19k\x19\x91\x19\xb7\x19\xdd\x1a\x04\x1a\ +*\x1aQ\x1aw\x1a\x9e\x1a\xc5\x1a\xec\x1b\x14\x1b;\x1b\ +c\x1b\x8a\x1b\xb2\x1b\xda\x1c\x02\x1c*\x1cR\x1c{\x1c\ +\xa3\x1c\xcc\x1c\xf5\x1d\x1e\x1dG\x1dp\x1d\x99\x1d\xc3\x1d\ +\xec\x1e\x16\x1e@\x1ej\x1e\x94\x1e\xbe\x1e\xe9\x1f\x13\x1f\ +>\x1fi\x1f\x94\x1f\xbf\x1f\xea \x15 A l \ +\x98 \xc4 \xf0!\x1c!H!u!\xa1!\xce!\ +\xfb\x22'\x22U\x22\x82\x22\xaf\x22\xdd#\x0a#8#\ +f#\x94#\xc2#\xf0$\x1f$M$|$\xab$\ +\xda%\x09%8%h%\x97%\xc7%\xf7&'&\ +W&\x87&\xb7&\xe8'\x18'I'z'\xab'\ +\xdc(\x0d(?(q(\xa2(\xd4)\x06)8)\ +k)\x9d)\xd0*\x02*5*h*\x9b*\xcf+\ +\x02+6+i+\x9d+\xd1,\x05,9,n,\ +\xa2,\xd7-\x0c-A-v-\xab-\xe1.\x16.\ +L.\x82.\xb7.\xee/$/Z/\x91/\xc7/\ +\xfe050l0\xa40\xdb1\x121J1\x821\ +\xba1\xf22*2c2\x9b2\xd43\x0d3F3\ +\x7f3\xb83\xf14+4e4\x9e4\xd85\x135\ +M5\x875\xc25\xfd676r6\xae6\xe97\ +$7`7\x9c7\xd78\x148P8\x8c8\xc89\ +\x059B9\x7f9\xbc9\xf9:6:t:\xb2:\ +\xef;-;k;\xaa;\xe8<' >`>\xa0>\ +\xe0?!?a?\xa2?\xe2@#@d@\xa6@\ +\xe7A)AjA\xacA\xeeB0BrB\xb5B\ +\xf7C:C}C\xc0D\x03DGD\x8aD\xceE\ +\x12EUE\x9aE\xdeF\x22FgF\xabF\xf0G\ +5G{G\xc0H\x05HKH\x91H\xd7I\x1dI\ +cI\xa9I\xf0J7J}J\xc4K\x0cKSK\ +\x9aK\xe2L*LrL\xbaM\x02MJM\x93M\ +\xdcN%NnN\xb7O\x00OIO\x93O\xddP\ +'PqP\xbbQ\x06QPQ\x9bQ\xe6R1R\ +|R\xc7S\x13S_S\xaaS\xf6TBT\x8fT\ +\xdbU(UuU\xc2V\x0fV\x5cV\xa9V\xf7W\ +DW\x92W\xe0X/X}X\xcbY\x1aYiY\ +\xb8Z\x07ZVZ\xa6Z\xf5[E[\x95[\xe5\x5c\ +5\x5c\x86\x5c\xd6]']x]\xc9^\x1a^l^\ +\xbd_\x0f_a_\xb3`\x05`W`\xaa`\xfca\ +Oa\xa2a\xf5bIb\x9cb\xf0cCc\x97c\ +\xebd@d\x94d\xe9e=e\x92e\xe7f=f\ +\x92f\xe8g=g\x93g\xe9h?h\x96h\xeci\ +Ci\x9ai\xf1jHj\x9fj\xf7kOk\xa7k\ +\xfflWl\xafm\x08m`m\xb9n\x12nkn\ +\xc4o\x1eoxo\xd1p+p\x86p\xe0q:q\ +\x95q\xf0rKr\xa6s\x01s]s\xb8t\x14t\ +pt\xccu(u\x85u\xe1v>v\x9bv\xf8w\ +Vw\xb3x\x11xnx\xccy*y\x89y\xe7z\ +Fz\xa5{\x04{c{\xc2|!|\x81|\xe1}\ +A}\xa1~\x01~b~\xc2\x7f#\x7f\x84\x7f\xe5\x80\ +G\x80\xa8\x81\x0a\x81k\x81\xcd\x820\x82\x92\x82\xf4\x83\ +W\x83\xba\x84\x1d\x84\x80\x84\xe3\x85G\x85\xab\x86\x0e\x86\ +r\x86\xd7\x87;\x87\x9f\x88\x04\x88i\x88\xce\x893\x89\ +\x99\x89\xfe\x8ad\x8a\xca\x8b0\x8b\x96\x8b\xfc\x8cc\x8c\ +\xca\x8d1\x8d\x98\x8d\xff\x8ef\x8e\xce\x8f6\x8f\x9e\x90\ +\x06\x90n\x90\xd6\x91?\x91\xa8\x92\x11\x92z\x92\xe3\x93\ +M\x93\xb6\x94 \x94\x8a\x94\xf4\x95_\x95\xc9\x964\x96\ +\x9f\x97\x0a\x97u\x97\xe0\x98L\x98\xb8\x99$\x99\x90\x99\ +\xfc\x9ah\x9a\xd5\x9bB\x9b\xaf\x9c\x1c\x9c\x89\x9c\xf7\x9d\ +d\x9d\xd2\x9e@\x9e\xae\x9f\x1d\x9f\x8b\x9f\xfa\xa0i\xa0\ +\xd8\xa1G\xa1\xb6\xa2&\xa2\x96\xa3\x06\xa3v\xa3\xe6\xa4\ +V\xa4\xc7\xa58\xa5\xa9\xa6\x1a\xa6\x8b\xa6\xfd\xa7n\xa7\ +\xe0\xa8R\xa8\xc4\xa97\xa9\xa9\xaa\x1c\xaa\x8f\xab\x02\xab\ +u\xab\xe9\xac\x5c\xac\xd0\xadD\xad\xb8\xae-\xae\xa1\xaf\ +\x16\xaf\x8b\xb0\x00\xb0u\xb0\xea\xb1`\xb1\xd6\xb2K\xb2\ +\xc2\xb38\xb3\xae\xb4%\xb4\x9c\xb5\x13\xb5\x8a\xb6\x01\xb6\ +y\xb6\xf0\xb7h\xb7\xe0\xb8Y\xb8\xd1\xb9J\xb9\xc2\xba\ +;\xba\xb5\xbb.\xbb\xa7\xbc!\xbc\x9b\xbd\x15\xbd\x8f\xbe\ +\x0a\xbe\x84\xbe\xff\xbfz\xbf\xf5\xc0p\xc0\xec\xc1g\xc1\ +\xe3\xc2_\xc2\xdb\xc3X\xc3\xd4\xc4Q\xc4\xce\xc5K\xc5\ +\xc8\xc6F\xc6\xc3\xc7A\xc7\xbf\xc8=\xc8\xbc\xc9:\xc9\ +\xb9\xca8\xca\xb7\xcb6\xcb\xb6\xcc5\xcc\xb5\xcd5\xcd\ +\xb5\xce6\xce\xb6\xcf7\xcf\xb8\xd09\xd0\xba\xd1<\xd1\ +\xbe\xd2?\xd2\xc1\xd3D\xd3\xc6\xd4I\xd4\xcb\xd5N\xd5\ +\xd1\xd6U\xd6\xd8\xd7\x5c\xd7\xe0\xd8d\xd8\xe8\xd9l\xd9\ +\xf1\xdav\xda\xfb\xdb\x80\xdc\x05\xdc\x8a\xdd\x10\xdd\x96\xde\ +\x1c\xde\xa2\xdf)\xdf\xaf\xe06\xe0\xbd\xe1D\xe1\xcc\xe2\ +S\xe2\xdb\xe3c\xe3\xeb\xe4s\xe4\xfc\xe5\x84\xe6\x0d\xe6\ +\x96\xe7\x1f\xe7\xa9\xe82\xe8\xbc\xe9F\xe9\xd0\xea[\xea\ +\xe5\xebp\xeb\xfb\xec\x86\xed\x11\xed\x9c\xee(\xee\xb4\xef\ +@\xef\xcc\xf0X\xf0\xe5\xf1r\xf1\xff\xf2\x8c\xf3\x19\xf3\ +\xa7\xf44\xf4\xc2\xf5P\xf5\xde\xf6m\xf6\xfb\xf7\x8a\xf8\ +\x19\xf8\xa8\xf98\xf9\xc7\xfaW\xfa\xe7\xfbw\xfc\x07\xfc\ +\x98\xfd)\xfd\xba\xfeK\xfe\xdc\xffm\xff\xff\x80\x00 \ +P8$\x16\x0d\x07\x84BaP\xb8d6\x1d\x0f\x88\ +DbQ8\xa4V-\x17\x8cFcQ\xb8\xe4v=\ +\x1f\x90HdR9$\x96M'\x94JeR\xb9d\ +\xb6]/\x98A\x00\x930(*l\x0c\x9c\x03\x02\x13\ +`P0\x07?\x02?\xe8O\xe8X\x06 \x01\xa4\x00\ +hO\xfa$\x1a\x93H\x82R\xdf\xf0J}J\x06\xff\ +\xa4\x80\xa9t\xd0\x05\x1a\x07U\xa5\xd5\xeb\xf4\xfa\x8d\x86\ +\x05S\x81S\xe9VhK\xfc\x05o\x01\xd5\xaa\xf6\xca\ +\x8d~\x0fh\xb4\xd2\x00P\x8a\x95\x92\xefK\xb0P\xac\ +W\x9aM\xca\x9dI\xbe]05\xca\xf0\x02\x98\xfe\xc8\ +>\xf2O\xa7\xa6U\xe2\xf3\xcc<2O\xb7\xce\x1aS\ +O\x07\xe8Bcm!\x10\x87\xa7)\x89\xb5C\x00v\ +\xb4#?\x01\x81*\x98\x88]\xf7i\x87\xa4g\xb18\ ++\x1e\xe7\x01\xb7\x8e\xed\xaa\x17:\x15\xfa\x0d\xba\xde\xda\ +\xf7\x98Ln;\x7f\xbe\xe2\xf0!\x99\xec\x0d\xe2\xbbj\ +\xe8T\xab\x18^\x7f6\x9f\x90\xc8uz\xbb>\xcf\x81\ +\xfc\xf8\xf4=\x9c\xbe\xb6\xf3#\xdc\xbaa|VN\x0f\ +\xa3c6\xfa\x94\x04\xbfAb\xcf\xf4\xe0)\xc0\x03:\ +r\x08-\xebzc\x03\xc1\x10L\x15\x05>\xe6\x94\x1c\ +c\x13p\x89\x04h\xc2\x86+\xee\x90\x00\xd0\xc8\x10(\ +C\x83 \xdb\x0f\x91\x00LD\x05\xc1q,M\x13\xc5\ +\x09B\xa4fE\x85\xf9\x17\x17\x8d\xa6\xfcdk\xb9\x08\ +\xb0;\x1b\x84\x84LtV5A0_\x14\xc8\x12\x0c\ +\x85!\xa2\xe7\xd4\x8c|\x93RI\x00SI\x84|\x8c\ +}\x1f(\xc4\x0a\x01\x07\xb2\xa8\x9aCK\x058\x0f-\ +\x812$\xbd/\xcc\x13\x0a\x04gL\x86\x08\xed3\x8a\ +\x87\x84\xd4v#\x09\x98\x08\x02\x8a\xf3\x88\xda7\xce\x84\ +\x5c\xa71O\x13\xcc\xf5\x03\x9d\x13\xe9\xc44P\x02\x11\ +\xc9A\x9b\xa8\xc42\x03\x01\x03-\x14?\x0c\x14h\xf0\ +\xe3Ot\x8d%I\xa3\xe7\x95,w\x0c\x94\xc8|o\ +S\x86\xad\x0d\x0d\x0d\x95\x09\x0e\xfe\x8b#}!JU\ +\x15MT\x873\x07\x99\xe1E\x0c\xa1\xf1\xb9Y\x9ah\ +\xc4\xb6\x03\x810\xf8\xdaDN\x22\xb8\xdbS\xc4\xae\x13\ +\x9bU\xc8q\xab\xae\xe1\xa1V\x15UV\x9e\x14\xc8\xc8\ +\x1e\x9b\xb6\x89\xa9O\xd1\x03u\xacD\xd7\xb5\xfb\xa4\x89\ +\xaaF\xdd\xbch\x9e\xb7\x09\xe6\xea\xcav\x13\xa8\xe0\x1f\ +\xb7I\xfb;\xb8\x8e\xdb\xb2\xf29Wr\xd4\x82<\xc8\ +E\x80\xe3\xbb\xab+\xa3d9\xd7\xdd\xe3}-\xd0-\ +\xec\xe0X\xc8\xa3\xc6\xe4\xbc\xce\xc5\xde\xbf\xb9`\x04\xdc\ +\x02\x84X\x88T\x05\xe2\x80r8\xca\x9e\x87\x8d\x9c\x1e\ +\xd6f\xe5j\x8b\xd6\xe0MB6\x10\xe2\xc6L7^\ +\xe8\x89\xf9\x95\x9fc\xa6\x5c(\x9a\xf9\x89\x9be!\xf7\ +2\x87\x02\x80xN\x15\x80:\xb6\x15 \xed.\x92\x9d\ +\xea\x81\xe8O\x06R\xe9\xad\x97r\xb5\x9b\xae\x17\xa6\x8c\ +\xe0`\xeec\xcdr\xbb\xb9\xa5\x93|\xdd\xb4\x83\xcc\x08\ +\xeb\x80\xa8\xf9\xaf\x93an\xc4\x1cb\xec\xb0\xc7\xb3\x87\ +\x96\x89\xbbi\xe4\x12\xe6GQ\xbf\xa3z8\xfb\x8c\xdb\ +\xa8~i\xef\x06E\x89\xbd\xef\x88>\xb8\x08\x82\xb1\xd1\ +\x12U\x86\x5c(~\x8eY\x9b\xa8\xcc\x1f\xdb\xc6\xd9\xa5\ +[K\x95\xd5y9h\xe8{\xefX\x07\xc6\xa74d\ +\xef\xbc\xee\xfa\x08t\x00\xa4^E\x95\xc1\x87L\x1er\ +\xa8v1\x8dS8\xe5i\xc8W\x1b~L,e\x16\ +\xda%'\x9f#?t o\x06\x9e\xf5\xcfx\x15W\ +@\x08tQ\x7fK\xd3\xf5(m\x99\xdd\x0c\xe2\x01\xb5\ +\xe7\x9a6\xa0\x11\xc9T\x9b\x926\xfb\xf9\x82\x04\x1ci\ +\x18\xfe\x0f\xbdJx`\xa1\x15\xf1\x95\xbc(d\x1fl\ +\xb8\xcf\x14\x1f\xf9\xe6\xd7\xa3\xb6\xf65\x17g\xda\xdf\x88\ +\xa7/Es<\xdf\xbf\xfd\xcfmh\x1c\x04\x84d\x01\ +\x15\xcf\x99\xc3\x91\xb5\x98\xe6\x18\xeb\x1f\x22\xcc\x85\xc9-\ +\x97\x92C\x1b\xa3vw\xae\xfd\xfeAT\xc0\xf8]\x18\ +\xae\x060l\x1e\x91\xc5\xc2=G\x93g\x0c`\xf2\x04\ +\xbb\x06D\xfc\x99<\x0f!l\xac~\x0f\xb71\x04\xe0\ +\xb41K\xcd\xfd\xc0\xa3\xb7\xcc\xfa 1\x99\x81\x0e\xbd\ +\xf8\x00\x95\xac\x1b\x96\xc2rnfM\xcc9\xa1\xa8\xe7\ +!\x91\x02\x02\xb1,\x0d\x02\xf8\x9c\x0e\xc1DQ\x06Q\ +D\x14\x03\x10-\x15\xc0\xeb\xfe\x021h\x82)a\xe4\ +;\xd6`\xe9\x8cC\x8cl\xc6Q\x9e6#@\xce\x1a\ +\x11\xacb\x0e\xb8\xdc9\xa1\x8c4|b(V\xc1\xb0\ +c\x07a\xca\xaecm\xa9\xb6@\xb7\x22\x88 s\xb6\ +\x220E\xc5\xc3\x07=\x15\xc0\xb0\x1b\x09R,.\x04\ +\x09\x1c\x14\x01\x5c\x91\x06\xf0\xa8\x8f\x15!\xad%\xc6X\ +\xbf\x93B\xbc\x5cI\xd1J\x9fG@\xe3o\x90a\xe3\ +Gh\xf0F\x9d[\xeb}\xaf\xbe??\x16H\xf5H\ +\xe4,\x1fln#D\x85P\xd8\x81h8T\x81\xc0\ +\xd3\x840\xa6l\x0d\x92`]C\xf2M\x0b\xf1^)\ +\xe6@\x90B\x83Dc)8\xe4\xf9%3\x88\x87O\ +\xe2\x12\xc3\xd7$\xfc\xc8\xe3\xb8}r\xd5=\x01y\xbc\ +\x07\x03\x8c\xe1\x11\xc1\x12r\x05W\xf6/\xa7@\xad\x11\ +\xd3\xac9J\x01\xc4\x98_\x0cs\x8e\xb0rJ\x10\x97\ +\x96\xee\xe5[\xd2\x9a\xf0\xa6A\x11\x09\x08\xdd\xdb\xcaD\ +\x00\xb4\x0c\x03\x05\xba\x0c\x1c\xa1\x10|D@%\x12D\ +\x90\x00z\x07\xc0\xf6\x13\xd4LB\x8aJ,#]\xc2\ +@\x99\xf1\xd2h\x91\xb7V\xc6\xe6\xac\xadW2\x01\xca\ +O\xd7-\x11\x1f\xc4\xdcE \xe2\x96\x04d\xce\x1d\x84\ +\x98\x1e\xa6@\x9a\x87\x11\x11\xc7M\xc6\xe3\xa3\x0d\xa3\x1a\ +\x9e\x0b\x84L\xf8`\x08\x8c\x15\xee\x98\x18\x03\xc7\xd2<\ +eS\xd0\x84\xd06\x92\xbfR',\xa5\xa3\xfaA\x09\ +L4\xd5Q\x06\x18j\xc0z\xa6\xa4\x80P\xd5\xd1\x12\ +%k\x00zhd\xba\x1a8!Y\x0d\xe0\xf2\xe1\x84\ +-\xa2\x90\x91VC\x0f\xc4HV\xaeA\xb2z\x90\x87\ +p\xf6d1.\x01\xb5\xec\x08\x08J\xfc)A\xdd\x81\ +\x09Ul\x93\xd3\xc1\x8c.\x03\xdd\x89\x0b+0\x96Q\ +\xb9\xe7\x1d\xea;\x98q\xae>\x1e\xb6\xf9`\xf5\xcc\x9b\ +\xeb\xaf$\xa5\x88\x82 UPE\x852\x03\xc0\x96\xc2\ +\x12\xean8\xc6\xe3.\x0e\x81A\xb5)\xe2Oc\xa8\ +\xec\xa82\xd6IoYJD\xec\xa7\xe5N\x22Oa\ +\xdd\xbd\xb7\xbaI\xcd 6\x08u\x04W\x93\xc0\x1bi\ +PP\xf6\xb9C\xd2\x97\x85#\xdc2\x05\xd9$\x86\x90\ +f'\x02\xf0w]H<\x07\x9a\x90\xf0\x8b(p\x11\ +\x5c&\xc5\x98\x1fc\xea\x22\xd5\x22D\x0d\xef@D\x9d\ +b8Y2\x1b\x90\x90\x12x\xf8\x0eW\xcc'\x5c\xfb\ +\xa2G\xe5#\xa4\xa8\x8e\xa2\x93:\xa3-R_uK\ +\xa4\x8a\xfa\xec\x10i\xfff\xc8\xe5,\x07\x01\x1a\xf5\x8b\ +\x1b\xbc\x91#p\xeb\x1c\xc2\xf7\x0a\x0a\xcb\x0c-\xe7t\ +b\x1d#\x8c\xa9D\xb0*\x06\x84\xbe!\x17\xb2 \x0e\ +'\xab\xe3|\xc3\x90O\xb9\xe2\xe8\x8eO\x17\xc9Z(\ +\xf5\xb3\x7f\x16O\x01+\xb9\x03n\xa4\x1d\x99\x82T\x04\ +\x8d\x83\x9c|\x11\xc4nA\x16\x18=\x14\x8e|\x8c8\ +D\x86I\x0es\x14W\xd62\x22+\xf2\x80\xdbF\xe0\ +t\x12);\xe2\x1c\xf2\xc0P\x18\xf9l\x5c\x91\x8c]\ +\x1d1\x85\xb2c6\xd1\xc7cW'\x81/\xe9\x0d\xb7\ +\x8f6\xdf\x11\x89\x22\x0a\xc1\xa8\x99\xceC\x00\x04gP\ +\x14\x90(\xb0\xa4\x11\xa2c>\x07\xda =\xc8\xe6P\ +\x15\xf9I\x1c*\xaa =\x9f\x5c\x97\x1a\xc30\x8a_\ +\x985\x07+L cx\xd2\x1e\xd7\x0a\xe4\x15\xab\xa6\ +i\x82\x06M\xec\xe6\xd2&\x065\x00\x1e\xab\xa2\x84d\ +\x81=L\x06\x111\xe6\xa7B\xafV\x09bI\xa0\xb4\ +&To\x83\xb7Z\x0e\x80\xbf\xad\xc1\xb4\xa0\x94D>\ +\xb2\xc3g\x0b\x0e3\x15Hn\xd3\xe4\x8b\xdd\xe0\xe1\xb1\ +\xc4XU\xd9A\xaf\x02\x90\x5c\x0f\x8f\x08q9\x01\xc2\ +wj\x0cPG\xb5\xc1b@\xaf\xc2\x102\x8b\x0d\xbc\ +'\x09F\xb0\xcayU\xcfY5\x9c\x0f \xf8\xf3!\ +\x9a\xf4D\x8a\xc9M\xb3H#\x89n\xdaR\x91T\xcc\ +\xd1\x8e'\xf6:\x90\xbb@\x84\x94\xf1\x1f\xbf\xc5\x98<\ +\xe0A- \x0bN\x0c(\x04\x07\x09\x0c$\xb3qh\ +W\xbe|F\x10\xb2\xcb\x01\xcc(,l\xbe\xf9u\xfc\ +\xd2U\xd0\xed\x8f=&\xde\x16\xb9\x00p\x88w\x8fN\ +\xa0\xeb~B\x96p|P\x01\xa0A\xa4\x01\xcd\xcb\xc7\ +\x06\x97\x05z\x1f\x86e\x1d\xc7\x0cD\xa79\x0f\x02\x83\ +\x9e\x08\x92\x11\x0d\x04GA\x15P\x13x\x108\xbc;\ +\xde\xce\xf4\xad\xc9sKW>\x8a@\x9d\xc7+\x08:\ +x\x83_\xb4\x92&\x86\x038\xdbU\xfbn\xed\xf2a\ +\xc3u\x94\x16\x98p\x88\x1eR\xa2\x05\xa3\xad\x89\x19\xde\ +N/\xa5\x11H\x18\x88/\x09\x1a\xd9\xee\xf8\x82m)\ +\x90)\xc6\x90\x19\xef@} da\xce8B\x8f\x81\ +\x04\xb2\xcb\xaf\xf3n\x1d\x12G\x17\x89\x1b|\x80-\x03\ +\x0d\x0f\xc5\xf3\x09\x19\xa3\xee\xb6\xb6\xf6\xe6\xdd\x0a\x1d\xa7\ +O\x00\x1d\xce\x0a\x00\x09\xc2\x1cDm\x06\x0ba\xc9\x22\ +\x0a/L\x22\x84\x97\xa9\x0e\xe8'\xb0nK\x08'=\ +\x80\x82\xcf\x82`?\xf9\x0e3\x1eVk\xad\x8f\x90\x9a\ +\xdcy\x9d4B\xdf\xba\xb1\x96\xb5\xec\x06\x81\x01k\xf1\ +\xc7\x19<\x01\x89\x13\xa9\x22\xc1\x980=g\x86\xec6\ +\x13\xa3\x84\xcf\xac\x07\x99\x0c\xf2\xed$b\x0f\x8f-'\ +ms7q#>s[\x85\xf0\xec\xae\xb9\xf2C\x1f\ +?\xac{\x83\xff\xdc\x03\xfc\x22\x08\xf5\xb7\xbc\x81\xef\xf1\ +\x1e\x1c\xbe8\xb5\x14w\x12\xfd\xe9\x1f\xbcu\xae\xda\x22\ +j\xdeZ\xed.\xd3-\xf0\xa4\xeeH\xb7\xaeL\x120\ +\x18\x16\xab\x02\x07k\x06He\x06\x1c\x81\xbaC\x80\xa0\ +\xf5\xc4\x14\x03\x904\x04F\x1e$\x8b\xd6\x16KD\xa6\ +\x84\x86\xe2\x01f\x100L\x0c+\x88\xfbb.ul\ +\xc8\xb6\xce\x96W\x0d\xec[P\x0e!\xcf\x82\x7f(\x8e\ +\x15\xd0p\x1b0BH\x89\x96\x18\xae\xc8\xa6\xaff\x17\ +\xc0i\x08`\x82H\x83\xe8\x1c\x01\xb0s\x09\xe4\xbfo\ +5\x05\x8cf\xfc\x09\xac\xc0pdXb&\xf3\x81\x8b\ +\x0a\xe1\xec\xbd\xc4\x86\x18\x90\xb8\x16\x8d\x8e\x0e\x00\x9a\xa6\ +\xab\x88\x91\xc0\x80\x0a\x04\x88\xfda\xf2\x1e\xe0\x97\x0d`\ +<\x9eO\x22#\x0e\xd6q\x90\xa0\xde\xb0\xa4\xf3J\xee\ +wh&\x16P\xf4\x1b\xe05\x0f\xa0@H\x8b|\x0c\ +Q\x04\x07Jj\xf6\x018\x18J\x88\x94\xe4\x82\xe5\xe1\ +\xcc\x1b\xef\xca\x06\xea\xcd\x0d\xe2.\xbbEb\xf2\xb0\x04\ +\x8f\xecl\xa9\xb0\xa8\xb7jP\xf8G6\x12\xd1@\x17\ +k\x82\x08\x84\x88=a\xca\x1b\xc0\x9f\x15 F\xa6\xb0\ +p\x15\xd0t\xa6d\x88\xc5f\xbe\x0f\x80\xb6\x830\x98\ +\xf7\xe2\x14\xfb\xaf\xbe\xcc\xb0\xa3\x13-\xef\x13lr\xbc\ +k4o'$\xfc\xafVHk\xe2\xfd\xc0~\x01\xe4\ +.{\xe6\x1e\x18\x11\xa0\x1e\x0c\xea\x01\x0c\xeeHj&\ +\x13\xc1\x0a\xee\xe1#\x09g\x91\x17\x09\xec3'\xd7\x00\ +\x22$d/z~\x91\x80\xdf1\x84\xc7g|\xef@\ +2\x03\xe1c\x1d\xe1\xba\xebD\x86\xaa\xa0\xd2\x08a\x97\ +\x1e\xe1|\x7f`g\x1f`~\xceA2\xfa\x04\x86>\ +\xe0\x9d `B>\xf0\xdc\xf6\xe25\x0e1\xc4\x220\ +\x06\x88\x10\x0a\xf3Pj\xec\xc0\x00\xe8!\x10\x15)\xc8\ +\x08\x80\xacH\x8c\xf2\x11\x8c\x92\x12\x00\xea\x7fj\xe0\x0b\ +\xd2D\x0e\xc4\x89\x0fAd\x13\xe1\x05% \xc4\xb6\x0d\ + \xc6,\xc7\x09\xf1y\x0e\x85v\xfcB0\xf3\x82\x09\ +\x03@8\x04D\x98\x14\xc1\xa0\xb8\xc4\x80\xc3A\xc7\x02\ +\xc0I\x19\xa5\x88\xa0`\x0a\x00\xcd`\xd4\x000\x03\xc4\ +\x80Y\x85z\x05\x81\xd5*!\xca\xdd\x8a\xcf!\x0e\xd5\ +\x1c\x0d\xe7\x0ep^\xa4rfd\xeeF\xbc\x8aR\xbc\ +\xc2\x0a\xfa\xc0\x98\x0b\xce\x12\x10\x01BH\x92(\x0d!\ +Y-\xa10o\x84\x00\x0a`\xce\x0f2\xe9-\xe4\x86\ +\x0fR\xf0\x0b\x01u/aR \x8c\xbf*\xa0d\x80\ +\xb2\x12\x9aq*\xbb\x92\xb7\x062 \xdfJ\x00\xee\x82\ +\x17,\xe1?,\x80\xc0H\x09\xdc\xd9@\xaa\x05A\xef\ +2\xe1\xeaRj\x16\x01r\xda\x15\x81\xae\x9b\xc0.\x03\ +\xa4\x80\xdb\xc1`\x13m\xb6\x0c\xc2\x104 \x1e\x02g\ +F\xe3\x13\x02\xb22a\x05\xcf-\x06\x10\xeb\x1b\xc2\x11\ +\x222\xc4!\x11\xa6\x01-\xa8\x13\xa1\x8a\x04\xf3\x80\x06\ +$\x80\x93\xa1p\x14\xb1f\x0b\x85&\xdbaJ\x09\x13\ +\x98\x0bD\x80\x8d\x01\xb0\x19\xb1\x04\x0c@v\xa3\x22\x0e\ +\xf6\xc7\xce\xff\xd1w6Q/6\x92\xbav\x89be\ +\x88^\xdf\x82\x19)@:\x13\xf3\xd0\x19\x0c<\x03D\ +\x80p@\xd6\xd5\x81V\xd5\xc4\xc0W\xa0\xd8\x0e\xb3\xec\ +\x12d\x81*!\xd4\x1c\xa5\x1a\x0c\x00o?A\xca\xdd\ +f\xbb\x122\xad\x0e\x13\x08VS\x0d6r\xb8\xcc\xf0\ +\xa7&\xb1;\x06\xc9l\x223\x80\x04\xe0`B!6\ +\x18o\x94D\xc2\xa5\x01\x81\x22\x0e\x8c\xf2\x11\xc4\x81$\ +@\xbc\x0e\xaf\xd0\xf3B@\xb9A\xec\x1ef6\xd8\x82\ +\x1d5@'\x052Z\xd8*AA3\xbbAlo\ +\x1c\xf0\x10\x1fNJ{\x821\x01\xe0\x92\xfe\xc1g\x1e\ +DQ3\xa1,\x12t\x8c\x0f\x0d\xd2%\x8d\xa4\x87\xe1\ +\x14\x0aT\x9c\x0c\xe4\x80<\x01\xfb\x0b\xe0\x98\xb0\xca|\ +\x22k\x1d\x16\xf0f!\xb1u\x00\x12\xb5AJ\xe0[\ +2\xbf\x18s\x18#I\x16\x09@\xb9,\xe1AHD\ +N\x1d\x94\xdc\x1c\xeer\x12\x80\xf38\x81L\xfe\x225\ +(\xc0\x0d9\x80\x90\x0bG$?@$\x02\xf4\xa22\ +\x01\xfb,\xe0\xc0\x16\xd5\x0c\x14\x821%\x8b!%\xc7\ +XY\xf1-\x1cq1A\x90\xecH\xe70\x1a\xb5,\ +\x19BAO@\xb3%!\x04\x14t\xd8H\x0e\x8f\x1a\ +\x01\x80\x16\x0c\xb6\x18\xe1p\x9d\xd3\xf4\x1c\x82\x08\xc4\x92\ +\x94\x03\xd4}\x19@\xa0\xf8\x80 H\x94\xa4\x0f\xd5l\ +\x0b\xb3\x88\x14\xecZt/\xb4\x9e\x93l \xef'Q\ +\xd4iR\x13\xbdRU~\xc0\xd3\x14\xc1\x02?\x22\xe0\ +\xa8\x10\xb5\x9c\x14\xe9\x80\xfe\x84P\x98k\x12\x0f`\xb4\ +\x17\x95\xb0\x15b@\xed\x14b\xf2LdV2\x16\x22\ +\x12\x1a\xae.\x9dX\xe2\x0aw\x15+R\xe2Q\x0c\x80\ +\xa0K\x01\x0c\x14\xec\x89ZB^w\x15\xaa\x0b,\x98\ +$\x93\xb0\xd8\x15\xbc}M\x86\xa9Qz\x11\x12h\x22\ +\xf2l%`S`\xa0f\x835[^BQ(\x13\ +\xec\x0e\xa0\xa4\xd1M\x18\xb5\xf4\x06Gm\xdf\x5c\xc2\x09\ +\x09\xd5\xc1K\xf4k1\x16, p\xeey\xb5\x94%\ +G\xc3\x22\x81S\x08`h\x08V\x14#\xe1\x9bea\ +\x80\x0f\x16\x5c\x0a\xc1\xdff!\xd6\xb1\xa6\xbbW\xb5\x16\ +#O\xba\xec\x95\x1f!\x95#`\x22,\x96S\xc7L\ +\xa2b6\x00\x06r@\xb9h\xe0\xe9e\x22-'a\ +\x1e\xf5!$\x0e\xc8X\x1f\x82aE\xd4af\xf5\xf6\ +\x1e0Z\x9fD@\xb2\xee\xe5Y3\xc8D\xb4|\xb5\ +A$\xe6\xf6\x94 \x90&\x1b\xaa\x82\x0d\xf0\xb8\x18\x81\ +j\xa7\xe7C\x16\xd1\xbbKb\x19c\x00}\x5c\x22\x1e\ +\xed\xf3\xbe\x0d\xd4\xc7\x1dO:H\x14\xf0\xf4J\x10l\ +\xea\x14Djk2\xe1\xee\x1e\xb3\xd0\x13\xe1\x0c\xcf*\ +0H\xe4\x81j\x88\x02\x15\xf0T\x22\xd6\xe9n\xc2\x1c\ +\xbb\xd4\xc3\x13T\x1c\xbck\xca\x88\xe4\xf4\x91\x006N\ +\x80\xde\x11`\x8ft\xa0\xb2\x7fr\xf6\x17ASC\x80\ +\xe8\xc3UTL\x0d\xd8\x15h\xec\x07\xcf5\x12\x94\x10\ +\xe3\xb5\xffF\xe20\xea%\x00\xeanLUV\x0a\x05\ + f~`\x8bx\xa0\xaeP\xe0\x0eL#\xee\x17w\ +\x98\x15!Qy\xe1%b\x05'[\x96\xad@\xce6\ +\xbbwp\xb6\xe5Ek\x8f\xc62f7R\xc1\xabS\ +\x07<\x86\x97J\x08\xe0\xb1]\x97gZ\x22V\x98a\ +\x9f}\xa1\x87TAau!P\x1d\xd7\xe8\x1dIG\ +W\x87\xc70\x13\x04#/\xbb:`v\xf7k+{\ +f\xe3+\xf7;B(b\x8bIp\x07\x14&\x06$\ +z\x06\x13\xcc\xf8\x80#VB\xbeU\xa8\xc032\x80\ +\x8c\xa1\xb2\x19\xe7\xda\x1a\x0b|\xe8\xe8c_.4\x1e\ +\x07\xb3E\x92\xb7\x1c\xb3\x13\x1d-\xf7hV\xcb\x85b\ +7*\x91%r\x83-Fw\xb30\xf3knO\x81\ +k\xd8U\x85\x98t\x22\xd7\xa9\x11W\xac\x1e\x11\xc3c\ +U\x89F\xd75`Xqo\xb8w\x89\x22%\x84\x15\ +\x19\x86H\x15\x86\x96\xf3\x80\x92\xc3s\xd8\x95\x8a\xb8\x97\ +\x7f\x0c\xc1@\xb1'+\x0e\xd9\x88Vx\x95\xc6J\xb7\ +4q\x06\x8d9\x01Ty\x8a\xd8\xd0!\xd2\xa9b\xb8\ +l!U\x82u\xd8f\x22\x970Z\xf6|\x22\xb6\x80\ +\x7f\x16C\x8d8\xf4 \x98]\x8bXa%\xf63&\ +2\xb6\xe9\xad1\x84\xf2\xc1\x13\xd8\xa9\x8fy\x14 \xb8\ +\x99FO)Xx\xbe\x84\xe6H~y\x0d\x80\xb9\x17\ +\x92\xe2\x06\xa8\x17\x22\xff\xa27g*\xd9\x92\x15\xc5R\ +7t\x22\xe9e\x22\x80\xd4FA\xbeF\x82\xe8.\xe3\ +v^B\xb2_C\x19\x96\x06p+b\xbfJT\x84\ +/\x02\xd5\x96\x83zic\x96;Y^6\xa2\x86`\ +\x09\x81\x97B\x1c+#\x0ciF\x9c\x1f\xc1\xfb\x97\xe3\ +\x1cjf\x04-#j \xe3\x94\x1f\xc3\x8c9\xa2\xb7\ +\x96b\x87\x82\x00\xd7\x9ba\x0b\x81\xaa\x8f\x89\xcf\xc3+\ +\xc2>\x96F\x0ak&\x08j\xa3\x14;\x85\xfc!\x86\ +\xa2_\xa5\xe4\x5c\xecpj\xc2\x0b\x9eFl_\xd9\xe0\ +^&\x7f\x9d4\xb7\x9eFy\x9c\xe2\x84]\x82\xcf\x95\ +e\xda^\x06\x1fD\xc2\x07r\xb8\xbd\x945\x8b\x94y\ +1\xa1\xa4\xf7\xa1\x19\x05\x8eD5s1\x7f\xa1\xda,\ +O.\x8e}vw\xa1@\x12\x0dZ<\x10\x97\x01\xa2\ +\xfaDO7\xe8\x1d\xc1\xd4\xe5`\x84S\x81\xbc\xb5\xcb\ +\xbaC \x0fh\xe0\xb8\x0e\x91\xe8\x10z\x0d\xa4zl\ +$\xbaT\x1a\xd7D\x09N\xfc\x1c\x220\x98\x00\x83\xa8\ + \xa3\x04\xc1\x02\x140\xb5\xa6\xfa\x90AC\xcdN\x88\ +\xe6\x0d\x87V#\x02\x9f\x0458\x14L\xde\x06\xda\x93\ +\xaa\xe4\x10\xd6\x81\xda\x1d\x19L\x18:\xbc\x16T\xa4#\ +\x86B\x97\xa0\xa9\x0b\xe1\x19O\xc0-\xab\x1a\xd4$\xe7\ +W'a \x15:\xe0\x12a\xe3\xaea\xda$\x87\xfc\ +\x02Q\x94\x09\xd0\x0a\xda\xe0F\x05r\x8dy\x22'\x9d\ +\xb9\xd9\x9dC\xac^\x19\xeb\xb0\xa3\x93\x9e\xfb\x0f\xb0c\ +\xb3\x9d\xa3\xc5\x9f\xc3\xac\x9e\xb9\xef\x95\xbb\x1e_\x99\xca\ +!Y\xf2a\xbb*_\xe6j)k\xe2\x1c;@\x1b\ +1\xde\x16!=[\x01x\x15zJ\x1d\x22P)\xe6\ +B\xdch\xa8\x06PCVB\x9fN\xd9\xdc`e\xf9\ +\x9d\xb9\xe4gC\xb0h\x05\xfd\x9d\xa6\x8a2\x02\x08g\ +\x14\xa5\xb2Y\xd0a\xa2\xa4j\x86\x1a`\x1a\x00X\xe0\ +\x02<\xdb\x8f\x99\xe2\x05\x99\xc2\xdf\xb7\x99\x5c8\x1bu\ +\x8c`\x01\xb7\xe1\xfd\xb2b\x0eJe\xd4\x1f\xbb\x82@\ +\xb0\xd0\x1f\x18(\xb4\xe1\xb9\xa7)@\x1c7\x0c\x1e\xbb\ +.$\xa2\x9e\x98\x06\x1f\xb9\x03\xb4\x22\x99\xf8A\x1b\xb8\ +H[\xea$[\xf2K\xc3\xcc\x98t\xa5\xbd\xba\xd7\xc0\ +<\x05\xc0|\x09\xc0\xbc\x0d\xc0\xe2\x08 \x00\x00\x03\ +\x00\x01\xa0\x03\x00\x01\x00\x00\x00\x01\x00\x00\x00\x02\xa0\x04\ +\x00\x01\x00\x00\x00`\x00\x00\x00\x03\xa0\x04\x00\x01\x00\x00\ +\x00`\x00\x00\x00\x00\x00\x00\x00\x00\x00Adobe\ + Photoshop Docum\ +ent Data Block\x00M\ +IB8nrTM\x00\x00\x00\x00MIB8r\ +yaL\xdc\x19\x00\x00\x01\x00\x03\x00\x00\x00\x03\x00\x00\ +\x00]\x00\x00\x00\x5c\x00\x00\x00\x04\x00\xff\xff\x9b\x0b\x00\ +\x00\x00\x00C\x04\x00\x00\x01\x00C\x04\x00\x00\x02\x00C\ +\x04\x00\x00MIB8mron\xff\x00\x08\x00<\ +\x01\x00\x00\x00\x00\x00\x00(\x00\x00\x00\x00\x00\xff\xff\x00\ +\x00\xff\xff\x00\x00\xff\xff\x00\x00\xff\xff\x00\x00\xff\xff\x00\ +\x00\xff\xff\x00\x00\xff\xff\x00\x00\xff\xff\x00\x00\xff\xff\x00\ +\x00\xff\xff\x07Layer 0MIB8i\ +nul\x14\x00\x00\x00\x07\x00\x00\x00L\x00a\x00y\ +\x00e\x00r\x00 \x000\x00\x00\x00MIB8r\ +snl\x04\x00\x00\x00ryalMIB8d\ +iyl\x04\x00\x00\x00\x03\x00\x00\x00MIB8l\ +blc\x04\x00\x00\x00\x01\x00\x00\x00MIB8x\ +fni\x04\x00\x00\x00\x00\x00\x00\x00MIB8o\ +knk\x04\x00\x00\x00\x00\x00\x00\x00MIB8f\ +psl\x04\x00\x00\x00\x00\x00\x00\x00MIB8r\ +lcl\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00M\ +IB8dmhsH\x00\x00\x00\x01\x00\x00\x00M\ +IB8tsuc\x00\x00\x00\x004\x00\x00\x00\x10\ +\x00\x00\x00\x01\x00\x00\x00\x00\x00\x08\x00\x00\x00met\ +adata\x01\x00\x00\x00\x09\x00\x00\x00lay\ +erTimebuod\xc2\x93A\xe0\xf78\ +\xd6A\x00MIB8prxf\x10\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\ +\x00S\x00O\x00\x0f\x00\x0c\x00\x0a\x00\x09\x00\x09\x00\x09\ +\x00\x09\x00\x15\x00I\x00K\x00\x12\x00\x14\x00\x14\x00\x12\ +\x00\x13\x00\x13\x00\x13\x00#\x00!\x00\x1e\x00\x1d\x00\x1f\ +\x00\x1d\x00\x1d\x00\x1d\x00\x1c\x00\x1e\x00\x1d\x00(\x00'\ +\x00&\x00&\x00&\x00%\x00$\x00$\x00\x22\x00 \ +\x00 \x00\x1e\x00\x22\x00\x1f\x00\x1e\x00\x1e\x00\x1f\x00!\ +\x00 \x00 \x00#\x00!\x00%\x00%\x00$\x00'\ +\x00(\x00(\x00+\x00\x1d\x00\x1d\x00\x1d\x00\x1d\x00\x1c\ +\x00\x1d\x00\x1e\x00\x1e\x00\x1f\x00 \x00#\x00\x13\x00\x13\ +\x00\x13\x00\x12\x00\x14\x00\x12\x00\x13\x00\x13\x00M\x00L\ +\x00\x09\x00\x09\x00\x08\x00\x09\x00\x0a\x00\x0a\x00\x0c\x00L\ +\x00W\x00 \x00\xfd\x00\x04\x05\x11!-1\xfe/\xfc\ +0\x181//0110010/1/0\ +010/0110/01\xfe0\x0a/2\ +1100/00//\xfe1\x000\xfe1\x05\ +010/01\xfe0\xfe1\xff0\x081/0\ +/-'\x18\x08\x01\xfe\x00\xff\x00\x07\x01\x14X\xab\xdb\ +\xec\xf0\xf0\xfd\xf1\x00\xf0\xfe\xf1\x00\xf2\xfd\xf1\xff\xf0\x01\ +\xf1\xf0\xf8\xf1\x03\xf0\xf1\xf1\xf0\xfe\xf1\xfe\xf0\x07\xf1\xf0\ +\xf0\xf1\xf1\xf0\xf1\xf0\xfc\xf1\xff\xf0\x1b\xf1\xf0\xf0\xf1\xf2\ +\xf1\xf0\xf1\xf0\xf1\xf1\xf2\xf0\xf1\xf0\xf1\xf0\xf0\xf1\xf0\xee\ +\xe4\xc2|.\x06\x00\x00\xff\x00\x03\x16\x86\xed\xfd\xb3\xff\ +\x04\xf9\xbfA\x06\x00\x03\x00\x08l\xf4\xb0\xff\x03\xfe\xbd\ +*\x01\x02\x00$\xd0\xae\xff\x02\xf8x\x07\x02\x02O\xf6\ +\xad\xff\x01\xc0\x14\x02\x05r\xfd\xad\xff\x01\xe1#\x02\x08\ +\x86\xfe\xad\xff\x01\xed+\x02\x08\x8f\xfe\xad\xff\x01\xef-\ +\x02\x09\x91\xfe\xf1\xff\x00\xfe\xdb\xff\xfe\xfe\xfd\xff\x00\xfe\ +\xec\xff\x01\xef,\x02\x08\x91\xfe\xfa\xff\x17\xfe\xcf\xc2\xc3\ +\xc2\xc4\xc3\xc4\xc3\xc3\xc4\xc4\xc1\xc3\xc3\xc2\xc3\xc2\xc2\xc3\ +\xc2\xc3\xc4\xc4\xfe\xc2\xfd\xc3\x0a\xc2\xc3\xc3\xc2\xc3\xc3\xc2\ +\xc3\xc2\xc2\xc1\xfe\xc3\xff\xc4\xf9\xc3\x06\xc4\xc3\xc3\xc4\xc2\ +\xc3\xc4\xfe\xc3\xff\xc2\x01\xc7\xf1\xf9\xff\x01\xf0-\x02\x09\ +\x90\xfe\xfa\xff\x03\xfaK\x18\x17\xfc\x18\x16\x17\x18\x16\x19\ +\x17\x18\x19\x19\x18\x19\x18\x17\x18\x19\x19\x18\x17\x17\x19\x17\ +\x17\x19\x17\xfb\x18\x11\x17\x16\x18\x16\x19\x19\x17\x18\x18\x19\ +\x18\x18\x19\x17\x19\x18\x19\x18\xfd\x19\x08\x18\x19\x19\x18\x19\ +\x19\x17,\xc7\xf9\xff\x01\xf0,\x01\x09\x90\xf9\xff\x01\xf9\ +8\xc0\x00\x01\x15\xc0\xf9\xff\x01\xef.\x02\x09\x91\xfe\xfa\ +\xff\x01\xf97\xc0\x00\x02\x14\xc2\xfe\xfa\xff\x01\xf0-\x02\ +\x09\x90\xfe\xfa\xff\x01\xf88\xc0\x00\x02\x14\xc2\xfe\xfa\xff\ +\x01\xef/\x01\x08\x90\xf9\xff\x01\xf99\xc0\x00\x01\x14\xc1\ +\xf9\xff\x01\xf0/\x02\x09\x90\xfe\xfa\xff\x01\xf97\xc0\x00\ +\x01\x12\xc0\xf9\xff\x01\xef-\x02\x09\x91\xfe\xfa\xff\x01\xf9\ +8\xc0\x00\x01\x14\xc2\xf9\xff\x01\xf1-\x02\x09\x90\xfe\xfa\ +\xff\x01\xfa8\xc0\x00\x01\x15\xc1\xf9\xff\x01\xef-\x01\x09\ +\x92\xf9\xff\x01\xf97\xe7\x00\x0d\x1aU\x87\xb8\xd5\xe6\xf7\ +\xf7\xe6\xd6\xb9\x88V\x1a\xe8\x00\x01\x15\xc2\xf9\xff\x01\xef\ +,\x02\x09\x91\xfe\xfa\xff\x01\xf98\xea\x00\x03\x1bw\xc7\ +\xfe\xf5\xff\x03\xfe\xc9x\x1d\xeb\x00\x01\x14\xc2\xf9\xff\x01\ +\xf0/\x01\x09\x90\xf9\xff\x01\xfa7\xec\x00\x028\xa8\xfb\ +\xef\xff\x02\xfb\xaa:\xed\x00\x01\x15\xc2\xf9\xff\x01\xef-\ +\x01\x09\x91\xf9\xff\x01\xf87\xee\x00\x01\x1c\xaa\xe9\xff\x01\ +\xac\x1e\xef\x00\x02\x14\xc1\xfe\xfa\xff\x01\xef/\x02\x08\x90\ +\xfe\xfa\xff\x01\xf98\xf0\x00\x02\x06x\xf4\xe7\xff\x02\xf5\ +z\x07\xf1\x00\x01\x15\xc2\xf9\xff\x01\xf0-\x02\x09\x91\xfe\ +\xfa\xff\x01\xf97\xf1\x00\x01F\xd9\xe3\xff\x01\xdbH\xf2\ +\x00\x01\x14\xc3\xf9\xff\x01\xf0/\x02\x09\x91\xfe\xfa\xff\x01\ +\xfa7\xf3\x00\x01\x02\x85\xdf\xff\x01\x88\x02\xf4\x00\x01\x15\ +\xc1\xf9\xff\x01\xf1-\x02\x09\x92\xfe\xfa\xff\x01\xf88\xf4\ +\x00\x01\x10\xb5\xdd\xff\x01\xb7\x10\xf5\x00\x01\x15\xc2\xf9\xff\ +\x01\xf0.\x01\x09\x90\xf9\xff\x01\xf98\xf5\x00\x01*\xda\ +\xdb\xff\x01\xdb+\xf6\x00\x01\x15\xc2\xf9\xff\x01\xf0.\x02\ +\x09\x90\xfe\xfa\xff\x01\xf99\xf6\x00\x01C\xf2\xd9\xff\x01\ +\xf3E\xf7\x00\x02\x15\xc3\xfe\xfa\xff\x01\xef-\x01\x08\x91\ +\xf9\xff\x01\xf97\xf7\x00\x01D\xf6\xd7\xff\x01\xf7E\xf8\ +\x00\x02\x14\xc2\xfe\xfa\xff\x01\xf0/\x02\x09\x91\xfe\xfa\xff\ +\x01\xf98\xf8\x00\x01F\xf7\xf0\xff\x07\xe5\x91H*\x0d\ +\x0c&\xe3\xee\xff\x01\xf7F\xf9\x00\x01\x14\xc1\xf9\xff\x01\ +\xf0.\x02\x09\x91\xfe\xfa\xff\x01\xf98\xf9\x00\x01G\xf7\ +\xf1\xff\x02\xe0S\x02\xfb\x00\x00\xdb\xed\xff\x01\xf7G\xfa\ +\x00\x01\x14\xc1\xf9\xff\x01\xf0.\x02\x09\x91\xfe\xfa\xff\x01\ +\xf99\xfa\x00\x015\xf5\xf1\xff\x01\x8c\x09\xf9\x00\x00\xdb\ +\xec\xff\x01\xf54\xfb\x00\x01\x14\xc2\xf9\xff\x01\xf1.\x02\ +\x09\x92\xfe\xfa\xff\x01\xf99\xfb\x00\x01\x1e\xe7\xf2\xff\x01\ +\xfdj\xf7\x00\x00\xdb\xeb\xff\x01\xe7\x1d\xfc\x00\x01\x15\xc1\ +\xf9\xff\x01\xf0/\x02\x08\x93\xfe\xfa\xff\x01\xf98\xfc\x00\ +\x01\x0e\xd3\xf1\xff\x00d\xf6\x00\x00\xdb\xea\xff\x01\xd1\x0d\ +\xfd\x00\x02\x15\xc1\xfe\xfa\xff\x01\xef.\x02\x09\x91\xfe\xfa\ +\xff\x01\xf98\xfd\x00\x01\x01\xb4\xf1\xff\x00\x9f\xf5\x00\x00\ +\xdb\xe9\xff\x01\xb1\x01\xfe\x00\x01\x14\xc1\xf9\xff\x01\xef-\ +\x01\x08\x8f\xf9\xff\x01\xf99\xfd\x00\x00|\xf1\xff\x01\xdf\ +\x0a\xf5\x00\x00\xdb\xe8\xff\x00w\xfe\x00\x02\x15\xbf\xfe\xfa\ +\xff\x01\xee.\x02\x09\x92\xfe\xfa\xff\x01\xf89\xfe\x00\x01\ +<\xfc\xf1\xff\x00d\xf4\x00\x00\xdb\xe8\xff\x05\xfb7\x00\ +\x00\x14\xc2\xf9\xff\x01\xef.\x01\x09\x91\xf9\xff\x05\xf98\ +\x00\x00\x0e\xe0\xf1\xff\x01\xe0\x05\xf4\x00\x00\xdb\xe7\xff\x04\ +\xda\x0a\x00\x14\xc1\xf9\xff\x01\xf0-\x02\x09\x90\xfe\xfa\xff\ +\x04\xf98\x00\x00\x8d\xf0\xff\x00\x89\xf3\x00\x00\xdb\xe6\xff\ +\x03\x81\x00\x14\xc1\xf9\xff\x01\xef,\x02\x09\x90\xfe\xfa\xff\ +\x04\xf97\x00\x10\xf3\xf0\xff\x00@\xf3\x00\x00\xdb\xe6\xff\ +\x03\xee\x0c\x15\xc2\xf9\xff\x01\xf1.\x01\x09\x91\xf9\xff\x03\ +\xf98\x00v\xf0\xff\x01\xf6\x05\xf3\x00\x00\xdb\xe5\xff\x02\ +q\x14\xc3\xf9\xff\x01\xf1.\x02\x09\x92\xfe\xfa\xff\x03\xf9\ +9\x00\xb5\xf0\xff\x00\xdc\xf2\x00\x00\x22\xf7'\x00\xd9\xf0\ +\xff\x02\xb2\x13\xc2\xf9\xff\x01\xf0.\x02\x09\x91\xfe\xfa\xff\ +\x03\xf97\x00\xd9\xf0\xff\x00\xc4\xe7\x00\x00\xbe\xf0\xff\x03\ +\xd7\x15\xc2\xfe\xfa\xff\x01\xf0.\x02\x09\x91\xfe\xfa\xff\x03\ +\xf98\x00\xf6\xf0\xff\x00\xb3\xe7\x00\x00\xaf\xf0\xff\x02\xf6\ +\x14\xc1\xf9\xff\x01\xef.\x02\x09\x91\xfe\xfa\xff\x03\xf88\ +\x00\xdf\xf0\xff\x00\xc6\xe7\x00\x00\xc2\xf0\xff\x02\xde\x15\xc1\ +\xf9\xff\x01\xef-\x02\x09\x91\xfe\xfa\xff\x03\xf97\x00\xbb\ +\xf0\xff\x00\xdd\xe7\x00\x00\xd9\xf0\xff\x03\xb9\x14\xc2\xfe\xfa\ +\xff\x01\xf1.\x02\x09\x91\xfe\xfa\xff\x03\xf98\x00\x88\xf0\ +\xff\x01\xf7\x06\xe9\x00\x01\x05\xf5\xf0\xff\x03\x84\x15\xc2\xfe\ +\xfa\xff\x01\xef.\x02\x09\x90\xfe\xfa\xff\x04\xf98\x00\x1f\ +\xfc\xf0\xff\x00B\xe9\x00\x00?\xf0\xff\x03\xf9\x1a\x14\xc1\ +\xf9\xff\x01\xef.\x02\x09\x92\xfe\xfa\xff\x04\xf97\x00\x00\ +\xa9\xf0\xff\x00\x8b\xe9\x00\x00\x89\xf0\xff\x03\x9e\x00\x15\xc2\ +\xf9\xff\x01\xf0.\x01\x09\x91\xf9\xff\x05\xf98\x00\x00\x22\ +\xf2\xf1\xff\x01\xe2\x06\xeb\x00\x01\x06\xe1\xf1\xff\x04\xef\x1b\ +\x00\x15\xc1\xf9\xff\x01\xef.\x01\x09\x91\xf9\xff\x01\xf97\ +\xfe\x00\x00^\xf0\xff\x00h\xeb\x00\x00g\xf0\xff\x04W\ +\x00\x00\x14\xc0\xf9\xff\x01\xef-\x02\x09\x91\xfe\xfa\xff\x01\ +\xf98\xfd\x00\x00\x9f\xf1\xff\x01\xe1\x0b\xed\x00\x01\x0b\xe2\ +\xf1\xff\x00\x9a\xfe\x00\x01\x13\xc0\xf9\xff\x01\xf0.\x02\x09\ +\x91\xfe\xfa\xff\x01\xf97\xfd\x00\x01\x09\xce\xf1\xff\x00\xa4\ +\xed\x00\x00\xa5\xf1\xff\x01\xcc\x07\xfe\x00\x01\x14\xc1\xf9\xff\ +\x01\xf1.\x01\x09\x91\xf9\xff\x01\xfa8\xfc\x00\x01\x1d\xe5\ +\xf1\xff\x00j\xef\x00\x00l\xf1\xff\x01\xe4\x1b\xfd\x00\x01\ +\x15\xc1\xf9\xff\x01\xef-\x02\x09\x91\xfe\xfa\xff\x01\xf97\ +\xfb\x00\x010\xf3\xf2\xff\x01\xfer\xf1\x00\x01u\xfe\xf2\ +\xff\x01\xf2/\xfc\x00\x01\x13\xc2\xf9\xff\x01\xf0-\x02\x09\ +\x91\xfe\xfa\xff\x01\xf99\xfa\x00\x01I\xfc\xf1\xff\x01\x95\ +\x0d\xf5\x00\x01\x0e\x98\xf1\xff\x01\xfcH\xfb\x00\x02\x15\xc2\ +\xfe\xfa\xff\x01\xf1.\x01\x09\x92\xf9\xff\x01\xf98\xf9\x00\ +\x01\x5c\xfc\xf1\xff\x02\xe6_\x05\xf9\x00\x02\x06`\xe8\xf1\ +\xff\x01\xfc\x5c\xfa\x00\x01\x15\xc2\xf9\xff\x01\xf0-\x02\x09\ +\x91\xfe\xfa\xff\x01\xf86\xf8\x00\x01Y\xfc\xf0\xff\x09\xee\ +\x9eV8\x1c\x1c8V\x9f\xef\xf0\xff\x01\xfcY\xf9\x00\ +\x02\x14\xc1\xfe\xfa\xff\x01\xf0-\x02\x09\x91\xfe\xfa\xff\x01\ +\xf98\xf7\x00\x01T\xfb\xd7\xff\x01\xfbU\xf8\x00\x01\x14\ +\xc2\xf9\xff\x01\xf0.\x02\x09\x92\xfe\xfa\xff\x01\xf86\xf6\ +\x00\x01P\xf7\xd9\xff\x01\xf8Q\xf7\x00\x01\x14\xc1\xf9\xff\ +\x01\xf0/\x01\x09\x91\xf9\xff\x01\xf98\xf5\x00\x013\xe1\ +\xdb\xff\x01\xe24\xf6\x00\x02\x15\xc1\xfe\xfa\xff\x01\xf0.\ +\x02\x09\x91\xfe\xfa\xff\x01\xf88\xf4\x00\x01\x14\xbd\xdd\xff\ +\x01\xbf\x15\xf5\x00\x01\x15\xc2\xf9\xff\x01\xf1-\x01\x09\x91\ +\xf9\xff\x01\xfa8\xf3\x00\x01\x03\x8b\xdf\xff\x01\x8e\x04\xf4\ +\x00\x01\x13\xc2\xf9\xff\x01\xf0.\x01\x08\x90\xf9\xff\x01\xf9\ +8\xf1\x00\x01I\xdb\xe3\xff\x01\xdcK\xf2\x00\x02\x14\xc2\ +\xfe\xfa\xff\x01\xf0.\x01\x09\x91\xf9\xff\x01\xf98\xf0\x00\ +\x02\x06x\xf4\xe7\xff\x02\xf4z\x07\xf1\x00\x01\x13\xc2\xf9\ +\xff\x01\xf0.\x02\x08\x91\xfe\xfa\xff\x01\xf97\xee\x00\x01\ +\x1b\xa6\xe9\xff\x01\xa8\x1c\xef\x00\x02\x15\xc0\xfe\xfa\xff\x01\ +\xef-\x02\x09\x91\xfe\xfa\xff\x01\xf89\xec\x00\x023\xa1\ +\xf8\xef\xff\x02\xf9\xa24\xed\x00\x01\x14\xc2\xf9\xff\x01\xef\ +-\x01\x09\x90\xf9\xff\x01\xf96\xea\x00\x03\x15m\xbd\xfb\ +\xf5\xff\x03\xfb\xben\x16\xeb\x00\x01\x14\xc0\xf9\xff\x01\xf1\ +,\x01\x09\x90\xf9\xff\x01\xf97\xe7\x00\x0d\x11Iz\xaa\ +\xc7\xd8\xe8\xe9\xd8\xc8\xabzJ\x11\xe8\x00\x01\x14\xc1\xf9\ +\xff\x01\xef/\x02\x09\x90\xfe\xfa\xff\x01\xf98\xc0\x00\x01\ +\x15\xc1\xf9\xff\x01\xf0-\x02\x09\x91\xfe\xfa\xff\x01\xf98\ +\xc0\x00\x01\x14\xc2\xf9\xff\x01\xef.\x02\x09\x91\xfe\xfa\xff\ +\x01\xf98\xc0\x00\x01\x14\xc1\xf9\xff\x01\xf0-\x01\x09\x91\ +\xf9\xff\x01\xf97\xc0\x00\x01\x14\xc1\xf9\xff\x01\xef.\x02\ +\x09\x90\xfe\xfa\xff\x01\xf99\xc0\x00\x02\x15\xc1\xfe\xfa\xff\ +\x01\xf0-\x01\x08\x91\xf9\xff\x01\xfa8\xc0\x00\x01\x15\xc1\ +\xf9\xff\x01\xf0.\x02\x09\x92\xfe\xfa\xff\x01\xf97\xc0\x00\ +\x01\x14\xc1\xf9\xff\x01\xf0-\x02\x09\x90\xfe\xfa\xff\x01\xf9\ +7\xc0\x00\x01\x14\xc3\xf9\xff\x01\xf1-\x02\x09\x91\xfe\xfa\ +\xff\x02\xfad;\xfe:\xfe9\x1589;;9:\ +:8;9:7:9:;99;:98\ +\xfd:\xff8\x017;\xfc9\x09;:9;;8\ +:979\xfe:\xff9\x09:89::8;\ +9J\xcf\xf9\xff\x01\xf0-\x01\x09\x91\xf8\xff\x00\xfa\xfd\ +\xf9\x08\xf8\xf9\xf9\xf8\xf9\xf8\xf8\xf9\xf8\xfd\xf9\x06\xfa\xf9\ +\xf9\xf8\xf9\xf8\xf8\xfe\xf9\x00\xf8\xfe\xf9\x0e\xf8\xf9\xf9\xf8\ +\xf9\xf8\xf9\xf8\xf8\xf9\xf8\xf9\xf9\xf8\xf8\xfd\xf9\x00\xf8\xfe\ +\xf9\x05\xf8\xf9\xf9\xf8\xfa\xfa\xfe\xf9\xff\xf8\x01\xf9\xfe\xf9\ +\xff\x01\xf0.\x02\x09\x91\xfe\xad\xff\x01\xf0.\x02\x08\x91\ +\xfe\xad\xff\x01\xee-\x01\x09\x8d\xac\xff\x01\xe9+\x02\x07\ +{\xfe\xad\xff\x01\xd5\x1f\x02\x04U\xf6\xae\xff\x02\xfd\xa3\ +\x0f\x02\x01'\xc9\xae\xff\x02\xe7Q\x03\x03\x00\x09]\xe9\ +\xb0\xff\x03\xf0\x80\x13\x00\xff\x00\x03\x12`\xcc\xf7\xfb\xfe\ +\x00\xff\xfc\xfe\x00\xff\xfe\xfe\x02\xff\xfe\xff\xfe\xfe\x05\xff\ +\xfe\xfe\xff\xfe\xff\xfd\xfe\x0a\xff\xfe\xff\xfe\xfe\xff\xfe\xff\ +\xff\xfe\xfe\xfc\xff\xff\xfe\xfe\xff\x04\xfe\xff\xfe\xff\xff\xfb\ +\xfe\xff\xff\xff\xfe\x02\xff\xfe\xff\xfc\xfe\x06\xfd\xf5\xcel\ +\x17\x00\x00\xff\x00\x08\x01\x0a.`\x86\x96\x97\x92\x92\xfe\ +\x91\xff\x92\x13\x93\x92\x92\x91\x92\x92\x90\x91\x92\x91\x90\x91\ +\x92\x91\x91\x93\x91\x91\x94\x91\xfc\x92\x05\x91\x92\x91\x91\x90\ +\x92\xfe\x91\x0f\x90\x92\x92\x93\x91\x90\x92\x92\x90\x92\x91\x90\ +\x91\x92\x92\x90\xfd\x91\x03\x93\x91\x90\x90\xfe\x91\x0b\x93\x90\ +\x90\x92\x8ayU+\x0c\x01\x00\x00\xfd\x00\x04\x01\x05\x0a\ +\x0c\x0b\xfb\x0a\x00\x09\xf2\x0a\xff\x09\xf0\x0a\x00\x09\xf6\x0a\ +\x00\x09\xee\x0a\x02\x08\x04\x01\xfd\x00\x01\x00\x02\x00\x02\x00\ +\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\ +\x02\x00\x02\x00\x02\x00\x02\x00\x06\x00\x06\x00\x06\x00\x06\x00\ +\x06\x00\x11\x00\x10\x00\x0c\x00\x0c\x00\x0e\x00\x0c\x00\x0f\x00\ +\x0e\x00\x0e\x00\x0e\x00\x0e\x00\x12\x00\x11\x00\x14\x00\x10\x00\ +\x12\x00\x14\x00\x12\x00\x0e\x00\x0f\x00\x0f\x00\x10\x00\x0e\x00\ +\x0a\x00\x06\x00\x08\x00\x08\x00\x06\x00\x08\x00\x10\x00\x11\x00\ +\x14\x00\x16\x00\x16\x00\x15\x00\x14\x00\x14\x00\x17\x00\x14\x00\ +\x16\x00\x0c\x00\x0a\x00\x0e\x00\x0f\x00\x0f\x00\x0c\x00\x0e\x00\ +\x0e\x00\x0e\x00\x10\x00\x13\x00\x06\x00\x06\x00\x06\x00\x06\x00\ +\x06\x00\x06\x00\x06\x00\x06\x00\x02\x00\x02\x00\x02\x00\x02\x00\ +\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\ +\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\ +\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xf4\xcc\xc1\xff\ +\xf5\xcc\xf4\xcc\xc1\xff\xf5\xcc\xf4\xcc\xc1\xff\xf5\xcc\xf4\xcc\ +\xc1\xff\xf5\xcc\xf4\xcc\xc1\xff\xf5\xcc\xf4\xcc\xe8\x00\x03\xcd\ +\xcc\xcc\xcd\xf8\xcc\x00\xcd\xe8\x00\xf5\xcc\xf4\xcc\xeb\x00\x02\ +\xcf\xcd\xcd\xf1\xcc\x00\xd3\xeb\x00\xf5\xcc\xf4\xcc\xed\x00\xea\ +\xcc\x00\xce\xed\x00\xf5\xcc\xf4\xcc\xef\x00\x00\xd1\xe6\xcc\xef\ +\x00\xf5\xcc\xf4\xcc\xf1\x00\x00\xd4\xe3\xcc\x00\xda\xf1\x00\xf5\ +\xcc\xf4\xcc\xf2\x00\xe0\xcc\x00\xcd\xf2\x00\xf5\xcc\xf4\xcc\xf4\ +\x00\x01\xff\xcd\xde\xcc\x00\xff\xf4\x00\xf5\xcc\xf4\xcc\xf5\x00\ +\x00\xcf\xdb\xcc\x00\xcf\xf5\x00\xf5\xcc\xf4\xcc\xf6\x00\x00\xce\ +\xd9\xcc\x00\xcf\xf6\x00\xf5\xcc\xf4\xcc\xf7\x00\x00\xcd\xd7\xcc\ +\x00\xce\xf7\x00\xf5\xcc\xf4\xcc\xf8\x00\x00\xce\xd5\xcc\x00\xce\ +\xf8\x00\xf5\xcc\xf4\xcc\xf9\x00\xec\xcc\x04\xcd\xce\xd7\xd4\xd0\ +\xeb\xcc\xf9\x00\xf5\xcc\xf4\xcc\xfa\x00\xee\xcc\x01\xcd\xff\xfb\ +\x00\xea\xcc\xfa\x00\xf5\xcc\xf4\xcc\xfb\x00\x00\xce\xef\xcc\x00\ +\xe2\xf9\x00\xea\xcc\x00\xcd\xfb\x00\xf5\xcc\xf4\xcc\xfc\x00\xee\ +\xcc\xf7\x00\xe9\xcc\x00\xd3\xfc\x00\xf5\xcc\xf4\xcc\xfd\x00\x00\ +\xda\xef\xcc\xf6\x00\xe8\xcc\x00\xd7\xfd\x00\xf5\xcc\xf4\xcc\xfe\ +\x00\x00\xff\xf0\xcc\x00\xcd\xf5\x00\xe7\xcc\x00\xff\xfe\x00\xf5\ +\xcc\xf4\xcc\xfe\x00\x00\xcd\xef\xcc\xf5\x00\xe7\xcc\x00\xcd\xfe\ +\x00\xf5\xcc\xf4\xcc\xff\x00\xee\xcc\xf4\x00\xe5\xcc\xff\x00\xf5\ +\xcc\xf4\xcc\x01\x00\xda\xee\xcc\xf4\x00\xe4\xcc\x00\x00\xf5\xcc\ +\xf4\xcc\x00\x00\xee\xcc\xf3\x00\xe5\xcc\x01\xcd\x00\xf5\xcc\xf4\ +\xcc\x00\xcf\xef\xcc\x00\xcf\xf3\x00\xe4\xcc\x00\xd4\xf5\xcc\xf4\ +\xcc\x00\xcd\xee\xcc\xf3\x00\xe4\xcc\x00\xcd\xf5\xcc\xe1\xcc\xf2\ +\x00\x00\xd2\xf7\xd1\xe2\xcc\xe1\xcc\xe7\x00\xe2\xcc\xe2\xcc\x00\ +\xcd\xe7\x00\xe2\xcc\xe1\xcc\xe7\x00\x00\xcd\xe3\xcc\xe1\xcc\xe7\ +\x00\xe2\xcc\xe1\xcc\x00\xd4\xe9\x00\xe1\xcc\xf4\xcc\x00\xcd\xee\ +\xcc\xe9\x00\x00\xce\xef\xcc\x00\xcd\xf5\xcc\xf4\xcc\x01\x00\xcd\ +\xf0\xcc\x00\xcd\xe9\x00\xee\xcc\x00\x00\xf5\xcc\xf4\xcc\x01\x00\ +\xd2\xef\xcc\x00\xd4\xeb\x00\x00\xd4\xef\xcc\x01\xcf\x00\xf5\xcc\ +\xf4\xcc\xff\x00\x00\xce\xf0\xcc\x00\xcd\xeb\x00\x00\xcd\xf0\xcc\ +\x02\xcd\x00\x00\xf5\xcc\xf4\xcc\xfe\x00\x00\xcd\xf0\xcc\x00\xd0\ +\xed\x00\x00\xd0\xf0\xcc\x00\xcd\xfe\x00\xf5\xcc\xf4\xcc\xfe\x00\ +\x00\xe2\xf0\xcc\x00\xcd\xed\x00\xf0\xcc\x01\xcd\xda\xfe\x00\xf5\ +\xcc\xf4\xcc\xfd\x00\x00\xd3\xef\xcc\xef\x00\x00\xcd\xf0\xcc\x00\ +\xcf\xfd\x00\xf5\xcc\xf4\xcc\xfc\x00\x00\xcf\xf0\xcc\x00\xcd\xf1\ +\x00\xef\xcc\x00\xce\xfc\x00\xf5\xcc\xf4\xcc\xfb\x00\x00\xce\xf0\ +\xcc\x01\xcd\xd7\xf5\x00\x00\xda\xef\xcc\x00\xcd\xfb\x00\xf5\xcc\ +\xf4\xcc\xfa\x00\x00\xcd\xed\xcc\xf9\x00\x00\xd4\xee\xcc\x00\xcd\ +\xfa\x00\xf5\xcc\xf4\xcc\xf9\x00\x00\xce\xeb\xcc\xff\xd1\xff\xcc\ +\x00\xcd\xee\xcc\x00\xce\xf9\x00\xf5\xcc\xf4\xcc\xf8\x00\x00\xce\ +\xd4\xcc\xf8\x00\xf5\xcc\xf4\xcc\xf7\x00\xd5\xcc\xf7\x00\xf5\xcc\ +\xf4\xcc\xf6\x00\x00\xcd\xd9\xcc\x00\xcd\xf6\x00\xf5\xcc\xf4\xcc\ +\xf5\x00\x01\xcc\xcd\xdc\xcc\x00\xce\xf5\x00\xf5\xcc\xf4\xcc\xf4\ +\x00\x01\xff\xcd\xde\xcc\x00\xff\xf4\x00\xf5\xcc\xf4\xcc\xf2\x00\ +\x00\xce\xe0\xcc\xf2\x00\xf5\xcc\xf4\xcc\xf1\x00\x00\xd4\xe3\xcc\ +\x00\xda\xf1\x00\xf5\xcc\xf4\xcc\xef\x00\x00\xcf\xe7\xcc\x00\xd1\ +\xef\x00\xf5\xcc\xf4\xcc\xed\x00\x00\xcd\xeb\xcc\x00\xcd\xed\x00\ +\xf5\xcc\xf4\xcc\xeb\x00\x02\xce\xcd\xcd\xf1\xcc\x00\xd0\xeb\x00\ +\xf5\xcc\xf4\xcc\xe8\x00\x04\xd2\xce\xcc\xcc\xcd\xfa\xcc\x01\xce\ +\xd2\xe8\x00\xf5\xcc\xf4\xcc\xc1\xff\xf5\xcc\xf4\xcc\xc1\xff\xf5\ +\xcc\xf4\xcc\xc1\xff\xf5\xcc\xf4\xcc\xc1\xff\xf5\xcc\xf4\xcc\xc1\ +\xff\xf5\xcc\xf4\xcc\xc1\xff\xf5\xcc\xf4\xcc\xc1\xff\xf5\xcc\xf4\ +\xcc\xc1\xff\xf5\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\ +\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\x01\x00\x02\ +\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\ +\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x06\x00\x06\x00\x06\ +\x00\x06\x00\x06\x00\x11\x00\x10\x00\x0c\x00\x0c\x00\x0e\x00\x0c\ +\x00\x0f\x00\x0e\x00\x0e\x00\x0e\x00\x0e\x00\x12\x00\x11\x00\x14\ +\x00\x10\x00\x12\x00\x14\x00\x12\x00\x0e\x00\x0f\x00\x0f\x00\x10\ +\x00\x0e\x00\x0a\x00\x06\x00\x08\x00\x08\x00\x06\x00\x08\x00\x10\ +\x00\x11\x00\x14\x00\x16\x00\x16\x00\x15\x00\x14\x00\x14\x00\x17\ +\x00\x14\x00\x16\x00\x0c\x00\x0a\x00\x0e\x00\x0f\x00\x0f\x00\x0c\ +\x00\x0e\x00\x0e\x00\x0e\x00\x10\x00\x13\x00\x06\x00\x06\x00\x06\ +\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x02\x00\x02\x00\x02\ +\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\ +\x00\x02\x00\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\ +\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xf4\ +\xcc\xc1\xff\xf5\xcc\xf4\xcc\xc1\xff\xf5\xcc\xf4\xcc\xc1\xff\xf5\ +\xcc\xf4\xcc\xc1\xff\xf5\xcc\xf4\xcc\xc1\xff\xf5\xcc\xf4\xcc\xe8\ +\x00\x03\xcd\xcc\xcc\xcd\xf8\xcc\x00\xcd\xe8\x00\xf5\xcc\xf4\xcc\ +\xeb\x00\x02\xcf\xcd\xcd\xf1\xcc\x00\xd3\xeb\x00\xf5\xcc\xf4\xcc\ +\xed\x00\xea\xcc\x00\xce\xed\x00\xf5\xcc\xf4\xcc\xef\x00\x00\xd1\ +\xe6\xcc\xef\x00\xf5\xcc\xf4\xcc\xf1\x00\x00\xd4\xe3\xcc\x00\xda\ +\xf1\x00\xf5\xcc\xf4\xcc\xf2\x00\xe0\xcc\x00\xcd\xf2\x00\xf5\xcc\ +\xf4\xcc\xf4\x00\x01\xff\xcd\xde\xcc\x00\xff\xf4\x00\xf5\xcc\xf4\ +\xcc\xf5\x00\x00\xcf\xdb\xcc\x00\xcf\xf5\x00\xf5\xcc\xf4\xcc\xf6\ +\x00\x00\xce\xd9\xcc\x00\xcf\xf6\x00\xf5\xcc\xf4\xcc\xf7\x00\x00\ +\xcd\xd7\xcc\x00\xce\xf7\x00\xf5\xcc\xf4\xcc\xf8\x00\x00\xce\xd5\ +\xcc\x00\xce\xf8\x00\xf5\xcc\xf4\xcc\xf9\x00\xec\xcc\x04\xcd\xce\ +\xd7\xd4\xd0\xeb\xcc\xf9\x00\xf5\xcc\xf4\xcc\xfa\x00\xee\xcc\x01\ +\xcd\xff\xfb\x00\xea\xcc\xfa\x00\xf5\xcc\xf4\xcc\xfb\x00\x00\xce\ +\xef\xcc\x00\xe2\xf9\x00\xea\xcc\x00\xcd\xfb\x00\xf5\xcc\xf4\xcc\ +\xfc\x00\xee\xcc\xf7\x00\xe9\xcc\x00\xd3\xfc\x00\xf5\xcc\xf4\xcc\ +\xfd\x00\x00\xda\xef\xcc\xf6\x00\xe8\xcc\x00\xd7\xfd\x00\xf5\xcc\ +\xf4\xcc\xfe\x00\x00\xff\xf0\xcc\x00\xcd\xf5\x00\xe7\xcc\x00\xff\ +\xfe\x00\xf5\xcc\xf4\xcc\xfe\x00\x00\xcd\xef\xcc\xf5\x00\xe7\xcc\ +\x00\xcd\xfe\x00\xf5\xcc\xf4\xcc\xff\x00\xee\xcc\xf4\x00\xe5\xcc\ +\xff\x00\xf5\xcc\xf4\xcc\x01\x00\xda\xee\xcc\xf4\x00\xe4\xcc\x00\ +\x00\xf5\xcc\xf4\xcc\x00\x00\xee\xcc\xf3\x00\xe5\xcc\x01\xcd\x00\ +\xf5\xcc\xf4\xcc\x00\xcf\xef\xcc\x00\xcf\xf3\x00\xe4\xcc\x00\xd4\ +\xf5\xcc\xf4\xcc\x00\xcd\xee\xcc\xf3\x00\xe4\xcc\x00\xcd\xf5\xcc\ +\xe1\xcc\xf2\x00\x00\xd2\xf7\xd1\xe2\xcc\xe1\xcc\xe7\x00\xe2\xcc\ +\xe2\xcc\x00\xcd\xe7\x00\xe2\xcc\xe1\xcc\xe7\x00\x00\xcd\xe3\xcc\ +\xe1\xcc\xe7\x00\xe2\xcc\xe1\xcc\x00\xd4\xe9\x00\xe1\xcc\xf4\xcc\ +\x00\xcd\xee\xcc\xe9\x00\x00\xce\xef\xcc\x00\xcd\xf5\xcc\xf4\xcc\ +\x01\x00\xcd\xf0\xcc\x00\xcd\xe9\x00\xee\xcc\x00\x00\xf5\xcc\xf4\ +\xcc\x01\x00\xd2\xef\xcc\x00\xd4\xeb\x00\x00\xd4\xef\xcc\x01\xcf\ +\x00\xf5\xcc\xf4\xcc\xff\x00\x00\xce\xf0\xcc\x00\xcd\xeb\x00\x00\ +\xcd\xf0\xcc\x02\xcd\x00\x00\xf5\xcc\xf4\xcc\xfe\x00\x00\xcd\xf0\ +\xcc\x00\xd0\xed\x00\x00\xd0\xf0\xcc\x00\xcd\xfe\x00\xf5\xcc\xf4\ +\xcc\xfe\x00\x00\xe2\xf0\xcc\x00\xcd\xed\x00\xf0\xcc\x01\xcd\xda\ +\xfe\x00\xf5\xcc\xf4\xcc\xfd\x00\x00\xd3\xef\xcc\xef\x00\x00\xcd\ +\xf0\xcc\x00\xcf\xfd\x00\xf5\xcc\xf4\xcc\xfc\x00\x00\xcf\xf0\xcc\ +\x00\xcd\xf1\x00\xef\xcc\x00\xce\xfc\x00\xf5\xcc\xf4\xcc\xfb\x00\ +\x00\xce\xf0\xcc\x01\xcd\xd7\xf5\x00\x00\xda\xef\xcc\x00\xcd\xfb\ +\x00\xf5\xcc\xf4\xcc\xfa\x00\x00\xcd\xed\xcc\xf9\x00\x00\xd4\xee\ +\xcc\x00\xcd\xfa\x00\xf5\xcc\xf4\xcc\xf9\x00\x00\xce\xeb\xcc\xff\ +\xd1\xff\xcc\x00\xcd\xee\xcc\x00\xce\xf9\x00\xf5\xcc\xf4\xcc\xf8\ +\x00\x00\xce\xd4\xcc\xf8\x00\xf5\xcc\xf4\xcc\xf7\x00\xd5\xcc\xf7\ +\x00\xf5\xcc\xf4\xcc\xf6\x00\x00\xcd\xd9\xcc\x00\xcd\xf6\x00\xf5\ +\xcc\xf4\xcc\xf5\x00\x01\xcc\xcd\xdc\xcc\x00\xce\xf5\x00\xf5\xcc\ +\xf4\xcc\xf4\x00\x01\xff\xcd\xde\xcc\x00\xff\xf4\x00\xf5\xcc\xf4\ +\xcc\xf2\x00\x00\xce\xe0\xcc\xf2\x00\xf5\xcc\xf4\xcc\xf1\x00\x00\ +\xd4\xe3\xcc\x00\xda\xf1\x00\xf5\xcc\xf4\xcc\xef\x00\x00\xcf\xe7\ +\xcc\x00\xd1\xef\x00\xf5\xcc\xf4\xcc\xed\x00\x00\xcd\xeb\xcc\x00\ +\xcd\xed\x00\xf5\xcc\xf4\xcc\xeb\x00\x02\xce\xcd\xcd\xf1\xcc\x00\ +\xd0\xeb\x00\xf5\xcc\xf4\xcc\xe8\x00\x04\xd2\xce\xcc\xcc\xcd\xfa\ +\xcc\x01\xce\xd2\xe8\x00\xf5\xcc\xf4\xcc\xc1\xff\xf5\xcc\xf4\xcc\ +\xc1\xff\xf5\xcc\xf4\xcc\xc1\xff\xf5\xcc\xf4\xcc\xc1\xff\xf5\xcc\ +\xf4\xcc\xc1\xff\xf5\xcc\xf4\xcc\xc1\xff\xf5\xcc\xf4\xcc\xc1\xff\ +\xf5\xcc\xf4\xcc\xc1\xff\xf5\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\ +\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\ +\x01\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\ +\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x06\x00\ +\x06\x00\x06\x00\x06\x00\x06\x00\x11\x00\x10\x00\x0c\x00\x0c\x00\ +\x0e\x00\x0c\x00\x0f\x00\x0e\x00\x0e\x00\x0e\x00\x0e\x00\x12\x00\ +\x11\x00\x14\x00\x10\x00\x12\x00\x14\x00\x12\x00\x0e\x00\x0f\x00\ +\x0f\x00\x10\x00\x0e\x00\x0a\x00\x06\x00\x08\x00\x08\x00\x06\x00\ +\x08\x00\x10\x00\x11\x00\x14\x00\x16\x00\x16\x00\x15\x00\x14\x00\ +\x14\x00\x17\x00\x14\x00\x16\x00\x0c\x00\x0a\x00\x0e\x00\x0f\x00\ +\x0f\x00\x0c\x00\x0e\x00\x0e\x00\x0e\x00\x10\x00\x13\x00\x06\x00\ +\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x02\x00\ +\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\x02\x00\ +\x02\x00\x02\x00\x02\x00\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\ +\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\ +\xa8\xcc\xf4\xcc\xc1\xff\xf5\xcc\xf4\xcc\xc1\xff\xf5\xcc\xf4\xcc\ +\xc1\xff\xf5\xcc\xf4\xcc\xc1\xff\xf5\xcc\xf4\xcc\xc1\xff\xf5\xcc\ +\xf4\xcc\xe8\x00\x03\xcd\xcc\xcc\xcd\xf8\xcc\x00\xcd\xe8\x00\xf5\ +\xcc\xf4\xcc\xeb\x00\x02\xcf\xcd\xcd\xf1\xcc\x00\xd3\xeb\x00\xf5\ +\xcc\xf4\xcc\xed\x00\xea\xcc\x00\xce\xed\x00\xf5\xcc\xf4\xcc\xef\ +\x00\x00\xd1\xe6\xcc\xef\x00\xf5\xcc\xf4\xcc\xf1\x00\x00\xd4\xe3\ +\xcc\x00\xda\xf1\x00\xf5\xcc\xf4\xcc\xf2\x00\xe0\xcc\x00\xcd\xf2\ +\x00\xf5\xcc\xf4\xcc\xf4\x00\x01\xff\xcd\xde\xcc\x00\xff\xf4\x00\ +\xf5\xcc\xf4\xcc\xf5\x00\x00\xcf\xdb\xcc\x00\xcf\xf5\x00\xf5\xcc\ +\xf4\xcc\xf6\x00\x00\xce\xd9\xcc\x00\xcf\xf6\x00\xf5\xcc\xf4\xcc\ +\xf7\x00\x00\xcd\xd7\xcc\x00\xce\xf7\x00\xf5\xcc\xf4\xcc\xf8\x00\ +\x00\xce\xd5\xcc\x00\xce\xf8\x00\xf5\xcc\xf4\xcc\xf9\x00\xec\xcc\ +\x04\xcd\xce\xd7\xd4\xd0\xeb\xcc\xf9\x00\xf5\xcc\xf4\xcc\xfa\x00\ +\xee\xcc\x01\xcd\xff\xfb\x00\xea\xcc\xfa\x00\xf5\xcc\xf4\xcc\xfb\ +\x00\x00\xce\xef\xcc\x00\xe2\xf9\x00\xea\xcc\x00\xcd\xfb\x00\xf5\ +\xcc\xf4\xcc\xfc\x00\xee\xcc\xf7\x00\xe9\xcc\x00\xd3\xfc\x00\xf5\ +\xcc\xf4\xcc\xfd\x00\x00\xda\xef\xcc\xf6\x00\xe8\xcc\x00\xd7\xfd\ +\x00\xf5\xcc\xf4\xcc\xfe\x00\x00\xff\xf0\xcc\x00\xcd\xf5\x00\xe7\ +\xcc\x00\xff\xfe\x00\xf5\xcc\xf4\xcc\xfe\x00\x00\xcd\xef\xcc\xf5\ +\x00\xe7\xcc\x00\xcd\xfe\x00\xf5\xcc\xf4\xcc\xff\x00\xee\xcc\xf4\ +\x00\xe5\xcc\xff\x00\xf5\xcc\xf4\xcc\x01\x00\xda\xee\xcc\xf4\x00\ +\xe4\xcc\x00\x00\xf5\xcc\xf4\xcc\x00\x00\xee\xcc\xf3\x00\xe5\xcc\ +\x01\xcd\x00\xf5\xcc\xf4\xcc\x00\xcf\xef\xcc\x00\xcf\xf3\x00\xe4\ +\xcc\x00\xd4\xf5\xcc\xf4\xcc\x00\xcd\xee\xcc\xf3\x00\xe4\xcc\x00\ +\xcd\xf5\xcc\xe1\xcc\xf2\x00\x00\xd2\xf7\xd1\xe2\xcc\xe1\xcc\xe7\ +\x00\xe2\xcc\xe2\xcc\x00\xcd\xe7\x00\xe2\xcc\xe1\xcc\xe7\x00\x00\ +\xcd\xe3\xcc\xe1\xcc\xe7\x00\xe2\xcc\xe1\xcc\x00\xd4\xe9\x00\xe1\ +\xcc\xf4\xcc\x00\xcd\xee\xcc\xe9\x00\x00\xce\xef\xcc\x00\xcd\xf5\ +\xcc\xf4\xcc\x01\x00\xcd\xf0\xcc\x00\xcd\xe9\x00\xee\xcc\x00\x00\ +\xf5\xcc\xf4\xcc\x01\x00\xd2\xef\xcc\x00\xd4\xeb\x00\x00\xd4\xef\ +\xcc\x01\xcf\x00\xf5\xcc\xf4\xcc\xff\x00\x00\xce\xf0\xcc\x00\xcd\ +\xeb\x00\x00\xcd\xf0\xcc\x02\xcd\x00\x00\xf5\xcc\xf4\xcc\xfe\x00\ +\x00\xcd\xf0\xcc\x00\xd0\xed\x00\x00\xd0\xf0\xcc\x00\xcd\xfe\x00\ +\xf5\xcc\xf4\xcc\xfe\x00\x00\xe2\xf0\xcc\x00\xcd\xed\x00\xf0\xcc\ +\x01\xcd\xda\xfe\x00\xf5\xcc\xf4\xcc\xfd\x00\x00\xd3\xef\xcc\xef\ +\x00\x00\xcd\xf0\xcc\x00\xcf\xfd\x00\xf5\xcc\xf4\xcc\xfc\x00\x00\ +\xcf\xf0\xcc\x00\xcd\xf1\x00\xef\xcc\x00\xce\xfc\x00\xf5\xcc\xf4\ +\xcc\xfb\x00\x00\xce\xf0\xcc\x01\xcd\xd7\xf5\x00\x00\xda\xef\xcc\ +\x00\xcd\xfb\x00\xf5\xcc\xf4\xcc\xfa\x00\x00\xcd\xed\xcc\xf9\x00\ +\x00\xd4\xee\xcc\x00\xcd\xfa\x00\xf5\xcc\xf4\xcc\xf9\x00\x00\xce\ +\xeb\xcc\xff\xd1\xff\xcc\x00\xcd\xee\xcc\x00\xce\xf9\x00\xf5\xcc\ +\xf4\xcc\xf8\x00\x00\xce\xd4\xcc\xf8\x00\xf5\xcc\xf4\xcc\xf7\x00\ +\xd5\xcc\xf7\x00\xf5\xcc\xf4\xcc\xf6\x00\x00\xcd\xd9\xcc\x00\xcd\ +\xf6\x00\xf5\xcc\xf4\xcc\xf5\x00\x01\xcc\xcd\xdc\xcc\x00\xce\xf5\ +\x00\xf5\xcc\xf4\xcc\xf4\x00\x01\xff\xcd\xde\xcc\x00\xff\xf4\x00\ +\xf5\xcc\xf4\xcc\xf2\x00\x00\xce\xe0\xcc\xf2\x00\xf5\xcc\xf4\xcc\ +\xf1\x00\x00\xd4\xe3\xcc\x00\xda\xf1\x00\xf5\xcc\xf4\xcc\xef\x00\ +\x00\xcf\xe7\xcc\x00\xd1\xef\x00\xf5\xcc\xf4\xcc\xed\x00\x00\xcd\ +\xeb\xcc\x00\xcd\xed\x00\xf5\xcc\xf4\xcc\xeb\x00\x02\xce\xcd\xcd\ +\xf1\xcc\x00\xd0\xeb\x00\xf5\xcc\xf4\xcc\xe8\x00\x04\xd2\xce\xcc\ +\xcc\xcd\xfa\xcc\x01\xce\xd2\xe8\x00\xf5\xcc\xf4\xcc\xc1\xff\xf5\ +\xcc\xf4\xcc\xc1\xff\xf5\xcc\xf4\xcc\xc1\xff\xf5\xcc\xf4\xcc\xc1\ +\xff\xf5\xcc\xf4\xcc\xc1\xff\xf5\xcc\xf4\xcc\xc1\xff\xf5\xcc\xf4\ +\xcc\xc1\xff\xf5\xcc\xf4\xcc\xc1\xff\xf5\xcc\xa8\xcc\xa8\xcc\xa8\ +\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\xcc\xa8\ +\xcc\xa8\xccMIB8ksML\x0e\x00\x00\x00\x00\ +\x00\xff\xff\x00\x00\x00\x00\x00\x002\x00\x80\x00\x00\x00M\ +IB8ttaP\x00\x00\x00\x00MIB8k\ +sMF\x0c\x00\x00\x00\x00\x00\xff\xff\x00\x00\x00\x00\x00\ +\x002\x00\x00\x00\x00\x00\ +\x00\x00\x05s\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22 standalone=\x22\ +no\x22?>\x0a\x0a \x0a <\ +title>eye on\x0a C\ +reated with Sket\ +ch.\x0a <\ +defs>\x0a \ + \x0a\ + \x0a \x0a\x0a\ +\x00\x00\x1f\xef\ +\x00\ +\x00\xe4\x14x\x9c\xed\x5c\x07\x5cS\xc7\x1f\xbf\x0c\x12\xf6\ +^2c\x98*\x10\xc2&\xc8\xde\x0a\x82l\x14\x85\x90\ +\x04\x88\x84$f\x80\xab\xe2\xaa\xd6U\x95\xba\xb5uo\ +\xc5\xd6]\xad\xdb\xd6Z\xf7\xb6u\xfc\xb1\xd6\xbaW\x15\ +\xb5\xa8\xf0\xbf{!\x10\x10-J\x00\xfb\xff\xbfo>\ +\xf7r\xef\xd6o\xdc\xbd\xbb\xdf\xdd\xbb{\x89\x89\xa0;\ +\x00@\x13\x98\x83Z@\x86>\x02P\x5cH\xd8_\x1e\ +\xbc\x10T\xfcD\xcc\x0f\xd3\x11\xcc\x09\xa4\xfap\x98\x98\ +@\xa9\xf7\x13\xe1\xc5HYN\xeam\x82\xb1J\x1a\xb3\ +z?\x96[\xa5L\x0be\xfa\xe9\x80`\x054\x14~\ +\x82\x1d\xc1\xba\xc1\xefL\xb0Q)\xc7U\x85\x16\x13]\ +\x01\x1d\xfa<\x08^\x98\xdf\x14\xfa\x93\x09)\x8d\xe9\x89\ +?\xa0\xab\x9f5\xbc\xe5\x8e\x8fG~C\x1a\x00\xfe\xa3\ +&\xf0\x95to\xdc\x9e \x05T\x00t\xe3\x00\x88]\ +\x8c\xe4\x87\xfaP\xfc\xb4_\x8f\x02\xc0\xc5P\xf9\x1f\xce\ +\x15\xe5\xf3h\xc9E\x22\x99HZ$\x12\xd3\x22#i\ +^\x9eL\x7f\x9ak&_\xc8\x15\x95I\xbb\x01t\xcb\ +\xf2\xf4byz\xd3\x98\xbe,/o\x96\xa7\x0f\xe8\x19\ +:D\xcc\xe6\x14\xf3d\xb4|^!_\x18L\x7f\xb4\ +k/\x9d\xc6\xe7\x06\xd33}\x13=\x13\xc5\x91\xbc\x22\ +~\xdc0\x09/uX\x9f4\xce\xb0bN \x97\x1e\ +\x1a\xa2\xdds\x08kH\x89\xb8\x84'c\xd3\x86\x94\x08\ +\x84R\xd6\x90`:\x1b\xd1gA?\x0af\xd0iX\ +\x12Yq0]\xc1XVb2-R$\xe1\xd1|\ +=\xfc\xdc9L\xef\x00\x9a\x7f\xa0\x07\xd370\xc0\xcb\ +\xc7\x0d1\xea\xc7\xf0\x0cd0}\xdc=\x99,\xcf@\ +\x96'\x93V\x0fz\x886\xbc\xf6\x94p\x0bX)Q\ +1\xf5\xe4\xe0]0\xbdH&\x13\xb3\x18\x8c\xb2\xb22\ +\x8f2o\x0f\x91\xa4\x90\xc1\x0c\x0c\x0cdxz1\xbc\ +\xbc\xdca\x0aw\xe9P\xa1\x8c=\xc4](uP\x14\ +\xa2,'\x8a'\xe5H\xf8b\x19_$\xa4\xa1{v\ +\xbeH.\x0b\xa6\xd3\xb5i*\xa8\x97\xabD\xdc@H\ +(\xf5\xc0d\xf4\xe0\x88J\x18C\xd8b\x06\xd3\xc3\x93\ +\xd1R&.\xa7!\x8fX.\x11`\xacq9\x0c\x9e\ +\x80W\xc2\x13\xca\xa40\x1f\xb3\xc5|be\xdd\xb5L\ +\xb2!\xfa\x9d\x84!\xb7\x89\x89\xef\xe7\xb7\xa4\xa4\xc5\x9c\ +RYt\xa9\xec\xfd9\xa5iC\xc5\x05\xee\x01\xcc|&|\xc6|}\xb9<\x0e\ +\xd3\xcb\x97\xeb\x8b\xe9\xa0i\xf6\xb7\x8a\x8e\x12q\xe4\xa8\ +\xe9\xd6\x17\xcd\xfd\xc0\xa2U\xb2\xbfUt\x92\x84\x0f\xbb\ +\x1d\xb6\xa0\x8d$Z(\xe6-Rq|\xa9L$\x19\ +\x1a\xd2\xa4\xf9c\x1dB*op\xd3Pe\x84\x80\x8f\ +u\x10b\xb6D\xcaC\xcd?\x98\xael\xff\xf4\xb72\ +\xa0<\xd8c\xc4bsP\xd7\x12\xc2\xc1Z8\xb7'\ +\xa3I\xe8\xbb\xb3\xf1?\xb6\x02\xdf\xca\xfen\x1aeE\ +<\xe1\xfb\x9eL\x95T\xef.D**\x90\x95\xb1%\ +\xbc\xf0B\xa8\xe9\x90\x7f\x1cw\x94\xa56\xcd\xf6\x96\xbe\ +\x19\x0a\x857\xab\x1e\xc6\xdb\xf5\xa3\xac\xf3f\xf5\xa9H\ +\xaa\xd2\xb7+\x06\x0eF\xfd\xc8\x01\x07-F\xc3\xa8\xd5\ +\x92p\xea\x07N\x04'\x82\x13\xc1\x89\xe0Dp\x228\ +\x11\x9c\x08N\x04'\x82\x13\xc1\x89\xe0Dp\x228\x11\ +\x9c\x08N\x04'\x82\x13\xc1\x89\xe0Dp\x228\x11\x9c\ +\x08N\x04'\x82\x13\xc1\x89\xe0Dp\x228\x11\x9c\x08\ +N\x04'\x82\x13\xc1\x89\xe0Dp\x228\x11\x9c\x08N\ +\x04'\x82\x13\xc1\x89\xe0Dp\x22j&\xa2\xddx\x0e\ +\x8c'\xe4\x06\xd3\xcb\xe8\xa1! \x22>\x91\xec\x84\ +\x9d93\x04\xcd\x80\xc5\xb10\xef\xcd\xfax\xect\x1e\ +\xd0\x11K\xf8BY\x92\x5c&\x96\xcb\xe0-:&\x07\ +\x92\xa5\xb2\xd4|\x91H\x80\xa5\x88\x17\xcax<\xa1\xbc\ +D\xe9G\xff\x91\x02\x09\xba7\xc0\xf2\xa6\xf2\x87\xa0\x14\ +\x11|\x19\xca\xd3X&O\xd2\x87]\xc2K\x8b\xceJ\ +k \xa6\xc8\x90,\x11\x89\x0aRy2\xb98)\x7f\ +\x10\x07\x06\xeb\x82d \x01\x22\xf8+\x004\x90\x0ax\ +@\x06\xe4@\x8ce\xd1\x167\xa4V\x16\x13!\x90\x09\ +\xeb9\xd2\xcd\x97\xf3\x052\xbe\x10+\x12\xdeka\xa9\ +#\x13\xb3{+$\x0eB\xe9\x89\xeeM$6V\x91\ +8\x09;y \x85\xa1\x16\x98\x5cb\x99P)\x04\x14\ +2_\xd2p\x93R(Ml\x8c\x91\x08#\x1bo\x84\ +\xb2\xc6\x9b\x84|\x81\xb4\xe1\xa6O\xa1\xac\xb4\xe1&\xba\ +D\x10\xd5p\x03\xf5\xd8Xt\x04\xa7\xb8\xb0^\x11\x0a\ +\x06AJlD$P\x1c\x9b\x04)\x5c\x1a\x8d+\x92\ +\xe7\x87\x89\xaa\x1a*3V\x22|+,B\xf0v\xba\ +\x08\x097-](\x8bqH\x11\xc8T\x1bC\x84\x80\ +Kk)\ +\x8b\xae2\x06\xb1\xa0\x12\xae\xa7\x0cO\xe1\x17\x16\xa9F\ +\xe8(# o\x0d\xc1\xa8\xe5\x90\x1e(x\x00q@\ +q\xf6\xb3\xfe\x1fkU\xceX\x9c~\xa3\x04\xa1\xa3\xea\ +s=T\x90\xd3M\x93\xb0\x85R1[\xc2\x13r\x86\ +*Z\xa2\x19\x16c\x87bA\x1al\xedl \x04R\ +\xd8\xc6\xd9\xd0\xcf\x83~\x0e\x18Z\xff\x94\xfab)\x8d\ +0z\xa0\xae\xae\x9e\x04\x97\xa0\x88\xb5\xc5\xee\xc8J>\ +\xc9z\x0d\xf7v\xd8}\x97\xa6\xf7\xa4\xa7\xd8\xbd\x96\x92\ +SE).\x8a\xfeA[\xd9\xe0\x14r\x91\xaa1\x7f\ +\x1c`\x14\x14\xc0\x18\x01\xbcR\xea3)B\x96\xcc\x9b\ +\xdf\x10\xe2\x85]\xfb\xc1\xab2\xc4\x17\xbb\xba7\x86`\ +e\xbe\xc4\xfcb$IK \xddF\xd1\xea\x8f\xc3t\ +\xa1\x90\x8dX\x7fGlr\xe7\xa9\xe0\xb1^\xab\xee\xd8\ +\x1d\x05\xd3\x07\x09\x0b\xd1\xac\xaf\x7f\xac\x16\x88a\x0aW\ +\x9f\xd7\xaeY\x1dX!\x1f\xc9\xb7Ar\x05\xf2\xea\x9d\ +B;oC5L5m\x8b\x09\x94h\xec\xc6\x80P\ +.\x10(\x04\x02\x94|\x91\x5c\xc8\x956\xebE82\ +\xa6\x92M\xf4\xe8\xa94{\xd0\xec\xf9\x00\x11\x8d\xcf\x11\ +\xc6FJ\xe3c\x82\xee)R\x01\x9f\xc3\x93f\x08\x12\ +\xd0\x83NhBG\x03\x8b\x83\x1ec\xe8\xa8\xd8M|\ +\x94J\xd9\xd4B\x89H.n\x12D\x11a\xc7\xff\x94\ +}xt*\xca\xa48\x12\x08\xef\xf5\xd8r\x99(\x96\ +'\xe4I\xd0q<\x8c\xfb\xa1b\xe5\x10\xa4\xadH\x8c\ +BPL|I!\xad\x03\xe4'\xc9%\x82&\x03\x19\ +\xa6\xfc\xa6!\x89\xd2\xc2\xa6\x83\x1d\x85-\x90\xa5\xb1\x0b\ +\x9b\x84\xe9sx0\x1fo\x88,^\x1a\x97\x96\x98\xa0\ +\xecN5\x95\xc1M\x12k\x15\x89$\xc3\xc2\x05\xfcB\ +\xa5\xa6\x0c\x14\xc2\xc7)\x83\x91v\xb9\xbc\x02\xb6\x1c\xeb\ +O\xb5Jy\x12Y\x0b\xc93\x94\xc1M\x93\xeb\xe4\x17\ +b\xa7\x5cU\x94k\xa4\xc8\x10\x11\xdb\x10\x81\xd8\xe8#\ +\x12\xa2\x7f-\x99H\x0c\x07M)OUq\xda\x02\xa8\ +\xc8\xb7Bu\xf3\xb1\x8e\xf9\xadp\x1d\x09\xea~\x9b\x05\ +cO\x90\xab\x22\x1ft\xc4\xd0\xc7\xa01\xdc\x14\xf3\xa2\ +*T<\x95\xba\x98b\x8f\xd6\xab(O\xe1\x08\xb0\x09\ +\xa0'\x81\xb2\x11X\x02B\xdd\xa5\xba\x07@\x17;\xe5\ +\x98\x1b\x99\x08\xef\x1f\x02}\xec\x0epG\xa1|u\x97\ +\xc18\xa0\xab\xa9\xa9\xa9\xa5\xa9\xab\xa5\xa5k\xa4\xa3\xad\ +cdf\xa0\xabk`fibbfbbi\xa4\ +\x8b\xa1\xfe\xafe\x10\xf4tt\xf4\xf4\xf5\x0c\xf5\xf5\x0d\ +M\xf5\xf5\xf5M\xd1E\xdfT\x91\xc5\xa85\x05\xd4\xed\ +\x03F\x9a\x90\xf9<\x12\x81\x0e\x88F\x04\x92\x11\xa1\xee\ +*\x14\x94Rw\x88\x10\x0a\xb9\xd4 `\xa8W\x1c\x09\ +\x10\x88d\x0d\x0aUSK[\x87\xd0<\x92\x00\x88$\ +e\xa4! \x90\x09$\x22\x99\xa8A\xa5hj\x90t\ +\xbda\xa4\x11\x89\xdc\xd5\x98\xa9\x11\xde\x97mB\x1f<\ +\xda\x8bb:c\xc9w\x11\x0e\x8ef)\xfb\xf3\xbd}\ +$cNGR\x9d*R\x1f_\x7f\xc2\x91\xfa\x9a/\ +\xdd4\xd69\xea\xab4n\xf4\x81e2?\x8b3\xe9\ +\xbf\xf3\xfe\xda<\xee\xe0Y\xf9\x8d\xa71.3\x97\x7f\ +\xbee\xd6\xa1s\x7f<[\xb1\xf5\xc7\xf37\xab3\x0a\ +J\xc7\xcf^\xb9\xed\xa7\x0b\x7f>\xf7\x8f\xcd,,\x9b\ +0g\xd5\xf6\xc3\x17o\xbd0\x02D\x22\xe4\x96\x8c\xf1\ +D\xa5h\xf8b,te\x1a\x93!\x07\x83\xe9&\x1a\ +^\xa3g\x98\x22\x0e\xf6\xa7\x9c~\xec\xed\x98\x7f]2\ +\xa6\x222\xd5\x8c#\xf5y\xe2DA\x0cP\x9d}\x0f\ +\x9c\x81L,\xb3\xe0F\xa7\xfb\xc9x\xbf7\xb0\xf0n\ +\x0e\x5c\x1aY\xa8\xfb\x0d\xe8\x920\x9aF \x14T\xa7\ +U\xc4;us\xac\x88\xef\x15\xefX\x91R\x11\xef8\ +sy}@R\xdd\xa9\xea4\xb7\x05\xbfN\x9dV\x10\ +\xb9\xdfm\xcd\x8a\x87z\xd6S\x08!\x17\xc6\xa5U\xa4\ +F.\xaf^h\xb7!v\xdd\xa4G\xe2Z\xc9\xaa\xa2\ +\xe7\xf67\xfdk_o\xac\x94\xae{\xd3o\xeb\xf7\xf6\ +[Y\xd6\xb5G\x17^\x1d\x90uz\xf6\x90:\xe0T\ +Y\xf6f{>\xa8y\x9a\x1e \x12\x16\x04\xdd\xbb\x9b\ +n\xfb\xe5\xe11V\x03^\xbd\xfa\xfa\xf5\xe5\xf2\x8a\x8a\ +oV\x9c(\xee\x97\xf3\xbb\xd5\xe95.a\xe6\xbc:\ +\x90\xbdS?h\xb2\xe0\xf8\xfa\x19'\x8el\xae\x03\xc1\ +\xd4\x8d\xc1ww\x97\xad\x91\xf7\xd7\xfaeKM\xf9\x82\ +\xde>y\xb5\x87o\x95g\xdf\x0bv\x0aY\x11{A\ +8vz\xd5oO\x8b\xc9O\xf6\x14\xd7\x81\x93K&\ +'V\x16\xcf\xb79csv\xb5Cr\xe6Tw\xfd\ +Y\x17\x87\xcd\xe9\xf5m\x90\xf9\xd9;\xb5r\xc6\xf9\x09\ +\xaf\xec\x17\xbc)p\x5cu\xbe\x22;X\xe7\x9e\x9d}\ +\xd6\xda.5n+'n\x1a#\xaf\xddZ\xf8\xf4\xd2\ +V\x85\xf8u\xa0\xee4\xa6\x94@\xfb\xac\x9a7\x03\xec\ +\x8d\xfb\x1b\x1c\xdd\x16m\xb6\xe8\xf5\xcb:\xf0\x07s\xe8\ +\xca\x98\xe8_\xfdC^]\x13l;\xc8\x18\xfe\xbd\x13\ +d$\xe6\xda\x8as\xc2_\xbe\xfdY\xfa\xc5\xfa\x91\xf7\ +\x08o\xacc\x9f\xa7;\xce\x9cc>;\xf7\xab\x01\x8c\ +\xad[\xfc\x0eS\x16\xe4>\xebgp+pXh\x9f\ +\x9aU\xa7\x9et\x17\x9c\xba\xb2j\x86\xf3\xe5\xddO\x1f\ +\x17>-\xc9\xda\x9bZ\xe3\xac_\x1es\xa4t\x00\xbb\ +v\xeb.\xd2\xde\xc0%S\xad\x07\xf4\xdf\xeb{y\xfd\ +0o\x8f\xbb{\xd3\x1e\x98q\x85\xc7o\x9f\xf0;lV`\x82\xa7U\xd5e\xea#\xcf:\x10p\ +\xa6bQ6l:\xa9ug0\xad\x85\xa4W\x8f]\ +q\xf9L\xcd\xd7[\x02\xec\xe3\x0f\xed\x99P\xea\xe6r\ +\xb9VtJrb\xe0\xba\x8b,\x8f\xd0\xac\x83>\xfd\ +\x1fl\xddyVT\xba\xab\x0e\xd0\x1e\x9d\x1c\xc8[4\ +z\xd6\xd9\xbfr'\xcf<>\xdb\xfb\xa1\xc3\xe6K\xe5\ +\x81_\xc6'\xb1k\x19\x9b\xb3\xee\xe7L!\x96\xc7\x1d\ +\xae9n\xe7..\xb6\xad\xe5\xcc\xab\x03\x89\xf2\xd9\x99\ +\x03\xd6\xcbK}\x82\xa7\x19\xfe\xb9#\x8e\xf6\x9c\xb6\x91\ +\xbe\xff\xf8\x91}\xbf\x14dxo\xeb\x9f=}\xb8\xd1\ +\xd5J\xfb\x9d7\xaf\xe4}6\xe2\xce\x9c\x0cJq\xee\ +\xd4\xa2\x9ad\x9dK\xe5k\xb3\x1f\xd5\x81\xc5\x153n\ +>\x1b\xb9\xec\x14\xa3,\xf9v\xaa\xb0\xdbE\x07\xf2\x91\ +\xb3\x7f\xdb\xef\xae\x03\x8b`\xdb\x19\x97\xfd\x9f~#7\ +\xb1\xab\x07\xce\x9a\x9a\xe1\xb3\xedp\xf6\x9e\xbbW\x8f\xfa\ +\xe9\xed*\x9f\xb5\xeb\xdc\xf3\x0d9u`\xe3\xd7^\xf3\ +\x7f>P\xfcWIhL8\x87Z=\xf9M\x1dx\ +f\xa15kFAF\xf4<\xf3\xc3k\x8a'\x7f\xbd\ +\x8521DoP\xaf\x98-{6>[\xc7Z\x95\ +\xbav\xfc\xd8;\x9e\x13\xae=\xdc?\xea\xd5\xde\x935\ +zi\x8f\x9fx\x1c\xffe\xa3\xf9\x17~W\x1el\xb8\ +\x92\x974\xaf\xc7\xd9\x1a\xfb\xe8\xc3\xb7_\xe6O\xda}\ +aW\xff\x0d\x0fo\x95\xffa\xfd\xf7\xc4n\xa71]\ +\x9eU<\x96}\xef^\xb5\xa6\xae\xe3\xd4\x04&\x9c+\ +\xf7/\x96\x0d7\xf8k@\x1d\xf8,\x13>\x9b\xf3\xab\ +Ekm3W\xed\xd8\xb3\xd2\xe6\x87\x91\x17\xd2\x1cG\ +\xd7\x01\xad\x8c\xcaA\x07ic\xc9\xe16\x9f\xdf\xff\xd9\ +\x82\xcd\xe6v\xd9k\xb7.i\xf2\xa5\x8b\xe5\xe7\xc93\ +\xff\x06\xe4\xb9\xc4\xf8*\xf7\x13_U\xc7\xae\xad\xa6R\ +/\x1d\x9c8\xed\xda\xd1(\xe3\xd0\xaa\xbb\xa7O\x0c\x9c\ +\xd0\xc7\xdc

\xf3\xee\xea\x97\xdfM\x15\xbd\x89\x8b\ +\x8dO\x0a\x15\x9d\xdbS\xf1\xf0\x9b+\xfdFW>\x1f\ +\xbe`\xd6\xd1\x17\xe5\x8c\x17\xf3^\x7f\xde\x9fZyK\ +6b\xfc\xb3\x93\xebi\x0fX}\x17\xfa\x16Ox\xed\ +\xb07\xa8\xa6\x0e$\xbd\xe9~7}\xc4}\xdd>K\ +\xbe\xbc/\xd8\xf9\xe3\xac]\xdf\xfda\x7f\x8d\xb3\xd7\xf7\ +H\xb7\xa0\x9c\x8b[\x02\x97\x07V\x1a_\xd4\x0b\xa7\xee\ +\xe8\xb3$\xd1\xb7o\xefn+\x96\xcc\xca e\x9d\xde\ +GHt\x0a\xad;\xf7\xbe>\xe8W\xc58\xd7\x15\xeb\ +\xc9\x07\x00\xcc\x22\x85#7\x08\x07\x5c8\x1d\xce\x87S\ +\x03\x1a\x9c\x1c\x17A\xbf\x0c:)\xe6C\x13a\x8b\x7f\ +HA\x03\x91\xf0G\x83f\xba'`\x02\xff\xfa\x01S\ +7.\x81/\x14\x11\xa1\x11Y\x02g\xa0\xe8\xcb\x15Y\ +\xd9\xfdh\xd4\x13\xd0\x88\xd4\x82\xb6+4\x97\xd8\x1c\xa9\ +815&\x0d3\xae\xa2#i\xe8\xf3\x16\xa0\x09\x9e\ +_P\x98'g\xdd\xe3\x92i4\xf0a0\xe2\x88%\ +2\xf4U\x1d\xe8\xf7\xe6\xf2\xa4\xd0\x5c#\x8c\x83~A\ +\x99L\x8c\xc2\xd1\xd8o\x9a_\x8c\xfcD4\xea\x9bJ\ + \x83\xd0o\x89\xfc\x85\x0a\xbf\x1b\x96F\xe1\x0fC~\ +n\x89\x10\x9a\x89D\xc4\xb3\x98[\xc2E\xfeC\xd0\xff\ +E\xa9\x1c\x99\x8f\xa4\x04\xe8\x1f_\xca\xe7\x95A\xff9\ +\xe8w\x14\xc8K\xf8\xd0\x8ff&\xa6%<64i\ +1\xbb\xc2Q\xc6\xe3\x14A?\x9a\x19\xe8J\xd2R\xe0\ +\x5c\x96\xdc\x13\xdaf\xba\x85*\xfe|\x15\xbf\x0c\x1al\ +H\xa8H\x91x(f\xd9\xd0\x5c9\xddh\xcc\xc0\xc0\ +\x00Z\x1c\xafL\xc0\x93\xc9\xdc\x93\xd9\x9cb\xb6\x84K\ +\x8b\x14\x95\x88\xd9B8\xc3S\xc8\x8c\xc1\xf8\xadO\x87\ +\xa8(\xea\xbd\x91\xad\x04\xaa[\x85\xefi_\xac\xce\x08\ +\xe6\xc7\x1a\xc3ZJ'Z\x0a\xed.8\x0b$Mo\ +\x0c\xcb\x9f\x07\xc0\xf6\xcf\x01\xb0\xfc\xad1\xccq1l\ +\xa3\xb0\xde\xb6\x9dT\x91\xc7\x1c\xb5\x17\x95\x8f\xfc\xf0y\ +\x1c\x0f\xa4\xd0\x06\xfcc\x82V@\x85\x9e\x07*\xaeA\ +=\xb4(\x85eKCz\xe3@\xfbU.\xa1\xc1\x19\ +8\x87Gso\xde\x88?:c\xcb|\xb8\xa5\xf0\x0a\ +xh\xa6\xcf\xa3e\xc0V\xc6\x17\x16\xc2\xea\x16r\xf9\ +\xd8\xf7\x8a\xf8\xc2wU\xe2Gfk\x06E\xbb\x860\ +Y^\x0bLs=\x80\xe1IS@zp\x0c\x90M\ +t\x00)\xe7\x1b\x18Ch\xa8\xb7\x04\xad\x0c\x80\x9e\xbc\ +L\xfb[\x8av\x8f\xa1\x85i&q\x1a\xbaH\xf9\xd8\ +\xe4\x0aD\xa6\xa4\xd18rI\xa9\x22\x0e\x9bOi\x00\ +m\xd8I\x99\x82.\xc0\x0e8\x00W8\xeb\xf7\x82\x9d\ +L\x10\x08\x03\xd1\xa0\x17H\x02i \x1b\x0c\x04\x1c\xd8\ +\x19\x95\x00\x09(\x03#\xc0h0\x1eL\x06\xd3\xc1,\ +0\x1f,\x02\xcb\xc1\x1aP\x096\x81\xed\xe0\x07\xb0\x1f\ +\xfc\x04\x8e\x82S\xe0<\xb8\x0c\xaa\xc0Mp\x0f<\x06\ +\xcf\xc1+h\xe0R\x09z\x04\x13B\x17\x82=\xc1\x89\ +\xd0\x83\xe0E\x08 \x84\x10\xa2\x09\x09\x84\x14B6!\ +\x8fPH\x10\x12\xe4\x84\x11\x84\xb1\x84\xc9\x84\x0a\xc2|\ +\xc2\x12\xc2\x1a\xc2w\x84\xef\x09\xfb\x09G\x08\xa7\x09\xbf\ +\x12\xae\x13\xee\x10\xfe\x22\xd4\x10ID]\xa2)\xd1\x96\ +\xe8Ld\x10\x03\x88\xe1\xc4\xde\xc44\xe2\x00b!q\ +0q\x18q\x1c\xf1K\xe2\x5c\xe2R\xe2z\xe26\xe2\ +~\xe2Q\xe2yb\x15\xf1\x1e\xb1\x9a\x04H:$s\ +RW\x92;)\x80\x14IJ\x22\xf5#\x15\x90$\xa4\ +\x91\xa4I\xa4\xd9\xa4\xa5\xa4J\xd2N\xd2a\xd2YR\ +\x15\xe9>\xe9o2\x85lB\xa6\x91\xdd\xc9A\xe48\ +r:\x99C\x1eL\x1eI\x9eB\x9eO^M\xdeF\ +>D>K\xbeN~L\xae\xd5\xd0\xd3\xb0\xd1\xe8\xa1\ +\xc1\xd2\x88\xd7\xc8\xd2(\xd4(\xd3\x18\xaf1[c\xa5\ +\xc6V\x8d\x1f5\xcek\xdc\xd4xN\xa1P\xcc).\ +\x14\x7fJ\x1c%\x9b2\x882\x9c2\x85\xf25e#\ +e\x1f\xe54\xe5\x06\x05\x0eh\xd4.\xd4\x1e\xd4`j\ +\x12\x95M\x95Q\xc7S\xe7Q\xd7S\xf7R\xcfPo\ +R_j\xeah\xdakzi\xc6h\xf6\xd3\x14j\x8e\ +\xd1\x9c\xad\xb9Vs\x8f\xe6\x19\xcd[\x9a\xaf\xb4\x0c\xb5\ +\x9c\xb4XZIZ\x5c\xad\xa1Z\xd3\xb4\x96k\xed\xd4\ +:\xa9uS\xeb\x95\xb6\x91\xb6\x8bv\xb0v\x9a\xf6 \ +\xed\xd1\xdas\xb5+\xb5\x7f\xd4\xbe\xa2\xfdTGG\x87\ +\xae\x13\xa8\xd3W\x87\xaf3Jg\xae\xce\xb7:?\xeb\ +\x5c\xd7\xf9[\xd7X\xb7\xbbn\xa4n\x8e\xae\x5c\xf7K\ +\xddU\xba\xfbt\x7f\xd5}\xaa\xa7\xa7\xe7\xac\x17\xa6\xd7\ +OO\xa6\xf7\xa5\xde\x1a\xbd\x83z\xd7\xf4^\xea\x9b\xe8\ +{\xe8\xc7\xebs\xf5\xcb\xf5\x17\xe8o\xd3?\xa3\xff\xd0\ +@\xcb\xc0\xc9 \xdc`\xa0\xc10\x83\xd9\x06\x9b\x0dN\ +\x1a\xdc7\xd42t6\x8c4d\x1b\x8e4\x5c`\xf8\ +\xbd\xe1E\xc3j#\x13#\xa6Q\x92Q\x89\xd1\x14\xa3\ +\xb5FG\x8cn\x1bS\x8d\x9d\x8d\xa3\x8d\xb9\xc6\xe3\x8c\ +\x97\x19\x1f4\xbeaB2q0\x894\xe1\x98\x8c5\ +Yn\xf2\xa3\xc9MS\x8a\xa9\x8bi\xbc\xe9 \xd3\xc9\ +\xa6\x1bLO\x98>636\xf31\xcb0\x1bb\xb6\ +\xc0l\xb7Y\x959\xc9\xdc\xd9<\xde\x5c`>\xcd|\ +\x93\xf9\x05\xf3\x1a\x0b[\x8bp\x0b\x9e\xc5D\x8bJ\x8b\ +3\x16/,\xad-\xc3,y\x96\x93,7Z\x9e\xb7\ +\xac\xe9B\xeb\x12\xdd\xa5\xb8\xcb\x8c.\xdb\xbb\x5c\xb5\x22\ +[u\xb7\xeakUf\xf5\x8d\xd5\x8fV\xf7\xadM\xad\ +\x83\xac9\xd6\x93\xac7Y\xfffC\xb4\xe9n\x93b\ +3\xdcf\x99\xcd1\x9bj[;\xdbX[\xb1\xed<\ +\xdb\x83\xb6\xf7\xed\xcc\xed\xc2\xec\x06\xd9\xcd\xb4\xdbcw\ +\xc7\xde\xc4>\xc4\x9eo?\xd3~\xaf\xfd]\x9a\x19-\ +\x9c&\xa0\xcd\xa5\x1d\xa2=\xeej\xd35\xae\xab\xbc\xeb\ +\x92\xae'\xba\xbe\xa2\xbb\xd0\xd3\xe9c\xe8\x1b\xe9W\x1d\ +\xb4\x1d\x02\x1c\x0a\x1cf:\x1cpx\xech\xef\x98\xe8\ +8\xc2q\x9d\xe3oNZN\x01NENs\x9c\x0e\ +;\xbdpvq\xcet\x9e\xe0\xbc\xdd\xf9\xb6\x8b\xa5K\ +\xbc\xcb0\x97u.W\x5c\xf5\x5cC]\x07\xbb.u\ +=\xd7\x8d\xd2-\xa0[q\xb7\xaf\xbb\x9d\xeaN\xec\xee\ +\xdb\xbd\xa8\xfb\x82\xee'{\x10{\xf8\xf5\xe0\xf7\xf8\xba\ +\xc7i7\x0d\xb7@7\xa1\xdbR\xb7\x8b\xee\xba\xee\xe1\ +\xee\xa5\xee\xeb\xdc\xaf{\x98{$x\x8c\xf1\xd8\xee\xf1\ +\x90\xe1\xc8\xe8\xc7\x98\xc18\xcc\xa8\xf5\xf4\xf5\x14x.\ +\xf7\xbc\xcc4f\xf6b\x8ea\xeed\xfe\xe5\xd5\xdd\x8b\ +\xe3\xb5\xc0\xeb\x9c\xb7\x9ew\x8cw\xb9\xf7\x0e\xef'>\ +=|x>\xdf\xf8\x5c\xf25\xf1M\xf4\x9d\xe0{\xc0\ +\xf7\x8d\x9f\xbf\x9f\xc4\xaf\xd2\xef\x8e\xbf\xa3\x7f\x9e\xffB\ +\xff\x8b\x01\xa6\x01\xc9\x01S\x02~\x0e\xd4\x08\x8c\x08,\ +\x0f\xfc!\xf0o\x96\x1fK\xc6\xda\xc4z\x14\xe4\x1eT\ +\x1c\xb46\xe8vO\x97\x9e\xbc\x9e\xcb{\xde\x08\xa6\x07\ +\xb3\x83\x97\x04W\x85\xd0B\xf2B\x16\x87T\x85v\x0d\ +e\x87.\x0d\xfd=\xcc!\x8c\x1b\xb62\xecVx\xb7\ +\xf0A\xe1\xeb\xc3\x1fFxFH\x22\xb6F\xbc\x88d\ +E~\x16\xb9/\x8a\x14\x15\x1b5)\xeaD\xb4qt\ +z\xf4\xfc\xe8k1\xf4\x98\xc2\x98u1\x8fc}c\ +\x87\xc7\xee\x8b\xd3\x88\xeb\x1d7#\xeeb\xbcm<'\ +~M\xfc\xe3^\xfe\xbd>\xebu\xa8\xb7n\xef\xd4\xde\ +\xf3{\xff\x9e\xd0=A\x92\xb03\x91\x98\xd8+\xf1\xab\ +\xc4+}\x9c\xfa\x08\xfblO\x02I\xf1I_%]\ +MvI\x1e\x9c\xbc\xab/\xa5or\xdf\x05}\xffL\ +a\xa6\x8cH9\x9cj\x92\x9a\x9b\xba6\xf5yZD\ +\xda\xb4\xb4\xcb\xe9\xae\xe9\xf2\xf4\x03\x19\x06\x199\x19k\ +2^dFeVdVe1\xb2>\xcb:\x9am\ +\x95\xcd\xcf\xde\xd1\x8f\xda/\xa3\xdf\xca~\xd5\xfd\xa3\xfb\ +\xcf\xea\x7f3\xc77g|\xce\x85\x01.\x03\x86\x0c8\ +2\xd0j\xa0`\xe0\xee\x5c\x83\x5cv\xee\xe6<\x8d\xbc\ +\xcc\xbc\xb5y\xaf\xd9I\xec\xa5\xec\xea\xfc\xf8\xfc\x85\xf9\ +\x8f9\x91\x9c9\x9c{\xdc0\xeeL\xee\x1d^0\xaf\ +\x82w\xab \xb8\xa0\xa2\xe0vap\xe1W\x85w\x8a\ +B\x8bf\x17\xdd\xe7G\xf2\xe7\xf3\x9f\x0c\x8a\x1b\xb4h\ +\xd0\x8b\xe2\xa4\xe2U\xc5u\x82L\xc1\xc6\x12\xcd\x92\xbc\ +\x92\xef\x85\xc6\xc2b\xe1!\x91\x9dh\x88\xe8\xb4\xb8\x87\ +x\xbc\xb8j0k\xf0\xac\xc1\x8f%\xbd%+\xa5\x04\ +\xe9\x00\xe9\x0e\x99)4\xa6\x8e\xc9]\xe5\x9f\xcb\xaf\x97\ +\x86\x94.(}Y\x96Q\xb6y\x88\xd1\x10\xe1\x90c\ +C\xbb\x0f\x9d8\xf4\xd6\xb0\x98a+\x86\x93\x87s\x86\ +\x1f\x18\xd1u\xc4\xe8\x11\xd7?\x0b\xffl\xc9H\xc2\xc8\ +\xfc\x91\x07\xca\x1d\xca\xc7\x95\xdf\x1c\x15;j\xf5h\xed\ +\xd1\xc5\xa3\x8f\x8f\xf1\x1cS1\xe6\xd9\xd8\xcc\xb1;\xc7\ +\xd9\x8e\x1b5\xee\xc6\xe7\xb1\x9f\xaf\x1b\xaf?^2\xfe\ +\xe2\x84\xa0\x09\x8b\xbe \x7f\xc1\xff\xe2\xc4D\xef\x89\xf3\ +&\xd6N\xe2N\xfae\xb2\xe7\xe4\xd9\x93_O\xe1L\ +\xf9e*s\xea\xdc\xa9u_\x16|yb\x9a\xdf\xb4\ +o\xa6S\xa6\x0b\xa7_\x98\x11:cu\x85Q\xc5\xb0\ +\x8a\x1b_%~\xb5m&m\xe6\xa4\x99\xcff\xe5\xce\ +:2\xdbg\xf6\xa29\xdas\xe4s\xaa\xe6&\xcc\xdd\ +1\xcfq\xde\xf4y\xaf\xe7\x17\xcd?\xbf b\xc1\xc6\ +\x856\x0b'.|\xf15\xf7\xeb3\xdf\x84}S\xb9\ +\xc8v\xd1\xe4E5\x8b\xf9\x8b/-\x89]\xb2m\xa9\ +\xf3\xd2\xd9\xcb(\xcbJ\x97\xfd\xb9\ +\xf1\xbe\xfb\xfb\x0b\xf7\xdf8\x90{\xe0\xf2\xc1\xac\x83\xe7\ +\x0e\xf5=t\xe2\xc7\xde?\xfe\xfcS\xccO\x07\x0f\x87\ +\x1f\xde\xfbs\xf0\xcf?\x1ca\x1d\xf9\xfe\x97\x80_\xb6\ +\x1f\xf5;\xba\xed\x98\xef\xb1\xad\xc7}\x8fo=\xe1w\ +b\xdbI\xff\x93;N\x05\x9e\xday\xba\xe7\xe9=g\ +B\xcf\xec?\x1bu\xf6\xa7s\xf1\xe7\x8e\x9e\xefs\xfe\ +\xf4\x85\xf4\x0b\x97.\xe6\x5c\xac\xba\xc4\xbdt\xfbW\xc1\ +\xafO~+\xfd\xed\xd5\xe5QW4\xaeL\xbajx\ +u\xf65\x9bkK\xff\xd3\xed?\x1b\xab\xfc\xaav_\ +\x8f\xba~\xec\xf7\xd4\xdf/\xdf\xe0\xdc\xb8\xf7\x87\xf4\x8f\ +\xd77\xc7\xfd\xa9\xf7\xe7\xec[\xf6\xb7\xd6\xdc\xf6\xba\xfd\ +\xc3\x9d\x98;\xa7\xee\xf6\xbf{\xf3\x9e\xf8\xde\xab\xfb\xe3\ +\x1f\x18=X\xf8\xd0\xf5\xe1\x96Ga\x8f\x8e=\xcez\ +|\xf3\x89\xe4I\xdd_S\x9evy\xba\xea\x99\xcf\xb3\ +\x03\xd5\xc9\xd5\xd7\x9e\x97<\x7f\xf5b\xd2\xcb./W\ +\xff\x1d\xf0\xf7\xe1\x9a\xcc\x9a[\xaf\xca^S_\xcf}\ +\xd3\xed\xcd\xce\xda\xde\xb5W\xeaJ\x1a\xdeH\xe0\xc0\x81\ +\x03\x07\x0e\x1c8p\xe0\xc0\x81\x03\x07\x0e\x1c8p\xe0\ +\xc0\x81\x03\x07\x0e\x1c8p\xe0\xc0\x81\x03\x07\x8e\xffc\ +\x90\xc9dMGG\xc7\xac\xce\xe6\xe3\xff\x15aaa\ +\x8b\x0a\x0a\x0a\xea\xe0\xff7\xa8.:\x9b\x9f\xff'\xa0\ +v\x8ft\xaft)))Guuu\xed\xda\x83\x96\ +\x8e\x8e\x8e\x15\x9dNO\xf7\xf3\xf3\x9b\xd0\xabW\xaf\x1d\ +\x19\x19\x19\xe7srr\xfe\xe4p8/\x90C~\x18\ +v\x01\xc6}\xef\xef\xef\xff\x85\x83\x83C\x06\xca\xd3\x1e\ +\xbc|*@\xed\x1d\xb5{\xd5:\x188p\xe0]k\ +k\xebw\xec\xf2\xfd0@\xfdY{zz\x96%'\ +'\x1f\x86e\xd7\xaa\xd2i\xa5\xab\xed\xdb\xb7\xef\x11X\ +\xc6\x10\xd8.l\xd5\xc1\xd3\xa7\x0877\xb7\x12.\x97\ +[\xa3\x94\x9b\xc7\xe3\xbdvww\x17}ly\x16\x16\ +\x16\x01QQQ\xaba9\xaf>B\xe7-:T\x16\ +,s\xad\xa5\xa5%K\x9d\xb2\x7f*\x80r\x05\x0d\x18\ +0\xe0\x96\xaa\xcc\x91\x91\x91+\xe13\xa2\xdd\xda2`\ +\x1b\xb5A:R\x97\xce\xdf\xe5\xa2\xa3\xa3\xd7\xb7W?\ +\xd9\x99\xd0\xd6\xd6\xee\x02\xfb\x8a\x9fTeMKK;\ +\xad\xaf\xafO\x7f_>\x12\x89DA}D~~\xfe\ +\xb3\xf6\xd6\xbd\xd2AZ\xd5L&s\x18\xa4M\xed(\ +\xfdt\x04\x90.CBB\xe6\xa9\xca\x9a\x97\x97\xf7\xd0\ +\xd6\xd66\xb6\xa5\xf46661\x99\x99\x99\xbfv\x94\ +\xde\x9b\xbb\xac\xac\xac\xcb\x90\xb7\xb8\x8e\xd6S{\xc3\xd5\ +\xd55\x1f\x8e\x09/Ud}\x83\xc6R\xe59g\xf8\ +G\x84\xb6\xcc\xe7\x9d\xa5\xf7\xe6\x0e\xd9L\x88\xa7\xce\xd6\ +\x9b:ann\xee\xdb\xbf\x7f\xff\xdfU\xe5\x8c\x89\x89\ +\xd9\x80\xfa\xf9\xf8\xf8\xf8\xad\x9d\xad\xf3\xe6\x0e\xda\xae\xdb\ +\xa9T\xea[\xdf:\xfa7CKK\xcb,11q\ +\xaf\xaa\x9c\xf0\xb9\xf8\xbb\xb3u\xfd\xbe\xfe\xc8\xd8\xd8\xb8\ +Gg\xebM\x9d \x12\x89d\x16\x8b5\xa3\xb3u\xdb\ +Z\x07\xc7\xe6\xa7p\x5c\x8a\xeel\xbd\xa9\x13P\x9e\xa8\ +O\xb9\xdd7whN\xfd\xbfR\x07\xc8\xc6A\xf2\xa8\ +C/9997\xd1\xb3\x84l\x16##\xa3\xee\x14\ +\x0aEOCCC\xd7\xd0\xd0\xd0\x19\x8e57\xda\xa1\ +\x0eb:[\x7fm\x01\xb2;\xd5\xa1\xfb~\xfd\xfaU\ +\xd1\xe9\xf4\xd4\xf7\xd9(\xa8\xefn\x8f\xe7\xe0]\xb6\xf3\ +\xa7\x0ed\xff\xa0yN[u\x10\x10\x100\x05\xce\xa3\ +\xb5\xfe\x89^{\xe8\x1f9$\x83\x99\x99\x99OG\xe8\ +L]@\xf3\xfb\xe6\xeb\x11\x1f\xe1\xde\xf4\xe8\xd1cP\ +ki\xb6\x97\xfe\x91C\xb2\xfc[\xd6\xf0`\x9f\xac\x9f\ +\x9e\x9e~\xb6\xad2\x7f\xe8\x1a^{\xea\x1f9\xb4\x96\ +\x82\xc6\x9b\xf6\xd2\x9b:\x80\xe6\xb7qqq[\xd4!\ +/\xea\xf3MMM[\xfd\xa5\x90\xf6\xd6?r\xb1\xb1\ +\xb1\xdf\xa9|\xab\xec\x93\x83\x97\x97\xd7\x085\xc8\xd9\xb0\ +\xd6\x0f\xc7\xbf\xe7\xce\xce\xce\x03ZC\xbb#\xf4\x8f\x1c\ +ZGio=~\x0c,--{\xa2\xb5\xff\xb6\xca\ +\x87\xec\xcb\xbc\xbc\xbc\xc7\xcd\xc2\xa6\xa3y\xdc\xfb\xe8w\ +\x94\xfe\xd1\xbb\x04h[\xf8w\x94^[\x03\xd4\xe7\xa3\ +\xfeB\x1d}\x0e\xd4\xb3\x86\x81\x81\x81\x13\x1cC\xce\xa9\ +\xc6\xf5\xe9\xd3\xe7\x80\xb6\xb6\xb6\xc5\xbbx\xe8(\xfd#\ +\x07i\xfd\xf6!\xef6\xda\x1b\x81\x81\x81S\xd5!\x97\ +\xbf\xbf\xffDe\x99h^\xd5\xfc}\x0c\x9c\x7f\xfd\xf1\ +\xae\xb6\xd7\x91\xfaG\xce\xc7\xc7gt\xc7i\xf8\xdd@\ +k\x86h\xcdD\x1d2YYY\x855/\x1f\xbd\x9b\ +Q\xed\xd7\xd0:\x86\xab\xab+\xb7y\xba\x8e\xd6?z\ +\xaf\x81\xdaH\x87(\xf9=\x80\xfa)U\x87H\x15h\x8d\xa8\xf9\xf8\ +\x8a\xd6\x92\x0c\x0c\x0c\x1cQ\xd9\xd0^\xb8\xdeV>\xe1\ +\xdc\xf7\x91r\xde\xf1\xa9\xc0\xd9\xd9y\xa0:\xdaU\xf7\ +\xee\xdd?\xf0+\xdao\x03\xf5\xf1={\xf6\x9c\xd9\x5c\ +gAAA_\xa9\x83G\x07\x07\x87Lu\xe8L\xdd\ +P\x9e\x87i\x8bC\xedS\xb5\xbfh\x0bP\x9bh\xf6\ +\xfe\xffc\xce\x114qh\xddC\x1d\xbc\xb5\x07\x90\xed\ +\xdd|\x8d\xe0c\x1c\x9c\xe3.W\x17O\xa6\xa6\xa6^\ +\xeaX\x1bG.%%\xe5\xd8\xa7\xbeg\x1a\xbd\xa7F\ +\xfbt\xda*\xeb\x87\xbc{\xff'\xa8c\x8d\x10\x8d\xeb\ +\x9fZ\x9f\xff.\xc06\xe7\xa9\x865\xe9Z\x0f\x0f\x0f\ +I[yA6h[\xfb\x1dd[\x98\x98\x980\xd4\ +\xa1\x9b\x8e\x82\x9d\x9d]\xbc:\xe6\x05p\x1c\x9d\xf51\ +\xfb\x0e\xd0;\xb9\xe0\xe0\xe0\xb9m\xa5\x8fd\xf8\xb7\x9e\ +\x11prr\xcaQG\x1d\xa0\xf3\x8dp,\xcd}\xd7\ +\xfb\x01U \x1b\xd3\xc5\xc5%\xaf\xf9\xda\xd0\xc7\xea\x1e\ +\xc9\xd0\x11\xbaj/8::f\xabk~\x8c\xde9\ +\xa1y\x0f:_\x8a\xe6Z\xe8,\x01r\xc8\x8f\xc2\x90\ +\xfd\x85\xecLu\xd0B<#\xde;[\x7f\xea\x00\x9d\ +NOS\xe7y\xc6\xf6vH\xf7\xe8\xbcqg\xebM\ +\x9d\xa0\xd1h\xc9\xea\xda\x07\xdd\x11.00\xf0\xcb\x7f\ +\xda\xf3\xf2o\x83\x99\x99\x99\xb7:\xe6\xff\xed\xe5T\xcf\ +1#\x87\xce\xee\xa03<\x9d\xad7uBSS\xd3\ +4!!awg\xeb\xba\xb9C\xba\xd6\xd7\xd7\xa7\xc5\ +\xc4\xc4T\xaa\x86\xa35)\xb4\x97\xbb\xb3\xf5\xa6N\xc0\ +\xe7\x9a\x84\xd6:;[\xe7-\xf55h\x7f\xa7\x97\x97\ +\xd7p\x18\xfeF\xe5\xb9x\x89\xcetv\xb6\xde\xd4\x0d\ +4G\xe8\x8c}#J\x87\xf6\x5c@\x1ez\xb7\xc4\x1b\ +\xb2\xf9\x91\xbd\xa5\x9a\x1e\xceEf\xb7\xc6\x06\xfe7\xa1\ +\x93\xce\xbf?k\xcd\xf9w\xb4\xae\x8e\xf6\x9d\xab\xe6M\ +JJ\xfa\x11\x9d\xf5\xef(\xfdt\x14\xd0\xda\x0a\xfaf\ +D{\xeb\x1e}\xdb\x03\xcd\x19Z\xcb\x17\xda\xe7\xd9\x9c\ +/4\x1fD\xdf\xbchO}t\x16\x90\x8d\x14\x1e\x1e\ +\xbe\xa4\xd9\xf9\xf969\xf4\xae\x10\xed\x8dh\xcb9\x22\ +\xb4\x16\xd5l\x1fd\x8d:\xd7\x08?5 \xbb\x0f}\ +\xdb\x06\xd9J\x1f3wCy\xd0>+X\x86\x10\x96\ +e\xae\x0e\x9e\xac\xac\xac\xc2\xd17\x8eT\xe9\xa09\xf7\ +\xff\xfa\xb7\xbf\xa8T\xaa\x11\x1a\xabQ\x9f\x8d\xde\xe7\xa2\ +o2eff^Bk\x0a\x0a \x0a Artboard\x0a \ +Created with Ske\ +tch.\x0a \ +\x0a \x0a \x0a \x0a \ + \x0a\x0a\ +\x00\x00\x04S\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22?>\x0a\x0a \x0a icon / outl\ +iner / entity / \ + error / Editor \ +only\x0a \ + Created w\ +ith Sketch.\x0a \x0a \ + \x0a \x0a\x0a\ +\x00\x00\x15\xcc\ +I\ +I*\x00j\x08\x00\x00\x80?\xe0@\x08$\x16\x0d\x07\ +\x84BaP\xb8d6\x1d\x0f\x88DbQ8\xa4V\ +-\x17\x8cFcQ\xb8\xe4v\x0b\x02\x7f\xc7\xa4R9\ +$\x96M'\x94JeR\xb8\xa4\x82Y/\x98Lf\ +S9\xa4\xd6a.\x9bNgS\xb9\xe4\xf6}#\x9c\ +O\xe8T:%\x16\x8d/\xa0\xd1\xe9T\xbae6\x9d\ +\x1f\x81\xd3\xeaU:\xa5V\x91Q\xabVkU\xba\xe4\ +B\x93]\xb0XlU*\xfd\x8e\xcdg\xb4N\xec\xb6\ +\x9be\xb6\xdd&\xb5\xdb\xeeW;\xa4J\xe3u\xbc^\ +o7{\xd5\xf6\xfdi\xbe_\xf0X:\xde\x07\x09\x87\ +\xc4Sp\xd6`\x0e6\xb4\xd0\xc8\x02\xdf\xb91L\x14\ +3\x05\x0dH\x02PWX\x0b<\xe6\xc6\x80\x5c\xc0]\ +#XY\xa7}Vqx\x0a\xc5\xcfCJflB\ +\x90R\x86\x84\x9f \x22AA\x11\xd7\x9e\x85o X\ +\x828K-8\xb1\xe9G\xd5\xda96\x1d|\xf5\xa9\ +\xcf\x06>:G8)\xd2\x0a\x0c\x9e; \xa8>\x10\ +!1\xc5\xd4\xcf9vo\x1dw\x9b6f\xfaK\x12\ +\x04\x84\x14/RohL\xc3?\xa2\xf6s\xe5\xb1~\ ++~y\x5c\x80\x04\xf4\x99\xa4*\x0a<,G\xe3B\ +8\xbe\x81\x99(\x99\xbfK\x04\x1a\xac\xbf\x893\x9ej\ +\x00\xce\x91\xf0U\xa0\xa2r\xde\xd0\x92\xd0H\xd6\xab\xa4\ ++\xec\x1e\xabB)+bf\x13\x88(\xc6\x94\x1c\xa8\ +)\x9c\x82\x9dH)\xe2\xd0\x82I\x03\xde\x82\x06\xa8+\ +f\x924#\xe4\x13\x01%\x11\x1b\x0a\xd6\xaeQ*;\ +\x13\x8d\xe8+\xda\x8e\x1d\xc8)*\x82\x94\xc1\xa4\xa4l\ +\x22\xc9\x00\x02h\xcb\x01\x81\xf9-\x8c\x11R\x0a\x05\xa3\ +1\x08\x00)JA\xa1`\x92\xc8J\xd4\xd2\xa9\xc8\xc8\ +\xc4N\x16\xa0\xa6z\x0a\x01\xa2\xb3\x11\x1c\x02O\x03\xf8\ +a=\x9e\xa9y\xad?\x82g\xb5\x05%\x80\x02\xe22\ +y\xcf\x00 I=\x86\x11\x8a;5\xaa\xd4\x82\x9f6\ +\xa2\xf19j\x82\x89H\xa9\xea\xcf\x00B\x88eO\x97\ +j\x19\x9dQ\x8b\xc7\xf5LONh\x93BJ\xc1#\ +b=I*\x95\x82\x9bJ\x22F}l 2g\xe9\ +~\x8a\x9f\x14\xc4\xcb]\xa9\x918\xb6\x82\x94H(\x04\ +\x88\x9fm\x08U\x04\x9b\x88\xd5d\xb2H\x90\xdb\x1c\x8d\ +D\xe5\xa2\x0a%\xa2\xa3\xa4\xcaF\xab0\x01(\x90C\ +\xe8\xa1)2\x8d\xb6u\xa2\xbaY\xea]h\x86\xc2n\ +\x8b\xa4\xed \x80:\x22i\xc1!\x8bB~\xab&\xbd\ +\xf4\x06\x9e\xb7\xed\x9a\x82\x02\xc8\x89\xc72\x83\xd74\xc4\ +\xbd\xdc\xebm\xd6\x86@\x02\x9a@VULh\xdd\x04\ +\x92k\x1cNG \xa3\x8a*\x19\xcc\xb1|\xeb\x84\xae\ +WJ\x95\x85\xa1p\x012\x90\x0c\xc8\xa852\x9c\xeb\ +\x1dFg\x07U1\xfcb\xe2 \x08\xf1\x04\x912\xae\ +@\xb7\xe4J>H\x85D\xe5\xb2\x0a$\xa2'\xac\xca\ +\xec-\x19x+\x99Q\xc8\x849\x0fgX:\xf1\x9e\ +\xa8\xd9\xfa\x13\x13\x9a\x08(^\x88\x9bs(L\xb7\xc4\ +\xe7\xda\x0a\x02\x22%\x84\xca(\xea+\xf6\xa8\xa2\xea\xc8\ +DO\xa6\x82\xa8\x89\xb12\xb2\xabtO^\xde(\x89\ +\x932\x87\x1bLE\x9d\xad\x1bj\x0f\x13\xb8\xe8$\xc0\ +\x88nr\x96\xea\xb6\xee\xe8-\xe4\x88\x1a\x93,\xe1\x8f\ +\xeaK\xae\xd6\xa2pH7\x09/\xee[\xa6\xc0\xd8\xef\ +\x00\x07\x1e\x87\xf22\x97&\x96\xf0\x0bo.\xa1\xf3(\ +/7\xc3s\xbcW>ft=\x1a\x1d\xd2\x86\x9d:\ +'\xd5\xa8\xdd\xe2\x7f\xd6\xa0\x9dx\x01\xc3\xa1\xfcHi\ +\xc5\xad\x9cn\xf3\xc8r[\xf2\xf5\xdf'\xde\x00\x01\xe1\ +x\x88w\x8d\xe4->WD\x88\xf7\x1d\xd2\xed\xd4\xad\ +\x9e\x82{\xc1\x1b_(\x0ey}\x12j\x08\x05k\x94\ +\xe0v\xb7\xe6G\x22\x0a\x03\x22&\xbe\xb52\xecH\x8f\ +\xc4\xa1\x7fi\xdc\x22\x95\x99xk$\x0a\xb8\x82\x02s\ +\x12K\x13\x10\xd14\x22%\x04\x8a\x82\x14\xffI\xf4\x10\ +'&\xbd\x09\x81$,+\x88(?\x80\xe5\x14V\x9d\ +\xd0\xb4x \x91\xe2|\x05\x8c\xd7\xa2qLAB\xcc\ +\x1b]F4C\xa0\x90\xf5\x08KT#,J\xd8g\ +\x84Vd.\xa1QS\x1f\xa6\x84\x16\xa9\xf0d\xfd\x9e\ +|2,(\x00L\x10P\xcf\x0eJ\xb0zA\x22\x1d\ +\xbf\xb9R\xdc\x80\x05\xc9\x05\x08\xc4T^/x\x90\xe5\ +\x1a@\x00}\xe4D\xd0\x89\xb8|\xcab\x0cN-\xa8\ +\x00`A\x92$\xa2@b\x8cO\xb1\x5c\x89\x99\x01\xa0\ +\x0b\x12\xd8\xfc\x1adTQ \x90\xbf\x13K\xc4d\x8c\ +\xc4F4F\xa8\xd9\x1bL\x84pKq\xcc\x8aGS\ +\xe9\x1d\xe3\x0cy=1\x94\x82A\xa8\xf8\x9e#J|\ +\x8f\xe4J7H(\xe5\x1d#\xb4x.\xb1\xeaF\xc6\ +y!\x1f\xa4\x99\x10\x92\xb1\xc6B\x119\x0c\x0c\xe4C\ +\x08\x8cE\xb2N\x00\x09\x1cD#\xec\x92\x94$>Q\ +\xc891!\xe4\xd1t\x95\xb2\xbc\x87\xcb\x10a\x1a\xc9\ +\xdcn\x04*\xe4 \x12\x00(hG8\x07\x99B\xf0\ +\xe2\x8e\x82{-d\xbc\x85\x932&M\x90\x06k5\ +\x80\x00\x82\x8f\xe0\xb0\x88L*\x0a\x04\x86\x83\x06\x11\x07\ +\xac.'\x14\x8a\xc5\xa1,\xc8\xc8*\x10\x88\x84\x1b!\ +\x00\x18\xbb\xec\x03$A\x0c\xa4\xe8\x89 \x05\xf9\x17\x96\ +\xcb\xa2\x8d\x09\x88\xb1\xf94i\xcb\xe1J!\x9c\xe8\xbf\ +7\x9e\xcf\xa7\xf4\x08\xbb\xfe\x87A\xa2\xd1\xa8\xf18\x14\ +\x0e\x11\x07\x9b\xc3@\x90\xf8\x8d\x22z\xda\xaa\x81\xdeU\ +\x86D aS\x82\xad\x86\x96\x02]v\x7f1hL\ +\xe6\xb4\x09\xcc\xee\xc7l\xb6\xcbho\xfbu\xca\xe7J\ +\x82A\xa7\xb4\xfa\x88\xc2%s\x89\xc6Y\x88xA\xe2\ +\xe7*4N\x86i\x9b\xecN\xcbg~M\xa7\xf6\xa1\ +\x9c\xf3\x15\x94\xae\xdc2\xb9\x8a\x0d\xd6\x99x\x87D/\ +y[\xf8>\x10\xeb\x84\x01r\x8e\x9c8jT\xfe\xca\ +\xe3&\x98\xebN\x1f'\x99\xda\xcf\xb2\xfbm\xcc_7\ +w\xa7g\xaaYFw\x08\x8a\xfe\xe2\xae\xb6\xd4\xf1>\ +}\xb5\xae\x99l1\xf3\xec\x8e\xd3u\xd4\x8an:\xbd\ +\x88.\xf0\x01M\x97\xdes\xf7\xccU\xfc\xa3\x08Wu\ +\x06v\x01\xa3;\x9bf\xe7\xec\xad}\x9f\x8c\x17\xaf\xf2\ +\xddv\xfb\xb2\xee\xff\x03\x14\xcf\xfe\x8c\x0f\xd8\x00\xcfm\ +\x80\x88\x10\x13\x0b s\xb9\xecc]\x04\xf5\xd2}_\ +\x17\xd2\x0fm_vuPx\x19U\xc0\x02R\x9c\xc4\ +\x14#e\x0b\xf7\xa4Bm\x9a\xf5\xa1\x90l\xe1'b\ +\x11\x8a\x19XQ\xbe\x85\x9f\xb6a\x7f\x15\x90\x82\xa5r\ +?\x008\xe0@\x0cc\xb3\x16#s\xa2WF'\x8a\ +\xdb\xa8\xaaC_b\xd7y\xbfh\x1dE\xfczB\x08\ +D\x81@>\x90\x81\x99\xe9(]X\x91\xb1\x89\x9f\x09\ +\x19\xb5\x91e\xd5\xbaH~d\xa7\x85\xd8R\x88e\xc0\ +yP\x06W\xa4\x9c|\xa5\x9817\x83\xa6\x06f_\ +\x9d\x169\x89-~\xa4\xb7eJ\x1d\x97\x02%@\x15\ +\x9e\x92\xaeo\x8f\xe5\xa9\x06\x5c\x9d\xd8\xa9\xda\x8bR'\ +\x94^{\x99]Y\xfa\x80\xa0\xa8J\x19\xed\x90 \xd9\ +\x0a\x8e_h\xdayE\xa4\x11jI\xf2\xa5T:\x05\ +?\xa0\xd6\x0a\x15\xf1\x9c\x1e\xf6J\xa1\xa7\xd4J\xc9l\ +\xa8\xd1Z\x95\xf1R\x85\xc5\xc0\xa3Oc\x80\x0c<\x8e\ +\xc3\x18\xf6\xae\xa1\xe7\x14\xbes\xadV\xda\x82\xcbOk\ +tR\xb9vMKP\x12>-sY\x08\x05\xd1s\ +V\x04\x02\x03(\x1c,\x94\xecjj\x88\xa7(\xab9\ +S\xb3n\x94\xba\xd0D\xed'\xd5\x7f\x0a\x11\xc4 )\ +J\x8c\xb0\x0a\xf9\x1d\xec3\x96(\xab\xe5\xba\xc6\xece\ +\xabL\x0a\xa2@\x97gr\x15^\xa9<\x16\xfe\xb1\xeb\ +\x07O\x0dPn\xbcII\xc1\xd9\xc8\xbb\x0b\xc5d;\ +\xfe\x89\xc0q\xb5\x03\x14\xc8\x10\x8b\xb9\x0b\xbc2;\x92\ +\x0b\xc42\x84\xff\x22\xca2T+'\xcb%\x8c?\x00\ +\xc4s5\x0b\x04\xce\x11\x5c\xc1\x09\xcc\xb3\xb8\xfa\xe5\xb2\ +\x12\xeb+@E\xb2\xec\x8dJ/\x90\x81\x05=J\x85\ +E\xc0\xf8\xd1\x9f\x10\x81\x08%4\xe4\x90\xa0I\xc3!\ +\x87S\xceW\x1dy\x0bR\xaa\xd0\x00T\xd8vt$\ +\x8da\xc7M\xa1\x13\xd22\x05(oB\x09\x0d\xb7h\ +\x14Xr\xc3uB\xb6\xfcl\xd8\xdf\x80\xd3\xd7\x81t\ +\x01\xfd\xeb,2\xd8p\xe9\x08K8W\xcf:\xda\x12\ +\xa0\x01\x7f\x88\x90R\xe1\xa6\xe3.\xc3\xd1*\x0d\x98s\ +_|\xca9\xecK\x90BVP\xc5\xb0\x95\xd0P\xb7\ +\x97\xa2\xcc \x1b\xad\x18B\xee\xc0\xdeBz\x0c\x83\xb4\ +\xea\xbb~\xe2\xe9\xed\xbb\x9e\xf3\xbd\x9d;\xbe\xfb\xc1\xf0\ +\x9f/\x03\xc3\xf1\xbcy\xd7\x8e\xf2<\xbf1\xf5\xf1|\ +\xdfC\xd1\xc8|\xafK\xd5\xf5\x96\xef?\xd7\xf6\xbd\xbf\ +g\xdb\xf7\xbd/w\xdf\xf8\xbc\xbf\x87\xe3\xf9\xbc/\x97\ +\xe7\xfa\xbb\x9f\xa7\xeb\xfb\xb8\xcf\xb7\xef\xfc\xb6\x8f\xc7\xf3\ +\xfd\xb4o\xd7\xf7\xfe\xb2\xc4\x04\x13\x00\xfe\x00\x04\x00\x01\ +\x00\x00\x00\x00\x00\x00\x00\x00\x01\x04\x00\x01\x00\x00\x00`\ +\x00\x00\x00\x01\x01\x04\x00\x01\x00\x00\x00`\x00\x00\x00\x02\ +\x01\x03\x00\x04\x00\x00\x00T\x09\x00\x00\x03\x01\x03\x00\x01\ +\x00\x00\x00\x05\x00\x00\x00\x06\x01\x03\x00\x01\x00\x00\x00\x02\ +\x00\x00\x00\x11\x01\x04\x00\x01\x00\x00\x00\x08\x00\x00\x00\x15\ +\x01\x03\x00\x01\x00\x00\x00\x04\x00\x00\x00\x16\x01\x04\x00\x01\ +\x00\x00\x00`\x00\x00\x00\x17\x01\x04\x00\x01\x00\x00\x00b\ +\x08\x00\x00\x1a\x01\x05\x00\x01\x00\x00\x00\x5c\x09\x00\x00\x1b\ +\x01\x05\x00\x01\x00\x00\x00d\x09\x00\x00\x1c\x01\x03\x00\x01\ +\x00\x00\x00\x01\x00\x00\x00(\x01\x03\x00\x01\x00\x00\x00\x02\ +\x00\x00\x001\x01\x02\x00\x10\x00\x00\x00l\x09\x00\x00=\ +\x01\x03\x00\x01\x00\x00\x00\x02\x00\x00\x00R\x01\x03\x00\x01\ +\x00\x00\x00\x02\x00\x00\x00S\x01\x03\x00\x04\x00\x00\x00|\ +\x09\x00\x00s\x87\x07\x00H\x0c\x00\x00\x84\x09\x00\x00\x00\ +\x00\x00\x00\x08\x00\x08\x00\x08\x00\x08\x00\x802\x02\x00\xe8\ +\x03\x00\x00\x802\x02\x00\xe8\x03\x00\x00paint\ +.net 4.0.9\x00\x01\x00\x01\x00\x01\ +\x00\x01\x00\x00\x00\x0cHLino\x02\x10\x00\x00m\ +ntrRGB XYZ \x07\xce\x00\x02\x00\ +\x09\x00\x06\x001\x00\x00acspMSFT\x00\ +\x00\x00\x00IEC sRGB\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf6\xd6\x00\x01\x00\x00\x00\ +\x00\xd3-HP \x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x11cprt\x00\x00\x01P\x00\ +\x00\x003desc\x00\x00\x01\x84\x00\x00\x00lw\ +tpt\x00\x00\x01\xf0\x00\x00\x00\x14bkpt\x00\ +\x00\x02\x04\x00\x00\x00\x14rXYZ\x00\x00\x02\x18\x00\ +\x00\x00\x14gXYZ\x00\x00\x02,\x00\x00\x00\x14b\ +XYZ\x00\x00\x02@\x00\x00\x00\x14dmnd\x00\ +\x00\x02T\x00\x00\x00pdmdd\x00\x00\x02\xc4\x00\ +\x00\x00\x88vued\x00\x00\x03L\x00\x00\x00\x86v\ +iew\x00\x00\x03\xd4\x00\x00\x00$lumi\x00\ +\x00\x03\xf8\x00\x00\x00\x14meas\x00\x00\x04\x0c\x00\ +\x00\x00$tech\x00\x00\x040\x00\x00\x00\x0cr\ +TRC\x00\x00\x04<\x00\x00\x08\x0cgTRC\x00\ +\x00\x04<\x00\x00\x08\x0cbTRC\x00\x00\x04<\x00\ +\x00\x08\x0ctext\x00\x00\x00\x00Copyr\ +ight (c) 1998 He\ +wlett-Packard Co\ +mpany\x00\x00desc\x00\x00\x00\x00\x00\ +\x00\x00\x12sRGB IEC61966\ +-2.1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x12\ +sRGB IEC61966-2.\ +1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00XYZ \x00\x00\x00\x00\x00\x00\xf3Q\x00\ +\x01\x00\x00\x00\x01\x16\xccXYZ \x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00XYZ \x00\ +\x00\x00\x00\x00\x00o\xa2\x00\x008\xf5\x00\x00\x03\x90X\ +YZ \x00\x00\x00\x00\x00\x00b\x99\x00\x00\xb7\x85\x00\ +\x00\x18\xdaXYZ \x00\x00\x00\x00\x00\x00$\xa0\x00\ +\x00\x0f\x84\x00\x00\xb6\xcfdesc\x00\x00\x00\x00\x00\ +\x00\x00\x16IEC http://ww\ +w.iec.ch\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x16IEC http://w\ +ww.iec.ch\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00desc\x00\x00\x00\x00\x00\ +\x00\x00.IEC 61966-2.1\ + Default RGB col\ +our space - sRGB\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00.IEC \ +61966-2.1 Defaul\ +t RGB colour spa\ +ce - sRGB\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\ +esc\x00\x00\x00\x00\x00\x00\x00,Refer\ +ence Viewing Con\ +dition in IEC619\ +66-2.1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00,Reference View\ +ing Condition in\ + IEC61966-2.1\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00view\x00\x00\x00\x00\x00\ +\x13\xa4\xfe\x00\x14_.\x00\x10\xcf\x14\x00\x03\xed\xcc\x00\ +\x04\x13\x0b\x00\x03\x5c\x9e\x00\x00\x00\x01XYZ \x00\ +\x00\x00\x00\x00L\x09V\x00P\x00\x00\x00W\x1f\xe7m\ +eas\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x8f\x00\ +\x00\x00\x02sig \x00\x00\x00\x00CRT c\ +urv\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x05\x00\ +\x0a\x00\x0f\x00\x14\x00\x19\x00\x1e\x00#\x00(\x00-\x00\ +2\x007\x00;\x00@\x00E\x00J\x00O\x00T\x00\ +Y\x00^\x00c\x00h\x00m\x00r\x00w\x00|\x00\ +\x81\x00\x86\x00\x8b\x00\x90\x00\x95\x00\x9a\x00\x9f\x00\xa4\x00\ +\xa9\x00\xae\x00\xb2\x00\xb7\x00\xbc\x00\xc1\x00\xc6\x00\xcb\x00\ +\xd0\x00\xd5\x00\xdb\x00\xe0\x00\xe5\x00\xeb\x00\xf0\x00\xf6\x00\ +\xfb\x01\x01\x01\x07\x01\x0d\x01\x13\x01\x19\x01\x1f\x01%\x01\ ++\x012\x018\x01>\x01E\x01L\x01R\x01Y\x01\ +`\x01g\x01n\x01u\x01|\x01\x83\x01\x8b\x01\x92\x01\ +\x9a\x01\xa1\x01\xa9\x01\xb1\x01\xb9\x01\xc1\x01\xc9\x01\xd1\x01\ +\xd9\x01\xe1\x01\xe9\x01\xf2\x01\xfa\x02\x03\x02\x0c\x02\x14\x02\ +\x1d\x02&\x02/\x028\x02A\x02K\x02T\x02]\x02\ +g\x02q\x02z\x02\x84\x02\x8e\x02\x98\x02\xa2\x02\xac\x02\ +\xb6\x02\xc1\x02\xcb\x02\xd5\x02\xe0\x02\xeb\x02\xf5\x03\x00\x03\ +\x0b\x03\x16\x03!\x03-\x038\x03C\x03O\x03Z\x03\ +f\x03r\x03~\x03\x8a\x03\x96\x03\xa2\x03\xae\x03\xba\x03\ +\xc7\x03\xd3\x03\xe0\x03\xec\x03\xf9\x04\x06\x04\x13\x04 \x04\ +-\x04;\x04H\x04U\x04c\x04q\x04~\x04\x8c\x04\ +\x9a\x04\xa8\x04\xb6\x04\xc4\x04\xd3\x04\xe1\x04\xf0\x04\xfe\x05\ +\x0d\x05\x1c\x05+\x05:\x05I\x05X\x05g\x05w\x05\ +\x86\x05\x96\x05\xa6\x05\xb5\x05\xc5\x05\xd5\x05\xe5\x05\xf6\x06\ +\x06\x06\x16\x06'\x067\x06H\x06Y\x06j\x06{\x06\ +\x8c\x06\x9d\x06\xaf\x06\xc0\x06\xd1\x06\xe3\x06\xf5\x07\x07\x07\ +\x19\x07+\x07=\x07O\x07a\x07t\x07\x86\x07\x99\x07\ +\xac\x07\xbf\x07\xd2\x07\xe5\x07\xf8\x08\x0b\x08\x1f\x082\x08\ +F\x08Z\x08n\x08\x82\x08\x96\x08\xaa\x08\xbe\x08\xd2\x08\ +\xe7\x08\xfb\x09\x10\x09%\x09:\x09O\x09d\x09y\x09\ +\x8f\x09\xa4\x09\xba\x09\xcf\x09\xe5\x09\xfb\x0a\x11\x0a'\x0a\ +=\x0aT\x0aj\x0a\x81\x0a\x98\x0a\xae\x0a\xc5\x0a\xdc\x0a\ +\xf3\x0b\x0b\x0b\x22\x0b9\x0bQ\x0bi\x0b\x80\x0b\x98\x0b\ +\xb0\x0b\xc8\x0b\xe1\x0b\xf9\x0c\x12\x0c*\x0cC\x0c\x5c\x0c\ +u\x0c\x8e\x0c\xa7\x0c\xc0\x0c\xd9\x0c\xf3\x0d\x0d\x0d&\x0d\ +@\x0dZ\x0dt\x0d\x8e\x0d\xa9\x0d\xc3\x0d\xde\x0d\xf8\x0e\ +\x13\x0e.\x0eI\x0ed\x0e\x7f\x0e\x9b\x0e\xb6\x0e\xd2\x0e\ +\xee\x0f\x09\x0f%\x0fA\x0f^\x0fz\x0f\x96\x0f\xb3\x0f\ +\xcf\x0f\xec\x10\x09\x10&\x10C\x10a\x10~\x10\x9b\x10\ +\xb9\x10\xd7\x10\xf5\x11\x13\x111\x11O\x11m\x11\x8c\x11\ +\xaa\x11\xc9\x11\xe8\x12\x07\x12&\x12E\x12d\x12\x84\x12\ +\xa3\x12\xc3\x12\xe3\x13\x03\x13#\x13C\x13c\x13\x83\x13\ +\xa4\x13\xc5\x13\xe5\x14\x06\x14'\x14I\x14j\x14\x8b\x14\ +\xad\x14\xce\x14\xf0\x15\x12\x154\x15V\x15x\x15\x9b\x15\ +\xbd\x15\xe0\x16\x03\x16&\x16I\x16l\x16\x8f\x16\xb2\x16\ +\xd6\x16\xfa\x17\x1d\x17A\x17e\x17\x89\x17\xae\x17\xd2\x17\ +\xf7\x18\x1b\x18@\x18e\x18\x8a\x18\xaf\x18\xd5\x18\xfa\x19\ + \x19E\x19k\x19\x91\x19\xb7\x19\xdd\x1a\x04\x1a*\x1a\ +Q\x1aw\x1a\x9e\x1a\xc5\x1a\xec\x1b\x14\x1b;\x1bc\x1b\ +\x8a\x1b\xb2\x1b\xda\x1c\x02\x1c*\x1cR\x1c{\x1c\xa3\x1c\ +\xcc\x1c\xf5\x1d\x1e\x1dG\x1dp\x1d\x99\x1d\xc3\x1d\xec\x1e\ +\x16\x1e@\x1ej\x1e\x94\x1e\xbe\x1e\xe9\x1f\x13\x1f>\x1f\ +i\x1f\x94\x1f\xbf\x1f\xea \x15 A l \x98 \ +\xc4 \xf0!\x1c!H!u!\xa1!\xce!\xfb\x22\ +'\x22U\x22\x82\x22\xaf\x22\xdd#\x0a#8#f#\ +\x94#\xc2#\xf0$\x1f$M$|$\xab$\xda%\ +\x09%8%h%\x97%\xc7%\xf7&'&W&\ +\x87&\xb7&\xe8'\x18'I'z'\xab'\xdc(\ +\x0d(?(q(\xa2(\xd4)\x06)8)k)\ +\x9d)\xd0*\x02*5*h*\x9b*\xcf+\x02+\ +6+i+\x9d+\xd1,\x05,9,n,\xa2,\ +\xd7-\x0c-A-v-\xab-\xe1.\x16.L.\ +\x82.\xb7.\xee/$/Z/\x91/\xc7/\xfe0\ +50l0\xa40\xdb1\x121J1\x821\xba1\ +\xf22*2c2\x9b2\xd43\x0d3F3\x7f3\ +\xb83\xf14+4e4\x9e4\xd85\x135M5\ +\x875\xc25\xfd676r6\xae6\xe97$7\ +`7\x9c7\xd78\x148P8\x8c8\xc89\x059\ +B9\x7f9\xbc9\xf9:6:t:\xb2:\xef;\ +-;k;\xaa;\xe8<' >`>\xa0>\xe0?\ +!?a?\xa2?\xe2@#@d@\xa6@\xe7A\ +)AjA\xacA\xeeB0BrB\xb5B\xf7C\ +:C}C\xc0D\x03DGD\x8aD\xceE\x12E\ +UE\x9aE\xdeF\x22FgF\xabF\xf0G5G\ +{G\xc0H\x05HKH\x91H\xd7I\x1dIcI\ +\xa9I\xf0J7J}J\xc4K\x0cKSK\x9aK\ +\xe2L*LrL\xbaM\x02MJM\x93M\xdcN\ +%NnN\xb7O\x00OIO\x93O\xddP'P\ +qP\xbbQ\x06QPQ\x9bQ\xe6R1R|R\ +\xc7S\x13S_S\xaaS\xf6TBT\x8fT\xdbU\ +(UuU\xc2V\x0fV\x5cV\xa9V\xf7WDW\ +\x92W\xe0X/X}X\xcbY\x1aYiY\xb8Z\ +\x07ZVZ\xa6Z\xf5[E[\x95[\xe5\x5c5\x5c\ +\x86\x5c\xd6]']x]\xc9^\x1a^l^\xbd_\ +\x0f_a_\xb3`\x05`W`\xaa`\xfcaOa\ +\xa2a\xf5bIb\x9cb\xf0cCc\x97c\xebd\ +@d\x94d\xe9e=e\x92e\xe7f=f\x92f\ +\xe8g=g\x93g\xe9h?h\x96h\xeciCi\ +\x9ai\xf1jHj\x9fj\xf7kOk\xa7k\xffl\ +Wl\xafm\x08m`m\xb9n\x12nkn\xc4o\ +\x1eoxo\xd1p+p\x86p\xe0q:q\x95q\ +\xf0rKr\xa6s\x01s]s\xb8t\x14tpt\ +\xccu(u\x85u\xe1v>v\x9bv\xf8wVw\ +\xb3x\x11xnx\xccy*y\x89y\xe7zFz\ +\xa5{\x04{c{\xc2|!|\x81|\xe1}A}\ +\xa1~\x01~b~\xc2\x7f#\x7f\x84\x7f\xe5\x80G\x80\ +\xa8\x81\x0a\x81k\x81\xcd\x820\x82\x92\x82\xf4\x83W\x83\ +\xba\x84\x1d\x84\x80\x84\xe3\x85G\x85\xab\x86\x0e\x86r\x86\ +\xd7\x87;\x87\x9f\x88\x04\x88i\x88\xce\x893\x89\x99\x89\ +\xfe\x8ad\x8a\xca\x8b0\x8b\x96\x8b\xfc\x8cc\x8c\xca\x8d\ +1\x8d\x98\x8d\xff\x8ef\x8e\xce\x8f6\x8f\x9e\x90\x06\x90\ +n\x90\xd6\x91?\x91\xa8\x92\x11\x92z\x92\xe3\x93M\x93\ +\xb6\x94 \x94\x8a\x94\xf4\x95_\x95\xc9\x964\x96\x9f\x97\ +\x0a\x97u\x97\xe0\x98L\x98\xb8\x99$\x99\x90\x99\xfc\x9a\ +h\x9a\xd5\x9bB\x9b\xaf\x9c\x1c\x9c\x89\x9c\xf7\x9dd\x9d\ +\xd2\x9e@\x9e\xae\x9f\x1d\x9f\x8b\x9f\xfa\xa0i\xa0\xd8\xa1\ +G\xa1\xb6\xa2&\xa2\x96\xa3\x06\xa3v\xa3\xe6\xa4V\xa4\ +\xc7\xa58\xa5\xa9\xa6\x1a\xa6\x8b\xa6\xfd\xa7n\xa7\xe0\xa8\ +R\xa8\xc4\xa97\xa9\xa9\xaa\x1c\xaa\x8f\xab\x02\xabu\xab\ +\xe9\xac\x5c\xac\xd0\xadD\xad\xb8\xae-\xae\xa1\xaf\x16\xaf\ +\x8b\xb0\x00\xb0u\xb0\xea\xb1`\xb1\xd6\xb2K\xb2\xc2\xb3\ +8\xb3\xae\xb4%\xb4\x9c\xb5\x13\xb5\x8a\xb6\x01\xb6y\xb6\ +\xf0\xb7h\xb7\xe0\xb8Y\xb8\xd1\xb9J\xb9\xc2\xba;\xba\ +\xb5\xbb.\xbb\xa7\xbc!\xbc\x9b\xbd\x15\xbd\x8f\xbe\x0a\xbe\ +\x84\xbe\xff\xbfz\xbf\xf5\xc0p\xc0\xec\xc1g\xc1\xe3\xc2\ +_\xc2\xdb\xc3X\xc3\xd4\xc4Q\xc4\xce\xc5K\xc5\xc8\xc6\ +F\xc6\xc3\xc7A\xc7\xbf\xc8=\xc8\xbc\xc9:\xc9\xb9\xca\ +8\xca\xb7\xcb6\xcb\xb6\xcc5\xcc\xb5\xcd5\xcd\xb5\xce\ +6\xce\xb6\xcf7\xcf\xb8\xd09\xd0\xba\xd1<\xd1\xbe\xd2\ +?\xd2\xc1\xd3D\xd3\xc6\xd4I\xd4\xcb\xd5N\xd5\xd1\xd6\ +U\xd6\xd8\xd7\x5c\xd7\xe0\xd8d\xd8\xe8\xd9l\xd9\xf1\xda\ +v\xda\xfb\xdb\x80\xdc\x05\xdc\x8a\xdd\x10\xdd\x96\xde\x1c\xde\ +\xa2\xdf)\xdf\xaf\xe06\xe0\xbd\xe1D\xe1\xcc\xe2S\xe2\ +\xdb\xe3c\xe3\xeb\xe4s\xe4\xfc\xe5\x84\xe6\x0d\xe6\x96\xe7\ +\x1f\xe7\xa9\xe82\xe8\xbc\xe9F\xe9\xd0\xea[\xea\xe5\xeb\ +p\xeb\xfb\xec\x86\xed\x11\xed\x9c\xee(\xee\xb4\xef@\xef\ +\xcc\xf0X\xf0\xe5\xf1r\xf1\xff\xf2\x8c\xf3\x19\xf3\xa7\xf4\ +4\xf4\xc2\xf5P\xf5\xde\xf6m\xf6\xfb\xf7\x8a\xf8\x19\xf8\ +\xa8\xf98\xf9\xc7\xfaW\xfa\xe7\xfbw\xfc\x07\xfc\x98\xfd\ +)\xfd\xba\xfeK\xfe\xdc\xffm\xff\xff\ +\x00\x00\x03\xa4\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22?>\x0a\x0a \x0a icon / outl\ +iner / entity / \ +Default - Update\ +d\x0a Created with\ + Sketch.\x0a\ + \x0a \x0a \ + \x0a \x0a\x0a\ +\x00\x00\x04\x84\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22?>\x0a\x0a \x0a icon / outl\ +iner / entity / \ +error / Not act\ +ive \x0a \ + Created w\ +ith Sketch.\x0a \x0a \ + \x0a \x0a\x0a\ +\x00\x00\x04i\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22?>\x0a\x0a \x0a icon / outl\ +iner / entity / \ + Editor only - U\ +pdated\x0a \ + Created\ + with Sketch.\x0a <\ +/defs>\x0a \x0a \ +\x0a \ +\x0a\x0a\ +\x00\x00\x15\x0a\ +I\ +I*\x00\xa8\x07\x00\x00\x80?\xe0@\x08$\x16\x0d\x07\ +\x84BaP\xb8d6\x1d\x0f\x88DbQ8\xa4V\ +-\x17\x8cFcQ\xb8\xe4v\x0b\x02\x7f\xc7\xa4R9\ +$\x96M'\x94JeR\xb8\xa4\x82Y/\x98Lf\ +S9\xa4\xd6a.\x9bNgS\xb9\xe4\xf6}#\x9c\ +O\xe8T:%\x16\x8d/\xa0\xd1\xe9T\xbae6\x9d\ +\x1f\x81\xd3\xeaU:\xa5V\x91Q\xabVkU\xba\xe4\ +B\x93]\xb0XlU*\xfd\x8e\xcdg\xb4N\xec\xb6\ +\x9be\xb6\xdd&\xb5\xdb\xeeW;\xa4J\xe3u\xbc^\ +o7{\xd5\xf6\xfdi\xbe_\xf0X:\xde\x07\x09\x87\ +\xc4Sp\xd6`\x0e6\xb5 \x05\xc1E0P\xcc\x14\ +5\x05\x09A]pW6r\x0a\xd6\xc6\x80_U\x9c\ +^\x02\xb1s\xd0\xd2\xa4\x01H)B\x0aO\x82\x91 \ +\xa0\x88\xeb\xce\x0a\xb7\x82\xac`\xab-\x0b\xd2\x8f\xa5\xb4\ +p,:\x99\xec\x80\x19\x059\xc1N\x90^<\xed\xd9\ +\x05A\xc1S\x1a\x1d\x1c\xf3\x85f\xeb\xd7x\x93i\x01\ +b\x0a\x90\x82\x85\xeaM\xe8)\x9bB\xbd\x9c\xf6l^\ +\xaa\xdfnW \x01AP\xb0S\xc5\x89\xf9\x058\xe8\ +R\x93?e\x83\xfa\xac\xbd\xcb\x82\x04\x03 \xa5Z\x0a\ +'.\x84\xb3B5\xaa\xe9\x0a\xfa\xff\xaa\xd0\x0aJ\x90\ +\x13\x88(\xc6\x94\x1c\xa8)\x9c\x82\x9dH)\xe2\xcc<\ +((j\x82\xb5\x898\xf8\xd0\xbeiD \xc2\xb4\xeb\ +\x94$\x8e\xa4\x03{\xbe\x8e\x9d\xc8)*\x82\x94\xcd\x09\ +\xb0\x8b$\x00\x0a\x0a\x18 \xa3\x04,\x82\xb2(\xc4\x1c\ +\x00\x0aM\x09a\x09\xc5\xab\xacV\xaaE\xf22\x04\x16\ +\xa0\xa6z\x0a\x01\xa2\xb29\x1c\x82\x8f\xed\x09\xeb\x06\x82\ +q\x9a\x08.#-\xb2\x08\x1240\xeca&\xae\x92\ +z\xa7(\xa2\xe9\x01j\x82\x89H\xac\xbe\x82\x0a-\x09\ +v\xa1\xa4\x02\xf2\x0aOJ\xe8\xa9*\xd0\x8d\x88\xf4\xdc\ +\xabP\xea|\xe0\xbb B\x02\x0a_\xa2\xa7\xc4\xe8\xd0\ +\xd2\x0ab@-\xa0\xa5\x12\x0a\xf8\xa2\x07\xda\x0a\x154\ +&\xe25D\xaa\x95\x22\x9bE\xa2)\x01h\x82\x89h\ +\xa8\xe8\xd0\x91\xad\x22\x04\xfd\xa0\x90b(J4#m\ +G6.u2\x99T!\x8e2\x0a\xe7\xa0\x80:\x22\ +i\xa0\xa1\x8bB~\xd6G\xf8\x1a\x82\xd4H ,\x88\ +\x9cm\x08=]\xc8\xeb\xddx\xb6X\x08Z@)\xa0\ +\xa5b*74$\x9a\xc6\x90Kh \xe2\x8a\x86m\ +\x0c7,\xdbk}|\xa5\xdb\xa8R@L\xbc\xa8\xa8\ +4\xd0\x9c\xf7:\x04\x1d \xa6**<4$Ly\ +x\xad\xd7\x9a\x95z\xa1)\x01l\x82\x89(\x89\xea\xd0\ +\xb9\xab:@\x0a\xc3\x88\xac\x14\xc6\xd6\xc9n\x10\xb6\xe1\ +J>\x18\x84$\x06\x82\x0a\x17\xa2&\xdbB\x13^H\ +\x15<\x82\x00\x88\x89`\xd0\x8a8=\xb2\xbcd*6\ +F\x83\xa4\x13P\x01\x8c\x22\x06\xc3B\xc9\xe1(\x15%\ +b\xa2&KB\x1cf\xcb\xf6r\xa2\xe7h2@\xdf\ + \x92*\x1f\xa11\xba&A\xa3 \xb62 j4\ +2\xa5\xe1\x9b\xc9\xd8\xfb\x18\xc7f\xda\xa0\x01\xab!\xda\ +\xc0\x03\xad-\x89\x06\x8e\x00k\xc8~\xc0\xc6\xecX\xf6\ +\xc96\xec\xcb\x1e\xa2\xa8\x1f\xfbV\xd8\x86\xed\xdb\x83L\ +\x7f\xee{\xaa\x1d\xbb\x80;\xca'\xa7\xb5[\xea\xc5\xbf\ +\xa0\x9a\x9c\x88\x88\xf0\xb9o\x11\xae\xa2\x9aJ\x80\xf0fD\x18aE\ +\x81\xad\xa4d\xbal\xdaU,\x81\xcb\xa6\xd3\x18\x1c\xce\ +\xa5\x5c\xae\xceb\xb5\xeb\x0d\x8a\x0d@\x00Af\xd40\ +\x0c:\xc7\x09\x95!\xe0\xc7\x8b`\x00\xd1#L\xdc\xa1\ +\x15Il\xde\xb2\x00\xad\xdd\xef\xf3\xb9\xd6\x03\x076\xb2\ +\xd9\xe6\xb6\x9b]\xb2T\x0f\x83:\xe0\xc0[\x93\xa6\x0c\ +\x1a\x91\xbf\xae\xf7\x9a\xb5\xeee\x84\xce\xcb\xf0Y\xed\x0c\ +G\x0dB\x91\xe2\xacr\xa2,\x19u\xa1\x13\xc8\xdbY\ +\x88\xadT\x01W\x9a\xdf/\xda-\xccR\xc1\xba\xde\xc0\ +\xf4\x96\x8d6\xc5\xfeQ\x83+\xb4#9\x1b;\x87\xb3\ +\xda\xcd6\xfb\xed\xf6\x83\xa3\xa2\xe0b8W)U2\ +\x06\xcf\xd0\x84\xe4n\xeee\xea\xb1\x9c\xeanz~l\ +\xefZi\x89\xe1\x80\xa0\xdb\x08\x18\x8e\xe4\xbf\x91\x90\xb0\ +\x99\x9d\xa6n\xb5\xe9\xd1z\x1f\xd6\x01\xebK\xde\xd6\x0d\ +*\x15\x90b\xa5aIP1\x01#1_\x86\xc9\xe3\ +m\x9eX\x02\x10?\xe1W\xa9\x06a\xde\xc7a\x9eJ\ +\x87\xa4\x18\x84G\x13s\xe9\x06\x19\x922\x85\xfe\x84Y\ +\xa7\x91\xfc\x86 V\xf2/_\xe0$\xa2\x04n\x92\xa2\ +\x19\x06\x1eSq\x95#'\x1d(\xad\xfa\x8bW\xd8\xc9\ +\x80\x7f\xe4U\x864I\xe3g\x9d\x15\x1d\x90b%7\ +\x15\x922\xae@J\xe1'>\x14\x92\x1a\x88\xc6[X\ +\xa4\xa4\x9aL\x8a\x8f\xf9=\x03\x94SiM\x0c\x95[\ +\xd7\xe5\xceK\xdd\x09z\x5c\x85\xe7\x19~\x1aiTI\ +\xb2N\x94%)RVs_\xb9\x12tXdz\x09\ +>\x98\x119\x89\xa1J\x85\xc4\x18\xa3M\xc3\xc8:~\ +\x96&\xf9j\x85ShJY;\xa1\xd1*&\x1eE\ +A$\x18\xd6A\x81tL\xd5A\x83$\x8e%\x9ee\ +x\xb2\x13\x8b\xa9\x9a^]\xac\x13\xdam\x11\xa7d\xd3\ +\xfc(F\x10`\xa5\x062\xd0a\xdd#9^\x99\xb6\ +\x80n+4\xf2\x98\xb2\x13J\xd5\x10\xad\xec\xbaJ\xad\ +\x96j\xfbA8\xb2\xadT\x9a\xcdC\xec\xfbbc\x9f\ +\xe4;\x1e\xddg\xeb+\x89(\xb6\x90\x9br\xe5\x85\xad\ +\xfa\xba\x81\xba\xae9\xce\xef\xb9\xa7g\x06x\xbc\xab\x8b\ +\xb2\xd3\xbb\xafu~\xf1\xbf\x13\xfb\xd1\xd7\xbd\xaf\xf6v\ +\xc5\xb80K\xf7\x08D\x8b\xe4\x18AM\xc5D\x18\xf8\ +\xc2\x9a \x81\x06%\x13r\x81\x06\x18q4\xa6\xe4\xc7\ +\x00\x09\xac\x00\xc41\xfcL\x8dA\x87L\x91x\xc7\xb1\ +\xc1\xbd\x06$2\x9c)\xc5@\xcb\x0c\xc1\x06\xb5\xf0@\ +6\x12\x07\xf3[\x8a\xbf@\xc3\xa4\x1a\x0b\xcds{\xc9\ +#\x00\x12\xa7\xdd\x03.\x19\x0c\xf2\x99=\x10`\xd9#\ +5\xf4K\xffT\xba\xb4f\xec\xff\x0cPh\xa5\x03\x0b\ +t\xd9\x14\xc2\xc6\x923{Y\xd85m\x83i\xda\xac\ +\xbd\xa3k\xdb\xb6\xf9{m\xdc7=\xd2\xc4\xca\xf7]\ +\xe3y\xdd\xaf\xed\xeb}\xdf\xaa\xbd\xff\x81\xe0\xa9\xed\xf3\ +\x83\xe1\xb8usr\xe28\xbe1m\xdd\xf8\xdeC\x91\ +\xe3\xb8^K\x95\xe5\xb8\xae[\x99\xde\xb9\x8ek\x9d\xdc\ +\xf9\xce{\xa1\xda\xba\x0e\x8b\xa5\xd0\xf8\xfe\x9b\xa9\xdb\xfa\ +N\xab\xad\xc1\x10\x10\x00\x13\x00\xfe\x00\x04\x00\x01\x00\x00\ +\x00\x00\x00\x00\x00\x00\x01\x04\x00\x01\x00\x00\x00`\x00\x00\ +\x00\x01\x01\x04\x00\x01\x00\x00\x00`\x00\x00\x00\x02\x01\x03\ +\x00\x04\x00\x00\x00\x92\x08\x00\x00\x03\x01\x03\x00\x01\x00\x00\ +\x00\x05\x00\x00\x00\x06\x01\x03\x00\x01\x00\x00\x00\x02\x00\x00\ +\x00\x11\x01\x04\x00\x01\x00\x00\x00\x08\x00\x00\x00\x15\x01\x03\ +\x00\x01\x00\x00\x00\x04\x00\x00\x00\x16\x01\x04\x00\x01\x00\x00\ +\x00`\x00\x00\x00\x17\x01\x04\x00\x01\x00\x00\x00\x9f\x07\x00\ +\x00\x1a\x01\x05\x00\x01\x00\x00\x00\x9a\x08\x00\x00\x1b\x01\x05\ +\x00\x01\x00\x00\x00\xa2\x08\x00\x00\x1c\x01\x03\x00\x01\x00\x00\ +\x00\x01\x00\x00\x00(\x01\x03\x00\x01\x00\x00\x00\x02\x00\x00\ +\x001\x01\x02\x00\x10\x00\x00\x00\xaa\x08\x00\x00=\x01\x03\ +\x00\x01\x00\x00\x00\x02\x00\x00\x00R\x01\x03\x00\x01\x00\x00\ +\x00\x02\x00\x00\x00S\x01\x03\x00\x04\x00\x00\x00\xba\x08\x00\ +\x00s\x87\x07\x00H\x0c\x00\x00\xc2\x08\x00\x00\x00\x00\x00\ +\x00\x08\x00\x08\x00\x08\x00\x08\x00\x802\x02\x00\xe8\x03\x00\ +\x00\x802\x02\x00\xe8\x03\x00\x00paint.n\ +et 4.0.9\x00\x01\x00\x01\x00\x01\x00\x01\ +\x00\x00\x00\x0cHLino\x02\x10\x00\x00mnt\ +rRGB XYZ \x07\xce\x00\x02\x00\x09\x00\ +\x06\x001\x00\x00acspMSFT\x00\x00\x00\ +\x00IEC sRGB\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\xf6\xd6\x00\x01\x00\x00\x00\x00\xd3\ +-HP \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x11cprt\x00\x00\x01P\x00\x00\x00\ +3desc\x00\x00\x01\x84\x00\x00\x00lwtp\ +t\x00\x00\x01\xf0\x00\x00\x00\x14bkpt\x00\x00\x02\ +\x04\x00\x00\x00\x14rXYZ\x00\x00\x02\x18\x00\x00\x00\ +\x14gXYZ\x00\x00\x02,\x00\x00\x00\x14bXY\ +Z\x00\x00\x02@\x00\x00\x00\x14dmnd\x00\x00\x02\ +T\x00\x00\x00pdmdd\x00\x00\x02\xc4\x00\x00\x00\ +\x88vued\x00\x00\x03L\x00\x00\x00\x86vie\ +w\x00\x00\x03\xd4\x00\x00\x00$lumi\x00\x00\x03\ +\xf8\x00\x00\x00\x14meas\x00\x00\x04\x0c\x00\x00\x00\ +$tech\x00\x00\x040\x00\x00\x00\x0crTR\ +C\x00\x00\x04<\x00\x00\x08\x0cgTRC\x00\x00\x04\ +<\x00\x00\x08\x0cbTRC\x00\x00\x04<\x00\x00\x08\ +\x0ctext\x00\x00\x00\x00Copyrig\ +ht (c) 1998 Hewl\ +ett-Packard Comp\ +any\x00\x00desc\x00\x00\x00\x00\x00\x00\x00\ +\x12sRGB IEC61966-2\ +.1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x12sR\ +GB IEC61966-2.1\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00XYZ \x00\x00\x00\x00\x00\x00\xf3Q\x00\x01\x00\ +\x00\x00\x01\x16\xccXYZ \x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00XYZ \x00\x00\x00\ +\x00\x00\x00o\xa2\x00\x008\xf5\x00\x00\x03\x90XYZ\ + \x00\x00\x00\x00\x00\x00b\x99\x00\x00\xb7\x85\x00\x00\x18\ +\xdaXYZ \x00\x00\x00\x00\x00\x00$\xa0\x00\x00\x0f\ +\x84\x00\x00\xb6\xcfdesc\x00\x00\x00\x00\x00\x00\x00\ +\x16IEC http://www.\ +iec.ch\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x16IEC http://www\ +.iec.ch\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00desc\x00\x00\x00\x00\x00\x00\x00\ +.IEC 61966-2.1 D\ +efault RGB colou\ +r space - sRGB\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00.IEC 61\ +966-2.1 Default \ +RGB colour space\ + - sRGB\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00des\ +c\x00\x00\x00\x00\x00\x00\x00,Referen\ +ce Viewing Condi\ +tion in IEC61966\ +-2.1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00,\ +Reference Viewin\ +g Condition in I\ +EC61966-2.1\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00view\x00\x00\x00\x00\x00\x13\xa4\ +\xfe\x00\x14_.\x00\x10\xcf\x14\x00\x03\xed\xcc\x00\x04\x13\ +\x0b\x00\x03\x5c\x9e\x00\x00\x00\x01XYZ \x00\x00\x00\ +\x00\x00L\x09V\x00P\x00\x00\x00W\x1f\xe7mea\ +s\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x8f\x00\x00\x00\ +\x02sig \x00\x00\x00\x00CRT cur\ +v\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x05\x00\x0a\x00\ +\x0f\x00\x14\x00\x19\x00\x1e\x00#\x00(\x00-\x002\x00\ +7\x00;\x00@\x00E\x00J\x00O\x00T\x00Y\x00\ +^\x00c\x00h\x00m\x00r\x00w\x00|\x00\x81\x00\ +\x86\x00\x8b\x00\x90\x00\x95\x00\x9a\x00\x9f\x00\xa4\x00\xa9\x00\ +\xae\x00\xb2\x00\xb7\x00\xbc\x00\xc1\x00\xc6\x00\xcb\x00\xd0\x00\ +\xd5\x00\xdb\x00\xe0\x00\xe5\x00\xeb\x00\xf0\x00\xf6\x00\xfb\x01\ +\x01\x01\x07\x01\x0d\x01\x13\x01\x19\x01\x1f\x01%\x01+\x01\ +2\x018\x01>\x01E\x01L\x01R\x01Y\x01`\x01\ +g\x01n\x01u\x01|\x01\x83\x01\x8b\x01\x92\x01\x9a\x01\ +\xa1\x01\xa9\x01\xb1\x01\xb9\x01\xc1\x01\xc9\x01\xd1\x01\xd9\x01\ +\xe1\x01\xe9\x01\xf2\x01\xfa\x02\x03\x02\x0c\x02\x14\x02\x1d\x02\ +&\x02/\x028\x02A\x02K\x02T\x02]\x02g\x02\ +q\x02z\x02\x84\x02\x8e\x02\x98\x02\xa2\x02\xac\x02\xb6\x02\ +\xc1\x02\xcb\x02\xd5\x02\xe0\x02\xeb\x02\xf5\x03\x00\x03\x0b\x03\ +\x16\x03!\x03-\x038\x03C\x03O\x03Z\x03f\x03\ +r\x03~\x03\x8a\x03\x96\x03\xa2\x03\xae\x03\xba\x03\xc7\x03\ +\xd3\x03\xe0\x03\xec\x03\xf9\x04\x06\x04\x13\x04 \x04-\x04\ +;\x04H\x04U\x04c\x04q\x04~\x04\x8c\x04\x9a\x04\ +\xa8\x04\xb6\x04\xc4\x04\xd3\x04\xe1\x04\xf0\x04\xfe\x05\x0d\x05\ +\x1c\x05+\x05:\x05I\x05X\x05g\x05w\x05\x86\x05\ +\x96\x05\xa6\x05\xb5\x05\xc5\x05\xd5\x05\xe5\x05\xf6\x06\x06\x06\ +\x16\x06'\x067\x06H\x06Y\x06j\x06{\x06\x8c\x06\ +\x9d\x06\xaf\x06\xc0\x06\xd1\x06\xe3\x06\xf5\x07\x07\x07\x19\x07\ ++\x07=\x07O\x07a\x07t\x07\x86\x07\x99\x07\xac\x07\ +\xbf\x07\xd2\x07\xe5\x07\xf8\x08\x0b\x08\x1f\x082\x08F\x08\ +Z\x08n\x08\x82\x08\x96\x08\xaa\x08\xbe\x08\xd2\x08\xe7\x08\ +\xfb\x09\x10\x09%\x09:\x09O\x09d\x09y\x09\x8f\x09\ +\xa4\x09\xba\x09\xcf\x09\xe5\x09\xfb\x0a\x11\x0a'\x0a=\x0a\ +T\x0aj\x0a\x81\x0a\x98\x0a\xae\x0a\xc5\x0a\xdc\x0a\xf3\x0b\ +\x0b\x0b\x22\x0b9\x0bQ\x0bi\x0b\x80\x0b\x98\x0b\xb0\x0b\ +\xc8\x0b\xe1\x0b\xf9\x0c\x12\x0c*\x0cC\x0c\x5c\x0cu\x0c\ +\x8e\x0c\xa7\x0c\xc0\x0c\xd9\x0c\xf3\x0d\x0d\x0d&\x0d@\x0d\ +Z\x0dt\x0d\x8e\x0d\xa9\x0d\xc3\x0d\xde\x0d\xf8\x0e\x13\x0e\ +.\x0eI\x0ed\x0e\x7f\x0e\x9b\x0e\xb6\x0e\xd2\x0e\xee\x0f\ +\x09\x0f%\x0fA\x0f^\x0fz\x0f\x96\x0f\xb3\x0f\xcf\x0f\ +\xec\x10\x09\x10&\x10C\x10a\x10~\x10\x9b\x10\xb9\x10\ +\xd7\x10\xf5\x11\x13\x111\x11O\x11m\x11\x8c\x11\xaa\x11\ +\xc9\x11\xe8\x12\x07\x12&\x12E\x12d\x12\x84\x12\xa3\x12\ +\xc3\x12\xe3\x13\x03\x13#\x13C\x13c\x13\x83\x13\xa4\x13\ +\xc5\x13\xe5\x14\x06\x14'\x14I\x14j\x14\x8b\x14\xad\x14\ +\xce\x14\xf0\x15\x12\x154\x15V\x15x\x15\x9b\x15\xbd\x15\ +\xe0\x16\x03\x16&\x16I\x16l\x16\x8f\x16\xb2\x16\xd6\x16\ +\xfa\x17\x1d\x17A\x17e\x17\x89\x17\xae\x17\xd2\x17\xf7\x18\ +\x1b\x18@\x18e\x18\x8a\x18\xaf\x18\xd5\x18\xfa\x19 \x19\ +E\x19k\x19\x91\x19\xb7\x19\xdd\x1a\x04\x1a*\x1aQ\x1a\ +w\x1a\x9e\x1a\xc5\x1a\xec\x1b\x14\x1b;\x1bc\x1b\x8a\x1b\ +\xb2\x1b\xda\x1c\x02\x1c*\x1cR\x1c{\x1c\xa3\x1c\xcc\x1c\ +\xf5\x1d\x1e\x1dG\x1dp\x1d\x99\x1d\xc3\x1d\xec\x1e\x16\x1e\ +@\x1ej\x1e\x94\x1e\xbe\x1e\xe9\x1f\x13\x1f>\x1fi\x1f\ +\x94\x1f\xbf\x1f\xea \x15 A l \x98 \xc4 \ +\xf0!\x1c!H!u!\xa1!\xce!\xfb\x22'\x22\ +U\x22\x82\x22\xaf\x22\xdd#\x0a#8#f#\x94#\ +\xc2#\xf0$\x1f$M$|$\xab$\xda%\x09%\ +8%h%\x97%\xc7%\xf7&'&W&\x87&\ +\xb7&\xe8'\x18'I'z'\xab'\xdc(\x0d(\ +?(q(\xa2(\xd4)\x06)8)k)\x9d)\ +\xd0*\x02*5*h*\x9b*\xcf+\x02+6+\ +i+\x9d+\xd1,\x05,9,n,\xa2,\xd7-\ +\x0c-A-v-\xab-\xe1.\x16.L.\x82.\ +\xb7.\xee/$/Z/\x91/\xc7/\xfe050\ +l0\xa40\xdb1\x121J1\x821\xba1\xf22\ +*2c2\x9b2\xd43\x0d3F3\x7f3\xb83\ +\xf14+4e4\x9e4\xd85\x135M5\x875\ +\xc25\xfd676r6\xae6\xe97$7`7\ +\x9c7\xd78\x148P8\x8c8\xc89\x059B9\ +\x7f9\xbc9\xf9:6:t:\xb2:\xef;-;\ +k;\xaa;\xe8<' >`>\xa0>\xe0?!?\ +a?\xa2?\xe2@#@d@\xa6@\xe7A)A\ +jA\xacA\xeeB0BrB\xb5B\xf7C:C\ +}C\xc0D\x03DGD\x8aD\xceE\x12EUE\ +\x9aE\xdeF\x22FgF\xabF\xf0G5G{G\ +\xc0H\x05HKH\x91H\xd7I\x1dIcI\xa9I\ +\xf0J7J}J\xc4K\x0cKSK\x9aK\xe2L\ +*LrL\xbaM\x02MJM\x93M\xdcN%N\ +nN\xb7O\x00OIO\x93O\xddP'PqP\ +\xbbQ\x06QPQ\x9bQ\xe6R1R|R\xc7S\ +\x13S_S\xaaS\xf6TBT\x8fT\xdbU(U\ +uU\xc2V\x0fV\x5cV\xa9V\xf7WDW\x92W\ +\xe0X/X}X\xcbY\x1aYiY\xb8Z\x07Z\ +VZ\xa6Z\xf5[E[\x95[\xe5\x5c5\x5c\x86\x5c\ +\xd6]']x]\xc9^\x1a^l^\xbd_\x0f_\ +a_\xb3`\x05`W`\xaa`\xfcaOa\xa2a\ +\xf5bIb\x9cb\xf0cCc\x97c\xebd@d\ +\x94d\xe9e=e\x92e\xe7f=f\x92f\xe8g\ +=g\x93g\xe9h?h\x96h\xeciCi\x9ai\ +\xf1jHj\x9fj\xf7kOk\xa7k\xfflWl\ +\xafm\x08m`m\xb9n\x12nkn\xc4o\x1eo\ +xo\xd1p+p\x86p\xe0q:q\x95q\xf0r\ +Kr\xa6s\x01s]s\xb8t\x14tpt\xccu\ +(u\x85u\xe1v>v\x9bv\xf8wVw\xb3x\ +\x11xnx\xccy*y\x89y\xe7zFz\xa5{\ +\x04{c{\xc2|!|\x81|\xe1}A}\xa1~\ +\x01~b~\xc2\x7f#\x7f\x84\x7f\xe5\x80G\x80\xa8\x81\ +\x0a\x81k\x81\xcd\x820\x82\x92\x82\xf4\x83W\x83\xba\x84\ +\x1d\x84\x80\x84\xe3\x85G\x85\xab\x86\x0e\x86r\x86\xd7\x87\ +;\x87\x9f\x88\x04\x88i\x88\xce\x893\x89\x99\x89\xfe\x8a\ +d\x8a\xca\x8b0\x8b\x96\x8b\xfc\x8cc\x8c\xca\x8d1\x8d\ +\x98\x8d\xff\x8ef\x8e\xce\x8f6\x8f\x9e\x90\x06\x90n\x90\ +\xd6\x91?\x91\xa8\x92\x11\x92z\x92\xe3\x93M\x93\xb6\x94\ + \x94\x8a\x94\xf4\x95_\x95\xc9\x964\x96\x9f\x97\x0a\x97\ +u\x97\xe0\x98L\x98\xb8\x99$\x99\x90\x99\xfc\x9ah\x9a\ +\xd5\x9bB\x9b\xaf\x9c\x1c\x9c\x89\x9c\xf7\x9dd\x9d\xd2\x9e\ +@\x9e\xae\x9f\x1d\x9f\x8b\x9f\xfa\xa0i\xa0\xd8\xa1G\xa1\ +\xb6\xa2&\xa2\x96\xa3\x06\xa3v\xa3\xe6\xa4V\xa4\xc7\xa5\ +8\xa5\xa9\xa6\x1a\xa6\x8b\xa6\xfd\xa7n\xa7\xe0\xa8R\xa8\ +\xc4\xa97\xa9\xa9\xaa\x1c\xaa\x8f\xab\x02\xabu\xab\xe9\xac\ +\x5c\xac\xd0\xadD\xad\xb8\xae-\xae\xa1\xaf\x16\xaf\x8b\xb0\ +\x00\xb0u\xb0\xea\xb1`\xb1\xd6\xb2K\xb2\xc2\xb38\xb3\ +\xae\xb4%\xb4\x9c\xb5\x13\xb5\x8a\xb6\x01\xb6y\xb6\xf0\xb7\ +h\xb7\xe0\xb8Y\xb8\xd1\xb9J\xb9\xc2\xba;\xba\xb5\xbb\ +.\xbb\xa7\xbc!\xbc\x9b\xbd\x15\xbd\x8f\xbe\x0a\xbe\x84\xbe\ +\xff\xbfz\xbf\xf5\xc0p\xc0\xec\xc1g\xc1\xe3\xc2_\xc2\ +\xdb\xc3X\xc3\xd4\xc4Q\xc4\xce\xc5K\xc5\xc8\xc6F\xc6\ +\xc3\xc7A\xc7\xbf\xc8=\xc8\xbc\xc9:\xc9\xb9\xca8\xca\ +\xb7\xcb6\xcb\xb6\xcc5\xcc\xb5\xcd5\xcd\xb5\xce6\xce\ +\xb6\xcf7\xcf\xb8\xd09\xd0\xba\xd1<\xd1\xbe\xd2?\xd2\ +\xc1\xd3D\xd3\xc6\xd4I\xd4\xcb\xd5N\xd5\xd1\xd6U\xd6\ +\xd8\xd7\x5c\xd7\xe0\xd8d\xd8\xe8\xd9l\xd9\xf1\xdav\xda\ +\xfb\xdb\x80\xdc\x05\xdc\x8a\xdd\x10\xdd\x96\xde\x1c\xde\xa2\xdf\ +)\xdf\xaf\xe06\xe0\xbd\xe1D\xe1\xcc\xe2S\xe2\xdb\xe3\ +c\xe3\xeb\xe4s\xe4\xfc\xe5\x84\xe6\x0d\xe6\x96\xe7\x1f\xe7\ +\xa9\xe82\xe8\xbc\xe9F\xe9\xd0\xea[\xea\xe5\xebp\xeb\ +\xfb\xec\x86\xed\x11\xed\x9c\xee(\xee\xb4\xef@\xef\xcc\xf0\ +X\xf0\xe5\xf1r\xf1\xff\xf2\x8c\xf3\x19\xf3\xa7\xf44\xf4\ +\xc2\xf5P\xf5\xde\xf6m\xf6\xfb\xf7\x8a\xf8\x19\xf8\xa8\xf9\ +8\xf9\xc7\xfaW\xfa\xe7\xfbw\xfc\x07\xfc\x98\xfd)\xfd\ +\xba\xfeK\xfe\xdc\xffm\xff\xff\ +\x00\x00\x04e\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22?>\x0a\x0a \x0a icon / outl\ +iner / entity / \ + Editor only - S\ +aved\x0a \ + Created w\ +ith Sketch.\x0a \x0a \ +\x0a \x0a \x0a\x0a\ +\x00\x00\x07\x13\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22 standalone=\x22\ +no\x22?>\x0a\x0a \x0a <\ +title>lock on\x0a \ +Created with Ske\ +tch.\x0a \ +\x0a \ + \ +\x0a \x0a \x0a\x0a\ +\x00\x00\x05\x10\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22?>\x0a\x0a \x0a icon / outl\ +iner / slice / s\ +tandard copy\x0a C\ +reated with Sket\ +ch.\x0a <\ +defs>\x0a \ + \ +\x0a \ +\x0a \x0a \ +\x0a \x0a \ + \x0a\x0a\ +\x00\x00\x04\x96\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22?>\x0a\x0a \x0a icon / outl\ +iner / entity / \ +Not active - Upd\ +ated\x0a \ + Created w\ +ith Sketch.\x0a \x0a \ +\x0a \x0a \x0a\x0a\ +\x00\x00\x04\x92\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22?>\x0a\x0a \x0a icon / outl\ +iner / entity / \ +Not active - Sav\ +ed\x0a <\ +desc>Created wit\ +h Sketch.\ +\x0a \x0a \x0a \ + \ +\x0a \x0a\ +\x0a\ +\x00\x00\x06\xcd\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22?>\x0a\x0a \x0a Group 13\x0a \ +Created with Ske\ +tch.\x0a \ +\x0a \x0a \ + \x0a \ + \x0a \ + \x0a \ + \x0a \ + \x0a \ + \x0a \ +\x0a\x0a\ +\x00\x00\x03~\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22?>\x0a\x0a \x0a icon / outl\ +iner / entity / \ +Loop v2\x0a\ + Create\ +d with Sketch.\x0a \x0a \x0a \ + \x0a\x0a\ +\x00\x00_l\ +I\ +I*\x00\x08\x00\x00\x00\x17\x00\xfe\x00\x04\x00\x01\x00\x00\ +\x00\x00\x00\x00\x00\x00\x01\x03\x00\x01\x00\x00\x00`\x00\x00\ +\x00\x01\x01\x03\x00\x01\x00\x00\x00`\x00\x00\x00\x02\x01\x03\ +\x00\x04\x00\x00\x00\x22\x01\x00\x00\x03\x01\x03\x00\x01\x00\x00\ +\x00\x05\x00\x00\x00\x06\x01\x03\x00\x01\x00\x00\x00\x02\x00\x00\ +\x00\x11\x01\x04\x00\x01\x00\x00\x00DS\x00\x00\x12\x01\x03\ +\x00\x01\x00\x00\x00\x01\x00\x00\x00\x15\x01\x03\x00\x01\x00\x00\ +\x00\x04\x00\x00\x00\x16\x01\x03\x00\x01\x00\x00\x00`\x00\x00\ +\x00\x17\x01\x04\x00\x01\x00\x00\x00\xfa\x0b\x00\x00\x1a\x01\x05\ +\x00\x01\x00\x00\x00*\x01\x00\x00\x1b\x01\x05\x00\x01\x00\x00\ +\x002\x01\x00\x00\x1c\x01\x03\x00\x01\x00\x00\x00\x01\x00\x00\ +\x00(\x01\x03\x00\x01\x00\x00\x00\x02\x00\x00\x001\x01\x02\ +\x00$\x00\x00\x00:\x01\x00\x002\x01\x02\x00\x14\x00\x00\ +\x00^\x01\x00\x00=\x01\x03\x00\x01\x00\x00\x00\x02\x00\x00\ +\x00R\x01\x03\x00\x01\x00\x00\x00\x01\x00\x00\x00\xbc\x02\x01\ +\x00\xfa8\x00\x00r\x01\x00\x00I\x86\x01\x00\x90\x0c\x00\ +\x00l:\x00\x00i\x87\x04\x00\x01\x00\x00\x00@_\x00\ +\x00s\x87\x07\x00H\x0c\x00\x00\xfcF\x00\x00\x00\x00\x00\ +\x00\x08\x00\x08\x00\x08\x00\x08\x00\x00\xf9\x15\x00\x10'\x00\ +\x00\x00\xf9\x15\x00\x10'\x00\x00Adobe P\ +hotoshop CC 2015\ +.5 (Windows)\x00201\ +7:03:08 11:37:45\ +\x00\x0a\x0a \x0a \ +\x0a pain\ +t.net 4.0.9\x0a \ + 2017-03-0\ +7T11:32:29-08:00\ +\x0a 2017-\ +03-08T11:37:45-0\ +8:00\x0a <\ +xmp:MetadataDate\ +>2017-03-08T11:3\ +7:45-08:00\x0a \ + image/tiff\x0a \ + 3\x0a \ + sR\ +GB IEC61966-2.1<\ +/photoshop:ICCPr\ +ofile>\x0a \ +\x0a \ + \x0a \ + adobe\ +:docid:photoshop\ +:94a27cdb-0433-1\ +1e7-b02d-9f84d9f\ +5a326\x0a \ + \x0a <\ +/photoshop:Docum\ +entAncestors>\x0a \ + xmp.iid\ +:16fdf09c-857d-9\ +44e-9783-e127cb1\ +b9cf4\x0a \ + adobe:docid:\ +photoshop:9f9351\ +ac-0436-11e7-b02\ +d-9f84d9f5a326\x0a xmp.did:ca7\ +71a70-f965-e14f-\ +9103-360465543db\ +f\x0a \ + \x0a \ + \x0a \ + \x0a \ + <\ +stEvt:action>cre\ +ated\x0a \ + xmp.iid:\ +ca771a70-f965-e1\ +4f-9103-36046554\ +3dbf\x0a \ + 2017-03-07\ +T11:32:29-08:00<\ +/stEvt:when>\x0a \ + <\ +stEvt:softwareAg\ +ent>Adobe Photos\ +hop CC 2015.5 (W\ +indows)\x0a \ + \x0a \ + \x0a \ + saved\x0a \ + <\ +stEvt:instanceID\ +>xmp.iid:16fdf09\ +c-857d-944e-9783\ +-e127cb1b9cf4\ +\x0a \ + 2\ +017-03-08T11:37:\ +45-08:00\x0a \ + Ado\ +be Photoshop CC \ +2015.5 (Windows)\ +\x0a \ + /\x0a \ + \x0a <\ +/rdf:Seq>\x0a \ + \x0a \x0a \ +\x0a\x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ +\x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a\ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ +\x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a\ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ +\x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a\ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ +\x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a\ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ +\x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a\ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ +\x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a\ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ +\x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a\ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ +\x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \x0a8BIM\x04\ +%\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x008BIM\x04:\x00\x00\x00\ +\x00\x00\xe5\x00\x00\x00\x10\x00\x00\x00\x01\x00\x00\x00\x00\x00\ +\x0bprintOutput\x00\x00\x00\x05\ +\x00\x00\x00\x00PstSbool\x01\x00\x00\x00\ +\x00Inteenum\x00\x00\x00\x00Int\ +e\x00\x00\x00\x00Clrm\x00\x00\x00\x0fpri\ +ntSixteenBitbool\ +\x00\x00\x00\x00\x0bprinterName\ +TEXT\x00\x00\x00\x01\x00\x00\x00\x00\x00\x0fpr\ +intProofSetupObj\ +c\x00\x00\x00\x0c\x00P\x00r\x00o\x00o\x00f\x00\ + \x00S\x00e\x00t\x00u\x00p\x00\x00\x00\x00\x00\ +\x0aproofSetup\x00\x00\x00\x01\x00\ +\x00\x00\x00Bltnenum\x00\x00\x00\x0cb\ +uiltinProof\x00\x00\x00\x09p\ +roofCMYK\x008BIM\x04;\x00\ +\x00\x00\x00\x02-\x00\x00\x00\x10\x00\x00\x00\x01\x00\x00\x00\ +\x00\x00\x12printOutputOp\ +tions\x00\x00\x00\x17\x00\x00\x00\x00Cpt\ +nbool\x00\x00\x00\x00\x00Clbrbo\ +ol\x00\x00\x00\x00\x00RgsMbool\x00\ +\x00\x00\x00\x00CrnCbool\x00\x00\x00\x00\ +\x00CntCbool\x00\x00\x00\x00\x00Lb\ +lsbool\x00\x00\x00\x00\x00Ngtvb\ +ool\x00\x00\x00\x00\x00EmlDbool\ +\x00\x00\x00\x00\x00Intrbool\x00\x00\x00\ +\x00\x00BckgObjc\x00\x00\x00\x01\x00\x00\ +\x00\x00\x00\x00RGBC\x00\x00\x00\x03\x00\x00\x00\x00\ +Rd doub@o\xe0\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00Grn doub@o\xe0\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00Bl doub\ +@o\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00BrdT\ +UntF#Rlt\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00Bld UntF#Rlt\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00Rslt\ +UntF#Pxl@b\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x0avectorDatabo\ +ol\x01\x00\x00\x00\x00PgPsenum\x00\ +\x00\x00\x00PgPs\x00\x00\x00\x00PgPC\x00\ +\x00\x00\x00LeftUntF#Rlt\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00Top U\ +ntF#Rlt\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00Scl UntF#Prc@\ +Y\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10cropW\ +henPrintingbool\x00\ +\x00\x00\x00\x0ecropRectBott\ +omlong\x00\x00\x00\x00\x00\x00\x00\x0ccr\ +opRectLeftlong\x00\x00\ +\x00\x00\x00\x00\x00\x0dcropRectRi\ +ghtlong\x00\x00\x00\x00\x00\x00\x00\x0bc\ +ropRectToplong\x00\x00\ +\x00\x00\x008BIM\x03\xed\x00\x00\x00\x00\x00\x10\x00\ +\x90\x00\x00\x00\x01\x00\x01\x00\x90\x00\x00\x00\x01\x00\x018\ +BIM\x04&\x00\x00\x00\x00\x00\x0e\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00?\x80\x00\x008BIM\x03\xee\x00\ +\x00\x00\x00\x00\x0d\x0cTransparen\ +cy\x008BIM\x04\x15\x00\x00\x00\x00\x00\x1e\x00\ +\x00\x00\x0d\x00T\x00r\x00a\x00n\x00s\x00p\x00\ +a\x00r\x00e\x00n\x00c\x00y\x00\x008BI\ +M\x045\x00\x00\x00\x00\x00\x11\x00\x00\x00\x01\x00\x00\xff\ +\xff\x00\x00\x00\x00\x00\x00\x00d\x01\x008BIM\x04\ +\x1d\x00\x00\x00\x00\x00\x04\x00\x00\x00\x008BIM\x04\ +\x0d\x00\x00\x00\x00\x00\x04\x00\x00\x00\x1e8BIM\x04\ +\x19\x00\x00\x00\x00\x00\x04\x00\x00\x00\x1e8BIM\x03\ +\xf3\x00\x00\x00\x00\x00\x09\x00\x00\x00\x00\x00\x00\x00\x00\x01\ +\x008BIM'\x10\x00\x00\x00\x00\x00\x0a\x00\x01\x00\ +\x00\x00\x00\x00\x00\x00\x018BIM\x03\xf5\x00\x00\x00\ +\x00\x00H\x00/ff\x00\x01\x00lff\x00\x06\x00\ +\x00\x00\x00\x00\x01\x00/ff\x00\x01\x00\xa1\x99\x9a\x00\ +\x06\x00\x00\x00\x00\x00\x01\x002\x00\x00\x00\x01\x00Z\x00\ +\x00\x00\x06\x00\x00\x00\x00\x00\x01\x005\x00\x00\x00\x01\x00\ +-\x00\x00\x00\x06\x00\x00\x00\x00\x00\x018BIM\x03\ +\xf8\x00\x00\x00\x00\x00p\x00\x00\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x03\ +\xe8\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x03\xe8\x00\x00\x00\ +\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\x03\xe8\x00\x00\x00\x00\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\x03\xe8\x00\x008BIM\x04\x00\x00\x00\x00\ +\x00\x00\x02\x00\x008BIM\x04\x02\x00\x00\x00\x00\x00\ +\x02\x00\x008BIM\x040\x00\x00\x00\x00\x00\x01\x01\ +\x008BIM\x04-\x00\x00\x00\x00\x00\x06\x00\x01\x00\ +\x00\x00\x0a8BIM\x04\x08\x00\x00\x00\x00\x00\x10\x00\ +\x00\x00\x01\x00\x00\x02@\x00\x00\x02@\x00\x00\x00\x008\ +BIM\x04\x1e\x00\x00\x00\x00\x00\x04\x00\x00\x00\x008\ +BIM\x04\x1a\x00\x00\x00\x00\x035\x00\x00\x00\x06\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00`\x00\x00\x00`\x00\ +\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00`\x00\x00\x00`\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\ +\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00null\x00\x00\ +\x00\x02\x00\x00\x00\x06boundsObjc\ +\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00Rct1\x00\x00\ +\x00\x04\x00\x00\x00\x00Top long\x00\x00\ +\x00\x00\x00\x00\x00\x00Leftlong\x00\x00\ +\x00\x00\x00\x00\x00\x00Btomlong\x00\x00\ +\x00`\x00\x00\x00\x00Rghtlong\x00\x00\ +\x00`\x00\x00\x00\x06slicesVlLs\ +\x00\x00\x00\x01Objc\x00\x00\x00\x01\x00\x00\x00\x00\ +\x00\x05slice\x00\x00\x00\x12\x00\x00\x00\x07s\ +liceIDlong\x00\x00\x00\x00\x00\x00\ +\x00\x07groupIDlong\x00\x00\x00\ +\x00\x00\x00\x00\x06originenum\x00\ +\x00\x00\x0cESliceOrigin\x00\ +\x00\x00\x0dautoGenerated\ +\x00\x00\x00\x00Typeenum\x00\x00\x00\x0a\ +ESliceType\x00\x00\x00\x00Im\ +g \x00\x00\x00\x06boundsObjc\ +\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00Rct1\x00\x00\ +\x00\x04\x00\x00\x00\x00Top long\x00\x00\ +\x00\x00\x00\x00\x00\x00Leftlong\x00\x00\ +\x00\x00\x00\x00\x00\x00Btomlong\x00\x00\ +\x00`\x00\x00\x00\x00Rghtlong\x00\x00\ +\x00`\x00\x00\x00\x03urlTEXT\x00\x00\x00\ +\x01\x00\x00\x00\x00\x00\x00nullTEXT\x00\ +\x00\x00\x01\x00\x00\x00\x00\x00\x00MsgeTEX\ +T\x00\x00\x00\x01\x00\x00\x00\x00\x00\x06altTa\ +gTEXT\x00\x00\x00\x01\x00\x00\x00\x00\x00\x0ec\ +ellTextIsHTMLboo\ +l\x01\x00\x00\x00\x08cellTextTE\ +XT\x00\x00\x00\x01\x00\x00\x00\x00\x00\x09horz\ +Alignenum\x00\x00\x00\x0fESl\ +iceHorzAlign\x00\x00\x00\x07\ +default\x00\x00\x00\x09vertA\ +lignenum\x00\x00\x00\x0fESli\ +ceVertAlign\x00\x00\x00\x07d\ +efault\x00\x00\x00\x0bbgColo\ +rTypeenum\x00\x00\x00\x11ESl\ +iceBGColorType\x00\x00\ +\x00\x00None\x00\x00\x00\x09topOut\ +setlong\x00\x00\x00\x00\x00\x00\x00\x0al\ +eftOutsetlong\x00\x00\x00\ +\x00\x00\x00\x00\x0cbottomOutse\ +tlong\x00\x00\x00\x00\x00\x00\x00\x0brig\ +htOutsetlong\x00\x00\x00\x00\ +\x008BIM\x04(\x00\x00\x00\x00\x00\x0c\x00\x00\x00\ +\x02?\xf0\x00\x00\x00\x00\x00\x008BIM\x04\x14\x00\ +\x00\x00\x00\x00\x04\x00\x00\x00\x0c8BIM\x04\x0c\x00\ +\x00\x00\x00\x038\x00\x00\x00\x01\x00\x00\x000\x00\x00\x00\ +0\x00\x00\x00\x90\x00\x00\x1b\x00\x00\x00\x03\x1c\x00\x18\x00\ +\x01\xff\xd8\xff\xed\x00\x0cAdobe_CM\x00\ +\x01\xff\xee\x00\x0eAdobe\x00d\x80\x00\x00\x00\ +\x01\xff\xdb\x00\x84\x00\x0c\x08\x08\x08\x09\x08\x0c\x09\x09\x0c\ +\x11\x0b\x0a\x0b\x11\x15\x0f\x0c\x0c\x0f\x15\x18\x13\x13\x15\x13\ +\x13\x18\x11\x0c\x0c\x0c\x0c\x0c\x0c\x11\x0c\x0c\x0c\x0c\x0c\x0c\ +\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\ +\x0c\x0c\x0c\x0c\x0c\x0c\x01\x0d\x0b\x0b\x0d\x0e\x0d\x10\x0e\x0e\ +\x10\x14\x0e\x0e\x0e\x14\x14\x0e\x0e\x0e\x0e\x14\x11\x0c\x0c\x0c\ +\x0c\x0c\x11\x11\x0c\x0c\x0c\x0c\x0c\x0c\x11\x0c\x0c\x0c\x0c\x0c\ +\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\ +\x0c\x0c\x0c\x0c\x0c\x0c\x0c\xff\xc0\x00\x11\x08\x000\x000\ +\x03\x01\x22\x00\x02\x11\x01\x03\x11\x01\xff\xdd\x00\x04\x00\x03\ +\xff\xc4\x01?\x00\x00\x01\x05\x01\x01\x01\x01\x01\x01\x00\x00\ +\x00\x00\x00\x00\x00\x03\x00\x01\x02\x04\x05\x06\x07\x08\x09\x0a\ +\x0b\x01\x00\x01\x05\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\ +\x00\x00\x01\x00\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x10\x00\ +\x01\x04\x01\x03\x02\x04\x02\x05\x07\x06\x08\x05\x03\x0c3\x01\ +\x00\x02\x11\x03\x04!\x121\x05AQa\x13\x22q\x81\ +2\x06\x14\x91\xa1\xb1B#$\x15R\xc1b34r\ +\x82\xd1C\x07%\x92S\xf0\xe1\xf1cs5\x16\xa2\xb2\ +\x83&D\x93TdE\xc2\xa3t6\x17\xd2U\xe2e\ +\xf2\xb3\x84\xc3\xd3u\xe3\xf3F'\x94\xa4\x85\xb4\x95\xc4\ +\xd4\xe4\xf4\xa5\xb5\xc5\xd5\xe5\xf5Vfv\x86\x96\xa6\xb6\ +\xc6\xd6\xe6\xf67GWgw\x87\x97\xa7\xb7\xc7\xd7\xe7\ +\xf7\x11\x00\x02\x02\x01\x02\x04\x04\x03\x04\x05\x06\x07\x07\x06\ +\x055\x01\x00\x02\x11\x03!1\x12\x04AQaq\x22\ +\x13\x052\x81\x91\x14\xa1\xb1B#\xc1R\xd1\xf03$\ +b\xe1r\x82\x92CS\x15cs4\xf1%\x06\x16\xa2\ +\xb2\x83\x07&5\xc2\xd2D\x93T\xa3\x17dEU6\ +te\xe2\xf2\xb3\x84\xc3\xd3u\xe3\xf3F\x94\xa4\x85\xb4\ +\x95\xc4\xd4\xe4\xf4\xa5\xb5\xc5\xd5\xe5\xf5Vfv\x86\x96\ +\xa6\xb6\xc6\xd6\xe6\xf6'7GWgw\x87\x97\xa7\xb7\ +\xc7\xff\xda\x00\x0c\x03\x01\x00\x02\x11\x03\x11\x00?\x00\xf5\ +T\x92P\xb5\xceensZ^\xe6\x82CG$\xa4\ +\xa5YuU\xff\x008\xf6\xb2x\xdc@N\xd7\xb1\xe3\ +s\x1c\x1c\xdf\x10d*X\xb8,\xb1\x9e\xbe[K\xee\ +\xb3S\xbb\xb0\xec6\xa6}#\x07&\xa7\xd2H\xaa\xe7\ +\x06=\x93\x22O\x05%:\x09$\x92J\x7f\xff\xd0\xf5\ +T\x1c\x9c\xaa\xf1\x9a\x0b\xe4\x97\x18kZ$\x94eK\ +\xaa{YM\xbd\xeb\xb0\x1f\x97\xfa\x84\x94\xb7\xdb\xefw\ +\xf3x\xaf>\x05\xda\x7f\x04+\x9b\xd4.s.}m\ +`\xa6\x5c\xd6\x93:\xf3:|\x15\xac\xf3x\xc6s\xa9\ +0F\xae#\x9d\xa3\xe9mK\x05\xd6Y\x88\xd7Zw\ +\x17L\x1e\xf1:nIL\xf1/7\xe3\xb2\xd2\x00.\ +\xe4\x0e$\x1d\xa8\xca\x97J\xd3\x1d\xf5\x9ekyj\xba\ +\x92\x9f\xff\xd1\xf5UW\xa8\xd6l\xc3\xb0\x01$A\x00\ +y\x1f\xfc\x8a\xb4\x92Jh7\xa95\xf5\x86\xb6\x8b-\ +1\x0e\x86\xe8t\xd7\xc5&_\x9b\xb42\x8cA[\x06\ +\x808\xc0\x1f/b\xbe\x92Jj`\xe3\xddQ\xb5\xf7\ +@u\xae\xdd\xb5\xbc\x05m$\x92S\xff\xd98BI\ +M\x04!\x00\x00\x00\x00\x00a\x00\x00\x00\x01\x01\x00\x00\ +\x00\x0f\x00A\x00d\x00o\x00b\x00e\x00 \x00P\ +\x00h\x00o\x00t\x00o\x00s\x00h\x00o\x00p\ +\x00\x00\x00\x19\x00A\x00d\x00o\x00b\x00e\x00 \ +\x00P\x00h\x00o\x00t\x00o\x00s\x00h\x00o\ +\x00p\x00 \x00C\x00C\x00 \x002\x000\x001\ +\x005\x00.\x005\x00\x00\x00\x01\x00\x00\x00\x0cHL\ +ino\x02\x10\x00\x00mntrRGB X\ +YZ \x07\xce\x00\x02\x00\x09\x00\x06\x001\x00\x00a\ +cspMSFT\x00\x00\x00\x00IEC s\ +RGB\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\xf6\xd6\x00\x01\x00\x00\x00\x00\xd3-HP \x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11c\ +prt\x00\x00\x01P\x00\x00\x003desc\x00\ +\x00\x01\x84\x00\x00\x00lwtpt\x00\x00\x01\xf0\x00\ +\x00\x00\x14bkpt\x00\x00\x02\x04\x00\x00\x00\x14r\ +XYZ\x00\x00\x02\x18\x00\x00\x00\x14gXYZ\x00\ +\x00\x02,\x00\x00\x00\x14bXYZ\x00\x00\x02@\x00\ +\x00\x00\x14dmnd\x00\x00\x02T\x00\x00\x00pd\ +mdd\x00\x00\x02\xc4\x00\x00\x00\x88vued\x00\ +\x00\x03L\x00\x00\x00\x86view\x00\x00\x03\xd4\x00\ +\x00\x00$lumi\x00\x00\x03\xf8\x00\x00\x00\x14m\ +eas\x00\x00\x04\x0c\x00\x00\x00$tech\x00\ +\x00\x040\x00\x00\x00\x0crTRC\x00\x00\x04<\x00\ +\x00\x08\x0cgTRC\x00\x00\x04<\x00\x00\x08\x0cb\ +TRC\x00\x00\x04<\x00\x00\x08\x0ctext\x00\ +\x00\x00\x00Copyright (c)\ + 1998 Hewlett-Pa\ +ckard Company\x00\x00d\ +esc\x00\x00\x00\x00\x00\x00\x00\x12sRGB \ +IEC61966-2.1\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x12sRGB IEC\ +61966-2.1\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00XYZ \x00\ +\x00\x00\x00\x00\x00\xf3Q\x00\x01\x00\x00\x00\x01\x16\xccX\ +YZ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00XYZ \x00\x00\x00\x00\x00\x00o\xa2\x00\ +\x008\xf5\x00\x00\x03\x90XYZ \x00\x00\x00\x00\x00\ +\x00b\x99\x00\x00\xb7\x85\x00\x00\x18\xdaXYZ \x00\ +\x00\x00\x00\x00\x00$\xa0\x00\x00\x0f\x84\x00\x00\xb6\xcfd\ +esc\x00\x00\x00\x00\x00\x00\x00\x16IEC h\ +ttp://www.iec.ch\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x16IEC \ +http://www.iec.c\ +h\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\ +esc\x00\x00\x00\x00\x00\x00\x00.IEC 6\ +1966-2.1 Default\ + RGB colour spac\ +e - sRGB\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00.IEC 61966-2.\ +1 Default RGB co\ +lour space - sRG\ +B\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00desc\x00\x00\x00\x00\x00\ +\x00\x00,Reference Vie\ +wing Condition i\ +n IEC61966-2.1\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00,Refere\ +nce Viewing Cond\ +ition in IEC6196\ +6-2.1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00v\ +iew\x00\x00\x00\x00\x00\x13\xa4\xfe\x00\x14_.\x00\ +\x10\xcf\x14\x00\x03\xed\xcc\x00\x04\x13\x0b\x00\x03\x5c\x9e\x00\ +\x00\x00\x01XYZ \x00\x00\x00\x00\x00L\x09V\x00\ +P\x00\x00\x00W\x1f\xe7meas\x00\x00\x00\x00\x00\ +\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x02\x8f\x00\x00\x00\x02sig \x00\ +\x00\x00\x00CRT curv\x00\x00\x00\x00\x00\ +\x00\x04\x00\x00\x00\x00\x05\x00\x0a\x00\x0f\x00\x14\x00\x19\x00\ +\x1e\x00#\x00(\x00-\x002\x007\x00;\x00@\x00\ +E\x00J\x00O\x00T\x00Y\x00^\x00c\x00h\x00\ +m\x00r\x00w\x00|\x00\x81\x00\x86\x00\x8b\x00\x90\x00\ +\x95\x00\x9a\x00\x9f\x00\xa4\x00\xa9\x00\xae\x00\xb2\x00\xb7\x00\ +\xbc\x00\xc1\x00\xc6\x00\xcb\x00\xd0\x00\xd5\x00\xdb\x00\xe0\x00\ +\xe5\x00\xeb\x00\xf0\x00\xf6\x00\xfb\x01\x01\x01\x07\x01\x0d\x01\ +\x13\x01\x19\x01\x1f\x01%\x01+\x012\x018\x01>\x01\ +E\x01L\x01R\x01Y\x01`\x01g\x01n\x01u\x01\ +|\x01\x83\x01\x8b\x01\x92\x01\x9a\x01\xa1\x01\xa9\x01\xb1\x01\ +\xb9\x01\xc1\x01\xc9\x01\xd1\x01\xd9\x01\xe1\x01\xe9\x01\xf2\x01\ +\xfa\x02\x03\x02\x0c\x02\x14\x02\x1d\x02&\x02/\x028\x02\ +A\x02K\x02T\x02]\x02g\x02q\x02z\x02\x84\x02\ +\x8e\x02\x98\x02\xa2\x02\xac\x02\xb6\x02\xc1\x02\xcb\x02\xd5\x02\ +\xe0\x02\xeb\x02\xf5\x03\x00\x03\x0b\x03\x16\x03!\x03-\x03\ +8\x03C\x03O\x03Z\x03f\x03r\x03~\x03\x8a\x03\ +\x96\x03\xa2\x03\xae\x03\xba\x03\xc7\x03\xd3\x03\xe0\x03\xec\x03\ +\xf9\x04\x06\x04\x13\x04 \x04-\x04;\x04H\x04U\x04\ +c\x04q\x04~\x04\x8c\x04\x9a\x04\xa8\x04\xb6\x04\xc4\x04\ +\xd3\x04\xe1\x04\xf0\x04\xfe\x05\x0d\x05\x1c\x05+\x05:\x05\ +I\x05X\x05g\x05w\x05\x86\x05\x96\x05\xa6\x05\xb5\x05\ +\xc5\x05\xd5\x05\xe5\x05\xf6\x06\x06\x06\x16\x06'\x067\x06\ +H\x06Y\x06j\x06{\x06\x8c\x06\x9d\x06\xaf\x06\xc0\x06\ +\xd1\x06\xe3\x06\xf5\x07\x07\x07\x19\x07+\x07=\x07O\x07\ +a\x07t\x07\x86\x07\x99\x07\xac\x07\xbf\x07\xd2\x07\xe5\x07\ +\xf8\x08\x0b\x08\x1f\x082\x08F\x08Z\x08n\x08\x82\x08\ +\x96\x08\xaa\x08\xbe\x08\xd2\x08\xe7\x08\xfb\x09\x10\x09%\x09\ +:\x09O\x09d\x09y\x09\x8f\x09\xa4\x09\xba\x09\xcf\x09\ +\xe5\x09\xfb\x0a\x11\x0a'\x0a=\x0aT\x0aj\x0a\x81\x0a\ +\x98\x0a\xae\x0a\xc5\x0a\xdc\x0a\xf3\x0b\x0b\x0b\x22\x0b9\x0b\ +Q\x0bi\x0b\x80\x0b\x98\x0b\xb0\x0b\xc8\x0b\xe1\x0b\xf9\x0c\ +\x12\x0c*\x0cC\x0c\x5c\x0cu\x0c\x8e\x0c\xa7\x0c\xc0\x0c\ +\xd9\x0c\xf3\x0d\x0d\x0d&\x0d@\x0dZ\x0dt\x0d\x8e\x0d\ +\xa9\x0d\xc3\x0d\xde\x0d\xf8\x0e\x13\x0e.\x0eI\x0ed\x0e\ +\x7f\x0e\x9b\x0e\xb6\x0e\xd2\x0e\xee\x0f\x09\x0f%\x0fA\x0f\ +^\x0fz\x0f\x96\x0f\xb3\x0f\xcf\x0f\xec\x10\x09\x10&\x10\ +C\x10a\x10~\x10\x9b\x10\xb9\x10\xd7\x10\xf5\x11\x13\x11\ +1\x11O\x11m\x11\x8c\x11\xaa\x11\xc9\x11\xe8\x12\x07\x12\ +&\x12E\x12d\x12\x84\x12\xa3\x12\xc3\x12\xe3\x13\x03\x13\ +#\x13C\x13c\x13\x83\x13\xa4\x13\xc5\x13\xe5\x14\x06\x14\ +'\x14I\x14j\x14\x8b\x14\xad\x14\xce\x14\xf0\x15\x12\x15\ +4\x15V\x15x\x15\x9b\x15\xbd\x15\xe0\x16\x03\x16&\x16\ +I\x16l\x16\x8f\x16\xb2\x16\xd6\x16\xfa\x17\x1d\x17A\x17\ +e\x17\x89\x17\xae\x17\xd2\x17\xf7\x18\x1b\x18@\x18e\x18\ +\x8a\x18\xaf\x18\xd5\x18\xfa\x19 \x19E\x19k\x19\x91\x19\ +\xb7\x19\xdd\x1a\x04\x1a*\x1aQ\x1aw\x1a\x9e\x1a\xc5\x1a\ +\xec\x1b\x14\x1b;\x1bc\x1b\x8a\x1b\xb2\x1b\xda\x1c\x02\x1c\ +*\x1cR\x1c{\x1c\xa3\x1c\xcc\x1c\xf5\x1d\x1e\x1dG\x1d\ +p\x1d\x99\x1d\xc3\x1d\xec\x1e\x16\x1e@\x1ej\x1e\x94\x1e\ +\xbe\x1e\xe9\x1f\x13\x1f>\x1fi\x1f\x94\x1f\xbf\x1f\xea \ +\x15 A l \x98 \xc4 \xf0!\x1c!H!\ +u!\xa1!\xce!\xfb\x22'\x22U\x22\x82\x22\xaf\x22\ +\xdd#\x0a#8#f#\x94#\xc2#\xf0$\x1f$\ +M$|$\xab$\xda%\x09%8%h%\x97%\ +\xc7%\xf7&'&W&\x87&\xb7&\xe8'\x18'\ +I'z'\xab'\xdc(\x0d(?(q(\xa2(\ +\xd4)\x06)8)k)\x9d)\xd0*\x02*5*\ +h*\x9b*\xcf+\x02+6+i+\x9d+\xd1,\ +\x05,9,n,\xa2,\xd7-\x0c-A-v-\ +\xab-\xe1.\x16.L.\x82.\xb7.\xee/$/\ +Z/\x91/\xc7/\xfe050l0\xa40\xdb1\ +\x121J1\x821\xba1\xf22*2c2\x9b2\ +\xd43\x0d3F3\x7f3\xb83\xf14+4e4\ +\x9e4\xd85\x135M5\x875\xc25\xfd676\ +r6\xae6\xe97$7`7\x9c7\xd78\x148\ +P8\x8c8\xc89\x059B9\x7f9\xbc9\xf9:\ +6:t:\xb2:\xef;-;k;\xaa;\xe8<\ +'\ + >`>\xa0>\xe0?!?a?\xa2?\xe2@\ +#@d@\xa6@\xe7A)AjA\xacA\xeeB\ +0BrB\xb5B\xf7C:C}C\xc0D\x03D\ +GD\x8aD\xceE\x12EUE\x9aE\xdeF\x22F\ +gF\xabF\xf0G5G{G\xc0H\x05HKH\ +\x91H\xd7I\x1dIcI\xa9I\xf0J7J}J\ +\xc4K\x0cKSK\x9aK\xe2L*LrL\xbaM\ +\x02MJM\x93M\xdcN%NnN\xb7O\x00O\ +IO\x93O\xddP'PqP\xbbQ\x06QPQ\ +\x9bQ\xe6R1R|R\xc7S\x13S_S\xaaS\ +\xf6TBT\x8fT\xdbU(UuU\xc2V\x0fV\ +\x5cV\xa9V\xf7WDW\x92W\xe0X/X}X\ +\xcbY\x1aYiY\xb8Z\x07ZVZ\xa6Z\xf5[\ +E[\x95[\xe5\x5c5\x5c\x86\x5c\xd6]']x]\ +\xc9^\x1a^l^\xbd_\x0f_a_\xb3`\x05`\ +W`\xaa`\xfcaOa\xa2a\xf5bIb\x9cb\ +\xf0cCc\x97c\xebd@d\x94d\xe9e=e\ +\x92e\xe7f=f\x92f\xe8g=g\x93g\xe9h\ +?h\x96h\xeciCi\x9ai\xf1jHj\x9fj\ +\xf7kOk\xa7k\xfflWl\xafm\x08m`m\ +\xb9n\x12nkn\xc4o\x1eoxo\xd1p+p\ +\x86p\xe0q:q\x95q\xf0rKr\xa6s\x01s\ +]s\xb8t\x14tpt\xccu(u\x85u\xe1v\ +>v\x9bv\xf8wVw\xb3x\x11xnx\xccy\ +*y\x89y\xe7zFz\xa5{\x04{c{\xc2|\ +!|\x81|\xe1}A}\xa1~\x01~b~\xc2\x7f\ +#\x7f\x84\x7f\xe5\x80G\x80\xa8\x81\x0a\x81k\x81\xcd\x82\ +0\x82\x92\x82\xf4\x83W\x83\xba\x84\x1d\x84\x80\x84\xe3\x85\ +G\x85\xab\x86\x0e\x86r\x86\xd7\x87;\x87\x9f\x88\x04\x88\ +i\x88\xce\x893\x89\x99\x89\xfe\x8ad\x8a\xca\x8b0\x8b\ +\x96\x8b\xfc\x8cc\x8c\xca\x8d1\x8d\x98\x8d\xff\x8ef\x8e\ +\xce\x8f6\x8f\x9e\x90\x06\x90n\x90\xd6\x91?\x91\xa8\x92\ +\x11\x92z\x92\xe3\x93M\x93\xb6\x94 \x94\x8a\x94\xf4\x95\ +_\x95\xc9\x964\x96\x9f\x97\x0a\x97u\x97\xe0\x98L\x98\ +\xb8\x99$\x99\x90\x99\xfc\x9ah\x9a\xd5\x9bB\x9b\xaf\x9c\ +\x1c\x9c\x89\x9c\xf7\x9dd\x9d\xd2\x9e@\x9e\xae\x9f\x1d\x9f\ +\x8b\x9f\xfa\xa0i\xa0\xd8\xa1G\xa1\xb6\xa2&\xa2\x96\xa3\ +\x06\xa3v\xa3\xe6\xa4V\xa4\xc7\xa58\xa5\xa9\xa6\x1a\xa6\ +\x8b\xa6\xfd\xa7n\xa7\xe0\xa8R\xa8\xc4\xa97\xa9\xa9\xaa\ +\x1c\xaa\x8f\xab\x02\xabu\xab\xe9\xac\x5c\xac\xd0\xadD\xad\ +\xb8\xae-\xae\xa1\xaf\x16\xaf\x8b\xb0\x00\xb0u\xb0\xea\xb1\ +`\xb1\xd6\xb2K\xb2\xc2\xb38\xb3\xae\xb4%\xb4\x9c\xb5\ +\x13\xb5\x8a\xb6\x01\xb6y\xb6\xf0\xb7h\xb7\xe0\xb8Y\xb8\ +\xd1\xb9J\xb9\xc2\xba;\xba\xb5\xbb.\xbb\xa7\xbc!\xbc\ +\x9b\xbd\x15\xbd\x8f\xbe\x0a\xbe\x84\xbe\xff\xbfz\xbf\xf5\xc0\ +p\xc0\xec\xc1g\xc1\xe3\xc2_\xc2\xdb\xc3X\xc3\xd4\xc4\ +Q\xc4\xce\xc5K\xc5\xc8\xc6F\xc6\xc3\xc7A\xc7\xbf\xc8\ +=\xc8\xbc\xc9:\xc9\xb9\xca8\xca\xb7\xcb6\xcb\xb6\xcc\ +5\xcc\xb5\xcd5\xcd\xb5\xce6\xce\xb6\xcf7\xcf\xb8\xd0\ +9\xd0\xba\xd1<\xd1\xbe\xd2?\xd2\xc1\xd3D\xd3\xc6\xd4\ +I\xd4\xcb\xd5N\xd5\xd1\xd6U\xd6\xd8\xd7\x5c\xd7\xe0\xd8\ +d\xd8\xe8\xd9l\xd9\xf1\xdav\xda\xfb\xdb\x80\xdc\x05\xdc\ +\x8a\xdd\x10\xdd\x96\xde\x1c\xde\xa2\xdf)\xdf\xaf\xe06\xe0\ +\xbd\xe1D\xe1\xcc\xe2S\xe2\xdb\xe3c\xe3\xeb\xe4s\xe4\ +\xfc\xe5\x84\xe6\x0d\xe6\x96\xe7\x1f\xe7\xa9\xe82\xe8\xbc\xe9\ +F\xe9\xd0\xea[\xea\xe5\xebp\xeb\xfb\xec\x86\xed\x11\xed\ +\x9c\xee(\xee\xb4\xef@\xef\xcc\xf0X\xf0\xe5\xf1r\xf1\ +\xff\xf2\x8c\xf3\x19\xf3\xa7\xf44\xf4\xc2\xf5P\xf5\xde\xf6\ +m\xf6\xfb\xf7\x8a\xf8\x19\xf8\xa8\xf98\xf9\xc7\xfaW\xfa\ +\xe7\xfbw\xfc\x07\xfc\x98\xfd)\xfd\xba\xfeK\xfe\xdc\xff\ +m\xff\xff\x80\x00 P8$\x16\x0d\x07\x84BaP\ +\xb8d6\x1d\x0f\x88DbQ8\xa4V-\x17\x8cF\ +cQ\xb8\xe4v=\x1f\x90HdR9$\x96M'\ +\x94JeR\xb9d\xb6]/\x98LfS9\xa4\xd6\ +m7\x9cNgS\xb9\xe4\xf6}?\xa0PhT:\ +%\x16\x8dG\xa4RiT\xbae6\x9dO\xa8Tj\ +U:\xa5V\xadW\xacVkU\xba\xe5v\xbd_\xb0\ +XlV;%\x96\x0a\x01\xb4\x00Cv\xb1\x15\xb4D\ ++\x0c\xdcC\xe0\xeb\xa0F\xd2\x01y\xde^\x0e;\xe3\ +q\xc5\x7fm_\xdcM\xbb6\x17\x0d\x1b\x0a\xe2CD\ +\x5caX\x8f\x8f,\x88rB\xa0VT\x19\x14|\xe6\ +^\xedl\xe31\x85\x9fY.tJ\x87V\x95\xc9\x87\ +\xd4a\xc4\xda\xb1\x81g\x5co\x1elIa\x1d\xa0V\ +X\xf0\xdc;\x17\xdb\xb5r\xc7|\x9dj\xf0YZ\x9e\ +%d\xbd\xc7:\x99yG\xf0O4\x17<}t_\ +\x08\x9e\xa1\xb3|\xb1N\xf1{T\x9b\xa08$f\xf0\ +\x1f\xcb\x1e3u1_\xe7M\xa5\xfdG\xd7w\xb5\xd3\ +\xdb\xf8NA\x7f0rS\xec\xb9\x16\xfeG\x15FO\ +\xf5v6\xc0\x02A\xfd\x01\x9f\xcf\x8c\x0c\x98\x8e\xf0I\ +**\xc1\x83R0m\xc2\x06\x938k\x19fl,\ +`\x9dp\xc9\xca\xe8\x9fG\xcb\xe6\x05\x81\xabX6\x11\ +\x06q(\x80\x11\xc5\x01`A\x15\x85\x0b\xba0V\xc6\ +\x04\xc1\x15\x19\x8d\xa7\xecl~@\xf1\xcaJ-\xc7\x83\ +\x90\xe3\x1f\x91\xa8\xa3\x82j\x99D\xb4\x8c>\x19rI\ +{\x02@\xa8\xb8\x09'\x80\xa1\x94\xa4\x1f\x0cr\xa8\xf9\ +\x12\x86b\x020O\xcb\x849+/\x8fQ\xd4\xc4\x8e\ +\x84\x93(ZPM\x06@\x115\x81H\x81m7\x94\ +\x84,\xe433'\xc9\xee\x94\x00S\xc8\x04-O\x83\ +\x88\xdd?\x913\xd0\x06\x88\x1eT)\xde*Q\x01C\ +\xdaw\x1dS\x1d\x1c\x8a\x92T\x89l\x1dR\x82J \ +]S\x05H\xffM\x8b\xc7\xdd<}&\x81\xb5D!\ +\x90u)H\x09\xd5\x00\xc2 ZU\x85\x09\x01W\x8c\ +\x14}d\x86\x82\xd5\xa87\x18\x15\xa6\xcb\x9a\x04\xb9\xe8\ +[Ju\x1c\x8dp\xb2\x18\x1e6)\xda\x9e\x05\xd6H\ +tMY\x86\x04\x9e\x02\x00\xa8e<}\x9fB\xbd\xac\ +\x160L%gm\xa0\x83E\xbcA\x0c\x97\x08\xfa\x88\ +\x10\xd7(\xd0W]\x04\xca\x889]\x84|\xf8-\x0e\ +\x08\x84\xd0P\x11\x0f\xb1(<\xdb\x95\x9b\xba\x09W\x06\ +\xc3h\x08\xb6\xc8]\x16u\x0a\x18(H{a\x07\x9a\ +\x88\x03a\x80AO\x87\x9a\x00\xfe$\x13\xa1\x876,\ +p\x0a\xd8\xc8V|c\x87\xb5\xf31c\x81\xbbH \x86\x19\xfbi\x863\xee\ +\x02\x04\x98\xa8\x14[\xa9\x96\x15o\x01\xa2\x19R\x90c\ +#\xae\xec\xec.\xd2\xef\xa2\x03[\xc0T\x1a\xdd\xe3\x84\ +\xa4\x19\x07\xe8$\xfe7\x09F7$[\xaa\x84o,\ +X\x07\xfc\xc8\x9e\x86\x11|\xe8\xdcT\xf4\x04\x9f\x03|\ +\xd4A\xb0\x87\xd2\x88\x96a4@C\x87\xca\xa9H\x92\ +T\x9d+\xces\xdd\x01S\xd1t}\xca\xb0\x03\xf7\x80\ +N\x1eS\x9a \xf7\x84\x12\xa1\x84\x17\x8c1\x96^I\ +=\xddy\x8a\xab\xf2\x16\x87\x04\xf7\xa4cE\xc8X\xeb\ +\xeb\x8aE\xff\xb4W\xf9\xbe\xea\xa2>|\x04\xde\x0a(\ +\x0c\x99\xa4\x06~\xb8\xe2\xf0ll}\x86w\xbd\xf7\xa9\ ++pTR~\x86v\x18\x03\x00\xe8a\xbd\xfd\x9a\xd1\ +\xe0\xb6\x0cV\x9a\xa0~\x10\x0du\xae\xc1\x1c\xbb\xc3\x89\ +\x10uB\x05\xd5\x08\x08\x09\x03\xca\x0b\xf7\x00\xedTV\ +\x0d\x805\x05\xc1\x01\x0cC#\xacs\x05\xd8<\x0d\x07\ +d!\x1c\xf0B\x12\x13\xd0k\x09\xc2\x12F\x12\xc2\xf1\ +\xea\x90\xa2\xf2<\xc7\x80\xe1\x86Ce=\x00!\xd1\x0d\ +\xc7\x18\xc1\x87B\xc4Z\xc3\xd1E\x09b\x01\x152\xa0\ +(\x06/\xf0,\x88\x81\x08\x1c\x89@\x90\x0cD\xd0:\ +\xaa\x00\x98\x18\x061L\x1f< <\xf1\x09\x18\xc8\x8b\ +B\xe8FE\xd0\xde8#\x00\xd8\x88.\xea!\x80\xd5\ +k\x11\xe0\xb8\x1a\x04\x11X\x13\x19 B\x0a@\xecq\ +\x04\x91(\x0e\x028\x8c\xae\xd5\xe9:B\x03li\x06\ +\x18\xfc\x0eX\xe0\xf8c\xd1\x8c\xad\xc3Uv\xcf\x99\xf8\ +\x17\x91@u\xa9\x01 -#@\xb4P\x03\x12(\x0b\ +\x81\xd6$\x07\xc1<\x94\x03\xa0RN\x01\x98$V\x1e\ +\xb8u{/nB\x14u\x9e\x01\x5c04\x8e\x80\x91\ +\x14\x020W%\xc1:\x22\x04@>Z\x01$\xd6\x02\ +\x00[XQ\xc2\xce^\x0a\x01\x03/\xc3\x0c\xa5'\xcd\ +\xa4\x06\x81\x04\x18\x15CXD\x99AT\xd5\x82`^\ +\x8eG\xe4\xd1\x1fr\x04{\x1b\x81\xe0;\x1a\xc2\xfb!\ +\x83:n\x0c#\xc0\x19\x9cl\xc2'\x11\xc4\x0e\x82G\ +,#E\x81n\x05e\x81\x1b\x0f\xd1\xf8\xc0\xe1\xb8\xe8\ +\x1cQ\x80p\x0d\x83\x046\xa1\x90\xe1\x1b0ls\x0f\ +I\xfc\x1b\xf0\xb8\x1a\ +\xe2hK\x00\x80\x130\xc4\xe2\x02\x1e\xebn\xb3\x09\x02\ +2\x13\xb0\xd4\x18\x80_\x0d\xa0v!\x87\xd8\x1b\x01\x9c\ +\xe3\xa0h\xe0%\x1c\xb9\xcb\x98\xfe\x82\x16<\xe1^\x13\ +d\xe4\x10\xa0\xcd\x0d\x021\x01\xa0\xfa\x13\x80\x9f\x10\xed\ +v!l\x06\xd8\xcb<[e\xfa\x96\x02\x18\xc8\x81\x94\ +\x17\x8c\x82\x0dP\x01\x10B-\x06.A\x06\x8f\xd2i\ +/D\x06l\xc2\x1b,\xc6;h$\xe5@ \x02\xa8\ +\x90\x0f1T\x12\xe9\xd4!\x91B\x19\xeb\xc5\x13\x02,\ +\xe8\xce\x90\xb2.\x94!\xea\xc8\x0a\x86P\x15\xa2\xa0\x86\ +\xa9\x10\x02\x0c\x92\x9b\x22\xe8\x02Np\x8d\x8f\x10\xb9\xc7\ +\x08C\xe0\x1cHC\x84\xfdj=\x16B(\x8d\xc0R\ +\xfe!\xa4\x00q\xac\x00\x82\x18\x85@\xf6zA<\xbb\ +\xc2nPH\xa0\x92\x89*\xb5\xa9\xd4\xb5\xaf\x10\x93\x80\ +(\x03$>\x01\xa7x\x00\xe0\x12&\x01G\x1e!\x18\ +\x121\xe8\xa7\x91\xa0\x22oh\xe5\xa1\xb2\xc9\x82\x18v\ +\xc1&\xca\xe3\xca#e\x04\x96\xe0\x14\xc9\x22\xe2\x03 \ +>\x8d\x89.\x8d\xa3&\xb9\xc94\xc9\x22\x90\xa0\x8b\xc4\ +b\xc1\xcc\x1b\xf1\xee\x22b\xef\x1b\x81\x8cy\xe3\xf6!\ +aq#\xe1L|\x00\xf8\x0bb\x08\xc9\x91\xd1!\x06\ +$\x04\xcf\x10\xe7\x09e\x19F\xb1\x17\xed^+\x8a\xb8\ +\xcb\xec\xee\x1aa\x91\x22\xe24\x10\x92t\x14\xa0\x91'\ +\xa0\xb4!\x8d\x91&\xa1\x8e\x8d\x92\x0e\x03\xe9\x88\x02.\ +\x148\xb0\xae\x1e\xa1\xe4B\xc1\x9a\x18\x011* \xfe\ +g!\xb4grp#\x80\xc1+ \xf0\xf0\xa0\xd8\x10\ +\xe4r\xae\xe9\xe0\x86\xe3\x04\x1cC\x02/\xe1\xb6\xa9\x81\ +\xda\xb3\xcc\x06\xc7J\x9e\x1cr\xae$\x8f\x92\xf9o\x9a\ ++\x8aA-j\xfc\xa4\xe2\xf8\x1bj\x5c\xa5a\xac\xd9\ +\x0af\xd3r\xde'\xf1\xda\x01!\x1f0\xa1du\x02\ +p\xe0,\x07-\xa5~\x1c\xb2\xd0\xb3\xc86\x1c\xa9\xf2\ +\x1b*P\x1b\x8f\x8a\xab\xa6\x130\x22\xb5\x19Mr\x14\ +G2\x07\xe76#j\xee\xc0k\xd6\x1b\xed\xa6\xa5a\ +\xaa\xa5\xd3J\x9e!\xc2\xb1S4[\x88j\xf8\x00{\ +6`\x9a\x96\x80\x1e\x02N2\x1f\x8a&\x86(d\x1b\ +S+\x0b\x81\xbe\x1a\xcd\xa71\xb0\x095\xf3\x8d8\xf3\ +\x9193\x959s\x999\xb3\x9d9\xf3\xa1:3\xa5\ +:s\xa9:\xb3\xad:\xf3\xb1;3\xb5;s\xb9;\ +\xb3\xbd;\xf3\xc1<3\xc5\x0a\x0a \x0a icon / outl\ +iner / entity / \ +Default\x0a\ + Create\ +d with Sketch.\x0a \ +\x0a \x0a <\ +path d=\x22M13.6916\ +3,3.24686842 L8.\ +01783965,6.52512\ +131 L2.34404932,\ +3.24686842 L8,0.\ +481790242 L13.69\ +163,3.24686842 Z\ + M7.25035308,7.8\ +2264135 L7.25035\ +308,14.7689324 L\ +1.9912897,11.723\ +6967 L1.9912897,\ +4.79310939 L7.25\ +035308,7.8226413\ +5 Z M14.0326515,\ +11.6884321 L8.74\ +360561,14.776916\ +3 L8.74360561,7.\ +8257203 L14.0024\ +918,4.79949203 L\ +14.0326515,11.68\ +84321 Z\x22 id=\x22Sha\ +pe\x22 fill=\x22#FFFFF\ +F\x22 fill-rule=\x22no\ +nzero\x22>\x0a \ + \x0a\x0a\ +\x00\x00\x03~\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22?>\x0a\x0a \x0a icon / outl\ +iner / entity / \ +Loop v2\x0a\ + Create\ +d with Sketch.\x0a \x0a \x0a \ + \x0a\x0a\ +\x00\x00\x19\xf8\ +\x00\ +\x00\xe0\x1cx\x9c\xed\x9c\x09\x5c\x14\xd5\x1f\xc0\xdf\xec\xc5\ +\xb5\xdc\x87\x17\xea\x8a\x1c^\xdc7\xca\xb9\xa0\xa0\x22\x08\ +xf\xc9\xb2;\xc0\xea\xb2\xbb\xee\x01hVj\xa6\xa5\ +\x96Gf^e\x1e\x99GiY\x1e\x99\x1d\x9af\x87\ +\x7f\xcb\xdb\xb2\x03\xf3oj\x99Q\xa6V\x9a\xfc\x7f\xbf\ +Y\x16\x06\x04E\x19\xc0\xfe\xcd\x97\x0f\xb3o\xde\xf5\xfb\ +\xbd\xdf\xbcy\xd7\xcc\x9b\xccL\xd2\x8b\x10bK\xbc\xc8\ +M\x22\x02\x17E,\x07!\xf3\x93\x0f\x07\x8a\xe5\x160\ +n\x88GyQ\xc2j\x7f\x88LI\xaa\xdd\x028\xb8\ +Z\xf3\xc9\xaa\xa4\xdcXq<\xab\xddLjV\x9e\xed\ +\xac\xf1\xe7\x11\xaa#\x11[\xdcT\x17\xaaS\x8d\xdb\x9f\ +\xf2f\xe5\xd3\x83%+\x14\x8f\xc4\x07\x5cAT\x18\xe3\ +\xf6\x00w6\x95S\x1b_\xb0\x0b\x8fQ\x9d\xe0T5\ +#\x03\xdd\xd2\x1e\x84DO\x99\xa9\xb6\xca\xfd\xaer\xa6\ +\x91\xd8\x80\x7f:!\xf2uX~\xb0\x87\xe5\xcf\xfe\xc6\ +\x14B\x02\x5c\xac\xbf\xc9*]\x01-\xcb.\xd6\x99t\ +\xc6b\x9d^&\x97\xcb\xc2BB\xa3e=F\xa8\xb5\ +*]\x99\xb1'\xc1\xd3\xb8\x90\xb0\xb8\x90pYhd\ +\x5cX88H\xbf\xc4r\xbdB9\x9e6\xc9\x0a\xe8\ +\x22\xb56\xde\xe7\x97w\xde\xf7\x91\xa9U\xf1>#\x22\ +3C2\xf5r\xbaX\x9d>\xc9@\xe7N\x1a\x92\xa7\ +\x9c4^\x19\xab\xf2IL\xb0\xefW\x1eW^\xa2/\ +\xa1M\x0aYy\x89Fk\x8c+\x8f\xf7Q\xa0\xfc8\ +p\xa3w\xb0\x8f\x8c\x89b\x1a\x1f\xefcQldf\ +\xb6L\xae3\xd0\xb2\xc8\xa0\xa8@ehx\x8c,:\ +6(426&,\xa2\x0f*\x1a\x15\x1c\x12\x1b\x1c\ +\x1a\x11\x18\x12\x1a\x17\x12\x1b\x17\x12*\xab\xc6'\xc1\x1e\ +\x8e\xfd\x0c\xaa\xc2\xb8\x9c\xd4\xfe\xd5\xe2\xe0,\xde\xa7\xd8\ +d\xd2\xc7\x05\x07\x97\x95\x95\x05\x95\x85\x07\xe9\x0cE\xc1\ +\xa1\xb1\xb1\xb1\xc1!a\xc1aa\x81\x10#\xd08Q\ +kR\x94\x07j\x8d\xdd-\x99X\xf3I\xa5\x8dJ\x83\ +ZoR\xeb\xb4284($\xb8\xa1D*eM\x1a\ +\xbd\xd9\xa0aTS)\x83i\x0d]BkMFH\ +\x17\xda`:\xbd\xf5\xda5,\xb2&\xb8Q\xc1\xa0m\ +f\xe6\xed\xf5-)i0\xa5\xd1\x94Vj\xba}J\ +c\xdeD=\x1d\x9cC\x1buf\x83\x92N+\x85\xa2\ +\xd4\xda\x15M\x0b\xd2\xe3\xe4\x06Za\xa2S\xe1?\x01\ +k[`HX`Hx\x1e\xd4\xb6\x90\xa8\xb8\xb0\xc8\ +\xc0\x90\x98\xb8\x90\x90~\xc1\xf5b\xd6\xcb#S\xa7R\ +\x17Nl \x0f\xa6\xc6\xb2\xf3`\xc5\xac\x9f\x07\xd4A\ +\x95\xc2\xa4hR.\xec\xb8\xac|T\xca\xb8B\x9d\xa1\ +DaJP\x97(\x8a\xe8`\x93\xba\xb0\xb0_p\xad\ +/+j\xcd\xa5\x89\x93\xeb4:\x03\xe8E'\x84\xf7\ +\x0bn\xc8\xbb\xc1T\x19ry\xb6AW\xa8\xd6\xd0\x09\ +\xc6\x9c\x01)\xb2\x8c4yThlTT`XP\ +(;\x1bV\xbc\xba\x05\xce\xcc\x8c\xcb\xd0\x1aM\x0a\xad\ +\x92\xceHM\x00\x8f \xb5Z\x15WX\x18AG\x85\ +\xc7D\x05\xd2\x85\xe1t`(\x1dA\x07\x16D+c\ +\x02\xa3\x14\x11\x91ttxAX\xb4R\xc5\xd8\xa0n\ +\xf2[\xb2N\xd5)\xcdXu\xab\xb3V\xdde\xd6\xac\ +\xe4\xb7d\x9dePC\xb3\xa3\xd04SD\x03\xd9\xdc\ +\x22*]m4\xe9\x0c\x13\x13\xeaT\x7f\xa6A\xc8\xa5\ +'\xd4\xf5\xb5\x06h\xd4L\x03\xa1W\x18\x8c4V\xff\ +x\x1fk\xfd\xf7\xb9%\x01\xa6an\xa38\x85\x12\x9b\ +\x96\x04%S\xc3A\xc5:\xbe\x8d'S\xdf\xeb\x05\xbc\ +%y\xe32\xca\x8ai\xed\xed\xeeLV\xac\xc631\ +\xea\x0aMe\x0a\x03\x9d\x5c\x04\x96N\xb8c\xbfc\xcd\ +\xb5n\xb2[\xec\x1dl1x\xbd\xcb\x13|\xeb\xf5\xb1\ +^\xf3z\xd7\xd3\x12\x95\xd5\xb6[:\x8e\xe0\xea\x9e\x03\ +:\xad\xe0\x9a^\xab\xa1\xc2q\x0f/\x84\x17\xc2\x0b\xe1\ +\x85\xf0Bx!\xbc\x10^\x08/\x84\x17\xc2\x0b\xe1\x85\ +\xf0Bx!\xbc\x10^\x08/\x84\x17\xc2\x0b\xe1\x85\xf0\ +Bx!\xbc\x10^\x08/\x84\x17\xc2\x0b\xe1\x85\xf0B\ +x!\xbc\x10^\x08/\x84\x17\xc2\x0b\xe1\x85\xf0Bx\ +!\xbc\x10^\x08/\x84\x17\xc2\x0b\xe1\x85\xf0Bx!\ +\x1c\x0b\xb1\xaf\xdd\x07FkU\xf1>e>\x89\x09$\ +&%#S\xe4\xc7\xec9s!\xf5`\xc2\xe2\x18\xe7\ +\xd9\xeapfw\x1eq\xd0\x1b\xd4ZS\x96\xd9\xa47\ +\x9b\xe0\x14\xb7\xc9\x91l\xa3)\xb7@\xa7\xd3012\ +\xb4&\x9a\xd6\x9aK\xacn\xfc\x95k\x0cx\xee\xcc\xa4\ +\xcdU\x97c\x8c\x14\xb5\x09\xd3\xd4\xe6I\x1b\x86(J\ +\xe8\xbc\xb4\x91y5\xc2,\x09\xb2\x0d:]a.m\ +2\xeb\xb3\x0a\xc6)\xc1[J\xb2\x89\x81\xe8\xe0\xaf\x90\ +\xc8H.\xa1\x89\x89\x98\x89\x9eIb\xaf\xaf\x89m\xcd\ +&Ec\xd2Vk$-0\xab5&\xb5\x96\xc9\x12\ +\xce\xed\x98\xd8\xf2\xccQ\x83,%\xee\x8b\xf1\x05\x81u\ +J\xec\xc6*q\x16\xb3\xf3\xc0\x08\xbe\xed\x98r\xe9M\ +Zk!\xa0\x90\x05\x86\x9a\x93\x9c\x22cfm\x88A\ ++\xaf=\xd1\x9ajO\x06\x17h\x8c5'C\x8aL\ +\xa55'i%\x9a\xd4\x9a\x13\xb0cm\xd6)\xca\xf1\ +E\xd5\x86\xb0(Hr\x06\xa4\xc8\x89e\xdb$\xc9Q\ +\xc9d*\x9d\xb9 IWQs1\x07\x18\xb4\xb7\xf8\ +\xa5hn\x8d\x97bP\xe5\x0d\xd3\x9a\xfaw\xcf\xd1\x98\ +\xd8\x95!E\xa3\x925\xe4\x9fc\xd4\x98\x18\xff\xecr\ +MRN\x8d\xb7})\xad4\xe9\x0c\xa9\x0a\x93\xa2\xa6\ +Vd\x17e\x1b\xad\xb5\x02\xdd\xd5\xbfr\xc6\x08t\xa1\ +\xa9\xa1\xec\xf3t\xfa\x06\xc5\xe6*5\x16\xffl\x832\ +iT\x8d\xb7\x8b\xd2\xa0\xd3\x8f(\xa6\xe1\xe2\xc2\xf5R\ +k\x8b\xac\x16s\xc2\x80\x1c\xd0)Eg2\xe9J4\ +:mQu\x12\xa95\x04U`\xf9;Z\xfds\xd4\ +E\xc5\xec\x00\x07k\x00\xe8V\xe3\x8d5G\xf8\xb3E\ +\x07\x92N,{?\xab\x7f\x99Z\xe5\xcf\x849\xd5\x96\ + qJu\xaaK\x16q\xd2<\x83Bk\xd4+\x0c\ +\xb4V9\xd1R\x13=\x99\x90.\x18J\xf2\xa0\xb6+\ +\x88\x96\x18\xa1\x8e+\xc0M\x83[I&V\xdf\xa5\x91\ +LLWF\x1e\xa9\xaa\xaa\x16\xa1\xa2,\xa1\x9d\x993\ +\x91UO\x91c\xcdy\x17\xe6\xbcC\xdds\xe1e\xe6\ +\xdc\xce\xaa\xa9%\x97\x00K\xfb`o\xadp\x96r\x09\ +\xaf0\xeet\x12\x5cX\x08!\x1a8J\xaa\x13Y|\ +V.YZ\xe3\x13\xc6\x1cG\xc3\xd1\xea\x13\xc9\x1c\x03\ +k}\x98<\xff`\xdcz,IC\x08\xcfc0\xf7\ +a\x8c-,e\x13T\x9f\x09\xea\x9c\x85Xt\xac\xb6\ +j`\x9d0\xdb\xeak\xcf\x5c\x01A\x92\xe5\xbf:\xac\ +K=\xfbwD\x970\xb2\xa6\xd4\x16\xf2\xab\xff-\x96\ +\xb9\x15\xb6\x1f;n\x83\x11\xac\xd46aDk\xd6h\ +,\x0a\x13I\x81\xce\xacU\x19\xeb\xb5 JS\xa8U\ +M\xbc\xedXU\x9e\xd4\xbb7HJ\xed=\xc4\xa8\x91\ +S{\x8b\xe0\xb9\xc4\xa8Q+i\xe3p\xcd`\xbc\xc9\ +\xa9:r\xc4L\x188\xdc\xe0\xdf\x869\xc9He\xe5\ +mSd\xd0\x99\xf5u\xbc$:f\xeb\x9f\xb5\xfdN\ +\xcb\xc5D\x96\xed\x80p\xee\xa80\x9bt\x03h-m\ +\xc0\xadx\x8c\xf6\x13\xf5\xd6\xee\xc7\xde\x12\x19}0$\ +\xa3\xa4H\xd6\x0a\xe5\x17\x9a\x0d\x9a:\x9d\x18c\xfc\xba\ +>\x99\xc6\xa2\xba\x1d\x9dD\xa11\xe5)\x8a\xea\xf89\ +)iHG\x97\x9b2\x8c\xe9y\x99\x83\xadM\xa9\xad\ +\xd5\xbbNd\xbbb\x9daR\xb2F]d\xb5\x94\xb3\ +\xa5\xf0\xe9Vo\xb4\xae\x8a.T\x98\x99\xb6\xd4\xae\x94\ +6\x98\x1a\x88>\xdc\xea]7\xbaCA\x11\xb3\xc3\x95\ +e\x5cWK\x82\x94\x015\x01\xa8\xc6\x10\x9d\x16\x7f\xed\ +L:=t\x98F\x9am8{\x0d\x18\xf2\x16_i\ +\x01\xd3(\xdf\xe2\xef`\xc0\xa6\xb7\x9e7s\x07\xf5\xb0\ +\xa4\x83\x7fAb%\xa9\xf5\xf7`\x9cx\x09\x85\xcc9\ +\xc6 \x82\x93\xd5&\xca\xb7\xfcSP\x05\x98;a\x17\ +iO\xa8\xaa\x93U?\x13)\xb3\xc3q\xac<\x13\xce\ +/\x11'\xe6\x8c\xa8\xa6`\xba\xaaSd:\x91\xda\xda\ +\xda\xda\xd9J\xed\xec\xa4\xae\x0e\xf6\x0e\xae\x9e\xceR\xa9\ +\xb3g{wwOw\xf7\xf6\xaeR\x86\xea\x9f\x86\xa1\ +\x1c\x1d\x1c\x1c\x9d\x1c]\x9c\x9c\x5c<\x9c\x9c\x9c<\xf0\ +\xe0\xe4aI\xe2\xda\x94\x0c\xaa> \xae\xb6\xa0|\xbe\ +\x90\xf2!\x02WJ\xe8JU}\x03\x05\x95T\xed\xa5\ +\x12AK1\xc5Pm8!\xa1\x04\x22\xb1\xc4\xc6\xd6\ +\xce\xde\x81\xaa\x1fH\x11\x81\xd0\x1a\xe8B(\x11%\x14\ +\x88\x04b\x1b\x89\xadX(\x0d\x87@W\xa1\xa8\x9b[\ +\xa88y\xa8\xc2\xddg\xc2\xd40\x89\xc7\xfc\x95o\xa4\ +t\xf7\xf5\xcc\xd9]\x10\x1ea\x98vHn\xe3\xb7 \ +\xb7\xf2\xf4\xafJc\xa4\xd7\xaa-\x8f\xfb\xa7>\x9b\xa7\ +J\xdb\xb3\xda\x14\xd5\xee\xf0\xb0\xef\xe9\xdf\xde\x9c\xfe\xe1\ +\x11\xf3\x99\xcb\xfd\x03\x16\xaey\xe2\xad\xe7\xf6\x1e\xfd\xef\ +\xef/o\xddw\xec\xec\x95\xe1\x85\xa53\x16\xad\xdd\xf6\ +\xd1\xf1\x1f\xaeF\x0f\x18QT6\xf3\xf9W\xb6\xef?\ +q\xee\x9a+\x11\x08@[\x11\xa3\x93\x8dD\x1c\xc9\xa8\ +\xd0-\xd4M\x04\x1aL\xf0q\x17\x87M\x9d\xef\x81\x1a\ +\xec\xce9T\x19\xee[p\xda0m\x81<\xd7Si\ +\x8c\xf8\xd5O\x82\x0a\xd8\xf8G\xee9\x0cJ\xacn\xa7\ +J\x1b\x16e\xa2\xbf\xafQ\xa1q\x0d\x02jU\xa8\xfa\ +\x8aH\x85\x8cLW\x92H\xae\xe4-\xc8\xf0\xeb\xe9\xbb\ + c`\x86\xef\x82\x9c\x05\x19\xbe\x0b\xd7T{dU\ +}q\xbb\xc0C\xb7\x0b<|\xbb\xc0#\xb7\x0b\ +!\xc02\xd4m\x03\x9b\x08^[\x8b\xeb\xf2P\xe6\x9a\ +Q^\x07j\xfd\x1a\x8a\xa7[\x05m0\x8c\x06\x85\xf3\ +j\xfd\x0a\x96\x10\xb2\xfd\x09B\xda\x7fU\xeb\xe7\xfb\x12\ +\xd4Q\xb8n\xdb>g\x95\xc7\x0b\xeb\x0b\xebc\x1fj\ +Z\x19\x84\x06\xad\xe1\x8e\x11\x9a\x00K^\x10fWc\ +\x1eY\xaa\xa5\x97\x93\xa1\xdd\x94\xd0\x97\x99\x0d2\x18\x89\ ++iY`\xfdJ|\xcf\x09\x1b\xd6\xa3O\x0e]H\ +\xe3\x88\x9f\x96\x0d\x87Z\x06\x13\x16\xb8\xdcZ\x95\x9a\xf9\ +n\x89Z\xdb\xd8E\xbc\xc7d\xf5\xb0\xd4k\xc0}\xcd\ +M\xe216\x88\xb8|\xeeA\x84?\x1f \x22w\x07\ +\x22\x1c\xf3\x22\x84P5\xd7m\xb0\xddp\x82w\xde\x88\ +\xae\xe7,\xf5\x9e\xa1\x81!\xa7`.\x1e\x8cjf\xa0\ +E\xe49y2\xa5\xd9Pj\x09c\xc6Vb\x98C\ +8\x13\x0f\xd2\x01f6\xddI\x0f\x18\xfd\x87A#\xd3\ +\x97$\x9142\x90d\xc1Lg\x14y\x08\xe66\xc5\ +\xa4\x04\xe69ed2\x99Jf\x90\xd9d\x1ey\x8e\ +,%+\xc8\x1a\xb2\x9el\x22[\xc8v\xb2\x8b\xec&\ +\x1f\x91\xcf\xc8\x17\xe4\x189E*\xc8Y\xf2\x13\xa9$\ +W\xc9u\xe8\xecl(G\xca\x9d\xea@u\xa5\xfc\xa8\ +\xdeT\x18\x15C%Pi\xd4`*\x87\x1aE\xe5S\ +E\x94\x962S\x93\xa9\xc7\xa9\xd9\xd4\x02j)\xb5\x92\ +ZO\xbdA\xbdM\xed\xa6>\xa1\x0eQ_R\xa7\xa9\ +\x0b\xd4o\xd4_\x02\xa1@*\xf0\x10t\x16\xf8\x0b\x82\ +\x051\x82d\xc1 A\x9e\xe0AA\x91`\x82`\x92\ +`\xba\xe0\x19\xc1b\xc1*\xc1\xab\x82m\x82\xdd\x82\xcf\ +\x04\xc7\x04\x15\x82\x9f\x04W\x84D\xe8 \xf4\x12v\x13\ +\x06\x0ac\x84ra\x96p\xb4\xb0Ph\x10>*\x9c\ +%\x5c$\x5c%\xdc$\xdc)\xdc/<\x22\xac\x10^\ +\x14\xfe)\x92\x88\xdcE2Q\xa0\xa8\xaf(]4L\ +\xa4\x14M\x10=*\x9a#Z*Z'\xda&\xda+\ +:\x22:-\xaa\x14\xdd\x14;\x8a\xbd\xc5\xbd\xc5q\xe2\ +\x0c\xf1Hq\x91\xb8L\xb7;kw\xdd\xde\xd5>\xc0>\xde>\xcf~\x9c\ +\xfdT\xfb\xc5\xf6\x9b\xec\xf7\xd9\x7fm\x7f\xd9\xc1\xc1\xc1\ +\xc7!\xd6a\xa8\x83\xdaa\x8a\xc3b\x87\xd7\x1d>v\ +8\xed\xf0\xa7\xd4M\xdaK*\x97\x8e\x91\x9a\xa5\xcfH\ +_\x91~ \xfdRz\xd9\xd1\xd1\xd1\xdf1\xc9q\xb4\ +\xa3\xc9\xf1\x19\xc7\xf5\x8e\x1f:~\xeb\xf8\x87\x93\xbbS\ +\x90S\x86\x93\xca\xe91\xa7eN\xdb\x9c\x0e;]r\ +\xb6s\xf6sNv~\xc8y\x92\xf3\x22\xe77\x9d?\ +w\xbe\xe8b\xe7\xe2\xef\x22wQ\xb8<\xea\xb2\xcc\xe5\ +m\x97\x13.W\x5c\xdd]C]\xb3\x5cK\x5c\xe7\xb8\ +np\xfd\xc4\xf5\xbc\x9b\x8d\x9b\xbf[\x9a\x9b\xcam\xba\ +\xdbj\xb7\x0f\xdd\xce\xb8\x0b\xdd\xbb\xbb\xcb\xdd\x95\xee\x8f\ +\xbb\xafq\xdf\xe7~\xd6C\xe2\x11\xe0\x91\xe11\xcec\ +\xb6\xc7k\x1e\x07=*=\xdd<#<\x87{\x96{\ +.\xf3|\xd7\xb3\xc2K\xe8\xe5\xef\x95\xe1\xa5\xf1\x9a\xeb\ +\xb5\xc5\xeb\xb8\xd7_\xed:\xb7KnG\xb7{\xaa\xdd\ +\xa6v\x87\xdb]k\xdf\xa9}R{\xba\xfd\xac\xf6\x9b\ +\xdb\x1fk\xffW\x07Y\x87\xb4\x0e\xe3;\xcc\xef\xb0\xbd\ +\xc37\x1dE\x1d{u\x1c\xda\xb1\xac\xe3\x8b\x1d\xf7u\ +\xbc\xd8\xc9\xa3S\xdfN\xcaN\xb3:m\xe9\xf4\x95\xb7\ +\xc0\xbb\x97w\x8e\xf7\xc3\xde\xab\xbd\x0fx_\xe9\xdc\xa5\ +\xf3\x80\xce\xfa\xceK:\x7f\xd8\xf9b\x17\xaf.I]\ +\xc6uY\xd8\xe5\xbd.\x17\xba\xbawM\xe8\xaa\xee\xba\ +\xb0\xeb\xfb]\x7f\x94y\xca\x92e\x1a\xd9b\xd9^Y\ +e7\xefn\xe9\xdd\xcc\xddVv;\xd8\xed\xbaO\x80\ +\xcf0\x9fi>\x9b}\xbe\xe9n\xdf=\xa6{a\xf7\ +\x85\xdd\xf7t\xaf\xf4\xed\xea\x9b\xe9;\xd9w\xa3\xefW\ +~v~1~\xc5~\xcf\xfb\xed\xf7\xbb\xe6\x1f\xe0?\ +\xc2\x7f\xa6\xffv\xff\xf3\x01\xed\x032\x02&\x05l\x0c\ +\xf8\xba\x87c\x8f\xc4\x1e\x13z\xac\xeaq\xb4\xa7\xa4g\ +L\xcf\xf1=_\xe8\xf9E/A\xaf\xc8^\xc5\xbd\x96\ +\xf5\xfa\xbc\xb7\xa0wTou\xef\x17z\x1f\xea#\xee\ +\x13\xdbG\xdbgU\x9f\x13\x81\xd2\xc0\xe4\xc0\xd2\xc0\x8d\ +\x81\xa7\x83\xbc\x82\x06\x07M\x0b\xda\x1et)\xd87x\ +t\xf0\xfc\xe0\xfd\xc17C\x22C4!kBN\x85\ +\xba\x85\x0e\x0c\x9d\x16\xba3\xf4\xb7\xb0^a\xca\xb0e\ +aG\xc3\x1d\xc3\xfb\x87?\x16\xbe#\xfc\xd7\x88\xde\x11\ +t\xc4\x8b\x11'#\xdd#3#gF\xee\x89\xfc;\ +*:\xca\x10\xb5)\xeaB\xb4ot~\xf4\xf2\xe8\x13\ +1\x1e1\xd91sb>\x8e\x15\xc7\xa6\xc4>\x16\xbb\ ++\xf6\xcf\xb8\xa88S\xdc\x96\xb8_\xfa\x06\xf6\x1d\xdf\ +wC\xdf\xf3\xfd\x02\xfa\xd1\xfd\xd6\xf4;\x13\xef\x13\xaf\ +\x88_\x19_\x91 K\xc8Ox)\xa1\x22\xb1[\xa2\ +\x22qU\xe2\xf7I\xdd\x93TIk\x93\xce%\xf7L\ +\x1e\x97\xfcj\xf2\xa5\x94\x90\x14C\xca\xd6\x94k\xf28\ +\xf9#\xf2\x0fR\x85\xa9\x03Rg\xa5\x1eLsK\x1b\ +\x96\xb64\xed\xdb\xfe>\xfd\x8b\xfao\xec_9 r\ +\xc0\xc3\x03>H\x17\xa7\x0fJ\x9f\x9f~\x22\xa3s\x86\ +2c}F\xe5\xc0\xe8\x81\x8f\x0c\xdc;H:(w\ +\xd0\xd2A\xdf\x0f\xee5\xd80xg\xa6 s`\xe6\ +\xb3\x99_\x0f\xf1\x1b\xa2\x1d\xb2=\x8bded=\x9b\ +\xf5Mv@\xf6\x84\xecw\x86J\x86f\x0f]6\xf4\ +\x87\x9c\xd0\x9c\xc99\xfbs\xdds\xc7\xe6n\xc8\xbd\x9a\ +\x97\x9277\xef\xd4\xb0\x1e\xc3\xcc\xc3\xf6\x0cw\x1e>\ +f\xf8\xfa\xe1\xd7F\xa4\x8eX0\xa2bd\xf0\xc8G\ +F~6\xaa\xe3(\xf5\xa8\x1d\xa3mF\x0f\x1f\xbdv\ +\xf4\x95\x07\xd2\x1ex\xee\x81\xb3c\x22\xc7\xcc\x18s\xfc\ +\xc1\x80\x07\xcb\x1f\xfc\xe4\xa1\x8e\x0fi\x1ezw\xac\xf3\ +X\xc5\xd87\xf3\xc5\xf9#\xf27\xe4\xdfPd)V\ +)\xae\x14d\x14,/\xa8T\xca\x95\xcf+\x7fR%\ +\xa9\x16\xaa.\xd0\xf1\xf4\x02\xfa\x5ca|\xe1\x82\xc2\xf3\ +E\xf1E\xcf\x16](N,^T|Q-W/\ +U\xff:.}\xdc\x8aq\xd7\xc6g\x8d\x7fe|\x95\ +f\x84fs\x89mI~\xc9\xdbZ7\xedx\xed^\ +]\x17]\xb9\xee\x90\xbe\xb7~\x86\xbebB\xdc\x84\xe7\ +&T\x1a\x06\x19\xd6\x1a)\xe3\x83\xc6\x1d&\x0f\x18L\ +\x1d0\xf70?a>]\x9aP\xba\xac\xf4\x8f\xb2\xe1\ +eo\x96\xbb\x96k\xcb\x0fL\xec5\xf1\xa9\x89\xe7&\ +\xf5\x9f\xf4\xf2\xc3\xa2\x87\x95\x0f\xef\x99\xdcm\xf2\xd4\xc9\ +\xa7\x1fI~d\xe5\xa3\xd4\xa3\x05\x8f\xeey\xac\xfbc\ +\xd3\x1f;;e\xc0\x94uS\xed\xa7\x8e\x9f\xfa\x9fi\ +!\xd3\x16L\xfb\xfd\xf1\x11\x8f\xef\x9c\xdey\xfa\x94\xe9\ +g\x9e\x18\xf0\xc4\xc6\x19N3\x0c3N\xcc\xec;s\ +\xc5\x93\xa2'\xd5O\x1e|*\xfc\xa9%O\xdd\x9c\xa5\ +\x9a\xf5\xe9\xec\x90\xd9\x8bf\xdf\x98\xa3\x9c\xf3\xe9\xd3\xa1\ +O/~\xba\xea\x99\xc2g\x0e\xce\x8d\x9a\xfb\xe2<\xc9\ +<\xed\xbc\xe3\xf3\x13\xe7\xaf[\xe0\xba`\xd2\x823\xcf\ +f>\xbbm\xa1l\xe1\xac\x85\xbf?7\xf6\xb9O\x16\ +E,Z\xf1\xbc\xfd\xf3\xe6\xe7+\x16\x0f^\xbcc\x89\ +\xef\x92yKn,-^zlY\xca\xb2\xcd\xcb\xbd\ +\x97?\xb5\xfc\xda\x0b\xaa\x17\x0e\xbf\x98\xf4\xe2\xa6\x15\x9d\ +W\xcc^\xf1\xd7K\xea\x97N\xae\x1c\xb0r\xdb*\xff\ +U\x8bVKV\x97\xae\xfea\xcd\xf05\xfb_\x8ey\ +y\xfd\xda\x8ekg\xaf\xfd\xfb\x15\xed+\x15\xebr\xd6\ +\xed]\x1f\xbd~\xfd\x06\xef\x0ds7\x0a6\x9a7^\ +xu\xcc\xab_\xbc\x96\xfa\xda\x8eM\x81\x9bVn\xf6\ +\xda<\xfbu\xf2\xba\xf9\xf5\x1f\xdf\xc8\x7f\xe3\xf8\x96A\ +[\xf6\xbc\x19\xf3\xe6\xa6\xb7\xfc\xdeZ\xbe\xd5}\xeb\xac\ +m\xd4\xb6\x89\xdb*\xb7\x17o\xaf\xd81j\xc7\xa1\xb7\ +\x07\xbe\xbdgg\xdf\x9d[\xdf\x09z\xe7\x95]\xddv\ +-{\xd7\xf3\xdd\xb9\xef\xd9\xbf7\xfd\xbd\xaa\xf7'\xbd\ +\x7f\xe5\x03\xfd\x07\x17w\x17\xed>\xb3g\xec\x9eS\x1f\ +\x8e\xfc\xf0\xe8\xde\xa1{\x0f\xee\x1b\xb4\xef\xe3\x8f\xfa\x7f\ +\xf4\xe1\xfe\xe4\xfd\xef\x7f\x1c\xff\xf1\xaeO\xe2>y\xfb\ +\xd3\x98O\xb7\x7f\x16\xf5\xd9\xb6\x03\x91\x07\xb6\xfe'\xf2\ +?[\x0fF\x1d\xdc\xf6y\xf4\xe7;\xbe\x88\xfdb\xe7\ +\xa1~\x87\xde;\x9cxx\xf7\x91\xd4#\x1f\x1d\xcd8\ +\xfa\xd9\xb1!\xc7\x0e\x1d\x1fv\xfc\xe4\x891'*N\ +\xaaN\x9e\xffR\xf3\xe5\xaf_\x95~u\xfd\xd4\x94\xaf\ +\xc5_\xcf\xfa\xc6\xe5\x9bE\xdfz\x7f\xbb\xea\xbb\x9e\xdf\ +m\xae\x88\xaax\xf7t\xea\xe9\x03\xdf\xe7~\x7f\xea\x8c\ +\xf2\xccO\xff5\xfe\xf7\xc6\xd9\xe9?8\xfe\xb0\xe8\x5c\ +\xd7s\xeb\xcf\x87\x9d\xdfu\xa1\xff\x85/~|\xe0\xc7\ +\xb3?\xe9\x7f\xba~q\xc6\xcf\xae?/\xbf\xd4\xe3\xd2\ +[\xbf$\xfdr\xa0rd\xe5\xd9_\x0d\xbfV\xfd6\ +\xe7r\x87\xcb\xaf\xfc\x1e\xf1\xfb\x9e+\xd9W\xbe\xbdZ\ +r\xf5\xfa\xb5Y\x7ft\xf8c\xdd\x9f1\x7f\xee\xffk\ +\xc4_\xe7\xae\x97\xdd\xb0\xb9\xb1\xf8\xef\x9e\x7f\xef\xbc9\ +\xe8\xe6\xd7U%5+\x93<<<<<<<<\ +<<<<<<<<<<<<<<<<\ +<<<<<\xffbl\x81\x91@[\xeb\xf1oe\ +\x05\x80{e^\x04\xf0Z\xb4\xb5>\xff&\xb0\xde\xb3\ +\xf7+}\x06t\x01ZBVG`\x180\x13\xd8\x01\ +\x1c\x03~\x00\xaeU\x83\xee\xe3\xc0\xdb\xc0\x93\xc0p\x00\ +\xd3\xb4\x84.\xf7\x0bX\xdf\xb1\xde\xb3\xaf\xc1\x8f@\x0a\ +\xc0E\xfe\x9d\x802`?p\x13hx\x97Z\xe3`\ +\x9aO\x80r\xa03\xc0\x85N\xf7#%\xc0_\x80\xb5\ +\xdc7\x00\x1dp\xaf\xf9\xc5\x00\xeb\x80\xeb\xc0\xdd\xda\xbc\ +10\xaf\x0d@\x1c\xc0e\xd9\xef\x17\xfa\x02\xe7\x00v\ +\x99\xd7\x02\xf6@S\xf3\xf0\x06\xd0F\x5c\xd9\xbc1^\ +\x05Z\xaa\x9dlK:\x00\x1f\x01\xec\xb2\x1e\x02|\x80\ +\xdb\xa5\x93\x00\xd8F\xfc\x0e\xb4\xb4\xed\xad\x5c\x01&\x01\ +6@k\xd9\xa75@[.\x01\xd8e\xbd\x04\x0c\x00\ +\x1a\x8a\xdf\x1f\xf8\x12h-\xbb\xd7\xe7\x14\x90\x0e\xb4\xb6\ +\x9dZ\x9a\x02\xe0\x0f\xc0Z\xce\xbf\x01\xecK\xad{\x1e\ +\x05\xc0\x13@[\xd9\xbd>8fB\x9d\xda\xdan\x5c\ +\x12\x09|\x0f\xb0\xcb\xf9\x1a\x80\xed\xfcV\xa0\xadl\xdd\ +\x18\xdb\x01\x17\xa0\xad\xed\xc6%\x9e\xc0\xfb\x00\xbb\x9c\x7f\ +\x02md\xe2;\x82\xedQo\xa0\xad\xed\xc6%\x22`\ +>\xd0\xd6\xb6m*\x97\x814\xa0\xad\xed\xc6%\xa9\xc0\ +\xfd\x5c\xef\xeb\x83s\xea\xff\x97k\x80c\x1c,\x0f\x17\ +v9\x0b\xe0\xbd\x84c\x96^\x80#\x80\xdfB\xf0\x07\ +\xce\x00\x5c\xc8\xb0\x82:\xa3\xeemm\xbf\xe6\x80\xe3N\ +.l_\x01\xe4\x02\xb7\x1b\xa3`\xdb\xcd\x85\xdd\xd9\xa0\ +\xee\x8d\x8d\x9d\xefwp\xfc\x83\xf3\x9c\xe6\xda`\x0e`\ +\x07\xdcI^K\xd8\x1f\xc12D\x00\xada3\xae\xc0\ +\xf9}\xfd\xf5\x88\xbb\x05\xe7\x0c\xe3\x80\xa6\xcal)\xfb\ +#X\x96\x7f\xca\x1a\x1e~\xc7\xe6\x08\xd0\xdc2\xdf\xed\ +\x1a^K\xda\x1f\xc1\xb5\x14\xecoZ\xcan\x5c\x80\xf3\ +\xdb\xb7\x00.\xca\x8bm~(\xd0T\xd9-m\x7f\xe4\ +\x0d\x80\xf5\xdd\xa2\xfb\x8e\xc9@s\xcb\xc8^\xeb\xbf\x0a\ +<\x084Evk\xd8\x1f\xc1u\x94\x96\xb6\xe3\xbd\xd0\ +\x0f\xc0\xb5\xff\xe6\x96\x0f\xc7\x97\x95\x00\xdbo\x1e\x80\xf3\ +\xb8\xdb\xc9o-\xfb\xe3\xb3\x84h\xa0\xb5\xec\xda\x14\xb0\ +\xcd\xc7\xf6\xa2\xb9e\xc3<\xc4\x80\x1fp\x14`\x87\xed\ +\x01\xda\x01\x8d\xe9\xd0Z\xf6G\xbe\x02\xee\xe6\xd9FK\ +\xf34\xc0E\xb9\x9e\x02\xacy\xe2\xbc\xaa\xfe\xf3\x98\xff\ +\x02\x8d\xd5\xbd\xd6\xb4?2\x15h=\x0b7\x0e\xae\x19\ +\xe2\x9a\x09\x17eJ\x02\xea\xe7\x8f\xcff\xd8\xed\x1a\xae\ +c\xa8T*U\xfdx\xadm\x7f|\xae\x81u\xa4U\ +\x8c|\x1bJ\x01.\xca\x83}-\xb6=\x0d\xc9\xc0\xf5\ +\xa3\x8b\x00;\xfeR\x00\x9f\xf7X\xe3\xb4\xb6\xfd\x91\x09\ +@\xebY\xbaa\xb8Z\xcb\xff\x1a\xb8\x9d\x1c\xfc`\xf9\ +A\x80\x9d\xe6c\x00\xdf\x93\xc0p|\xce\x19\xd0D\xb8\ +z\xe6\xb6\x05h\x1d+7\x0eWe\xd9\x0b\xdcI\x16\ +\xaeC\xac\x06\xd8\xe9\xce\x03\x09\xc0\xdd\xe8\xfc\x1e\xc0\x85\ +\xce'\x80{\xb7\x1c7`\xbb\xc1EY\xde\x04\x9a*\ +S\x0f\xb0\xdfOA\xb7F\xa3\xd145\xfdf\x80\x0b\ +\x9d\xb1\xec\xf7f5\xee\xf8\x0e\xe0\xa2,\xf8\xee\xc4\xdd\ +\xc8\xc5:\x8fu\x9f\x9d\xc7*\xa0)ku8\x96\xe5\ +B\xe7o\x81{\xb7\x1c7\xbc\x03pQ\x96o\x80\xbb\ +\x95\x8dm?\xf6\x01\xec|\xb0\x8f\xc0\xbe\xe2v\xe9\xb8\ +j3\xf1}\xc7{6\x1cG\xe0\xbb\x03\x5c\x94\x05\xd7\ +\xda\xd9\xe3\x99\xa6\x82\xef\xf0,\x07\xd8y\xe1X\x09\xc7\ +L\x0d\xc5\xc71\x16\x17\xeb\xe2\xc8t\xa0\xf9\x16l\x1e\ +]\x01.\xd6\x1d\x90\xe6\xbc;Z\x08\xb0\x9fq\xa2N\ +f\xa0~\xbcD\x80\x0b]Q\xd6\xfd\xf2\x8e\xefz\x80\ +\x8b2\xcd\x06\x9a\xa3\x07\xbe;\x8asdv\x9e8\x87\ +v\x00\xacqp\x8e\xcd\x85\xae\xf8\xeeq\xf3-\xc7\x0d\ +8\xf6\xfe\x0dhn\x99\xf0}\xa1{i\x83\xd8\xe0\x1a\ +Q\xfd\xfe\x15\xd7\x92|\x01\xcc\xfb4\xd0\x5c=\x7f\x01\ +\xac\xf3\x8e\xfb\x85\x87\x80\xe6\x96\x0b)\x06\x9a\xab\x0b\xb6\ +\xf1\x0b\x81\xfa6{\x16\xe0B\xc7\x11\x00\x176\xe3\x1a\ +\xeb~\x98\xe6\x80\xf5\x93\xdd^4\x07\xac\x13\xec\xe7\xff\ +\xf7\xb2\x8f\xa0>\xb8\xee\xc1\x85n-\x01\x8e\xbd\xeb\xaf\ +\x11\xdc\x0bk\x00\xaet\x0a\x03\xb8X\x1bG\x0e\x00\xf7\ +\xfb;\xd3\xf8\x9c\x1a\xdf\xd3inY\xef\xe6\xd9\xfb\x9d\ +\xe0b\x8d\x10\xfb\xf5\xfb\xad\xcdo\x8c\x10\xa0\xb9k\xd2\ +\xd8V\x18\x80\xe6\xea\x82c\xd0\xe6\xb6;8\xb6\x08\x06\ +\xb8\xb0Mk\x91\x01p1/x\x0e\xb8\x97\xf7\x0e\xf0\ +\x99\xdcb\xa0\xb9\xf2\xb1\x0c\xff\xd4=\x02c\x00.\xae\ +\x01\xeeo\x1c\x0b4\xf6|\x80\x0d\x8e1\xf3\x81\xfak\ +C\xf7j{,Ck\xd8\xaa\xa5\x18\x05p5?\xc6\ +gN8\xef\xc1\xfd\xa58\xd7\xf2\xae\x06\xdd\xe8\x87\xe3\ +/\x1cgr!\x0buF\xdd\xdb\xda~\x5c\x90\x07p\ +\xb9\x9f\xb1\xa5A\xdb\xe3~\xe3\xb6\xb6\x1b\x97d\x03\x5c\ +\xbd\x07\xdd\x1a<\x03\xdc\xe9\x9d\x97\x7f\x1a\xe1\x00\x17\xf3\ +\xff\x96\x82\xbd\x8f\x19\xc1\xbd;\xb8\x87\xa7\xad\xed\xc6%\ +\x1e\xc0\xbb@[\xd9\xb81\xd0\xd6\xf8\xdc`\x13\xc0\xf6\ +\xc75)|\x97\xbb\xad\xed\xc6%B\x00\xd7:\xdb\xca\ +\xd6\xf5a\xb75\xf8~\xe7\xc3\x00\xbe\x7fm\x0d\xc7\xbd\ +\x9c\xb8\xa7\xb3\xad\xed\xc658Gh\x8b\xf7F\xac\xe0\ +;\x17\x83\x80\x86t\xc31?\x8e\xb7\xd8\xf1\x17\x01M\ +\x19\x03\xff\x93h\x8b\xfd\xef(\xab)\xfb\xdfq]\x1d\ +\xdf;g\xa7\xdd\x07\xe0^\xff\xd6\xb2Ok\x81k+\ +\xf8\xcd\x88\x96\xb6=~\xdb\x03\xe7\x0cM\xd5\x0b\xdf\xf3\ +\xac\xaf\x17\xce\x07\xf1\x9b\x17-i\x8f\xb6\x02\xc7H+\ +\x01\xf6\xfe\xf9\xe6\x82\xcf\x0a\xf1\xdd\x88\xe6\xec#\xc2\xb5\ +(\xf6<\x12\xc7J\x5c\xae\x11\xdeo\xe0\xb8\x0f\xbfm\ +\x83c\xa5{\x99\xbba\x1a|\xcfJ\x0bx\x01\x5c\xe8\ +\x94\x0c\xe07\x8e\xd8rp\xce\xfd\xff\xfe\xed/W\x00\ +\xfbjl\xb3\xf1y.~\x93\xe9$\x80k<\x17\x00\ +t\xe3{(\x1b\x01\x8c3\x10\xc04-\xa1\x0b\xae\xaf\ +\xe3\xb7\xbe\xd8\xd7\x80\xff\x06^\xeb\x82\xf5\x9d\xfd\xed\xbb\ +\xb6\xd6\xe7\xdf\x0a\xd6\xfb\xff\xf7\xb6\x87\x87\x87\x87\x87\x87\ +\x87\x87\x87\x87\x87\x87\x87\x87\x87\x87\x87\x87\x87\x87\x87\x87\ +\x87\x87\x87\x87\x87\x87\x87\x87\xe7\x1f\x81\xf0%\x8a\x08\xe1\ +\x97\x82?\xf2\x92\x80\x88\x187!\xf9/\x09k\xdd\x96\ +\xa8\xff\x03;\xbc\xca\x99\ +\x00\x00\x08'\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22?>\x0a\x0a \x0a icon / outl\ +iner / slice / n\ +ot active - save\ +d\x0a Created with\ + Sketch.\x0a\ + \x0a \x0a \ + \x0a \ + \x0a \ + \x0a \ + \ +\x0a \ + \x0a <\ +rect id=\x22Rectang\ +le-22-Copy-2\x22 tr\ +ansform=\x22transla\ +te(7.409295, 7.7\ +12904) rotate(-4\ +5.000000) transl\ +ate(-7.409295, -\ +7.712904) \x22 x=\x226\ +.40929495\x22 y=\x22-1\ +.28709556\x22 width\ +=\x222\x22 height=\x2218\x22\ +>\x0a \ + \x0a \x0a<\ +/svg>\x0a\ +\x00\x00\x05\x1d\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22?>\x0a\x0a \x0a Artboard\x0a \ +Created with Ske\ +tch.\x0a \ +\x0a\ + \x0a \ + \x0a \ + \x0a \ +\x0a\x0a\ +\x00\x00\x05\x09\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22?>\x0a\x0a \x0a Artboard\x0a \ +Created with Ske\ +tch.\x0a \ +\ +\x0a \x0a \ + \x0a \ + \x0a \ +\x0a\x0a\ +\x00\x00\x07^\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22?>\x0a\x0a \x0a icon / outlin\ +er / visible / m\ +ixed state - hov\ +er\x0a <\ +desc>Created wit\ +h Sketch.\ +\x0a \x0a \ + \x0a \ + \x0a \ + \ +\x0a \ + \x0a\ + \ + \ +\x0a \ + \x0a \ + \x0a \ + \x0a\ + \x0a \ + \x0a\x0a\ +\x00\x001/\ +\x00\ +\x01\x04 x\x9c\xed=\x07@SW\xd7\xf7%\xec\xa5\ +lpF\x147#\xcc$\xa8\x88\xb8P\xa9\x0a\x8a\xa3\ +\xfaIH\xc2\xd0\x90`\x12\xdc\xab\xcb~\xd5\xd6\x81\xd6\ +]m\xd5\xda\xaa\xd5\xd6Zg\x9d\xe0.8\xab\xb6\xda\ +\xe1\xde\x0a8\x90\x99\xfc\xe7\xbc\xe4a\x8c\x8c\xa0Q\xfb\ +\xf7\xcb\x0d\xe7\xbd;\xce=\xe7\xdcs\xef;\xf7\xdc\xfb\ +\x06\xb1\xb1\xa4-!\xc4\x86x\x115\xb1\x80\x18E\xb4\ +\x076}J\x84\x03\xa5\x17g\xd1q\xc0\xa3\xfc)\xb6\ +.\x1f\x90)+]\x9c\x05\x07g\x86\xce\x90\x06\x94\x8b\ +\x1e\x8e\xbb.\x8e\xb5=\xf4hz2\xf8s\x08\xd5\x80\ +Xj\xe3T\x18\xd5\xb02\xde\x89j\xa4G\xa7\xb5\x1e\ +/.\x1e\x89\x0f\xc4\xbaSAt\xdc\x0d\xe2\xa9T\xdc\ +3|\xd6.\xa7\xe7\x0d\xc3x\ +\x83_!\xbf'\xea\x05\xf4\xa4\xfd\xd9\x95O#\xa4U\ +}\xe6\x1c%\x96'I8\xfdR\xe5*\xb92U\x9e\ +\xc1\x89\x8e\xe6\x04\x05r\xc39\xad\x07\xa5\xc9\xc4\xf2\xb1\ +\xca6\x04\x93\x82\xc0\x10\xf8\xe3p\xb9\x82 \x9e\x80\x1b\ +F:D\x8e\xcb\x10\x8aFIT\x9c$IJ\x9a\xac\ +\xa3O\xfe\xcf{}8i\xe2\x8e>\x83Bc\x03c\ +3\xa2%\xa9i='($\xf1\x13\xde\x19 \x9a0\ +J\xc4\x17\xfbDv\xb2\xeb0N0.=#]\xa2\ +\x12r\xc6\xa5KeJ\xc1\xb8\x8e>B\xe4/\x808\ +f\x07\xf8ph\x14\xd5\xa8\x8e>Z\xc1\x06\xc7\xf6\xe3\ +D\xcb\x15\x12N\xa8\x7f\x98\x9f\x88\x1b\xcc\xe3\x84\xf3\xfd\ +\xb9\xa1|^PH{\x144, \x90\x1f\xc0\x0d\xf1\ +\x0b\xe4\x0a\x02\xf9\x82@.G\x17|:\xd9\xc1\xb1\x83\ +B\x9c,\x88\xeb\xda]\xc7\x0eR\x1d}RU\xaa\x0c\ +A@\xc0\xd8\xb1c\xfd\xc7\x06\xfb\xcb\x15)\x01\x5c>\ +\x9f\x1f\x10\x18\x14\x10\x14\xe4\x07\x18~\xca\xf12\x95p\ +\x9c\x9fL\xd9\x5cK\x84\xa1\xd3U\xa2\x14)\xd22T\ +ir\x19\x07\xd3\xc2$y\xa6\xaa\xa3\x8f\x8f\x1dG/\ +\xe8\xda\x95\x9eQ\xc9H\xa6\xf4\xa7\xdb\xe8/\x92\xa7\x07\ +\x8c\x13f\x04p\xfd\x03\x03\xaa\xaa$\x16U\xd6\xc9\xc8\ +THi\xd1\xc4\xa2\x00\x89T\x92.\x91\xa9\x94P\x8f\ +[e\xbd\x0c\xa6\xef\xaafYY\x5c-c\x9066\ +\xb6fy\xd3\xd3\xab\xac\xa9Tu\x1b\xa3\xaa\xb9\xa6r\ +\xc0\xf8\x0cI@\x9cD)\xcfT\x88$\xdd\xc6@S\ +\x9e\xe9\x15U\x0b\xdc\x05\xd1\x0a\x89P%\xe9\x0a\xd0\x09\ +G\x9b_`\x90_`\xf0\x00n\xa8 0L\x10\x14\ +\xea\x17\xc8\x13\x04\x06v\x080\xc04\xa0\x11+\x17\xa7\ +%\x8f\xd7\xa3\x01\x83\x22d\x003b\xfd\x02\xc3+i\ +\xe8a\x1a\xd2\x801(\x16\xaa\x84FQ\xd1\xc7\xad\xaa\ +=r\xc5\x00\xb9\x5c\xda\xa9\xd6\x0bL\xafa\xba*z\ +\xd4\xc4\x22A\xb2\x5c\x91.TuJK\x17\xa6H\x02\ +Ti\xc9\xc9\x1d\x02\x9e\xe5\xea\xa1Vv\xb4 Z.\ +\x95+\xa0\x95\x92N\xc1\x1d\x02\xaa\xca\xae\xb2VLt\ +t?\x85<9M*\xe9\xa4\x8c\xeb\xd1\x85\x13\xd3-\ +:\x8c\xcb\x0f\x0b\xf3\x0b\xf2\xe7\xea\x93\xd1\xc3\xab\x92N\ +W\xb9(\x13Gl\x94L$QB\x93\x94\x9d\x9e\x1b\ +9\xf4\xb5\xd4E\x98\xf2|.S M\xeb\xa4\xb5\x08\ +b\xb9(M\xfcll\x0b\x84\x22\xa1D\x12\x92\x9c\xec\ +\x07\x22\x05\xfaq\xb9\x92p\xbf$!\x1c$a\x92p\ +a\xa8H\x1c\xc4\xe3\x86t\x08\xd0\x91\xa8\x8e4(\xda\ +_\x0cd\x93\x93C$a\xc1\xbc0?Ir\xb0\xc4\ +\x8f+\x09\x91\xf8%\x85\x8bx~a\xc2\x90PIx\ +pRP\xb8H\x5c51m\xee\xf3\xe2\xeb+\xa7\xa6\ +\xc6w\xa0/4A\x8cL\xa9\x12BqLWZ\x9e\ +4\x90\x87\x1f\x1a,\x11\xf3\xf9\xc9~ S\xb2_R\ +(\xc8#\x0c\x0a\x0c\xf3\x13\x06\x07\x07qy\x81a\x10\ +\x0f\xa1\x87\xc9\xf3\xd5_ \xcdp\x87\xb2\xaa\xb5\x18\x1e\ +\x12\x1c\xce\x0b\xe2\x89Q\x8b!Z-\xf2D!I~\ +\xe2\xb0d\x89(\x5c\x98\xc4\x0b\x16\x051\x8c\xf4\x88\xbd\ +\xc0\xa8\xaf\x22\x0d\xcc\xbeP\xaa\x87S\xa9[Qp\x90\ +$\x9c\xcf\xf3K\x16's\xfdB\xf9!b?~h\ +2\xdfO\x18\x12\xc6\x0d\xe7\x86'\x85\x09\x85\xe1\x0c\x8b\ +*\xc8\xbc\xc0\xaag\x1a\xeaq|\x15\x83(^2\xba\ +\xba\x9e\xa6\x0dt\x86P\xa1\x94\xa0\xf9\xe9\xe8\xc3\xd8\x1f\ +\x9f\x17*`\x1d\xda\x8c\xc1\x08C\xd3\xdeID[\x18\ +\xe8\xfe\xe7r\xab\xaf\x96\xf6bw\x1a\xa7\x82\x17\xaaW\ +\xcfcl\xaaDV\x93e\xd4\xc3\xaa\x9e\x88R\x9e\xac\ +\x1a+TH\xa2R@\xd3\xc6\x98\xa5\xaa\xaa\xbd\xa0\xef\ +Z.\xb9W\xe8\x08\xa5p\xcc\xabuCprxX\ +\x92\x04\xac6O,\x0a\xf2\x13\xf2B\xa0\x07P\x87\xe1\ +\xa1\xdc\xe0\xe0\xf0 a\x08\x97+~\xb5n\x80>\xe0\ +\x0aB\xb8o\xbf\x1b\x9e\x91\x17\xa5\x0ae)\x12q\xa7\ +\x00\xa6\x22\x93\xf1\xff\xa9\xe7\x8c\xb3\x87/\xd7sUN\ +\xe8\xff\x82\x9e\xd3\xe6>o\x13\x19;k`C\xb5\xa8\ +z\xfe\xac\xd6Y\x0e\xd0y\xcb\xe0\xa8\x07Tz\xeaU\ +\x09l\xfa`fbfbfbfbfbfb\ +fbfbfbfbfbfbfbfb\ +fbfbfbfbfbfbfbfb\ +fbfbfbfbfbfbfbfb\ +fbfbfbfbfbfbfbfb\ +fbfbfbfbfbfbfbfb\ +b&v\xcf\xde}\x95\xc8\xc4\x1d}\xc6\xfaDv\x22\ +\x8d\xa8\xa1\x84\xdd\xd0\xb7G\xe5\x99E\xe8Wzy]\ +bb-|\xe9\xf7o\xeb\x1f\x1e\xeey]\xb5E\xf6\ +\xe4\xe2\x1e\xfe\xfc}\xb7\xc7\x0f\xa3\xcb\x04t\xd9u,\ +g\xde`&\xf6\x19\x8a4\x99\xaao\xa6*#S\x05\ +I|\x95\x98\xf4S\xaa\xe2\x93\xe4r)\x8d\x11#S\ +I$\xb2\xcct&\x8e\xe7h\xa9\x02\xd3\xf5\xe8\xba\xf1\ +i\xe3\x10\xa3K\x9a\x0a\xeb<\xa3)Q\xbc#L\x97\ +\x0c\xe86x@%3m\x85~\x0a\xb9<9^\xa2\ +\xca\xcc\xe8\x9b4R\x04\xd9\x0e\xa4\x1fQ\x109\xfc\x92\ +\x09\x87\xc4\x13\x09Q\x91L\x92AW\xb1\xcb\xa8\xc4f\ +\xc8t\x91\xaad:\x89\x1c\x922\xd3\xa4\xaa4\x19M\ +\x12\xd2\xb64vt\xec\x90\xdeZmD >\xcb\xef\ +\xb9\x16\xbb\xe8\xb5\xb8/\xfdF\x82R\xfb\xae3\xb4+\ +C%c\x1a\x01\x8dLRT&\xe2R\x94\xb1\xcfJ\ +\x14\xb2\xe8g\x09\x99\xeaY\xa2O\x92TY\x99x'\ +E5\xa62\xd1-]\xda\xb52\x01z|F\xba\x8b\ +hT\x8aN\x11Z\x01I\x5c\x8f.\xd1D\xfbj9\ +\x89\x13s8byfRg\xf9%\xc2\x84\x1e\x0a\xd9\ +\x0by]\xa4/\xe2uQ\x88\x07\x0c\x94\xa9\xba7\x8f\ +\x93\xaa\x88^\xe8\x22\x15s\xaa\xca\x8fSJUt~\ +\xbfq\xd2\xceq\x95\xd9vc$\x22\x95\x5c\xd1U\xa8\ +\x12V\x8e\x8a~)\xfd\x94\xcc\xa8\xc0\xb8\xee\x1cM+\ +A\x92\xac\xaa\x8a\xfc\x00yF\x95l\xe3ERm~\ +?\x85\xa8\xf3\x90\xca\xec\xfa\x22\x85?\xf0\xeb\xb5\xc7_o\ +9x\xf6\xfa\x93\x84\xe41\xd3\x17\xac\xd9z\xe8\xdc\x8d\ +\xa2\xf0\x1e\x83R\xc6~\xbc\xf0\x9bm\x87\xcf\xdf|\xea\ +LX,\x90\xd6\x82\x96\xc9\xda\xca2\x94\x16\xa1\x19\xd7\ +\xc5\x02$\x18\xed\xe3j\x19\xf4\xde\x5c7\x94`\x7f\xdc\ +\xa9\x82\xe0\x16I\x97\x15\xefgE\xc7\xbb\x8b\x94!\x85\ +\xbeV(\x80u\xcb\xd0\xec\xd3 \xc4*Oq\xb7\x81\ +a*\xc9\x95J\x11\xaa\x97\xa0\xd53\x114\x17\x88\x03\ +\x9b\xe6\xe9L\x22\xc9\x93\x86\xf9\x12\xf7\x85{g\xe5\x1c\ +X\xd7j}\xf1\xc0b\x0d\xd9\xd4w}\xd3S\xe7:\ +\x9c\xb86\xe4\xec\xb9\xbbM\xbc\xf6\xfbw\xb0\x98\xffW\ +\xc5\xc6\xa9\xa7\xa6D\xde\xeb]\xb4CC\xba!\x12\xbb\ +h\xcc\x88\x07S\x9a\x05\xfc\xfe\xfb\xd4\x1d\xc5\x1f\xce_\ +QY\x10p\xe1f\x85\xe7U\xf5\x81z\xda\x92\xbd)\ +\x12\xf5\xcd+.qSu\xd9{G\xadx\ +\x9a\xea\xb2.qj\xef\xef\xafLm\x16\xf3\xce\x02Y\ +|\xea\xc6\x90\x80\xa9\xa7\xd2\xca7\x0e>6\xf6\xc2\xdd\ +\x0d\x99\xb3\x1e\xa8\x9a\xb0\x7f\xe8\x17\xd3k\xe8\xe0P\xe1\ +\xe0\xfd\x8e\x7f&\x96F]P7\xed1\xf2\xfb\xcf>\ +*\xfatl\xc75M\x1a\x93&\x0e\x166[gF\ +l\xba\x1f\x13\x13\xbc\xe8\x9c\xa4\xe3w\xd4\x06g2z\ +_\xe7\xeeO\xaf\xff\x11\xe37\xea\xcfF\xb7\x1c\x1c\xd7\ +\xe6g\xef\x9cn\xbd\x87\xb3\xe8\xe4\xea\xd5~\xcaE\x97\ +n,\xca\xf8\xb5\xfe\xd6\xc0\x87\x87\xa2CO\x1f\xaah\ +\xa6!S\xec\xbd\xdf\x99\xf9E\xec\x86\x1f\xc6\x08f;\ +\xff\xd1bM\xad\x8d9]sc\xfa(R3=\xf9\ +\x1f\xcf\x1a:\xa9\x8b\xcb\x1f\xc7\x0e\xc9\xbaM|gV\ +\x83-\x7fY&\xfd\xfe\xee\x9d\xf1\xa2\x03\xbc\x16\xdfD\ +\xaf\xbe\x10\xb6g\xe3\xa5\x07M\xe7\xac\x1f\xc2\xdbr-\ +\xac\xf1\xaa\x8fOe\x5ck?\xf4\xdedy=\xe1\xc7\ +Nv\xa7\xd7\xaf\x8b\xbb\xd4\xb1\xdf\xe0\x07\xd7F\xba\xc4\ +\xaf\x98\xd2q{\xfe\x85\xc2oR\x9c\xec>_\x9c\xf0\ +{\xe7\xaf\xd5\x97\xce4\xfb\xb3\xf8#e\xaboE\x9d\ +~\xdc\x97#.\xbe\xd5)r\xd7\xe6\xb8\xb8\xb9\xa3\xbf\ +\xcd|\x1a\xfa\xc1\xaca\x93X.\xbf\xef\xdb\xb8\xa0\x9f\ +cW\xde\xcf\xb7#N\xec\xf7\xe5\x8f\x1fqZZc\ +\x93\xce\xd4\xd2?\x17<\xba\x87\x0eq\xbcP\xf8\xed\xe5\ +\x9c93\xb2z\x8d\x96\xef\xdb3\x8f\xbb{\xc5\xae\xbf\ +\xaf\xb8g\x9ej-X\xb2\x5cro\xd4\xecO\xc8\xea\ +o\xa8\xc1\xab\xac\xca\xfe\xcb\xdd\xb4bW\xfe%\x8f\x9f\ +\xd3\xd6N\x1f|\xe8\xa7\xe2i\xac%\xbd\x14\x0f'\x08\ +E\xe1q\xbd/M\x5c2\xbex\xcb\xc0\x95e\xa9S\ +nx\x15\xa6]*Ox\xb8\xf6\xf3i\xbf\x1c/\x9a\ +\xd8\xf4\x8f\xa26m\x8emQ\x7f=kR\xf7\xab\x81\ +?\xed\xd4\x0ak/\xb8a5\xb4\xc8\xa9A\xe2\xa4\x05\ +\xb3{\xa9\x85\x7f\x9fSS\xbe\x91\x9a_\x1f\xcb6\x94\ +\xff9\xd5e\xf3\xe0\xa7\x09\x97\x8a\xbc2.m\xb8\xb8\ +V\x92\xdb~\xaa\xdd\x8a{K4\xe4t\xd3\x1d\xbe\xa1\ +\x9d\xfe^\xa8\x9eS\x91S\x96U6eDi\xf4\xd3\ +z\x0f\x124D\xbc\xb9\xa2YYVE\xd6\x89\xc7\x1f\ +?\x88\x89\xed\xbb\xed\xba\x86\xac\x8e\xccP_\xdb\xa3\xc3\ +\xfd|\xef\xef\xed5\xa4\xe7\x94k{\xb5\x98\xf1\xf1\xf7\ +K\xa6\xde\xae\xf7G\xe4\x8e\x00\x06\xf7\xba\xbc\xa8w$\ +0\x08\xd0a\xce\xff\x95\xa1\xdf\x9b\xc1}W\xcb\xa0\xb7\ +\x16\xd1\x97\x7f\x5c\xb9\xfc\xcaM\xefVq\x09\xdf\xf4j\ +\xfa\xe5\xd8\xa5{\xa7\xf5o\xdcr\xc7\xd9k\x1f)v\ +\xfe\x1e\xcf\xf6j\xf6\x15\xb4\xe7w\xed\xac\xd7\x8c\xb6\xeb\ +\xc3\x09\xed\x9f\xc2\ +i29\x0b\x5c\xcatX\x8f\xe2Wx\x06\x0f\x19\xca\ +\xb1>\x0e.\xa5-x\xb2\xe0<\x09E\xca\x8c\xd8\xf8\ +\xee\x03hW\xab[4\x07?\xd5C\x9e\x0bE\xe7\xb4\ +\xce\xca\x19\xbf\x9e\xfd8\x1cR\xb7\xe0,\xcaP\x80+\ +B\xf5\x83x\xb0X\xa2\x04\xe7\x8d\xfa\x10\xe2\xd2\xb1\xaa\ +\x0c\xccGO\xc0-i\x14\xc6Y\xe8\x03\xb8)@@\ +\x88{a\x83\xa4\xa7\ +\xa8\x1a\x0b\x8d\x0c\xd8\xb7\xda\xd8\xa3\xfet\x9fQ\x1e\xb9\ +\xcf\xf2\xaa\xc2\x93\xaf\x04/\x0c\xd6\x84\xec9\xcf\xf2\x92\ +\x16\x13\xb2\xed#B\xbc.<\xcbk\xf1%\x8cQ\xe8\ +\xb7\xad'\xf4\xda\xe3\x81\xe3E\xef\xf3gi\x12\x91?\ +*\xb42\xd4\x8a`D\xd0\xe3\xe7\x8f\xe4*\xd5\xc3\xe9\ +\xaa\xf5s9\xa87\x11x\xb3\x99\x0a\x0e\xac\xc7E\x12\ +\x8e\x9f\xe1 ~\xe9\x8aU\xcb\xd1>N\x92,\xc1u\ +\xbf\x84\x93\x00\xa3,M\x96\x02\xdd-\x13\xa7\xd1_r\ +K\x93U\xd7\x89/Y\xcd h\xc75\x04\xd7\xd5j\ +\xe26\xc2\x9f\xd4?\xe1F\xd8\xf7s\x89\x85\xab=a\ +\x0f[\x0e%Te\xbf\xf5\xb1M x\xe5\x0djz\ +S;\xee\xe9P\xc5\xa2\x935\x1b\x0f\xca4z\xa9E\ +\xa2\xe3\x06pD\x99\x8a1\xda2zueI\xec\xc0\ +H\xb9\x11o\xd2\x844'\xad\x89\x1f\x18\x9ap\x12A\ +:\x93n\xa4\x17\xe9K\x06\x90!\xe4?D\x04\xc6(\ +\x9d(\xc8X2\x89\xbcG\xa6\x93\x99d\x0e\xf9\x9c,\ +!+\xc8j\xb2\x96l$?\x92md\x17\xd9O\x0e\ +\x91_\xc8Ir\x96\x5c$\x97\xc8ur\x97\x14\x90\x22\ +R\x06\xee\xae5\xe5H\xb9R\xdeTS\xca\x97jG\ +\x05Q<\xaa\x13\xd5\x8d\xeaC\xc5QC\xa8D*\x85\ +\x92Q\x99\xd4$\xea\x03j&\x95E-\xa1\xbe\xa2\xd6\ +R\x9b\xa8\x1d\xd4~\xea(u\x8a\xfa\x9d\xbaL\xdd\xa6\ +\x1eR\xa5,6\xcb\x81\xe5\xc6j\xccj\xc9\x0a`\xf1\ +XQ\xac\xde\xac\x01\xac\xe1\xac\x14\xd6h\xd6\x04\xd6\x87\ +\xacY\xacE\xac\x95\xac\xefX[Y\xfbY\xbf\xb0\xce\ +\xb2.\xb1\xee\xb2\x9e\xb0\x09\xdb\x9e\xed\xc1n\xc6\xf6c\ +\xf3\xd8\xd1\xec\xbe\xec\xa1\xecd\xb6\x82=\x85=\x83\xbd\ +\x80\xbd\x92\xbd\x91\xbd\x93}\x98}\x86}\x89}\x8f]\ +bae\xe1j\xc1\xb1\xf0\xb3\x88\xb0\xe8i1\xd0B\ +d1\xdab\x8a\xc5\xa7\x16K,\xbe\xb5\xd8jq\xc0\ +\xe2\x8c\xc5e\x8b\x02\x0b\xb5\xa5\xa3e#\xcbv\x96\x02\ +\xcb\x18\xcb\xc1\x96)\x96c-\xa7[.\xb0\x5cc\xb9\ +\xc5\xf2\xa0\xe5Y\xcb\xeb\x96EVVV\x1eV\xad\xac\ +\xc2\xadzZ\x0d\xb1\x1ai5\xd1\xeaS\xab/\xac\xbe\ +\xb7\xdagu\xca\xea\xaa\xd5\x13kkko\xebv\xd6\ +\x1d\xad\xfbZ\x0b\xadU\xd6\xd3\xad\x17[\x7fg\xbd\xd7\ +\xfa\xb4\xf5u\xebb\x1b{\x9b\xa66A6\xddm\x86\ +\xda\xc8l\xde\xb7Y`\xb3\xcef\x8f\xcdi\x9b\x9b6\ +e\xb6\xf5m}m\x05\xb6}m\xc5\xb6\xe3mg\xdb\ +\xae\xb6\xddi{\xc2\xf6\xbam\x99\x9d\xb3]+\xbb\x8e\ +v\x03\xecF\xda\xbdg\xb7\xc8n\xa3\xddA\xbb?\xec\ +\x1e\xd9\xdb\xdb\xfb\xd8\xf3\xed\xfb\xdb\xa7\xd9O\xb3_d\ +\xff\x83\xfd\x11\xfb\xcb\xf6%\x0e.\x0em\x1d\xa2\x1d\x86\ +9d:\xccr\xf8\xc6a\x9f\xc3\xef\x0e\x8f\x1c\x1d\x1d\ +[:vv\x1c\xea\xa8r\x9c\xe5\xb8\xd61\xc7\xf1/\ +\xc7b'W'\x7f\xa7\x18'\xb1\xd3T\xa7\xa5N[\ +\x9dN;=\xa8g[\xcf\xb7^T\xbd\xff\xd4\x9bP\ +oA\xbd\xcd\xf5N\xd4\xbbW\xdf\xb6~\xcb\xfa\xd1\xf5\ +\x85\xf5\xa7\xd4_Z\x7fG\xfd\xf3\xf5\x9f8\xbb:s\ +\x9d\xfb:\xa7;\x7f\xea\xbc\xce\xf9\xa8\xf3-\x17k\x97\ +\x96.\xdd\x5c\xc4.\x1f\xba\xacr\xc9q\xb9\xea\xcav\ +m\xee\x1a\xed*r\xfd\xc0u\xb5\xebA\xd7\xebnV\ +n\xad\xdcb\xdcF\xba\xcdt\xdb\xe0v\xdc\xad\xc0\xdd\ +\xc5=\xc4=\xc1}\x9c\xfbR\xf7\xdd\xee\x97<\xd8\x1e\ +-=b<\xa4\x1e\xb3=~\xf48\xe7Q\xea\xd9\xd8\ +3\xcaS\xe2\xf9\x89\xe7F\xcf\xd3\x9eO\xbd\x1azu\ +\xf6\x92x\xcd\xf0\xfa\xde\xeb\xacW\xa97\xc7\xbb\x9b\xf7\ +(\xef\xb9\xde\xdb\xbc\xffl`\xd1\xa0m\x83\xfe\x0d\xc6\ +6X\xde\xe0`\x83{\x0d\xdd\x1aF4\x145\x9c\xd1\ +\xf0\xc7\x86\x17\x1a\xb1\x1a\xb5m\x14\xd7hb\xa3U\x8d\ +r\x1b=i\xdc\xa4q\x8f\xc6\x19\x8d\x177\xcei|\ +\xaf\x89G\x93\xceMF6\x99\xdfdO\x93\xdbM]\ +\x9bvj\x9a\xd6t~\xd3\xbdM\xefp\xdc9Q\x1c\ +)g\x11\xe7\x00\xa7\xa0Y\xa3f=\x9be6\xfb\xaa\ +\xd9\xf1fe>\xad|\x06\xfa\xbc\xef\xf3\xbd\xcf\x9f\xcd\ +\xed\x9a\xf3\x9a'7\x9f\xdf<\xbbyA\x8b\xa6-b\ +[Lj\xb1\xbe\xc5\x05_[_\x9eo\xaa\xefB\xdf\ +\xc3\xbeO[\xb6j9\xa8\xe5\xc7-\xb7\xb5\xbc\xd5\xca\ +\xabUL\xab\x09\xad\xd6\xb7\xfa\xa3\xb5c\xeb\xc8\xd6\xa3\ +[\xafl\xfdk\x1b\xab6\xbc6\xa3\xda|\xd1\xe6d\ +[V\xdb\xd0\xb6\xa9m\x97\xb6=\xd1\x8e\xd5.\xac]\ +Z\xbb/\xda\x9djo\xd9\x9e\xdf^\xd6~e\xfb\xf3\ +~\x0e~Q~c\xfc\xd6\xfb]\xf6\xf7\xf0\xef\xe3\xff\ +\xbe\xff6\xff\x07\x01-\x02\x86\x06\xcc\x0d8\x1c\xa0\x0e\ +\x0c\x0d\x94\x06\xae\x0e\xbc\xc8u\xe1\xf6\xe2\xbe\xcf\xdd\xc9\ +}\x18\xd46H\x14\xb44\xe8\xd7`\xc7\xe0\xee\xc1S\ +\x83\xb7\x07\x17\x86\xb4\x0b\x91\x84,\x0f\xf9-\xd454\ +6\xf4\xe3\xd0\xec\xd0\x8a\xb0\xf00E\xd8\xc6\xb0\xdb\xe1\ +-\xc2\x13\xc3\x97\x85\x9f\xe7\xb9\xf1\xfa\xf1>\xe5\x1d\xe1\ +[\xf2\xbb\xf0\xa7\xf2w\xf1K\x04a\x02\x95\xe0GA\ +~\x84_\xc4\xa8\x88u\x11\xb7:\xb4\xea \xe9\xb0\xba\ +\xc3\xd5\x8e>\x1d\x85\x1d\xbf\xeax\xa9\x13\xa7Sb\xa7\ +/;]\x8al\x16)\x8c\x5c\x19y\xa5s\xf3\xce\xe2\ +\xcek:\xdf\x8cj\x1352\xea\xbb\xa8\x07]\x02\xbb\ +(\xbal\xe9\xf24Z\x10=9z_Wv\xd7\x1e\ +]gt=\xde\xcd\xa5\xdb\xc0nK\xba\xfd\xd5\xdd\xa7\ +{J\xf7\xf5\xdd\x0bz\x84\xf6\x98\xd8c_O\xcb\x9e\ +\xbd{\xce\xedy>\xa6q\x8c(fmLA\xaf\xf0\ +^\x93{\x1d\xe8\xed\xd0;\xbe\xf7\x92\xdeW\xfa\xb4\xed\ +\xa3\xe8\xb33\x96\x15\xdb+v^\xec\x1f\xef\xf8\xbe#\ +{g[_\xd27\xa6\xef\xbc\xbe\x7f\xf6k\xd5ot\ +\xbf\x9f\xfb[\xf5\xef\xd7\x7fi\xff\x1bq\xdc\xb8Iq\ +\x87\xe3]\xe3G\xc4\xaf\x8b/\x1a\xd0e\xc0\xec\x01\x17\ +\x07\xb6\x1e\x9890;\xa1^\xc2\xb0\x84\xb5\x09O\x07\ +u\x1d\x945\xe8\xd2\xe0\x80\xc1\x93\x07\xff2\xa4\xc1\x90\ +\xb4!\xdb\x87Z\x0fM\x18\xbaf\xe8\x93w\xbb\xbd\xfb\ +\xf9\xbb\xd7\x87\x85\x0e\x9b>\xec\xdc\xf0V\xc3\xc7\x0d?\ +\xfa\x9f\x06\xff\x91\xfeg\xf7\x88z#\x84#6'Z\ +&\x0eJ\x5c\x97X.\xec+\x5c)|\x92\x14\x93\xb4\ +,\xa9@\x14-Z(\xba+\xee,\x9e/\xbe-\xe9\ +(\xc9\x92\xdcL\xee\x98\x9c\x95|+\xa5c\xca\xbc\x94\ +\xdb\xa9\x91\xa9\x0bR\xef\xa5E\xa7-I+\x1c\xd9s\ +\xe4\x8a\x91OG\xf5\x1d\xf5\xcd(\x8dt\x90\xf4\xfbt\ +\x9b\xf4\xc4\xf4\x1d2\x17\xd9(\xd9\x01y\x13\xf98\xf9\ +\xa9\x8cv\x19\xd33.\x8d\x16\x8c\xfe|t\x81\xa2\xb7\ +b\x8d\x92R\x0eWnW\xb9\x813\x95\x9b\xd9:\xf3\ +\xa3\xcc\xcbc:\x8dY:\xa6xl\xc2\xd8\xcd\xe3\x9c\ +\xc7\xc9\xc6\xe5\x8eo;\xfe\x93\xf17't\x9f\xf0\xf5\ +D\x8b\x89\xa2\x89\xd9\x93\x9aMzo\xd2\xe5\xc9Q\x93\ +\xbf\x9aBMI\x9a\x92=\xb5\xf9\xd4\x0f\xa7^\x9f\xd6\ +c\xda\xb7\xef\xd9\xbd7\xea\xbd\xbc\xf7\x03\xdf\xcfz\xff\ +\xf1\x07\x83>\xd8\xf9a\xe3\x0f\xa7}x\xf5\xa3\x1e\x1f\ +\xad\x9f\xee4]1\xfd\xfc\xc7\x11\x1f\xaf\xf8\xaf\xc5\x7f\ +\xd3\xfe{\xfc\x93\xe0O\x16\x7f\xa2\x9e!\x9eqlf\ +\xe0\xcc\x053\xcb?\x15}z\xec3\xeeg\x8b>\xd3\ +\xccJ\x9eu|v\xd8\xec\xe5s\xac\xe6\xc8\xe6\x9c\x9b\ +\x1b9\xf7\xdb,\xe7\xac\x09YW\xe7\xc5\xce\xdb:\x9f\ +3\x7f\xc6\xfc\xc7\x9f\x8f\xf8\xfc\xe8\x82\x90\x05+\x16\xda\ +-\xcc\x5cxiQ\x9fE\xdb\x17\xb7XY\xf6\xf4\ +\x0b\xf1\x17\xa7\x97w^\xbeqE\xe3\x153W\x94~\ +\x99\xf6\xe5o_\xf5\xf8j\xeb\xca\x96+\x17\xac\xb2Z\ +5f\xd5\x8d\xd5\x09\xab\x0f\x7f\xcd\xfbz\xed\x9a\x06k\ +f\xae\xa9\xf8F\xf6\xcd\xa5o\xe3\xbe=\xb06|\xed\ +\xdau\x8d\xd6\xcd^\xcfZ\x9f\xb9\xfe\xf6w\xc3\xbe;\ +\xb9\xa1\xeb\x86\xed\x1b\xfd6~\xf5\xbd\xc7\xf73\x7f \ +?d\xfepgS\xe2\xa6s?\xf6\xfe1{3o\ +\xf3\xc6\x9f|\x7fZ\xb6\xc5u\xcb\x8c\xad\xd4\xd6\xf1[\ +\x0b\xb6\xa5n\xbb\xb4}\xc8\xf6S;z\xed\xc8\xde\x19\ +\xb1s\xcb\xcf\xfe?\x7f\xb3\xab\xd9\xae\xa5\xbb\xddw\xcf\ +\xdec\xb7\xe7\xc3=\x9a\xbd\x13\xf6>\xd9\x97\xb1\xef\xde\ +\xfe\x94\xfdW\xb3Gd_\xcc\x19\x9c\xf3\xeb\x81\xfe\x07\ +\x8e\x1f\xec}\xf0\xc8\xa1\xee\x87r\x0eG\x1d\xde{\xa4\ +\xe3\x91]G\x05Gw\x1c\xe3\x1d\xdb\xf6K\xd8/[\ +sCs\xb7\xe4\x85\xe6m9\x1ev|\xeb\x89\xf0\x13\ +\xdbO\xf2O\xee<\xd5\xe1\xd4\x9e\xd3\x91\xa7\xf7\x9f\xe9\ +z\xe6\xd0\xaf1\xbf\xfer\xf6\x9d\xb3\xa7\xce\x0d<\xf7\ +\xdb\xf9a\xe7/\xfd&\xfe\xed\xd6\xef\xd2\xdf\x0b/\x8c\ +\xb9Pvq\xda\x1f\x96\x7f\xcc\xf8\xb3\xfe\x9f\x0b\xfej\ +\xf4\xd7\xca\xbf\xdb\xfc\xfd\xfd\xa5\xb0K\xbb/w\xbd\x9c\ +{%\xfe\xca\xc5\xab\xa2\xabw\xaf)\xaf\x95_\xff\xf0\ +\x86\xe3\x8d\x057\x9b\xde\x5c{+\xe8\xd6\xae\xdb\xddo\ +\x9f\xbc\xf3\xee\x9d\xebw3\xee\x96\xdd\x9b~\xdf\xf9\xfe\ +\xb2\x07\xad\x1f\xfc\x94\xdf9?\xb7`p\xc1\xf5BE\ +\xa1\xe6\xe1\xa7\x8f\xbc\x1f}\xf38\xe4q\xf6\x93~O\ +\xfe*J/*{:\xa3\xd8\xbb\xf8\xdb\x12^\xc9\xe1\ +\xd2A\xa57\xcb\xc6\x96[\x97/\xaahS\xb1S\xdd\ +[\xfd\x87&\xbd\xf2\xfe\x849\x98\x839\x98\xc3?*\ +XXXX:9997h\xd0\xa0Y\x8b\x16-\ +\xfcZ\xb5j\xc5m\xd9\xb2e\x80\x1e\x04\x1a\x82\x01\x0e\ +\x9d\xd6\xe5\xe9\x97c<@\x0f\xf7\x85\xb2*\xea\x06\x18\ +\xe00\x10\xd0\xbau\xeb C>\x06\xf2\x050\xfc\xf4\ +\xf1\xaaJ\xd7\xc4\xcb\x10\xdf\xa0\xbdt=\xd4S\xd3\xa6\ +M[\xb9\xba\xbaz\xc1:\xc4F\xefN\x83\xd1\x01\xeb\ +\xd4\xaf_\xdf\xad{\xf7\xee\x83?\xf9\xe4\x93\xf5\xdf\x7f\ +\xff\xfd\xc5\xdd\xbbw\xdf\xdb\xb7o_\x01\xc2\xfe\xfd\xfb\ +\x0b\xf5\xc10/;;\xfbaU8\x0c^U4\xaa\ +\x02}<\xc3:\x0c=}\x9aU\xe1W\xc7\xab\xba\xba\ +\x8c\xecU\xd5\xc72\xc3|C:{\xf6\xecy\xb0u\ +\xeb\xd6kK\x97.\xcd\x16\x89D\x93|}}\xfd-\ +--\xadj\xd7\xfa\xb3\xe0\xe2\xe2\xe21j\xd4\xa8\xe9\ +@\xeb\xfe\xb1c\xc7*rss5f\xa8;\x1c>\ +|\xb8d\xf1\xe2\xc5{CBB\xa2\x8c\xed\x03\xbcf\ +\x12\x12\x12\xa4999\x8f\xdf\xb6\xfc\xff\x06\xf8\xe5\x97\ +_\xd4\x0b\x17.\xdc\xed\xe3\xe3\xd3\xd6\x18[\xd4\xb8q\ +\xe3\x16k\xd6\xac9\xf9\xb6\xe5\xfe7\xc1\xa1C\x87\x8a\ +\x13\x13\x13\xc7\xc1\xd8\xb6\xaeI\xf7,\x08\x91\x91\x91}\ +\x0f\x1e\xae\x0dj\xd2\xbf\xb5\xb5\ +\xb5\xadJ\xa5\x9ak\x0a\xfd\xff\x93\xfb\x10ec\xe0M\ +\xc9\x8d\xfao\xde\xbcy\xfb\xda\xc6\xbf1\xfa\xc7r\xf0\ +\x91N\xe0\x1ac\xd9\xb2e9x\xfe\xe2\x8b/\x0e`\ +\x9c93q\x04\x98{\xf63y\xfau\xf4\xe3\xfa\xf8\ +L\x19\x93\xaf\x0f\xfayU\xc5\x99z\xfa<\xf5i\x1b\ +\xd23\x04C\xf9\xf5e3\x94\x03a\xc5\x8a\x15\x87q\ +\xedU\x9b\xfeqmf\xcc\xf8W*\x95sj\xd3\xff\ +\x91#GJ;t\xe8\xd0\x1b\xd7\xd8\xb0V\xf3\xc4\xb3\ +!0\xf9\xb8\x96sss\xf3f\xd2\x18G`\xe2\xfa\ +\xb8\xfae\x98\x87\xc0\xd4\xd5\x8fW\xc5O\xaf\x8e\x87>\ +_\xc3:\x0c}&\xce\xd0\xd5/c\xea\x19\xcaj\x18\ +\xc7\xba8\xa6\xb1\x0f\x8c\xd1\x7fm\xe3\x9f\xd1\x7fm\xb4\ +p]\xe7\xe7\xe7\xc7\xab\x89\xd6\xffJpvvvG\ +\xdf\xd2\x18\xfb\x83{\x115\xd12\xd6\xfe\xa3\xfe\xdb\xb7\ +o\x1f\xfe\xa6\xda\xf8O\x0e\xe8\xd3\xa3\x1d\xaaMg\xa6\ +\xb4?\xb8\x9e3\x8f\x7fm0V\xff8\xfeq\x7f\xb4\ +&Z8\xff\x1ak\x7f\xfc\xfd\xfd\xf9L\xbd~\xfd\xfa\ +\x89'L\x98\xb0\xa8\xae\xfb|\xff\x86\x80\xfa\xc7\xb9\xde\ +\x18\xfb_\x9b\xfe\x8d\x1d\xff\xfa\xf6\x07\xfb\x01\xd3\x98\xbf\ +|\xf9\xf2\x838/\xbd\x99\x96\xff3\x82\x93\x93\x93\x8b\ +\xb1\xf6\xdfT\xfe?3\xff6l\xd8\xd0\x07\xe9\xea\x97\ +m\xdb\xb6\xed\xba\xfe\xb5\xf1o\x0f\x8c\xfd\xa9M\xff\xe8\ +\xa3\x9a\xd2\xff\xe4r\xb9\x1d\x7f\xfe\xf9\xe7;\xd5\xcd\x0f\ +qqq\xc9oJ\x07o3\xe8\xfc\x9fZ\xed\x8f\xb1\ +\xe3?333\xcb\x18\xfb\xbfz\xf5\xea\xbc\xda\xf0`\ +NX\x5c\xdb\x9e\xab1\x01\xef\xf1)\x14\x8aY\xe8g\ +\xef\xde\xbd\xfb.\xf6\xaf\xfe\x1e!\xc61\x0f\xef\xd1!\ +\x0e\xee\xa1`\x9dW\xe5kL@\xfd\x1b3\xfe\x8dY\ +\xff\x1ak\x7f\xa0\xbd\xe5\xb5\xf1c\x00\xe7\x04ww\xf7\ +\x06umW\x9b6m\x82\xb3\xb2\xb2\xb6\xe6\xe4\xe4<\ +2\x96\x97!\xe0=\xa4y\xf3\xe6m\x07[\xf9\xda|\ +ec\xedO]\xe6\xdf\xdah\xd5u\x7fZ7'\x08\ +\x8ci\x0f\xfaR\xb8W\xfb\xb2:\xaf\x0e\xb6n\xddz\ +5>>>\xa5v\x09\xea\x16\xea2\xfe\x8d\x9d\x7fk\ +\xa3\x85\xd7\xba\x5c.\x9f\x89\xf3\x80\xb1\xed\xafmNh\ +\xd7\xae](\xea\xc8\xd4z\xaf\xa2\x1f\xae\x99r\xed\xc2\ +\xf8\x9f\xa6\xf4\xff\x8d\xf5\x7fp\x0e\xde\xb9s\xe7\xad\xba\ +\xb4\xdfpN\xb0\xb3\xb3s@\x1b\xf1\xba\xf5n\x08\x9f\ +\x7f\xfe\xf9N\x07\x07\x07\xa7\x9a\xf4aL0v\xfc\x1b\ +\xbb\xfe\xad\xeb\xfe\x83\x87\x87G\xa3\xaf\xbe\xfa\xeah]\ +\xda\xce\xcc\x09B\xa1p<\xb3vx\x1b\x80\xd7\xafX\ +,\x9e\xf4*\xfa\xc7\xf1\x8f\xfb\xa1\xc6\xe8\xdf\x18\xfbo\ +\x8c\xfeQn\xfd\xfd\x1f\xbcn\xa6L\x99\xb2\xbc\x8em\ +\x7fkz7\x04\xf4\x99, \xbc\x8c\xfe\x8d\xf5?\x8d\ +\xf5\xff\xd1\xff|\xd9\xfd\x9f\x84\x84\x84Qu\x99\x13\xfe\ +I\xb0k\xd7\xae\xbb\xde\xde\xdeM_F\xff\xc6\xda\x1f\ +c\xf6?_u\xff\xf9e\xe6\x84\x7f\x0a\xe0\xd8\xe9\xdc\ +\xb9s\xdf\xb7\xad\x7fc\xec\x7fM{\x0c/3'\xfc\ +S\x00\xdb\x9e\x98\x988\xb6.\xfaG\xfbo\x8c\xffS\ +\x9b\xfda\xee?\x1a3\xfek\xdb\xff\xd7\xcd\x09_ \ +~^^\xde[\xd7k]\xc1\xd8>\xa8\xcb\xfe\xbf\xa9\ +\xe6\xdf\xba\xdc\xff\x9a5k\xd6&S\xe9\x04\xd7\xdd\xf8\ +l\x1e\xfa,\x9d:u\x8a\x05\x1f\x0a\xef\x07z\xf2\xf9\ +\xfc\xeeuY\x93\x1b\x0b\xe8\x9f\x19\xa3\x7fc\xf7\x9fM\ +y\xff\xcb\x18\xfd'%%M0\x85\x1e\x8e\x1e=Z\ +\x96\x91\x911\xb3&\x1f\xe5u\xcd\xfb\xd8\x86\x7f\xa2\xfe\ +k\xdbc\xee\xd3\xa7\xcf\x08S\xb4\xff\x9bo\xbe9U\ +\xaf^=\x97\x9a{\xfa\xf5\xe9\x1f\xa1w\xef\xde\xc3k\ +\xd2\xbf\xb1\xfb\xcf\xc6\xe8\xdf\x18\xff\xb36\xfd\xe3\xb5a\ +\xaag\x18\xb7o\xdf~\xc3\x98\xbd\xa3\xd7\xa9\x7flK\ +u{x\xc6\xfa\xff\xc6\xd8\x7f\x9c3\xc7\x8c\x193\xef\ +U\xec\x0f\xf8>\x0da}\xf0\xd4\x94\xedG~qq\ +q5\xee\x9d\xbd\xeeu\x07\xb6\x09\xe7\x9b\xea\xf4o\x8c\ +\xff\xf3\xba\xed?>?\x0d\xbe\xff\xedWmku\xfe\ +\xd2\xc4\x89\x13\x97Tw?\xe1M\xac\xfbv\xec\xd8q\ +\x13\xdb\xa8\xcf\xd7X\xfbo\xac\xff\x89\xf7.\x8c\x19\x8f\ +U\xd9\x9f\x85\x0b\x17\xeez\xdd:X\xbe|\xf9!\xbc\ +\xc6\xde\x86\xfe\x11\xf0\x9e\x84>_\x1c\xff\xf8\x8eKm\ +c\x16\xdfK2\x95\xfd\xc7\xfd\x07C\xfd\x0f\x1c8p\ +\xe4\x9bh?\x02\xce\x09\x01\x01\x01\x11oC\xff\x08\xef\ +\xbc\xf3N\x92\xfe\xf87v\xff\xdfX\xfbS\x1b-C\ +\xfb\x83\xe3\x11}\xc47\xd5~F\x86\xf8\xf8\xf8\xca/\ +\xfe\xbcI\xfd#/\xe6]\x8a\xba\xf8\x9f\xa6\xba\xffn\ +\xa8\xffU\xabV\xe5\x9a\xa2]\xeb\xd6\xad;\x8b6\xb6\ +.u&M\x9a\xb4\x14\xe7\x847\xbd\xef\x07c~\x7f\ +]\xf4o\xec\xfd\xdf\xba>\xff\x83{\x86\xa6zf{\ +\xe8\xd0\xa1\x19x-}\xf9\xe5\x97G\xeaR\x0f\xf7\x8f\ +\xdf\xb4\xfe\xb1\xcd\xb8\xf66v\xff\xcdX\xff\xbf\xae\xf6\ +\x07\xe6\xa3-\xa6j\x93\x8d\x8d\x8d\x1d\xd2\xc4\xf1ZSW\xfdcx\x999\xe1\ +e\x01t4\x87\xe1\xab\xb3?o\xe5\xfd#\xc3\xfa?\ +\xfc\xf0\xc3\xc5Wm\x1b\xfat\xf8\xee\xf4\xcb\xf4\x01\xce\ +\x09x\x7f\xe0u\xea~\xc3\x86\x0d\xe7\xf5y\xe2\xfa\xd7\ +\x18\xfd\xbf\xae\xf5\xaf\x81,.\xa6\xf8v\xd0\xe6\xcd\x9b\ +\xff~\x19\xfdc\xc09\x01\xef\x93\xbd\x0e\xddC\xdb\x9e\ +\x18>3m\xec\xfck\xca\xfd7\x9c\xc3\xaa\xbb\xff\x8b\ +\xf7\xa9M\xf1,\xce\xf4\xe9\xd3\xbf}\xd9>\xc0\x80\xf7\ +\x8bM9'`\x9b\x18\x9b\xaf\x1f\xde\xf6\xfa\xab\xaa\xd0\ +\xbd{\xf7A\xa6\x98\x8f\xf1\xd9\xadW\xe9\x03|n\xc2\ +\x14\xcf\x02`[\xbav\xed:\xb0*\x1eu\xd9\x7f3\ +\xa5\xfek{\xfe\xc7T~\xf6\xbau\xeb\xceT\xf5\xdc\ +Am\x01\xe7\x02\xbc\x9fc\x0a\x19jzG\xc0\xd8\xf5\ +W]\xf6\x9fk\x93\xc7\xd8\xe7\xdf\xc6\x8f\x1f\xbf\xd0D\ +\xd7~\x05\xfa\xf9\xcc\xfd\x81\x9a\x02\xfa\xaf\xb8\xd65\xd5\ +\xf3G\xd8\x86\x9a\xf8\xbd\x8d\xf7_p\xff\xad]\xbbv\ +a\xb5\xe9\x02\x03\xee\xc7\x9bB\x0f\x08(\x17\xae{\xf0\ +\x19\x0d|O\x0f\xdf\x19C\xc08\xe6\xa1\xffe\xca\xfb\ +0@\xab\x02\x9f+\xa8\xa9}\xc6\xbe\xffej\xfbS\ +\x97w\xd8F\x8f\x1e\xfd\xa9\xa9t\xf26\x00\x9f\xe3\xae\ +\xee~B]\xde?5\xe5\xf3'\xc6\x8e\x7f&H\xa5\ +\xd2\x8f\xdf\xb6\x1e_\x05\xf0}\x86\xaa\xee'\x98\xfa\xfb\ +\x1b/\xb3\xff`l\xe8\xd5\xab\xd7\xb07\xfd\x9c\x8a)\ +\x01\xef7\x06\x06\x06v\xd0o\x93\xb1\xcf\x1f\x9ar\xfd\ +\xf5*\xdf\xffi\xd2\xa4IK\xf0\x85Mr\xff\xefm\ +\x00\xae}\xf4\xe7\x84\xba<\xff`\xaa\xf7\xafkZ\x7f\ +\x19\x13\xf0;A\xb8\xd7\xf9\xb6u\xc9\xc0\x86\x0d\x1b~\ +\xdb\xbe}\xfb\xf5\xba\xd4a\xe6\x04S\xde\x7f\xaf\xcb\xf7\ +\x97L\xf1\x0e9\xae\x11\xde\xe6\xfb\x92\xc8;99y\ +\x1a\xca\x82\xef#\xe3{\xc9u\xa9\x8fs\x02\xea\xd4\xd4\ +\xf7\xdf\xdf\x94\xfe1\xfc\x93\xde\x7f\xc7\xf1\x8c\xef\xe7\xd7\ +\x85\x0e>\x7f\x83\xef\x88\x98j\xfc\xbf\xad\xef\xef\xe1\xde\ +\xca\xe6\xcd\x9b/\xbdn\xbd\xe3\xb7=p\xcdP\x93,\ +\xf8\x9d\x0a\x9c\xe3\x8c\xa5Y\xdd\xb7\x5c\xf5\xc1\x94\xfb?\ +U=\xffl\xaa\x80>\x12\xac\xa3\xfe0\xb5\xde7m\ +\xda\xf4gM\xef\x11\x19\x06\xdc;\xc2\xef\xb6\x98\x8a\xbf\ +\xb1\xfa7\xd6\xfe\xd7\xd5\xff\xafk\xe0p8\xad\xf1\x7f\ +\x9f\xbc\x8a\xaf\x84\xcfY\xcd\x981c\x03\xfe\xef\x83\x97\ +\x91\xe1e\xe6\x84\xea\x00\xfd\x1fS~\x7f\xf5M~\xff\ +\xb3a\xc3\x86\xcdp\xaeF\x9b\x8d\xdf\xa8\xc1o2\xa1\ +\x0c\xb8\xc7\x83\x80\xf1\xec\xec\xecGX\x8680\xa7N\ +\xc5:\xa6\xe0\x8d\xbe\x1a~\xdb\xd1\x14\xe3\xdf\x94\xdf?\ +\xfc_\xfb\xfeg\xff\xfe\xfd%\xd5\xcd\x09\xf8\xecXm\ +\xfa\x7f\x9b\xfb?\xff\x96\x80s\x9e\xe1\x9c\x80\xef\xbb\x19\ +\xf3\xad\x857\xf1\xfe\xdd\xffB\xc0\xef\x9b2s\x02\xea\ +A \x10\xc4\x98\xf2\xfd\x17S}\xff\xe1\xdf\x1c\x989\ +\x01\xf7\xbdM\xfd\xfc\x95)\xbe\x7f\xf2\xbf\x14\xea\xb2\xff\ +f\xaa\xef\x9f\xbc\xea\xfe\xcf\xbf)\xd4\xe5\xfd\xf7\xd7\xf5\ +\xfc\xe1\xffrx[\xef?\x9a\xf5\xaf\x0duy\xff\xcb\ +T\xfe'\xda\x1f\x9c{\xf0\x99?\x5c\xa7\xeb\x01\x9f\x01\ +\xb4OxF\x1c\x1d\x1e\x9f\xc1\xc32\xfd<\xecK\xbd\ +\xfa\x02\xbd2\xbe\x1e\x0f\x86\xa6>?\x9a\x16\x02\xd2\xd0\ +\xaf\xa7\x0f\xfa4\x18y\xf4h\xf1u\xfc\xf9\xfeU\xb7\ +E\xc0\xb4\xa5*\xf9#\x22\x22z\xe1\xff\xc2y\x93\xfe\ +\x0f\xd3\x07x\x1d\xe8\x03\xaeO\x0c\xe3x\xd6\x8f\x1b\xd6\ +\xd1\xa7SU\x9d\xaah\xd7\xc4\xab&\x9eU\xd15\x86\ +6\xcah\xd8^}Z\xc6\xdc\xf37\xe5\xfd/3\xd4\ +\x1dL\xb9\xffl\x86\xba\x03\xee\x05\x1ac\x7fF\x8f\x1e\ +\xfd\xd9\xdb\x96\xf5\xdf\x08\xb8Oa\xc4\xff\x1f\xb4NJ\ +J\x9ah\x1e\xff\xa6\x07|\x16\xb2\xb6\xef\xbb\xb2\xd9l\ +\x0b|\xce\xd4\xfc\xffgM\x0b\xb8G\xfe\xfe\xfb\xef\xaf\ +rpp\xa8W\x93\xfe\xf1\xff3\xe3\xff\x8e\xff\xff\xfa\ +\xed\xd4\x7f*\xe0\xfb\xfbQQQ\xfdY,\x16\xbb&\ +\xfd3s@\xaf^\xbd\x86\x9b\xe2;bf\xd0\xfa=\ +\xf8\x8c\x05>\xa7R\x9b\xee\x99\x80\xffS)666\ +\x11\xbf\xeb\x83\xcf\xcf\xeb\xff\xbfP\xc3\xff\x1djL>\ +\x93\xae.\xbf&\x9c\xea\xca\xf4\xf3\x0c\xf3\x0d\xa1\xaa\xb2\ +\x9ahT\xc5\xdfXY\x11\xd0\xde\x1c8p\xe0\xc9\xd7\ +_\x7f}\xeb\xac_\xce\xc4\ +qO\x83I\xe3\xd90\x8d\x80u\xf5\xe2\xf3\xf5\xeb\xeb\ +\x83a=\xa4e(\x0f\x93\xc7\xc8d\x98\xa7_G_\ +\x16}Y\xf5A\x9f\x86a9\x961\xf9X_&\x93\ +\xcd\xc0\xef\xe6\xe2<\x8a\xfe\x0e>_\x83\xfa\xac\x8b\xfe\ +\xf5\xfb\x01\xff'9\xf6\x05\xd2\xb1\xb5\xb5\xb5\xc7xU\ +\x80v\xab\xba2c\x00\xeb\xbf*\x8d\x97\x95\xc5T|\ +\x19\xc0u\x14\xfa2/\xabws0\x07s0\x877\ +\x14\xd8_R\x04\xfdR\x0a~\xe4K\x16\xb1\xa0\xe3\x84\ +$~\xc9~\x16\xd7\xa2F\x89\xe5I\x12N\xbfT\xb9\ +J\xaeL\x95gp\xba\xcaE\x99\xe9\x12\x99\x8a\xd3U\ +\xa8\x12r\xbaH\xe5\xa2Q\x84\xd7%&6v\x80B\ +\x86\xf8\x18\xef#\x1c\xaf \xa4A\x02M\x87\xad\x03|\ +\x0em\x18\xb1\xd0h\x08q\xa0\xdfi\xb0\x88\xc2r8\ +\xb2\xf0\x88\xf5drE\xba\x86\xd8\xa0\x00\xcc\x13\xf7\xad\ +\x09\xc1\x1a\xb5\x83u|\xaa0C\xc2\xe1\x22\x1di\xa6\ +\x0c\xbf>\x83_\x8b\xb4&\xf1$\x95\x08I\x06\x91\x10\ +\x0e\xe1j\xe5\x93\xca\x94\x0a\x14@\x09U\xe8\xf4\xf84\ +1\xa6\x01\xbc1-\x92&I1M\xe9\xda\x93&K\ +\x1e\xa7+\xa7\xd3\xa3d\xa3\xe4\xfai\xa92#\xf9\xb9\ +\xb4H\x8a\xf4m\x18uc\x9e25\x1dy\xf4\xc4\xc6\ +\xd1<2\x95*]q\x08@}\x9d\xd6\xa1V\xbaD\ +%\x14\x83ru9\xb6R\xe1x\x89b@Z\xbaD\ +,\xcfL\x8a:\xc7+\xc9\x90\xf4\xb8B\xd3L\x1e\xa7\ +\xc8\xd0\xd5}>P\xd0\xea\xbe\xa4\x1eq v\xc4V\ +\xf7s'1\xa47q\x01\xad\xb8\x11O\xe2M\x1a\x00\ +\xb4&\xcdA+\xcd\xe1\xe7\x03\xe7\xc6\xa4\x11i\x02\xd0\ +\x92\xf8\x92\x16pl\x05\xd0\x02\xca\x9a\xd1\x18\x1c\xc0n\ +\x039\xdac\x0b\xc0\xc1Z\xbe4vK\xfa\xd7\x16\xea\ +6\xd2QiF\xff\x1aC\xac9p\xf3\x02p\x07\xbe\ +.\xc4\x15~\xb1\xa4\x0f-\x91\x0d\x80\x1d\xfc\x1c =\ +\x88p*\x88\x85\xa5s3?\xae:\xa0<\xd0\x8b\x1b\ +\x10\x10\xc8\xe5\x06\x06r\x03\x03\xb8\x01\xf4\x09\x93pP\ +\x07\xda\x05\x04a\x09\xe4\x06\x04\xa8\xb9$P\xcd\xb5\x0c\ +\xd4\x15\xa9\xb9\x9a@\x1b\xc0\x0f\xf0k\xe5eC\xa9\x89\ +\x86XSn\x83\xd7_\xbcWPPQH\x0a\xd4\x85\ +\xe4aE\xa1\xa6\x80*,(.d\x17\x14\x16B\x8e\ +\xba\xc0\xba\xb0\x00\xa3\x85\x05\xe5P\xd4\x10\x13\x0f1U\ +X\xf8\x10\x8f\x90,xp-{\x92\xbf\x15\x8c2\xc2\ +\xf6\x98~\xbfb\xb3\xc6\xa2do\x94\x15\x8cj\x1b\xe9\ +\xe3\x1f4l\xf5\xee\xb6\x14\x8b\xb48\xb9Q\xc3*\x1e\ +g\xcdb\xf5-\xda\xa0\xa1\xf6\xb9\xb1,\x15\x15\x10\xb9\ +\xdc\x9ce3]\x0d\x91\xfb\xedX6\xb31\x92\xef\xc7\ +\xb2\x9d\xab.\xd4\x10\xf5E\x8dZ]\x01\xe7{\x90\xd9\ +\x9ee3W]\xaa\xf1T\x9f\xc8\xce\xc9>\x90s \ +'\xe7\xc0\x81\xfd99\x90\x80?\x88\xab\xb3+r\xec\ +\xb21\x83\xce\xdb\xaf\xce\xd1\x1c(\xc9\xb1B<(\x86\ +T6u\xb8\xb0DC\x15\x00\xf59@\x88]\xda\xdb\ +\xcb\xb3\xdc\xcb\xc3\xd3\xcb\xc3\xdb\xd3\xcb\xdb\xdb\xcb\xdb\x8b\ +>yzz\xe3_\x99\x97\xb3\xa7\x07\x14A\x19\x94x\ +y{\x22B\x85\xb7\x0d\x8d\xe9\xed\xd9\xfe0\x92jO\ +\xd9\xce\x81s\x09o\x1f\xa1\xdc\xf7A,\xdf\x1fE/\ +\x85\xac\xf0}\x84\xe5\x96\x8dQ\x86!U\xcc\xab\xcc\xcb\ +\x0f\xa0l\xa0\xa6U\x09\x9f\x10\xf1\x22\xab\x83\x84r\xdb\ +\x8f\x04\x03\xb4\xa8\xd6%\xe1\x84_\xa29\xe8}\x88P\ +.4]?-]v\x09\xcf'_\xad\xa1\xae\xf3\x0f\ +C\x95l()\xd4Qg\x95v\xbcS\x0e<\x92\x8f\ +\x80(\xfb\xe9*\x94m\x16\x0a\x97\x07\x87\xc5\xd6\x85\xc4\ +\x91;\xeb\xf0\xdd\xe2\x0a\x8d\xa6\xa2\xf8\xde\xe1\xd9\xdc[\ +\x80\x87\x04@\xb14iR\xfeTC\x1dl\xf0\x84\xb0\ +\x82\xb7>z\xa4a=\xde\x1e~W\xc7\xa3 \x80n\ +'\xa9(\x02\xce\x82bB\x89/\xdf\xd7PWS\xee\ +3$\x80\xd5\xdc\x12\xe8\xdd\x99\xa5OQ\x842B\x85\ +^\xbd\xad\xa1\xae\xf1\xf2\xa1\xc1\xfb\xb5\x0df\xd9\xcc\xd1\ +6\xa0\xe3\xad\x22\x8d\xe5bk0s\xdb\xafk\xa8\x9d\ +N\x85:*\x05\xba6Z@\xe3\x1b\x1d-\xd2\xb0\x0f\ +6\x18_rUC\x95Nz\x08r\xe4\xe8\xd4\x83\x18\ +\x96\xa5\xe1`\x07\x96\x17iH\xc9\xdf\x1a\xea\xb0\xc5c\ +]\x93Q\x17YZMW\x10jT\xe9\xaf\x1a\xean\ +\xd3'\x0cy\x7f\xa6\xb3\xca\x09\xd5\xf1\x16\x94\x95\xf6-\ +\xaa,\xd3uQ\x09\x1fdot\x14\x0a\xd5c\x9f\x12\ +\x96{\x0e-\xbb\x1fe3\x17k\x86\x97\x12\xca\xe6\x8b\ +3\x1a2\xb6\xb8\xb2s\x03\x98\x0e\xe7\x15\x13\xb2)_\ +c]~rR\xac\xb7g\xf7\xf2\xfb\x1a2\xbe\x84\xe9\ +\xd7\xcaa\xc1+!dB\x81\x86U6\xd3\xa2\x8c\x90\ +\xd2{\x1a2\xa1\xf4\x05$~)!#\x0a4\xd4)\ +\x17\xc0.\xbd\xab!\xc3\xcb\x98\xde\xf6\xd7\xb5\x90\x16\x94\ +W\x01H7\x04Z$\xaa\x22\xbc\x5c\xa7\x07\x10\xcaf\ +\x9e\x96\x1dd5|\xfa\x00b)@\xb3\xf4\x8e\x86z\ +\xea]\x01\xed\xd2\xf6\xc93\xa9@]\xac\xdb@c\x89\ +u9\xa0A\xd7\xddd\xa9uba\xebgc\xeb\xf9\ +\x15\x84\xec\x82\xa2C\x0d!RzKC\xb6\xaa\x81\xd2\ +^$\xf0\x80\x11\xab\x98\xaf&d\xe4M\x90*\x02\x22\ +\xa575\x16I0\xcf\xd0c\xc4\x9f\x1e#\x96%<\ +B\x1a\x96\xdd\x80^N\xd5\x22\x94\x82\xc1\xdd\xafw]\ +Z F.4\xec\xec\xcd\x22\x0dk\xa9u\xe9\x0d\x0d\ +{\xbf\x16\x05\x87\xea\x1c\xdd\x08i\xaa\x06-f4<\ +\x02C\xf20\xa2\xa8=\xdd\xb5\x0a\xa2\xd9\xc00#[\ +\xf25l;b\xbd\x0c\x86\x89\xfa\xba\x86\xf5\x03=\x84\ +\x18\x05\xb2\xe1\xca\xbbS\xa0!\xa5\xd0\xf24\x1c\xb5e\ +\xf3Jz\x92\x12\xa0y\xcb5[\xaf3\xd8\xc0\x0ar\ +I!(2\x02\x04\xa2\x96ZC\xbf=(\x80\x02w\ +\xed\x00\xd0!\xb2\x80c\xbe\x86\xdc\x82n\xd1\x0a\xd5\x10\ +4y#_\xa3S\x22C\xae\x98G\xca\x80\xdcC\xe8\ +t\xeb\xa5E\xa8'Pf\x01\x0e\x08\xddE\xfb\x8c\xed\ +}\x14\x0f.\xb6\xd4\x12\x10\xaf4\x0d\xf4\x09\x82\xb0\xef\ +i\xc7]a\xa5|\x05\xe9\x0e\x03\xdb#\x93\xf35,n\xa5hY\ +:\xa5\x92+\xc0\xf3X\x91V6R\x0a\xec.\x90\xca\ +\x8b\x87\xe9\xbdH0\xcdT\xb9\xc3\x13\x94\x0c\xfaO\x1d\ +L\xb4\xa2kQ\xe0*\x01I\x17\x03\x9d5\x8fQ\xa4\ +[\x1a\x8b90\x04\xf4\x8d\x18=\xde\xc8E\xa0R\xe6\ +\x018\x0d\x0f\xdd\xd1\x90\xf30\xdc\x5c\xf7=w\x15\x84\ +C\xd7\xb8\x14\xc14\xf0\xf7#\x10h\x09\xcc\x01O\x9c\ +\x98A\xa9\xebf\xaa\x14\x07x8LL\xe4[0\x12\ +)%\xa0\xef\xf2\xe0\x8aJ\x0bXI\x0aze\x10\xce\ +(\x9b\x00K\xf0\x148\xab\x07BEW}\xb3\xa3\xbd\ +\xec&\xc3\xc0;\xe3\x0dmkx\x16\x9a0\xa9\x0cF\ +\xb8N\xdf:k\x8a\x17\xf0B\xe8\xaf\x8a\xa5v%\x84\ +\xe5\xb0\x0c.A\xb2\xb0\xd4\xc0\x84Q\xc5a`\x0d\xe6\ +\xe5kl\xd5\x17f\x8bCC\xc5\xb3/\xaaA\xb4\x8a\ +\x91\xa5\x8c=|\xc6\x95\xf7\x94\x90OOk\xa8/\xe0\ +\xd2\xd3\x99\xdb\xca\xab)\xac\x88\x90\x8f\xa1\xec(\x5cr\ +\xcc\x0c\xa1\xd32\x0fd\x1cVvFC\xdd\xea\xa0f\ +.\xe8J\xdd\x15\xf3@\xaf-\x1f\x9c\x01K9\x92h\ +{\xb0\xd0\x8f\xd1\x18h\xd3\xea\x18\xd8\xcd\xdf\xae\x83\x8d\ +\xfd\xc2Z7\xdc\xe9\xf9\x08\xc8\x825\x9e\x5cz\x15.\ +\xcbi\xa4\xc1A@8\xea\xaf\x1b\xe6\x0c\xdf\x02B\xe9\ +\x0c7t\x86\xf5b\x18LwNi\x85\xb6\xd1)\xfb\ +\x01\xa1\x82/\x81\xa1\xb8\x1c\x0azI.~\xaa\xd1h\ +\xad(#\x1c\xff\x1e\x88\xfe\x07\xcc \x7f\x0e\x87\xf1(\ +\xb8\x9e\xaf\x9dAh\xfeaw\x08\xab\xf5\xfa\x070\xff\ +<\xd8\xd0\x16\x1a\xd1\xe0 tH!3\xcf\x86\xdf$\ +\x8e\xcd&\xef\xbc\xfa\xa8\xa4\xa2\xa2\xe4\xd1\xd5\x9dS\x9b\ +\x814V\x8b\x0a\xe9\xf9Eg\xc1y0gJ\x8a\xcb\ +\xe1\x1a{\xaesy0\xc7\xf2\xaf\xc3\xd4y\xfb\xe8s\ +\xf34\xef\x00\xb1\xf4>\xa8)\x89\xd1\xda f\x0c\xe7\ +\x10\x0b\xabE\xe2\xca\x0bD79\xec\xab\xd4\xb4nJ\ +(\xa5g\xfe\xfd\xfa\x9d\x863?\xf5\x9cE\xd3e\xe5\ +\xe8f(\xdaZ\x94\x8a#\xd4\x025\xdf\x9d\xc7\x8f\x88\ +\xe0\x0b\x04<8\x84\x0b\xf8\x82\x08>?B\xc0\xe7U\ +\x084<*<\xa2\x9co\x0b\xa9\x88\x08\x9e\x80\x1f\xce\ +W\x0b4|[\x01O\x8b\xdc\xeb\x04#m1\xda\xb0\ +\x12\x9b\xe2\x92\x92\xe2\x92b\xf8\xab(\xb1*\xd5\xc6\xd5\ +%\x04\xc0I[B\x97A\x0c\xca1\xd7\x12\xe3\xa5\xa5\ +\xea\x12M1U\xa2\xae\xbc\xec60\xfd\x08\x91\x07@\ +\xfd\xb3\xef@_\xedX\xd6\x131\xe3lS\x96\xc5\xc0\ +\x22p\xe2*V\xd5cQ\xad\x8eB\xecf\x7f6\x9b\ +\xd8\x0e\xbf\x0dN^\xc14W\xf4\xff\x5c\x12s\x9f\x96\ +\x81cY\x0e\xa0V\xb34j8Z\x02@\xa4Bm\ +G'\xe1\x00\xc7r<\x80\xf5\xc0T\x19\x80\x86F.\ +W[U<9.\xf5D_\xd2\x86\xb2\xf3O\x9c\xbe\ +`aV\x96z\xae&\xcbu^V\xd6\xdc\xac\xac9\ +s\xb3\xe6\x22\xcc\x9d7w\xee\xfc\xb9\xe5Y\x96\x18\x9f\ +\x03\x18\xf5\xe6de\xcd\x83X\xd6\x1c\x1a!kN\xc5\ +\x5c6\xa4\xe7\xa8\xe7\xda\xcf\x9b3'k\xc6\xf8\x81\xed\ +\x1c`\xb9\x00N4ei\xe7`_\x06\x8e\xffC;\ +\x8dm\x01\x9c\x8b\x00\x1e\xd8\xb1l,\xa8\x0a\x5c\x1a\xb0\ +j\xf8Y\x81;nE\xff\x9caY\xe1\x00?'p\ +\xd3\xb51\x078\xbb@\xbe\x1b}\xf6\x00p\x82%\x86\ +=\x1c\x9d\xe8\x85\x86\x03}\xb4\xa1q\xb4\xcb\x0cw\xfa\ +\xecI\x83\x16\xc3\x11~\x0et\x0d\xfc\xb9\xeax=\xfb\ +U#\xd7\xb7\xb9\xd5\xff\x1e\xe7\xee\xd7<\x81#\xf4G\ +\xeeA\x88\xe5\xe7\x1e\x82\xe3\x83\xdc\xc3p\xbc\x9f{\x04\ +\x8ews\x0b\x09;/77\xaf8\x97\xe4\xdd\x22O\ +r\xef\xe4\x82\x17x\x04-\x92\xe3\x15:\x8d\x92\xe3\ +\x05t\xd7B\xcb\xf2\xca+5_\x00\x95N?\x01\xf5\ +\xe6W*\x1f\xe6\xcf\xbc\xfb\xa0~r\x12QKu\xfd\ +H\xf2\xee\xe6jNh\xe8\xc6Py\xba\xbe\x83\xe91\ +\xefd\xae\x96\xdaSr\x22W\xcb\xab\x88\xce\xd5J\x02\ +\xf3[n\xde)\x9d\xfaa&\xb8\x81\x03*\xef\x16$\ +\x1e\x02\xd6%h\xfeM\x88\x17\xea\x06\xa0\x9a`I>\ +\xc8\x0a=x\xa2\x14\x9a\xf48\xf7>\xcd\x1a\x07\xd8]\ +H\xdd%j\x1c\xd0\xa0\x82{\x90\xbaE,N\xe0\x90\ +/\x05\x91N\x14\x90\xfb\x90uX\x93\x0f\xc7C\x9a\x02\ +8\x1e\xd4\x14\xc2\xf1\x80\xe6a\xe5\xe5cx\xac\xeer\ +3\x1b\x10\xb3\x011\x1b\x10\xb3\x011\x1b\x10\xb3\x011\ +\x1b\x10\xb3\x01y\x0b\x06D{\x8f)V9\x8a\x10\xb8\ +\x84\xe9\xfb?t\x08\x9a\xa6\xbb\xd7\xd2O\xa8R1\xf7\ +]\xbak\xf1\x1c\xf4\xf1\xf0\xf0\x7f\xa8-\xb6Q\ +\x00\x00\x09a\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22?>\x0a\x0a \x0a Sky Icon / \ +System / View\x0a \ +Created with Ske\ +tch.\x0a \ +\x0a \x0a \ + \x0a \ + \x0a \ + \x0a \ + \ + \ +\x0a \ + \ +\x0a \ + <\ +/path>\x0a \ + \x0a \ + \x0a \x0a \x0a\ + \x0a\x0a\ +\ +\x00\x00\x14\xc4\ +I\ +I*\x00b\x07\x00\x00\x80?\xe0@\x08$\x16\x0d\x07\ +\x84BaP\xb8d6\x1d\x0f\x88DbQ8\xa4V\ +-\x17\x8cFcQ\xb8\xe4v\x0b\x02\x7f\xc7\xa4R9\ +$\x96M'\x94JeR\xb8\xa4\x82Y/\x98Lf\ +S9\xa4\xd6a.\x9bNgS\xb9\xe4\xf6}#\x9c\ +O\xe8T:%\x16\x8d/\xa0\xd1\xe9T\xbae6\x9d\ +\x1f\x81\xd3\xeaU:\xa5V\x91Q\xabVkU\xba\xe4\ +B\x93]\xb0XlU*\xfd\x8e\xcdg\xb4N\xec\xb6\ +\x9be\xb6\xdd&\xb5\xdb\xeeW;\xa4J\xe3u\xbc^\ +o7{\xd5\xf6\xfdi\xbe_\xf0X:\xde\x07\x09\x87\ +\xc4Sp\xd8\x9cf6\x7f\x8b\xc7drS<\x86O\ +-\x97\x93\xe5s\x19\xbc\xe4k5\x9d\xd0hk\xd5\x8d\ +\x16\x97M-\xd2Q\x00:\xbb\xf4\x805\x05\x1d\xc1F\ +PQ\x8c\x14;\x05\x08\xee!.\xf8+\xc2\x0a\xe3\x82\ +\xb3\xe0\xac\xe8+\x13V\x01s_s\xf9MM\x0f\x8f\ +l\x90\x06\xe0\xa5\xc8)B\x0a7\x82\x80f\xd2\x18#\ +.\x0a\xaf\x82\xa9x\xfc\x0bG.e\xe6\x98\xf3\xeb\xb2\ +\x01\xc4\x14\xe1\x05)\xc1@\x95g\xe7~\x0a\x90\xe3\xb1\ +\xbd|\xda\x17\xa2`\xf5,\x88\x13n\x82\x11\xa8(\xaa\ +\xbd\x15\xa8(\xe4\xe3\x9cJ\x9b\xfc\xab\xbb\x8a4\x00\xa2\ +\xa4\x002\x0a9\xa0\xa3\xda\x0a\x05\xb1\x07\xb2\x0aB\xa0\ +\xa4k\x8e|\xa8\xf0zY\x13%p\x9a|\x90\x08\xc8\ +)&\x82\x84\xcd\x11\xb6\x82\x8d\xce9p\xa1\xc5\x09T\ +r\x94\xc5Na\xfe\x01 \xa4\x1a\x0a=4\xe8y\x11\ +\x0c\xb8\xe7\xf2s\x1d\xa5\x12bO\x1e\xc4\xe8\x10 \x82\ +\x94\xc8(\x93\x22\xa2\xd1\xba\x08,\xb8\xed\xf3\xce\xfe1\ +\xf3\x02}(3(\x10T\x82\x96\x08(K,#\xa6\ +\xe3\xaa\xe3\x9a\xb0\x82\x95'$\xd3\x22D\x90\x08o\xb2\ +\x08\x06\xcd\x899\xe8\x82\x8a.9x\x94\xce\x89-\x0a\ +\x92N\xcc\xf2\x04\x22\xa0\xa5\x8a\x0a\x04\xcf\xa9\x81\xf0\x82\ +\x89\xce9wCLI\xed\x0e\x91\xd1(\xacYF\xa0\ +\xa0B\xa4\xe4\xa0\x85b\x0a[\xa0\xa7\x0a\x0ar#\xe8\ ++^\x82\x17\xa8(8\xaeRh \x9e\xe3\x97H\xf5\ +7;\xd3)\xe5:\xd1\x9f\xe2<\xd1P\xa9\x87\x02\x0a\ +:;\xf2J,\x90M\xc8 F\xb1V\xa0\x00\xa0\xe3\ +\x974T#\x0aW\xa9\xdd~\x85\xa4\x01\xaa\x0a`\xd1\ +\xeaa\x18\x82\x8f\xce9\xef] Vh\x01g\xac\xf0\ +\xf2\x08\x1f\xb8\xe6e\x97l\xa7U\xda=m\xa0\xc9\x00\ +<\x82\x99((0\xa3IH \xd8\xe3\x92\xf4%\xd2\ +\x82\xdd\x8ba\xce\xeb\xbck\xb5\xe9%\xe1\xe9\xb5\xb6\x90\ +\x01\xc8)\x8a\x82\x85\x8a`\xc8\xe3\x93\xb0\x85\xd5\x84\xad\ +\xe6\x92\x0a\x1e8\xe7\x9a\x1d{#\xb9B9;$\x0e\ +\xd2\x08Y\xa0\xa2Z\x98P8\xe3\x0c}\x8f\xafE\x94\ +\xde\xd5\xda\xf7\xce\x22\x9a\xe5H\xdeX\x81\x0f\x92\x0d\x8a\ +\x82\x85W6o\x840C\xbb\x8eE!Z\x0d\xac\xa5\ +EI\x00z\x82\x97\xe8(\x06\xa6\x0c\xae99\x88\x1f\ +\xf9\xc2\xfe\xfa\xa0\x99#W~\xaa\x19\xecq\x9f\xa6\x8e\ +~(\x82\xe4H >\xa6UH J\xe3\x9f{\x06\ +\xc4\xc2Fh `\xe3\x9e\xda\x923\xc1#\x1br\x05\ +\x02\xa0\x83\x92\xa4D\xb8\xe3\xc55\x83\xd9\xccq\x02\xe3\ +\x90\x1c\x22/\xcb#2\x9a\x08\xf2\x00\x00b\xa4 8\ +\xf7\x02yfi\x8ckx\x82_h$\xfe\xa3s\x08\ +\xc0\xec\x82\x91*\x95\xce\x82\x01\xfb\xc7\x1f\xb0\xf4\xac\x97\ +\x14\x82\x11\xf1.\xd8\x9b\x16\xa8(\x94\xa9\x1b\xae8I\ +\xb5\x9f\xe1\x12\x0a\x02\xa5\x99\x86\xec\xa9y\xc0\x00\x9d\xdf\ +mJ)\xb3\x18*F+\x8e\x1e0i\x06\xb2\x82\x08\ +\x0a\x91\xb0\x82\x85>\xa2\x9bw\x00\x14\x82\x9eZ8\xe2\ +o\xba\x81<\x08#\xac\xa7\xfd\x10\xe7Y\xdf\xa6\xa6\xfa\ +\x0a\x10*F3\x8elL\x11 \x18D\x15\xab\x94\xf1\ +\xbc\xeeJ#\xad\x22\xea\x5c\x82\x04B\xa47\x8e; \ +9D\x08m&\xa2\xa4\xb5H H|\xc51#\x90\ +@\xeeT\x96\x8b\xb55c\xe8\xba\x92\x07\x98A\x12\xf0\ +\x00\x01EHB\x10P\xfb\x06\xca[s \x83u\xad\ +\x15 \x86q\xc5\xf4% O\x84\x82=\xf2\x9d\x09\x08\ + ! \xaa\x91l=R~\xe1\x87\xf8\xa9 \xa1X\ +\xa9\x10\x04`\x06\x06u\x00A\xa0\xf0\x88L*\x17\x0c\ +\x86\xc3\xa1\xf1\x08\x88\x01\xff\x14D\xc1\xce\xd1(\xccj\ +7\x09O@\xc0&8\xa3\xfe9$\x92\xc2$Ri\ +Lr?\x13\x8a\x08\xa0\xed\x0886U4\x8d8\xe0\ +\xe2H\xfb\xeak<\x9e\xc2\xa4@h;r\x0e\x1d\x9f\ +Q\xa1N\xf88\xb6>\xe5\x94Q\xe8\xf4\xea|\xfaY\ +'\x8a\x17\xa0\xea\x1a\x95j\x0ci\x8f\xa6+v\x08\xcc\ +\x88\xd1\x07K\xd8i\xe5x\xfa\xaa\xab#\xb3\xca\xaa6\ +\xe9-R\x17\x22O\xc1\xcc\x17\x19\xa3\x8a\x0e*\x8f\xbd\ +o6\x19\x102\x0e\xd6\xa2`%)\xa8\xf9\x9e\x19p\ +\xc3\xd8\xa2\x98\xe9\x5c\x0e\x1b\x22\x04A\xd8\xd0q\x8eF\ +H\xa5\x8f\x973t\xf9\x12\x9a\x0eY\xd0F\xd9\x90q\ +\xe4}\xf3\x8c\xc8i\xa28\xdd|2\xe7\x0e\x91\x07 \ +\xec\x988ke\x125\xc7\xd2\xdb\xc8\xe4\x88\xdb\x07I\ +pb\x0eH8\xe2\x99\x10\xd8\xf1\xe0\xfc\xeex\x03i\ +\xb0\x8a\x0c \xec8>\x0f\xa5'\x83\x9d#\xe8\xee\xe4\ +&E\x05\x83E\xa0\xc0\x1f\x14\x1d\xe7\xa9\x8f\xb4\xa3]\ +\x1e\x7f\xc7\x8f\xd4\xf8E\x090u\x94\x1c\x09\xea\x85Y\ +\x90a\xdd\x1f{\x18\xe4\x88\x0eA\xc8\xb4\x1cf\x7fP\ +\x93\xf1\x07\x13\x11\xf2\xe5%|\xdc\x18M\xbc}RD\ +\x89\x9fA\x8a\x04\x1c\x03\x82\xd0\x83\xa1\x07\x1e\x10r\x99\ +\x1f>\xd3\xe5\x01\x07\x16\xd0r\x1d\x07\x05\xe1\xf4\x1c\xfd\ +]\xd1\xf2\x914\x85[(\xdd\xaf\x85\xd2\x94\x88XA\ +\xca7\xee0B\x8f\x04\x1c\xb0A\xcb\x84\x1c\xe1A\xdc\ +\x94)\xb7A\x81\xf4\x1cHA\xc5\x04\x1c\x10\x90\x90\x98\ +\xc9\x06\x17\x11\xf2\xa2(k\xa0\xb8\xe5\xa6\x8e\xd3T\x88\ +T\x89\x10p\x16W\x9a\x97\x985\x06\x16Q\xf2\xb1R\ +\x98Z\x09\xcd\x9b\x98\xe5\xe3\xfeTA\x8at\x1d\x96\x9a\ +\xe7\xf4\xf4\xf8i\x11\xf9\x19`\x9dY\x1a\x1d\x8e\x9d\xda\ +\x14P3A\xca\xe4\x1c\x1e\xa0)4i{A\x854\ +}\xa8\x5ch\x96\x1e\x9c`(\xb5m\x22\x05\x10yu\ +\x06\x10\xe9J\xa1\x08/\xd0u\xa5\x03:\xe8\x89}\xfd\ +\xa7\x97\x9a\x81gH\xa1\xe4\x18\x88w\xaa\x99\xa9\xe1A\ +\x87d~Y\x9d+\x17\xaa\xb3\x5ckZ\xc0\xff~\x10\ +bE\x07\x09k\xc6\x99CA\x86\xf4|\xb6x\xace\ +\xba\xd8Y\xec\x86\x9a)A\x87$\x1c{v\xad\x05\x1d\ +\x7fA\x88d\x1c\x8dj\xe1\xfbi\x81\xb1\x1e+q\xd2\ +H\x81\xb4\x1c\x8aA\xc5\xab\x91&\xa9@\x01\xd5\x1f\x93\ +'\xfb\xb6\x86\xbb\xdd\xcb\xc60H\x83$\x1cnA\xe3\ +\xe4\x18\x07\xaaZ\xc4\x19k\xb3\x11\xf36\xf9KV\xd9\ +\x83\x03t\xb0ZM\x22\x05j\xc9M\x07\x0f\xe4\x16\x82\ +m\x00\x0c)\x15\x07*Q\xf3\xab\x16kq\x8a\xcb\x1a\ +s\xf1\xcc\xb9\x06H\xa5d\x188fs\xb4\x19EA\ +\xb3\x80\x00\x11B\xe4D\x19IA\x93t\x191A\x8c\ +\xf4\x1c\xc8G\xf4l\xd5\xf6\xcc,\x5c\xcbQ\xd5\xb5}\ +a\xbc\xc0u\x9ds]\xd7\xb5-\x7fa\xd8\xb64\xf7\ +[\xd96}\xa3.\xd9\xb6\x9d\xb3m\xa06\xbd\xbbq\ +\xdc\xb5MOs\xdd\xb7{Cp\xde7\xbd\xf2\xd9\xd5\ +w\xde\x03\x81\xd6\xb7\xfe\x0b\x85\xe1\x97\x9d\xeb\x87\xe2\xb8\ +\xb6\xd7\x84\xe38\xfeA&\xe2y\x1eS\x86\xe4\xf9^\ +c}\xe5\xf9\x9esv\xe6\xf9\xde\x83m\xe7\xfa\x1e\x93\ +d\xe8\xfa^\xa3^\xe9\xfa\x9e\xb3W\xea\xfa\xde\xc3\x16\ +\xeb\xfb\x1e\xd2\xa9\xec\xfb^\xe3\x00\xe3\xbb\x9e\xf3d@\ +@\x13\x00\xfe\x00\x04\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\ +\x01\x04\x00\x01\x00\x00\x00`\x00\x00\x00\x01\x01\x04\x00\x01\ +\x00\x00\x00`\x00\x00\x00\x02\x01\x03\x00\x04\x00\x00\x00L\ +\x08\x00\x00\x03\x01\x03\x00\x01\x00\x00\x00\x05\x00\x00\x00\x06\ +\x01\x03\x00\x01\x00\x00\x00\x02\x00\x00\x00\x11\x01\x04\x00\x01\ +\x00\x00\x00\x08\x00\x00\x00\x15\x01\x03\x00\x01\x00\x00\x00\x04\ +\x00\x00\x00\x16\x01\x04\x00\x01\x00\x00\x00`\x00\x00\x00\x17\ +\x01\x04\x00\x01\x00\x00\x00Z\x07\x00\x00\x1a\x01\x05\x00\x01\ +\x00\x00\x00T\x08\x00\x00\x1b\x01\x05\x00\x01\x00\x00\x00\x5c\ +\x08\x00\x00\x1c\x01\x03\x00\x01\x00\x00\x00\x01\x00\x00\x00(\ +\x01\x03\x00\x01\x00\x00\x00\x02\x00\x00\x001\x01\x02\x00\x10\ +\x00\x00\x00d\x08\x00\x00=\x01\x03\x00\x01\x00\x00\x00\x02\ +\x00\x00\x00R\x01\x03\x00\x01\x00\x00\x00\x02\x00\x00\x00S\ +\x01\x03\x00\x04\x00\x00\x00t\x08\x00\x00s\x87\x07\x00H\ +\x0c\x00\x00|\x08\x00\x00\x00\x00\x00\x00\x08\x00\x08\x00\x08\ +\x00\x08\x00\x802\x02\x00\xe8\x03\x00\x00\x802\x02\x00\xe8\ +\x03\x00\x00paint.net 4.0\ +.9\x00\x01\x00\x01\x00\x01\x00\x01\x00\x00\x00\x0cHL\ +ino\x02\x10\x00\x00mntrRGB X\ +YZ \x07\xce\x00\x02\x00\x09\x00\x06\x001\x00\x00a\ +cspMSFT\x00\x00\x00\x00IEC s\ +RGB\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\xf6\xd6\x00\x01\x00\x00\x00\x00\xd3-HP \x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11c\ +prt\x00\x00\x01P\x00\x00\x003desc\x00\ +\x00\x01\x84\x00\x00\x00lwtpt\x00\x00\x01\xf0\x00\ +\x00\x00\x14bkpt\x00\x00\x02\x04\x00\x00\x00\x14r\ +XYZ\x00\x00\x02\x18\x00\x00\x00\x14gXYZ\x00\ +\x00\x02,\x00\x00\x00\x14bXYZ\x00\x00\x02@\x00\ +\x00\x00\x14dmnd\x00\x00\x02T\x00\x00\x00pd\ +mdd\x00\x00\x02\xc4\x00\x00\x00\x88vued\x00\ +\x00\x03L\x00\x00\x00\x86view\x00\x00\x03\xd4\x00\ +\x00\x00$lumi\x00\x00\x03\xf8\x00\x00\x00\x14m\ +eas\x00\x00\x04\x0c\x00\x00\x00$tech\x00\ +\x00\x040\x00\x00\x00\x0crTRC\x00\x00\x04<\x00\ +\x00\x08\x0cgTRC\x00\x00\x04<\x00\x00\x08\x0cb\ +TRC\x00\x00\x04<\x00\x00\x08\x0ctext\x00\ +\x00\x00\x00Copyright (c)\ + 1998 Hewlett-Pa\ +ckard Company\x00\x00d\ +esc\x00\x00\x00\x00\x00\x00\x00\x12sRGB \ +IEC61966-2.1\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x12sRGB IEC\ +61966-2.1\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00XYZ \x00\ +\x00\x00\x00\x00\x00\xf3Q\x00\x01\x00\x00\x00\x01\x16\xccX\ +YZ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00XYZ \x00\x00\x00\x00\x00\x00o\xa2\x00\ +\x008\xf5\x00\x00\x03\x90XYZ \x00\x00\x00\x00\x00\ +\x00b\x99\x00\x00\xb7\x85\x00\x00\x18\xdaXYZ \x00\ +\x00\x00\x00\x00\x00$\xa0\x00\x00\x0f\x84\x00\x00\xb6\xcfd\ +esc\x00\x00\x00\x00\x00\x00\x00\x16IEC h\ +ttp://www.iec.ch\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x16IEC \ +http://www.iec.c\ +h\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\ +esc\x00\x00\x00\x00\x00\x00\x00.IEC 6\ +1966-2.1 Default\ + RGB colour spac\ +e - sRGB\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00.IEC 61966-2.\ +1 Default RGB co\ +lour space - sRG\ +B\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00desc\x00\x00\x00\x00\x00\ +\x00\x00,Reference Vie\ +wing Condition i\ +n IEC61966-2.1\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00,Refere\ +nce Viewing Cond\ +ition in IEC6196\ +6-2.1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00v\ +iew\x00\x00\x00\x00\x00\x13\xa4\xfe\x00\x14_.\x00\ +\x10\xcf\x14\x00\x03\xed\xcc\x00\x04\x13\x0b\x00\x03\x5c\x9e\x00\ +\x00\x00\x01XYZ \x00\x00\x00\x00\x00L\x09V\x00\ +P\x00\x00\x00W\x1f\xe7meas\x00\x00\x00\x00\x00\ +\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x02\x8f\x00\x00\x00\x02sig \x00\ +\x00\x00\x00CRT curv\x00\x00\x00\x00\x00\ +\x00\x04\x00\x00\x00\x00\x05\x00\x0a\x00\x0f\x00\x14\x00\x19\x00\ +\x1e\x00#\x00(\x00-\x002\x007\x00;\x00@\x00\ +E\x00J\x00O\x00T\x00Y\x00^\x00c\x00h\x00\ +m\x00r\x00w\x00|\x00\x81\x00\x86\x00\x8b\x00\x90\x00\ +\x95\x00\x9a\x00\x9f\x00\xa4\x00\xa9\x00\xae\x00\xb2\x00\xb7\x00\ +\xbc\x00\xc1\x00\xc6\x00\xcb\x00\xd0\x00\xd5\x00\xdb\x00\xe0\x00\ +\xe5\x00\xeb\x00\xf0\x00\xf6\x00\xfb\x01\x01\x01\x07\x01\x0d\x01\ +\x13\x01\x19\x01\x1f\x01%\x01+\x012\x018\x01>\x01\ +E\x01L\x01R\x01Y\x01`\x01g\x01n\x01u\x01\ +|\x01\x83\x01\x8b\x01\x92\x01\x9a\x01\xa1\x01\xa9\x01\xb1\x01\ +\xb9\x01\xc1\x01\xc9\x01\xd1\x01\xd9\x01\xe1\x01\xe9\x01\xf2\x01\ +\xfa\x02\x03\x02\x0c\x02\x14\x02\x1d\x02&\x02/\x028\x02\ +A\x02K\x02T\x02]\x02g\x02q\x02z\x02\x84\x02\ +\x8e\x02\x98\x02\xa2\x02\xac\x02\xb6\x02\xc1\x02\xcb\x02\xd5\x02\ +\xe0\x02\xeb\x02\xf5\x03\x00\x03\x0b\x03\x16\x03!\x03-\x03\ +8\x03C\x03O\x03Z\x03f\x03r\x03~\x03\x8a\x03\ +\x96\x03\xa2\x03\xae\x03\xba\x03\xc7\x03\xd3\x03\xe0\x03\xec\x03\ +\xf9\x04\x06\x04\x13\x04 \x04-\x04;\x04H\x04U\x04\ +c\x04q\x04~\x04\x8c\x04\x9a\x04\xa8\x04\xb6\x04\xc4\x04\ +\xd3\x04\xe1\x04\xf0\x04\xfe\x05\x0d\x05\x1c\x05+\x05:\x05\ +I\x05X\x05g\x05w\x05\x86\x05\x96\x05\xa6\x05\xb5\x05\ +\xc5\x05\xd5\x05\xe5\x05\xf6\x06\x06\x06\x16\x06'\x067\x06\ +H\x06Y\x06j\x06{\x06\x8c\x06\x9d\x06\xaf\x06\xc0\x06\ +\xd1\x06\xe3\x06\xf5\x07\x07\x07\x19\x07+\x07=\x07O\x07\ +a\x07t\x07\x86\x07\x99\x07\xac\x07\xbf\x07\xd2\x07\xe5\x07\ +\xf8\x08\x0b\x08\x1f\x082\x08F\x08Z\x08n\x08\x82\x08\ +\x96\x08\xaa\x08\xbe\x08\xd2\x08\xe7\x08\xfb\x09\x10\x09%\x09\ +:\x09O\x09d\x09y\x09\x8f\x09\xa4\x09\xba\x09\xcf\x09\ +\xe5\x09\xfb\x0a\x11\x0a'\x0a=\x0aT\x0aj\x0a\x81\x0a\ +\x98\x0a\xae\x0a\xc5\x0a\xdc\x0a\xf3\x0b\x0b\x0b\x22\x0b9\x0b\ +Q\x0bi\x0b\x80\x0b\x98\x0b\xb0\x0b\xc8\x0b\xe1\x0b\xf9\x0c\ +\x12\x0c*\x0cC\x0c\x5c\x0cu\x0c\x8e\x0c\xa7\x0c\xc0\x0c\ +\xd9\x0c\xf3\x0d\x0d\x0d&\x0d@\x0dZ\x0dt\x0d\x8e\x0d\ +\xa9\x0d\xc3\x0d\xde\x0d\xf8\x0e\x13\x0e.\x0eI\x0ed\x0e\ +\x7f\x0e\x9b\x0e\xb6\x0e\xd2\x0e\xee\x0f\x09\x0f%\x0fA\x0f\ +^\x0fz\x0f\x96\x0f\xb3\x0f\xcf\x0f\xec\x10\x09\x10&\x10\ +C\x10a\x10~\x10\x9b\x10\xb9\x10\xd7\x10\xf5\x11\x13\x11\ +1\x11O\x11m\x11\x8c\x11\xaa\x11\xc9\x11\xe8\x12\x07\x12\ +&\x12E\x12d\x12\x84\x12\xa3\x12\xc3\x12\xe3\x13\x03\x13\ +#\x13C\x13c\x13\x83\x13\xa4\x13\xc5\x13\xe5\x14\x06\x14\ +'\x14I\x14j\x14\x8b\x14\xad\x14\xce\x14\xf0\x15\x12\x15\ +4\x15V\x15x\x15\x9b\x15\xbd\x15\xe0\x16\x03\x16&\x16\ +I\x16l\x16\x8f\x16\xb2\x16\xd6\x16\xfa\x17\x1d\x17A\x17\ +e\x17\x89\x17\xae\x17\xd2\x17\xf7\x18\x1b\x18@\x18e\x18\ +\x8a\x18\xaf\x18\xd5\x18\xfa\x19 \x19E\x19k\x19\x91\x19\ +\xb7\x19\xdd\x1a\x04\x1a*\x1aQ\x1aw\x1a\x9e\x1a\xc5\x1a\ +\xec\x1b\x14\x1b;\x1bc\x1b\x8a\x1b\xb2\x1b\xda\x1c\x02\x1c\ +*\x1cR\x1c{\x1c\xa3\x1c\xcc\x1c\xf5\x1d\x1e\x1dG\x1d\ +p\x1d\x99\x1d\xc3\x1d\xec\x1e\x16\x1e@\x1ej\x1e\x94\x1e\ +\xbe\x1e\xe9\x1f\x13\x1f>\x1fi\x1f\x94\x1f\xbf\x1f\xea \ +\x15 A l \x98 \xc4 \xf0!\x1c!H!\ +u!\xa1!\xce!\xfb\x22'\x22U\x22\x82\x22\xaf\x22\ +\xdd#\x0a#8#f#\x94#\xc2#\xf0$\x1f$\ +M$|$\xab$\xda%\x09%8%h%\x97%\ +\xc7%\xf7&'&W&\x87&\xb7&\xe8'\x18'\ +I'z'\xab'\xdc(\x0d(?(q(\xa2(\ +\xd4)\x06)8)k)\x9d)\xd0*\x02*5*\ +h*\x9b*\xcf+\x02+6+i+\x9d+\xd1,\ +\x05,9,n,\xa2,\xd7-\x0c-A-v-\ +\xab-\xe1.\x16.L.\x82.\xb7.\xee/$/\ +Z/\x91/\xc7/\xfe050l0\xa40\xdb1\ +\x121J1\x821\xba1\xf22*2c2\x9b2\ +\xd43\x0d3F3\x7f3\xb83\xf14+4e4\ +\x9e4\xd85\x135M5\x875\xc25\xfd676\ +r6\xae6\xe97$7`7\x9c7\xd78\x148\ +P8\x8c8\xc89\x059B9\x7f9\xbc9\xf9:\ +6:t:\xb2:\xef;-;k;\xaa;\xe8<\ +'\ + >`>\xa0>\xe0?!?a?\xa2?\xe2@\ +#@d@\xa6@\xe7A)AjA\xacA\xeeB\ +0BrB\xb5B\xf7C:C}C\xc0D\x03D\ +GD\x8aD\xceE\x12EUE\x9aE\xdeF\x22F\ +gF\xabF\xf0G5G{G\xc0H\x05HKH\ +\x91H\xd7I\x1dIcI\xa9I\xf0J7J}J\ +\xc4K\x0cKSK\x9aK\xe2L*LrL\xbaM\ +\x02MJM\x93M\xdcN%NnN\xb7O\x00O\ +IO\x93O\xddP'PqP\xbbQ\x06QPQ\ +\x9bQ\xe6R1R|R\xc7S\x13S_S\xaaS\ +\xf6TBT\x8fT\xdbU(UuU\xc2V\x0fV\ +\x5cV\xa9V\xf7WDW\x92W\xe0X/X}X\ +\xcbY\x1aYiY\xb8Z\x07ZVZ\xa6Z\xf5[\ +E[\x95[\xe5\x5c5\x5c\x86\x5c\xd6]']x]\ +\xc9^\x1a^l^\xbd_\x0f_a_\xb3`\x05`\ +W`\xaa`\xfcaOa\xa2a\xf5bIb\x9cb\ +\xf0cCc\x97c\xebd@d\x94d\xe9e=e\ +\x92e\xe7f=f\x92f\xe8g=g\x93g\xe9h\ +?h\x96h\xeciCi\x9ai\xf1jHj\x9fj\ +\xf7kOk\xa7k\xfflWl\xafm\x08m`m\ +\xb9n\x12nkn\xc4o\x1eoxo\xd1p+p\ +\x86p\xe0q:q\x95q\xf0rKr\xa6s\x01s\ +]s\xb8t\x14tpt\xccu(u\x85u\xe1v\ +>v\x9bv\xf8wVw\xb3x\x11xnx\xccy\ +*y\x89y\xe7zFz\xa5{\x04{c{\xc2|\ +!|\x81|\xe1}A}\xa1~\x01~b~\xc2\x7f\ +#\x7f\x84\x7f\xe5\x80G\x80\xa8\x81\x0a\x81k\x81\xcd\x82\ +0\x82\x92\x82\xf4\x83W\x83\xba\x84\x1d\x84\x80\x84\xe3\x85\ +G\x85\xab\x86\x0e\x86r\x86\xd7\x87;\x87\x9f\x88\x04\x88\ +i\x88\xce\x893\x89\x99\x89\xfe\x8ad\x8a\xca\x8b0\x8b\ +\x96\x8b\xfc\x8cc\x8c\xca\x8d1\x8d\x98\x8d\xff\x8ef\x8e\ +\xce\x8f6\x8f\x9e\x90\x06\x90n\x90\xd6\x91?\x91\xa8\x92\ +\x11\x92z\x92\xe3\x93M\x93\xb6\x94 \x94\x8a\x94\xf4\x95\ +_\x95\xc9\x964\x96\x9f\x97\x0a\x97u\x97\xe0\x98L\x98\ +\xb8\x99$\x99\x90\x99\xfc\x9ah\x9a\xd5\x9bB\x9b\xaf\x9c\ +\x1c\x9c\x89\x9c\xf7\x9dd\x9d\xd2\x9e@\x9e\xae\x9f\x1d\x9f\ +\x8b\x9f\xfa\xa0i\xa0\xd8\xa1G\xa1\xb6\xa2&\xa2\x96\xa3\ +\x06\xa3v\xa3\xe6\xa4V\xa4\xc7\xa58\xa5\xa9\xa6\x1a\xa6\ +\x8b\xa6\xfd\xa7n\xa7\xe0\xa8R\xa8\xc4\xa97\xa9\xa9\xaa\ +\x1c\xaa\x8f\xab\x02\xabu\xab\xe9\xac\x5c\xac\xd0\xadD\xad\ +\xb8\xae-\xae\xa1\xaf\x16\xaf\x8b\xb0\x00\xb0u\xb0\xea\xb1\ +`\xb1\xd6\xb2K\xb2\xc2\xb38\xb3\xae\xb4%\xb4\x9c\xb5\ +\x13\xb5\x8a\xb6\x01\xb6y\xb6\xf0\xb7h\xb7\xe0\xb8Y\xb8\ +\xd1\xb9J\xb9\xc2\xba;\xba\xb5\xbb.\xbb\xa7\xbc!\xbc\ +\x9b\xbd\x15\xbd\x8f\xbe\x0a\xbe\x84\xbe\xff\xbfz\xbf\xf5\xc0\ +p\xc0\xec\xc1g\xc1\xe3\xc2_\xc2\xdb\xc3X\xc3\xd4\xc4\ +Q\xc4\xce\xc5K\xc5\xc8\xc6F\xc6\xc3\xc7A\xc7\xbf\xc8\ +=\xc8\xbc\xc9:\xc9\xb9\xca8\xca\xb7\xcb6\xcb\xb6\xcc\ +5\xcc\xb5\xcd5\xcd\xb5\xce6\xce\xb6\xcf7\xcf\xb8\xd0\ +9\xd0\xba\xd1<\xd1\xbe\xd2?\xd2\xc1\xd3D\xd3\xc6\xd4\ +I\xd4\xcb\xd5N\xd5\xd1\xd6U\xd6\xd8\xd7\x5c\xd7\xe0\xd8\ +d\xd8\xe8\xd9l\xd9\xf1\xdav\xda\xfb\xdb\x80\xdc\x05\xdc\ +\x8a\xdd\x10\xdd\x96\xde\x1c\xde\xa2\xdf)\xdf\xaf\xe06\xe0\ +\xbd\xe1D\xe1\xcc\xe2S\xe2\xdb\xe3c\xe3\xeb\xe4s\xe4\ +\xfc\xe5\x84\xe6\x0d\xe6\x96\xe7\x1f\xe7\xa9\xe82\xe8\xbc\xe9\ +F\xe9\xd0\xea[\xea\xe5\xebp\xeb\xfb\xec\x86\xed\x11\xed\ +\x9c\xee(\xee\xb4\xef@\xef\xcc\xf0X\xf0\xe5\xf1r\xf1\ +\xff\xf2\x8c\xf3\x19\xf3\xa7\xf44\xf4\xc2\xf5P\xf5\xde\xf6\ +m\xf6\xfb\xf7\x8a\xf8\x19\xf8\xa8\xf98\xf9\xc7\xfaW\xfa\ +\xe7\xfbw\xfc\x07\xfc\x98\xfd)\xfd\xba\xfeK\xfe\xdc\xff\ +m\xff\xff\ +\x00\x00\x081\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22?>\x0a\x0a \x0a icon / outl\ +iner / slice / n\ +ot active - save\ +d copy\x0a \ + Created\ + with Sketch.\x0a <\ +/defs>\x0a \x0a \x0a \ + <\ +/path>\x0a \ + \x0a <\ +path d=\x22M14.9826\ +165,6.50282053 C\ +14.7276121,2.868\ +84654 11.6988335\ +,0 8,0 C6.821531\ +33,0 5.71107957,\ +0.29121506 4.736\ +68211,0.80560781\ + C5.52211072,1.5\ +7704166 8.929157\ +37,4.97484587 10\ +.4514738,6.50452\ +22 C10.82345,6.5\ +0282053 14.72604\ +01,6.5045222 14.\ +9826165,6.502820\ +53 Z\x22 id=\x22Combin\ +ed-Shape\x22>\x0a \x0a \ + \x0a \x0a\ + \x0a\x0a\ +\ +\x00\x00\x09\x94\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22?>\x0a\x0a \x0a Artboard\x0a \ +Created with Ske\ +tch.\x0a \ +\x0a\ + \x0a \ + \ +\x0a \ + <\ +/rect>\x0a \ + \x0a \ + <\ +/path>\x0a \ + \x0a \x0a \x0a\x0a\ +\x00\x00\x02\xad\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22?>\x0a\x0a \x0a Icons / Sys\ +tem / Carat / Wh\ +ite / Default\x0a \ +Created with Ske\ +tch.\x0a \ +\ +\x0a \x0a \ +\x0a\x0a\ +\x00\x00\x8e\x0c\ +I\ +I*\x00\x08\x00\x00\x00\x19\x00\xfe\x00\x04\x00\x01\x00\x00\ +\x00\x00\x00\x00\x00\x00\x01\x03\x00\x01\x00\x00\x00`\x00\x00\ +\x00\x01\x01\x03\x00\x01\x00\x00\x00`\x00\x00\x00\x02\x01\x03\ +\x00\x04\x00\x00\x00:\x01\x00\x00\x03\x01\x03\x00\x01\x00\x00\ +\x00\x05\x00\x00\x00\x06\x01\x03\x00\x01\x00\x00\x00\x02\x00\x00\ +\x00\x11\x01\x04\x00\x01\x00\x00\x00`V\x00\x00\x12\x01\x03\ +\x00\x01\x00\x00\x00\x01\x00\x00\x00\x15\x01\x03\x00\x01\x00\x00\ +\x00\x04\x00\x00\x00\x16\x01\x03\x00\x01\x00\x00\x00`\x00\x00\ +\x00\x17\x01\x04\x00\x01\x00\x00\x00\xd9\x15\x00\x00\x1a\x01\x05\ +\x00\x01\x00\x00\x00B\x01\x00\x00\x1b\x01\x05\x00\x01\x00\x00\ +\x00J\x01\x00\x00\x1c\x01\x03\x00\x01\x00\x00\x00\x01\x00\x00\ +\x00(\x01\x03\x00\x01\x00\x00\x00\x02\x00\x00\x001\x01\x02\ +\x00\x22\x00\x00\x00R\x01\x00\x002\x01\x02\x00\x14\x00\x00\ +\x00t\x01\x00\x00=\x01\x03\x00\x01\x00\x00\x00\x02\x00\x00\ +\x00R\x01\x03\x00\x01\x00\x00\x00\x01\x00\x00\x00\xbc\x02\x01\ +\x00\x1a;\x00\x00\x88\x01\x00\x00\xbb\x83\x07\x00\x0f\x00\x00\ +\x00\xa2<\x00\x00I\x86\x01\x00f\x0d\x00\x00\xb2<\x00\ +\x00i\x87\x04\x00\x01\x00\x00\x00\x0a\x0a \x0a\ + \x0a \ + Adobe Photosho\ +p CC 2015.5 (Win\ +dows)\x0a \ + 2017-03-07T11:3\ +2:29-08:00\x0a \ + 2017-04-04T\ +11:28-07:00\x0a \ + 2017-04-\ +04T11:28-07:00\x0a image/tiff\ +\x0a \ + 3\x0a sRGB IEC61966-\ +2.1\x0a \ + \x0a \x0a \ + a\ +dobe:docid:photo\ +shop:94a27cdb-04\ +33-11e7-b02d-9f8\ +4d9f5a326\x0a \ + adobe:\ +docid:photoshop:\ +acaee4ff-1960-11\ +e7-bae7-e6e7a5cd\ +2814\x0a \ + \x0a \x0a \ + xmp.iid:\ +fa5f33a4-5729-d3\ +41-9ab8-5edce3a2\ +68a4\x0a \ + adobe:docid:p\ +hotoshop:696e80e\ +4-1964-11e7-8c4b\ +-d6fec7ab83c2\ +\x0a xmp.did:ca77\ +1a70-f965-e14f-9\ +103-360465543dbf\ +\x0a \ + \x0a \ + \x0a \ + \x0a \ + crea\ +ted\x0a \ + xmp.iid:c\ +a771a70-f965-e14\ +f-9103-360465543\ +dbf\x0a \ + 2017-03-07T\ +11:32:29-08:00\x0a \ + Adobe Photosh\ +op CC 2015.5 (Wi\ +ndows)\x0a \ + \x0a \ + \x0a \ + saved\x0a \ + \ +xmp.iid:16fdf09c\ +-857d-944e-9783-\ +e127cb1b9cf4\x0a\ + \ + 20\ +17-03-08T11:37:4\ +5-08:00\x0a \ + Adob\ +e Photoshop CC 2\ +015.5 (Windows)<\ +/stEvt:softwareA\ +gent>\x0a \ + /\x0a \ + \x0a \ + \x0a \ + saved\x0a \ + xmp.\ +iid:fa5f33a4-572\ +9-d341-9ab8-5edc\ +e3a268a4\x0a \ + 2017-0\ +4-04T11:28-07:00\ +\x0a \ + \ +Adobe Photo\ +shop CC 2017 (Wi\ +ndows)\x0a \ + <\ +stEvt:changed>/<\ +/stEvt:changed>\x0a\ + <\ +/rdf:li>\x0a \ + \x0a\ + \x0a \ +\x0a \ +\x0a\x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ +\x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a\ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ +\x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a\ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ +\x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a\ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ +\x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a\ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ +\x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a\ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ +\x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a\ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ +\x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a\ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \x0a \ + \ + \ + \ + \ + \ + \ +\x0a \ + \x0a\x1c\x01Z\x00\x03\x1b%G\x1c\x02\x00\x00\x02\x00\x00\ +\x008BIM\x04%\x00\x00\x00\x00\x00\x10\xcd\xcf\xfa\ +}\xa8\xc7\xbe\x09\x05pv\xae\xaf\x05\xc3N8BI\ +M\x04:\x00\x00\x00\x00\x00\xe5\x00\x00\x00\x10\x00\x00\x00\ +\x01\x00\x00\x00\x00\x00\x0bprintOutp\ +ut\x00\x00\x00\x05\x00\x00\x00\x00PstSbo\ +ol\x01\x00\x00\x00\x00Inteenum\x00\ +\x00\x00\x00Inte\x00\x00\x00\x00Clrm\x00\ +\x00\x00\x0fprintSixteenB\ +itbool\x00\x00\x00\x00\x0bprint\ +erNameTEXT\x00\x00\x00\x01\x00\x00\ +\x00\x00\x00\x0fprintProofSe\ +tupObjc\x00\x00\x00\x0c\x00P\x00r\x00\ +o\x00o\x00f\x00 \x00S\x00e\x00t\x00u\x00\ +p\x00\x00\x00\x00\x00\x0aproofSetu\ +p\x00\x00\x00\x01\x00\x00\x00\x00Bltnenu\ +m\x00\x00\x00\x0cbuiltinProo\ +f\x00\x00\x00\x09proofCMYK\x008\ +BIM\x04;\x00\x00\x00\x00\x02-\x00\x00\x00\x10\x00\ +\x00\x00\x01\x00\x00\x00\x00\x00\x12printOu\ +tputOptions\x00\x00\x00\x17\x00\ +\x00\x00\x00Cptnbool\x00\x00\x00\x00\x00\ +Clbrbool\x00\x00\x00\x00\x00Rgs\ +Mbool\x00\x00\x00\x00\x00CrnCbo\ +ol\x00\x00\x00\x00\x00CntCbool\x00\ +\x00\x00\x00\x00Lblsbool\x00\x00\x00\x00\ +\x00Ngtvbool\x00\x00\x00\x00\x00Em\ +lDbool\x00\x00\x00\x00\x00Intrb\ +ool\x00\x00\x00\x00\x00BckgObjc\ +\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00RGBC\x00\x00\ +\x00\x03\x00\x00\x00\x00Rd doub@o\ +\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00Grn do\ +ub@o\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00Bl\ + doub@o\xe0\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00BrdTUntF#Rlt\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00Bld Un\ +tF#Rlt\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00RsltUntF#Pxl@b\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0avector\ +Databool\x01\x00\x00\x00\x00PgP\ +senum\x00\x00\x00\x00PgPs\x00\x00\x00\ +\x00PgPC\x00\x00\x00\x00LeftUnt\ +F#Rlt\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00Top UntF#Rlt\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00Scl Unt\ +F#Prc@Y\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x10cropWhenPrintin\ +gbool\x00\x00\x00\x00\x0ecropRe\ +ctBottomlong\x00\x00\x00\x00\ +\x00\x00\x00\x0ccropRectLeft\ +long\x00\x00\x00\x00\x00\x00\x00\x0dcrop\ +RectRightlong\x00\x00\x00\ +\x00\x00\x00\x00\x0bcropRectTop\ +long\x00\x00\x00\x00\x008BIM\x03\xed\x00\ +\x00\x00\x00\x00\x10\x00\x90\x00\x00\x00\x01\x00\x01\x00\x90\x00\ +\x00\x00\x01\x00\x018BIM\x04&\x00\x00\x00\x00\x00\ +\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00?\x80\x00\x008\ +BIM\x03\xee\x00\x00\x00\x00\x00\x0d\x0cTran\ +sparency\x008BIM\x04\x15\x00\ +\x00\x00\x00\x00\x1e\x00\x00\x00\x0d\x00T\x00r\x00a\x00\ +n\x00s\x00p\x00a\x00r\x00e\x00n\x00c\x00\ +y\x00\x008BIM\x045\x00\x00\x00\x00\x00\x11\x00\ +\x00\x00\x01\x00\x00\xff\xff\x00\x00\x00\x00\x00\x00\x00d\x01\ +\x008BIM\x04\x1d\x00\x00\x00\x00\x00\x04\x00\x00\x00\ +\x008BIM\x03\xf2\x00\x00\x00\x00\x00\x0a\x00\x00\xff\ +\xff\xff\xff\xff\xff\x00\x008BIM\x04\x0d\x00\x00\x00\ +\x00\x00\x04\x00\x00\x00\x1e8BIM\x04\x19\x00\x00\x00\ +\x00\x00\x04\x00\x00\x00\x1e8BIM\x03\xf3\x00\x00\x00\ +\x00\x00\x09\x00\x00\x00\x00\x00\x00\x00\x00\x01\x008BI\ +M'\x10\x00\x00\x00\x00\x00\x0a\x00\x01\x00\x00\x00\x00\x00\ +\x00\x00\x018BIM\x03\xf5\x00\x00\x00\x00\x00H\x00\ +/ff\x00\x01\x00lff\x00\x06\x00\x00\x00\x00\x00\ +\x01\x00/ff\x00\x01\x00\xa1\x99\x9a\x00\x06\x00\x00\x00\ +\x00\x00\x01\x002\x00\x00\x00\x01\x00Z\x00\x00\x00\x06\x00\ +\x00\x00\x00\x00\x01\x005\x00\x00\x00\x01\x00-\x00\x00\x00\ +\x06\x00\x00\x00\x00\x00\x018BIM\x03\xf8\x00\x00\x00\ +\x00\x00p\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x03\xe8\x00\x00\x00\ +\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\x03\xe8\x00\x00\x00\x00\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\x03\xe8\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x03\ +\xe8\x00\x008BIM\x04\x00\x00\x00\x00\x00\x00\x02\x00\ +\x008BIM\x04\x02\x00\x00\x00\x00\x00\x02\x00\x008\ +BIM\x040\x00\x00\x00\x00\x00\x01\x01\x008BI\ +M\x04-\x00\x00\x00\x00\x00\x06\x00\x01\x00\x00\x00\x038\ +BIM\x04\x08\x00\x00\x00\x00\x00\x10\x00\x00\x00\x01\x00\ +\x00\x02@\x00\x00\x02@\x00\x00\x00\x008BIM\x04\ +\x1e\x00\x00\x00\x00\x00\x04\x00\x00\x00\x008BIM\x04\ +\x1a\x00\x00\x00\x00\x035\x00\x00\x00\x06\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00`\x00\x00\x00`\x00\x00\x00\x00\x00\ +\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00`\x00\x00\x00`\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x01\ +\x00\x00\x00\x00\x00\x00null\x00\x00\x00\x02\x00\x00\ +\x00\x06boundsObjc\x00\x00\x00\x01\ +\x00\x00\x00\x00\x00\x00Rct1\x00\x00\x00\x04\x00\x00\ +\x00\x00Top long\x00\x00\x00\x00\x00\x00\ +\x00\x00Leftlong\x00\x00\x00\x00\x00\x00\ +\x00\x00Btomlong\x00\x00\x00`\x00\x00\ +\x00\x00Rghtlong\x00\x00\x00`\x00\x00\ +\x00\x06slicesVlLs\x00\x00\x00\x01\ +Objc\x00\x00\x00\x01\x00\x00\x00\x00\x00\x05sl\ +ice\x00\x00\x00\x12\x00\x00\x00\x07slice\ +IDlong\x00\x00\x00\x00\x00\x00\x00\x07gr\ +oupIDlong\x00\x00\x00\x00\x00\x00\x00\ +\x06originenum\x00\x00\x00\x0cE\ +SliceOrigin\x00\x00\x00\x0da\ +utoGenerated\x00\x00\x00\x00\ +Typeenum\x00\x00\x00\x0aESli\ +ceType\x00\x00\x00\x00Img \x00\x00\ +\x00\x06boundsObjc\x00\x00\x00\x01\ +\x00\x00\x00\x00\x00\x00Rct1\x00\x00\x00\x04\x00\x00\ +\x00\x00Top long\x00\x00\x00\x00\x00\x00\ +\x00\x00Leftlong\x00\x00\x00\x00\x00\x00\ +\x00\x00Btomlong\x00\x00\x00`\x00\x00\ +\x00\x00Rghtlong\x00\x00\x00`\x00\x00\ +\x00\x03urlTEXT\x00\x00\x00\x01\x00\x00\x00\ +\x00\x00\x00nullTEXT\x00\x00\x00\x01\x00\ +\x00\x00\x00\x00\x00MsgeTEXT\x00\x00\x00\ +\x01\x00\x00\x00\x00\x00\x06altTagTEX\ +T\x00\x00\x00\x01\x00\x00\x00\x00\x00\x0ecellT\ +extIsHTMLbool\x01\x00\x00\ +\x00\x08cellTextTEXT\x00\x00\ +\x00\x01\x00\x00\x00\x00\x00\x09horzAlig\ +nenum\x00\x00\x00\x0fESliceH\ +orzAlign\x00\x00\x00\x07defa\ +ult\x00\x00\x00\x09vertAlign\ +enum\x00\x00\x00\x0fESliceVe\ +rtAlign\x00\x00\x00\x07defau\ +lt\x00\x00\x00\x0bbgColorTyp\ +eenum\x00\x00\x00\x11ESliceB\ +GColorType\x00\x00\x00\x00No\ +ne\x00\x00\x00\x09topOutsetl\ +ong\x00\x00\x00\x00\x00\x00\x00\x0aleftO\ +utsetlong\x00\x00\x00\x00\x00\x00\x00\ +\x0cbottomOutsetlon\ +g\x00\x00\x00\x00\x00\x00\x00\x0brightOu\ +tsetlong\x00\x00\x00\x00\x008BI\ +M\x04(\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x02?\xf0\x00\ +\x00\x00\x00\x00\x008BIM\x04\x14\x00\x00\x00\x00\x00\ +\x04\x00\x00\x00\x0d8BIM\x04\x0c\x00\x00\x00\x00\x03\ +\xfb\x00\x00\x00\x01\x00\x00\x000\x00\x00\x000\x00\x00\x00\ +\x90\x00\x00\x1b\x00\x00\x00\x03\xdf\x00\x18\x00\x01\xff\xd8\xff\ +\xed\x00\x0cAdobe_CM\x00\x01\xff\xee\x00\ +\x0eAdobe\x00d\x80\x00\x00\x00\x01\xff\xdb\x00\ +\x84\x00\x0c\x08\x08\x08\x09\x08\x0c\x09\x09\x0c\x11\x0b\x0a\x0b\ +\x11\x15\x0f\x0c\x0c\x0f\x15\x18\x13\x13\x15\x13\x13\x18\x11\x0c\ +\x0c\x0c\x0c\x0c\x0c\x11\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\ +\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\ +\x0c\x0c\x01\x0d\x0b\x0b\x0d\x0e\x0d\x10\x0e\x0e\x10\x14\x0e\x0e\ +\x0e\x14\x14\x0e\x0e\x0e\x0e\x14\x11\x0c\x0c\x0c\x0c\x0c\x11\x11\ +\x0c\x0c\x0c\x0c\x0c\x0c\x11\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\ +\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\ +\x0c\x0c\x0c\xff\xc0\x00\x11\x08\x000\x000\x03\x01\x22\x00\ +\x02\x11\x01\x03\x11\x01\xff\xdd\x00\x04\x00\x03\xff\xc4\x01?\ +\x00\x00\x01\x05\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\ +\x00\x03\x00\x01\x02\x04\x05\x06\x07\x08\x09\x0a\x0b\x01\x00\x01\ +\x05\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\ +\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x10\x00\x01\x04\x01\x03\ +\x02\x04\x02\x05\x07\x06\x08\x05\x03\x0c3\x01\x00\x02\x11\x03\ +\x04!\x121\x05AQa\x13\x22q\x812\x06\x14\x91\ +\xa1\xb1B#$\x15R\xc1b34r\x82\xd1C\x07\ +%\x92S\xf0\xe1\xf1cs5\x16\xa2\xb2\x83&D\x93\ +TdE\xc2\xa3t6\x17\xd2U\xe2e\xf2\xb3\x84\xc3\ +\xd3u\xe3\xf3F'\x94\xa4\x85\xb4\x95\xc4\xd4\xe4\xf4\xa5\ +\xb5\xc5\xd5\xe5\xf5Vfv\x86\x96\xa6\xb6\xc6\xd6\xe6\xf6\ +7GWgw\x87\x97\xa7\xb7\xc7\xd7\xe7\xf7\x11\x00\x02\ +\x02\x01\x02\x04\x04\x03\x04\x05\x06\x07\x07\x06\x055\x01\x00\ +\x02\x11\x03!1\x12\x04AQaq\x22\x13\x052\x81\ +\x91\x14\xa1\xb1B#\xc1R\xd1\xf03$b\xe1r\x82\ +\x92CS\x15cs4\xf1%\x06\x16\xa2\xb2\x83\x07&\ +5\xc2\xd2D\x93T\xa3\x17dEU6te\xe2\xf2\ +\xb3\x84\xc3\xd3u\xe3\xf3F\x94\xa4\x85\xb4\x95\xc4\xd4\xe4\ +\xf4\xa5\xb5\xc5\xd5\xe5\xf5Vfv\x86\x96\xa6\xb6\xc6\xd6\ +\xe6\xf6'7GWgw\x87\x97\xa7\xb7\xc7\xff\xda\x00\ +\x0c\x03\x01\x00\x02\x11\x03\x11\x00?\x00\xf4<\xdc\xcc\x96\ +d\x9a\xa9;@\x80\x00\x00\x92O\xc6P\xfd~\xab\xe0\ +\xff\x00\xfbl\x7f\xe4R\xc9\xff\x00\x95\x1b\xfdz\xff\x00\ +\xef\xabN\xd79\x95\xb9\xcdi{\x9a\x09\x0d\x1c\x92\x92\ +\x9c\xa7e\xf5\x16}79\xb3\xc6\xe6\xb4~V\xa7n\ +OSp\x96\x978\x1e\xe1\x80\x8f\xc1\xaa\xc6.\x0bl\ +g\xaf\x96\xd2\xfb\xac\xd4\xee\x9d\x07a\xb53\xea\x18Y\ +5>\x92EW81\xec\x99\x12x))\x0f\xaf\xd5\ +|\x1f\xfe`\xff\x00\xc8\xa2`fdY\x91\xe9Zw\ +\x02\x0f \x02\x08\xfe\xaa\xd2Y\x18?\xf2\x81\xff\x00\xae\ +~T\x94\xff\x00\xff\xd0\xef\xf2\x7f\xe5F\xff\x00^\xbf\ +\xfb\xea\xd0\xc9\xca\xaf\x19\xa0\xbeIq\x86\xb5\xa2IY\ +\xf9?\xf2\xa3\x7f\xaf_\xfd\xf5Y\xea\x9e\xd6Soz\ +\xec\x07\xe5\xfe\xa1%-\xf6\xfb\xdd\xfc\xde+\xcf\x81v\ +\x9f\xc1\x0a\xe6\xf5\x0b\x9c\xcb\x9f[X)\x975\xa4\xce\ +\xbc\xce\x9f\x05k<\xde1\x9c\xeaL\x11\xab\x88\xe7h\ +\xfa[R\xc1u\x96b5\xd6\x9d\xc5\xd3\x07\xbcN\x9b\ +\x92S\x01E\x01L\x01\ +R\x01Y\x01`\x01g\x01n\x01u\x01|\x01\x83\x01\ +\x8b\x01\x92\x01\x9a\x01\xa1\x01\xa9\x01\xb1\x01\xb9\x01\xc1\x01\ +\xc9\x01\xd1\x01\xd9\x01\xe1\x01\xe9\x01\xf2\x01\xfa\x02\x03\x02\ +\x0c\x02\x14\x02\x1d\x02&\x02/\x028\x02A\x02K\x02\ +T\x02]\x02g\x02q\x02z\x02\x84\x02\x8e\x02\x98\x02\ +\xa2\x02\xac\x02\xb6\x02\xc1\x02\xcb\x02\xd5\x02\xe0\x02\xeb\x02\ +\xf5\x03\x00\x03\x0b\x03\x16\x03!\x03-\x038\x03C\x03\ +O\x03Z\x03f\x03r\x03~\x03\x8a\x03\x96\x03\xa2\x03\ +\xae\x03\xba\x03\xc7\x03\xd3\x03\xe0\x03\xec\x03\xf9\x04\x06\x04\ +\x13\x04 \x04-\x04;\x04H\x04U\x04c\x04q\x04\ +~\x04\x8c\x04\x9a\x04\xa8\x04\xb6\x04\xc4\x04\xd3\x04\xe1\x04\ +\xf0\x04\xfe\x05\x0d\x05\x1c\x05+\x05:\x05I\x05X\x05\ +g\x05w\x05\x86\x05\x96\x05\xa6\x05\xb5\x05\xc5\x05\xd5\x05\ +\xe5\x05\xf6\x06\x06\x06\x16\x06'\x067\x06H\x06Y\x06\ +j\x06{\x06\x8c\x06\x9d\x06\xaf\x06\xc0\x06\xd1\x06\xe3\x06\ +\xf5\x07\x07\x07\x19\x07+\x07=\x07O\x07a\x07t\x07\ +\x86\x07\x99\x07\xac\x07\xbf\x07\xd2\x07\xe5\x07\xf8\x08\x0b\x08\ +\x1f\x082\x08F\x08Z\x08n\x08\x82\x08\x96\x08\xaa\x08\ +\xbe\x08\xd2\x08\xe7\x08\xfb\x09\x10\x09%\x09:\x09O\x09\ +d\x09y\x09\x8f\x09\xa4\x09\xba\x09\xcf\x09\xe5\x09\xfb\x0a\ +\x11\x0a'\x0a=\x0aT\x0aj\x0a\x81\x0a\x98\x0a\xae\x0a\ +\xc5\x0a\xdc\x0a\xf3\x0b\x0b\x0b\x22\x0b9\x0bQ\x0bi\x0b\ +\x80\x0b\x98\x0b\xb0\x0b\xc8\x0b\xe1\x0b\xf9\x0c\x12\x0c*\x0c\ +C\x0c\x5c\x0cu\x0c\x8e\x0c\xa7\x0c\xc0\x0c\xd9\x0c\xf3\x0d\ +\x0d\x0d&\x0d@\x0dZ\x0dt\x0d\x8e\x0d\xa9\x0d\xc3\x0d\ +\xde\x0d\xf8\x0e\x13\x0e.\x0eI\x0ed\x0e\x7f\x0e\x9b\x0e\ +\xb6\x0e\xd2\x0e\xee\x0f\x09\x0f%\x0fA\x0f^\x0fz\x0f\ +\x96\x0f\xb3\x0f\xcf\x0f\xec\x10\x09\x10&\x10C\x10a\x10\ +~\x10\x9b\x10\xb9\x10\xd7\x10\xf5\x11\x13\x111\x11O\x11\ +m\x11\x8c\x11\xaa\x11\xc9\x11\xe8\x12\x07\x12&\x12E\x12\ +d\x12\x84\x12\xa3\x12\xc3\x12\xe3\x13\x03\x13#\x13C\x13\ +c\x13\x83\x13\xa4\x13\xc5\x13\xe5\x14\x06\x14'\x14I\x14\ +j\x14\x8b\x14\xad\x14\xce\x14\xf0\x15\x12\x154\x15V\x15\ +x\x15\x9b\x15\xbd\x15\xe0\x16\x03\x16&\x16I\x16l\x16\ +\x8f\x16\xb2\x16\xd6\x16\xfa\x17\x1d\x17A\x17e\x17\x89\x17\ +\xae\x17\xd2\x17\xf7\x18\x1b\x18@\x18e\x18\x8a\x18\xaf\x18\ +\xd5\x18\xfa\x19 \x19E\x19k\x19\x91\x19\xb7\x19\xdd\x1a\ +\x04\x1a*\x1aQ\x1aw\x1a\x9e\x1a\xc5\x1a\xec\x1b\x14\x1b\ +;\x1bc\x1b\x8a\x1b\xb2\x1b\xda\x1c\x02\x1c*\x1cR\x1c\ +{\x1c\xa3\x1c\xcc\x1c\xf5\x1d\x1e\x1dG\x1dp\x1d\x99\x1d\ +\xc3\x1d\xec\x1e\x16\x1e@\x1ej\x1e\x94\x1e\xbe\x1e\xe9\x1f\ +\x13\x1f>\x1fi\x1f\x94\x1f\xbf\x1f\xea \x15 A \ +l \x98 \xc4 \xf0!\x1c!H!u!\xa1!\ +\xce!\xfb\x22'\x22U\x22\x82\x22\xaf\x22\xdd#\x0a#\ +8#f#\x94#\xc2#\xf0$\x1f$M$|$\ +\xab$\xda%\x09%8%h%\x97%\xc7%\xf7&\ +'&W&\x87&\xb7&\xe8'\x18'I'z'\ +\xab'\xdc(\x0d(?(q(\xa2(\xd4)\x06)\ +8)k)\x9d)\xd0*\x02*5*h*\x9b*\ +\xcf+\x02+6+i+\x9d+\xd1,\x05,9,\ +n,\xa2,\xd7-\x0c-A-v-\xab-\xe1.\ +\x16.L.\x82.\xb7.\xee/$/Z/\x91/\ +\xc7/\xfe050l0\xa40\xdb1\x121J1\ +\x821\xba1\xf22*2c2\x9b2\xd43\x0d3\ +F3\x7f3\xb83\xf14+4e4\x9e4\xd85\ +\x135M5\x875\xc25\xfd676r6\xae6\ +\xe97$7`7\x9c7\xd78\x148P8\x8c8\ +\xc89\x059B9\x7f9\xbc9\xf9:6:t:\ +\xb2:\xef;-;k;\xaa;\xe8<' >`>\ +\xa0>\xe0?!?a?\xa2?\xe2@#@d@\ +\xa6@\xe7A)AjA\xacA\xeeB0BrB\ +\xb5B\xf7C:C}C\xc0D\x03DGD\x8aD\ +\xceE\x12EUE\x9aE\xdeF\x22FgF\xabF\ +\xf0G5G{G\xc0H\x05HKH\x91H\xd7I\ +\x1dIcI\xa9I\xf0J7J}J\xc4K\x0cK\ +SK\x9aK\xe2L*LrL\xbaM\x02MJM\ +\x93M\xdcN%NnN\xb7O\x00OIO\x93O\ +\xddP'PqP\xbbQ\x06QPQ\x9bQ\xe6R\ +1R|R\xc7S\x13S_S\xaaS\xf6TBT\ +\x8fT\xdbU(UuU\xc2V\x0fV\x5cV\xa9V\ +\xf7WDW\x92W\xe0X/X}X\xcbY\x1aY\ +iY\xb8Z\x07ZVZ\xa6Z\xf5[E[\x95[\ +\xe5\x5c5\x5c\x86\x5c\xd6]']x]\xc9^\x1a^\ +l^\xbd_\x0f_a_\xb3`\x05`W`\xaa`\ +\xfcaOa\xa2a\xf5bIb\x9cb\xf0cCc\ +\x97c\xebd@d\x94d\xe9e=e\x92e\xe7f\ +=f\x92f\xe8g=g\x93g\xe9h?h\x96h\ +\xeciCi\x9ai\xf1jHj\x9fj\xf7kOk\ +\xa7k\xfflWl\xafm\x08m`m\xb9n\x12n\ +kn\xc4o\x1eoxo\xd1p+p\x86p\xe0q\ +:q\x95q\xf0rKr\xa6s\x01s]s\xb8t\ +\x14tpt\xccu(u\x85u\xe1v>v\x9bv\ +\xf8wVw\xb3x\x11xnx\xccy*y\x89y\ +\xe7zFz\xa5{\x04{c{\xc2|!|\x81|\ +\xe1}A}\xa1~\x01~b~\xc2\x7f#\x7f\x84\x7f\ +\xe5\x80G\x80\xa8\x81\x0a\x81k\x81\xcd\x820\x82\x92\x82\ +\xf4\x83W\x83\xba\x84\x1d\x84\x80\x84\xe3\x85G\x85\xab\x86\ +\x0e\x86r\x86\xd7\x87;\x87\x9f\x88\x04\x88i\x88\xce\x89\ +3\x89\x99\x89\xfe\x8ad\x8a\xca\x8b0\x8b\x96\x8b\xfc\x8c\ +c\x8c\xca\x8d1\x8d\x98\x8d\xff\x8ef\x8e\xce\x8f6\x8f\ +\x9e\x90\x06\x90n\x90\xd6\x91?\x91\xa8\x92\x11\x92z\x92\ +\xe3\x93M\x93\xb6\x94 \x94\x8a\x94\xf4\x95_\x95\xc9\x96\ +4\x96\x9f\x97\x0a\x97u\x97\xe0\x98L\x98\xb8\x99$\x99\ +\x90\x99\xfc\x9ah\x9a\xd5\x9bB\x9b\xaf\x9c\x1c\x9c\x89\x9c\ +\xf7\x9dd\x9d\xd2\x9e@\x9e\xae\x9f\x1d\x9f\x8b\x9f\xfa\xa0\ +i\xa0\xd8\xa1G\xa1\xb6\xa2&\xa2\x96\xa3\x06\xa3v\xa3\ +\xe6\xa4V\xa4\xc7\xa58\xa5\xa9\xa6\x1a\xa6\x8b\xa6\xfd\xa7\ +n\xa7\xe0\xa8R\xa8\xc4\xa97\xa9\xa9\xaa\x1c\xaa\x8f\xab\ +\x02\xabu\xab\xe9\xac\x5c\xac\xd0\xadD\xad\xb8\xae-\xae\ +\xa1\xaf\x16\xaf\x8b\xb0\x00\xb0u\xb0\xea\xb1`\xb1\xd6\xb2\ +K\xb2\xc2\xb38\xb3\xae\xb4%\xb4\x9c\xb5\x13\xb5\x8a\xb6\ +\x01\xb6y\xb6\xf0\xb7h\xb7\xe0\xb8Y\xb8\xd1\xb9J\xb9\ +\xc2\xba;\xba\xb5\xbb.\xbb\xa7\xbc!\xbc\x9b\xbd\x15\xbd\ +\x8f\xbe\x0a\xbe\x84\xbe\xff\xbfz\xbf\xf5\xc0p\xc0\xec\xc1\ +g\xc1\xe3\xc2_\xc2\xdb\xc3X\xc3\xd4\xc4Q\xc4\xce\xc5\ +K\xc5\xc8\xc6F\xc6\xc3\xc7A\xc7\xbf\xc8=\xc8\xbc\xc9\ +:\xc9\xb9\xca8\xca\xb7\xcb6\xcb\xb6\xcc5\xcc\xb5\xcd\ +5\xcd\xb5\xce6\xce\xb6\xcf7\xcf\xb8\xd09\xd0\xba\xd1\ +<\xd1\xbe\xd2?\xd2\xc1\xd3D\xd3\xc6\xd4I\xd4\xcb\xd5\ +N\xd5\xd1\xd6U\xd6\xd8\xd7\x5c\xd7\xe0\xd8d\xd8\xe8\xd9\ +l\xd9\xf1\xdav\xda\xfb\xdb\x80\xdc\x05\xdc\x8a\xdd\x10\xdd\ +\x96\xde\x1c\xde\xa2\xdf)\xdf\xaf\xe06\xe0\xbd\xe1D\xe1\ +\xcc\xe2S\xe2\xdb\xe3c\xe3\xeb\xe4s\xe4\xfc\xe5\x84\xe6\ +\x0d\xe6\x96\xe7\x1f\xe7\xa9\xe82\xe8\xbc\xe9F\xe9\xd0\xea\ +[\xea\xe5\xebp\xeb\xfb\xec\x86\xed\x11\xed\x9c\xee(\xee\ +\xb4\xef@\xef\xcc\xf0X\xf0\xe5\xf1r\xf1\xff\xf2\x8c\xf3\ +\x19\xf3\xa7\xf44\xf4\xc2\xf5P\xf5\xde\xf6m\xf6\xfb\xf7\ +\x8a\xf8\x19\xf8\xa8\xf98\xf9\xc7\xfaW\xfa\xe7\xfbw\xfc\ +\x07\xfc\x98\xfd)\xfd\xba\xfeK\xfe\xdc\xffm\xff\xff\x80\ +\x00 P8$\x16\x0d\x07\x84BaP\xb8d6\x1d\ +\x0f\x88DbQ8\xa4V-\x17\x8cFcQ\xb8\xe4\ +v=\x1f\x90HdR9$\x96M'\x94JeR\ +\xb9d\xb6]/\x98A\x00\x930(*l\x0c\x9c\x03\ +\x02\x13`P0\x07?\x02?\xe8O\xe8X\x06 \x01\ +\xa4\x00hO\xfa$\x1a\x93H\x82R\xdf\xf0J}J\ +\x06\xff\xa4\x80\xa9t\xd0\x05\x1a\x07U\xa5\xd5\xeb\xf4\xfa\ +\x8d\x86\x05S\x81S\xe9VhK\xfc\x05o\x01\xd5\xaa\ +\xf6\xca\x8d~\x0fh\xb4\xd2\x00P\x8a\x95\x92\xefK\xb0\ +P\xacW\x9aM\xca\x9dI\xbe]05\xca\xf0\x02\x98\ +\xfe\xc8>\xf2O\xa7\xa6U\xe2\xf3\xcc<2O\xb7\xce\ +\x1aSO\x07\xe8Bcm!\x10\x87\xa7)\x89\xb5C\ +\x00v\xb4#?\x01\x81*\x98\x88]\xf7i\x87\xa4g\ +\xb18+\x1e\xe7\x01\xb7\x8e\xed\xaa\x17:\x15\xfa\x0d\xba\ +\xde\xda\xf7\x98Ln;\x7f\xbe\xe2\xf0!\x99\xec\x0d\xe2\ +\xbbj\xe8T\xab\x18^\x7f6\x9f\x90\xc8uz\xbb>\ +\xcf\x81\xfc\xf8\xf4=\x9c\xbe\xb6\xf3#\xdc\xbaa|V\ +N\x0f\xa3c6\xfa\x94\x04\xbfAb\xcf\xf4\xe0)\xc0\ +\x03:r\x08-\xebzc\x03\xc1\x10L\x15\x05>\xe6\ +\x94\x1cc\x13p\x89\x04h\xc2\x86+\xee\x90\x00\xd0\xc8\ +\x10(C\x83 \xdb\x0f\x91\x00LD\x05\xc1q,M\ +\x13\xc5\x09B\xa4fE\x85\xf9\x17\x17\x8d\xa6\xfcdk\ +\xb9\x08\xb0;\x1b\x84\x84LtV5A0_\x14\xc8\ +\x12\x0c\x85!\xa2\xe7\xd4\x8c|\x93RI\x00SI\x84\ +|\x8c}\x1f(\xc4\x0a\x01\x07\xb2\xa8\x9aCK\x058\ +\x0f-\x812$\xbd/\xcc\x13\x0a\x04gL\x86\x08\xed\ +3\x8a\x87\x84\xd4v#\x09\x98\x08\x02\x8a\xf3\x88\xda7\ +\xce\x84\x5c\xa71O\x13\xcc\xf5\x03\x9d\x13\xe9\xc44P\ +\x02\x11\xc9A\x9b\xa8\xc42\x03\x01\x03-\x14?\x0c\x14\ +h\xf0\xe3Ot\x8d%I\xa3\xe7\x95,w\x0c\x94\xc8\ +|oS\x86\xad\x0d\x0d\x0d\x95\x09\x0e\xfe\x8b#}!\ +JU\x15MT\x873\x07\x99\xe1E\x0c\xa1\xf1\xb9Y\ +\x9ah\xc4\xb6\x03\x810\xf8\xdaDN\x22\xb8\xdbS\xc4\ +\xae\x13\x9bU\xc8q\xab\xae\xe1\xa1V\x15UV\x9e\x14\ +\xc8\xc8\x1e\x9b\xb6\x89\xa9O\xd1\x03u\xacD\xd7\xb5\xfb\ +\xa4\x89\xaaF\xdd\xbch\x9e\xb7\x09\xe6\xea\xcav\x13\xa8\ +\xe0\x1f\xb7I\xfb;\xb8\x8e\xdb\xb2\xf29Wr\xd4\x82\ +<\xc8E!C\x81\x17\xc8\x10\x05P\xe0<\xdc\x02\xa0\ +\x97Q\xf8|\xe0\x87\xc6\x08|\x9e\xefA\xf0{C\ +<\x01\x08\x0eli\xb9\xd4\xf2k@p\x12xa\xfd\ +\xfd\x06\xe5&+\xe0\x80\x9b\x12\xf0L>\x8e\xe8,:\ +]\xbb\xe7\x02\x0f\xa5\x17\xbe\xc7\xdc\xfc\x08z\xcc\x80!\ +\x9c 6\x11\xb44V\xa0\x08yn\x89\xcb\x198F\ +\x10\x10p\xd2\x18\xe9\x85\x90\x00\xb0\x1c%!\xc0\xb9p\ +\xa0\xb5\xc3\xb9\xe1\x93\x0f\xc5\xda\xba\x09\x0b\xd5T\xc1\xa0\ +(\x22\xa2@\xadw\xc0\xc8\x1f8\x86J\xf0\xc1\xfc&\ +\x85\x0eA\xfc*(\x1b\x08\x08s\xd0QOI\xea&\ +\x10\xef\x17\xc4\xa8U\x8cA\xa8\x8c\x0c\xb9\x5c\ +/b!\x16_\xf1,\x1f8\xa0\xc6\x1f#\xb83\x08\ +\x04`O\xcb\xd1\x0e%f\x00zRq\x19\xf5\x0a\xe0\ +c1\xc1\xe9\x1c\x5c#\xd4yK`y%\x1f\xbb.\ +\x8a\xcc\xceM\x10\xb6n?\x07\xdb\xd1\x93\xc9\x00\x12M\ +\xd0Z('\x00\xc8_@(\x88\x0bi\xcc)\x04,\ +\xe9\x0c\xcc\x1c{\x92\x84\xa6\x16\xa7\x80qZ\xc1\xb8D\ +\xb6\xe2\x1e\xa5\x87\x90\xef\x0a\x93\xec\x14Aa\xdc:\x93\ +\xd3\xb9wb\xb2Z<\x133$\xdf\xb4T\x013\xcd\ +l'(Z>\xc7\xd3\xd1zcQ\xea\xa2\x91%E\ +\xc5\xb0:\xa3A$\x88\x0b\xaa<*C\xfd!\x0b\xc8\ +]\x04\x1a@l\x10\xc4\x1d)\x14\x80N\x96\x01\x82 \ +-)\x80\xa1\x10\x14\xcc0P\x17\x01!El\xc7\x06\ +3&H\x99\x96N\xe3\x5c|\x96yH\x82L\xbf\xd7\ +\x9ed\xe2\x84\xdbD\xa0Z\xa6\x01\xb9\x04+F\xcb\xdc\ +!\x83\xaa\xaa\x0eEH\x0c\x07\x8dY\x1d\xa9\x00\x17U\ +\xd0t\x92D\xd0\xc0_\xf2l\xc9\xab\xd0X8\xab@\ +\xdbL3\x12\x0e\xd3\xaaxF\x9f\x94P\x8aSE\xc9\ +B\xc275\xc7\xdb'\xa2tU\x05\xa8\x00\xd0 \x96\ +p}\x22\x09`C\x06\x81]a\xc4\xcaa\x0eV,\ +G\xcf\x00\xb4\x1c\x08\x84\xe0\x14\x02\x22\x1c\x09@\xf2\x98\ +]\xcd8\xad\xd4\x19WP\x86U4^\x5c\x0d#\x8f\ +\xfe(W\xb4\x13\x22\xaax\xd8w$2\x7f\x0e\xa48\ +\x14\x01 \xf6\xb6C\xcd0\xaf\x81Om\xc6\x80\x1f\xb7\ +@\x9c\x86\x0ek|8\x02\xb5\xc1\x05l({$H\ +\x8df\xa6D\xd5!P\x8a\x01W2.\xbe-\x0c\xd4\ +\xa8\xc4BN-+\x1bLK\xc9\ +\xc8\x0f\x15x\x0ck\x01\x5c\x0c\x06\x8e\x99Kd\xe8P\ +h\x8cU&~\x80\x90\x17\x15\x98Lk\xc0\x80\x22C\ +\x22\xf8w\x0a\xa2\xf7\x0e\x0a\xcb\x8c\xfa$`\x8c\x15\xef\ +\xb4\x18\x03\xc8\x9c'\xc8\x90\xe8\x12;\ +\xa0\xa4ne\xcc\xd7\x17}\xea\x12\xb8\xa1\x97\x04+\x06\ +\xcb\x94B_\xfc/\xba\xe4\xb4\xa7\xe0`*\x06\xb28\ +*\x06\xb688H\xf2\x09<\xc2P\xc6\xceB\xdd\xdb\ +\x88\xdc\xec,\x1a\x90?\x09\xe41\xf5\x06\xe1S\x9f\xc4\ +\x9d\xf0\xa6\xf7\xcadbw\xa3\x19\xab\xa2\xa2\xae\xc4j\ +\xea\xb9\xa78\x91)0C\xa4\xc1\x12\xb0\x08\x07\xfe\xed\ +\xe8\xb8\x92\xa34o>\x22\xfc\xfd\xa04\x13\xa8\xb9\x14\ +\xefCE\xbd\x11B\x9f\xcd\xd2\xc5\xc4P\xfb\xc2\xf8c\ +\x0c\xdf*\x91e\xb6\xdcS\x8d\x16\xb0\x07\x81)\x0c\x10\ +Z\xec1\x8b-|'\xb5\x08\x15\x98\xa0\xbfb\x03\xbc\ +\xbeB$\x94[\xcb\x04U|P\xcbDF\xef\xec\x5c\ +\xa2\x9a\xc5H\xc3\xb0p'\xb6\xc0\xc6\x90\x01\xd7n\x05\ +&\xce/\xc5~\x1f\x83s\x17\x12>\xfb\xf6C\xab\x8b\ +\x99\xb9\xd9e\x5c\xe2\xc5}\xb1\xc8>\x8d\xcc{Q1\ +8 \xf8&\xedxd\xbd&@~\xbdp\xbc\x0d\x86\ +\xc7\x01\x19\xdb\x8a#\xc4\x9c\xa7\x5c\x0c\xb6\x87[\xcf\x22\ +\xfcn\xe5\xb5\xaa\xc8\x9e\xf2\xd1\xfb\xd101\xd0D\x0a\ +\x85'\x19\x19\xcb\xf4\x86)\xc1\xbc5\xa5\x08[\x064\ +\x91!\x5c~\x0c\xef\xa2m\xf4\xe1:\x9b\x85\xe2\xb5w\ +Qx\x81\x12\xd5\xb0\x0bW\xf1D\xc1b\xc3\x90\x8e\xb1\ +\xc1\xc4\x88V\x01\x03\xa5k[\xe8\x98\xb7\xcc\x8deV\ +O\xa9\xf7f[\xb89{s\x90\xdeg\x099\xaf6\ +H+\xf7\x09\x8a\xc1\xb0\x06\xba\xc0 !\x91\xb8u\x8e\ +`\xbb\xd7\xc1\xa0\xec\xecC\x9e\xcc8\x0a\x07\xc1\xc8\xce\ +\xe9x\x9b\xaff!\xa0\xe1\xdb\xc4\x5cb\x0a\xa1\xafx\ +\x10n%\x01z\x92A\x06\xbd\xec!J\xb1,/$\ +\x02\xcc\x1c>\x0cl\xa54\xfa:\x07\x18\xc1\xf1B\xc4\ +Z\xf8\xd1D\x89\xb2\x88\x89\x15\x95\xbb\xba\x90W\x84\xe6\ +zA\x15\x92\xfc;\xca\x90N\xef'\xfb\xc9!'\x80\ +1\xd3\x81h\xe8\x06\xc1\x08\x1c\xf5@\x90\x0cz\xd0;\ +K\x00\x98\x18\xa7@\xfb[\xeb\x92F{\x86@\xba\xc4\ +!\xbc\xfa\x0e\x01\xb0L90\x8a\x89\x5c\xa2\xce*\xfd\ +\x95BH\xb2\xf8rY\xb2\x87\x8f\xad\x5c\x83\xb5\x87\xa1\ +!$\xf0\x06\xd4\xcfM\xd6\x00\xd0 \xd6\xe0\x98\x10\xfd\ +\xd0R\x8d\xc0\xe8$\xf5@p\x11\xfaZ\xa4\x8ac0\ +a\xfd@\xe6\xe2\x12\xc7r\x22?\x80\xaa\x91\xfet\x81\ +\xcf\x81\xdf\x0b\xfc\xc9\x14e\xbd+.\xffB\x04\x7f\xea\ +\xfc\x08.\xa2K\xe4\xa6kbr\x01\x80\x1e\x02\xf0\x14\ +\x03\xac \x02\xd0\x1a\xf6\x001\x01@.\x03\xabt\x03\ +\xe0O\x02@:i\xe0(\x03.8\xda\x8d\xb8\x0e\xad\ +\xbcm\x02X\xad\x87\xd6\xe8\x822\xf2\xe7\x88\xff\x22&\ +\xf3ev\xd9\xed\x18\xa9\x09:\xe2b\x5c_\xec\xd2\x06\ +\x8f\xc6\x04\x88\xf4\x04`W\x02\xa0N\xf4\xe0D4 \ +\x1e\x02E\xf4\x86\xc3\x5c\xfaB4\x16p\x90\x14\x01\x03\ +\x09`\xc3\x04g\xd0\xa7\x0e\xd0#\x0b\xea~\x8d\x96\xff\ +G\x22\x9ag\xf6\xff\xc0\x00\xf3\xe2P\xc7@\x1a\x02\x0e\ +\xe4\x0d`\x89\x0c`\xaaG\xa4\x7f\x08\xc2(\xaf\x0b\x88\ +ua\xd8\xc2\xc9\x14!\x84\xc8\x19\xc1\x84\x8a\x10\x9c\x83\ +p\xa0\xf8\x8azU\xca~ZM\x12f\x08\xae\xe9\xaa\ +\xc8\xa2\x0a$\xc6BD\xfc\x00H\xce\xc1\x1a\x16\x0e,\ +\x05p\xd0`KZ\xf0\xe1\xc4\xf7\xa1\xb0\xad\x01\xc4\x1b\ +O\x06\x1c!\xb2\xeb\x81\xcc~O\xecY\x80\xf1\x13\xe1\ +*\x09\xd1D\x0cB\x18\x1d1L\x1cez\x05\xa7\xe4\ +%\x0b\xe2\xf8PL#\x0e\x8c~\x90T\x22PX\x11\ +\x10\x5c#0\xb8#\xe5\xfe\x13\x91x\x18`Y\x17\xe0\ +nRf\xbe\x1d\xf1\x88\x1dc\xd6\x1c\xa1\xbc\x1cq\x94\ +\x1b\x8e<\x1a\xd1$\x1c\xf1\xa0\x1c1 \xb6A\xec\xb6\ +\x826\x9ea\x14\xdf\xc0\xea!\x87\xfe\x7f@]\x12\x81\ +\xb4%\x08\x8c\xc4,F}\xc9\x94\x5c!\xe4\xe8\xeeZ\ +\xa1O\xf8\xe9\x8eb\xa8\xea \xf9\xe8d$\x00\x9b\x1e\ +\xa0\xc0\xa4 \xfe\x13\xe2`<\xca\xb2\x1e!\xdb\x14\xc1\ +\xd2\x1cq\xc1\x12\x81\xb6mA\xda\x1d\x11\xfa\x1d\xc7V\ +\xeb\xab~\x9f\xc1\xd3\x1a\x81\xe8A,\xb8\x0dk\xc2\x12\ +\x82 N\x80\xde\x09a\x8b#al%\x10\x80\x02q\ +\xc9\x15\xe2.~N\x14x\xee\x5cy\x8d\xdf\x10\x02\x16\ +\xda+\xfe#\xd1\xc8j\xa0\x80\x0a\x020`Q\x88\x1d\ +\xf2\x18\x1c\xc1\xc0Pa\xc8q\xa7\x1d\x19A\xc6\x1br\ +t\x1b\xb1 \xfe\xc7n\xd2n\xfc\x17b \x11\xd2\x94\ +\x0e$\x98\x14\xcb\xd0$\xf1Z\x15\xad\xcb\x0bRH\xe5\ +\x92L\xe1\xae^\xc5\xa5\x86\xe20`\xba\xd0d#\xaa\ +\xc0\x180\xa2 \xf2j\x1daK,\xe1\x1c\x8c\xd1\xa0\ +\x1c\xe1\xc2\xaa\x81\xd4\x1c\x91W\x0d\x02\x16\xfc`F\x15\ +R\xec\x1a\xb0:!J\x9e\x13\x01\x0f/\xa0\xd3\x1cP\ +\x9e\xe4\xe8\x98\xf8\xa8\xa1\x16b#\x16\xaea+g\xfc\ +H\xec\xc5+\xe29\x09a\x02\x14 \x972`\xbc\xeb\ +h\xdc\x1c\xd3&\x09`<<\x01\xfb.K\x9eCN\ +\xaa\x1a\xef\xb0\xebB\x16E\x81\x98\x17\xea\xfc\x08QX\ +\xec\xcc\xa5\x0f\x024\xd9%c\x0a\xb0V\xa8r\xb3%\ +1\xde\xba\x83'\x10m\xa6#\xef\xd4\x0c \xf2\x0ds\ +\x80\x10\xcd\xf6\x1f\xc1\xfa\xe4 e0\xd3<\x22J\xc0\ +\x18\x0c\xdc!q\x8e\x1b\xd1R\xfd\xa2G\x04\x88<\xc4\ +\xb0\xb5\x16%\x9f9\x02\x1f1\x12\xb4#\x11r#\xc0\ +}< \x9b)A\x1c\x16B \xc3,6\xc3\xa4\x12\ +\x91\xe0\x8b=\xa0\xac\xf4\xe0C\x0d\x81\xa1>a\x88\x16\ +\xf3\xec\x14\xa1\xef?!\xea%\x91>\x0f\x01,\x9f`\ +\xa9/\xe2\x16k\xe7\xf4\x05\xf1\xc0$\x92\xa3*rT\ +\xb9c30\xb1\xd6\xdd\x8dS\x0b4\x16!3\xbe#\ +\xa0KB\xe0],\xe1J\x19\xe6\x1e!!'C\xe0\ +\xf0\x144D\x11\x22X_\x0b\xcc\x0ea\x1e\x0a4T\ +\x0c\xd4:!\x08b\x18\xc0\xfdF \xbd(\x22P\xe4\ +)F\x94\xa2 \x0dTt\x08\x81\x95G\xa1z$\x8f\ +\x82\xf8s\x07\x0f!\xe1A\xd2\xae\xe9%\xae\xcb\x91\xdd\ +1Q\xe0\xa2(\xb7%\xa2;\x0b\xc0 \xb5, \x02\ +\xe2\x18\x9c\xc1l\x14tb\x0f\xd3*$\xe2\x9e\x98\xb2\ +a&B/\x12\x14N\x0a\x01\xb3L\xe1\x9e$\x8a4\ +\x07@\x90\xd3,\xe8!\xef\xe0\x11\x00\xd4\xea\xa1/A\ +\x0d\x07\x15\xcd\x0a\xe5FK$\xae\x18\xdd\x8b\xa2\x7fo\ +\x9a\xa93\x1c#\xec\x88\x14L\x8c\xc9\x02\x18\x93\xd3z\ +\x07\x22P\x91\xf3\x96$\x0c\xe4\x18\xc1p\x9ej8$\ +px\xcf\xe1R\x1aj\xc6!k$\xb2\x88p\xb2\xe2\ +F\xf2*\x095\xd0OA\xaf1A\xef56\x91l\ +fo\x9b7J\xf8$+\x08\x14\xe0\x8dV`\xb0\xaa\ +j\xab@\x00U\x1a\x91\xac$Jf\x10\x01@\x09\x95\ +\x80\x0b\xe2@\xecA\xd8\x1c\xf4T\x0a K?!\xef\ +?b>\xf4n\xaa\x1b\x0f\xac\x03b\x18\xd7\xc1d\x13\ +\xcdv\x10@\xc7H\x13\x02\x11UF\x06I!5\xea\ +\x0e\xf8\xeb?+\x12P\xe1\xf4\x997\x0a!PN\xf0\ +$il\x0f\x80\xd3]\xe1\x06!\x8b\x88\xee@U-\ +a\xc2$\x95\x0bP\xe0T\xc9\x22>k\xee\xe4\x05s\ +\x9e$\x91x\x13\x81\x86\xdc\xa2\x18\x18v\x10\x16\x89H\ +\x0e \x9a$\x92>}T\x85[\xee\xd2\xe5ec;\ +B\x1d;\x93m\x5c\xeb\xf974\x9f\x10\x82CV`\ +\x8c\x0a\xeb\x08\x15\x13\x878\xa9C8\xf5P$\x13\x97\ +9\xa2=\x22\x0c\xb8\x05q $\x95{W\xf5\x82!\ +\x88\xd0\x1a\xc1\x98\x0b\xf6t\x06\xc6$\x22\xf4\x83,b\ +-;\x00{b\xc2\x1b\x16\xb1n#\x0a\xf0\x9bU\x06\ +#\xc7@\xe3!H\x19\xb4Z \xf3S4\xc1~$\ +\x8a\xfc\xb0\x052\xb0B?(4\x00\x05*\xf0$\x8e\ +\xbe\x0b\xa0\xe9#\x01\x16\xb5\x88.\xcb\x80Y\x0d\x82A\ +TV\x80\x22\xb3`VO\x91U%p\xbf63;\ +\xd68\xbf\xd6<$\x08\x8c\xb0\xe1\x5c\x1bL,!\x91\ +\xf0\x0b\xef\x1a\x16\xaf\x1e$q\x0d.\xc1T\x1a\xa0\x0b\ +q`\x0c#\x8dh\x121\x10\xb2\x02O< |\x09\ +\xd3\xc8\x16\x22\x18`S\x8d6B5#\xf2CO.\ +\x10d\xab\xedn0\xadno9Bb\x10\xe9\xe8`\ +\xfa\x02HJu\xf2\x05\x17`\x06B\x19P\xa1\x16\xd3\ + \xec%\x12'\x22\xa2(*T\xb0\x14r\xfa\x10\xe0\ +\xd3:BL\xcd kP\xa7l!\xf3\xd0\xc3\x81z\ +\xc3\xc2?A(?u\x02\x0fhV\x88!\x8f\xf6Z\ +\xe5\xb3P0c]bL\x12\x17\xb8\x16\x87H\x07\x80\ +\x96!\x8d\xbe\x15\xf0>\x0aBYL'$\xc6\x80P\ +!\x8a\xf0@\x00\xa6\x05\x16\x02%w\xd4\x15\x17\xe8\x1a\ +U6!K*\x0f5;mt\xee\xa77Abw\ +E\x0a\x97I6wM6\xb5\xcc#\x07\xfez)Q\ +x\xe2M2\x13%2\x82\x18\x8c\xcb\xd6\x0b\x80f\x91\ +\x02V4\xe0\x86\x0a\x87v\x15b!R\x95\x22\x17\x02\ +Y\x02\x0bR\xc0\x22\x19\x09\x01g\x09P\x99oU\xb7\ +\x7f\xcaw*\x83-tu\xc7O\xd7O6\xf67]\ +7\xb2\xf4\x02H\xed\xe0\xe0\x11\x98&\x0eb\x18\xfe\xd5\ +\xe9 \xc1\xd0%\x8a\xdcB!6\x18B!{\x81 \ +\x0e\x96\x9c\x94\xc2Wq`\x0a\x00\xd50\x1a\x8fj!\ +\x8d^\x0cX\xb0\x07XT\xdcj\xdb\x7f\xf0\xa5b\x80\ +}zb\x17z\xa9\xe9IP\xb5\x81(\xb7\x81tj\ +\x94V\x17\x89\xc6\xf2(Vt\x0b\xe0mf\xe1\x98%\ +\x8fk~\x81P\x1aE\xf0!\x96\xf8\x13+\x08\x0d\x02\ +`\x98\x01*\x17@o\x90\xa0\x8bV\xd2\xdfm\x12\xe2\ +#V\x7fT\x98\xbe\x89\xed\xd4\xc5U\xc9h\xe2/B\ +\xa2H\x07\x190\x08\xcb*\x17\x22 \x0f\xb9<\x0b\x93\ +\xec\x16\xe1KD\xa45q\x01\xa9.\x82\x19q\xf7\x22\ +&\x0ep\xb1\xa9\xe1rB\x14`K\x1c\x06*\x80#\ +\x95D\xf2\x97\xa0 \xd2\xabb\xb6S\x80\x8d\xdb\x80\xd8\ +\xcf1\x88\x04\xdeu,\xb7u1SBh!\x8e|\ +\xe8\x02_l6\xc6N\xa2\x10\xfe\xc8\xa1s\x82R\xee\ +@\xd4\xc3!*\x22\x18t\x09\x81\x89\x9b\xa1k\x96\xd7\ +\xfb$V\x83\x1d\x09\x9d\x9a\x82!h\xd5X\xae\xe6q\ +iW\xb4$\xa7\xb9400!\x97\x94\x15\x93\xd0A\ +-'\x83\x00\xa6\x99a\xe7\x84\xc1>FA\xbe\x1a\xe4\ +\x12\x97 \x80\x13:\x09j\xa2\x1fv\xd7h#\x97<\ +\x91\x81_\x9cB+\x97x\xc3\x97\xa2$\xba\x04@\xd1\ +qq+\xad\x1d\x9d\xa2P\x13\xba8\x18\x8d\x88\x05\xe0\ +v!\x8e\x02\x1b\x01\x9dl ig\xb3\x92!sG\ +48\xf6!h \x15\xe16\x9d!\x0a\x0c\xc29:\ +\x94\x15\x86\x8d\xd1\x8c\x18\xc4!Y\xd1P\x0d\xa1\xa3\x19\ +\x88$\xd9<\x0f\xa18\x09\xfa\x8d[\x22\x17\x0d\x95\xe9\ +,\xbaR#\x0bS\x07\x82\x19G\xa1\x94\x17\x94t\x0d\ +Y\x0e#z\x16\xc4Z\x1c\x22\x9a!\xa7b\x12\xd9\xb7\ +\xad;\xb9+n\xed\xa5U\xe2Q\x99\xd6\xc8\xc1\x22\x85\ +\x82`gL\xe1\xb3M:\x9a!E\xfa\x83@+>\ +\x00\xf3\xae\xe1/\x11b\x19\xad\xc1\x9f8\xd9\xc0u\x18\ +6\xf6p\xb5m\xf9\xcd;uU18\x10H\xf0\x03\ +\x00bSr\x97-)W0!\xeb\xc2\x0a\x8b\xbc\x15\ +\xa5TJd\x07JP\xdc5\xa0%\x10\xcf\xb7}S\ +F\xcc\xc04\x86\xa6D\x22x\x17\x8e1\x82#s\xa9\ +\xabb'\xb0\x98\x07\x16\x90\xaef\x1a-n\xca d\ +\xf8\xd4%o\xba\x04 S\x8f\x01\xa46\x03d!n\ +\xfc\x0fm\xb0\x13\xd3\x84D\xa6\x88\xf6\x10%\x02r\xe9\ +\x11r\xe9}P4\x03(\xe4e\xa2`\x14{\xa8\x11\ +\x81#\xba\xf1\xb7\xb5U\xb7[\xb6%\x16\x11\xd1\x8b\x00\ +\xc4\x07yj\xd5\x0d\x14r\x95[c\xb3v%L\x03\ +o\x81\xb3J\xa2\x19S\x01&\xcf\xa28h\x89\xc7J\ +@3\xbe\xe0>\xfbp*\xfb\x8f\xba\x05SG\x03\x14\ +\xa4OE\x998\xcb|\x1c\xc1\xbf\xa6\xb8Wm\xa2(\ +\xb9\x88H\xed\x97J\x9aP\xfc\xd5V4\x8b:\x81i\ +bJ)\xfb\x86\x18\xcd\xac!\x81q\xc3\xa1L\xde\xc0\ +\xb6 \x94\xab\xb9\xfb\xf7}Q\x0d\x07\xdbH\xc2\xc4\x06\ +\xf4n\xf3!\xd4\xcb\xa8\x223m\x99\x1d$x_\x80\ +XcnY\x7f\x5c\xb0\xb5\x92\xc2V\x10\x9c|\x14\xa0\ +\x91\xc8 \xb4!\x95\xec\x80\x81\x8e\xfb{\xee\x03 ?\ +\x0b\xc0#j:\xe2 \x8c\xaa\x8da\x9a\x18\x011\xca\ +\xa0\xfe\xbd\xd5\xb5\x8b\x90K\x8b\xc2/\x05\x07\x8b\xa2S\ +\x0f\xb0\xfa\xc4\x22\xdcx%E\x1a\x0c\x00\xf0r\x5c\x9e\ +!\xb1\x1c\x82\xc1\xd5\x12\x12\x06\xad1\xfa\x1d\xb2\xcb\x0d\ +\x92\x83 \x01\xc7\x0e\xae\x0a\xf8\x5c\x14\x22p\xa6Y\xfb\ +\x0bb\xf5U\x92\x9c\xc9\xac\x94\xa1\x88\x89\x91\x88\xd8\x90\ +\xeaF\xbf\xce\xc5\x07\x191\x94\x1bq%\x19\xb5\xed\x1a\ +kfOY\x1bHu\xc0U\xd4\x8dO\xbcqB'\ +\xf9\xa7\x0e\x9c\x85\xceiu\x82^e\xa1\x1f\xd5!d\ +\xd2dL*P\xd9\xcf\x12\xdc\x1c\xbc\xe7,\xae\xb8\x1c\ +\xb1.\x1b2|\x1b\x92\x0d!\xfd/\x08\xd9n\xb99\ +r \xbc\xfe~\xbcn\x22\x9a\xc0\x9e\x9d\x08\xc5\xf9\xd6\ +\x8b|`%\x9bIZ\xe1D\xcf,\xf6#f\x05\x0d\ +\x91\x8e\x1b\xf3\x9e\xe3\xc1\xab\x12]\xae\xf0\xe1\xc3(\x9c\ +\xd6\x22\xfce\xd3X\x00\x1e4\xf8\x9a1\xdb\xc7}\x0d\ +o$\x10JxzJ\xa0z\x09\xb0\x80\x02I\xae\x1f\ +\x86H\x1e\x11.\x1b]s\x9f\xc1\xad9\xfdc\x91}\ +\xc3\xcfP\xef\xdc\x99\x1e~}\x01\xb5\xfc\xc2\x8a\xbc#\ +B]E\x104\x9do\x1b\xd3\xe0>%0\x087\x1c\ +\x96\x0c\xca\x99\xc8\xca\xfe\x11\x9c\xfc\xc5n\xa2.\xaf\x14\ +\xe2\x0dY\xfc\x1a\xec\x18\xc1\xde'\xe4\xe2D\x07~T\ +\x09S\x80\x0da\x0at\x0cO\x86\x09+\xc7\x14\xfe\x81\ +\xc2>\xaf\x1aP9\xc6\x92b&\xee1C\xb9\xe7b\ +\x18nF\x84cG\x9co\x02\x0b\xe8\xde\x86^E\xce\ +;&\x99\xe7\xddE\xe8\xc6\xf7\xe9\xa2\x85C\xa5\x8d\xe9\ +`\x02_\xf0\xb4 \x9a\xbb\xcc\x1e9\x80\xbcu\xd8>\ +Q\xec.\xa5\xebt\x8e\xed\xa5\xab\xac>=\xec^\xd5\ +\xdc9\xa4s=\x03h\xa4\xb9\xaa\xa1\x09F\xde\xd7\xee\ +\xbe$\xb5\xb3S\xdbE\xa8\x00\xf8&\x0e\x95\xde\x0d!\ +\x07\xeb>\xed\xf0e#\x19\xb20\x09U\xec#\x1b|\ +\x08?\x18\x0a8\x1d\xba_\x09\xf2.l<\xdc:\x17\ +\x01L\x90\xa0\xd9\xe0\x06&)/\xb7\xda\x00W\xf3\xe0\ +m\xf2_D\xda\x98\x85\xe4/\x14\x18!e3\x828\ +e\xb80\x0a\x98t\x11\x90\x1b\xf4\x7fdRG\xe5)\ +\xa1!\xbe\x1c\xe6$\x89\x14\xcf \x9dIPr\x05x\ +\xa0\x00\xff6c\x02\x1cnE\xe1\xe9%\xed\xe7\xe3\xac\ +<_\x95\xe8?\x94n_\x98\xc5\xde\xac\x22\x1f\xa6c\ +>\x94oE\xdb\xf8~y\xe8\x9f\x9f\xf9\xa6\x82)f\ +\xbf\xd6\xe7\xc4\x13\xc1y\xfc\xa1W!\xc2P)\xe6[\ +\x10\xd7`\x05\x00d\xfbt\xa4)\xf6\xbf\xfb\x22\x0en\ +?\xbc,\xff\xb0 F\x8c;\x06\x9a \x0f\xf7\xf8\x06\ +\x09\x05\x82@\xa0@\x08P\x00\x05\x0d\x01?\xa2\x0f\xe8\ +\x5c2\x1a\x03\x88\xbf`\xd18\xd4l\x01\x08\x81\xc1c\ +\xd18\xf48\x05!\x8eH\xe1\xd184E\xfd(\x86\ +\xc4\xe5\x92H\xf4z\x0d\x19\x85\xcb&\xd1\xc8\x5c\x92Y\ +&\x85NcRG\xed\x0d\xfb\x13\x92>i\x0f\x87\x9d\ +-\xde\xe3\xa77\x1b\xd5\x16\xb3\xa2\xa8\xe1{\xd5\xde\xb3\ +\xe9\xd5n\xb9]\x8eA\x80v\x10%\x8c\x08\x05\x99L\ +\xe15\xe9<\x22\x81j\xb7[\xeb\x95\xabm\xc2\xe9u\ +\x9dM \xb7k\xd4v\xd9y\xbd\xdf\xf0\x11\xa9e\x11\ +\xf9\x17\xad`q\x18\x9cV/\x19\x8d\xc7c\xf2\x19\x1c\ +\x96O)\x95\xcbe\xf3\x19\x9c\xd6o9\x9d\xcfg\xf4\ +\x1a\x1d\x16\x8fI{\x80\x80\x00\x00\x00\x03\x00\x01\xa0\x03\ +\x00\x01\x00\x00\x00\x01\x00\x00\x00\x02\xa0\x04\x00\x01\x00\x00\ +\x00`\x00\x00\x00\x03\xa0\x04\x00\x01\x00\x00\x00`\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00Adobe Pho\ +toshop Document \ +Data Block\x00MIB8n\ +rTM\x00\x00\x00\x00MIB8ryaL$\ +!\x00\x00\x01\x00\x03\x00\x00\x00\x03\x00\x00\x00]\x00\x00\ +\x00\x5c\x00\x00\x00\x04\x00\xff\xff\x88\x0d\x00\x00\x00\x00\x0c\ +\x06\x00\x00\x01\x00\x0c\x06\x00\x00\x02\x00\x0c\x06\x00\x00M\ +IB8mron\xff\x00\x08\x00<\x01\x00\x00\x00\ +\x00\x00\x00(\x00\x00\x00\x00\x00\xff\xff\x00\x00\xff\xff\x00\ +\x00\xff\xff\x00\x00\xff\xff\x00\x00\xff\xff\x00\x00\xff\xff\x00\ +\x00\xff\xff\x00\x00\xff\xff\x00\x00\xff\xff\x00\x00\xff\xff\x07\ +Layer 0MIB8inul\x14\ +\x00\x00\x00\x07\x00\x00\x00L\x00a\x00y\x00e\x00r\ +\x00 \x000\x00\x00\x00MIB8rsnl\x04\ +\x00\x00\x00ryalMIB8diyl\x04\ +\x00\x00\x00\x03\x00\x00\x00MIB8lblc\x04\ +\x00\x00\x00\x01\x00\x00\x00MIB8xfni\x04\ +\x00\x00\x00\x00\x00\x00\x00MIB8oknk\x04\ +\x00\x00\x00\x00\x00\x00\x00MIB8fpsl\x04\ +\x00\x00\x00\x04\x00\x00\x00MIB8rlcl\x08\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00MIB8d\ +mhsH\x00\x00\x00\x01\x00\x00\x00MIB8t\ +suc\x00\x00\x00\x004\x00\x00\x00\x10\x00\x00\x00\x01\ +\x00\x00\x00\x00\x00\x08\x00\x00\x00metadat\ +a\x01\x00\x00\x00\x09\x00\x00\x00layerTi\ +mebuod\xc5\xa4\xf3l\xf98\xd6A\x00M\ +IB8prxf\x10\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00S\x00O\ +\x00\x0f\x00\x0c\x00\x0a\x00\x09\x00\x09\x00\x09\x00\x09\x00\x15\ +\x00K\x00K\x00\x1e\x00\x1e\x00\x1e\x00\x1c\x00)\x00'\ +\x00(\x00$\x00'\x00\x22\x00'\x00$\x00&\x00%\ +\x00%\x00 \x00\x1d\x00\x1c\x00\x1c\x00\x1d\x00\x1b\x00\x1d\ +\x00!\x00\x22\x00#\x00%\x00!\x00$\x00+\x00+\ +\x00,\x00+\x00(\x00%\x00&\x00.\x00/\x00.\ +\x00+\x00-\x00-\x00.\x00-\x00.\x00/\x00-\ +\x00.\x00-\x00.\x00-\x00-\x00*\x00%\x00#\ +\x00(\x00,\x00+\x00,\x00,\x00%\x00#\x00!\ +\x00&\x00\x22\x00!\x00\x13\x00\x14\x00L\x00\x09\x00\x09\ +\x00\x08\x00\x09\x00\x0a\x00\x0a\x00\x0c\x00L\x00W\x00 \ +\x00\xfd\x00\x04\x05\x11!-1\xfe/\xfc0\x181/\ +/0110010/1/0010/\ +0110/01\xfe0\x0a/21100\ +/00//\xfe1\x000\xfe1\x05010/\ +01\xfe0\xfe1\xff0\x081/0/-'\x18\ +\x08\x01\xfe\x00\xff\x00\x07\x01\x14X\xab\xdb\xec\xf0\xf0\xfd\ +\xf1\x00\xf0\xfe\xf1\x00\xf2\xfd\xf1\xff\xf0\x01\xf1\xf0\xf8\xf1\ +\x03\xf0\xf1\xf1\xf0\xfe\xf1\xfe\xf0\x07\xf1\xf0\xf0\xf1\xf1\xf0\ +\xf1\xf0\xfc\xf1\xff\xf0\x1b\xf1\xf0\xf0\xf1\xf2\xf1\xf0\xf1\xf0\ +\xf1\xf1\xf2\xf0\xf1\xf0\xf1\xf0\xf0\xf1\xf0\xee\xe4\xc2|.\ +\x06\x00\x00\xff\x00\x03\x16\x86\xed\xfd\xb3\xff\x04\xf9\xbfA\ +\x06\x00\x03\x00\x08l\xf4\xb0\xff\x03\xfe\xbd*\x01\x02\x00\ +$\xd0\xae\xff\x02\xf8x\x07\x02\x02O\xf6\xad\xff\x01\xc0\ +\x14\x02\x05r\xfd\xad\xff\x01\xe1#\x02\x08\x86\xfe\xad\xff\ +\x01\xed+\x02\x08\x8f\xfe\xad\xff\x01\xef-\x02\x09\x91\xfe\ +\xf1\xff\x00\xfe\xdb\xff\xfe\xfe\xfd\xff\x00\xfe\xec\xff\x01\xef\ +,\x02\x08\x91\xfe\xfa\xff\x17\xfe\xcf\xc2\xc3\xc2\xc4\xc3\xc4\ +\xc3\xc3\xc4\xc4\xc1\xc3\xc3\xc2\xc3\xc2\xc2\xc3\xc2\xc3\xc4\xc4\ +\xfe\xc2\xff\xc3\x0c\xcb\xd5\xdc\xe1\xe1\xdd\xd5\xcc\xc2\xc3\xc2\ +\xc2\xc1\xfe\xc3\xff\xc4\xf9\xc3\x06\xc4\xc3\xc3\xc4\xc2\xc3\xc4\ +\xfe\xc3\xff\xc2\x01\xc7\xf1\xf9\xff\x01\xf0-\x02\x09\x90\xfe\ +\xfa\xff\x03\xfaK\x18\x17\xfc\x18\x14\x17\x18\x16\x19\x17\x18\ +\x19\x19\x18\x19\x18\x17\x18\x19\x19\x18\x17/~\xce\xf4\xfb\ +\xff\x13\xf7\xc8\x810\x18\x16\x19\x19\x17\x18\x18\x19\x18\x18\ +\x19\x17\x19\x18\x19\x18\xfd\x19\x08\x18\x19\x19\x18\x19\x19\x17\ +,\xc7\xf9\xff\x01\xf0,\x01\x09\x90\xf9\xff\x01\xf98\xeb\ +\x00\x020\x9f\xea\xf5\xff\x02\xeb\x996\xe8\x00\x01\x15\xc0\ +\xf9\xff\x01\xef.\x02\x09\x91\xfe\xfa\xff\x01\xf97\xec\x00\ +\x01u\xf4\xf1\xff\x01\xf7c\xe9\x00\x02\x14\xc2\xfe\xfa\xff\ +\x01\xf0-\x02\x09\x90\xfe\xfa\xff\x01\xf88\xee\x00\x01\x12\ +\x91\xed\xff\x01\x9a\x17\xeb\x00\x02\x14\xc2\xfe\xfa\xff\x01\xef\ +/\x01\x08\x90\xf9\xff\x01\xf99\xef\x00\x01\x0e\xc7\xeb\xff\ +\x01\xba\x02\xec\x00\x01\x14\xc1\xf9\xff\x01\xf0/\x02\x09\x90\ +\xfe\xfa\xff\x01\xf97\xef\x00\x00\x95\xfa\xff\x09\xd1\x9c]\ +B;Hj\xaa\xd6\xfe\xfa\xff\x01\x97\x04\xed\x00\x01\x12\ +\xc0\xf9\xff\x01\xef-\x02\x09\x91\xfe\xfa\xff\x01\xf98\xf0\ +\x00\x00r\xfb\xff\x02\xc9E\x02\xfa\x00\x02\x05C\xbf\xfa\ +\xff\x00\x86\xed\x00\x01\x14\xc2\xf9\xff\x01\xf1-\x02\x09\x90\ +\xfe\xfa\xff\x01\xfa8\xf1\x00\x01-\xf5\xfc\xff\x01\xa3\x09\ +\xf6\x00\x02\x02s\xfc\xfc\xff\x01\xee\x16\xee\x00\x01\x15\xc1\ +\xf9\xff\x01\xef-\x01\x09\x92\xf9\xff\x01\xf97\xf1\x00\x00\ +\xb6\xfc\xff\x01\xa8\x06\xf3\x00\x01C\xe7\xfc\xff\x00\xa0\xee\ +\x00\x01\x15\xc2\xf9\xff\x01\xef,\x02\x09\x91\xfe\xfa\xff\x01\ +\xf98\xf2\x00\x01\x1b\xf4\xfd\xff\x01\xe3\x13\xf1\x00\x01:\ +\xfa\xfd\xff\x01\xf9%\xef\x00\x01\x14\xc2\xf9\xff\x01\xf0/\ +\x01\x09\x90\xf9\xff\x01\xfa7\xf2\x00\x00\x82\xfc\xff\x00g\ +\xef\x00\x00\x8f\xfc\xff\x00\x87\xef\x00\x01\x15\xc2\xf9\xff\x01\ +\xef-\x01\x09\x91\xf9\xff\x01\xf87\xf3\x00\x01\x12\xea\xfd\ +\xff\x01\xe9\x0d\xef\x00\x01\x08\xd8\xfd\xff\x01\xdf\x0a\xf0\x00\ +\x02\x14\xc1\xfe\xfa\xff\x01\xef/\x02\x08\x90\xfe\xfa\xff\x01\ +\xf98\xf3\x00\x00n\xfc\xff\x00\xad\xed\x00\x00o\xfd\xff\ +\x01\xfd0\xf0\x00\x01\x15\xc2\xf9\xff\x01\xf0-\x02\x09\x91\ +\xfe\xfa\xff\x01\xf97\xf4\x00\x01\x0f\xe5\xfd\xff\x01\xfe;\ +\xed\x00\x01\x17\xee\xfd\xff\x00T\xf0\x00\x01\x14\xc3\xf9\xff\ +\x01\xf0/\x02\x09\x91\xfe\xfa\xff\x01\xfa7\xf4\x00\x01(\ +\xef\xfd\xff\x01\xc2\x02\xec\x00\x00\xcb\xfd\xff\x00c\xf0\x00\ +\x01\x15\xc1\xf9\xff\x01\xf1-\x02\x09\x92\xfe\xfa\xff\x01\xf8\ +8\xf4\x00\x06\x01\x1bP\xc0\xff\xffI\xeb\x00\x00\xb0\xfd\ +\xff\x00m\xf0\x00\x01\x15\xc2\xf9\xff\x01\xf0.\x01\x09\x90\ +\xf9\xff\x01\xf98\xf0\x00\x02C\x87\x07\xeb\x00\x00\xb6\xfd\ +\xff\x00m\xf0\x00\x01\x15\xc2\xf9\xff\x01\xf0.\x02\x09\x90\ +\xfe\xfa\xff\x01\xf99\xd8\x00\x01\x09\xda\xfd\xff\x00b\xf0\ +\x00\x02\x15\xc3\xfe\xfa\xff\x01\xef-\x01\x08\x91\xf9\xff\x01\ +\xf97\xd8\x00\x018\xfe\xfd\xff\x00Q\xf0\x00\x02\x14\xc2\ +\xfe\xfa\xff\x01\xf0/\x02\x09\x91\xfe\xfa\xff\x01\xf98\xd8\ +\x00\x00\x9b\xfd\xff\x01\xfc2\xf0\x00\x01\x14\xc1\xf9\xff\x01\ +\xf0.\x02\x09\x91\xfe\xfa\xff\x01\xf98\xd9\x00\x01*\xf8\ +\xfd\xff\x01\xd5\x06\xf0\x00\x01\x14\xc1\xf9\xff\x01\xf0.\x02\ +\x09\x91\xfe\xfa\xff\x01\xf99\xd9\x00\x00\x8e\xfc\xff\x00\x80\ +\xef\x00\x01\x14\xc2\xf9\xff\x01\xf1.\x02\x09\x92\xfe\xfa\xff\ +\x01\xf99\xda\x00\x01\x07\xdf\xfd\xff\x01\xe5\x19\xef\x00\x01\ +\x15\xc1\xf9\xff\x01\xf0/\x02\x08\x93\xfe\xfa\xff\x01\xf98\ +\xda\x00\x01B\xfe\xfd\xff\x04\xef\xc8\xca\xad^\xf2\x00\x02\ +\x15\xc1\xfe\xfa\xff\x01\xef.\x02\x09\x91\xfe\xfa\xff\x01\xf9\ +8\xe0\x00\x06\x0c\x22Cg\x84\x9c\xda\xf7\xff\x01\xb9(\ +\xf4\x00\x01\x14\xc1\xf9\xff\x01\xef-\x01\x08\x8f\xf9\xff\x01\ +\xf99\xe6\x00\x07\x0d(Hn\x97\xbb\xde\xf4\xf1\xff\x01\ +\xd1\x0a\xf5\x00\x02\x15\xbf\xfe\xfa\xff\x01\xee.\x02\x09\x92\ +\xfe\xfa\xff\x01\xf89\xef\x00\x0a\x02\x0e\x1d:Pf~\ +\x9b\xc2\xdf\xf8\xea\xff\x00Q\xf5\x00\x01\x14\xc2\xf9\xff\x01\ +\xef.\x01\x09\x91\xf9\xff\x01\xf98\xf4\x00\x07\x059]\ +\x88\xaf\xd1\xe3\xee\xe2\xff\x00\x9f\xf5\x00\x01\x14\xc1\xf9\xff\ +\x01\xf0-\x02\x09\x90\xfe\xfa\xff\x01\xf98\xf6\x00\x02\x10\ +{\xd0\xe3\xff\x03\xfa\xf0\xdc\xed\xfd\xff\x00\xc1\xf5\x00\x01\ +\x14\xc1\xf9\xff\x01\xef,\x02\x09\x90\xfe\xfa\xff\x01\xf97\ +\xf7\x00\x01$\xd4\xe8\xff\x0a\xfb\xe5\xc7\x9fyR8)\ +\x18\x08\x9d\xfd\xff\x01\xe2\x0f\xf6\x00\x01\x15\xc2\xf9\xff\x01\ +\xf1.\x01\x09\x91\xf9\xff\x01\xf98\xf8\x00\x01\x05\xc8\xed\ +\xff\x07\xf7\xe2\xc0\x9crJ+\x0d\xf9\x00\x00\x8a\xfd\xff\ +\x01\xf8&\xf6\x00\x01\x14\xc3\xf9\xff\x01\xf1.\x02\x09\x92\ +\xfe\xfa\xff\x01\xf99\xf8\x00\x00`\xf4\xff\x09\xfd\xea\xcd\ +\xa7\x82jXC#\x0c\xf3\x00\x00k\xfc\xff\x00J\xf6\ +\x00\x01\x13\xc2\xf9\xff\x01\xf0.\x02\x09\x91\xfe\xfa\xff\x01\ +\xf97\xf8\x00\x00\xaf\xfa\xff\x07\xfb\xe6\xc6\xa3wR/\ +\x11\xeb\x00\x00D\xfc\xff\x00p\xf6\x00\x02\x15\xc2\xfe\xfa\ +\xff\x01\xf0.\x02\x09\x91\xfe\xfa\xff\x01\xf98\xf8\x00\x00\ +\xc1\xfd\xff\x04\xeaxJ+\x0f\xe5\x00\x01#\xf8\xfd\xff\ +\x00\x97\xf6\x00\x01\x14\xc1\xf9\xff\x01\xef.\x02\x09\x91\xfe\ +\xfa\xff\x01\xf88\xf8\x00\x00\xa1\xfd\xff\x01\xe5\x03\xe2\x00\ +\x01\x08\xdf\xfd\xff\x00\xbe\xf6\x00\x01\x15\xc1\xf9\xff\x01\xef\ +-\x02\x09\x91\xfe\xfa\xff\x01\xf97\xf8\x00\x00y\xfd\xff\ +\x01\xfc.\xe1\x00\x00\xc0\xfd\xff\x01\xdd\x0a\xf7\x00\x02\x14\ +\xc2\xfe\xfa\xff\x01\xf1.\x02\x09\x91\xfe\xfa\xff\x01\xf98\ +\xf8\x00\x00M\xfc\xff\x00T\xf3\x00\x05?\x95\xb6\xa2f\ +\x0b\xf5\x00\x00\x96\xfd\xff\x01\xf7&\xf7\x00\x02\x15\xc2\xfe\ +\xfa\xff\x01\xef.\x02\x09\x90\xfe\xfa\xff\x01\xf98\xf8\x00\ +\x01.\xfd\xfd\xff\x00w\xf5\x00\x02\x08\x97\xfd\xfd\xff\x01\ +\xc5#\xf6\x00\x00r\xfc\xff\x00C\xf7\x00\x01\x14\xc1\xf9\ +\xff\x01\xef.\x02\x09\x92\xfe\xfa\xff\x01\xf97\xf8\x00\x01\ +\x10\xe8\xfd\xff\x00\xa2\xf6\x00\x01\x01\xaf\xfa\xff\x01\xe11\ +\xf7\x00\x00H\xfc\xff\x00i\xf7\x00\x01\x15\xc2\xf9\xff\x01\ +\xf0.\x01\x09\x91\xf9\xff\x01\xf98\xf7\x00\x00\xcb\xfd\xff\ +\x00\xc7\xf6\x00\x00?\xf8\xff\x00\xb7\xf7\x00\x01'\xfa\xfd\ +\xff\x00\x87\xf7\x00\x01\x15\xc1\xf9\xff\x01\xef.\x01\x09\x91\ +\xf9\xff\x01\xf97\xf7\x00\x00\xa7\xfd\xff\x01\xe3\x0d\xf7\x00\ +\x00\xa0\xf8\xff\x01\xe6\x0b\xf8\x00\x01\x0c\xe4\xfd\xff\x00\x9d\ +\xf7\x00\x01\x14\xc0\xf9\xff\x01\xef-\x02\x09\x91\xfe\xfa\xff\ +\x01\xf98\xf7\x00\x00|\xfd\xff\x01\xf5\x1f\xf7\x00\x00\xcb\ +\xf8\xff\x01\xf7\x22\xf7\x00\x00\xc3\xfd\xff\x00\xb3\xf7\x00\x01\ +\x13\xc0\xf9\xff\x01\xf0.\x02\x09\x91\xfe\xfa\xff\x01\xf97\ +\xf7\x00\x00W\xfd\xff\x01\xfc.\xf7\x00\x00\xc0\xf8\xff\x01\ +\xf3\x1e\xf7\x00\x00\xa0\xfd\xff\x01\xcb\x01\xf8\x00\x01\x14\xc1\ +\xf9\xff\x01\xf1.\x01\x09\x91\xf9\xff\x01\xfa8\xf7\x00\x01\ +0\xfd\xfd\xff\x00A\xf7\x00\x00\x82\xf8\xff\x01\xdc\x05\xf7\ +\x00\x00t\xfd\xff\x01\xe8\x14\xf8\x00\x01\x15\xc1\xf9\xff\x01\ +\xef-\x02\x09\x91\xfe\xfa\xff\x01\xf97\xf7\x00\x01\x14\xee\ +\xfd\xff\x00^\xf7\x00\x01$\xf9\xf9\xff\x00\x90\xf6\x00\x00\ +N\xfd\xff\x01\xfb-\xf8\x00\x01\x13\xc2\xf9\xff\x01\xf0-\ +\x02\x09\x91\xfe\xfa\xff\x01\xf99\xf7\x00\x01\x02\xcd\xfd\xff\ +\x00\x8a\xf6\x00\x00k\xfb\xff\x02\xfe\xa1\x0a\xf6\x00\x005\ +\xfc\xff\x00T\xf8\x00\x02\x15\xc2\xfe\xfa\xff\x01\xf1.\x01\ +\x09\x92\xf9\xff\x01\xf98\xf6\x00\x00\xb4\xfd\xff\x00\xae\xf5\ +\x00\x01P\xd7\xfd\xff\x01\xfa\x22\xf5\x00\x01(\xfa\xfd\xff\ +\x00x\xf8\x00\x01\x15\xc2\xf9\xff\x01\xf0-\x02\x09\x91\xfe\ +\xfa\xff\x01\xf86\xf6\x00\x00\xa1\xfd\xff\x01\xd1\x04\xf5\x00\ +\x00T\xfc\xff\x00H\xf5\x00\x01\x18\xf0\xfd\xff\x00\x9f\xf8\ +\x00\x02\x14\xc1\xfe\xfa\xff\x01\xf0-\x02\x09\x91\xfe\xfa\xff\ +\x01\xf98\xf6\x00\x00\x8c\xfd\xff\x01\xee\x18\xf5\x00\x00=\ +\xfc\xff\x00s\xf5\x00\x01\x06\xda\xfd\xff\x00\xc6\xf8\x00\x01\ +\x14\xc2\xf9\xff\x01\xf0.\x02\x09\x92\xfe\xfa\xff\x01\xf86\ +\xf6\x00\x00r\xfd\xff\x01\xfe4\xf5\x00\x01%\xf7\xfd\xff\ +\x00\x98\xf4\x00\x00\xba\xfd\xff\x01\xe3\x0f\xf9\x00\x01\x14\xc1\ +\xf9\xff\x01\xf0/\x01\x09\x91\xf9\xff\x01\xf98\xf6\x00\x00\ +F\xfc\xff\x00[\xf5\x00\x01\x08\xdc\xfd\xff\x00\x90\xf4\x00\ +\x00\x8f\xfd\xff\x01\xfb,\xf9\x00\x02\x15\xc1\xfe\xfa\xff\x01\ +\xf0.\x02\x09\x91\xfe\xfa\xff\x01\xf88\xf6\x00\x01'\xfa\ +\xfd\xff\x00\x80\xf4\x00\x00t\xfe\xff\x01\xee-\xf4\x00\x00\ +j\xfc\xff\x00K\xf9\x00\x01\x15\xc2\xf9\xff\x01\xf1-\x01\ +\x09\x91\xf9\xff\x01\xfa8\xf6\x00\x01\x0b\xe2\xfd\xff\x00\xab\ +\xf3\x00\x03D\x97\x8a)\xf3\x00\x00@\xfc\xff\x00u\xf9\ +\x00\x01\x13\xc2\xf9\xff\x01\xf0.\x01\x08\x90\xf9\xff\x01\xf9\ +8\xf5\x00\x00\xc4\xfd\xff\x01\xcd\x01\xe2\x00\x01 \xf7\xfd\ +\xff\x00\x9a\xf9\x00\x02\x14\xc2\xfe\xfa\xff\x01\xf0.\x01\x09\ +\x91\xf9\xff\x01\xf98\xf5\x00\x00\x9c\xfd\xff\x01\xeb\x15\xe1\ +\x00\x00\xd8\xfd\xff\x00\xbb\xf9\x00\x01\x13\xc2\xf9\xff\x01\xf0\ +.\x02\x08\x91\xfe\xfa\xff\x01\xf97\xf5\x00\x00t\xfd\xff\ +\x01\xfe1\xe4\x00\x03\x07\x1c=\xd4\xfd\xff\x00\xce\xf9\x00\ +\x02\x15\xc0\xfe\xfa\xff\x01\xef-\x02\x09\x91\xfe\xfa\xff\x01\ +\xf89\xf5\x00\x00N\xfc\xff\x00S\xec\x00\x09\x02\x12\x22\ +3Ei\x8f\xb7\xd7\xf1\xfb\xff\x00\xc9\xf9\x00\x01\x14\xc2\ +\xf9\xff\x01\xef-\x01\x09\x90\xf9\xff\x01\xf96\xf5\x00\x01\ +)\xfb\xfd\xff\x00z\xf2\x00\x08\x03\x1a7Z\x85\xa8\xd0\ +\xe9\xf6\xf4\xff\x00\x8b\xf9\x00\x01\x14\xc0\xf9\xff\x01\xf1,\ +\x01\x09\x90\xf9\xff\x01\xf97\xf5\x00\x01\x0f\xe8\xfd\xff\x00\ +\x92\xf9\x00\x08\x03\x0d\x1d\x0a\x0a \x0a icon / Prefer\ +ences / Global\x0a Created with Sk\ +etch.\x0a \ + \x0a \x0a \ +\x0a\x0a\ +\x00\x00\x09\xaf\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22?>\x0a\x0a \x0a icon / Prefer\ +ences / Camera\x0a Created with Sk\ +etch.\x0a \ + \x0a \x0a \ + \ +\x0a \x0a \ + \x0a\x0a\ +\x00\x00\x05\xc2\ +<\ +svg width=\x2224\x22 h\ +eight=\x2224\x22 viewB\ +ox=\x220 0 24 24\x22 f\ +ill=\x22none\x22 xmlns\ +=\x22http://www.w3.\ +org/2000/svg\x22>\x0a<\ +path d=\x22M21.4629\ + 11.2764C20.6447\ + 10.508 19.5748 \ +10.0719 18.4419 \ +10.0719C17.8965 \ +10.0719 17.351 1\ +0.1758 16.8475 1\ +0.3834C16.5748 9\ +.26204 15.9664 8\ +.2237 15.1063 7.\ +37226C13.8685 6.\ +16779 12.6717 5.\ +47607 10.4147 5.\ +47607C7.92095 5.\ +47607 6.586 6.16\ +779 5.32725 7.37\ +226C4.08949 8.57\ +673 3.30673 10.1\ +907 3.30673 11.8\ +935C3.30673 12.1\ +635 3.32771 12.4\ +335 3.34869 12.7\ +035C2.84519 12.8\ +281 2.49509 13.0\ +831 2.13844 13.4\ +362C1.57201 13.9\ +761 1.25732 14.7\ +029 1.25732 15.4\ +713C1.25732 17.1\ +534 2.66292 18.5\ +032 4.3832 18.50\ +32L18.2741 18.52\ +4C20.7286 18.524\ + 22.7426 16.5927\ + 22.7426 14.2045\ +C22.7217 13.1039\ + 22.2811 12.0656\ + 21.4629 11.2764\ +ZM17.2975 16.665\ +9L4.65419 16.686\ +7C3.62622 16.686\ +7 3.45969 16.038\ +7 3.37771 15.643\ +7C3.30673 15.301\ +7 3.37861 14.788\ +2 3.53455 14.579\ +9C3.74825 14.294\ +4 4.10093 14.164\ +9 4.5273 14.1216\ +C4.76182 14.0979\ + 5.1687 14.0552 \ +5.32721 13.8355C\ +5.43211 13.6901 \ +5.47406 13.5032 \ +5.45308 13.3163C\ +5.36917 12.901 5\ +.32721 12.5272 5\ +.32721 12.1119C5\ +.32721 10.7413 5\ +.6315 9.73925 6.\ +63849 8.76321C7.\ +64549 7.78717 8.\ +98815 7.24724 10\ +.4147 7.24724C11\ +.8413 7.24724 12\ +.9769 7.56395 13\ +.9839 8.53999C14\ +.865 9.39143 15.\ +3895 10.4921 15.\ +5154 11.655C15.5\ +363 11.8627 15.6\ +622 12.0703 15.8\ +72 12.1534C16.06\ +08 12.2365 16.31\ +26 12.2365 16.48\ +04 12.1119C17.63\ +42 11.3643 18.84\ +8 11.1981 19.876\ + 12.1742C20.4424\ + 12.7141 20.7426\ + 13.4362 20.7426\ + 14.2045C20.7426\ + 15.9074 19.0808\ + 16.6659 17.2975\ + 16.6659Z\x22 fill=\ +\x22white\x22/>\x0a\ +\x0a\ +\x00\x00\x00\xab\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x10\x00\x00\x00\x0d\x08\x06\x00\x00\x00\xa0\xbb\xee$\ +\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\ +\x04gAMA\x00\x00\xb1\x8f\x0b\xfca\x05\x00\x00\x00\ +UIDAT8Oc\xfc\xff\xff?\x03%\x80\x09\ +J\x93\x0d\xf0\x1a\xd0\xd8\xd8H\xd0y\x04]@\xc8\x10\ +\x940\xc0\xa7\xb8\xbe\xbe\x9e\x11\xcaD\x01D\x87\x01.\ +\xc3I\x0aDl\x86\x90d\x006o\x10m\x00\xae0\ +\xc0\x9b\x90`N\xc6\xa5\x19\x04\x08\xba\x00\x9ff\x10\x18\ +\xe8\xa4\xcc\xc0\x00\x00\x9d\xda\x22\x8d\x12\xa2\xae,\x00\x00\ +\x00\x00IEND\xaeB`\x82\ +\x00\x00\x05p\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22?>\x0a\x0a \x0a icon / Prefer\ +ences / viewport\ +\x0a Created with \ +Sketch.\x0a \ + \x0a \ + \ +\x0a \x0a \x0a \ + \x0a\x0a\ +\x00\x00\x00\xca\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x10\x00\x00\x00\x0d\x08\x06\x00\x00\x00\xa0\xbb\xee$\ +\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\ +\x04gAMA\x00\x00\xb1\x8f\x0b\xfca\x05\x00\x00\x00\ +\x09pHYs\x00\x00\x0e\xc3\x00\x00\x0e\xc3\x01\xc7o\ +\xa8d\x00\x00\x00_IDAT8O\xc5\x91\xc1\x0e\ +\xc0 \x08C\xc1\x1f\x07\xbe\x9c\x05'\x86\xc4\xb9\x89\x1e\ +\xf6.r\xa1\xd2\x16U\x15\x0c\x11\xb9\x87\x07\x88\x08\xdb\ +8\x80\xcc<]\x5c\xa1\xb4w\x9b\xff\x05z\x88\x19b\ +\xe0\xe9\x10\xbd\x11\x17I[\xf0E\x17*o\x1d\xcf\x88\ +\x16\x8eB\xb4\xcf\xab\xc0\xc9\x15\xfd\x82\x1d\x11c\xa81\ +\xfa\xfb\x06\xe0\x02\xfbk*\x0b\x22\xb70[\x00\x00\x00\ +\x00IEND\xaeB`\x82\ +\x00\x00\x05\xfe\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22?>\x0a\x0a Icons / Editor\ + / EMFX / Motion\ +\x0a \x0a \x0a \ + \x0a \ + \x0a\x0a\ +\x00\x00\x00\xa0\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x10\x00\x00\x00\x0d\x08\x06\x00\x00\x00\xa0\xbb\xee$\ +\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\ +\x04gAMA\x00\x00\xb1\x8f\x0b\xfca\x05\x00\x00\x00\ +\x09pHYs\x00\x00\x0e\xc3\x00\x00\x0e\xc3\x01\xc7o\ +\xa8d\x00\x00\x005IDAT8Oclhh\ +\xf8\xcf\x80\x06\xea\xeb\xeb\x19\xa1L\x82\x80\x09J\x93\x0d\ +\xb0\xba\x80\x18\x00s%\xd9.hll\x04[L\xb1\ +\x17F\x0d\x185\x80\x81\x81\x81\x01\x00\xc0\x1c\x0a\x95\xd5\ +0\x97g\x00\x00\x00\x00IEND\xaeB`\x82\ +\x00\x00\x11\xbc\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22?>\x0a\x0a \x0a icon / Prefer\ +ences / Debug\x0a \ +Created with Ske\ +tch.\x0a \ +\x0a \x0a \ + \x0a \ + \x0a <\ +/g>\x0a\x0a\ +\x00\x00\x125\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22?>\x0a\x0a \x0a icon / Prefer\ +ences / Experime\ +ntal\x0a \ + Created w\ +ith Sketch.\x0a \ +\x0a \x0a \x0a\x0a\ +\x00\x00\x04\x0e\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22?>\x0a\x0a \x0a icon / Prefer\ +ences / Files\x0a \ +Created with Ske\ +tch.\x0a \ +\x0a \x0a \ + \x0a\x0a\ +\x00\x00\x03`\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22?>\x0a\x0a \x0a icon / Prefer\ +ences / Gizmos\x0a Created with Sk\ +etch.\x0a \ + \x0a \x0a \ + \x0a\x0a\ +\x00\x00\x00[\ +\x00\ +\x00\x01Fx\x9c\x8d\x8c1\x0a\x800\x10\x04\xe7\xacD\ +P;\xeb\x94\x96>\xc1\xa7\xf9d\xad\x05\xcf\x8d\x88B\ +\xc0\x98Y\x86\x83cY\xa80B\x80V\x99\x0c\x06`\ +\x94z1KS\x22\x0b/\xd5m\xc4\xdd)\xa2\x93\xcd\ +\xb7\xfd~Pk5\xde\x5c\xef\xdaI\xf0\x12\xb6\xbc+\ +\xf6\xf8\xd7M9\x01\x0cb\x81\xee\ +\x00\x00\x00[\ +\x00\ +\x00\x01Fx\x9c\xc5\xc81\x0e@@\x18D\xe1\xf9W\ +!**\xad-\x95n\xc0\xcd\xec\xd1\x1c\xc5\x11\x94\x0a\ +\xf1\xec\xc6\x8a\x0bH|\x93\xd7\x8c\xe4d\xf2^jT\ +i0\xa9\x95\xd4\xc7\xe2\xa5)fqI\xd0\xcb\xe5\x12\ +@\x7f\xe3q\xcep\x8c\xb0w\xb0\xd5\xb0\x96\xb0\x14\x10\ +\xec\xfe\xbe.\xbb\x00\x9d\x16jC\ +\x00\x00\x01F\ +\x00\ +\x00\x02\x00\x01\x00 \x00\x00\x0c\x00\x04\x000\x01\x00\ +\x00\x16\x00\x00\x00(\x00\x00\x00 \x00\x00\x00@\x00\x00\ +\x00\x01\x00\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x07\xf8\x00\x00\x07\xf8\x00\x00\x0f\xfc\x00\x00\x0f\xfc\ +\x00\x00\x1f\xfc\x00\x00\x1f\xfe\x00\x00?\xfe\x00\x00/\xfe\ +\x00\x00o\xfe\x00\x00\xef\xfe\x00\x00\xcf\xf6\x00\x00\x0d\xb6\ +\x00\x00\x0d\xb4\x00\x00\x0d\xb0\x00\x00\x0d\x80\x00\x00\x0c\x00\ +\x00\x00\x0c\x00\x00\x00\x0c\x00\x00\x00\x0c\x00\x00\x00\x0c\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf0\x03\ +\xff\xff\xf0\x03\xff\xff\xf0\x03\xff\xff\xe0\x01\xff\xff\xe0\x01\ +\xff\xff\xc0\x01\xff\xff\xc0\x00\xff\xff\x80\x00\xff\xff\x80\x00\ +\xff\xff\x00\x00\xff\xfe\x00\x00\xff\xfe\x00\x00\xff\xfe \x00\ +\xff\xff\xe0\x01\xff\xff\xe0\x03\xff\xff\xe0\x0f\xff\xff\xe0\x7f\ +\xff\xff\xe1\xff\xff\xff\xe1\xff\xff\xff\xe1\xff\xff\xff\xe1\xff\ +\xff\xff\xf3\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\ +\x00\x00\x00\xa7\ +\x00\ +\x00\x0c\xbex\x9c\xed\x921\x0a\xc20\x18\x85_t\xe8\ +Rp\x13\xc7\x8e=\x867\xf0J\x1e\xc1cx\x0c\xc1\ +\x8btsut(<_\x8bC1\x12K\x93\xdfA\ +\xfe\x0f\x1e\x09\x09\xf9^\x02\x01V\x08h\x1a\x8c\xe3\xb9\ +\x06\xb6\x00ZEK\xd8+\x01;\x8c\xd4p\x1c\xc7q\ +\x9c?\x85\x11\xa6\xf2\x82\xfe\x8f\xf2R\x15\x09\xf9\x0f\xfc\ +\x99\x15_\xe59\xfe\xa9\xc1\xce?\xe7!\x8b+\xe2\xb7\ +\xbci\x8b\xf8c\xdbt\x92}\xf7\x94\xbf\xa0\xdc\x08k\ +\xbf\x11\xe9\x0f9\x8f~C>*\xf2\xaetk\xf22\ +$\x90G\x05C\xd4rR\xba\xf0\xda?\x90W\x9d\xbb\ +)O\x85i\xaa%\ +\x00\x00\x01F\ +\x00\ +\x00\x02\x00\x01\x00 \x00\x00\x06\x00\x06\x000\x01\x00\ +\x00\x16\x00\x00\x00(\x00\x00\x00 \x00\x00\x00@\x00\x00\ +\x00\x01\x00\x01\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\ +\x00\xff\xff\xff\x00\x000\x00\x00\x000\x00\x00\x000\x00\ +\x00\x01\xfe\x00\x00\x01\xfe\x00\x00\x000\x00\x00\x000\x00\ +\x00\x001\x80\x00\x00\x01\x80\x00\x00\x03\x00\x00\x00\x03\x00\ +\x00\x00\x06\x00\x00\x00F\x00\x00\x00l\x00\x00\x00|\x00\ +\x00\x00\x7f\x80\x00\x00\x7f\x00\x00\x00~\x00\x00\x00|\x00\ +\x00\x00x\x00\x00\x00p\x00\x00?\xe0\x00\x00 \x00\ +\x00 \x00\x00 \x00\x00 \x00\x00 \x00\ +\x00 \x00\x00 \x00\x00?\xe0\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\xff\xcf\xff\xff\xff\xcf\xff\xff\xff\xcf\xff\ +\xff\xfe\x01\xff\xff\xfe\x01\xff\xff\xff\xcf\xff\xff\xff\xce\x7f\ +\xff\xff\xcc?\xff\xff\xfc?\xff\xff\xf8\x7f\xff\xffx\x7f\ +\xff\xff0\xff\xff\xff\x10\xff\xff\xff\x01\xff\xff\xff\x00\x1f\ +\xff\xff\x00?\xff\xff\x00\x7f\xff\xff\x00\xff\xff\xff\x01\xff\ +\xff\xff\x03\xff\xff\x80\x07\xff\xff\x80\x0f\xff\xff\x9f\xcf\xff\ +\xff\x9f\xcf\xff\xff\x9f\xcf\xff\xff\x9f\xcf\xff\xff\x9f\xcf\xff\ +\xff\x9f\xcf\xff\xff\x9f\xcf\xff\xff\x80\x0f\xff\xff\x80\x0f\xff\ +\xff\xff\xff\xff\xff\ +\x00\x00\x00`\ +\x00\ +\x00\x01Fx\x9cc``b`dPP``\xe0\ +f\xe0e0`d`\x10c``\xd0\x00b\xa0\x10\ +\x83\x03\x103\x02!\x0840 \x00\x13\x14\x83\xc0\xff\ +\xff\xff\x19H\x025@\x1c\x82\x03\x0b\xe0\x91\xab\xc1m\ +\xe4\x7fR@3&\xfe\xdd\xbc\xff\xff\xe7\xe6\xf9\xff\x1f\ +0\xf0\x83i\x10\x1f\x9b:\x5c\x00\x00\x81\xb3~\xf0\ +\x00\x00\x01F\ +\x00\ +\x00\x02\x00\x01\x00 \x00\x00\x0f\x00\x0f\x000\x01\x00\ +\x00\x16\x00\x00\x00(\x00\x00\x00 \x00\x00\x00@\x00\x00\ +\x00\x01\x00\x01\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\ +\x00\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x03\x80\x00\x00\x02\x80\x00\x00\x02\x80\ +\x00\x00\x02\x80\x00\x00\x02\x80\x00\x00\x04@\x00\x00\x0c`\ +\x00\x03\xf0\x1f\x80\x02\x01\x00\x80\x03\xf0\x1f\x80\x00\x0c`\ +\x00\x00\x04@\x00\x00\x02\x80\x00\x00\x02\x80\x00\x00\x02\x80\ +\x00\x00\x02\x80\x00\x00\x03\x80\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\ +\xff\xff\xfe\xff\xff\xff\xfc\x7f\xff\xff\xfc\x7f\xff\xff\xfc\x7f\ +\xff\xff\xfc\x7f\xff\xff\xfc\x7f\xff\xff\xf9?\xff\xff\xf1\x1f\ +\xff\xfc\x03\x80\x7f\xf0\x1e\xf0\x1f\xfc\x03\x80\x7f\xff\xf1\x1f\ +\xff\xff\xf9?\xff\xff\xfc\x7f\xff\xff\xfc\x7f\xff\xff\xfc\x7f\ +\xff\xff\xfc\x7f\xff\xff\xfc\x7f\xff\xff\xfe\xff\xff\xff\xfe\xff\ +\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\ +\x00\x00\x01F\ +\x00\ +\x00\x02\x00\x01\x00 \x00\x00\x10\x00\x0d\x000\x01\x00\ +\x00\x16\x00\x00\x00(\x00\x00\x00 \x00\x00\x00@\x00\x00\ +\x00\x01\x00\x01\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\ +\x00\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\ + \x01\x00\x00@\x00\xc0\x01\x80\x008\x0e\x00\x00\x07\xf0\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf9\xff\xff\xcf\xf8\xff\xff\ +\x8f\xfc?\xfe\x1f\xfe\x07\xe0?\xff\x00\x00\x7f\xff\xc0\x01\ +\xff\xff\xf8\x0f\xff\xff\xff\xff\xff\xff\xff\x7f\xff\xff\xfe?\ +\xff\xff\xff\x7f\xff\xff\xff\x7f\xff\xff\xff\x7f\xff\xff\xfe?\ +\xff\xff\xff\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\ +\x00\x00\x00X\ +\x00\ +\x00\x01Fx\x9c\xc5\xcd1\x0a\x800\x0cF\xe1\x97.\ +\xe2\xa4\x93k;:z\x83z\xb3\xf6\xc8\xbdA\xfc\x0b\ +\x05A\x9c\x5c|\xe1#\x90\xa1\x85\x80\x91\x12\xac\xcc\x1c\ +\x06\x1b\xb0\x8bN\x9cb\x9a^\xe5.\x0c=w\xe7\xef\ +\xfc\xa5V>+\x92\x1bDYd\x1a;\xea\xd9,\xe5\ +\xf9\xd7\x05'\x93i\xe6\ +\x00\x00\x01F\ +\x00\ +\x00\x02\x00\x01\x00 \x00\x00\x03\x00\x03\x000\x01\x00\ +\x00\x16\x00\x00\x00(\x00\x00\x00 \x00\x00\x00@\x00\x00\ +\x00\x01\x00\x01\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\ +\x00\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x1e\x00\x00\x00\x1e\x00\ +\x00\x00\x1e\x00\x00\x00\x1e\x00\x00\x18\x1e\x00\x00\x14\x0c\x00\ +\x00\x12\x00\x00\x00\x11\xe0\x00\x00\x10\x10\x00\x00\x10 \x00\ +\x00\x10@\x00\x00\x10\x80\x00\x00\x11\x00\x00\x00\x12\x00\x00\ +\x00\x14\x00\x00\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xf3\xff\xff\xff\xe1\xff\xff\xff\xc0\xff\xff\xff\xc0\xff\ +\xff\xff\xc0\xff\xff\xff\xc0\xff\xff\xe7\xc0\xff\xff\xe3\xe1\xbf\ +\xff\xe1\xf3\xbf\xff\xe0\x1e\x0f\xff\xe0\x0f\xbf\xff\xe0\x1f\xbf\ +\xff\xe0?\xff\xff\xe0\x7f\xff\xff\xe0\xff\xff\xff\xe1\xff\xff\ +\xff\xe3\xff\xff\xff\xe7\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\ +\x00\x00\x01F\ +\x00\ +\x00\x02\x00\x01\x00 \x00\x00\x00\x00\x18\x000\x01\x00\ +\x00\x16\x00\x00\x00(\x00\x00\x00 \x00\x00\x00@\x00\x00\ +\x00\x01\x00\x01\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\ +\x00\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\xf0\x00\x00\x00\x88\x00\x00\x00\x84\x00\x00\x00\x82\x00\x00\ +\x00A\x00\x00\x00 \x80\x00\x00\x10@\x00\x00\x0b\xa0\x00\ +\x00\x05\xd6\x00\x00\x02\xe9\x00\x00\x01a\x00\x00\x00\x81\x00\ +\x00\x00@\x80\x00\x00\x80@\x00\x00\x80 \x00\x00p \ +\x00\x00\x08 \x00\x00\x04@\x00\x00\x03\x80\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\x0f\xff\xff\xff\x07\xff\xff\xff\x03\xff\xff\xff\x01\xff\xff\ +\xff\x80\xfc\xff\x0f\xc0~|c\xe0?1\xf9\xf0\x1f\x87\ +\xff\xf8\x09\xfd\xff\xfc\x00\xf8\xff\xfe\x00\xf0\x7f\xff\x00\xfd\ +\xdb\xff\x80}\xdb\xff\x00=\xdb\xff\x00\x1d\xc3\xff\x80\x1d\ +\xdb\xff\xf0\x1d\xdb\xff\xf8=\xdb\xff\xfcp\x7f\xff\xff\xf8\ +\xff\xff\xff\xfd\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\ +\x00\x00\x01F\ +\x00\ +\x00\x02\x00\x01\x00 \x00\x00\x01\x00\x01\x000\x01\x00\ +\x00\x16\x00\x00\x00(\x00\x00\x00 \x00\x00\x00@\x00\x00\ +\x00\x01\x00\x01\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\ +\x00\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x18\x00\x00\x00\x18\x00\x00\x00\x18\x00\x00\x00\xff\x00\x00\ +\x00\xff\x00\x00\x00\x18\x00\x00\x00\x18\x00\x00\x00\x18\xc0\x00\ +\x00\x00\xc0\x00\x00\x01\x80\x00\x00\x01\x80\x00\x00\x03\x00\x00\ +\x00#\x00\x00\x006\x00\x00\x00>\x00\x00\x00?\xc0\x00\ +\x00?\x80\x00\x00?\x00\x00\x00>\x00\x00\x00<\x00\x00\ +\x008\x00\x00\x000\x00\x00\x00 \x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xe7\xff\xff\xff\xe7\xff\xff\xff\xe7\xff\xff\xff\x00\xff\xff\ +\xff\x00\xff\xff\xff\xe7\xff\xff\xff\xe7?\xff\xff\xe6\x1f\xff\ +\xff\xfe\x1f\xff\xff\xfc?\xff\xff\xbc?\xff\xff\x98\x7f\xff\ +\xff\x88\x7f\xff\xff\x80\xff\xff\xff\x80\x0f\xff\xff\x80\x1f\xff\ +\xff\x80?\xff\xff\x80\x7f\xff\xff\x80\xff\xff\xff\x81\xff\xff\ +\xff\x83\xff\xff\xff\x87\xff\xff\xff\x8f\xff\xff\xff\x9f\xff\xff\ +\xff\xff\xff\xff\xff\ +\x00\x00\x01F\ +\x00\ +\x00\x02\x00\x01\x00 \x00\x00\x0f\x00\x0f\x000\x01\x00\ +\x00\x16\x00\x00\x00(\x00\x00\x00 \x00\x00\x00@\x00\x00\ +\x00\x01\x00\x01\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\ +\x00\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x07\xe0\ +\x00\x00\x18\x18\x00\x00 \x04\x00\x00@\x02\x00\x00\x80\x01\ +\x00\x01\x00\x00\x80\x01\x00\x00\x80\x02\x00\x00@\x02\x00\x00\ +@\x02\x02\x00@\x02\x02\x00\x00\x02\x03\x00\x00\x02\x00\x00\ +\x00\x01\x00\x7f\x80\x01\x00 \x80\x00\x80\x10\x80\x00@\x08\ +\x80\x00 \x04\x80\x00\x18\x1a\x80\x00\x07\xe1\x80\x00\x00\x00\ +\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf8\x1f\ +\xff\xff\xe0\x07\xff\xff\xc7\xe3\xff\xff\x9f\xf9\xff\xff?\xfc\ +\xff\xfe\x7f\xfe\x7f\xfe\x7f\xfe\x7f\xfc\xff\xff?\xfc\xff\xff\ +?\xfc\xfc\x7f?\xfc\xfc\x7f\xff\xfc\xfc\x7f\xff\xfc\xff\xff\ +\xff\xfe\x7f\x80\x7f\xfe\x7f\xc0\x7f\xff?\xe0\x7f\xff\x9f\xf0\ +\x7f\xff\xc7\xe0\x7f\xff\xe0\x04\x7f\xff\xf8\x1e\x7f\xff\xff\xff\ +\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\ +\x00\x00\x01F\ +\x00\ +\x00\x02\x00\x01\x00 \x00\x00\x0f\x00\x0f\x000\x01\x00\ +\x00\x16\x00\x00\x00(\x00\x00\x00 \x00\x00\x00@\x00\x00\ +\x00\x01\x00\x01\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\ +\x00\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x80\x00\x00\x04@\ +\x00\x00\x08 \x00\x00\x02\x80\x00\x00\x22\x88\x00\x00B\x84\ +\x00\x00\x9e\xf2\x00\x01\x00\x01\x00\x00\x9e\xf2\x00\x00B\x84\ +\x00\x00\x22\x88\x00\x00\x02\x80\x00\x00\x08 \x00\x00\x04@\ +\x00\x00\x02\x80\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff\xfc\x7f\xff\xff\xf8?\ +\xff\xff\xf0\x1f\xff\xff\xfc\x7f\xff\xff\xdcw\xff\xff\x9cs\ +\xff\xff\x00\x01\xff\xfe\x00\x00\xff\xff\x00\x01\xff\xff\x9cs\ +\xff\xff\xdcw\xff\xff\xfc\x7f\xff\xff\xf0\x1f\xff\xff\xf8?\ +\xff\xff\xfc\x7f\xff\xff\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\ +\x00\x00\x01F\ +\x00\ +\x00\x02\x00\x01\x00 \x00\x00\x04\x00\x06\x000\x01\x00\ +\x00\x16\x00\x00\x00(\x00\x00\x00 \x00\x00\x00@\x00\x00\ +\x00\x01\x00\x01\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\ +\x00\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x03\xe0\x00\x00\x03\xe8\x00\x00\x03\xe0\x00\x00\x03\xe8\ +\x00\x00\x00\x08\x00\x00\x01\xf0\x00\x00\x0c\x00\x00\x00\x0c\x00\ +\x00\x00\x00\x00\x00\x00`\x00\x00\x00`\x00\x00\x00\x00\x00\ +\x00\x1f\x00\x00\x00\x13@\x00\x00\x13@\x00\x00\x1f@\x00\ +\x00\x00@\x00\x00\x0f\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf8\x0f\ +\xff\xff\xf8\x07\xff\xff\xf8\x03\xff\xff\xf8\x03\xff\xff\xf8\x03\ +\xff\xff\xf8\x03\xff\xff\xf0\x03\xff\xff\xe0\x03\xff\xff\xe1\xff\ +\xff\xff\x93\xff\xff\xff\x0f\xff\xff\xff\x0f\xff\xff\xc0\x1f\xff\ +\xff\xc0?\xff\xff\xc0\x1f\xff\xff\xc0\x1f\xff\xff\xc0\x1f\xff\ +\xff\xc0\x1f\xff\xff\xe0\x1f\xff\xff\xf0\x1f\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\ +\x00\x00\x01F\ +\x00\ +\x00\x02\x00\x01\x00 \x00\x00\x01\x00\x01\x000\x01\x00\ +\x00\x16\x00\x00\x00(\x00\x00\x00 \x00\x00\x00@\x00\x00\ +\x00\x01\x00\x01\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\ +\x00\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x00\x00\ +\x00\x0e\x00\x00\x00\x0e\x00\x00\x00\x00\x80\x00\x00\x01@\x00\ +\x00\x00\xa0\x00\x00\x00P\x00\x00\x00(\x00\x00\x00\x14\x00\ +\x00\x00\x0a\x00\x00\x00\x05\x00\x00\x00\x02\x80\x00\x00\xc1\x00\ +\x00\x00\xc0\xe0\x00\x01\x80\xe0\x00\x01\x80\xe0\x00\x03\x00\x00\ +\x00#\x00\x00\x006\x00\x00\x00>\x00\x00\x00?\xc0\x00\ +\x00?\x80\x00\x00?\x00\x00\x00>\x00\x00\x00<\x00\x00\ +\x008\x00\x00\x000\x00\x00\x00 \x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\xff\xff\xff\xff\xf1\xff\xff\xff\xe0\xff\xff\ +\xff\xe0\xff\xff\xff\xe0\xff\xff\xff\xf0\x7f\xff\xff\xfe?\xff\ +\xff\xff\x1f\xff\xff\xff\x8f\xff\xff\xff\xc7\xff\xff\xff\xe3\xff\ +\xff\xff\xf1\xff\xff\xff\xf8\xff\xff\xff<\x7f\xff\xfe\x1e\x1f\ +\xff\xfe\x1e\x0f\xff\xfc>\x0f\xff\xbc>\x0f\xff\x98\x7f\x1f\ +\xff\x88\x7f\xff\xff\x80\xff\xff\xff\x80\x0f\xff\xff\x80\x1f\xff\ +\xff\x80?\xff\xff\x80\x7f\xff\xff\x80\xff\xff\xff\x81\xff\xff\ +\xff\x83\xff\xff\xff\x87\xff\xff\xff\x8f\xff\xff\xff\x9f\xff\xff\ +\xff\xff\xff\xff\xff\ +\x00\x00\x01F\ +\x00\ +\x00\x02\x00\x01\x00 \x00\x00\x01\x00\x01\x000\x01\x00\ +\x00\x16\x00\x00\x00(\x00\x00\x00 \x00\x00\x00@\x00\x00\ +\x00\x01\x00\x01\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\ +\x00\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\x00\x00\ +\x00\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc0\x00\ +\x00\x00\xc0\x00\x00\x01\x80\x00\x00\x01\x80\x00\x00\x03\x00\x00\ +\x00#\x00\x00\x006\x00\x00\x00>\x00\x00\x00?\xc0\x00\ +\x00?\x80\x00\x00?\x00\x00\x00>\x00\x00\x00<\x00\x00\ +\x008\x00\x00\x000\x00\x00\x00 \x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\ +\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff?\xff\xff\xfe\x1f\xff\ +\xff\xfe\x1f\xff\xff\xfc?\xff\xff\xbc?\xff\xff\x98\x7f\xff\ +\xff\x88\x7f\xff\xff\x80\xff\xff\xff\x80\x0f\xff\xff\x80\x1f\xff\ +\xff\x80?\xff\xff\x80\x7f\xff\xff\x80\xff\xff\xff\x81\xff\xff\ +\xff\x83\xff\xff\xff\x87\xff\xff\xff\x8f\xff\xff\xff\x9f\xff\xff\ +\xff\xff\xff\xff\xff\ +\x00\x00\x00\xc9\ +\x00\ +\x00\x0c\xbex\x9cc``b`dPP`\x00\x83\ +\x15<\x0c\x0cb@Z\x03\x88AB\x0e@\xcc\xc8 \ +\x01\x91\xe4a\x18@`<\x93\x04D\xba\xe13\xff\xff\ +g\x98I4\x22\xd5\x0a\x88\xf9g\x88C\xa3\xe6\x8f\x9a\ +?\x10\xe6\x13\x8f\xc8\xcbb4\xcc\xbf\xc3\x0e\xfc\x07\x83\ +!j\xfe\xa8\xe31\xcd\xa4\xb5\xf9\x103i\x142\xff\ +Q\x01\xad\xcd\xa7\xbaE45\x1c\xab\xf9T4\x1c\xd3\ +|\xea\x1a\x8ef>\xd5\x0dG6\x9f\x16\x863\xd0\xa5\ +\xc0\xa1\x9d\xe1C\x1a\x80\xc2\xfd\x01\x83\xfd\xff\x03\x0c\xf2\ +\x041H\x1d\x18\x00\xa9\x7f\xf2\x10\xfc\x07\xc8\xde\x03\xc4\ +3\xea\xff\xff\xef\x00\xe2\x06\xa0t\x03?\x10\x03\xe5\x1a\ +\x80\xe2\x0dP\xb1F n\x06\xe2v \xee\x07\xe2\xf9\ +\xd0\x04\x05\x00\x85\x1b/\xe1\ +\x00\x00\x00\x5c\ +\x00\ +\x00\x01Fx\x9cc``b`dPP``\x10\ +`\xe0d0`d`\x10c``\xd0\x00b\xa0\x10\ +\x83\x03\x103\x02!\x0840 \x00\x13\x14\x83\xc0\xff\ +\xff\xff\x19\x06\x1a\xfc\x87\x81\x1f\xf2\xd4\xc7\x0d\x8c\xff\xff\ +\x1f`\xfe\xff\xff\x01\xfb\xff\xff\x1f\xf8!b\x7f\xec\xff\ +\xff\xffW\x0f\xb7\x16\x00\xb3\x96jC\ +\x00\x00\x01F\ +\x00\ +\x00\x02\x00\x01\x00 \x00\x00\x07\x00\x18\x000\x01\x00\ +\x00\x16\x00\x00\x00(\x00\x00\x00 \x00\x00\x00@\x00\x00\ +\x00\x01\x00\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x01\xe0\x00\x00\x01\x10\x00\x00\x01\x08\x00\x00\x01\x04\x00\ +\x00\x00\x82\x00\x00\x00A\x00\x00\x00 \x80\x00\x00\x17@\ +\x00\x00\x0b\xac\x00\x00\x05\xd2\x00\x00\x02\xc2\x00\x00\x01\x02\ +\x00\x00\x00\x81\x00\x00\x01\x00\x80\x00\x01\x00@\x00\x00\xe0\ +@\x00\x00\x10@\x00\x00\x08\x80\x00\x00\x07\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xfe\x1f\xff\xff\xfe\x0f\xff\xff\xfe\x07\xff\xff\xfe\x03\xff\ +\xff\xff\x01\xff\xff\xff\x80\xff\xff\xff\xc0\x7f\xff\xff\xe0?\ +\xff\xff\xf0\x13\xff\xff\xf8\x01\xff\xff\xfc\x01\xff\xff\xfe\x01\ +\xff\xff\xff\x00\xff\xff\xfe\x00\x7f\xff\xfe\x00?\xff\xff\x00\ +?\xff\xff\xe0?\xff\xff\xf0\x7f\xff\xff\xf8\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\ +\x00\x00\x01F\ +\x00\ +\x00\x02\x00\x01\x00 \x00\x00\x11\x00\x0d\x000\x01\x00\ +\x00\x16\x00\x00\x00(\x00\x00\x00 \x00\x00\x00@\x00\x00\ +\x00\x01\x00\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff?\xff\xff\xff\x1f\xff\ +\xff\xff\x8f\xff\xff\xff\xc4\x0f\xff\xff\xe1\xe7\xff\xff\xf3\xf3\ +\xff\xff\xe3\xf9\xff\xff\xef\xfd\xff\xff\xef\xfd\xff\xff\xef\xfd\ +\xff\xff\xef\xfd\xff\xff\xe7\xf9\xff\xff\xf3\xf3\xff\xff\xf9\xe7\ +\xff\xff\xfc\x0f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\ +\x00\x00\x01F\ +\x00\ +\x00\x02\x00\x01\x00 \x00\x00\x07\x00\x0e\x000\x01\x00\ +\x00\x16\x00\x00\x00(\x00\x00\x00 \x00\x00\x00@\x00\x00\ +\x00\x01\x00\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x07\xf8\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\xf7\xff\xff\xff\xe7\xff\xff\xff\xe7\ +\xff\xff\xff\x0f\xff\xff\xfe\x7f\xff\xff\xfe\x7f\xff\xfe\xfe\xff\ +\xff\xff~\xff\xff\xfe \x01\xff\xff\x00\x01\xff\xfe0\x03\ +\xff\xff~\xff\xff\xfe\xfc\x7f\xff\xff\xfc\x7f\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\ +\x00\x00\x01F\ +\x00\ +\x00\x02\x00\x01\x00 \x00\x00\x03\x00\x03\x000\x01\x00\ +\x00\x16\x00\x00\x00(\x00\x00\x00 \x00\x00\x00@\x00\x00\ +\x00\x01\x00\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x18\x00\x00\x00\x14\x00\x00\x00\x12\x00\x00\ +\x00\x11\xf8\x00\x00\x10\x08\x00\x00\x10\x10\x00\x00\x10 \x00\ +\x00\x10@\x00\x00\x10\x80\x00\x00\x11\x00\x00\x00\x12\x00\x00\ +\x00\x14\x00\x00\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\xe7\xff\xff\xff\xe3\xff\xff\xff\xe1\xff\xff\ +\xff\xe0\x07\xff\xff\xe0\x07\xff\xff\xe0\x0f\xff\xff\xe0\x1f\xff\ +\xff\xe0?\xff\xff\xe0\x7f\xff\xff\xe0\xff\xff\xff\xe1\xff\xff\ +\xff\xe3\xff\xff\xff\xe7\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\ +\x00\x00\x01F\ +\x00\ +\x00\x02\x00\x01\x00 \x00\x00\x10\x00\x08\x000\x01\x00\ +\x00\x16\x00\x00\x00(\x00\x00\x00 \x00\x00\x00@\x00\x00\ +\x00\x01\x00\x01\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\ +\x00\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\xf0\x00\x00\x07\xf0\ +\x00\x00\x0f\xf8\x00\x00\x1f\xf8\x00\x00\x1f\xfc\x00\x00?\xfc\ +\x00\x00w\xfc\x00\x00g\xfe\x00\x00\x07\xf6\x00\x00\x0d\xb6\ +\x00\x00\x0d\xb2\x00\x00\x19\xb0\x00\x00\x19\xb0\x00\x00\x01\x80\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xfc\x0f\xff\xff\xf8\x07\xff\xff\xf0\x07\ +\xff\xff\xe0\x03\xff\xff\xc0\x03\xff\xff\xc0\x01\xff\xff\x80\x01\ +\xff\xff\x00\x01\xff\xff\x00\x00\xff\xff\x90\x00\xff\xff\xe0\x00\ +\xff\xff\xe0\x00\xff\xff\xc0\x05\xff\xff\xc0\x07\xff\xff\xe4\x0f\ +\xff\xff\xfe\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\ +\x00\x00\x01F\ +\x00\ +\x00\x02\x00\x01\x00 \x00\x00\x03\x00\x03\x000\x01\x00\ +\x00\x16\x00\x00\x00(\x00\x00\x00 \x00\x00\x00@\x00\x00\ +\x00\x01\x00\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x0a\x00\ +\x00\x00\x11\x00\x00\x00*\x80\x00\x18[@\x00\x14\x80 \ +\x00\x12[@\x00\x11\xea\x80\x00\x10\x11\x00\x00\x10*\x00\ +\x00\x10D\x00\x00\x10\x80\x00\x00\x11\x00\x00\x00\x12\x00\x00\ +\x00\x14\x00\x00\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfb\xff\xff\xff\xf1\xff\ +\xff\xff\xe0\xff\xff\xff\xd1\x7f\xff\xe7\x80?\xff\xe3\x00\x1f\ +\xff\xe1\x80?\xff\xe0\x11\x7f\xff\xe0\x00\xff\xff\xe0\x11\xff\ +\xff\xe0;\xff\xff\xe0\x7f\xff\xff\xe0\xff\xff\xff\xe1\xff\xff\ +\xff\xe3\xff\xff\xff\xe7\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\ +\x00\x00\x01F\ +\x00\ +\x00\x02\x00\x01\x00 \x00\x00\x0f\x00\x0f\x000\x01\x00\ +\x00\x16\x00\x00\x00(\x00\x00\x00 \x00\x00\x00@\x00\x00\ +\x00\x01\x00\x01\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\ +\x00\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00?\xff\x80\x00!\x00\x80\x00!*\x80\x00!T\ +\x80\x00!*\x80\x00!T\x80\x00!*\x80\x00!T\ +\x80\x00!\x00\x80\x00!\xfe\x80\x00 \x00\x80\x00 \x00\ +\x80\x00 \x00\x80\x00 \x00\x80\x00?\xff\x80\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xc0\x00\x7f\xff\xc0\x00\x7f\xff\xce\x00\x7f\xff\xce\x00\ +\x7f\xff\xce\x00\x7f\xff\xce\x00\x7f\xff\xce\x00\x7f\xff\xce\x00\ +\x7f\xff\xce\x00\x7f\xff\xce\x00\x7f\xff\xcf\xfe\x7f\xff\xcf\xfe\ +\x7f\xff\xcf\xfe\x7f\xff\xc0\x00\x7f\xff\xc0\x00\x7f\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\ +\x00\x00\x01F\ +\x00\ +\x00\x02\x00\x01\x00 \x00\x00\x03\x00\x03\x000\x01\x00\ +\x00\x16\x00\x00\x00(\x00\x00\x00 \x00\x00\x00@\x00\x00\ +\x00\x01\x00\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18\x00\x00\x00\x14\x00\x00\ +\x00\x12\x00\x00\x00\x15\xf0\x00\x00\x16\x10\x00\x00\x17\xa0\x00\ +\x00\x17@\x00\x00\x16\x80\x00\x00\x15\x00\x00\x00\x12\x00\x00\ +\x00\x14\x00\x00\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe7\xff\xff\xff\xe3\xff\xff\ +\xff\xe1\xff\xff\xff\xe0\x0f\xff\xff\xe0\x0f\xff\xff\xe0\x1f\xff\ +\xff\xe0?\xff\xff\xe0\x7f\xff\xff\xe0\xff\xff\xff\xe1\xff\xff\ +\xff\xe3\xff\xff\xff\xe7\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\ +\x00\x00\x01F\ +\x00\ +\x00\x02\x00\x01\x00 \x00\x00\x06\x00\x06\x000\x01\x00\ +\x00\x16\x00\x00\x00(\x00\x00\x00 \x00\x00\x00@\x00\x00\ +\x00\x01\x00\x01\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\ +\x00\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x01\xfe\x00\x00\x01\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x01\x80\x00\x00\x01\x80\x00\x00\x03\x00\x00\x00\x03\x00\ +\x00\x00\x06\x00\x00\x00F\x00\x00\x00l\x00\x00\x00|\x00\ +\x00\x00\x7f\x80\x00\x00\x7f\x00\x00\x00~\x00\x00\x00|\x00\ +\x00\x00x\x00\x00\x00p\x00\x00?\xe0\x00\x00 \x00\ +\x00 \x00\x00 \x00\x00 \x00\x00 \x00\ +\x00 \x00\x00 \x00\x00?\xe0\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xfe\x01\xff\xff\xfe\x01\xff\xff\xff\xff\xff\xff\xff\xfe\x7f\ +\xff\xff\xfc?\xff\xff\xfc?\xff\xff\xf8\x7f\xff\xffx\x7f\ +\xff\xff0\xff\xff\xff\x10\xff\xff\xff\x01\xff\xff\xff\x00\x1f\ +\xff\xff\x00?\xff\xff\x00\x7f\xff\xff\x00\xff\xff\xff\x01\xff\ +\xff\xff\x03\xff\xff\x80\x07\xff\xff\x80\x0f\xff\xff\x9f\xcf\xff\ +\xff\x9f\xcf\xff\xff\x9f\xcf\xff\xff\x9f\xcf\xff\xff\x9f\xcf\xff\ +\xff\x9f\xcf\xff\xff\x9f\xcf\xff\xff\x80\x0f\xff\xff\x80\x0f\xff\ +\xff\xff\xff\xff\xff\ +\x00\x00\x01F\ +\x00\ +\x00\x02\x00\x01\x00 \x00\x00\x0b\x00\x09\x000\x01\x00\ +\x00\x16\x00\x00\x00(\x00\x00\x00 \x00\x00\x00@\x00\x00\ +\x00\x01\x00\x01\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\ +\x00\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18\x00\x00\x00\x18\ +\x00\x00\x000\x00\x00\x000\x00\x00\x00`\x00\x00\x04`\ +\x00\x00\x06\xc0\x00\x00\x07\xc0\x00\x00\x07\xf8\x00\x00\x07\xf0\ +\x00\x00\x07\xe0\x00\x00\x07\xc0\x00\x00\x07\x80\x00\x01\xff\x00\ +\x00\x01\x01\x00\x00\x01\x01\x00\x00\x01\x01\x00\x00\x01\x01\x00\ +\x00\x01\x01\x00\x00\x01\x01\x00\x00\x01\x01\x00\x00\x01\xff\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\xe7\xff\xff\xff\xc3\xff\xff\xff\xc3\ +\xff\xff\xff\x87\xff\xff\xf7\x87\xff\xff\xf3\x0f\xff\xff\xf1\x0f\ +\xff\xff\xf0\x1f\xff\xff\xf0\x01\xff\xff\xf0\x03\xff\xff\xf0\x07\ +\xff\xff\xf0\x0f\xff\xff\xf0\x1f\xff\xfc\x00?\xff\xfc\x00\x7f\ +\xff\xfc\xfe\x7f\xff\xfc\xfe\x7f\xff\xfc\xfe\x7f\xff\xfc\xfe\x7f\ +\xff\xfc\xfe\x7f\xff\xfc\xfe\x7f\xff\xfc\xfe\x7f\xff\xfc\x00\x7f\ +\xff\xfc\x00\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\ +\x00\x00\x00V\ +\x00\ +\x00\x01Fx\x9c\xc5\xc8\xb1\x0d\x800\x0cD\xd1\xef4\ +\x88\x0a*\xda\xa4\xa4d\x03\xd8\xcc\x8c\x9c\x0d\xccE\x8a\ +D\x01\x15\x0d\xdfz\xb2t\x900J\x81\x99\x91\xcd`\ +\x01V\xd1\xc4!\xa6k\x9d\xdc\xa5\xae\x15\x11\xfc]<\ +s\xd9+d\x99d\xe8?W\xd7\xee\xe1\x12_\xbcu\ +\x01\xec\xfbi\xe6\ +\x00\x00\x01F\ +\x00\ +\x00\x02\x00\x01\x00 \x00\x00\x10\x00\x11\x000\x01\x00\ +\x00\x16\x00\x00\x00(\x00\x00\x00 \x00\x00\x00@\x00\x00\ +\x00\x01\x00\x01\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\ +\x00\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xfc\x1f\xc0\x00\x04\x10\ +\x00\x00\x04\x10\x00\x00\x04\x10\x00\x00\x04\x10\x00\x00\x04\x10\ +\x00\x00\x07\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\xfc\x01\xc0\x1f\xfc\x01\xc0\x1f\xfc\x01\xc0\ +\x1f\xff\xf1\xc7\xff\xff\xf1\xc7\xff\xff\xf1\xc7\xff\xff\xf0\x07\ +\xff\xff\xf0\x07\xff\xff\xf0\x07\xff\xff\xff\x7f\xff\xff\xfe?\ +\xff\xff\xff\x7f\xff\xff\xff\x7f\xff\xff\xff\x7f\xff\xff\xfe?\ +\xff\xff\xff\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\ +\xff\xff\xff\xff\xff\ +\x00\x00\x00\xef\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xffa\ +\x00\x00\x00\x04gAMA\x00\x00\xb1\x8f\x0b\xfca\x05\ +\x00\x00\x00\x09pHYs\x00\x00\x0e\xc3\x00\x00\x0e\xc3\ +\x01\xc7o\xa8d\x00\x00\x00\x18tEXtSof\ +tware\x00paint.net \ +4.0.6\xfc\x8cc\xdf\x00\x00\x00mIDA\ +T8O\xb5\x8c\xd1\x0a\xc0 \x0c\x03\xfdt\xff\xbc\xb3\ +\x83d]\xa8\xd82\xf6p\xa2\xc7\x99af\x9fHe\ +\x87\xe7\xb2\xae\x15\xd0\xf3\xdf}Htb\xce\xb9\xbe\xc9\ +\x80\xcb\x0a\xdb\x01\x88\x13\xff\x0d\xec@\x08\xdc\xa5\x03.\ +\x15\x8dc\xcb7$DD\xe3\xccQBD4\xce\x1c\ +%DD\xe3\xccQBD4\xce\x1ce\x07|\xe6\x80\ +\xe3\xab\x15\xd0\x83\xd7\xa3\x8f\x8d\x0b\xd1.k\xedV\x14\ +\x8b0\x00\x00\x00\x00IEND\xaeB`\x82\ +\x00\x00\x00\xd0\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xffa\ +\x00\x00\x00\x04gAMA\x00\x00\xb1\x8f\x0b\xfca\x05\ +\x00\x00\x00\x09pHYs\x00\x00\x0e\xc2\x00\x00\x0e\xc2\ +\x01\x15(J\x80\x00\x00\x00\x18tEXtSof\ +tware\x00paint.net \ +4.0.6\xfc\x8cc\xdf\x00\x00\x00NIDA\ +T8O\xdd\x8c\xc1\x09\x00 \x0c\x03\xbb\xffT\xdd\xac\ +\x1a\xb0\x82\xb6*U\x10\xf4q\x8f\x5cBHD\x8ep\ +e\x04+\xb2\x02+\xa7XQ\xc6\xcc\x9c\xe3\xd8\xd5\xce\ +\x88\x7f\x0e<\xee\x1e`\xacl\x1f\xcc\x5c\xed\x8cx\xff\ +\x00`\xd8\x8f=\x07\x9a\x10G(\x01oN\x98?\xf6\ +\xff\xda\xc5\x00\x00\x00\x00IEND\xaeB`\x82\ +\x00\x00\x00\xd4\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xffa\ +\x00\x00\x00\x04gAMA\x00\x00\xb1\x8f\x0b\xfca\x05\ +\x00\x00\x00\x09pHYs\x00\x00\x0e\xc2\x00\x00\x0e\xc2\ +\x01\x15(J\x80\x00\x00\x00\x18tEXtSof\ +tware\x00paint.net \ +4.0.6\xfc\x8cc\xdf\x00\x00\x00RIDA\ +T8O\xed\x8fA\x0a\xc00\x08\x04}\xba?\xb7\xce\ +a/a\xa1m\xbc\xe4\x90\xc0\x043\xd1\x05\xa3\xaaF\ +X\xf9\x07+\xa1\x0fW\x97\xfe_X\x09\x0a\xc8\xcc~\ +\xfa\x1e\xb0R0<\x0a\xf8\x82\x95\xa0\x15V\xbfb%\ +(`{\x85\x1bpB\x000<\x0ax\xa7\xe2\x01V\ +T\xcf_\x16\xfbf\x81\x00\x00\x00\x00IEND\xae\ +B`\x82\ +\x00\x00\x03\xea\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x93\x00\x00\x00\x15\x08\x06\x00\x00\x00B\x0c\xdc\xd0\ +\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\ +\x04gAMA\x00\x00\xb1\x8f\x0b\xfca\x05\x00\x00\x00\ +\x09pHYs\x00\x00\x0b\x11\x00\x00\x0b\x11\x01\x7fd\ +_\x91\x00\x00\x03\x7fIDAThC\xed\x9a\xbbN\ +*Q\x14\x86\x07Cb,\xec}#\x1e\x81\xc6\xca\xbb\ +!\xbe\x81\x8d\x8d\x8d%\x0d=Zig\xb4\xd0\xc4H\ +c(H,\x88\x85Zx\x04\x04\x01\xaf\xf1\x0e\xe2\x92\ +o\x9d\xb3\xf7\x19\x07\xf4\xe4h5\xb0\xff\xe4\x97q\xad\ +=4|\xf9\xf7\x9a\x0d^,\x16\x93n\x9e\x9e\x9e\x96\ +\xa9\xa9)\x99\x9c\x9ctvV\xc3\x03\x5ct\xe3\x05w\ +\xc0\xb4\xbe\xbe.\xa7\xa7\xbf\xda>\x95\xf3\xf3s\xb9\xb8\ +\xb8\x90\xeb\xebk\xb9\xb9\xb9q\xeeS\xf3\xf9\xc3\x01<\ +\xc0\x05|\x04\xb9\xc1\x16& :;;\x93B\xa1 \ +\xb5ZMnoo\xe5\xe1\xe1A\x9e\x9f\x9f\xa5\xd1h\ +8\xf7\xb9\xe1\x00\x1e\xe0\x02>\xe0\x04f:`\xa2X\ +n\x83T*\x95\x94\xc2\xc7\xc7G}\x83V\xab%o\ +ooj\xa7\xfe\x95a\x00\x1e\xe0\x02>\xe0\x04^\x08\ + \x0b\x13 U\xabU-\x12i\x10\xf8\xfa\xfa\xea\x00\ +\xeaS\xb1\x9d\xe5\xf3y\xc9d2\xb2\xb9\xb9\xa9\xde\xdd\ +\xdd\xd5\x1a=\xbf\xe0\x05nLB)L\x14 \x0d\x90\ +\xa0\x0f\x98\x9a\xcd\xa6\xec\xec\xec\xc8\xd2\xd2\x92\x0e^\x98\ +kj\xf4\x9czO\xc7\xc7\xc7\xb2\xbd\xbd\xadpt3\ +=\xd6\x98\xa0\x81\x17\xb81@y\xa4\x12{ \xd1e\ +\x12\x09XVVV$\x1e\x8fw5=\xd6\xb8\xf4\xea\ +\x1d\x01\xc9\xc6\xc6F\x07@A\xb3\x86\xb5\xb0\x82\xe1\x06\ +~\xe8y\x95JE\x87*\xf6B\xe0\xc0\x10\x0843\ +33\xb2\xba\xba*\xc5bQ\xcd55z\xac\xe1\xcd\ +\x9c\xc2/\xb6/\x7f\x22\xed\xed\xed\xd9\xebn5\xd6r\ +\x0f\xac\xc0\x0d\xfcP\xd7dbJg{C,X\x5c\ +\x5cT`\x80'(j\xf4XC\xcc\xb9t\x0a\xbf\x98\ +\x87\xfc\xd0\xa0\xc3\xc3C[\xe3\x1a\xf9\x81\xe2\x1e\x047\ +\xf0C\xcd\x830?\x144'&&\x14\x18\xd2((\ +j\xf4Xs\x7f\x7f\xef`\xea\x011`\x1bH\xb0\x81\ +\x87W\xff\xb5\x7f\x0d\xf7 >\x7f\xf8\xa1\xe6]^^\ +\xca\xcb\xcb\xcb\x07\x98\xc6\xc7\xc7\xff\x09\x13k\x887\xa7\ +\xf0\x8b'6?(\xd8@\x84\x82 a\xeeAp\x03\ +?\xd4<\xa6q3/!`ZXXP`\xbe\xda\ +\xe6X\x03Lf{t\x0a\xaf~\x0a\x13\xfcP\xf3\xae\ +\xae\xae:\x92\xc9\x00\xf3\xd5\x00\x9eN\xa7\xe5\xee\xee\xce\ +\xde\xe7\x14^}g\x9b\xe3\x1c\x0a}H&\xb69\xff\ +\xcc\xc4+\xe7\x06\xc9dR\xa1\xf9\xcc\x89DBO@\ +]2\x85_?\x19\xc0\xe1\xc5\xceL\x0c\xe0L\xe3\x9e\ +\xe7\xd9&\x89srr\x22\xcb\xcb\xcb2??/c\ +ccj\xaeS\xa9\x94M\xa7\xb9\xb99==7 \ +:\x85S\xdf=\x1a@\x84\x89}\x9ac\x9b\xe3X\x1c\ +\x98\x0cP\x9c\x1f\x01T\xb9\x5c\xd6\x03\xaa\x83\x83\x03\xf5\ +\xd1\xd1\x91\xfe\x9f\xcdfevv\xd6\x02\xc5\xa1\x95S\ +\xb8\xf5\xdf\x87\x96\xad\xdfg\x92\xccK\xf0CO\xe9!\ +\xa6\x86\x86\x86d``@\xd6\xd6\xd6\xf4\xcd\x01\x8a:\ +\x8f\xff\x0c\xda\x18\xc00i\x94\xcb\xe5\x14\xa8\xd1\xd1Q\ +\x85\xcb)\xfc\x02\x12\x7fB\x05M\xcf\x80\x84`\xc4\xa4\ +\x92\xfd\xd5\x00\xc0\x0c\x0e\x0e\xdat\x1a\x19\x19\xd1\xc5\x9f\ +\x09\x22\xeb\xf5\xba\xec\xef\xef\xcb\xd6\xd6\x96\x90nN\xbd\ +!\xb6/\xe6!\x86r\x9e\xd8\xb0\xf9\xa2\xb7\xde\xee5\ +\x9a\x7fgd3+\xd9_\x0d\xf0\x07\x0d\x0f\x0fK$\ +\x12\x91h4\xaa\xaff\xcb\xfbLL\xf0\xc4\x1b =\ +==\xfd\xa9:\xf5\xba\x08\x12\x12\x89\xcf\xdc\x0f\x92\x85\ +\x09\xd3\xe0\xcc\xa9V\xab* \xec\x85\x0cW\xdc\xec\x06\ +\xec\xfe\x96a\x00\x1e\xe0\x82Q'\x08\x12\xb609;\ +\xff\xcc1y\x07P\x7f\x17\xd6Q\x02K\x02\x00\x00\x00\ +\x00IEND\xaeB`\x82\ +\x00\x00\x01\xbb\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x0f\x00\x00\x00\x10\x08\x06\x00\x00\x00\xc9V%\x04\ +\x00\x00\x01\x82IDAT(\x91\x8d\xd2O\x88\x8eQ\ +\x14\x06\xf0\xdf7\xf3\xa6Qc#\xb1\x9b\xbe\xc6\xd0,\ +,&\x1dM\x8aI\xa9Ql\xecg\xa1H2J\xb3\ +\xb2\xb4\xc5\xdeJ\x91\xb5\xa6\xc8\xbf\xa5P\x16rD\xb1\ +\xa0\x11\x92\x92\x05if\xc1\xa4)\x8b\xf7}\xa7\xfb}\ +>\xe5Y\x9d{\xcf}\xce9\xf7yN\xc7\x7f 3\ +Gq\x0a\xdb#b\xbe\xbd\xaf\x9a\xe4\x16\x8c\x16\xefW\ +\x22\xe2[fV8\x8e1\x5c\xc1\x91\xa2\xe0H\xa7\x09\ +\xf6a\x02\xd3x\x8aw\x98\xc5\x14~c\xa5(<\x8c\ +M\xd8\xda)*m\xc0\x09\x1c\xc5$\xae\xe3E\xdf\x0f\ +f\xf0\x18\x9b\xf1\xbd\xca\xcc\xcb\xf8\x899\xbc\xc7%\xdc\ +\xc78\xe6\xf1*\x22\xae5\x0d\xba\x11q+3\xbb\x98\ +\x1a\xc2g,#\xb0\x18\x11w\x22b\x0d\x8bX\xc0\xd5\ +\xcc<4H\xc8*\x22.\x16\xa3\x97\xb9\xc9\x22\xde\x9f\ +\x99\x0f0\x91\x99\xc3\xed\xe5\xd0\xa0\x8a\x0d\xde\x16\xf1K\ +\xdcS\x0b\xfa\x05\xc7z\xc8\x99\xb9\x13\x072s.3\ +\xf7\xe2\x1c\x96p\x13\x9fp7\x22\xf6\xe0\xb4\xda\xb2\x91\ +\xaa\xa8\xbe\x80\x8f8\x8b\xdd\xf8\x85\x0b\xb8\x81\xd5\xa6\xc1\ +\x13\xb5\xa5\xb7\xf1\xbc\x1c\xfb\x07\xb6E\xc446\xe2\x0d\ +\x0e\xab}\xff\x80nC\x9a\x8d\x88\x93\x11\xb1T\xfa\xbc\ +\xabI\xee\x88\x88\xb5\xcc\x9c\xc1\xa36\xdd\x8c\xdc\x83\xf5\ +\xce\x11\xf1\x1a\xcb\x8dM\x1aqZ\x8c\xf7\x13\xfb\x05\x1b\ +S/I\x8b\xce?\xe2\xbf\xc9\xf8\x8a3\xc5\xf9Y\x11\ +\xf7,@\x8bu\xb5#bU\xeda\x8b\x87\xea-;\ +\x88\xf3\x83\xc8\x7f\x00k\xb9|\xe7dF#\x7f\x00\x00\ +\x00\x00IEND\xaeB`\x82\ +\x00\x00\x01\x01\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x0f\x00\x00\x00\x12\x08\x06\x00\x00\x00\x84\x9e\x84\x0f\ +\x00\x00\x00\xc8IDAT8\x8d\xa5\xd3=N\x031\ +\x10\x86\xe1gQ\x02]\xe8R\xf3\x97\x0e\xaa\xbd\x12E\ +.\x10J\x84\xc4=\xd2%\x12\x15\x11\xe7\xd8\x8d\x10\xa2\ +\xe5 H\x88M\x11G\xdaX\xded1_7\xdf\xe8\ +\x9d\xf1\x8c\xed\xa2i\x1am\xd5u-\xd2\x19\xbec\xb3\ +,K'\xb1\x99\xd0\x03\xceS\x89>\xf0\x04W\xb9\xf0\ +\xf5\x7f\xe0\x9b\x5cx\x841.s\xe0]\xc7,x\x12\ +\x15\xd9\xd3\xa0\x03\xba\xc3\x10\xb7!\xbe@i;\xffJ\ +\xb8\xf7.x\x88\x0aE\x88OC\xfc\x8a\x97c\xc7^\ +\xe3-\xf2~\xf1\xd86\x0e\xcd\xfc\x84\xf6\xdb]\xe2\xb3\ +/\xfcn;\x1f\xfc\x84b{:\xb6\xed]\xf79\xbe\ +\xfe\x0a\x7f`\x81\xe7T\xb2k\xdbm\xddK|I(\ +\xaa\xaa\xea\xc1\xa75\xc0\x14\xb3\x1cx\x03\xb2\x99!K\ +\xef\xfb\x80\xb9\x00\x00\x00\x00IEND\xaeB`\x82\ +\ +\x00\x00\x02\x1e\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x18\x00\x00\x00\x11\x08\x06\x00\x00\x00\xc7xl0\ +\x00\x00\x01\xe5IDAT8\x8d\x95\xd4]h\x8ea\ +\x18\x07\xf0\xdflIQC\xf2q\x22\x8a\x92\xe2\xd8G\ +!\x0e\x97\x16j\x07D\x88\x94R\xcb\xe7\xa2\x9c\x8d\x92\ +\x906\x16K\xf9\x96!\xc7\xac\xa4\x90\x83\xb7)\x07r\ +\x22\x12\xcd\xc1\x88%\x8b\xf9:\xb8\xafw\xef\xd3\xb3g\ +\xeb\xdd\xbf\x9e\xee\xfb\xbe\xee\xeb\xb9\xfe\xd7\xe7]S*\ +\x95\xea\xf1\xd5pl\xc2\x0d\x5c\xc7\xc6\xdc\xddy\xec.\ +\xf8g\x18\xc6\xe1\x07\x9a\xb0\x03\xbf\xf0\x1d\x9b\xf1$t\ +\xce\xe2p\xec\xbbC\xb7\xb3\x1a\xe3P\x87At\xc5y\ +:\x8ea1\xae\x85\xac\x84\xd3\xf8\x8c-\xe8\xad\xd6x\ +9\x82,N\xe0\x19\xf6bY\xc8Z\xb0\x14\xbb\xc6j\ +\xbc\x88\xe0Ox9\x80\xcbX\x81\xa3\xb8\x82\xbb\x19\xbd\ +\x16\xfc\xcb}\x0dq\xf72+\xcf\x13\xc0\x1b\xec\xc3<\ +<\x0c\xaf\xf7\xe4t\xeeK\xb5x\x1f\xe7\xfd\xe8\xc9\xec\ +\xbbc\xdf^D\x00\x17\xc3\x93\xf1hC\x7f\xee\xfe\xb5\ +T\xb7\x8e8ORI\xdf\x03\xcc\xc0_\xb4\x8eD\xb0\ +\x06\x8bB\xe9\x10f\x8e\xe2\xc8\x00\xb6\xaa\xa4{v\xfc\ +\xfb\x14\xbdE\x04\xf5\xb8\x84W\xd2,L\x93\xda\xb2\xa6\ +@\xb7\x0f71\x07\xabC\xb66\xd6;\x0c/2\x9c\ +\xc1\xac\xf0\xea\x96T\xe0\x06\xec\x1c!\x8a\xb6X\xb7\xc5\ +\xbaN\x8a\xbc\xab\x88\xa01\x0c\x1f\x97\xfa\x1f\x9a\xf1\x01\ +\xa7\xa4\xc2\xe7\xf1\x02\x8f\xb1\x1e\xf3\xb1J\xa4\xa7LP\ +\x8b)\x11f\x87T\xc0\xf6\x90\xc3O\x1c\xc4D\x5c\xc5\ +TL\xce\x91\x9c\xc3\x04)-\xb5\xb1*\x13,\xc4\x17\ +\xbc\x95\x8a\xb9\x00\x9fB\x0e'\xa57\x09\x96H\x13\xfd\ +.Gp\x0f\xad\x98+\xa5ghf\xea\xa4^n*\ +\x08\xbd\xdc\xe3\x9dx\x94\xbb\x1b\xcc\x9d\x7f\xe36\x8eH\ +3\xf01K\xf0M\xe5-*B\x8f\xca\x10\xe5\xb1]\ +\xea\xb6\xe78\x10\xb2\x0bY\x85\xbaQ\x0cW\x83f)\ +\xbd}\xd8 \xbd\xc0\xd9'\xa5\xb0M\xc7\x82~\xac\xc4\ +r)\x95\x8dR\x0d\x86\xf0\x1f\x84\xf8v\x1d=\x86M\ +P\x00\x00\x00\x00IEND\xaeB`\x82\ +\x00\x00\x01p\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x12\x00\x00\x00\x12\x08\x06\x00\x00\x00V\xce\x8eW\ +\x00\x00\x017IDAT8\x8d\x9d\x93\xc1J\xc3@\ +\x14EO\xa2\xa0\xa0\xa2\x05\x11\xba\xf3#\xde\xd2\x8d\xf4\ +\x1b\xc4\x1fp'\x88\xa0\x82Pp\xa3\xa2;\xc5\x95\xee\ +\x14\x7f\xe7\x82\x1f\xe1\xc6\x8d\xa4P\xb5\x9a\xb4\xd5E_\ +a\x88IF\xbc0d\xde\xcd\xc9\x9d7a\x06\x22\x92\ +\xb4#i/\xc6\xcd\xc6\x00\xe0\x02\x98\x01n\x9a\xa04\ +\xd6\x0d\xb0\x0a\xb4|\xfe\xbf \xef\xa6j\xfe\xf7 I\ +\x9d\xa0\xfc\x06\x0aI\x9b\x91\x85\xeb%i \xe9#\xc6\ +\xfd\xeaH\xd2v\xc9\xfa\xf4\x112\x07\x92\xe6+\x83$\ +\xedK\xca\x80\xdbR\xd0\x08(J\xde!\xd0\x93t)\ +)\x05H$\xed\x02g\xc0J\x00\x0e\x81\xdcC\x16\x99\ +\xfc\xa3w&\xc7`\xce\x9fS\xbd\x01\xdd\x14x\x02^\ +K+\x0e\x80\x9e\x8f\xb1\x07\xf5\xdd\xcf\xbd\x9e\xea\x0b\xc8\ +\x92`k\x1d\xe0\x0eh\x9b\xd9B\xe0g@afk\ +\x81\xf7\x0c,\x03'fvM\x95$m\x94\xea\xbe\x87\ +\x85\xdeV\xe5\xc7M\x92\x94K\x1a\xc4\xb8\xa4\xee\x85_\ +\x89.\xb0\xee\xd6\x0bplf\x0fU|\xd3\x15\xb9\x07\ +\xdaA\xbd\x04<\xd6\xc1\xb5Af6\x04\xae\x02\xeb\xd4\ +\xcc\xc6u|\xed\xd6\x00\xfc\xb0\xf5\x81\xdc\xccZMl\ +\xe3\xed\xf7\x0e\xce\x81\xa3&\x0e\xe0\x07\x81\x1e\x7f\x14\x8c\ +;\xe7\x95\x00\x00\x00\x00IEND\xaeB`\x82\ +\x00\x00\x01{\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x12\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1b\x06/\x5c\ +\x00\x00\x01BIDAT8\x8d\x95\xd3?K\xdbQ\ +\x14\xc6\xf1OB\xaa\x9bb\xfd\xb3IQ\xc8(\x08\x97\ +:\x1b\xa8\x9d\x5c\xb5\xd0\xcdEqt\x93\x80\xef\xa0o\ +\xa0N.\x0e\xba\xd61\x10p\x90\x0a\xbf\x0cm\x17\xb3\ +\xb8\xb8H\x15u\x8a\xa0`\x1c\xe2\ +\x06\x15\x9c`$\xa5t\x05\xc5\x1c\x90\x11\xccD^\xc6\ +%\xfe\xbf\x1e\x96r\x80\x86P\xc5'\x1c\xe3\x0b4\x1a\ +\x8d:\x96\xf3\x80\xae\x03\x92\xd0\x88\x05\x8b8(\x0c\xd8\ +\xa3\x02\xbec\x12-L\x04T\x00k\xfd*\xaa\xa0\x1e\ +y\x1b\xfb]\xe0RJmz7{\x12\x9b\x91\x0f\xf5\ +\xf0\xb4c\xe9\x07\x1aG\x0d\x19\xf6\xfa\xc0\xde\xa2\xdb\xd5\ +fq\x869/\x8d-\xe1a\x10\xd02\x8eB\x7f\xc0\ +\x1a\xa6p\x8b\x0d\x0c\xe3g\x9c\xef\xe8\x98\x9d\xce(\xe2\ +\x17\x96B?\x06d=*\xdb\xc5\xbf\xd0\xeb\x98\xeeU\ +Q!\xcb\xb2\xc3\xc8\x7fx\x9f\x93Y\x5c\xe07F\xf1\ +5<\xb5\xa8\xf4/\x9a\xb17\x81\xfb\x12Vc#\x0b\ +\xc8\x06\xb6\xb1\x82C\xfc\xc1|\x17O\x13\x0b8E9\ +\xcf_\xeb\x16\xafC\xa9\xe8}\x1e\xb60\x86\xcf\xa1\xbf\ +\x85\xae\x0e\xe09\xef|\xfe\x16\xee\xf0\x14\xfa)t\xab\ +\x9f'\xa5t\x07\xcf)mR\xad\xb7y\x8e\x81\x00\x00\ +\x00\x00IEND\xaeB`\x82\ +\x00\x00\x02,\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x11\x00\x00\x00\x10\x08\x06\x00\x00\x00\xf01\x94_\ +\x00\x00\x01\xf3IDAT8\x8de\xd3K\x88\x8fa\ +\x14\x06\xf0\xdf\x7f\xfc\x95\xb0@\x22\x9a\x92{\xe4\x9aS\ +\x9a\x85\xb2\x125R\xee\xa5L)\x16\xa6\x90\x8d\xb2D\ +\x12Rl$\xc9(I.Qr\xbf\xaf\xa4\x8e\x14\xd1\ +\xe4R\xc8\x06\xc9%\xb7$,\xbeW}\x8dSo_\ +o\xe7;\xcf\xfb<\xe79\xa7\xa1Gd\xe6h\xac\xc1\ +\x1c\x8c\xc1\x1f\xf4\xc2C\x9c\xc6\xc1\x88\xf8X\xafi\xa9\ +\x15\xf7\xce\xcc\x9d\xb8\x83N\xbc\xc5R\xdcB_\x1c\xc5\ +(<\xcd\xcc5u\x90F\x01\xe8\x8bs\xf8\x8c\x09\x18\ +_\xf2kq\x11\x0b1\xb5\xb0\x9a\x82\xa18\x1b\x11\x9d\ +u&\xc70\x02W\xf1\x18\xaf\xb0>\x22\xf6G\xc4\x0b\ +\xfc\xc4Jt`:V\xa0-3;\xa1\x91\x99m\xb8\ +\x81O\x18\x19\x11\xdf3s\x11N\xe15\x9e\xe1:\x96\ +a\x12\xeeEDd\xe6\xf4\x22\xbd\xb5\x05\xdb\xd1\x07;\ +\x22\xe2{a\xb6\xa4|[1\x1bG#br\x91z\ +937`0\xbebs#3_c\x0b\xc6\xe1\x01\ +\xba\x0b\xb3~\x05\xa8;\x22&\xd4\x0c8\x8b\x05\xe5z\ +\x18\x93\x9a\x18\x80\x13\xf8P\x12\xcf0\x11\xf3\xcay\x92\ +\x99\xcd\x88\xf8\xe5\xff8\x8e\xad\xcdri\xd6\x12\x8f\x22\ +\xe2\x15\x0e\xe0@fvcca\xfc\x02\x17\xf0\xa3<\ +\xf4\x05?Z\xf0\x06]\xd8\x8d\x9b\xb8_\xa3>Ye\ +w/\x95{\xad\xd8\x13\x11\xcb\xb1\x17\x97\xf0\xb1Y\xa4\ +tFD{)\xec\xca\xcc{8\x89\x81=\xe8o\xab\ +\xc9Z\xa22\xe4H#3\x87\xe0)fFDwf\ +v\xa9\xe6\x01\x16\xe16\xc6b\xbe\xaa\xd9\x0f\xf0\x5c5\ +\x9c\xdf0\xbc%\x22\xdeb\x03\xceg\xe6*\xf4\xae\xbd\ +\x9c\x11\xf1^5|\xab\xb1\x1e\x87\xd0^\xfa\xd2\x1e\x11\ +\xbf\x1b5\xfd\xeb\xb0\x09g\xb0\x0b\x8b1\xab\xa4\xaf\x14\ +\x80q\xb8[\xfa\xd3\x11\x11W\xa8-`D\xec+\xf4\ +g\xa8\xf6%0\x0c\xfd\x8b\x0b\xd7\xf0\xae\xb0j\xfb\x07\ +@Y\xc0\x9e\x91\x99\xd30W\xb5\xb5\x83J\xf1C\x9c\ +\x8f\x88\x97=\xff\xff\x0b\x84C\xb2\xa8\xaa\xc4\xf2\x0e\x00\ +\x00\x00\x00IEND\xaeB`\x82\ +\x00\x00\x00\xee\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x0a\x00\x00\x00\x0d\x08\x06\x00\x00\x00\x907\xff\x05\ +\x00\x00\x00\xb5IDAT(\x91}\xd0\xa1\x8aBQ\ +\x14\x85\xe1O\xb9\xcdd\x9b\xeek\x08\xbe\xc7X\x0c:\ +\x08\xfa V\x1f@\xb1h1\xcc4\xc1l\xbc0\xc1\ +7\x10\x83ED\xc3\x14\x83\x96s`s\xb9\xcc\x82\x13\ +\xf6f\xb1\xfe\xb5O\xa3,\xcbO\xac\xfd\xafY\x11\x86\ +\x01\xfe\xc2\xdc\xc0\x1c\x1f8F\xe3\x0f\xeea\x9e&\xd3\ +\x0e\x9b&N\xd8\xe2\x19L\x1d\xccp\xc3\x17\x148\xa4\ +\x17\x91\x0b\xb4R\xea\x19\x9a5\xc5'\xe8%\xe4*/\ +\xab\xc6\x8c\xbcgdV<&\x22\x87\x19Y\x97\x98\x91\ +{,\xab}rbF>0\xc2+x\xc6\xb8\x145\ +\xc8S%\xac/}\xf88!\x0f\xf8F\xbb\x8eZ\xa0\ +\x9b\x16]\x5c\xab\xdd\x92~\xdf\xc4\xcd&:\xc3\xef\xf7\ +E\x00\x00\x00\x00IEND\xaeB`\x82\ +\x00\x00\x015\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x0f\x00\x00\x00\x0f\x08\x06\x00\x00\x00;\xd6\x95J\ +\x00\x00\x00\xfcIDAT(\x91\x95\xd0\xcf*D\x01\ +\x14\xc7\xf1\xcf\xcc\xcaB<\x06YX\x9d\xe6\x09\x94\x12\ +SJ\x9a\x97\xb0'\x8bY\xc8+XY\x121\xfe\x16\ +\x1b;ew\x1e@\xd9YX\xb0A\xd9\x10c\xe1\xca\ +\xedv\xa7\xc6os:\xe7\xf4\xfd\xfdN\xa7\x91\x99\xab\ +\xf8\xc0aD\xdc\xfb\x87\x1a\x99\xd9\xc1\x1e\xfa\xb8\xc1\x01\ +\x8e\x22\xe2a\x18x\x14O\x18)\xcd\xfb\xb8\xc6>\x8e\ +#\xe2\xb1\x16\x86\xcc\x06Z\xa5\xb1W#\xc4HW\x92\xccZ\xcf5\x97\ +i|8\xb0\x14h\x0e\xcc\x06^\x06\xb6\x03#\xf0~\ +\xfdU\xf5@aq\xa2\x8d\xf7\xfe\x00p\x13\xf0\xb8\xb3\ +\xe6\x9bx(\x80M\xc0 `\x82\xb3f\xd1U\xf1\x80\ +\xf7\xfe-\xa0-0/e\x1c\xc0Y\x03\x88\x22\xe0_\ +`Faq\x22+}M:@\xfc\xca\xf1\xc0?\xc0\ +{\x99\xeb\xce&\x0f\x03K\x80N\xde\xfb\xe7\xb3\xd1\xd9\ +`\x08\xa4\xd2\x03\x08q\xed\x07\xb4\x8f\x06\x0f\x03'\x80\ +\xe1\xc02g\xcd\xd8K\xec\xed\x05T\x02\xbb\x81\xbd@\ +\x0f\xa0\x03p\x168\x00\xac\x13B\xcc+\x8b\x89*\x00\ +\x0a\x8b'u\xf6\xbe\xee\x1d\xe0]g\xcda\xa9t\x0d\ +!\xc1\xceE\xa37\x12J-E\xe7\x81\xcd\xc0\xa7 \ +\x968\x9bD*\xdd\x1f(\x06F\xc6C\xa7>\xae6\ +\xeah\x09\xb4\x89\xbc\xfd\xc0@g\xcd\xef1\x04~p\ +\xfc\xe2\x1f\xa5\xd2}\x9d5-\x80\x02\xef}\x0bg\xcd\ +\xad\xce\x9a\x9b\xbd\xf7\xad\x81\x83@\x0d\xb0\x03x\x04X\ +\x0c\xbeZ*\xbd\x03\xd8\x0a\xbc\x12\xc3\xba?\x1a\x1a\xeb\ +\xaci\xee\xac\xe9\xec\xaci\x8b\x10]\x81R\xe0.`\ +Qz\x0e\x5c\x1b\xc7N\xc0\xf7R\xe9!\xce\x9a/W\ +\x94.\xb8\x18+!N\x01]\x81]\xce\x9a<`*\ +\xe0\x09\xd5\x90\x1b\xc5*\x81{\x81\xe9q\xde\xa5^\x8e\ +\x94$\x8f8k\x14\xf0\x0bP \x95n0\x09o\x00\ +\xd6I\xa5'\xd4K\x16!\xee\x8f\x07>-\x95\xdeD\ +\xa8\x7f\x80\x95\xc0\x9b\xc01\xa07\xb0\x0f\x18\x10\xd7z\ +]\x22\xf7\x0e\x03\xcd\x80\x8e\x97\xaa\x82k\x80\x85R\xe9\ +\x0fR\x0c\xef\xfd\x9d\xf1\xef@B\xad\x7f\x0d\xf4u\xd6\ +\x8cv\xd6\xcc\x11B\xdc\x02L\x8b\x8au\x94\xed\x9e\xa9\ +8\x96g?\xa0\xcaYs\xbc\xb12|C*\xbd\x22\ +\x96_N\xe4\xfd\x09\x14:k\x06;k*S\x82e\ +%I\x9c5\xb3@\xf4\x04R\xdd\xb0\x8fT\xba^\xb5\ +x\xef_\x8fa[\x09\x17\xaa \xf1\x82\xf7\xfe\x93\xff\ +9\xc8fg\xcd\x00\xa9\xf4d`\xb7\xb3\xe6B\xbb-\ +,Nt\x00r\xcaJ\x92\xbb\xd37H\xa5\xf7\x00w\ +\xc7\xe9\x82\xe8\x95n\xc0\xcf\xd1K=\x9c5\x87\xb2m\ +D\x0fK\xa5\xf79k\xe6\x0a!\xd6\xa7\x19\x19\xe3\xbd\ +?\xea\xbd\xdf%\x95\xde\x94\xd1\xfd\xaa\xe2\xf8\x1b0\x11\ +\xf8\x22\xfeZ\x01S\x9c5\x87R\xb1\xce\x96\xbaK\xa5\ +\x97\x96\xd5G\xba\xf7\xe3\xd7\x00\x0c\xf2\x9eQikg\ +S|\xe0;`\x18\xa1Z\xca\x9c5\x1f\xa6\x84\x9a\x8a\ +\x05\xe73\xe6u\x8d\xcc!4\xb4\x96\x97\x92i\xca\x01\ +v9k\xc6e\xf0^\x03\xce\xc4\xff\x1b\x84`u\xda\ +Z\xca\xe8\xb7\xc0\x83\xc0\x1a\x02d\x17I\xa5_m\xea\ +\x016:kr\xa5\xd2oK\xa5\x87\xa5\x98\xce\x9a5\ +@\x8e\x10\xe26g\xcd\x90\x8c\xf0\xb4\x8fcW`\xbe\ +\xb3f\x04\xf0,P\x0d\xcc\x91Jw\x86\xd8\x01{\xe5\ +\xe5\xf7!\x80LCT\x0a\x8c\xcc\xcd\xcb\xd7\x84\x98\x0f\ +\xcd\xcd\xcb?\xb1\xb3\xa2|;\xc0\xce\x8a\xf2\x9a\x9d?\ +m=\x99\x12\x96Jw\xcb\xcd\xcb\xff\x8cP\xebg\x80\ +\x22g\xcd\xbc([\x9d\x9b\x97\x7f\x1ax\x06h\xb6\xb3\ +\xa2|Cc\x1e\x98\xe9\xacQ\x01\xeb9\x1ay\xad\x81\ +\xc5R\xe9-R\xe9\x87.\x1aN \x95\x9eE@\xc1\ +\xc7\x22\xbb\xc2Y\xb32]\xa1\x10b\x01p\x12\x18\x0d\ +\x1738\x93j\x81\xf1\xce\x9a\xd2\xb4\x8d\xfb\xbd\xf7\x00\ +\x1b\x09\x19^\x00l\x91J\xaf\x03~\x00?\x09hG\ +hT\x06\x98L\xe8\xf9\xf5\xa8\xac$\x89Tz\x1b0\ +X*\xdd\xa6!\x0fT\x03O\xa6\x1b\x07\xf0\xdeW\x10\ +2\xb8\xa3\xb3f(0\x85\x00FO\x033\xa2\xf1J\ +\xe0>B\xb2A@\xcd\x86\xe8v\x02\xaa\xfe\x9d\xf2@\ +m\x1c\x8f\x00O8kvK\xa5G\x01\xab\xa2\xfb!\ + \xe5!\xe0\x1e\xa9\xf4^\xa0g\xe4W\x11\xe0\xb7?\ +\x01\x8c~%\xe0?@\x95T\x9a\x94\x0e\xa9tw`\ +&\xa1#\xaer\xd6\xc4V\xfc\xe2\xa4\x1c_W7\x15\ +\x98\xed\xac9&\x95>\x97\x16\x9ej\xe0zB=\xa7\ +\xa8\x06\xf8\x0aX*\x84X^V\x92D\x16'r\xf1\ +\xbe\x18\x18E\xc8\xfc\xf4\xdb\xd6\xe9\xb8\xff\xba8\xdf\x85\ +\x10\x8f\xba\x92\xe4\x89\x86\xafd\xc5\x89\x07\xf0\xfe%B\ +&\xb7#\x5c4\x0f\x02\x7f\x01c\x80\xe5\xce\x9a\xa2\x06\ +\xf7*\xdd\x9b\xd0\xef+\xe3\xd83\xea\xa8\x8d\xdeY+\ +\x84XT\xefJ\x96-\x8d\x1e7\x11!\xc4\x1f\x044\ +\xeb\xe2\xac\xa9\xca\x94\x91J/\x04&\x10\x10\xd35\xa6\ +\xb3I\xad8\xde\x90\x16\x12\xba\xdc\xf4\xccu\xa9\xf4\x1d\ +\x80\x02\x8e\x08!\x1a5\xde\xe4\x03\x00\x08!\xe6\x02\xc7\ +\x81\x84T\xfa\xa94\xe3\x00\xcb\x09q\x9eV\x96\xe5\xf3\ +\xec\xb2\xde\x86R\xe9\x02`-\xa1,?\x22@\xeex\ +\xc2}\xf0sg\xcd\xf0lu]\xd6\xdb0^H\x9e\ +\x03N\x01\x09`~4\xbeL\x08\x91\xb5\xf1\xcb\xf6@\ +\x9a' `H\xeay\xbe\xa7\xa9:\xfe\x03\x5c\xaa\xea\ +&\xfd\x17M\xd2\x00\x00\x00%tEXtdat\ +e:create\x002016-01\ +-08T15:18:18+00:\ +00\x01E\x99\xf0\x00\x00\x00%tEXtda\ +te:modify\x002016-0\ +1-08T15:18:18+00\ +:00p\x18!L\x00\x00\x00\x00IEND\xae\ +B`\x82\ +\x00\x00\x00\xce\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x0c\x00\x00\x00\x0c\x08\x06\x00\x00\x00Vu\x5c\xe7\ +\x00\x00\x00\x95IDAT(\x91\x9d\xd0\xb1\x09\x02Q\ +\x10E\xd1\xb3\x22\x08\xb6a,\x98\xd9\x80\x81\xa0e\x88\ +\x91%\x18Z\x82\x89b\x19\x0a\x826 \xfc`\xc1\xd8\ +\xd0\x16\x04#\x0d\xfe.\xac\xe8\xdf\x05_x\x87\xcb\xcc\ +\x9b,\x84\xf0\xc2\x01S1{L$\xd2\xc6\x19y\x85\ +\xe5\xe8\xa4\x84,\x84\x90\x9a%7lp\xc5\xba`\x0b\ +\xf4\xeb\x84\xb9\xd8\xa1\x14\xc6\x1a:\xf4\xf0\xa8\xb0\x19\xba\ +)\xa1\xd5|\xf5\xf7\x86\x9b\xcf\xb7\xee\x9aN\xda\x8a\xa5\ +\xcb\x1cqO\x09\x7f\xbd\xf5\x84\x0b\x96\x05[aX'\ +\x8c\xf0\xac\xb0A\xc1~\xe6\x0d\xc9\xd6\x1dQ\xcd\xba\xaa\ +\xa1\x00\x00\x00\x00IEND\xaeB`\x82\ +\x00\x00\x01}\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xffa\ +\x00\x00\x01DIDAT8\x8d\x95\xd2\xb1KVQ\ +\x14\x00\xf0\xdf\xf7Qa\xe2\x12N\x91\x93\x85MN\x9d\ +\xa1E\x10\x84\x86j\xd4M\x87\x96\xc0\xdd]\xb7hh\ +\x8d \xa1!A\x1cZ\x85\xa6j*\xf2P\xe0\x90\xe2\ +\x1f\x10\x88A\x86aa|\xe2\xf0\xae\xa1\xaf\x0b\xe6\x99\ +\xde;\xf7\x9c\xdf=\x5cNG\x89\xcc\xbc\x829Lb\ +\x18\x7f\x90X\xc4RD\x1c\xaaD\xa74\x8f\xe25\xae\ +\x96\xfc/\xf40P\xfeW1\x15\x11\xfbm\xa0[n\ +^=\xd1\x0c\x971\x8bql\xe2.\x9e\xd5&\xe8\x96\ +\xb1\x87*g\xdf#\xe2\x1d\xc6\xf0\x153\x99y\xab\x06\ +L\xd5d\xecBD|\xc3\xa3\x92\xfb\xa7\xf6\x82\xe6\xc1\ +~\xa3\xaf\x0dd\xe6\x00\x06\xb1Qr\xd7k@\x0f{\ +xP\x90\x9f\xd8\xc6+\xdcl\xd5\xf7j\xc0:\x02[\ +\x11\xf1\xe9\xf8 3\xdb\x13\xc1\xe7v\xa2\x8b\x17\xe5\xfb\ +if\xf6W\x9ahv\xe2\x00/k\x13,b\x06\xb7\ +\xb1\x96\x99\xf3x\x8f\x8b\xa5\xe6\x00\x97\xf0\x04;m\xe0\ +x\x91\x06\xb1\x82\x89\xca\xed=,c\x1a\x1fq'\x22\ +~\x9c\x02\x0a\xd2\xc1=\xcd*\x8fh\xb61\xf1\x5c\xf3\ +\xa8_4\xfbr\x0a\xf9\x0b\x9c\x15\x99y\x03oq\x0d\ +\x1f0\x11\x11\xfb\xff\x0dT\x907\xb8\x7f.\xa0\x82<\ +>7p\x02Y\xc0\xc3#S\xefd\xae\x0f\x1eB$\ +\x00\x00\x00\x00IEND\xaeB`\x82\ +\x00\x00\x01x\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x10\x00\x00\x00\x12\x08\x06\x00\x00\x00R;^j\ +\x00\x00\x01?IDAT8\x8d\x9d\xd3=K\x5cA\ +\x14\xc6\xf1\xdf\xae\x06\x04\x8bt\xdb\xa8\x88q#\xa2\xd8\ +X\xa4\xb2\x15\x041\xd8\x05\xa2\x95\xe5\xd6!\xd8,n\ +!~\x06+IJ\xf3\x09\x94\x10P\x904n\x11H\ +0$\xf8\x02.\x0b\x0a\x16Vb\xe1\x8a\x8538\x19\ +]\xc2\xfa\xc0\xe5\x9e\xf3\x1c\xce\x7f\xce\x9d\x99[\xa8\xd7\ +\xeb\x12\xad\xa1\x8a\x96\x7fu\x89\x97\x99w\x8a\xc1bf\ +\x8e\xa3O\x07\xca\x01\xaf\xc2\xf3,@\x01\xe5N\x01\xdd\ +I\xdc\x8f\x9e6\x80\x1d\xf4\x86E&\xf0\x13\xe7\xf9\x04\ +\xb1q\xe8\x09\xc0<\xa6\xf1\x19%|\xc2B\x0ex\x9d\ +\x81r\xbd\xc0J\x88\xabq\xfa\x22\xc6BS\x0a\x18\xc5\ +\x1c\xba\x12\xc0\x12\x86C<\x82\xf7\x110\x80#|\x0c\ +\xc5\x12~\xe3\x9d\x87\xfb\xd0\x13VMUEw\x11\xdb\ +\xf8\x9e\x15oPK\xf2\x8a\xc7\xf7\xa3\x8c\xc5\xb8\x07\xb5\ +\xac\xb8\x81\xc3$ob\x06?B\xbe\x857hD\xc0\ +W\xec\x85\xf8\x1a\xab\x19p3Lz\x10\xf2_\xd8\xc7\ +\xb7\xf4\x14\xe2\x0e\xaf\xa3\xe1i\x1d\x87\xf7Q4\xe2E\ +Z\xc6$\xce\xdc\x9f\xc2\x97\xe0Wp\x91\x00N\xda\x01\ +\xa60\x1b\xe2\xb7I\xc3\x876\x13\xfc\x8dF\xfe3\xfd\ +O\xc7\xb8\x92|b\xa7\x80&\xfe\xe0\xf6\xb9\x80\x16v\ +S\xe3\x0e3\xc49\xa5\x12)N:\x00\x00\x00\x00I\ +END\xaeB`\x82\ +\x00\x00\x01\x1b\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x0e\x00\x00\x00\x0d\x08\x06\x00\x00\x00\x99\xdc_\x7f\ +\x00\x00\x00\xe2IDAT(\x91\x9d\xd1/K\x83Q\ +\x14\x06\xf0\xdf\xe6\x8aE\x98_`&\x83U\x10\xbf\x82\ +\x98\x9d0\x16\x945\xbb \xd6\x05\xcd.\x88}j\xb1\ +\x0cV4\x1b_\x164\xac\xb8b\x96\x81\xc5 2\x16\ +v\x06\x97\xd7wC|\xe0p\xcfs\xce\xf3\xdcs\xff\ +\x94\xb2,\xbb\xc0\x99\xdf8\xc1u\xe4}\xec\xa7\xcd2\ +\xeePG7j\xc3\xe0O\x89\xee\x12\xc7\xf8\xc2\x18\xcd\ +\x0a^#z\xd8\xc4\x0e\xaa\x18%\xc6g\x1ca\x15\x0d\ +\xf4\xcaI\xf3\x1b\x07\xf8\xc0\x15\xb6\x93^\x1d-tb\ +\x80\xd4\x08\xefh\xa2\x82\x07\xacc\x037\x18\xe04\xbd\ +c\x1e\x8fh\x87\xa1\x8b\xdb\xd0\x1d\xc6\xa9\x88\x9d\x8b\xd0\ +\xc6.\xf6\x827\xf0\x96\x0a\x8a&\xc2\x04\xe7\x91\x0fq\ +\x9f\x17,2\xc2On\xfd\xb3q)\xfem,z\x9c\ +\x15\xacE\xccy\xd5\xec\xde\x9f\xcb\x8c[x\xc9\xf1\xb1\ +\xd9\x1f\xd7\xe6\xc5)P\xcb+^\xfd\x05+R\x00\x00\ +\x00\x00IEND\xaeB`\x82\ +\x00\x00\x01\xcf\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xffa\ +\x00\x00\x01\x96IDAT8\x8dm\xd3M\x88\x8eQ\ +\x14\x07\xf0\xdf\xf3\xf4R\x83\x8d\x05\xc5\xbc\x14)\xcd\x8a\ +\x95(R\x13\xa5\xac\xcc\xc6GMJY\x8cX(K\ +\x99\x8c\x05\x9a\xb1b\xc3b\xc6\x82R2\xd9\xc8(_\ +eA\x16b\xa1\xde\x84\x89Y\xccBB\xa4\x19\x1f\xc3\ +\xe2\x9e\x9b\xdb\x93S\xb7\xdb9\xf7\x9c\x7f\xff\xf3?\xe7\ +V\x9dN\xc7\x7fl\x1b\xfa\xb1\x05m\xfc\xc6\x1bL`\ +\x0c/sb\xd5\x00X\x82\xab\xd8^\xc4>\xa3\x85E\ +\xe1\xcf\xe1\x22\x8eb\xb6.\x12\xdbxZ\x14\x7f\xc3q\ +,\xc7\x0a\x9c\xc3\x0f\xd4\x18\xc0=,\xc8\x0cj<\xc6\ +\x06\xcc\xe0\x12\xce`\xba\xd1\xda\x1a\x0ca\x0f*\x8ce\ +\x80\xfd\xb8\x8c)\xf4\xe2uQ\xd4\x1d\xa0\x1f\x8b\xd8F\ +\x5c\xc1\xea\xdc\xc2\xc1\xb8\x87\x1b\xc5\x83x\x8bI\x9c\xc4\ +\xc2\x88?\xc1mT5\xba\xb0)\x1e\xde5(\x0fc\ +/n\xe20\x9ec}\xa1\x91VP\xccLv\xe2\x96\ +46\xf8\x8e\xf18-i\xac\xfb\xd0\x87u\x19\xa0\x9c\ +\xc44\x0ea-\x1e\xe2\x0e\xbe\xc6\xdb/<\x88C\xd2\ +L\x8d\xf7\x98\x8d\xe0+\x9c\xc7(\xce\xe2\x83\xb4<\x03\ +X\xdah\xefE\x06\x98\xc1\xfd\x08\xce\x8b\xfb\x19zp\ +,\xee\xc1L\xb9\xb0\x1e\xfem\xe2\x0eI\xd5I\x1c\x08\ +\xfa\xa5U\xf8S\xf8}\xb8\x86\xb9\xdc\xff\x84$\xd4\xaa\ +\xe8q\x5cZ\x9al\xb9xs\x80\xdf\x08\xb6\xa7K\x01\ +\xfb\xa5m\x84]\xd2\x87\x19\xc1b\xac\x8c\xa2G\xd8\x1a\ +9\xa3\x18j~\xa6.\x9c\xc2\x11\xcc\x8f\xd8\xcfh\xa1\ +\x15\xfe'\x9c\xc0\x85R\x83\xa6\xb5\xb1[\x9a\xfb2i\ +\x84S\xb8\x8b\xeb\xf8\x92\x13\xff\x02w\x5ckPMg\ +\xdc\xa5\x00\x00\x00\x00IEND\xaeB`\x82\ +\x00\x00\x01\x86\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x0f\x00\x00\x00\x0e\x08\x06\x00\x00\x00\xf0\x8aF\xef\ +\x00\x00\x01MIDAT(\x91\x85\xd21K\xd6Q\ +\x14\x06\xf0\x9fW\x0a)jhh\xc8h\x91\x1c5\xe9\ +PRIC\x82\x0e\xd9 !\x82\xd1j\x1f \xa8o\ +\xd0\x16\xb4\xb4\xd4\xe6`\xb4DB\xadA\xe0\x10\x1dT\ +hlh\x11A\x8c\x8ah\x10\xa9lx\xef?^\xfe\ +\xf0\xf2\x9e\xe9\x9e\xe79\xcf}\xce9\x9c\x01\xad\xc8\xcc\ +\x9bX\xc6\x15\x9c\xc2O|\xc4s\xbc\x8c\x88\xbfM\xed\ +@\x97\xe8\x18V0\x8f/X\xc3W\x9c\xc6\x0cF\xf1\ +\x1e\xb7#b\xaf-^\xc3\x1c\x1e\xe0qD\xfc\xee\xe2\ +\x0a\xee\xe2)>a*\x22\x0e\x1ar!3\x0f3\xf3\ +~{\x8c\xd6H\xb3\xb5\xee\xe1\x7f\xe7\xcc\x5c\xc7qL\ +D\xc4a\x9f\x0f^\xe0\x1a\xce\x95\xcc<\x89I\xac\xf6\ +\x13\xd6X\xc50F\x0b.\xa3`;3\x8f\xf4q=\ +\x8a]\xfc\xc1\xa5\x82G\x95\x1b\xc7\xab>\xaeou\x96\ +:\x88{\x05\x17*1\x86\xc1\xcc\x1c\xe9\xe1:\x82)\ +|\xab\xd0\xc5\x82\x1f5\xb9\x8e7X\xea\xe1z\x07\xef\ +p\xb5\x01\x0a>\xd7\xf7\x10~a\xb1\x87xI\xe7p\ +\xa6k\xbeY\xf0\xba\xab\xe0\x06\xf62s\xac\xd5\xf2$\ +\xcec\x1f'*\xbcR\xf0\x04\x9b\x15\x98\xc7\x87\xae\xb9\ +\x9a\xd8\xc7\x16n\xd5|\x03\xcf\x9a#9\xab\xb3\xe93\ +X\x88\x88\xf5v\xcf\x999\xa1\xb3\xed\xef\x98\x8e\x88\x9d\ +\x7fI\x1dq\x82#,l\xf1\x00\x00\x00\x00IEN\ +D\xaeB`\x82\ +\x00\x00\x01\xc6\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x11\x00\x00\x00\x10\x08\x06\x00\x00\x00\xf01\x94_\ +\x00\x00\x01\x8dIDAT8\x8d\x9d\xd3M\x88\xcda\ +\x14\x06\xf0\xdf\x9d\x99\xcd\xd8h\xc6,$ERS\xcc\ +4\xa5\x135\xd9\xcclg(\x12\x1b\x0b)\x16>v\ +\x16\xa2,(\xcdF\xcab\xa6\x1b[\x85\x22+K\xf9\ +X\xb9\x0ee!#D\x16\xa8!\x09\xc9\xc2\xc7\xe2\xff\ +\xcet\xfb\xd7\xcc\x8dS\xef\xe6=\xe7<\xcfs\xbe\x1a\ +\xfe\xd32\xb3\x89\xfd8\xde\xe8\x108\x82\xb5X\x85\xd5\ +\xe8F\x17\xd6c\x1bz\xd0\xea\xe9@x\x06O1\x83\ +\xe5\xd8\x83e\xb8\x82\xbeBp\xa2{\x09\x15\x1bp\x16\ +\xc3\xe8G/\x9ax\x84\x83\xd8\x87\x81\x88hv-\x02\ +\xb0\x157\xf0\x10o\xd1\x8a\x88i\x0c\xe04\x0eG\xc4\ +\x17\xfcVj\x9aO\x5c\x89\xbdE\xe2\x1b\xac@\x94w\ +)3[8R\x00~df?>B#3\x03\xc7\ +\xd0\xc0\xbb\xc26\x8a\x8b\x111U\x08\xee\xa8\x9ay\x0b\ +\xcf\xf1\x12?\xf1=\x22\xee\xf7\x14\xc6\xed\xc51\x8b\xc7\ +\xb8\x80'm\x15\xee\xc4H\x01\x1a\xc4I|\xc2\x98\xc2\ +.3\xc7q\x0d\xbb#\xe2\xf6b\xcd.\xb1S\x98\xc0\ +xD\xccQ\xcd\x5cI\xdc\x81\xcb\x999\xf9/\x00\x0b\ +J\xda\x82\xb6\xe0\xaejt\xdfj\xbeI\x9c\xc7h;\ +\xc0\x82\x926{\x8d\xafu\x80b\xef\x8bo\xae\xee\xa8\ +o\xec\x90jCef/\x8e\xe2\x05n\xe2\x19\x063\ +\xb3;\x22~-\xa5d\x08\xb3\x99y\x08\xaf\xb0\x19\xa7\ +\xf0@5\xf6\x0fXWWR\x07\x19\xc6\x01\xd5qM\ +D\xc4.l\xc29Lc\x0d6v*\xe73\xc6\x22\ +\xe2\xde\xfcGD\xfc\xc1\xd5\xcc\xbc\xae\xba\x97\xbe:\xc8\ +_\xc6l\x83y\x0c\xda\xbaW\x00\x00\x00\x00IEN\ +D\xaeB`\x82\ +\x00\x00\x01\x89\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x15\x00\x00\x00\x14\x08\x06\x00\x00\x00bKv3\ +\x00\x00\x01PIDAT8\x8d\xad\xd4\xb1K[Q\ +\x14\xc7\xf1O$\xb4\xee\x12j\xabq\xaaYJ\x05\xc9\ +_P\x07\x17\x07\x17\xc1BE:T\x90\xae\x9d\x0a\xed\ +\xa0t\x13\x97v\xc8\xd8\xc5\xc1E7\xdduN\x16\xa5\ +\x94\xd6M#m\x05'\x95XQ\xe2\x90\x9b\x12\x02\xef\ +\xbd\x9b\x92\x1f\x5c.<\xce\xf9\xf2;\xf7\xc7y\xb9f\ +\xb3)I\xb5Z\x0d\x9e\xe3\x00oQ)\x97\xcb\x89\xf5\ +m\x0ddV\xfc\x87b\xa1?P\x8d\x85\xe6\x92\xc6\x0f\ +\xa3\xc3C\xdc\xe16\x16\x1a\xe3\xf4o\x00\xe6\xf1\x1a\xab\ +\xfd\x80\xe6\xb1\x88\xef\xf8\x8a\xc7\x18\xc7`RC\xd6\xf8\ +S\xa8\xa0\x94\xd0\x7f\x86S\xd4q\x1c\xee\xbd|\x86\xcb\ +}\xac\xe1#\xc6\xc2\xb7?\xf8\xd6\x01\xfb\x85\x93p\xd7\ +\xf1;W\xadF\x85\xfa\x00\xcbx\x8f\x1d\xbcI+\x8e\ +y\xd3\x12n\xf0\x19O\xb1\x9d\xd5\x10\x03\xdd\xc2\x86V\ +8W\xd8\xcdj\xe8|\xd3A\x8c\xe0\x09F;\xee!\ +\xbc\xc2\xbcV\xfa\x9f\xb4B\x91\xb4\xb2y\xbc\xc44&\ +\x03\xb4\x90b`\x093x\x81\x9fiN7\xc3\xe9t\ +\x5c\x0c.\x8bx\x87\x09\x9cc\x1d_p\x99\x04lC\ +\xbbu\x8d\xa3p`\x01\x1f\xb4\x82\xbaH\x83\xa5A\xbb\ +5\x8bF\x0c\xac\xad\x98\xf4\x1bx\x86\xb9Xh\xe2\x9a\ +\xf2oU\x0b8\xc4\x8a>\xfe\xa4\x87\xf1(\xcab\x0f\ +\xd0\x9eu\x0f\xb5UQ\xc4\x18\x14\xeam\x00\x00\x00\x00\ +IEND\xaeB`\x82\ +\x00\x00\x01J\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x0d\x00\x00\x00\x0d\x08\x06\x00\x00\x00r\xeb\xe4|\ +\x00\x00\x01\x11IDAT(\x91\x85\xd2\xbf+\xc4q\ +\x1c\xc7\xf1\xc7\x9d\x93\xe4\xa2\xcb \x8b\xb2(\x7f\x00\x03\ +e2\xa0\x94\xd1 \xeab\xb1 \x0b2#\x93,\x16\ +\x89\x0c&E\xba\xc2\xa0\x84\x81\xbe\xc9$\xeb1\xa9\xeb\ +&\x8b\x1f\xc9p\x9f\xab\xef\xe9\xe2=\xbe?\xaf\xe7\xe7\ +\xf5\xfa|z%\xa2(\xca\xa3M\xe5\xaca\x11\x0bX\ +\xfduv\x9d\xc24\xd2\xd8@\x0b\xe6p\x11\x04Gx\ +\xc5\x16^\xb0\x84B\x0a\xb9 x\xc3\x09\x06\xb0\x19v\ +O\x98G\x0ac\xb8\x85d\xcc6\x87\xed\x00M\x85\xdd\ +0&\xb1R\x06 \x11EQ\xcc\xe2\x1c\xcb\xe8\xc0z\x5c\x14\xff\ +\xbdN\xdc\xe3,\xc4\x83\x1a\x5c\xa2\x07C8-;e\ +\xd0\x8c=\xbc+\xd5\xa7.@)\xa5\x86|`G\xa9\ +n\x99$\x8a(\xa0\x0bMxD6@Y\xdc\x85K\ +Z\x91G\xf1\x07i\x04=o\x03\x18\x5c\xb7\x00\x00\x00\ +\x00IEND\xaeB`\x82\ +\x00\x00\x02\x15\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x13\x00\x00\x00\x14\x08\x06\x00\x00\x00oU\x06t\ +\x00\x00\x01\xdcIDAT8\x8d\x9d\xd4]h\xcfQ\ +\x1c\xc7\xf1\xd7\x7ff)\xe5\xa15\xca\x05\x174\xb5\xd4\ +\x94\x8b\xb1%\xb1\xac<\xa4(S\xd4.\xdcz\xb8q\ +\xe7F\x89\xc2\x8dZ+)\x96I\xc9\xe4!\x91\x9a\x84\ +\x95q\xf1\xbf\xf0\xfc\x90;#\xa1\x11.H\xcd\x5c|\ +\xcf?\xbf\xfe\xfe\xff\xfd\xd6N\x9d\xce\xefw\x1e\xde\xe7\ +\x9c\xcf\xf7\xf3=\x85b\xb1h\x02\xa5\x06\xbbS]\x88\ +W8\x8a\xb3\xd9I\xb5\x13\x00MA/\xba\xd2\xff\x07\ +4\xa1\x0f\xd3q\x22\xbbc\x1e\xe8L\x02\xbdG+\xe6\ +a#\xc6p \xcb\xc8\x83m\xc5z\xbcD\x1b\x1e\xa4\ +\xfe\x1b\xf8\x84\xb9\x98Q\x9a<\xde5g\xe2\xb9\xd0\xe8\ +\x07F3c+1\x07\x1f\xf1}\xbc\x93M\xc3)\x8c\ +\xe0Ij{Q\x97\xc6\x97\xe2\x0a\x0a8\x84?\xd5N\ +6\x0bW\xb1\x0a_q_\xe8\xd4\x85~!\xfe\x00\xea\ +q\x1c=\xd9\xc5YX\x03n\xa1\x19/\xb0\x0d\xef\xd2\ +\xce\xab\xf1\x13w\x84F=\xd8W~\xa5\x12lv\xda\ +\xb1\x19\x0f\xb1\x01\x97\xb1\x1c\x17D\xe4v\xa4\xf9G\xb0\ +?\xf5\xfd\x07\xab\xc3\xcd\xa4\xc5\x10\xd6\x09Q\xcfc\x85\ +\x7f\xfe\xfa\x85\xbd2\xbe\xaa\x04\xdb\x8e\x16<\x126(\ +E\xe7\xa4\xd0\xaf\x15SqOD\xafj\xa9\xc1\xb2\xf4\ +\xdd\x8do\x99\xb1\xcd\xb8\x8bMx\x9c\x07*\xc1\x86\xd3\ +w{\xa6\x7f\x0f.b\xb10\xec\xeb\xfd7\x08\xdf\xb5\xd4\xa6\xe3w\x88\x1c\x5c\x92&\ +<\xc3.\x0cV8@\xbf\xc8\xcfF!\xc55\xe1\x82\ +\xa6B\xd9\x134?\xb5\xc3*\x84>\x95v\x5c\x12\xe9\ +\xf6[\xb8a\x04[\xca\xd3\xe9m\xaa\xd5@p[\x04\ +e,\x81F\xb1\x16\x83y\xafF\xa5\xd2\x88\xd3\x227\ +\x89g\xea\x1c\x16L\x06v\x1d\x8b\xc4\xd5:\xf1Y<\ +\x96\x03\x93\x81\x1d\xc6\x1b\xac\x11\xf6\xe9\x10\xd69\xf8\x17\ +-\x83l\x7f\xf5\xb9\xae\x1b\x00\x00\x00\x00IEND\ +\xaeB`\x82\ +\x00\x00\x02\xff\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\ +\x00\x00\x00\x04gAMA\x00\x00\xb1\x8f\x0b\xfca\x05\ +\x00\x00\x00 cHRM\x00\x00z&\x00\x00\x80\x84\ +\x00\x00\xfa\x00\x00\x00\x80\xe8\x00\x00u0\x00\x00\xea`\ +\x00\x00:\x98\x00\x00\x17p\x9c\xbaQ<\x00\x00\x00\x06\ +bKGD\x00\xff\x00\xff\x00\xff\xa0\xbd\xa7\x93\x00\x00\ +\x00\x09pHYs\x00\x00\x0b\x12\x00\x00\x0b\x12\x01\xd2\ +\xdd~\xfc\x00\x00\x00\x07tIME\x07\xe0\x01\x08\x0f\ +\x12,c4\xebp\x00\x00\x01\xeeIDATX\xc3\ +\xed\x95\xbdk\x14A\x18\xc6\x7fo\x12D\x09\x09\x82 \ +h#H\x02\x16I\x99\xbf }\xdap\xdb\xc8\x92\xca\ +\xe2\x16\xff\x00\xc12U\x88\xec\x15!\xd5\x14\xe2\x1e)\ +\x02Q\xc4t6\x92\xc2\x90\xc6B,\xceBN\x11<\ +\x0c\xf9 \x09\x5c>nR\xdc\x9c\xbeYw7\x93\x8f\ +\xce}\x96\x81w\xe6}v\xe6\xd9g\xde\x99\x85\x12%\ +J\xfc\xef\x90\xbcD%\xac\xde\x03\x06]\xd7*\xfeA\ +\xdd\xd4~\xa6\xb8\x0f\x81\xfb\xc0\x100\x00\x1c\x01m`\ +\x17\xd8\xac\x9b\xda\xb7\xbcu\xfa\xf2\x95\xc9\xa2 \x0d\xa0\ +!\xc8W\xd7\x1a@3\x08\xa3\xf5 \x8c\x1e)\xeec\ +A>\x08\xf2\x0ex#\xc8\xaa \xef\x05\xd9\x00\xee\x04\ +a\xc4\x85\x05\x00\x87\xea\xeb;\xca\x85~`\x02\xf8\xa8\ +&>*\x98g\xb7h\x0b\x06\xce\xdd\xa4\xae\xedS\x89\ +\x89\xdf\x06at\x17X\x03F\x80a\xe0)\xf0\x22\xc5\ +\x9f\x06\xda\x89\x89_{\xcc\x9d\xef\x80uO/\x06H\ +L\xdc\x02\x9e\xdb?Y;\xa9\xb9\x8a\xe7\xb5x\xa1\x03\ +\xe2\xea\xd3b\x11D\x17\xeb'\xf9[\xbb\x0f4W\x8b\ +\xbd\xb2\x80\x02\xec\x03\xc7\xee\xdd\xe1,B\x10FO\x80\ +&\xb0e\xb1;\x82|NL|m\x02\x8e\x81\x13\xf7\ +\xee\xcd\x8c\xfcR\xaa?v)\x07\xb4\x95)[\xc5b\ +{\x9e\xf7g\xe4\xcf\xed{\x09H\xd5\x80N\xdd\x12\xe4\ +\x86\x8b\xdb\x9a\xeb\xf8\xd3\x82\x9c$&^\xf6\xb1\xb3\xcf\ +\x87\x94\xc2m\x15og\x11|\x17\xbf\x88\x80\x8e\x8a'\ +U\xfc\xe5\x12\x1fp\x06\xbe50^\x09\xab[\xc0(\ +\xf0\xccb-\xdd\x0b\xeaU\x9a\x0bP\x09\xabU\xa0\x05\ +\x1c\xb8\xb6\x0d\xfc\xaa\x9b\xda\x0fo\x01\xbd\xb3\xefj`\ +V\x0bs{\xbe\x9a\x98xEs]~)}/\xb8\ +\xfe\x18\xe0/\xc0\xa9n\xd1=r\x1a-\xe0eb\xe2\ +95\xb6\x07\xfc\xe6\xdf\x7fB\x07\xf8\x0e,\x90\xf3\xbf\ +(\x120\x935X7\xb5\xac\xe1y\xd7\xb2\x9c\x04 \ +\xef\x22*Q\xa2D\x89S\xad\x83\xa9\xe2\x81\x96I:\ +\x00\x00\x00%tEXtdate:cre\ +ate\x002016-01-08T1\ +5:18:44+00:00\x8e\x05\xfd\ +\xe0\x00\x00\x00%tEXtdate:mo\ +dify\x002016-01-08T\ +15:18:44+00:00\xffX\ +E\x5c\x00\x00\x00\x00IEND\xaeB`\x82\ +\x00\x00\x01\xeb\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x11\x00\x00\x00\x10\x08\x06\x00\x00\x00\xf01\x94_\ +\x00\x00\x01\xb2IDAT8\x8d\x95\xd3Oh\xcfq\ +\x18\x07\xf0\xd7\xf7\xb7%s\x908(.\x8aYM\x19\ +y\x14\x8a\x1c89\xb98\x92\x9b\x96\x7f3\xb2&\x9b\ +?5\x89\xb3\xc2\x8a\x5c8)M\x9a\x03Jqz\x0e\ +\x86\x83\x03\x07\xb2\xd5\xe4_\x88R3\x87\xdfw\xf5m\ +~#O}\xeaS\xef\xe7\xfd\xee\xfd|\x9e\xcf\xbb0\ +Cef+\xce\xa1\x1d\x0f\xd1\x13\x11\xef\x1b\xf5\x16\x0d\ +\xc8\x813X\x8d\x05\x15h\x14\x8fq$\x22^7\x14\ +\xc9\xcc-\xe8\xc7J\xcc\x9d\xc9!\xde!q4\x22\x9e\ +C\x91\x99;p\x18+0\xe7/\xe4\xe9\xf5\x09#\xe8\ +\xada\x02\xcd\xe5\xf9\xdf\x9a\xc0\xaf\x022\xb3\xc0nt\ +\xa3\x0dM\xffp\xf0\x04]\x111\x02\xb5\x12X\x8e]\ +X\x88>\xbc\xc0\xe44\xf2\x07\xdc\xc1N\xacCWf\ +\xce\x83Zf>\xc2S\xbcA[D\x0c\xa0\x03\xa7\xf0\ +\x0a\xe3\x18\xc2\x86\x88\xd8\x16\x11\xb7\xd57\xb7\x0c\xe3\x99\ +y\xbdY}m\xab\xb0V}3\x0f\x22\xe2'Nd\ +\xe6Y\xcc\x8f\x88\xd1);\x99Y\xc3&\xb4\xe23\xee\ +O\xbd\xc9,\x9c\xc4\x01\xbc\xc5\xfe\x88\x18\xae\xceR\x92\ +;\xcb\xbeB}\xa3W\x22b\xb2\xc8\xcc\x96\xd2zg\ +i\x7f\x08{\xf1\x11\xfb0\x8cC\xe8\xc1w\x9c/\xef\ +\x05\x8ec\xb0\xc8\xcc\xaf\x98\x8d\xed\xe5\xbc2\xb3\xb9$\ +\xf6\xa2\x05c\xe8\x8e\x88\x9b%^\xe04\x8e\xe1e\x91\ +\x99m\xb8\x88\xf5\xb8\x85\xce\xa9\x8cdf\x13\xda#\xe2\ +Ye\xac\x0e\x5c.\xdf\xef\x06\x0eV\xbf\xfd\x12\x0cb\ +#\xeebOD\x8cU\xf05\xb8\xa4\x1e\xc8k\xea\x19\ +\xfaB\xe3\x00..\x9dm\xc5=\x5c\xc0\x00\x96\xe2\xaa\ +zf\xbeU9\x7f\x88T\xc4\x16\x95\x02\x9bK\xfb}\ +\x11\xf1\xa3Q\xefos\xf3\x98\x0b\x981\xe3\xce\x00\x00\ +\x00\x00IEND\xaeB`\x82\ +\x00\x00\x02\x91\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x14\x00\x00\x00\x11\x08\x06\x00\x00\x00\xddD\x8c\xbe\ +\x00\x00\x02XIDAT8\x8d}\x93QhVe\ +\x18\xc7\x7f\xcf\xc7>(u\xcb\xae\xc4\xd01\x91\x85|\ +Q\x9a\x9eH\xac\xad\x18\x12\x14\xee\xb2\xb0\xebH(\x1a\ +\x0c\x04a\xdd\x85\x17\x0e\x12/\x82\x04\xe92\xbf`\x22\ +\x08\x0e\xbb\x182%\xb5\xa0\xde\xb352\xa9\x1b\xa9\x8b\ +\xe9\x96\xae\xf8J\xc4\xc2\xfau\xd1\xfb\xe9\xd9\xe7\xf2\xb9\ +9\xe79\xe7\xf9\xff\xfe\xff\x07\xde\x17:J]\xa3\x8e\ +\xa8g\xd5y\xf5\xb6\xba\xa4\xce\xa9\x1f\xa9;;5Y\ +\x87\xfa\xc0\xc7\xb7\xd4\x9b\xea\xd5\x0c|^\xedS\x9fR\ +\x87\xd5O\xd4[\xea\xa4\xfa\xc4C\x81\xd9\xfd\x8e\xfa\xae\ +\xfa\xb1\xba\xf1\x7f\x92lR\xcf\xa9\xd7\xd4-+\x02\xd5\ +\xd1\xbc\xda.\xb5\xa6\x9eZ\x09V\x11\xd7\xd5\x93y\x93\ +\xb5\xcb\x80joN6\xa6nW_S\x0f?\x0c\x98\ +\x01\xab\xd4\x9f\xd5\x0f\xab\xc0.\xe0m\xe0Z\x9e\xdb\x09\ +\xec\x02\xba\xd5O\x81_\x81q\xe0zD,\x03F\xc4\ +mu\x0a\x18P\x1f\x01\xee\x00\x84:\x0bLD\xc4x\ +vz\x07\xb8\x1c\x11\x17\xd4\xae\x99\x99\x99iu.\x22\ +N\xf7\xf4\xf4|\xd1\xdf\xdf\xffg\x9e[\x0d<\x0b<\ +\x07\x5c\x8c\x88o\x00j\xc0\x93\xc0\xb7\x15\xf3.\xe0\xaf\ +\x9c\xe2\xaez\x1exO\x9dj\xb5Z\x8beYN\xa4\ +\x94^_XXx\x1c\xf8\x0ah\x02\x7f\xb4\xc55\xe0\ +Q\xa0U\x01.\x01\xab*}\xb3\xf2\xfe\x98\xfa\x06p\ +b~~\xbeY\x96\xe5\x9a\x88\xf8\x05X\xac\x02\x17\x81\ +\xde\x8a\xe8\x07\xe0\x99vS\x14\xc5\x8f@by}\x07\ +\x0c\x15E\xd1\x0e\xf2{\x15\xf8%\xf0Jex\x0ex\ +\xa9\x03\xd0\xec\xe8\x9f\x06\x0e\xb6\x9b\x88\xf8\xbb\x0a\xfc\x0c\ +xS\xddP\xf9\xf9\x93\xda\x00Pw4\x1a\x8du\x80\ +\xc0\x11\xe0b\xd6\x8e\xa5\x94\xf6u\x18\x11j\x0d\xf8\x1e\ +\xa8\x03G\xf3\xb3\x17\xd8\x03\x5c\x00\xae\x00\xcd\xb2,_\ +\x05\x8e\xe5\x10\x1f\x00\xefg\x93\xe1\xa2(>\xbf\x07\xcc\ +)\x1aY\x5c\x02\x07\xf8\xef\x5c\x0e\x02/\x03#\x11\xd1\ +q\xeb!\xa5\xb4\x1b8\x0et\x03\x83EQ\x94\xed\x95\ +\x89\x88+\xc0\x00\xb0\x19\x98\x00\x86\x80I`\x1a8\xa1\ +n\xcd\xc6\xf56\xb0(\x8a\xb3\xc06\xe0\x12p&\xa5\ +\xd4w/a\xbb\xf2a\xdd\x0f\x8c\xe6\xd5\xbf\x06~\x03\ +\xb6\x00S\xc0\xa1\x88\xb8\xd1\x91\xb4\x96\xd7\xdf\x0b\x0c.\ +\xbfO\xf7\xc1u\xe0\x05`+\xb0\x1e\xb8\x09\x9c\x03f\ +#\xe2\x9f\x954)\xa5\x17\x81}\xff\x02\xe28ya\ +\x96\xfd\xc4\x97\x00\x00\x00\x00IEND\xaeB`\x82\ +\ +\x00\x00\x04x\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\ +\x00\x00\x00\x04gAMA\x00\x00\xb1\x8f\x0b\xfca\x05\ +\x00\x00\x00 cHRM\x00\x00z&\x00\x00\x80\x84\ +\x00\x00\xfa\x00\x00\x00\x80\xe8\x00\x00u0\x00\x00\xea`\ +\x00\x00:\x98\x00\x00\x17p\x9c\xbaQ<\x00\x00\x00\x06\ +bKGD\x00\xff\x00\xff\x00\xff\xa0\xbd\xa7\x93\x00\x00\ +\x00\x09oFFs\x00\x00\x01@\x00\x00\x00\x00\x00s\ +\x05\xb7\x16\x00\x00\x00\x09pHYs\x00\x00\x0b\x13\x00\ +\x00\x0b\x13\x01\x00\x9a\x9c\x18\x00\x00\x00\x07tIME\ +\x07\xdf\x0c\x12\x0e\x1b\x0b$&IW\x00\x00\x00\x09v\ +pAg\x00\x00\x03@\x00\x00\x00 \x00\xbe\xe6\x89Z\ +\x00\x00\x03=IDATX\xc3\xe5\x97MhUG\ +\x14\xc7\x7f'\xba\xf3\xa3`\xa3Q\xb1\xa9-(*\xb5\ +(6\x96 \xadP\xdc\xc4\x16\x04\xad\xe0}\xbb\xa1\xb8\ +\xb0p\x1fZ\xa8\x8b\x82\xe8\xa6\x14\xba\x11\xee\x05\x15\x17\ +N\xa1p/h\xa4.\x0b\x8d\xa4\xa4i\xd4E\x055\ +~ H\xd1*\xa95DP*\x88\xf6\x9d.\xdey\ +\x8f\xf1a\xde\xbb\xe6C\x17\x9e\xcd\x999\x1f\x9c\xff\x9c\ +\xff\xdc\x99\xb9\xf0\x8aE\x8a\x04\x95\x5c\x19`\x8f\xa2?\ +\xe4>\xbd\xff*\x00\xfc\x02lR\xf4\x0fA>\xc8|\ +\x12\xfa\xf6\x03\xf3\x81S\x99O\xfa\xcc\xd6\x03lVT\ +\x049\x92\xf9d\x18 r\xf1^A:\x81\x93\x99O\ +\xfa\x01f\x16(~\x14\xd8d\xd3u\xc0I`[\x10\ +\xf21\xf0\x090\x0f\xe83\xdb\x97\xc0g6\x1e\x05\x86\ +K\xae\x8c\xa2_\x03\xed\xc0O\xb5\xe4\xb6f\xc5#\x17\ +\xefUt\xa7\xa2\xaah\x05PE\xb7F.\xfe\xbe\x16\ +\xa3\xe8iEQ\xf4\xbd\xc0\xd6\xadh}l\xfam\xa0\ +\xddbO\xb7\x04`\xbc\x7f+\xc8cA\x9e\x0a\xd2\x06\ +\xfcg\xf3\xafJ\xae\xdc^\xe5P\x06\x05A\x90w\x22\ +\x17Sr\xe5E\x82\xbc)\xc8C\xe0\xb1 \xdd\x16\xb7\ +\xca\xf4\x95\xdc\xa7\xb4\x04`\xb2\ +y/0\x02\xcc1\xb0k\xcc~.\xac\xd3\x94\x82\xdc\ +\xa7c\x99O\xfe\x01\xc6\xcc\xf4 \xf3\xc9hP\xbc\x06\ +\xf4b\xb0G6\xda\xf8\x14p\xd9\xc6\x1b\x80\xb5\x0d\x80\ +[\x03\x088\x95\x1a\xa7\xe3\xf8\xcf\x99\xbfK\xd1.\xe3\ +y\x10\x18\xb2q\xb7\xa2\xab-\xf6\xec\x0b\x030\x8e\x9b\ +\xf9\x07\xcd\xdf#\xc8rAn\xe5>\x1d\x03\x86,w\ +\x8b \x8b\x80G\xb9O\xaf\x85\xb9-?\xc3\x82\xf2\xbb\ +\xe9\x95\xa6\x7f6}\xde\xf4\x0a\xd3\xfd\x8d\x89\x85:\xd0\ +J2\x9f\xdc\x00\x1eA\x9d\xa7~\x80\xdc\xa7\x0f\x80+\ +A\xe8\xaf\x13\x02`<\xb6\x8a9\x03\x88\xc5\x0e\x04\xf6\ +\x0bA\xfePc^!\x0aj\xfc7\x03!\xc8nE\ +\x97\x0b\xa2\x99O\xae\x06\xf6\x03T?\xc9\x8a\xa2}\x8d\ +yS\xb5\x07\xb0\xf3~\xf89\xf6\xeb\xc0\xf5\xf1\xf2\xa6\ +d\x0fLF\x0au\xa0\x15\xff\xd3\x0e\xa0\xc8\x1eh&\ +v=\xc7\x8an\x0e\xef\x01xy\x14,\x03z\x80[\ +%W^\xfa\xc2\x1d\x00*\xa6\xe7\x96\x5c\xb9\xa3\x96\xa7\ +\xe83'\xe48\xf3\xa7\xc0\x1bfz\x0b\xb8Tr\xe5\ +O3\x9f\x0cT\xbb[@\x22\x17\x1f\x07\xb6O\xb2\x0b\ +\x15\xab'\xc0\x13`q\xee\xd3\xd1\x22/\xa2\x13\xc0\xe7\ +\xc0\xdf\xf6$\xab\xd3V\xb0\x03\x15\xe0]`\xa5\xa2j\ +\xfe\xdf\xa8\xbe\x94\x9aS\x10\xb9\xb8\x97\xea\xf3\xeb&\xd0\ +\x95\xfb\xf4\xdeD\x96^r\xe5]\xc0![\xfd\xb1\xcc\ +'_\xd4|mA\xd0\xda\x86\xa4<(\xde\x9d\xf9d\ +B\xc5Mf\x98\xfe&,^\x07\x10\xb9x\x81\xa2\xe7\ +#\x17\x1f\xb6y\xa6\xe8\x0e\xe0\x8e\xa2\x1ff>\x19\x99\ +Dq\x14\xedUtc\xee\xd3\xef\x1a}b\xab]\x0a\ +\xfci\x9c\xfdEu\xb7\xdeV\xf4\xfd\xa9\xfe\x0fh\x94\ +\x1a\x05\xed\xa6+V\xfc_`\xfdt\x17\x0f\x01t4\ +\xd8g\x01\xfb\xa6\xbbx\x1d\x80\xa2\xf3\xec\x98m\xd3\xfa\ +\xed\xaf\xbb\x22\x17G\xd3\x0d`&\x80 ?\x02\x9d\x8a\ +>\x11d\x04\xb8\x0b\xdcU\xf4\xc2\xcb\xe8\xc2\xeb-\xff\ +\x03Q\x9bYF6Y\xf5\xec\x00\x00\x00%tEX\ +tdate:create\x00201\ +5-12-18T14:27:11\ ++00:00YM\xe3\xc6\x00\x00\x00%tE\ +Xtdate:modify\x0020\ +15-12-18T14:27:1\ +1+00:00(\x10[z\x00\x00\x00\x00I\ +END\xaeB`\x82\ +\x00\x00\x01U\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xffa\ +\x00\x00\x01\x1cIDAT8\x8d\xa5\x92?K\xc3P\ +\x14\xc5\x7f\xa9\x11%\x8b\x1d\x5c\x5c\x05\x05'\xa1\xdcM\ +\xfc\x02*n\xd9\x5c]\xc5/P\x1c;\xf9=\x1cU\ +\xea\x87\x10\x0eq\x12\xc4\xa5\x11\x8b\xe0\xa6(4R\x9a\ +8\xe4EB\xdaj\x82\x07\x1e\x8f\xfb\xe7\x9c\xfb\xce\xe3\ +z\x922 c6\x92J\xbc\x08\xf8\xc0\x17\xb0\x04\x8c\ +}G\xf6f\x90\x07f\xb6^NH:\x05B3\xdb\ +\x91t\x09\x1cx\xee\x05\xef\x15r\xcbM\xb8\x02\xd2R\ +~\x1b\xd8\x04\xae\x81=`\xc1\x07\x86\xc0\xee\x1c\x0b\xbf\ +\xe1\x0c\xe8\xfb\xc0\xc4\xcc\xe2\xa6lIm \xf5\x8bD\ +\x14E!\xb0_\x93\xff\x9c\xa6\xe99\xe4?Z\xe0(\ +\x08\x82\xc3:\xec$I\x1e\x0a\x81V\xcd\x89s\xf1o\ +\x81\xb2\x85\xa7\xd1ht\x0b,\x03\x9f\x95\xda\x9a;\x8f\ +\xc0[\x96e\xe3)\x81N\xa7s2o\x8a\xa4\x10\xb8\ +\x00\xb6\x80.\xd0\x03V\x9aX\x18\xba\xde\x04\xd8 _\ +\x22\x9a\x08\x0c\x80;\xe0\x1ex1\xb3\x9b)\x0b\x7f\xe0\ +\x158&_\xef\xbe\xa4\xdeOER\x5cS\xa4\xe8_\ +uw[R\xecI\xfa\x00&MD\x1c< \xfe\x06\ +\x8cB^q\x9bC\x89i\x00\x00\x00\x00IEND\ +\xaeB`\x82\ +\x00\x00\x01\xf9\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x13\x00\x00\x00\x13\x08\x06\x00\x00\x00rP6\xcc\ +\x00\x00\x01\xc0IDAT8\x8d\x9d\xd4M\x88\x8eQ\ +\x14\x07\xf0\xdf\xc3\xe4c\xf0\x8e\xa4\xa4X!a3\xf9\ +*55)!\x0b\x1f\xb1bMYH\x0a)+\x91\ +\x22\x89a%I\x16^5Y\xf8JV>J\x91G\ +Y(\xb11,$\xe3{2\xc64bq\xcfSO\ +\x0f\xaf\xf7\xcd\xa9[\xb7s\xcf\xfd\x9f\xff\xf9\x9fso\ +\x96\xe7\xb9\x16\xac\x1b\x07\xb0\x10\xef\xd0\x83S\xf8U\x0e\ +jk\x01h#.E\xec\x10f\xe1$j8T\x0e\ +\x1c\xd5\x04h-.\x22\xc3\x0eL\xc4\xb2\x00\xdd\x8b\xb1\ +\xad\x82M\x93J\xc9\xb0\x05\xa7\xf1\x13\x0fbM\xc2\x8c\ +\xf2\x85fe\xce\xc58|\xae$\xe9\xc40\xde6c\ +\xb6\x14O#p\x00\xe70=\xce:p\x0d\x93q\x16\ +\xdf\xfe\x05\xb6\x1a\xb7\xb1\x00/\xf1\x15\x1b$}j\xb8\ +\x89%\xb8\x87=U\x16e\xb05\xb8\x82v\x1c\xc4l\ +I\x93\xed\xb8\x80\x1b\x92\xf8O\xa4\xc6\x0c6\x02\xebB\ +/\xc6`\x1f\x1e\x06\xab\x13\x18\xc1\xf9\x88y\x8c\x15\xf8\ +R\x05\x225`\x1e\xae\x07\xa3\xfd8\x82\xc5\xd2@n\ +\x8b\x05w\xb0\xbe\x11P\x01v\x5c\x12\xf6(\x0e\x87?\ +\xc7|l\xc2L<\x0a\xe6#q^\xc3\x1c\xbcF\x7f\ +\xb9\xcc\xe5\xf8\x18\xac\x0a\x1b\x8d]\x18\x8f\xab\xa8\x97\x80\ +`w$\xe1\ +M\xd9\xf9\x1b\x87\xd0i\x8b\x22\xfc\x9f\xfe\x00\x00\x00\x00\ +IEND\xaeB`\x82\ +\x00\x00\x02\xbf\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x16\x00\x00\x00\x13\x08\x06\x00\x00\x00\x94y\xfd\x88\ +\x00\x00\x02\x86IDAT8\x8d\x8d\xd4]\x88\x97U\ +\x10\x06\xf0\xdf\x7fQ\xd0B\xdb2)\x08D]\xc9B\ +\xec\xa6!\x03\xa3\xb2 \xd1J(\x0d#\x13\x14\x0b\x8b\ +\xc0\x82\xad\x9b0\x0a\xa4@\x906BJ\x141\xb0 \ +$\xfb\xf0\x22r\xefV\xcc\x14fS\xe8\x036HJ\ +J\x0d!\xdd\xf2\x03#\xda.\xceYx\xf7M\xc9\x81\ +\xc3\xcb{f\xe693\xcf|t\xb4$3\xc7\xe1s\ +\x04\x0e\xe3B=k#\xe2\xf7js5^\xc63\xf8\ +\x0bK#\xe2@\x13\xa7\xab\x0d\x8c\xf9\x98\x80)8\x8e\ +\x07\xb1\x0c\xab*\xe8t|\x85n\xf4\xe0\x05\xack\x83\ +\x5c\x0a\xf8Z\x1c\x8d\x88\x11|\x8a\x91z\x7fCfN\ +\xc3\x00\xfa\x22\xe2\xb9\x888\x83\x1f0\xf5J\x80\x7f\xc5\ +4\x88\x88\xdd\x98\x8e\xdb\xf0\x08\x0e\xe1\xd5\x88\xd8\xd1\xb0\ +\x9f\x81_\xae\x04\xf8{\xcc\xcd\xcc\xf1\x15\xfc\x18\xbe\xc5\ +QL\xc2`\xcb\xfeN\x1c\xf9_\xe0\x888W\x9d\xef\ +o\x5c\xf7*\x94<\x81\x0fk\xf1Fe)\xf6\xb4q\ +:\xcd\x9f\xcc\x9c\x80\xdb\xf1\x12f)\xb4\xdc\x84[p\ +\xb1\x9en\x9c\xc0\xcf8\x85\x05X\x83\xfd\x11qb\x0c\ +pf\xce\xc3\x8b\xd5h\x10\x07\xf1<\x1e\xc5f\xbc\x16\ +\x11\xbb\xaa\xedU\xf8\x0e\xaf`%~\xabXw\xe1\x1c\ +\xb6bk'3{\xf1,6`wD\x9c\xad\x00\x9b\ +p7\xceD\xc4\x03\xad\xcc\x96\xe0\x0d\xa5\x83f7|\ +\xee\xa8\x01\xcd\x91\x99g3\xb3\xbb\xcdQf\xf6d\xe6\ +Hf\xceo\xeb\xaa\xfe\xeb\xcc|\xeb2\xba\xf7\xc6\xd5\ +\xb47d\xe6\xfa\x88\x18n\xe8\x17\xd4\xd4\x1e\xc2\x97-\ +\xc7\x99J\x1bv5\xee\x16b\x0b~\xc4\xad\x9d\xcc\x9c\ +Tix\x12\xfd\xf5\x1c\xc4'\x95\xa2\x0fp_D\x0c\ +5@\xf6`/\x1eG\x1f\xfe\xac\xdf9\xd5\xe4\xe9N\ +\xc3\xf8\x1a,Rx]X#\x1a\xc2u\x18V\xc6\x98\ +\xc2\xeb\x12\xa5\xc8=\x98\x88/p\x12O\xe1\x18\xe6\x8d\ +i\xb7\xc6#\xdbq\x00\x9f\xe1Fl\xc2\xdf\x15`#\ +\x1eS\x86\xe64~\xc2\x8c\x88\xf8\xa3\xf6\xf7\x85\x88\xf8\ +\xe7?\xc0\x99\xb9\x02\xef\xe0\xe1\x88\xd8W\xef\xaeG\xd6\ +\x94\xdf\x8e\x88m\x0d\xfb]\xf8h\xb4\x1dGe\xcc\xe4\ +e\xe6l\xbc\x8f\xc9x\xb3\xa1:]#\xbc\x19\xfbZ\ +\xb1\x0c\xe0\x9ev\x80\xed\x91\x1eVv/\x85+\x99\xd9\ +\xa5\x0c\xc9De\xff\xf6g\xe6\xac\x86\xcf\x90\xc2\xf5\xe5\ +\x81#\xe2$V+\x85Z\x91\x99\x93\x95\xd59S\xa1\ +f\x07\xd6c 3\xefm\xb8\x8eh\xc9\xa5\xb6[\xbf\ +\xb26\xfb\xf0M=\x8b#\xe2|}|'\x96\xe3\xdd\ +\xcc\xfc\x18\xaf+E\x1d#\xff\x02\xad\xb1\xf2$\x9a\xc7\ +|\xa6\x00\x00\x00\x00IEND\xaeB`\x82\ +\x00\x00\x02=\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x13\x00\x00\x00\x12\x08\x06\x00\x00\x00\xb9\x0c\xe5i\ +\x00\x00\x02\x04IDAT8\x8d\xad\xd4\xcfKTa\ +\x14\xc6\xf1\xaf6\x5cc&\x09\x84\x89\x91\x81\x82D.\ +.t\xa3\xa9\xa0\xb6\x17\x83\xcc\x7f\xa0\xeex\xab\x8d\x08\ +\xd5JJC\x0b\xda\x14ZV\x1b\xdf\xdew\xfa!\xb4\ +S\xaaM\xe0\xca\x19#52\xf1N\xbd\x17\xa1\xc8\x8d\ +\xad\xd2`\xae\xc9\x85\x99\xdb\xa2\x94\x8c\x08g\xecY\x9d\ +\xc5\xe1\xc3\xe1p8%Z\xeb\x1bV\xc2\xee\xa3\xc8\xbc\ +\x9aIm\xd7%Z\xeb\x00\xb8\x0b\xf4Z\x09;\xd8\x0b\ +V\x0a\xb0\xbc\xbc\xdc\x03H%\xc5\xbeb'\xdc\xc6n\ +\xde\x1a\xe6\x83\xd6g\x80Y%\x85\xb1'\xcc\xf7}\xd6\ +\xd6\xd6p2\x99z`RI\x11.\x1a\x03\x10B2\ +<|\x9b\x85\x85\x85v\xe0\x8d\x92\xa2\xbch,\x08~\ +\xee\xfe\xfb\xe6&\xa9t\xba\x06\x98RRT\x14\x85E\ +\xa3QB\xa1\x10cc\x0fP\xea!ss\xf3\x8d\xc0\ +[%E\xac`\xac\xaa\xea(\x03\xfd\x97\xa9\xac\x8ca\ +\x18\x06\xd9l\x96\x89\x89\xc9#\xc0\xb4\x92\xe2pA\x18\ +@<\x1e\xffxu\xa0\x7f\xa3\xa1\xbe\x9e\xc7O\xc6y\ +\xf6\xfc\x05s\xf3\xf3\xd5A\x10\xcc*)\xaa\x0b\xc2\x80\ +\xd7eeeM\xb6\x9d\xd0\xdd\xdd\x16\x87\xa2QV>\ +\xaf\x90L>\x8a\xe5\xf3\xf9i%Em!\x18V\xc2\ +v\x80\x86\xd6\x96\x96doo\x0f\xef\x16\x17I\xa5\xd3\ +8\x99L,\x97\xcb\xa5\x94\x14\x8d\xbb\xc6~\x81\x9e\x95\ +\xb0\xadxm\x9a\xe6\ +\xd3\xad\xa6\xd0V\xb1\xb4\xe408t\xad\x02\xf8\xe7\xa1\ +\x1e\x88Dp2\xefY_\xfff\x9c\xea<9\xee\xba\ +\xee~\xd34\x93;0\xcf\xf3\xf0<\xef_\xce\x8ed\ +\xb3Y\x06\x87\xae\x97^\xbaxA\xba\xae\x1b6M\xf3\ +\xfe\xd6?\xfb\x1f\xe9\xfb\x01\xfd\x9c\xd6\xcao\xa8\xd4\xb1\ +\x00\x00\x00\x00IEND\xaeB`\x82\ +\x00\x00\x01\x5c\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x0c\x00\x00\x00\x0c\x08\x06\x00\x00\x00Vu\x5c\xe7\ +\x00\x00\x01#IDAT(\x91m\x90?(\x84\x01\ +\x18\xc6\x7f\xef\xe7\x9b.\x03\xc9\xec\x06\x8aA\xc8`P\ +$\xebe0\xd8t\x03\x83\xc5`30;\x93U\xf9\ +su\x06\x8b\xc5\x22euJ1*\x97l\xca \x94\ +\xae\xfcI\xfd,\xdf\xe9K\x9e\xf1\xe9\xfd=\xcf\xd3\x0b\ +\x99\xd4.\xb5\xa2\xde\xa97\xea\xadZW\xcbjB^\ +\xea\x88\xdaP\xb7\xd5\xc9\x9c_T\xab\xea\x89Z\xc8'\ +7\xd4!u\x8d\x7f\xa4\xae\xaa5\x80P7\x80\x01\xe0\ +\x1c\x98\x02\x8e\x80\xb3\x88x\xf8\x03\xdd\x03s)0\x03\ +\x8cEDS\x058\x05Jj\x118\x88\x88[\xb5\x1b\ +\xa8\x03\xb3)@D4[I\x11\xf1\x08\xec\xa8)\xb0\ +\xac\xf6\x03\x83@\x15XJ\x80\xb6\x5cs\x9a\x03\xbf#\ +b\x0b(\x01_\xc0\x07\xf0\x91\x00\xcfY=@\xaaF\ +\xb6\xb9S]\x07\x8e\x81v`\x02\xb8\x0e\xb5\x0c\xcc\x02\ ++\x999\x0c\xbc\x00\xef\xc0nD\xbcf\xe0<0\x8e\ +\x9a\xa8\x97jM\x9dV7\xd5\xbe\xdcw:\xd4\x0bu\ +\x11\xa0U_\x00\xb6\x81\x1e`\x0f\x18\x02\xde\xb2\xdd\x0b\ +@%\x22\xf6\x7f\x81\x5c\xdah6\xaf\x17\xf8\x04\xae\x80\ +\xc3\x88xj\xdd\xfc\x00\xa7\xf6\xbd\x96\x10\xb6\xbf\xd9\x00\ +\x00\x00\x00IEND\xaeB`\x82\ +\x00\x00\x01\xd0\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x14\x00\x00\x00\x10\x08\x06\x00\x00\x00\x16\x18_\x1b\ +\x00\x00\x01\x97IDAT8\x8d\xad\xd4\xcf\x8bOQ\ +\x18\xc7\xf1\xd7w\x9aIJ\x8a\xac\xfc\xc8ld$\x0b\ +\xd33ca!ij\xa2\x99\xd9XY\xda\xd9Q\x9a\ +\x85\xc2\x1f )Jb\xa9l\xa7(EJ\x84,\x1e\ +\xc2\x86\x155\x89\x05\x9b\xafh\xfcfq\xcf\x9d\xb9\xa6\ +kL\x8dO\xdd\xee\xe9~\xde\xcf\xe7\xdc{\xcfsN\ +GQf\xae\xc55L\xe39n\xe0nD\xfc\xd2P\ +fn\xc38\x02\x1bq'\x22\x8e\xd4~O\x81\x86q\ +\x00\x83\x05\x1a\xc4\x15\xbc\xc8\xcc\xbd\x85\xd9\x93\x99\x0f\xf0\ +\x0c\x93X\x81\x01\xec\xca\xcc-\x7f\x04\x96\xb0\xa3e|\ +6\x22F#b\x1d\x0e\xe2tf>\xc4-|\xc1>\ +\xac\x89\x88\x11\xbc\xc4v\x9c\x9c\x0d\xcc\xcc{\x18\xc6X\ +y\xf6\xa96#\xe2>Na\x07ND\xc4\xee\x88\xb8\ +\x1e\x11\xdf\x0a\xf2\x1dO1\x9a\x99\x1b\xea7\xdc\x89\x9b\ +xW\xa0\x1a\xae\xf5\xa3\xdc/k\xd7\x13\x5c\xc2tf\ +\x1e\xee\xf9\x0b\xd4Tw\x11\xccq\xcc\xa0\x7f1\x81\xff\ +TD|\xc6W\xe6\x16\xe5\xbf\xa9-pI\x93\xb4\x15\ +\xaf\x5cJ}o\x0b\xb4?3\xfb0\x15\x11\xef\xd1i\ +\x9a\x99\xb9\x1a#\xd8\x8a~<^(\xb0\x8b!U\xf3\ +\x9e\xc9\xccc\xf8P\xbcU\x999\xa9j\xf6e\xf8\xa8\ +Z\xd9\x99f@'3\x7f\xe2*\xa6\xcc\xb5H\x9fj\ +\x07\x8c\x95\xe2Mx\x8d\xb7\xb8\xad\xea\xbd:hya\ +\xce\xe3b/.\xe0\x10&Z>\xbf\xa9\xf5\xe5\x1aZ\ +\x80y\xd3\x81\xcc\xdc\x5cfjj@\xb5;\xe6\xff\x96\ +\x09\xd5\x894_\xdd\x88x\xd5i1f\x95\x99\xe3\xaa\ +\xa3\xaa\x0e}\x14\x11\xe7\x16\xaa\xf9\x0d\xa0\xcdx<3\ +\xa5\x8a\xf0\x00\x00\x00\x00IEND\xaeB`\x82\ +\x00\x00\x01X\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x0f\x00\x00\x00\x10\x08\x06\x00\x00\x00\xc9V%\x04\ +\x00\x00\x01\x1fIDAT(\x91\x95\xd0\xbf\xab\xcfQ\ +\x1c\xc7\xf1\xc7\xe7v\xb8r\x19X\x94\x1feq\x07\x85\ +\xd4{`0\xf9\x03\x84R\x18\xac\x06\x832Q\xca\xbf\ +`Q\x06\xfe\x03\x0c\xba\x7f\xc3]^\x0b\x912(%\ +E\x08I_\xe12\xdcs\xeb\x9b\xe9x\xd6\xbbsz\ +\x9d\xf7\xb3\xf7\xe9=%\xd9\x84\x078l\x8c\xaf\xb8W\ +U\xb7\xa7$\x87\xf0tP\x9cg\xd7\x02\xde\xe3\xe7\x7f\ +\x8a\xcf\xf1i\x82$\xcb88(~\xc1jU\xcdZ\ +\x0f\x1a>\x0f\xcak\xd8\x86\xd9\x94\xe4\x12n\xe0\xc5\xa0\ +<\xe1(\xce5\x9c\xc0\xf5\xaaz8(Kr\x19\xa7\ +\x1b^\xe2T\x92\xb5Aw\x09WpkJ\xb2\xb5\x7f\ +{\xef\xa0\xfc\x1d+U\xb5\xd2\xf0\xabO\xff0(\xff\ +\xb1\xbeq\x0b\xb8\x8a\x0b\xd6\x171\xc2\x22\xee$9\xd3\ +\xb0\x8c\xbbU\xf5hP\x96\xe4\x1b\x8e5\xac\xe2Z\x92\ +#\x83\xeev\x9c\xc7\xd9\x86\xfb\xf8\x88\xfd\xff4\xed\xc0\ +\x01<\xc1\x8f\xb9\xfc\x0d\x8eW\xd5\xeb)\xc9nl\xee\ +\x0f\xfbp\xb3\xdf\xb7`'\xde\xe17\x1e\xf7\xda`\xd6\ +p\x11{z\xb0\x88\xb7s\x0d\xaf\xfa\xb9\x84\x93\xbd6\ +x\xf6\x17\xf1zO\xd5\x8bA\xa4\xa9\x00\x00\x00\x00I\ +END\xaeB`\x82\ +\x00\x00\x01\x0a\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x08\x00\x00\x00\x0d\x08\x06\x00\x00\x00\x94\xc2/8\ +\x00\x00\x00\xd1IDAT\x18\x95]\xd1\xbf/\xc3a\ +\x10\xc7\xf1\x97'\xd5\xc9h\x11F\x83\xe8\x82\xa4\xb1\x96\ +\x8d\x8dAl\x9a\x0e\xfe\x83\xae\x1d\x18\xc4`\xa71\x1b\ +\x0c\x12\x8b\xc9`\xd3\xe1;t3h\x18-\x12\x93(\ +\xea\xc7\xe0\x9e4\xf5I\x9e\xdc=w\xef{\xee\xc9\xdd\ +XQ\x14B\xab8B\x05\x1d\xec\xe01Er\x06\x97\ +X\xc01^q\x81R)\x80\x06&\xd0\xc7\x1efq\ +\x8b\xad\x0c\xac\x87=\xc7s\x9c;l&T\xb1\x14@\ +\x17\xe5\xf0oPM\xd8\xc5x\x04\x9b\x86\xeaa*\xa1\ +\x15\xbd\xa1\x8d\x8f\xf0\xdf\xf0\x95\xf0\x84\x83H\x9c\x18\xd5\ +K\xfe\xe4!~\x02\xce\x9aF/\xcf\xe1\x1d\xfb\xff\xaa\ +\x17\xd1\xcd\xc0<\xceP\x8f\xfb$Vp\x9d[\xdcc\ +\x19\xdb\xf8F\x0d\x0f\xb8\xca/|b\xcd\xdf\x0eN1\ +\x87\x0d\x0c~\x01]'-R\x7f\xd2\xe3\xe9\x00\x00\x00\ +\x00IEND\xaeB`\x82\ +\x00\x00\x01~\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x0f\x00\x00\x00\x10\x08\x06\x00\x00\x00\xc9V%\x04\ +\x00\x00\x01EIDAT(\x91\x85\xd2\xbbjVQ\ +\x14\x04\xe0/\x1a\xa3h\xe5\x05A\xd0\x17\x10\x04\x85\x05\ +\xa6P\x10D\xb0\xb5\xb0\xb2Jc\xa1\x9d\x85\x8d\x01\xb1\ +\x15\x1b\x0b\x11\x0b\xf1\x15\x22v\xa9,l\x84)R\x05\ +\x84\x08\x0a\x81\x88\x22\xa8` x\x89\xc5\xd9\x07~\x0f\ +\xffe`\xc3\xda\xb3Xkf\x0f[\x92\x0fIN\x1b\ +A\x92\x85$\x17\xcd\xc0\x5c\x92]\x5c\xc5\xbb\xc6\xed\xc3\ +S\x5c\xc6\xc3V\x8f\xc3v?\xbc\x85\x13\xb3\x94\x06x\ +\xb9\xa7\x15\xd7q\xb8\x9d#x\x81\xbf\xb89\xc2\x0f\xcf\ +\x0dIv\x93\x9c\x1d]\x99d.\xc9\xc9Y\xd2\xbd\xed\ +Gx\x82E|\xc27\x5c\xc2\xca\x14\xee\xf5X\xe5!\ +\x92\x1cL\xf2|\xe8\xa6W\xbe\xa5\x0bm\x1c\x16\xb0\x8c\ +3\xcd\xc12\xbeb\xab\x1f^k!L\xc21\x1c\xc2\ +\x0e>\xeb\xc2\x5c\x9do\xcd\xa5\xaaZ\x9bb{/\xee\ +\xe1qU}\x1f\xda\xbe\x80\xb7\xd8\x8f?m\xf3\x01l\ +O\xe2\xaa\xeag\xaf|\x05\x1fq\x0e_\xf0C\x97\xe8\ +\xea\x14\xeeU?\xbcRU\x9bIvp\x17\xf7\xabj\ +\xbd\xf56G^\xf0\x1f\xd7\xdb~\x80_\xb8\xad\xfb\xa6\ +\x1bx\x86\xdf\x93r\xc0\xfb^y\x11Gq\xbc\xddO\ +\xe1Z[8\x09o\xe6\xdb[\xefT\xd5z\x92\xf3\xba\ +\xdf\xb6TU\x1bS\x06\xc1?\xb7?\x88\x1a\xfe<\x0d\ +\xb2\x00\x00\x00\x00IEND\xaeB`\x82\ +\x00\x00\x02\xce\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x17\x00\x00\x00\x13\x08\x06\x00\x00\x00{\xbb\x96\xb6\ +\x00\x00\x02\x95IDAT8\x8du\xd5]\x88\x96U\ +\x10\x07\xf0\xdf\xbe\xec\xa6\xb5R\x86\x19\x15Kx\x11F\ +B\x118\xb1\x98e\x94PT\x0a\xf6\xa9\x90\x10^I\ +Y$\xacE7\x19!D]\xa4E\x1f.\xa1\x88\x22\ +\xde\x88X\x04]\xecEEA\x9f'D\x12\x17\xb2\x94\ +\xa4\x15\xc2\xb0\xb7R\xa3\x0f\xb2\x8b3k\x8f\xcf\xbe\x0e\ +\x1c\x9e\xe7\x9c\x99\xf9\xcf\xccyf\xfeO\x9f\x96\x94R\ +\xfa\xf1>\x02\xfb\xf0G\xae\xd58\x91f}8\x93\xcf\ +\x95X\x86\x19\xf8\x02\x9b\xf0\x0bt\xda\xe0X\x88\xe9\x98\ +\x85c\xb8\x17\x0f\xe2\xd1\xd4Ok\xd8n\xc5\x0e\xdc\x8f\ +\x1b\xf0\x0c>\xc7\xec\xf3\x81_\x8a\xc3\x11q\x06\xefd\ +\x860\x13\x17\xe3\x82<{\x00\xabR\xf7\x0fn\xc6s\ +\x98\x8b7\xce\x07>\x81\xab!\x22\xf6`Nf5\x8c\ +\x058\x95vO4|\xf6\xe2\x086\xa3\x8b\x870\xb7\ +\x17\xf8A\x5c_J\x19\xc8\x00Gq\x00_\xe3'\xfc\ +\x9b\xd5-j\xf8\xbc\x95\xcf\x93\xd8\xae~\x8b\x15S\xc0\ +#\xe2T\x02-n\x1c\xaf\xc1\x8f\xf86\xf7\x8b\x1aU\ +\xef\xc3G\xad*\xe0\xb6\xbe&p)e:\xe6\xe3i\ +\x5c\x93\x80Wa\x00\xa3\xd8\x95\xc0kqK\xba\x8d\xab\ +w<\x99\xfdL\xb5[\x8eu\x12t\xb8\x94\xb2;\xc1\ +\xd6c?\x86\xf02\xfe\xc6\xe3\x11\xf1\x1a\x8e'\xd8p\ +#\xa7\xebpQc\xdf\xc5o\xb8\xac\xbf\x942\x82\xc7\ +\xb0\x01\xab\x22\xe2d\x06\x1c\xc4\x8b\xf8!\x22>l8\ +\x1f\xc4\x96\xf4\xa1\xde\xf3\x16\xe7J\x17C\xfdx\x01C\ +\x11\xd1m\x19l\xc6\x93\xb8\xd5Ty\x1e\x0f\xab\xb3\xb0\ +-\xc1\xdar\xa2\xa36\xfd\x86R\xca%-\xe5\xedj\ +\xdb\xdd\xd9\xc3\xf18F\xd4\xfe~\xb5\x87~\x16&\xfa\ +q\x9fz%\xdf\x97R\xc60\x96\x01GR7ZJ\ +\xd9\x16\x11\x13-\x80\x1d\xea@\x1dn\x9d_\x8eA\x8c\ +\x9f\xed\x96\xcc\xfcn\xb5\x1b\xeeR\x87g\x5c\xe5\x8c/\ +\xf1\xba\xda\xa2\xa7{d\xda\x94%x\x0f#}\xbd\xb4\ +\xa5\x94\xad\xf8\x14\xef\xe2\x0a<\x8bO\xd4\x1e\xee\xe2/\ +\xdc\x84\x1b\xf1\x9d\xda\xe7\x9341\xaa\x92\xdc\xbc)C\ +TJyD%\xaaC\x11\xf1sD\x1c\xc0SX\x9a\ +k0M/\xc4\xdb\xf8\x00\x1b\xf3lHe\xc9\xcf0\ +\xdei\x01_\x8b\x9d*Aml\xa8\xba\xf8\x1dwd\ +\xd6\xf01v\xe7\xfbZ\xbc\xa4\x12\xdd@&3\x85\xb8\ +~U\xb9\x1b\x8ef\xc0\x8e:\x81\x83x\x13W6\xec\ +W\xe2\x95\x0c\xbeN\xe5\x94%\xf8Jn\xda\xd7\xb2<\ +#/\xce,v\xaa\x1c\xbe,\x03O\xc3\x9fm?\xff\ +\xff@\xceJ/V\x1cS)w\x13\xbe\xc9uOD\ +LV\xd4\x0bX\x1b\x18\xfe\x03:\x81\xbf\x95\xfd\x1fR\ +q\x00\x00\x00\x00IEND\xaeB`\x82\ +\x00\x00\x01]\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x0e\x00\x00\x00\x0e\x08\x06\x00\x00\x00\x1fH-\xd1\ +\x00\x00\x01$IDAT(\x91\x9d\xd2!K\xa4a\ +\x14\xc5\xf1\xdf\xbcc\x90\xc5\xb5\xd8\xd7\xb22i\xda\xfd\ +\x00b\xd02A6\xca&\xd3\xb2U\x90A\xfc\x00&\ +\x8b\xb8[D\x10\xd4\x22\x82\xc5f\xb5\xb8\xb7\x88\x96\x0d\ +\xe6M\xc2*\x83\x82\x08\x1a\xe6\x1dy}w4\xeci\ +\x0f\xf7\xfc9\xf7\x1e\x1e\x99\xf9\xcd\x7f\xa8\x91\x99W8\ +\x88\x88\xee{\xc6\xcc\x1c\xc5\x0c:X.pQ\x0e\xd6\ +\xde\x00\xda\x99y\x84k\x1cc*\x22z\x05\x94i\x8f\ +o\xc0\x97\xf8\x88\x0f\xe5{\x17\x8a\xc14\x22V\xf1w\ +\x08\xdc\xc14np\x8f\xc3W`\x09\xafU\xe1\xccl\ +c\x1f\xa7\xf8\x8c\xa5\x88\xe8\xd1/\xe7(\x22\xe6kw\ +u\xd1*\x93~\xe1kDC\xc7x\x17\xfa*\x00\xe6\ +KG\x079=z\xde\xaek\xf8{\x85\x5c\xa3S\x0b\ +(C\x22!\x1c\xc1ry\x9e\x91\x17_~.\xb0\x89\ +\xf5\x8b+#\xe7.\x94\xcd\xa69c\x9d\x1d@()\ +\x9b\x14vJ\xc0\xd9{\x06\xbf\xaf\x80m\xd3\xbe\xdab\ +\xad\x07\xa8z\xbd~ \x02\xcd\xf2\xbb\xa1f\x89}\x89\ +\x8e\x14\x19\x22\x96\x04\xfe\xa8\x94\xe7\x97\xb76\x1f\x1e\x88\ +@\xdc(\xd6\xcaw=\xdd6N\x00\xc3@\x09\x9d\x1b\ +\x14\xfajV\x80Z.\xbf\xf7\x15\xef\x94\x80\x0d\xb50\ +,\x81\xd7\x0c\x81[\xe8\xec\xe9\x00\x09\xe0%`(\x99\ +J\x93/\x14Y_\xf3:&`7\xednC\xc0\xc2\ +VAo>\xda\xdeZ\x07H\xa6\xd2\xa03h\x1e\xa2\ +?\xc7aX\xb9DD\xf9\xf8\xaf?]\xe7\xfa\xd7\x9f\ +\xdb\xbe\xf4\xad\x14\xf19~\xac\x94\xa2\xaf\xdfF\x98_\ +\x1f\xc6\xcc)k(e\x9dp!\xa0\xcb\x1e\xaf\x8a\x10\ +d\x0b\xbdv\xbd\xf2\xe7\x22\xe6\x81#\xb9B/\xe3\x13\ +\x93\xb6?\x1aPT\x03\xd2\xb1C\xf1\xe2\xf8\xc4\xa4\x07\ +\x9cg\xb7p\xb5[\x8c\x8dOL\xce\x1aR\x05\xb4\xf3\ +6@W\xc8\xfb\x11\xb0O\xed{\xe6\x0b#mH\x8c\ +\x00\x0fBs\xb1\xc0\xf9n\xb6\xbb\x9bp\xc9\xee\x13\xf0\ +\xeeWh4\xea\x1b\xae\x1b\xfb\x18\x1dN%\xb3a\xc2\ +\x9c\xee\x11\xf0-0\x80~v\x934\x97\xec\xdf\x1bU\ +5\xb4\xb3\xda\xfaP\xa2\xdf\x8c\xdb^u\x99`E\xbc\ +\xe7F\xce\x8c\x8eqj\xf8,\xdd\xdd)\x84\xb3\x9b\xba\ +\xa5R(\xd9\xe0\xde\xec\x0c\x99l\x9e\x9eb\x1f\x8e\xe3\ +\xea\xa7O)\xa4\x94T\xca\xf7\x00\xe8\x1f\x18\xc2q\x1c\ +\x84\x10\xbe\xd7I)Y\xf5\xaa\xccLO\xb10w\x97\ +g\xf8_\xe1\x1f\x16\x8f\x0dW\xeaa@l\x00\x00\x00\ +%tEXtdate:create\ +\x002015-12-18T14:2\ +7:00+00:003\x90\xe8\xec\x00\x00\ +\x00%tEXtdate:modif\ +y\x002015-12-18T14:\ +27:00+00:00B\xcdPP\x00\ +\x00\x00\x00IEND\xaeB`\x82\ +\x00\x00\x01\xa9\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x0f\x00\x00\x00\x0e\x08\x06\x00\x00\x00\xf0\x8aF\xef\ +\x00\x00\x01pIDAT(\x91}\xd2\xbbk\x94Q\ +\x14\x04\xf0\xdf.A\x22\xd8\x88O\xb0\xf0Q\xf9\x8a\xa8\ +\x1c\x9bhaa\x1b%\x01\x11\x8b\xfc\x01\x06A1+\ +\x096Z\x88HH\x0am\x04\x03*ha\xe3\xa3\xb3\ +\x08\x98*\x12\xe5@\x1a1\x08V\x0a\x8a\x06\x82b*\ +\x1bS\xec\xfd`\xf7#\xe4\xb4wf\xce\xcc\x9c\xdb\xb0\ +\xc6d\xe6~\xdc\xc1!\xbc\xc3XD\xfc\xaa\xe3\x1a5\ +R?n\xe2\x046w<\xfd\xc4\x5c\x11\xf9\xd2E\xce\ +\xcc\xb3h\xe1\x186\xad\xe5\xa6\xcc2>\xe0VD\xbc\ +od\xe63\x0ca\xe3:\xa4\xfa\xfc\xc5\xedj\xf30\ +\xae\xe10z\xd6!\xfd\xc1|\xd9<_\x01\xdf\xe2\x22\ +\xbea7\xfat\xf7\xb1\xac]\xdc\x06|\xc5Ghf\ +\xe6,\x16\xf1\x19\x17\xb4s\xdf\xc0',\xe15NF\ +\xc4\x00\x86\xb1\x05?2\xf3IO\xb1q\x14\xc7\xb1'\ +\x22\x16q73\xa7\xb0-\x22\xbew88\x82\x83X\ +\xc1\x5c\x95\xb9\x17\xafp\xaaX\x1a\x89\x88\x85\x8a\x91\x99\ +\xe70\x89\xed\x98\x8e\x88\x1642s\x1c\xa3%\xcb%\ +\x9c\xc6\xf5\x92\xff)\xae\xe0\xbf\xf6)\x9b\x98(\x9ac\ +M\x0c\xa2\x17/\xb1\x10\x11\x13\xd8\x81\xc7\xa5\xc4\x91\x88\ +\xd8\x1b\x11/0S\xca\xdd\x89\xf3\x95\xed\x03x\xa8}\ +\xaa\x07\xe5\x14\xff:lo\xc5=\x0c\xe0\x0d.G\xc4\ +R\xfd{\xee\xc34\x02\x8fp\x1fS8S\x9c]\x8d\ +\x88\xdf\x15\xbe\x8b\xdc!\xb2\xab\x88\xf4\xe39Z\x11\xb1\ +R\xc7\xad\x02\xcc\x87tf \xe3\x97\xea\x00\x00\x00\x00\ +IEND\xaeB`\x82\ +\x00\x00\x01\x04\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x08\x00\x00\x00\x0d\x08\x06\x00\x00\x00\x94\xc2/8\ +\x00\x00\x00\xcbIDAT\x18\x95]\xd0!K\x83a\ +\x14\xc5\xf1\xdf\x1e\xa7\xc5j\x19[\xb1\xc9\x92\x22\xab\x82\ +\xc1\xb0\xa8\xc1l\xda\x17\x10\xeb`\x03\x0d~\x82\x81\xb2\ +:0\x18\xd6V\xdc\xa2\xe1\x05WDP\xd1\xb8\xe2\x07\ +\x105\x18\xde\xfb\xe0\xf0\x94{9\xfc9\x97{*E\ +Q\xc0&\xae\xb0\x87G\x9c\xe2\x0e\x12\xaa\xb8\xc57\x06\ +\xd8\xc6\x18\x8d\x0c\x1c\x87\xd9C\x1f\x9fXG'\x03G\ +x\xc2=>p\xa3\xd4A\x06Z\x98\x86\xb9\x86y\xec\ +\xbbh%\xd4\xf0\xeaOg1W\xd1IX\x89\xbb\xf0\ +\x15\xdf\x08\xaf\x9b\xe2\xee\xb2\x06\x01^`\x91\xf0\x8c\xfa\ +\x12\xb0\xc09.E\x07\x0f\xd8\xf9\x97\xd2\xcfK\xc2\x04\ +\xfb\xd8\x08\xef\x04#4s\xc2\x04o\x119\xc3\x10\xef\ +x\xc9\x09?8\xc4\x16\xae\x95\x85\xb5\x95\xd5\xfb\x05\x08\ +|+}\x8e\x949\xf5\x00\x00\x00\x00IEND\xae\ +B`\x82\ +\x00\x00\x06\x1d\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\ +\x00\x00\x00\x04gAMA\x00\x00\xb1\x8f\x0b\xfca\x05\ +\x00\x00\x00 cHRM\x00\x00z&\x00\x00\x80\x84\ +\x00\x00\xfa\x00\x00\x00\x80\xe8\x00\x00u0\x00\x00\xea`\ +\x00\x00:\x98\x00\x00\x17p\x9c\xbaQ<\x00\x00\x00\x06\ +bKGD\x00\xff\x00\xff\x00\xff\xa0\xbd\xa7\x93\x00\x00\ +\x00\x09oFFs\x00\x00\x01\x00\x00\x00\x00\x00\x00|\ +]\xbdz\x00\x00\x00\x09pHYs\x00\x00\x0b\x12\x00\ +\x00\x0b\x12\x01\xd2\xdd~\xfc\x00\x00\x00\x07tIME\ +\x07\xdf\x0c\x12\x0e\x1b\x00\xb3\xf4\x90\xdf\x00\x00\x00\x09v\ +pAg\x00\x00\x02`\x00\x00\x00 \x00\x1f=\x87\xd8\ +\x00\x00\x04\xe2IDATX\xc3\xed\x97YlTU\ +\x18\x80\xbf\xdb\xb9C;3]fa\xe8\x02\xb4@\x99\ +.\xd0R*\xb4\x104b\xc2\xea\x86\x18\x97 \xea\x83\ +F4\xfaf4F_\x5c\xde$\xf2\xa0\x0f&FE\ +\xe2\x83\x01#\xa6\x88@@)E\x81\xcaRZ\xbaP\ +\xbaP\xa4\xdbl\x1d\x0b\x85v\x98i;\xbd>\xdcs\ +\x87)\x9d\xa5`|\xd2?\xb99\xe7\xfc\xe7\xfc\xe7\xff\ +\xce\xb9\xff\xf9\xcf\xbd\xf0_\x17\xe9^\x0d\x93S\x0cX\ +\xac3\x99\x91\x9c\x82N\x96\x19\x1f\x1b%\x18\x08\xf0\xd7\ +\x80\x9bP(\xf4\xef\x00\xd8\xecY\xcc\xce\x9d\x8f}V\ +6\xf6\xac\xd91\xc7\x0dx\x9c\xf8\xbc.\xdc\xfd\xbdx\ +\x5c\xbd\xff\x1c \xddleaa\x09\x05\x8b\xca4\xd5\ +\xeb\xc0\x9b\x80#\xca\xf03\xc0\x0f\xc0\x1e\xa0\xbf\xf7j\ +\x17\xed\x17\xeb\xf1y\xdd\xf7\x06`\xb6\xd8\xd8\xb0i\x0b\ +RR\x12\xc0W\xc0f \x1d\x98\x00\xde\x07N\x01)\ +b\xae\x5c\xe0\x9b\x08\xf3s\xc0c\x80\xf7\xf7_\x7f\xc6\ +\xd9w\xf5\xee\x00\xcc\x16\x1b\x1b7o\x05\xb0\x00>\xe0\ +i\xa0J\xeb\xbf\xe5\x1f\xc1`4\x85\xc7\x8f\x8f\x8f!\ +\xcbz\xadY\x00\xb4\x8b\xfas\xc0\x9e\xdf~\xd9\x8f\xab\ +\xbf{\x92\x8f\xa4x\x00y\x0b\x0a\xb5j\x0fP\x01T\ +\xdd\xb8>\xa8\xe9\xca\x0dF\xd3v\xe08\xd0\x08\x9c\x96\ +e\xfd\x0e`\x0e@(\x14\xea\x10\x0b<\x09\xec\x06^\ +Z\xbd~\x136{\xd6\xf4v\xc0:3\x93\xf5\x8f?\ +\x0b\xf02\xf09`\x08\x06\x03$'\xa7d\x02M\xc0\ +\xac8\xec\xe7\x81\xe5\x11\xed\xb3b\x019\xed\x17/\xb8\ +\x1a\xce\x9eH\xbc\x03s\xf3\xf2\xb5\xea\x87@\x99p\x0e\ +\xe0N\xe0\x1c`\x19\xa0\x88\xd7\x00P)\xcao\x1dE\ +\xa5\x98\xd2\xd2\x13\x03dXl\x88\x09\xe6\x02\x1dMu\ +\xb5Z\xd7\xa7L_\x0e\x00f\xcd9\xb0.I\xa7\xc3\ +>+'1@\xce\xdcy\x00\xcf\x00-\xa0\x9emW\ +_7\xa8\xc7\xef\xebi\x028\x80\x8fD\xfd\x0bM\x99\ +\x9a\x9e\x11\x1f\xc0f\xcf\xd4\xaa\xaf\x01}\x8a\xa2pc\ +\xe8\x1a\xe7jk\xb89t\x0d`\x1b\xb0e\x9a\x10/\ +\x88r4\xacQ\x94D;\x10\x8e\xcdl\xa0\x5c\x92$\ +\xd22,\xf8GnRsd\x1fW:[\x01\xbe\x17\ +\x03\xb7'\x00\xb0\x8a2\x9c:\x83\xc1@|\x00\xb1\xfd\ +\x002\xf0\xaa\xd7\xdd\xaf\xad\x1c\xff\xc80gOVS\ +sd\x1f\x97\xdbZ\x00\xde\x05\xd6\xc4\x01xO\x94o\ +\x01]\xa0\xbe\xce\x98\x00\x16\x9b\x9d\xc5e\x15\xa0\x1e=\ +\x80\xfd\x91\x06\x9ax\x9c\xbd\xd4\xfdQC\xed\xf1\xc3\x00\ +\xc7\x80w\xa28\xf7\x00\x1f\xa3&\xb2\xd5\xc0\x06\x9f\xd7\ +\xc5\xf5A_l\x809\xb9\xe1\xe3\xf7\x06\xf0\x0a\x80\xbb\ +\xbf'\xe6\xf2z\xfe\xec\xe4Rs=\xc0'\xc0:\xc0\ +\x1f\xd1]!\xcaZ\xd4\x14\xdd\xd5T\x7fz\x92\xbd|\ +\xe7\x84\xb2^\x1f\xd9\xdc\xa9(\x0a\xa3\xa3A\xe2Ic\ +\xdd)<\xce\x1e*\x1fX{\xd4hJ5E\x19R\ +\x04\x14{\x5c}x]}\x93:\xa6\xec\xc0\xc4\xe4\xbb\ +\xfc\xb2$I\xdc\xff\xd0F\x8c\xa6\xb4\xb8\x10ng/\ +\x87\x7f\xda\xcd\x89\xea\x03(\xb7\xa3\xfcm \x84\x88\xea\ +\x96\x863S\xec\xa6\x00\xb8o\xdf\xdf\x0f\x02\xf9\x80\x92\ +n\xb6\xe2(.%\x91\x8c\x06\x03\xd8\xecYH\x92d\ +A\xcd\x84\x1f\x00:\x80\xeaC?\x12-\x96\xa6\x00x\ +\x9c\xbd4\xab\xa4'\x22\xf5#\xc37\x13\x02\x00\xcc_\ +X\x0c\xf0\x99h\xa6\xf9G\x869zpoT\xe7\x10\ +%\x06\x00|\x93\x07\x8f\x03\xa4\x18\x8c\x94\x96\xaf\x00\xa0\ +\xb3\xad\x99\xc0-\xff\x14\xbb\x0c\x8bM\xbb\x9e\x9f\xd7\xec\ +N\x1e;\xc8\xa0\xcf\x1b\x138*\xc0\x80\xd7\xa5UO\ +\x03+\x01J\x96V\x86\xfb\x0d\xc6TZ.\x9c\xc1?\ +2|\xdb\xb9\xd9J\xee\xbc\x85\x8c\x8f\x8d!\xeb\xf5\xdf\ +\x09\x08R\xd3\xccq\x01\xa2&\xa2\x89P\x88+\x1d\xad\ +\x00O\x09\x95\x22\x9e\x10\xf0\xf0\x82\x82E8\x8a\x96\x00\ +`\xb1\xdaYr\xdfJ6n\xde\xca\xe2\xa5\x95\xc8z\ +\xfd*\xa0\x5c\xcc]\x90=;7\xee+\x8by\x19\xb5\ +_l@Q\x14'j\x04k\xcf#\xc0!`g^\ +~!\xa5\xe5+\xd8\xf0\xc4\x16\x16\x95UX$I\xda\ +. O\x01%b\x9a]\xf3\x1d\xc5\xe8d9&@\ +\xdcO\xb2\x0c\xb3\x15{f\x0e\x06\xa3\x89\xa4$\x1d\xc5\ +K\x96i\xbbQ\xad(\xcaZI\x92@M\xb1;\x80\ +\x00\xf0\x22\xb0W\x98\x97\x00\xcd\x80Ts\xb8\x0a\xcf\x1d\ +\xe7?n\x0ch2t}\x90!\xf1\x09\x96\xb7\xa0 \ +\xb2k\x8d$I_\xa2\xde\x8a\x00\xfb\x80'\x01.5\ +\x9d'\x10\xf0\x93_X\xd2\x92\x9ea\x91n\x0c]c\ +\xc0\xe3\x8a\xe9#.@\xa4\x0cx\x5c\x8c\x8f\x8d\x22\xeb\ +g\xecB\x8d\x8dm\xa8A\xfa(0\xd8\xd1\xda\xc8\xd5\ +\xae\xb6p\xc0u_\xe9\xc0QTJg[3\x13\x13\ +\xb1\x7fT\xee\xea\xc7\xa4l\xf9*\x1cE\xa5\xc8\xfa\x19\ +a]wW;]\x9d\xadSR\xect\xe5\xae\x7f\xcd\ +dY\x8f=3\x1b\x9dNf\xc0\xeb\x22\x18\xb8uO\ +\x8e\xff\x17M\xfe\x06<\xc9\x9b\xa3b\xcb\x06=\x00\x00\ +\x00%tEXtdate:creat\ +e\x002015-12-18T14:\ +27:00+00:003\x90\xe8\xec\x00\ +\x00\x00%tEXtdate:modi\ +fy\x002015-12-18T14\ +:27:00+00:00B\xcdPP\ +\x00\x00\x00\x00IEND\xaeB`\x82\ +\x00\x00\x01Z\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x0e\x00\x00\x00\x11\x08\x06\x00\x00\x00\xed\xc8\x9d\x9f\ +\x00\x00\x01!IDAT(\x91\xc5\xd3\xbf+\xc5Q\ +\x18\xc7\xf1\xd7\xe5\x86\xe4\x12\x8b\xd1j5\xca\x8f.!\ +\xe4\x0fP\xc4\xceD\x06e\x91\x12\x7f\x81\xcd \x19d\ +\xb0\xc8d\x91\xc1f\xfe\xda\xc8b\x10I\xa9\x9b\x9f\xc3\ +9\xd7\x8f\xd3\xa5L>u\x86\xf3<\xe7\xfd\x9c\xf3\x9c\ +>O.\xcb\xb2\x02\x96\xd1\xe0S\x8d\xa8\xf6]\xb5\xa8\ +/o\xf2x\xc0\x0e\x0ep\x85M\xdc\xe35\x01\x1fQ\ +\xc2\x14\x86\xf21x\x86N\x1c\xa2\x1d\x0b\x15@\x98A\ +\x11\xc5\xaa/\xc1Kt\xa3\x03\xbb\xa8K\xa0E\xcc\xa3\ +\x17YU\x92\xbc\xc30\x9ep\x84\x96\x18_\xc5$z\ +pQ\xee1U\x09\x13X\xc3)N\xe2+\x8a\xb8)\ +\x1f\xaa\x04\xc2[|\xda\x05\xc6\xd1/|\xd8\x87rY\ +\x96\xfd\xc0\xfe\xae\xb4\xc7\xff\x07g1\xf8Wp\x09s\ +\xd8\xc6t\x9a\xac\xf4\xab9\xaccD0D\x93\xe0\xa8\ +6\xac\xfctc\x0e\x1b\xa2\xadp\x8dstaL\xf0\ +q>\x05\xab\xb1%xu\x00\xb7_r\xd7\xe8C\xab\ +0\x0c\x852X\x83=\xc1b\xa3\xb1`s\xb2\x0a\xb1\ +\xe7\x17\x1c\xe7\x85\x19\xdb\xc7P,\xf2(\x8c\xdas\xd2\ +F)\xe6\xc0;/f:\x9b\xed\xa3J\x96\x00\x00\x00\ +\x00IEND\xaeB`\x82\ +\x00\x00\x02\x0c\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x0e\x00\x00\x00\x0f\x08\x06\x00\x00\x00\xd4\x14\xfet\ +\x00\x00\x01\xd3IDAT(\x91\x8d\x90\xbfk\x13a\ +\x18\xc7?wy#I\x04\xc1HMq(m\x22\xa5\ +\x15/\x15DA\xed\xdda\x8d.\x82q\xabm\x97\x03\ +AJ]\x5cJ\x97\xc6?\xc2\x1f\xc5\xd1\xc9\xae\xea\x5c\ +\xa5w7\xd4\xa1\x08=\x0bbQ\xc8-\xd23%C\ +\x04\xf1\x02i\x1c\xbc\xf7\xed\x05\x1c|\xb6\xef\xe7\x9e\xe7\ +\x9e\xf7\xf9hc\xe5\xca7\x8ej\xd6\xb6\xccm\xd7\xf3\ +\x17\x81\xe5\x84m\xdb\x969\xebz\xfe4\xe0\xcbF\xf1\ +\xec\xe9\x93\xb2\x0c\xcf\xd7\xd6\x86\x01n\xd6j\xe3\xf5\xfa\ +\x9d2\xc0\x97\xbd\xbd_\xc1\xce\x0e\x86a\x14\x1f7V\ +\xd5\x06Q*\x95\x8e\x82\xc8\xea\x00\xb9|>#y\x14\ +E:\xff(\xd1\xe9t>\xcb\xa0\xebz\x07\xa0\x7fx\ +\xf8]\xf28\x8e\xbf\x02d2\x99V\x14E\xea\xa9\x9a\ +\xe38\xb7S?\xda\x02\xda@\x05\x98HX;\xe1'\ +\x80)\xb5\xd1\xf5\xfcG\xa9\xc1\xd0\xb6\xcc\xb6\xeb\xf9\x97\ +\x80\xfb\x09\xdb\xb5-s\xcb\xf5\xfcq\xe0\xa5\x1al4\ +Vk2\xac\xbfZ\x1f\x01v\xa7\xaf]\xbdx}f\ +\xa6\x06\x106\xc3\xa10l2991\xfcpiI\ +\x89\x14U\xc3P\xeb^\x17\xde\x08\x80\x93\xc5S\xc7\x14\ +\xef\xf7\xb3a\xd8D\x88\xac> \xb2\xdb\xed\x1e\xa8\x83\ +5-\xfe\xdb\xdb\xff)y\xaf\xd7kKqi\x91\x9a\ +\xe38\xf7R7\xbe\x03Z\xc09\xa0\x9a\xb0\x03`\x03\ +(\x02W\xd2r.\xa4\x06?\xd8\x96\xd9r=\xff4\ + y\xd3\xb6\xcc\x0d\xd7\xf3\xcf\x00J\xa4XX\x98_\ +\x91as\xd3}\x0f4\x0d\xe3\xfc\xadj\xb5\xba\x02\xd0\ +\xfa\xd1\xfa\x18\xc7\xbf_\x9c\xadTF\xe6\xe6\xe7\x94H\ +q\xb7^W\xeb\x82\xe0S\x0e`tt\xec\xb8\xe4A\ +\x10\xe4<\xcf#_(\x0c\x88\x14\xfcgi\x9a\x16\x0f\ +\x88t\x1c\xe7A\xea\xfb[`?\xb9\xefr\xc2\xf6\x13\ +>\x04\xdc\x90\x8d\x7f\x00\xbf\x16\xa5`bD\x0f\x81\x00\ +\x00\x00\x00IEND\xaeB`\x82\ +\x00\x00\x01}\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x14\x00\x00\x00\x10\x08\x06\x00\x00\x00\x16\x18_\x1b\ +\x00\x00\x01DIDAT8\x8d\xad\x93A+DQ\ +\x18\x86\x1f#\x8d\xc8l\x94\x14QC\x16\xa2,N\x83\ +\x8d\x8dbJI\x8d,X($\x14\x0b!)%;\ +eq\xcb\xf0c\xf8\x09\xde\x95\xad\x85\xb2\xb1\xb1`c\ +cc\xe1\xbb:\x9d\xb9\xf72x7_\xefw\xcf\xf7\ +\x9c\xf7\x9e\xd3\x81\x14I:\x95\x94K\xfb\x9e\xa6\xc4\x01\ +I\x1d\xc0!0\xf7/@`\x15h\x02v\xeb\x056\ +\x84\x0d\xfb\xcd\x07\xa0\xc7Z%\xe7\xdc\xed_\x12\xcex\ +0\x80\xbdz\x12&\x017\x03_\x91\xd4\xfb+\xa0\xa4\ +\x22P6\xfbl\xb5\x11\xd8\x0e\xd6\x95$u\xfd$\xe1\ +\x06\x9f\xe7\xfa\x0eL\x02\xaf\xd6_\x97T0\xd8(p\ +\x03D\x99@Iy`\xc5\xec\x95s\xee\xce\x1bj\x03\ +\xd6\x0cv\x0d\x14\x80yI\xd3Y\x09\x17\x80v\xe0\x0d\ +8\xb3^\xe4\xa5\xdc\xf7`\xb1\xaa\x92\x9a\xd3\x80\xf1e\ +\x5c8\xe7\x9e\x00\x9cs/^\xca\xce\x00\x06\xd0\x0f\x1c\ +\xd4\x00%\x8d\x00\xe3\x96\xe6<\x18\xf2S&\xe9HR\ +_\x98p\xcb\xea=p,i\xca6\x9a\x05.\x81\xc7\ +\x0c`\x1e\xa8~\x01\xed\xf6\x96\xcc;`\x07\x980?\ +\x06,\x02\xc3\x19@\x80\xb2\xa4J\x9cp\x19h\x09\x16\ +\x14\xad\x0e|\x03\xf2\x15Ij\xcdQ\xfb2\x00\x06\xad\ +\x0e\xd5\x01\xec\x06N>\x00o\x01\x5c\xe2;\xefo\xbb\ +\x00\x00\x00\x00IEND\xaeB`\x82\ +\x00\x00\x01u\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x0b\x00\x00\x00\x10\x08\x06\x00\x00\x00\xc0\xbd\x85~\ +\x00\x00\x01\xcfy\xce=g\xa2!\xc9n\x5c\xc3!\xfc\ +\xc2F\xfc\xc0\xcd\xaaz\xaf\x13\x1eO\xf22\xc9i\x1d\ +\x92\xcc%YJr\x0e&I\xb6c\x11g\xaaj\xc5\ +\x14\x92l\xc6s\x5c\x18p\x19\xb7\xd6\x13BU\xfd\xc6\ +%\xdc\x18p\x0cO\xd6\x13v\x05\xaf\xb1m\x06?\xab\ +j\xb5\xb5\xdc\x87\xa3X\xc6a\xec\xac\xaag\xad\xe6\xdb\ +\x80\x17IN\xb5\x87\x19\xdci\xe7>\xb64\x93\x03X\ +\x19\xf0\x10\x0bIf\xab\xea\x03\x96\xb0\x80/U\xf58\ +\xc9&\xdc\xc5\xed\xa1\xaa\xfe\xe2js\xd3\xfe\x7f\x11\xef\ +Z~\x1d\x0f\xaa\xea\xfb\xd0\x06x\x85!\xc9\x0e|\xc5\ +,\xc6\xed\x9c\xc0S\x18\xba\xa1\x971\xdfo!\xc9A\ +\xbc\xa9\xaa\xb5q\xa0\x11\x8fp\x0f[\xb1\x17Gp\x12\ +WF\xc1d\xcai\xb1\x85k\xed\xdeSUs#\xdf\ +;\xc3.\xec\xef\xf2?=9-\xfe\x88U\xfck]\ +7\xf4\xe40%>\x8f\xb7\xf8\x8cO8\xdb\x93\xff\x01\ +?\x07g7v\xdb#C\x00\x00\x00\x00IEND\ +\xaeB`\x82\ +\x00\x00\x01\x03\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x13\x00\x00\x00\x11\x08\x06\x00\x00\x00?\x98\x97\xc7\ +\x00\x00\x00\xcaIDAT8\x8d\xed\xd2=J\x03Q\ +\x14@\xe1od2\xa6\x11W\x90F\xec\xd2Y\x84\x08\ +.!\xe0\x02DHe\xe1n\xa6\xb2Nm'$\xa5\ +\x16YA\xba\xb1\xb0\xb1\xc8\x16\x04GL\x8a\x99\xe0\xf8\ +\x08f^\xb4\xf4\xc0\xe5\x15\x17\xce\xbb\x7fIQ\x14\x0f\ +\xb8\xd0\x9e\x15\xae1\x0b\x13)Fx\xc6\x02\x07;D\ +=\x0cq\xba-\x99\x22\xc1\x13n[Tu\x82\x17\x5c\ +\xa1\xdfp\x1ca\x99\xb6\x104\xf9\xa8\xdfA\x1d\xdf\xd8\ +\xd5V\xc8\xab\xaa\x930\xee\xf0\x16+\xfb\x89\xf7\xb0\xcd\ +.&\xf5o1\x9cQ\x0d\xaf\xc9\xa1j\xbb\xe3H\xd9\ +\x14\xf9\xb6\x05\x94\xb8\x8f\x94\x1d#\xff\xcb\x99Eo\xf3\ +_\xf6%\xfb\xfc\xa5\xa7D\xb69\x8dKt\x90\xed)\ +K6\xb29\xceq\xd3H\xae\xf6\xa8\xecq\x0d\xfe\xb1\ +\x1c=z\xc7\xebp\x00\x00\x00\x00IEND\xaeB\ +`\x82\ +\x00\x00\x01)\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x12\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1b\x06/\x5c\ +\x00\x00\x00\xf0IDAT8\x8d\xd5\xd2/K\x83Q\ +\x18\x05\xf0\xdf\xe6\x9a`0h1\xbb&\x13\xee'\x10\ +\xf4KX\xd4l\x10\xecV\x99E\xa3q3\x1b\xd4b\ +5\x18\x9f0\x0d6\x83`S\x04\xa3 \xce\xe0\x8b\xbc\ +\x5c\xdc\xdd\x16=\xed\xdc?\xe7\x1c\xce\xf34\x22bh\ +4\xeeRJ\x9d\xc2\xfd/\x9a\x93<\xfa\x9fB-l\ +\xd7\xf8:^0\xa8\xf8\xdb\xa4B\x8d:\x89\x88\x1e\x06\ +)\xa5\x93\xec|\x07\x07\x05\x9d\xe7V\xc9%\x22\xf6\xd1\ +\xc7\x1c\xeeG\x88\xb5\xd1\xcd\x13]c\x15\xef\x18b\x09\ +\x9f\xb8\xc40\xa5\xb4\xf5\x87Y\x07\x17y\xa2W\x9c\xe3\ +\x0a\x0b\xd8\xc5)\xe6\xb1RJ_\xec(\x22\x9a)\xa5\ +\xaf\x88\xd8\xc3qA\xe7)\x8f\xd9\xab>M\x8db\xd9\ +5\x83\xb1\x89\xc6M\xed\x01\x87\x15\xedOS\xf626\ +#\xe2\xc8\xcf\xd6\xcf\xe0\x0c\xb7x,\x99\xe6B\x1b\x98\ +\xc5G\xc5o\xd0\xc5\x22\xd6*\xf7\x1cm\xb2\xa9\x8d\xc2\ +$\x9b\xfd\x0d1\x8aV\x95q\x1f\x8eP\x00\x00\x00\x00\ +IEND\xaeB`\x82\ +\x00\x00\x02\x01\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x11\x00\x00\x00\x14\x08\x06\x00\x00\x00k\xa0\xd6I\ +\x00\x00\x01\xc8IDAT8\x8d}\xd3\xcf\x8b\xcdQ\ +\x18\xc7\xf1\xd7\xdc\xaeD\xc9(4\xca\x1d\x1b\x16\xc4\xea\ +\xa2\x98\x85\xc5\x10eAhJj\x84\xf8\x0b\xb0\xc4\xca\ +\x86\xa4&c\xd6\xb2\xa04%\xc9\x8f\xe4\xc7$\xc4\xbd\ ++3S\x16\x16D\x94_%\xc5\x8c\xb8\x16\xe7\xf96\ +\xdf\xf9\xba\xdf9\x9b\xcfs\xcey\xce\xfb<\xcfy\x9e\ +\xd3\xd1j\xb5\xb4\x1b\xcdf\x13\x06q\x1c?by\x1f\ +&p-\xef\xdb\xd1h4\xdaBb\xf4c>\x06b\ +~\x13\xfb\xf19\xefT)9\xbc+\xf4\x0a6\x87=\ +\x0b\xbf\x8a\x802\xc8\x06\x5c\xc5JLb\x07:\xb1\x08\ +\xbbs~\x8bq\x06\xab\xdbAN\xa2\x8a\x13\xb9\xb5\x87\ +x\x1f\xba0\xa2\xbb\x8e\xa7\x18+B6bk\xd8}\ +\x11\x0d\x5c\x08\xdd\x84\xb3x\x80\x1e\x0c\xa3U\x84d\xb7\ +\x7f\x88T\xb3\xf9eSo\xb1\x0d\x7f\xf07;\x94\x87\ +\xac\x8b(\xbec\x8b\xf4\x1e}X\x8e\x9f\x18\x0a\xbf/\ +\x91Rov>\x0f9\x1a:\x841\x5c\x8a\xfdc\xb1\ +>\x18\xe0\xf31\xdf\x89&\xb6g}\xd2\x8d\xd7\xb1\xd9\ +\x1d\xe9\xac\xc2\xa8T\xd6\xa5\xf8\x8a\xf5x\x9e\xbbx6\ +\xe6f\x91\x1c\x92*2\x1c\x00\x18\xc7]\xcc\x91\x9a\x0e\ +\xe6\xe1H\x0e2\x81o\x95\x08\xf9@.\xe4\xfc\xb8\x18\ +z0\xf4I\xf8N+HEj\xae\x1a\xde`\xa4\x00\ +\xb9\x15i\xac\xc1\x0a\xe9\x81\xefDZ\xd3 \xbda\xdf\ +@\xf17N\xc6!R\xc5\xe0\x14\x9e\xe5\x9d\xaa\xe8\x0a\ +\xfb\x95\xf6c<\xb4\x06\xf5z\xfd?\x87\x8a\xa9&\xaa\ +\x95@\x96\x85~,\xd9W\xc1\xbd\xb0\xfb\xb1\xa0\xb0\xbf\ +\x04{\xc2\xbe?\x13d\x04\x8f\xa5\xb4nc\xad\xf4\xed\ +{\xa4\x12wJ\x9f\xede\x19\xa4\x1a\xba\x17\x8f\xa4W\ +\x7fQ\xf0\x19\xc5\xe12@\x16\x09\xbc\x8b\x08\xce\xe1-\ +~K\x1d|Zj\x81O3A\xfe\x015\x8de<\ +wk\x85?\x00\x00\x00\x00IEND\xaeB`\x82\ +\ +\x00\x00\x01\xba\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x15\x00\x00\x00\x10\x08\x06\x00\x00\x00\xf9\xda4%\ +\x00\x00\x01\x81IDAT8\x8d\xa5\xd1M\x88\x8ea\ +\x14\xc6\xf1\xdf\xfb6>\x92\x92|Dij4\xa1\xec\ +8\x1b+5\xb1\x18f\xa1f\xc5J1\xc3DVR\ +H!+;\x14\xc9J\xd2lf\xe3\xabdg)\x97\ +\x94\xb2\xb1 e\xc9\xdeJ\x16\x9eW\x8f\xe9\x19\x93q\ +V\xe7>\xd7\xb9\xfe\xf7\xb9\xef\xd3\xb3\x84H\xd2\xc3.\ +L\xe0 f\xaa\xea\xcd@\xef/`\xda\x94d\xef_\ +\xb8}\x5c\xc0e\xacn\x03ah\x01\xd3q\xec\xc1\xcb\ +\x05\xf4Q\x8c\xe1\x1df\xbbn\x9c?e\x1fS\x18O\ +\xb2\xbdC_\x87\xc7\xb8\x86\xdd\xb87\xbf\xa7k\xd2q\ +\x0c7\xf9\x19\x9cj\x01\x97\xe3\x01\xceV\xd5\x93\xa6\xfc\ +m\xd1Iq\xb2\x95\x1fM\xb2\xb6\x01\xf6p\x15\x17\x07\ +\xc0$\x9b;\xfc\x7fB\x93\x0c\xe3@\xab\xb4\x0a\xd3M\ +^\xb8SUo[\xfaX\x92\x1d\x8bM:\xd5Q;\ +\x9dd\xa8\xaa^W\xd5\xe7$\xd3IF\x1am\x16\x97\ +\x92l\xe8\x84&\x19\xc2\xb1\x8e\xd7l\xc1d\xd33\x83\ +\xbb\xb8\x01U\xf5\x03\xd71\x97d\xe5\xc0\xd0kA'\ +1\xd7\x01\x85W\xb8\x8f\xdb\xad\xdaDU=k\xbc7\ +\xb1\x11\x87\xd1kC_`\xff\x02\xd0\xae\xf8\x88\x9dU\ +\xf5=\xc9\x1a|@\xf0\xb4\xdf\x00G\xb1\xef\x1f\x80\xb0\ +\x15\xe7\x9a|\x19>\xf9\xb5\xe4m\x83?\x9d\xd6\xfa\x8a\ +\x7f\x88\xf3IF\xaa\xea+\xae\xe0=FzIV\xe0\ +\x0b\xd6/\x01\x0a\x8f\xaa\xea\x10\xbf\x97=\xd6Kr\x04\ +\x0f\x97\x08\x1c\xc4xU=\x1f\x1c\xfa8\xf1\x9f@\xb8\ +\xd5\xbc\x18\xfc\x049\xa0\x7f\x85\xe9\xdfLL\x00\x00\x00\ +\x00IEND\xaeB`\x82\ +\x00\x00\x01\xb8\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x11\x00\x00\x00\x12\x08\x06\x00\x00\x00\xbd\xf95T\ +\x00\x00\x01\x7fIDAT8\x8d\x95\xd3;hTQ\ +\x10\xc6\xf1\xdf\xbd((jv;\x05+\xc1\xad\x04!\ +0\x8d\x8d\x16\x82\x88H*A\xd2\xd9\xf8\xa8\x04\x1b5\ +\x82\x9d\x06;\xed\xc4B\x10\x0b\xedl$\xb0`e\x93\ +\x22\x0e\xda\x1bS\x89/\x10\x82\x16\xc1g\xb4\xc8\x89\x5c\ +\xd7\xbb\xbbf\xe0p\x98\xef|\xe7\xcf\xcc\x1cN\x95\x99\ +\xbd\x88X\xb4\xc1\xc8\xccI\x5cA\xa7\xca\xcc{\x98\xc6\ +\x02nF\xc4\xa31\x97\x8f\xe1\x01:E\xba[ef\ +\x0f/\x1b\xbek\x11qu\x0ch\x19\xdd\x92\xee\xadK\ ++\xcbE\xf8\x85'c\x00w\x0a\xe03>F\xc4R\ +]\xce\xfa\x98\xc3\x0f\xf43\xb3;\x04p\x02\xa7\xf18\ +\x22:8\x05\xeb\x903\x11q\x1c\xfb\xf0\xd5\xda|\x06\ +\x01{p\x1f\xd7#b\x0a\x22b\x0e\xaa\x16\xf3v<\ +\xc3+\xac\xcf\xa6\xc6C\xcc\xb4\x0d\xfe\x1fH\x03\xf6\x0d\ +\x9b\x1b\xd2\xdb\x88\xd8\xdd\xe6\xad\xdb\xc4\x12+\x03\xf9\xf7\ +a\xc6Q\x90\xff\x8eQ\x90\xc1\xb3m\x1b\x82d\xe6I\ +\xac\xe2ic\xc9\xcc\x1bm\xfe\xb6\xd7\x99\xc5y\xf4\x22\ +\xe2]C\xdf\x82\xf7\xd6\x9e\xffhD\xac\xfeUIf\ +\x1e){\x1f\x971\xdd\x04@D|\xc1A\x1c\xc6R\ +f\xee\xcc\xcc\x99?\x95d\xe6\xa7R~\x17\xb7\x22\xe2\ +\xc2\xb0\xfe3\xf3\x1cn\x17\xffJD\xec\xa8\xca\x97~\ +^<\x1f\x22b\xd70@\x81L\xe05&\x8at\xa0\ +\xc6\xc5\x86gkf\x1e\x1a\x05\xc1$\x16\xf1\xb3\xe4\x97\ +\xaa\xcc\x9c\xc7\x1b\xccF\xc4\x8b1\x80fE\x9bp\x16\ +\xfb\x7f\x03$D\x8d]u\xca0\xbc\x00\x00\x00\x00I\ +END\xaeB`\x82\ +\x00\x00\x04\xdc\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22?>\x0a\x0a Set object hei\ +ght 1\x0a \ + \x0a \ + \x0a \ + \x0a \x0a \ + \x0a <\ +/g>\x0a\x0a\ +\x00\x00\x01h\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x0c\x00\x00\x00\x10\x08\x06\x00\x00\x00\x22a\x9e\x07\ +\x00\x00\x01/IDAT(\x91m\xd2!H\x9dQ\ +\x14\x07\xf0\xdf\xf7=\xf0\xa5!\x82\x93\x85\x85\x81E\x96\ +\x0c\x074mma\xb0\xf0\x94\x19\xb5Y\xc4<\x1cC\ +\x04\xe3\xb3\x8a\x0b\xa6\x85\x85\x19\x1e\x0c\x8b\xc50\xb4\xdd\ +&cF\x8b\x08o,\x092\xa6\x8c\x85w\x95\x8f\xbb\ +\xef\xa4{\xcf\xff\x9c\xff\xff\xfc\xcf\xbd\x95\x96H)=\ +\xc5\x17\xbc\x89\x88_M\xacn)\xee`\x0f\x17\xd8(\ +\xf1\xaaQ8\x89>z\xe8\xe0;\xa6\xf1\x0d[\x11q\ +\xf6\xa0\x90R\x9a\xc1\x0f,c\x1cG\x111\x8f)\xec\ +\xe3 \xa5\xb4\x04UJ\xa9\x9b\xe5\x9f4\x94\xb7#b\ +\xb3\xa1>\x85\x13\xf4j\xac`\xa2\x18\xf5\xb2y\x89\x88\ +!\xde\xe1C\x8d\xb7\xe8\x16\x0d\xbfK\xb38\xc4\x5c\xdd\ +\xc2\xde\x1a\x11q{o\xfa\xbc\x05\xaf\xcaD\xf6qS\ +\x1b\xed\xfc\xba\xc0\x1f\xb7\x90\xac\xe1\xa0\x8e\x88S\x1c\xe3\ +O\x03|V\xb0/b\x01;UN\x8c\xe13^\xe1\ +\x11\xce\xf2\xf99V3\xc1bD\x5cV\x05\xd3\x1c\xd6\ +\xf1\x1a?q\x87M\x0c\x22\xe2o\xab\xb9\xdc\xd8\xc7\x0b\ +|\x8a\x88\xdd&\xf6\xdf\xe7\xcb\xf1\x1e_\xf1\xb1\x04\xee\ +=\xcc\xe2\xa5\xd1\x9bt\x8d\xfeP'/b\x98G\xbb\ +\xc2\xe0\x1f\x06\xdbU3\x9dA\x19\x09\x00\x00\x00\x00I\ +END\xaeB`\x82\ +\x00\x00\x01O\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x13\x00\x00\x00\x12\x08\x06\x00\x00\x00\xb9\x0c\xe5i\ +\x00\x00\x01\x16IDAT8\x8d\xe5\xd4=/DA\ +\x14\xc6\xf1\xdf\xae\xcd\x8d\xd7H\xd8\x88\xc6&tJ\x89\ +B\x22\xdb)t(\x84\x8f\xe0\xa5\xf09T:\x85\x1a\ +A\xa3Pjt\xbe\x00\xb2\x05\xd1\xa0\x14B\x16\xbb\x89\ +(\xee\xacl.\xb9w\xb3JOu\xe6\xccs\xfe9\ +3g2\xb9J\xa5r\x8e)\xed\xe9\x18\xcb\xa8A\x01\ +\xe3a\xe3\x05\xcf(\xe2!\x050\x84W\xf4a\x01\x07\ +\x0d`!\x18\xea(a\x04\xdb(\xa7\xc0\xf6\xb0\x8f+\ +\x9c\x06\xe0!\x96\xf2\xc1P\xc5S\xabg\x0b\xba\xc5l\ +\xa8\x9b\xc7Q>\xdd\x9f\xa9kl\x84x\xae\xf0\x8b\xa1\ +\x88\xc5\x14@)\xb1\xde\xc5\x16\x06\x92\xb0{\x9ca\x06\ +\x11z\x9a\xf6\xde\xf0\x8eK\xf1}5\xf4)\x1e\xc8\x0f\ +\xd8#VS\xbaJU\x12\xd6\x8b\x15td\xd4U\xb1\ +\x83\x8f\xe6dr\x00\xa3Xo\xa1\x895Lfu\x06\ +w\xd8\xcc\x80\x95\x91K&\xff\xfa4\xfe3\xac\x0b\x83\ +m2\x22\xf1\x0f\xf2=\xcdH\xfc\xedT\xd1\x89\x9b\x0c\ +\xc00&\xc4\xef\xb1?\xd4\xd4\x0a\xb8\xc0t\x00F\xc1\ +<\xd6BG\xddMq\x1d'_\xecY0\xc6f\xd8\ +\x84\x84\x00\x00\x00\x00IEND\xaeB`\x82\ +\x00\x00\x01/\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x08\x00\x00\x00\x10\x08\x06\x00\x00\x00+\x8a>}\ +\x00\x00\x00\xf6IDAT(\x91m\xd0=+\x86\x01\ +\x18\xc5\xf1\xdf\xf3\x84\xb2\xb0\x89\xf4$\xe4\xa5\x8c\xae\x12\ +\x8b\x922\xd9\x18\x14\xa3\x85\xd5\x8a\xcf`\x90\xcd\xcb&\ +e\x91\xcc>\xc0UH^V\x93A\x8aE\x8a\xb0\xdc\ +wn\xe5l\xd7\xe9\x7f\xaeN\xa7\xa6Pf\x0e\xe1\x1c\ +w\x98\x8e\x88/\xa8\xfb\xd5\x22v\xd0\x8e\xd1\xd2\xac\x02\ +\x9fh\xa0\x05\x1f\xa5\xd9T\x01\x0ep\x8dK\x5c\xfd\xf7\ +\xe1\x15\x0f\xb8\x8d\x88\xef\xff\x80u\x0cb&3;\xff\ +\x00\x99\xb9\x899\x1c\xe1\x19W\x999\x09\xb5\x02\xb8,\ +\xfa\xacb\x1e\xb3h\xc5[Sfv\xa1\x1f\x138\xc4\ +MD\xf4\x14\xc1\xaezQn\x19Cx/v\x00\x11\ +\xf1X+\x8f\xcc\x5c\xc2\x02\xc60\x1c\x11O\xd5\x92\x0d\ +\xac\xe1\x0c7\xb8\xc8\xcc6\xa8gf3\xb6\xd1\x8bc\ +\xec\xa3\x03\x93\xe5\x92\x1b\xf8\xc2xD\x85\x9fX\x87\xdbU\x95uc\x11\x97\xca~\x0f\ +L\xe2\x03:\xaa\xc8&p\x00\x9f\xb1'~o\xc5\xd1\ + \xf8\x1e\x1d\xec\xca\x93\xd5\xd1\x17\xfey\xf4\x87?\x8d\ +\xe7-\x84u\xdc\xc0\xee\xc8\xe9\xc7\xeb\x88\x1dA_\x0d\ +\xab\xf1\x02\x9bsU\x5c\xc1}\xcc\xa0\x177q(\xda\ +k\xc5(\xae\xe3G\x863\xd8\x88\xf7\xf8\xaa\x1dk\xd1\ +\x89_xT\x10\xef\xc5\x02F2I\xa7\x078\x8b\xb7\ +\xb9\xc4\x83\xb8\x16\xf6\x02\x8e\xe3[.\xe72\xb6b2\ +\x93\xf6iTZ\xceV\xec\x97\xa6\xda\x90\xb4|\x22\xad\ +\xc2>i\x00+8-i9\x90I\xda\xac\xa0\x81\xc1\ +hk\x18\x87\xb1\x1c\xb1\xf1x\x9f\xf5g\xff\xaeb\x1e\ +\xe7h_\x8d\xa6\xa4\xcdX\xb4\x9e?\x9f\x8b\xd1\xd2\x89\ + \xf9K\xe3<\xd9;\xec\x95v\xa8\xec\xd4j\xd2d\ +{\xf2dE\xe7\xb4\x05C\xd2\x94\x8ap\x17\x17\x8a\x02\ +Ed$]f\xc3\xde\x86\x0d\xd2\xad~\x91$(-\ +\xb9\x0a\xc3\xb8\x855x\xa9\xfd\xbc\xfe\x8bl\x08\xa7\xa2\ +\xca)l\xafJ\xfe\x0dZUP\xe3\xae\x0f\xedJ\x00\ +\x00\x00\x00IEND\xaeB`\x82\ +\x00\x00\x01\xfc\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x17\x00\x00\x00\x12\x08\x06\x00\x00\x00\xb0\xe7E\x13\ +\x00\x00\x01\xc3IDAT8\x8d\xad\xd4\xcd\x8bNa\ +\x1c\xc6\xf1\xcf\x19/y\x9d\x85\x97\x14)\xa4\xcc\xc8\x82\ +\xe6\x96\x14EY(Rd\xa3\x89$\x8d\x05\xe5e\x1a\ +ec\x83\xb2\xb2\x90\x8d\x8d\x05v\x96vVVV\xd7\ +)\x7f\x02\xf2\x0f\xc8[\x8a\x1e\x8b\xe7\x9czL\xe7\x99\ +\x19q\xd5\xa9\xfb\xba\xbb\x7f\xdf\xdf\xd5\xef>\xe7T\xbd\ +^\xcfBT\xd7u\x85\xb3\x18\xc7G|\xc6\xb3\x89\x89\ +\x89\xa1\x80\xc5\x0b\x22\xf7u\x1d\xebJ)\xb7 \xc9X\ +\xb3\xf7`X\xc1HUU\xba\x9e\xba\xaeo\xd7u\xbd\ +\xac\xf5\xf8\x81WIv'9\x84\xefX?\xac\xbe\xaa\ +*#]\x1d\x93\x8cb\xa6\x19\xc3\x1f*\xa5\xbc\xc5[\ +\x9c\xd4\x1f\xcfPu\xc2q\x0e\xab0\x9d\xa4=\xf3\x0b\ +cI.b\x0b\xde\xe9\xcf}\xe1\xf0$\x15.7v\ +\x07\x8e5\xeb\xc7\xf8\x86\x8d8\x82Q<\x9b\x0b\xdeu\ +\xa1\x8716\xe0o\xe2e)\xa5\x87\xa7\x1daV\x96\ +R\xbe.(9\xae\xcc\xf2\x07\x92\xec\x9d#\xe0\xda$\ +\x17\xe6\x85'\xd9\x8c\x13\x1d\xe7ff\x9d\xdb\xde6,\ +\xa5|\xc0\xd2$\xa7\xe7K~\x09\x8b:\xe0\xa7\x92l\ +m\xc1x\x8d'I\xda\xb1>\xc6T\x92\x83\x9d\xf0$\ +K1\xd5\x01\xd64\xbc\x91dg\x03\xde\x84]\xb8\xd1\ +\xa4\xef\xe1\x1a^$\x19o\x8b\xaa\x01\xf8$\x9e\x0f\x81\ +\xc3W\xfd\x0fg\xdd\xc0\xde7\xec,\xa5\xbco\x18\xf7\ +0\x893\xf898\x96\xcb\xe6\xd6\xcaY`X\x81G\ +\x03\xfe.\x96\xe0\x0d\x0e\x8e4\x1d\xf7`\xff<\xf0a\ +:\x9e\xe4d\xb3\xde\xd7\xc0a[\x9b|\xf6\xeb\xf7\xb7\ +z\x98du)\xe55\xb6\xe1\x0e6TI\xd6\xe8\xff\ +#\x96\xffc\x83\x07\xa5\x94\xe9\xd6$Y5\x82\xf3\xff\ +\x01\x0cW\x93\xecnM)\xe5\xcbb\xfd\xdb\xfd\xf4\x1f\ +\xe0p\x1fG[\xf3\x1b\xdb,\x90K\x95\x7f\xdek\x00\ +\x00\x00\x00IEND\xaeB`\x82\ +\x00\x00\x01\xb8\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x15\x00\x00\x00\x0e\x08\x06\x00\x00\x00\xc0\x06W\xce\ +\x00\x00\x01\x7fIDAT8\x8d\x8d\xd3\xbdk\x15Q\ +\x10\xc6\xe1g\xaf\x17EQ\xd1\x18E\x04\xb1\xd2F\xcb\ +\x01k\x0b\xed\x82\xa4NH\xa1EH\xa7]\x08\xa2H\ +\x04M\xa5\x85 \x8a \xe2_ X(\x08\x8aU\xc0\ +)\xc5\xc2&\x85\xe2g\xe7G\x22\x92\x0f\x8b\xdd\xab\xeb\ +\x82\xbbw\xba3\xf3\xce\xef\xcc9\xe7=\x85Fd\xe6\ +fLa\x0cG\xb1\x17[\xd1\xaf$k\xf8\x81\x0fx\ +\x81k\x11\xb1Tg\x145\xd8q\xdc\xc11\xf4\x9a\x9b\ +u\xc4\x1bLF\xc4\xcb?\xd0\xcc\xbc\x8b\xb3\x0d\xe1\x0a\ +>\xe3#~V\xb9-\xd5\xe4\xfb\xb0\xa3\xa1\xdf\xc0\xa5\ +\x88\x98/2\xf3\x02\xe6k\xa0\x07\xb8\x12\x11o\xdbF\ +\xcb\xcc]\x98\xab\x86\x19\xa9\x95\xc6\x8b\xcc\xfc\x86\xedx\ +\x84\xd3\x11\xb1>\xd4\x81\xff\xdd`\x12\xd71\x8awE\ +fn`-\x22\xfa\xed\xad\x9d\xe0Sx\x82\xf5\xc1\x83\ +l\xca\xcc\xd7\x999\xd2\xd27h\x9e\xce\xccC\xb5\xf5\ +\x91\xcc|\x8e\xc7U\xaa(2sYi\x19\xf8\x8a=\ +\x11\xb1\xda\x00\xf5q\x15\xd3\xca\x07\x9a\xc5+,(m\ +W\x8f\xef}\xdc\xc6\xb9*\xb1\x13\x13\xb8_\xc1F\x95\ +6\x1b\xf3\xd7\xa7p\x11\xdb\xfes\x98\x87\xbd\x888\x8f\ +\xa7\xb5\xe4\xfe\x0a8\xa3\xb4\xd4x\x03\xa8\x05\xf8\x1eg\ +z\x10\x11'1\x83/\xaa\xab\x88\x88[\xb8\xa7\xf4_\ +W\xac\xe2\x19\x0eG\xc4\xaf\xa2K\x9d\x99\x07\xb1\x88\x03\ +\x8d\xd22\x96\x94_\xf5rD|\x1a\x14:\xa15\xf8\ +\x14n`7f#ba\xd8\xdea\xe073\xf3D\ +\x9b\xe67\xefB~?\xd8\xe7\x90V\x00\x00\x00\x00I\ +END\xaeB`\x82\ +\x00\x00\x02\x0e\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x12\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1b\x06/\x5c\ +\x00\x00\x01\xd5IDAT8\x8dm\xd3M\x88\xceQ\ +\x14\x06\xf0\xdf;\xc6\x82)\xb10jl|5\x92\x8f\ +1u\x94\x90\x95\x95\x9a\x94\x12j2\x09[\x1a6,\ +H6\xa3|\x84\xcd\xa4h\xb2\xd1\x88\x99\x85\xaf\x86\xa4\ +\x88l\x8ef\x8a\x15K\xb3@hR\x94\x91X\xbc\xd7\ +\xf4\xce\xbf9u\xeb\x9e\xf3\x9c\x9es\xces\xef\xa9e\ +\xe6\x1cl\xc3hD\x8c\x9b\xc12\xb3\x0fK\xd0\x1d\x11\ +\x7ff\xca\xa9e\xe6\x03\xcc\xc5j\xb4G\xc4Df\x1e\ +\xc2A\xec\x88\x88\x8f\x999\x86\xa5h-g/\x1eF\ +\xc4\xdb\xffDMh\xc7\x1d\xfc\xc5\xfc\x12_\x8cuh\ +)\xfe0\xceD\xc4/\xdc,\xd8\x93\xc6\x8e\x9a\xb0\x1f\ +[\xf1\x1c\x9b!\x22N\xe3\x18\x96\x97\xbce\xf8Z\xee\ +\xdf\xb0\x16\x9f\xa7\x11E\xc4\x8b\x88\xd8\x8d\xe38\x95\x99\ +\x07\x0a6\x80\xdd\xe5\xde\x82\xef\x99\xb9\x08kp\xf6\x7f\ +\xd1)\x8d\x1a\x9d\xcc\x5c\x88\x07\x18\x88\x88\xfe\xcc<\x82\ +\x11\x5cB?\x8e\xe2bD\xdc\xcd\xcc\x1az\x8b\xb6\xe7\ +\xa6\x11\x15\xb2\x16\xdc\xc6c\x5c+z\xacG'\x86\x22\ +b\xa4\xe4m\xc1u\x0caC\xad\x04[\xd1\x19\x11\x8f\ +\x8a?\x1b]\x111\xdcP`\x05\xc6\x11\xd8\xa4\xfee\ +6b\x14\xef\x9bK\xde\x05tg\xe63L\x94Xo\ +\xa5\xd9\x85\xb8\x887x\x8dA\xcc\xc3J\xdco$\x1a\ +\xc3\x95\x88\xf8\xdd\xd0EG\xe9b\x01\xda\xcah7*\ +\x05\xdeR\x11\xbb\xa2\xd5N\xec\xc2>u\x91g\xe1G\ +\x19\xe9\x9e\xfa\x83L\x15m\x9a\x81\xa0\x96\x99'\xd1\x83\ +\x9e\x92<\x88=\x11q\x19?q\xb5\xe83e\xd5\xe7\ +\xefB\x1f>\xa8\xaf\xc7d\x03\xf6\xb2h\xf4N\xfdC\ +\xdej\xdc\xbbf\xd3m;V\xa9/\xe7d\x05\x9b\xc0\ +y\xf5\xbd\xec\xa8.ou\xb4\xc3h\x8b\x88\xb1\xea\xc8\ +\xea{\xd8\x87/XQ\x05\xa7uT\xf4\xf84\x03\x09\ +\x9c\xc0\x19<\xc5\xab*\xf8\x0f\xdd\xdb\x9d,w\xcc\x1f\ +\xb4\x00\x00\x00\x00IEND\xaeB`\x82\ +\x00\x00\x04\xe9\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\ +\x00\x00\x00\x04gAMA\x00\x00\xb1\x8f\x0b\xfca\x05\ +\x00\x00\x00 cHRM\x00\x00z&\x00\x00\x80\x84\ +\x00\x00\xfa\x00\x00\x00\x80\xe8\x00\x00u0\x00\x00\xea`\ +\x00\x00:\x98\x00\x00\x17p\x9c\xbaQ<\x00\x00\x00\x06\ +bKGD\x00\xff\x00\xff\x00\xff\xa0\xbd\xa7\x93\x00\x00\ +\x00\x09oFFs\x00\x00\x02\xc0\x00\x00\x00\x00\x00\x5c\ +]\xb9S\x00\x00\x00\x09pHYs\x00\x00\x0b\x13\x00\ +\x00\x0b\x13\x01\x00\x9a\x9c\x18\x00\x00\x00\x07tIME\ +\x07\xdf\x0c\x12\x0e\x1b\x0b$&IW\x00\x00\x00\x09v\ +pAg\x00\x00\x03@\x00\x00\x00 \x00\xbe\xe6\x89Z\ +\x00\x00\x03\xaeIDATX\xc3\xed\xd6]\x88UU\ +\x14\x07\xf0\xdf\x98\x8e\x96\xa8QIjA\x1f\x04BD\ +\xd0KQ\xf8\x12\x91\x11=\x04\xf5b'\x85\x8e\x88\x8d\ +i\xa7\x14\x02\xc3\xc2\xbe\xa0\xcc,8f\x1aa\xa7/\ +N\x11J\x05RP\xe1C\x1f\x86\x0f\xbe\x98(\x94\x1a\ +F\x94\x85Y\x98\xcd\x80:\xde\x1e\xf6\xbe\xce\x9e\xdb\xbd\ +3:MO\xb5\xe0p\xf7\xddg\x9d\xb5\xfe{}\xfc\ +\xf7\xe2\xbf.]\xcdE\x96\x17Oa\xc5(\xdb\x9f]\ +W\xe5'C)\x8cM\xd6+p\x02\x07p\xec\x1f:\ +\x9e\x82\x19\xb8\x1a\xa7\x0d\x00\x0e\xd4Uy\xc5h\x1c=\ +\xcb\x8b\x06N\x0e\xa7\xd7\x0a\xe0X\x07cS\xb0\x11\x1b\ +\xeb\xaa\xfch\x04``a\x8c\xcc\xea\xba*;\x02h\ +~\xb0\x16S\xf1\x07&`\x12n\xc7\xac,/\xde\xc5\ +\xf7Q\xb5\x0b\xefa:\xaeCo]\x95/%\xa6\x9a\ +5\xb6\x04k\x84\x14\x8f\xc9\xf2bU\x13D[\x00\x98\ +\x17\xd1\xf6cL\xb2\x7f!\xee\x8b\xc0\xc6\xe3\xec\x08\xe6\ +Z,C\x1fR\x00?dy\xb1\x00O\xa3;>\xcb\ +\xb0j\xc8\x08\xe0!\xcc\xc48\xfc\x88\x8bp\x17.\xc0\ +Y\xf1\x99\x8f\x8b\xb1\x07G\xe2i\x8f&6\x1e\x8b\xfa\ +\xeb\x92\xbdo1o\xd8\x14\xd4U\xf9J\x9b\xb4lC\ +\x95\xa4d\x0dz\xea\xaa\xdc\x89\x9dh\xad\x8d?\xf1L\ +\xf2\xffg\xcc\xaf\xabr{\xaa\xd4\xa9\x06\xee\xc0e\x06\ +\xaa\xb8\x0b\xbf\xe1~\xac\xc6\xb9B\x9b\xbd\x9d\xe5\xc5-\ +uU~\x99\xe5\xc5R\xf4\xd5U\xb9!\xcb\x8b\x1e<\ +\x19\xc16\x9d\xcf\xa9\xab\xf2\x8bV_\x9dR\xb0\x14\xb3\ +\xda\xec7\xe2\xd3\x1f\xd30\x11\x1fdy\xb1\x0c+\x85\ +\x22\xdb\x80\xf5-a\x9f\xdf\xce\xf9P\x006\xe2\xb3\xe8\ +,\x95cx\x1d7\x09\xc56\x1e\xe7\xc7P/\xc0\x8c\ +,/~O\xf4\x8f\x0a9\xdf\xde\xc1O\xc7\x1ax\xcd\ +\xd0\xf2j\x96\x17\xbdX+\x14\xdat\xbc)tLw\ +\xd4\xd9\x8f|(\xe7\x1d\x01dyq'.\xd5\x99\xc9\ +\xba\xf0\x0b\x1eF)\xb4\xe3\x84\xe4\xfd^<\x81\xc3\xc3\ +\x1c\xa4c\x0a\x1e\xd4\xbe\x06Ri\x08\xfd\xbcI\xe0\x8d\ +T\xd6\xc7\xc8\xcc\xc6\xae\x91\x00x\x03\xdb\x87\x89\xc0.\ +\xa1\x1d\x97\xb7y\xbfR`\xbfm#\x8a@;\x1eh\ +\x95,/\x16\x09\x0c\xd7\x94\xc3\x02qM\xc2d\xa10\ +\x17c\xdf\x19\x03\xc8\xf2b\xb9p\x95\xa6\x11\xe8\xc2q\ +!\xbf\x87\xf0\x82\xd0\x05\xf0\x13\xee\xc1%x\xd6\x00O\ +\xbc\x95\xe5\xc5\xaduU~~\xa6)\xb8M\xfb\x1a8\ +.\xe4\xbe;\xd9\xfbF\xa0\xdd\x0f\xe3\xbbE\x06\xc8j\ +\x22\xde\xcf\xf2ba]\x95\x9b\xcf\x04\xc0\xa3\xf1\x04M\ +\x1eh\xa0W`\xc7\xc7\x13\x00G1\x17\x07\xe3o\x1f\ +\xb6\xc6\xc8\xad\x13:\xe3<\xbc\x98\xe5Eo\xbb\xab<\ +\x1d\xc9\x1a\xd8SW\xe5\x95\x1d\xd2r\xaf\xc0rM\xd9\ +\x8f\xb9uU~\xd5F\x17z\x84V\x9c\x1a\xb7\x8f\x08\ +t<\x08D[\x00\x09\x0f4\x84Ke\x1c\x9e3\x90\ +\xf3}x$\x86\xf9S\xc9< \xcc\x077\xe0F\xec\ +\x10Z\xb2\xf9\xddA,I\xd31\x1c\x0f\xf4\x0b\xfc\xde\ +\x9d\x80=\x89\xcbQ\xc7\xbd9\x06\xe6\x81\x13\xd8\x1d\xed\ +.\xc6\xddx@ \xabnL\xc3\xcbY^l\x1en\ + i\xf2@\xbfPd\xd7\x08\x83\xc8^a.\x98\x8e\ +\x9b\xe3\xfb\xdd\x06\xcf\x03\xdf\x09\x83\x0bL\xab\xab\xf2\xf9\ +,/~\x8d\xe9\xeb\x12\xae\xf0S\x8eN\x8b\x07\xb2\xbc\ +\x98\x1c\xc3\xbb\xa5\xae\xca\x1dq{K\xa2\xf2\xb5d\x1e\ +\xc8\xf2\xe2\xfa\xb8lD{\x9b\xb2\xbc\x18\x8b\xee\xba*\ +7\xa5\xb6[\x01\x8cI\x8ahr\xb2\xdf\x10\xfa\xfbP\ +\x043\x94\x1c\xc19q}\xaa\xc6\xea\xaa|'\xda\x1d\ +$\xad\x00f\xc6b\x1c-\x19D\xe5i\xe8\xdb\x01\xc8\ +p\x95\xbf\xcf\x00#\x95\x06>\x1e\xc5\xc3\xfc/\xff\x8e\ +\xfc\x05\x99&,\xa0:Dw\xab\x00\x00\x00%tE\ +Xtdate:create\x0020\ +15-12-18T14:27:1\ +1+00:00YM\xe3\xc6\x00\x00\x00%t\ +EXtdate:modify\x002\ +015-12-18T14:27:\ +11+00:00(\x10[z\x00\x00\x00\x00\ +IEND\xaeB`\x82\ +\x00\x00\x04~\ +\x00\ +\x00\x01\x00\x01\x00\x10\x10\x00\x00\x00\x00 \x00h\x04\x00\ +\x00\x16\x00\x00\x00(\x00\x00\x00\x10\x00\x00\x00 \x00\x00\ +\x00\x01\x00 \x00\x00\x00\x00\x00@\x04\x00\x00\x13\x0b\x00\ +\x00\x13\x0b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +>\x00\x00\x00\xa1\x00\x00\x00\xd6\x00\x00\x00\xeb\x00\x00\x00\ +\xec\x00\x00\x00\xd8\x00\x00\x00\xa7\x00\x00\x00G\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x9e\x02\x022\ +\xff\x04\x10\x81\xff\x03#\xaa\xff\x02,\xbb\xff\x02-\xbc\ +\xff\x03$\xac\xff\x03\x12\x85\xff\x02\x028\xff\x00\x00\x00\ +\xac\x00\x00\x00\x12\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x0c\x00\x00\x00\xbb\x03\x08\x5c\xff\x02/\xcb\ +\xff\x00;\xca\xff\x00:\xca\xff\x009\xca\xff\x009\xca\ +\xff\x00:\xca\xff\x00;\xca\xff\x022\xcb\xff\x03\x09b\ +\xff\x00\x00\x00\xc9\x00\x00\x00\x13\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x98\x04\x08^\xff\x015\xca\xff\x00:\xca\ +\xff\x008\xca\xff\x008\xca\xff\x008\xca\xff\x008\xca\ +\xff\x008\xca\xff\x008\xca\xff\x00:\xca\xff\x018\xca\ +\xff\x03\x09c\xff\x00\x00\x00\xaf\x00\x00\x00\x00\x00\x00\x00\ +0\x00\x00\x00\xfd\x02.\xc8\xff\x00:\xca\xff\x008\xca\ +\xff\x008\xca\xff\x008\xca\xff\x008\xca\xff\x008\xca\ +\xff\x008\xca\xff\x008\xca\xff\x008\xca\xff\x00:\xca\ +\xff\x022\xcb\xff\x02\x027\xff\x00\x00\x00E\x00\x00\x00\ +\x92\x04\x0eu\xff\x00:\xca\xff\x008\xca\xff\x008\xca\ +\xff\x008\xca\xff\x008\xca\xff\x008\xca\xff\x008\xca\ +\xff\x008\xca\xff\x008\xca\xff\x008\xca\xff\x008\xca\ +\xff\x00;\xca\xff\x03\x13\x87\xff\x00\x00\x00\xaa\x00\x00\x00\ +\xce\x02\x1f\xa4\xff\x00:\xc9\xff\x008\xc9\xff\x008\xca\ +\xff\x008\xca\xff\x008\xca\xff\x008\xca\xff\x008\xca\ +\xff\x008\xca\xff\x008\xca\xff\x008\xca\xff\x008\xca\ +\xff\x00:\xca\xff\x03%\xaf\xff\x00\x00\x00\xdc\x00\x00\x00\ +\xea\x02)\xb9\xff\x01:\xca\xff\x088\xd1\xff\x098\xd1\ +\xff\x078\xd0\xff\x058\xce\xff\x038\xcd\xff\x028\xcc\ +\xff\x018\xca\xff\x008\xca\xff\x008\xca\xff\x008\xca\ +\xff\x009\xca\xff\x02-\xbd\xff\x00\x00\x00\xed\x00\x00\x00\ +\xe8\x02)\xb8\xff\x0d:\xd6\xff\x139\xdb\xff\x118\xd9\ +\xff\x0f8\xd7\xff\x0d8\xd6\xff\x0b8\xd4\xff\x0a8\xd3\ +\xff\x088\xd1\xff\x068\xcf\xff\x048\xce\xff\x028\xcb\ +\xff\x009\xc9\xff\x02-\xbd\xff\x00\x00\x00\xed\x00\x00\x00\ +\xcb\x06\x1d\xa5\xff\x1b;\xe2\xff\x1a9\xe2\xff\x189\xe0\ +\xff\x179\xde\xff\x159\xdd\xff\x139\xdb\xff\x129\xda\ +\xff\x108\xd8\xff\x0e8\xd7\xff\x0c8\xd5\xff\x0a8\xd3\ +\xff\x01:\xcb\xff\x03$\xad\xff\x00\x00\x00\xd9\x00\x00\x00\ +\x8b\x07\x0dr\xff\x22;\xe8\xff\x22:\xe9\xff 9\xe7\ +\xff\x1e9\xe5\xff\x1c9\xe3\xff\x1b9\xe2\xff\x199\xe0\ +\xff\x179\xdf\xff\x169\xdd\xff\x149\xdc\xff\x139\xdb\ +\xff\x07;\xd0\xff\x03\x11\x82\xff\x00\x00\x00\xa3\x00\x00\x00\ +(\x00\x00\x00\xfa\x1c+\xd7\xff,;\xf2\xff(:\xee\ +\xff&:\xec\xff$:\xeb\xff#:\xe9\xff!:\xe7\ +\xff\x1f9\xe6\xff\x1d9\xe4\xff\x1c9\xe3\xff\x1b;\xe2\ +\xff\x090\xd1\xff\x02\x02/\xff\x00\x00\x00;\x00\x00\x00\ +\x00\x00\x00\x00\x88\x07\x08[\xff,5\xf1\xff3;\xf8\ +\xff.;\xf3\xff,:\xf1\xff*:\xf0\xff(:\xee\ +\xff':\xed\xff%:\xeb\xff&;\xec\xff\x1c6\xe3\ +\xff\x04\x08]\xff\x00\x00\x00\x9f\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x05\x00\x00\x00\xaa\x08\x08[\xff)+\xe2\ +\xff8;\xfc\xff7;\xfc\xff4;\xf9\xff2;\xf8\ +\xff1;\xf6\xff/;\xf5\xff#/\xe5\xff\x06\x08`\ +\xff\x00\x00\x00\xbb\x00\x00\x00\x0b\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x88\x00\x00\x00\ +\xf6\x0e\x0ex\xff\x1e\x1f\xb8\xff)+\xda\xff)+\xdb\ +\xff\x1d!\xba\xff\x0e\x0f~\xff\x00\x00\x00\xfb\x00\x00\x00\ +\x96\x00\x00\x00\x0b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ ++\x00\x00\x00\x8a\x00\x00\x00\xc8\x00\x00\x00\xe7\x00\x00\x00\ +\xe8\x00\x00\x00\xcb\x00\x00\x00\x91\x00\x00\x003\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0\x0f\x00\ +\x00\xc0\x03\x00\x00\x80\x01\x00\x00\x80\x01\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x01\x00\ +\x00\x80\x01\x00\x00\xc0\x03\x00\x00\xf0\x0f\x00\x00\ +\x00\x00\x03?\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22?>\x0a\x0a source control\ + connected\x0a \x0a \ +\x0a \ + \x0a\x0a\ +\x00\x00\x03C\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22?>\x0a\x0a source control\ + - not setup\x0a \x0a \ + \x0a \x0a\x0a\ +\x00\x00\x04~\ +\x00\ +\x00\x01\x00\x01\x00\x10\x10\x00\x00\x00\x00 \x00h\x04\x00\ +\x00\x16\x00\x00\x00(\x00\x00\x00\x10\x00\x00\x00 \x00\x00\ +\x00\x01\x00 \x00\x00\x00\x00\x00@\x04\x00\x00\x13\x0b\x00\ +\x00\x13\x0b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1c\x1a\x1c\ +>\x1c\x0f\x1b\xa1\x1c\x13\x1b\xd6\x1b\x1e\x1b\xeb\x19\x1d\x1a\ +\xec\x17\x0f\x17\xd8\x13\x05\x11\xa7\x0d\x09\x0cG\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00###\x0a#\x19\x22\x9e!$\x22\ +\xff\x18q!\xff\x0d\xb6\x1e\xff\x09\xd0\x1d\xff\x09\xd2\x1d\ +\xff\x0d\xba\x1f\xff\x16x \xff\x18!\x19\xff\x10\x05\x0f\ +\xac\x0f\x0f\x0f\x12\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00%&%\x0c'\x1b&\xbb\x1fK$\xff\x09\xcd\x1d\ +\xff\x00\xfd\x19\xff\x00\xfb\x18\xff\x00\xf7\x18\xff\x00\xf6\x18\ +\xff\x00\xfa\x18\xff\x00\xff\x19\xff\x0a\xd7\x1f\xff\x18P\x1e\ +\xff\x12\x06\x11\xc9\x04\x05\x05\x13\x00\x00\x00\x00\x00\x00\x00\ +\x00-#,\x98\x22I&\xff\x03\xe6\x1a\xff\x00\xfb\x18\ +\xff\x00\xf0\x19\xff\x00\xf0\x19\xff\x00\xf0\x19\xff\x00\xf0\x19\ +\xff\x00\xf0\x19\xff\x00\xf0\x19\xff\x00\xf9\x18\xff\x05\xf1\x1c\ +\xff\x18P\x1e\xff\x11\x06\x11\xaf\x00\x00\x00\x00.,.\ +0+.+\xfd\x08\xc8\x1c\xff\x00\xfb\x18\xff\x00\xf0\x19\ +\xff\x00\xf0\x19\xff\x00\xf0\x19\xff\x00\xf0\x19\xff\x00\xf0\x19\ +\xff\x00\xf0\x19\xff\x00\xf0\x19\xff\x00\xf0\x19\xff\x00\xfa\x18\ +\xff\x09\xd7\x1e\xff\x19\x22\x1a\xff\x0c\x09\x0cE3&1\ +\x92\x1dk%\xff\x00\xfb\x18\xff\x00\xf0\x19\xff\x00\xf0\x18\ +\xff\x00\xf0\x18\xff\x00\xf0\x19\xff\x00\xf0\x19\xff\x00\xf0\x19\ +\xff\x00\xf0\x19\xff\x00\xf0\x19\xff\x00\xf0\x19\xff\x00\xf0\x19\ +\xff\x00\xff\x19\xff\x16x \xff\x14\x07\x13\xaa3'2\ +\xce\x0f\xa5\x1f\xff\x00\xfc\x17\xff\x00\xf0\x17\xff\x01\xf0\x1a\ +\xff\x02\xf0\x1b\xff\x00\xf0\x19\xff\x00\xf0\x18\xff\x00\xf0\x18\ +\xff\x00\xf0\x18\xff\x00\xf0\x19\xff\x00\xf0\x19\xff\x00\xf0\x19\ +\xff\x00\xfa\x18\xff\x0c\xba\x1f\xff\x1a\x12\x19\xdc5/4\ +\xea\x07\xc2\x1a\xff\x03\xf9\x1b\xff!\xf27\xff%\xf2:\ +\xff\x1e\xf24\xff\x16\xf1-\xff\x0f\xf1&\xff\x08\xf0!\ +\xff\x04\xf0\x1c\xff\x01\xf0\x1a\xff\x00\xf0\x18\xff\x00\xf0\x18\ +\xff\x00\xf7\x18\xff\x08\xd1\x1d\xff\x1b\x1f\x1c\xed616\ +\xe8\x07\xc1\x1b\xff:\xfcO\xffT\xf5e\xffH\xf4Z\ +\xffA\xf4S\xff9\xf4M\xff1\xf3F\xff*\xf2?\ +\xff\x22\xf27\xff\x1a\xf10\xff\x12\xf1*\xff\x08\xf0 \ +\xff\x00\xf7\x17\xff\x08\xd0\x1d\xff\x1d \x1d\xed8.7\ +\xcb \xa1.\xffs\xff\x82\xffr\xf6\x80\xffi\xf6x\ +\xffb\xf6q\xffZ\xf6k\xffS\xf5d\xffL\xf5]\ +\xffD\xf4W\xff=\xf4P\xff6\xf3I\xff-\xf2A\ +\xff\x06\xfb\x1f\xff\x0b\xb5\x1d\xff \x17\x1f\xd9;2:\ +\x8b3i9\xff\x91\xff\x9d\xff\x95\xfa\x9f\xff\x8b\xf8\x96\ +\xff\x83\xf8\x8f\xff{\xf7\x88\xfft\xf7\x82\xffm\xf7{\ +\xffe\xf6t\xff^\xf6n\xffV\xf5g\xffS\xf5d\ +\xff\x1d\xfe5\xff\x13q\x1d\xff\x1f\x12\x1e\xa3><=\ +(262\xfa\x83\xc4\x8a\xff\xbf\xff\xc7\xff\xac\xfa\xb4\ +\xff\xa5\xfa\xae\xff\x9d\xf9\xa7\xff\x96\xf9\xa0\xff\x8e\xf9\x99\ +\xff\x87\xf8\x92\xff\x7f\xf7\x8c\xffx\xf7\x85\xfft\xff\x83\ +\xff(\xce9\xff\x1f' \xff!\x1e!;\x00\x00\x00\ +\x00>;>\x88DME\xff\xbd\xe3\xc2\xff\xdb\xff\xdf\ +\xff\xc7\xfd\xcc\xff\xbe\xfb\xc4\xff\xb6\xfb\xbe\xff\xaf\xfa\xb7\ +\xff\xa8\xfa\xb0\xff\xa1\xfa\xaa\xff\xa3\xff\xad\xffx\xeb\x84\ +\xff$M(\xff'\x1f&\x9f\x00\x00\x00\x00\x00\x00\x00\ +\x00<=<\x05979\xaaLPL\xff\xba\xc7\xbb\ +\xff\xf1\xff\xf4\xff\xee\xff\xf0\xff\xe2\xff\xe6\xff\xda\xff\xdf\ +\xff\xd5\xff\xda\xff\xcd\xff\xd3\xff\x9b\xd0\xa0\xff9M;\ +\xff#\x1d#\xbb\x0d\x0e\x0d\x0b\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00CCC\x04<;<\x889:9\ +\xf6lnl\xff\xa4\xa8\xa4\xff\xc3\xcb\xc4\xff\xc1\xcd\xc2\ +\xff\xa2\xb0\xa3\xffitj\xff333\xfb,'+\ +\x96$$$\x0b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00BBB\ ++555\x8a111\xc8444\xe7333\ +\xe8-+-\xcb,*,\x911113\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0\x0f\x00\ +\x00\xc0\x03\x00\x00\x80\x01\x00\x00\x80\x01\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x01\x00\ +\x00\x80\x01\x00\x00\xc0\x03\x00\x00\xf0\x0f\x00\x00\ +\x00\x00\x03E\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22?>\x0a\x0a source control\ + - warning v2\x0a \x0a \ + \x0a \x0a\x0a\ +\x00\x00\x04~\ +\x00\ +\x00\x01\x00\x01\x00\x10\x10\x00\x00\x00\x00 \x00h\x04\x00\ +\x00\x16\x00\x00\x00(\x00\x00\x00\x10\x00\x00\x00 \x00\x00\ +\x00\x01\x00 \x00\x00\x00\x00\x00@\x04\x00\x00\x13\x0b\x00\ +\x00\x13\x0b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +>\x00\x00\x00\xa1\x00\x00\x00\xd6\x00\x00\x00\xeb\x00\x00\x00\ +\xec\x00\x00\x00\xd8\x00\x00\x00\xa7\x00\x00\x00G\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x9e\x0148\ +\xff\x02\x8c\x92\xff\x01\xbf\xc1\xff\x01\xd5\xd4\xff\x01\xd6\xd5\ +\xff\x01\xc2\xc3\xff\x01\x91\x97\xff\x01;@\xff\x00\x00\x00\ +\xac\x00\x00\x00\x12\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x0c\x00\x00\x00\xbb\x01bh\xff\x01\xe7\xe6\ +\xff\x00\xec\xe6\xff\x00\xec\xe6\xff\x00\xeb\xe6\xff\x00\xeb\xe6\ +\xff\x00\xec\xe6\xff\x00\xec\xe6\xff\x01\xe8\xe6\xff\x01io\ +\xff\x00\x00\x00\xc9\x00\x00\x00\x13\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x98\x02cj\xff\x00\xea\xe6\xff\x00\xec\xe6\ +\xff\x00\xeb\xe6\xff\x00\xeb\xe6\xff\x00\xeb\xe6\xff\x00\xeb\xe6\ +\xff\x00\xeb\xe6\xff\x00\xeb\xe6\xff\x00\xec\xe6\xff\x01\xeb\xe6\ +\xff\x01jp\xff\x00\x00\x00\xaf\x00\x00\x00\x00\x00\x00\x00\ +0\x00\x00\x00\xfd\x01\xe4\xe4\xff\x00\xec\xe6\xff\x00\xeb\xe6\ +\xff\x00\xeb\xe6\xff\x00\xeb\xe6\xff\x00\xeb\xe6\xff\x00\xeb\xe6\ +\xff\x00\xeb\xe6\xff\x00\xeb\xe6\xff\x00\xeb\xe6\xff\x00\xec\xe6\ +\xff\x01\xe8\xe6\xff\x019>\xff\x00\x00\x00E\x00\x00\x00\ +\x92\x02~\x84\xff\x00\xec\xe6\xff\x00\xeb\xe6\xff\x00\xeb\xe6\ +\xff\x00\xeb\xe6\xff\x00\xeb\xe6\xff\x00\xeb\xe6\xff\x00\xeb\xe6\ +\xff\x00\xeb\xe6\xff\x00\xeb\xe6\xff\x00\xeb\xe6\xff\x00\xeb\xe6\ +\xff\x00\xec\xe6\xff\x01\x93\x9a\xff\x00\x00\x00\xaa\x00\x00\x00\ +\xce\x02\xb7\xba\xff\x00\xec\xe6\xff\x00\xeb\xe6\xff\x00\xeb\xe6\ +\xff\x00\xeb\xe6\xff\x00\xeb\xe6\xff\x00\xeb\xe6\xff\x00\xeb\xe6\ +\xff\x00\xeb\xe6\xff\x00\xeb\xe6\xff\x00\xeb\xe6\xff\x00\xeb\xe6\ +\xff\x00\xec\xe6\xff\x01\xc6\xc6\xff\x00\x00\x00\xdc\x00\x00\x00\ +\xea\x01\xd3\xd3\xff\x00\xec\xe6\xff\x04\xeb\xe9\xff\x04\xeb\xe9\ +\xff\x03\xeb\xe9\xff\x02\xeb\xe8\xff\x02\xeb\xe7\xff\x01\xeb\xe7\ +\xff\x00\xeb\xe6\xff\x00\xeb\xe6\xff\x00\xeb\xe6\xff\x00\xeb\xe6\ +\xff\x00\xeb\xe6\xff\x01\xd7\xd6\xff\x00\x00\x00\xed\x00\x00\x00\ +\xe8\x01\xd0\xd1\xff\x06\xec\xec\xff\x09\xeb\xee\xff\x08\xeb\xed\ +\xff\x07\xeb\xec\xff\x06\xeb\xeb\xff\x05\xeb\xeb\xff\x05\xeb\xea\ +\xff\x04\xeb\xe9\xff\x03\xeb\xe8\xff\x02\xeb\xe8\xff\x01\xeb\xe7\ +\xff\x00\xeb\xe6\xff\x01\xd7\xd6\xff\x00\x00\x00\xed\x00\x00\x00\ +\xcb\x03\xb4\xb9\xff\x0d\xec\xf1\xff\x0d\xeb\xf1\xff\x0c\xeb\xf0\ +\xff\x0b\xeb\xef\xff\x0a\xeb\xef\xff\x09\xeb\xee\xff\x08\xeb\xed\ +\xff\x07\xeb\xed\xff\x07\xeb\xec\xff\x06\xeb\xeb\xff\x05\xeb\xea\ +\xff\x01\xec\xe6\xff\x01\xc2\xc4\xff\x00\x00\x00\xd9\x00\x00\x00\ +\x8b\x03x\x7f\xff\x10\xec\xf4\xff\x10\xec\xf4\xff\x0f\xec\xf3\ +\xff\x0e\xec\xf3\xff\x0e\xeb\xf2\xff\x0d\xeb\xf1\xff\x0c\xeb\xf1\ +\xff\x0b\xeb\xf0\xff\x0a\xeb\xef\xff\x09\xeb\xee\xff\x09\xeb\xee\ +\xff\x03\xec\xe9\xff\x01\x8d\x93\xff\x00\x00\x00\xa3\x00\x00\x00\ +(\x00\x00\x00\xfa\x0d\xd9\xe5\xff\x15\xec\xf9\xff\x13\xec\xf7\ +\xff\x12\xec\xf6\xff\x11\xec\xf5\xff\x10\xec\xf5\xff\x10\xec\xf4\ +\xff\x0f\xec\xf3\xff\x0e\xeb\xf2\xff\x0d\xeb\xf2\xff\x0d\xec\xf1\ +\xff\x04\xe7\xe9\xff\x0115\xff\x00\x00\x00;\x00\x00\x00\ +\x00\x00\x00\x00\x88\x03^e\xff\x15\xe9\xf8\xff\x18\xec\xfb\ +\xff\x16\xec\xf9\xff\x15\xec\xf9\xff\x14\xec\xf8\xff\x13\xec\xf7\ +\xff\x12\xec\xf6\xff\x12\xec\xf6\xff\x12\xec\xf6\xff\x0d\xea\xf1\ +\xff\x02ci\xff\x00\x00\x00\x9f\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x05\x00\x00\x00\xaa\x03]d\xff\x13\xd9\xea\ +\xff\x1a\xec\xfe\xff\x1a\xec\xfd\xff\x19\xec\xfc\xff\x18\xec\xfb\ +\xff\x17\xec\xfb\xff\x17\xec\xfa\xff\x11\xe3\xf1\xff\x03cj\ +\xff\x00\x00\x00\xbb\x00\x00\x00\x0b\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x88\x00\x00\x00\ +\xf6\x06w\x81\xff\x0e\xb2\xc0\xff\x13\xd1\xe2\xff\x13\xd2\xe2\ +\xff\x0e\xb6\xc3\xff\x07~\x88\xff\x00\x00\x00\xfb\x00\x00\x00\ +\x96\x00\x00\x00\x0b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ ++\x00\x00\x00\x8a\x00\x00\x00\xc8\x00\x00\x00\xe7\x00\x00\x00\ +\xe8\x00\x00\x00\xcb\x00\x00\x00\x91\x00\x00\x003\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0\x0f\x00\ +\x00\xc0\x03\x00\x00\x80\x01\x00\x00\x80\x01\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x01\x00\ +\x00\x80\x01\x00\x00\xc0\x03\x00\x00\xf0\x0f\x00\x00\ +\x00\x00\x04~\ +\x00\ +\x00\x01\x00\x01\x00\x10\x10\x00\x00\x01\x00 \x00h\x04\x00\ +\x00\x16\x00\x00\x00(\x00\x00\x00\x10\x00\x00\x00 \x00\x00\ +\x00\x01\x00 \x00\x00\x00\x00\x00@\x04\x00\x00\x13\x0b\x00\ +\x00\x13\x0b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00|||\ +>|||\xa1|||\xd6|||\xeb|||\ +\xec|||\xd8|||\xa7|||G\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00|||\x0a|||\x9e\x89\x89\x89\ +\xff\x9e\x9e\x9e\xff\xa8\xa8\xa8\xff\xac\xac\xac\xff\xad\xad\xad\ +\xff\xa9\xa9\xa9\xff\x9f\x9f\x9f\xff\x8b\x8b\x8b\xff|||\ +\xac|||\x12\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00|||\x0c|||\xbb\x94\x94\x94\xff\xb0\xb0\xb0\ +\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\ +\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\xff\x96\x96\x96\ +\xff|||\xc9|||\x13\x00\x00\x00\x00\x00\x00\x00\ +\x00|||\x98\x95\x95\x95\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\ +\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\ +\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\ +\xff\x96\x96\x96\xff|||\xaf\x00\x00\x00\x00|||\ +0|||\xfd\xb0\xb0\xb0\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\ +\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\ +\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\ +\xff\xb0\xb0\xb0\xff\x8a\x8a\x8a\xff|||E|||\ +\x92\x9b\x9b\x9b\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\ +\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\ +\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\ +\xff\xb0\xb0\xb0\xff\x9f\x9f\x9f\xff|||\xaa|||\ +\xce\xa6\xa6\xa6\xff\xaf\xaf\xaf\xff\xaf\xaf\xaf\xff\xb0\xb0\xb0\ +\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\ +\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\ +\xff\xb0\xb0\xb0\xff\xaa\xaa\xaa\xff|||\xdc|||\ +\xea\xac\xac\xac\xff\xb0\xb0\xb0\xff\xb3\xb3\xb3\xff\xb4\xb4\xb4\ +\xff\xb3\xb3\xb3\xff\xb2\xb2\xb2\xff\xb1\xb1\xb1\xff\xb1\xb1\xb1\ +\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\xff\xb0\xb0\xb0\ +\xff\xb0\xb0\xb0\xff\xad\xad\xad\xff|||\xed|||\ +\xe8\xac\xac\xac\xff\xb6\xb6\xb6\xff\xb9\xb9\xb9\xff\xb8\xb8\xb8\ +\xff\xb7\xb7\xb7\xff\xb6\xb6\xb6\xff\xb5\xb5\xb5\xff\xb4\xb4\xb4\ +\xff\xb3\xb3\xb3\xff\xb2\xb2\xb2\xff\xb2\xb2\xb2\xff\xb0\xb0\xb0\ +\xff\xaf\xaf\xaf\xff\xad\xad\xad\xff|||\xed|||\ +\xcb\xa8\xa8\xa8\xff\xbd\xbd\xbd\xff\xbc\xbc\xbc\xff\xbb\xbb\xbb\ +\xff\xbb\xbb\xbb\xff\xba\xba\xba\xff\xb9\xb9\xb9\xff\xb8\xb8\xb8\ +\xff\xb7\xb7\xb7\xff\xb6\xb6\xb6\xff\xb5\xb5\xb5\xff\xb4\xb4\xb4\ +\xff\xb0\xb0\xb0\xff\xa9\xa9\xa9\xff|||\xd9|||\ +\x8b\x9b\x9b\x9b\xff\xc0\xc0\xc0\xff\xc0\xc0\xc0\xff\xbf\xbf\xbf\ +\xff\xbe\xbe\xbe\xff\xbd\xbd\xbd\xff\xbd\xbd\xbd\xff\xbc\xbc\xbc\ +\xff\xbb\xbb\xbb\xff\xba\xba\xba\xff\xb9\xb9\xb9\xff\xb9\xb9\xb9\ +\xff\xb3\xb3\xb3\xff\x9e\x9e\x9e\xff|||\xa3|||\ +(|||\xfa\xba\xba\xba\xff\xc5\xc5\xc5\xff\xc3\xc3\xc3\ +\xff\xc2\xc2\xc2\xff\xc1\xc1\xc1\xff\xc1\xc1\xc1\xff\xc0\xc0\xc0\ +\xff\xbf\xbf\xbf\xff\xbe\xbe\xbe\xff\xbd\xbd\xbd\xff\xbd\xbd\xbd\ +\xff\xb4\xb4\xb4\xff\x88\x88\x88\xff|||;\x00\x00\x00\ +\x00|||\x88\x95\x95\x95\xff\xc5\xc5\xc5\xff\xc8\xc8\xc8\ +\xff\xc6\xc6\xc6\xff\xc5\xc5\xc5\xff\xc4\xc4\xc4\xff\xc3\xc3\xc3\ +\xff\xc3\xc3\xc3\xff\xc2\xc2\xc2\xff\xc2\xc2\xc2\xff\xbd\xbd\xbd\ +\xff\x95\x95\x95\xff|||\x9f\x00\x00\x00\x00\x00\x00\x00\ +\x00|||\x05|||\xaa\x95\x95\x95\xff\xc0\xc0\xc0\ +\xff\xcb\xcb\xcb\xff\xca\xca\xca\xff\xc9\xc9\xc9\xff\xc8\xc8\xc8\ +\xff\xc7\xc7\xc7\xff\xc7\xc7\xc7\xff\xc0\xc0\xc0\xff\x96\x96\x96\ +\xff|||\xbb|||\x0b\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00|||\x04|||\x88|||\ +\xf6\x9e\x9e\x9e\xff\xb3\xb3\xb3\xff\xbe\xbe\xbe\xff\xbf\xbf\xbf\ +\xff\xb3\xb3\xb3\xff\xa0\xa0\xa0\xff|||\xfb|||\ +\x96|||\x0b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00|||\ ++|||\x8a|||\xc8|||\xe7|||\ +\xe8|||\xcb|||\x91|||3\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0\x0f\x00\ +\x00\xc0\x03\x00\x00\x80\x01\x00\x00\x80\x01\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x01\x00\ +\x00\x80\x01\x00\x00\xc0\x03\x00\x00\xf0\x0f\x00\x00\ +\x00\x00\x03=\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22?>\x0a\x0a source control\ + error v2\x0a \x0a \x0a \ +\x0a\x0a\ +" + +qt_resource_name = b"\ +\x00\x0f\ +\x04T\x95'\ +\x00b\ +\x00m\x00p\x000\x000\x000\x000\x005\x00_\x000\x000\x00.\x00p\x00n\x00g\ +\x00\x0f\ +\x04S\x95\xc7\ +\x00b\ +\x00m\x00p\x000\x000\x000\x000\x006\x00_\x000\x005\x00.\x00p\x00n\x00g\ +\x00\x09\ +\x0a\xc5\xacG\ +\x00w\ +\x00a\x00t\x00e\x00r\x00.\x00p\x00n\x00g\ +\x00\x15\ +\x06Z\x7fG\ +\x00p\ +\x00a\x00r\x00t\x00i\x00c\x00l\x00e\x00s\x00_\x00t\x00r\x00e\x00e\x00_\x000\x000\ +\x00.\x00p\x00n\x00g\ +\x00\x0f\ +\x04_\x95'\ +\x00b\ +\x00m\x00p\x000\x000\x000\x000\x005\x00_\x000\x009\x00.\x00p\x00n\x00g\ +\x00\x16\ +\x0eE\x9e\x87\ +\x00e\ +\x00r\x00r\x00o\x00r\x00_\x00r\x00e\x00p\x00o\x00r\x00t\x00_\x00e\x00r\x00r\x00o\ +\x00r\x00.\x00s\x00v\x00g\ +\x00\x09\ +\x08\xbcm\xc2\ +\x00s\ +\x00t\x00a\x00t\x00u\x00s\x00b\x00a\x00r\ +\x00\x0f\ +\x04P\x95\xc7\ +\x00b\ +\x00m\x00p\x000\x000\x000\x000\x006\x00_\x000\x004\x00.\x00p\x00n\x00g\ +\x00\x0f\ +\x04\x5c\x95'\ +\x00b\ +\x00m\x00p\x000\x000\x000\x000\x005\x00_\x000\x008\x00.\x00p\x00n\x00g\ +\x00\x18\ +\x00\xf0&'\ +\x00e\ +\x00r\x00r\x00o\x00r\x00_\x00r\x00e\x00p\x00o\x00r\x00t\x00_\x00w\x00a\x00r\x00n\ +\x00i\x00n\x00g\x00.\x00s\x00v\x00g\ +\x00\x18\ +\x0c\x85t\xe7\ +\x00e\ +\x00r\x00r\x00o\x00r\x00_\x00r\x00e\x00p\x00o\x00r\x00t\x00_\x00c\x00o\x00m\x00m\ +\x00e\x00n\x00t\x00.\x00s\x00v\x00g\ +\x00\x0a\ +\x03\xd6;g\ +\x00M\ +\x00a\x00i\x00n\x00W\x00i\x00n\x00d\x00o\x00w\ +\x00\x0f\ +\x04U\x95\xc7\ +\x00b\ +\x00m\x00p\x000\x000\x000\x000\x006\x00_\x000\x003\x00.\x00p\x00n\x00g\ +\x00\x09\ +\x0c\xe6\xbd#\ +\x00v\ +\x00i\x00e\x00w\x00p\x00a\x00n\x00e\x00s\ +\x00\x0f\ +\x04a\x95'\ +\x00b\ +\x00m\x00p\x000\x000\x000\x000\x005\x00_\x000\x007\x00.\x00p\x00n\x00g\ +\x00\x07\ +\x0a\xc9\xa6S\ +\x00c\ +\x00u\x00r\x00s\x00o\x00r\x00s\ +\x00\x15\ +\x06S\x7fG\ +\x00p\ +\x00a\x00r\x00t\x00i\x00c\x00l\x00e\x00s\x00_\x00t\x00r\x00e\x00e\x00_\x000\x007\ +\x00.\x00p\x00n\x00g\ +\x00\x0f\ +\x04R\x95\xc7\ +\x00b\ +\x00m\x00p\x000\x000\x000\x000\x006\x00_\x000\x002\x00.\x00p\x00n\x00g\ +\x00\x0f\ +\x04^\x95'\ +\x00b\ +\x00m\x00p\x000\x000\x000\x000\x005\x00_\x000\x006\x00.\x00p\x00n\x00g\ +\x00\x15\ +\x06P\x7fG\ +\x00p\ +\x00a\x00r\x00t\x00i\x00c\x00l\x00e\x00s\x00_\x00t\x00r\x00e\x00e\x00_\x000\x006\ +\x00.\x00p\x00n\x00g\ +\x00\x0f\ +\x04W\x95\xc7\ +\x00b\ +\x00m\x00p\x000\x000\x000\x000\x006\x00_\x000\x001\x00.\x00p\x00n\x00g\ +\x00\x0f\ +\x04S\x95'\ +\x00b\ +\x00m\x00p\x000\x000\x000\x000\x005\x00_\x000\x005\x00.\x00p\x00n\x00g\ +\x00\x15\ +\x06a\x7fG\ +\x00p\ +\x00a\x00r\x00t\x00i\x00c\x00l\x00e\x00s\x00_\x00t\x00r\x00e\x00e\x00_\x000\x005\ +\x00.\x00p\x00n\x00g\ +\x00\x0f\ +\x04T\x95\xc7\ +\x00b\ +\x00m\x00p\x000\x000\x000\x000\x006\x00_\x000\x000\x00.\x00p\x00n\x00g\ +\x00\x0f\ +\x04P\x95'\ +\x00b\ +\x00m\x00p\x000\x000\x000\x000\x005\x00_\x000\x004\x00.\x00p\x00n\x00g\ +\x00\x03\ +\x00\x00x\xc3\ +\x00r\ +\x00e\x00s\ +\x00\x14\ +\x07\x22u\xc7\ +\x00a\ +\x00r\x00h\x00i\x00t\x00y\x00p\x00e\x00_\x00t\x00r\x00e\x00e\x00_\x000\x003\x00.\ +\x00p\x00n\x00g\ +\x00\x05\ +\x00O\xa6S\ +\x00I\ +\x00c\x00o\x00n\x00s\ +\x00\x15\ +\x06^\x7fG\ +\x00p\ +\x00a\x00r\x00t\x00i\x00c\x00l\x00e\x00s\x00_\x00t\x00r\x00e\x00e\x00_\x000\x004\ +\x00.\x00p\x00n\x00g\ +\x00\x0f\ +\x04U\x95'\ +\x00b\ +\x00m\x00p\x000\x000\x000\x000\x005\x00_\x000\x003\x00.\x00p\x00n\x00g\ +\x00\x14\ +\x07!u\xc7\ +\x00a\ +\x00r\x00h\x00i\x00t\x00y\x00p\x00e\x00_\x00t\x00r\x00e\x00e\x00_\x000\x002\x00.\ +\x00p\x00n\x00g\ +\x00\x15\ +\x06_\x7fG\ +\x00p\ +\x00a\x00r\x00t\x00i\x00c\x00l\x00e\x00s\x00_\x00t\x00r\x00e\x00e\x00_\x000\x003\ +\x00.\x00p\x00n\x00g\ +\x00\x0b\ +\x0f\x08B\x1e\ +\x00A\ +\x00p\x00p\x00l\x00i\x00c\x00a\x00t\x00i\x00o\x00n\ +\x00\x0f\ +\x04R\x95'\ +\x00b\ +\x00m\x00p\x000\x000\x000\x000\x005\x00_\x000\x002\x00.\x00p\x00n\x00g\ +\x00\x14\ +\x07(u\xc7\ +\x00a\ +\x00r\x00h\x00i\x00t\x00y\x00p\x00e\x00_\x00t\x00r\x00e\x00e\x00_\x000\x001\x00.\ +\x00p\x00n\x00g\ +\x00\x17\ +\x04\xc9\x5cG\ +\x00e\ +\x00r\x00r\x00o\x00r\x00_\x00r\x00e\x00p\x00o\x00r\x00t\x00_\x00h\x00e\x00l\x00p\ +\x00e\x00r\x00.\x00s\x00v\x00g\ +\x00\x0f\ +\x04a\x95\xc7\ +\x00b\ +\x00m\x00p\x000\x000\x000\x000\x006\x00_\x000\x007\x00.\x00p\x00n\x00g\ +\x00\x15\ +\x06\x5c\x7fG\ +\x00p\ +\x00a\x00r\x00t\x00i\x00c\x00l\x00e\x00s\x00_\x00t\x00r\x00e\x00e\x00_\x000\x002\ +\x00.\x00p\x00n\x00g\ +\x00\x0f\ +\x04W\x95'\ +\x00b\ +\x00m\x00p\x000\x000\x000\x000\x005\x00_\x000\x001\x00.\x00p\x00n\x00g\ +\x00\x14\ +\x07'u\xc7\ +\x00a\ +\x00r\x00h\x00i\x00t\x00y\x00p\x00e\x00_\x00t\x00r\x00e\x00e\x00_\x000\x000\x00.\ +\x00p\x00n\x00g\ +\x00\x0f\ +\x04^\x95\xc7\ +\x00b\ +\x00m\x00p\x000\x000\x000\x000\x006\x00_\x000\x006\x00.\x00p\x00n\x00g\ +\x00\x15\ +\x06]\x7fG\ +\x00p\ +\x00a\x00r\x00t\x00i\x00c\x00l\x00e\x00s\x00_\x00t\x00r\x00e\x00e\x00_\x000\x001\ +\x00.\x00p\x00n\x00g\ +\x00\x1c\ +\x0d\x96`\x07\ +\x00o\ +\x003\x00d\x00e\x00_\x00a\x00p\x00p\x00l\x00i\x00c\x00a\x00t\x00i\x00o\x00n\x00_\ +\x00r\x00e\x00v\x00e\x00r\x00s\x00e\x00.\x00s\x00v\x00g\ +\x00\x0f\ +\x0e\x0f\xf3\xff\ +\x00o\ +\x003\x00d\x00e\x00_\x00e\x00d\x00i\x00t\x00o\x00r\x00.\x00i\x00c\x00o\ +\x00\x14\ +\x0b\x1b&\xb6\ +\x00P\ +\x00a\x00d\x00l\x00o\x00c\x00k\x00_\x00D\x00i\x00s\x00a\x00b\x00l\x00e\x00d\x00.\ +\x00t\x00i\x00f\ +\x00\x17\ +\x0c\x9a\xdb\xc7\ +\x00l\ +\x00o\x00c\x00k\x00_\x00c\x00i\x00r\x00c\x00l\x00e\x00_\x00d\x00e\x00f\x00a\x00u\ +\x00l\x00t\x00.\x00s\x00v\x00g\ +\x00\x10\ +\x07T\xb1'\ +\x00D\ +\x00e\x00f\x00a\x00u\x00l\x00t\x00_\x00o\x00p\x00e\x00n\x00.\x00s\x00v\x00g\ +\x00\x19\ +\x0e\xd2\x13\xe7\ +\x00S\ +\x00l\x00i\x00c\x00e\x00_\x00H\x00a\x00n\x00d\x00l\x00e\x00_\x00M\x00o\x00d\x00i\ +\x00f\x00i\x00e\x00d\x00.\x00s\x00v\x00g\ +\x00\x0e\ +\x0b\xd8M\x87\ +\x00l\ +\x00a\x00y\x00e\x00r\x00_\x00i\x00c\x00o\x00n\x00.\x00s\x00v\x00g\ +\x00\x15\ +\x01\xaf\x1c'\ +\x00E\ +\x00n\x00t\x00i\x00t\x00y\x00_\x00N\x00o\x00t\x00_\x00A\x00c\x00t\x00i\x00v\x00e\ +\x00.\x00s\x00v\x00g\ +\x00\x19\ +\x05\xf2\xd2\x07\ +\x00v\ +\x00i\x00s\x00_\x00o\x00n\x00_\x00N\x00o\x00t\x00T\x00r\x00a\x00n\x00s\x00p\x00a\ +\x00r\x00e\x00n\x00t\x00.\x00s\x00v\x00g\ +\x00\x1c\ +\x05A\x11\x07\ +\x00S\ +\x00l\x00i\x00c\x00e\x00_\x00H\x00a\x00n\x00d\x00l\x00e\x00_\x00E\x00d\x00i\x00t\ +\x00o\x00r\x00_\x00O\x00n\x00l\x00y\x00.\x00s\x00v\x00g\ +\x00\x16\ +\x0c>\x8f\xc7\ +\x00v\ +\x00i\x00s\x00_\x00c\x00i\x00r\x00c\x00l\x00e\x00_\x00d\x00e\x00f\x00a\x00u\x00l\ +\x00t\x00.\x00s\x00v\x00g\ +\x00%\ +\x0f-\x08'\ +\x00S\ +\x00l\x00i\x00c\x00e\x00_\x00H\x00a\x00n\x00d\x00l\x00e\x00_\x00M\x00o\x00d\x00i\ +\x00f\x00i\x00e\x00d\x00_\x00E\x00d\x00i\x00t\x00o\x00r\x00_\x00O\x00n\x00l\x00y\ +\x00.\x00s\x00v\x00g\ +\x00\x0a\ +\x01\xb91\x87\ +\x00l\ +\x00o\x00c\x00k\x00e\x00d\x00.\x00s\x00v\x00g\ +\x00\x0f\ +\x05bA^\ +\x00E\ +\x00y\x00e\x00_\x00O\x00p\x00e\x00n\x00_\x00H\x00i\x00d\x00d\x00e\x00n\ +\x00\x1b\ +\x05K\x05V\ +\x00P\ +\x00a\x00d\x00l\x00o\x00c\x00k\x00_\x00P\x00a\x00r\x00t\x00i\x00a\x00l\x00_\x00E\ +\x00n\x00a\x00b\x00l\x00e\x00d\x00.\x00t\x00i\x00f\ +\x00\x0c\ +\x0f^26\ +\x00E\ +\x00y\x00e\x00_\x00O\x00p\x00e\x00n\x00.\x00t\x00i\x00f\ +\x00\x10\ +\x03\xcaZG\ +\x00S\ +\x00l\x00i\x00c\x00e\x00_\x00E\x00n\x00t\x00i\x00t\x00y\x00.\x00s\x00v\x00g\ +\x00\x16\ +\x06\x8e\x16\xc7\ +\x00E\ +\x00n\x00t\x00i\x00t\x00y\x00_\x00E\x00d\x00i\x00t\x00o\x00r\x00_\x00O\x00n\x00l\ +\x00y\x00.\x00s\x00v\x00g\ +\x00\x1b\ +\x04\xe2\x14'\ +\x00l\ +\x00o\x00c\x00k\x00_\x00c\x00i\x00r\x00c\x00l\x00e\x00_\x00t\x00r\x00a\x00n\x00s\ +\x00p\x00a\x00r\x00e\x00n\x00t\x00.\x00s\x00v\x00g\ +\x00\x0d\ +\x01m\xcf\x96\ +\x00E\ +\x00y\x00e\x00_\x00S\x00l\x00a\x00s\x00h\x00.\x00t\x00i\x00f\ +\x00\x14\ +\x0e\x00\x9e6\ +\x00E\ +\x00y\x00e\x00_\x00P\x00a\x00r\x00t\x00i\x00a\x00l\x00_\x00O\x00p\x00e\x00n\x00.\ +\x00t\x00i\x00f\ +\x00\x07\ +\x0c\xf8ZG\ +\x00E\ +\x00y\x00e\x00.\x00s\x00v\x00g\ +\x00\x14\ +\x07T)\xf6\ +\x00E\ +\x00y\x00e\x00_\x00S\x00l\x00a\x00s\x00h\x00_\x00H\x00i\x00d\x00d\x00e\x00n\x00.\ +\x00t\x00i\x00f\ +\x00\x1a\ +\x00\xe3\x5c\xa7\ +\x00v\ +\x00i\x00s\x00_\x00c\x00i\x00r\x00c\x00l\x00e\x00_\x00t\x00r\x00a\x00n\x00s\x00p\ +\x00a\x00r\x00e\x00n\x00t\x00.\x00s\x00v\x00g\ +\x00/\ +\x0a\xf8TG\ +\x00S\ +\x00l\x00i\x00c\x00e\x00_\x00E\x00n\x00t\x00i\x00t\x00y\x00_\x00M\x00o\x00d\x00i\ +\x00f\x00i\x00e\x00d\x00_\x00E\x00d\x00i\x00t\x00o\x00r\x00_\x00O\x00n\x00l\x00y\ +\x00_\x00U\x00n\x00s\x00a\x00v\x00a\x00b\x00l\x00e\x00.\x00s\x00v\x00g\ +\x00\x13\ +\x09+\x00\xf6\ +\x00P\ +\x00a\x00d\x00l\x00o\x00c\x00k\x00_\x00E\x00n\x00a\x00b\x00l\x00e\x00d\x00.\x00t\ +\x00i\x00f\ +\x00\x19\ +\x07,\xf6\x07\ +\x00S\ +\x00l\x00i\x00c\x00e\x00_\x00E\x00n\x00t\x00i\x00t\x00y\x00_\x00M\x00o\x00d\x00i\ +\x00f\x00i\x00e\x00d\x00.\x00s\x00v\x00g\ +\x00.\ +\x07\x84Qg\ +\x00S\ +\x00l\x00i\x00c\x00e\x00_\x00E\x00n\x00t\x00i\x00t\x00y\x00_\x00M\x00o\x00d\x00i\ +\x00f\x00i\x00e\x00d\x00_\x00N\x00o\x00t\x00_\x00A\x00c\x00t\x00i\x00v\x00e\x00_\ +\x00U\x00n\x00s\x00a\x00v\x00a\x00b\x00l\x00e\x00.\x00s\x00v\x00g\ +\x00%\ +\x08\xc2\x87g\ +\x00S\ +\x00l\x00i\x00c\x00e\x00_\x00E\x00n\x00t\x00i\x00t\x00y\x00_\x00M\x00o\x00d\x00i\ +\x00f\x00i\x00e\x00d\x00_\x00E\x00d\x00i\x00t\x00o\x00r\x00_\x00O\x00n\x00l\x00y\ +\x00.\x00s\x00v\x00g\ +\x00\x19\ +\x0e\x89\x90\x16\ +\x00P\ +\x00a\x00d\x00l\x00o\x00c\x00k\x00_\x00E\x00n\x00a\x00b\x00l\x00e\x00d\x00_\x00H\ +\x00o\x00v\x00e\x00r\x00.\x00t\x00i\x00f\ +\x00\x1c\ +\x0bd6G\ +\x00S\ +\x00l\x00i\x00c\x00e\x00_\x00E\x00n\x00t\x00i\x00t\x00y\x00_\x00E\x00d\x00i\x00t\ +\x00o\x00r\x00_\x00O\x00n\x00l\x00y\x00.\x00s\x00v\x00g\ +\x00\x0b\ +\x052\xac\xa7\ +\x00P\ +\x00a\x00d\x00l\x00o\x00c\x00k\x00.\x00s\x00v\x00g\ +\x00\x10\ +\x08Y\x11\xa7\ +\x00S\ +\x00l\x00i\x00c\x00e\x00_\x00H\x00a\x00n\x00d\x00l\x00e\x00.\x00s\x00v\x00g\ +\x00$\ +\x05\xcb\xc5\xc7\ +\x00S\ +\x00l\x00i\x00c\x00e\x00_\x00E\x00n\x00t\x00i\x00t\x00y\x00_\x00M\x00o\x00d\x00i\ +\x00f\x00i\x00e\x00d\x00_\x00N\x00o\x00t\x00_\x00A\x00c\x00t\x00i\x00v\x00e\x00.\ +\x00s\x00v\x00g\ +\x00\x1b\ +\x0e\xf5\xfe\xc7\ +\x00S\ +\x00l\x00i\x00c\x00e\x00_\x00E\x00n\x00t\x00i\x00t\x00y\x00_\x00N\x00o\x00t\x00_\ +\x00A\x00c\x00t\x00i\x00v\x00e\x00.\x00s\x00v\x00g\ +\x00\x0c\ +\x0e=1\x87\ +\x00u\ +\x00n\x00l\x00o\x00c\x00k\x00e\x00d\x00.\x00s\x00v\x00g\ +\x00\x1a\ +\x00\x9cw\x07\ +\x00S\ +\x00l\x00i\x00c\x00e\x00_\x00E\x00n\x00t\x00i\x00t\x00y\x00_\x00U\x00n\x00s\x00a\ +\x00v\x00a\x00b\x00l\x00e\x00.\x00s\x00v\x00g\ +\x00\x1a\ +\x0a\xe9\xdc\x96\ +\x00P\ +\x00a\x00d\x00l\x00o\x00c\x00k\x00_\x00D\x00i\x00s\x00a\x00b\x00l\x00e\x00d\x00_\ +\x00H\x00o\x00v\x00e\x00r\x00.\x00t\x00i\x00f\ +\x00\x0a\ +\x00\xb5\xd1\xa7\ +\x00E\ +\x00n\x00t\x00i\x00t\x00y\x00.\x00s\x00v\x00g\ +\x00#\ +\x08\x0b\xd5\x87\ +\x00S\ +\x00l\x00i\x00c\x00e\x00_\x00E\x00n\x00t\x00i\x00t\x00y\x00_\x00M\x00o\x00d\x00i\ +\x00f\x00i\x00e\x00d\x00_\x00U\x00n\x00s\x00a\x00v\x00a\x00b\x00l\x00e\x00.\x00s\ +\x00v\x00g\ +\x00\x13\ +\x0e\x1c\x0e\xf6\ +\x00E\ +\x00y\x00e\x00_\x00S\x00l\x00a\x00s\x00h\x00_\x00H\x00o\x00v\x00e\x00r\x00.\x00t\ +\x00i\x00f\ +\x00\x1b\ +\x03\x98\x0c'\ +\x00S\ +\x00l\x00i\x00c\x00e\x00_\x00H\x00a\x00n\x00d\x00l\x00e\x00_\x00N\x00o\x00t\x00_\ +\x00A\x00c\x00t\x00i\x00v\x00e\x00.\x00s\x00v\x00g\ +\x00\x17\ +\x03\xf8\xf5g\ +\x00l\ +\x00o\x00c\x00k\x00_\x00o\x00n\x00_\x00t\x00r\x00a\x00n\x00s\x00p\x00a\x00r\x00e\ +\x00n\x00t\x00.\x00s\x00v\x00g\ +\x00\x1a\ +\x00\xb2\x86\xa7\ +\x00l\ +\x00o\x00c\x00k\x00_\x00o\x00n\x00_\x00N\x00o\x00t\x00T\x00r\x00a\x00n\x00s\x00p\ +\x00a\x00r\x00e\x00n\x00t\x00.\x00s\x00v\x00g\ +\x00\x08\ +\x00\x95Ug\ +\x00v\ +\x00i\x00s\x00b\x00.\x00s\x00v\x00g\ +\x00\x15\ +\x0c\x87\x8f\xd6\ +\x00E\ +\x00y\x00e\x00_\x00P\x00a\x00r\x00t\x00i\x00a\x00l\x00_\x00S\x00l\x00a\x00s\x00h\ +\x00.\x00t\x00i\x00f\ +\x00\x0f\ +\x09\xcbq\xa7\ +\x00v\ +\x00i\x00s\x00b\x00_\x00h\x00i\x00d\x00d\x00e\x00n\x00.\x00s\x00v\x00g\ +\x00\x12\ +\x02{\xf5\x96\ +\x00E\ +\x00y\x00e\x00_\x00O\x00p\x00e\x00n\x00_\x00H\x00o\x00v\x00e\x00r\x00.\x00t\x00i\ +\x00f\ +\x00$\ +\x0a9L\xa7\ +\x00S\ +\x00l\x00i\x00c\x00e\x00_\x00H\x00a\x00n\x00d\x00l\x00e\x00_\x00M\x00o\x00d\x00i\ +\x00f\x00i\x00e\x00d\x00_\x00N\x00o\x00t\x00_\x00A\x00c\x00t\x00i\x00v\x00e\x00.\ +\x00s\x00v\x00g\ +\x00\x16\ +\x05\x5c\xa1g\ +\x00v\ +\x00i\x00s\x00_\x00o\x00n\x00_\x00t\x00r\x00a\x00n\x00s\x00p\x00a\x00r\x00e\x00n\ +\x00t\x00.\x00s\x00v\x00g\ +\x00\x12\ +\x0cS?'\ +\x00D\ +\x00e\x00f\x00a\x00u\x00l\x00t\x00_\x00c\x00l\x00o\x00s\x00e\x00d\x00.\x00s\x00v\ +\x00g\ +\x00\x1c\ +\x0d\x1b}6\ +\x00P\ +\x00a\x00d\x00l\x00o\x00c\x00k\x00_\x00P\x00a\x00r\x00t\x00i\x00a\x00l\x00_\x00D\ +\x00i\x00s\x00a\x00b\x00l\x00e\x00d\x00.\x00t\x00i\x00f\ +\x00\x12\ +\x06\xdb\x9dg\ +\x00P\ +\x00r\x00e\x00f\x00e\x00r\x00e\x00n\x00c\x00e\x00s\x00_\x000\x001\x00.\x00p\x00n\ +\x00g\ +\x00\x0a\ +\x08v\x9cg\ +\x00G\ +\x00l\x00o\x00b\x00a\x00l\x00.\x00s\x00v\x00g\ +\x00\x0a\ +\x0c\x8dj\xa7\ +\x00C\ +\x00a\x00m\x00e\x00r\x00a\x00.\x00s\x00v\x00g\ +\x00\x18\ +\x03\x0f\xe0\xa7\ +\x00A\ +\x00W\x00S\x00_\x00p\x00r\x00e\x00f\x00e\x00r\x00e\x00n\x00c\x00e\x00s\x00_\x00i\ +\x00c\x00o\x00n\x00.\x00s\x00v\x00g\ +\x00\x12\ +\x06\xd8\x9dg\ +\x00P\ +\x00r\x00e\x00f\x00e\x00r\x00e\x00n\x00c\x00e\x00s\x00_\x000\x000\x00.\x00p\x00n\ +\x00g\ +\x00\x0c\ +\x0d\x08\xc6'\ +\x00V\ +\x00i\x00e\x00w\x00p\x00o\x00r\x00t\x00.\x00s\x00v\x00g\ +\x00\x12\ +\x06\xe1\x9dg\ +\x00P\ +\x00r\x00e\x00f\x00e\x00r\x00e\x00n\x00c\x00e\x00s\x00_\x000\x003\x00.\x00p\x00n\ +\x00g\ +\x00\x0a\ +\x00k\xd7\xa7\ +\x00M\ +\x00o\x00t\x00i\x00o\x00n\x00.\x00s\x00v\x00g\ +\x00\x12\ +\x06\xde\x9dg\ +\x00P\ +\x00r\x00e\x00f\x00e\x00r\x00e\x00n\x00c\x00e\x00s\x00_\x000\x002\x00.\x00p\x00n\ +\x00g\ +\x00\x09\ +\x09\xba\xcf\xa7\ +\x00D\ +\x00e\x00b\x00u\x00g\x00.\x00s\x00v\x00g\ +\x00\x10\ +\x03l\x17\xc7\ +\x00E\ +\x00x\x00p\x00e\x00r\x00i\x00m\x00e\x00n\x00t\x00a\x00l\x00.\x00s\x00v\x00g\ +\x00\x09\ +\x02\xc6\xc0\xc7\ +\x00F\ +\x00i\x00l\x00e\x00s\x00.\x00s\x00v\x00g\ +\x00\x0a\ +\x04o\x98\xe7\ +\x00G\ +\x00i\x00z\x00m\x00o\x00s\x00.\x00s\x00v\x00g\ +\x00\x07\ +\x0f\x07J\x02\ +\x00h\ +\x00i\x00t\x00.\x00c\x00u\x00r\ +\x00\x0e\ +\x06\x0c\xfb\x82\ +\x00a\ +\x00r\x00r\x00o\x00w\x00_\x00d\x00o\x00w\x00n\x00.\x00c\x00u\x00r\ +\x00\x0b\ +\x06\x89\xd9\x82\ +\x00c\ +\x00u\x00r\x00s\x00o\x00r\x001\x00.\x00c\x00u\x00r\ +\x00\x0b\ +\x06\x80\xd9\x82\ +\x00c\ +\x00u\x00r\x00s\x00o\x00r\x002\x00.\x00c\x00u\x00r\ +\x00\x17\ +\x06h\xad\xa2\ +\x00p\ +\x00o\x00i\x00n\x00t\x00e\x00r\x00_\x00s\x00o\x00_\x00s\x00e\x00l\x00_\x00p\x00l\ +\x00u\x00s\x00.\x00c\x00u\x00r\ +\x00\x0d\ +\x08\x8c:\xe2\ +\x00l\ +\x00e\x00f\x00t\x00r\x00i\x00g\x00h\x00t\x00.\x00c\x00u\x00r\ +\x00\x0e\ +\x03\x0c\x0f\xc2\ +\x00p\ +\x00o\x00i\x00n\x00t\x00e\x00r\x00H\x00i\x00t\x00.\x00c\x00u\x00r\ +\x00\x12\ +\x03\xfe\x1c\x82\ +\x00p\ +\x00o\x00i\x00n\x00t\x00e\x00r\x00_\x00s\x00m\x00o\x00o\x00t\x00h\x00.\x00c\x00u\ +\x00r\ +\x00\x11\ +\x06\x8d\xde\x82\ +\x00a\ +\x00r\x00r\x00o\x00w\x00_\x00u\x00p\x00r\x00i\x00g\x00h\x00t\x00.\x00c\x00u\x00r\ +\ +\x00\x0e\ +\x02\xc2\xa5\x82\ +\x00a\ +\x00r\x00r\x00_\x00a\x00d\x00d\x00k\x00e\x00y\x00.\x00c\x00u\x00r\ +\x00\x15\ +\x07\x0a7B\ +\x00p\ +\x00o\x00i\x00n\x00t\x00e\x00r\x00_\x00g\x00e\x00t\x00h\x00e\x00i\x00g\x00h\x00t\ +\x00.\x00c\x00u\x00r\ +\x00\x10\ +\x08\x83\x1e\x22\ +\x00p\ +\x00o\x00i\x00n\x00t\x00e\x00r\x00_\x00p\x00l\x00u\x00s\x00.\x00c\x00u\x00r\ +\x00\x11\ +\x0d\xbf%b\ +\x00o\ +\x00b\x00j\x00e\x00c\x00t\x00_\x00r\x00o\x00t\x00a\x00t\x00e\x00.\x00c\x00u\x00r\ +\ +\x00\x0f\ +\x07\xb5h\x82\ +\x00o\ +\x00b\x00j\x00e\x00c\x00t\x00_\x00m\x00o\x00v\x00e\x00.\x00c\x00u\x00r\ +\x00\x13\ +\x00.\xa8\x22\ +\x00p\ +\x00o\x00i\x00n\x00t\x00e\x00r\x00_\x00l\x00i\x00n\x00k\x00n\x00o\x00w\x00.\x00c\ +\x00u\x00r\ +\x00\x10\ +\x07\x0b\x1e\x82\ +\x00p\ +\x00o\x00i\x00n\x00t\x00e\x00r\x00_\x00l\x00i\x00n\x00k\x00.\x00c\x00u\x00r\ +\x00\x11\ +\x01\x93\x0c\x22\ +\x00p\ +\x00o\x00i\x00n\x00t\x00e\x00r\x00_\x00m\x00i\x00n\x00u\x00s\x00.\x00c\x00u\x00r\ +\ +\x00\x13\ +\x0aQ\xeab\ +\x00p\ +\x00o\x00i\x00n\x00t\x00e\x00r\x00D\x00r\x00a\x00g\x00I\x00t\x00e\x00m\x00.\x00c\ +\x00u\x00r\ +\x00\x0c\ +\x0b\xd0gb\ +\x00a\ +\x00r\x00r\x00o\x00w\x00_\x00u\x00p\x00.\x00c\x00u\x00r\ +\x00\x0f\ +\x0eO\xc8\x02\ +\x00p\ +\x00i\x00c\x00k\x00_\x00c\x00u\x00r\x00s\x00o\x00r\x00.\x00c\x00u\x00r\ +\x00\x0c\ +\x0el\xec\xa2\ +\x00c\ +\x00u\x00r\x000\x000\x000\x000\x001\x00.\x00c\x00u\x00r\ +\x00\x0c\ +\x0em\xec\xa2\ +\x00c\ +\x00u\x00r\x000\x000\x000\x000\x002\x00.\x00c\x00u\x00r\ +\x00\x0c\ +\x0en\xec\xa2\ +\x00c\ +\x00u\x00r\x000\x000\x000\x000\x003\x00.\x00c\x00u\x00r\ +\x00\x0c\ +\x05\xaa\xdb\xa2\ +\x00h\ +\x00a\x00n\x00d\x00D\x00r\x00a\x00g\x00.\x00c\x00u\x00r\ +\x00\x0c\ +\x0eo\xec\xa2\ +\x00c\ +\x00u\x00r\x000\x000\x000\x000\x004\x00.\x00c\x00u\x00r\ +\x00\x10\ +\x03y\xfd\xc2\ +\x00o\ +\x00b\x00j\x00e\x00c\x00t\x00_\x00s\x00c\x00a\x00l\x00e\x00.\x00c\x00u\x00r\ +\x00\x0c\ +\x0ep\xec\xa2\ +\x00c\ +\x00u\x00r\x000\x000\x000\x000\x005\x00.\x00c\x00u\x00r\ +\x00\x0c\ +\x02\xaeA\x82\ +\x00p\ +\x00o\x00i\x00n\x00t\x00e\x00r\x00_\x00.\x00c\x00u\x00r\ +\x00\x15\ +\x0eb\xe8\x22\ +\x00p\ +\x00o\x00i\x00n\x00t\x00e\x00r\x00_\x00s\x00o\x00_\x00s\x00e\x00l\x00e\x00c\x00t\ +\x00.\x00c\x00u\x00r\ +\x00\x13\ +\x096M\x02\ +\x00a\ +\x00r\x00r\x00o\x00w\x00_\x00d\x00o\x00w\x00n\x00r\x00i\x00g\x00h\x00t\x00.\x00c\ +\x00u\x00r\ +\x00\x13\ +\x0f\xbas\x02\ +\x00p\ +\x00o\x00i\x00n\x00t\x00e\x00r\x00_\x00f\x00l\x00a\x00t\x00t\x00e\x00n\x00.\x00c\ +\x00u\x00r\ +\x00\x0c\ +\x0fy\xb7\xc7\ +\x00m\ +\x00a\x00x\x00i\x00m\x00i\x00z\x00e\x00.\x00p\x00n\x00g\ +\x00\x10\ +\x0a5o'\ +\x00h\ +\x00i\x00d\x00e\x00_\x00h\x00e\x00l\x00p\x00e\x00r\x00s\x00.\x00p\x00n\x00g\ +\x00\x10\ +\x0a\x9d~\xc7\ +\x00d\ +\x00i\x00s\x00p\x00l\x00a\x00y\x00_\x00i\x00n\x00f\x00o\x00.\x00p\x00n\x00g\ +\x00\x17\ +\x04\xb0\xfe\xc7\ +\x00e\ +\x00d\x00i\x00t\x00w\x00i\x00t\x00h\x00b\x00u\x00t\x00t\x00o\x00n\x00_\x00d\x00a\ +\x00r\x00k\x00.\x00p\x00n\x00g\ +\x00\x08\ +\x06b\x87\xf3\ +\x00t\ +\x00o\x00o\x00l\x00b\x00a\x00r\x00s\ +\x00\x1d\ +\x08\xa8\xaf\xe7\ +\x00s\ +\x00t\x00a\x00n\x00d\x00a\x00r\x00d\x00_\x00v\x00i\x00e\x00w\x00s\x00_\x00t\x00o\ +\x00o\x00l\x00b\x00a\x00r\x00-\x000\x005\x00.\x00p\x00n\x00g\ +\x00\x15\ +\x0e\x98q\xa7\ +\x00o\ +\x00b\x00j\x00e\x00c\x00t\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\x00-\x000\x004\ +\x00.\x00p\x00n\x00g\ +\x00\x18\ +\x000\xce\x87\ +\x00e\ +\x00d\x00i\x00t\x00_\x00m\x00o\x00d\x00e\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\ +\x00-\x001\x004\x00.\x00p\x00n\x00g\ +\x00\x18\ +\x00N\xce\x87\ +\x00e\ +\x00d\x00i\x00t\x00_\x00m\x00o\x00d\x00e\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\ +\x00-\x000\x006\x00.\x00p\x00n\x00g\ +\x00\x1d\ +\x08\xd5\xaf\xe7\ +\x00s\ +\x00t\x00a\x00n\x00d\x00a\x00r\x00d\x00_\x00v\x00i\x00e\x00w\x00s\x00_\x00t\x00o\ +\x00o\x00l\x00b\x00a\x00r\x00-\x001\x002\x00.\x00p\x00n\x00g\ +\x00\x1d\ +\x08\xa7\xaf\xe7\ +\x00s\ +\x00t\x00a\x00n\x00d\x00a\x00r\x00d\x00_\x00v\x00i\x00e\x00w\x00s\x00_\x00t\x00o\ +\x00o\x00l\x00b\x00a\x00r\x00-\x000\x004\x00.\x00p\x00n\x00g\ +\x00\x18\ +\x005\xce\x87\ +\x00e\ +\x00d\x00i\x00t\x00_\x00m\x00o\x00d\x00e\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\ +\x00-\x001\x003\x00.\x00p\x00n\x00g\ +\x00\x18\ +\x00C\xce\x87\ +\x00e\ +\x00d\x00i\x00t\x00_\x00m\x00o\x00d\x00e\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\ +\x00-\x000\x005\x00.\x00p\x00n\x00g\ +\x00\x1d\ +\x08\xd4\xaf\xe7\ +\x00s\ +\x00t\x00a\x00n\x00d\x00a\x00r\x00d\x00_\x00v\x00i\x00e\x00w\x00s\x00_\x00t\x00o\ +\x00o\x00l\x00b\x00a\x00r\x00-\x001\x001\x00.\x00p\x00n\x00g\ +\x00\x15\ +\x0e\xecq\xa7\ +\x00o\ +\x00b\x00j\x00e\x00c\x00t\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\x00-\x001\x000\ +\x00.\x00p\x00n\x00g\ +\x00\x18\ +\x00$\xce\x87\ +\x00e\ +\x00d\x00i\x00t\x00_\x00m\x00o\x00d\x00e\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\ +\x00-\x002\x000\x00.\x00p\x00n\x00g\ +\x00\x1d\ +\x08\xa6\xaf\xe7\ +\x00s\ +\x00t\x00a\x00n\x00d\x00a\x00r\x00d\x00_\x00v\x00i\x00e\x00w\x00s\x00_\x00t\x00o\ +\x00o\x00l\x00b\x00a\x00r\x00-\x000\x003\x00.\x00p\x00n\x00g\ +\x00\x15\ +\x0e\x9aq\xa7\ +\x00o\ +\x00b\x00j\x00e\x00c\x00t\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\x00-\x000\x002\ +\x00.\x00p\x00n\x00g\ +\x00\x18\ +\x002\xce\x87\ +\x00e\ +\x00d\x00i\x00t\x00_\x00m\x00o\x00d\x00e\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\ +\x00-\x001\x002\x00.\x00p\x00n\x00g\ +\x00\x1e\ +\x076,\x87\ +\x00p\ +\x00r\x00o\x00c\x00e\x00d\x00u\x00r\x00a\x00l\x00m\x00a\x00t\x00e\x00r\x00i\x00a\ +\x00l\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\x00.\x00p\x00n\x00g\ +\x00\x1d\ +\x08\xd3\xaf\xe7\ +\x00s\ +\x00t\x00a\x00n\x00d\x00a\x00r\x00d\x00_\x00v\x00i\x00e\x00w\x00s\x00_\x00t\x00o\ +\x00o\x00l\x00b\x00a\x00r\x00-\x001\x000\x00.\x00p\x00n\x00g\ +\x00\x1d\ +\x08\xa5\xaf\xe7\ +\x00s\ +\x00t\x00a\x00n\x00d\x00a\x00r\x00d\x00_\x00v\x00i\x00e\x00w\x00s\x00_\x00t\x00o\ +\x00o\x00l\x00b\x00a\x00r\x00-\x000\x002\x00.\x00p\x00n\x00g\ +\x00\x15\ +\x0e\x9fq\xa7\ +\x00o\ +\x00b\x00j\x00e\x00c\x00t\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\x00-\x000\x001\ +\x00.\x00p\x00n\x00g\ +\x00\x18\ +\x007\xce\x87\ +\x00e\ +\x00d\x00i\x00t\x00_\x00m\x00o\x00d\x00e\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\ +\x00-\x001\x001\x00.\x00p\x00n\x00g\ +\x00\x18\ +\x00E\xce\x87\ +\x00e\ +\x00d\x00i\x00t\x00_\x00m\x00o\x00d\x00e\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\ +\x00-\x000\x003\x00.\x00p\x00n\x00g\ +\x00\x13\ +\x0c\xd0\x1e\x87\ +\x00m\ +\x00i\x00s\x00c\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\x00-\x000\x000\x00.\x00p\ +\x00n\x00g\ +\x00\x1d\ +\x08\xa4\xaf\xe7\ +\x00s\ +\x00t\x00a\x00n\x00d\x00a\x00r\x00d\x00_\x00v\x00i\x00e\x00w\x00s\x00_\x00t\x00o\ +\x00o\x00l\x00b\x00a\x00r\x00-\x000\x001\x00.\x00p\x00n\x00g\ +\x00\x15\ +\x0e\x9cq\xa7\ +\x00o\ +\x00b\x00j\x00e\x00c\x00t\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\x00-\x000\x000\ +\x00.\x00p\x00n\x00g\ +\x00\x18\ +\x004\xce\x87\ +\x00e\ +\x00d\x00i\x00t\x00_\x00m\x00o\x00d\x00e\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\ +\x00-\x001\x000\x00.\x00p\x00n\x00g\ +\x00\x1d\ +\x08\xdb\xaf\xe7\ +\x00s\ +\x00t\x00a\x00n\x00d\x00a\x00r\x00d\x00_\x00v\x00i\x00e\x00w\x00s\x00_\x00t\x00o\ +\x00o\x00l\x00b\x00a\x00r\x00-\x001\x008\x00.\x00p\x00n\x00g\ +\x00\x18\ +\x00B\xce\x87\ +\x00e\ +\x00d\x00i\x00t\x00_\x00m\x00o\x00d\x00e\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\ +\x00-\x000\x002\x00.\x00p\x00n\x00g\ +\x00\x15\ +\x0e\x97q\xa7\ +\x00o\ +\x00b\x00j\x00e\x00c\x00t\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\x00-\x000\x009\ +\x00.\x00p\x00n\x00g\ +\x00\x18\ +\x00?\xce\x87\ +\x00e\ +\x00d\x00i\x00t\x00_\x00m\x00o\x00d\x00e\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\ +\x00-\x001\x009\x00.\x00p\x00n\x00g\ +\x00\x10\ +\x0f\xf1A\xe7\ +\x00O\ +\x00b\x00j\x00S\x00e\x00l\x00e\x00c\x00t\x00i\x00o\x00n\x00.\x00p\x00n\x00g\ +\x00\x1d\ +\x08\xa3\xaf\xe7\ +\x00s\ +\x00t\x00a\x00n\x00d\x00a\x00r\x00d\x00_\x00v\x00i\x00e\x00w\x00s\x00_\x00t\x00o\ +\x00o\x00l\x00b\x00a\x00r\x00-\x000\x000\x00.\x00p\x00n\x00g\ +\x00\x1d\ +\x08\xda\xaf\xe7\ +\x00s\ +\x00t\x00a\x00n\x00d\x00a\x00r\x00d\x00_\x00v\x00i\x00e\x00w\x00s\x00_\x00t\x00o\ +\x00o\x00l\x00b\x00a\x00r\x00-\x001\x007\x00.\x00p\x00n\x00g\ +\x00\x18\ +\x00G\xce\x87\ +\x00e\ +\x00d\x00i\x00t\x00_\x00m\x00o\x00d\x00e\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\ +\x00-\x000\x001\x00.\x00p\x00n\x00g\ +\x00\x1d\ +\x08\xac\xaf\xe7\ +\x00s\ +\x00t\x00a\x00n\x00d\x00a\x00r\x00d\x00_\x00v\x00i\x00e\x00w\x00s\x00_\x00t\x00o\ +\x00o\x00l\x00b\x00a\x00r\x00-\x000\x009\x00.\x00p\x00n\x00g\ +\x00\x15\ +\x0e\x94q\xa7\ +\x00o\ +\x00b\x00j\x00e\x00c\x00t\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\x00-\x000\x008\ +\x00.\x00p\x00n\x00g\ +\x00\x18\ +\x00<\xce\x87\ +\x00e\ +\x00d\x00i\x00t\x00_\x00m\x00o\x00d\x00e\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\ +\x00-\x001\x008\x00.\x00p\x00n\x00g\ +\x00\x1d\ +\x08\xd9\xaf\xe7\ +\x00s\ +\x00t\x00a\x00n\x00d\x00a\x00r\x00d\x00_\x00v\x00i\x00e\x00w\x00s\x00_\x00t\x00o\ +\x00o\x00l\x00b\x00a\x00r\x00-\x001\x006\x00.\x00p\x00n\x00g\ +\x00\x18\ +\x00#\xce\x87\ +\x00e\ +\x00d\x00i\x00t\x00_\x00m\x00o\x00d\x00e\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\ +\x00-\x002\x005\x00.\x00p\x00n\x00g\ +\x00\x18\ +\x00D\xce\x87\ +\x00e\ +\x00d\x00i\x00t\x00_\x00m\x00o\x00d\x00e\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\ +\x00-\x000\x000\x00.\x00p\x00n\x00g\ +\x00\x1d\ +\x08\xab\xaf\xe7\ +\x00s\ +\x00t\x00a\x00n\x00d\x00a\x00r\x00d\x00_\x00v\x00i\x00e\x00w\x00s\x00_\x00t\x00o\ +\x00o\x00l\x00b\x00a\x00r\x00-\x000\x008\x00.\x00p\x00n\x00g\ +\x00\x15\ +\x0e\x99q\xa7\ +\x00o\ +\x00b\x00j\x00e\x00c\x00t\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\x00-\x000\x007\ +\x00.\x00p\x00n\x00g\ +\x00\x18\ +\x00A\xce\x87\ +\x00e\ +\x00d\x00i\x00t\x00_\x00m\x00o\x00d\x00e\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\ +\x00-\x001\x007\x00.\x00p\x00n\x00g\ +\x00\x18\ +\x00O\xce\x87\ +\x00e\ +\x00d\x00i\x00t\x00_\x00m\x00o\x00d\x00e\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\ +\x00-\x000\x009\x00.\x00p\x00n\x00g\ +\x00\x1d\ +\x08\xd8\xaf\xe7\ +\x00s\ +\x00t\x00a\x00n\x00d\x00a\x00r\x00d\x00_\x00v\x00i\x00e\x00w\x00s\x00_\x00t\x00o\ +\x00o\x00l\x00b\x00a\x00r\x00-\x001\x005\x00.\x00p\x00n\x00g\ +\x00\x18\ +\x00 \xce\x87\ +\x00e\ +\x00d\x00i\x00t\x00_\x00m\x00o\x00d\x00e\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\ +\x00-\x002\x004\x00.\x00p\x00n\x00g\ +\x00\x1d\ +\x08\xaa\xaf\xe7\ +\x00s\ +\x00t\x00a\x00n\x00d\x00a\x00r\x00d\x00_\x00v\x00i\x00e\x00w\x00s\x00_\x00t\x00o\ +\x00o\x00l\x00b\x00a\x00r\x00-\x000\x007\x00.\x00p\x00n\x00g\ +\x00\x15\ +\x0e\x96q\xa7\ +\x00o\ +\x00b\x00j\x00e\x00c\x00t\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\x00-\x000\x006\ +\x00.\x00p\x00n\x00g\ +\x00\x18\ +\x00>\xce\x87\ +\x00e\ +\x00d\x00i\x00t\x00_\x00m\x00o\x00d\x00e\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\ +\x00-\x001\x006\x00.\x00p\x00n\x00g\ +\x00\x18\ +\x00L\xce\x87\ +\x00e\ +\x00d\x00i\x00t\x00_\x00m\x00o\x00d\x00e\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\ +\x00-\x000\x008\x00.\x00p\x00n\x00g\ +\x00\x15\ +\x0e\x9d|'\ +\x00o\ +\x00b\x00j\x00e\x00c\x00t\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\x00-\x000\x003\ +\x00.\x00s\x00v\x00g\ +\x00\x1d\ +\x08\xd7\xaf\xe7\ +\x00s\ +\x00t\x00a\x00n\x00d\x00a\x00r\x00d\x00_\x00v\x00i\x00e\x00w\x00s\x00_\x00t\x00o\ +\x00o\x00l\x00b\x00a\x00r\x00-\x001\x004\x00.\x00p\x00n\x00g\ +\x00\x18\ +\x00%\xce\x87\ +\x00e\ +\x00d\x00i\x00t\x00_\x00m\x00o\x00d\x00e\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\ +\x00-\x002\x003\x00.\x00p\x00n\x00g\ +\x00\x1d\ +\x08\xa9\xaf\xe7\ +\x00s\ +\x00t\x00a\x00n\x00d\x00a\x00r\x00d\x00_\x00v\x00i\x00e\x00w\x00s\x00_\x00t\x00o\ +\x00o\x00l\x00b\x00a\x00r\x00-\x000\x006\x00.\x00p\x00n\x00g\ +\x00\x15\ +\x0e\x9bq\xa7\ +\x00o\ +\x00b\x00j\x00e\x00c\x00t\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\x00-\x000\x005\ +\x00.\x00p\x00n\x00g\ +\x00\x18\ +\x003\xce\x87\ +\x00e\ +\x00d\x00i\x00t\x00_\x00m\x00o\x00d\x00e\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\ +\x00-\x001\x005\x00.\x00p\x00n\x00g\ +\x00\x18\ +\x00Q\xce\x87\ +\x00e\ +\x00d\x00i\x00t\x00_\x00m\x00o\x00d\x00e\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\ +\x00-\x000\x007\x00.\x00p\x00n\x00g\ +\x00\x1d\ +\x08\xd6\xaf\xe7\ +\x00s\ +\x00t\x00a\x00n\x00d\x00a\x00r\x00d\x00_\x00v\x00i\x00e\x00w\x00s\x00_\x00t\x00o\ +\x00o\x00l\x00b\x00a\x00r\x00-\x001\x003\x00.\x00p\x00n\x00g\ +\x00\x18\ +\x00\x22\xce\x87\ +\x00e\ +\x00d\x00i\x00t\x00_\x00m\x00o\x00d\x00e\x00_\x00t\x00o\x00o\x00l\x00b\x00a\x00r\ +\x00-\x002\x002\x00.\x00p\x00n\x00g\ +\x00\x10\ +\x0c\x99\xf5\x1f\ +\x00b\ +\x00a\x00l\x00l\x00_\x00o\x00f\x00f\x00l\x00i\x00n\x00e\x00.\x00i\x00c\x00o\ +\x00\x1c\ +\x0d\xbb\x8bG\ +\x00s\ +\x00o\x00u\x00r\x00c\x00e\x00_\x00c\x00o\x00n\x00t\x00r\x00o\x00l\x00_\x00c\x00o\ +\x00n\x00n\x00e\x00c\x00t\x00e\x00d\x00.\x00s\x00v\x00g\ +\x00\x1c\ +\x03ZJ\xe7\ +\x00s\ +\x00o\x00u\x00r\x00c\x00e\x00_\x00c\x00o\x00n\x00t\x00r\x00o\x00l\x00-\x00n\x00o\ +\x00t\x00_\x00s\x00e\x00t\x00u\x00p\x00.\x00s\x00v\x00g\ +\x00\x0f\ +\x0a\x0d'\xdf\ +\x00b\ +\x00a\x00l\x00l\x00_\x00o\x00n\x00l\x00i\x00n\x00e\x00.\x00i\x00c\x00o\ +\x00\x1d\ +\x03\xe3zG\ +\x00s\ +\x00o\x00u\x00r\x00c\x00e\x00_\x00c\x00o\x00n\x00t\x00r\x00o\x00l\x00-\x00w\x00a\ +\x00r\x00n\x00i\x00n\x00g\x00_\x00v\x002\x00.\x00s\x00v\x00g\ +\x00\x10\ +\x0c\xa1\xe6\x1f\ +\x00b\ +\x00a\x00l\x00l\x00_\x00p\x00e\x00n\x00d\x00i\x00n\x00g\x00.\x00i\x00c\x00o\ +\x00\x11\ +\x08tl?\ +\x00b\ +\x00a\x00l\x00l\x00_\x00d\x00i\x00s\x00a\x00b\x00l\x00e\x00d\x00.\x00i\x00c\x00o\ +\ +\x00\x1b\ +\x00\x22\x12'\ +\x00s\ +\x00o\x00u\x00r\x00c\x00e\x00_\x00c\x00o\x00n\x00t\x00r\x00o\x00l\x00_\x00e\x00r\ +\x00r\x00o\x00r\x00_\x00v\x002\x00.\x00s\x00v\x00g\ +" + +qt_resource_struct = b"\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00*\x00\x00\x00\x01\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x03\xa8\x00\x02\x00\x00\x00\x0d\x00\x00\x00\xc7\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x03\xe2\x00\x02\x00\x00\x002\x00\x00\x00\x95\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x01F\x00\x00\x00\x00\x00\x01\x00\x00\xb10\ +\x00\x00\x01z\x88\x90A<\ +\x00\x00\x01\xb2\x00\x02\x00\x00\x00\x01\x00\x00\x00[\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x03\x84\x00\x00\x00\x00\x00\x01\x00\x00\xc6R\ +\x00\x00\x01z\x88\x90@,\ +\x00\x00\x00\xfe\x00\x00\x00\x00\x00\x01\x00\x00\xad\x09\ +\x00\x00\x01z\x88\x90@9\ +\x00\x00\x04\xc0\x00\x00\x00\x00\x00\x01\x00\x00\xce&\ +\x00\x00\x01z\x88\x90@)\ +\x00\x00\x02p\x00\x00\x00\x00\x00\x01\x00\x00\xbeB\ +\x00\x00\x01z\x88\x90@6\ +\x00\x00\x03\x0c\x00\x00\x00\x00\x00\x01\x00\x00\xc3\xce\ +\x00\x00\x01z\x88\x90@-\ +\x00\x00\x00$\x00\x00\x00\x00\x00\x01\x00\x00\x01\x88\ +\x00\x00\x01z\x88\x90@:\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ +\x00\x00\x01z\x88\x90@'\ +\x00\x00\x03`\x00\x00\x00\x00\x00\x01\x00\x00\xc5\xc3\ +\x00\x00\x01z\x88\x90@4\ +\x00\x00\x04\x22\x00\x00\x00\x00\x00\x01\x00\x00\xca_\ +\x00\x00\x01z\x88\x90@+\ +\x00\x00\x01\xcc\x00\x00\x00\x00\x00\x01\x00\x00\xbaZ\ +\x00\x00\x01z\x88\x90@7\ +\x00\x00\x05\x9a\x00\x00\x00\x00\x00\x01\x00\x00\xdbw\ +\x00\x00\x01z\x88\x90@(\ +\x00\x00\x02\xe8\x00\x00\x00\x00\x00\x01\x00\x00\xc3$\ +\x00\x00\x01z\x88\x90@5\ +\x00\x00\x01\x22\x00\x00\x00\x00\x00\x01\x00\x00\xae\x82\ +\x00\x00\x01z\x88\x90@1\ +\x00\x00\x02\x94\x00\x00\x00\x00\x00\x01\x00\x00\xbf1\ +\x00\x00\x01z\x88\x90@.\ +\x00\x00\x05\xec\x00\x00\x00\x00\x00\x01\x00\x00\xdec\ +\x00\x00\x01z\x88\x90@<\ +\x00\x00\x00\x90\x00\x00\x00\x00\x00\x01\x00\x00\xa6\x97\ +\x00\x00\x01z\x88\x90@2\ +\x00\x00\x02\x08\x00\x00\x00\x00\x00\x01\x00\x00\xbbp\ +\x00\x00\x01z\x88\x90@0\ +\x00\x00\x05F\x00\x00\x00\x00\x00\x01\x00\x00\xd5k\ +\x00\x00\x01z\x88\x90@=\ +\x00\x00\x05\x12\x00\x00\x00\x00\x00\x01\x00\x00\xd0\x86\ +\x00\x00\x01{[\xfa+\x98\ +\x00\x00\x02\xb8\x00\x00\x00\x00\x00\x01\x00\x00\xc2@\ +\x00\x00\x01z\x88\x90@R\ +\x00\x00\x02@\x00\x00\x00\x00\x00\x01\x00\x00\xbdi\ +\x00\x00\x01z\x88\x90@S\ +\x00\x00\x00`\x00\x00\x00\x00\x00\x01\x00\x00\xa5\xc3\ +\x00\x00\x01z\x88\x90@J\ +\x00\x00\x05j\x00\x00\x00\x00\x00\x01\x00\x00\xdaw\ +\x00\x00\x01z\x88\x90@M\ +\x00\x00\x06\x10\x00\x00\x00\x00\x00\x01\x00\x00\xe2\xb4\ +\x00\x00\x01z\x88\x90@L\ +\x00\x00\x03\xf2\x00\x00\x00\x00\x00\x01\x00\x00\xc9,\ +\x00\x00\x01z\x88\x90@O\ +\x00\x00\x04t\x00\x00\x00\x00\x00\x01\x00\x00\xcd\x1d\ +\x00\x00\x01z\x88\x90@N\ +\x00\x00\x030\x00\x00\x00\x00\x00\x01\x00\x00\xc4\xc1\ +\x00\x00\x01z\x88\x90@Q\ +\x00\x00\x04F\x00\x00\x00\x00\x00\x01\x00\x00\xccI\ +\x00\x00\x01z\x88\x90@$\ +\x00\x00\x03\xb4\x00\x00\x00\x00\x00\x01\x00\x00\xc8X\ +\x00\x00\x01z\x88\x90@%\ +\x00\x00\x05\xbe\x00\x00\x00\x00\x00\x01\x00\x00\xdd\x8f\ +\x00\x00\x01z\x88\x90@!\ +\x00\x00\x04\xe4\x00\x00\x00\x00\x00\x01\x00\x00\xcf\xb2\ +\x00\x00\x01z\x88\x90@#\ +\x00\x00\x00\xe6\x00\x02\x00\x00\x00\x01\x00\x00\x00R\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00H\x00\x00\x00\x00\x00\x01\x00\x00\x03\xf4\ +\x00\x00\x01z\x88\x90BH\ +\x00\x00\x02,\x00\x02\x00\x00\x00\x01\x00\x00\x002\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x01|\x00\x00\x00\x00\x00\x01\x00\x00\xb3\xd9\ +\x00\x00\x01z\x88\x90A:\ +\x00\x00\x01\xf0\x00\x02\x00\x00\x00\x04\x00\x00\x00.\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\xb4\x00\x00\x00\x00\x00\x01\x00\x00\xa9\x0c\ +\x00\x00\x01z\x88\x90A;\ +\x00\x00\x04\xa4\x00\x02\x00\x00\x00\x02\x00\x00\x00+\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x03\xa8\x00\x02\x00\x00\x00\x01\x00\x00\x00-\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x06@\x00\x00\x00\x00\x00\x01\x00\x00\xe3\x88\ +\x00\x00\x01{zp@\xc4\ +\x00\x00\x06~\x00\x01\x00\x00\x00\x01\x00\x00\xebr\ +\x00\x00\x01z\x88\x90A\xb7\ +\x00\x00\x17.\x00\x00\x00\x00\x00\x01\x00\x05\xae\xc9\ +\x00\x00\x01z\x88\x90<\xf1\ +\x00\x00\x16\xe2\x00\x00\x00\x00\x00\x01\x00\x05\xad\x1d\ +\x00\x00\x01z\x88\x90<\xf4\ +\x00\x00\x17\x08\x00\x00\x00\x00\x00\x01\x00\x05\xad\xf1\ +\x00\x00\x01z\x88\x90<\xd1\ +\x00\x00\x16\xc4\x00\x00\x00\x00\x00\x01\x00\x05\xac*\ +\x00\x00\x01z\x88\x90<\xf5\ +\x00\x00\x03\xa8\x00\x02\x00\x00\x00\x1f\x00\x00\x003\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x14\x5c\x00\x00\x00\x00\x00\x01\x00\x05\x98\x97\ +\x00\x00\x01z\x88\x90A\xde\ +\x00\x00\x14\xae\x00\x00\x00\x00\x00\x01\x00\x05\x9b+\ +\x00\x00\x01z\x88\x90A\xdf\ +\x00\x00\x16\x1e\x00\x00\x00\x00\x00\x01\x00\x05\xa7\xf2\ +\x00\x00\x01z\x88\x90A\xda\ +\x00\x00\x13\x98\x00\x00\x00\x00\x00\x01\x00\x05\x92%\ +\x00\x00\x01z\x88\x90@\xa7\ +\x00\x00\x13$\x00\x00\x00\x00\x00\x01\x00\x05\x8f5\ +\x00\x00\x01z\x88\x90A\xd9\ +\x00\x00\x15\xda\x00\x00\x00\x00\x00\x01\x00\x05\xa5^\ +\x00\x00\x01z\x88\x90A\xba\ +\x00\x00\x13F\x00\x00\x00\x00\x00\x01\x00\x05\x90\x7f\ +\x00\x00\x01z\x88\x90A\xe1\ +\x00\x00\x15\x9e\x00\x00\x00\x00\x00\x01\x00\x05\xa2\xca\ +\x00\x00\x01z\x88\x90Af\ +\x00\x00\x12v\x00\x01\x00\x00\x00\x01\x00\x05\x8b3\ +\x00\x00\x01z\x88\x90@\xa9\ +\x00\x00\x12\xd0\x00\x00\x00\x00\x00\x01\x00\x05\x8d\x87\ +\x00\x00\x01z\x88\x90A\xe2\ +\x00\x00\x12\xb4\x00\x01\x00\x00\x00\x01\x00\x05\x8c\xdc\ +\x00\x00\x01z\x88\x90@\xf8\ +\x00\x00\x12\x98\x00\x00\x00\x00\x00\x01\x00\x05\x8b\x92\ +\x00\x00\x01z\x88\x90@\xf8\ +\x00\x00\x13p\x00\x01\x00\x00\x00\x01\x00\x05\x91\xc9\ +\x00\x00\x01z\x88\x90@\xae\ +\x00\x00\x13\xba\x00\x00\x00\x00\x00\x01\x00\x05\x93o\ +\x00\x00\x01z\x88\x90A\xdc\ +\x00\x00\x14\x88\x00\x00\x00\x00\x00\x01\x00\x05\x99\xe1\ +\x00\x00\x01z\x88\x90A\xdd\ +\x00\x00\x148\x00\x00\x00\x00\x00\x01\x00\x05\x97M\ +\x00\x00\x01z\x88\x90A\xb8\ +\x00\x00\x13\xea\x00\x00\x00\x00\x00\x01\x00\x05\x94\xb9\ +\x00\x00\x01z\x88\x90A\xdf\ +\x00\x00\x13\x04\x00\x01\x00\x00\x00\x01\x00\x05\x8e\xd1\ +\x00\x00\x01z\x88\x90A\x98\ +\x00\x00\x16l\x00\x01\x00\x00\x00\x01\x00\x05\xaa\x86\ +\x00\x00\x01z\x88\x90@\xab\ +\x00\x00\x14\xd6\x00\x01\x00\x00\x00\x01\x00\x05\x9cu\ +\x00\x00\x01z\x88\x90A\xd9\ +\x00\x00\x15\x02\x00\x01\x00\x00\x00\x01\x00\x05\x9dB\ +\x00\x00\x01z\x88\x90@\xac\ +\x00\x00\x14\x10\x00\x00\x00\x00\x00\x01\x00\x05\x96\x03\ +\x00\x00\x01z\x88\x90A\xb9\ +\x00\x00\x15 \x00\x00\x00\x00\x00\x01\x00\x05\x9d\xa2\ +\x00\x00\x01z\x88\x90A\xd6\ +\x00\x00\x16<\x00\x00\x00\x00\x00\x01\x00\x05\xa9<\ +\x00\x00\x01z\x88\x90A\xe3\ +\x00\x00\x15D\x00\x00\x00\x00\x00\x01\x00\x05\x9e\xec\ +\x00\x00\x01z\x88\x90@\xf3\ +\x00\x00\x15b\x00\x00\x00\x00\x00\x01\x00\x05\xa06\ +\x00\x00\x01z\x88\x90@\xf4\ +\x00\x00\x15\x80\x00\x00\x00\x00\x00\x01\x00\x05\xa1\x80\ +\x00\x00\x01z\x88\x90@\xf5\ +\x00\x00\x15\xbc\x00\x00\x00\x00\x00\x01\x00\x05\xa4\x14\ +\x00\x00\x01z\x88\x90@\xf6\ +\x00\x00\x16\x00\x00\x00\x00\x00\x00\x01\x00\x05\xa6\xa8\ +\x00\x00\x01z\x88\x90@\xf7\ +\x00\x00\x12b\x00\x01\x00\x00\x00\x01\x00\x05\x8a\xd4\ +\x00\x00\x01z\x88\x90Ag\ +\x00\x00\x16\x98\x00\x00\x00\x00\x00\x01\x00\x05\xaa\xe0\ +\x00\x00\x01z\x88\x90A\xdb\ +\x00\x00\x03\xa8\x00\x02\x00\x00\x00\x08\x00\x00\x00S\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00%@\x00\x00\x00\x00\x00\x01\x00\x06B\x8d\ +\x00\x00\x01z\x88\x90B\x0a\ +\x00\x00$P\x00\x00\x00\x00\x00\x01\x00\x06.w\ +\x00\x00\x01z\x88\x90B\x06\ +\x00\x00$\xb2\x00\x00\x00\x00\x00\x01\x00\x066@\ +\x00\x00\x01z\x88\x90B\x07\ +\x00\x00%\x18\x00\x00\x00\x00\x00\x01\x00\x06>\x0b\ +\x00\x00\x01z\x88\x90@\xb2\ +\x00\x00$\x8e\x00\x00\x00\x00\x00\x01\x00\x061\xbe\ +\x00\x00\x01z\x88\x90@\xb4\ +\x00\x00#\xec\x00\x00\x00\x00\x00\x01\x00\x06&\xb2\ +\x00\x00\x01z\x88\x90@\xb4\ +\x00\x00$\xf2\x00\x00\x00\x00\x00\x01\x00\x069\x89\ +\x00\x00\x01z\x88\x90@\xb6\ +\x00\x00$\x12\x00\x00\x00\x00\x00\x01\x00\x06+4\ +\x00\x00\x01z\x88\x90B\x09\ +\x00\x00\x17b\x00\x02\x00\x00\x009\x00\x00\x00\x5c\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00 \xe2\x00\x00\x00\x00\x00\x01\x00\x06\x09\x92\ +\x00\x00\x01z\x88\x90<\xef\ +\x00\x00#\xb6\x00\x00\x00\x00\x00\x01\x00\x06!\xc5\ +\x00\x00\x01z\x88\x90<\xec\ +\x00\x00\x1fZ\x00\x00\x00\x00\x00\x01\x00\x05\xfaT\ +\x00\x00\x01z\x88\x90<\xf0\ +\x00\x00\x19\xb0\x00\x00\x00\x00\x00\x01\x00\x05\xc6\xbb\ +\x00\x00\x01z\x88\x90<\xeb\ +\x00\x00\x22d\x00\x00\x00\x00\x00\x01\x00\x06\x17\x91\ +\x00\x00\x01z\x88\x90<\xed\ +\x00\x00\x17\xe8\x00\x00\x00\x00\x00\x01\x00\x05\xb5{\ +\x00\x00\x01z\x88\x90<\xe3\ +\x00\x00\x1aV\x00\x00\x00\x00\x00\x01\x00\x05\xca\x8a\ +\x00\x00\x01z\x88\x90<\xe0\ +\x00\x00#\x0a\x00\x00\x00\x00\x00\x01\x00\x06\x1b\xf7\ +\x00\x00\x01z\x88\x90<\xe4\ +\x00\x00\x1c\x86\x00\x00\x00\x00\x00\x01\x00\x05\xddK\ +\x00\x00\x01z\x88\x90<\xde\ +\x00\x00\x18\xd4\x00\x00\x00\x00\x00\x01\x00\x05\xbc\xc0\ +\x00\x00\x01z\x88\x90<\xe2\ +\x00\x00\x1b~\x00\x00\x00\x00\x00\x01\x00\x05\xd2]\ +\x00\x00\x01z\x88\x90<\xdf\ +\x00\x00\x1e\xe4\x00\x00\x00\x00\x00\x01\x00\x05\xf4\x13\ +\x00\x00\x01z\x88\x90<\xe8\ +\x00\x00!\x88\x00\x00\x00\x00\x00\x01\x00\x06\x0d\xcb\ +\x00\x00\x01z\x88\x90<\xe5\ +\x00\x00\x1db\x00\x00\x00\x00\x00\x01\x00\x05\xe7\xe0\ +\x00\x00\x01z\x88\x90<\xe9\ +\x00\x00 6\x00\x00\x00\x00\x00\x01\x00\x06\x04\x88\ +\x00\x00\x01z\x88\x90<\xe7\ +\x00\x00\x1c\xfc\x00\x00\x00\x00\x00\x01\x00\x05\xe3 \ +\x00\x00\x01z\x88\x90<\xd4\ +\x00\x00\x19\x0a\x00\x00\x00\x00\x00\x01\x00\x05\xbd\xb2\ +\x00\x00\x01z\x88\x90<\xd7\ +\x00\x00\x1f\x90\x00\x00\x00\x00\x00\x01\x00\x05\xfc\x01\ +\x00\x00\x01z\x88\x90<\xd2\ +\x00\x00\x1b\xb4\x00\x00\x00\x00\x00\x01\x00\x05\xd3\xab\ +\x00\x00\x01z\x88\x90<\xd6\ +\x00\x00\x1e>\x00\x00\x00\x00\x00\x01\x00\x05\xee\xb1\ +\x00\x00\x01z\x88\x90<\xd3\ +\x00\x00!\xbe\x00\x00\x00\x00\x00\x01\x00\x06\x0f\x89\ +\x00\x00\x01z\x88\x90<\xdb\ +\x00\x00\x18\x1e\x00\x00\x00\x00\x00\x01\x00\x05\xb7\x9d\ +\x00\x00\x01z\x88\x90<\xd8\ +\x00\x00 l\x00\x00\x00\x00\x00\x01\x00\x06\x06\x98\ +\x00\x00\x01z\x88\x90<\xdc\ +\x00\x00#@\x00\x00\x00\x00\x00\x01\x00\x06\x1d\xf7\ +\x00\x00\x01z\x88\x90<\xd9\ +\x00\x00\x1a\x8c\x00\x00\x00\x00\x00\x01\x00\x05\xcb\xa9\ +\x00\x00\x01z\x88\x90=\x06\ +\x00\x00\x1d\xbe\x00\x00\x00\x00\x00\x01\x00\x05\xeb\x81\ +\x00\x00\x01z\x88\x90=\x07\ +\x00\x00\x1c\x16\x00\x00\x00\x00\x00\x01\x00\x05\xd8\xc7\ +\x00\x00\x01z\x88\x90=\x08\ +\x00\x00\x1b\x0e\x00\x00\x00\x00\x00\x01\x00\x05\xcf\x06\ +\x00\x00\x01z\x88\x90=\x0a\ +\x00\x00\x19\xe6\x00\x00\x00\x00\x00\x01\x00\x05\xc7\x8d\ +\x00\x00\x01z\x88\x90=\x0b\ +\x00\x00\x18\x94\x00\x00\x00\x00\x00\x01\x00\x05\xba\x90\ +\x00\x00\x01z\x88\x90=\x0c\ +\x00\x00\x17x\x00\x00\x00\x00\x00\x01\x00\x05\xb2\xb7\ +\x00\x00\x01z\x88\x90=\x0e\ +\x00\x00\x22\x9a\x00\x00\x00\x00\x00\x01\x00\x06\x18\xe4\ +\x00\x00\x01z\x88\x90=\x0f\ +\x00\x00!\x18\x00\x00\x00\x00\x00\x01\x00\x06\x0a\x99\ +\x00\x00\x01z\x88\x90=\x10\ +\x00\x00\x1f\xc6\x00\x00\x00\x00\x00\x01\x00\x05\xfd\x09\ +\x00\x00\x01z\x88\x90=\x12\ +\x00\x00\x1et\x00\x00\x00\x00\x00\x01\x00\x05\xef\xbf\ +\x00\x00\x01z\x88\x90=\x13\ +\x00\x00\x1a\xce\x00\x00\x00\x00\x00\x01\x00\x05\xcd|\ +\x00\x00\x01z\x88\x90=\x15\ +\x00\x00\x19@\x00\x00\x00\x00\x00\x01\x00\x05\xbe\xeb\ +\x00\x00\x01z\x88\x90=\x16\ +\x00\x00\x18T\x00\x00\x00\x00\x00\x01\x00\x05\xb9\x11\ +\x00\x00\x01z\x88\x90=\x17\ +\x00\x00#v\x00\x00\x00\x00\x00\x01\x00\x06\x1f\xb3\ +\x00\x00\x01z\x88\x90=\x19\ +\x00\x00\x22$\x00\x00\x00\x00\x00\x01\x00\x06\x16%\ +\x00\x00\x01z\x88\x90=\x1a\ +\x00\x00 \xa2\x00\x00\x00\x00\x00\x01\x00\x06\x08\x19\ +\x00\x00\x01z\x88\x90=\x1b\ +\x00\x00\x1f\x1a\x00\x00\x00\x00\x00\x01\x00\x05\xf5t\ +\x00\x00\x01z\x88\x90=\x1d\ +\x00\x00\x1d\xfe\x00\x00\x00\x00\x00\x01\x00\x05\xedU\ +\x00\x00\x01z\x88\x90=\x1e\ +\x00\x00\x1c\xbc\x00\x00\x00\x00\x00\x01\x00\x05\xe1\xc7\ +\x00\x00\x01z\x88\x90=\x1f\ +\x00\x00\x1b\xea\x00\x00\x00\x00\x00\x01\x00\x05\xd5\xc4\ +\x00\x00\x01z\x88\x90<\xf6\ +\x00\x00\x1e\xb4\x00\x00\x00\x00\x00\x01\x00\x05\xf1A\ +\x00\x00\x01z\x88\x90=\x02\ +\x00\x00!X\x00\x00\x00\x00\x00\x01\x00\x06\x0b\xc6\ +\x00\x00\x01z\x88\x90<\xff\ +\x00\x00\x1d2\x00\x00\x00\x00\x00\x01\x00\x05\xe5\x1d\ +\x00\x00\x01z\x88\x90=\x03\ +\x00\x00\x17\xb8\x00\x00\x00\x00\x00\x01\x00\x05\xb4v\ +\x00\x00\x01z\x88\x90<\xfc\ +\x00\x00 \x06\x00\x00\x00\x00\x00\x01\x00\x06\x03*\ +\x00\x00\x01z\x88\x90=\x00\ +\x00\x00\x1a&\x00\x00\x00\x00\x00\x01\x00\x05\xc9\x0e\ +\x00\x00\x01z\x88\x90<\xfb\ +\x00\x00\x22\xda\x00\x00\x00\x00\x00\x01\x00\x06\x1a\x17\ +\x00\x00\x01z\x88\x90<\xfe\ +\x00\x00\x1cV\x00\x00\x00\x00\x00\x01\x00\x05\xda\xb6\ +\x00\x00\x01z\x88\x90<\xf8\ +\x00\x00!\xf4\x00\x00\x00\x00\x00\x01\x00\x06\x11E\ +\x00\x00\x01z\x88\x90<\xfb\ +\x00\x00\x1bN\x00\x00\x00\x00\x00\x01\x00\x05\xd0\xd0\ +\x00\x00\x01z\x88\x90<\xf9\ +\x00\x00\x19\x80\x00\x00\x00\x00\x00\x01\x00\x05\xc0C\ +\x00\x00\x01z\x88\x90=\x05\ +\x00\x00\x1d\x98\x00\x00\x00\x00\x00\x01\x00\x05\xea!\ +\x00\x00\x01z\x88\x90<\xcf\ +\x00\x00\x0f,\x00\x00\x00\x00\x00\x01\x00\x04:\x97\ +\x00\x00\x01z\x88\x90B;\ +\x00\x00\x0d|\x00\x00\x00\x00\x00\x01\x00\x03\xa4:\ +\x00\x00\x01z\x88\x90@\x8d\ +\x00\x00\x0e\xf2\x00\x00\x00\x00\x00\x01\x00\x045\x8a\ +\x00\x00\x01z\x88\x90A\x9c\ +\x00\x00\x0d\xf0\x00\x00\x00\x00\x00\x01\x00\x04\x07,\ +\x00\x00\x01z\x88\x90@a\ +\x00\x00\x0ah\x00\x00\x00\x00\x00\x01\x00\x03E?\ +\x00\x00\x01z\x88\x90B8\ +\x00\x00\x09\xd8\x00\x01\x00\x00\x00\x01\x00\x02|Z\ +\x00\x00\x01z\x88\x90@m\ +\x00\x00\x07\x84\x00\x00\x00\x00\x00\x01\x00\x01\x9b\x8b\ +\x00\x00\x01z\x88\x90@b\ +\x00\x00\x08\xac\x00\x00\x00\x00\x00\x01\x00\x01\xb6{\ +\x00\x00\x01z\x88\x90A\xa0\ +\x00\x00\x0f\x96\x00\x00\x00\x00\x00\x01\x00\x04|\x91\ +\x00\x00\x01z\x88\x90@i\ +\x00\x00\x0e\x82\x00\x00\x00\x00\x00\x01\x00\x04(>\ +\x00\x00\x01z\x88\x90@\x94\ +\x00\x00\x09D\x00\x00\x00\x00\x00\x01\x00\x02q\xb7\ +\x00\x00\x01z\x88\x90@\x87\ +\x00\x00\x0e\xbe\x00\x00\x00\x00\x00\x01\x00\x040i\ +\x00\x00\x01z\x88\x90A\x9d\ +\x00\x00\x09\x9c\x00\x00\x00\x00\x00\x01\x00\x02y\xc6\ +\x00\x00\x01z\x88\x90A\x9b\ +\x00\x00\x0c\x92\x00\x00\x00\x00\x00\x01\x00\x03\x88\x0e\ +\x00\x00\x01z\x88\x90@w\ +\x00\x00\x07\xec\x00\x00\x00\x00\x00\x01\x00\x01\xa9\xae\ +\x00\x00\x01z\x88\x90@\x90\ +\x00\x00\x08\xea\x00\x00\x00\x00\x00\x01\x00\x01\xd2!\ +\x00\x00\x01z\x88\x90@\x80\ +\x00\x00\x10\x0e\x00\x00\x00\x00\x00\x01\x00\x04\x99\x8e\ +\x00\x00\x01z\x88\x90B:\ +\x00\x00\x08\xc6\x00\x00\x00\x00\x00\x01\x00\x01\xbcy\ +\x00\x00\x01z\x88\x90@g\ +\x00\x00\x0c\xd4\x00\x00\x00\x00\x00\x01\x00\x03\x949\ +\x00\x00\x01z\x88\x90@\x8c\ +\x00\x00\x07\xb4\x00\x00\x00\x00\x00\x01\x00\x01\xa0%\ +\x00\x00\x01z\x88\x90B9\ +\x00\x00\x09j\x00\x00\x00\x00\x00\x01\x00\x02u[\ +\x00\x00\x01z\x88\x90@b\ +\x00\x00\x0b2\x00\x00\x00\x00\x00\x01\x00\x03a\xfa\ +\x00\x00\x01z\x88\x90@\x89\ +\x00\x00\x0a:\x00\x01\x00\x00\x00\x01\x00\x03%L\ +\x00\x00\x01z\x88\x90@o\ +\x00\x00\x07\x04\x00\x00\x00\x00\x00\x01\x00\x01\x90\xa8\ +\x00\x00\x01z\x88\x90@`\ +\x00\x00\x0bj\x00\x00\x00\x00\x00\x01\x00\x03e\xa2\ +\x00\x00\x01z\x88\x90@\x8c\ +\x00\x00\x0e\x0a\x00\x00\x00\x00\x00\x01\x00\x04\x0a\xc0\ +\x00\x00\x01z\x88\x90@\x8d\ +\x00\x00\x0c\xae\x00\x00\x00\x00\x00\x01\x00\x03\x8f%\ +\x00\x00\x01z\x88\x90@\x8f\ +\x00\x00\x0b\xcc\x00\x00\x00\x00\x00\x01\x00\x03j*\ +\x00\x00\x01z\x88\x90@\x8a\ +\x00\x00\x0b\x06\x00\x00\x00\x00\x00\x01\x00\x03L*\ +\x00\x00\x01z\x88\x90@{\ +\x00\x00\x0fr\x00\x00\x00\x00\x00\x01\x00\x04s,\ +\x00\x00\x01z\x88\x90B<\ +\x00\x00\x0f\xc0\x00\x00\x00\x00\x00\x01\x00\x04\x91Y\ +\x00\x00\x01z\x88\x90@\x93\ +\x00\x00\x0d\xb6\x00\x00\x00\x00\x00\x01\x00\x03\xa7\xbc\ +\x00\x00\x01z\x88\x90@z\ +\x00\x00\x0a\xa2\x00\x00\x00\x00\x00\x01\x00\x03G\xd3\ +\x00\x00\x01z\x88\x90@\x8b\ +\x00\x00\x06\xa2\x00\x00\x00\x00\x00\x01\x00\x01.\x89\ +\x00\x00\x01z\x88\x90@x\ +\x00\x00\x0cT\x00\x00\x00\x00\x00\x01\x00\x03\x83\xa5\ +\x00\x00\x01z\x88\x90@\x88\ +\x00\x00\x07b\x00\x00\x00\x00\x00\x01\x00\x01\x98_\ +\x00\x00\x01z\x88\x90A\x8b\ +\x00\x00\x08*\x00\x00\x00\x00\x00\x01\x00\x01\xae\xc7\ +\x00\x00\x01z\x88\x90B7\ +\x00\x00\x10@\x00\x00\x00\x00\x00\x01\x00\x04\xa3&\ +\x00\x00\x01z\x88\x90@_\ +\x00\x00\x0fB\x00\x01\x00\x00\x00\x01\x00\x04A\xf9\ +\x00\x00\x01z\x88\x90@l\ +\x00\x00\x06\xd0\x00\x00\x00\x00\x00\x01\x00\x01\x8e\x11\ +\x00\x00\x01z\x88\x90A\x9b\ +\x00\x00\x0a&\x00\x00\x00\x00\x00\x01\x00\x03\x1f\xd5\ +\x00\x00\x01z\x88\x90@e\ +\x00\x00\x10j\x00\x00\x00\x00\x00\x01\x00\x04\xa5\xd7\ +\x00\x00\x01z\x88\x90@~\ +\x00\x00\x09\xf8\x00\x00\x00\x00\x00\x01\x00\x02\x9f\xc9\ +\x00\x00\x01z\x88\x90@k\ +\x00\x00\x0eV\x00\x01\x00\x00\x00\x01\x00\x04\x0eB\ +\x00\x00\x01z\x88\x90@p\ +\x00\x00\x0d^\x00\x00\x00\x00\x00\x01\x00\x03\x9di\ +\x00\x00\x01z\x88\x90B.\ +\x00\x00\x0c\x1c\x00\x00\x00\x00\x00\x01\x00\x03n\x97\ +\x00\x00\x01z\x88\x90@|\ +\x00\x00\x07*\x00\x00\x00\x00\x00\x01\x00\x01\x93G\ +\x00\x00\x01z\x88\x90@\x91\ +\x00\x00\x0d\x22\x00\x00\x00\x00\x00\x01\x00\x03\x98\xd3\ +\x00\x00\x01z\x88\x90@\x8f\ +\x00\x00\x08\x5c\x00\x00\x00\x00\x00\x01\x00\x01\xb1^\ +\x00\x00\x01z\x88\x90@\x92\ +\x00\x00\x09&\x00\x00\x00\x00\x00\x01\x00\x02\x5c\x1d\ +\x00\x00\x01z\x88\x90@f\ +\x00\x00\x11\xae\x00\x00\x00\x00\x00\x01\x00\x05X\xbf\ +\x00\x00\x01z\x88\x90@u\ +\x00\x00\x120\x00\x00\x00\x00\x00\x01\x00\x05\x83^\ +\x00\x00\x01z\x88\x90@q\ +\x00\x00\x11\x06\x00\x00\x00\x00\x00\x01\x00\x05L\x08\ +\x00\x00\x01z\x88\x90@W\ +\x00\x00\x12\x0a\x00\x00\x00\x00\x00\x01\x00\x05q%\ +\x00\x00\x01z\x88\x90@d\ +\x00\x00\x12H\x00\x00\x00\x00\x00\x01\x00\x05\x87p\ +\x00\x00\x01z\x88\x90@r\ +\x00\x00\x11<\x00\x00\x00\x00\x00\x01\x00\x05Q\xce\ +\x00\x00\x01z\x88\x90@\x82\ +\x00\x00\x10\xa8\x00\x00\x00\x00\x00\x01\x00\x053\xe7\ +\x00\x00\x01z\x88\x90@\x83\ +\x00\x00\x11\xc8\x00\x00\x00\x00\x00\x01\x00\x05^\xc1\ +\x00\x00\x01z\x88\x90@\x85\ +\x00\x00\x11\x84\x00\x00\x00\x00\x00\x01\x00\x05W\xf1\ +\x00\x00\x01z\x88\x90@\x86\ +\x00\x00\x10\xd2\x00\x00\x00\x00\x00\x01\x00\x054t\ +\x00\x00\x01z\x88\x90@s\ +\x00\x00\x11\xf2\x00\x00\x00\x00\x00\x01\x00\x05_e\ +\x00\x00\x01z\x88\x90@^\ +\x00\x00\x10\xec\x00\x00\x00\x00\x00\x01\x00\x05BU\ +\x00\x00\x01z\x88\x90@X\ +\x00\x00\x11f\x00\x00\x00\x00\x00\x01\x00\x05R}\ +\x00\x00\x01z\x88\x90@\x98\ +" + +def qInitResources(): + QtCore.qRegisterResourceData(0x03, qt_resource_struct, qt_resource_name, qt_resource_data) + +def qCleanupResources(): + QtCore.qUnregisterResourceData(0x03, qt_resource_struct, qt_resource_name, qt_resource_data) + +qInitResources() diff --git a/Gems/AWSCore/Code/Tools/ResourceMappingTool/tests/unit/controller/test_error_controller.py b/Gems/AWSCore/Code/Tools/ResourceMappingTool/tests/unit/controller/test_error_controller.py new file mode 100644 index 0000000000..e6271a5a75 --- /dev/null +++ b/Gems/AWSCore/Code/Tools/ResourceMappingTool/tests/unit/controller/test_error_controller.py @@ -0,0 +1,29 @@ +""" +Copyright (c) Contributors to the Open 3D Engine Project. +For complete copyright and license terms please see the LICENSE at the root of this distribution. + +SPDX-License-Identifier: Apache-2.0 OR MIT +""" + +from unittest import TestCase +from unittest.mock import (call, MagicMock, patch) + +from controller.error_controller import ErrorController + +class TestErrorController(TestCase): + """ + ErrorController unit test cases + """ + def setUp(self) -> None: + view_manager_patcher: patch = patch("controller.error_controller.ViewManager") + self.addCleanup(view_manager_patcher.stop) + self._mock_view_manager: MagicMock = view_manager_patcher.start() + + self._mocked_view_manager: MagicMock = self._mock_view_manager.get_instance.return_value + self._mocked_error_page: MagicMock = self._mocked_view_manager.get_error_page.return_value + + self._test_error_controller: ErrorController = ErrorController() + self._test_error_controller.setup() + + def test_setup_with_expected_behavior_connected(self) -> None: + self._mocked_error_page.ok_button.clicked.connect.assert_called_once_with(self._test_error_controller._ok) diff --git a/Gems/AWSCore/Code/Tools/ResourceMappingTool/tests/unit/controller/test_view_edit_controller.py b/Gems/AWSCore/Code/Tools/ResourceMappingTool/tests/unit/controller/test_view_edit_controller.py index f854d2cd68..c73bddcd9c 100755 --- a/Gems/AWSCore/Code/Tools/ResourceMappingTool/tests/unit/controller/test_view_edit_controller.py +++ b/Gems/AWSCore/Code/Tools/ResourceMappingTool/tests/unit/controller/test_view_edit_controller.py @@ -22,6 +22,8 @@ class TestViewEditController(TestCase): TODO: add test cases once error handling is ready """ _expected_account_id: str = "1234567890" + _expected_account_id_attribute_name = "AccountId" + _expected_account_id_template_vale: str = "EMPTY" _expected_region: str = "aws-global" _expected_config_directory: str = "dummy/directory/" _expected_config_file_name: str = "dummy.json" @@ -98,8 +100,6 @@ class TestViewEditController(TestCase): self._test_view_edit_controller._filter_based_on_search_text) self._mocked_view_edit_page.cancel_button.clicked.connect.assert_called_once_with( self._test_view_edit_controller._cancel) - self._mocked_view_edit_page.create_new_button.clicked.connect.assert_called_once_with( - self._test_view_edit_controller._create_new_config_file) self._mocked_view_edit_page.rescan_button.clicked.connect.assert_called_once_with( self._test_view_edit_controller._rescan_config_directory) @@ -301,6 +301,7 @@ class TestViewEditController(TestCase): expected_new_config_directory, constants.RESOURCE_MAPPING_CONFIG_FILE_NAME_SUFFIX) assert self._mocked_configuration_manager.configuration.config_files == [] self._mocked_view_edit_page.set_config_files.assert_called_with([]) + self._mocked_view_edit_page.set_config_location.assert_called_with(expected_new_config_directory) self._test_view_edit_controller.set_notification_page_frame_text_sender.emit.assert_called_once_with( notification_label_text.NOTIFICATION_LOADING_MESSAGE) @@ -418,13 +419,18 @@ class TestViewEditController(TestCase): self, mock_json_utils: MagicMock, mock_file_utils: MagicMock) -> None: self._mocked_view_edit_page.config_file_combobox.currentText.return_value = \ TestViewEditController._expected_config_file_name - expected_json_dict: Dict[str, any] = {"dummyKey": "dummyValue"} + expected_json_dict: Dict[str, any] = { + "dummyKey": "dummyValue", + self._expected_account_id_attribute_name: self._expected_account_id_template_vale} + mock_json_utils.RESOURCE_MAPPING_ACCOUNTID_JSON_KEY_NAME = self._expected_account_id_attribute_name + mock_json_utils.RESOURCE_MAPPING_ACCOUNTID_TEMPLATE_VALUE = self._expected_account_id_template_vale mock_json_utils.validate_resources_according_to_json_schema.return_value = [] mock_json_utils.convert_resources_to_json_dict.return_value = expected_json_dict mock_file_utils.join_path.return_value = TestViewEditController._expected_config_file_full_path mocked_call_args: call = self._mocked_view_edit_page.save_changes_button.clicked.connect.call_args[0] mocked_call_args[0]() # triggering save_changes_button connected function + assert expected_json_dict["AccountId"] == self._mocked_configuration_manager.configuration.account_id mock_json_utils.convert_resources_to_json_dict.assert_called_once() mock_json_utils.write_into_json_file.assert_called_once_with( TestViewEditController._expected_config_file_full_path, expected_json_dict) @@ -468,37 +474,6 @@ class TestViewEditController(TestCase): mocked_call_args[0]() # triggering cancel_button connected function mock_application.instance.return_value.quit.assert_called_once() - @patch("controller.view_edit_controller.file_utils") - @patch("controller.view_edit_controller.json_utils") - def test_page_create_new_button_invoke_view_edit_page_set_config_files_with_expected_config_files( - self, mock_json_utils: MagicMock, mock_file_utils: MagicMock) -> None: - expected_config_files: List[str] = ["dummyfile"] - mock_file_utils.find_files_with_suffix_under_directory.return_value = expected_config_files - mocked_call_args: call = \ - self._mocked_view_edit_page.create_new_button.clicked.connect.call_args[0] - - mocked_call_args[0]() # triggering create_new_button connected function - mock_file_utils.join_path.assert_called_once() - mock_json_utils.create_empty_resource_mapping_file.assert_called_once() - mock_file_utils.find_files_with_suffix_under_directory.assert_called_once() - self._mocked_view_edit_page.set_config_files.assert_called_with(expected_config_files) - self._test_view_edit_controller.set_notification_frame_text_sender.emit.assert_called_once() - - @patch("controller.view_edit_controller.file_utils") - @patch("controller.view_edit_controller.json_utils") - def test_page_create_new_button_post_notification_when_create_file_throw_exception( - self, mock_json_utils: MagicMock, mock_file_utils: MagicMock) -> None: - expected_config_files: List[str] = ["dummyfile"] - mock_json_utils.create_empty_resource_mapping_file.side_effect = IOError("dummy IO error") - mocked_call_args: call = \ - self._mocked_view_edit_page.create_new_button.clicked.connect.call_args[0] - - mocked_call_args[0]() # triggering create_new_button connected function - mock_file_utils.join_path.assert_called_once() - mock_json_utils.create_empty_resource_mapping_file.assert_called_once() - mock_file_utils.find_files_with_suffix_under_directory.assert_not_called() - assert len(self._test_view_edit_controller.set_notification_frame_text_sender.emit.mock_calls) == 2 - @patch("controller.view_edit_controller.file_utils") def test_page_rescan_button_post_notification_when_find_files_throw_exception( self, mock_file_utils: MagicMock) -> None: diff --git a/Gems/AWSCore/Code/Tools/ResourceMappingTool/tests/unit/utils/test_json_utils.py b/Gems/AWSCore/Code/Tools/ResourceMappingTool/tests/unit/utils/test_json_utils.py index cadcca6ee6..7eb92ff222 100755 --- a/Gems/AWSCore/Code/Tools/ResourceMappingTool/tests/unit/utils/test_json_utils.py +++ b/Gems/AWSCore/Code/Tools/ResourceMappingTool/tests/unit/utils/test_json_utils.py @@ -43,7 +43,7 @@ class TestJsonUtils(TestCase): json_utils._RESOURCE_MAPPING_TYPE_JSON_KEY_NAME: _expected_bucket_type, json_utils._RESOURCE_MAPPING_NAMEID_JSON_KEY_NAME: _expected_bucket_name }}, - json_utils._RESOURCE_MAPPING_ACCOUNTID_JSON_KEY_NAME: _expected_account_id, + json_utils.RESOURCE_MAPPING_ACCOUNTID_JSON_KEY_NAME: _expected_account_id, json_utils._RESOURCE_MAPPING_REGION_JSON_KEY_NAME: _expected_region, json_utils._RESOURCE_MAPPING_VERSION_JSON_KEY_NAME: json_utils._RESOURCE_MAPPING_JSON_FORMAT_VERSION } @@ -64,7 +64,7 @@ class TestJsonUtils(TestCase): def test_convert_resources_to_json_dict_return_expected_json_dict(self) -> None: old_json_dict: Dict[str, any] = { - json_utils._RESOURCE_MAPPING_ACCOUNTID_JSON_KEY_NAME: TestJsonUtils._expected_account_id, + json_utils.RESOURCE_MAPPING_ACCOUNTID_JSON_KEY_NAME: TestJsonUtils._expected_account_id, json_utils._RESOURCE_MAPPING_REGION_JSON_KEY_NAME: TestJsonUtils._expected_region } actual_json_dict: Dict[str, any] = \ @@ -76,20 +76,6 @@ class TestJsonUtils(TestCase): json_utils.convert_json_dict_to_resources(TestJsonUtils._expected_json_dict) assert actual_resources == [TestJsonUtils._expected_bucket_resource_mapping] - def test_create_empty_resource_mapping_file_succeed(self) -> None: - mocked_open: MagicMock = MagicMock() - self._mock_open.return_value.__enter__.return_value = mocked_open - expected_json_dict: Dict[str, any] = \ - {json_utils._RESOURCE_MAPPING_JSON_KEY_NAME: {}, - json_utils._RESOURCE_MAPPING_ACCOUNTID_JSON_KEY_NAME: TestJsonUtils._expected_account_id, - json_utils._RESOURCE_MAPPING_REGION_JSON_KEY_NAME: TestJsonUtils._expected_region, - json_utils._RESOURCE_MAPPING_VERSION_JSON_KEY_NAME: json_utils._RESOURCE_MAPPING_JSON_FORMAT_VERSION} - json_utils.create_empty_resource_mapping_file(TestJsonUtils._expected_file_name, - TestJsonUtils._expected_account_id, - TestJsonUtils._expected_region) - self._mock_open.assert_called_once_with(TestJsonUtils._expected_file_name, "w") - self._mock_json_dump.assert_called_once_with(expected_json_dict, mocked_open, indent=4, sort_keys=True) - def test_read_from_json_file_return_expected_json_dict(self) -> None: mocked_open: MagicMock = MagicMock() self._mock_open.return_value.__enter__.return_value = mocked_open @@ -114,12 +100,18 @@ class TestJsonUtils(TestCase): def test_validate_json_dict_according_to_json_schema_raise_error_when_json_dict_has_no_accountid(self) -> None: invalid_json_dict: Dict[str, any] = copy.deepcopy(TestJsonUtils._expected_json_dict) - invalid_json_dict.pop(json_utils._RESOURCE_MAPPING_ACCOUNTID_JSON_KEY_NAME) + invalid_json_dict.pop(json_utils.RESOURCE_MAPPING_ACCOUNTID_JSON_KEY_NAME) self.assertRaises(KeyError, json_utils.validate_json_dict_according_to_json_schema, invalid_json_dict) + def test_validate_json_dict_according_to_json_schema_pass_when_json_dict_has_template_accountid(self) -> None: + valid_json_dict: Dict[str, any] = copy.deepcopy(TestJsonUtils._expected_json_dict) + valid_json_dict[json_utils.RESOURCE_MAPPING_ACCOUNTID_JSON_KEY_NAME] = \ + json_utils.RESOURCE_MAPPING_ACCOUNTID_TEMPLATE_VALUE + json_utils.validate_json_dict_according_to_json_schema(valid_json_dict) + def test_validate_json_dict_according_to_json_schema_raise_error_when_json_dict_has_invalid_accountid(self) -> None: invalid_json_dict: Dict[str, any] = copy.deepcopy(TestJsonUtils._expected_json_dict) - invalid_json_dict[json_utils._RESOURCE_MAPPING_ACCOUNTID_JSON_KEY_NAME] = \ + invalid_json_dict[json_utils.RESOURCE_MAPPING_ACCOUNTID_JSON_KEY_NAME] = \ TestJsonUtils._expected_invalid_account_id self.assertRaises(ValueError, json_utils.validate_json_dict_according_to_json_schema, invalid_json_dict) diff --git a/Gems/AWSCore/Code/Tools/ResourceMappingTool/utils/json_utils.py b/Gems/AWSCore/Code/Tools/ResourceMappingTool/utils/json_utils.py index 10f7c8ed33..5b9377ada3 100755 --- a/Gems/AWSCore/Code/Tools/ResourceMappingTool/utils/json_utils.py +++ b/Gems/AWSCore/Code/Tools/ResourceMappingTool/utils/json_utils.py @@ -22,16 +22,16 @@ logger = logging.getLogger(__name__) _RESOURCE_MAPPING_JSON_KEY_NAME: str = "AWSResourceMappings" _RESOURCE_MAPPING_TYPE_JSON_KEY_NAME: str = "Type" _RESOURCE_MAPPING_NAMEID_JSON_KEY_NAME: str = "Name/ID" -_RESOURCE_MAPPING_ACCOUNTID_JSON_KEY_NAME: str = "AccountId" _RESOURCE_MAPPING_REGION_JSON_KEY_NAME: str = "Region" _RESOURCE_MAPPING_VERSION_JSON_KEY_NAME: str = "Version" _RESOURCE_MAPPING_JSON_FORMAT_VERSION: str = "1.0.0" -_RESOURCE_MAPPING_ACCOUNTID_PATTERN: str = "^[0-9]{12}$" +RESOURCE_MAPPING_ACCOUNTID_JSON_KEY_NAME: str = "AccountId" +RESOURCE_MAPPING_ACCOUNTID_TEMPLATE_VALUE: str = "EMPTY" +_RESOURCE_MAPPING_ACCOUNTID_PATTERN: str = f"^[0-9]{{12}}|{RESOURCE_MAPPING_ACCOUNTID_TEMPLATE_VALUE}$" _RESOURCE_MAPPING_REGION_PATTERN: str = "^[a-z]{2}-[a-z]{4,9}-[0-9]{1}$" _RESOURCE_MAPPING_VERSION_PATTERN: str = "^[0-9]{1}.[0-9]{1}.[0-9]{1}$" - def _add_validation_error_message(errors: Dict[int, List[str]], row: int, error_message: str) -> None: if row in errors.keys(): errors[row].append(error_message) @@ -64,9 +64,9 @@ def _validate_required_key_in_json_dict(json_dict: Dict[str, any], json_dict_nam def convert_resources_to_json_dict(resources: List[ResourceMappingAttributes], old_json_dict: Dict[str, any]) -> Dict[str, any]: - default_account_id: str = old_json_dict[_RESOURCE_MAPPING_ACCOUNTID_JSON_KEY_NAME] + default_account_id: str = old_json_dict[RESOURCE_MAPPING_ACCOUNTID_JSON_KEY_NAME] default_region: str = old_json_dict[_RESOURCE_MAPPING_REGION_JSON_KEY_NAME] - json_dict: Dict[str, any] = {_RESOURCE_MAPPING_ACCOUNTID_JSON_KEY_NAME: default_account_id, + json_dict: Dict[str, any] = {RESOURCE_MAPPING_ACCOUNTID_JSON_KEY_NAME: default_account_id, _RESOURCE_MAPPING_REGION_JSON_KEY_NAME: default_region, _RESOURCE_MAPPING_VERSION_JSON_KEY_NAME: _RESOURCE_MAPPING_JSON_FORMAT_VERSION, _RESOURCE_MAPPING_JSON_KEY_NAME: {}} @@ -76,7 +76,7 @@ def convert_resources_to_json_dict(resources: List[ResourceMappingAttributes], json_resource_attributes = {_RESOURCE_MAPPING_TYPE_JSON_KEY_NAME: resource.type, _RESOURCE_MAPPING_NAMEID_JSON_KEY_NAME: resource.name_id} if not resource.account_id == default_account_id: - json_resource_attributes[_RESOURCE_MAPPING_ACCOUNTID_JSON_KEY_NAME] = resource.account_id + json_resource_attributes[RESOURCE_MAPPING_ACCOUNTID_JSON_KEY_NAME] = resource.account_id if not resource.region == default_region: json_resource_attributes[_RESOURCE_MAPPING_REGION_JSON_KEY_NAME] = resource.region @@ -88,7 +88,7 @@ def convert_resources_to_json_dict(resources: List[ResourceMappingAttributes], def convert_json_dict_to_resources(json_dict: Dict[str, any]) -> List[ResourceMappingAttributes]: - default_account_id: str = json_dict[_RESOURCE_MAPPING_ACCOUNTID_JSON_KEY_NAME] + default_account_id: str = json_dict[RESOURCE_MAPPING_ACCOUNTID_JSON_KEY_NAME] default_region: str = json_dict[_RESOURCE_MAPPING_REGION_JSON_KEY_NAME] resources: List[ResourceMappingAttributes] = [] @@ -102,8 +102,8 @@ def convert_json_dict_to_resources(json_dict: Dict[str, any]) -> List[ResourceMa .build_type(resource_value[_RESOURCE_MAPPING_TYPE_JSON_KEY_NAME]) \ .build_name_id(resource_value[_RESOURCE_MAPPING_NAMEID_JSON_KEY_NAME]) - if _RESOURCE_MAPPING_ACCOUNTID_JSON_KEY_NAME in resource_value.keys(): - resource_builder.build_account_id(resource_value[_RESOURCE_MAPPING_ACCOUNTID_JSON_KEY_NAME]) + if RESOURCE_MAPPING_ACCOUNTID_JSON_KEY_NAME in resource_value.keys(): + resource_builder.build_account_id(resource_value[RESOURCE_MAPPING_ACCOUNTID_JSON_KEY_NAME]) else: resource_builder.build_account_id(default_account_id) @@ -119,14 +119,6 @@ def convert_json_dict_to_resources(json_dict: Dict[str, any]) -> List[ResourceMa return resources -def create_empty_resource_mapping_file(file_name: str, account_id: str, region: str) -> None: - json_dict: Dict[str, any] = {_RESOURCE_MAPPING_JSON_KEY_NAME: {}, - _RESOURCE_MAPPING_ACCOUNTID_JSON_KEY_NAME: account_id, - _RESOURCE_MAPPING_REGION_JSON_KEY_NAME: region, - _RESOURCE_MAPPING_VERSION_JSON_KEY_NAME: _RESOURCE_MAPPING_JSON_FORMAT_VERSION} - write_into_json_file(file_name, json_dict) - - def read_from_json_file(file_name: str) -> Dict[str, any]: try: json_dict: Dict[str, any] = {} @@ -179,7 +171,7 @@ def validate_resources_according_to_json_schema(resources: List[ResourceMappingA invalid_resources, row_count, error_messages.INVALID_FORMAT_UNEXPECTED_VALUE_IN_TABLE_ERROR_MESSAGE.format( resource.account_id, - _RESOURCE_MAPPING_ACCOUNTID_JSON_KEY_NAME, + RESOURCE_MAPPING_ACCOUNTID_JSON_KEY_NAME, _RESOURCE_MAPPING_ACCOUNTID_PATTERN)) if not re.match(_RESOURCE_MAPPING_REGION_PATTERN, resource.region): @@ -198,11 +190,11 @@ def validate_json_dict_according_to_json_schema(json_dict: Dict[str, any]) -> No _validate_required_key_in_json_dict(json_dict, "root", _RESOURCE_MAPPING_VERSION_JSON_KEY_NAME) _validate_required_key_in_json_dict(json_dict, "root", _RESOURCE_MAPPING_JSON_KEY_NAME) - _validate_required_key_in_json_dict(json_dict, "root", _RESOURCE_MAPPING_ACCOUNTID_JSON_KEY_NAME) - if not re.match(_RESOURCE_MAPPING_ACCOUNTID_PATTERN, json_dict[_RESOURCE_MAPPING_ACCOUNTID_JSON_KEY_NAME]): + _validate_required_key_in_json_dict(json_dict, "root", RESOURCE_MAPPING_ACCOUNTID_JSON_KEY_NAME) + if not re.match(_RESOURCE_MAPPING_ACCOUNTID_PATTERN, json_dict[RESOURCE_MAPPING_ACCOUNTID_JSON_KEY_NAME]): raise ValueError(error_messages.INVALID_FORMAT_UNEXPECTED_VALUE_IN_FILE_ERROR_MESSAGE.format( - json_dict[_RESOURCE_MAPPING_ACCOUNTID_JSON_KEY_NAME], - f"root/{_RESOURCE_MAPPING_ACCOUNTID_JSON_KEY_NAME}", + json_dict[RESOURCE_MAPPING_ACCOUNTID_JSON_KEY_NAME], + f"root/{RESOURCE_MAPPING_ACCOUNTID_JSON_KEY_NAME}", _RESOURCE_MAPPING_ACCOUNTID_PATTERN)) _validate_required_key_in_json_dict(json_dict, "root", _RESOURCE_MAPPING_REGION_JSON_KEY_NAME) diff --git a/Gems/AWSCore/Code/Tools/ResourceMappingTool/view/common_view_components.py b/Gems/AWSCore/Code/Tools/ResourceMappingTool/view/common_view_components.py index 7797905dd7..8a9fc1625d 100755 --- a/Gems/AWSCore/Code/Tools/ResourceMappingTool/view/common_view_components.py +++ b/Gems/AWSCore/Code/Tools/ResourceMappingTool/view/common_view_components.py @@ -8,7 +8,7 @@ SPDX-License-Identifier: Apache-2.0 OR MIT from PySide2.QtCore import Slot from PySide2.QtGui import (QIcon, QPixmap) from PySide2.QtWidgets import (QFrame, QHBoxLayout, QLabel, QLayout, QLineEdit, QPushButton, - QSizePolicy, QWidget) + QSizePolicy, QVBoxLayout, QWidget) class SearchFilterLineEdit(QLineEdit): @@ -25,39 +25,61 @@ class SearchFilterLineEdit(QLineEdit): class NotificationFrame(QFrame): """NotificationFrame is composed of information icon, notification title and close icon""" - def __init__(self, parent: QWidget, pixmap: QPixmap, title: str, closeable: bool) -> None: + def __init__(self, parent: QWidget, pixmap: QPixmap, content: str, closeable: bool, title: str = '') -> None: super().__init__(parent) self.setObjectName("NotificationFrame") - self.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Maximum)) + self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Maximum) self.setFrameStyle(QFrame.StyledPanel | QFrame.Plain) + self._header_layout: QHBoxLayout = QHBoxLayout(self) + self._header_layout.setSizeConstraint(QLayout.SetMinimumSize) + self._header_layout.setContentsMargins(0, 0, 0, 0) + self._header_layout.setSpacing(0) + icon_label: QLabel = QLabel(self) icon_label.setObjectName("NotificationIcon") icon_label.setPixmap(pixmap) + self._header_layout.addWidget(icon_label) + + text_widget = QWidget(self) + text_layout: QVBoxLayout = QVBoxLayout(text_widget) + text_layout.setContentsMargins(0, 0, 0, 0) + text_layout.setSpacing(5) self._title_label: QLabel = QLabel(title, self) - self._title_label.setOpenExternalLinks(True) self._title_label.setObjectName("NotificationTitle") - self._title_label.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)) - self._title_label.setWordWrap(True) + self._title_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred) + text_layout.addWidget(self._title_label) + if not title: + self._title_label.hide() + + self._content_label: QLabel = QLabel(content, self) + self._content_label.setOpenExternalLinks(True) + self._content_label.setObjectName("NotificationContent") + self._content_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred) + self._content_label.setWordWrap(True) + text_layout.addWidget(self._content_label) + + self._header_layout.addWidget(text_widget) - header_layout: QHBoxLayout = QHBoxLayout(self) - header_layout.setSizeConstraint(QLayout.SetMinimumSize) - header_layout.setContentsMargins(0, 0, 0, 0) - header_layout.addWidget(icon_label) - header_layout.addWidget(self._title_label) if closeable: cancel_button: QPushButton = QPushButton(self) cancel_button.setIcon(QIcon(":/stylesheet/img/close.svg")) cancel_button.setFlat(True) cancel_button.clicked.connect(self.hide) - header_layout.addWidget(cancel_button) - self.setLayout(header_layout) + self._header_layout.addWidget(cancel_button) + self.setLayout(self._header_layout) self.setVisible(False) @Slot(str) - def set_frame_text_receiver(self, text: str) -> None: - self._title_label.setText(text) + def set_frame_text_receiver(self, content: str, title: str = '') -> None: + if title: + self._title_label.setText(title) + self._title_label.show() + else: + self._title_label.hide() + + self._content_label.setText(content) self.setVisible(True) diff --git a/Gems/AWSCore/Code/Tools/ResourceMappingTool/view/error_page.py b/Gems/AWSCore/Code/Tools/ResourceMappingTool/view/error_page.py index df4ce946bb..4232dcba85 100644 --- a/Gems/AWSCore/Code/Tools/ResourceMappingTool/view/error_page.py +++ b/Gems/AWSCore/Code/Tools/ResourceMappingTool/view/error_page.py @@ -5,6 +5,7 @@ For complete copyright and license terms please see the LICENSE at the root of t SPDX-License-Identifier: Apache-2.0 OR MIT """ +from PySide2.QtCore import Qt from PySide2.QtGui import QPixmap from PySide2.QtWidgets import (QHBoxLayout, QLayout, QPushButton, QSizePolicy, QSpacerItem, QVBoxLayout, QWidget) @@ -24,7 +25,13 @@ class ErrorPage(QWidget): page_vertical_layout: QVBoxLayout = QVBoxLayout(self) page_vertical_layout.setSizeConstraint(QLayout.SetMinimumSize) - page_vertical_layout.setMargin(0) + page_vertical_layout.setContentsMargins( + view_size_constants.ERROR_PAGE_LAYOUT_MARGIN_LEFTRIGHT, + view_size_constants.ERROR_PAGE_LAYOUT_MARGIN_TOPBOTTOM, + view_size_constants.ERROR_PAGE_LAYOUT_MARGIN_LEFTRIGHT, + view_size_constants.ERROR_PAGE_LAYOUT_MARGIN_TOPBOTTOM + ) + page_vertical_layout.setSpacing(view_size_constants.ERROR_PAGE_LAYOUT_SPACING) self._setup_notification_area() page_vertical_layout.addWidget(self._notification_area) @@ -39,15 +46,16 @@ class ErrorPage(QWidget): view_size_constants.ERROR_PAGE_NOTIFICATION_AREA_HEIGHT) notification_area_layout: QVBoxLayout = QVBoxLayout(self._notification_area) + notification_area_layout.setSpacing(0) notification_area_layout.setSizeConstraint(QLayout.SetMinimumSize) - notification_area_layout.setContentsMargins( - view_size_constants.ERROR_PAGE_LAYOUT_MARGIN_LEFTRIGHT, - view_size_constants.MAIN_PAGE_LAYOUT_MARGIN_TOPBOTTOM, - view_size_constants.ERROR_PAGE_LAYOUT_MARGIN_LEFTRIGHT, 0) + notification_area_layout.setContentsMargins(0, 0, 0, 0) + notification_area_layout.setSpacing(0) + notification_area_layout.setAlignment(Qt.AlignTop | Qt.AlignLeft) notification_frame: NotificationFrame = \ - NotificationFrame(self, QPixmap(":/error_report_warning.svg"), - error_messages.ERROR_PAGE_TOOL_SETUP_ERROR_MESSAGE, False) + NotificationFrame(self, QPixmap(":/error_report_helper.svg"), + error_messages.ERROR_PAGE_TOOL_SETUP_ERROR_MESSAGE, + False, error_messages.ERROR_PAGE_TOOL_SETUP_ERROR_TITLE) notification_frame.setObjectName("ErrorPage") notification_frame.setMinimumSize(view_size_constants.ERROR_PAGE_MAIN_WINDOW_WIDTH, view_size_constants.ERROR_PAGE_NOTIFICATION_AREA_HEIGHT) @@ -62,11 +70,8 @@ class ErrorPage(QWidget): footer_area_layout: QHBoxLayout = QHBoxLayout(self._footer_area) footer_area_layout.setSizeConstraint(QLayout.SetMinimumSize) - footer_area_layout.setContentsMargins( - view_size_constants.ERROR_PAGE_LAYOUT_MARGIN_LEFTRIGHT, - view_size_constants.ERROR_PAGE_LAYOUT_MARGIN_TOPBOTTOM, - view_size_constants.ERROR_PAGE_LAYOUT_MARGIN_LEFTRIGHT, - view_size_constants.ERROR_PAGE_LAYOUT_MARGIN_TOPBOTTOM) + footer_area_layout.setContentsMargins(0, 0, 0, 0) + footer_area_layout.setAlignment(Qt.AlignBottom | Qt.AlignRight) footer_area_spacer: QSpacerItem = QSpacerItem(view_size_constants.ERROR_PAGE_MAIN_WINDOW_WIDTH, view_size_constants.INTERACTION_COMPONENT_HEIGHT, diff --git a/Gems/AWSCore/Code/Tools/ResourceMappingTool/view/view_edit_page.py b/Gems/AWSCore/Code/Tools/ResourceMappingTool/view/view_edit_page.py index aabe634c0e..b673e547a0 100755 --- a/Gems/AWSCore/Code/Tools/ResourceMappingTool/view/view_edit_page.py +++ b/Gems/AWSCore/Code/Tools/ResourceMappingTool/view/view_edit_page.py @@ -18,6 +18,9 @@ from model.resource_proxy_model import ResourceProxyModel from model.resource_table_model import (ResourceTableConstants, ResourceTableModel) from view.common_view_components import (NotificationFrame, SearchFilterLineEdit) +HIGHLIGHT_FIELD_PROPERTY = 'HighlightField' +HIGHLIGHT_TEXT_PROPERTY = 'HighlightText' + class ViewEditPageConstants(object): NOTIFICATION_PAGE_INDEX = 0 @@ -180,6 +183,7 @@ class ViewEditPage(QWidget): view_size_constants.INTERACTION_COMPONENT_HEIGHT) self._config_file_combobox.setCurrentIndex(-1) header_area_layout.addWidget(self._config_file_combobox) + self._config_file_combobox.currentIndexChanged.connect(self._set_config_file_combobox_style) header_area_spacer: QSpacerItem = QSpacerItem(view_size_constants.TOOL_APPLICATION_MAIN_WINDOW_WIDTH, view_size_constants.INTERACTION_COMPONENT_HEIGHT, @@ -202,7 +206,6 @@ class ViewEditPage(QWidget): self._config_location_button: QPushButton = QPushButton(self._header_area) self._config_location_button.setIcon(QIcon(":/Gallery/Folder.svg")) - self._config_location_button.setFlat(True) self._config_location_button.setMinimumSize(view_size_constants.INTERACTION_COMPONENT_HEIGHT, view_size_constants.INTERACTION_COMPONENT_HEIGHT) header_area_layout.addWidget(self._config_location_button) @@ -341,13 +344,6 @@ class ViewEditPage(QWidget): view_size_constants.INTERACTION_COMPONENT_HEIGHT) footer_area_layout.addWidget(self._save_changes_button) - self._create_new_button: QPushButton = QPushButton(self._footer_area) - self._create_new_button.setObjectName("Primary") - self._create_new_button.setText(notification_label_text.VIEW_EDIT_PAGE_CREATE_NEW_TEXT) - self._create_new_button.setMinimumSize(view_size_constants.CREATE_NEW_BUTTON_WIDTH, - view_size_constants.INTERACTION_COMPONENT_HEIGHT) - footer_area_layout.addWidget(self._create_new_button) - self._rescan_button: QPushButton = QPushButton(self._footer_area) self._rescan_button.setObjectName("Secondary") self._rescan_button.setText(notification_label_text.VIEW_EDIT_PAGE_RESCAN_TEXT) @@ -398,10 +394,6 @@ class ViewEditPage(QWidget): def search_filter_input(self) -> QLineEdit: return self._search_filter_line_edit - @property - def create_new_button(self) -> QPushButton: - return self._create_new_button - @property def rescan_button(self) -> QPushButton: return self._rescan_button @@ -442,24 +434,53 @@ class ViewEditPage(QWidget): if config_files: self._notification_page_frame.set_frame_text_receiver( notification_label_text.VIEW_EDIT_PAGE_SELECT_CONFIG_FILE_MESSAGE) - self._create_new_button.setVisible(False) self._rescan_button.setVisible(False) else: self._notification_page_frame.set_frame_text_receiver( - notification_label_text.VIEW_EDIT_PAGE_NO_CONFIG_FILE_FOUND_MESSAGE) - self._create_new_button.setVisible(True) + notification_label_text.VIEW_EDIT_PAGE_NO_CONFIG_FILE_FOUND_MESSAGE, + notification_label_text.VIEW_EDIT_PAGE_NO_CONFIG_FILE_FOUND_TITLE) self._rescan_button.setVisible(True) - self._config_file_combobox.blockSignals(False) + self.set_config_location() - def set_config_location(self, config_location: str) -> None: + self._config_file_combobox.blockSignals(False) + self._set_config_file_combobox_style() + if len(config_files) == 1: + # If there's only one config file under the selected directory, load it automatically. + self._config_file_combobox.setCurrentIndex(0) + + def _set_config_file_combobox_style(self): + if self._config_file_combobox.count() > 0 and self._config_file_combobox.currentIndex() == -1: + self._config_file_combobox.setProperty(HIGHLIGHT_FIELD_PROPERTY, True) + else: + self._config_file_combobox.setProperty(HIGHLIGHT_FIELD_PROPERTY, False) + + # Update the style + self._config_file_combobox.setStyle(self._config_file_combobox.style()) + + def set_config_location(self, config_location: str = None) -> None: """Set config file location in text label""" self._config_location_text.clear() - metrics: QFontMetrics = QFontMetrics(self._config_location_text.font()) - elided_text: str = metrics.elidedText(config_location, Qt.ElideMiddle, self._config_location_text.width()) - self._config_location_text.setText(elided_text) - self._config_location_text.setToolTip(config_location) + if not config_location: + self._config_location_text.setText(notification_label_text.VIEW_EDIT_PAGE_INVALID_CONFIG_LOCATION_TEXT) + self._config_location_text.setProperty(HIGHLIGHT_TEXT_PROPERTY, True) + + self._config_location_button.setFlat(False) + self._config_location_button.setProperty(HIGHLIGHT_FIELD_PROPERTY, True) + else: + metrics: QFontMetrics = QFontMetrics(self._config_location_text.font()) + elided_text: str = metrics.elidedText(config_location, Qt.ElideMiddle, self._config_location_text.width()) + self._config_location_text.setText(elided_text) + self._config_location_text.setToolTip(config_location) + self._config_location_text.setProperty(HIGHLIGHT_TEXT_PROPERTY, False) + + self._config_location_button.setFlat(True) + self._config_location_button.setProperty(HIGHLIGHT_FIELD_PROPERTY, False) + + # Update the style + self._config_location_text.setStyle(self._config_location_text.style()) + self._config_location_button.setStyle(self._config_location_button.style()) def set_table_view_page_interactions_enabled(self, enabled: bool) -> None: self._table_view_page.setEnabled(enabled) diff --git a/Templates/DefaultProject/Template/Config/default_aws_resource_mappings.json b/Templates/DefaultProject/Template/Config/default_aws_resource_mappings.json new file mode 100644 index 0000000000..79dca07d01 --- /dev/null +++ b/Templates/DefaultProject/Template/Config/default_aws_resource_mappings.json @@ -0,0 +1,6 @@ +{ + "AWSResourceMappings": {}, + "AccountId": "EMPTY", + "Region": "us-east-1", + "Version": "1.0.0" +} diff --git a/Templates/DefaultProject/Template/Registry/awscoreconfiguration.setreg b/Templates/DefaultProject/Template/Registry/awscoreconfiguration.setreg new file mode 100644 index 0000000000..c84ae4c3af --- /dev/null +++ b/Templates/DefaultProject/Template/Registry/awscoreconfiguration.setreg @@ -0,0 +1,10 @@ +{ + "Amazon": + { + "AWSCore": + { + "ProfileName": "default", + "ResourceMappingConfigFileName": "default_aws_resource_mappings.json" + } + } +} diff --git a/Templates/DefaultProject/template.json b/Templates/DefaultProject/template.json index 37409a11b4..6cf861a2ef 100644 --- a/Templates/DefaultProject/template.json +++ b/Templates/DefaultProject/template.json @@ -174,6 +174,12 @@ "isTemplated": false, "isOptional": false }, + { + "file": "Config/default_aws_resource_mappings.json", + "origin": "Config/default_aws_resource_mappings.json", + "isTemplated": false, + "isOptional": false + }, { "file": "EngineFinder.cmake", "origin": "EngineFinder.cmake", @@ -246,6 +252,12 @@ "isTemplated": true, "isOptional": false }, + { + "file": "Registry/awscoreconfiguration.setreg", + "origin": "Registry/awscoreconfiguration.setreg", + "isTemplated": false, + "isOptional": false + }, { "file": "Resources/LegacyLogoLauncher.bmp", "origin": "Resources/LegacyLogoLauncher.bmp",

TLNUqC~|_2C!L zU-J4mR=3OEOk=&CFv^XUY{1(!*gI*zy@kD&<~x1t4@KYI#w-v%#)@m%EMxG-HKSt% zxRyF+>>W`x&PPeTWt=$fobf+|6Ec+Oca*ybG3(GhdobO<1kt@fAkC!&&Y${()gS+e z8CHT$1ASN2elD89jZk~%z zdM+VKJpNLCp&X&aSj2Ih5yZJbIs!a!MwAOF(+Pw5sQ!7>=AWtZPn2_}a8^I=5mzWT z8+ZfFWu5s@`={9ebg68F&X>i|dE7E1m^Jp)U9uY%h4ec(#t7S#1nH5e?D2m~X^ zGshkb_AyXpo+ch7^k05qES4OE~?4pZ)_%JR_KKEqUL5(4 zFwmST7of`5Q{^cemIxE1%%}!A3TX`1>-xa5T9vMW>-zY>k z_Y&WipoTr_bYEhO2;kPMdKoO1xD5sgEC7wSC4w^KEmCgyCb)xgJ>_CT*FTh>DXB-f zQp>wi&92n)u5{D{$WrCh=DuG^+2;eH_ssM1S^UqMy}c!6t=$#O7V6=TQMLITHK#RM?sTsLilH@Ywv6oF_V zi2s9Bp$qj5muvJ$H6?l-f6bwcr-Vo1h&!P_Vm|z&mny$Nm7gZ`Iy=n{%{NBUp!VaV zMc|&!8&Dh490P@~D&K(`#g)+WFhd7qL~jRK{Ll)Q3l6ZWi@gc_+J#$fE^-XtBzJ=M z$kX}GH5?jX-a_bihIPOoO2h(`%_#8+l+jvHm~s~-8|6w$7DC?~s@#k!7p2PSyF@&B zr+JB;M~HE{oN;>aB;U{tjhO15`qLa(@V)UeobcO?J>5j%&bawXR2G=;Cey6)8 zXqQux8rtGyBxwZ-3iN}l95=D@npxBcz9kwQpHg;HQp^9JtHadtj@0sww55);rH*d& zlQ<*1WeL@MhtTsBp+_>Id&2YqXf7Bz1GU#5aYE-z=L@2?`7{)sx`4>%yto)~#wjr) z6kHh%wT@MOa-gn*C%Duk1T*m+HES?e5|PKjLlB~LT)yvBipXdvDO&L^~= zp&X}tPT5P@MtO;{jFQe2UI(aVI_J7yCuKK!Mb))nS{iE4jnqSD=ObdnADxq+WHXL9 z=3jt!Is7di14GGv%$^zT0T%h$fzl57Si{YjoC9msNI6szqtH%I5WZ)3fD=*3ZsSrd zkZQI?Ut-NoHQPR;W!e|E*J&B!bdf)~(zjyNHk&+mYkL&y)(KnM7anx{x_u+cU1=7= zrI3`JQ>WFTHhZLh5e|#zxW@hk%1a)d!rGHY#sa(z(o#i z*h5}5c?t%oVO-isOYwsn1YaRLIKAC`X}9&0Wo2s)Sl@yY9cx4=wnf%xEqj4ATFdEg zos9L}8f)|`cf7Sbc08M{EwNXZwnm%xDp||oPNKvAyLRSE*E}wC6gbnlz=_Uij%%hZ zpmxm&Jl3B3kuG$qcddoCgyt7e^7MilD0Bkj$+|M*KFAY|Rxqyl)qo}rpTVW3D;M0e zx~0B(Gs7xLDuzqi%4)y%E-9}1b`jHP zw{5`4D0D_YvWLQwF2n%FK=W6S^8)RwH%L7b4KR=2e^Xr2oWWHtwcK28WrXxQa{=rO4w`dfeVt&=idE_- zb7)f7Wri~<8k@aFPB6jjA@Z0H%`oOwX3XIKYAem)|LVMEbX+^+Qq9!nw*91RlTB#t zJRJ$0h9f_q)9?{`($b?#1_}$VtU&hq1$n2c`JNL-$YAwNB`r9G0pa0B(TAh z&(TQC#^jM{f^@t|g8D`IL=zQhN#zYDTMisioizTs19@=c0ag~xWaC!kwKI&Xk%v8L zd=eSt>&Eax-K*reD!og_u%P~VV>HR&nlbv@u!1~SWt3yQ8+*Gj<1J_^{DEp-PROVr zw4yVzCC@ba%3{&za%lVW2r<)aNtZF!^n6#)3nq>iPT?F?Cjwcmj8|of?Wr{iiQyIN zF=Fu-Jz{Nm%rQ-c#Zc7rj;6oCnEG#B4}&w(Gwj%O8pk_jeZrB^^z+!)QM)JRjUgZG=YEhVhMAYCXKBH=8m`zWq$z$!PpoZw?H=)LX^+B52QtU?LRiQj! zOmze+wggp-?jRmj^bXWU6U_#lg!;O|Ay}~}$wyQ>9mAc-Q z#3Pbw_En3tuBk?!_+%oj(vo@2T2N&{OpD_xWiS6XZkv@xo%B5?mHf>v`5sYPp}Eoj zj$*6q{J;x}kwOWOF5v zIqMNqNKQ$kt512aBIlKh2C531ssydB%Wpl&<`^$`B=eJp)RBOgSzj&LdjUHFn`I9= zm4t4QX*6FJv06q(GcL+d`kib-%wp*h;r+3m(vG~*aY@o*8-tE2OK+UJ;^;$Z=!mzL z!ip;Xw-n~KggB{2WYL#N6@xian5~j_OSyt|Qt+;1QK`e=HK`p$zZ$*&TxE>tSDGSJ zTuUgg`E}VU#*y=*nTN(@*&cIhv`Js+nlUSp(z){3{)Hr0m4!!u_`j1H{%geNAL9*q zb9h~>NTksr%>dU}S+N4A@9~Oa3(P$dzlcU^{z?8Ly6y;DYMe;B@W-^fB4N9t)9;GN zZ(frTBEr5vC}UQH1^M$JVdy`$K=?KoD_j9Gh0~Bf4<&a#WiJ%g2BXL?vS7PB$Pr4xi&o!~VEejDV)F35(ORABVy2Jf7&}GE{@dazC%obc(|7P- zaaBsF`~mTkQPFGnFFD4DmlAj#8<;G~|1scl+JF3uoz*fE_Gy{-XMNjyM$0d!e=pmS zx;*hc4I*ccJMA&yi_F*GvzF~d{><*zi**W|c4MR!yxM&n*>aoRp5UY1h?YevyAkP% zuI-+SY`HkOa$j7<*MvJCxAA3w8GJ58zeG9FeCR8os2-EKR7B_wlPP)WfbLgCy&-|` zqkXoz`)VFLdal|N`=4x3BA?GyzNp2#Syfl!PjNS$Y)E;!bIq~*%tWr>*ef~w+t~wI zj(c!CbS^FUzU`)kXt5A`yVm51FI#8i6i!KO)f2Tkt-s~Y?!XfMEf!lhmUL`cvCOel zkPRcP^fVjvmu+G*C3l;%ae|*Wze1kXbn{v8;bsTq%)~eIfM+*NAb+!J(?z0xKV9?l zV-+;tZ#UkBCC$U@#$*~+@0|D5(cw8~&geH^L-y5=)57I9r~T)8G=W`Nt{2WG+6< zc7n+~lDSTj$uzyW+?mOAJvKMX0dMyjguAJKG~w&-#*DL1XBjG&}z(`I2(CcBXT{bMp^(L+ooS#23aU09J^EHYqYL^+kNZIX-IMUetLi3H{!^NUYn$Ta{h+fF5yJ8Ogvn>mu-?`Ndv!)!$OIvNlq6^P`-a=V% z@ogwPe5Zp8Yu}F@cagu1?Ucmo*@R@37NvK-BYL`E4G{YY5MGWt#VM&r{r7>C??_Ol z6PoWMYQ4~pOlA~Xhqt(VAv~@E{r^t=g8t*=-TP0ZFW$p91?r7(M?Qbk4D>&1*$e&O z+KQn6-%UilqnaHG(BIRQ0R4@3&^oJwY}ZbN>ZlAI=QoGvI%O4>&13DACKfuYU=lAI`~S#u*bHb0j3c;mc&6 zvBA4s_FY8l-rlXpdihD<6|5lcxV578Yd*I)F_yTxaE8;0-S~XANiRS2H{Qog6D<3n z1S=JZeps6!InaaEM-s`FE0sTnl_Xl9fdzI6#uH!10|LbjtLYlAb$g@1JFCzc!_!_m(nezrQ0ZgL2PdI{4g7_pz+cNT* zl*w;-F`1m>cWIJ8%{6#RPhXZ`lNt zaJWx=#3vHh$zi{u+|^ z5u?)m)?_7C>MWn|SA)}^LDd~!8W1m9rckdi$JA5oW-m+&;#s7`X?$zb?DQp!g5%Ra ziK?%MDXA}gg~gzSg;Itxit+{_q6Xb9#?oC(OdOeoqv>5(QFXu3lE^oc@Po)5FQG3Y zpbuvWf6|@{s?^`Xnz7>y)P(6BM>%vn$pp*_gVjQhxDSDNw*lJILGGdq$(4iML%f9B zL2Yh~mJrbu@X-)%q9J4x`{xh4PS>utj)xAC!diwHHHkaXtDnZ2cK)=sa^A<z{+_XI!E1 z`SF*aM-uU#4Po0**KK!rSa1vjJ`pUhdk|bFkJ^Ghi>w6uxM6{y#+7PdDbWx_<9$#H zEu$tJ@uPI6w4&6dRHlT7;xiaAQ0_u4uSG4dK$X*b$s(M7Pe60tq%br;c$olh>q9?> zhPES8gnX!f3)-Ctgtn>Uuy$~45^4_S3lqSZpL(zoRSfu5kg={7$V=|A3Stov#|q;W z_b}MG5@!gkCmI6JQ5I2VP#&eEGeDpRE!$ASU-5Z$N?F2a-17jRp?A(i(!ETC4mlF; z{Cf(TvnSEk(B7As;HEzGVTfOQGjxvDVHK1Hln@O87*SvnWjLibr6Z*|C9HtY$Wv0k`rof? zMKP$&r3fPgsq%w_VamUMLbKN-;$}$2%R;D~BJ*OfYCHTksJR}W3F1GK4Q);2*NFm^ zlHgYXAH!gwfa4z0pe_TS30SY2gsb z6OIc~a#N!3afFU>f5ZsPy>yI6?xdQTR5Q(jhW?Lp{>+DR?nxbJHX$=mP)Q%!9r&aD zA!yrxGX*?8QwCb*v*XMklh7~z$HF|p!yaZh|BN*!*r>1da?+-lv4UaD+x1a&-;m)0CLW;U^tbIn6wT()bw?LyiO=`$NWB z{iFrdj=sDE?&?Ed1cbG}hQhZE7^nV*5L`K_k65kVBya ztGXGnU0~lXD0i!0M|grLaZ9J93f+jc>)l}OMd@xBMJs-~X<~in?lgBFS=UU@bz~1?jn=vR*1G|AC`^L+Vks-1yZG`6Zr<#ox4vXs zmWvctKo4C6up4l9;li49rOR5Z>=axUVV7*;{2O~UGiQ8LAjBCxy`bp*`&^-#j}m&>5qcW`F@RbId6%7g@bE$?Jl9tWRqt*pfZ`2ki%a2Ii~^T6 z`8bnvMzRaY9exM%2;~}h4w>j>`S})8IqgCdf<7#Brr5)k5axo6yv6F6f7$^77 zJ0Oa|!oE~9T{(D+kg_{%i(C00c)M%aWD68F4YNVpi@s)X!%Yilb7(k+%cdu`PN87Dl!KnwJr}wiCLf6FPhT34u<#$%jzrK8*7@r1qg~-*OW%#C~A|eA~|G ztT!^*9R+h)(`-ePTli{hI>HM?6KzaA>tw8L=G)XNIaoL9pH%m=4p5q-&1Nls=&jxc z>n(fM8n`fiY??J%$asaU@fOB?WaO7J+L85M!l(s5GRlxy{*RG^9qt)M0x~g$i~!^V zd>BsHl`1k!u{YYpP$T+X#i?4Fg>$0UVjK^XBMz(nWI*AsN%WQNuVGbiMIYL2BXsjP zb|wK0?{JQ`vpF2s89W7i!fUOvlP6^NTCs(9tJ+#tdVbWNw$!otYUp9{SO1e~tVN5G ztwo$g!eJZ6Tnn>3ZPq_5MAaQjFmtoBEm9B7t`-=oDVl9d*`oK@^i;$=)Ay#lUIL6=CU*23%H;g;>CU|%o7jLokJY^g`_pg_$u_yeP-IxIm8Dr-1IchA4 z*vD_o4?Z%+OzD?lj5hioF!~EVHo}Mw2r@z&p%ytS*t3R^Aw+0N`@$mrPb+#)`xBy+ z+5Ta))s*i6-}<>GA~&B2YZx;c1r%qDvd+HK%`tpi5NAHmP%1^+X4If5Ldxl;fvA_S zyO92U+idUk`rZcBek=8PmDK`N^gf6u1o7!z*{2nJUN2*7c}Rnv&w_?fXFW^Iql@*R zJglDlqEoo49%kF{S9*xl5dnJe{K&237o8&ObVsn(lq0|B6g8lGgXp&$CYmh{5t^MR zG^O`)7~lW%7*_}4KZ)SVi|+7Awoe9P50npo)fc+?M{Qb9qtU?loUYfoRn{+bE*I20 z*XhhliSx|V#_i{R=e6E>H3uEj3bK6@#-g>_aCtaF;Ln6Go;lOER+ZL{I)GVWS@4_tM3Yc9LRWf`Zj zqA}8`Se^Zxl$X4kdcj!0H`Rocwy@ucJbgYk3fATqIOq@OSkt+ci!tPb>-7dz)0F<(xzkSq4-5%<)&i6*kOk&9AIWaoREX9URv z+MUXhlKyHqmE$CxqB4-TTv|-h`sjFm10BT}$!p{bM!_*_Z` zIde_&YaK=HO zJxZ0&juxGb)H}{4%Hw^h;Fn04{k-Bh;TJ|uC!>YURqapD6Z$Q+qeNY(Oz=*rfsobq z4`r)__N|^@mL{|m+44UJvF0fEJ=hHnAB4g)$_LZHO9wI2pXEEK4IVpq5d3v;E#5kA za{zN0W;3c^wv6bPmSHmSOCn#GOtq}TSN>{RZ5KQBsmVQ4q~O(_pgy7c2d`rmA9#1G zEXjSp%H@?AzXcl3z04Kn*DA~}nA!V1HQ~g?J&z+#mCWDW>9eG)oNvV5`OIIwRYtGQ zJ>F%fI#VIVJ1jL&>BZ}`zwUwq?}8nNs@CzeuQjMj=0QZRn&NRoR??bB2JGO0!fGCF z_)>KWcL&MVaA)Hk<7V8L?`p1dW2I8d!M%m(KXisD7eW4fkHA5+LgSfWGwwq7-}m^h zw|DrS<)4Pa9d;?b(o0y%UHouG#&)iMw;ts-b0%MwD>}7p#raLAt+(7Md{*AHIVAPr zd9IB?k<%AM*8BOmTr6LE(f&zI|7xbOZCw&;oLb(cC#wvl3+rcAiXNzH7+j&b^Gsv- z^3wH9jUSeC&%JV4Z5bl`<@#la7fq{|q8FOn$sHa|-AgdLH}78p?`lq8j4|Fkz8LZ9 ziu@wXOvoZF#r^Xg+-QZ)!1gsvro*qTn9%|#MDVB0>X?TNuj-I%$k$Mly2f=5 ztY!kqGoS~%TmRuHfCFvt;7tN;f3VgRzF|Pr+_+5GzLL_8@+#p?L~#(F1Y+jLn^NeJ zJ$qOum`vU6^Y1a4PS;5OEg0)m+{>+kce%7?PU2l0f(3|fuc}J|kn{CE_Y3-EF4{o< zRgynHUwj#US>$$=1^NS9K0|*MQROSsUJL#AZlP?F+yQS;pY0UIy$&i}ScwQd?)r_j zX3>91SPkp_2fttDdqH1ndXepuqRgPgXYl55amrLmI(zAa5Vg(^2tyqRlf(#f zaOS_Gqxe~4agsk^bKH@yy$@`o&s=r0GqGc_i!Om_0WRy0_7}W zzXBy~S3fL?H=+npMiaWE5VheL4|t0U+K9|QW;oo-4Ga8RS?LM=33a`=XL@-v7ta3l z`g!QDyQu-c6d~6gD!98>A-c`)Rl~b==d(-j+|a@O*oOoS!Y9{64)#Ni!*d>@>N)BKn+b=|v!EVjG36-Xi+zMq zuqu<8DM(mcL3nNlA$dmmpL7%EkI&aygP~vHHtf*9;SK}(zxQ5*{^$o-BUS_rz$V3v zCzH^hGH3+-BSXp1U;Yv;a&jDgjal9O^>(rjeuG|+`}YP`5|bFo##Jz`(Pg-bbbS;y zUq3>AGi|~6=rmFF78U@*D4_vaWLOE*r_84uBFx%D)ShAxR{9gxe;{l@UH{x}?S}rz zJGRgtdhaguYxf_+GZMm2(3?%2&oSaEx?Va%|K-={!SoL!>B#5lye-EXYx@{Rhtur% zJ*=VDLh>9f=KBdm>-QfpE)H3J)Wy!KLI2I^e(XSczM`x! z{LLFz!O~}NPJwMRf!H@*nrX*X7>n=oFbYb)s}NP+aW=4%aCQMDq8ZA`l+cW4j202r z9wBP4LIaa|>j&Z8&x8*#bNuUlhW`Cx_%amwCr2cqzh^86`ddG+LciH3SfLY$Sh3k^tZw;!3Se|`|3a*=@c&(cl~l_K+a>ZY}}n#^l@CUe*q}!v<2HOqBbMo=Zp=3xnntPvODw(%r^T+tA_y9=P}bI&YqaZ^aoM zi$pEVSbQtC+P@NXb3z})@|%RC-oI*SOUz@*ENa~_*P7(Kl~#m&PfqeG|30okzZ?!o|HTc-X+hEMptjd zccalyU@~PCCC-Z@v@Oxrv}{BPJK{L)spvzr4C}yWHc|bHsQv|1IlT)#f#wzCoxhty zbLChX)c$>n-itHuhQG%4wM2oc7vDqMQ}U}hF|Nl>f@|V-pq4g&jM(T9Co53W;Dndb_xYon+#&-_d+cdY$A6NM`n}fdLsijy#djeAo>`@SwQp?NMmH=E?Q=%TuZr_ zFybHOH^RinRCz1ajFl%e-y)2AMY-a;7c{Gll|gO(Gn^y(TXzCzN1peK8mwLdI-WK` zjo*)Tg2i##pi%(piDYpqLR~jaaJGmvwX2|mwp6(Z)oe`|8%h{+_B(7CJv>$e?tQi$YL9m3LECgo zHRx2m6}3;D_5h=f5mh_lTyf@m0X$%$6GlO}f+-?w_-eH;*qu*EZ3a8|MZmLcY~V4X zA&mM@81OWx&dK@z({;EbPO({&dhZ1VwEi6>?8>*ScpO~kl9Q}!M1DQ*rG{&GL zGVhrn6n^YJ2O78BfU3LII1;XR8lyYx)v@nHNgR47YUnldTIJCmKS~D_}3>P0D7^p``5%q3w+`q{?ZuiQ%N0DWm9- zNQ3YAUPRIu&K-XLnJmcFeFX|rS_YuxSG5utbsD}Dx-4rA&R-RG4%7=kFN7?0hIa&a znkIpn>JFeidEY>=i~zhVc>9(Fa4FG4-aG|)vQ1@)2qPY+ekT#n=n-N`(@~K8~Xx<70(=@>U%e82r{|O zg4)}wgTW)GALDHQW$A*paZnMkko+RB{}pFX(9aas^*>DB_Tj%$+8S%qF@axT7dys| zANm74g|%mqAM~u4=NFIF^lm?lx(zyhUU*7-k~~qs9^(fud0L*J8f$TPy=A;O@k?_J=g@p;gx^$ceXINtpeO1@ub1I?>*Q2VpfGoV?P zKlUx(j;;rD13rLC&gIxi{xcH?Z)r%b*zA)h-M%Hk$3rl5N1l%c`}8hyD&)l7RKkc*T9_J1FOPVMncP#F6x8>+hQt^+x)i$YaYHG0+iN6AJoC=0#nz4GW0 zTtTP|+_(8sVX zovi{JsoH2le;PmisQ>$#eTV1x_>S{K+v#T)pl#?b%3gxk^>K|OwR!*=BaH z0j@ae$yM%tCQxrbyStvtR&h!9`DWcmc-*=)CY2Vr<;oPR&bYbmFV|e*rp(c+E$qg> zU`D5wTnW;>@3sQjw6|{1q(A8T75A<5y2A2?Ew0az$Gq)|v0z-~dIS6EY*$##G{E&7 z(eM9=X!fJmOns>@`Op=G_gr$^i)D5Zbgmj#hBl#RUAR)OiJT*wHd+QB{6r$6c-m~HPhLk<32;Gwj-NI)%pfGM6$ zhy9gh4f~$8j$I|Gl39*I*__JX9a@h**7<@LZ+9De+E2Tjv6!(xY3^mS-QHBQ!Cumy zTQ=Kq$nN`rkIp~r`nErG4YI3Ww#F^a?lkJtvdcu>8|?ELA+)e--wcAegdmN`~`3PNm30;y1os9{dq-PJIt%t@V&~Bx{xv+%u-L%bV zcIDSwL{Hg{*C;Eg*(#S@)8n_C z;3r`%Mf+=wY+l8+k*`KH<}x}Dh9Kf z{kGT_w$tpQ)`^I4GoK@MQDJ71LQXO4W~+Cuh*dP5W@U-nUz(fnqPQS zj!$TIuhYoS)2zY$=WLp=cEJfv%wL6TG%=zJk80Y2KQy(GAq&xj=NEm{+>LC9h30zj zp5{EF-*h+CN$qc#LCX3ggnBwmrdXoR;B39lcI|)(7VAhY!NFthKQx#EM514hMoS&KXVltElxrY=E3s28kjXR>#BqGr{Z2 zu6TFwYIvlAM~~sr7J0GOg0#7EOKK&vdXFqB?ap5=yD}%fc#n*Dg3GB_(!s$6rT3)< z+^(JRlajF#0 zX9?K3T9^FtMRkM3a%9UllHWh8i6_5&Q8P|{`Jz^Z{PIO@rFb&YuSV}2P@W{p6`P>^ zoO}-6DDH9uan)H}=G5%ZfIm`Q6B^M&lB)(slSjn8dt$TpANtqYoqt8_Sgr4gU!r4P z&!(sGD@=H6%TzA5a(~O+P$#}KFmYLf?T*DEx|iQ=f8w5TWglm? z)tjq-IGS~bTCBHCE1tiew@vX-bZZWK?HabL&0}s zZQ3rm6(hGjXA7cJ`?oC^9XD0CU_{(Jy=5Ob!$#Mu2d?1Ge|Z7y+%0SOsN%OoKk$a* zUhb1SPT^i|4~~mJ)brH0WKWzsnYmH%x#F1%Yf5`QT}WS1)+Sv$u_&f?rcq_?in2WN zMwDE)mIOpMw>Doy@b>mD%q=T#VF$wq>VWO^(mG#ZO%u@tYaKrJ-$&#>o9`f|Z!0Ak z;FTx3v135ayp!-QR$HJmQ9-zG7gl3R4@9wcOnr#8Cjb10n4dV4`}yz`1G7Jh=;?n% zIIx4#lM)_}_lKh=K%5h-pqwFOVE=$O=U{B(nuRc7Hf9LC#l@QNTru>Q)?lUZe!*qf z=Xqs|4fLD0BVM;Pcd|f#$Q?xC^4-0Nae1rB{fSB359^^nXW%AQ04$HuM(ez%oY4P@ zym3Wk%^)a|`g{x4%BIiZ*<7we`0M()LumWln4w!l)eDSUP@fX924(6iFGWcCCDsBU zW@xPGHxiwR;e>e}ge6!NF_{-&Z6>pU7yA3I!5`j>w6{Y4>n=s;&%Zkj{XhF;p#Nrn zFZ72zfu20qXV9FKJOulPEquud{jtOEFe~!E*1~Es_YGRD@}9hpL^5}j3;EB6QM7cY z%G=GjGim6p6Rsi^y`{eK_9xNyPMQ)vfN~$<*m_D6O4_c}6r!_e9^tvggmsdHSLYM9 z7vfzm3;%=9y!X1d5?2wn_rtGxUp|S!7*lwD6z|g6`0_FIKY0!N`XgF&ecF$^=#PB5iu|qVXSAK|^=EtRzBE5q6K$VA z6Mhk-M8rWEp9FsqP93HUB_z+kBJ;n5umPUHWVW&rcCr)pazOu~eqHE4{}g8!GJgRj z_qM$*g#OgGw$N`sj#ixE|KNjn83~c!%}aLu`~z#OMN{w%uZpi&qu9oMOD9iN&LCc^ z-T96&DE)dCBlO_eS)6Crf!XiaA9|5@{;f{`0n4DzZ&1P$P(O}?^!U#roy{P>KDR-L_K7bM?^Qj)b>HcyX^uHc~HHM1D(7*R=KBPha|gdWs~xf1B9gh|9`@2c>W8%dx$WXW+8HDE-ss{>$2{V<5?T0;G@U9-=Oa^ zpY_8>Gxa*4JEQ;d0BCpqE7p&{3wMF#sc2`qZuk_qn%tq8_R!h_Jf(XV43aMe^@T82 z(?mF7oit9OF%3QoViY1DPRA~JiU{Q~%3(^>gd^~A@D}A2!aOIcoNCVTB;{WbC=J-(M zH0PO>OEtF=X8xd*nc4@<`EQ^k{ZBtypYGF93x!`Ue*&W_V868Wh03V?dg>|AH3C{v zdB`ssr;L-kSW_DG@R^hp`Cp);&@iaNiSe0oa84n}MfK3=n6iwPVG)d_AC$B&k`ak< zWQY=D3*~OY9CxbRhA_*S@EFZPWS%GGjMtPrQ?OHd*qd1B9PYml8gyVJq&~R(7qqV6 zgoba0W?)e&;!cWE#6fVbS0-w?W!(&>ll!WY?G^TdGQ!ZC%(WenGBghL$8nJx6e>0-}84tgtKi zWcvs3##~q+v4$u~#Ml7yDKjYJDZ?odq48H|N(Loj+yCw1ng6ph-MOUCP~|j=rKyo} zYTA?zbiRCZ5|r$RCnnc+pcToxn#hWwu>zixq*#c#A@O}G?3b7u;SOqg!9x>Q*v!ZN z^{F0oB~&YvfQiDeWr8!8C#X9gy_O(DlqA3k;4VrI$_b*haNviFK#gaHXaE`>|O~N2o1^${)S4gxOq``CJ z|3##Mm%V;~em46-Nxl2vS_QQ3=%ff6*vs_~Y+QieIa*Hi9K|>RQz&C7gDBBX97oTA zhzKC83BqddkXJ-u+8wI-HdRY^@yQ=ZIhpoClKvDTPvYq}#BRR^SV8AbST+7-lRD^7 z5s0&WD{KLC($FJEB_rTDaWmd1$JLSFC5Q{vUkYj|@`JlX!oWp4pf~pOB8-Aq^d;Cw z*+F@Y5;G5u)AeR7`X1#R%4EtY!nE~N^KYt_M$04`bCOuekwiK#B=}54Lg%$N4~Pv1 zc0yr9Cu|t^rO6HqtjGrE77pV4Wobu1m53+E%>VP&1h3c}2cz}T(ij6p_;L(Cc?u(D z#ZGBlCHb}l$D`j6CDD&4v2sMYjk1yQ0_7>nTuRzU(X@|J1gLU4UnVlCW|}!n*g(qh z*b76g*VHj6y!>VqTsnYA66@P32o0~BB0z_V8r1lu5WX3mn&to=h(t9}W8P33b=u}0 z=%}9#9#(_}qE?IQ;VQ$YofF{WW!u2pL{;Qv%1TQ3B95TtU@B!aC3+f1JSfqxu<$HV znDBtAy-w9)M+TkLqhjBaaxB}_8R#^BLljmG!26%Z`&$8pk#R-rAV(T> zMzlxrgMQw1;2ztRSPxC8? z;am~UgEhsa@U6)6^M|j-y-pqB3vkEK*RbEXul`TiH1h4!VdF%9d`r@V_|?<|23KG#hy5;+19QkP^MwgTT4E0~>Wvyg zi)=L)wuf37@NIb=DyWpkb3AmunC8Bkkk>qp2UJ43R`v-Sh9Iho7Kgw_hs;9|rw%^} zffXc_LgKJjs0j(iid8rS5lto~#0IOsCm}}2x3h(45dE>Asak6D=;Ndu1vi3Dx{8Q6 zMatnFQ?OXr?-4#wcHk&fo$SQ9Ls^=hVXqrjxgPn;Uqz@P_*fdETJXNeoQ?WHLq0sa zZG$px^Mz)DbPZy}-v(`0`YCG~_)YAELPlU8ucUHpU?b}#)vQ2xi~5ehEUfP=0&#Xt z_rMU`apM<=$fF$+2tUy&4m3uNy)Y1(^|AwHv7bu{6e0SfxvAPQ!U*a=;b%!X>@;C$ zHDO546nr)K?+7d$EIEMMg7P}cuzUO3g#HY4t~`t@9dC<{uT2XGNZ+vcZvbm#_n~3` z79V@LP=7buH>y(pdkvmzarpgGcGBba>pkRRXz6!$*J|TRzvML@rs{qH$oi%FVdR)6 z`yWJ0cWr{k*ulV$)t1H#{ z*hVeV`swq3QFh)zSv=dDSHI?*b4F2uiXw`jf&>L6h)R&0bIv*EoO8}OBZ?p(s06`8 zP!Lf;P(e`y1E}vl-S_^gwraQT-Sv-8b&bQ!Gu@|8pFZ91%rf(QndfG=G*2kZnpw-7 zQF&-4Ao50IvDrGFWm?&$9}mvx1etcM=hA&|dK3BXuckT3Cf_%WLmu44GzhtSPE&Xo z!}q4>vqoj6y2uBpnJQscy2kVh*kF2|=(o40YH37nLtDYRh8(duZ;EhzFrAkla^A(nJmI^Pl<`ckyZjpC09PSZA7c*lui6`p z`ZWFYWsM?bQjJ25ltdLwFB=`=$ukc#n#VF^dBSjb!oI;nDV7g9EpCo~l$G!dOV zgQr&+N<~e0cQ0aTH+=A5&ADfWD{op|<})zMZ%|0k?@K(S@lanOxL*Ih-iT{}=>|O? z3qi{UJ$B9awyL^sW!F3G*Ub?fb@J1-uG0ZF!qM8_|~CUV4p zwt{~2B>ah9%Fx~8p1L*NY@%s8UmoztrR%WYOxKXm_Q{_#yrwmrsAaKLOEvhf-8{`9 z*Jn=Anhq9GZaJDev_w6hYdn(m^%2(yyJ+rbq#<{DZNOm-R<^f+wi=7KxCUvdLv!#B z^5*H_QuTI3y+_pRz+&>!;Lt2#`3Gi7K_`?4~-de;LDy=UqRZ+4o;t6eK#vKLa# zOH6WQQr#AE#_O6&q}w(>ZIuHSBSFiQ8?^F5#+8j^e}ywCvtIlgxkl;h>E@^crF!;( z=w79`ZF^!$m7M3e#>y$d!ea-O;2YzvDT#tDO7IKurVR3%u>lGm$VP)6%y6Hv9$mLlI#HPvdXm3d1m3=K|m&7j{ zb161uo~-m4-&7mf-G?U90%U$}f0cekrfxh4EoE!4zj+07AI81Sg`Yt0wRa=Y1g~)c8=Y09+M9Y zG-SnxxoqTR*t+vvtE5>UH2Dr)| zBUIRYw?Q?Ju=w(T>O16pP&W?>Zv;Js=YoSmpO7c#5kfD%l_qot{3Dcy_m{{Dpg(ZE{x#nB>IZFJQg&PV_@C79mmaaaV9BNn*cBawY@`m!6rB-G)$4@Kj*w%dK zeJH=XHi%bIJfd!rXPSRu{WhNDqgU&H@Tlxv*AUIavFcspTApRd%2=I(=En9@UC5B{ zIaLE%pGpOLPq|^w`Jq#o#WlH|!syo2d+Hd`FM0;bwa>$5B$9-XKi952hbY>1K3^$= z;pK4#tq_{RYxzweuIH5Va7|j($@Ctc+>>0BEo#NPkDtFaT0VK~aiM&*&QYbLUp3Pl z2SOX~a2=j;?`h~f^v7zj>Byl~I%w(A+B#UCA!p9Uf>Es9k;Mai$Rdx-`3@E?(1rz1_ps&Q2=bSk4x%kObPi&q zW3JUsr$mta}&?J7o6kl>$)(1+y08Kr~jPWDAj#-9!A^l=y|Bq?zeMY z@y?z@b60?NBty~DF$eyqcQdK+UQJ4jbBKk6Snp!BMQ}f?$Yo+TqUGSkZ6?V4XKvub zd%3GtbYge0!u$i@GAiq_qnhdVaa^mgAqDTXd37%VR%qUeaiwsw!ymt>$#|Ru@9aXp z2kKGWjhNE9x3?AJ#?}{B@CqyX5amn0>i>vc=z}j`llfwWal|I2Q5Z?Yt*c?On za1$X}<(U$E?h5@+1~Q;u|1HjJEgC_6-j@Dg3H{^a$nm)@YxOtOo~_8f`k|FeHOjkd@@k@V$lO7odOo z%MR$z`X-5yM(8`3y8UMz@?raDW})BzH?Cki{nrLDR4C&y^wSmEt8|CXg#~1^;ZYFT5{etCNH(<%HL0v?8*RlzGbtId&87 zmm=KqnsC`#LUQN-&im9(9%quXUziiVfwzTbs{HdoQvL=zpZfL_Z8s9~8}|I1#&>P- zxOf*3jW~+`l5*-eVdQc`?+`-!?SzJip)hxHAe5%r8c~e!nAy@Zk7DG67xE_DPBVY2 z>6zrt|6M=sN?S2SjhvlqMVJ&znAk>1?~x!s10NB8b4(N5`!ay+v*^4A?x@#CA1W); z07cS`u$nL#i5iJX^@3lBQLtSGZrA;eEd2+0ey{<7*PQ5h-d@n*pcSaT{4D8 zq&z~&Ou374BjpOp1%y$52vba{ato^5lWL~(--KRLPS`{kuQdaI5!X0o3?6(5g|Qi( zsvuLn4HQY9~Fio)R^JbKpPF(!U9l^{8@Ps@#rhj-#3%P|}_jCpCjR z#1@X(gKJ-+|HlM$;#p#r*2Bj|CzN@B9O+@W@{7njpqKY5kl&UMoTCRH6xk+^R*Os% zQve-L!w*I(u&{%IEAN9GRL@>YTF>OW$T+@`FoM=|#1t*l@gZWEmiq~l1gLU;s$7C< zHYALr{V=wRlw)_yC_$|?SqF`N`LZ0m+UW#sPwUYZQEFw;xYsoKB4lJ@WH%_{4SyFo z&sG_CzpEz;2Fl+6)x;t|-qZN2h^;Jy^H#yXhffeC;cqDM_b7Kz-lMFe#9eVbpE8{i z{Sp>3OEuG;6F-+Kr@b!r0x8G15=K9m(F1plL1&c5%SLGX)fo(0)#G}R|CE6dG3mHZ z#OX+A2_N-_hYe4&bp=)Q2wCJuF*g4dYX^Hz4}n#zOTom|Js{c!bfh$;)S*a1FH9w_XN*Hx{#uhrW#xlW$FP}oELuV>fP1VC%!ad3w zz_sZ_Np%!arRI(Mhi$dR`JvDC@N}VR3R^%c@nxXI8QeLPofTFWx^B&9kO-L*@|ALg za)7dn@*(A2%3G9WlyrQHn@1GJe5Yz@TSTv>nz;xg^$8=2W_+OV@7N7c`7-O zC{m9*gm#s^0JYL_|Io!ztWZ+w?GNhO;?5yVdKeLd#}%%E4dRku?3obIifuWlxQ_Y`f*(IZ`n66Fk=;XIO-Cv-|bxr`rG0@LFe_MFleO$GzY#Gj{~dE zd;z1`Fh&MCtUm+7Izc%~F-q!719@oqDCGgl9h4ZIa6YaJ+t8+(uTafYdAJhQY)=@P zLm2XIrT{!T_7VyM2H+cles-d_1sOKLLj-;+Uk$os907MmnPAnX*&8hqU~jh%JgzT< zb&y{QkHL2FF);nCEa<`xUH+OIEWyh}i9bK(aY{By>XH06(=zUgbErr1`$Nips5RII zjX%O^D})JA&2&r+q0bc@Mverv&eVZx$6z6WdIMTlmj%yQ6OTquiS@GrQsrA0Zg)UW8e~6ZcH)DO~7|K663d9sNhd&D{$#_6&D> z?8Le2j=Q36pHQ`#R4w(QzHX%KLo-_5^te~Y>^vx3G7i7%d1b%~s>&W+1vfUp2fBxs z;|}g?GSIu-vZLWM+ys1*n1Wot*e~SNaLq6fKXc4gLut9-uq%h8f#^lodHllSK`#A= zzh6#tso$D$rPU=Dk*PCTEt0*+(v9`S_kb+g-`>f1Q_o!iNQ2&{30J+igcrXm%6#5HnM(Qj<6QZ*N*40r#aj4G;)`^jz_U4o5c~HM|X}R6zJY@ zT!ZBb6Y=+zODAqTHW`mE|2v>`yQibR;7k~=B!q_ z%7?5Rtd3l6vAu5jTVS63ZOg|;bsSwROLyLNYO{=<>+1a261M0PXK4vF?3Nf2Tx%_r zP>&LpuvE9NmeB9+W{DBOW2GfLwMVig)$cS))H+h-4%CaxIFa4^8Z1U)y9-6R_< zF^Px2<}g8@4JtEnhnEpBLE8s6nc%rX&Y8eFg*2L=T~Lz_R4rWvux=n_D|bRmX+jHR zfzY<6W@EN5FcTf`=ig< z!wlbHuWUnJ2M52$2K`3!g0>n2s;mpiHMk_zA2w{TPEaM{p8i`-!6-KUJ9}!PIrY;P zzm1ts-h~j8rSE`vcN_UOP;98a8sgxE`sf#Ne){Maaewqt|M6z}@SpL+`WSnlllpuM z8Z(XP=jzUO0J^J99q8{O?6=`F7) zch}d|$oj|kqR#Ue#~^>5Ykuru1==GH9Z`DPE=KCH8rp0sUh!30qgON%>$M7mmL^+k z*&IKVaz{&&X?tpk*0JS!X{K7}q3Qo

Event ID: 

Local Event Time: 

%.3f seconds

%.3f seconds

Event Trigger Time: 

%.3f seconds

%.3f seconds

Is Ranged Event: 

%s

%s

Global Weight: 

%.3f

%.3f

Local Weight: 

%.3f

%.3f

Emitted By: